From a1ba2d1ca3a1d6c9c36a79a196dd3ccb83ede353 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Wed, 4 Jul 2012 14:22:28 +0000 Subject: [PATCH 0001/1476] import ldns 1.6.13 --- Changelog | 704 + LICENSE | 26 + Makefile.in | 1098 + README | 144 + README.snapshots | 8 + README.svn | 26 + aclocal.m4 | 8620 +++++++ acx_nlnetlabs.m4 | 1370 ++ ax_pkg_swig.m4 | 135 + ax_python_devel.m4 | 327 + buffer.c | 176 + compat/b32_ntop.c | 333 + compat/b32_pton.c | 387 + compat/b64_ntop.c | 202 + compat/b64_pton.c | 260 + compat/calloc.c | 24 + compat/ctime_r.c | 16 + compat/fake-rfc2553.c | 229 + compat/fake-rfc2553.h | 183 + compat/gmtime_r.c | 14 + compat/inet_aton.c | 182 + compat/inet_ntop.c | 218 + compat/inet_pton.c | 230 + compat/isascii.c | 15 + compat/isblank.c | 15 + compat/localtime_r.c | 14 + compat/malloc.c | 22 + compat/memmove.c | 43 + compat/realloc.c | 30 + compat/snprintf.c | 770 + compat/strlcpy.c | 57 + compat/timegm.c | 31 + config.guess | 1530 ++ config.sub | 1773 ++ configure | 18779 ++++++++++++++++ configure.ac | 674 + contrib/NETLDNS.readme.txt | 10 + contrib/NETLDNS.tar.gz | Bin 0 -> 54578 bytes contrib/build-solaris.sh | 50 + contrib/ldnsx/LICENSE | 28 + contrib/ldnsx/Makefile | 89 + contrib/ldnsx/README | 36 + contrib/ldnsx/examples/ldnsx-axfr.py | 30 + contrib/ldnsx/examples/ldnsx-dnssec.py | 39 + contrib/ldnsx/examples/ldnsx-mx1.py | 11 + contrib/ldnsx/examples/ldnsx-mx2.py | 17 + contrib/ldnsx/examples/ldnsx-walk.py | 25 + contrib/ldnsx/ldnsx.py | 916 + contrib/ldnsx/source/api/ldnsx.rst | 15 + contrib/ldnsx/source/api/packet.rst | 6 + contrib/ldnsx/source/api/resolver.rst | 6 + contrib/ldnsx/source/api/resource_record.rst | 6 + contrib/ldnsx/source/conf.py | 194 + contrib/ldnsx/source/examples/ldnsx-axfr.rst | 6 + .../ldnsx/source/examples/ldnsx-dnssec.rst | 6 + contrib/ldnsx/source/examples/ldnsx-mx1.rst | 6 + contrib/ldnsx/source/examples/ldnsx-mx2.rst | 6 + contrib/ldnsx/source/examples/ldnsx-walk.rst | 6 + contrib/ldnsx/source/index.rst | 57 + contrib/python/LICENSE | 27 + contrib/python/Makefile | 67 + contrib/python/docs/Makefile | 70 + contrib/python/docs/source/conf.py | 180 + .../python/docs/source/examples/example1.rst | 68 + .../python/docs/source/examples/example2.py | 45 + .../python/docs/source/examples/example2.rst | 100 + .../python/docs/source/examples/example3.rst | 7 + .../python/docs/source/examples/example4.rst | 7 + .../python/docs/source/examples/example5.rst | 14 + .../python/docs/source/examples/example6.rst | 12 + .../python/docs/source/examples/example7.rst | 8 + .../python/docs/source/examples/example8.rst | 17 + contrib/python/docs/source/examples/index.rst | 12 + contrib/python/docs/source/index.rst | 22 + contrib/python/docs/source/install.rst | 46 + contrib/python/docs/source/modules/ldns.rst | 40 + .../docs/source/modules/ldns_buffer.rst | 11 + .../python/docs/source/modules/ldns_dname.rst | 11 + .../docs/source/modules/ldns_dnssec.rst | 28 + .../python/docs/source/modules/ldns_func.rst | 253 + .../python/docs/source/modules/ldns_key.rst | 11 + .../docs/source/modules/ldns_key_list.rst | 11 + .../python/docs/source/modules/ldns_pkt.rst | 11 + .../python/docs/source/modules/ldns_rdf.rst | 47 + .../docs/source/modules/ldns_resolver.rst | 13 + .../python/docs/source/modules/ldns_rr.rst | 18 + .../docs/source/modules/ldns_rr_list.rst | 11 + .../python/docs/source/modules/ldns_zone.rst | 11 + contrib/python/examples/ldns-axfr.py | 56 + contrib/python/examples/ldns-buf.py | 8 + contrib/python/examples/ldns-dnssec.py | 45 + contrib/python/examples/ldns-higher.py | 36 + contrib/python/examples/ldns-keygen.py | 46 + contrib/python/examples/ldns-mx.py | 15 + contrib/python/examples/ldns-mx1.py | 18 + contrib/python/examples/ldns-mx2.py | 19 + contrib/python/examples/ldns-newpkt.py | 17 + contrib/python/examples/ldns-signzone.py | 65 + contrib/python/examples/ldns-zone.py | 15 + .../examples/ldns_rr_iter_frm_fp_l.demo.py | 15 + .../examples/ldns_rr_new_frm_fp_l.demo.py | 43 + contrib/python/examples/python3/ldns-axfr.py | 56 + contrib/python/examples/python3/ldns-buf.py | 8 + .../python/examples/python3/ldns-dnssec.py | 45 + .../python/examples/python3/ldns-higher.py | 36 + .../python/examples/python3/ldns-keygen.py | 46 + contrib/python/examples/python3/ldns-mx.py | 15 + contrib/python/examples/python3/ldns-mx1.py | 18 + contrib/python/examples/python3/ldns-mx2.py | 19 + .../python/examples/python3/ldns-newpkt.py | 17 + contrib/python/examples/python3/ldns-zone.py | 15 + .../python3/ldns_rr_iter_frm_fp_l.demo.py | 12 + .../python3/ldns_rr_new_frm_fp_l.demo.py | 43 + contrib/python/examples/zone.txt | 15 + contrib/python/file_py3.i | 120 + contrib/python/ldns.i | 362 + contrib/python/ldns_buffer.i | 565 + contrib/python/ldns_dname.i | 196 + contrib/python/ldns_dnssec.i | 434 + contrib/python/ldns_key.i | 536 + contrib/python/ldns_packet.i | 1086 + contrib/python/ldns_rdf.i | 426 + contrib/python/ldns_resolver.i | 946 + contrib/python/ldns_rr.i | 1584 ++ contrib/python/ldns_zone.i | 298 + dname.c | 565 + dnssec.c | 1764 ++ dnssec_sign.c | 1420 ++ dnssec_verify.c | 2699 +++ dnssec_zone.c | 1093 + doc/API-header.xml | 109 + doc/API.xml | 462 + doc/CodingStyle | 64 + doc/TODO | 22 + doc/design.dox | 124 + doc/dns-lib-implementations | 56 + doc/doxyparse.pl | 288 + doc/function_manpages | 223 + doc/header.html | 10 + doc/images/LogoInGradientBar2-y100.png | Bin 0 -> 60773 bytes doc/images/libdnsoverview.png | Bin 0 -> 43646 bytes doc/images/libdnsoverview.svg | 475 + doc/libdns.css | 425 + doc/tutorial1_mx.dox | 98 + doc/tutorial2_zone.dox | 111 + doc/tutorial3_signzone.dox | 206 + drill/ChangeLog.22-nov-2005 | 105 + drill/Makefile.in | 119 + drill/README | 12 + drill/REGRESSIONS | 25 + drill/chasetrace.c | 395 + drill/config.h.in | 293 + drill/configure | 6678 ++++++ drill/configure.ac | 259 + drill/dnssec.c | 473 + drill/drill.1 | 230 + drill/drill.c | 934 + drill/drill.h | 104 + drill/drill_util.c | 305 + drill/drill_util.h | 58 + drill/error.c | 115 + drill/install-sh | 520 + drill/root.c | 122 + drill/securetrace.c | 746 + drill/work.c | 276 + duration.c | 354 + error.c | 112 + examples/Makefile.in | 182 + examples/README | 5 + examples/config.h.in | 363 + examples/configure | 7158 ++++++ examples/configure.ac | 421 + examples/fake-rfc2553.h | 175 + examples/ldns-chaos.1 | 26 + examples/ldns-chaos.c | 125 + examples/ldns-compare-zones.1 | 57 + examples/ldns-compare-zones.c | 283 + examples/ldns-dpa.1 | 151 + examples/ldns-dpa.c | 2838 +++ examples/ldns-dpa.h | 92 + examples/ldns-gen-zone.1 | 98 + examples/ldns-gen-zone.c | 310 + examples/ldns-key2ds.1 | 41 + examples/ldns-key2ds.c | 199 + examples/ldns-keyfetcher.1 | 64 + examples/ldns-keyfetcher.c | 722 + examples/ldns-keygen.1 | 53 + examples/ldns-keygen.c | 307 + examples/ldns-mx.1 | 23 + examples/ldns-mx.c | 88 + examples/ldns-notify.1 | 66 + examples/ldns-notify.c | 334 + examples/ldns-nsec3-hash.1 | 34 + examples/ldns-nsec3-hash.c | 127 + examples/ldns-read-zone.1 | 69 + examples/ldns-read-zone.c | 212 + examples/ldns-resolver.1 | 26 + examples/ldns-resolver.c | 47 + examples/ldns-revoke.1 | 27 + examples/ldns-revoke.c | 104 + examples/ldns-rrsig.1 | 30 + examples/ldns-rrsig.c | 219 + examples/ldns-signzone.1 | 164 + examples/ldns-signzone.c | 839 + examples/ldns-test-edns.1 | 41 + examples/ldns-test-edns.c | 248 + examples/ldns-testns.1 | 131 + examples/ldns-testns.c | 577 + examples/ldns-testpkts.c | 881 + examples/ldns-testpkts.h | 255 + examples/ldns-update.1 | 44 + examples/ldns-update.c | 310 + examples/ldns-verify-zone.1 | 89 + examples/ldns-verify-zone.c | 946 + examples/ldns-version.1 | 22 + examples/ldns-version.c | 16 + examples/ldns-walk.1 | 49 + examples/ldns-walk.c | 671 + examples/ldns-zcat.1 | 30 + examples/ldns-zcat.c | 171 + examples/ldns-zsplit.1 | 39 + examples/ldns-zsplit.c | 272 + examples/ldnsd.1 | 26 + examples/ldnsd.c | 243 + higher.c | 359 + host2str.c | 2314 ++ host2wire.c | 434 + install-sh | 527 + keys.c | 1693 ++ ldns/buffer.h | 644 + ldns/common.h.in | 68 + ldns/config.h.in | 555 + ldns/dname.h | 201 + ldns/dnssec.h | 522 + ldns/dnssec_sign.h | 383 + ldns/dnssec_verify.h | 873 + ldns/dnssec_zone.h | 476 + ldns/duration.h | 109 + ldns/error.h | 123 + ldns/higher.h | 113 + ldns/host2str.h | 759 + ldns/host2wire.h | 164 + ldns/keys.h | 603 + ldns/ldns.h | 156 + ldns/net.h.in | 208 + ldns/packet.h | 855 + ldns/parse.h | 167 + ldns/rbtree.h | 230 + ldns/rdata.h | 385 + ldns/resolver.h | 721 + ldns/rr.h | 887 + ldns/rr_functions.h | 363 + ldns/sha1.h | 38 + ldns/sha2.h | 149 + ldns/str2host.h | 251 + ldns/tsig.h | 101 + ldns/update.h | 115 + ldns/util.h.in | 367 + ldns/wire2host.h | 197 + ldns/zone.h | 176 + ldns_symbols.def | 783 + libdns.doxygen | 1684 ++ libdns.vim | 459 + linktest.c | 13 + ltmain.sh | 9661 ++++++++ net.c | 907 + packaging/fedora/ldns.spec | 212 + packaging/ldns-config.1 | 43 + packaging/ldns-config.in | 31 + packaging/libldns.pc.in | 13 + packet.c | 1007 + parse.c | 448 + rbtree.c | 670 + rdata.c | 675 + resolver.c | 1350 ++ rr.c | 2426 ++ rr_functions.c | 419 + sha1.c | 177 + sha2.c | 982 + str2host.c | 1320 ++ tsig.c | 472 + update.c | 318 + util.c | 492 + wire2host.c | 456 + zone.c | 431 + 285 files changed, 134028 insertions(+) create mode 100644 Changelog create mode 100644 LICENSE create mode 100644 Makefile.in create mode 100644 README create mode 100644 README.snapshots create mode 100644 README.svn create mode 100644 aclocal.m4 create mode 100644 acx_nlnetlabs.m4 create mode 100644 ax_pkg_swig.m4 create mode 100644 ax_python_devel.m4 create mode 100644 buffer.c create mode 100644 compat/b32_ntop.c create mode 100644 compat/b32_pton.c create mode 100644 compat/b64_ntop.c create mode 100644 compat/b64_pton.c create mode 100644 compat/calloc.c create mode 100644 compat/ctime_r.c create mode 100644 compat/fake-rfc2553.c create mode 100644 compat/fake-rfc2553.h create mode 100644 compat/gmtime_r.c create mode 100644 compat/inet_aton.c create mode 100644 compat/inet_ntop.c create mode 100644 compat/inet_pton.c create mode 100644 compat/isascii.c create mode 100644 compat/isblank.c create mode 100644 compat/localtime_r.c create mode 100644 compat/malloc.c create mode 100644 compat/memmove.c create mode 100644 compat/realloc.c create mode 100644 compat/snprintf.c create mode 100644 compat/strlcpy.c create mode 100644 compat/timegm.c create mode 100755 config.guess create mode 100755 config.sub create mode 100755 configure create mode 100644 configure.ac create mode 100644 contrib/NETLDNS.readme.txt create mode 100644 contrib/NETLDNS.tar.gz create mode 100755 contrib/build-solaris.sh create mode 100644 contrib/ldnsx/LICENSE create mode 100644 contrib/ldnsx/Makefile create mode 100644 contrib/ldnsx/README create mode 100644 contrib/ldnsx/examples/ldnsx-axfr.py create mode 100644 contrib/ldnsx/examples/ldnsx-dnssec.py create mode 100644 contrib/ldnsx/examples/ldnsx-mx1.py create mode 100644 contrib/ldnsx/examples/ldnsx-mx2.py create mode 100755 contrib/ldnsx/examples/ldnsx-walk.py create mode 100644 contrib/ldnsx/ldnsx.py create mode 100644 contrib/ldnsx/source/api/ldnsx.rst create mode 100644 contrib/ldnsx/source/api/packet.rst create mode 100644 contrib/ldnsx/source/api/resolver.rst create mode 100644 contrib/ldnsx/source/api/resource_record.rst create mode 100644 contrib/ldnsx/source/conf.py create mode 100644 contrib/ldnsx/source/examples/ldnsx-axfr.rst create mode 100644 contrib/ldnsx/source/examples/ldnsx-dnssec.rst create mode 100644 contrib/ldnsx/source/examples/ldnsx-mx1.rst create mode 100644 contrib/ldnsx/source/examples/ldnsx-mx2.rst create mode 100644 contrib/ldnsx/source/examples/ldnsx-walk.rst create mode 100644 contrib/ldnsx/source/index.rst create mode 100644 contrib/python/LICENSE create mode 100644 contrib/python/Makefile create mode 100644 contrib/python/docs/Makefile create mode 100644 contrib/python/docs/source/conf.py create mode 100644 contrib/python/docs/source/examples/example1.rst create mode 100755 contrib/python/docs/source/examples/example2.py create mode 100644 contrib/python/docs/source/examples/example2.rst create mode 100644 contrib/python/docs/source/examples/example3.rst create mode 100644 contrib/python/docs/source/examples/example4.rst create mode 100644 contrib/python/docs/source/examples/example5.rst create mode 100644 contrib/python/docs/source/examples/example6.rst create mode 100644 contrib/python/docs/source/examples/example7.rst create mode 100644 contrib/python/docs/source/examples/example8.rst create mode 100644 contrib/python/docs/source/examples/index.rst create mode 100644 contrib/python/docs/source/index.rst create mode 100644 contrib/python/docs/source/install.rst create mode 100644 contrib/python/docs/source/modules/ldns.rst create mode 100644 contrib/python/docs/source/modules/ldns_buffer.rst create mode 100644 contrib/python/docs/source/modules/ldns_dname.rst create mode 100644 contrib/python/docs/source/modules/ldns_dnssec.rst create mode 100644 contrib/python/docs/source/modules/ldns_func.rst create mode 100644 contrib/python/docs/source/modules/ldns_key.rst create mode 100644 contrib/python/docs/source/modules/ldns_key_list.rst create mode 100644 contrib/python/docs/source/modules/ldns_pkt.rst create mode 100644 contrib/python/docs/source/modules/ldns_rdf.rst create mode 100644 contrib/python/docs/source/modules/ldns_resolver.rst create mode 100644 contrib/python/docs/source/modules/ldns_rr.rst create mode 100644 contrib/python/docs/source/modules/ldns_rr_list.rst create mode 100644 contrib/python/docs/source/modules/ldns_zone.rst create mode 100755 contrib/python/examples/ldns-axfr.py create mode 100755 contrib/python/examples/ldns-buf.py create mode 100755 contrib/python/examples/ldns-dnssec.py create mode 100755 contrib/python/examples/ldns-higher.py create mode 100755 contrib/python/examples/ldns-keygen.py create mode 100755 contrib/python/examples/ldns-mx.py create mode 100755 contrib/python/examples/ldns-mx1.py create mode 100755 contrib/python/examples/ldns-mx2.py create mode 100755 contrib/python/examples/ldns-newpkt.py create mode 100755 contrib/python/examples/ldns-signzone.py create mode 100755 contrib/python/examples/ldns-zone.py create mode 100644 contrib/python/examples/ldns_rr_iter_frm_fp_l.demo.py create mode 100644 contrib/python/examples/ldns_rr_new_frm_fp_l.demo.py create mode 100755 contrib/python/examples/python3/ldns-axfr.py create mode 100755 contrib/python/examples/python3/ldns-buf.py create mode 100755 contrib/python/examples/python3/ldns-dnssec.py create mode 100755 contrib/python/examples/python3/ldns-higher.py create mode 100755 contrib/python/examples/python3/ldns-keygen.py create mode 100755 contrib/python/examples/python3/ldns-mx.py create mode 100755 contrib/python/examples/python3/ldns-mx1.py create mode 100755 contrib/python/examples/python3/ldns-mx2.py create mode 100755 contrib/python/examples/python3/ldns-newpkt.py create mode 100755 contrib/python/examples/python3/ldns-zone.py create mode 100644 contrib/python/examples/python3/ldns_rr_iter_frm_fp_l.demo.py create mode 100644 contrib/python/examples/python3/ldns_rr_new_frm_fp_l.demo.py create mode 100644 contrib/python/examples/zone.txt create mode 100644 contrib/python/file_py3.i create mode 100644 contrib/python/ldns.i create mode 100644 contrib/python/ldns_buffer.i create mode 100644 contrib/python/ldns_dname.i create mode 100644 contrib/python/ldns_dnssec.i create mode 100644 contrib/python/ldns_key.i create mode 100644 contrib/python/ldns_packet.i create mode 100644 contrib/python/ldns_rdf.i create mode 100644 contrib/python/ldns_resolver.i create mode 100644 contrib/python/ldns_rr.i create mode 100644 contrib/python/ldns_zone.i create mode 100644 dname.c create mode 100644 dnssec.c create mode 100644 dnssec_sign.c create mode 100644 dnssec_verify.c create mode 100644 dnssec_zone.c create mode 100644 doc/API-header.xml create mode 100644 doc/API.xml create mode 100644 doc/CodingStyle create mode 100644 doc/TODO create mode 100644 doc/design.dox create mode 100644 doc/dns-lib-implementations create mode 100755 doc/doxyparse.pl create mode 100644 doc/function_manpages create mode 100644 doc/header.html create mode 100644 doc/images/LogoInGradientBar2-y100.png create mode 100644 doc/images/libdnsoverview.png create mode 100644 doc/images/libdnsoverview.svg create mode 100644 doc/libdns.css create mode 100644 doc/tutorial1_mx.dox create mode 100644 doc/tutorial2_zone.dox create mode 100644 doc/tutorial3_signzone.dox create mode 100644 drill/ChangeLog.22-nov-2005 create mode 100644 drill/Makefile.in create mode 100644 drill/README create mode 100644 drill/REGRESSIONS create mode 100644 drill/chasetrace.c create mode 100644 drill/config.h.in create mode 100755 drill/configure create mode 100644 drill/configure.ac create mode 100644 drill/dnssec.c create mode 100644 drill/drill.1 create mode 100644 drill/drill.c create mode 100644 drill/drill.h create mode 100644 drill/drill_util.c create mode 100644 drill/drill_util.h create mode 100644 drill/error.c create mode 100755 drill/install-sh create mode 100644 drill/root.c create mode 100644 drill/securetrace.c create mode 100644 drill/work.c create mode 100644 duration.c create mode 100644 error.c create mode 100644 examples/Makefile.in create mode 100644 examples/README create mode 100644 examples/config.h.in create mode 100755 examples/configure create mode 100644 examples/configure.ac create mode 100644 examples/fake-rfc2553.h create mode 100644 examples/ldns-chaos.1 create mode 100644 examples/ldns-chaos.c create mode 100644 examples/ldns-compare-zones.1 create mode 100644 examples/ldns-compare-zones.c create mode 100644 examples/ldns-dpa.1 create mode 100644 examples/ldns-dpa.c create mode 100644 examples/ldns-dpa.h create mode 100644 examples/ldns-gen-zone.1 create mode 100644 examples/ldns-gen-zone.c create mode 100644 examples/ldns-key2ds.1 create mode 100644 examples/ldns-key2ds.c create mode 100644 examples/ldns-keyfetcher.1 create mode 100644 examples/ldns-keyfetcher.c create mode 100644 examples/ldns-keygen.1 create mode 100644 examples/ldns-keygen.c create mode 100644 examples/ldns-mx.1 create mode 100644 examples/ldns-mx.c create mode 100644 examples/ldns-notify.1 create mode 100644 examples/ldns-notify.c create mode 100644 examples/ldns-nsec3-hash.1 create mode 100644 examples/ldns-nsec3-hash.c create mode 100644 examples/ldns-read-zone.1 create mode 100644 examples/ldns-read-zone.c create mode 100644 examples/ldns-resolver.1 create mode 100644 examples/ldns-resolver.c create mode 100644 examples/ldns-revoke.1 create mode 100644 examples/ldns-revoke.c create mode 100644 examples/ldns-rrsig.1 create mode 100644 examples/ldns-rrsig.c create mode 100644 examples/ldns-signzone.1 create mode 100644 examples/ldns-signzone.c create mode 100644 examples/ldns-test-edns.1 create mode 100644 examples/ldns-test-edns.c create mode 100644 examples/ldns-testns.1 create mode 100644 examples/ldns-testns.c create mode 100644 examples/ldns-testpkts.c create mode 100644 examples/ldns-testpkts.h create mode 100644 examples/ldns-update.1 create mode 100644 examples/ldns-update.c create mode 100644 examples/ldns-verify-zone.1 create mode 100644 examples/ldns-verify-zone.c create mode 100644 examples/ldns-version.1 create mode 100644 examples/ldns-version.c create mode 100644 examples/ldns-walk.1 create mode 100644 examples/ldns-walk.c create mode 100644 examples/ldns-zcat.1 create mode 100644 examples/ldns-zcat.c create mode 100644 examples/ldns-zsplit.1 create mode 100644 examples/ldns-zsplit.c create mode 100644 examples/ldnsd.1 create mode 100644 examples/ldnsd.c create mode 100644 higher.c create mode 100644 host2str.c create mode 100644 host2wire.c create mode 100755 install-sh create mode 100644 keys.c create mode 100644 ldns/buffer.h create mode 100644 ldns/common.h.in create mode 100644 ldns/config.h.in create mode 100644 ldns/dname.h create mode 100644 ldns/dnssec.h create mode 100644 ldns/dnssec_sign.h create mode 100644 ldns/dnssec_verify.h create mode 100644 ldns/dnssec_zone.h create mode 100644 ldns/duration.h create mode 100644 ldns/error.h create mode 100644 ldns/higher.h create mode 100644 ldns/host2str.h create mode 100644 ldns/host2wire.h create mode 100644 ldns/keys.h create mode 100644 ldns/ldns.h create mode 100644 ldns/net.h.in create mode 100644 ldns/packet.h create mode 100644 ldns/parse.h create mode 100644 ldns/rbtree.h create mode 100644 ldns/rdata.h create mode 100644 ldns/resolver.h create mode 100644 ldns/rr.h create mode 100644 ldns/rr_functions.h create mode 100644 ldns/sha1.h create mode 100644 ldns/sha2.h create mode 100644 ldns/str2host.h create mode 100644 ldns/tsig.h create mode 100644 ldns/update.h create mode 100644 ldns/util.h.in create mode 100644 ldns/wire2host.h create mode 100644 ldns/zone.h create mode 100644 ldns_symbols.def create mode 100644 libdns.doxygen create mode 100644 libdns.vim create mode 100644 linktest.c create mode 100755 ltmain.sh create mode 100644 net.c create mode 100644 packaging/fedora/ldns.spec create mode 100644 packaging/ldns-config.1 create mode 100755 packaging/ldns-config.in create mode 100644 packaging/libldns.pc.in create mode 100644 packet.c create mode 100644 parse.c create mode 100644 rbtree.c create mode 100644 rdata.c create mode 100644 resolver.c create mode 100644 rr.c create mode 100644 rr_functions.c create mode 100644 sha1.c create mode 100644 sha2.c create mode 100644 str2host.c create mode 100644 tsig.c create mode 100644 update.c create mode 100644 util.c create mode 100644 wire2host.c create mode 100644 zone.c diff --git a/Changelog b/Changelog new file mode 100644 index 00000000000..93e53931d84 --- /dev/null +++ b/Changelog @@ -0,0 +1,704 @@ +1.6.13 2012-05-21 + * New -S option for ldns-verify-zone to chase signatures online. + * New -k option for ldns-verify-zone to validate using a trusted key. + * New inception and expiration margin options (-i and -e) to + ldns-verify-zone. + * New ldns_dnssec_zone_new_frm_fp and ldns_dnssec_zone_new_frm_fp_l + functions. + * New ldns_duration* functions (copied from OpenDNSSEC source) + * fix ldns-verify-zone to allow NSEC3 signatures to come before + the NSEC3 RR in all cases. Thanks Wolfgang Nagele. + * Zero the correct flag (opt-out) when creating NSEC3PARAMS. + Thanks Peter van Dijk. + * Canonicalize RRSIG's Signer's name too when validating, because + bind and unbound do that too. Thanks Peter van Dijk. + * bugfix #433: Allocate rdf using ldns_rdf_new in ldns_dname_label + * bugfix #432: Use LDNS_MALLOC & LDNS_FREE i.s.o. malloc & free + * bugfix #431: Added error message for LDNS_STATUS_INVALID_B32_EXT + * bugfix #427: Explicitely link ssl with the programs that use it. + * Fix reading \DDD: Error on values that are outside range (>255). + * bugfix #429: fix doxyparse.pl fails on NetBSD because specified + path to perl. + * New ECDSA support (RFC 6605), use --disable-ecdsa for older openssl. + * fix verifying denial of existence for DS's in NSEC3 Opt-Out zones. + Thanks John Barnitz + +1.6.12 2012-01-11 + * bugfix #413: Fix manpage source for srcdir != builddir + * Canonicalize the signers name rdata field in RRSIGs when signing + * Ignore minor version of Private-key-format (so v1.3 may be used) + * Allow a check_time to be given in stead of always checking against + the current time. With ldns-verify-zone the check_time can be set + with the -t option. + * Added functions for updating and manipulating SOA serial numbers. + ldns-read-zone has an option -S for updating and manipulating the + serial numbers. + * The library Makefile is now GNU and BSD make compatible. + * bugfix #419: NSEC3 validation of a name covered by a wildcard with + no data. + * Two new options (--with-drill and --with-examples) to the main + configure script (in the root of the source tree) to build drill + and examples too. + * Fix days_since_epoch to year_yday calculation on 32bits systems. + +1.6.11 2011-09-29 + * bugfix #394: Fix socket leak on errors + * bugfix #392: Apex only and percentage checks for ldns-verify-zone + (thanks Miek Gieben) + * bugfix #398: Allow NSEC RRSIGs before the NSEC3 in ldns-verify-zone + * Fix python site package path from sitelib to sitearch for pyldns. + * Fix python api to support python2 and python3 (thanks Karel Slany). + * bugfix #401: Correction of date/time functions algorithm and + prevention of an infinite loop therein + * bugfix #402: Correct the minimum and maximum number of rdata fields + in TSIG. (thanks David Keeler) + * bugfix #403: Fix heap overflow (thanks David Keeler) + * bugfix #404: Make parsing APL strings more robust + (thanks David Keeler) + * bugfix #391: Complete library assessment to prevent assertion errors + through ldns_rdf_size usage. + * Slightly more specific error messaging on wrong number of rdata + fields with the LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG and + LDNS_STATUS_MISSING_RDATA_FIELDS_KEY result codes. + * bugfix #406: More rigorous openssl result code handling to prevent + future crashes within openssl. + * Fix ldns_fetch_valid_domain_keys to search deeper than just one level + for a DNSKEY that signed a DS RR. (this function was used in the + check_dnssec_trace nagios module) + * bugfix #407: Canonicalize TSIG dnames and algorithm fields + * A new output specifier to accommodate configuration of what to show + in comment texts when converting host and/or wire-format data to + string. All conversion to string and printing functions have a new + version that have such a format specifier as an extra argument. + The default is changed so that only DNSKEY RR's are annotated with + an comment show the Key Tag of the DNSKEY. + * Fixed the ldns resolver to not mark a nameserver unreachable when + edns0 is tried unsuccessfully with size 4096 (no return packet came), + but to still try TCP. A big UDP packet might have been corrupted by + fragments dropping firewalls. + * Update of libdns.vim (thanks Miek Gieben) + * Added the ldnsx Python module to our contrib section, which adds even + more pythonisticism to the usage of ldns with Python. (Many thanks + to Christpher Olah and Paul Wouters) + The ldnsx module is automatically installed when --with-pyldns is + used with configuring, but may explicitly be excluded with the + --without-pyldnsx option to configure. + * bugfix #410: Fix clearing out temporary data on stack in sha2.c + * bugfix #411: Don't let empty non-terminal NSEC3s cause assertion failure. + +1.6.10 2011-05-31 + * New example tool added: ldns-gen-zone. + * bugfix #359: Serial-arithmetic for the inception and expiration + fields of a RRSIG and correctly converting them to broken-out time + information. + * bugfix #364: Slight performance increase of ldns-verifyzone. + * bugfix #367: Fix to allow glue records with the same name as the + delegation. + * Fix ldns-verifyzone to allow NSEC3-less records for NS rrsets *and* + glue when the zone is opt-out. + * bugfix #376: Adapt ldns_nsec3_salt, ldns_nsec3_iterations, + ldns_nsec3_flags and ldns_nsec3_algorithm to work for NSEC3PARAMS too. + * pyldns memory leaks fixed by Bedrich Kosata (at the cost of a bit + performance) + * Better handling of reference variables in ldns_rr_new_frm_fp_l from + pyldns, with a very nice generator function by Bedrich Kosata. + * Decoupling of the rdfs in rrs in the python wrappers to enable + the python garbage collector by Bedrich Kosata. + * bugfix #380: Minimizing effect of discrepancies in sizeof(bool) at + build time and when used. + * bugfix #383: Fix detection of empty nonterminals of multiple labels. + * Fixed the ommission of rrsets in nsec(3)s and rrsigs to all occluded + names (in stead of just the ones that contain glue only) and all + occluded records on the delegation points (in stead of just the glue). + * Clarify the operation of ldns_dnssec_mark_glue and the usage of + ldns_dnssec_node_next_nonglue functions in the documentation. + * Added function ldns_dnssec_mark_and_get_glue as an real fast + alternative for ldns_zone_glue_rr_list. + * Fix parse buffer overflow for max length domain names. + * Fix Makefile for U in environment, since wrong U is more common than + deansification necessity. + +1.6.9 2011-03-16 + * Fix creating NSEC(3) bitmaps: make array size 65536, + don't add doubles. + * Fix printout of escaped binary in TXT records. + * Parsing TXT records: don't skip starting whitespace that is quoted. + * bugfix #358: Check if memory was successfully allocated in + ldns_rdf2str(). + * Added more memory allocation checks in host2str.c + * python wrapper for ldns_fetch_valid_domain_keys by Bedrich Kosata. + * fix to compile python wrapper with swig 2.0.2. + * Don't fallback to SHA-1 when creating NSEC3 hash with another + algorithm identifier, fail instead (no other algorithm identifiers + are assigned yet). + +1.6.8 2011-01-24 + * Fix ldns zone, so that $TTL definition match RFC 2308. + * Fix lots of missing checks on allocation failures and parse of + NSEC with many types and max parse length in hosts_frm_fp routine + and off by one in read_anchor_file routine (thanks Dan Kaminsky and + Justin Ferguson). + * bugfix #335: Drill: Print both SHA-1 and SHA-256 corresponding DS + records. + * Print correct WHEN in query packet (is not always 1-1-1970) + * ldns-test-edns: new example tool that detects EDNS support. + * fix ldns_resolver_send without openssl. + * bugfix #342: patch for support for more CERT key types (RFC4398). + * bugfix #351: fix udp_send hang if UDP checksum error. + * fix set_bit (from NSEC3 sign) patch from Jan Komissar. + +1.6.7 2010-11-08 + * EXPERIMENTAL ecdsa implementation, please do not enable on real + servers. + * GOST code enabled by default (RFC 5933). + * bugfix #326: ignore whitespace between directives and their values. + * Header comment to advertise ldns_axfr_complete to check for + successfully completed zone transfers. + * read resolv.conf skips interface labels, e.g. %eth0. + * Fix drill verify NSEC3 denials. + * Use closesocket() on windows. + * Add ldns_get_signing_algorithm_by_name that understand aliases, + names changed to RFC names and aliases for compatibility added. + * bugfix: don't print final dot if the domain is relative. + * bugfix: resolver search continue when packet rcode != NOERROR. + * bugfix: resolver push all domains in search directive to list. + * bugfix: resolver search by default includes the root domain. + * bugfix: tcp read could fail on single octet recv. + * bugfix: read of RR in unknown syntax with missing fields. + * added ldns_pkt_tsig_sign_next() and ldns_pkt_tsig_verify_next() + to sign and verify TSIG RRs on subsequent messages + (section 4.4, RFC 2845, thanks to Michael Sheldon). + * bugfix: signer sigs nsecs with zsks only. + * bugfix #333: fix ldns_dname_absolute for name ending with backslash. + +1.6.6 2010-08-09 + * Fix ldns_rr_clone to copy question rrs properly. + * Fix ldns_sign_zone(_nsec3) to clone the soa for the new zone. + * Fix ldns_wire2dname size check from reading 1 byte beyond buffer end. + * Fix ldns_wire2dname from reading 1 byte beyond end for pointer. + * Fix crash using GOST for particular platform configurations. + * extern C declarations used in the header file. + * Removed debug fprintf from resolver.c. + * ldns-signzone checks if public key file is for the right zone. + * NETLDNS, .NET port of ldns functionality, by Alex Nicoll, in contrib. + * Fix handling of comments in resolv.conf parse. + * GOST code enabled if SSL recent, RFC 5933. + * bugfix #317: segfault util.c ldns_init_random() fixed. + * Fix ldns_tsig_mac_new: allocate enough memory for the hash, fix use of + b64_pton_calculate_size. + * Fix ldns_dname_cat: size calculation and handling of realloc(). + * Fix ldns_rr_pop_rdf: fix handling of realloc(). + * Fix ldns-signzone for single type key scheme: sign whole zone if there + are only KSKs. + * Fix ldns_resolver: also close socket if AXFR failed (if you don't, + it would block subsequent transfers (thanks Roland van Rijswijk). + * Fix drill: allow for a secure trace if you use DS records as trust + anchors (thanks Jan Komissar). + +1.6.5 2010-06-15 + * Catch \X where X is a digit as an error. + * Fix segfault when ip6 ldns resolver only has ip4 servers. + * Fix NSEC record after DNSKEY at zone apex not properly signed. + * Fix syntax error if last label too long and no dot at end of domain. + * Fix parse of \# syntax with space for type LOC. + * Fix ldns_dname_absolute for escape sequences, fixes some parse errs. + * bugfix #297: linking ssl, bug due to patch submitted as #296. + * bugfix #299: added missing declarations to host2str.h + * ldns-compare-zones -s to not exclude SOA record from comparison. + * --disable-rpath fix + * fix ldns_pkt_empty(), reported by Alex Nicoll. + * fix ldns_resolver_new_frm_fp not ignore lines after a comment. + * python code for ldns_rr.new_question_frm_str() + * Fix ldns_dnssec_verify_denial: the signature selection routine. + * Type TALINK parsed (draft-ietf-dnsop-trust-history). + * bugfix #304: fixed dead loop in ldns_tcp_read_wire() and + ldns_tcp_read_wire_timeout(). + * GOST support with correct algorithm numbers. The plan is to make it + enabled if openssl support is detected, but it is disabled by + default in this release because the RFC is not ready. + * Fixed comment in rbtree.h about being first member and data ptr. + * Fixed possibly leak in case of out of memory in ldns_native2rdf... + * ldns_dname_is_wildcard added. + * Fixed: signatures over wildcards had the wrong labelcount. + * Fixed ldns_verify() inconsistent return values. + * Fixed ldns_resolver to copy and free tsig name, data and algorithm. + * Fixed ldns_resolver to push search onto searchlist. + * A ldns resolver now defaults to a non-recursive resolver that handles + the TC bit. + * ldns_resolver_print() prints more details. + * Fixed ldns_rdf2buffer_str_time(), which did not print timestamps + on 64bit systems. + * Make ldns_resolver_nameservers_randomize() more random. + * bugfix #310: POSIX specifies NULL second argument of gettimeofday. + * fix compiler warnings from llvm clang compiler. + * bugfix #309: ldns_pkt_clone did not clone the tsig_rr. + * Fix gentoo ebuild for drill, 'no m4 directory'. + * bugfix #313: drill trace on an empty nonterminal continuation. + +1.6.4 2010-01-20 + * Imported pyldns contribution by Zdenek Vasicek and Karel Slany. + Changed its configure and Makefile to fit into ldns. + Added its dname_* methods to the rdf_* class (as is the ldns API). + Changed swig destroy of ldns_buffer class to ldns_buffer_free. + Declared ldns_pkt_all and ldns_pkt_all_noquestion so swig sees them. + * Bugfix: parse PTR target of .tomhendrikx.nl with error not crash. + * Bugfix: handle escaped characters in TXT rdata. + * bug292: no longer crash on malformed domain names where a label is + on position 255, which was a buffer overflow by one. + * Fix ldns_get_rr_list_hosts_frm_fp_l (strncpy to strlcpy change), + which fixes resolv.conf reading badly terminated string buffers. + * Fix ldns_pkt_set_random_id to be more random, and a little faster, + it did not do value 0 statistically correctly. + * Fix ldns_rdf2native_sockaddr_storage to set sockaddr type to zeroes, + for portability. + * bug295: nsec3-hash routine no longer case sensitive. + * bug298: drill failed nsec3 denial of existence proof. + +1.6.3 2009-12-04 + * Bugfix: allow for unknown resource records in zonefile with rdlen=0. + * Bugfix: also mark an RR as question if it comes from the wire + * Bugfix: NSEC3 bitmap contained NSEC + * Bugfix: Inherit class when creating signatures + +1.6.2 2009-11-12 + * Fix Makefile patch from Havard Eidnes, better install.sh usage. + * Fix parse error on SOA serial of 2910532839. + Fix print of ';' and readback of '\;' in names, also for '\\'. + Fix parse of '\(' and '\)' in names. Also for file read. Also '\.' + * Fix signature creation when TTLs are different for RRs in RRset. + * bug273: fix so EDNS rdata is included in pkt to wire conversion. + * bug274: fix use of c++ keyword 'class' for RR class in the code. + * bug275: fix memory leak of packet edns rdata. + * Fix timeout procedure for TCP and AXFR on Solaris. + * Fix occasional NSEC bitmap bogus + * Fix rr comparing (was in reversed order since 1.6.0) + * bug278: fix parsing HINFO rdata (and other cases). + * Fix previous owner name: also pick up if owner name is @. + * RFC5702: enabled sha2 functions by default. This requires OpenSSL 0.9.8 or higher. + Reason for this default is the root to be signed with RSASHA256. + * Fix various LDNS RR parsing issues: IPSECKEY, WKS, NSAP, very long lines + * Fix: Make ldns_dname_is_subdomain case insensitive. + * Fix ldns-verify-zone so that address records at zone NS set are not considered glue + (Or glue records fall below delegation) + * Fix LOC RR altitude printing. + * Feature: Added period (e.g. '3m6d') support at explicit TTLs. + * Feature: DNSKEY rrset by default signed with minimal signatures + but -A option for ldns-signzone to sign it with all keys. + This makes the DNSKEY responses smaller for signed domains. + +1.6.1 2009-09-14 + * --enable-gost : use the GOST algorithm (experimental). + * Added some missing options to drill manpage + * Some fixes to --without-ssl option + * Fixed quote parsing withing strings + * Bitmask fix in EDNS handling + * Fixed non-fqdn domain name completion for rdata field domain + names of length 1 + * Fixed chain validation with SHA256 DS records + +1.6.0 + Additions: + * Addition of an ldns-config script which gives cflags and libs + values, for use in configure scripts for applications that use + use ldns. Can be disabled with ./configure --disable-ldns-config + * Added direct sha1, sha256, and sha512 support in ldns. + With these functions, all NSEC3 functionality can still be + used, even if ldns is built without OpenSSL. Thanks to OpenBSD, + Steve Reid, and Aaron D. Gifford for the code. + * Added reading/writing support for the SPF Resource Record + * Base32 functions are now exported + Bugfixes: + * ldns_is_rrset did not go through the complete rrset, but + only compared the first two records. Thanks to Olafur + Gudmundsson for report and patch + * Fixed a small memory bug in ldns_rr_list_subtype_by_rdf(), + thanks to Marius Rieder for finding an patching this. + * --without-ssl should now work. Make sure that examples/ and + drill also get the --without-ssl flag on their configure, if + this is used. + * Some malloc() return value checks have been added + * NSEC3 creation has been improved wrt to empty nonterminals, + and opt-out. + * Fixed a bug in the parser when reading large NSEC3 salt + values. + * Made the allowed length for domain names on wire + and presentation format the same. + Example tools: + * ldns-key2ds can now also generate DS records for keys without + the SEP flag + * ldns-signzone now equalizes the TTL of the DNSKEY RRset (to + the first non-default DNSKEY TTL value it sees) + +1.5.1 + Example tools: + * ldns-signzone was broken in 1.5.0 for multiple keys, this + has been repaired + + Build system: + * Removed a small erroneous output warning in + examples/configure and drill/configure + +1.5.0 + Bug fixes: + * fixed a possible memory overflow in the RR parser + * build flag fix for Sun Studio + * fixed a building race condition in the copying of header + files + * EDNS0 extended rcode; the correct assembled code number + is now printed (still in the EDNS0 field, though) + * ldns_pkt_rr no longer leaks memory (in fact, it no longer + copies anything all) + + API addition: + * ldns_key now has support for 'external' data, in which + case the OpenSSL EVP structures are not used; + ldns_key_set_external_key() and ldns_key_external_key() + * added ldns_key_get_file_base_name() which creates a + 'default' filename base string for key storage, of the + form "K++" + * the ldns_dnssec_* family of structures now have deep_free() + functions, which also free the ldns_rr's contained in them + * there is now an ldns_match_wildcard() function, which checks + whether a domain name matches a wildcard name + * ldns_sign_public has been split up; this resulted in the + addition of ldns_create_empty_rrsig() and + ldns_sign_public_buffer() + + Examples: + * ldns-signzone can now automatically add DNSKEY records when + using an OpenSSL engine, as it already did when using key + files + * added new example tool: ldns-nsec3-hash + * ldns-dpa can now filter on specific query name and types + * ldnsd has fixes for the zone name, a fix for the return + value of recvfrom(), and an memory initialization fix + (Thanks to Colm MacCárthaigh for the patch) + * Fixed memory leaks in ldnsd + + + +1.4.1 + Bug fixes: + * fixed a build issue where ldns lib existence was done too early + * removed unnecessary check for pcap.h + * NSEC3 optout flag now correctly printed in string output + * inttypes.h moved to configured inclusion + * fixed NSEC3 type bitmaps for empty nonterminals and unsigned + delegations + + API addition: + * for that last fix, we added a new function + ldns_dname_add_from() that can clone parts of a dname + +1.4.0 + Bug fixes: + * sig chase return code fix (patch from Rafael Justo, bug id 189) + * rdata.c memory leaks on error and allocation checks fixed (patch + from Shane Kerr, bug id 188) + * zone.c memory leaks on error and allocation checks fixed (patch + from Shane Kerr, bug id 189) + * ldns-zplit output and error messages fixed (patch from Shane Kerr, + bug id 190) + * Fixed potential buffer overflow in ldns_str2rdf_dname + * Signing code no longer signs delegation NS rrsets + * Some minor configure/makefile updates + * Fixed a bug in the randomness initialization + * Fixed a bug in the reading of resolv.conf + * Fixed a bug concerning whitespace in zone data (with patch from Ondrej + Sury, bug 213) + * Fixed a small fallback problem in axfr client code + + API CHANGES: + * added 2str convenience functions: + - ldns_rr_type2str + - ldns_rr_class2str + - ldns_rr_type2buffer_str + - ldns_rr_class2buffer_str + * buffer2str() is now called ldns_buffer2str + * base32 and base64 function names are now also prepended with ldns_ + * ldns_rr_new_frm_str() now returns an error on missing RDATA fields. + Since you cannot read QUESTION section RRs with this anymore, + there is now a function called ldns_rr_new_question_frm_str() + + LIBRARY FEATURES: + * DS RRs string representation now add bubblebabble in a comment + (patch from Jakob Schlyter) + * DLV RR type added + * TCP fallback system has been improved + * HMAC-SHA256 TSIG support has been added. + * TTLS are now correcly set in NSEC(3) records when signing zones + + EXAMPLE TOOLS: + * New example: ldns-revoke to revoke DNSKEYs according to RFC5011 + * ldns-testpkts has been fixed and updated + * ldns-signzone now has the option to not add the DNSKEY + * ldns-signzone now has an (full zone only) opt-out option for + NSEC3 + * ldns-keygen can create HMAC-SHA1 and HMAC-SHA256 symmetric keys + * ldns-walk output has been fixed + * ldns-compare-zones has been fixed, and now has an option + to show all differences (-a) + * ldns-read-zone now has an option to print DNSSEC records only + +1.3 + Base library: + + * Added a new family of functions based around ldns_dnssec_zone, + which is a new structure that keeps a zone sorted through an + rbtree and links signatures and NSEC(3) records directly to their + RRset. These functions all start with ldns_dnssec_ + + * ldns_zone_sign and ldns_zone_sign_nsec3 are now deprecated, but + have been changed to internally use the new + ldns_dnssec_zone_sign(_nsec3) + + * Moved some ldns_buffer functions inline, so a clean rebuild of + applications relying on those is needed (otherwise you'll get + linker errors) + * ldns_dname_label now returns one extra (zero) + byte, so it can be seen as an fqdn. + * NSEC3 type code update for signing algorithms. + * DSA key generation of DNSKEY RRs fixed (one byte too small). + + * Added support for RSA/SHA256 and RSA/SHA512, as specified in + draft-ietf-dnsext-dnssec-rsasha256-04. The typecodes are not + final, and this feature is not enabled by default. It can be + enabled at compilation time with the flag --with-sha2 + + * Added 2wire_canonical family of functions that lowercase dnames + in rdata fields in resource records of the types in the list in + rfc3597 + + * Added base32 conversion functions. + + * Fixed DSA RRSIG conversion when calling OpenSSL + + Drill: + + * Chase output is completely different, it shows, in ascii, the + relations in the trust hierarchy. + + Examples: + * Added ldns-verify-zone, that can verify the internal DNSSEC records + of a signed BIND-style zone file + + * ldns-keygen now takes an -a argument specifying the algorithm, + instead of -R or -D. -a list show a list of supported algorithms + + * ldns-keygen now defaults to the exponent RSA_F4 instead of RSA_3 + for RSA key generation + + * ldns-signzone now has support for HSMs + * ldns-signzone uses the new ldns_dnssec_ structures and functions + which improves its speed, and output; RRSIGS are now placed + directly after their RRset, NSEC(3) records directly after the + name they handle + + Contrib: + * new contrib/ dir with user contributions + * added compilation script for solaris (thanks to Jakob Schlyter) + +28 Nov 2007 1.2.2: + * Added support for HMAC-MD5 keys in generator + * Added a new example tool (written by Ondrej Sury): ldns-compare-zones + * ldns-keygen now checks key sizes for rfc conformancy + * ldns-signzone outputs SSL error if present + * Fixed manpages (thanks to Ondrej Sury) + * Fixed Makefile for -j + * Fixed a $ORIGIN error when reading zones + * Fixed another off-by-one error + +03 Oct 2007 1.2.1: + * Fixed an offset error in rr comparison + * Fixed ldns-read-zone exit code + * Added check for availability of SHA256 hashing algorithm + * Fixed ldns-key2ds -2 argument + * Fixed $ORIGIN bug in .key files + * Output algorithms as an integer instead of their mnemonic + * Fixed a memory leak in dnssec code when SHA256 is not available + * Updated fedora .spec file + +11 Apr 2007 1.2.0: + * canonicalization of rdata in DNSSEC functions now adheres to the + rr type list in rfc3597, not rfc4035, which will be updated + (see http://www.ops.ietf.org/lists/namedroppers/namedroppers.2007/msg00183.html) + * ldns-walk now support dnames with maximum label length + * ldnsd now takes an extra argument containing the address to listen on + * signing no longer signs every rrset with KSK's, but only the DNSKEY rrset + * ported to Solaris 10 + * added ldns_send_buffer() function + * added ldns-testpkts fake packet server + * added ldns-notify to send NOTIFY packets + * ldns-dpa can now accurately calculate the number of matches per + second + * libtool is now used for compilation too (still gcc, but not directly) + * Bugfixes: + - TSIG signing buffer size + - resolv.conf reading (comments) + - dname comparison off by one error + - typo in keyfetchers output file name fixed (a . too much) + - fixed zone file parser when comments contain ( or ) + - fixed LOC RR type + - fixed CERT RR type + + Drill: + * drill prints error on failed axfr. + * drill now accepts mangled packets with -f + * old -c option (use tcp) changed to -t + * -c option to specify alternative resolv.conf file added + * feedback of signature chase improved + * chaser now stops at root when no trusted keys are found + instead of looping forever trying to find the DS for . + * Fixed bugs: + - wildcard on multiple labels signature verification + - error in -f packet writing for malformed packets + - made KSK check more resilient + +7 Jul 2006: 1.1.0: ldns-team + * Added tutorials and an introduction to the documentation + * Added include/ and lib/ dirs so that you can compile against ldns + without installing ldns on your system + * Makefile updates + * Starting usage of assert throughout the library to catch illegal calls + * Solaris 9 testing was carried out. Ldns now compiles on that + platform; some gnuism were identified and fixed. + * The ldns_zone structure was stress tested. The current setup + (ie. just a list of rrs) can scale to zone file in order of + megabytes. Sorting such zone is still difficult. + * Reading multiline b64 encoded rdata works. + * OpenSSL was made optional, configure --without-ssl. + Ofcourse all dnssec/tsig related functions are disabled + * Building of examples and drill now happens with the same + defines as the building of ldns itself. + * Preliminary sha-256 support was added. Currently is your + OpenSSL supports it, it is supported in the DS creation. + * ldns_resolver_search was implemented + * Fixed a lot of bugs + + Drill: + * -r was killed in favor of -o
which + allows for a header bits setting (and maybe more in the + future) + * DNSSEC is never automaticaly set, even when you query + for DNSKEY/RRSIG or DS. + * Implement a crude RTT check, it now distinguishes between + reachable and unreachable. + * A form of secure tracing was added + * Secure Chasing has been improved + * -x does a reverse lookup for the given IP address + + Examples: + * ldns-dpa was added to the examples - this is the Dns Packet + Analyzer tool. + * ldnsd - as very, very simple nameserver impl. + * ldns-zsplit - split zones for parrallel signing + * ldns-zcat - cat split zones back together + * ldns-keyfetcher - Fetches DNSKEY records with a few (non-strong, + non-DNSSEC) anti-spoofing techniques. + * ldns-walk - 'Walks' a DNSSEC signed zone + * Added an all-static target to the makefile so you can use examples + without installing the library + * When building in the source tree or in a direct subdirectory of + the build dir, configure does not need --with-ldns=../ anymore + + Code: + * All networking code was moved to net.c + * rdata.c: added asserts to the rdf set/get functions + * const keyword was added to pointer arguments that + aren't changed + + API: + Changed: + * renamed ldns/dns.h to ldns/ldns.h + * ldns_rr_new_frm_str() is extented with an extra variable which + in common use may be NULL. This trickles through to: + o ldns_rr_new_frm_fp + o ldns_rr_new_frm_fp_l + Which also get an extra variable + Also the function has been changed to return a status message. + The compiled RR is returned in the first argument. + * ldns_zone_new_frm_fp_l() and ldns_zone_new_frm_fp() are + changed to return a status msg. + * ldns_key_new_frm_fp is changed to return ldns_status and + the actual key list in the first argument + * ldns_rdata_new_frm_fp[_l]() are changed to return a status. + the rdf is return in the first argument + * ldns_resolver_new_frm_fp: same treatment: return status and + the new resolver in the first argument + * ldns_pkt_query_new_frm_str(): same: return status and the + packet in the first arg + * tsig.h: internal used functions are now static: + ldns_digest_name and ldns_tsig_mac_new + * ldns_key_rr2ds has an extra argument to specify the hash to + use. + * ldns_pkt_rcode() is renamed to ldns_pkt_get_rcode, ldns_pkt_rcode + is now the rcode type, like ldns_pkt_opcode + New: + * ldns_resolver_searchlist_count: return the searchlist counter + * ldns_zone_sort: Sort a zone + * ldns_bgsend(): background send, returns a socket. + * ldns_pkt_empty(): check is a packet is empty + * ldns_rr_list_pop_rr_list(): pop multiple rr's from another rr_list + * ldns_rr_list_push_rr_list(): push multiple rr's to an rr_list + * ldns_rr_list_compare(): compare 2 ldns_rr_lists + * ldns_pkt_push_rr_list: rr_list equiv for rr + * ldns_pkt_safe_push_rr_list: rr_list equiv for rr + Removed: + * ldns_resolver_bgsend(): was not used in 1.0.0 and is not used now + * ldns_udp_server_connect(): was faulty and isn't really part of + the core ldns idea any how. + * ldns_rr_list_insert_rr(): obsoleted, because not used. + * char *_when was removed from the ldns_pkt structure + +18 Oct 2005: 1.0.0: ldns-team + * Commited a patch from Håkan Olsson + * Added UPDATE support (Jakob Schlyter and Håkan Olsson) + * License change: ldns is now BSD licensed + * ldns now depends on SSL + * Networking code cleanup, added (some) server udp/tcp support + * A zone type is introduced. Currently this is a list + of RRs, so it will not scale well. + * [beta] Zonefile parsing was added + * [tools] Drill was added to ldns - see drill/ + * [tools] experimental signer was added + * [building] better check for ssl + * [building] major revision of build system + * [building] added rpm .spec in packaging/ (thanks to Paul Wouters) + * [building] A lot of cleanup in the build scripts (thanks to Jakob Schlyter + and Paul Wouters) + +28 Jul 2005: 0.70: ldns-team + * [func] ldns_pkt_get_section now returns copies from the rrlists + in the packet. This can be freed by the user program + * [code] added ldns_ prefixes to function from util.h + * [inst] removed documentation from default make install + * Usual fixes in documentation and code + +20 Jun 2005: 0.66: ldns-team + Rel. Focus: drill-pre2 uses some functions which are + not in 0.65 + * dnssec_cd bit function was added + * Zone infrastructure was added + * Usual fixes in documentation and code + +13 Jun 2005: 0.65: ldns-team + * Repository is online at: + http://www.nlnetlabs.nl/ldns/svn/ + * Apply reference copying throuhgout ldns, except in 2 + places in the ldns_resolver structure (._domain and + ._nameservers) + * Usual array of bugfixes + * Documentation added + * keygen.c added as an example for DNSSEC programming + +23 May 2005: 0.60: ldns-team + * Removed config.h from the header installed files + (you're not supposed to include that in a libary) + * Further tweaking + - DNSSEC signing/verification works + - Assorted bug fixes and tweaks (memory management) + +May 2005: 0.50: ldns-team + * First usable release + * Basic DNS functionality works + * DNSSEC validation works diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000000..6d4c6be0966 --- /dev/null +++ b/LICENSE @@ -0,0 +1,26 @@ +Copyright (c) 2005,2006, NLnetLabs +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. diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 00000000000..dfe3f352b13 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,1098 @@ +# Standard installation pathnames +# See the file LICENSE for the license +SHELL = @SHELL@ +VERSION = @PACKAGE_VERSION@ +version_info = @LIBTOOL_VERSION_INFO@ +srcdir = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +mandir = @mandir@ +datarootdir = @datarootdir@ +datadir = @datadir@ +libdir = @libdir@ +includedir = @includedir@ +doxygen = @doxygen@ +pywrapdir = ${srcdir}/contrib/python +pyldnsxwrapdir = ${srcdir}/contrib/ldnsx +swig = @swig@ +swigpy_flags = -python @SWIGPY3@ +python_site = @PYTHON_SITE_PKG@ +pyldns_inst = @PYLDNSINST@ +pyldns_uninst = @PYLDNSUNINST@ +pyldnsx_inst = @PYLDNSXINST@ +pyldnsx_uninst = @PYLDNSXUNINST@ +libtool = @libtool@ + +# override $U variable which is used by autotools for deansification (for +# K&R C compilers), but causes problems if $U is defined in the env). +U= + +CC = @CC@ +CFLAGS = @CFLAGS@ +CPPFLAGS = -I. -I$(srcdir) @CPPFLAGS@ @DEFS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +LIBOBJDIR = compat/ +LIBOBJS = @LIBOBJS@ +PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@ +PYTHON_LDFLAGS = @PYTHON_LDFLAGS@ +PYTHON_X_CFLAGS = @PYTHON_X_CFLAGS@ +LIBSSL_CPPFLAGS = @LIBSSL_CPPFLAGS@ +LIBSSL_LDFLAGS = @LIBSSL_LDFLAGS@ +LIBSSL_LIBS = @LIBSSL_LIBS@ +LIBPCAP_LIBS = @LIBPCAP_LIBS@ +RUNTIME_PATH = @RUNTIME_PATH@ +LIBTOOL = $(libtool) --tag=CC --quiet +LINT = splint +LINTFLAGS = +quiet -weak -warnposix -unrecog -Din_addr_t=uint32_t -Du_int=unsigned -Du_char=uint8_t -preproc -Drlimit=rlimit64 -D__gnuc_va_list=va_list +# Extra flags from configure +LINTFLAGS += @LINTFLAGS@ +LINTFLAGS += "-DBN_ULONG=unsigned long" -Dkrb5_int32=int "-Dkrb5_ui_4=unsigned int" -DPQ_64BIT=uint64_t -DRC4_INT=unsigned -fixedformalarray -D"ENGINE=unsigned" -D"RSA=unsigned" -D"DSA=unsigned" -D"EVP_PKEY=unsigned" -D"EVP_MD=unsigned" -D"SSL=unsigned" -D"SSL_CTX=unsigned" -D"X509=unsigned" -D"RC4_KEY=unsigned" -D"EVP_MD_CTX=unsigned" -D"EC_KEY=unsigned" -D"EC_POINT=unsigned" -D"EC_GROUP=unsigned" -D"EVP_PKEY_ASN1_METHOD=struct evp_pkey_asn1_method_st" -D"EVP_PKEY_CTX=struct evp_pkey_ctx_st" +# compat with OpenBSD +LINTFLAGS += "-Dsigset_t=long" +# FreeBSD8 +LINTFLAGS += "-D__uint16_t=uint16_t" -D"__pure2=" -D"__wchar_t=wchar_t" -D"__packed=" -D"__aligned(x)=" +# Ubuntu oneiric" +LINTFLAGS += -D"__BEGIN_DECLS=" -D"__ssize_t=ssize_t" -D"__intptr_t=intptr_t" -D"__nonnull(x)=" -D"__THROW=" -D"__wur=" -D"__off_t=unsigned" -D"__off64_t=unsigned" -D"__useconds_t=unsigned" -D"__uid_t=unsigned" -D"__gid_t=unsigned" -D"__attribute_deprecated__=" -D"__pid_t=unsigned" -D"__restrict=" -D"__END_DECLS=" -D"__BEGIN_NAMESPACE_STD=" -D"__END_NAMESPACE_STD=" -D"__BEGIN_NAMESPACE_C99=" -D"__END_NAMESPACE_C99=" -D"__socklen_t=unsigned" -D"sa_family_t=unsigned " -D"__mode_t=unsigned" -D"u_int16_t=uint16_t" -D"u_int32_t=uint32_t" -D"u_int8_t=uint8_t" -D"u_short=unsigned short" -D"__u16=uint16_t" -D"__u32=uint32_t" -D"__u64=uint64_t" +DEPFLAG = @DEPFLAG@ + +INSTALL = $(srcdir)/install-sh + +LIBLOBJS = $(LIBOBJS:.o=.lo) +LDNS_LOBJS = buffer.lo dname.lo dnssec.lo dnssec_sign.lo dnssec_verify.lo dnssec_zone.lo duration.lo error.lo higher.lo host2str.lo host2wire.lo keys.lo net.lo packet.lo parse.lo rbtree.lo rdata.lo resolver.lo rr.lo rr_functions.lo sha1.lo sha2.lo str2host.lo tsig.lo update.lo util.lo wire2host.lo zone.lo +LDNS_LOBJS_EX = ^linktest\.c$$ +LDNS_ALL_LOBJS = $(LDNS_LOBJS) $(LIBLOBJS) +LIB = libldns.la + +LDNS_HEADERS = buffer.h dname.h dnssec.h dnssec_sign.h dnssec_verify.h dnssec_zone.h duration.h error.h higher.h host2str.h host2wire.h keys.h ldns.h packet.h parse.h rbtree.h rdata.h resolver.h rr_functions.h rr.h sha1.h sha2.h str2host.h tsig.h update.h wire2host.h zone.h +LDNS_HEADERS_EX = ^config\.h|common\.h|util\.h|net\.h$$ +LDNS_HEADERS_GEN= common.h util.h net.h + +PYLDNS_I_FILES = $(pywrapdir)/file_py3.i $(pywrapdir)/ldns_buffer.i $(pywrapdir)/ldns_dname.i $(pywrapdir)/ldns_dnssec.i $(pywrapdir)/ldns.i $(pywrapdir)/ldns_key.i $(pywrapdir)/ldns_packet.i $(pywrapdir)/ldns_rdf.i $(pywrapdir)/ldns_resolver.i $(pywrapdir)/ldns_rr.i $(pywrapdir)/ldns_zone.i + +DRILL_LOBJS = drill/chasetrace.lo drill/dnssec.lo drill/drill.lo drill/drill_util.lo drill/error.lo drill/root.lo drill/securetrace.lo drill/work.lo + +EXAMPLE_LOBJS = examples/ldns-chaos.lo examples/ldns-compare-zones.lo examples/ldnsd.lo examples/ldns-dpa.lo examples/ldns-gen-zone.lo examples/ldns-key2ds.lo examples/ldns-keyfetcher.lo examples/ldns-keygen.lo examples/ldns-mx.lo examples/ldns-notify.lo examples/ldns-nsec3-hash.lo examples/ldns-read-zone.lo examples/ldns-resolver.lo examples/ldns-revoke.lo examples/ldns-rrsig.lo examples/ldns-signzone.lo examples/ldns-test-edns.lo examples/ldns-testns.lo examples/ldns-testpkts.lo examples/ldns-update.lo examples/ldns-verify-zone.lo examples/ldns-version.lo examples/ldns-walk.lo examples/ldns-zcat.lo examples/ldns-zsplit.lo +EXAMPLE_PROGS = examples/ldns-chaos examples/ldns-compare-zones examples/ldnsd examples/ldns-gen-zone examples/ldns-key2ds examples/ldns-keyfetcher examples/ldns-keygen examples/ldns-mx examples/ldns-notify examples/ldns-read-zone examples/ldns-resolver examples/ldns-rrsig examples/ldns-test-edns examples/ldns-update examples/ldns-version examples/ldns-walk examples/ldns-zcat examples/ldns-zsplit +EX_PROGS_BASENM = ldns-chaos ldns-compare-zones ldnsd ldns-dpa ldns-gen-zone ldns-key2ds ldns-keyfetcher ldns-keygen ldns-mx ldns-notify ldns-nsec3-hash ldns-read-zone ldns-resolver ldns-revoke ldns-rrsig ldns-signzone ldns-test-edns ldns-testns ldns-testpkts ldns-update ldns-verify-zone ldns-version ldns-walk ldns-zcat ldns-zsplit +EXAMPLE_PROGS_EX= ^examples/ldns-testpkts\.c|examples/ldns-testns\.c|examples/ldns-dpa\.c|examples/ldns-nsec3-hash\.c|examples/ldns-revoke\.c|examples/ldns-signzone\.c|examples/ldns-verify-zone\.c$$ +TESTNS = examples/ldns-testns +TESTNS_LOBJS = examples/ldns-testns.lo examples/ldns-testpkts.lo +LDNS_DPA = examples/ldns-dpa +LDNS_DPA_LOBJS = examples/ldns-dpa.lo +EX_SSL_PROGS = examples/ldns-nsec3-hash examples/ldns-revoke examples/ldns-signzone examples/ldns-verify-zone +EX_SSL_LOBJS = examples/ldns-nsec3-hash.lo examples/ldns-revoke.lo examples/ldns-signzone.lo examples/ldns-verify-zone.lo + + +COMPILE = $(CC) $(CPPFLAGS) $(CFLAGS) +COMP_LIB = $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(CFLAGS) +LINK = $(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) +LINK_LIB = $(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(LDFLAGS) \ + $(LIBS) -version-number $(version_info) -no-undefined +LINK_EXE = $(LIBTOOL) --mode=link $(CC) $(CPPFLAGS) \ + $(LIBSSL_CPPFLAGS) $(CFLAGS) $(LDFLAGS) + +.PHONY: clean realclean docclean manpages doc lint all lib pyldns test +.PHONY: install uninstall install-doc uninstall-doc uninstall-pyldns +.PHONY: install-h uninstall-h install-lib uninstall-lib install-pyldns + +all: setup-builddir lib linktest manpages @PYLDNS@ @DRILL@ @EXAMPLES@ + +.SUFFIXES: .c .o .a .lo .h .i + +.c.lo: + $(COMP_LIB) $(LIBSSL_CPPFLAGS) -c $< -o $@ + +$(LDNS_LOBJS) $(LIBLOBJS) $(DRILL_LOBJS) $(EXAMPLE_LOBJS): + $(COMP_LIB) $(LIBSSL_CPPFLAGS) -c $(srcdir)/$(@:.lo=.c) -o $@ + +setup-builddir: + @if test ! -d compat ; then mkdir compat ; fi + @if test ! -d drill ; then mkdir drill ; fi + @if test ! -d examples ; then mkdir examples ; fi + @if test ! -h config.h ; then ln -s ldns/config.h . ; fi + @if test ! -h lib ; then ln -s .libs lib ; fi ; + @if test ! -d include ; then $(INSTALL) -d include; fi + @if test ! -h include/ldns ; then ln -s ../ldns include/ldns || echo "include/ldns exists"; fi + +putdown-builddir: + rm -f include/ldns lib config.h + test ! -d include || rmdir include || : + if test -d examples -a ! -f examples/README; then rmdir examples || : ; fi + if test -d drill -a ! -f drill/README ; then rmdir drill || : ; fi + if test -d compat -a ! -f compat/malloc.c; then rmdir compat || : ; fi + +drill: no-drill-config-h drill/drill +no-drill-config-h: + @if test -e $(srcdir)/drill/config.h -o -e drill/config.h ; \ + then echo "A config.h was detected in the drill subdirectory." ; \ + echo "This does not work when building drill from here." ; \ + echo "Either remove the config.h from the subdirectory" ; \ + echo "or build drill there." ; \ + exit -1 ; \ + fi +drill/drill: $(DRILL_LOBJS) $(LIB) + $(LINK_EXE) $(DRILL_LOBJS) $(LIBS) $(LIBSSL_LIBS) -lldns -o drill/drill + +install-drill: drill/drill + $(INSTALL) -m 755 -d $(DESTDIR)$(bindir) + $(INSTALL) -m 755 -d $(DESTDIR)$(mandir) + $(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man1 + $(LIBTOOL) --mode=install cp drill/drill $(DESTDIR)$(bindir) + $(INSTALL) -m 644 $(srcdir)/drill/drill.1 $(DESTDIR)$(mandir)/man1/drill.1 + +uninstall-drill: + rm -f $(DESTDIR)$(bindir)/drill $(DESTDIR)$(mandir)/man1/drill.1 + test ! -d $(DESTDIR)$(mandir) || rmdir -p $(DESTDIR)$(mandir)/man1 || :; + test ! -d $(DESTDIR)$(bindir) || rmdir -p $(DESTDIR)$(bindir) || : ; + +clean-drill: + $(LIBTOOL) --mode clean rm -f $(DRILL_LOBJS) drill/drill + +examples: no-examples-config-h $(EXAMPLE_PROGS) $(TESTNS) $(LDNS_DPA) $(EX_SSL_PROGS) +no-examples-config-h: + @if test -e $(srcdir)/examples/config.h -o -e examples/config.h ; \ + then echo "A config.h was detected in the examples subdirectory." ; \ + echo "This does not work when building examples from here." ; \ + echo "Either remove the config.h from the subdirectory" ; \ + echo "or build examples there." ; \ + exit -1 ; \ + fi +$(EXAMPLE_PROGS): + $(LINK_EXE) $@.lo $(LIBS) -lldns -o $@ + +$(TESTNS): + $(LINK_EXE) $(TESTNS_LOBJS) $(LIBS) -lldns -o $(TESTNS) + +$(LDNS_DPA): + $(LINK_EXE) $(LDNS_DPA_LOBJS) $(LIBS) $(LIBPCAP_LIBS) -lldns \ + -o $(LDNS_DPA) + +$(EX_SSL_PROGS): + $(LINK_EXE) $@.lo $(LIBS) $(LIBSSL_LIBS) -lldns -o $@ + +install-examples: $(EXAMPLE_PROGS) $(TESTNS) $(LDNS_DPA) $(EX_SSL_PROGS) + $(INSTALL) -m 755 -d $(DESTDIR)$(bindir) + $(INSTALL) -m 755 -d $(DESTDIR)$(mandir) + $(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man1 + for p in $(EXAMPLE_PROGS) $(TESTNS) $(LDNS_DPA) $(EX_SSL_PROGS) ; do \ + $(LIBTOOL) --mode=install cp $$p $(DESTDIR)$(bindir) ; \ + $(INSTALL) -m 644 $(srcdir)/$$p.1 $(DESTDIR)$(mandir)/man1 ; \ + done + +uninstall-examples: + for p in $(EX_PROGS_BASENM) ; do \ + rm -f $(DESTDIR)$(bindir)/$$p $(DESTDIR)$(mandir)/man1/$$p.1 ;\ + done + test ! -d $(DESTDIR)$(mandir) || rmdir -p $(DESTDIR)$(mandir)/man1 || :; + test ! -d $(DESTDIR)$(bindir) || rmdir -p $(DESTDIR)$(bindir) || : ; + +clean-examples: + $(LIBTOOL) --mode clean rm -f $(EXAMPLE_PROGS) + $(LIBTOOL) --mode clean rm -f $(TESTNS) $(LDNS_DPA) $(EX_SSL_PROGS) + $(LIBTOOL) --mode clean rm -f $(EXAMPLE_LOBJS) + +linktest: $(srcdir)/linktest.c libldns.la + $(LIBTOOL) --mode=link $(CC) $(srcdir)/linktest.c $(CPPFLAGS) $(LIBSSL_CPPFLAGS) $(CFLAGS) -lldns $(LIBS) -o linktest + +lib: libldns.la + +lib-export-all: libldns.la-export-all + +libldns.la: $(LDNS_ALL_LOBJS) + $(LINK_LIB) $(LIBSSL_LDFLAGS) $(LIBSSL_LIBS) --export-symbols $(srcdir)/ldns_symbols.def -o libldns.la $(LDNS_ALL_LOBJS) -rpath $(libdir) $(RUNTIME_PATH) + +libldns.la-export-all: $(LDNS_ALL_LOBJS) + $(LINK_LIB) -o libldns.la $(LDNS_ALL_LOBJS) -rpath $(libdir) $(RUNTIME_PATH) + +mancheck: + sh -c 'find . -name \*.\[13\] -exec troff -z {} \;' 2>&1 | sed "s/^\.\///" | sed "s/\(:[0\-9]\+:\)/\1 warning:/g" + +doxygen: manpages + if test ! -e doc/header.html ; then \ + $(INSTALL) -c -m 644 $(srcdir)/doc/header.html doc/ ; \ + fi ; + $(doxygen) $(srcdir)/libdns.doxygen + +doc: manpages $(doxygen) + @$(INSTALL) -d doc + +manpages: $(srcdir)/doc/function_manpages + @$(INSTALL) -d doc + @cat $(srcdir)/ldns/*.h \ + | $(srcdir)/doc/doxyparse.pl \ + -m $(srcdir)/doc/function_manpages 2>&1 \ + | grep -v ^doxygen | grep -v ^cat > doc/ldns_manpages + +pyldns: _ldns.la + +$(pywrapdir)/ldns_wrapper.c: $(PYLDNS_I_FILES) ldns/config.h + $(swig) $(swigpy_flags) -o $@ $(CPPFLAGS) $(PYTHON_CPPFLAGS) $(pywrapdir)/ldns.i + +ldns_wrapper.lo: $(pywrapdir)/ldns_wrapper.c ldns/config.h + $(COMP_LIB) -I./include/ldns $(PYTHON_CPPFLAGS) $(PYTHON_X_CFLAGS) -c $< -o $@ + +_ldns.la: ldns_wrapper.lo libldns.la + $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(PYTHON_CFLAGS) $(LDFLAGS) $(PYTHON_LDFLAGS) -module -version-number $(version_info) -no-undefined -o $@ $< -rpath $(python_site) -L. -L.libs -lldns $(LIBS) + +install: install-h install-lib @INSTALL_CONFIG@ install-manpages $(pyldns_inst) $(pyldnsx_inst) @INSTALL_DRILL@ @INSTALL_EXAMPLES@ + +uninstall: uninstall-manpages @UNINSTALL_CONFIG@ uninstall-h uninstall-lib $(pyldns_uninst) $(pyldnsx_uninst) @UNINSTALL_DRILL@ @UNINSTALL_EXAMPLES@ + +destclean: uninstall + +install-config: + $(INSTALL) -d $(DESTDIR)$(bindir) + $(INSTALL) -c -m 755 packaging/ldns-config $(DESTDIR)$(bindir) + +uninstall-config: + rm -f $(DESTDIR)$(bindir)/ldns-config + test ! -d $(DESTDIR)$(bindir) || rmdir -p $(DESTDIR)$(bindir) || echo "ok, dir already gone" + +install-config-manpage: + ${INSTALL} -d $(DESTDIR)$(mandir)/man1 + ${INSTALL} -c -m 444 $(srcdir)/packaging/ldns-config.1 $(DESTDIR)$(mandir)/man1/ + + +uninstall-config-manpage: + rm -f $(DESTDIR)$(mandir)/man1/ldns-config.1 + test ! -d $(DESTDIR)$(mandir)/man1 || rmdir -p $(DESTDIR)$(mandir)/man1 || echo "ok, dir already gone" + +install-manpages: manpages @INSTALL_CONFIG_MANPAGE@ + ${INSTALL} -d $(DESTDIR)$(mandir)/man3 + for f in doc/man/man3/*; do \ + ${INSTALL} -c -m 444 $$f $(DESTDIR)$(mandir)/man3/; \ + done + +uninstall-manpages: @UNINSTALL_CONFIG_MANPAGE@ + for m in `cat $(srcdir)/ldns/*.h | perl $(srcdir)/doc/doxyparse.pl -m $(srcdir)/doc/function_manpages 2>&1 | grep -v ^doxygen | grep -v ^cat` ; do \ + rm -f $(DESTDIR)$(mandir)/man3/$$m.3 ; done + test ! -d $(DESTDIR)$(mandir)/man3 || rmdir -p $(DESTDIR)$(mandir)/man3 || echo "ok, dir already gone" + +install-h: lib + $(INSTALL) -m 755 -d $(DESTDIR)$(includedir)/ldns + for i in $(LDNS_HEADERS); do \ + $(INSTALL) -c -m 644 $(srcdir)/ldns/$$i $(DESTDIR)$(includedir)/ldns/; done + for i in $(LDNS_HEADERS_GEN); do \ + $(INSTALL) -c -m 644 ldns/$$i $(DESTDIR)$(includedir)/ldns/; done + +uninstall-h: + for i in $(LDNS_HEADERS) $(LDNS_HEADERS_GEN); do \ + rm -f $(DESTDIR)$(includedir)/ldns/$$i; done + test ! -d $(DESTDIR)$(includedir)/ldns || rmdir -p $(DESTDIR)$(includedir)/ldns || echo "ok, dir already gone" + exit 0 + +install-lib: lib + $(INSTALL) -m 755 -d $(DESTDIR)$(libdir) + $(LIBTOOL) --mode=install cp libldns.la $(DESTDIR)$(libdir) + $(LIBTOOL) --mode=finish $(DESTDIR)$(libdir) + +uninstall-lib: + $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/libldns.la + test ! -d $(DESTDIR)$(libdir) || rmdir -p $(DESTDIR)$(libdir) || echo "ok, dir already gone" + +install-pyldns: @PYLDNS@ + $(INSTALL) -m 755 -d $(DESTDIR)$(python_site)/ldns + $(INSTALL) -c -m 644 $(pywrapdir)/ldns.py $(DESTDIR)$(python_site)/ldns.py + $(LIBTOOL) --mode=install cp _ldns.la $(DESTDIR)$(python_site) + $(LIBTOOL) --mode=finish $(DESTDIR)$(python_site) + +uninstall-pyldns: + rm -f $(DESTDIR)$(python_site)/ldns/* + test ! -d $(DESTDIR)$(python_site)/ldns || rmdir $(DESTDIR)$(python_site)/ldns || echo "ok, dir already gone" + +install-pyldnsx: + $(INSTALL) -c -m 644 $(pyldnsxwrapdir)/ldnsx.py $(DESTDIR)$(python_site)/ldnsx.py + +uninstall-pyldnsx: + rm -f $(DESTDIR)$(python_site)/ldnsx.py + +clean-manpages: + for m in `cat $(srcdir)/ldns/*.h | $(srcdir)/doc/doxyparse.pl -m $(srcdir)/doc/function_manpages 2>&1 | grep -v ^doxygen | grep -v ^cat` ; do\ + rm -f doc/man/man3/$${m}.3 ; done + rm -f doc/ldns_manpages + test ! -d doc/man/man3 || rmdir -p doc/man/man3 || : + +clean-lib: + $(LIBTOOL) --mode clean rm -f $(LDNS_LOBJS) $(LIBLOBJS) + $(LIBTOOL) --mode clean rm -f linktest libldns.la + $(LIBTOOL) --mode clean rm -f $(pywrapdir)/ldns_wrapper.c + $(LIBTOOL) --mode clean rm -f $(pywrapdir)/ldns.py + +clean: @CLEAN_DRILL@ @CLEAN_EXAMPLES@ clean-manpages clean-lib putdown-builddir + +realclean: clean docclean + rm -f config.status + rm -f config.log + rm -f Makefile + rm -f ldns/config.h + rm -f ldns/util.h + rm -f ldns/common.h + rm -f ldns/net.h + rm -f packaging/ldns-config + rm -f packaging/libldns.pc + if test -d packaging -a ! -f packaging/ldns-config.in ; then \ + rmdir packaging || : ; fi + rm -f libtool + if test -d ldns ; then \ + echo "is builddir srcdir" > ldns/YES ; \ + if test -f $(srcdir)/ldns/YES ; then \ + echo Leaving headers files because srcdir == builddir;\ + rm -f ldns/YES; \ + else \ + echo Removing header files in builddir;\ + for f in `(cd $(srcdir); echo ldns/*.h)`; do \ + rm -f $$f ; done ; \ + rm -f ldns/YES; \ + test ! -d ldns || rmdir ldns || : ; \ + fi ;\ + fi + +docclean: + rm -rf doc/html/ + rm -rf doc/man/ + rm -rf doc/latex/ + rm -f doc/*.txt + rm -f doc/*.tex + rm -f doc/ldns_manpages + +distclean: realclean + rm -fr autom4te.cache + rm -f config.guess config.sub configure ltmain.sh ldns/config.h.in + +## No need for changes here + +lint: @LINT_DRILL@ @LINT_EXAMPLES@ + for i in $(srcdir)/*.c; do \ + $(LINT) $(LINTFLAGS) -I. -I$(srcdir) $(srcdir)/$$i ; \ + if test $$? -ne 0 ; then exit 1 ; fi ; \ + done + +lint-drill: + for i in $(srcdir)/drill/*.c; do \ + $(LINT) $(LINTFLAGS) -I. -I$(srcdir) $(srcdir)/$$i ; \ + if test $$? -ne 0 ; then exit 1 ; fi ; \ + done + +lint-examples: + for i in $(srcdir)/examples/*.c; do \ + $(LINT) $(LINTFLAGS) -I. -I$(srcdir) $(srcdir)/$$i ; \ + if test $$? -ne 0 ; then exit 1 ; fi ; \ + done + +tags: $(srcdir)/*.c ldns/*.[ch] + ctags -f $(srcdir)/tags $(srcdir)/*.[ch] ldns/*.[ch] + +allclean: test-clean clean + +test-clean: + tpkg -b test clean + +test: + if test -x "`which bash`"; then bash test/test_all.sh; else sh test/test_all.sh; fi + + +# Recreate symbols file, only needed when API changes +# make clean first (and after this make clean; make again) +symbols: lib-export-all + nm -g lib/libldns.so | cut -d " " -f 3 | grep ldns | sort > $(srcdir)/ldns_symbols.def + +TMP_FILE=temporary.tmp +sources: + for mf in $(srcdir)/Makefile.in Makefile ; do \ + if test -e $$mf ; then \ + cp $$mf $$mf.bak ;\ + sed -e 's/^LDNS_LOBJS[ ]*=.*$$/LDNS_LOBJS = '"`(cd $(srcdir); ls -1 *.c | egrep -v '$(LDNS_LOBJS_EX)' | sed 's/\.c/\.lo/g' | tr '\n' ' ')`"'/g' \ + -e 's/^LDNS_HEADERS[ ]*=.*$$/LDNS_HEADERS = '"`(cd $(srcdir)/ldns; ls -1 *.h | egrep -v '$(LDNS_HEADERS_EX)' | tr '\n' ' ')`"'/g' \ + -e 's?^PYLDNS_I_FILES[ ]*=.*$$?PYLDNS_I_FILES = '"`(cd $(srcdir)/contrib; echo python/*.i | sed 's/python/\$$(pywrapdir)/g')`"'?g' \ + -e 's?^DRILL_LOBJS[ ]*=.*$$?DRILL_LOBJS = '"`(cd $(srcdir); echo drill/*.c | sed 's/\.c/\.lo/g')`"'?g' \ + -e 's?^EXAMPLE_LOBJS[ ]*=.*$$?EXAMPLE_LOBJS = '"`(cd $(srcdir); echo examples/*.c | sed 's/\.c/\.lo/g')`"'?g' \ + -e 's?^EXAMPLE_PROGS[ ]*=.*$$?EXAMPLE_PROGS = '"`(cd $(srcdir); ls -1 examples/*.c | egrep -v '$(EXAMPLE_PROGS_EX)' | sed 's/\.c//g' | tr '\n' ' ')`"'?g' \ + -e 's?^EX_PROGS_BASENM[ ]*=.*$$?EX_PROGS_BASENM = '"`(cd $(srcdir); ls -1 examples/*.c | sed -e 's/\.c//g' -e 's?examples/??g' | tr '\n' ' ')`"'?g' \ + $$mf > $(TMP_FILE) ;\ + mv $(TMP_FILE) $$mf ;\ + fi;\ + done + + +# dependency generation +DEPEND_TMP=depend1073.tmp +DEPEND_TMP2=depend1074.tmp +DEPEND_TARGET=Makefile +DEPEND_TARGET2=$(srcdir)/Makefile.in +# actions: generate deplines from gcc, +# then, filter out home/xx, /usr/xx and /opt/xx lines (some cc already do this) +# then, remove empty " \" lines +# then, add srcdir before .c and .h in deps. +# then, remove srcdir from the (generated) parser and lexer. +# and mention the .lo +depend: + if test ! -e config.h ; then ln -s ldns/config.h . ; fi + echo "" > $(DEPEND_TMP) + for builddir in `pwd` ; do \ + for subdir in . compat examples drill; do \ + (cd $(srcdir) ; $(CC) $(DEPFLAG) $(CPPFLAGS) $(CFLAGS) -I$$builddir -I$$subdir $$subdir/*.c) | \ + sed -e 's!'$$HOME'[^ ]* !!g' -e 's!'$$HOME'[^ ]*$$!!g' \ + -e 's!/usr[^ ]* !!g' -e 's!/usr[^ ]*$$!!g' \ + -e 's!/opt[^ ]* !!g' -e 's!/opt[^ ]*$$!!g' | \ + sed -e '/^ \\$$/d' | \ + sed -e 's? *\([^ ]*\.[ch]\)? $$(srcdir)/\1?g' | \ + sed -e 's? *\([^ ]*\.inc\)? $$(srcdir)/\1?g' | \ + sed -e 's?$$(srcdir)/ldns/config.h?ldns/config.h?g' \ + -e 's?$$(srcdir)/config.h?ldns/config.h?g' \ + -e 's?$$(srcdir)/ldns/common.h?ldns/common.h?g' \ + -e 's?$$(srcdir)/ldns/util.h?ldns/util.h?g' \ + -e 's?$$(srcdir)/ldns/net.h?ldns/net.h?g' \ + -e 's!\(.*\)\.o[ :]*!'"$$subdir/"'\1.lo '"$$subdir/"'\1.o: !g' \ + -e 's?^\.\/??g' -e 's? \.\/? ?g' \ + >> $(DEPEND_TMP) ;\ + done; \ + done + for p in $(EXAMPLE_PROGS) $(LDNS_DPA) $(EX_SSL_PROGS); do \ + echo "$$p: $$p.lo $$p.o \$$(LIB)" >> $(DEPEND_TMP) ; done + echo "$(TESTNS): `for o in $(TESTNS_LOBJS) ; do \ + echo -n "$$o $${o%lo}o " ; done` \$$(LIB)" \ + >> $(DEPEND_TMP) + cp $(DEPEND_TARGET) $(DEPEND_TMP2) + head -`egrep -n "# Dependencies" $(DEPEND_TARGET) | tail -1 | sed -e 's/:.*$$//'` $(DEPEND_TMP2) > $(DEPEND_TARGET) + cat $(DEPEND_TMP) >> $(DEPEND_TARGET) + @if diff $(DEPEND_TARGET) $(DEPEND_TMP2); then echo " $(DEPEND_TARGET) unchanged"; else echo " Updated $(DEPEND_TARGET))"; fi + @if test -f $(DEPEND_TARGET2); then \ + cp $(DEPEND_TARGET2) $(DEPEND_TMP2); \ + head -`egrep -n "# Dependencies" $(DEPEND_TARGET2) | tail -1 | sed -e 's/:.*$$//'` $(DEPEND_TMP2) > $(DEPEND_TARGET2); \ + cat $(DEPEND_TMP) >> $(DEPEND_TARGET2); \ + if diff $(DEPEND_TARGET2) $(DEPEND_TMP2); then echo " $(DEPEND_TARGET2) unchanged"; else echo " Updated $(DEPEND_TARGET2))"; fi; \ + fi + rm -f $(DEPEND_TMP) $(DEPEND_TMP2) + +# Dependencies + +buffer.lo buffer.o: $(srcdir)/buffer.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +dname.lo dname.o: $(srcdir)/dname.c $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +dnssec.lo dnssec.o: $(srcdir)/dnssec.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +dnssec_sign.lo dnssec_sign.o: $(srcdir)/dnssec_sign.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +dnssec_verify.lo dnssec_verify.o: $(srcdir)/dnssec_verify.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +dnssec_zone.lo dnssec_zone.o: $(srcdir)/dnssec_zone.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +duration.lo duration.o: $(srcdir)/duration.c \ + $(srcdir)/ldns/duration.h +error.lo error.o: $(srcdir)/error.c $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +higher.lo higher.o: $(srcdir)/higher.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +host2str.lo host2str.o: $(srcdir)/host2str.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +host2wire.lo host2wire.o: $(srcdir)/host2wire.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +keys.lo keys.o: $(srcdir)/keys.c $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +linktest.lo linktest.o: $(srcdir)/linktest.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +net.lo net.o: $(srcdir)/net.c $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +packet.lo packet.o: $(srcdir)/packet.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +parse.lo parse.o: $(srcdir)/parse.c $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +rbtree.lo rbtree.o: $(srcdir)/rbtree.c \ + $(srcdir)/ldns/rbtree.h \ + +rdata.lo rdata.o: $(srcdir)/rdata.c $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +resolver.lo resolver.o: $(srcdir)/resolver.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +rr.lo rr.o: $(srcdir)/rr.c $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +rr_functions.lo rr_functions.o: $(srcdir)/rr_functions.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +sha1.lo sha1.o: $(srcdir)/sha1.c $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +sha2.lo sha2.o: $(srcdir)/sha2.c $(srcdir)/ldns/sha2.h +str2host.lo str2host.o: $(srcdir)/str2host.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +tsig.lo tsig.o: $(srcdir)/tsig.c $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +update.lo update.o: $(srcdir)/update.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +util.lo util.o: $(srcdir)/util.c $(srcdir)/ldns/rdata.h \ + $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/rr.h $(srcdir)/ldns/buffer.h +wire2host.lo wire2host.o: $(srcdir)/wire2host.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +zone.lo zone.o: $(srcdir)/zone.c $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +compat/b32_ntop.lo compat/b32_ntop.o: $(srcdir)/compat/b32_ntop.c +compat/b32_pton.lo compat/b32_pton.o: $(srcdir)/compat/b32_pton.c +compat/b64_ntop.lo compat/b64_ntop.o: $(srcdir)/compat/b64_ntop.c +compat/b64_pton.lo compat/b64_pton.o: $(srcdir)/compat/b64_pton.c +compat/calloc.lo compat/calloc.o: $(srcdir)/compat/calloc.c +compat/ctime_r.lo compat/ctime_r.o: $(srcdir)/compat/ctime_r.c +compat/fake-rfc2553.lo compat/fake-rfc2553.o: $(srcdir)/compat/fake-rfc2553.c \ + $(srcdir)/compat/fake-rfc2553.h +compat/gmtime_r.lo compat/gmtime_r.o: $(srcdir)/compat/gmtime_r.c +compat/inet_aton.lo compat/inet_aton.o: $(srcdir)/compat/inet_aton.c \ + +compat/inet_ntop.lo compat/inet_ntop.o: $(srcdir)/compat/inet_ntop.c \ + +compat/inet_pton.lo compat/inet_pton.o: $(srcdir)/compat/inet_pton.c \ + +compat/isascii.lo compat/isascii.o: $(srcdir)/compat/isascii.c +compat/isblank.lo compat/isblank.o: $(srcdir)/compat/isblank.c +compat/localtime_r.lo compat/localtime_r.o: $(srcdir)/compat/localtime_r.c \ + +compat/malloc.lo compat/malloc.o: $(srcdir)/compat/malloc.c +compat/memmove.lo compat/memmove.o: $(srcdir)/compat/memmove.c +compat/realloc.lo compat/realloc.o: $(srcdir)/compat/realloc.c +compat/snprintf.lo compat/snprintf.o: $(srcdir)/compat/snprintf.c +compat/strlcpy.lo compat/strlcpy.o: $(srcdir)/compat/strlcpy.c +compat/timegm.lo compat/timegm.o: $(srcdir)/compat/timegm.c +examples/ldns-chaos.lo examples/ldns-chaos.o: $(srcdir)/examples/ldns-chaos.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +examples/ldns-compare-zones.lo examples/ldns-compare-zones.o: $(srcdir)/examples/ldns-compare-zones.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +examples/ldnsd.lo examples/ldnsd.o: $(srcdir)/examples/ldnsd.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +examples/ldns-dpa.lo examples/ldns-dpa.o: $(srcdir)/examples/ldns-dpa.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h $(srcdir)/examples/ldns-dpa.h +examples/ldns-gen-zone.lo examples/ldns-gen-zone.o: $(srcdir)/examples/ldns-gen-zone.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +examples/ldns-key2ds.lo examples/ldns-key2ds.o: $(srcdir)/examples/ldns-key2ds.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +examples/ldns-keyfetcher.lo examples/ldns-keyfetcher.o: $(srcdir)/examples/ldns-keyfetcher.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +examples/ldns-keygen.lo examples/ldns-keygen.o: $(srcdir)/examples/ldns-keygen.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +examples/ldns-mx.lo examples/ldns-mx.o: $(srcdir)/examples/ldns-mx.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +examples/ldns-notify.lo examples/ldns-notify.o: $(srcdir)/examples/ldns-notify.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +examples/ldns-nsec3-hash.lo examples/ldns-nsec3-hash.o: $(srcdir)/examples/ldns-nsec3-hash.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +examples/ldns-read-zone.lo examples/ldns-read-zone.o: $(srcdir)/examples/ldns-read-zone.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +examples/ldns-resolver.lo examples/ldns-resolver.o: $(srcdir)/examples/ldns-resolver.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +examples/ldns-revoke.lo examples/ldns-revoke.o: $(srcdir)/examples/ldns-revoke.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +examples/ldns-rrsig.lo examples/ldns-rrsig.o: $(srcdir)/examples/ldns-rrsig.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +examples/ldns-signzone.lo examples/ldns-signzone.o: $(srcdir)/examples/ldns-signzone.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +examples/ldns-test-edns.lo examples/ldns-test-edns.o: $(srcdir)/examples/ldns-test-edns.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +examples/ldns-testns.lo examples/ldns-testns.o: $(srcdir)/examples/ldns-testns.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h $(srcdir)/examples/ldns-testpkts.h +examples/ldns-testpkts.lo examples/ldns-testpkts.o: $(srcdir)/examples/ldns-testpkts.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h $(srcdir)/examples/ldns-testpkts.h +examples/ldns-update.lo examples/ldns-update.o: $(srcdir)/examples/ldns-update.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +examples/ldns-verify-zone.lo examples/ldns-verify-zone.o: $(srcdir)/examples/ldns-verify-zone.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +examples/ldns-version.lo examples/ldns-version.o: $(srcdir)/examples/ldns-version.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +examples/ldns-walk.lo examples/ldns-walk.o: $(srcdir)/examples/ldns-walk.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +examples/ldns-zcat.lo examples/ldns-zcat.o: $(srcdir)/examples/ldns-zcat.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +examples/ldns-zsplit.lo examples/ldns-zsplit.o: $(srcdir)/examples/ldns-zsplit.c \ + $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +drill/chasetrace.lo drill/chasetrace.o: $(srcdir)/drill/chasetrace.c $(srcdir)/drill/drill.h \ + $(srcdir)/drill/drill_util.h $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +drill/dnssec.lo drill/dnssec.o: $(srcdir)/drill/dnssec.c $(srcdir)/drill/drill.h \ + $(srcdir)/drill/drill_util.h $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +drill/drill.lo drill/drill.o: $(srcdir)/drill/drill.c $(srcdir)/drill/drill.h \ + $(srcdir)/drill/drill_util.h $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +drill/drill_util.lo drill/drill_util.o: $(srcdir)/drill/drill_util.c $(srcdir)/drill/drill.h \ + $(srcdir)/drill/drill_util.h $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +drill/error.lo drill/error.o: $(srcdir)/drill/error.c $(srcdir)/drill/drill.h \ + $(srcdir)/drill/drill_util.h $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +drill/root.lo drill/root.o: $(srcdir)/drill/root.c $(srcdir)/drill/drill.h \ + $(srcdir)/drill/drill_util.h $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +drill/securetrace.lo drill/securetrace.o: $(srcdir)/drill/securetrace.c $(srcdir)/drill/drill.h \ + $(srcdir)/drill/drill_util.h $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +drill/work.lo drill/work.o: $(srcdir)/drill/work.c $(srcdir)/drill/drill.h \ + $(srcdir)/drill/drill_util.h $(srcdir)/ldns/ldns.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +examples/ldns-chaos: examples/ldns-chaos.lo examples/ldns-chaos.o $(LIB) +examples/ldns-compare-zones: examples/ldns-compare-zones.lo examples/ldns-compare-zones.o $(LIB) +examples/ldnsd: examples/ldnsd.lo examples/ldnsd.o $(LIB) +examples/ldns-gen-zone: examples/ldns-gen-zone.lo examples/ldns-gen-zone.o $(LIB) +examples/ldns-key2ds: examples/ldns-key2ds.lo examples/ldns-key2ds.o $(LIB) +examples/ldns-keyfetcher: examples/ldns-keyfetcher.lo examples/ldns-keyfetcher.o $(LIB) +examples/ldns-keygen: examples/ldns-keygen.lo examples/ldns-keygen.o $(LIB) +examples/ldns-mx: examples/ldns-mx.lo examples/ldns-mx.o $(LIB) +examples/ldns-notify: examples/ldns-notify.lo examples/ldns-notify.o $(LIB) +examples/ldns-read-zone: examples/ldns-read-zone.lo examples/ldns-read-zone.o $(LIB) +examples/ldns-resolver: examples/ldns-resolver.lo examples/ldns-resolver.o $(LIB) +examples/ldns-rrsig: examples/ldns-rrsig.lo examples/ldns-rrsig.o $(LIB) +examples/ldns-test-edns: examples/ldns-test-edns.lo examples/ldns-test-edns.o $(LIB) +examples/ldns-update: examples/ldns-update.lo examples/ldns-update.o $(LIB) +examples/ldns-version: examples/ldns-version.lo examples/ldns-version.o $(LIB) +examples/ldns-walk: examples/ldns-walk.lo examples/ldns-walk.o $(LIB) +examples/ldns-zcat: examples/ldns-zcat.lo examples/ldns-zcat.o $(LIB) +examples/ldns-zsplit: examples/ldns-zsplit.lo examples/ldns-zsplit.o $(LIB) +examples/ldns-dpa: examples/ldns-dpa.lo examples/ldns-dpa.o $(LIB) +examples/ldns-nsec3-hash: examples/ldns-nsec3-hash.lo examples/ldns-nsec3-hash.o $(LIB) +examples/ldns-revoke: examples/ldns-revoke.lo examples/ldns-revoke.o $(LIB) +examples/ldns-signzone: examples/ldns-signzone.lo examples/ldns-signzone.o $(LIB) +examples/ldns-verify-zone: examples/ldns-verify-zone.lo examples/ldns-verify-zone.o $(LIB) +examples/ldns-testns: examples/ldns-testns.lo examples/ldns-testns.o examples/ldns-testpkts.lo examples/ldns-testpkts.o $(LIB) diff --git a/README b/README new file mode 100644 index 00000000000..70eb3dc0f89 --- /dev/null +++ b/README @@ -0,0 +1,144 @@ + +Contents: + REQUIREMENTS + INSTALLATION + libdns + examples + drill + INFORMATION FOR SPECIFIC OPERATING SYSTEMS + Mac OS X + Solaris + KNOWN ISSUES + pyldns + Your Support + +Project page: +http://www.nlnetlabs.nl/ldns/ +On that page you can also subscribe to the ldns mailing list. + +* Development +ldns is mainly developed on Linux and FreeBSD. It is regularly tested to +compile on other systems like Solaris and Mac OS X. + +REQUIREMENTS +- OpenSSL (Optional, but needed for features like DNSSEC) +- libpcap (Optional, but needed for examples/ldns-dpa) +- (GNU) libtool (in OSX, that's glibtool, not libtool) +- GNU make + +INSTALLATION +1. Unpack the tarball +2. cd ldns- +3. ./configure +4. gmake (it needs gnu make to compile, on systems where GNU make is the + default you can just use 'make') +5. sudo gmake install +6. Optional. (cd examples; ./configure; gmake), make example programs included. +7. Optional. (cd drill; ./configure; gmake; gmake install), to build drill. + +You can configure and compile it in a separate build directory. + +* Examples +There are some examples and dns related tools in the examples/ directory. +These can be built with: +1. cd examples/ +2. ./configure [--with-ldns=] +3. gmake + +* Drill +Drill can be built with: +1. cd drill/ +2. ./configure [--with-ldns=] +3. gmake + +Note that you need to set LD_LIBRARY_PATH if you want to run the binaries +and you have not installed the library to a system directory. You can use +the make target all-static for the examples to run them if you don't want to +install the library. + + +* Building from subversion repository + +If you are building from the repository you will need to have (gnu) +autotools like libtool and autoreconf installed. A list of all the commands +needed to build everything can be found in README.svn. Note that the actual +commands may be a little bit different on your machine. Most notable, you'll need to run libtoolize (or glibtoolize), if you skip this step, you'll get an error about missing config.sub. + +* Developers +ldns is developed by the ldns team at NLnet Labs. This team currently +consists of: + o Willem Toorop + o Wouter Wijngaards + o Matthijs Mekking + +Former main developers: + o Jelte Jansen + o Miek Gieben + +* Credits +We have received patches from the following people, thanks! + o Bedrich Kosata + o Erik Rozendaal + o Håkan Olsson + o Jakob Schlyter + o Paul Wouters + o Simon Vallet + o Ondřej Surý + + +INFORMATION FOR SPECIFIC OPERATING SYSTEMS + +MAC OS X + +For MACOSX 10.4 and later, it seems that you have to set the +MACOSX_DEPLOYMENT_TARGET environment variable to 10.4 before running +make. Apparently it defaults to 10.1. + +This appears to be a known problem in 10.2 to 10.4, see: +http://developer.apple.com/qa/qa2001/qa1233.html +for more information. + + +SOLARIS + +In Solaris multi-architecture systems (that have both 32-bit and +64-bit support), it can be a bit taxing to convince the system to +compile in 64-bit mode. Jakob Schlyter has kindly contributed a build +script that sets the right build and link options. You can find it in +contrib/build-solaris.sh + +KNOWN ISSUES + +A complete list of currently known open issues can be found here: +http://www.nlnetlabs.nl/projects/ldns/bugs + +* pyldns +Compiling pyldns produces many ``unused parameter'' warnings. Those are +harmless and may safely be ignored. +Also when building with Swig which version is before 2.0.4, compiling +pyldns produces many ``missing initializer'' warnings. Those are harmless +too. + +Your Support +NLnet Labs offers all of its software products as open source, most are +published under a BDS license. You can download them, not only from the +NLnet Labs website but also through the various OS distributions for +which NSD, ldns, and Unbound are packaged. We therefore have little idea +who uses our software in production environments and have no direct ties +with 'our customers'. + +Therefore, we ask you to contact us at users@NLnetLabs.nl and tell us +whether you use one of our products in your production environment, +what that environment looks like, and maybe even share some praise. +We would like to refer to the fact that your organization is using our +products. We will only do that if you explicitly allow us. In all other +cases we will keep the information you share with us to ourselves. + +In addition to the moral support you can also support us +financially. NLnet Labs is a recognized not-for-profit charity foundation +that is chartered to develop open-source software and open-standards +for the Internet. If you use our software to satisfaction please express +that by giving us a donation. For small donations PayPal can be used. For +larger and regular donations please contact us at users@NLnetLabs.nl. Also +see http://www.nlnetlabs.nl/labs/contributors/. + diff --git a/README.snapshots b/README.snapshots new file mode 100644 index 00000000000..891fcca1d6e --- /dev/null +++ b/README.snapshots @@ -0,0 +1,8 @@ +ldns - snapshot releases + +Snapshot releases are not official released. They can be released to +interested parties for development. + +Snapshots can be recognized from the date in the the tar file name. + +They should not be used for packaging in distributions. diff --git a/README.svn b/README.svn new file mode 100644 index 00000000000..10f7cb4163d --- /dev/null +++ b/README.svn @@ -0,0 +1,26 @@ + +# The ldns subversion repository can found at: +# www.nlnetlabs.nl/ldns/svn/ + +# small list of commands to build all on a linux system +# libtoolize is needed for most other targets + +# on Solaris, and other systems that may not have +# the default 'automake' and 'aclocal' script aliases, +# the correct versions may need to be set. On those +# systems, the 'autoreconf' line should be changed to: +# AUTOMAKE=automake-1.10 ACLOCAL=aclocal-1.10 autoreconf +# (and these systems probably need gmake instead of make) + +# older versions of libtoolize do not support --install +# so you might need to remove that (with newer versions +# it is needed) +libtoolize -c --install +autoreconf --install +./configure +make +make doc # needs doxygen for the html pages +(cd examples && autoreconf && ./configure && make) +(cd drill && autoreconf && ./configure && make) +(cd pcat && autoreconf && ./configure && make) +(cd examples/nsd-test && autoreconf && ./configure && make) diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 00000000000..55f3c925f96 --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,8620 @@ +# generated automatically by aclocal 1.11.3 -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, +# Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +m4_define([_LT_COPYING], [dnl +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is part of GNU Libtool. +# +# GNU Libtool is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, or +# obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +]) + +# serial 57 LT_INIT + + +# LT_PREREQ(VERSION) +# ------------------ +# Complain and exit if this libtool version is less that VERSION. +m4_defun([LT_PREREQ], +[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, + [m4_default([$3], + [m4_fatal([Libtool version $1 or higher is required], + 63)])], + [$2])]) + + +# _LT_CHECK_BUILDDIR +# ------------------ +# Complain if the absolute build directory name contains unusual characters +m4_defun([_LT_CHECK_BUILDDIR], +[case `pwd` in + *\ * | *\ *) + AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; +esac +]) + + +# LT_INIT([OPTIONS]) +# ------------------ +AC_DEFUN([LT_INIT], +[AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT +AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +AC_BEFORE([$0], [LT_LANG])dnl +AC_BEFORE([$0], [LT_OUTPUT])dnl +AC_BEFORE([$0], [LTDL_INIT])dnl +m4_require([_LT_CHECK_BUILDDIR])dnl + +dnl Autoconf doesn't catch unexpanded LT_ macros by default: +m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl +m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl +dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 +dnl unless we require an AC_DEFUNed macro: +AC_REQUIRE([LTOPTIONS_VERSION])dnl +AC_REQUIRE([LTSUGAR_VERSION])dnl +AC_REQUIRE([LTVERSION_VERSION])dnl +AC_REQUIRE([LTOBSOLETE_VERSION])dnl +m4_require([_LT_PROG_LTMAIN])dnl + +_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) + +dnl Parse OPTIONS +_LT_SET_OPTIONS([$0], [$1]) + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ltmain" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +_LT_SETUP + +# Only expand once: +m4_define([LT_INIT]) +])# LT_INIT + +# Old names: +AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) +AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PROG_LIBTOOL], []) +dnl AC_DEFUN([AM_PROG_LIBTOOL], []) + + +# _LT_CC_BASENAME(CC) +# ------------------- +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +m4_defun([_LT_CC_BASENAME], +[for cc_temp in $1""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +]) + + +# _LT_FILEUTILS_DEFAULTS +# ---------------------- +# It is okay to use these file commands and assume they have been set +# sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'. +m4_defun([_LT_FILEUTILS_DEFAULTS], +[: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} +])# _LT_FILEUTILS_DEFAULTS + + +# _LT_SETUP +# --------- +m4_defun([_LT_SETUP], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl + +_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl +dnl +_LT_DECL([], [host_alias], [0], [The host system])dnl +_LT_DECL([], [host], [0])dnl +_LT_DECL([], [host_os], [0])dnl +dnl +_LT_DECL([], [build_alias], [0], [The build system])dnl +_LT_DECL([], [build], [0])dnl +_LT_DECL([], [build_os], [0])dnl +dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +dnl +AC_REQUIRE([AC_PROG_LN_S])dnl +test -z "$LN_S" && LN_S="ln -s" +_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl +dnl +AC_REQUIRE([LT_CMD_MAX_LEN])dnl +_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl +_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl +dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl +m4_require([_LT_CMD_RELOAD])dnl +m4_require([_LT_CHECK_MAGIC_METHOD])dnl +m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl +m4_require([_LT_CMD_OLD_ARCHIVE])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_WITH_SYSROOT])dnl + +_LT_CONFIG_LIBTOOL_INIT([ +# See if we are running on zsh, and set the options which allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi +]) +if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + +_LT_CHECK_OBJDIR + +m4_require([_LT_TAG_COMPILER])dnl + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld="$lt_cv_prog_gnu_ld" + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + _LT_PATH_MAGIC + fi + ;; +esac + +# Use C for the default configuration in the libtool script +LT_SUPPORTED_TAG([CC]) +_LT_LANG_C_CONFIG +_LT_LANG_DEFAULT_CONFIG +_LT_CONFIG_COMMANDS +])# _LT_SETUP + + +# _LT_PREPARE_SED_QUOTE_VARS +# -------------------------- +# Define a few sed substitution that help us do robust quoting. +m4_defun([_LT_PREPARE_SED_QUOTE_VARS], +[# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([["`\\]]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' +]) + +# _LT_PROG_LTMAIN +# --------------- +# Note that this code is called both from `configure', and `config.status' +# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, +# `config.status' has no value for ac_aux_dir unless we are using Automake, +# so we pass a copy along to make sure it has a sensible value anyway. +m4_defun([_LT_PROG_LTMAIN], +[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl +_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) +ltmain="$ac_aux_dir/ltmain.sh" +])# _LT_PROG_LTMAIN + + + +# So that we can recreate a full libtool script including additional +# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS +# in macros and then make a single call at the end using the `libtool' +# label. + + +# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) +# ---------------------------------------- +# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL_INIT], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_INIT], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_INIT]) + + +# _LT_CONFIG_LIBTOOL([COMMANDS]) +# ------------------------------ +# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) + + +# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) +# ----------------------------------------------------- +m4_defun([_LT_CONFIG_SAVE_COMMANDS], +[_LT_CONFIG_LIBTOOL([$1]) +_LT_CONFIG_LIBTOOL_INIT([$2]) +]) + + +# _LT_FORMAT_COMMENT([COMMENT]) +# ----------------------------- +# Add leading comment marks to the start of each line, and a trailing +# full-stop to the whole comment if one is not present already. +m4_define([_LT_FORMAT_COMMENT], +[m4_ifval([$1], [ +m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], + [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) +)]) + + + + + +# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) +# ------------------------------------------------------------------- +# CONFIGNAME is the name given to the value in the libtool script. +# VARNAME is the (base) name used in the configure script. +# VALUE may be 0, 1 or 2 for a computed quote escaped value based on +# VARNAME. Any other value will be used directly. +m4_define([_LT_DECL], +[lt_if_append_uniq([lt_decl_varnames], [$2], [, ], + [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], + [m4_ifval([$1], [$1], [$2])]) + lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) + m4_ifval([$4], + [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) + lt_dict_add_subkey([lt_decl_dict], [$2], + [tagged?], [m4_ifval([$5], [yes], [no])])]) +]) + + +# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) +# -------------------------------------------------------- +m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) + + +# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_tag_varnames], +[_lt_decl_filter([tagged?], [yes], $@)]) + + +# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) +# --------------------------------------------------------- +m4_define([_lt_decl_filter], +[m4_case([$#], + [0], [m4_fatal([$0: too few arguments: $#])], + [1], [m4_fatal([$0: too few arguments: $#: $1])], + [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], + [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], + [lt_dict_filter([lt_decl_dict], $@)])[]dnl +]) + + +# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) +# -------------------------------------------------- +m4_define([lt_decl_quote_varnames], +[_lt_decl_filter([value], [1], $@)]) + + +# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_dquote_varnames], +[_lt_decl_filter([value], [2], $@)]) + + +# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_varnames_tagged], +[m4_assert([$# <= 2])dnl +_$0(m4_quote(m4_default([$1], [[, ]])), + m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), + m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) +m4_define([_lt_decl_varnames_tagged], +[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) + + +# lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_all_varnames], +[_$0(m4_quote(m4_default([$1], [[, ]])), + m4_if([$2], [], + m4_quote(lt_decl_varnames), + m4_quote(m4_shift($@))))[]dnl +]) +m4_define([_lt_decl_all_varnames], +[lt_join($@, lt_decl_varnames_tagged([$1], + lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl +]) + + +# _LT_CONFIG_STATUS_DECLARE([VARNAME]) +# ------------------------------------ +# Quote a variable value, and forward it to `config.status' so that its +# declaration there will have the same value as in `configure'. VARNAME +# must have a single quote delimited value for this to work. +m4_define([_LT_CONFIG_STATUS_DECLARE], +[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) + + +# _LT_CONFIG_STATUS_DECLARATIONS +# ------------------------------ +# We delimit libtool config variables with single quotes, so when +# we write them to config.status, we have to be sure to quote all +# embedded single quotes properly. In configure, this macro expands +# each variable declared with _LT_DECL (and _LT_TAGDECL) into: +# +# ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' +m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], +[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), + [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAGS +# ---------------- +# Output comment and list of tags supported by the script +m4_defun([_LT_LIBTOOL_TAGS], +[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl +available_tags="_LT_TAGS"dnl +]) + + +# _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) +# ----------------------------------- +# Extract the dictionary values for VARNAME (optionally with TAG) and +# expand to a commented shell variable setting: +# +# # Some comment about what VAR is for. +# visible_name=$lt_internal_name +m4_define([_LT_LIBTOOL_DECLARE], +[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], + [description])))[]dnl +m4_pushdef([_libtool_name], + m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl +m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), + [0], [_libtool_name=[$]$1], + [1], [_libtool_name=$lt_[]$1], + [2], [_libtool_name=$lt_[]$1], + [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl +m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl +]) + + +# _LT_LIBTOOL_CONFIG_VARS +# ----------------------- +# Produce commented declarations of non-tagged libtool config variables +# suitable for insertion in the LIBTOOL CONFIG section of the `libtool' +# script. Tagged libtool config variables (even for the LIBTOOL CONFIG +# section) are produced by _LT_LIBTOOL_TAG_VARS. +m4_defun([_LT_LIBTOOL_CONFIG_VARS], +[m4_foreach([_lt_var], + m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAG_VARS(TAG) +# ------------------------- +m4_define([_LT_LIBTOOL_TAG_VARS], +[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) + + +# _LT_TAGVAR(VARNAME, [TAGNAME]) +# ------------------------------ +m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) + + +# _LT_CONFIG_COMMANDS +# ------------------- +# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of +# variables for single and double quote escaping we saved from calls +# to _LT_DECL, we can put quote escaped variables declarations +# into `config.status', and then the shell code to quote escape them in +# for loops in `config.status'. Finally, any additional code accumulated +# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. +m4_defun([_LT_CONFIG_COMMANDS], +[AC_PROVIDE_IFELSE([LT_OUTPUT], + dnl If the libtool generation code has been placed in $CONFIG_LT, + dnl instead of duplicating it all over again into config.status, + dnl then we will have config.status run $CONFIG_LT later, so it + dnl needs to know what name is stored there: + [AC_CONFIG_COMMANDS([libtool], + [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], + dnl If the libtool generation code is destined for config.status, + dnl expand the accumulated commands and init code now: + [AC_CONFIG_COMMANDS([libtool], + [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) +])#_LT_CONFIG_COMMANDS + + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], +[ + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +_LT_CONFIG_STATUS_DECLARATIONS +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$[]1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_quote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_dquote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +_LT_OUTPUT_LIBTOOL_INIT +]) + +# _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) +# ------------------------------------ +# Generate a child script FILE with all initialization necessary to +# reuse the environment learned by the parent script, and make the +# file executable. If COMMENT is supplied, it is inserted after the +# `#!' sequence but before initialization text begins. After this +# macro, additional text can be appended to FILE to form the body of +# the child script. The macro ends with non-zero status if the +# file could not be fully written (such as if the disk is full). +m4_ifdef([AS_INIT_GENERATED], +[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], +[m4_defun([_LT_GENERATED_FILE_INIT], +[m4_require([AS_PREPARE])]dnl +[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl +[lt_write_fail=0 +cat >$1 <<_ASEOF || lt_write_fail=1 +#! $SHELL +# Generated by $as_me. +$2 +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$1 <<\_ASEOF || lt_write_fail=1 +AS_SHELL_SANITIZE +_AS_PREPARE +exec AS_MESSAGE_FD>&1 +_ASEOF +test $lt_write_fail = 0 && chmod +x $1[]dnl +m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT + +# LT_OUTPUT +# --------- +# This macro allows early generation of the libtool script (before +# AC_OUTPUT is called), incase it is used in configure for compilation +# tests. +AC_DEFUN([LT_OUTPUT], +[: ${CONFIG_LT=./config.lt} +AC_MSG_NOTICE([creating $CONFIG_LT]) +_LT_GENERATED_FILE_INIT(["$CONFIG_LT"], +[# Run this file to recreate a libtool stub with the current configuration.]) + +cat >>"$CONFIG_LT" <<\_LTEOF +lt_cl_silent=false +exec AS_MESSAGE_LOG_FD>>config.log +{ + echo + AS_BOX([Running $as_me.]) +} >&AS_MESSAGE_LOG_FD + +lt_cl_help="\ +\`$as_me' creates a local libtool stub from the current configuration, +for use in further configure time tests before the real libtool is +generated. + +Usage: $[0] [[OPTIONS]] + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + +Report bugs to ." + +lt_cl_version="\ +m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl +m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) +configured by $[0], generated by m4_PACKAGE_STRING. + +Copyright (C) 2011 Free Software Foundation, Inc. +This config.lt script is free software; the Free Software Foundation +gives unlimited permision to copy, distribute and modify it." + +while test $[#] != 0 +do + case $[1] in + --version | --v* | -V ) + echo "$lt_cl_version"; exit 0 ;; + --help | --h* | -h ) + echo "$lt_cl_help"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --quiet | --q* | --silent | --s* | -q ) + lt_cl_silent=: ;; + + -*) AC_MSG_ERROR([unrecognized option: $[1] +Try \`$[0] --help' for more information.]) ;; + + *) AC_MSG_ERROR([unrecognized argument: $[1] +Try \`$[0] --help' for more information.]) ;; + esac + shift +done + +if $lt_cl_silent; then + exec AS_MESSAGE_FD>/dev/null +fi +_LTEOF + +cat >>"$CONFIG_LT" <<_LTEOF +_LT_OUTPUT_LIBTOOL_COMMANDS_INIT +_LTEOF + +cat >>"$CONFIG_LT" <<\_LTEOF +AC_MSG_NOTICE([creating $ofile]) +_LT_OUTPUT_LIBTOOL_COMMANDS +AS_EXIT(0) +_LTEOF +chmod +x "$CONFIG_LT" + +# configure is writing to config.log, but config.lt does its own redirection, +# appending to config.log, which fails on DOS, as config.log is still kept +# open by configure. Here we exec the FD to /dev/null, effectively closing +# config.log, so it can be properly (re)opened and appended to by config.lt. +lt_cl_success=: +test "$silent" = yes && + lt_config_lt_args="$lt_config_lt_args --quiet" +exec AS_MESSAGE_LOG_FD>/dev/null +$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false +exec AS_MESSAGE_LOG_FD>>config.log +$lt_cl_success || AS_EXIT(1) +])# LT_OUTPUT + + +# _LT_CONFIG(TAG) +# --------------- +# If TAG is the built-in tag, create an initial libtool script with a +# default configuration from the untagged config vars. Otherwise add code +# to config.status for appending the configuration named by TAG from the +# matching tagged config vars. +m4_defun([_LT_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_CONFIG_SAVE_COMMANDS([ + m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl + m4_if(_LT_TAG, [C], [ + # See if we are running on zsh, and set the options which allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + + cfgfile="${ofile}T" + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL + +# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +_LT_COPYING +_LT_LIBTOOL_TAGS + +# ### BEGIN LIBTOOL CONFIG +_LT_LIBTOOL_CONFIG_VARS +_LT_LIBTOOL_TAG_VARS +# ### END LIBTOOL CONFIG + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + _LT_PROG_LTMAIN + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + _LT_PROG_REPLACE_SHELLFNS + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +], +[cat <<_LT_EOF >> "$ofile" + +dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded +dnl in a comment (ie after a #). +# ### BEGIN LIBTOOL TAG CONFIG: $1 +_LT_LIBTOOL_TAG_VARS(_LT_TAG) +# ### END LIBTOOL TAG CONFIG: $1 +_LT_EOF +])dnl /m4_if +], +[m4_if([$1], [], [ + PACKAGE='$PACKAGE' + VERSION='$VERSION' + TIMESTAMP='$TIMESTAMP' + RM='$RM' + ofile='$ofile'], []) +])dnl /_LT_CONFIG_SAVE_COMMANDS +])# _LT_CONFIG + + +# LT_SUPPORTED_TAG(TAG) +# --------------------- +# Trace this macro to discover what tags are supported by the libtool +# --tag option, using: +# autoconf --trace 'LT_SUPPORTED_TAG:$1' +AC_DEFUN([LT_SUPPORTED_TAG], []) + + +# C support is built-in for now +m4_define([_LT_LANG_C_enabled], []) +m4_define([_LT_TAGS], []) + + +# LT_LANG(LANG) +# ------------- +# Enable libtool support for the given language if not already enabled. +AC_DEFUN([LT_LANG], +[AC_BEFORE([$0], [LT_OUTPUT])dnl +m4_case([$1], + [C], [_LT_LANG(C)], + [C++], [_LT_LANG(CXX)], + [Go], [_LT_LANG(GO)], + [Java], [_LT_LANG(GCJ)], + [Fortran 77], [_LT_LANG(F77)], + [Fortran], [_LT_LANG(FC)], + [Windows Resource], [_LT_LANG(RC)], + [m4_ifdef([_LT_LANG_]$1[_CONFIG], + [_LT_LANG($1)], + [m4_fatal([$0: unsupported language: "$1"])])])dnl +])# LT_LANG + + +# _LT_LANG(LANGNAME) +# ------------------ +m4_defun([_LT_LANG], +[m4_ifdef([_LT_LANG_]$1[_enabled], [], + [LT_SUPPORTED_TAG([$1])dnl + m4_append([_LT_TAGS], [$1 ])dnl + m4_define([_LT_LANG_]$1[_enabled], [])dnl + _LT_LANG_$1_CONFIG($1)])dnl +])# _LT_LANG + + +m4_ifndef([AC_PROG_GO], [ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_GO. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +m4_defun([AC_PROG_GO], +[AC_LANG_PUSH(Go)dnl +AC_ARG_VAR([GOC], [Go compiler command])dnl +AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl +_AC_ARG_VAR_LDFLAGS()dnl +AC_CHECK_TOOL(GOC, gccgo) +if test -z "$GOC"; then + if test -n "$ac_tool_prefix"; then + AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) + fi +fi +if test -z "$GOC"; then + AC_CHECK_PROG(GOC, gccgo, gccgo, false) +fi +])#m4_defun +])#m4_ifndef + + +# _LT_LANG_DEFAULT_CONFIG +# ----------------------- +m4_defun([_LT_LANG_DEFAULT_CONFIG], +[AC_PROVIDE_IFELSE([AC_PROG_CXX], + [LT_LANG(CXX)], + [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) + +AC_PROVIDE_IFELSE([AC_PROG_F77], + [LT_LANG(F77)], + [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) + +AC_PROVIDE_IFELSE([AC_PROG_FC], + [LT_LANG(FC)], + [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) + +dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal +dnl pulling things in needlessly. +AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([LT_PROG_GCJ], + [LT_LANG(GCJ)], + [m4_ifdef([AC_PROG_GCJ], + [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([A][M_PROG_GCJ], + [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([LT_PROG_GCJ], + [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) + +AC_PROVIDE_IFELSE([AC_PROG_GO], + [LT_LANG(GO)], + [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) + +AC_PROVIDE_IFELSE([LT_PROG_RC], + [LT_LANG(RC)], + [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) +])# _LT_LANG_DEFAULT_CONFIG + +# Obsolete macros: +AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) +AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) +AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) +AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) +AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_CXX], []) +dnl AC_DEFUN([AC_LIBTOOL_F77], []) +dnl AC_DEFUN([AC_LIBTOOL_FC], []) +dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) +dnl AC_DEFUN([AC_LIBTOOL_RC], []) + + +# _LT_TAG_COMPILER +# ---------------- +m4_defun([_LT_TAG_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl +_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl +_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl +_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_TAG_COMPILER + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +m4_defun([_LT_COMPILER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +m4_defun([_LT_LINKER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* +])# _LT_LINKER_BOILERPLATE + +# _LT_REQUIRED_DARWIN_CHECKS +# ------------------------- +m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ + case $host_os in + rhapsody* | darwin*) + AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) + AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) + AC_CHECK_TOOL([LIPO], [lipo], [:]) + AC_CHECK_TOOL([OTOOL], [otool], [:]) + AC_CHECK_TOOL([OTOOL64], [otool64], [:]) + _LT_DECL([], [DSYMUTIL], [1], + [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) + _LT_DECL([], [NMEDIT], [1], + [Tool to change global to local symbols on Mac OS X]) + _LT_DECL([], [LIPO], [1], + [Tool to manipulate fat objects and archives on Mac OS X]) + _LT_DECL([], [OTOOL], [1], + [ldd/readelf like tool for Mach-O binaries on Mac OS X]) + _LT_DECL([], [OTOOL64], [1], + [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) + + AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], + [lt_cv_apple_cc_single_mod=no + if test -z "${LT_MULTI_MODULE}"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test $_lt_result -eq 0; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi]) + + AC_CACHE_CHECK([for -exported_symbols_list linker flag], + [lt_cv_ld_exported_symbols_list], + [lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [lt_cv_ld_exported_symbols_list=yes], + [lt_cv_ld_exported_symbols_list=no]) + LDFLAGS="$save_LDFLAGS" + ]) + + AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], + [lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD + echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD + $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD + echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD + $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + ]) + case $host_os in + rhapsody* | darwin1.[[012]]) + _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + 10.[[012]]*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test "$lt_cv_apple_cc_single_mod" = "yes"; then + _lt_dar_single_mod='$single_module' + fi + if test "$lt_cv_ld_exported_symbols_list" = "yes"; then + _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac +]) + + +# _LT_DARWIN_LINKER_FEATURES([TAG]) +# --------------------------------- +# Checks for linker and compiler features on darwin +m4_defun([_LT_DARWIN_LINKER_FEATURES], +[ + m4_require([_LT_REQUIRED_DARWIN_CHECKS]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_automatic, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + if test "$lt_cv_ld_force_load" = "yes"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], + [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='' + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" + case $cc_basename in + ifort*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test "$_lt_dar_can_shared" = "yes"; then + output_verbose_link_cmd=func_echo_all + _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + m4_if([$1], [CXX], +[ if test "$lt_cv_apple_cc_single_mod" != "yes"; then + _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" + fi +],[]) + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi +]) + +# _LT_SYS_MODULE_PATH_AIX([TAGNAME]) +# ---------------------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +# Store the results from the different compilers for each TAGNAME. +# Allow to override them for all tags through lt_cv_aix_libpath. +m4_defun([_LT_SYS_MODULE_PATH_AIX], +[m4_require([_LT_DECL_SED])dnl +if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], + [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ + lt_aix_libpath_sed='[ + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }]' + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi],[]) + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])="/usr/lib:/lib" + fi + ]) + aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) +fi +])# _LT_SYS_MODULE_PATH_AIX + + +# _LT_SHELL_INIT(ARG) +# ------------------- +m4_define([_LT_SHELL_INIT], +[m4_divert_text([M4SH-INIT], [$1 +])])# _LT_SHELL_INIT + + + +# _LT_PROG_ECHO_BACKSLASH +# ----------------------- +# Find how we can fake an echo command that does not interpret backslash. +# In particular, with Autoconf 2.60 or later we add some code to the start +# of the generated configure script which will find a shell with a builtin +# printf (which we can use as an echo command). +m4_defun([_LT_PROG_ECHO_BACKSLASH], +[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +AC_MSG_CHECKING([how to print strings]) +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$[]1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + +case "$ECHO" in + printf*) AC_MSG_RESULT([printf]) ;; + print*) AC_MSG_RESULT([print -r]) ;; + *) AC_MSG_RESULT([cat]) ;; +esac + +m4_ifdef([_AS_DETECT_SUGGESTED], +[_AS_DETECT_SUGGESTED([ + test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test "X`printf %s $ECHO`" = "X$ECHO" \ + || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) + +_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) +_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) +])# _LT_PROG_ECHO_BACKSLASH + + +# _LT_WITH_SYSROOT +# ---------------- +AC_DEFUN([_LT_WITH_SYSROOT], +[AC_MSG_CHECKING([for sysroot]) +AC_ARG_WITH([sysroot], +[ --with-sysroot[=DIR] Search for dependent libraries within DIR + (or the compiler's sysroot if not specified).], +[], [with_sysroot=no]) + +dnl lt_sysroot will always be passed unquoted. We quote it here +dnl in case the user passed a directory name. +lt_sysroot= +case ${with_sysroot} in #( + yes) + if test "$GCC" = yes; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + AC_MSG_RESULT([${with_sysroot}]) + AC_MSG_ERROR([The sysroot must be an absolute path.]) + ;; +esac + + AC_MSG_RESULT([${lt_sysroot:-no}]) +_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl +[dependent libraries, and in which our libraries should be installed.])]) + +# _LT_ENABLE_LOCK +# --------------- +m4_defun([_LT_ENABLE_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AS_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD="${LD-ld}_sol2" + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks="$enable_libtool_lock" +])# _LT_ENABLE_LOCK + + +# _LT_PROG_AR +# ----------- +m4_defun([_LT_PROG_AR], +[AC_CHECK_TOOLS(AR, [ar], false) +: ${AR=ar} +: ${AR_FLAGS=cru} +_LT_DECL([], [AR], [1], [The archiver]) +_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) + +AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], + [lt_cv_ar_at_file=no + AC_COMPILE_IFELSE([AC_LANG_PROGRAM], + [echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([lt_ar_try]) + if test "$ac_status" -eq 0; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + AC_TRY_EVAL([lt_ar_try]) + if test "$ac_status" -ne 0; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + ]) + ]) + +if test "x$lt_cv_ar_at_file" = xno; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi +_LT_DECL([], [archiver_list_spec], [1], + [How to feed a file listing to the archiver]) +])# _LT_PROG_AR + + +# _LT_CMD_OLD_ARCHIVE +# ------------------- +m4_defun([_LT_CMD_OLD_ARCHIVE], +[_LT_PROG_AR + +AC_CHECK_TOOL(STRIP, strip, :) +test -z "$STRIP" && STRIP=: +_LT_DECL([], [STRIP], [1], [A symbol stripping program]) + +AC_CHECK_TOOL(RANLIB, ranlib, :) +test -z "$RANLIB" && RANLIB=: +_LT_DECL([], [RANLIB], [1], + [Commands used to install an old-style archive]) + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac +_LT_DECL([], [old_postinstall_cmds], [2]) +_LT_DECL([], [old_postuninstall_cmds], [2]) +_LT_TAGDECL([], [old_archive_cmds], [2], + [Commands used to build an old-style archive]) +_LT_DECL([], [lock_old_archive_extraction], [0], + [Whether to use a lock for old archive extraction]) +])# _LT_CMD_OLD_ARCHIVE + + +# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([_LT_COMPILER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $RM conftest* +]) + +if test x"[$]$2" = xyes; then + m4_if([$5], , :, [$5]) +else + m4_if([$6], , :, [$6]) +fi +])# _LT_COMPILER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) + + +# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------- +# Check whether the given linker option works +AC_DEFUN([_LT_LINKER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $3" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" +]) + +if test x"[$]$2" = xyes; then + m4_if([$4], , :, [$4]) +else + m4_if([$5], , :, [$5]) +fi +])# _LT_LINKER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) + + +# LT_CMD_MAX_LEN +#--------------- +AC_DEFUN([LT_CMD_MAX_LEN], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8 ; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac +]) +if test -n $lt_cv_sys_max_cmd_len ; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +max_cmd_len=$lt_cv_sys_max_cmd_len +_LT_DECL([], [max_cmd_len], [0], + [What is the maximum length of a command?]) +])# LT_CMD_MAX_LEN + +# Old name: +AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) + + +# _LT_HEADER_DLFCN +# ---------------- +m4_defun([_LT_HEADER_DLFCN], +[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl +])# _LT_HEADER_DLFCN + + +# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# ---------------------------------------------------------------- +m4_defun([_LT_TRY_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test "$cross_compiling" = yes; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +[#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +}] +_LT_EOF + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_TRY_DLOPEN_SELF + + +# LT_SYS_DLOPEN_SELF +# ------------------ +AC_DEFUN([LT_SYS_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen="shl_load"], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen="dlopen"], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +_LT_DECL([dlopen_support], [enable_dlopen], [0], + [Whether dlopen is supported]) +_LT_DECL([dlopen_self], [enable_dlopen_self], [0], + [Whether dlopen of programs is supported]) +_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], + [Whether dlopen of statically linked programs is supported]) +])# LT_SYS_DLOPEN_SELF + +# Old name: +AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) + + +# _LT_COMPILER_C_O([TAGNAME]) +# --------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler. +# This macro does not hard code the compiler like AC_PROG_CC_C_O. +m4_defun([_LT_COMPILER_C_O], +[m4_require([_LT_DECL_SED])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* +]) +_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], + [Does compiler simultaneously support -c and -o options?]) +])# _LT_COMPILER_C_O + + +# _LT_COMPILER_FILE_LOCKS([TAGNAME]) +# ---------------------------------- +# Check to see if we can do hard links to lock some files if needed +m4_defun([_LT_COMPILER_FILE_LOCKS], +[m4_require([_LT_ENABLE_LOCK])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_COMPILER_C_O([$1]) + +hard_links="nottested" +if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test "$hard_links" = no; then + AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) +])# _LT_COMPILER_FILE_LOCKS + + +# _LT_CHECK_OBJDIR +# ---------------- +m4_defun([_LT_CHECK_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +_LT_DECL([], [objdir], [0], + [The name of the directory that contains temporary libtool files])dnl +m4_pattern_allow([LT_OBJDIR])dnl +AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/", + [Define to the sub-directory in which libtool stores uninstalled libraries.]) +])# _LT_CHECK_OBJDIR + + +# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) +# -------------------------------------- +# Check hardcoding attributes. +m4_defun([_LT_LINKER_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || + test -n "$_LT_TAGVAR(runpath_var, $1)" || + test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then + + # We can hardcode non-existent directories. + if test "$_LT_TAGVAR(hardcode_direct, $1)" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no && + test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then + # Linking always hardcodes the temporary library directory. + _LT_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) + +if test "$_LT_TAGVAR(hardcode_action, $1)" = relink || + test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi +_LT_TAGDECL([], [hardcode_action], [0], + [How to hardcode a shared library path into an executable]) +])# _LT_LINKER_HARDCODE_LIBPATH + + +# _LT_CMD_STRIPLIB +# ---------------- +m4_defun([_LT_CMD_STRIPLIB], +[m4_require([_LT_DECL_EGREP]) +striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +_LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) +_LT_DECL([], [striplib], [1]) +])# _LT_CMD_STRIPLIB + + +# _LT_SYS_DYNAMIC_LINKER([TAG]) +# ----------------------------- +# PORTME Fill in your ld.so characteristics +m4_defun([_LT_SYS_DYNAMIC_LINKER], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_OBJDUMP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +AC_MSG_CHECKING([dynamic linker characteristics]) +m4_if([$1], + [], [ +if test "$GCC" = yes; then + case $host_os in + darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; + *) lt_awk_arg="/^libraries:/" ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq="s,=\([[A-Za-z]]:\),\1,g" ;; + *) lt_sed_strip_eq="s,=/,/,g" ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary. + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path/$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" + else + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS=" "; FS="/|\n";} { + lt_foo=""; + lt_count=0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo="/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[[lt_foo]]++; } + if (lt_freq[[lt_foo]] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's,/\([[A-Za-z]]:\),\1,g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix[[4-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + library_names_spec='${libname}.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec="$LIB" + if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[23]].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=yes + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[[3-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], + [lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ + LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], + [lt_cv_shlibpath_overrides_runpath=yes])]) + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + ]) + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[[89]] | openbsd2.[[89]].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +fi +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" +fi + +_LT_DECL([], [variables_saved_for_relink], [1], + [Variables whose values should be saved in libtool wrapper scripts and + restored at link time]) +_LT_DECL([], [need_lib_prefix], [0], + [Do we need the "lib" prefix for modules?]) +_LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) +_LT_DECL([], [version_type], [0], [Library versioning type]) +_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) +_LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) +_LT_DECL([], [shlibpath_overrides_runpath], [0], + [Is shlibpath searched before the hard-coded library search path?]) +_LT_DECL([], [libname_spec], [1], [Format of library name prefix]) +_LT_DECL([], [library_names_spec], [1], + [[List of archive names. First name is the real one, the rest are links. + The last name is the one that the linker finds with -lNAME]]) +_LT_DECL([], [soname_spec], [1], + [[The coded name of the library, if different from the real name]]) +_LT_DECL([], [install_override_mode], [1], + [Permission mode override for installation of shared libraries]) +_LT_DECL([], [postinstall_cmds], [2], + [Command to use after installation of a shared archive]) +_LT_DECL([], [postuninstall_cmds], [2], + [Command to use after uninstallation of a shared archive]) +_LT_DECL([], [finish_cmds], [2], + [Commands used to finish a libtool library installation in a directory]) +_LT_DECL([], [finish_eval], [1], + [[As "finish_cmds", except a single script fragment to be evaled but + not shown]]) +_LT_DECL([], [hardcode_into_libs], [0], + [Whether we should hardcode library paths into libraries]) +_LT_DECL([], [sys_lib_search_path_spec], [2], + [Compile-time system search path for libraries]) +_LT_DECL([], [sys_lib_dlsearch_path_spec], [2], + [Run-time system search path for libraries]) +])# _LT_SYS_DYNAMIC_LINKER + + +# _LT_PATH_TOOL_PREFIX(TOOL) +# -------------------------- +# find a file program which can recognize shared library +AC_DEFUN([_LT_PATH_TOOL_PREFIX], +[m4_require([_LT_DECL_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="m4_if([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$1; then + lt_cv_path_MAGIC_CMD="$ac_dir/$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac]) +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +_LT_DECL([], [MAGIC_CMD], [0], + [Used to examine libraries when file_magic_cmd begins with "file"])dnl +])# _LT_PATH_TOOL_PREFIX + +# Old name: +AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) + + +# _LT_PATH_MAGIC +# -------------- +# find a file program which can recognize a shared library +m4_defun([_LT_PATH_MAGIC], +[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# _LT_PATH_MAGIC + + +# LT_PATH_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([LT_PATH_LD], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PROG_ECHO_BACKSLASH])dnl + +AC_ARG_WITH([gnu-ld], + [AS_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test "$withval" = no || with_gnu_ld=yes], + [with_gnu_ld=no])dnl + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[[3-9]]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + +_LT_DECL([], [deplibs_check_method], [1], + [Method to check whether dependent libraries are shared objects]) +_LT_DECL([], [file_magic_cmd], [1], + [Command to use when deplibs_check_method = "file_magic"]) +_LT_DECL([], [file_magic_glob], [1], + [How to find potential files when deplibs_check_method = "file_magic"]) +_LT_DECL([], [want_nocaseglob], [1], + [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) +])# _LT_CHECK_MAGIC_METHOD + + +# LT_PATH_NM +# ---------- +# find the pathname to a BSD- or MS-compatible name lister +AC_DEFUN([LT_PATH_NM], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + : ${lt_cv_path_NM=no} +fi]) +if test "$lt_cv_path_NM" != "no"; then + NM="$lt_cv_path_NM" +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) + case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols" + ;; + *) + DUMPBIN=: + ;; + esac + fi + AC_SUBST([DUMPBIN]) + if test "$DUMPBIN" != ":"; then + NM="$DUMPBIN" + fi +fi +test -z "$NM" && NM=nm +AC_SUBST([NM]) +_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl + +AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], + [lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) + cat conftest.out >&AS_MESSAGE_LOG_FD + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest*]) +])# LT_PATH_NM + +# Old names: +AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) +AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_PROG_NM], []) +dnl AC_DEFUN([AC_PROG_NM], []) + +# _LT_CHECK_SHAREDLIB_FROM_LINKLIB +# -------------------------------- +# how to determine the name of the shared library +# associated with a specific link library. +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +m4_require([_LT_DECL_DLLTOOL]) +AC_CACHE_CHECK([how to associate runtime and link libraries], +lt_cv_sharedlib_from_linklib_cmd, +[lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh + # decide which to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd="$ECHO" + ;; +esac +]) +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + +_LT_DECL([], [sharedlib_from_linklib_cmd], [1], + [Command to associate shared and link libraries]) +])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB + + +# _LT_PATH_MANIFEST_TOOL +# ---------------------- +# locate the manifest tool +m4_defun([_LT_PATH_MANIFEST_TOOL], +[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], + [lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&AS_MESSAGE_LOG_FD + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest*]) +if test "x$lt_cv_path_mainfest_tool" != xyes; then + MANIFEST_TOOL=: +fi +_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl +])# _LT_PATH_MANIFEST_TOOL + + +# LT_LIB_M +# -------- +# check for math library +AC_DEFUN([LT_LIB_M], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM="-lm") + ;; +esac +AC_SUBST([LIBM]) +])# LT_LIB_M + +# Old name: +AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_CHECK_LIBM], []) + + +# _LT_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------- +m4_defun([_LT_COMPILER_NO_RTTI], +[m4_require([_LT_TAG_COMPILER])dnl + +_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test "$GCC" = yes; then + case $cc_basename in + nvcc*) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; + *) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; + esac + + _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], + [Compiler flag to turn off builtin functions]) +])# _LT_COMPILER_NO_RTTI + + +# _LT_CMD_GLOBAL_SYMBOLS +# ---------------------- +m4_defun([_LT_CMD_GLOBAL_SYMBOLS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([LT_PATH_NM])dnl +AC_REQUIRE([LT_PATH_LD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_TAG_COMPILER])dnl + +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) + if test "$host_cpu" = ia64; then + symcode='[[ABCDEGRST]]' + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function + # and D for any global variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK ['"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ +" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ +" s[1]~/^[@?]/{print s[1], s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx]" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + nlist=conftest.nm + if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +/* DATA imports from DLLs on WIN32 con't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT@&t@_DLSYM_CONST +#elif defined(__osf__) +/* This system does not cope well with relocations in const data. */ +# define LT@&t@_DLSYM_CONST +#else +# define LT@&t@_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT@&t@_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[[]] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + +_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], + [Take the output of nm and produce a listing of raw symbols and C names]) +_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], + [Transform the output of nm in a proper C declaration]) +_LT_DECL([global_symbol_to_c_name_address], + [lt_cv_sys_global_symbol_to_c_name_address], [1], + [Transform the output of nm in a C name address pair]) +_LT_DECL([global_symbol_to_c_name_address_lib_prefix], + [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], + [Transform the output of nm in a C name address pair when lib prefix is needed]) +_LT_DECL([], [nm_file_list_spec], [1], + [Specify filename containing input files for $NM]) +]) # _LT_CMD_GLOBAL_SYMBOLS + + +# _LT_COMPILER_PIC([TAGNAME]) +# --------------------------- +m4_defun([_LT_COMPILER_PIC], +[m4_require([_LT_TAG_COMPILER])dnl +_LT_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_TAGVAR(lt_prog_compiler_static, $1)= + +m4_if([$1], [CXX], [ + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix[[4-9]]*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + if test "$host_cpu" != ia64; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + ecpc* ) + # old Intel C++ for x86_64 which still supported -KPIC. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) + # IBM XL 8.0, 9.0 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd* | netbsdelf*-gnu) + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test "$GCC" = yes; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' + if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + + hpux9* | hpux10* | hpux11*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + # old Intel for x86_64 which still supported -KPIC. + ecc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' + _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' + ;; + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='' + ;; + *Sun\ F* | *Sun*Fortran*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + *Intel*\ [[CF]]*Compiler*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + *Portland\ Group*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + rdos*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" + ;; +esac + +AC_CACHE_CHECK([for $compiler option to produce PIC], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) +_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], + [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], + [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], + [Additional compiler flags for building library objects]) + +_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], + [How to pass a linker flag through the compiler]) +# +# Check to make sure the static flag actually works. +# +wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" +_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) +_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], + [Compiler flag to prevent dynamic linking]) +])# _LT_COMPILER_PIC + + +# _LT_LINKER_SHLIBS([TAGNAME]) +# ---------------------------- +# See if the linker supports building shared libraries. +m4_defun([_LT_LINKER_SHLIBS], +[AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +m4_if([$1], [CXX], [ + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + case $host_os in + aix[[4-9]]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global defined + # symbols, whereas GNU nm marks them as "W". + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" + ;; + cygwin* | mingw* | cegcc*) + case $cc_basename in + cl*) + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + ;; + esac + ;; + linux* | k*bsd*-gnu | gnu*) + _LT_TAGVAR(link_all_deplibs, $1)=no + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +], [ + runpath_var= + _LT_TAGVAR(allow_undefined_flag, $1)= + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(archive_cmds, $1)= + _LT_TAGVAR(archive_expsym_cmds, $1)= + _LT_TAGVAR(compiler_needs_object, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(hardcode_automatic, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(hardcode_libdir_separator, $1)= + _LT_TAGVAR(hardcode_minus_L, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_TAGVAR(inherit_rpath, $1)=no + _LT_TAGVAR(link_all_deplibs, $1)=unknown + _LT_TAGVAR(module_cmds, $1)= + _LT_TAGVAR(module_expsym_cmds, $1)= + _LT_TAGVAR(old_archive_from_new_cmds, $1)= + _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_TAGVAR(thread_safe_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. +dnl Note also adjust exclude_expsyms for C++ above. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + linux* | k*bsd*-gnu | gnu*) + _LT_TAGVAR(link_all_deplibs, $1)=no + ;; + esac + + _LT_TAGVAR(ld_shlibs, $1)=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test "$with_gnu_ld" = yes; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; + *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test "$lt_use_gnu_ld_interface" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[[3-9]]*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test "$host_os" = linux-dietlibc; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test "$tmp_diet" = no + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + _LT_TAGVAR(whole_archive_flag_spec, $1)= + tmp_sharedflag='--shared' ;; + xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then + runpath_var= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix[[4-9]]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global + # defined symbols, whereas GNU nm marks them as "W". + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' + + if test "$GCC" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + _LT_TAGVAR(link_all_deplibs, $1)=no + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + bsdi[[45]]*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + esac + ;; + + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + m4_if($1, [], [ + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + _LT_LINKER_OPTION([if $CC understands -b], + _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], + [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) + ;; + esac + fi + if test "$with_gnu_ld" = no; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], + [lt_cv_irix_exported_symbol], + [save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" + AC_LINK_IFELSE( + [AC_LANG_SOURCE( + [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], + [C++], [[int foo (void) { return 0; }]], + [Fortran 77], [[ + subroutine foo + end]], + [Fortran], [[ + subroutine foo + end]])])], + [lt_cv_irix_exported_symbol=yes], + [lt_cv_irix_exported_symbol=no]) + LDFLAGS="$save_LDFLAGS"]) + if test "$lt_cv_irix_exported_symbol" = yes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' + fi + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *nto* | *qnx*) + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + else + case $host_os in + openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + ;; + esac + fi + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' + if test "$GCC" = yes; then + wlarc='${wl}' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='${wl}' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. GCC discards it without `$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test "$GCC" = yes; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + fi + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + if test x$host_vendor = xsni; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym' + ;; + esac + fi + fi +]) +AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) +test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld + +_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl +_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl +_LT_DECL([], [extract_expsyms_cmds], [2], + [The commands to extract the exported symbol list from a shared archive]) + +# +# Do we need to explicitly link libc? +# +case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $_LT_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_CACHE_CHECK([whether -lc should be explicitly linked in], + [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), + [$RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) + _LT_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) + then + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no + else + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + ]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) + ;; + esac + fi + ;; +esac + +_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], + [Whether or not to add -lc for building shared libraries]) +_LT_TAGDECL([allow_libtool_libs_with_static_runtimes], + [enable_shared_with_static_runtimes], [0], + [Whether or not to disallow shared libs when runtime libs are static]) +_LT_TAGDECL([], [export_dynamic_flag_spec], [1], + [Compiler flag to allow reflexive dlopens]) +_LT_TAGDECL([], [whole_archive_flag_spec], [1], + [Compiler flag to generate shared objects directly from archives]) +_LT_TAGDECL([], [compiler_needs_object], [1], + [Whether the compiler copes with passing no objects directly]) +_LT_TAGDECL([], [old_archive_from_new_cmds], [2], + [Create an old-style archive from a shared archive]) +_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], + [Create a temporary old-style archive to link instead of a shared archive]) +_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) +_LT_TAGDECL([], [archive_expsym_cmds], [2]) +_LT_TAGDECL([], [module_cmds], [2], + [Commands used to build a loadable module if different from building + a shared archive.]) +_LT_TAGDECL([], [module_expsym_cmds], [2]) +_LT_TAGDECL([], [with_gnu_ld], [1], + [Whether we are building with GNU ld or not]) +_LT_TAGDECL([], [allow_undefined_flag], [1], + [Flag that allows shared libraries with undefined symbols to be built]) +_LT_TAGDECL([], [no_undefined_flag], [1], + [Flag that enforces no undefined symbols]) +_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], + [Flag to hardcode $libdir into a binary during linking. + This must work even if $libdir does not exist]) +_LT_TAGDECL([], [hardcode_libdir_separator], [1], + [Whether we need a single "-rpath" flag with a separated argument]) +_LT_TAGDECL([], [hardcode_direct], [0], + [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes + DIR into the resulting binary]) +_LT_TAGDECL([], [hardcode_direct_absolute], [0], + [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes + DIR into the resulting binary and the resulting library dependency is + "absolute", i.e impossible to change by setting ${shlibpath_var} if the + library is relocated]) +_LT_TAGDECL([], [hardcode_minus_L], [0], + [Set to "yes" if using the -LDIR flag during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_shlibpath_var], [0], + [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_automatic], [0], + [Set to "yes" if building a shared library automatically hardcodes DIR + into the library and all subsequent libraries and executables linked + against it]) +_LT_TAGDECL([], [inherit_rpath], [0], + [Set to yes if linker adds runtime paths of dependent libraries + to runtime path list]) +_LT_TAGDECL([], [link_all_deplibs], [0], + [Whether libtool must link a program against all its dependency libraries]) +_LT_TAGDECL([], [always_export_symbols], [0], + [Set to "yes" if exported symbols are required]) +_LT_TAGDECL([], [export_symbols_cmds], [2], + [The commands to list exported symbols]) +_LT_TAGDECL([], [exclude_expsyms], [1], + [Symbols that should not be listed in the preloaded symbols]) +_LT_TAGDECL([], [include_expsyms], [1], + [Symbols that must always be exported]) +_LT_TAGDECL([], [prelink_cmds], [2], + [Commands necessary for linking programs (against libraries) with templates]) +_LT_TAGDECL([], [postlink_cmds], [2], + [Commands necessary for finishing linking programs]) +_LT_TAGDECL([], [file_list_spec], [1], + [Specify filename containing input files]) +dnl FIXME: Not yet implemented +dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], +dnl [Compiler flag to generate thread safe objects]) +])# _LT_LINKER_SHLIBS + + +# _LT_LANG_C_CONFIG([TAG]) +# ------------------------ +# Ensure that the configuration variables for a C compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to `libtool'. +m4_defun([_LT_LANG_C_CONFIG], +[m4_require([_LT_DECL_EGREP])dnl +lt_save_CC="$CC" +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + +_LT_TAG_COMPILER +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + LT_SYS_DLOPEN_SELF + _LT_CMD_STRIPLIB + + # Report which library types will actually be built + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[[4-9]]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_CONFIG($1) +fi +AC_LANG_POP +CC="$lt_save_CC" +])# _LT_LANG_C_CONFIG + + +# _LT_LANG_CXX_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a C++ compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to `libtool'. +m4_defun([_LT_LANG_CXX_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_PROG_CXXCPP +else + _lt_caught_CXX_error=yes +fi + +AC_LANG_PUSH(C++) +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(compiler_needs_object, $1)=no +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the CXX compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_caught_CXX_error" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests + lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_CFLAGS=$CFLAGS + lt_save_LD=$LD + lt_save_GCC=$GCC + GCC=$GXX + lt_save_with_gnu_ld=$with_gnu_ld + lt_save_path_LD=$lt_cv_path_LD + if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx + else + $as_unset lt_cv_prog_gnu_ld + fi + if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX + else + $as_unset lt_cv_path_LD + fi + test -z "${LDCXX+set}" || LD=$LDCXX + CC=${CXX-"c++"} + CFLAGS=$CXXFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + # We don't want -fno-exception when compiling C++ code, so set the + # no_builtin_flag separately + if test "$GXX" = yes; then + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + else + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + fi + + if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + LT_PATH_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test "$with_gnu_ld" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | + $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + GXX=no + with_gnu_ld=no + wlarc= + fi + + # PORTME: fill in a description of your system's C++ link characteristics + AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) + _LT_TAGVAR(ld_shlibs, $1)=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aix[[4-9]]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' + + if test "$GXX" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to + # export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty + # executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared + # libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32* | cegcc*) + case $GXX,$cc_basename in + ,cl* | no,cl*) + # Native MSVC + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # g++ + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + freebsd2.*) + # C++ shared libraries reported to be fairly broken before + # switch to ELF + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + freebsd-elf*) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + gnu*) + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + hpux9*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' + fi + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc* | ecpc* ) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + case `$CC -V` in + *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) + _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' + _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + ;; + *) # Version 6 and above use weak symbols + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + ;; + xl* | mpixl* | bgxl*) + # IBM XL 8.0 on PPC, with GNU ld + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + + lynxos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + m88k*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + + *nto* | *qnx*) + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + openbsd2*) + # C++ shared libraries are fairly broken + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + fi + output_verbose_link_cmd=func_echo_all + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + case $host in + osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; + *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; + esac + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + case $host in + osf3*) + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + ;; + *) + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ + $RM $lib.exp' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + case $host in + osf3*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + psos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' + if $CC --version | $GREP -v '^2\.7' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + fi + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ + '"$_LT_TAGVAR(old_archive_cmds, $1)" + _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ + '"$_LT_TAGVAR(reload_cmds, $1)" + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + vxworks*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) + test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + + _LT_TAGVAR(GCC, $1)="$GXX" + _LT_TAGVAR(LD, $1)="$LD" + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS + LDCXX=$LD + LD=$lt_save_LD + GCC=$lt_save_GCC + with_gnu_ld=$lt_save_with_gnu_ld + lt_cv_path_LDCXX=$lt_cv_path_LD + lt_cv_path_LD=$lt_save_path_LD + lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld + lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +fi # test "$_lt_caught_CXX_error" != yes + +AC_LANG_POP +])# _LT_LANG_CXX_CONFIG + + +# _LT_FUNC_STRIPNAME_CNF +# ---------------------- +# func_stripname_cnf prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# +# This function is identical to the (non-XSI) version of func_stripname, +# except this one can be used by m4 code that may be executed by configure, +# rather than the libtool script. +m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl +AC_REQUIRE([_LT_DECL_SED]) +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) +func_stripname_cnf () +{ + case ${2} in + .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; + esac +} # func_stripname_cnf +])# _LT_FUNC_STRIPNAME_CNF + +# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) +# --------------------------------- +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +m4_defun([_LT_SYS_HIDDEN_LIBDEPS], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl +# Dependencies to place before and after the object being linked: +_LT_TAGVAR(predep_objects, $1)= +_LT_TAGVAR(postdep_objects, $1)= +_LT_TAGVAR(predeps, $1)= +_LT_TAGVAR(postdeps, $1)= +_LT_TAGVAR(compiler_lib_search_path, $1)= + +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF +int a; +void foo (void) { a = 0; } +_LT_EOF +], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +_LT_EOF +], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer*4 a + a=0 + return + end +_LT_EOF +], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer a + a=0 + return + end +_LT_EOF +], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF +public class foo { + private int a; + public void bar (void) { + a = 0; + } +}; +_LT_EOF +], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF +package foo +func foo() { +} +_LT_EOF +]) + +_lt_libdeps_save_CFLAGS=$CFLAGS +case "$CC $CFLAGS " in #( +*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; +*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; +*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; +esac + +dnl Parse the compiler output and extract the necessary +dnl objects, libraries and library flags. +if AC_TRY_EVAL(ac_compile); then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + for p in `eval "$output_verbose_link_cmd"`; do + case ${prev}${p} in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test $p = "-L" || + test $p = "-R"; then + prev=$p + continue + fi + + # Expand the sysroot to ease extracting the directories later. + if test -z "$prev"; then + case $p in + -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; + -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; + -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; + esac + fi + case $p in + =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; + esac + if test "$pre_test_object_deps_done" = no; then + case ${prev} in + -L | -R) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then + _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" + else + _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$_LT_TAGVAR(postdeps, $1)"; then + _LT_TAGVAR(postdeps, $1)="${prev}${p}" + else + _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}" + fi + fi + prev= + ;; + + *.lto.$objext) ;; # Ignore GCC LTO objects + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test "$pre_test_object_deps_done" = no; then + if test -z "$_LT_TAGVAR(predep_objects, $1)"; then + _LT_TAGVAR(predep_objects, $1)="$p" + else + _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" + fi + else + if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then + _LT_TAGVAR(postdep_objects, $1)="$p" + else + _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling $1 test program" +fi + +$RM -f confest.$objext +CFLAGS=$_lt_libdeps_save_CFLAGS + +# PORTME: override above test on systems where it is broken +m4_if([$1], [CXX], +[case $host_os in +interix[[3-9]]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + _LT_TAGVAR(predep_objects,$1)= + _LT_TAGVAR(postdep_objects,$1)= + _LT_TAGVAR(postdeps,$1)= + ;; + +linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + if test "$solaris_use_stlport4" != yes; then + _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' + fi + ;; + esac + ;; + +solaris*) + case $cc_basename in + CC* | sunCC*) + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + # Adding this requires a known-good setup of shared libraries for + # Sun compiler versions before 5.6, else PIC objects from an old + # archive will be linked into the output, leading to subtle bugs. + if test "$solaris_use_stlport4" != yes; then + _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' + fi + ;; + esac + ;; +esac +]) + +case " $_LT_TAGVAR(postdeps, $1) " in +*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; +esac + _LT_TAGVAR(compiler_lib_search_dirs, $1)= +if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then + _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` +fi +_LT_TAGDECL([], [compiler_lib_search_dirs], [1], + [The directories searched by this compiler when creating a shared library]) +_LT_TAGDECL([], [predep_objects], [1], + [Dependencies to place before and after the objects being linked to + create a shared library]) +_LT_TAGDECL([], [postdep_objects], [1]) +_LT_TAGDECL([], [predeps], [1]) +_LT_TAGDECL([], [postdeps], [1]) +_LT_TAGDECL([], [compiler_lib_search_path], [1], + [The library search path used internally by the compiler when linking + a shared library]) +])# _LT_SYS_HIDDEN_LIBDEPS + + +# _LT_LANG_F77_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a Fortran 77 compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_F77_CONFIG], +[AC_LANG_PUSH(Fortran 77) +if test -z "$F77" || test "X$F77" = "Xno"; then + _lt_disable_F77=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the F77 compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_disable_F77" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC="$CC" + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${F77-"f77"} + CFLAGS=$FFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + GCC=$G77 + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)="$G77" + _LT_TAGVAR(LD, $1)="$LD" + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC="$lt_save_CC" + CFLAGS="$lt_save_CFLAGS" +fi # test "$_lt_disable_F77" != yes + +AC_LANG_POP +])# _LT_LANG_F77_CONFIG + + +# _LT_LANG_FC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for a Fortran compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_FC_CONFIG], +[AC_LANG_PUSH(Fortran) + +if test -z "$FC" || test "X$FC" = "Xno"; then + _lt_disable_FC=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for fc test sources. +ac_ext=${ac_fc_srcext-f} + +# Object file extension for compiled fc test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the FC compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_disable_FC" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC="$CC" + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${FC-"f95"} + CFLAGS=$FCFLAGS + compiler=$CC + GCC=$ac_cv_fc_compiler_gnu + + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu" + _LT_TAGVAR(LD, $1)="$LD" + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test "$_lt_disable_FC" != yes + +AC_LANG_POP +])# _LT_LANG_FC_CONFIG + + +# _LT_LANG_GCJ_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Java Compiler compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_GCJ_CONFIG], +[AC_REQUIRE([LT_PROG_GCJ])dnl +AC_LANG_SAVE + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GCJ-"gcj"} +CFLAGS=$GCJFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)="$LD" +_LT_CC_BASENAME([$compiler]) + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GCJ_CONFIG + + +# _LT_LANG_GO_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Go compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_GO_CONFIG], +[AC_REQUIRE([LT_PROG_GO])dnl +AC_LANG_SAVE + +# Source file extension for Go test sources. +ac_ext=go + +# Object file extension for compiled Go test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="package main; func main() { }" + +# Code to be used in simple link tests +lt_simple_link_test_code='package main; func main() { }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GOC-"gccgo"} +CFLAGS=$GOFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)="$LD" +_LT_CC_BASENAME([$compiler]) + +# Go did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GO_CONFIG + + +# _LT_LANG_RC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for the Windows resource compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_RC_CONFIG], +[AC_REQUIRE([LT_PROG_RC])dnl +AC_LANG_SAVE + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' + +# Code to be used in simple link tests +lt_simple_link_test_code="$lt_simple_compile_test_code" + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC= +CC=${RC-"windres"} +CFLAGS= +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) +_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + +if test -n "$compiler"; then + : + _LT_CONFIG($1) +fi + +GCC=$lt_save_GCC +AC_LANG_RESTORE +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_RC_CONFIG + + +# LT_PROG_GCJ +# ----------- +AC_DEFUN([LT_PROG_GCJ], +[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], + [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], + [AC_CHECK_TOOL(GCJ, gcj,) + test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS)])])[]dnl +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_GCJ], []) + + +# LT_PROG_GO +# ---------- +AC_DEFUN([LT_PROG_GO], +[AC_CHECK_TOOL(GOC, gccgo,) +]) + + +# LT_PROG_RC +# ---------- +AC_DEFUN([LT_PROG_RC], +[AC_CHECK_TOOL(RC, windres,) +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_RC], []) + + +# _LT_DECL_EGREP +# -------------- +# If we don't have a new enough Autoconf to choose the best grep +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_EGREP], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_REQUIRE([AC_PROG_FGREP])dnl +test -z "$GREP" && GREP=grep +_LT_DECL([], [GREP], [1], [A grep program that handles long lines]) +_LT_DECL([], [EGREP], [1], [An ERE matcher]) +_LT_DECL([], [FGREP], [1], [A literal string matcher]) +dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too +AC_SUBST([GREP]) +]) + + +# _LT_DECL_OBJDUMP +# -------------- +# If we don't have a new enough Autoconf to choose the best objdump +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_OBJDUMP], +[AC_CHECK_TOOL(OBJDUMP, objdump, false) +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) +AC_SUBST([OBJDUMP]) +]) + +# _LT_DECL_DLLTOOL +# ---------------- +# Ensure DLLTOOL variable is set. +m4_defun([_LT_DECL_DLLTOOL], +[AC_CHECK_TOOL(DLLTOOL, dlltool, false) +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program]) +AC_SUBST([DLLTOOL]) +]) + +# _LT_DECL_SED +# ------------ +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +m4_defun([_LT_DECL_SED], +[AC_PROG_SED +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" +_LT_DECL([], [SED], [1], [A sed program that does not truncate output]) +_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], + [Sed that helps us avoid accidentally triggering echo(1) options like -n]) +])# _LT_DECL_SED + +m4_ifndef([AC_PROG_SED], [ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # + +m4_defun([AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +IFS=$as_save_IFS +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f $lt_ac_sed && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test $lt_ac_count -gt 10 && break + lt_ac_count=`expr $lt_ac_count + 1` + if test $lt_ac_count -gt $lt_ac_max; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_SUBST([SED]) +AC_MSG_RESULT([$SED]) +])#AC_PROG_SED +])#m4_ifndef + +# Old name: +AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_SED], []) + + +# _LT_CHECK_SHELL_FEATURES +# ------------------------ +# Find out whether the shell is Bourne or XSI compatible, +# or has some other useful features. +m4_defun([_LT_CHECK_SHELL_FEATURES], +[AC_MSG_CHECKING([whether the shell understands some XSI constructs]) +# Try some XSI features +xsi_shell=no +( _lt_dummy="a/b/c" + test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ + = c,a/b,b/c, \ + && eval 'test $(( 1 + 1 )) -eq 2 \ + && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ + && xsi_shell=yes +AC_MSG_RESULT([$xsi_shell]) +_LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell']) + +AC_MSG_CHECKING([whether the shell understands "+="]) +lt_shell_append=no +( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \ + >/dev/null 2>&1 \ + && lt_shell_append=yes +AC_MSG_RESULT([$lt_shell_append]) +_LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append']) + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi +_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac +_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl +_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl +])# _LT_CHECK_SHELL_FEATURES + + +# _LT_PROG_FUNCTION_REPLACE (FUNCNAME, REPLACEMENT-BODY) +# ------------------------------------------------------ +# In `$cfgfile', look for function FUNCNAME delimited by `^FUNCNAME ()$' and +# '^} FUNCNAME ', and replace its body with REPLACEMENT-BODY. +m4_defun([_LT_PROG_FUNCTION_REPLACE], +[dnl { +sed -e '/^$1 ()$/,/^} # $1 /c\ +$1 ()\ +{\ +m4_bpatsubsts([$2], [$], [\\], [^\([ ]\)], [\\\1]) +} # Extended-shell $1 implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: +]) + + +# _LT_PROG_REPLACE_SHELLFNS +# ------------------------- +# Replace existing portable implementations of several shell functions with +# equivalent extended shell implementations where those features are available.. +m4_defun([_LT_PROG_REPLACE_SHELLFNS], +[if test x"$xsi_shell" = xyes; then + _LT_PROG_FUNCTION_REPLACE([func_dirname], [dnl + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac]) + + _LT_PROG_FUNCTION_REPLACE([func_basename], [dnl + func_basename_result="${1##*/}"]) + + _LT_PROG_FUNCTION_REPLACE([func_dirname_and_basename], [dnl + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac + func_basename_result="${1##*/}"]) + + _LT_PROG_FUNCTION_REPLACE([func_stripname], [dnl + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary parameter first. + func_stripname_result=${3} + func_stripname_result=${func_stripname_result#"${1}"} + func_stripname_result=${func_stripname_result%"${2}"}]) + + _LT_PROG_FUNCTION_REPLACE([func_split_long_opt], [dnl + func_split_long_opt_name=${1%%=*} + func_split_long_opt_arg=${1#*=}]) + + _LT_PROG_FUNCTION_REPLACE([func_split_short_opt], [dnl + func_split_short_opt_arg=${1#??} + func_split_short_opt_name=${1%"$func_split_short_opt_arg"}]) + + _LT_PROG_FUNCTION_REPLACE([func_lo2o], [dnl + case ${1} in + *.lo) func_lo2o_result=${1%.lo}.${objext} ;; + *) func_lo2o_result=${1} ;; + esac]) + + _LT_PROG_FUNCTION_REPLACE([func_xform], [ func_xform_result=${1%.*}.lo]) + + _LT_PROG_FUNCTION_REPLACE([func_arith], [ func_arith_result=$(( $[*] ))]) + + _LT_PROG_FUNCTION_REPLACE([func_len], [ func_len_result=${#1}]) +fi + +if test x"$lt_shell_append" = xyes; then + _LT_PROG_FUNCTION_REPLACE([func_append], [ eval "${1}+=\\${2}"]) + + _LT_PROG_FUNCTION_REPLACE([func_append_quoted], [dnl + func_quote_for_eval "${2}" +dnl m4 expansion turns \\\\ into \\, and then the shell eval turns that into \ + eval "${1}+=\\\\ \\$func_quote_for_eval_result"]) + + # Save a `func_append' function call where possible by direct use of '+=' + sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +else + # Save a `func_append' function call even when '+=' is not available + sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +fi + +if test x"$_lt_function_replace_fail" = x":"; then + AC_MSG_WARN([Unable to substitute extended shell functions in $ofile]) +fi +]) + +# _LT_PATH_CONVERSION_FUNCTIONS +# ----------------------------- +# Determine which file name conversion functions should be used by +# func_to_host_file (and, implicitly, by func_to_host_path). These are needed +# for certain cross-compile configurations and native mingw. +m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_MSG_CHECKING([how to convert $build file names to $host format]) +AC_CACHE_VAL(lt_cv_to_host_file_cmd, +[case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac +]) +to_host_file_cmd=$lt_cv_to_host_file_cmd +AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) +_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], + [0], [convert $build file names to $host format])dnl + +AC_MSG_CHECKING([how to convert $build file names to toolchain format]) +AC_CACHE_VAL(lt_cv_to_tool_file_cmd, +[#assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac +]) +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) +_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], + [0], [convert $build files to toolchain format])dnl +])# _LT_PATH_CONVERSION_FUNCTIONS + +# Helper functions for option handling. -*- Autoconf -*- +# +# Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 7 ltoptions.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) + + +# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) +# ------------------------------------------ +m4_define([_LT_MANGLE_OPTION], +[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) + + +# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) +# --------------------------------------- +# Set option OPTION-NAME for macro MACRO-NAME, and if there is a +# matching handler defined, dispatch to it. Other OPTION-NAMEs are +# saved as a flag. +m4_define([_LT_SET_OPTION], +[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl +m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), + _LT_MANGLE_DEFUN([$1], [$2]), + [m4_warning([Unknown $1 option `$2'])])[]dnl +]) + + +# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) +# ------------------------------------------------------------ +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +m4_define([_LT_IF_OPTION], +[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) + + +# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) +# ------------------------------------------------------- +# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME +# are set. +m4_define([_LT_UNLESS_OPTIONS], +[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), + [m4_define([$0_found])])])[]dnl +m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 +])[]dnl +]) + + +# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) +# ---------------------------------------- +# OPTION-LIST is a space-separated list of Libtool options associated +# with MACRO-NAME. If any OPTION has a matching handler declared with +# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about +# the unknown option and exit. +m4_defun([_LT_SET_OPTIONS], +[# Set options +m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [_LT_SET_OPTION([$1], _LT_Option)]) + +m4_if([$1],[LT_INIT],[ + dnl + dnl Simply set some default values (i.e off) if boolean options were not + dnl specified: + _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no + ]) + _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no + ]) + dnl + dnl If no reference was made to various pairs of opposing options, then + dnl we run the default mode handler for the pair. For example, if neither + dnl `shared' nor `disable-shared' was passed, we enable building of shared + dnl archives by default: + _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) + _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], + [_LT_ENABLE_FAST_INSTALL]) + ]) +])# _LT_SET_OPTIONS + + + +# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) +# ----------------------------------------- +m4_define([_LT_MANGLE_DEFUN], +[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) + + +# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) +# ----------------------------------------------- +m4_define([LT_OPTION_DEFINE], +[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl +])# LT_OPTION_DEFINE + + +# dlopen +# ------ +LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes +]) + +AU_DEFUN([AC_LIBTOOL_DLOPEN], +[_LT_SET_OPTION([LT_INIT], [dlopen]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the `dlopen' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) + + +# win32-dll +# --------- +# Declare package support for building win32 dll's. +LT_OPTION_DEFINE([LT_INIT], [win32-dll], +[enable_win32_dll=yes + +case $host in +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; +esac + +test -z "$AS" && AS=as +_LT_DECL([], [AS], [1], [Assembler program])dnl + +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl + +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl +])# win32-dll + +AU_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +_LT_SET_OPTION([LT_INIT], [win32-dll]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the `win32-dll' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) + + +# _LT_ENABLE_SHARED([DEFAULT]) +# ---------------------------- +# implement the --enable-shared flag, and supports the `shared' and +# `disable-shared' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +m4_define([_LT_ENABLE_SHARED], +[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([shared], + [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) + + _LT_DECL([build_libtool_libs], [enable_shared], [0], + [Whether or not to build shared libraries]) +])# _LT_ENABLE_SHARED + +LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) +]) + +AC_DEFUN([AC_DISABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], [disable-shared]) +]) + +AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_SHARED], []) +dnl AC_DEFUN([AM_DISABLE_SHARED], []) + + + +# _LT_ENABLE_STATIC([DEFAULT]) +# ---------------------------- +# implement the --enable-static flag, and support the `static' and +# `disable-static' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +m4_define([_LT_ENABLE_STATIC], +[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([static], + [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_static=]_LT_ENABLE_STATIC_DEFAULT) + + _LT_DECL([build_old_libs], [enable_static], [0], + [Whether or not to build static libraries]) +])# _LT_ENABLE_STATIC + +LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) +]) + +AC_DEFUN([AC_DISABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], [disable-static]) +]) + +AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_STATIC], []) +dnl AC_DEFUN([AM_DISABLE_STATIC], []) + + + +# _LT_ENABLE_FAST_INSTALL([DEFAULT]) +# ---------------------------------- +# implement the --enable-fast-install flag, and support the `fast-install' +# and `disable-fast-install' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +m4_define([_LT_ENABLE_FAST_INSTALL], +[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([fast-install], + [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) + +_LT_DECL([fast_install], [enable_fast_install], [0], + [Whether or not to optimize for fast installation])dnl +])# _LT_ENABLE_FAST_INSTALL + +LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) + +# Old names: +AU_DEFUN([AC_ENABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the `fast-install' option into LT_INIT's first parameter.]) +]) + +AU_DEFUN([AC_DISABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], [disable-fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the `disable-fast-install' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) +dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) + + +# _LT_WITH_PIC([MODE]) +# -------------------- +# implement the --with-pic flag, and support the `pic-only' and `no-pic' +# LT_INIT options. +# MODE is either `yes' or `no'. If omitted, it defaults to `both'. +m4_define([_LT_WITH_PIC], +[AC_ARG_WITH([pic], + [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for lt_pkg in $withval; do + IFS="$lt_save_ifs" + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [pic_mode=default]) + +test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) + +_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl +])# _LT_WITH_PIC + +LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) + +# Old name: +AU_DEFUN([AC_LIBTOOL_PICMODE], +[_LT_SET_OPTION([LT_INIT], [pic-only]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the `pic-only' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) + + +m4_define([_LTDL_MODE], []) +LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], + [m4_define([_LTDL_MODE], [nonrecursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [recursive], + [m4_define([_LTDL_MODE], [recursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [subproject], + [m4_define([_LTDL_MODE], [subproject])]) + +m4_define([_LTDL_TYPE], []) +LT_OPTION_DEFINE([LTDL_INIT], [installable], + [m4_define([_LTDL_TYPE], [installable])]) +LT_OPTION_DEFINE([LTDL_INIT], [convenience], + [m4_define([_LTDL_TYPE], [convenience])]) + +# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- +# +# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 6 ltsugar.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) + + +# lt_join(SEP, ARG1, [ARG2...]) +# ----------------------------- +# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their +# associated separator. +# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier +# versions in m4sugar had bugs. +m4_define([lt_join], +[m4_if([$#], [1], [], + [$#], [2], [[$2]], + [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) +m4_define([_lt_join], +[m4_if([$#$2], [2], [], + [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) + + +# lt_car(LIST) +# lt_cdr(LIST) +# ------------ +# Manipulate m4 lists. +# These macros are necessary as long as will still need to support +# Autoconf-2.59 which quotes differently. +m4_define([lt_car], [[$1]]) +m4_define([lt_cdr], +[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], + [$#], 1, [], + [m4_dquote(m4_shift($@))])]) +m4_define([lt_unquote], $1) + + +# lt_append(MACRO-NAME, STRING, [SEPARATOR]) +# ------------------------------------------ +# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. +# Note that neither SEPARATOR nor STRING are expanded; they are appended +# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). +# No SEPARATOR is output if MACRO-NAME was previously undefined (different +# than defined and empty). +# +# This macro is needed until we can rely on Autoconf 2.62, since earlier +# versions of m4sugar mistakenly expanded SEPARATOR but not STRING. +m4_define([lt_append], +[m4_define([$1], + m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) + + + +# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) +# ---------------------------------------------------------- +# Produce a SEP delimited list of all paired combinations of elements of +# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list +# has the form PREFIXmINFIXSUFFIXn. +# Needed until we can rely on m4_combine added in Autoconf 2.62. +m4_define([lt_combine], +[m4_if(m4_eval([$# > 3]), [1], + [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl +[[m4_foreach([_Lt_prefix], [$2], + [m4_foreach([_Lt_suffix], + ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, + [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) + + +# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) +# ----------------------------------------------------------------------- +# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited +# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. +m4_define([lt_if_append_uniq], +[m4_ifdef([$1], + [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], + [lt_append([$1], [$2], [$3])$4], + [$5])], + [lt_append([$1], [$2], [$3])$4])]) + + +# lt_dict_add(DICT, KEY, VALUE) +# ----------------------------- +m4_define([lt_dict_add], +[m4_define([$1($2)], [$3])]) + + +# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) +# -------------------------------------------- +m4_define([lt_dict_add_subkey], +[m4_define([$1($2:$3)], [$4])]) + + +# lt_dict_fetch(DICT, KEY, [SUBKEY]) +# ---------------------------------- +m4_define([lt_dict_fetch], +[m4_ifval([$3], + m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), + m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) + + +# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) +# ----------------------------------------------------------------- +m4_define([lt_if_dict_fetch], +[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], + [$5], + [$6])]) + + +# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) +# -------------------------------------------------------------- +m4_define([lt_dict_filter], +[m4_if([$5], [], [], + [lt_join(m4_quote(m4_default([$4], [[, ]])), + lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), + [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl +]) + +# ltversion.m4 -- version numbers -*- Autoconf -*- +# +# Copyright (C) 2004 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# @configure_input@ + +# serial 3337 ltversion.m4 +# This file is part of GNU Libtool + +m4_define([LT_PACKAGE_VERSION], [2.4.2]) +m4_define([LT_PACKAGE_REVISION], [1.3337]) + +AC_DEFUN([LTVERSION_VERSION], +[macro_version='2.4.2' +macro_revision='1.3337' +_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) +_LT_DECL(, macro_revision, 0) +]) + +# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- +# +# Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004. +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 5 lt~obsolete.m4 + +# These exist entirely to fool aclocal when bootstrapping libtool. +# +# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) +# which have later been changed to m4_define as they aren't part of the +# exported API, or moved to Autoconf or Automake where they belong. +# +# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN +# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us +# using a macro with the same name in our local m4/libtool.m4 it'll +# pull the old libtool.m4 in (it doesn't see our shiny new m4_define +# and doesn't know about Autoconf macros at all.) +# +# So we provide this file, which has a silly filename so it's always +# included after everything else. This provides aclocal with the +# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything +# because those macros already exist, or will be overwritten later. +# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. +# +# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. +# Yes, that means every name once taken will need to remain here until +# we give up compatibility with versions before 1.7, at which point +# we need to keep only those names which we still refer to. + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) + +m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) +m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) +m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) +m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) +m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) +m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) +m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) +m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) +m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) +m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) +m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) +m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) +m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) +m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) +m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) +m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) +m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) +m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) +m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) +m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) +m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) +m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) +m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) +m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) +m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) +m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) +m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) +m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) +m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) +m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) +m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) +m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) +m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) +m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) +m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) +m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) +m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) +m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) +m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) +m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) +m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) +m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) +m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) +m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) +m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) +m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) +m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) +m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) +m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) +m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) + diff --git a/acx_nlnetlabs.m4 b/acx_nlnetlabs.m4 new file mode 100644 index 00000000000..e90c81ea02a --- /dev/null +++ b/acx_nlnetlabs.m4 @@ -0,0 +1,1370 @@ +# acx_nlnetlabs.m4 - common macros for configure checks +# Copyright 2009, Wouter Wijngaards, NLnet Labs. +# BSD licensed. +# +# Version 21 +# 2012-02-09 Fix AHX_MEMCMP_BROKEN with undef in compat/memcmp.h. +# 2012-01-20 Fix COMPILER_FLAGS_UNBOUND for gcc 4.6.2 assigned-not-used-warns. +# 2011-12-05 Fix getaddrinfowithincludes on windows with fedora16 mingw32-gcc. +# Fix ACX_MALLOC for redefined malloc error. +# Fix GETADDRINFO_WITH_INCLUDES to add -lws2_32 +# 2011-11-10 Fix FLTO test to not drop a.out in current directory. +# 2011-11-01 Fix FLTO test for llvm on Lion. +# 2011-08-01 Fix nonblock test (broken at v13). +# 2011-08-01 Fix autoconf 2.68 warnings +# 2011-06-23 Add ACX_CHECK_FLTO to check -flto. +# 2010-08-16 Fix FLAG_OMITTED for AS_TR_CPP changes in autoconf-2.66. +# 2010-07-02 Add check for ss_family (for minix). +# 2010-04-26 Fix to use CPPFLAGS for CHECK_COMPILER_FLAGS. +# 2010-03-01 Fix RPATH using CONFIG_COMMANDS to run at the very end. +# 2010-02-18 WITH_SSL outputs the LIBSSL_LDFLAGS, LIBS, CPPFLAGS seperate, -ldl +# 2010-02-01 added ACX_CHECK_MEMCMP_SIGNED, AHX_MEMCMP_BROKEN +# 2010-01-20 added AHX_COONFIG_STRLCAT +# 2009-07-14 U_CHAR detection improved for windows crosscompile. +# added ACX_FUNC_MALLOC +# fixup some #if to #ifdef +# NONBLOCKING test for mingw crosscompile. +# 2009-07-13 added ACX_WITH_SSL_OPTIONAL +# 2009-07-03 fixup LDFLAGS for empty ssl dir. +# +# Automates some of the checking constructs. Aims at portability for POSIX. +# Documentation for functions is below. +# +# the following macro's are provided in this file: +# (see below for details on each macro). +# +# ACX_ESCAPE_BACKSLASH - escape backslashes in var for C-preproc. +# ACX_RSRC_VERSION - create windows resource version number. +# ACX_CHECK_COMPILER_FLAG - see if cc supports a flag. +# ACX_CHECK_ERROR_FLAGS - see which flag is -werror (used below). +# ACX_CHECK_COMPILER_FLAG_NEEDED - see if flags make the code compile cleanly. +# ACX_DEPFLAG - find cc dependency flags. +# ACX_DETERMINE_EXT_FLAGS_UNBOUND - find out which flags enable BSD and POSIX. +# ACX_CHECK_FORMAT_ATTRIBUTE - find cc printf format syntax. +# ACX_CHECK_UNUSED_ATTRIBUTE - find cc variable unused syntax. +# ACX_CHECK_FLTO - see if cc supports -flto and use it if so. +# ACX_LIBTOOL_C_ONLY - create libtool for C only, improved. +# ACX_TYPE_U_CHAR - u_char type. +# ACX_TYPE_RLIM_T - rlim_t type. +# ACX_TYPE_SOCKLEN_T - socklen_t type. +# ACX_TYPE_IN_ADDR_T - in_addr_t type. +# ACX_TYPE_IN_PORT_T - in_port_t type. +# ACX_ARG_RPATH - add --disable-rpath option. +# ACX_WITH_SSL - add --with-ssl option, link -lcrypto. +# ACX_WITH_SSL_OPTIONAL - add --with-ssl option, link -lcrypto, +# where --without-ssl is also accepted +# ACX_LIB_SSL - setup to link -lssl. +# ACX_SYS_LARGEFILE - improved sys_largefile, fseeko, >2G files. +# ACX_CHECK_GETADDRINFO_WITH_INCLUDES - find getaddrinfo, portably. +# ACX_FUNC_DEPRECATED - see if func is deprecated. +# ACX_CHECK_NONBLOCKING_BROKEN - see if nonblocking sockets really work. +# ACX_MKDIR_ONE_ARG - determine mkdir(2) number of arguments. +# ACX_FUNC_IOCTLSOCKET - find ioctlsocket, portably. +# ACX_FUNC_MALLOC - check malloc, define replacement . +# AHX_CONFIG_FORMAT_ATTRIBUTE - config.h text for format. +# AHX_CONFIG_UNUSED_ATTRIBUTE - config.h text for unused. +# AHX_CONFIG_FSEEKO - define fseeko, ftello fallback. +# AHX_CONFIG_RAND_MAX - define RAND_MAX if needed. +# AHX_CONFIG_MAXHOSTNAMELEN - define MAXHOSTNAMELEN if needed. +# AHX_CONFIG_IPV6_MIN_MTU - define IPV6_MIN_MTU if needed. +# AHX_CONFIG_SNPRINTF - snprintf compat prototype +# AHX_CONFIG_INET_PTON - inet_pton compat prototype +# AHX_CONFIG_INET_NTOP - inet_ntop compat prototype +# AHX_CONFIG_INET_ATON - inet_aton compat prototype +# AHX_CONFIG_MEMMOVE - memmove compat prototype +# AHX_CONFIG_STRLCAT - strlcat compat prototype +# AHX_CONFIG_STRLCPY - strlcpy compat prototype +# AHX_CONFIG_GMTIME_R - gmtime_r compat prototype +# AHX_CONFIG_W32_SLEEP - w32 compat for sleep +# AHX_CONFIG_W32_USLEEP - w32 compat for usleep +# AHX_CONFIG_W32_RANDOM - w32 compat for random +# AHX_CONFIG_W32_SRANDOM - w32 compat for srandom +# AHX_CONFIG_W32_FD_SET_T - w32 detection of FD_SET_T. +# ACX_CFLAGS_STRIP - strip one flag from CFLAGS +# ACX_STRIP_EXT_FLAGS - strip extension flags from CFLAGS +# AHX_CONFIG_FLAG_OMITTED - define omitted flag +# AHX_CONFIG_FLAG_EXT - define omitted extension flag +# AHX_CONFIG_EXT_FLAGS - define the stripped extension flags +# ACX_CHECK_MEMCMP_SIGNED - check if memcmp uses signed characters. +# AHX_MEMCMP_BROKEN - replace memcmp func for CHECK_MEMCMP_SIGNED. +# ACX_CHECK_SS_FAMILY - check for sockaddr_storage.ss_family +# + +dnl Escape backslashes as \\, for C:\ paths, for the C preprocessor defines. +dnl for example, ACX_ESCAPE_BACKSLASH($from_var, to_var) +dnl $1: the text to change. +dnl $2: the result. +AC_DEFUN([ACX_ESCAPE_BACKSLASH], [$2="`echo $1 | sed -e 's/\\\\/\\\\\\\\/g'`" +]) + +dnl Calculate comma separated windows-resource numbers from package version. +dnl Picks the first three(,0) or four numbers out of the name. +dnl $1: variable for the result +AC_DEFUN([ACX_RSRC_VERSION], +[$1=[`echo $PACKAGE_VERSION | sed -e 's/^[^0-9]*\([0-9]\)[^0-9]*\([0-9]\)[^0-9]*\([0-9]\)[^0-9]*\([0-9]\).*$/\1,\2,\3,\4/' -e 's/^[^0-9]*\([0-9]\)[^0-9]*\([0-9]\)[^0-9]*\([0-9]\)[^0-9]*$/\1,\2,\3,0/' `] +]) + +dnl Routine to help check for compiler flags. +dnl Checks if the compiler will accept the flag. +dnl $1: the flag without a - in front, so g to check -g. +dnl $2: executed if yes +dnl $3: executed if no +AC_DEFUN([ACX_CHECK_COMPILER_FLAG], +[ +AC_REQUIRE([AC_PROG_CC]) +AC_MSG_CHECKING(whether $CC supports -$1) +cache=`echo $1 | sed 'y%.=/+-%___p_%'` +AC_CACHE_VAL(cv_prog_cc_flag_$cache, +[ +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -$1 -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c +]) +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +AC_MSG_RESULT(yes) +: +$2 +else +AC_MSG_RESULT(no) +: +$3 +fi +]) + +dnl setup flags for ACX_CHECK_COMPILER_FLAG_NEEDED +dnl ERRFLAG: result, compiler flag to turn warnings into errors +AC_DEFUN([ACX_CHECK_ERROR_FLAGS], +[ +ACX_CHECK_COMPILER_FLAG(Werror, [ERRFLAG="-Werror"], [ERRFLAG="-errwarn"]) +ACX_CHECK_COMPILER_FLAG(Wall, [ERRFLAG="$ERRFLAG -Wall"], + [ERRFLAG="$ERRFLAG -errfmt"]) +]) + +dnl Routine to help check for needed compiler flags. +dnl $1: flags for CC +dnl $2: the includes and code +dnl $3: if the given code only compiles with the flag, execute argument 3 +dnl $4: if the given code compiles without the flag, execute argument 4 +dnl $5: with and without flag the compile fails, execute argument 5. +AC_DEFUN([ACX_CHECK_COMPILER_FLAG_NEEDED], +[ +AC_REQUIRE([AC_PROG_CC]) +AC_REQUIRE([ACX_CHECK_ERROR_FLAGS]) +AC_MSG_CHECKING(whether we need $1 as a flag for $CC) +cache=AS_TR_SH($1) +dnl cache=`echo $1 | sed 'y%.=/+- %___p__%'` +AC_CACHE_VAL(cv_prog_cc_flag_needed_$cache, +[ +echo '$2' > conftest.c +echo 'void f(){}' >>conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=no" +else +[ +if test -z "`$CC $CPPFLAGS $CFLAGS $1 $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=yes" +else +eval "cv_prog_cc_flag_needed_$cache=fail" +#echo 'Test with flag fails too!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS $1 $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS $1 $ERRFLAG -c conftest.c 2>&1` +#exit 1 +fi +] +fi +rm -f conftest conftest.c conftest.o +]) +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = yes"; then +AC_MSG_RESULT(yes) +: +$3 +else +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = no"; then +AC_MSG_RESULT(no) +#echo 'Test with flag is no!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS $1 $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS $1 $ERRFLAG -c conftest.c 2>&1` +#exit 1 +: +$4 +else +AC_MSG_RESULT(failed) +: +$5 +fi +fi +]) + +dnl Check for CC dependency flag +dnl DEPFLAG: set to flag that generates dependencies. +AC_DEFUN([ACX_DEPFLAG], +[ +AC_MSG_CHECKING([$CC dependency flag]) +echo 'void f(){}' >conftest.c +if test "`$CC -MM conftest.c 2>&1`" = "conftest.o: conftest.c"; then + DEPFLAG="-MM" +else + if test "`$CC -xM1 conftest.c 2>&1`" = "conftest.o: conftest.c"; then + DEPFLAG="-xM1" + else + DEPFLAG="-MM" # dunno do something + fi +fi +AC_MSG_RESULT($DEPFLAG) +rm -f conftest.c +AC_SUBST(DEPFLAG) +]) + +dnl Determine flags that gives POSIX and BSD functionality. +dnl CFLAGS is modified for the result. +AC_DEFUN([ACX_DETERMINE_EXT_FLAGS_UNBOUND], +[ +ACX_CHECK_COMPILER_FLAG(std=c99, [C99FLAG="-std=c99"]) +ACX_CHECK_COMPILER_FLAG(xc99, [C99FLAG="-xc99"]) + +AC_CHECK_HEADERS([getopt.h time.h],,, [AC_INCLUDES_DEFAULT]) + +ACX_CHECK_COMPILER_FLAG_NEEDED($C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_ALL_SOURCE, +[ +#include "confdefs.h" +#include +#include +#include +#ifdef HAVE_TIME_H +#include +#endif +#include +#include +#ifdef HAVE_GETOPT_H +#include +#endif + +int test() { + int a; + char **opts = NULL; + struct timeval tv; + char *t; + time_t time = 0; + char *buf = NULL; + const char* str = NULL; + struct msghdr msg; + msg.msg_control = 0; + t = ctime_r(&time, buf); + tv.tv_usec = 10; + srandom(32); + a = getopt(2, opts, "a"); + a = isascii(32); + str = gai_strerror(0); + if(str && t && tv.tv_usec && msg.msg_control) + a = 0; + return a; +} +], [CFLAGS="$CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_ALL_SOURCE"]) + +ACX_CHECK_COMPILER_FLAG_NEEDED($C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE, +[ +#include "confdefs.h" +#include +#include +#include +#ifdef HAVE_TIME_H +#include +#endif +#include +#include +#ifdef HAVE_GETOPT_H +#include +#endif + +int test() { + int a; + char **opts = NULL; + struct timeval tv; + char *t; + time_t time = 0; + char *buf = NULL; + const char* str = NULL; + struct msghdr msg; + msg.msg_control = 0; + t = ctime_r(&time, buf); + tv.tv_usec = 10; + srandom(32); + a = getopt(2, opts, "a"); + a = isascii(32); + str = gai_strerror(0); + if(str && t && tv.tv_usec && msg.msg_control) + a = 0; + return a; +} +], [CFLAGS="$CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE"]) + +ACX_CHECK_COMPILER_FLAG_NEEDED($C99FLAG, +[ +#include +#include +int test() { + int a = 0; + return a; +} +], [CFLAGS="$CFLAGS $C99FLAG"]) + +ACX_CHECK_COMPILER_FLAG_NEEDED(-D_BSD_SOURCE, +[ +#include + +int test() { + int a; + a = isascii(32); + return a; +} +], [CFLAGS="$CFLAGS -D_BSD_SOURCE"]) + +ACX_CHECK_COMPILER_FLAG_NEEDED(-D_GNU_SOURCE, +[ +#include + +int test() { + struct in6_pktinfo inf; + int a = (int)sizeof(inf); + return a; +} +], [CFLAGS="$CFLAGS -D_GNU_SOURCE"]) + +# check again for GNU_SOURCE for setresgid. May fail if setresgid +# is not available at all. -D_FRSRESGID is to make this check unique. +# otherwise we would get the previous cached result. +ACX_CHECK_COMPILER_FLAG_NEEDED(-D_GNU_SOURCE -D_FRSRESGID, +[ +#include + +int test() { + int a = setresgid(0,0,0); + a = setresuid(0,0,0); + return a; +} +], [CFLAGS="$CFLAGS -D_GNU_SOURCE"]) + +ACX_CHECK_COMPILER_FLAG_NEEDED(-D_POSIX_C_SOURCE=200112, +[ +#include "confdefs.h" +#ifdef HAVE_TIME_H +#include +#endif +#include + +int test() { + int a = 0; + char *t; + time_t time = 0; + char *buf = NULL; + const char* str = NULL; + t = ctime_r(&time, buf); + str = gai_strerror(0); + if(t && str) + a = 0; + return a; +} +], [CFLAGS="$CFLAGS -D_POSIX_C_SOURCE=200112"]) + +ACX_CHECK_COMPILER_FLAG_NEEDED(-D__EXTENSIONS__, +[ +#include "confdefs.h" +#include +#include +#include +#ifdef HAVE_TIME_H +#include +#endif +#include +#ifdef HAVE_GETOPT_H +#include +#endif + +int test() { + int a; + char **opts = NULL; + struct timeval tv; + tv.tv_usec = 10; + srandom(32); + a = getopt(2, opts, "a"); + a = isascii(32); + if(tv.tv_usec) + a = 0; + return a; +} +], [CFLAGS="$CFLAGS -D__EXTENSIONS__"]) + +])dnl End of ACX_DETERMINE_EXT_FLAGS_UNBOUND + +dnl Check if CC supports -flto. +dnl in a way that supports clang and suncc (that flag does something else, +dnl but fails to link). It sets it in CFLAGS if it works. +AC_DEFUN([ACX_CHECK_FLTO], +[AC_MSG_CHECKING([if $CC supports -flto]) +BAKCFLAGS="$CFLAGS" +CFLAGS="$CFLAGS -flto" +AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])], [ + if $CC $CFLAGS -o conftest conftest.c 2>&1 | grep "warning: no debug symbols in executable" >/dev/null; then + CFLAGS="$BAKCFLAGS" + AC_MSG_RESULT(no) + else + AC_MSG_RESULT(yes) + fi + rm -f conftest conftest.c conftest.o +], [CFLAGS="$BAKCFLAGS" ; AC_MSG_RESULT(no)]) +]) + +dnl Check the printf-format attribute (if any) +dnl result in HAVE_ATTR_FORMAT. +dnl Make sure you also include the AHX_CONFIG_FORMAT_ATTRIBUTE. +AC_DEFUN([ACX_CHECK_FORMAT_ATTRIBUTE], +[AC_REQUIRE([AC_PROG_CC]) +AC_MSG_CHECKING(whether the C compiler (${CC-cc}) accepts the "format" attribute) +AC_CACHE_VAL(ac_cv_c_format_attribute, +[ac_cv_c_format_attribute=no +AC_TRY_COMPILE( +[#include +void f (char *format, ...) __attribute__ ((format (printf, 1, 2))); +void (*pf) (char *format, ...) __attribute__ ((format (printf, 1, 2))); +], [ + f ("%s", "str"); +], +[ac_cv_c_format_attribute="yes"], +[ac_cv_c_format_attribute="no"]) +]) + +AC_MSG_RESULT($ac_cv_c_format_attribute) +if test $ac_cv_c_format_attribute = yes; then + AC_DEFINE(HAVE_ATTR_FORMAT, 1, [Whether the C compiler accepts the "format" attribute]) +fi +])dnl End of ACX_CHECK_FORMAT_ATTRIBUTE + +dnl Setup ATTR_FORMAT config.h parts. +dnl make sure you call ACX_CHECK_FORMAT_ATTRIBUTE also. +AC_DEFUN([AHX_CONFIG_FORMAT_ATTRIBUTE], +[ +#ifdef HAVE_ATTR_FORMAT +# define ATTR_FORMAT(archetype, string_index, first_to_check) \ + __attribute__ ((format (archetype, string_index, first_to_check))) +#else /* !HAVE_ATTR_FORMAT */ +# define ATTR_FORMAT(archetype, string_index, first_to_check) /* empty */ +#endif /* !HAVE_ATTR_FORMAT */ +]) + +dnl Check how to mark function arguments as unused. +dnl result in HAVE_ATTR_UNUSED. +dnl Make sure you include AHX_CONFIG_UNUSED_ATTRIBUTE also. +AC_DEFUN([ACX_CHECK_UNUSED_ATTRIBUTE], +[AC_REQUIRE([AC_PROG_CC]) +AC_MSG_CHECKING(whether the C compiler (${CC-cc}) accepts the "unused" attribute) +AC_CACHE_VAL(ac_cv_c_unused_attribute, +[ac_cv_c_unused_attribute=no +AC_TRY_COMPILE( +[#include +void f (char *u __attribute__((unused))); +], [ + f ("x"); +], +[ac_cv_c_unused_attribute="yes"], +[ac_cv_c_unused_attribute="no"]) +]) + +dnl Setup ATTR_UNUSED config.h parts. +dnl make sure you call ACX_CHECK_UNUSED_ATTRIBUTE also. +AC_DEFUN([AHX_CONFIG_UNUSED_ATTRIBUTE], +[ +#if defined(DOXYGEN) +# define ATTR_UNUSED(x) x +#elif defined(__cplusplus) +# define ATTR_UNUSED(x) +#elif defined(HAVE_ATTR_UNUSED) +# define ATTR_UNUSED(x) x __attribute__((unused)) +#else /* !HAVE_ATTR_UNUSED */ +# define ATTR_UNUSED(x) x +#endif /* !HAVE_ATTR_UNUSED */ +]) + +AC_MSG_RESULT($ac_cv_c_unused_attribute) +if test $ac_cv_c_unused_attribute = yes; then + AC_DEFINE(HAVE_ATTR_UNUSED, 1, [Whether the C compiler accepts the "unused" attribute]) +fi +])dnl + +dnl Pre-fun for ACX_LIBTOOL_C_ONLY +AC_DEFUN([ACX_LIBTOOL_C_PRE], [ +# skip these tests, we do not need them. +AC_DEFUN([AC_PROG_F77], [:]) +AC_DEFUN([AC_PROG_FC], [:]) +AC_DEFUN([AC_PROG_CXX], [:]) +AC_DEFUN([AC_PROG_CXXCPP], [:]) +AC_DEFUN([AC_PROG_OBJC], [:]) +AC_DEFUN([AC_PROG_OBJCCPP], [:]) +AC_DEFUN([AC_LIBTOOL_CXX], [:]) +AC_DEFUN([AC_LIBTOOL_F77], [:]) +# always use ./libtool unless override from commandline (libtool=mylibtool) +if test -z "$libtool"; then + libtool="./libtool" +fi +AC_SUBST(libtool) +# avoid libtool max commandline length test on systems that fork slowly. +AC_CANONICAL_HOST +if echo "$host_os" | grep "sunos4" >/dev/null; then + lt_cv_sys_max_cmd_len=32750; +fi +AC_PATH_TOOL(AR, ar, [false]) +if test $AR = false; then + AC_MSG_ERROR([Cannot find 'ar', please extend PATH to include it]) +fi +]) + +dnl Perform libtool check, portably, only for C +AC_DEFUN([ACX_LIBTOOL_C_ONLY], [ +dnl as a requirement so that is gets called before LIBTOOL +dnl because libtools 'AC_REQUIRE' names are right after this one, before +dnl this function contents. +AC_REQUIRE([ACX_LIBTOOL_C_PRE]) +AC_PROG_LIBTOOL +]) + +dnl Detect if u_char type is defined, otherwise define it. +AC_DEFUN([ACX_TYPE_U_CHAR], +[AC_CHECK_TYPE([u_char], , + [AC_DEFINE([u_char], [unsigned char], [Define to 'unsigned char if not defined])], [ +AC_INCLUDES_DEFAULT +#ifdef HAVE_WINSOCK2_H +# include +#endif +]) ]) + +dnl Detect if rlim_t type is defined, otherwise define it. +AC_DEFUN([ACX_TYPE_RLIM_T], +[AC_CHECK_TYPE(rlim_t, , + [AC_DEFINE([rlim_t], [unsigned long], [Define to 'int' if not defined])], [ +AC_INCLUDES_DEFAULT +#ifdef HAVE_SYS_RESOURCE_H +# include +#endif +]) ]) + +dnl Detect if socklen_t type is defined, otherwise define it. +AC_DEFUN([ACX_TYPE_SOCKLEN_T], +[ +AC_CHECK_TYPE(socklen_t, , + [AC_DEFINE([socklen_t], [int], [Define to 'int' if not defined])], [ +AC_INCLUDES_DEFAULT +#ifdef HAVE_SYS_SOCKET_H +# include +#endif +#ifdef HAVE_WS2TCPIP_H +# include +#endif +]) ]) + +dnl Detect if in_addr_t type is defined, otherwise define it. +AC_DEFUN([ACX_TYPE_IN_ADDR_T], +[ AC_CHECK_TYPE(in_addr_t, [], [AC_DEFINE([in_addr_t], [uint32_t], [in_addr_t])], [ +AC_INCLUDES_DEFAULT +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_NETINET_IN_H +# include +#endif +]) ]) + +dnl Detect if in_port_t type is defined, otherwise define it. +AC_DEFUN([ACX_TYPE_IN_PORT_T], +[ AC_CHECK_TYPE(in_port_t, [], [AC_DEFINE([in_port_t], [uint16_t], [in_port_t])], [ +AC_INCLUDES_DEFAULT +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_NETINET_IN_H +# include +#endif +]) ]) + +dnl Add option to disable the evil rpath. Check whether to use rpath or not. +dnl Adds the --disable-rpath option. Uses trick to edit the ./libtool. +AC_DEFUN([ACX_ARG_RPATH], +[ +AC_ARG_ENABLE(rpath, + [ --disable-rpath disable hardcoded rpath (default=enabled)], + enable_rpath=$enableval, enable_rpath=yes) +if test "x$enable_rpath" = xno; then + dnl AC_MSG_RESULT([Fixing libtool for -rpath problems.]) + AC_CONFIG_COMMANDS([disable-rpath], [ + sed < libtool > libtool-2 \ + 's/^hardcode_libdir_flag_spec.*$'/'hardcode_libdir_flag_spec=" -D__LIBTOOL_RPATH_SED__ "/' + mv libtool-2 libtool + chmod 755 libtool + libtool="./libtool" + ]) +fi +]) + +dnl Add a -R to the RUNTIME_PATH. Only if rpath is enabled and it is +dnl an absolute path. +dnl $1: the pathname to add. +AC_DEFUN([ACX_RUNTIME_PATH_ADD], [ + if test "x$enable_rpath" = xyes; then + if echo "$1" | grep "^/" >/dev/null; then + RUNTIME_PATH="$RUNTIME_PATH -R$1" + fi + fi +]) + +dnl Common code for both ACX_WITH_SSL and ACX_WITH_SSL_OPTIONAL +dnl Takes one argument; the withval checked in those 2 functions +dnl sets up the environment for the given openssl path +AC_DEFUN([ACX_SSL_CHECKS], [ + withval=$1 + if test x_$withval != x_no; then + AC_MSG_CHECKING(for SSL) + if test x_$withval = x_ -o x_$withval = x_yes; then + withval="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw /usr" + fi + for dir in $withval; do + ssldir="$dir" + if test -f "$dir/include/openssl/ssl.h"; then + found_ssl="yes" + AC_DEFINE_UNQUOTED([HAVE_SSL], [], [Define if you have the SSL libraries installed.]) + dnl assume /usr/include is already in the include-path. + if test "$ssldir" != "/usr"; then + CPPFLAGS="$CPPFLAGS -I$ssldir/include" + LIBSSL_CPPFLAGS="$LIBSSL_CPPFLAGS -I$ssldir/include" + fi + break; + fi + done + if test x_$found_ssl != x_yes; then + AC_MSG_ERROR(Cannot find the SSL libraries in $withval) + else + AC_MSG_RESULT(found in $ssldir) + HAVE_SSL=yes + dnl assume /usr is already in the lib and dynlib paths. + if test "$ssldir" != "/usr" -a "$ssldir" != ""; then + LDFLAGS="$LDFLAGS -L$ssldir/lib" + LIBSSL_LDFLAGS="$LIBSSL_LDFLAGS -L$ssldir/lib" + ACX_RUNTIME_PATH_ADD([$ssldir/lib]) + fi + + AC_MSG_CHECKING([for HMAC_CTX_init in -lcrypto]) + LIBS="$LIBS -lcrypto" + LIBSSL_LIBS="$LIBSSL_LIBS -lcrypto" + AC_TRY_LINK(, [ + int HMAC_CTX_init(void); + (void)HMAC_CTX_init(); + ], [ + AC_MSG_RESULT(yes) + AC_DEFINE([HAVE_HMAC_CTX_INIT], 1, + [If you have HMAC_CTX_init]) + ], [ + AC_MSG_RESULT(no) + # check if -lwsock32 or -lgdi32 are needed. + BAKLIBS="$LIBS" + BAKSSLLIBS="$LIBSSL_LIBS" + LIBS="$LIBS -lgdi32" + LIBSSL_LIBS="$LIBSSL_LIBS -lgdi32" + AC_MSG_CHECKING([if -lcrypto needs -lgdi32]) + AC_TRY_LINK([], [ + int HMAC_CTX_init(void); + (void)HMAC_CTX_init(); + ],[ + AC_DEFINE([HAVE_HMAC_CTX_INIT], 1, + [If you have HMAC_CTX_init]) + AC_MSG_RESULT(yes) + ],[ + AC_MSG_RESULT(no) + LIBS="$BAKLIBS" + LIBSSL_LIBS="$BAKSSLLIBS" + LIBS="$LIBS -ldl" + LIBSSL_LIBS="$LIBSSL_LIBS -ldl" + AC_MSG_CHECKING([if -lcrypto needs -ldl]) + AC_TRY_LINK([], [ + int HMAC_CTX_init(void); + (void)HMAC_CTX_init(); + ],[ + AC_DEFINE([HAVE_HMAC_CTX_INIT], 1, + [If you have HMAC_CTX_init]) + AC_MSG_RESULT(yes) + ],[ + AC_MSG_RESULT(no) + AC_MSG_ERROR([OpenSSL found in $ssldir, but version 0.9.7 or higher is required]) + ]) + ]) + ]) + fi + AC_SUBST(HAVE_SSL) + AC_SUBST(RUNTIME_PATH) + # openssl engine functionality needs dlopen(). + BAKLIBS="$LIBS" + AC_SEARCH_LIBS([dlopen], [dl]) + if test "$LIBS" != "$BAKLIBS"; then + LIBSSL_LIBS="$LIBSSL_LIBS -ldl" + fi + fi +AC_CHECK_HEADERS([openssl/ssl.h],,, [AC_INCLUDES_DEFAULT]) +AC_CHECK_HEADERS([openssl/err.h],,, [AC_INCLUDES_DEFAULT]) +AC_CHECK_HEADERS([openssl/rand.h],,, [AC_INCLUDES_DEFAULT]) +])dnl End of ACX_SSL_CHECKS + +dnl Check for SSL, where SSL is mandatory +dnl Adds --with-ssl option, searches for openssl and defines HAVE_SSL if found +dnl Setup of CPPFLAGS, CFLAGS. Adds -lcrypto to LIBS. +dnl Checks main header files of SSL. +dnl +AC_DEFUN([ACX_WITH_SSL], +[ +AC_ARG_WITH(ssl, AC_HELP_STRING([--with-ssl=pathname], + [enable SSL (will check /usr/local/ssl + /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw /usr)]),[ + ],[ + withval="yes" + ]) + if test x_$withval = x_no; then + AC_MSG_ERROR([Need SSL library to do digital signature cryptography]) + fi + ACX_SSL_CHECKS($withval) +])dnl End of ACX_WITH_SSL + +dnl Check for SSL, where ssl is optional (--without-ssl is allowed) +dnl Adds --with-ssl option, searches for openssl and defines HAVE_SSL if found +dnl Setup of CPPFLAGS, CFLAGS. Adds -lcrypto to LIBS. +dnl Checks main header files of SSL. +dnl +AC_DEFUN([ACX_WITH_SSL_OPTIONAL], +[ +AC_ARG_WITH(ssl, AC_HELP_STRING([--with-ssl=pathname], + [enable SSL (will check /usr/local/ssl + /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw /usr)]),[ + ],[ + withval="yes" + ]) + ACX_SSL_CHECKS($withval) +])dnl End of ACX_WITH_SSL_OPTIONAL + +dnl Setup to use -lssl +dnl To use -lcrypto, use the ACX_WITH_SSL setup (before this one). +AC_DEFUN([ACX_LIB_SSL], +[ +# check if libssl needs libdl +BAKLIBS="$LIBS" +LIBS="-lssl $LIBS" +AC_MSG_CHECKING([if libssl needs libdl]) +AC_TRY_LINK_FUNC([SSL_CTX_new], [ + AC_MSG_RESULT([no]) + LIBS="$BAKLIBS" +] , [ + AC_MSG_RESULT([yes]) + LIBS="$BAKLIBS" + AC_SEARCH_LIBS([dlopen], [dl]) +]) ])dnl End of ACX_LIB_SSL + +dnl Setup to use very large files (>2Gb). +dnl setups fseeko and its own +AC_DEFUN([ACX_SYS_LARGEFILE], +[ +AC_SYS_LARGEFILE +dnl try to see if an additional _LARGEFILE_SOURCE 1 is needed to get fseeko +ACX_CHECK_COMPILER_FLAG_NEEDED(-D_LARGEFILE_SOURCE=1, +[ +#include +int test() { + int a = fseeko(stdin, 0, 0); + return a; +} +], [CFLAGS="$CFLAGS -D_LARGEFILE_SOURCE=1"]) +]) + +dnl Check getaddrinfo. +dnl Works on linux, solaris, bsd and windows(links winsock). +dnl defines HAVE_GETADDRINFO, USE_WINSOCK. +AC_DEFUN([ACX_CHECK_GETADDRINFO_WITH_INCLUDES], +[AC_REQUIRE([AC_PROG_CC]) +AC_MSG_CHECKING(for getaddrinfo) +ac_cv_func_getaddrinfo=no +AC_LINK_IFELSE( +[AC_LANG_SOURCE([[ +#ifdef __cplusplus +extern "C" +{ +#endif +char* getaddrinfo(); +char* (*f) () = getaddrinfo; +#ifdef __cplusplus +} +#endif +int main() { + ; + return 0; +} +]])], +dnl this case on linux, solaris, bsd +[ac_cv_func_getaddrinfo="yes" +dnl see if on windows +if test "$ac_cv_header_windows_h" = "yes"; then + AC_DEFINE(USE_WINSOCK, 1, [Whether the windows socket API is used]) + USE_WINSOCK="1" + LIBS="$LIBS -lws2_32" +fi +], +dnl no quick getaddrinfo, try mingw32 and winsock2 library. +ORIGLIBS="$LIBS" +LIBS="$LIBS -lws2_32" +AC_LINK_IFELSE( +[AC_LANG_PROGRAM( +[ +#ifdef HAVE_WS2TCPIP_H +#include +#endif +], +[ + (void)getaddrinfo(NULL, NULL, NULL, NULL); +] +)], +[ +ac_cv_func_getaddrinfo="yes" +dnl already: LIBS="$LIBS -lws2_32" +AC_DEFINE(USE_WINSOCK, 1, [Whether the windows socket API is used]) +USE_WINSOCK="1" +], +[ +ac_cv_func_getaddrinfo="no" +LIBS="$ORIGLIBS" +]) +) + +AC_MSG_RESULT($ac_cv_func_getaddrinfo) +if test $ac_cv_func_getaddrinfo = yes; then + AC_DEFINE(HAVE_GETADDRINFO, 1, [Whether getaddrinfo is available]) +fi +])dnl Endof AC_CHECK_GETADDRINFO_WITH_INCLUDES + +dnl check if a function is deprecated. defines DEPRECATED_func in config.h. +dnl $1: function name +dnl $2: C-statement that calls the function. +dnl $3: includes for the program. +dnl $4: executes if yes +dnl $5: executes if no +AC_DEFUN([ACX_FUNC_DEPRECATED], +[ +AC_REQUIRE([AC_PROG_CC]) +AC_MSG_CHECKING(if $1 is deprecated) +cache=`echo $1 | sed 'y%.=/+-%___p_%'` +AC_CACHE_VAL(cv_cc_deprecated_$cache, +[ +echo '$3' >conftest.c +echo 'void f(){ $2 }' >>conftest.c +if test -z "`$CC -c conftest.c 2>&1 | grep deprecated`"; then +eval "cv_cc_deprecated_$cache=no" +else +eval "cv_cc_deprecated_$cache=yes" +fi +rm -f conftest conftest.o conftest.c +]) +if eval "test \"`echo '$cv_cc_deprecated_'$cache`\" = yes"; then +AC_MSG_RESULT(yes) +AC_DEFINE_UNQUOTED(AS_TR_CPP([DEPRECATED_$1]), 1, [Whether $1 is deprecated]) +: +$4 +else +AC_MSG_RESULT(no) +: +$5 +fi +])dnl end of ACX_FUNC_DEPRECATED + +dnl check if select and nonblocking sockets actually work. +dnl Needs fork(2) and select(2). +dnl defines NONBLOCKING_IS_BROKEN, and if that is true multiple reads from +dnl a nonblocking socket do not work, a new call to select is necessary. +AC_DEFUN([ACX_CHECK_NONBLOCKING_BROKEN], +[ +AC_MSG_CHECKING([if nonblocking sockets work]) +if echo $target | grep mingw32 >/dev/null; then + AC_MSG_RESULT([no (windows)]) + AC_DEFINE([NONBLOCKING_IS_BROKEN], 1, [Define if the network stack does not fully support nonblocking io (causes lower performance).]) +else +AC_RUN_IFELSE([ +AC_LANG_SOURCE([[ +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_TIME_H +#include +#endif + +int main(void) +{ + int port; + int sfd, cfd; + int num = 10; + int i, p; + struct sockaddr_in a; + /* test if select and nonblocking reads work well together */ + /* open port. + fork child to send 10 messages. + select to read. + then try to nonblocking read the 10 messages + then, nonblocking read must give EAGAIN + */ + + port = 12345 + (time(0)%32); + sfd = socket(PF_INET, SOCK_DGRAM, 0); + if(sfd == -1) { + perror("socket"); + return 1; + } + memset(&a, 0, sizeof(a)); + a.sin_family = AF_INET; + a.sin_port = htons(port); + a.sin_addr.s_addr = inet_addr("127.0.0.1"); + if(bind(sfd, (struct sockaddr*)&a, sizeof(a)) < 0) { + perror("bind"); + return 1; + } + if(fcntl(sfd, F_SETFL, O_NONBLOCK) == -1) { + perror("fcntl"); + return 1; + } + + cfd = socket(PF_INET, SOCK_DGRAM, 0); + if(cfd == -1) { + perror("client socket"); + return 1; + } + a.sin_port = 0; + if(bind(cfd, (struct sockaddr*)&a, sizeof(a)) < 0) { + perror("client bind"); + return 1; + } + a.sin_port = htons(port); + + /* no handler, causes exit in 10 seconds */ + alarm(10); + + /* send and receive on the socket */ + if((p=fork()) == 0) { + for(i=0; i +#include +#ifdef HAVE_WINSOCK2_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +], [ + (void)mkdir("directory"); +], +AC_MSG_RESULT(yes) +AC_DEFINE(MKDIR_HAS_ONE_ARG, 1, [Define if mkdir has one argument.]) +, +AC_MSG_RESULT(no) +) +])dnl end of ACX_MKDIR_ONE_ARG + +dnl Check for ioctlsocket function. works on mingw32 too. +AC_DEFUN([ACX_FUNC_IOCTLSOCKET], +[ +# check ioctlsocket +AC_MSG_CHECKING(for ioctlsocket) +AC_LINK_IFELSE([AC_LANG_PROGRAM([ +#ifdef HAVE_WINSOCK2_H +#include +#endif +], [ + (void)ioctlsocket(0, 0, NULL); +])], [ +AC_MSG_RESULT(yes) +AC_DEFINE(HAVE_IOCTLSOCKET, 1, [if the function 'ioctlsocket' is available]) +],[AC_MSG_RESULT(no)]) +])dnl end of ACX_FUNC_IOCTLSOCKET + +dnl detect malloc and provide malloc compat prototype. +dnl $1: unique name for compat code +AC_DEFUN([ACX_FUNC_MALLOC], +[ + AC_MSG_CHECKING([for GNU libc compatible malloc]) + AC_RUN_IFELSE([AC_LANG_PROGRAM( +[[#if defined STDC_HEADERS || defined HAVE_STDLIB_H +#include +#else +char *malloc (); +#endif +]], [ if(malloc(0) != 0) return 1;]) +], + [AC_MSG_RESULT([no]) + AC_LIBOBJ(malloc) + AC_DEFINE_UNQUOTED([malloc], [rpl_malloc_$1], [Define if replacement function should be used.])] , + [AC_MSG_RESULT([yes]) + AC_DEFINE([HAVE_MALLOC], 1, [If have GNU libc compatible malloc])], + [AC_MSG_RESULT([no (crosscompile)]) + AC_LIBOBJ(malloc) + AC_DEFINE_UNQUOTED([malloc], [rpl_malloc_$1], [Define if replacement function should be used.])] ) +]) + +dnl Define fallback for fseeko and ftello if needed. +AC_DEFUN([AHX_CONFIG_FSEEKO], +[ +#ifndef HAVE_FSEEKO +#define fseeko fseek +#define ftello ftell +#endif /* HAVE_FSEEKO */ +]) + +dnl Define RAND_MAX if not defined +AC_DEFUN([AHX_CONFIG_RAND_MAX], +[ +#ifndef RAND_MAX +#define RAND_MAX 2147483647 +#endif +]) + +dnl Define MAXHOSTNAMELEN if not defined +AC_DEFUN([AHX_CONFIG_MAXHOSTNAMELEN], +[ +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 256 +#endif +]) + +dnl Define IPV6_MIN_MTU if not defined +AC_DEFUN([AHX_CONFIG_IPV6_MIN_MTU], +[ +#ifndef IPV6_MIN_MTU +#define IPV6_MIN_MTU 1280 +#endif /* IPV6_MIN_MTU */ +]) + +dnl provide snprintf, vsnprintf compat prototype +dnl $1: unique name for compat code +AC_DEFUN([AHX_CONFIG_SNPRINTF], +[ +#ifndef HAVE_SNPRINTF +#define snprintf snprintf_$1 +#define vsnprintf vsnprintf_$1 +#include +int snprintf (char *str, size_t count, const char *fmt, ...); +int vsnprintf (char *str, size_t count, const char *fmt, va_list arg); +#endif /* HAVE_SNPRINTF */ +]) + +dnl provide inet_pton compat prototype. +dnl $1: unique name for compat code +AC_DEFUN([AHX_CONFIG_INET_PTON], +[ +#ifndef HAVE_INET_PTON +#define inet_pton inet_pton_$1 +int inet_pton(int af, const char* src, void* dst); +#endif /* HAVE_INET_PTON */ +]) + +dnl provide inet_ntop compat prototype. +dnl $1: unique name for compat code +AC_DEFUN([AHX_CONFIG_INET_NTOP], +[ +#ifndef HAVE_INET_NTOP +#define inet_ntop inet_ntop_$1 +const char *inet_ntop(int af, const void *src, char *dst, size_t size); +#endif +]) + +dnl provide inet_aton compat prototype. +dnl $1: unique name for compat code +AC_DEFUN([AHX_CONFIG_INET_ATON], +[ +#ifndef HAVE_INET_ATON +#define inet_aton inet_aton_$1 +int inet_aton(const char *cp, struct in_addr *addr); +#endif +]) + +dnl provide memmove compat prototype. +dnl $1: unique name for compat code +AC_DEFUN([AHX_CONFIG_MEMMOVE], +[ +#ifndef HAVE_MEMMOVE +#define memmove memmove_$1 +void *memmove(void *dest, const void *src, size_t n); +#endif +]) + +dnl provide strlcat compat prototype. +dnl $1: unique name for compat code +AC_DEFUN([AHX_CONFIG_STRLCAT], +[ +#ifndef HAVE_STRLCAT +#define strlcat strlcat_$1 +size_t strlcat(char *dst, const char *src, size_t siz); +#endif +]) + +dnl provide strlcpy compat prototype. +dnl $1: unique name for compat code +AC_DEFUN([AHX_CONFIG_STRLCPY], +[ +#ifndef HAVE_STRLCPY +#define strlcpy strlcpy_$1 +size_t strlcpy(char *dst, const char *src, size_t siz); +#endif +]) + +dnl provide gmtime_r compat prototype. +dnl $1: unique name for compat code +AC_DEFUN([AHX_CONFIG_GMTIME_R], +[ +#ifndef HAVE_GMTIME_R +#define gmtime_r gmtime_r_$1 +struct tm *gmtime_r(const time_t *timep, struct tm *result); +#endif +]) + +dnl provide w32 compat definition for sleep +AC_DEFUN([AHX_CONFIG_W32_SLEEP], +[ +#ifndef HAVE_SLEEP +#define sleep(x) Sleep((x)*1000) /* on win32 */ +#endif /* HAVE_SLEEP */ +]) + +dnl provide w32 compat definition for usleep +AC_DEFUN([AHX_CONFIG_W32_USLEEP], +[ +#ifndef HAVE_USLEEP +#define usleep(x) Sleep((x)/1000 + 1) /* on win32 */ +#endif /* HAVE_USLEEP */ +]) + +dnl provide w32 compat definition for random +AC_DEFUN([AHX_CONFIG_W32_RANDOM], +[ +#ifndef HAVE_RANDOM +#define random rand /* on win32, for tests only (bad random) */ +#endif /* HAVE_RANDOM */ +]) + +dnl provide w32 compat definition for srandom +AC_DEFUN([AHX_CONFIG_W32_SRANDOM], +[ +#ifndef HAVE_SRANDOM +#define srandom(x) srand(x) /* on win32, for tests only (bad random) */ +#endif /* HAVE_SRANDOM */ +]) + +dnl provide w32 compat definition for FD_SET_T +AC_DEFUN([AHX_CONFIG_W32_FD_SET_T], +[ +/* detect if we need to cast to unsigned int for FD_SET to avoid warnings */ +#ifdef HAVE_WINSOCK2_H +#define FD_SET_T (u_int) +#else +#define FD_SET_T +#endif +]) + +dnl Remove an extension flag from CFLAGS, define replacement to be made. +dnl Used by ACX_STRIP_EXT_FLAGS. +dnl $1: the name of the flag, for example -D_GNU_SOURCE. +AC_DEFUN([ACX_CFLAGS_STRIP], +[ + if echo $CFLAGS | grep " $1" >/dev/null 2>&1; then + CFLAGS="`echo $CFLAGS | sed -e 's/ $1//g'`" + AC_DEFINE(m4_bpatsubst(OMITTED_$1,[[-=]],_), 1, Put $1 define in config.h) + fi +]) + +dnl Remove EXT flags from the CFLAGS and set them to be defined in config.h +dnl use with ACX_DETERMINE_EXT_FLAGS. +AC_DEFUN([ACX_STRIP_EXT_FLAGS], +[ + AC_MSG_NOTICE([Stripping extension flags...]) + ACX_CFLAGS_STRIP(-D_GNU_SOURCE) + ACX_CFLAGS_STRIP(-D_BSD_SOURCE) + ACX_CFLAGS_STRIP(-D__EXTENSIONS__) + ACX_CFLAGS_STRIP(-D_POSIX_C_SOURCE=200112) + ACX_CFLAGS_STRIP(-D_XOPEN_SOURCE=600) + ACX_CFLAGS_STRIP(-D_XOPEN_SOURCE_EXTENDED=1) + ACX_CFLAGS_STRIP(-D_ALL_SOURCE) + ACX_CFLAGS_STRIP(-D_LARGEFILE_SOURCE=1) +]) dnl End of ACX_STRIP_EXT_FLAGS + +dnl define one omitted flag for config.h +dnl $1: flag name. -D_GNU_SOURCE +dnl $2: replacement define. _GNU_SOURCE +dnl $3: define value, 1 +AC_DEFUN([AHX_CONFIG_FLAG_OMITTED], +[#if defined($1) && !defined($2) +#define $2 $3 +[#]endif ]) + +dnl Wrapper for AHX_CONFIG_FLAG_OMITTED for -D style flags +dnl $1: the -DNAME or -DNAME=value string. +AC_DEFUN([AHX_CONFIG_FLAG_EXT], +[AHX_CONFIG_FLAG_OMITTED(m4_bpatsubst(OMITTED_$1,[[-=]],_),m4_bpatsubst(m4_bpatsubst($1,-D,),=.*$,),m4_if(m4_bregexp($1,=),-1,1,m4_bpatsubst($1,^.*=,))) +]) + +dnl config.h part to define omitted cflags, use with ACX_STRIP_EXT_FLAGS. +AC_DEFUN([AHX_CONFIG_EXT_FLAGS], +[AHX_CONFIG_FLAG_EXT(-D_GNU_SOURCE) +AHX_CONFIG_FLAG_EXT(-D_BSD_SOURCE) +AHX_CONFIG_FLAG_EXT(-D__EXTENSIONS__) +AHX_CONFIG_FLAG_EXT(-D_POSIX_C_SOURCE=200112) +AHX_CONFIG_FLAG_EXT(-D_XOPEN_SOURCE=600) +AHX_CONFIG_FLAG_EXT(-D_XOPEN_SOURCE_EXTENDED=1) +AHX_CONFIG_FLAG_EXT(-D_ALL_SOURCE) +AHX_CONFIG_FLAG_EXT(-D_LARGEFILE_SOURCE=1) +]) + +dnl check if memcmp is using signed characters and replace if so. +AC_DEFUN([ACX_CHECK_MEMCMP_SIGNED], +[AC_MSG_CHECKING([if memcmp compares unsigned]) +AC_RUN_IFELSE([AC_LANG_SOURCE([[ +#include +#include +#include +int main(void) +{ + char a = 255, b = 0; + if(memcmp(&a, &b, 1) < 0) + return 1; + return 0; +} +]])], [AC_MSG_RESULT([yes]) ], +[ AC_MSG_RESULT([no]) + AC_DEFINE([MEMCMP_IS_BROKEN], [1], [Define if memcmp() does not compare unsigned bytes]) + AC_LIBOBJ([memcmp]) +], [ AC_MSG_RESULT([cross-compile no]) + AC_DEFINE([MEMCMP_IS_BROKEN], [1], [Define if memcmp() does not compare unsigned bytes]) + AC_LIBOBJ([memcmp]) +]) ]) + +dnl define memcmp to its replacement, pass unique id for program as arg +AC_DEFUN([AHX_MEMCMP_BROKEN], [ +#ifdef MEMCMP_IS_BROKEN +#include "compat/memcmp.h" +#define memcmp memcmp_$1 +int memcmp(const void *x, const void *y, size_t n); +#endif +]) + +dnl ACX_CHECK_SS_FAMILY - check for sockaddr_storage.ss_family +AC_DEFUN([ACX_CHECK_SS_FAMILY], +[AC_CHECK_MEMBER([struct sockaddr_storage.ss_family], [], [ + AC_CHECK_MEMBER([struct sockaddr_storage.__ss_family], [ + AC_DEFINE([ss_family], [__ss_family], [Fallback member name for socket family in struct sockaddr_storage]) + ],, [AC_INCLUDES_DEFAULT +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif + ]) +], [AC_INCLUDES_DEFAULT +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +]) ]) + +dnl End of file diff --git a/ax_pkg_swig.m4 b/ax_pkg_swig.m4 new file mode 100644 index 00000000000..a1a58dc1e5b --- /dev/null +++ b/ax_pkg_swig.m4 @@ -0,0 +1,135 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_pkg_swig.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PKG_SWIG([major.minor.micro], [action-if-found], [action-if-not-found]) +# +# DESCRIPTION +# +# This macro searches for a SWIG installation on your system. If found, +# then SWIG is AC_SUBST'd; if not found, then $SWIG is empty. If SWIG is +# found, then SWIG_LIB is set to the SWIG library path, and AC_SUBST'd. +# +# You can use the optional first argument to check if the version of the +# available SWIG is greater than or equal to the value of the argument. It +# should have the format: N[.N[.N]] (N is a number between 0 and 999. Only +# the first N is mandatory.) If the version argument is given (e.g. +# 1.3.17), AX_PKG_SWIG checks that the swig package is this version number +# or higher. +# +# As usual, action-if-found is executed if SWIG is found, otherwise +# action-if-not-found is executed. +# +# In configure.in, use as: +# +# AX_PKG_SWIG(1.3.17, [], [ AC_MSG_ERROR([SWIG is required to build..]) ]) +# AX_SWIG_ENABLE_CXX +# AX_SWIG_MULTI_MODULE_SUPPORT +# AX_SWIG_PYTHON +# +# LICENSE +# +# Copyright (c) 2008 Sebastian Huber +# Copyright (c) 2008 Alan W. Irwin +# Copyright (c) 2008 Rafael Laboissiere +# Copyright (c) 2008 Andrew Collier +# Copyright (c) 2011 Murray Cumming +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 8 + +AC_DEFUN([AX_PKG_SWIG],[ + # Ubuntu has swig 2.0 as /usr/bin/swig2.0 + AC_PATH_PROGS([SWIG],[swig2.0 swig]) + if test -z "$SWIG" ; then + m4_ifval([$3],[$3],[:]) + elif test -n "$1" ; then + AC_MSG_CHECKING([SWIG version]) + [swig_version=`$SWIG -version 2>&1 | grep 'SWIG Version' | sed 's/.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/g'`] + AC_MSG_RESULT([$swig_version]) + if test -n "$swig_version" ; then + # Calculate the required version number components + [required=$1] + [required_major=`echo $required | sed 's/[^0-9].*//'`] + if test -z "$required_major" ; then + [required_major=0] + fi + [required=`echo $required | sed 's/[0-9]*[^0-9]//'`] + [required_minor=`echo $required | sed 's/[^0-9].*//'`] + if test -z "$required_minor" ; then + [required_minor=0] + fi + [required=`echo $required | sed 's/[0-9]*[^0-9]//'`] + [required_patch=`echo $required | sed 's/[^0-9].*//'`] + if test -z "$required_patch" ; then + [required_patch=0] + fi + # Calculate the available version number components + [available=$swig_version] + [available_major=`echo $available | sed 's/[^0-9].*//'`] + if test -z "$available_major" ; then + [available_major=0] + fi + [available=`echo $available | sed 's/[0-9]*[^0-9]//'`] + [available_minor=`echo $available | sed 's/[^0-9].*//'`] + if test -z "$available_minor" ; then + [available_minor=0] + fi + [available=`echo $available | sed 's/[0-9]*[^0-9]//'`] + [available_patch=`echo $available | sed 's/[^0-9].*//'`] + if test -z "$available_patch" ; then + [available_patch=0] + fi + # Convert the version tuple into a single number for easier comparison. + # Using base 100 should be safe since SWIG internally uses BCD values + # to encode its version number. + required_swig_vernum=`expr $required_major \* 10000 \ + \+ $required_minor \* 100 \+ $required_patch` + available_swig_vernum=`expr $available_major \* 10000 \ + \+ $available_minor \* 100 \+ $available_patch` + + if test $available_swig_vernum -lt $required_swig_vernum; then + AC_MSG_WARN([SWIG version >= $1 is required. You have $swig_version.]) + SWIG='' + m4_ifval([$3],[$3],[]) + else + AC_MSG_CHECKING([for SWIG library]) + SWIG_LIB=`$SWIG -swiglib` + AC_MSG_RESULT([$SWIG_LIB]) + m4_ifval([$2],[$2],[]) + fi + else + AC_MSG_WARN([cannot determine SWIG version]) + SWIG='' + m4_ifval([$3],[$3],[]) + fi + fi + AC_SUBST([SWIG_LIB]) +]) diff --git a/ax_python_devel.m4 b/ax_python_devel.m4 new file mode 100644 index 00000000000..2ce6afe8350 --- /dev/null +++ b/ax_python_devel.m4 @@ -0,0 +1,327 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_python_devel.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PYTHON_DEVEL([version]) +# +# DESCRIPTION +# +# Note: Defines as a precious variable "PYTHON_VERSION". Don't override it +# in your configure.ac. +# +# This macro checks for Python and tries to get the include path to +# 'Python.h'. It provides the $(PYTHON_CPPFLAGS) and $(PYTHON_LDFLAGS) +# output variables. It also exports $(PYTHON_EXTRA_LIBS) and +# $(PYTHON_EXTRA_LDFLAGS) for embedding Python in your code. +# +# You can search for some particular version of Python by passing a +# parameter to this macro, for example ">= '2.3.1'", or "== '2.4'". Please +# note that you *have* to pass also an operator along with the version to +# match, and pay special attention to the single quotes surrounding the +# version number. Don't use "PYTHON_VERSION" for this: that environment +# variable is declared as precious and thus reserved for the end-user. +# +# This macro should work for all versions of Python >= 2.1.0. As an end +# user, you can disable the check for the python version by setting the +# PYTHON_NOVERSIONCHECK environment variable to something else than the +# empty string. +# +# If you need to use this macro for an older Python version, please +# contact the authors. We're always open for feedback. +# +# LICENSE +# +# Copyright (c) 2009 Sebastian Huber +# Copyright (c) 2009 Alan W. Irwin +# Copyright (c) 2009 Rafael Laboissiere +# Copyright (c) 2009 Andrew Collier +# Copyright (c) 2009 Matteo Settenvini +# Copyright (c) 2009 Horst Knorr +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 8 + +AU_ALIAS([AC_PYTHON_DEVEL], [AX_PYTHON_DEVEL]) +AC_DEFUN([AX_PYTHON_DEVEL],[ + # + # Allow the use of a (user set) custom python version + # + AC_ARG_VAR([PYTHON_VERSION],[The installed Python + version to use, for example '2.3'. This string + will be appended to the Python interpreter + canonical name.]) + + AC_PATH_PROG([PYTHON],[python[$PYTHON_VERSION]]) + if test -z "$PYTHON"; then + AC_MSG_ERROR([Cannot find python$PYTHON_VERSION in your system path]) + PYTHON_VERSION="" + fi + + # + # Check for a version of Python >= 2.1.0 + # + AC_MSG_CHECKING([for a version of Python >= '2.1.0']) + ac_supports_python_ver=`$PYTHON -c "import sys; \ + ver = sys.version.split ()[[0]]; \ + print (ver >= '2.1.0')"` + if test "$ac_supports_python_ver" != "True"; then + if test -z "$PYTHON_NOVERSIONCHECK"; then + AC_MSG_RESULT([no]) + AC_MSG_FAILURE([ +This version of the AC@&t@_PYTHON_DEVEL macro +doesn't work properly with versions of Python before +2.1.0. You may need to re-run configure, setting the +variables PYTHON_CPPFLAGS, PYTHON_LDFLAGS, PYTHON_SITE_PKG, +PYTHON_EXTRA_LIBS and PYTHON_EXTRA_LDFLAGS by hand. +Moreover, to disable this check, set PYTHON_NOVERSIONCHECK +to something else than an empty string. +]) + else + AC_MSG_RESULT([skip at user request]) + fi + else + AC_MSG_RESULT([yes]) + fi + + # + # if the macro parameter ``version'' is set, honour it + # + if test -n "$1"; then + AC_MSG_CHECKING([for a version of Python $1]) + ac_supports_python_ver=`$PYTHON -c "import sys; \ + ver = sys.version.split ()[[0]]; \ + print (ver $1)"` + if test "$ac_supports_python_ver" = "True"; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + AC_MSG_ERROR([this package requires Python $1. +If you have it installed, but it isn't the default Python +interpreter in your system path, please pass the PYTHON_VERSION +variable to configure. See ``configure --help'' for reference. +]) + PYTHON_VERSION="" + fi + fi + + # + # Check if you have distutils, else fail + # + AC_MSG_CHECKING([for the distutils Python package]) + ac_distutils_result=`$PYTHON -c "import distutils" 2>&1` + if test -z "$ac_distutils_result"; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + AC_MSG_ERROR([cannot import Python module "distutils". +Please check your Python installation. The error was: +$ac_distutils_result]) + PYTHON_VERSION="" + fi + + # + # Check for Python include path + # + AC_MSG_CHECKING([for Python include path]) + if test -z "$PYTHON_CPPFLAGS"; then + python_path=`$PYTHON -c "import distutils.sysconfig; \ + print (distutils.sysconfig.get_python_inc ());"` + if test -n "${python_path}"; then + python_path="-I$python_path" + fi + PYTHON_CPPFLAGS=$python_path + fi + AC_MSG_RESULT([$PYTHON_CPPFLAGS]) + AC_SUBST([PYTHON_CPPFLAGS]) + + # + # Check for Python library path + # + AC_MSG_CHECKING([for Python library path]) + if test -z "$PYTHON_LDFLAGS"; then + # (makes two attempts to ensure we've got a version number + # from the interpreter) + ac_python_version=`cat<]], + [[Py_Initialize();]]) + ],[pythonexists=yes],[pythonexists=no]) + AC_LANG_POP([C]) + # turn back to default flags + CPPFLAGS="$ac_save_CPPFLAGS" + LIBS="$ac_save_LIBS" + + AC_MSG_RESULT([$pythonexists]) + + if test ! "x$pythonexists" = "xyes"; then + AC_MSG_FAILURE([ + Could not link test program to Python. Maybe the main Python library has been + installed in some non-standard library path. If so, pass it to configure, + via the LDFLAGS environment variable. + Example: ./configure LDFLAGS="-L/usr/non-standard-path/python/lib" + ============================================================================ + ERROR! + You probably have to install the development version of the Python package + for your distribution. The exact name of this package varies among them. + ============================================================================ + ]) + PYTHON_VERSION="" + fi + + # + # all done! + # +]) diff --git a/buffer.c b/buffer.c new file mode 100644 index 00000000000..5a6b0ba74c8 --- /dev/null +++ b/buffer.c @@ -0,0 +1,176 @@ +/* + * buffer.c -- generic memory buffer . + * + * Copyright (c) 2001-2008, NLnet Labs. All rights reserved. + * + * See LICENSE for the license. + * + */ + +#include + +#include +#include + +ldns_buffer * +ldns_buffer_new(size_t capacity) +{ + ldns_buffer *buffer = LDNS_MALLOC(ldns_buffer); + + if (!buffer) { + return NULL; + } + + buffer->_data = (uint8_t *) LDNS_XMALLOC(uint8_t, capacity); + if (!buffer->_data) { + LDNS_FREE(buffer); + return NULL; + } + + buffer->_position = 0; + buffer->_limit = buffer->_capacity = capacity; + buffer->_fixed = 0; + buffer->_status = LDNS_STATUS_OK; + + ldns_buffer_invariant(buffer); + + return buffer; +} + +void +ldns_buffer_new_frm_data(ldns_buffer *buffer, void *data, size_t size) +{ + assert(data != NULL); + + buffer->_position = 0; + buffer->_limit = buffer->_capacity = size; + buffer->_fixed = 0; + buffer->_data = LDNS_XMALLOC(uint8_t, size); + if(!buffer->_data) { + buffer->_status = LDNS_STATUS_MEM_ERR; + return; + } + memcpy(buffer->_data, data, size); + buffer->_status = LDNS_STATUS_OK; + + ldns_buffer_invariant(buffer); +} + +bool +ldns_buffer_set_capacity(ldns_buffer *buffer, size_t capacity) +{ + void *data; + + ldns_buffer_invariant(buffer); + assert(buffer->_position <= capacity); + + data = (uint8_t *) LDNS_XREALLOC(buffer->_data, uint8_t, capacity); + if (!data) { + buffer->_status = LDNS_STATUS_MEM_ERR; + return false; + } else { + buffer->_data = data; + buffer->_limit = buffer->_capacity = capacity; + return true; + } +} + +bool +ldns_buffer_reserve(ldns_buffer *buffer, size_t amount) +{ + ldns_buffer_invariant(buffer); + assert(!buffer->_fixed); + if (buffer->_capacity < buffer->_position + amount) { + size_t new_capacity = buffer->_capacity * 3 / 2; + + if (new_capacity < buffer->_position + amount) { + new_capacity = buffer->_position + amount; + } + if (!ldns_buffer_set_capacity(buffer, new_capacity)) { + buffer->_status = LDNS_STATUS_MEM_ERR; + return false; + } + } + buffer->_limit = buffer->_capacity; + return true; +} + +int +ldns_buffer_printf(ldns_buffer *buffer, const char *format, ...) +{ + va_list args; + int written = 0; + size_t remaining; + + if (ldns_buffer_status_ok(buffer)) { + ldns_buffer_invariant(buffer); + assert(buffer->_limit == buffer->_capacity); + + remaining = ldns_buffer_remaining(buffer); + va_start(args, format); + written = vsnprintf((char *) ldns_buffer_current(buffer), remaining, + format, args); + va_end(args); + if (written == -1) { + buffer->_status = LDNS_STATUS_INTERNAL_ERR; + return -1; + } else if ((size_t) written >= remaining) { + if (!ldns_buffer_reserve(buffer, (size_t) written + 1)) { + buffer->_status = LDNS_STATUS_MEM_ERR; + return -1; + } + va_start(args, format); + written = vsnprintf((char *) ldns_buffer_current(buffer), + ldns_buffer_remaining(buffer), format, args); + va_end(args); + if (written == -1) { + buffer->_status = LDNS_STATUS_INTERNAL_ERR; + return -1; + } + } + buffer->_position += written; + } + return written; +} + +void +ldns_buffer_free(ldns_buffer *buffer) +{ + if (!buffer) { + return; + } + + LDNS_FREE(buffer->_data); + + LDNS_FREE(buffer); +} + +void * +ldns_buffer_export(ldns_buffer *buffer) +{ + buffer->_fixed = 1; + return buffer->_data; +} + +int +ldns_bgetc(ldns_buffer *buffer) +{ + if (!ldns_buffer_available_at(buffer, buffer->_position, sizeof(uint8_t))) { + ldns_buffer_set_position(buffer, ldns_buffer_limit(buffer)); + /* ldns_buffer_rewind(buffer);*/ + return EOF; + } + return (int)ldns_buffer_read_u8(buffer); +} + +void +ldns_buffer_copy(ldns_buffer* result, ldns_buffer* from) +{ + size_t tocopy = ldns_buffer_limit(from); + + if(tocopy > ldns_buffer_capacity(result)) + tocopy = ldns_buffer_capacity(result); + ldns_buffer_clear(result); + ldns_buffer_write(result, ldns_buffer_begin(from), tocopy); + ldns_buffer_flip(result); +} diff --git a/compat/b32_ntop.c b/compat/b32_ntop.c new file mode 100644 index 00000000000..038ebdc9580 --- /dev/null +++ b/compat/b32_ntop.c @@ -0,0 +1,333 @@ +/* + * Copyright (c) 1996, 1998 by Internet Software Consortium. + * + * 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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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. + */ + +/* + * Portions Copyright (c) 1995 by International Business Machines, Inc. + * + * International Business Machines, Inc. (hereinafter called IBM) grants + * permission under its copyrights to use, copy, modify, and distribute this + * Software with or without fee, provided that the above copyright notice and + * all paragraphs of this notice appear in all copies, and that the name of IBM + * not be used in connection with the marketing of any product incorporating + * the Software or modifications thereof, without specific, written prior + * permission. + * + * To the extent it has a right to do so, IBM grants an immunity from suit + * under its patents, if any, for the use, sale or manufacture of products to + * the extent that such products are used for performing Domain Name System + * dynamic updates in TCP/IP networks by means of the Software. No immunity is + * granted for any product per se or for any other function of any product. + * + * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, + * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN + * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ +#include + +#include +#include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#include +#include +#include +#include + +#include + +static const char Base32[] = + "abcdefghijklmnopqrstuvwxyz234567"; +/* "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";*/ +/* 00000000001111111111222222222233 + 01234567890123456789012345678901*/ +static const char Base32_extended_hex[] = +/* "0123456789ABCDEFGHIJKLMNOPQRSTUV";*/ + "0123456789abcdefghijklmnopqrstuv"; +static const char Pad32 = '='; + +/* (From RFC3548 and draft-josefsson-rfc3548bis-00.txt) +5. Base 32 Encoding + + The Base 32 encoding is designed to represent arbitrary sequences of + octets in a form that needs to be case insensitive but need not be + humanly readable. + + A 33-character subset of US-ASCII is used, enabling 5 bits to be + represented per printable character. (The extra 33rd character, "=", + is used to signify a special processing function.) + + The encoding process represents 40-bit groups of input bits as output + strings of 8 encoded characters. Proceeding from left to right, a + 40-bit input group is formed by concatenating 5 8bit input groups. + These 40 bits are then treated as 8 concatenated 5-bit groups, each + of which is translated into a single digit in the base 32 alphabet. + When encoding a bit stream via the base 32 encoding, the bit stream + must be presumed to be ordered with the most-significant-bit first. + That is, the first bit in the stream will be the high-order bit in + the first 8bit byte, and the eighth bit will be the low-order bit in + the first 8bit byte, and so on. + + Each 5-bit group is used as an index into an array of 32 printable + characters. The character referenced by the index is placed in the + output string. These characters, identified in Table 3, below, are + selected from US-ASCII digits and uppercase letters. + + Table 3: The Base 32 Alphabet + + Value Encoding Value Encoding Value Encoding Value Encoding + 0 A 9 J 18 S 27 3 + 1 B 10 K 19 T 28 4 + 2 C 11 L 20 U 29 5 + 3 D 12 M 21 V 30 6 + 4 E 13 N 22 W 31 7 + 5 F 14 O 23 X + 6 G 15 P 24 Y (pad) = + 7 H 16 Q 25 Z + 8 I 17 R 26 2 + + + Special processing is performed if fewer than 40 bits are available + at the end of the data being encoded. A full encoding quantum is + always completed at the end of a body. When fewer than 40 input bits + are available in an input group, zero bits are added (on the right) + to form an integral number of 5-bit groups. Padding at the end of + the data is performed using the "=" character. Since all base 32 + input is an integral number of octets, only the following cases can + arise: + + (1) the final quantum of encoding input is an integral multiple of 40 + bits; here, the final unit of encoded output will be an integral + multiple of 8 characters with no "=" padding, + + (2) the final quantum of encoding input is exactly 8 bits; here, the + final unit of encoded output will be two characters followed by six + "=" padding characters, + + (3) the final quantum of encoding input is exactly 16 bits; here, the + final unit of encoded output will be four characters followed by four + "=" padding characters, + + (4) the final quantum of encoding input is exactly 24 bits; here, the + final unit of encoded output will be five characters followed by + three "=" padding characters, or + + (5) the final quantum of encoding input is exactly 32 bits; here, the + final unit of encoded output will be seven characters followed by one + "=" padding character. + + +6. Base 32 Encoding with Extended Hex Alphabet + + The following description of base 32 is due to [7]. This encoding + should not be regarded as the same as the "base32" encoding, and + should not be referred to as only "base32". + + One property with this alphabet, that the base64 and base32 alphabet + lack, is that encoded data maintain its sort order when the encoded + data is compared bit-wise. + + This encoding is identical to the previous one, except for the + alphabet. The new alphabet is found in table 4. + + Table 4: The "Extended Hex" Base 32 Alphabet + + Value Encoding Value Encoding Value Encoding Value Encoding + 0 0 9 9 18 I 27 R + 1 1 10 A 19 J 28 S + 2 2 11 B 20 K 29 T + 3 3 12 C 21 L 30 U + 4 4 13 D 22 M 31 V + 5 5 14 E 23 N + 6 6 15 F 24 O (pad) = + 7 7 16 G 25 P + 8 8 17 H 26 Q + +*/ + + +int +ldns_b32_ntop_ar(uint8_t const *src, size_t srclength, char *target, size_t targsize, const char B32_ar[]) { + size_t datalength = 0; + uint8_t input[5]; + uint8_t output[8]; + size_t i; + memset(output, 0, 8); + + while (4 < srclength) { + input[0] = *src++; + input[1] = *src++; + input[2] = *src++; + input[3] = *src++; + input[4] = *src++; + srclength -= 5; + + output[0] = (input[0] & 0xf8) >> 3; + output[1] = ((input[0] & 0x07) << 2) + ((input[1] & 0xc0) >> 6); + output[2] = (input[1] & 0x3e) >> 1; + output[3] = ((input[1] & 0x01) << 4) + ((input[2] & 0xf0) >> 4); + output[4] = ((input[2] & 0x0f) << 1) + ((input[3] & 0x80) >> 7); + output[5] = (input[3] & 0x7c) >> 2; + output[6] = ((input[3] & 0x03) << 3) + ((input[4] & 0xe0) >> 5); + output[7] = (input[4] & 0x1f); + + assert(output[0] < 32); + assert(output[1] < 32); + assert(output[2] < 32); + assert(output[3] < 32); + assert(output[4] < 32); + assert(output[5] < 32); + assert(output[6] < 32); + assert(output[7] < 32); + + if (datalength + 8 > targsize) { + return (-1); + } + target[datalength++] = B32_ar[output[0]]; + target[datalength++] = B32_ar[output[1]]; + target[datalength++] = B32_ar[output[2]]; + target[datalength++] = B32_ar[output[3]]; + target[datalength++] = B32_ar[output[4]]; + target[datalength++] = B32_ar[output[5]]; + target[datalength++] = B32_ar[output[6]]; + target[datalength++] = B32_ar[output[7]]; + } + + /* Now we worry about padding. */ + if (0 != srclength) { + /* Get what's left. */ + input[0] = input[1] = input[2] = input[3] = input[4] = (uint8_t) '\0'; + for (i = 0; i < srclength; i++) + input[i] = *src++; + + output[0] = (input[0] & 0xf8) >> 3; + assert(output[0] < 32); + if (srclength >= 1) { + output[1] = ((input[0] & 0x07) << 2) + ((input[1] & 0xc0) >> 6); + assert(output[1] < 32); + output[2] = (input[1] & 0x3e) >> 1; + assert(output[2] < 32); + } + if (srclength >= 2) { + output[3] = ((input[1] & 0x01) << 4) + ((input[2] & 0xf0) >> 4); + assert(output[3] < 32); + } + if (srclength >= 3) { + output[4] = ((input[2] & 0x0f) << 1) + ((input[3] & 0x80) >> 7); + assert(output[4] < 32); + output[5] = (input[3] & 0x7c) >> 2; + assert(output[5] < 32); + } + if (srclength >= 4) { + output[6] = ((input[3] & 0x03) << 3) + ((input[4] & 0xe0) >> 5); + assert(output[6] < 32); + } + + + if (datalength + 1 > targsize) { + return (-2); + } + target[datalength++] = B32_ar[output[0]]; + if (srclength >= 1) { + if (datalength + 1 > targsize) { return (-2); } + target[datalength++] = B32_ar[output[1]]; + if (srclength == 1 && output[2] == 0) { + if (datalength + 1 > targsize) { return (-2); } + target[datalength++] = Pad32; + } else { + if (datalength + 1 > targsize) { return (-2); } + target[datalength++] = B32_ar[output[2]]; + } + } else { + if (datalength + 1 > targsize) { return (-2); } + target[datalength++] = Pad32; + if (datalength + 1 > targsize) { return (-2); } + target[datalength++] = Pad32; + } + if (srclength >= 2) { + if (datalength + 1 > targsize) { return (-2); } + target[datalength++] = B32_ar[output[3]]; + } else { + if (datalength + 1 > targsize) { return (-2); } + target[datalength++] = Pad32; + } + if (srclength >= 3) { + if (datalength + 1 > targsize) { return (-2); } + target[datalength++] = B32_ar[output[4]]; + if (srclength == 3 && output[5] == 0) { + if (datalength + 1 > targsize) { return (-2); } + target[datalength++] = Pad32; + } else { + if (datalength + 1 > targsize) { return (-2); } + target[datalength++] = B32_ar[output[5]]; + } + } else { + if (datalength + 1 > targsize) { return (-2); } + target[datalength++] = Pad32; + if (datalength + 1 > targsize) { return (-2); } + target[datalength++] = Pad32; + } + if (srclength >= 4) { + if (datalength + 1 > targsize) { return (-2); } + target[datalength++] = B32_ar[output[6]]; + } else { + if (datalength + 1 > targsize) { return (-2); } + target[datalength++] = Pad32; + } + if (datalength + 1 > targsize) { return (-2); } + target[datalength++] = Pad32; + } + if (datalength+1 > targsize) { + return (int) (datalength); + } + target[datalength] = '\0'; /* Returned value doesn't count \0. */ + return (int) (datalength); +} + +int +ldns_b32_ntop(uint8_t const *src, size_t srclength, char *target, size_t targsize) { + return ldns_b32_ntop_ar(src, srclength, target, targsize, Base32); +} + +/* deprecated, here for backwards compatibility */ +int +b32_ntop(uint8_t const *src, size_t srclength, char *target, size_t targsize) { + return ldns_b32_ntop_ar(src, srclength, target, targsize, Base32); +} + +int +ldns_b32_ntop_extended_hex(uint8_t const *src, size_t srclength, char *target, size_t targsize) { + return ldns_b32_ntop_ar(src, srclength, target, targsize, Base32_extended_hex); +} + +/* deprecated, here for backwards compatibility */ +int +b32_ntop_extended_hex(uint8_t const *src, size_t srclength, char *target, size_t targsize) { + return ldns_b32_ntop_ar(src, srclength, target, targsize, Base32_extended_hex); +} + diff --git a/compat/b32_pton.c b/compat/b32_pton.c new file mode 100644 index 00000000000..9c261e615b9 --- /dev/null +++ b/compat/b32_pton.c @@ -0,0 +1,387 @@ +/* + * Copyright (c) 1996, 1998 by Internet Software Consortium. + * + * 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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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. + */ + +/* + * Portions Copyright (c) 1995 by International Business Machines, Inc. + * + * International Business Machines, Inc. (hereinafter called IBM) grants + * permission under its copyrights to use, copy, modify, and distribute this + * Software with or without fee, provided that the above copyright notice and + * all paragraphs of this notice appear in all copies, and that the name of IBM + * not be used in connection with the marketing of any product incorporating + * the Software or modifications thereof, without specific, written prior + * permission. + * + * To the extent it has a right to do so, IBM grants an immunity from suit + * under its patents, if any, for the use, sale or manufacture of products to + * the extent that such products are used for performing Domain Name System + * dynamic updates in TCP/IP networks by means of the Software. No immunity is + * granted for any product per se or for any other function of any product. + * + * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, + * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN + * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ +#include + +#include +#include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#include +#include +#include +#include + +/* "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";*/ +static const char Base32[] = + "abcdefghijklmnopqrstuvwxyz234567"; +/* "0123456789ABCDEFGHIJKLMNOPQRSTUV";*/ +static const char Base32_extended_hex[] = + "0123456789abcdefghijklmnopqrstuv"; +static const char Pad32 = '='; + +/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) +5. Base 32 Encoding + + The Base 32 encoding is designed to represent arbitrary sequences of + octets in a form that needs to be case insensitive but need not be + humanly readable. + + A 33-character subset of US-ASCII is used, enabling 5 bits to be + represented per printable character. (The extra 33rd character, "=", + is used to signify a special processing function.) + + The encoding process represents 40-bit groups of input bits as output + strings of 8 encoded characters. Proceeding from left to right, a + 40-bit input group is formed by concatenating 5 8bit input groups. + These 40 bits are then treated as 8 concatenated 5-bit groups, each + of which is translated into a single digit in the base 32 alphabet. + When encoding a bit stream via the base 32 encoding, the bit stream + must be presumed to be ordered with the most-significant-bit first. + That is, the first bit in the stream will be the high-order bit in + the first 8bit byte, and the eighth bit will be the low-order bit in + the first 8bit byte, and so on. + + Each 5-bit group is used as an index into an array of 32 printable + characters. The character referenced by the index is placed in the + output string. These characters, identified in Table 3, below, are + selected from US-ASCII digits and uppercase letters. + + Table 3: The Base 32 Alphabet + + Value Encoding Value Encoding Value Encoding Value Encoding + 0 A 9 J 18 S 27 3 + 1 B 10 K 19 T 28 4 + 2 C 11 L 20 U 29 5 + 3 D 12 M 21 V 30 6 + 4 E 13 N 22 W 31 7 + 5 F 14 O 23 X + 6 G 15 P 24 Y (pad) = + 7 H 16 Q 25 Z + 8 I 17 R 26 2 + + + Special processing is performed if fewer than 40 bits are available + at the end of the data being encoded. A full encoding quantum is + always completed at the end of a body. When fewer than 40 input bits + are available in an input group, zero bits are added (on the right) + to form an integral number of 5-bit groups. Padding at the end of + the data is performed using the "=" character. Since all base 32 + input is an integral number of octets, only the following cases can + arise: + + (1) the final quantum of encoding input is an integral multiple of 40 + bits; here, the final unit of encoded output will be an integral + multiple of 8 characters with no "=" padding, + + (2) the final quantum of encoding input is exactly 8 bits; here, the + final unit of encoded output will be two characters followed by six + "=" padding characters, + + (3) the final quantum of encoding input is exactly 16 bits; here, the + final unit of encoded output will be four characters followed by four + "=" padding characters, + + (4) the final quantum of encoding input is exactly 24 bits; here, the + final unit of encoded output will be five characters followed by + three "=" padding characters, or + + (5) the final quantum of encoding input is exactly 32 bits; here, the + final unit of encoded output will be seven characters followed by one + "=" padding character. + + +6. Base 32 Encoding with Extended Hex Alphabet + + The following description of base 32 is due to [7]. This encoding + should not be regarded as the same as the "base32" encoding, and + should not be referred to as only "base32". + + One property with this alphabet, that the base32 and base32 alphabet + lack, is that encoded data maintain its sort order when the encoded + data is compared bit-wise. + + This encoding is identical to the previous one, except for the + alphabet. The new alphabet is found in table 4. + + Table 4: The "Extended Hex" Base 32 Alphabet + + Value Encoding Value Encoding Value Encoding Value Encoding + 0 0 9 9 18 I 27 R + 1 1 10 A 19 J 28 S + 2 2 11 B 20 K 29 T + 3 3 12 C 21 L 30 U + 4 4 13 D 22 M 31 V + 5 5 14 E 23 N + 6 6 15 F 24 O (pad) = + 7 7 16 G 25 P + 8 8 17 H 26 Q + + + + +*/ +/* skips all whitespace anywhere. + converts characters, four at a time, starting at (or after) + src from base - 32 numbers into three 8 bit bytes in the target area. + it returns the number of data bytes stored at the target, or -1 on error. + */ + +int +ldns_b32_pton_ar(char const *src, size_t hashed_owner_str_len, uint8_t *target, size_t targsize, const char B32_ar[]) +{ + int tarindex, state, ch; + char *pos; + int i = 0; + + state = 0; + tarindex = 0; + + while ((ch = *src++) != '\0' && (i == 0 || i < (int) hashed_owner_str_len)) { + i++; + ch = tolower(ch); + if (isspace((unsigned char)ch)) /* Skip whitespace anywhere. */ + continue; + + if (ch == Pad32) + break; + + pos = strchr(B32_ar, ch); + if (pos == 0) { + /* A non-base32 character. */ + return (-ch); + } + + switch (state) { + case 0: + if (target) { + if ((size_t)tarindex >= targsize) { + return (-2); + } + target[tarindex] = (pos - B32_ar) << 3; + } + state = 1; + break; + case 1: + if (target) { + if ((size_t)tarindex + 1 >= targsize) { + return (-3); + } + target[tarindex] |= (pos - B32_ar) >> 2; + target[tarindex+1] = ((pos - B32_ar) & 0x03) + << 6 ; + } + tarindex++; + state = 2; + break; + case 2: + if (target) { + if ((size_t)tarindex + 1 >= targsize) { + return (-4); + } + target[tarindex] |= (pos - B32_ar) << 1; + } + /*tarindex++;*/ + state = 3; + break; + case 3: + if (target) { + if ((size_t)tarindex + 1 >= targsize) { + return (-5); + } + target[tarindex] |= (pos - B32_ar) >> 4; + target[tarindex+1] = ((pos - B32_ar) & 0x0f) << 4 ; + } + tarindex++; + state = 4; + break; + case 4: + if (target) { + if ((size_t)tarindex + 1 >= targsize) { + return (-6); + } + target[tarindex] |= (pos - B32_ar) >> 1; + target[tarindex+1] = ((pos - B32_ar) & 0x01) + << 7 ; + } + tarindex++; + state = 5; + break; + case 5: + if (target) { + if ((size_t)tarindex + 1 >= targsize) { + return (-7); + } + target[tarindex] |= (pos - B32_ar) << 2; + } + state = 6; + break; + case 6: + if (target) { + if ((size_t)tarindex + 1 >= targsize) { + return (-8); + } + target[tarindex] |= (pos - B32_ar) >> 3; + target[tarindex+1] = ((pos - B32_ar) & 0x07) + << 5 ; + } + tarindex++; + state = 7; + break; + case 7: + if (target) { + if ((size_t)tarindex + 1 >= targsize) { + return (-9); + } + target[tarindex] |= (pos - B32_ar); + } + tarindex++; + state = 0; + break; + default: + abort(); + } + } + + /* + * We are done decoding Base-32 chars. Let's see if we ended + * on a byte boundary, and/or with erroneous trailing characters. + */ + + if (ch == Pad32) { /* We got a pad char. */ + ch = *src++; /* Skip it, get next. */ + switch (state) { + case 0: /* Invalid = in first position */ + case 1: /* Invalid = in second position */ + return (-10); + + case 2: /* Valid, means one byte of info */ + case 3: + /* Skip any number of spaces. */ + for ((void)NULL; ch != '\0'; ch = *src++) + if (!isspace((unsigned char)ch)) + break; + /* Make sure there is another trailing = sign. */ + if (ch != Pad32) { + return (-11); + } + ch = *src++; /* Skip the = */ + /* Fall through to "single trailing =" case. */ + /* FALLTHROUGH */ + + case 4: /* Valid, means two bytes of info */ + case 5: + case 6: + /* + * We know this char is an =. Is there anything but + * whitespace after it? + */ + for ((void)NULL; ch != '\0'; ch = *src++) + if (!(isspace((unsigned char)ch) || ch == '=')) { + return (-12); + } + + case 7: /* Valid, means three bytes of info */ + /* + * We know this char is an =. Is there anything but + * whitespace after it? + */ + for ((void)NULL; ch != '\0'; ch = *src++) + if (!isspace((unsigned char)ch)) { + return (-13); + } + + /* + * Now make sure for cases 2 and 3 that the "extra" + * bits that slopped past the last full byte were + * zeros. If we don't check them, they become a + * subliminal channel. + */ + if (target && target[tarindex] != 0) { + return (-14); + } + } + } else { + /* + * We ended by seeing the end of the string. Make sure we + * have no partial bytes lying around. + */ + if (state != 0) + return (-15); + } + + return (tarindex); +} + +int +ldns_b32_pton(char const *src, size_t hashed_owner_str_len, uint8_t *target, size_t targsize) +{ + return ldns_b32_pton_ar(src, hashed_owner_str_len, target, targsize, Base32); +} + +/* deprecated, here for backwards compatibility */ +int +b32_pton(char const *src, size_t hashed_owner_str_len, uint8_t *target, size_t targsize) +{ + return ldns_b32_pton_ar(src, hashed_owner_str_len, target, targsize, Base32); +} + +int +ldns_b32_pton_extended_hex(char const *src, size_t hashed_owner_str_len, uint8_t *target, size_t targsize) +{ + return ldns_b32_pton_ar(src, hashed_owner_str_len, target, targsize, Base32_extended_hex); +} + +/* deprecated, here for backwards compatibility */ +int +b32_pton_extended_hex(char const *src, size_t hashed_owner_str_len, uint8_t *target, size_t targsize) +{ + return ldns_b32_pton_ar(src, hashed_owner_str_len, target, targsize, Base32_extended_hex); +} diff --git a/compat/b64_ntop.c b/compat/b64_ntop.c new file mode 100644 index 00000000000..d0b52b514bd --- /dev/null +++ b/compat/b64_ntop.c @@ -0,0 +1,202 @@ +/* + * Copyright (c) 1996, 1998 by Internet Software Consortium. + * + * 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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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. + */ + +/* + * Portions Copyright (c) 1995 by International Business Machines, Inc. + * + * International Business Machines, Inc. (hereinafter called IBM) grants + * permission under its copyrights to use, copy, modify, and distribute this + * Software with or without fee, provided that the above copyright notice and + * all paragraphs of this notice appear in all copies, and that the name of IBM + * not be used in connection with the marketing of any product incorporating + * the Software or modifications thereof, without specific, written prior + * permission. + * + * To the extent it has a right to do so, IBM grants an immunity from suit + * under its patents, if any, for the use, sale or manufacture of products to + * the extent that such products are used for performing Domain Name System + * dynamic updates in TCP/IP networks by means of the Software. No immunity is + * granted for any product per se or for any other function of any product. + * + * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, + * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN + * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ +#include + +#include +#include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#include +#include +#include +#include + +#define Assert(Cond) if (!(Cond)) abort() + +static const char Base64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char Pad64 = '='; + +/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) + The following encoding technique is taken from RFC 1521 by Borenstein + and Freed. It is reproduced here in a slightly edited form for + convenience. + + A 65-character subset of US-ASCII is used, enabling 6 bits to be + represented per printable character. (The extra 65th character, "=", + is used to signify a special processing function.) + + The encoding process represents 24-bit groups of input bits as output + strings of 4 encoded characters. Proceeding from left to right, a + 24-bit input group is formed by concatenating 3 8-bit input groups. + These 24 bits are then treated as 4 concatenated 6-bit groups, each + of which is translated into a single digit in the base64 alphabet. + + Each 6-bit group is used as an index into an array of 64 printable + characters. The character referenced by the index is placed in the + output string. + + Table 1: The Base64 Alphabet + + Value Encoding Value Encoding Value Encoding Value Encoding + 0 A 17 R 34 i 51 z + 1 B 18 S 35 j 52 0 + 2 C 19 T 36 k 53 1 + 3 D 20 U 37 l 54 2 + 4 E 21 V 38 m 55 3 + 5 F 22 W 39 n 56 4 + 6 G 23 X 40 o 57 5 + 7 H 24 Y 41 p 58 6 + 8 I 25 Z 42 q 59 7 + 9 J 26 a 43 r 60 8 + 10 K 27 b 44 s 61 9 + 11 L 28 c 45 t 62 + + 12 M 29 d 46 u 63 / + 13 N 30 e 47 v + 14 O 31 f 48 w (pad) = + 15 P 32 g 49 x + 16 Q 33 h 50 y + + Special processing is performed if fewer than 24 bits are available + at the end of the data being encoded. A full encoding quantum is + always completed at the end of a quantity. When fewer than 24 input + bits are available in an input group, zero bits are added (on the + right) to form an integral number of 6-bit groups. Padding at the + end of the data is performed using the '=' character. + + Since all base64 input is an integral number of octets, only the + ------------------------------------------------- + following cases can arise: + + (1) the final quantum of encoding input is an integral + multiple of 24 bits; here, the final unit of encoded + output will be an integral multiple of 4 characters + with no "=" padding, + (2) the final quantum of encoding input is exactly 8 bits; + here, the final unit of encoded output will be two + characters followed by two "=" padding characters, or + (3) the final quantum of encoding input is exactly 16 bits; + here, the final unit of encoded output will be three + characters followed by one "=" padding character. + */ + +int +ldns_b64_ntop(uint8_t const *src, size_t srclength, char *target, size_t targsize) { + size_t datalength = 0; + uint8_t input[3]; + uint8_t output[4]; + size_t i; + + if (srclength == 0) { + if (targsize > 0) { + target[0] = '\0'; + return 0; + } else { + return -1; + } + } + + while (2 < srclength) { + input[0] = *src++; + input[1] = *src++; + input[2] = *src++; + srclength -= 3; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + output[3] = input[2] & 0x3f; + Assert(output[0] < 64); + Assert(output[1] < 64); + Assert(output[2] < 64); + Assert(output[3] < 64); + + if (datalength + 4 > targsize) { + return (-1); + } + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + target[datalength++] = Base64[output[2]]; + target[datalength++] = Base64[output[3]]; + } + + /* Now we worry about padding. */ + if (0 != srclength) { + /* Get what's left. */ + input[0] = input[1] = input[2] = (uint8_t) '\0'; + for (i = 0; i < srclength; i++) + input[i] = *src++; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + Assert(output[0] < 64); + Assert(output[1] < 64); + Assert(output[2] < 64); + + if (datalength + 4 > targsize) { + return (-2); + } + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + if (srclength == 1) { + target[datalength++] = Pad64; + } else { + target[datalength++] = Base64[output[2]]; + } + target[datalength++] = Pad64; + } + if (datalength >= targsize) { + return (-3); + } + target[datalength] = '\0'; /* Returned value doesn't count \0. */ + return (int) (datalength); +} diff --git a/compat/b64_pton.c b/compat/b64_pton.c new file mode 100644 index 00000000000..aa637d22754 --- /dev/null +++ b/compat/b64_pton.c @@ -0,0 +1,260 @@ +/* + * Copyright (c) 1996, 1998 by Internet Software Consortium. + * + * 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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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. + */ + +/* + * Portions Copyright (c) 1995 by International Business Machines, Inc. + * + * International Business Machines, Inc. (hereinafter called IBM) grants + * permission under its copyrights to use, copy, modify, and distribute this + * Software with or without fee, provided that the above copyright notice and + * all paragraphs of this notice appear in all copies, and that the name of IBM + * not be used in connection with the marketing of any product incorporating + * the Software or modifications thereof, without specific, written prior + * permission. + * + * To the extent it has a right to do so, IBM grants an immunity from suit + * under its patents, if any, for the use, sale or manufacture of products to + * the extent that such products are used for performing Domain Name System + * dynamic updates in TCP/IP networks by means of the Software. No immunity is + * granted for any product per se or for any other function of any product. + * + * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, + * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN + * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ +#include + +#include +#include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#include +#include +#include +#include + +#define Assert(Cond) if (!(Cond)) abort() + +static const char Base64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char Pad64 = '='; + +/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) + The following encoding technique is taken from RFC 1521 by Borenstein + and Freed. It is reproduced here in a slightly edited form for + convenience. + + A 65-character subset of US-ASCII is used, enabling 6 bits to be + represented per printable character. (The extra 65th character, "=", + is used to signify a special processing function.) + + The encoding process represents 24-bit groups of input bits as output + strings of 4 encoded characters. Proceeding from left to right, a + 24-bit input group is formed by concatenating 3 8-bit input groups. + These 24 bits are then treated as 4 concatenated 6-bit groups, each + of which is translated into a single digit in the base64 alphabet. + + Each 6-bit group is used as an index into an array of 64 printable + characters. The character referenced by the index is placed in the + output string. + + Table 1: The Base64 Alphabet + + Value Encoding Value Encoding Value Encoding Value Encoding + 0 A 17 R 34 i 51 z + 1 B 18 S 35 j 52 0 + 2 C 19 T 36 k 53 1 + 3 D 20 U 37 l 54 2 + 4 E 21 V 38 m 55 3 + 5 F 22 W 39 n 56 4 + 6 G 23 X 40 o 57 5 + 7 H 24 Y 41 p 58 6 + 8 I 25 Z 42 q 59 7 + 9 J 26 a 43 r 60 8 + 10 K 27 b 44 s 61 9 + 11 L 28 c 45 t 62 + + 12 M 29 d 46 u 63 / + 13 N 30 e 47 v + 14 O 31 f 48 w (pad) = + 15 P 32 g 49 x + 16 Q 33 h 50 y + + Special processing is performed if fewer than 24 bits are available + at the end of the data being encoded. A full encoding quantum is + always completed at the end of a quantity. When fewer than 24 input + bits are available in an input group, zero bits are added (on the + right) to form an integral number of 6-bit groups. Padding at the + end of the data is performed using the '=' character. + + Since all base64 input is an integral number of octets, only the + ------------------------------------------------- + following cases can arise: + + (1) the final quantum of encoding input is an integral + multiple of 24 bits; here, the final unit of encoded + output will be an integral multiple of 4 characters + with no "=" padding, + (2) the final quantum of encoding input is exactly 8 bits; + here, the final unit of encoded output will be two + characters followed by two "=" padding characters, or + (3) the final quantum of encoding input is exactly 16 bits; + here, the final unit of encoded output will be three + characters followed by one "=" padding character. + */ + +/* skips all whitespace anywhere. + converts characters, four at a time, starting at (or after) + src from base - 64 numbers into three 8 bit bytes in the target area. + it returns the number of data bytes stored at the target, or -1 on error. + */ + +int +ldns_b64_pton(char const *src, uint8_t *target, size_t targsize) +{ + int tarindex, state, ch; + char *pos; + + state = 0; + tarindex = 0; + + if (strlen(src) == 0) { + return 0; + } + + while ((ch = *src++) != '\0') { + if (isspace((unsigned char)ch)) /* Skip whitespace anywhere. */ + continue; + + if (ch == Pad64) + break; + + pos = strchr(Base64, ch); + if (pos == 0) { + /* A non-base64 character. */ + return (-1); + } + + switch (state) { + case 0: + if (target) { + if ((size_t)tarindex >= targsize) + return (-1); + target[tarindex] = (pos - Base64) << 2; + } + state = 1; + break; + case 1: + if (target) { + if ((size_t)tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 4; + target[tarindex+1] = ((pos - Base64) & 0x0f) + << 4 ; + } + tarindex++; + state = 2; + break; + case 2: + if (target) { + if ((size_t)tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 2; + target[tarindex+1] = ((pos - Base64) & 0x03) + << 6; + } + tarindex++; + state = 3; + break; + case 3: + if (target) { + if ((size_t)tarindex >= targsize) + return (-1); + target[tarindex] |= (pos - Base64); + } + tarindex++; + state = 0; + break; + default: + abort(); + } + } + + /* + * We are done decoding Base-64 chars. Let's see if we ended + * on a byte boundary, and/or with erroneous trailing characters. + */ + + if (ch == Pad64) { /* We got a pad char. */ + ch = *src++; /* Skip it, get next. */ + switch (state) { + case 0: /* Invalid = in first position */ + case 1: /* Invalid = in second position */ + return (-1); + + case 2: /* Valid, means one byte of info */ + /* Skip any number of spaces. */ + for ((void)NULL; ch != '\0'; ch = *src++) + if (!isspace((unsigned char)ch)) + break; + /* Make sure there is another trailing = sign. */ + if (ch != Pad64) + return (-1); + ch = *src++; /* Skip the = */ + /* Fall through to "single trailing =" case. */ + /* FALLTHROUGH */ + + case 3: /* Valid, means two bytes of info */ + /* + * We know this char is an =. Is there anything but + * whitespace after it? + */ + for ((void)NULL; ch != '\0'; ch = *src++) + if (!isspace((unsigned char)ch)) + return (-1); + + /* + * Now make sure for cases 2 and 3 that the "extra" + * bits that slopped past the last full byte were + * zeros. If we don't check them, they become a + * subliminal channel. + */ + if (target && target[tarindex] != 0) + return (-1); + } + } else { + /* + * We ended by seeing the end of the string. Make sure we + * have no partial bytes lying around. + */ + if (state != 0) + return (-1); + } + + return (tarindex); +} diff --git a/compat/calloc.c b/compat/calloc.c new file mode 100644 index 00000000000..c86b956757f --- /dev/null +++ b/compat/calloc.c @@ -0,0 +1,24 @@ +/* Just a replacement, if the original malloc is not + GNU-compliant. See autoconf documentation. */ + +#if HAVE_CONFIG_H +#include +#endif + +void *calloc(); + +#if !HAVE_BZERO && HAVE_MEMSET +# define bzero(buf, bytes) ((void) memset (buf, 0, bytes)) +#endif + +void * +calloc(size_t num, size_t size) +{ + void *new = malloc(num * size); + if (!new) { + return NULL; + } + bzero(new, num * size); + return new; +} + diff --git a/compat/ctime_r.c b/compat/ctime_r.c new file mode 100644 index 00000000000..4ffd8b7e352 --- /dev/null +++ b/compat/ctime_r.c @@ -0,0 +1,16 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_TIME_H +#include +#endif + +char *ctime_r(const time_t *timep, char *buf) +{ + /* no thread safety. */ + char* result = ctime(timep); + if(buf && result) + strcpy(buf, result); + return result; +} diff --git a/compat/fake-rfc2553.c b/compat/fake-rfc2553.c new file mode 100644 index 00000000000..431e04a2156 --- /dev/null +++ b/compat/fake-rfc2553.c @@ -0,0 +1,229 @@ +/* From openssh 4.3p2 filename openbsd-compat/fake-rfc2553.h */ +/* + * Copyright (C) 2000-2003 Damien Miller. All rights reserved. + * Copyright (C) 1999 WIDE Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Pseudo-implementation of RFC2553 name / address resolution functions + * + * But these functions are not implemented correctly. The minimum subset + * is implemented for ssh use only. For example, this routine assumes + * that ai_family is AF_INET. Don't use it for another purpose. + */ + +#include +#include +#include +#include +#include +#include +#include "compat/fake-rfc2553.h" + +#ifndef HAVE_GETNAMEINFO +int getnameinfo(const struct sockaddr *sa, size_t ATTR_UNUSED(salen), char *host, + size_t hostlen, char *serv, size_t servlen, int flags) +{ + struct sockaddr_in *sin = (struct sockaddr_in *)sa; + struct hostent *hp; + char tmpserv[16]; + + if (serv != NULL) { + snprintf(tmpserv, sizeof(tmpserv), "%d", ntohs(sin->sin_port)); + if (strlcpy(serv, tmpserv, servlen) >= servlen) + return (EAI_MEMORY); + } + + if (host != NULL) { + if (flags & NI_NUMERICHOST) { + if (strlcpy(host, inet_ntoa(sin->sin_addr), + hostlen) >= hostlen) + return (EAI_MEMORY); + else + return (0); + } else { + hp = gethostbyaddr((char *)&sin->sin_addr, + sizeof(struct in_addr), AF_INET); + if (hp == NULL) + return (EAI_NODATA); + + if (strlcpy(host, hp->h_name, hostlen) >= hostlen) + return (EAI_MEMORY); + else + return (0); + } + } + return (0); +} +#endif /* !HAVE_GETNAMEINFO */ + +#ifndef HAVE_GAI_STRERROR +#ifdef HAVE_CONST_GAI_STRERROR_PROTO +const char * +#else +char * +#endif +gai_strerror(int err) +{ + switch (err) { + case EAI_NODATA: + return ("no address associated with name"); + case EAI_MEMORY: + return ("memory allocation failure."); + case EAI_NONAME: + return ("nodename nor servname provided, or not known"); + default: + return ("unknown/invalid error."); + } +} +#endif /* !HAVE_GAI_STRERROR */ + +#ifndef HAVE_FREEADDRINFO +void +freeaddrinfo(struct addrinfo *ai) +{ + struct addrinfo *next; + + for(; ai != NULL;) { + next = ai->ai_next; + free(ai); + ai = next; + } +} +#endif /* !HAVE_FREEADDRINFO */ + +#ifndef HAVE_GETADDRINFO +static struct +addrinfo *malloc_ai(int port, u_long addr, const struct addrinfo *hints) +{ + struct addrinfo *ai; + + ai = malloc(sizeof(*ai) + sizeof(struct sockaddr_in)); + if (ai == NULL) + return (NULL); + + memset(ai, '\0', sizeof(*ai) + sizeof(struct sockaddr_in)); + + ai->ai_addr = (struct sockaddr *)(ai + 1); + /* XXX -- ssh doesn't use sa_len */ + ai->ai_addrlen = sizeof(struct sockaddr_in); + ai->ai_addr->sa_family = ai->ai_family = AF_INET; + + ((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port; + ((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr; + + /* XXX: the following is not generally correct, but does what we want */ + if (hints->ai_socktype) + ai->ai_socktype = hints->ai_socktype; + else + ai->ai_socktype = SOCK_STREAM; + + if (hints->ai_protocol) + ai->ai_protocol = hints->ai_protocol; + + return (ai); +} + +int +getaddrinfo(const char *hostname, const char *servname, + const struct addrinfo *hints, struct addrinfo **res) +{ + struct hostent *hp; + struct servent *sp; + struct in_addr in; + int i; + long int port; + u_long addr; + + port = 0; + if (servname != NULL) { + char *cp; + + port = strtol(servname, &cp, 10); + if (port > 0 && port <= 65535 && *cp == '\0') + port = htons(port); + else if ((sp = getservbyname(servname, NULL)) != NULL) + port = sp->s_port; + else + port = 0; + } + + if (hints && hints->ai_flags & AI_PASSIVE) { + addr = htonl(0x00000000); + if (hostname && inet_aton(hostname, &in) != 0) + addr = in.s_addr; + *res = malloc_ai(port, addr, hints); + if (*res == NULL) + return (EAI_MEMORY); + return (0); + } + + if (!hostname) { + *res = malloc_ai(port, htonl(0x7f000001), hints); + if (*res == NULL) + return (EAI_MEMORY); + return (0); + } + + if (inet_aton(hostname, &in)) { + *res = malloc_ai(port, in.s_addr, hints); + if (*res == NULL) + return (EAI_MEMORY); + return (0); + } + + /* Don't try DNS if AI_NUMERICHOST is set */ + if (hints && hints->ai_flags & AI_NUMERICHOST) + return (EAI_NONAME); + + hp = gethostbyname(hostname); + if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) { + struct addrinfo *cur, *prev; + + cur = prev = *res = NULL; + for (i = 0; hp->h_addr_list[i]; i++) { + struct in_addr *in = (struct in_addr *)hp->h_addr_list[i]; + + cur = malloc_ai(port, in->s_addr, hints); + if (cur == NULL) { + if (*res != NULL) + freeaddrinfo(*res); + return (EAI_MEMORY); + } + if (prev) + prev->ai_next = cur; + else + *res = cur; + + prev = cur; + } + return (0); + } + + return (EAI_NODATA); +} +#endif /* !HAVE_GETADDRINFO */ diff --git a/compat/fake-rfc2553.h b/compat/fake-rfc2553.h new file mode 100644 index 00000000000..4c277ee902d --- /dev/null +++ b/compat/fake-rfc2553.h @@ -0,0 +1,183 @@ +/* From openssh 4.3p2 filename openbsd-compat/fake-rfc2553.h */ +/* + * Copyright (C) 2000-2003 Damien Miller. All rights reserved. + * Copyright (C) 1999 WIDE Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Pseudo-implementation of RFC2553 name / address resolution functions + * + * But these functions are not implemented correctly. The minimum subset + * is implemented for ssh use only. For example, this routine assumes + * that ai_family is AF_INET. Don't use it for another purpose. + */ + +#ifndef _FAKE_RFC2553_H +#define _FAKE_RFC2553_H + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * First, socket and INET6 related definitions + */ +#ifndef HAVE_STRUCT_SOCKADDR_STORAGE +#ifndef _SS_MAXSIZE +# define _SS_MAXSIZE 128 /* Implementation specific max size */ +# define _SS_PADSIZE (_SS_MAXSIZE - sizeof (struct sockaddr)) +struct sockaddr_storage { + struct sockaddr ss_sa; + char __ss_pad2[_SS_PADSIZE]; +}; +# define ss_family ss_sa.sa_family +#endif /* _SS_MAXSIZE */ +#endif /* !HAVE_STRUCT_SOCKADDR_STORAGE */ + +#ifndef IN6_IS_ADDR_LOOPBACK +# define IN6_IS_ADDR_LOOPBACK(a) \ + (((uint32_t *)(a))[0] == 0 && ((uint32_t *)(a))[1] == 0 && \ + ((uint32_t *)(a))[2] == 0 && ((uint32_t *)(a))[3] == htonl(1)) +#endif /* !IN6_IS_ADDR_LOOPBACK */ + +#ifndef HAVE_STRUCT_IN6_ADDR +struct in6_addr { + uint8_t s6_addr[16]; +}; +#endif /* !HAVE_STRUCT_IN6_ADDR */ + +#ifndef HAVE_STRUCT_SOCKADDR_IN6 +struct sockaddr_in6 { + unsigned short sin6_family; + uint16_t sin6_port; + uint32_t sin6_flowinfo; + struct in6_addr sin6_addr; +}; +#endif /* !HAVE_STRUCT_SOCKADDR_IN6 */ + +#ifndef AF_INET6 +/* Define it to something that should never appear */ +#define AF_INET6 AF_MAX +#endif + +/* + * Next, RFC2553 name / address resolution API + */ + +#ifndef NI_NUMERICHOST +# define NI_NUMERICHOST (1) +#endif +#ifndef NI_NAMEREQD +# define NI_NAMEREQD (1<<1) +#endif +#ifndef NI_NUMERICSERV +# define NI_NUMERICSERV (1<<2) +#endif + +#ifndef AI_PASSIVE +# define AI_PASSIVE (1) +#endif +#ifndef AI_CANONNAME +# define AI_CANONNAME (1<<1) +#endif +#ifndef AI_NUMERICHOST +# define AI_NUMERICHOST (1<<2) +#endif + +#ifndef NI_MAXSERV +# define NI_MAXSERV 32 +#endif /* !NI_MAXSERV */ +#ifndef NI_MAXHOST +# define NI_MAXHOST 1025 +#endif /* !NI_MAXHOST */ + +#ifndef INT_MAX +#define INT_MAX 0xffffffff +#endif + +#ifndef EAI_NODATA +# define EAI_NODATA (INT_MAX - 1) +#endif +#ifndef EAI_MEMORY +# define EAI_MEMORY (INT_MAX - 2) +#endif +#ifndef EAI_NONAME +# define EAI_NONAME (INT_MAX - 3) +#endif +#ifndef EAI_SYSTEM +# define EAI_SYSTEM (INT_MAX - 4) +#endif + +#ifndef HAVE_STRUCT_ADDRINFO +struct addrinfo { + int ai_flags; /* AI_PASSIVE, AI_CANONNAME */ + int ai_family; /* PF_xxx */ + int ai_socktype; /* SOCK_xxx */ + int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ + size_t ai_addrlen; /* length of ai_addr */ + char *ai_canonname; /* canonical name for hostname */ + struct sockaddr *ai_addr; /* binary address */ + struct addrinfo *ai_next; /* next structure in linked list */ +}; +#endif /* !HAVE_STRUCT_ADDRINFO */ + +#ifndef HAVE_GETADDRINFO +#ifdef getaddrinfo +# undef getaddrinfo +#endif +#define getaddrinfo(a,b,c,d) (ssh_getaddrinfo(a,b,c,d)) +int getaddrinfo(const char *, const char *, + const struct addrinfo *, struct addrinfo **); +#endif /* !HAVE_GETADDRINFO */ + +#if !defined(HAVE_GAI_STRERROR) && !defined(HAVE_CONST_GAI_STRERROR_PROTO) +#define gai_strerror(a) (ssh_gai_strerror(a)) +char *gai_strerror(int); +#endif /* !HAVE_GAI_STRERROR */ + +#ifndef HAVE_FREEADDRINFO +#define freeaddrinfo(a) (ssh_freeaddrinfo(a)) +void freeaddrinfo(struct addrinfo *); +#endif /* !HAVE_FREEADDRINFO */ + +#ifndef HAVE_GETNAMEINFO +#define getnameinfo(a,b,c,d,e,f,g) (ssh_getnameinfo(a,b,c,d,e,f,g)) +int getnameinfo(const struct sockaddr *, size_t, char *, size_t, + char *, size_t, int); +#endif /* !HAVE_GETNAMEINFO */ + +#ifdef __cplusplus +} +#endif + +#endif /* !_FAKE_RFC2553_H */ + diff --git a/compat/gmtime_r.c b/compat/gmtime_r.c new file mode 100644 index 00000000000..7062e7dee30 --- /dev/null +++ b/compat/gmtime_r.c @@ -0,0 +1,14 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_TIME_H +#include +#endif + +struct tm *gmtime_r(const time_t *timep, struct tm *result) +{ + /* no thread safety. */ + *result = *gmtime(timep); + return result; +} diff --git a/compat/inet_aton.c b/compat/inet_aton.c new file mode 100644 index 00000000000..e8c3a57b9ac --- /dev/null +++ b/compat/inet_aton.c @@ -0,0 +1,182 @@ +/* From openssh4.3p2 compat/inet_aton.c */ +/* + * Copyright (c) 1983, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * - + * Portions Copyright (c) 1993 by Digital Equipment Corporation. + * + * 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, and that + * the name of Digital Equipment Corporation not be used in advertising or + * publicity pertaining to distribution of the document or software without + * specific, written prior permission. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION 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. + * - + * --Copyright-- + */ + +/* OPENBSD ORIGINAL: lib/libc/net/inet_addr.c */ + +#include + +#if !defined(HAVE_INET_ATON) + +#include +#include +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#include + +#if 0 +/* + * Ascii internet address interpretation routine. + * The value returned is in network order. + */ +in_addr_t +inet_addr(const char *cp) +{ + struct in_addr val; + + if (inet_aton(cp, &val)) + return (val.s_addr); + return (INADDR_NONE); +} +#endif + +/* + * Check whether "cp" is a valid ascii representation + * of an Internet address and convert to a binary address. + * Returns 1 if the address is valid, 0 if not. + * This replaces inet_addr, the return value from which + * cannot distinguish between failure and a local broadcast address. + */ +int +inet_aton(const char *cp, struct in_addr *addr) +{ + uint32_t val; + int base, n; + char c; + unsigned int parts[4]; + unsigned int *pp = parts; + + c = *cp; + for (;;) { + /* + * Collect number up to ``.''. + * Values are specified as for C: + * 0x=hex, 0=octal, isdigit=decimal. + */ + if (!isdigit((int) c)) + return (0); + val = 0; base = 10; + if (c == '0') { + c = *++cp; + if (c == 'x' || c == 'X') + base = 16, c = *++cp; + else + base = 8; + } + for (;;) { + if (isascii((int) c) && isdigit((int) c)) { + val = (val * base) + (c - '0'); + c = *++cp; + } else if (base == 16 && isascii((int) c) && isxdigit((int) c)) { + val = (val << 4) | + (c + 10 - (islower((int) c) ? 'a' : 'A')); + c = *++cp; + } else + break; + } + if (c == '.') { + /* + * Internet format: + * a.b.c.d + * a.b.c (with c treated as 16 bits) + * a.b (with b treated as 24 bits) + */ + if (pp >= parts + 3) + return (0); + *pp++ = val; + c = *++cp; + } else + break; + } + /* + * Check for trailing characters. + */ + if (c != '\0' && (!isascii((int) c) || !isspace((int) c))) + return (0); + /* + * Concoct the address according to + * the number of parts specified. + */ + n = pp - parts + 1; + switch (n) { + + case 0: + return (0); /* initial nondigit */ + + case 1: /* a -- 32 bits */ + break; + + case 2: /* a.b -- 8.24 bits */ + if ((val > 0xffffff) || (parts[0] > 0xff)) + return (0); + val |= parts[0] << 24; + break; + + case 3: /* a.b.c -- 8.8.16 bits */ + if ((val > 0xffff) || (parts[0] > 0xff) || (parts[1] > 0xff)) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16); + break; + + case 4: /* a.b.c.d -- 8.8.8.8 bits */ + if ((val > 0xff) || (parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff)) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); + break; + } + if (addr) + addr->s_addr = htonl(val); + return (1); +} + +#endif /* !defined(HAVE_INET_ATON) */ diff --git a/compat/inet_ntop.c b/compat/inet_ntop.c new file mode 100644 index 00000000000..52197d0e6d4 --- /dev/null +++ b/compat/inet_ntop.c @@ -0,0 +1,218 @@ +/* From openssh 4.3p2 compat/inet_ntop.c */ +/* Copyright (c) 1996 by Internet Software Consortium. + * + * 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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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. + */ + +/* OPENBSD ORIGINAL: lib/libc/net/inet_ntop.c */ + +#include + +#ifndef HAVE_INET_NTOP + +#include +#include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#include +#include +#include + +#ifndef IN6ADDRSZ +#define IN6ADDRSZ 16 /* IPv6 T_AAAA */ +#endif + +#ifndef INT16SZ +#define INT16SZ 2 /* for systems without 16-bit ints */ +#endif + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + +static const char *inet_ntop4(const u_char *src, char *dst, size_t size); +static const char *inet_ntop6(const u_char *src, char *dst, size_t size); + +/* char * + * inet_ntop(af, src, dst, size) + * convert a network format address to presentation format. + * return: + * pointer to presentation format address (`dst'), or NULL (see errno). + * author: + * Paul Vixie, 1996. + */ +const char * +inet_ntop(int af, const void *src, char *dst, size_t size) +{ + switch (af) { + case AF_INET: + return (inet_ntop4(src, dst, size)); + case AF_INET6: + return (inet_ntop6(src, dst, size)); + default: +#ifdef EAFNOSUPPORT + errno = EAFNOSUPPORT; +#else + errno = ENOSYS; +#endif + return (NULL); + } + /* NOTREACHED */ +} + +/* const char * + * inet_ntop4(src, dst, size) + * format an IPv4 address, more or less like inet_ntoa() + * return: + * `dst' (as a const) + * notes: + * (1) uses no statics + * (2) takes a u_char* not an in_addr as input + * author: + * Paul Vixie, 1996. + */ +static const char * +inet_ntop4(const u_char *src, char *dst, size_t size) +{ + static const char fmt[] = "%u.%u.%u.%u"; + char tmp[sizeof "255.255.255.255"]; + int l; + + l = snprintf(tmp, size, fmt, src[0], src[1], src[2], src[3]); + if (l <= 0 || l >= (int)size) { + errno = ENOSPC; + return (NULL); + } + strlcpy(dst, tmp, size); + return (dst); +} + +/* const char * + * inet_ntop6(src, dst, size) + * convert IPv6 binary address into presentation (printable) format + * author: + * Paul Vixie, 1996. + */ +static const char * +inet_ntop6(const u_char *src, char *dst, size_t size) +{ + /* + * Note that int32_t and int16_t need only be "at least" large enough + * to contain a value of the specified size. On some systems, like + * Crays, there is no such thing as an integer variable with 16 bits. + * Keep this in mind if you think this function should have been coded + * to use pointer overlays. All the world's not a VAX. + */ + char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; + char *tp, *ep; + struct { int base, len; } best, cur; + u_int words[IN6ADDRSZ / INT16SZ]; + int i; + int advance; + + /* + * Preprocess: + * Copy the input (bytewise) array into a wordwise array. + * Find the longest run of 0x00's in src[] for :: shorthanding. + */ + memset(words, '\0', sizeof words); + for (i = 0; i < IN6ADDRSZ; i++) + words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); + best.base = -1; + best.len = 0; + cur.base = -1; + cur.len = 0; + for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { + if (words[i] == 0) { + if (cur.base == -1) + cur.base = i, cur.len = 1; + else + cur.len++; + } else { + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + cur.base = -1; + } + } + } + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + } + if (best.base != -1 && best.len < 2) + best.base = -1; + + /* + * Format the result. + */ + tp = tmp; + ep = tmp + sizeof(tmp); + for (i = 0; i < (IN6ADDRSZ / INT16SZ) && tp < ep; i++) { + /* Are we inside the best run of 0x00's? */ + if (best.base != -1 && i >= best.base && + i < (best.base + best.len)) { + if (i == best.base) { + if (tp + 1 >= ep) + return (NULL); + *tp++ = ':'; + } + continue; + } + /* Are we following an initial run of 0x00s or any real hex? */ + if (i != 0) { + if (tp + 1 >= ep) + return (NULL); + *tp++ = ':'; + } + /* Is this address an encapsulated IPv4? */ + if (i == 6 && best.base == 0 && + (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { + if (!inet_ntop4(src+12, tp, (size_t)(ep - tp))) + return (NULL); + tp += strlen(tp); + break; + } + advance = snprintf(tp, ep - tp, "%x", words[i]); + if (advance <= 0 || advance >= ep - tp) + return (NULL); + tp += advance; + } + /* Was it a trailing run of 0x00's? */ + if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) { + if (tp + 1 >= ep) + return (NULL); + *tp++ = ':'; + } + if (tp + 1 >= ep) + return (NULL); + *tp++ = '\0'; + + /* + * Check for overflow, copy, and we're done. + */ + if ((size_t)(tp - tmp) > size) { + errno = ENOSPC; + return (NULL); + } + strlcpy(dst, tmp, size); + return (dst); +} + +#endif /* !HAVE_INET_NTOP */ diff --git a/compat/inet_pton.c b/compat/inet_pton.c new file mode 100644 index 00000000000..7a4f57614fc --- /dev/null +++ b/compat/inet_pton.c @@ -0,0 +1,230 @@ +/* $KAME: inet_pton.c,v 1.5 2001/08/20 02:32:40 itojun Exp $ */ + +/* Copyright (c) 1996 by Internet Software Consortium. + * + * 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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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. + */ + +#include + +#include +#include +#include + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + +static int inet_pton4 (const char *src, uint8_t *dst); +static int inet_pton6 (const char *src, uint8_t *dst); + +/* + * + * The definitions we might miss. + * + */ +#ifndef NS_INT16SZ +#define NS_INT16SZ 2 +#endif + +#ifndef NS_IN6ADDRSZ +#define NS_IN6ADDRSZ 16 +#endif + +#ifndef NS_INADDRSZ +#define NS_INADDRSZ 4 +#endif + +/* int + * inet_pton(af, src, dst) + * convert from presentation format (which usually means ASCII printable) + * to network format (which is usually some kind of binary format). + * return: + * 1 if the address was valid for the specified address family + * 0 if the address wasn't valid (`dst' is untouched in this case) + * -1 if some other error occurred (`dst' is untouched in this case, too) + * author: + * Paul Vixie, 1996. + */ +int +inet_pton(af, src, dst) + int af; + const char *src; + void *dst; +{ + switch (af) { + case AF_INET: + return (inet_pton4(src, dst)); + case AF_INET6: + return (inet_pton6(src, dst)); + default: +#ifdef EAFNOSUPPORT + errno = EAFNOSUPPORT; +#else + errno = ENOSYS; +#endif + return (-1); + } + /* NOTREACHED */ +} + +/* int + * inet_pton4(src, dst) + * like inet_aton() but without all the hexadecimal and shorthand. + * return: + * 1 if `src' is a valid dotted quad, else 0. + * notice: + * does not touch `dst' unless it's returning 1. + * author: + * Paul Vixie, 1996. + */ +static int +inet_pton4(src, dst) + const char *src; + uint8_t *dst; +{ + static const char digits[] = "0123456789"; + int saw_digit, octets, ch; + uint8_t tmp[NS_INADDRSZ], *tp; + + saw_digit = 0; + octets = 0; + *(tp = tmp) = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + if ((pch = strchr(digits, ch)) != NULL) { + uint32_t new = *tp * 10 + (pch - digits); + + if (new > 255) + return (0); + *tp = new; + if (! saw_digit) { + if (++octets > 4) + return (0); + saw_digit = 1; + } + } else if (ch == '.' && saw_digit) { + if (octets == 4) + return (0); + *++tp = 0; + saw_digit = 0; + } else + return (0); + } + if (octets < 4) + return (0); + + memcpy(dst, tmp, NS_INADDRSZ); + return (1); +} + +/* int + * inet_pton6(src, dst) + * convert presentation level address to network order binary form. + * return: + * 1 if `src' is a valid [RFC1884 2.2] address, else 0. + * notice: + * (1) does not touch `dst' unless it's returning 1. + * (2) :: in a full address is silently ignored. + * credit: + * inspired by Mark Andrews. + * author: + * Paul Vixie, 1996. + */ +static int +inet_pton6(src, dst) + const char *src; + uint8_t *dst; +{ + static const char xdigits_l[] = "0123456789abcdef", + xdigits_u[] = "0123456789ABCDEF"; + uint8_t tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; + const char *xdigits, *curtok; + int ch, saw_xdigit; + uint32_t val; + + memset((tp = tmp), '\0', NS_IN6ADDRSZ); + endp = tp + NS_IN6ADDRSZ; + colonp = NULL; + /* Leading :: requires some special handling. */ + if (*src == ':') + if (*++src != ':') + return (0); + curtok = src; + saw_xdigit = 0; + val = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) + pch = strchr((xdigits = xdigits_u), ch); + if (pch != NULL) { + val <<= 4; + val |= (pch - xdigits); + if (val > 0xffff) + return (0); + saw_xdigit = 1; + continue; + } + if (ch == ':') { + curtok = src; + if (!saw_xdigit) { + if (colonp) + return (0); + colonp = tp; + continue; + } + if (tp + NS_INT16SZ > endp) + return (0); + *tp++ = (uint8_t) (val >> 8) & 0xff; + *tp++ = (uint8_t) val & 0xff; + saw_xdigit = 0; + val = 0; + continue; + } + if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && + inet_pton4(curtok, tp) > 0) { + tp += NS_INADDRSZ; + saw_xdigit = 0; + break; /* '\0' was seen by inet_pton4(). */ + } + return (0); + } + if (saw_xdigit) { + if (tp + NS_INT16SZ > endp) + return (0); + *tp++ = (uint8_t) (val >> 8) & 0xff; + *tp++ = (uint8_t) val & 0xff; + } + if (colonp != NULL) { + /* + * Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + const int n = tp - colonp; + int i; + + for (i = 1; i <= n; i++) { + endp[- i] = colonp[n - i]; + colonp[n - i] = 0; + } + tp = endp; + } + if (tp != endp) + return (0); + memcpy(dst, tmp, NS_IN6ADDRSZ); + return (1); +} diff --git a/compat/isascii.c b/compat/isascii.c new file mode 100644 index 00000000000..8a4ab374311 --- /dev/null +++ b/compat/isascii.c @@ -0,0 +1,15 @@ +/* Just a replacement, if the original isascii is not + present */ + +#if HAVE_CONFIG_H +#include +#endif + +int isascii(int c); + +/* true if character is ascii. */ +int +isascii(int c) +{ + return c >= 0 && c < 128; +} diff --git a/compat/isblank.c b/compat/isblank.c new file mode 100644 index 00000000000..3b38154c5fd --- /dev/null +++ b/compat/isblank.c @@ -0,0 +1,15 @@ +/* Just a replacement, if the original isblank is not + present */ + +#if HAVE_CONFIG_H +#include +#endif + +int isblank(int c); + +/* true if character is a blank (space or tab). C99. */ +int +isblank(int c) +{ + return (c == ' ') || (c == '\t'); +} diff --git a/compat/localtime_r.c b/compat/localtime_r.c new file mode 100644 index 00000000000..017c6e4d659 --- /dev/null +++ b/compat/localtime_r.c @@ -0,0 +1,14 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_TIME_H +#include +#endif + +struct tm *localtime_r(const time_t *timep, struct tm *result) +{ + /* no thread safety. */ + *result = *localtime(timep); + return result; +} diff --git a/compat/malloc.c b/compat/malloc.c new file mode 100644 index 00000000000..bbc632e4f63 --- /dev/null +++ b/compat/malloc.c @@ -0,0 +1,22 @@ +/* Just a replacement, if the original malloc is not + GNU-compliant. See autoconf documentation. */ + +#if HAVE_CONFIG_H +#include +#endif +#undef malloc + +#include + +void *malloc (); + +/* Allocate an N-byte block of memory from the heap. + If N is zero, allocate a 1-byte block. */ + +void * +rpl_malloc (size_t n) +{ + if (n == 0) + n = 1; + return malloc (n); +} diff --git a/compat/memmove.c b/compat/memmove.c new file mode 100644 index 00000000000..e458092c33f --- /dev/null +++ b/compat/memmove.c @@ -0,0 +1,43 @@ +/* + * memmove.c: memmove compat implementation. + * + * Copyright (c) 2001-2008, NLnet Labs. All rights reserved. + * + * See LICENSE for the license. +*/ + +#include +#include + +void *memmove(void *dest, const void *src, size_t n); + +void *memmove(void *dest, const void *src, size_t n) +{ + uint8_t* from = (uint8_t*) src; + uint8_t* to = (uint8_t*) dest; + + if (from == to || n == 0) + return dest; + if (to > from && to-from < (int)n) { + /* to overlaps with from */ + /* */ + /* */ + /* copy in reverse, to avoid overwriting from */ + int i; + for(i=n-1; i>=0; i--) + to[i] = from[i]; + return dest; + } + if (from > to && from-to < (int)n) { + /* to overlaps with from */ + /* */ + /* */ + /* copy forwards, to avoid overwriting from */ + size_t i; + for(i=0; i +#endif +#undef realloc + +#include + +void *realloc (void*, size_t); +void *malloc (size_t); + +/* Changes allocation to new sizes, copies over old data. + * if oldptr is NULL, does a malloc. + * if size is zero, allocate 1-byte block.... + * (does not return NULL and free block) + */ + +void * +rpl_realloc (void* ptr, size_t n) +{ + if (n == 0) + n = 1; + if(ptr == 0) { + return malloc(n); + } + return realloc(ptr, n); +} + diff --git a/compat/snprintf.c b/compat/snprintf.c new file mode 100644 index 00000000000..b7445111cb3 --- /dev/null +++ b/compat/snprintf.c @@ -0,0 +1,770 @@ +#include + +#ifndef HAVE_SNPRINTF + +#include +#include + +/* Define this as a fall through, HAVE_STDARG_H is probably already set */ + +#define HAVE_VARARGS_H + +/************************************************************** + * Original: + * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 + * A bombproof version of doprnt (dopr) included. + * Sigh. This sort of thing is always nasty do deal with. Note that + * the version here does not include floating point... + * + * snprintf() is used instead of sprintf() as it does limit checks + * for string length. This covers a nasty loophole. + * + * The other functions are there to prevent NULL pointers from + * causing nast effects. + * + * More Recently: + * Brandon Long (blong@fiction.net) 9/15/96 for mutt 0.43 + * This was ugly. It is still ugly. I opted out of floating point + * numbers, but the formatter understands just about everything + * from the normal C string format, at least as far as I can tell from + * the Solaris 2.5 printf(3S) man page. + * + * Brandon Long (blong@fiction.net) 10/22/97 for mutt 0.87.1 + * Ok, added some minimal floating point support, which means this + * probably requires libm on most operating systems. Don't yet + * support the exponent (e,E) and sigfig (g,G). Also, fmtint() + * was pretty badly broken, it just wasn't being exercised in ways + * which showed it, so that's been fixed. Also, formated the code + * to mutt conventions, and removed dead code left over from the + * original. Also, there is now a builtin-test, just compile with: + * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm + * and run snprintf for results. + * + **************************************************************/ + + +/* varargs declarations: */ + +#if defined(HAVE_STDARG_H) +# include +# define HAVE_STDARGS /* let's hope that works everywhere (mj) */ +# define VA_LOCAL_DECL va_list ap +# define VA_START(f) va_start(ap, f) +# define VA_SHIFT(v,t) ; /* no-op for ANSI */ +# define VA_END va_end(ap) +#else +# if defined(HAVE_VARARGS_H) +# include +# undef HAVE_STDARGS +# define VA_LOCAL_DECL va_list ap +# define VA_START(f) va_start(ap) /* f is ignored! */ +# define VA_SHIFT(v,t) v = va_arg(ap,t) +# define VA_END va_end(ap) +# else +/*XX ** NO VARARGS ** XX*/ +# endif +#endif + +int snprintf (char *str, size_t count, const char *fmt, ...); +int vsnprintf (char *str, size_t count, const char *fmt, va_list arg); + +static void dopr (char *buffer, size_t maxlen, const char *format, + va_list args); +static void fmtstr (char *buffer, size_t *currlen, size_t maxlen, + char *value, int flags, int min, int max); +static void fmtint (char *buffer, size_t *currlen, size_t maxlen, + long value, int base, int min, int max, int flags); +static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, + long double fvalue, int min, int max, int flags); +static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c ); + +int vsnprintf (char *str, size_t count, const char *fmt, va_list args) +{ + str[0] = 0; + dopr(str, count, fmt, args); + return(strlen(str)); +} + +/* VARARGS3 */ +#ifdef HAVE_STDARGS +int snprintf (char *str,size_t count,const char *fmt,...) +#else +int snprintf (va_alist) va_dcl +#endif +{ +#ifndef HAVE_STDARGS + char *str; + size_t count; + char *fmt; +#endif + VA_LOCAL_DECL; + + VA_START (fmt); + VA_SHIFT (str, char *); + VA_SHIFT (count, size_t ); + VA_SHIFT (fmt, char *); + (void) vsnprintf(str, count, fmt, ap); + VA_END; + return(strlen(str)); +} + +/* + * dopr(): poor man's version of doprintf + */ + +/* format read states */ +#define DP_S_DEFAULT 0 +#define DP_S_FLAGS 1 +#define DP_S_MIN 2 +#define DP_S_DOT 3 +#define DP_S_MAX 4 +#define DP_S_MOD 5 +#define DP_S_CONV 6 +#define DP_S_DONE 7 + +/* format flags - Bits */ +#define DP_F_MINUS 1 +#define DP_F_PLUS 2 +#define DP_F_SPACE 4 +#define DP_F_NUM 8 +#define DP_F_ZERO 16 +#define DP_F_UP 32 + +/* Conversion Flags */ +#define DP_C_SHORT 1 +#define DP_C_LONG 2 +#define DP_C_LDOUBLE 3 + +#define char_to_int(p) (p - '0') +#define MAX(p,q) ((p >= q) ? p : q) + +static void dopr (char *buffer, size_t maxlen, const char *format, va_list args) +{ + char ch; + long value; + long double fvalue; + char *strvalue; + int min; + int max; + int state; + int flags; + int cflags; + size_t currlen; + + state = DP_S_DEFAULT; + currlen = flags = cflags = min = 0; + max = -1; + ch = *format++; + + while (state != DP_S_DONE) + { + if ((ch == '\0') || (currlen >= maxlen)) + state = DP_S_DONE; + + switch(state) + { + case DP_S_DEFAULT: + if (ch == '%') + state = DP_S_FLAGS; + else + dopr_outch (buffer, &currlen, maxlen, ch); + ch = *format++; + break; + case DP_S_FLAGS: + switch (ch) + { + case '-': + flags |= DP_F_MINUS; + ch = *format++; + break; + case '+': + flags |= DP_F_PLUS; + ch = *format++; + break; + case ' ': + flags |= DP_F_SPACE; + ch = *format++; + break; + case '#': + flags |= DP_F_NUM; + ch = *format++; + break; + case '0': + flags |= DP_F_ZERO; + ch = *format++; + break; + default: + state = DP_S_MIN; + break; + } + break; + case DP_S_MIN: + if (isdigit((int) ch)) + { + min = 10*min + char_to_int (ch); + ch = *format++; + } + else if (ch == '*') + { + min = va_arg (args, int); + ch = *format++; + state = DP_S_DOT; + } + else + state = DP_S_DOT; + break; + case DP_S_DOT: + if (ch == '.') + { + state = DP_S_MAX; + ch = *format++; + } + else + state = DP_S_MOD; + break; + case DP_S_MAX: + if (isdigit((int) ch)) + { + if (max < 0) + max = 0; + max = 10*max + char_to_int (ch); + ch = *format++; + } + else if (ch == '*') + { + max = va_arg (args, int); + ch = *format++; + state = DP_S_MOD; + } + else + state = DP_S_MOD; + break; + case DP_S_MOD: + /* Currently, we don't support Long Long, bummer */ + switch (ch) + { + case 'h': + cflags = DP_C_SHORT; + ch = *format++; + break; + case 'l': + cflags = DP_C_LONG; + ch = *format++; + break; + case 'L': + cflags = DP_C_LDOUBLE; + ch = *format++; + break; + default: + break; + } + state = DP_S_CONV; + break; + case DP_S_CONV: + switch (ch) + { + case 'd': + case 'i': + if (cflags == DP_C_SHORT) + value = va_arg (args, int); + else if (cflags == DP_C_LONG) + value = va_arg (args, long int); + else + value = va_arg (args, int); + fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); + break; + case 'o': + flags &= ~DP_F_PLUS; + if (cflags == DP_C_SHORT) + value = va_arg (args, unsigned int); + else if (cflags == DP_C_LONG) + value = va_arg (args, unsigned long int); + else + value = va_arg (args, unsigned int); + fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags); + break; + case 'u': + flags &= ~DP_F_PLUS; + if (cflags == DP_C_SHORT) + value = va_arg (args, unsigned int); + else if (cflags == DP_C_LONG) + value = va_arg (args, unsigned long int); + else + value = va_arg (args, unsigned int); + fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); + break; + case 'X': + flags |= DP_F_UP; + case 'x': + flags &= ~DP_F_PLUS; + if (cflags == DP_C_SHORT) + value = va_arg (args, unsigned int); + else if (cflags == DP_C_LONG) + value = va_arg (args, unsigned long int); + else + value = va_arg (args, unsigned int); + fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags); + break; + case 'f': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg (args, long double); + else + fvalue = va_arg (args, double); + /* um, floating point? */ + fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); + break; + case 'E': + flags |= DP_F_UP; + case 'e': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg (args, long double); + else + fvalue = va_arg (args, double); + break; + case 'G': + flags |= DP_F_UP; + case 'g': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg (args, long double); + else + fvalue = va_arg (args, double); + break; + case 'c': + dopr_outch (buffer, &currlen, maxlen, va_arg (args, int)); + break; + case 's': + strvalue = va_arg (args, char *); + if (max < 0) + max = maxlen; /* ie, no max */ + fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max); + break; + case 'p': + strvalue = va_arg (args, void *); + fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags); + break; + case 'n': + if (cflags == DP_C_SHORT) + { + short int *num; + num = va_arg (args, short int *); + *num = currlen; + } + else if (cflags == DP_C_LONG) + { + long int *num; + num = va_arg (args, long int *); + *num = currlen; + } + else + { + int *num; + num = va_arg (args, int *); + *num = currlen; + } + break; + case '%': + dopr_outch (buffer, &currlen, maxlen, ch); + break; + case 'w': + /* not supported yet, treat as next char */ + ch = *format++; + break; + default: + /* Unknown, skip */ + break; + } + ch = *format++; + state = DP_S_DEFAULT; + flags = cflags = min = 0; + max = -1; + break; + case DP_S_DONE: + break; + default: + /* hmm? */ + break; /* some picky compilers need this */ + } + } + if (currlen < maxlen - 1) + buffer[currlen] = '\0'; + else + buffer[maxlen - 1] = '\0'; +} + +static void fmtstr (char *buffer, size_t *currlen, size_t maxlen, + char *value, int flags, int min, int max) +{ + int padlen, strln; /* amount to pad */ + int cnt = 0; + + if (value == 0) + { + value = (char *) ""; + } + + for (strln = 0; value[strln]; ++strln); /* strlen */ + padlen = min - strln; + if (padlen < 0) + padlen = 0; + if (flags & DP_F_MINUS) + padlen = -padlen; /* Left Justify */ + + while ((padlen > 0) && (cnt < max)) + { + dopr_outch (buffer, currlen, maxlen, ' '); + --padlen; + ++cnt; + } + while (*value && (cnt < max)) + { + dopr_outch (buffer, currlen, maxlen, *value++); + ++cnt; + } + while ((padlen < 0) && (cnt < max)) + { + dopr_outch (buffer, currlen, maxlen, ' '); + ++padlen; + ++cnt; + } +} + +/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */ + +static void fmtint (char *buffer, size_t *currlen, size_t maxlen, + long value, int base, int min, int max, int flags) +{ + int signvalue = 0; + unsigned long uvalue; + char convert[20]; + int place = 0; + int spadlen = 0; /* amount to space pad */ + int zpadlen = 0; /* amount to zero pad */ + int caps = 0; + + if (max < 0) + max = 0; + + uvalue = value; + if( value < 0 ) { + signvalue = '-'; + uvalue = -value; + } + else + if (flags & DP_F_PLUS) /* Do a sign (+/i) */ + signvalue = '+'; + else + if (flags & DP_F_SPACE) + signvalue = ' '; + + if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ + + do { + convert[place++] = + (caps? "0123456789ABCDEF":"0123456789abcdef") + [uvalue % (unsigned)base ]; + uvalue = (uvalue / (unsigned)base ); + } while(uvalue && (place < 20)); + if (place == 20) place--; + convert[place] = 0; + + zpadlen = max - place; + spadlen = min - MAX (max, place) - (signvalue ? 1 : 0); + if (zpadlen < 0) zpadlen = 0; + if (spadlen < 0) spadlen = 0; + if (flags & DP_F_ZERO) + { + zpadlen = MAX(zpadlen, spadlen); + spadlen = 0; + } + if (flags & DP_F_MINUS) + spadlen = -spadlen; /* Left Justifty */ + +#ifdef DEBUG_SNPRINTF + dprint (1, (debugfile, "zpad: %d, spad: %d, min: %d, max: %d, place: %d\n", + zpadlen, spadlen, min, max, place)); +#endif + + /* Spaces */ + while (spadlen > 0) + { + dopr_outch (buffer, currlen, maxlen, ' '); + --spadlen; + } + + /* Sign */ + if (signvalue) + dopr_outch (buffer, currlen, maxlen, signvalue); + + /* Zeros */ + if (zpadlen > 0) + { + while (zpadlen > 0) + { + dopr_outch (buffer, currlen, maxlen, '0'); + --zpadlen; + } + } + + /* Digits */ + while (place > 0) + dopr_outch (buffer, currlen, maxlen, convert[--place]); + + /* Left Justified spaces */ + while (spadlen < 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + ++spadlen; + } +} + +static long double abs_val (long double value) +{ + long double result = value; + + if (value < 0) + result = -value; + + return result; +} + +static double pow10 (double exp) +{ + long double result = 1; + + while (exp) + { + result *= 10; + exp--; + } + + return result; +} + +static double round (double value) +{ + long intpart; + + intpart = value; + value = value - intpart; + if (value >= 0.5) + intpart++; + + return intpart; +} + +static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, + long double fvalue, int min, int max, int flags) +{ + int signvalue = 0; + long double ufvalue; + char iconvert[20]; + char fconvert[20]; + int iplace = 0; + int fplace = 0; + int padlen = 0; /* amount to pad */ + int zpadlen = 0; + int caps = 0; + long intpart; + long fracpart; + + /* + * AIX manpage says the default is 0, but Solaris says the default + * is 6, and sprintf on AIX defaults to 6 + */ + if (max < 0) + max = 6; + + ufvalue = abs_val (fvalue); + + if (fvalue < 0) + signvalue = '-'; + else + if (flags & DP_F_PLUS) /* Do a sign (+/i) */ + signvalue = '+'; + else + if (flags & DP_F_SPACE) + signvalue = ' '; + +#if 0 + if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ +#endif + + intpart = ufvalue; + + /* + * Sorry, we only support 9 digits past the decimal because of our + * conversion method + */ + if (max > 9) + max = 9; + + /* We "cheat" by converting the fractional part to integer by + * multiplying by a factor of 10 + */ + fracpart = round ((pow10 (max)) * (ufvalue - intpart)); + + if (fracpart >= pow10 (max)) + { + intpart++; + fracpart -= pow10 (max); + } + +#ifdef DEBUG_SNPRINTF + dprint (1, (debugfile, "fmtfp: %f =? %d.%d\n", fvalue, intpart, fracpart)); +#endif + + /* Convert integer part */ + do { + iconvert[iplace++] = + (caps? "0123456789ABCDEF":"0123456789abcdef")[intpart % 10]; + intpart = (intpart / 10); + } while(intpart && (iplace < 20)); + if (iplace == 20) iplace--; + iconvert[iplace] = 0; + + /* Convert fractional part */ + do { + fconvert[fplace++] = + (caps? "0123456789ABCDEF":"0123456789abcdef")[fracpart % 10]; + fracpart = (fracpart / 10); + } while(fracpart && (fplace < 20)); + if (fplace == 20) fplace--; + fconvert[fplace] = 0; + + /* -1 for decimal point, another -1 if we are printing a sign */ + padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); + zpadlen = max - fplace; + if (zpadlen < 0) + zpadlen = 0; + if (padlen < 0) + padlen = 0; + if (flags & DP_F_MINUS) + padlen = -padlen; /* Left Justifty */ + + if ((flags & DP_F_ZERO) && (padlen > 0)) + { + if (signvalue) + { + dopr_outch (buffer, currlen, maxlen, signvalue); + --padlen; + signvalue = 0; + } + while (padlen > 0) + { + dopr_outch (buffer, currlen, maxlen, '0'); + --padlen; + } + } + while (padlen > 0) + { + dopr_outch (buffer, currlen, maxlen, ' '); + --padlen; + } + if (signvalue) + dopr_outch (buffer, currlen, maxlen, signvalue); + + while (iplace > 0) + dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]); + + /* + * Decimal point. This should probably use locale to find the correct + * char to print out. + */ + dopr_outch (buffer, currlen, maxlen, '.'); + + while (zpadlen > 0) + { + dopr_outch (buffer, currlen, maxlen, '0'); + --zpadlen; + } + + while (fplace > 0) + dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]); + + while (padlen < 0) + { + dopr_outch (buffer, currlen, maxlen, ' '); + ++padlen; + } +} + +static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c) +{ + if (*currlen < maxlen) + buffer[(*currlen)++] = c; +} + +#ifdef TEST_SNPRINTF +#ifndef LONG_STRING +#define LONG_STRING 1024 +#endif +int main (void) +{ + char buf1[LONG_STRING]; + char buf2[LONG_STRING]; + char *fp_fmt[] = { + "%-1.5f", + "%1.5f", + "%123.9f", + "%10.5f", + "% 10.5f", + "%+22.9f", + "%+4.9f", + "%01.3f", + "%4f", + "%3.1f", + "%3.2f", + NULL + }; + double fp_nums[] = { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996, + 0.9996, 1.996, 4.136, 0}; + char *int_fmt[] = { + "%-1.5d", + "%1.5d", + "%123.9d", + "%5.5d", + "%10.5d", + "% 10.5d", + "%+22.33d", + "%01.3d", + "%4d", + NULL + }; + long int_nums[] = { -1, 134, 91340, 341, 0203, 0}; + int x, y; + int fail = 0; + int num = 0; + + printf ("Testing snprintf format codes against system sprintf...\n"); + + for (x = 0; fp_fmt[x] != NULL ; x++) + for (y = 0; fp_nums[y] != 0 ; y++) + { + snprintf (buf1, sizeof (buf1), fp_fmt[x], fp_nums[y]); + sprintf (buf2, fp_fmt[x], fp_nums[y]); + if (strcmp (buf1, buf2)) + { + printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n", + fp_fmt[x], buf1, buf2); + fail++; + } + num++; + } + + for (x = 0; int_fmt[x] != NULL ; x++) + for (y = 0; int_nums[y] != 0 ; y++) + { + snprintf (buf1, sizeof (buf1), int_fmt[x], int_nums[y]); + sprintf (buf2, int_fmt[x], int_nums[y]); + if (strcmp (buf1, buf2)) + { + printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n", + int_fmt[x], buf1, buf2); + fail++; + } + num++; + } + printf ("%d tests failed out of %d.\n", fail, num); +} +#endif /* SNPRINTF_TEST */ + +#endif /* !HAVE_SNPRINTF */ diff --git a/compat/strlcpy.c b/compat/strlcpy.c new file mode 100644 index 00000000000..d6c34c1d83c --- /dev/null +++ b/compat/strlcpy.c @@ -0,0 +1,57 @@ +/* from openssh 4.3p2 compat/strlcpy.c */ +/* + * Copyright (c) 1998 Todd C. Miller + * + * 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. + */ + +/* OPENBSD ORIGINAL: lib/libc/string/strlcpy.c */ + +#include +#ifndef HAVE_STRLCPY + +#include +#include + +/* + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +size_t +strlcpy(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0 && --n != 0) { + do { + if ((*d++ = *s++) == 0) + break; + } while (--n != 0); + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + + return(s - src - 1); /* count does not include NUL */ +} + +#endif /* !HAVE_STRLCPY */ diff --git a/compat/timegm.c b/compat/timegm.c new file mode 100644 index 00000000000..97e1e544366 --- /dev/null +++ b/compat/timegm.c @@ -0,0 +1,31 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#ifdef HAVE_STDLIB_H +#include +#endif + +#include + +time_t +timegm (struct tm *tm) { + time_t ret; + char *tz; + + tz = getenv("TZ"); + putenv((char*)"TZ="); + tzset(); + ret = mktime(tm); + if (tz) { + char buf[256]; + snprintf(buf, sizeof(buf), "TZ=%s", tz); + putenv(tz); + } + else + putenv((char*)"TZ"); + tzset(); + return ret; +} diff --git a/config.guess b/config.guess new file mode 100755 index 00000000000..d622a44e551 --- /dev/null +++ b/config.guess @@ -0,0 +1,1530 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011, 2012 Free Software Foundation, Inc. + +timestamp='2012-02-10' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner. Please send patches (context +# diff format) to and include a ChangeLog +# entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + aarch64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + hexagon:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + LIBC=gnu + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-gnu + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + i386) + eval $set_cc_for_build + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + UNAME_PROCESSOR="x86_64" + fi + fi ;; + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo ${UNAME_MACHINE}-unknown-esx + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/config.sub b/config.sub new file mode 100755 index 00000000000..c894da45500 --- /dev/null +++ b/config.sub @@ -0,0 +1,1773 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011, 2012 Free Software Foundation, Inc. + +timestamp='2012-02-10' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted GNU ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + android-linux) + os=-linux-android + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | be32 | be64 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | epiphany \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 \ + | ns16k | ns32k \ + | open8 \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pyramid \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | we32k \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pyramid-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze) + basic_machine=microblaze-xilinx + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i386-pc + os=-msys + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/configure b/configure new file mode 100755 index 00000000000..36936562102 --- /dev/null +++ b/configure @@ -0,0 +1,18779 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.68 for ldns 1.6.13. +# +# Report bugs to . +# +# +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software +# Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1 + + test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ + || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + # We cannot yet assume a decent shell, so we have to provide a + # neutralization value for shells without unset; and this also + # works around shells that cannot unset nonexistent variables. + # Preserve -v and -x to the replacement shell. + BASH_ENV=/dev/null + ENV=/dev/null + (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV + export CONFIG_SHELL + case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; + esac + exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"} +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org and +$0: libdns@nlnetlabs.nl about your system, including any +$0: error possibly output before this message. Then install +$0: a modern shell, or manually run the script under such a +$0: shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + +SHELL=${CONFIG_SHELL-/bin/sh} + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='ldns' +PACKAGE_TARNAME='libdns' +PACKAGE_VERSION='1.6.13' +PACKAGE_STRING='ldns 1.6.13' +PACKAGE_BUGREPORT='libdns@nlnetlabs.nl' +PACKAGE_URL='' + +ac_unique_file="packet.c" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='LTLIBOBJS +ldns_build_config_have_attr_unused +ldns_build_config_have_attr_format +ldns_build_config_have_ssl +WINDRES +LIBOBJS +LIBPCAP_LIBS +include_unistd_h +include_systypes_h +include_inttypes_h +ldns_build_config_have_inttypes_h +include_sys_socket_h +LIBSSL_LIBS +LIBSSL_LDFLAGS +LIBSSL_CPPFLAGS +RUNTIME_PATH +HAVE_SSL +OTOOL64 +OTOOL +LIPO +NMEDIT +DSYMUTIL +MANIFEST_TOOL +AWK +RANLIB +STRIP +ac_ct_AR +DLLTOOL +OBJDUMP +LN_S +NM +ac_ct_DUMPBIN +DUMPBIN +LD +FGREP +SED +LIBTOOL +AR +libtool +PYLDNSXUNINST +PYLDNSXINST +PYLDNSUNINST +PYLDNSINST +PYLDNSX +PYTHON_X_CFLAGS +swig +PYLDNS +SWIG_LIB +SWIG +SWIGPY3 +PYTHON_EXTRA_LDFLAGS +PYTHON_EXTRA_LIBS +PYTHON_SITE_PKG +PYTHON_LDFLAGS +PYTHON_CPPFLAGS +PYTHON +PYTHON_VERSION +UNINSTALL_CONFIG_MANPAGE +UNINSTALL_CONFIG +INSTALL_CONFIG_MANPAGE +INSTALL_CONFIG +LINT_EXAMPLES +CLEAN_EXAMPLES +UNINSTALL_EXAMPLES +INSTALL_EXAMPLES +EXAMPLES +LINT_DRILL +CLEAN_DRILL +UNINSTALL_DRILL +INSTALL_DRILL +DRILL +doxygen +LINTFLAGS +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +SET_MAKE +DEPFLAG +EGREP +GREP +CPP +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +LDNS_VERSION_MICRO +LDNS_VERSION_MINOR +LDNS_VERSION_MAJOR +LIBTOOL_VERSION_INFO +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +with_drill +with_examples +enable_ldns_config +with_pyldns +with_pyldnsx +enable_shared +enable_static +with_pic +enable_fast_install +with_gnu_ld +with_sysroot +enable_libtool_lock +with_ssl +enable_sha2 +enable_gost +enable_ecdsa +enable_rpath +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP +PYTHON_VERSION' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used" >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +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 ldns 1.6.13 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/libdns] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of ldns 1.6.13:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --disable-ldns-config disable installation of ldns-config (default=enabled) + --enable-shared[=PKGS] build shared libraries [default=yes] + --enable-static[=PKGS] build static libraries [default=yes] + --enable-fast-install[=PKGS] + optimize for fast installation [default=yes] + --disable-libtool-lock avoid locking (might break parallel builds) + --disable-sha2 Disable SHA256 and SHA512 RRSIG support + --disable-gost Disable GOST support + --disable-ecdsa Disable ECDSA support + --disable-rpath disable hardcoded rpath (default=enabled) + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-drill Also build drill. + --with-examples Also build examples. + --with-pyldns generate python library, or --without-pyldns to + disable Python support. + --without-pyldnsx Do not install the ldnsx python module, or + --with-pyldnsx to install it. + --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use + both] + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-sysroot=DIR Search for dependent libraries within DIR + (or the compiler's sysroot if not specified). + --with-ssl=pathname enable SSL (will check /usr/local/ssl /usr/lib/ssl + /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw + /usr) + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CPP C preprocessor + PYTHON_VERSION + The installed Python version to use, for example '2.3'. This + string will be appended to the Python interpreter canonical + name. + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to . +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +ldns configure 1.6.13 +generated by GNU Autoconf 2.68 + +Copyright (C) 2010 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} +( $as_echo "## ---------------------------------- ## +## Report this to libdns@nlnetlabs.nl ## +## ---------------------------------- ##" + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_check_type LINENO TYPE VAR INCLUDES +# ------------------------------------------- +# Tests whether TYPE exists after having included INCLUDES, setting cache +# variable VAR accordingly. +ac_fn_c_check_type () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof ($2)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof (($2))) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + eval "$3=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_type + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* 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 $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func + +# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES +# --------------------------------------------- +# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR +# accordingly. +ac_fn_c_check_decl () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + as_decl_name=`echo $2|sed 's/ *(.*//'` + as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 +$as_echo_n "checking whether $as_decl_name is declared... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +#ifndef $as_decl_name +#ifdef __cplusplus + (void) $as_decl_use; +#else + (void) $as_decl_name; +#endif +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_decl + +# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES +# -------------------------------------------- +# Tries to find the compile-time value of EXPR in a program that includes +# INCLUDES, setting VAR accordingly. Returns whether the value could be +# computed +ac_fn_c_compute_int () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) >= 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_lo=0 ac_mid=0 + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=$ac_mid; break +else + as_fn_arith $ac_mid + 1 && ac_lo=$as_val + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) < 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=-1 ac_mid=-1 + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) >= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_lo=$ac_mid; break +else + as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + ac_lo= ac_hi= +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=$ac_mid +else + as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in #(( +?*) eval "$3=\$ac_lo"; ac_retval=0 ;; +'') ac_retval=1 ;; +esac + else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +static long int longval () { return $2; } +static unsigned long int ulongval () { return $2; } +#include +#include +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + return 1; + if (($2) < 0) + { + long int i = longval (); + if (i != ($2)) + return 1; + fprintf (f, "%ld", i); + } + else + { + unsigned long int i = ulongval (); + if (i != ($2)) + return 1; + fprintf (f, "%lu", i); + } + /* Do not output a trailing newline, as this causes \r\n confusion + on some platforms. */ + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + echo >>conftest.val; read $3 &5 +$as_echo_n "checking for $2.$3... " >&6; } +if eval \${$4+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main () +{ +static $2 ac_aggr; +if (ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$4=yes" +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main () +{ +static $2 ac_aggr; +if (sizeof ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$4=yes" +else + eval "$4=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$4 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_member +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 ldns $as_me 1.6.13, which was +generated by GNU Autoconf 2.68. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +# needed to build correct soname +LIBTOOL_VERSION_INFO=1:6:13 + +LDNS_VERSION_MAJOR=1 + +LDNS_VERSION_MINOR=6 + +LDNS_VERSION_MICRO=13 + + +OURCPPFLAGS='' +CPPFLAGS=${CPPFLAGS:-${OURCPPFLAGS}} +CFLAGS="$CFLAGS" + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + 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 eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default" +if test "x$ac_cv_header_minix_config_h" = xyes; then : + MINIX=yes +else + MINIX= +fi + + + if test "$MINIX" = yes; then + +$as_echo "#define _POSIX_SOURCE 1" >>confdefs.h + + +$as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h + + +$as_echo "#define _MINIX 1" >>confdefs.h + + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5 +$as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; } +if ${ac_cv_safe_to_define___extensions__+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +# define __EXTENSIONS__ 1 + $ac_includes_default +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_safe_to_define___extensions__=yes +else + ac_cv_safe_to_define___extensions__=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5 +$as_echo "$ac_cv_safe_to_define___extensions__" >&6; } + test $ac_cv_safe_to_define___extensions__ = yes && + $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h + + $as_echo "#define _ALL_SOURCE 1" >>confdefs.h + + $as_echo "#define _GNU_SOURCE 1" >>confdefs.h + + $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h + + $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h + + + +# Checks for programs. +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $CC dependency flag" >&5 +$as_echo_n "checking $CC dependency flag... " >&6; } +echo 'void f(){}' >conftest.c +if test "`$CC -MM conftest.c 2>&1`" = "conftest.o: conftest.c"; then + DEPFLAG="-MM" +else + if test "`$CC -xM1 conftest.c 2>&1`" = "conftest.o: conftest.c"; then + DEPFLAG="-xM1" + else + DEPFLAG="-MM" # dunno do something + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $DEPFLAG" >&5 +$as_echo "$DEPFLAG" >&6; } +rm -f conftest.c + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + + +# Extra (sp)lint flags for NetBSD +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +case "$host_os" in + netbsd*) LINTFLAGS="'-D__RENAME(x)=' -D_NETINET_IN_H_ $LINTFLAGS" + ;; + *) LINTFLAGS="$LINTFLAGS" + ;; +esac + + + +$as_echo "#define WINVER 0x0502" >>confdefs.h + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -std=c99" >&5 +$as_echo_n "checking whether $CC supports -std=c99... " >&6; } +cache=`echo std=c99 | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -std=c99 -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +C99FLAG="-std=c99" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: + +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -xc99" >&5 +$as_echo_n "checking whether $CC supports -xc99... " >&6; } +cache=`echo xc99 | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -xc99 -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +C99FLAG="-xc99" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: + +fi + + +# routine to copy files +# argument 1 is a list of files (relative to the source dir) +# argument 2 is a destination directory (relative to the current +# working directory + + +# copy all .h files in the dir at argument 1 +# (relative to source) to the dir at argument 2 +# (relative to current dir) + + +# Checks for typedefs, structures, and compiler characteristics. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 +$as_echo_n "checking for an ANSI C-conforming const... " >&6; } +if ${ac_cv_c_const+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +/* FIXME: Include the comments suggested by Paul. */ +#ifndef __cplusplus + /* Ultrix mips cc rejects this. */ + typedef int charset[2]; + const charset cs; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *pcpcc; + char **ppc; + /* NEC SVR4.0.2 mips cc rejects this. */ + struct point {int x, y;}; + static struct point const zero = {0,0}; + /* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in + an arm of an if-expression whose if-part is not a constant + expression */ + const char *g = "string"; + pcpcc = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++pcpcc; + ppc = (char**) pcpcc; + pcpcc = (char const *const *) ppc; + { /* SCO 3.2v4 cc rejects this. */ + char *t; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; + if (s) return 0; + } + { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; + } + { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; + } + { /* AIX XL C 1.02.0.0 rejects this saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; }; + struct s *b; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + if (!foo) return 0; + } + return !cs[0] && !zero.x; +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_const=yes +else + ac_cv_c_const=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_const" >&5 +$as_echo "$ac_cv_c_const" >&6; } +if test $ac_cv_c_const = no; then + +$as_echo "#define const /**/" >>confdefs.h + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -g" >&5 +$as_echo_n "checking whether $CC supports -g... " >&6; } +cache=`echo g | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -g -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +CFLAGS="-g $CFLAGS" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: + +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -O2" >&5 +$as_echo_n "checking whether $CC supports -O2... " >&6; } +cache=`echo O2 | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -O2 -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +CFLAGS="-O2 $CFLAGS" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: + +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wall" >&5 +$as_echo_n "checking whether $CC supports -Wall... " >&6; } +cache=`echo Wall | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -Wall -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +CFLAGS="-Wall $CFLAGS" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: + +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -W" >&5 +$as_echo_n "checking whether $CC supports -W... " >&6; } +cache=`echo W | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -W -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +CFLAGS="-W $CFLAGS" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: + +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wwrite-strings" >&5 +$as_echo_n "checking whether $CC supports -Wwrite-strings... " >&6; } +cache=`echo Wwrite-strings | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -Wwrite-strings -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +CFLAGS="-Wwrite-strings $CFLAGS" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: + +fi + + + +for ac_header in getopt.h time.h +do : + 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 eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +# MinGW32 tests +for ac_header in winsock2.h ws2tcpip.h +do : + 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 eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +# end mingw32 tests + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Werror" >&5 +$as_echo_n "checking whether $CC supports -Werror... " >&6; } +cache=`echo Werror | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -Werror -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +ERRFLAG="-Werror" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: +ERRFLAG="-errwarn" +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wall" >&5 +$as_echo_n "checking whether $CC supports -Wall... " >&6; } +cache=`echo Wall | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -Wall -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +ERRFLAG="$ERRFLAG -Wall" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: +ERRFLAG="$ERRFLAG -errfmt" +fi + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -std=c99" >&5 +$as_echo_n "checking whether $CC supports -std=c99... " >&6; } +cache=`echo std=c99 | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -std=c99 -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +C99FLAG="-std=c99" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: + +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -xc99" >&5 +$as_echo_n "checking whether $CC supports -xc99... " >&6; } +cache=`echo xc99 | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -xc99 -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +C99FLAG="-xc99" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: + +fi + + +for ac_header in getopt.h time.h +do : + 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 eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we need $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_ALL_SOURCE as a flag for $CC" >&5 +$as_echo_n "checking whether we need $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_ALL_SOURCE as a flag for $CC... " >&6; } +cache=`$as_echo "$C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_ALL_SOURCE" | $as_tr_sh` +if eval \${cv_prog_cc_flag_needed_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo ' +#include "confdefs.h" +#include +#include +#include +#ifdef HAVE_TIME_H +#include +#endif +#include +#include +#ifdef HAVE_GETOPT_H +#include +#endif + +int test() { + int a; + char **opts = NULL; + struct timeval tv; + char *t; + time_t time = 0; + char *buf = NULL; + const char* str = NULL; + struct msghdr msg; + msg.msg_control = 0; + t = ctime_r(&time, buf); + tv.tv_usec = 10; + srandom(32); + a = getopt(2, opts, "a"); + a = isascii(32); + str = gai_strerror(0); + if(str && t && tv.tv_usec && msg.msg_control) + a = 0; + return a; +} +' > conftest.c +echo 'void f(){}' >>conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=no" +else + +if test -z "`$CC $CPPFLAGS $CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_ALL_SOURCE $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=yes" +else +eval "cv_prog_cc_flag_needed_$cache=fail" +#echo 'Test with flag fails too!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_ALL_SOURCE $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_ALL_SOURCE $ERRFLAG -c conftest.c 2>&1` +#exit 1 +fi + +fi +rm -f conftest conftest.c conftest.o + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +CFLAGS="$CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_ALL_SOURCE" +else +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = no"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +#echo 'Test with flag is no!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_ALL_SOURCE $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_ALL_SOURCE $ERRFLAG -c conftest.c 2>&1` +#exit 1 +: + +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +: + +fi +fi + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we need $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE as a flag for $CC" >&5 +$as_echo_n "checking whether we need $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE as a flag for $CC... " >&6; } +cache=`$as_echo "$C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE" | $as_tr_sh` +if eval \${cv_prog_cc_flag_needed_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo ' +#include "confdefs.h" +#include +#include +#include +#ifdef HAVE_TIME_H +#include +#endif +#include +#include +#ifdef HAVE_GETOPT_H +#include +#endif + +int test() { + int a; + char **opts = NULL; + struct timeval tv; + char *t; + time_t time = 0; + char *buf = NULL; + const char* str = NULL; + struct msghdr msg; + msg.msg_control = 0; + t = ctime_r(&time, buf); + tv.tv_usec = 10; + srandom(32); + a = getopt(2, opts, "a"); + a = isascii(32); + str = gai_strerror(0); + if(str && t && tv.tv_usec && msg.msg_control) + a = 0; + return a; +} +' > conftest.c +echo 'void f(){}' >>conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=no" +else + +if test -z "`$CC $CPPFLAGS $CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=yes" +else +eval "cv_prog_cc_flag_needed_$cache=fail" +#echo 'Test with flag fails too!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE $ERRFLAG -c conftest.c 2>&1` +#exit 1 +fi + +fi +rm -f conftest conftest.c conftest.o + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +CFLAGS="$CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE" +else +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = no"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +#echo 'Test with flag is no!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE $ERRFLAG -c conftest.c 2>&1` +#exit 1 +: + +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +: + +fi +fi + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we need $C99FLAG as a flag for $CC" >&5 +$as_echo_n "checking whether we need $C99FLAG as a flag for $CC... " >&6; } +cache=`$as_echo "$C99FLAG" | $as_tr_sh` +if eval \${cv_prog_cc_flag_needed_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo ' +#include +#include +int test() { + int a = 0; + return a; +} +' > conftest.c +echo 'void f(){}' >>conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=no" +else + +if test -z "`$CC $CPPFLAGS $CFLAGS $C99FLAG $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=yes" +else +eval "cv_prog_cc_flag_needed_$cache=fail" +#echo 'Test with flag fails too!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS $C99FLAG $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS $C99FLAG $ERRFLAG -c conftest.c 2>&1` +#exit 1 +fi + +fi +rm -f conftest conftest.c conftest.o + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +CFLAGS="$CFLAGS $C99FLAG" +else +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = no"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +#echo 'Test with flag is no!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS $C99FLAG $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS $C99FLAG $ERRFLAG -c conftest.c 2>&1` +#exit 1 +: + +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +: + +fi +fi + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we need -D_BSD_SOURCE as a flag for $CC" >&5 +$as_echo_n "checking whether we need -D_BSD_SOURCE as a flag for $CC... " >&6; } +cache=_D_BSD_SOURCE +if eval \${cv_prog_cc_flag_needed_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo ' +#include + +int test() { + int a; + a = isascii(32); + return a; +} +' > conftest.c +echo 'void f(){}' >>conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=no" +else + +if test -z "`$CC $CPPFLAGS $CFLAGS -D_BSD_SOURCE $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=yes" +else +eval "cv_prog_cc_flag_needed_$cache=fail" +#echo 'Test with flag fails too!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS -D_BSD_SOURCE $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS -D_BSD_SOURCE $ERRFLAG -c conftest.c 2>&1` +#exit 1 +fi + +fi +rm -f conftest conftest.c conftest.o + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +CFLAGS="$CFLAGS -D_BSD_SOURCE" +else +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = no"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +#echo 'Test with flag is no!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS -D_BSD_SOURCE $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS -D_BSD_SOURCE $ERRFLAG -c conftest.c 2>&1` +#exit 1 +: + +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +: + +fi +fi + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we need -D_GNU_SOURCE as a flag for $CC" >&5 +$as_echo_n "checking whether we need -D_GNU_SOURCE as a flag for $CC... " >&6; } +cache=_D_GNU_SOURCE +if eval \${cv_prog_cc_flag_needed_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo ' +#include + +int test() { + struct in6_pktinfo inf; + int a = (int)sizeof(inf); + return a; +} +' > conftest.c +echo 'void f(){}' >>conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=no" +else + +if test -z "`$CC $CPPFLAGS $CFLAGS -D_GNU_SOURCE $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=yes" +else +eval "cv_prog_cc_flag_needed_$cache=fail" +#echo 'Test with flag fails too!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS -D_GNU_SOURCE $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS -D_GNU_SOURCE $ERRFLAG -c conftest.c 2>&1` +#exit 1 +fi + +fi +rm -f conftest conftest.c conftest.o + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +CFLAGS="$CFLAGS -D_GNU_SOURCE" +else +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = no"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +#echo 'Test with flag is no!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS -D_GNU_SOURCE $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS -D_GNU_SOURCE $ERRFLAG -c conftest.c 2>&1` +#exit 1 +: + +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +: + +fi +fi + + +# check again for GNU_SOURCE for setresgid. May fail if setresgid +# is not available at all. -D_FRSRESGID is to make this check unique. +# otherwise we would get the previous cached result. + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we need -D_GNU_SOURCE -D_FRSRESGID as a flag for $CC" >&5 +$as_echo_n "checking whether we need -D_GNU_SOURCE -D_FRSRESGID as a flag for $CC... " >&6; } +cache=_D_GNU_SOURCE__D_FRSRESGID +if eval \${cv_prog_cc_flag_needed_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo ' +#include + +int test() { + int a = setresgid(0,0,0); + a = setresuid(0,0,0); + return a; +} +' > conftest.c +echo 'void f(){}' >>conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=no" +else + +if test -z "`$CC $CPPFLAGS $CFLAGS -D_GNU_SOURCE -D_FRSRESGID $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=yes" +else +eval "cv_prog_cc_flag_needed_$cache=fail" +#echo 'Test with flag fails too!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS -D_GNU_SOURCE -D_FRSRESGID $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS -D_GNU_SOURCE -D_FRSRESGID $ERRFLAG -c conftest.c 2>&1` +#exit 1 +fi + +fi +rm -f conftest conftest.c conftest.o + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +CFLAGS="$CFLAGS -D_GNU_SOURCE" +else +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = no"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +#echo 'Test with flag is no!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS -D_GNU_SOURCE -D_FRSRESGID $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS -D_GNU_SOURCE -D_FRSRESGID $ERRFLAG -c conftest.c 2>&1` +#exit 1 +: + +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +: + +fi +fi + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we need -D_POSIX_C_SOURCE=200112 as a flag for $CC" >&5 +$as_echo_n "checking whether we need -D_POSIX_C_SOURCE=200112 as a flag for $CC... " >&6; } +cache=`$as_echo "-D_POSIX_C_SOURCE=200112" | $as_tr_sh` +if eval \${cv_prog_cc_flag_needed_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo ' +#include "confdefs.h" +#ifdef HAVE_TIME_H +#include +#endif +#include + +int test() { + int a = 0; + char *t; + time_t time = 0; + char *buf = NULL; + const char* str = NULL; + t = ctime_r(&time, buf); + str = gai_strerror(0); + if(t && str) + a = 0; + return a; +} +' > conftest.c +echo 'void f(){}' >>conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=no" +else + +if test -z "`$CC $CPPFLAGS $CFLAGS -D_POSIX_C_SOURCE=200112 $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=yes" +else +eval "cv_prog_cc_flag_needed_$cache=fail" +#echo 'Test with flag fails too!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS -D_POSIX_C_SOURCE=200112 $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS -D_POSIX_C_SOURCE=200112 $ERRFLAG -c conftest.c 2>&1` +#exit 1 +fi + +fi +rm -f conftest conftest.c conftest.o + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +CFLAGS="$CFLAGS -D_POSIX_C_SOURCE=200112" +else +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = no"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +#echo 'Test with flag is no!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS -D_POSIX_C_SOURCE=200112 $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS -D_POSIX_C_SOURCE=200112 $ERRFLAG -c conftest.c 2>&1` +#exit 1 +: + +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +: + +fi +fi + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we need -D__EXTENSIONS__ as a flag for $CC" >&5 +$as_echo_n "checking whether we need -D__EXTENSIONS__ as a flag for $CC... " >&6; } +cache=_D__EXTENSIONS__ +if eval \${cv_prog_cc_flag_needed_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo ' +#include "confdefs.h" +#include +#include +#include +#ifdef HAVE_TIME_H +#include +#endif +#include +#ifdef HAVE_GETOPT_H +#include +#endif + +int test() { + int a; + char **opts = NULL; + struct timeval tv; + tv.tv_usec = 10; + srandom(32); + a = getopt(2, opts, "a"); + a = isascii(32); + if(tv.tv_usec) + a = 0; + return a; +} +' > conftest.c +echo 'void f(){}' >>conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=no" +else + +if test -z "`$CC $CPPFLAGS $CFLAGS -D__EXTENSIONS__ $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=yes" +else +eval "cv_prog_cc_flag_needed_$cache=fail" +#echo 'Test with flag fails too!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS -D__EXTENSIONS__ $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS -D__EXTENSIONS__ $ERRFLAG -c conftest.c 2>&1` +#exit 1 +fi + +fi +rm -f conftest conftest.c conftest.o + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +CFLAGS="$CFLAGS -D__EXTENSIONS__" +else +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = no"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +#echo 'Test with flag is no!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS -D__EXTENSIONS__ $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS -D__EXTENSIONS__ $ERRFLAG -c conftest.c 2>&1` +#exit 1 +: + +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +: + +fi +fi + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 +$as_echo_n "checking for inline... " >&6; } +if ${ac_cv_c_inline+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __cplusplus +typedef int foo_t; +static $ac_kw foo_t static_foo () {return 0; } +$ac_kw foo_t foo () {return 0; } +#endif + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_inline=$ac_kw +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test "$ac_cv_c_inline" != no && break +done + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 +$as_echo "$ac_cv_c_inline" >&6; } + +case $ac_cv_c_inline in + inline | yes) ;; + *) + case $ac_cv_c_inline in + no) ac_val=;; + *) ac_val=$ac_cv_c_inline;; + esac + cat >>confdefs.h <<_ACEOF +#ifndef __cplusplus +#define inline $ac_val +#endif +_ACEOF + ;; +esac + +ac_fn_c_check_type "$LINENO" "int8_t" "ac_cv_type_int8_t" "$ac_includes_default" +if test "x$ac_cv_type_int8_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define int8_t char +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "int16_t" "ac_cv_type_int16_t" "$ac_includes_default" +if test "x$ac_cv_type_int16_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define int16_t short +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "int32_t" "ac_cv_type_int32_t" "$ac_includes_default" +if test "x$ac_cv_type_int32_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define int32_t int +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "int64_t" "ac_cv_type_int64_t" "$ac_includes_default" +if test "x$ac_cv_type_int64_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define int64_t long long +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "uint8_t" "ac_cv_type_uint8_t" "$ac_includes_default" +if test "x$ac_cv_type_uint8_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define uint8_t unsigned char +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "uint16_t" "ac_cv_type_uint16_t" "$ac_includes_default" +if test "x$ac_cv_type_uint16_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define uint16_t unsigned short +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "uint32_t" "ac_cv_type_uint32_t" "$ac_includes_default" +if test "x$ac_cv_type_uint32_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define uint32_t unsigned int +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "uint64_t" "ac_cv_type_uint64_t" "$ac_includes_default" +if test "x$ac_cv_type_uint64_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define uint64_t unsigned long long +_ACEOF + +fi + + +# my own checks +# Extract the first word of "doxygen", so it can be a program name with args. +set dummy doxygen; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_doxygen+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$doxygen"; then + ac_cv_prog_doxygen="$doxygen" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_doxygen="doxygen" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +doxygen=$ac_cv_prog_doxygen +if test -n "$doxygen"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $doxygen" >&5 +$as_echo "$doxygen" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + +# check to see if libraries are needed for these functions. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing socket" >&5 +$as_echo_n "checking for library containing socket... " >&6; } +if ${ac_cv_search_socket+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +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 socket (); +int +main () +{ +return socket (); + ; + return 0; +} +_ACEOF +for ac_lib in '' socket; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_socket=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_socket+:} false; then : + break +fi +done +if ${ac_cv_search_socket+:} false; then : + +else + ac_cv_search_socket=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_socket" >&5 +$as_echo "$ac_cv_search_socket" >&6; } +ac_res=$ac_cv_search_socket +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing inet_pton" >&5 +$as_echo_n "checking for library containing inet_pton... " >&6; } +if ${ac_cv_search_inet_pton+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +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 inet_pton (); +int +main () +{ +return inet_pton (); + ; + return 0; +} +_ACEOF +for ac_lib in '' nsl; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_inet_pton=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_inet_pton+:} false; then : + break +fi +done +if ${ac_cv_search_inet_pton+:} false; then : + +else + ac_cv_search_inet_pton=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_inet_pton" >&5 +$as_echo "$ac_cv_search_inet_pton" >&6; } +ac_res=$ac_cv_search_inet_pton +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + + + + +# Check whether --with-drill was given. +if test "${with_drill+set}" = set; then : + withval=$with_drill; +else + with_drill="no" +fi + +if test x_$with_drill != x_no ; then + DRILL=drill + + INSTALL_DRILL=install-drill + + UNINSTALL_DRILL=uninstall-drill + + CLEAN_DRILL=clean-drill + + LINT_DRILL=lint-drill + + if test -e $srcdir/drill/config.h -o -e drill/config.h ; then + as_fn_error $? " +A config.h was detected in the drill subdirectory. +This does not work with the --with-drill option. +Please remove the config.h from the drill subdirectory +or do not use the --with-drill option." "$LINENO" 5 + fi +else + DRILL="" + + INSTALL_DRILL="" + + UNINSTALL_DRILL="" + + CLEAN_DRILL="" + + LINT_DRILL="" + +fi + + + +# Check whether --with-examples was given. +if test "${with_examples+set}" = set; then : + withval=$with_examples; +else + with_examples="no" +fi + +if test x_$with_examples != x_no ; then + EXAMPLES=examples + + INSTALL_EXAMPLES=install-examples + + UNINSTALL_EXAMPLES=uninstall-examples + + CLEAN_EXAMPLES=clean-examples + + LINT_EXAMPLES=lint-examples + + if test -e $srcdir/examples/config.h -o -e examples/config.h ; then + as_fn_error $? " +A config.h was detected in the examples subdirectory. +This does not work with the --with-examples option. +Please remove the config.h from the examples subdirectory +or do not use the --with-examples option." "$LINENO" 5 + fi +else + EXAMPLES="" + + INSTALL_EXAMPLES="" + + UNINSTALL_EXAMPLES="" + + CLEAN_EXAMPLES="" + + LINT_EXAMPLES="" + +fi + +# add option to disable installation of ldns-config script +# Check whether --enable-ldns-config was given. +if test "${enable_ldns_config+set}" = set; then : + enableval=$enable_ldns_config; enable_ldns_config=$enableval +else + enable_ldns_config=yes +fi + +if test "x$enable_ldns_config" = xyes; then + INSTALL_CONFIG=install-config + + INSTALL_CONFIG_MANPAGE=install-config-manpage + + UNINSTALL_CONFIG=uninstall-config + + UNINSTALL_CONFIG_MANPAGE=uninstall-config-manpage + +else + INSTALL_CONFIG="" + + INSTALL_CONFIG_MANPAGE="" + + UNINSTALL_CONFIG="" + + UNINSTALL_CONFIG_MANPAGE="" + +fi + +# check for python +PYTHON_X_CFLAGS="" +ldns_with_pyldns=no +ldns_with_pyldnsx=no + +# Check whether --with-pyldns was given. +if test "${with_pyldns+set}" = set; then : + withval=$with_pyldns; +else + withval="no" +fi + +ldns_have_python=no +if test x_$withval != x_no; then + # =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_python_devel.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PYTHON_DEVEL([version]) +# +# DESCRIPTION +# +# Note: Defines as a precious variable "PYTHON_VERSION". Don't override it +# in your configure.ac. +# +# This macro checks for Python and tries to get the include path to +# 'Python.h'. It provides the $(PYTHON_CPPFLAGS) and $(PYTHON_LDFLAGS) +# output variables. It also exports $(PYTHON_EXTRA_LIBS) and +# $(PYTHON_EXTRA_LDFLAGS) for embedding Python in your code. +# +# You can search for some particular version of Python by passing a +# parameter to this macro, for example ">= '2.3.1'", or "== '2.4'". Please +# note that you *have* to pass also an operator along with the version to +# match, and pay special attention to the single quotes surrounding the +# version number. Don't use "PYTHON_VERSION" for this: that environment +# variable is declared as precious and thus reserved for the end-user. +# +# This macro should work for all versions of Python >= 2.1.0. As an end +# user, you can disable the check for the python version by setting the +# PYTHON_NOVERSIONCHECK environment variable to something else than the +# empty string. +# +# If you need to use this macro for an older Python version, please +# contact the authors. We're always open for feedback. +# +# LICENSE +# +# Copyright (c) 2009 Sebastian Huber +# Copyright (c) 2009 Alan W. Irwin +# Copyright (c) 2009 Rafael Laboissiere +# Copyright (c) 2009 Andrew Collier +# Copyright (c) 2009 Matteo Settenvini +# Copyright (c) 2009 Horst Knorr +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 8 + +# This is what autoupdate's m4 run will expand. It fires +# the warning (with _au_warn_XXX), outputs it into the +# updated configure.ac (with AC_DIAGNOSE), and then outputs +# the replacement expansion. + + +# This is an auxiliary macro that is also run when +# autoupdate runs m4. It simply calls m4_warning, but +# we need a wrapper so that each warning is emitted only +# once. We break the quoting in m4_warning's argument in +# order to expand this macro's arguments, not AU_DEFUN's. + + +# Finally, this is the expansion that is picked up by +# autoconf. It tells the user to run autoupdate, and +# then outputs the replacement expansion. We do not care +# about autoupdate's warning because that contains +# information on what to do *after* running autoupdate. + + + + ac_save_LIBS="$LIBS" + + # + # Allow the use of a (user set) custom python version + # + + + # Extract the first word of "python[$PYTHON_VERSION]", so it can be a program name with args. +set dummy python$PYTHON_VERSION; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PYTHON+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PYTHON in + [\\/]* | ?:[\\/]*) + ac_cv_path_PYTHON="$PYTHON" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_PYTHON="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PYTHON=$ac_cv_path_PYTHON +if test -n "$PYTHON"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON" >&5 +$as_echo "$PYTHON" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test -z "$PYTHON"; then + as_fn_error $? "Cannot find python$PYTHON_VERSION in your system path" "$LINENO" 5 + PYTHON_VERSION="" + fi + + # + # Check for a version of Python >= 2.1.0 + # + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a version of Python >= '2.1.0'" >&5 +$as_echo_n "checking for a version of Python >= '2.1.0'... " >&6; } + ac_supports_python_ver=`$PYTHON -c "import sys; \ + ver = sys.version.split ()[0]; \ + print (ver >= '2.1.0')"` + if test "$ac_supports_python_ver" != "True"; then + if test -z "$PYTHON_NOVERSIONCHECK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? " +This version of the AC_PYTHON_DEVEL macro +doesn't work properly with versions of Python before +2.1.0. You may need to re-run configure, setting the +variables PYTHON_CPPFLAGS, PYTHON_LDFLAGS, PYTHON_SITE_PKG, +PYTHON_EXTRA_LIBS and PYTHON_EXTRA_LDFLAGS by hand. +Moreover, to disable this check, set PYTHON_NOVERSIONCHECK +to something else than an empty string. + +See \`config.log' for more details" "$LINENO" 5; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: skip at user request" >&5 +$as_echo "skip at user request" >&6; } + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + fi + + # + # if the macro parameter ``version'' is set, honour it + # + if test -n ">= '2.4.0'"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a version of Python >= '2.4.0'" >&5 +$as_echo_n "checking for a version of Python >= '2.4.0'... " >&6; } + ac_supports_python_ver=`$PYTHON -c "import sys; \ + ver = sys.version.split ()[0]; \ + print (ver >= '2.4.0')"` + if test "$ac_supports_python_ver" = "True"; then + { $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 $? "this package requires Python >= '2.4.0'. +If you have it installed, but it isn't the default Python +interpreter in your system path, please pass the PYTHON_VERSION +variable to configure. See \`\`configure --help'' for reference. +" "$LINENO" 5 + PYTHON_VERSION="" + fi + fi + + # + # Check if you have distutils, else fail + # + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the distutils Python package" >&5 +$as_echo_n "checking for the distutils Python package... " >&6; } + ac_distutils_result=`$PYTHON -c "import distutils" 2>&1` + if test -z "$ac_distutils_result"; then + { $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 $? "cannot import Python module \"distutils\". +Please check your Python installation. The error was: +$ac_distutils_result" "$LINENO" 5 + PYTHON_VERSION="" + fi + + # + # Check for Python include path + # + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python include path" >&5 +$as_echo_n "checking for Python include path... " >&6; } + if test -z "$PYTHON_CPPFLAGS"; then + python_path=`$PYTHON -c "import distutils.sysconfig; \ + print (distutils.sysconfig.get_python_inc ());"` + if test -n "${python_path}"; then + python_path="-I$python_path" + fi + PYTHON_CPPFLAGS=$python_path + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_CPPFLAGS" >&5 +$as_echo "$PYTHON_CPPFLAGS" >&6; } + + + # + # Check for Python library path + # + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python library path" >&5 +$as_echo_n "checking for Python library path... " >&6; } + if test -z "$PYTHON_LDFLAGS"; then + # (makes two attempts to ensure we've got a version number + # from the interpreter) + ac_python_version=`cat<>confdefs.h <<_ACEOF +#define HAVE_PYTHON "$ac_python_version" +_ACEOF + + + # First, the library directory: + ac_python_libdir=`cat<&5 +$as_echo "$PYTHON_LDFLAGS" >&6; } + + + # + # Check for site packages + # + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python site-packages path" >&5 +$as_echo_n "checking for Python site-packages path... " >&6; } + if test -z "$PYTHON_SITE_PKG"; then + PYTHON_SITE_PKG=`$PYTHON -c "import distutils.sysconfig; \ + print (distutils.sysconfig.get_python_lib(1,0));"` + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_SITE_PKG" >&5 +$as_echo "$PYTHON_SITE_PKG" >&6; } + + + # + # libraries which must be linked in when embedding + # + { $as_echo "$as_me:${as_lineno-$LINENO}: checking python extra libraries" >&5 +$as_echo_n "checking python extra libraries... " >&6; } + if test -z "$PYTHON_EXTRA_LIBS"; then + PYTHON_EXTRA_LIBS=`$PYTHON -c "import distutils.sysconfig; \ + conf = distutils.sysconfig.get_config_var; \ + print (conf('LOCALMODLIBS') + ' ' + conf('LIBS'))"` + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_EXTRA_LIBS" >&5 +$as_echo "$PYTHON_EXTRA_LIBS" >&6; } + + + # + # linking flags needed when embedding + # + { $as_echo "$as_me:${as_lineno-$LINENO}: checking python extra linking flags" >&5 +$as_echo_n "checking python extra linking flags... " >&6; } + if test -z "$PYTHON_EXTRA_LDFLAGS"; then + PYTHON_EXTRA_LDFLAGS=`$PYTHON -c "import distutils.sysconfig; \ + conf = distutils.sysconfig.get_config_var; \ + print (conf('LINKFORSHARED'))"` + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_EXTRA_LDFLAGS" >&5 +$as_echo "$PYTHON_EXTRA_LDFLAGS" >&6; } + + + # + # final check to see if everything compiles alright + # + { $as_echo "$as_me:${as_lineno-$LINENO}: checking consistency of all components of python development environment" >&5 +$as_echo_n "checking consistency of all components of python development environment... " >&6; } + # save current global flags + ac_save_LIBS="$LIBS" + ac_save_CPPFLAGS="$CPPFLAGS" + LIBS="$ac_save_LIBS $PYTHON_LDFLAGS $PYTHON_EXTRA_LDFLAGS $PYTHON_EXTRA_LIBS" + CPPFLAGS="$ac_save_CPPFLAGS $PYTHON_CPPFLAGS" + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include +int +main () +{ +Py_Initialize(); + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + pythonexists=yes +else + pythonexists=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + # turn back to default flags + CPPFLAGS="$ac_save_CPPFLAGS" + LIBS="$ac_save_LIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $pythonexists" >&5 +$as_echo "$pythonexists" >&6; } + + if test ! "x$pythonexists" = "xyes"; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? " + Could not link test program to Python. Maybe the main Python library has been + installed in some non-standard library path. If so, pass it to configure, + via the LDFLAGS environment variable. + Example: ./configure LDFLAGS=\"-L/usr/non-standard-path/python/lib\" + ============================================================================ + ERROR! + You probably have to install the development version of the Python package + for your distribution. The exact name of this package varies among them. + ============================================================================ + +See \`config.log' for more details" "$LINENO" 5; } + PYTHON_VERSION="" + fi + + # + # all done! + # + + if test ! -z "$ac_python_version"; then + ldns_have_python=yes + fi + + # pass additional Python 3 option to SWIG + if test `$PYTHON -c "import sys; \ + ver = sys.version.split()[0]; \ + print(ver >= '3')"` = "True"; then + SWIGPY3="-py3 -DPY3" + + fi + + # check for SWIG + if test x_$ldns_have_python != x_no; then + # =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_pkg_swig.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PKG_SWIG([major.minor.micro], [action-if-found], [action-if-not-found]) +# +# DESCRIPTION +# +# This macro searches for a SWIG installation on your system. If found, +# then SWIG is AC_SUBST'd; if not found, then $SWIG is empty. If SWIG is +# found, then SWIG_LIB is set to the SWIG library path, and AC_SUBST'd. +# +# You can use the optional first argument to check if the version of the +# available SWIG is greater than or equal to the value of the argument. It +# should have the format: N[.N[.N]] (N is a number between 0 and 999. Only +# the first N is mandatory.) If the version argument is given (e.g. +# 1.3.17), AX_PKG_SWIG checks that the swig package is this version number +# or higher. +# +# As usual, action-if-found is executed if SWIG is found, otherwise +# action-if-not-found is executed. +# +# In configure.in, use as: +# +# AX_PKG_SWIG(1.3.17, [], [ AC_MSG_ERROR([SWIG is required to build..]) ]) +# AX_SWIG_ENABLE_CXX +# AX_SWIG_MULTI_MODULE_SUPPORT +# AX_SWIG_PYTHON +# +# LICENSE +# +# Copyright (c) 2008 Sebastian Huber +# Copyright (c) 2008 Alan W. Irwin +# Copyright (c) 2008 Rafael Laboissiere +# Copyright (c) 2008 Andrew Collier +# Copyright (c) 2011 Murray Cumming +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 8 + + + + + # check for >=SWIG-2.0.4 if Python 3.2 used + if test `$PYTHON -c "import sys; \ + ver = sys.version.split()[0]; \ + print(ver >= '3.2')"` = "True"; then + + # Ubuntu has swig 2.0 as /usr/bin/swig2.0 + for ac_prog in swig2.0 swig +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_SWIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $SWIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_SWIG="$SWIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_SWIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +SWIG=$ac_cv_path_SWIG +if test -n "$SWIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SWIG" >&5 +$as_echo "$SWIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$SWIG" && break +done + + if test -z "$SWIG" ; then + as_fn_error $? "SWIG-2.0.4 is required to build pyldns for Python 3.2 and greater." "$LINENO" 5 + elif test -n "2.0.4" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking SWIG version" >&5 +$as_echo_n "checking SWIG version... " >&6; } + swig_version=`$SWIG -version 2>&1 | grep 'SWIG Version' | sed 's/.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/g'` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $swig_version" >&5 +$as_echo "$swig_version" >&6; } + if test -n "$swig_version" ; then + # Calculate the required version number components + required=2.0.4 + required_major=`echo $required | sed 's/[^0-9].*//'` + if test -z "$required_major" ; then + required_major=0 + fi + required=`echo $required | sed 's/[0-9]*[^0-9]//'` + required_minor=`echo $required | sed 's/[^0-9].*//'` + if test -z "$required_minor" ; then + required_minor=0 + fi + required=`echo $required | sed 's/[0-9]*[^0-9]//'` + required_patch=`echo $required | sed 's/[^0-9].*//'` + if test -z "$required_patch" ; then + required_patch=0 + fi + # Calculate the available version number components + available=$swig_version + available_major=`echo $available | sed 's/[^0-9].*//'` + if test -z "$available_major" ; then + available_major=0 + fi + available=`echo $available | sed 's/[0-9]*[^0-9]//'` + available_minor=`echo $available | sed 's/[^0-9].*//'` + if test -z "$available_minor" ; then + available_minor=0 + fi + available=`echo $available | sed 's/[0-9]*[^0-9]//'` + available_patch=`echo $available | sed 's/[^0-9].*//'` + if test -z "$available_patch" ; then + available_patch=0 + fi + # Convert the version tuple into a single number for easier comparison. + # Using base 100 should be safe since SWIG internally uses BCD values + # to encode its version number. + required_swig_vernum=`expr $required_major \* 10000 \ + \+ $required_minor \* 100 \+ $required_patch` + available_swig_vernum=`expr $available_major \* 10000 \ + \+ $available_minor \* 100 \+ $available_patch` + + if test $available_swig_vernum -lt $required_swig_vernum; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: SWIG version >= 2.0.4 is required. You have $swig_version." >&5 +$as_echo "$as_me: WARNING: SWIG version >= 2.0.4 is required. You have $swig_version." >&2;} + SWIG='' + as_fn_error $? "SWIG-2.0.4 is required to build pyldns for Python 3.2 and greater." "$LINENO" 5 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SWIG library" >&5 +$as_echo_n "checking for SWIG library... " >&6; } + SWIG_LIB=`$SWIG -swiglib` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SWIG_LIB" >&5 +$as_echo "$SWIG_LIB" >&6; } + + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cannot determine SWIG version" >&5 +$as_echo "$as_me: WARNING: cannot determine SWIG version" >&2;} + SWIG='' + as_fn_error $? "SWIG-2.0.4 is required to build pyldns for Python 3.2 and greater." "$LINENO" 5 + fi + fi + + + else + + # Ubuntu has swig 2.0 as /usr/bin/swig2.0 + for ac_prog in swig2.0 swig +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_SWIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $SWIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_SWIG="$SWIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_SWIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +SWIG=$ac_cv_path_SWIG +if test -n "$SWIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SWIG" >&5 +$as_echo "$SWIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$SWIG" && break +done + + if test -z "$SWIG" ; then + : + elif test -n "" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking SWIG version" >&5 +$as_echo_n "checking SWIG version... " >&6; } + swig_version=`$SWIG -version 2>&1 | grep 'SWIG Version' | sed 's/.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/g'` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $swig_version" >&5 +$as_echo "$swig_version" >&6; } + if test -n "$swig_version" ; then + # Calculate the required version number components + required= + required_major=`echo $required | sed 's/[^0-9].*//'` + if test -z "$required_major" ; then + required_major=0 + fi + required=`echo $required | sed 's/[0-9]*[^0-9]//'` + required_minor=`echo $required | sed 's/[^0-9].*//'` + if test -z "$required_minor" ; then + required_minor=0 + fi + required=`echo $required | sed 's/[0-9]*[^0-9]//'` + required_patch=`echo $required | sed 's/[^0-9].*//'` + if test -z "$required_patch" ; then + required_patch=0 + fi + # Calculate the available version number components + available=$swig_version + available_major=`echo $available | sed 's/[^0-9].*//'` + if test -z "$available_major" ; then + available_major=0 + fi + available=`echo $available | sed 's/[0-9]*[^0-9]//'` + available_minor=`echo $available | sed 's/[^0-9].*//'` + if test -z "$available_minor" ; then + available_minor=0 + fi + available=`echo $available | sed 's/[0-9]*[^0-9]//'` + available_patch=`echo $available | sed 's/[^0-9].*//'` + if test -z "$available_patch" ; then + available_patch=0 + fi + # Convert the version tuple into a single number for easier comparison. + # Using base 100 should be safe since SWIG internally uses BCD values + # to encode its version number. + required_swig_vernum=`expr $required_major \* 10000 \ + \+ $required_minor \* 100 \+ $required_patch` + available_swig_vernum=`expr $available_major \* 10000 \ + \+ $available_minor \* 100 \+ $available_patch` + + if test $available_swig_vernum -lt $required_swig_vernum; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: SWIG version >= is required. You have $swig_version." >&5 +$as_echo "$as_me: WARNING: SWIG version >= is required. You have $swig_version." >&2;} + SWIG='' + + else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SWIG library" >&5 +$as_echo_n "checking for SWIG library... " >&6; } + SWIG_LIB=`$SWIG -swiglib` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SWIG_LIB" >&5 +$as_echo "$SWIG_LIB" >&6; } + + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cannot determine SWIG version" >&5 +$as_echo "$as_me: WARNING: cannot determine SWIG version" >&2;} + SWIG='' + + fi + fi + + + fi + + if test ! -x "$SWIG"; then + as_fn_error $? "failed to find SWIG tool, install it, or do not build pyldns" "$LINENO" 5 + else + +$as_echo "#define HAVE_SWIG 1" >>confdefs.h + + PYLDNS="pyldns" + + swig="$SWIG" + + ldns_with_pyldns=yes + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: *** don't have Python, skipping SWIG, no pyldns ***" >&5 +$as_echo "*** don't have Python, skipping SWIG, no pyldns ***" >&6; } # ' + fi + + # xtra cflags for pyldns + if test x_$ldns_have_python != x_no; then + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -fno-strict-aliasing" >&5 +$as_echo_n "checking whether $CC supports -fno-strict-aliasing... " >&6; } +cache=`echo fno-strict-aliasing | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -fno-strict-aliasing -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +PYTHON_X_CFLAGS="-fno-strict-aliasing" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: + +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wno-missing-field-initializers" >&5 +$as_echo_n "checking whether $CC supports -Wno-missing-field-initializers... " >&6; } +cache=`echo Wno-missing-field-initializers | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -Wno-missing-field-initializers -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +PYTHON_X_CFLAGS="-Wno-missing-field-initializers $PYTHON_X_CFLAGS" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: + +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wno-unused-parameter" >&5 +$as_echo_n "checking whether $CC supports -Wno-unused-parameter... " >&6; } +cache=`echo Wno-unused-parameter | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -Wno-unused-parameter -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +PYTHON_X_CFLAGS="-Wno-unused-parameter $PYTHON_X_CFLAGS" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: + +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wno-unused-variable" >&5 +$as_echo_n "checking whether $CC supports -Wno-unused-variable... " >&6; } +cache=`echo Wno-unused-variable | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -Wno-unused-variable -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +PYTHON_X_CFLAGS="-Wno-unused-variable $PYTHON_X_CFLAGS" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: + +fi + + fi +fi + + +# Check for pyldnsx + +# Check whether --with-pyldnsx was given. +if test "${with_pyldnsx+set}" = set; then : + withval=$with_pyldnsx; +else + withval="with_pyldns" +fi + +if test x_$withval != x_no; then + if test x_$ldns_with_pyldns != x_no; then + PYLDNSX="pyldnsx" + + ldns_with_pyldnsx=yes + else + if test x_$withval != x_with_pyldns; then + as_fn_error $? "--with-pyldns is needed for the ldnsx python module" "$LINENO" 5 + fi + fi +fi + +if test x_$ldns_with_pyldns != x_no; then + PYLDNSINST="install-pyldns" + PYLDNSUNINST="uninstall-pyldns" + +else + PYLDNSINST="" + PYLDNSUNINST="" + +fi +if test x_$ldns_with_pyldnsx != x_no; then + PYLDNSXINST="install-pyldnsx" + PYLDNSXUNINST="uninstall-pyldnsx" + +else + PYLDNSXINST="" + PYLDNSXUNINST="" + +fi + + +# Use libtool + +# skip these tests, we do not need them. + + + + + + + + +# always use ./libtool unless override from commandline (libtool=mylibtool) +if test -z "$libtool"; then + libtool="./libtool" +fi + +# avoid libtool max commandline length test on systems that fork slowly. + +if echo "$host_os" | grep "sunos4" >/dev/null; then + lt_cv_sys_max_cmd_len=32750; +fi +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. +set dummy ${ac_tool_prefix}ar; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $AR in + [\\/]* | ?:[\\/]*) + ac_cv_path_AR="$AR" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_AR="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +AR=$ac_cv_path_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_AR"; then + ac_pt_AR=$AR + # Extract the first word of "ar", so it can be a program name with args. +set dummy ar; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_AR in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_AR="$ac_pt_AR" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_ac_pt_AR="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_AR=$ac_cv_path_ac_pt_AR +if test -n "$ac_pt_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_AR" >&5 +$as_echo "$ac_pt_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_pt_AR + fi +else + AR="$ac_cv_path_AR" +fi + +if test $AR = false; then + as_fn_error $? "Cannot find 'ar', please extend PATH to include it" "$LINENO" 5 +fi + +case `pwd` in + *\ * | *\ *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 +$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; +esac + + + +macro_version='2.4.2' +macro_revision='1.3337' + + + + + + + + + + + + + +ltmain="$ac_aux_dir/ltmain.sh" + +# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 +$as_echo_n "checking how to print strings... " >&6; } +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "" +} + +case "$ECHO" in + printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 +$as_echo "printf" >&6; } ;; + print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 +$as_echo "print -r" >&6; } ;; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 +$as_echo "cat" >&6; } ;; +esac + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_SED" && $as_test_x "$ac_path_SED"; } || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 +$as_echo_n "checking for fgrep... " >&6; } +if ${ac_cv_path_FGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 + then ac_cv_path_FGREP="$GREP -F" + else + if test -z "$FGREP"; then + ac_path_FGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in fgrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_FGREP" && $as_test_x "$ac_path_FGREP"; } || continue +# Check for GNU ac_path_FGREP and select it if it is found. + # Check for GNU $ac_path_FGREP +case `"$ac_path_FGREP" --version 2>&1` in +*GNU*) + ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'FGREP' >> "conftest.nl" + "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_FGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_FGREP="$ac_path_FGREP" + ac_path_FGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_FGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_FGREP"; then + as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_FGREP=$FGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 +$as_echo "$ac_cv_path_FGREP" >&6; } + FGREP="$ac_cv_path_FGREP" + + +test -z "$GREP" && GREP=grep + + + + + + + + + + + + + + + + + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${lt_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${lt_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 +$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } +if ${lt_cv_path_NM+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + : ${lt_cv_path_NM=no} +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 +$as_echo "$lt_cv_path_NM" >&6; } +if test "$lt_cv_path_NM" != "no"; then + NM="$lt_cv_path_NM" +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + if test -n "$ac_tool_prefix"; then + for ac_prog in dumpbin "link -dump" + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DUMPBIN"; then + ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DUMPBIN=$ac_cv_prog_DUMPBIN +if test -n "$DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 +$as_echo "$DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$DUMPBIN" && break + done +fi +if test -z "$DUMPBIN"; then + ac_ct_DUMPBIN=$DUMPBIN + for ac_prog in dumpbin "link -dump" +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DUMPBIN"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN +if test -n "$ac_ct_DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 +$as_echo "$ac_ct_DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_DUMPBIN" && break +done + + if test "x$ac_ct_DUMPBIN" = x; then + DUMPBIN=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DUMPBIN=$ac_ct_DUMPBIN + fi +fi + + case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols" + ;; + *) + DUMPBIN=: + ;; + esac + fi + + if test "$DUMPBIN" != ":"; then + NM="$DUMPBIN" + fi +fi +test -z "$NM" && NM=nm + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 +$as_echo_n "checking the name lister ($NM) interface... " >&6; } +if ${lt_cv_nm_interface+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: output\"" >&5) + cat conftest.out >&5 + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 +$as_echo "$lt_cv_nm_interface" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 +$as_echo_n "checking whether ln -s works... " >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 +$as_echo "no, using $LN_S" >&6; } +fi + +# find the maximum length of command line arguments +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 +$as_echo_n "checking the maximum length of command line arguments... " >&6; } +if ${lt_cv_sys_max_cmd_len+:} false; then : + $as_echo_n "(cached) " >&6 +else + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8 ; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac + +fi + +if test -n $lt_cv_sys_max_cmd_len ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 +$as_echo "$lt_cv_sys_max_cmd_len" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } +fi +max_cmd_len=$lt_cv_sys_max_cmd_len + + + + + + +: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 +$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } +# Try some XSI features +xsi_shell=no +( _lt_dummy="a/b/c" + test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ + = c,a/b,b/c, \ + && eval 'test $(( 1 + 1 )) -eq 2 \ + && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ + && xsi_shell=yes +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 +$as_echo "$xsi_shell" >&6; } + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 +$as_echo_n "checking whether the shell understands \"+=\"... " >&6; } +lt_shell_append=no +( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ + >/dev/null 2>&1 \ + && lt_shell_append=yes +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 +$as_echo "$lt_shell_append" >&6; } + + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi + + + + + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 +$as_echo_n "checking how to convert $build file names to $host format... " >&6; } +if ${lt_cv_to_host_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac + +fi + +to_host_file_cmd=$lt_cv_to_host_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 +$as_echo "$lt_cv_to_host_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 +$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } +if ${lt_cv_to_tool_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + #assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac + +fi + +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 +$as_echo "$lt_cv_to_tool_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 +$as_echo_n "checking for $LD option to reload object files... " >&6; } +if ${lt_cv_ld_reload_flag+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_reload_flag='-r' +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 +$as_echo "$lt_cv_ld_reload_flag" >&6; } +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + if test "$GCC" != yes; then + reload_cmds=false + fi + ;; + darwin*) + if test "$GCC" = yes; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' + else + reload_cmds='$LD$reload_flag -o $output$reload_objs' + fi + ;; +esac + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + +test -z "$OBJDUMP" && OBJDUMP=objdump + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 +$as_echo_n "checking how to recognize dependent libraries... " >&6; } +if ${lt_cv_deplibs_check_method+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# `unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# which responds to the $file_magic_cmd with a given extended regex. +# If you have `file' or equivalent on your system and you're not sure +# whether `pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[4-9]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[45]*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. + if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[3-9]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 +$as_echo "$lt_cv_deplibs_check_method" >&6; } + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + + + + + + + + + + + + + + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DLLTOOL=$ac_cv_prog_DLLTOOL +if test -n "$DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 +$as_echo "$DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DLLTOOL"; then + ac_ct_DLLTOOL=$DLLTOOL + # Extract the first word of "dlltool", so it can be a program name with args. +set dummy dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DLLTOOL"; then + ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_DLLTOOL="dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL +if test -n "$ac_ct_DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 +$as_echo "$ac_ct_DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DLLTOOL" = x; then + DLLTOOL="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DLLTOOL=$ac_ct_DLLTOOL + fi +else + DLLTOOL="$ac_cv_prog_DLLTOOL" +fi + +test -z "$DLLTOOL" && DLLTOOL=dlltool + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 +$as_echo_n "checking how to associate runtime and link libraries... " >&6; } +if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh + # decide which to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd="$ECHO" + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 +$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + + + + + + + +if test -n "$ac_tool_prefix"; then + for ac_prog in ar + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AR="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AR" && break + done +fi +if test -z "$AR"; then + ac_ct_AR=$AR + for ac_prog in ar +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_AR="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_AR" && break +done + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +fi + +: ${AR=ar} +: ${AR_FLAGS=cru} + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 +$as_echo_n "checking for archiver @FILE support... " >&6; } +if ${lt_cv_ar_at_file+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ar_at_file=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test "$ac_status" -eq 0; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test "$ac_status" -ne 0; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 +$as_echo "$lt_cv_ar_at_file" >&6; } + +if test "x$lt_cv_ar_at_file" = xno; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +test -z "$STRIP" && STRIP=: + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +test -z "$RANLIB" && RANLIB=: + + + + + + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac + + + + + + + + + + + + + + + + + + + + + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + + + + + + + + + + + + + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 +$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } +if ${lt_cv_sys_global_symbol_pipe+:} false; then : + $as_echo_n "(cached) " >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[ABCDGISTW]' + ;; +hpux*) + if test "$host_cpu" = ia64; then + symcode='[ABCDEGRST]' + fi + ;; +irix* | nonstopux*) + symcode='[BCDEGRST]' + ;; +osf*) + symcode='[BCDEGQRST]' + ;; +solaris*) + symcode='[BDRT]' + ;; +sco3.2v5*) + symcode='[DT]' + ;; +sysv4.2uw2*) + symcode='[DT]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[ABDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function + # and D for any global variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK '"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ +" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ +" s[1]~/^[@?]/{print s[1], s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Now try to grab the symbols. + nlist=conftest.nm + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 + (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +/* DATA imports from DLLs on WIN32 con't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined(__osf__) +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 +$as_echo_n "checking for sysroot... " >&6; } + +# Check whether --with-sysroot was given. +if test "${with_sysroot+set}" = set; then : + withval=$with_sysroot; +else + with_sysroot=no +fi + + +lt_sysroot= +case ${with_sysroot} in #( + yes) + if test "$GCC" = yes; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${with_sysroot}" >&5 +$as_echo "${with_sysroot}" >&6; } + as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 + ;; +esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 +$as_echo "${lt_sysroot:-no}" >&6; } + + + + + +# Check whether --enable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then : + enableval=$enable_libtool_lock; +fi + +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 +$as_echo_n "checking whether the C compiler needs -belf... " >&6; } +if ${lt_cv_cc_needs_belf+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_cc_needs_belf=yes +else + lt_cv_cc_needs_belf=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 +$as_echo "$lt_cv_cc_needs_belf" >&6; } + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD="${LD-ld}_sol2" + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks="$enable_libtool_lock" + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. +set dummy ${ac_tool_prefix}mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$MANIFEST_TOOL"; then + ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL +if test -n "$MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 +$as_echo "$MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_MANIFEST_TOOL"; then + ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL + # Extract the first word of "mt", so it can be a program name with args. +set dummy mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_MANIFEST_TOOL"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL +if test -n "$ac_ct_MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 +$as_echo "$ac_ct_MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_MANIFEST_TOOL" = x; then + MANIFEST_TOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL + fi +else + MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" +fi + +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 +$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } +if ${lt_cv_path_mainfest_tool+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&5 + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 +$as_echo "$lt_cv_path_mainfest_tool" >&6; } +if test "x$lt_cv_path_mainfest_tool" != xyes; then + MANIFEST_TOOL=: +fi + + + + + + + case $host_os in + rhapsody* | darwin*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. +set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DSYMUTIL"; then + ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DSYMUTIL=$ac_cv_prog_DSYMUTIL +if test -n "$DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 +$as_echo "$DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DSYMUTIL"; then + ac_ct_DSYMUTIL=$DSYMUTIL + # Extract the first word of "dsymutil", so it can be a program name with args. +set dummy dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DSYMUTIL"; then + ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL +if test -n "$ac_ct_DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 +$as_echo "$ac_ct_DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DSYMUTIL" = x; then + DSYMUTIL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DSYMUTIL=$ac_ct_DSYMUTIL + fi +else + DSYMUTIL="$ac_cv_prog_DSYMUTIL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. +set dummy ${ac_tool_prefix}nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NMEDIT"; then + ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +NMEDIT=$ac_cv_prog_NMEDIT +if test -n "$NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 +$as_echo "$NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_NMEDIT"; then + ac_ct_NMEDIT=$NMEDIT + # Extract the first word of "nmedit", so it can be a program name with args. +set dummy nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_NMEDIT"; then + ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_NMEDIT="nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT +if test -n "$ac_ct_NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 +$as_echo "$ac_ct_NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_NMEDIT" = x; then + NMEDIT=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + NMEDIT=$ac_ct_NMEDIT + fi +else + NMEDIT="$ac_cv_prog_NMEDIT" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. +set dummy ${ac_tool_prefix}lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LIPO"; then + ac_cv_prog_LIPO="$LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_LIPO="${ac_tool_prefix}lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LIPO=$ac_cv_prog_LIPO +if test -n "$LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 +$as_echo "$LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_LIPO"; then + ac_ct_LIPO=$LIPO + # Extract the first word of "lipo", so it can be a program name with args. +set dummy lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_LIPO"; then + ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_LIPO="lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO +if test -n "$ac_ct_LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 +$as_echo "$ac_ct_LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_LIPO" = x; then + LIPO=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + LIPO=$ac_ct_LIPO + fi +else + LIPO="$ac_cv_prog_LIPO" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL"; then + ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_OTOOL="${ac_tool_prefix}otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL=$ac_cv_prog_OTOOL +if test -n "$OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 +$as_echo "$OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL"; then + ac_ct_OTOOL=$OTOOL + # Extract the first word of "otool", so it can be a program name with args. +set dummy otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL"; then + ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_OTOOL="otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL +if test -n "$ac_ct_OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 +$as_echo "$ac_ct_OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL" = x; then + OTOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL=$ac_ct_OTOOL + fi +else + OTOOL="$ac_cv_prog_OTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL64"; then + ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL64=$ac_cv_prog_OTOOL64 +if test -n "$OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 +$as_echo "$OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL64"; then + ac_ct_OTOOL64=$OTOOL64 + # Extract the first word of "otool64", so it can be a program name with args. +set dummy otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL64"; then + ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_OTOOL64="otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 +if test -n "$ac_ct_OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 +$as_echo "$ac_ct_OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL64" = x; then + OTOOL64=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL64=$ac_ct_OTOOL64 + fi +else + OTOOL64="$ac_cv_prog_OTOOL64" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 +$as_echo_n "checking for -single_module linker flag... " >&6; } +if ${lt_cv_apple_cc_single_mod+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_apple_cc_single_mod=no + if test -z "${LT_MULTI_MODULE}"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&5 + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test $_lt_result -eq 0; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&5 + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 +$as_echo "$lt_cv_apple_cc_single_mod" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 +$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } +if ${lt_cv_ld_exported_symbols_list+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_ld_exported_symbols_list=yes +else + lt_cv_ld_exported_symbols_list=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 +$as_echo "$lt_cv_ld_exported_symbols_list" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 +$as_echo_n "checking for -force_load linker flag... " >&6; } +if ${lt_cv_ld_force_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 + echo "$AR cru libconftest.a conftest.o" >&5 + $AR cru libconftest.a conftest.o 2>&5 + echo "$RANLIB libconftest.a" >&5 + $RANLIB libconftest.a 2>&5 + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&5 + elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&5 + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 +$as_echo "$lt_cv_ld_force_load" >&6; } + case $host_os in + rhapsody* | darwin1.[012]) + _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[91]*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + 10.[012]*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test "$lt_cv_apple_cc_single_mod" = "yes"; then + _lt_dar_single_mod='$single_module' + fi + if test "$lt_cv_ld_exported_symbols_list" = "yes"; then + _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac + +for ac_header in dlfcn.h +do : + ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default +" +if test "x$ac_cv_header_dlfcn_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DLFCN_H 1 +_ACEOF + +fi + +done + + + + + + + +# Set options + + + + enable_dlopen=no + + + enable_win32_dll=no + + + # Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then : + enableval=$enable_shared; p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_shared=yes +fi + + + + + + + + + + # Check whether --enable-static was given. +if test "${enable_static+set}" = set; then : + enableval=$enable_static; p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_static=yes +fi + + + + + + + + + + +# Check whether --with-pic was given. +if test "${with_pic+set}" = set; then : + withval=$with_pic; lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for lt_pkg in $withval; do + IFS="$lt_save_ifs" + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + pic_mode=default +fi + + +test -z "$pic_mode" && pic_mode=default + + + + + + + + # Check whether --enable-fast-install was given. +if test "${enable_fast_install+set}" = set; then : + enableval=$enable_fast_install; p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_fast_install=yes +fi + + + + + + + + + + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ltmain" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +test -z "$LN_S" && LN_S="ln -s" + + + + + + + + + + + + + + +if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 +$as_echo_n "checking for objdir... " >&6; } +if ${lt_cv_objdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 +$as_echo "$lt_cv_objdir" >&6; } +objdir=$lt_cv_objdir + + + + + +cat >>confdefs.h <<_ACEOF +#define LT_OBJDIR "$lt_cv_objdir/" +_ACEOF + + + + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld="$lt_cv_prog_gnu_ld" + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` + + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 +$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/${ac_tool_prefix}file; then + lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + + +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 +$as_echo_n "checking for file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/file; then + lt_cv_path_MAGIC_CMD="$ac_dir/file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + else + MAGIC_CMD=: + fi +fi + + fi + ;; +esac + +# Use C for the default configuration in the libtool script + +lt_save_CC="$CC" +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +objext=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* + +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* + + +if test -n "$compiler"; then + +lt_prog_compiler_no_builtin_flag= + +if test "$GCC" = yes; then + case $cc_basename in + nvcc*) + lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; + *) + lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } +if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } + +if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then + lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" +else + : +fi + +fi + + + + + + + lt_prog_compiler_wl= +lt_prog_compiler_pic= +lt_prog_compiler_static= + + + if test "$GCC" = yes; then + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_static='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + lt_prog_compiler_pic='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + lt_prog_compiler_static= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + ;; + + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic=-Kconform_pic + fi + ;; + + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + lt_prog_compiler_wl='-Xlinker ' + if test -n "$lt_prog_compiler_pic"; then + lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + else + lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + # old Intel for x86_64 which still supported -KPIC. + ecc*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='--shared' + lt_prog_compiler_static='--static' + ;; + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-qpic' + lt_prog_compiler_static='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='' + ;; + *Sun\ F* | *Sun*Fortran*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Wl,' + ;; + *Intel*\ [CF]*Compiler*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + *Portland\ Group*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + + rdos*) + lt_prog_compiler_static='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + lt_prog_compiler_wl='-Qoption ld ';; + *) + lt_prog_compiler_wl='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl='-Qoption ld ' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + lt_prog_compiler_pic='-Kconform_pic' + lt_prog_compiler_static='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_can_build_shared=no + ;; + + uts4*) + lt_prog_compiler_pic='-pic' + lt_prog_compiler_static='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared=no + ;; + esac + fi + +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic= + ;; + *) + lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" + ;; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } +if ${lt_cv_prog_compiler_pic+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic=$lt_prog_compiler_pic +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 +$as_echo "$lt_cv_prog_compiler_pic" >&6; } +lt_prog_compiler_pic=$lt_cv_prog_compiler_pic + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 +$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } +if ${lt_cv_prog_compiler_pic_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_works=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_pic_works=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 +$as_echo "$lt_cv_prog_compiler_pic_works" >&6; } + +if test x"$lt_cv_prog_compiler_pic_works" = xyes; then + case $lt_prog_compiler_pic in + "" | " "*) ;; + *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; + esac +else + lt_prog_compiler_pic= + lt_prog_compiler_can_build_shared=no +fi + +fi + + + + + + + + + + + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if ${lt_cv_prog_compiler_static_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_static_works=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_static_works=yes + fi + else + lt_cv_prog_compiler_static_works=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 +$as_echo "$lt_cv_prog_compiler_static_works" >&6; } + +if test x"$lt_cv_prog_compiler_static_works" = xyes; then + : +else + lt_prog_compiler_static= +fi + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +$as_echo_n "checking if we can lock with hard links... " >&6; } + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +$as_echo "$hard_links" >&6; } + if test "$hard_links" = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + + runpath_var= + allow_undefined_flag= + always_export_symbols=no + archive_cmds= + archive_expsym_cmds= + compiler_needs_object=no + enable_shared_with_static_runtimes=no + export_dynamic_flag_spec= + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + hardcode_automatic=no + hardcode_direct=no + hardcode_direct_absolute=no + hardcode_libdir_flag_spec= + hardcode_libdir_separator= + hardcode_minus_L=no + hardcode_shlibpath_var=unsupported + inherit_rpath=no + link_all_deplibs=unknown + module_cmds= + module_expsym_cmds= + old_archive_from_new_cmds= + old_archive_from_expsyms_cmds= + thread_safe_flag_spec= + whole_archive_flag_spec= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + linux* | k*bsd*-gnu | gnu*) + link_all_deplibs=no + ;; + esac + + ld_shlibs=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test "$with_gnu_ld" = yes; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; + *\ \(GNU\ Binutils\)\ [3-9]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test "$lt_use_gnu_ld_interface" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + export_dynamic_flag_spec='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec= + fi + supports_anon_versioning=no + case `$LD -v 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[3-9]*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + export_dynamic_flag_spec='${wl}--export-all-symbols' + allow_undefined_flag=unsupported + always_export_symbols=no + enable_shared_with_static_runtimes=yes + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs=no + fi + ;; + + haiku*) + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + link_all_deplibs=yes + ;; + + interix[3-9]*) + hardcode_direct=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test "$host_os" = linux-dietlibc; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test "$tmp_diet" = no + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + whole_archive_flag_spec= + tmp_sharedflag='--shared' ;; + xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + compiler_needs_object=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + compiler_needs_object=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test "x$supports_anon_versioning" = xyes; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + ld_shlibs=no + fi + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test "$ld_shlibs" = no; then + runpath_var= + hardcode_libdir_flag_spec= + export_dynamic_flag_spec= + whole_archive_flag_spec= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix[4-9]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global + # defined symbols, whereas GNU nm marks them as "W". + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds='' + hardcode_direct=yes + hardcode_direct_absolute=yes + hardcode_libdir_separator=':' + link_all_deplibs=yes + file_list_spec='${wl}-f,' + + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + link_all_deplibs=no + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + export_dynamic_flag_spec='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_="/usr/lib:/lib" + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag="-z nodefs" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_="/usr/lib:/lib" + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag=' ${wl}-bernotok' + allow_undefined_flag=' ${wl}-berok' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' + fi + archive_cmds_need_lc=yes + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + bsdi[45]*) + export_dynamic_flag_spec=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + always_export_symbols=yes + file_list_spec='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, )='true' + enable_shared_with_static_runtimes=yes + exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + old_postinstall_cmds='chmod 644 $oldlib' + postlink_cmds='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_from_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' + enable_shared_with_static_runtimes=yes + ;; + esac + ;; + + darwin* | rhapsody*) + + + archive_cmds_need_lc=no + hardcode_direct=no + hardcode_automatic=yes + hardcode_shlibpath_var=unsupported + if test "$lt_cv_ld_force_load" = "yes"; then + whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + + else + whole_archive_flag_spec='' + fi + link_all_deplibs=yes + allow_undefined_flag="$_lt_dar_allow_undefined" + case $cc_basename in + ifort*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test "$_lt_dar_can_shared" = "yes"; then + output_verbose_link_cmd=func_echo_all + archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + + else + ld_shlibs=no + fi + + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + if test "$GCC" = yes; then + archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + export_dynamic_flag_spec='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='${wl}-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 +$as_echo_n "checking if $CC understands -b... " >&6; } +if ${lt_cv_prog_compiler__b+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler__b=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -b" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler__b=yes + fi + else + lt_cv_prog_compiler__b=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 +$as_echo "$lt_cv_prog_compiler__b" >&6; } + +if test x"$lt_cv_prog_compiler__b" = xyes; then + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' +else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' +fi + + ;; + esac + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct=no + hardcode_shlibpath_var=no + ;; + *) + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 +$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } +if ${lt_cv_irix_exported_symbol+:} false; then : + $as_echo_n "(cached) " >&6 +else + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int foo (void) { return 0; } +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_irix_exported_symbol=yes +else + lt_cv_irix_exported_symbol=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 +$as_echo "$lt_cv_irix_exported_symbol" >&6; } + if test "$lt_cv_irix_exported_symbol" = yes; then + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' + fi + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + inherit_rpath=yes + link_all_deplibs=yes + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + newsos6) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_shlibpath_var=no + ;; + + *nto* | *qnx*) + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + hardcode_shlibpath_var=no + hardcode_direct_absolute=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + else + case $host_os in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-R$libdir' + ;; + *) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + esac + fi + else + ld_shlibs=no + fi + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + archive_cmds_need_lc='no' + hardcode_libdir_separator=: + ;; + + solaris*) + no_undefined_flag=' -z defs' + if test "$GCC" = yes; then + wlarc='${wl}' + archive_cmds='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='${wl}' + archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. GCC discards it without `$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test "$GCC" = yes; then + whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + else + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' + fi + ;; + esac + link_all_deplibs=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds='$CC -r -o $output$reload_objs' + hardcode_direct=no + ;; + motorola) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag='${wl}-z,text' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag='${wl}-z,text' + allow_undefined_flag='${wl}-z,nodefs' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='${wl}-R,$libdir' + hardcode_libdir_separator=':' + link_all_deplibs=yes + export_dynamic_flag_spec='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac + + if test x$host_vendor = xsni; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + export_dynamic_flag_spec='${wl}-Blargedynsym' + ;; + esac + fi + fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 +$as_echo "$ld_shlibs" >&6; } +test "$ld_shlibs" = no && can_build_shared=no + +with_gnu_ld=$with_gnu_ld + + + + + + + + + + + + + + + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } +if ${lt_cv_archive_cmds_need_lc+:} false; then : + $as_echo_n "(cached) " >&6 +else + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl + pic_flag=$lt_prog_compiler_pic + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + then + lt_cv_archive_cmds_need_lc=no + else + lt_cv_archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 +$as_echo "$lt_cv_archive_cmds_need_lc" >&6; } + archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc + ;; + esac + fi + ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +$as_echo_n "checking dynamic linker characteristics... " >&6; } + +if test "$GCC" = yes; then + case $host_os in + darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; + *) lt_awk_arg="/^libraries:/" ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;; + *) lt_sed_strip_eq="s,=/,/,g" ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary. + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path/$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" + else + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS=" "; FS="/|\n";} { + lt_foo=""; + lt_count=0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo="/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[lt_foo]++; } + if (lt_freq[lt_foo] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's,/\([A-Za-z]:\),\1,g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix[4-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + library_names_spec='${libname}.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec="$LIB" + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[23].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=yes + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[3-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + if ${lt_cv_shlibpath_overrides_runpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : + lt_cv_shlibpath_overrides_runpath=yes +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + +fi + + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +$as_echo "$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +fi +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +$as_echo_n "checking how to hardcode library paths into programs... " >&6; } +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || + test -n "$runpath_var" || + test "X$hardcode_automatic" = "Xyes" ; then + + # We can hardcode non-existent directories. + if test "$hardcode_direct" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && + test "$hardcode_minus_L" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 +$as_echo "$hardcode_action" >&6; } + +if test "$hardcode_action" = relink || + test "$inherit_rpath" = yes; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + + + + + + if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +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 dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + +fi + + ;; + + *) + ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" +if test "x$ac_cv_func_shl_load" = xyes; then : + lt_cv_dlopen="shl_load" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 +$as_echo_n "checking for shl_load in -ldld... " >&6; } +if ${ac_cv_lib_dld_shl_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +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 shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_shl_load=yes +else + ac_cv_lib_dld_shl_load=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 +$as_echo "$ac_cv_lib_dld_shl_load" >&6; } +if test "x$ac_cv_lib_dld_shl_load" = xyes; then : + lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" +else + ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" +if test "x$ac_cv_func_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +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 dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 +$as_echo_n "checking for dlopen in -lsvld... " >&6; } +if ${ac_cv_lib_svld_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +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 dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_svld_dlopen=yes +else + ac_cv_lib_svld_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 +$as_echo "$ac_cv_lib_svld_dlopen" >&6; } +if test "x$ac_cv_lib_svld_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 +$as_echo_n "checking for dld_link in -ldld... " >&6; } +if ${ac_cv_lib_dld_dld_link+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +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 dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_dld_link=yes +else + ac_cv_lib_dld_dld_link=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 +$as_echo "$ac_cv_lib_dld_dld_link" >&6; } +if test "x$ac_cv_lib_dld_dld_link" = xyes; then : + lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" +fi + + +fi + + +fi + + +fi + + +fi + + +fi + + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 +$as_echo_n "checking whether a program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 +$as_echo "$lt_cv_dlopen_self" >&6; } + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 +$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self_static+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self_static=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self_static=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 +$as_echo "$lt_cv_dlopen_self_static" >&6; } + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + + + + + + + + + + + + + + + + + +striplib= +old_striplib= +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 +$as_echo_n "checking whether stripping libraries is possible... " >&6; } +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + { $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; } + fi + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +fi + + + + + + + + + + + + + # Report which library types will actually be built + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 +$as_echo_n "checking if libtool supports shared libraries... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 +$as_echo "$can_build_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 +$as_echo_n "checking whether to build shared libraries... " >&6; } + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[4-9]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 +$as_echo "$enable_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 +$as_echo_n "checking whether to build static libraries... " >&6; } + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 +$as_echo "$enable_static" >&6; } + + + + +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC="$lt_save_CC" + + + + + + + + + + + + + + + + ac_config_commands="$ac_config_commands libtool" + + + + +# Only expand once: + + + + +tmp_CPPFLAGS=$CPPFLAGS +tmp_LDFLAGS=$LDFLAGS +tmp_LIBS=$LIBS + + + +# Check whether --with-ssl was given. +if test "${with_ssl+set}" = set; then : + withval=$with_ssl; + +else + + withval="yes" + +fi + + + withval=$withval + if test x_$withval != x_no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL" >&5 +$as_echo_n "checking for SSL... " >&6; } + if test x_$withval = x_ -o x_$withval = x_yes; then + withval="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw /usr" + fi + for dir in $withval; do + ssldir="$dir" + if test -f "$dir/include/openssl/ssl.h"; then + found_ssl="yes" + +cat >>confdefs.h <<_ACEOF +#define HAVE_SSL /**/ +_ACEOF + + if test "$ssldir" != "/usr"; then + CPPFLAGS="$CPPFLAGS -I$ssldir/include" + LIBSSL_CPPFLAGS="$LIBSSL_CPPFLAGS -I$ssldir/include" + fi + break; + fi + done + if test x_$found_ssl != x_yes; then + as_fn_error $? "Cannot find the SSL libraries in $withval" "$LINENO" 5 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in $ssldir" >&5 +$as_echo "found in $ssldir" >&6; } + HAVE_SSL=yes + if test "$ssldir" != "/usr" -a "$ssldir" != ""; then + LDFLAGS="$LDFLAGS -L$ssldir/lib" + LIBSSL_LDFLAGS="$LIBSSL_LDFLAGS -L$ssldir/lib" + + if test "x$enable_rpath" = xyes; then + if echo "$ssldir/lib" | grep "^/" >/dev/null; then + RUNTIME_PATH="$RUNTIME_PATH -R$ssldir/lib" + fi + fi + + 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; } + LIBS="$LIBS -lcrypto" + LIBSSL_LIBS="$LIBSSL_LIBS -lcrypto" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + int HMAC_CTX_init(void); + (void)HMAC_CTX_init(); + + ; + return 0; +} +_ACEOF +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 + + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + # check if -lwsock32 or -lgdi32 are needed. + BAKLIBS="$LIBS" + BAKSSLLIBS="$LIBSSL_LIBS" + LIBS="$LIBS -lgdi32" + LIBSSL_LIBS="$LIBSSL_LIBS -lgdi32" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if -lcrypto needs -lgdi32" >&5 +$as_echo_n "checking if -lcrypto needs -lgdi32... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + int HMAC_CTX_init(void); + (void)HMAC_CTX_init(); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + +$as_echo "#define HAVE_HMAC_CTX_INIT 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; } + LIBS="$BAKLIBS" + LIBSSL_LIBS="$BAKSSLLIBS" + LIBS="$LIBS -ldl" + LIBSSL_LIBS="$LIBSSL_LIBS -ldl" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if -lcrypto needs -ldl" >&5 +$as_echo_n "checking if -lcrypto needs -ldl... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + int HMAC_CTX_init(void); + (void)HMAC_CTX_init(); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + +$as_echo "#define HAVE_HMAC_CTX_INIT 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 \ + conftest$ac_exeext conftest.$ac_ext + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + fi + + + # openssl engine functionality needs dlopen(). + BAKLIBS="$LIBS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5 +$as_echo_n "checking for library containing dlopen... " >&6; } +if ${ac_cv_search_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +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 dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +for ac_lib in '' dl; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_dlopen=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_dlopen+:} false; then : + break +fi +done +if ${ac_cv_search_dlopen+:} false; then : + +else + ac_cv_search_dlopen=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5 +$as_echo "$ac_cv_search_dlopen" >&6; } +ac_res=$ac_cv_search_dlopen +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + + if test "$LIBS" != "$BAKLIBS"; then + LIBSSL_LIBS="$LIBSSL_LIBS -ldl" + fi + fi +for ac_header in openssl/ssl.h +do : + ac_fn_c_check_header_compile "$LINENO" "openssl/ssl.h" "ac_cv_header_openssl_ssl_h" "$ac_includes_default +" +if test "x$ac_cv_header_openssl_ssl_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OPENSSL_SSL_H 1 +_ACEOF + +fi + +done + +for ac_header in openssl/err.h +do : + ac_fn_c_check_header_compile "$LINENO" "openssl/err.h" "ac_cv_header_openssl_err_h" "$ac_includes_default +" +if test "x$ac_cv_header_openssl_err_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OPENSSL_ERR_H 1 +_ACEOF + +fi + +done + +for ac_header in openssl/rand.h +do : + ac_fn_c_check_header_compile "$LINENO" "openssl/rand.h" "ac_cv_header_openssl_rand_h" "$ac_includes_default +" +if test "x$ac_cv_header_openssl_rand_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OPENSSL_RAND_H 1 +_ACEOF + +fi + +done + + + + +for ac_func in EVP_sha256 +do : + ac_fn_c_check_func "$LINENO" "EVP_sha256" "ac_cv_func_EVP_sha256" +if test "x$ac_cv_func_EVP_sha256" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_EVP_SHA256 1 +_ACEOF + +fi +done + + +# for macosx, see if glibtool exists and use that +# BSD's need to know the version... +#AC_CHECK_PROG(glibtool, glibtool, [glibtool], ) +#AC_CHECK_PROGS(libtool, [libtool15 libtool], [./libtool]) + +# Check whether --enable-sha2 was given. +if test "${enable_sha2+set}" = set; then : + enableval=$enable_sha2; +fi + +case "$enable_sha2" in + no) + ;; + yes|*) + if test "x$HAVE_SSL" != "xyes"; then + as_fn_error $? "SHA2 enabled, but no SSL support" "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SHA256 and SHA512" >&5 +$as_echo_n "checking for SHA256 and SHA512... " >&6; } + ac_fn_c_check_func "$LINENO" "SHA256_Init" "ac_cv_func_SHA256_Init" +if test "x$ac_cv_func_SHA256_Init" = xyes; then : + +else + + as_fn_error $? "No SHA2 functions found in OpenSSL: please upgrade OpenSSL or rerun with --disable-sha2" "$LINENO" 5 + +fi + + +cat >>confdefs.h <<_ACEOF +#define USE_SHA2 1 +_ACEOF + + ;; +esac + +# Check whether --enable-gost was given. +if test "${enable_gost+set}" = set; then : + enableval=$enable_gost; +fi + +case "$enable_gost" in + no) + ;; + *) if test "x$HAVE_SSL" != "xyes"; then + as_fn_error $? "GOST enabled, but no SSL support" "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GOST" >&5 +$as_echo_n "checking for GOST... " >&6; } + ac_fn_c_check_func "$LINENO" "EVP_PKEY_set_type_str" "ac_cv_func_EVP_PKEY_set_type_str" +if test "x$ac_cv_func_EVP_PKEY_set_type_str" = xyes; then : + +else + as_fn_error $? "OpenSSL >= 1.0.0 is needed for GOST support or rerun with --disable-gost" "$LINENO" 5 +fi + + ac_fn_c_check_func "$LINENO" "EC_KEY_new" "ac_cv_func_EC_KEY_new" +if test "x$ac_cv_func_EC_KEY_new" = xyes; then : + +else + as_fn_error $? "No ECC functions found in OpenSSL: please upgrade OpenSSL or rerun with --disable-gost" "$LINENO" 5 +fi + + +cat >>confdefs.h <<_ACEOF +#define USE_GOST 1 +_ACEOF + + ;; +esac + +# Check whether --enable-ecdsa was given. +if test "${enable_ecdsa+set}" = set; then : + enableval=$enable_ecdsa; +fi + +case "$enable_ecdsa" in + no) + ;; + *) if test "x$HAVE_SSL" != "xyes"; then + as_fn_error $? "ECDSA enabled, but no SSL support" "$LINENO" 5 + fi + ac_fn_c_check_func "$LINENO" "ECDSA_sign" "ac_cv_func_ECDSA_sign" +if test "x$ac_cv_func_ECDSA_sign" = xyes; then : + +else + as_fn_error $? "OpenSSL does not support ECDSA: please upgrade OpenSSL or rerun with --disable-ecdsa" "$LINENO" 5 +fi + + ac_fn_c_check_func "$LINENO" "SHA384_Init" "ac_cv_func_SHA384_Init" +if test "x$ac_cv_func_SHA384_Init" = xyes; then : + +else + as_fn_error $? "OpenSSL does not support SHA384: please upgrade OpenSSL or rerun with --disable-ecdsa" "$LINENO" 5 +fi + + ac_fn_c_check_decl "$LINENO" "NID_X9_62_prime256v1" "ac_cv_have_decl_NID_X9_62_prime256v1" "$ac_includes_default +#include + +" +if test "x$ac_cv_have_decl_NID_X9_62_prime256v1" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_NID_X9_62_PRIME256V1 $ac_have_decl +_ACEOF +if test $ac_have_decl = 1; then : + +else + as_fn_error $? "OpenSSL does not support the ECDSA curves: please upgrade OpenSSL or rerun with --disable-ecdsa" "$LINENO" 5 +fi +ac_fn_c_check_decl "$LINENO" "NID_secp384r1" "ac_cv_have_decl_NID_secp384r1" "$ac_includes_default +#include + +" +if test "x$ac_cv_have_decl_NID_secp384r1" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_NID_SECP384R1 $ac_have_decl +_ACEOF +if test $ac_have_decl = 1; then : + +else + as_fn_error $? "OpenSSL does not support the ECDSA curves: please upgrade OpenSSL or rerun with --disable-ecdsa" "$LINENO" 5 +fi + + # we now know we have ECDSA and the required curves. + +cat >>confdefs.h <<_ACEOF +#define USE_ECDSA 1 +_ACEOF + + ;; +esac + + + + +CPPFLAGS=$tmp_CPPFLAGS +LDFLAGS=$tmp_LDFLAGS +LIBS=$tmp_LIBS + + +# add option to disable the evil rpath + +# Check whether --enable-rpath was given. +if test "${enable_rpath+set}" = set; then : + enableval=$enable_rpath; enable_rpath=$enableval +else + enable_rpath=yes +fi + +if test "x$enable_rpath" = xno; then + ac_config_commands="$ac_config_commands disable-rpath" + +fi + + +#AC_RUN_IFELSE([AC_LANG_SOURCE( +#[ +#int main() +#{ +#short one = 1; +#char *cp = (char*)&one; +#if ( *cp == 0 ) +#return(0); +#else +#return(1); +#} +#])], [],[ +#AC_DEFINE(CONFCHECK_LITTLE_ENDIAN, 1, [system appears to be little-endian]) +#],[]) + +# should define WORDS_BIGENDIAN if the system is big-endian + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 +$as_echo_n "checking whether byte ordering is bigendian... " >&6; } +if ${ac_cv_c_bigendian+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_bigendian=unknown + # See if we're dealing with a universal compiler. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __APPLE_CC__ + not a universal capable compiler + #endif + typedef int dummy; + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + # Check for potential -arch flags. It is not universal unless + # there are at least two -arch flags with different values. + ac_arch= + ac_prev= + for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do + if test -n "$ac_prev"; then + case $ac_word in + i?86 | x86_64 | ppc | ppc64) + if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then + ac_arch=$ac_word + else + ac_cv_c_bigendian=universal + break + fi + ;; + esac + ac_prev= + elif test "x$ac_word" = "x-arch"; then + ac_prev=arch + fi + done +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if test $ac_cv_c_bigendian = unknown; then + # See if sys/param.h defines the BYTE_ORDER macro. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ + && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ + && LITTLE_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main () +{ +#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to _BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main () +{ +#ifndef _BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # Compile a test program. + if test "$cross_compiling" = yes; then : + # Try to guess by grepping values from an object file. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +short int ascii_mm[] = + { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; + short int ascii_ii[] = + { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; + int use_ascii (int i) { + return ascii_mm[i] + ascii_ii[i]; + } + short int ebcdic_ii[] = + { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; + short int ebcdic_mm[] = + { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; + int use_ebcdic (int i) { + return ebcdic_mm[i] + ebcdic_ii[i]; + } + extern int foo; + +int +main () +{ +return use_ascii (foo) == use_ebcdic (foo); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then + ac_cv_c_bigendian=yes + fi + if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi + fi +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long int l; + char c[sizeof (long int)]; + } u; + u.l = 1; + return u.c[sizeof (long int) - 1] == 1; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_c_bigendian=no +else + ac_cv_c_bigendian=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 +$as_echo "$ac_cv_c_bigendian" >&6; } + case $ac_cv_c_bigendian in #( + yes) + $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h +;; #( + no) + ;; #( + universal) + +$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h + + ;; #( + *) + as_fn_error $? "unknown endianness + presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; + esac + + +# Checks for header files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdbool.h that conforms to C99" >&5 +$as_echo_n "checking for stdbool.h that conforms to C99... " >&6; } +if ${ac_cv_header_stdbool_h+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#ifndef bool + "error: bool is not defined" +#endif +#ifndef false + "error: false is not defined" +#endif +#if false + "error: false is not 0" +#endif +#ifndef true + "error: true is not defined" +#endif +#if true != 1 + "error: true is not 1" +#endif +#ifndef __bool_true_false_are_defined + "error: __bool_true_false_are_defined is not defined" +#endif + + struct s { _Bool s: 1; _Bool t; } s; + + char a[true == 1 ? 1 : -1]; + char b[false == 0 ? 1 : -1]; + char c[__bool_true_false_are_defined == 1 ? 1 : -1]; + char d[(bool) 0.5 == true ? 1 : -1]; + /* See body of main program for 'e'. */ + char f[(_Bool) 0.0 == false ? 1 : -1]; + char g[true]; + char h[sizeof (_Bool)]; + char i[sizeof s.t]; + enum { j = false, k = true, l = false * true, m = true * 256 }; + /* The following fails for + HP aC++/ANSI C B3910B A.05.55 [Dec 04 2003]. */ + _Bool n[m]; + char o[sizeof n == m * sizeof n[0] ? 1 : -1]; + char p[-1 - (_Bool) 0 < 0 && -1 - (bool) 0 < 0 ? 1 : -1]; + /* Catch a bug in an HP-UX C compiler. See + http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html + http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html + */ + _Bool q = true; + _Bool *pq = &q; + +int +main () +{ + + bool e = &s; + *pq |= q; + *pq |= ! q; + /* Refer to every declared value, to avoid compiler optimizations. */ + return (!a + !b + !c + !d + !e + !f + !g + !h + !i + !!j + !k + !!l + + !m + !n + !o + !p + !q + !pq); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdbool_h=yes +else + ac_cv_header_stdbool_h=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdbool_h" >&5 +$as_echo "$ac_cv_header_stdbool_h" >&6; } +ac_fn_c_check_type "$LINENO" "_Bool" "ac_cv_type__Bool" "$ac_includes_default" +if test "x$ac_cv_type__Bool" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE__BOOL 1 +_ACEOF + + +fi + +if test $ac_cv_header_stdbool_h = yes; then + +$as_echo "#define HAVE_STDBOOL_H 1" >>confdefs.h + +fi + +#AC_HEADER_SYS_WAIT +#AC_CHECK_HEADERS([getopt.h fcntl.h stdlib.h string.h strings.h unistd.h]) +# do the very minimum - we can always extend this +for ac_header in getopt.h stdarg.h openssl/ssl.h netinet/in.h time.h arpa/inet.h netdb.h +do : + 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 eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in sys/param.h sys/mount.h +do : + 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 HAVE_SYS_PARAM_H + # include + #endif + + +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +ac_fn_c_check_header_compile "$LINENO" "sys/socket.h" "ac_cv_header_sys_socket_h" "$ac_includes_default + + #if HAVE_SYS_PARAM_H + # include + #endif + + +" +if test "x$ac_cv_header_sys_socket_h" = xyes; then : + +include_sys_socket_h='#include ' + +$as_echo "#define HAVE_SYS_SOCKET_H 1" >>confdefs.h + + +else + +include_sys_socket_h='' + +fi + + + +ac_fn_c_check_header_compile "$LINENO" "inttypes.h" "ac_cv_header_inttypes_h" "$ac_includes_default + +" +if test "x$ac_cv_header_inttypes_h" = xyes; then : + +include_inttypes_h='#include ' + +$as_echo "#define HAVE_INTTYPES_H 1" >>confdefs.h + +ldns_build_config_have_inttypes_h=1 + + +else + +include_inttypes_h='' +ldns_build_config_have_inttypes_h=0 + + +fi + + + +ac_fn_c_check_header_compile "$LINENO" "sys/types.h" "ac_cv_header_sys_types_h" "$ac_includes_default + +" +if test "x$ac_cv_header_sys_types_h" = xyes; then : + +include_systypes_h='#include ' + +$as_echo "#define HAVE_SYS_TYPES_H 1" >>confdefs.h + + +else + +include_systypes_h='' + +fi + + + +ac_fn_c_check_header_compile "$LINENO" "unistd.h" "ac_cv_header_unistd_h" "$ac_includes_default + +" +if test "x$ac_cv_header_unistd_h" = xyes; then : + +include_unistd_h='#include ' + +$as_echo "#define HAVE_UNISTD_H 1" >>confdefs.h + + +else + +include_unistd_h='' + +fi + + + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of time_t" >&5 +$as_echo_n "checking size of time_t... " >&6; } +if ${ac_cv_sizeof_time_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (time_t))" "ac_cv_sizeof_time_t" " +$ac_includes_default +#ifdef TIME_WITH_SYS_TIME +# include +# include +#else +# ifdef HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif + +"; then : + +else + if test "$ac_cv_type_time_t" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (time_t) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_time_t=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_time_t" >&5 +$as_echo "$ac_cv_sizeof_time_t" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_TIME_T $ac_cv_sizeof_time_t +_ACEOF + + + +if test x_$with_examples != x_no; then +for ac_header in pcap.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "pcap.h" "ac_cv_header_pcap_h" "$ac_includes_default" +if test "x$ac_cv_header_pcap_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_PCAP_H 1 +_ACEOF + +else + $ac_includes_default +fi + +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pcap_open_offline in -lpcap" >&5 +$as_echo_n "checking for pcap_open_offline in -lpcap... " >&6; } +if ${ac_cv_lib_pcap_pcap_open_offline+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpcap $LIBS" +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 pcap_open_offline (); +int +main () +{ +return pcap_open_offline (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_pcap_pcap_open_offline=yes +else + ac_cv_lib_pcap_pcap_open_offline=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcap_pcap_open_offline" >&5 +$as_echo "$ac_cv_lib_pcap_pcap_open_offline" >&6; } +if test "x$ac_cv_lib_pcap_pcap_open_offline" = xyes; then : + + +$as_echo "#define HAVE_LIBPCAP 1" >>confdefs.h + LIBPCAP_LIBS=-lpcap + + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Can't find pcap library (needed for ldns-dpa, will not build dpa now.)" >&5 +$as_echo "$as_me: WARNING: Can't find pcap library (needed for ldns-dpa, will not build dpa now.)" >&2;} + + +fi + +for ac_header in netinet/in_systm.h net/if.h netinet/ip.h netinet/udp.h netinet/igmp.h netinet/if_ether.h netinet/ip6.h net/ethernet.h netinet/ip_compat.h +do : + 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 +#ifdef HAVE_NETINET_IN_SYSTM_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +fi + + +ac_fn_c_check_type "$LINENO" "socklen_t" "ac_cv_type_socklen_t" " +$ac_includes_default +#ifdef HAVE_SYS_SOCKET_H +# include +#endif +#ifdef HAVE_WS2TCPIP_H +# include +#endif + +" +if test "x$ac_cv_type_socklen_t" = xyes; then : + +else + +$as_echo "#define socklen_t int" >>confdefs.h + +fi + +ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" +if test "x$ac_cv_type_size_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned int +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "ssize_t" "ac_cv_type_ssize_t" "$ac_includes_default" +if test "x$ac_cv_type_ssize_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define ssize_t int +_ACEOF + +fi + + + ac_fn_c_check_type "$LINENO" "intptr_t" "ac_cv_type_intptr_t" "$ac_includes_default" +if test "x$ac_cv_type_intptr_t" = xyes; then : + +$as_echo "#define HAVE_INTPTR_T 1" >>confdefs.h + +else + for ac_type in 'int' 'long int' 'long long int'; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(sizeof (void *) <= sizeof ($ac_type))]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +cat >>confdefs.h <<_ACEOF +#define intptr_t $ac_type +_ACEOF + + ac_type= +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test -z "$ac_type" && break + done +fi + + +ac_fn_c_check_type "$LINENO" "in_addr_t" "ac_cv_type_in_addr_t" " +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_NETINET_IN_H +# include +#endif +" +if test "x$ac_cv_type_in_addr_t" = xyes; then : + +else + +$as_echo "#define in_addr_t uint32_t" >>confdefs.h + +fi + +ac_fn_c_check_type "$LINENO" "in_port_t" "ac_cv_type_in_port_t" " +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_NETINET_IN_H +# include +#endif +" +if test "x$ac_cv_type_in_port_t" = xyes; then : + +else + +$as_echo "#define in_port_t uint16_t" >>confdefs.h + +fi + +ac_fn_c_check_member "$LINENO" "struct sockaddr_storage" "ss_family" "ac_cv_member_struct_sockaddr_storage_ss_family" "$ac_includes_default +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif + +" +if test "x$ac_cv_member_struct_sockaddr_storage_ss_family" = xyes; then : + +else + + ac_fn_c_check_member "$LINENO" "struct sockaddr_storage" "__ss_family" "ac_cv_member_struct_sockaddr_storage___ss_family" "$ac_includes_default +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif + +" +if test "x$ac_cv_member_struct_sockaddr_storage___ss_family" = xyes; then : + + +$as_echo "#define ss_family __ss_family" >>confdefs.h + + +fi + + +fi + + +for ac_header in stdlib.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" +if test "x$ac_cv_header_stdlib_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STDLIB_H 1 +_ACEOF + +fi + +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible malloc" >&5 +$as_echo_n "checking for GNU libc compatible malloc... " >&6; } +if ${ac_cv_func_malloc_0_nonnull+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_malloc_0_nonnull=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#if defined STDC_HEADERS || defined HAVE_STDLIB_H +# include +#else +char *malloc (); +#endif + +int +main () +{ +return ! malloc (0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_malloc_0_nonnull=yes +else + ac_cv_func_malloc_0_nonnull=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_malloc_0_nonnull" >&5 +$as_echo "$ac_cv_func_malloc_0_nonnull" >&6; } +if test $ac_cv_func_malloc_0_nonnull = yes; then : + +$as_echo "#define HAVE_MALLOC 1" >>confdefs.h + +else + $as_echo "#define HAVE_MALLOC 0" >>confdefs.h + + case " $LIBOBJS " in + *" malloc.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS malloc.$ac_objext" + ;; +esac + + +$as_echo "#define malloc rpl_malloc" >>confdefs.h + +fi + + +for ac_header in stdlib.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" +if test "x$ac_cv_header_stdlib_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STDLIB_H 1 +_ACEOF + +fi + +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible realloc" >&5 +$as_echo_n "checking for GNU libc compatible realloc... " >&6; } +if ${ac_cv_func_realloc_0_nonnull+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_realloc_0_nonnull=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#if defined STDC_HEADERS || defined HAVE_STDLIB_H +# include +#else +char *realloc (); +#endif + +int +main () +{ +return ! realloc (0, 0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_realloc_0_nonnull=yes +else + ac_cv_func_realloc_0_nonnull=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_realloc_0_nonnull" >&5 +$as_echo "$ac_cv_func_realloc_0_nonnull" >&6; } +if test $ac_cv_func_realloc_0_nonnull = yes; then : + +$as_echo "#define HAVE_REALLOC 1" >>confdefs.h + +else + $as_echo "#define HAVE_REALLOC 0" >>confdefs.h + + case " $LIBOBJS " in + *" realloc.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS realloc.$ac_objext" + ;; +esac + + +$as_echo "#define realloc rpl_realloc" >>confdefs.h + +fi + + + +ac_fn_c_check_func "$LINENO" "b64_pton" "ac_cv_func_b64_pton" +if test "x$ac_cv_func_b64_pton" = xyes; then : + $as_echo "#define HAVE_B64_PTON 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" b64_pton.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS b64_pton.$ac_objext" + ;; +esac + +fi + + +ac_fn_c_check_func "$LINENO" "b64_ntop" "ac_cv_func_b64_ntop" +if test "x$ac_cv_func_b64_ntop" = xyes; then : + $as_echo "#define HAVE_B64_NTOP 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" b64_ntop.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS b64_ntop.$ac_objext" + ;; +esac + +fi + + +ac_fn_c_check_func "$LINENO" "b32_pton" "ac_cv_func_b32_pton" +if test "x$ac_cv_func_b32_pton" = xyes; then : + $as_echo "#define HAVE_B32_PTON 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" b32_pton.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS b32_pton.$ac_objext" + ;; +esac + +fi + + +ac_fn_c_check_func "$LINENO" "b32_ntop" "ac_cv_func_b32_ntop" +if test "x$ac_cv_func_b32_ntop" = xyes; then : + $as_echo "#define HAVE_B32_NTOP 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" b32_ntop.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS b32_ntop.$ac_objext" + ;; +esac + +fi + + +ac_fn_c_check_func "$LINENO" "calloc" "ac_cv_func_calloc" +if test "x$ac_cv_func_calloc" = xyes; then : + $as_echo "#define HAVE_CALLOC 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" calloc.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS calloc.$ac_objext" + ;; +esac + +fi + + +ac_fn_c_check_func "$LINENO" "timegm" "ac_cv_func_timegm" +if test "x$ac_cv_func_timegm" = xyes; then : + $as_echo "#define HAVE_TIMEGM 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" timegm.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS timegm.$ac_objext" + ;; +esac + +fi + + +ac_fn_c_check_func "$LINENO" "gmtime_r" "ac_cv_func_gmtime_r" +if test "x$ac_cv_func_gmtime_r" = xyes; then : + $as_echo "#define HAVE_GMTIME_R 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" gmtime_r.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS gmtime_r.$ac_objext" + ;; +esac + +fi + + +ac_fn_c_check_func "$LINENO" "ctime_r" "ac_cv_func_ctime_r" +if test "x$ac_cv_func_ctime_r" = xyes; then : + $as_echo "#define HAVE_CTIME_R 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" ctime_r.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS ctime_r.$ac_objext" + ;; +esac + +fi + + +ac_fn_c_check_func "$LINENO" "localtime_r" "ac_cv_func_localtime_r" +if test "x$ac_cv_func_localtime_r" = xyes; then : + $as_echo "#define HAVE_LOCALTIME_R 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" localtime_r.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS localtime_r.$ac_objext" + ;; +esac + +fi + + +ac_fn_c_check_func "$LINENO" "isblank" "ac_cv_func_isblank" +if test "x$ac_cv_func_isblank" = xyes; then : + $as_echo "#define HAVE_ISBLANK 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" isblank.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS isblank.$ac_objext" + ;; +esac + +fi + + +ac_fn_c_check_func "$LINENO" "isascii" "ac_cv_func_isascii" +if test "x$ac_cv_func_isascii" = xyes; then : + $as_echo "#define HAVE_ISASCII 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" isascii.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS isascii.$ac_objext" + ;; +esac + +fi + + +ac_fn_c_check_func "$LINENO" "inet_aton" "ac_cv_func_inet_aton" +if test "x$ac_cv_func_inet_aton" = xyes; then : + $as_echo "#define HAVE_INET_ATON 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" inet_aton.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS inet_aton.$ac_objext" + ;; +esac + +fi + + +ac_fn_c_check_func "$LINENO" "inet_pton" "ac_cv_func_inet_pton" +if test "x$ac_cv_func_inet_pton" = xyes; then : + $as_echo "#define HAVE_INET_PTON 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" inet_pton.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS inet_pton.$ac_objext" + ;; +esac + +fi + + +ac_fn_c_check_func "$LINENO" "inet_ntop" "ac_cv_func_inet_ntop" +if test "x$ac_cv_func_inet_ntop" = xyes; then : + $as_echo "#define HAVE_INET_NTOP 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" inet_ntop.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS inet_ntop.$ac_objext" + ;; +esac + +fi + + +ac_fn_c_check_func "$LINENO" "snprintf" "ac_cv_func_snprintf" +if test "x$ac_cv_func_snprintf" = xyes; then : + $as_echo "#define HAVE_SNPRINTF 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" snprintf.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS snprintf.$ac_objext" + ;; +esac + +fi + + +ac_fn_c_check_func "$LINENO" "strlcpy" "ac_cv_func_strlcpy" +if test "x$ac_cv_func_strlcpy" = xyes; then : + $as_echo "#define HAVE_STRLCPY 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" strlcpy.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS strlcpy.$ac_objext" + ;; +esac + +fi + + +ac_fn_c_check_func "$LINENO" "memmove" "ac_cv_func_memmove" +if test "x$ac_cv_func_memmove" = xyes; then : + $as_echo "#define HAVE_MEMMOVE 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" memmove.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS memmove.$ac_objext" + ;; +esac + +fi + + +ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default" +if test "x$ac_cv_type_pid_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define pid_t int +_ACEOF + +fi + +for ac_header in vfork.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "vfork.h" "ac_cv_header_vfork_h" "$ac_includes_default" +if test "x$ac_cv_header_vfork_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_VFORK_H 1 +_ACEOF + +fi + +done + +for ac_func in fork vfork +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 : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +if test "x$ac_cv_func_fork" = xyes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working fork" >&5 +$as_echo_n "checking for working fork... " >&6; } +if ${ac_cv_func_fork_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_fork_works=cross +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* By Ruediger Kuhlmann. */ + return fork () < 0; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_fork_works=yes +else + ac_cv_func_fork_works=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_fork_works" >&5 +$as_echo "$ac_cv_func_fork_works" >&6; } + +else + ac_cv_func_fork_works=$ac_cv_func_fork +fi +if test "x$ac_cv_func_fork_works" = xcross; then + case $host in + *-*-amigaos* | *-*-msdosdjgpp*) + # Override, as these systems have only a dummy fork() stub + ac_cv_func_fork_works=no + ;; + *) + ac_cv_func_fork_works=yes + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&5 +$as_echo "$as_me: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&2;} +fi +ac_cv_func_vfork_works=$ac_cv_func_vfork +if test "x$ac_cv_func_vfork" = xyes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working vfork" >&5 +$as_echo_n "checking for working vfork... " >&6; } +if ${ac_cv_func_vfork_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_vfork_works=cross +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Thanks to Paul Eggert for this test. */ +$ac_includes_default +#include +#ifdef HAVE_VFORK_H +# include +#endif +/* On some sparc systems, changes by the child to local and incoming + argument registers are propagated back to the parent. The compiler + is told about this with #include , but some compilers + (e.g. gcc -O) don't grok . Test for this by using a + static variable whose address is put into a register that is + clobbered by the vfork. */ +static void +#ifdef __cplusplus +sparc_address_test (int arg) +# else +sparc_address_test (arg) int arg; +#endif +{ + static pid_t child; + if (!child) { + child = vfork (); + if (child < 0) { + perror ("vfork"); + _exit(2); + } + if (!child) { + arg = getpid(); + write(-1, "", 0); + _exit (arg); + } + } +} + +int +main () +{ + pid_t parent = getpid (); + pid_t child; + + sparc_address_test (0); + + child = vfork (); + + if (child == 0) { + /* Here is another test for sparc vfork register problems. This + test uses lots of local variables, at least as many local + variables as main has allocated so far including compiler + temporaries. 4 locals are enough for gcc 1.40.3 on a Solaris + 4.1.3 sparc, but we use 8 to be safe. A buggy compiler should + reuse the register of parent for one of the local variables, + since it will think that parent can't possibly be used any more + in this routine. Assigning to the local variable will thus + munge parent in the parent process. */ + pid_t + p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(), + p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid(); + /* Convince the compiler that p..p7 are live; otherwise, it might + use the same hardware register for all 8 local variables. */ + if (p != p1 || p != p2 || p != p3 || p != p4 + || p != p5 || p != p6 || p != p7) + _exit(1); + + /* On some systems (e.g. IRIX 3.3), vfork doesn't separate parent + from child file descriptors. If the child closes a descriptor + before it execs or exits, this munges the parent's descriptor + as well. Test for this by closing stdout in the child. */ + _exit(close(fileno(stdout)) != 0); + } else { + int status; + struct stat st; + + while (wait(&status) != child) + ; + return ( + /* Was there some problem with vforking? */ + child < 0 + + /* Did the child fail? (This shouldn't happen.) */ + || status + + /* Did the vfork/compiler bug occur? */ + || parent != getpid() + + /* Did the file descriptor bug occur? */ + || fstat(fileno(stdout), &st) != 0 + ); + } +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_vfork_works=yes +else + ac_cv_func_vfork_works=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_vfork_works" >&5 +$as_echo "$ac_cv_func_vfork_works" >&6; } + +fi; +if test "x$ac_cv_func_fork_works" = xcross; then + ac_cv_func_vfork_works=$ac_cv_func_vfork + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&5 +$as_echo "$as_me: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&2;} +fi + +if test "x$ac_cv_func_vfork_works" = xyes; then + +$as_echo "#define HAVE_WORKING_VFORK 1" >>confdefs.h + +else + +$as_echo "#define vfork fork" >>confdefs.h + +fi +if test "x$ac_cv_func_fork_works" = xyes; then + +$as_echo "#define HAVE_WORKING_FORK 1" >>confdefs.h + +fi + +for ac_func in endprotoent endservent sleep random fcntl strtoul bzero memset +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 : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for getaddrinfo" >&5 +$as_echo_n "checking for getaddrinfo... " >&6; } +ac_cv_func_getaddrinfo=no +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#ifdef __cplusplus +extern "C" +{ +#endif +char* getaddrinfo(); +char* (*f) () = getaddrinfo; +#ifdef __cplusplus +} +#endif +int main() { + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_func_getaddrinfo="yes" +if test "$ac_cv_header_windows_h" = "yes"; then + +$as_echo "#define USE_WINSOCK 1" >>confdefs.h + + USE_WINSOCK="1" + LIBS="$LIBS -lws2_32" +fi + +else + ORIGLIBS="$LIBS" +LIBS="$LIBS -lws2_32" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#ifdef HAVE_WS2TCPIP_H +#include +#endif + +int +main () +{ + + (void)getaddrinfo(NULL, NULL, NULL, NULL); + + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + +ac_cv_func_getaddrinfo="yes" + +$as_echo "#define USE_WINSOCK 1" >>confdefs.h + +USE_WINSOCK="1" + +else + +ac_cv_func_getaddrinfo="no" +LIBS="$ORIGLIBS" + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_getaddrinfo" >&5 +$as_echo "$ac_cv_func_getaddrinfo" >&6; } +if test $ac_cv_func_getaddrinfo = yes; then + +$as_echo "#define HAVE_GETADDRINFO 1" >>confdefs.h + +fi + +if test $ac_cv_func_getaddrinfo = no; then + case " $LIBOBJS " in + *" fake-rfc2553.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS fake-rfc2553.$ac_objext" + ;; +esac + +fi +if test "$USE_WINSOCK" = 1; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}windres", so it can be a program name with args. +set dummy ${ac_tool_prefix}windres; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_WINDRES+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$WINDRES"; then + ac_cv_prog_WINDRES="$WINDRES" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_WINDRES="${ac_tool_prefix}windres" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +WINDRES=$ac_cv_prog_WINDRES +if test -n "$WINDRES"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WINDRES" >&5 +$as_echo "$WINDRES" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_WINDRES"; then + ac_ct_WINDRES=$WINDRES + # Extract the first word of "windres", so it can be a program name with args. +set dummy windres; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_WINDRES+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_WINDRES"; then + ac_cv_prog_ac_ct_WINDRES="$ac_ct_WINDRES" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_WINDRES="windres" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_WINDRES=$ac_cv_prog_ac_ct_WINDRES +if test -n "$ac_ct_WINDRES"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_WINDRES" >&5 +$as_echo "$ac_ct_WINDRES" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_WINDRES" = x; then + WINDRES="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + WINDRES=$ac_ct_WINDRES + fi +else + WINDRES="$ac_cv_prog_WINDRES" +fi + +fi + +# check ioctlsocket +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ioctlsocket" >&5 +$as_echo_n "checking for ioctlsocket... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#ifdef HAVE_WINSOCK2_H +#include +#endif + +int +main () +{ + + (void)ioctlsocket(0, 0, NULL); + + ; + return 0; +} +_ACEOF +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_IOCTLSOCKET 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + +#AC_SEARCH_LIBS(RSA_new, [crypto]) + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler (${CC-cc}) accepts the \"format\" attribute" >&5 +$as_echo_n "checking whether the C compiler (${CC-cc}) accepts the \"format\" attribute... " >&6; } +if ${ac_cv_c_format_attribute+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_format_attribute=no +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +void f (char *format, ...) __attribute__ ((format (printf, 1, 2))); +void (*pf) (char *format, ...) __attribute__ ((format (printf, 1, 2))); + +int +main () +{ + + f ("%s", "str"); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_format_attribute="yes" +else + ac_cv_c_format_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_format_attribute" >&5 +$as_echo "$ac_cv_c_format_attribute" >&6; } +if test $ac_cv_c_format_attribute = yes; then + +$as_echo "#define HAVE_ATTR_FORMAT 1" >>confdefs.h + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler (${CC-cc}) accepts the \"unused\" attribute" >&5 +$as_echo_n "checking whether the C compiler (${CC-cc}) accepts the \"unused\" attribute... " >&6; } +if ${ac_cv_c_unused_attribute+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_unused_attribute=no +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +void f (char *u __attribute__((unused))); + +int +main () +{ + + f ("x"); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_unused_attribute="yes" +else + ac_cv_c_unused_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_unused_attribute" >&5 +$as_echo "$ac_cv_c_unused_attribute" >&6; } +if test $ac_cv_c_unused_attribute = yes; then + +$as_echo "#define HAVE_ATTR_UNUSED 1" >>confdefs.h + +fi + + +# check OSX deployment target which is needed +if echo $build_os | grep darwin > /dev/null; then + export MACOSX_DEPLOYMENT_TARGET="10.4" +fi + + +$as_echo "#define SYSCONFDIR sysconfdir" >>confdefs.h + + + + + + +if test "x$HAVE_SSL" = "xyes"; then + ldns_build_config_have_ssl=1 + +else + ldns_build_config_have_ssl=0 + +fi +if test "x$ac_cv_c_format_attribute" = "xyes"; then + ldns_build_config_have_attr_format=1 + +else + ldns_build_config_have_attr_format=0 + +fi +if test "x$ac_cv_c_unused_attribute" = "xyes"; then + ldns_build_config_have_attr_unused=1 + +else + ldns_build_config_have_attr_unused=0 + +fi + +ac_config_files="$ac_config_files Makefile ldns/common.h ldns/net.h ldns/util.h packaging/libldns.pc packaging/ldns-config" + + +ac_config_headers="$ac_config_headers ldns/config.h" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by ldns $as_me 1.6.13, which was +generated by GNU Autoconf 2.68. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +ldns config.status 1.6.13 +configured by $0, generated by GNU Autoconf 2.68, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2010 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# + + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' +macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' +enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' +enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' +pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' +enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' +SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' +ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' +PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' +host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' +host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' +host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' +build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' +build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' +build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' +SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' +Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' +GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' +EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' +FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' +LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' +NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' +LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' +max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' +ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' +exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' +lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' +lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' +lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' +lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' +lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' +reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' +reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' +OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' +deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' +file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' +file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' +want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' +DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' +sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' +AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' +AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' +archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' +STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' +RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' +old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' +old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' +lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' +CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' +CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' +compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' +GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' +nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' +lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' +objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' +MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' +need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' +MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' +DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' +NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' +LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' +OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' +OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' +libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' +shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' +extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' +compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' +module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' +with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' +no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' +hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' +hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' +inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' +link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' +always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' +exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' +include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' +prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' +postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' +file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' +variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' +need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' +need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' +version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' +runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' +libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' +library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' +soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' +install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' +postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' +postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' +finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' +hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' +sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' +sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`' +hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' +enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' +old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' +striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' + +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in SHELL \ +ECHO \ +PATH_SEPARATOR \ +SED \ +GREP \ +EGREP \ +FGREP \ +LD \ +NM \ +LN_S \ +lt_SP2NL \ +lt_NL2SP \ +reload_flag \ +OBJDUMP \ +deplibs_check_method \ +file_magic_cmd \ +file_magic_glob \ +want_nocaseglob \ +DLLTOOL \ +sharedlib_from_linklib_cmd \ +AR \ +AR_FLAGS \ +archiver_list_spec \ +STRIP \ +RANLIB \ +CC \ +CFLAGS \ +compiler \ +lt_cv_sys_global_symbol_pipe \ +lt_cv_sys_global_symbol_to_cdecl \ +lt_cv_sys_global_symbol_to_c_name_address \ +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ +nm_file_list_spec \ +lt_prog_compiler_no_builtin_flag \ +lt_prog_compiler_pic \ +lt_prog_compiler_wl \ +lt_prog_compiler_static \ +lt_cv_prog_compiler_c_o \ +need_locks \ +MANIFEST_TOOL \ +DSYMUTIL \ +NMEDIT \ +LIPO \ +OTOOL \ +OTOOL64 \ +shrext_cmds \ +export_dynamic_flag_spec \ +whole_archive_flag_spec \ +compiler_needs_object \ +with_gnu_ld \ +allow_undefined_flag \ +no_undefined_flag \ +hardcode_libdir_flag_spec \ +hardcode_libdir_separator \ +exclude_expsyms \ +include_expsyms \ +file_list_spec \ +variables_saved_for_relink \ +libname_spec \ +library_names_spec \ +soname_spec \ +install_override_mode \ +finish_eval \ +old_striplib \ +striplib; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in reload_cmds \ +old_postinstall_cmds \ +old_postuninstall_cmds \ +old_archive_cmds \ +extract_expsyms_cmds \ +old_archive_from_new_cmds \ +old_archive_from_expsyms_cmds \ +archive_cmds \ +archive_expsym_cmds \ +module_cmds \ +module_expsym_cmds \ +export_symbols_cmds \ +prelink_cmds \ +postlink_cmds \ +postinstall_cmds \ +postuninstall_cmds \ +finish_cmds \ +sys_lib_search_path_spec \ +sys_lib_dlsearch_path_spec; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +ac_aux_dir='$ac_aux_dir' +xsi_shell='$xsi_shell' +lt_shell_append='$lt_shell_append' + +# See if we are running on zsh, and set the options which allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + + + PACKAGE='$PACKAGE' + VERSION='$VERSION' + TIMESTAMP='$TIMESTAMP' + RM='$RM' + ofile='$ofile' + + + + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; + "disable-rpath") CONFIG_COMMANDS="$CONFIG_COMMANDS disable-rpath" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "ldns/common.h") CONFIG_FILES="$CONFIG_FILES ldns/common.h" ;; + "ldns/net.h") CONFIG_FILES="$CONFIG_FILES ldns/net.h" ;; + "ldns/util.h") CONFIG_FILES="$CONFIG_FILES ldns/util.h" ;; + "packaging/libldns.pc") CONFIG_FILES="$CONFIG_FILES packaging/libldns.pc" ;; + "packaging/ldns-config") CONFIG_FILES="$CONFIG_FILES packaging/ldns-config" ;; + "ldns/config.h") CONFIG_HEADERS="$CONFIG_HEADERS ldns/config.h" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi + ;; + + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "libtool":C) + + # See if we are running on zsh, and set the options which allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + + cfgfile="${ofile}T" + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL + +# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is part of GNU Libtool. +# +# GNU Libtool is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, or +# obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +# The names of the tagged configurations supported by this script. +available_tags="" + +# ### BEGIN LIBTOOL CONFIG + +# Which release of libtool.m4 was used? +macro_version=$macro_version +macro_revision=$macro_revision + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# What type of objects to build. +pic_mode=$pic_mode + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# An echo program that protects backslashes. +ECHO=$lt_ECHO + +# The PATH separator for the build system. +PATH_SEPARATOR=$lt_PATH_SEPARATOR + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="\$SED -e 1s/^X//" + +# A grep program that handles long lines. +GREP=$lt_GREP + +# An ERE matcher. +EGREP=$lt_EGREP + +# A literal string matcher. +FGREP=$lt_FGREP + +# A BSD- or MS-compatible name lister. +NM=$lt_NM + +# Whether we need soft or hard links. +LN_S=$lt_LN_S + +# What is the maximum length of a command? +max_cmd_len=$max_cmd_len + +# Object file suffix (normally "o"). +objext=$ac_objext + +# Executable file suffix (normally ""). +exeext=$exeext + +# whether the shell understands "unset". +lt_unset=$lt_unset + +# turn spaces into newlines. +SP2NL=$lt_lt_SP2NL + +# turn newlines into spaces. +NL2SP=$lt_lt_NL2SP + +# convert \$build file names to \$host format. +to_host_file_cmd=$lt_cv_to_host_file_cmd + +# convert \$build files to toolchain format. +to_tool_file_cmd=$lt_cv_to_tool_file_cmd + +# An object symbol dumper. +OBJDUMP=$lt_OBJDUMP + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method = "file_magic". +file_magic_cmd=$lt_file_magic_cmd + +# How to find potential files when deplibs_check_method = "file_magic". +file_magic_glob=$lt_file_magic_glob + +# Find potential files using nocaseglob when deplibs_check_method = "file_magic". +want_nocaseglob=$lt_want_nocaseglob + +# DLL creation program. +DLLTOOL=$lt_DLLTOOL + +# Command to associate shared and link libraries. +sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd + +# The archiver. +AR=$lt_AR + +# Flags to create an archive. +AR_FLAGS=$lt_AR_FLAGS + +# How to feed a file listing to the archiver. +archiver_list_spec=$lt_archiver_list_spec + +# A symbol stripping program. +STRIP=$lt_STRIP + +# Commands used to install an old-style archive. +RANLIB=$lt_RANLIB +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Whether to use a lock for old archive extraction. +lock_old_archive_extraction=$lock_old_archive_extraction + +# A C compiler. +LTCC=$lt_CC + +# LTCC compiler flags. +LTCFLAGS=$lt_CFLAGS + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration. +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair. +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# Transform the output of nm in a C name address pair when lib prefix is needed. +global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix + +# Specify filename containing input files for \$NM. +nm_file_list_spec=$lt_nm_file_list_spec + +# The root where to search for dependent libraries,and in which our libraries should be installed. +lt_sysroot=$lt_sysroot + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# Used to examine libraries when file_magic_cmd begins with "file". +MAGIC_CMD=$MAGIC_CMD + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Manifest tool. +MANIFEST_TOOL=$lt_MANIFEST_TOOL + +# Tool to manipulate archived DWARF debug symbol files on Mac OS X. +DSYMUTIL=$lt_DSYMUTIL + +# Tool to change global to local symbols on Mac OS X. +NMEDIT=$lt_NMEDIT + +# Tool to manipulate fat objects and archives on Mac OS X. +LIPO=$lt_LIPO + +# ldd/readelf like tool for Mach-O binaries on Mac OS X. +OTOOL=$lt_OTOOL + +# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. +OTOOL64=$lt_OTOOL64 + +# Old archive suffix (normally "a"). +libext=$libext + +# Shared library suffix (normally ".so"). +shrext_cmds=$lt_shrext_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at link time. +variables_saved_for_relink=$lt_variables_saved_for_relink + +# Do we need the "lib" prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Library versioning type. +version_type=$version_type + +# Shared library runtime path variable. +runpath_var=$runpath_var + +# Shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Permission mode override for installation of shared libraries. +install_override_mode=$lt_install_override_mode + +# Command to use after installation of a shared archive. +postinstall_cmds=$lt_postinstall_cmds + +# Command to use after uninstallation of a shared archive. +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# As "finish_cmds", except a single script fragment to be evaled but +# not shown. +finish_eval=$lt_finish_eval + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Compile-time system search path for libraries. +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries. +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + + +# The linker used to build libraries. +LD=$lt_LD + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds + +# A language specific compiler. +CC=$lt_compiler + +# Is the compiler the GNU compiler? +with_gcc=$GCC + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds +module_expsym_cmds=$lt_module_expsym_cmds + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \${shlibpath_var} if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds + +# Commands necessary for finishing linking programs. +postlink_cmds=$lt_postlink_cmds + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# ### END LIBTOOL CONFIG + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + +ltmain="$ac_aux_dir/ltmain.sh" + + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + if test x"$xsi_shell" = xyes; then + sed -e '/^func_dirname ()$/,/^} # func_dirname /c\ +func_dirname ()\ +{\ +\ case ${1} in\ +\ */*) func_dirname_result="${1%/*}${2}" ;;\ +\ * ) func_dirname_result="${3}" ;;\ +\ esac\ +} # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_basename ()$/,/^} # func_basename /c\ +func_basename ()\ +{\ +\ func_basename_result="${1##*/}"\ +} # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\ +func_dirname_and_basename ()\ +{\ +\ case ${1} in\ +\ */*) func_dirname_result="${1%/*}${2}" ;;\ +\ * ) func_dirname_result="${3}" ;;\ +\ esac\ +\ func_basename_result="${1##*/}"\ +} # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_stripname ()$/,/^} # func_stripname /c\ +func_stripname ()\ +{\ +\ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\ +\ # positional parameters, so assign one to ordinary parameter first.\ +\ func_stripname_result=${3}\ +\ func_stripname_result=${func_stripname_result#"${1}"}\ +\ func_stripname_result=${func_stripname_result%"${2}"}\ +} # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\ +func_split_long_opt ()\ +{\ +\ func_split_long_opt_name=${1%%=*}\ +\ func_split_long_opt_arg=${1#*=}\ +} # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\ +func_split_short_opt ()\ +{\ +\ func_split_short_opt_arg=${1#??}\ +\ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\ +} # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\ +func_lo2o ()\ +{\ +\ case ${1} in\ +\ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\ +\ *) func_lo2o_result=${1} ;;\ +\ esac\ +} # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_xform ()$/,/^} # func_xform /c\ +func_xform ()\ +{\ + func_xform_result=${1%.*}.lo\ +} # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_arith ()$/,/^} # func_arith /c\ +func_arith ()\ +{\ + func_arith_result=$(( $* ))\ +} # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_len ()$/,/^} # func_len /c\ +func_len ()\ +{\ + func_len_result=${#1}\ +} # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + +fi + +if test x"$lt_shell_append" = xyes; then + sed -e '/^func_append ()$/,/^} # func_append /c\ +func_append ()\ +{\ + eval "${1}+=\\${2}"\ +} # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\ +func_append_quoted ()\ +{\ +\ func_quote_for_eval "${2}"\ +\ eval "${1}+=\\\\ \\$func_quote_for_eval_result"\ +} # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + # Save a `func_append' function call where possible by direct use of '+=' + sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +else + # Save a `func_append' function call even when '+=' is not available + sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +fi + +if test x"$_lt_function_replace_fail" = x":"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5 +$as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;} +fi + + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" + + ;; + "disable-rpath":C) + sed < libtool > libtool-2 \ + 's/^hardcode_libdir_flag_spec.*$'/'hardcode_libdir_flag_spec=" -D__LIBTOOL_RPATH_SED__ "/' + mv libtool-2 libtool + chmod 755 libtool + libtool="./libtool" + ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + + +echo "copying header files" + +for file in $srcdir/ldns//*.h; do + sh $srcdir/install-sh -m 644 $file ldns/ +done + + + + + diff --git a/configure.ac b/configure.ac new file mode 100644 index 00000000000..500e8e67415 --- /dev/null +++ b/configure.ac @@ -0,0 +1,674 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. +AC_PREREQ(2.56) +sinclude(acx_nlnetlabs.m4) + +# must be numbers. ac_defun because of later processing. +m4_define([VERSION_MAJOR],[1]) +m4_define([VERSION_MINOR],[6]) +m4_define([VERSION_MICRO],[13]) +AC_INIT(ldns, m4_defn([VERSION_MAJOR]).m4_defn([VERSION_MINOR]).m4_defn([VERSION_MICRO]), libdns@nlnetlabs.nl, libdns) +AC_CONFIG_SRCDIR([packet.c]) +# needed to build correct soname +AC_SUBST(LIBTOOL_VERSION_INFO, VERSION_MAJOR:VERSION_MINOR:VERSION_MICRO) +AC_SUBST(LDNS_VERSION_MAJOR, [VERSION_MAJOR]) +AC_SUBST(LDNS_VERSION_MINOR, [VERSION_MINOR]) +AC_SUBST(LDNS_VERSION_MICRO, [VERSION_MICRO]) + +OURCPPFLAGS='' +CPPFLAGS=${CPPFLAGS:-${OURCPPFLAGS}} +CFLAGS="$CFLAGS" + +AC_AIX +# Checks for programs. +AC_PROG_CC +ACX_DEPFLAG +AC_PROG_MAKE_SET + +# Extra (sp)lint flags for NetBSD +AC_CANONICAL_HOST +case "$host_os" in + netbsd*) LINTFLAGS="'-D__RENAME(x)=' -D_NETINET_IN_H_ $LINTFLAGS" + ;; + *) LINTFLAGS="$LINTFLAGS" + ;; +esac +AC_SUBST(LINTFLAGS) + +AC_DEFINE(WINVER, 0x0502, [the version of the windows API enabled]) + +ACX_CHECK_COMPILER_FLAG(std=c99, [C99FLAG="-std=c99"]) +ACX_CHECK_COMPILER_FLAG(xc99, [C99FLAG="-xc99"]) + +# routine to copy files +# argument 1 is a list of files (relative to the source dir) +# argument 2 is a destination directory (relative to the current +# working directory +AC_DEFUN([COPY_FILES], +[ +for file in $1; do + sh $srcdir/install-sh -m 644 $file $2 +done +]) + +# copy all .h files in the dir at argument 1 +# (relative to source) to the dir at argument 2 +# (relative to current dir) +AC_DEFUN([COPY_HEADER_FILES], +[ +echo "copying header files" +COPY_FILES($srcdir/$1/*.h, $2) +]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_LANG_C +ACX_CHECK_COMPILER_FLAG(g, [CFLAGS="-g $CFLAGS"]) +ACX_CHECK_COMPILER_FLAG(O2, [CFLAGS="-O2 $CFLAGS"]) +ACX_CHECK_COMPILER_FLAG(Wall, [CFLAGS="-Wall $CFLAGS"]) +ACX_CHECK_COMPILER_FLAG(W, [CFLAGS="-W $CFLAGS"]) +ACX_CHECK_COMPILER_FLAG(Wwrite-strings, [CFLAGS="-Wwrite-strings $CFLAGS"]) + + +AC_CHECK_HEADERS([getopt.h time.h],,, [AC_INCLUDES_DEFAULT]) + +# MinGW32 tests +AC_CHECK_HEADERS([winsock2.h ws2tcpip.h],,, [AC_INCLUDES_DEFAULT]) +# end mingw32 tests + +ACX_DETERMINE_EXT_FLAGS_UNBOUND + +AC_C_INLINE +AC_CHECK_TYPE(int8_t, char) +AC_CHECK_TYPE(int16_t, short) +AC_CHECK_TYPE(int32_t, int) +AC_CHECK_TYPE(int64_t, long long) +AC_CHECK_TYPE(uint8_t, unsigned char) +AC_CHECK_TYPE(uint16_t, unsigned short) +AC_CHECK_TYPE(uint32_t, unsigned int) +AC_CHECK_TYPE(uint64_t, unsigned long long) + +# my own checks +AC_CHECK_PROG(doxygen, doxygen, doxygen) + +# check to see if libraries are needed for these functions. +AC_SEARCH_LIBS([socket], [socket]) +AC_SEARCH_LIBS([inet_pton], [nsl]) + + +AC_ARG_WITH(drill, AC_HELP_STRING([--with-drill], + [Also build drill.]), + [],[with_drill="no"]) +if test x_$with_drill != x_no ; then + AC_SUBST(DRILL,[drill]) + AC_SUBST(INSTALL_DRILL,[install-drill]) + AC_SUBST(UNINSTALL_DRILL,[uninstall-drill]) + AC_SUBST(CLEAN_DRILL,[clean-drill]) + AC_SUBST(LINT_DRILL,[lint-drill]) + if test -e $srcdir/drill/config.h -o -e drill/config.h ; then + AC_MSG_ERROR([ +A config.h was detected in the drill subdirectory. +This does not work with the --with-drill option. +Please remove the config.h from the drill subdirectory +or do not use the --with-drill option.]) + fi +else + AC_SUBST(DRILL,[""]) + AC_SUBST(INSTALL_DRILL,[""]) + AC_SUBST(UNINSTALL_DRILL,[""]) + AC_SUBST(CLEAN_DRILL,[""]) + AC_SUBST(LINT_DRILL,[""]) +fi + + +AC_ARG_WITH(examples, AC_HELP_STRING([--with-examples], + [Also build examples.]), + [],[with_examples="no"]) +if test x_$with_examples != x_no ; then + AC_SUBST(EXAMPLES,[examples]) + AC_SUBST(INSTALL_EXAMPLES,[install-examples]) + AC_SUBST(UNINSTALL_EXAMPLES,[uninstall-examples]) + AC_SUBST(CLEAN_EXAMPLES,[clean-examples]) + AC_SUBST(LINT_EXAMPLES,[lint-examples]) + if test -e $srcdir/examples/config.h -o -e examples/config.h ; then + AC_MSG_ERROR([ +A config.h was detected in the examples subdirectory. +This does not work with the --with-examples option. +Please remove the config.h from the examples subdirectory +or do not use the --with-examples option.]) + fi +else + AC_SUBST(EXAMPLES,[""]) + AC_SUBST(INSTALL_EXAMPLES,[""]) + AC_SUBST(UNINSTALL_EXAMPLES,[""]) + AC_SUBST(CLEAN_EXAMPLES,[""]) + AC_SUBST(LINT_EXAMPLES,[""]) +fi + +# add option to disable installation of ldns-config script +AC_ARG_ENABLE(ldns-config, [ --disable-ldns-config disable installation of ldns-config (default=enabled)], + enable_ldns_config=$enableval, enable_ldns_config=yes) +if test "x$enable_ldns_config" = xyes; then + AC_SUBST(INSTALL_CONFIG, [install-config]) + AC_SUBST(INSTALL_CONFIG_MANPAGE, [install-config-manpage]) + AC_SUBST(UNINSTALL_CONFIG, [uninstall-config]) + AC_SUBST(UNINSTALL_CONFIG_MANPAGE, [uninstall-config-manpage]) +else + AC_SUBST(INSTALL_CONFIG, [""]) + AC_SUBST(INSTALL_CONFIG_MANPAGE, [""]) + AC_SUBST(UNINSTALL_CONFIG, [""]) + AC_SUBST(UNINSTALL_CONFIG_MANPAGE, [""]) +fi + +# check for python +PYTHON_X_CFLAGS="" +ldns_with_pyldns=no +ldns_with_pyldnsx=no +AC_ARG_WITH(pyldns, AC_HELP_STRING([--with-pyldns], + [generate python library, or --without-pyldns to disable Python support.]), + [],[ withval="no" ]) +ldns_have_python=no +if test x_$withval != x_no; then + sinclude(ax_python_devel.m4) + ac_save_LIBS="$LIBS" dnl otherwise AC_PYTHON_DEVEL thrashes $LIBS + + AX_PYTHON_DEVEL([>= '2.4.0']) + if test ! -z "$ac_python_version"; then + ldns_have_python=yes + fi + + # pass additional Python 3 option to SWIG + if test `$PYTHON -c "import sys; \ + ver = sys.version.split()[[0]]; \ + print(ver >= '3')"` = "True"; then + AC_SUBST(SWIGPY3, ["-py3 -DPY3"]) + fi + + # check for SWIG + if test x_$ldns_have_python != x_no; then + sinclude(ax_pkg_swig.m4) + + # check for >=SWIG-2.0.4 if Python 3.2 used + if test `$PYTHON -c "import sys; \ + ver = sys.version.split()[[0]]; \ + print(ver >= '3.2')"` = "True"; then + AX_PKG_SWIG(2.0.4, [], [AC_MSG_ERROR([SWIG-2.0.4 is required to build pyldns for Python 3.2 and greater.])]) + else + AX_PKG_SWIG + fi + + if test ! -x "$SWIG"; then + AC_MSG_ERROR([failed to find SWIG tool, install it, or do not build pyldns]) + else + AC_DEFINE(HAVE_SWIG,1,[Define if you have SWIG libraries and header files.]) + AC_SUBST(PYLDNS, "pyldns") + AC_SUBST(swig, "$SWIG") + ldns_with_pyldns=yes + fi + else + AC_MSG_RESULT([*** don't have Python, skipping SWIG, no pyldns ***]) # ' + fi + + # xtra cflags for pyldns + if test x_$ldns_have_python != x_no; then + ACX_CHECK_COMPILER_FLAG(fno-strict-aliasing, [PYTHON_X_CFLAGS="-fno-strict-aliasing"]) + ACX_CHECK_COMPILER_FLAG(Wno-missing-field-initializers, [PYTHON_X_CFLAGS="-Wno-missing-field-initializers $PYTHON_X_CFLAGS"]) + ACX_CHECK_COMPILER_FLAG(Wno-unused-parameter, [PYTHON_X_CFLAGS="-Wno-unused-parameter $PYTHON_X_CFLAGS"]) + ACX_CHECK_COMPILER_FLAG(Wno-unused-variable, [PYTHON_X_CFLAGS="-Wno-unused-variable $PYTHON_X_CFLAGS"]) + fi +fi +AC_SUBST(PYTHON_X_CFLAGS) + +# Check for pyldnsx +AC_ARG_WITH(pyldnsx, AC_HELP_STRING([--without-pyldnsx], + [Do not install the ldnsx python module, or --with-pyldnsx to install it.]), + [],[ withval="with_pyldns" ]) +if test x_$withval != x_no; then + if test x_$ldns_with_pyldns != x_no; then + AC_SUBST(PYLDNSX, "pyldnsx") + ldns_with_pyldnsx=yes + else + if test x_$withval != x_with_pyldns; then + AC_MSG_ERROR([--with-pyldns is needed for the ldnsx python module]) + fi + fi +fi + +if test x_$ldns_with_pyldns != x_no; then + AC_SUBST(PYLDNSINST, "install-pyldns")dnl + AC_SUBST(PYLDNSUNINST, "uninstall-pyldns") +else + AC_SUBST(PYLDNSINST, "")dnl + AC_SUBST(PYLDNSUNINST, "") +fi +if test x_$ldns_with_pyldnsx != x_no; then + AC_SUBST(PYLDNSXINST, "install-pyldnsx")dnl + AC_SUBST(PYLDNSXUNINST, "uninstall-pyldnsx") +else + AC_SUBST(PYLDNSXINST, "")dnl + AC_SUBST(PYLDNSXUNINST, "") +fi + + +# Use libtool +ACX_LIBTOOL_C_ONLY + +tmp_CPPFLAGS=$CPPFLAGS +tmp_LDFLAGS=$LDFLAGS +tmp_LIBS=$LIBS + +ACX_WITH_SSL_OPTIONAL + +AC_CHECK_FUNCS([EVP_sha256]) + +# for macosx, see if glibtool exists and use that +# BSD's need to know the version... +#AC_CHECK_PROG(glibtool, glibtool, [glibtool], ) +#AC_CHECK_PROGS(libtool, [libtool15 libtool], [./libtool]) + +AC_ARG_ENABLE(sha2, AC_HELP_STRING([--disable-sha2], [Disable SHA256 and SHA512 RRSIG support])) +case "$enable_sha2" in + no) + ;; + yes|*) + if test "x$HAVE_SSL" != "xyes"; then + AC_MSG_ERROR([SHA2 enabled, but no SSL support]) + fi + AC_MSG_CHECKING(for SHA256 and SHA512) + AC_CHECK_FUNC(SHA256_Init, [], [ + AC_MSG_ERROR([No SHA2 functions found in OpenSSL: please upgrade OpenSSL or rerun with --disable-sha2]) + ]) + AC_DEFINE_UNQUOTED([USE_SHA2], [1], [Define this to enable SHA256 and SHA512 support.]) + ;; +esac + +AC_ARG_ENABLE(gost, AC_HELP_STRING([--disable-gost], [Disable GOST support])) +case "$enable_gost" in + no) + ;; + *) dnl default + if test "x$HAVE_SSL" != "xyes"; then + AC_MSG_ERROR([GOST enabled, but no SSL support]) + fi + AC_MSG_CHECKING(for GOST) + AC_CHECK_FUNC(EVP_PKEY_set_type_str, [],[AC_MSG_ERROR([OpenSSL >= 1.0.0 is needed for GOST support or rerun with --disable-gost])]) + AC_CHECK_FUNC(EC_KEY_new, [], [AC_MSG_ERROR([No ECC functions found in OpenSSL: please upgrade OpenSSL or rerun with --disable-gost])]) + AC_DEFINE_UNQUOTED([USE_GOST], [1], [Define this to enable GOST support.]) + ;; +esac + +AC_ARG_ENABLE(ecdsa, AC_HELP_STRING([--disable-ecdsa], [Disable ECDSA support])) +case "$enable_ecdsa" in + no) + ;; + *) dnl default + if test "x$HAVE_SSL" != "xyes"; then + AC_MSG_ERROR([ECDSA enabled, but no SSL support]) + fi + AC_CHECK_FUNC(ECDSA_sign, [], [AC_MSG_ERROR([OpenSSL does not support ECDSA: please upgrade OpenSSL or rerun with --disable-ecdsa])]) + AC_CHECK_FUNC(SHA384_Init, [], [AC_MSG_ERROR([OpenSSL does not support SHA384: please upgrade OpenSSL or rerun with --disable-ecdsa])]) + AC_CHECK_DECLS([NID_X9_62_prime256v1, NID_secp384r1], [], [AC_MSG_ERROR([OpenSSL does not support the ECDSA curves: please upgrade OpenSSL or rerun with --disable-ecdsa])], [AC_INCLUDES_DEFAULT +#include + ]) + # we now know we have ECDSA and the required curves. + AC_DEFINE_UNQUOTED([USE_ECDSA], [1], [Define this to enable ECDSA support.]) + ;; +esac + +AC_SUBST(LIBSSL_CPPFLAGS) +AC_SUBST(LIBSSL_LDFLAGS) +AC_SUBST(LIBSSL_LIBS) +CPPFLAGS=$tmp_CPPFLAGS +LDFLAGS=$tmp_LDFLAGS +LIBS=$tmp_LIBS + + +# add option to disable the evil rpath +ACX_ARG_RPATH + +#AC_RUN_IFELSE([AC_LANG_SOURCE( +#[ +#int main() +#{ +#short one = 1; +#char *cp = (char*)&one; +#if ( *cp == 0 ) +#return(0); +#else +#return(1); +#} +#])], [],[ +#AC_DEFINE(CONFCHECK_LITTLE_ENDIAN, 1, [system appears to be little-endian]) +#],[]) + +# should define WORDS_BIGENDIAN if the system is big-endian +AC_C_BIGENDIAN + +# Checks for header files. +AC_HEADER_STDC +AC_HEADER_STDBOOL +#AC_HEADER_SYS_WAIT +#AC_CHECK_HEADERS([getopt.h fcntl.h stdlib.h string.h strings.h unistd.h]) +# do the very minimum - we can always extend this +AC_CHECK_HEADERS([getopt.h stdarg.h openssl/ssl.h netinet/in.h time.h arpa/inet.h netdb.h],,, [AC_INCLUDES_DEFAULT]) +AC_CHECK_HEADERS(sys/param.h sys/mount.h,,, +[AC_INCLUDES_DEFAULT + [ + #if HAVE_SYS_PARAM_H + # include + #endif + ] +]) +AC_CHECK_HEADER(sys/socket.h, +[ +include_sys_socket_h='#include ' +AC_DEFINE(HAVE_SYS_SOCKET_H, 1, [define if you have sys/socket.h]) +],[ +include_sys_socket_h='' +],[AC_INCLUDES_DEFAULT + [ + #if HAVE_SYS_PARAM_H + # include + #endif + ] +]) +AC_SUBST(include_sys_socket_h) +AC_CHECK_HEADER(inttypes.h, +[ +include_inttypes_h='#include ' +AC_DEFINE(HAVE_INTTYPES_H, 1, [define if you have inttypes.h]) +AC_SUBST(ldns_build_config_have_inttypes_h, 1) +],[ +include_inttypes_h='' +AC_SUBST(ldns_build_config_have_inttypes_h, 0) +],[AC_INCLUDES_DEFAULT +]) +AC_SUBST(include_inttypes_h) +AC_CHECK_HEADER(sys/types.h, +[ +include_systypes_h='#include ' +AC_DEFINE(HAVE_SYS_TYPES_H, 1, [define if you have sys/types.h]) +],[ +include_systypes_h='' +],[AC_INCLUDES_DEFAULT +]) +AC_SUBST(include_systypes_h) +AC_CHECK_HEADER(unistd.h, +[ +include_unistd_h='#include ' +AC_DEFINE(HAVE_UNISTD_H, 1, [define if you have unistd.h]) +],[ +include_unistd_h='' +],[AC_INCLUDES_DEFAULT +]) +AC_SUBST(include_unistd_h) + +AC_CHECK_SIZEOF(time_t,,[ +AC_INCLUDES_DEFAULT +#ifdef TIME_WITH_SYS_TIME +# include +# include +#else +# ifdef HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif +]) + +if test x_$with_examples != x_no; then +AC_CHECK_HEADERS([pcap.h],, [AC_INCLUDES_DEFAULT]) +AC_CHECK_LIB(pcap, pcap_open_offline, [ + AC_DEFINE([HAVE_LIBPCAP], [1], [Define to 1 if you have the `pcap' library (-lpcap).])dnl` + AC_SUBST([LIBPCAP_LIBS], [-lpcap]) + ], [ + AC_MSG_WARN([Can't find pcap library (needed for ldns-dpa, will not build dpa now.)])dnl' + AC_SUBST([LIBPCAP_LIBS], []) + ] +) +AC_CHECK_HEADERS([netinet/in_systm.h net/if.h netinet/ip.h netinet/udp.h netinet/igmp.h netinet/if_ether.h netinet/ip6.h net/ethernet.h netinet/ip_compat.h],,, [ +AC_INCLUDES_DEFAULT +#ifdef HAVE_NETINET_IN_SYSTM_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif]) +fi + +ACX_TYPE_SOCKLEN_T +AC_TYPE_SIZE_T +AC_TYPE_SSIZE_T +AC_TYPE_INTPTR_T +AC_CHECK_TYPE(in_addr_t, [], [AC_DEFINE([in_addr_t], [uint32_t], [in_addr_t])], [ +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_NETINET_IN_H +# include +#endif]) +AC_CHECK_TYPE(in_port_t, [], [AC_DEFINE([in_port_t], [uint16_t], [in_port_t])], [ +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_NETINET_IN_H +# include +#endif]) +ACX_CHECK_SS_FAMILY + +AC_FUNC_MALLOC +AC_FUNC_REALLOC + +AC_REPLACE_FUNCS(b64_pton) +AC_REPLACE_FUNCS(b64_ntop) +AC_REPLACE_FUNCS(b32_pton) +AC_REPLACE_FUNCS(b32_ntop) +AC_REPLACE_FUNCS(calloc) +AC_REPLACE_FUNCS(timegm) +AC_REPLACE_FUNCS(gmtime_r) +AC_REPLACE_FUNCS(ctime_r) +AC_REPLACE_FUNCS(localtime_r) +AC_REPLACE_FUNCS(isblank) +AC_REPLACE_FUNCS(isascii) +AC_REPLACE_FUNCS(inet_aton) +AC_REPLACE_FUNCS(inet_pton) +AC_REPLACE_FUNCS(inet_ntop) +AC_REPLACE_FUNCS(snprintf) +AC_REPLACE_FUNCS(strlcpy) +AC_REPLACE_FUNCS(memmove) +AC_FUNC_FORK +AC_CHECK_FUNCS([endprotoent endservent sleep random fcntl strtoul bzero memset]) + +ACX_CHECK_GETADDRINFO_WITH_INCLUDES +if test $ac_cv_func_getaddrinfo = no; then + AC_LIBOBJ([fake-rfc2553]) +fi +if test "$USE_WINSOCK" = 1; then + AC_CHECK_TOOL(WINDRES, windres) +fi +ACX_FUNC_IOCTLSOCKET + +#AC_SEARCH_LIBS(RSA_new, [crypto]) + +ACX_CHECK_FORMAT_ATTRIBUTE +ACX_CHECK_UNUSED_ATTRIBUTE + +# check OSX deployment target which is needed +if echo $build_os | grep darwin > /dev/null; then + export MACOSX_DEPLOYMENT_TARGET="10.4" +fi + +AC_DEFINE([SYSCONFDIR], [sysconfdir], [System configuration dir]) + +AH_BOTTOM([ +#include +#include +#include +#include + +#ifndef LITTLE_ENDIAN +#define LITTLE_ENDIAN 1234 +#endif + +#ifndef BIG_ENDIAN +#define BIG_ENDIAN 4321 +#endif + +#ifndef BYTE_ORDER +#ifdef WORDS_BIGENDIAN +#define BYTE_ORDER BIG_ENDIAN +#else +#define BYTE_ORDER LITTLE_ENDIAN +#endif /* WORDS_BIGENDIAN */ +#endif /* BYTE_ORDER */ + +#if STDC_HEADERS +#include +#include +#endif + +#ifdef HAVE_STDINT_H +#include +#endif + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#ifdef HAVE_WINSOCK2_H +#include +#endif + +#ifdef HAVE_WS2TCPIP_H +#include +#endif +] +AHX_CONFIG_W32_FD_SET_T +) + +AH_BOTTOM([ +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef B64_PTON +int ldns_b64_ntop(uint8_t const *src, size_t srclength, + char *target, size_t targsize); +/** + * calculates the size needed to store the result of b64_ntop + */ +/*@unused@*/ +static inline size_t ldns_b64_ntop_calculate_size(size_t srcsize) +{ + return ((((srcsize + 2) / 3) * 4) + 1); +} +#endif /* !B64_PTON */ +#ifndef B64_NTOP +int ldns_b64_pton(char const *src, uint8_t *target, size_t targsize); +/** + * calculates the size needed to store the result of ldns_b64_pton + */ +/*@unused@*/ +static inline size_t ldns_b64_pton_calculate_size(size_t srcsize) +{ + return (((((srcsize + 3) / 4) * 3)) + 1); +} +#endif /* !B64_NTOP */ + +#ifndef HAVE_SLEEP +/* use windows sleep, in millisecs, instead */ +#define sleep(x) Sleep((x)*1000) +#endif + +#ifndef HAVE_RANDOM +#define srandom(x) srand(x) +#define random(x) rand(x) +#endif + +#ifndef HAVE_TIMEGM +#include +time_t timegm (struct tm *tm); +#endif /* !TIMEGM */ +#ifndef HAVE_GMTIME_R +struct tm *gmtime_r(const time_t *timep, struct tm *result); +#endif +#ifndef HAVE_LOCALTIME_R +struct tm *localtime_r(const time_t *timep, struct tm *result); +#endif +#ifndef HAVE_ISBLANK +int isblank(int c); +#endif /* !HAVE_ISBLANK */ +#ifndef HAVE_ISASCII +int isascii(int c); +#endif /* !HAVE_ISASCII */ +#ifndef HAVE_SNPRINTF +#include +int snprintf (char *str, size_t count, const char *fmt, ...); +int vsnprintf (char *str, size_t count, const char *fmt, va_list arg); +#endif /* HAVE_SNPRINTF */ +#ifndef HAVE_INET_PTON +int inet_pton(int af, const char* src, void* dst); +#endif /* HAVE_INET_PTON */ +#ifndef HAVE_INET_NTOP +const char *inet_ntop(int af, const void *src, char *dst, size_t size); +#endif +#ifndef HAVE_INET_ATON +int inet_aton(const char *cp, struct in_addr *addr); +#endif +#ifndef HAVE_MEMMOVE +void *memmove(void *dest, const void *src, size_t n); +#endif +#ifndef HAVE_STRLCPY +size_t strlcpy(char *dst, const char *src, size_t siz); +#endif +#ifdef __cplusplus +} +#endif +#ifndef HAVE_GETADDRINFO +#include "compat/fake-rfc2553.h" +#endif +#ifndef HAVE_STRTOUL +#define strtoul (unsigned long)strtol +#endif +]) + +if test "x$HAVE_SSL" = "xyes"; then + AC_SUBST(ldns_build_config_have_ssl, 1) +else + AC_SUBST(ldns_build_config_have_ssl, 0) +fi +if test "x$ac_cv_c_format_attribute" = "xyes"; then + AC_SUBST(ldns_build_config_have_attr_format, 1) +else + AC_SUBST(ldns_build_config_have_attr_format, 0) +fi +if test "x$ac_cv_c_unused_attribute" = "xyes"; then + AC_SUBST(ldns_build_config_have_attr_unused, 1) +else + AC_SUBST(ldns_build_config_have_attr_unused, 0) +fi + +AC_CONFIG_FILES([Makefile ldns/common.h ldns/net.h ldns/util.h packaging/libldns.pc packaging/ldns-config]) + +AC_CONFIG_HEADER([ldns/config.h]) +AC_OUTPUT +COPY_HEADER_FILES(ldns/, ldns/) + +dnl AC_CONFIG_SUBDIRS([drill]) + + diff --git a/contrib/NETLDNS.readme.txt b/contrib/NETLDNS.readme.txt new file mode 100644 index 00000000000..29069b6a3c0 --- /dev/null +++ b/contrib/NETLDNS.readme.txt @@ -0,0 +1,10 @@ +NETLDNS is a functionality port of NLnet Labs' LDNS to the .NET +2.0 framework, contributed by Alex Nicoll of the Carnegie Mellon +University Software Engineering Institute. NETLDNS is released +under the BSD license. NETLDNS uses Mihnea Radulescu's BigInteger +Library (http://www.codeproject.com/KB/cs/BigInteger_Library.aspx) +from CodeProject to help with key manipulation. Please contact Alex at +anicoll@cert.org with inquiries or requests for newer versions. + +This project is not supported by NLnet Labs. + diff --git a/contrib/NETLDNS.tar.gz b/contrib/NETLDNS.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..b9d51a1d664d89773b0b107d63fb6bfddcefba5c GIT binary patch literal 54578 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 + +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 Xelerance 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. diff --git a/contrib/ldnsx/Makefile b/contrib/ldnsx/Makefile new file mode 100644 index 00000000000..92e70ce3cf9 --- /dev/null +++ b/contrib/ldnsx/Makefile @@ -0,0 +1,89 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = build + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source + +.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + -rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/ldnsx.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/ldnsx.qhc" + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ + "run these through (pdf)latex." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." diff --git a/contrib/ldnsx/README b/contrib/ldnsx/README new file mode 100644 index 00000000000..66f89d2df42 --- /dev/null +++ b/contrib/ldnsx/README @@ -0,0 +1,36 @@ +LDNSX: Easy DNS (including DNSSEC) via ldns. + +ldns is a great library. It is a powerfull tool for +working with DNS. python-ldns it is a straight up clone of the C +interface, howver that is not a very good interface for python. Its +documentation is incomplete and some functions don't work as +described. And some objects don't have a full python API. + +ldnsx aims to fix this. It wraps around the ldns python bindings, +working around its limitations and providing a well-documented, more +pythonistic interface. + +Written by Christopher Olah + +Examples +======== + +Query the default resolver for google.com's A records. Print the response +packet. + +>>> import ldnsx +>>> resolver = ldnsx.resolver() +>>> print resolver.query("google.com","A") + +Print the NS records for com. from f.root-servers.net if we get a +response, else an error message. + +>>> import ldnsx +>>> pkt = ldnsx.resolver("f.root-servers.net").query("com.","NS") +>>> if pkt: +>>> for rr in pkt.answer(): +>>> print rr +>>> else: +>>> print "response not received" + + diff --git a/contrib/ldnsx/examples/ldnsx-axfr.py b/contrib/ldnsx/examples/ldnsx-axfr.py new file mode 100644 index 00000000000..224bb572754 --- /dev/null +++ b/contrib/ldnsx/examples/ldnsx-axfr.py @@ -0,0 +1,30 @@ +#!/usr/bin/python +# vim:fileencoding=utf-8 +# +# AXFR client with IDN (Internationalized Domain Names) support +# + +import ldns +import encodings.idna + +def utf2name(name): + return '.'.join([encodings.idna.ToASCII(a) for a in name.split('.')]) +def name2utf(name): + return '.'.join([encodings.idna.ToUnicode(a) for a in name.split('.')]) + +resolver = ldnsx.resolver("zone.nic.cz") + +#Print results +for rr in resolver.AXFR(utf2name(u"háčkyčárky.cz")): + # rdf = rr.owner() + # if (rdf.get_type() == ldns.LDNS_RDF_TYPE_DNAME): + # print "RDF owner: type=",rr.type(),"data=",name2utf(rr.owner()) + # else: + # print "RDF owner: type=",rdf.get_type_str(),"data=",str(rdf) + # print " RR type=", rr.get_type_str()," ttl=",rr.ttl() + # for rdf in rr.rdfs(): + # if (rdf.get_type() == ldns.LDNS_RDF_TYPE_DNAME): + # print " RDF: type=",rdf.get_type_str(),"data=",name2utf(str(rdf)) + # else: + # print " RDF: type=",rdf.get_type_str(),"data=",str(rdf) + diff --git a/contrib/ldnsx/examples/ldnsx-dnssec.py b/contrib/ldnsx/examples/ldnsx-dnssec.py new file mode 100644 index 00000000000..c28ad5ccd0f --- /dev/null +++ b/contrib/ldnsx/examples/ldnsx-dnssec.py @@ -0,0 +1,39 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +import ldnsx +import sys + +debug = True + +if len(sys.argv) < 2: + print "Usage:", sys.argv[0], "domain [resolver_addr]" + sys.exit(1) + +name = sys.argv[1] + +# Create resolver +resolver = ldnsx.resolver(dnssec=True) + +# Custom resolver +if len(sys.argv) > 2: + # Clear previous nameservers + resolver.set_nameservers(sys.argv[2:]) + +# Resolve DNS name +pkt = resolver.query(name, "A") + +if pkt and pkt.answer(): + + # Debug + if debug: + print "NS returned:", pkt.rcode(), "(AA: %d AD: %d)" % ( "AA" in pkt.flags(), "AD" in pkt.flags() ) + + # SERVFAIL indicated bogus name + if pkt.rcode() == "SERVFAIL": + print name, "failed to resolve" + + # Check AD (Authenticated) bit + if pkt.rcode() == "NOERROR": + if "AD" in pkt.flags(): print name, "is secure" + else: print name, "is insecure" + diff --git a/contrib/ldnsx/examples/ldnsx-mx1.py b/contrib/ldnsx/examples/ldnsx-mx1.py new file mode 100644 index 00000000000..60dfc426bb9 --- /dev/null +++ b/contrib/ldnsx/examples/ldnsx-mx1.py @@ -0,0 +1,11 @@ +import ldnsx + +resolver = ldnsx.resolver() + +pkt = resolver.query("nic.cz", "MX") + +if (pkt): + mx = pkt.answer() + if (mx): + mx.sort() + print mx diff --git a/contrib/ldnsx/examples/ldnsx-mx2.py b/contrib/ldnsx/examples/ldnsx-mx2.py new file mode 100644 index 00000000000..8bee67ff3b7 --- /dev/null +++ b/contrib/ldnsx/examples/ldnsx-mx2.py @@ -0,0 +1,17 @@ +#!/usr/bin/python +# +# MX is a small program that prints out the mx records for a particular domain +# +import ldnsx + +resolver = ldnsx.resolver() + +pkt = resolver.query("nic.cz", "MX") +if pkt: + for rr in pkt.answer(rr_type = "MX"): + rdf = rr.owner() + print rr + #Could also do: + #print rr[0], rr[1], rr[2], rr[3], " ".join(rr[4:]) + #print rr.owner(), rr.ttl(), rr.rr_clas(), rr.rr_type(), " ".join(rr[4:]) + diff --git a/contrib/ldnsx/examples/ldnsx-walk.py b/contrib/ldnsx/examples/ldnsx-walk.py new file mode 100755 index 00000000000..98109390799 --- /dev/null +++ b/contrib/ldnsx/examples/ldnsx-walk.py @@ -0,0 +1,25 @@ +#!/usr/bin/python +# vim:fileencoding=utf-8 +# +# Walk a domain that's using NSEC and print in zonefile format. + +import sys +import ldnsx + +def walk(domain): + res = ldnsx.resolver("193.110.157.136", dnssec=True) + pkt = res.query(domain, 666) + try: + nsec_rr = pkt.authority(rr_type="NSEC")[0] + except: + print "no NSEC found, domain is not signed or using NSEC3" + sys.exit() + for rr_type in nsec_rr[5].split(' ')[:-1]: + for rr in ldnsx.get_rrs(domain, rr_type): + print str(rr)[:-1] + next_rec = nsec_rr[4] + if (next_rec != domain) and (next_rec[-len(domain):] == domain): + walk(next_rec) + +walk("xelerance.com") + diff --git a/contrib/ldnsx/ldnsx.py b/contrib/ldnsx/ldnsx.py new file mode 100644 index 00000000000..ee81b2fdaab --- /dev/null +++ b/contrib/ldnsx/ldnsx.py @@ -0,0 +1,916 @@ +# Copyright (C) Xelerance Corp. . +# Author: Christopher Olah +# License: BSD + +""" Easy DNS (including DNSSEC) via ldns. + +ldns is a great library. It is a powerfull tool for +working with DNS. python-ldns it is a straight up clone of the C +interface, howver that is not a very good interface for python. Its +documentation is incomplete and some functions don't work as +described. And some objects don't have a full python API. + +ldnsx aims to fix this. It wraps around the ldns python bindings, +working around its limitations and providing a well-documented, more +pythonistic interface. + +**WARNING:** + +**API subject to change.** No backwards compatibility guarantee. Write software using this version at your own risk! + +Examples +-------- + +Query the default resolver for google.com's A records. Print the response +packet. + +>>> import ldnsx +>>> resolver = ldnsx.resolver() +>>> print resolver.query("google.com","A") + + +Print the root NS records from f.root-servers.net; if we get a +response, else an error message. + +>>> import ldnsx +>>> pkt = ldnsx.resolver("f.root-servers.net").query(".", "NS") +>>> if pkt: +>>> for rr in pkt.answer(): +>>> print rr +>>> else: +>>> print "response not received" + +""" + +import time, sys, calendar, warnings, socket +try: + import ldns +except ImportError: + print >> sys.stderr, "ldnsx requires the ldns-python sub-package from http://www.nlnetlabs.nl/projects/ldns/" + print >> sys.stderr, "Fedora/CentOS: yum install ldns-python" + print >> sys.stderr, "Debian/Ubuntu: apt-get install python-ldns" + print >> sys.stderr, "openSUSE: zypper in python-ldns" + sys.exit(1) + +__version__ = "0.1" + +def isValidIP(ipaddr): + try: + v4 = socket.inet_pton(socket.AF_INET,ipaddr) + return 4 + except: + try: + v6 = socket.inet_pton(socket.AF_INET6,ipaddr) + return 6 + except: + return 0 + +def query(name, rr_type, rr_class="IN", flags=["RD"], tries = 3, res=None): + """Convenience function. Creates a resolver and then queries it. Refer to resolver.query() + * name -- domain to query for + * rr_type -- rr_type to query for + * flags -- flags for query (list of strings) + * tries -- number of times to retry the query on failure + * res -- configurations for the resolver as a dict -- see resolver() + """ + if isinstance(res, list) or isinstance(res, tuple): + res = resolver(*res) + elif isinstance(res, dict): + res = resolver(**res) + else: + res = resolver(res) + return res.query(name, rr_type, rr_class, flags, tries) + +def get_rrs(name, rr_type, rr_class="IN", tries = 3, strict = False, res=None, **kwds): + """Convenience function. Gets RRs for name of type rr_type trying tries times. + If strict, it raises and exception on failure, otherwise it returns []. + * name -- domain to query for + * rr_type -- rr_type to query for + * flags -- flags for query (list of strings) + * tries -- number of times to retry the query on failure + * strict -- if the query fails, do we return [] or raise an exception? + * res -- configurations for the resolver as a dict -- see resolver() + * kwds -- query filters, refer to packet.answer() + """ + if isinstance(res, list) or isinstance(res, tuple): + res = resolver(*res) + elif isinstance(res, dict): + res = resolver(**res) + else: + res = resolver(res) + if "|" in rr_type: + pkt = res.query(name, "ANY", rr_class=rr_class, tries=tries) + else: + pkt = res.query(name, rr_type, rr_class=rr_class, tries=tries) + if pkt: + if rr_type in ["", "ANY", "*"]: + return pkt.answer( **kwds) + else: + return pkt.answer(rr_type=rr_type, **kwds) + else: + if strict: + raise Exception("LDNS couldn't complete query") + else: + return [] + +def secure_query(name, rr_type, rr_class="IN", flags=["RD"], tries = 1, flex=False, res=None): + """Convenience function. Creates a resolver and then does a DNSSEC query. Refer to resolver.query() + * name -- domain to query for + * rr_type -- rr_type to query for + * flags -- flags for query (list of strings) + * tries -- number of times to retry the query on failure + * flex -- if we can't verify data, exception or warning? + * res -- configurations for the resolver as a dict -- see resolver()""" + if isinstance(res, list) or isinstance(res, tuple): + res = resolver(*res) + elif isinstance(res, dict): + res = resolver(**res) + else: + res = resolver(res) + pkt = res.query(name, rr_type, rr_class, flags, tries) + if pkt.rcode() == "SERVFAIL": + raise Exception("%s lookup failed (server error or dnssec validation failed)" % name) + if pkt.rcode() == "NXDOMAIN": + if "AD" in pkt.flags(): + raise Exception("%s lookup failed (non-existence proven by DNSSEC)" % hostname ) + else: + raise Exception("%s lookup failed" % hostname ) + if pkt.rcode() == "NOERROR": + if "AD" not in pkt.flags(): + if not flex: + raise Exception("DNS lookup was insecure") + else: + warnings.warn("DNS lookup was insecure") + return pkt + else: + raise Exception("unknown ldns error, %s" % pkt.rcode()) + + + +class resolver: + """ A wrapper around ldns.ldns_resolver. + + **Examples** + + Making resolvers is easy! + + >>> from ldnsx import resolver + >>> resolver() # from /etc/resolv.conf + + >>> resolver("") # resolver with no nameservers + + >>> resolver("193.110.157.135") #resolver pointing to ip addr + + >>> resolver("f.root-servers.net") # resolver pointing ip address(es) resolved from name + + >>> resolver("193.110.157.135, 193.110.157.136") + >>> # resolver pointing to multiple ip addr, first takes precedence. + + + So is playing around with their nameservers! + + >>> import ldnsx + >>> res = ldnsx.resolver("192.168.1.1") + >>> res.add_nameserver("192.168.1.2") + >>> res.add_nameserver("192.168.1.3") + >>> res.nameservers_ip() + ["192.168.1.1","192.168.1.2","192.168.1.3"] + + And querying! + + >>> from ldnsx import resolver + >>> res= resolver() + >>> res.query("cow.com","A") + ;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 7663 + ;; flags: qr rd ra ; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 + ;; QUESTION SECTION: + ;; cow.com. IN A + ;; ANSWER SECTION: + cow.com. 300 IN A 208.87.34.18 + ;; AUTHORITY SECTION: + ;; ADDITIONAL SECTION: + ;; Query time: 313 msec + ;; SERVER: 192.168.111.9 + ;; WHEN: Fri Jun 3 11:01:02 2011 + ;; MSG SIZE rcvd: 41 + + + """ + + def __init__(self, ns = None, dnssec = False, tcp = False, port = 53): + """resolver constructor + + * ns -- the nameserver/comma delimited nameserver list + defaults to settings from /etc/resolv.conf + * dnssec -- should the resolver try and use dnssec or not? + * tcp -- should the resolver use TCP + 'auto' is a depricated work around for old ldns problems + * port -- the port to use, must be the same for all nameservers + + """ + # We construct based on a file and dump the nameservers rather than using + # ldns_resolver_new() to avoid environment/configuration/magic specific + # bugs. + self._ldns_resolver = ldns.ldns_resolver.new_frm_file("/etc/resolv.conf") + if ns != None: + self.drop_nameservers() + nm_list = ns.split(',') + nm_list = map(lambda s: s.strip(), nm_list) + nm_list = filter(lambda s: s != "", nm_list) + nm_list.reverse() + for nm in nm_list: + self.add_nameserver(nm) + # Configure DNSSEC, tcp and port + self.set_dnssec(dnssec) + if tcp == 'auto': + self.autotcp = True + self._ldns_resolver.set_usevc(False) + else: + self.autotcp = False + self._ldns_resolver.set_usevc(tcp) + self._ldns_resolver.set_port(port) + + + def query(self, name, rr_type, rr_class="IN", flags=["RD"], tries = 3): + """Run a query on the resolver. + + * name -- name to query for + * rr_type -- the record type to query for + * rr_class -- the class to query for, defaults to IN (Internet) + * flags -- the flags to send the query with + * tries -- the number of times to attempt to acheive query in case of packet loss, etc + + **Examples** + + Let's get some A records! + + >>> google_a_records = resolver.query("google.com","A").answer() + + Using DNSSEC is easy :) + + >>> dnssec_pkt = ldnsx.resolver(dnssec=True).query("xelerance.com") + + We let you use strings to make things easy, but if you prefer stay close to DNS... + + >>> AAAA = 28 + >>> resolver.query("ipv6.google.com", AAAA) + + **More about rr_type** + + rr_type must be a supported resource record type. There are a large number of RR types: + + =========== =================================== ================== + TYPE Value and meaning Reference + =========== =================================== ================== + A 1 a host address [RFC1035] + NS 2 an authoritative name server [RFC1035] + ... + AAAA 28 IP6 Address [RFC3596] + ... + DS 43 Delegation Signer [RFC4034][RFC3658] + ... + DNSKEY 48 DNSKEY [RFC4034][RFC3755] + ... + Unassigned 32770-65279 + Private use 65280-65534 + Reserved 65535 + =========== =================================== ================== + + (From http://www.iana.org/assignments/dns-parameters) + + RR types are given as a string (eg. "A"). In the case of Unassigned/Private use/Reserved ones, + they are given as "TYPEXXXXX" where XXXXX is the number. ie. RR type 65280 is "TYPE65280". You + may also pass the integer, but you always be given the string. + + If the version of ldnsx you are using is old, it is possible that there could be new rr_types that + we don't recognise mnemonic for. You can still use the number XXX or the string "TYPEXXX". To + determine what rr_type menmonics we support, please refer to resolver.supported_rr_types() + + """ + # Determine rr_type int + if rr_type in _rr_types.keys(): + _rr_type = _rr_types[rr_type] + elif isinstance(rr_type,int): + _rr_type = rr_type + elif isinstance(rr_type,str) and rr_type[0:4] == "TYPE": + try: + _rr_type = int(rr_type[4:]) + except: + raise Exception("%s is a bad RR type. TYPEXXXX: XXXX must be a number") + else: + raise Exception("ldnsx (version %s) does not support the RR type %s." % (__version__, str(rr_type)) ) + # Determine rr_class int + if rr_class == "IN": _rr_class = ldns.LDNS_RR_CLASS_IN + elif rr_class == "CH": _rr_class = ldns.LDNS_RR_CLASS_CH + elif rr_class == "HS": _rr_class = ldns.LDNS_RR_CLASS_HS + else: + raise Exception("ldnsx (version %s) does not support the RR class %s." % (__version__, str(rr_class)) ) + # Determine flags int + _flags = 0 + if "QR" in flags: _flags |= ldns.LDNS_QR + if "AA" in flags: _flags |= ldns.LDNS_AA + if "TC" in flags: _flags |= ldns.LDNS_TC + if "RD" in flags: _flags |= ldns.LDNS_RD + if "CD" in flags: _flags |= ldns.LDNS_CD + if "RA" in flags: _flags |= ldns.LDNS_RA + if "AD" in flags: _flags |= ldns.LDNS_AD + # Query + if tries == 0: return None + try: + pkt = self._ldns_resolver.query(name, _rr_type, _rr_class, _flags) + except KeyboardInterrupt: #Since so much time is spent waiting on ldns, this is very common place for Ctr-C to fall + raise + except: #Since the ldns exceptiion is not very descriptive... + raise Exception("ldns backend ran into problems. Likely, the name you were querying for, %s, was invalid." % name) + #Deal with failed queries + if not pkt: + if tries <= 1: + return None + else: + # One of the major causes of none-packets is truncation of packets + # When autotcp is set, we are in a flexible enough position to try and use tcp + # to get around this. + # Either way, we want to replace the resolver, since resolvers will sometimes + # just freeze up. + if self.autotcp: + self = resolver( ",".join(self.nameservers_ip()),tcp=True, dnssec = self._ldns_resolver.dnssec()) + self.autotcp = True + pkt = self.query(name, rr_type, rr_class=rr_class, flags=flags, tries = tries-1) + self._ldns_resolver.set_usevc(False) + return pkt + else: + self = resolver( ",".join(self.nameservers_ip()), tcp = self._ldns_resolver.usevc(), dnssec = self._ldns_resolver.dnssec() ) + time.sleep(1) # It could be that things are failing because of a brief outage + return self.query(name, rr_type, rr_class=rr_class, flags=flags, tries = tries-1) + elif self.autotcp: + pkt = packet(pkt) + if "TC" in pkt.flags(): + self._ldns_resolver.set_usevc(True) + pkt2 = self.query(name, rr_type, rr_class=rr_class, flags=flags, tries = tries-1) + self._ldns_resolver.set_usevc(False) + if pkt2: return packet(pkt2) + return pkt + return packet(pkt) + #ret = [] + #for rr in pkt.answer().rrs(): + # ret.append([str(rr.owner()),rr.ttl(),rr.get_class_str(),rr.get_type_str()]+[str(rdf) for rdf in rr.rdfs()]) + #return ret + + def suported_rr_types(self): + """ Returns the supported DNS resource record types. + + Refer to resolver.query() for thorough documentation of resource + record types or refer to: + + http://www.iana.org/assignments/dns-parameters + + """ + return _rr_types.keys() + + def AXFR(self,name): + """AXFR for name + + * name -- name to AXFR for + + This function is a generator. As it AXFRs it will yield you the records. + + **Example** + + Let's get a list of the tlds (gotta catch em all!): + + >>> tlds = [] + >>> for rr in resolver("f.root-servers.net").AXFR("."): + >>> if rr.rr_type() == "NS": + >>> tlds.append(rr.owner()) + + """ + #Dname seems to be unecessary on some computers, but it is on others. Avoid bugs. + if self._ldns_resolver.axfr_start(ldns.ldns_dname(name), ldns.LDNS_RR_CLASS_IN) != ldns.LDNS_STATUS_OK: + raise Exception("Starting AXFR failed. Error: %s" % ldns.ldns_get_errorstr_by_id(status)) + pres = self._ldns_resolver.axfr_next() + while pres: + yield resource_record(pres) + pres = self._ldns_resolver.axfr_next() + + def nameservers_ip(self): + """ returns a list of the resolvers nameservers (as IP addr) + + """ + nm_stack2 =[] + nm_str_stack2=[] + nm = self._ldns_resolver.pop_nameserver() + while nm: + nm_stack2.append(nm) + nm_str_stack2.append(str(nm)) + nm = self._ldns_resolver.pop_nameserver() + for nm in nm_stack2: + self._ldns_resolver.push_nameserver(nm) + nm_str_stack2.reverse() + return nm_str_stack2 + + + def add_nameserver(self,ns): + """ Add a nameserver, IPv4/IPv6/name. + + """ + if isValidIP(ns) == 4: + address = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_A,ns) + self._ldns_resolver.push_nameserver(address) + elif isValidIP(ns) == 6: + address = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_AAAA,ns) + self._ldns_resolver.push_nameserver(address) + else: + resolver = ldns.ldns_resolver.new_frm_file("/etc/resolv.conf") + #address = resolver.get_addr_by_name(ns) + address = resolver.get_addr_by_name(ldns.ldns_dname(ns)) + if not address: + address = resolver.get_addr_by_name(ldns.ldns_dname(ns)) + if not address: + raise Exception("Failed to resolve address for %s" % ns) + for rr in address.rrs(): + self._ldns_resolver.push_nameserver_rr(rr) + + def drop_nameservers(self): + """Drops all nameservers. + This function causes the resolver to forget all nameservers. + + """ + while self._ldns_resolver.pop_nameserver(): + pass + + def set_nameservers(self, nm_list): + """Takes a list of nameservers and sets the resolver to use them + + """ + self.drop_nameservers() + for nm in nm_list: + self.add_nameserver(nm) + + def __repr__(self): + return "" % ", ".join(self.nameservers_ip()) + __str__ = __repr__ + + def set_dnssec(self,new_dnssec_status): + """Set whether the resolver uses DNSSEC. + + """ + self._ldns_resolver.set_dnssec(new_dnssec_status) + +class packet: + + def _construct_rr_filter(self, **kwds): + def match(pattern, target): + if pattern[0] in ["<",">","!"]: + rel = pattern[0] + pattern=pattern[1:] + elif pattern[0:2] in ["<=","=>"]: + rel = pattern[0:2] + pattern=pattern[2:] + else: + rel = "=" + for val in pattern.split("|"): + if {"<" : target < val, + ">" : target > val, + "!" : target != val, + "=" : target == val, + ">=": target >= val, + "<=": target <= val}[rel]: + return True + return False + def f(rr): + for key in kwds.keys(): + if ( ( isinstance(kwds[key], list) and str(rr[key]) not in map(str,kwds[key]) ) + or ( not isinstance(kwds[key], list) and not match(str(kwds[key]), str(rr[key])))): + return False + return True + return f + + def __init__(self, pkt): + self._ldns_pkt = pkt + + def __repr__(self): + return str(self._ldns_pkt) + __str__ = __repr__ + + def rcode(self): + """Returns the rcode. + + Example returned value: "NOERROR" + + possilbe rcodes (via ldns): "FORMERR", "MASK", "NOERROR", + "NOTAUTH", "NOTIMPL", "NOTZONE", "NXDOMAIN", + "NXRSET", "REFUSED", "SERVFAIL", "SHIFT", + "YXDOMAIN", "YXRRSET" + + Refer to http://www.iana.org/assignments/dns-parameters + section: DNS RCODEs + """ + return self._ldns_pkt.rcode2str() + + def opcode(self): + """Returns the rcode. + + Example returned value: "QUERY" + + """ + return self._ldns_pkt.opcode2str() + + def flags(self): + """Return packet flags (as list of strings). + + Example returned value: ['QR', 'RA', 'RD'] + + **What are the flags?** + + ======== ==== ===================== ========= + Bit Flag Description Reference + ======== ==== ===================== ========= + bit 5 AA Authoritative Answer [RFC1035] + bit 6 TC Truncated Response [RFC1035] + bit 7 RD Recursion Desired [RFC1035] + bit 8 RA Recursion Allowed [RFC1035] + bit 9 Reserved + bit 10 AD Authentic Data [RFC4035] + bit 11 CD Checking Disabled [RFC4035] + ======== ==== ===================== ========= + + (from http://www.iana.org/assignments/dns-parameters) + + There is also QR. It is mentioned in other sources, + though not the above page. It being false means that + the packet is a query, it being true means that it is + a response. + + """ + ret = [] + if self._ldns_pkt.aa(): ret += ["AA"] + if self._ldns_pkt.ad(): ret += ["AD"] + if self._ldns_pkt.cd(): ret += ["CD"] + if self._ldns_pkt.qr(): ret += ["QR"] + if self._ldns_pkt.ra(): ret += ["RA"] + if self._ldns_pkt.rd(): ret += ["RD"] + if self._ldns_pkt.tc(): ret += ["TC"] + return ret + + def answer(self, **filters): + """Returns the answer section. + + * filters -- a filtering mechanism + + Since a very common desire is to filter the resource records in a packet + section, we provide a special tool for doing this: filters. They are a + lot like regular python filters, but more convenient. If you set a + field equal to some value, you will only receive resource records for which + it holds true. + + **Examples** + + >>> res = ldnsx.resolver() + >>> pkt = res.query("google.ca","A") + >>> pkt.answer() + [google.ca. 28 IN A 74.125.91.99 + , google.ca. 28 IN A 74.125.91.105 + , google.ca. 28 IN A 74.125.91.147 + , google.ca. 28 IN A 74.125.91.103 + , google.ca. 28 IN A 74.125.91.104 + , google.ca. 28 IN A 74.125.91.106 + ] + + To understand filters, consider the following: + + >>> pkt = ldnsx.query("cow.com","ANY") + >>> pkt.answer() + [cow.com. 276 IN A 208.87.32.75 + , cow.com. 3576 IN NS sell.internettraffic.com. + , cow.com. 3576 IN NS buy.internettraffic.com. + , cow.com. 3576 IN SOA buy.internettraffic.com. hostmaster.hostingnet.com. 1308785320 10800 3600 604800 3600 + ] + >>> pkt.answer(rr_type="A") + [cow.com. 276 IN A 208.87.32.75 + ] + >>> pkt.answer(rr_type="A|NS") + [cow.com. 276 IN A 208.87.32.75 + , cow.com. 3576 IN NS sell.internettraffic.com. + , cow.com. 3576 IN NS buy.internettraffic.com. + ] + >>> pkt.answer(rr_type="!NS") + [cow.com. 276 IN A 208.87.32.75 + , cow.com. 3576 IN SOA buy.internettraffic.com. hostmaster.hostingnet.com. 1308785320 10800 3600 604800 3600 + ] + + fields are the same as when indexing a resource record. + note: ordering is alphabetical. + """ + ret = [resource_record(rr) for rr in self._ldns_pkt.answer().rrs()] + return filter(self._construct_rr_filter(**filters), ret) + + def authority(self, **filters): + """Returns the authority section. + + * filters -- a filtering mechanism + + Since a very common desire is to filter the resource records in a packet + section, we provide a special tool for doing this: filters. They are a + lot like regular python filters, but more convenient. If you set a + field equal to some value, you will only receive resource records for which + it holds true. See answer() for details. + + **Examples** + + >>> res = ldnsx.resolver() + >>> pkt = res.query("google.ca","A") + >>> pkt.authority() + [google.ca. 251090 IN NS ns3.google.com. + , google.ca. 251090 IN NS ns1.google.com. + , google.ca. 251090 IN NS ns2.google.com. + , google.ca. 251090 IN NS ns4.google.com. + ] + + """ + ret = [resource_record(rr) for rr in self._ldns_pkt.authority().rrs()] + return filter(self._construct_rr_filter(**filters), ret) + + def additional(self, **filters): + """Returns the additional section. + + * filters -- a filtering mechanism + + Since a very common desire is to filter the resource records in a packet + section, we provide a special tool for doing this: filters. They are a + lot like regular python filters, but more convenient. If you set a + field equal to some value, you will only receive resource records for which + it holds true. See answer() for details. + + **Examples** + + >>> res = ldnsx.resolver() + >>> pkt = res.query("google.ca","A") + >>> pkt.additional() + [ns3.google.com. 268778 IN A 216.239.36.10 + , ns1.google.com. 262925 IN A 216.239.32.10 + , ns2.google.com. 255659 IN A 216.239.34.10 + , ns4.google.com. 264489 IN A 216.239.38.10 + ] + + """ + ret = [resource_record(rr) for rr in self._ldns_pkt.additional().rrs()] + return filter(self._construct_rr_filter(**filters), ret) + + def question(self, **filters): + """Returns the question section. + + * filters -- a filtering mechanism + + Since a very common desire is to filter the resource records in a packet + section, we provide a special tool for doing this: filters. They are a + lot like regular python filters, but more convenient. If you set a + field equal to some value, you will only receive resource records for which + it holds true. See answer() for details. + + """ + ret = [resource_record(rr) for rr in self._ldns_pkt.question().rrs()] + return filter(self._construct_rr_filter(**filters), ret) + +class resource_record: + + _rdfs = None + _iter_pos = None + + def __init__(self, rr): + self._ldns_rr = rr + self._rdfs = [str(rr.owner()),rr.ttl(),rr.get_class_str(),rr.get_type_str()]+[str(rdf) for rdf in rr.rdfs()] + + def __repr__(self): + return str(self._ldns_rr) + + __str__ = __repr__ + + def __iter__(self): + self._iter_pos = 0 + return self + + def next(self): + if self._iter_pos < len(self._rdfs): + self._iter_pos += 1 + return self._rdfs[self._iter_pos-1] + else: + raise StopIteration + + def __len__(self): + try: + return len(_rdfs) + except: + return 0 + + def __getitem__(self, n): + if isinstance(n, int): + return self._rdfs[n] + elif isinstance(n, str): + n = n.lower() + if n in ["owner"]: + return self.owner() + elif n in ["rr_type", "rr type", "type"]: + return self.rr_type() + elif n in ["rr_class", "rr class", "class"]: + return self.rr_class() + elif n in ["covered_type", "covered type", "type2"]: + return self.covered_type() + elif n in ["ttl"]: + return self.ttl() + elif n in ["ip"]: + return self.ip() + elif n in ["alg", "algorithm"]: + return self.alg() + elif n in ["protocol"]: + return self.protocol() + elif n in ["flags"]: + return self.flags() + else: + raise Exception("ldnsx (version %s) does not recognize the rr field %s" % (__version__,n) ) + else: + raise TypeError("bad type %s for index resource record" % type(n) ) + + + #def rdfs(self): + # return self._rdfs.clone() + + def owner(self): + """Get the RR's owner""" + return str(self._ldns_rr.owner()) + + def rr_type(self): + """Get a RR's type """ + return self._ldns_rr.get_type_str() + + def covered_type(self): + """Get an RRSIG RR's covered type""" + if self.rr_type() == "RRSIG": + return self[4] + else: + return "" + + def rr_class(self): + """Get the RR's collapse""" + return self._ldns_rr.get_class_str() + + def ttl(self): + """Get the RR's TTL""" + return self._ldns_rr.ttl() + + def inception(self, out_format="UTC"): + """returns the inception time in format out_format, defaulting to a UTC string. + options for out_format are: + + UTC -- a UTC string eg. 20110712192610 (2011/07/12 19:26:10) + unix -- number of seconds since the epoch, Jan 1, 1970 + struct_time -- the format used by python's time library + """ + # Something very strange is going on with inception/expiration dates in DNS. + # According to RFC 4034 section 3.1.5 (http://tools.ietf.org/html/rfc4034#page-9) + # the inception/expiration fields should be in seconds since Jan 1, 1970, the Unix + # epoch (as is standard in unix). Yet all the packets I've seen provide UTC encoded + # as a string instead, eg. "20110712192610" which is 2011/07/12 19:26:10. + # + # It turns out that this is a standard thing that ldns is doing before the data gets + # to us. + if self.rr_type() == "RRSIG": + if out_format.lower() in ["utc", "utc str", "utc_str"]: + return self[9] + elif out_format.lower() in ["unix", "posix", "ctime"]: + return calendar.timegm(time.strptime(self[9], "%Y%m%d%H%M%S")) + elif out_format.lower() in ["relative"]: + return calendar.timegm(time.strptime(self[9], "%Y%m%d%H%M%S")) - time.time() + elif out_format.lower() in ["struct_time", "time.struct_time"]: + return time.strptime(self[9], "%Y%m%d%H%M%S") + else: + raise Exception("unrecognized time format") + else: + return "" + + def expiration(self, out_format="UTC"): + """get expiration time. see inception() for more information""" + if self.rr_type() == "RRSIG": + if out_format.lower() in ["utc", "utc str", "utc_str"]: + return self[8] + elif out_format.lower() in ["unix", "posix", "ctime"]: + return calendar.timegm(time.strptime(self[8], "%Y%m%d%H%M%S")) + elif out_format.lower() in ["relative"]: + return calendar.timegm(time.strptime(self[8], "%Y%m%d%H%M%S")) - time.time() + elif out_format.lower() in ["struct_time", "time.struct_time"]: + return time.strptime(self[8], "%Y%m%d%H%M%S") + else: + raise Exception("unrecognized time format") + else: + return "" + + def ip(self): + """ IP address form A/AAAA record""" + if self.rr_type() in ["A", "AAAA"]: + return self[4] + else: + raise Exception("ldnsx does not support ip for records other than A/AAAA") + + def alg(self): + """Returns algorithm of RRSIG/DNSKEY/DS""" + t = self.rr_type() + if t == "RRSIG": + return int(self[5]) + elif t == "DNSKEY": + return int(self[6]) + elif t == "DS": + return int(self[5]) + else: + return -1 + + def protocol(self): + """ Returns proticol of the DNSKEY""" + t = self.rr_type() + if t == "DNSKEY": + return int(self[5]) + else: + return -1 + + def flags(self): + """Return RR flags for DNSKEY """ + t = self.rr_type() + if t == "DNSKEY": + ret = [] + n = int(self[4]) + for m in range(1): + if 2**(15-m) & n: + if m == 7: ret.append("ZONE") + elif m == 8: ret.append("REVOKE") + elif m ==15: ret.append("SEP") + else: ret.append(m) + return ret + else: + return [] + +_rr_types={ + "A" : ldns.LDNS_RR_TYPE_A, + "A6" : ldns.LDNS_RR_TYPE_A6, + "AAAA" : ldns.LDNS_RR_TYPE_AAAA, + "AFSDB": ldns.LDNS_RR_TYPE_AFSDB, + "ANY" : ldns.LDNS_RR_TYPE_ANY, + "APL" : ldns.LDNS_RR_TYPE_APL, + "ATMA" : ldns.LDNS_RR_TYPE_ATMA, + "AXFR" : ldns.LDNS_RR_TYPE_AXFR, + "CERT" : ldns.LDNS_RR_TYPE_CERT, + "CNAME": ldns.LDNS_RR_TYPE_CNAME, + "COUNT": ldns.LDNS_RR_TYPE_COUNT, + "DHCID": ldns.LDNS_RR_TYPE_DHCID, + "DLV" : ldns.LDNS_RR_TYPE_DLV, + "DNAME": ldns.LDNS_RR_TYPE_DNAME, + "DNSKEY": ldns.LDNS_RR_TYPE_DNSKEY, + "DS" : ldns.LDNS_RR_TYPE_DS, + "EID" : ldns.LDNS_RR_TYPE_EID, + "FIRST": ldns.LDNS_RR_TYPE_FIRST, + "GID" : ldns.LDNS_RR_TYPE_GID, + "GPOS" : ldns.LDNS_RR_TYPE_GPOS, + "HINFO": ldns.LDNS_RR_TYPE_HINFO, + "IPSECKEY": ldns.LDNS_RR_TYPE_IPSECKEY, + "ISDN" : ldns.LDNS_RR_TYPE_ISDN, + "IXFR" : ldns.LDNS_RR_TYPE_IXFR, + "KEY" : ldns.LDNS_RR_TYPE_KEY, + "KX" : ldns.LDNS_RR_TYPE_KX, + "LAST" : ldns.LDNS_RR_TYPE_LAST, + "LOC" : ldns.LDNS_RR_TYPE_LOC, + "MAILA": ldns.LDNS_RR_TYPE_MAILA, + "MAILB": ldns.LDNS_RR_TYPE_MAILB, + "MB" : ldns.LDNS_RR_TYPE_MB, + "MD" : ldns.LDNS_RR_TYPE_MD, + "MF" : ldns.LDNS_RR_TYPE_MF, + "MG" : ldns.LDNS_RR_TYPE_MG, + "MINFO": ldns.LDNS_RR_TYPE_MINFO, + "MR" : ldns.LDNS_RR_TYPE_MR, + "MX" : ldns.LDNS_RR_TYPE_MX, + "NAPTR": ldns.LDNS_RR_TYPE_NAPTR, + "NIMLOC": ldns.LDNS_RR_TYPE_NIMLOC, + "NS" : ldns.LDNS_RR_TYPE_NS, + "NSAP" : ldns.LDNS_RR_TYPE_NSAP, + "NSAP_PTR" : ldns.LDNS_RR_TYPE_NSAP_PTR, + "NSEC" : ldns.LDNS_RR_TYPE_NSEC, + "NSEC3": ldns.LDNS_RR_TYPE_NSEC3, + "NSEC3PARAMS" : ldns.LDNS_RR_TYPE_NSEC3PARAMS, + "NULL" : ldns.LDNS_RR_TYPE_NULL, + "NXT" : ldns.LDNS_RR_TYPE_NXT, + "OPT" : ldns.LDNS_RR_TYPE_OPT, + "PTR" : ldns.LDNS_RR_TYPE_PTR, + "PX" : ldns.LDNS_RR_TYPE_PX, + "RP" : ldns.LDNS_RR_TYPE_RP, + "RRSIG": ldns.LDNS_RR_TYPE_RRSIG, + "RT" : ldns.LDNS_RR_TYPE_RT, + "SIG" : ldns.LDNS_RR_TYPE_SIG, + "SINK" : ldns.LDNS_RR_TYPE_SINK, + "SOA" : ldns.LDNS_RR_TYPE_SOA, + "SRV" : ldns.LDNS_RR_TYPE_SRV, + "SSHFP": ldns.LDNS_RR_TYPE_SSHFP, + "TSIG" : ldns.LDNS_RR_TYPE_TSIG, + "TXT" : ldns.LDNS_RR_TYPE_TXT, + "UID" : ldns.LDNS_RR_TYPE_UID, + "UINFO": ldns.LDNS_RR_TYPE_UINFO, + "UNSPEC": ldns.LDNS_RR_TYPE_UNSPEC, + "WKS" : ldns.LDNS_RR_TYPE_WKS, + "X25" : ldns.LDNS_RR_TYPE_X25 +} + diff --git a/contrib/ldnsx/source/api/ldnsx.rst b/contrib/ldnsx/source/api/ldnsx.rst new file mode 100644 index 00000000000..7610adb2d39 --- /dev/null +++ b/contrib/ldnsx/source/api/ldnsx.rst @@ -0,0 +1,15 @@ +LDNSX API Reference +=================== + +.. automodule:: ldnsx + :members: query, get_rrs, secure_query + +Classes +------- +.. toctree:: + :maxdepth: 1 + :glob: + + resolver + packet + resource_record diff --git a/contrib/ldnsx/source/api/packet.rst b/contrib/ldnsx/source/api/packet.rst new file mode 100644 index 00000000000..81499407da0 --- /dev/null +++ b/contrib/ldnsx/source/api/packet.rst @@ -0,0 +1,6 @@ +Class packet +============== + +.. autoclass:: ldnsx.packet + :members: + :undoc-members: diff --git a/contrib/ldnsx/source/api/resolver.rst b/contrib/ldnsx/source/api/resolver.rst new file mode 100644 index 00000000000..2e2fba05148 --- /dev/null +++ b/contrib/ldnsx/source/api/resolver.rst @@ -0,0 +1,6 @@ +Class resolver +=============== + +.. autoclass:: ldnsx.resolver + :members: + :undoc-members: diff --git a/contrib/ldnsx/source/api/resource_record.rst b/contrib/ldnsx/source/api/resource_record.rst new file mode 100644 index 00000000000..429df0df7c9 --- /dev/null +++ b/contrib/ldnsx/source/api/resource_record.rst @@ -0,0 +1,6 @@ +Class resource_record +===================== + +.. autoclass:: ldnsx.resource_record + :members: + :undoc-members: diff --git a/contrib/ldnsx/source/conf.py b/contrib/ldnsx/source/conf.py new file mode 100644 index 00000000000..5b856d4cd78 --- /dev/null +++ b/contrib/ldnsx/source/conf.py @@ -0,0 +1,194 @@ +# -*- coding: utf-8 -*- +# +# ldnsx documentation build configuration file, created by +# sphinx-quickstart on Mon May 30 16:56:19 2011. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +sys.path.append(os.path.abspath('..')) + +# -- General configuration ----------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest']#, 'sphinx.ext.jsmath'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'ldnsx' +copyright = u'2011, Christopher Olah' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '0.0' +# The full version, including alpha/beta/rc tags. +release = '-1' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of documents that shouldn't be included in the build. +#unused_docs = [] + +# List of directories, relative to source directory, that shouldn't be searched +# for source files. +exclude_trees = [] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. Major themes that come with +# Sphinx are currently 'default' and 'sphinxdoc'. +html_theme = 'default' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_use_modindex = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = '' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'ldnsxdoc' + + +# -- Options for LaTeX output -------------------------------------------------- + +# The paper size ('letter' or 'a4'). +#latex_paper_size = 'letter' + +# The font size ('10pt', '11pt' or '12pt'). +#latex_font_size = '10pt' + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('index', 'ldnsx.tex', u'ldnsx Documentation', + u'Christopher Olah', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# Additional stuff for the LaTeX preamble. +#latex_preamble = '' + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_use_modindex = True diff --git a/contrib/ldnsx/source/examples/ldnsx-axfr.rst b/contrib/ldnsx/source/examples/ldnsx-axfr.rst new file mode 100644 index 00000000000..de51038dbfb --- /dev/null +++ b/contrib/ldnsx/source/examples/ldnsx-axfr.rst @@ -0,0 +1,6 @@ +AXFR Example +============ + +.. literalinclude:: ../../examples/ldnsx-axfr.py + :language: python + :linenos: diff --git a/contrib/ldnsx/source/examples/ldnsx-dnssec.rst b/contrib/ldnsx/source/examples/ldnsx-dnssec.rst new file mode 100644 index 00000000000..b93699923da --- /dev/null +++ b/contrib/ldnsx/source/examples/ldnsx-dnssec.rst @@ -0,0 +1,6 @@ +DNSSEC Example +============== + +.. literalinclude:: ../../examples/ldnsx-dnssec.py + :language: python + :linenos: diff --git a/contrib/ldnsx/source/examples/ldnsx-mx1.rst b/contrib/ldnsx/source/examples/ldnsx-mx1.rst new file mode 100644 index 00000000000..a6d7bbba0e3 --- /dev/null +++ b/contrib/ldnsx/source/examples/ldnsx-mx1.rst @@ -0,0 +1,6 @@ +MX1 +=== + +.. literalinclude:: ../../examples/ldnsx-mx1.py + :language: python + :linenos: diff --git a/contrib/ldnsx/source/examples/ldnsx-mx2.rst b/contrib/ldnsx/source/examples/ldnsx-mx2.rst new file mode 100644 index 00000000000..105c75ef532 --- /dev/null +++ b/contrib/ldnsx/source/examples/ldnsx-mx2.rst @@ -0,0 +1,6 @@ +MX2 +=== + +.. literalinclude:: ../../examples/ldnsx-mx2.py + :language: python + :linenos: diff --git a/contrib/ldnsx/source/examples/ldnsx-walk.rst b/contrib/ldnsx/source/examples/ldnsx-walk.rst new file mode 100644 index 00000000000..6cfb103cc1d --- /dev/null +++ b/contrib/ldnsx/source/examples/ldnsx-walk.rst @@ -0,0 +1,6 @@ +NSEC Walker +=========== + +.. literalinclude:: ../../examples/ldnsx-walk.py + :language: python + :linenos: diff --git a/contrib/ldnsx/source/index.rst b/contrib/ldnsx/source/index.rst new file mode 100644 index 00000000000..43de8b5d613 --- /dev/null +++ b/contrib/ldnsx/source/index.rst @@ -0,0 +1,57 @@ +Welcome to ldnsx's documentation! +================================= + +LDNSX: Easy DNS (including DNSSEC) via ldns. + +ldns is a great library. It is a powerfull tool for +working with DNS. python-ldns it is a straight up clone of the C +interface, howver that is not a very good interface for python. Its +documentation is incomplete and some functions don't work as +described. And some objects don't have a full python API. + +ldnsx aims to fix this. It wraps around the ldns python bindings, +working around its limitations and providing a well-documented, more +pythonistic interface. + +Reference +========= + +.. toctree:: + :maxdepth: 1 + + api/ldnsx + +.. toctree:: + :maxdepth: 2 + + api/resolver + api/packet + api/resource_record + +Examples +======== + +Examples translated from ldns examples: + +.. toctree:: + :maxdepth: 1 + + examples/ldnsx-axfr + examples/ldnsx-dnssec + examples/ldnsx-mx1 + examples/ldnsx-mx2 + +Others: + +.. toctree:: + :maxdepth: 1 + + examples/ldnsx-walk + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`search` + diff --git a/contrib/python/LICENSE b/contrib/python/LICENSE new file mode 100644 index 00000000000..1eb01e12161 --- /dev/null +++ b/contrib/python/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz) + Karel Slany (slany AT fit.vutbr.cz) +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 the organization 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. diff --git a/contrib/python/Makefile b/contrib/python/Makefile new file mode 100644 index 00000000000..c43970509a4 --- /dev/null +++ b/contrib/python/Makefile @@ -0,0 +1,67 @@ +# Makefile: compilation of sources and documentation, test environment +# +# Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz) +# Karel Slany (slany AT fit.vutbr.cz) +# 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 the organization 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. + +help: + @echo "Please use \`make ' where is one of" + @echo " testenv to make test environment and run bash " + @echo " usefull in case you don't want to install ldns but want to test examples" + @echo " doc to make documentation" + @echo " clean clean all" + +../../Makefile: ../../configure + cd ../.. && ./configure --with-python + +_ldns.so: ../../Makefile + $(MAKE) -C ../.. + +../../.libs/ldns.so.1: ../../Makefile + $(MAKE) -C ../.. + +clean: + rm -rdf examples/ldns + rm -f _ldns.so ldns_wrapper.o + $(MAKE) -C ../.. clean + +testenv: ../../.libs/libldns.so.1 _ldns.so + rm -rdf examples/ldns + cd examples && mkdir ldns && ln -s ../../ldns.py ldns/__init__.py && ln -s ../../_ldns.so ldns/_ldns.so && ln -s ../../../../.libs/libldns.so.1 ldns/libldns.so.1 && ls -la + @echo "Run a script by typing ./script_name.py" + cd examples && LD_LIBRARY_PATH=ldns bash + rm -rdf examples/ldns + +doc: ../../.libs/ldns.so.1 _ldns.so + $(MAKE) -C docs html + +#for development only +swig: ldns.i + swig -python -py3 -o ldns_wrapper.c -I../.. ldns.i + gcc -c ldns_wrapper.c -O9 -fPIC -I../.. -I../../ldns -I/usr/include/python3.1 -I. -o ldns_wrapper.o + ld -shared ldns_wrapper.o -L../../.libs -lldns -o _ldns.so + diff --git a/contrib/python/docs/Makefile b/contrib/python/docs/Makefile new file mode 100644 index 00000000000..856ecd45e18 --- /dev/null +++ b/contrib/python/docs/Makefile @@ -0,0 +1,70 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source + +.PHONY: help clean html web pickle htmlhelp latex changes linkcheck + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " pickle to make pickle files (usable by e.g. sphinx-web)" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " changes to make an overview over all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + +clean: + -rm -rf build/* + +html: + mkdir -p build/html build/doctrees + LD_LIBRARY_PATH=../../../.libs $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) build/html + @echo + @echo "Build finished. The HTML pages are in build/html." + +pickle: + mkdir -p build/pickle build/doctrees + LD_LIBRARY_PATH=../../../.libs $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) build/pickle + @echo + @echo "Build finished; now you can process the pickle files or run" + @echo " sphinx-web build/pickle" + @echo "to start the sphinx-web server." + +web: pickle + +htmlhelp: + mkdir -p build/htmlhelp build/doctrees + LD_LIBRARY_PATH=../../../.libs $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) build/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in build/htmlhelp." + +latex: + mkdir -p build/latex build/doctrees + LD_LIBRARY_PATH=../../../.libs $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) build/latex + @echo + @echo "Build finished; the LaTeX files are in build/latex." + @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ + "run these through (pdf)latex." + +changes: + mkdir -p build/changes build/doctrees + LD_LIBRARY_PATH=../../../.libs $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) build/changes + @echo + @echo "The overview file is in build/changes." + +linkcheck: + mkdir -p build/linkcheck build/doctrees + LD_LIBRARY_PATH=../../../.libs $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) build/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in build/linkcheck/output.txt." diff --git a/contrib/python/docs/source/conf.py b/contrib/python/docs/source/conf.py new file mode 100644 index 00000000000..22b73bcd712 --- /dev/null +++ b/contrib/python/docs/source/conf.py @@ -0,0 +1,180 @@ +# -*- coding: utf-8 -*- +# +# Unbound documentation build configuration file, created by +# sphinx-quickstart on Fri Jan 2 19:14:13 2009. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# The contents of this file are pickled, so don't put values in the namespace +# that aren't pickleable (module imports are okay, they're removed automatically). +# +# All configuration values have a default value; values that are commented out +# serve to show the default value. + +import sys, os + +# If your extensions are in another directory, add it here. If the directory +# is relative to the documentation root, use os.path.abspath to make it +# absolute, like shown here. +sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__),'../../'))) +#print sys.path + +# General configuration +# --------------------- + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# General substitutions. +project = 'pyLDNS' +copyright = '2009, Karel Slany, Zdenek Vasicek' + +# The default replacements for |version| and |release|, also used in various +# other places throughout the built documents. +# +# The short X.Y version. +version = '1.0' +# The full version, including alpha/beta/rc tags. +release = '1.0.0' + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +today_fmt = '%B %d, %Y' + +# List of documents that shouldn't be included in the build. +#unused_docs = [] + +# List of directories, relative to source directories, that shouldn't be searched +# for source files. +#exclude_dirs = [] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + + +# Options for HTML output +# ----------------------- + +# The style sheet to use for HTML and HTML Help pages. A file of that name +# must exist either in Sphinx' static/ path, or in one of the custom paths +# given in html_static_path. +html_style = 'default.css' + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (within the static path) to place at the top of +# the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +html_use_modindex = False + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +html_split_index = False + +# If true, the reST sources are included in the HTML build as _sources/. +html_copy_source = False + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = '' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'ldnsdoc' + + +# Options for LaTeX output +# ------------------------ + +# The paper size ('letter' or 'a4'). +#latex_paper_size = 'letter' + +# The font size ('10pt', '11pt' or '12pt'). +#latex_font_size = '10pt' + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, document class [howto/manual]). +latex_documents = [ + ('index', 'ldns-doc.tex', 'LDNS Documentation', + 'Karel Slany, Zdenek Vasicek', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# Additional stuff for the LaTeX preamble. +#latex_preamble = '' + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_use_modindex = True diff --git a/contrib/python/docs/source/examples/example1.rst b/contrib/python/docs/source/examples/example1.rst new file mode 100644 index 00000000000..b44141759f5 --- /dev/null +++ b/contrib/python/docs/source/examples/example1.rst @@ -0,0 +1,68 @@ +Resolving the MX records +============================== + +This basic example shows how to create a resolver which asks for MX records which contain the information about mail servers. + +:: + + #!/usr/bin/python + # + # MX is a small program that prints out the mx records for a particular domain + # + import ldns + + resolver = ldns.ldns_resolver.new_frm_file("/etc/resolv.conf") + + dname = ldns.ldns_dname("nic.cz") + + pkt = resolver.query(dname, ldns.LDNS_RR_TYPE_MX, ldns.LDNS_RR_CLASS_IN, ldns.LDNS_RD) + if (pkt): + mx = pkt.rr_list_by_type(ldns.LDNS_RR_TYPE_MX, ldns.LDNS_SECTION_ANSWER) + if (mx): + mx.sort() + print mx + +Resolving step by step +------------------------ + +First of all we import :mod:`ldns` extension module which make LDNS functions and classes accessible:: + + import ldns + +If importing fails, it means that Python cannot find the module or ldns library. + +Then we create the resolver by :meth:`ldns.ldns_resolver.new_frm_file` constructor :: + + resolver = ldns.ldns_resolver.new_frm_file("/etc/resolv.conf") + +and domain name variable dname:: + + dname = ldns.ldns_dname("nic.cz") + +To create a resolver you may also use:: + + resolver = ldns.ldns_resolver.new_frm_file(None) + +which behaves in the same manner as the command above. + +In the third step we tell the resolver to query for our domain, type MX, of class IN:: + + pkt = resolver.query(dname, ldns.LDNS_RR_TYPE_MX, ldns.LDNS_RR_CLASS_IN, ldns.LDNS_RD) + +The function should return a packet if everything goes well and this packet will contain resource records we asked for. +Note that there exists a simplier way. Instead of using a dname variable, we can use a string which will be automatically converted. +:: + + pkt = resolver.query("fit.vutbr.cz", ldns.LDNS_RR_TYPE_MX, ldns.LDNS_RR_CLASS_IN, ldns.LDNS_RD) + +Now, we test whether the resolver returns a packet and then get all RRs of type MX from the answer packet and store them in list mx:: + + if (pkt): + mx = pkt.rr_list_by_type(ldns.LDNS_RR_TYPE_MX, ldns.LDNS_SECTION_ANSWER) + +If this list is not empty, we sort and print the content to stdout:: + + if (mx): + mx.sort() + print mx + diff --git a/contrib/python/docs/source/examples/example2.py b/contrib/python/docs/source/examples/example2.py new file mode 100755 index 00000000000..7dabb917902 --- /dev/null +++ b/contrib/python/docs/source/examples/example2.py @@ -0,0 +1,45 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +import ldns +import sys + +debug = True + +# Check args +argc = len(sys.argv) +name = "www.nic.cz" +if argc < 2: + print("Usage:", sys.argv[0], "domain [resolver_addr]") + sys.exit(1) +else: + name = sys.argv[1] + +# Create resolver +resolver = ldns.ldns_resolver.new_frm_file("/etc/resolv.conf") +resolver.set_dnssec(True) + +# Custom resolver +if argc > 2: + # Clear previous nameservers + ns = resolver.pop_nameserver() + while ns != None: + ns = resolver.pop_nameserver() + ip = ldns.ldns_rdf.new_frm_str(sys.argv[2], ldns.LDNS_RDF_TYPE_A) + resolver.push_nameserver(ip) + +# Resolve DNS name +pkt = resolver.query(name, ldns.LDNS_RR_TYPE_A, ldns.LDNS_RR_CLASS_IN) +if pkt and pkt.answer(): + + # Debug + if debug: + print("NS returned:", pkt.get_rcode(), "(AA: %d AD: %d)" % ( pkt.ad(), pkt.ad() )) + + # SERVFAIL indicated bogus name + if pkt.get_rcode() is ldns.LDNS_RCODE_SERVFAIL: + print(name, "is bogus") + + # Check AD (Authenticated) bit + if pkt.get_rcode() is ldns.LDNS_RCODE_NOERROR: + if pkt.ad(): print(name, "is secure") + else: print(name, "is insecure") diff --git a/contrib/python/docs/source/examples/example2.rst b/contrib/python/docs/source/examples/example2.rst new file mode 100644 index 00000000000..b1734386e7d --- /dev/null +++ b/contrib/python/docs/source/examples/example2.rst @@ -0,0 +1,100 @@ +.. _ex_dnssec: + +Querying DNS-SEC validators +=========================== + +This basic example shows how to query validating resolver and +evaluate answer. + +Resolving step by step +------------------------ + +For DNS queries, we need to initialize ldns resolver (covered in previous example). + +:: + + # Create resolver + resolver = ldns.ldns_resolver.new_frm_file("/etc/resolv.conf") + resolver.set_dnssec(True) + + # Custom resolver + if argc > 2: + # Clear previous nameservers + ns = resolver.pop_nameserver() + while ns != None: + ns = resolver.pop_nameserver() + ip = ldns.ldns_rdf.new_frm_str(sys.argv[2], ldns.LDNS_RDF_TYPE_A) + resolver.push_nameserver(ip) + +Note the second line :meth:`resolver.set_dnssec`, which enables DNSSEC OK bit +in queries in order to get meaningful results. + +As we have resolver initialized, we can start querying for domain names : + +:: + + # Resolve DNS name + pkt = resolver.query(name, ldns.LDNS_RR_TYPE_A, ldns.LDNS_RR_CLASS_IN) + if pkt and pkt.answer(): + +Now we evaluate result, where two flags are crucial : + + * Return code + * AD flag (authenticated) + +When return code is `SERVFAIL`, it means that validating resolver marked requested +name as **bogus** (or bad configuration). + +**AD** flag is set if domain name is authenticated **(secure)** or false if +it's insecure. + +Complete source code +-------------------- + + .. literalinclude:: ../../../examples/ldns-dnssec.py + :language: python + + +Testing +------- + +In order to get meaningful results, you have to enter IP address of validating +resolver or setup your own (see howto). + +Execute `./example2.py` with options `domain name` and `resolver IP`, +example: + +:: + + user@localhost# ./example2.py www.dnssec.cz 127.0.0.1 # Secure (Configured Unbound running on localhost) + user@localhost# ./example2.py www.rhybar.cz 127.0.0.1 # Bogus + +Howto setup Unbound as validating resolver +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Install Unbound according to instructions. +Modify following options in `unbound.conf` (located in `/etc` or `/usr/local/etc`)/ + + +Uncomment `module-config` and set `validator` before iterator. + +:: + + module-config: "validator iterator" + +Download DLV keys and update path in `unbound.conf`:: + + # DLV keys + # Download from http://ftp.isc.org/www/dlv/dlv.isc.org.key + dlv-anchor-file: "/usr/local/etc/unbound/dlv.isc.org.key" + +Update trusted keys (`.cz` for example):: + + # Trusted keys + # For current key, see www.dnssec.cz + trusted-keys-file: "/usr/local/etc/unbound/trusted.key" + +Now you should have well configured Unbound, so run it:: + + user@localhost# unbound -dv + diff --git a/contrib/python/docs/source/examples/example3.rst b/contrib/python/docs/source/examples/example3.rst new file mode 100644 index 00000000000..91f5e9d1448 --- /dev/null +++ b/contrib/python/docs/source/examples/example3.rst @@ -0,0 +1,7 @@ +High-level functions +=========================== + +This basic example shows how to get name by addr and vice versa. + +.. literalinclude:: ../../../examples/ldns-higher.py + :language: python diff --git a/contrib/python/docs/source/examples/example4.rst b/contrib/python/docs/source/examples/example4.rst new file mode 100644 index 00000000000..2f41f76bde7 --- /dev/null +++ b/contrib/python/docs/source/examples/example4.rst @@ -0,0 +1,7 @@ +AXFR client with IDN support +=============================== + +This example shows how to get AXFR working and how to get involved Internationalized Domain Names (IDN) + +.. literalinclude:: ../../../examples/ldns-axfr.py + :language: python diff --git a/contrib/python/docs/source/examples/example5.rst b/contrib/python/docs/source/examples/example5.rst new file mode 100644 index 00000000000..787c169265d --- /dev/null +++ b/contrib/python/docs/source/examples/example5.rst @@ -0,0 +1,14 @@ +Examine the results +=============================== + +This example shows how to go through the obtained results + +.. literalinclude:: ../../../examples/ldns-mx2.py + :language: python + +This snippet of code prints:: + + nic.cz. 1761 IN MX 20 mx.cznic.org. + nic.cz. 1761 IN MX 10 mail.nic.cz. + nic.cz. 1761 IN MX 15 mail4.nic.cz. + diff --git a/contrib/python/docs/source/examples/example6.rst b/contrib/python/docs/source/examples/example6.rst new file mode 100644 index 00000000000..d0fd6899801 --- /dev/null +++ b/contrib/python/docs/source/examples/example6.rst @@ -0,0 +1,12 @@ +Read zone file +=============================== + +This example shows how to read the content of a zone file + +.. literalinclude:: ../../../examples/ldns-zone.py + :language: python + +Zone file ``zone.txt``: + +.. literalinclude:: ../../../examples/zone.txt + diff --git a/contrib/python/docs/source/examples/example7.rst b/contrib/python/docs/source/examples/example7.rst new file mode 100644 index 00000000000..3e3e2dc22e5 --- /dev/null +++ b/contrib/python/docs/source/examples/example7.rst @@ -0,0 +1,8 @@ +Generate public/private key pair +======================================= + +This example shows how generate keys for DNSSEC (i.e. for signing a zone file according DNSSECbis). + +.. literalinclude:: ../../../examples/ldns-keygen.py + :language: python + diff --git a/contrib/python/docs/source/examples/example8.rst b/contrib/python/docs/source/examples/example8.rst new file mode 100644 index 00000000000..6fc550a8604 --- /dev/null +++ b/contrib/python/docs/source/examples/example8.rst @@ -0,0 +1,17 @@ +Signing of a zone file +=============================== + +This example shows how to sign the content of the given zone file + +.. literalinclude:: ../../../examples/ldns-signzone.py + :language: python + +In order to be able sign a zone file, you have to generate a key-pair using ``ldns-keygen.py``. Don't forget to modify tag number. + +Signing consists of three steps + +1. In the first step, the content of a zone file is readed and parsed. This can be done using :class:`ldns.ldns_zone` class. + +2. In the second step, the private and public key is readed and public key is inserted into zone (as DNSKEY). + +3. In the last step, the DNSSEC zone instace is created and all the RRs from zone file are copied here. Then, all the records are signed using :meth:`ldns.ldns_zone.sign` method. If the signing was successfull, the content of DNSSEC zone is written to a file. diff --git a/contrib/python/docs/source/examples/index.rst b/contrib/python/docs/source/examples/index.rst new file mode 100644 index 00000000000..8f7f381c329 --- /dev/null +++ b/contrib/python/docs/source/examples/index.rst @@ -0,0 +1,12 @@ +Tutorials +============================== + +Here you can find a set of simple applications which utilizes the ldns library in Python environment. + +`Tutorials` + +.. toctree:: + :maxdepth: 1 + :glob: + + example* diff --git a/contrib/python/docs/source/index.rst b/contrib/python/docs/source/index.rst new file mode 100644 index 00000000000..d00b639d1ac --- /dev/null +++ b/contrib/python/docs/source/index.rst @@ -0,0 +1,22 @@ +PyLDNS documentation +======================================= + +PyLDNS provides an `LDNS`_ wrapper (Python extension module) - the thinnest layer over the library possible. Everything you can do from the C API, you can do from Python, but with less effort. The purpose of porting LDNS library to Python is to simplify DNS programming and usage of LDNS, however, still preserve the performance of this library as the speed represents the main benefit of LDNS. The proposed object approach allows the users to be concentrated at the essential part of application only and don't bother with deallocation of objects and so on. + +.. _LDNS: http://www.nlnetlabs.nl/projects/ldns/ + +Contents +---------- +.. toctree:: + :maxdepth: 2 + + install.rst + examples/index.rst + modules/ldns + +Indices and tables +------------------- + +* :ref:`genindex` +* :ref:`search` + diff --git a/contrib/python/docs/source/install.rst b/contrib/python/docs/source/install.rst new file mode 100644 index 00000000000..b3845b6e21b --- /dev/null +++ b/contrib/python/docs/source/install.rst @@ -0,0 +1,46 @@ +Installation +=================================== + +**Prerequisites** + +Python 2.4 or higher, SWIG 1.3 or higher, GNU make + +**Download** + +You can download the source codes `here`_. +The latest release is 1.4.1, Jan 15, 2009. + +.. _here: ldns-1.4.1-py.tar.gz + +**Compiling** + +After downloading, you can compile the library by doing:: + + > tar -xzf ldns-1.4.1-py.tar.gz + > cd ldns-1.4.1 + > ./configure --with-pyldns + > make + +You need GNU make to compile pyLDNS; SWIG and Python development libraries to compile extension module. + + +**Testing** + +If the compilation is successfull, you can test the python LDNS extension module by:: + + > cd contrib/python + > make testenv + > ./ldns-mx.py + +This will start a new shell, during which the symbolic links will be working. +When you exit the shell, then symbolic links will be deleted. + +In ``contrib/examples`` you can find many simple applications in python which demostrates the capabilities of LDNS library. + +**Installation** + +To install libraries and extension type:: + + > cd ldns-1.4.1 + > make install + diff --git a/contrib/python/docs/source/modules/ldns.rst b/contrib/python/docs/source/modules/ldns.rst new file mode 100644 index 00000000000..2c5e7b2455d --- /dev/null +++ b/contrib/python/docs/source/modules/ldns.rst @@ -0,0 +1,40 @@ +LDNS module documentation +================================ + +Here you can find the documentation of pyLDNS extension module. This module consists of several classes and a couple of functions. + +.. toctree:: + :maxdepth: 1 + :glob: + + ldns_resolver + ldns_pkt + ldns_rr + ldns_rdf + ldns_dname + ldns_rr_list + ldns_zone + ldns_key + ldns_key_list + ldns_buffer + ldns_dnssec + ldns_func + + + + +**Differences against libLDNS** + +* You don't need to use ldns-compare functions, instances can be compared using standard operators <, >, = :: + + if (some_rr.owner() == another_rr.rdf(1)): + pass + +* Classes contain static methods that create new instances, the name of these methods starts with the new\_ prefix (e.g. :meth:`ldns.ldns_pkt.new_frm_file`). + +* Is it possible to print the content of an object using ``print objinst`` (see :meth:`ldns.ldns_resolver.get_addr_by_name`). + +* Classes contain write_to_buffer method that writes the content into buffer. + +* All the methods that consume parameter of (const ldns_rdf) type allows to use string instead (see :meth:`ldns.ldns_resolver.query`). + diff --git a/contrib/python/docs/source/modules/ldns_buffer.rst b/contrib/python/docs/source/modules/ldns_buffer.rst new file mode 100644 index 00000000000..7f59e75e3ed --- /dev/null +++ b/contrib/python/docs/source/modules/ldns_buffer.rst @@ -0,0 +1,11 @@ +Class ldns_buffer +================================ + + +.. automodule:: ldns + +Class ldns_buffer +------------------------------ +.. autoclass:: ldns_buffer + :members: + :undoc-members: diff --git a/contrib/python/docs/source/modules/ldns_dname.rst b/contrib/python/docs/source/modules/ldns_dname.rst new file mode 100644 index 00000000000..18373bf8e66 --- /dev/null +++ b/contrib/python/docs/source/modules/ldns_dname.rst @@ -0,0 +1,11 @@ +Class ldns_dname +================================ + + +.. automodule:: ldns + +Class ldns_dname +------------------------------ +.. autoclass:: ldns_dname + :members: + :undoc-members: diff --git a/contrib/python/docs/source/modules/ldns_dnssec.rst b/contrib/python/docs/source/modules/ldns_dnssec.rst new file mode 100644 index 00000000000..bc5719dd557 --- /dev/null +++ b/contrib/python/docs/source/modules/ldns_dnssec.rst @@ -0,0 +1,28 @@ +Class ldns_dnssec_zone +================================ + +.. automodule:: ldns + +Class ldns_dnssec_zone +------------------------------ +.. autoclass:: ldns_dnssec_zone + :members: + :undoc-members: + +Class ldns_dnssec_name +------------------------------ +.. autoclass:: ldns_dnssec_name + :members: + :undoc-members: + +Class ldns_dnssec_rrsets +------------------------------ +.. autoclass:: ldns_dnssec_rrsets + :members: + :undoc-members: + +Class ldns_dnssec_rrs +------------------------------ +.. autoclass:: ldns_dnssec_rrs + :members: + :undoc-members: diff --git a/contrib/python/docs/source/modules/ldns_func.rst b/contrib/python/docs/source/modules/ldns_func.rst new file mode 100644 index 00000000000..7a9b8a8959f --- /dev/null +++ b/contrib/python/docs/source/modules/ldns_func.rst @@ -0,0 +1,253 @@ +Various functions +================================ + +Here you can find list of functions that are not assigned to the classes. +These functions have the same parameters as LDNS functions of the same name. +You are encouraged to read the LDNS documentation. + +**List of functions** + + * ldns_algorithm2buffer_str + * ldns_bget_keyword_data + * ldns_bget_token + * ldns_bgetc + * ldns_bskipcs + * ldns_bubblebabble + * ldns_buffer2pkt_wire + * ldns_buffer2str + * ldns_calc_keytag + * ldns_calc_keytag_raw + * ldns_cert_algorithm2buffer_str + * ldns_convert_dsa_rrsig_asn12rdf + * ldns_convert_dsa_rrsig_rdf2asn1 + * ldns_create_nsec + * ldns_create_nsec3 + * ldns_dname2buffer_wire + * ldns_dname2canonical + * ldns_dnssec_build_data_chain + * ldns_dnssec_chain_nsec3_list + * ldns_dnssec_create_nsec + * ldns_dnssec_create_nsec3 + * ldns_dnssec_create_nsec_bitmap + * ldns_dnssec_data_chain_deep_free + * ldns_dnssec_data_chain_free + * ldns_dnssec_data_chain_new + * ldns_dnssec_data_chain_print + * ldns_dnssec_default_add_to_signatures + * ldns_dnssec_default_delete_signatures + * ldns_dnssec_default_leave_signatures + * ldns_dnssec_default_replace_signatures + * ldns_dnssec_derive_trust_tree + * ldns_dnssec_derive_trust_tree_dnskey_rrset + * ldns_dnssec_derive_trust_tree_ds_rrset + * ldns_dnssec_derive_trust_tree_no_sig + * ldns_dnssec_derive_trust_tree_normal_rrset + * ldns_dnssec_get_dnskey_for_rrsig + * ldns_dnssec_get_rrsig_for_name_and_type + * ldns_dnssec_nsec3_closest_encloser + * ldns_dnssec_pkt_get_rrsigs_for_name_and_type + * ldns_dnssec_pkt_get_rrsigs_for_type + * ldns_dnssec_pkt_has_rrsigs + * ldns_dnssec_remove_signatures + * ldns_dnssec_trust_tree_add_parent + * ldns_dnssec_trust_tree_contains_keys + * ldns_dnssec_trust_tree_depth + * ldns_dnssec_trust_tree_free + * ldns_dnssec_trust_tree_new + * ldns_dnssec_trust_tree_print + * ldns_dnssec_verify_denial + * ldns_dnssec_verify_denial_nsec3 + * ldns_fetch_valid_domain_keys + * ldns_fget_keyword_data + * ldns_fget_keyword_data_l + * ldns_fget_token + * ldns_fget_token_l + * ldns_fskipcs + * ldns_fskipcs_l + * ldns_get_bit + * ldns_get_bit_r + * ldns_get_errorstr_by_id + * ldns_get_rr_class_by_name + * ldns_get_rr_list_addr_by_name + * ldns_get_rr_list_hosts_frm_file + * ldns_get_rr_list_hosts_frm_fp + * ldns_get_rr_list_hosts_frm_fp_l + * ldns_get_rr_list_name_by_addr + * ldns_get_rr_type_by_name + * ldns_getaddrinfo + * ldns_hexdigit_to_int + * ldns_hexstring_to_data + * ldns_init_random + * ldns_int_to_hexdigit + * ldns_is_rrset + * ldns_key2buffer_str + * ldns_key2rr + * ldns_key2str + * ldns_lookup_by_id + * ldns_lookup_by_name + * ldns_native2rdf_int16 + * ldns_native2rdf_int16_data + * ldns_native2rdf_int32 + * ldns_native2rdf_int8 + * ldns_nsec3_add_param_rdfs + * ldns_nsec3_algorithm + * ldns_nsec3_bitmap + * ldns_nsec3_flags + * ldns_nsec3_hash_name + * ldns_nsec3_hash_name_frm_nsec3 + * ldns_nsec3_iterations + * ldns_nsec3_next_owner + * ldns_nsec3_optout + * ldns_nsec3_salt + * ldns_nsec3_salt_data + * ldns_nsec3_salt_length + * ldns_nsec_bitmap_covers_type + * ldns_nsec_covers_name + * ldns_nsec_get_bitmap + * ldns_nsec_type_check + * ldns_octet + * ldns_pkt2buffer_str + * ldns_pkt2buffer_wire + * ldns_pkt2str + * ldns_pkt2wire + * ldns_pktheader2buffer_str + * ldns_power + * ldns_print_rr_rdf + * ldns_rbtree_create + * ldns_rbtree_delete + * ldns_rbtree_find_less_equal + * ldns_rbtree_first + * ldns_rbtree_free + * ldns_rbtree_init + * ldns_rbtree_insert + * ldns_rbtree_insert_vref + * ldns_rbtree_last + * ldns_rbtree_next + * ldns_rbtree_previous + * ldns_rbtree_search + * ldns_rdf2buffer_str + * ldns_rdf2buffer_str_a + * ldns_rdf2buffer_str_aaaa + * ldns_rdf2buffer_str_alg + * ldns_rdf2buffer_str_apl + * ldns_rdf2buffer_str_b64 + * ldns_rdf2buffer_str_cert_alg + * ldns_rdf2buffer_str_class + * ldns_rdf2buffer_str_dname + * ldns_rdf2buffer_str_hex + * ldns_rdf2buffer_str_int16 + * ldns_rdf2buffer_str_int16_data + * ldns_rdf2buffer_str_ipseckey + * ldns_rdf2buffer_str_loc + * ldns_rdf2buffer_str_nsap + * ldns_rdf2buffer_str_nsec + * ldns_rdf2buffer_str_period + * ldns_rdf2buffer_str_str + * ldns_rdf2buffer_str_tsig + * ldns_rdf2buffer_str_tsigtime + * ldns_rdf2buffer_str_type + * ldns_rdf2buffer_str_unknown + * ldns_rdf2buffer_str_wks + * ldns_rdf2buffer_wire + * ldns_rdf2buffer_wire_canonical + * ldns_rdf2native_int16 + * ldns_rdf2native_int32 + * ldns_rdf2native_int8 + * ldns_rdf2native_sockaddr_storage + * ldns_rdf2native_time_t + * ldns_rdf2rr_type + * ldns_rdf2str + * ldns_rdf2wire + * ldns_read_anchor_file + * ldns_read_uint16 + * ldns_read_uint32 + * ldns_rr2buffer_str + * ldns_rr2buffer_wire + * ldns_rr2buffer_wire_canonical + * ldns_rr2canonical + * ldns_rr2str + * ldns_rr2wire + * ldns_rrsig2buffer_wire + * ldns_send + * ldns_send_buffer + * ldns_set_bit + * ldns_sign_public + * ldns_sockaddr_storage2rdf + * ldns_str2period + * ldns_str2rdf_a + * ldns_str2rdf_aaaa + * ldns_str2rdf_alg + * ldns_str2rdf_apl + * ldns_str2rdf_b32_ext + * ldns_str2rdf_b64 + * ldns_str2rdf_cert_alg + * ldns_str2rdf_class + * ldns_str2rdf_dname + * ldns_str2rdf_hex + * ldns_str2rdf_int16 + * ldns_str2rdf_int32 + * ldns_str2rdf_int8 + * ldns_str2rdf_loc + * ldns_str2rdf_nsap + * ldns_str2rdf_nsec + * ldns_str2rdf_nsec3_salt + * ldns_str2rdf_period + * ldns_str2rdf_service + * ldns_str2rdf_str + * ldns_str2rdf_time + * ldns_str2rdf_tsig + * ldns_str2rdf_type + * ldns_str2rdf_unknown + * ldns_str2rdf_wks + * ldns_tcp_bgsend + * ldns_tcp_connect + * ldns_tcp_read_wire + * ldns_tcp_send + * ldns_tcp_send_query + * ldns_traverse_postorder + * ldns_tsig_algorithm + * ldns_tsig_keydata + * ldns_tsig_keydata_clone + * ldns_tsig_keyname + * ldns_tsig_keyname_clone + * ldns_udp_bgsend + * ldns_udp_connect + * ldns_udp_read_wire + * ldns_udp_send + * ldns_udp_send_query + * ldns_update_pkt_new + * ldns_update_pkt_tsig_add + * ldns_update_prcount + * ldns_update_set_adcount + * ldns_update_set_prcount + * ldns_update_set_upcount + * ldns_update_soa_mname + * ldns_update_soa_zone_mname + * ldns_update_upcount + * ldns_update_zocount + * ldns_validate_domain_dnskey + * ldns_validate_domain_ds + * ldns_verify + * ldns_verify_rrsig + * ldns_verify_rrsig_buffers + * ldns_verify_rrsig_buffers_raw + * ldns_verify_rrsig_dsa + * ldns_verify_rrsig_dsa_raw + * ldns_verify_rrsig_keylist + * ldns_verify_rrsig_rsamd5 + * ldns_verify_rrsig_rsamd5_raw + * ldns_verify_rrsig_rsasha1 + * ldns_verify_rrsig_rsasha1_raw + * ldns_verify_rrsig_rsasha256_raw + * ldns_verify_rrsig_rsasha512_raw + * ldns_verify_trusted + * ldns_version + * ldns_wire2dname + * ldns_wire2pkt + * ldns_wire2rdf + * ldns_wire2rr + * ldns_write_uint16 + * ldns_write_uint32 + * ldns_write_uint64_as_uint48 + * mktime_from_utc + * qsort_rr_compare_nsec3 diff --git a/contrib/python/docs/source/modules/ldns_key.rst b/contrib/python/docs/source/modules/ldns_key.rst new file mode 100644 index 00000000000..4d35766b799 --- /dev/null +++ b/contrib/python/docs/source/modules/ldns_key.rst @@ -0,0 +1,11 @@ +Class ldns_key +================================ + + +.. automodule:: ldns + +Class ldns_key +------------------------------ +.. autoclass:: ldns_key + :members: + :undoc-members: diff --git a/contrib/python/docs/source/modules/ldns_key_list.rst b/contrib/python/docs/source/modules/ldns_key_list.rst new file mode 100644 index 00000000000..e8e447452e3 --- /dev/null +++ b/contrib/python/docs/source/modules/ldns_key_list.rst @@ -0,0 +1,11 @@ +Class ldns_key_list +================================ + + +.. automodule:: ldns + +Class ldns_key_list +------------------------------ +.. autoclass:: ldns_key_list + :members: + :undoc-members: diff --git a/contrib/python/docs/source/modules/ldns_pkt.rst b/contrib/python/docs/source/modules/ldns_pkt.rst new file mode 100644 index 00000000000..eb00a0bc077 --- /dev/null +++ b/contrib/python/docs/source/modules/ldns_pkt.rst @@ -0,0 +1,11 @@ +Class ldns_pkt +================================ + + +.. automodule:: ldns + +Class ldns_pkt +------------------------------ +.. autoclass:: ldns_pkt + :members: + :undoc-members: diff --git a/contrib/python/docs/source/modules/ldns_rdf.rst b/contrib/python/docs/source/modules/ldns_rdf.rst new file mode 100644 index 00000000000..5ed1799b1bb --- /dev/null +++ b/contrib/python/docs/source/modules/ldns_rdf.rst @@ -0,0 +1,47 @@ +Class ldns_rdf +================================ + + +.. automodule:: ldns + +Class ldns_rdf +------------------------------ +.. autoclass:: ldns_rdf + :members: + :undoc-members: + +Predefined constants +------------------------------ + +**RDF TYPE** + * LDNS_RDF_TYPE_NONE, + * LDNS_RDF_TYPE_DNAME, + * LDNS_RDF_TYPE_INT8, + * LDNS_RDF_TYPE_INT16, + * LDNS_RDF_TYPE_INT32, + * LDNS_RDF_TYPE_A, + * LDNS_RDF_TYPE_AAAA, + * LDNS_RDF_TYPE_STR, + * LDNS_RDF_TYPE_APL, + * LDNS_RDF_TYPE_B32_EXT, + * LDNS_RDF_TYPE_B64, + * LDNS_RDF_TYPE_HEX, + * LDNS_RDF_TYPE_NSEC, + * LDNS_RDF_TYPE_TYPE, + * LDNS_RDF_TYPE_CLASS, + * LDNS_RDF_TYPE_CERT_ALG, + * LDNS_RDF_TYPE_ALG, + * LDNS_RDF_TYPE_UNKNOWN, + * LDNS_RDF_TYPE_TIME, + * LDNS_RDF_TYPE_PERIOD, + * LDNS_RDF_TYPE_TSIGTIME, + * LDNS_RDF_TYPE_TSIG, + * LDNS_RDF_TYPE_INT16_DATA, + * LDNS_RDF_TYPE_SERVICE, + * LDNS_RDF_TYPE_LOC, + * LDNS_RDF_TYPE_WKS, + * LDNS_RDF_TYPE_NSAP, + * LDNS_RDF_TYPE_IPSECKEY, + * LDNS_RDF_TYPE_NSEC3_SALT, + * LDNS_RDF_TYPE_NSEC3_NEXT_OWNER + diff --git a/contrib/python/docs/source/modules/ldns_resolver.rst b/contrib/python/docs/source/modules/ldns_resolver.rst new file mode 100644 index 00000000000..2fda23a2f01 --- /dev/null +++ b/contrib/python/docs/source/modules/ldns_resolver.rst @@ -0,0 +1,13 @@ +Class ldns_resolver +================================ + +.. automodule:: ldns + +Class ldns_resolver +------------------------------ +.. autoclass:: ldns_resolver + :members: + :undoc-members: + + + diff --git a/contrib/python/docs/source/modules/ldns_rr.rst b/contrib/python/docs/source/modules/ldns_rr.rst new file mode 100644 index 00000000000..78404cda0dc --- /dev/null +++ b/contrib/python/docs/source/modules/ldns_rr.rst @@ -0,0 +1,18 @@ +Class ldns_rr +================================ + + +.. automodule:: ldns + +Class ldns_rr +------------------------------ +.. autoclass:: ldns_rr + :members: + :undoc-members: + +Class ldns_rr_descriptor +------------------------------ +.. autoclass:: ldns_rr_descriptor + :members: + :undoc-members: + diff --git a/contrib/python/docs/source/modules/ldns_rr_list.rst b/contrib/python/docs/source/modules/ldns_rr_list.rst new file mode 100644 index 00000000000..f044093790e --- /dev/null +++ b/contrib/python/docs/source/modules/ldns_rr_list.rst @@ -0,0 +1,11 @@ +Class ldns_rr_list +================================ + + +.. automodule:: ldns + +Class ldns_rr_list +------------------------------ +.. autoclass:: ldns_rr_list + :members: + :undoc-members: diff --git a/contrib/python/docs/source/modules/ldns_zone.rst b/contrib/python/docs/source/modules/ldns_zone.rst new file mode 100644 index 00000000000..5331429222c --- /dev/null +++ b/contrib/python/docs/source/modules/ldns_zone.rst @@ -0,0 +1,11 @@ +Class ldns_zone +================================ + + +.. automodule:: ldns + +Class ldns_zone +------------------------------ +.. autoclass:: ldns_zone + :members: + :undoc-members: diff --git a/contrib/python/examples/ldns-axfr.py b/contrib/python/examples/ldns-axfr.py new file mode 100755 index 00000000000..5333484fa11 --- /dev/null +++ b/contrib/python/examples/ldns-axfr.py @@ -0,0 +1,56 @@ +#!/usr/bin/python +# vim:fileencoding=utf-8 +# +# AXFR client with IDN (Internationalized Domain Names) support +# + +import ldns +import encodings.idna + +def utf2name(name): + return '.'.join([encodings.idna.ToASCII(a) for a in name.split('.')]) +def name2utf(name): + return '.'.join([encodings.idna.ToUnicode(a) for a in name.split('.')]) + + +resolver = ldns.ldns_resolver.new_frm_file("/etc/resolv.conf") + +#addr = ldns.ldns_get_rr_list_addr_by_name(resolver, "zone.nic.cz", ldns.LDNS_RR_CLASS_IN, ldns.LDNS_RD); +addr = resolver.get_addr_by_name("zone.nic.cz", ldns.LDNS_RR_CLASS_IN, ldns.LDNS_RD); +if (not addr): + raise Exception("Can't retrieve server address") + +print "Addr_by_name:",str(addr).replace("\n","; ") + +#remove all nameservers +while resolver.pop_nameserver(): + pass + +#insert server addr +for rr in addr.rrs(): + resolver.push_nameserver_rr(rr) + +#AXFR transfer +status = resolver.axfr_start(utf2name(u"háčkyčárky.cz"), ldns.LDNS_RR_CLASS_IN) +if status != ldns.LDNS_STATUS_OK: + raise Exception("Can't start AXFR. Error: %s" % ldns.ldns_get_errorstr_by_id(status)) + +#Print results +while True: + rr = resolver.axfr_next() + if not rr: + break + + rdf = rr.owner() + if (rdf.get_type() == ldns.LDNS_RDF_TYPE_DNAME): + print "RDF owner: type=",rdf.get_type_str(),"data=",name2utf(str(rdf)) + else: + print "RDF owner: type=",rdf.get_type_str(),"data=",str(rdf) + print " RR type=", rr.get_type_str()," ttl=",rr.ttl() + for rdf in rr.rdfs(): + if (rdf.get_type() == ldns.LDNS_RDF_TYPE_DNAME): + print " RDF: type=",rdf.get_type_str(),"data=",name2utf(str(rdf)) + else: + print " RDF: type=",rdf.get_type_str(),"data=",str(rdf) + + print diff --git a/contrib/python/examples/ldns-buf.py b/contrib/python/examples/ldns-buf.py new file mode 100755 index 00000000000..73d8a029ffb --- /dev/null +++ b/contrib/python/examples/ldns-buf.py @@ -0,0 +1,8 @@ +#!/usr/bin/python + +import ldns + +buf = ldns.ldns_buffer(1024) +buf.printf("Test buffer") +print buf + diff --git a/contrib/python/examples/ldns-dnssec.py b/contrib/python/examples/ldns-dnssec.py new file mode 100755 index 00000000000..bb2acfdf762 --- /dev/null +++ b/contrib/python/examples/ldns-dnssec.py @@ -0,0 +1,45 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +import ldns +import sys + +debug = True + +# Check args +argc = len(sys.argv) +name = "www.nic.cz" +if argc < 2: + print "Usage:", sys.argv[0], "domain [resolver_addr]" + sys.exit(1) +else: + name = sys.argv[1] + +# Create resolver +resolver = ldns.ldns_resolver.new_frm_file("/etc/resolv.conf") +resolver.set_dnssec(True) + +# Custom resolver +if argc > 2: + # Clear previous nameservers + ns = resolver.pop_nameserver() + while ns != None: + ns = resolver.pop_nameserver() + ip = ldns.ldns_rdf.new_frm_str(sys.argv[2], ldns.LDNS_RDF_TYPE_A) + resolver.push_nameserver(ip) + +# Resolve DNS name +pkt = resolver.query(name, ldns.LDNS_RR_TYPE_A, ldns.LDNS_RR_CLASS_IN) +if pkt and pkt.answer(): + + # Debug + if debug: + print "NS returned:", pkt.get_rcode(), "(AA: %d AD: %d)" % ( pkt.ad(), pkt.ad() ) + + # SERVFAIL indicated bogus name + if pkt.get_rcode() is ldns.LDNS_RCODE_SERVFAIL: + print name, "is bogus" + + # Check AD (Authenticated) bit + if pkt.get_rcode() is ldns.LDNS_RCODE_NOERROR: + if pkt.ad(): print name, "is secure" + else: print name, "is insecure" diff --git a/contrib/python/examples/ldns-higher.py b/contrib/python/examples/ldns-higher.py new file mode 100755 index 00000000000..5175ec0e7ae --- /dev/null +++ b/contrib/python/examples/ldns-higher.py @@ -0,0 +1,36 @@ +#!/usr/bin/python +import ldns + +resolver = ldns.ldns_resolver.new_frm_file("/etc/resolv.conf") + +dnn = ldns.ldns_dname("www.google.com") +print dnn.get_type_str(), dnn + +dna = ldns.ldns_rdf.new_frm_str("74.125.43.99",ldns.LDNS_RDF_TYPE_A) +print dna.get_type_str(), dna + +name = resolver.get_name_by_addr(dna) +if (not name): raise Exception("Can't retrieve server name") +for rr in name.rrs(): + print rr + +name = resolver.get_name_by_addr("74.125.43.99") +if (not name): raise Exception("Can't retrieve server name") +for rr in name.rrs(): + print rr + +addr = resolver.get_addr_by_name(dnn) +if (not addr): raise Exception("Can't retrieve server address") +for rr in addr.rrs(): + print rr + +addr = resolver.get_addr_by_name("www.google.com") +if (not addr): raise Exception("Can't retrieve server address") +for rr in addr.rrs(): + print rr + +hosts = ldns.ldns_rr_list.new_frm_file("/etc/hosts") +if (not hosts): raise Exception("Can't retrieve the content of file") +for rr in hosts.rrs(): + print rr + diff --git a/contrib/python/examples/ldns-keygen.py b/contrib/python/examples/ldns-keygen.py new file mode 100755 index 00000000000..3ddf41a946e --- /dev/null +++ b/contrib/python/examples/ldns-keygen.py @@ -0,0 +1,46 @@ +#!/usr/bin/python +# +# This example shows how to generate public/private key pair +# +import ldns + +algorithm = ldns.LDNS_SIGN_DSA +bits = 512 + +ldns.ldns_init_random(open("/dev/random","rb"), (bits+7)//8) + +domain = ldns.ldns_dname("example.") + +#generate a new key +key = ldns.ldns_key.new_frm_algorithm(algorithm, bits); +print key + +#set owner +key.set_pubkey_owner(domain) + +#create the public from the ldns_key +pubkey = key.key_to_rr() +#previous command is equivalent to +# pubkey = ldns.ldns_key2rr(key) +print pubkey + +#calculate and set the keytag +key.set_keytag(ldns.ldns_calc_keytag(pubkey)) + +#build the DS record +ds = ldns.ldns_key_rr2ds(pubkey, ldns.LDNS_SHA1) +print ds + +owner, tag = pubkey.owner(), key.keytag() + +#write public key to .key file +fw = open("key-%s-%d.key" % (owner,tag), "wb") +pubkey.print_to_file(fw) + +#write private key to .priv file +fw = open("key-%s-%d.private" % (owner,tag), "wb") +key.print_to_file(fw) + +#write DS to .ds file +fw = open("key-%s-%d.ds" % (owner,tag), "wb") +ds.print_to_file(fw) diff --git a/contrib/python/examples/ldns-mx.py b/contrib/python/examples/ldns-mx.py new file mode 100755 index 00000000000..38c3f11c163 --- /dev/null +++ b/contrib/python/examples/ldns-mx.py @@ -0,0 +1,15 @@ +#!/usr/bin/python +# +# MX is a small program that prints out the mx records for a particular domain +# +import ldns + +resolver = ldns.ldns_resolver.new_frm_file("/etc/resolv.conf") + +pkt = resolver.query("nic.cz", ldns.LDNS_RR_TYPE_MX,ldns.LDNS_RR_CLASS_IN) + +if (pkt): + mx = pkt.rr_list_by_type(ldns.LDNS_RR_TYPE_MX, ldns.LDNS_SECTION_ANSWER) + if (mx): + mx.sort() + print mx diff --git a/contrib/python/examples/ldns-mx1.py b/contrib/python/examples/ldns-mx1.py new file mode 100755 index 00000000000..3dade1ed3d3 --- /dev/null +++ b/contrib/python/examples/ldns-mx1.py @@ -0,0 +1,18 @@ +#!/usr/bin/python +# +# MX is a small program that prints out the mx records for a particular domain +# +import ldns + +dname = ldns.ldns_dname("nic.cz") +print dname + +resolver = ldns.ldns_resolver.new_frm_file("/etc/resolv.conf") + +pkt = resolver.query(dname, ldns.LDNS_RR_TYPE_MX,ldns.LDNS_RR_CLASS_IN) + +if (pkt): + mx = pkt.rr_list_by_type(ldns.LDNS_RR_TYPE_MX, ldns.LDNS_SECTION_ANSWER) + if (mx): + mx.sort() + print mx diff --git a/contrib/python/examples/ldns-mx2.py b/contrib/python/examples/ldns-mx2.py new file mode 100755 index 00000000000..4fff98a4b1d --- /dev/null +++ b/contrib/python/examples/ldns-mx2.py @@ -0,0 +1,19 @@ +#!/usr/bin/python +# +# MX is a small program that prints out the mx records for a particular domain +# +import ldns + +resolver = ldns.ldns_resolver.new_frm_file("/etc/resolv.conf") + +pkt = resolver.query("nic.cz", ldns.LDNS_RR_TYPE_MX,ldns.LDNS_RR_CLASS_IN) +if (pkt) and (pkt.answer()): + + for rr in pkt.answer().rrs(): + if (rr.get_type() != ldns.LDNS_RR_TYPE_MX): + continue + + rdf = rr.owner() + print rdf," ",rr.ttl()," ",rr.get_class_str()," ",rr.get_type_str()," ", + print " ".join(str(rdf) for rdf in rr.rdfs()) + diff --git a/contrib/python/examples/ldns-newpkt.py b/contrib/python/examples/ldns-newpkt.py new file mode 100755 index 00000000000..d124a80f80e --- /dev/null +++ b/contrib/python/examples/ldns-newpkt.py @@ -0,0 +1,17 @@ +#!/usr/bin/python + +import ldns + +pkt = ldns.ldns_pkt.new_query_frm_str("www.google.com",ldns.LDNS_RR_TYPE_ANY, ldns.LDNS_RR_CLASS_IN, ldns.LDNS_QR | ldns.LDNS_AA) + +rra = ldns.ldns_rr.new_frm_str("www.google.com. IN A 192.168.1.1",300) +rrb = ldns.ldns_rr.new_frm_str("www.google.com. IN TXT Some\ Description",300) + +list = ldns.ldns_rr_list() +if (rra): list.push_rr(rra) +if (rrb): list.push_rr(rrb) + +pkt.push_rr_list(ldns.LDNS_SECTION_ANSWER, list) + +print "Packet:" +print pkt diff --git a/contrib/python/examples/ldns-signzone.py b/contrib/python/examples/ldns-signzone.py new file mode 100755 index 00000000000..41f76626eae --- /dev/null +++ b/contrib/python/examples/ldns-signzone.py @@ -0,0 +1,65 @@ +#!/usr/bin/python +# This example shows how to sign a given zone file with private key + +import ldns +import sys, os, time + +#private key TAG which identifies the private key +#use ldns-keygen.py in order to obtain private key +keytag = 30761 + +# Read zone file +#------------------------------------------------------------- + +zone = ldns.ldns_zone.new_frm_fp(open("zone.txt","r"), None, 0, ldns.LDNS_RR_CLASS_IN) +soa = zone.soa() +origin = soa.owner() + +# Prepare keys +#------------------------------------------------------------- + +#Read private key from file +keyfile = open("key-%s-%d.private" % (origin, keytag), "r"); +key = ldns.ldns_key.new_frm_fp(keyfile) + +#Read public key from file +pubfname = "key-%s-%d.key" % (origin, keytag) +pubkey = None +if os.path.isfile(pubfname): + pubkeyfile = open(pubfname, "r"); + pubkey,_,_,_ = ldns.ldns_rr.new_frm_fp(pubkeyfile) + +if not pubkey: + #Create new public key + pubkey = key.key_to_rr() + +#Set key expiration +key.set_expiration(int(time.time()) + 365*60*60*24) #365 days + +#Set key owner (important step) +key.set_pubkey_owner(origin) + +#Insert DNSKEY RR +zone.push_rr(pubkey) + +# Sign zone +#------------------------------------------------------------- + +#Create keylist and push private key +keys = ldns.ldns_key_list() +keys.push_key(key) + +#Add SOA +signed_zone = ldns.ldns_dnssec_zone() +signed_zone.add_rr(soa) + +#Add RRs +for rr in zone.rrs().rrs(): + print "RR:",str(rr), + signed_zone.add_rr(rr) + +added_rrs = ldns.ldns_rr_list() +status = signed_zone.sign(added_rrs, keys) +if (status == ldns.LDNS_STATUS_OK): + signed_zone.print_to_file(open("zone_signed.txt","w")) + diff --git a/contrib/python/examples/ldns-zone.py b/contrib/python/examples/ldns-zone.py new file mode 100755 index 00000000000..266e6e5b471 --- /dev/null +++ b/contrib/python/examples/ldns-zone.py @@ -0,0 +1,15 @@ +#!/usr/bin/python +import ldns + +#Read zone from file +zone = ldns.ldns_zone.new_frm_fp(open("zone.txt","r"), None, 0, ldns.LDNS_RR_CLASS_IN) +print zone + +print "SOA:", zone.soa() +for r in zone.rrs().rrs(): + print "RR:", r + + +zone = ldns.ldns_zone() +#print zone + diff --git a/contrib/python/examples/ldns_rr_iter_frm_fp_l.demo.py b/contrib/python/examples/ldns_rr_iter_frm_fp_l.demo.py new file mode 100644 index 00000000000..e123f90dbc6 --- /dev/null +++ b/contrib/python/examples/ldns_rr_iter_frm_fp_l.demo.py @@ -0,0 +1,15 @@ +import ldns +import sys + +if len(sys.argv) <= 1: + print "Usage: %s zone_file" % sys.argv[0] + sys.exit() + +inp = open(sys.argv[1],"r"); +for rr in ldns.ldns_rr_iter_frm_fp_l(inp): + print rr + +inp.close() + + + diff --git a/contrib/python/examples/ldns_rr_new_frm_fp_l.demo.py b/contrib/python/examples/ldns_rr_new_frm_fp_l.demo.py new file mode 100644 index 00000000000..70992254b6a --- /dev/null +++ b/contrib/python/examples/ldns_rr_new_frm_fp_l.demo.py @@ -0,0 +1,43 @@ +import ldns +import sys + +if len(sys.argv) <= 1: + print "Usage: %s zone_file" % sys.argv[0] + sys.exit() + +inp = open(sys.argv[1],"r"); +# variables that preserve the parsers state +my_ttl = 3600; +my_origin = None +my_prev = None +# additional state variables +last_pos = 0 +line_nr = 0 + +while True: + ret = ldns.ldns_rr_new_frm_fp_l_(inp, my_ttl, my_origin, my_prev) + s, rr, line_inc, new_ttl, new_origin, new_prev = ret # unpack the result + line_nr += line_inc # increase number of parsed lines + my_prev = new_prev # update ref to previous owner + + if s == ldns.LDNS_STATUS_SYNTAX_TTL: + my_ttl = new_ttl # update default TTL + print "$TTL:", my_ttl + elif s == ldns.LDNS_STATUS_SYNTAX_ORIGIN: + my_origin = new_origin # update reference to origin + print "$ORIGIN:", my_origin + elif s == ldns.LDNS_STATUS_SYNTAX_EMPTY: + if last_pos == inp.tell(): + break # no advance since last read - EOF + last_pos = inp.tell() + elif s != ldns.LDNS_STATUS_OK: + print "! parse error in line", line_nr + else: + # we are sure to have LDNS_STATUS_OK + print rr + +inp.close() +print "--------------------" +print "Read %d lines" % line_nr + + diff --git a/contrib/python/examples/python3/ldns-axfr.py b/contrib/python/examples/python3/ldns-axfr.py new file mode 100755 index 00000000000..fb8e5cf5e2f --- /dev/null +++ b/contrib/python/examples/python3/ldns-axfr.py @@ -0,0 +1,56 @@ +#!/usr/bin/python +# vim:fileencoding=utf-8 +# +# AXFR client with IDN (Internationalized Domain Names) support +# + +import ldns +import encodings.idna + +def utf2name(name): + return '.'.join([encodings.idna.ToASCII(a).decode("utf-8") for a in name.split('.')]) +def name2utf(name): + return '.'.join([encodings.idna.ToUnicode(a) for a in name.split('.')]) + + +resolver = ldns.ldns_resolver.new_frm_file("/etc/resolv.conf") + +#addr = ldns.ldns_get_rr_list_addr_by_name(resolver, "zone.nic.cz", ldns.LDNS_RR_CLASS_IN, ldns.LDNS_RD); +addr = resolver.get_addr_by_name("zone.nic.cz", ldns.LDNS_RR_CLASS_IN, ldns.LDNS_RD); +if (not addr): + raise Exception("Can't retrieve server address") + +print("Addr_by_name:",str(addr).replace("\n","; ")) + +#remove all nameservers +while resolver.pop_nameserver(): + pass + +#insert server addr +for rr in addr.rrs(): + resolver.push_nameserver_rr(rr) + +#AXFR transfer +status = resolver.axfr_start(utf2name("háčkyčárky.cz"), ldns.LDNS_RR_CLASS_IN) +if status != ldns.LDNS_STATUS_OK: + raise Exception("Can't start AXFR. Error: %s" % ldns.ldns_get_errorstr_by_id(status)) + +#Print results +while True: + rr = resolver.axfr_next() + if not rr: + break + + rdf = rr.owner() + if (rdf.get_type() == ldns.LDNS_RDF_TYPE_DNAME): + print("RDF owner: type=",rdf.get_type_str(),"data=",name2utf(str(rdf))) + else: + print("RDF owner: type=",rdf.get_type_str(),"data=",str(rdf)) + print(" RR type=", rr.get_type_str()," ttl=",rr.ttl()) + for rdf in rr.rdfs(): + if (rdf.get_type() == ldns.LDNS_RDF_TYPE_DNAME): + print(" RDF: type=",rdf.get_type_str(),"data=",name2utf(str(rdf))) + else: + print(" RDF: type=",rdf.get_type_str(),"data=",str(rdf)) + + print() diff --git a/contrib/python/examples/python3/ldns-buf.py b/contrib/python/examples/python3/ldns-buf.py new file mode 100755 index 00000000000..498d51f6c3a --- /dev/null +++ b/contrib/python/examples/python3/ldns-buf.py @@ -0,0 +1,8 @@ +#!/usr/bin/python + +import ldns + +buf = ldns.ldns_buffer(1024) +buf.printf("Test buffer") +print(buf) + diff --git a/contrib/python/examples/python3/ldns-dnssec.py b/contrib/python/examples/python3/ldns-dnssec.py new file mode 100755 index 00000000000..7dabb917902 --- /dev/null +++ b/contrib/python/examples/python3/ldns-dnssec.py @@ -0,0 +1,45 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +import ldns +import sys + +debug = True + +# Check args +argc = len(sys.argv) +name = "www.nic.cz" +if argc < 2: + print("Usage:", sys.argv[0], "domain [resolver_addr]") + sys.exit(1) +else: + name = sys.argv[1] + +# Create resolver +resolver = ldns.ldns_resolver.new_frm_file("/etc/resolv.conf") +resolver.set_dnssec(True) + +# Custom resolver +if argc > 2: + # Clear previous nameservers + ns = resolver.pop_nameserver() + while ns != None: + ns = resolver.pop_nameserver() + ip = ldns.ldns_rdf.new_frm_str(sys.argv[2], ldns.LDNS_RDF_TYPE_A) + resolver.push_nameserver(ip) + +# Resolve DNS name +pkt = resolver.query(name, ldns.LDNS_RR_TYPE_A, ldns.LDNS_RR_CLASS_IN) +if pkt and pkt.answer(): + + # Debug + if debug: + print("NS returned:", pkt.get_rcode(), "(AA: %d AD: %d)" % ( pkt.ad(), pkt.ad() )) + + # SERVFAIL indicated bogus name + if pkt.get_rcode() is ldns.LDNS_RCODE_SERVFAIL: + print(name, "is bogus") + + # Check AD (Authenticated) bit + if pkt.get_rcode() is ldns.LDNS_RCODE_NOERROR: + if pkt.ad(): print(name, "is secure") + else: print(name, "is insecure") diff --git a/contrib/python/examples/python3/ldns-higher.py b/contrib/python/examples/python3/ldns-higher.py new file mode 100755 index 00000000000..8712e63178d --- /dev/null +++ b/contrib/python/examples/python3/ldns-higher.py @@ -0,0 +1,36 @@ +#!/usr/bin/python +import ldns + +resolver = ldns.ldns_resolver.new_frm_file("/etc/resolv.conf") + +dnn = ldns.ldns_dname("www.google.com") +print(dnn.get_type_str(), dnn) + +dna = ldns.ldns_rdf.new_frm_str("74.125.43.99",ldns.LDNS_RDF_TYPE_A) +print(dna.get_type_str(), dna) + +name = resolver.get_name_by_addr(dna) +if (not name): raise Exception("Can't retrieve server name") +for rr in name.rrs(): + print(rr) + +name = resolver.get_name_by_addr("74.125.43.99") +if (not name): raise Exception("Can't retrieve server name") +for rr in name.rrs(): + print(rr) + +addr = resolver.get_addr_by_name(dnn) +if (not addr): raise Exception("Can't retrieve server address") +for rr in addr.rrs(): + print(rr) + +addr = resolver.get_addr_by_name("www.google.com") +if (not addr): raise Exception("Can't retrieve server address") +for rr in addr.rrs(): + print(rr) + +hosts = ldns.ldns_rr_list.new_frm_file("/etc/hosts") +if (not hosts): raise Exception("Can't retrieve the content of file") +for rr in hosts.rrs(): + print(rr) + diff --git a/contrib/python/examples/python3/ldns-keygen.py b/contrib/python/examples/python3/ldns-keygen.py new file mode 100755 index 00000000000..4a5457e4988 --- /dev/null +++ b/contrib/python/examples/python3/ldns-keygen.py @@ -0,0 +1,46 @@ +#!/usr/bin/python +# +# This example shows how to generate public/private key pair +# +import ldns + +algorithm = ldns.LDNS_SIGN_DSA +bits = 512 + +ldns.ldns_init_random(open("/dev/random","rb"), (bits+7)//8) + +domain = ldns.ldns_dname("example.") + +#generate a new key +key = ldns.ldns_key.new_frm_algorithm(algorithm, bits); +print(key) + +#set owner +key.set_pubkey_owner(domain) + +#create the public from the ldns_key +pubkey = key.key_to_rr() +#previous command is equivalent to +# pubkey = ldns.ldns_key2rr(key) +print(pubkey) + +#calculate and set the keytag +key.set_keytag(ldns.ldns_calc_keytag(pubkey)) + +#build the DS record +ds = ldns.ldns_key_rr2ds(pubkey, ldns.LDNS_SHA1) +print(ds) + +owner, tag = pubkey.owner(), key.keytag() + +#write public key to .key file +fw = open("key-%s-%d.key" % (owner,tag), "wb") +pubkey.print_to_file(fw) + +#write private key to .priv file +fw = open("key-%s-%d.private" % (owner,tag), "wb") +key.print_to_file(fw) + +#write DS to .ds file +fw = open("key-%s-%d.ds" % (owner,tag), "wb") +ds.print_to_file(fw) diff --git a/contrib/python/examples/python3/ldns-mx.py b/contrib/python/examples/python3/ldns-mx.py new file mode 100755 index 00000000000..1d2ba03669c --- /dev/null +++ b/contrib/python/examples/python3/ldns-mx.py @@ -0,0 +1,15 @@ +#!/usr/bin/python +# +# MX is a small program that prints out the mx records for a particular domain +# +import ldns + +resolver = ldns.ldns_resolver.new_frm_file("/etc/resolv.conf") + +pkt = resolver.query("nic.cz", ldns.LDNS_RR_TYPE_MX,ldns.LDNS_RR_CLASS_IN) + +if (pkt): + mx = pkt.rr_list_by_type(ldns.LDNS_RR_TYPE_MX, ldns.LDNS_SECTION_ANSWER) + if (mx): + mx.sort() + print(mx) diff --git a/contrib/python/examples/python3/ldns-mx1.py b/contrib/python/examples/python3/ldns-mx1.py new file mode 100755 index 00000000000..d10863e3936 --- /dev/null +++ b/contrib/python/examples/python3/ldns-mx1.py @@ -0,0 +1,18 @@ +#!/usr/bin/python +# +# MX is a small program that prints out the mx records for a particular domain +# +import ldns + +dname = ldns.ldns_dname("nic.cz") +print(dname) + +resolver = ldns.ldns_resolver.new_frm_file("/etc/resolv.conf") + +pkt = resolver.query(dname, ldns.LDNS_RR_TYPE_MX,ldns.LDNS_RR_CLASS_IN) + +if (pkt): + mx = pkt.rr_list_by_type(ldns.LDNS_RR_TYPE_MX, ldns.LDNS_SECTION_ANSWER) + if (mx): + mx.sort() + print(mx) diff --git a/contrib/python/examples/python3/ldns-mx2.py b/contrib/python/examples/python3/ldns-mx2.py new file mode 100755 index 00000000000..9c8b103bf13 --- /dev/null +++ b/contrib/python/examples/python3/ldns-mx2.py @@ -0,0 +1,19 @@ +#!/usr/bin/python +# +# MX is a small program that prints out the mx records for a particular domain +# +import ldns + +resolver = ldns.ldns_resolver.new_frm_file("/etc/resolv.conf") + +pkt = resolver.query("nic.cz", ldns.LDNS_RR_TYPE_MX,ldns.LDNS_RR_CLASS_IN) +if (pkt) and (pkt.answer()): + + for rr in pkt.answer().rrs(): + if (rr.get_type() != ldns.LDNS_RR_TYPE_MX): + continue + + rdf = rr.owner() + print(rdf," ",rr.ttl()," ",rr.get_class_str()," ",rr.get_type_str()," ", end=" ") + print(" ".join(str(rdf) for rdf in rr.rdfs())) + diff --git a/contrib/python/examples/python3/ldns-newpkt.py b/contrib/python/examples/python3/ldns-newpkt.py new file mode 100755 index 00000000000..49bad5ef77e --- /dev/null +++ b/contrib/python/examples/python3/ldns-newpkt.py @@ -0,0 +1,17 @@ +#!/usr/bin/python + +import ldns + +pkt = ldns.ldns_pkt.new_query_frm_str("www.google.com",ldns.LDNS_RR_TYPE_ANY, ldns.LDNS_RR_CLASS_IN, ldns.LDNS_QR | ldns.LDNS_AA) + +rra = ldns.ldns_rr.new_frm_str("www.google.com. IN A 192.168.1.1",300) +rrb = ldns.ldns_rr.new_frm_str("www.google.com. IN TXT Some\ Description",300) + +list = ldns.ldns_rr_list() +if (rra): list.push_rr(rra) +if (rrb): list.push_rr(rrb) + +pkt.push_rr_list(ldns.LDNS_SECTION_ANSWER, list) + +print("Packet:") +print(pkt) diff --git a/contrib/python/examples/python3/ldns-zone.py b/contrib/python/examples/python3/ldns-zone.py new file mode 100755 index 00000000000..b465eaa56bd --- /dev/null +++ b/contrib/python/examples/python3/ldns-zone.py @@ -0,0 +1,15 @@ +#!/usr/bin/python +import ldns + +#Read zone from file +zone = ldns.ldns_zone.new_frm_fp(open("../zone.txt","r"), None, 0, ldns.LDNS_RR_CLASS_IN) +print(zone) + +print("SOA:", zone.soa()) +for r in zone.rrs().rrs(): + print("RR:", r) + + +zone = ldns.ldns_zone() +#print zone + diff --git a/contrib/python/examples/python3/ldns_rr_iter_frm_fp_l.demo.py b/contrib/python/examples/python3/ldns_rr_iter_frm_fp_l.demo.py new file mode 100644 index 00000000000..18edd1109bf --- /dev/null +++ b/contrib/python/examples/python3/ldns_rr_iter_frm_fp_l.demo.py @@ -0,0 +1,12 @@ +import ldns +import sys + +if len(sys.argv) <= 1: + print("Usage: %s zone_file" % sys.argv[0]) + sys.exit() + +inp = open(sys.argv[1],"r"); +for rr in ldns.ldns_rr_iter_frm_fp_l(inp): + print(rr) + +inp.close() diff --git a/contrib/python/examples/python3/ldns_rr_new_frm_fp_l.demo.py b/contrib/python/examples/python3/ldns_rr_new_frm_fp_l.demo.py new file mode 100644 index 00000000000..1bd667b027c --- /dev/null +++ b/contrib/python/examples/python3/ldns_rr_new_frm_fp_l.demo.py @@ -0,0 +1,43 @@ +import ldns +import sys + +if len(sys.argv) <= 1: + print("Usage: %s zone_file" % sys.argv[0]) + sys.exit() + +inp = open(sys.argv[1],"r"); +# variables that preserve the parsers state +my_ttl = 3600; +my_origin = None +my_prev = None +# additional state variables +last_pos = 0 +line_nr = 0 + +while True: + ret = ldns.ldns_rr_new_frm_fp_l_(inp, my_ttl, my_origin, my_prev) + s, rr, line_inc, new_ttl, new_origin, new_prev = ret # unpack the result + line_nr += line_inc # increase number of parsed lines + my_prev = new_prev # update ref to previous owner + + if s == ldns.LDNS_STATUS_SYNTAX_TTL: + my_ttl = new_ttl # update default TTL + print("$TTL:", my_ttl) + elif s == ldns.LDNS_STATUS_SYNTAX_ORIGIN: + my_origin = new_origin # update reference to origin + print("$ORIGIN:", my_origin) + elif s == ldns.LDNS_STATUS_SYNTAX_EMPTY: + if last_pos == inp.tell(): + break # no advance since last read - EOF + last_pos = inp.tell() + elif s != ldns.LDNS_STATUS_OK: + print("! parse error in line", line_nr) + else: + # we are sure to have LDNS_STATUS_OK + print(rr) + +inp.close() +print("--------------------") +print("Read %d lines" % line_nr) + + diff --git a/contrib/python/examples/zone.txt b/contrib/python/examples/zone.txt new file mode 100644 index 00000000000..ffc87263f12 --- /dev/null +++ b/contrib/python/examples/zone.txt @@ -0,0 +1,15 @@ +$ORIGIN example. +$TTL 600 + +example. IN SOA example. admin.example. ( + 2008022501 ; serial + 28800 ; refresh (8 hours) + 7200 ; retry (2 hours) + 604800 ; expire (1 week) + 18000 ; minimum (5 hours) + ) + +@ IN MX 10 mail.example. +@ IN NS ns1 +@ IN NS ns2 +@ IN A 192.168.1.1 diff --git a/contrib/python/file_py3.i b/contrib/python/file_py3.i new file mode 100644 index 00000000000..b3f55e82ab5 --- /dev/null +++ b/contrib/python/file_py3.i @@ -0,0 +1,120 @@ +/* + * file_py3.i: Typemaps for FILE* for Python 3 + * + * Copyright (c) 2011, Karel Slany (karel.slany AT nic.cz) + * 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 the organization 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 +#include +%} + +%types(FILE *); + +/* converts basic file descriptor flags onto a string */ +%fragment("fdfl_to_str", "header") { +const char * +fdfl_to_str(int fdfl) { + + static const char * const file_mode[] = {"w+", "w", "r"}; + + if (fdfl & O_RDWR) { + return file_mode[0]; + } else if (fdfl & O_WRONLY) { + return file_mode[1]; + } else { + return file_mode[2]; + } +} +} + +%fragment("obj_to_file","header", fragment="fdfl_to_str") { +FILE * +obj_to_file(PyObject *obj) { +%#if PY_VERSION_HEX >= 0x03000000 + int fd, fdfl; + FILE *fp; + if (!PyLong_Check(obj) && /* is not an integer */ + PyObject_HasAttrString(obj, "fileno") && /* has fileno method */ + (PyObject_CallMethod(obj, "flush", NULL) != NULL) && /* flush() succeeded */ + ((fd = PyObject_AsFileDescriptor(obj)) != -1) && /* got file descriptor */ + ((fdfl = fcntl(fd, F_GETFL)) != -1) /* got descriptor flags */ + ) { + fp = fdopen(dup(fd), fdfl_to_str(fdfl)); /* the FILE* must be flushed + and closed after being used */ +#ifdef SWIG_FILE3_DEBUG + fprintf(stderr, "opening fd %d (fl %d \"%s\") as FILE %p\n", + fd, fdfl, fdfl_to_str(fdfl), (void *)fp); +#endif + return fp; + } +%#endif + return NULL; +} +} + +/* returns -1 if error occurred */ +%fragment("dispose_file", "header") { +int +dispose_file(FILE **fp) { +#ifdef SWIG_FILE3_DEBUG + fprintf(stderr, "flushing FILE %p\n", (void *)fp); +#endif + if (*fp == NULL) { + return 0; + } + if ((fflush(*fp) == 0) && /* flush file */ + (fclose(*fp) == 0)) { /* close file */ + *fp = NULL; + return 0; + } + return -1; +} +} + +%typemap(arginit, noblock = 1) FILE* { + $1 = NULL; +} + +%typemap(check, noblock = 1) FILE* { + if ($1 == NULL) { + SWIG_exception_fail(SWIG_ValueError, "in method '" "$symname" "', argument " + "$argnum"" of type '" "$type""'"); + } +} + +%typemap(in, noblock = 1, fragment = "obj_to_file") FILE* { + $1 = obj_to_file($input); +} + +%typemap(freearg, noblock = 1, fragment = "dispose_file") FILE* { + if (dispose_file(&$1) == -1) { + SWIG_exception_fail(SWIG_IOError, "closing file in method '" "$symname" "', argument " + "$argnum"" of type '" "$type""'"); + } +} diff --git a/contrib/python/ldns.i b/contrib/python/ldns.i new file mode 100644 index 00000000000..122ebe18e0a --- /dev/null +++ b/contrib/python/ldns.i @@ -0,0 +1,362 @@ +/* + * ldns.i: LDNS interface file + * + * Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz) + * Karel Slany (slany AT fit.vutbr.cz) + * 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 the organization 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. + */ + +%module ldns +#pragma SWIG nowarn=454 +%{ + +#include "ldns.h" +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +%} + +//#define LDNS_DEBUG +//#define SWIG_FILE3_DEBUG + +%include "stdint.i" // uint_16_t is known type now +#ifdef PY3 +%include "file_py3.i" // python 3 FILE * +#else +%include "file.i" // FILE * +#endif +%include "typemaps.i" + +%inline %{ +struct timeval* ldns_make_timeval(uint32_t sec, uint32_t usec) +{ + struct timeval* res = (struct timeval*)malloc(sizeof(*res)); + res->tv_sec = sec; + res->tv_usec = usec; + return res; +} +uint32_t ldns_read_timeval_sec(struct timeval* t) { + return (uint32_t)t->tv_sec; } +uint32_t ldns_read_timeval_usec(struct timeval* t) { + return (uint32_t)t->tv_usec; } +%} + +%immutable ldns_struct_lookup_table::name; +%immutable ldns_struct_rr_descriptor::_name; +%immutable ldns_error_str; +%immutable ldns_signing_algorithms; + +//new_frm_fp_l +%apply int *OUTPUT { int *line_nr}; +%apply uint32_t *OUTPUT { uint32_t *default_ttl}; + +// wire2pkt +%apply (char *STRING, int LENGTH) { (const char *str, int len) }; + +%include "ldns_packet.i" +%include "ldns_resolver.i" +%include "ldns_rr.i" + +%inline %{ +int Python_str_Check(PyObject *o) { +#if PY_VERSION_HEX>=0x03000000 + return PyUnicode_Check(o); +#else + return PyString_Check(o); +#endif +} +%} + +%include "ldns_rdf.i" +%include "ldns_zone.i" +%include "ldns_key.i" +%include "ldns_buffer.i" +%include "ldns_dnssec.i" + +%include + %include +%include +%include + %include +%include +%include + %include + %include +%include + %include + %include + %include + %include +%include +%include + %include +%include + %include + %include +%include + %include + %include +%include + %include + +typedef struct ldns_dnssec_name { }; +typedef struct ldns_dnssec_rrs { }; +typedef struct ldns_dnssec_rrsets { }; +typedef struct ldns_dnssec_zone { }; +// ================================================================================ + +%include "ldns_dname.i" + +%inline %{ + PyObject* ldns_rr_new_frm_str_(const char *str, uint32_t default_ttl, ldns_rdf* origin, ldns_rdf* prev) + //returns tuple (status, ldns_rr, prev) + { + PyObject* tuple; + + /* origin and prev have to be cloned in order to decouple the data + * from the python wrapper + */ + if (origin != NULL) + origin = ldns_rdf_clone(origin); + if (prev != NULL) + prev = ldns_rdf_clone(prev); + + ldns_rdf *p_prev = prev; + ldns_rdf **pp_prev = &p_prev; + if (p_prev == 0) pp_prev = 0; + + ldns_rr *p_rr = 0; + ldns_rr **pp_rr = &p_rr; + + ldns_status st = ldns_rr_new_frm_str(pp_rr, str, default_ttl, origin, pp_prev); + + tuple = PyTuple_New(3); + PyTuple_SetItem(tuple, 0, SWIG_From_int(st)); + PyTuple_SetItem(tuple, 1, (st == LDNS_STATUS_OK) ? + SWIG_NewPointerObj(SWIG_as_voidptr(p_rr), SWIGTYPE_p_ldns_struct_rr, SWIG_POINTER_OWN | 0 ) : + (Py_INCREF(Py_None), Py_None)); + PyTuple_SetItem(tuple, 2, (p_prev != prev) ? + SWIG_NewPointerObj(SWIG_as_voidptr(p_prev), SWIGTYPE_p_ldns_struct_rdf, SWIG_POINTER_OWN | 0 ) : + (Py_INCREF(Py_None), Py_None)); + return tuple; + } + + PyObject* ldns_rr_new_frm_fp_l_(FILE *fp, uint32_t default_ttl, ldns_rdf* origin, ldns_rdf* prev) + //returns tuple (status, ldns_rr, [line if ret_linenr], ttl, origin, prev) + { + int linenr = 0; + int *p_linenr = &linenr; + + uint32_t defttl = default_ttl; + uint32_t *p_defttl = &defttl; + if (defttl == 0) p_defttl = 0; + + /* origin and prev have to be cloned in order to decouple the data + * from the python wrapper + */ + if (origin != NULL) + origin = ldns_rdf_clone(origin); + if (prev != NULL) + prev = ldns_rdf_clone(prev); + + ldns_rdf *p_origin = origin; + ldns_rdf **pp_origin = &p_origin; + //if (p_origin == 0) pp_origin = 0; + + ldns_rdf *p_prev = prev; + ldns_rdf **pp_prev = &p_prev; + //if (p_prev == 0) pp_prev = 0; + + ldns_rr *p_rr = 0; + ldns_rr **pp_rr = &p_rr; + + ldns_status st = ldns_rr_new_frm_fp_l(pp_rr, fp, p_defttl, pp_origin, pp_prev, p_linenr); + + PyObject* tuple; + tuple = PyTuple_New(6); + int idx = 0; + PyTuple_SetItem(tuple, idx, SWIG_From_int(st)); + idx++; + PyTuple_SetItem(tuple, idx, (st == LDNS_STATUS_OK) ? + SWIG_NewPointerObj(SWIG_as_voidptr(p_rr), SWIGTYPE_p_ldns_struct_rr, SWIG_POINTER_OWN | 0 ) : + (Py_INCREF(Py_None), Py_None)); + idx++; + PyTuple_SetItem(tuple, idx, SWIG_From_int(linenr)); + idx++; + PyTuple_SetItem(tuple, idx, SWIG_From_int(defttl)); + idx++; + PyTuple_SetItem(tuple, idx, SWIG_NewPointerObj(SWIG_as_voidptr(p_origin), SWIGTYPE_p_ldns_struct_rdf, SWIG_POINTER_OWN | 0 )); + idx++; + PyTuple_SetItem(tuple, idx, SWIG_NewPointerObj(SWIG_as_voidptr(p_prev), SWIGTYPE_p_ldns_struct_rdf, SWIG_POINTER_OWN | 0 )); + return tuple; + } + + +PyObject* ldns_rr_new_question_frm_str_(const char *str, ldns_rdf* origin, ldns_rdf* prev) + //returns tuple (status, ldns_rr, prev) + { + PyObject* tuple; + + /* origin and prev have to be cloned in order to decouple the data + * from the python wrapper + */ + if (origin != NULL) + origin = ldns_rdf_clone(origin); + if (prev != NULL) + prev = ldns_rdf_clone(prev); + + ldns_rdf *p_prev = prev; + ldns_rdf **pp_prev = &p_prev; + if (p_prev == 0) pp_prev = 0; + + ldns_rr *p_rr = 0; + ldns_rr **pp_rr = &p_rr; + + ldns_status st = ldns_rr_new_question_frm_str(pp_rr, str, origin, pp_prev); + + tuple = PyTuple_New(3); + PyTuple_SetItem(tuple, 0, SWIG_From_int(st)); + PyTuple_SetItem(tuple, 1, (st == LDNS_STATUS_OK) ? + SWIG_NewPointerObj(SWIG_as_voidptr(p_rr), SWIGTYPE_p_ldns_struct_rr, SWIG_POINTER_OWN | 0 ) : + (Py_INCREF(Py_None), Py_None)); + PyTuple_SetItem(tuple, 2, (p_prev != prev) ? + SWIG_NewPointerObj(SWIG_as_voidptr(p_prev), SWIGTYPE_p_ldns_struct_rdf, SWIG_POINTER_OWN | 0 ) : + (Py_INCREF(Py_None), Py_None)); + return tuple; + } + + + +PyObject* ldns_fetch_valid_domain_keys_(const ldns_resolver * res, const ldns_rdf * domain, + const ldns_rr_list * keys) + //returns tuple (status, result) + { + PyObject* tuple; + + ldns_rr_list *rrl = 0; + ldns_status st = 0; + rrl = ldns_fetch_valid_domain_keys(res, domain, keys, &st); + + + tuple = PyTuple_New(2); + PyTuple_SetItem(tuple, 0, SWIG_From_int(st)); + PyTuple_SetItem(tuple, 1, (st == LDNS_STATUS_OK) ? + SWIG_NewPointerObj(SWIG_as_voidptr(rrl), SWIGTYPE_p_ldns_struct_rr_list, SWIG_POINTER_OWN | 0 ) : + (Py_INCREF(Py_None), Py_None)); + return tuple; + } + +PyObject* ldns_wire2pkt_(const char *str, int len) + //returns tuple (status, result) + { + PyObject *resultobj = 0; + ldns_pkt *arg1 = NULL; + uint8_t *arg2 = (uint8_t *) str; + size_t arg3 = (size_t) len; + ldns_status result; + PyObject* tuple; + + result = (ldns_status)ldns_wire2pkt(&arg1,arg2,arg3); + tuple = PyTuple_New(2); + PyTuple_SetItem(tuple, 0, SWIG_From_int(result)); + if (result == LDNS_STATUS_OK) + PyTuple_SetItem(tuple, 1, SWIG_NewPointerObj(SWIG_as_voidptr(arg1), SWIGTYPE_p_ldns_struct_pkt, SWIG_POINTER_OWN | 0 )); + else { + Py_INCREF(Py_None); + PyTuple_SetItem(tuple, 1, Py_None); + } + return tuple; +} + +%} + +%pythoncode %{ +def ldns_fetch_valid_domain_keys(res, domain, keys): + return _ldns.ldns_fetch_valid_domain_keys_(res, domain, keys) + +def ldns_wire2pkt(data): + return _ldns.ldns_wire2pkt_(data) + +def ldns_rr_iter_frm_fp_l(input_file): + """Creates an iterator (generator) that returns individual parsed + RRs from an open zone file.""" + # variables that preserve the parsers state + my_ttl = 0; + my_origin = None + my_prev = None + # additional state variables + last_pos = 0 + line_nr = 0 + + while True: + ret = _ldns.ldns_rr_new_frm_fp_l_(input_file, my_ttl, my_origin, my_prev) + s, rr, line_inc, new_ttl, new_origin, new_prev = ret # unpack the result + line_nr += line_inc # increase number of parsed lines + my_prev = new_prev # update ref to previous owner + + if s == _ldns.LDNS_STATUS_SYNTAX_TTL: + my_ttl = new_ttl # update default TTL + elif s == _ldns.LDNS_STATUS_SYNTAX_ORIGIN: + my_origin = new_origin # update reference to origin + elif s == _ldns.LDNS_STATUS_SYNTAX_EMPTY: + if last_pos == input_file.tell(): + break # no advance since last read - EOF + last_pos = input_file.tell() + elif s != _ldns.LDNS_STATUS_OK: + raise ValueError("Parse error in line %d" % line_nr) + else: + # we are sure to have LDNS_STATUS_OK + yield rr + +%} diff --git a/contrib/python/ldns_buffer.i b/contrib/python/ldns_buffer.i new file mode 100644 index 00000000000..1e743c00780 --- /dev/null +++ b/contrib/python/ldns_buffer.i @@ -0,0 +1,565 @@ +/****************************************************************************** + * ldns_buffer.i: LDNS buffer class + * + * Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz) + * Karel Slany (slany AT fit.vutbr.cz) + * 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 the organization 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. + ******************************************************************************/ + +%typemap(in,numinputs=0,noblock=1) (ldns_buffer **) +{ + ldns_buffer *$1_buf; + $1 = &$1_buf; +} + +/* result generation */ +%typemap(argout,noblock=1) (ldns_buffer **) +{ + $result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(SWIG_as_voidptr($1_buf), SWIGTYPE_p_ldns_struct_buffer, SWIG_POINTER_OWN | 0 )); +} + +%nodefaultctor ldns_struct_buffer; //no default constructor & destructor +%nodefaultdtor ldns_struct_buffer; + +%delobject ldns_buffer_free; +%newobject ldns_buffer_new; +%newobject ldns_dname_new; +%newobject ldns_dname_new_frm_data; +%newobject ldns_dname_label; + +# limit the number of arguments to 2 and +# deal with variable number of arguments the Python way +%varargs(2, char *arg = NULL) ldns_buffer_printf; + +%rename(ldns_buffer) ldns_struct_buffer; + +#ifdef LDNS_DEBUG +%rename(__ldns_buffer_free) ldns_buffer_free; +%inline %{ +void _ldns_buffer_free (ldns_buffer* b) { + printf("******** LDNS_BUFFER free 0x%lX ************\n", (long unsigned int)b); + ldns_buffer_free(b); +} +%} +#else +%rename(_ldns_buffer_free) ldns_buffer_free; +#endif + +%ignore ldns_struct_buffer::_position; +%ignore ldns_struct_buffer::_limit; +%ignore ldns_struct_buffer::_capacity; +%ignore ldns_struct_buffer::_data; +%ignore ldns_struct_buffer::_fixed; +%ignore ldns_struct_buffer::_status; + +%extend ldns_struct_buffer { + + %pythoncode %{ + def __init__(self, capacity): + """Creates a new buffer with the specified capacity. + + :param capacity: the size (in bytes) to allocate for the buffer + """ + self.this = _ldns.ldns_buffer_new(capacity) + + __swig_destroy__ = _ldns._ldns_buffer_free + + def __str__(self): + """Returns the data in the buffer as a string. Buffer data must be char * type.""" + return _ldns.ldns_buffer2str(self) + + def getc(self): + """returns the next character from a buffer. + + Advances the position pointer with 1. When end of buffer is reached returns EOF. This is the buffer's equivalent for getc(). + + :returns: (int) EOF on failure otherwise return the character + """ + return _ldns.ldns_bgetc(self) + + #LDNS_BUFFER_METHODS_# + def at(self,at): + """returns a pointer to the data at the indicated position. + + :param at: + position + :returns: (uint8_t \*) the pointer to the data + """ + return _ldns.ldns_buffer_at(self,at) + #parameters: const ldns_buffer *,size_t, + #retvals: uint8_t * + + def available(self,count): + """checks if the buffer has count bytes available at the current position + + :param count: + how much is available + :returns: (int) true or false + """ + return _ldns.ldns_buffer_available(self,count) + #parameters: ldns_buffer *,size_t, + #retvals: int + + def available_at(self,at,count): + """checks if the buffer has at least COUNT more bytes available. + + Before reading or writing the caller needs to ensure enough space is available! + + :param at: + indicated position + :param count: + how much is available + :returns: (int) true or false + """ + return _ldns.ldns_buffer_available_at(self,at,count) + #parameters: ldns_buffer *,size_t,size_t, + #retvals: int + + def begin(self): + """returns a pointer to the beginning of the buffer (the data at position 0). + + :returns: (uint8_t \*) the pointer + """ + return _ldns.ldns_buffer_begin(self) + #parameters: const ldns_buffer *, + #retvals: uint8_t * + + def capacity(self): + """returns the number of bytes the buffer can hold. + + :returns: (size_t) the number of bytes + """ + return _ldns.ldns_buffer_capacity(self) + #parameters: ldns_buffer *, + #retvals: size_t + + def clear(self): + """clears the buffer and make it ready for writing. + + The buffer's limit is set to the capacity and the position is set to 0. + """ + _ldns.ldns_buffer_clear(self) + #parameters: ldns_buffer *, + #retvals: + + def copy(self,bfrom): + """Copy contents of the other buffer to this buffer. + + Silently truncated if this buffer is too small. + + :param bfrom: other buffer + """ + _ldns.ldns_buffer_copy(self,bfrom) + #parameters: ldns_buffer *,ldns_buffer *, + #retvals: + + def current(self): + """returns a pointer to the data at the buffer's current position. + + :returns: (uint8_t \*) the pointer + """ + return _ldns.ldns_buffer_current(self) + #parameters: ldns_buffer *, + #retvals: uint8_t * + + def end(self): + """returns a pointer to the end of the buffer (the data at the buffer's limit). + + :returns: (uint8_t \*) the pointer + """ + return _ldns.ldns_buffer_end(self) + #parameters: ldns_buffer *, + #retvals: uint8_t * + + def export(self): + """Makes the buffer fixed and returns a pointer to the data. + + The caller is responsible for free'ing the result. + + :returns: (void \*) void + """ + return _ldns.ldns_buffer_export(self) + #parameters: ldns_buffer *, + #retvals: void * + + def flip(self): + """makes the buffer ready for reading the data that has been written to the buffer. + + The buffer's limit is set to the current position and the position is set to 0. + """ + _ldns.ldns_buffer_flip(self) + #parameters: ldns_buffer *, + + def invariant(self): + _ldns.ldns_buffer_invariant(self) + #parameters: ldns_buffer *, + + def limit(self): + """returns the maximum size of the buffer + + :returns: (size_t) the size + """ + return _ldns.ldns_buffer_limit(self) + #parameters: ldns_buffer *, + #retvals: size_t + + def position(self): + """returns the current position in the buffer (as a number of bytes) + + :returns: (size_t) the current position + """ + return _ldns.ldns_buffer_position(self) + #parameters: ldns_buffer *, + #retvals: size_t + + def printf(self, str, *args): + """Prints to the buffer, increasing the capacity if required using buffer_reserve(). + + The buffer's position is set to the terminating '\0'. Returns the number of characters written (not including the terminating '\0') or -1 on failure. + :param str: a string + :returns: (int) + """ + data = str % args + return _ldns.ldns_buffer_printf(self,data) + #parameters: ldns_buffer *,const char *,... + #retvals: int + + def read(self,data,count): + """copies count bytes of data at the current position to the given data-array + + :param data: + buffer to copy to + :param count: + the length of the data to copy + """ + _ldns.ldns_buffer_read(self,data,count) + #parameters: ldns_buffer *,void *,size_t, + #retvals: + + def read_at(self,at,data,count): + """copies count bytes of data at the given position to the given data-array + + :param at: + the position in the buffer to start + :param data: + buffer to copy to + :param count: + the length of the data to copy + """ + _ldns.ldns_buffer_read_at(self,at,data,count) + #parameters: ldns_buffer *,size_t,void *,size_t, + #retvals: + + def read_u16(self): + """returns the 2-byte integer value at the current position in the buffer + + :returns: (uint16_t) 2 byte integer + """ + return _ldns.ldns_buffer_read_u16(self) + #parameters: ldns_buffer *, + #retvals: uint16_t + + def read_u16_at(self,at): + """returns the 2-byte integer value at the given position in the buffer + + :param at: + position in the buffer + :returns: (uint16_t) 2 byte integer + """ + return _ldns.ldns_buffer_read_u16_at(self,at) + #parameters: ldns_buffer *,size_t, + #retvals: uint16_t + + def read_u32(self): + """returns the 4-byte integer value at the current position in the buffer + + :returns: (uint32_t) 4 byte integer + """ + return _ldns.ldns_buffer_read_u32(self) + #parameters: ldns_buffer *, + #retvals: uint32_t + + def read_u32_at(self,at): + """returns the 4-byte integer value at the given position in the buffer + + :param at: + position in the buffer + :returns: (uint32_t) 4 byte integer + """ + return _ldns.ldns_buffer_read_u32_at(self,at) + #parameters: ldns_buffer *,size_t, + #retvals: uint32_t + + def read_u8(self): + """returns the byte value at the current position in the buffer + + :returns: (uint8_t) 1 byte integer + """ + return _ldns.ldns_buffer_read_u8(self) + #parameters: ldns_buffer *, + #retvals: uint8_t + + def read_u8_at(self,at): + """returns the byte value at the given position in the buffer + + :param at: + the position in the buffer + :returns: (uint8_t) 1 byte integer + """ + return _ldns.ldns_buffer_read_u8_at(self,at) + #parameters: ldns_buffer *,size_t, + #retvals: uint8_t + + def remaining(self): + """returns the number of bytes remaining between the buffer's position and limit. + + :returns: (size_t) the number of bytes + """ + return _ldns.ldns_buffer_remaining(self) + #parameters: ldns_buffer *, + #retvals: size_t + + def remaining_at(self,at): + """returns the number of bytes remaining between the indicated position and the limit. + + :param at: + indicated position + :returns: (size_t) number of bytes + """ + return _ldns.ldns_buffer_remaining_at(self,at) + #parameters: ldns_buffer *,size_t, + #retvals: size_t + + def reserve(self,amount): + """ensures BUFFER can contain at least AMOUNT more bytes. + + The buffer's capacity is increased if necessary using buffer_set_capacity(). + + The buffer's limit is always set to the (possibly increased) capacity. + + :param amount: + amount to use + :returns: (bool) whether this failed or succeeded + """ + return _ldns.ldns_buffer_reserve(self,amount) + #parameters: ldns_buffer *,size_t, + #retvals: bool + + def rewind(self): + """make the buffer ready for re-reading the data. + + The buffer's position is reset to 0. + """ + _ldns.ldns_buffer_rewind(self) + #parameters: ldns_buffer *, + #retvals: + + def set_capacity(self,capacity): + """changes the buffer's capacity. + + The data is reallocated so any pointers to the data may become invalid. The buffer's limit is set to the buffer's new capacity. + + :param capacity: + the capacity to use + :returns: (bool) whether this failed or succeeded + """ + return _ldns.ldns_buffer_set_capacity(self,capacity) + #parameters: ldns_buffer *,size_t, + #retvals: bool + + def set_limit(self,limit): + """changes the buffer's limit. + + If the buffer's position is greater than the new limit the position is set to the limit. + + :param limit: + the new limit + """ + _ldns.ldns_buffer_set_limit(self,limit) + #parameters: ldns_buffer *,size_t, + #retvals: + + def set_position(self,mark): + """sets the buffer's position to MARK. + + The position must be less than or equal to the buffer's limit. + + :param mark: + the mark to use + """ + _ldns.ldns_buffer_set_position(self,mark) + #parameters: ldns_buffer *,size_t, + #retvals: + + def skip(self,count): + """changes the buffer's position by COUNT bytes. + + The position must not be moved behind the buffer's limit or before the beginning of the buffer. + + :param count: + the count to use + """ + _ldns.ldns_buffer_skip(self,count) + #parameters: ldns_buffer *,ssize_t, + #retvals: + + def status(self): + """returns the status of the buffer + + :returns: (ldns_status) the status + """ + return _ldns.ldns_buffer_status(self) + #parameters: ldns_buffer *, + #retvals: ldns_status + + def status_ok(self): + """returns true if the status of the buffer is LDNS_STATUS_OK, false otherwise + + :returns: (bool) true or false + """ + return _ldns.ldns_buffer_status_ok(self) + #parameters: ldns_buffer *, + #retvals: bool + + def write(self,data,count): + """writes count bytes of data to the current position of the buffer + + :param data: + the data to write + :param count: + the lenght of the data to write + """ + _ldns.ldns_buffer_write(self,data,count) + #parameters: ldns_buffer *,const void *,size_t, + #retvals: + + def write_at(self,at,data,count): + """writes the given data to the buffer at the specified position + + :param at: + the position (in number of bytes) to write the data at + :param data: + pointer to the data to write to the buffer + :param count: + the number of bytes of data to write + """ + _ldns.ldns_buffer_write_at(self,at,data,count) + #parameters: ldns_buffer *,size_t,const void *,size_t, + #retvals: + + def write_string(self,str): + """copies the given (null-delimited) string to the current position at the buffer + + :param str: + the string to write + """ + _ldns.ldns_buffer_write_string(self,str) + #parameters: ldns_buffer *,const char *, + #retvals: + + def write_string_at(self,at,str): + """copies the given (null-delimited) string to the specified position at the buffer + + :param at: + the position in the buffer + :param str: + the string to write + """ + _ldns.ldns_buffer_write_string_at(self,at,str) + #parameters: ldns_buffer *,size_t,const char *, + #retvals: + + def write_u16(self,data): + """writes the given 2 byte integer at the current position in the buffer + + :param data: + the 16 bits to write + """ + _ldns.ldns_buffer_write_u16(self,data) + #parameters: ldns_buffer *,uint16_t, + #retvals: + + def write_u16_at(self,at,data): + """writes the given 2 byte integer at the given position in the buffer + + :param at: + the position in the buffer + :param data: + the 16 bits to write + """ + _ldns.ldns_buffer_write_u16_at(self,at,data) + #parameters: ldns_buffer *,size_t,uint16_t, + #retvals: + + def write_u32(self,data): + """writes the given 4 byte integer at the current position in the buffer + + :param data: + the 32 bits to write + """ + _ldns.ldns_buffer_write_u32(self,data) + #parameters: ldns_buffer *,uint32_t, + #retvals: + + def write_u32_at(self,at,data): + """writes the given 4 byte integer at the given position in the buffer + + :param at: + the position in the buffer + :param data: + the 32 bits to write + """ + _ldns.ldns_buffer_write_u32_at(self,at,data) + #parameters: ldns_buffer *,size_t,uint32_t, + #retvals: + + def write_u8(self,data): + """writes the given byte of data at the current position in the buffer + + :param data: + the 8 bits to write + """ + _ldns.ldns_buffer_write_u8(self,data) + #parameters: ldns_buffer *,uint8_t, + #retvals: + + def write_u8_at(self,at,data): + """writes the given byte of data at the given position in the buffer + + :param at: + the position in the buffer + :param data: + the 8 bits to write + """ + _ldns.ldns_buffer_write_u8_at(self,at,data) + #parameters: ldns_buffer *,size_t,uint8_t, + #retvals: + + #_LDNS_BUFFER_METHODS# + %} +} + diff --git a/contrib/python/ldns_dname.i b/contrib/python/ldns_dname.i new file mode 100644 index 00000000000..0aac54c1060 --- /dev/null +++ b/contrib/python/ldns_dname.i @@ -0,0 +1,196 @@ +/****************************************************************************** + * ldns_dname.i: LDNS domain name class + * + * Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz) + * Karel Slany (slany AT fit.vutbr.cz) + * 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 the organization 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. + ******************************************************************************/ +%pythoncode %{ + class ldns_dname(ldns_rdf): + """Domain name + + This class contains methods to read and manipulate domain names. + Domain names are stored in ldns_rdf structures, with the type LDNS_RDF_TYPE_DNAME + + **Usage** + + >>> import ldns + >>> resolver = ldns.ldns_resolver.new_frm_file("/etc/resolv.conf") + >>> dn1 = ldns.ldns_dname("test.nic.cz") + >>> print dn1 + test.nic.cz. + >>> dn2 = ldns.ldns_dname("nic.cz") + >>> if dn2.is_subdomain(dn1): print dn2,"is subdomain of",dn1 + >>> if dn1.is_subdomain(dn2): print dn1,"is subdomain of",dn2 + test.nic.cz. is subdomain of nic.cz. + """ + def __init__(self, str): + """Creates a new dname rdf from a string. + + :parameter str: str string to use + """ + self.this = _ldns.ldns_dname_new_frm_str(str) + + @staticmethod + def new_frm_str(str): + """Creates a new dname rdf instance from a string. + + This static method is equivalent to using of default class constructor. + + :parameter str: str string to use + """ + return ldns_dname(str) + + def absolute(self): + """Checks whether the given dname string is absolute (i.e. ends with a '.') + + :returns: (bool) True or False + """ + return self.endswith(".") + + + def make_canonical(self): + """Put a dname into canonical fmt - ie. lowercase it + """ + _ldns.ldns_dname2canonical(self) + + def __cmp__(self,other): + """Compares the two dname rdf's according to the algorithm for ordering in RFC4034 Section 6. + + :param other: + the second dname rdf to compare + :returns: (int) -1 if dname comes before other, 1 if dname comes after other, and 0 if they are equal. + """ + return _ldns.ldns_dname_compare(self,other) + + def write_to_buffer(self,buffer): + """Copies the dname data to the buffer in wire format. + + :param buffer: buffer to append the result to + :returns: (ldns_status) ldns_status + """ + return _ldns.ldns_dname2buffer_wire(buffer,self) + #parameters: ldns_buffer *,const ldns_rdf *, + #retvals: ldns_status + + #LDNS_DNAME_METHODS_# + + def cat(self,rd2): + """concatenates rd2 after this dname (rd2 is copied, this dname is modified) + + :param rd2: + the rightside + :returns: (ldns_status) LDNS_STATUS_OK on success + """ + return _ldns.ldns_dname_cat(self,rd2) + #parameters: ldns_rdf *,ldns_rdf *, + #retvals: ldns_status + + def cat_clone(self,rd2): + """concatenates two dnames together + + :param rd2: + the rightside + :returns: (ldns_rdf \*) a new rdf with leftside/rightside + """ + return _ldns.ldns_dname_cat_clone(self,rd2) + #parameters: const ldns_rdf *,const ldns_rdf *, + #retvals: ldns_rdf * + + def interval(self,middle,next): + """check if middle lays in the interval defined by prev and next prev <= middle < next. + + This is usefull for nsec checking + + :param middle: + the dname to check + :param next: + the next dname return 0 on error or unknown, -1 when middle is in the interval, +1 when not + :returns: (int) + """ + return _ldns.ldns_dname_interval(self,middle,next) + #parameters: const ldns_rdf *,const ldns_rdf *,const ldns_rdf *, + #retvals: int + + def is_subdomain(self,parent): + """Tests wether the name sub falls under parent (i.e. is a subdomain of parent). + + This function will return false if the given dnames are equal. + + :param parent: + (ldns_rdf) the parent's name + :returns: (bool) true if sub falls under parent, otherwise false + """ + return _ldns.ldns_dname_is_subdomain(self,parent) + #parameters: const ldns_rdf *,const ldns_rdf *, + #retvals: bool + + def label(self,labelpos): + """look inside the rdf and if it is an LDNS_RDF_TYPE_DNAME try and retrieve a specific label. + + The labels are numbered starting from 0 (left most). + + :param labelpos: + return the label with this number + :returns: (ldns_rdf \*) a ldns_rdf* with the label as name or NULL on error + """ + return _ldns.ldns_dname_label(self,labelpos) + #parameters: const ldns_rdf *,uint8_t, + #retvals: ldns_rdf * + + def label_count(self): + """count the number of labels inside a LDNS_RDF_DNAME type rdf. + + :returns: (uint8_t) the number of labels + """ + return _ldns.ldns_dname_label_count(self) + #parameters: const ldns_rdf *, + #retvals: uint8_t + + def left_chop(self): + """chop one label off the left side of a dname. + + so wwww.nlnetlabs.nl, becomes nlnetlabs.nl + + :returns: (ldns_rdf \*) the remaining dname + """ + return _ldns.ldns_dname_left_chop(self) + #parameters: const ldns_rdf *, + #retvals: ldns_rdf * + + def reverse(self): + """Returns a clone of the given dname with the labels reversed. + + :returns: (ldns_rdf \*) clone of the dname with the labels reversed. + """ + return _ldns.ldns_dname_reverse(self) + #parameters: const ldns_rdf *, + #retvals: ldns_rdf * + + #_LDNS_DNAME_METHODS# +%} + diff --git a/contrib/python/ldns_dnssec.i b/contrib/python/ldns_dnssec.i new file mode 100644 index 00000000000..6c065648466 --- /dev/null +++ b/contrib/python/ldns_dnssec.i @@ -0,0 +1,434 @@ +/****************************************************************************** + * ldns_dnssec.i: DNSSEC zone, name, rrs + * + * Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz) + * Karel Slany (slany AT fit.vutbr.cz) + * 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 the organization 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. + ******************************************************************************/ +%nodefaultctor ldns_dnssec_rrs; //no default constructor & destructor +%nodefaultdtor ldns_dnssec_rrs; + +%newobject ldns_dnssec_rrs_new; +%delobject ldns_dnssec_rrs_free; + +%extend ldns_dnssec_rrs { + %pythoncode %{ + + def __init__(self): + """Creates a new entry for 1 pointer to an rr and 1 pointer to the next rrs. + + :returns: (ldns_dnssec_rrs) the allocated data + """ + self.this = _ldns.ldns_dnssec_rrs_new() + if not self.this: + raise Exception("Can't create rrs instance") + + __swig_destroy__ = _ldns.ldns_dnssec_rrs_free + + #LDNS_DNSSEC_RRS_METHODS_# + def add_rr(self,rr): + """Adds an RR to the list of RRs. + + The list will remain ordered + + :param rr: + the RR to add + :returns: (ldns_status) LDNS_STATUS_OK on success + """ + return _ldns.ldns_dnssec_rrs_add_rr(self,rr) + #parameters: ldns_dnssec_rrs *,ldns_rr *, + #retvals: ldns_status + #_LDNS_DNSSEC_RRS_METHODS# + %} +} + +// ================================================================================ +// DNNSEC RRS +// ================================================================================ +%nodefaultctor ldns_dnssec_rrsets; //no default constructor & destructor +%nodefaultdtor ldns_dnssec_rrsets; + +%newobject ldns_dnssec_rrsets_new; +%delobject ldns_dnssec_rrsets_free; + +%extend ldns_dnssec_rrsets { + %pythoncode %{ + def __init__(self): + """Creates a new list (entry) of RRsets. + + :returns: (ldns_dnssec_rrsets \*) instance + """ + self.this = _ldns.ldns_dnssec_rrsets_new() + if not self.this: + raise Exception("Can't create rrsets instance") + + __swig_destroy__ = _ldns.ldns_dnssec_rrsets_free + + def print_to_file(self, file, follow): + """Print the given list of rrsets to the given file descriptor. + + :param file: file pointer + :param follow: if set to false, only print the first RRset + """ + _ldns.ldns_dnssec_rrsets_print(file,self,follow) + #parameters: FILE *,ldns_dnssec_rrsets *,bool, + #retvals: + + #LDNS_DNSSEC_RRSETS_METHODS_# + def add_rr(self,rr): + """Add an ldns_rr to the corresponding RRset in the given list of RRsets. + + If it is not present, add it as a new RRset with 1 record. + + :param rr: + the rr to add to the list of rrsets + :returns: (ldns_status) LDNS_STATUS_OK on success + """ + return _ldns.ldns_dnssec_rrsets_add_rr(self,rr) + #parameters: ldns_dnssec_rrsets *,ldns_rr *, + #retvals: ldns_status + + def set_type(self,atype): + """Sets the RR type of the rrset (that is head of the given list). + + :param atype: + :returns: (ldns_status) LDNS_STATUS_OK on success + """ + return _ldns.ldns_dnssec_rrsets_set_type(self,atype) + #parameters: ldns_dnssec_rrsets *,ldns_rr_type, + #retvals: ldns_status + + def type(self): + """Returns the rr type of the rrset (that is head of the given list). + + :returns: (ldns_rr_type) the rr type + """ + return _ldns.ldns_dnssec_rrsets_type(self) + #parameters: ldns_dnssec_rrsets *, + #retvals: ldns_rr_type + #_LDNS_DNSSEC_RRSETS_METHODS# + %} +} + +// ================================================================================ +// DNNSEC NAME +// ================================================================================ +%nodefaultctor ldns_dnssec_name; //no default constructor & destructor +%nodefaultdtor ldns_dnssec_name; + +%newobject ldns_dnssec_name_new; +%delobject ldns_dnssec_name_free; + +%extend ldns_dnssec_name { + %pythoncode %{ + def __init__(self): + """Create a new instance of dnssec name.""" + self.this = _ldns.ldns_dnssec_name_new() + if not self.this: + raise Exception("Can't create dnssec name instance") + + __swig_destroy__ = _ldns.ldns_dnssec_name_free + + def print_to_file(self,file): + """Prints the RRs in the dnssec name structure to the given file descriptor. + + :param file: file pointer + """ + _ldns.ldns_dnssec_name_print(file, self) + #parameters: FILE *,ldns_dnssec_name *, + + @staticmethod + def new_frm_rr(raiseException=True): + """Create a new instace of dnssec name for the given RR. + + :returns: (ldns_dnssec_name) instance + """ + name = _ldns.ldns_dnssec_name_new_frm_rr(self) + if (not name) and (raiseException): + raise Exception("Can't create dnssec name") + return name + + #LDNS_DNSSEC_NAME_METHODS_# + def add_rr(self,rr): + """Inserts the given rr at the right place in the current dnssec_name No checking is done whether the name matches. + + :param rr: + The RR to add + :returns: (ldns_status) LDNS_STATUS_OK on success, error code otherwise + """ + return _ldns.ldns_dnssec_name_add_rr(self,rr) + #parameters: ldns_dnssec_name *,ldns_rr *, + #retvals: ldns_status + + def find_rrset(self,atype): + """Find the RRset with the given type in within this name structure. + + :param atype: + :returns: (ldns_dnssec_rrsets \*) the RRset, or NULL if not present + """ + return _ldns.ldns_dnssec_name_find_rrset(self,atype) + #parameters: ldns_dnssec_name *,ldns_rr_type, + #retvals: ldns_dnssec_rrsets * + + def name(self): + """Returns the domain name of the given dnssec_name structure. + + :returns: (ldns_rdf \*) the domain name + """ + return _ldns.ldns_dnssec_name_name(self) + #parameters: ldns_dnssec_name *, + #retvals: ldns_rdf * + + def set_name(self,dname): + """Sets the domain name of the given dnssec_name structure. + + :param dname: + the domain name to set it to. This data is *not* copied. + """ + _ldns.ldns_dnssec_name_set_name(self,dname) + #parameters: ldns_dnssec_name *,ldns_rdf *, + #retvals: + + def set_nsec(self,nsec): + """Sets the NSEC(3) RR of the given dnssec_name structure. + + :param nsec: + the nsec rr to set it to. This data is *not* copied. + """ + _ldns.ldns_dnssec_name_set_nsec(self,nsec) + #parameters: ldns_dnssec_name *,ldns_rr *, + #retvals: + #_LDNS_DNSSEC_NAME_METHODS# + %} +} + +// ================================================================================ +// DNNSEC ZONE +// ================================================================================ +%nodefaultctor ldns_dnssec_zone; //no default constructor & destructor +%nodefaultdtor ldns_dnssec_zone; + +%newobject ldns_dnssec_zone_new; +%delobject ldns_dnssec_zone_free; + +%inline %{ +ldns_status ldns_dnssec_zone_sign_defcb(ldns_dnssec_zone *zone, ldns_rr_list *new_rrs, ldns_key_list *key_list, int cbtype) +{ + if (cbtype == 0) + return ldns_dnssec_zone_sign(zone, new_rrs, key_list, ldns_dnssec_default_add_to_signatures, NULL); + if (cbtype == 1) + return ldns_dnssec_zone_sign(zone, new_rrs, key_list, ldns_dnssec_default_leave_signatures, NULL); + if (cbtype == 2) + return ldns_dnssec_zone_sign(zone, new_rrs, key_list, ldns_dnssec_default_delete_signatures, NULL); + + return ldns_dnssec_zone_sign(zone, new_rrs, key_list, ldns_dnssec_default_replace_signatures, NULL); +} +%} + +%extend ldns_dnssec_zone { + %pythoncode %{ + + def __init__(self): + """Creates a new dnssec_zone instance""" + self.this = _ldns.ldns_dnssec_zone_new() + if not self.this: + raise Exception("Can't create dnssec zone instance") + + __swig_destroy__ = _ldns.ldns_dnssec_zone_free + + def print_to_file(self,file): + """Prints the complete zone to the given file descriptor. + + :param file: file pointer + """ + _ldns.ldns_dnssec_zone_print(file, self) + #parameters: FILE *, ldns_dnssec_zone *, + #retvals: + + def create_nsec3s(self,new_rrs,algorithm,flags,iterations,salt_length,salt): + """Adds NSEC3 records to the zone. + + :param new_rrs: + :param algorithm: + :param flags: + :param iterations: + :param salt_length: + :param salt: + :returns: (ldns_status) + """ + return _ldns.ldns_dnssec_zone_create_nsec3s(self,new_rrs,algorithm,flags,iterations,salt_length,salt) + #parameters: ldns_dnssec_zone *,ldns_rr_list *,uint8_t,uint8_t,uint16_t,uint8_t,uint8_t *, + #retvals: ldns_status + + def create_nsecs(self,new_rrs): + """Adds NSEC records to the given dnssec_zone. + + :param new_rrs: + ldns_rr's created by this function are added to this rr list, so the caller can free them later + :returns: (ldns_status) LDNS_STATUS_OK on success, an error code otherwise + """ + return _ldns.ldns_dnssec_zone_create_nsecs(self,new_rrs) + #parameters: ldns_dnssec_zone *,ldns_rr_list *, + #retvals: ldns_status + + def create_rrsigs(self,new_rrs,key_list,func,arg): + """Adds signatures to the zone. + + :param new_rrs: + the RRSIG RRs that are created are also added to this list, so the caller can free them later + :param key_list: + list of keys to sign with. + :param func: + Callback function to decide what keys to use and what to do with old signatures + :param arg: + Optional argument for the callback function + :returns: (ldns_status) LDNS_STATUS_OK on success, error otherwise + """ + return _ldns.ldns_dnssec_zone_create_rrsigs(self,new_rrs,key_list,func,arg) + #parameters: ldns_dnssec_zone *,ldns_rr_list *,ldns_key_list *,int(*)(ldns_rr *, void *),void *, + #retvals: ldns_status + + def sign_cb(self,new_rrs,key_list,func,arg): + """signs the given zone with the given keys (with callback function) + + :param new_rrs: + newly created resource records are added to this list, to free them later + :param key_list: + the list of keys to sign the zone with + :param func: + callback function that decides what to do with old signatures. + This function takes an ldns_rr and an optional arg argument, and returns one of four values: + + * LDNS_SIGNATURE_LEAVE_ADD_NEW - leave the signature and add a new one for the corresponding key + + * LDNS_SIGNATURE_REMOVE_ADD_NEW - remove the signature and replace is with a new one from the same key + + * LDNS_SIGNATURE_LEAVE_NO_ADD - leave the signature and do not add a new one with the corresponding key + + * LDNS_SIGNATURE_REMOVE_NO_ADD - remove the signature and do not replace + + :param arg: + optional argument for the callback function + :returns: (ldns_status) LDNS_STATUS_OK on success, an error code otherwise + """ + return _ldns.ldns_dnssec_zone_sign(self,new_rrs,key_list,func,arg) + #parameters: ldns_dnssec_zone *,ldns_rr_list *,ldns_key_list *,int(*)(ldns_rr *, void *),void *, + #retvals: ldns_status + + def sign(self,new_rrs,key_list, cbtype=3): + """signs the given zone with the given keys + + :param new_rrs: + newly created resource records are added to this list, to free them later + :param key_list: + the list of keys to sign the zone with + :param cb_type: + specifies how to deal with old signatures, possible values: + + * 0 - ldns_dnssec_default_add_to_signatures, + + * 1 - ldns_dnssec_default_leave_signatures, + + * 2 - ldns_dnssec_default_delete_signatures, + + * 3 - ldns_dnssec_default_replace_signatures + + :returns: (ldns_status) LDNS_STATUS_OK on success, an error code otherwise + """ + return _ldns.ldns_dnssec_zone_sign_defcb(self,new_rrs,key_list, cbtype) + #parameters: ldns_dnssec_zone *,ldns_rr_list *,ldns_key_list *, + #retvals: ldns_status + + def sign_nsec3(self,new_rrs,key_list,func,arg,algorithm,flags,iterations,salt_length,salt): + """signs the given zone with the given new zone, with NSEC3 + + :param new_rrs: + newly created resource records are added to this list, to free them later + :param key_list: + the list of keys to sign the zone with + :param func: + callback function that decides what to do with old signatures + :param arg: + optional argument for the callback function + :param algorithm: + the NSEC3 hashing algorithm to use + :param flags: + NSEC3 flags + :param iterations: + the number of NSEC3 hash iterations to use + :param salt_length: + the length (in octets) of the NSEC3 salt + :param salt: + the NSEC3 salt data + :returns: (ldns_status) LDNS_STATUS_OK on success, an error code otherwise + """ + return _ldns.ldns_dnssec_zone_sign_nsec3(self,new_rrs,key_list,func,arg,algorithm,flags,iterations,salt_length,salt) + #parameters: ldns_dnssec_zone *,ldns_rr_list *,ldns_key_list *,int(*)(ldns_rr *, void *),void *,uint8_t,uint8_t,uint16_t,uint8_t,uint8_t *, + #retvals: ldns_status + + #LDNS_DNSSEC_ZONE_METHODS_# + def add_empty_nonterminals(self): + """Adds explicit dnssec_name structures for the empty nonterminals in this zone. + + (this is needed for NSEC3 generation) + + :returns: (ldns_status) + """ + return _ldns.ldns_dnssec_zone_add_empty_nonterminals(self) + #parameters: ldns_dnssec_zone *, + #retvals: ldns_status + + def add_rr(self,rr): + """Adds the given RR to the zone. + + It find whether there is a dnssec_name with that name present. + If so, add it to that, if not create a new one. + Special handling of NSEC and RRSIG provided. + + :param rr: + The RR to add + :returns: (ldns_status) LDNS_STATUS_OK on success, an error code otherwise + """ + return _ldns.ldns_dnssec_zone_add_rr(self,rr) + #parameters: ldns_dnssec_zone *,ldns_rr *, + #retvals: ldns_status + + def find_rrset(self,dname,atype): + """Find the RRset with the given name and type in the zone. + + :param dname: + the domain name of the RRset to find + :param atype: + :returns: (ldns_dnssec_rrsets \*) the RRset, or NULL if not present + """ + return _ldns.ldns_dnssec_zone_find_rrset(self,dname,atype) + #parameters: ldns_dnssec_zone *,ldns_rdf *,ldns_rr_type, + #retvals: ldns_dnssec_rrsets * + + #_LDNS_DNSSEC_ZONE_METHODS# + %} +} diff --git a/contrib/python/ldns_key.i b/contrib/python/ldns_key.i new file mode 100644 index 00000000000..26a9b0f57fa --- /dev/null +++ b/contrib/python/ldns_key.i @@ -0,0 +1,536 @@ +/****************************************************************************** + * ldns_key.i: LDNS key class + * + * Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz) + * Karel Slany (slany AT fit.vutbr.cz) + * 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 the organization 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. + ******************************************************************************/ +%typemap(in,numinputs=0,noblock=1) (ldns_key **) +{ + ldns_key *$1_key; + $1 = &$1_key; +} + +/* result generation */ +%typemap(argout,noblock=1) (ldns_key **) +{ + $result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(SWIG_as_voidptr($1_key), SWIGTYPE_p_ldns_struct_key, SWIG_POINTER_OWN | 0 )); +} + +%exception ldns_key_set_pubkey_owner(ldns_key *k, ldns_rdf *r) %{ $action Py_INCREF(obj1); %} + +%nodefaultctor ldns_struct_key; //no default constructor & destructor +%nodefaultdtor ldns_struct_key; + +%delobject ldns_key_free; +%delobject ldns_key_deep_free; +%newobject ldns_key_list_pop_key; +%newobject ldns_key2rr; +%newobject ldns_key_new_frm_algorithm; +%newobject ldns_key_new_frm_fp; +%newobject ldns_key_new_frm_fp_l; +%newobject ldns_key_new_frm_engine; + +%rename(ldns_key) ldns_struct_key; + +#ifdef LDNS_DEBUG +%rename(__ldns_key_free) ldns_key_free; +%inline %{ +void _ldns_key_free (ldns_key* k) { + printf("******** LDNS_KEY free 0x%lX ************\n", (long unsigned int)k); + ldns_key_deep_free(k); +} +%} +#else +%rename(_ldns_key_free) ldns_key_deep_free; +%rename(__ldns_key_free) ldns_key_free; +#endif + +%feature("docstring") ldns_struct_key "Key class + +This class can contains all types of keys that are used in DNSSEC. Mostly used to store private keys, since public keys can also be stored in a ldns_rr with type LDNS_RR_TYPE_DNSKEY. This class can also store some variables that influence the signatures generated by signing with this key, for instance the inception date. + +**Usage** + + >>> import ldns + >>> ldns.ldns_init_random(open(\"/dev/random\",\"rb\"), 512/8) + >>> key = ldns.ldns_key.new_frm_algorithm(ldns.LDNS_SIGN_DSA, 512) #generate new DSA key + >>> print key + Private-key-format: v1.2 + Algorithm: 3 (DSA) + Prime(p): XXXXXXXXHRQBGRflHZQriSAoLI2g+LGvZz8BlEesO+ZQg65wrFGs9IC441y/mn3nFnXfCdtX6zbN5bQuabPdlQ== + Subprime(q): XXXXXdnWs/cWsGDglhEyZRLEVA8= + Base(g): XXXXXXXqrd+dm2bcxDBdCsZRzkXQ22FxCk2ycnjgevr+s2HfA57BPk3xwqCrHUwuOBVg3Fvq4bpldrCe0sT6Og== + Private_value(x): XXXXXcVubZF33pj04z4ZoETsQW1Y= + Public_value(y): XXXXXX8t6zfOxJHoy57qteIw9sOZ/Zu0yFiPO083sPm11NlFx3b4m7TJ2k41gYicHXHLUQK1p0xXFToeZEkPGQ== + >>> fw = open(\"key.priv\", \"wb\") + >>> key.print_to_file(fw) #write priv key to file +" + +%extend ldns_struct_key { + + %pythoncode %{ + def __init__(self): + self.this = _ldns.ldns_key_new() + if not self.this: + raise Exception("Can't create instance of this class") + + __swig_destroy__ = _ldns._ldns_key_free + + def __str__(self): + """converts the data to presentation format""" + return _ldns.ldns_key2str(self) + + + def key_to_rr(self): + """converts a ldns_key to a public key rr + + :returns: (ldns_rr \*) ldns_rr representation of the key + """ + return _ldns.ldns_key2rr(self) + #parameters: const ldns_key *, + #retvals: ldns_rr * + + def print_to_file(self, file): + """print a private key to the file ouput + + :param file: output file pointer + """ + _ldns.ldns_key_print(file, self) + #parameters: FILE *, const ldns_key *, + #retvals: + + #LDNS_KEY_CONSTRUCTORS_# + @staticmethod + def new_frm_fp(file, raiseException=True): + """Creates a new priv key based on the contents of the file pointed by fp. + + :param file: a file object + :param raiseException: if True, an exception occurs in case a key instance can't be created + :returns: key instance or None. If the object can't be created and raiseException is True, an exception occurs. + """ + status, key = _ldns.ldns_key_new_frm_fp(file) + if status != LDNS_STATUS_OK: + if (raiseException): raise Exception("Can't create key, error: %s (%d)" % (_ldns.ldns_get_errorstr_by_id(status),status)) + return None + return key + + @staticmethod + def new_frm_fp_l(file, raiseException=True): + """Creates a new private key based on the contents of the file pointed by fp. + + :param file: a file object + :param raiseException: if True, an exception occurs in case a key instance can't be created + :returns: + * key - key instance or None. If an instance can't be created and raiseException is True, an exception occurs. + + * line - the line number (for debugging) + """ + status, key, line = _ldns.ldns_key_new_frm_fp_l(file) + if status != LDNS_STATUS_OK: + if (raiseException): raise Exception("Can't create key, error: %d" % status) + return None + return key, line + + @staticmethod + def new_frm_algorithm(algorithm, size, raiseException=True): + """Creates a new key based on the algorithm. + + :param algorithm: the algorithm to use + :param size: the number of bytes for the keysize + :param raiseException: if True, an exception occurs in case a key instance can't be created + :returns: key instance or None. If the object can't be created and raiseException is True, an exception occurs. + + **Algorithms** + LDNS_SIGN_RSAMD5, LDNS_SIGN_RSASHA1, LDNS_SIGN_DSA, LDNS_SIGN_RSASHA1_NSEC3, LDNS_SIGN_RSASHA256, LDNS_SIGN_RSASHA256_NSEC3, LDNS_SIGN_RSASHA512, LDNS_SIGN_RSASHA512_NSEC3, LDNS_SIGN_DSA_NSEC3, LDNS_SIGN_HMACMD5, LDNS_SIGN_HMACSHA1, LDNS_SIGN_HMACSHA256 + """ + key = _ldns.ldns_key_new_frm_algorithm(algorithm, size) + if (not key) and (raiseException): raise Exception("Can't create key, error: %d" % status) + return key + #_LDNS_KEY_CONSTRUCTORS# + + #LDNS_KEY_METHODS_# + def algorithm(self): + """return the signing alg of the key + + :returns: (ldns_signing_algorithm) the algorithm + """ + return _ldns.ldns_key_algorithm(self) + #parameters: const ldns_key *, + #retvals: ldns_signing_algorithm + + def dsa_key(self): + """returns the (openssl) DSA struct contained in the key + + :returns: (DSA \*) + """ + return _ldns.ldns_key_dsa_key(self) + #parameters: const ldns_key *, + #retvals: DSA * + + def evp_key(self): + """returns the (openssl) EVP struct contained in the key + + :returns: (EVP_PKEY \*) the RSA * structure in the key + """ + return _ldns.ldns_key_evp_key(self) + #parameters: const ldns_key *, + #retvals: EVP_PKEY * + + def expiration(self): + """return the key's expiration date + + :returns: (uint32_t) the experiration date + """ + return _ldns.ldns_key_expiration(self) + #parameters: const ldns_key *, + #retvals: uint32_t + + def flags(self): + """return the flag of the key + + :returns: (uint16_t) the flag + """ + return _ldns.ldns_key_flags(self) + #parameters: const ldns_key *, + #retvals: uint16_t + + def hmac_key(self): + """return the hmac key data + + :returns: (unsigned char \*) the hmac key data + """ + return _ldns.ldns_key_hmac_key(self) + #parameters: const ldns_key *, + #retvals: unsigned char * + + def hmac_size(self): + """return the hmac key size + + :returns: (size_t) the hmac key size + """ + return _ldns.ldns_key_hmac_size(self) + #parameters: const ldns_key *, + #retvals: size_t + + def inception(self): + """return the key's inception date + + :returns: (uint32_t) the inception date + """ + return _ldns.ldns_key_inception(self) + #parameters: const ldns_key *, + #retvals: uint32_t + + def keytag(self): + """return the keytag + + :returns: (uint16_t) the keytag + """ + return _ldns.ldns_key_keytag(self) + #parameters: const ldns_key *, + #retvals: uint16_t + + def origttl(self): + """return the original ttl of the key + + :returns: (uint32_t) the original ttl + """ + return _ldns.ldns_key_origttl(self) + #parameters: const ldns_key *, + #retvals: uint32_t + + def pubkey_owner(self): + """return the public key's owner + + :returns: (ldns_rdf \*) the owner + """ + return _ldns.ldns_key_pubkey_owner(self) + #parameters: const ldns_key *, + #retvals: ldns_rdf * + + def rsa_key(self): + """returns the (openssl) RSA struct contained in the key + + :returns: (RSA \*) the RSA * structure in the key + """ + return _ldns.ldns_key_rsa_key(self) + #parameters: const ldns_key *, + #retvals: RSA * + + def set_algorithm(self,l): + """Set the key's algorithm. + + :param l: + the algorithm + """ + _ldns.ldns_key_set_algorithm(self,l) + #parameters: ldns_key *,ldns_signing_algorithm, + #retvals: + + def set_dsa_key(self,d): + """Set the key's dsa data. + + :param d: + the dsa data + """ + _ldns.ldns_key_set_dsa_key(self,d) + #parameters: ldns_key *,DSA *, + #retvals: + + def set_evp_key(self,e): + """Set the key's evp key. + + :param e: + the evp key + """ + _ldns.ldns_key_set_evp_key(self,e) + #parameters: ldns_key *,EVP_PKEY *, + #retvals: + + def set_expiration(self,e): + """Set the key's expiration date (seconds after epoch). + + :param e: + the expiration + """ + _ldns.ldns_key_set_expiration(self,e) + #parameters: ldns_key *,uint32_t, + #retvals: + + def set_flags(self,flags): + """Set the key's flags. + + :param flags: + the flags + """ + _ldns.ldns_key_set_flags(self,flags) + #parameters: ldns_key *,uint16_t, + #retvals: + + def set_hmac_key(self,hmac): + """Set the key's hmac data. + + :param hmac: + the raw key data + """ + _ldns.ldns_key_set_hmac_key(self,hmac) + #parameters: ldns_key *,unsigned char *, + #retvals: + + def set_hmac_size(self,hmac_size): + """Set the key's hmac size. + + :param hmac_size: + the size of the hmac data + """ + _ldns.ldns_key_set_hmac_size(self,hmac_size) + #parameters: ldns_key *,size_t, + #retvals: + + def set_inception(self,i): + """Set the key's inception date (seconds after epoch). + + :param i: + the inception + """ + _ldns.ldns_key_set_inception(self,i) + #parameters: ldns_key *,uint32_t, + #retvals: + + def set_keytag(self,tag): + """Set the key's key tag. + + :param tag: + the keytag + """ + _ldns.ldns_key_set_keytag(self,tag) + #parameters: ldns_key *,uint16_t, + #retvals: + + def set_origttl(self,t): + """Set the key's original ttl. + + :param t: + the ttl + """ + _ldns.ldns_key_set_origttl(self,t) + #parameters: ldns_key *,uint32_t, + #retvals: + + def set_pubkey_owner(self,r): + """Set the key's pubkey owner. + + :param r: + the owner + """ + _ldns.ldns_key_set_pubkey_owner(self,r) + #parameters: ldns_key *,ldns_rdf *, + #retvals: + + def set_rsa_key(self,r): + """Set the key's rsa data. + + :param r: + the rsa data + """ + _ldns.ldns_key_set_rsa_key(self,r) + #parameters: ldns_key *,RSA *, + #retvals: + + def set_use(self,v): + """set the use flag + + :param v: + the boolean value to set the _use field to + """ + _ldns.ldns_key_set_use(self,v) + #parameters: ldns_key *,bool, + #retvals: + + def use(self): + """return the use flag + + :returns: (bool) the boolean value of the _use field + """ + return _ldns.ldns_key_use(self) + #parameters: const ldns_key *, + #retvals: bool + #_LDNS_KEY_METHODS# + %} +} + +%nodefaultctor ldns_struct_key_list; //no default constructor & destructor +%nodefaultdtor ldns_struct_key_list; + +%newobject ldns_key_list_new; +%newobject ldns_key_list_pop_key; +%delobject ldns_key_list_free; +%delobject ldns_key_list_push_key; + +%rename(ldns_key_list) ldns_struct_key_list; + +#ifdef LDNS_DEBUG +%rename(__ldns_key_list_free) ldns_key_list_free; +%inline %{ +void _ldns_key_list_free (ldns_key_list* k) { + printf("******** LDNS_KEY_LIST free 0x%lX ************\n", (long unsigned int)k); + ldns_key_list_free(k); +} +%} +#else +%rename(_ldns_key_list_free) ldns_key_list_free; +#endif + +%extend ldns_struct_key_list { + + %pythoncode %{ + def __init__(self): + self.this = _ldns.ldns_key_list_new() + if not self.this: + raise Exception("Can't create class") + + __swig_destroy__ = _ldns._ldns_key_list_free + + def keys(self): + """Key list iterator""" + for i in range(0, self.key_count()): + yield self.key(i) + + def __str__(self): + i = 0 + s = "" + for k in self.keys(): + i += 1 + s += "key %d:\n %s\n" % (i, str(k).replace("\n","\n ")) + return s + + #LDNS_KEY_LIST_METHODS_# + def key(self,nr): + """returns a pointer to the key in the list at the given position + + :param nr: + the position in the list + :returns: (ldns_key \*) the key + """ + return _ldns.ldns_key_list_key(self,nr) + #parameters: const ldns_key_list *,size_t, + #retvals: ldns_key * + + def key_count(self): + """returns the number of keys in the key list + + :returns: (size_t) the numbers of keys in the list + """ + return _ldns.ldns_key_list_key_count(self) + #parameters: const ldns_key_list *, + #retvals: size_t + + def pop_key(self): + """pops the last rr from a keylist + + :returns: (ldns_key \*) NULL if nothing to pop. Otherwise the popped RR + """ + return _ldns.ldns_key_list_pop_key(self) + #parameters: ldns_key_list *, + #retvals: ldns_key * + + def push_key(self,key): + """pushes a key to a keylist + + :param key: + the key to push + :returns: (bool) false on error, otherwise true + """ + return _ldns.ldns_key_list_push_key(self,key) + #parameters: ldns_key_list *,ldns_key *, + #retvals: bool + + def set_key_count(self,count): + """Set the keylist's key count to count. + + :param count: + the cuont + """ + _ldns.ldns_key_list_set_key_count(self,count) + #parameters: ldns_key_list *,size_t, + #retvals: + + def set_use(self,v): + """Set the 'use' flag for all keys in the list. + + :param v: + The value to set the use flags to + """ + _ldns.ldns_key_list_set_use(self,v) + #parameters: ldns_key_list *,bool, + #retvals: + + #_LDNS_KEY_LIST_METHODS# + %} +} + diff --git a/contrib/python/ldns_packet.i b/contrib/python/ldns_packet.i new file mode 100644 index 00000000000..a1ad6b7c821 --- /dev/null +++ b/contrib/python/ldns_packet.i @@ -0,0 +1,1086 @@ +/****************************************************************************** + * ldns_packet.i: LDNS packet class + * + * Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz) + * Karel Slany (slany AT fit.vutbr.cz) + * 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 the organization 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. + ******************************************************************************/ +%typemap(in,numinputs=0,noblock=1) (ldns_pkt **) +{ + ldns_pkt *$1_pkt; + $1 = &$1_pkt; +} + +/* result generation */ +%typemap(argout,noblock=1) (ldns_pkt **) +{ + $result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(SWIG_as_voidptr($1_pkt), SWIGTYPE_p_ldns_struct_pkt, SWIG_POINTER_OWN | 0 )); +} + +%newobject ldns_pkt_new; +%newobject ldns_pkt_clone; +%newobject ldns_pkt_rr_list_by_type; +%newobject ldns_pkt_rr_list_by_name_and_type; +%newobject ldns_pkt_rr_list_by_name; +%newobject ldns_update_pkt_new; + + +%nodefaultctor ldns_struct_pkt; //no default constructor & destructor +%nodefaultdtor ldns_struct_pkt; + +%rename(ldns_pkt) ldns_struct_pkt; +#ifdef LDNS_DEBUG +%rename(__ldns_pkt_free) ldns_pkt_free; +%inline %{ +void _ldns_pkt_free (ldns_pkt* p) { + printf("******** LDNS_PKT free 0x%lX ************\n", (long unsigned int)p); + ldns_pkt_free(p); +} +%} +#else +%rename(_ldns_pkt_free) ldns_pkt_free; +#endif + +%newobject ldns_pkt2str; +%newobject ldns_pkt_opcode2str; +%newobject ldns_pkt_rcode2str; +%newobject ldns_pkt_algorithm2str; +%newobject ldns_pkt_cert_algorithm2str; + + +/* cloning of packet_lists to make them independent of the original packet */ + +%newobject _ldns_pkt_additional; +%newobject _ldns_pkt_answer; +%newobject _ldns_pkt_authority; +%newobject _ldns_pkt_question; + +%rename(__ldns_pkt_additional) ldns_pkt_additional; +%inline %{ +ldns_rr_list* _ldns_pkt_additional(ldns_pkt* p) { + return ldns_rr_list_clone(ldns_pkt_additional(p)); +} +%} + +%rename(__ldns_pkt_answer) ldns_pkt_answer; +%inline %{ +ldns_rr_list* _ldns_pkt_answer(ldns_pkt* p) { + return ldns_rr_list_clone(ldns_pkt_answer(p)); +} +%} + +%rename(__ldns_pkt_authority) ldns_pkt_authority; +%inline %{ +ldns_rr_list* _ldns_pkt_authority(ldns_pkt* p) { + return ldns_rr_list_clone(ldns_pkt_authority(p)); +} +%} + +%rename(__ldns_pkt_question) ldns_pkt_question; +%inline %{ +ldns_rr_list* _ldns_pkt_question(ldns_pkt* p) { + return ldns_rr_list_clone(ldns_pkt_question(p)); +} +%} + +/* clone data when pushed in */ + +%rename(__ldns_pkt_push_rr) ldns_pkt_push_rr; +%inline %{ +bool _ldns_pkt_push_rr(ldns_pkt* p, ldns_pkt_section sec, ldns_rr *rr) { + return ldns_pkt_push_rr(p, sec, ldns_rr_clone(rr)); +} +%} + +%rename(__ldns_pkt_push_rr_list) ldns_pkt_push_rr_list; +%inline %{ +bool _ldns_pkt_push_rr_list(ldns_pkt* p, ldns_pkt_section sec, ldns_rr_list *rrl) { + return ldns_pkt_push_rr_list(p, sec, ldns_rr_list_clone(rrl)); +} +%} + +%feature("docstring") ldns_struct_pkt "LDNS packet object. + +The ldns_pkt object contains DNS packed (either a query or an answer). It is the complete representation of what you actually send to a nameserver, and what you get back (see :class:`ldns.ldns_resolver`). + +**Usage** + +>>> import ldns +>>> resolver = ldns.ldns_resolver.new_frm_file(\"/etc/resolv.conf\") +>>> pkt = resolver.query(\"nic.cz\", ldns.LDNS_RR_TYPE_NS,ldns.LDNS_RR_CLASS_IN) +>>> print pkt +;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 63004 +;; flags: qr rd ra ; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 0 +;; QUESTION SECTION: +;; nic.cz. IN NS +;; ANSWER SECTION: +nic.cz. 758 IN NS a.ns.nic.cz. +nic.cz. 758 IN NS c.ns.nic.cz. +nic.cz. 758 IN NS e.ns.nic.cz. +;; AUTHORITY SECTION: +;; ADDITIONAL SECTION: +;; Query time: 8 msec +;; SERVER: 82.100.38.2 +;; WHEN: Thu Jan 11 12:54:33 2009 +;; MSG SIZE rcvd: 75 + +This simple example instances a resolver in order to resolve NS for nic.cz. +" + +%extend ldns_struct_pkt { + + %pythoncode %{ + def __init__(self): + raise Exception("This class can't be created directly. Please use: ldns_pkt_new(), ldns_pkt_query_new() or ldns_pkt_query_new_frm_str()") + + __swig_destroy__ = _ldns._ldns_pkt_free + + #LDNS_PKT_CONSTRUCTORS_# + @staticmethod + def new_query(rr_name, rr_type, rr_class, flags): + """Creates a packet with a query in it for the given name, type and class. + + :param rr_name: the name to query for + :param rr_type: the type to query for + :param rr_class: the class to query for + :param flags: packet flags + :returns: new ldns_pkt object + """ + return _ldns.ldns_pkt_query_new(rr_name, rr_type, rr_class, flags) + + @staticmethod + def new_query_frm_str(rr_name, rr_type, rr_class, flags, raiseException = True): + """Creates a query packet for the given name, type, class. + + :param rr_name: the name to query for + :param rr_type: the type to query for + :param rr_class: the class to query for + :param flags: packet flags + :param raiseException: if True, an exception occurs in case a resolver object can't be created + :returns: query packet object or None. If the object can't be created and raiseException is True, an exception occurs. + + + **Usage** + + >>> pkt = ldns.ldns_pkt.new_query_frm_str("test.nic.cz",ldns.LDNS_RR_TYPE_ANY, ldns.LDNS_RR_CLASS_IN, ldns.LDNS_QR | ldns.LDNS_AA) + >>> rra = ldns.ldns_rr.new_frm_str("test.nic.cz. IN A 192.168.1.1",300) + >>> list = ldns.ldns_rr_list() + >>> if (rra): list.push_rr(rra) + >>> pkt.push_rr_list(ldns.LDNS_SECTION_ANSWER, list) + >>> print pkt + ;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 0 + ;; flags: qr aa ; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 + ;; QUESTION SECTION: + ;; test.nic.cz. IN ANY + ;; ANSWER SECTION: + test.nic.cz. 300 IN A 192.168.1.1 + ;; AUTHORITY SECTION: + ;; ADDITIONAL SECTION: + ;; Query time: 0 msec + ;; WHEN: Thu Jan 1 01:00:00 1970 + ;; MSG SIZE rcvd: 0 + """ + status, pkt = _ldns.ldns_pkt_query_new_frm_str(rr_name, rr_type, rr_class, flags) + if status != LDNS_STATUS_OK: + if (raiseException): raise Exception("Can't create query packet, error: %d" % status) + return None + return pkt + #_LDNS_PKT_CONSTRUCTORS# + + def __str__(self): + """Converts the data in the DNS packet to presentation format""" + return _ldns.ldns_pkt2str(self) + + def opcode2str(self): + """Converts a packet opcode to its mnemonic and returns that as an allocated null-terminated string.""" + return _ldns.ldns_pkt_opcode2str(sefl.get_opcode()) + + def rcode2str(self): + """Converts a packet rcode to its mnemonic and returns that as an allocated null-terminated string.""" + return _ldns.ldns_pkt_rcode2str(self.get_rcode()) + + def print_to_file(self,output): + """Prints the data in the DNS packet to the given file stream (in presentation format).""" + _ldns.ldns_pkt_print(output,self) + #parameters: FILE *,const ldns_pkt *, + + def write_to_buffer(self, buffer): + """Copies the packet data to the buffer in wire format. + + :param buffer: buffer to append the result to + :returns: (ldns_status) ldns_status + """ + return _ldns.ldns_pkt2buffer_wire(buffer, self) + #parameters: ldns_buffer *,const ldns_pkt *, + #retvals: ldns_status + + @staticmethod + def algorithm2str(alg): + """Converts a signing algorithms to its mnemonic and returns that as an allocated null-terminated string.""" + return _ldns.ldns_pkt_algorithm2str(alg) + #parameters: ldns_algorithm, + + @staticmethod + def cert_algorithm2str(alg): + """Converts a cert algorithm to its mnemonic and returns that as an allocated null-terminated string.""" + return _ldns.ldns_pkt_cert_algorithm2str(alg) + #parameters: ldns_algorithm, + + #LDNS_PKT_METHODS_# + def aa(self): + """Read the packet's aa bit. + + :returns: (bool) value of the bit + """ + return _ldns.ldns_pkt_aa(self) + #parameters: const ldns_pkt *, + #retvals: bool + + def ad(self): + """Read the packet's ad bit. + + :returns: (bool) value of the bit + """ + return _ldns.ldns_pkt_ad(self) + #parameters: const ldns_pkt *, + #retvals: bool + + def additional(self): + """Return the packet's additional section. + + :returns: (ldns_rr_list \*) the section + """ + return _ldns._ldns_pkt_additional(self) + #parameters: const ldns_pkt *, + #retvals: ldns_rr_list * + + def all(self): + return _ldns.ldns_pkt_all(self) + #parameters: const ldns_pkt *, + #retvals: ldns_rr_list * + + def all_noquestion(self): + return _ldns.ldns_pkt_all_noquestion(self) + #parameters: const ldns_pkt *, + #retvals: ldns_rr_list * + + def ancount(self): + """Return the packet's an count. + + :returns: (uint16_t) the an count + """ + return _ldns.ldns_pkt_ancount(self) + #parameters: const ldns_pkt *, + #retvals: uint16_t + + def answer(self): + """Return the packet's answer section. + + :returns: (ldns_rr_list \*) the section + """ + return _ldns._ldns_pkt_answer(self) + #parameters: const ldns_pkt *, + #retvals: ldns_rr_list * + + def answerfrom(self): + """Return the packet's answerfrom. + + :returns: (ldns_rdf \*) the name of the server + """ + return _ldns.ldns_pkt_answerfrom(self) + #parameters: const ldns_pkt *, + #retvals: ldns_rdf * + + def arcount(self): + """Return the packet's ar count. + + :returns: (uint16_t) the ar count + """ + return _ldns.ldns_pkt_arcount(self) + #parameters: const ldns_pkt *, + #retvals: uint16_t + + def authority(self): + """Return the packet's authority section. + + :returns: (ldns_rr_list \*) the section + """ + return _ldns._ldns_pkt_authority(self) + #parameters: const ldns_pkt *, + #retvals: ldns_rr_list * + + def cd(self): + """Read the packet's cd bit. + + :returns: (bool) value of the bit + """ + return _ldns.ldns_pkt_cd(self) + #parameters: const ldns_pkt *, + #retvals: bool + + def clone(self): + """clones the given packet, creating a fully allocated copy + + :returns: (ldns_pkt \*) ldns_pkt* pointer to the new packet + """ + return _ldns.ldns_pkt_clone(self) + #parameters: ldns_pkt *, + #retvals: ldns_pkt * + + def edns(self): + """returns true if this packet needs and EDNS rr to be sent. + + At the moment the only reason is an expected packet size larger than 512 bytes, but for instance dnssec would be a good reason too. + + :returns: (bool) true if packet needs edns rr + """ + return _ldns.ldns_pkt_edns(self) + #parameters: const ldns_pkt *, + #retvals: bool + + def edns_data(self): + """return the packet's edns data + + :returns: (ldns_rdf \*) the data + """ + return _ldns.ldns_pkt_edns_data(self) + #parameters: const ldns_pkt *, + #retvals: ldns_rdf * + + def edns_do(self): + """return the packet's edns do bit + + :returns: (bool) the bit's value + """ + return _ldns.ldns_pkt_edns_do(self) + #parameters: const ldns_pkt *, + #retvals: bool + + def edns_extended_rcode(self): + """return the packet's edns extended rcode + + :returns: (uint8_t) the rcode + """ + return _ldns.ldns_pkt_edns_extended_rcode(self) + #parameters: const ldns_pkt *, + #retvals: uint8_t + + def edns_udp_size(self): + """return the packet's edns udp size + + :returns: (uint16_t) the size + """ + return _ldns.ldns_pkt_edns_udp_size(self) + #parameters: const ldns_pkt *, + #retvals: uint16_t + + def edns_version(self): + """return the packet's edns version + + :returns: (uint8_t) the version + """ + return _ldns.ldns_pkt_edns_version(self) + #parameters: const ldns_pkt *, + #retvals: uint8_t + + def edns_z(self): + """return the packet's edns z value + + :returns: (uint16_t) the z value + """ + return _ldns.ldns_pkt_edns_z(self) + #parameters: const ldns_pkt *, + #retvals: uint16_t + + def empty(self): + """check if a packet is empty + + :returns: (bool) true: empty, false: empty + """ + return _ldns.ldns_pkt_empty(self) + #parameters: ldns_pkt *, + #retvals: bool + + def get_opcode(self): + """Read the packet's code. + + :returns: (ldns_pkt_opcode) the opcode + """ + return _ldns.ldns_pkt_get_opcode(self) + #parameters: const ldns_pkt *, + #retvals: ldns_pkt_opcode + + def get_rcode(self): + """Return the packet's respons code. + + :returns: (ldns_pkt_rcode) the respons code + """ + return _ldns.ldns_pkt_get_rcode(self) + #parameters: const ldns_pkt *, + #retvals: ldns_pkt_rcode + + def get_section_clone(self,s): + """return all the rr_list's in the packet. + + Clone the lists, instead of returning pointers. + + :param s: + what section(s) to return + :returns: (ldns_rr_list \*) ldns_rr_list with the rr's or NULL if none were found + """ + return _ldns.ldns_pkt_get_section_clone(self,s) + #parameters: const ldns_pkt *,ldns_pkt_section, + #retvals: ldns_rr_list * + + def id(self): + """Read the packet id. + + :returns: (uint16_t) the packet id + """ + return _ldns.ldns_pkt_id(self) + #parameters: const ldns_pkt *, + #retvals: uint16_t + + def nscount(self): + """Return the packet's ns count. + + :returns: (uint16_t) the ns count + """ + return _ldns.ldns_pkt_nscount(self) + #parameters: const ldns_pkt *, + #retvals: uint16_t + + def push_rr(self,section,rr): + """push an rr on a packet + + :param section: + where to put it + :param rr: + rr to push + :returns: (bool) a boolean which is true when the rr was added + """ + return _ldns._ldns_pkt_push_rr(self,section,rr) + #parameters: ldns_pkt *,ldns_pkt_section,ldns_rr *, + #retvals: bool + + def push_rr_list(self,section,list): + """push a rr_list on a packet + + :param section: + where to put it + :param list: + the rr_list to push + :returns: (bool) a boolean which is true when the rr was added + """ + return _ldns._ldns_pkt_push_rr_list(self,section,list) + #parameters: ldns_pkt *,ldns_pkt_section,ldns_rr_list *, + #retvals: bool + + def qdcount(self): + """Return the packet's qd count. + + :returns: (uint16_t) the qd count + """ + return _ldns.ldns_pkt_qdcount(self) + #parameters: const ldns_pkt *, + #retvals: uint16_t + + def qr(self): + """Read the packet's qr bit. + + :returns: (bool) value of the bit + """ + return _ldns.ldns_pkt_qr(self) + #parameters: const ldns_pkt *, + #retvals: bool + + def querytime(self): + """Return the packet's querytime. + + :returns: (uint32_t) the querytime + """ + return _ldns.ldns_pkt_querytime(self) + #parameters: const ldns_pkt *, + #retvals: uint32_t + + def question(self): + """Return the packet's question section. + + :returns: (ldns_rr_list \*) the section + """ + return _ldns._ldns_pkt_question(self) + #parameters: const ldns_pkt *, + #retvals: ldns_rr_list * + + def ra(self): + """Read the packet's ra bit. + + :returns: (bool) value of the bit + """ + return _ldns.ldns_pkt_ra(self) + #parameters: const ldns_pkt *, + #retvals: bool + + def rd(self): + """Read the packet's rd bit. + + :returns: (bool) value of the bit + """ + return _ldns.ldns_pkt_rd(self) + #parameters: const ldns_pkt *, + #retvals: bool + + def reply_type(self): + """looks inside the packet to determine what kind of packet it is, AUTH, NXDOMAIN, REFERRAL, etc. + + :returns: (ldns_pkt_type) the type of packet + """ + return _ldns.ldns_pkt_reply_type(self) + #parameters: ldns_pkt *, + #retvals: ldns_pkt_type + + def rr(self,sec,rr): + """check to see if an rr exist in the packet + + :param sec: + in which section to look + :param rr: + the rr to look for + :returns: (bool) + """ + return _ldns.ldns_pkt_rr(self,sec,rr) + #parameters: ldns_pkt *,ldns_pkt_section,ldns_rr *, + #retvals: bool + + def rr_list_by_name(self,r,s): + """return all the rr with a specific name from a packet. + + Optionally specify from which section in the packet + + :param r: + the name + :param s: + the packet's section + :returns: (ldns_rr_list \*) a list with the rr's or NULL if none were found + """ + return _ldns.ldns_pkt_rr_list_by_name(self,r,s) + #parameters: ldns_pkt *,ldns_rdf *,ldns_pkt_section, + #retvals: ldns_rr_list * + + def rr_list_by_name_and_type(self,ownername,atype,sec): + """return all the rr with a specific type and type from a packet. + + Optionally specify from which section in the packet + + :param ownername: + the name + :param atype: + :param sec: + the packet's section + :returns: (ldns_rr_list \*) a list with the rr's or NULL if none were found + """ + return _ldns.ldns_pkt_rr_list_by_name_and_type(self,ownername,atype,sec) + #parameters: const ldns_pkt *,const ldns_rdf *,ldns_rr_type,ldns_pkt_section, + #retvals: ldns_rr_list * + + def rr_list_by_type(self,t,s): + """return all the rr with a specific type from a packet. + + Optionally specify from which section in the packet + + :param t: + the type + :param s: + the packet's section + :returns: (ldns_rr_list \*) a list with the rr's or NULL if none were found + """ + return _ldns.ldns_pkt_rr_list_by_type(self,t,s) + #parameters: const ldns_pkt *,ldns_rr_type,ldns_pkt_section, + #retvals: ldns_rr_list * + + def safe_push_rr(self,sec,rr): + """push an rr on a packet, provided the RR is not there. + + :param sec: + where to put it + :param rr: + rr to push + :returns: (bool) a boolean which is true when the rr was added + """ + return _ldns.ldns_pkt_safe_push_rr(self,sec,rr) + #parameters: ldns_pkt *,ldns_pkt_section,ldns_rr *, + #retvals: bool + + def safe_push_rr_list(self,sec,list): + """push an rr_list to a packet, provided the RRs are not already there. + + :param sec: + where to put it + :param list: + the rr_list to push + :returns: (bool) a boolean which is true when the rr was added + """ + return _ldns.ldns_pkt_safe_push_rr_list(self,sec,list) + #parameters: ldns_pkt *,ldns_pkt_section,ldns_rr_list *, + #retvals: bool + + def section_count(self,s): + return _ldns.ldns_pkt_section_count(self,s) + #parameters: const ldns_pkt *,ldns_pkt_section, + #retvals: uint16_t + + def set_aa(self,b): + """Set the packet's aa bit. + + :param b: + the value to set (boolean) + """ + _ldns.ldns_pkt_set_aa(self,b) + #parameters: ldns_pkt *,bool, + #retvals: + + def set_ad(self,b): + """Set the packet's ad bit. + + :param b: + the value to set (boolean) + """ + _ldns.ldns_pkt_set_ad(self,b) + #parameters: ldns_pkt *,bool, + #retvals: + + def set_additional(self,rr): + """directly set the additional section + + :param rr: + rrlist to set + """ + _ldns.ldns_pkt_set_additional(self,rr) + #parameters: ldns_pkt *,ldns_rr_list *, + #retvals: + + def set_ancount(self,c): + """Set the packet's an count. + + :param c: + the count + """ + _ldns.ldns_pkt_set_ancount(self,c) + #parameters: ldns_pkt *,uint16_t, + #retvals: + + def set_answer(self,rr): + """directly set the answer section + + :param rr: + rrlist to set + """ + _ldns.ldns_pkt_set_answer(self,rr) + #parameters: ldns_pkt *,ldns_rr_list *, + #retvals: + + def set_answerfrom(self,r): + """Set the packet's answering server. + + :param r: + the address + """ + _ldns.ldns_pkt_set_answerfrom(self,r) + #parameters: ldns_pkt *,ldns_rdf *, + #retvals: + + def set_arcount(self,c): + """Set the packet's arcount. + + :param c: + the count + """ + _ldns.ldns_pkt_set_arcount(self,c) + #parameters: ldns_pkt *,uint16_t, + #retvals: + + def set_authority(self,rr): + """directly set the auhority section + + :param rr: + rrlist to set + """ + _ldns.ldns_pkt_set_authority(self,rr) + #parameters: ldns_pkt *,ldns_rr_list *, + #retvals: + + def set_cd(self,b): + """Set the packet's cd bit. + + :param b: + the value to set (boolean) + """ + _ldns.ldns_pkt_set_cd(self,b) + #parameters: ldns_pkt *,bool, + #retvals: + + def set_edns_data(self,data): + """Set the packet's edns data. + + :param data: + the data + """ + _ldns.ldns_pkt_set_edns_data(self,data) + #parameters: ldns_pkt *,ldns_rdf *, + #retvals: + + def set_edns_do(self,value): + """Set the packet's edns do bit. + + :param value: + the bit's new value + """ + _ldns.ldns_pkt_set_edns_do(self,value) + #parameters: ldns_pkt *,bool, + #retvals: + + def set_edns_extended_rcode(self,c): + """Set the packet's edns extended rcode. + + :param c: + the code + """ + _ldns.ldns_pkt_set_edns_extended_rcode(self,c) + #parameters: ldns_pkt *,uint8_t, + #retvals: + + def set_edns_udp_size(self,s): + """Set the packet's edns udp size. + + :param s: + the size + """ + _ldns.ldns_pkt_set_edns_udp_size(self,s) + #parameters: ldns_pkt *,uint16_t, + #retvals: + + def set_edns_version(self,v): + """Set the packet's edns version. + + :param v: + the version + """ + _ldns.ldns_pkt_set_edns_version(self,v) + #parameters: ldns_pkt *,uint8_t, + #retvals: + + def set_edns_z(self,z): + """Set the packet's edns z value. + + :param z: + the value + """ + _ldns.ldns_pkt_set_edns_z(self,z) + #parameters: ldns_pkt *,uint16_t, + #retvals: + + def set_flags(self,flags): + """sets the flags in a packet. + + :param flags: + ORed values: LDNS_QR| LDNS_AR for instance + :returns: (bool) true on success otherwise false + """ + return _ldns.ldns_pkt_set_flags(self,flags) + #parameters: ldns_pkt *,uint16_t, + #retvals: bool + + def set_id(self,id): + """Set the packet's id. + + :param id: + the id to set + """ + _ldns.ldns_pkt_set_id(self,id) + #parameters: ldns_pkt *,uint16_t, + #retvals: + + def set_nscount(self,c): + """Set the packet's ns count. + + :param c: + the count + """ + _ldns.ldns_pkt_set_nscount(self,c) + #parameters: ldns_pkt *,uint16_t, + #retvals: + + def set_opcode(self,c): + """Set the packet's opcode. + + :param c: + the opcode + """ + _ldns.ldns_pkt_set_opcode(self,c) + #parameters: ldns_pkt *,ldns_pkt_opcode, + #retvals: + + def set_qdcount(self,c): + """Set the packet's qd count. + + :param c: + the count + """ + _ldns.ldns_pkt_set_qdcount(self,c) + #parameters: ldns_pkt *,uint16_t, + #retvals: + + def set_qr(self,b): + """Set the packet's qr bit. + + :param b: + the value to set (boolean) + """ + _ldns.ldns_pkt_set_qr(self,b) + #parameters: ldns_pkt *,bool, + #retvals: + + def set_querytime(self,t): + """Set the packet's query time. + + :param t: + the querytime in msec + """ + _ldns.ldns_pkt_set_querytime(self,t) + #parameters: ldns_pkt *,uint32_t, + #retvals: + + def set_question(self,rr): + """directly set the question section + + :param rr: + rrlist to set + """ + _ldns.ldns_pkt_set_question(self,rr) + #parameters: ldns_pkt *,ldns_rr_list *, + #retvals: + + def set_ra(self,b): + """Set the packet's ra bit. + + :param b: + the value to set (boolean) + """ + _ldns.ldns_pkt_set_ra(self,b) + #parameters: ldns_pkt *,bool, + #retvals: + + def set_random_id(self): + """Set the packet's id to a random value. + """ + _ldns.ldns_pkt_set_random_id(self) + #parameters: ldns_pkt *, + #retvals: + + def set_rcode(self,c): + """Set the packet's respons code. + + :param c: + the rcode + """ + _ldns.ldns_pkt_set_rcode(self,c) + #parameters: ldns_pkt *,uint8_t, + #retvals: + + def set_rd(self,b): + """Set the packet's rd bit. + + :param b: + the value to set (boolean) + """ + _ldns.ldns_pkt_set_rd(self,b) + #parameters: ldns_pkt *,bool, + #retvals: + + def set_section_count(self,s,x): + """Set a packet's section count to x. + + :param s: + the section + :param x: + the section count + """ + _ldns.ldns_pkt_set_section_count(self,s,x) + #parameters: ldns_pkt *,ldns_pkt_section,uint16_t, + #retvals: + + def set_size(self,s): + """Set the packet's size. + + :param s: + the size + """ + _ldns.ldns_pkt_set_size(self,s) + #parameters: ldns_pkt *,size_t, + #retvals: + + def set_tc(self,b): + """Set the packet's tc bit. + + :param b: + the value to set (boolean) + """ + _ldns.ldns_pkt_set_tc(self,b) + #parameters: ldns_pkt *,bool, + #retvals: + + def set_timestamp(self,timeval): + _ldns.ldns_pkt_set_timestamp(self,timeval) + #parameters: ldns_pkt *,struct timeval, + #retvals: + + def set_tsig(self,t): + """Set the packet's tsig rr. + + :param t: + the tsig rr + """ + _ldns.ldns_pkt_set_tsig(self,t) + #parameters: ldns_pkt *,ldns_rr *, + #retvals: + + def size(self): + """Return the packet's size in bytes. + + :returns: (size_t) the size + """ + return _ldns.ldns_pkt_size(self) + #parameters: const ldns_pkt *, + #retvals: size_t + + def tc(self): + """Read the packet's tc bit. + + :returns: (bool) value of the bit + """ + return _ldns.ldns_pkt_tc(self) + #parameters: const ldns_pkt *, + #retvals: bool + + def timestamp(self): + """Return the packet's timestamp. + + :returns: (struct timeval) the timestamp + """ + return _ldns.ldns_pkt_timestamp(self) + #parameters: const ldns_pkt *, + #retvals: struct timeval + + def tsig(self): + """Return the packet's tsig pseudo rr's. + + :returns: (ldns_rr \*) the tsig rr + """ + return _ldns.ldns_pkt_tsig(self) + #parameters: const ldns_pkt *, + #retvals: ldns_rr * + + #_LDNS_PKT_METHODS# + + #LDNS update methods + #LDNS_METHODS_# + def update_pkt_tsig_add(self,r): + """add tsig credentials to a packet from a resolver + + :param r: + resolver to copy from + :returns: (ldns_status) status wether successfull or not + """ + return _ldns.ldns_update_pkt_tsig_add(self,r) + #parameters: ldns_pkt *,ldns_resolver *, + #retvals: ldns_status + + def update_prcount(self): + """Get the zo count. + + :returns: (uint16_t) the pr count + """ + return _ldns.ldns_update_prcount(self) + #parameters: const ldns_pkt *, + #retvals: uint16_t + + def update_set_adcount(self,c): + """Set the ad count. + + :param c: + the ad count to set + """ + _ldns.ldns_update_set_adcount(self,c) + #parameters: ldns_pkt *,uint16_t, + #retvals: + + def update_set_prcount(self,c): + """Set the pr count. + + :param c: + the pr count to set + """ + _ldns.ldns_update_set_prcount(self,c) + #parameters: ldns_pkt *,uint16_t, + #retvals: + + def update_set_upcount(self,c): + """Set the up count. + + :param c: + the up count to set + """ + _ldns.ldns_update_set_upcount(self,c) + #parameters: ldns_pkt *,uint16_t, + #retvals: + + def update_set_zo(self,v): + _ldns.ldns_update_set_zo(self,v) + #parameters: ldns_pkt *,uint16_t, + #retvals: + + def update_upcount(self): + """Get the zo count. + + :returns: (uint16_t) the up count + """ + return _ldns.ldns_update_upcount(self) + #parameters: const ldns_pkt *, + #retvals: uint16_t + + def update_zocount(self): + """Get the zo count. + + :returns: (uint16_t) the zo count + """ + return _ldns.ldns_update_zocount(self) + #parameters: const ldns_pkt *, + #retvals: uint16_t + + #_LDNS_METHODS# + %} +} diff --git a/contrib/python/ldns_rdf.i b/contrib/python/ldns_rdf.i new file mode 100644 index 00000000000..5a7e3007964 --- /dev/null +++ b/contrib/python/ldns_rdf.i @@ -0,0 +1,426 @@ +/****************************************************************************** + * ldns_rdata.i: LDNS record data + * + * Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz) + * Karel Slany (slany AT fit.vutbr.cz) + * 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 the organization 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. + ******************************************************************************/ + +//automatic conversion of const ldns_rdf* parameter from string +%typemap(in,noblock=1) const ldns_rdf * (void* argp, $1_ltype tmp = 0, int res) { + if (Python_str_Check($input)) { +#ifdef SWIG_Python_str_AsChar + tmp = ldns_dname_new_frm_str(SWIG_Python_str_AsChar($input)); +#else + tmp = ldns_dname_new_frm_str(PyString_AsString($input)); +#endif + if (tmp == NULL) { + %argument_fail(SWIG_TypeError, "char *", $symname, $argnum); + } + $1 = ($1_ltype) tmp; + } else { + res = SWIG_ConvertPtr($input, &argp, SWIGTYPE_p_ldns_struct_rdf, 0 | 0 ); + if (!SWIG_IsOK(res)) { + %argument_fail(res, "ldns_rdf const *", $symname, $argnum); + } + $1 = ($1_ltype) argp; + } +} + +%typemap(in,numinputs=0,noblock=1) (ldns_rdf **) +{ + ldns_rdf *$1_rdf; + $1 = &$1_rdf; +} + +// result generation +%typemap(argout,noblock=1) (ldns_rdf **) +{ + $result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(SWIG_as_voidptr($1_rdf), SWIGTYPE_p_ldns_struct_rdf, SWIG_POINTER_OWN | 0 )); +} + +%nodefaultctor ldns_struct_rdf; //no default constructor & destructor +%nodefaultdtor ldns_struct_rdf; + +%newobject ldns_dname_new; +%newobject ldns_dname_new_frm_str; +%newobject ldns_dname_new_frm_data; + +%newobject ldns_rdf_new; +%newobject ldns_rdf_new_frm_str; +%newobject ldns_rdf_new_frm_data; + +%delobject ldns_rdf_deep_free; +%delobject ldns_rdf_free; + +%rename(ldns_rdf) ldns_struct_rdf; + +%inline %{ + +const char *ldns_rdf_type2str(const ldns_rdf *rdf) +{ + if (rdf) { + switch(ldns_rdf_get_type(rdf)) { + case LDNS_RDF_TYPE_NONE: return 0; + case LDNS_RDF_TYPE_DNAME: return "DNAME"; + case LDNS_RDF_TYPE_INT8: return "INT8"; + case LDNS_RDF_TYPE_INT16: return "INT16"; + case LDNS_RDF_TYPE_INT32: return "INT32"; + case LDNS_RDF_TYPE_PERIOD: return "PERIOD"; + case LDNS_RDF_TYPE_TSIGTIME: return "TSIGTIME"; + case LDNS_RDF_TYPE_A: return "A"; + case LDNS_RDF_TYPE_AAAA: return "AAAA"; + case LDNS_RDF_TYPE_STR: return "STR"; + case LDNS_RDF_TYPE_APL: return "APL"; + case LDNS_RDF_TYPE_B32_EXT: return "B32_EXT"; + case LDNS_RDF_TYPE_B64: return "B64"; + case LDNS_RDF_TYPE_HEX: return "HEX"; + case LDNS_RDF_TYPE_NSEC: return "NSEC"; + case LDNS_RDF_TYPE_NSEC3_SALT: return "NSEC3_SALT"; + case LDNS_RDF_TYPE_TYPE: return "TYPE"; + case LDNS_RDF_TYPE_CLASS: return "CLASS"; + case LDNS_RDF_TYPE_CERT_ALG: return "CER_ALG"; + case LDNS_RDF_TYPE_ALG: return "ALG"; + case LDNS_RDF_TYPE_UNKNOWN: return "UNKNOWN"; + case LDNS_RDF_TYPE_TIME: return "TIME"; + case LDNS_RDF_TYPE_LOC: return "LOC"; + case LDNS_RDF_TYPE_WKS: return "WKS"; + case LDNS_RDF_TYPE_SERVICE: return "SERVICE"; + case LDNS_RDF_TYPE_NSAP: return "NSAP"; + case LDNS_RDF_TYPE_ATMA: return "ATMA"; + case LDNS_RDF_TYPE_IPSECKEY: return "IPSECKEY"; + case LDNS_RDF_TYPE_TSIG: return "TSIG"; + case LDNS_RDF_TYPE_INT16_DATA: return "INT16_DATA"; + case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER: return "NSEC3_NEXT_OWNER"; + } + } + return 0; +} +%} + +#ifdef LDNS_DEBUG +%rename(__ldns_rdf_deep_free) ldns_rdf_deep_free; +%rename(__ldns_rdf_free) ldns_rdf_free; +%inline %{ +void _ldns_rdf_free (ldns_rdf* r) { + printf("******** LDNS_RDF free 0x%lX ************\n", (long unsigned int)r); + ldns_rdf_free(r); +} +%} +#else +%rename(_ldns_rdf_deep_free) ldns_rdf_deep_free; +%rename(_ldns_rdf_free) ldns_rdf_free; +#endif + +%newobject ldns_rdf2str; + + +%feature("docstring") ldns_struct_rdf "Resource record data field. + +The data is a network ordered array of bytes, which size is specified by the (16-bit) size field. To correctly parse it, use the type specified in the (16-bit) type field with a value from ldns_rdf_type." + +%extend ldns_struct_rdf { + + %pythoncode %{ + def __init__(self): + raise Exception("This class can't be created directly. Please use: ldns_rdf_new, ldns_rdf_new_frm_data, ldns_rdf_new_frm_str, ldns_rdf_new_frm_fp, ldns_rdf_new_frm_fp_l") + + __swig_destroy__ = _ldns._ldns_rdf_deep_free + + #LDNS_RDF_CONSTRUCTORS_# + @staticmethod + def new_frm_str(str, rr_type, raiseException = True): + """Creates a new rdf from a string of a given type. + + :param str: string to use + :param rr_type: the type of RDF. See predefined `RDF_TYPE_` constants + :param raiseException: if True, an exception occurs in case a RDF object can't be created + :returns: RDF object or None. If the object can't be created and raiseException is True, an exception occurs. + + **Usage** + >>> rdf = ldns.ldns_rdf.new_frm_str("74.125.43.99",ldns.LDNS_RDF_TYPE_A) + >>> print rdf, rdf.get_type_str() + A 74.125.43.99 + >>> name = ldns.ldns_resolver.new_frm_file().get_name_by_addr(rdf) + >>> if (name): print name + 99.43.125.74.in-addr.arpa. 85277 IN PTR bw-in-f99.google.com. + """ + rr = _ldns.ldns_rdf_new_frm_str(rr_type, str) + if not rr: + if (raiseException): raise Exception("Can't create query packet, error: %d" % status) + return rr + #_LDNS_RDF_CONSTRUCTORS# + + def __str__(self): + """Converts the rdata field to presentation format""" + return _ldns.ldns_rdf2str(self) + + def __cmp__(self,other): + """compares two rdf's on their wire formats. + + (To order dnames according to rfc4034, use ldns_dname_compare) + + :param other: + the second one RDF + :returns: (int) 0 if equal -1 if self comes before other +1 if other comes before self + """ + return _ldns.ldns_rdf_compare(self,other) + + def print_to_file(self,output): + """Prints the data in the rdata field to the given file stream (in presentation format).""" + _ldns.ldns_rdf_print(output,self) + + def get_type_str(self): + """Converts type to string""" + return ldns_rdf_type2str(self) + + def write_to_buffer(self, buffer): + """Copies the rdata data to the buffer in wire format. + + :param buffer: buffer to append the result to + :returns: (ldns_status) ldns_status + """ + return _ldns.ldns_rdf2buffer_wire(buffer, self) + #parameters: ldns_buffer *,const ldns_rdf *, + #retvals: ldns_status + + def write_to_buffer_canonical(self, buffer): + """Copies the rdata data to the buffer in wire format If the rdata is a dname, the letters will be lowercased during the conversion. + + :param buffer: LDNS buffer + :returns: (ldns_status) ldns_status + """ + return _ldns.ldns_rdf2buffer_wire_canonical(buffer, self) + #parameters: ldns_buffer *,const ldns_rdf *, + #retvals: ldns_status + + #LDNS_RDF_METHODS_# + def address_reverse(self): + """reverses an rdf, only actually useful for AAAA and A records. + + The returned rdf has the type LDNS_RDF_TYPE_DNAME! + + :returns: (ldns_rdf \*) the reversed rdf (a newly created rdf) + """ + return _ldns.ldns_rdf_address_reverse(self) + #parameters: ldns_rdf *, + #retvals: ldns_rdf * + + def clone(self): + """clones a rdf structure. + + The data is copied. + + :returns: (ldns_rdf \*) a new rdf structure + """ + return _ldns.ldns_rdf_clone(self) + #parameters: const ldns_rdf *, + #retvals: ldns_rdf * + + def data(self): + """returns the data of the rdf. + + :returns: (uint8_t \*) uint8_t* pointer to the rdf's data + """ + return _ldns.ldns_rdf_data(self) + #parameters: const ldns_rdf *, + #retvals: uint8_t * + + def get_type(self): + """returns the type of the rdf. + + We need to insert _get_ here to prevent conflict the the rdf_type TYPE. + + :returns: (ldns_rdf_type) ldns_rdf_type with the type + """ + return _ldns.ldns_rdf_get_type(self) + #parameters: const ldns_rdf *, + #retvals: ldns_rdf_type + + def set_data(self,data): + """sets the size of the rdf. + + :param data: + """ + _ldns.ldns_rdf_set_data(self,data) + #parameters: ldns_rdf *,void *, + #retvals: + + def set_size(self,size): + """sets the size of the rdf. + + :param size: + the new size + """ + _ldns.ldns_rdf_set_size(self,size) + #parameters: ldns_rdf *,size_t, + #retvals: + + def set_type(self,atype): + """sets the size of the rdf. + + :param atype: + """ + _ldns.ldns_rdf_set_type(self,atype) + #parameters: ldns_rdf *,ldns_rdf_type, + #retvals: + + def size(self): + """returns the size of the rdf. + + :returns: (size_t) uint16_t with the size + """ + return _ldns.ldns_rdf_size(self) + #parameters: const ldns_rdf *, + #retvals: size_t + + @staticmethod + def dname_new_frm_str(str): + """Creates a new dname rdf instance from a string. + + This static method is equivalent to using of default class constructor. + + :parameter str: str string to use + """ + return _ldns.ldns_dname_new_frm_str(str) + + def absolute(self): + """Checks whether the given dname string is absolute (i.e. ends with a '.') + + :returns: (bool) True or False + """ + return self.endswith(".") + + def make_canonical(self): + """Put a dname into canonical fmt - ie. lowercase it + """ + _ldns.ldns_dname2canonical(self) + + def dname_compare(self,other): + """Compares the two dname rdf's according to the algorithm for ordering in RFC4034 Section 6. + + :param other: + the second dname rdf to compare + :returns: (int) -1 if dname comes before other, 1 if dname comes after other, and 0 if they are equal. + """ + return _ldns.ldns_dname_compare(self,other) + + def cat(self,rd2): + """concatenates rd2 after this dname (rd2 is copied, this dname is modified) + + :param rd2: + the rightside + :returns: (ldns_status) LDNS_STATUS_OK on success + """ + return _ldns.ldns_dname_cat(self,rd2) + #parameters: ldns_rdf *,ldns_rdf *, + #retvals: ldns_status + + def cat_clone(self,rd2): + """concatenates two dnames together + + :param rd2: + the rightside + :returns: (ldns_rdf \*) a new rdf with leftside/rightside + """ + return _ldns.ldns_dname_cat_clone(self,rd2) + #parameters: const ldns_rdf *,const ldns_rdf *, + #retvals: ldns_rdf * + + def interval(self,middle,next): + """check if middle lays in the interval defined by prev and next prev <= middle < next. + + This is usefull for nsec checking + + :param middle: + the dname to check + :param next: + the next dname return 0 on error or unknown, -1 when middle is in the interval, +1 when not + :returns: (int) + """ + return _ldns.ldns_dname_interval(self,middle,next) + #parameters: const ldns_rdf *,const ldns_rdf *,const ldns_rdf *, + #retvals: int + + def is_subdomain(self,parent): + """Tests wether the name sub falls under parent (i.e. is a subdomain of parent). + + This function will return false if the given dnames are equal. + + :param parent: + (ldns_rdf) the parent's name + :returns: (bool) true if sub falls under parent, otherwise false + """ + return _ldns.ldns_dname_is_subdomain(self,parent) + #parameters: const ldns_rdf *,const ldns_rdf *, + #retvals: bool + + def label(self,labelpos): + """look inside the rdf and if it is an LDNS_RDF_TYPE_DNAME try and retrieve a specific label. + + The labels are numbered starting from 0 (left most). + + :param labelpos: + return the label with this number + :returns: (ldns_rdf \*) a ldns_rdf* with the label as name or NULL on error + """ + return _ldns.ldns_dname_label(self,labelpos) + #parameters: const ldns_rdf *,uint8_t, + #retvals: ldns_rdf * + + def label_count(self): + """count the number of labels inside a LDNS_RDF_DNAME type rdf. + + :returns: (uint8_t) the number of labels + """ + return _ldns.ldns_dname_label_count(self) + #parameters: const ldns_rdf *, + #retvals: uint8_t + + def left_chop(self): + """chop one label off the left side of a dname. + + so wwww.nlnetlabs.nl, becomes nlnetlabs.nl + + :returns: (ldns_rdf \*) the remaining dname + """ + return _ldns.ldns_dname_left_chop(self) + #parameters: const ldns_rdf *, + #retvals: ldns_rdf * + + def reverse(self): + """Returns a clone of the given dname with the labels reversed. + + :returns: (ldns_rdf \*) clone of the dname with the labels reversed. + """ + return _ldns.ldns_dname_reverse(self) + #parameters: const ldns_rdf *, + #retvals: ldns_rdf * + + #_LDNS_RDF_METHODS# + %} +} diff --git a/contrib/python/ldns_resolver.i b/contrib/python/ldns_resolver.i new file mode 100644 index 00000000000..b9640674b5a --- /dev/null +++ b/contrib/python/ldns_resolver.i @@ -0,0 +1,946 @@ +/****************************************************************************** + * ldns_resolver.i: LDNS resolver class + * + * Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz) + * Karel Slany (slany AT fit.vutbr.cz) + * 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 the organization 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. + ******************************************************************************/ + +%typemap(in,numinputs=0,noblock=1) (ldns_resolver **r) +{ + ldns_resolver *$1_res; + $1 = &$1_res; +} + +/* result generation */ +%typemap(argout,noblock=1) (ldns_resolver **r) +{ + $result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(SWIG_as_voidptr($1_res), SWIGTYPE_p_ldns_struct_resolver, SWIG_POINTER_OWN | 0 )); +} + +//TODO: pop_nameserver a podobne funkce musi predat objekt do spravy PYTHONU!! +%newobject ldns_resolver_pop_nameserver; +%newobject ldns_resolver_query; +%newobject ldns_axfr_next; + +%delobject ldns_resolver_deep_free; +%delobject ldns_resolver_free; + +%nodefaultctor ldns_struct_resolver; //no default constructor & destructor +%nodefaultdtor ldns_struct_resolver; + +%ignore ldns_struct_resolver::_searchlist; +%ignore ldns_struct_resolver::_nameservers; +%ignore ldns_resolver_set_nameservers; + +%rename(ldns_resolver) ldns_struct_resolver; + +#ifdef LDNS_DEBUG +%rename(__ldns_resolver_deep_free) ldns_resolver_deep_free; +%rename(__ldns_resolver_free) ldns_resolver_free; +%inline %{ +void _ldns_resolver_free (ldns_resolver* r) { + printf("******** LDNS_RESOLVER deep free 0x%lX ************\n", (long unsigned int)r); + ldns_resolver_deep_free(r); +} +%} +#else +%rename(_ldns_resolver_deep_free) ldns_resolver_deep_free; +%rename(_ldns_resolver_free) ldns_resolver_free; +#endif + +%feature("docstring") ldns_struct_resolver "LDNS resolver object. + +The ldns_resolver object keeps a list of nameservers and can perform queries. + +**Usage** + +>>> import ldns +>>> resolver = ldns.ldns_resolver.new_frm_file(\"/etc/resolv.conf\") +>>> pkt = resolver.query(\"www.nic.cz\", ldns.LDNS_RR_TYPE_A,ldns.LDNS_RR_CLASS_IN) +>>> if (pkt) and (pkt.answer()): +>>> print pkt.answer() +www.nic.cz. 1757 IN A 217.31.205.50 + +This simple example instances a resolver in order to resolve www.nic.cz record of A type. +" + +%extend ldns_struct_resolver { + + %pythoncode %{ + def __init__(self): + raise Exception("This class can't be created directly. Please use: new_frm_file(filename), new_frm_fp(file) or new_frm_fp_l(file,line)") + + __swig_destroy__ = _ldns._ldns_resolver_free + + #LDNS_RESOLVER_CONSTRUCTORS_# + @staticmethod + def new_frm_file(filename = "/etc/resolv.conf", raiseException=True): + """Creates a resolver object from given filename + + :param filename: name of file which contains informations (usually /etc/resolv.conf) + :param raiseException: if True, an exception occurs in case a resolver object can't be created + :returns: resolver object or None. If the object can't be created and raiseException is True, an exception occurs. + """ + status, resolver = _ldns.ldns_resolver_new_frm_file(filename) + if status != LDNS_STATUS_OK: + if (raiseException): raise Exception("Can't create resolver, error: %d" % status) + return None + return resolver + + @staticmethod + def new_frm_fp(file, raiseException=True): + """Creates a resolver object from file + + :param file: a file object + :param raiseException: if True, an exception occurs in case a resolver object can't be created + :returns: resolver object or None. If the object can't be created and raiseException is True, an exception occurs. + """ + status, resolver = _ldns.ldns_resolver_new_frm_fp(file) + if status != LDNS_STATUS_OK: + if (raiseException): raise Exception("Can't create resolver, error: %d" % status) + return None + return resolver + + @staticmethod + def new_frm_fp_l(file, raiseException=True): + """Creates a resolver object from file + + :param file: a file object + :param raiseException: if True, an exception occurs in case a resolver instance can't be created + :returns: + * resolver - resolver instance or None. If an instance can't be created and raiseException is True, an exception occurs. + + * line - the line number (for debugging) + """ + status, resolver, line = _ldns.ldns_resolver_new_frm_fp_l(file) + if status != LDNS_STATUS_OK: + if (raiseException): raise Exception("Can't create resolver, error: %d" % status) + return None + return resolver, line + + #_LDNS_RESOLVER_CONSTRUCTORS# + + # High level functions + def get_addr_by_name(self, name, aclass = _ldns.LDNS_RR_CLASS_IN, flags = _ldns.LDNS_RD): + """Ask the resolver about name and return all address records + + :param name: (ldns_rdf) the name to look for + :param aclass: the class to use + :param flags: give some optional flags to the query + + :returns: RR List object or None + + **Usage** + >>> addr = resolver.get_addr_by_name("www.google.com", ldns.LDNS_RR_CLASS_IN, ldns.LDNS_RD) + >>> if (not addr): raise Exception("Can't retrieve server address") + >>> for rr in addr.rrs(): + >>> print rr + www.l.google.com. 300 IN A 74.125.43.99 + www.l.google.com. 300 IN A 74.125.43.103 + www.l.google.com. 300 IN A 74.125.43.104 + www.l.google.com. 300 IN A 74.125.43.147 + + """ + rdf = name + if isinstance(name, str): + rdf = _ldns.ldns_dname_new_frm_str(name) + return _ldns.ldns_get_rr_list_addr_by_name(self, rdf, aclass, flags) + + def get_name_by_addr(self, addr, aclass = _ldns.LDNS_RR_CLASS_IN, flags = _ldns.LDNS_RD): + """Ask the resolver about the address and return the name + + :param name: (ldns_rdf of A or AAAA type) the addr to look for. If a string is given, A or AAAA type is identified automatically + :param aclass: the class to use + :param flags: give some optional flags to the query + + :returns: RR List object or None + + **Usage** + >>> addr = resolver.get_name_by_addr("74.125.43.99", ldns.LDNS_RR_CLASS_IN, ldns.LDNS_RD) + >>> if (not addr): raise Exception("Can't retrieve server address") + >>> for rr in addr.rrs(): + >>> print rr + 99.43.125.74.in-addr.arpa. 85641 IN PTR bw-in-f99.google.com. + + """ + rdf = addr + if isinstance(addr, str): + if (addr.find("::") >= 0): #IPv6 + rdf = _ldns.ldns_rdf_new_frm_str(_ldns.LDNS_RDF_TYPE_AAAA, addr) + else: + rdf = _ldns.ldns_rdf_new_frm_str(_ldns.LDNS_RDF_TYPE_A, addr) + return _ldns.ldns_get_rr_list_name_by_addr(self, rdf, aclass, flags) + + def print_to_file(self,output): + """Print a resolver (in sofar that is possible) state to output.""" + _ldns.ldns_resolver_print(output,self) + + def axfr_start(self, domain, aclass): + """Prepares the resolver for an axfr query. The query is sent and the answers can be read with axfr_next + + **Usage** + :: + + status = resolver.axfr_start("nic.cz", ldns.LDNS_RR_CLASS_IN) + if (status != ldns.LDNS_STATUS_OK): raise Exception("Can't start AXFR, error: %s" % ldns.ldns_get_errorstr_by_id(status)) + #Print the results + while True: + rr = resolver.axfr_next() + if not rr: + break + + print rr + + """ + rdf = domain + if isinstance(domain, str): + rdf = _ldns.ldns_dname_new_frm_str(domain) + return _ldns.ldns_axfr_start(self, rdf, aclass) + #parameters: ldns_resolver *resolver, ldns_rdf *domain, ldns_rr_class c + #retvals: int + + def axfr_complete(self): + """returns true if the axfr transfer has completed (i.e. 2 SOA RRs and no errors were encountered)""" + return _ldns.ldns_axfr_complete(self) + #parameters: const ldns_resolver *, + #retvals: bool + + def axfr_last_pkt(self): + """returns a pointer to the last ldns_pkt that was sent by the server in the AXFR transfer uasable for instance to get the error code on failure""" + return _ldns.ldns_axfr_last_pkt(self) + #parameters: const ldns_resolver *, + #retvals: ldns_pkt * + + def axfr_next(self): + """get the next stream of RRs in a AXFR""" + return _ldns.ldns_axfr_next(self) + #parameters: ldns_resolver *, + #retvals: ldns_rr * + + #LDNS_RESOLVER_METHODS_# + def debug(self): + """Get the debug status of the resolver. + + :returns: (bool) true if so, otherwise false + """ + return _ldns.ldns_resolver_debug(self) + #parameters: const ldns_resolver *, + #retvals: bool + + def dec_nameserver_count(self): + """Decrement the resolver's nameserver count. + """ + _ldns.ldns_resolver_dec_nameserver_count(self) + #parameters: ldns_resolver *, + #retvals: + + def defnames(self): + return _ldns.ldns_resolver_defnames(self) + #parameters: const ldns_resolver *, + #retvals: bool + + def dnsrch(self): + return _ldns.ldns_resolver_dnsrch(self) + #parameters: const ldns_resolver *, + #retvals: bool + + def dnssec(self): + """Does the resolver do DNSSEC. + + :returns: (bool) true: yes, false: no + """ + return _ldns.ldns_resolver_dnssec(self) + #parameters: const ldns_resolver *, + #retvals: bool + + def dnssec_anchors(self): + """Get the resolver's DNSSEC anchors. + + :returns: (ldns_rr_list \*) an rr_list containg trusted DNSSEC anchors + """ + return _ldns.ldns_resolver_dnssec_anchors(self) + #parameters: const ldns_resolver *, + #retvals: ldns_rr_list * + + def dnssec_cd(self): + """Does the resolver set the CD bit. + + :returns: (bool) true: yes, false: no + """ + return _ldns.ldns_resolver_dnssec_cd(self) + #parameters: const ldns_resolver *, + #retvals: bool + + def domain(self): + """What is the default dname to add to relative queries. + + :returns: (ldns_rdf \*) the dname which is added + """ + return _ldns.ldns_resolver_domain(self) + #parameters: const ldns_resolver *, + #retvals: ldns_rdf * + + def edns_udp_size(self): + """Get the resolver's udp size. + + :returns: (uint16_t) the udp mesg size + """ + return _ldns.ldns_resolver_edns_udp_size(self) + #parameters: const ldns_resolver *, + #retvals: uint16_t + + def fail(self): + """Does the resolver only try the first nameserver. + + :returns: (bool) true: yes, fail, false: no, try the others + """ + return _ldns.ldns_resolver_fail(self) + #parameters: const ldns_resolver *, + #retvals: bool + + def fallback(self): + """Get the truncation fallback status. + + :returns: (bool) whether the truncation fallback mechanism is used + """ + return _ldns.ldns_resolver_fallback(self) + #parameters: const ldns_resolver *, + #retvals: bool + + def igntc(self): + """Does the resolver ignore the TC bit (truncated). + + :returns: (bool) true: yes, false: no + """ + return _ldns.ldns_resolver_igntc(self) + #parameters: const ldns_resolver *, + #retvals: bool + + def incr_nameserver_count(self): + """Incremental the resolver's nameserver count. + """ + _ldns.ldns_resolver_incr_nameserver_count(self) + #parameters: ldns_resolver *, + #retvals: + + def ip6(self): + """Does the resolver use ip6 or ip4. + + :returns: (uint8_t) 0: both, 1: ip4, 2:ip6 + """ + return _ldns.ldns_resolver_ip6(self) + #parameters: const ldns_resolver *, + #retvals: uint8_t + + def nameserver_count(self): + """How many nameserver are configured in the resolver. + + :returns: (size_t) number of nameservers + """ + return _ldns.ldns_resolver_nameserver_count(self) + #parameters: const ldns_resolver *, + #retvals: size_t + + def nameserver_rtt(self,pos): + """Return the used round trip time for a specific nameserver. + + :param pos: + the index to the nameserver + :returns: (size_t) the rrt, 0: infinite, >0: undefined (as of * yet) + """ + return _ldns.ldns_resolver_nameserver_rtt(self,pos) + #parameters: const ldns_resolver *,size_t, + #retvals: size_t + + def nameservers(self): + """Return the configured nameserver ip address. + + :returns: (ldns_rdf \*\*) a ldns_rdf pointer to a list of the addresses + """ + return _ldns.ldns_resolver_nameservers(self) + #parameters: const ldns_resolver *, + #retvals: ldns_rdf ** + + def nameservers_randomize(self): + """randomize the nameserver list in the resolver + """ + _ldns.ldns_resolver_nameservers_randomize(self) + #parameters: ldns_resolver *, + #retvals: + + def pop_nameserver(self): + """pop the last nameserver from the resolver. + + :returns: (ldns_rdf \*) the popped address or NULL if empty + """ + return _ldns.ldns_resolver_pop_nameserver(self) + #parameters: ldns_resolver *, + #retvals: ldns_rdf * + + def port(self): + """Get the port the resolver should use. + + :returns: (uint16_t) the port number + """ + return _ldns.ldns_resolver_port(self) + #parameters: const ldns_resolver *, + #retvals: uint16_t + + def prepare_query_pkt(self,name,t,c,f): + """Form a query packet from a resolver and name/type/class combo. + + :param name: + :param t: + query for this type (may be 0, defaults to A) + :param c: + query for this class (may be 0, default to IN) + :param f: + the query flags + :returns: * (ldns_status) ldns_pkt* a packet with the reply from the nameserver + * (ldns_pkt \*\*) query packet class + """ + return _ldns.ldns_resolver_prepare_query_pkt(self,name,t,c,f) + #parameters: ldns_resolver *,const ldns_rdf *,ldns_rr_type,ldns_rr_class,uint16_t, + #retvals: ldns_status,ldns_pkt ** + + def push_dnssec_anchor(self,rr): + """Push a new trust anchor to the resolver. + + It must be a DS or DNSKEY rr + + :param rr: + the RR to add as a trust anchor. + :returns: (ldns_status) a status + """ + return _ldns.ldns_resolver_push_dnssec_anchor(self,rr) + #parameters: ldns_resolver *,ldns_rr *, + #retvals: ldns_status + + def push_nameserver(self,n): + """push a new nameserver to the resolver. + + It must be an IP address v4 or v6. + + :param n: + the ip address + :returns: (ldns_status) ldns_status a status + """ + return _ldns.ldns_resolver_push_nameserver(self,n) + #parameters: ldns_resolver *,ldns_rdf *, + #retvals: ldns_status + + def push_nameserver_rr(self,rr): + """push a new nameserver to the resolver. + + It must be an A or AAAA RR record type + + :param rr: + the resource record + :returns: (ldns_status) ldns_status a status + """ + return _ldns.ldns_resolver_push_nameserver_rr(self,rr) + #parameters: ldns_resolver *,ldns_rr *, + #retvals: ldns_status + + def push_nameserver_rr_list(self,rrlist): + """push a new nameserver rr_list to the resolver. + + :param rrlist: + the rr_list to push + :returns: (ldns_status) ldns_status a status + """ + return _ldns.ldns_resolver_push_nameserver_rr_list(self,rrlist) + #parameters: ldns_resolver *,ldns_rr_list *, + #retvals: ldns_status + + def push_searchlist(self,rd): + """Push a new rd to the resolver's searchlist. + + :param rd: + to push + """ + _ldns.ldns_resolver_push_searchlist(self,rd) + #parameters: ldns_resolver *,ldns_rdf *, + #retvals: + + def query(self,name,atype=_ldns.LDNS_RR_TYPE_A,aclass=_ldns.LDNS_RR_CLASS_IN,flags=_ldns.LDNS_RD): + """Send a query to a nameserver. + + :param name: (ldns_rdf) the name to look for + :param atype: the RR type to use + :param aclass: the RR class to use + :param flags: give some optional flags to the query + :returns: (ldns_pkt) a packet with the reply from the nameserver if _defnames is true the default domain will be added + """ + return _ldns.ldns_resolver_query(self,name,atype,aclass,flags) + #parameters: const ldns_resolver *,const ldns_rdf *,ldns_rr_type,ldns_rr_class,uint16_t, + #retvals: ldns_pkt * + + def random(self): + """Does the resolver randomize the nameserver before usage. + + :returns: (bool) true: yes, false: no + """ + return _ldns.ldns_resolver_random(self) + #parameters: const ldns_resolver *, + #retvals: bool + + def recursive(self): + """Is the resolver set to recurse. + + :returns: (bool) true if so, otherwise false + """ + return _ldns.ldns_resolver_recursive(self) + #parameters: const ldns_resolver *, + #retvals: bool + + def retrans(self): + """Get the retransmit interval. + + :returns: (uint8_t) the retransmit interval + """ + return _ldns.ldns_resolver_retrans(self) + #parameters: const ldns_resolver *, + #retvals: uint8_t + + def retry(self): + """Get the number of retries. + + :returns: (uint8_t) the number of retries + """ + return _ldns.ldns_resolver_retry(self) + #parameters: const ldns_resolver *, + #retvals: uint8_t + + def rtt(self): + """Return the used round trip times for the nameservers. + + :returns: (size_t \*) a size_t* pointer to the list. yet) + """ + return _ldns.ldns_resolver_rtt(self) + #parameters: const ldns_resolver *, + #retvals: size_t * + + def search(self,rdf,t,c,flags): + """Send the query for using the resolver and take the search list into account The search algorithm is as follows: If the name is absolute, try it as-is, otherwise apply the search list. + + :param rdf: + :param t: + query for this type (may be 0, defaults to A) + :param c: + query for this class (may be 0, default to IN) + :param flags: + the query flags + :returns: (ldns_pkt \*) ldns_pkt* a packet with the reply from the nameserver + """ + return _ldns.ldns_resolver_search(self,rdf,t,c,flags) + #parameters: const ldns_resolver *,const ldns_rdf *,ldns_rr_type,ldns_rr_class,uint16_t, + #retvals: ldns_pkt * + + def searchlist(self): + """What is the searchlist as used by the resolver. + + :returns: (ldns_rdf \*\*) a ldns_rdf pointer to a list of the addresses + """ + return _ldns.ldns_resolver_searchlist(self) + #parameters: const ldns_resolver *, + #retvals: ldns_rdf \*\* + + def searchlist_count(self): + """Return the resolver's searchlist count. + + :returns: (size_t) the searchlist count + """ + return _ldns.ldns_resolver_searchlist_count(self) + #parameters: const ldns_resolver *, + #retvals: size_t + + def send(self,name,t,c,flags): + """Send the query for name as-is. + + :param name: + :param t: + query for this type (may be 0, defaults to A) + :param c: + query for this class (may be 0, default to IN) + :param flags: + the query flags + :returns: * (ldns_status) ldns_pkt* a packet with the reply from the nameserver + * (ldns_pkt \*\*) + """ + return _ldns.ldns_resolver_send(self,name,t,c,flags) + #parameters: ldns_resolver *,const ldns_rdf *,ldns_rr_type,ldns_rr_class,uint16_t, + #retvals: ldns_status,ldns_pkt ** + + def send_pkt(self,query_pkt): + """Send the given packet to a nameserver. + + :param query_pkt: + :returns: * (ldns_status) + * (ldns_pkt \*\*) + """ + return _ldns.ldns_resolver_send_pkt(self,query_pkt) + #parameters: ldns_resolver *,ldns_pkt *, + #retvals: ldns_status,ldns_pkt ** + + def set_debug(self,b): + """Set the resolver debugging. + + :param b: + true: debug on: false debug off + """ + _ldns.ldns_resolver_set_debug(self,b) + #parameters: ldns_resolver *,bool, + #retvals: + + def set_defnames(self,b): + """Whether the resolver uses the name set with _set_domain. + + :param b: + true: use the defaults, false: don't use them + """ + _ldns.ldns_resolver_set_defnames(self,b) + #parameters: ldns_resolver *,bool, + #retvals: + + def set_dnsrch(self,b): + """Whether the resolver uses the searchlist. + + :param b: + true: use the list, false: don't use the list + """ + _ldns.ldns_resolver_set_dnsrch(self,b) + #parameters: ldns_resolver *,bool, + #retvals: + + def set_dnssec(self,b): + """Whether the resolver uses DNSSEC. + + :param b: + true: use DNSSEC, false: don't use DNSSEC + """ + _ldns.ldns_resolver_set_dnssec(self,b) + #parameters: ldns_resolver *,bool, + #retvals: + + def set_dnssec_anchors(self,l): + """Set the resolver's DNSSEC anchor list directly. + + RRs should be of type DS or DNSKEY. + + :param l: + the list of RRs to use as trust anchors + """ + _ldns.ldns_resolver_set_dnssec_anchors(self,l) + #parameters: ldns_resolver *,ldns_rr_list *, + #retvals: + + def set_dnssec_cd(self,b): + """Whether the resolver uses the checking disable bit. + + :param b: + true: enable , false: don't use TCP + """ + _ldns.ldns_resolver_set_dnssec_cd(self,b) + #parameters: ldns_resolver *,bool, + #retvals: + + def set_domain(self,rd): + """Set the resolver's default domain. + + This gets appended when no absolute name is given + + :param rd: + the name to append + """ + _ldns.ldns_resolver_set_domain(self,rd) + #parameters: ldns_resolver *,ldns_rdf *, + #retvals: + + def set_edns_udp_size(self,s): + """Set maximum udp size. + + :param s: + the udp max size + """ + _ldns.ldns_resolver_set_edns_udp_size(self,s) + #parameters: ldns_resolver *,uint16_t, + #retvals: + + def set_fail(self,b): + """Whether or not to fail after one failed query. + + :param b: + true: yes fail, false: continue with next nameserver + """ + _ldns.ldns_resolver_set_fail(self,b) + #parameters: ldns_resolver *,bool, + #retvals: + + def set_fallback(self,fallback): + """Set whether the resolvers truncation fallback mechanism is used when ldns_resolver_query() is called. + + :param fallback: + whether to use the fallback mechanism + """ + _ldns.ldns_resolver_set_fallback(self,fallback) + #parameters: ldns_resolver *,bool, + #retvals: + + def set_igntc(self,b): + """Whether or not to ignore the TC bit. + + :param b: + true: yes ignore, false: don't ignore + """ + _ldns.ldns_resolver_set_igntc(self,b) + #parameters: ldns_resolver *,bool, + #retvals: + + def set_ip6(self,i): + """Whether the resolver uses ip6. + + :param i: + 0: no pref, 1: ip4, 2: ip6 + """ + _ldns.ldns_resolver_set_ip6(self,i) + #parameters: ldns_resolver *,uint8_t, + #retvals: + + def set_nameserver_count(self,c): + """Set the resolver's nameserver count directly. + + :param c: + the nameserver count + """ + _ldns.ldns_resolver_set_nameserver_count(self,c) + #parameters: ldns_resolver *,size_t, + #retvals: + + def set_nameserver_rtt(self,pos,value): + """Set round trip time for a specific nameserver. + + Note this currently differentiates between: unreachable and reachable. + + :param pos: + the nameserver position + :param value: + the rtt + """ + _ldns.ldns_resolver_set_nameserver_rtt(self,pos,value) + #parameters: ldns_resolver *,size_t,size_t, + #retvals: + + def set_nameservers(self,rd): + """Set the resolver's nameserver count directly by using an rdf list. + + :param rd: + the resolver addresses + """ + _ldns.ldns_resolver_set_nameservers(self,rd) + #parameters: ldns_resolver *,ldns_rdf **, + #retvals: + + def set_port(self,p): + """Set the port the resolver should use. + + :param p: + the port number + """ + _ldns.ldns_resolver_set_port(self,p) + #parameters: ldns_resolver *,uint16_t, + #retvals: + + def set_random(self,b): + """Should the nameserver list be randomized before each use. + + :param b: + true: randomize, false: don't + """ + _ldns.ldns_resolver_set_random(self,b) + #parameters: ldns_resolver *,bool, + #retvals: + + def set_recursive(self,b): + """Set the resolver recursion. + + :param b: + true: set to recurse, false: unset + """ + _ldns.ldns_resolver_set_recursive(self,b) + #parameters: ldns_resolver *,bool, + #retvals: + + def set_retrans(self,re): + """Set the resolver retrans timeout (in seconds). + + :param re: + the retransmission interval in seconds + """ + _ldns.ldns_resolver_set_retrans(self,re) + #parameters: ldns_resolver *,uint8_t, + #retvals: + + def set_retry(self,re): + """Set the resolver retry interval (in seconds). + + :param re: + the retry interval + """ + _ldns.ldns_resolver_set_retry(self,re) + #parameters: ldns_resolver *,uint8_t, + #retvals: + + def set_rtt(self,rtt): + """Set round trip time for all nameservers. + + Note this currently differentiates between: unreachable and reachable. + + :param rtt: + a list with the times + """ + _ldns.ldns_resolver_set_rtt(self,rtt) + #parameters: ldns_resolver *,size_t *, + #retvals: + + def set_searchlist_count(self,c): + _ldns.ldns_resolver_set_searchlist_count(self,c) + #parameters: ldns_resolver *,size_t, + #retvals: + + def set_timeout(self,timeout): + """Set the resolver's socket time out when talking to remote hosts. + + :param timeout: + the timeout to use + """ + _ldns.ldns_resolver_set_timeout(self,timeout) + #parameters: ldns_resolver *,struct timeval, + #retvals: + + def set_tsig_algorithm(self,tsig_algorithm): + """Set the tsig algorithm. + + :param tsig_algorithm: + the tsig algorithm + """ + _ldns.ldns_resolver_set_tsig_algorithm(self,tsig_algorithm) + #parameters: ldns_resolver *,char *, + #retvals: + + def set_tsig_keydata(self,tsig_keydata): + """Set the tsig key data. + + :param tsig_keydata: + the key data + """ + _ldns.ldns_resolver_set_tsig_keydata(self,tsig_keydata) + #parameters: ldns_resolver *,char *, + #retvals: + + def set_tsig_keyname(self,tsig_keyname): + """Set the tsig key name. + + :param tsig_keyname: + the tsig key name + """ + _ldns.ldns_resolver_set_tsig_keyname(self,tsig_keyname) + #parameters: ldns_resolver *,char *, + #retvals: + + def set_usevc(self,b): + """Whether the resolver uses a virtual circuit (TCP). + + :param b: + true: use TCP, false: don't use TCP + """ + _ldns.ldns_resolver_set_usevc(self,b) + #parameters: ldns_resolver *,bool, + #retvals: + + def timeout(self): + """What is the timeout on socket connections. + + :returns: (struct timeval) the timeout as struct timeval + """ + return _ldns.ldns_resolver_timeout(self) + #parameters: const ldns_resolver *, + #retvals: struct timeval + + def trusted_key(self,keys,trusted_keys): + """Returns true if at least one of the provided keys is a trust anchor. + + :param keys: + the keyset to check + :param trusted_keys: + the subset of trusted keys in the 'keys' rrset + :returns: (bool) true if at least one of the provided keys is a configured trust anchor + """ + return _ldns.ldns_resolver_trusted_key(self,keys,trusted_keys) + #parameters: const ldns_resolver *,ldns_rr_list *,ldns_rr_list *, + #retvals: bool + + def tsig_algorithm(self): + """Return the tsig algorithm as used by the nameserver. + + :returns: (char \*) the algorithm used. + """ + return _ldns.ldns_resolver_tsig_algorithm(self) + #parameters: const ldns_resolver *, + #retvals: char * + + def tsig_keydata(self): + """Return the tsig keydata as used by the nameserver. + + :returns: (char \*) the keydata used. + """ + return _ldns.ldns_resolver_tsig_keydata(self) + #parameters: const ldns_resolver *, + #retvals: char * + + def tsig_keyname(self): + """Return the tsig keyname as used by the nameserver. + + :returns: (char \*) the name used. + """ + return _ldns.ldns_resolver_tsig_keyname(self) + #parameters: const ldns_resolver *, + #retvals: char * + + def usevc(self): + """Does the resolver use tcp or udp. + + :returns: (bool) true: tcp, false: udp + """ + return _ldns.ldns_resolver_usevc(self) + #parameters: const ldns_resolver *, + #retvals: bool + + #_LDNS_RESOLVER_METHODS# + %} +} diff --git a/contrib/python/ldns_rr.i b/contrib/python/ldns_rr.i new file mode 100644 index 00000000000..1a9f3f1c21b --- /dev/null +++ b/contrib/python/ldns_rr.i @@ -0,0 +1,1584 @@ +/****************************************************************************** + * ldns_rr.i: LDNS resource records (RR), RR list + * + * Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz) + * Karel Slany (slany AT fit.vutbr.cz) + * 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 the organization 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. + ******************************************************************************/ + +%typemap(in,numinputs=0,noblock=1) (ldns_rr **) +{ + ldns_rr *$1_rr; + $1 = &$1_rr; +} + +/* result generation */ +%typemap(argout,noblock=1) (ldns_rr **) +{ + $result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(SWIG_as_voidptr($1_rr), SWIGTYPE_p_ldns_struct_rr, SWIG_POINTER_OWN | 0 )); +} + +%nodefaultctor ldns_struct_rr; //no default constructor & destructor +%nodefaultdtor ldns_struct_rr; + +%ignore ldns_struct_rr::_rdata_fields; + +%newobject ldns_rr_clone; +%newobject ldns_rr_new; +%newobject ldns_rr_pop_rdf; +%delobject ldns_rr_free; + +%rename(ldns_rr) ldns_struct_rr; + +#ifdef LDNS_DEBUG +%rename(__ldns_rr_free) ldns_rr_free; +%inline %{ +void _ldns_rr_free (ldns_rr* r) { + printf("******** LDNS_RR free 0x%lX ************\n", (long unsigned int)r); + ldns_rr_free(r); +} +%} +#else +%rename(_ldns_rr_free) ldns_rr_free; +#endif + +%newobject ldns_rr2str; +%newobject ldns_rr_type2str; +%newobject ldns_rr_class2str; +%newobject ldns_read_anchor_file; + + +// clone rdf data on pull + +%newobject _ldns_rr_rdf; +%rename(__ldns_rr_rdf) ldns_rr_rdf; +%inline %{ +ldns_rdf* _ldns_rr_rdf(ldns_rr* rr, size_t i) { + return ldns_rdf_clone(ldns_rr_rdf(rr, i)); +} +%} + +%newobject _ldns_rr_rrsig_algorithm; +%rename(__ldns_rr_rrsig_algorithm) ldns_rr_rrsig_algorithm; +%inline %{ +ldns_rdf* _ldns_rr_rrsig_algorithm(ldns_rr* rr) { + return ldns_rdf_clone(ldns_rr_rrsig_algorithm(rr)); +} +%} + +%newobject _ldns_rr_dnskey_algorithm; +%rename(__ldns_rr_dnskey_algorithm) ldns_rr_dnskey_algorithm; +%inline %{ +ldns_rdf* _ldns_rr_dnskey_algorithm(ldns_rr* rr) { + return ldns_rdf_clone(ldns_rr_dnskey_algorithm(rr)); +} +%} + +%newobject _ldns_rr_dnskey_flags; +%rename(__ldns_rr_dnskey_flags) ldns_rr_dnskey_flags; +%inline %{ +ldns_rdf* _ldns_rr_dnskey_flags(ldns_rr* rr) { + return ldns_rdf_clone(ldns_rr_dnskey_flags(rr)); +} +%} + +%newobject _ldns_rr_dnskey_key; +%rename(__ldns_rr_dnskey_key) ldns_rr_dnskey_key; +%inline %{ +ldns_rdf* _ldns_rr_dnskey_key(ldns_rr* rr) { + return ldns_rdf_clone(ldns_rr_dnskey_key(rr)); +} +%} + +%newobject _ldns_rr_dnskey_protocol; +%rename(__ldns_rr_dnskey_protocol) ldns_rr_dnskey_protocol; +%inline %{ +ldns_rdf* _ldns_rr_dnskey_protocol(ldns_rr* rr) { + return ldns_rdf_clone(ldns_rr_dnskey_protocol(rr)); +} +%} + + +%newobject _ldns_rr_owner; +%rename(__ldns_rr_owner) ldns_rr_owner; +%inline %{ +ldns_rdf* _ldns_rr_owner(ldns_rr* rr) { + return ldns_rdf_clone(ldns_rr_owner(rr)); +} +%} + + +%newobject _ldns_rr_a_address; +%rename(__ldns_rr_a_address) ldns_rr_a_address; +%inline %{ +ldns_rdf* _ldns_rr_a_address(ldns_rr* rr) { + return ldns_rdf_clone(ldns_rr_a_address(rr)); +} +%} + + +%newobject _ldns_rr_mx_exchange; +%rename(__ldns_rr_mx_exchange) ldns_rr_mx_exchange; +%inline %{ +ldns_rdf* _ldns_rr_mx_exchange(ldns_rr* rr) { + return ldns_rdf_clone(ldns_rr_mx_exchange(rr)); +} +%} + + +%newobject _ldns_rr_mx_preference; +%rename(__ldns_rr_mx_preference) ldns_rr_mx_preference; +%inline %{ +ldns_rdf* _ldns_rr_mx_preference(ldns_rr* rr) { + return ldns_rdf_clone(ldns_rr_mx_preference(rr)); +} +%} + + +%newobject _ldns_rr_ns_nsdname; +%rename(__ldns_rr_ns_nsdname) ldns_rr_ns_nsdname; +%inline %{ +ldns_rdf* _ldns_rr_ns_nsdname(ldns_rr* rr) { + return ldns_rdf_clone(ldns_rr_ns_nsdname(rr)); +} +%} + + +%newobject _ldns_rr_rrsig_expiration; +%rename(__ldns_rr_rrsig_expiration) ldns_rr_rrsig_expiration; +%inline %{ +ldns_rdf* _ldns_rr_rrsig_expiration(ldns_rr* rr) { + return ldns_rdf_clone(ldns_rr_rrsig_expiration(rr)); +} +%} + + +%newobject _ldns_rr_rrsig_inception; +%rename(__ldns_rr_rrsig_inception) ldns_rr_rrsig_inception; +%inline %{ +ldns_rdf* _ldns_rr_rrsig_inception(ldns_rr* rr) { + return ldns_rdf_clone(ldns_rr_rrsig_inception(rr)); +} +%} + + +%newobject _ldns_rr_rrsig_keytag; +%rename(__ldns_rr_rrsig_keytag) ldns_rr_rrsig_keytag; +%inline %{ +ldns_rdf* _ldns_rr_rrsig_keytag(ldns_rr* rr) { + return ldns_rdf_clone(ldns_rr_rrsig_keytag(rr)); +} +%} + + +%newobject _ldns_rr_rrsig_labels; +%rename(__ldns_rr_rrsig_labels) ldns_rr_rrsig_labels; +%inline %{ +ldns_rdf* _ldns_rr_rrsig_labels(ldns_rr* rr) { + return ldns_rdf_clone(ldns_rr_rrsig_labels(rr)); +} +%} + + +%newobject _ldns_rr_rrsig_origttl; +%rename(__ldns_rr_rrsig_origttl) ldns_rr_rrsig_origttl; +%inline %{ +ldns_rdf* _ldns_rr_rrsig_origttl(ldns_rr* rr) { + return ldns_rdf_clone(ldns_rr_rrsig_origttl(rr)); +} +%} + + +%newobject _ldns_rr_rrsig_sig; +%rename(__ldns_rr_rrsig_sig) ldns_rr_rrsig_sig; +%inline %{ +ldns_rdf* _ldns_rr_rrsig_sig(ldns_rr* rr) { + return ldns_rdf_clone(ldns_rr_rrsig_sig(rr)); +} +%} + + +%newobject _ldns_rr_rrsig_signame; +%rename(__ldns_rr_rrsig_signame) ldns_rr_rrsig_signame; +%inline %{ +ldns_rdf* _ldns_rr_rrsig_signame(ldns_rr* rr) { + return ldns_rdf_clone(ldns_rr_rrsig_signame(rr)); +} +%} + + +%newobject _ldns_rr_rrsig_typecovered; +%rename(__ldns_rr_rrsig_typecovered) ldns_rr_rrsig_typecovered; +%inline %{ +ldns_rdf* _ldns_rr_rrsig_typecovered(ldns_rr* rr) { + return ldns_rdf_clone(ldns_rr_rrsig_typecovered(rr)); +} +%} + +// end of pull cloning + +// clone rdf data on push + +%rename(__ldns_rr_a_set_address) ldns_rr_a_set_address; +%inline %{ +bool _ldns_rr_a_set_address(ldns_rr* rr, ldns_rdf* rdf) { + return ldns_rr_a_set_address(rr, ldns_rdf_clone(rdf)); +} +%} + +%rename(__ldns_rr_dnskey_set_algorithm) ldns_rr_dnskey_set_algorithm; +%inline %{ +bool _ldns_rr_dnskey_set_algorithm(ldns_rr* rr, ldns_rdf* rdf) { + return ldns_rr_dnskey_set_algorithm(rr, ldns_rdf_clone(rdf)); +} +%} + +%rename(__ldns_rr_dnskey_set_flags) ldns_rr_dnskey_set_flags; +%inline %{ +bool _ldns_rr_dnskey_set_flags(ldns_rr* rr, ldns_rdf* rdf) { + return ldns_rr_dnskey_set_flags(rr, ldns_rdf_clone(rdf)); +} +%} + +%rename(__ldns_rr_dnskey_set_key) ldns_rr_dnskey_set_key; +%inline %{ +bool _ldns_rr_dnskey_set_key(ldns_rr* rr, ldns_rdf* rdf) { + return ldns_rr_dnskey_set_key(rr, ldns_rdf_clone(rdf)); +} +%} + +%rename(__ldns_rr_dnskey_set_protocol) ldns_rr_dnskey_set_protocol; +%inline %{ +bool _ldns_rr_dnskey_set_protocol(ldns_rr* rr, ldns_rdf* rdf) { + return ldns_rr_dnskey_set_protocol(rr, ldns_rdf_clone(rdf)); +} +%} + +%rename(__ldns_rr_push_rdf) ldns_rr_push_rdf; +%inline %{ +bool _ldns_rr_push_rdf(ldns_rr* rr, ldns_rdf* rdf) { + return ldns_rr_push_rdf(rr, ldns_rdf_clone(rdf)); +} +%} + +%rename(__ldns_rr_rrsig_set_algorithm) ldns_rr_rrsig_set_algorithm; +%inline %{ +bool _ldns_rr_rrsig_set_algorithm(ldns_rr* rr, ldns_rdf* rdf) { + return ldns_rr_rrsig_set_algorithm(rr, ldns_rdf_clone(rdf)); +} +%} + +%rename(__ldns_rr_rrsig_set_expiration) ldns_rr_rrsig_set_expiration; +%inline %{ +bool _ldns_rr_rrsig_set_expiration(ldns_rr* rr, ldns_rdf* rdf) { + return ldns_rr_rrsig_set_expiration(rr, ldns_rdf_clone(rdf)); +} +%} + +%rename(__ldns_rr_rrsig_set_inception) ldns_rr_rrsig_set_inception; +%inline %{ +bool _ldns_rr_rrsig_set_inception(ldns_rr* rr, ldns_rdf* rdf) { + return ldns_rr_rrsig_set_inception(rr, ldns_rdf_clone(rdf)); +} +%} + +%rename(__ldns_rr_rrsig_set_keytag) ldns_rr_rrsig_set_keytag; +%inline %{ +bool _ldns_rr_rrsig_set_keytag(ldns_rr* rr, ldns_rdf* rdf) { + return ldns_rr_rrsig_set_keytag(rr, ldns_rdf_clone(rdf)); +} +%} + +%rename(__ldns_rr_rrsig_set_labels) ldns_rr_rrsig_set_labels; +%inline %{ +bool _ldns_rr_rrsig_set_labels(ldns_rr* rr, ldns_rdf* rdf) { + return ldns_rr_rrsig_set_labels(rr, ldns_rdf_clone(rdf)); +} +%} + +%rename(__ldns_rr_rrsig_set_origttl) ldns_rr_rrsig_set_origttl; +%inline %{ +bool _ldns_rr_rrsig_set_origttl(ldns_rr* rr, ldns_rdf* rdf) { + return ldns_rr_rrsig_set_origttl(rr, ldns_rdf_clone(rdf)); +} +%} + +%rename(__ldns_rr_rrsig_set_sig) ldns_rr_rrsig_set_sig; +%inline %{ +bool _ldns_rr_rrsig_set_sig(ldns_rr* rr, ldns_rdf* rdf) { + return ldns_rr_rrsig_set_sig(rr, ldns_rdf_clone(rdf)); +} +%} + +%rename(__ldns_rr_rrsig_set_signame) ldns_rr_rrsig_set_signame; +%inline %{ +bool _ldns_rr_rrsig_set_signame(ldns_rr* rr, ldns_rdf* rdf) { + return ldns_rr_rrsig_set_signame(rr, ldns_rdf_clone(rdf)); +} +%} + +%rename(__ldns_rr_rrsig_set_typecovered) ldns_rr_rrsig_set_typecovered; +%inline %{ +bool _ldns_rr_rrsig_set_typecovered(ldns_rr* rr, ldns_rdf* rdf) { + return ldns_rr_rrsig_set_typecovered(rr, ldns_rdf_clone(rdf)); +} +%} + +%rename(__ldns_rr_set_owner) ldns_rr_set_owner; +%inline %{ +void _ldns_rr_set_owner(ldns_rr* rr, ldns_rdf* rdf) { + return ldns_rr_set_owner(rr, ldns_rdf_clone(rdf)); +} +%} + +%rename(__ldns_rr_set_rdf) ldns_rr_set_rdf; +%inline %{ + ldns_rdf* _ldns_rr_set_rdf(ldns_rr* rr, ldns_rdf* rdf, size_t pos) { + return ldns_rr_set_rdf(rr, ldns_rdf_clone(rdf), pos); +} +%} + +// end of push cloning + +%rename(_ldns_rr_new_frm_str) ldns_rr_new_frm_str; +%rename(_ldns_rr_new_frm_fp_l) ldns_rr_new_frm_fp_l; +%rename(_ldns_rr_new_frm_fp) ldns_rr_new_frm_fp; + +%feature("docstring") ldns_struct_rr "Resource Record (RR) + +The RR is the basic DNS element that contains actual data. This class allows to create RR and manipulate with the content." + +%extend ldns_struct_rr { + + %pythoncode %{ + def __init__(self): + raise Exception("This class can't be created directly. Please use: ldns_rr_new, ldns_rr_new_frm_type, new_frm_fp(), new_frm_fp_l(), new_frm_str() or new_question_frm_str") + + __swig_destroy__ = _ldns._ldns_rr_free + + #LDNS_RR_CONSTRUCTORS_# + @staticmethod + def new_frm_str(str, default_ttl=0, origin=None, prev=None, raiseException=True): + """Creates an rr object from a string. + + The string should be a fully filled-in rr, like ownername [space] TTL [space] CLASS [space] TYPE [space] RDATA. + + :param str: the string to convert + :param default_ttl: default ttl value for the rr. If 0 DEF_TTL will be used + :param origin: when the owner is relative add this + :param prev: the previous ownername + :param raiseException: if True, an exception occurs in case a rr instance can't be created + :returns: + * rr - (ldnsrr) RR instance or None. If the object can't be created and raiseException is True, an exception occurs. + + **Usage** + + >>> import ldns + >>> rr = ldns.ldns_rr.new_frm_str("www.nic.cz. IN A 192.168.1.1",300) + >>> print rr + www.nic.cz. 300 IN A 192.168.1.1 + """ + status, rr, prev = _ldns.ldns_rr_new_frm_str_(str, default_ttl, origin, prev) + if status != LDNS_STATUS_OK: + if (raiseException): raise Exception("Can't create RR, error: %d" % status) + return None + return rr + + @staticmethod + def new_question_frm_str(str, default_ttl=0, origin=None, prev=None, raiseException=True): + """Creates an rr object from a string. + + The string is like new_frm_str but without rdata. + + :param str: the string to convert + :param origin: when the owner is relative add this + :param prev: the previous ownername + :param raiseException: if True, an exception occurs in case a rr instance can't be created + :returns: + * rr - (ldnsrr) RR instance or None. If the object can't be created and raiseException is True, an exception occurs. + """ + status, rr, prev = _ldns.ldns_rr_new_question_frm_str_(str, origin, prev) + if status != LDNS_STATUS_OK: + if (raiseException): raise Exception("Can't create RR, error: %d" % status) + return None + return rr + + @staticmethod + def new_frm_str_prev(str, default_ttl=0, origin=None, prev=None, raiseException=True): + """Creates an rr object from a string. + + The string should be a fully filled-in rr, like ownername [space] TTL [space] CLASS [space] TYPE [space] RDATA. + + :param str: the string to convert + :param default_ttl: default ttl value for the rr. If 0 DEF_TTL will be used + :param origin: when the owner is relative add this + :param prev: the previous ownername + :param raiseException: if True, an exception occurs in case a rr instance can't be created + :returns: + * rr - (ldnsrr) RR instance or None. If the object can't be created and raiseException is True, an exception occurs. + + * prev - (ldns_rdf) ownername found in this string or None + """ + status, rr, prev = _ldns.ldns_rr_new_frm_str_(str, default_ttl, origin, prev) + if status != LDNS_STATUS_OK: + if (raiseException): raise Exception("Can't create RR, error: %d" % status) + return None + return rr, prev + + @staticmethod + def new_frm_fp(file, default_ttl=0, origin=None, prev=None, raiseException=True): + """Creates a new rr from a file containing a string. + + :param file: file pointer + :param default_ttl: If 0 DEF_TTL will be used + :param origin: when the owner is relative add this. + :param prev: when the owner is whitespaces use this. + :param raiseException: if True, an exception occurs in case a resolver object can't be created + :returns: + * rr - (ldns_rr) RR object or None. If the object can't be created and raiseException is True, an exception occurs. + + * ttl - (int) None or TTL if the file contains a $TTL directive + + * origin - (ldns_rdf) None or dname if the file contains a $ORIGIN directive + + * prev - (ldns_rdf) None or updated value of prev parameter + """ + res = _ldns.ldns_rr_new_frm_fp_l_(file, default_ttl, origin, prev, 0) + if res[0] != LDNS_STATUS_OK: + if (raiseException): raise Exception("Can't create RR, error: %d" % res[0]) + return None + return res[1:] + + @staticmethod + def new_frm_fp_l(file, default_ttl=0, origin=None, prev=None, raiseException=True): + """Creates a new rr from a file containing a string. + + :param file: file pointer + :param default_ttl: If 0 DEF_TTL will be used + :param origin: when the owner is relative add this. + :param prev: when the owner is whitespaces use this. + :param raiseException: if True, an exception occurs in case a resolver object can't be created + :returns: + * rr - (ldns_rr) RR object or None. If the object can't be created and raiseException is True, an exception occurs. + + * line - (int) line number (for debugging) + + * ttl - (int) None or TTL if the file contains a $TTL directive + + * origin - (ldns_rdf) None or dname if the file contains a $ORIGIN directive + + * prev - (ldns_rdf) None or updated value of prev parameter + """ + res = _ldns.ldns_rr_new_frm_fp_l_(file, default_ttl, origin, prev, 1) + if res[0] != LDNS_STATUS_OK: + if (raiseException): raise Exception("Can't create RR, error: %d" % res[0]) + return None + return res[1:] + #_LDNS_RR_CONSTRUCTORS# + + + def __str__(self): + """converts the data in the resource record to presentation format""" + return _ldns.ldns_rr2str(self) + + def __cmp__(self, other): + """compares two rrs. + + The TTL is not looked at. + + :param other: + the second RR one + :returns: (int) 0 if equal -1 if self comes before other RR +1 if other RR comes before self + """ + return _ldns.ldns_rr_compare(self,other) + + def rdfs(self): + """returns the list of rdata records.""" + for i in range(0,self.rd_count()): + yield self.rdf(i) + + def print_to_file(self,output): + """Prints the data in the resource record to the given file stream (in presentation format).""" + _ldns.ldns_rr_print(output,self) + #parameters: FILE *,const ldns_rr *, + + def get_type_str(self): + """Converts an RR type value to its string representation, and returns that string.""" + return _ldns.ldns_rr_type2str(self.get_type()) + #parameters: const ldns_rr_type, + + def get_class_str(self): + """Converts an RR class value to its string representation, and returns that string.""" + return _ldns.ldns_rr_class2str(self.get_class()) + #parameters: const ldns_rr_class, + + @staticmethod + def dnskey_key_size_raw(keydata,len,alg): + """get the length of the keydata in bits""" + return _ldns.ldns_rr_dnskey_key_size_raw(keydata,len,alg) + #parameters: const unsigned char *,const size_t,const ldns_algorithm, + #retvals: size_t + + def write_to_buffer(self,buffer,section): + """Copies the rr data to the buffer in wire format. + + :param buffer: buffer to append the result to buffer + :param section: the section in the packet this rr is supposed to be in (to determine whether to add rdata or not) + :returns: (ldns_status) ldns_status + """ + return _ldns.ldns_rr2buffer_wire(buffer,self,section) + #parameters: ldns_buffer *,const ldns_rr *,int, + #retvals: ldns_status + + def write_to_buffer_canonical(self,buffer,section): + """Copies the rr data to the buffer in wire format, in canonical format according to RFC3597 (every dname in rdata fields of RR's mentioned in that RFC will be lowercased). + + :param buffer: buffer to append the result to buffer + :param section: the section in the packet this rr is supposed to be in (to determine whether to add rdata or not) + :returns: (ldns_status) ldns_status + """ + return _ldns.ldns_rr2buffer_wire_canonical(buffer,self,section) + #parameters: ldns_buffer *,const ldns_rr *,int, + #retvals: ldns_status + + def write_data_to_buffer(self,buffer): + """Converts an rr's rdata to wireformat, while excluding the ownername and all the stuff before the rdata. + + This is needed in DNSSEC keytag calculation, the ds calcalution from the key and maybe elsewhere. + + :param buffer: buffer to append the result to + :returns: (ldns_status) ldns_status + """ + return _ldns.ldns_rr_rdata2buffer_wire(buffer,self) + #parameters: ldns_buffer *,const ldns_rr *, + #retvals: ldns_status + + def write_rrsig_to_buffer(self,buffer): + """Converts a rrsig to wireformat BUT EXCLUDE the rrsig rdata + + This is needed in DNSSEC verification. + + :param buffer: buffer to append the result to + :returns: (ldns_status) ldns_status + """ + return _ldns.ldns_rrsig2buffer_wire(buffer,self) + #parameters: ldns_buffer *,const ldns_rr *, + #retvals: ldns_status + + #LDNS_RR_METHODS_# + def a_address(self): + """returns the address of a LDNS_RR_TYPE_A rr + + :returns: (ldns_rdf \*) a ldns_rdf* with the address or NULL on failure + """ + return _ldns._ldns_rr_a_address(self) + #parameters: const ldns_rr *, + #retvals: ldns_rdf * + + def a_set_address(self,f): + """sets the address of a LDNS_RR_TYPE_A rr + + :param f: + the address to set + :returns: (bool) true on success, false otherwise + """ + return _ldns._ldns_rr_a_set_address(self,f) + #parameters: ldns_rr *,ldns_rdf *, + #retvals: bool + + def clone(self): + """clones a rr and all its data + + :returns: (ldns_rr \*) the new rr or NULL on failure + """ + return _ldns.ldns_rr_clone(self) + #parameters: const ldns_rr *, + #retvals: ldns_rr * + + def compare_ds(self,rr2): + """returns true of the given rr's are equal. + + Also returns true if one record is a DS that represents the same DNSKEY record as the other record + + :param rr2: + the second rr + :returns: (bool) true if equal otherwise false + """ + return _ldns.ldns_rr_compare_ds(self,rr2) + #parameters: const ldns_rr *,const ldns_rr *, + #retvals: bool + + def compare_no_rdata(self,rr2): + """compares two rrs, up to the rdata. + + :param rr2: + the second one + :returns: (int) 0 if equal -1 if rr1 comes before rr2 +1 if rr2 comes before rr1 + """ + return _ldns.ldns_rr_compare_no_rdata(self,rr2) + #parameters: const ldns_rr *,const ldns_rr *, + #retvals: int + + def dnskey_algorithm(self): + """returns the algorithm of a LDNS_RR_TYPE_DNSKEY rr + + :returns: (ldns_rdf \*) a ldns_rdf* with the algorithm or NULL on failure + """ + return _ldns._ldns_rr_dnskey_algorithm(self) + #parameters: const ldns_rr *, + #retvals: ldns_rdf * + + def dnskey_flags(self): + """returns the flags of a LDNS_RR_TYPE_DNSKEY rr + + :returns: (ldns_rdf \*) a ldns_rdf* with the flags or NULL on failure + """ + return _ldns._ldns_rr_dnskey_flags(self) + #parameters: const ldns_rr *, + #retvals: ldns_rdf * + + def dnskey_key(self): + """returns the key data of a LDNS_RR_TYPE_DNSKEY rr + + :returns: (ldns_rdf \*) a ldns_rdf* with the key data or NULL on failure + """ + return _ldns._ldns_rr_dnskey_key(self) + #parameters: const ldns_rr *, + #retvals: ldns_rdf * + + def dnskey_key_size(self): + """get the length of the keydata in bits + + :returns: (size_t) the keysize in bits + """ + return _ldns.ldns_rr_dnskey_key_size(self) + #parameters: const ldns_rr *, + #retvals: size_t + + def dnskey_protocol(self): + """returns the protocol of a LDNS_RR_TYPE_DNSKEY rr + + :returns: (ldns_rdf \*) a ldns_rdf* with the protocol or NULL on failure + """ + return _ldns._ldns_rr_dnskey_protocol(self) + #parameters: const ldns_rr *, + #retvals: ldns_rdf * + + def dnskey_set_algorithm(self,f): + """sets the algorithm of a LDNS_RR_TYPE_DNSKEY rr + + :param f: + the algorithm to set + :returns: (bool) true on success, false otherwise + """ + return _ldns._ldns_rr_dnskey_set_algorithm(self,f) + #parameters: ldns_rr *,ldns_rdf *, + #retvals: bool + + def dnskey_set_flags(self,f): + """sets the flags of a LDNS_RR_TYPE_DNSKEY rr + + :param f: + the flags to set + :returns: (bool) true on success, false otherwise + """ + return _ldns._ldns_rr_dnskey_set_flags(self,f) + #parameters: ldns_rr *,ldns_rdf *, + #retvals: bool + + def dnskey_set_key(self,f): + """sets the key data of a LDNS_RR_TYPE_DNSKEY rr + + :param f: + the key data to set + :returns: (bool) true on success, false otherwise + """ + return _ldns._ldns_rr_dnskey_set_key(self,f) + #parameters: ldns_rr *,ldns_rdf *, + #retvals: bool + + def dnskey_set_protocol(self,f): + """sets the protocol of a LDNS_RR_TYPE_DNSKEY rr + + :param f: + the protocol to set + :returns: (bool) true on success, false otherwise + """ + return _ldns._ldns_rr_dnskey_set_protocol(self,f) + #parameters: ldns_rr *,ldns_rdf *, + #retvals: bool + + def get_class(self): + """returns the class of the rr. + + :returns: (ldns_rr_class) the class of the rr + """ + return _ldns.ldns_rr_get_class(self) + #parameters: const ldns_rr *, + #retvals: ldns_rr_class + + def get_type(self): + """returns the type of the rr. + + :returns: (ldns_rr_type) the type of the rr + """ + return _ldns.ldns_rr_get_type(self) + #parameters: const ldns_rr *, + #retvals: ldns_rr_type + + def label_count(self): + """counts the number of labels of the ownername. + + :returns: (uint8_t) the number of labels + """ + return _ldns.ldns_rr_label_count(self) + #parameters: ldns_rr *, + #retvals: uint8_t + + def mx_exchange(self): + """returns the mx host of a LDNS_RR_TYPE_MX rr + + :returns: (ldns_rdf \*) a ldns_rdf* with the name of the MX host or NULL on failure + """ + return _ldns._ldns_rr_mx_exchange(self) + #parameters: const ldns_rr *, + #retvals: ldns_rdf * + + def mx_preference(self): + """returns the mx pref. + + of a LDNS_RR_TYPE_MX rr + + :returns: (ldns_rdf \*) a ldns_rdf* with the preference or NULL on failure + """ + return _ldns._ldns_rr_mx_preference(self) + #parameters: const ldns_rr *, + #retvals: ldns_rdf * + + def ns_nsdname(self): + """returns the name of a LDNS_RR_TYPE_NS rr + + :returns: (ldns_rdf \*) a ldns_rdf* with the name or NULL on failure + """ + return _ldns._ldns_rr_ns_nsdname(self) + #parameters: const ldns_rr *, + #retvals: ldns_rdf * + + def owner(self): + """returns the owner name of an rr structure. + + :returns: (ldns_rdf \*) ldns_rdf * + """ + return _ldns._ldns_rr_owner(self) + #parameters: const ldns_rr *, + #retvals: ldns_rdf * + + def pop_rdf(self): + """removes a rd_field member, it will be popped from the last position. + + :returns: (ldns_rdf \*) rdf which was popped (null if nothing) + """ + return _ldns.ldns_rr_pop_rdf(self) + #parameters: ldns_rr *, + #retvals: ldns_rdf * + + def push_rdf(self,f): + """sets rd_field member, it will be placed in the next available spot. + + :param f: + :returns: (bool) bool + """ + return _ldns._ldns_rr_push_rdf(self,f) + #parameters: ldns_rr *,const ldns_rdf *, + #retvals: bool + + def rd_count(self): + """returns the rd_count of an rr structure. + + :returns: (size_t) the rd count of the rr + """ + return _ldns.ldns_rr_rd_count(self) + #parameters: const ldns_rr *, + #retvals: size_t + + def rdf(self,nr): + """returns the rdata field member counter. + + :param nr: + the number of the rdf to return + :returns: (ldns_rdf \*) ldns_rdf * + """ + return _ldns._ldns_rr_rdf(self,nr) + #parameters: const ldns_rr *,size_t, + #retvals: ldns_rdf * + + def rrsig_algorithm(self): + """returns the algorithm of a LDNS_RR_TYPE_RRSIG RR + + :returns: (ldns_rdf \*) a ldns_rdf* with the algorithm or NULL on failure + """ + return _ldns._ldns_rr_rrsig_algorithm(self) + #parameters: const ldns_rr *, + #retvals: ldns_rdf * + + def rrsig_expiration(self): + """returns the expiration time of a LDNS_RR_TYPE_RRSIG RR + + :returns: (ldns_rdf \*) a ldns_rdf* with the expiration time or NULL on failure + """ + return _ldns._ldns_rr_rrsig_expiration(self) + #parameters: const ldns_rr *, + #retvals: ldns_rdf * + + def rrsig_inception(self): + """returns the inception time of a LDNS_RR_TYPE_RRSIG RR + + :returns: (ldns_rdf \*) a ldns_rdf* with the inception time or NULL on failure + """ + return _ldns._ldns_rr_rrsig_inception(self) + #parameters: const ldns_rr *, + #retvals: ldns_rdf * + + def rrsig_keytag(self): + """returns the keytag of a LDNS_RR_TYPE_RRSIG RR + + :returns: (ldns_rdf \*) a ldns_rdf* with the keytag or NULL on failure + """ + return _ldns._ldns_rr_rrsig_keytag(self) + #parameters: const ldns_rr *, + #retvals: ldns_rdf * + + def rrsig_labels(self): + """returns the number of labels of a LDNS_RR_TYPE_RRSIG RR + + :returns: (ldns_rdf \*) a ldns_rdf* with the number of labels or NULL on failure + """ + return _ldns._ldns_rr_rrsig_labels(self) + #parameters: const ldns_rr *, + #retvals: ldns_rdf * + + def rrsig_origttl(self): + """returns the original TTL of a LDNS_RR_TYPE_RRSIG RR + + :returns: (ldns_rdf \*) a ldns_rdf* with the original TTL or NULL on failure + """ + return _ldns._ldns_rr_rrsig_origttl(self) + #parameters: const ldns_rr *, + #retvals: ldns_rdf * + + def rrsig_set_algorithm(self,f): + """sets the algorithm of a LDNS_RR_TYPE_RRSIG rr + + :param f: + the algorithm to set + :returns: (bool) true on success, false otherwise + """ + return _ldns._ldns_rr_rrsig_set_algorithm(self,f) + #parameters: ldns_rr *,ldns_rdf *, + #retvals: bool + + def rrsig_set_expiration(self,f): + """sets the expireation date of a LDNS_RR_TYPE_RRSIG rr + + :param f: + the expireation date to set + :returns: (bool) true on success, false otherwise + """ + return _ldns._ldns_rr_rrsig_set_expiration(self,f) + #parameters: ldns_rr *,ldns_rdf *, + #retvals: bool + + def rrsig_set_inception(self,f): + """sets the inception date of a LDNS_RR_TYPE_RRSIG rr + + :param f: + the inception date to set + :returns: (bool) true on success, false otherwise + """ + return _ldns._ldns_rr_rrsig_set_inception(self,f) + #parameters: ldns_rr *,ldns_rdf *, + #retvals: bool + + def rrsig_set_keytag(self,f): + """sets the keytag of a LDNS_RR_TYPE_RRSIG rr + + :param f: + the keytag to set + :returns: (bool) true on success, false otherwise + """ + return _ldns._ldns_rr_rrsig_set_keytag(self,f) + #parameters: ldns_rr *,ldns_rdf *, + #retvals: bool + + def rrsig_set_labels(self,f): + """sets the number of labels of a LDNS_RR_TYPE_RRSIG rr + + :param f: + the number of labels to set + :returns: (bool) true on success, false otherwise + """ + return _ldns._ldns_rr_rrsig_set_labels(self,f) + #parameters: ldns_rr *,ldns_rdf *, + #retvals: bool + + def rrsig_set_origttl(self,f): + """sets the original TTL of a LDNS_RR_TYPE_RRSIG rr + + :param f: + the original TTL to set + :returns: (bool) true on success, false otherwise + """ + return _ldns._ldns_rr_rrsig_set_origttl(self,f) + #parameters: ldns_rr *,ldns_rdf *, + #retvals: bool + + def rrsig_set_sig(self,f): + """sets the signature data of a LDNS_RR_TYPE_RRSIG rr + + :param f: + the signature data to set + :returns: (bool) true on success, false otherwise + """ + return _ldns._ldns_rr_rrsig_set_sig(self,f) + #parameters: ldns_rr *,ldns_rdf *, + #retvals: bool + + def rrsig_set_signame(self,f): + """sets the signers name of a LDNS_RR_TYPE_RRSIG rr + + :param f: + the signers name to set + :returns: (bool) true on success, false otherwise + """ + return _ldns._ldns_rr_rrsig_set_signame(self,f) + #parameters: ldns_rr *,ldns_rdf *, + #retvals: bool + + def rrsig_set_typecovered(self,f): + """sets the typecovered of a LDNS_RR_TYPE_RRSIG rr + + :param f: + the typecovered to set + :returns: (bool) true on success, false otherwise + """ + return _ldns._ldns_rr_rrsig_set_typecovered(self,f) + #parameters: ldns_rr *,ldns_rdf *, + #retvals: bool + + def rrsig_sig(self): + """returns the signature data of a LDNS_RR_TYPE_RRSIG RR + + :returns: (ldns_rdf \*) a ldns_rdf* with the signature data or NULL on failure + """ + return _ldns._ldns_rr_rrsig_sig(self) + #parameters: const ldns_rr *, + #retvals: ldns_rdf * + + def rrsig_signame(self): + """returns the signers name of a LDNS_RR_TYPE_RRSIG RR + + :returns: (ldns_rdf \*) a ldns_rdf* with the signers name or NULL on failure + """ + return _ldns._ldns_rr_rrsig_signame(self) + #parameters: const ldns_rr *, + #retvals: ldns_rdf * + + def rrsig_typecovered(self): + """returns the type covered of a LDNS_RR_TYPE_RRSIG rr + + :returns: (ldns_rdf \*) a ldns_rdf* with the type covered or NULL on failure + """ + return _ldns._ldns_rr_rrsig_typecovered(self) + #parameters: const ldns_rr *, + #retvals: ldns_rdf * + + def set_class(self,rr_class): + """sets the class in the rr. + + :param rr_class: + set to this class + """ + _ldns.ldns_rr_set_class(self,rr_class) + #parameters: ldns_rr *,ldns_rr_class, + #retvals: + + def set_owner(self,owner): + """sets the owner in the rr structure. + + :param owner: + """ + _ldns._ldns_rr_set_owner(self,owner) + #parameters: ldns_rr *,ldns_rdf *, + #retvals: + + def set_rd_count(self,count): + """sets the rd_count in the rr. + + :param count: + set to this count + """ + _ldns.ldns_rr_set_rd_count(self,count) + #parameters: ldns_rr *,size_t, + #retvals: + + def set_rdf(self,f,position): + """sets a rdf member, it will be set on the position given. + + The old value is returned, like pop. + + :param f: + :param position: + the position the set the rdf + :returns: (ldns_rdf \*) the old value in the rr, NULL on failyre + """ + return _ldns._ldns_rr_set_rdf(self,f,position) + #parameters: ldns_rr *,const ldns_rdf *,size_t, + #retvals: ldns_rdf * + + def set_ttl(self,ttl): + """sets the ttl in the rr structure. + + :param ttl: + set to this ttl + """ + _ldns.ldns_rr_set_ttl(self,ttl) + #parameters: ldns_rr *,uint32_t, + #retvals: + + def set_type(self,rr_type): + """sets the type in the rr. + + :param rr_type: + set to this type + """ + _ldns.ldns_rr_set_type(self,rr_type) + #parameters: ldns_rr *,ldns_rr_type, + #retvals: + + def ttl(self): + """returns the ttl of an rr structure. + + :returns: (uint32_t) the ttl of the rr + """ + return _ldns.ldns_rr_ttl(self) + #parameters: const ldns_rr *, + #retvals: uint32_t + + def uncompressed_size(self): + """calculates the uncompressed size of an RR. + + :returns: (size_t) size of the rr + """ + return _ldns.ldns_rr_uncompressed_size(self) + #parameters: const ldns_rr *, + #retvals: size_t + + #_LDNS_RR_METHODS# + %} +} + +%nodefaultctor ldns_struct_rr_list; //no default constructor & destructor +%nodefaultdtor ldns_struct_rr_list; + +%ignore ldns_struct_rr_list::_rrs; + +%newobject ldns_rr_list_clone; +%newobject ldns_rr_list_pop_rr; +%newobject ldns_rr_list_pop_rr_list; +%newobject ldns_rr_list_pop_rrset; +%newobject ldns_rr_list_rr; +%newobject ldns_rr_list_new; +%delobject ldns_rr_list_deep_free; +%delobject ldns_rr_list_free; + +%rename(ldns_rr_list) ldns_struct_rr_list; +#ifdef LDNS_DEBUG +%rename(__ldns_rr_list_deep_free) ldns_rr_list_deep_free; +%rename(__ldns_rr_list_free) ldns_rr_list_free; +%inline %{ +void _ldns_rr_list_free(ldns_rr_list* r) { + printf("******** LDNS_RR_LIST deep free 0x%lX ************\n", (long unsigned int)r); + ldns_rr_list_deep_free(r); +} +%} +#else +%rename(_ldns_rr_list_deep_free) ldns_rr_list_deep_free; +%rename(_ldns_rr_list_free) ldns_rr_list_free; +#endif + +/* clone data on push */ + +%rename(__ldns_rr_list_push_rr) ldns_rr_list_push_rr; +%inline %{ +void _ldns_rr_list_push_rr(ldns_rr_list* r, ldns_rr *rr) { + ldns_rr_list_push_rr(r, ldns_rr_clone(rr)); +} +%} + +%rename(__ldns_rr_list_push_rr_list) ldns_rr_list_push_rr_list; +%inline %{ +void _ldns_rr_list_push_rr_list(ldns_rr_list* r, ldns_rr_list *r2) { + ldns_rr_list_push_rr_list(r, ldns_rr_list_clone(r2)); +} +%} + +%rename(__ldns_rr_list_cat) ldns_rr_list_cat; +%inline %{ +void _ldns_rr_list_cat(ldns_rr_list* r, ldns_rr_list *r2) { + ldns_rr_list_cat(r, ldns_rr_list_clone(r2)); +} +%} + + +/* clone data on pull */ + +%newobject _ldns_rr_list_rr; + +%rename(__ldns_rr_list_rr) ldns_rr_list_rr; +%inline %{ +ldns_rr* _ldns_rr_list_rr(ldns_rr_list* r, int i) { + return ldns_rr_clone(ldns_rr_list_rr(r, i)); +} +%} + +%newobject ldns_rr_list2str; + +%rename(__ldns_rr_list_owner) ldns_rr_list_owner; +%inline %{ +ldns_rdf* _ldns_rr_list_owner(ldns_rr_list* r) { + return ldns_rdf_clone(ldns_rr_list_owner(r)); +} +%} + + + +%feature("docstring") ldns_struct_rr_list "List of Resource Records. + +This class contains a list of RR's (see :class:`ldns.ldns_rr`). +" + +%extend ldns_struct_rr_list { + + %pythoncode %{ + def __init__(self): + self.this = _ldns.ldns_rr_list_new() + if not self.this: + raise Exception("Can't create new RR_LIST") + + __swig_destroy__ = _ldns._ldns_rr_list_deep_free + + #LDNS_RR_LIST_CONSTRUCTORS_# + @staticmethod + def new_frm_file(filename="/etc/hosts", raiseException=True): + """Creates an RR List object from a file content + + Goes through a file and returns a rr_list containing all the defined hosts in there. + + :param filename: the filename to use + :returns: RR List object or None. If the object can't be created and raiseException is True, an exception occurs. + + **Usage** + >>> alist = ldns.ldns_rr_list.new_frm_file() + >>> print alist + localhost. 3600 IN A 127.0.0.1 + ... + + """ + rr = _ldns.ldns_get_rr_list_hosts_frm_file(filename) + if (not rr) and (raiseException): raise Exception("Can't create RR List, error: %d" % status) + return rr + #_LDNS_RR_LIST_CONSTRUCTORS# + + def __str__(self): + """converts a list of resource records to presentation format""" + return _ldns.ldns_rr_list2str(self) + + def print_to_file(self,output): + """print a rr_list to output param[in] output the fd to print to param[in] list the rr_list to print""" + _ldns.ldns_rr_list_print(output,self) + + + def to_canonical(self): + """converts each dname in each rr in a rr_list to its canonical form.""" + _ldns.ldns_rr_list2canonical(self) + #parameters: ldns_rr_list *, + #retvals: + + def rrs(self): + """returns the list of rr records.""" + for i in range(0,self.rr_count()): + yield self.rr(i) + + def is_rrset(self): + """checks if an rr_list is a rrset.""" + return _ldns.ldns_is_rrset(self) + + def __cmp__(self,rrl2): + """compares two rr listss. + + :param rrl2: + the second one + :returns: (int) 0 if equal -1 if this list comes before rrl2 +1 if rrl2 comes before this list + """ + return _ldns.ldns_rr_list_compare(self,rrl2) + + def write_to_buffer(self, buffer): + """Copies the rr_list data to the buffer in wire format. + + :param buffer: output buffer to append the result to + :returns: (ldns_status) ldns_status + """ + return _ldns.ldns_rr_list2buffer_wire(buffer,self) + + #LDNS_RR_LIST_METHODS_# + def cat(self,right): + """concatenates two ldns_rr_lists together. + + This modifies rr list (to extend it and add the pointers from right). + + :param right: + the rightside + :returns: (bool) a left with right concatenated to it + """ + return _ldns._ldns_rr_list_cat(self,right) + #parameters: ldns_rr_list *,ldns_rr_list *, + #retvals: bool + + def cat_clone(self,right): + """concatenates two ldns_rr_lists together, but makes clones of the rr's (instead of pointer copying). + + :param right: + the rightside + :returns: (ldns_rr_list \*) a new rr_list with leftside/rightside concatenated + """ + return _ldns.ldns_rr_list_cat_clone(self,right) + #parameters: ldns_rr_list *,ldns_rr_list *, + #retvals: ldns_rr_list * + + def clone(self): + """clones an rrlist. + + :returns: (ldns_rr_list \*) the cloned rr list + """ + return _ldns.ldns_rr_list_clone(self) + #parameters: const ldns_rr_list *, + #retvals: ldns_rr_list * + + def contains_rr(self,rr): + """returns true if the given rr is one of the rrs in the list, or if it is equal to one + + :param rr: + the rr to check + :returns: (bool) true if rr_list contains rr, false otherwise + """ + return _ldns.ldns_rr_list_contains_rr(self,rr) + #parameters: const ldns_rr_list *,ldns_rr *, + #retvals: bool + + def owner(self): + """Returns the owner domain name rdf of the first element of the RR If there are no elements present, NULL is returned. + + :returns: (ldns_rdf \*) dname of the first element, or NULL if the list is empty + """ + return _ldns._ldns_rr_list_owner(self) + #parameters: const ldns_rr_list *, + #retvals: ldns_rdf * + + def pop_rr(self): + """pops the last rr from an rrlist. + + :returns: (ldns_rr \*) NULL if nothing to pop. Otherwise the popped RR + """ + rr = _ldns.ldns_rr_list_pop_rr(self) + #if hasattr(self, "_python_rr_refs") and rr in self._python_rr_refs: + # self._python_rr_refs.remove(rr) + return rr + #parameters: ldns_rr_list *, + #retvals: ldns_rr * + + def pop_rr_list(self,size): + """pops an rr_list of size s from an rrlist. + + :param size: + the number of rr's to pop + :returns: (ldns_rr_list \*) NULL if nothing to pop. Otherwise the popped rr_list + """ + return _ldns.ldns_rr_list_pop_rr_list(self,size) + #parameters: ldns_rr_list *,size_t, + #retvals: ldns_rr_list * + + def pop_rrset(self): + """pops the first rrset from the list, the list must be sorted, so that all rr's from each rrset are next to each other + + :returns: (ldns_rr_list \*) + """ + return _ldns.ldns_rr_list_pop_rrset(self) + #parameters: ldns_rr_list *, + #retvals: ldns_rr_list * + + def push_rr(self,rr): + """pushes an rr to an rrlist. + + :param rr: + the rr to push + :returns: (bool) false on error, otherwise true + """ + #if hasattr(self, "_python_rr_refs"): + # self._python_rr_refs.add(rr) + #else: + # self._python_rr_refs = set([rr]) + return _ldns._ldns_rr_list_push_rr(self,rr) + #parameters: ldns_rr_list *,const ldns_rr *, + #retvals: bool + + def push_rr_list(self,push_list): + """pushes an rr_list to an rrlist. + + :param push_list: + the rr_list to push + :returns: (bool) false on error, otherwise true + """ + return _ldns._ldns_rr_list_push_rr_list(self,push_list) + #parameters: ldns_rr_list *,const ldns_rr_list *, + #retvals: bool + + def rr(self,nr): + """returns a specific rr of an rrlist. + + :param nr: + return this rr + :returns: (ldns_rr \*) the rr at position nr + """ + return _ldns._ldns_rr_list_rr(self,nr) + #parameters: const ldns_rr_list *,size_t, + #retvals: ldns_rr * + + def rr_count(self): + """returns the number of rr's in an rr_list. + + :returns: (size_t) the number of rr's + """ + return _ldns.ldns_rr_list_rr_count(self) + #parameters: const ldns_rr_list *, + #retvals: size_t + + def set_rr(self,r,count): + """set a rr on a specific index in a ldns_rr_list + + :param r: + the rr to set + :param count: + index into the rr_list + :returns: (ldns_rr \*) the old rr which was stored in the rr_list, or NULL is the index was too large set a specific rr + """ + return _ldns.ldns_rr_list_set_rr(self,r,count) + #parameters: ldns_rr_list *,const ldns_rr *,size_t, + #retvals: ldns_rr * + + def set_rr_count(self,count): + """sets the number of rr's in an rr_list. + + :param count: + the number of rr in this list + """ + _ldns.ldns_rr_list_set_rr_count(self,count) + #parameters: ldns_rr_list *,size_t, + #retvals: + + def sort(self): + """sorts an rr_list (canonical wire format). + + the sorting is done inband. + """ + _ldns.ldns_rr_list_sort(self) + #parameters: ldns_rr_list *, + #retvals: + + def subtype_by_rdf(self,r,pos): + """Return the rr_list which matches the rdf at position field. + + Think type-covered stuff for RRSIG + + :param r: + the rdf to use for the comparison + :param pos: + at which position can we find the rdf + :returns: (ldns_rr_list \*) a new rr list with only the RRs that match + """ + return _ldns.ldns_rr_list_subtype_by_rdf(self,r,pos) + #parameters: ldns_rr_list *,ldns_rdf *,size_t, + #retvals: ldns_rr_list * + + def type(self): + """Returns the type of the first element of the RR If there are no elements present, 0 is returned (LDNS_RR_TYPE_A). + + :returns: (ldns_rr_type) rr_type of the first element, or 0 if the list is empty + """ + return _ldns.ldns_rr_list_type(self) + #parameters: const ldns_rr_list *, + #retvals: ldns_rr_type + #_LDNS_RR_LIST_METHODS# + %} +} + +%newobject ldns_rr_descript; + +%nodefaultctor ldns_struct_rr_descriptor; //no default constructor & destructor +%nodefaultdtor ldns_struct_rr_descriptor; +%rename(ldns_rr_descriptor) ldns_struct_rr_descriptor; + + + + +%feature("docstring") ldns_struct_rr_descriptor "Resource Record descriptor +This structure contains, for all rr types, the rdata fields that are defined." + +%extend ldns_struct_rr_descriptor { + %pythoncode %{ + def __init__(self): + raise Exception("This class can't be created directly. Please use: ldns_rr_descript") + #LDNS_RR_DESCRIPTOR_METHODS_# + def field_type(self,field): + """returns the rdf type for the given rdata field number of the rr type for the given descriptor. + + :param field: + the field number + :returns: (ldns_rdf_type) the rdf type for the field + """ + return _ldns.ldns_rr_descriptor_field_type(self,field) + #parameters: const ldns_rr_descriptor *,size_t, + #retvals: ldns_rdf_type + + def maximum(self): + """returns the maximum number of rdata fields of the rr type this descriptor describes. + + :returns: (size_t) the maximum number of rdata fields + """ + return _ldns.ldns_rr_descriptor_maximum(self) + #parameters: const ldns_rr_descriptor *, + #retvals: size_t + + def minimum(self): + """returns the minimum number of rdata fields of the rr type this descriptor describes. + + :returns: (size_t) the minimum number of rdata fields + """ + return _ldns.ldns_rr_descriptor_minimum(self) + #parameters: const ldns_rr_descriptor *, + #retvals: size_t + + #_LDNS_RR_DESCRIPTOR_METHODS# + %} +} + +/* + +rrsig checking wrappers + + copying of rr pointers into the good_keys list leads to double free + problems, therefore we provide two options - either ignore the keys + or get list of indexes of the keys. The latter allows fetching of the + keys later on from the original key set +*/ + +%rename(__ldns_verify_rrsig_keylist) ldns_verify_rrsig_keylist; +%inline %{ +ldns_status ldns_verify_rrsig_keylist_status_only(ldns_rr_list *rrset, + ldns_rr *rrsig, + const ldns_rr_list *keys) { + ldns_rr_list *good_keys = ldns_rr_list_new(); + ldns_status status = ldns_verify_rrsig_keylist(rrset, rrsig, keys, good_keys); + ldns_rr_list_free(good_keys); + return status; +} +%} + +%rename(__ldns_verify_rrsig_keylist) ldns_verify_rrsig_keylist; +%inline %{ +PyObject* ldns_verify_rrsig_keylist_(ldns_rr_list *rrset, + ldns_rr *rrsig, + const ldns_rr_list *keys) { + PyObject* tuple; + PyObject* keylist; + ldns_rr_list *good_keys = ldns_rr_list_new(); + ldns_status status = ldns_verify_rrsig_keylist(rrset, rrsig, keys, good_keys); + + tuple = PyTuple_New(2); + PyTuple_SetItem(tuple, 0, SWIG_From_int(status)); + keylist = PyList_New(0); + if (status == LDNS_STATUS_OK) { + unsigned int i; + for (i = 0; i < ldns_rr_list_rr_count(keys); i++) + if (ldns_rr_list_contains_rr(good_keys, ldns_rr_list_rr(keys, i))) + PyList_Append(keylist, SWIG_From_int(i)); + } + PyTuple_SetItem(tuple, 1, keylist); + ldns_rr_list_free(good_keys); + return tuple; + } +%} + + +%rename(__ldns_verify_rrsig_keylist_notime) ldns_verify_rrsig_keylist_notime; +%inline %{ +ldns_status ldns_verify_rrsig_keylist_notime_status_only(ldns_rr_list *rrset, + ldns_rr *rrsig, + const ldns_rr_list *keys) { + ldns_rr_list *good_keys = ldns_rr_list_new(); + ldns_status status = ldns_verify_rrsig_keylist_notime(rrset, rrsig, keys, good_keys); + ldns_rr_list_free(good_keys); + return status; +} +%} + +%rename(__ldns_verify_rrsig_keylist_notime) ldns_verify_rrsig_keylist_notime; +%inline %{ +PyObject* ldns_verify_rrsig_keylist_notime_(ldns_rr_list *rrset, + ldns_rr *rrsig, + const ldns_rr_list *keys) { + PyObject* tuple; + PyObject* keylist; + ldns_rr_list *good_keys = ldns_rr_list_new(); + ldns_status status = ldns_verify_rrsig_keylist_notime(rrset, rrsig, keys, good_keys); + + tuple = PyTuple_New(2); + PyTuple_SetItem(tuple, 0, SWIG_From_int(status)); + keylist = PyList_New(0); + if (status == LDNS_STATUS_OK) { + unsigned int i; + for (i = 0; i < ldns_rr_list_rr_count(keys); i++) + if (ldns_rr_list_contains_rr(good_keys, ldns_rr_list_rr(keys, i))) + PyList_Append(keylist, SWIG_From_int(i)); + } + PyTuple_SetItem(tuple, 1, keylist); + ldns_rr_list_free(good_keys); + return tuple; + } +%} + +/* -- end of rrsig checking wrappers */ + diff --git a/contrib/python/ldns_zone.i b/contrib/python/ldns_zone.i new file mode 100644 index 00000000000..2afdd969309 --- /dev/null +++ b/contrib/python/ldns_zone.i @@ -0,0 +1,298 @@ +/****************************************************************************** + * ldns_zone.i: LDNS zone class + * + * Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz) + * Karel Slany (slany AT fit.vutbr.cz) + * 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 the organization 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. + ******************************************************************************/ + +%typemap(in,numinputs=0,noblock=1) (ldns_zone **) +{ + ldns_zone *$1_zone; + $1 = &$1_zone; +} + +/* result generation */ +%typemap(argout,noblock=1) (ldns_zone **) +{ + $result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(SWIG_as_voidptr($1_zone), SWIGTYPE_p_ldns_struct_zone, SWIG_POINTER_OWN | 0 )); +} + +%nodefaultctor ldns_struct_zone; //no default constructor & destructor +%nodefaultdtor ldns_struct_zone; + +%newobject ldns_zone_new_frm_fp; +%newobject ldns_zone_new_frm_fp_l; +%newobject ldns_zone_new; +%delobject ldns_zone_free; +%delobject ldns_zone_deep_free; +%delobject ldns_zone_push_rr; +%delobject ldns_zone_push_rr_list; + +%ignore ldns_struct_zone::_soa; +%ignore ldns_struct_zone::_rrs; + +%rename(ldns_zone) ldns_struct_zone; + +#ifdef LDNS_DEBUG +%rename(__ldns_zone_free) ldns_zone_free; +%rename(__ldns_zone_deep_free) ldns_zone_deep_free; +%inline %{ +void _ldns_zone_free (ldns_zone* z) { + printf("******** LDNS_ZONE free 0x%lX ************\n", (long unsigned int)z); + ldns_zone_deep_free(z); +} +%} +#else +%rename(__ldns_zone_free) ldns_zone_free; +%rename(_ldns_zone_free) ldns_zone_deep_free; +#endif +%feature("docstring") ldns_struct_zone "Zone definitions + +**Usage** + +This class is able to read and parse the content of zone file by doing: + +>>> import ldns +>>> zone = ldns.ldns_zone.new_frm_fp(open(\"zone.txt\",\"r\"), None, 0, ldns.LDNS_RR_CLASS_IN) +>>> print zone.soa() +example. 600 IN SOA example. admin.example. 2008022501 28800 7200 604800 18000 +>>> print zone.rrs() +example. 600 IN MX 10 mail.example. +example. 600 IN NS ns1.example. +example. 600 IN NS ns2.example. +example. 600 IN A 192.168.1.1 + +The ``zone.txt`` file contains the following records:: + + $ORIGIN example. + $TTL 600 + + example. IN SOA example. admin.example. ( + 2008022501 ; serial + 28800 ; refresh (8 hours) + 7200 ; retry (2 hours) + 604800 ; expire (1 week) + 18000 ; minimum (5 hours) + ) + + @ IN MX 10 mail.example. + @ IN NS ns1 + @ IN NS ns2 + @ IN A 192.168.1.1 +" + +%extend ldns_struct_zone { + + %pythoncode %{ + def __init__(self): + self.this = _ldns.ldns_zone_new() + if not self.this: + raise Exception("Can't create zone.") + + __swig_destroy__ = _ldns._ldns_zone_free + + def __str__(self): + return str(self.soa()) + "\n" + str(self.rrs()) + + def print_to_file(self,output): + """Prints the data in the zone to the given file stream (in presentation format).""" + _ldns.ldns_zone_print(output,self) + #parameters: FILE *,const ldns_zone *, + + #LDNS_ZONE_CONSTRUCTORS_# + @staticmethod + def new_frm_fp(file, origin, ttl, rr_class=_ldns.LDNS_RR_CLASS_IN, raiseException=True): + """Creates a new zone object from given file pointer + + :param file: a file object + :param origin: (ldns_rdf) the zones' origin + :param ttl: default ttl to use + :param rr_class: efault class to use (IN) + :param raiseException: if True, an exception occurs in case a zone instance can't be created + :returns: zone instance or None. If an instance can't be created and raiseException is True, an exception occurs. + """ + status, zone = _ldns.ldns_zone_new_frm_fp(file, origin, ttl, rr_class) + if status != LDNS_STATUS_OK: + if (raiseException): raise Exception("Can't create zone, error: %s (%d)" % (_ldns.ldns_get_errorstr_by_id(status),status)) + return None + return zone + + @staticmethod + def new_frm_fp_l(file, origin, ttl, rr_class, raiseException=True): + """Create a new zone from a file, keep track of the line numbering + + :param file: a file object + :param origin: (ldns_rdf) the zones' origin + :param ttl: default ttl to use + :param rr_class: efault class to use (IN) + :param raiseException: if True, an exception occurs in case a zone instance can't be created + :returns: + * zone - zone instance or None. If an instance can't be created and raiseException is True, an exception occurs. + + * line - used for error msg, to get to the line number + """ + status, zone = _ldns.ldns_zone_new_frm_fp_l(file, line) + if status != LDNS_STATUS_OK: + if (raiseException): raise Exception("Can't create zone, error: %d" % status) + return None + return zone + #_LDNS_ZONE_CONSTRUCTORS# + + def sign(self,key_list): + """Signs the zone, and returns a newly allocated signed zone. + + :param key_list: + list of keys to sign with + :returns: (ldns_zone \*) signed zone + """ + return _ldns.ldns_zone_sign(self,key_list) + #parameters: const ldns_zone *,ldns_key_list *, + #retvals: ldns_zone * + + def sign_nsec3(self,key_list,algorithm,flags,iterations,salt_length,salt): + """Signs the zone with NSEC3, and returns a newly allocated signed zone. + + :param key_list: + list of keys to sign with + :param algorithm: + the NSEC3 hashing algorithm to use + :param flags: + NSEC3 flags + :param iterations: + the number of NSEC3 hash iterations to use + :param salt_length: + the length (in octets) of the NSEC3 salt + :param salt: + the NSEC3 salt data + :returns: (ldns_zone \*) signed zone + """ + return _ldns.ldns_zone_sign_nsec3(self,key_list,algorithm,flags,iterations,salt_length,salt) + #parameters: ldns_zone *,ldns_key_list *,uint8_t,uint8_t,uint16_t,uint8_t,uint8_t *, + #retvals: ldns_zone * + + #LDNS_ZONE_METHODS_# + def glue_rr_list(self): + """Retrieve all resource records from the zone that are glue records. + + The resulting list does are pointer references to the zone's data. + + Due to the current zone implementation (as a list of rr's), this function is extremely slow. Another (probably better) way to do this is to use an ldns_dnssec_zone structure and the mark_glue function + + :returns: (ldns_rr_list \*) the rr_list with the glue + """ + return _ldns.ldns_zone_glue_rr_list(self) + #parameters: const ldns_zone *, + #retvals: ldns_rr_list * + + def push_rr(self,rr): + """push an single rr to a zone structure. + + This function use pointer copying, so the rr_list structure inside z is modified! + + :param rr: + the rr to add + :returns: (bool) a true on succes otherwise falsed + """ + return _ldns.ldns_zone_push_rr(self,rr) + #parameters: ldns_zone *,ldns_rr *, + #retvals: bool + + def push_rr_list(self,list): + """push an rrlist to a zone structure. + + This function use pointer copying, so the rr_list structure inside z is modified! + + :param list: + the list to add + :returns: (bool) a true on succes otherwise falsed + """ + return _ldns.ldns_zone_push_rr_list(self,list) + #parameters: ldns_zone *,ldns_rr_list *, + #retvals: bool + + def rr_count(self): + """Returns the number of resource records in the zone, NOT counting the SOA record. + + :returns: (size_t) the number of rr's in the zone + """ + return _ldns.ldns_zone_rr_count(self) + #parameters: const ldns_zone *, + #retvals: size_t + + def rrs(self): + """Get a list of a zone's content. + + Note that the SOA isn't included in this list. You need to get the with ldns_zone_soa. + + :returns: (ldns_rr_list \*) the rrs from this zone + """ + return _ldns.ldns_zone_rrs(self) + #parameters: const ldns_zone *, + #retvals: ldns_rr_list * + + def set_rrs(self,rrlist): + """Set the zone's contents. + + :param rrlist: + the rrlist to use + """ + _ldns.ldns_zone_set_rrs(self,rrlist) + #parameters: ldns_zone *,ldns_rr_list *, + #retvals: + + def set_soa(self,soa): + """Set the zone's soa record. + + :param soa: + the soa to set + """ + _ldns.ldns_zone_set_soa(self,soa) + #parameters: ldns_zone *,ldns_rr *, + #retvals: + + def soa(self): + """Return the soa record of a zone. + + :returns: (ldns_rr \*) the soa record in the zone + """ + return _ldns.ldns_zone_soa(self) + #parameters: const ldns_zone *, + #retvals: ldns_rr * + + def sort(self): + """Sort the rrs in a zone, with the current impl. + + this is slow + """ + _ldns.ldns_zone_sort(self) + #parameters: ldns_zone *, + #retvals: + + #_LDNS_ZONE_METHODS# + %} +} diff --git a/dname.c b/dname.c new file mode 100644 index 00000000000..f3770feafb5 --- /dev/null +++ b/dname.c @@ -0,0 +1,565 @@ +/* + * dname.c + * + * dname specific rdata implementations + * A dname is a rdf structure with type LDNS_RDF_TYPE_DNAME + * It is not a /real/ type! All function must therefor check + * for LDNS_RDF_TYPE_DNAME. + * + * a Net::DNS like library for C + * + * (c) NLnet Labs, 2004-2006 + * + * See the file LICENSE for the license + */ + +#include + +#include + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif + +ldns_rdf * +ldns_dname_cat_clone(const ldns_rdf *rd1, const ldns_rdf *rd2) +{ + ldns_rdf *new; + uint16_t new_size; + uint8_t *buf; + uint16_t left_size; + + if (ldns_rdf_get_type(rd1) != LDNS_RDF_TYPE_DNAME || + ldns_rdf_get_type(rd2) != LDNS_RDF_TYPE_DNAME) { + return NULL; + } + + /* remove root label if it is present at the end of the left + * rd, by reducing the size with 1 + */ + left_size = ldns_rdf_size(rd1); + if (left_size > 0 &&ldns_rdf_data(rd1)[left_size - 1] == 0) { + left_size--; + } + + /* we overwrite the nullbyte of rd1 */ + new_size = left_size + ldns_rdf_size(rd2); + buf = LDNS_XMALLOC(uint8_t, new_size); + if (!buf) { + return NULL; + } + + /* put the two dname's after each other */ + memcpy(buf, ldns_rdf_data(rd1), left_size); + memcpy(buf + left_size, ldns_rdf_data(rd2), ldns_rdf_size(rd2)); + + new = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, new_size, buf); + + LDNS_FREE(buf); + return new; +} + +ldns_status +ldns_dname_cat(ldns_rdf *rd1, ldns_rdf *rd2) +{ + uint16_t left_size; + uint16_t size; + uint8_t* newd; + + if (ldns_rdf_get_type(rd1) != LDNS_RDF_TYPE_DNAME || + ldns_rdf_get_type(rd2) != LDNS_RDF_TYPE_DNAME) { + return LDNS_STATUS_ERR; + } + + /* remove root label if it is present at the end of the left + * rd, by reducing the size with 1 + */ + left_size = ldns_rdf_size(rd1); + if (left_size > 0 &&ldns_rdf_data(rd1)[left_size - 1] == 0) { + left_size--; + } + + size = left_size + ldns_rdf_size(rd2); + newd = LDNS_XREALLOC(ldns_rdf_data(rd1), uint8_t, size); + if(!newd) { + return LDNS_STATUS_MEM_ERR; + } + + ldns_rdf_set_data(rd1, newd); + memcpy(ldns_rdf_data(rd1) + left_size, ldns_rdf_data(rd2), + ldns_rdf_size(rd2)); + ldns_rdf_set_size(rd1, size); + + return LDNS_STATUS_OK; +} + +ldns_rdf * +ldns_dname_reverse(const ldns_rdf *d) +{ + ldns_rdf *new; + ldns_rdf *tmp; + ldns_rdf *d_tmp; + ldns_status status; + + d_tmp = ldns_rdf_clone(d); + + new = ldns_dname_new_frm_str("."); + if(!new) + return NULL; + + while(ldns_dname_label_count(d_tmp) > 0) { + tmp = ldns_dname_label(d_tmp, 0); + status = ldns_dname_cat(tmp, new); + if(status != LDNS_STATUS_OK) { + ldns_rdf_deep_free(new); + ldns_rdf_deep_free(d_tmp); + return NULL; + } + ldns_rdf_deep_free(new); + new = tmp; + tmp = ldns_dname_left_chop(d_tmp); + ldns_rdf_deep_free(d_tmp); + d_tmp = tmp; + } + ldns_rdf_deep_free(d_tmp); + + return new; +} + +ldns_rdf * +ldns_dname_clone_from(const ldns_rdf *d, uint16_t n) +{ + uint8_t *data; + uint8_t label_size; + size_t data_size; + + if (!d || + ldns_rdf_get_type(d) != LDNS_RDF_TYPE_DNAME || + ldns_dname_label_count(d) < n) { + return NULL; + } + + data = ldns_rdf_data(d); + data_size = ldns_rdf_size(d); + while (n > 0) { + label_size = data[0] + 1; + data += label_size; + if (data_size < label_size) { + /* this label is very broken */ + return NULL; + } + data_size -= label_size; + n--; + } + + return ldns_dname_new_frm_data(data_size, data); +} + +ldns_rdf * +ldns_dname_left_chop(const ldns_rdf *d) +{ + uint8_t label_pos; + ldns_rdf *chop; + + if (!d) { + return NULL; + } + + if (ldns_rdf_get_type(d) != LDNS_RDF_TYPE_DNAME) { + return NULL; + } + if (ldns_dname_label_count(d) == 0) { + /* root label */ + return NULL; + } + /* 05blaat02nl00 */ + label_pos = ldns_rdf_data(d)[0]; + + chop = ldns_dname_new_frm_data(ldns_rdf_size(d) - label_pos - 1, + ldns_rdf_data(d) + label_pos + 1); + return chop; +} + +uint8_t +ldns_dname_label_count(const ldns_rdf *r) +{ + uint16_t src_pos; + uint16_t len; + uint8_t i; + size_t r_size; + + if (!r) { + return 0; + } + + i = 0; + src_pos = 0; + r_size = ldns_rdf_size(r); + + if (ldns_rdf_get_type(r) != LDNS_RDF_TYPE_DNAME) { + return 0; + } else { + len = ldns_rdf_data(r)[src_pos]; /* start of the label */ + + /* single root label */ + if (1 == r_size) { + return 0; + } else { + while ((len > 0) && src_pos < r_size) { + src_pos++; + src_pos += len; + len = ldns_rdf_data(r)[src_pos]; + i++; + } + } + } + return i; +} + +ldns_rdf * +ldns_dname_new(uint16_t s, void *d) +{ + ldns_rdf *rd; + + rd = LDNS_MALLOC(ldns_rdf); + if (!rd) { + return NULL; + } + ldns_rdf_set_size(rd, s); + ldns_rdf_set_type(rd, LDNS_RDF_TYPE_DNAME); + ldns_rdf_set_data(rd, d); + return rd; +} + +ldns_rdf * +ldns_dname_new_frm_str(const char *str) +{ + return ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, str); +} + +ldns_rdf * +ldns_dname_new_frm_data(uint16_t size, const void *data) +{ + return ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, size, data); +} + +void +ldns_dname2canonical(const ldns_rdf *rd) +{ + uint8_t *rdd; + uint16_t i; + + if (ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_DNAME) { + return; + } + + rdd = (uint8_t*)ldns_rdf_data(rd); + for (i = 0; i < ldns_rdf_size(rd); i++, rdd++) { + *rdd = (uint8_t)LDNS_DNAME_NORMALIZE((int)*rdd); + } +} + +bool +ldns_dname_is_subdomain(const ldns_rdf *sub, const ldns_rdf *parent) +{ + uint8_t sub_lab; + uint8_t par_lab; + int8_t i, j; + ldns_rdf *tmp_sub = NULL; + ldns_rdf *tmp_par = NULL; + ldns_rdf *sub_clone; + ldns_rdf *parent_clone; + bool result = true; + + if (ldns_rdf_get_type(sub) != LDNS_RDF_TYPE_DNAME || + ldns_rdf_get_type(parent) != LDNS_RDF_TYPE_DNAME || + ldns_rdf_compare(sub, parent) == 0) { + return false; + } + + /* would be nicer if we do not have to clone... */ + sub_clone = ldns_dname_clone_from(sub, 0); + parent_clone = ldns_dname_clone_from(parent, 0); + ldns_dname2canonical(sub_clone); + ldns_dname2canonical(parent_clone); + + sub_lab = ldns_dname_label_count(sub_clone); + par_lab = ldns_dname_label_count(parent_clone); + + /* if sub sits above parent, it cannot be a child/sub domain */ + if (sub_lab < par_lab) { + result = false; + } else { + /* check all labels the from the parent labels, from right to left. + * When they /all/ match we have found a subdomain + */ + j = sub_lab - 1; /* we count from zero, thank you */ + for (i = par_lab -1; i >= 0; i--) { + tmp_sub = ldns_dname_label(sub_clone, j); + tmp_par = ldns_dname_label(parent_clone, i); + if (!tmp_sub || !tmp_par) { + /* deep free does null check */ + ldns_rdf_deep_free(tmp_sub); + ldns_rdf_deep_free(tmp_par); + result = false; + break; + } + + if (ldns_rdf_compare(tmp_sub, tmp_par) != 0) { + /* they are not equal */ + ldns_rdf_deep_free(tmp_sub); + ldns_rdf_deep_free(tmp_par); + result = false; + break; + } + ldns_rdf_deep_free(tmp_sub); + ldns_rdf_deep_free(tmp_par); + j--; + } + } + ldns_rdf_deep_free(sub_clone); + ldns_rdf_deep_free(parent_clone); + return result; +} + +int +ldns_dname_compare(const ldns_rdf *dname1, const ldns_rdf *dname2) +{ + size_t lc1, lc2, lc1f, lc2f; + size_t i; + int result = 0; + uint8_t *lp1, *lp2; + + /* see RFC4034 for this algorithm */ + /* this algorithm assumes the names are normalized to case */ + + /* only when both are not NULL we can say anything about them */ + if (!dname1 && !dname2) { + return 0; + } + if (!dname1 || !dname2) { + return -1; + } + /* asserts must happen later as we are looking in the + * dname, which could be NULL. But this case is handled + * above + */ + assert(ldns_rdf_get_type(dname1) == LDNS_RDF_TYPE_DNAME); + assert(ldns_rdf_get_type(dname2) == LDNS_RDF_TYPE_DNAME); + + lc1 = ldns_dname_label_count(dname1); + lc2 = ldns_dname_label_count(dname2); + + if (lc1 == 0 && lc2 == 0) { + return 0; + } + if (lc1 == 0) { + return -1; + } + if (lc2 == 0) { + return 1; + } + lc1--; + lc2--; + /* we start at the last label */ + while (true) { + /* find the label first */ + lc1f = lc1; + lp1 = ldns_rdf_data(dname1); + while (lc1f > 0) { + lp1 += *lp1 + 1; + lc1f--; + } + + /* and find the other one */ + lc2f = lc2; + lp2 = ldns_rdf_data(dname2); + while (lc2f > 0) { + lp2 += *lp2 + 1; + lc2f--; + } + + /* now check the label character for character. */ + for (i = 1; i < (size_t)(*lp1 + 1); i++) { + if (i > *lp2) { + /* apparently label 1 is larger */ + result = 1; + goto done; + } + if (LDNS_DNAME_NORMALIZE((int) *(lp1 + i)) < + LDNS_DNAME_NORMALIZE((int) *(lp2 + i))) { + result = -1; + goto done; + } else if (LDNS_DNAME_NORMALIZE((int) *(lp1 + i)) > + LDNS_DNAME_NORMALIZE((int) *(lp2 + i))) { + result = 1; + goto done; + } + } + if (*lp1 < *lp2) { + /* apparently label 2 is larger */ + result = -1; + goto done; + } + if (lc1 == 0 && lc2 > 0) { + result = -1; + goto done; + } else if (lc1 > 0 && lc2 == 0) { + result = 1; + goto done; + } else if (lc1 == 0 && lc2 == 0) { + result = 0; + goto done; + } + lc1--; + lc2--; + } + + done: + return result; +} + +int +ldns_dname_is_wildcard(const ldns_rdf* dname) +{ + return ( ldns_dname_label_count(dname) > 0 && + ldns_rdf_data(dname)[0] == 1 && + ldns_rdf_data(dname)[1] == '*'); +} + +int +ldns_dname_match_wildcard(const ldns_rdf *dname, const ldns_rdf *wildcard) +{ + ldns_rdf *wc_chopped; + int result; + /* check whether it really is a wildcard */ + if (ldns_dname_is_wildcard(wildcard)) { + /* ok, so the dname needs to be a subdomain of the wildcard + * without the * + */ + wc_chopped = ldns_dname_left_chop(wildcard); + result = (int) ldns_dname_is_subdomain(dname, wc_chopped); + ldns_rdf_deep_free(wc_chopped); + } else { + result = (ldns_dname_compare(dname, wildcard) == 0); + } + return result; +} + +/* nsec test: does prev <= middle < next + * -1 = yes + * 0 = error/can't tell + * 1 = no + */ +int +ldns_dname_interval(const ldns_rdf *prev, const ldns_rdf *middle, + const ldns_rdf *next) +{ + int prev_check, next_check; + + assert(ldns_rdf_get_type(prev) == LDNS_RDF_TYPE_DNAME); + assert(ldns_rdf_get_type(middle) == LDNS_RDF_TYPE_DNAME); + assert(ldns_rdf_get_type(next) == LDNS_RDF_TYPE_DNAME); + + prev_check = ldns_dname_compare(prev, middle); + next_check = ldns_dname_compare(middle, next); + /* <= next. This cannot be the case for nsec, because then we would + * have gotten the nsec of next... + */ + if (next_check == 0) { + return 0; + } + + /* <= */ + if ((prev_check == -1 || prev_check == 0) && + /* < */ + next_check == -1) { + return -1; + } else { + return 1; + } +} + + +bool +ldns_dname_str_absolute(const char *dname_str) +{ + const char* s; + if(dname_str && strcmp(dname_str, ".") == 0) + return 1; + if(!dname_str || strlen(dname_str) < 2) + return 0; + if(dname_str[strlen(dname_str) - 1] != '.') + return 0; + if(dname_str[strlen(dname_str) - 2] != '\\') + return 1; /* ends in . and no \ before it */ + /* so we have the case of ends in . and there is \ before it */ + for(s=dname_str; *s; s++) { + if(*s == '\\') { + if(s[1] && s[2] && s[3] /* check length */ + && isdigit(s[1]) && isdigit(s[2]) && + isdigit(s[3])) + s += 3; + else if(!s[1] || isdigit(s[1])) /* escape of nul,0-9 */ + return 0; /* parse error */ + else s++; /* another character escaped */ + } + else if(!*(s+1) && *s == '.') + return 1; /* trailing dot, unescaped */ + } + return 0; +} + +ldns_rdf * +ldns_dname_label(const ldns_rdf *rdf, uint8_t labelpos) +{ + uint8_t labelcnt; + uint16_t src_pos; + uint16_t len; + ldns_rdf *tmpnew; + size_t s; + uint8_t *data; + + if (ldns_rdf_get_type(rdf) != LDNS_RDF_TYPE_DNAME) { + return NULL; + } + + labelcnt = 0; + src_pos = 0; + s = ldns_rdf_size(rdf); + + len = ldns_rdf_data(rdf)[src_pos]; /* label start */ + while ((len > 0) && src_pos < s) { + if (labelcnt == labelpos) { + /* found our label */ + data = LDNS_XMALLOC(uint8_t, len + 2); + if (!data) { + return NULL; + } + memcpy(data, ldns_rdf_data(rdf) + src_pos, len + 1); + data[len + 2 - 1] = 0; + + tmpnew = ldns_rdf_new( LDNS_RDF_TYPE_DNAME + , len + 2, data); + if (!tmpnew) { + LDNS_FREE(data); + return NULL; + } + return tmpnew; + } + src_pos++; + src_pos += len; + len = ldns_rdf_data(rdf)[src_pos]; + labelcnt++; + } + return NULL; +} diff --git a/dnssec.c b/dnssec.c new file mode 100644 index 00000000000..c6e93211787 --- /dev/null +++ b/dnssec.c @@ -0,0 +1,1764 @@ +/* + * dnssec.c + * + * contains the cryptographic function needed for DNSSEC in ldns + * The crypto library used is openssl + * + * (c) NLnet Labs, 2004-2008 + * + * See the file LICENSE for the license + */ + +#include + +#include +#include + +#include +#include + +#ifdef HAVE_SSL +#include +#include +#include +#include +#include +#endif + +ldns_rr * +ldns_dnssec_get_rrsig_for_name_and_type(const ldns_rdf *name, + const ldns_rr_type type, + const ldns_rr_list *rrs) +{ + size_t i; + ldns_rr *candidate; + + if (!name || !rrs) { + return NULL; + } + + for (i = 0; i < ldns_rr_list_rr_count(rrs); i++) { + candidate = ldns_rr_list_rr(rrs, i); + if (ldns_rr_get_type(candidate) == LDNS_RR_TYPE_RRSIG) { + if (ldns_dname_compare(ldns_rr_owner(candidate), + name) == 0 && + ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(candidate)) + == type + ) { + return candidate; + } + } + } + + return NULL; +} + +ldns_rr * +ldns_dnssec_get_dnskey_for_rrsig(const ldns_rr *rrsig, + const ldns_rr_list *rrs) +{ + size_t i; + ldns_rr *candidate; + + if (!rrsig || !rrs) { + return NULL; + } + + for (i = 0; i < ldns_rr_list_rr_count(rrs); i++) { + candidate = ldns_rr_list_rr(rrs, i); + if (ldns_rr_get_type(candidate) == LDNS_RR_TYPE_DNSKEY) { + if (ldns_dname_compare(ldns_rr_owner(candidate), + ldns_rr_rrsig_signame(rrsig)) == 0 && + ldns_rdf2native_int16(ldns_rr_rrsig_keytag(rrsig)) == + ldns_calc_keytag(candidate) + ) { + return candidate; + } + } + } + + return NULL; +} + +ldns_rdf * +ldns_nsec_get_bitmap(ldns_rr *nsec) { + if (ldns_rr_get_type(nsec) == LDNS_RR_TYPE_NSEC) { + return ldns_rr_rdf(nsec, 1); + } else if (ldns_rr_get_type(nsec) == LDNS_RR_TYPE_NSEC3) { + return ldns_rr_rdf(nsec, 5); + } else { + return NULL; + } +} + +/*return the owner name of the closest encloser for name from the list of rrs */ +/* this is NOT the hash, but the original name! */ +ldns_rdf * +ldns_dnssec_nsec3_closest_encloser(ldns_rdf *qname, + ATTR_UNUSED(ldns_rr_type qtype), + ldns_rr_list *nsec3s) +{ + /* remember parameters, they must match */ + uint8_t algorithm; + uint32_t iterations; + uint8_t salt_length; + uint8_t *salt; + + ldns_rdf *sname, *hashed_sname, *tmp; + bool flag; + + bool exact_match_found; + bool in_range_found; + + ldns_status status; + ldns_rdf *zone_name; + + size_t nsec_i; + ldns_rr *nsec; + ldns_rdf *result = NULL; + + if (!qname || !nsec3s || ldns_rr_list_rr_count(nsec3s) < 1) { + return NULL; + } + + nsec = ldns_rr_list_rr(nsec3s, 0); + algorithm = ldns_nsec3_algorithm(nsec); + salt_length = ldns_nsec3_salt_length(nsec); + salt = ldns_nsec3_salt_data(nsec); + iterations = ldns_nsec3_iterations(nsec); + + sname = ldns_rdf_clone(qname); + + flag = false; + + zone_name = ldns_dname_left_chop(ldns_rr_owner(nsec)); + + /* algorithm from nsec3-07 8.3 */ + while (ldns_dname_label_count(sname) > 0) { + exact_match_found = false; + in_range_found = false; + + hashed_sname = ldns_nsec3_hash_name(sname, + algorithm, + iterations, + salt_length, + salt); + + status = ldns_dname_cat(hashed_sname, zone_name); + if(status != LDNS_STATUS_OK) { + LDNS_FREE(salt); + ldns_rdf_deep_free(zone_name); + ldns_rdf_deep_free(sname); + return NULL; + } + + for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsec3s); nsec_i++) { + nsec = ldns_rr_list_rr(nsec3s, nsec_i); + + /* check values of iterations etc! */ + + /* exact match? */ + if (ldns_dname_compare(ldns_rr_owner(nsec), hashed_sname) == 0) { + exact_match_found = true; + } else if (ldns_nsec_covers_name(nsec, hashed_sname)) { + in_range_found = true; + } + + } + if (!exact_match_found && in_range_found) { + flag = true; + } else if (exact_match_found && flag) { + result = ldns_rdf_clone(sname); + /* RFC 5155: 8.3. 2.** "The proof is complete" */ + ldns_rdf_deep_free(hashed_sname); + goto done; + } else if (exact_match_found && !flag) { + /* error! */ + ldns_rdf_deep_free(hashed_sname); + goto done; + } else { + flag = false; + } + + ldns_rdf_deep_free(hashed_sname); + tmp = sname; + sname = ldns_dname_left_chop(sname); + ldns_rdf_deep_free(tmp); + } + + done: + LDNS_FREE(salt); + ldns_rdf_deep_free(zone_name); + ldns_rdf_deep_free(sname); + + return result; +} + +bool +ldns_dnssec_pkt_has_rrsigs(const ldns_pkt *pkt) +{ + size_t i; + for (i = 0; i < ldns_pkt_ancount(pkt); i++) { + if (ldns_rr_get_type(ldns_rr_list_rr(ldns_pkt_answer(pkt), i)) == + LDNS_RR_TYPE_RRSIG) { + return true; + } + } + for (i = 0; i < ldns_pkt_nscount(pkt); i++) { + if (ldns_rr_get_type(ldns_rr_list_rr(ldns_pkt_authority(pkt), i)) == + LDNS_RR_TYPE_RRSIG) { + return true; + } + } + return false; +} + +ldns_rr_list * +ldns_dnssec_pkt_get_rrsigs_for_name_and_type(const ldns_pkt *pkt, + ldns_rdf *name, + ldns_rr_type type) +{ + uint16_t t_netorder; + ldns_rr_list *sigs; + ldns_rr_list *sigs_covered; + ldns_rdf *rdf_t; + + sigs = ldns_pkt_rr_list_by_name_and_type(pkt, + name, + LDNS_RR_TYPE_RRSIG, + LDNS_SECTION_ANY_NOQUESTION + ); + + t_netorder = htons(type); /* rdf are in network order! */ + rdf_t = ldns_rdf_new(LDNS_RDF_TYPE_TYPE, LDNS_RDF_SIZE_WORD, &t_netorder); + sigs_covered = ldns_rr_list_subtype_by_rdf(sigs, rdf_t, 0); + + ldns_rdf_free(rdf_t); + ldns_rr_list_deep_free(sigs); + + return sigs_covered; + +} + +ldns_rr_list * +ldns_dnssec_pkt_get_rrsigs_for_type(const ldns_pkt *pkt, ldns_rr_type type) +{ + uint16_t t_netorder; + ldns_rr_list *sigs; + ldns_rr_list *sigs_covered; + ldns_rdf *rdf_t; + + sigs = ldns_pkt_rr_list_by_type(pkt, + LDNS_RR_TYPE_RRSIG, + LDNS_SECTION_ANY_NOQUESTION + ); + + t_netorder = htons(type); /* rdf are in network order! */ + rdf_t = ldns_rdf_new(LDNS_RDF_TYPE_TYPE, + 2, + &t_netorder); + sigs_covered = ldns_rr_list_subtype_by_rdf(sigs, rdf_t, 0); + + ldns_rdf_free(rdf_t); + ldns_rr_list_deep_free(sigs); + + return sigs_covered; + +} + +/* used only on the public key RR */ +uint16_t +ldns_calc_keytag(const ldns_rr *key) +{ + uint16_t ac16; + ldns_buffer *keybuf; + size_t keysize; + + if (!key) { + return 0; + } + + if (ldns_rr_get_type(key) != LDNS_RR_TYPE_DNSKEY && + ldns_rr_get_type(key) != LDNS_RR_TYPE_KEY + ) { + return 0; + } + + /* rdata to buf - only put the rdata in a buffer */ + keybuf = ldns_buffer_new(LDNS_MIN_BUFLEN); /* grows */ + if (!keybuf) { + return 0; + } + (void)ldns_rr_rdata2buffer_wire(keybuf, key); + /* the current pos in the buffer is the keysize */ + keysize= ldns_buffer_position(keybuf); + + ac16 = ldns_calc_keytag_raw(ldns_buffer_begin(keybuf), keysize); + ldns_buffer_free(keybuf); + return ac16; +} + +uint16_t ldns_calc_keytag_raw(uint8_t* key, size_t keysize) +{ + unsigned int i; + uint32_t ac32; + uint16_t ac16; + + if(keysize < 4) { + return 0; + } + /* look at the algorithm field, copied from 2535bis */ + if (key[3] == LDNS_RSAMD5) { + ac16 = 0; + if (keysize > 4) { + memmove(&ac16, key + keysize - 3, 2); + } + ac16 = ntohs(ac16); + return (uint16_t) ac16; + } else { + ac32 = 0; + for (i = 0; (size_t)i < keysize; ++i) { + ac32 += (i & 1) ? key[i] : key[i] << 8; + } + ac32 += (ac32 >> 16) & 0xFFFF; + return (uint16_t) (ac32 & 0xFFFF); + } +} + +#ifdef HAVE_SSL +DSA * +ldns_key_buf2dsa(ldns_buffer *key) +{ + return ldns_key_buf2dsa_raw((unsigned char*)ldns_buffer_begin(key), + ldns_buffer_position(key)); +} + +DSA * +ldns_key_buf2dsa_raw(unsigned char* key, size_t len) +{ + uint8_t T; + uint16_t length; + uint16_t offset; + DSA *dsa; + BIGNUM *Q; BIGNUM *P; + BIGNUM *G; BIGNUM *Y; + + if(len == 0) + return NULL; + T = (uint8_t)key[0]; + length = (64 + T * 8); + offset = 1; + + if (T > 8) { + return NULL; + } + if(len < (size_t)1 + SHA_DIGEST_LENGTH + 3*length) + return NULL; + + Q = BN_bin2bn(key+offset, SHA_DIGEST_LENGTH, NULL); + offset += SHA_DIGEST_LENGTH; + + P = BN_bin2bn(key+offset, (int)length, NULL); + offset += length; + + G = BN_bin2bn(key+offset, (int)length, NULL); + 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())) { + BN_free(Q); + BN_free(P); + BN_free(G); + BN_free(Y); + return NULL; + } +#ifndef S_SPLINT_S + dsa->p = P; + dsa->q = Q; + dsa->g = G; + dsa->pub_key = Y; +#endif /* splint */ + + return dsa; +} + +RSA * +ldns_key_buf2rsa(ldns_buffer *key) +{ + return ldns_key_buf2rsa_raw((unsigned char*)ldns_buffer_begin(key), + ldns_buffer_position(key)); +} + +RSA * +ldns_key_buf2rsa_raw(unsigned char* key, size_t len) +{ + uint16_t offset; + uint16_t exp; + uint16_t int16; + RSA *rsa; + BIGNUM *modulus; + BIGNUM *exponent; + + if (len == 0) + return NULL; + if (key[0] == 0) { + if(len < 3) + return NULL; + /* need some smart comment here XXX*/ + /* the exponent is too large so it's places + * futher...???? */ + memmove(&int16, key+1, 2); + exp = ntohs(int16); + offset = 3; + } else { + exp = key[0]; + offset = 1; + } + + /* key length at least one */ + if(len < (size_t)offset + exp + 1) + return NULL; + + /* Exponent */ + exponent = BN_new(); + if(!exponent) return NULL; + (void) BN_bin2bn(key+offset, (int)exp, exponent); + offset += exp; + + /* Modulus */ + modulus = BN_new(); + if(!modulus) { + BN_free(exponent); + return NULL; + } + /* length of the buffer must match the key length! */ + (void) BN_bin2bn(key+offset, (int)(len - offset), modulus); + + rsa = RSA_new(); + if(!rsa) { + BN_free(exponent); + BN_free(modulus); + return NULL; + } +#ifndef S_SPLINT_S + rsa->n = modulus; + rsa->e = exponent; +#endif /* splint */ + + return rsa; +} + +int +ldns_digest_evp(unsigned char* data, unsigned int len, unsigned char* dest, + const EVP_MD* md) +{ + EVP_MD_CTX* ctx; + ctx = EVP_MD_CTX_create(); + if(!ctx) + return false; + if(!EVP_DigestInit_ex(ctx, md, NULL) || + !EVP_DigestUpdate(ctx, data, len) || + !EVP_DigestFinal_ex(ctx, dest, NULL)) { + EVP_MD_CTX_destroy(ctx); + return false; + } + EVP_MD_CTX_destroy(ctx); + return true; +} +#endif /* HAVE_SSL */ + +ldns_rr * +ldns_key_rr2ds(const ldns_rr *key, ldns_hash h) +{ + ldns_rdf *tmp; + ldns_rr *ds; + uint16_t keytag; + uint8_t sha1hash; + uint8_t *digest; + ldns_buffer *data_buf; +#ifdef USE_GOST + const EVP_MD* md = NULL; +#endif + + if (ldns_rr_get_type(key) != LDNS_RR_TYPE_DNSKEY) { + return NULL; + } + + ds = ldns_rr_new(); + if (!ds) { + return NULL; + } + ldns_rr_set_type(ds, LDNS_RR_TYPE_DS); + ldns_rr_set_owner(ds, ldns_rdf_clone( + ldns_rr_owner(key))); + ldns_rr_set_ttl(ds, ldns_rr_ttl(key)); + ldns_rr_set_class(ds, ldns_rr_get_class(key)); + + switch(h) { + default: + case LDNS_SHA1: + digest = LDNS_XMALLOC(uint8_t, LDNS_SHA1_DIGEST_LENGTH); + if (!digest) { + ldns_rr_free(ds); + return NULL; + } + break; + case LDNS_SHA256: + digest = LDNS_XMALLOC(uint8_t, LDNS_SHA256_DIGEST_LENGTH); + if (!digest) { + ldns_rr_free(ds); + return NULL; + } + break; + case LDNS_HASH_GOST: +#ifdef USE_GOST + (void)ldns_key_EVP_load_gost_id(); + md = EVP_get_digestbyname("md_gost94"); + if(!md) { + ldns_rr_free(ds); + return NULL; + } + digest = LDNS_XMALLOC(uint8_t, EVP_MD_size(md)); + if (!digest) { + ldns_rr_free(ds); + return NULL; + } + break; +#else + /* not implemented */ + ldns_rr_free(ds); + return NULL; +#endif + case LDNS_SHA384: +#ifdef USE_ECDSA + digest = LDNS_XMALLOC(uint8_t, SHA384_DIGEST_LENGTH); + if (!digest) { + ldns_rr_free(ds); + return NULL; + } + break; +#else + /* not implemented */ + ldns_rr_free(ds); + return NULL; +#endif + } + + data_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN); + if (!data_buf) { + LDNS_FREE(digest); + ldns_rr_free(ds); + return NULL; + } + + /* keytag */ + keytag = htons(ldns_calc_keytag((ldns_rr*)key)); + tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT16, + sizeof(uint16_t), + &keytag); + ldns_rr_push_rdf(ds, tmp); + + /* copy the algorithm field */ + if ((tmp = ldns_rr_rdf(key, 2)) == NULL) { + LDNS_FREE(digest); + ldns_buffer_free(data_buf); + ldns_rr_free(ds); + return NULL; + } else { + ldns_rr_push_rdf(ds, ldns_rdf_clone( tmp )); + } + + /* digest hash type */ + sha1hash = (uint8_t)h; + tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT8, + sizeof(uint8_t), + &sha1hash); + ldns_rr_push_rdf(ds, tmp); + + /* digest */ + /* owner name */ + tmp = ldns_rdf_clone(ldns_rr_owner(key)); + ldns_dname2canonical(tmp); + if (ldns_rdf2buffer_wire(data_buf, tmp) != LDNS_STATUS_OK) { + LDNS_FREE(digest); + ldns_buffer_free(data_buf); + ldns_rr_free(ds); + ldns_rdf_deep_free(tmp); + return NULL; + } + ldns_rdf_deep_free(tmp); + + /* all the rdata's */ + if (ldns_rr_rdata2buffer_wire(data_buf, + (ldns_rr*)key) != LDNS_STATUS_OK) { + LDNS_FREE(digest); + ldns_buffer_free(data_buf); + ldns_rr_free(ds); + return NULL; + } + switch(h) { + case LDNS_SHA1: + (void) ldns_sha1((unsigned char *) ldns_buffer_begin(data_buf), + (unsigned int) ldns_buffer_position(data_buf), + (unsigned char *) digest); + + tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX, + LDNS_SHA1_DIGEST_LENGTH, + digest); + ldns_rr_push_rdf(ds, tmp); + + break; + case LDNS_SHA256: + (void) ldns_sha256((unsigned char *) ldns_buffer_begin(data_buf), + (unsigned int) ldns_buffer_position(data_buf), + (unsigned char *) digest); + tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX, + LDNS_SHA256_DIGEST_LENGTH, + digest); + ldns_rr_push_rdf(ds, tmp); + break; + case LDNS_HASH_GOST: +#ifdef USE_GOST + if(!ldns_digest_evp((unsigned char *) ldns_buffer_begin(data_buf), + (unsigned int) ldns_buffer_position(data_buf), + (unsigned char *) digest, md)) { + LDNS_FREE(digest); + ldns_buffer_free(data_buf); + ldns_rr_free(ds); + return NULL; + } + tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX, + (size_t)EVP_MD_size(md), + digest); + ldns_rr_push_rdf(ds, tmp); +#endif + break; + case LDNS_SHA384: +#ifdef USE_ECDSA + (void) SHA384((unsigned char *) ldns_buffer_begin(data_buf), + (unsigned int) ldns_buffer_position(data_buf), + (unsigned char *) digest); + tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX, + SHA384_DIGEST_LENGTH, + digest); + ldns_rr_push_rdf(ds, tmp); +#endif + break; + } + + LDNS_FREE(digest); + ldns_buffer_free(data_buf); + return ds; +} + +ldns_rdf * +ldns_dnssec_create_nsec_bitmap(ldns_rr_type rr_type_list[], + size_t size, + ldns_rr_type nsec_type) +{ + size_t i; + uint8_t *bitmap; + uint16_t bm_len = 0; + uint16_t i_type; + ldns_rdf *bitmap_rdf; + + uint8_t *data = NULL; + uint8_t cur_data[32]; + uint8_t cur_window = 0; + uint8_t cur_window_max = 0; + uint16_t cur_data_size = 0; + + if (nsec_type != LDNS_RR_TYPE_NSEC && + nsec_type != LDNS_RR_TYPE_NSEC3) { + return NULL; + } + + i_type = 0; + for (i = 0; i < size; i++) { + if (i_type < rr_type_list[i]) + i_type = rr_type_list[i]; + } + if (i_type < nsec_type) { + i_type = nsec_type; + } + + bm_len = i_type / 8 + 2; + bitmap = LDNS_XMALLOC(uint8_t, bm_len); + if(!bitmap) return NULL; + for (i = 0; i < bm_len; i++) { + bitmap[i] = 0; + } + + for (i = 0; i < size; i++) { + i_type = rr_type_list[i]; + ldns_set_bit(bitmap + (int) i_type / 8, + (int) (7 - (i_type % 8)), + true); + } + + /* fold it into windows TODO: can this be done directly? */ + memset(cur_data, 0, 32); + for (i = 0; i < bm_len; i++) { + if (i / 32 > cur_window) { + /* check, copy, new */ + if (cur_window_max > 0) { + /* this window has stuff, add it */ + data = LDNS_XREALLOC(data, + uint8_t, + cur_data_size + cur_window_max + 3); + if(!data) { + LDNS_FREE(bitmap); + return NULL; + } + data[cur_data_size] = cur_window; + data[cur_data_size + 1] = cur_window_max + 1; + memcpy(data + cur_data_size + 2, + cur_data, + cur_window_max+1); + cur_data_size += cur_window_max + 3; + } + cur_window++; + cur_window_max = 0; + memset(cur_data, 0, 32); + } + cur_data[i%32] = bitmap[i]; + if (bitmap[i] > 0) { + cur_window_max = i%32; + } + } + if (cur_window_max > 0 || cur_data[0] != 0) { + /* this window has stuff, add it */ + data = LDNS_XREALLOC(data, + uint8_t, + cur_data_size + cur_window_max + 3); + if(!data) { + LDNS_FREE(bitmap); + return NULL; + } + data[cur_data_size] = cur_window; + data[cur_data_size + 1] = cur_window_max + 1; + memcpy(data + cur_data_size + 2, cur_data, cur_window_max+1); + cur_data_size += cur_window_max + 3; + } + + bitmap_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_NSEC, + cur_data_size, + data); + + LDNS_FREE(bitmap); + LDNS_FREE(data); + + return bitmap_rdf; +} + +int +ldns_dnssec_rrsets_contains_type(ldns_dnssec_rrsets *rrsets, + ldns_rr_type type) +{ + ldns_dnssec_rrsets *cur_rrset = rrsets; + while (cur_rrset) { + if (cur_rrset->type == type) { + return 1; + } + cur_rrset = cur_rrset->next; + } + return 0; +} + +ldns_rr * +ldns_dnssec_create_nsec(ldns_dnssec_name *from, + ldns_dnssec_name *to, + ldns_rr_type nsec_type) +{ + ldns_rr *nsec_rr; + ldns_rr_type types[65536]; + size_t type_count = 0; + ldns_dnssec_rrsets *cur_rrsets; + int on_delegation_point; + + if (!from || !to || (nsec_type != LDNS_RR_TYPE_NSEC)) { + return NULL; + } + + nsec_rr = ldns_rr_new(); + ldns_rr_set_type(nsec_rr, nsec_type); + ldns_rr_set_owner(nsec_rr, ldns_rdf_clone(ldns_dnssec_name_name(from))); + ldns_rr_push_rdf(nsec_rr, ldns_rdf_clone(ldns_dnssec_name_name(to))); + + on_delegation_point = ldns_dnssec_rrsets_contains_type( + from->rrsets, LDNS_RR_TYPE_NS) + && !ldns_dnssec_rrsets_contains_type( + from->rrsets, LDNS_RR_TYPE_SOA); + + cur_rrsets = from->rrsets; + while (cur_rrsets) { + /* Do not include non-authoritative rrsets on the delegation point + * in the type bitmap */ + if ((on_delegation_point && ( + cur_rrsets->type == LDNS_RR_TYPE_NS + || cur_rrsets->type == LDNS_RR_TYPE_DS)) + || (!on_delegation_point && + cur_rrsets->type != LDNS_RR_TYPE_RRSIG + && cur_rrsets->type != LDNS_RR_TYPE_NSEC)) { + + types[type_count] = cur_rrsets->type; + type_count++; + } + cur_rrsets = cur_rrsets->next; + + } + types[type_count] = LDNS_RR_TYPE_RRSIG; + type_count++; + types[type_count] = LDNS_RR_TYPE_NSEC; + type_count++; + + ldns_rr_push_rdf(nsec_rr, ldns_dnssec_create_nsec_bitmap(types, + type_count, + nsec_type)); + + return nsec_rr; +} + +ldns_rr * +ldns_dnssec_create_nsec3(ldns_dnssec_name *from, + ldns_dnssec_name *to, + ldns_rdf *zone_name, + uint8_t algorithm, + uint8_t flags, + uint16_t iterations, + uint8_t salt_length, + uint8_t *salt) +{ + ldns_rr *nsec_rr; + ldns_rr_type types[65536]; + size_t type_count = 0; + ldns_dnssec_rrsets *cur_rrsets; + ldns_status status; + int on_delegation_point; + + if (!from) { + return NULL; + } + + nsec_rr = ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3); + ldns_rr_set_owner(nsec_rr, + ldns_nsec3_hash_name(ldns_dnssec_name_name(from), + algorithm, + iterations, + salt_length, + salt)); + status = ldns_dname_cat(ldns_rr_owner(nsec_rr), zone_name); + if(status != LDNS_STATUS_OK) { + ldns_rr_free(nsec_rr); + return NULL; + } + ldns_nsec3_add_param_rdfs(nsec_rr, + algorithm, + flags, + iterations, + salt_length, + salt); + + on_delegation_point = ldns_dnssec_rrsets_contains_type( + from->rrsets, LDNS_RR_TYPE_NS) + && !ldns_dnssec_rrsets_contains_type( + from->rrsets, LDNS_RR_TYPE_SOA); + cur_rrsets = from->rrsets; + while (cur_rrsets) { + /* Do not include non-authoritative rrsets on the delegation point + * in the type bitmap. Potentionally not skipping insecure + * delegation should have been done earlier, in function + * ldns_dnssec_zone_create_nsec3s, or even earlier in: + * ldns_dnssec_zone_sign_nsec3_flg . + */ + if ((on_delegation_point && ( + cur_rrsets->type == LDNS_RR_TYPE_NS + || cur_rrsets->type == LDNS_RR_TYPE_DS)) + || (!on_delegation_point && + cur_rrsets->type != LDNS_RR_TYPE_RRSIG)) { + + types[type_count] = cur_rrsets->type; + type_count++; + } + cur_rrsets = cur_rrsets->next; + } + /* always add rrsig type if this is not an unsigned + * delegation + */ + if (type_count > 0 && + !(type_count == 1 && types[0] == LDNS_RR_TYPE_NS)) { + types[type_count] = LDNS_RR_TYPE_RRSIG; + type_count++; + } + + /* leave next rdata empty if they weren't precomputed yet */ + if (to && to->hashed_name) { + (void) ldns_rr_set_rdf(nsec_rr, + ldns_rdf_clone(to->hashed_name), + 4); + } else { + (void) ldns_rr_set_rdf(nsec_rr, NULL, 4); + } + + ldns_rr_push_rdf(nsec_rr, + ldns_dnssec_create_nsec_bitmap(types, + type_count, + LDNS_RR_TYPE_NSEC3)); + + return nsec_rr; +} + +ldns_rr * +ldns_create_nsec(ldns_rdf *cur_owner, ldns_rdf *next_owner, ldns_rr_list *rrs) +{ + /* we do not do any check here - garbage in, garbage out */ + + /* the the start and end names - get the type from the + * before rrlist */ + + /* inefficient, just give it a name, a next name, and a list of rrs */ + /* we make 1 big uberbitmap first, then windows */ + /* todo: make something more efficient :) */ + uint16_t i; + ldns_rr *i_rr; + uint16_t i_type; + + ldns_rr *nsec = NULL; + ldns_rr_type i_type_list[65536]; + size_t type_count = 0; + + nsec = ldns_rr_new(); + ldns_rr_set_type(nsec, LDNS_RR_TYPE_NSEC); + ldns_rr_set_owner(nsec, ldns_rdf_clone(cur_owner)); + ldns_rr_push_rdf(nsec, ldns_rdf_clone(next_owner)); + + for (i = 0; i < ldns_rr_list_rr_count(rrs); i++) { + i_rr = ldns_rr_list_rr(rrs, i); + if (ldns_rdf_compare(cur_owner, + ldns_rr_owner(i_rr)) == 0) { + i_type = ldns_rr_get_type(i_rr); + if (i_type != LDNS_RR_TYPE_RRSIG && i_type != LDNS_RR_TYPE_NSEC) { + if (type_count == 0 || i_type_list[type_count-1] != i_type) { + i_type_list[type_count] = i_type; + type_count++; + } + } + } + } + + i_type_list[type_count] = LDNS_RR_TYPE_RRSIG; + type_count++; + i_type_list[type_count] = LDNS_RR_TYPE_NSEC; + type_count++; + + ldns_rr_push_rdf(nsec, + ldns_dnssec_create_nsec_bitmap(i_type_list, + type_count, LDNS_RR_TYPE_NSEC)); + + return nsec; +} + +ldns_rdf * +ldns_nsec3_hash_name(ldns_rdf *name, + uint8_t algorithm, + uint16_t iterations, + uint8_t salt_length, + uint8_t *salt) +{ + size_t hashed_owner_str_len; + ldns_rdf *cann; + ldns_rdf *hashed_owner; + unsigned char *hashed_owner_str; + char *hashed_owner_b32; + size_t hashed_owner_b32_len; + uint32_t cur_it; + /* define to contain the largest possible hash, which is + * sha1 at the moment */ + unsigned char hash[LDNS_SHA1_DIGEST_LENGTH]; + ldns_status status; + + /* TODO: mnemonic list for hash algs SHA-1, default to 1 now (sha1) */ + if (algorithm != LDNS_SHA1) { + return NULL; + } + + /* prepare the owner name according to the draft section bla */ + cann = ldns_rdf_clone(name); + if(!cann) { + fprintf(stderr, "Memory error\n"); + return NULL; + } + ldns_dname2canonical(cann); + + hashed_owner_str_len = salt_length + ldns_rdf_size(cann); + hashed_owner_str = LDNS_XMALLOC(unsigned char, hashed_owner_str_len); + if(!hashed_owner_str) { + ldns_rdf_deep_free(cann); + return NULL; + } + memcpy(hashed_owner_str, ldns_rdf_data(cann), ldns_rdf_size(cann)); + memcpy(hashed_owner_str + ldns_rdf_size(cann), salt, salt_length); + ldns_rdf_deep_free(cann); + + for (cur_it = iterations + 1; cur_it > 0; cur_it--) { + (void) ldns_sha1((unsigned char *) hashed_owner_str, + (unsigned int) hashed_owner_str_len, hash); + + LDNS_FREE(hashed_owner_str); + hashed_owner_str_len = salt_length + LDNS_SHA1_DIGEST_LENGTH; + hashed_owner_str = LDNS_XMALLOC(unsigned char, hashed_owner_str_len); + if (!hashed_owner_str) { + return NULL; + } + memcpy(hashed_owner_str, hash, LDNS_SHA1_DIGEST_LENGTH); + memcpy(hashed_owner_str + LDNS_SHA1_DIGEST_LENGTH, salt, salt_length); + hashed_owner_str_len = LDNS_SHA1_DIGEST_LENGTH + salt_length; + } + + LDNS_FREE(hashed_owner_str); + hashed_owner_str = hash; + hashed_owner_str_len = LDNS_SHA1_DIGEST_LENGTH; + + hashed_owner_b32 = LDNS_XMALLOC(char, + ldns_b32_ntop_calculate_size(hashed_owner_str_len) + 1); + if(!hashed_owner_b32) { + return NULL; + } + hashed_owner_b32_len = (size_t) ldns_b32_ntop_extended_hex( + (uint8_t *) hashed_owner_str, + hashed_owner_str_len, + hashed_owner_b32, + ldns_b32_ntop_calculate_size(hashed_owner_str_len)+1); + if (hashed_owner_b32_len < 1) { + fprintf(stderr, "Error in base32 extended hex encoding "); + fprintf(stderr, "of hashed owner name (name: "); + ldns_rdf_print(stderr, name); + fprintf(stderr, ", return code: %u)\n", + (unsigned int) hashed_owner_b32_len); + LDNS_FREE(hashed_owner_b32); + return NULL; + } + hashed_owner_b32[hashed_owner_b32_len] = '\0'; + + status = ldns_str2rdf_dname(&hashed_owner, hashed_owner_b32); + if (status != LDNS_STATUS_OK) { + fprintf(stderr, "Error creating rdf from %s\n", hashed_owner_b32); + LDNS_FREE(hashed_owner_b32); + return NULL; + } + + LDNS_FREE(hashed_owner_b32); + return hashed_owner; +} + +void +ldns_nsec3_add_param_rdfs(ldns_rr *rr, + uint8_t algorithm, + uint8_t flags, + uint16_t iterations, + uint8_t salt_length, + uint8_t *salt) +{ + ldns_rdf *salt_rdf = NULL; + uint8_t *salt_data = NULL; + ldns_rdf *old; + + old = ldns_rr_set_rdf(rr, + ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT8, + 1, (void*)&algorithm), + 0); + if (old) ldns_rdf_deep_free(old); + + old = ldns_rr_set_rdf(rr, + ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT8, + 1, (void*)&flags), + 1); + if (old) ldns_rdf_deep_free(old); + + old = ldns_rr_set_rdf(rr, + ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, + iterations), + 2); + if (old) ldns_rdf_deep_free(old); + + salt_data = LDNS_XMALLOC(uint8_t, salt_length + 1); + if(!salt_data) { + /* no way to return error */ + return; + } + salt_data[0] = salt_length; + memcpy(salt_data + 1, salt, salt_length); + salt_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_NSEC3_SALT, + salt_length + 1, + salt_data); + if(!salt_rdf) { + LDNS_FREE(salt_data); + /* no way to return error */ + return; + } + + old = ldns_rr_set_rdf(rr, salt_rdf, 3); + if (old) ldns_rdf_deep_free(old); + LDNS_FREE(salt_data); +} + +static int +rr_list_delegation_only(ldns_rdf *origin, ldns_rr_list *rr_list) +{ + size_t i; + ldns_rr *cur_rr; + if (!origin || !rr_list) return 0; + for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) { + cur_rr = ldns_rr_list_rr(rr_list, i); + if (ldns_dname_compare(ldns_rr_owner(cur_rr), origin) == 0) { + return 0; + } + if (ldns_rr_get_type(cur_rr) != LDNS_RR_TYPE_NS) { + return 0; + } + } + return 1; +} + +/* this will NOT return the NSEC3 completed, you will have to run the + finalize function on the rrlist later! */ +ldns_rr * +ldns_create_nsec3(ldns_rdf *cur_owner, + ldns_rdf *cur_zone, + ldns_rr_list *rrs, + uint8_t algorithm, + uint8_t flags, + uint16_t iterations, + uint8_t salt_length, + uint8_t *salt, + bool emptynonterminal) +{ + size_t i; + ldns_rr *i_rr; + uint16_t i_type; + + ldns_rr *nsec = NULL; + ldns_rdf *hashed_owner = NULL; + + ldns_status status; + + ldns_rr_type i_type_list[1024]; + size_t type_count = 0; + + hashed_owner = ldns_nsec3_hash_name(cur_owner, + algorithm, + iterations, + salt_length, + salt); + status = ldns_dname_cat(hashed_owner, cur_zone); + if(status != LDNS_STATUS_OK) + return NULL; + + nsec = ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3); + if(!nsec) + return NULL; + ldns_rr_set_type(nsec, LDNS_RR_TYPE_NSEC3); + ldns_rr_set_owner(nsec, hashed_owner); + + ldns_nsec3_add_param_rdfs(nsec, + algorithm, + flags, + iterations, + salt_length, + salt); + (void) ldns_rr_set_rdf(nsec, NULL, 4); + + + for (i = 0; i < ldns_rr_list_rr_count(rrs); i++) { + i_rr = ldns_rr_list_rr(rrs, i); + if (ldns_rdf_compare(cur_owner, + ldns_rr_owner(i_rr)) == 0) { + i_type = ldns_rr_get_type(i_rr); + if (type_count == 0 || i_type_list[type_count-1] != i_type) { + i_type_list[type_count] = i_type; + type_count++; + } + } + } + + /* add RRSIG anyway, but only if this is not an ENT or + * an unsigned delegation */ + if (!emptynonterminal && !rr_list_delegation_only(cur_zone, rrs)) { + i_type_list[type_count] = LDNS_RR_TYPE_RRSIG; + type_count++; + } + + /* and SOA if owner == zone */ + if (ldns_dname_compare(cur_zone, cur_owner) == 0) { + i_type_list[type_count] = LDNS_RR_TYPE_SOA; + type_count++; + } + + ldns_rr_push_rdf(nsec, + ldns_dnssec_create_nsec_bitmap(i_type_list, + type_count, LDNS_RR_TYPE_NSEC3)); + + return nsec; +} + +uint8_t +ldns_nsec3_algorithm(const ldns_rr *nsec3_rr) +{ + if (nsec3_rr && + (ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3 || + ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3PARAM) + && (ldns_rr_rdf(nsec3_rr, 0) != NULL) + && ldns_rdf_size(ldns_rr_rdf(nsec3_rr, 0)) > 0) { + return ldns_rdf2native_int8(ldns_rr_rdf(nsec3_rr, 0)); + } + return 0; +} + +uint8_t +ldns_nsec3_flags(const ldns_rr *nsec3_rr) +{ + if (nsec3_rr && + (ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3 || + ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3PARAM) + && (ldns_rr_rdf(nsec3_rr, 1) != NULL) + && ldns_rdf_size(ldns_rr_rdf(nsec3_rr, 1)) > 0) { + return ldns_rdf2native_int8(ldns_rr_rdf(nsec3_rr, 1)); + } + return 0; +} + +bool +ldns_nsec3_optout(const ldns_rr *nsec3_rr) +{ + return (ldns_nsec3_flags(nsec3_rr) & LDNS_NSEC3_VARS_OPTOUT_MASK); +} + +uint16_t +ldns_nsec3_iterations(const ldns_rr *nsec3_rr) +{ + if (nsec3_rr && + (ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3 || + ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3PARAM) + && (ldns_rr_rdf(nsec3_rr, 2) != NULL) + && ldns_rdf_size(ldns_rr_rdf(nsec3_rr, 2)) > 0) { + return ldns_rdf2native_int16(ldns_rr_rdf(nsec3_rr, 2)); + } + return 0; + +} + +ldns_rdf * +ldns_nsec3_salt(const ldns_rr *nsec3_rr) +{ + if (nsec3_rr && + (ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3 || + ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3PARAM) + ) { + return ldns_rr_rdf(nsec3_rr, 3); + } + return NULL; +} + +uint8_t +ldns_nsec3_salt_length(const ldns_rr *nsec3_rr) +{ + ldns_rdf *salt_rdf = ldns_nsec3_salt(nsec3_rr); + if (salt_rdf && ldns_rdf_size(salt_rdf) > 0) { + return (uint8_t) ldns_rdf_data(salt_rdf)[0]; + } + return 0; +} + +/* allocs data, free with LDNS_FREE() */ +uint8_t * +ldns_nsec3_salt_data(const ldns_rr *nsec3_rr) +{ + uint8_t salt_length; + uint8_t *salt; + + ldns_rdf *salt_rdf = ldns_nsec3_salt(nsec3_rr); + if (salt_rdf && ldns_rdf_size(salt_rdf) > 0) { + salt_length = ldns_rdf_data(salt_rdf)[0]; + salt = LDNS_XMALLOC(uint8_t, salt_length); + if(!salt) return NULL; + memcpy(salt, &ldns_rdf_data(salt_rdf)[1], salt_length); + return salt; + } + return NULL; +} + +ldns_rdf * +ldns_nsec3_next_owner(const ldns_rr *nsec3_rr) +{ + if (!nsec3_rr || ldns_rr_get_type(nsec3_rr) != LDNS_RR_TYPE_NSEC3) { + return NULL; + } else { + return ldns_rr_rdf(nsec3_rr, 4); + } +} + +ldns_rdf * +ldns_nsec3_bitmap(const ldns_rr *nsec3_rr) +{ + if (!nsec3_rr || ldns_rr_get_type(nsec3_rr) != LDNS_RR_TYPE_NSEC3) { + return NULL; + } else { + return ldns_rr_rdf(nsec3_rr, 5); + } +} + +ldns_rdf * +ldns_nsec3_hash_name_frm_nsec3(const ldns_rr *nsec, ldns_rdf *name) +{ + uint8_t algorithm; + uint16_t iterations; + uint8_t salt_length; + uint8_t *salt = 0; + + ldns_rdf *hashed_owner; + + algorithm = ldns_nsec3_algorithm(nsec); + salt_length = ldns_nsec3_salt_length(nsec); + salt = ldns_nsec3_salt_data(nsec); + iterations = ldns_nsec3_iterations(nsec); + + hashed_owner = ldns_nsec3_hash_name(name, + algorithm, + iterations, + salt_length, + salt); + + LDNS_FREE(salt); + return hashed_owner; +} + +bool +ldns_nsec_bitmap_covers_type(const ldns_rdf *nsec_bitmap, ldns_rr_type type) +{ + uint8_t window_block_nr; + uint8_t bitmap_length; + uint16_t cur_type; + uint16_t pos = 0; + uint16_t bit_pos; + uint8_t *data; + + if (nsec_bitmap == NULL) { + return false; + } + data = ldns_rdf_data(nsec_bitmap); + while(pos < ldns_rdf_size(nsec_bitmap)) { + window_block_nr = data[pos]; + bitmap_length = data[pos + 1]; + pos += 2; + + for (bit_pos = 0; bit_pos < (bitmap_length) * 8; bit_pos++) { + if (ldns_get_bit(&data[pos], bit_pos)) { + cur_type = 256 * (uint16_t) window_block_nr + bit_pos; + if (cur_type == type) { + return true; + } + } + } + + pos += (uint16_t) bitmap_length; + } + return false; +} + +bool +ldns_nsec_covers_name(const ldns_rr *nsec, const ldns_rdf *name) +{ + ldns_rdf *nsec_owner = ldns_rr_owner(nsec); + ldns_rdf *hash_next; + char *next_hash_str; + ldns_rdf *nsec_next = NULL; + ldns_status status; + ldns_rdf *chopped_dname; + bool result; + + if (ldns_rr_get_type(nsec) == LDNS_RR_TYPE_NSEC) { + if (ldns_rr_rdf(nsec, 0) != NULL) { + nsec_next = ldns_rdf_clone(ldns_rr_rdf(nsec, 0)); + } else { + return false; + } + } else if (ldns_rr_get_type(nsec) == LDNS_RR_TYPE_NSEC3) { + hash_next = ldns_nsec3_next_owner(nsec); + next_hash_str = ldns_rdf2str(hash_next); + nsec_next = ldns_dname_new_frm_str(next_hash_str); + LDNS_FREE(next_hash_str); + chopped_dname = ldns_dname_left_chop(nsec_owner); + status = ldns_dname_cat(nsec_next, chopped_dname); + ldns_rdf_deep_free(chopped_dname); + if (status != LDNS_STATUS_OK) { + printf("error catting: %s\n", ldns_get_errorstr_by_id(status)); + } + } else { + ldns_rdf_deep_free(nsec_next); + return false; + } + + /* in the case of the last nsec */ + if(ldns_dname_compare(nsec_owner, nsec_next) > 0) { + result = (ldns_dname_compare(nsec_owner, name) <= 0 || + ldns_dname_compare(name, nsec_next) < 0); + } else { + result = (ldns_dname_compare(nsec_owner, name) <= 0 && + ldns_dname_compare(name, nsec_next) < 0); + } + + ldns_rdf_deep_free(nsec_next); + return result; +} + +#ifdef HAVE_SSL +/* sig may be null - if so look in the packet */ + +ldns_status +ldns_pkt_verify_time(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o, + ldns_rr_list *k, ldns_rr_list *s, + time_t check_time, ldns_rr_list *good_keys) +{ + ldns_rr_list *rrset; + ldns_rr_list *sigs; + ldns_rr_list *sigs_covered; + ldns_rdf *rdf_t; + ldns_rr_type t_netorder; + + if (!k) { + return LDNS_STATUS_ERR; + /* return LDNS_STATUS_CRYPTO_NO_DNSKEY; */ + } + + if (t == LDNS_RR_TYPE_RRSIG) { + /* we don't have RRSIG(RRSIG) (yet? ;-) ) */ + return LDNS_STATUS_ERR; + } + + if (s) { + /* if s is not NULL, the sigs are given to use */ + sigs = s; + } else { + /* otherwise get them from the packet */ + sigs = ldns_pkt_rr_list_by_name_and_type(p, o, LDNS_RR_TYPE_RRSIG, + LDNS_SECTION_ANY_NOQUESTION); + if (!sigs) { + /* no sigs */ + return LDNS_STATUS_ERR; + /* return LDNS_STATUS_CRYPTO_NO_RRSIG; */ + } + } + + /* rrsig are subtyped, so now we need to find the correct + * sigs for the type t + */ + t_netorder = htons(t); /* rdf are in network order! */ + /* a type identifier is a 16-bit number, so the size is 2 bytes */ + rdf_t = ldns_rdf_new(LDNS_RDF_TYPE_TYPE, + 2, + &t_netorder); + sigs_covered = ldns_rr_list_subtype_by_rdf(sigs, rdf_t, 0); + + rrset = ldns_pkt_rr_list_by_name_and_type(p, + o, + t, + LDNS_SECTION_ANY_NOQUESTION); + + if (!rrset) { + return LDNS_STATUS_ERR; + } + + if (!sigs_covered) { + return LDNS_STATUS_ERR; + } + + return ldns_verify_time(rrset, sigs, k, check_time, good_keys); +} + +ldns_status +ldns_pkt_verify(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o, + ldns_rr_list *k, ldns_rr_list *s, ldns_rr_list *good_keys) +{ + return ldns_pkt_verify_time(p, t, o, k, s, ldns_time(NULL), good_keys); +} +#endif /* HAVE_SSL */ + +ldns_status +ldns_dnssec_chain_nsec3_list(ldns_rr_list *nsec3_rrs) +{ + size_t i; + char *next_nsec_owner_str; + ldns_rdf *next_nsec_owner_label; + ldns_rdf *next_nsec_rdf; + ldns_status status = LDNS_STATUS_OK; + + for (i = 0; i < ldns_rr_list_rr_count(nsec3_rrs); i++) { + if (i == ldns_rr_list_rr_count(nsec3_rrs) - 1) { + next_nsec_owner_label = + ldns_dname_label(ldns_rr_owner(ldns_rr_list_rr(nsec3_rrs, + 0)), 0); + next_nsec_owner_str = ldns_rdf2str(next_nsec_owner_label); + if (next_nsec_owner_str[strlen(next_nsec_owner_str) - 1] + == '.') { + next_nsec_owner_str[strlen(next_nsec_owner_str) - 1] + = '\0'; + } + status = ldns_str2rdf_b32_ext(&next_nsec_rdf, + next_nsec_owner_str); + if (!ldns_rr_set_rdf(ldns_rr_list_rr(nsec3_rrs, i), + next_nsec_rdf, 4)) { + /* todo: error */ + } + + ldns_rdf_deep_free(next_nsec_owner_label); + LDNS_FREE(next_nsec_owner_str); + } else { + next_nsec_owner_label = + ldns_dname_label(ldns_rr_owner(ldns_rr_list_rr(nsec3_rrs, + i + 1)), + 0); + next_nsec_owner_str = ldns_rdf2str(next_nsec_owner_label); + if (next_nsec_owner_str[strlen(next_nsec_owner_str) - 1] + == '.') { + next_nsec_owner_str[strlen(next_nsec_owner_str) - 1] + = '\0'; + } + status = ldns_str2rdf_b32_ext(&next_nsec_rdf, + next_nsec_owner_str); + ldns_rdf_deep_free(next_nsec_owner_label); + LDNS_FREE(next_nsec_owner_str); + if (!ldns_rr_set_rdf(ldns_rr_list_rr(nsec3_rrs, i), + next_nsec_rdf, 4)) { + /* todo: error */ + } + } + } + return status; +} + +int +qsort_rr_compare_nsec3(const void *a, const void *b) +{ + const ldns_rr *rr1 = * (const ldns_rr **) a; + const ldns_rr *rr2 = * (const ldns_rr **) b; + if (rr1 == NULL && rr2 == NULL) { + return 0; + } + if (rr1 == NULL) { + return -1; + } + if (rr2 == NULL) { + return 1; + } + return ldns_rdf_compare(ldns_rr_owner(rr1), ldns_rr_owner(rr2)); +} + +void +ldns_rr_list_sort_nsec3(ldns_rr_list *unsorted) +{ + qsort(unsorted->_rrs, + ldns_rr_list_rr_count(unsorted), + sizeof(ldns_rr *), + qsort_rr_compare_nsec3); +} + +int +ldns_dnssec_default_add_to_signatures( ATTR_UNUSED(ldns_rr *sig) + , ATTR_UNUSED(void *n) + ) +{ + return LDNS_SIGNATURE_LEAVE_ADD_NEW; +} + +int +ldns_dnssec_default_leave_signatures( ATTR_UNUSED(ldns_rr *sig) + , ATTR_UNUSED(void *n) + ) +{ + return LDNS_SIGNATURE_LEAVE_NO_ADD; +} + +int +ldns_dnssec_default_delete_signatures( ATTR_UNUSED(ldns_rr *sig) + , ATTR_UNUSED(void *n) + ) +{ + return LDNS_SIGNATURE_REMOVE_NO_ADD; +} + +int +ldns_dnssec_default_replace_signatures( ATTR_UNUSED(ldns_rr *sig) + , ATTR_UNUSED(void *n) + ) +{ + return LDNS_SIGNATURE_REMOVE_ADD_NEW; +} + +#ifdef HAVE_SSL +ldns_rdf * +ldns_convert_dsa_rrsig_asn12rdf(const ldns_buffer *sig, + const long sig_len) +{ + ldns_rdf *sigdata_rdf; + DSA_SIG *dsasig; + unsigned char *dsasig_data = (unsigned char*)ldns_buffer_begin(sig); + size_t byte_offset; + + dsasig = d2i_DSA_SIG(NULL, + (const unsigned char **)&dsasig_data, + sig_len); + if (!dsasig) { + DSA_SIG_free(dsasig); + return NULL; + } + + dsasig_data = LDNS_XMALLOC(unsigned char, 41); + if(!dsasig_data) { + DSA_SIG_free(dsasig); + return NULL; + } + dsasig_data[0] = 0; + byte_offset = (size_t) (20 - BN_num_bytes(dsasig->r)); + if (byte_offset > 20) { + DSA_SIG_free(dsasig); + LDNS_FREE(dsasig_data); + return NULL; + } + memset(&dsasig_data[1], 0, byte_offset); + BN_bn2bin(dsasig->r, &dsasig_data[1 + byte_offset]); + byte_offset = (size_t) (20 - BN_num_bytes(dsasig->s)); + if (byte_offset > 20) { + DSA_SIG_free(dsasig); + LDNS_FREE(dsasig_data); + return NULL; + } + memset(&dsasig_data[21], 0, byte_offset); + BN_bn2bin(dsasig->s, &dsasig_data[21 + byte_offset]); + + sigdata_rdf = ldns_rdf_new(LDNS_RDF_TYPE_B64, 41, dsasig_data); + if(!sigdata_rdf) { + LDNS_FREE(dsasig_data); + } + DSA_SIG_free(dsasig); + + return sigdata_rdf; +} + +ldns_status +ldns_convert_dsa_rrsig_rdf2asn1(ldns_buffer *target_buffer, + const ldns_rdf *sig_rdf) +{ + /* the EVP api wants the DER encoding of the signature... */ + BIGNUM *R, *S; + DSA_SIG *dsasig; + unsigned char *raw_sig = NULL; + int raw_sig_len; + + if(ldns_rdf_size(sig_rdf) < 1 + 2*SHA_DIGEST_LENGTH) + return LDNS_STATUS_SYNTAX_RDATA_ERR; + /* extract the R and S field from the sig buffer */ + R = BN_new(); + if(!R) return LDNS_STATUS_MEM_ERR; + (void) BN_bin2bn((unsigned char *) ldns_rdf_data(sig_rdf) + 1, + SHA_DIGEST_LENGTH, R); + S = BN_new(); + if(!S) { + BN_free(R); + return LDNS_STATUS_MEM_ERR; + } + (void) BN_bin2bn((unsigned char *) ldns_rdf_data(sig_rdf) + 21, + SHA_DIGEST_LENGTH, S); + + dsasig = DSA_SIG_new(); + if (!dsasig) { + BN_free(R); + BN_free(S); + return LDNS_STATUS_MEM_ERR; + } + + dsasig->r = R; + dsasig->s = S; + + raw_sig_len = i2d_DSA_SIG(dsasig, &raw_sig); + if (raw_sig_len < 0) { + DSA_SIG_free(dsasig); + free(raw_sig); + return LDNS_STATUS_SSL_ERR; + } + if (ldns_buffer_reserve(target_buffer, (size_t) raw_sig_len)) { + ldns_buffer_write(target_buffer, raw_sig, (size_t)raw_sig_len); + } + + DSA_SIG_free(dsasig); + free(raw_sig); + + return ldns_buffer_status(target_buffer); +} + +#ifdef USE_ECDSA +#ifndef S_SPLINT_S +ldns_rdf * +ldns_convert_ecdsa_rrsig_asn12rdf(const ldns_buffer *sig, const long sig_len) +{ + ECDSA_SIG* ecdsa_sig; + unsigned char *data = (unsigned char*)ldns_buffer_begin(sig); + ldns_rdf* rdf; + ecdsa_sig = d2i_ECDSA_SIG(NULL, (const unsigned char **)&data, sig_len); + if(!ecdsa_sig) return NULL; + + /* "r | s". */ + data = LDNS_XMALLOC(unsigned char, + BN_num_bytes(ecdsa_sig->r) + BN_num_bytes(ecdsa_sig->s)); + if(!data) { + ECDSA_SIG_free(ecdsa_sig); + return NULL; + } + BN_bn2bin(ecdsa_sig->r, data); + BN_bn2bin(ecdsa_sig->s, data+BN_num_bytes(ecdsa_sig->r)); + rdf = ldns_rdf_new(LDNS_RDF_TYPE_B64, (size_t)( + BN_num_bytes(ecdsa_sig->r) + BN_num_bytes(ecdsa_sig->s)), data); + ECDSA_SIG_free(ecdsa_sig); + return rdf; +} + +ldns_status +ldns_convert_ecdsa_rrsig_rdf2asn1(ldns_buffer *target_buffer, + const ldns_rdf *sig_rdf) +{ + ECDSA_SIG* sig; + int raw_sig_len; + long bnsize = (long)ldns_rdf_size(sig_rdf) / 2; + /* if too short, or not even length, do not bother */ + if(bnsize < 16 || (size_t)bnsize*2 != ldns_rdf_size(sig_rdf)) + return LDNS_STATUS_ERR; + + /* use the raw data to parse two evenly long BIGNUMs, "r | s". */ + sig = ECDSA_SIG_new(); + if(!sig) return LDNS_STATUS_MEM_ERR; + sig->r = BN_bin2bn((const unsigned char*)ldns_rdf_data(sig_rdf), + bnsize, sig->r); + sig->s = BN_bin2bn((const unsigned char*)ldns_rdf_data(sig_rdf)+bnsize, + bnsize, sig->s); + if(!sig->r || !sig->s) { + ECDSA_SIG_free(sig); + return LDNS_STATUS_MEM_ERR; + } + + raw_sig_len = i2d_ECDSA_SIG(sig, NULL); + if (ldns_buffer_reserve(target_buffer, (size_t) raw_sig_len)) { + unsigned char* pp = (unsigned char*) + ldns_buffer_current(target_buffer); + raw_sig_len = i2d_ECDSA_SIG(sig, &pp); + ldns_buffer_skip(target_buffer, (ssize_t) raw_sig_len); + } + ECDSA_SIG_free(sig); + + return ldns_buffer_status(target_buffer); +} + +#endif /* S_SPLINT_S */ +#endif /* USE_ECDSA */ +#endif /* HAVE_SSL */ diff --git a/dnssec_sign.c b/dnssec_sign.c new file mode 100644 index 00000000000..88878bad044 --- /dev/null +++ b/dnssec_sign.c @@ -0,0 +1,1420 @@ +#include + +#include + +#include +#include + +#include +#include + +#ifdef HAVE_SSL +/* this entire file is rather useless when you don't have + * crypto... + */ +#include +#include +#include +#include +#include +#endif /* HAVE_SSL */ + +ldns_rr * +ldns_create_empty_rrsig(ldns_rr_list *rrset, + ldns_key *current_key) +{ + uint32_t orig_ttl; + ldns_rr_class orig_class; + time_t now; + ldns_rr *current_sig; + uint8_t label_count; + ldns_rdf *signame; + + label_count = ldns_dname_label_count(ldns_rr_owner(ldns_rr_list_rr(rrset, + 0))); + /* RFC4035 2.2: not counting the leftmost label if it is a wildcard */ + if(ldns_dname_is_wildcard(ldns_rr_owner(ldns_rr_list_rr(rrset, 0)))) + label_count --; + + current_sig = ldns_rr_new_frm_type(LDNS_RR_TYPE_RRSIG); + + /* set the type on the new signature */ + orig_ttl = ldns_rr_ttl(ldns_rr_list_rr(rrset, 0)); + orig_class = ldns_rr_get_class(ldns_rr_list_rr(rrset, 0)); + + ldns_rr_set_ttl(current_sig, orig_ttl); + ldns_rr_set_class(current_sig, orig_class); + ldns_rr_set_owner(current_sig, + ldns_rdf_clone( + ldns_rr_owner( + ldns_rr_list_rr(rrset, + 0)))); + + /* fill in what we know of the signature */ + + /* set the orig_ttl */ + (void)ldns_rr_rrsig_set_origttl( + current_sig, + ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, + orig_ttl)); + /* the signers name */ + signame = ldns_rdf_clone(ldns_key_pubkey_owner(current_key)); + ldns_dname2canonical(signame); + (void)ldns_rr_rrsig_set_signame( + current_sig, + signame); + /* label count - get it from the first rr in the rr_list */ + (void)ldns_rr_rrsig_set_labels( + current_sig, + ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, + label_count)); + /* inception, expiration */ + now = time(NULL); + if (ldns_key_inception(current_key) != 0) { + (void)ldns_rr_rrsig_set_inception( + current_sig, + ldns_native2rdf_int32( + LDNS_RDF_TYPE_TIME, + ldns_key_inception(current_key))); + } else { + (void)ldns_rr_rrsig_set_inception( + current_sig, + ldns_native2rdf_int32(LDNS_RDF_TYPE_TIME, now)); + } + if (ldns_key_expiration(current_key) != 0) { + (void)ldns_rr_rrsig_set_expiration( + current_sig, + ldns_native2rdf_int32( + LDNS_RDF_TYPE_TIME, + ldns_key_expiration(current_key))); + } else { + (void)ldns_rr_rrsig_set_expiration( + current_sig, + ldns_native2rdf_int32( + LDNS_RDF_TYPE_TIME, + now + LDNS_DEFAULT_EXP_TIME)); + } + + (void)ldns_rr_rrsig_set_keytag( + current_sig, + ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, + ldns_key_keytag(current_key))); + + (void)ldns_rr_rrsig_set_algorithm( + current_sig, + ldns_native2rdf_int8( + LDNS_RDF_TYPE_ALG, + ldns_key_algorithm(current_key))); + + (void)ldns_rr_rrsig_set_typecovered( + current_sig, + ldns_native2rdf_int16( + LDNS_RDF_TYPE_TYPE, + ldns_rr_get_type(ldns_rr_list_rr(rrset, + 0)))); + return current_sig; +} + +#ifdef HAVE_SSL +ldns_rdf * +ldns_sign_public_buffer(ldns_buffer *sign_buf, ldns_key *current_key) +{ + ldns_rdf *b64rdf = NULL; + + switch(ldns_key_algorithm(current_key)) { + case LDNS_SIGN_DSA: + case LDNS_SIGN_DSA_NSEC3: + b64rdf = ldns_sign_public_evp( + sign_buf, + ldns_key_evp_key(current_key), + EVP_dss1()); + break; + case LDNS_SIGN_RSASHA1: + case LDNS_SIGN_RSASHA1_NSEC3: + b64rdf = ldns_sign_public_evp( + sign_buf, + ldns_key_evp_key(current_key), + EVP_sha1()); + break; +#ifdef USE_SHA2 + case LDNS_SIGN_RSASHA256: + b64rdf = ldns_sign_public_evp( + sign_buf, + ldns_key_evp_key(current_key), + EVP_sha256()); + break; + case LDNS_SIGN_RSASHA512: + b64rdf = ldns_sign_public_evp( + sign_buf, + ldns_key_evp_key(current_key), + EVP_sha512()); + break; +#endif /* USE_SHA2 */ +#ifdef USE_GOST + case LDNS_SIGN_ECC_GOST: + b64rdf = ldns_sign_public_evp( + sign_buf, + ldns_key_evp_key(current_key), + EVP_get_digestbyname("md_gost94")); + break; +#endif /* USE_GOST */ +#ifdef USE_ECDSA + case LDNS_SIGN_ECDSAP256SHA256: + b64rdf = ldns_sign_public_evp( + sign_buf, + ldns_key_evp_key(current_key), + EVP_sha256()); + break; + case LDNS_SIGN_ECDSAP384SHA384: + b64rdf = ldns_sign_public_evp( + sign_buf, + ldns_key_evp_key(current_key), + EVP_sha384()); + break; +#endif + case LDNS_SIGN_RSAMD5: + b64rdf = ldns_sign_public_evp( + sign_buf, + ldns_key_evp_key(current_key), + EVP_md5()); + break; + default: + /* do _you_ know this alg? */ + printf("unknown algorithm, "); + printf("is the one used available on this system?\n"); + break; + } + + return b64rdf; +} + +/** + * use this function to sign with a public/private key alg + * return the created signatures + */ +ldns_rr_list * +ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys) +{ + ldns_rr_list *signatures; + ldns_rr_list *rrset_clone; + ldns_rr *current_sig; + ldns_rdf *b64rdf; + ldns_key *current_key; + size_t key_count; + uint16_t i; + ldns_buffer *sign_buf; + ldns_rdf *new_owner; + + if (!rrset || ldns_rr_list_rr_count(rrset) < 1 || !keys) { + return NULL; + } + + new_owner = NULL; + + signatures = ldns_rr_list_new(); + + /* prepare a signature and add all the know data + * prepare the rrset. Sign this together. */ + rrset_clone = ldns_rr_list_clone(rrset); + if (!rrset_clone) { + return NULL; + } + + /* make it canonical */ + for(i = 0; i < ldns_rr_list_rr_count(rrset_clone); i++) { + ldns_rr_set_ttl(ldns_rr_list_rr(rrset_clone, i), + ldns_rr_ttl(ldns_rr_list_rr(rrset, 0))); + ldns_rr2canonical(ldns_rr_list_rr(rrset_clone, i)); + } + /* sort */ + ldns_rr_list_sort(rrset_clone); + + for (key_count = 0; + key_count < ldns_key_list_key_count(keys); + key_count++) { + if (!ldns_key_use(ldns_key_list_key(keys, key_count))) { + continue; + } + sign_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN); + if (!sign_buf) { + ldns_rr_list_free(rrset_clone); + ldns_rr_list_free(signatures); + ldns_rdf_free(new_owner); + return NULL; + } + b64rdf = NULL; + + current_key = ldns_key_list_key(keys, key_count); + /* sign all RRs with keys that have ZSKbit, !SEPbit. + sign DNSKEY RRs with keys that have ZSKbit&SEPbit */ + if (ldns_key_flags(current_key) & LDNS_KEY_ZONE_KEY) { + current_sig = ldns_create_empty_rrsig(rrset_clone, + current_key); + + /* right now, we have: a key, a semi-sig and an rrset. For + * which we can create the sig and base64 encode that and + * add that to the signature */ + + if (ldns_rrsig2buffer_wire(sign_buf, current_sig) + != LDNS_STATUS_OK) { + ldns_buffer_free(sign_buf); + /* ERROR */ + ldns_rr_list_deep_free(rrset_clone); + return NULL; + } + + /* add the rrset in sign_buf */ + if (ldns_rr_list2buffer_wire(sign_buf, rrset_clone) + != LDNS_STATUS_OK) { + ldns_buffer_free(sign_buf); + ldns_rr_list_deep_free(rrset_clone); + return NULL; + } + + b64rdf = ldns_sign_public_buffer(sign_buf, current_key); + + if (!b64rdf) { + /* signing went wrong */ + ldns_rr_list_deep_free(rrset_clone); + return NULL; + } + + ldns_rr_rrsig_set_sig(current_sig, b64rdf); + + /* push the signature to the signatures list */ + ldns_rr_list_push_rr(signatures, current_sig); + } + ldns_buffer_free(sign_buf); /* restart for the next key */ + } + ldns_rr_list_deep_free(rrset_clone); + + return signatures; +} + +/** + * Sign data with DSA + * + * \param[in] to_sign The ldns_buffer containing raw data that is + * to be signed + * \param[in] key The DSA key structure to sign with + * \return ldns_rdf for the RRSIG ldns_rr + */ +ldns_rdf * +ldns_sign_public_dsa(ldns_buffer *to_sign, DSA *key) +{ + unsigned char *sha1_hash; + ldns_rdf *sigdata_rdf; + ldns_buffer *b64sig; + + DSA_SIG *sig; + uint8_t *data; + size_t pad; + + b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN); + if (!b64sig) { + return NULL; + } + + sha1_hash = SHA1((unsigned char*)ldns_buffer_begin(to_sign), + ldns_buffer_position(to_sign), NULL); + if (!sha1_hash) { + ldns_buffer_free(b64sig); + return NULL; + } + + sig = DSA_do_sign(sha1_hash, SHA_DIGEST_LENGTH, key); + if(!sig) { + ldns_buffer_free(b64sig); + return NULL; + } + + data = LDNS_XMALLOC(uint8_t, 1 + 2 * SHA_DIGEST_LENGTH); + if(!data) { + ldns_buffer_free(b64sig); + DSA_SIG_free(sig); + return NULL; + } + + data[0] = 1; + pad = 20 - (size_t) BN_num_bytes(sig->r); + if (pad > 0) { + memset(data + 1, 0, pad); + } + BN_bn2bin(sig->r, (unsigned char *) (data + 1) + pad); + + pad = 20 - (size_t) BN_num_bytes(sig->s); + if (pad > 0) { + memset(data + 1 + SHA_DIGEST_LENGTH, 0, pad); + } + BN_bn2bin(sig->s, (unsigned char *) (data + 1 + SHA_DIGEST_LENGTH + pad)); + + sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, + 1 + 2 * SHA_DIGEST_LENGTH, + data); + + ldns_buffer_free(b64sig); + LDNS_FREE(data); + DSA_SIG_free(sig); + + return sigdata_rdf; +} + +#ifdef USE_ECDSA +#ifndef S_SPLINT_S +static int +ldns_pkey_is_ecdsa(EVP_PKEY* pkey) +{ + EC_KEY* ec; + const EC_GROUP* g; + if(EVP_PKEY_type(pkey->type) != EVP_PKEY_EC) + return 0; + ec = EVP_PKEY_get1_EC_KEY(pkey); + g = EC_KEY_get0_group(ec); + if(!g) { + EC_KEY_free(ec); + return 0; + } + if(EC_GROUP_get_curve_name(g) == NID_secp224r1 || + EC_GROUP_get_curve_name(g) == NID_X9_62_prime256v1 || + EC_GROUP_get_curve_name(g) == NID_secp384r1) { + EC_KEY_free(ec); + return 1; + } + /* downref the eckey, the original is still inside the pkey */ + EC_KEY_free(ec); + return 0; +} +#endif /* splint */ +#endif /* USE_ECDSA */ + +ldns_rdf * +ldns_sign_public_evp(ldns_buffer *to_sign, + EVP_PKEY *key, + const EVP_MD *digest_type) +{ + unsigned int siglen; + ldns_rdf *sigdata_rdf; + ldns_buffer *b64sig; + EVP_MD_CTX ctx; + const EVP_MD *md_type; + int r; + + siglen = 0; + b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN); + if (!b64sig) { + return NULL; + } + + /* initializes a signing context */ + md_type = digest_type; + if(!md_type) { + /* unknown message difest */ + ldns_buffer_free(b64sig); + return NULL; + } + + EVP_MD_CTX_init(&ctx); + r = EVP_SignInit(&ctx, md_type); + if(r == 1) { + r = EVP_SignUpdate(&ctx, (unsigned char*) + ldns_buffer_begin(to_sign), + ldns_buffer_position(to_sign)); + } else { + ldns_buffer_free(b64sig); + return NULL; + } + if(r == 1) { + r = EVP_SignFinal(&ctx, (unsigned char*) + ldns_buffer_begin(b64sig), &siglen, key); + } else { + ldns_buffer_free(b64sig); + return NULL; + } + if(r != 1) { + ldns_buffer_free(b64sig); + return NULL; + } + + /* unfortunately, OpenSSL output is differenct from DNS DSA format */ +#ifndef S_SPLINT_S + if (EVP_PKEY_type(key->type) == EVP_PKEY_DSA) { + sigdata_rdf = ldns_convert_dsa_rrsig_asn12rdf(b64sig, siglen); +#ifdef USE_ECDSA + } else if(EVP_PKEY_type(key->type) == EVP_PKEY_EC && + ldns_pkey_is_ecdsa(key)) { + sigdata_rdf = ldns_convert_ecdsa_rrsig_asn12rdf(b64sig, siglen); +#endif + } else { + /* ok output for other types is the same */ + sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen, + ldns_buffer_begin(b64sig)); + } +#endif /* splint */ + ldns_buffer_free(b64sig); + EVP_MD_CTX_cleanup(&ctx); + return sigdata_rdf; +} + +ldns_rdf * +ldns_sign_public_rsasha1(ldns_buffer *to_sign, RSA *key) +{ + unsigned char *sha1_hash; + unsigned int siglen; + ldns_rdf *sigdata_rdf; + ldns_buffer *b64sig; + int result; + + siglen = 0; + b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN); + if (!b64sig) { + return NULL; + } + + sha1_hash = SHA1((unsigned char*)ldns_buffer_begin(to_sign), + ldns_buffer_position(to_sign), NULL); + if (!sha1_hash) { + ldns_buffer_free(b64sig); + return NULL; + } + + result = RSA_sign(NID_sha1, sha1_hash, SHA_DIGEST_LENGTH, + (unsigned char*)ldns_buffer_begin(b64sig), + &siglen, key); + if (result != 1) { + return NULL; + } + + if (result != 1) { + return NULL; + } + + sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen, + ldns_buffer_begin(b64sig)); + ldns_buffer_free(b64sig); /* can't free this buffer ?? */ + return sigdata_rdf; +} + +ldns_rdf * +ldns_sign_public_rsamd5(ldns_buffer *to_sign, RSA *key) +{ + unsigned char *md5_hash; + unsigned int siglen; + ldns_rdf *sigdata_rdf; + ldns_buffer *b64sig; + + b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN); + if (!b64sig) { + return NULL; + } + + md5_hash = MD5((unsigned char*)ldns_buffer_begin(to_sign), + ldns_buffer_position(to_sign), NULL); + if (!md5_hash) { + ldns_buffer_free(b64sig); + return NULL; + } + + RSA_sign(NID_md5, md5_hash, MD5_DIGEST_LENGTH, + (unsigned char*)ldns_buffer_begin(b64sig), + &siglen, key); + + sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen, + ldns_buffer_begin(b64sig)); + ldns_buffer_free(b64sig); + return sigdata_rdf; +} +#endif /* HAVE_SSL */ + +/** + * Pushes all rrs from the rrsets of type A and AAAA on gluelist. + */ +static ldns_status +ldns_dnssec_addresses_on_glue_list( + ldns_dnssec_rrsets *cur_rrset, + ldns_rr_list *glue_list) +{ + ldns_dnssec_rrs *cur_rrs; + while (cur_rrset) { + if (cur_rrset->type == LDNS_RR_TYPE_A + || cur_rrset->type == LDNS_RR_TYPE_AAAA) { + for (cur_rrs = cur_rrset->rrs; + cur_rrs; + cur_rrs = cur_rrs->next) { + if (cur_rrs->rr) { + if (!ldns_rr_list_push_rr(glue_list, + cur_rrs->rr)) { + return LDNS_STATUS_MEM_ERR; + /* ldns_rr_list_push_rr() + * returns false when unable + * to increase the capacity + * of the ldsn_rr_list + */ + } + } + } + } + cur_rrset = cur_rrset->next; + } + return LDNS_STATUS_OK; +} + +/** + * Marks the names in the zone that are occluded. Those names will be skipped + * when walking the tree with the ldns_dnssec_name_node_next_nonglue() + * function. But watch out! Names that are partially occluded (like glue with + * the same name as the delegation) will not be marked and should specifically + * be taken into account seperately. + * + * When glue_list is given (not NULL), in the process of marking the names, all + * glue resource records will be pushed to that list, even glue at delegation names. + * + * \param[in] zone the zone in which to mark the names + * \param[in] glue_list the list to which to push the glue rrs + * \return LDNS_STATUS_OK on success, an error code otherwise + */ +ldns_status +ldns_dnssec_zone_mark_and_get_glue(ldns_dnssec_zone *zone, + ldns_rr_list *glue_list) +{ + ldns_rbnode_t *node; + ldns_dnssec_name *name; + ldns_rdf *owner; + ldns_rdf *cut = NULL; /* keeps track of zone cuts */ + /* When the cut is caused by a delegation, below_delegation will be 1. + * When caused by a DNAME, below_delegation will be 0. + */ + int below_delegation = -1; /* init suppresses comiler warning */ + ldns_status s; + + if (!zone || !zone->names) { + return LDNS_STATUS_NULL; + } + for (node = ldns_rbtree_first(zone->names); + node != LDNS_RBTREE_NULL; + node = ldns_rbtree_next(node)) { + name = (ldns_dnssec_name *) node->data; + owner = ldns_dnssec_name_name(name); + + if (cut) { + /* The previous node was a zone cut, or a subdomain + * below a zone cut. Is this node (still) a subdomain + * below the cut? Then the name is occluded. Unless + * the name contains a SOA, after which we are + * authoritative again. + * + * FIXME! If there are labels in between the SOA and + * the cut, going from the authoritative space (below + * the SOA) up into occluded space again, will not be + * detected with the contruct below! + */ + if (ldns_dname_is_subdomain(owner, cut) && + !ldns_dnssec_rrsets_contains_type( + name->rrsets, LDNS_RR_TYPE_SOA)) { + + if (below_delegation && glue_list) { + s = ldns_dnssec_addresses_on_glue_list( + name->rrsets, glue_list); + if (s != LDNS_STATUS_OK) { + return s; + } + } + name->is_glue = true; /* Mark occluded name! */ + continue; + } else { + cut = NULL; + } + } + + /* The node is not below a zone cut. Is it a zone cut itself? + * Everything below a SOA is authoritative of course; Except + * when the name also contains a DNAME :). + */ + if (ldns_dnssec_rrsets_contains_type( + name->rrsets, LDNS_RR_TYPE_NS) + && !ldns_dnssec_rrsets_contains_type( + name->rrsets, LDNS_RR_TYPE_SOA)) { + cut = owner; + below_delegation = 1; + if (glue_list) { /* record glue on the zone cut */ + s = ldns_dnssec_addresses_on_glue_list( + name->rrsets, glue_list); + if (s != LDNS_STATUS_OK) { + return s; + } + } + } else if (ldns_dnssec_rrsets_contains_type( + name->rrsets, LDNS_RR_TYPE_DNAME)) { + cut = owner; + below_delegation = 0; + } + } + return LDNS_STATUS_OK; +} + +/** + * Marks the names in the zone that are occluded. Those names will be skipped + * when walking the tree with the ldns_dnssec_name_node_next_nonglue() + * function. But watch out! Names that are partially occluded (like glue with + * the same name as the delegation) will not be marked and should specifically + * be taken into account seperately. + * + * \param[in] zone the zone in which to mark the names + * \return LDNS_STATUS_OK on success, an error code otherwise + */ +ldns_status +ldns_dnssec_zone_mark_glue(ldns_dnssec_zone *zone) +{ + return ldns_dnssec_zone_mark_and_get_glue(zone, NULL); +} + +ldns_rbnode_t * +ldns_dnssec_name_node_next_nonglue(ldns_rbnode_t *node) +{ + ldns_rbnode_t *next_node = NULL; + ldns_dnssec_name *next_name = NULL; + bool done = false; + + if (node == LDNS_RBTREE_NULL) { + return NULL; + } + next_node = node; + while (!done) { + if (next_node == LDNS_RBTREE_NULL) { + return NULL; + } else { + next_name = (ldns_dnssec_name *)next_node->data; + if (!next_name->is_glue) { + done = true; + } else { + next_node = ldns_rbtree_next(next_node); + } + } + } + return next_node; +} + +ldns_status +ldns_dnssec_zone_create_nsecs(ldns_dnssec_zone *zone, + ldns_rr_list *new_rrs) +{ + + ldns_rbnode_t *first_node, *cur_node, *next_node; + ldns_dnssec_name *cur_name, *next_name; + ldns_rr *nsec_rr; + uint32_t nsec_ttl; + ldns_dnssec_rrsets *soa; + + /* the TTL of NSEC rrs should be set to the minimum TTL of + * the zone SOA (RFC4035 Section 2.3) + */ + soa = ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_SOA); + + /* did the caller actually set it? if not, + * fall back to default ttl + */ + if (soa && soa->rrs && soa->rrs->rr + && (ldns_rr_rdf(soa->rrs->rr, 6) != NULL)) { + nsec_ttl = ldns_rdf2native_int32(ldns_rr_rdf(soa->rrs->rr, 6)); + } else { + nsec_ttl = LDNS_DEFAULT_TTL; + } + + first_node = ldns_dnssec_name_node_next_nonglue( + ldns_rbtree_first(zone->names)); + cur_node = first_node; + if (cur_node) { + next_node = ldns_dnssec_name_node_next_nonglue( + ldns_rbtree_next(cur_node)); + } else { + next_node = NULL; + } + + while (cur_node && next_node) { + cur_name = (ldns_dnssec_name *)cur_node->data; + next_name = (ldns_dnssec_name *)next_node->data; + nsec_rr = ldns_dnssec_create_nsec(cur_name, + next_name, + LDNS_RR_TYPE_NSEC); + ldns_rr_set_ttl(nsec_rr, nsec_ttl); + if(ldns_dnssec_name_add_rr(cur_name, nsec_rr)!=LDNS_STATUS_OK){ + ldns_rr_free(nsec_rr); + return LDNS_STATUS_ERR; + } + ldns_rr_list_push_rr(new_rrs, nsec_rr); + cur_node = next_node; + if (cur_node) { + next_node = ldns_dnssec_name_node_next_nonglue( + ldns_rbtree_next(cur_node)); + } + } + + if (cur_node && !next_node) { + cur_name = (ldns_dnssec_name *)cur_node->data; + next_name = (ldns_dnssec_name *)first_node->data; + nsec_rr = ldns_dnssec_create_nsec(cur_name, + next_name, + LDNS_RR_TYPE_NSEC); + ldns_rr_set_ttl(nsec_rr, nsec_ttl); + if(ldns_dnssec_name_add_rr(cur_name, nsec_rr)!=LDNS_STATUS_OK){ + ldns_rr_free(nsec_rr); + return LDNS_STATUS_ERR; + } + ldns_rr_list_push_rr(new_rrs, nsec_rr); + } else { + printf("error\n"); + } + + return LDNS_STATUS_OK; +} + +#ifdef HAVE_SSL +/* in dnssec_zone.c */ +extern int ldns_dname_compare_v(const void *a, const void *b); + +ldns_status +ldns_dnssec_zone_create_nsec3s_mkmap(ldns_dnssec_zone *zone, + ldns_rr_list *new_rrs, + uint8_t algorithm, + uint8_t flags, + uint16_t iterations, + uint8_t salt_length, + uint8_t *salt, + ldns_rbtree_t **map) +{ + ldns_rbnode_t *first_name_node; + ldns_rbnode_t *current_name_node; + ldns_dnssec_name *current_name; + ldns_status result = LDNS_STATUS_OK; + ldns_rr *nsec_rr; + ldns_rr_list *nsec3_list; + uint32_t nsec_ttl; + ldns_dnssec_rrsets *soa; + ldns_rbnode_t *hashmap_node; + + if (!zone || !new_rrs || !zone->names) { + return LDNS_STATUS_ERR; + } + + /* the TTL of NSEC rrs should be set to the minimum TTL of + * the zone SOA (RFC4035 Section 2.3) + */ + soa = ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_SOA); + + /* did the caller actually set it? if not, + * fall back to default ttl + */ + if (soa && soa->rrs && soa->rrs->rr + && ldns_rr_rdf(soa->rrs->rr, 6) != NULL) { + nsec_ttl = ldns_rdf2native_int32(ldns_rr_rdf(soa->rrs->rr, 6)); + } else { + nsec_ttl = LDNS_DEFAULT_TTL; + } + + if (map) { + if ((*map = ldns_rbtree_create(ldns_dname_compare_v)) + == NULL) { + map = NULL; + }; + } + nsec3_list = ldns_rr_list_new(); + + first_name_node = ldns_dnssec_name_node_next_nonglue( + ldns_rbtree_first(zone->names)); + + current_name_node = first_name_node; + + while (current_name_node && + current_name_node != LDNS_RBTREE_NULL) { + current_name = (ldns_dnssec_name *) current_name_node->data; + nsec_rr = ldns_dnssec_create_nsec3(current_name, + NULL, + zone->soa->name, + algorithm, + flags, + iterations, + salt_length, + salt); + /* by default, our nsec based generator adds rrsigs + * remove the bitmap for empty nonterminals */ + if (!current_name->rrsets) { + ldns_rdf_deep_free(ldns_rr_pop_rdf(nsec_rr)); + } + ldns_rr_set_ttl(nsec_rr, nsec_ttl); + result = ldns_dnssec_name_add_rr(current_name, nsec_rr); + ldns_rr_list_push_rr(new_rrs, nsec_rr); + ldns_rr_list_push_rr(nsec3_list, nsec_rr); + if (map) { + hashmap_node = LDNS_MALLOC(ldns_rbnode_t); + if (hashmap_node && ldns_rr_owner(nsec_rr)) { + hashmap_node->key = ldns_dname_label( + ldns_rr_owner(nsec_rr), 0); + if (hashmap_node->key) { + hashmap_node->data = current_name->name; + (void) ldns_rbtree_insert( + *map, hashmap_node); + } + } + } + current_name_node = ldns_dnssec_name_node_next_nonglue( + ldns_rbtree_next(current_name_node)); + } + if (result != LDNS_STATUS_OK) { + return result; + } + + ldns_rr_list_sort_nsec3(nsec3_list); + result = ldns_dnssec_chain_nsec3_list(nsec3_list); + if (result != LDNS_STATUS_OK) { + return result; + } + + ldns_rr_list_free(nsec3_list); + return result; +} + +ldns_status +ldns_dnssec_zone_create_nsec3s(ldns_dnssec_zone *zone, + ldns_rr_list *new_rrs, + uint8_t algorithm, + uint8_t flags, + uint16_t iterations, + uint8_t salt_length, + uint8_t *salt) +{ + return ldns_dnssec_zone_create_nsec3s_mkmap(zone, new_rrs, algorithm, + flags, iterations, salt_length, salt, NULL); + +} +#endif /* HAVE_SSL */ + +ldns_dnssec_rrs * +ldns_dnssec_remove_signatures( ldns_dnssec_rrs *signatures + , ATTR_UNUSED(ldns_key_list *key_list) + , int (*func)(ldns_rr *, void *) + , void *arg + ) +{ + ldns_dnssec_rrs *base_rrs = signatures; + ldns_dnssec_rrs *cur_rr = base_rrs; + ldns_dnssec_rrs *prev_rr = NULL; + ldns_dnssec_rrs *next_rr; + + uint16_t keytag; + size_t i; + + if (!cur_rr) { + switch(func(NULL, arg)) { + case LDNS_SIGNATURE_LEAVE_ADD_NEW: + case LDNS_SIGNATURE_REMOVE_ADD_NEW: + break; + case LDNS_SIGNATURE_LEAVE_NO_ADD: + case LDNS_SIGNATURE_REMOVE_NO_ADD: + ldns_key_list_set_use(key_list, false); + break; + default: + fprintf(stderr, "[XX] unknown return value from callback\n"); + break; + } + return NULL; + } + (void)func(cur_rr->rr, arg); + + while (cur_rr) { + next_rr = cur_rr->next; + + switch (func(cur_rr->rr, arg)) { + case LDNS_SIGNATURE_LEAVE_ADD_NEW: + prev_rr = cur_rr; + break; + case LDNS_SIGNATURE_LEAVE_NO_ADD: + keytag = ldns_rdf2native_int16( + ldns_rr_rrsig_keytag(cur_rr->rr)); + for (i = 0; i < ldns_key_list_key_count(key_list); i++) { + if (ldns_key_keytag(ldns_key_list_key(key_list, i)) == + keytag) { + ldns_key_set_use(ldns_key_list_key(key_list, i), + false); + } + } + prev_rr = cur_rr; + break; + case LDNS_SIGNATURE_REMOVE_NO_ADD: + keytag = ldns_rdf2native_int16( + ldns_rr_rrsig_keytag(cur_rr->rr)); + for (i = 0; i < ldns_key_list_key_count(key_list); i++) { + if (ldns_key_keytag(ldns_key_list_key(key_list, i)) + == keytag) { + ldns_key_set_use(ldns_key_list_key(key_list, i), + false); + } + } + if (prev_rr) { + prev_rr->next = next_rr; + } else { + base_rrs = next_rr; + } + LDNS_FREE(cur_rr); + break; + case LDNS_SIGNATURE_REMOVE_ADD_NEW: + if (prev_rr) { + prev_rr->next = next_rr; + } else { + base_rrs = next_rr; + } + LDNS_FREE(cur_rr); + break; + default: + fprintf(stderr, "[XX] unknown return value from callback\n"); + break; + } + cur_rr = next_rr; + } + + return base_rrs; +} + +#ifdef HAVE_SSL +ldns_status +ldns_dnssec_zone_create_rrsigs(ldns_dnssec_zone *zone, + ldns_rr_list *new_rrs, + ldns_key_list *key_list, + int (*func)(ldns_rr *, void*), + void *arg) +{ + return ldns_dnssec_zone_create_rrsigs_flg(zone, new_rrs, key_list, + func, arg, 0); +} + +/** If there are KSKs use only them and mark ZSKs unused */ +static void +ldns_key_list_filter_for_dnskey(ldns_key_list *key_list) +{ + int saw_ksk = 0; + size_t i; + for(i=0; inames); + while (cur_node != LDNS_RBTREE_NULL) { + cur_name = (ldns_dnssec_name *) cur_node->data; + + if (!cur_name->is_glue) { + on_delegation_point = ldns_dnssec_rrsets_contains_type( + cur_name->rrsets, LDNS_RR_TYPE_NS) + && !ldns_dnssec_rrsets_contains_type( + cur_name->rrsets, LDNS_RR_TYPE_SOA); + cur_rrset = cur_name->rrsets; + while (cur_rrset) { + /* reset keys to use */ + ldns_key_list_set_use(key_list, true); + + /* walk through old sigs, remove the old, + and mark which keys (not) to use) */ + cur_rrset->signatures = + ldns_dnssec_remove_signatures(cur_rrset->signatures, + key_list, + func, + arg); + if(!(flags&LDNS_SIGN_DNSKEY_WITH_ZSK) && + cur_rrset->type == LDNS_RR_TYPE_DNSKEY) + ldns_key_list_filter_for_dnskey(key_list); + + if(cur_rrset->type != LDNS_RR_TYPE_DNSKEY) + ldns_key_list_filter_for_non_dnskey(key_list); + + /* TODO: just set count to zero? */ + rr_list = ldns_rr_list_new(); + + cur_rr = cur_rrset->rrs; + while (cur_rr) { + ldns_rr_list_push_rr(rr_list, cur_rr->rr); + cur_rr = cur_rr->next; + } + + /* only sign non-delegation RRsets */ + /* (glue should have been marked earlier, + * except on the delegation points itself) */ + if (!on_delegation_point || + ldns_rr_list_type(rr_list) + == LDNS_RR_TYPE_DS || + ldns_rr_list_type(rr_list) + == LDNS_RR_TYPE_NSEC || + ldns_rr_list_type(rr_list) + == LDNS_RR_TYPE_NSEC3) { + siglist = ldns_sign_public(rr_list, key_list); + for (i = 0; i < ldns_rr_list_rr_count(siglist); i++) { + if (cur_rrset->signatures) { + result = ldns_dnssec_rrs_add_rr(cur_rrset->signatures, + ldns_rr_list_rr(siglist, + i)); + } else { + cur_rrset->signatures = ldns_dnssec_rrs_new(); + cur_rrset->signatures->rr = + ldns_rr_list_rr(siglist, i); + ldns_rr_list_push_rr(new_rrs, + ldns_rr_list_rr(siglist, + i)); + } + } + ldns_rr_list_free(siglist); + } + + ldns_rr_list_free(rr_list); + + cur_rrset = cur_rrset->next; + } + + /* sign the nsec */ + ldns_key_list_set_use(key_list, true); + cur_name->nsec_signatures = + ldns_dnssec_remove_signatures(cur_name->nsec_signatures, + key_list, + func, + arg); + ldns_key_list_filter_for_non_dnskey(key_list); + + rr_list = ldns_rr_list_new(); + ldns_rr_list_push_rr(rr_list, cur_name->nsec); + siglist = ldns_sign_public(rr_list, key_list); + + for (i = 0; i < ldns_rr_list_rr_count(siglist); i++) { + if (cur_name->nsec_signatures) { + result = ldns_dnssec_rrs_add_rr(cur_name->nsec_signatures, + ldns_rr_list_rr(siglist, i)); + } else { + cur_name->nsec_signatures = ldns_dnssec_rrs_new(); + cur_name->nsec_signatures->rr = + ldns_rr_list_rr(siglist, i); + ldns_rr_list_push_rr(new_rrs, + ldns_rr_list_rr(siglist, i)); + } + } + + ldns_rr_list_free(siglist); + ldns_rr_list_free(rr_list); + } + cur_node = ldns_rbtree_next(cur_node); + } + + ldns_rr_list_deep_free(pubkey_list); + return result; +} + +ldns_status +ldns_dnssec_zone_sign(ldns_dnssec_zone *zone, + ldns_rr_list *new_rrs, + ldns_key_list *key_list, + int (*func)(ldns_rr *, void *), + void *arg) +{ + return ldns_dnssec_zone_sign_flg(zone, new_rrs, key_list, func, arg, 0); +} + +ldns_status +ldns_dnssec_zone_sign_flg(ldns_dnssec_zone *zone, + ldns_rr_list *new_rrs, + ldns_key_list *key_list, + int (*func)(ldns_rr *, void *), + void *arg, + int flags) +{ + ldns_status result = LDNS_STATUS_OK; + + if (!zone || !new_rrs || !key_list) { + return LDNS_STATUS_ERR; + } + + /* zone is already sorted */ + result = ldns_dnssec_zone_mark_glue(zone); + if (result != LDNS_STATUS_OK) { + return result; + } + + /* check whether we need to add nsecs */ + if (zone->names && !((ldns_dnssec_name *)zone->names->root->data)->nsec) { + result = ldns_dnssec_zone_create_nsecs(zone, new_rrs); + if (result != LDNS_STATUS_OK) { + return result; + } + } + + result = ldns_dnssec_zone_create_rrsigs_flg(zone, + new_rrs, + key_list, + func, + arg, + flags); + + return result; +} + +ldns_status +ldns_dnssec_zone_sign_nsec3(ldns_dnssec_zone *zone, + ldns_rr_list *new_rrs, + ldns_key_list *key_list, + int (*func)(ldns_rr *, void *), + void *arg, + uint8_t algorithm, + uint8_t flags, + uint16_t iterations, + uint8_t salt_length, + uint8_t *salt) +{ + return ldns_dnssec_zone_sign_nsec3_flg_mkmap(zone, new_rrs, key_list, + func, arg, algorithm, flags, iterations, salt_length, salt, 0, + NULL); +} + +ldns_status +ldns_dnssec_zone_sign_nsec3_flg_mkmap(ldns_dnssec_zone *zone, + ldns_rr_list *new_rrs, + ldns_key_list *key_list, + int (*func)(ldns_rr *, void *), + void *arg, + uint8_t algorithm, + uint8_t flags, + uint16_t iterations, + uint8_t salt_length, + uint8_t *salt, + int signflags, + ldns_rbtree_t **map) +{ + ldns_rr *nsec3, *nsec3param; + ldns_status result = LDNS_STATUS_OK; + + /* zone is already sorted */ + result = ldns_dnssec_zone_mark_glue(zone); + if (result != LDNS_STATUS_OK) { + return result; + } + + /* TODO if there are already nsec3s presents and their + * parameters are the same as these, we don't have to recreate + */ + if (zone->names) { + /* add empty nonterminals */ + result = ldns_dnssec_zone_add_empty_nonterminals(zone); + if (result != LDNS_STATUS_OK) { + return result; + } + + nsec3 = ((ldns_dnssec_name *)zone->names->root->data)->nsec; + if (nsec3 && ldns_rr_get_type(nsec3) == LDNS_RR_TYPE_NSEC3) { + /* no need to recreate */ + } else { + if (!ldns_dnssec_zone_find_rrset(zone, + zone->soa->name, + LDNS_RR_TYPE_NSEC3PARAM)) { + /* create and add the nsec3param rr */ + nsec3param = + ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3PARAM); + ldns_rr_set_owner(nsec3param, + ldns_rdf_clone(zone->soa->name)); + ldns_nsec3_add_param_rdfs(nsec3param, + algorithm, + flags, + iterations, + salt_length, + salt); + /* always set bit 7 of the flags to zero, according to + * rfc5155 section 11. The bits are counted from right to left, + * so bit 7 in rfc5155 is bit 0 in ldns */ + ldns_set_bit(ldns_rdf_data(ldns_rr_rdf(nsec3param, 1)), 0, 0); + result = ldns_dnssec_zone_add_rr(zone, nsec3param); + if (result != LDNS_STATUS_OK) { + return result; + } + ldns_rr_list_push_rr(new_rrs, nsec3param); + } + result = ldns_dnssec_zone_create_nsec3s_mkmap(zone, + new_rrs, + algorithm, + flags, + iterations, + salt_length, + salt, + map); + if (result != LDNS_STATUS_OK) { + return result; + } + } + + result = ldns_dnssec_zone_create_rrsigs_flg(zone, + new_rrs, + key_list, + func, + arg, + signflags); + } + + return result; +} + +ldns_status +ldns_dnssec_zone_sign_nsec3_flg(ldns_dnssec_zone *zone, + ldns_rr_list *new_rrs, + ldns_key_list *key_list, + int (*func)(ldns_rr *, void *), + void *arg, + uint8_t algorithm, + uint8_t flags, + uint16_t iterations, + uint8_t salt_length, + uint8_t *salt, + int signflags) +{ + return ldns_dnssec_zone_sign_nsec3_flg_mkmap(zone, new_rrs, key_list, + func, arg, algorithm, flags, iterations, salt_length, salt, + signflags, NULL); +} + +ldns_zone * +ldns_zone_sign(const ldns_zone *zone, ldns_key_list *key_list) +{ + ldns_dnssec_zone *dnssec_zone; + ldns_zone *signed_zone; + ldns_rr_list *new_rrs; + size_t i; + + signed_zone = ldns_zone_new(); + dnssec_zone = ldns_dnssec_zone_new(); + + (void) ldns_dnssec_zone_add_rr(dnssec_zone, ldns_zone_soa(zone)); + ldns_zone_set_soa(signed_zone, ldns_rr_clone(ldns_zone_soa(zone))); + + for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) { + (void) ldns_dnssec_zone_add_rr(dnssec_zone, + ldns_rr_list_rr(ldns_zone_rrs(zone), + i)); + ldns_zone_push_rr(signed_zone, + ldns_rr_clone(ldns_rr_list_rr(ldns_zone_rrs(zone), + i))); + } + + new_rrs = ldns_rr_list_new(); + (void) ldns_dnssec_zone_sign(dnssec_zone, + new_rrs, + key_list, + ldns_dnssec_default_replace_signatures, + NULL); + + for (i = 0; i < ldns_rr_list_rr_count(new_rrs); i++) { + ldns_rr_list_push_rr(ldns_zone_rrs(signed_zone), + ldns_rr_clone(ldns_rr_list_rr(new_rrs, i))); + } + + ldns_rr_list_deep_free(new_rrs); + ldns_dnssec_zone_free(dnssec_zone); + + return signed_zone; +} + +ldns_zone * +ldns_zone_sign_nsec3(ldns_zone *zone, ldns_key_list *key_list, uint8_t algorithm, uint8_t flags, uint16_t iterations, uint8_t salt_length, uint8_t *salt) +{ + ldns_dnssec_zone *dnssec_zone; + ldns_zone *signed_zone; + ldns_rr_list *new_rrs; + size_t i; + + signed_zone = ldns_zone_new(); + dnssec_zone = ldns_dnssec_zone_new(); + + (void) ldns_dnssec_zone_add_rr(dnssec_zone, ldns_zone_soa(zone)); + ldns_zone_set_soa(signed_zone, ldns_rr_clone(ldns_zone_soa(zone))); + + for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) { + (void) ldns_dnssec_zone_add_rr(dnssec_zone, + ldns_rr_list_rr(ldns_zone_rrs(zone), + i)); + ldns_zone_push_rr(signed_zone, + ldns_rr_clone(ldns_rr_list_rr(ldns_zone_rrs(zone), + i))); + } + + new_rrs = ldns_rr_list_new(); + (void) ldns_dnssec_zone_sign_nsec3(dnssec_zone, + new_rrs, + key_list, + ldns_dnssec_default_replace_signatures, + NULL, + algorithm, + flags, + iterations, + salt_length, + salt); + + for (i = 0; i < ldns_rr_list_rr_count(new_rrs); i++) { + ldns_rr_list_push_rr(ldns_zone_rrs(signed_zone), + ldns_rr_clone(ldns_rr_list_rr(new_rrs, i))); + } + + ldns_rr_list_deep_free(new_rrs); + ldns_dnssec_zone_free(dnssec_zone); + + return signed_zone; +} +#endif /* HAVE_SSL */ + + diff --git a/dnssec_verify.c b/dnssec_verify.c new file mode 100644 index 00000000000..68c70c5e848 --- /dev/null +++ b/dnssec_verify.c @@ -0,0 +1,2699 @@ +#include + +#include + +#include +#include + +#ifdef HAVE_SSL +/* this entire file is rather useless when you don't have + * crypto... + */ +#include +#include +#include +#include +#include + +ldns_dnssec_data_chain * +ldns_dnssec_data_chain_new() +{ + ldns_dnssec_data_chain *nc = LDNS_CALLOC(ldns_dnssec_data_chain, 1); + if(!nc) return NULL; + /* + * not needed anymore because CALLOC initalizes everything to zero. + + nc->rrset = NULL; + nc->parent_type = 0; + nc->parent = NULL; + nc->signatures = NULL; + nc->packet_rcode = 0; + nc->packet_qtype = 0; + nc->packet_nodata = false; + + */ + return nc; +} + +void +ldns_dnssec_data_chain_free(ldns_dnssec_data_chain *chain) +{ + LDNS_FREE(chain); +} + +void +ldns_dnssec_data_chain_deep_free(ldns_dnssec_data_chain *chain) +{ + ldns_rr_list_deep_free(chain->rrset); + ldns_rr_list_deep_free(chain->signatures); + if (chain->parent) { + ldns_dnssec_data_chain_deep_free(chain->parent); + } + LDNS_FREE(chain); +} + +void +ldns_dnssec_data_chain_print_fmt(FILE *out, const ldns_output_format *fmt, + const ldns_dnssec_data_chain *chain) +{ + ldns_lookup_table *rcode; + const ldns_rr_descriptor *rr_descriptor; + if (chain) { + ldns_dnssec_data_chain_print_fmt(out, fmt, chain->parent); + if (ldns_rr_list_rr_count(chain->rrset) > 0) { + rcode = ldns_lookup_by_id(ldns_rcodes, + (int) chain->packet_rcode); + if (rcode) { + fprintf(out, ";; rcode: %s\n", rcode->name); + } + + rr_descriptor = ldns_rr_descript(chain->packet_qtype); + if (rr_descriptor && rr_descriptor->_name) { + fprintf(out, ";; qtype: %s\n", rr_descriptor->_name); + } else if (chain->packet_qtype != 0) { + fprintf(out, "TYPE%u", + chain->packet_qtype); + } + if (chain->packet_nodata) { + fprintf(out, ";; NODATA response\n"); + } + fprintf(out, "rrset:\n"); + ldns_rr_list_print_fmt(out, fmt, chain->rrset); + fprintf(out, "sigs:\n"); + ldns_rr_list_print_fmt(out, fmt, chain->signatures); + fprintf(out, "---\n"); + } else { + fprintf(out, "\n"); + } + } +} +void +ldns_dnssec_data_chain_print(FILE *out, const ldns_dnssec_data_chain *chain) +{ + ldns_dnssec_data_chain_print_fmt( + out, ldns_output_format_default, chain); +} + + +static void +ldns_dnssec_build_data_chain_dnskey(ldns_resolver *res, + uint16_t qflags, + const ldns_pkt *pkt, + ldns_rr_list *signatures, + ldns_dnssec_data_chain *new_chain, + ldns_rdf *key_name, + ldns_rr_class c) { + ldns_rr_list *keys; + ldns_pkt *my_pkt; + if (signatures && ldns_rr_list_rr_count(signatures) > 0) { + new_chain->signatures = ldns_rr_list_clone(signatures); + new_chain->parent_type = 0; + + keys = ldns_pkt_rr_list_by_name_and_type( + pkt, + key_name, + LDNS_RR_TYPE_DNSKEY, + LDNS_SECTION_ANY_NOQUESTION + ); + if (!keys) { + my_pkt = ldns_resolver_query(res, + key_name, + LDNS_RR_TYPE_DNSKEY, + c, + qflags); + if (my_pkt) { + keys = ldns_pkt_rr_list_by_name_and_type( + my_pkt, + key_name, + LDNS_RR_TYPE_DNSKEY, + LDNS_SECTION_ANY_NOQUESTION + ); + new_chain->parent = ldns_dnssec_build_data_chain(res, + qflags, + keys, + my_pkt, + NULL); + new_chain->parent->packet_qtype = LDNS_RR_TYPE_DNSKEY; + ldns_pkt_free(my_pkt); + } + } else { + new_chain->parent = ldns_dnssec_build_data_chain(res, + qflags, + keys, + pkt, + NULL); + new_chain->parent->packet_qtype = LDNS_RR_TYPE_DNSKEY; + } + ldns_rr_list_deep_free(keys); + } +} + +static void +ldns_dnssec_build_data_chain_other(ldns_resolver *res, + uint16_t qflags, + ldns_dnssec_data_chain *new_chain, + ldns_rdf *key_name, + ldns_rr_class c, + ldns_rr_list *dss) +{ + /* 'self-signed', parent is a DS */ + + /* okay, either we have other keys signing the current one, + * or the current + * one should have a DS record in the parent zone. + * How do we find this out? Try both? + * + * request DNSKEYS for current zone, + * add all signatures to current level + */ + ldns_pkt *my_pkt; + ldns_rr_list *signatures2; + + new_chain->parent_type = 1; + + my_pkt = ldns_resolver_query(res, + key_name, + LDNS_RR_TYPE_DS, + c, + qflags); + if (my_pkt) { + dss = ldns_pkt_rr_list_by_name_and_type(my_pkt, + key_name, + LDNS_RR_TYPE_DS, + LDNS_SECTION_ANY_NOQUESTION + ); + if (dss) { + new_chain->parent = ldns_dnssec_build_data_chain(res, + qflags, + dss, + my_pkt, + NULL); + new_chain->parent->packet_qtype = LDNS_RR_TYPE_DS; + ldns_rr_list_deep_free(dss); + } + ldns_pkt_free(my_pkt); + } + + my_pkt = ldns_resolver_query(res, + key_name, + LDNS_RR_TYPE_DNSKEY, + c, + qflags); + if (my_pkt) { + signatures2 = ldns_pkt_rr_list_by_name_and_type(my_pkt, + key_name, + LDNS_RR_TYPE_RRSIG, + LDNS_SECTION_ANSWER); + if (signatures2) { + if (new_chain->signatures) { + printf("There were already sigs!\n"); + ldns_rr_list_deep_free(new_chain->signatures); + printf("replacing the old sigs\n"); + } + new_chain->signatures = signatures2; + } + ldns_pkt_free(my_pkt); + } +} + +ldns_dnssec_data_chain * +ldns_dnssec_build_data_chain_nokeyname(ldns_resolver *res, + uint16_t qflags, + ldns_rr *orig_rr, + const ldns_rr_list *rrset, + ldns_dnssec_data_chain *new_chain) +{ + ldns_rdf *possible_parent_name; + ldns_pkt *my_pkt; + /* apparently we were not able to find a signing key, so + we assume the chain ends here + */ + /* try parents for auth denial of DS */ + if (orig_rr) { + possible_parent_name = ldns_rr_owner(orig_rr); + } else if (rrset && ldns_rr_list_rr_count(rrset) > 0) { + possible_parent_name = ldns_rr_owner(ldns_rr_list_rr(rrset, 0)); + } else { + /* no information to go on, give up */ + return new_chain; + } + + my_pkt = ldns_resolver_query(res, + possible_parent_name, + LDNS_RR_TYPE_DS, + LDNS_RR_CLASS_IN, + qflags); + if (!my_pkt) { + return new_chain; + } + + if (ldns_pkt_ancount(my_pkt) > 0) { + /* add error, no sigs but DS in parent */ + /*ldns_pkt_print(stdout, my_pkt);*/ + ldns_pkt_free(my_pkt); + } else { + /* are there signatures? */ + new_chain->parent = ldns_dnssec_build_data_chain(res, + qflags, + NULL, + my_pkt, + NULL); + + new_chain->parent->packet_qtype = LDNS_RR_TYPE_DS; + + } + return new_chain; +} + + +ldns_dnssec_data_chain * +ldns_dnssec_build_data_chain(ldns_resolver *res, + uint16_t qflags, + const ldns_rr_list *rrset, + const ldns_pkt *pkt, + ldns_rr *orig_rr) +{ + ldns_rr_list *signatures = NULL; + ldns_rr_list *dss = NULL; + + ldns_rr_list *my_rrset; + + ldns_pkt *my_pkt; + + ldns_rdf *name = NULL, *key_name = NULL; + ldns_rr_type type = 0; + ldns_rr_class c = 0; + + bool other_rrset = false; + + ldns_dnssec_data_chain *new_chain = ldns_dnssec_data_chain_new(); + + if (!ldns_dnssec_pkt_has_rrsigs(pkt)) { + /* hmm. no dnssec data in the packet. go up to try and deny + * DS? */ + return new_chain; + } + + if (orig_rr) { + new_chain->rrset = ldns_rr_list_new(); + ldns_rr_list_push_rr(new_chain->rrset, orig_rr); + new_chain->parent = ldns_dnssec_build_data_chain(res, + qflags, + rrset, + pkt, + NULL); + new_chain->packet_rcode = ldns_pkt_get_rcode(pkt); + new_chain->packet_qtype = ldns_rr_get_type(orig_rr); + if (ldns_pkt_ancount(pkt) == 0) { + new_chain->packet_nodata = true; + } + return new_chain; + } + + if (!rrset || ldns_rr_list_rr_count(rrset) < 1) { + /* hmm, no data, do we have denial? only works if pkt was given, + otherwise caller has to do the check himself */ + new_chain->packet_nodata = true; + if (pkt) { + my_rrset = ldns_pkt_rr_list_by_type(pkt, + LDNS_RR_TYPE_NSEC, + LDNS_SECTION_ANY_NOQUESTION + ); + if (my_rrset) { + if (ldns_rr_list_rr_count(my_rrset) > 0) { + type = LDNS_RR_TYPE_NSEC; + other_rrset = true; + } else { + ldns_rr_list_deep_free(my_rrset); + my_rrset = NULL; + } + } else { + /* nothing, try nsec3 */ + my_rrset = ldns_pkt_rr_list_by_type(pkt, + LDNS_RR_TYPE_NSEC3, + LDNS_SECTION_ANY_NOQUESTION); + if (my_rrset) { + if (ldns_rr_list_rr_count(my_rrset) > 0) { + type = LDNS_RR_TYPE_NSEC3; + other_rrset = true; + } else { + ldns_rr_list_deep_free(my_rrset); + my_rrset = NULL; + } + } else { + /* nothing, stop */ + /* try parent zone? for denied insecure? */ + return new_chain; + } + } + } else { + return new_chain; + } + } else { + my_rrset = (ldns_rr_list *) rrset; + } + + if (my_rrset && ldns_rr_list_rr_count(my_rrset) > 0) { + new_chain->rrset = ldns_rr_list_clone(my_rrset); + name = ldns_rr_owner(ldns_rr_list_rr(my_rrset, 0)); + type = ldns_rr_get_type(ldns_rr_list_rr(my_rrset, 0)); + c = ldns_rr_get_class(ldns_rr_list_rr(my_rrset, 0)); + } + + if (other_rrset) { + ldns_rr_list_deep_free(my_rrset); + } + + /* normally there will only be 1 signature 'set' + but there can be more than 1 denial (wildcards) + so check for NSEC + */ + if (type == LDNS_RR_TYPE_NSEC || type == LDNS_RR_TYPE_NSEC3) { + /* just throw in all signatures, the tree builder must sort + this out */ + if (pkt) { + signatures = ldns_dnssec_pkt_get_rrsigs_for_type(pkt, type); + } else { + my_pkt = ldns_resolver_query(res, name, type, c, qflags); + if (my_pkt) { + signatures = ldns_dnssec_pkt_get_rrsigs_for_type(pkt, type); + ldns_pkt_free(my_pkt); + } + } + } else { + if (pkt) { + signatures = + ldns_dnssec_pkt_get_rrsigs_for_name_and_type(pkt, + name, + type); + } + if (!signatures) { + my_pkt = ldns_resolver_query(res, name, type, c, qflags); + if (my_pkt) { + signatures = + ldns_dnssec_pkt_get_rrsigs_for_name_and_type(my_pkt, + name, + type); + ldns_pkt_free(my_pkt); + } + } + } + + if (signatures && ldns_rr_list_rr_count(signatures) > 0) { + key_name = ldns_rr_rdf(ldns_rr_list_rr(signatures, 0), 7); + } + + if (!key_name) { + return ldns_dnssec_build_data_chain_nokeyname(res, + qflags, + orig_rr, + rrset, + new_chain); + } + + if (type != LDNS_RR_TYPE_DNSKEY) { + ldns_dnssec_build_data_chain_dnskey(res, + qflags, + pkt, + signatures, + new_chain, + key_name, + c + ); + } else { + ldns_dnssec_build_data_chain_other(res, + qflags, + new_chain, + key_name, + c, + dss + + ); + } + if (signatures) { + ldns_rr_list_deep_free(signatures); + } + + return new_chain; +} + +ldns_dnssec_trust_tree * +ldns_dnssec_trust_tree_new() +{ + ldns_dnssec_trust_tree *new_tree = LDNS_XMALLOC(ldns_dnssec_trust_tree, + 1); + if(!new_tree) return NULL; + new_tree->rr = NULL; + new_tree->rrset = NULL; + new_tree->parent_count = 0; + + return new_tree; +} + +void +ldns_dnssec_trust_tree_free(ldns_dnssec_trust_tree *tree) +{ + size_t i; + if (tree) { + for (i = 0; i < tree->parent_count; i++) { + ldns_dnssec_trust_tree_free(tree->parents[i]); + } + } + LDNS_FREE(tree); +} + +size_t +ldns_dnssec_trust_tree_depth(ldns_dnssec_trust_tree *tree) +{ + size_t result = 0; + size_t parent = 0; + size_t i; + + for (i = 0; i < tree->parent_count; i++) { + parent = ldns_dnssec_trust_tree_depth(tree->parents[i]); + if (parent > result) { + result = parent; + } + } + return 1 + result; +} + +/* TODO ldns_ */ +static void +print_tabs(FILE *out, size_t nr, uint8_t *map, size_t treedepth) +{ + size_t i; + for (i = 0; i < nr; i++) { + if (i == nr - 1) { + fprintf(out, "|---"); + } else if (map && i < treedepth && map[i] == 1) { + fprintf(out, "| "); + } else { + fprintf(out, " "); + } + } +} + +void +ldns_dnssec_trust_tree_print_sm_fmt(FILE *out, + const ldns_output_format *fmt, + ldns_dnssec_trust_tree *tree, + size_t tabs, + bool extended, + uint8_t *sibmap, + size_t treedepth) +{ + size_t i; + const ldns_rr_descriptor *descriptor; + bool mapset = false; + + if (!sibmap) { + treedepth = ldns_dnssec_trust_tree_depth(tree); + sibmap = LDNS_XMALLOC(uint8_t, treedepth); + if(!sibmap) + return; /* mem err */ + memset(sibmap, 0, treedepth); + mapset = true; + } + + if (tree) { + if (tree->rr) { + print_tabs(out, tabs, sibmap, treedepth); + ldns_rdf_print(out, ldns_rr_owner(tree->rr)); + descriptor = ldns_rr_descript(ldns_rr_get_type(tree->rr)); + + if (descriptor->_name) { + fprintf(out, " (%s", descriptor->_name); + } else { + fprintf(out, " (TYPE%d", + ldns_rr_get_type(tree->rr)); + } + if (tabs > 0) { + if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_DNSKEY) { + fprintf(out, " keytag: %u", + (unsigned int) ldns_calc_keytag(tree->rr)); + fprintf(out, " alg: "); + ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 2)); + fprintf(out, " flags: "); + ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 0)); + } else if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_DS) { + fprintf(out, " keytag: "); + ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 0)); + fprintf(out, " digest type: "); + ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 2)); + } + if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NSEC) { + fprintf(out, " "); + ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 0)); + fprintf(out, " "); + ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 1)); + } + } + + fprintf(out, ")\n"); + for (i = 0; i < tree->parent_count; i++) { + if (tree->parent_count > 1 && i < tree->parent_count - 1) { + sibmap[tabs] = 1; + } else { + sibmap[tabs] = 0; + } + /* only print errors */ + if (ldns_rr_get_type(tree->parents[i]->rr) == + LDNS_RR_TYPE_NSEC || + ldns_rr_get_type(tree->parents[i]->rr) == + LDNS_RR_TYPE_NSEC3) { + if (tree->parent_status[i] == LDNS_STATUS_OK) { + print_tabs(out, tabs + 1, sibmap, treedepth); + if (tabs == 0 && + ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NS && + ldns_rr_rd_count(tree->rr) > 0) { + fprintf(out, "Existence of DS is denied by:\n"); + } else { + fprintf(out, "Existence is denied by:\n"); + } + } else { + /* NS records aren't signed */ + if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NS) { + fprintf(out, "Existence of DS is denied by:\n"); + } else { + print_tabs(out, tabs + 1, sibmap, treedepth); + fprintf(out, + "Error in denial of existence: %s\n", + ldns_get_errorstr_by_id( + tree->parent_status[i])); + } + } + } else + if (tree->parent_status[i] != LDNS_STATUS_OK) { + print_tabs(out, tabs + 1, sibmap, treedepth); + fprintf(out, + "%s:\n", + ldns_get_errorstr_by_id( + tree->parent_status[i])); + if (tree->parent_status[i] + == LDNS_STATUS_SSL_ERR) { + printf("; SSL Error: "); + ERR_load_crypto_strings(); + ERR_print_errors_fp(stdout); + printf("\n"); + } + ldns_rr_print_fmt(out, fmt, + tree-> + parent_signature[i]); + printf("For RRset:\n"); + ldns_rr_list_print_fmt(out, fmt, + tree->rrset); + printf("With key:\n"); + ldns_rr_print_fmt(out, fmt, + tree->parents[i]->rr); + } + ldns_dnssec_trust_tree_print_sm_fmt(out, fmt, + tree->parents[i], + tabs+1, + extended, + sibmap, + treedepth); + } + } else { + print_tabs(out, tabs, sibmap, treedepth); + fprintf(out, "\n"); + } + } else { + fprintf(out, "\n"); + } + + if (mapset) { + LDNS_FREE(sibmap); + } +} + +void +ldns_dnssec_trust_tree_print_sm(FILE *out, + ldns_dnssec_trust_tree *tree, + size_t tabs, + bool extended, + uint8_t *sibmap, + size_t treedepth) +{ + ldns_dnssec_trust_tree_print_sm_fmt(out, ldns_output_format_default, + tree, tabs, extended, sibmap, treedepth); +} + +void +ldns_dnssec_trust_tree_print_fmt(FILE *out, const ldns_output_format *fmt, + ldns_dnssec_trust_tree *tree, + size_t tabs, + bool extended) +{ + ldns_dnssec_trust_tree_print_sm_fmt(out, fmt, + tree, tabs, extended, NULL, 0); +} + +void +ldns_dnssec_trust_tree_print(FILE *out, + ldns_dnssec_trust_tree *tree, + size_t tabs, + bool extended) +{ + ldns_dnssec_trust_tree_print_fmt(out, ldns_output_format_default, + tree, tabs, extended); +} + + +ldns_status +ldns_dnssec_trust_tree_add_parent(ldns_dnssec_trust_tree *tree, + const ldns_dnssec_trust_tree *parent, + const ldns_rr *signature, + const ldns_status parent_status) +{ + if (tree + && parent + && tree->parent_count < LDNS_DNSSEC_TRUST_TREE_MAX_PARENTS) { + /* + printf("Add parent for: "); + ldns_rr_print(stdout, tree->rr); + printf("parent: "); + ldns_rr_print(stdout, parent->rr); + */ + tree->parents[tree->parent_count] = + (ldns_dnssec_trust_tree *) parent; + tree->parent_status[tree->parent_count] = parent_status; + tree->parent_signature[tree->parent_count] = (ldns_rr *) signature; + tree->parent_count++; + return LDNS_STATUS_OK; + } else { + return LDNS_STATUS_ERR; + } +} + +/* if rr is null, take the first from the rrset */ +ldns_dnssec_trust_tree * +ldns_dnssec_derive_trust_tree_time( + ldns_dnssec_data_chain *data_chain, + ldns_rr *rr, + time_t check_time + ) +{ + ldns_rr_list *cur_rrset; + ldns_rr_list *cur_sigs; + ldns_rr *cur_rr = NULL; + ldns_rr *cur_sig_rr; + size_t i, j; + + ldns_dnssec_trust_tree *new_tree = ldns_dnssec_trust_tree_new(); + if(!new_tree) + return NULL; + + if (data_chain && data_chain->rrset) { + cur_rrset = data_chain->rrset; + + cur_sigs = data_chain->signatures; + + if (rr) { + cur_rr = rr; + } + + if (!cur_rr && ldns_rr_list_rr_count(cur_rrset) > 0) { + cur_rr = ldns_rr_list_rr(cur_rrset, 0); + } + + if (cur_rr) { + new_tree->rr = cur_rr; + new_tree->rrset = cur_rrset; + /* there are three possibilities: + 1 - 'normal' rrset, signed by a key + 2 - dnskey signed by other dnskey + 3 - dnskey proven by higher level DS + (data denied by nsec is a special case that can + occur in multiple places) + + */ + if (cur_sigs) { + for (i = 0; i < ldns_rr_list_rr_count(cur_sigs); i++) { + /* find the appropriate key in the parent list */ + cur_sig_rr = ldns_rr_list_rr(cur_sigs, i); + + if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_NSEC) { + if (ldns_dname_compare(ldns_rr_owner(cur_sig_rr), + ldns_rr_owner(cur_rr))) + { + /* find first that does match */ + + for (j = 0; + j < ldns_rr_list_rr_count(cur_rrset) && + ldns_dname_compare(ldns_rr_owner(cur_sig_rr),ldns_rr_owner(cur_rr)) != 0; + j++) { + cur_rr = ldns_rr_list_rr(cur_rrset, j); + + } + if (ldns_dname_compare(ldns_rr_owner(cur_sig_rr), + ldns_rr_owner(cur_rr))) + { + break; + } + } + + } + /* option 1 */ + if (data_chain->parent) { + ldns_dnssec_derive_trust_tree_normal_rrset_time( + new_tree, + data_chain, + cur_sig_rr, + check_time); + } + + /* option 2 */ + ldns_dnssec_derive_trust_tree_dnskey_rrset_time( + new_tree, + data_chain, + cur_rr, + cur_sig_rr, + check_time); + } + + ldns_dnssec_derive_trust_tree_ds_rrset_time( + new_tree, data_chain, + cur_rr, check_time); + } else { + /* no signatures? maybe it's nsec data */ + + /* just add every rr from parent as new parent */ + ldns_dnssec_derive_trust_tree_no_sig_time( + new_tree, data_chain, check_time); + } + } + } + + return new_tree; +} + +ldns_dnssec_trust_tree * +ldns_dnssec_derive_trust_tree(ldns_dnssec_data_chain *data_chain, ldns_rr *rr) +{ + return ldns_dnssec_derive_trust_tree_time(data_chain, rr, ldns_time(NULL)); +} + +void +ldns_dnssec_derive_trust_tree_normal_rrset_time( + ldns_dnssec_trust_tree *new_tree, + ldns_dnssec_data_chain *data_chain, + ldns_rr *cur_sig_rr, + time_t check_time) +{ + size_t i, j; + ldns_rr_list *cur_rrset = ldns_rr_list_clone(data_chain->rrset); + ldns_dnssec_trust_tree *cur_parent_tree; + ldns_rr *cur_parent_rr; + uint16_t cur_keytag; + ldns_rr_list *tmp_rrset = NULL; + ldns_status cur_status; + + cur_keytag = ldns_rdf2native_int16(ldns_rr_rrsig_keytag(cur_sig_rr)); + + for (j = 0; j < ldns_rr_list_rr_count(data_chain->parent->rrset); j++) { + cur_parent_rr = ldns_rr_list_rr(data_chain->parent->rrset, j); + if (ldns_rr_get_type(cur_parent_rr) == LDNS_RR_TYPE_DNSKEY) { + if (ldns_calc_keytag(cur_parent_rr) == cur_keytag) { + + /* TODO: check wildcard nsec too */ + if (cur_rrset && ldns_rr_list_rr_count(cur_rrset) > 0) { + tmp_rrset = cur_rrset; + if (ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0)) + == LDNS_RR_TYPE_NSEC || + ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0)) + == LDNS_RR_TYPE_NSEC3) { + /* might contain different names! + sort and split */ + ldns_rr_list_sort(cur_rrset); + if (tmp_rrset && tmp_rrset != cur_rrset) { + ldns_rr_list_deep_free(tmp_rrset); + tmp_rrset = NULL; + } + tmp_rrset = ldns_rr_list_pop_rrset(cur_rrset); + + /* with nsecs, this might be the wrong one */ + while (tmp_rrset && + ldns_rr_list_rr_count(cur_rrset) > 0 && + ldns_dname_compare( + ldns_rr_owner(ldns_rr_list_rr( + tmp_rrset, 0)), + ldns_rr_owner(cur_sig_rr)) != 0) { + ldns_rr_list_deep_free(tmp_rrset); + tmp_rrset = + ldns_rr_list_pop_rrset(cur_rrset); + } + } + cur_status = ldns_verify_rrsig_time( + tmp_rrset, + cur_sig_rr, + cur_parent_rr, + check_time); + /* avoid dupes */ + for (i = 0; i < new_tree->parent_count; i++) { + if (cur_parent_rr == new_tree->parents[i]->rr) { + goto done; + } + } + + cur_parent_tree = + ldns_dnssec_derive_trust_tree_time( + data_chain->parent, + cur_parent_rr, + check_time); + (void)ldns_dnssec_trust_tree_add_parent(new_tree, + cur_parent_tree, + cur_sig_rr, + cur_status); + } + } + } + } + done: + if (tmp_rrset && tmp_rrset != cur_rrset) { + ldns_rr_list_deep_free(tmp_rrset); + } + ldns_rr_list_deep_free(cur_rrset); +} + +void +ldns_dnssec_derive_trust_tree_normal_rrset(ldns_dnssec_trust_tree *new_tree, + ldns_dnssec_data_chain *data_chain, + ldns_rr *cur_sig_rr) +{ + ldns_dnssec_derive_trust_tree_normal_rrset_time( + new_tree, data_chain, cur_sig_rr, ldns_time(NULL)); +} + +void +ldns_dnssec_derive_trust_tree_dnskey_rrset_time( + ldns_dnssec_trust_tree *new_tree, + ldns_dnssec_data_chain *data_chain, + ldns_rr *cur_rr, + ldns_rr *cur_sig_rr, + time_t check_time) +{ + size_t j; + ldns_rr_list *cur_rrset = data_chain->rrset; + ldns_dnssec_trust_tree *cur_parent_tree; + ldns_rr *cur_parent_rr; + uint16_t cur_keytag; + ldns_status cur_status; + + cur_keytag = ldns_rdf2native_int16(ldns_rr_rrsig_keytag(cur_sig_rr)); + + for (j = 0; j < ldns_rr_list_rr_count(cur_rrset); j++) { + cur_parent_rr = ldns_rr_list_rr(cur_rrset, j); + if (cur_parent_rr != cur_rr && + ldns_rr_get_type(cur_parent_rr) == LDNS_RR_TYPE_DNSKEY) { + if (ldns_calc_keytag(cur_parent_rr) == cur_keytag + ) { + cur_parent_tree = ldns_dnssec_trust_tree_new(); + cur_parent_tree->rr = cur_parent_rr; + cur_parent_tree->rrset = cur_rrset; + cur_status = ldns_verify_rrsig_time( + cur_rrset, cur_sig_rr, + cur_parent_rr, check_time); + (void) ldns_dnssec_trust_tree_add_parent(new_tree, + cur_parent_tree, cur_sig_rr, cur_status); + } + } + } +} + +void +ldns_dnssec_derive_trust_tree_dnskey_rrset(ldns_dnssec_trust_tree *new_tree, + ldns_dnssec_data_chain *data_chain, + ldns_rr *cur_rr, + ldns_rr *cur_sig_rr) +{ + ldns_dnssec_derive_trust_tree_dnskey_rrset_time( + new_tree, data_chain, cur_rr, cur_sig_rr, ldns_time(NULL)); +} + +void +ldns_dnssec_derive_trust_tree_ds_rrset_time( + ldns_dnssec_trust_tree *new_tree, + ldns_dnssec_data_chain *data_chain, + ldns_rr *cur_rr, + time_t check_time) +{ + size_t j, h; + ldns_rr_list *cur_rrset = data_chain->rrset; + ldns_dnssec_trust_tree *cur_parent_tree; + ldns_rr *cur_parent_rr; + + /* try the parent to see whether there are DSs there */ + if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_DNSKEY && + data_chain->parent && + data_chain->parent->rrset + ) { + for (j = 0; + j < ldns_rr_list_rr_count(data_chain->parent->rrset); + j++) { + cur_parent_rr = ldns_rr_list_rr(data_chain->parent->rrset, j); + if (ldns_rr_get_type(cur_parent_rr) == LDNS_RR_TYPE_DS) { + for (h = 0; h < ldns_rr_list_rr_count(cur_rrset); h++) { + cur_rr = ldns_rr_list_rr(cur_rrset, h); + if (ldns_rr_compare_ds(cur_rr, cur_parent_rr)) { + cur_parent_tree = + ldns_dnssec_derive_trust_tree_time( + data_chain->parent, + cur_parent_rr, + check_time); + (void) ldns_dnssec_trust_tree_add_parent( + new_tree, + cur_parent_tree, + NULL, + LDNS_STATUS_OK); + } else { + /*ldns_rr_print(stdout, cur_parent_rr);*/ + } + } + } + } + } +} + +void +ldns_dnssec_derive_trust_tree_ds_rrset(ldns_dnssec_trust_tree *new_tree, + ldns_dnssec_data_chain *data_chain, + ldns_rr *cur_rr) +{ + ldns_dnssec_derive_trust_tree_ds_rrset_time( + new_tree, data_chain, cur_rr, ldns_time(NULL)); +} + +void +ldns_dnssec_derive_trust_tree_no_sig_time( + ldns_dnssec_trust_tree *new_tree, + ldns_dnssec_data_chain *data_chain, + time_t check_time) +{ + size_t i; + ldns_rr_list *cur_rrset; + ldns_rr *cur_parent_rr; + ldns_dnssec_trust_tree *cur_parent_tree; + ldns_status result; + + if (data_chain->parent && data_chain->parent->rrset) { + cur_rrset = data_chain->parent->rrset; + /* nsec? */ + if (cur_rrset && ldns_rr_list_rr_count(cur_rrset) > 0) { + if (ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0)) == + LDNS_RR_TYPE_NSEC3) { + result = ldns_dnssec_verify_denial_nsec3( + new_tree->rr, + cur_rrset, + data_chain->parent->signatures, + data_chain->packet_rcode, + data_chain->packet_qtype, + data_chain->packet_nodata); + } else if (ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0)) == + LDNS_RR_TYPE_NSEC) { + result = ldns_dnssec_verify_denial( + new_tree->rr, + cur_rrset, + data_chain->parent->signatures); + } else { + /* unsigned zone, unsigned parent */ + result = LDNS_STATUS_OK; + } + } else { + result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; + } + for (i = 0; i < ldns_rr_list_rr_count(cur_rrset); i++) { + cur_parent_rr = ldns_rr_list_rr(cur_rrset, i); + cur_parent_tree = + ldns_dnssec_derive_trust_tree_time( + data_chain->parent, + cur_parent_rr, + check_time); + (void) ldns_dnssec_trust_tree_add_parent(new_tree, + cur_parent_tree, NULL, result); + } + } +} + +void +ldns_dnssec_derive_trust_tree_no_sig(ldns_dnssec_trust_tree *new_tree, + ldns_dnssec_data_chain *data_chain) +{ + ldns_dnssec_derive_trust_tree_no_sig_time( + new_tree, data_chain, ldns_time(NULL)); +} + +/* + * returns OK if there is a path from tree to key with only OK + * the (first) error in between otherwise + * or NOT_FOUND if the key wasn't present at all + */ +ldns_status +ldns_dnssec_trust_tree_contains_keys(ldns_dnssec_trust_tree *tree, + ldns_rr_list *trusted_keys) +{ + size_t i; + ldns_status result = LDNS_STATUS_CRYPTO_NO_DNSKEY; + bool equal; + ldns_status parent_result; + + if (tree && trusted_keys && ldns_rr_list_rr_count(trusted_keys) > 0) + { if (tree->rr) { + for (i = 0; i < ldns_rr_list_rr_count(trusted_keys); i++) { + equal = ldns_rr_compare_ds( + tree->rr, + ldns_rr_list_rr(trusted_keys, i)); + if (equal) { + result = LDNS_STATUS_OK; + return result; + } + } + } + for (i = 0; i < tree->parent_count; i++) { + parent_result = + ldns_dnssec_trust_tree_contains_keys(tree->parents[i], + trusted_keys); + if (parent_result != LDNS_STATUS_CRYPTO_NO_DNSKEY) { + if (tree->parent_status[i] != LDNS_STATUS_OK) { + result = tree->parent_status[i]; + } else { + if (ldns_rr_get_type(tree->rr) + == LDNS_RR_TYPE_NSEC && + parent_result == LDNS_STATUS_OK + ) { + result = + LDNS_STATUS_DNSSEC_EXISTENCE_DENIED; + } else { + result = parent_result; + } + } + } + } + } else { + result = LDNS_STATUS_ERR; + } + + return result; +} + +ldns_status +ldns_verify_time( + ldns_rr_list *rrset, + ldns_rr_list *rrsig, + const ldns_rr_list *keys, + time_t check_time, + ldns_rr_list *good_keys + ) +{ + uint16_t i; + ldns_status verify_result = LDNS_STATUS_ERR; + + if (!rrset || !rrsig || !keys) { + return LDNS_STATUS_ERR; + } + + if (ldns_rr_list_rr_count(rrset) < 1) { + return LDNS_STATUS_ERR; + } + + if (ldns_rr_list_rr_count(rrsig) < 1) { + return LDNS_STATUS_CRYPTO_NO_RRSIG; + } + + if (ldns_rr_list_rr_count(keys) < 1) { + verify_result = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY; + } else { + for (i = 0; i < ldns_rr_list_rr_count(rrsig); i++) { + ldns_status s = ldns_verify_rrsig_keylist_time( + rrset, ldns_rr_list_rr(rrsig, i), + keys, check_time, good_keys); + /* try a little to get more descriptive error */ + if(s == LDNS_STATUS_OK) { + verify_result = LDNS_STATUS_OK; + } else if(verify_result == LDNS_STATUS_ERR) + verify_result = s; + else if(s != LDNS_STATUS_ERR && verify_result == + LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY) + verify_result = s; + } + } + return verify_result; +} + +ldns_status +ldns_verify(ldns_rr_list *rrset, ldns_rr_list *rrsig, const ldns_rr_list *keys, + ldns_rr_list *good_keys) +{ + return ldns_verify_time(rrset, rrsig, keys, ldns_time(NULL), good_keys); +} + +ldns_status +ldns_verify_notime(ldns_rr_list *rrset, ldns_rr_list *rrsig, + const ldns_rr_list *keys, ldns_rr_list *good_keys) +{ + uint16_t i; + ldns_status verify_result = LDNS_STATUS_ERR; + + if (!rrset || !rrsig || !keys) { + return LDNS_STATUS_ERR; + } + + if (ldns_rr_list_rr_count(rrset) < 1) { + return LDNS_STATUS_ERR; + } + + if (ldns_rr_list_rr_count(rrsig) < 1) { + return LDNS_STATUS_CRYPTO_NO_RRSIG; + } + + if (ldns_rr_list_rr_count(keys) < 1) { + verify_result = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY; + } else { + for (i = 0; i < ldns_rr_list_rr_count(rrsig); i++) { + ldns_status s = ldns_verify_rrsig_keylist_notime(rrset, + ldns_rr_list_rr(rrsig, i), keys, good_keys); + + /* try a little to get more descriptive error */ + if (s == LDNS_STATUS_OK) { + verify_result = LDNS_STATUS_OK; + } else if (verify_result == LDNS_STATUS_ERR) { + verify_result = s; + } else if (s != LDNS_STATUS_ERR && verify_result == + LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY) { + verify_result = s; + } + } + } + return verify_result; +} + +ldns_rr_list * +ldns_fetch_valid_domain_keys_time(const ldns_resolver *res, + const ldns_rdf *domain, + const ldns_rr_list *keys, + time_t check_time, + ldns_status *status) +{ + ldns_rr_list * trusted_keys = NULL; + ldns_rr_list * ds_keys = NULL; + ldns_rdf * prev_parent_domain; + ldns_rdf * parent_domain; + ldns_rr_list * parent_keys = NULL; + + if (res && domain && keys) { + + if ((trusted_keys = ldns_validate_domain_dnskey_time(res, + domain, keys, check_time))) { + *status = LDNS_STATUS_OK; + } else { + /* No trusted keys in this domain, we'll have to find some in the parent domain */ + *status = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY; + + parent_domain = ldns_dname_left_chop(domain); + while (ldns_rdf_size(parent_domain) > 0) { + /* Fail if we are at the root */ + + if ((parent_keys = + ldns_fetch_valid_domain_keys_time(res, + parent_domain, + keys, + check_time, + status))) { + /* Check DS records */ + if ((ds_keys = + ldns_validate_domain_ds_time(res, + domain, + parent_keys, + check_time))) { + trusted_keys = + ldns_fetch_valid_domain_keys_time( + res, + domain, + ds_keys, + check_time, + status); + ldns_rr_list_deep_free(ds_keys); + } else { + /* No valid DS at the parent -- fail */ + *status = LDNS_STATUS_CRYPTO_NO_TRUSTED_DS ; + } + ldns_rr_list_deep_free(parent_keys); + break; + } else { + parent_domain = ldns_dname_left_chop(( + prev_parent_domain + = parent_domain + )); + ldns_rdf_deep_free(prev_parent_domain); + } + } + ldns_rdf_deep_free(parent_domain); + } + } + return trusted_keys; +} + +ldns_rr_list * +ldns_fetch_valid_domain_keys(const ldns_resolver *res, + const ldns_rdf *domain, + const ldns_rr_list *keys, + ldns_status *status) +{ + return ldns_fetch_valid_domain_keys_time( + res, domain, keys, ldns_time(NULL), status); +} + +ldns_rr_list * +ldns_validate_domain_dnskey_time( + const ldns_resolver * res, + const ldns_rdf * domain, + const ldns_rr_list * keys, + time_t check_time + ) +{ + ldns_pkt * keypkt; + ldns_rr * cur_key; + uint16_t key_i; uint16_t key_j; uint16_t key_k; + uint16_t sig_i; ldns_rr * cur_sig; + + ldns_rr_list * domain_keys = NULL; + ldns_rr_list * domain_sigs = NULL; + ldns_rr_list * trusted_keys = NULL; + + /* Fetch keys for the domain */ + keypkt = ldns_resolver_query(res, domain, + LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN, LDNS_RD); + if (keypkt) { + domain_keys = ldns_pkt_rr_list_by_type(keypkt, + LDNS_RR_TYPE_DNSKEY, + LDNS_SECTION_ANSWER); + domain_sigs = ldns_pkt_rr_list_by_type(keypkt, + LDNS_RR_TYPE_RRSIG, + LDNS_SECTION_ANSWER); + + /* Try to validate the record using our keys */ + for (key_i=0; key_i< ldns_rr_list_rr_count(domain_keys); key_i++) { + + cur_key = ldns_rr_list_rr(domain_keys, key_i); + for (key_j=0; key_j= ldns_dname_label_count(ldns_rr_owner(rr))) { + + /* Query name *is* the "next closer". */ + hashed_next_closer = hashed_name; + } else { + + /* "next closer" has less labels than the query name. + * Create the name and hash it. + */ + next_closer = ldns_dname_clone_from( + ldns_rr_owner(rr), + ldns_dname_label_count(ldns_rr_owner(rr)) + - (ldns_dname_label_count(closest_encloser) + 1) + ); + hashed_next_closer = ldns_nsec3_hash_name_frm_nsec3( + ldns_rr_list_rr(nsecs, 0), + next_closer + ); + (void) ldns_dname_cat(hashed_next_closer, zone_name); + } + /* Find the NSEC3 that covers the "next closer" */ + for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) { + if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, i), + hashed_next_closer) && + ldns_nsec3_optout(ldns_rr_list_rr(nsecs, i))) { + + result = LDNS_STATUS_OK; + if (match) { + *match = ldns_rr_list_rr(nsecs, i); + } + break; + } + } + if (ldns_dname_label_count(closest_encloser) + 1 + < ldns_dname_label_count(ldns_rr_owner(rr))) { + + /* "next closer" has less labels than the query name. + * Dispose of the temporary variables that held that name. + */ + ldns_rdf_deep_free(hashed_next_closer); + ldns_rdf_deep_free(next_closer); + } + ldns_rdf_deep_free(closest_encloser); + } + + done: + ldns_rdf_deep_free(zone_name); + return result; +} + +ldns_status +ldns_dnssec_verify_denial_nsec3(ldns_rr *rr, + ldns_rr_list *nsecs, + ldns_rr_list *rrsigs, + ldns_pkt_rcode packet_rcode, + ldns_rr_type packet_qtype, + bool packet_nodata) +{ + return ldns_dnssec_verify_denial_nsec3_match( + rr, nsecs, rrsigs, packet_rcode, + packet_qtype, packet_nodata, NULL + ); +} + + +#endif /* HAVE_SSL */ + +#ifdef USE_GOST +EVP_PKEY* +ldns_gost2pkey_raw(unsigned char* key, size_t keylen) +{ + /* prefix header for X509 encoding */ + uint8_t asn[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85, + 0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85, + 0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03, + 0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40}; + unsigned char encoded[37+64]; + const unsigned char* pp; + if(keylen != 64) { + /* key wrong size */ + return NULL; + } + + /* create evp_key */ + memmove(encoded, asn, 37); + memmove(encoded+37, key, 64); + pp = (unsigned char*)&encoded[0]; + + return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded)); +} + +static ldns_status +ldns_verify_rrsig_gost_raw(unsigned char* sig, size_t siglen, + ldns_buffer* rrset, unsigned char* key, size_t keylen) +{ + EVP_PKEY *evp_key; + ldns_status result; + + (void) ldns_key_EVP_load_gost_id(); + evp_key = ldns_gost2pkey_raw(key, keylen); + if(!evp_key) { + /* could not convert key */ + return LDNS_STATUS_CRYPTO_BOGUS; + } + + /* verify signature */ + result = ldns_verify_rrsig_evp_raw(sig, siglen, rrset, + evp_key, EVP_get_digestbyname("md_gost94")); + EVP_PKEY_free(evp_key); + + return result; +} +#endif + +#ifdef USE_ECDSA +EVP_PKEY* +ldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo) +{ + unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */ + const unsigned char* pp = buf; + EVP_PKEY *evp_key; + EC_KEY *ec; + /* check length, which uncompressed must be 2 bignums */ + if(algo == LDNS_ECDSAP256SHA256) { + if(keylen != 2*256/8) return NULL; + ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + } else if(algo == LDNS_ECDSAP384SHA384) { + if(keylen != 2*384/8) return NULL; + ec = EC_KEY_new_by_curve_name(NID_secp384r1); + } else ec = NULL; + if(!ec) return NULL; + if(keylen+1 > sizeof(buf)) + return NULL; /* sanity check */ + /* prepend the 0x02 (from docs) (or actually 0x04 from implementation + * of openssl) for uncompressed data */ + buf[0] = POINT_CONVERSION_UNCOMPRESSED; + memmove(buf+1, key, keylen); + if(!o2i_ECPublicKey(&ec, &pp, (int)keylen+1)) { + EC_KEY_free(ec); + return NULL; + } + evp_key = EVP_PKEY_new(); + if(!evp_key) { + EC_KEY_free(ec); + return NULL; + } + if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) { + EVP_PKEY_free(evp_key); + EC_KEY_free(ec); + return NULL; + } + return evp_key; +} + +static ldns_status +ldns_verify_rrsig_ecdsa_raw(unsigned char* sig, size_t siglen, + ldns_buffer* rrset, unsigned char* key, size_t keylen, uint8_t algo) +{ + EVP_PKEY *evp_key; + ldns_status result; + const EVP_MD *d; + + evp_key = ldns_ecdsa2pkey_raw(key, keylen, algo); + if(!evp_key) { + /* could not convert key */ + return LDNS_STATUS_CRYPTO_BOGUS; + } + if(algo == LDNS_ECDSAP256SHA256) + d = EVP_sha256(); + else d = EVP_sha384(); /* LDNS_ECDSAP384SHA384 */ + result = ldns_verify_rrsig_evp_raw(sig, siglen, rrset, evp_key, d); + EVP_PKEY_free(evp_key); + return result; +} +#endif + +ldns_status +ldns_verify_rrsig_buffers(ldns_buffer *rawsig_buf, ldns_buffer *verify_buf, + ldns_buffer *key_buf, uint8_t algo) +{ + return ldns_verify_rrsig_buffers_raw( + (unsigned char*)ldns_buffer_begin(rawsig_buf), + ldns_buffer_position(rawsig_buf), + verify_buf, + (unsigned char*)ldns_buffer_begin(key_buf), + ldns_buffer_position(key_buf), algo); +} + +ldns_status +ldns_verify_rrsig_buffers_raw(unsigned char* sig, size_t siglen, + ldns_buffer *verify_buf, unsigned char* key, size_t keylen, + uint8_t algo) +{ + /* check for right key */ + switch(algo) { + case LDNS_DSA: + case LDNS_DSA_NSEC3: + return ldns_verify_rrsig_dsa_raw(sig, + siglen, + verify_buf, + key, + keylen); + break; + case LDNS_RSASHA1: + case LDNS_RSASHA1_NSEC3: + return ldns_verify_rrsig_rsasha1_raw(sig, + siglen, + verify_buf, + key, + keylen); + break; +#ifdef USE_SHA2 + case LDNS_RSASHA256: + return ldns_verify_rrsig_rsasha256_raw(sig, + siglen, + verify_buf, + key, + keylen); + break; + case LDNS_RSASHA512: + return ldns_verify_rrsig_rsasha512_raw(sig, + siglen, + verify_buf, + key, + keylen); + break; +#endif +#ifdef USE_GOST + case LDNS_ECC_GOST: + return ldns_verify_rrsig_gost_raw(sig, siglen, verify_buf, + key, keylen); + break; +#endif +#ifdef USE_ECDSA + case LDNS_ECDSAP256SHA256: + case LDNS_ECDSAP384SHA384: + return ldns_verify_rrsig_ecdsa_raw(sig, siglen, verify_buf, + key, keylen, algo); + break; +#endif + case LDNS_RSAMD5: + return ldns_verify_rrsig_rsamd5_raw(sig, + siglen, + verify_buf, + key, + keylen); + break; + default: + /* do you know this alg?! */ + return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO; + } +} + + +/** + * Reset the ttl in the rrset with the orig_ttl from the sig + * and update owner name if it was wildcard + * Also canonicalizes the rrset. + * @param rrset: rrset to modify + * @param sig: signature to take TTL and wildcard values from + */ +static void +ldns_rrset_use_signature_ttl(ldns_rr_list* rrset_clone, ldns_rr* rrsig) +{ + uint32_t orig_ttl; + uint16_t i; + uint8_t label_count; + ldns_rdf *wildcard_name; + ldns_rdf *wildcard_chopped; + ldns_rdf *wildcard_chopped_tmp; + + if ((rrsig == NULL) || ldns_rr_rd_count(rrsig) < 4) { + return; + } + + orig_ttl = ldns_rdf2native_int32( ldns_rr_rdf(rrsig, 3)); + label_count = ldns_rdf2native_int8(ldns_rr_rdf(rrsig, 2)); + + for(i = 0; i < ldns_rr_list_rr_count(rrset_clone); i++) { + if (label_count < + ldns_dname_label_count( + ldns_rr_owner(ldns_rr_list_rr(rrset_clone, i)))) { + (void) ldns_str2rdf_dname(&wildcard_name, "*"); + wildcard_chopped = ldns_rdf_clone(ldns_rr_owner( + ldns_rr_list_rr(rrset_clone, i))); + while (label_count < ldns_dname_label_count(wildcard_chopped)) { + wildcard_chopped_tmp = ldns_dname_left_chop( + wildcard_chopped); + ldns_rdf_deep_free(wildcard_chopped); + wildcard_chopped = wildcard_chopped_tmp; + } + (void) ldns_dname_cat(wildcard_name, wildcard_chopped); + ldns_rdf_deep_free(wildcard_chopped); + ldns_rdf_deep_free(ldns_rr_owner(ldns_rr_list_rr( + rrset_clone, i))); + ldns_rr_set_owner(ldns_rr_list_rr(rrset_clone, i), + wildcard_name); + } + ldns_rr_set_ttl(ldns_rr_list_rr(rrset_clone, i), orig_ttl); + /* convert to lowercase */ + ldns_rr2canonical(ldns_rr_list_rr(rrset_clone, i)); + } +} + +/** + * Make raw signature buffer out of rrsig + * @param rawsig_buf: raw signature buffer for result + * @param rrsig: signature to convert + * @return OK or more specific error. + */ +static ldns_status +ldns_rrsig2rawsig_buffer(ldns_buffer* rawsig_buf, ldns_rr* rrsig) +{ + uint8_t sig_algo; + + if (rrsig == NULL) { + return LDNS_STATUS_CRYPTO_NO_RRSIG; + } + if (ldns_rr_rdf(rrsig, 1) == NULL) { + return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG; + } + sig_algo = ldns_rdf2native_int8(ldns_rr_rdf(rrsig, 1)); + /* check for known and implemented algo's now (otherwise + * the function could return a wrong error + */ + /* create a buffer with signature rdata */ + /* for some algorithms we need other data than for others... */ + /* (the DSA API wants DER encoding for instance) */ + + switch(sig_algo) { + case LDNS_RSAMD5: + case LDNS_RSASHA1: + case LDNS_RSASHA1_NSEC3: +#ifdef USE_SHA2 + case LDNS_RSASHA256: + case LDNS_RSASHA512: +#endif +#ifdef USE_GOST + case LDNS_ECC_GOST: +#endif + if (ldns_rr_rdf(rrsig, 8) == NULL) { + return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG; + } + if (ldns_rdf2buffer_wire(rawsig_buf, ldns_rr_rdf(rrsig, 8)) + != LDNS_STATUS_OK) { + return LDNS_STATUS_MEM_ERR; + } + break; + case LDNS_DSA: + case LDNS_DSA_NSEC3: + /* EVP takes rfc2459 format, which is a tad longer than dns format */ + if (ldns_rr_rdf(rrsig, 8) == NULL) { + return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG; + } + if (ldns_convert_dsa_rrsig_rdf2asn1( + rawsig_buf, ldns_rr_rdf(rrsig, 8)) + != LDNS_STATUS_OK) { + /* + if (ldns_rdf2buffer_wire(rawsig_buf, + ldns_rr_rdf(rrsig, 8)) != LDNS_STATUS_OK) { + */ + return LDNS_STATUS_MEM_ERR; + } + break; +#ifdef USE_ECDSA + case LDNS_ECDSAP256SHA256: + case LDNS_ECDSAP384SHA384: + /* EVP produces an ASN prefix on the signature, which is + * not used in the DNS */ + if (ldns_rr_rdf(rrsig, 8) == NULL) { + return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG; + } + if (ldns_convert_ecdsa_rrsig_rdf2asn1( + rawsig_buf, ldns_rr_rdf(rrsig, 8)) + != LDNS_STATUS_OK) { + return LDNS_STATUS_MEM_ERR; + } + break; +#endif + case LDNS_DH: + case LDNS_ECC: + case LDNS_INDIRECT: + return LDNS_STATUS_CRYPTO_ALGO_NOT_IMPL; + default: + return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO; + } + return LDNS_STATUS_OK; +} + +/** + * Check RRSIG timestamps against the given 'now' time. + * @param rrsig: signature to check. + * @param now: the current time in seconds epoch. + * @return status code LDNS_STATUS_OK if all is fine. + */ +static ldns_status +ldns_rrsig_check_timestamps(ldns_rr* rrsig, time_t now) +{ + int32_t inception, expiration; + + /* check the signature time stamps */ + inception = (int32_t)ldns_rdf2native_time_t( + ldns_rr_rrsig_inception(rrsig)); + expiration = (int32_t)ldns_rdf2native_time_t( + ldns_rr_rrsig_expiration(rrsig)); + + if (expiration - inception < 0) { + /* bad sig, expiration before inception?? Tsssg */ + return LDNS_STATUS_CRYPTO_EXPIRATION_BEFORE_INCEPTION; + } + if (((int32_t) now) - inception < 0) { + /* bad sig, inception date has not yet come to pass */ + return LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED; + } + if (expiration - ((int32_t) now) < 0) { + /* bad sig, expiration date has passed */ + return LDNS_STATUS_CRYPTO_SIG_EXPIRED; + } + return LDNS_STATUS_OK; +} + +/** + * Prepare for verification. + * @param rawsig_buf: raw signature buffer made ready. + * @param verify_buf: data for verification buffer made ready. + * @param rrset_clone: made ready. + * @param rrsig: signature to prepare for. + * @return LDNS_STATUS_OK is all went well. Otherwise specific error. + */ +static ldns_status +ldns_prepare_for_verify(ldns_buffer* rawsig_buf, ldns_buffer* verify_buf, + ldns_rr_list* rrset_clone, ldns_rr* rrsig) +{ + ldns_status result; + + /* canonicalize the sig */ + ldns_dname2canonical(ldns_rr_owner(rrsig)); + + /* check if the typecovered is equal to the type checked */ + if (ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rrsig)) != + ldns_rr_get_type(ldns_rr_list_rr(rrset_clone, 0))) + return LDNS_STATUS_CRYPTO_TYPE_COVERED_ERR; + + /* create a buffer with b64 signature rdata */ + result = ldns_rrsig2rawsig_buffer(rawsig_buf, rrsig); + if(result != LDNS_STATUS_OK) + return result; + + /* use TTL from signature. Use wildcard names for wildcards */ + /* also canonicalizes rrset_clone */ + ldns_rrset_use_signature_ttl(rrset_clone, rrsig); + + /* sort the rrset in canonical order */ + ldns_rr_list_sort(rrset_clone); + + /* put the signature rr (without the b64) to the verify_buf */ + if (ldns_rrsig2buffer_wire(verify_buf, rrsig) != LDNS_STATUS_OK) + return LDNS_STATUS_MEM_ERR; + + /* add the rrset in verify_buf */ + if(ldns_rr_list2buffer_wire(verify_buf, rrset_clone) + != LDNS_STATUS_OK) + return LDNS_STATUS_MEM_ERR; + + return LDNS_STATUS_OK; +} + +/** + * Check if a key matches a signature. + * Checks keytag, sigalgo and signature. + * @param rawsig_buf: raw signature buffer for verify + * @param verify_buf: raw data buffer for verify + * @param rrsig: the rrsig + * @param key: key to attempt. + * @return LDNS_STATUS_OK if OK, else some specific error. + */ +static ldns_status +ldns_verify_test_sig_key(ldns_buffer* rawsig_buf, ldns_buffer* verify_buf, + ldns_rr* rrsig, ldns_rr* key) +{ + uint8_t sig_algo; + + if (rrsig == NULL) { + return LDNS_STATUS_CRYPTO_NO_RRSIG; + } + if (ldns_rr_rdf(rrsig, 1) == NULL) { + return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG; + } + sig_algo = ldns_rdf2native_int8(ldns_rr_rdf(rrsig, 1)); + + /* before anything, check if the keytags match */ + if (ldns_calc_keytag(key) + == + ldns_rdf2native_int16(ldns_rr_rrsig_keytag(rrsig)) + ) { + ldns_buffer* key_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN); + ldns_status result = LDNS_STATUS_ERR; + + /* put the key-data in a buffer, that's the third rdf, with + * the base64 encoded key data */ + if (ldns_rr_rdf(key, 3) == NULL) { + ldns_buffer_free(key_buf); + return LDNS_STATUS_MISSING_RDATA_FIELDS_KEY; + } + if (ldns_rdf2buffer_wire(key_buf, ldns_rr_rdf(key, 3)) + != LDNS_STATUS_OK) { + ldns_buffer_free(key_buf); + /* returning is bad might screw up + good keys later in the list + what to do? */ + return LDNS_STATUS_ERR; + } + + if (ldns_rr_rdf(key, 2) == NULL) { + result = LDNS_STATUS_MISSING_RDATA_FIELDS_KEY; + } + else if (sig_algo == ldns_rdf2native_int8( + ldns_rr_rdf(key, 2))) { + result = ldns_verify_rrsig_buffers(rawsig_buf, + verify_buf, key_buf, sig_algo); + } else { + /* No keys with the corresponding algorithm are found */ + result = LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY; + } + + ldns_buffer_free(key_buf); + return result; + } + else { + /* No keys with the corresponding keytag are found */ + return LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY; + } +} + +/* + * to verify: + * - create the wire fmt of the b64 key rdata + * - create the wire fmt of the sorted rrset + * - create the wire fmt of the b64 sig rdata + * - create the wire fmt of the sig without the b64 rdata + * - cat the sig data (without b64 rdata) to the rrset + * - verify the rrset+sig, with the b64 data and the b64 key data + */ +ldns_status +ldns_verify_rrsig_keylist_time( + ldns_rr_list *rrset, + ldns_rr *rrsig, + const ldns_rr_list *keys, + time_t check_time, + ldns_rr_list *good_keys) +{ + ldns_status result; + ldns_rr_list *valid = ldns_rr_list_new(); + if (!valid) + return LDNS_STATUS_MEM_ERR; + + result = ldns_verify_rrsig_keylist_notime(rrset, rrsig, keys, valid); + if(result != LDNS_STATUS_OK) { + ldns_rr_list_free(valid); + return result; + } + + /* check timestamps last; its OK except time */ + result = ldns_rrsig_check_timestamps(rrsig, check_time); + if(result != LDNS_STATUS_OK) { + ldns_rr_list_free(valid); + return result; + } + + ldns_rr_list_cat(good_keys, valid); + ldns_rr_list_free(valid); + return LDNS_STATUS_OK; +} + +/* + * to verify: + * - create the wire fmt of the b64 key rdata + * - create the wire fmt of the sorted rrset + * - create the wire fmt of the b64 sig rdata + * - create the wire fmt of the sig without the b64 rdata + * - cat the sig data (without b64 rdata) to the rrset + * - verify the rrset+sig, with the b64 data and the b64 key data + */ +ldns_status +ldns_verify_rrsig_keylist(ldns_rr_list *rrset, + ldns_rr *rrsig, + const ldns_rr_list *keys, + ldns_rr_list *good_keys) +{ + return ldns_verify_rrsig_keylist_time( + rrset, rrsig, keys, ldns_time(NULL), good_keys); +} + +ldns_status +ldns_verify_rrsig_keylist_notime(ldns_rr_list *rrset, + ldns_rr *rrsig, + const ldns_rr_list *keys, + ldns_rr_list *good_keys) +{ + ldns_buffer *rawsig_buf; + ldns_buffer *verify_buf; + uint16_t i; + ldns_status result, status; + ldns_rr_list *rrset_clone; + ldns_rr_list *validkeys; + + if (!rrset) { + return LDNS_STATUS_ERR; + } + + validkeys = ldns_rr_list_new(); + if (!validkeys) { + return LDNS_STATUS_MEM_ERR; + } + + /* clone the rrset so that we can fiddle with it */ + rrset_clone = ldns_rr_list_clone(rrset); + + /* create the buffers which will certainly hold the raw data */ + rawsig_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN); + verify_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN); + + result = ldns_prepare_for_verify(rawsig_buf, verify_buf, + rrset_clone, rrsig); + if(result != LDNS_STATUS_OK) { + ldns_buffer_free(verify_buf); + ldns_buffer_free(rawsig_buf); + ldns_rr_list_deep_free(rrset_clone); + ldns_rr_list_free(validkeys); + return result; + } + + result = LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY; + for(i = 0; i < ldns_rr_list_rr_count(keys); i++) { + status = ldns_verify_test_sig_key(rawsig_buf, verify_buf, + rrsig, ldns_rr_list_rr(keys, i)); + if (status == LDNS_STATUS_OK) { + /* one of the keys has matched, don't break + * here, instead put the 'winning' key in + * the validkey list and return the list + * later */ + if (!ldns_rr_list_push_rr(validkeys, + ldns_rr_list_rr(keys,i))) { + /* couldn't push the key?? */ + ldns_buffer_free(rawsig_buf); + ldns_buffer_free(verify_buf); + ldns_rr_list_deep_free(rrset_clone); + ldns_rr_list_free(validkeys); + return LDNS_STATUS_MEM_ERR; + } + + result = status; + } + + if (result == LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY) { + result = status; + } + } + + /* no longer needed */ + ldns_rr_list_deep_free(rrset_clone); + ldns_buffer_free(rawsig_buf); + ldns_buffer_free(verify_buf); + + if (ldns_rr_list_rr_count(validkeys) == 0) { + /* no keys were added, return last error */ + ldns_rr_list_free(validkeys); + return result; + } + + /* do not check timestamps */ + + ldns_rr_list_cat(good_keys, validkeys); + ldns_rr_list_free(validkeys); + return LDNS_STATUS_OK; +} + +ldns_status +ldns_verify_rrsig_time( + ldns_rr_list *rrset, + ldns_rr *rrsig, + ldns_rr *key, + time_t check_time) +{ + ldns_buffer *rawsig_buf; + ldns_buffer *verify_buf; + ldns_status result; + ldns_rr_list *rrset_clone; + + if (!rrset) { + return LDNS_STATUS_NO_DATA; + } + /* clone the rrset so that we can fiddle with it */ + rrset_clone = ldns_rr_list_clone(rrset); + /* create the buffers which will certainly hold the raw data */ + rawsig_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN); + verify_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN); + + result = ldns_prepare_for_verify(rawsig_buf, verify_buf, + rrset_clone, rrsig); + if(result != LDNS_STATUS_OK) { + ldns_rr_list_deep_free(rrset_clone); + ldns_buffer_free(rawsig_buf); + ldns_buffer_free(verify_buf); + return result; + } + result = ldns_verify_test_sig_key(rawsig_buf, verify_buf, + rrsig, key); + /* no longer needed */ + ldns_rr_list_deep_free(rrset_clone); + ldns_buffer_free(rawsig_buf); + ldns_buffer_free(verify_buf); + + /* check timestamp last, apart from time its OK */ + if(result == LDNS_STATUS_OK) + result = ldns_rrsig_check_timestamps(rrsig, check_time); + + return result; +} + +ldns_status +ldns_verify_rrsig(ldns_rr_list *rrset, ldns_rr *rrsig, ldns_rr *key) +{ + return ldns_verify_rrsig_time(rrset, rrsig, key, ldns_time(NULL)); +} + + +ldns_status +ldns_verify_rrsig_evp(ldns_buffer *sig, + ldns_buffer *rrset, + EVP_PKEY *key, + const EVP_MD *digest_type) +{ + return ldns_verify_rrsig_evp_raw( + (unsigned char*)ldns_buffer_begin(sig), + ldns_buffer_position(sig), + rrset, + key, + digest_type); +} + +ldns_status +ldns_verify_rrsig_evp_raw(unsigned char *sig, size_t siglen, + ldns_buffer *rrset, EVP_PKEY *key, const EVP_MD *digest_type) +{ + EVP_MD_CTX ctx; + int res; + + EVP_MD_CTX_init(&ctx); + + EVP_VerifyInit(&ctx, digest_type); + EVP_VerifyUpdate(&ctx, + ldns_buffer_begin(rrset), + ldns_buffer_position(rrset)); + res = EVP_VerifyFinal(&ctx, sig, (unsigned int) siglen, key); + + EVP_MD_CTX_cleanup(&ctx); + + if (res == 1) { + return LDNS_STATUS_OK; + } else if (res == 0) { + return LDNS_STATUS_CRYPTO_BOGUS; + } + /* TODO how to communicate internal SSL error? + let caller use ssl's get_error() */ + return LDNS_STATUS_SSL_ERR; +} + +ldns_status +ldns_verify_rrsig_dsa(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key) +{ + return ldns_verify_rrsig_dsa_raw( + (unsigned char*) ldns_buffer_begin(sig), + ldns_buffer_position(sig), + rrset, + (unsigned char*) ldns_buffer_begin(key), + ldns_buffer_position(key)); +} + +ldns_status +ldns_verify_rrsig_rsasha1(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key) +{ + return ldns_verify_rrsig_rsasha1_raw( + (unsigned char*)ldns_buffer_begin(sig), + ldns_buffer_position(sig), + rrset, + (unsigned char*) ldns_buffer_begin(key), + ldns_buffer_position(key)); +} + +ldns_status +ldns_verify_rrsig_rsamd5(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key) +{ + return ldns_verify_rrsig_rsamd5_raw( + (unsigned char*)ldns_buffer_begin(sig), + ldns_buffer_position(sig), + rrset, + (unsigned char*) ldns_buffer_begin(key), + ldns_buffer_position(key)); +} + +ldns_status +ldns_verify_rrsig_dsa_raw(unsigned char* sig, size_t siglen, + ldns_buffer* rrset, unsigned char* key, size_t keylen) +{ + EVP_PKEY *evp_key; + ldns_status result; + + evp_key = EVP_PKEY_new(); + if (EVP_PKEY_assign_DSA(evp_key, ldns_key_buf2dsa_raw(key, keylen))) { + result = ldns_verify_rrsig_evp_raw(sig, + siglen, + rrset, + evp_key, + EVP_dss1()); + } else { + result = LDNS_STATUS_SSL_ERR; + } + EVP_PKEY_free(evp_key); + return result; + +} + +ldns_status +ldns_verify_rrsig_rsasha1_raw(unsigned char* sig, size_t siglen, + ldns_buffer* rrset, unsigned char* key, size_t keylen) +{ + EVP_PKEY *evp_key; + ldns_status result; + + evp_key = EVP_PKEY_new(); + if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) { + result = ldns_verify_rrsig_evp_raw(sig, + siglen, + rrset, + evp_key, + EVP_sha1()); + } else { + result = LDNS_STATUS_SSL_ERR; + } + EVP_PKEY_free(evp_key); + + return result; +} + +ldns_status +ldns_verify_rrsig_rsasha256_raw(unsigned char* sig, + size_t siglen, + ldns_buffer* rrset, + unsigned char* key, + size_t keylen) +{ +#ifdef USE_SHA2 + EVP_PKEY *evp_key; + ldns_status result; + + evp_key = EVP_PKEY_new(); + if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) { + result = ldns_verify_rrsig_evp_raw(sig, + siglen, + rrset, + evp_key, + EVP_sha256()); + } else { + result = LDNS_STATUS_SSL_ERR; + } + EVP_PKEY_free(evp_key); + + return result; +#else + /* touch these to prevent compiler warnings */ + (void) sig; + (void) siglen; + (void) rrset; + (void) key; + (void) keylen; + return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO; +#endif +} + +ldns_status +ldns_verify_rrsig_rsasha512_raw(unsigned char* sig, + size_t siglen, + ldns_buffer* rrset, + unsigned char* key, + size_t keylen) +{ +#ifdef USE_SHA2 + EVP_PKEY *evp_key; + ldns_status result; + + evp_key = EVP_PKEY_new(); + if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) { + result = ldns_verify_rrsig_evp_raw(sig, + siglen, + rrset, + evp_key, + EVP_sha512()); + } else { + result = LDNS_STATUS_SSL_ERR; + } + EVP_PKEY_free(evp_key); + + return result; +#else + /* touch these to prevent compiler warnings */ + (void) sig; + (void) siglen; + (void) rrset; + (void) key; + (void) keylen; + return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO; +#endif +} + + +ldns_status +ldns_verify_rrsig_rsamd5_raw(unsigned char* sig, + size_t siglen, + ldns_buffer* rrset, + unsigned char* key, + size_t keylen) +{ + EVP_PKEY *evp_key; + ldns_status result; + + evp_key = EVP_PKEY_new(); + if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) { + result = ldns_verify_rrsig_evp_raw(sig, + siglen, + rrset, + evp_key, + EVP_md5()); + } else { + result = LDNS_STATUS_SSL_ERR; + } + EVP_PKEY_free(evp_key); + + return result; +} + +#endif diff --git a/dnssec_zone.c b/dnssec_zone.c new file mode 100644 index 00000000000..1f7274bbc96 --- /dev/null +++ b/dnssec_zone.c @@ -0,0 +1,1093 @@ +/* + * special zone file structures and functions for better dnssec handling + */ + +#include + +#include + +ldns_dnssec_rrs * +ldns_dnssec_rrs_new() +{ + ldns_dnssec_rrs *new_rrs; + new_rrs = LDNS_MALLOC(ldns_dnssec_rrs); + if(!new_rrs) return NULL; + new_rrs->rr = NULL; + new_rrs->next = NULL; + return new_rrs; +} + +INLINE void +ldns_dnssec_rrs_free_internal(ldns_dnssec_rrs *rrs, int deep) +{ + ldns_dnssec_rrs *next; + while (rrs) { + next = rrs->next; + if (deep) { + ldns_rr_free(rrs->rr); + } + LDNS_FREE(rrs); + rrs = next; + } +} + +void +ldns_dnssec_rrs_free(ldns_dnssec_rrs *rrs) +{ + ldns_dnssec_rrs_free_internal(rrs, 0); +} + +void +ldns_dnssec_rrs_deep_free(ldns_dnssec_rrs *rrs) +{ + ldns_dnssec_rrs_free_internal(rrs, 1); +} + +ldns_status +ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr) +{ + int cmp; + ldns_dnssec_rrs *new_rrs; + if (!rrs || !rr) { + return LDNS_STATUS_ERR; + } + + /* this could be done more efficiently; name and type should already + be equal */ + cmp = ldns_rr_compare(rrs->rr, + rr); + /* should we error on equal? */ + if (cmp <= 0) { + if (rrs->next) { + return ldns_dnssec_rrs_add_rr(rrs->next, rr); + } else { + new_rrs = ldns_dnssec_rrs_new(); + new_rrs->rr = rr; + rrs->next = new_rrs; + } + } else if (cmp > 0) { + /* put the current old rr in the new next, put the new + rr in the current container */ + new_rrs = ldns_dnssec_rrs_new(); + new_rrs->rr = rrs->rr; + new_rrs->next = rrs->next; + rrs->rr = rr; + rrs->next = new_rrs; + } + return LDNS_STATUS_OK; +} + +void +ldns_dnssec_rrs_print_fmt(FILE *out, const ldns_output_format *fmt, + ldns_dnssec_rrs *rrs) +{ + if (!rrs) { + if ((fmt->flags & LDNS_COMMENT_LAYOUT)) + fprintf(out, "; "); + } else { + if (rrs->rr) { + ldns_rr_print_fmt(out, fmt, rrs->rr); + } + if (rrs->next) { + ldns_dnssec_rrs_print_fmt(out, fmt, rrs->next); + } + } +} + +void +ldns_dnssec_rrs_print(FILE *out, ldns_dnssec_rrs *rrs) +{ + ldns_dnssec_rrs_print_fmt(out, ldns_output_format_default, rrs); +} + + +ldns_dnssec_rrsets * +ldns_dnssec_rrsets_new() +{ + ldns_dnssec_rrsets *new_rrsets; + new_rrsets = LDNS_MALLOC(ldns_dnssec_rrsets); + if(!new_rrsets) return NULL; + new_rrsets->rrs = NULL; + new_rrsets->type = 0; + new_rrsets->signatures = NULL; + new_rrsets->next = NULL; + return new_rrsets; +} + +INLINE void +ldns_dnssec_rrsets_free_internal(ldns_dnssec_rrsets *rrsets, int deep) +{ + if (rrsets) { + if (rrsets->rrs) { + ldns_dnssec_rrs_free_internal(rrsets->rrs, deep); + } + if (rrsets->next) { + ldns_dnssec_rrsets_free_internal(rrsets->next, deep); + } + if (rrsets->signatures) { + ldns_dnssec_rrs_free_internal(rrsets->signatures, deep); + } + LDNS_FREE(rrsets); + } +} + +void +ldns_dnssec_rrsets_free(ldns_dnssec_rrsets *rrsets) +{ + ldns_dnssec_rrsets_free_internal(rrsets, 0); +} + +void +ldns_dnssec_rrsets_deep_free(ldns_dnssec_rrsets *rrsets) +{ + ldns_dnssec_rrsets_free_internal(rrsets, 1); +} + +ldns_rr_type +ldns_dnssec_rrsets_type(ldns_dnssec_rrsets *rrsets) +{ + if (rrsets) { + return rrsets->type; + } else { + return 0; + } +} + +ldns_status +ldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets *rrsets, + ldns_rr_type type) +{ + if (rrsets) { + rrsets->type = type; + return LDNS_STATUS_OK; + } + return LDNS_STATUS_ERR; +} + +ldns_dnssec_rrsets * +ldns_dnssec_rrsets_new_frm_rr(ldns_rr *rr) +{ + ldns_dnssec_rrsets *new_rrsets; + ldns_rr_type rr_type; + bool rrsig; + + new_rrsets = ldns_dnssec_rrsets_new(); + rr_type = ldns_rr_get_type(rr); + if (rr_type == LDNS_RR_TYPE_RRSIG) { + rrsig = true; + rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)); + } else { + rrsig = false; + } + if (!rrsig) { + new_rrsets->rrs = ldns_dnssec_rrs_new(); + new_rrsets->rrs->rr = rr; + } else { + new_rrsets->signatures = ldns_dnssec_rrs_new(); + new_rrsets->signatures->rr = rr; + } + new_rrsets->type = rr_type; + return new_rrsets; +} + +ldns_status +ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets *rrsets, ldns_rr *rr) +{ + ldns_dnssec_rrsets *new_rrsets; + ldns_rr_type rr_type; + bool rrsig = false; + ldns_status result = LDNS_STATUS_OK; + + if (!rrsets || !rr) { + return LDNS_STATUS_ERR; + } + + rr_type = ldns_rr_get_type(rr); + + if (rr_type == LDNS_RR_TYPE_RRSIG) { + rrsig = true; + rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)); + } + + if (!rrsets->rrs && rrsets->type == 0 && !rrsets->signatures) { + if (!rrsig) { + rrsets->rrs = ldns_dnssec_rrs_new(); + rrsets->rrs->rr = rr; + rrsets->type = rr_type; + } else { + rrsets->signatures = ldns_dnssec_rrs_new(); + rrsets->signatures->rr = rr; + rrsets->type = rr_type; + } + return LDNS_STATUS_OK; + } + + if (rr_type > ldns_dnssec_rrsets_type(rrsets)) { + if (rrsets->next) { + result = ldns_dnssec_rrsets_add_rr(rrsets->next, rr); + } else { + new_rrsets = ldns_dnssec_rrsets_new_frm_rr(rr); + rrsets->next = new_rrsets; + } + } else if (rr_type < ldns_dnssec_rrsets_type(rrsets)) { + /* move the current one into the new next, + replace field of current with data from new rr */ + new_rrsets = ldns_dnssec_rrsets_new(); + new_rrsets->rrs = rrsets->rrs; + new_rrsets->type = rrsets->type; + new_rrsets->signatures = rrsets->signatures; + new_rrsets->next = rrsets->next; + if (!rrsig) { + rrsets->rrs = ldns_dnssec_rrs_new(); + rrsets->rrs->rr = rr; + rrsets->signatures = NULL; + } else { + rrsets->rrs = NULL; + rrsets->signatures = ldns_dnssec_rrs_new(); + rrsets->signatures->rr = rr; + } + rrsets->type = rr_type; + rrsets->next = new_rrsets; + } else { + /* equal, add to current rrsets */ + if (rrsig) { + if (rrsets->signatures) { + result = ldns_dnssec_rrs_add_rr(rrsets->signatures, rr); + } else { + rrsets->signatures = ldns_dnssec_rrs_new(); + rrsets->signatures->rr = rr; + } + } else { + if (rrsets->rrs) { + result = ldns_dnssec_rrs_add_rr(rrsets->rrs, rr); + } else { + rrsets->rrs = ldns_dnssec_rrs_new(); + rrsets->rrs->rr = rr; + } + } + } + + return result; +} + +void +ldns_dnssec_rrsets_print_soa_fmt(FILE *out, const ldns_output_format *fmt, + ldns_dnssec_rrsets *rrsets, + bool follow, + bool show_soa) +{ + if (!rrsets) { + if ((fmt->flags & LDNS_COMMENT_LAYOUT)) + fprintf(out, "; \n"); + } else { + if (rrsets->rrs && + (show_soa || + ldns_rr_get_type(rrsets->rrs->rr) != LDNS_RR_TYPE_SOA + ) + ) { + ldns_dnssec_rrs_print_fmt(out, fmt, rrsets->rrs); + if (rrsets->signatures) { + ldns_dnssec_rrs_print_fmt(out, fmt, + rrsets->signatures); + } + } + if (follow && rrsets->next) { + ldns_dnssec_rrsets_print_soa_fmt(out, fmt, + rrsets->next, follow, show_soa); + } + } +} + +void +ldns_dnssec_rrsets_print_soa(FILE *out, + ldns_dnssec_rrsets *rrsets, + bool follow, + bool show_soa) +{ + ldns_dnssec_rrsets_print_soa_fmt(out, ldns_output_format_default, + rrsets, follow, show_soa); +} + + +void +ldns_dnssec_rrsets_print_fmt(FILE *out, const ldns_output_format *fmt, + ldns_dnssec_rrsets *rrsets, + bool follow) +{ + ldns_dnssec_rrsets_print_soa_fmt(out, fmt, rrsets, follow, true); +} + +void +ldns_dnssec_rrsets_print(FILE *out, ldns_dnssec_rrsets *rrsets, bool follow) +{ + ldns_dnssec_rrsets_print_fmt(out, ldns_output_format_default, + rrsets, follow); +} + +ldns_dnssec_name * +ldns_dnssec_name_new() +{ + ldns_dnssec_name *new_name; + + new_name = LDNS_CALLOC(ldns_dnssec_name, 1); + if (!new_name) { + return NULL; + } + /* + * not needed anymore because CALLOC initalizes everything to zero. + + new_name->name = NULL; + new_name->rrsets = NULL; + new_name->name_alloced = false; + new_name->nsec = NULL; + new_name->nsec_signatures = NULL; + + new_name->is_glue = false; + new_name->hashed_name = NULL; + + */ + return new_name; +} + +ldns_dnssec_name * +ldns_dnssec_name_new_frm_rr(ldns_rr *rr) +{ + ldns_dnssec_name *new_name = ldns_dnssec_name_new(); + + new_name->name = ldns_rr_owner(rr); + if(ldns_dnssec_name_add_rr(new_name, rr) != LDNS_STATUS_OK) { + ldns_dnssec_name_free(new_name); + return NULL; + } + + return new_name; +} + +INLINE void +ldns_dnssec_name_free_internal(ldns_dnssec_name *name, + int deep) +{ + if (name) { + if (name->name_alloced) { + ldns_rdf_deep_free(name->name); + } + if (name->rrsets) { + ldns_dnssec_rrsets_free_internal(name->rrsets, deep); + } + if (name->nsec && deep) { + ldns_rr_free(name->nsec); + } + if (name->nsec_signatures) { + ldns_dnssec_rrs_free_internal(name->nsec_signatures, deep); + } + if (name->hashed_name) { + if (deep) { + ldns_rdf_deep_free(name->hashed_name); + } + } + LDNS_FREE(name); + } +} + +void +ldns_dnssec_name_free(ldns_dnssec_name *name) +{ + ldns_dnssec_name_free_internal(name, 0); +} + +void +ldns_dnssec_name_deep_free(ldns_dnssec_name *name) +{ + ldns_dnssec_name_free_internal(name, 1); +} + +ldns_rdf * +ldns_dnssec_name_name(ldns_dnssec_name *name) +{ + if (name) { + return name->name; + } + return NULL; +} + +bool +ldns_dnssec_name_is_glue(ldns_dnssec_name *name) +{ + if (name) { + return name->is_glue; + } + return false; +} + +void +ldns_dnssec_name_set_name(ldns_dnssec_name *rrset, + ldns_rdf *dname) +{ + if (rrset && dname) { + rrset->name = dname; + } +} + +ldns_rr * +ldns_dnssec_name_nsec(ldns_dnssec_name *rrset) +{ + if (rrset) { + return rrset->nsec; + } + return NULL; +} + +void +ldns_dnssec_name_set_nsec(ldns_dnssec_name *rrset, ldns_rr *nsec) +{ + if (rrset && nsec) { + rrset->nsec = nsec; + } +} + +int +ldns_dnssec_name_cmp(const void *a, const void *b) +{ + ldns_dnssec_name *na = (ldns_dnssec_name *) a; + ldns_dnssec_name *nb = (ldns_dnssec_name *) b; + + if (na && nb) { + return ldns_dname_compare(ldns_dnssec_name_name(na), + ldns_dnssec_name_name(nb)); + } else if (na) { + return 1; + } else if (nb) { + return -1; + } else { + return 0; + } +} + +ldns_status +ldns_dnssec_name_add_rr(ldns_dnssec_name *name, + ldns_rr *rr) +{ + ldns_status result = LDNS_STATUS_OK; + ldns_rdf *name_name; + bool hashed_name = false; + ldns_rr_type rr_type; + ldns_rr_type typecovered = 0; + + /* special handling for NSEC3 and NSECX covering RRSIGS */ + + if (!name || !rr) { + return LDNS_STATUS_ERR; + } + + rr_type = ldns_rr_get_type(rr); + + if (rr_type == LDNS_RR_TYPE_RRSIG) { + typecovered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)); + } + +#ifdef HAVE_SSL + if (rr_type == LDNS_RR_TYPE_NSEC3 || + typecovered == LDNS_RR_TYPE_NSEC3) { + name_name = ldns_nsec3_hash_name_frm_nsec3(rr, + ldns_dnssec_name_name(name)); + hashed_name = true; + } else { + name_name = ldns_dnssec_name_name(name); + } +#else + name_name = ldns_dnssec_name_name(name); +#endif /* HAVE_SSL */ + + if (rr_type == LDNS_RR_TYPE_NSEC || + rr_type == LDNS_RR_TYPE_NSEC3) { + /* XX check if is already set (and error?) */ + name->nsec = rr; + } else if (typecovered == LDNS_RR_TYPE_NSEC || + typecovered == LDNS_RR_TYPE_NSEC3) { + if (name->nsec_signatures) { + result = ldns_dnssec_rrs_add_rr(name->nsec_signatures, rr); + } else { + name->nsec_signatures = ldns_dnssec_rrs_new(); + name->nsec_signatures->rr = rr; + } + } else { + /* it's a 'normal' RR, add it to the right rrset */ + if (name->rrsets) { + result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr); + } else { + name->rrsets = ldns_dnssec_rrsets_new(); + result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr); + } + } + + if (hashed_name) { + ldns_rdf_deep_free(name_name); + } + + return result; +} + +ldns_dnssec_rrsets * +ldns_dnssec_name_find_rrset(ldns_dnssec_name *name, + ldns_rr_type type) { + ldns_dnssec_rrsets *result; + + result = name->rrsets; + while (result) { + if (result->type == type) { + return result; + } else { + result = result->next; + } + } + return NULL; +} + +ldns_dnssec_rrsets * +ldns_dnssec_zone_find_rrset(ldns_dnssec_zone *zone, + ldns_rdf *dname, + ldns_rr_type type) +{ + ldns_rbnode_t *node; + + if (!zone || !dname) { + return NULL; + } + + node = ldns_rbtree_search(zone->names, dname); + if (node) { + return ldns_dnssec_name_find_rrset((ldns_dnssec_name *)node->data, + type); + } else { + return NULL; + } +} + +void +ldns_dnssec_name_print_soa_fmt(FILE *out, const ldns_output_format *fmt, + ldns_dnssec_name *name, + bool show_soa) +{ + if (name) { + if(name->rrsets) { + ldns_dnssec_rrsets_print_soa_fmt(out, fmt, + name->rrsets, true, show_soa); + } else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) { + fprintf(out, ";; Empty nonterminal: "); + ldns_rdf_print(out, name->name); + fprintf(out, "\n"); + } + if(name->nsec) { + ldns_rr_print_fmt(out, fmt, name->nsec); + } + if (name->nsec_signatures) { + ldns_dnssec_rrs_print_fmt(out, fmt, + name->nsec_signatures); + } + } else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) { + fprintf(out, "; \n"); + } +} + +void +ldns_dnssec_name_print_soa(FILE *out, ldns_dnssec_name *name, bool show_soa) +{ + ldns_dnssec_name_print_soa_fmt(out, ldns_output_format_default, + name, show_soa); +} + +void +ldns_dnssec_name_print_fmt(FILE *out, const ldns_output_format *fmt, + ldns_dnssec_name *name) +{ + ldns_dnssec_name_print_soa_fmt(out, fmt, name, true); +} + +void +ldns_dnssec_name_print(FILE *out, ldns_dnssec_name *name) +{ + ldns_dnssec_name_print_fmt(out, ldns_output_format_default, name); +} + + +ldns_dnssec_zone * +ldns_dnssec_zone_new() +{ + ldns_dnssec_zone *zone = LDNS_MALLOC(ldns_dnssec_zone); + if(!zone) return NULL; + zone->soa = NULL; + zone->names = NULL; + + return zone; +} + +static bool +rr_is_rrsig_covering(ldns_rr* rr, ldns_rr_type t) +{ + return ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG + && ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)) == t; +} + +/* When the zone is first read into an list and then inserted into an + * ldns_dnssec_zone (rbtree) the nodes of the rbtree are allocated close (next) + * to each other. Because ldns-verify-zone (the only program that uses this + * function) uses the rbtree mostly for sequentual walking, this results + * in a speed increase (of 15% on linux) because we have less CPU-cache misses. + */ +#define FASTER_DNSSEC_ZONE_NEW_FRM_FP 1 /* Because of L2 cache efficiency */ + +ldns_status +ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, ldns_rdf* origin, + uint32_t ttl, ldns_rr_class ATTR_UNUSED(c), int* line_nr) +{ + ldns_rr* cur_rr; + size_t i; + + ldns_rdf *my_origin = NULL; + ldns_rdf *my_prev = NULL; + + ldns_dnssec_zone *newzone = ldns_dnssec_zone_new(); + /* when reading NSEC3s, there is a chance that we encounter nsecs + for empty nonterminals, whose nonterminals we cannot derive yet + because the needed information is to be read later. in that case + we keep a list of those nsec3's and retry to add them later */ + ldns_rr_list* todo_nsec3s = ldns_rr_list_new(); + ldns_rr_list* todo_nsec3_rrsigs = ldns_rr_list_new(); + + ldns_status status = LDNS_STATUS_MEM_ERR; + +#ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP + ldns_zone* zone = NULL; + if (ldns_zone_new_frm_fp_l(&zone, fp, origin,ttl, c, line_nr) + != LDNS_STATUS_OK) goto error; +#else + uint32_t my_ttl = ttl; +#endif + + if (!newzone || !todo_nsec3s || !todo_nsec3_rrsigs ) goto error; + + if (origin) { + if (!(my_origin = ldns_rdf_clone(origin))) goto error; + if (!(my_prev = ldns_rdf_clone(origin))) goto error; + } + +#ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP + if (ldns_dnssec_zone_add_rr(newzone, ldns_zone_soa(zone)) + != LDNS_STATUS_OK) goto error; + + for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) { + cur_rr = ldns_rr_list_rr(ldns_zone_rrs(zone), i); + status = LDNS_STATUS_OK; +#else + while (!feof(fp)) { + status = ldns_rr_new_frm_fp_l(&cur_rr, fp, &my_ttl, &my_origin, + &my_prev, line_nr); + +#endif + switch (status) { + case LDNS_STATUS_OK: + + status = ldns_dnssec_zone_add_rr(newzone, cur_rr); + if (status == + LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND) { + + if (rr_is_rrsig_covering(cur_rr, + LDNS_RR_TYPE_NSEC3)){ + ldns_rr_list_push_rr(todo_nsec3_rrsigs, + cur_rr); + } else { + ldns_rr_list_push_rr(todo_nsec3s, + cur_rr); + } + } else if (status != LDNS_STATUS_OK) + goto error; + + break; + + + case LDNS_STATUS_SYNTAX_EMPTY: /* empty line was seen */ + case LDNS_STATUS_SYNTAX_TTL: /* the ttl was set*/ + case LDNS_STATUS_SYNTAX_ORIGIN: /* the origin was set*/ + break; + + case LDNS_STATUS_SYNTAX_INCLUDE:/* $include not implemented */ + status = LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL; + break; + + default: + goto error; + } + } + + if (ldns_rr_list_rr_count(todo_nsec3s) > 0) { + (void) ldns_dnssec_zone_add_empty_nonterminals(newzone); + for (i = 0; i < ldns_rr_list_rr_count(todo_nsec3s); i++) { + cur_rr = ldns_rr_list_rr(todo_nsec3s, i); + status = ldns_dnssec_zone_add_rr(newzone, cur_rr); + } + for (i = 0; i < ldns_rr_list_rr_count(todo_nsec3_rrsigs); i++){ + cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i); + status = ldns_dnssec_zone_add_rr(newzone, cur_rr); + } + } else if (ldns_rr_list_rr_count(todo_nsec3_rrsigs) > 0) { + for (i = 0; i < ldns_rr_list_rr_count(todo_nsec3_rrsigs); i++){ + cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i); + status = ldns_dnssec_zone_add_rr(newzone, cur_rr); + } + } + + ldns_rr_list_free(todo_nsec3_rrsigs); + ldns_rr_list_free(todo_nsec3s); + + if (z) { + *z = newzone; + } else { + ldns_dnssec_zone_free(newzone); + } + + return LDNS_STATUS_OK; + +error: +#ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP + if (zone) { + ldns_zone_free(zone); + } +#endif + if (my_origin) { + ldns_rdf_deep_free(my_origin); + } + if (my_prev) { + ldns_rdf_deep_free(my_prev); + } + if (newzone) { + ldns_dnssec_zone_free(newzone); + } + return status; +} + +ldns_status +ldns_dnssec_zone_new_frm_fp(ldns_dnssec_zone** z, FILE* fp, ldns_rdf* origin, + uint32_t ttl, ldns_rr_class ATTR_UNUSED(c)) +{ + return ldns_dnssec_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL); +} + +void +ldns_dnssec_name_node_free(ldns_rbnode_t *node, void *arg) { + (void) arg; + ldns_dnssec_name_free((ldns_dnssec_name *)node->data); + LDNS_FREE(node); +} + +void +ldns_dnssec_name_node_deep_free(ldns_rbnode_t *node, void *arg) { + (void) arg; + ldns_dnssec_name_deep_free((ldns_dnssec_name *)node->data); + LDNS_FREE(node); +} + +void +ldns_dnssec_zone_free(ldns_dnssec_zone *zone) +{ + if (zone) { + if (zone->names) { + /* destroy all name structures within the tree */ + ldns_traverse_postorder(zone->names, + ldns_dnssec_name_node_free, + NULL); + LDNS_FREE(zone->names); + } + LDNS_FREE(zone); + } +} + +void +ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone) +{ + if (zone) { + if (zone->names) { + /* destroy all name structures within the tree */ + ldns_traverse_postorder(zone->names, + ldns_dnssec_name_node_deep_free, + NULL); + LDNS_FREE(zone->names); + } + LDNS_FREE(zone); + } +} + +/* use for dname comparison in tree */ +int +ldns_dname_compare_v(const void *a, const void *b) { + return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b); +} + +#ifdef HAVE_SSL +ldns_rbnode_t * +ldns_dnssec_zone_find_nsec3_original(ldns_dnssec_zone *zone, + ldns_rr *rr) { + ldns_rbnode_t *current_node = ldns_rbtree_first(zone->names); + ldns_dnssec_name *current_name; + ldns_rdf *hashed_name; + + hashed_name = ldns_dname_label(ldns_rr_owner(rr), 0); + + while (current_node != LDNS_RBTREE_NULL) { + current_name = (ldns_dnssec_name *) current_node->data; + if (!current_name->hashed_name) { + current_name->hashed_name = + ldns_nsec3_hash_name_frm_nsec3(rr, current_name->name); + } + if (ldns_dname_compare(hashed_name, + current_name->hashed_name) + == 0) { + ldns_rdf_deep_free(hashed_name); + return current_node; + } + current_node = ldns_rbtree_next(current_node); + } + ldns_rdf_deep_free(hashed_name); + return NULL; +} + +ldns_status +ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr) +{ + ldns_status result = LDNS_STATUS_OK; + ldns_dnssec_name *cur_name; + ldns_rbnode_t *cur_node; + ldns_rr_type type_covered = 0; + + if (!zone || !rr) { + return LDNS_STATUS_ERR; + } + + if (!zone->names) { + zone->names = ldns_rbtree_create(ldns_dname_compare_v); + if(!zone->names) return LDNS_STATUS_MEM_ERR; + } + + /* we need the original of the hashed name if this is + an NSEC3, or an RRSIG that covers an NSEC3 */ + if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) { + type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)); + } + if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 || + type_covered == LDNS_RR_TYPE_NSEC3) { + cur_node = ldns_dnssec_zone_find_nsec3_original(zone, + rr); + if (!cur_node) { + return LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND; + } + } else { + cur_node = ldns_rbtree_search(zone->names, ldns_rr_owner(rr)); + } + + if (!cur_node) { + /* add */ + cur_name = ldns_dnssec_name_new_frm_rr(rr); + if(!cur_name) return LDNS_STATUS_MEM_ERR; + cur_node = LDNS_MALLOC(ldns_rbnode_t); + if(!cur_node) { + ldns_dnssec_name_free(cur_name); + return LDNS_STATUS_MEM_ERR; + } + cur_node->key = ldns_rr_owner(rr); + cur_node->data = cur_name; + (void)ldns_rbtree_insert(zone->names, cur_node); + } else { + cur_name = (ldns_dnssec_name *) cur_node->data; + result = ldns_dnssec_name_add_rr(cur_name, rr); + } + + if (result != LDNS_STATUS_OK) { + fprintf(stderr, "error adding rr: "); + ldns_rr_print(stderr, rr); + } + + /*TODO ldns_dnssec_name_print_names(stdout, zone->names, 0);*/ + if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) { + zone->soa = cur_name; + } + + return result; +} +#endif /* HAVE_SSL */ + +void +ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt, + ldns_rbtree_t *tree, + bool print_soa) +{ + ldns_rbnode_t *node; + ldns_dnssec_name *name; + + node = ldns_rbtree_first(tree); + while (node != LDNS_RBTREE_NULL) { + name = (ldns_dnssec_name *) node->data; + ldns_dnssec_name_print_soa_fmt(out, fmt, name, print_soa); + if ((fmt->flags & LDNS_COMMENT_LAYOUT)) + fprintf(out, ";\n"); + node = ldns_rbtree_next(node); + } +} + +void +ldns_dnssec_zone_names_print(FILE *out, ldns_rbtree_t *tree, bool print_soa) +{ + ldns_dnssec_zone_names_print_fmt(out, ldns_output_format_default, + tree, print_soa); +} + +void +ldns_dnssec_zone_print_fmt(FILE *out, const ldns_output_format *fmt, + ldns_dnssec_zone *zone) +{ + if (zone) { + if (zone->soa) { + if ((fmt->flags & LDNS_COMMENT_LAYOUT)) { + fprintf(out, ";; Zone: "); + ldns_rdf_print(out, ldns_dnssec_name_name( + zone->soa)); + fprintf(out, "\n;\n"); + } + ldns_dnssec_rrsets_print_fmt(out, fmt, + ldns_dnssec_name_find_rrset( + zone->soa, + LDNS_RR_TYPE_SOA), + false); + if ((fmt->flags & LDNS_COMMENT_LAYOUT)) + fprintf(out, ";\n"); + } + + if (zone->names) { + ldns_dnssec_zone_names_print_fmt(out, fmt, + zone->names, false); + } + } +} + +void +ldns_dnssec_zone_print(FILE *out, ldns_dnssec_zone *zone) +{ + ldns_dnssec_zone_print_fmt(out, ldns_output_format_default, zone); +} + +ldns_status +ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone) +{ + ldns_dnssec_name *new_name; + ldns_rdf *cur_name; + ldns_rdf *next_name; + ldns_rbnode_t *cur_node, *next_node, *new_node; + + /* for the detection */ + uint16_t i, cur_label_count, next_label_count; + uint16_t soa_label_count = 0; + ldns_rdf *l1, *l2; + int lpos; + + if (!zone) { + return LDNS_STATUS_ERR; + } + if (zone->soa && zone->soa->name) { + soa_label_count = ldns_dname_label_count(zone->soa->name); + } + + cur_node = ldns_rbtree_first(zone->names); + while (cur_node != LDNS_RBTREE_NULL) { + next_node = ldns_rbtree_next(cur_node); + + /* skip glue */ + while (next_node != LDNS_RBTREE_NULL && + next_node->data && + ((ldns_dnssec_name *)next_node->data)->is_glue + ) { + next_node = ldns_rbtree_next(next_node); + } + + if (next_node == LDNS_RBTREE_NULL) { + next_node = ldns_rbtree_first(zone->names); + } + + cur_name = ((ldns_dnssec_name *)cur_node->data)->name; + next_name = ((ldns_dnssec_name *)next_node->data)->name; + cur_label_count = ldns_dname_label_count(cur_name); + next_label_count = ldns_dname_label_count(next_name); + + /* Since the names are in canonical order, we can + * recognize empty non-terminals by their labels; + * every label after the first one on the next owner + * name is a non-terminal if it either does not exist + * in the current name or is different from the same + * label in the current name (counting from the end) + */ + for (i = 1; i < next_label_count - soa_label_count; i++) { + lpos = (int)cur_label_count - (int)next_label_count + (int)i; + if (lpos >= 0) { + l1 = ldns_dname_clone_from(cur_name, (uint8_t)lpos); + } else { + l1 = NULL; + } + l2 = ldns_dname_clone_from(next_name, i); + + if (!l1 || ldns_dname_compare(l1, l2) != 0) { + /* We have an empty nonterminal, add it to the + * tree + */ + new_name = ldns_dnssec_name_new(); + if (!new_name) { + return LDNS_STATUS_MEM_ERR; + } + new_name->name = ldns_dname_clone_from(next_name, + i); + if (!new_name->name) { + ldns_dnssec_name_free(new_name); + return LDNS_STATUS_MEM_ERR; + } + new_name->name_alloced = true; + new_node = LDNS_MALLOC(ldns_rbnode_t); + if (!new_node) { + ldns_dnssec_name_free(new_name); + return LDNS_STATUS_MEM_ERR; + } + new_node->key = new_name->name; + new_node->data = new_name; + (void)ldns_rbtree_insert(zone->names, new_node); + } + ldns_rdf_deep_free(l1); + ldns_rdf_deep_free(l2); + } + + /* we might have inserted a new node after + * the current one so we can't just use next() + */ + if (next_node != ldns_rbtree_first(zone->names)) { + cur_node = next_node; + } else { + cur_node = LDNS_RBTREE_NULL; + } + } + return LDNS_STATUS_OK; +} + +bool +ldns_dnssec_zone_is_nsec3_optout(ldns_dnssec_zone* zone) +{ + ldns_rr* nsec3; + ldns_rbnode_t* node; + + if (ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_NSEC3PARAM)) { + node = ldns_rbtree_first(zone->names); + while (node != LDNS_RBTREE_NULL) { + nsec3 = ((ldns_dnssec_name*)node->data)->nsec; + if (nsec3 &&ldns_rr_get_type(nsec3) + == LDNS_RR_TYPE_NSEC3 && + ldns_nsec3_optout(nsec3)) { + return true; + } + node = ldns_rbtree_next(node); + } + } + return false; +} diff --git a/doc/API-header.xml b/doc/API-header.xml new file mode 100644 index 00000000000..a4cd081bee6 --- /dev/null +++ b/doc/API-header.xml @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + +LibDNS API + + NLnet Labs +

+ + Kruislaan 419 + Amsterdam + 1098 VA + The Netherlands + + miek@nlnetlabs.nl + http://www.nlnetlabs.nl +
+ + + NLnet Labs +
+ + Kruislaan 419 + Amsterdam + 1098 VA + The Netherlands + + jelte@nlnetlabs.nl + http://www.nlnetlabs.nl +
+
+ + NLnet Labs +
+ + Kruislaan 419 + Amsterdam + 1098 VA + The Netherlands + + erik@nlnetlabs.nl + http://www.nlnetlabs.nl +
+
+ +DNS +Elite +Hacking + + +A small abstract will come here, TBD. + + + + + + +
+ +LibDNS (or lDNS) is modelled after the Net::DNS perl library. It has +been shown that Net::DNS can be used vefficiently for +programming DNS aware applications. We want to bring the same +level of efficiency to C programmers. + + +The lDNS API consist of two layers. The top-layer, this is +what is actually exported to the application via the library. And the +bottom-layer, this is what lDNS needs to compile and function. + +
+ +
+ +Short intermezzo detailing differences with other libraries. Most important +ones are the libc resolver interface (from BIND8) and the lwres_ interface +from BIND9. + +
+ +
+ +At its lowest level lDNS is only dependent on libc. It uses a +few networking systems calls; socket, bind, send/recv and friends. + + +Further more it is to be expected that lDNS will depend on OpenSSL for +its cryptography. + + +As said, lDNS is modelled after Net::DNS, therefor its application API +looks very much like the one used for Net::DNS. Some modification are made +ofcourse, because not all functionality of Perl can be caught in C. + + + +This API document was written by carefully looking at the documentation +contained in the Net::DNS Perl module. + +
diff --git a/doc/API.xml b/doc/API.xml new file mode 100644 index 00000000000..07007b9a295 --- /dev/null +++ b/doc/API.xml @@ -0,0 +1,462 @@ + + + + + + + + + + + + + + +LibDNS API + + NLnet Labs +
+ + Kruislaan 419 + Amsterdam + 1098 VA + The Netherlands + + miek@nlnetlabs.nl + http://www.nlnetlabs.nl +
+
+ + NLnet Labs +
+ + Kruislaan 419 + Amsterdam + 1098 VA + The Netherlands + + jelte@nlnetlabs.nl + http://www.nlnetlabs.nl +
+
+ + NLnet Labs +
+ + Kruislaan 419 + Amsterdam + 1098 VA + The Netherlands + + erik@nlnetlabs.nl + http://www.nlnetlabs.nl +
+
+ +DNS +Elite +Hacking + + +A small abstract will come here, TBD. + + +
+ + + +
+ +LibDNS (or lDNS) is modelled after the Net::DNS perl library. It has +been shown that Net::DNS can be used vefficiently for +programming DNS aware applications. We want to bring the same +level of efficiency to C programmers. + + +The lDNS API consist of two layers. The top-layer, this is +what is actually exported to the application via the library. And the +bottom-layer, this is what lDNS needs to compile and function. + +
+ +
+ +Short intermezzo detailing differences with other libraries. Most important +ones are the libc resolver interface (from BIND8) and the lwres_ interface +from BIND9. + +
+ +
+ +At its lowest level lDNS is only dependent on libc. It uses a +few networking systems calls; socket, bind, send/recv and friends. + + +Further more it is to be expected that lDNS will depend on OpenSSL for +its cryptography. + + +As said, lDNS is modelled after Net::DNS, therefor its application API +looks very much like the one used for Net::DNS. Some modification are made +ofcourse, because not all functionality of Perl can be caught in C. + + + +This API document was written by carefully looking at the documentation +contained in the Net::DNS Perl module. + +
+ +
+ +The rdf structure, the RData Field, is a type that contains the different +types in the rdata of an RR. Consider the following example: + +example.com. IN MX 10 mx.example.com. + +The "10 mx.example.com." is the rdata in this case. It consists of two +fields, "10" and "mx.example.com". These have the types (in this case) +LDNS_RDF_TYPE_INT8 and LDNS_RDF_TYPE_DNAME. + + +The following functions operate on this structure. + + + + +Create a new rdf structure. Return a pointer to it. + + +Get the size of a rdf structure. + + +Set the size of a rdf structure. + + +Set the type of a rdf structure. + + +Get the type of a rdf structure. + + +Set the (binary/network order) data of a rdf structure. + + +Get a pointer to the data in a rdf structure. + + +Free a rdf structure. + + +Create a new rdf structure from a string and a specific rdf_type. +The type is needed to perform the correct conversion. + + + +
+ +
+ +These functions operate on ldns_rr structures. + + + + +Returns a pointer to the newly created ldns_rr structure. + + +Prints the record to the stream s. + + +Returns a pointer to a ldns_buffer containing with string containing +RR-specific data. + + +Returns the record's owner name as a ldns_rdf type. + + +Returns the record's type. + + +Returns the record's class. + + +Returns the record's time-to-live (TTL). + + + + + +TODO the 'set' functions of the 'get' + +
+ +
+ +In the DNS the atomic data type is an RRset. This is a list +of RRs with the same ownername, type and class. Net::DNS doesn't +have rrsets as a seperate object. + + +In lDNS we have the ldns_rr_list, which just holds a bunch of RR's. +No specific check are made on the RRs that can be put in such a list. +Special wrapper functions exist which allow the usage of ldns_rr_list +of real (RFC compliant) RR sets. + + +TODO: See rr.c + +
+ +
+ + + +Create a new resolver structure and return the pointer to that. + + +Returns the version of lDNS. + + +Returns a ldns_pkt representing the MX records +for the specified dname. Function is documented differently in Net::DNS. +Do we need stuff like this?? XXX + + + Set the default domain for this resolver. This domain is added + when a query is made with a name without a trailing dot. + + + + +Add a new nameserver to the resolver. These nameservers are queried + when a search() or query() is done. + + + + Add a domain to the searchlist of a resolver. + + + Perform a query. Try all the nameservers in the *res structure. Apply + the search list. And default domain. +If type is NULL it defaults to 'A', +If class is NULL it default to 'IN'. + + +Perform a query. Only the default domain is added. +If type is NULL it defaults to 'A', +If class is NULL it default to 'IN'. + + +No search list nor default domain is applied. Return a pointer to a ldns_pkt +structure with the information from the nameserver. +If type is NULL it defaults to 'A', +If class is NULL it default to 'IN'. + + + + +TODO XX Gazillion helper functions to set port, src-port, etc. etc. + +
+ +
+ +A packet structure (ldns_pkt) has five sections: + +The header section, a ldns_hdr structure. +The question section, a ldns_rr_list structure. +The answer section, a ldns_rr_list structure. +The authority section, a ldns_rr_list structure. +The additional section, a ldns_rr_list structure. + + + + + +ldns_hdr represents the header section of a DNS packet. + + +A list of RRs in the Question section of a DNS packet. + + +A list of RRs in the Question section of a DNS packet. + + +A list of RRs in the Question section of a DNS packet. + + +A list of RRs in the Question section of a DNS packet. + + + + + + + +Creates a new empty packet. + + +Returns the packet data in binary format, suitable for sending to a +nameserver. [XXX, suitable for sending to a NS?] + + +Returns a ldns_hdr structure representing the header section of +the packet. + + + Returns a pointer to a ldns_rr_list representing the question section +of the packet. + + + Returns a pointer to a ldns_rr_list representing the answer section of +the packet. + + + +Returns a pointer to a ldns_rr_list representing the authority section +of the packet. + + + +Returns a pointer to a ldns_rr_list of representing the additional +section of the packet. + + + +Prints the packet data on the standard output in an ASCII format similar +to that used in DNS zone files. See RFC1035. + + + +Returns a ldns_buffer containing the string representation of the packet. + + + +Returns the IP address from which we received this packet. User-created +packets will return NULL. + + + +Returns the size of the packet in bytes as it was received from a +nameserver. User-created packets will return 0. [XXX +user-created??] + + + +Adds *rr to the specified section of the packet. Return LDNS_STATUS_OK +on success, LDNS_STATUS_ERR otherwise. + + + +Adds *rr to the specified section of the packet provided that the RR +does not already exist in the packet. Return LDNS_STATUS_OK +on success, LDNS_STATUS_ERR otherwise. + + +Removes a RR from the specified section of the packet. Returns NULL if +no RR's could be popped. + + +Retrieve all RRs in a packet matching certain criteria. XXX function needs +to be specified better. + + +Print packet p to stream s. + + + + +
+ +
+ +Some resource records can have special access function no other RR has. +Those are detailed here. XXX TODO don't exist (yet?). + +
+ +
+ +insert your long list here. + +
+ +
+ +A small example, which queries a nameserver on localhost +to diplay the MX records for miek.nl. + + + +
+ +/** + * An example ldns program + * In semi-C code + * + * Setup a resolver + * Query a nameserver + * Print the result + */ + +#include <ldns.h> + +int +main(void) +{ + ldns_resolver *res; + ldns_rdf *default_dom; + ldns_rdf *nameserver; + ldns_rdf *qname; + ldns_pkt *pkt; + + /* init */ + res = ldns_resolver_new(); + if (!res) + return 1; + + /* create a default domain and add it */ + default_dom = ldns_rdf_new_frm_str("miek.nl.", LDNS_RDF_TYPE_DNAME); + nameserver = ldns_rdf_new_frm_str("127.0.0.1", LDNS_RDF_TYPE_A); + + if (ldns_resolver_domain(res, default_dom) != LDNS_STATUS_OK) + return 1; + if (ldns_resolver_nameserver_push(res, nameserver) != LDNS_STATUS_OK) + return 1; + + /* setup the question */ + qname = ldns_rdf_new_frm_str("www", LDNS_RDF_TYPE_DNAME); + + /* fire it off. "miek.nl." will be added */ + pkt = ldns_resolver_query(res, qname, LDNS_RR_TYPE_MX, NULL); + + /* print the resulting pkt to stdout */ + ldns_pkt_print(stdout, pkt); + + return 0; +} + +
+
+
+ +
+ + +
diff --git a/doc/CodingStyle b/doc/CodingStyle new file mode 100644 index 00000000000..a326e5c3f99 --- /dev/null +++ b/doc/CodingStyle @@ -0,0 +1,64 @@ +The libdns coding style guide + +* Use of tabs (real tabs, 8 positions long) +* Spaces only after comma's, and in between operators. + And after keywords (if, while, for) +* Underscores to make long names readable +* prefix (exported) identifiers with 'ldns_' +* no unneeded parentheses after 'return' +* always curly brackets in if-statements +* use defines for (weird) constants, and masks +* type 'bool', constants 'true'/'false'. Don't compare bools for + equality. +* always use LDNS_MALLOC/FREE etc, or the new/free/deep_free functions +* buffer can scale, so don't alloc the max size, but the min size +* make lint (uses splint) is your friend + + +* Return values: + - status code (structure to fill is usually passed as a first argument) + - new/pointer: return pointer or NULL on error + - 'read' functions: ldns_status wire2thing(uint8_t *p, size_t max, + size_t pos, *thing); + - void functions like ldns_rr_free + - bool functions + +* Parameter sequence: (dest, [dest_meta, ] src, [src_meta] etc) +* structure/union field names start with _ when "private" +* enum for rcode, opcode, types etc, + example: + enum ldns_rcode { + LDNS_RCODE_OK = 0, + ... = ., + LDNS_RCODE_FIRST = LDNS_RCODE_OK, + LDNS_RCODE_LAST = 15, + LDNS_RCODE_COUNT = LDNS_RCODE_LAST + 1 + } +* Everything by reference, all data structures an optional _clone() function +* arrays: ps[] with size_t p_count for the number of elements +* _size for size in bytes +* _free and _clone copies perform deep free/copy. + +* Standard abbreviations, don't abbreviate other names: + + id = identity + rr = resource record + rrset = resource record set + rdata = resource data + rdf = resource data field + rcode = result code + qr = query/resource bit + aa = authoritative answer + tc = truncated + rd = recursion disabled + cd = checking disabled + ra = recursion available + ad = authentic data + qdcount = question section count + ancount = answer section count + nscount = authority section count + arcount = additional section count + +ldns- +* use exit(EXIT_FAILURE)/ exit(SUCCES) +* diff --git a/doc/TODO b/doc/TODO new file mode 100644 index 00000000000..2d2e9dcdb33 --- /dev/null +++ b/doc/TODO @@ -0,0 +1,22 @@ +TODO + +Features: +* Multi-line zone file parsing +* Configure option for not printing DNSSEC RR comments +* HMAC and MD5 without OpenSSL +* HIP RR support +* Parse 'search' attribute in /etc/resolv.conf +* Make use of automake (Bug #173) +* ./configure --with-tools --with-drill (Bug #264) +* Drill: print appropriate DS RRs (relates to Bug #355) +* ldns-signzone optout to be really optout +* Compression when generating wireformat. Preferably with a configurable + policy: refer only backwards, case sensitivity, only refer to other owner + names, etc. + +Bugfixes: +* Bug #279: fix return values for net.h functions, and related: make return + values for functions that cannot return memory-failure today. Needs medium + version increase because of API change. +* Long out-standing packaging bugs (debian) +* Lazy ABI diff --git a/doc/design.dox b/doc/design.dox new file mode 100644 index 00000000000..a4cbeadb8f9 --- /dev/null +++ b/doc/design.dox @@ -0,0 +1,124 @@ +/** \page design Design + +The following image shows the various modules of libdns and their +functionality. + +\image html libdnsoverview.png + +\section central_structures Central structures + + - \ref ldns_pkt A DNS Packet, which can contain a query, answers, and additional information. + - \ref ldns_rr A Resource Record, which holds a bit of information about a specific domain name. + - \ref ldns_rdf An RDATA field, every Resource Record contains one or more RDATA fields, depending on the type of RR. These are the 'basic types' of DNS data. + - \ref ldns_rr_list A list of resource records + - \ref ldns_zone A representation of a DNS Zone. + +The actual structure definitions are named \c ldns_struct_ which are all typedeffed to \c ldns_ + + +A DNS Resource record looks like this: + +
+nlnetlabs.nl.   600     IN      MX             10    open.nlnetlabs.nl.
+ \              \       \       \              \                     /
+  owner          ttl     class   type           \        rdf[]      /
+  (rdf)     (uint32_t) (rr_class) (rr_type)
+                                                 10          := rdf[0]
+                                                 open.nlnetlabs.nl. := rdf[1]
+
+ +* Owner: +The owner name is put in an \c ldns_rdf structure, which is a normal rdata field but always +has the type LDNS_RDF_TYPE_DNAME. + +An \ref ldns_rdf structure has 3 members; the size, the type of rdata and a void * +pointer to the data. The data is always in uncompressed wireformat. + +The RSH (rdata) is put in an array of rdf's (in this case 2). + +The entire resource record is put in a RR structure, which has +the fields described above (under the RR): + - owner (nlnetlabs.nl.) + - ttl (600) + - class (LDNS_RR_CLASS_IN: 'IN') + - type (LDNS_RR_TYPE_MX: 'MX') + - rd_count (2) + - rdata_fields[rd_count] + - rdf[0] (10) + - rdf[1] (open.nlnetlabs.nl.) + +* RR list structure: +An RR list structure is simply a structure with a counter +and an array of RR structures. Different kinds of RR's can +be grouped together this way. + +* RRset structure: +An RRset structure is an RR list structure, but its accessor +function checks if the \c ldns_rr structures in there are: + - from the same type + - have the same TTL + - have the same ownername + +This is the RFC definition of an RRset. + +* pkt structure: +A pkt structure consists out of a header structure where +packet specific flags are kept, TC, RD, IP from the server which +sent the packet, etc. +Further more it is divided in 4 sections: question, authority, answer +and additional. + +All four sections have the type RRlist that simply hold a list of RR's + + +\section wire_module Wire module and central structures Interface + +As the WIRE module takes care of the compression/decompression +it needs a buffer which holds all the binary DNS data. +All functions will operate on such a buffer to extract specific +information which is then stored in RR structures. + + +\section resolver_module Resolver module and central structures Interface + +The resolver module always returns a pkt structure. Either with +the answer or a SERVFAIL pkt. + +The exact function-call parameters have not yet been +decided on. + +Also the resolver module will need to access some of the +to_wire and from_wire function to creates ldn_pkt's from +the data it receives (arrow not drawn). + + +\section str_module str module and central structures Interface + +Convert to and from strings. This module could be used +to read in a zone file (list of RRs) and convert the text strings to +the format used by ldns. Or the other way around. + + +\section net_module Net module and resolver module interface + +The resolver module will get a packet and will mold it so that +it can be sent off to a nameserver. +It might need to interface with the wire module (arrow not drawn). + +\section Net module and OS/libc interface +OS/network calls will be used here. The Net module is the only part of +the library where the underlying OS matters. + +\section Client program ldns interface +Any client program will have access to +- Wire module +- Central structures +- Resolver module +- str module (arrow not drawn in the above figure) + +\section dnssec_module DNSSEC module +The DNSSEC types are handled in the RR module, but the crypto +routines are contained in this module. This module will depend +on OpenSSL for the crypto routines. + +*/ diff --git a/doc/dns-lib-implementations b/doc/dns-lib-implementations new file mode 100644 index 00000000000..18d01afb30f --- /dev/null +++ b/doc/dns-lib-implementations @@ -0,0 +1,56 @@ +http://www.posadis.org/projects/poslib.php +Poslib DNS library - Default branch + +http://www.posadis.org/poslib?DokuWiki=2b00f9da090fb9d4ad3d6e98b9c2f61f + +Poslib is the C++ library for applications using the Domain Name System +that is used by all Posadis tools, including the Posadis DNS server and the +Zoneedit and Dnsquery tools. It consists of a library for creating client +applications using DNS, and a server library for DNS servers. + + +FireDNS Library +http://firestuff.org/projects/firedns +FireDNS Library +--------------- +(c) 2002 Ian Gulliver under the GNU Public License, Version 2. +See GPL for more details. + +From libfiredns(3): + +libfiredns is a library for handling asynchronous DNS +requests. It provides a very simple interface for sending +requests and parsing reponses, as well as low-timeout +blocking functions. libfiredns functions have much lower +timeouts than the stock functions and tend to be faster +because they send requests to all configured system +nameservers at the same time. + +If you have questions or comments, you can reach me at +ian@penguinhosting.net. + + + +skadns + + Skadns is Kind of an Asynchronous DNS client software. + + * Kind of: it's small. Really small. But it just works. + * Asynchronous: all DNS operations are non-blocking. + * DNS client software: it's a DNS client, what you may know as a "stub resolver". To perform full DNS resolution, you will still need a full resolver like dnscache. + + Similar work + + * ares is an asynchronous DNS resolver library with a nice interface + * and more configuration options than skadns (and a very reasonable + * size). Use it if you find that skadns lacks configurability (you + * shouldn't need more than it provides, but well, you're the user). + * Yet it doesn't hide the DNS internals as opaquely as skadns does, + * giving you a bunch of fds to select() on instead of just one. + * adns works fine, and is small for a GNU project. Impressive. But + * the interface is still too complex and much too generic - the + * usual problems with GNU software. + + +ADNS; documentation scares - is it still active +simular aims - different ways diff --git a/doc/doxyparse.pl b/doc/doxyparse.pl new file mode 100755 index 00000000000..526c617101b --- /dev/null +++ b/doc/doxyparse.pl @@ -0,0 +1,288 @@ +#!/usr/bin/env perl + +# Doxygen is usefull for html documentation, but sucks +# in making manual pages. Still tool also parses the .h +# files with the doxygen documentation and creates +# the man page we want +# +# 2 way process +# 1. All the .h files are processed to create in file in which: +# filename | API | description | return values +# are documented +# 2. Another file is parsed which states which function should +# be grouped together in which manpage. Symlinks are also created. +# +# With this all in place, all documentation should be autogenerated +# from the doxydoc. + +use Getopt::Std; + +my $state; +my $description; +my $struct_description; +my $key; +my $return; +my $param; +my $api; +my $const; + +my %description; +my %api; +my %return; +my %options; +my %manpages; +my %see_also; + +my $BASE="doc/man"; +my $MAN_SECTION = "3"; +my $MAN_HEADER = ".TH ldns $MAN_SECTION \"30 May 2006\"\n"; +my $MAN_MIDDLE = ".SH AUTHOR +The ldns team at NLnet Labs. Which consists out of +Jelte Jansen and Miek Gieben. + +.SH REPORTING BUGS +Please report bugs to ldns-team\@nlnetlabs.nl or in +our bugzilla at +http://www.nlnetlabs.nl/bugs/index.html + +.SH COPYRIGHT +Copyright (c) 2004 - 2006 NLnet Labs. +.PP +Licensed under the BSD License. There is NO warranty; not even for +MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. +"; +my $MAN_FOOTER = ".SH REMARKS +This manpage was automaticly generated from the ldns source code by +use of Doxygen and some perl. +"; + +getopts("m:",\%options); +# if -m manpage file is given process that file +# parse the file which tells us what manpages go together +my $functions, $see_also; +if (defined $options{'m'}) { + # process + open(MAN, "<$options{'m'}") or die "Cannot open $options{'m'}"; + # it's line based: + # func1, func2, .. | see_also1, see_also2, ... + while() { + chomp; + if (/^#/) { next; } + if (/^$/) { next; } + ($functions, $see_also) = split /[\t ]*\|[\t ]*/, $_; + #print "{$functions}\n"; + #print "{$see_also}\n"; + my @funcs = split /[\t ]*,[\t ]*/, $functions; + my @also = split /[\t ]*,[\t ]*/, $see_also; + $manpages{$funcs[0]} = \@funcs; + $see_also{$funcs[0]} = \@also; + #print "[", $funcs[0], "]\n"; + } + close(MAN); +} else { + print "Need -m file to process the .h files\n"; + exit 1; +} + +# 0 - somewhere in the file +# 1 - in a doxygen par +# 2 - after doxygen, except funcion + +# create our pwd +mkdir "doc"; +mkdir "doc/man"; +mkdir "doc/man/man$MAN_SECTION"; + +$state = 0; +my $i; +my @lines = ; +my $max = @lines; + +while($i < $max) { + $typedef = ""; + if ($lines[$i] =~ /^typedef struct/ and $lines[$i + 1] =~ /^struct/) { + # move typedef to below struct + $typedef = $lines[$i]; + $j = $i; + while ($lines[$j] !~ /}/) { + $lines[$j] = $lines[$j+1]; + $j++; + } + $lines[$j] = $lines[$j+1]; + $lines[$j + 1] = $typedef; + } + + $cur_line = $lines[$i]; + chomp($cur_line); + if ($cur_line =~ /^\/\*\*[\t ]*$/) { + # /** Seen + #print "Comment seen! [$cur_line]\n"; + $state = 1; + undef $description; + undef $struct_description; + $i++; + next; + } + if ($cur_line =~ /\*\// and $state == 1) { + #print "END Comment seen!\n"; + $state = 2; + $i++; + next; + } + + if ($state == 1) { + # inside doxygen + $cur_line =~ s/\\/\\\\/g; + $cur_line =~ s/^[ \t]*\* ?//; + $description = $description . "\n" . $cur_line; + #$description = $description . "\n.br\n" . $cur_line; + } + if ($state == 2 and $cur_line =~ /const/) { + # the const word exists in the function call + #$const = "const"; + #s/[\t ]*const[\t ]*//; + } else { + #undef $const; + } + + if ($cur_line =~ /^INLINE/) { + $cur_line =~ s/^INLINE\s*//; + while ($cur_line !~ /{/) { + $i++; + $cur_line .= " ".$lines[$i]; + $cur_line =~ s/\n//; + } + $cur_line =~ s/{/;/; + } + + if ($cur_line =~ /^[^#*\/ ]([\w\*]+)[\t ]+(.*?)[({](.*)\s*/ and $state == 2) { + while ($cur_line !~ /\)\s*;/) { + $i++; + $cur_line .= $lines[$i]; + chomp($cur_line); + $cur_line =~ s/\n/ /g; + $cur_line =~ s/\s\s*/ /g; + } + $cur_line =~ /([\w\* ]+)[\t ]+(.*?)\((.*)\)\s*;/; + # this should also end the current comment parsing + $return = $1; + $key = $2; + $api = $3; + # sometimes the * is stuck to the function + # name instead to the return type + if ($key =~ /^\*/) { + #print"Name starts with *\n"; + $key =~ s/^\*//; + if (defined($const)) { + $return = $const . " " . $return . '*'; + } else { + $return = $return . '*'; + } + } + $description =~ s/\\param\[in\][ \t]*([\*\w]+)[ \t]+/.br\n\\fB$1\\fR: /g; + $description =~ s/\\param\[out\][ \t]*([\*\w]+)[ \t]+/.br\n\\fB$1\\fR: /g; + $description =~ s/\\return[ \t]*/.br\nReturns /g; + + $description{$key} = $description; + $api{$key} = $api; + $return{$key} = $return; + undef $description; + undef $struct_description; + $state = 0; + } elsif ($state == 2 and ( + $cur_line =~ /^typedef\sstruct\s(\w+)\s(\w+);/ or + $cur_line =~ /^typedef\senum\s(\w+)\s(\w+);/)) { + $struct_description .= "\n.br\n" . $cur_line; + $key = $2; + $struct_description =~ s/\/\*\*\s*(.*?)\s*\*\//\\fB$1:\\fR/g; + $description{$key} = $struct_description; + $api{$key} = "struct"; + $return{$key} = $1; + undef $description; + undef $struct_description; + $state = 0; + } else { + $struct_description .= "\n.br\n" . $cur_line; + } + $i++; +} + +# create the manpages +foreach (keys %manpages) { + $name = $manpages{$_}; + $also = $see_also{$_}; + + $filename = @$name[0]; + $filename = "$BASE/man$MAN_SECTION/$filename.$MAN_SECTION"; + + my $symlink_file = @$name[0] . "." . $MAN_SECTION; + +# print STDOUT $filename,"\n"; + open (MAN, ">$filename") or die "Can not open $filename"; + + print MAN $MAN_HEADER; + print MAN ".SH NAME\n"; + print MAN join ", ", @$name; + print MAN "\n\n"; + print MAN ".SH SYNOPSIS\n"; + + print MAN "#include \n.br\n"; + print MAN "#include \n.br\n"; + + print MAN ".PP\n"; + print MAN "#include \n"; + print MAN ".PP\n"; + + foreach (@$name) { + $b = $return{$_}; + $b =~ s/\s+$//; + if ($api{$_} ne "struct") { + print MAN $b, " ", $_; + print MAN "(", $api{$_},");\n"; + print MAN ".PP\n"; + } + } + + print MAN "\n.SH DESCRIPTION\n"; + foreach (@$name) { + print MAN ".HP\n"; + print MAN "\\fI", $_, "\\fR"; + if ($api{$_} ne "struct") { + print MAN "()"; + } +# print MAN ".br\n"; + print MAN $description{$_}; + print MAN "\n.PP\n"; + } + + print MAN $MAN_MIDDLE; + + if (defined(@$also)) { + print MAN "\n.SH SEE ALSO\n\\fI"; + print MAN join "\\fR, \\fI", @$also; + print MAN "\\fR.\nAnd "; + print MAN "\\fBperldoc Net::DNS\\fR, \\fBRFC1034\\fR, +\\fBRFC1035\\fR, \\fBRFC4033\\fR, \\fBRFC4034\\fR and \\fBRFC4035\\fR.\n"; + } else { + print MAN ".SH SEE ALSO +\\fBperldoc Net::DNS\\fR, \\fBRFC1034\\fR, +\\fBRFC1035\\fR, \\fBRFC4033\\fR, \\fBRFC4034\\fR and \\fBRFC4035\\fR.\n"; + } + + print MAN $MAN_FOOTER; + + # create symlinks + chdir("$BASE/man$MAN_SECTION"); + foreach (@$name) { + print STDERR $_,"\n"; + my $new_file = $_ . "." . $MAN_SECTION; + if ($new_file eq $symlink_file) { + next; + } + #print STDOUT "\t", $new_file, " -> ", $symlink_file, "\n"; + symlink $symlink_file, $new_file; + } + chdir("../../.."); # and back, tricky and fragile... + close(MAN); +} diff --git a/doc/function_manpages b/doc/function_manpages new file mode 100644 index 00000000000..15706fada57 --- /dev/null +++ b/doc/function_manpages @@ -0,0 +1,223 @@ +# first function name will be the real name of the manpage +# other names are aliases (symlinks) +# all functions specified on the same line are included in the +# same manual page. We cannot deal with linebreaks! +# function named after the pipe `|' are put in the "see also" section + +# functions that must be included, separated by commas + +### host2wire.h +# conversion functions +ldns_rr2wire, ldns_pkt2wire, ldns_rdf2wire | ldns_wire2rr, ldns_wire2pkt, ldns_wire2rdf +# lower level conversions, some are from host2str.h +ldns_pkt2buffer_str, ldns_pktheader2buffer_str, ldns_rr2buffer_str, ldns_rr_list2buffer_str, ldns_rdf2buffer_str, ldns_key2buffer_str, ldns_pkt2buffer_wire, ldns_rr2buffer_wire, ldns_rdf2buffer_wire, ldns_rrsig2buffer_wire, ldns_rr_rdata2buffer_wire | ldns_pkt2str, ldns_rr2str, ldns_rdf2str, ldns_rr_list2str, ldns_key2str +### /host2wire.h + +### host2str.h +ldns_rr2str, ldns_pkt2str, ldns_rdf2str, ldns_rr_list2str, ldns_key2str | ldns_rr_print, ldns_rdf_print, ldns_pkt_print, ldns_rr_list_print, ldns_resolver_print, ldns_zone_print +ldns_rr_print, ldns_rdf_print, ldns_pkt_print, ldns_rr_list_print, ldns_resolver_print, ldns_zone_print | ldns_rr2str, ldns_rdf2str, ldns_pkt2str, ldns_rr_list2str, ldns_key2str +### /host2str.h + +### host2str.h +# and even lower +ldns_rdf2buffer_str_a, ldns_rdf2buffer_str_aaaa, ldns_rdf2buffer_str_str, ldns_rdf2buffer_str_b64, ldns_rdf2buffer_str_hex, ldns_rdf2buffer_str_type, ldns_rdf2buffer_str_class, ldns_rdf2buffer_str_alg, ldns_rdf2buffer_str_loc, ldns_rdf2buffer_str_unknown, ldns_rdf2buffer_str_nsap, ldns_rdf2buffer_str_wks, ldns_rdf2buffer_str_nsec, ldns_rdf2buffer_str_period, ldns_rdf2buffer_str_tsigtime, ldns_rdf2buffer_str_apl, ldns_rdf2buffer_str_int16_data, ldns_rdf2buffer_str_int16, ldns_rdf2buffer_str_ipseckey +### /host2str.h + +### wire2host.h +# wirefunctions +ldns_wire2rr, ldns_wire2pkt, ldns_wire2rdf, ldns_wire2dname | ldns_rr2wire, ldns_pkt2wire, ldns_rdf2wire, ldns_dname2wire +ldns_buffer2pkt_wire +### /wire2host.h + +### dname.h +ldns_dname_left_chop, ldns_dname_label_count | ldns_dname +ldns_dname2canonical | ldns_dname +ldns_dname_cat_clone, ldns_dname_cat | ldns_dname +ldns_dname_new, ldns_dname_new_frm_str, ldns_dname_new_frm_data | ldns_dname, ldns_pkt_query_new_frm_str, ldns_rdf_new_frm_str, ldns_rr_new_frm_str +ldns_dname_is_subdomain, ldns_dname_str_absolute, ldns_dname_label | ldns_dname +ldns_dname_compare, ldns_dname_interval | ldns_dname_is_subdomain | ldns_dname +ldns_dname | ldns_dname_left_chop, ldns_dname_label_count, ldns_dname2canonical, ldns_dname_cat, ldns_dname_cat_clone, ldns_dname_new, ldns_dname_new_frm_str, ldns_dname_new_frm_data, ldns_dname_is_subdomain, ldns_dname_str_absolute, ldns_dname_label, ldns_dname_compare, ldns_dname_interval +### /dname.h + +### rdata.h +ldns_rdf, ldns_rdf_type | ldns_rdf_set_size, ldns_rdf_set_type, ldns_rdf_set_data, ldns_rdf_size, ldns_rdf_get_type, ldns_rdf_data, ldns_rdf_compare, ldns_rdf_new, ldns_rdf_clone, ldns_rdf_new_frm_data, ldns_rdf_new_frm_str, ldns_rdf_new_frm_fp, ldns_rdf_free, ldns_rdf_deep_free, ldns_rdf_print, ldns_native2rdf_int8, ldns_native2rdf_int16, ldns_native2rdf_int32, ldns_native2rdf_int16_data, ldns_rdf2native_int8, ldns_rdf2native_int16, ldns_rdf2native_int32, ldns_rdf2native_sockaddr_storage, ldns_rdf2native_time_t, ldns_native2rdf_int8, ldns_native2rdf_int16, ldns_native2rdf_int32, ldns_native2rdf_int16_data, ldns_rdf2native_int8, ldns_rdf2native_int16, ldns_rdf2native_int32, ldns_rdf2native_sockaddr_storage, ldns_rdf2native_time_t, ldns_native2rdf_int8, ldns_native2rdf_int16, ldns_native2rdf_int32, ldns_native2rdf_int16_data, ldns_rdf2native_int8, ldns_rdf2native_int16, ldns_rdf2native_int32, ldns_rdf2native_sockaddr_storage, ldns_rdf2native_time_t +ldns_rdf_set_size, ldns_rdf_set_type, ldns_rdf_set_data | ldns_rdf +ldns_rdf_size, ldns_rdf_get_type, ldns_rdf_data, ldns_rdf_compare | ldns_rdf +ldns_rdf_new, ldns_rdf_clone, ldns_rdf_new_frm_data, ldns_rdf_new_frm_str, ldns_rdf_new_frm_fp, ldns_rdf_free, ldns_rdf_deep_free, ldns_rdf_print | ldns_rdf +ldns_native2rdf_int8, ldns_native2rdf_int16, ldns_native2rdf_int32, ldns_native2rdf_int16_data, ldns_rdf2native_int8, ldns_rdf2native_int16, ldns_rdf2native_int32, ldns_rdf2native_sockaddr_storage, ldns_rdf2native_time_t | ldns_rdf +ldns_rdf_address_reverse | ldns_rdf +ldns_octet | ldns_rdf +# why is this in rdata.h? +ldns_str2period +### /rdata.h + +### higher.h +ldns_get_rr_list_addr_by_name, ldns_get_rr_list_name_by_addr | ldns_rr_list, ldns_rr +ldns_get_rr_list_hosts_frm_fp, ldns_get_rr_list_hosts_frm_file | ldns_rr_list, ldns_rr, ldns_get_rr_list_hosts_frm_fp_l +ldns_get_rr_list_hosts_frm_fp_l | ldns_rr_list +ldns_getaddrinfo +### /higher.h + +# +### dnssec.h +# +ldns_calc_keytag, ldns_verify, ldns_verify_rrsig, ldns_verify_rrsig_dsa, ldns_verify_rrsig_rsasha1, ldns_verify_rrsig_rsamd5, ldns_key_rr2ds, ldns_key_buf2dsa, ldns_key_buf2rsa | ldns_key, ldns_sign_public, ldns_zone_sign, ldns_verify, ldns_verify_rrsig + +# algs +ldns_verify_rrsig_dsa, ldns_verify_rrsig_rsasha1, ldns_verify_rrsig_rsamd5 | ldns_key, ldns_sign_public, ldns_zone_sign, ldns_verify, ldns_verify_rrsig + +# tsig +ldns_pkt_tsig_verify, ldns_pkt_tsig_sign | ldns_key + +# verify +ldns_verify, ldns_verify_rrsig, ldns_verify_rrsig_keylist, ldns_verify_rrsig_keylist_notime, ldns_verify_notime | ldns_verify_rrsig_evp | ldns_verify_rrsig_dsa, ldns_verify_rrsig_rsasha1, ldns_verify_rrsig_rsamd5, ldns_sign_public, ldns_zone_sign, ldns_key + +# convert +ldns_key_buf2dsa, ldns_key_buf2rsa | ldns_key_rr2ds +ldns_key_rr2ds | ldns_key +ldns_create_nsec | ldns_sign_public + +# signing +ldns_sign_public | ldns_sign_public_dsa, ldns_sign_public_rsamd5, ldns_sign_public_rsasha1, ldns_verify, ldns_verify_rrsig, ldns_key +ldns_sign_public_dsa, ldns_sign_public_rsamd5, ldns_sign_public_rsasha1 | ldns_sign_public +ldns_dnssec_zone_sign, ldns_dnssec_zone_sign_nsec3 | ldns_zone_sign, ldns_zone_sign_nsec3 | ldns_sign_public, ldns_key, ldns_init_random +ldns_init_random | ldns_sign_public, ldns_key +ldns_pkt_verify | ldns_verify, ldns_sign_public, ldns_zone_sign + +# new family of dnssec functions +ldns_dnssec_zone, ldns_dnssec_name, ldns_dnssec_rrs, ldns_dnssec_rrsets | ldns_dnssec_zone_new, ldns_dnssec_name_new, ldns_dnssec_rrs_new, ldns_dnssec_rrsets_new +ldns_dnssec_zone_find_rrset, ldns_dnssec_zone_new, ldns_dnssec_zone_free, ldns_dnssec_zone_add_rr, ldns_dnssec_zone_names_print, ldns_dnssec_zone_print, ldns_dnssec_zone_add_empty_nonterminals | ldns_dnssec_zone +ldns_dnssec_name_new, ldns_dnssec_name_new_frm_rr, ldns_dnssec_name_free, ldns_dnssec_name_name, ldns_dnssec_name_set_name, ldns_dnssec_name_set_nsec, ldns_dnssec_name_cmp, ldns_dnssec_name_add_rr, ldns_dnssec_name_find_rrset, ldns_dnssec_name_print | ldns_dnssec_zone +ldns_dnssec_rrsets_new, ldns_dnssec_rrsets_free, ldns_dnssec_rrsets_type, ldns_dnssec_rrsets_set_type, ldns_dnssec_rrsets_add_rr, ldns_dnssec_rrsets_print | ldns_dnssec_zone +ldns_dnssec_rrs_new, ldns_dnssec_rrs_free, ldns_dnssec_rrs_add_rr, ldns_dnssec_rrs_print | ldns_dnssec_zone + +# verification +ldns_dnssec_data_chain, ldns_dnssec_data_chain_struct, ldns_dnssec_trust_tree | ldns_dnssec_data_chain_new, ldns_dnssec_trust_tree_new, ldns_dnssec_verify_denial +ldns_dnssec_data_chain_new, ldns_dnssec_data_chain_free, ldns_dnssec_data_chain_deep_free, ldns_dnssec_build_data_chain, ldns_dnssec_data_chain_print | ldns_dnssec_data_chain +ldns_dnssec_trust_tree_new, ldns_dnssec_trust_tree_free, ldns_dnssec_trust_tree_depth, ldns_dnssec_derive_trust_tree, ldns_dnssec_trust_tree_contains_keys, ldns_dnssec_trust_tree_print, ldns_dnssec_trust_tree_print_sm, ldns_dnssec_trust_tree_add_parent, ldns_dnssec_derive_trust_tree_normal_rrset, ldns_dnssec_derive_trust_tree_dnskey_rrset, ldns_dnssec_derive_trust_tree_ds_rrset, ldns_dnssec_derive_trust_tree_no_sig | ldns_dnssec_data_chain, ldns_dnssec_trust_tree +ldns_dnssec_verify_denial, ldns_dnssec_verify_denial_nsec3 | ldns_dnssec_trust_tree, ldns_dnssec_data_chain + +# new signing functions +ldns_dnssec_zone_sign, ldns_dnssec_zone_sign_nsec3, ldns_dnssec_zone_mark_glue, ldns_dnssec_name_node_next_nonglue, ldns_dnssec_zone_create_nsecs, ldns_dnssec_remove_signatures, ldns_dnssec_zone_create_rrsigs | ldns_dnssec_zone + +### /dnssec.h + +### dnskey.h +ldns_key_new | ldns_key, ldns_key_list_new +ldns_key_new_frm_algorithm, ldns_key_new_frm_fp, ldns_key_new_frm_fp_l | ldns_key +ldns_key_new_frm_fp_rsa, ldns_key_new_frm_fp_rsa_l | ldns_key_new_frm_fp, ldns_key +ldns_key_new_frm_fp_dsa, ldns_key_new_frm_fp_dsa_l | ldns_key_new_frm_fp, ldns_key +ldns_key_list_new | ldns_key_new, ldns_key +# access, write +ldns_key_set_algorithm, ldns_key_set_rsa_key, ldns_key_set_dsa_key, ldns_key_set_hmac_key, ldns_key_set_origttl, ldns_key_set_inception, ldns_key_set_expiration, ldns_key_set_pubkey_owner, ldns_key_set_keytag, ldns_key_set_flags, ldns_key_list_set_key_count, ldns_key_algo_supported | ldns_key_push_key, ldns_key +ldns_key_list_push_key | ldns_key_list_pop_key, ldns_key +ldns_key_list_pop_key | ldns_key_list_push_key, ldns_key +# access, read +ldns_key_list_key_count, ldns_key_list_key, ldns_key_rsa_key, ldns_key_dsa_key, ldns_key_algorithm, ldns_key_hmac_key, ldns_key_origttl, ldns_key_inception, ldns_key_expiration, ldns_key_keytag, ldns_key_pubkey_owner, ldns_key_flags | ldns_key +# convert +ldns_key2rr | ldns_key +ldns_key_free, ldns_key_deep_free, ldns_key_list_free | ldns_key +# +ldns_key_print | ldns_key_new, ldns_key +ldns_key | ldns_key_new, ldns_key_new_frm_algorithm,ldns_key_new_frm_fp,ldns_key_new_frm_fp_l, ldns_key_new_frm_fp_rsa, ldns_key_new_frm_fp_rsa_l, ldns_key_new_frm_fp_dsa, ldns_key_new_frm_fp_dsa_l, ldns_key_list_new, ldns_key_set_algorithm, ldns_key_set_rsa_key, ldns_key_set_dsa_key, ldns_key_set_hmac_key, ldns_key_set_origttl, ldns_key_set_inception, ldns_key_set_expiration, ldns_key_set_pubkey_owner, ldns_key_set_keytag, ldns_key_set_flags, ldns_key_list_set_key_count, ldns_key_list_push_key, ldns_key_list_pop_key, ldns_key_list_key_count, ldns_key_list_key, ldns_key_rsa_key, ldns_key_dsa_key, ldns_key_algorithm, ldns_key_hmac_key, ldns_key_origttl, ldns_key_inception, ldns_key_expiration, ldns_key_keytag, ldns_key_pubkey_owner, ldns_key_flags, ldns_key2rr, ldns_key_free, ldns_key_deep_free, ldns_key_list_free, ldns_key_print +### /dnskey.h + +### MIEK TOT HIER TOT HIER + +# lists +ldns_key_list_new, ldns_key_list_push_key, ldns_key_list_pop_key, ldns_key_list_key_count, ldns_key_list_key | ldns_key_list, ldns_key +ldns_key_rsa_key, ldns_key_dsa_key, ldns_key_algorithm, ldns_key_hmac_key | ldns_key_list, ldns_key + +# gets/sets +ldns_key_origttl, ldns_key_inception, ldns_key_expiration, ldns_key_keytag, ldns_key_pubkey_owner, ldns_key_flags | ldns_key +ldns_key_set_algorithm, ldns_key_set_rsa_key, ldns_key_set_dsa_key, ldns_key_set_hmac_key, ldns_key_set_origttl, ldns_key_set_inception, ldns_key_set_expiration, ldns_key_set_pubkey_owner, ldns_key_set_keytag, ldns_key_set_flags, ldns_key_list_set_key_count | ldns_key + +# errr.h +ldns_get_errorstr_by_id | ldns_status +ldns_status | ldns_get_errorstr_by_id + +### net.h +ldns_send | ldns_pkt, ldns_resolver +ldns_tcp_send_query, ldns_tcp_read_wire, ldns_tcp_connect | ldns_send, ldns_pkt, ldns_resolver +### /net.h + +### buffer.h +# general +ldns_buffer | ldns_buffer_new, ldns_buffer_new_frm_data, ldns_buffer_clear, ldns_buffer_printf, ldns_buffer_free, ldns_buffer_export, ldns_buffer_flip, ldns_buffer_rewind, ldns_buffer_position, ldns_buffer_set_position, ldns_buffer_skip, ldns_buffer_limit, ldns_buffer_set_limit, ldns_buffer_capacity, ldns_buffer_set_capacity, ldns_buffer_reserve, ldns_buffer_at, ldns_buffer_begin, ldns_buffer_end, ldns_buffer_current, ldns_buffer_remaining_at, ldns_buffer_remaining, ldns_buffer_available_at, ldns_buffer_available, ldns_buffer_status, ldns_buffer_status_ok, ldns_buffer_write_at, ldns_buffer_write_at, ldns_buffer_write, ldns_buffer_write_string_at, ldns_buffer_write_string, ldns_buffer_write_u8_at, ldns_buffer_write_u8, ldns_buffer_write_u16_at, ldns_buffer_write_u16, ldns_buffer_read_at, ldns_buffer_read, ldns_buffer_read_u8_at, ldns_buffer_read_u8, ldns_buffer_read_u16_at, ldns_buffer_read_u16, ldns_buffer_read_u32_at, ldns_buffer_read_u32 +ldns_buffer_new, ldns_buffer_new_frm_data, ldns_buffer_clear, ldns_buffer_printf, ldns_buffer_free, ldns_buffer_export | ldns_buffer +# position +ldns_buffer_flip, ldns_buffer_rewind, ldns_buffer_position, ldns_buffer_set_position, ldns_buffer_skip | ldns_buffer +# values and pointers +ldns_buffer_limit, ldns_buffer_set_limit, ldns_buffer_capacity, ldns_buffer_set_capacity, ldns_buffer_reserve, ldns_buffer_at, ldns_buffer_begin, ldns_buffer_end, ldns_buffer_current | ldns_buffer +# info +ldns_buffer_remaining_at, ldns_buffer_remaining, ldns_buffer_available_at, ldns_buffer_available, ldns_buffer_status, ldns_buffer_status_ok | ldns_buffer +# read and write +ldns_buffer_write_at, ldns_buffer_write_at, ldns_buffer_write, ldns_buffer_write_string_at, ldns_buffer_write_string, ldns_buffer_write_u8_at, ldns_buffer_write_u8, ldns_buffer_write_u16_at, ldns_buffer_write_u16, ldns_buffer_read_at, ldns_buffer_read, ldns_buffer_read_u8_at, ldns_buffer_read_u8, ldns_buffer_read_u16_at, ldns_buffer_read_u16, ldns_buffer_read_u32_at, ldns_buffer_read_u32 | ldns_buffer +### /buffer.h + +# parse.h +ldns_bget_token, ldns_bgetc, ldns_bskipcs | ldns_buffer +ldns_fget_token, ldns_fskipcs | ldns_buffer +ldns_str_remove_comment + + +# rr.h and other general rr funcs +ldns_rr, ldns_rr_class, ldns_rr_type, ldns_rr_compress, ldns_rr_list | ldns_rr_new, ldns_rr_new_frm_type, ldns_rr_new_frm_str, ldns_rr_new_frm_fp, ldns_rr_free, ldns_rr_print, ldns_rr_set_owner, ldns_rr_set_ttl, ldns_rr_set_type, ldns_rr_set_rd_count, ldns_rr_set_class, ldns_rr_set_rdf, ldns_rr_push_rdf, ldns_rr_pop_rdf, ldns_rr_rdf, ldns_rr_owner, ldns_rr_rd_count, ldns_rr_ttl, ldns_rr_get_class, ldns_rr_list_rr_count, ldns_rr_list_set_rr_count, ldns_rr_list_new, ldns_rr_list_free, ldns_rr_list_cat, ldns_rr_list_push_rr, ldns_rr_list_pop_rr, ldns_is_rrset, ldns_rr_set_push_rr, ldns_rr_set_pop_rr, ldns_get_rr_class_by_name, ldns_get_rr_type_by_name, ldns_rr_list_clone, ldns_rr_list_sort, ldns_rr_compare, ldns_rr_compare_ds, ldns_rr_uncompressed_size, ldns_rr2canonical, ldns_rr_label_count, ldns_is_rrset, ldns_rr_descriptor, ldns_rr_descript +ldns_rr_new, ldns_rr_new_frm_type, ldns_rr_new_frm_str, ldns_rr_new_frm_fp, ldns_rr_free, ldns_rr_print | ldns_rr, ldns_rr_list +ldns_rr_set_owner, ldns_rr_set_ttl, ldns_rr_set_type, ldns_rr_set_rd_count, ldns_rr_set_class, ldns_rr_set_rdf | ldns_rr, ldns_rr_list +ldns_rr_push_rdf, ldns_rr_pop_rdf | ldns_rr, ldns_rr_list +ldns_rr_rdf, ldns_rr_owner, ldns_rr_rd_count, ldns_rr_ttl, ldns_rr_get_class | ldns_rr, ldns_rr_list +ldns_rr_list_rr_count, ldns_rr_list_set_rr_count | ldns_rr, ldns_rr_list +ldns_rr_list_new, ldns_rr_list_free | ldns_rr, ldns_rr_list +ldns_rr_list_cat, ldns_rr_list_push_rr, ldns_rr_list_pop_rr | ldns_rr, ldns_rr_list +ldns_is_rrset | ldns_rr, ldns_rr_list +ldns_rr_set_push_rr, ldns_rr_set_pop_rr | ldns_rr, ldns_rr_list +ldns_get_rr_class_by_name, ldns_get_rr_type_by_name | ldns_rr, ldns_rr_list +ldns_rr_list_clone | ldns_rr, ldns_rr_list +ldns_rr_list_sort | ldns_rr, ldns_rr_list +ldns_rr_compare, ldns_rr_compare_ds | ldns_rr, ldns_rr_list +ldns_rr_uncompressed_size | ldns_rr, ldns_rr_list +ldns_rr2canonical | ldns_rr, ldns_rr_list +ldns_rr_label_count | ldns_rr, ldns_rr_list +ldns_is_rrset | ldns_rr + +# rr descriptors +ldns_rr_descriptor, ldns_rr_descript, ldns_rr_descriptor_minimum, ldns_rr_descriptor_maximum, ldns_rr_descriptor_field_type | ldns_rr, ldns_rdf + +# packet.h +ldns_pkt, ldns_pkt_section, ldns_pkt_type | ldns_pkt_new, ldns_pkt_free, ldns_pkt_print, ldns_pkt_query_new, ldns_pkt_query_new_frm_str, ldns_pkt_reply_type, ldns_pkt_id, ldns_pkt_qr, ldns_pkt_aa, ldns_pkt_tc, ldns_pkt_rd, ldns_pkt_cd, ldns_pkt_ra, ldns_pkt_ad, ldns_pkt_get_opcode, ldns_pkt_get_rcode, ldns_pkt_qdcount, ldns_pkt_ancount, ldns_pkt_nscount, ldns_pkt_arcount, ldns_pkt_answerfrom, ldns_pkt_querytime, ldns_pkt_size, ldns_pkt_tsig, ldns_pkt_question, ldns_pkt_answer, ldns_pkt_authority, ldns_pkt_additional, ldns_pkt_get_section_clone, ldns_pkt_rr_list_by_name, ldns_pkt_rr_list_by_type, ldns_pkt_rr_list_by_name_and_type, ldns_pkt_set_flags, ldns_pkt_set_id, ldns_pkt_set_qr, ldns_pkt_set_aa, ldns_pkt_set_tc, ldns_pkt_set_rd, ldns_pkt_set_cd, ldns_pkt_set_ra, ldns_pkt_set_ad, ldns_pkt_set_opcode, ldns_pkt_set_rcode, ldns_pkt_set_qdcount, ldns_pkt_set_ancount, ldns_pkt_set_nscount, ldns_pkt_set_arcount, ldns_pkt_set_answerfrom, ldns_pkt_set_querytime, ldns_pkt_set_size, ldns_pkt_set_section_count, ldns_pkt_set_tsig, ldns_pkt_edns, ldns_pkt_edns_udp_size, ldns_pkt_edns_extended_rcode, ldns_pkt_edns_version, ldns_pkt_edns_z, ldns_pkt_edns_data, ldns_pkt_set_edns_udp_size, ldns_pkt_set_edns_extended_rcode, ldns_pkt_set_edns_version, ldns_pkt_set_edns_z, ldns_pkt_set_edns_data + +ldns_pkt_new, ldns_pkt_free, ldns_pkt_print, ldns_pkt_query_new, ldns_pkt_query_new_frm_str, ldns_pkt_reply_type | ldns_pkt +# gets +ldns_pkt_id, ldns_pkt_qr, ldns_pkt_aa, ldns_pkt_tc, ldns_pkt_rd, ldns_pkt_cd, ldns_pkt_ra, ldns_pkt_ad, ldns_pkt_get_opcode, ldns_pkt_get_rcode, ldns_pkt_qdcount, ldns_pkt_ancount, ldns_pkt_nscount, ldns_pkt_arcount, ldns_pkt_answerfrom, ldns_pkt_querytime, ldns_pkt_size, ldns_pkt_tsig, ldns_pkt_question, ldns_pkt_answer, ldns_pkt_authority, ldns_pkt_additional, ldns_pkt_get_section_clone, ldns_pkt_rr_list_by_name, ldns_pkt_rr_list_by_type, ldns_pkt_rr_list_by_name_and_type | ldns_pkt +# sets +ldns_pkt_set_flags, ldns_pkt_set_id, ldns_pkt_set_qr, ldns_pkt_set_aa, ldns_pkt_set_tc, ldns_pkt_set_rd, ldns_pkt_set_cd, ldns_pkt_set_ra, ldns_pkt_set_ad, ldns_pkt_set_opcode, ldns_pkt_set_rcode, ldns_pkt_set_qdcount, ldns_pkt_set_ancount, ldns_pkt_set_nscount, ldns_pkt_set_arcount, ldns_pkt_set_answerfrom, ldns_pkt_set_querytime, ldns_pkt_set_size, ldns_pkt_set_section_count, ldns_pkt_set_tsig | ldns_pkt +# EDNS0 +ldns_pkt_edns, ldns_pkt_edns_udp_size, ldns_pkt_edns_extended_rcode, ldns_pkt_edns_version, ldns_pkt_edns_z, ldns_pkt_edns_data, ldns_pkt_set_edns_udp_size, ldns_pkt_set_edns_extended_rcode, ldns_pkt_set_edns_version, ldns_pkt_set_edns_z, ldns_pkt_set_edns_data | ldns_pkt + +# rr_functions.h +ldns_rr_ns_nsdname +# +ldns_rr_mx_preference, ldns_rr_mx_exchange +# +ldns_rr_rrsig_typecovered, ldns_rr_rrsig_set_typecovered, ldns_rr_rrsig_algorithm, ldns_rr_rrsig_set_algorithm, ldns_rr_rrsig_labels, ldns_rr_rrsig_set_labels, ldns_rr_rrsig_origttl, ldns_rr_rrsig_set_origttl, ldns_rr_rrsig_expiration, ldns_rr_rrsig_set_expiration, ldns_rr_rrsig_inception, ldns_rr_rrsig_set_inception, ldns_rr_rrsig_keytag, ldns_rr_rrsig_set_keytag, ldns_rr_rrsig_signame, ldns_rr_rrsig_set_signame, ldns_rr_rrsig_sig, ldns_rr_rrsig_set_sig +# +ldns_rr_dnskey_flags, ldns_rr_dnskey_set_flags, ldns_rr_dnskey_protocol, ldns_rr_dnskey_set_protocol, ldns_rr_dnskey_algorithm, ldns_rr_dnskey_set_algorithm, ldns_rr_dnskey_key, ldns_rr_dnskey_set_key | ldns_rr + +### zone.h +ldns_zone | ldns_zone_new, ldns_zone_deep_free, ldns_zone_new_frm_fp, ldns_zone_new_frm_fp_l, ldns_zone_sort, ldns_zone_glue_rr_list, ldns_zone_push_rr, ldns_zone_push_rr_list, ldns_zone_set_rrs, ldns_zone_set_soa, ldns_zone_rrs, ldns_zone_soa, ldns_zone_rr_count, + + +ldns_zone_new, ldns_zone_deep_free, ldns_zone_new_frm_fp, ldns_zone_new_frm_fp_l | ldns_zone +ldns_zone_sort, ldns_zone_glue_rr_list | ldns_zone +ldns_zone_push_rr, ldns_zone_push_rr_list | ldns_zone +ldns_zone_set_rrs, ldns_zone_set_soa | ldns_zone, ldns_zone_rrs, ldns_zone_soa +ldns_zone_rrs, ldns_zone_soa | ldns_zone ldns_zone_set_rrs +ldns_zone_rr_count | ldns_zone + +### update.h +ldns_update_pkt_new | ldns_update_pkt_tsig_add, ldns_update_pkt_tsig_add, ldns_update_zocount, ldns_update_prcount, ldns_update_upcount, ldns_update_adcount, ldns_update_set_zocount, ldns_update_set_prcount, ldns_update_set_upcount, ldns_update_set_adcount, + +ldns_update_pkt_tsig_add | ldns_update_pkt_new +ldns_update_zocount, ldns_update_prcount, ldns_update_upcount, ldns_update_adcount | ldns_update_pkt_new +ldns_update_set_zocount, ldns_update_set_prcount, ldns_update_set_upcount, ldns_update_set_adcount | ldns_update_pkt_new diff --git a/doc/header.html b/doc/header.html new file mode 100644 index 00000000000..5b311bd9863 --- /dev/null +++ b/doc/header.html @@ -0,0 +1,10 @@ + + +ldns documentation + + + + diff --git a/doc/images/LogoInGradientBar2-y100.png b/doc/images/LogoInGradientBar2-y100.png new file mode 100644 index 0000000000000000000000000000000000000000..0e753611279d503619e61b5e518ac2b0f8bb03dc GIT binary patch literal 60773 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

o$GReupNRI^H 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�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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + - CLIENT - + any program making use of ldns + + + - WIRE module - + from_wire to_wire- convert to and from wireformat- all name encoding and decoding is contained in these functions + + + - central structures - + pkt structurerdf structuredname structurerr structurerrlist structurerrset structurepkt structurezone structure + + + - resolver module - + stub resolversendquerybgsendaxfr + + + - net module - + all network interfacing code + + - OS/libc layer - + + str module + from_str to_str- convert from and to string- dig-style formatted output + + + DNSSEC module + signverify + + + + + + + + + + diff --git a/doc/libdns.css b/doc/libdns.css new file mode 100644 index 00000000000..2d2f3858637 --- /dev/null +++ b/doc/libdns.css @@ -0,0 +1,425 @@ +BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV { + font-family: Geneva, Arial, Helvetica, sans-serif; +} +BODY,TD { + font-size: 90%; +} +H1 { +text-align: center; + font-size: 160%; +} +H2 { + font-size: 120%; +} +H3 { + font-size: 100%; +} +CAPTION { font-weight: bold } +DIV.qindex { + width: 100%; + background-color: #e8eef2; + border: 1px solid #84c7b0; + text-align: center; + margin: 2px; + padding: 2px; + line-height: 140%; +} +DIV.nav { + width: 100%; + background-color: #e8eef2; + border: 1px solid #84c7b0; + text-align: center; + margin: 2px; + padding: 2px; + line-height: 140%; +} + +DIV.navtab { + background-color: #e8eef2; + border: 1px solid #84c7b0; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} +TD.navtab { + font-size: 70%; +} +A { + text-decoration: none; + font-weight: bold; + color: #1ba159; +} + +A.qindex { + text-decoration: none; + font-weight: bold; + color: #1ba159; +} +A.qindex:visited { + text-decoration: none; + font-weight: bold; + color: #1b7159; +} +A.qindex:hover { + text-decoration: none; + background-color: #ddffdd; +} +A.qindexHL { + text-decoration: none; + font-weight: bold; + background-color: #6666cc; + color: #ffffff; + border: 1px double #9295C2; +} +A.qindexHL:hover { + text-decoration: none; + background-color: #6666cc; + color: #ffffff; +} +A.qindexHL:visited { text-decoration: none; background-color: #6666cc; color: #ffffff } +A.el { text-decoration: none; font-weight: bold } +A.elRef { font-weight: bold } +A.code:link { text-decoration: none; font-weight: normal; color: #1ba159} +A.code:visited { text-decoration: none; font-weight: normal; color: #1b7159} +A.codeRef:link { font-weight: normal; color: #1ba159} +A.codeRef:visited { font-weight: normal; color: #1b7159} +A:hover { text-decoration: none; background-color: #c0c0c0 } + +DL.el { margin-left: -1cm } +.fragment { + font-family: monospace; + font-size: 100%; +} +PRE.fragment { + border: 1px solid #CCCCCC; + background-color: #f5f5f5; + margin-top: 4px; + margin-bottom: 4px; + margin-left: 2px; + margin-right: 8px; + padding-left: 6px; + padding-right: 6px; + padding-top: 4px; + padding-bottom: 4px; +} +DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px } +TD.md { background-color: #F4F4FB; font-weight: bold; } +TD.mdPrefix { + background-color: #F4F4FB; + color: #606060; + font-size: 80%; +} +TD.mdname1 { background-color: #F4FBF4; font-weight: bold; color: #602020; } +TD.mdname { background-color: #F4FBF4; font-weight: bold; color: #602020; width: 600px; } +DIV.groupHeader { + margin-left: 16px; + margin-top: 12px; + margin-bottom: 6px; + font-weight: bold; +} +DIV.groupText { margin-left: 16px; font-style: italic; font-size: 90% } +BODY { + background: white; + color: black; + margin-right: 20px; + margin-left: 20px; +} +TD.indexkey { + background-color: #e8eef2; + font-weight: bold; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +TD.indexvalue { + background-color: #e8eef2; + font-style: italic; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +TR.memlist { + background-color: #f0f0f0; +} +P.formulaDsp { text-align: center; } +IMG.formulaDsp { } +IMG.formulaInl { vertical-align: middle; } +SPAN.keyword { color: #008000 } +SPAN.keywordtype { color: #604020 } +SPAN.keywordflow { color: #e08000 } +SPAN.comment { color: #800000 } +SPAN.preprocessor { color: #806020 } +SPAN.stringliteral { color: #002080 } +SPAN.charliteral { color: #008080 } +.mdTable { + border: 1px solid #868686; + background-color: #F4F4FB; +} +.mdRow { + padding: 8px 10px; +} +.mdescLeft { + padding: 0px 8px 4px 8px; + font-size: 80%; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +.mdescRight { + padding: 0px 8px 4px 8px; + font-size: 80%; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +.memItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memItemRight { + padding: 1px 8px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: none; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplItemRight { + padding: 1px 8px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: none; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplParams { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + color: #606060; + background-color: #FAFAFA; + font-size: 80%; +} +.search { color: #009933; + font-weight: bold; +} +FORM.search { + margin-bottom: 0px; + margin-top: 0px; +} +INPUT.search { font-size: 75%; + color: #008000; + font-weight: normal; + background-color: #e8eef2; +} +TD.tiny { font-size: 75%; +} +a { + color: #1ba159; +} +a:visited { + color: #1b7159; +} +.dirtab { padding: 4px; + border-collapse: collapse; + border: 1px solid #84b0c7; +} +TH.dirtab { background: #e8eef2; + font-weight: bold; +} +HR { height: 1px; + border: none; + border-top: 1px solid black; +} + +/* tabs styles, based on http://www.alistapart.com/articles/slidingdoors */ + +DIV.tabs +{ + float : left; + width : 100%; + background : url("tab_b.gif") repeat-x bottom; + margin-bottom : 4px; +} + +DIV.tabs UL +{ + margin : 0px; + padding-left : 10px; + list-style : none; +} + +DIV.tabs LI, DIV.tabs FORM +{ + display : inline; + margin : 0px; + padding : 0px; +} + +DIV.tabs FORM +{ + float : right; +} + +DIV.tabs A +{ + float : left; + background : url("tab_r.gif") no-repeat right top; + border-bottom : 1px solid #84C7B0; + font-size : x-small; + font-weight : bold; + text-decoration : none; +} + +DIV.tabs A:hover +{ + background-position: 100% -150px; +} + +DIV.tabs A:link, DIV.tabs A:visited, +DIV.tabs A:active, DIV.tabs A:hover +{ + color: #1b7159; +} + +DIV.tabs SPAN +{ + float : left; + display : block; + background : url("tab_l.gif") no-repeat left top; + padding : 5px 9px; + white-space : nowrap; +} + +DIV.tabs INPUT +{ + float : right; + display : inline; + font-size : 1em; +} + +DIV.tabs TD +{ + font-size : x-small; + font-weight : bold; + text-decoration : none; +} + + + +/* Commented Backslash Hack hides rule from IE5-Mac \*/ +DIV.tabs SPAN {float : none;} +/* End IE5-Mac hack */ + +DIV.tabs A:hover SPAN +{ + background-position: 0% -150px; +} + +DIV.tabs LI#current A +{ + background-position: 100% -150px; + border-width : 0px; +} + +DIV.tabs LI#current SPAN +{ + background-position: 0% -150px; + padding-bottom : 6px; +} + +DIV.nav +{ + background : none; + border : none; + border-bottom : 1px solid #84C7B0; +} + +.logo +{ + text-align: right; +} diff --git a/doc/tutorial1_mx.dox b/doc/tutorial1_mx.dox new file mode 100644 index 00000000000..f442e7f501c --- /dev/null +++ b/doc/tutorial1_mx.dox @@ -0,0 +1,98 @@ +/** + \page tutorial1_mx Tutorial 1: Querying for MX records + \dontinclude ldns-mx.c + + The full source code can be found in \link examples/ldns-mx.c \endlink + + ldns-mx is a simple tool that queries your default caching forwarder for + the MX (Mail exchange) record of the given domain. + +

+   % ldns-mx nlnetlabs.nl
+   nlnetlabs.nl.   86400   IN      MX      100 omval.tednet.nl.
+   nlnetlabs.nl.   86400   IN      MX      50 open.nlnetlabs.nl.
+   
+ + First of all, we need to include the correct header files, so + that all functions are available to us: + + \skip include + \until dns.h + + In this case we have used a configure script to generate a config.h file + that does all our inclusions for us, so that it can be compiled on + multiple platforms. If your platform supports the include files \c + stdint.h and \c stdlib.h, you can include these instead of using a + configure script. + + The first included files are prerequisites that ldns needs to function. + The last one, of course, includes the functions of ldns itself. + + In our main function, we declare some variables that we are going to use: + + \skipline ldns_resolver + \until ldns_status + + - The \c ldns_resolver structure keeps a list of nameservers, and can perform queries for us + - An \c ldns_rdf is a basic data type of dns, the RDATA. See \ref design for a description about the building blocks of DNS. + In this case, \c domain will be used to store the name the user specifies when calling the program + - An \c ldns_pkt is a DNS packet, for instance a complete query, or an answer + - The \c ldns_rr_list structure contains a list of DNS Resource Records (RRs). In this case, we will store the MX records we find in the list. + - \c ldns_status is the basic type for status messages in ldns. Most functions will return a value of this type. + + First, we parse the command line argument (checks omitted on this page, see full source code), and store it in our \c domain variable: + \skipline ldns_dname_new_frm_str + + This function takes a string containing a domain name (like + "nlnetlabs.nl") and returns an \c ldns_rdf representing that name. If + somehow the given string can not be parsed it returns NULL. + + Then, we create the resolver structure: + \skipline ldns_resolver_new + + Most of the functions work like this, the first argument is a pointer to + the structure where ldns should store its results (which is also a + pointer). The function returns a status code indicating success + (\ref LDNS_STATUS_OK) or an error number. Remember that these types of + functions allocate memory that you should free later (using the + ldns_free_ functions). + + The second argument is the filename that contains information about the + resolver structure that is to be created. If this argument is NULL, + /etc/resolv.conf is used. The syntax of the file is like that of + /etc/resolv.conf. + + + + We tell the resolver to query for our domain, type MX, of class IN: + \skipline ldns_resolver_query + \until ) + + The last argument contains flags to influence the type of query the + resolver structure sends. In this case, we want the nameserver to use + recursion, so that we'll get the final answer. Therefore, we specify the + \ref LDNS_RD (Recursion Desired) flag. + + This should return a packet if everything goes well. + + We get all RRs of type MX from the answer packet and store them in our list: + \skipline ldns_pkt_rr_list_by_type + \until ) + + If this list is not empty, we sort and print it: + \skipline ldns_rr_list_sort + \skipline ldns_rr_list_print + + And finally, just to be proper, we free our allocated data: + \skipline free( + \until resolver_deep_free + + For structures that can contain other ldns structures, there are two types of free() function available + - \c ldns_free_ frees only the allocated data for the structure itself. + - \c ldns_deep_free_ frees the structure, and ALL structures that + are nested in it. For example, of you \c deep_free an ldns_rr_list, + all \c ldns_rr structures that were present in the list are also + freed. + + +*/ diff --git a/doc/tutorial2_zone.dox b/doc/tutorial2_zone.dox new file mode 100644 index 00000000000..680ccb46a31 --- /dev/null +++ b/doc/tutorial2_zone.dox @@ -0,0 +1,111 @@ +/** + \page tutorial2_zone Tutorial 2: Reading a zone file + \dontinclude ldns-read-zone.c + + The full source code can be found in \link examples/ldns-read-zone.c \endlink + + ldns-read-zone reads a zone file, and prints it to stdout, with 1 resource record per line. + +
+% cat example.zone
+$ORIGIN example.
+$TTL 600
+
+example.        IN SOA  example. op.example. (
+                                2004022501 ; serial
+                                28800      ; refresh (8 hours)
+                                7200       ; retry (2 hours)
+                                604800     ; expire (1 week)
+                                18000      ; minimum (5 hours)
+                                )
+
+@       IN      MX      10 mail.example.
+@       IN      NS      ns1
+@       IN      NS      ns2
+@       IN      A       123.123.123.123
+
+% ldns-read-zone example.zone
+example.        600     IN      SOA     example. op.example. 2004022501 28800 7200 604800 18000
+example.        600     IN      MX      10 mail.example.
+example.        600     IN      NS      ns1.example.
+example.        600     IN      NS      ns2.example.
+example.        600     IN      A       123.123.123.123
+   
+ + + +Again, let's start with including some necessary header files: + +\skipline include +\until errno + +In this example, we are going to open a file, if that fails, we'll need errno.h to display an error message. + +Okay, let's declare the variables we are going to need today: + +\skipline filename +\until ldns_status + +The only two ldns-specific types here are \c ldns_zone and \c ldns_status. + - \c ldns_zone is the structure that can contain a complete zone + - \c ldns_status again is used to check return values of ldns functions + + +If we get no filename, we'll read standard input, otherwise, we'll try to +open the given filename: +\skipline if (argc == 0) +\until exit(EXIT_FAILURE) +\until } +\until } + + +With the \c FILE pointer in our hands, we visit ldns to pour it into a zone +structure: +\skipline ldns_zone_new_frm_fp_l + +There is also a \c ldns_zone_new_frm_fp, but this one also remembers the +line number it was on, so we can use that if we encounter a parse error. + +Just like in \ref tutorial1_mx, the first argument is a pointer +to the place ldns should store its creation in, and again, the return value +is the status code. + +The second argument is the file pointer where our zone data should reside. + +The third argument, if not NULL, is a \c dname that contains the zones +origin. It will place this dname after every name in the file that is not a +fully qualified domain name. + +The fourth argument, if not 0, is the default TTL to use. + +Both these values can be specified in the zone file by setting \c $ORIGIN and \c $TTL. + +The fifth argument specifies the default class, which defaults to IN (\ref LDNS_RR_CLASS_IN). + +And finally, every time \c ldns_zone_new_frm_fp_l reads a line from the +input file pointer, it will increment the value pointed to by the last +argument with 1. + + +Okay, with that, we should have a nice zone structure. Of course we need to +check whether it has succeeded. + +\skipline LDNS_STATUS_OK +\until deep_free + +If everything went well, we sort the zone if necessary, print it, and free it. + +Since \c ldns_zone contains other ldns structures, we use \c ldns_deep_free +so that every \c ldns_rr_list, \c ldns_rr et cetera are freed too. + +\until line_nr); +\until } + +If something went wrong, we use \c ldns_get_errorstr_by_id() to get a nice +error string instead of just a status integer. + +And of course, we should play nice and close the file: +\skipline fclose +\until exit + +*/ diff --git a/doc/tutorial3_signzone.dox b/doc/tutorial3_signzone.dox new file mode 100644 index 00000000000..1943e557ae4 --- /dev/null +++ b/doc/tutorial3_signzone.dox @@ -0,0 +1,206 @@ +/** + \page tutorial3_signzone Tutorial 3: Signing a zone file + \dontinclude ldns-signzone.c + + The full source code can be found in \link examples/ldns-signzone.c \endlink + + Of course, we start by the usual includes. Since we need a bit more here, + we'll add those right away. + + \skipline include + \until define + + Let's skip the boring usage() and sanity check functions, and dive right + into main(). + + \skipline main(int argc + \skipline { + + We'll be reading another zone file, so let's prepare some variables for that. + + \skipline zone + \until argi + + We will create a separate zone structure for the signed zone, so let's have a clear name for the original one. + + \skipline zone + \until zone + + To sign a zone, we need keys, so we need some variables to read and store it; + + \skipline key + \until status + + The \ref ldns_key structure holds (private) keys. These can be of any + supported algorithm type; you can put an RSA key in it, an DSA key, or an + HMAC key. Public keys can simply be put in an \ref ldns_rr structure with + type \ref LDNS_RR_TYPE_DNSKEY. + + The \ref ldns_key_list type is much like the \ref ldns_rr_list, only, you + guessed it, for \c ldns_key entries. + + + The signed zone will be stored in a new file. + + \skipline file + \until file + + And we have some command line options for the output zone. + + \skipline tm + \until class + + \c origin is a domain name, so it can be stored in an \ref ldns_rdf + variable with type \ref LDNS_RDF_TYPE_DNAME. + + The next part is option parsing, which is pretty straightforward using \c + getopt(), so we'll skip this too. U can always look to the source of the + file to check it out. + + Okay that's it for the variables, let's get to work! + + First we'll try to read in the zone that is to be signed. + + \skipline fopen(zone + \until } else { + + If the file exists and can be read, we'll let ldns mold it into a zone + structure: + + \skipline zone_new + + This creates a new (\c new) zone from (\c frm) a filepointer (\c fp), + while remembering the current line (\c l) in the input file (for error + messages). + + A pointer to the zone structure to be filled is passed as the first + argument, like in most \c new_frm functions. + + Like a lot of ldns functions, this one returns a \c ldns_status + indicating success or the type of failure, so let us check that. + + \skipline STATUS + \until } else { + + If everything is ok so far, we check if the zone has a SOA record and contains actual data. + + \skipline orig_soa + \until } + \until } + \until } + + Now that we have the complete zone in our memory, we won't be needing the file anymore. + + \skipline fclose + \until } + + If there was no origin given, we'll use the one derived from the original zone file. + + \skipline origin + \until } + + No signing party can be complete without keys to sign with, let's fetch those. + + Multiple key files can be specified on the command line, by using the + base names of the .key/.private file pairs. + + \skipline key + \until fopen + + As you can see, we append ".private" to the name, which should result in + the complete file name of the private key. Later we'll also form the + ".key" file name, which will be directly included in the signed zone. + + If the file exists, we'll read it and create a \c ldns_key from its + contents, much like the way we read the zone earlier. + + \skipline line_nr + \until STATUS + + If this went ok, we need to set the inception and expiration times, which + are set in the keys, but will eventually end up in the RRSIGs generated + by those keys. + + \skipline expiration + \until } + \skipline inception + \until } + + And now that we have read the private keys, we read the public keys and + add them to the zone. + + Reading them from the files works roughly the same as reading private + keys, but public keys are normal Resource Records, and they can be stored + in general \c ldns_rr structures. + + \skipline FREE + \until } + \until } + + With \c push() we add them to our key list and our zone. This function + clones the data, so we can safely free it after that. + + \skipline push + \until free + + And if we're done, we free the allocated memory for the file name. + + \until FREE + + If the reading did not work, we print an error. Finally, we move on to + the next key in the argument list. + + \skipline } else { + \until } + \until } + \until } + + Just to be sure, we add a little check to see if we actually have any keys now. + + \skipline count + \until } + + So, we have our zone, we have our keys, let's do some signing! + + \skipline sign + + Yes. That's it. We now have a completely signed zone, \c ldns_zone_sign + checks the keys, and uses the zone signing keys to sign the data resource + records. NSEC and RRSIG resource records are generated and added to the + new zone. + + So now that we have a signed zone, all that is left is to store it somewhere. + + If no explicit output file name was given, we'll just append ".signed" to + the original zone file name. + + \skipline outputfile + \until } + + \c ldns_zone_sign returns NULL if the signing did not work, so we must check that. + + \skipline signed_zone + \until } else { + + Writing to a file is no different than normal printing, so we'll print to + the file and close it. + + \skipline print + \until } + + And of course, give an error if the signing failed. + + \skipline } else { + \until } + + Just to be nice, let's free the rest of the data we allocated, and exit + with the right return value. + + \skipline free + \until } + + + + + +*/ \ No newline at end of file diff --git a/drill/ChangeLog.22-nov-2005 b/drill/ChangeLog.22-nov-2005 new file mode 100644 index 00000000000..1ce8b0b7c07 --- /dev/null +++ b/drill/ChangeLog.22-nov-2005 @@ -0,0 +1,105 @@ +--------- Drill now is a subdirectory in ldns. To make life easier +--------- we are using ldns' version numbering for drill from now on. +--------- Sadly this means we GO BACKWARDS in the versions +--------- This ChangeLog will not be updated anymore - all changes are +--------- documented in ldns' ChangeLog + +1.0-pre3: to be released: drill-team + * Secure tracing works + * Added section about DNSSEC in the manual page + * Allow the class information to be given to do_chase() + * Lint fixes for the code + * Bugzilla was setup for drill + * Bug #97 (drill); -S crash was fixed + * Add -Q (quiet) flag was added. This supresses output from drill. + +1.0-pre2: 20 Jun 2005: drill-team + * Second prerelease + * Bugs where fix in the chasing functionality + +1.0-pre1: 1 Jun 2005: drill-team + * First drill release based on ldns + * drill's core code is not much more simple, as + all the difficult stuff is moved to ldns. + * Much saner argument parsing + +---------- Above Newer drill based on ldns -------------- +---------- Below Older drill with it's own DNS handling -------------- + +0.9.2: Feb 3 2005: drill-team + * Added two more options (borrowed from dig) + --rd, don't set the RD bit in queries + --fail, don't query the next nameserver on SERVFAIL + * Fixed handling of obscure data types + * Handle classes other the 'IN' when making a query + + * For people using FreeBSD: drill is now in the ports + (Thanks to Jaap Akkerhuis) + +0.9.1: Jan 5 2005: drill-team + * Makefile tweaks + * drill ns . works + * re-check the root in when tracing + * added handling for some lesser known types (including WKS) + +0.9: Dec 6 2004: drill-team + * big configure.ac and Makefile.in updates (made more general) + * escapes in names argument and txt and dname data + * gcc 2(.95) support + * packet wire data is now checked for dangerous elements (like + looping compression etc) + * (Multiple) Octal char representation + * Responses can be saved to file + * 'Answers' can be read from file instead of server + * Lots and lots of bugfixes and improvements + +0.8.1: Oct 27 2004: Miek + * configure.ac updates + * secure resolving updates (still doesn't work) + * printing additions + - CERT RR supported + - LOC RR support + * All non supported RRs are handled as unknown + * If no namservers found in /etc/resolv.conf + default to 127.0.0.1 + * Various bugs fixed + - Close sockets after using them + - Some memory leaks were plugged + +0.8: Oct 26 2004: Miek + * Lots of features added. Drill is almost feature complete + * Unknown RR's are supported + * Numerous smaller updates in documentation + * Numerous code cleanups + * Dig is no longer needed to build drill + +0.7: Oct 21 2004: Miek + * reworked interal code + * DNSSEC is working, except the secure resolving + * build updates + * more sane options parsing + * more sane argument handling + +0.6-alpha: Oct 2004: Jelte + * No log + +0.5-alpha: Sept 22 2004: Miek + * most of the DNS stuff is working + * moved to configure + * tested on Linux/FreeBSD + * fully IPV6 capable + * new DNSSEC types supported + * DNSSEC somewhat working + * gcc => 3 is needed for building + +0.4-alpha: Sept 9 2004: Miek + * moved to autoconf for building + * lots of various updates + * really a workable program now + +0.3-alpha: Sept 6 2004: Miek + * IPv6 support + * automatic secure resolving + * --trace updates + * --chase updates + * more checks diff --git a/drill/Makefile.in b/drill/Makefile.in new file mode 100644 index 00000000000..5730f0809c7 --- /dev/null +++ b/drill/Makefile.in @@ -0,0 +1,119 @@ +# Standard installation pathnames +# See the file LICENSE for the license +SHELL = @SHELL@ +VERSION = @PACKAGE_VERSION@ +basesrcdir = $(shell basename `pwd`) +srcdir = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +mandir = @mandir@ +includedir = @includedir@ + +CC = @CC@ +CFLAGS = -I. @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +INSTALL = $(srcdir)/install-sh -c +INSTALL_PROGRAM = $(INSTALL) +LDNSDIR = @LDNSDIR@ +LIBS_STC = @LIBS_STC@ + +COMPILE = $(CC) $(CPPFLAGS) $(CFLAGS) -I. -I$(srcdir) +LINK = $(CC) $(CFLAGS) $(LDFLAGS) + +LINT = splint +LINTFLAGS=+quiet -weak -warnposix -unrecog -Din_addr_t=uint32_t -Du_int=unsigned -Du_char=uint8_t -preproc -Drlimit=rlimit64 -D__gnuc_va_list=va_list +#-Dglob64=glob -Dglobfree64=globfree +# compat with openssl linux edition. +LINTFLAGS+="-DBN_ULONG=unsigned long" -Dkrb5_int32=int "-Dkrb5_ui_4=unsigned int" -DPQ_64BIT=uint64_t -DRC4_INT=unsigned -fixedformalarray -D"ENGINE=unsigned" -D"RSA=unsigned" -D"DSA=unsigned" -D"EVP_PKEY=unsigned" -D"EVP_MD=unsigned" -D"SSL=unsigned" -D"SSL_CTX=unsigned" -D"X509=unsigned" -D"RC4_KEY=unsigned" -D"EVP_MD_CTX=unsigned" +# compat with NetBSD +ifeq "$(shell uname)" "NetBSD" +LINTFLAGS+="-D__RENAME(x)=" -D_NETINET_IN_H_ +endif +# compat with OpenBSD +LINTFLAGS+="-Dsigset_t=long" +# FreeBSD8 +LINTFLAGS+="-D__uint16_t=uint16_t" +LINTFLAGS+=-D__signed__=signed "-D__packed=" "-D__aligned(x)=" +# Ubuntu Linux 11.04 +LINTFLAGS+="-D__u16=struct __u16" "-D__u32=struct __u32" "-D__u64=struct __u64" + +OBJ=drill.o drill_util.o error.o root.o work.o chasetrace.o dnssec.o securetrace.o +SRC=$(OBJ:.o=.c) + +HEADER=drill.h $(srcdir)/drill_util.h + +.PHONY: all clean realclean docclean doc release tags install all-static + +all: drill +all-static: drill-stc + +tags: + ctags *.[ch] + +drill: $(OBJ) + $(LINK) -o drill $(OBJ) $(LIBS) + +drill-stc: $(OBJ) + $(LINK) -o drill $(OBJ) $(LIBS_STC) + +## implicit rule +%.o: $(srcdir)/%.c + $(COMPILE) -c $< + +clean: + rm -f ${OBJ} + rm -f drill + rm -f *core + rm -f config.h.in~ + rm -f config.log + rm -f config.guess + rm -f config.status + +docclean: + rm -rf doxydoc + +distclean: clean docclean + rm -f config.h + rm -f drill.h + +realclean: clean docclean + rm -f tags + rm -f config.log + rm -f config.sub + rm -f ltmain.sh + rm -f config.status + rm -rf autom4te.cache + rm -f config.h + rm -f config.h.in + rm -f drill.h + rm -f configure + rm -f Makefile + rm -f aclocal.m4 + +doc: + doxygen drill.doxygen + +install: all + $(INSTALL) -d $(DESTDIR)$(bindir) + $(INSTALL) drill $(DESTDIR)$(bindir)/drill + $(INSTALL) -m 644 $(srcdir)/drill.1 $(DESTDIR)$(mandir)/man1/drill.1 + +uninstall: + @echo + rm -f -- $(DESTDIR)$(bindir)/drill + rm -f -- $(DESTDIR)$(mandir)/man1/drill.1 + rmdir -p $(DESTDIR)$(bindir) + rmdir -p $(DESTDIR)$(mandir)/man1 + @echo + +lint: + @for i in $(SRC) ; do \ + $(LINT) $(LINTFLAGS) $(CPPFLAGS) -I$(srcdir) $(srcdir)/$$i ; \ + if [ $$? -ne 0 ] ; then exit 1 ; fi ; \ + done + +confclean: clean + rm -rf config.log config.status config.h Makefile diff --git a/drill/README b/drill/README new file mode 100644 index 00000000000..bbbb816ef4a --- /dev/null +++ b/drill/README @@ -0,0 +1,12 @@ +QUICK INSTALL GUIDE + +drill is a subdirectory in ldns. + +To compile drill you need: +autoreconf && ./configure && make + +If ldns is installed in a different location, use --with-ldns=directory +See also ./configure --help + +In the first case you must run drill as: +LD_LIBRARY_PATH=../.libs ./drill diff --git a/drill/REGRESSIONS b/drill/REGRESSIONS new file mode 100644 index 00000000000..b8f6be9cc90 --- /dev/null +++ b/drill/REGRESSIONS @@ -0,0 +1,25 @@ +REGRESSIONS + +This version of drill is based on ldns and as such some things +are slightly changed. This file documents the changes. + +o When tracing (-T option) we use the local resolver (as specified + in /etc/resolv.conf) to lookup names. This increases the speed + dramatically, but you obviously need to be able to reach a recursive + server/cache. + Previously drill would try to resolve the names by itself. + +o Printing of DSs after DNSKEY records. Because we don't parse our + own packets anymore, we cannot print the DS directly after the DNSKEY + record. The DSs are now printed AFTER the packet. + +o The long options are removed. + +o The chase function has a different output, and will be subject to change + in the near future. + +o The useless (for jokes only) -I option was dropped. + +FIXED: +o the argument parsing is much smarter, the order doesn't matter (much) + anymore diff --git a/drill/chasetrace.c b/drill/chasetrace.c new file mode 100644 index 00000000000..c2bbfd00901 --- /dev/null +++ b/drill/chasetrace.c @@ -0,0 +1,395 @@ +/* + * chasetrace.c + * Where all the hard work concerning chasing + * and tracing is done + * (c) 2005, 2006 NLnet Labs + * + * See the file LICENSE for the license + * + */ + +#include "drill.h" +#include + +/** + * trace down from the root to name + */ + +/* same naive method as in drill0.9 + * We resolver _ALL_ the names, which is ofcourse not needed + * We _do_ use the local resolver to do that, so it still is + * fast, but it can be made to run much faster + */ +ldns_pkt * +do_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t, + ldns_rr_class c) +{ + ldns_resolver *res; + ldns_pkt *p; + ldns_rr_list *new_nss_a; + ldns_rr_list *new_nss_aaaa; + ldns_rr_list *final_answer; + ldns_rr_list *new_nss; + ldns_rr_list *ns_addr; + uint16_t loop_count; + ldns_rdf *pop; + ldns_status status; + size_t i; + + loop_count = 0; + new_nss_a = NULL; + new_nss_aaaa = NULL; + new_nss = NULL; + ns_addr = NULL; + final_answer = NULL; + p = ldns_pkt_new(); + res = ldns_resolver_new(); + + if (!p || !res) { + error("Memory allocation failed"); + return NULL; + } + + /* transfer some properties of local_res to res, + * because they were given on the commandline */ + ldns_resolver_set_ip6(res, + ldns_resolver_ip6(local_res)); + ldns_resolver_set_port(res, + ldns_resolver_port(local_res)); + ldns_resolver_set_debug(res, + ldns_resolver_debug(local_res)); + ldns_resolver_set_dnssec(res, + ldns_resolver_dnssec(local_res)); + ldns_resolver_set_fail(res, + ldns_resolver_fail(local_res)); + ldns_resolver_set_usevc(res, + ldns_resolver_usevc(local_res)); + ldns_resolver_set_random(res, + ldns_resolver_random(local_res)); + ldns_resolver_set_recursive(res, false); + + /* setup the root nameserver in the new resolver */ + status = ldns_resolver_push_nameserver_rr_list(res, global_dns_root); + if (status != LDNS_STATUS_OK) { + fprintf(stderr, "Error adding root servers to resolver: %s\n", ldns_get_errorstr_by_id(status)); + ldns_rr_list_print(stdout, global_dns_root); + return NULL; + } + + /* this must be a real query to local_res */ + status = ldns_resolver_send(&p, res, ldns_dname_new_frm_str("."), LDNS_RR_TYPE_NS, c, 0); + /* p can still be NULL */ + + + if (ldns_pkt_empty(p)) { + warning("No root server information received"); + } + + if (status == LDNS_STATUS_OK) { + if (!ldns_pkt_empty(p)) { + drill_pkt_print(stdout, local_res, p); + } + } else { + error("cannot use local resolver"); + return NULL; + } + + status = ldns_resolver_send(&p, res, name, t, c, 0); + + while(status == LDNS_STATUS_OK && + ldns_pkt_reply_type(p) == LDNS_PACKET_REFERRAL) { + + if (!p) { + /* some error occurred, bail out */ + return NULL; + } + + new_nss_a = ldns_pkt_rr_list_by_type(p, + LDNS_RR_TYPE_A, LDNS_SECTION_ADDITIONAL); + new_nss_aaaa = ldns_pkt_rr_list_by_type(p, + LDNS_RR_TYPE_AAAA, LDNS_SECTION_ADDITIONAL); + new_nss = ldns_pkt_rr_list_by_type(p, + LDNS_RR_TYPE_NS, LDNS_SECTION_AUTHORITY); + + if (verbosity != -1) { + ldns_rr_list_print(stdout, new_nss); + } + /* checks itself for verbosity */ + drill_pkt_print_footer(stdout, local_res, p); + + /* remove the old nameserver from the resolver */ + while((pop = ldns_resolver_pop_nameserver(res))) { /* do it */ } + + /* also check for new_nss emptyness */ + + if (!new_nss_aaaa && !new_nss_a) { + /* + * no nameserver found!!! + * try to resolve the names we do got + */ + for(i = 0; i < ldns_rr_list_rr_count(new_nss); i++) { + /* get the name of the nameserver */ + pop = ldns_rr_rdf(ldns_rr_list_rr(new_nss, i), 0); + if (!pop) { + break; + } + + ldns_rr_list_print(stdout, new_nss); + ldns_rdf_print(stdout, pop); + /* retrieve it's addresses */ + ns_addr = ldns_rr_list_cat_clone(ns_addr, + ldns_get_rr_list_addr_by_name(local_res, pop, c, 0)); + } + + if (ns_addr) { + if (ldns_resolver_push_nameserver_rr_list(res, ns_addr) != + LDNS_STATUS_OK) { + error("Error adding new nameservers"); + ldns_pkt_free(p); + return NULL; + } + ldns_rr_list_free(ns_addr); + } else { + ldns_rr_list_print(stdout, ns_addr); + error("Could not find the nameserver ip addr; abort"); + ldns_pkt_free(p); + return NULL; + } + } + + /* add the new ones */ + if (new_nss_aaaa) { + if (ldns_resolver_push_nameserver_rr_list(res, new_nss_aaaa) != + LDNS_STATUS_OK) { + error("adding new nameservers"); + ldns_pkt_free(p); + return NULL; + } + } + if (new_nss_a) { + if (ldns_resolver_push_nameserver_rr_list(res, new_nss_a) != + LDNS_STATUS_OK) { + error("adding new nameservers"); + ldns_pkt_free(p); + return NULL; + } + } + + if (loop_count++ > 20) { + /* unlikely that we are doing something usefull */ + error("Looks like we are looping"); + ldns_pkt_free(p); + return NULL; + } + + status = ldns_resolver_send(&p, res, name, t, c, 0); + new_nss_aaaa = NULL; + new_nss_a = NULL; + ns_addr = NULL; + } + + status = ldns_resolver_send(&p, res, name, t, c, 0); + + if (!p) { + return NULL; + } + + new_nss = ldns_pkt_authority(p); + final_answer = ldns_pkt_answer(p); + + if (verbosity != -1) { + ldns_rr_list_print(stdout, final_answer); + ldns_rr_list_print(stdout, new_nss); + + } + drill_pkt_print_footer(stdout, local_res, p); + ldns_pkt_free(p); + return NULL; +} + + +/** + * Chase the given rr to a known and trusted key + * + * Based on drill 0.9 + * + * the last argument prev_key_list, if not null, and type == DS, then the ds + * rr list we have must all be a ds for the keys in this list + */ +#ifdef HAVE_SSL +ldns_status +do_chase(ldns_resolver *res, + ldns_rdf *name, + ldns_rr_type type, + ldns_rr_class c, + ldns_rr_list *trusted_keys, + ldns_pkt *pkt_o, + uint16_t qflags, + ldns_rr_list * ATTR_UNUSED(prev_key_list), + int verbosity) +{ + ldns_rr_list *rrset = NULL; + ldns_status result; + ldns_rr *orig_rr = NULL; + +/* + ldns_rr_list *sigs; + ldns_rr *cur_sig; + uint16_t sig_i; + ldns_rr_list *keys; +*/ + ldns_pkt *pkt; + ldns_status tree_result; + ldns_dnssec_data_chain *chain; + ldns_dnssec_trust_tree *tree; + + const ldns_rr_descriptor *descriptor; + descriptor = ldns_rr_descript(type); + + ldns_dname2canonical(name); + + pkt = ldns_pkt_clone(pkt_o); + if (!name) { + mesg("No name to chase"); + ldns_pkt_free(pkt); + return LDNS_STATUS_EMPTY_LABEL; + } + if (verbosity != -1) { + printf(";; Chasing: "); + ldns_rdf_print(stdout, name); + if (descriptor && descriptor->_name) { + printf(" %s\n", descriptor->_name); + } else { + printf(" type %d\n", type); + } + } + + if (!trusted_keys || ldns_rr_list_rr_count(trusted_keys) < 1) { + warning("No trusted keys specified"); + } + + if (pkt) { + rrset = ldns_pkt_rr_list_by_name_and_type(pkt, + name, + type, + LDNS_SECTION_ANSWER + ); + if (!rrset) { + /* nothing in answer, try authority */ + rrset = ldns_pkt_rr_list_by_name_and_type(pkt, + name, + type, + LDNS_SECTION_AUTHORITY + ); + } + /* answer might be a cname, chase that first, then chase + cname target? (TODO) */ + if (!rrset) { + rrset = ldns_pkt_rr_list_by_name_and_type(pkt, + name, + LDNS_RR_TYPE_CNAME, + LDNS_SECTION_ANSWER + ); + if (!rrset) { + /* nothing in answer, try authority */ + rrset = ldns_pkt_rr_list_by_name_and_type(pkt, + name, + LDNS_RR_TYPE_CNAME, + LDNS_SECTION_AUTHORITY + ); + } + } + } else { + /* no packet? */ + if (verbosity >= 0) { + fprintf(stderr, "%s", ldns_get_errorstr_by_id(LDNS_STATUS_MEM_ERR)); + fprintf(stderr, "\n"); + } + return LDNS_STATUS_MEM_ERR; + } + + if (!rrset) { + /* not found in original packet, try again */ + ldns_pkt_free(pkt); + pkt = NULL; + pkt = ldns_resolver_query(res, name, type, c, qflags); + + if (!pkt) { + if (verbosity >= 0) { + fprintf(stderr, "%s", ldns_get_errorstr_by_id(LDNS_STATUS_NETWORK_ERR)); + fprintf(stderr, "\n"); + } + return LDNS_STATUS_NETWORK_ERR; + } + if (verbosity >= 5) { + ldns_pkt_print(stdout, pkt); + } + + rrset = ldns_pkt_rr_list_by_name_and_type(pkt, + name, + type, + LDNS_SECTION_ANSWER + ); + } + + orig_rr = ldns_rr_new(); + +/* if the answer had no answer section, we need to construct our own rr (for instance if + * the rr qe asked for doesn't exist. This rr will be destroyed when the chain is freed */ + if (ldns_pkt_ancount(pkt) < 1) { + ldns_rr_set_type(orig_rr, type); + ldns_rr_set_owner(orig_rr, ldns_rdf_clone(name)); + + chain = ldns_dnssec_build_data_chain(res, qflags, rrset, pkt, ldns_rr_clone(orig_rr)); + } else { + /* chase the first answer */ + chain = ldns_dnssec_build_data_chain(res, qflags, rrset, pkt, NULL); + } + + if (verbosity >= 4) { + printf("\n\nDNSSEC Data Chain:\n"); + ldns_dnssec_data_chain_print(stdout, chain); + } + + result = LDNS_STATUS_OK; + + tree = ldns_dnssec_derive_trust_tree(chain, NULL); + + if (verbosity >= 2) { + printf("\n\nDNSSEC Trust tree:\n"); + ldns_dnssec_trust_tree_print(stdout, tree, 0, true); + } + + if (ldns_rr_list_rr_count(trusted_keys) > 0) { + tree_result = ldns_dnssec_trust_tree_contains_keys(tree, trusted_keys); + + if (tree_result == LDNS_STATUS_DNSSEC_EXISTENCE_DENIED) { + if (verbosity >= 1) { + printf("Existence denied or verifiably insecure\n"); + } + result = LDNS_STATUS_OK; + } else if (tree_result != LDNS_STATUS_OK) { + if (verbosity >= 1) { + printf("No trusted keys found in tree: first error was: %s\n", ldns_get_errorstr_by_id(tree_result)); + } + result = tree_result; + } + + } else { + if (verbosity >= 0) { + printf("You have not provided any trusted keys.\n"); + } + } + + ldns_rr_free(orig_rr); + ldns_dnssec_trust_tree_free(tree); + ldns_dnssec_data_chain_deep_free(chain); + + ldns_rr_list_deep_free(rrset); + ldns_pkt_free(pkt); + /* ldns_rr_free(orig_rr);*/ + + return result; +} +#endif /* HAVE_SSL */ + diff --git a/drill/config.h.in b/drill/config.h.in new file mode 100644 index 00000000000..9b2a282a8e9 --- /dev/null +++ b/drill/config.h.in @@ -0,0 +1,293 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the header file. */ +#undef HAVE_ARPA_INET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ASSERT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_CTYPE_H + +/* Whether getaddrinfo is available */ +#undef HAVE_GETADDRINFO + +/* Define to 1 if you have the header file. */ +#undef HAVE_GETOPT_H + +/* If you have HMAC_CTX_init */ +#undef HAVE_HMAC_CTX_INIT + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `isblank' function. */ +#undef HAVE_ISBLANK + +/* Define to 1 if you have the `ldns' library (-lldns). */ +#undef HAVE_LIBLDNS + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IF_ETHER_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IN_SYSTM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IP6_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IP_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_UDP_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NET_IF_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_ERR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_RAND_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_SSL_H + +/* Define if you have the SSL libraries installed. */ +#undef HAVE_SSL + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDIO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_MOUNT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SELECT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SOCKET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_WINSOCK2_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_WS2TCPIP_H + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# undef _ALL_SOURCE +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# undef _GNU_SOURCE +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# undef _POSIX_PTHREAD_SEMANTICS +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# undef _TANDEM_SOURCE +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# undef __EXTENSIONS__ +#endif + + +/* Whether the windows socket API is used */ +#undef USE_WINSOCK + +/* the version of the windows API enabled */ +#undef WINVER + +/* Define to 1 if on MINIX. */ +#undef _MINIX + +/* Define to 2 if the system does not provide POSIX.1 features except with + this defined. */ +#undef _POSIX_1_SOURCE + +/* Define to 1 if you need to in order for `stat' and other things to work. */ +#undef _POSIX_SOURCE + +/* in_addr_t */ +#undef in_addr_t + +/* in_port_t */ +#undef in_port_t + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +#undef inline +#endif + +/* Define to `short' if does not define. */ +#undef int16_t + +/* Define to `int' if does not define. */ +#undef int32_t + +/* Define to `long long' if does not define. */ +#undef int64_t + +/* Define to `char' if does not define. */ +#undef int8_t + +/* Define to `unsigned int' if does not define. */ +#undef size_t + +/* Define to 'int' if not defined */ +#undef socklen_t + +/* Define to `int' if does not define. */ +#undef ssize_t + +/* Define to `unsigned short' if does not define. */ +#undef uint16_t + +/* Define to `unsigned int' if does not define. */ +#undef uint32_t + +/* Define to `unsigned long long' if does not define. */ +#undef uint64_t + +/* Define to `unsigned char' if does not define. */ +#undef uint8_t + + + +#include +#include +#include +#include + +#if STDC_HEADERS +#include +#include +#endif + +#ifdef HAVE_STDINT_H +#include +#endif + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#ifdef HAVE_NETINET_UDP_H +#include +#endif + +#ifdef HAVE_TIME_H +#include +#endif + +#ifdef HAVE_NETINET_IN_SYSTM_H +#include +#endif + +#ifdef HAVE_NETINET_IP_H +#include +#endif + +#ifdef HAVE_NET_IF_H +#include +#endif + +#ifdef HAVE_NETINET_IF_ETHER_H +#include +#endif + +#ifdef HAVE_WINSOCK2_H +#define USE_WINSOCK 1 +#include +#endif + +#ifdef HAVE_WS2TCPIP_H +#include +#endif + +extern char *optarg; +extern int optind, opterr; + +#ifndef EXIT_FAILURE +#define EXIT_FAILURE 1 +#endif +#ifndef EXIT_SUCCESS +#define EXIT_SUCCESS 0 +#endif + +#ifdef S_SPLINT_S +#define FD_ZERO(a) /* a */ +#define FD_SET(a,b) /* a, b */ +#endif + diff --git a/drill/configure b/drill/configure new file mode 100755 index 00000000000..95bc4356072 --- /dev/null +++ b/drill/configure @@ -0,0 +1,6678 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.68 for ldns 1.6.13. +# +# Report bugs to . +# +# +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software +# Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + # We cannot yet assume a decent shell, so we have to provide a + # neutralization value for shells without unset; and this also + # works around shells that cannot unset nonexistent variables. + # Preserve -v and -x to the replacement shell. + BASH_ENV=/dev/null + ENV=/dev/null + (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV + export CONFIG_SHELL + case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; + esac + exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"} +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org and +$0: libdns@nlnetlabs.nl about your system, including any +$0: error possibly output before this message. Then install +$0: a modern shell, or manually run the script under such a +$0: shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='ldns' +PACKAGE_TARNAME='libdns' +PACKAGE_VERSION='1.6.13' +PACKAGE_STRING='ldns 1.6.13' +PACKAGE_BUGREPORT='libdns@nlnetlabs.nl' +PACKAGE_URL='' + +ac_unique_file="drill.c" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='LTLIBOBJS +LIBOBJS +LDNSDIR +LIBS_STC +RUNTIME_PATH +HAVE_SSL +libtool +SET_MAKE +EGREP +GREP +CPP +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_rpath +with_ssl +with_ldns +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used" >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +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 ldns 1.6.13 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/libdns] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of ldns 1.6.13:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --disable-rpath disable hardcoded rpath (default=enabled) + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-ssl=pathname enable SSL (will check /usr/local/ssl /usr/lib/ssl + /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw + /usr) + --with-ldns=PATH specify prefix of path of ldns library to use + + + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CPP C preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to . +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +ldns configure 1.6.13 +generated by GNU Autoconf 2.68 + +Copyright (C) 2010 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} +( $as_echo "## ---------------------------------- ## +## Report this to libdns@nlnetlabs.nl ## +## ---------------------------------- ##" + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_check_type LINENO TYPE VAR INCLUDES +# ------------------------------------------- +# Tests whether TYPE exists after having included INCLUDES, setting cache +# variable VAR accordingly. +ac_fn_c_check_type () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof ($2)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof (($2))) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + eval "$3=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_type + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* 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 $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func +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 ldns $as_me 1.6.13, which was +generated by GNU Autoconf 2.68. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +# acx_nlnetlabs.m4 - common macros for configure checks +# Copyright 2009, Wouter Wijngaards, NLnet Labs. +# BSD licensed. +# +# Version 21 +# 2012-02-09 Fix AHX_MEMCMP_BROKEN with undef in compat/memcmp.h. +# 2012-01-20 Fix COMPILER_FLAGS_UNBOUND for gcc 4.6.2 assigned-not-used-warns. +# 2011-12-05 Fix getaddrinfowithincludes on windows with fedora16 mingw32-gcc. +# Fix ACX_MALLOC for redefined malloc error. +# Fix GETADDRINFO_WITH_INCLUDES to add -lws2_32 +# 2011-11-10 Fix FLTO test to not drop a.out in current directory. +# 2011-11-01 Fix FLTO test for llvm on Lion. +# 2011-08-01 Fix nonblock test (broken at v13). +# 2011-08-01 Fix autoconf 2.68 warnings +# 2011-06-23 Add ACX_CHECK_FLTO to check -flto. +# 2010-08-16 Fix FLAG_OMITTED for AS_TR_CPP changes in autoconf-2.66. +# 2010-07-02 Add check for ss_family (for minix). +# 2010-04-26 Fix to use CPPFLAGS for CHECK_COMPILER_FLAGS. +# 2010-03-01 Fix RPATH using CONFIG_COMMANDS to run at the very end. +# 2010-02-18 WITH_SSL outputs the LIBSSL_LDFLAGS, LIBS, CPPFLAGS seperate, -ldl +# 2010-02-01 added ACX_CHECK_MEMCMP_SIGNED, AHX_MEMCMP_BROKEN +# 2010-01-20 added AHX_COONFIG_STRLCAT +# 2009-07-14 U_CHAR detection improved for windows crosscompile. +# added ACX_FUNC_MALLOC +# fixup some #if to #ifdef +# NONBLOCKING test for mingw crosscompile. +# 2009-07-13 added ACX_WITH_SSL_OPTIONAL +# 2009-07-03 fixup LDFLAGS for empty ssl dir. +# +# Automates some of the checking constructs. Aims at portability for POSIX. +# Documentation for functions is below. +# +# the following macro's are provided in this file: +# (see below for details on each macro). +# +# ACX_ESCAPE_BACKSLASH - escape backslashes in var for C-preproc. +# ACX_RSRC_VERSION - create windows resource version number. +# ACX_CHECK_COMPILER_FLAG - see if cc supports a flag. +# ACX_CHECK_ERROR_FLAGS - see which flag is -werror (used below). +# ACX_CHECK_COMPILER_FLAG_NEEDED - see if flags make the code compile cleanly. +# ACX_DEPFLAG - find cc dependency flags. +# ACX_DETERMINE_EXT_FLAGS_UNBOUND - find out which flags enable BSD and POSIX. +# ACX_CHECK_FORMAT_ATTRIBUTE - find cc printf format syntax. +# ACX_CHECK_UNUSED_ATTRIBUTE - find cc variable unused syntax. +# ACX_CHECK_FLTO - see if cc supports -flto and use it if so. +# ACX_LIBTOOL_C_ONLY - create libtool for C only, improved. +# ACX_TYPE_U_CHAR - u_char type. +# ACX_TYPE_RLIM_T - rlim_t type. +# ACX_TYPE_SOCKLEN_T - socklen_t type. +# ACX_TYPE_IN_ADDR_T - in_addr_t type. +# ACX_TYPE_IN_PORT_T - in_port_t type. +# ACX_ARG_RPATH - add --disable-rpath option. +# ACX_WITH_SSL - add --with-ssl option, link -lcrypto. +# ACX_WITH_SSL_OPTIONAL - add --with-ssl option, link -lcrypto, +# where --without-ssl is also accepted +# ACX_LIB_SSL - setup to link -lssl. +# ACX_SYS_LARGEFILE - improved sys_largefile, fseeko, >2G files. +# ACX_CHECK_GETADDRINFO_WITH_INCLUDES - find getaddrinfo, portably. +# ACX_FUNC_DEPRECATED - see if func is deprecated. +# ACX_CHECK_NONBLOCKING_BROKEN - see if nonblocking sockets really work. +# ACX_MKDIR_ONE_ARG - determine mkdir(2) number of arguments. +# ACX_FUNC_IOCTLSOCKET - find ioctlsocket, portably. +# ACX_FUNC_MALLOC - check malloc, define replacement . +# AHX_CONFIG_FORMAT_ATTRIBUTE - config.h text for format. +# AHX_CONFIG_UNUSED_ATTRIBUTE - config.h text for unused. +# AHX_CONFIG_FSEEKO - define fseeko, ftello fallback. +# AHX_CONFIG_RAND_MAX - define RAND_MAX if needed. +# AHX_CONFIG_MAXHOSTNAMELEN - define MAXHOSTNAMELEN if needed. +# AHX_CONFIG_IPV6_MIN_MTU - define IPV6_MIN_MTU if needed. +# AHX_CONFIG_SNPRINTF - snprintf compat prototype +# AHX_CONFIG_INET_PTON - inet_pton compat prototype +# AHX_CONFIG_INET_NTOP - inet_ntop compat prototype +# AHX_CONFIG_INET_ATON - inet_aton compat prototype +# AHX_CONFIG_MEMMOVE - memmove compat prototype +# AHX_CONFIG_STRLCAT - strlcat compat prototype +# AHX_CONFIG_STRLCPY - strlcpy compat prototype +# AHX_CONFIG_GMTIME_R - gmtime_r compat prototype +# AHX_CONFIG_W32_SLEEP - w32 compat for sleep +# AHX_CONFIG_W32_USLEEP - w32 compat for usleep +# AHX_CONFIG_W32_RANDOM - w32 compat for random +# AHX_CONFIG_W32_SRANDOM - w32 compat for srandom +# AHX_CONFIG_W32_FD_SET_T - w32 detection of FD_SET_T. +# ACX_CFLAGS_STRIP - strip one flag from CFLAGS +# ACX_STRIP_EXT_FLAGS - strip extension flags from CFLAGS +# AHX_CONFIG_FLAG_OMITTED - define omitted flag +# AHX_CONFIG_FLAG_EXT - define omitted extension flag +# AHX_CONFIG_EXT_FLAGS - define the stripped extension flags +# ACX_CHECK_MEMCMP_SIGNED - check if memcmp uses signed characters. +# AHX_MEMCMP_BROKEN - replace memcmp func for CHECK_MEMCMP_SIGNED. +# ACX_CHECK_SS_FAMILY - check for sockaddr_storage.ss_family +# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +OURCPPFLAGS='' +CPPFLAGS=${CPPFLAGS:-${OURCPPFLAGS}} +OURCFLAGS='-g' +CFLAGS=${CFLAGS:-${OURCFLAGS}} + +$as_echo "#define WINVER 0x0502" >>confdefs.h + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + 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 eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default" +if test "x$ac_cv_header_minix_config_h" = xyes; then : + MINIX=yes +else + MINIX= +fi + + + if test "$MINIX" = yes; then + +$as_echo "#define _POSIX_SOURCE 1" >>confdefs.h + + +$as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h + + +$as_echo "#define _MINIX 1" >>confdefs.h + + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5 +$as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; } +if ${ac_cv_safe_to_define___extensions__+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +# define __EXTENSIONS__ 1 + $ac_includes_default +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_safe_to_define___extensions__=yes +else + ac_cv_safe_to_define___extensions__=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5 +$as_echo "$ac_cv_safe_to_define___extensions__" >&6; } + test $ac_cv_safe_to_define___extensions__ = yes && + $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h + + $as_echo "#define _ALL_SOURCE 1" >>confdefs.h + + $as_echo "#define _GNU_SOURCE 1" >>confdefs.h + + $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h + + $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h + + + +# Checks for programs. +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +for ac_prog in glibtool libtool15 libtool +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_libtool+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$libtool"; then + ac_cv_prog_libtool="$libtool" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_libtool="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +libtool=$ac_cv_prog_libtool +if test -n "$libtool"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libtool" >&5 +$as_echo "$libtool" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$libtool" && break +done +test -n "$libtool" || libtool="../libtool" + + +# add option to disable the evil rpath +# Check whether --enable-rpath was given. +if test "${enable_rpath+set}" = set; then : + enableval=$enable_rpath; enable_rpath=$enableval +else + enable_rpath=yes +fi + + +if test "x$enable_rpath" = xyes; then + RPATH_VAL="-Wl,-rpath=\${libdir}" +fi + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -std=c99" >&5 +$as_echo_n "checking whether $CC supports -std=c99... " >&6; } +cache=`echo std=c99 | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -std=c99 -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +C99FLAG="-std=c99" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: + +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -xc99" >&5 +$as_echo_n "checking whether $CC supports -xc99... " >&6; } +cache=`echo xc99 | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -xc99 -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +C99FLAG="-xc99" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: + +fi + + +ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" +if test "x$ac_cv_type_size_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned int +_ACEOF + +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -O2" >&5 +$as_echo_n "checking whether $CC supports -O2... " >&6; } +cache=`echo O2 | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -O2 -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +CFLAGS="$CFLAGS -O2" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: + +fi + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Werror" >&5 +$as_echo_n "checking whether $CC supports -Werror... " >&6; } +cache=`echo Werror | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -Werror -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +ERRFLAG="-Werror" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: +ERRFLAG="-errwarn" +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wall" >&5 +$as_echo_n "checking whether $CC supports -Wall... " >&6; } +cache=`echo Wall | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -Wall -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +ERRFLAG="$ERRFLAG -Wall" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: +ERRFLAG="$ERRFLAG -errfmt" +fi + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we need $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 as a flag for $CC" >&5 +$as_echo_n "checking whether we need $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 as a flag for $CC... " >&6; } +cache=`$as_echo "$C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600" | $as_tr_sh` +if eval \${cv_prog_cc_flag_needed_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo ' +#include "confdefs.h" +#include +#include +#include +#ifdef HAVE_TIME_H +#include +#endif +#include +#ifdef HAVE_GETOPT_H +#include +#endif + +int test() { + int a; + char **opts = NULL; + struct timeval tv; + char *t; + time_t time = 0; + char *buf = NULL; + t = ctime_r(&time, buf); + tv.tv_usec = 10; + srandom(32); + a = getopt(2, opts, "a"); + a = isascii(32); + return a; +} +' > conftest.c +echo 'void f(){}' >>conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=no" +else + +if test -z "`$CC $CPPFLAGS $CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=yes" +else +eval "cv_prog_cc_flag_needed_$cache=fail" +#echo 'Test with flag fails too!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 $ERRFLAG -c conftest.c 2>&1` +#exit 1 +fi + +fi +rm -f conftest conftest.c conftest.o + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +CFLAGS="$CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600" +else +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = no"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +#echo 'Test with flag is no!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 $ERRFLAG -c conftest.c 2>&1` +#exit 1 +: + +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +: + +fi +fi + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we need $C99FLAG as a flag for $CC" >&5 +$as_echo_n "checking whether we need $C99FLAG as a flag for $CC... " >&6; } +cache=`$as_echo "$C99FLAG" | $as_tr_sh` +if eval \${cv_prog_cc_flag_needed_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo '#include ' > conftest.c +echo 'void f(){}' >>conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=no" +else + +if test -z "`$CC $CPPFLAGS $CFLAGS $C99FLAG $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=yes" +else +eval "cv_prog_cc_flag_needed_$cache=fail" +#echo 'Test with flag fails too!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS $C99FLAG $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS $C99FLAG $ERRFLAG -c conftest.c 2>&1` +#exit 1 +fi + +fi +rm -f conftest conftest.c conftest.o + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +CFLAGS="$CFLAGS $C99FLAG" +else +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = no"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +#echo 'Test with flag is no!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS $C99FLAG $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS $C99FLAG $ERRFLAG -c conftest.c 2>&1` +#exit 1 +: + +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +: + +fi +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 +$as_echo_n "checking for inline... " >&6; } +if ${ac_cv_c_inline+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __cplusplus +typedef int foo_t; +static $ac_kw foo_t static_foo () {return 0; } +$ac_kw foo_t foo () {return 0; } +#endif + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_inline=$ac_kw +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test "$ac_cv_c_inline" != no && break +done + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 +$as_echo "$ac_cv_c_inline" >&6; } + +case $ac_cv_c_inline in + inline | yes) ;; + *) + case $ac_cv_c_inline in + no) ac_val=;; + *) ac_val=$ac_cv_c_inline;; + esac + cat >>confdefs.h <<_ACEOF +#ifndef __cplusplus +#define inline $ac_val +#endif +_ACEOF + ;; +esac + +ac_fn_c_check_type "$LINENO" "int8_t" "ac_cv_type_int8_t" "$ac_includes_default" +if test "x$ac_cv_type_int8_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define int8_t char +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "int16_t" "ac_cv_type_int16_t" "$ac_includes_default" +if test "x$ac_cv_type_int16_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define int16_t short +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "int32_t" "ac_cv_type_int32_t" "$ac_includes_default" +if test "x$ac_cv_type_int32_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define int32_t int +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "int64_t" "ac_cv_type_int64_t" "$ac_includes_default" +if test "x$ac_cv_type_int64_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define int64_t long long +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "uint8_t" "ac_cv_type_uint8_t" "$ac_includes_default" +if test "x$ac_cv_type_uint8_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define uint8_t unsigned char +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "uint16_t" "ac_cv_type_uint16_t" "$ac_includes_default" +if test "x$ac_cv_type_uint16_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define uint16_t unsigned short +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "uint32_t" "ac_cv_type_uint32_t" "$ac_includes_default" +if test "x$ac_cv_type_uint32_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define uint32_t unsigned int +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "uint64_t" "ac_cv_type_uint64_t" "$ac_includes_default" +if test "x$ac_cv_type_uint64_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define uint64_t unsigned long long +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "ssize_t" "ac_cv_type_ssize_t" "$ac_includes_default" +if test "x$ac_cv_type_ssize_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define ssize_t int +_ACEOF + +fi + + +for ac_header in sys/types.h getopt.h stdlib.h stdio.h assert.h netinet/in.h ctype.h time.h arpa/inet.h sys/time.h sys/socket.h sys/select.h +do : + 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 eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in netinet/in_systm.h net/if.h netinet/ip.h netinet/udp.h netinet/if_ether.h netinet/ip6.h +do : + 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 +#ifdef HAVE_NETINET_IN_SYSTM_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +# MinGW32 tests +for ac_header in winsock2.h ws2tcpip.h +do : + 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 eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + +ac_fn_c_check_type "$LINENO" "socklen_t" "ac_cv_type_socklen_t" " +$ac_includes_default +#ifdef HAVE_SYS_SOCKET_H +# include +#endif +#ifdef HAVE_WS2TCPIP_H +# include +#endif + +" +if test "x$ac_cv_type_socklen_t" = xyes; then : + +else + +$as_echo "#define socklen_t int" >>confdefs.h + +fi + +for ac_header in sys/param.h sys/mount.h +do : + 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 HAVE_SYS_PARAM_H + # include + #endif + + +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +ac_fn_c_check_type "$LINENO" "in_addr_t" "ac_cv_type_in_addr_t" " +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_NETINET_IN_H +# include +#endif +" +if test "x$ac_cv_type_in_addr_t" = xyes; then : + +else + +$as_echo "#define in_addr_t uint32_t" >>confdefs.h + +fi + +ac_fn_c_check_type "$LINENO" "in_port_t" "ac_cv_type_in_port_t" " +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_NETINET_IN_H +# include +#endif +" +if test "x$ac_cv_type_in_port_t" = xyes; then : + +else + +$as_echo "#define in_port_t uint16_t" >>confdefs.h + +fi + + +# check to see if libraries are needed for these functions. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing socket" >&5 +$as_echo_n "checking for library containing socket... " >&6; } +if ${ac_cv_search_socket+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +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 socket (); +int +main () +{ +return socket (); + ; + return 0; +} +_ACEOF +for ac_lib in '' socket; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_socket=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_socket+:} false; then : + break +fi +done +if ${ac_cv_search_socket+:} false; then : + +else + ac_cv_search_socket=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_socket" >&5 +$as_echo "$ac_cv_search_socket" >&6; } +ac_res=$ac_cv_search_socket +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing inet_pton" >&5 +$as_echo_n "checking for library containing inet_pton... " >&6; } +if ${ac_cv_search_inet_pton+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +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 inet_pton (); +int +main () +{ +return inet_pton (); + ; + return 0; +} +_ACEOF +for ac_lib in '' nsl; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_inet_pton=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_inet_pton+:} false; then : + break +fi +done +if ${ac_cv_search_inet_pton+:} false; then : + +else + ac_cv_search_inet_pton=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_inet_pton" >&5 +$as_echo "$ac_cv_search_inet_pton" >&6; } +ac_res=$ac_cv_search_inet_pton +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + + + + +# Check whether --with-ssl was given. +if test "${with_ssl+set}" = set; then : + withval=$with_ssl; + +else + + withval="yes" + +fi + + + withval=$withval + if test x_$withval != x_no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL" >&5 +$as_echo_n "checking for SSL... " >&6; } + if test x_$withval = x_ -o x_$withval = x_yes; then + withval="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw /usr" + fi + for dir in $withval; do + ssldir="$dir" + if test -f "$dir/include/openssl/ssl.h"; then + found_ssl="yes" + +cat >>confdefs.h <<_ACEOF +#define HAVE_SSL /**/ +_ACEOF + + if test "$ssldir" != "/usr"; then + CPPFLAGS="$CPPFLAGS -I$ssldir/include" + LIBSSL_CPPFLAGS="$LIBSSL_CPPFLAGS -I$ssldir/include" + fi + break; + fi + done + if test x_$found_ssl != x_yes; then + as_fn_error $? "Cannot find the SSL libraries in $withval" "$LINENO" 5 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in $ssldir" >&5 +$as_echo "found in $ssldir" >&6; } + HAVE_SSL=yes + if test "$ssldir" != "/usr" -a "$ssldir" != ""; then + LDFLAGS="$LDFLAGS -L$ssldir/lib" + LIBSSL_LDFLAGS="$LIBSSL_LDFLAGS -L$ssldir/lib" + + if test "x$enable_rpath" = xyes; then + if echo "$ssldir/lib" | grep "^/" >/dev/null; then + RUNTIME_PATH="$RUNTIME_PATH -R$ssldir/lib" + fi + fi + + 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; } + LIBS="$LIBS -lcrypto" + LIBSSL_LIBS="$LIBSSL_LIBS -lcrypto" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + int HMAC_CTX_init(void); + (void)HMAC_CTX_init(); + + ; + return 0; +} +_ACEOF +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 + + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + # check if -lwsock32 or -lgdi32 are needed. + BAKLIBS="$LIBS" + BAKSSLLIBS="$LIBSSL_LIBS" + LIBS="$LIBS -lgdi32" + LIBSSL_LIBS="$LIBSSL_LIBS -lgdi32" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if -lcrypto needs -lgdi32" >&5 +$as_echo_n "checking if -lcrypto needs -lgdi32... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + int HMAC_CTX_init(void); + (void)HMAC_CTX_init(); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + +$as_echo "#define HAVE_HMAC_CTX_INIT 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; } + LIBS="$BAKLIBS" + LIBSSL_LIBS="$BAKSSLLIBS" + LIBS="$LIBS -ldl" + LIBSSL_LIBS="$LIBSSL_LIBS -ldl" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if -lcrypto needs -ldl" >&5 +$as_echo_n "checking if -lcrypto needs -ldl... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + int HMAC_CTX_init(void); + (void)HMAC_CTX_init(); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + +$as_echo "#define HAVE_HMAC_CTX_INIT 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 \ + conftest$ac_exeext conftest.$ac_ext + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + fi + + + # openssl engine functionality needs dlopen(). + BAKLIBS="$LIBS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5 +$as_echo_n "checking for library containing dlopen... " >&6; } +if ${ac_cv_search_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +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 dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +for ac_lib in '' dl; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_dlopen=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_dlopen+:} false; then : + break +fi +done +if ${ac_cv_search_dlopen+:} false; then : + +else + ac_cv_search_dlopen=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5 +$as_echo "$ac_cv_search_dlopen" >&6; } +ac_res=$ac_cv_search_dlopen +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + + if test "$LIBS" != "$BAKLIBS"; then + LIBSSL_LIBS="$LIBSSL_LIBS -ldl" + fi + fi +for ac_header in openssl/ssl.h +do : + ac_fn_c_check_header_compile "$LINENO" "openssl/ssl.h" "ac_cv_header_openssl_ssl_h" "$ac_includes_default +" +if test "x$ac_cv_header_openssl_ssl_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OPENSSL_SSL_H 1 +_ACEOF + +fi + +done + +for ac_header in openssl/err.h +do : + ac_fn_c_check_header_compile "$LINENO" "openssl/err.h" "ac_cv_header_openssl_err_h" "$ac_includes_default +" +if test "x$ac_cv_header_openssl_err_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OPENSSL_ERR_H 1 +_ACEOF + +fi + +done + +for ac_header in openssl/rand.h +do : + ac_fn_c_check_header_compile "$LINENO" "openssl/rand.h" "ac_cv_header_openssl_rand_h" "$ac_includes_default +" +if test "x$ac_cv_header_openssl_rand_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OPENSSL_RAND_H 1 +_ACEOF + +fi + +done + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for getaddrinfo" >&5 +$as_echo_n "checking for getaddrinfo... " >&6; } +ac_cv_func_getaddrinfo=no +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#ifdef __cplusplus +extern "C" +{ +#endif +char* getaddrinfo(); +char* (*f) () = getaddrinfo; +#ifdef __cplusplus +} +#endif +int main() { + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_func_getaddrinfo="yes" +if test "$ac_cv_header_windows_h" = "yes"; then + +$as_echo "#define USE_WINSOCK 1" >>confdefs.h + + USE_WINSOCK="1" + LIBS="$LIBS -lws2_32" +fi + +else + ORIGLIBS="$LIBS" +LIBS="$LIBS -lws2_32" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#ifdef HAVE_WS2TCPIP_H +#include +#endif + +int +main () +{ + + (void)getaddrinfo(NULL, NULL, NULL, NULL); + + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + +ac_cv_func_getaddrinfo="yes" + +$as_echo "#define USE_WINSOCK 1" >>confdefs.h + +USE_WINSOCK="1" + +else + +ac_cv_func_getaddrinfo="no" +LIBS="$ORIGLIBS" + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_getaddrinfo" >&5 +$as_echo "$ac_cv_func_getaddrinfo" >&6; } +if test $ac_cv_func_getaddrinfo = yes; then + +$as_echo "#define HAVE_GETADDRINFO 1" >>confdefs.h + +fi + + +LIBS_STC="$LIBS" + + +# check for ldns + +# Check whether --with-ldns was given. +if test "${with_ldns+set}" = set; then : + withval=$with_ldns; + specialldnsdir="$withval" + CPPFLAGS="$CPPFLAGS -I$withval/include" + LDFLAGS="-L$withval -L$withval/lib $LDFLAGS" + LDNSDIR="$withval" + LIBS="-lldns $LIBS" + LIBS_STC="$withval/lib/libldns.a $LIBS_STC" + + +fi + + +#AC_CHECK_HEADER(ldns/ldns.h,, [ +# AC_MSG_ERROR([Can't find ldns headers (make copy-headers in devel source.)]) +# ], [AC_INCLUDES_DEFAULT] +#) + +for ac_func in isblank +do : + ac_fn_c_check_func "$LINENO" "isblank" "ac_cv_func_isblank" +if test "x$ac_cv_func_isblank" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_ISBLANK 1 +_ACEOF + +fi +done + + +# check for ldns development source tree +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ldns devel source" >&5 +$as_echo_n "checking for ldns devel source... " >&6; } +ldns_dev_dir=.. +if test -f $ldns_dev_dir/ldns/util.h && \ + grep LDNS_VERSION $ldns_dev_dir/ldns/util.h >/dev/null; then + ldns_version=`grep LDNS_VERSION $ldns_dev_dir/ldns/util.h | sed -e 's/^.*"\(.*\)".*$/\1/'` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: using $ldns_dev_dir with $ldns_version" >&5 +$as_echo "using $ldns_dev_dir with $ldns_version" >&6; } + CPPFLAGS="$CPPFLAGS -I$ldns_dev_dir/include" + LDFLAGS="-L$ldns_dev_dir -L$ldns_dev_dir/lib $LDFLAGS" + LIBS="-lldns $LIBS" + +$as_echo "#define HAVE_LIBLDNS 1" >>confdefs.h + + LDNSDIR="$ldns_dev_dir" + LIBS_STC="$ldns_dev_dir/lib/libldns.a $LIBS_STC" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ldns_rr_new in -lldns" >&5 +$as_echo_n "checking for ldns_rr_new in -lldns... " >&6; } +if ${ac_cv_lib_ldns_ldns_rr_new+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lldns $LIBS" +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 ldns_rr_new (); +int +main () +{ +return ldns_rr_new (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_ldns_ldns_rr_new=yes +else + ac_cv_lib_ldns_ldns_rr_new=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ldns_ldns_rr_new" >&5 +$as_echo "$ac_cv_lib_ldns_ldns_rr_new" >&6; } +if test "x$ac_cv_lib_ldns_ldns_rr_new" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBLDNS 1 +_ACEOF + + LIBS="-lldns $LIBS" + +else + + as_fn_error $? "Can't find ldns library" "$LINENO" 5 + + +fi + +fi + + + + + +ac_config_files="$ac_config_files Makefile" + +ac_config_headers="$ac_config_headers config.h" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by ldns $as_me 1.6.13, which was +generated by GNU Autoconf 2.68. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Report bugs to ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +ldns config.status 1.6.13 +configured by $0, generated by GNU Autoconf 2.68, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2010 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi + ;; + + + esac + +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + diff --git a/drill/configure.ac b/drill/configure.ac new file mode 100644 index 00000000000..afd5c63803b --- /dev/null +++ b/drill/configure.ac @@ -0,0 +1,259 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ(2.56) +AC_INIT(ldns, 1.6.13, libdns@nlnetlabs.nl,libdns) +AC_CONFIG_SRCDIR([drill.c]) +sinclude(../acx_nlnetlabs.m4) + +OURCPPFLAGS='' +CPPFLAGS=${CPPFLAGS:-${OURCPPFLAGS}} +OURCFLAGS='-g' +CFLAGS=${CFLAGS:-${OURCFLAGS}} +AC_DEFINE(WINVER, 0x0502, [the version of the windows API enabled]) + +AC_AIX +# Checks for programs. +AC_PROG_CC +AC_PROG_MAKE_SET +AC_CHECK_PROGS(libtool, [glibtool libtool15 libtool], [../libtool]) + +# add option to disable the evil rpath +dnl Check whether to use rpath or not +AC_ARG_ENABLE(rpath, + [ --disable-rpath disable hardcoded rpath (default=enabled)], + enable_rpath=$enableval, enable_rpath=yes) + +if test "x$enable_rpath" = xyes; then + RPATH_VAL="-Wl,-rpath=\${libdir}" +fi + + +ACX_CHECK_COMPILER_FLAG(std=c99, [C99FLAG="-std=c99"]) +ACX_CHECK_COMPILER_FLAG(xc99, [C99FLAG="-xc99"]) + +AC_TYPE_SIZE_T +ACX_CHECK_COMPILER_FLAG(O2, [CFLAGS="$CFLAGS -O2"]) + +ACX_CHECK_COMPILER_FLAG_NEEDED($C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600, +[ +#include "confdefs.h" +#include +#include +#include +#ifdef HAVE_TIME_H +#include +#endif +#include +#ifdef HAVE_GETOPT_H +#include +#endif + +int test() { + int a; + char **opts = NULL; + struct timeval tv; + char *t; + time_t time = 0; + char *buf = NULL; + t = ctime_r(&time, buf); + tv.tv_usec = 10; + srandom(32); + a = getopt(2, opts, "a"); + a = isascii(32); + return a; +} +], [CFLAGS="$CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600"]) + + +ACX_CHECK_COMPILER_FLAG_NEEDED($C99FLAG, [#include ], [CFLAGS="$CFLAGS $C99FLAG"]) + +AC_C_INLINE +AC_CHECK_TYPE(int8_t, char) +AC_CHECK_TYPE(int16_t, short) +AC_CHECK_TYPE(int32_t, int) +AC_CHECK_TYPE(int64_t, long long) +AC_CHECK_TYPE(uint8_t, unsigned char) +AC_CHECK_TYPE(uint16_t, unsigned short) +AC_CHECK_TYPE(uint32_t, unsigned int) +AC_CHECK_TYPE(uint64_t, unsigned long long) +AC_CHECK_TYPE(ssize_t, int) + +AC_CHECK_HEADERS([sys/types.h getopt.h stdlib.h stdio.h assert.h netinet/in.h ctype.h time.h arpa/inet.h sys/time.h sys/socket.h sys/select.h],,, [AC_INCLUDES_DEFAULT]) +AC_CHECK_HEADERS([netinet/in_systm.h net/if.h netinet/ip.h netinet/udp.h netinet/if_ether.h netinet/ip6.h],,, [ +AC_INCLUDES_DEFAULT +#ifdef HAVE_NETINET_IN_SYSTM_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif]) +# MinGW32 tests +AC_CHECK_HEADERS([winsock2.h ws2tcpip.h],,, [AC_INCLUDES_DEFAULT]) + +ACX_TYPE_SOCKLEN_T +AC_CHECK_HEADERS([sys/param.h sys/mount.h],,, +[AC_INCLUDES_DEFAULT] +[ + [ + #if HAVE_SYS_PARAM_H + # include + #endif + ] +]) +AC_CHECK_TYPE(in_addr_t, [], [AC_DEFINE([in_addr_t], [uint32_t], [in_addr_t])], [ +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_NETINET_IN_H +# include +#endif]) +AC_CHECK_TYPE(in_port_t, [], [AC_DEFINE([in_port_t], [uint16_t], [in_port_t])], [ +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_NETINET_IN_H +# include +#endif]) + +# check to see if libraries are needed for these functions. +AC_SEARCH_LIBS(socket, socket) +AC_SEARCH_LIBS([inet_pton], [nsl]) + +ACX_WITH_SSL_OPTIONAL + +ACX_CHECK_GETADDRINFO_WITH_INCLUDES + +LIBS_STC="$LIBS" +AC_SUBST(LIBS_STC) + +# check for ldns +AC_ARG_WITH(ldns, + AC_HELP_STRING([--with-ldns=PATH specify prefix of path of ldns library to use]) + , + [ + specialldnsdir="$withval" + CPPFLAGS="$CPPFLAGS -I$withval/include" + LDFLAGS="-L$withval -L$withval/lib $LDFLAGS" + LDNSDIR="$withval" + LIBS="-lldns $LIBS" + LIBS_STC="$withval/lib/libldns.a $LIBS_STC" + ] +) + +#AC_CHECK_HEADER(ldns/ldns.h,, [ +# AC_MSG_ERROR([Can't find ldns headers (make copy-headers in devel source.)]) +# ], [AC_INCLUDES_DEFAULT] +#) + +AC_CHECK_FUNCS(isblank) + +# check for ldns development source tree +AC_MSG_CHECKING([for ldns devel source]) +ldns_dev_dir=.. +if test -f $ldns_dev_dir/ldns/util.h && \ + grep LDNS_VERSION $ldns_dev_dir/ldns/util.h >/dev/null; then + ldns_version=`grep LDNS_VERSION $ldns_dev_dir/ldns/util.h | sed -e 's/^.*"\(.*\)".*$/\1/'` + AC_MSG_RESULT([using $ldns_dev_dir with $ldns_version]) + CPPFLAGS="$CPPFLAGS -I$ldns_dev_dir/include" + LDFLAGS="-L$ldns_dev_dir -L$ldns_dev_dir/lib $LDFLAGS" + LIBS="-lldns $LIBS" + AC_DEFINE(HAVE_LIBLDNS, 1, [If the ldns library is available.]) + LDNSDIR="$ldns_dev_dir" + LIBS_STC="$ldns_dev_dir/lib/libldns.a $LIBS_STC" +else + AC_MSG_RESULT([no]) + AC_CHECK_LIB(ldns, ldns_rr_new, , [ + AC_MSG_ERROR([Can't find ldns library]) + ] + ) +fi + +AC_SUBST(LDNSDIR) + +AH_BOTTOM([ + +#include +#include +#include +#include + +#if STDC_HEADERS +#include +#include +#endif + +#ifdef HAVE_STDINT_H +#include +#endif + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#ifdef HAVE_NETINET_UDP_H +#include +#endif + +#ifdef HAVE_TIME_H +#include +#endif + +#ifdef HAVE_NETINET_IN_SYSTM_H +#include +#endif + +#ifdef HAVE_NETINET_IP_H +#include +#endif + +#ifdef HAVE_NET_IF_H +#include +#endif + +#ifdef HAVE_NETINET_IF_ETHER_H +#include +#endif + +#ifdef HAVE_WINSOCK2_H +#define USE_WINSOCK 1 +#include +#endif + +#ifdef HAVE_WS2TCPIP_H +#include +#endif + +extern char *optarg; +extern int optind, opterr; + +#ifndef EXIT_FAILURE +#define EXIT_FAILURE 1 +#endif +#ifndef EXIT_SUCCESS +#define EXIT_SUCCESS 0 +#endif + +#ifdef S_SPLINT_S +#define FD_ZERO(a) /* a */ +#define FD_SET(a,b) /* a, b */ +#endif +]) + +AC_CONFIG_FILES([Makefile]) +AC_CONFIG_HEADER([config.h]) +AC_OUTPUT diff --git a/drill/dnssec.c b/drill/dnssec.c new file mode 100644 index 00000000000..b72ffb95dad --- /dev/null +++ b/drill/dnssec.c @@ -0,0 +1,473 @@ +/* + * dnssec.c + * Some DNSSEC helper function are defined here + * and tracing is done + * (c) 2005 NLnet Labs + * + * See the file LICENSE for the license + * + */ + +#include "drill.h" +#include + +/* get rr_type from a server from a server */ +ldns_rr_list * +get_rr(ldns_resolver *res, ldns_rdf *zname, ldns_rr_type t, ldns_rr_class c) +{ + /* query, retrieve, extract and return */ + ldns_pkt *p; + ldns_rr_list *found; + + p = ldns_pkt_new(); + found = NULL; + + if (ldns_resolver_send(&p, res, zname, t, c, 0) != LDNS_STATUS_OK) { + /* oops */ + return NULL; + } else { + found = ldns_pkt_rr_list_by_type(p, t, LDNS_SECTION_ANY_NOQUESTION); + } + return found; +} + +void +drill_pkt_print(FILE *fd, ldns_resolver *r, ldns_pkt *p) +{ + ldns_rr_list *new_nss; + ldns_rr_list *hostnames; + + if (verbosity < 5) { + return; + } + + hostnames = ldns_get_rr_list_name_by_addr(r, ldns_pkt_answerfrom(p), 0, 0); + + new_nss = ldns_pkt_rr_list_by_type(p, + LDNS_RR_TYPE_NS, LDNS_SECTION_ANSWER); + ldns_rr_list_print(fd, new_nss); + + /* new_nss can be empty.... */ + + fprintf(fd, ";; Received %d bytes from %s#%d(", + (int) ldns_pkt_size(p), + ldns_rdf2str(ldns_pkt_answerfrom(p)), + (int) ldns_resolver_port(r)); + /* if we can resolve this print it, other print the ip again */ + if (hostnames) { + ldns_rdf_print(fd, + ldns_rr_rdf(ldns_rr_list_rr(hostnames, 0), 0)); + ldns_rr_list_deep_free(hostnames); + } else { + fprintf(fd, "%s", ldns_rdf2str(ldns_pkt_answerfrom(p))); + } + fprintf(fd, ") in %u ms\n\n", (unsigned int)ldns_pkt_querytime(p)); +} + +void +drill_pkt_print_footer(FILE *fd, ldns_resolver *r, ldns_pkt *p) +{ + ldns_rr_list *hostnames; + + if (verbosity < 5) { + return; + } + + hostnames = ldns_get_rr_list_name_by_addr(r, ldns_pkt_answerfrom(p), 0, 0); + + fprintf(fd, ";; Received %d bytes from %s#%d(", + (int) ldns_pkt_size(p), + ldns_rdf2str(ldns_pkt_answerfrom(p)), + (int) ldns_resolver_port(r)); + /* if we can resolve this print it, other print the ip again */ + if (hostnames) { + ldns_rdf_print(fd, + ldns_rr_rdf(ldns_rr_list_rr(hostnames, 0), 0)); + ldns_rr_list_deep_free(hostnames); + } else { + fprintf(fd, "%s", ldns_rdf2str(ldns_pkt_answerfrom(p))); + } + fprintf(fd, ") in %u ms\n\n", (unsigned int)ldns_pkt_querytime(p)); +} +/* + * generic function to get some RRset from a nameserver + * and possible some signatures too (that would be the day...) + */ +ldns_pkt_type +get_dnssec_rr(ldns_pkt *p, ldns_rdf *name, ldns_rr_type t, + ldns_rr_list **rrlist, ldns_rr_list **sig) +{ + ldns_pkt_type pt = LDNS_PACKET_UNKNOWN; + ldns_rr_list *rr = NULL; + ldns_rr_list *sigs = NULL; + size_t i; + + if (!p) { + if (rrlist) { + *rrlist = NULL; + } + return LDNS_PACKET_UNKNOWN; + } + + pt = ldns_pkt_reply_type(p); + if (name) { + rr = ldns_pkt_rr_list_by_name_and_type(p, name, t, LDNS_SECTION_ANSWER); + if (!rr) { + rr = ldns_pkt_rr_list_by_name_and_type(p, name, t, LDNS_SECTION_AUTHORITY); + } + sigs = ldns_pkt_rr_list_by_name_and_type(p, name, LDNS_RR_TYPE_RRSIG, + LDNS_SECTION_ANSWER); + if (!sigs) { + sigs = ldns_pkt_rr_list_by_name_and_type(p, name, LDNS_RR_TYPE_RRSIG, + LDNS_SECTION_AUTHORITY); + } + } else { + /* A DS-referral - get the DS records if they are there */ + rr = ldns_pkt_rr_list_by_type(p, t, LDNS_SECTION_AUTHORITY); + sigs = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_RRSIG, + LDNS_SECTION_AUTHORITY); + } + if (sig) { + *sig = ldns_rr_list_new(); + for (i = 0; i < ldns_rr_list_rr_count(sigs); i++) { + /* only add the sigs that cover this type */ + if (ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(ldns_rr_list_rr(sigs, i))) == + t) { + ldns_rr_list_push_rr(*sig, ldns_rr_clone(ldns_rr_list_rr(sigs, i))); + } + } + } + ldns_rr_list_deep_free(sigs); + if (rrlist) { + *rrlist = rr; + } + + if (pt == LDNS_PACKET_NXDOMAIN || pt == LDNS_PACKET_NODATA) { + return pt; + } else { + return LDNS_PACKET_ANSWER; + } +} + + +ldns_status +ldns_verify_denial(ldns_pkt *pkt, ldns_rdf *name, ldns_rr_type type, ldns_rr_list **nsec_rrs, ldns_rr_list **nsec_rr_sigs) +{ + uint16_t nsec_i; + + ldns_rr_list *nsecs; + ldns_status result; + + if (verbosity >= 5) { + printf("VERIFY DENIAL FROM:\n"); + ldns_pkt_print(stdout, pkt); + } + + result = LDNS_STATUS_CRYPTO_NO_RRSIG; + /* Try to see if there are NSECS in the packet */ + nsecs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_NSEC, LDNS_SECTION_ANY_NOQUESTION); + if (nsecs) { + for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsecs); nsec_i++) { + /* there are four options: + * - name equals ownername and is covered by the type bitmap + * - name equals ownername but is not covered by the type bitmap + * - name falls within nsec coverage but is not equal to the owner name + * - name falls outside of nsec coverage + */ + if (ldns_dname_compare(ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), name) == 0) { + /* + printf("CHECKING NSEC:\n"); + ldns_rr_print(stdout, ldns_rr_list_rr(nsecs, nsec_i)); + printf("DAWASEM\n"); + */ + if (ldns_nsec_bitmap_covers_type( + ldns_nsec_get_bitmap(ldns_rr_list_rr(nsecs, + nsec_i)), + type)) { + /* Error, according to the nsec this rrset is signed */ + result = LDNS_STATUS_CRYPTO_NO_RRSIG; + } else { + /* ok nsec denies existence */ + if (verbosity >= 3) { + printf(";; Existence of data set with this type denied by NSEC\n"); + } + /*printf(";; Verifiably insecure.\n");*/ + if (nsec_rrs && nsec_rr_sigs) { + (void) get_dnssec_rr(pkt, ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), LDNS_RR_TYPE_NSEC, nsec_rrs, nsec_rr_sigs); + } + ldns_rr_list_deep_free(nsecs); + return LDNS_STATUS_OK; + } + } else if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, nsec_i), name)) { + if (verbosity >= 3) { + printf(";; Existence of data set with this name denied by NSEC\n"); + } + if (nsec_rrs && nsec_rr_sigs) { + (void) get_dnssec_rr(pkt, ldns_rr_owner(ldns_rr_list_rr(nsecs, nsec_i)), LDNS_RR_TYPE_NSEC, nsec_rrs, nsec_rr_sigs); + } + ldns_rr_list_deep_free(nsecs); + return LDNS_STATUS_OK; + } else { + /* nsec has nothing to do with this data */ + } + } + ldns_rr_list_deep_free(nsecs); + } else if( (nsecs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_NSEC3, LDNS_SECTION_ANY_NOQUESTION)) ) { + ldns_rr_list* sigs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_RRSIG, LDNS_SECTION_ANY_NOQUESTION); + ldns_rr* q = ldns_rr_new(); + ldns_rr* match = NULL; + if(!sigs) return LDNS_STATUS_MEM_ERR; + if(!q) return LDNS_STATUS_MEM_ERR; + ldns_rr_set_question(q, 1); + ldns_rr_set_ttl(q, 0); + ldns_rr_set_owner(q, ldns_rdf_clone(name)); + if(!ldns_rr_owner(q)) return LDNS_STATUS_MEM_ERR; + ldns_rr_set_type(q, type); + + /* result = ldns_dnssec_verify_denial_nsec3(q, nsecs, sigs, ldns_pkt_get_rcode(pkt), type, ldns_pkt_ancount(pkt) == 0); */ + result = ldns_dnssec_verify_denial_nsec3_match(q, nsecs, sigs, ldns_pkt_get_rcode(pkt), type, ldns_pkt_ancount(pkt) == 0, &match); + if (result == LDNS_STATUS_OK && match && nsec_rrs && nsec_rr_sigs) { + (void) get_dnssec_rr(pkt, ldns_rr_owner(match), LDNS_RR_TYPE_NSEC3, nsec_rrs, nsec_rr_sigs); + } + ldns_rr_free(q); + ldns_rr_list_deep_free(nsecs); + ldns_rr_list_deep_free(sigs); + } + return result; +} + +/* NSEC3 draft -07 */ +/*return hash name match*/ +ldns_rr * +ldns_nsec3_exact_match(ldns_rdf *qname, ldns_rr_type qtype, ldns_rr_list *nsec3s) { + uint8_t algorithm; + uint32_t iterations; + uint8_t salt_length; + uint8_t *salt; + + ldns_rdf *sname = NULL, *hashed_sname = NULL; + + size_t nsec_i; + ldns_rr *nsec; + ldns_rr *result = NULL; + + const ldns_rr_descriptor *descriptor; + + ldns_rdf *zone_name = NULL; + + if (verbosity >= 4) { + printf(";; finding exact match for "); + descriptor = ldns_rr_descript(qtype); + if (descriptor && descriptor->_name) { + printf("%s ", descriptor->_name); + } else { + printf("TYPE%d ", qtype); + } + ldns_rdf_print(stdout, qname); + printf("\n"); + } + + if (!qname || !nsec3s || ldns_rr_list_rr_count(nsec3s) < 1) { + if (verbosity >= 4) { + printf("no qname, nsec3s or list empty\n"); + } + return NULL; + } + + nsec = ldns_rr_list_rr(nsec3s, 0); + algorithm = ldns_nsec3_algorithm(nsec); + salt_length = ldns_nsec3_salt_length(nsec); + salt = ldns_nsec3_salt_data(nsec); + iterations = ldns_nsec3_iterations(nsec); + if (salt == NULL) { + goto done; + } + + sname = ldns_rdf_clone(qname); + if (sname == NULL) { + goto done; + } + if (verbosity >= 4) { + printf(";; owner name hashes to: "); + } + hashed_sname = ldns_nsec3_hash_name(sname, algorithm, iterations, salt_length, salt); + if (hashed_sname == NULL) { + goto done; + } + zone_name = ldns_dname_left_chop(ldns_rr_owner(nsec)); + if (zone_name == NULL) { + goto done; + } + if (ldns_dname_cat(hashed_sname, zone_name) != LDNS_STATUS_OK) { + goto done; + }; + + if (verbosity >= 4) { + ldns_rdf_print(stdout, hashed_sname); + printf("\n"); + } + + for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsec3s); nsec_i++) { + nsec = ldns_rr_list_rr(nsec3s, nsec_i); + + /* check values of iterations etc! */ + + /* exact match? */ + if (ldns_dname_compare(ldns_rr_owner(nsec), hashed_sname) == 0) { + result = nsec; + goto done; + } + + } + +done: + ldns_rdf_deep_free(zone_name); + ldns_rdf_deep_free(sname); + ldns_rdf_deep_free(hashed_sname); + LDNS_FREE(salt); + + if (verbosity >= 4) { + if (result) { + printf(";; Found.\n"); + } else { + printf(";; Not foud.\n"); + } + } + return result; +} + +/*return the owner name of the closest encloser for name from the list of rrs */ +/* this is NOT the hash, but the original name! */ +ldns_rdf * +ldns_nsec3_closest_encloser(ldns_rdf *qname, ldns_rr_type qtype, ldns_rr_list *nsec3s) +{ + /* remember parameters, they must match */ + uint8_t algorithm; + uint32_t iterations; + uint8_t salt_length; + uint8_t *salt; + + ldns_rdf *sname = NULL, *hashed_sname = NULL, *tmp; + bool flag; + + bool exact_match_found; + bool in_range_found; + + ldns_rdf *zone_name = NULL; + + size_t nsec_i; + ldns_rr *nsec; + ldns_rdf *result = NULL; + + if (!qname || !nsec3s || ldns_rr_list_rr_count(nsec3s) < 1) { + return NULL; + } + + if (verbosity >= 4) { + printf(";; finding closest encloser for type %d ", qtype); + ldns_rdf_print(stdout, qname); + printf("\n"); + } + + nsec = ldns_rr_list_rr(nsec3s, 0); + algorithm = ldns_nsec3_algorithm(nsec); + salt_length = ldns_nsec3_salt_length(nsec); + salt = ldns_nsec3_salt_data(nsec); + iterations = ldns_nsec3_iterations(nsec); + if (salt == NULL) { + goto done; + } + + sname = ldns_rdf_clone(qname); + if (sname == NULL) { + goto done; + } + + flag = false; + + zone_name = ldns_dname_left_chop(ldns_rr_owner(nsec)); + if (zone_name == NULL) { + goto done; + } + + /* algorithm from nsec3-07 8.3 */ + while (ldns_dname_label_count(sname) > 0) { + exact_match_found = false; + in_range_found = false; + + if (verbosity >= 3) { + printf(";; "); + ldns_rdf_print(stdout, sname); + printf(" hashes to: "); + } + hashed_sname = ldns_nsec3_hash_name(sname, algorithm, iterations, salt_length, salt); + if (hashed_sname == NULL) { + goto done; + } + + if (ldns_dname_cat(hashed_sname, zone_name) != LDNS_STATUS_OK){ + goto done; + } + + if (verbosity >= 3) { + ldns_rdf_print(stdout, hashed_sname); + printf("\n"); + } + + for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsec3s); nsec_i++) { + nsec = ldns_rr_list_rr(nsec3s, nsec_i); + + /* check values of iterations etc! */ + + /* exact match? */ + if (ldns_dname_compare(ldns_rr_owner(nsec), hashed_sname) == 0) { + if (verbosity >= 4) { + printf(";; exact match found\n"); + } + exact_match_found = true; + } else if (ldns_nsec_covers_name(nsec, hashed_sname)) { + if (verbosity >= 4) { + printf(";; in range of an nsec\n"); + } + in_range_found = true; + } + + } + if (!exact_match_found && in_range_found) { + flag = true; + } else if (exact_match_found && flag) { + result = ldns_rdf_clone(sname); + } else if (exact_match_found && !flag) { + // error! + if (verbosity >= 4) { + printf(";; the closest encloser is the same name (ie. this is an exact match, ie there is no closest encloser)\n"); + } + ldns_rdf_deep_free(hashed_sname); + goto done; + } else { + flag = false; + } + + ldns_rdf_deep_free(hashed_sname); + tmp = sname; + sname = ldns_dname_left_chop(sname); + ldns_rdf_deep_free(tmp); + if (sname == NULL) { + goto done; + } + } + +done: + LDNS_FREE(salt); + ldns_rdf_deep_free(zone_name); + ldns_rdf_deep_free(sname); + + if (!result) { + if (verbosity >= 4) { + printf(";; no closest encloser found\n"); + } + } + + /* todo checks from end of 6.2. here or in caller? */ + return result; +} diff --git a/drill/drill.1 b/drill/drill.1 new file mode 100644 index 00000000000..24cfd6dabe9 --- /dev/null +++ b/drill/drill.1 @@ -0,0 +1,230 @@ +.\" @(#)drill.1 1.7.0 14-Jul-2004 OF; +.TH drill 1 "28 May 2006" +.SH NAME +drill \- get (debug) information out of DNS(SEC) +.SH SYNOPSIS +.B drill +[ +.IR OPTIONS +] +.IR name +[ +.IR @server +] +[ +.IR type +] +[ +.IR class +] + +.SH DESCRIPTION +\fBdrill\fR is a tool to designed to get all sorts of information out of the +DNS. It is specificly designed to be used with DNSSEC. +.PP +The name \fBdrill\fR is a pun on \fBdig\fR. With \fBdrill\fR you should be able +get even more information than with \fBdig\fR. +.PP +If no arguments are given class defaults to 'IN' and type to 'A'. The +server(s) specified in /etc/resolv.conf are used to query against. + +.PP +\fIname\fR +Ask for this name. + +.PP +\fI@server\fR +Send to query to this server. If not specified use the nameservers from +\fI/etc/resolv.conf\fR. + +.PP +\fItype\fR +Ask for this RR type. If type is not given on the command line it defaults +to 'A'. Except when doing to reverse lookup when it defaults to 'PTR'. + +.PP +\fIclass\fR +Use this class when querying. + +.SH SAMPLE USAGE +\fBdrill mx miek.nl\fR +Show the MX records of the domain miek.nl + +.TP +\fBdrill -S jelte.nlnetlabs.nl\fR +Chase any signatures in the jelte.nlnetlab.nl domain. This option is +only available when ldns has been compiled with openssl-support. + +.TP +\fBdrill -TD www.example.com\fR +Do a DNSSEC (-D) trace (-T) from the rootservers down to www.example.com. +This option only works when ldns has been compiled with openssl support. + +.TP +\fBdrill -s dnskey jelte.nlnetlabs.nl\fR +Show the DNSKEY record(s) for jelte.nlnetlabs.nl. For each found DNSKEY +record also print the DS record. + +.SH OPTIONS + +.TP +\fB\-D +Enable DNSSEC in the query. When querying for DNSSEC types (DNSKEY, RRSIG, +DS and NSEC) this is \fInot\fR automaticly enabled. + +.TP +\fB\-T +Trace \fIname\fR from the root down. When using this option the @server and +the type arguments are not used. + +.TP +\fB\-S +Chase the signature(s) of 'name' to a known key or as high up in +the tree as possible. + +.TP +\fB\-V \fIlevel\fR +Be more verbose. Set level to 5 to see the actual query that is sent. + +.TP +\fB\-Q +Quiet mode, this overrules -V. + +.TP +\fB\-f \fIfile\fR +Read the query from a file. The query must be dumped with -w. + +.TP +\fB\-i \fIfile\fR +read the answer from the file instead from the network. This aids +in debugging and can be used to check if a query on disk is valid. +If the file contains binary data it is assumed to be a query in +network order. + +.TP +\fB\-w \fIfile\fR +Write an answer packet to file. + +.TP +\fB\-q \fIfile\fR +Write the query packet to file. + +.TP +\fB\-v +Show drill's version. + +.TP +\fB\-h +Show a short help message. + +.SS QUERY OPTIONS + +.TP +\fB\-4 +Stay on ip4. Only send queries to ip4 enabled nameservers. + +.TP +\fB\-6 +Stay on ip6. Only send queries to ip6 enabled nameservers. + +.TP +\fB\-a +Use the resolver structure's fallback mechanism if the answer +is truncated (TC=1). If a truncated packet is received and this +option is set, drill will first send a new query with EDNS0 +buffer size 4096. + +If the EDNS0 buffer size was already set to 512+ bytes, or the +above retry also results in a truncated answer, the resolver +structure will fall back to TCP. + +.TP +\fB\-b \fIsize\fR +Use size as the buffer size in the EDNS0 pseudo RR. + +.TP +\fB\-c \fIfile\fR +Use file instead of /etc/resolv.conf for nameserver configuration. + +.TP +\fB\-d \fIdomain\fR +When tracing (-T), start from this domain instead of the root. + +.TP +\fB\-t +Use TCP/IP when querying a server + +.TP +\fB\-k \fIkeyfile\fR +Use this file to read a (trusted) key from. When this options is +given \fBdrill\fR tries to validate the current answer with this +key. No chasing is done. When \fBdrill\fR is doing a secure trace, this +key will be used as trust anchor. Can contain a DNSKEY or a DS record. + +.TP +\fB\-o \fImnemonic\fR +Use this option to set or unset specific header bits. A bit is +set by using the bit mnemonic in CAPITAL letters. A bit is unset when +the mnemonic is given in lowercase. The following mnemonics are +understood by \fBdrill\fR: + + QR, qr: set, unset QueRy (default: on) + AA, aa: set, unset Authoritative Answer (default: off) + TC, tc: set, unset TrunCated (default: off) + RD, rd: set, unset Recursion Desired (default: on) + CD, cd: set, unset Checking Disabled (default: off) + RA, ra: set, unset Recursion Available (default: off) + AD, ad: set, unset Authenticated Data (default: off) + +Thus: \fB-o CD\fR, will enable Checking Disabled, which instructs the +cache to not validate the answers it gives out. + +.TP +\fB\-p \fIport\fR +Use this port instead of the default of 53. + +.TP +\fB\-r \fIfile\fR +When tracing (-T), use file as a root servers hint file. + +.TP +\fB\-s +When encountering a DNSKEY print the equivalent DS also. + +.TP +\fB\-u +Use UDP when querying a server. This is the default. + +.TP +\fB\-w \fIfile\fR +write the answer to a file. The file will contain a hexadecimal dump +of the query. This can be used in conjunction with -f. + +.TP +\fB\-x +Do a reverse loopup. The type argument is not used, it is preset to PTR. + +.TP +\fB\-y \fI\fR +specify named base64 tsig key, and optional an algorithm (defaults to hmac-md5.sig-alg.reg.int) + +.TP +\fB\-z \fR +don't randomize the nameserver list before sending queries. + + +.SH AUTHOR +Jelte Jansen and Miek Gieben. Both of NLnet Labs. + +.SH REPORTING BUGS +Report bugs to . + +.SH BUGS + +.SH COPYRIGHT +Copyright (c) 2004-2008 NLnet Labs. +Licensed under the revised BSD license. There is NO warranty; not even for MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. + +.SH SEE ALSO +\fBdig\fR(1), \fIRFC403{3,4,5}\fR. diff --git a/drill/drill.c b/drill/drill.c new file mode 100644 index 00000000000..2f779634d8e --- /dev/null +++ b/drill/drill.c @@ -0,0 +1,934 @@ +/* + * drill.c + * the main file of drill + * (c) 2005-2008 NLnet Labs + * + * See the file LICENSE for the license + * + */ + +#include "drill.h" +#include + +#ifdef HAVE_SSL +#include +#endif + +#define IP6_ARPA_MAX_LEN 65 + +/* query debug, 2 hex dumps */ +int verbosity; + +static void +usage(FILE *stream, const char *progname) +{ + fprintf(stream, " Usage: %s name [@server] [type] [class]\n", progname); + fprintf(stream, "\t can be a domain name or an IP address (-x lookups)\n"); + fprintf(stream, "\t defaults to A\n"); + fprintf(stream, "\t defaults to IN\n"); + fprintf(stream, "\n\targuments may be placed in random order\n"); + fprintf(stream, "\n Options:\n"); + fprintf(stream, "\t-D\t\tenable DNSSEC (DO bit)\n"); +#ifdef HAVE_SSL + fprintf(stream, "\t-T\t\ttrace from the root down to \n"); + fprintf(stream, "\t-S\t\tchase signature(s) from to a know key [*]\n"); +#endif /*HAVE_SSL*/ + fprintf(stream, "\t-V \tverbosity (0-5)\n"); + fprintf(stream, "\t-Q\t\tquiet mode (overrules -V)\n"); + fprintf(stream, "\n"); + fprintf(stream, "\t-f file\t\tread packet from file and send it\n"); + fprintf(stream, "\t-i file\t\tread packet from file and print it\n"); + fprintf(stream, "\t-w file\t\twrite answer packet to file\n"); + fprintf(stream, "\t-q file\t\twrite query packet to file\n"); + fprintf(stream, "\t-h\t\tshow this help\n"); + fprintf(stream, "\t-v\t\tshow version\n"); + fprintf(stream, "\n Query options:\n"); + fprintf(stream, "\t-4\t\tstay on ip4\n"); + fprintf(stream, "\t-6\t\tstay on ip6\n"); + fprintf(stream, "\t-a\t\tfallback to EDNS0 and TCP if the answer is truncated\n"); + fprintf(stream, "\t-b \tuse as the buffer size (defaults to 512 b)\n"); + fprintf(stream, "\t-c \t\tuse file for rescursive nameserver configuration (/etc/resolv.conf)\n"); + fprintf(stream, "\t-k \tspecify a file that contains a trusted DNSSEC key (DNSKEY|DS) [**]\n"); + fprintf(stream, "\t\t\tused to verify any signatures in the current answer\n"); + fprintf(stream, "\t-o \tset flags to: [QR|qr][AA|aa][TC|tc][RD|rd][CD|cd][RA|ra][AD|ad]\n"); + fprintf(stream, "\t\t\tlowercase: unset bit, uppercase: set bit\n"); + fprintf(stream, "\t-p \tuse as remote port number\n"); + fprintf(stream, "\t-s\t\tshow the DS RR for each key in a packet\n"); + fprintf(stream, "\t-u\t\tsend the query with udp (the default)\n"); + fprintf(stream, "\t-x\t\tdo a reverse lookup\n"); + fprintf(stream, "\twhen doing a secure trace:\n"); + fprintf(stream, "\t-r \t\tuse file as root servers hint file\n"); + fprintf(stream, "\t-t\t\tsend the query with tcp (connected)\n"); + fprintf(stream, "\t-d \t\tuse domain as the start point for the trace\n"); + fprintf(stream, "\t-y \tspecify named base64 tsig key, and optional an\n\t\t\talgorithm (defaults to hmac-md5.sig-alg.reg.int)\n"); + fprintf(stream, "\t-z\t\tdon't randomize the nameservers before use\n"); + fprintf(stream, "\n [*] = enables/implies DNSSEC\n"); + fprintf(stream, " [**] = can be given more than once\n"); + fprintf(stream, "\n ldns-team@nlnetlabs.nl | http://www.nlnetlabs.nl/ldns/\n"); +} + +/** + * Prints the drill version to stderr + */ +static void +version(FILE *stream, const char *progname) +{ + fprintf(stream, "%s version %s (ldns version %s)\n", progname, DRILL_VERSION, ldns_version()); + fprintf(stream, "Written by NLnet Labs.\n"); + fprintf(stream, "\nCopyright (c) 2004-2008 NLnet Labs.\n"); + fprintf(stream, "Licensed under the revised BSD license.\n"); + fprintf(stream, "There is NO warranty; not even for MERCHANTABILITY or FITNESS\n"); + fprintf(stream, "FOR A PARTICULAR PURPOSE.\n"); +} + + +/** + * Main function of drill + * parse the arguments and prepare a query + */ +int +main(int argc, char *argv[]) +{ + ldns_resolver *res = NULL; + ldns_resolver *cmdline_res = NULL; /* only used to resolv @name names */ + ldns_rr_list *cmdline_rr_list = NULL; + ldns_rdf *cmdline_dname = NULL; + ldns_rdf *qname, *qname_tmp; + ldns_pkt *pkt; + ldns_pkt *qpkt; + char *serv; + const char *name; + char *name2; + char *progname; + char *query_file = NULL; + char *answer_file = NULL; + ldns_buffer *query_buffer = NULL; + ldns_rdf *serv_rdf; + ldns_rr_type type; + ldns_rr_class clas; +#if 0 + ldns_pkt_opcode opcode = LDNS_PACKET_QUERY; +#endif + int i, c; + int int_type; + int int_clas; + int PURPOSE; + char *tsig_name = NULL; + char *tsig_data = NULL; + char *tsig_algorithm = NULL; + size_t tsig_separator; + size_t tsig_separator2; + ldns_rr *axfr_rr; + ldns_status status; + char *type_str; + + /* list of keys used in dnssec operations */ + ldns_rr_list *key_list = ldns_rr_list_new(); + /* what key verify the current answer */ + ldns_rr_list *key_verified; + + /* resolver options */ + uint16_t qflags; + uint16_t qbuf; + uint16_t qport; + uint8_t qfamily; + bool qdnssec; + bool qfallback; + bool qds; + bool qusevc; + bool qrandom; + + char *resolv_conf_file = NULL; + + ldns_rdf *trace_start_name = NULL; + + int result = 0; + +#ifdef USE_WINSOCK + int r; + WSADATA wsa_data; +#endif + + int_type = -1; serv = NULL; type = 0; + int_clas = -1; name = NULL; clas = 0; + qname = NULL; + progname = strdup(argv[0]); + +#ifdef USE_WINSOCK + r = WSAStartup(MAKEWORD(2,2), &wsa_data); + if(r != 0) { + printf("Failed WSAStartup: %d\n", r); + result = EXIT_FAILURE; + goto exit; + } +#endif /* USE_WINSOCK */ + + + PURPOSE = DRILL_QUERY; + qflags = LDNS_RD; + qport = LDNS_PORT; + verbosity = 2; + qdnssec = false; + qfamily = LDNS_RESOLV_INETANY; + qfallback = false; + qds = false; + qbuf = 0; + qusevc = false; + qrandom = true; + key_verified = NULL; + + ldns_init_random(NULL, 0); + + if (argc == 0) { + usage(stdout, progname); + result = EXIT_FAILURE; + goto exit; + } + + /* string from orig drill: "i:w:I46Sk:TNp:b:DsvhVcuaq:f:xr" */ + /* global first, query opt next, option with parm's last + * and sorted */ /* "46DITSVQf:i:w:q:achuvxzy:so:p:b:k:" */ + + while ((c = getopt(argc, argv, "46ab:c:d:Df:hi:Ik:o:p:q:Qr:sStTuvV:w:xy:z")) != -1) { + switch(c) { + /* global options */ + case '4': + qfamily = LDNS_RESOLV_INET; + break; + case '6': + qfamily = LDNS_RESOLV_INET6; + break; + case 'D': + qdnssec = true; + break; + case 'I': + /* reserved for backward compatibility */ + break; + case 'T': + if (PURPOSE == DRILL_CHASE) { + fprintf(stderr, "-T and -S cannot be used at the same time.\n"); + exit(EXIT_FAILURE); + } + PURPOSE = DRILL_TRACE; + break; +#ifdef HAVE_SSL + case 'S': + if (PURPOSE == DRILL_TRACE) { + fprintf(stderr, "-T and -S cannot be used at the same time.\n"); + exit(EXIT_FAILURE); + } + PURPOSE = DRILL_CHASE; + break; +#endif /* HAVE_SSL */ + case 'V': + if (strtok(optarg, "0123456789") != NULL) { + fprintf(stderr, "-V expects an number as an argument.\n"); + exit(EXIT_FAILURE); + } + verbosity = atoi(optarg); + break; + case 'Q': + verbosity = -1; + break; + case 'f': + query_file = optarg; + break; + case 'i': + answer_file = optarg; + PURPOSE = DRILL_AFROMFILE; + break; + case 'w': + answer_file = optarg; + break; + case 'q': + query_file = optarg; + PURPOSE = DRILL_QTOFILE; + break; + case 'r': + if (global_dns_root) { + fprintf(stderr, "There was already a series of root servers set\n"); + exit(EXIT_FAILURE); + } + global_dns_root = read_root_hints(optarg); + if (!global_dns_root) { + fprintf(stderr, "Unable to read root hints file %s, aborting\n", optarg); + exit(EXIT_FAILURE); + } + break; + /* query options */ + case 'a': + qfallback = true; + break; + case 'b': + qbuf = (uint16_t)atoi(optarg); + if (qbuf == 0) { + error("%s", " could not be converted"); + } + break; + case 'c': + resolv_conf_file = optarg; + break; + case 't': + qusevc = true; + break; + case 'k': + status = read_key_file(optarg, key_list); + if (status != LDNS_STATUS_OK) { + error("Could not parse the key file %s: %s", optarg, ldns_get_errorstr_by_id(status)); + } + qdnssec = true; /* enable that too */ + break; + case 'o': + /* only looks at the first hit: capital=ON, lowercase=OFF*/ + if (strstr(optarg, "QR")) { + DRILL_ON(qflags, LDNS_QR); + } + if (strstr(optarg, "qr")) { + DRILL_OFF(qflags, LDNS_QR); + } + if (strstr(optarg, "AA")) { + DRILL_ON(qflags, LDNS_AA); + } + if (strstr(optarg, "aa")) { + DRILL_OFF(qflags, LDNS_AA); + } + if (strstr(optarg, "TC")) { + DRILL_ON(qflags, LDNS_TC); + } + if (strstr(optarg, "tc")) { + DRILL_OFF(qflags, LDNS_TC); + } + if (strstr(optarg, "RD")) { + DRILL_ON(qflags, LDNS_RD); + } + if (strstr(optarg, "rd")) { + DRILL_OFF(qflags, LDNS_RD); + } + if (strstr(optarg, "CD")) { + DRILL_ON(qflags, LDNS_CD); + } + if (strstr(optarg, "cd")) { + DRILL_OFF(qflags, LDNS_CD); + } + if (strstr(optarg, "RA")) { + DRILL_ON(qflags, LDNS_RA); + } + if (strstr(optarg, "ra")) { + DRILL_OFF(qflags, LDNS_RA); + } + if (strstr(optarg, "AD")) { + DRILL_ON(qflags, LDNS_AD); + } + if (strstr(optarg, "ad")) { + DRILL_OFF(qflags, LDNS_AD); + } + break; + case 'p': + qport = (uint16_t)atoi(optarg); + if (qport == 0) { + error("%s", " could not be converted"); + } + break; + case 's': + qds = true; + break; + case 'u': + qusevc = false; + break; + case 'v': + version(stdout, progname); + result = EXIT_SUCCESS; + goto exit; + case 'x': + PURPOSE = DRILL_REVERSE; + break; + case 'y': +#ifdef HAVE_SSL + if (strchr(optarg, ':')) { + tsig_separator = (size_t) (strchr(optarg, ':') - optarg); + if (strchr(optarg + tsig_separator + 1, ':')) { + tsig_separator2 = (size_t) (strchr(optarg + tsig_separator + 1, ':') - optarg); + tsig_algorithm = xmalloc(strlen(optarg) - tsig_separator2); + strncpy(tsig_algorithm, optarg + tsig_separator2 + 1, strlen(optarg) - tsig_separator2); + tsig_algorithm[strlen(optarg) - tsig_separator2 - 1] = '\0'; + } else { + tsig_separator2 = strlen(optarg); + tsig_algorithm = xmalloc(26); + strncpy(tsig_algorithm, "hmac-md5.sig-alg.reg.int.", 25); + tsig_algorithm[25] = '\0'; + } + tsig_name = xmalloc(tsig_separator + 1); + tsig_data = xmalloc(tsig_separator2 - tsig_separator); + strncpy(tsig_name, optarg, tsig_separator); + strncpy(tsig_data, optarg + tsig_separator + 1, tsig_separator2 - tsig_separator - 1); + /* strncpy does not append \0 if source is longer than n */ + tsig_name[tsig_separator] = '\0'; + tsig_data[ tsig_separator2 - tsig_separator - 1] = '\0'; + } +#else + fprintf(stderr, "TSIG requested, but SSL is not supported\n"); + result = EXIT_FAILURE; + goto exit; +#endif /* HAVE_SSL */ + break; + case 'z': + qrandom = false; + break; + case 'd': + trace_start_name = ldns_dname_new_frm_str(optarg); + if (!trace_start_name) { + fprintf(stderr, "Unable to parse argument for -%c\n", c); + result = EXIT_FAILURE; + goto exit; + } + break; + case 'h': + version(stdout, progname); + usage(stdout, progname); + result = EXIT_SUCCESS; + goto exit; + break; + default: + fprintf(stderr, "Unknown argument: -%c, use -h to see usage\n", c); + result = EXIT_FAILURE; + goto exit; + } + } + argc -= optind; + argv += optind; + + /* do a secure trace when requested */ + if (PURPOSE == DRILL_TRACE && qdnssec) { +#ifdef HAVE_SSL + if (ldns_rr_list_rr_count(key_list) == 0) { + warning("%s", "No trusted keys were given. Will not be able to verify authenticity!"); + } + PURPOSE = DRILL_SECTRACE; +#else + fprintf(stderr, "ldns has not been compiled with OpenSSL support. Secure trace not available\n"); + exit(1); +#endif /* HAVE_SSL */ + } + + /* parse the arguments, with multiple arguments, the last argument + * found is used */ + for(i = 0; i < argc; i++) { + + /* if ^@ then it's a server */ + if (argv[i][0] == '@') { + if (strlen(argv[i]) == 1) { + warning("%s", "No nameserver given"); + exit(EXIT_FAILURE); + } + serv = argv[i] + 1; + continue; + } + /* if has a dot, it's a name */ + if (strchr(argv[i], '.')) { + name = argv[i]; + continue; + } + /* if it matches a type, it's a type */ + if (int_type == -1) { + type = ldns_get_rr_type_by_name(argv[i]); + if (type != 0) { + int_type = 0; + continue; + } + } + /* if it matches a class, it's a class */ + if (int_clas == -1) { + clas = ldns_get_rr_class_by_name(argv[i]); + if (clas != 0) { + int_clas = 0; + continue; + } + } + /* it all fails assume it's a name */ + name = argv[i]; + } + /* act like dig and use for . NS */ + if (!name) { + name = "."; + int_type = 0; + type = LDNS_RR_TYPE_NS; + } + + /* defaults if not given */ + if (int_clas == -1) { + clas = LDNS_RR_CLASS_IN; + } + if (int_type == -1) { + if (PURPOSE != DRILL_REVERSE) { + type = LDNS_RR_TYPE_A; + } else { + type = LDNS_RR_TYPE_PTR; + } + } + + /* set the nameserver to use */ + if (!serv) { + /* no server given make a resolver from /etc/resolv.conf */ + status = ldns_resolver_new_frm_file(&res, resolv_conf_file); + if (status != LDNS_STATUS_OK) { + warning("Could not create a resolver structure: %s (%s)\n" + "Try drill @localhost if you have a resolver running on your machine.", + ldns_get_errorstr_by_id(status), resolv_conf_file); + result = EXIT_FAILURE; + goto exit; + } + } else { + res = ldns_resolver_new(); + if (!res || strlen(serv) <= 0) { + warning("Could not create a resolver structure"); + result = EXIT_FAILURE; + goto exit; + } + /* add the nameserver */ + serv_rdf = ldns_rdf_new_addr_frm_str(serv); + if (!serv_rdf) { + /* try to resolv the name if possible */ + status = ldns_resolver_new_frm_file(&cmdline_res, resolv_conf_file); + + if (status != LDNS_STATUS_OK) { + error("%s", "@server ip could not be converted"); + } + ldns_resolver_set_dnssec(cmdline_res, qdnssec); + ldns_resolver_set_ip6(cmdline_res, qfamily); + ldns_resolver_set_fallback(cmdline_res, qfallback); + ldns_resolver_set_usevc(cmdline_res, qusevc); + + cmdline_dname = ldns_dname_new_frm_str(serv); + + cmdline_rr_list = ldns_get_rr_list_addr_by_name( + cmdline_res, + cmdline_dname, + LDNS_RR_CLASS_IN, + qflags); + ldns_rdf_deep_free(cmdline_dname); + if (!cmdline_rr_list) { + /* This error msg is not always accurate */ + error("%s `%s\'", "could not find any address for the name:", serv); + } else { + if (ldns_resolver_push_nameserver_rr_list( + res, + cmdline_rr_list + ) != LDNS_STATUS_OK) { + error("%s", "pushing nameserver"); + } + } + } else { + if (ldns_resolver_push_nameserver(res, serv_rdf) != LDNS_STATUS_OK) { + error("%s", "pushing nameserver"); + } else { + ldns_rdf_deep_free(serv_rdf); + } + } + } + /* set the resolver options */ + ldns_resolver_set_port(res, qport); + if (verbosity >= 5) { + ldns_resolver_set_debug(res, true); + } else { + ldns_resolver_set_debug(res, false); + } + ldns_resolver_set_dnssec(res, qdnssec); +/* ldns_resolver_set_dnssec_cd(res, qdnssec);*/ + ldns_resolver_set_ip6(res, qfamily); + ldns_resolver_set_fallback(res, qfallback); + ldns_resolver_set_usevc(res, qusevc); + ldns_resolver_set_random(res, qrandom); + if (qbuf != 0) { + ldns_resolver_set_edns_udp_size(res, qbuf); + } + + if (!name && + PURPOSE != DRILL_AFROMFILE && + !query_file + ) { + usage(stdout, progname); + result = EXIT_FAILURE; + goto exit; + } + + if (tsig_name && tsig_data) { + ldns_resolver_set_tsig_keyname(res, tsig_name); + ldns_resolver_set_tsig_keydata(res, tsig_data); + ldns_resolver_set_tsig_algorithm(res, tsig_algorithm); + } + + /* main switching part of drill */ + switch(PURPOSE) { + case DRILL_TRACE: + /* do a trace from the root down */ + if (!global_dns_root) { + init_root(); + } + qname = ldns_dname_new_frm_str(name); + if (!qname) { + error("%s", "parsing query name"); + } + /* don't care about return packet */ + (void)do_trace(res, qname, type, clas); + clear_root(); + break; + case DRILL_SECTRACE: + /* do a secure trace from the root down */ + if (!global_dns_root) { + init_root(); + } + qname = ldns_dname_new_frm_str(name); + if (!qname) { + error("%s", "making qname"); + } + /* don't care about return packet */ +#ifdef HAVE_SSL + result = do_secure_trace(res, qname, type, clas, key_list, trace_start_name); +#endif /* HAVE_SSL */ + clear_root(); + break; + case DRILL_CHASE: + qname = ldns_dname_new_frm_str(name); + if (!qname) { + error("%s", "making qname"); + } + + ldns_resolver_set_dnssec(res, true); + ldns_resolver_set_dnssec_cd(res, true); + /* set dnssec implies udp_size of 4096 */ + ldns_resolver_set_edns_udp_size(res, 4096); + pkt = ldns_resolver_query(res, qname, type, clas, qflags); + + if (!pkt) { + error("%s", "error pkt sending"); + result = EXIT_FAILURE; + } else { + if (verbosity >= 3) { + ldns_pkt_print(stdout, pkt); + } + + if (!ldns_pkt_answer(pkt)) { + mesg("No answer in packet"); + } else { +#ifdef HAVE_SSL + ldns_resolver_set_dnssec_anchors(res, ldns_rr_list_clone(key_list)); + result = do_chase(res, qname, type, + clas, key_list, + pkt, qflags, NULL, + verbosity); + if (result == LDNS_STATUS_OK) { + if (verbosity != -1) { + mesg("Chase successful"); + } + result = 0; + } else { + if (verbosity != -1) { + mesg("Chase failed."); + } + } +#endif /* HAVE_SSL */ + } + ldns_pkt_free(pkt); + } + break; + case DRILL_AFROMFILE: + pkt = read_hex_pkt(answer_file); + if (pkt) { + if (verbosity != -1) { + ldns_pkt_print(stdout, pkt); + } + ldns_pkt_free(pkt); + } + + break; + case DRILL_QTOFILE: + qname = ldns_dname_new_frm_str(name); + if (!qname) { + error("%s", "making qname"); + } + + status = ldns_resolver_prepare_query_pkt(&qpkt, res, qname, type, clas, qflags); + if(status != LDNS_STATUS_OK) { + error("%s", "making query: %s", + ldns_get_errorstr_by_id(status)); + } + dump_hex(qpkt, query_file); + ldns_pkt_free(qpkt); + break; + case DRILL_NSEC: + break; + case DRILL_REVERSE: + /* ipv4 or ipv6 addr? */ + if (strchr(name, ':')) { + if (strchr(name, '.')) { + error("Syntax error: both '.' and ':' seen in address\n"); + } + name2 = malloc(IP6_ARPA_MAX_LEN + 20); + c = 0; + for (i=0; i<(int)strlen(name); i++) { + if (i >= IP6_ARPA_MAX_LEN) { + error("%s", "reverse argument to long"); + } + if (name[i] == ':') { + if (i < (int) strlen(name) && name[i + 1] == ':') { + error("%s", ":: not supported (yet)"); + } else { + if (i + 2 == (int) strlen(name) || name[i + 2] == ':') { + name2[c++] = '0'; + name2[c++] = '.'; + name2[c++] = '0'; + name2[c++] = '.'; + name2[c++] = '0'; + name2[c++] = '.'; + } else if (i + 3 == (int) strlen(name) || name[i + 3] == ':') { + name2[c++] = '0'; + name2[c++] = '.'; + name2[c++] = '0'; + name2[c++] = '.'; + } else if (i + 4 == (int) strlen(name) || name[i + 4] == ':') { + name2[c++] = '0'; + name2[c++] = '.'; + } + } + } else { + name2[c++] = name[i]; + name2[c++] = '.'; + } + } + name2[c++] = '\0'; + + qname = ldns_dname_new_frm_str(name2); + qname_tmp = ldns_dname_reverse(qname); + ldns_rdf_deep_free(qname); + qname = qname_tmp; + qname_tmp = ldns_dname_new_frm_str("ip6.arpa."); + status = ldns_dname_cat(qname, qname_tmp); + if (status != LDNS_STATUS_OK) { + error("%s", "could not create reverse address for ip6: %s\n", ldns_get_errorstr_by_id(status)); + } + ldns_rdf_deep_free(qname_tmp); + + free(name2); + } else { + qname = ldns_dname_new_frm_str(name); + qname_tmp = ldns_dname_reverse(qname); + ldns_rdf_deep_free(qname); + qname = qname_tmp; + qname_tmp = ldns_dname_new_frm_str("in-addr.arpa."); + status = ldns_dname_cat(qname, qname_tmp); + if (status != LDNS_STATUS_OK) { + error("%s", "could not create reverse address for ip4: %s\n", ldns_get_errorstr_by_id(status)); + } + ldns_rdf_deep_free(qname_tmp); + } + if (!qname) { + error("%s", "-x implies an ip address"); + } + + /* create a packet and set the RD flag on it */ + pkt = ldns_resolver_query(res, qname, type, clas, qflags); + if (!pkt) { + error("%s", "pkt sending"); + result = EXIT_FAILURE; + } else { + if (verbosity != -1) { + ldns_pkt_print(stdout, pkt); + } + ldns_pkt_free(pkt); + } + break; + case DRILL_QUERY: + default: + if (query_file) { + /* this old way, the query packet needed + to be parseable, but we want to be able + to send mangled packets, so we need + to do it directly */ + #if 0 + qpkt = read_hex_pkt(query_file); + if (qpkt) { + status = ldns_resolver_send_pkt(&pkt, res, qpkt); + if (status != LDNS_STATUS_OK) { + printf("Error: %s\n", ldns_get_errorstr_by_id(status)); + exit(1); + } + } else { + /* qpkt was bogus, reset pkt */ + pkt = NULL; + } + #endif + query_buffer = read_hex_buffer(query_file); + if (query_buffer) { + status = ldns_send_buffer(&pkt, res, query_buffer, NULL); + ldns_buffer_free(query_buffer); + if (status != LDNS_STATUS_OK) { + printf("Error: %s\n", ldns_get_errorstr_by_id(status)); + exit(1); + } + } else { + printf("NO BUFFER\n"); + pkt = NULL; + } + } else { + qname = ldns_dname_new_frm_str(name); + if (!qname) { + error("%s", "error in making qname"); + } + + if (type == LDNS_RR_TYPE_AXFR) { + status = ldns_axfr_start(res, qname, clas); + if(status != LDNS_STATUS_OK) { + error("Error starting axfr: %s", + ldns_get_errorstr_by_id(status)); + } + axfr_rr = ldns_axfr_next(res); + if(!axfr_rr) { + fprintf(stderr, "AXFR failed.\n"); + ldns_pkt_print(stdout, + ldns_axfr_last_pkt(res)); + goto exit; + } + while (axfr_rr) { + if (verbosity != -1) { + ldns_rr_print(stdout, axfr_rr); + } + ldns_rr_free(axfr_rr); + axfr_rr = ldns_axfr_next(res); + } + + goto exit; + } else { + /* create a packet and set the RD flag on it */ + pkt = ldns_resolver_query(res, qname, type, clas, qflags); + } + } + + if (!pkt) { + mesg("No packet received"); + result = EXIT_FAILURE; + } else { + if (verbosity != -1) { + ldns_pkt_print(stdout, pkt); + if (ldns_pkt_tc(pkt)) { + fprintf(stdout, + "\n;; WARNING: The answer packet was truncated; you might want to\n"); + fprintf(stdout, + ";; query again with TCP (-t argument), or EDNS0 (-b for buffer size)\n"); + } + } + if (qds) { + if (verbosity != -1) { + print_ds_of_keys(pkt); + printf("\n"); + } + } + + if (ldns_rr_list_rr_count(key_list) > 0) { + /* -k's were given on the cmd line */ + ldns_rr_list *rrset_verified; + uint16_t key_count; + + rrset_verified = ldns_pkt_rr_list_by_name_and_type( + pkt, qname, type, + LDNS_SECTION_ANY_NOQUESTION); + + if (type == LDNS_RR_TYPE_ANY) { + /* don't verify this */ + break; + } + + if (verbosity != -1) { + printf("; "); + ldns_rr_list_print(stdout, rrset_verified); + } + + /* verify */ +#ifdef HAVE_SSL + key_verified = ldns_rr_list_new(); + result = ldns_pkt_verify(pkt, type, qname, key_list, NULL, key_verified); + + if (result == LDNS_STATUS_ERR) { + /* is the existence denied then? */ + result = ldns_verify_denial(pkt, qname, type, NULL, NULL); + if (result == LDNS_STATUS_OK) { + if (verbosity != -1) { + printf("Existence denied for "); + ldns_rdf_print(stdout, qname); + type_str = ldns_rr_type2str(type); + printf("\t%s\n", type_str); + LDNS_FREE(type_str); + } + } else { + if (verbosity != -1) { + printf("Bad data; RR for name and " + "type not found or failed to " + "verify, and denial of " + "existence failed.\n"); + } + } + } else if (result == LDNS_STATUS_OK) { + for(key_count = 0; key_count < ldns_rr_list_rr_count(key_verified); + key_count++) { + if (verbosity != -1) { + printf("; VALIDATED by id = %u, owner = ", + (unsigned int)ldns_calc_keytag( + ldns_rr_list_rr(key_verified, key_count))); + ldns_rdf_print(stdout, ldns_rr_owner( + ldns_rr_list_rr(key_list, key_count))); + printf("\n"); + } + } + } else { + for(key_count = 0; key_count < ldns_rr_list_rr_count(key_list); + key_count++) { + if (verbosity != -1) { + printf("; %s for id = %u, owner = ", + ldns_get_errorstr_by_id(result), + (unsigned int)ldns_calc_keytag( + ldns_rr_list_rr(key_list, key_count))); + ldns_rdf_print(stdout, ldns_rr_owner( + + ldns_rr_list_rr(key_list, + key_count))); + printf("\n"); + } + } + } + ldns_rr_list_free(key_verified); +#else + (void) key_count; +#endif /* HAVE_SSL */ + } + if (answer_file) { + dump_hex(pkt, answer_file); + } + ldns_pkt_free(pkt); + } + + break; + } + + exit: + ldns_rdf_deep_free(qname); + ldns_resolver_deep_free(res); + ldns_resolver_deep_free(cmdline_res); + ldns_rr_list_deep_free(key_list); + ldns_rr_list_deep_free(cmdline_rr_list); + ldns_rdf_deep_free(trace_start_name); + xfree(progname); + xfree(tsig_name); + xfree(tsig_data); + xfree(tsig_algorithm); + +#ifdef HAVE_SSL + ERR_remove_state(0); + CRYPTO_cleanup_all_ex_data(); + ERR_free_strings(); + EVP_cleanup(); +#endif +#ifdef USE_WINSOCK + WSACleanup(); +#endif + + return result; +} diff --git a/drill/drill.h b/drill/drill.h new file mode 100644 index 00000000000..69b0396b217 --- /dev/null +++ b/drill/drill.h @@ -0,0 +1,104 @@ +/* + * drill.h + * the main header file of drill + * (c) 2005, 2006 NLnet Labs + * + * See the file LICENSE for the license + * + */ +#ifndef _DRILL_H_ +#define _DRILL_H_ +#include "config.h" + +#include "drill_util.h" + +#define DRILL_VERSION PACKAGE_VERSION + +/* what kind of stuff do we allow */ +#define DRILL_QUERY 0 +#define DRILL_TRACE 1 +#define DRILL_CHASE 2 +#define DRILL_AFROMFILE 3 +#define DRILL_QTOFILE 4 +#define DRILL_NSEC 5 +#define DRILL_REVERSE 6 +#define DRILL_SECTRACE 7 + +#define DRILL_ON(VAR, BIT) \ +(VAR) = (VAR) | (BIT) +#define DRILL_OFF(VAR, BIT) \ +(VAR) = (VAR) & ~(BIT) + +extern ldns_rr_list *global_dns_root; +extern bool qds; +extern int verbosity; + +ldns_pkt *do_trace(ldns_resolver *res, + ldns_rdf *name, + ldns_rr_type type, + ldns_rr_class c); +ldns_status do_chase(ldns_resolver *res, + ldns_rdf *name, + ldns_rr_type type, + ldns_rr_class c, + ldns_rr_list *trusted_keys, + ldns_pkt *pkt_o, + uint16_t qflags, + ldns_rr_list *prev_key_list, + int verbosity); +int do_secure_trace(ldns_resolver *res, + ldns_rdf *name, + ldns_rr_type type, + ldns_rr_class c, + ldns_rr_list *trusted_keys, + ldns_rdf *start_name); + +ldns_rr_list * get_rr(ldns_resolver *res, + ldns_rdf *zname, + ldns_rr_type t, + ldns_rr_class c); + +void drill_pkt_print(FILE *fd, ldns_resolver *r, ldns_pkt *p); +void drill_pkt_print_footer(FILE *fd, ldns_resolver *r, ldns_pkt *p); + +ldns_pkt_type get_dnssec_rr(ldns_pkt *p, + ldns_rdf *name, + ldns_rr_type t, + ldns_rr_list **rrlist, + ldns_rr_list **sig); + +ldns_rr *ldns_nsec3_exact_match(ldns_rdf *qname, + ldns_rr_type qtype, + ldns_rr_list *nsec3s); + +ldns_rdf *ldns_nsec3_closest_encloser(ldns_rdf *qname, + ldns_rr_type qtype, + ldns_rr_list *nsec3s); + +/* verifies denial of existence of *name in *pkt (must contain NSEC or NSEC3 records + * if *nsec_rrs and *nsec_rr_sigs are given, pointers to the relevant nsecs and their signatures are + * placed there + */ +ldns_status ldns_verify_denial(ldns_pkt *pkt, + ldns_rdf *name, + ldns_rr_type type, + ldns_rr_list **nsec_rrs, + ldns_rr_list **nsec_rr_sigs); + +ldns_status read_key_file(const char *filename, ldns_rr_list *key_list); +ldns_pkt *read_hex_pkt(char *filename); +ldns_buffer *read_hex_buffer(char *filename); +void init_root(void); +ldns_rr_list *read_root_hints(const char *filename); +void clear_root(void); +void dump_hex(const ldns_pkt *pkt, const char *file); +void warning(const char *fmt, ...); +void error(const char *fmt, ...); +void mesg(const char *fmt, ...); + +/* screen.c */ +void resolver_print_nameservers(ldns_resolver *r); +void print_dnskey(ldns_rr_list *key_list); +void print_ds(ldns_rr_list *ds_list); + +#endif /* _DRILL_H_ */ diff --git a/drill/drill_util.c b/drill/drill_util.c new file mode 100644 index 00000000000..98d88e7942d --- /dev/null +++ b/drill/drill_util.c @@ -0,0 +1,305 @@ +/* + * util.c + * some handy function needed in drill and not implemented + * in ldns + * (c) 2005 NLnet Labs + * + * See the file LICENSE for the license + * + */ + +#include "drill.h" +#include + +#include + +static size_t +read_line(FILE *input, char *line, size_t len) +{ + size_t i; + + char c; + for (i = 0; i < len-1; i++) { + c = getc(input); + if (c == EOF) { + return -1; + } else if (c != '\n') { + line[i] = c; + } else { + break; + } + } + line[i] = '\0'; + return i; +} + +/* key_list must be initialized with ldns_rr_list_new() */ +ldns_status +read_key_file(const char *filename, ldns_rr_list *key_list) +{ + int line_len = 0; + int line_nr = 0; + int key_count = 0; + char line[LDNS_MAX_PACKETLEN]; + ldns_status status; + FILE *input_file; + ldns_rr *rr; + + input_file = fopen(filename, "r"); + if (!input_file) { + fprintf(stderr, "Error opening %s: %s\n", + filename, strerror(errno)); + return LDNS_STATUS_ERR; + } + while (line_len >= 0) { + line_len = (int) read_line(input_file, line, sizeof(line)); + line_nr++; + if (line_len > 0 && line[0] != ';') { + status = ldns_rr_new_frm_str(&rr, line, 0, NULL, NULL); + if (status != LDNS_STATUS_OK) { + fprintf(stderr, + "Error parsing DNSKEY RR in line %d: %s\n", + line_nr, + ldns_get_errorstr_by_id(status)); + } else if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_DNSKEY || + ldns_rr_get_type(rr) == LDNS_RR_TYPE_DS) { + ldns_rr_list_push_rr(key_list, rr); + key_count++; + } else { + ldns_rr_free(rr); + } + } + } + printf(";; Number of trusted keys: %d\n", key_count); + if (key_count > 0) { + return LDNS_STATUS_OK; + } else { + /*fprintf(stderr, "No keys read\n");*/ + return LDNS_STATUS_ERR; + } +} + +ldns_rdf * +ldns_rdf_new_addr_frm_str(char *str) +{ + ldns_rdf *a; + + a = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, str); + if (!a) { + /* maybe ip6 */ + a = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, str); + if (!a) { + return NULL; + } + } + return a; +} + +static inline void +local_print_ds(FILE* out, const char* pre, ldns_rr* ds) +{ + if (out && ds) { + fprintf(out, "%s", pre); + ldns_rr_print(out, ds); + ldns_rr_free(ds); + } +} + +/* + * For all keys in a packet print the DS + */ +void +print_ds_of_keys(ldns_pkt *p) +{ + ldns_rr_list *keys; + uint16_t i; + ldns_rr *ds; + + /* TODO fix the section stuff, here or in ldns */ + keys = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_DNSKEY, + LDNS_SECTION_ANSWER); + + /* this also returns the question section rr, which does not + * have any data.... and this inturn crashes everything */ + + if (keys) { + for (i = 0; i < ldns_rr_list_rr_count(keys); i++) { + fprintf(stdout, ";\n; equivalent DS records for key %u:\n", + (unsigned int)ldns_calc_keytag(ldns_rr_list_rr(keys, i))); + + ds = ldns_key_rr2ds(ldns_rr_list_rr(keys, i), LDNS_SHA1); + local_print_ds(stdout, "; sha1: ", ds); + ds = ldns_key_rr2ds(ldns_rr_list_rr(keys, i), LDNS_SHA256); + local_print_ds(stdout, "; sha256: ", ds); + } + } +} + +static void +print_class_type(FILE *fp, ldns_rr *r) +{ + ldns_lookup_table *lt; + lt = ldns_lookup_by_id(ldns_rr_classes, ldns_rr_get_class(r)); + if (lt) { + fprintf(fp, " %s", lt->name); + } else { + fprintf(fp, " CLASS%d", ldns_rr_get_class(r)); + } + /* okay not THE way - but the quickest */ + switch (ldns_rr_get_type(r)) { + case LDNS_RR_TYPE_RRSIG: + fprintf(fp, " RRSIG "); + break; + case LDNS_RR_TYPE_DNSKEY: + fprintf(fp, " DNSKEY "); + break; + case LDNS_RR_TYPE_DS: + fprintf(fp, " DS "); + break; + default: + break; + } +} + + +void +print_ds_abbr(FILE *fp, ldns_rr *ds) +{ + if (!ds || (ldns_rr_get_type(ds) != LDNS_RR_TYPE_DS)) { + return; + } + + ldns_rdf_print(fp, ldns_rr_owner(ds)); + fprintf(fp, " %d", (int)ldns_rr_ttl(ds)); + print_class_type(fp, ds); + ldns_rdf_print(fp, ldns_rr_rdf(ds, 0)); fprintf(fp, " "); + ldns_rdf_print(fp, ldns_rr_rdf(ds, 1)); fprintf(fp, " "); + ldns_rdf_print(fp, ldns_rr_rdf(ds, 2)); fprintf(fp, " "); + ldns_rdf_print(fp, ldns_rr_rdf(ds, 3)); fprintf(fp, " "); +} + +/* print some of the elements of a signature */ +void +print_rrsig_abbr(FILE *fp, ldns_rr *sig) { + if (!sig || (ldns_rr_get_type(sig) != LDNS_RR_TYPE_RRSIG)) { + return; + } + + ldns_rdf_print(fp, ldns_rr_owner(sig)); + fprintf(fp, " %d", (int)ldns_rr_ttl(sig)); + print_class_type(fp, sig); + + /* print a number of rdf's */ + /* typecovered */ + ldns_rdf_print(fp, ldns_rr_rdf(sig, 0)); fprintf(fp, " "); + /* algo */ + ldns_rdf_print(fp, ldns_rr_rdf(sig, 1)); fprintf(fp, " "); + /* labels */ + ldns_rdf_print(fp, ldns_rr_rdf(sig, 2)); fprintf(fp, " (\n\t\t\t"); + /* expir */ + ldns_rdf_print(fp, ldns_rr_rdf(sig, 4)); fprintf(fp, " "); + /* incep */ + ldns_rdf_print(fp, ldns_rr_rdf(sig, 5)); fprintf(fp, " "); + /* key-id */ + ldns_rdf_print(fp, ldns_rr_rdf(sig, 6)); fprintf(fp, " "); + /* key owner */ + ldns_rdf_print(fp, ldns_rr_rdf(sig, 7)); fprintf(fp, ")"); +} + +void +print_dnskey_abbr(FILE *fp, ldns_rr *key) +{ + if (!key || (ldns_rr_get_type(key) != LDNS_RR_TYPE_DNSKEY)) { + return; + } + + ldns_rdf_print(fp, ldns_rr_owner(key)); + fprintf(fp, " %d", (int)ldns_rr_ttl(key)); + print_class_type(fp, key); + + /* print a number of rdf's */ + /* flags */ + ldns_rdf_print(fp, ldns_rr_rdf(key, 0)); fprintf(fp, " "); + /* proto */ + ldns_rdf_print(fp, ldns_rr_rdf(key, 1)); fprintf(fp, " "); + /* algo */ + ldns_rdf_print(fp, ldns_rr_rdf(key, 2)); + + if (ldns_rdf2native_int16(ldns_rr_rdf(key, 0)) == 256) { + fprintf(fp, " ;{id = %u (zsk), size = %db}", (unsigned int)ldns_calc_keytag(key), + (int)ldns_rr_dnskey_key_size(key)); + return; + } + if (ldns_rdf2native_int16(ldns_rr_rdf(key, 0)) == 257) { + fprintf(fp, " ;{id = %u (ksk), size = %db}", (unsigned int)ldns_calc_keytag(key), + (int)ldns_rr_dnskey_key_size(key)); + return; + } + fprintf(fp, " ;{id = %u, size = %db}", (unsigned int)ldns_calc_keytag(key), + (int)ldns_rr_dnskey_key_size(key)); +} + +void +print_rr_list_abbr(FILE *fp, ldns_rr_list *rrlist, const char *usr) +{ + size_t i; + ldns_rr_type tp; + + for(i = 0; i < ldns_rr_list_rr_count(rrlist); i++) { + tp = ldns_rr_get_type(ldns_rr_list_rr(rrlist, i)); + if (i == 0 && tp != LDNS_RR_TYPE_RRSIG) { + if (usr) { + fprintf(fp, "%s ", usr); + } + } + switch(tp) { + case LDNS_RR_TYPE_DNSKEY: + print_dnskey_abbr(fp, ldns_rr_list_rr(rrlist, i)); + break; + case LDNS_RR_TYPE_RRSIG: + print_rrsig_abbr(fp, ldns_rr_list_rr(rrlist, i)); + break; + case LDNS_RR_TYPE_DS: + print_ds_abbr(fp, ldns_rr_list_rr(rrlist, i)); + break; + default: + /* not handled */ + break; + } + fputs("\n", fp); + } +} + +void * +xmalloc(size_t s) +{ + void *p; + + p = malloc(s); + if (!p) { + printf("Mem failure\n"); + exit(EXIT_FAILURE); + } + return p; +} + +void * +xrealloc(void *p, size_t size) +{ + void *q; + + q = realloc(p, size); + if (!q) { + printf("Mem failure\n"); + exit(EXIT_FAILURE); + } + return q; +} + +void +xfree(void *p) +{ + if (p) { + free(p); + } +} diff --git a/drill/drill_util.h b/drill/drill_util.h new file mode 100644 index 00000000000..de7844118db --- /dev/null +++ b/drill/drill_util.h @@ -0,0 +1,58 @@ +/* + * util.h + * util.c header file + * in ldns + * (c) 2005 NLnet Labs + * + * See the file LICENSE for the license + * + */ + +#ifndef _DRILL_UTIL_H_ +#define _DRILL_UTIL_H_ +#include + +/** + * return a address rdf, either A or AAAA + * NULL if anything goes wrong + */ +ldns_rdf * ldns_rdf_new_addr_frm_str(char *); + +/** + * print all the ds of the keys in the packet + */ +void print_ds_of_keys(ldns_pkt *p); + +/** + * print some rdfs of a signature + */ +void print_rrsig_abbr(FILE *fp, ldns_rr *sig); +/** + * print some rdfs of a dnskey + */ +void print_dnskey_abbr(FILE *fp, ldns_rr *key); +/** + * print some rdfs of a ds + */ +void print_ds_abbr(FILE *fp, ldns_rr *ds); + +/** + * print some rdfs of a rr in a rr_list + */ +void print_rr_list_abbr(FILE *fp, ldns_rr_list *sig, const char *usr); + +/** + * Alloc some memory, with error checking + */ +void *xmalloc(size_t s); + +/** + * Realloc some memory, with error checking + */ +void *xrealloc(void *p, size_t s); + +/** + * Free the data + */ +void xfree(void *q); +#endif /* _DRILL_UTIL_H_ */ diff --git a/drill/error.c b/drill/error.c new file mode 100644 index 00000000000..e67b7fca020 --- /dev/null +++ b/drill/error.c @@ -0,0 +1,115 @@ +/** + * error.c + * + * error reporting routines + * basicly wrappers around printf + * + * (c) 2005 NLnet Labs + * + * See the file LICENSE for the license + * + */ + +#include "drill.h" +#include + +static void +warning_va_list(const char *fmt, va_list args) +{ + fprintf(stderr, "Warning: "); + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); +} + +void +warning(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + warning_va_list(fmt, args); + va_end(args); +} + +static void +error_va_list(const char *fmt, va_list args) +{ + fprintf(stderr, "Error: "); + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); +} + +void +error(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + error_va_list(fmt, args); + va_end(args); + exit(EXIT_FAILURE); +} + +static void +verbose_va_list(const char *fmt, va_list args) +{ + vfprintf(stdout, fmt, args); + fprintf(stdout, "\n"); +} + +/* print stuff */ +void +mesg(const char *fmt, ...) +{ + va_list args; + if (verbosity == -1) { + return; + } + fprintf(stdout, ";; "); + va_start(args, fmt); + verbose_va_list(fmt, args); + va_end(args); +} + +/* print stuff when in verbose mode (1) */ +void +verbose(const char *fmt, ...) +{ + va_list args; + if (verbosity < 1) { + return; + } + + va_start(args, fmt); + verbose_va_list(fmt, args); + va_end(args); +} + +/* print stuff when in vverbose mode (2) */ +void +vverbose(const char *fmt, ...) +{ + va_list args; + if (verbosity < 2) { + return; + } + + va_start(args, fmt); + verbose_va_list(fmt, args); + va_end(args); +} + +static void +debug_va_list(const char *fmt, va_list args) +{ + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); +} + +void +debug(const char *fmt, ...) +{ + va_list args; + fprintf(stderr, "[DEBUG] "); + va_start(args, fmt); + debug_va_list(fmt, args); + va_end(args); +} diff --git a/drill/install-sh b/drill/install-sh new file mode 100755 index 00000000000..6781b987bdb --- /dev/null +++ b/drill/install-sh @@ -0,0 +1,520 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2009-04-28.21; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +nl=' +' +IFS=" "" $nl" + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +no_target_directory= + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) dst_arg=$2 + shift;; + + -T) no_target_directory=true;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + trap '(exit $?); exit' 1 2 13 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dst_arg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writeable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + -*) prefix='./';; + *) prefix='';; + esac + + eval "$initialize_posix_glob" + + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir + shift + $posix_glob set +f + IFS=$oIFS + + prefixes= + + for d + do + test -z "$d" && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && + + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/drill/root.c b/drill/root.c new file mode 100644 index 00000000000..a829935cd5a --- /dev/null +++ b/drill/root.c @@ -0,0 +1,122 @@ +/* + * root.c + * Function to handle to the rootservers + * and to update and prime them + * (c) 2005 NLnet Labs + * + * See the file LICENSE for the license + * + */ + +#include "drill.h" +#include +#include + +/* a global list of the root-servers */ +ldns_rr_list *global_dns_root = NULL; + +/* put a hardcoded list in the root and + * init the root rrlist structure */ +void +init_root(void) +{ + ldns_rr *r; + + global_dns_root = ldns_rr_list_new(); + + (void)ldns_rr_new_frm_str(&r, "A.ROOT-SERVERS.NET. 3600000 A 198.41.0.4", 0, NULL, NULL); + ldns_rr_list_push_rr(global_dns_root, r); + (void)ldns_rr_new_frm_str(&r, "A.ROOT-SERVERS.NET. 3600000 AAAA 2001:503:BA3E::2:30", 0, NULL, NULL); + ldns_rr_list_push_rr(global_dns_root, r); + (void)ldns_rr_new_frm_str(&r, "B.ROOT-SERVERS.NET. 3600000 A 192.228.79.201", 0, NULL, NULL); + ldns_rr_list_push_rr(global_dns_root, r); + (void)ldns_rr_new_frm_str(&r, "C.ROOT-SERVERS.NET. 3600000 A 192.33.4.12", 0, NULL, NULL); + ldns_rr_list_push_rr(global_dns_root, r); + (void)ldns_rr_new_frm_str(&r, "D.ROOT-SERVERS.NET. 3600000 A 128.8.10.90", 0, NULL, NULL); + ldns_rr_list_push_rr(global_dns_root, r); + (void)ldns_rr_new_frm_str(&r, "E.ROOT-SERVERS.NET. 3600000 A 192.203.230.10", 0, NULL, NULL); + ldns_rr_list_push_rr(global_dns_root, r); + (void)ldns_rr_new_frm_str(&r, "F.ROOT-SERVERS.NET. 3600000 A 192.5.5.241", 0, NULL, NULL); + ldns_rr_list_push_rr(global_dns_root, r); + (void)ldns_rr_new_frm_str(&r, "F.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:2F::F", 0, NULL, NULL); + ldns_rr_list_push_rr(global_dns_root, r); + (void)ldns_rr_new_frm_str(&r, "G.ROOT-SERVERS.NET. 3600000 A 192.112.36.4", 0, NULL, NULL); + ldns_rr_list_push_rr(global_dns_root, r); + (void)ldns_rr_new_frm_str(&r, "H.ROOT-SERVERS.NET. 3600000 A 128.63.2.53", 0, NULL, NULL); + ldns_rr_list_push_rr(global_dns_root, r); + (void)ldns_rr_new_frm_str(&r, "H.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:1::803F:235", 0, NULL, NULL); + ldns_rr_list_push_rr(global_dns_root, r); + (void)ldns_rr_new_frm_str(&r, "I.ROOT-SERVERS.NET. 3600000 A 192.36.148.17", 0, NULL, NULL); + ldns_rr_list_push_rr(global_dns_root, r); + (void)ldns_rr_new_frm_str(&r, "J.ROOT-SERVERS.NET. 3600000 A 192.58.128.30", 0, NULL, NULL); + ldns_rr_list_push_rr(global_dns_root, r); + (void)ldns_rr_new_frm_str(&r, "J.ROOT-SERVERS.NET. 3600000 AAAA 2001:503:C27::2:30", 0, NULL, NULL); + ldns_rr_list_push_rr(global_dns_root, r); + (void)ldns_rr_new_frm_str(&r, "K.ROOT-SERVERS.NET. 3600000 A 193.0.14.129 ", 0, NULL, NULL); + ldns_rr_list_push_rr(global_dns_root, r); + (void)ldns_rr_new_frm_str(&r, "K.ROOT-SERVERS.NET. 3600000 AAAA 2001:7FD::1", 0, NULL, NULL); + ldns_rr_list_push_rr(global_dns_root, r); + (void)ldns_rr_new_frm_str(&r, "L.ROOT-SERVERS.NET. 3600000 A 199.7.83.42", 0, NULL, NULL); + ldns_rr_list_push_rr(global_dns_root, r); + (void)ldns_rr_new_frm_str(&r, "L.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:3::42 ", 0, NULL, NULL); + ldns_rr_list_push_rr(global_dns_root, r); + (void)ldns_rr_new_frm_str(&r, "M.ROOT-SERVERS.NET. 3600000 A 202.12.27.33", 0, NULL, NULL); + ldns_rr_list_push_rr(global_dns_root, r); + (void)ldns_rr_new_frm_str(&r, "M.ROOT-SERVERS.NET. 3600000 AAAA 2001:DC3::35", 0, NULL, NULL); + ldns_rr_list_push_rr(global_dns_root, r); +} + +/* + * Read a hints file as root + * + * The file with the given path should contain a list of NS RRs + * for the root zone and A records for those NS RRs. + * Read them, check them, and append the a records to the rr list given. + */ +ldns_rr_list * +read_root_hints(const char *filename) +{ + FILE *fp = NULL; + int line_nr = 0; + ldns_zone *z; + ldns_status status; + ldns_rr_list *addresses = NULL; + ldns_rr *rr; + size_t i; + + fp = fopen(filename, "r"); + if (!fp) { + fprintf(stderr, "Unable to open %s for reading: %s\n", filename, strerror(errno)); + return NULL; + } + + status = ldns_zone_new_frm_fp_l(&z, fp, NULL, 0, 0, &line_nr); + fclose(fp); + if (status != LDNS_STATUS_OK) { + fprintf(stderr, "Error reading root hints file: %s\n", ldns_get_errorstr_by_id(status)); + return NULL; + } else { + addresses = ldns_rr_list_new(); + for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(z)); i++) { + rr = ldns_rr_list_rr(ldns_zone_rrs(z), i); + /*if ((address_family == 0 || address_family == 1) && + */ + if ( ldns_rr_get_type(rr) == LDNS_RR_TYPE_A ) { + ldns_rr_list_push_rr(addresses, ldns_rr_clone(rr)); + } + /*if ((address_family == 0 || address_family == 2) &&*/ + if ( ldns_rr_get_type(rr) == LDNS_RR_TYPE_AAAA) { + ldns_rr_list_push_rr(addresses, ldns_rr_clone(rr)); + } + } + ldns_zone_deep_free(z); + return addresses; + } +} + + +void +clear_root(void) +{ + ldns_rr_list_deep_free(global_dns_root); +} diff --git a/drill/securetrace.c b/drill/securetrace.c new file mode 100644 index 00000000000..029ebf51d6f --- /dev/null +++ b/drill/securetrace.c @@ -0,0 +1,746 @@ +/* + * securechasetrace.c + * Where all the hard work concerning secure tracing is done + * + * (c) 2005, 2006 NLnet Labs + * + * See the file LICENSE for the license + * + */ + +#include "drill.h" +#include + +#define SELF "[S]" /* self sig ok */ +#define TRUST "[T]" /* chain from parent */ +#define BOGUS "[B]" /* bogus */ +#define UNSIGNED "[U]" /* no relevant dnssec data found */ + +#if 0 +/* See if there is a key/ds in trusted that matches + * a ds in *ds. + */ +static ldns_rr_list * +ds_key_match(ldns_rr_list *ds, ldns_rr_list *trusted) +{ + size_t i, j; + bool match; + ldns_rr *rr_i, *rr_j; + ldns_rr_list *keys; + + if (!trusted || !ds) { + return NULL; + } + + match = false; + keys = ldns_rr_list_new(); + if (!keys) { + return NULL; + } + + if (!ds || !trusted) { + return NULL; + } + + for (i = 0; i < ldns_rr_list_rr_count(trusted); i++) { + rr_i = ldns_rr_list_rr(trusted, i); + for (j = 0; j < ldns_rr_list_rr_count(ds); j++) { + + rr_j = ldns_rr_list_rr(ds, j); + if (ldns_rr_compare_ds(rr_i, rr_j)) { + match = true; + /* only allow unique RRs to match */ + ldns_rr_set_push_rr(keys, rr_i); + } + } + } + if (match) { + return keys; + } else { + return NULL; + } +} +#endif + +ldns_pkt * +get_dnssec_pkt(ldns_resolver *r, ldns_rdf *name, ldns_rr_type t) +{ + ldns_pkt *p = NULL; + p = ldns_resolver_query(r, name, t, LDNS_RR_CLASS_IN, 0); + if (!p) { + return NULL; + } else { + if (verbosity >= 5) { + ldns_pkt_print(stdout, p); + } + return p; + } +} + +#ifdef HAVE_SSL +/* + * retrieve keys for this zone + */ +static ldns_pkt_type +get_key(ldns_pkt *p, ldns_rdf *apexname, ldns_rr_list **rrlist, ldns_rr_list **opt_sig) +{ + return get_dnssec_rr(p, apexname, LDNS_RR_TYPE_DNSKEY, rrlist, opt_sig); +} + +/* + * check to see if we can find a DS rrset here which we can then follow + */ +static ldns_pkt_type +get_ds(ldns_pkt *p, ldns_rdf *ownername, ldns_rr_list **rrlist, ldns_rr_list **opt_sig) +{ + return get_dnssec_rr(p, ownername, LDNS_RR_TYPE_DS, rrlist, opt_sig); +} +#endif /* HAVE_SSL */ + +void +remove_resolver_nameservers(ldns_resolver *res) +{ + ldns_rdf *pop; + + /* remove the old nameserver from the resolver */ + while((pop = ldns_resolver_pop_nameserver(res))) { + ldns_rdf_deep_free(pop); + } + +} + +void +show_current_nameservers(FILE *out, ldns_resolver *res) +{ + size_t i; + fprintf(out, "Current nameservers for resolver object:\n"); + for (i = 0; i < ldns_resolver_nameserver_count(res); i++) { + ldns_rdf_print(out, ldns_resolver_nameservers(res)[i]); + fprintf(out, "\n"); + } +} + +/*ldns_pkt **/ +#ifdef HAVE_SSL +int +do_secure_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t, + ldns_rr_class c, ldns_rr_list *trusted_keys, ldns_rdf *start_name + ) +{ + ldns_resolver *res; + ldns_pkt *p, *local_p; + ldns_rr_list *new_nss; + ldns_rr_list *ns_addr; + ldns_rdf *pop; + ldns_rdf **labels = NULL; + ldns_status status, st; + ssize_t i; + size_t j; + size_t k; + size_t l; + uint8_t labels_count; + + /* dnssec */ + ldns_rr_list *key_list; + ldns_rr_list *key_sig_list; + ldns_rr_list *ds_list; + ldns_rr_list *ds_sig_list; + ldns_rr_list *correct_key_list; + ldns_rr_list *trusted_ds_rrs; + bool new_keys_trusted = false; + ldns_rr_list *current_correct_keys; + ldns_rr_list *dataset; + + ldns_rr_list *nsec_rrs = NULL; + ldns_rr_list *nsec_rr_sigs = NULL; + + /* empty non-terminal check */ + bool ent; + + /* glue handling */ + ldns_rr_list *new_ns_addr; + ldns_rr_list *old_ns_addr; + ldns_rr *ns_rr; + + int result = 0; + + /* printing niceness */ + const ldns_rr_descriptor *descriptor; + + descriptor = ldns_rr_descript(t); + + new_nss = NULL; + ns_addr = NULL; + key_list = NULL; + ds_list = NULL; + + p = NULL; + local_p = NULL; + res = ldns_resolver_new(); + key_sig_list = NULL; + ds_sig_list = NULL; + + if (!res) { + error("Memory allocation failed"); + result = -1; + return result; + } + + correct_key_list = ldns_rr_list_new(); + if (!correct_key_list) { + error("Memory allocation failed"); + result = -1; + return result; + } + + trusted_ds_rrs = ldns_rr_list_new(); + if (!trusted_ds_rrs) { + error("Memory allocation failed"); + result = -1; + return result; + } + /* Add all preset trusted DS signatures to the list of trusted DS RRs. */ + for (j = 0; j < ldns_rr_list_rr_count(trusted_keys); j++) { + ldns_rr* one_rr = ldns_rr_list_rr(trusted_keys, j); + if (ldns_rr_get_type(one_rr) == LDNS_RR_TYPE_DS) { + ldns_rr_list_push_rr(trusted_ds_rrs, ldns_rr_clone(one_rr)); + } + } + + /* transfer some properties of local_res to res */ + ldns_resolver_set_ip6(res, + ldns_resolver_ip6(local_res)); + ldns_resolver_set_port(res, + ldns_resolver_port(local_res)); + ldns_resolver_set_debug(res, + ldns_resolver_debug(local_res)); + ldns_resolver_set_fail(res, + ldns_resolver_fail(local_res)); + ldns_resolver_set_usevc(res, + ldns_resolver_usevc(local_res)); + ldns_resolver_set_random(res, + ldns_resolver_random(local_res)); + ldns_resolver_set_recursive(local_res, true); + + ldns_resolver_set_recursive(res, false); + ldns_resolver_set_dnssec_cd(res, false); + ldns_resolver_set_dnssec(res, true); + + /* setup the root nameserver in the new resolver */ + status = ldns_resolver_push_nameserver_rr_list(res, global_dns_root); + if (status != LDNS_STATUS_OK) { + printf("ERRRRR: %s\n", ldns_get_errorstr_by_id(status)); + ldns_rr_list_print(stdout, global_dns_root); + return status; + } + labels_count = ldns_dname_label_count(name); + if (start_name) { + if (ldns_dname_is_subdomain(name, start_name)) { + labels_count -= ldns_dname_label_count(start_name); + } else { + fprintf(stderr, "Error; "); + ldns_rdf_print(stderr, name); + fprintf(stderr, " is not a subdomain of "); + ldns_rdf_print(stderr, start_name); + fprintf(stderr, "\n"); + goto done; + } + } + labels = LDNS_XMALLOC(ldns_rdf*, labels_count + 2); + if (!labels) { + goto done; + } + labels[0] = ldns_dname_new_frm_str(LDNS_ROOT_LABEL_STR); + labels[1] = ldns_rdf_clone(name); + for(i = 2 ; i < (ssize_t)labels_count + 2; i++) { + labels[i] = ldns_dname_left_chop(labels[i - 1]); + } + + /* get the nameserver for the label + * ask: dnskey and ds for the label + */ + for(i = (ssize_t)labels_count + 1; i > 0; i--) { + status = ldns_resolver_send(&local_p, res, labels[i], LDNS_RR_TYPE_NS, c, 0); + + if (verbosity >= 5) { + ldns_pkt_print(stdout, local_p); + } + + new_nss = ldns_pkt_rr_list_by_type(local_p, + LDNS_RR_TYPE_NS, LDNS_SECTION_ANSWER); + if (!new_nss) { + /* if it's a delegation, servers put them in the auth section */ + new_nss = ldns_pkt_rr_list_by_type(local_p, + LDNS_RR_TYPE_NS, LDNS_SECTION_AUTHORITY); + } + + /* if this is the final step there might not be nameserver records + of course if the data is in the apex, there are, so cover both + cases */ + if (new_nss || i > 1) { + for(j = 0; j < ldns_rr_list_rr_count(new_nss); j++) { + ns_rr = ldns_rr_list_rr(new_nss, j); + pop = ldns_rr_rdf(ns_rr, 0); + if (!pop) { + printf("nopo\n"); + break; + } + /* retrieve it's addresses */ + /* trust glue? */ + new_ns_addr = NULL; + if (ldns_dname_is_subdomain(pop, labels[i])) { + new_ns_addr = ldns_pkt_rr_list_by_name_and_type(local_p, pop, LDNS_RR_TYPE_A, LDNS_SECTION_ADDITIONAL); + } + if (!new_ns_addr || ldns_rr_list_rr_count(new_ns_addr) == 0) { + new_ns_addr = ldns_get_rr_list_addr_by_name(res, pop, c, 0); + } + if (!new_ns_addr || ldns_rr_list_rr_count(new_ns_addr) == 0) { + new_ns_addr = ldns_get_rr_list_addr_by_name(local_res, pop, c, 0); + } + + if (new_ns_addr) { + old_ns_addr = ns_addr; + ns_addr = ldns_rr_list_cat_clone(ns_addr, new_ns_addr); + ldns_rr_list_deep_free(old_ns_addr); + } + ldns_rr_list_deep_free(new_ns_addr); + } + ldns_rr_list_deep_free(new_nss); + + if (ns_addr) { + remove_resolver_nameservers(res); + + if (ldns_resolver_push_nameserver_rr_list(res, ns_addr) != + LDNS_STATUS_OK) { + error("Error adding new nameservers"); + ldns_pkt_free(local_p); + goto done; + } + ldns_rr_list_deep_free(ns_addr); + } else { + status = ldns_verify_denial(local_p, labels[i], LDNS_RR_TYPE_NS, &nsec_rrs, &nsec_rr_sigs); + + /* verify the nsec3 themselves*/ + if (verbosity >= 4) { + printf("NSEC(3) Records to verify:\n"); + ldns_rr_list_print(stdout, nsec_rrs); + printf("With signatures:\n"); + ldns_rr_list_print(stdout, nsec_rr_sigs); + printf("correct keys:\n"); + ldns_rr_list_print(stdout, correct_key_list); + } + + if (status == LDNS_STATUS_OK) { + if ((st = ldns_verify(nsec_rrs, nsec_rr_sigs, trusted_keys, NULL)) == LDNS_STATUS_OK) { + fprintf(stdout, "%s ", TRUST); + fprintf(stdout, "Existence denied: "); + ldns_rdf_print(stdout, labels[i]); + /* + if (descriptor && descriptor->_name) { + printf(" %s", descriptor->_name); + } else { + printf(" TYPE%u", t); + } + */ fprintf(stdout, " NS\n"); + } else if ((st = ldns_verify(nsec_rrs, nsec_rr_sigs, correct_key_list, NULL)) == LDNS_STATUS_OK) { + fprintf(stdout, "%s ", SELF); + fprintf(stdout, "Existence denied: "); + ldns_rdf_print(stdout, labels[i]); + /* + if (descriptor && descriptor->_name) { + printf(" %s", descriptor->_name); + } else { + printf(" TYPE%u", t); + } + */ + fprintf(stdout, " NS\n"); + } else { + fprintf(stdout, "%s ", BOGUS); + result = 1; + printf(";; Error verifying denial of existence for name "); + ldns_rdf_print(stdout, labels[i]); + /* + printf(" type "); + if (descriptor && descriptor->_name) { + printf("%s", descriptor->_name); + } else { + printf("TYPE%u", t); + } + */ printf("NS: %s\n", ldns_get_errorstr_by_id(st)); + } + } else { + fprintf(stdout, "%s ", BOGUS); + result = 1; + printf(";; Error verifying denial of existence for name "); + ldns_rdf_print(stdout, labels[i]); + printf("NS: %s\n", ldns_get_errorstr_by_id(status)); + } + + /* there might be an empty non-terminal, in which case we need to continue */ + ent = false; + for (j = 0; j < ldns_rr_list_rr_count(nsec_rrs); j++) { + if (ldns_dname_is_subdomain(ldns_rr_rdf(ldns_rr_list_rr(nsec_rrs, j), 0), labels[i])) { + ent = true; + } + } + if (!ent) { + ldns_rr_list_deep_free(nsec_rrs); + ldns_rr_list_deep_free(nsec_rr_sigs); + ldns_pkt_free(local_p); + goto done; + } else { + printf(";; There is an empty non-terminal here, continue\n"); + continue; + } + goto done; + } + + if (ldns_resolver_nameserver_count(res) == 0) { + error("No nameservers found for this node"); + goto done; + } + } + ldns_pkt_free(local_p); + + fprintf(stdout, ";; Domain: "); + ldns_rdf_print(stdout, labels[i]); + fprintf(stdout, "\n"); + + /* retrieve keys for current domain, and verify them + if they match an already trusted DS, or if one of the + keys used to sign these is trusted, add the keys to + the trusted list */ + p = get_dnssec_pkt(res, labels[i], LDNS_RR_TYPE_DNSKEY); + (void) get_key(p, labels[i], &key_list, &key_sig_list); + if (key_sig_list) { + if (key_list) { + current_correct_keys = ldns_rr_list_new(); + if ((st = ldns_verify(key_list, key_sig_list, key_list, current_correct_keys)) == + LDNS_STATUS_OK) { + /* add all signed keys (don't just add current_correct, you'd miss + * the zsk's then */ + for (j = 0; j < ldns_rr_list_rr_count(key_list); j++) { + ldns_rr_list_push_rr(correct_key_list, ldns_rr_clone(ldns_rr_list_rr(key_list, j))); + } + + /* check whether these keys were signed + * by a trusted keys. if so, these + * keys are also trusted */ + new_keys_trusted = false; + for (k = 0; k < ldns_rr_list_rr_count(current_correct_keys); k++) { + for (j = 0; j < ldns_rr_list_rr_count(trusted_ds_rrs); j++) { + if (ldns_rr_compare_ds(ldns_rr_list_rr(current_correct_keys, k), + ldns_rr_list_rr(trusted_ds_rrs, j))) { + new_keys_trusted = true; + } + } + } + + /* also all keys are trusted if one of the current correct keys is trusted */ + for (k = 0; k < ldns_rr_list_rr_count(current_correct_keys); k++) { + for (j = 0; j < ldns_rr_list_rr_count(trusted_keys); j++) { + if (ldns_rr_compare(ldns_rr_list_rr(current_correct_keys, k), + ldns_rr_list_rr(trusted_keys, j)) == 0) { + new_keys_trusted = true; + } + } + } + + + if (new_keys_trusted) { + ldns_rr_list_push_rr_list(trusted_keys, key_list); + print_rr_list_abbr(stdout, key_list, TRUST); + ldns_rr_list_free(key_list); + key_list = NULL; + } else { + if (verbosity >= 2) { + printf(";; Signature ok but no chain to a trusted key or ds record\n"); + } + print_rr_list_abbr(stdout, key_list, SELF); + ldns_rr_list_deep_free(key_list); + key_list = NULL; + } + } else { + print_rr_list_abbr(stdout, key_list, BOGUS); + result = 2; + ldns_rr_list_deep_free(key_list); + key_list = NULL; + } + ldns_rr_list_free(current_correct_keys); + current_correct_keys = NULL; + } else { + printf(";; No DNSKEY record found for "); + ldns_rdf_print(stdout, labels[i]); + printf("\n"); + } + } + + ldns_pkt_free(p); + ldns_rr_list_deep_free(key_sig_list); + key_sig_list = NULL; + + /* check the DS records for the next child domain */ + if (i > 1) { + p = get_dnssec_pkt(res, labels[i-1], LDNS_RR_TYPE_DS); + (void) get_ds(p, labels[i-1], &ds_list, &ds_sig_list); + if (!ds_list) { + ldns_pkt_free(p); + if (ds_sig_list) { + ldns_rr_list_deep_free(ds_sig_list); + } + p = get_dnssec_pkt(res, name, LDNS_RR_TYPE_DNSKEY); + (void) get_ds(p, NULL, &ds_list, &ds_sig_list); + } + if (ds_sig_list) { + if (ds_list) { + if (verbosity >= 4) { + printf("VERIFYING:\n"); + printf("DS LIST:\n"); + ldns_rr_list_print(stdout, ds_list); + printf("SIGS:\n"); + ldns_rr_list_print(stdout, ds_sig_list); + printf("KEYS:\n"); + ldns_rr_list_print(stdout, correct_key_list); + } + + current_correct_keys = ldns_rr_list_new(); + + if ((st = ldns_verify(ds_list, ds_sig_list, correct_key_list, current_correct_keys)) == + LDNS_STATUS_OK) { + /* if the ds is signed by a trusted key and a key from correct keys + matches that ds, add that key to the trusted keys */ + new_keys_trusted = false; + if (verbosity >= 2) { + printf("Checking if signing key is trusted:\n"); + } + for (j = 0; j < ldns_rr_list_rr_count(current_correct_keys); j++) { + if (verbosity >= 2) { + printf("New key: "); + ldns_rr_print(stdout, ldns_rr_list_rr(current_correct_keys, j)); + } + for (k = 0; k < ldns_rr_list_rr_count(trusted_keys); k++) { + if (verbosity >= 2) { + printf("\tTrusted key: "); + ldns_rr_print(stdout, ldns_rr_list_rr(trusted_keys, k)); + } + if (ldns_rr_compare(ldns_rr_list_rr(current_correct_keys, j), + ldns_rr_list_rr(trusted_keys, k)) == 0) { + if (verbosity >= 2) { + printf("Key is now trusted!\n"); + } + for (l = 0; l < ldns_rr_list_rr_count(ds_list); l++) { + ldns_rr_list_push_rr(trusted_ds_rrs, ldns_rr_clone(ldns_rr_list_rr(ds_list, l))); + new_keys_trusted = true; + } + } + } + } + if (new_keys_trusted) { + print_rr_list_abbr(stdout, ds_list, TRUST); + } else { + print_rr_list_abbr(stdout, ds_list, SELF); + } + } else { + result = 3; + print_rr_list_abbr(stdout, ds_list, BOGUS); + } + + ldns_rr_list_free(current_correct_keys); + current_correct_keys = NULL; + } else { + /* wait apparently there were no keys either, go back to the ds packet */ + ldns_pkt_free(p); + ldns_rr_list_deep_free(ds_sig_list); + p = get_dnssec_pkt(res, labels[i-1], LDNS_RR_TYPE_DS); + (void) get_ds(p, labels[i-1], &ds_list, &ds_sig_list); + + status = ldns_verify_denial(p, labels[i-1], LDNS_RR_TYPE_DS, &nsec_rrs, &nsec_rr_sigs); + + if (verbosity >= 4) { + printf("NSEC(3) Records to verify:\n"); + ldns_rr_list_print(stdout, nsec_rrs); + printf("With signatures:\n"); + ldns_rr_list_print(stdout, nsec_rr_sigs); + printf("correct keys:\n"); + ldns_rr_list_print(stdout, correct_key_list); + } + + if (status == LDNS_STATUS_OK) { + if ((st = ldns_verify(nsec_rrs, nsec_rr_sigs, trusted_keys, NULL)) == LDNS_STATUS_OK) { + fprintf(stdout, "%s ", TRUST); + fprintf(stdout, "Existence denied: "); + ldns_rdf_print(stdout, labels[i-1]); + printf(" DS"); + fprintf(stdout, "\n"); + } else if ((st = ldns_verify(nsec_rrs, nsec_rr_sigs, correct_key_list, NULL)) == LDNS_STATUS_OK) { + fprintf(stdout, "%s ", SELF); + fprintf(stdout, "Existence denied: "); + ldns_rdf_print(stdout, labels[i-1]); + printf(" DS"); + fprintf(stdout, "\n"); + } else { + result = 4; + fprintf(stdout, "%s ", BOGUS); + printf("Error verifying denial of existence for "); + ldns_rdf_print(stdout, labels[i-1]); + printf(" DS"); + printf(": %s\n", ldns_get_errorstr_by_id(st)); + } + + + } else { + if (status == LDNS_STATUS_CRYPTO_NO_RRSIG) { + printf(";; No DS for "); + ldns_rdf_print(stdout, labels[i - 1]); + } else { + printf("[B] Unable to verify denial of existence for "); + ldns_rdf_print(stdout, labels[i - 1]); + printf(" DS: %s\n", ldns_get_errorstr_by_id(status)); + } + } + if (verbosity >= 2) { + printf(";; No ds record for delegation\n"); + } + } + } + ldns_rr_list_deep_free(ds_list); + ldns_pkt_free(p); + } else { + /* if this is the last label, just verify the data and stop */ + p = get_dnssec_pkt(res, labels[i], t); + (void) get_dnssec_rr(p, labels[i], t, &dataset, &key_sig_list); + if (dataset && ldns_rr_list_rr_count(dataset) > 0) { + if (key_sig_list && ldns_rr_list_rr_count(key_sig_list) > 0) { + + /* If this is a wildcard, you must be able to deny exact match */ + if ((st = ldns_verify(dataset, key_sig_list, trusted_keys, NULL)) == LDNS_STATUS_OK) { + fprintf(stdout, "%s ", TRUST); + ldns_rr_list_print(stdout, dataset); + } else if ((st = ldns_verify(dataset, key_sig_list, correct_key_list, NULL)) == LDNS_STATUS_OK) { + fprintf(stdout, "%s ", SELF); + ldns_rr_list_print(stdout, dataset); + } else { + result = 5; + fprintf(stdout, "%s ", BOGUS); + ldns_rr_list_print(stdout, dataset); + printf(";; Error: %s\n", ldns_get_errorstr_by_id(st)); + } + } else { + fprintf(stdout, "%s ", UNSIGNED); + ldns_rr_list_print(stdout, dataset); + } + ldns_rr_list_deep_free(dataset); + } else { + status = ldns_verify_denial(p, name, t, &nsec_rrs, &nsec_rr_sigs); + if (status == LDNS_STATUS_OK) { + /* verify the nsec3 themselves*/ + if (verbosity >= 5) { + printf("NSEC(3) Records to verify:\n"); + ldns_rr_list_print(stdout, nsec_rrs); + printf("With signatures:\n"); + ldns_rr_list_print(stdout, nsec_rr_sigs); + printf("correct keys:\n"); + ldns_rr_list_print(stdout, correct_key_list); +/* + printf("trusted keys at %p:\n", trusted_keys); + ldns_rr_list_print(stdout, trusted_keys); +*/ } + + if ((st = ldns_verify(nsec_rrs, nsec_rr_sigs, trusted_keys, NULL)) == LDNS_STATUS_OK) { + fprintf(stdout, "%s ", TRUST); + fprintf(stdout, "Existence denied: "); + ldns_rdf_print(stdout, name); + if (descriptor && descriptor->_name) { + printf(" %s", descriptor->_name); + } else { + printf(" TYPE%u", t); + } + fprintf(stdout, "\n"); + } else if ((st = ldns_verify(nsec_rrs, nsec_rr_sigs, correct_key_list, NULL)) == LDNS_STATUS_OK) { + fprintf(stdout, "%s ", SELF); + fprintf(stdout, "Existence denied: "); + ldns_rdf_print(stdout, name); + if (descriptor && descriptor->_name) { + printf(" %s", descriptor->_name); + } else { + printf(" TYPE%u", t); + } + fprintf(stdout, "\n"); + } else { + result = 6; + fprintf(stdout, "%s ", BOGUS); + printf("Error verifying denial of existence for "); + ldns_rdf_print(stdout, name); + printf(" type "); + if (descriptor && descriptor->_name) { + printf("%s", descriptor->_name); + } else { + printf("TYPE%u", t); + } + printf(": %s\n", ldns_get_errorstr_by_id(st)); + } + + ldns_rr_list_deep_free(nsec_rrs); + ldns_rr_list_deep_free(nsec_rr_sigs); + } else { +/* +*/ + if (status == LDNS_STATUS_CRYPTO_NO_RRSIG) { + printf("%s ", UNSIGNED); + printf("No data found for: "); + ldns_rdf_print(stdout, name); + printf(" type "); + if (descriptor && descriptor->_name) { + printf("%s", descriptor->_name); + } else { + printf("TYPE%u", t); + } + printf("\n"); + } else { + printf("[B] Unable to verify denial of existence for "); + ldns_rdf_print(stdout, name); + printf(" type "); + if (descriptor && descriptor->_name) { + printf("%s", descriptor->_name); + } else { + printf("TYPE%u", t); + } + printf("\n"); + } + + } + } + ldns_pkt_free(p); + } + + new_nss = NULL; + ns_addr = NULL; + ldns_rr_list_deep_free(key_list); + key_list = NULL; + ldns_rr_list_deep_free(key_sig_list); + key_sig_list = NULL; + ds_list = NULL; + ldns_rr_list_deep_free(ds_sig_list); + ds_sig_list = NULL; + } + printf(";;" SELF " self sig OK; " BOGUS " bogus; " TRUST " trusted\n"); + /* verbose mode? + printf("Trusted keys:\n"); + ldns_rr_list_print(stdout, trusted_keys); + printf("trusted dss:\n"); + ldns_rr_list_print(stdout, trusted_ds_rrs); + */ + + done: + ldns_rr_list_deep_free(trusted_ds_rrs); + ldns_rr_list_deep_free(correct_key_list); + ldns_resolver_deep_free(res); + if (labels) { + for(i = 0 ; i < (ssize_t)labels_count + 2; i++) { + ldns_rdf_deep_free(labels[i]); + } + LDNS_FREE(labels); + } + return result; +} +#endif /* HAVE_SSL */ diff --git a/drill/work.c b/drill/work.c new file mode 100644 index 00000000000..3a9cb5855d7 --- /dev/null +++ b/drill/work.c @@ -0,0 +1,276 @@ +/* + * work.c + * Where all the hard work is done + * (c) 2005 NLnet Labs + * + * See the file LICENSE for the license + * + */ + +#include "drill.h" +#include + +/** + * Converts a hex string to binary data + * len is the length of the string + * buf is the buffer to store the result in + * offset is the starting position in the result buffer + * + * This function returns the length of the result + */ +size_t +hexstr2bin(char *hexstr, int len, uint8_t *buf, size_t offset, size_t buf_len) +{ + char c; + int i; + uint8_t int8 = 0; + int sec = 0; + size_t bufpos = 0; + + if (len % 2 != 0) { + return 0; + } + + for (i=0; i= '0' && c <= '9') { + int8 += c & 0x0f; + } else if (c >= 'a' && c <= 'z') { + int8 += (c & 0x0f) + 9; + } else if (c >= 'A' && c <= 'Z') { + int8 += (c & 0x0f) + 9; + } else { + return 0; + } + + if (sec == 0) { + int8 = int8 << 4; + sec = 1; + } else { + if (bufpos + offset + 1 <= buf_len) { + buf[bufpos+offset] = int8; + int8 = 0; + sec = 0; + bufpos++; + } else { + error("Buffer too small in hexstr2bin"); + } + } + } + } + return bufpos; +} + +size_t +packetbuffromfile(char *filename, uint8_t *wire) +{ + FILE *fp = NULL; + int c; + + /* stat hack + * 0 = normal + * 1 = comment (skip to end of line) + * 2 = unprintable character found, read binary data directly + */ + int state = 0; + uint8_t *hexbuf = xmalloc(LDNS_MAX_PACKETLEN); + int hexbufpos = 0; + size_t wirelen; + + if (strncmp(filename, "-", 2) == 0) { + fp = stdin; + } else { + fp = fopen(filename, "r"); + } + if (fp == NULL) { + perror("Unable to open file for reading"); + xfree(hexbuf); + return 0; + } + + /*verbose("Opened %s\n", filename);*/ + + c = fgetc(fp); + while (c != EOF && hexbufpos < LDNS_MAX_PACKETLEN) { + if (state < 2 && !isascii(c)) { + /*verbose("non ascii character found in file: (%d) switching to raw mode\n", c);*/ + state = 2; + } + switch (state) { + case 0: + if ( (c >= '0' && c <= '9') || + (c >= 'a' && c <= 'f') || + (c >= 'A' && c <= 'F') ) + { + hexbuf[hexbufpos] = (uint8_t) c; + hexbufpos++; + } else if (c == ';') { + state = 1; + } else if (c == ' ' || c == '\t' || c == '\n') { + /* skip whitespace */ + } + break; + case 1: + if (c == '\n' || c == EOF) { + state = 0; + } + break; + case 2: + hexbuf[hexbufpos] = (uint8_t) c; + hexbufpos++; + break; + default: + warning("unknown state while reading %s", filename); + xfree(hexbuf); + return 0; + break; + } + c = fgetc(fp); + } + + if (c == EOF) { + /* + if (have_drill_opt && drill_opt->verbose) { + verbose("END OF FILE REACHED\n"); + if (state < 2) { + verbose("read:\n"); + verbose("%s\n", hexbuf); + } else { + verbose("Not printing wire because it contains non ascii data\n"); + } + } + */ + } + if (hexbufpos >= LDNS_MAX_PACKETLEN) { + /*verbose("packet size reached\n");*/ + } + + /* lenient mode: length must be multiple of 2 */ + if (hexbufpos % 2 != 0) { + hexbuf[hexbufpos] = (uint8_t) '0'; + hexbufpos++; + } + + if (state < 2) { + wirelen = hexstr2bin((char *) hexbuf, + hexbufpos, + wire, + 0, + LDNS_MAX_PACKETLEN); + } else { + memcpy(wire, hexbuf, (size_t) hexbufpos); + wirelen = (size_t) hexbufpos; + } + if (fp != stdin) { + fclose(fp); + } + xfree(hexbuf); + return wirelen; +} + +ldns_buffer * +read_hex_buffer(char *filename) +{ + uint8_t *wire; + size_t wiresize; + ldns_buffer *result_buffer = NULL; + + FILE *fp = NULL; + + if (strncmp(filename, "-", 2) != 0) { + fp = fopen(filename, "r"); + } else { + fp = stdin; + } + + if (fp == NULL) { + perror(""); + warning("Unable to open %s", filename); + return NULL; + } + + wire = xmalloc(LDNS_MAX_PACKETLEN); + + wiresize = packetbuffromfile(filename, wire); + + result_buffer = LDNS_MALLOC(ldns_buffer); + ldns_buffer_new_frm_data(result_buffer, wire, wiresize); + ldns_buffer_set_position(result_buffer, ldns_buffer_capacity(result_buffer)); + + xfree(wire); + return result_buffer; +} + +ldns_pkt * +read_hex_pkt(char *filename) +{ + uint8_t *wire; + size_t wiresize; + + ldns_pkt *pkt = NULL; + + ldns_status status = LDNS_STATUS_ERR; + + wire = xmalloc(LDNS_MAX_PACKETLEN); + + wiresize = packetbuffromfile(filename, wire); + + if (wiresize > 0) { + status = ldns_wire2pkt(&pkt, wire, wiresize); + } + + xfree(wire); + + if (status == LDNS_STATUS_OK) { + return pkt; + } else { + fprintf(stderr, "Error parsing hex file: %s\n", + ldns_get_errorstr_by_id(status)); + return NULL; + } +} + +void +dump_hex(const ldns_pkt *pkt, const char *filename) +{ + uint8_t *wire; + size_t size, i; + FILE *fp; + ldns_status status; + + fp = fopen(filename, "w"); + + if (fp == NULL) { + error("Unable to open %s for writing", filename); + return; + } + + status = ldns_pkt2wire(&wire, pkt, &size); + + if (status != LDNS_STATUS_OK) { + error("Unable to convert packet: error code %u", status); + return; + } + + fprintf(fp, "; 0"); + for (i = 1; i < 20; i++) { + fprintf(fp, " %2u", (unsigned int) i); + } + fprintf(fp, "\n"); + fprintf(fp, ";--"); + for (i = 1; i < 20; i++) { + fprintf(fp, " --"); + } + fprintf(fp, "\n"); + for (i = 0; i < size; i++) { + if (i % 20 == 0 && i > 0) { + fprintf(fp, "\t;\t%4u-%4u\n", (unsigned int) i-19, (unsigned int) i); + } + fprintf(fp, " %02x", (unsigned int)wire[i]); + } + fprintf(fp, "\n"); + fclose(fp); +} diff --git a/duration.c b/duration.c new file mode 100644 index 00000000000..6d0a388c5e6 --- /dev/null +++ b/duration.c @@ -0,0 +1,354 @@ +/* + * $Id: duration.c 4518 2011-02-24 15:39:09Z matthijs $ + * + * Copyright (c) 2009 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: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * + * This file is copied from the OpenDNSSEC source repository + * and only slightly adapted to make it fit. + */ + +/** + * + * Durations. + */ + +#include +#include + +#include +#include +#include +#include + + +/** + * Create a new 'instant' duration. + * + */ +ldns_duration_type* +ldns_duration_create(void) +{ + ldns_duration_type* duration; + + duration = malloc(sizeof(ldns_duration_type)); + if (!duration) { + return NULL; + } + duration->years = 0; + duration->months = 0; + duration->weeks = 0; + duration->days = 0; + duration->hours = 0; + duration->minutes = 0; + duration->seconds = 0; + return duration; +} + + +/** + * Compare durations. + * + */ +int +ldns_duration_compare(ldns_duration_type* d1, ldns_duration_type* d2) +{ + if (!d1 && !d2) { + return 0; + } + if (!d1 || !d2) { + return d1?-1:1; + } + + if (d1->years != d2->years) { + return (int) (d1->years - d2->years); + } + if (d1->months != d2->months) { + return (int) (d1->months - d2->months); + } + if (d1->weeks != d2->weeks) { + return (int) (d1->weeks - d2->weeks); + } + if (d1->days != d2->days) { + return (int) (d1->days - d2->days); + } + if (d1->hours != d2->hours) { + return (int) (d1->hours - d2->hours); + } + if (d1->minutes != d2->minutes) { + return (int) (d1->minutes - d2->minutes); + } + if (d1->seconds != d2->seconds) { + return (int) (d1->seconds - d2->seconds); + } + + return 0; +} + + +/** + * Create a duration from string. + * + */ +ldns_duration_type* +ldns_duration_create_from_string(const char* str) +{ + ldns_duration_type* duration = ldns_duration_create(); + char* P, *X, *T, *W; + int not_weeks = 0; + + if (!duration) { + return NULL; + } + if (!str) { + return duration; + } + + P = strchr(str, 'P'); + if (!P) { + ldns_duration_cleanup(duration); + return NULL; + } + + T = strchr(str, 'T'); + X = strchr(str, 'Y'); + if (X) { + duration->years = (time_t) atoi(str+1); + str = X; + not_weeks = 1; + } + X = strchr(str, 'M'); + if (X && (!T || (size_t) (X-P) < (size_t) (T-P))) { + duration->months = (time_t) atoi(str+1); + str = X; + not_weeks = 1; + } + X = strchr(str, 'D'); + if (X) { + duration->days = (time_t) atoi(str+1); + str = X; + not_weeks = 1; + } + if (T) { + str = T; + not_weeks = 1; + } + X = strchr(str, 'H'); + if (X && T) { + duration->hours = (time_t) atoi(str+1); + str = X; + not_weeks = 1; + } + X = strrchr(str, 'M'); + if (X && T && (size_t) (X-P) > (size_t) (T-P)) { + duration->minutes = (time_t) atoi(str+1); + str = X; + not_weeks = 1; + } + X = strchr(str, 'S'); + if (X && T) { + duration->seconds = (time_t) atoi(str+1); + str = X; + not_weeks = 1; + } + + W = strchr(str, 'W'); + if (W) { + if (not_weeks) { + ldns_duration_cleanup(duration); + return NULL; + } else { + duration->weeks = (time_t) atoi(str+1); + str = W; + } + } + return duration; +} + + +/** + * Get the number of digits in a number. + * + */ +static size_t +digits_in_number(time_t duration) +{ + uint32_t period = (uint32_t) duration; + size_t count = 0; + + while (period > 0) { + count++; + period /= 10; + } + return count; +} + + +/** + * Convert a duration to a string. + * + */ +char* +ldns_duration2string(ldns_duration_type* duration) +{ + char* str = NULL, *num = NULL; + size_t count = 2; + int T = 0; + + if (!duration) { + return NULL; + } + + if (duration->years > 0) { + count = count + 1 + digits_in_number(duration->years); + } + if (duration->months > 0) { + count = count + 1 + digits_in_number(duration->months); + } + if (duration->weeks > 0) { + count = count + 1 + digits_in_number(duration->weeks); + } + if (duration->days > 0) { + count = count + 1 + digits_in_number(duration->days); + } + if (duration->hours > 0) { + count = count + 1 + digits_in_number(duration->hours); + T = 1; + } + if (duration->minutes > 0) { + count = count + 1 + digits_in_number(duration->minutes); + T = 1; + } + if (duration->seconds > 0) { + count = count + 1 + digits_in_number(duration->seconds); + T = 1; + } + if (T) { + count++; + } + + str = (char*) calloc(count, sizeof(char)); + str[0] = 'P'; + str[1] = '\0'; + + if (duration->years > 0) { + count = digits_in_number(duration->years); + num = (char*) calloc(count+2, sizeof(char)); + snprintf(num, count+2, "%uY", (unsigned int) duration->years); + str = strncat(str, num, count+2); + free((void*) num); + } + if (duration->months > 0) { + count = digits_in_number(duration->months); + num = (char*) calloc(count+2, sizeof(char)); + snprintf(num, count+2, "%uM", (unsigned int) duration->months); + str = strncat(str, num, count+2); + free((void*) num); + } + if (duration->weeks > 0) { + count = digits_in_number(duration->weeks); + num = (char*) calloc(count+2, sizeof(char)); + snprintf(num, count+2, "%uW", (unsigned int) duration->weeks); + str = strncat(str, num, count+2); + free((void*) num); + } + if (duration->days > 0) { + count = digits_in_number(duration->days); + num = (char*) calloc(count+2, sizeof(char)); + snprintf(num, count+2, "%uD", (unsigned int) duration->days); + str = strncat(str, num, count+2); + free((void*) num); + } + if (T) { + str = strncat(str, "T", 1); + } + if (duration->hours > 0) { + count = digits_in_number(duration->hours); + num = (char*) calloc(count+2, sizeof(char)); + snprintf(num, count+2, "%uH", (unsigned int) duration->hours); + str = strncat(str, num, count+2); + free((void*) num); + } + if (duration->minutes > 0) { + count = digits_in_number(duration->minutes); + num = (char*) calloc(count+2, sizeof(char)); + snprintf(num, count+2, "%uM", (unsigned int) duration->minutes); + str = strncat(str, num, count+2); + free((void*) num); + } + if (duration->seconds > 0) { + count = digits_in_number(duration->seconds); + num = (char*) calloc(count+2, sizeof(char)); + snprintf(num, count+2, "%uS", (unsigned int) duration->seconds); + str = strncat(str, num, count+2); + free((void*) num); + } + return str; +} + + +/** + * Convert a duration to a time. + * + */ +time_t +ldns_duration2time(ldns_duration_type* duration) +{ + time_t period = 0; + + if (duration) { + period += (duration->seconds); + period += (duration->minutes)*60; + period += (duration->hours)*3600; + period += (duration->days)*86400; + period += (duration->weeks)*86400*7; + period += (duration->months)*86400*31; + period += (duration->years)*86400*365; + + /* [TODO] calculate correct number of days in this month/year */ + /* + if (duration->months || duration->years) { + } + */ + } + return period; +} + + +/** + * Clean up duration. + * + */ +void +ldns_duration_cleanup(ldns_duration_type* duration) +{ + if (!duration) { + return; + } + free(duration); + return; +} diff --git a/error.c b/error.c new file mode 100644 index 00000000000..cf6788ffb36 --- /dev/null +++ b/error.c @@ -0,0 +1,112 @@ +/* + * a error2str function to make sense of all the + * error codes we have laying ardoun + * + * a Net::DNS like library for C + * LibDNS Team @ NLnet Labs + * (c) NLnet Labs, 2005-2006 + * See the file LICENSE for the license + */ + +#include + +#include + +ldns_lookup_table ldns_error_str[] = { + { LDNS_STATUS_OK, "All OK" }, + { LDNS_STATUS_EMPTY_LABEL, "Empty label" }, + { LDNS_STATUS_LABEL_OVERFLOW, "Label length overflow" }, + { LDNS_STATUS_DOMAINNAME_OVERFLOW, "Domainname length overflow" }, + { LDNS_STATUS_DOMAINNAME_UNDERFLOW, "Domainname length underflow (zero length)" }, + { LDNS_STATUS_DDD_OVERFLOW, "\\DDD sequence overflow (>255)" }, + { LDNS_STATUS_PACKET_OVERFLOW, "Packet size overflow" }, + { LDNS_STATUS_INVALID_POINTER, "Invalid compression pointer" }, + { LDNS_STATUS_MEM_ERR, "General memory error" }, + { LDNS_STATUS_INTERNAL_ERR, "Internal error, this should not happen" }, + { LDNS_STATUS_SSL_ERR, "Error in SSL library" }, + { LDNS_STATUS_ERR, "General LDNS error" }, + { LDNS_STATUS_INVALID_INT, "Conversion error, integer expected" }, + { LDNS_STATUS_INVALID_IP4, "Conversion error, ip4 addr expected" }, + { LDNS_STATUS_INVALID_IP6, "Conversion error, ip6 addr expected" }, + { LDNS_STATUS_INVALID_STR, "Conversion error, string expected" }, + { LDNS_STATUS_INVALID_B32_EXT, "Conversion error, b32 ext encoding expected" }, + { LDNS_STATUS_INVALID_B64, "Conversion error, b64 encoding expected" }, + { LDNS_STATUS_INVALID_HEX, "Conversion error, hex encoding expected" }, + { LDNS_STATUS_INVALID_TIME, "Conversion error, time encoding expected" }, + { LDNS_STATUS_NETWORK_ERR, "Could not send or receive, because of network error" }, + { LDNS_STATUS_ADDRESS_ERR, "Could not start AXFR, because of address error" }, + { LDNS_STATUS_FILE_ERR, "Could not open the files" }, + { LDNS_STATUS_UNKNOWN_INET, "Uknown address family" }, + { LDNS_STATUS_NOT_IMPL, "This function is not implemented (yet), please notify the developers - or not..." }, + { LDNS_STATUS_NULL, "Supplied value pointer null" }, + { LDNS_STATUS_CRYPTO_UNKNOWN_ALGO, "Unknown cryptographic algorithm" }, + { LDNS_STATUS_CRYPTO_ALGO_NOT_IMPL, "Cryptographic algorithm not implemented" }, + { LDNS_STATUS_CRYPTO_NO_RRSIG, "No DNSSEC signature(s)" }, + { LDNS_STATUS_CRYPTO_NO_DNSKEY, "No DNSSEC public key(s)" }, + { LDNS_STATUS_CRYPTO_TYPE_COVERED_ERR, "The signature does not cover this RRset" }, + { LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY, "No signatures found for trusted DNSSEC public key(s)" }, + { LDNS_STATUS_CRYPTO_NO_DS, "No DS record(s)" }, + { LDNS_STATUS_CRYPTO_NO_TRUSTED_DS, "Could not validate DS record(s)" }, + { LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY, "No keys with the keytag and algorithm from the RRSIG found" }, + { LDNS_STATUS_CRYPTO_VALIDATED, "Valid DNSSEC signature" }, + { LDNS_STATUS_CRYPTO_BOGUS, "Bogus DNSSEC signature" }, + { LDNS_STATUS_CRYPTO_SIG_EXPIRED, "DNSSEC signature has expired" }, + { LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED, "DNSSEC signature not incepted yet" }, + { LDNS_STATUS_CRYPTO_TSIG_BOGUS, "Bogus TSIG signature" }, + { LDNS_STATUS_CRYPTO_TSIG_ERR, "Could not create TSIG signature" }, + { LDNS_STATUS_CRYPTO_EXPIRATION_BEFORE_INCEPTION, "DNSSEC signature has expiration date earlier than inception date" }, + { LDNS_STATUS_ENGINE_KEY_NOT_LOADED, "Unable to load private key from engine" }, + { LDNS_STATUS_NSEC3_ERR, "Error in NSEC3 denial of existence proof" }, + { LDNS_STATUS_RES_NO_NS, "No (valid) nameservers defined in the resolver" }, + { LDNS_STATUS_RES_QUERY, "No correct query given to resolver" }, + { LDNS_STATUS_WIRE_INCOMPLETE_HEADER, "header section incomplete" }, + { LDNS_STATUS_WIRE_INCOMPLETE_QUESTION, "question section incomplete" }, + { LDNS_STATUS_WIRE_INCOMPLETE_ANSWER, "answer section incomplete" }, + { LDNS_STATUS_WIRE_INCOMPLETE_AUTHORITY, "authority section incomplete" }, + { LDNS_STATUS_WIRE_INCOMPLETE_ADDITIONAL, "additional section incomplete" }, + { LDNS_STATUS_NO_DATA, "No data" }, + { LDNS_STATUS_CERT_BAD_ALGORITHM, "Bad algorithm type for CERT record" }, + { LDNS_STATUS_SYNTAX_TYPE_ERR, "Syntax error, could not parse the RR's type" }, + { LDNS_STATUS_SYNTAX_CLASS_ERR, "Syntax error, could not parse the RR's class" }, + { LDNS_STATUS_SYNTAX_TTL_ERR, "Syntax error, could not parse the RR's TTL" }, + { LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL, "Syntax error, $INCLUDE not implemented" }, + { LDNS_STATUS_SYNTAX_RDATA_ERR, "Syntax error, could not parse the RR's rdata" }, + { LDNS_STATUS_SYNTAX_DNAME_ERR, "Syntax error, could not parse the RR's dname(s)" }, + { LDNS_STATUS_SYNTAX_VERSION_ERR, "Syntax error, version mismatch" }, + { LDNS_STATUS_SYNTAX_ALG_ERR, "Syntax error, algorithm unknown or non parseable" }, + { LDNS_STATUS_SYNTAX_KEYWORD_ERR, "Syntax error, unknown keyword in input" }, + { LDNS_STATUS_SYNTAX_ERR, "Syntax error, could not parse the RR" }, + { LDNS_STATUS_SYNTAX_EMPTY, "Empty line was returned" }, + { LDNS_STATUS_SYNTAX_TTL, "$TTL directive was seen in the zone" }, + { LDNS_STATUS_SYNTAX_ORIGIN, "$ORIGIN directive was seen in the zone" }, + { LDNS_STATUS_SYNTAX_INCLUDE, "$INCLUDE directive was seen in the zone" }, + { LDNS_STATUS_SYNTAX_ITERATIONS_OVERFLOW, "Iterations count for NSEC3 record higher than maximum" }, + { LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR, "Syntax error, value expected" }, + { LDNS_STATUS_SYNTAX_INTEGER_OVERFLOW, "Syntax error, integer value too large" }, + { LDNS_STATUS_SYNTAX_BAD_ESCAPE, "Syntax error, bad escape sequence" }, + { LDNS_STATUS_SOCKET_ERROR, "Error creating socket" }, + { LDNS_STATUS_DNSSEC_EXISTENCE_DENIED, "Existence denied by NSEC" }, + { LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED, "RR not covered by the given NSEC RRs" }, + { LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED, "wildcard not covered by the given NSEC RRs" }, + { LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND, "original of NSEC3 hashed name could not be found" }, + { LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG, "The RRSIG has to few rdata fields" }, + { LDNS_STATUS_MISSING_RDATA_FIELDS_KEY, "The DNSKEY has to few rdata fields" }, + { LDNS_STATUS_CRYPTO_SIG_EXPIRED_WITHIN_MARGIN, + "DNSSEC signature will expire too soon" }, + { LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED_WITHIN_MARGIN, + "DNSSEC signature not incepted long enough" }, + { 0, NULL } +}; + +const char * +ldns_get_errorstr_by_id(ldns_status err) +{ + ldns_lookup_table *lt; + + lt = ldns_lookup_by_id(ldns_error_str, err); + + if (lt) { + return lt->name; + } + return NULL; +} diff --git a/examples/Makefile.in b/examples/Makefile.in new file mode 100644 index 00000000000..5344ee6739c --- /dev/null +++ b/examples/Makefile.in @@ -0,0 +1,182 @@ +# Standard installation pathnames +# See the file LICENSE for the license +SHELL = @SHELL@ +VERSION = @PACKAGE_VERSION@ +basesrcdir = $(shell basename `pwd`) +srcdir = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +mandir = @mandir@ +libtool = @libtool@ + +CC = @CC@ +CFLAGS = -I. -I${srcdir} @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBNSL_LIBS = @LIBNSL_LIBS@ +LIBSSL_CPPFLAGS = @LIBSSL_CPPFLAGS@ +LIBSSL_LDFLAGS = @LIBSSL_LDFLAGS@ +LIBSSL_LIBS = @LIBSSL_LIBS@ +LIBS = @LIBS@ +RUNTIME_PATH = @RUNTIME_PATH@ +LDNSDIR = @LDNSDIR@ + +INSTALL = $(srcdir)/../install-sh + +COMPILE = $(CC) $(CPPFLAGS) $(LIBSSL_CPPFLAGS) $(CFLAGS) +LINK = $(libtool) --tag=CC --quiet --mode=link $(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) $(RUNTIME_PATH) +LINK_STATIC = $(libtool) --tag=CC --quiet --mode=link $(CC) $(CFLAGS) -static $(LDFLAGS) $(LIBS) $(RUNTIME_PATH) + +LINT = splint +LINTFLAGS=+quiet -weak -warnposix -unrecog -Din_addr_t=uint32_t -Du_int=unsigned -Du_char=uint8_t -preproc -Drlimit=rlimit64 -D__gnuc_va_list=va_list +#-Dglob64=glob -Dglobfree64=globfree +# compat with openssl linux edition. +LINTFLAGS+="-DBN_ULONG=unsigned long" -Dkrb5_int32=int "-Dkrb5_ui_4=unsigned int" -DPQ_64BIT=uint64_t -DRC4_INT=unsigned -fixedformalarray -D"ENGINE=unsigned" -D"RSA=unsigned" -D"DSA=unsigned" -D"EVP_PKEY=unsigned" -D"EVP_MD=unsigned" -D"SSL=unsigned" -D"SSL_CTX=unsigned" -D"X509=unsigned" -D"RC4_KEY=unsigned" -D"EVP_MD_CTX=unsigned" +# compat with NetBSD +ifeq "$(shell uname)" "NetBSD" +LINTFLAGS+="-D__RENAME(x)=" -D_NETINET_IN_H_ +endif +# compat with OpenBSD +LINTFLAGS+="-Dsigset_t=long" +# FreeBSD8 +LINTFLAGS+="-D__uint16_t=uint16_t" +LINTFLAGS+=-D__signed__=signed "-D__packed=" "-D__aligned(x)=" +# Ubuntu 11.04 +LINTFLAGS+="-D__u16=struct __u16" "-D__u32=struct __u32" "-D__u64=struct __u64" + +HEADER = config.h +MAIN_SOURCES = ldns-read-zone.c \ + ldns-mx.c \ + ldns-chaos.c \ + ldns-update.c \ + ldns-keygen.c \ + ldns-key2ds.c \ + ldns-version.c \ + ldns-rrsig.c \ + ldns-walk.c \ + ldns-zsplit.c \ + ldns-zcat.c \ + ldns-dpa.c \ + ldns-resolver.c \ + ldns-test-edns.c \ + ldns-keyfetcher.c \ + ldns-notify.c \ + ldns-testns.c \ + ldns-compare-zones.c \ + ldns-gen-zone.c \ + ldnsd.c + +MAIN_SSL_SOURCES = ldns-signzone.c \ + ldns-verify-zone.c \ + ldns-revoke.c \ + ldns-nsec3-hash.c + +OTHER_SOURCES = ldns-testpkts.c + +PROGRAMS=$(MAIN_SOURCES:.c=) +SSL_PROGRAMS=$(MAIN_SSL_SOURCES:.c=) + +.PHONY: all clean realclean all-static +.SECONDARY: $(MAIN_SOURCES:.c=.o) $(OTHER_SOURCES:.c=.o) $(MAIN_SSL_SOURCES:.c=.o) + +all: $(addsuffix .prg,$(PROGRAMS)) $(addsuffix .prg-ssl,$(SSL_PROGRAMS)) + +all-static: $(addsuffix .stc,$(PROGRAMS)) $(addsuffix .stc-ssl,$(SSL_PROGRAMS)) + +%.o: $(srcdir)/%.c + $(COMPILE) -o $@ -c $< + +# ldns-testns uses more sources. +ldns-testns.o: $(srcdir)/ldns-testns.c $(srcdir)/ldns-testpkts.c $(srcdir)/ldns-testpkts.h +ldns-testns.prg: ldns-testpkts.o +ldns-testns.stc: ldns-testpkts.o + +ldnsd.prg: ldnsd.o + @if test ! -f $(@:.prg=) -o $< -nt $(@:.prg=); then \ + echo $(LINK) $(LIBNSL_LIBS) -o $(@:.prg=) $^ ; \ + $(LINK) $(LIBNSL_LIBS) -o $(@:.prg=) $^ ; \ + fi + +ldnsd.stc: ldnsd.o + @if test ! -f $@ -o $< -nt $@; then \ + echo $(LINK_STATIC) $(LIBNSL_LDFLAGS) -o $@ $^ ; \ + $(LINK_STATIC) $(LIBNSL_LDFLAGS) -o $@ $^ ; \ + fi + +%.prg-ssl: %.o + @if test ! -f $(@:.prg-ssl=) -o $< -nt $(@:.prg-ssl=); then \ + echo $(LINK) $(LIBNSL_LIBS) $(LIBSSL_LDFLAGS) $(LIBSSL_LIBS) -o $(@:.prg-ssl=) $^ ; \ + $(LINK) $(LIBNSL_LIBS) $(LIBSSL_LDFLAGS) $(LIBSSL_LIBS) -o $(@:.prg-ssl=) $^ ; \ + fi + +%.stc-ssl: %.o + @if test ! -f $@ -o $< -nt $@; then \ + echo $(LINK_STATIC) $(LIBNSL_LIBS) $(LIBSSL_LDFLAGS) $(LIBSSL_LIBS) -o $@ $^ ; \ + $(LINK_STATIC) $(LIBNSL_LIBS) $(LIBSSL_LDFLAGS) $(LIBSSL_LIBS) -o $@ $^ ; \ + fi + +%.prg: %.o + @if test ! -f $(@:.prg=) -o $< -nt $(@:.prg=); then \ + echo $(LINK) -o $(@:.prg=) $^ ; \ + $(LINK) -o $(@:.prg=) $^ ; \ + fi + +%.stc: %.o + @if test ! -f $@ -o $< -nt $@; then \ + echo $(LINK_STATIC) -o $@ $^ ; \ + $(LINK_STATIC) -o $@ $^ ; \ + fi + +lint: + for i in $(MAIN_SOURCES) $(OTHER_SOURCES); do \ + $(LINT) $(LINTFLAGS) -I. -I$(srcdir) $(srcdir)/$$i $(CPPFLAGS); \ + if [ $$? -ne 0 ] ; then exit 1 ; fi ; \ + done + +clean: + rm -f *.o *.lo + rm -rf .libs + rm -f $(PROGRAMS) $(SSL_PROGRAMS) + rm -f $(addsuffix .stc,$(PROGRAMS)) $(addsuffix .stc-ssl,$(SSL_PROGRAMS)) + +realclean: clean + rm -rf autom4te.cache/ + rm -f config.log config.status aclocal.m4 config.h.in configure Makefile + rm -f config.h + +confclean: clean + rm -rf config.log config.status config.h Makefile + +install: $(PROGRAMS) $(SSL_PROGRAMS) + $(INSTALL) -d -m 755 $(DESTDIR)$(bindir) + $(INSTALL) -d -m 755 $(DESTDIR)$(mandir) + $(INSTALL) -d -m 755 $(DESTDIR)$(mandir)/man1 + for i in $(PROGRAMS) $(SSL_PROGRAMS); do \ + $(libtool) --tag=CC --mode=install ${INSTALL} -c $$i $(DESTDIR)$(bindir) ; \ + $(INSTALL) -c -m 644 $(srcdir)/$$i.1 $(DESTDIR)$(mandir)/man1/$$i.1 ; \ + done + exit 0 + +install-static: all-static + $(INSTALL) -d -m 755 $(DESTDIR)$(bindir) + $(INSTALL) -d -m 755 $(DESTDIR)$(mandir) + $(INSTALL) -d -m 755 $(DESTDIR)$(mandir)/man1 + for i in $(PROGRAMS); do \ + $(libtool) --tag=CC --mode=install ${INSTALL} -c $$i.stc $(DESTDIR)$(bindir) ; \ + $(INSTALL) -c -m 644 $(srcdir)/$$i.1 $(DESTDIR)$(mandir)/man1/$$i.1 ; \ + done + for i in $(SSL_PROGRAMS); do \ + $(libtool) --tag=CC --mode=install ${INSTALL} -c $$i.stc-ssl $(DESTDIR)$(bindir) ; \ + $(INSTALL) -c -m 644 $(srcdir)/$$i.1 $(DESTDIR)$(mandir)/man1/$$i.1 ; \ + done + exit 0 + +uninstall: + for i in $(PROGRAMS) $(SSL_PROGRAMS); do \ + rm -f $(DESTDIR)$(bindir)/$$i ; \ + rm -f $(DESTDIR)$(mandir)/man1/$$i.1 ; \ + done + exit 0 + rmdir -p $(DESTDIR)$(bindir) + rmdir -p $(DESTDIR)$(mandir) diff --git a/examples/README b/examples/README new file mode 100644 index 00000000000..f84fe9d8cf7 --- /dev/null +++ b/examples/README @@ -0,0 +1,5 @@ +These tools are examples of ldns usage. They are not meant for production +systems and will not be supported as such. + +Compilation: +autoreconf && ./configure && make diff --git a/examples/config.h.in b/examples/config.h.in new file mode 100644 index 00000000000..dad78b17a22 --- /dev/null +++ b/examples/config.h.in @@ -0,0 +1,363 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the header file. */ +#undef HAVE_ARPA_INET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ASSERT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_CTYPE_H + +/* Define to 1 if you have the declaration of `in6addr_any', and to 0 if you + don't. */ +#undef HAVE_DECL_IN6ADDR_ANY + +/* Define to 1 if you have the `fork' function. */ +#undef HAVE_FORK + +/* Whether getaddrinfo is available */ +#undef HAVE_GETADDRINFO + +/* Define to 1 if you have the header file. */ +#undef HAVE_GETOPT_H + +/* If you have HMAC_CTX_init */ +#undef HAVE_HMAC_CTX_INIT + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `isblank' function. */ +#undef HAVE_ISBLANK + +/* Define to 1 if you have the `ldns' library (-lldns). */ +#undef HAVE_LIBLDNS + +/* Define to 1 if you have the `pcap' library (-lpcap). */ +#undef HAVE_LIBPCAP + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETDB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IF_ETHER_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IGMP_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IN_SYSTM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IP6_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IP_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_UDP_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NET_IF_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_ERR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_RAND_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_SSL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_PCAP_H + +/* Define to 1 if you have the `random' function. */ +#undef HAVE_RANDOM + +/* Define to 1 if you have the `sleep' function. */ +#undef HAVE_SLEEP + +/* Define to 1 if you have the `srandom' function. */ +#undef HAVE_SRANDOM + +/* Define if you have the SSL libraries installed. */ +#undef HAVE_SSL + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDIO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_MOUNT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SELECT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SOCKET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the `vfork' function. */ +#undef HAVE_VFORK + +/* Define to 1 if you have the header file. */ +#undef HAVE_VFORK_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_WINSOCK2_H + +/* Define to 1 if `fork' works. */ +#undef HAVE_WORKING_FORK + +/* Define to 1 if `vfork' works. */ +#undef HAVE_WORKING_VFORK + +/* Define to 1 if you have the header file. */ +#undef HAVE_WS2TCPIP_H + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define this to enable ECDSA support. */ +#undef USE_ECDSA + +/* Define this to enable GOST support. */ +#undef USE_GOST + +/* Define this to enable SHA256 and SHA512 support. */ +#undef USE_SHA2 + +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# undef _ALL_SOURCE +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# undef _GNU_SOURCE +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# undef _POSIX_PTHREAD_SEMANTICS +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# undef _TANDEM_SOURCE +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# undef __EXTENSIONS__ +#endif + + +/* the version of the windows API enabled */ +#undef WINVER + +/* Define to 1 if on MINIX. */ +#undef _MINIX + +/* Define to 2 if the system does not provide POSIX.1 features except with + this defined. */ +#undef _POSIX_1_SOURCE + +/* Define to 1 if you need to in order for `stat' and other things to work. */ +#undef _POSIX_SOURCE + +/* in_addr_t */ +#undef in_addr_t + +/* in_port_t */ +#undef in_port_t + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +#undef inline +#endif + +/* Define to `short' if does not define. */ +#undef int16_t + +/* Define to `int' if does not define. */ +#undef int32_t + +/* Define to `long long' if does not define. */ +#undef int64_t + +/* Define to `char' if does not define. */ +#undef int8_t + +/* Define to `int' if does not define. */ +#undef pid_t + +/* Define to `unsigned int' if does not define. */ +#undef size_t + +/* Define to 'int' if not defined */ +#undef socklen_t + +/* Define to `int' if does not define. */ +#undef ssize_t + +/* Define to `unsigned short' if does not define. */ +#undef uint16_t + +/* Define to `unsigned int' if does not define. */ +#undef uint32_t + +/* Define to `unsigned long long' if does not define. */ +#undef uint64_t + +/* Define to `unsigned char' if does not define. */ +#undef uint8_t + +/* Define as `fork' if `vfork' does not work. */ +#undef vfork + + + +#include +#include +#include +#include + +#if STDC_HEADERS +#include +#include +#endif + +#ifdef HAVE_STDINT_H +#include +#endif + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#ifdef HAVE_NETINET_UDP_H +#include +#endif + +#ifdef HAVE_TIME_H +#include +#endif + +#ifdef HAVE_PCAP_H +#include +#endif + +#ifdef HAVE_NETINET_IN_SYSTM_H +#include +#endif + +#ifdef HAVE_NETINET_IP_H +#include +#endif + +#ifdef HAVE_NET_IF_H +#include +#endif + +#ifdef HAVE_NETINET_IF_ETHER_H +#include +#endif + +#ifdef HAVE_WINSOCK2_H +#define USE_WINSOCK 1 +#include +#endif + +#ifdef HAVE_WS2TCPIP_H +#include +#endif + +#ifndef HAVE_GETADDRINFO +#include +#endif + +#ifndef HAVE_RANDOM +/* random can be replaced by rand for ldnsexamples */ +#define random rand +#endif + +#ifndef HAVE_SRANDOM +/* srandom can be replaced by srand for ldnsexamples */ +#define srandom srand +#endif + +extern char *optarg; +extern int optind, opterr; + +#ifndef EXIT_FAILURE +#define EXIT_FAILURE 1 +#endif +#ifndef EXIT_SUCCESS +#define EXIT_SUCCESS 0 +#endif + +#ifdef S_SPLINT_S +#define FD_ZERO(a) /* a */ +#define FD_SET(a,b) /* a, b */ +#endif + diff --git a/examples/configure b/examples/configure new file mode 100755 index 00000000000..46dc9988c1f --- /dev/null +++ b/examples/configure @@ -0,0 +1,7158 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.68 for ldns 1.6.13. +# +# Report bugs to . +# +# +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software +# Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + # We cannot yet assume a decent shell, so we have to provide a + # neutralization value for shells without unset; and this also + # works around shells that cannot unset nonexistent variables. + # Preserve -v and -x to the replacement shell. + BASH_ENV=/dev/null + ENV=/dev/null + (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV + export CONFIG_SHELL + case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; + esac + exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"} +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org and +$0: libdns@nlnetlabs.nl about your system, including any +$0: error possibly output before this message. Then install +$0: a modern shell, or manually run the script under such a +$0: shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='ldns' +PACKAGE_TARNAME='libdns' +PACKAGE_VERSION='1.6.13' +PACKAGE_STRING='ldns 1.6.13' +PACKAGE_BUGREPORT='libdns@nlnetlabs.nl' +PACKAGE_URL='' + +ac_unique_file="ldns-read-zone.c" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='LTLIBOBJS +LIBOBJS +LDNSDIR +LIBSSL_LIBS +LIBSSL_LDFLAGS +LIBSSL_CPPFLAGS +RUNTIME_PATH +HAVE_SSL +LIBNSL_LIBS +libtool +SET_MAKE +EGREP +GREP +CPP +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_rpath +with_ssl +enable_sha2 +enable_gost +enable_ecdsa +with_ldns +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used" >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +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 ldns 1.6.13 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/libdns] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of ldns 1.6.13:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --disable-rpath Disable hardcoded rpath (default=enabled) + --disable-sha2 Disable SHA256 and SHA512 RRSIG support + --disable-gost Disable GOST support + --enable-ecdsa Enable ECDSA support, experimental + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-ssl=pathname enable SSL (will check /usr/local/ssl /usr/lib/ssl + /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw + /usr) + --with-ldns=PATH specify prefix of path of ldns library to use + + + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CPP C preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to . +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +ldns configure 1.6.13 +generated by GNU Autoconf 2.68 + +Copyright (C) 2010 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} +( $as_echo "## ---------------------------------- ## +## Report this to libdns@nlnetlabs.nl ## +## ---------------------------------- ##" + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_check_type LINENO TYPE VAR INCLUDES +# ------------------------------------------- +# Tests whether TYPE exists after having included INCLUDES, setting cache +# variable VAR accordingly. +ac_fn_c_check_type () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof ($2)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof (($2))) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + eval "$3=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_type + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* 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 $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func + +# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES +# --------------------------------------------- +# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR +# accordingly. +ac_fn_c_check_decl () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + as_decl_name=`echo $2|sed 's/ *(.*//'` + as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 +$as_echo_n "checking whether $as_decl_name is declared... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +#ifndef $as_decl_name +#ifdef __cplusplus + (void) $as_decl_use; +#else + (void) $as_decl_name; +#endif +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_decl +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 ldns $as_me 1.6.13, which was +generated by GNU Autoconf 2.68. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +# acx_nlnetlabs.m4 - common macros for configure checks +# Copyright 2009, Wouter Wijngaards, NLnet Labs. +# BSD licensed. +# +# Version 21 +# 2012-02-09 Fix AHX_MEMCMP_BROKEN with undef in compat/memcmp.h. +# 2012-01-20 Fix COMPILER_FLAGS_UNBOUND for gcc 4.6.2 assigned-not-used-warns. +# 2011-12-05 Fix getaddrinfowithincludes on windows with fedora16 mingw32-gcc. +# Fix ACX_MALLOC for redefined malloc error. +# Fix GETADDRINFO_WITH_INCLUDES to add -lws2_32 +# 2011-11-10 Fix FLTO test to not drop a.out in current directory. +# 2011-11-01 Fix FLTO test for llvm on Lion. +# 2011-08-01 Fix nonblock test (broken at v13). +# 2011-08-01 Fix autoconf 2.68 warnings +# 2011-06-23 Add ACX_CHECK_FLTO to check -flto. +# 2010-08-16 Fix FLAG_OMITTED for AS_TR_CPP changes in autoconf-2.66. +# 2010-07-02 Add check for ss_family (for minix). +# 2010-04-26 Fix to use CPPFLAGS for CHECK_COMPILER_FLAGS. +# 2010-03-01 Fix RPATH using CONFIG_COMMANDS to run at the very end. +# 2010-02-18 WITH_SSL outputs the LIBSSL_LDFLAGS, LIBS, CPPFLAGS seperate, -ldl +# 2010-02-01 added ACX_CHECK_MEMCMP_SIGNED, AHX_MEMCMP_BROKEN +# 2010-01-20 added AHX_COONFIG_STRLCAT +# 2009-07-14 U_CHAR detection improved for windows crosscompile. +# added ACX_FUNC_MALLOC +# fixup some #if to #ifdef +# NONBLOCKING test for mingw crosscompile. +# 2009-07-13 added ACX_WITH_SSL_OPTIONAL +# 2009-07-03 fixup LDFLAGS for empty ssl dir. +# +# Automates some of the checking constructs. Aims at portability for POSIX. +# Documentation for functions is below. +# +# the following macro's are provided in this file: +# (see below for details on each macro). +# +# ACX_ESCAPE_BACKSLASH - escape backslashes in var for C-preproc. +# ACX_RSRC_VERSION - create windows resource version number. +# ACX_CHECK_COMPILER_FLAG - see if cc supports a flag. +# ACX_CHECK_ERROR_FLAGS - see which flag is -werror (used below). +# ACX_CHECK_COMPILER_FLAG_NEEDED - see if flags make the code compile cleanly. +# ACX_DEPFLAG - find cc dependency flags. +# ACX_DETERMINE_EXT_FLAGS_UNBOUND - find out which flags enable BSD and POSIX. +# ACX_CHECK_FORMAT_ATTRIBUTE - find cc printf format syntax. +# ACX_CHECK_UNUSED_ATTRIBUTE - find cc variable unused syntax. +# ACX_CHECK_FLTO - see if cc supports -flto and use it if so. +# ACX_LIBTOOL_C_ONLY - create libtool for C only, improved. +# ACX_TYPE_U_CHAR - u_char type. +# ACX_TYPE_RLIM_T - rlim_t type. +# ACX_TYPE_SOCKLEN_T - socklen_t type. +# ACX_TYPE_IN_ADDR_T - in_addr_t type. +# ACX_TYPE_IN_PORT_T - in_port_t type. +# ACX_ARG_RPATH - add --disable-rpath option. +# ACX_WITH_SSL - add --with-ssl option, link -lcrypto. +# ACX_WITH_SSL_OPTIONAL - add --with-ssl option, link -lcrypto, +# where --without-ssl is also accepted +# ACX_LIB_SSL - setup to link -lssl. +# ACX_SYS_LARGEFILE - improved sys_largefile, fseeko, >2G files. +# ACX_CHECK_GETADDRINFO_WITH_INCLUDES - find getaddrinfo, portably. +# ACX_FUNC_DEPRECATED - see if func is deprecated. +# ACX_CHECK_NONBLOCKING_BROKEN - see if nonblocking sockets really work. +# ACX_MKDIR_ONE_ARG - determine mkdir(2) number of arguments. +# ACX_FUNC_IOCTLSOCKET - find ioctlsocket, portably. +# ACX_FUNC_MALLOC - check malloc, define replacement . +# AHX_CONFIG_FORMAT_ATTRIBUTE - config.h text for format. +# AHX_CONFIG_UNUSED_ATTRIBUTE - config.h text for unused. +# AHX_CONFIG_FSEEKO - define fseeko, ftello fallback. +# AHX_CONFIG_RAND_MAX - define RAND_MAX if needed. +# AHX_CONFIG_MAXHOSTNAMELEN - define MAXHOSTNAMELEN if needed. +# AHX_CONFIG_IPV6_MIN_MTU - define IPV6_MIN_MTU if needed. +# AHX_CONFIG_SNPRINTF - snprintf compat prototype +# AHX_CONFIG_INET_PTON - inet_pton compat prototype +# AHX_CONFIG_INET_NTOP - inet_ntop compat prototype +# AHX_CONFIG_INET_ATON - inet_aton compat prototype +# AHX_CONFIG_MEMMOVE - memmove compat prototype +# AHX_CONFIG_STRLCAT - strlcat compat prototype +# AHX_CONFIG_STRLCPY - strlcpy compat prototype +# AHX_CONFIG_GMTIME_R - gmtime_r compat prototype +# AHX_CONFIG_W32_SLEEP - w32 compat for sleep +# AHX_CONFIG_W32_USLEEP - w32 compat for usleep +# AHX_CONFIG_W32_RANDOM - w32 compat for random +# AHX_CONFIG_W32_SRANDOM - w32 compat for srandom +# AHX_CONFIG_W32_FD_SET_T - w32 detection of FD_SET_T. +# ACX_CFLAGS_STRIP - strip one flag from CFLAGS +# ACX_STRIP_EXT_FLAGS - strip extension flags from CFLAGS +# AHX_CONFIG_FLAG_OMITTED - define omitted flag +# AHX_CONFIG_FLAG_EXT - define omitted extension flag +# AHX_CONFIG_EXT_FLAGS - define the stripped extension flags +# ACX_CHECK_MEMCMP_SIGNED - check if memcmp uses signed characters. +# AHX_MEMCMP_BROKEN - replace memcmp func for CHECK_MEMCMP_SIGNED. +# ACX_CHECK_SS_FAMILY - check for sockaddr_storage.ss_family +# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +OURCPPFLAGS='' +CPPFLAGS=${CPPFLAGS:-${OURCPPFLAGS}} +OURCFLAGS='-g' +CFLAGS=${CFLAGS:-${OURCFLAGS}} + +$as_echo "#define WINVER 0x0502" >>confdefs.h + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + 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 eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default" +if test "x$ac_cv_header_minix_config_h" = xyes; then : + MINIX=yes +else + MINIX= +fi + + + if test "$MINIX" = yes; then + +$as_echo "#define _POSIX_SOURCE 1" >>confdefs.h + + +$as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h + + +$as_echo "#define _MINIX 1" >>confdefs.h + + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5 +$as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; } +if ${ac_cv_safe_to_define___extensions__+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +# define __EXTENSIONS__ 1 + $ac_includes_default +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_safe_to_define___extensions__=yes +else + ac_cv_safe_to_define___extensions__=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5 +$as_echo "$ac_cv_safe_to_define___extensions__" >&6; } + test $ac_cv_safe_to_define___extensions__ = yes && + $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h + + $as_echo "#define _ALL_SOURCE 1" >>confdefs.h + + $as_echo "#define _GNU_SOURCE 1" >>confdefs.h + + $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h + + $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h + + + +# Checks for programs. +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +for ac_prog in glibtool libtool15 libtool +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_libtool+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$libtool"; then + ac_cv_prog_libtool="$libtool" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_libtool="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +libtool=$ac_cv_prog_libtool +if test -n "$libtool"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libtool" >&5 +$as_echo "$libtool" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$libtool" && break +done +test -n "$libtool" || libtool="../libtool" + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -std=c99" >&5 +$as_echo_n "checking whether $CC supports -std=c99... " >&6; } +cache=`echo std=c99 | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -std=c99 -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +C99FLAG="-std=c99" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: + +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -xc99" >&5 +$as_echo_n "checking whether $CC supports -xc99... " >&6; } +cache=`echo xc99 | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -xc99 -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +C99FLAG="-xc99" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: + +fi + + +# Check whether --enable-rpath was given. +if test "${enable_rpath+set}" = set; then : + enableval=$enable_rpath; enable_rpath=$enableval +else + enable_rpath=yes +fi + + +if test "x$enable_rpath" = xyes; then + RPATH_VAL="-Wl,-rpath=\${libdir}" +fi + + +ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" +if test "x$ac_cv_type_size_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned int +_ACEOF + +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -O2" >&5 +$as_echo_n "checking whether $CC supports -O2... " >&6; } +cache=`echo O2 | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -O2 -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +CFLAGS="$CFLAGS -O2" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: + +fi + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Werror" >&5 +$as_echo_n "checking whether $CC supports -Werror... " >&6; } +cache=`echo Werror | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -Werror -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +ERRFLAG="-Werror" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: +ERRFLAG="-errwarn" +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wall" >&5 +$as_echo_n "checking whether $CC supports -Wall... " >&6; } +cache=`echo Wall | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -Wall -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +ERRFLAG="$ERRFLAG -Wall" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: +ERRFLAG="$ERRFLAG -errfmt" +fi + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we need $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 as a flag for $CC" >&5 +$as_echo_n "checking whether we need $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 as a flag for $CC... " >&6; } +cache=`$as_echo "$C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600" | $as_tr_sh` +if eval \${cv_prog_cc_flag_needed_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo ' +#include "confdefs.h" +#include +#include +#include +#ifdef HAVE_TIME_H +#include +#endif +#include +#ifdef HAVE_GETOPT_H +#include +#endif + +int test() { + int a; + char **opts = NULL; + struct timeval tv; + char *t; + time_t time = 0; + char *buf = NULL; + t = ctime_r(&time, buf); + tv.tv_usec = 10; + srandom(32); + a = getopt(2, opts, "a"); + a = isascii(32); + return a; +} +' > conftest.c +echo 'void f(){}' >>conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=no" +else + +if test -z "`$CC $CPPFLAGS $CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=yes" +else +eval "cv_prog_cc_flag_needed_$cache=fail" +#echo 'Test with flag fails too!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 $ERRFLAG -c conftest.c 2>&1` +#exit 1 +fi + +fi +rm -f conftest conftest.c conftest.o + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +CFLAGS="$CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600" +else +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = no"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +#echo 'Test with flag is no!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 $ERRFLAG -c conftest.c 2>&1` +#exit 1 +: + +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +: + +fi +fi + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we need $C99FLAG as a flag for $CC" >&5 +$as_echo_n "checking whether we need $C99FLAG as a flag for $CC... " >&6; } +cache=`$as_echo "$C99FLAG" | $as_tr_sh` +if eval \${cv_prog_cc_flag_needed_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo '#include ' > conftest.c +echo 'void f(){}' >>conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=no" +else + +if test -z "`$CC $CPPFLAGS $CFLAGS $C99FLAG $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=yes" +else +eval "cv_prog_cc_flag_needed_$cache=fail" +#echo 'Test with flag fails too!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS $C99FLAG $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS $C99FLAG $ERRFLAG -c conftest.c 2>&1` +#exit 1 +fi + +fi +rm -f conftest conftest.c conftest.o + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +CFLAGS="$CFLAGS $C99FLAG" +else +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = no"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +#echo 'Test with flag is no!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS $C99FLAG $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS $C99FLAG $ERRFLAG -c conftest.c 2>&1` +#exit 1 +: + +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +: + +fi +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 +$as_echo_n "checking for inline... " >&6; } +if ${ac_cv_c_inline+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __cplusplus +typedef int foo_t; +static $ac_kw foo_t static_foo () {return 0; } +$ac_kw foo_t foo () {return 0; } +#endif + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_inline=$ac_kw +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test "$ac_cv_c_inline" != no && break +done + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 +$as_echo "$ac_cv_c_inline" >&6; } + +case $ac_cv_c_inline in + inline | yes) ;; + *) + case $ac_cv_c_inline in + no) ac_val=;; + *) ac_val=$ac_cv_c_inline;; + esac + cat >>confdefs.h <<_ACEOF +#ifndef __cplusplus +#define inline $ac_val +#endif +_ACEOF + ;; +esac + +ac_fn_c_check_type "$LINENO" "int8_t" "ac_cv_type_int8_t" "$ac_includes_default" +if test "x$ac_cv_type_int8_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define int8_t char +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "int16_t" "ac_cv_type_int16_t" "$ac_includes_default" +if test "x$ac_cv_type_int16_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define int16_t short +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "int32_t" "ac_cv_type_int32_t" "$ac_includes_default" +if test "x$ac_cv_type_int32_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define int32_t int +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "int64_t" "ac_cv_type_int64_t" "$ac_includes_default" +if test "x$ac_cv_type_int64_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define int64_t long long +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "uint8_t" "ac_cv_type_uint8_t" "$ac_includes_default" +if test "x$ac_cv_type_uint8_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define uint8_t unsigned char +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "uint16_t" "ac_cv_type_uint16_t" "$ac_includes_default" +if test "x$ac_cv_type_uint16_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define uint16_t unsigned short +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "uint32_t" "ac_cv_type_uint32_t" "$ac_includes_default" +if test "x$ac_cv_type_uint32_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define uint32_t unsigned int +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "uint64_t" "ac_cv_type_uint64_t" "$ac_includes_default" +if test "x$ac_cv_type_uint64_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define uint64_t unsigned long long +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "ssize_t" "ac_cv_type_ssize_t" "$ac_includes_default" +if test "x$ac_cv_type_ssize_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define ssize_t int +_ACEOF + +fi + + +for ac_header in sys/types.h getopt.h stdlib.h stdio.h assert.h netinet/in.h ctype.h time.h pcap.h arpa/inet.h sys/time.h sys/socket.h sys/select.h netdb.h +do : + 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 eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in winsock2.h ws2tcpip.h +do : + 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 eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in netinet/in_systm.h net/if.h netinet/ip.h netinet/udp.h netinet/igmp.h netinet/if_ether.h netinet/ip6.h +do : + 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 +#ifdef HAVE_NETINET_IN_SYSTM_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + +ac_fn_c_check_type "$LINENO" "socklen_t" "ac_cv_type_socklen_t" " +$ac_includes_default +#ifdef HAVE_SYS_SOCKET_H +# include +#endif +#ifdef HAVE_WS2TCPIP_H +# include +#endif + +" +if test "x$ac_cv_type_socklen_t" = xyes; then : + +else + +$as_echo "#define socklen_t int" >>confdefs.h + +fi + +for ac_header in sys/param.h sys/mount.h +do : + 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 HAVE_SYS_PARAM_H + # include + #endif + + +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +ac_fn_c_check_type "$LINENO" "in_addr_t" "ac_cv_type_in_addr_t" " +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_NETINET_IN_H +# include +#endif +" +if test "x$ac_cv_type_in_addr_t" = xyes; then : + +else + +$as_echo "#define in_addr_t uint32_t" >>confdefs.h + +fi + +ac_fn_c_check_type "$LINENO" "in_port_t" "ac_cv_type_in_port_t" " +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_NETINET_IN_H +# include +#endif +" +if test "x$ac_cv_type_in_port_t" = xyes; then : + +else + +$as_echo "#define in_port_t uint16_t" >>confdefs.h + +fi + + +# check to see if libraries are needed for these functions. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing socket" >&5 +$as_echo_n "checking for library containing socket... " >&6; } +if ${ac_cv_search_socket+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +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 socket (); +int +main () +{ +return socket (); + ; + return 0; +} +_ACEOF +for ac_lib in '' socket; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_socket=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_socket+:} false; then : + break +fi +done +if ${ac_cv_search_socket+:} false; then : + +else + ac_cv_search_socket=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_socket" >&5 +$as_echo "$ac_cv_search_socket" >&6; } +ac_res=$ac_cv_search_socket +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +tmp_LIBS="$LIBS" +LIBS= +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing inet_pton" >&5 +$as_echo_n "checking for library containing inet_pton... " >&6; } +if ${ac_cv_search_inet_pton+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +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 inet_pton (); +int +main () +{ +return inet_pton (); + ; + return 0; +} +_ACEOF +for ac_lib in '' nsl; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_inet_pton=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_inet_pton+:} false; then : + break +fi +done +if ${ac_cv_search_inet_pton+:} false; then : + +else + ac_cv_search_inet_pton=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_inet_pton" >&5 +$as_echo "$ac_cv_search_inet_pton" >&6; } +ac_res=$ac_cv_search_inet_pton +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +LIBNSL_LIBS=$LIBS + +LIBS="$tmp_LIBS" + +tmp_CPPFLAGS="$CPPFLAGS" +tmp_LDFLAGS="$LDFLAGS" +tmp_LIBS="$LIBS" + + + +# Check whether --with-ssl was given. +if test "${with_ssl+set}" = set; then : + withval=$with_ssl; + +else + + withval="yes" + +fi + + + withval=$withval + if test x_$withval != x_no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL" >&5 +$as_echo_n "checking for SSL... " >&6; } + if test x_$withval = x_ -o x_$withval = x_yes; then + withval="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw /usr" + fi + for dir in $withval; do + ssldir="$dir" + if test -f "$dir/include/openssl/ssl.h"; then + found_ssl="yes" + +cat >>confdefs.h <<_ACEOF +#define HAVE_SSL /**/ +_ACEOF + + if test "$ssldir" != "/usr"; then + CPPFLAGS="$CPPFLAGS -I$ssldir/include" + LIBSSL_CPPFLAGS="$LIBSSL_CPPFLAGS -I$ssldir/include" + fi + break; + fi + done + if test x_$found_ssl != x_yes; then + as_fn_error $? "Cannot find the SSL libraries in $withval" "$LINENO" 5 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in $ssldir" >&5 +$as_echo "found in $ssldir" >&6; } + HAVE_SSL=yes + if test "$ssldir" != "/usr" -a "$ssldir" != ""; then + LDFLAGS="$LDFLAGS -L$ssldir/lib" + LIBSSL_LDFLAGS="$LIBSSL_LDFLAGS -L$ssldir/lib" + + if test "x$enable_rpath" = xyes; then + if echo "$ssldir/lib" | grep "^/" >/dev/null; then + RUNTIME_PATH="$RUNTIME_PATH -R$ssldir/lib" + fi + fi + + 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; } + LIBS="$LIBS -lcrypto" + LIBSSL_LIBS="$LIBSSL_LIBS -lcrypto" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + int HMAC_CTX_init(void); + (void)HMAC_CTX_init(); + + ; + return 0; +} +_ACEOF +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 + + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + # check if -lwsock32 or -lgdi32 are needed. + BAKLIBS="$LIBS" + BAKSSLLIBS="$LIBSSL_LIBS" + LIBS="$LIBS -lgdi32" + LIBSSL_LIBS="$LIBSSL_LIBS -lgdi32" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if -lcrypto needs -lgdi32" >&5 +$as_echo_n "checking if -lcrypto needs -lgdi32... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + int HMAC_CTX_init(void); + (void)HMAC_CTX_init(); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + +$as_echo "#define HAVE_HMAC_CTX_INIT 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; } + LIBS="$BAKLIBS" + LIBSSL_LIBS="$BAKSSLLIBS" + LIBS="$LIBS -ldl" + LIBSSL_LIBS="$LIBSSL_LIBS -ldl" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if -lcrypto needs -ldl" >&5 +$as_echo_n "checking if -lcrypto needs -ldl... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + int HMAC_CTX_init(void); + (void)HMAC_CTX_init(); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + +$as_echo "#define HAVE_HMAC_CTX_INIT 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 \ + conftest$ac_exeext conftest.$ac_ext + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + fi + + + # openssl engine functionality needs dlopen(). + BAKLIBS="$LIBS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5 +$as_echo_n "checking for library containing dlopen... " >&6; } +if ${ac_cv_search_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +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 dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +for ac_lib in '' dl; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_dlopen=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_dlopen+:} false; then : + break +fi +done +if ${ac_cv_search_dlopen+:} false; then : + +else + ac_cv_search_dlopen=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5 +$as_echo "$ac_cv_search_dlopen" >&6; } +ac_res=$ac_cv_search_dlopen +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + + if test "$LIBS" != "$BAKLIBS"; then + LIBSSL_LIBS="$LIBSSL_LIBS -ldl" + fi + fi +for ac_header in openssl/ssl.h +do : + ac_fn_c_check_header_compile "$LINENO" "openssl/ssl.h" "ac_cv_header_openssl_ssl_h" "$ac_includes_default +" +if test "x$ac_cv_header_openssl_ssl_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OPENSSL_SSL_H 1 +_ACEOF + +fi + +done + +for ac_header in openssl/err.h +do : + ac_fn_c_check_header_compile "$LINENO" "openssl/err.h" "ac_cv_header_openssl_err_h" "$ac_includes_default +" +if test "x$ac_cv_header_openssl_err_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OPENSSL_ERR_H 1 +_ACEOF + +fi + +done + +for ac_header in openssl/rand.h +do : + ac_fn_c_check_header_compile "$LINENO" "openssl/rand.h" "ac_cv_header_openssl_rand_h" "$ac_includes_default +" +if test "x$ac_cv_header_openssl_rand_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OPENSSL_RAND_H 1 +_ACEOF + +fi + +done + + + + + + + + +CPPFLAGS="$tmp_CPPFLAGS" +LDFLAGS="$tmp_LDFLAGS" +LIBS="$tmp_LIBS" + +# use libcrypto to check the following: +tmp_LDFLAGS="$LDFLAGS" +tmp_LIBS="$LIBS" +LDFLAGS="$LDFLAGS $LIBSSL_LDFLAGS" +LIBS="$LIBS $LIBSSL_LIBS" +# Check whether --enable-sha2 was given. +if test "${enable_sha2+set}" = set; then : + enableval=$enable_sha2; +fi + +case "$enable_sha2" in + no) + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SHA256 and SHA512" >&5 +$as_echo_n "checking for SHA256 and SHA512... " >&6; } + ac_fn_c_check_func "$LINENO" "SHA256_Init" "ac_cv_func_SHA256_Init" +if test "x$ac_cv_func_SHA256_Init" = xyes; then : + +else + + as_fn_error $? "SHA2 enabled, but no SHA2 functions found in OpenSSL" "$LINENO" 5 + +fi + + +cat >>confdefs.h <<_ACEOF +#define USE_SHA2 1 +_ACEOF + + ;; +esac + +# Check whether --enable-gost was given. +if test "${enable_gost+set}" = set; then : + enableval=$enable_gost; +fi + +case "$enable_gost" in + no) + ;; + *) + if test "x$HAVE_SSL" != "xyes"; then + as_fn_error $? "GOST enabled, but no SSL support" "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GOST" >&5 +$as_echo_n "checking for GOST... " >&6; } + ac_fn_c_check_func "$LINENO" "EVP_PKEY_set_type_str" "ac_cv_func_EVP_PKEY_set_type_str" +if test "x$ac_cv_func_EVP_PKEY_set_type_str" = xyes; then : + +else + as_fn_error $? "OpenSSL >= 1.0.0 is needed for GOST support or rerun with --disable-gost" "$LINENO" 5 +fi + + ac_fn_c_check_func "$LINENO" "EC_KEY_new" "ac_cv_func_EC_KEY_new" +if test "x$ac_cv_func_EC_KEY_new" = xyes; then : + +else + as_fn_error $? "No ECC functions found in OpenSSL: please upgrade OpenSSL or rerun with --disable-gost" "$LINENO" 5 +fi + + +cat >>confdefs.h <<_ACEOF +#define USE_GOST 1 +_ACEOF + + ;; +esac + +# Check whether --enable-ecdsa was given. +if test "${enable_ecdsa+set}" = set; then : + enableval=$enable_ecdsa; +fi + +case "$enable_ecdsa" in + yes) + ac_fn_c_check_func "$LINENO" "ECDSA_sign" "ac_cv_func_ECDSA_sign" +if test "x$ac_cv_func_ECDSA_sign" = xyes; then : + +else + as_fn_error $? "OpenSSL does not support ECDSA" "$LINENO" 5 +fi + + +cat >>confdefs.h <<_ACEOF +#define USE_ECDSA 1 +_ACEOF + + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: + ***************************************************************** + *** YOU HAVE ENABLED ECDSA WHICH IS EXPERIMENTAL AT THIS TIME *** + *** PLEASE DO NOT USE THIS ON THE PUBLIC INTERNET *** + *****************************************************************" >&5 +$as_echo "$as_me: WARNING: + ***************************************************************** + *** YOU HAVE ENABLED ECDSA WHICH IS EXPERIMENTAL AT THIS TIME *** + *** PLEASE DO NOT USE THIS ON THE PUBLIC INTERNET *** + *****************************************************************" >&2;} + ;; + no|*) + ;; +esac + +LDFLAGS="$tmp_LDFLAGS" +LIBS="$tmp_LIBS" + +#AC_CHECK_HEADER(ldns/ldns.h,, [ +# AC_MSG_ERROR([Can't find ldns headers (make copy-headers in devel source.)]) +# ], [AC_INCLUDES_DEFAULT] +#) + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pcap_open_offline in -lpcap" >&5 +$as_echo_n "checking for pcap_open_offline in -lpcap... " >&6; } +if ${ac_cv_lib_pcap_pcap_open_offline+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpcap $LIBS" +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 pcap_open_offline (); +int +main () +{ +return pcap_open_offline (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_pcap_pcap_open_offline=yes +else + ac_cv_lib_pcap_pcap_open_offline=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcap_pcap_open_offline" >&5 +$as_echo "$ac_cv_lib_pcap_pcap_open_offline" >&6; } +if test "x$ac_cv_lib_pcap_pcap_open_offline" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBPCAP 1 +_ACEOF + + LIBS="-lpcap $LIBS" + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Can't find pcap library (needed for ldns-dpa, will not build dpa now.)" >&5 +$as_echo "$as_me: WARNING: Can't find pcap library (needed for ldns-dpa, will not build dpa now.)" >&2;} + + +fi + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for getaddrinfo" >&5 +$as_echo_n "checking for getaddrinfo... " >&6; } +if ${ac_cv_func_getaddrinfo+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_func_getaddrinfo=no +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#ifdef __cplusplus +extern "C" +{ +#endif +char* getaddrinfo(); +char* (*f) () = getaddrinfo; +#ifdef __cplusplus +} +#endif +int main() { + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_func_getaddrinfo="yes" +else + ORIGLIBS="$LIBS" +LIBS="$LIBS -lws2_32" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#ifdef HAVE_WS2TCPIP_H +#include +#endif + +int +main () +{ + + (void)getaddrinfo(NULL, NULL, NULL, NULL); + + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_func_getaddrinfo="yes" +LDFLAGS="$LDFLAGS -lws2_32" + +else + ac_cv_func_getaddrinfo="no" +LIBS="$ORIGLIBS" + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_getaddrinfo" >&5 +$as_echo "$ac_cv_func_getaddrinfo" >&6; } +if test $ac_cv_func_getaddrinfo = yes; then + +$as_echo "#define HAVE_GETADDRINFO 1" >>confdefs.h + +fi + + +ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default" +if test "x$ac_cv_type_pid_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define pid_t int +_ACEOF + +fi + +for ac_header in vfork.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "vfork.h" "ac_cv_header_vfork_h" "$ac_includes_default" +if test "x$ac_cv_header_vfork_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_VFORK_H 1 +_ACEOF + +fi + +done + +for ac_func in fork vfork +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 : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +if test "x$ac_cv_func_fork" = xyes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working fork" >&5 +$as_echo_n "checking for working fork... " >&6; } +if ${ac_cv_func_fork_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_fork_works=cross +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* By Ruediger Kuhlmann. */ + return fork () < 0; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_fork_works=yes +else + ac_cv_func_fork_works=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_fork_works" >&5 +$as_echo "$ac_cv_func_fork_works" >&6; } + +else + ac_cv_func_fork_works=$ac_cv_func_fork +fi +if test "x$ac_cv_func_fork_works" = xcross; then + case $host in + *-*-amigaos* | *-*-msdosdjgpp*) + # Override, as these systems have only a dummy fork() stub + ac_cv_func_fork_works=no + ;; + *) + ac_cv_func_fork_works=yes + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&5 +$as_echo "$as_me: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&2;} +fi +ac_cv_func_vfork_works=$ac_cv_func_vfork +if test "x$ac_cv_func_vfork" = xyes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working vfork" >&5 +$as_echo_n "checking for working vfork... " >&6; } +if ${ac_cv_func_vfork_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_vfork_works=cross +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Thanks to Paul Eggert for this test. */ +$ac_includes_default +#include +#ifdef HAVE_VFORK_H +# include +#endif +/* On some sparc systems, changes by the child to local and incoming + argument registers are propagated back to the parent. The compiler + is told about this with #include , but some compilers + (e.g. gcc -O) don't grok . Test for this by using a + static variable whose address is put into a register that is + clobbered by the vfork. */ +static void +#ifdef __cplusplus +sparc_address_test (int arg) +# else +sparc_address_test (arg) int arg; +#endif +{ + static pid_t child; + if (!child) { + child = vfork (); + if (child < 0) { + perror ("vfork"); + _exit(2); + } + if (!child) { + arg = getpid(); + write(-1, "", 0); + _exit (arg); + } + } +} + +int +main () +{ + pid_t parent = getpid (); + pid_t child; + + sparc_address_test (0); + + child = vfork (); + + if (child == 0) { + /* Here is another test for sparc vfork register problems. This + test uses lots of local variables, at least as many local + variables as main has allocated so far including compiler + temporaries. 4 locals are enough for gcc 1.40.3 on a Solaris + 4.1.3 sparc, but we use 8 to be safe. A buggy compiler should + reuse the register of parent for one of the local variables, + since it will think that parent can't possibly be used any more + in this routine. Assigning to the local variable will thus + munge parent in the parent process. */ + pid_t + p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(), + p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid(); + /* Convince the compiler that p..p7 are live; otherwise, it might + use the same hardware register for all 8 local variables. */ + if (p != p1 || p != p2 || p != p3 || p != p4 + || p != p5 || p != p6 || p != p7) + _exit(1); + + /* On some systems (e.g. IRIX 3.3), vfork doesn't separate parent + from child file descriptors. If the child closes a descriptor + before it execs or exits, this munges the parent's descriptor + as well. Test for this by closing stdout in the child. */ + _exit(close(fileno(stdout)) != 0); + } else { + int status; + struct stat st; + + while (wait(&status) != child) + ; + return ( + /* Was there some problem with vforking? */ + child < 0 + + /* Did the child fail? (This shouldn't happen.) */ + || status + + /* Did the vfork/compiler bug occur? */ + || parent != getpid() + + /* Did the file descriptor bug occur? */ + || fstat(fileno(stdout), &st) != 0 + ); + } +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_vfork_works=yes +else + ac_cv_func_vfork_works=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_vfork_works" >&5 +$as_echo "$ac_cv_func_vfork_works" >&6; } + +fi; +if test "x$ac_cv_func_fork_works" = xcross; then + ac_cv_func_vfork_works=$ac_cv_func_vfork + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&5 +$as_echo "$as_me: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&2;} +fi + +if test "x$ac_cv_func_vfork_works" = xyes; then + +$as_echo "#define HAVE_WORKING_VFORK 1" >>confdefs.h + +else + +$as_echo "#define vfork fork" >>confdefs.h + +fi +if test "x$ac_cv_func_fork_works" = xyes; then + +$as_echo "#define HAVE_WORKING_FORK 1" >>confdefs.h + +fi + +for ac_func in isblank srandom random sleep +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 : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +ac_fn_c_check_decl "$LINENO" "in6addr_any" "ac_cv_have_decl_in6addr_any" "$ac_includes_default +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_TIME_H +#include +#endif +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_SYS_SELECT_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETINET_UDP_H +#include +#endif +#ifdef HAVE_NETINET_IGMP_H +#include +#endif + +" +if test "x$ac_cv_have_decl_in6addr_any" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_IN6ADDR_ANY $ac_have_decl +_ACEOF + + +# check for ldns + +# Check whether --with-ldns was given. +if test "${with_ldns+set}" = set; then : + withval=$with_ldns; + specialldnsdir="$withval" + CPPFLAGS="$CPPFLAGS -I$withval/include" + LDFLAGS="-L$withval -L$withval/lib $LDFLAGS" + LDNSDIR="$withval" + + +fi + + +# check for ldns development source tree +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ldns devel source" >&5 +$as_echo_n "checking for ldns devel source... " >&6; } +ldns_dev_dir=.. +if test -f $ldns_dev_dir/ldns/util.h && \ + grep LDNS_VERSION $ldns_dev_dir/ldns/util.h >/dev/null; then + ldns_version=`grep LDNS_VERSION $ldns_dev_dir/ldns/util.h | sed -e 's/^.*"\(.*\)".*$/\1/'` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: using $ldns_dev_dir with $ldns_version" >&5 +$as_echo "using $ldns_dev_dir with $ldns_version" >&6; } + CPPFLAGS="$CPPFLAGS -I$ldns_dev_dir/include" + LDFLAGS="-L$ldns_dev_dir -L$ldns_dev_dir/lib $LDFLAGS" + LIBS="$LIBS -lldns" + +$as_echo "#define HAVE_LIBLDNS 1" >>confdefs.h + + LDNSDIR="$ldns_dev_dir" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ldns_rr_new in -lldns" >&5 +$as_echo_n "checking for ldns_rr_new in -lldns... " >&6; } +if ${ac_cv_lib_ldns_ldns_rr_new+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lldns $LIBS" +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 ldns_rr_new (); +int +main () +{ +return ldns_rr_new (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_ldns_ldns_rr_new=yes +else + ac_cv_lib_ldns_ldns_rr_new=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ldns_ldns_rr_new" >&5 +$as_echo "$ac_cv_lib_ldns_ldns_rr_new" >&6; } +if test "x$ac_cv_lib_ldns_ldns_rr_new" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBLDNS 1 +_ACEOF + + LIBS="-lldns $LIBS" + +else + + as_fn_error $? "Can't find ldns library" "$LINENO" 5 + + +fi + +fi + + + + + + +ac_config_files="$ac_config_files Makefile" + +ac_config_headers="$ac_config_headers config.h" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by ldns $as_me 1.6.13, which was +generated by GNU Autoconf 2.68. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Report bugs to ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +ldns config.status 1.6.13 +configured by $0, generated by GNU Autoconf 2.68, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2010 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi + ;; + + + esac + +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + diff --git a/examples/configure.ac b/examples/configure.ac new file mode 100644 index 00000000000..67345dac7cd --- /dev/null +++ b/examples/configure.ac @@ -0,0 +1,421 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ(2.56) +AC_INIT(ldns, 1.6.13, libdns@nlnetlabs.nl,libdns) +AC_CONFIG_SRCDIR([ldns-read-zone.c]) +sinclude(../acx_nlnetlabs.m4) + +OURCPPFLAGS='' +CPPFLAGS=${CPPFLAGS:-${OURCPPFLAGS}} +OURCFLAGS='-g' +CFLAGS=${CFLAGS:-${OURCFLAGS}} +AC_DEFINE(WINVER, 0x0502, [the version of the windows API enabled]) + +AC_AIX +# Checks for programs. +AC_PROG_CC +AC_PROG_MAKE_SET +AC_CHECK_PROGS(libtool, [glibtool libtool15 libtool], [../libtool]) + +ACX_CHECK_COMPILER_FLAG(std=c99, [C99FLAG="-std=c99"]) +ACX_CHECK_COMPILER_FLAG(xc99, [C99FLAG="-xc99"]) + +AC_ARG_ENABLE(rpath, + [AC_HELP_STRING([--disable-rpath], [Disable hardcoded rpath (default=enabled)])], + enable_rpath=$enableval, enable_rpath=yes) + +if test "x$enable_rpath" = xyes; then + RPATH_VAL="-Wl,-rpath=\${libdir}" +fi + + +AC_TYPE_SIZE_T +ACX_CHECK_COMPILER_FLAG(O2, [CFLAGS="$CFLAGS -O2"]) + +ACX_CHECK_COMPILER_FLAG_NEEDED($C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600, +[ +#include "confdefs.h" +#include +#include +#include +#ifdef HAVE_TIME_H +#include +#endif +#include +#ifdef HAVE_GETOPT_H +#include +#endif + +int test() { + int a; + char **opts = NULL; + struct timeval tv; + char *t; + time_t time = 0; + char *buf = NULL; + t = ctime_r(&time, buf); + tv.tv_usec = 10; + srandom(32); + a = getopt(2, opts, "a"); + a = isascii(32); + return a; +} +], [CFLAGS="$CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600"]) + + +ACX_CHECK_COMPILER_FLAG_NEEDED($C99FLAG, [#include ], [CFLAGS="$CFLAGS $C99FLAG"]) + +AC_C_INLINE +AC_CHECK_TYPE(int8_t, char) +AC_CHECK_TYPE(int16_t, short) +AC_CHECK_TYPE(int32_t, int) +AC_CHECK_TYPE(int64_t, long long) +AC_CHECK_TYPE(uint8_t, unsigned char) +AC_CHECK_TYPE(uint16_t, unsigned short) +AC_CHECK_TYPE(uint32_t, unsigned int) +AC_CHECK_TYPE(uint64_t, unsigned long long) +AC_CHECK_TYPE(ssize_t, int) + +AC_CHECK_HEADERS([sys/types.h getopt.h stdlib.h stdio.h assert.h netinet/in.h ctype.h time.h pcap.h arpa/inet.h sys/time.h sys/socket.h sys/select.h netdb.h],,, [AC_INCLUDES_DEFAULT]) +AC_CHECK_HEADERS([winsock2.h ws2tcpip.h],,, [AC_INCLUDES_DEFAULT]) +AC_CHECK_HEADERS([netinet/in_systm.h net/if.h netinet/ip.h netinet/udp.h netinet/igmp.h netinet/if_ether.h netinet/ip6.h],,, [ +AC_INCLUDES_DEFAULT +#ifdef HAVE_NETINET_IN_SYSTM_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif]) + +ACX_TYPE_SOCKLEN_T +AC_CHECK_HEADERS([sys/param.h sys/mount.h],,, +[AC_INCLUDES_DEFAULT] +[ + [ + #if HAVE_SYS_PARAM_H + # include + #endif + ] +]) +AC_CHECK_TYPE(in_addr_t, [], [AC_DEFINE([in_addr_t], [uint32_t], [in_addr_t])], [ +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_NETINET_IN_H +# include +#endif]) +AC_CHECK_TYPE(in_port_t, [], [AC_DEFINE([in_port_t], [uint16_t], [in_port_t])], [ +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_NETINET_IN_H +# include +#endif]) + +# check to see if libraries are needed for these functions. +AC_SEARCH_LIBS(socket, socket) +tmp_LIBS="$LIBS" +LIBS= +AC_SEARCH_LIBS(inet_pton, nsl) +AC_SUBST(LIBNSL_LIBS,$LIBS) +LIBS="$tmp_LIBS" + +tmp_CPPFLAGS="$CPPFLAGS" +tmp_LDFLAGS="$LDFLAGS" +tmp_LIBS="$LIBS" + +ACX_WITH_SSL_OPTIONAL + +AC_SUBST(LIBSSL_CPPFLAGS) +AC_SUBST(LIBSSL_LDFLAGS) +AC_SUBST(LIBSSL_LIBS) + +CPPFLAGS="$tmp_CPPFLAGS" +LDFLAGS="$tmp_LDFLAGS" +LIBS="$tmp_LIBS" + +# use libcrypto to check the following: +tmp_LDFLAGS="$LDFLAGS" +tmp_LIBS="$LIBS" +LDFLAGS="$LDFLAGS $LIBSSL_LDFLAGS" +LIBS="$LIBS $LIBSSL_LIBS" +AC_ARG_ENABLE(sha2, AC_HELP_STRING([--disable-sha2], [Disable SHA256 and SHA512 RRSIG support])) +case "$enable_sha2" in + no) + ;; + *) + AC_MSG_CHECKING(for SHA256 and SHA512) + AC_CHECK_FUNC(SHA256_Init,, [ + AC_MSG_ERROR([SHA2 enabled, but no SHA2 functions found in OpenSSL]) + ]) + AC_DEFINE_UNQUOTED([USE_SHA2], [1], [Define this to enable SHA256 and SHA512 support.]) + ;; +esac + +AC_ARG_ENABLE(gost, AC_HELP_STRING([--disable-gost], [Disable GOST support])) +case "$enable_gost" in + no) + ;; + *) + if test "x$HAVE_SSL" != "xyes"; then + AC_MSG_ERROR([GOST enabled, but no SSL support]) + fi + AC_MSG_CHECKING(for GOST) + AC_CHECK_FUNC(EVP_PKEY_set_type_str, [],[AC_MSG_ERROR([OpenSSL >= 1.0.0 is needed for GOST support or rerun with --disable-gost])]) + AC_CHECK_FUNC(EC_KEY_new, [], [AC_MSG_ERROR([No ECC functions found in OpenSSL: please upgrade OpenSSL or rerun with --disable-gost])]) + AC_DEFINE_UNQUOTED([USE_GOST], [1], [Define this to enable GOST support.]) + ;; +esac + +AC_ARG_ENABLE(ecdsa, AC_HELP_STRING([--enable-ecdsa], [Enable ECDSA support, experimental])) +case "$enable_ecdsa" in + yes) + AC_CHECK_FUNC(ECDSA_sign,,[AC_MSG_ERROR([OpenSSL does not support ECDSA])]) + AC_DEFINE_UNQUOTED([USE_ECDSA], [1], [Define this to enable ECDSA support.]) + AC_WARN([ + ***************************************************************** + *** YOU HAVE ENABLED ECDSA WHICH IS EXPERIMENTAL AT THIS TIME *** + *** PLEASE DO NOT USE THIS ON THE PUBLIC INTERNET *** + *****************************************************************]) + ;; + no|*) + ;; +esac + +LDFLAGS="$tmp_LDFLAGS" +LIBS="$tmp_LIBS" + +#AC_CHECK_HEADER(ldns/ldns.h,, [ +# AC_MSG_ERROR([Can't find ldns headers (make copy-headers in devel source.)]) +# ], [AC_INCLUDES_DEFAULT] +#) + +AC_CHECK_LIB(pcap, pcap_open_offline,, [ + AC_MSG_WARN([Can't find pcap library (needed for ldns-dpa, will not build dpa now.)]) + ] +) + + +AC_DEFUN([AC_CHECK_GETADDRINFO_WITH_INCLUDES], +[AC_REQUIRE([AC_PROG_CC]) +AC_MSG_CHECKING(for getaddrinfo) +AC_CACHE_VAL(ac_cv_func_getaddrinfo, +[ac_cv_func_getaddrinfo=no +AC_LINK_IFELSE( +[ +#ifdef __cplusplus +extern "C" +{ +#endif +char* getaddrinfo(); +char* (*f) () = getaddrinfo; +#ifdef __cplusplus +} +#endif +int main() { + ; + return 0; +} +], +dnl this case on linux, solaris, bsd +[ac_cv_func_getaddrinfo="yes"], +dnl no quick getaddrinfo, try mingw32 and winsock2 library. +ORIGLIBS="$LIBS" +LIBS="$LIBS -lws2_32" +AC_LINK_IFELSE( +AC_LANG_PROGRAM( +[ +#ifdef HAVE_WS2TCPIP_H +#include +#endif +], +[ + (void)getaddrinfo(NULL, NULL, NULL, NULL); +] +), +[ac_cv_func_getaddrinfo="yes" +LDFLAGS="$LDFLAGS -lws2_32" +], +[ac_cv_func_getaddrinfo="no" +LIBS="$ORIGLIBS" +]) +) +]) + +AC_MSG_RESULT($ac_cv_func_getaddrinfo) +if test $ac_cv_func_getaddrinfo = yes; then + AC_DEFINE(HAVE_GETADDRINFO, 1, [Whether getaddrinfo is available]) +fi +])dnl + +AC_CHECK_GETADDRINFO_WITH_INCLUDES + +AC_FUNC_FORK +AC_CHECK_FUNCS(isblank srandom random sleep) +AC_CHECK_DECLS([in6addr_any],,,[AC_INCLUDES_DEFAULT +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_TIME_H +#include +#endif +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_SYS_SELECT_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETINET_UDP_H +#include +#endif +#ifdef HAVE_NETINET_IGMP_H +#include +#endif +]) + +# check for ldns +AC_ARG_WITH(ldns, + AC_HELP_STRING([--with-ldns=PATH specify prefix of path of ldns library to use]) + , + [ + specialldnsdir="$withval" + CPPFLAGS="$CPPFLAGS -I$withval/include" + LDFLAGS="-L$withval -L$withval/lib $LDFLAGS" + LDNSDIR="$withval" + ] +) + +# check for ldns development source tree +AC_MSG_CHECKING([for ldns devel source]) +ldns_dev_dir=.. +if test -f $ldns_dev_dir/ldns/util.h && \ + grep LDNS_VERSION $ldns_dev_dir/ldns/util.h >/dev/null; then + ldns_version=`grep LDNS_VERSION $ldns_dev_dir/ldns/util.h | sed -e 's/^.*"\(.*\)".*$/\1/'` + AC_MSG_RESULT([using $ldns_dev_dir with $ldns_version]) + CPPFLAGS="$CPPFLAGS -I$ldns_dev_dir/include" + LDFLAGS="-L$ldns_dev_dir -L$ldns_dev_dir/lib $LDFLAGS" + LIBS="$LIBS -lldns" + AC_DEFINE(HAVE_LIBLDNS, 1, [If the ldns library is available.]) + LDNSDIR="$ldns_dev_dir" +else + AC_MSG_RESULT([no]) + AC_CHECK_LIB(ldns, ldns_rr_new,, [ + AC_MSG_ERROR([Can't find ldns library]) + ] + ) +fi + +AC_SUBST(LDNSDIR) + + +AH_BOTTOM([ + +#include +#include +#include +#include + +#if STDC_HEADERS +#include +#include +#endif + +#ifdef HAVE_STDINT_H +#include +#endif + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#ifdef HAVE_NETINET_UDP_H +#include +#endif + +#ifdef HAVE_TIME_H +#include +#endif + +#ifdef HAVE_PCAP_H +#include +#endif + +#ifdef HAVE_NETINET_IN_SYSTM_H +#include +#endif + +#ifdef HAVE_NETINET_IP_H +#include +#endif + +#ifdef HAVE_NET_IF_H +#include +#endif + +#ifdef HAVE_NETINET_IF_ETHER_H +#include +#endif + +#ifdef HAVE_WINSOCK2_H +#define USE_WINSOCK 1 +#include +#endif + +#ifdef HAVE_WS2TCPIP_H +#include +#endif + +#ifndef HAVE_GETADDRINFO +#include +#endif + +#ifndef HAVE_RANDOM +/* random can be replaced by rand for ldnsexamples */ +#define random rand +#endif + +#ifndef HAVE_SRANDOM +/* srandom can be replaced by srand for ldnsexamples */ +#define srandom srand +#endif + +extern char *optarg; +extern int optind, opterr; + +#ifndef EXIT_FAILURE +#define EXIT_FAILURE 1 +#endif +#ifndef EXIT_SUCCESS +#define EXIT_SUCCESS 0 +#endif + +#ifdef S_SPLINT_S +#define FD_ZERO(a) /* a */ +#define FD_SET(a,b) /* a, b */ +#endif +]) + +AC_CONFIG_FILES([Makefile]) +AC_CONFIG_HEADER([config.h]) +AC_OUTPUT diff --git a/examples/fake-rfc2553.h b/examples/fake-rfc2553.h new file mode 100644 index 00000000000..1e9add1eb03 --- /dev/null +++ b/examples/fake-rfc2553.h @@ -0,0 +1,175 @@ +/* From openssh 4.3p2 filename openbsd-compat/fake-rfc2553.h */ +/* + * Copyright (C) 2000-2003 Damien Miller. All rights reserved. + * Copyright (C) 1999 WIDE Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Pseudo-implementation of RFC2553 name / address resolution functions + * + * But these functions are not implemented correctly. The minimum subset + * is implemented for ssh use only. For example, this routine assumes + * that ai_family is AF_INET. Don't use it for another purpose. + */ + +#ifndef _FAKE_RFC2553_H +#define _FAKE_RFC2553_H + +#include +#include +#include +#include + +/* + * First, socket and INET6 related definitions + */ +#ifndef HAVE_STRUCT_SOCKADDR_STORAGE +#ifndef _SS_MAXSIZE +# define _SS_MAXSIZE 128 /* Implementation specific max size */ +# define _SS_PADSIZE (_SS_MAXSIZE - sizeof (struct sockaddr)) +struct sockaddr_storage { + struct sockaddr ss_sa; + char __ss_pad2[_SS_PADSIZE]; +}; +# define ss_family ss_sa.sa_family +#endif /* _SS_MAXSIZE */ +#endif /* !HAVE_STRUCT_SOCKADDR_STORAGE */ + +#ifndef IN6_IS_ADDR_LOOPBACK +# define IN6_IS_ADDR_LOOPBACK(a) \ + (((uint32_t *)(a))[0] == 0 && ((uint32_t *)(a))[1] == 0 && \ + ((uint32_t *)(a))[2] == 0 && ((uint32_t *)(a))[3] == htonl(1)) +#endif /* !IN6_IS_ADDR_LOOPBACK */ + +#ifndef HAVE_STRUCT_IN6_ADDR +struct in6_addr { + uint8_t s6_addr[16]; +}; +#endif /* !HAVE_STRUCT_IN6_ADDR */ + +#ifndef HAVE_STRUCT_SOCKADDR_IN6 +struct sockaddr_in6 { + unsigned short sin6_family; + uint16_t sin6_port; + uint32_t sin6_flowinfo; + struct in6_addr sin6_addr; +}; +#endif /* !HAVE_STRUCT_SOCKADDR_IN6 */ + +#ifndef AF_INET6 +/* Define it to something that should never appear */ +#define AF_INET6 AF_MAX +#endif + +/* + * Next, RFC2553 name / address resolution API + */ + +#ifndef NI_NUMERICHOST +# define NI_NUMERICHOST (1) +#endif +#ifndef NI_NAMEREQD +# define NI_NAMEREQD (1<<1) +#endif +#ifndef NI_NUMERICSERV +# define NI_NUMERICSERV (1<<2) +#endif + +#ifndef AI_PASSIVE +# define AI_PASSIVE (1) +#endif +#ifndef AI_CANONNAME +# define AI_CANONNAME (1<<1) +#endif +#ifndef AI_NUMERICHOST +# define AI_NUMERICHOST (1<<2) +#endif + +#ifndef NI_MAXSERV +# define NI_MAXSERV 32 +#endif /* !NI_MAXSERV */ +#ifndef NI_MAXHOST +# define NI_MAXHOST 1025 +#endif /* !NI_MAXHOST */ + +#ifndef INT_MAX +#define INT_MAX 0xffffffff +#endif + +#ifndef EAI_NODATA +# define EAI_NODATA (INT_MAX - 1) +#endif +#ifndef EAI_MEMORY +# define EAI_MEMORY (INT_MAX - 2) +#endif +#ifndef EAI_NONAME +# define EAI_NONAME (INT_MAX - 3) +#endif +#ifndef EAI_SYSTEM +# define EAI_SYSTEM (INT_MAX - 4) +#endif + +#ifndef HAVE_STRUCT_ADDRINFO +struct addrinfo { + int ai_flags; /* AI_PASSIVE, AI_CANONNAME */ + int ai_family; /* PF_xxx */ + int ai_socktype; /* SOCK_xxx */ + int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ + size_t ai_addrlen; /* length of ai_addr */ + char *ai_canonname; /* canonical name for hostname */ + struct sockaddr *ai_addr; /* binary address */ + struct addrinfo *ai_next; /* next structure in linked list */ +}; +#endif /* !HAVE_STRUCT_ADDRINFO */ + +#ifndef HAVE_GETADDRINFO +#ifdef getaddrinfo +# undef getaddrinfo +#endif +#define getaddrinfo(a,b,c,d) (ssh_getaddrinfo(a,b,c,d)) +int getaddrinfo(const char *, const char *, + const struct addrinfo *, struct addrinfo **); +#endif /* !HAVE_GETADDRINFO */ + +#if !defined(HAVE_GAI_STRERROR) && !defined(HAVE_CONST_GAI_STRERROR_PROTO) +#define gai_strerror(a) (ssh_gai_strerror(a)) +char *gai_strerror(int); +#endif /* !HAVE_GAI_STRERROR */ + +#ifndef HAVE_FREEADDRINFO +#define freeaddrinfo(a) (ssh_freeaddrinfo(a)) +void freeaddrinfo(struct addrinfo *); +#endif /* !HAVE_FREEADDRINFO */ + +#ifndef HAVE_GETNAMEINFO +#define getnameinfo(a,b,c,d,e,f,g) (ssh_getnameinfo(a,b,c,d,e,f,g)) +int getnameinfo(const struct sockaddr *, size_t, char *, size_t, + char *, size_t, int); +#endif /* !HAVE_GETNAMEINFO */ + +#endif /* !_FAKE_RFC2553_H */ + diff --git a/examples/ldns-chaos.1 b/examples/ldns-chaos.1 new file mode 100644 index 00000000000..e9b7bf46dc9 --- /dev/null +++ b/examples/ldns-chaos.1 @@ -0,0 +1,26 @@ +.TH ldns-chaos 1 "27 Apr 2005" +.SH NAME +ldns-chaos \- give some information about a nameserver +.SH SYNOPSIS +.B ldns-chaos +.IR NAMESERVER + +.SH DESCRIPTION +\fBldns-chaos\fR retrieves all the addresses of the nameserver and then queries +each address for its \fIversion.bind\fR and \fIhostname.bind\fR. +.PP +\fBldns-chaos\fR is a bit more complex than \fBldns-mx\fR. + +.SH OPTIONS +\fBldns-chaos\fR has no options. + +.SH AUTHOR +Written by the ldns team as an example for ldns usage. + +.SH REPORTING BUGS +Report bugs to . + +.SH COPYRIGHT +Copyright (C) 2005 NLnet Labs. This is free software. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. diff --git a/examples/ldns-chaos.c b/examples/ldns-chaos.c new file mode 100644 index 00000000000..a1e1b796bfb --- /dev/null +++ b/examples/ldns-chaos.c @@ -0,0 +1,125 @@ +/* + * chaos is a small programs that prints some information + * about a nameserver + * + * (c) NLnet Labs, 2005 - 2008 + * + * See the file LICENSE for the license + */ + +#include "config.h" + +#include + +static int +usage(FILE *fp, char *prog) { + fprintf(fp, "%s server\n", prog); + fprintf(fp, " print out some information about server\n"); + return 0; +} + +int +main(int argc, char *argv[]) +{ + ldns_resolver *res; + ldns_rdf *name; + ldns_rdf *version, *id; + ldns_pkt *p; + ldns_rr_list *addr; + ldns_rr_list *info; + ldns_status s; + ldns_rdf *pop; + size_t i; + + if (argc != 2) { + usage(stdout, argv[0]); + exit(EXIT_FAILURE); + } else { + /* create a rdf from the command line arg */ + name = ldns_dname_new_frm_str(argv[1]); + if (!name) { + usage(stdout, argv[0]); + exit(EXIT_FAILURE); + } + } + + /* create rdf for what we are going to ask */ + version = ldns_dname_new_frm_str("version.bind"); + id = ldns_dname_new_frm_str("hostname.bind"); + + /* create a new resolver from /etc/resolv.conf */ + s = ldns_resolver_new_frm_file(&res, NULL); + if (s != LDNS_STATUS_OK) { + ldns_rdf_deep_free(name); + exit(EXIT_FAILURE); + } + ldns_resolver_set_retry(res, 1); /* don't want to wait too long */ + + /* use the resolver to send it a query for the a/aaaa of name */ + addr = ldns_get_rr_list_addr_by_name(res, name, LDNS_RR_CLASS_IN, LDNS_RD); + if (!addr) { + fprintf(stderr, " *** could not get an address for %s\n", argv[1]); + ldns_rdf_deep_free(name); + ldns_resolver_deep_free(res); + exit(EXIT_FAILURE); + } + + /* remove current list of nameservers from resolver */ + while((pop = ldns_resolver_pop_nameserver(res))) { ldns_rdf_deep_free(pop); } + + + /* can be multihomed */ + for(i = 0; i < ldns_rr_list_rr_count(addr); i++) { + if (i > 0) { + fprintf(stdout, "\n"); + } + + if (ldns_resolver_push_nameserver_rr(res, + ldns_rr_list_rr(addr, i)) != LDNS_STATUS_OK) { + printf("Error adding nameserver to resolver\n"); + } + + ldns_rr_print(stdout, ldns_rr_list_rr(addr, i)); + fprintf(stdout, "\n"); + + p = ldns_resolver_query(res, version, LDNS_RR_TYPE_TXT, + LDNS_RR_CLASS_CH, LDNS_RD); + if (p) { + ldns_pkt_print(stdout, p); + info = ldns_pkt_rr_list_by_type(p, + LDNS_RR_TYPE_TXT, LDNS_SECTION_ANSWER); + + if (info) { + ldns_rr_list_print(stdout, info); + ldns_rr_list_deep_free(info); + } else { + printf(" *** version retrieval failed\n"); + } + ldns_pkt_free(p); + } else { + printf(" *** query failed\n"); + } + + p = ldns_resolver_query(res, id, LDNS_RR_TYPE_TXT, + LDNS_RR_CLASS_CH, LDNS_RD); + if (p) { + info = ldns_pkt_rr_list_by_type(p, + LDNS_RR_TYPE_TXT, LDNS_SECTION_ANSWER); + if (info) { + ldns_rr_list_print(stdout, info); + ldns_rr_list_deep_free(info); + } else { + printf(" *** id retrieval failed\n"); + } + ldns_pkt_free(p); + } else { + printf(" *** query failed for\n"); + } + ldns_rdf_deep_free(ldns_resolver_pop_nameserver(res)); + + } + + ldns_rdf_deep_free(name); + ldns_resolver_deep_free(res); + exit(EXIT_SUCCESS); +} diff --git a/examples/ldns-compare-zones.1 b/examples/ldns-compare-zones.1 new file mode 100644 index 00000000000..facccd87456 --- /dev/null +++ b/examples/ldns-compare-zones.1 @@ -0,0 +1,57 @@ +.TH ldns-compare-zones 1 "17 Oct 2007" +.SH NAME +ldns-compare-zones \- read and compare two zonefiles and print differences +.SH SYNOPSIS +.B ldns-compare-zones +.IR [-c] +.IR [-i] +.IR [-d] +.IR [-z] +.IR [-s] +.IR ZONEFILE1 +.IR ZONEFILE2 +.SH DESCRIPTION +\fBldns-compare-zones\fR reads two DNS zone files and prints number of differences. +.nf +Output is formated to: + +NUM_INS -NUM_DEL ~NUM_CHG + +.fi +The major comparison is based on the owner name. If an owner name is present in zonefile 1, but not in zonefile 2, the resource records with this owner name are considered deleted, and counted as NUM_DEL. If an owner name is present in zonefile 2, but not in zonefile 1, the resource records with this owner name are considered inserted, and counted as NUM_INS. If an owner name is present in both, but there is a difference in the amount or content of the records, these are considered changed, and counted as NUM_CHG. +.SH OPTIONS +.TP +\fB-c\fR +Print resource records whose owner names are in both zone files, but with different resource records. (a.k.a. changed) +.TP +\fB-i\fR +Print resource records whose owner names are present only in ZONEFILE2 (a.k.a. inserted) +.TP +\fB-d\fR +Print resource records whose owner names are present only in ZONEFILE1 (a.k.a. deleted) +.TP +\fB-a\fR +Print all changes. Specifying this option is the same as specifying -c -i +amd -d. +.TP +\fB-z\fR +Suppress zone sorting; this option is not recommended; it can cause records +to be incorrectly marked as changed, depending of the nature of the changes. +.TP +\fB-s\fR +Do not exclude the SOA record from the comparison. The SOA record may +then show up as changed due to a new serial number. Off by default since +you may be interested to know if (other zone apex elements) have changed. +.TP +\fB-h\fR +Show usage and exit +.TP +\fB-v\fR +Show the version and exit +.SH AUTHOR +Written by Ondřej Surý for CZ.NIC, z.s.p.o. (czech domain registry) +.SH REPORTING BUGS +Report bugs to . +.SH COPYRIGHT +Copyright (C) 2005 CZ.NIC, z.s.p.o.. This is free software. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. diff --git a/examples/ldns-compare-zones.c b/examples/ldns-compare-zones.c new file mode 100644 index 00000000000..663b744acc5 --- /dev/null +++ b/examples/ldns-compare-zones.c @@ -0,0 +1,283 @@ +/* + * ldns-compare-zones compares two zone files + * + * Written by Ondrej Sury in 2007 + * + * Modified a bit by NLnet Labs. + * + * See the file LICENSE for the license + */ + +#include "config.h" +#include +#include +#include +#include + +#include + +#include + +#define OP_INS '+' +#define OP_DEL '-' +#define OP_CHG '~' + +static void +usage(char *prog) +{ + printf("Usage: %s [-v] [-i] [-d] [-c] [-s] \n", + prog); + printf(" -i - print inserted\n"); + printf(" -d - print deleted\n"); + printf(" -c - print changed\n"); + printf(" -a - print all differences (-i -d -c)\n"); + printf(" -s - do not exclude SOA record from comparison\n"); + printf(" -z - do not sort zones\n"); +} + +int +main(int argc, char **argv) +{ + char *fn1, *fn2; + FILE *fp1, *fp2; + ldns_zone *z1, *z2; + ldns_status s; + size_t i , j; + ldns_rr_list *rrl1, *rrl2; + int rr_cmp, rr_chg = 0; + ldns_rr *rr1 = NULL, *rr2 = NULL, *rrx = NULL; + int line_nr1 = 0, line_nr2 = 0; + size_t rrc1 , rrc2; + size_t num_ins = 0, num_del = 0, num_chg = 0; + int c; + bool opt_deleted = false, opt_inserted = false, opt_changed = false; + bool sort = true, inc_soa = false; + char op = 0; + + while ((c = getopt(argc, argv, "ahvdicsz")) != -1) { + switch (c) { + case 'h': + usage(argv[0]); + exit(EXIT_SUCCESS); + break; + case 'v': + printf("%s version %s (ldns version %s)\n", + argv[0], + LDNS_VERSION, + ldns_version()); + exit(EXIT_SUCCESS); + break; + case 's': + inc_soa = true; + break; + case 'z': + sort = false; + break; + case 'd': + opt_deleted = true; + break; + case 'i': + opt_inserted = true; + break; + case 'c': + opt_changed = true; + break; + case 'a': + opt_deleted = true; + opt_inserted = true; + opt_changed = true; + break; + } + } + + argc -= optind; + argv += optind; + + if (argc != 2) { + argc -= optind; + argv -= optind; + usage(argv[0]); + exit(EXIT_FAILURE); + } + fn1 = argv[0]; + fp1 = fopen(fn1, "r"); + if (!fp1) { + fprintf(stderr, "Unable to open %s: %s\n", fn1, strerror(errno)); + exit(EXIT_FAILURE); + } + /* Read first zone */ + s = ldns_zone_new_frm_fp_l(&z1, fp1, NULL, 0, + LDNS_RR_CLASS_IN, &line_nr1); + if (s != LDNS_STATUS_OK) { + fclose(fp1); + fprintf(stderr, "%s: %s at %d\n", + fn1, + ldns_get_errorstr_by_id(s), + line_nr1); + exit(EXIT_FAILURE); + } + fclose(fp1); + + fn2 = argv[1]; + fp2 = fopen(fn2, "r"); + if (!fp2) { + fprintf(stderr, "Unable to open %s: %s\n", fn2, strerror(errno)); + exit(EXIT_FAILURE); + } + /* Read second zone */ + s = ldns_zone_new_frm_fp_l(&z2, fp2, NULL, 0, + LDNS_RR_CLASS_IN, &line_nr2); + if (s != LDNS_STATUS_OK) { + ldns_zone_deep_free(z1); + fclose(fp2); + fprintf(stderr, "%s: %s at %d\n", + fn2, + ldns_get_errorstr_by_id(s), + line_nr2); + exit(EXIT_FAILURE); + } + fclose(fp2); + + rrl1 = ldns_zone_rrs(z1); + rrc1 = ldns_rr_list_rr_count(rrl1); + + rrl2 = ldns_zone_rrs(z2); + rrc2 = ldns_rr_list_rr_count(rrl2); + + if (sort) { + /* canonicalize zone 1 */ + ldns_rr2canonical(ldns_zone_soa(z1)); + for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(z1)); i++) { + ldns_rr2canonical(ldns_rr_list_rr(ldns_zone_rrs(z1), i)); + } + /* sort zone 1 */ + ldns_zone_sort(z1); + /* canonicalize zone 2 */ + ldns_rr2canonical(ldns_zone_soa(z2)); + for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(z2)); i++) { + ldns_rr2canonical(ldns_rr_list_rr(ldns_zone_rrs(z2), i)); + } + /* sort zone 2 */ + ldns_zone_sort(z2); + } + + if(inc_soa) { + ldns_rr_list* wsoa = ldns_rr_list_new(); + ldns_rr_list_push_rr(wsoa, ldns_zone_soa(z1)); + ldns_rr_list_cat(wsoa, rrl1); + rrl1 = wsoa; + rrc1 = ldns_rr_list_rr_count(rrl1); + wsoa = ldns_rr_list_new(); + ldns_rr_list_push_rr(wsoa, ldns_zone_soa(z2)); + ldns_rr_list_cat(wsoa, rrl2); + rrl2 = wsoa; + rrc2 = ldns_rr_list_rr_count(rrl2); + if(sort) { + ldns_rr_list_sort(rrl1); + ldns_rr_list_sort(rrl2); + } + } + + /* + * Walk through both zones. The previously seen resource record is + * kept (in the variable rrx) so that we can recognize when we are + * handling a new owner name. If the owner name changes, we have to + * set the operator again. + */ + for (i = 0, j = 0; i < rrc1 || j < rrc2;) { + rr_cmp = 0; + if (i < rrc1 && j < rrc2) { + rr1 = ldns_rr_list_rr(rrl1, i); + rr2 = ldns_rr_list_rr(rrl2, j); + rr_cmp = ldns_rr_compare(rr1, rr2); + + /* Completely skip if the rrs are equal */ + if (rr_cmp == 0) { + i++; + j++; + continue; + } + rr_chg = ldns_dname_compare(ldns_rr_owner(rr1), + ldns_rr_owner(rr2)); + } else if (i >= rrc1) { + /* we have reached the end of zone 1, so the current record + * from zone 2 automatically sorts higher + */ + rr1 = NULL; + rr2 = ldns_rr_list_rr(rrl2, j); + rr_chg = rr_cmp = 1; + } else if (j >= rrc2) { + /* we have reached the end of zone 2, so the current record + * from zone 1 automatically sorts lower + */ + rr1 = ldns_rr_list_rr(rrl1, i); + rr2 = NULL; + rr_chg = rr_cmp = -1; + } + if (rr_cmp < 0) { + i++; + if ((rrx != NULL) && (ldns_dname_compare(ldns_rr_owner(rr1), + ldns_rr_owner(rrx) + ) != 0)) { + /* The owner name is different, forget previous rr */ + rrx = NULL; + } + if (rrx == NULL) { + if (rr_chg == 0) { + num_chg++; + op = OP_CHG; + } else { + num_del++; + op = OP_DEL; + } + rrx = rr1; + } + if (((op == OP_DEL) && opt_deleted) || + ((op == OP_CHG) && opt_changed)) { + printf("%c-", op); + ldns_rr_print(stdout, rr1); + } + } else if (rr_cmp > 0) { + j++; + if ((rrx != NULL) && (ldns_dname_compare(ldns_rr_owner(rr2), + ldns_rr_owner(rrx) + ) != 0)) { + rrx = NULL; + } + if (rrx == NULL) { + if (rr_chg == 0) { + num_chg++; + op = OP_CHG; + } else { + num_ins++; + op = OP_INS; + } + /* remember this rr for it's name in the next iteration */ + rrx = rr2; + } + if (((op == OP_INS) && opt_inserted) || + ((op == OP_CHG) && opt_changed)) { + printf("%c+", op); + ldns_rr_print(stdout, rr2); + } + } + } + + printf("\t%c%u\t%c%u\t%c%u\n", + OP_INS, + (unsigned int) num_ins, + OP_DEL, + (unsigned int) num_del, + OP_CHG, + (unsigned int) num_chg); + + /* Free resources */ + if(inc_soa) { + ldns_rr_list_free(rrl1); + ldns_rr_list_free(rrl2); + } + ldns_zone_deep_free(z2); + ldns_zone_deep_free(z1); + + return 0; +} diff --git a/examples/ldns-dpa.1 b/examples/ldns-dpa.1 new file mode 100644 index 00000000000..0b433df6617 --- /dev/null +++ b/examples/ldns-dpa.1 @@ -0,0 +1,151 @@ +.TH dpa 1 "1 Nov 2005" +.SH NAME +dpa \- DNS Packet Analyzer. Analyze DNS packets in ip trace files +.SH SYNOPSIS +.B dpa +[ +.IR OPTION +] +.IR TRACEFILE + +.SH DESCRIPTION +\fBdpa\fR is used to analyze dns packets in trace files. It has 3 main options: count, filter, and count uniques (i.e. count all different occurences). + +.SH OPTIONS +.TP +\fB-c\fR \fIexpressionlist\fR +Count occurrences of matching expressions + +.TP +\fB-f\fR \fIexpression\fR +Filter: only process packets that match the expression + +.TP +\fB-h\fR +Show usage + +.TP +\fB-p\fR +Show the total number of correct DNS packets, and percentage of -u and +-c values (of the total of matching on the -f filter. if no filter is +given, percentages are on all correct dns packets) + +.TP +\fB-of\fR \fIfile\fR +Write all packets that match the -f flag to file, as pcap data. + +.TP +\fB-ofh\fR \fIfile\fR +Write all packets that match the -f flag to file, in hexadecimal format, +readable by drill. + +.TP +\fB-s\fR +Show possible match names + +.TP +\fB-s\fR \fImatchname\fR +show possible match operators and values for name + +.TP +\fB-sf\fR +Only evaluate packets (in representation format) that match the -f filter. +If no -f was given, evaluate all correct dns packets. + +.TP +\fB-u\fR \fImatchnamelist\fR +Count every occurence of every value of the matchname (for instance, count all packetsizes, see EXAMPLES in ldns-dpa(1) ). + +.TP +\fB-ua\fR +For every matchname in -u, show the average value of all matches. Behaviour for match types that do not have an integer value is undefined. + +.TP +\fB-uac\fR +For every matchname in -u, show the average number of times this value was encountered. + +.TP +\fB-um\fR \fInumber\fR +Only show the results from -u for values that occurred more than times. + +.TP +\fB-v\fR \fIlevel\fR +Set verbosity to level (1-5, 5 being the highest). Mostly used for debugging. + +.TP +\fB-notip\fR \fIfile\fR +Write packets that were not recognized as IP packets to file (as pcap data). + +.TP +\fB-baddns\fR \fIfile\fR +Write dns packets that were too mangled to parse to file (as pcap data). + +.TP +\fB-version\fR +Show version and exit + +.SH LIST AND MATCHES + +A is a comma separated list of match names (use -s to see possible match names). +A is a comma separated list of expressions. + +An expression has the following form: +: () + | + & + + +: + +: + = equal to + != not equal to + > greater than + < lesser than + >= greater than or equal to + <= lesser than or equal to + ~= contains + +See the -s option for possible matchnames, operators and values. + +.SH EXAMPLES + +.TP +ldns-dpa -u packetsize -p test.tr +Count all different packetsizes in test.tr and show the precentages. + +.TP +ldns-dpa -f "edns=1&qr=0" -of edns.tr test.tr +Filter out all edns enable queries in test.tr and put them in edns.tr + +.TP +ldns-dpa -f edns=1 -c tc=1 -u rcode test.tr +For all edns packets, count the number of truncated packets and all their rcodes in test.tr. + +.TP +ldns-dpa -c tc=1,qr=0,qr=1,opcode=QUERY test.tr +For all packets, count the number of truncated packets, the number of packets with qr=0, the number of packets with qr=1 and the number of queries in test.tr. + +.TP +ldns-dpa -u packetsize -ua test.tr +Show all packet sizes and the average packet size per packet. + +.TP +ldns-dpa -u srcaddress -uac test.tr +Show all packet source addresses and the average number of packets sent from this address. + +.TP +sudo tcpdump -i eth0 -s 0 -U -w - port 53 | ldns-dpa -f qr=0 -sf +Print all query packets seen on the specified interface. + + +.SH AUTHOR +Written by Jelte Jansen for NLnetLabs. + +.SH REPORTING BUGS +Report bugs to . + +.SH COPYRIGHT +Copyright (C) 2005 NLnet Labs. This is free software. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. diff --git a/examples/ldns-dpa.c b/examples/ldns-dpa.c new file mode 100644 index 00000000000..c5717b245e9 --- /dev/null +++ b/examples/ldns-dpa.c @@ -0,0 +1,2838 @@ +/* + * ldns-dpa inspects the (udp) DNS packets found in a pcap file + * and provides statistics about them + * + * (C) NLnet Labs 2006 - 2008 + * + * See the file LICENSE for the license + */ +#include "config.h" + +#include + +#ifdef HAVE_PCAP_H +#ifdef HAVE_LIBPCAP +#include "ldns-dpa.h" + +#ifdef HAVE_NETINET_IP6_H +#include +#endif +#include + +#ifndef IP_OFFMASK +#define IP_OFFMASK 0x1fff +#endif + +int verbosity = 1; + +#define ETHER_HEADER_LENGTH 14 +#define UDP_HEADER_LENGTH 8 +#define IP6_HEADER_LENGTH 40 + +/* some systems don't have this? */ +#ifndef ETHERTYPE_IPV6 +#define ETHERTYPE_IPV6 0x86dd +#endif + +#define MAX_MATCHES 20 +#define MAX_OPERATORS 7 + + +/* global options */ +bool show_filter_matches = false; +size_t total_nr_of_dns_packets = 0; +size_t total_nr_of_filtered_packets = 0; +size_t not_ip_packets = 0; +size_t bad_dns_packets = 0; +size_t arp_packets = 0; +size_t udp_packets = 0; +size_t tcp_packets = 0; +size_t fragmented_packets = 0; +size_t lost_packet_fragments = 0; +FILE *hexdumpfile = NULL; +pcap_dumper_t *dumper = NULL; +pcap_dumper_t *not_ip_dump = NULL; +pcap_dumper_t *bad_dns_dump = NULL; + + +struct +fragment_part { + uint16_t ip_id; + uint8_t data[65536]; + size_t cur_len; +}; + +struct fragment_part *fragment_p; + +/* To add a match, + * - add it to the enum + * - add it to the table_matches const + * - add a handler to value_matches + * - tell in get_string_value() where in the packet the data lies + * - add to parser? + * - add to show_match_ function + */ +enum enum_match_ids { + MATCH_ID, + MATCH_OPCODE, + MATCH_RCODE, + MATCH_PACKETSIZE, + MATCH_QR, + MATCH_TC, + MATCH_AD, + MATCH_CD, + MATCH_RD, + MATCH_EDNS, + MATCH_EDNS_PACKETSIZE, + MATCH_DO, + MATCH_QUESTION_SIZE, + MATCH_ANSWER_SIZE, + MATCH_AUTHORITY_SIZE, + MATCH_ADDITIONAL_SIZE, + MATCH_SRC_ADDRESS, + MATCH_DST_ADDRESS, + MATCH_TIMESTAMP, + MATCH_QUERY, + MATCH_QTYPE, + MATCH_QNAME, + MATCH_ANSWER, + MATCH_AUTHORITY, + MATCH_ADDITIONAL, + MATCH_LAST +}; +typedef enum enum_match_ids match_id; + +enum enum_counter_types { + TYPE_INT, + TYPE_BOOL, + TYPE_OPCODE, + TYPE_RCODE, + TYPE_STRING, + TYPE_TIMESTAMP, + TYPE_ADDRESS, + TYPE_RR, + TYPE_RR_TYPE, + TYPE_LAST +}; +typedef enum enum_counter_types counter_type; + +const ldns_lookup_table lt_types[] = { + {TYPE_INT, "int" }, + {TYPE_BOOL, "bool" }, + {TYPE_OPCODE, "opcode" }, + {TYPE_RCODE, "rcode" }, + {TYPE_STRING, "string" }, + {TYPE_TIMESTAMP, "timestamp" }, + {TYPE_ADDRESS, "address" }, + {TYPE_RR, "rr" }, + { 0, NULL } +}; + +enum enum_type_operators { + OP_EQUAL, + OP_NOTEQUAL, + OP_GREATER, + OP_LESSER, + OP_GREATEREQUAL, + OP_LESSEREQUAL, + OP_CONTAINS, + OP_LAST +}; +typedef enum enum_type_operators type_operator; + +const ldns_lookup_table lt_operators[] = { + { OP_EQUAL, "=" }, + { OP_NOTEQUAL, "!=" }, + { OP_GREATER, ">" }, + { OP_LESSER, "<" }, + { OP_GREATEREQUAL, ">=" }, + { OP_LESSEREQUAL, "<=" }, + { OP_CONTAINS, "~=" }, + { 0, NULL } +}; + +static const char *get_op_str(type_operator op) { + const ldns_lookup_table *lt; + lt = ldns_lookup_by_id((ldns_lookup_table *) lt_operators, op); + if (lt) { + return lt->name; + } else { + fprintf(stderr, "Unknown operator id: %u\n", op); + exit(1); + } +} + +static type_operator +get_op_id(char *op_str) +{ + const ldns_lookup_table *lt; + lt = ldns_lookup_by_name((ldns_lookup_table *) lt_operators, op_str); + if (lt) { + return (type_operator) lt->id; + } else { + fprintf(stderr, "Unknown operator: %s\n", op_str); + exit(1); + } +} + +struct struct_type_operators { + counter_type type; + size_t operator_count; + type_operator operators[10]; +}; +typedef struct struct_type_operators type_operators; + +const type_operators const_type_operators[] = { + { TYPE_INT, 6, { OP_EQUAL, OP_NOTEQUAL, OP_GREATER, OP_LESSER, OP_GREATEREQUAL, OP_LESSEREQUAL, 0, 0, 0, 0 } }, + { TYPE_BOOL, 2, { OP_EQUAL, OP_NOTEQUAL, 0, 0, 0, 0, 0, 0, 0, 0} }, + { TYPE_OPCODE, 2, { OP_EQUAL, OP_NOTEQUAL, 0, 0, 0, 0, 0, 0, 0, 0} }, + { TYPE_RCODE, 2, { OP_EQUAL, OP_NOTEQUAL, 0, 0, 0, 0, 0, 0, 0, 0} }, + { TYPE_STRING, 3, { OP_EQUAL, OP_NOTEQUAL, OP_CONTAINS, 0, 0, 0, 0, 0, 0, 0} }, + { TYPE_TIMESTAMP, 6, { OP_EQUAL, OP_NOTEQUAL, OP_GREATER, OP_LESSER, OP_GREATEREQUAL, OP_LESSEREQUAL, 0, 0, 0, 0 } }, + { TYPE_ADDRESS, 3, { OP_EQUAL, OP_NOTEQUAL, OP_CONTAINS, 0, 0, 0, 0, 0, 0, 0} }, + { TYPE_RR, 3, { OP_EQUAL, OP_NOTEQUAL, OP_CONTAINS, 0, 0, 0, 0, 0, 0, 0} }, + { TYPE_RR_TYPE, 6, { OP_EQUAL, OP_NOTEQUAL, OP_GREATER, OP_LESSER, OP_GREATEREQUAL, OP_LESSEREQUAL, 0, 0, 0, 0 } }, + { 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } +}; + +const type_operators * +get_type_operators(counter_type type) { + const type_operators *to = const_type_operators; + while (to) { + if (to->type == type) { + return to; + } + to++; + } + return NULL; +} + +struct struct_match_table { + match_id id; + const char *name; + const char *description; + const counter_type type; +}; +typedef struct struct_match_table match_table; + +/* order of entries has been changed after gprof analysis, and reasoning + * about the uses of -u arguments + */ +const match_table matches[] = { + { MATCH_QUERY, "query", "String representation of the query RR", TYPE_RR }, + { MATCH_QTYPE, "qtype", "RR Type of the question RR, if present", TYPE_RR_TYPE }, + { MATCH_QNAME, "qname", "Owner name of the question RR, if present", TYPE_STRING }, + { MATCH_SRC_ADDRESS, "srcaddress", "address the packet was sent from", TYPE_ADDRESS }, + { MATCH_TIMESTAMP, "timestamp", "time the packet was sent", TYPE_TIMESTAMP }, + { MATCH_DST_ADDRESS, "dstaddress", "address the packet was sent to", TYPE_ADDRESS }, + { MATCH_EDNS_PACKETSIZE, "edns-packetsize", "packets size specified in edns rr", TYPE_INT }, + { MATCH_ID, "id", "id of the packet", TYPE_INT }, + { MATCH_OPCODE, "opcode", "opcode of packet (rfc1035)", TYPE_OPCODE }, + { MATCH_RCODE, "rcode", "response code of packet", TYPE_RCODE }, + { MATCH_PACKETSIZE, "packetsize", "size of packet in bytes", TYPE_INT }, + { MATCH_QR, "qr", "value of qr bit", TYPE_BOOL }, + { MATCH_TC, "tc", "value of tc bit", TYPE_BOOL }, + { MATCH_AD, "ad", "value of ad bit", TYPE_BOOL }, + { MATCH_CD, "cd", "value of cd bit", TYPE_BOOL }, + { MATCH_RD, "rd", "value of rd bit", TYPE_BOOL }, + { MATCH_EDNS, "edns", "existence of edns rr", TYPE_BOOL }, + { MATCH_DO, "do", "value of do bit", TYPE_BOOL }, + { MATCH_QUESTION_SIZE, "questionsize", "number of rrs in the question section", TYPE_INT }, + { MATCH_ANSWER_SIZE, "answersize", "number of rrs in the answer section", TYPE_INT }, + { MATCH_AUTHORITY_SIZE, "authoritysize", "number of rrs in the authority section", TYPE_INT }, + { MATCH_ADDITIONAL_SIZE, "additionalsize", "number of rrs in the additional section", TYPE_INT }, + { MATCH_ANSWER, "answer", "String representation of the answer RRs", TYPE_RR }, + { MATCH_AUTHORITY, "authority", "String representation of the authority RRs", TYPE_RR }, + { MATCH_ADDITIONAL, "additional", "String representation of the additional RRs", TYPE_RR }, + { 0, NULL , NULL, TYPE_INT} +}; + +enum enum_match_expression_operators { + MATCH_EXPR_OR, + MATCH_EXPR_AND, + MATCH_EXPR_LEAF +}; +typedef enum enum_match_expression_operators match_expression_operator; + +struct struct_match_operation { + match_id id; + type_operator operator; + char *value; +}; +typedef struct struct_match_operation match_operation; + +typedef struct struct_match_expression match_expression; +struct struct_match_expression { + /* and or or, or leaf (in which case there are no subtrees, but only a match_table */ + match_expression_operator op; + match_expression *left; + match_expression *right; + match_operation *match; + size_t count; +}; + +typedef struct struct_match_counters match_counters; +struct struct_match_counters { +/* + match_expression **counter; + size_t size; +*/ + match_expression *match; + match_counters *left; + match_counters *right; +}; + +match_table * +get_match_by_name(char *name) { + match_table *mt = (match_table *) matches; + if (name) { + while (mt->name != NULL) { + if (strcasecmp(name, mt->name) == 0) { + return mt; + } + mt++; + } + } + return NULL; +} + +static match_table * +get_match_by_id(match_id id) { + match_table *mt = (match_table *) matches; + + while (mt->name != NULL) { + if (mt->id == id) { + return mt; + } + mt++; + } + return NULL; +} + +static const char * +get_match_name_str(match_id id) { + match_table *mt = get_match_by_id(id); + if (mt) { + return mt->name; + } else { + fprintf(stderr, "Unknown match id: %u\n", id); + exit(1); + return "Unknown match id"; + } +} + +static void +print_match_operation(FILE *output, match_operation *mc) +{ + match_table *mt = NULL; + ldns_lookup_table *lt; + struct timeval time; + time_t time_tt; + int value; + size_t pos; + char *tmp, *tmp2; + + if (mc) { + mt = get_match_by_id(mc->id); + + if (mt) { + fprintf(output, "%s %s ",mt->name, get_op_str(mc->operator)); + + switch (mt->type) { + case TYPE_INT: + case TYPE_STRING: + case TYPE_ADDRESS: + case TYPE_RR: + fprintf(output, "'%s'", mc->value); + break; + case TYPE_BOOL: + if (strncmp(mc->value, "1", 2) == 0) { + fprintf(output,"'true'"); + } else { + fprintf(output,"'false'"); + } + break; + case TYPE_OPCODE: + value = atoi(mc->value); + lt = ldns_lookup_by_id(ldns_opcodes, value); + if (lt) { + fprintf(output, "%s", lt->name); + } else { + fprintf(output, "%s", mc->value); + } + break; + case TYPE_RCODE: + value = atoi(mc->value); + lt = ldns_lookup_by_id(ldns_rcodes, value); + if (lt) { + fprintf(output, "%s", lt->name); + } else { + fprintf(output, "%s", mc->value); + } + break; + case TYPE_TIMESTAMP: +#ifndef S_SPLINT_S + time.tv_sec = (long int) atol(mc->value); +#endif + time_tt = (time_t)time.tv_sec; + tmp = ctime(&time_tt); + tmp2 = malloc(strlen(tmp) + 1); + for (pos = 0; pos < strlen(tmp); pos++) { + if (tmp[pos] == '\n') { + tmp2[pos] = '\0'; + } else { + tmp2[pos] = tmp[pos]; + } + } + tmp2[pos] = '\0'; + fprintf(output, "%s", tmp2); + free(tmp2); + break; + default: + fprintf(output, "'%s'", mc->value); + } + + } else { + fprintf(output, "%u %s '%s'", mc->id, get_op_str(mc->operator), mc->value); + } + } else { + fprintf(output, "(nil)"); + } +} + +static void +print_match_expression(FILE *output, match_expression *expr) +{ + if (expr) { + switch (expr->op) { + case MATCH_EXPR_OR: + fprintf(output, "("); + print_match_expression(output, expr->left); + fprintf(output, " | "); + print_match_expression(output, expr->right); + fprintf(output, ")"); + break; + case MATCH_EXPR_AND: + fprintf(output, "("); + print_match_expression(output, expr->left); + fprintf(output, " & "); + print_match_expression(output, expr->right); + fprintf(output, ")"); + break; + case MATCH_EXPR_LEAF: + print_match_operation(output, expr->match); + break; + default: +/* + fprintf(output, "ERROR PRINTING MATCH: unknown op: %u\n", expr->op); + exit(1); +*/ + fprintf(output, "("); +if (expr->left) { + print_match_expression(output, expr->left); +} + fprintf(output, " ? "); +if (expr->right) { + print_match_expression(output, expr->right); +} + fprintf(output, ") _"); +if (expr->match) { + print_match_operation(output, expr->match); +} +fprintf(output, "_"); + } + } else { + printf("(nil)"); + } +} + +static void +print_counters(FILE *output, match_counters *counters, bool show_percentages, size_t total, int count_minimum) +{ + double percentage; + + if (!counters || !output) { + return; + } + + if (counters->left) { + print_counters(output, counters->left, show_percentages, total, count_minimum); + } + if (counters->match) { + if (count_minimum < (int) counters->match->count) { + print_match_expression(output, counters->match); + printf(": %u", (unsigned int) counters->match->count); + if (show_percentages) { + percentage = (double) counters->match->count / (double) total * 100.0; + printf(" (%.2f%%)", percentage); + } + printf("\n"); + } + } + if (counters->right) { + print_counters(output, counters->right, show_percentages, total, count_minimum); + } + + return; +} + +static void +ldns_pkt2file_hex(FILE *fp, const ldns_pkt *pkt) +{ + uint8_t *wire; + size_t size, i; + ldns_status status; + + status = ldns_pkt2wire(&wire, pkt, &size); + + if (status != LDNS_STATUS_OK) { + fprintf(stderr, "Unable to convert packet: error code %u", status); + return; + } + + fprintf(fp, "; 0"); + for (i = 1; i < 20; i++) { + fprintf(fp, " %2u", (unsigned int) i); + } + fprintf(fp, "\n"); + fprintf(fp, ";--"); + for (i = 1; i < 20; i++) { + fprintf(fp, " --"); + } + fprintf(fp, "\n"); + for (i = 0; i < size; i++) { + if (i % 20 == 0 && i > 0) { + fprintf(fp, "\t; %4u-%4u\n", (unsigned int) i-19, (unsigned int) i); + } + fprintf(fp, " %02x", (unsigned int)wire[i]); + } + fprintf(fp, "\n\n"); +} + +/* + * Calculate the total for all match operations with the same id as this one + * (if they are 'under' this one in the tree, which should be the case in + * the unique counter tree + */ +static size_t +calculate_total_value(match_counters *counters, match_operation *cur) +{ + size_t result = 0; + + if (!counters) { + return 0; + } + + if (counters->match->match->id == cur->id) { + result = (size_t) atol(counters->match->match->value) * counters->match->count; + } + + if (counters->left) { + result += calculate_total_value(counters->left, cur); + } + if (counters->right) { + result += calculate_total_value(counters->right, cur); + } + + return result; +} + +static size_t +calculate_total_count_matches(match_counters *counters, match_operation *cur) +{ + size_t result = 0; + + if (!counters) { + return 0; + } + + if (counters->match->match->id == cur->id) { + result = 1; + } + + if (counters->left) { + /* In some cases, you don't want the number of actual + counted matches, for instance when calculating the + average number of queries per second. In this case + you want the number of seconds */ + if (cur->id == MATCH_TIMESTAMP) { + result += (size_t) abs((int) (atol(counters->match->match->value) - atol(counters->left->match->match->value))) - 1; + } + result += calculate_total_count_matches(counters->left, cur); + } + if (counters->right) { + if (cur->id == MATCH_TIMESTAMP) { + result += (size_t) abs((int) (atol(counters->right->match->match->value) - atol(counters->match->match->value))) - 1; + } + result += calculate_total_count_matches(counters->right, cur); + } + + return result; +} + +/** + * Returns true if there is a previous match operation with the given type + * in the counters structure + */ +static bool +has_previous_match(match_counters *counters, match_operation *cur) +{ + if (!counters) { + return false; + } + + if (counters->left) { + if (counters->left->match->match->id == cur->id) { + return true; + } else if (has_previous_match(counters->left, cur)) { + return true; + } else if (counters->left->right) { + if (counters->left->right->match->match->id == cur->id) { + return true; + } else if (has_previous_match(counters->left->right, cur)) { + return true; + } + } + } + return false; +} + +/** + * Returns true if there is a later match operation with the given type + * in the counters structure + */ +static bool +has_next_match(match_counters *counters, match_operation *cur) +{ + if (!counters) { + return false; + } + + if (counters->right) { + if (counters->right->match->match->id == cur->id) { + return true; + } else if (has_next_match(counters->right, cur)) { + return true; + } else if (counters->right->left) { + if (counters->right->left->match->match->id == cur->id) { + return true; + } else if (has_next_match(counters->right->left, cur)) { + return true; + } + } + } + return false; +} + +/** + * Returns the first match with the same type at *cur in + * the counter list, or NULL if it is not found + */ +static match_expression * +get_first_match_expression(match_counters *counters, match_operation *cur) +{ + if (!counters) { + return NULL; + } + + if (has_previous_match(counters, cur)) { + return get_first_match_expression(counters->left, cur); + } else if (counters->match->match->id == cur->id) { + return counters->match; + } else if (counters->right) { + return get_first_match_expression(counters->right, cur); + } else { + return NULL; + } +} + +/** + * Returns the second match expression with the same type at *cur in + * the counter list, or NULL if it is not found + */ +static match_expression * +get_second_match_expression(match_counters *counters, match_operation *cur) +{ + if (!counters) { + return NULL; + } + + if (has_previous_match(counters, cur)) { + if (has_previous_match(counters->left, cur)) { + return get_second_match_expression(counters->left, cur); + } else { + return counters->left->match; + } +/* + } else if (counters->match->match->id == cur->id) { + return counters->match->match->value; +*/ } else if (counters->right) { + return get_first_match_expression(counters->right, cur); + } else { + return NULL; + } +} + +/** + * Returns the last match expression with the same type at *cur in + * the counter list, or NULL if it is not found + */ +static match_expression * +get_last_match_expression(match_counters *counters, match_operation *cur) +{ + if (!counters) { + return NULL; + } + + if (has_next_match(counters, cur)) { + return get_last_match_expression(counters->right, cur); + } else if (counters->match->match->id == cur->id) { + return counters->match; + } else if (counters->left) { + return get_last_match_expression(counters->left, cur); + } else { + return NULL; + } +} + +/** + * Returns the last but one match expression with the same type at *cur in + * the counter list, or NULL if it is not found + */ +static match_expression * +get_last_but_one_match_expression(match_counters *counters, match_operation *cur) +{ + if (!counters) { + return NULL; + } + + if (has_next_match(counters, cur)) { + if (has_next_match(counters->right, cur)) { + return get_last_but_one_match_expression(counters->right, cur); + } else { + return counters->match; + } +/* + } else if (counters->match->match->id == cur->id) { + return counters->match->match->value; +*/ } else if (counters->left) { + return get_last_match_expression(counters->right, cur); + } else { + return NULL; + } +} + +static size_t +get_first_count(match_counters *counters, match_operation *cur) +{ + match_expression *o = get_first_match_expression(counters, cur); + if (o) { + return o->count; + } else { + return 0; + } +} + +static size_t +get_last_count(match_counters *counters, match_operation *cur) +{ + match_expression *o = get_last_match_expression(counters, cur); + if (o) { + return o->count; + } else { + return 0; + } +} + + +static size_t +calculate_total_count(match_counters *counters, match_operation *cur) +{ + size_t result = 0; + + if (!counters) { + return 0; + } + + if (counters->match->match->id == cur->id) { + result = counters->match->count; + } + + if (counters->left) { + result += calculate_total_count(counters->left, cur); + } + if (counters->right) { + result += calculate_total_count(counters->right, cur); + } + + return result; +} + +static void +print_counter_averages(FILE *output, match_counters *counters, match_operation *cur) +{ + size_t total_value; + size_t total_count; + match_table *mt; + + if (!counters || !output) { + return; + } + + if (!cur) { + cur = counters->match->match; + mt = get_match_by_id(cur->id); + total_value = calculate_total_value(counters, cur); + total_count = calculate_total_count(counters, cur); + printf("Average for %s: (%u / %u) %.02f\n", mt->name, (unsigned int) total_value, (unsigned int) total_count, (float) total_value / (float) total_count); + if (counters->left) { + print_counter_averages(output, counters->left, cur); + } + if (counters->right) { + print_counter_averages(output, counters->right, cur); + } + } else { + if (counters->left) { + if (counters->left->match->match->id != cur->id) { + print_counter_averages(output, counters->left, NULL); + } + } + if (counters->right) { + if (counters->right->match->match->id != cur->id) { + print_counter_averages(output, counters->right, NULL); + } + } + } + + return; +} + +static void +print_counter_average_count(FILE *output, match_counters *counters, match_operation *cur, bool remove_first_last) +{ + size_t total_matches; + size_t total_count; + match_table *mt; + + if (!counters || !output) { + return; + } + + if (!cur) { + cur = counters->match->match; + mt = get_match_by_id(cur->id); + total_matches = calculate_total_count_matches(counters, cur); + total_count = calculate_total_count(counters, cur); + /* Remove the first and last for instance for timestamp average counts (half seconds drag down the average) */ + if (remove_first_last) { + total_count -= get_first_count(counters, cur); + total_count -= get_last_count(counters, cur); + printf("Removing first count from average: %u\n", (unsigned int) get_first_count(counters,cur)); + printf("Removing last count from average: %u\n", (unsigned int) get_last_count(counters,cur)); + /* in the case where we count the differences between match values too + * (like with timestamps) we need to subtract from the match count too + */ + if (cur->id == MATCH_TIMESTAMP) { + if (get_first_match_expression(counters, cur) && get_second_match_expression(counters, cur)) { + total_matches -= atol(get_second_match_expression(counters, cur)->match->value) - atol(get_first_match_expression(counters, cur)->match->value); + } + if (get_last_match_expression(counters, cur) && get_last_but_one_match_expression(counters, cur)) { + total_matches -= atol(get_last_match_expression(counters, cur)->match->value) - atol(get_last_but_one_match_expression(counters, cur)->match->value); + } + } else { + total_matches -= 2; + } + } + printf("Average count for %s: (%u / %u) %.02f\n", mt->name, (unsigned int) total_count, (unsigned int) total_matches, (float) total_count / (float) total_matches); + if (counters->left) { + print_counter_averages(output, counters->left, cur); + } + if (counters->right) { + print_counter_averages(output, counters->right, cur); + } + } else { + if (counters->left) { + if (counters->left->match->match->id != cur->id) { + print_counter_averages(output, counters->left, NULL); + } + } + if (counters->right) { + if (counters->right->match->match->id != cur->id) { + print_counter_averages(output, counters->right, NULL); + } + } + } + + return; +} + +static bool +match_int(type_operator operator, + char *value, + char *mvalue) +{ + int a, b; + + if (!value || !mvalue) { + return false; + } + + a = atoi(value); + b = atoi(mvalue); + + switch (operator) { + case OP_EQUAL: + return a == b; + break; + case OP_NOTEQUAL: + return a != b; + break; + case OP_GREATER: + return a > b; + break; + case OP_LESSER: + return a < b; + break; + case OP_GREATEREQUAL: + return a >= b; + break; + case OP_LESSEREQUAL: + return a <= b; + break; + default: + fprintf(stderr, "Unknown operator: %u\n", operator); + exit(2); + } +} + +static bool +match_opcode(type_operator operator, + char *value, + char *mvalue) +{ + ldns_pkt_opcode a, b; + int i; + ldns_lookup_table *lt; + + /* try parse name first, then parse as int */ + lt = ldns_lookup_by_name(ldns_opcodes, value); + if (lt) { + a = lt->id; + } else { + i = atoi(value); + if (i >= 0 && !isdigit(value[0]) == 0) { + lt = ldns_lookup_by_id(ldns_opcodes, i); + if (lt) { + a = lt->id; + } else { + fprintf(stderr, "Unknown opcode: %s\n", value); + exit(1); + return false; + } + } else { + fprintf(stderr, "Unknown opcode: %s\n", value); + exit(1); + return false; + } + } + + lt = ldns_lookup_by_name(ldns_opcodes, mvalue); + if (lt) { + b = lt->id; + } else { + i = atoi(mvalue); + if (i >= 0 && !isdigit(mvalue[0]) == 0) { + lt = ldns_lookup_by_id(ldns_opcodes, i); + if (lt) { + b = lt->id; + } else { + fprintf(stderr, "Unknown opcode: %s\n", mvalue); + exit(1); + return false; + } + } else { + fprintf(stderr, "Unknown opcode: %s\n", mvalue); + exit(1); + return false; + } + } + + switch(operator) { + case OP_EQUAL: + return a == b; + break; + case OP_NOTEQUAL: + return a != b; + break; + default: + fprintf(stderr, "Error bad operator for opcode: %s\n", get_op_str(operator)); + return false; + break; + } +} + +static bool +match_str(type_operator operator, + char *value, + char *mvalue) +{ + char *valuedup, *mvaluedup; + size_t i; + bool result; + + if (operator == OP_CONTAINS) { + /* strcasestr is not C89 + return strcasestr(value, mvalue) != 0; + */ + valuedup = strdup(value); + mvaluedup = strdup(mvalue); + for (i = 0; i < strlen(valuedup); i++) { + valuedup[i] = tolower(valuedup[i]); + } + for (i = 0; i < strlen(mvaluedup); i++) { + mvaluedup[i] = tolower(mvaluedup[i]); + } + result = strstr(valuedup, mvaluedup) != 0; + free(valuedup); + free(mvaluedup); + return result; + } else if (operator == OP_EQUAL) { + return strcmp(value, mvalue) == 0; + } else { + return strcmp(value, mvalue) != 0; + } +} + +static bool +match_rr_type(type_operator operator, + char *value, + char *mvalue) +{ + ldns_rr_type a,b; + + a = ldns_get_rr_type_by_name(value); + b = ldns_get_rr_type_by_name(mvalue); + + switch (operator) { + case OP_EQUAL: + return a == b; + break; + case OP_NOTEQUAL: + return a != b; + break; + case OP_GREATER: + return a > b; + break; + case OP_LESSER: + return a < b; + break; + case OP_GREATEREQUAL: + return a >= b; + break; + case OP_LESSEREQUAL: + return a <= b; + break; + default: + fprintf(stderr, "Unknown operator: %u\n", operator); + exit(2); + } +} + +static bool +match_rcode(type_operator operator, + char *value, + char *mvalue) +{ + int a, b; + int i; + ldns_lookup_table *lt; + + /* try parse name first, then parse as int */ + lt = ldns_lookup_by_name(ldns_rcodes, value); + if (lt) { + a = lt->id; + } else { + i = atoi(value); + if (i >= 0 && !isdigit(value[0]) == 0) { + lt = ldns_lookup_by_id(ldns_rcodes, i); + if (lt) { + a = lt->id; + } else { + fprintf(stderr, "Unknown rcode: %s\n", value); + exit(1); + return false; + } + } else { + fprintf(stderr, "Unknown rcode: %s\n", value); + exit(1); + return false; + } + } + + lt = ldns_lookup_by_name(ldns_rcodes, mvalue); + if (lt) { + b = lt->id; + } else { + i = atoi(mvalue); + + if (i >= 0 && !isdigit(mvalue[0]) == 0) { + lt = ldns_lookup_by_id(ldns_rcodes, i); + if (lt) { + b = lt->id; + } else { + fprintf(stderr, "Unknown rcode: %s\n", mvalue); + exit(1); + return false; + } + } else { + fprintf(stderr, "Unknown rcode: %s\n", mvalue); + exit(1); + return false; + } + } + + switch(operator) { + case OP_EQUAL: + return a == b; + break; + case OP_NOTEQUAL: + return a != b; + break; + default: + fprintf(stderr, "Error bad operator for rcode: %s\n", get_op_str(operator)); + return false; + break; + } +} + +static bool +value_matches(match_id id, + type_operator operator, + char *value, + char *mvalue) +{ + int result; + + if (verbosity >= 5) { + printf("Match %s: %s %s %s: ", get_match_name_str(id), value, get_op_str(operator), mvalue); + } + switch(id) { + case MATCH_OPCODE: + result = match_opcode(operator, value, mvalue); + break; + case MATCH_RCODE: + result = match_rcode(operator, value, mvalue); + break; + case MATCH_ID: + case MATCH_QR: + case MATCH_TC: + case MATCH_AD: + case MATCH_CD: + case MATCH_RD: + case MATCH_DO: + case MATCH_PACKETSIZE: + case MATCH_EDNS: + case MATCH_EDNS_PACKETSIZE: + case MATCH_QUESTION_SIZE: + case MATCH_ANSWER_SIZE: + case MATCH_AUTHORITY_SIZE: + case MATCH_ADDITIONAL_SIZE: + case MATCH_TIMESTAMP: + result = match_int(operator, value, mvalue); + break; + case MATCH_QUERY: + case MATCH_QNAME: + case MATCH_ANSWER: + case MATCH_AUTHORITY: + case MATCH_ADDITIONAL: + result = match_str(operator, value, mvalue); + break; + case MATCH_SRC_ADDRESS: + case MATCH_DST_ADDRESS: + result = match_str(operator, value, mvalue); + break; + case MATCH_QTYPE: + result = match_rr_type(operator, value, mvalue); + break; + default: + fprintf(stderr, "Error: value_matches() for operator %s not implemented yet.\n", get_op_str((type_operator) id)); + exit(3); + } + if (verbosity >= 5) { + if (result) { + printf("true\n"); + } else { + printf("false\n"); + } + } + return result; +} + +static char * +get_string_value(match_id id, ldns_pkt *pkt, ldns_rdf *src_addr, ldns_rdf *dst_addr) +{ + char *val; + match_table *mt; + size_t valsize = 100; + + val = malloc(valsize); + memset(val, 0, valsize); + + switch(id) { + case MATCH_QR: + snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_qr(pkt)); + break; + case MATCH_ID: + snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_id(pkt)); + break; + case MATCH_OPCODE: + snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_get_opcode(pkt)); + break; + case MATCH_RCODE: + snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_get_rcode(pkt)); + break; + case MATCH_PACKETSIZE: + snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_size(pkt)); + break; + case MATCH_TC: + snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_tc(pkt)); + break; + case MATCH_AD: + snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_ad(pkt)); + break; + case MATCH_CD: + snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_cd(pkt)); + break; + case MATCH_RD: + snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_rd(pkt)); + break; + case MATCH_EDNS: + snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_edns(pkt)); + break; + case MATCH_EDNS_PACKETSIZE: + snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_edns_udp_size(pkt)); + break; + case MATCH_DO: + snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_edns_do(pkt)); + break; + case MATCH_QUESTION_SIZE: + snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_qdcount(pkt)); + break; + case MATCH_ANSWER_SIZE: + snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_ancount(pkt)); + break; + case MATCH_AUTHORITY_SIZE: + snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_nscount(pkt)); + break; + case MATCH_ADDITIONAL_SIZE: + snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_arcount(pkt)); + break; + case MATCH_SRC_ADDRESS: + free(val); + val = ldns_rdf2str(src_addr); + break; + case MATCH_DST_ADDRESS: + free(val); + val = ldns_rdf2str(dst_addr); + break; + case MATCH_TIMESTAMP: + snprintf(val, valsize, "%u", (unsigned int) ldns_pkt_timestamp(pkt).tv_sec); + break; + case MATCH_QUERY: + if (ldns_pkt_qdcount(pkt) > 0) { + free(val); + val = ldns_rr2str(ldns_rr_list_rr(ldns_pkt_question(pkt), 0)); + /* replace \n for nicer printing later */ + if (strchr(val, '\n')) { + *(strchr(val, '\n')) = '\0'; + } + } else { + val[0] = '\0'; + } + break; + case MATCH_QNAME: + if (ldns_pkt_qdcount(pkt) > 0) { + free(val); + val = ldns_rdf2str(ldns_rr_owner(ldns_rr_list_rr(ldns_pkt_question(pkt), 0))); + /* replace \n for nicer printing later */ + if (strchr(val, '\n')) { + *(strchr(val, '\n')) = '\0'; + } + } else { + val[0] = '\0'; + } + break; + case MATCH_QTYPE: + if (ldns_pkt_qdcount(pkt) > 0) { + free(val); + val = ldns_rr_type2str(ldns_rr_get_type(ldns_rr_list_rr(ldns_pkt_question(pkt), 0))); + } else { + val[0] = '\0'; + } + break; + case MATCH_ANSWER: + if (ldns_pkt_ancount(pkt) > 0) { + free(val); + val = ldns_rr_list2str(ldns_pkt_answer(pkt)); + } else { + val[0] = '\0'; + } + break; + case MATCH_AUTHORITY: + if (ldns_pkt_nscount(pkt) > 0) { + free(val); + val = ldns_rr_list2str(ldns_pkt_authority(pkt)); + } else { + val[0] = '\0'; + } + break; + case MATCH_ADDITIONAL: + if (ldns_pkt_arcount(pkt) > 0) { + free(val); + val = ldns_rr_list2str(ldns_pkt_additional(pkt)); + } else { + val[0] = '\0'; + } + break; + default: + mt = get_match_by_id(id); + if (!mt) { + printf("ERROR UNKNOWN MATCH_TABLE ID %u\n", id); + exit(1); + } + printf("Matcher for %s not implemented yet\n", mt->name); + exit(1); + return NULL; + } + + return val; +} + +static bool +match_packet_to_operation(ldns_pkt *pkt, ldns_rdf *src_addr, ldns_rdf *dst_addr, match_operation *operation) +{ + bool result; + char *val; + + if (!pkt || !operation) { + return false; + } else { + val = get_string_value(operation->id, pkt, src_addr, dst_addr); + if (!val) { + return false; + } + result = value_matches(operation->id, operation->operator, val, operation->value); + free(val); + return result; + } +} + +static int +match_operation_compare(const void *a, const void *b) +{ + match_operation *moa, *mob; + match_table *mt; + long ia, ib; + + if (!a) { + return 1; + } else if (!b) { + return -1; + } else { + moa = (match_operation *) a; + mob = (match_operation *) b; + + if (moa->id < mob->id) { + return -1; + } else if (moa->id > mob->id) { + return 1; + } else { + if (moa->operator < mob->operator) { + return -1; + } else if (moa->operator > mob->operator) { + return 1; + } else { + mt = get_match_by_id(moa->id); + if (mt) { + switch (mt->type) { + case TYPE_INT: + case TYPE_TIMESTAMP: + case TYPE_BOOL: + case TYPE_OPCODE: + case TYPE_RCODE: + ia = atol(moa->value); + ib = atol(mob->value); + return ia - ib; + break; + case TYPE_STRING: + case TYPE_ADDRESS: + case TYPE_RR: + default: + return strcmp(moa->value, mob->value); + break; + } + } else { + return strcmp(moa->value, mob->value); + } + } + } + } +} + +static int +match_expression_compare(const void *a, const void *b) +{ + match_expression *mea, *meb; + + if (!a) { + return 1; + } else if (!b) { + return -1; + } else { + mea = (match_expression *) a; + meb = (match_expression *) b; + + if (mea->op < meb->op) { + return -1; + } else if (mea->op > meb->op) { + return 1; + } else { + switch(mea->op) { + case MATCH_EXPR_AND: + case MATCH_EXPR_OR: + if (match_expression_compare(mea->left, meb->left) < 0) { + return -1; + } else if (match_expression_compare(mea->left, meb->left) > 0) { + return 1; + } else { + return match_expression_compare(mea->right, meb->right); + } + break; + case MATCH_EXPR_LEAF: + return match_operation_compare(mea->match, meb->match); + break; + default: + fprintf(stderr, "Unknown Match Expression logic operator: %u\n", mea->op); + exit(1); + } + } + } +} + +/** + * If count is true, and the counter is found, its count is increased by 1 + */ +static int +add_match_counter(match_counters *counters, + match_expression *expr, + bool count) +{ + int cmp; + match_counters *new; + + if (!counters || !expr) { + return -1; + } else { + if (counters->match) { + cmp = match_expression_compare(counters->match, + expr); + if (cmp > 0) { + if (counters->left) { + return add_match_counter(counters->left, + expr, + count); + } else { + new = malloc(sizeof(match_counters)); + new->left = NULL; + new->right = NULL; + new->match = expr; + counters->left = new; + return 0; + } + } else if (cmp < 0) { + if (counters->right) { + return add_match_counter(counters->right, + expr, + count); + } else { + new = malloc(sizeof(match_counters)); + new->left = NULL; + new->right = NULL; + new->match = expr; + counters->right = new; + return 0; + } + } else { + /* already there? */ + if (count) { + counters->match->count++; + } + return 1; + } + } else { + /* shouldn't happen but anyway */ + counters->match = expr; + } + } + return 0; +} + +static bool +match_dns_packet_to_expr(ldns_pkt *pkt, ldns_rdf *src_addr, ldns_rdf *dst_addr, match_expression *expr) +{ + bool result; + + if (!pkt || !expr) { + return false; + } + + switch(expr->op) { + case MATCH_EXPR_OR: + result = (match_dns_packet_to_expr(pkt, src_addr, dst_addr, expr->left) || + match_dns_packet_to_expr(pkt, src_addr, dst_addr, expr->right)); + break; + case MATCH_EXPR_AND: + result = (match_dns_packet_to_expr(pkt, src_addr, dst_addr, expr->left) && + match_dns_packet_to_expr(pkt, src_addr, dst_addr, expr->right)); + break; + case MATCH_EXPR_LEAF: + result = match_packet_to_operation(pkt, src_addr, dst_addr, expr->match); + break; + default: + fprintf(stderr, "Error, unknown expression operator %u\n", expr->op); + fprintf(stderr, "full expression:\n"); + print_match_expression(stderr, expr); + fprintf(stderr, "\n"); + exit(1); + } + + if (result) { + if (verbosity >= 5) { + printf("Found Match:\n"); + print_match_expression(stdout, expr); + printf("\nCount now %u\n", (unsigned int) expr->count); + } + expr->count++; + } + + return result; +} + +static void +free_match_operation(match_operation *operation) +{ + if (operation) { + if (operation->value) { + free(operation->value); + } + free(operation); + } +} + +static void +free_match_expression(match_expression *expr) +{ + if (expr) { + switch(expr->op) { + case MATCH_EXPR_OR: + case MATCH_EXPR_AND: + free_match_expression(expr->left); + free_match_expression(expr->right); + break; + case MATCH_EXPR_LEAF: + free_match_operation(expr->match); + break; + } + free(expr); + } +} + +static void +free_counters(match_counters *counters) +{ + if (counters) { + if (counters->left) { + free_counters(counters->left); + } + if (counters->match) { + free_match_expression(counters->match); + } + if (counters->right) { + free_counters(counters->right); + } + free(counters); + } +} + +static void +match_pkt_counters(ldns_pkt *pkt, ldns_rdf *src_addr, ldns_rdf *dst_addr, match_counters *counts) +{ + if (counts->left) { + match_pkt_counters(pkt, src_addr, dst_addr, counts->left); + } + if (counts->match) { + if (match_dns_packet_to_expr(pkt, src_addr, dst_addr, counts->match)) { +/* + counts->match->count++; +*/ + } + } + if (counts->right) { + match_pkt_counters(pkt, src_addr, dst_addr, counts->right); + } +} + +static void +match_pkt_uniques(ldns_pkt *pkt, ldns_rdf *src_addr, ldns_rdf *dst_addr, match_counters *uniques, match_id unique_ids[], size_t unique_id_count) +{ + match_expression *me; + size_t i; + match_operation *mo; + int add_result; + + for (i = 0; i < unique_id_count; i++) { + mo = malloc(sizeof(match_operation)); + mo->id = unique_ids[i]; + mo->operator = OP_EQUAL; + mo->value = get_string_value(mo->id, pkt, src_addr, dst_addr); + + me = malloc(sizeof(match_expression)); + me->op = MATCH_EXPR_LEAF; + me->left = NULL; + me->right = NULL; + me->match = mo; + me->count = 1; + + add_result = add_match_counter(uniques, me, true); + /* if result=1 it was already found, so delete new one */ + if (add_result == 1) { + free_match_expression(me); + } + } + +#if 0 + size_t i, j; + bool found; + match_expression *me; + match_operation *mo; + + /* get the value, match uniques for that, if not match, add new */ + /* all unique values should be MATCH_EXPR_LEAF */ + found = false; + for (j = 0; j < uniques->size; j++) { + if (uniques->counter[j]->match->id == unique_ids[i]) { + if (match_dns_packet_to_expr(pkt, src_addr, dst_addr, uniques->counter[j])) { + found = true; + } + } + } + if (!found) { + mo = malloc(sizeof(match_operation)); + mo->id = unique_ids[i]; + mo->operator = OP_EQUAL; + mo->value = get_string_value(mo->id, pkt, src_addr, dst_addr); + + me = malloc(sizeof(match_expression)); + me->match = mo; + me->op = MATCH_EXPR_LEAF; + me->left = NULL; + me->right = NULL; + me->count = 1; + + add_counter(uniques, me); + } + } +#endif +} + +static match_expression * +parse_match_expression(char *string) +{ + match_expression *expr; + size_t i,j; + size_t leftstart, leftend = 0; + char *left_str, *op, *val; + match_table *mt; + match_operation *mo = NULL; + const type_operators *tos; + match_expression *result; + ldns_lookup_table *lt = NULL; + + /* remove whitespace */ + char *str = malloc(strlen(string) + 1); + + j = 0; + for (i = 0; i < strlen(string); i++) { + if(!isspace(string[i])) { + str[j] = string[i]; + j++; + } + } + str[j] = '\0'; + + expr = malloc(sizeof(match_expression)); + expr->left = NULL; + expr->right = NULL; + expr->match = NULL; + expr->count = 0; + leftstart = 0; + for (i = 0; i < strlen(str); i++) { + if (str[i] == '&') { + expr->op = MATCH_EXPR_AND; + if (!expr->left) { + left_str = malloc(leftend - leftstart + 2); + strncpy(left_str, &str[leftstart], leftend-leftstart+1); + left_str[leftend - leftstart + 1] = '\0'; + expr->left = parse_match_expression(left_str); + free(left_str); + } + expr->right = parse_match_expression(&str[i+1]); + if (expr->left && expr->right) { + result = expr; + goto done; + } else { + result = NULL; + goto done; + } + } else if (str[i] == '|') { + expr->op = MATCH_EXPR_OR; + if (!expr->left) { + left_str = malloc(leftend - leftstart + 2); + strncpy(left_str, &str[leftstart], leftend-leftstart+1); + left_str[leftend - leftstart + 1] = '\0'; + expr->left = parse_match_expression(left_str); + free(left_str); + } + expr->right = parse_match_expression(&str[i+1]); + expr->count = 0; + if (expr->left && expr->right) { + result = expr; + goto done; + } else { + result = NULL; + goto done; + } + } else if (str[i] == '(') { + leftstart = i + 1; + j = 1; + while (j > 0) { + i++; + if (i > strlen(str)) { + printf("parse error: no closing bracket: %s\n", str); + printf(" "); + for (j = 0; j < leftstart - 1; j++) { + printf(" "); + } + printf("^\n"); + result = NULL; + goto done; + } + if (str[i] == ')') { + j--; + } else if (str[i] == '(') { + j++; + } else { + } + } + leftend = i-1; + left_str = malloc(leftend - leftstart + 1); + strncpy(left_str, &str[leftstart], leftend - leftstart + 1); + expr->left = parse_match_expression(left_str); + free(left_str); + if (i >= strlen(str)-1) { + result = expr->left; + goto done; + } + } else if (str[i] == ')') { + printf("parse error: ) without (\n"); + result = NULL; + goto done; + } else { + leftend = i; + } + } + + /* no operators or hooks left, expr should be of the form + now */ + for (i = 0; i < strlen(str); i++) { + if (str[i] == '=' || + str[i] == '>' || + str[i] == '<' || + str[i] == '!' || + str[i] == '~' + ) { + leftend = i-1; + op = malloc(3); + j = 0; + op[j] = str[i]; + i++; + j++; + + if (i > strlen(str)) { + printf("parse error no right hand side: %s\n", str); + result = NULL; + goto done; + } + if (str[i] == '=' || + str[i] == '>' || + str[i] == '<' || + str[i] == '!' || + str[i] == '~' + ) { + op[j] = str[i]; + i++; + j++; + if (i > strlen(str)) { + printf("parse error no right hand side: %s\n", str); + result = NULL; + goto done; + } + } + op[j] = '\0'; + left_str = malloc(leftend - leftstart + 2); + strncpy(left_str, &str[leftstart], leftend - leftstart + 1); + left_str[leftend - leftstart + 1] = '\0'; + mt = get_match_by_name(left_str); + if (!mt) { + printf("parse error: unknown match name: %s\n", left_str); + result = NULL; + goto done; + } else { + /* check if operator is allowed */ + tos = get_type_operators(mt->type); + for (j = 0; j < tos->operator_count; j++) { + if (get_op_id(op) == tos->operators[j]) { + mo = malloc(sizeof(match_operation)); + mo->id = mt->id; + mo->operator = get_op_id(op); + switch (mt->type) { + case TYPE_BOOL: + val = malloc(2); + if (strncmp(&str[i], "true", 5) == 0 || + strncmp(&str[i], "TRUE", 5) == 0 || + strncmp(&str[i], "True", 5) == 0 || + strncmp(&str[i], "1", 2) == 0 + ) { + val[0] = '1'; + val[1] = '\0'; + } else if (strncmp(&str[i], "false", 5) == 0 || + strncmp(&str[i], "FALSE", 5) == 0 || + strncmp(&str[i], "False", 5) == 0 || + strncmp(&str[i], "0", 2) == 0 + ) { + + val[0] = '0'; + } else { + fprintf(stderr, "Bad value for bool: %s\n", &str[i]); + exit(EXIT_FAILURE); + } + val[1] = '\0'; + break; + case TYPE_RR: + /* convert first so we have the same strings for the same rrs in match_ later */ + /* + qrr = ldns_rr_new_frm_str(&str[i], LDNS_DEFAULT_TTL, NULL); + if (!qrr) { + fprintf(stderr, "Bad value for RR: %s\n", &str[i]); + exit(EXIT_FAILURE); + } + val = ldns_rr2str(qrr); + */ + /* remove \n for readability */ + /* + if (strchr(val, '\n')) { + *(strchr(val, '\n')) = '\0'; + } + ldns_rr_free(qrr); + */ + val = strdup(&str[i]); + break; + case TYPE_OPCODE: + lt = ldns_lookup_by_name(ldns_opcodes, &str[i]); + if (lt) { + val = malloc(4); + snprintf(val, 3, "%u", (unsigned int) lt->id); + } else { + val = strdup(&str[i]); + } + break; + case TYPE_RCODE: + lt = ldns_lookup_by_name(ldns_rcodes, &str[i]); + if (lt) { + val = malloc(4); + snprintf(val, 3, "%u", (unsigned int) lt->id); + } else { + val = strdup(&str[i]); + } + break; + default: + val = strdup(&str[i]); + break; + } + mo->value = val; + } + } + if (!mo) { + printf("parse error: operator %s not allowed for match %s\n", op, left_str); + result = NULL; + goto done; + } + } + free(left_str); + free(op); + expr->match = mo; + expr->op = MATCH_EXPR_LEAF; + result = expr; + goto done; + } + } + + result = NULL; + + done: + free(str); + if (!result) { + free_match_expression(expr); + } + return result; + +} +/* end of matches and counts */ +void +usage(FILE *output) +{ + fprintf(output, "Usage: ldns-dpa [OPTIONS] \n"); + fprintf(output, "Options:\n"); + fprintf(output, "\t-c :\tCount occurrences of matching expressions\n"); + fprintf(output, "\t-f :\tFilter occurrences of matching expressions\n"); + fprintf(output, "\t-h:\t\tshow this help\n"); + fprintf(output, "\t-p:\t\tshow percentage of -u and -c values (of the total of\n\t\t\tmatching on the -f filter. if no filter is given,\n\t\t\tpercentages are on all correct dns packets)\n"); + fprintf(output, "\t-of :\tWrite pcap packets that match the -f flag to file\n"); + fprintf(output, "\t-ofh :\tWrite pcap packets that match the -f flag to file\n\t\tin a hexadecimal format readable by drill\n"); + fprintf(output, "\t-s:\t\tshow possible match names\n"); + fprintf(output, "\t-s :\tshow possible match operators and values for \n"); + fprintf(output, "\t-sf:\t\tPrint packet that match -f. If no -f is given, print\n\t\t\tall dns packets\n"); + fprintf(output, "\t-u :\tCount all occurrences of matchname\n"); + fprintf(output, "\t-ua:\t\tShow average value of every -u matchname\n"); + fprintf(output, "\t-uac:\t\tShow average count of every -u matchname\n"); + fprintf(output, "\t-um :\tOnly show -u results that occured more than number times\n"); + fprintf(output, "\t-v :\tbe more verbose\n"); + fprintf(output, "\t-notip :\tDump pcap packets that were not recognized as\n\t\t\tIP packets to file\n"); + fprintf(output, "\t-baddns :\tDump mangled dns packets to file\n"); + fprintf(output, "\t-version:\tShow the version and exit\n"); + fprintf(output, "\n"); + fprintf(output, "The filename '-' stands for stdin or stdout, so you can use \"-of -\" if you want to pipe the output to another process\n"); + fprintf(output, "\n"); + fprintf(output, "A is a comma separated list of items\n"); + fprintf(output, "\n"); + fprintf(output, "An expression has the following form:\n"); + fprintf(output, ":\t()\n"); + fprintf(output, "\t | \n"); + fprintf(output, "\t & \n"); + fprintf(output, "\t\n"); + fprintf(output, "\n"); + fprintf(output, ":\t \n"); + fprintf(output, "\n"); + fprintf(output, "See the -s option for possible matchnames, operators and values.\n"); +} + +void +show_match_names(char *name) +{ + size_t j; + match_table *mt; + ldns_lookup_table *lt; + const type_operators *tos; + char *str; + size_t i; + + if (name) { + mt = get_match_by_name(name); + if (mt) { + printf("%s:\n", mt->name); + printf("\t%s.\n", mt->description); + printf("\toperators: "); + printf("\t"); + tos = get_type_operators(mt->type); + if (tos) { + for (j = 0; j < tos->operator_count; j++) { + printf("%s ", get_op_str(tos->operators[j])); +/* + lt = ldns_lookup_by_id((ldns_lookup_table *) lt_operators, tos->operators[j]); + if (lt) { + printf("%s ", lt->name); + } else { + printf("? "); + } +*/ + } + } else { + printf("unknown type"); + } + + printf("\n"); + printf("\tValues:\n"); + switch (mt->type) { + case TYPE_INT: + printf("\t\t\n"); + break; + case TYPE_BOOL: + printf("\t\t0\n"); + printf("\t\t1\n"); + printf("\t\ttrue\n"); + printf("\t\tfalse\n"); + break; + case TYPE_OPCODE: + printf("\t\t\n"); + lt = ldns_opcodes; + while (lt->name != NULL) { + printf("\t\t%s\n", lt->name); + lt++; + } + break; + case TYPE_RCODE: + printf("\t\t\n"); + lt = ldns_rcodes; + while (lt->name != NULL) { + printf("\t\t%s\n", lt->name); + lt++; + } + break; + case TYPE_STRING: + printf("\t\t\n"); + break; + case TYPE_TIMESTAMP: + printf("\t\t (seconds since epoch)\n"); + break; + case TYPE_ADDRESS: + printf("\t\t\n"); + break; + case TYPE_RR: + printf("\t\t\n"); + break; + default: + break; + } + } else { + printf("Unknown match name: %s\n", name); + } + } else { + mt = (match_table *) matches; + while (mt->name != NULL) { + str = (char *) mt->name; + printf("%s:", str); + i = strlen(str) + 1; + while (i < 24) { + printf(" "); + i++; + } + printf("%s\n", mt->description); + mt++; + } + } +} + +int +handle_ether_packet(const u_char *data, struct pcap_pkthdr cur_hdr, match_counters *count, match_expression *match_expr, match_counters *uniques, match_id unique_ids[], size_t unique_id_count) +{ + struct ether_header *eptr; + struct ip *iptr; + struct ip6_hdr *ip6_hdr; + int ip_hdr_size; + uint8_t protocol; + size_t data_offset = 0; + ldns_rdf *src_addr, *dst_addr; + uint8_t *ap; + char *astr; + bpf_u_int32 len = cur_hdr.caplen; + struct timeval timestamp; + uint16_t ip_flags; + uint16_t ip_len; + uint16_t ip_id; + uint16_t ip_f_offset; + const u_char *newdata = NULL; +/* +printf("timeval: %u ; %u\n", cur_hdr.ts.tv_sec, cur_hdr.ts.tv_usec); +*/ + + uint8_t *dnspkt; + + ldns_pkt *pkt; + ldns_status status; + + /* lets start with the ether header... */ + eptr = (struct ether_header *) data; + /* Do a couple of checks to see what packet type we have..*/ + if (ntohs (eptr->ether_type) == ETHERTYPE_IP) + { + if (verbosity >= 5) { + printf("Ethernet type hex:%x dec:%u is an IP packet\n", + (unsigned int) ntohs(eptr->ether_type), + (unsigned int) ntohs(eptr->ether_type)); + } + + data_offset = ETHER_HEADER_LENGTH; + iptr = (struct ip *) (data + data_offset); + /* + printf("IP_OFF: %u (%04x) %04x %04x (%d) (%d)\n", iptr->ip_off, iptr->ip_off, IP_MF, IP_DF, iptr->ip_off & 0x4000, iptr->ip_off & 0x2000); + */ + ip_flags = ldns_read_uint16(&(iptr->ip_off)); + ip_id = ldns_read_uint16(&(iptr->ip_id)); + ip_len = ldns_read_uint16(&(iptr->ip_len)); + ip_f_offset = (ip_flags & IP_OFFMASK)*8; + if (ip_flags & IP_MF && ip_f_offset == 0) { + /*printf("First Frag id %u len\n", ip_id, ip_len);*/ + fragment_p->ip_id = ip_id; + memset(fragment_p->data, 0, 65535); + memcpy(fragment_p->data, iptr, ip_len); + fragment_p->cur_len = ip_len + 20; +/* + for (ip_len = 0; ip_len < fragment_p->cur_len; ip_len++) { + if (ip_len > 0 && ip_len % 20 == 0) { + printf("\t; %u - %u\n", ip_len - 19, ip_len); + } + printf("%02x ", fragment_p->data[ip_len]); + } + printf("\t; ??? - %u\n", ip_len); +*/ + return 0; + } else + if (ip_flags & IP_MF && ip_f_offset != 0) { + /*printf("Next frag\n");*/ + if (ip_id == fragment_p->ip_id) { + /*printf("add fragment to current id %u len %u offset %u\n", ip_id, ip_len, ip_f_offset);*/ + memcpy(fragment_p->data + (ip_f_offset) + 20, data+data_offset+20, ip_len - (iptr->ip_hl)*4); + /*printf("COPIED %u\n", ip_len);*/ + fragment_p->cur_len = fragment_p->cur_len + ip_len - 20; + /*printf("cur len now %u\n", fragment_p->cur_len);*/ +/* + for (ip_len = 0; ip_len < fragment_p->cur_len; ip_len++) { + if (ip_len > 0 && ip_len % 20 == 0) { + printf("\t; %u - %u\n", ip_len - 19, ip_len); + } + printf("%02x ", fragment_p->data[ip_len]); + } + printf("\t; ??? - %u\n", ip_len); +*/ + return 0; + } else { + /*printf("Lost fragment %u\n", iptr->ip_id);*/ + lost_packet_fragments++; + return 1; + } + } else + if (!(ip_flags & IP_MF) && ip_f_offset != 0) { + /*printf("Last frag\n");*/ + if (ip_id == fragment_p->ip_id) { + /*printf("add fragment to current id %u len %u offset %u\n", ip_id, ip_len, ip_f_offset);*/ + memcpy(fragment_p->data + ip_f_offset + 20, data+data_offset+20, ip_len - 20); + fragment_p->cur_len = fragment_p->cur_len + ip_len - 20; + iptr = (struct ip *) fragment_p->data; + newdata = malloc(fragment_p->cur_len + data_offset); + if (!newdata) { + printf("Malloc failed, out of mem?\n"); + exit(4); + } + memcpy((char *) newdata, data, data_offset); + memcpy((char *) newdata+data_offset, fragment_p->data, fragment_p->cur_len); + iptr->ip_len = (u_short) ldns_read_uint16(&(fragment_p->cur_len)); + iptr->ip_off = 0; + len = (bpf_u_int32) fragment_p->cur_len; + cur_hdr.caplen = len; + fragment_p->ip_id = 0; + fragmented_packets++; +/* + for (ip_len = 0; ip_len < fragment_p->cur_len; ip_len++) { + if (ip_len > 0 && ip_len % 20 == 0) { + printf("\t; %u - %u\n", ip_len - 19, ip_len); + } + printf("%02x ", fragment_p->data[ip_len]); + } + printf("\t; ??? - %u\n", ip_len); +*/ + } else { + /*printf("Lost fragment %u\n", iptr->ip_id);*/ + lost_packet_fragments++; + return 1; + } + } else { + newdata = data; + } +/* + if (iptr->ip_off & 0x0040) { + printf("Don't fragment\n"); + } +*/ + + /* in_addr portability woes, going manual for now */ + /* ipv4 */ + ap = (uint8_t *) &(iptr->ip_src); + astr = malloc(INET_ADDRSTRLEN); + if (inet_ntop(AF_INET, ap, astr, INET_ADDRSTRLEN)) { + if (ldns_str2rdf_a(&src_addr, astr) == LDNS_STATUS_OK) { + + } + free(astr); + } + ap = (uint8_t *) &(iptr->ip_dst); + astr = malloc(INET_ADDRSTRLEN); + if (inet_ntop(AF_INET, ap, astr, INET_ADDRSTRLEN)) { + if (ldns_str2rdf_a(&dst_addr, astr) == LDNS_STATUS_OK) { + + } + free(astr); + } + + ip_hdr_size = (int) iptr->ip_hl * 4; + protocol = (uint8_t) iptr->ip_p; + + data_offset += ip_hdr_size; + + if (protocol == IPPROTO_UDP) { + udp_packets++; + data_offset += UDP_HEADER_LENGTH; + + dnspkt = (uint8_t *) (newdata + data_offset); + + /*printf("packet starts at byte %u\n", data_offset);*/ + + /*printf("Len: %u\n", len);*/ + + status = ldns_wire2pkt(&pkt, dnspkt, len - data_offset); + + if (status != LDNS_STATUS_OK) { + if (verbosity >= 3) { + printf("No dns packet: %s\n", ldns_get_errorstr_by_id(status)); + } + if (verbosity >= 5) { + for (ip_len = 0; ip_len < len - data_offset; ip_len++) { + if (ip_len > 0 && ip_len % 20 == 0) { + printf("\t; %u - %u\n", (unsigned int) ip_len - 19, (unsigned int) ip_len); + } + printf("%02x ", (unsigned int) dnspkt[ip_len]); + } + printf("\t; ??? - %u\n", (unsigned int) ip_len); + + } + bad_dns_packets++; + if (bad_dns_dump) { + pcap_dump((u_char *)bad_dns_dump, &cur_hdr, newdata); + } + } else { + timestamp.tv_sec = cur_hdr.ts.tv_sec; + timestamp.tv_usec = cur_hdr.ts.tv_usec; + ldns_pkt_set_timestamp(pkt, timestamp); + + if (verbosity >= 4) { + printf("DNS packet\n"); + ldns_pkt_print(stdout, pkt); + printf("\n\n"); + } + + total_nr_of_dns_packets++; + + if (match_expr) { + if (match_dns_packet_to_expr(pkt, src_addr, dst_addr, match_expr)) { + /* if outputfile write */ + if (dumper) { + pcap_dump((u_char *)dumper, &cur_hdr, data); + } + if (hexdumpfile) { + fprintf(hexdumpfile, ";; %u\n", (unsigned int) total_nr_of_dns_packets); + ldns_pkt2file_hex(hexdumpfile, pkt); + } + if (show_filter_matches) { + printf(";; From: "); + ldns_rdf_print(stdout, src_addr); + printf("\n"); + printf(";; To: "); + ldns_rdf_print(stdout, dst_addr); + printf("\n"); + ldns_pkt_print(stdout, pkt); + printf("------------------------------------------------------------\n\n"); + } + } else { + ldns_pkt_free(pkt); + ldns_rdf_deep_free(src_addr); + ldns_rdf_deep_free(dst_addr); + return 0; + } + } else { + if (dumper) { + pcap_dump((u_char *)dumper, &cur_hdr, data); + } + if (hexdumpfile) { + fprintf(hexdumpfile, ";; %u\n", (unsigned int) total_nr_of_dns_packets); + ldns_pkt2file_hex(hexdumpfile, pkt); + } + if (show_filter_matches) { + printf(";; From: "); + ldns_rdf_print(stdout, src_addr); + printf("\n"); + printf(";; To: "); + ldns_rdf_print(stdout, dst_addr); + printf("\n"); + ldns_pkt_print(stdout, pkt); + printf("------------------------------------------------------------\n\n"); + } + } + + /* General counters here */ + total_nr_of_filtered_packets++; + + match_pkt_counters(pkt, src_addr, dst_addr, count); + match_pkt_uniques(pkt, src_addr, dst_addr, uniques, unique_ids, unique_id_count); + + ldns_pkt_free(pkt); + pkt = NULL; + } + ldns_rdf_deep_free(src_addr); + ldns_rdf_deep_free(dst_addr); + + } else if (protocol == IPPROTO_TCP) { + /* tcp packets are skipped */ + tcp_packets++; + } + /* don't have a define for ethertype ipv6 */ + } else if (ntohs (eptr->ether_type) == ETHERTYPE_IPV6) { + /*printf("IPv6!\n");*/ + + + /* copied from ipv4, move this to function? */ + + data_offset = ETHER_HEADER_LENGTH; + ip6_hdr = (struct ip6_hdr *) (data + data_offset); + + newdata = data; + + /* in_addr portability woes, going manual for now */ + /* ipv6 */ + ap = (uint8_t *) &(ip6_hdr->ip6_src); + astr = malloc(INET6_ADDRSTRLEN); + if (inet_ntop(AF_INET6, ap, astr, INET6_ADDRSTRLEN)) { + if (ldns_str2rdf_aaaa(&src_addr, astr) == LDNS_STATUS_OK) { + + } + free(astr); + } + ap = (uint8_t *) &(ip6_hdr->ip6_dst); + astr = malloc(INET6_ADDRSTRLEN); + if (inet_ntop(AF_INET6, ap, astr, INET6_ADDRSTRLEN)) { + if (ldns_str2rdf_aaaa(&dst_addr, astr) == LDNS_STATUS_OK) { + + } + free(astr); + } + + ip_hdr_size = IP6_HEADER_LENGTH; + protocol = (uint8_t) ip6_hdr->ip6_ctlun.ip6_un1.ip6_un1_nxt; + + data_offset += ip_hdr_size; + + if (protocol == IPPROTO_UDP) { + udp_packets++; + /*printf("V6 UDP!\n");*/ + data_offset += UDP_HEADER_LENGTH; + + dnspkt = (uint8_t *) (newdata + data_offset); + + /*printf("Len: %u\n", len);*/ + + status = ldns_wire2pkt(&pkt, dnspkt, len - data_offset); + + if (status != LDNS_STATUS_OK) { + if (verbosity >= 3) { + printf("No dns packet: %s\n", ldns_get_errorstr_by_id(status)); + } + bad_dns_packets++; + if (bad_dns_dump) { + pcap_dump((u_char *)bad_dns_dump, &cur_hdr, newdata); + } + } else { + timestamp.tv_sec = cur_hdr.ts.tv_sec; + timestamp.tv_usec = cur_hdr.ts.tv_usec; + ldns_pkt_set_timestamp(pkt, timestamp); + + if (verbosity >= 4) { + printf("DNS packet\n"); + ldns_pkt_print(stdout, pkt); + printf("\n\n"); + } + + total_nr_of_dns_packets++; + + if (match_expr) { + if (match_dns_packet_to_expr(pkt, src_addr, dst_addr, match_expr)) { + /* if outputfile write */ + if (dumper) { + pcap_dump((u_char *)dumper, &cur_hdr, data); + } + if (show_filter_matches) { + printf(";; From: "); + ldns_rdf_print(stdout, src_addr); + printf("\n"); + printf(";; To: "); + ldns_rdf_print(stdout, dst_addr); + printf("\n"); + ldns_pkt_print(stdout, pkt); + printf("------------------------------------------------------------\n\n"); + } + } else { + ldns_pkt_free(pkt); + ldns_rdf_deep_free(src_addr); + ldns_rdf_deep_free(dst_addr); + return 0; + } + } else { + if (show_filter_matches) { + printf(";; From: "); + ldns_rdf_print(stdout, src_addr); + printf("\n"); + printf(";; To: "); + ldns_rdf_print(stdout, dst_addr); + printf("\n"); + ldns_pkt_print(stdout, pkt); + printf("------------------------------------------------------------\n\n"); + } + } + + /* General counters here */ + total_nr_of_filtered_packets++; + + match_pkt_counters(pkt, src_addr, dst_addr, count); + match_pkt_uniques(pkt, src_addr, dst_addr, uniques, unique_ids, unique_id_count); + + ldns_pkt_free(pkt); + pkt = NULL; + } + ldns_rdf_deep_free(src_addr); + ldns_rdf_deep_free(dst_addr); + + } else if (protocol == IPPROTO_TCP) { + /* tcp packets are skipped */ + tcp_packets++; + } else { + printf("ipv6 unknown next header type: %u\n", (unsigned int) protocol); + } + + + + } else if (ntohs (eptr->ether_type) == ETHERTYPE_ARP) { + if (verbosity >= 5) { + printf("Ethernet type hex:%x dec:%u is an ARP packet\n", + (unsigned int) ntohs(eptr->ether_type), + (unsigned int) ntohs(eptr->ether_type)); + } + arp_packets++; + } else { + printf("Ethernet type %x not IP\n", (unsigned int) ntohs(eptr->ether_type)); + if (verbosity >= 5) { + printf("Ethernet type %x not IP\n", (unsigned int) ntohs(eptr->ether_type)); + } + not_ip_packets++; + if (not_ip_dump) { + pcap_dump((u_char *)not_ip_dump, &cur_hdr, data); + } + } + + return 0; +} + +bool +parse_match_list(match_counters *counters, char *string) +{ + size_t i; + match_expression *expr; +/* match_counter *mc;*/ + size_t lastpos = 0; + char *substring; + + /*printf("Parsing match list: '%s'\n", string);*/ + + for (i = 0; i < strlen(string); i++) { + if (string[i] == ',') { + if (i<2) { + fprintf(stderr, "Matchlist cannot start with ,\n"); + return false; + } else { + substring = malloc(strlen(string)+1); + strncpy(substring, &string[lastpos], i - lastpos + 1); + substring[i - lastpos] = '\0'; + expr = parse_match_expression(substring); + if (!expr) { + return false; + } + free(substring); + /* + if (expr->op != MATCH_EXPR_LEAF) { + fprintf(stderr, "Matchlist can only contain , not a logic expression\n"); + return false; + } + */ + add_match_counter(counters, expr, false); + lastpos = i+1; + } + } + } + substring = malloc(strlen(string) + 1); + strncpy(substring, &string[lastpos], i - lastpos + 1); + substring[i - lastpos] = '\0'; + expr = parse_match_expression(substring); + + if (!expr) { + fprintf(stderr, "Bad match: %s\n", substring); + return false; + } + free(substring); + /* + if (expr->op != MATCH_EXPR_LEAF) { + fprintf(stderr, "Matchlist can only contain , not a logic expression\n"); + return false; + } + */ + add_match_counter(counters, expr, false); + return true; +} + +bool +parse_uniques(match_id ids[], size_t *count, char *string) +{ + size_t i, j, lastpos; + char *str, *strpart; + match_table *mt; + + /*printf("Parsing unique counts: '%s'\n", string);*/ + str = malloc(strlen(string) + 1); + j = 0; + for (i = 0; i < strlen(string); i++) { + if (!isspace(string[i])) { + str[j] = string[i]; + j++; + } + } + str[j] = '\0'; + + lastpos = 0; + for (i = 0; i <= strlen(str); i++) { + if (str[i] == ',' || i >= strlen(str)) { + strpart = malloc(i - lastpos + 1); + strncpy(strpart, &str[lastpos], i - lastpos); + strpart[i - lastpos] = '\0'; + if ((mt = get_match_by_name(strpart))) { + ids[*count] = mt->id; + *count = *count + 1; + } else { + printf("Error parsing match list; unknown match name: %s\n", strpart); + return false; + } + free(strpart); + lastpos = i + 1; + } + } + if (i > lastpos) { + strpart = malloc(i - lastpos + 1); + strncpy(strpart, &str[lastpos], i - lastpos); + strpart[i - lastpos] = '\0'; + if ((mt = get_match_by_name(strpart))) { + ids[*count] = mt->id; + *count = *count + 1; + } else { + printf("Error parsing match list; unknown match name: %s\n", strpart); + return false; + } + free(strpart); + lastpos = i + 1; + } + free(str); + return true; +} + +int main(int argc, char *argv[]) { + + int i; + int status = EXIT_SUCCESS; + match_counters *count = malloc(sizeof(match_counters)); + const char *inputfile = NULL; + char errbuf[PCAP_ERRBUF_SIZE]; + pcap_t *pc = NULL; + const u_char *cur; + struct pcap_pkthdr cur_hdr; + match_expression *expr = NULL; + match_id unique_ids[MAX_MATCHES]; + size_t unique_id_count = 0; /* number of unique counters */ + match_counters *uniques = malloc(sizeof(match_counters)); + char *dumpfile = NULL; + char *hexdumpfilename = NULL; + char *not_ip_dumpfile = NULL; + char *bad_dns_dumpfile = NULL; + + bool show_percentages = false; + bool show_averages = false; + bool show_average_count = false; + int unique_minimum = 0; + + count->left = NULL; + count->match = NULL; + count->right = NULL; + uniques->left = NULL; + uniques->match = NULL; + uniques->right = NULL; + + fragment_p = malloc(sizeof(struct fragment_part)); + fragment_p->ip_id = 0; + fragment_p->cur_len = 0; + + for (i = 1; i < argc; i++) { + + if (strncmp(argv[i], "-baddns", 8) == 0) { + if (i + 1 < argc) { + bad_dns_dumpfile = argv[i + 1]; + i++; + } else { + usage(stderr); + status = EXIT_FAILURE; + goto exit; + } + } else if (strncmp(argv[i], "-notip", 7) == 0) { + if (i + 1 < argc) { + not_ip_dumpfile = argv[i + 1]; + i++; + } else { + usage(stderr); + status = EXIT_FAILURE; + goto exit; + } + } else if (strncmp(argv[i], "-c", 3) == 0) { + if (i + 1 < argc) { + if (!parse_match_list(count, argv[i + 1])) { + status = EXIT_FAILURE; + goto exit; + } + i++; + } else { + usage(stderr); + status = EXIT_FAILURE; + goto exit; + } + } else if (strncmp(argv[i], "-f", 3) == 0) { + if (i + 1 < argc) { + if (expr || strchr(argv[i+1], ',')) { + fprintf(stderr, "You can only specify 1 filter expression.\n"); + status = EXIT_FAILURE; + goto exit; + } + expr = parse_match_expression(argv[i + 1]); + i++; + } else { + usage(stderr); + status = EXIT_FAILURE; + goto exit; + } + } else if (strncmp(argv[i], "-h", 3) == 0) { + usage(stdout); + status = EXIT_SUCCESS; + goto exit; + } else if (strncmp(argv[i], "-p", 3) == 0) { + show_percentages = true; + } else if (strncmp(argv[i], "-of", 4) == 0) { + if (i + 1 < argc) { + dumpfile = argv[i + 1]; + i++; + } else { + usage(stderr); + status = EXIT_FAILURE; + goto exit; + } + } else if (strncmp(argv[i], "-ofh", 5) == 0) { + if (i + 1 < argc) { + hexdumpfilename = argv[i + 1]; + i++; + } else { + usage(stderr); + status = EXIT_FAILURE; + goto exit; + } + } else if (strncmp(argv[i], "-s", 3) == 0) { + if (i + 1 < argc) { + show_match_names(argv[i + 1]); + } else { + show_match_names(NULL); + } + status = EXIT_SUCCESS; + goto exit; + } else if (strncmp(argv[i], "-sf", 4) == 0) { + show_filter_matches = true; + } else if (strncmp(argv[i], "-u", 3) == 0) { + if (i + 1 < argc) { + if (!parse_uniques(unique_ids, &unique_id_count, argv[i + 1])) { + status = EXIT_FAILURE; + goto exit; + } + i++; + } else { + usage(stderr); + status = EXIT_FAILURE; + goto exit; + } + } else if (strcmp("-ua", argv[i]) == 0) { + show_averages = true; + } else if (strcmp("-uac", argv[i]) == 0) { + show_average_count = true; + } else if (strcmp("-um", argv[i]) == 0) { + if (i + 1 < argc) { + unique_minimum = atoi(argv[i+1]); + i++; + } else { + fprintf(stderr, "-um requires an argument"); + usage(stderr); + status = EXIT_FAILURE; + goto exit; + } + } else if (strcmp("-v", argv[i]) == 0) { + i++; + if (i < argc) { + verbosity = atoi(argv[i]); + } + } else if (strcmp("-version", argv[i]) == 0) { + printf("dns packet analyzer, version %s (ldns version %s)\n", LDNS_VERSION, ldns_version()); + goto exit; + } else { + if (inputfile) { + fprintf(stderr, "You can only specify 1 input file\n"); + exit(1); + } + inputfile = argv[i]; + } + } + + if (!inputfile) { + inputfile = "-"; + } + + if (verbosity >= 5) { + printf("Filter:\n"); + print_match_expression(stdout, expr); + printf("\n\n"); + } + + pc = pcap_open_offline(inputfile, errbuf); + + if (!pc) { + if (errno != 0) { + printf("Error opening pcap file %s: %s\n", inputfile, errbuf); + exit(1); + } else { + goto showresult; + } + } + + if (dumpfile) { + dumper = pcap_dump_open(pc, dumpfile); + + if (!dumper) { + printf("Error opening pcap dump file %s: %s\n", dumpfile, errbuf); + exit(1); + } + } + + if (hexdumpfilename) { + if (strncmp(hexdumpfilename, "-", 2) != 0) { + printf("hexdump is file\n"); + hexdumpfile = fopen(hexdumpfilename, "w"); + } else { + printf("hexdump is stdout\n"); + hexdumpfile = stdout; + } + + if (!hexdumpfile) { + printf("Error opening hex dump file %s: %s\n", hexdumpfilename, strerror(errno)); + exit(1); + } + } + + if (not_ip_dumpfile) { + not_ip_dump = pcap_dump_open(pc, not_ip_dumpfile); + if (!not_ip_dump) { + printf("Error opening pcap dump file NOT_IP: %s\n", errbuf); + } + } + if (bad_dns_dumpfile) { + bad_dns_dump = pcap_dump_open(pc, bad_dns_dumpfile); + if (!bad_dns_dump) { + printf("Error opening pcap dump file NOT_IP: %s\n", errbuf); + } + } + + while ((cur = pcap_next(pc, &cur_hdr))) { + if (verbosity >= 5) { + printf("\n\n\n[PKT_HDR] caplen: %u \tlen: %u\n", (unsigned int)cur_hdr.caplen, (unsigned int)cur_hdr.len); + } + handle_ether_packet(cur, cur_hdr, count, expr, uniques, unique_ids, unique_id_count); + } + + if (not_ip_dump) { + pcap_dump_close(not_ip_dump); + } + + if (bad_dns_dump) { + pcap_dump_close(bad_dns_dump); + } + + if (dumper) { + pcap_dump_close(dumper); + } + + if (hexdumpfile && hexdumpfile != stdout) { + fclose(hexdumpfile); + } + + pcap_close(pc); + + showresult: + if (show_percentages) { + fprintf(stdout, "Packets that are not IP: %u\n", (unsigned int) not_ip_packets); + fprintf(stdout, "bad dns packets: %u\n", (unsigned int) bad_dns_packets); + fprintf(stdout, "arp packets: %u\n", (unsigned int) arp_packets); + fprintf(stdout, "udp packets: %u\n", (unsigned int) udp_packets); + fprintf(stdout, "tcp packets (skipped): %u\n", (unsigned int) tcp_packets); + fprintf(stdout, "reassembled fragmented packets: %u\n", (unsigned int) fragmented_packets); + fprintf(stdout, "packet fragments lost: %u\n", (unsigned int) lost_packet_fragments); + fprintf(stdout, "Total number of DNS packets: %u\n", (unsigned int) total_nr_of_dns_packets); + fprintf(stdout, "Total number of DNS packets after filter: %u\n", (unsigned int) total_nr_of_filtered_packets); + } + if (count->match) { + print_counters(stdout, count, show_percentages, total_nr_of_filtered_packets, 0); + } + if (uniques->match) { + print_counters(stdout, uniques, show_percentages, total_nr_of_filtered_packets, unique_minimum); + if (show_averages) { + print_counter_averages(stdout, uniques, NULL); + } + if (show_average_count) { + print_counter_average_count(stdout, uniques, NULL, true); + } + } + + exit: + + free_match_expression(expr); + free_counters(count); + free_counters(uniques); + + return status; +} + +#else +int main() { + fprintf(stderr, "ldns-dpa was not built because there is no pcap library on this system, or there was no pcap header file at compilation time. Please install pcap and rebuild.\n"); + return 1; +} +#endif +#else +int main() { + fprintf(stderr, "ldns-dpa was not built because there is no pcap library on this system, or there was no pcap header file at compilation time. Please install pcap and rebuild.\n"); + return 1; +} +#endif + + diff --git a/examples/ldns-dpa.h b/examples/ldns-dpa.h new file mode 100644 index 00000000000..b56530d0ef0 --- /dev/null +++ b/examples/ldns-dpa.h @@ -0,0 +1,92 @@ +#include +#include +#include +#include + +#if STDC_HEADERS +#include +#include +#endif + +#ifdef HAVE_STDINT_H +#include +#endif + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#ifdef HAVE_NETINET_UDP_H +#include +#endif + +#ifdef HAVE_TIME_H +#include +#endif + +#ifdef HAVE_PCAP_H +#include +#endif + +#ifdef HAVE_NETINET_IN_SYSTM_H +#include +#endif + +#ifdef HAVE_NETINET_IP_H +#include +#endif + +#ifdef HAVE_NET_IF_H +#include +#endif + +#ifdef HAVE_NETINET_IF_ETHER_H +#include +#endif + +#ifdef HAVE_WINSOCK2_H +#define USE_WINSOCK 1 +#include +#endif + +#ifdef HAVE_WS2TCPIP_H +#include +#endif + +#ifndef HAVE_GETADDRINFO +#include +#endif + +#ifndef HAVE_RANDOM +/* random can be replaced by rand for ldnsexamples */ +#define random rand +#endif + +#ifndef HAVE_SRANDOM +/* srandom can be replaced by srand for ldnsexamples */ +#define srandom srand +#endif + +extern char *optarg; +extern int optind, opterr; + +#ifndef EXIT_FAILURE +#define EXIT_FAILURE 1 +#endif +#ifndef EXIT_SUCCESS +#define EXIT_SUCCESS 0 +#endif + +#ifdef S_SPLINT_S +#define FD_ZERO(a) /* a */ +#define FD_SET(a,b) /* a, b */ +#endif + diff --git a/examples/ldns-gen-zone.1 b/examples/ldns-gen-zone.1 new file mode 100644 index 00000000000..5e7129b8892 --- /dev/null +++ b/examples/ldns-gen-zone.1 @@ -0,0 +1,98 @@ +.TH ldns-gen-zone 1 "10 June 2010" +.SH NAME +ldns-gen-zone \- read a zonefile and print it while adding DS records and extra RR's +.SH SYNOPSIS +.B ldns-gen-zone +.IR ZONEFILE + +.SH DESCRIPTION + +\fBldns-gen-zone\fR reads a DNS zone file and prints it. + +It is build for speed, not for a nice formatting. The output +has one resource record per line and no pretty-printing makeup. + +DNSSEC data (NSEC, NSEC3, RRSIG or DNSKEY) is not stripped. You may want to +use \fBldns-read-zone\fR for that. Existing DS records are also not stripped. + +The idea is to use this tool for quickly generating a representative +artificial zonefile from a real zonefile, to use it for testing purposes. + +.SH OPTIONS +.TP +\fB-a NUM\fR +Adds NUM extra artificial NS RRSets to the output. +The RRSets owner names start +with 'xn--' in an attempt to ensure uniqueness (nl.-zone does not support +IDN's - and this tool was written with that knowledge in mind). + +An artificial NS RRSet has two NS records; ns1.example.com and +ns2.example.com. + +.TP +\fB-p NUM\fR +Add NUM% of DS RRSets to the NS RRSets (anywhere between +1-4 DS records per RRSet). + +.TP +\fB-o ORIGIN\fR +Sets an $ORIGIN, which can be handy if the one in the zonefile +is set to '@' for example. If there is an $ORIGIN in the zonefile, +this option will silently be ignored. + +.TP +\fB-s\fR +This is the recommended way of processing large zones that +are already sorted and canonicalized (ie lowercase). It skips the +sorting and canonicalization step that is required for properly +grouping RRSets together (before adding any DS records to them. Skipping +this step will speed things up. + +It is not recommended to use this option if you want to add DS records +to unsorted, non-canonicalized zones. + +.TP +\fB-h\fR +Show usage and exit. + +.TP +\fB-v\fR +Show version and exit. + +.SH EXAMPLES + +.TP +\fBldns-gen-zone -a 100000 -p 10 -s ./zonefile.txt\fR +Read a zonefile, add 100.000 artificial NS RRSets and 10% of DS records, +print it to standard output. Don't sort (will only work well if the input +zonefile is already sorted and canonicalized). + +.TP +\fBldns-gen-zone -p 10 -s -o nl zonefile.txt | named-compilezone -s relative -i none -o zonefile_10.txt nl /dev/stdin\fR +This creates a nicely formatted zone file with the help of \fBnamed-compilezone\fR. +It adds 10% DS records to the .nl zone, reformats it and saves it as \fBzonefile_10.txt\fR. + +.SH AUTHOR +Initially written by Marco Davids, several modifications added by Miek +Gieben, both from SIDN. + +.SH REPORTING BUGS +Report bugs to . + +.SH BUGS +Only undiscovered ones. + +.SH CAVEATS +May require a machine with a considerable amount of memory for large zone files. + +Fake DS records hashes are generated as digest type SHA-256 (RFC4509). Be aware not to change +the DIGESTTYPE #define in the source code in anything else but 2 if you want +to keep things realistic. + +Despite a number of efforts, this program is still not the fastest in the +world. + +.SH COPYRIGHT +Copyright (C) 2010 SIDN. This is free software. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. diff --git a/examples/ldns-gen-zone.c b/examples/ldns-gen-zone.c new file mode 100644 index 00000000000..cf5e5fd8d7a --- /dev/null +++ b/examples/ldns-gen-zone.c @@ -0,0 +1,310 @@ +/* + * Reads a zone file from disk and prints it to stdout, one RR per line. + * Adds artificial DS records and RRs. + * For the purpose of generating a test zone file + * + * (c) SIDN 2010/2011 - Marco Davids/Miek Gieben + * + * See the LICENSE file for the license + */ + +#include "config.h" +#include +#include +#include +#include + +#define NUM_DS 4 /* maximum of 4 DS records per delegation */ +#define ALGO 8 /* Algorithm to use for fake DS records - RSASHA256 - RFC5702 */ +#define DIGESTTYPE 2 /* Digest type to use for fake DS records - SHA-256 - RFC 4509 */ + + +/** + * Usage function. + * + */ +static void +usage(FILE *fp, char *prog) { + fprintf(fp, "\n\nUsage: %s [-hsv] [-ap NUM] [-o ORIGIN] []\n", prog); + fprintf(fp, "\tReads a zonefile and add some artificial NS RRsets and DS records.\n"); + fprintf(fp, "\tIf no zonefile is given, the zone is read from stdin.\n"); + fprintf(fp, "\t-a add NUM artifical delegations (NS RRSets) to output.\n"); + fprintf(fp, "\t-p add NUM percent of DS RRset's to the NS RRsets (1-%d RR's per DS RRset).\n", NUM_DS); + fprintf(fp, "\t-o ORIGIN sets an $ORIGIN, which can be handy if the one in the zonefile is set to @.\n"); + fprintf(fp, "\t-s if input zone file is already sorted and canonicalized (ie all lowercase),\n\t use this option to speed things up while inserting DS records.\n"); + fprintf(fp, "\t-h show this text.\n"); + fprintf(fp, "\t-v shows the version and exits.\n"); + fprintf(fp, "\nif no file is given standard input is read.\n\n"); +} + +/** + * Insert the DS records, return the amount added. + * + */ +static int +insert_ds(ldns_rdf *dsowner, uint32_t ttl) +{ + int d, dsrand; + int keytag = 0; + char *dsownerstr; + char digeststr[70]; + + /** + * Average the amount of DS records per delegation a little. + */ + dsrand = 1+rand() % NUM_DS; + for(d = 0; d < dsrand; d++) { + keytag = 1+rand() % 65535; + /** + * Dynamic hashes method below is still too slow... 20% slower than a fixed string... + * + * We assume RAND_MAX is 32 bit, http://www.gnu.org/s/libc/manual/html_node/ISO-Random.html + * 2147483647 or 0x7FFFFFFF + */ + snprintf(digeststr, 65, + "%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x", + (unsigned) rand()%RAND_MAX, (unsigned) rand()%RAND_MAX, (unsigned) rand()%RAND_MAX, + (unsigned) rand()%RAND_MAX, (unsigned) rand()%RAND_MAX, (unsigned) rand()%RAND_MAX, + (unsigned) rand()%RAND_MAX, (unsigned) rand()%RAND_MAX, (unsigned) rand()%RAND_MAX, + (unsigned) rand()%RAND_MAX, (unsigned) rand()%RAND_MAX, (unsigned) rand()%RAND_MAX, + (unsigned) rand()%RAND_MAX, (unsigned) rand()%RAND_MAX, (unsigned) rand()%RAND_MAX, + (unsigned) rand()%RAND_MAX); + dsownerstr = ldns_rdf2str(dsowner); + fprintf(stdout, "%s\t%u\tIN\tDS\t%d %d %d %s\n", dsownerstr, (unsigned) ttl, keytag, ALGO, DIGESTTYPE, digeststr); + } + return dsrand; +} + +int +main(int argc, char **argv) { + char *filename, *rrstr, *ownerstr; + const char *classtypestr1 = "IN NS ns1.example.com."; + const char *classtypestr2 = "IN NS ns2.example.com."; + const size_t classtypelen = strlen(classtypestr1); + /* Simply because this was developed by SIDN and we don't use xn-- for .nl :-) */ + const char *punystr = "xn--fake-rr"; + const size_t punylen = strlen(punystr); + size_t rrstrlen, ownerlen; + FILE *fp; + int c, nsrand; + uint32_t ttl; + int counta,countd,countr; + ldns_zone *z; + ldns_rdf *origin = NULL; + int line_nr = 0; + int addrrs = 0; + int dsperc = 0; + bool canonicalize = true; + bool sort = true; + bool do_ds = false; + ldns_status s; + size_t i; + ldns_rr_list *rrset_list; + ldns_rdf *owner; + ldns_rr_type cur_rr_type; + ldns_rr *cur_rr; + ldns_status status; + + counta = countd = countr = 0; + + /** + * Set some random seed. + */ + srand((unsigned int)time(NULL)); + + /** + * Commandline options. + */ + while ((c = getopt(argc, argv, "a:p:shvo:")) != -1) { + switch (c) { + case 'a': + addrrs = atoi(optarg); + if (addrrs <= 0) { + fprintf(stderr, "error\n"); + exit(EXIT_FAILURE); + } + break; + case 'o': + origin = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, optarg); + if (!origin) { + fprintf(stderr, "error: creating origin from -o %s failed.\n", optarg); + exit(EXIT_FAILURE); + } + break; + case 'p': + dsperc = atoi(optarg); + if (dsperc <= 0 || dsperc > 100) { + fprintf(stderr, "error: percentage of signed delegations must be between [0-100].\n"); + exit(EXIT_FAILURE); + } + do_ds = true; + break; + case 's': + sort = false; + canonicalize = false; + break; + case 'h': + usage(stdout, argv[0]); + exit(EXIT_SUCCESS); + case 'v': + fprintf(stdout, "ldns-gen-zone version %s (ldns version %s)\n", LDNS_VERSION, ldns_version()); + exit(EXIT_SUCCESS); + default: + fprintf(stderr, "\nTry -h for more information.\n\n"); + exit(EXIT_FAILURE); + } + } + argc -= optind; + argv += optind; + + /** + * Read zone. + */ + if (argc == 0) { + fp = stdin; + } else { + filename = argv[0]; + fp = fopen(filename, "r"); + if (!fp) { + fprintf(stderr, "Unable to open %s: %s\n", filename, strerror (errno)); + exit(EXIT_FAILURE); + } + } + s = ldns_zone_new_frm_fp_l(&z, fp, origin, 0, LDNS_RR_CLASS_IN, &line_nr); + if (s != LDNS_STATUS_OK) { + fprintf(stderr, "%s at %d\n", ldns_get_errorstr_by_id(s), line_nr); + exit(EXIT_FAILURE); + } + if (!ldns_zone_soa(z)) { + fprintf(stderr, "No zone data seen\n"); + exit(EXIT_FAILURE); + } + + ttl = ldns_rr_ttl(ldns_zone_soa(z)); + if (!origin) { + origin = ldns_rr_owner(ldns_zone_soa(z)); + // Check for root (.) origin here TODO(MG) + } + ownerstr = ldns_rdf2str(origin); + if (!ownerstr) { + fprintf(stderr, "ldns_rdf2str(origin) failed\n"); + exit(EXIT_FAILURE); + } + ownerlen = strlen(ownerstr); + + ldns_rr_print(stdout, ldns_zone_soa(z)); + + if (addrrs > 0) { + while (addrrs > counta) { + counta++; + rrstrlen = punylen + ownerlen + classtypelen + 4; + rrstrlen *= 2; /* estimate */ + rrstr = (char*)malloc(rrstrlen); + if (!rrstr) { + fprintf(stderr, "malloc() failed: Out of memory\n"); + exit(EXIT_FAILURE); + } + (void)snprintf(rrstr, rrstrlen, "%s%d.%s %u %s", punystr, counta, + ownerstr, (unsigned) ttl, classtypestr1); + status = ldns_rr_new_frm_str(&cur_rr, rrstr, 0, NULL, NULL); + if (status == LDNS_STATUS_OK) { + ldns_rr_print(stdout, cur_rr); + ldns_rr_free(cur_rr); + } else { + fprintf(stderr, "ldns_rr_new_frm_str() failed\n"); + exit(EXIT_FAILURE); + } + + (void)snprintf(rrstr, rrstrlen, "%s%d.%s %u %s", punystr, counta, + ownerstr, (unsigned) ttl, classtypestr2); + status = ldns_rr_new_frm_str(&cur_rr, rrstr, 0, NULL, NULL); + if (status == LDNS_STATUS_OK) { + ldns_rr_print(stdout, cur_rr); + } else { + fprintf(stderr, "ldns_rr_new_frm_str() failed\n"); + exit(EXIT_FAILURE); + } + + free(rrstr); + + /* may we add a DS record as well? */ + if (do_ds) { + /* + * Per definition this may not be the same as the origin, so no + * check required same for NS check - so the only thing left is some + * randomization. + */ + nsrand = rand() % 100; + if (nsrand < dsperc) { + owner = ldns_rr_owner(cur_rr); + ttl = ldns_rr_ttl(cur_rr); + countd += insert_ds(owner, ttl); + } + } + ldns_rr_free(cur_rr); + } + } + + if (!do_ds) { + ldns_rr_list_print(stdout, ldns_zone_rrs(z)); + } else { + /* + * We use dns_rr_list_pop_rrset and that requires a sorted list weird things may happen + * if the -s option was used on unsorted, non-canonicalized input + */ + if (canonicalize) { + ldns_rr2canonical(ldns_zone_soa(z)); + for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(z)); i++) { + ldns_rr2canonical(ldns_rr_list_rr(ldns_zone_rrs(z), i)); + } + } + + if (sort) { + ldns_zone_sort(z); + } + + /* Work on a per RRset basis for DS records - weird things will happen if the -s option + * was used in combination with an unsorted zone file + */ + while((rrset_list = ldns_rr_list_pop_rrset(ldns_zone_rrs(z)))) { + owner = ldns_rr_list_owner(rrset_list); + cur_rr_type = ldns_rr_list_type(rrset_list); + /** + * Print them... + */ + cur_rr = ldns_rr_list_pop_rr(rrset_list); + while (cur_rr) { + ttl = ldns_rr_ttl(cur_rr); + fprintf(stdout, "%s", ldns_rr2str(cur_rr)); + cur_rr = ldns_rr_list_pop_rr(rrset_list); + } + /* + * And all the way at the end a DS record if + * we are dealing with an NS rrset + */ + nsrand = rand() % 100; + if (nsrand == 0) { + nsrand = 100; + } + + if ((cur_rr_type == LDNS_RR_TYPE_NS) && + (ldns_rdf_compare(owner, origin) != 0) && (nsrand < dsperc)) { + /** + * No DS records for the $ORIGIN, only for delegations, obey dsperc. + */ + countr++; + countd += insert_ds(owner, ttl); + } + ldns_rr_list_free(rrset_list); + ldns_rdf_free(owner); + } + } + + /** + * And done... + */ + fclose(fp); + fprintf(stdout, ";; Added %d DS records (percentage was %d) to %d NS RRset's (from input-zone: %d, from added: %d)\n;; lines in original input-zone: %d\n", + countd, dsperc, counta + countr, countr, counta, line_nr); + exit(EXIT_SUCCESS); +} diff --git a/examples/ldns-key2ds.1 b/examples/ldns-key2ds.1 new file mode 100644 index 00000000000..6fdbee5f1a3 --- /dev/null +++ b/examples/ldns-key2ds.1 @@ -0,0 +1,41 @@ +.TH ldns-key2ds 1 "30 May 2005" +.SH NAME +ldns-key2ds \- transform a DNSKEY RR to a DS RR +.SH SYNOPSIS +.B ldns-key2ds +.IR file + +.SH DESCRIPTION +\fBldns-key2ds\fR is used to transform a public DNSKEY RR to a DS RR. +When run it will read \fIfile\fR with a DNSKEY RR in it and +it will create a .ds file with the DS RR in it. + +It prints out the basename for this file (K++). + +By default it takes a pick of algorithm similar to the key algorithm, +SHA1 for RSASHA1, and so on. + +.SH OPTIONS +.TP +\fB-n\fR +Write the result DS Resource Record to stdout instead of a file + +.TP +\fB-1\fR +Use SHA1 as the hash function. + +.TP +\fB-2\fR +Use SHA256 as the hash function + + +.SH AUTHOR +Written by the ldns team as an example for ldns usage. + +.SH REPORTING BUGS +Report bugs to . + +.SH COPYRIGHT +Copyright (C) 2005 NLnet Labs. This is free software. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. diff --git a/examples/ldns-key2ds.c b/examples/ldns-key2ds.c new file mode 100644 index 00000000000..a3e54383ab9 --- /dev/null +++ b/examples/ldns-key2ds.c @@ -0,0 +1,199 @@ +/* + * key2ds transforms a public key into its DS + * It (currently) prints out the public key + * + * (c) NLnet Labs, 2005 - 2008 + * See the file LICENSE for the license + */ + +#include "config.h" + +#include + +#include + +static void +usage(FILE *fp, char *prog) { + fprintf(fp, "%s [-fn] [-1|-2] keyfile\n", prog); + fprintf(fp, " Generate a DS RR from the DNSKEYS in keyfile\n"); + fprintf(fp, " The following file will be created: "); + fprintf(fp, "K++.ds\n"); + fprintf(fp, " The base name (K++ will be printed to stdout\n"); + fprintf(fp, "Options:\n"); + fprintf(fp, " -f: ignore SEP flag (i.e. make DS records for any key)\n"); + fprintf(fp, " -n: do not write DS records to file(s) but to stdout\n"); + fprintf(fp, " (default) use similar hash to the key algorithm.\n"); + fprintf(fp, " -1: use SHA1 for the DS hash\n"); + fprintf(fp, " -2: use SHA256 for the DS hash\n"); +#ifdef USE_GOST + fprintf(fp, " -g: use GOST for the DS hash\n"); +#endif +#ifdef USE_ECDSA + fprintf(fp, " -4: use SHA384 for the DS hash\n"); +#endif +} + +static int +is_suitable_dnskey(ldns_rr *rr, int sep_only) +{ + if (!rr || ldns_rr_get_type(rr) != LDNS_RR_TYPE_DNSKEY) { + return 0; + } + return !sep_only || + (ldns_rdf2native_int16(ldns_rr_dnskey_flags(rr)) & + LDNS_KEY_SEP_KEY); +} + +static ldns_hash +suitable_hash(ldns_signing_algorithm algorithm) +{ + switch (algorithm) { + case LDNS_SIGN_RSASHA256: + case LDNS_SIGN_RSASHA512: + return LDNS_SHA256; + case LDNS_SIGN_ECC_GOST: +#ifdef USE_GOST + return LDNS_HASH_GOST; +#else + return LDNS_SHA256; +#endif +#ifdef USE_ECDSA + case LDNS_SIGN_ECDSAP256SHA256: + return LDNS_SHA256; + case LDNS_SIGN_ECDSAP384SHA384: + return LDNS_SHA384; +#endif + default: + return LDNS_SHA1; + } + return LDNS_SHA1; +} + +int +main(int argc, char *argv[]) +{ + FILE *keyfp, *dsfp; + char *keyname; + char *dsname; + char *owner; + ldns_rr *k, *ds; + ldns_signing_algorithm alg; + ldns_hash h; + int similar_hash=1; + char *program = argv[0]; + int nofile = 0; + ldns_rdf *origin = NULL; + ldns_status result = LDNS_STATUS_OK; + int sep_only = 1; + + alg = 0; + h = LDNS_SHA1; + + argv++, argc--; + while (argc && argv[0][0] == '-') { + if (strcmp(argv[0], "-1") == 0) { + h = LDNS_SHA1; + similar_hash = 0; + } + if (strcmp(argv[0], "-2") == 0) { + h = LDNS_SHA256; + similar_hash = 0; + } +#ifdef USE_GOST + if (strcmp(argv[0], "-g") == 0) { + if(!ldns_key_EVP_load_gost_id()) { + fprintf(stderr, "error: libcrypto does not provide GOST\n"); + exit(EXIT_FAILURE); + } + h = LDNS_HASH_GOST; + similar_hash = 0; + } +#endif +#ifdef USE_ECDSA + if (strcmp(argv[0], "-4") == 0) { + h = LDNS_SHA384; + similar_hash = 0; + } +#endif + if (strcmp(argv[0], "-f") == 0) { + sep_only = 0; + } + if (strcmp(argv[0], "-n") == 0) { + nofile=1; + } + argv++, argc--; + } + + if (argc != 1) { + usage(stderr, program); + exit(EXIT_FAILURE); + } + keyname = strdup(argv[0]); + + keyfp = fopen(keyname, "r"); + if (!keyfp) { + fprintf(stderr, "Failed to open public key file %s: %s\n", keyname, + strerror(errno)); + exit(EXIT_FAILURE); + } + + while (result == LDNS_STATUS_OK) { + result = ldns_rr_new_frm_fp(&k, keyfp, 0, &origin, NULL); + while (result == LDNS_STATUS_SYNTAX_ORIGIN || + result == LDNS_STATUS_SYNTAX_TTL || + (result == LDNS_STATUS_OK && !is_suitable_dnskey(k, sep_only)) + ) { + if (result == LDNS_STATUS_OK) { + ldns_rr_free(k); + } + result = ldns_rr_new_frm_fp(&k, keyfp, 0, &origin, NULL); + } + if (result == LDNS_STATUS_SYNTAX_EMPTY) { + /* we're done */ + break; + } + if (result != LDNS_STATUS_OK) { + fprintf(stderr, "Could not read public key from file %s: %s\n", keyname, ldns_get_errorstr_by_id(result)); + exit(EXIT_FAILURE); + } + + owner = ldns_rdf2str(ldns_rr_owner(k)); + alg = ldns_rdf2native_int8(ldns_rr_dnskey_algorithm(k)); + if(similar_hash) + h = suitable_hash(alg); + + ds = ldns_key_rr2ds(k, h); + if (!ds) { + fprintf(stderr, "Conversion to a DS RR failed\n"); + ldns_rr_free(k); + free(owner); + exit(EXIT_FAILURE); + } + + /* print the public key RR to .key */ + dsname = LDNS_XMALLOC(char, strlen(owner) + 16); + snprintf(dsname, strlen(owner) + 15, "K%s+%03u+%05u.ds", owner, alg, (unsigned int) ldns_calc_keytag(k)); + + if (nofile) + ldns_rr_print(stdout,ds); + else { + dsfp = fopen(dsname, "w"); + if (!dsfp) { + fprintf(stderr, "Unable to open %s: %s\n", dsname, strerror(errno)); + exit(EXIT_FAILURE); + } else { + ldns_rr_print(dsfp, ds); + fclose(dsfp); + fprintf(stdout, "K%s+%03u+%05u\n", owner, alg, (unsigned int) ldns_calc_keytag(k)); + } + } + + ldns_rr_free(ds); + ldns_rr_free(k); + free(owner); + LDNS_FREE(dsname); + } + fclose(keyfp); + free(keyname); + exit(EXIT_SUCCESS); +} diff --git a/examples/ldns-keyfetcher.1 b/examples/ldns-keyfetcher.1 new file mode 100644 index 00000000000..6ddc14eacf8 --- /dev/null +++ b/examples/ldns-keyfetcher.1 @@ -0,0 +1,64 @@ +.TH ldns-keyfetcher 1 "4 Apr 2006" +.SH NAME +ldns-keyfetcher \- retrieve the DNSSEC DNSKEYs for a zone +.SH SYNOPSIS +.B ldns-keyfetcher +[ +.IR OPTIONS +] +.IR DOMAIN + +.SH DESCRIPTION +\fBldns-keyfetcher\fR is used to retrieve the DNSKEYs of a zone. + +First it finds all authoritative nameservers of the zone by tracing it from +the root down. All authoritative nameservers are then queried (using TCP) +for the DNSKEY RRset of the zone apex. If the results are all the same, +the key resource record set is printed. + + +.SH OPTIONS +\fB-4\fR \fI\fR +Only use IPv4 + +\fB-6\fR \fI\fR +Only use IPv6 + +\fB-h\fR \fI\fR +Show a help text and exit + +\fB-i\fR +Insecurer mode; there will only be one query for the DNSKEYS. There will not +be crosschecking of all authoritative nameservers. + +\fB-v\fR \fIverbosity\fR + +Set the verbosity level. The following levels are available: + + 0: default, only print the DNSKEY RRset found, or an error on failure. + 1: Show the nameservers that are queried + 2: Show more info on what is checked + 3: Show the intermediate results (authority and dnskey rrsets) + 4: Print the answer packets that are returned + +\fB-r\fR \fIfile\fR + +Use file as the root hints file, should contain A records in presentation +format. The default is /etc/named.root. You can get this file from +http://www.internic.net/zones/named.root. + +\fB-s\fR \fI\fR +Don't print the keys to stdout, but store them in files. + +The filenames will be of the format K.+.+.key + +.SH AUTHOR +Written by Jelte Jansen for NLnet Labs. + +.SH REPORTING BUGS +Report bugs to . + +.SH COPYRIGHT +Copyright (C) 2006 NLnet Labs. This is free software. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. diff --git a/examples/ldns-keyfetcher.c b/examples/ldns-keyfetcher.c new file mode 100644 index 00000000000..267822f8868 --- /dev/null +++ b/examples/ldns-keyfetcher.c @@ -0,0 +1,722 @@ +/* + * ldns-keyfetcher retrieves the DNSKEYS for a certain domain + * It traces the authoritatives nameservers down from the root + * And uses TCP, to minimize spoofing danger. + * + * (c) NLnet Labs, 2006 - 2008 + * See the file LICENSE for the license + */ + +#include "config.h" +#include +#include + +int verbosity = 0; +/* 0=use both ip4 and ip6 (default). 1=ip4only. 2=ip6only. */ +uint8_t address_family = 0; +bool store_in_file = false; + +static void +usage(FILE *fp, char *prog) { + fprintf(fp, "%s domain\n", prog); + fprintf(fp, " retrieve the dnskeys for a domain\n"); + fprintf(fp, "Options:\n"); + fprintf(fp, "-4\t\tUse IPv4 only\n"); + fprintf(fp, "-6\t\tUse IPv6 only\n"); + fprintf(fp, "-h\t\tShow this help\n"); + fprintf(fp, "-i\t\tInsecurer mode; don't do checks, just query for the keys\n"); + fprintf(fp, "-r \tUse file to read root hints from\n"); + fprintf(fp, "-s\t\tDon't print the keys but store them in files\n\t\tcalled K.+.+.key\n"); + fprintf(fp, "-v \tVerbosity level (0-5, not verbose-very verbose)\n"); +} + +static ldns_rr_list * +retrieve_dnskeys(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t, + ldns_rr_class c, ldns_rr_list *dns_root) +{ + ldns_resolver *res; + ldns_pkt *p; + ldns_rr_list *new_nss_a; + ldns_rr_list *new_nss_aaaa; + ldns_rr_list *new_nss; + ldns_rr_list *ns_addr; + ldns_rr_list *ns_addr2; + uint16_t loop_count; + ldns_rdf *pop; + ldns_status status; + size_t i; + + size_t nss_i; + ldns_rr_list *answer_list = NULL; + ldns_rr_list *authority_list = NULL; + + size_t last_nameserver_count; + ldns_rdf **last_nameservers; + + loop_count = 0; + new_nss_a = NULL; + new_nss_aaaa = NULL; + new_nss = NULL; + ns_addr = NULL; + ns_addr2 = NULL; + p = ldns_pkt_new(); + res = ldns_resolver_new(); + + if (!p || !res) { + fprintf(stderr, "Memory allocation failed"); + return NULL; + } + + if (verbosity >= 2) { + printf("Finding dnskey data for zone: "); + ldns_rdf_print(stdout, name); + printf("\n\n"); + } + + /* transfer some properties of local_res to res, + * because they were given on the commandline */ + ldns_resolver_set_ip6(res, + ldns_resolver_ip6(local_res)); + ldns_resolver_set_port(res, + ldns_resolver_port(local_res)); + ldns_resolver_set_debug(res, + ldns_resolver_debug(local_res)); + ldns_resolver_set_dnssec(res, + ldns_resolver_dnssec(local_res)); + ldns_resolver_set_fail(res, + ldns_resolver_fail(local_res)); + ldns_resolver_set_usevc(res, + ldns_resolver_usevc(local_res)); + ldns_resolver_set_random(res, + ldns_resolver_random(local_res)); + ldns_resolver_set_recursive(res, false); + + /* setup the root nameserver in the new resolver */ + status = ldns_resolver_push_nameserver_rr_list(res, dns_root); + if (status != LDNS_STATUS_OK) { + fprintf(stderr, "Error setting root nameservers in resolver: %s\n", ldns_get_errorstr_by_id(status)); + return NULL; + } + + ldns_pkt_free(p); + status = ldns_resolver_send(&p, res, name, t, c, 0); + if (status != LDNS_STATUS_OK) { + fprintf(stderr, "Error querying root servers: %s\n", ldns_get_errorstr_by_id(status)); + return NULL; + } + + if (ldns_pkt_get_rcode(p) != LDNS_RCODE_NOERROR) { + printf("Error in packet:\n"); + ldns_pkt_print(stdout, p); + return NULL; + } + + if (verbosity >= 4) { + ldns_pkt_print(stdout, p); + printf("\n\n"); + } + + /* from now on, use TCP */ + ldns_resolver_set_usevc(res, true); + + while(status == LDNS_STATUS_OK && + ldns_pkt_reply_type(p) == LDNS_PACKET_REFERRAL) { + + if (verbosity >= 3) { + printf("This is a delegation!\n\n"); + } + if (address_family == 0 || address_family == 1) { + new_nss_a = ldns_pkt_rr_list_by_type(p, + LDNS_RR_TYPE_A, LDNS_SECTION_ADDITIONAL); + } else { + new_nss_a = ldns_rr_list_new(); + } + if (address_family == 0 || address_family == 2) { + new_nss_aaaa = ldns_pkt_rr_list_by_type(p, + LDNS_RR_TYPE_AAAA, LDNS_SECTION_ADDITIONAL); + } else { + new_nss_aaaa = ldns_rr_list_new(); + } + new_nss = ldns_pkt_rr_list_by_type(p, + LDNS_RR_TYPE_NS, LDNS_SECTION_AUTHORITY); + + /* remove the old nameserver from the resolver */ + while((pop = ldns_resolver_pop_nameserver(res))) { ldns_rdf_deep_free(pop); } + + /* also check for new_nss emptyness */ + + if (!new_nss_aaaa && !new_nss_a) { + /* + * no nameserver found!!! + * try to resolve the names we do got + */ + if (verbosity >= 3) { + printf("Did not get address record for nameserver, doing seperate query.\n"); + } + ns_addr = ldns_rr_list_new(); + for(i = 0; (size_t) i < ldns_rr_list_rr_count(new_nss); i++) { + /* get the name of the nameserver */ + pop = ldns_rr_rdf(ldns_rr_list_rr(new_nss, i), 0); + if (!pop) { + break; + } + + /* retrieve it's addresses */ + ns_addr2 = ldns_get_rr_list_addr_by_name(local_res, pop, c, 0); + if (!ldns_rr_list_cat(ns_addr, ns_addr2)) { + fprintf(stderr, "Internal error adding nameserver address.\n"); + exit(EXIT_FAILURE); + } + ldns_rr_list_free(ns_addr2); + } + + if (ns_addr) { + if (ldns_resolver_push_nameserver_rr_list(res, ns_addr) != + LDNS_STATUS_OK) { + fprintf(stderr, "Error adding new nameservers"); + ldns_pkt_free(p); + return NULL; + } + ldns_rr_list_deep_free(ns_addr); + } else { + ldns_rr_list_print(stdout, ns_addr); + fprintf(stderr, "Could not find the nameserver ip addr; abort"); + ldns_pkt_free(p); + return NULL; + } + } + + /* normally, the first working ns is used, but we need all now, so do it one by one + * if the answer is null, take it from the next resolver + * if the answer is not, compare it to that of the next resolver + * error if different, continue if the same + * if answer list null and no resolvers left die. + */ + + ldns_rr_list_deep_free(answer_list); + ldns_rr_list_deep_free(authority_list); + answer_list = NULL; + authority_list = NULL; + for (nss_i = 0; nss_i < ldns_rr_list_rr_count(new_nss_aaaa); nss_i++) { + while((pop = ldns_resolver_pop_nameserver(res))) { ldns_rdf_deep_free(pop); } + + status = ldns_resolver_push_nameserver(res, ldns_rr_rdf(ldns_rr_list_rr(new_nss_aaaa, nss_i), 0)); + if (status != LDNS_STATUS_OK) { + fprintf(stderr, "Error adding nameserver to resolver: %s\n", ldns_get_errorstr_by_id(status)); + } + + if (verbosity >= 1) { + fprintf(stdout, "Querying nameserver: "); + ldns_rdf_print(stdout, ldns_rr_owner(ldns_rr_list_rr(new_nss_aaaa, nss_i))); + fprintf(stdout, " ("); + ldns_rdf_print(stdout, ldns_rr_rdf(ldns_rr_list_rr(new_nss_aaaa, nss_i), 0)); + fprintf(stdout, ")\n"); + } + status = ldns_resolver_push_nameserver(res, ldns_rr_rdf(ldns_rr_list_rr(new_nss_aaaa, nss_i), 0)); + if (status != LDNS_STATUS_OK) { + fprintf(stderr, "Error adding nameserver to resolver: %s\n", ldns_get_errorstr_by_id(status)); + } + + ldns_pkt_free(p); + status = ldns_resolver_send(&p, res, name, t, c, 0); + if (status == LDNS_STATUS_OK && p) { + if (ldns_pkt_get_rcode(p) != LDNS_RCODE_NOERROR) { + printf("Error in packet:\n"); + ldns_pkt_print(stdout, p); + return NULL; + } + + if (verbosity >= 4) { + ldns_pkt_print(stdout, p); + printf("\n\n"); + } + + if (answer_list) { + if (verbosity >= 2) { + printf("Comparing answer list of answer to previous\n\n"); + } + ldns_rr_list_sort(ldns_pkt_answer(p)); + ldns_rr_list_sort(answer_list); + if (ldns_rr_list_compare(answer_list, ldns_pkt_answer(p)) != 0) { + fprintf(stderr, "ERROR: different answer answer from nameserver\n"); + fprintf(stderr, "\nI had (from previous servers):\n"); + ldns_rr_list_print(stderr, answer_list); + fprintf(stderr, "\nI received (from nameserver at "); + ldns_rdf_print(stderr, ldns_resolver_nameservers(res)[0]); + fprintf(stderr, "):\n"); + ldns_rr_list_print(stderr, ldns_pkt_answer(p)); + exit(EXIT_FAILURE); + } + } else { + answer_list = ldns_rr_list_clone(ldns_pkt_answer(p)); + ldns_rr_list_sort(answer_list); + if (verbosity >= 2) { + printf("First answer list for this set, nothing to compare with\n\n"); + } + } + if (authority_list) { + if (verbosity >= 2) { + printf("Comparing authority list of answer to previous\n\n"); + } + ldns_rr_list_sort(ldns_pkt_authority(p)); + ldns_rr_list_sort(authority_list); + if (ldns_rr_list_compare(authority_list, ldns_pkt_authority(p)) != 0) { + fprintf(stderr, "ERROR: different authority answer from nameserver\n"); + fprintf(stderr, "\nI had (from previous servers):\n"); + ldns_rr_list_print(stderr, authority_list); + fprintf(stderr, "\nI received (from nameserver at "); + ldns_rdf_print(stderr, ldns_resolver_nameservers(res)[0]); + fprintf(stderr, "):\n"); + ldns_rr_list_print(stderr, ldns_pkt_authority(p)); + exit(EXIT_FAILURE); + } + } else { + authority_list = ldns_rr_list_clone(ldns_pkt_authority(p)); + ldns_rr_list_sort(authority_list); + if (verbosity >= 2) { + printf("First authority list for this set, nothing to compare with\n\n"); + } + if (verbosity >= 3) { + printf("NS RRset:\n"); + ldns_rr_list_print(stdout, authority_list); + printf("\n"); + } + } + } + } + + ldns_rr_list_deep_free(answer_list); + ldns_rr_list_deep_free(authority_list); + answer_list = NULL; + authority_list = NULL; + for (nss_i = 0; nss_i < ldns_rr_list_rr_count(new_nss_a); nss_i++) { + + while((pop = ldns_resolver_pop_nameserver(res))) {ldns_rdf_deep_free(pop); } + + if (verbosity >= 1) { + fprintf(stdout, "Querying nameserver: "); + ldns_rdf_print(stdout, ldns_rr_owner(ldns_rr_list_rr(new_nss_a, nss_i))); + fprintf(stdout, " ("); + ldns_rdf_print(stdout, ldns_rr_rdf(ldns_rr_list_rr(new_nss_a, nss_i), 0)); + fprintf(stdout, ")\n"); + } + status = ldns_resolver_push_nameserver(res, ldns_rr_rdf(ldns_rr_list_rr(new_nss_a, nss_i), 0)); + if (status != LDNS_STATUS_OK) { + fprintf(stderr, "Error adding nameserver to resolver: %s\n", ldns_get_errorstr_by_id(status)); + } + + ldns_pkt_free(p); + status = ldns_resolver_send(&p, res, name, t, c, 0); + + if (status == LDNS_STATUS_OK) { + if (ldns_pkt_get_rcode(p) != LDNS_RCODE_NOERROR) { + printf("Error in packet:\n"); + ldns_pkt_print(stdout, p); + return NULL; + } + + if (verbosity >= 4) { + ldns_pkt_print(stdout, p); + printf("\n\n"); + } + + if (answer_list) { + if (verbosity >= 2) { + printf("Comparing answer list of answer to previous\n\n"); + } + ldns_rr_list_sort(ldns_pkt_answer(p)); + ldns_rr_list_sort(answer_list); + if (ldns_rr_list_compare(answer_list, ldns_pkt_answer(p)) != 0) { + fprintf(stderr, "ERROR: different answer answer from nameserver\n"); + fprintf(stderr, "\nI had (from previous servers):\n"); + ldns_rr_list_print(stderr, answer_list); + fprintf(stderr, "\nI received (from nameserver at "); + ldns_rdf_print(stderr, ldns_resolver_nameservers(res)[0]); + fprintf(stderr, "):\n"); + ldns_rr_list_print(stderr, ldns_pkt_answer(p)); + exit(EXIT_FAILURE); + } + } else { + if (verbosity >= 2) { + printf("First answer list for this set, nothing to compare with\n\n"); + } + answer_list = ldns_rr_list_clone(ldns_pkt_answer(p)); + ldns_rr_list_sort(answer_list); + } + if (authority_list) { + if (verbosity >= 2) { + printf("Comparing authority list of answer to previous\n\n"); + } + ldns_rr_list_sort(ldns_pkt_authority(p)); + ldns_rr_list_sort(authority_list); + if (ldns_rr_list_compare(authority_list, ldns_pkt_authority(p)) != 0) { + fprintf(stderr, "ERROR: different authority answer from nameserver\n"); + fprintf(stderr, "\nI had (from previous servers):\n"); + ldns_rr_list_print(stderr, authority_list); + fprintf(stderr, "\nI received (from nameserver at "); + ldns_rdf_print(stderr, ldns_resolver_nameservers(res)[0]); + fprintf(stderr, "):\n"); + ldns_rr_list_print(stderr, ldns_pkt_authority(p)); + exit(EXIT_FAILURE); + } + } else { + if (verbosity >= 2) { + printf("First authority list for this set, nothing to compare with\n\n"); + } + authority_list = ldns_rr_list_clone(ldns_pkt_authority(p)); + ldns_rr_list_sort(authority_list); + if (verbosity >= 3) { + printf("NS RRset:\n"); + ldns_rr_list_print(stdout, authority_list); + printf("\n"); + } + } + } + } + ldns_rr_list_deep_free(authority_list); + authority_list = NULL; + + if (loop_count++ > 20) { + /* unlikely that we are doing something usefull */ + fprintf(stderr, "Looks like we are looping"); + ldns_pkt_free(p); + return NULL; + } + + ldns_pkt_free(p); + + if (verbosity >= 3) { + fprintf(stdout, "This level ok. Continuing to next.\n\n"); + } + + status = ldns_resolver_send(&p, res, name, t, c, 0); + + if (status != LDNS_STATUS_OK) { + fprintf(stderr, "Error querying root servers: %s\n", ldns_get_errorstr_by_id(status)); + return NULL; + } + + if (ldns_pkt_get_rcode(p) != LDNS_RCODE_NOERROR) { + printf("Error in packet:\n"); + ldns_pkt_print(stdout, p); + return NULL; + } + + if (verbosity >= 4) { + ldns_pkt_print(stdout, p); + printf("\n\n"); + } + + + ldns_rr_list_deep_free(new_nss_aaaa); + ldns_rr_list_deep_free(new_nss_a); + ldns_rr_list_deep_free(new_nss); + new_nss_aaaa = NULL; + new_nss_a = NULL; + ns_addr = NULL; + } + + ldns_rr_list_deep_free(answer_list); + answer_list = NULL; + /* clone the nameserver list, we are going to handle them one by one */ + last_nameserver_count = 0; + last_nameservers = LDNS_XMALLOC(ldns_rdf *, ldns_resolver_nameserver_count(res)); + + pop = NULL; + while((pop = ldns_resolver_pop_nameserver(res))) { + last_nameservers[last_nameserver_count] = pop; + last_nameserver_count++; + } + + for (nss_i = 0; nss_i < last_nameserver_count; nss_i++) { + /* remove previous nameserver */ + while((pop = ldns_resolver_pop_nameserver(res))) { ldns_rdf_deep_free(pop); } + + if (verbosity >= 1) { + printf("Querying nameserver: "); + ldns_rdf_print(stdout, last_nameservers[nss_i]); + printf("\n"); + } + status = ldns_resolver_push_nameserver(res, last_nameservers[nss_i]); + if (status != LDNS_STATUS_OK) { + fprintf(stderr, "Error adding nameserver to resolver: %s\n", ldns_get_errorstr_by_id(status)); + } + + ldns_pkt_free(p); + status = ldns_resolver_send(&p, res, name, t, c, 0); + + if (!p) { + fprintf(stderr, "no packet received\n"); + return NULL; + } + + if (status == LDNS_STATUS_RES_NO_NS) { + fprintf(stderr, "Error: nameserver at "); + ldns_rdf_print(stderr, last_nameservers[nss_i]); + fprintf(stderr, " not responding. Unable to check RRset here, aborting.\n"); + return NULL; + } + + if (ldns_pkt_get_rcode(p) != LDNS_RCODE_NOERROR) { + printf("Error in packet:\n"); + ldns_pkt_print(stdout, p); + return NULL; + } + + if (answer_list) { + if (verbosity >= 2) { + printf("1Comparing answer rr list of answer to previous\n"); + } + ldns_rr_list_sort(ldns_pkt_answer(p)); + ldns_rr_list_sort(answer_list); + if (ldns_rr_list_compare(answer_list, ldns_pkt_answer(p)) != 0) { + printf("ERROR: different answer section in response from nameserver\n"); + fprintf(stderr, "\nI had:\n"); + ldns_rr_list_print(stderr, answer_list); + fprintf(stderr, "\nI received (from nameserver at "); + ldns_rdf_print(stderr, ldns_resolver_nameservers(res)[0]); + fprintf(stderr, "):\n"); + ldns_rr_list_print(stderr, ldns_pkt_answer(p)); + exit(EXIT_FAILURE); + } + } else { + if (verbosity >= 2) { + printf("First answer rr list for this set, nothing to compare with\n"); + } + answer_list = ldns_rr_list_clone(ldns_pkt_answer(p)); + if (verbosity >= 3) { + printf("DNSKEY RRset:\n"); + ldns_rr_list_print(stdout, answer_list); + } + } + + } + + for (nss_i = 0; nss_i < last_nameserver_count; nss_i++) { + ldns_rdf_deep_free(last_nameservers[nss_i]); + } + LDNS_FREE(last_nameservers); + ldns_resolver_deep_free(res); + ldns_pkt_free(p); + return answer_list; +} + + +/* + * The file with the given path should contain a list of NS RRs + * for the root zone and A records for those NS RRs. + * Read them, check them, and append the a records to the rr list given. + */ +ldns_rr_list * +read_root_hints(const char *filename) +{ + FILE *fp = NULL; + int line_nr = 0; + ldns_zone *z; + ldns_status status; + ldns_rr_list *addresses = NULL; + ldns_rr *rr; + size_t i; + + fp = fopen(filename, "r"); + if (!fp) { + fprintf(stderr, "Unable to open %s for reading: %s\n", filename, strerror(errno)); + return NULL; + } + + status = ldns_zone_new_frm_fp_l(&z, fp, NULL, 0, 0, &line_nr); + fclose(fp); + if (status != LDNS_STATUS_OK) { + fprintf(stderr, "Error reading root hints file: %s\n", ldns_get_errorstr_by_id(status)); + return NULL; + } else { + addresses = ldns_rr_list_new(); + for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(z)); i++) { + rr = ldns_rr_list_rr(ldns_zone_rrs(z), i); + if ((address_family == 0 || address_family == 1) && + ldns_rr_get_type(rr) == LDNS_RR_TYPE_A ) { + ldns_rr_list_push_rr(addresses, ldns_rr_clone(rr)); + } + if ((address_family == 0 || address_family == 2) && + ldns_rr_get_type(rr) == LDNS_RR_TYPE_AAAA) { + ldns_rr_list_push_rr(addresses, ldns_rr_clone(rr)); + } + } + ldns_zone_deep_free(z); + return addresses; + } +} + + +int +main(int argc, char *argv[]) +{ + ldns_resolver *res; + ldns_rdf *ns; + ldns_rdf *domain; + ldns_rr_list *l = NULL; + + ldns_rr_list *dns_root = NULL; + const char *root_file = "/etc/named.root"; + + ldns_status status; + + int i; + + char *domain_str; + char *outputfile_str; + ldns_buffer *outputfile_buffer; + FILE *outputfile; + ldns_rr *k; + + bool insecure = false; + ldns_pkt *pkt; + + domain = NULL; + res = NULL; + + if (argc < 2) { + usage(stdout, argv[0]); + exit(EXIT_FAILURE); + } else { + for (i = 1; i < argc; i++) { + if (strncmp("-4", argv[i], 3) == 0) { + if (address_family != 0) { + fprintf(stderr, "Options -4 and -6 cannot be specified at the same time\n"); + exit(EXIT_FAILURE); + } + address_family = 1; + } else if (strncmp("-6", argv[i], 3) == 0) { + if (address_family != 0) { + fprintf(stderr, "Options -4 and -6 cannot be specified at the same time\n"); + exit(EXIT_FAILURE); + } + address_family = 2; + } else if (strncmp("-h", argv[i], 3) == 0) { + usage(stdout, argv[0]); + exit(EXIT_SUCCESS); + } else if (strncmp("-i", argv[i], 2) == 0) { + insecure = true; + } else if (strncmp("-r", argv[i], 2) == 0) { + if (strlen(argv[i]) > 2) { + root_file = argv[i]+2; + } else if (i+1 >= argc) { + usage(stdout, argv[0]); + exit(EXIT_FAILURE); + } else { + root_file = argv[i+1]; + i++; + } + } else if (strncmp("-s", argv[i], 3) == 0) { + store_in_file = true; + } else if (strncmp("-v", argv[i], 2) == 0) { + if (strlen(argv[i]) > 2) { + verbosity = atoi(argv[i]+2); + } else if (i+1 > argc) { + usage(stdout, argv[0]); + exit(EXIT_FAILURE); + } else { + verbosity = atoi(argv[i+1]); + i++; + } + } else { + /* create a rdf from the command line arg */ + if (domain) { + fprintf(stdout, "You can only specify one domain at a time\n"); + exit(EXIT_FAILURE); + } + + domain = ldns_dname_new_frm_str(argv[i]); + } + + } + if (!domain) { + usage(stdout, argv[0]); + exit(EXIT_FAILURE); + } + } + + dns_root = read_root_hints(root_file); + if (!dns_root) { + fprintf(stderr, "cannot read the root hints file\n"); + exit(EXIT_FAILURE); + } + + /* create a new resolver from /etc/resolv.conf */ + status = ldns_resolver_new_frm_file(&res, NULL); + + if (status != LDNS_STATUS_OK) { + fprintf(stderr, "Warning: Unable to create stub resolver from /etc/resolv.conf:\n"); + fprintf(stderr, "%s\n", ldns_get_errorstr_by_id(status)); + fprintf(stderr, "defaulting to nameserver at 127.0.0.1 for separate nameserver name lookups\n"); + res = ldns_resolver_new(); + ns = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, "127.0.0.1"); + status = ldns_resolver_push_nameserver(res, ns); + if (status != LDNS_STATUS_OK) { + fprintf(stderr, "Unable to create stub resolver: %s\n", ldns_get_errorstr_by_id(status)); + exit(EXIT_FAILURE); + } + ldns_rdf_deep_free(ns); + } + + ldns_resolver_set_ip6(res, address_family); + + if (insecure) { + pkt = ldns_resolver_query(res, domain, LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN, LDNS_RD); + if (pkt) { + l = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_DNSKEY, LDNS_SECTION_ANY_NOQUESTION); + } + } else { + l = retrieve_dnskeys(res, domain, LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN, dns_root); + } + + /* separator for result data and verbosity data */ + if (verbosity > 0) { + fprintf(stdout, "; ---------------------------\n"); + fprintf(stdout, "; Got the following keys:\n"); + } + if (l) { + if (store_in_file) { + /* create filename: + * K.+.+.key + */ + for (i = 0; (size_t) i < ldns_rr_list_rr_count(l); i++) { + k = ldns_rr_list_rr(l, (size_t) i); + + outputfile_buffer = ldns_buffer_new(300); + domain_str = ldns_rdf2str(ldns_rr_owner(k)); + ldns_buffer_printf(outputfile_buffer, "K%s+%03u+%05u.key", domain_str, ldns_rdf2native_int8(ldns_rr_rdf(k, 2)), + (unsigned int) ldns_calc_keytag(k)); + outputfile_str = ldns_buffer_export(outputfile_buffer); + + if (verbosity >= 1) { + fprintf(stdout, "Writing key to file %s\n", outputfile_str); + } + + outputfile = fopen(outputfile_str, "w"); + if (!outputfile) { + fprintf(stderr, "Error writing key to file %s: %s\n", outputfile_str, strerror(errno)); + } else { + ldns_rr_print(outputfile, k); + fclose(outputfile); + } + + LDNS_FREE(domain_str); + LDNS_FREE(outputfile_str); + LDNS_FREE(outputfile_buffer); + } + } else { + ldns_rr_list_print(stdout, l); + } + } else { + fprintf(stderr, "no answer packet received, stub resolver config:\n"); + ldns_resolver_print(stderr, res); + } + printf("\n"); + + ldns_rdf_deep_free(domain); + ldns_resolver_deep_free(res); + ldns_rr_list_deep_free(l); + ldns_rr_list_deep_free(dns_root); + return EXIT_SUCCESS; +} diff --git a/examples/ldns-keygen.1 b/examples/ldns-keygen.1 new file mode 100644 index 00000000000..36124d52a47 --- /dev/null +++ b/examples/ldns-keygen.1 @@ -0,0 +1,53 @@ +.TH ldns-keygen 1 "27 May 2008" +.SH NAME +ldns-keygen \- generate a DNSSEC key pair +.SH SYNOPSIS +.B ldns-keygen +[ +.IR OPTION +] +.IR DOMAIN + +.SH DESCRIPTION +\fBldns-keygen\fR is used to generate a private/public keypair. When run, it +will create 3 files; a .key file with the public DNSKEY, a .private +file with the private keydata and a .ds with the DS record of the +DNSKEY record. + +It prints out the basename for these files: K++ + +.SH OPTIONS +.TP +\fB-a \fI\fR +Create a key with this algorithm. Specifying 'list' here gives a list of supported algorithms. +Several alias names are also accepted (from older versions and other software), +the list gives names from the RFC. Also the plain algo number is accepted. + +.TP +\fB-b \fI\fR +Use this many bits for the key length. + +.TP +\fB-k\fR +When given, generate a key signing key. This just sets the flag field to +257 instead of 256 in the DNSKEY RR in the .key file. + +.TP +\fB-r \fIdevice\fR +Make ldns-keygen use this file to seed the random generator with. This will +default to /dev/random. + +.TP +\fB-v\fR +Show the version and exit + +.SH AUTHOR +Written by the ldns team as an example for ldns usage. + +.SH REPORTING BUGS +Report bugs to . + +.SH COPYRIGHT +Copyright (C) 2005-2008 NLnet Labs. This is free software. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. diff --git a/examples/ldns-keygen.c b/examples/ldns-keygen.c new file mode 100644 index 00000000000..576541790c9 --- /dev/null +++ b/examples/ldns-keygen.c @@ -0,0 +1,307 @@ +/* + * keygen is a small programs that generate a dnskey and private key + * for a particular domain. + * + * (c) NLnet Labs, 2005 - 2008 + * See the file LICENSE for the license + */ + +#include "config.h" + +#include + +#include + +#ifdef HAVE_SSL +static void +usage(FILE *fp, char *prog) { + fprintf(fp, "%s -a [-b bits] [-r /dev/random] [-v] domain\n", + prog); + fprintf(fp, " generate a new key pair for domain\n"); + fprintf(fp, " -a \tuse the specified algorithm (-a list to"); + fprintf(fp, " show a list)\n"); + fprintf(fp, " -k\t\tset the flags to 257; key signing key\n"); + fprintf(fp, " -b \tspecify the keylength\n"); + fprintf(fp, " -r \tspecify a random device (defaults to /dev/random)\n"); + fprintf(fp, "\t\tto seed the random generator with\n"); + fprintf(fp, " -v\t\tshow the version and exit\n"); + fprintf(fp, " The following files will be created:\n"); + fprintf(fp, " K++.key\tPublic key in RR format\n"); + fprintf(fp, " K++.private\tPrivate key in key format\n"); + fprintf(fp, " K++.ds\tDS in RR format (only for DNSSEC keys)\n"); + fprintf(fp, " The base name (K++ will be printed to stdout\n"); +} + +static void +show_algorithms(FILE *out) +{ + ldns_lookup_table *lt = ldns_signing_algorithms; + fprintf(out, "Possible algorithms:\n"); + + while (lt->name) { + fprintf(out, "%s\n", lt->name); + lt++; + } +} + +int +main(int argc, char *argv[]) +{ + int c; + char *prog; + + /* default key size */ + uint16_t def_bits = 1024; + uint16_t bits = def_bits; + bool ksk; + + FILE *file; + FILE *random; + char *filename; + char *owner; + + ldns_signing_algorithm algorithm; + ldns_rdf *domain; + ldns_rr *pubkey; + ldns_key *key; + ldns_rr *ds; + + prog = strdup(argv[0]); + algorithm = 0; + random = NULL; + ksk = false; /* don't create a ksk per default */ + + while ((c = getopt(argc, argv, "a:kb:r:v25")) != -1) { + switch (c) { + case 'a': + if (algorithm != 0) { + fprintf(stderr, "The -a argument can only be used once\n"); + exit(1); + } + if (strncmp(optarg, "list", 5) == 0) { + show_algorithms(stdout); + exit(EXIT_SUCCESS); + } + algorithm = ldns_get_signing_algorithm_by_name(optarg); + if (algorithm == 0) { + fprintf(stderr, "Algorithm %s not found\n", optarg); + show_algorithms(stderr); + exit(EXIT_FAILURE); + } + break; + case 'b': + bits = (uint16_t) atoi(optarg); + if (bits == 0) { + fprintf(stderr, "%s: %s %d", prog, "Can not parse the -b argument, setting it to the default\n", (int) def_bits); + bits = def_bits; + } + break; + case 'k': + ksk = true; + break; + case 'r': + random = fopen(optarg, "r"); + if (!random) { + fprintf(stderr, "Cannot open random file %s: %s\n", optarg, strerror(errno)); + exit(EXIT_FAILURE); + } + break; + case 'v': + printf("DNSSEC key generator version %s (ldns version %s)\n", LDNS_VERSION, ldns_version()); + exit(EXIT_SUCCESS); + break; + default: + usage(stderr, prog); + exit(EXIT_FAILURE); + } + } + argc -= optind; + argv += optind; + + if (algorithm == 0) { + printf("Please use the -a argument to provide an algorithm\n"); + exit(1); + } + + if (argc != 1) { + usage(stderr, prog); + exit(EXIT_FAILURE); + } + free(prog); + + /* check whether key size is within RFC boundaries */ + switch (algorithm) { + case LDNS_SIGN_RSAMD5: + case LDNS_SIGN_RSASHA1: + if (bits < 512 || bits > 4096) { + fprintf(stderr, "For RSA, the key size must be between "); + fprintf(stderr, " 512 and 4096 bytes. Aborting.\n"); + exit(1); + } + break; + case LDNS_SIGN_DSA: + if (bits < 512 || bits > 4096) { + fprintf(stderr, "For DSA, the key size must be between "); + fprintf(stderr, " 512 and 1024 bytes. Aborting.\n"); + exit(1); + } + break; +#ifdef USE_GOST + case LDNS_SIGN_ECC_GOST: + if(!ldns_key_EVP_load_gost_id()) { + fprintf(stderr, "error: libcrypto does not provide GOST\n"); + exit(EXIT_FAILURE); + } + break; +#endif +#ifdef USE_ECDSA + case LDNS_SIGN_ECDSAP256SHA256: + case LDNS_SIGN_ECDSAP384SHA384: +#endif + case LDNS_SIGN_HMACMD5: + case LDNS_SIGN_HMACSHA1: + case LDNS_SIGN_HMACSHA256: + default: + break; + } + + if (!random) { + random = fopen("/dev/random", "r"); + if (!random) { + fprintf(stderr, "Cannot open random file %s: %s\n", optarg, strerror(errno)); + exit(EXIT_FAILURE); + } + } + + (void)ldns_init_random(random, (unsigned int) bits/8); + fclose(random); + + /* create an rdf from the domain name */ + domain = ldns_dname_new_frm_str(argv[0]); + + /* generate a new key */ + key = ldns_key_new_frm_algorithm(algorithm, bits); + + /* set the owner name in the key - this is a /seperate/ step */ + ldns_key_set_pubkey_owner(key, domain); + + /* ksk flag */ + if (ksk) { + ldns_key_set_flags(key, ldns_key_flags(key) + 1); + } + + /* create the public from the ldns_key */ + pubkey = ldns_key2rr(key); + if (!pubkey) { + fprintf(stderr, "Could not extract the public key from the key structure..."); + ldns_key_deep_free(key); + exit(EXIT_FAILURE); + } + owner = ldns_rdf2str(ldns_rr_owner(pubkey)); + + /* calculate and set the keytag */ + ldns_key_set_keytag(key, ldns_calc_keytag(pubkey)); + + /* build the DS record */ + switch (algorithm) { +#ifdef USE_ECDSA + case LDNS_SIGN_ECDSAP384SHA384: + ds = ldns_key_rr2ds(pubkey, LDNS_SHA384); + break; + case LDNS_SIGN_ECDSAP256SHA256: +#endif + case LDNS_SIGN_RSASHA256: + case LDNS_SIGN_RSASHA512: + ds = ldns_key_rr2ds(pubkey, LDNS_SHA256); + break; + case LDNS_SIGN_ECC_GOST: +#ifdef USE_GOST + ds = ldns_key_rr2ds(pubkey, LDNS_HASH_GOST); +#else + ds = ldns_key_rr2ds(pubkey, LDNS_SHA256); +#endif + break; + default: + ds = ldns_key_rr2ds(pubkey, LDNS_SHA1); + break; + } + + /* print the public key RR to .key */ + filename = LDNS_XMALLOC(char, strlen(owner) + 17); + snprintf(filename, strlen(owner) + 16, "K%s+%03u+%05u.key", owner, algorithm, (unsigned int) ldns_key_keytag(key)); + file = fopen(filename, "w"); + if (!file) { + fprintf(stderr, "Unable to open %s: %s\n", filename, strerror(errno)); + ldns_key_deep_free(key); + free(owner); + ldns_rr_free(pubkey); + ldns_rr_free(ds); + LDNS_FREE(filename); + exit(EXIT_FAILURE); + } else { + /* temporarily set question so that TTL is not printed */ + ldns_rr_set_question(pubkey, true); + ldns_rr_print(file, pubkey); + ldns_rr_set_question(pubkey, false); + fclose(file); + LDNS_FREE(filename); + } + + /* print the priv key to stderr */ + filename = LDNS_XMALLOC(char, strlen(owner) + 21); + snprintf(filename, strlen(owner) + 20, "K%s+%03u+%05u.private", owner, algorithm, (unsigned int) ldns_key_keytag(key)); + file = fopen(filename, "w"); + if (!file) { + fprintf(stderr, "Unable to open %s: %s\n", filename, strerror(errno)); + ldns_key_deep_free(key); + free(owner); + ldns_rr_free(pubkey); + ldns_rr_free(ds); + LDNS_FREE(filename); + exit(EXIT_FAILURE); + } else { + ldns_key_print(file, key); + fclose(file); + LDNS_FREE(filename); + } + + /* print the DS to .ds */ + if (algorithm != LDNS_SIGN_HMACMD5 && + algorithm != LDNS_SIGN_HMACSHA1 && + algorithm != LDNS_SIGN_HMACSHA256) { + filename = LDNS_XMALLOC(char, strlen(owner) + 16); + snprintf(filename, strlen(owner) + 15, "K%s+%03u+%05u.ds", owner, algorithm, (unsigned int) ldns_key_keytag(key)); + file = fopen(filename, "w"); + if (!file) { + fprintf(stderr, "Unable to open %s: %s\n", filename, strerror(errno)); + ldns_key_deep_free(key); + free(owner); + ldns_rr_free(pubkey); + ldns_rr_free(ds); + LDNS_FREE(filename); + exit(EXIT_FAILURE); + } else { + /* temporarily set question so that TTL is not printed */ + ldns_rr_set_question(ds, true); + ldns_rr_print(file, ds); + ldns_rr_set_question(ds, false); + fclose(file); + LDNS_FREE(filename); + } + } + + fprintf(stdout, "K%s+%03u+%05u\n", owner, algorithm, (unsigned int) ldns_key_keytag(key)); + ldns_key_deep_free(key); + free(owner); + ldns_rr_free(pubkey); + ldns_rr_free(ds); + exit(EXIT_SUCCESS); +} +#else +int +main(int argc, char **argv) +{ + fprintf(stderr, "ldns-keygen needs OpenSSL support, which has not been compiled in\n"); + return 1; +} +#endif /* HAVE_SSL */ diff --git a/examples/ldns-mx.1 b/examples/ldns-mx.1 new file mode 100644 index 00000000000..cad97abcd82 --- /dev/null +++ b/examples/ldns-mx.1 @@ -0,0 +1,23 @@ +.TH ldns-mx 1 "27 Apr 2005" +.SH NAME +ldns-mx \- print out the mx record(s) for a domain +.SH SYNOPSIS +.B ldns-mx +.IR DOMAIN + +.SH DESCRIPTION +\fBldns-mx\fR is used to print out mx information of a domain. + +.SH OPTIONS +\fBldns-mx\fR has no options. + +.SH AUTHOR +Written by the ldns team as an example for ldns usage. + +.SH REPORTING BUGS +Report bugs to . + +.SH COPYRIGHT +Copyright (C) 2005 NLnet Labs. This is free software. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. diff --git a/examples/ldns-mx.c b/examples/ldns-mx.c new file mode 100644 index 00000000000..873cf55f87d --- /dev/null +++ b/examples/ldns-mx.c @@ -0,0 +1,88 @@ +/* + * mx is a small program that prints out the mx records + * for a particular domain + * (c) NLnet Labs, 2005 - 2008 + * See the file LICENSE for the license + */ + +#include "config.h" + +#include + +static int +usage(FILE *fp, char *prog) { + fprintf(fp, "%s domain\n", prog); + fprintf(fp, " print out the mx for domain\n"); + return 0; +} + +int +main(int argc, char *argv[]) +{ + ldns_resolver *res; + ldns_rdf *domain; + ldns_pkt *p; + ldns_rr_list *mx; + ldns_status s; + + p = NULL; + mx = NULL; + domain = NULL; + res = NULL; + + if (argc != 2) { + usage(stdout, argv[0]); + exit(EXIT_FAILURE); + } else { + /* create a rdf from the command line arg */ + domain = ldns_dname_new_frm_str(argv[1]); + if (!domain) { + usage(stdout, argv[0]); + exit(EXIT_FAILURE); + } + } + + /* create a new resolver from /etc/resolv.conf */ + s = ldns_resolver_new_frm_file(&res, NULL); + + if (s != LDNS_STATUS_OK) { + exit(EXIT_FAILURE); + } + + /* use the resolver to send a query for the mx + * records of the domain given on the command line + */ + p = ldns_resolver_query(res, + domain, + LDNS_RR_TYPE_MX, + LDNS_RR_CLASS_IN, + LDNS_RD); + + ldns_rdf_deep_free(domain); + + if (!p) { + exit(EXIT_FAILURE); + } else { + /* retrieve the MX records from the answer section of that + * packet + */ + mx = ldns_pkt_rr_list_by_type(p, + LDNS_RR_TYPE_MX, + LDNS_SECTION_ANSWER); + if (!mx) { + fprintf(stderr, + " *** invalid answer name %s after MX query for %s\n", + argv[1], argv[1]); + ldns_pkt_free(p); + ldns_resolver_deep_free(res); + exit(EXIT_FAILURE); + } else { + ldns_rr_list_sort(mx); + ldns_rr_list_print(stdout, mx); + ldns_rr_list_deep_free(mx); + } + } + ldns_pkt_free(p); + ldns_resolver_deep_free(res); + return 0; +} diff --git a/examples/ldns-notify.1 b/examples/ldns-notify.1 new file mode 100644 index 00000000000..7ae77ac0465 --- /dev/null +++ b/examples/ldns-notify.1 @@ -0,0 +1,66 @@ +.TH ldns-notify 1 "9 Jan 2007" +.SH NAME +ldns-notify \- notify DNS servers that updates are available +.SH SYNOPSIS +.B ldns-notify +[options] +-z zone +.IR servers + +.SH DESCRIPTION + +\fBldns-notify\fR sends a NOTIFY message to DNS servers. This tells them +that an updated zone is available at the master servers. It can perform +TSIG signatures and it can add a SOA serial number of the updated zone. +If a server already has that serial number it will disregard the message. + +.SH OPTIONS +.TP +\fB-z zone\fR +The zone that is updated. + +.TP +\fB-h\fR +Show usage and exit + +.TP +\fB-v\fR +Show the version and exit + +.TP +\fB-s serial\fR +Append a SOA record indicating the serial number of the updated zone. + +.TP +\fB-p port\fR +Use port as destination port (default the DNS port 53) for the UDP packets. + +.TP +\fB-y key:data\fR +Use the given TSIG key and base64-data to sign the NOTIFY. Uses the +hmac-md5 algorithm. + +.TP +\fB-d\fR +Print verbose debug information. The query that is sent and the query +that is received. + +.TP +\fB-r num\fR +Specify the maximum number of retries before notify gives up trying to +send the UDP packet. + +.SH EXIT CODE +The program exits with a 0 exit code if all servers replied an +acknowledgement to the notify message, and a failure exit code otherwise. + +.SH AUTHOR +Written by the ldns team as an example for ldns usage. + +.SH REPORTING BUGS +Report bugs to . + +.SH COPYRIGHT +Copyright (C) 2005 NLnet Labs. This is free software. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. diff --git a/examples/ldns-notify.c b/examples/ldns-notify.c new file mode 100644 index 00000000000..018a716faad --- /dev/null +++ b/examples/ldns-notify.c @@ -0,0 +1,334 @@ +/* + * ldns-notify.c - ldns-notify(8) + * + * Copyright (c) 2001-2008, NLnet Labs, All right reserved + * + * See LICENSE for the license + * + * send a notify packet to a server + */ + +#include "config.h" + +/* ldns */ +#include + +#ifdef HAVE_NETDB_H +#include +#endif +#include + +static int verbose = 1; +static int max_num_retry = 15; /* times to try */ + +static void +usage(void) +{ + fprintf(stderr, "usage: ldns-notify [other options] -z zone \n"); + fprintf(stderr, "Ldns notify utility\n\n"); + fprintf(stderr, " Supported options:\n"); + fprintf(stderr, "\t-z zone\t\tThe zone\n"); + fprintf(stderr, "\t-s version\tSOA version number to include\n"); + fprintf(stderr, "\t-y key:data\tTSIG sign the query\n"); + fprintf(stderr, "\t-p port\t\tport to use to send to\n"); + fprintf(stderr, "\t-v\t\tPrint version information\n"); + fprintf(stderr, "\t-d\t\tPrint verbose debug information\n"); + fprintf(stderr, "\t-r num\t\tmax number of retries (%d)\n", + max_num_retry); + fprintf(stderr, "\t-h\t\tPrint this help information\n\n"); + fprintf(stderr, "Report bugs to \n"); + exit(1); +} + +static void +version(void) +{ + fprintf(stderr, "%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION); + fprintf(stderr, "Written by NLnet Labs.\n\n"); + fprintf(stderr, + "Copyright (C) 2001-2008 NLnet Labs. This is free software.\n" + "There is NO warranty; not even for MERCHANTABILITY or FITNESS\n" + "FOR A PARTICULAR PURPOSE.\n"); + exit(0); +} + +static void +notify_host(int s, struct addrinfo* res, uint8_t* wire, size_t wiresize, + const char* addrstr) +{ + int timeout_retry = 5; /* seconds */ + int num_retry = max_num_retry; +#ifndef S_SPLINT_S + fd_set rfds; +#endif + struct timeval tv; + int retval = 0; + ssize_t received = 0; + int got_ack = 0; + socklen_t addrlen = 0; + uint8_t replybuf[2048]; + ldns_status status; + ldns_pkt* pkt = NULL; + + while(!got_ack) { + /* send it */ + if(sendto(s, (void*)wire, wiresize, 0, + res->ai_addr, res->ai_addrlen) == -1) { + printf("warning: send to %s failed: %s\n", + addrstr, strerror(errno)); +#ifndef USE_WINSOCK + close(s); +#else + closesocket(s); +#endif + return; + } + + /* wait for ACK packet */ +#ifndef S_SPLINT_S + FD_ZERO(&rfds); + FD_SET(s, &rfds); + tv.tv_sec = timeout_retry; /* seconds */ +#endif + tv.tv_usec = 0; /* microseconds */ + retval = select(s + 1, &rfds, NULL, NULL, &tv); + if (retval == -1) { + printf("error waiting for reply from %s: %s\n", + addrstr, strerror(errno)); +#ifndef USE_WINSOCK + close(s); +#else + closesocket(s); +#endif + return; + } + if(retval == 0) { + num_retry--; + if(num_retry == 0) { + printf("error: failed to send notify to %s.\n", + addrstr); + exit(1); + } + printf("timeout (%d s) expired, retry notify to %s.\n", + timeout_retry, addrstr); + } + if (retval == 1) { + got_ack = 1; + } + } + + /* got reply */ + addrlen = res->ai_addrlen; + received = recvfrom(s, (void*)replybuf, sizeof(replybuf), 0, + res->ai_addr, &addrlen); + res->ai_addrlen = addrlen; + +#ifndef USE_WINSOCK + close(s); +#else + closesocket(s); +#endif + if (received == -1) { + printf("recv %s failed: %s\n", addrstr, strerror(errno)); + return; + } + + /* check reply */ + status = ldns_wire2pkt(&pkt, replybuf, (size_t)received); + if(status != LDNS_STATUS_OK) { + ssize_t i; + printf("Could not parse reply packet: %s\n", + ldns_get_errorstr_by_id(status)); + if (verbose > 1) { + printf("hexdump of reply: "); + for(i=0; i 1) { + printf("hexdump of reply: "); + for(i=0; i 1) { + printf("Hexdump of notify packet:\n"); + for(i=0; i<(int)wiresize; i++) + printf("%02x", (unsigned)wire[i]); + printf("\n"); + } + + for(i=0; iai_next) { + int s = socket(res->ai_family, res->ai_socktype, + res->ai_protocol); + if(s == -1) + continue; + /* send the notify */ + notify_host(s, res, wire, wiresize, argv[i]); + } + freeaddrinfo(res0); + } + + ldns_pkt_free(notify); + free(wire); + return 0; +} diff --git a/examples/ldns-nsec3-hash.1 b/examples/ldns-nsec3-hash.1 new file mode 100644 index 00000000000..1b0f70ce395 --- /dev/null +++ b/examples/ldns-nsec3-hash.1 @@ -0,0 +1,34 @@ +.TH ldns-nsec3-hash.c 1 "10 Dec 2008" +.SH NAME +ldns-nsec3-hash \- print out the NSEC3 hash for a domain name +.SH SYNOPSIS +.B ldns-nsec3-hash +.IR + +.SH DESCRIPTION +\fBldns-nsec3-hash\fR is used to print out the NSEC3 hash for the given domain name. + +.SH OPTIONS +.TP +\fB-a\fR \fInumber\fR +Use the given algorithm number for the hash calculation. Defaults to 1 (SHA-1). + +.TP +\fB-s\fR \fIsalt\fR +Use the given salt for the hash calculation. Salt value should be in hexadecimal format. + +.TP +\fB-t\fR \fIcount\fR +Use count iterations for the hash calculation. + + +.SH AUTHOR +Written by the ldns team as an example for ldns usage. + +.SH REPORTING BUGS +Report bugs to . + +.SH COPYRIGHT +Copyright (C) 2008 NLnet Labs. This is free software. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. diff --git a/examples/ldns-nsec3-hash.c b/examples/ldns-nsec3-hash.c new file mode 100644 index 00000000000..0ba2e68aec4 --- /dev/null +++ b/examples/ldns-nsec3-hash.c @@ -0,0 +1,127 @@ +/* + * ldns-signzone signs a zone file + * + * (c) NLnet Labs, 2005 - 2008 + * See the file LICENSE for the license + */ + +#include "config.h" +#include +#include + +#include + +#include + +#include +#include + +#ifdef HAVE_SSL +#include +#include +#endif /* HAVE_SSL */ + +#define MAX_FILENAME_LEN 250 +int verbosity = 1; + +static void +usage(FILE *fp, const char *prog) { + fprintf(fp, "%s [OPTIONS] \n", prog); + fprintf(fp, " prints the NSEC3 hash of the given domain name\n"); + fprintf(fp, "-a [algorithm] hashing algorithm\n"); + fprintf(fp, "-t [number] number of hash iterations\n"); + fprintf(fp, "-s [string] salt\n"); +} + +int +main(int argc, char *argv[]) +{ + ldns_rdf *dname, *hashed_dname; + uint8_t nsec3_algorithm = 1; + size_t nsec3_iterations_cmd = 1; + uint16_t nsec3_iterations = 1; + uint8_t nsec3_salt_length = 0; + uint8_t *nsec3_salt = NULL; + + char *prog = strdup(argv[0]); + + int c; + while ((c = getopt(argc, argv, "a:s:t:")) != -1) { + switch (c) { + case 'a': + nsec3_algorithm = (uint8_t) atoi(optarg); + break; + case 's': + if (strlen(optarg) % 2 != 0) { + fprintf(stderr, "Salt value is not valid hex data, not a multiple of 2 characters\n"); + exit(EXIT_FAILURE); + } + if (strlen(optarg) > 512) { + fprintf(stderr, "Salt too long\n"); + exit(EXIT_FAILURE); + } + nsec3_salt_length = (uint8_t) (strlen(optarg) / 2); + nsec3_salt = LDNS_XMALLOC(uint8_t, nsec3_salt_length); + for (c = 0; c < (int) strlen(optarg); c += 2) { + if (isxdigit((int) optarg[c]) && isxdigit((int) optarg[c+1])) { + nsec3_salt[c/2] = (uint8_t) ldns_hexdigit_to_int(optarg[c]) * 16 + + ldns_hexdigit_to_int(optarg[c+1]); + } else { + fprintf(stderr, "Salt value is not valid hex data.\n"); + exit(EXIT_FAILURE); + } + } + + break; + case 't': + nsec3_iterations_cmd = (size_t) atol(optarg); + if (nsec3_iterations_cmd > LDNS_NSEC3_MAX_ITERATIONS) { + fprintf(stderr, "Iterations count can not exceed %u, quitting\n", LDNS_NSEC3_MAX_ITERATIONS); + exit(EXIT_FAILURE); + } + nsec3_iterations = (uint16_t) nsec3_iterations_cmd; + break; + default: + usage(stderr, prog); + exit(EXIT_SUCCESS); + } + } + + argc -= optind; + argv += optind; + + if (argc < 1) { + printf("Error: not enough arguments\n"); + usage(stdout, prog); + exit(EXIT_FAILURE); + } else { + dname = ldns_dname_new_frm_str(argv[0]); + if (!dname) { + fprintf(stderr, + "Error: unable to parse domain name\n"); + return EXIT_FAILURE; + } + hashed_dname = ldns_nsec3_hash_name(dname, + nsec3_algorithm, + nsec3_iterations, + nsec3_salt_length, + nsec3_salt); + if (!hashed_dname) { + fprintf(stderr, + "Error creating NSEC3 hash\n"); + return EXIT_FAILURE; + } + ldns_rdf_print(stdout, hashed_dname); + printf("\n"); + ldns_rdf_deep_free(dname); + ldns_rdf_deep_free(hashed_dname); + } + + if (nsec3_salt) { + free(nsec3_salt); + } + + free(prog); + + return EXIT_SUCCESS; +} diff --git a/examples/ldns-read-zone.1 b/examples/ldns-read-zone.1 new file mode 100644 index 00000000000..81f238d601c --- /dev/null +++ b/examples/ldns-read-zone.1 @@ -0,0 +1,69 @@ +.TH ldns-read-zone 1 "30 May 2005" +.SH NAME +ldns-read-zone \- read a zonefile and print it +.SH SYNOPSIS +.B ldns-read-zone +.IR ZONEFILE + +.SH DESCRIPTION + +\fBldns-read-zone\fR reads a DNS zone file and prints it. The output has 1 +resource record per line, and no pretty-printing makeup. + +.SH OPTIONS +.TP +\fB-c\fR +Canonicalize all resource records in the zone before printing + +.TP +\fB-d\fR +Only print DNSSEC data from the zone. This option skips every record +that is not of type NSEC, NSEC3, RRSIG or DNSKEY. DS records are not +printed. + +.TP +\fB-h\fR +Show usage and exit + +.TP +\fB-n\fR +Do not print the SOA record + +.TP +\fB-s\fR +Strip DNSSEC data from the zone. This option skips every record +that is of type NSEC, NSEC3, RRSIG or DNSKEY. DS records are still +printed. + +.TP +\fB-S\fR \fI[[+|0]number | YYYYMMDDxx | unixtime ]\fR +Set serial number to the given \fInumber\fR, or when preceded by a sign, +offset the exisiting number with it. When giving the literal strings +\fIYYYYMMDDxx\fR or \fIunixtime\fR, the serial number is tried to be reset +in datecounter or in unixtime format respectively. Though is the updated serial +number is smaller than the original one, the original one is simply +increased by one. + +When updating a serial number, records of type NSEC, NSEC3, RRSIG and DNSKEY +will be skipped when printing the zone. + + +.TP +\fB-v\fR +Show the version and exit + +.TP +\fB-z\fR +Sort the zone before printing (this implies -c) + + +.SH AUTHOR +Written by the ldns team as an example for ldns usage. + +.SH REPORTING BUGS +Report bugs to . + +.SH COPYRIGHT +Copyright (C) 2005 NLnet Labs. This is free software. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. diff --git a/examples/ldns-read-zone.c b/examples/ldns-read-zone.c new file mode 100644 index 00000000000..ac32bac7f73 --- /dev/null +++ b/examples/ldns-read-zone.c @@ -0,0 +1,212 @@ +/* + * read a zone file from disk and prints it, one RR per line + * + * (c) NLnetLabs 2005-2008 + * + * See the file LICENSE for the license + */ + +#include "config.h" +#include +#include + +#include +#include + +#include + +int +main(int argc, char **argv) +{ + char *filename; + FILE *fp; + ldns_zone *z; + int line_nr = 0; + int c; + bool canonicalize = false; + bool sort = false; + bool strip = false; + bool only_dnssec = false; + bool print_soa = true; + ldns_status s; + size_t i; + ldns_rr_list *stripped_list; + ldns_rr *cur_rr; + ldns_rr_type cur_rr_type; + const ldns_output_format *fmt = NULL; + ldns_soa_serial_increment_func_t soa_serial_increment_func = NULL; + int soa_serial_increment_func_data = 0; + + while ((c = getopt(argc, argv, "bcdhnsvzS:")) != -1) { + switch(c) { + case 'b': + fmt = ldns_output_format_bubblebabble; + case 'c': + canonicalize = true; + break; + case 'd': + only_dnssec = true; + if (strip) { + fprintf(stderr, "Warning: stripping both DNSSEC and non-DNSSEC records. Output will be sparse.\n"); + } + break; + case 'h': + printf("Usage: %s [-c] [-v] [-z] \n", argv[0]); + printf("\tReads the zonefile and prints it.\n"); + printf("\tThe RR count of the zone is printed to stderr.\n"); + printf("\t-b include bubblebabble of DS's.\n"); + printf("\t-c canonicalize all rrs in the zone.\n"); + printf("\t-d only show DNSSEC data from the zone\n"); + printf("\t-h show this text\n"); + printf("\t-n do not print the SOA record\n"); + printf("\t-s strip DNSSEC data from the zone\n"); + printf("\t-S [[+|-] | YYYYMMDDxx | " + " unixtime ]\n" + "\t\tSet serial number to or," + " when preceded by a sign,\n" + "\t\toffset the existing number with " + ". With YYYYMMDDxx\n" + "\t\tthe serial is formatted as a datecounter" + ", and with unixtime as the\n" + "\t\tnumber of seconds since 1-1-1970." + " However, on serial number" + "\n\t\tdecrease, +1 is used in stead" + ". (implies -s)\n"); + printf("\t-v shows the version and exits\n"); + printf("\t-z sort the zone (implies -c).\n"); + printf("\nif no file is given standard input is read\n"); + exit(EXIT_SUCCESS); + break; + case 'n': + print_soa = false; + break; + case 's': + strip = true; + if (only_dnssec) { + fprintf(stderr, "Warning: stripping both DNSSEC and non-DNSSEC records. Output will be sparse.\n"); + } + break; + case 'v': + printf("read zone version %s (ldns version %s)\n", LDNS_VERSION, ldns_version()); + exit(EXIT_SUCCESS); + break; + case 'z': + canonicalize = true; + sort = true; + break; + case 'S': + strip = true; + if (*optarg == '+' || *optarg == '-') { + soa_serial_increment_func_data = + atoi(optarg); + soa_serial_increment_func = + ldns_soa_serial_increment_by; + } else if (! strtok(optarg, "0123456789")) { + soa_serial_increment_func_data = + atoi(optarg); + soa_serial_increment_func = + ldns_soa_serial_identity; + } else if (!strcasecmp(optarg, "YYYYMMDDxx")){ + soa_serial_increment_func = + ldns_soa_serial_datecounter; + } else if (!strcasecmp(optarg, "unixtime")){ + soa_serial_increment_func = + ldns_soa_serial_unixtime; + } else { + fprintf(stderr, "-S expects a number " + "optionally preceded by a " + "+ or - sign to indicate an " + "offset, or the text YYYYMM" + "DDxx or unixtime\n"); + exit(EXIT_FAILURE); + } + break; + } + } + + argc -= optind; + argv += optind; + + if (argc == 0) { + fp = stdin; + } else { + filename = argv[0]; + + fp = fopen(filename, "r"); + if (!fp) { + fprintf(stderr, "Unable to open %s: %s\n", filename, strerror(errno)); + exit(EXIT_FAILURE); + } + } + + s = ldns_zone_new_frm_fp_l(&z, fp, NULL, 0, LDNS_RR_CLASS_IN, &line_nr); + + if (strip) { + stripped_list = ldns_rr_list_new(); + while ((cur_rr = ldns_rr_list_pop_rr(ldns_zone_rrs(z)))) { + cur_rr_type = ldns_rr_get_type(cur_rr); + if (cur_rr_type == LDNS_RR_TYPE_RRSIG || + cur_rr_type == LDNS_RR_TYPE_NSEC || + cur_rr_type == LDNS_RR_TYPE_NSEC3 || + cur_rr_type == LDNS_RR_TYPE_NSEC3PARAM + ) { + ldns_rr_free(cur_rr); + } else { + ldns_rr_list_push_rr(stripped_list, cur_rr); + } + } + ldns_rr_list_free(ldns_zone_rrs(z)); + ldns_zone_set_rrs(z, stripped_list); + } + if (only_dnssec) { + stripped_list = ldns_rr_list_new(); + while ((cur_rr = ldns_rr_list_pop_rr(ldns_zone_rrs(z)))) { + cur_rr_type = ldns_rr_get_type(cur_rr); + if (cur_rr_type == LDNS_RR_TYPE_RRSIG || + cur_rr_type == LDNS_RR_TYPE_NSEC || + cur_rr_type == LDNS_RR_TYPE_NSEC3 || + cur_rr_type == LDNS_RR_TYPE_NSEC3PARAM + ) { + ldns_rr_list_push_rr(stripped_list, cur_rr); + } else { + ldns_rr_free(cur_rr); + } + } + ldns_rr_list_free(ldns_zone_rrs(z)); + ldns_zone_set_rrs(z, stripped_list); + } + + if (s == LDNS_STATUS_OK) { + if (canonicalize) { + ldns_rr2canonical(ldns_zone_soa(z)); + for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(z)); i++) { + ldns_rr2canonical(ldns_rr_list_rr(ldns_zone_rrs(z), i)); + } + } + if (sort) { + ldns_zone_sort(z); + } + + if (print_soa && ldns_zone_soa(z)) { + if (soa_serial_increment_func) { + ldns_rr_soa_increment_func_int( + ldns_zone_soa(z) + , soa_serial_increment_func + , soa_serial_increment_func_data + ); + } + ldns_rr_print_fmt(stdout, fmt, ldns_zone_soa(z)); + } + ldns_rr_list_print_fmt(stdout, fmt, ldns_zone_rrs(z)); + + ldns_zone_deep_free(z); + } else { + fprintf(stderr, "%s at %d\n", + ldns_get_errorstr_by_id(s), + line_nr); + exit(EXIT_FAILURE); + } + fclose(fp); + + exit(EXIT_SUCCESS); +} diff --git a/examples/ldns-resolver.1 b/examples/ldns-resolver.1 new file mode 100644 index 00000000000..9552e6860ce --- /dev/null +++ b/examples/ldns-resolver.1 @@ -0,0 +1,26 @@ +.TH ldns-resolver 1 "27 Apr 2005" +.SH NAME +ldns-resolver \- tries to create a resolver from a resolv.conf file. +.SH SYNOPSIS +.B ldns-resolver +.IR file + +.SH DESCRIPTION +\fBldns-resolver\fR tries to create a resolver from a resolv.conf file. +This is only useful to test the library for robusteness with input data. + +.SH OPTIONS +\fBldns-resolver\fR takes a filename of the resolv.conf file as input. +For example \fIldns-resolver /etc/resolv.conf\fR will show if the file can +be parsed successfully. + +.SH AUTHOR +Written by the ldns team as an example for ldns usage. + +.SH REPORTING BUGS +Report bugs to . + +.SH COPYRIGHT +Copyright (C) 2005 NLnet Labs. This is free software. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. diff --git a/examples/ldns-resolver.c b/examples/ldns-resolver.c new file mode 100644 index 00000000000..04dcc35febd --- /dev/null +++ b/examples/ldns-resolver.c @@ -0,0 +1,47 @@ +/* + * ldns-resolver tries to create a resolver structure from /dev/urandom + * this is only useful to test the library for robusteness with input data + * + * (c) NLnet Labs 2006 - 2008 + * See the file LICENSE for the license + */ + +#include "config.h" +#include "errno.h" + +#include + +int +main(int argc, char **argv) { + + ldns_resolver *r; + int line = 1; + FILE *rand; + ldns_status s; + + if (argc != 2 || strncmp(argv[1], "-h", 3) == 0) { + printf("Usage: ldns-resolver \n"); + printf("Tries to create a stub resolver structure from the given file.\n"); + exit(EXIT_FAILURE); + } + + if (!(rand = fopen(argv[1], "r"))) { + printf("Error opening %s: %s\n", argv[1], strerror(errno)); + exit(EXIT_FAILURE); + } + + printf("Trying to read from %s\n", argv[1]); + s = ldns_resolver_new_frm_fp_l(&r, rand, &line); + if (s != LDNS_STATUS_OK) { + printf("Failed: %s at line %d\n", ldns_get_errorstr_by_id(s), line); + exit(EXIT_FAILURE); + } else { + printf("Succes\n"); + ldns_resolver_print(stdout, r); + ldns_resolver_deep_free(r); + } + + fclose(rand); + + return EXIT_SUCCESS; +} diff --git a/examples/ldns-revoke.1 b/examples/ldns-revoke.1 new file mode 100644 index 00000000000..5a16244dac4 --- /dev/null +++ b/examples/ldns-revoke.1 @@ -0,0 +1,27 @@ +.TH ldns-revoke 1 "23 Jul 2008" +.SH NAME +ldns-revoke \- sets the revoke bit of a DNSKEY +.SH SYNOPSIS +.B ldns-revoke +.IR file + +.SH DESCRIPTION +\fBldns-revoke\fR is used to revoke a public DNSKEY RR. +When run it will read \fIfile\fR with a DNSKEY RR in it, +sets the revoke bit and write back the output to \fIfile\fR . + +.SH OPTIONS +.TP +\fB-n\fR +Write the result to stdout instead of a file + +.SH AUTHOR +Written by the ldns team as an example for ldns usage. + +.SH REPORTING BUGS +Report bugs to . + +.SH COPYRIGHT +Copyright (C) 2008 NLnet Labs. This is free software. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. diff --git a/examples/ldns-revoke.c b/examples/ldns-revoke.c new file mode 100644 index 00000000000..f46c98f0109 --- /dev/null +++ b/examples/ldns-revoke.c @@ -0,0 +1,104 @@ +/* + * revoke sets the revoke bit of a public key. + * + * (c) NLnet Labs, 2005 - 2008 + * See the file LICENSE for the license + */ + +#include "config.h" + +#include +#ifdef HAVE_SSL +#include +#endif /* HAVE_SSL */ + +#include + +static void +usage(FILE *fp, char *prog) { + fprintf(fp, "%s [-n] keyfile\n", prog); + fprintf(fp, " Revokes a key\n"); + fprintf(fp, "Options:\n"); + fprintf(fp, " -n: do not write to file but to stdout\n"); +} + +int +main(int argc, char *argv[]) +{ + FILE *keyfp; + char *keyname; + ldns_rr *k; + uint16_t flags; + char *program = argv[0]; + int nofile = 0; + ldns_rdf *origin = NULL; + ldns_status result; + + argv++, argc--; + while (argc && argv[0][0] == '-') { + if (strcmp(argv[0], "-n") == 0) { + nofile=1; + } + else { + usage(stderr, program); + exit(EXIT_FAILURE); + } + argv++, argc--; + } + + if (argc != 1) { + usage(stderr, program); + exit(EXIT_FAILURE); + } + keyname = strdup(argv[0]); + + keyfp = fopen(keyname, "r"); + if (!keyfp) { + fprintf(stderr, "Failed to open public key file %s: %s\n", keyname, + strerror(errno)); + exit(EXIT_FAILURE); + } + + result = ldns_rr_new_frm_fp(&k, keyfp, 0, &origin, NULL); + /* what does this while loop do? */ + while (result == LDNS_STATUS_SYNTAX_ORIGIN) { + result = ldns_rr_new_frm_fp(&k, keyfp, 0, &origin, NULL); + } + if (result != LDNS_STATUS_OK) { + fprintf(stderr, "Could not read public key from file %s: %s\n", keyname, ldns_get_errorstr_by_id(result)); + exit(EXIT_FAILURE); + } + fclose(keyfp); + + flags = ldns_read_uint16(ldns_rdf_data(ldns_rr_dnskey_flags(k))); + flags |= LDNS_KEY_REVOKE_KEY; + + if (!ldns_rr_dnskey_set_flags(k, + ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, flags))) + { + fprintf(stderr, "Revocation failed\n"); + exit(EXIT_FAILURE); + } + + /* print the public key RR to .key */ + + if (nofile) + ldns_rr_print(stdout,k); + else { + keyfp = fopen(keyname, "w"); + if (!keyfp) { + fprintf(stderr, "Unable to open %s: %s\n", keyname, + strerror(errno)); + exit(EXIT_FAILURE); + } else { + ldns_rr_print(keyfp, k); + fclose(keyfp); + fprintf(stdout, "DNSKEY revoked\n"); + } + } + + free(keyname); + ldns_rr_free(k); + + exit(EXIT_SUCCESS); +} diff --git a/examples/ldns-rrsig.1 b/examples/ldns-rrsig.1 new file mode 100644 index 00000000000..3aee863e057 --- /dev/null +++ b/examples/ldns-rrsig.1 @@ -0,0 +1,30 @@ +.TH ldns-rrsig 1 "27 Apr 2005" +.SH NAME +ldns-rrsig \- print out the inception and expiration dates in human +readable form +.SH SYNOPSIS +.B ldns-rrsig +.IR domain +[ +.IR type +] + +.SH DESCRIPTION +\fBldns-rrsig\fR is used to print the expiration and inception date of +a RRSIG. The first argument is a domain name. \fBldns-rrsig\fR will +query the authoritative servers for that domain to get a list of RRSIGs. +It will then print out the inception and experiration dates for the RRSIG +covering the SOA record. +.PP +If the second argument \fBtype\fR is given the RRSIG covering that type will be shown. + +.SH AUTHOR +Written by the ldns team as an example for ldns usage. + +.SH REPORTING BUGS +Report bugs to . + +.SH COPYRIGHT +Copyright (C) 2005 NLnet Labs. This is free software. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. diff --git a/examples/ldns-rrsig.c b/examples/ldns-rrsig.c new file mode 100644 index 00000000000..a6658616008 --- /dev/null +++ b/examples/ldns-rrsig.c @@ -0,0 +1,219 @@ +/* + * ldns-rrsig prints out the inception and expiration dates in a more readable + * way than the normal RRSIG presentation format + * + * for a particulary domain + * (c) NLnet Labs, 2005 - 2008 + * See the file LICENSE for the license + */ + +#include "config.h" + +#include + +static int +usage(FILE *fp, char *prog) { + fprintf(fp, "%s domain [type]\n", prog); + fprintf(fp, " print out the inception and expiration dates\n"); + fprintf(fp, " in a more human readable form\n"); + fprintf(fp, " \tquery for RRSIG(), defaults to SOA\n"); + return 0; +} + +int +main(int argc, char *argv[]) +{ + ldns_resolver *res; + ldns_resolver *localres; + ldns_rdf *domain; + ldns_pkt *p; + ldns_rr_list *rrsig; + ldns_rr_list *rrsig_type; + ldns_rr_list *ns; + ldns_rr_list *ns_ip; + uint8_t i, j; + ldns_rr_type t; + const char * type_name; + struct tm incep, expir; + char incep_buf[26]; + char expir_buf[26]; + ldns_status s; + time_t now = time(NULL); + + p = NULL; + rrsig = NULL; + rrsig_type = NULL; + domain = NULL; + + /* option parsing */ + + if (argc < 2) { + usage(stdout, argv[0]); + exit(EXIT_FAILURE); + } else { + /* create a rdf from the command line arg */ + domain = ldns_dname_new_frm_str(argv[1]); + if (!domain) { + usage(stdout, argv[0]); + exit(EXIT_FAILURE); + } + } + + if (argc == 3) { + /* optional type arg */ + type_name = strdup(argv[2]); + t = ldns_rdf2rr_type( + ldns_rdf_new_frm_str(LDNS_RDF_TYPE_TYPE, type_name)); + if (t == 0) { + fprintf(stderr, " *** %s is not a valid RR type\n", type_name); + exit(EXIT_FAILURE); + } + } else { + t = LDNS_RR_TYPE_SOA; + type_name = "SOA"; + } + + /* create a new resolver from /etc/resolv.conf */ + s = ldns_resolver_new_frm_file(&localres, NULL); + if (s != LDNS_STATUS_OK) { + exit(EXIT_FAILURE); + } + + /* first get the nameserver of the domain in question */ + p = ldns_resolver_query(localres, domain, LDNS_RR_TYPE_NS, + LDNS_RR_CLASS_IN, LDNS_RD); + if (!p) { + fprintf(stderr," *** Could not find any nameserver for %s", argv[1]); + ldns_resolver_deep_free(localres); + exit(EXIT_FAILURE); + } + ns = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_NS, LDNS_SECTION_ANSWER); + + if (!ns) { + fprintf(stderr," *** Could not find any nameserver for %s", argv[1]); + ldns_pkt_free(p); + ldns_resolver_deep_free(localres); + exit(EXIT_FAILURE); + } + + /* use our local resolver to resolv the names in the for usage in our + * new resolver */ + res = ldns_resolver_new(); + if (!res) { + ldns_pkt_free(p); + ldns_resolver_deep_free(localres); + ldns_rr_list_deep_free(ns); + exit(EXIT_FAILURE); + } + for(i = 0; i < ldns_rr_list_rr_count(ns); i++) { + ns_ip = ldns_get_rr_list_addr_by_name(localres, + ldns_rr_ns_nsdname(ldns_rr_list_rr(ns, i)), + LDNS_RR_CLASS_IN, LDNS_RD); + /* add these to new resolver */ + for(j = 0; j < ldns_rr_list_rr_count(ns_ip); j++) { + if (ldns_resolver_push_nameserver(res, + ldns_rr_a_address(ldns_rr_list_rr(ns_ip, j))) != LDNS_STATUS_OK) { + printf("Error adding nameserver to resolver\n"); + ldns_pkt_free(p); + ldns_resolver_deep_free(res); + ldns_resolver_deep_free(localres); + ldns_rr_list_deep_free(ns); + exit(EXIT_FAILURE); + } + } + ldns_rr_list_deep_free(ns_ip); + + } + + /* enable DNSSEC */ + ldns_resolver_set_dnssec(res, true); + /* also set CD, we want EVERYTHING! */ + ldns_resolver_set_dnssec_cd(res, true); + + /* use the resolver to send it a query for the soa + * records of the domain given on the command line + */ + ldns_pkt_free(p); + p = ldns_resolver_query(res, domain, LDNS_RR_TYPE_RRSIG, LDNS_RR_CLASS_IN, LDNS_RD); + + ldns_rdf_deep_free(domain); + + if (!p) { + ldns_resolver_deep_free(localres); + ldns_rr_list_deep_free(ns); + exit(EXIT_FAILURE); + } else { + /* retrieve the RRSIG records from the answer section of that + * packet + */ + rrsig = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_RRSIG, LDNS_SECTION_ANSWER); + if (!rrsig) { + fprintf(stderr, + " *** invalid answer name %s after RRSIG query for %s\n", + argv[1], argv[1]); + ldns_pkt_free(p); + ldns_resolver_deep_free(res); + ldns_rr_list_deep_free(ns); + exit(EXIT_FAILURE); + } else { + rrsig_type = ldns_rr_list_new(); + + for(i = 0; i < ldns_rr_list_rr_count(rrsig); i++) { + if (ldns_rdf2rr_type( + ldns_rr_rrsig_typecovered( + ldns_rr_list_rr(rrsig, i))) == t) { + ldns_rr_list_push_rr(rrsig_type, + ldns_rr_list_rr(rrsig, i)); + } + } + if (ldns_rr_list_rr_count(rrsig_type) == 0) { + fprintf(stderr, " *** No RRSIG(%s) type found\n", + type_name); + ldns_resolver_deep_free(localres); + ldns_resolver_deep_free(res); + ldns_pkt_free(p); + ldns_rr_list_deep_free(ns); + ldns_rr_list_free(rrsig); + ldns_rr_list_deep_free(rrsig_type); + exit(EXIT_FAILURE); + } + + for(i = 0; i < ldns_rr_list_rr_count(rrsig_type); i++) { + memset(&incep, 0, sizeof(incep)); + if (ldns_serial_arithmitics_gmtime_r( + ldns_rdf2native_time_t( + ldns_rr_rrsig_inception( + ldns_rr_list_rr(rrsig_type, i))), + now, &incep + ) + && asctime_r(&incep, incep_buf)) { + incep_buf[24] = '\0'; + } else { + incep_buf[0] = '\0'; + } + memset(&expir, 0, sizeof(expir)); + if (ldns_serial_arithmitics_gmtime_r( + ldns_rdf2native_time_t( + ldns_rr_rrsig_expiration( + ldns_rr_list_rr(rrsig_type, i))), + now, &expir + ) + && asctime_r(&expir, expir_buf)) { + expir_buf[24] = '\0'; + } else { + expir_buf[0] = '\0'; + } + + fprintf(stdout, "%s RRSIG(%s): %s - %s\n", + argv[1], type_name, incep_buf, expir_buf); + } + ldns_rr_list_free(rrsig); + ldns_rr_list_deep_free(rrsig_type); + } + } + ldns_pkt_free(p); + ldns_resolver_deep_free(localres); + ldns_resolver_deep_free(res); + ldns_rr_list_deep_free(ns); + return 0; +} diff --git a/examples/ldns-signzone.1 b/examples/ldns-signzone.1 new file mode 100644 index 00000000000..a83da94e63d --- /dev/null +++ b/examples/ldns-signzone.1 @@ -0,0 +1,164 @@ +.TH ldns-signzone 1 "30 May 2005" +.SH NAME +ldns-signzone \- sign a zonefile with DNSSEC data +.SH SYNOPSIS +.B ldns-signzone +[ +.IR OPTIONS +] +.IR ZONEFILE +.IR +KEY +[KEY +[KEY] ... +] + +.SH DESCRIPTION + +\fBldns-signzone\fR is used to generate a DNSSEC signed zone. When run it +will create a new zonefile that contains RRSIG and NSEC resource records, as +specified in RFC 4033, RFC 4034 and RFC 4035. + +Keys must be specified by their base name (i.e. without .private). If +the DNSKEY that belongs to the key in the .private file is not present +in the zone, it will be read from the file .key. If that +file does not exist, the DNSKEY value will be generated from the +private key. + +Multiple keys can be specified, Key Signing Keys are used as such when +they are either already present in the zone, or specified in a .key +file, and have the KSK bit set. + +.SH OPTIONS +.TP +\fB-b\fR +Augments the zone and the RR's with extra comment texts for a more readable +layout, easier to debug. DS records will have a bubblebabble version of +the data in the comment text, NSEC3 records will have the original NSEC3 +in the comment text. + +Without this option, only DNSKEY RR's will have their Key Tag annotated in +the comment text. + +.TP +\fB-d\fR +Normally, if the DNSKEY RR for a key that is used to sign the zone is +not found in the zone file, it will be read from .key, or derived from +the private key (in that order). This option turns that feature off, +so that only the signatures are added to the zone. + +.TP +\fB-e\fR \fIdate\fR +Set expiration date of the signatures to this date, the format can be +YYYYMMDD[hhmmss], or a timestamp. + +.TP +\fB-f\fR \fIfile\fR +Use this file to store the signed zone in (default .signed) + +.TP +\fB-i\fR \fIdate\fR +Set inception date of the signatures to this date, the format can be +YYYYMMDD[hhmmss], or a timestamp. + +.TP +\fB-o\fR \fIorigin\fR +Use this as the origin of the zone + +.TP +\fB-v\fR +Print the version and exit + +.TP +\fB-A\fR +Sign the DNSKEY record with all keys. By default it is signed with a +minimal number of keys, to keep the response size for the DNSKEY query +small, and only the SEP keys that are passed are used. If there are no +SEP keys, the DNSKEY RRset is signed with the non\-SEP keys. This option +turns off the default and all keys are used to sign the DNSKEY RRset. + +.TP +\fB-E\fR \fIname\fR +Use the EVP cryptographic engine with the given name for signing. This +can have some extra options; see ENGINE OPTIONS for more information. + +.TP +\fB-k\fR \fIid,int\fR +Use the key with the given id as the signing key for algorithm int as +a Zone signing key. This option is used when you use an OpenSSL +engine, see ENGINE OPTIONS for more information. + +.TP +\fB-K\fR \fIid,int\fR + +Use the key with the given id as the signing key for algorithm int as +a Key signing key. This options is used when you use an OpenSSL engine, +see ENGINE OPTIONS for more information. + +.TP +\fB-n\fR +Use NSEC3 instead of NSEC. + +.TP +If you use NSEC3, you can specify the following extra options: + +.TP +\fB-a\fR \fIalgorithm\fR +Algorithm used to create the hashed NSEC3 owner names + +.TP +\fB-p\fR +Opt-out. All NSEC3 records in the zone will have the Opt-out flag set. After signing, you can add insecure delegations to the signed zone. + +.TP +\fB-s\fR \fIstring\fR +Salt + +.TP +\fB-t\fR \fInumber\fR +Number of hash iterations + +.SH ENGINE OPTIONS +You can modify the possible engines, if supported, by setting an +OpenSSL configuration file. This is done through the environment +variable OPENSSL_CONF. If you use -E with a non-existent engine name, +ldns-signzone will print a list of engines supported by your +configuration. + +The key options (-k and -K) work as follows; you specify a key id, and a DNSSEC algorithm number (for instance, 5 for RSASHA1). The key id can be any of the following: + + + : + id_ + slot_-id_ + label_
\n"); + fprintf(output, "Listens on the specified port and answers queries for the given zone\n"); + fprintf(output, "This is NOT a full-fledged authoritative nameserver!\n"); +} + +static int udp_bind(int sock, int port, const char *my_address) +{ + struct sockaddr_in addr; + in_addr_t maddr = INADDR_ANY; + + if (my_address) { +#ifdef AF_INET6 + if (inet_pton(AF_INET6, my_address, &maddr) < 1) { +#else + if (0) { +#endif + if (inet_pton(AF_INET, my_address, &maddr) < 1) { + return -2; + } + } + } + +#ifndef S_SPLINT_S + addr.sin_family = AF_INET; +#endif + addr.sin_port = (in_port_t) htons((uint16_t)port); + addr.sin_addr.s_addr = maddr; + return bind(sock, (struct sockaddr *)&addr, (socklen_t) sizeof(addr)); +} + +/* this will probably be moved to a better place in the library itself */ +ldns_rr_list * +get_rrset(const ldns_zone *zone, const ldns_rdf *owner_name, const ldns_rr_type qtype, const ldns_rr_class qclass) +{ + uint16_t i; + ldns_rr_list *rrlist = ldns_rr_list_new(); + ldns_rr *cur_rr; + if (!zone || !owner_name) { + fprintf(stderr, "Warning: get_rrset called with NULL zone or owner name\n"); + return rrlist; + } + + for (i = 0; i < ldns_zone_rr_count(zone); i++) { + cur_rr = ldns_rr_list_rr(ldns_zone_rrs(zone), i); + if (ldns_dname_compare(ldns_rr_owner(cur_rr), owner_name) == 0 && + ldns_rr_get_class(cur_rr) == qclass && + ldns_rr_get_type(cur_rr) == qtype + ) { + ldns_rr_list_push_rr(rrlist, ldns_rr_clone(cur_rr)); + } + } + + printf("Found rrset of %u rrs\n", (unsigned int) ldns_rr_list_rr_count(rrlist)); + + return rrlist; +} + +int +main(int argc, char **argv) +{ + /* arguments */ + int port; + const char *zone_file; + + /* network */ + int sock; + ssize_t nb; + struct sockaddr addr_me; + struct sockaddr addr_him; + socklen_t hislen = (socklen_t) sizeof(addr_him); + uint8_t inbuf[INBUF_SIZE]; + uint8_t *outbuf; + + /* dns */ + ldns_status status; + ldns_pkt *query_pkt; + ldns_pkt *answer_pkt; + size_t answer_size; + ldns_rr *query_rr; + ldns_rr_list *answer_qr; + ldns_rr_list *answer_an; + ldns_rr_list *answer_ns; + ldns_rr_list *answer_ad; + ldns_rdf *origin = NULL; + + /* zone */ + ldns_zone *zone; + int line_nr; + FILE *zone_fp; + + /* use this to listen on specified interfaces later? */ + char *my_address = NULL; + + if (argc < 5) { + usage(stderr); + exit(EXIT_FAILURE); + } else { + my_address = argv[1]; + port = atoi(argv[2]); + if (port < 1) { + usage(stderr); + exit(EXIT_FAILURE); + } + if (ldns_str2rdf_dname(&origin, argv[3]) != LDNS_STATUS_OK) { + fprintf(stderr, "Bad origin, not a correct domain name\n"); + usage(stderr); + exit(EXIT_FAILURE); + } + zone_file = argv[4]; + } + + printf("Reading zone file %s\n", zone_file); + zone_fp = fopen(zone_file, "r"); + if (!zone_fp) { + fprintf(stderr, "Unable to open %s: %s\n", zone_file, strerror(errno)); + exit(EXIT_FAILURE); + } + + line_nr = 0; + status = ldns_zone_new_frm_fp_l(&zone, zone_fp, origin, 0, LDNS_RR_CLASS_IN, &line_nr); + + if (status != LDNS_STATUS_OK) { + printf("Zone reader failed, aborting\n"); + exit(EXIT_FAILURE); + } else { + printf("Read %u resource records in zone file\n", (unsigned int) ldns_zone_rr_count(zone)); + } + fclose(zone_fp); + + printf("Listening on port %d\n", port); + sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) { + fprintf(stderr, "%s: socket(): %s\n", argv[0], strerror(errno)); + exit(1); + } + memset(&addr_me, 0, sizeof(addr_me)); + + /* bind: try all ports in that range */ + if (udp_bind(sock, port, my_address)) { + fprintf(stderr, "%s: cannot bind(): %s\n", argv[0], strerror(errno)); + exit(errno); + } + + /* Done. Now receive */ + while (1) { + nb = recvfrom(sock, (void*)inbuf, INBUF_SIZE, 0, + &addr_him, &hislen); + if (nb < 1) { + fprintf(stderr, "%s: recvfrom(): %s\n", + argv[0], strerror(errno)); + exit(1); + } + + /* + show(inbuf, nb, nn, hp, sp, ip, bp); + */ + printf("Got query of %u bytes\n", (unsigned int) nb); + status = ldns_wire2pkt(&query_pkt, inbuf, (size_t) nb); + if (status != LDNS_STATUS_OK) { + printf("Got bad packet: %s\n", ldns_get_errorstr_by_id(status)); + } else { + ldns_pkt_print(stdout, query_pkt); + } + + query_rr = ldns_rr_list_rr(ldns_pkt_question(query_pkt), 0); + printf("QUERY RR: \n"); + ldns_rr_print(stdout, query_rr); + + answer_qr = ldns_rr_list_new(); + ldns_rr_list_push_rr(answer_qr, ldns_rr_clone(query_rr)); + + answer_an = get_rrset(zone, ldns_rr_owner(query_rr), ldns_rr_get_type(query_rr), ldns_rr_get_class(query_rr)); + answer_pkt = ldns_pkt_new(); + answer_ns = ldns_rr_list_new(); + answer_ad = ldns_rr_list_new(); + + ldns_pkt_set_qr(answer_pkt, 1); + ldns_pkt_set_aa(answer_pkt, 1); + ldns_pkt_set_id(answer_pkt, ldns_pkt_id(query_pkt)); + + ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_QUESTION, answer_qr); + ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_ANSWER, answer_an); + ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_AUTHORITY, answer_ns); + ldns_pkt_push_rr_list(answer_pkt, LDNS_SECTION_ADDITIONAL, answer_ad); + + status = ldns_pkt2wire(&outbuf, answer_pkt, &answer_size); + + printf("Answer packet size: %u bytes.\n", (unsigned int) answer_size); + if (status != LDNS_STATUS_OK) { + printf("Error creating answer: %s\n", ldns_get_errorstr_by_id(status)); + } else { + nb = sendto(sock, (void*)outbuf, answer_size, 0, + &addr_him, hislen); + } + + ldns_pkt_free(query_pkt); + ldns_pkt_free(answer_pkt); + LDNS_FREE(outbuf); + ldns_rr_list_free(answer_qr); + ldns_rr_list_free(answer_an); + ldns_rr_list_free(answer_ns); + ldns_rr_list_free(answer_ad); + } + + ldns_rdf_deep_free(origin); + ldns_zone_deep_free(zone); + + return 0; +} diff --git a/higher.c b/higher.c new file mode 100644 index 00000000000..c9eb1731ae2 --- /dev/null +++ b/higher.c @@ -0,0 +1,359 @@ +/* + * higher.c + * + * Specify some higher level functions that would + * be usefull to would be developers + * + * a Net::DNS like library for C + * + * (c) NLnet Labs, 2004-2006 + * + * See the file LICENSE for the license + */ + +#include + +#include + +#ifdef HAVE_SSL +#include +#include +#endif /* HAVE_SSL */ + +ldns_rr_list * +ldns_get_rr_list_addr_by_name(ldns_resolver *res, ldns_rdf *name, ldns_rr_class c, + uint16_t flags) +{ + ldns_pkt *pkt; + ldns_rr_list *aaaa; + ldns_rr_list *a; + ldns_rr_list *result = NULL; + ldns_rr_list *hostsfilenames; + size_t i; + uint8_t ip6; + + a = NULL; + aaaa = NULL; + result = NULL; + + if (!res) { + return NULL; + } + if (ldns_rdf_get_type(name) != LDNS_RDF_TYPE_DNAME) { + return NULL; + } + + ip6 = ldns_resolver_ip6(res); /* we use INET_ANY here, save + what was there */ + + ldns_resolver_set_ip6(res, LDNS_RESOLV_INETANY); + + hostsfilenames = ldns_get_rr_list_hosts_frm_file(NULL); + for (i = 0; i < ldns_rr_list_rr_count(hostsfilenames); i++) { + if (ldns_rdf_compare(name, + ldns_rr_owner(ldns_rr_list_rr(hostsfilenames, + i))) == 0) { + if (!result) { + result = ldns_rr_list_new(); + } + ldns_rr_list_push_rr(result, + ldns_rr_clone(ldns_rr_list_rr(hostsfilenames, i))); + } + } + ldns_rr_list_deep_free(hostsfilenames); + + if (result) { + return result; + } + + /* add the RD flags, because we want an answer */ + pkt = ldns_resolver_query(res, name, LDNS_RR_TYPE_AAAA, c, flags | LDNS_RD); + if (pkt) { + /* extract the data we need */ + aaaa = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_AAAA, + LDNS_SECTION_ANSWER); + ldns_pkt_free(pkt); + } + + pkt = ldns_resolver_query(res, name, LDNS_RR_TYPE_A, c, flags | LDNS_RD); + if (pkt) { + /* extract the data we need */ + a = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_A, LDNS_SECTION_ANSWER); + ldns_pkt_free(pkt); + } + ldns_resolver_set_ip6(res, ip6); + + if (aaaa && a) { + result = ldns_rr_list_cat_clone(aaaa, a); + ldns_rr_list_deep_free(aaaa); + ldns_rr_list_deep_free(a); + return result; + } + + if (aaaa) { + result = ldns_rr_list_clone(aaaa); + } + + if (a) { + result = ldns_rr_list_clone(a); + } + + ldns_rr_list_deep_free(aaaa); + ldns_rr_list_deep_free(a); + return result; +} + +ldns_rr_list * +ldns_get_rr_list_name_by_addr(ldns_resolver *res, ldns_rdf *addr, ldns_rr_class c, + uint16_t flags) +{ + ldns_pkt *pkt; + ldns_rr_list *names; + ldns_rdf *name; + + names = NULL; + + if (!res || !addr) { + return NULL; + } + + if (ldns_rdf_get_type(addr) != LDNS_RDF_TYPE_A && + ldns_rdf_get_type(addr) != LDNS_RDF_TYPE_AAAA) { + return NULL; + } + + name = ldns_rdf_address_reverse(addr); + + /* add the RD flags, because we want an answer */ + pkt = ldns_resolver_query(res, name, LDNS_RR_TYPE_PTR, c, flags | LDNS_RD); + if (pkt) { + /* extract the data we need */ + names = ldns_pkt_rr_list_by_type(pkt, + LDNS_RR_TYPE_PTR, LDNS_SECTION_ANSWER); + } + return names; +} + +/* read a line, put it in a buffer, parse the buffer */ +ldns_rr_list * +ldns_get_rr_list_hosts_frm_fp(FILE *fp) +{ + return ldns_get_rr_list_hosts_frm_fp_l(fp, NULL); +} + +ldns_rr_list * +ldns_get_rr_list_hosts_frm_fp_l(FILE *fp, int *line_nr) +{ + ssize_t i, j; + size_t cnt; + char *line; + char *word; + char *addr; + char *rr_str; + ldns_buffer *linebuf; + ldns_rr *rr; + ldns_rr_list *list; + ldns_rdf *tmp; + bool ip6; + ldns_status parse_result; + + line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1); + word = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1); + addr = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1); + rr_str = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1); + ip6 = false; + list = ldns_rr_list_new(); + rr = NULL; + if(!line || !word || !addr || !rr_str || !list) { + LDNS_FREE(line); + LDNS_FREE(word); + LDNS_FREE(addr); + LDNS_FREE(rr_str); + ldns_rr_list_free(list); + return NULL; + } + + for(i = ldns_fget_token_l(fp, line, "\n", LDNS_MAX_LINELEN, line_nr); + i > 0; i = ldns_fget_token_l(fp, line, "\n", LDNS_MAX_LINELEN, line_nr)) { + /* # is comment */ + if (line[0] == '#') { + continue; + } + /* put it in a buffer for further processing */ + linebuf = LDNS_MALLOC(ldns_buffer); + if(!linebuf) { + LDNS_FREE(line); + LDNS_FREE(word); + LDNS_FREE(addr); + LDNS_FREE(rr_str); + ldns_rr_list_deep_free(list); + return NULL; + } + + ldns_buffer_new_frm_data(linebuf, line, (size_t) i); + for(cnt = 0, j = ldns_bget_token(linebuf, word, LDNS_PARSE_NO_NL, LDNS_MAX_LINELEN); + j > 0; + j = ldns_bget_token(linebuf, word, LDNS_PARSE_NO_NL, LDNS_MAX_LINELEN), cnt++) { + if (cnt == 0) { + /* the address */ + if ((tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, + word))) { + /* ip6 */ + ldns_rdf_deep_free(tmp); + ip6 = true; + } else { + if ((tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, + word))) { + /* ip4 */ + ldns_rdf_deep_free(tmp); + ip6 = false; + } else { + /* kaput */ + break; + } + } + (void)strlcpy(addr, word, LDNS_MAX_LINELEN+1); + } else { + /* la al la la */ + if (ip6) { + snprintf(rr_str, LDNS_MAX_LINELEN, + "%s IN AAAA %s", word, addr); + } else { + snprintf(rr_str, LDNS_MAX_LINELEN, + "%s IN A %s", word, addr); + } + parse_result = ldns_rr_new_frm_str(&rr, rr_str, 0, NULL, NULL); + if (parse_result == LDNS_STATUS_OK && ldns_rr_owner(rr) && ldns_rr_rd_count(rr) > 0) { + ldns_rr_list_push_rr(list, ldns_rr_clone(rr)); + } + ldns_rr_free(rr); + } + } + ldns_buffer_free(linebuf); + } + LDNS_FREE(line); + LDNS_FREE(word); + LDNS_FREE(addr); + LDNS_FREE(rr_str); + return list; +} + +ldns_rr_list * +ldns_get_rr_list_hosts_frm_file(char *filename) +{ + ldns_rr_list *names; + FILE *fp; + + if (!filename) { + fp = fopen(LDNS_RESOLV_HOSTS, "r"); + + } else { + fp = fopen(filename, "r"); + } + if (!fp) { + return NULL; + } + + names = ldns_get_rr_list_hosts_frm_fp(fp); + fclose(fp); + return names; +} + +uint16_t +ldns_getaddrinfo(ldns_resolver *res, ldns_rdf *node, ldns_rr_class c, + ldns_rr_list **ret) +{ + ldns_rdf_type t; + uint16_t names_found; + ldns_resolver *r; + ldns_status s; + + t = ldns_rdf_get_type(node); + names_found = 0; + r = res; + + if (res == NULL) { + /* prepare a new resolver, using /etc/resolv.conf as a guide */ + s = ldns_resolver_new_frm_file(&r, NULL); + if (s != LDNS_STATUS_OK) { + return 0; + } + } + + if (t == LDNS_RDF_TYPE_DNAME) { + /* we're asked to query for a name */ + *ret = ldns_get_rr_list_addr_by_name(r, node, c, 0); + names_found = ldns_rr_list_rr_count(*ret); + } + + if (t == LDNS_RDF_TYPE_A || t == LDNS_RDF_TYPE_AAAA) { + /* an address */ + *ret = ldns_get_rr_list_name_by_addr(r, node, c, 0); + names_found = ldns_rr_list_rr_count(*ret); + } + + if (res == NULL) { + ldns_resolver_deep_free(r); + } + + return names_found; +} + +bool +ldns_nsec_type_check(ldns_rr *nsec, ldns_rr_type t) +{ + /* does the nsec cover the t given? */ + /* copied from host2str.c line 465: ldns_rdf2buffer_str_nsec */ + uint8_t window_block_nr; + uint8_t bitmap_length; + uint16_t type; + uint16_t pos = 0; + uint16_t bit_pos; + ldns_rdf *nsec_type_list = ldns_rr_rdf(nsec, 1); + uint8_t *data; + + if (nsec_type_list == NULL) { + return false; + } + data = ldns_rdf_data(nsec_type_list); + + while(pos < ldns_rdf_size(nsec_type_list)) { + window_block_nr = data[pos]; + bitmap_length = data[pos + 1]; + pos += 2; + + for (bit_pos = 0; bit_pos < (bitmap_length) * 8; bit_pos++) { + if (ldns_get_bit(&data[pos], bit_pos)) { + type = 256 * (uint16_t) window_block_nr + bit_pos; + + if ((ldns_rr_type)type == t) { + /* we have a winner */ + return true; + } + } + } + pos += (uint16_t) bitmap_length; + } + return false; +} + +void +ldns_print_rr_rdf(FILE *fp, ldns_rr *r, int rdfnum, ...) +{ + int16_t rdf; + ldns_rdf *rd; + va_list va_rdf; + va_start(va_rdf, rdfnum); + + for (rdf = (int16_t)rdfnum; rdf != -1; rdf = (int16_t)va_arg(va_rdf, int)) + { + rd = ldns_rr_rdf(r, rdf); + if (!rd) { + continue; + } else { + ldns_rdf_print(fp, rd); + fprintf(fp, " "); /* not sure if we want to do this */ + } + } + va_end(va_rdf); +} diff --git a/host2str.c b/host2str.c new file mode 100644 index 00000000000..c185e0f04db --- /dev/null +++ b/host2str.c @@ -0,0 +1,2314 @@ +/* + * host2str.c + * + * conversion routines from the host format + * to the presentation format (strings) + * + * a Net::DNS like library for C + * + * (c) NLnet Labs, 2004-2006 + * + * See the file LICENSE for the license + */ +#include + +#include + +#include + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#include +#include + +#ifndef INET_ADDRSTRLEN +#define INET_ADDRSTRLEN 16 +#endif +#ifndef INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN 46 +#endif + +/* lookup tables for standard DNS stuff */ + +/* Taken from RFC 2535, section 7. */ +ldns_lookup_table ldns_algorithms[] = { + { LDNS_RSAMD5, "RSAMD5" }, + { LDNS_DH, "DH" }, + { LDNS_DSA, "DSA" }, + { LDNS_ECC, "ECC" }, + { LDNS_RSASHA1, "RSASHA1" }, + { LDNS_DSA_NSEC3, "DSA-NSEC3-SHA1" }, + { LDNS_RSASHA1_NSEC3, "RSASHA1-NSEC3-SHA1" }, +#ifdef USE_SHA2 + { LDNS_RSASHA256, "RSASHA256"}, + { LDNS_RSASHA512, "RSASHA512"}, +#endif +#ifdef USE_GOST + { LDNS_ECC_GOST, "ECC-GOST"}, +#endif +#ifdef USE_ECDSA + { LDNS_ECDSAP256SHA256, "ECDSAP256SHA256"}, + { LDNS_ECDSAP384SHA384, "ECDSAP384SHA384"}, +#endif + { LDNS_INDIRECT, "INDIRECT" }, + { LDNS_PRIVATEDNS, "PRIVATEDNS" }, + { LDNS_PRIVATEOID, "PRIVATEOID" }, + { 0, NULL } +}; + +/* Taken from RFC 4398 */ +ldns_lookup_table ldns_cert_algorithms[] = { + { LDNS_CERT_PKIX, "PKIX" }, + { LDNS_CERT_SPKI, "SPKI" }, + { LDNS_CERT_PGP, "PGP" }, + { LDNS_CERT_IPKIX, "IPKIX" }, + { LDNS_CERT_ISPKI, "ISPKI" }, + { LDNS_CERT_IPGP, "IPGP" }, + { LDNS_CERT_ACPKIX, "ACPKIX" }, + { LDNS_CERT_IACPKIX, "IACPKIX" }, + { LDNS_CERT_URI, "URI" }, + { LDNS_CERT_OID, "OID" }, + { 0, NULL } +}; + +/* classes */ +ldns_lookup_table ldns_rr_classes[] = { + { LDNS_RR_CLASS_IN, "IN" }, + { LDNS_RR_CLASS_CH, "CH" }, + { LDNS_RR_CLASS_HS, "HS" }, + { LDNS_RR_CLASS_NONE, "NONE" }, + { LDNS_RR_CLASS_ANY, "ANY" }, + { 0, NULL } +}; + +/* if these are used elsewhere */ +ldns_lookup_table ldns_rcodes[] = { + { LDNS_RCODE_NOERROR, "NOERROR" }, + { LDNS_RCODE_FORMERR, "FORMERR" }, + { LDNS_RCODE_SERVFAIL, "SERVFAIL" }, + { LDNS_RCODE_NXDOMAIN, "NXDOMAIN" }, + { LDNS_RCODE_NOTIMPL, "NOTIMPL" }, + { LDNS_RCODE_REFUSED, "REFUSED" }, + { LDNS_RCODE_YXDOMAIN, "YXDOMAIN" }, + { LDNS_RCODE_YXRRSET, "YXRRSET" }, + { LDNS_RCODE_NXRRSET, "NXRRSET" }, + { LDNS_RCODE_NOTAUTH, "NOTAUTH" }, + { LDNS_RCODE_NOTZONE, "NOTZONE" }, + { 0, NULL } +}; + +ldns_lookup_table ldns_opcodes[] = { + { LDNS_PACKET_QUERY, "QUERY" }, + { LDNS_PACKET_IQUERY, "IQUERY" }, + { LDNS_PACKET_STATUS, "STATUS" }, + { LDNS_PACKET_NOTIFY, "NOTIFY" }, + { LDNS_PACKET_UPDATE, "UPDATE" }, + { 0, NULL } +}; + +const ldns_output_format ldns_output_format_nocomments_record = { 0, NULL }; +const ldns_output_format *ldns_output_format_nocomments + = &ldns_output_format_nocomments_record; +const ldns_output_format ldns_output_format_onlykeyids_record = { + LDNS_COMMENT_KEY, NULL +}; +const ldns_output_format *ldns_output_format_onlykeyids + = &ldns_output_format_onlykeyids_record; +const ldns_output_format *ldns_output_format_default + = &ldns_output_format_onlykeyids_record; +const ldns_output_format ldns_output_format_bubblebabble_record = { + LDNS_COMMENT_KEY | LDNS_COMMENT_BUBBLEBABBLE | LDNS_COMMENT_FLAGS, NULL +}; +const ldns_output_format *ldns_output_format_bubblebabble + = &ldns_output_format_bubblebabble_record; + +ldns_status +ldns_pkt_opcode2buffer_str(ldns_buffer *output, ldns_pkt_opcode opcode) +{ + ldns_lookup_table *lt = ldns_lookup_by_id(ldns_opcodes, opcode); + if (lt && lt->name) { + ldns_buffer_printf(output, "%s", lt->name); + } else { + ldns_buffer_printf(output, "OPCODE%u", opcode); + } + return ldns_buffer_status(output); +} + +ldns_status +ldns_pkt_rcode2buffer_str(ldns_buffer *output, ldns_pkt_rcode rcode) +{ + ldns_lookup_table *lt = ldns_lookup_by_id(ldns_rcodes, rcode); + if (lt && lt->name) { + ldns_buffer_printf(output, "%s", lt->name); + } else { + ldns_buffer_printf(output, "RCODE%u", rcode); + } + return ldns_buffer_status(output); +} + +ldns_status +ldns_algorithm2buffer_str(ldns_buffer *output, + ldns_algorithm algorithm) +{ + ldns_lookup_table *lt = ldns_lookup_by_id(ldns_algorithms, + algorithm); + if (lt && lt->name) { + ldns_buffer_printf(output, "%s", lt->name); + } else { + ldns_buffer_printf(output, "ALG%u", algorithm); + } + return ldns_buffer_status(output); +} + +ldns_status +ldns_cert_algorithm2buffer_str(ldns_buffer *output, + ldns_cert_algorithm cert_algorithm) +{ + ldns_lookup_table *lt = ldns_lookup_by_id(ldns_cert_algorithms, + cert_algorithm); + if (lt && lt->name) { + ldns_buffer_printf(output, "%s", lt->name); + } else { + ldns_buffer_printf(output, "CERT_ALG%u", + cert_algorithm); + } + return ldns_buffer_status(output); +} + +char * +ldns_pkt_opcode2str(ldns_pkt_opcode opcode) +{ + char *str; + ldns_buffer *buf; + + buf = ldns_buffer_new(12); + if (!buf) { + return NULL; + } + + str = NULL; + if (ldns_pkt_opcode2buffer_str(buf, opcode) == LDNS_STATUS_OK) { + str = ldns_buffer2str(buf); + } + + ldns_buffer_free(buf); + return str; +} + +char * +ldns_pkt_rcode2str(ldns_pkt_rcode rcode) +{ + char *str; + ldns_buffer *buf; + + buf = ldns_buffer_new(10); + if (!buf) { + return NULL; + } + + str = NULL; + if (ldns_pkt_rcode2buffer_str(buf, rcode) == LDNS_STATUS_OK) { + str = ldns_buffer2str(buf); + } + + ldns_buffer_free(buf); + return str; +} + +char * +ldns_pkt_algorithm2str(ldns_algorithm algorithm) +{ + char *str; + ldns_buffer *buf; + + buf = ldns_buffer_new(10); + if (!buf) { + return NULL; + } + + str = NULL; + if (ldns_algorithm2buffer_str(buf, algorithm) + == LDNS_STATUS_OK) { + str = ldns_buffer2str(buf); + } + + ldns_buffer_free(buf); + return str; +} + +char * +ldns_pkt_cert_algorithm2str(ldns_cert_algorithm cert_algorithm) +{ + char *str; + ldns_buffer *buf; + + buf = ldns_buffer_new(10); + if (!buf) { + return NULL; + } + + str = NULL; + if (ldns_cert_algorithm2buffer_str(buf, cert_algorithm) + == LDNS_STATUS_OK) { + str = ldns_buffer2str(buf); + } + + ldns_buffer_free(buf); + return str; +} + + +/* do NOT pass compressed data here :p */ +ldns_status +ldns_rdf2buffer_str_dname(ldns_buffer *output, const ldns_rdf *dname) +{ + /* can we do with 1 pos var? or without at all? */ + uint8_t src_pos = 0; + uint8_t len; + uint8_t *data; + uint8_t i; + unsigned char c; + + data = (uint8_t*)ldns_rdf_data(dname); + len = data[src_pos]; + + if (ldns_rdf_size(dname) > LDNS_MAX_DOMAINLEN) { + /* too large, return */ + return LDNS_STATUS_DOMAINNAME_OVERFLOW; + } + + /* special case: root label */ + if (1 == ldns_rdf_size(dname)) { + ldns_buffer_printf(output, "."); + } else { + while ((len > 0) && src_pos < ldns_rdf_size(dname)) { + src_pos++; + for(i = 0; i < len; i++) { + /* paranoia check for various 'strange' + characters in dnames + */ + c = (unsigned char) data[src_pos]; + if(c == '.' || c == ';' || + c == '(' || c == ')' || + c == '\\') { + ldns_buffer_printf(output, "\\%c", + data[src_pos]); + } else if (!(isascii(c) && isgraph(c))) { + ldns_buffer_printf(output, "\\%03u", + data[src_pos]); + } else { + ldns_buffer_printf(output, "%c", data[src_pos]); + } + src_pos++; + } + + if (src_pos < ldns_rdf_size(dname)) { + ldns_buffer_printf(output, "."); + } + len = data[src_pos]; + } + } + return ldns_buffer_status(output); +} + +ldns_status +ldns_rdf2buffer_str_int8(ldns_buffer *output, const ldns_rdf *rdf) +{ + uint8_t data = ldns_rdf_data(rdf)[0]; + ldns_buffer_printf(output, "%lu", (unsigned long) data); + return ldns_buffer_status(output); +} + +ldns_status +ldns_rdf2buffer_str_int16(ldns_buffer *output, const ldns_rdf *rdf) +{ + uint16_t data = ldns_read_uint16(ldns_rdf_data(rdf)); + ldns_buffer_printf(output, "%lu", (unsigned long) data); + return ldns_buffer_status(output); +} + +ldns_status +ldns_rdf2buffer_str_int32(ldns_buffer *output, const ldns_rdf *rdf) +{ + uint32_t data = ldns_read_uint32(ldns_rdf_data(rdf)); + ldns_buffer_printf(output, "%lu", (unsigned long) data); + return ldns_buffer_status(output); +} + +ldns_status +ldns_rdf2buffer_str_time(ldns_buffer *output, const ldns_rdf *rdf) +{ + /* create a YYYYMMDDHHMMSS string if possible */ + struct tm tm; + char date_buf[16]; + + memset(&tm, 0, sizeof(tm)); + if (ldns_serial_arithmitics_gmtime_r(ldns_rdf2native_int32(rdf), time(NULL), &tm) + && strftime(date_buf, 15, "%Y%m%d%H%M%S", &tm)) { + ldns_buffer_printf(output, "%s", date_buf); + } + return ldns_buffer_status(output); +} + +ldns_status +ldns_rdf2buffer_str_a(ldns_buffer *output, const ldns_rdf *rdf) +{ + char str[INET_ADDRSTRLEN]; + + if (inet_ntop(AF_INET, ldns_rdf_data(rdf), str, INET_ADDRSTRLEN)) { + ldns_buffer_printf(output, "%s", str); + } + return ldns_buffer_status(output); +} + +ldns_status +ldns_rdf2buffer_str_aaaa(ldns_buffer *output, const ldns_rdf *rdf) +{ + char str[INET6_ADDRSTRLEN]; + + if (inet_ntop(AF_INET6, ldns_rdf_data(rdf), str, INET6_ADDRSTRLEN)) { + ldns_buffer_printf(output, "%s", str); + } + + return ldns_buffer_status(output); +} + +ldns_status +ldns_rdf2buffer_str_str(ldns_buffer *output, const ldns_rdf *rdf) +{ + const uint8_t *data = ldns_rdf_data(rdf); + uint8_t length = data[0]; + size_t i; + + ldns_buffer_printf(output, "\""); + for (i = 1; i <= length; ++i) { + char ch = (char) data[i]; + if (isprint((int)ch) || ch=='\t') { + if (ch=='\"'||ch=='\\') + ldns_buffer_printf(output, "\\%c", ch); + else + ldns_buffer_printf(output, "%c", ch); + } else { + ldns_buffer_printf(output, "\\%03u", + (unsigned)(uint8_t) ch); + } + } + ldns_buffer_printf(output, "\""); + return ldns_buffer_status(output); +} + +ldns_status +ldns_rdf2buffer_str_b64(ldns_buffer *output, const ldns_rdf *rdf) +{ + size_t size = ldns_b64_ntop_calculate_size(ldns_rdf_size(rdf)); + char *b64 = LDNS_XMALLOC(char, size); + if(!b64) return LDNS_STATUS_MEM_ERR; + if (ldns_b64_ntop(ldns_rdf_data(rdf), ldns_rdf_size(rdf), b64, size)) { + ldns_buffer_printf(output, "%s", b64); + } + LDNS_FREE(b64); + return ldns_buffer_status(output); +} + +ldns_status +ldns_rdf2buffer_str_b32_ext(ldns_buffer *output, const ldns_rdf *rdf) +{ + size_t size; + char *b32; + if(ldns_rdf_size(rdf) == 0) + return LDNS_STATUS_OK; + /* remove -1 for the b32-hash-len octet */ + size = ldns_b32_ntop_calculate_size(ldns_rdf_size(rdf) - 1); + /* add one for the end nul for the string */ + b32 = LDNS_XMALLOC(char, size + 1); + if(!b32) return LDNS_STATUS_MEM_ERR; + size = (size_t) ldns_b32_ntop_extended_hex(ldns_rdf_data(rdf) + 1, + ldns_rdf_size(rdf) - 1, b32, size+1); + if (size > 0) { + ldns_buffer_printf(output, "%s", b32); + } + LDNS_FREE(b32); + return ldns_buffer_status(output); +} + +ldns_status +ldns_rdf2buffer_str_hex(ldns_buffer *output, const ldns_rdf *rdf) +{ + size_t i; + for (i = 0; i < ldns_rdf_size(rdf); i++) { + ldns_buffer_printf(output, "%02x", ldns_rdf_data(rdf)[i]); + } + + return ldns_buffer_status(output); +} + +ldns_status +ldns_rdf2buffer_str_type(ldns_buffer *output, const ldns_rdf *rdf) +{ + uint16_t data = ldns_read_uint16(ldns_rdf_data(rdf)); + const ldns_rr_descriptor *descriptor; + + descriptor = ldns_rr_descript(data); + if (descriptor && descriptor->_name) { + ldns_buffer_printf(output, "%s", descriptor->_name); + } else { + ldns_buffer_printf(output, "TYPE%u", data); + } + return ldns_buffer_status(output); +} + +ldns_status +ldns_rdf2buffer_str_class(ldns_buffer *output, const ldns_rdf *rdf) +{ + uint16_t data = ldns_read_uint16(ldns_rdf_data(rdf)); + ldns_lookup_table *lt; + + lt = ldns_lookup_by_id(ldns_rr_classes, (int) data); + if (lt) { + ldns_buffer_printf(output, "\t%s", lt->name); + } else { + ldns_buffer_printf(output, "\tCLASS%d", data); + } + return ldns_buffer_status(output); +} + +ldns_status +ldns_rdf2buffer_str_cert_alg(ldns_buffer *output, const ldns_rdf *rdf) +{ + uint16_t data = ldns_read_uint16(ldns_rdf_data(rdf)); + ldns_lookup_table *lt; + lt = ldns_lookup_by_id(ldns_cert_algorithms, (int) data); + if (lt) { + ldns_buffer_printf(output, "%s", lt->name); + } else { + ldns_buffer_printf(output, "%d", data); + } + return ldns_buffer_status(output); +} + +ldns_status +ldns_rdf2buffer_str_alg(ldns_buffer *output, const ldns_rdf *rdf) +{ + /* don't use algorithm mnemonics in the presentation format + this kind of got sneaked into the rfc's */ + uint8_t data = ldns_rdf_data(rdf)[0]; + ldns_buffer_printf(output, "%d", data); + return ldns_buffer_status(output); +} + +static void +loc_cm_print(ldns_buffer *output, uint8_t mantissa, uint8_t exponent) +{ + uint8_t i; + /* is it 0. ? */ + if(exponent < 2) { + if(exponent == 1) + mantissa *= 10; + ldns_buffer_printf(output, "0.%02ld", (long)mantissa); + return; + } + /* always */ + ldns_buffer_printf(output, "%d", (int)mantissa); + for(i=0; i_name) { + ldns_buffer_printf(output, "%s", descriptor->_name); + } else { + /* exceptions for pseudotypes */ + switch (type) { + case LDNS_RR_TYPE_IXFR: + ldns_buffer_printf(output, "IXFR"); + break; + case LDNS_RR_TYPE_AXFR: + ldns_buffer_printf(output, "AXFR"); + break; + case LDNS_RR_TYPE_MAILA: + ldns_buffer_printf(output, "MAILA"); + break; + case LDNS_RR_TYPE_MAILB: + ldns_buffer_printf(output, "MAILB"); + break; + case LDNS_RR_TYPE_ANY: + ldns_buffer_printf(output, "ANY"); + break; + default: + ldns_buffer_printf(output, "TYPE%u", type); + } + } + return ldns_buffer_status(output); +} + +char * +ldns_rr_type2str(const ldns_rr_type type) +{ + char *str; + ldns_buffer *buf; + + buf = ldns_buffer_new(10); + if (!buf) { + return NULL; + } + + str = NULL; + if (ldns_rr_type2buffer_str(buf, type) == LDNS_STATUS_OK) { + str = ldns_buffer2str(buf); + } + + ldns_buffer_free(buf); + return str; +} + + +ldns_status +ldns_rr_class2buffer_str(ldns_buffer *output, + const ldns_rr_class klass) +{ + ldns_lookup_table *lt; + + lt = ldns_lookup_by_id(ldns_rr_classes, klass); + if (lt) { + ldns_buffer_printf(output, "%s", lt->name); + } else { + ldns_buffer_printf(output, "CLASS%d", klass); + } + return ldns_buffer_status(output); +} + +char * +ldns_rr_class2str(const ldns_rr_class klass) +{ + ldns_buffer *buf; + char *str; + + buf = ldns_buffer_new(10); + if (!buf) { + return NULL; + } + + str = NULL; + if (ldns_rr_class2buffer_str(buf, klass) == LDNS_STATUS_OK) { + str = ldns_buffer2str(buf); + } + ldns_buffer_free(buf); + return str; +} + +ldns_status +ldns_rdf2buffer_str_loc(ldns_buffer *output, const ldns_rdf *rdf) +{ + /* we could do checking (ie degrees < 90 etc)? */ + uint8_t version = ldns_rdf_data(rdf)[0]; + uint8_t size; + uint8_t horizontal_precision; + uint8_t vertical_precision; + uint32_t longitude; + uint32_t latitude; + uint32_t altitude; + char northerness; + char easterness; + uint32_t h; + uint32_t m; + double s; + + uint32_t equator = (uint32_t) ldns_power(2, 31); + + if (version == 0) { + size = ldns_rdf_data(rdf)[1]; + horizontal_precision = ldns_rdf_data(rdf)[2]; + vertical_precision = ldns_rdf_data(rdf)[3]; + + latitude = ldns_read_uint32(&ldns_rdf_data(rdf)[4]); + longitude = ldns_read_uint32(&ldns_rdf_data(rdf)[8]); + altitude = ldns_read_uint32(&ldns_rdf_data(rdf)[12]); + + if (latitude > equator) { + northerness = 'N'; + latitude = latitude - equator; + } else { + northerness = 'S'; + latitude = equator - latitude; + } + h = latitude / (1000 * 60 * 60); + latitude = latitude % (1000 * 60 * 60); + m = latitude / (1000 * 60); + latitude = latitude % (1000 * 60); + s = (double) latitude / 1000.0; + ldns_buffer_printf(output, "%02u %02u %0.3f %c ", + h, m, s, northerness); + + if (longitude > equator) { + easterness = 'E'; + longitude = longitude - equator; + } else { + easterness = 'W'; + longitude = equator - longitude; + } + h = longitude / (1000 * 60 * 60); + longitude = longitude % (1000 * 60 * 60); + m = longitude / (1000 * 60); + longitude = longitude % (1000 * 60); + s = (double) longitude / (1000.0); + ldns_buffer_printf(output, "%02u %02u %0.3f %c ", + h, m, s, easterness); + + + s = ((double) altitude) / 100; + s -= 100000; + + if(altitude%100 != 0) + ldns_buffer_printf(output, "%.2f", s); + else + ldns_buffer_printf(output, "%.0f", s); + + ldns_buffer_printf(output, "m "); + + loc_cm_print(output, (size & 0xf0) >> 4, size & 0x0f); + ldns_buffer_printf(output, "m "); + + loc_cm_print(output, (horizontal_precision & 0xf0) >> 4, + horizontal_precision & 0x0f); + ldns_buffer_printf(output, "m "); + + loc_cm_print(output, (vertical_precision & 0xf0) >> 4, + vertical_precision & 0x0f); + ldns_buffer_printf(output, "m"); + + return ldns_buffer_status(output); + } else { + return ldns_rdf2buffer_str_hex(output, rdf); + } +} + +ldns_status +ldns_rdf2buffer_str_unknown(ldns_buffer *output, const ldns_rdf *rdf) +{ + ldns_buffer_printf(output, "\\# %u ", ldns_rdf_size(rdf)); + return ldns_rdf2buffer_str_hex(output, rdf); +} + +ldns_status +ldns_rdf2buffer_str_nsap(ldns_buffer *output, const ldns_rdf *rdf) +{ + ldns_buffer_printf(output, "0x"); + return ldns_rdf2buffer_str_hex(output, rdf); +} + +ldns_status +ldns_rdf2buffer_str_atma(ldns_buffer *output, const ldns_rdf *rdf) +{ + return ldns_rdf2buffer_str_hex(output, rdf); +} + +ldns_status +ldns_rdf2buffer_str_wks(ldns_buffer *output, const ldns_rdf *rdf) +{ + /* protocol, followed by bitmap of services */ + struct protoent *protocol; + char *proto_name = NULL; + uint8_t protocol_nr; + struct servent *service; + uint16_t current_service; + + protocol_nr = ldns_rdf_data(rdf)[0]; + protocol = getprotobynumber((int) protocol_nr); + if (protocol && (protocol->p_name != NULL)) { + proto_name = protocol->p_name; + ldns_buffer_printf(output, "%s ", protocol->p_name); + } else { + ldns_buffer_printf(output, "%u ", protocol_nr); + } + +#ifdef HAVE_ENDPROTOENT + endprotoent(); +#endif + + for (current_service = 0; + current_service < ldns_rdf_size(rdf) * 7; current_service++) { + if (ldns_get_bit(&(ldns_rdf_data(rdf)[1]), current_service)) { + service = getservbyport((int) htons(current_service), + proto_name); + if (service && service->s_name) { + ldns_buffer_printf(output, "%s ", service->s_name); + } else { + ldns_buffer_printf(output, "%u ", current_service); + } +#ifdef HAVE_ENDSERVENT + endservent(); +#endif + } + } + return ldns_buffer_status(output); +} + +ldns_status +ldns_rdf2buffer_str_nsec(ldns_buffer *output, const ldns_rdf *rdf) +{ + /* Note: this code is duplicated in higher.c in + * ldns_nsec_type_check() function + */ + uint8_t window_block_nr; + uint8_t bitmap_length; + uint16_t type; + uint16_t pos = 0; + uint16_t bit_pos; + uint8_t *data = ldns_rdf_data(rdf); + const ldns_rr_descriptor *descriptor; + + while(pos < ldns_rdf_size(rdf)) { + window_block_nr = data[pos]; + bitmap_length = data[pos + 1]; + pos += 2; + + for (bit_pos = 0; bit_pos < (bitmap_length) * 8; bit_pos++) { + if (ldns_get_bit(&data[pos], bit_pos)) { + type = 256 * (uint16_t) window_block_nr + bit_pos; + descriptor = ldns_rr_descript(type); + + if (descriptor && descriptor->_name) { + ldns_buffer_printf(output, "%s ", + descriptor->_name); + } else { + ldns_buffer_printf(output, "TYPE%u ", type); + } + } + } + + pos += (uint16_t) bitmap_length; + } + + return ldns_buffer_status(output); +} + +ldns_status +ldns_rdf2buffer_str_nsec3_salt(ldns_buffer *output, const ldns_rdf *rdf) +{ + uint8_t salt_length; + uint8_t salt_pos; + + uint8_t *data = ldns_rdf_data(rdf); + + if(ldns_rdf_size(rdf) == 0) { + output->_status = LDNS_STATUS_ERR; + return ldns_buffer_status(output); + } + salt_length = data[0]; + /* from now there are variable length entries so remember pos */ + if (salt_length == 0 || ((size_t)salt_length)+1 > ldns_rdf_size(rdf)) { + ldns_buffer_printf(output, "- "); + } else { + for (salt_pos = 0; salt_pos < salt_length; salt_pos++) { + ldns_buffer_printf(output, "%02x", data[1 + salt_pos]); + } + ldns_buffer_printf(output, " "); + } + + return ldns_buffer_status(output); +} + +ldns_status +ldns_rdf2buffer_str_period(ldns_buffer *output, const ldns_rdf *rdf) +{ + /* period is the number of seconds */ + uint32_t p = ldns_read_uint32(ldns_rdf_data(rdf)); + ldns_buffer_printf(output, "%u", p); + return ldns_buffer_status(output); +} + +ldns_status +ldns_rdf2buffer_str_tsigtime(ldns_buffer *output,const ldns_rdf *rdf) +{ + /* tsigtime is 48 bits network order unsigned integer */ + uint64_t tsigtime = 0; + uint8_t *data = ldns_rdf_data(rdf); + + if (ldns_rdf_size(rdf) != 6) { + return LDNS_STATUS_ERR; + } + + tsigtime = ldns_read_uint16(data); + tsigtime *= 65536; + tsigtime += ldns_read_uint16(data+2); + tsigtime *= 65536; + + ldns_buffer_printf(output, "%llu ", tsigtime); + + return ldns_buffer_status(output); +} + +ldns_status +ldns_rdf2buffer_str_apl(ldns_buffer *output, const ldns_rdf *rdf) +{ + uint8_t *data = ldns_rdf_data(rdf); + uint16_t address_family; + uint8_t prefix; + bool negation; + uint8_t adf_length; + size_t i; + size_t pos = 0; + + while (pos < (unsigned int) ldns_rdf_size(rdf)) { + if(pos + 3 >= (unsigned)ldns_rdf_size(rdf)) + return LDNS_STATUS_SYNTAX_RDATA_ERR; + address_family = ldns_read_uint16(&data[pos]); + prefix = data[pos + 2]; + negation = data[pos + 3] & LDNS_APL_NEGATION; + adf_length = data[pos + 3] & LDNS_APL_MASK; + if (address_family == LDNS_APL_IP4) { + /* check if prefix < 32? */ + if (negation) { + ldns_buffer_printf(output, "!"); + } + ldns_buffer_printf(output, "%u:", address_family); + /* address is variable length 0 - 4 */ + for (i = 0; i < 4; i++) { + if (i > 0) { + ldns_buffer_printf(output, "."); + } + if (i < (unsigned short) adf_length) { + if(pos+i+4 >= ldns_rdf_size(rdf)) + return LDNS_STATUS_SYNTAX_RDATA_ERR; + ldns_buffer_printf(output, "%d", + data[pos + i + 4]); + } else { + ldns_buffer_printf(output, "0"); + } + } + ldns_buffer_printf(output, "/%u ", prefix); + } else if (address_family == LDNS_APL_IP6) { + /* check if prefix < 128? */ + if (negation) { + ldns_buffer_printf(output, "!"); + } + ldns_buffer_printf(output, "%u:", address_family); + /* address is variable length 0 - 16 */ + for (i = 0; i < 16; i++) { + if (i % 2 == 0 && i > 0) { + ldns_buffer_printf(output, ":"); + } + if (i < (unsigned short) adf_length) { + if(pos+i+4 >= ldns_rdf_size(rdf)) + return LDNS_STATUS_SYNTAX_RDATA_ERR; + ldns_buffer_printf(output, "%02x", + data[pos + i + 4]); + } else { + ldns_buffer_printf(output, "00"); + } + } + ldns_buffer_printf(output, "/%u ", prefix); + + } else { + /* unknown address family */ + ldns_buffer_printf(output, "Unknown address family: %u data: ", + address_family); + for (i = 1; i < (unsigned short) (4 + adf_length); i++) { + if(pos+i >= ldns_rdf_size(rdf)) + return LDNS_STATUS_SYNTAX_RDATA_ERR; + ldns_buffer_printf(output, "%02x", data[i]); + } + } + pos += 4 + adf_length; + } + return ldns_buffer_status(output); +} + +ldns_status +ldns_rdf2buffer_str_int16_data(ldns_buffer *output, const ldns_rdf *rdf) +{ + /* Subtract the size (2) of the number that specifies the length */ + size_t size = ldns_b64_ntop_calculate_size(ldns_rdf_size(rdf) - 2); + char *b64 = LDNS_XMALLOC(char, size); + if(!b64) + return LDNS_STATUS_MEM_ERR; + + ldns_buffer_printf(output, "%u ", ldns_rdf_size(rdf) - 2); + + if (ldns_rdf_size(rdf) > 2 && + ldns_b64_ntop(ldns_rdf_data(rdf) + 2, + ldns_rdf_size(rdf) - 2, + b64, size)) { + ldns_buffer_printf(output, "%s", b64); + } + LDNS_FREE(b64); + return ldns_buffer_status(output); +} + +ldns_status +ldns_rdf2buffer_str_ipseckey(ldns_buffer *output, const ldns_rdf *rdf) +{ + /* wire format from + http://www.ietf.org/internet-drafts/draft-ietf-ipseckey-rr-12.txt + */ + uint8_t *data = ldns_rdf_data(rdf); + uint8_t precedence; + uint8_t gateway_type; + uint8_t algorithm; + + ldns_rdf *gateway = NULL; + uint8_t *gateway_data; + + size_t public_key_size; + uint8_t *public_key_data; + ldns_rdf *public_key; + + size_t offset = 0; + ldns_status status; + + precedence = data[0]; + gateway_type = data[1]; + algorithm = data[2]; + offset = 3; + + switch (gateway_type) { + case 0: + /* no gateway */ + break; + case 1: + gateway_data = LDNS_XMALLOC(uint8_t, LDNS_IP4ADDRLEN); + if(!gateway_data) + return LDNS_STATUS_MEM_ERR; + memcpy(gateway_data, &data[offset], LDNS_IP4ADDRLEN); + gateway = ldns_rdf_new(LDNS_RDF_TYPE_A, LDNS_IP4ADDRLEN , gateway_data); + offset += LDNS_IP4ADDRLEN; + if(!gateway) { + LDNS_FREE(gateway_data); + return LDNS_STATUS_MEM_ERR; + } + break; + case 2: + gateway_data = LDNS_XMALLOC(uint8_t, LDNS_IP6ADDRLEN); + if(!gateway_data) + return LDNS_STATUS_MEM_ERR; + memcpy(gateway_data, &data[offset], LDNS_IP6ADDRLEN); + offset += LDNS_IP6ADDRLEN; + gateway = + ldns_rdf_new(LDNS_RDF_TYPE_AAAA, LDNS_IP6ADDRLEN, gateway_data); + if(!gateway) { + LDNS_FREE(gateway_data); + return LDNS_STATUS_MEM_ERR; + } + break; + case 3: + status = ldns_wire2dname(&gateway, data, ldns_rdf_size(rdf), &offset); + if(status != LDNS_STATUS_OK) + return status; + break; + default: + /* error? */ + break; + } + + public_key_size = ldns_rdf_size(rdf) - offset; + public_key_data = LDNS_XMALLOC(uint8_t, public_key_size); + if(!public_key_data) { + ldns_rdf_free(gateway); + return LDNS_STATUS_MEM_ERR; + } + memcpy(public_key_data, &data[offset], public_key_size); + public_key = ldns_rdf_new(LDNS_RDF_TYPE_B64, public_key_size, public_key_data); + if(!public_key) { + LDNS_FREE(public_key_data); + ldns_rdf_free(gateway); + return LDNS_STATUS_MEM_ERR; + } + + ldns_buffer_printf(output, "%u %u %u ", precedence, gateway_type, algorithm); + if (gateway) + (void) ldns_rdf2buffer_str(output, gateway); + else + ldns_buffer_printf(output, "."); + ldns_buffer_printf(output, " "); + (void) ldns_rdf2buffer_str(output, public_key); + + ldns_rdf_free(gateway); + ldns_rdf_free(public_key); + + return ldns_buffer_status(output); +} + +ldns_status +ldns_rdf2buffer_str_tsig(ldns_buffer *output, const ldns_rdf *rdf) +{ + /* TSIG RRs have no presentation format, make them #size */ + return ldns_rdf2buffer_str_unknown(output, rdf); +} + + +ldns_status +ldns_rdf2buffer_str(ldns_buffer *buffer, const ldns_rdf *rdf) +{ + ldns_status res = LDNS_STATUS_OK; + + /*ldns_buffer_printf(buffer, "%u:", ldns_rdf_get_type(rdf));*/ + if (rdf) { + switch(ldns_rdf_get_type(rdf)) { + case LDNS_RDF_TYPE_NONE: + break; + case LDNS_RDF_TYPE_DNAME: + res = ldns_rdf2buffer_str_dname(buffer, rdf); + break; + case LDNS_RDF_TYPE_INT8: + res = ldns_rdf2buffer_str_int8(buffer, rdf); + break; + case LDNS_RDF_TYPE_INT16: + res = ldns_rdf2buffer_str_int16(buffer, rdf); + break; + case LDNS_RDF_TYPE_INT32: + res = ldns_rdf2buffer_str_int32(buffer, rdf); + break; + case LDNS_RDF_TYPE_PERIOD: + res = ldns_rdf2buffer_str_period(buffer, rdf); + break; + case LDNS_RDF_TYPE_TSIGTIME: + res = ldns_rdf2buffer_str_tsigtime(buffer, rdf); + break; + case LDNS_RDF_TYPE_A: + res = ldns_rdf2buffer_str_a(buffer, rdf); + break; + case LDNS_RDF_TYPE_AAAA: + res = ldns_rdf2buffer_str_aaaa(buffer, rdf); + break; + case LDNS_RDF_TYPE_STR: + res = ldns_rdf2buffer_str_str(buffer, rdf); + break; + case LDNS_RDF_TYPE_APL: + res = ldns_rdf2buffer_str_apl(buffer, rdf); + break; + case LDNS_RDF_TYPE_B32_EXT: + res = ldns_rdf2buffer_str_b32_ext(buffer, rdf); + break; + case LDNS_RDF_TYPE_B64: + res = ldns_rdf2buffer_str_b64(buffer, rdf); + break; + case LDNS_RDF_TYPE_HEX: + res = ldns_rdf2buffer_str_hex(buffer, rdf); + break; + case LDNS_RDF_TYPE_NSEC: + res = ldns_rdf2buffer_str_nsec(buffer, rdf); + break; + case LDNS_RDF_TYPE_NSEC3_SALT: + res = ldns_rdf2buffer_str_nsec3_salt(buffer, rdf); + break; + case LDNS_RDF_TYPE_TYPE: + res = ldns_rdf2buffer_str_type(buffer, rdf); + break; + case LDNS_RDF_TYPE_CLASS: + res = ldns_rdf2buffer_str_class(buffer, rdf); + break; + case LDNS_RDF_TYPE_CERT_ALG: + res = ldns_rdf2buffer_str_cert_alg(buffer, rdf); + break; + case LDNS_RDF_TYPE_ALG: + res = ldns_rdf2buffer_str_alg(buffer, rdf); + break; + case LDNS_RDF_TYPE_UNKNOWN: + res = ldns_rdf2buffer_str_unknown(buffer, rdf); + break; + case LDNS_RDF_TYPE_TIME: + res = ldns_rdf2buffer_str_time(buffer, rdf); + break; + case LDNS_RDF_TYPE_LOC: + res = ldns_rdf2buffer_str_loc(buffer, rdf); + break; + case LDNS_RDF_TYPE_WKS: + case LDNS_RDF_TYPE_SERVICE: + res = ldns_rdf2buffer_str_wks(buffer, rdf); + break; + case LDNS_RDF_TYPE_NSAP: + res = ldns_rdf2buffer_str_nsap(buffer, rdf); + break; + case LDNS_RDF_TYPE_ATMA: + res = ldns_rdf2buffer_str_atma(buffer, rdf); + break; + case LDNS_RDF_TYPE_IPSECKEY: + res = ldns_rdf2buffer_str_ipseckey(buffer, rdf); + break; + case LDNS_RDF_TYPE_TSIG: + res = ldns_rdf2buffer_str_tsig(buffer, rdf); + break; + case LDNS_RDF_TYPE_INT16_DATA: + res = ldns_rdf2buffer_str_int16_data(buffer, rdf); + break; + case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER: + res = ldns_rdf2buffer_str_b32_ext(buffer, rdf); + break; + } + } else { + ldns_buffer_printf(buffer, "(null) "); + res = ldns_buffer_status(buffer); + } + return res; +} + +ldns_rdf * +ldns_b32_ext2dname(const ldns_rdf *rdf) +{ + size_t size; + char *b32; + ldns_rdf *out; + if(ldns_rdf_size(rdf) == 0) + return NULL; + /* remove -1 for the b32-hash-len octet */ + size = ldns_b32_ntop_calculate_size(ldns_rdf_size(rdf) - 1); + /* add one for the end nul for the string */ + b32 = LDNS_XMALLOC(char, size + 2); + if (b32) { + if (ldns_b32_ntop_extended_hex(ldns_rdf_data(rdf) + 1, + ldns_rdf_size(rdf) - 1, b32, size+1) > 0) { + b32[size] = '.'; + b32[size+1] = '\0'; + if (ldns_str2rdf_dname(&out, b32) == LDNS_STATUS_OK) { + LDNS_FREE(b32); + return out; + } + } + LDNS_FREE(b32); + } + return NULL; +} + +ldns_status +ldns_rr2buffer_str_fmt(ldns_buffer *output, + const ldns_output_format *fmt, const ldns_rr *rr) +{ + uint16_t i, flags; + ldns_status status = LDNS_STATUS_OK; + + if (fmt == NULL) { + fmt = ldns_output_format_default; + } + if (!rr) { + if (LDNS_COMMENT_NULLS & fmt->flags) { + ldns_buffer_printf(output, "; (null)\n"); + } + return ldns_buffer_status(output); + } + if (ldns_rr_owner(rr)) { + status = ldns_rdf2buffer_str_dname(output, ldns_rr_owner(rr)); + } + if (status != LDNS_STATUS_OK) { + return status; + } + + /* TTL should NOT be printed if it is a question */ + if (!ldns_rr_is_question(rr)) { + ldns_buffer_printf(output, "\t%d", ldns_rr_ttl(rr)); + } + + ldns_buffer_printf(output, "\t"); + status = ldns_rr_class2buffer_str(output, ldns_rr_get_class(rr)); + if (status != LDNS_STATUS_OK) { + return status; + } + ldns_buffer_printf(output, "\t"); + + status = ldns_rr_type2buffer_str(output, ldns_rr_get_type(rr)); + if (status != LDNS_STATUS_OK) { + return status; + } + + if (ldns_rr_rd_count(rr) > 0) { + ldns_buffer_printf(output, "\t"); + } else if (!ldns_rr_is_question(rr)) { + ldns_buffer_printf(output, "\t\\# 0"); + } + + for (i = 0; i < ldns_rr_rd_count(rr); i++) { + /* ldns_rdf2buffer_str handles NULL input fine! */ + status = ldns_rdf2buffer_str(output, ldns_rr_rdf(rr, i)); + if(status != LDNS_STATUS_OK) + return status; + if (i < ldns_rr_rd_count(rr) - 1) { + ldns_buffer_printf(output, " "); + } + } + /* per RR special comments - handy for DNSSEC types */ + /* check to prevent question sec. rr from + * getting here */ + if (ldns_rr_rd_count(rr) > 0) { + switch (ldns_rr_get_type(rr)) { + case LDNS_RR_TYPE_DNSKEY: + /* if ldns_rr_rd_count(rr) > 0 + then ldns_rr_rdf(rr, 0) exists! */ + if (! (fmt->flags & LDNS_COMMENT_KEY)) { + break; + } + flags = ldns_rdf2native_int16( + ldns_rr_rdf(rr, 0)); + ldns_buffer_printf(output, " ;{"); + if (fmt->flags & LDNS_COMMENT_KEY_ID) { + ldns_buffer_printf(output, "id = %u", + (unsigned int) + ldns_calc_keytag(rr)); + } + if ((fmt->flags & LDNS_COMMENT_KEY_TYPE) + && (flags & LDNS_KEY_ZONE_KEY)){ + if (flags & LDNS_KEY_SEP_KEY) { + ldns_buffer_printf( + output, " (ksk)"); + } + else { + ldns_buffer_printf( + output, " (zsk)"); + } + if (fmt->flags & LDNS_COMMENT_KEY_SIZE){ + ldns_buffer_printf( + output, ", "); + } + } else if (fmt->flags + & (LDNS_COMMENT_KEY_ID + |LDNS_COMMENT_KEY_SIZE)) { + ldns_buffer_printf( output, ", "); + } + if (fmt->flags & LDNS_COMMENT_KEY_SIZE) { + ldns_buffer_printf(output, "size = %db", + ldns_rr_dnskey_key_size(rr)); + } + ldns_buffer_printf(output, "}"); + break; + case LDNS_RR_TYPE_RRSIG: + if ((fmt->flags & LDNS_COMMENT_KEY) + && (fmt->flags + & LDNS_COMMENT_RRSIGS) + && ldns_rr_rdf(rr, 6) != NULL) { + ldns_buffer_printf(output + , " ;{id = %d}" + , ldns_rdf2native_int16( + ldns_rr_rdf(rr, 6))); + } + break; + case LDNS_RR_TYPE_DS: + if ((fmt->flags & LDNS_COMMENT_BUBBLEBABBLE) + && ldns_rr_rdf(rr, 3) != NULL) { + uint8_t *data = ldns_rdf_data( + ldns_rr_rdf(rr, 3)); + size_t len = ldns_rdf_size( + ldns_rr_rdf(rr, 3)); + char *babble = ldns_bubblebabble( + data, len); + if(babble) { + ldns_buffer_printf(output + , " ;{%s}", babble); + } + LDNS_FREE(babble); + } + break; + case LDNS_RR_TYPE_NSEC3: + if (! (fmt->flags & LDNS_COMMENT_FLAGS) && + ! (fmt->flags & LDNS_COMMENT_NSEC3_CHAIN)) { + break; + } + ldns_buffer_printf(output, " ;{"); + if ((fmt->flags & LDNS_COMMENT_FLAGS)) { + if (ldns_nsec3_optout(rr)) { + ldns_buffer_printf(output, + " flags: optout"); + } else { + ldns_buffer_printf(output, + " flags: -"); + } + if (fmt->flags & LDNS_COMMENT_NSEC3_CHAIN + && fmt->data != NULL) { + ldns_buffer_printf(output, ", "); + } + } + if (fmt->flags & LDNS_COMMENT_NSEC3_CHAIN + && fmt->data != NULL) { + ldns_rbnode_t *node; + ldns_rdf *key = ldns_dname_label( + ldns_rr_owner(rr), 0); + if (key) { + node = ldns_rbtree_search( + (ldns_rbtree_t *) + fmt->data, + (void *) key); + if (node->data) { + ldns_buffer_printf( + output, + "from: "); + (void) + ldns_rdf2buffer_str( + output, + (ldns_rdf *) + node->data); + } + ldns_rdf_free(key); + } + key = ldns_b32_ext2dname( + ldns_nsec3_next_owner(rr)); + if (key) { + node = ldns_rbtree_search( + (ldns_rbtree_t *) + fmt->data, + (void *) key); + if (node->data) { + ldns_buffer_printf( + output, + " to: "); + (void) + ldns_rdf2buffer_str( + output, + (ldns_rdf *) + node->data); + } + ldns_rdf_free(key); + } + } + ldns_buffer_printf(output, "}"); + break; + default: + break; + + } + } + /* last */ + ldns_buffer_printf(output, "\n"); + return ldns_buffer_status(output); +} + +ldns_status +ldns_rr2buffer_str(ldns_buffer *output, const ldns_rr *rr) +{ + return ldns_rr2buffer_str_fmt(output, ldns_output_format_default, rr); +} + +ldns_status +ldns_rr_list2buffer_str_fmt(ldns_buffer *output, + const ldns_output_format *fmt, const ldns_rr_list *list) +{ + uint16_t i; + + for(i = 0; i < ldns_rr_list_rr_count(list); i++) { + (void) ldns_rr2buffer_str_fmt(output, fmt, + ldns_rr_list_rr(list, i)); + } + return ldns_buffer_status(output); +} + +ldns_status +ldns_rr_list2buffer_str(ldns_buffer *output, const ldns_rr_list *list) +{ + return ldns_rr_list2buffer_str_fmt( + output, ldns_output_format_default, list); +} + +ldns_status +ldns_pktheader2buffer_str(ldns_buffer *output, const ldns_pkt *pkt) +{ + ldns_lookup_table *opcode = ldns_lookup_by_id(ldns_opcodes, + (int) ldns_pkt_get_opcode(pkt)); + ldns_lookup_table *rcode = ldns_lookup_by_id(ldns_rcodes, + (int) ldns_pkt_get_rcode(pkt)); + + ldns_buffer_printf(output, ";; ->>HEADER<<- "); + if (opcode) { + ldns_buffer_printf(output, "opcode: %s, ", opcode->name); + } else { + ldns_buffer_printf(output, "opcode: ?? (%u), ", + ldns_pkt_get_opcode(pkt)); + } + if (rcode) { + ldns_buffer_printf(output, "rcode: %s, ", rcode->name); + } else { + ldns_buffer_printf(output, "rcode: ?? (%u), ", ldns_pkt_get_rcode(pkt)); + } + ldns_buffer_printf(output, "id: %d\n", ldns_pkt_id(pkt)); + ldns_buffer_printf(output, ";; flags: "); + + if (ldns_pkt_qr(pkt)) { + ldns_buffer_printf(output, "qr "); + } + if (ldns_pkt_aa(pkt)) { + ldns_buffer_printf(output, "aa "); + } + if (ldns_pkt_tc(pkt)) { + ldns_buffer_printf(output, "tc "); + } + if (ldns_pkt_rd(pkt)) { + ldns_buffer_printf(output, "rd "); + } + if (ldns_pkt_cd(pkt)) { + ldns_buffer_printf(output, "cd "); + } + if (ldns_pkt_ra(pkt)) { + ldns_buffer_printf(output, "ra "); + } + if (ldns_pkt_ad(pkt)) { + ldns_buffer_printf(output, "ad "); + } + ldns_buffer_printf(output, "; "); + ldns_buffer_printf(output, "QUERY: %u, ", ldns_pkt_qdcount(pkt)); + ldns_buffer_printf(output, "ANSWER: %u, ", ldns_pkt_ancount(pkt)); + ldns_buffer_printf(output, "AUTHORITY: %u, ", ldns_pkt_nscount(pkt)); + ldns_buffer_printf(output, "ADDITIONAL: %u ", ldns_pkt_arcount(pkt)); + return ldns_buffer_status(output); +} + +ldns_status +ldns_pkt2buffer_str_fmt(ldns_buffer *output, + const ldns_output_format *fmt, const ldns_pkt *pkt) +{ + uint16_t i; + ldns_status status = LDNS_STATUS_OK; + char *tmp; + struct timeval time; + time_t time_tt; + + if (!pkt) { + ldns_buffer_printf(output, "null"); + return LDNS_STATUS_OK; + } + + if (ldns_buffer_status_ok(output)) { + status = ldns_pktheader2buffer_str(output, pkt); + if (status != LDNS_STATUS_OK) { + return status; + } + + ldns_buffer_printf(output, "\n"); + + ldns_buffer_printf(output, ";; QUESTION SECTION:\n;; "); + + + for (i = 0; i < ldns_pkt_qdcount(pkt); i++) { + status = ldns_rr2buffer_str_fmt(output, fmt, + ldns_rr_list_rr( + ldns_pkt_question(pkt), i)); + if (status != LDNS_STATUS_OK) { + return status; + } + } + ldns_buffer_printf(output, "\n"); + + ldns_buffer_printf(output, ";; ANSWER SECTION:\n"); + for (i = 0; i < ldns_pkt_ancount(pkt); i++) { + status = ldns_rr2buffer_str_fmt(output, fmt, + ldns_rr_list_rr( + ldns_pkt_answer(pkt), i)); + if (status != LDNS_STATUS_OK) { + return status; + } + + } + ldns_buffer_printf(output, "\n"); + + ldns_buffer_printf(output, ";; AUTHORITY SECTION:\n"); + + for (i = 0; i < ldns_pkt_nscount(pkt); i++) { + status = ldns_rr2buffer_str_fmt(output, fmt, + ldns_rr_list_rr( + ldns_pkt_authority(pkt), i)); + if (status != LDNS_STATUS_OK) { + return status; + } + } + ldns_buffer_printf(output, "\n"); + + ldns_buffer_printf(output, ";; ADDITIONAL SECTION:\n"); + for (i = 0; i < ldns_pkt_arcount(pkt); i++) { + status = ldns_rr2buffer_str_fmt(output, fmt, + ldns_rr_list_rr( + ldns_pkt_additional(pkt), i)); + if (status != LDNS_STATUS_OK) { + return status; + } + + } + ldns_buffer_printf(output, "\n"); + /* add some futher fields */ + ldns_buffer_printf(output, ";; Query time: %d msec\n", + ldns_pkt_querytime(pkt)); + if (ldns_pkt_edns(pkt)) { + ldns_buffer_printf(output, + ";; EDNS: version %u; flags:", + ldns_pkt_edns_version(pkt)); + if (ldns_pkt_edns_do(pkt)) { + ldns_buffer_printf(output, " do"); + } + /* the extended rcode is the value set, shifted four bits, + * and or'd with the original rcode */ + if (ldns_pkt_edns_extended_rcode(pkt)) { + ldns_buffer_printf(output, " ; ext-rcode: %d", + (ldns_pkt_edns_extended_rcode(pkt) << 4 | ldns_pkt_get_rcode(pkt))); + } + ldns_buffer_printf(output, " ; udp: %u\n", + ldns_pkt_edns_udp_size(pkt)); + + if (ldns_pkt_edns_data(pkt)) { + ldns_buffer_printf(output, ";; Data: "); + (void)ldns_rdf2buffer_str(output, + ldns_pkt_edns_data(pkt)); + ldns_buffer_printf(output, "\n"); + } + } + if (ldns_pkt_tsig(pkt)) { + ldns_buffer_printf(output, ";; TSIG:\n;; "); + (void) ldns_rr2buffer_str_fmt( + output, fmt, ldns_pkt_tsig(pkt)); + ldns_buffer_printf(output, "\n"); + } + if (ldns_pkt_answerfrom(pkt)) { + tmp = ldns_rdf2str(ldns_pkt_answerfrom(pkt)); + ldns_buffer_printf(output, ";; SERVER: %s\n", tmp); + LDNS_FREE(tmp); + } + time = ldns_pkt_timestamp(pkt); + time_tt = (time_t)time.tv_sec; + ldns_buffer_printf(output, ";; WHEN: %s", + (char*)ctime(&time_tt)); + + ldns_buffer_printf(output, ";; MSG SIZE rcvd: %d\n", + (int)ldns_pkt_size(pkt)); + } else { + return ldns_buffer_status(output); + } + return status; +} + +ldns_status +ldns_pkt2buffer_str(ldns_buffer *output, const ldns_pkt *pkt) +{ + return ldns_pkt2buffer_str_fmt(output, ldns_output_format_default, pkt); +} + + +#ifdef HAVE_SSL +static ldns_status +ldns_hmac_key2buffer_str(ldns_buffer *output, const ldns_key *k) +{ + ldns_status status; + size_t i; + ldns_rdf *b64_bignum; + + ldns_buffer_printf(output, "Key: "); + + i = ldns_key_hmac_size(k); + b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, ldns_key_hmac_key(k)); + status = ldns_rdf2buffer_str(output, b64_bignum); + ldns_rdf_deep_free(b64_bignum); + ldns_buffer_printf(output, "\n"); + return status; +} +#endif + +#if defined(HAVE_SSL) && defined(USE_GOST) +static ldns_status +ldns_gost_key2buffer_str(ldns_buffer *output, EVP_PKEY *p) +{ + unsigned char* pp = NULL; + int ret; + ldns_rdf *b64_bignum; + ldns_status status; + + ldns_buffer_printf(output, "GostAsn1: "); + + ret = i2d_PrivateKey(p, &pp); + b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, (size_t)ret, pp); + status = ldns_rdf2buffer_str(output, b64_bignum); + + ldns_rdf_deep_free(b64_bignum); + OPENSSL_free(pp); + ldns_buffer_printf(output, "\n"); + return status; +} +#endif + +ldns_status +ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) +{ + ldns_status status = LDNS_STATUS_OK; + unsigned char *bignum; +#ifndef S_SPLINT_S + uint16_t i; +#endif + +#ifdef HAVE_SSL + /* not used when ssl is not defined */ + ldns_rdf *b64_bignum = NULL; + + RSA *rsa; + DSA *dsa; +#endif /* HAVE_SSL */ + + if (!k) { + return LDNS_STATUS_ERR; + } + + bignum = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN); + if (!bignum) { + return LDNS_STATUS_ERR; + } + + if (ldns_buffer_status_ok(output)) { +#ifdef HAVE_SSL + switch(ldns_key_algorithm(k)) { + case LDNS_SIGN_RSASHA1: + case LDNS_SIGN_RSASHA1_NSEC3: + case LDNS_SIGN_RSASHA256: + case LDNS_SIGN_RSASHA512: + case LDNS_SIGN_RSAMD5: + /* copied by looking at dnssec-keygen output */ + /* header */ + rsa = ldns_key_rsa_key(k); + + ldns_buffer_printf(output,"Private-key-format: v1.2\n"); + switch(ldns_key_algorithm(k)) { + case LDNS_SIGN_RSAMD5: + ldns_buffer_printf(output, + "Algorithm: %u (RSA)\n", + LDNS_RSAMD5); + break; + case LDNS_SIGN_RSASHA1: + ldns_buffer_printf(output, + "Algorithm: %u (RSASHA1)\n", + LDNS_RSASHA1); + break; + case LDNS_SIGN_RSASHA1_NSEC3: + ldns_buffer_printf(output, + "Algorithm: %u (RSASHA1_NSEC3)\n", + LDNS_RSASHA1_NSEC3); + break; +#ifdef USE_SHA2 + case LDNS_SIGN_RSASHA256: + ldns_buffer_printf(output, + "Algorithm: %u (RSASHA256)\n", + LDNS_RSASHA256); + break; + case LDNS_SIGN_RSASHA512: + ldns_buffer_printf(output, + "Algorithm: %u (RSASHA512)\n", + LDNS_RSASHA512); + break; +#endif + default: + fprintf(stderr, "Warning: unknown signature "); + fprintf(stderr, + "algorithm type %u\n", + ldns_key_algorithm(k)); + ldns_buffer_printf(output, + "Algorithm: %u (Unknown)\n", + ldns_key_algorithm(k)); + break; + } + + /* print to buf, convert to bin, convert to b64, + * print to buf */ + ldns_buffer_printf(output, "Modulus: "); +#ifndef S_SPLINT_S + i = (uint16_t)BN_bn2bin(rsa->n, bignum); + if (i > LDNS_MAX_KEYLEN) { + goto error; + } + b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); + if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + goto error; + } + ldns_rdf_deep_free(b64_bignum); + ldns_buffer_printf(output, "\n"); + ldns_buffer_printf(output, "PublicExponent: "); + i = (uint16_t)BN_bn2bin(rsa->e, bignum); + if (i > LDNS_MAX_KEYLEN) { + goto error; + } + b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); + if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + goto error; + } + ldns_rdf_deep_free(b64_bignum); + ldns_buffer_printf(output, "\n"); + + ldns_buffer_printf(output, "PrivateExponent: "); + if (rsa->d) { + i = (uint16_t)BN_bn2bin(rsa->d, bignum); + if (i > LDNS_MAX_KEYLEN) { + goto error; + } + b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); + if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + goto error; + } + ldns_rdf_deep_free(b64_bignum); + ldns_buffer_printf(output, "\n"); + } else { + ldns_buffer_printf(output, "(Not available)\n"); + } + + ldns_buffer_printf(output, "Prime1: "); + if (rsa->p) { + i = (uint16_t)BN_bn2bin(rsa->p, bignum); + if (i > LDNS_MAX_KEYLEN) { + goto error; + } + b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); + if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + goto error; + } + ldns_rdf_deep_free(b64_bignum); + ldns_buffer_printf(output, "\n"); + } else { + ldns_buffer_printf(output, "(Not available)\n"); + } + + ldns_buffer_printf(output, "Prime2: "); + if (rsa->q) { + i = (uint16_t)BN_bn2bin(rsa->q, bignum); + if (i > LDNS_MAX_KEYLEN) { + goto error; + } + b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); + if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + goto error; + } + ldns_rdf_deep_free(b64_bignum); + ldns_buffer_printf(output, "\n"); + } else { + ldns_buffer_printf(output, "(Not available)\n"); + } + + ldns_buffer_printf(output, "Exponent1: "); + if (rsa->dmp1) { + i = (uint16_t)BN_bn2bin(rsa->dmp1, bignum); + if (i > LDNS_MAX_KEYLEN) { + goto error; + } + b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); + if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + goto error; + } + ldns_rdf_deep_free(b64_bignum); + ldns_buffer_printf(output, "\n"); + } else { + ldns_buffer_printf(output, "(Not available)\n"); + } + + ldns_buffer_printf(output, "Exponent2: "); + if (rsa->dmq1) { + i = (uint16_t)BN_bn2bin(rsa->dmq1, bignum); + if (i > LDNS_MAX_KEYLEN) { + goto error; + } + b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); + if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + goto error; + } + ldns_rdf_deep_free(b64_bignum); + ldns_buffer_printf(output, "\n"); + } else { + ldns_buffer_printf(output, "(Not available)\n"); + } + + ldns_buffer_printf(output, "Coefficient: "); + if (rsa->iqmp) { + i = (uint16_t)BN_bn2bin(rsa->iqmp, bignum); + if (i > LDNS_MAX_KEYLEN) { + goto error; + } + b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); + if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + goto error; + } + ldns_rdf_deep_free(b64_bignum); + ldns_buffer_printf(output, "\n"); + } else { + ldns_buffer_printf(output, "(Not available)\n"); + } +#endif /* splint */ + + RSA_free(rsa); + break; + case LDNS_SIGN_DSA: + case LDNS_SIGN_DSA_NSEC3: + dsa = ldns_key_dsa_key(k); + + ldns_buffer_printf(output,"Private-key-format: v1.2\n"); + if (ldns_key_algorithm(k) == LDNS_SIGN_DSA) { + ldns_buffer_printf(output,"Algorithm: 3 (DSA)\n"); + } else if (ldns_key_algorithm(k) == LDNS_SIGN_DSA_NSEC3) { + ldns_buffer_printf(output,"Algorithm: 6 (DSA_NSEC3)\n"); + } + + /* print to buf, convert to bin, convert to b64, + * print to buf */ + ldns_buffer_printf(output, "Prime(p): "); +#ifndef S_SPLINT_S + if (dsa->p) { + i = (uint16_t)BN_bn2bin(dsa->p, bignum); + if (i > LDNS_MAX_KEYLEN) { + goto error; + } + b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); + if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + goto error; + } + ldns_rdf_deep_free(b64_bignum); + ldns_buffer_printf(output, "\n"); + } else { + printf("(Not available)\n"); + } + + ldns_buffer_printf(output, "Subprime(q): "); + if (dsa->q) { + i = (uint16_t)BN_bn2bin(dsa->q, bignum); + if (i > LDNS_MAX_KEYLEN) { + goto error; + } + b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); + if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + goto error; + } + ldns_rdf_deep_free(b64_bignum); + ldns_buffer_printf(output, "\n"); + } else { + printf("(Not available)\n"); + } + + ldns_buffer_printf(output, "Base(g): "); + if (dsa->g) { + i = (uint16_t)BN_bn2bin(dsa->g, bignum); + if (i > LDNS_MAX_KEYLEN) { + goto error; + } + b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); + if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + goto error; + } + ldns_rdf_deep_free(b64_bignum); + ldns_buffer_printf(output, "\n"); + } else { + printf("(Not available)\n"); + } + + ldns_buffer_printf(output, "Private_value(x): "); + if (dsa->priv_key) { + i = (uint16_t)BN_bn2bin(dsa->priv_key, bignum); + if (i > LDNS_MAX_KEYLEN) { + goto error; + } + b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); + if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + goto error; + } + ldns_rdf_deep_free(b64_bignum); + ldns_buffer_printf(output, "\n"); + } else { + printf("(Not available)\n"); + } + + ldns_buffer_printf(output, "Public_value(y): "); + if (dsa->pub_key) { + i = (uint16_t)BN_bn2bin(dsa->pub_key, bignum); + if (i > LDNS_MAX_KEYLEN) { + goto error; + } + b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); + if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + goto error; + } + ldns_rdf_deep_free(b64_bignum); + ldns_buffer_printf(output, "\n"); + } else { + printf("(Not available)\n"); + } +#endif /* splint */ + break; + case LDNS_SIGN_ECC_GOST: + /* no format defined, use blob */ +#if defined(HAVE_SSL) && defined(USE_GOST) + ldns_buffer_printf(output, "Private-key-format: v1.2\n"); + ldns_buffer_printf(output, "Algorithm: %d (ECC-GOST)\n", LDNS_SIGN_ECC_GOST); + status = ldns_gost_key2buffer_str(output, +#ifndef S_SPLINT_S + k->_key.key +#else + NULL +#endif + ); +#else + goto error; +#endif /* GOST */ + break; + case LDNS_SIGN_ECDSAP256SHA256: + case LDNS_SIGN_ECDSAP384SHA384: +#ifdef USE_ECDSA + ldns_buffer_printf(output, "Private-key-format: v1.2\n"); + ldns_buffer_printf(output, "Algorithm: %d (", ldns_key_algorithm(k)); + status=ldns_algorithm2buffer_str(output, (ldns_algorithm)ldns_key_algorithm(k)); +#ifndef S_SPLINT_S + ldns_buffer_printf(output, ")\n"); + if(k->_key.key) { + EC_KEY* ec = EVP_PKEY_get1_EC_KEY(k->_key.key); + const BIGNUM* b = EC_KEY_get0_private_key(ec); + ldns_buffer_printf(output, "PrivateKey: "); + i = (uint16_t)BN_bn2bin(b, bignum); + if (i > LDNS_MAX_KEYLEN) { + goto error; + } + b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); + if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + goto error; + } + ldns_rdf_deep_free(b64_bignum); + ldns_buffer_printf(output, "\n"); + /* down reference count in EC_KEY + * its still assigned to the PKEY */ + EC_KEY_free(ec); + } +#endif /* splint */ +#else + goto error; +#endif /* ECDSA */ + break; + case LDNS_SIGN_HMACMD5: + /* there's not much of a format defined for TSIG */ + /* It's just a binary blob, Same for all algorithms */ + ldns_buffer_printf(output, "Private-key-format: v1.2\n"); + ldns_buffer_printf(output, "Algorithm: 157 (HMAC_MD5)\n"); + status = ldns_hmac_key2buffer_str(output, k); + break; + case LDNS_SIGN_HMACSHA1: + ldns_buffer_printf(output, "Private-key-format: v1.2\n"); + ldns_buffer_printf(output, "Algorithm: 158 (HMAC_SHA1)\n"); + status = ldns_hmac_key2buffer_str(output, k); + break; + case LDNS_SIGN_HMACSHA256: + ldns_buffer_printf(output, "Private-key-format: v1.2\n"); + ldns_buffer_printf(output, "Algorithm: 159 (HMAC_SHA256)\n"); + status = ldns_hmac_key2buffer_str(output, k); + break; + } +#endif /* HAVE_SSL */ + } else { +#ifdef HAVE_SSL + LDNS_FREE(b64_bignum); +#endif + LDNS_FREE(bignum); + return ldns_buffer_status(output); + } + LDNS_FREE(bignum); + return status; + +#ifdef HAVE_SSL + /* compiles warn the label isn't used */ +error: + LDNS_FREE(bignum); + return LDNS_STATUS_ERR; +#endif /* HAVE_SSL */ + +} + +/* + * Zero terminate the buffer and fix it to the size of the string. + */ +char * +ldns_buffer2str(ldns_buffer *buffer) +{ + char *tmp_str; + char *str; + + /* check if buffer ends with \0, if not, and + if there is space, add it */ + if (*(ldns_buffer_at(buffer, ldns_buffer_position(buffer))) != 0) { + if (!ldns_buffer_reserve(buffer, 1)) { + return NULL; + } + ldns_buffer_write_u8(buffer, (uint8_t) '\0'); + if (!ldns_buffer_set_capacity(buffer, ldns_buffer_position(buffer))) { + return NULL; + } + } + + tmp_str = ldns_buffer_export(buffer); + str = LDNS_XMALLOC(char, strlen(tmp_str) + 1); + if(!str) { + return NULL; + } + memcpy(str, tmp_str, strlen(tmp_str) + 1); + + return str; +} + +char * +ldns_rdf2str(const ldns_rdf *rdf) +{ + char *result = NULL; + ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN); + + if (!tmp_buffer) { + return NULL; + } + if (ldns_rdf2buffer_str(tmp_buffer, rdf) == LDNS_STATUS_OK) { + /* export and return string, destroy rest */ + result = ldns_buffer2str(tmp_buffer); + } + ldns_buffer_free(tmp_buffer); + return result; +} + +char * +ldns_rr2str_fmt(const ldns_output_format *fmt, const ldns_rr *rr) +{ + char *result = NULL; + ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN); + + if (!tmp_buffer) { + return NULL; + } + if (ldns_rr2buffer_str_fmt(tmp_buffer, fmt, rr) + == LDNS_STATUS_OK) { + /* export and return string, destroy rest */ + result = ldns_buffer2str(tmp_buffer); + } + ldns_buffer_free(tmp_buffer); + return result; +} + +char * +ldns_rr2str(const ldns_rr *rr) +{ + return ldns_rr2str_fmt(ldns_output_format_default, rr); +} + +char * +ldns_pkt2str_fmt(const ldns_output_format *fmt, const ldns_pkt *pkt) +{ + char *result = NULL; + ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN); + + if (!tmp_buffer) { + return NULL; + } + if (ldns_pkt2buffer_str_fmt(tmp_buffer, fmt, pkt) + == LDNS_STATUS_OK) { + /* export and return string, destroy rest */ + result = ldns_buffer2str(tmp_buffer); + } + + ldns_buffer_free(tmp_buffer); + return result; +} + +char * +ldns_pkt2str(const ldns_pkt *pkt) +{ + return ldns_pkt2str_fmt(ldns_output_format_default, pkt); +} + +char * +ldns_key2str(const ldns_key *k) +{ + char *result = NULL; + ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN); + + if (!tmp_buffer) { + return NULL; + } + if (ldns_key2buffer_str(tmp_buffer, k) == LDNS_STATUS_OK) { + /* export and return string, destroy rest */ + result = ldns_buffer2str(tmp_buffer); + } + ldns_buffer_free(tmp_buffer); + return result; +} + +char * +ldns_rr_list2str_fmt(const ldns_output_format *fmt, const ldns_rr_list *list) +{ + char *result = NULL; + ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN); + + if (!tmp_buffer) { + return NULL; + } + if (list) { + if (ldns_rr_list2buffer_str_fmt( + tmp_buffer, fmt, list) + == LDNS_STATUS_OK) { + } + } else { + if (fmt == NULL) { + fmt = ldns_output_format_default; + } + if (fmt->flags & LDNS_COMMENT_NULLS) { + ldns_buffer_printf(tmp_buffer, "; (null)\n"); + } + } + + /* export and return string, destroy rest */ + result = ldns_buffer2str(tmp_buffer); + ldns_buffer_free(tmp_buffer); + return result; +} + +char * +ldns_rr_list2str(const ldns_rr_list *list) +{ + return ldns_rr_list2str_fmt(ldns_output_format_default, list); +} + +void +ldns_rdf_print(FILE *output, const ldns_rdf *rdf) +{ + char *str = ldns_rdf2str(rdf); + if (str) { + fprintf(output, "%s", str); + } else { + fprintf(output, "Unable to convert rdf to string\n"); + } + LDNS_FREE(str); +} + +void +ldns_rr_print_fmt(FILE *output, + const ldns_output_format *fmt, const ldns_rr *rr) +{ + char *str = ldns_rr2str_fmt(fmt, rr); + if (str) { + fprintf(output, "%s", str); + } else { + fprintf(output, "Unable to convert rr to string\n"); + } + LDNS_FREE(str); +} + +void +ldns_rr_print(FILE *output, const ldns_rr *rr) +{ + ldns_rr_print_fmt(output, ldns_output_format_default, rr); +} + +void +ldns_pkt_print_fmt(FILE *output, + const ldns_output_format *fmt, const ldns_pkt *pkt) +{ + char *str = ldns_pkt2str_fmt(fmt, pkt); + if (str) { + fprintf(output, "%s", str); + } else { + fprintf(output, "Unable to convert packet to string\n"); + } + LDNS_FREE(str); +} + +void +ldns_pkt_print(FILE *output, const ldns_pkt *pkt) +{ + ldns_pkt_print_fmt(output, ldns_output_format_default, pkt); +} + +void +ldns_rr_list_print_fmt(FILE *output, + const ldns_output_format *fmt, const ldns_rr_list *lst) +{ + size_t i; + for (i = 0; i < ldns_rr_list_rr_count(lst); i++) { + ldns_rr_print_fmt(output, fmt, ldns_rr_list_rr(lst, i)); + } +} + +void +ldns_rr_list_print(FILE *output, const ldns_rr_list *lst) +{ + ldns_rr_list_print_fmt(output, ldns_output_format_default, lst); +} + +void +ldns_resolver_print_fmt(FILE *output, + const ldns_output_format *fmt, const ldns_resolver *r) +{ + uint16_t i; + ldns_rdf **n; + ldns_rdf **s; + size_t *rtt; + if (!r) { + return; + } + n = ldns_resolver_nameservers(r); + s = ldns_resolver_searchlist(r); + rtt = ldns_resolver_rtt(r); + + fprintf(output, "port: %d\n", (int)ldns_resolver_port(r)); + fprintf(output, "edns0 size: %d\n", (int)ldns_resolver_edns_udp_size(r)); + fprintf(output, "use ip6: %d\n", (int)ldns_resolver_ip6(r)); + + fprintf(output, "recursive: %d\n", ldns_resolver_recursive(r)); + fprintf(output, "usevc: %d\n", ldns_resolver_usevc(r)); + fprintf(output, "igntc: %d\n", ldns_resolver_igntc(r)); + fprintf(output, "fail: %d\n", ldns_resolver_fail(r)); + fprintf(output, "retry: %d\n", (int)ldns_resolver_retry(r)); + fprintf(output, "retrans: %d\n", (int)ldns_resolver_retrans(r)); + fprintf(output, "fallback: %d\n", ldns_resolver_fallback(r)); + fprintf(output, "random: %d\n", ldns_resolver_random(r)); + fprintf(output, "timeout: %d\n", (int)ldns_resolver_timeout(r).tv_sec); + fprintf(output, "dnssec: %d\n", ldns_resolver_dnssec(r)); + fprintf(output, "dnssec cd: %d\n", ldns_resolver_dnssec_cd(r)); + fprintf(output, "trust anchors (%d listed):\n", + (int)ldns_rr_list_rr_count(ldns_resolver_dnssec_anchors(r))); + ldns_rr_list_print_fmt(output, fmt, ldns_resolver_dnssec_anchors(r)); + fprintf(output, "tsig: %s %s\n", + ldns_resolver_tsig_keyname(r)?ldns_resolver_tsig_keyname(r):"-", + ldns_resolver_tsig_algorithm(r)?ldns_resolver_tsig_algorithm(r):"-"); + fprintf(output, "debug: %d\n", ldns_resolver_debug(r)); + + fprintf(output, "default domain: "); + ldns_rdf_print(output, ldns_resolver_domain(r)); + fprintf(output, "\n"); + fprintf(output, "apply default domain: %d\n", ldns_resolver_defnames(r)); + + fprintf(output, "searchlist (%d listed):\n", (int)ldns_resolver_searchlist_count(r)); + for (i = 0; i < ldns_resolver_searchlist_count(r); i++) { + fprintf(output, "\t"); + ldns_rdf_print(output, s[i]); + fprintf(output, "\n"); + } + fprintf(output, "apply search list: %d\n", ldns_resolver_dnsrch(r)); + + fprintf(output, "nameservers (%d listed):\n", (int)ldns_resolver_nameserver_count(r)); + for (i = 0; i < ldns_resolver_nameserver_count(r); i++) { + fprintf(output, "\t"); + ldns_rdf_print(output, n[i]); + + switch ((int)rtt[i]) { + case LDNS_RESOLV_RTT_MIN: + fprintf(output, " - reachable\n"); + break; + case LDNS_RESOLV_RTT_INF: + fprintf(output, " - unreachable\n"); + break; + } + } +} + +void +ldns_resolver_print(FILE *output, const ldns_resolver *r) +{ + ldns_resolver_print_fmt(output, ldns_output_format_default, r); +} + +void +ldns_zone_print_fmt(FILE *output, + const ldns_output_format *fmt, const ldns_zone *z) +{ + if(ldns_zone_soa(z)) + ldns_rr_print_fmt(output, fmt, ldns_zone_soa(z)); + ldns_rr_list_print_fmt(output, fmt, ldns_zone_rrs(z)); +} +void +ldns_zone_print(FILE *output, const ldns_zone *z) +{ + ldns_zone_print_fmt(output, ldns_output_format_default, z); +} diff --git a/host2wire.c b/host2wire.c new file mode 100644 index 00000000000..b5b0ba8ff20 --- /dev/null +++ b/host2wire.c @@ -0,0 +1,434 @@ +/* + * host2wire.c + * + * conversion routines from the host to the wire format. + * This will usually just a re-ordering of the + * data (as we store it in network format) + * + * a Net::DNS like library for C + * + * (c) NLnet Labs, 2004-2006 + * + * See the file LICENSE for the license + */ + +#include + +#include + +/* TODO Jelte + add a pointer to a 'possiblecompression' structure + to all the needed functions? + something like an array of name, pointer values? + every dname part could be added to it +*/ + +ldns_status +ldns_dname2buffer_wire(ldns_buffer *buffer, const ldns_rdf *name) +{ + if (ldns_buffer_reserve(buffer, ldns_rdf_size(name))) { + ldns_buffer_write(buffer, ldns_rdf_data(name), ldns_rdf_size(name)); + } + return ldns_buffer_status(buffer); +} + +ldns_status +ldns_rdf2buffer_wire(ldns_buffer *buffer, const ldns_rdf *rdf) +{ + if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) { + ldns_buffer_write(buffer, ldns_rdf_data(rdf), ldns_rdf_size(rdf)); + } + return ldns_buffer_status(buffer); +} + +ldns_status +ldns_rdf2buffer_wire_canonical(ldns_buffer *buffer, const ldns_rdf *rdf) +{ + size_t i; + uint8_t *rdf_data; + + if (ldns_rdf_get_type(rdf) == LDNS_RDF_TYPE_DNAME) { + if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) { + rdf_data = ldns_rdf_data(rdf); + for (i = 0; i < ldns_rdf_size(rdf); i++) { + ldns_buffer_write_u8(buffer, + (uint8_t) LDNS_DNAME_NORMALIZE((int)rdf_data[i])); + } + } + } else { + /* direct copy for all other types */ + if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) { + ldns_buffer_write(buffer, + ldns_rdf_data(rdf), + ldns_rdf_size(rdf)); + } + } + return ldns_buffer_status(buffer); +} + +/* convert a rr list to wireformat */ +ldns_status +ldns_rr_list2buffer_wire(ldns_buffer *buffer,const ldns_rr_list *rr_list) +{ + uint16_t rr_count; + uint16_t i; + + rr_count = ldns_rr_list_rr_count(rr_list); + for(i = 0; i < rr_count; i++) { + (void)ldns_rr2buffer_wire(buffer, ldns_rr_list_rr(rr_list, i), + LDNS_SECTION_ANY); + } + return ldns_buffer_status(buffer); +} + +ldns_status +ldns_rr2buffer_wire_canonical(ldns_buffer *buffer, + const ldns_rr *rr, + int section) +{ + uint16_t i; + uint16_t rdl_pos = 0; + bool pre_rfc3597 = false; + switch (ldns_rr_get_type(rr)) { + case LDNS_RR_TYPE_NS: + case LDNS_RR_TYPE_MD: + case LDNS_RR_TYPE_MF: + case LDNS_RR_TYPE_CNAME: + case LDNS_RR_TYPE_SOA: + case LDNS_RR_TYPE_MB: + case LDNS_RR_TYPE_MG: + case LDNS_RR_TYPE_MR: + case LDNS_RR_TYPE_PTR: + case LDNS_RR_TYPE_HINFO: + case LDNS_RR_TYPE_MINFO: + case LDNS_RR_TYPE_MX: + case LDNS_RR_TYPE_RP: + case LDNS_RR_TYPE_AFSDB: + case LDNS_RR_TYPE_RT: + case LDNS_RR_TYPE_SIG: + case LDNS_RR_TYPE_PX: + case LDNS_RR_TYPE_NXT: + case LDNS_RR_TYPE_NAPTR: + case LDNS_RR_TYPE_KX: + case LDNS_RR_TYPE_SRV: + case LDNS_RR_TYPE_DNAME: + case LDNS_RR_TYPE_A6: + case LDNS_RR_TYPE_RRSIG: + pre_rfc3597 = true; + break; + default: + break; + } + + if (ldns_rr_owner(rr)) { + (void) ldns_rdf2buffer_wire_canonical(buffer, ldns_rr_owner(rr)); + } + + if (ldns_buffer_reserve(buffer, 4)) { + (void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr)); + (void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr)); + } + + if (section != LDNS_SECTION_QUESTION) { + if (ldns_buffer_reserve(buffer, 6)) { + ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr)); + /* remember pos for later */ + rdl_pos = ldns_buffer_position(buffer); + ldns_buffer_write_u16(buffer, 0); + } + + for (i = 0; i < ldns_rr_rd_count(rr); i++) { + if (pre_rfc3597) { + (void) ldns_rdf2buffer_wire_canonical( + buffer, ldns_rr_rdf(rr, i)); + } else { + (void) ldns_rdf2buffer_wire( + buffer, ldns_rr_rdf(rr, i)); + } + } + + if (rdl_pos != 0) { + ldns_buffer_write_u16_at(buffer, rdl_pos, + ldns_buffer_position(buffer) + - rdl_pos - 2); + } + } + return ldns_buffer_status(buffer); +} + +ldns_status +ldns_rr2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr, int section) +{ + uint16_t i; + uint16_t rdl_pos = 0; + + if (ldns_rr_owner(rr)) { + (void) ldns_dname2buffer_wire(buffer, ldns_rr_owner(rr)); + } + + if (ldns_buffer_reserve(buffer, 4)) { + (void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr)); + (void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr)); + } + + if (section != LDNS_SECTION_QUESTION) { + if (ldns_buffer_reserve(buffer, 6)) { + ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr)); + /* remember pos for later */ + rdl_pos = ldns_buffer_position(buffer); + ldns_buffer_write_u16(buffer, 0); + } + + for (i = 0; i < ldns_rr_rd_count(rr); i++) { + (void) ldns_rdf2buffer_wire( + buffer, ldns_rr_rdf(rr, i)); + } + + if (rdl_pos != 0) { + ldns_buffer_write_u16_at(buffer, rdl_pos, + ldns_buffer_position(buffer) + - rdl_pos - 2); + } + } + return ldns_buffer_status(buffer); +} + +ldns_status +ldns_rrsig2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr) +{ + uint16_t i; + + /* it must be a sig RR */ + if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_RRSIG) { + return LDNS_STATUS_ERR; + } + + /* Convert all the rdfs, except the actual signature data + * rdf number 8 - the last, hence: -1 */ + for (i = 0; i < ldns_rr_rd_count(rr) - 1; i++) { + (void) ldns_rdf2buffer_wire_canonical(buffer, ldns_rr_rdf(rr, i)); + } + + return ldns_buffer_status(buffer); +} + +ldns_status +ldns_rr_rdata2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr) +{ + uint16_t i; + /* convert all the rdf's */ + for (i = 0; i < ldns_rr_rd_count(rr); i++) { + (void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr, i)); + } + + return ldns_buffer_status(buffer); +} + +/* + * Copies the packet header data to the buffer in wire format + */ +static ldns_status +ldns_hdr2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet) +{ + uint8_t flags; + uint16_t arcount; + + if (ldns_buffer_reserve(buffer, 12)) { + ldns_buffer_write_u16(buffer, ldns_pkt_id(packet)); + + flags = ldns_pkt_qr(packet) << 7 + | ldns_pkt_get_opcode(packet) << 3 + | ldns_pkt_aa(packet) << 2 + | ldns_pkt_tc(packet) << 1 | ldns_pkt_rd(packet); + ldns_buffer_write_u8(buffer, flags); + + flags = ldns_pkt_ra(packet) << 7 + /*| ldns_pkt_z(packet) << 6*/ + | ldns_pkt_ad(packet) << 5 + | ldns_pkt_cd(packet) << 4 | ldns_pkt_get_rcode(packet); + ldns_buffer_write_u8(buffer, flags); + + ldns_buffer_write_u16(buffer, ldns_pkt_qdcount(packet)); + ldns_buffer_write_u16(buffer, ldns_pkt_ancount(packet)); + ldns_buffer_write_u16(buffer, ldns_pkt_nscount(packet)); + /* add EDNS0 and TSIG to additional if they are there */ + arcount = ldns_pkt_arcount(packet); + if (ldns_pkt_tsig(packet)) { + arcount++; + } + if (ldns_pkt_edns(packet)) { + arcount++; + } + ldns_buffer_write_u16(buffer, arcount); + } + + return ldns_buffer_status(buffer); +} + +ldns_status +ldns_pkt2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet) +{ + ldns_rr_list *rr_list; + uint16_t i; + + /* edns tmp vars */ + ldns_rr *edns_rr; + uint8_t edata[4]; + + (void) ldns_hdr2buffer_wire(buffer, packet); + + rr_list = ldns_pkt_question(packet); + if (rr_list) { + for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) { + (void) ldns_rr2buffer_wire(buffer, + ldns_rr_list_rr(rr_list, i), LDNS_SECTION_QUESTION); + } + } + rr_list = ldns_pkt_answer(packet); + if (rr_list) { + for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) { + (void) ldns_rr2buffer_wire(buffer, + ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ANSWER); + } + } + rr_list = ldns_pkt_authority(packet); + if (rr_list) { + for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) { + (void) ldns_rr2buffer_wire(buffer, + ldns_rr_list_rr(rr_list, i), LDNS_SECTION_AUTHORITY); + } + } + rr_list = ldns_pkt_additional(packet); + if (rr_list) { + for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) { + (void) ldns_rr2buffer_wire(buffer, + ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ADDITIONAL); + } + } + + /* add EDNS to additional if it is needed */ + if (ldns_pkt_edns(packet)) { + edns_rr = ldns_rr_new(); + if(!edns_rr) return LDNS_STATUS_MEM_ERR; + ldns_rr_set_owner(edns_rr, + ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, ".")); + ldns_rr_set_type(edns_rr, LDNS_RR_TYPE_OPT); + ldns_rr_set_class(edns_rr, ldns_pkt_edns_udp_size(packet)); + edata[0] = ldns_pkt_edns_extended_rcode(packet); + edata[1] = ldns_pkt_edns_version(packet); + ldns_write_uint16(&edata[2], ldns_pkt_edns_z(packet)); + ldns_rr_set_ttl(edns_rr, ldns_read_uint32(edata)); + /* don't forget to add the edns rdata (if any) */ + if (packet->_edns_data) + ldns_rr_push_rdf (edns_rr, packet->_edns_data); + (void)ldns_rr2buffer_wire(buffer, edns_rr, LDNS_SECTION_ADDITIONAL); + /* take the edns rdata back out of the rr before we free rr */ + if (packet->_edns_data) + (void)ldns_rr_pop_rdf (edns_rr); + ldns_rr_free(edns_rr); + } + + /* add TSIG to additional if it is there */ + if (ldns_pkt_tsig(packet)) { + (void) ldns_rr2buffer_wire(buffer, + ldns_pkt_tsig(packet), LDNS_SECTION_ADDITIONAL); + } + + return LDNS_STATUS_OK; +} + +ldns_status +ldns_rdf2wire(uint8_t **dest, const ldns_rdf *rdf, size_t *result_size) +{ + ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN); + uint8_t *result = NULL; + ldns_status status; + *result_size = 0; + *dest = NULL; + if(!buffer) return LDNS_STATUS_MEM_ERR; + + status = ldns_rdf2buffer_wire(buffer, rdf); + if (status == LDNS_STATUS_OK) { + *result_size = ldns_buffer_position(buffer); + result = (uint8_t *) ldns_buffer_export(buffer); + } else { + ldns_buffer_free(buffer); + return status; + } + + if (result) { + *dest = LDNS_XMALLOC(uint8_t, ldns_buffer_position(buffer)); + if(!*dest) { + ldns_buffer_free(buffer); + return LDNS_STATUS_MEM_ERR; + } + memcpy(*dest, result, ldns_buffer_position(buffer)); + } + + ldns_buffer_free(buffer); + return status; +} + +ldns_status +ldns_rr2wire(uint8_t **dest, const ldns_rr *rr, int section, size_t *result_size) +{ + ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN); + uint8_t *result = NULL; + ldns_status status; + *result_size = 0; + *dest = NULL; + if(!buffer) return LDNS_STATUS_MEM_ERR; + + status = ldns_rr2buffer_wire(buffer, rr, section); + if (status == LDNS_STATUS_OK) { + *result_size = ldns_buffer_position(buffer); + result = (uint8_t *) ldns_buffer_export(buffer); + } else { + ldns_buffer_free(buffer); + return status; + } + + if (result) { + *dest = LDNS_XMALLOC(uint8_t, ldns_buffer_position(buffer)); + if(!*dest) { + ldns_buffer_free(buffer); + return LDNS_STATUS_MEM_ERR; + } + memcpy(*dest, result, ldns_buffer_position(buffer)); + } + + ldns_buffer_free(buffer); + return status; +} + +ldns_status +ldns_pkt2wire(uint8_t **dest, const ldns_pkt *packet, size_t *result_size) +{ + ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN); + uint8_t *result = NULL; + ldns_status status; + *result_size = 0; + *dest = NULL; + if(!buffer) return LDNS_STATUS_MEM_ERR; + + status = ldns_pkt2buffer_wire(buffer, packet); + if (status == LDNS_STATUS_OK) { + *result_size = ldns_buffer_position(buffer); + result = (uint8_t *) ldns_buffer_export(buffer); + } else { + ldns_buffer_free(buffer); + return status; + } + + if (result) { + *dest = LDNS_XMALLOC(uint8_t, ldns_buffer_position(buffer)); + if(!*dest) { + ldns_buffer_free(buffer); + return LDNS_STATUS_MEM_ERR; + } + memcpy(*dest, result, ldns_buffer_position(buffer)); + } + + ldns_buffer_free(buffer); + return status; +} diff --git a/install-sh b/install-sh new file mode 100755 index 00000000000..a9244eb0786 --- /dev/null +++ b/install-sh @@ -0,0 +1,527 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2011-01-19.21; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +nl=' +' +IFS=" "" $nl" + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +no_target_directory= + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) dst_arg=$2 + # Protect names problematic for `test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) no_target_directory=true;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for `test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names problematic for `test' and other utilities. + case $src in + -* | [=\(\)!]) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + dst=$dst_arg + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writeable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + eval "$initialize_posix_glob" + + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir + shift + $posix_glob set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && + + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/keys.c b/keys.c new file mode 100644 index 00000000000..54f26681494 --- /dev/null +++ b/keys.c @@ -0,0 +1,1693 @@ +/* + * keys.c handle private keys for use in DNSSEC + * + * This module should hide some of the openSSL complexities + * and give a general interface for private keys and hmac + * handling + * + * (c) NLnet Labs, 2004-2006 + * + * See the file LICENSE for the license + */ + +#include + +#include + +#ifdef HAVE_SSL +#include +#include +#include +#endif /* HAVE_SSL */ + +ldns_lookup_table ldns_signing_algorithms[] = { + { LDNS_SIGN_RSAMD5, "RSAMD5" }, + { LDNS_SIGN_RSASHA1, "RSASHA1" }, + { LDNS_SIGN_RSASHA1_NSEC3, "RSASHA1-NSEC3-SHA1" }, +#ifdef USE_SHA2 + { LDNS_SIGN_RSASHA256, "RSASHA256" }, + { LDNS_SIGN_RSASHA512, "RSASHA512" }, +#endif +#ifdef USE_GOST + { LDNS_SIGN_ECC_GOST, "ECC-GOST" }, +#endif +#ifdef USE_ECDSA + { LDNS_SIGN_ECDSAP256SHA256, "ECDSAP256SHA256" }, + { LDNS_SIGN_ECDSAP384SHA384, "ECDSAP384SHA384" }, +#endif + { LDNS_SIGN_DSA, "DSA" }, + { LDNS_SIGN_DSA_NSEC3, "DSA-NSEC3-SHA1" }, + { LDNS_SIGN_HMACMD5, "hmac-md5.sig-alg.reg.int" }, + { LDNS_SIGN_HMACSHA1, "hmac-sha1" }, + { LDNS_SIGN_HMACSHA256, "hmac-sha256" }, + { 0, NULL } +}; + +ldns_key_list * +ldns_key_list_new() +{ + ldns_key_list *key_list = LDNS_MALLOC(ldns_key_list); + if (!key_list) { + return NULL; + } else { + key_list->_key_count = 0; + key_list->_keys = NULL; + return key_list; + } +} + +ldns_key * +ldns_key_new() +{ + ldns_key *newkey; + + newkey = LDNS_MALLOC(ldns_key); + if (!newkey) { + return NULL; + } else { + /* some defaults - not sure wether to do this */ + ldns_key_set_use(newkey, true); + ldns_key_set_flags(newkey, LDNS_KEY_ZONE_KEY); + ldns_key_set_origttl(newkey, 0); + ldns_key_set_keytag(newkey, 0); + ldns_key_set_inception(newkey, 0); + ldns_key_set_expiration(newkey, 0); + ldns_key_set_pubkey_owner(newkey, NULL); +#ifdef HAVE_SSL + ldns_key_set_evp_key(newkey, NULL); +#endif /* HAVE_SSL */ + ldns_key_set_hmac_key(newkey, NULL); + ldns_key_set_external_key(newkey, NULL); + return newkey; + } +} + +ldns_status +ldns_key_new_frm_fp(ldns_key **k, FILE *fp) +{ + return ldns_key_new_frm_fp_l(k, fp, NULL); +} + +#ifdef HAVE_SSL +ldns_status +ldns_key_new_frm_engine(ldns_key **key, ENGINE *e, char *key_id, ldns_algorithm alg) +{ + ldns_key *k; + + k = ldns_key_new(); + if(!k) return LDNS_STATUS_MEM_ERR; +#ifndef S_SPLINT_S + k->_key.key = ENGINE_load_private_key(e, key_id, UI_OpenSSL(), NULL); + if(!k->_key.key) { + ldns_key_free(k); + return LDNS_STATUS_ERR; + } + ldns_key_set_algorithm(k, (ldns_signing_algorithm) alg); + if (!k->_key.key) { + ldns_key_free(k); + return LDNS_STATUS_ENGINE_KEY_NOT_LOADED; + } +#endif /* splint */ + *key = k; + return LDNS_STATUS_OK; +} +#endif + +#ifdef USE_GOST +/** store GOST engine reference loaded into OpenSSL library */ +ENGINE* ldns_gost_engine = NULL; + +int +ldns_key_EVP_load_gost_id(void) +{ + static int gost_id = 0; + const EVP_PKEY_ASN1_METHOD* meth; + ENGINE* e; + + if(gost_id) return gost_id; + + /* see if configuration loaded gost implementation from other engine*/ + meth = EVP_PKEY_asn1_find_str(NULL, "gost2001", -1); + if(meth) { + EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth); + return gost_id; + } + + /* see if engine can be loaded already */ + e = ENGINE_by_id("gost"); + if(!e) { + /* load it ourself, in case statically linked */ + ENGINE_load_builtin_engines(); + ENGINE_load_dynamic(); + e = ENGINE_by_id("gost"); + } + if(!e) { + /* no gost engine in openssl */ + return 0; + } + if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) { + ENGINE_finish(e); + ENGINE_free(e); + return 0; + } + + meth = EVP_PKEY_asn1_find_str(&e, "gost2001", -1); + if(!meth) { + /* algo not found */ + ENGINE_finish(e); + ENGINE_free(e); + return 0; + } + /* Note: do not ENGINE_finish and ENGINE_free the acquired engine + * on some platforms this frees up the meth and unloads gost stuff */ + ldns_gost_engine = e; + + EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth); + return gost_id; +} + +void ldns_key_EVP_unload_gost(void) +{ + if(ldns_gost_engine) { + ENGINE_finish(ldns_gost_engine); + ENGINE_free(ldns_gost_engine); + ldns_gost_engine = NULL; + } +} + +/** read GOST private key */ +static EVP_PKEY* +ldns_key_new_frm_fp_gost_l(FILE* fp, int* line_nr) +{ + char token[16384]; + const unsigned char* pp; + int gost_id; + EVP_PKEY* pkey; + ldns_rdf* b64rdf = NULL; + + gost_id = ldns_key_EVP_load_gost_id(); + if(!gost_id) + return NULL; + + if (ldns_fget_keyword_data_l(fp, "GostAsn1", ": ", token, "\n", + sizeof(token), line_nr) == -1) + return NULL; + while(strlen(token) < 96) { + /* read more b64 from the file, b64 split on multiple lines */ + if(ldns_fget_token_l(fp, token+strlen(token), "\n", + sizeof(token)-strlen(token), line_nr) == -1) + return NULL; + } + if(ldns_str2rdf_b64(&b64rdf, token) != LDNS_STATUS_OK) + return NULL; + pp = (unsigned char*)ldns_rdf_data(b64rdf); + pkey = d2i_PrivateKey(gost_id, NULL, &pp, (int)ldns_rdf_size(b64rdf)); + ldns_rdf_deep_free(b64rdf); + return pkey; +} +#endif + +#ifdef USE_ECDSA +/** calculate public key from private key */ +static int +ldns_EC_KEY_calc_public(EC_KEY* ec) +{ + EC_POINT* pub_key; + const EC_GROUP* group; + group = EC_KEY_get0_group(ec); + pub_key = EC_POINT_new(group); + if(!pub_key) return 0; + if(!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group))) { + EC_POINT_free(pub_key); + return 0; + } + if(!EC_POINT_mul(group, pub_key, EC_KEY_get0_private_key(ec), + NULL, NULL, NULL)) { + EC_POINT_free(pub_key); + return 0; + } + if(EC_KEY_set_public_key(ec, pub_key) == 0) { + EC_POINT_free(pub_key); + return 0; + } + EC_POINT_free(pub_key); + return 1; +} + +/** read ECDSA private key */ +static EVP_PKEY* +ldns_key_new_frm_fp_ecdsa_l(FILE* fp, ldns_algorithm alg, int* line_nr) +{ + char token[16384]; + ldns_rdf* b64rdf = NULL; + unsigned char* pp; + BIGNUM* bn; + EVP_PKEY* evp_key; + EC_KEY* ec; + if (ldns_fget_keyword_data_l(fp, "PrivateKey", ": ", token, "\n", + sizeof(token), line_nr) == -1) + return NULL; + if(ldns_str2rdf_b64(&b64rdf, token) != LDNS_STATUS_OK) + return NULL; + pp = (unsigned char*)ldns_rdf_data(b64rdf); + + if(alg == LDNS_ECDSAP256SHA256) + ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + else if(alg == LDNS_ECDSAP384SHA384) + ec = EC_KEY_new_by_curve_name(NID_secp384r1); + else ec = NULL; + if(!ec) { + ldns_rdf_deep_free(b64rdf); + return NULL; + } + bn = BN_bin2bn(pp, (int)ldns_rdf_size(b64rdf), NULL); + ldns_rdf_deep_free(b64rdf); + if(!bn) { + EC_KEY_free(ec); + return NULL; + } + EC_KEY_set_private_key(ec, bn); + BN_free(bn); + if(!ldns_EC_KEY_calc_public(ec)) { + EC_KEY_free(ec); + return NULL; + } + + evp_key = EVP_PKEY_new(); + if(!evp_key) { + EC_KEY_free(ec); + return NULL; + } + if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) { + EVP_PKEY_free(evp_key); + EC_KEY_free(ec); + return NULL; + } + return evp_key; +} +#endif + +ldns_status +ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr) +{ + ldns_key *k; + char *d; + ldns_signing_algorithm alg; + ldns_rr *key_rr; +#ifdef HAVE_SSL + RSA *rsa; + DSA *dsa; + unsigned char *hmac; + size_t hmac_size; +#endif /* HAVE_SSL */ + + k = ldns_key_new(); + + d = LDNS_XMALLOC(char, LDNS_MAX_LINELEN); + if (!k || !d) { + ldns_key_free(k); + LDNS_FREE(d); + return LDNS_STATUS_MEM_ERR; + } + + alg = 0; + + /* the file is highly structured. Do this in sequence */ + /* RSA: + * Private-key-format: v1.x. + * Algorithm: 1 (RSA) + + */ + /* get the key format version number */ + if (ldns_fget_keyword_data_l(fp, "Private-key-format", ": ", d, "\n", + LDNS_MAX_LINELEN, line_nr) == -1) { + /* no version information */ + ldns_key_free(k); + LDNS_FREE(d); + return LDNS_STATUS_SYNTAX_ERR; + } + if (strncmp(d, "v1.", 3) != 0) { + ldns_key_free(k); + LDNS_FREE(d); + return LDNS_STATUS_SYNTAX_VERSION_ERR; + } + + /* get the algorithm type, our file function strip ( ) so there are + * not in the return string! */ + if (ldns_fget_keyword_data_l(fp, "Algorithm", ": ", d, "\n", + LDNS_MAX_LINELEN, line_nr) == -1) { + /* no alg information */ + ldns_key_free(k); + LDNS_FREE(d); + return LDNS_STATUS_SYNTAX_ALG_ERR; + } + + if (strncmp(d, "1 RSA", 2) == 0) { + alg = LDNS_SIGN_RSAMD5; + } + if (strncmp(d, "2 DH", 2) == 0) { + alg = (ldns_signing_algorithm)LDNS_DH; + } + if (strncmp(d, "3 DSA", 2) == 0) { + alg = LDNS_SIGN_DSA; + } + if (strncmp(d, "4 ECC", 2) == 0) { + alg = (ldns_signing_algorithm)LDNS_ECC; + } + if (strncmp(d, "5 RSASHA1", 2) == 0) { + alg = LDNS_SIGN_RSASHA1; + } + if (strncmp(d, "6 DSA", 2) == 0) { + alg = LDNS_SIGN_DSA_NSEC3; + } + if (strncmp(d, "7 RSASHA1", 2) == 0) { + alg = LDNS_SIGN_RSASHA1_NSEC3; + } + + if (strncmp(d, "8 RSASHA256", 2) == 0) { +#ifdef USE_SHA2 + alg = LDNS_SIGN_RSASHA256; +#else + fprintf(stderr, "Warning: SHA256 not compiled into this "); + fprintf(stderr, "version of ldns\n"); +#endif + } + if (strncmp(d, "10 RSASHA512", 3) == 0) { +#ifdef USE_SHA2 + alg = LDNS_SIGN_RSASHA512; +#else + fprintf(stderr, "Warning: SHA512 not compiled into this "); + fprintf(stderr, "version of ldns\n"); +#endif + } + if (strncmp(d, "12 ECC-GOST", 3) == 0) { +#ifdef USE_GOST + alg = LDNS_SIGN_ECC_GOST; +#else + fprintf(stderr, "Warning: ECC-GOST not compiled into this "); + fprintf(stderr, "version of ldns, use --enable-gost\n"); +#endif + } + if (strncmp(d, "13 ECDSAP256SHA256", 3) == 0) { +#ifdef USE_ECDSA + alg = LDNS_SIGN_ECDSAP256SHA256; +#else + fprintf(stderr, "Warning: ECDSA not compiled into this "); + fprintf(stderr, "version of ldns, use --enable-ecdsa\n"); +#endif + } + if (strncmp(d, "14 ECDSAP384SHA384", 3) == 0) { +#ifdef USE_ECDSA + alg = LDNS_SIGN_ECDSAP384SHA384; +#else + fprintf(stderr, "Warning: ECDSA not compiled into this "); + fprintf(stderr, "version of ldns, use --enable-ecdsa\n"); +#endif + } + if (strncmp(d, "157 HMAC-MD5", 4) == 0) { + alg = LDNS_SIGN_HMACMD5; + } + if (strncmp(d, "158 HMAC-SHA1", 4) == 0) { + alg = LDNS_SIGN_HMACSHA1; + } + if (strncmp(d, "159 HMAC-SHA256", 4) == 0) { + alg = LDNS_SIGN_HMACSHA256; + } + + LDNS_FREE(d); + + switch(alg) { + case LDNS_SIGN_RSAMD5: + case LDNS_SIGN_RSASHA1: + case LDNS_SIGN_RSASHA1_NSEC3: +#ifdef USE_SHA2 + case LDNS_SIGN_RSASHA256: + case LDNS_SIGN_RSASHA512: +#endif + ldns_key_set_algorithm(k, alg); +#ifdef HAVE_SSL + rsa = ldns_key_new_frm_fp_rsa_l(fp, line_nr); + if (!rsa) { + ldns_key_free(k); + return LDNS_STATUS_ERR; + } + ldns_key_set_rsa_key(k, rsa); + RSA_free(rsa); +#endif /* HAVE_SSL */ + break; + case LDNS_SIGN_DSA: + case LDNS_SIGN_DSA_NSEC3: + ldns_key_set_algorithm(k, alg); +#ifdef HAVE_SSL + dsa = ldns_key_new_frm_fp_dsa_l(fp, line_nr); + if (!dsa) { + ldns_key_free(k); + return LDNS_STATUS_ERR; + } + ldns_key_set_dsa_key(k, dsa); + DSA_free(dsa); +#endif /* HAVE_SSL */ + break; + case LDNS_SIGN_HMACMD5: + case LDNS_SIGN_HMACSHA1: + case LDNS_SIGN_HMACSHA256: + ldns_key_set_algorithm(k, alg); +#ifdef HAVE_SSL + hmac = ldns_key_new_frm_fp_hmac_l(fp, line_nr, &hmac_size); + if (!hmac) { + ldns_key_free(k); + return LDNS_STATUS_ERR; + } + ldns_key_set_hmac_size(k, hmac_size); + ldns_key_set_hmac_key(k, hmac); +#endif /* HAVE_SSL */ + break; + case LDNS_SIGN_ECC_GOST: + ldns_key_set_algorithm(k, alg); +#if defined(HAVE_SSL) && defined(USE_GOST) + if(!ldns_key_EVP_load_gost_id()) { + ldns_key_free(k); + return LDNS_STATUS_CRYPTO_ALGO_NOT_IMPL; + } + ldns_key_set_evp_key(k, + ldns_key_new_frm_fp_gost_l(fp, line_nr)); +#ifndef S_SPLINT_S + if(!k->_key.key) { + ldns_key_free(k); + return LDNS_STATUS_ERR; + } +#endif /* splint */ +#endif + break; +#ifdef USE_ECDSA + case LDNS_SIGN_ECDSAP256SHA256: + case LDNS_SIGN_ECDSAP384SHA384: + ldns_key_set_algorithm(k, alg); + ldns_key_set_evp_key(k, + ldns_key_new_frm_fp_ecdsa_l(fp, (ldns_algorithm)alg, line_nr)); +#ifndef S_SPLINT_S + if(!k->_key.key) { + ldns_key_free(k); + return LDNS_STATUS_ERR; + } +#endif /* splint */ + break; +#endif + default: + ldns_key_free(k); + return LDNS_STATUS_SYNTAX_ALG_ERR; + } + key_rr = ldns_key2rr(k); + ldns_key_set_keytag(k, ldns_calc_keytag(key_rr)); + ldns_rr_free(key_rr); + + if (key) { + *key = k; + return LDNS_STATUS_OK; + } + return LDNS_STATUS_ERR; +} + +#ifdef HAVE_SSL +RSA * +ldns_key_new_frm_fp_rsa(FILE *f) +{ + return ldns_key_new_frm_fp_rsa_l(f, NULL); +} + +RSA * +ldns_key_new_frm_fp_rsa_l(FILE *f, int *line_nr) +{ + /* we parse + * Modulus: + * PublicExponent: + * PrivateExponent: + * Prime1: + * Prime2: + * Exponent1: + * Exponent2: + * Coefficient: + * + * man 3 RSA: + * + * struct + * { + * BIGNUM *n; // public modulus + * BIGNUM *e; // public exponent + * BIGNUM *d; // private exponent + * BIGNUM *p; // secret prime factor + * BIGNUM *q; // secret prime factor + * BIGNUM *dmp1; // d mod (p-1) + * BIGNUM *dmq1; // d mod (q-1) + * BIGNUM *iqmp; // q^-1 mod p + * // ... + * + */ + char *d; + RSA *rsa; + uint8_t *buf; + int i; + + d = LDNS_XMALLOC(char, LDNS_MAX_LINELEN); + buf = LDNS_XMALLOC(uint8_t, LDNS_MAX_LINELEN); + rsa = RSA_new(); + if (!d || !rsa || !buf) { + goto error; + } + + /* I could use functions again, but that seems an overkill, + * allthough this also looks tedious + */ + + /* Modules, rsa->n */ + if (ldns_fget_keyword_data_l(f, "Modulus", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) { + goto error; + } + i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d))); +#ifndef S_SPLINT_S + rsa->n = BN_bin2bn((const char unsigned*)buf, i, NULL); + if (!rsa->n) { + goto error; + } + + /* PublicExponent, rsa->e */ + if (ldns_fget_keyword_data_l(f, "PublicExponent", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) { + goto error; + } + i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d))); + rsa->e = BN_bin2bn((const char unsigned*)buf, i, NULL); + if (!rsa->e) { + goto error; + } + + /* PrivateExponent, rsa->d */ + if (ldns_fget_keyword_data_l(f, "PrivateExponent", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) { + goto error; + } + i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d))); + rsa->d = BN_bin2bn((const char unsigned*)buf, i, NULL); + if (!rsa->d) { + goto error; + } + + /* Prime1, rsa->p */ + if (ldns_fget_keyword_data_l(f, "Prime1", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) { + goto error; + } + i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d))); + rsa->p = BN_bin2bn((const char unsigned*)buf, i, NULL); + if (!rsa->p) { + goto error; + } + + /* Prime2, rsa->q */ + if (ldns_fget_keyword_data_l(f, "Prime2", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) { + goto error; + } + i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d))); + rsa->q = BN_bin2bn((const char unsigned*)buf, i, NULL); + if (!rsa->q) { + goto error; + } + + /* Exponent1, rsa->dmp1 */ + if (ldns_fget_keyword_data_l(f, "Exponent1", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) { + goto error; + } + i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d))); + rsa->dmp1 = BN_bin2bn((const char unsigned*)buf, i, NULL); + if (!rsa->dmp1) { + goto error; + } + + /* Exponent2, rsa->dmq1 */ + if (ldns_fget_keyword_data_l(f, "Exponent2", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) { + goto error; + } + i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d))); + rsa->dmq1 = BN_bin2bn((const char unsigned*)buf, i, NULL); + if (!rsa->dmq1) { + goto error; + } + + /* Coefficient, rsa->iqmp */ + if (ldns_fget_keyword_data_l(f, "Coefficient", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) { + goto error; + } + i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d))); + rsa->iqmp = BN_bin2bn((const char unsigned*)buf, i, NULL); + if (!rsa->iqmp) { + goto error; + } +#endif /* splint */ + + LDNS_FREE(buf); + LDNS_FREE(d); + return rsa; + +error: + RSA_free(rsa); + LDNS_FREE(d); + LDNS_FREE(buf); + return NULL; +} + +DSA * +ldns_key_new_frm_fp_dsa(FILE *f) +{ + return ldns_key_new_frm_fp_dsa_l(f, NULL); +} + +DSA * +ldns_key_new_frm_fp_dsa_l(FILE *f, ATTR_UNUSED(int *line_nr)) +{ + int i; + char *d; + DSA *dsa; + uint8_t *buf; + + d = LDNS_XMALLOC(char, LDNS_MAX_LINELEN); + buf = LDNS_XMALLOC(uint8_t, LDNS_MAX_LINELEN); + dsa = DSA_new(); + if (!d || !dsa || !buf) { + goto error; + } + + /* the line parser removes the () from the input... */ + + /* Prime, dsa->p */ + if (ldns_fget_keyword_data_l(f, "Primep", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) { + goto error; + } + i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d))); +#ifndef S_SPLINT_S + dsa->p = BN_bin2bn((const char unsigned*)buf, i, NULL); + if (!dsa->p) { + goto error; + } + + /* Subprime, dsa->q */ + if (ldns_fget_keyword_data_l(f, "Subprimeq", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) { + goto error; + } + i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d))); + dsa->q = BN_bin2bn((const char unsigned*)buf, i, NULL); + if (!dsa->q) { + goto error; + } + + /* Base, dsa->g */ + if (ldns_fget_keyword_data_l(f, "Baseg", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) { + goto error; + } + i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d))); + dsa->g = BN_bin2bn((const char unsigned*)buf, i, NULL); + if (!dsa->g) { + goto error; + } + + /* Private key, dsa->priv_key */ + if (ldns_fget_keyword_data_l(f, "Private_valuex", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) { + goto error; + } + i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d))); + dsa->priv_key = BN_bin2bn((const char unsigned*)buf, i, NULL); + if (!dsa->priv_key) { + goto error; + } + + /* Public key, dsa->priv_key */ + if (ldns_fget_keyword_data_l(f, "Public_valuey", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) { + goto error; + } + i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d))); + dsa->pub_key = BN_bin2bn((const char unsigned*)buf, i, NULL); + if (!dsa->pub_key) { + goto error; + } +#endif /* splint */ + + LDNS_FREE(buf); + LDNS_FREE(d); + + return dsa; + +error: + LDNS_FREE(d); + LDNS_FREE(buf); + DSA_free(dsa); + return NULL; +} + +unsigned char * +ldns_key_new_frm_fp_hmac(FILE *f, size_t *hmac_size) +{ + return ldns_key_new_frm_fp_hmac_l(f, NULL, hmac_size); +} + +unsigned char * +ldns_key_new_frm_fp_hmac_l( FILE *f + , ATTR_UNUSED(int *line_nr) + , size_t *hmac_size + ) +{ + size_t i; + char *d; + unsigned char *buf; + + d = LDNS_XMALLOC(char, LDNS_MAX_LINELEN); + buf = LDNS_XMALLOC(unsigned char, LDNS_MAX_LINELEN); + if(!d || !buf) { + goto error; + } + + if (ldns_fget_keyword_data_l(f, "Key", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) { + goto error; + } + i = (size_t) ldns_b64_pton((const char*)d, + buf, + ldns_b64_ntop_calculate_size(strlen(d))); + + *hmac_size = i; + return buf; + + error: + LDNS_FREE(d); + LDNS_FREE(buf); + *hmac_size = 0; + return NULL; +} +#endif /* HAVE_SSL */ + +#ifdef USE_GOST +static EVP_PKEY* +ldns_gen_gost_key(void) +{ + EVP_PKEY_CTX* ctx; + EVP_PKEY* p = NULL; + int gost_id = ldns_key_EVP_load_gost_id(); + if(!gost_id) + return NULL; + ctx = EVP_PKEY_CTX_new_id(gost_id, NULL); + if(!ctx) { + /* the id should be available now */ + return NULL; + } + if(EVP_PKEY_CTX_ctrl_str(ctx, "paramset", "A") <= 0) { + /* cannot set paramset */ + EVP_PKEY_CTX_free(ctx); + return NULL; + } + + if(EVP_PKEY_keygen_init(ctx) <= 0) { + EVP_PKEY_CTX_free(ctx); + return NULL; + } + if(EVP_PKEY_keygen(ctx, &p) <= 0) { + EVP_PKEY_free(p); + EVP_PKEY_CTX_free(ctx); + return NULL; + } + EVP_PKEY_CTX_free(ctx); + return p; +} +#endif + +ldns_key * +ldns_key_new_frm_algorithm(ldns_signing_algorithm alg, uint16_t size) +{ + ldns_key *k; +#ifdef HAVE_SSL + DSA *d; + RSA *r; +# ifdef USE_ECDSA + EC_KEY *ec = NULL; +# endif +#else + int i; + uint16_t offset = 0; +#endif + unsigned char *hmac; + + k = ldns_key_new(); + if (!k) { + return NULL; + } + switch(alg) { + case LDNS_SIGN_RSAMD5: + case LDNS_SIGN_RSASHA1: + case LDNS_SIGN_RSASHA1_NSEC3: + case LDNS_SIGN_RSASHA256: + case LDNS_SIGN_RSASHA512: +#ifdef HAVE_SSL + r = RSA_generate_key((int)size, RSA_F4, NULL, NULL); + if(!r) { + ldns_key_free(k); + return NULL; + } + if (RSA_check_key(r) != 1) { + ldns_key_free(k); + return NULL; + } + ldns_key_set_rsa_key(k, r); +#endif /* HAVE_SSL */ + break; + case LDNS_SIGN_DSA: + case LDNS_SIGN_DSA_NSEC3: +#ifdef HAVE_SSL + d = DSA_generate_parameters((int)size, NULL, 0, NULL, NULL, NULL, NULL); + if (!d) { + ldns_key_free(k); + return NULL; + } + if (DSA_generate_key(d) != 1) { + ldns_key_free(k); + return NULL; + } + ldns_key_set_dsa_key(k, d); +#endif /* HAVE_SSL */ + break; + case LDNS_SIGN_HMACMD5: + case LDNS_SIGN_HMACSHA1: + case LDNS_SIGN_HMACSHA256: +#ifdef HAVE_SSL +#ifndef S_SPLINT_S + k->_key.key = NULL; +#endif /* splint */ +#endif /* HAVE_SSL */ + size = size / 8; + ldns_key_set_hmac_size(k, size); + + hmac = LDNS_XMALLOC(unsigned char, size); + if(!hmac) { + ldns_key_free(k); + return NULL; + } +#ifdef HAVE_SSL + if (RAND_bytes(hmac, (int) size) != 1) { + LDNS_FREE(hmac); + ldns_key_free(k); + return NULL; + } +#else + while (offset + sizeof(i) < size) { + i = random(); + memcpy(&hmac[offset], &i, sizeof(i)); + offset += sizeof(i); + } + if (offset < size) { + i = random(); + memcpy(&hmac[offset], &i, size - offset); + } +#endif /* HAVE_SSL */ + ldns_key_set_hmac_key(k, hmac); + + ldns_key_set_flags(k, 0); + break; + case LDNS_SIGN_ECC_GOST: +#if defined(HAVE_SSL) && defined(USE_GOST) + ldns_key_set_evp_key(k, ldns_gen_gost_key()); +#ifndef S_SPLINT_S + if(!k->_key.key) { + ldns_key_free(k); + return NULL; + } +#endif /* splint */ +#else + ldns_key_free(k); + return NULL; +#endif /* HAVE_SSL and USE_GOST */ + break; + case LDNS_SIGN_ECDSAP256SHA256: + case LDNS_SIGN_ECDSAP384SHA384: +#ifdef USE_ECDSA + if(alg == LDNS_SIGN_ECDSAP256SHA256) + ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + else if(alg == LDNS_SIGN_ECDSAP384SHA384) + ec = EC_KEY_new_by_curve_name(NID_secp384r1); + if(!ec) { + ldns_key_free(k); + return NULL; + } + if(!EC_KEY_generate_key(ec)) { + ldns_key_free(k); + EC_KEY_free(ec); + return NULL; + } +#ifndef S_SPLINT_S + k->_key.key = EVP_PKEY_new(); + if(!k->_key.key) { + ldns_key_free(k); + EC_KEY_free(ec); + return NULL; + } + if (!EVP_PKEY_assign_EC_KEY(k->_key.key, ec)) { + ldns_key_free(k); + EC_KEY_free(ec); + return NULL; + } +#endif /* splint */ +#else + ldns_key_free(k); + return NULL; +#endif /* ECDSA */ + break; + } + ldns_key_set_algorithm(k, alg); + return k; +} + +void +ldns_key_print(FILE *output, const ldns_key *k) +{ + char *str = ldns_key2str(k); + if (str) { + fprintf(output, "%s", str); + } else { + fprintf(output, "Unable to convert private key to string\n"); + } + LDNS_FREE(str); +} + + +void +ldns_key_set_algorithm(ldns_key *k, ldns_signing_algorithm l) +{ + k->_alg = l; +} + +void +ldns_key_set_flags(ldns_key *k, uint16_t f) +{ + k->_extra.dnssec.flags = f; +} + +#ifdef HAVE_SSL +#ifndef S_SPLINT_S +void +ldns_key_set_evp_key(ldns_key *k, EVP_PKEY *e) +{ + k->_key.key = e; +} + +void +ldns_key_set_rsa_key(ldns_key *k, RSA *r) +{ + EVP_PKEY *key = EVP_PKEY_new(); + EVP_PKEY_set1_RSA(key, r); + k->_key.key = key; +} + +void +ldns_key_set_dsa_key(ldns_key *k, DSA *d) +{ + EVP_PKEY *key = EVP_PKEY_new(); + EVP_PKEY_set1_DSA(key, d); + k->_key.key = key; +} +#endif /* splint */ +#endif /* HAVE_SSL */ + +void +ldns_key_set_hmac_key(ldns_key *k, unsigned char *hmac) +{ + k->_key.hmac.key = hmac; +} + +void +ldns_key_set_hmac_size(ldns_key *k, size_t hmac_size) +{ + k->_key.hmac.size = hmac_size; +} + +void +ldns_key_set_external_key(ldns_key *k, void *external_key) +{ + k->_key.external_key = external_key; +} + +void +ldns_key_set_origttl(ldns_key *k, uint32_t t) +{ + k->_extra.dnssec.orig_ttl = t; +} + +void +ldns_key_set_inception(ldns_key *k, uint32_t i) +{ + k->_extra.dnssec.inception = i; +} + +void +ldns_key_set_expiration(ldns_key *k, uint32_t e) +{ + k->_extra.dnssec.expiration = e; +} + +void +ldns_key_set_pubkey_owner(ldns_key *k, ldns_rdf *r) +{ + k->_pubkey_owner = r; +} + +void +ldns_key_set_keytag(ldns_key *k, uint16_t tag) +{ + k->_extra.dnssec.keytag = tag; +} + +/* read */ +size_t +ldns_key_list_key_count(const ldns_key_list *key_list) +{ + return key_list->_key_count; +} + +ldns_key * +ldns_key_list_key(const ldns_key_list *key, size_t nr) +{ + if (nr < ldns_key_list_key_count(key)) { + return key->_keys[nr]; + } else { + return NULL; + } +} + +ldns_signing_algorithm +ldns_key_algorithm(const ldns_key *k) +{ + return k->_alg; +} + +void +ldns_key_set_use(ldns_key *k, bool v) +{ + if (k) { + k->_use = v; + } +} + +bool +ldns_key_use(const ldns_key *k) +{ + if (k) { + return k->_use; + } + return false; +} + +#ifdef HAVE_SSL +#ifndef S_SPLINT_S +EVP_PKEY * +ldns_key_evp_key(const ldns_key *k) +{ + return k->_key.key; +} + +RSA * +ldns_key_rsa_key(const ldns_key *k) +{ + if (k->_key.key) { + return EVP_PKEY_get1_RSA(k->_key.key); + } else { + return NULL; + } +} + +DSA * +ldns_key_dsa_key(const ldns_key *k) +{ + if (k->_key.key) { + return EVP_PKEY_get1_DSA(k->_key.key); + } else { + return NULL; + } +} +#endif /* splint */ +#endif /* HAVE_SSL */ + +unsigned char * +ldns_key_hmac_key(const ldns_key *k) +{ + if (k->_key.hmac.key) { + return k->_key.hmac.key; + } else { + return NULL; + } +} + +size_t +ldns_key_hmac_size(const ldns_key *k) +{ + if (k->_key.hmac.size) { + return k->_key.hmac.size; + } else { + return 0; + } +} + +void * +ldns_key_external_key(const ldns_key *k) +{ + return k->_key.external_key; +} + +uint32_t +ldns_key_origttl(const ldns_key *k) +{ + return k->_extra.dnssec.orig_ttl; +} + +uint16_t +ldns_key_flags(const ldns_key *k) +{ + return k->_extra.dnssec.flags; +} + +uint32_t +ldns_key_inception(const ldns_key *k) +{ + return k->_extra.dnssec.inception; +} + +uint32_t +ldns_key_expiration(const ldns_key *k) +{ + return k->_extra.dnssec.expiration; +} + +uint16_t +ldns_key_keytag(const ldns_key *k) +{ + return k->_extra.dnssec.keytag; +} + +ldns_rdf * +ldns_key_pubkey_owner(const ldns_key *k) +{ + return k->_pubkey_owner; +} + +/* write */ +void +ldns_key_list_set_use(ldns_key_list *keys, bool v) +{ + size_t i; + + for (i = 0; i < ldns_key_list_key_count(keys); i++) { + ldns_key_set_use(ldns_key_list_key(keys, i), v); + } +} + +void +ldns_key_list_set_key_count(ldns_key_list *key, size_t count) +{ + key->_key_count = count; +} + +bool +ldns_key_list_push_key(ldns_key_list *key_list, ldns_key *key) +{ + size_t key_count; + ldns_key **keys; + + key_count = ldns_key_list_key_count(key_list); + + /* grow the array */ + keys = LDNS_XREALLOC( + key_list->_keys, ldns_key *, key_count + 1); + if (!keys) { + return false; + } + + /* add the new member */ + key_list->_keys = keys; + key_list->_keys[key_count] = key; + + ldns_key_list_set_key_count(key_list, key_count + 1); + return true; +} + +ldns_key * +ldns_key_list_pop_key(ldns_key_list *key_list) +{ + size_t key_count; + ldns_key** a; + ldns_key *pop; + + if (!key_list) { + return NULL; + } + + key_count = ldns_key_list_key_count(key_list); + if (key_count == 0) { + return NULL; + } + + pop = ldns_key_list_key(key_list, key_count); + + /* shrink the array */ + a = LDNS_XREALLOC(key_list->_keys, ldns_key *, key_count - 1); + if(a) { + key_list->_keys = a; + } + + ldns_key_list_set_key_count(key_list, key_count - 1); + + return pop; +} + +#ifdef HAVE_SSL +#ifndef S_SPLINT_S +/* data pointer must be large enough (LDNS_MAX_KEYLEN) */ +static bool +ldns_key_rsa2bin(unsigned char *data, RSA *k, uint16_t *size) +{ + int i,j; + + if (!k) { + return false; + } + + if (BN_num_bytes(k->e) <= 256) { + /* normally only this path is executed (small factors are + * more common + */ + data[0] = (unsigned char) BN_num_bytes(k->e); + i = BN_bn2bin(k->e, data + 1); + j = BN_bn2bin(k->n, data + i + 1); + *size = (uint16_t) i + j; + } else if (BN_num_bytes(k->e) <= 65536) { + data[0] = 0; + /* BN_bn2bin does bigendian, _uint16 also */ + ldns_write_uint16(data + 1, (uint16_t) BN_num_bytes(k->e)); + + BN_bn2bin(k->e, data + 3); + BN_bn2bin(k->n, data + 4 + BN_num_bytes(k->e)); + *size = (uint16_t) BN_num_bytes(k->n) + 6; + } else { + return false; + } + return true; +} + +/* data pointer must be large enough (LDNS_MAX_KEYLEN) */ +static bool +ldns_key_dsa2bin(unsigned char *data, DSA *k, uint16_t *size) +{ + uint8_t T; + + if (!k) { + return false; + } + + /* See RFC2536 */ + *size = (uint16_t)BN_num_bytes(k->g); + T = (*size - 64) / 8; + memcpy(data, &T, 1); + + if (T > 8) { + fprintf(stderr, "DSA key with T > 8 (ie. > 1024 bits)"); + fprintf(stderr, " not implemented\n"); + return false; + } + + /* size = 64 + (T * 8); */ + data[0] = (unsigned char)T; + BN_bn2bin(k->q, data + 1 ); /* 20 octects */ + BN_bn2bin(k->p, data + 21 ); /* offset octects */ + BN_bn2bin(k->g, data + 21 + *size); /* offset octets */ + BN_bn2bin(k->pub_key, data + 21 + *size + *size); /* offset octets */ + *size = 21 + (*size * 3); + return true; +} + +#ifdef USE_GOST +static bool +ldns_key_gost2bin(unsigned char* data, EVP_PKEY* k, uint16_t* size) +{ + int i; + unsigned char* pp = NULL; + if(i2d_PUBKEY(k, &pp) != 37 + 64) { + /* expect 37 byte(ASN header) and 64 byte(X and Y) */ + CRYPTO_free(pp); + return false; + } + /* omit ASN header */ + for(i=0; i<64; i++) + data[i] = pp[i+37]; + CRYPTO_free(pp); + *size = 64; + return true; +} +#endif /* USE_GOST */ +#endif /* splint */ +#endif /* HAVE_SSL */ + +ldns_rr * +ldns_key2rr(const ldns_key *k) +{ + /* this function will convert a the keydata contained in + * rsa/dsa pointers to a DNSKEY rr. It will fill in as + * much as it can, but it does not know about key-flags + * for instance + */ + ldns_rr *pubkey; + ldns_rdf *keybin; + unsigned char *bin = NULL; + uint16_t size = 0; +#ifdef HAVE_SSL + RSA *rsa = NULL; + DSA *dsa = NULL; +#endif /* HAVE_SSL */ +#ifdef USE_ECDSA + EC_KEY* ec; +#endif + int internal_data = 0; + + pubkey = ldns_rr_new(); + if (!k) { + return NULL; + } + + switch (ldns_key_algorithm(k)) { + case LDNS_SIGN_HMACMD5: + case LDNS_SIGN_HMACSHA1: + case LDNS_SIGN_HMACSHA256: + ldns_rr_set_type(pubkey, LDNS_RR_TYPE_KEY); + break; + default: + ldns_rr_set_type(pubkey, LDNS_RR_TYPE_DNSKEY); + break; + } + /* zero-th rdf - flags */ + ldns_rr_push_rdf(pubkey, + ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, + ldns_key_flags(k))); + /* first - proto */ + ldns_rr_push_rdf(pubkey, + ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, LDNS_DNSSEC_KEYPROTO)); + + if (ldns_key_pubkey_owner(k)) { + ldns_rr_set_owner(pubkey, ldns_rdf_clone(ldns_key_pubkey_owner(k))); + } + + /* third - da algorithm */ + switch(ldns_key_algorithm(k)) { + case LDNS_SIGN_RSAMD5: + case LDNS_SIGN_RSASHA1: + case LDNS_SIGN_RSASHA1_NSEC3: + case LDNS_SIGN_RSASHA256: + case LDNS_SIGN_RSASHA512: + ldns_rr_push_rdf(pubkey, + ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG, ldns_key_algorithm(k))); +#ifdef HAVE_SSL + rsa = ldns_key_rsa_key(k); + if (rsa) { + bin = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN); + if (!bin) { + ldns_rr_free(pubkey); + return NULL; + } + if (!ldns_key_rsa2bin(bin, rsa, &size)) { + LDNS_FREE(bin); + ldns_rr_free(pubkey); + return NULL; + } + RSA_free(rsa); + internal_data = 1; + } +#endif + size++; + break; + case LDNS_SIGN_DSA: + ldns_rr_push_rdf(pubkey, + ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG, LDNS_DSA)); +#ifdef HAVE_SSL + dsa = ldns_key_dsa_key(k); + if (dsa) { + bin = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN); + if (!bin) { + ldns_rr_free(pubkey); + return NULL; + } + if (!ldns_key_dsa2bin(bin, dsa, &size)) { + LDNS_FREE(bin); + ldns_rr_free(pubkey); + return NULL; + } + DSA_free(dsa); + internal_data = 1; + } +#endif /* HAVE_SSL */ + break; + case LDNS_SIGN_DSA_NSEC3: + ldns_rr_push_rdf(pubkey, + ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG, LDNS_DSA_NSEC3)); +#ifdef HAVE_SSL + dsa = ldns_key_dsa_key(k); + if (dsa) { + bin = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN); + if (!bin) { + ldns_rr_free(pubkey); + return NULL; + } + if (!ldns_key_dsa2bin(bin, dsa, &size)) { + LDNS_FREE(bin); + ldns_rr_free(pubkey); + return NULL; + } + DSA_free(dsa); + internal_data = 1; + } +#endif /* HAVE_SSL */ + break; + case LDNS_SIGN_ECC_GOST: + ldns_rr_push_rdf(pubkey, ldns_native2rdf_int8( + LDNS_RDF_TYPE_ALG, ldns_key_algorithm(k))); +#if defined(HAVE_SSL) && defined(USE_GOST) + bin = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN); + if (!bin) { + ldns_rr_free(pubkey); + return NULL; + } +#ifndef S_SPLINT_S + if (!ldns_key_gost2bin(bin, k->_key.key, &size)) { + LDNS_FREE(bin); + ldns_rr_free(pubkey); + return NULL; + } +#endif /* splint */ + internal_data = 1; +#else + ldns_rr_free(pubkey); + return NULL; +#endif /* HAVE_SSL and USE_GOST */ + break; + case LDNS_SIGN_ECDSAP256SHA256: + case LDNS_SIGN_ECDSAP384SHA384: +#ifdef USE_ECDSA + ldns_rr_push_rdf(pubkey, ldns_native2rdf_int8( + LDNS_RDF_TYPE_ALG, ldns_key_algorithm(k))); + bin = NULL; +#ifndef S_SPLINT_S + ec = EVP_PKEY_get1_EC_KEY(k->_key.key); +#endif + EC_KEY_set_conv_form(ec, POINT_CONVERSION_UNCOMPRESSED); + size = (uint16_t)i2o_ECPublicKey(ec, NULL); + if(!i2o_ECPublicKey(ec, &bin)) { + EC_KEY_free(ec); + ldns_rr_free(pubkey); + return NULL; + } + if(size > 1) { + /* move back one byte to shave off the 0x02 + * 'uncompressed' indicator that openssl made + * Actually its 0x04 (from implementation). + */ + assert(bin[0] == POINT_CONVERSION_UNCOMPRESSED); + size -= 1; + memmove(bin, bin+1, size); + } + /* down the reference count for ec, its still assigned + * to the pkey */ + EC_KEY_free(ec); + internal_data = 1; +#else + ldns_rr_free(pubkey); + return NULL; +#endif /* ECDSA */ + break; + case LDNS_SIGN_HMACMD5: + case LDNS_SIGN_HMACSHA1: + case LDNS_SIGN_HMACSHA256: + bin = LDNS_XMALLOC(unsigned char, ldns_key_hmac_size(k)); + if (!bin) { + ldns_rr_free(pubkey); + return NULL; + } + ldns_rr_push_rdf(pubkey, + ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG, + ldns_key_algorithm(k))); + size = ldns_key_hmac_size(k); + memcpy(bin, ldns_key_hmac_key(k), size); + internal_data = 1; + break; + } + /* fourth the key bin material */ + if (internal_data) { + keybin = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, size, bin); + LDNS_FREE(bin); + ldns_rr_push_rdf(pubkey, keybin); + } + return pubkey; +} + +void +ldns_key_free(ldns_key *key) +{ + LDNS_FREE(key); +} + +void +ldns_key_deep_free(ldns_key *key) +{ + unsigned char* hmac; + if (ldns_key_pubkey_owner(key)) { + ldns_rdf_deep_free(ldns_key_pubkey_owner(key)); + } +#ifdef HAVE_SSL + if (ldns_key_evp_key(key)) { + EVP_PKEY_free(ldns_key_evp_key(key)); + } +#endif /* HAVE_SSL */ + if (ldns_key_hmac_key(key)) { + hmac = ldns_key_hmac_key(key); + LDNS_FREE(hmac); + } + LDNS_FREE(key); +} + +void +ldns_key_list_free(ldns_key_list *key_list) +{ + size_t i; + for (i = 0; i < ldns_key_list_key_count(key_list); i++) { + ldns_key_deep_free(ldns_key_list_key(key_list, i)); + } + LDNS_FREE(key_list->_keys); + LDNS_FREE(key_list); +} + +ldns_rr * +ldns_read_anchor_file(const char *filename) +{ + FILE *fp; + /*char line[LDNS_MAX_PACKETLEN];*/ + char *line = LDNS_XMALLOC(char, LDNS_MAX_PACKETLEN); + int c; + size_t i = 0; + ldns_rr *r; + ldns_status status; + if(!line) { + return NULL; + } + + fp = fopen(filename, "r"); + if (!fp) { + fprintf(stderr, "Unable to open %s: %s\n", filename, strerror(errno)); + LDNS_FREE(line); + return NULL; + } + + while ((c = fgetc(fp)) && i+1 < LDNS_MAX_PACKETLEN && c != EOF) { + line[i] = c; + i++; + } + line[i] = '\0'; + + fclose(fp); + + if (i <= 0) { + fprintf(stderr, "nothing read from %s", filename); + LDNS_FREE(line); + return NULL; + } else { + status = ldns_rr_new_frm_str(&r, line, 0, NULL, NULL); + if (status == LDNS_STATUS_OK && (ldns_rr_get_type(r) == LDNS_RR_TYPE_DNSKEY || ldns_rr_get_type(r) == LDNS_RR_TYPE_DS)) { + LDNS_FREE(line); + return r; + } else { + fprintf(stderr, "Error creating DNSKEY or DS rr from %s: %s\n", filename, ldns_get_errorstr_by_id(status)); + LDNS_FREE(line); + return NULL; + } + } +} + +char * +ldns_key_get_file_base_name(ldns_key *key) +{ + ldns_buffer *buffer; + char *file_base_name; + + buffer = ldns_buffer_new(255); + ldns_buffer_printf(buffer, "K"); + (void)ldns_rdf2buffer_str_dname(buffer, ldns_key_pubkey_owner(key)); + ldns_buffer_printf(buffer, + "+%03u+%05u", + ldns_key_algorithm(key), + ldns_key_keytag(key)); + file_base_name = strdup(ldns_buffer_export(buffer)); + ldns_buffer_free(buffer); + return file_base_name; +} + +int ldns_key_algo_supported(int algo) +{ + ldns_lookup_table *lt = ldns_signing_algorithms; + while(lt->name) { + if(lt->id == algo) + return 1; + lt++; + } + return 0; +} + +ldns_signing_algorithm ldns_get_signing_algorithm_by_name(const char* name) +{ + /* list of (signing algorithm id, alias_name) */ + ldns_lookup_table aliases[] = { + /* from bind dnssec-keygen */ + {LDNS_SIGN_HMACMD5, "HMAC-MD5"}, + {LDNS_SIGN_DSA_NSEC3, "NSEC3DSA"}, + {LDNS_SIGN_RSASHA1_NSEC3, "NSEC3RSASHA1"}, + /* old ldns usage, now RFC names */ + {LDNS_SIGN_DSA_NSEC3, "DSA_NSEC3" }, + {LDNS_SIGN_RSASHA1_NSEC3, "RSASHA1_NSEC3" }, +#ifdef USE_GOST + {LDNS_SIGN_ECC_GOST, "GOST"}, +#endif + /* compat with possible output */ + {LDNS_DH, "DH"}, + {LDNS_ECC, "ECC"}, + {LDNS_INDIRECT, "INDIRECT"}, + {LDNS_PRIVATEDNS, "PRIVATEDNS"}, + {LDNS_PRIVATEOID, "PRIVATEOID"}, + {0, NULL}}; + ldns_lookup_table* lt = ldns_signing_algorithms; + while(lt->name) { + if(strcasecmp(lt->name, name) == 0) + return lt->id; + lt++; + } + lt = aliases; + while(lt->name) { + if(strcasecmp(lt->name, name) == 0) + return lt->id; + lt++; + } + if(atoi(name) != 0) + return atoi(name); + return 0; +} diff --git a/ldns/buffer.h b/ldns/buffer.h new file mode 100644 index 00000000000..03df14c9915 --- /dev/null +++ b/ldns/buffer.h @@ -0,0 +1,644 @@ +/* + * buffer.h -- generic memory buffer. + * + * Copyright (c) 2005-2008, NLnet Labs. All rights reserved. + * + * See LICENSE for the license. + * + * + * The buffer module implements a generic buffer. The API is based on + * the java.nio.Buffer interface. + */ + +#ifndef LDNS_BUFFER_H +#define LDNS_BUFFER_H + +#include +#include +#include + +#include +#include + +#include "ldns/util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * number of initial bytes in buffer of + * which we cannot tell the size before hand + */ +#define LDNS_MIN_BUFLEN 512 + +/** + * \file buffer.h + * + * This file contains the definition of ldns_buffer, and functions to manipulate those. + */ + +/** + * implementation of buffers to ease operations + * + * ldns_buffers can contain arbitrary information, per octet. You can write + * to the current end of a buffer, read from the current position, and + * access any data within it. + * + * Example use of buffers is in the source code of \ref host2str.c + */ +struct ldns_struct_buffer +{ + /** The current position used for reading/writing */ + size_t _position; + + /** The read/write limit */ + size_t _limit; + + /** The amount of data the buffer can contain */ + size_t _capacity; + + /** The data contained in the buffer */ + uint8_t *_data; + + /** If the buffer is fixed it cannot be resized */ + unsigned _fixed : 1; + + /** The current state of the buffer. If writing to the buffer fails + * for any reason, this value is changed. This way, you can perform + * multiple writes in sequence and check for success afterwards. */ + ldns_status _status; +}; +typedef struct ldns_struct_buffer ldns_buffer; + + +#ifdef NDEBUG +INLINE void +ldns_buffer_invariant(ldns_buffer *ATTR_UNUSED(buffer)) +{ +} +#else +INLINE void +ldns_buffer_invariant(ldns_buffer *buffer) +{ + assert(buffer != NULL); + assert(buffer->_position <= buffer->_limit); + assert(buffer->_limit <= buffer->_capacity); + assert(buffer->_data != NULL); +} +#endif + +/** + * creates a new buffer with the specified capacity. + * + * \param[in] capacity the size (in bytes) to allocate for the buffer + * \return the created buffer + */ +ldns_buffer *ldns_buffer_new(size_t capacity); + +/** + * creates a buffer with the specified data. The data IS copied + * and MEMORY allocations are done. The buffer is not fixed and can + * be resized using buffer_reserve(). + * + * \param[in] buffer pointer to the buffer to put the data in + * \param[in] data the data to encapsulate in the buffer + * \param[in] size the size of the data + */ +void ldns_buffer_new_frm_data(ldns_buffer *buffer, void *data, size_t size); + +/** + * clears the buffer and make it ready for writing. The buffer's limit + * is set to the capacity and the position is set to 0. + * \param[in] buffer the buffer to clear + */ +INLINE void ldns_buffer_clear(ldns_buffer *buffer) +{ + ldns_buffer_invariant(buffer); + + /* reset status here? */ + + buffer->_position = 0; + buffer->_limit = buffer->_capacity; +} + +/** + * makes the buffer ready for reading the data that has been written to + * the buffer. The buffer's limit is set to the current position and + * the position is set to 0. + * + * \param[in] buffer the buffer to flip + * \return void + */ +INLINE void ldns_buffer_flip(ldns_buffer *buffer) +{ + ldns_buffer_invariant(buffer); + + buffer->_limit = buffer->_position; + buffer->_position = 0; +} + +/** + * make the buffer ready for re-reading the data. The buffer's + * position is reset to 0. + * \param[in] buffer the buffer to rewind + */ +INLINE void ldns_buffer_rewind(ldns_buffer *buffer) +{ + ldns_buffer_invariant(buffer); + + buffer->_position = 0; +} + +/** + * returns the current position in the buffer (as a number of bytes) + * \param[in] buffer the buffer + * \return the current position + */ +INLINE size_t +ldns_buffer_position(ldns_buffer *buffer) +{ + return buffer->_position; +} + +/** + * sets the buffer's position to MARK. The position must be less than + * or equal to the buffer's limit. + * \param[in] buffer the buffer + * \param[in] mark the mark to use + */ +INLINE void +ldns_buffer_set_position(ldns_buffer *buffer, size_t mark) +{ + assert(mark <= buffer->_limit); + buffer->_position = mark; +} + +/** + * changes the buffer's position by COUNT bytes. The position must not + * be moved behind the buffer's limit or before the beginning of the + * buffer. + * \param[in] buffer the buffer + * \param[in] count the count to use + */ +INLINE void +ldns_buffer_skip(ldns_buffer *buffer, ssize_t count) +{ + assert(buffer->_position + count <= buffer->_limit); + buffer->_position += count; +} + +/** + * returns the maximum size of the buffer + * \param[in] buffer + * \return the size + */ +INLINE size_t +ldns_buffer_limit(ldns_buffer *buffer) +{ + return buffer->_limit; +} + +/** + * changes the buffer's limit. If the buffer's position is greater + * than the new limit the position is set to the limit. + * \param[in] buffer the buffer + * \param[in] limit the new limit + */ +INLINE void +ldns_buffer_set_limit(ldns_buffer *buffer, size_t limit) +{ + assert(limit <= buffer->_capacity); + buffer->_limit = limit; + if (buffer->_position > buffer->_limit) + buffer->_position = buffer->_limit; +} + +/** + * returns the number of bytes the buffer can hold. + * \param[in] buffer the buffer + * \return the number of bytes + */ +INLINE size_t +ldns_buffer_capacity(ldns_buffer *buffer) +{ + return buffer->_capacity; +} + +/** + * changes the buffer's capacity. The data is reallocated so any + * pointers to the data may become invalid. The buffer's limit is set + * to the buffer's new capacity. + * \param[in] buffer the buffer + * \param[in] capacity the capacity to use + * \return whether this failed or succeeded + */ +bool ldns_buffer_set_capacity(ldns_buffer *buffer, size_t capacity); + +/** + * ensures BUFFER can contain at least AMOUNT more bytes. The buffer's + * capacity is increased if necessary using buffer_set_capacity(). + * + * The buffer's limit is always set to the (possibly increased) + * capacity. + * \param[in] buffer the buffer + * \param[in] amount amount to use + * \return whether this failed or succeeded + */ +bool ldns_buffer_reserve(ldns_buffer *buffer, size_t amount); + +/** + * returns a pointer to the data at the indicated position. + * \param[in] buffer the buffer + * \param[in] at position + * \return the pointer to the data + */ +INLINE uint8_t * +ldns_buffer_at(const ldns_buffer *buffer, size_t at) +{ + assert(at <= buffer->_limit); + return buffer->_data + at; +} + +/** + * returns a pointer to the beginning of the buffer (the data at + * position 0). + * \param[in] buffer the buffer + * \return the pointer + */ +INLINE uint8_t * +ldns_buffer_begin(const ldns_buffer *buffer) +{ + return ldns_buffer_at(buffer, 0); +} + +/** + * returns a pointer to the end of the buffer (the data at the buffer's + * limit). + * \param[in] buffer the buffer + * \return the pointer + */ +INLINE uint8_t * +ldns_buffer_end(ldns_buffer *buffer) +{ + return ldns_buffer_at(buffer, buffer->_limit); +} + +/** + * returns a pointer to the data at the buffer's current position. + * \param[in] buffer the buffer + * \return the pointer + */ +INLINE uint8_t * +ldns_buffer_current(ldns_buffer *buffer) +{ + return ldns_buffer_at(buffer, buffer->_position); +} + +/** + * returns the number of bytes remaining between the indicated position and + * the limit. + * \param[in] buffer the buffer + * \param[in] at indicated position + * \return number of bytes + */ +INLINE size_t +ldns_buffer_remaining_at(ldns_buffer *buffer, size_t at) +{ + ldns_buffer_invariant(buffer); + assert(at <= buffer->_limit); + return buffer->_limit - at; +} + +/** + * returns the number of bytes remaining between the buffer's position and + * limit. + * \param[in] buffer the buffer + * \return the number of bytes + */ +INLINE size_t +ldns_buffer_remaining(ldns_buffer *buffer) +{ + return ldns_buffer_remaining_at(buffer, buffer->_position); +} + +/** + * checks if the buffer has at least COUNT more bytes available. + * Before reading or writing the caller needs to ensure enough space + * is available! + * \param[in] buffer the buffer + * \param[in] at indicated position + * \param[in] count how much is available + * \return true or false (as int?) + */ +INLINE int +ldns_buffer_available_at(ldns_buffer *buffer, size_t at, size_t count) +{ + return count <= ldns_buffer_remaining_at(buffer, at); +} + +/** + * checks if the buffer has count bytes available at the current position + * \param[in] buffer the buffer + * \param[in] count how much is available + * \return true or false (as int?) + */ +INLINE int +ldns_buffer_available(ldns_buffer *buffer, size_t count) +{ + return ldns_buffer_available_at(buffer, buffer->_position, count); +} + +/** + * writes the given data to the buffer at the specified position + * \param[in] buffer the buffer + * \param[in] at the position (in number of bytes) to write the data at + * \param[in] data pointer to the data to write to the buffer + * \param[in] count the number of bytes of data to write + */ +INLINE void +ldns_buffer_write_at(ldns_buffer *buffer, size_t at, const void *data, size_t count) +{ + assert(ldns_buffer_available_at(buffer, at, count)); + memcpy(buffer->_data + at, data, count); +} + +/** + * writes count bytes of data to the current position of the buffer + * \param[in] buffer the buffer + * \param[in] data the data to write + * \param[in] count the lenght of the data to write + */ +INLINE void +ldns_buffer_write(ldns_buffer *buffer, const void *data, size_t count) +{ + ldns_buffer_write_at(buffer, buffer->_position, data, count); + buffer->_position += count; +} + +/** + * copies the given (null-delimited) string to the specified position at the buffer + * \param[in] buffer the buffer + * \param[in] at the position in the buffer + * \param[in] str the string to write + */ +INLINE void +ldns_buffer_write_string_at(ldns_buffer *buffer, size_t at, const char *str) +{ + ldns_buffer_write_at(buffer, at, str, strlen(str)); +} + +/** + * copies the given (null-delimited) string to the current position at the buffer + * \param[in] buffer the buffer + * \param[in] str the string to write + */ +INLINE void +ldns_buffer_write_string(ldns_buffer *buffer, const char *str) +{ + ldns_buffer_write(buffer, str, strlen(str)); +} + +/** + * writes the given byte of data at the given position in the buffer + * \param[in] buffer the buffer + * \param[in] at the position in the buffer + * \param[in] data the 8 bits to write + */ +INLINE void +ldns_buffer_write_u8_at(ldns_buffer *buffer, size_t at, uint8_t data) +{ + assert(ldns_buffer_available_at(buffer, at, sizeof(data))); + buffer->_data[at] = data; +} + +/** + * writes the given byte of data at the current position in the buffer + * \param[in] buffer the buffer + * \param[in] data the 8 bits to write + */ +INLINE void +ldns_buffer_write_u8(ldns_buffer *buffer, uint8_t data) +{ + ldns_buffer_write_u8_at(buffer, buffer->_position, data); + buffer->_position += sizeof(data); +} + +/** + * writes the given 2 byte integer at the given position in the buffer + * \param[in] buffer the buffer + * \param[in] at the position in the buffer + * \param[in] data the 16 bits to write + */ +INLINE void +ldns_buffer_write_u16_at(ldns_buffer *buffer, size_t at, uint16_t data) +{ + assert(ldns_buffer_available_at(buffer, at, sizeof(data))); + ldns_write_uint16(buffer->_data + at, data); +} + +/** + * writes the given 2 byte integer at the current position in the buffer + * \param[in] buffer the buffer + * \param[in] data the 16 bits to write + */ +INLINE void +ldns_buffer_write_u16(ldns_buffer *buffer, uint16_t data) +{ + ldns_buffer_write_u16_at(buffer, buffer->_position, data); + buffer->_position += sizeof(data); +} + +/** + * writes the given 4 byte integer at the given position in the buffer + * \param[in] buffer the buffer + * \param[in] at the position in the buffer + * \param[in] data the 32 bits to write + */ +INLINE void +ldns_buffer_write_u32_at(ldns_buffer *buffer, size_t at, uint32_t data) +{ + assert(ldns_buffer_available_at(buffer, at, sizeof(data))); + ldns_write_uint32(buffer->_data + at, data); +} + +/** + * writes the given 4 byte integer at the current position in the buffer + * \param[in] buffer the buffer + * \param[in] data the 32 bits to write + */ +INLINE void +ldns_buffer_write_u32(ldns_buffer *buffer, uint32_t data) +{ + ldns_buffer_write_u32_at(buffer, buffer->_position, data); + buffer->_position += sizeof(data); +} + +/** + * copies count bytes of data at the given position to the given data-array + * \param[in] buffer the buffer + * \param[in] at the position in the buffer to start + * \param[out] data buffer to copy to + * \param[in] count the length of the data to copy + */ +INLINE void +ldns_buffer_read_at(ldns_buffer *buffer, size_t at, void *data, size_t count) +{ + assert(ldns_buffer_available_at(buffer, at, count)); + memcpy(data, buffer->_data + at, count); +} + +/** + * copies count bytes of data at the current position to the given data-array + * \param[in] buffer the buffer + * \param[out] data buffer to copy to + * \param[in] count the length of the data to copy + */ +INLINE void +ldns_buffer_read(ldns_buffer *buffer, void *data, size_t count) +{ + ldns_buffer_read_at(buffer, buffer->_position, data, count); + buffer->_position += count; +} + +/** + * returns the byte value at the given position in the buffer + * \param[in] buffer the buffer + * \param[in] at the position in the buffer + * \return 1 byte integer + */ +INLINE uint8_t +ldns_buffer_read_u8_at(ldns_buffer *buffer, size_t at) +{ + assert(ldns_buffer_available_at(buffer, at, sizeof(uint8_t))); + return buffer->_data[at]; +} + +/** + * returns the byte value at the current position in the buffer + * \param[in] buffer the buffer + * \return 1 byte integer + */ +INLINE uint8_t +ldns_buffer_read_u8(ldns_buffer *buffer) +{ + uint8_t result = ldns_buffer_read_u8_at(buffer, buffer->_position); + buffer->_position += sizeof(uint8_t); + return result; +} + +/** + * returns the 2-byte integer value at the given position in the buffer + * \param[in] buffer the buffer + * \param[in] at position in the buffer + * \return 2 byte integer + */ +INLINE uint16_t +ldns_buffer_read_u16_at(ldns_buffer *buffer, size_t at) +{ + assert(ldns_buffer_available_at(buffer, at, sizeof(uint16_t))); + return ldns_read_uint16(buffer->_data + at); +} + +/** + * returns the 2-byte integer value at the current position in the buffer + * \param[in] buffer the buffer + * \return 2 byte integer + */ +INLINE uint16_t +ldns_buffer_read_u16(ldns_buffer *buffer) +{ + uint16_t result = ldns_buffer_read_u16_at(buffer, buffer->_position); + buffer->_position += sizeof(uint16_t); + return result; +} + +/** + * returns the 4-byte integer value at the given position in the buffer + * \param[in] buffer the buffer + * \param[in] at position in the buffer + * \return 4 byte integer + */ +INLINE uint32_t +ldns_buffer_read_u32_at(ldns_buffer *buffer, size_t at) +{ + assert(ldns_buffer_available_at(buffer, at, sizeof(uint32_t))); + return ldns_read_uint32(buffer->_data + at); +} + +/** + * returns the 4-byte integer value at the current position in the buffer + * \param[in] buffer the buffer + * \return 4 byte integer + */ +INLINE uint32_t +ldns_buffer_read_u32(ldns_buffer *buffer) +{ + uint32_t result = ldns_buffer_read_u32_at(buffer, buffer->_position); + buffer->_position += sizeof(uint32_t); + return result; +} + +/** + * returns the status of the buffer + * \param[in] buffer + * \return the status + */ +INLINE ldns_status +ldns_buffer_status(ldns_buffer *buffer) +{ + return buffer->_status; +} + +/** + * returns true if the status of the buffer is LDNS_STATUS_OK, false otherwise + * \param[in] buffer the buffer + * \return true or false + */ +INLINE bool +ldns_buffer_status_ok(ldns_buffer *buffer) +{ + if (buffer) { + return ldns_buffer_status(buffer) == LDNS_STATUS_OK; + } else { + return false; + } +} + +/** + * prints to the buffer, increasing the capacity if required using + * buffer_reserve(). The buffer's position is set to the terminating '\\0' + * Returns the number of characters written (not including the + * terminating '\\0') or -1 on failure. + */ +int ldns_buffer_printf(ldns_buffer *buffer, const char *format, ...); +/* ATTR_FORMAT(printf, 2, 3);*/ + +/** + * frees the buffer. + * \param[in] *buffer the buffer to be freed + * \return void + */ +void ldns_buffer_free(ldns_buffer *buffer); + +/** + * Makes the buffer fixed and returns a pointer to the data. The + * caller is responsible for free'ing the result. + * \param[in] *buffer the buffer to be exported + * \return void + */ +void *ldns_buffer_export(ldns_buffer *buffer); + +/** + * Copy contents of the other buffer to this buffer. Silently truncated + * if this buffer is too small. + * \param[out] *result resulting buffer which is copied to. + * \param[in] *from what to copy to result. + */ +void ldns_buffer_copy(ldns_buffer* result, ldns_buffer* from); + +#ifdef __cplusplus +} +#endif + +#endif /* LDNS_BUFFER_H */ diff --git a/ldns/common.h.in b/ldns/common.h.in new file mode 100644 index 00000000000..5d6254752a5 --- /dev/null +++ b/ldns/common.h.in @@ -0,0 +1,68 @@ +/** + * \file common.h + * + * Common definitions for LDNS + */ + +/** + * a Net::DNS like library for C + * + * (c) NLnet Labs, 2004-2006 + * + * See the file LICENSE for the license + */ + +#ifndef LDNS_COMMON_H +#define LDNS_COMMON_H + +/* + * The build configuration that is used in the distributed headers, + * as detected and determined by the auto configure script. + */ +#define LDNS_BUILD_CONFIG_HAVE_SSL @ldns_build_config_have_ssl@ +#define LDNS_BUILD_CONFIG_HAVE_INTTYPES_H @ldns_build_config_have_inttypes_h@ +#define LDNS_BUILD_CONFIG_HAVE_ATTR_FORMAT @ldns_build_config_have_attr_format@ +#define LDNS_BUILD_CONFIG_HAVE_ATTR_UNUSED @ldns_build_config_have_attr_unused@ + +/* + * HAVE_STDBOOL_H is not available when distributed as a library, but no build + * configuration variables may be used (like those above) because the header + * is sometimes only available when using special compiler flags to enable the + * c99 environment. Because we cannot force the usage of this flag, we have to + * provide a default type. Below what is suggested by the autoconf manual. + */ +/*@ignore@*/ +/* splint barfs on this construct */ +#ifdef HAVE_STDBOOL_H +# include +#else +# ifndef HAVE__BOOL +# ifdef __cplusplus +typedef bool _Bool; +# else +# define _Bool signed char +# endif +# endif +# define bool _Bool +# define false 0 +# define true 1 +# define __bool_true_false_are_defined 1 +#endif +/*@end@*/ + +#if LDNS_BUILD_CONFIG_HAVE_ATTR_FORMAT +#define ATTR_FORMAT(archetype, string_index, first_to_check) \ + __attribute__ ((format (archetype, string_index, first_to_check))) +#else /* !LDNS_BUILD_CONFIG_HAVE_ATTR_FORMAT */ +#define ATTR_FORMAT(archetype, string_index, first_to_check) /* empty */ +#endif /* !LDNS_BUILD_CONFIG_HAVE_ATTR_FORMAT */ + +#if defined(__cplusplus) +#define ATTR_UNUSED(x) +#elif LDNS_BUILD_CONFIG_HAVE_ATTR_UNUSED +#define ATTR_UNUSED(x) x __attribute__((unused)) +#else /* !LDNS_BUILD_CONFIG_HAVE_ATTR_UNUSED */ +#define ATTR_UNUSED(x) x +#endif /* !LDNS_BUILD_CONFIG_HAVE_ATTR_UNUSED */ + +#endif /* LDNS_COMMON_H */ diff --git a/ldns/config.h.in b/ldns/config.h.in new file mode 100644 index 00000000000..3393e99767e --- /dev/null +++ b/ldns/config.h.in @@ -0,0 +1,555 @@ +/* ldns/config.h.in. Generated from configure.ac by autoheader. */ + +/* Define if building universal (internal helper macro) */ +#undef AC_APPLE_UNIVERSAL_BUILD + +/* Define to 1 if you have the header file. */ +#undef HAVE_ARPA_INET_H + +/* Whether the C compiler accepts the "format" attribute */ +#undef HAVE_ATTR_FORMAT + +/* Whether the C compiler accepts the "unused" attribute */ +#undef HAVE_ATTR_UNUSED + +/* Define to 1 if you have the `b32_ntop' function. */ +#undef HAVE_B32_NTOP + +/* Define to 1 if you have the `b32_pton' function. */ +#undef HAVE_B32_PTON + +/* Define to 1 if you have the `b64_ntop' function. */ +#undef HAVE_B64_NTOP + +/* Define to 1 if you have the `b64_pton' function. */ +#undef HAVE_B64_PTON + +/* Define to 1 if you have the `bzero' function. */ +#undef HAVE_BZERO + +/* Define to 1 if you have the `calloc' function. */ +#undef HAVE_CALLOC + +/* Define to 1 if you have the `ctime_r' function. */ +#undef HAVE_CTIME_R + +/* Define to 1 if you have the declaration of `NID_secp384r1', and to 0 if you + don't. */ +#undef HAVE_DECL_NID_SECP384R1 + +/* Define to 1 if you have the declaration of `NID_X9_62_prime256v1', and to 0 + if you don't. */ +#undef HAVE_DECL_NID_X9_62_PRIME256V1 + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the `endprotoent' function. */ +#undef HAVE_ENDPROTOENT + +/* Define to 1 if you have the `endservent' function. */ +#undef HAVE_ENDSERVENT + +/* Define to 1 if you have the `EVP_sha256' function. */ +#undef HAVE_EVP_SHA256 + +/* Define to 1 if you have the `fcntl' function. */ +#undef HAVE_FCNTL + +/* Define to 1 if you have the `fork' function. */ +#undef HAVE_FORK + +/* Whether getaddrinfo is available */ +#undef HAVE_GETADDRINFO + +/* Define to 1 if you have the header file. */ +#undef HAVE_GETOPT_H + +/* Define to 1 if you have the `gmtime_r' function. */ +#undef HAVE_GMTIME_R + +/* If you have HMAC_CTX_init */ +#undef HAVE_HMAC_CTX_INIT + +/* Define to 1 if you have the `inet_aton' function. */ +#undef HAVE_INET_ATON + +/* Define to 1 if you have the `inet_ntop' function. */ +#undef HAVE_INET_NTOP + +/* Define to 1 if you have the `inet_pton' function. */ +#undef HAVE_INET_PTON + +/* Define to 1 if the system has the type `intptr_t'. */ +#undef HAVE_INTPTR_T + +/* define if you have inttypes.h */ +#undef HAVE_INTTYPES_H + +/* if the function 'ioctlsocket' is available */ +#undef HAVE_IOCTLSOCKET + +/* Define to 1 if you have the `isascii' function. */ +#undef HAVE_ISASCII + +/* Define to 1 if you have the `isblank' function. */ +#undef HAVE_ISBLANK + +/* Define to 1 if you have the `pcap' library (-lpcap). */ +#undef HAVE_LIBPCAP + +/* Define to 1 if you have the `localtime_r' function. */ +#undef HAVE_LOCALTIME_R + +/* Define to 1 if your system has a GNU libc compatible `malloc' function, and + to 0 otherwise. */ +#undef HAVE_MALLOC + +/* Define to 1 if you have the `memmove' function. */ +#undef HAVE_MEMMOVE + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `memset' function. */ +#undef HAVE_MEMSET + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETDB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IF_ETHER_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IGMP_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IN_SYSTM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IP6_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IP_COMPAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IP_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_UDP_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NET_ETHERNET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NET_IF_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_ERR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_RAND_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_SSL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_PCAP_H + +/* If available, contains the Python version number currently in use. */ +#undef HAVE_PYTHON + +/* Define to 1 if you have the `random' function. */ +#undef HAVE_RANDOM + +/* Define to 1 if your system has a GNU libc compatible `realloc' function, + and to 0 otherwise. */ +#undef HAVE_REALLOC + +/* Define to 1 if you have the `sleep' function. */ +#undef HAVE_SLEEP + +/* Define to 1 if you have the `snprintf' function. */ +#undef HAVE_SNPRINTF + +/* Define if you have the SSL libraries installed. */ +#undef HAVE_SSL + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDARG_H + +/* Define to 1 if stdbool.h conforms to C99. */ +#undef HAVE_STDBOOL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strlcpy' function. */ +#undef HAVE_STRLCPY + +/* Define to 1 if you have the `strtoul' function. */ +#undef HAVE_STRTOUL + +/* Define if you have SWIG libraries and header files. */ +#undef HAVE_SWIG + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_MOUNT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* define if you have sys/socket.h */ +#undef HAVE_SYS_SOCKET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* define if you have sys/types.h */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the `timegm' function. */ +#undef HAVE_TIMEGM + +/* Define to 1 if you have the header file. */ +#undef HAVE_TIME_H + +/* define if you have unistd.h */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the `vfork' function. */ +#undef HAVE_VFORK + +/* Define to 1 if you have the header file. */ +#undef HAVE_VFORK_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_WINSOCK2_H + +/* Define to 1 if `fork' works. */ +#undef HAVE_WORKING_FORK + +/* Define to 1 if `vfork' works. */ +#undef HAVE_WORKING_VFORK + +/* Define to 1 if you have the header file. */ +#undef HAVE_WS2TCPIP_H + +/* Define to 1 if the system has the type `_Bool'. */ +#undef HAVE__BOOL + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#undef LT_OBJDIR + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* The size of `time_t', as computed by sizeof. */ +#undef SIZEOF_TIME_T + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* System configuration dir */ +#undef SYSCONFDIR + +/* Define this to enable ECDSA support. */ +#undef USE_ECDSA + +/* Define this to enable GOST support. */ +#undef USE_GOST + +/* Define this to enable SHA256 and SHA512 support. */ +#undef USE_SHA2 + +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# undef _ALL_SOURCE +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# undef _GNU_SOURCE +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# undef _POSIX_PTHREAD_SEMANTICS +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# undef _TANDEM_SOURCE +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# undef __EXTENSIONS__ +#endif + + +/* Whether the windows socket API is used */ +#undef USE_WINSOCK + +/* the version of the windows API enabled */ +#undef WINVER + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +# undef WORDS_BIGENDIAN +# endif +#endif + +/* Define to 1 if on MINIX. */ +#undef _MINIX + +/* Define to 2 if the system does not provide POSIX.1 features except with + this defined. */ +#undef _POSIX_1_SOURCE + +/* Define to 1 if you need to in order for `stat' and other things to work. */ +#undef _POSIX_SOURCE + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* in_addr_t */ +#undef in_addr_t + +/* in_port_t */ +#undef in_port_t + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +#undef inline +#endif + +/* Define to `short' if does not define. */ +#undef int16_t + +/* Define to `int' if does not define. */ +#undef int32_t + +/* Define to `long long' if does not define. */ +#undef int64_t + +/* Define to `char' if does not define. */ +#undef int8_t + +/* Define to the type of a signed integer type wide enough to hold a pointer, + if such a type exists, and if the system does not define it. */ +#undef intptr_t + +/* Define to rpl_malloc if the replacement function should be used. */ +#undef malloc + +/* Define to `int' if does not define. */ +#undef pid_t + +/* Define to rpl_realloc if the replacement function should be used. */ +#undef realloc + +/* Define to `unsigned int' if does not define. */ +#undef size_t + +/* Define to 'int' if not defined */ +#undef socklen_t + +/* Fallback member name for socket family in struct sockaddr_storage */ +#undef ss_family + +/* Define to `int' if does not define. */ +#undef ssize_t + +/* Define to `unsigned short' if does not define. */ +#undef uint16_t + +/* Define to `unsigned int' if does not define. */ +#undef uint32_t + +/* Define to `unsigned long long' if does not define. */ +#undef uint64_t + +/* Define to `unsigned char' if does not define. */ +#undef uint8_t + +/* Define as `fork' if `vfork' does not work. */ +#undef vfork + + +#include +#include +#include +#include + +#ifndef LITTLE_ENDIAN +#define LITTLE_ENDIAN 1234 +#endif + +#ifndef BIG_ENDIAN +#define BIG_ENDIAN 4321 +#endif + +#ifndef BYTE_ORDER +#ifdef WORDS_BIGENDIAN +#define BYTE_ORDER BIG_ENDIAN +#else +#define BYTE_ORDER LITTLE_ENDIAN +#endif /* WORDS_BIGENDIAN */ +#endif /* BYTE_ORDER */ + +#if STDC_HEADERS +#include +#include +#endif + +#ifdef HAVE_STDINT_H +#include +#endif + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#ifdef HAVE_WINSOCK2_H +#include +#endif + +#ifdef HAVE_WS2TCPIP_H +#include +#endif + + +/* detect if we need to cast to unsigned int for FD_SET to avoid warnings */ +#ifdef HAVE_WINSOCK2_H +#define FD_SET_T (u_int) +#else +#define FD_SET_T +#endif + + + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef B64_PTON +int ldns_b64_ntop(uint8_t const *src, size_t srclength, + char *target, size_t targsize); +/** + * calculates the size needed to store the result of b64_ntop + */ +/*@unused@*/ +static inline size_t ldns_b64_ntop_calculate_size(size_t srcsize) +{ + return ((((srcsize + 2) / 3) * 4) + 1); +} +#endif /* !B64_PTON */ +#ifndef B64_NTOP +int ldns_b64_pton(char const *src, uint8_t *target, size_t targsize); +/** + * calculates the size needed to store the result of ldns_b64_pton + */ +/*@unused@*/ +static inline size_t ldns_b64_pton_calculate_size(size_t srcsize) +{ + return (((((srcsize + 3) / 4) * 3)) + 1); +} +#endif /* !B64_NTOP */ + +#ifndef HAVE_SLEEP +/* use windows sleep, in millisecs, instead */ +#define sleep(x) Sleep((x)*1000) +#endif + +#ifndef HAVE_RANDOM +#define srandom(x) srand(x) +#define random(x) rand(x) +#endif + +#ifndef HAVE_TIMEGM +#include +time_t timegm (struct tm *tm); +#endif /* !TIMEGM */ +#ifndef HAVE_GMTIME_R +struct tm *gmtime_r(const time_t *timep, struct tm *result); +#endif +#ifndef HAVE_LOCALTIME_R +struct tm *localtime_r(const time_t *timep, struct tm *result); +#endif +#ifndef HAVE_ISBLANK +int isblank(int c); +#endif /* !HAVE_ISBLANK */ +#ifndef HAVE_ISASCII +int isascii(int c); +#endif /* !HAVE_ISASCII */ +#ifndef HAVE_SNPRINTF +#include +int snprintf (char *str, size_t count, const char *fmt, ...); +int vsnprintf (char *str, size_t count, const char *fmt, va_list arg); +#endif /* HAVE_SNPRINTF */ +#ifndef HAVE_INET_PTON +int inet_pton(int af, const char* src, void* dst); +#endif /* HAVE_INET_PTON */ +#ifndef HAVE_INET_NTOP +const char *inet_ntop(int af, const void *src, char *dst, size_t size); +#endif +#ifndef HAVE_INET_ATON +int inet_aton(const char *cp, struct in_addr *addr); +#endif +#ifndef HAVE_MEMMOVE +void *memmove(void *dest, const void *src, size_t n); +#endif +#ifndef HAVE_STRLCPY +size_t strlcpy(char *dst, const char *src, size_t siz); +#endif +#ifdef __cplusplus +} +#endif +#ifndef HAVE_GETADDRINFO +#include "compat/fake-rfc2553.h" +#endif +#ifndef HAVE_STRTOUL +#define strtoul (unsigned long)strtol +#endif + diff --git a/ldns/dname.h b/ldns/dname.h new file mode 100644 index 00000000000..a91f075257c --- /dev/null +++ b/ldns/dname.h @@ -0,0 +1,201 @@ +/* + * dname.h + * + * dname definitions + * + * a Net::DNS like library for C + * + * (c) NLnet Labs, 2004-2006 + * + * See the file LICENSE for the license + */ + +/** + * \file dname.h + * + * dname contains function to read and manipulate domain names. + * + * Example domain names are "www.nlnetlabs.nl." and "." (the root) + * + * If a domain name ends with a dot ("."), it is called a Fully Qualified + * Domain Name (FQDN). In certain places (for instance when reading a zone + * file), an origin (which is just another domain name) non-FQDNs will be + * placed after the current. For instance, if i have a zone file where the + * origin has been set to "nl.", and my file contains the name + * "www.nlnetlabs", it will result in "www.nlnetlabs.nl.". Internally, dnames are + * always absolute (the dot is added when it is missing and there is no origin). + * + * An FQDN is also + * known as an absolute domain name, therefore the function to check this is + * called \ref ldns_dname_str_absolute + * + * Domain names are stored in \ref ldns_rdf structures, with the type + * \ref LDNS_RDF_TYPE_DNAME + * + * This module is *NOT* about the RR type called DNAME. + */ + + +#ifndef LDNS_DNAME_H +#define LDNS_DNAME_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define LDNS_DNAME_NORMALIZE tolower + +/** + * concatenates two dnames together + * \param[in] rd1 the leftside + * \param[in] rd2 the rightside + * \return a new rdf with leftside/rightside + */ +ldns_rdf *ldns_dname_cat_clone(const ldns_rdf *rd1, const ldns_rdf *rd2); + +/** + * concatenates rd2 after rd1 (rd2 is copied, rd1 is modified) + * \param[in] rd1 the leftside + * \param[in] rd2 the rightside + * \return LDNS_STATUS_OK on success + */ +ldns_status ldns_dname_cat(ldns_rdf *rd1, ldns_rdf *rd2); + +/** + * Returns a clone of the given dname with the labels + * reversed + * \param[in] d the dname to reverse + * \return clone of the dname with the labels reversed. + */ +ldns_rdf *ldns_dname_reverse(const ldns_rdf *d); + +/** + * Clones the given dname from the nth label on + * \param[in] d The dname to clone + * \param[in] n the label nr to clone from, if this is 0, the complete + * dname is cloned + * \return A newly allocated *rdf structure, containing the cloned dname, + * or NULL if either d was NULL, not a dname, or if n >= + * label_count + */ +ldns_rdf * +ldns_dname_clone_from(const ldns_rdf *d, uint16_t n); + +/** + * chop one label off the left side of a dname. so + * wwww.nlnetlabs.nl, becomes nlnetlabs.nl + * This new name is a clone and must be freed with ldns_deep_free() + * \param[in] d the dname to chop + * \return the remaining dname + */ +ldns_rdf *ldns_dname_left_chop(const ldns_rdf *d); + +/** + * count the number of labels inside a LDNS_RDF_DNAME type rdf. + * \param[in] *r the rdf + * \return the number of labels + */ +uint8_t ldns_dname_label_count(const ldns_rdf *r); + +/** + * creates a new dname rdf from a string. + * \param[in] str string to use + * \return ldns_rdf* or NULL in case of an error + */ +ldns_rdf *ldns_dname_new_frm_str(const char *str); + +/** + * Create a new dname rdf from a string + * \param[in] s the size of the new dname + * \param[in] *data pointer to the actual data + * \return ldns_rdf* + */ +ldns_rdf *ldns_dname_new(uint16_t s, void *data); + +/** + * Create a new dname rdf from data (the data is copied) + * \param[in] size the size of the data + * \param[in] *data pointer to the actual data + * \return ldns_rdf* + */ +ldns_rdf *ldns_dname_new_frm_data(uint16_t size, const void *data); + +/** + * Put a dname into canonical fmt - ie. lowercase it + * \param[in] rdf the dname to lowercase + * \return void + */ +void ldns_dname2canonical(const ldns_rdf *rdf); + +/** + * test wether the name sub falls under parent (i.e. is a subdomain + * of parent). This function will return false if the given dnames are + * equal. + * \param[in] sub the name to test + * \param[in] parent the parent's name + * \return true if sub falls under parent, otherwise false + */ +bool ldns_dname_is_subdomain(const ldns_rdf *sub, const ldns_rdf *parent); + +/** + * Compares the two dname rdf's according to the algorithm for ordering + * in RFC4034 Section 6. + * \param[in] dname1 First dname rdf to compare + * \param[in] dname2 Second dname rdf to compare + * \return -1 if dname1 comes before dname2, 1 if dname1 comes after dname2, and 0 if they are equal. + */ +int ldns_dname_compare(const ldns_rdf *dname1, const ldns_rdf *dname2); + +/** + * Checks whether the dname matches the given wildcard + * \param[in] dname The dname to check + * \param[in] wildcard The wildcard to check with + * \return 1 If the wildcard matches, OR if 'wildcard' is not a wildcard and + * the names are *exactly* the same + * 0 If the wildcard does not match, or if it is not a wildcard and + * the names are not the same + */ +int ldns_dname_match_wildcard(const ldns_rdf *dname, const ldns_rdf *wildcard); + +/** + * check if middle lays in the interval defined by prev and next + * prev <= middle < next. This is usefull for nsec checking + * \param[in] prev the previous dname + * \param[in] middle the dname to check + * \param[in] next the next dname + * return 0 on error or unknown, -1 when middle is in the interval, +1 when not + */ +int ldns_dname_interval(const ldns_rdf *prev, const ldns_rdf *middle, const ldns_rdf *next); + +/** + * Checks whether the given dname string is absolute (i.e. ends with a '.') + * \param[in] *dname_str a string representing the dname + * \return true or false + */ +bool ldns_dname_str_absolute(const char *dname_str); + +/** + * look inside the rdf and if it is an LDNS_RDF_TYPE_DNAME + * try and retrieve a specific label. The labels are numbered + * starting from 0 (left most). + * \param[in] rdf the rdf to look in + * \param[in] labelpos return the label with this number + * \return a ldns_rdf* with the label as name or NULL on error + */ +ldns_rdf * ldns_dname_label(const ldns_rdf *rdf, uint8_t labelpos); + +/** + * Check if dname is a wildcard, starts with *. + * \param[in] dname: the rdf to look in + * \return true if a wildcard, false if not. + */ +int ldns_dname_is_wildcard(const ldns_rdf* dname); + +#ifdef __cplusplus +} +#endif + +#endif /* LDNS_DNAME_H */ diff --git a/ldns/dnssec.h b/ldns/dnssec.h new file mode 100644 index 00000000000..9e602b5bc1d --- /dev/null +++ b/ldns/dnssec.h @@ -0,0 +1,522 @@ +/* + * dnssec.h -- defines for the Domain Name System (SEC) (DNSSEC) + * + * Copyright (c) 2005-2008, NLnet Labs. All rights reserved. + * + * See LICENSE for the license. + * + * A bunch of defines that are used in the DNS + */ + +/** + * \file dnssec.h + * + * This module contains base functions for DNSSEC operations + * (RFC4033 t/m RFC4035). + * + * Since those functions heavily rely op cryptographic operations, + * this module is dependent on openssl. + * + */ + + +#ifndef LDNS_DNSSEC_H +#define LDNS_DNSSEC_H + +#include +#if LDNS_BUILD_CONFIG_HAVE_SSL +#include +#include +#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define LDNS_MAX_KEYLEN 2048 +#define LDNS_DNSSEC_KEYPROTO 3 +/* default time before sigs expire */ +#define LDNS_DEFAULT_EXP_TIME 2419200 /* 4 weeks */ + +/** return values for the old-signature callback */ +#define LDNS_SIGNATURE_LEAVE_ADD_NEW 0 +#define LDNS_SIGNATURE_LEAVE_NO_ADD 1 +#define LDNS_SIGNATURE_REMOVE_ADD_NEW 2 +#define LDNS_SIGNATURE_REMOVE_NO_ADD 3 + +/** + * Returns the first RRSIG rr that corresponds to the rrset + * with the given name and type + * + * \param[in] name The dname of the RRset covered by the RRSIG to find + * \param[in] type The type of the RRset covered by the RRSIG to find + * \param[in] rrs List of rrs to search in + * \returns Pointer to the first RRsig ldns_rr found, or NULL if it is + * not present + */ +ldns_rr *ldns_dnssec_get_rrsig_for_name_and_type(const ldns_rdf *name, + const ldns_rr_type type, + const ldns_rr_list *rrs); + +/** + * Returns the DNSKEY that corresponds to the given RRSIG rr from the list, if + * any + * + * \param[in] rrsig The rrsig to find the DNSKEY for + * \param[in] rrs The rr list to find the key in + * \return The DNSKEY that corresponds to the given RRSIG, or NULL if it was + * not found. + */ +ldns_rr *ldns_dnssec_get_dnskey_for_rrsig(const ldns_rr *rrsig, const ldns_rr_list *rrs); + +/** + * Returns the rdata field that contains the bitmap of the covered types of + * the given NSEC record + * + * \param[in] nsec The nsec to get the covered type bitmap of + * \return An ldns_rdf containing the bitmap, or NULL on error + */ +ldns_rdf *ldns_nsec_get_bitmap(ldns_rr *nsec); + + +#define LDNS_NSEC3_MAX_ITERATIONS 65535 + +/** + * Returns the dname of the closest (provable) encloser + */ +ldns_rdf * +ldns_dnssec_nsec3_closest_encloser(ldns_rdf *qname, + ldns_rr_type qtype, + ldns_rr_list *nsec3s); + +/** + * Checks whether the packet contains rrsigs + */ +bool +ldns_dnssec_pkt_has_rrsigs(const ldns_pkt *pkt); + +/** + * Returns a ldns_rr_list containing the signatures covering the given name + * and type + */ +ldns_rr_list *ldns_dnssec_pkt_get_rrsigs_for_name_and_type(const ldns_pkt *pkt, ldns_rdf *name, ldns_rr_type type); + +/** + * Returns a ldns_rr_list containing the signatures covering the given type + */ +ldns_rr_list *ldns_dnssec_pkt_get_rrsigs_for_type(const ldns_pkt *pkt, ldns_rr_type type); + +/** + * calculates a keytag of a key for use in DNSSEC. + * + * \param[in] key the key as an RR to use for the calc. + * \return the keytag + */ +uint16_t ldns_calc_keytag(const ldns_rr *key); + +/** + * Calculates keytag of DNSSEC key, operates on wireformat rdata. + * \param[in] key the key as uncompressed wireformat rdata. + * \param[in] keysize length of key data. + * \return the keytag + */ +uint16_t ldns_calc_keytag_raw(uint8_t* key, size_t keysize); + +#if LDNS_BUILD_CONFIG_HAVE_SSL +/** + * converts a buffer holding key material to a DSA key in openssl. + * + * \param[in] key the key to convert + * \return a DSA * structure with the key material + */ +DSA *ldns_key_buf2dsa(ldns_buffer *key); +/** + * Like ldns_key_buf2dsa, but uses raw buffer. + * \param[in] key the uncompressed wireformat of the key. + * \param[in] len length of key data + * \return a DSA * structure with the key material + */ +DSA *ldns_key_buf2dsa_raw(unsigned char* key, size_t len); + +/** + * Utility function to calculate hash using generic EVP_MD pointer. + * \param[in] data the data to hash. + * \param[in] len length of data. + * \param[out] dest the destination of the hash, must be large enough. + * \param[in] md the message digest to use. + * \return true if worked, false on failure. + */ +int ldns_digest_evp(unsigned char* data, unsigned int len, + unsigned char* dest, const EVP_MD* md); + +/** + * Converts a holding buffer with key material to EVP PKEY in openssl. + * Only available if ldns was compiled with GOST. + * \param[in] key data to convert + * \param[in] keylen length of the key data + * \return the key or NULL on error. + */ +EVP_PKEY* ldns_gost2pkey_raw(unsigned char* key, size_t keylen); + +/** + * Converts a holding buffer with key material to EVP PKEY in openssl. + * Only available if ldns was compiled with ECDSA. + * \param[in] key data to convert + * \param[in] keylen length of the key data + * \param[in] algo precise algorithm to initialize ECC group values. + * \return the key or NULL on error. + */ +EVP_PKEY* ldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo); + +#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ + +#if LDNS_BUILD_CONFIG_HAVE_SSL +/** + * converts a buffer holding key material to a RSA key in openssl. + * + * \param[in] key the key to convert + * \return a RSA * structure with the key material + */ +RSA *ldns_key_buf2rsa(ldns_buffer *key); + +/** + * Like ldns_key_buf2rsa, but uses raw buffer. + * \param[in] key the uncompressed wireformat of the key. + * \param[in] len length of key data + * \return a RSA * structure with the key material + */ +RSA *ldns_key_buf2rsa_raw(unsigned char* key, size_t len); +#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ + +/** + * returns a new DS rr that represents the given key rr. + * + * \param[in] *key the key to convert + * \param[in] h the hash to use LDNS_SHA1/LDNS_SHA256 + * \return ldns_rr* a new rr pointer to a DS + */ +ldns_rr *ldns_key_rr2ds(const ldns_rr *key, ldns_hash h); + +/** + * Create the type bitmap for an NSEC(3) record + */ +ldns_rdf * +ldns_dnssec_create_nsec_bitmap(ldns_rr_type rr_type_list[], + size_t size, + ldns_rr_type nsec_type); + +/** + * returns whether a rrset of the given type is found in the rrsets. + * + * \param[in] rrsets the rrsets to be tested + * \param[in] type the type to test for + * \return int 1 if the type was found, 0 otherwise. + */ +int +ldns_dnssec_rrsets_contains_type (ldns_dnssec_rrsets *rrsets, ldns_rr_type type); + +/** + * Creates NSEC + */ +ldns_rr * +ldns_dnssec_create_nsec(ldns_dnssec_name *from, + ldns_dnssec_name *to, + ldns_rr_type nsec_type); + + +/** + * Creates NSEC3 + */ +ldns_rr * +ldns_dnssec_create_nsec3(ldns_dnssec_name *from, + ldns_dnssec_name *to, + ldns_rdf *zone_name, + uint8_t algorithm, + uint8_t flags, + uint16_t iterations, + uint8_t salt_length, + uint8_t *salt); + +/** + * Create a NSEC record + * \param[in] cur_owner the current owner which should be taken as the starting point + * \param[in] next_owner the rrlist which the nsec rr should point to + * \param[in] rrs all rrs from the zone, to find all RR types of cur_owner in + * \return a ldns_rr with the nsec record in it + */ +ldns_rr * ldns_create_nsec(ldns_rdf *cur_owner, ldns_rdf *next_owner, ldns_rr_list *rrs); + +/** + * Calculates the hashed name using the given parameters + * \param[in] *name The owner name to calculate the hash for + * \param[in] algorithm The hash algorithm to use + * \param[in] iterations The number of hash iterations to use + * \param[in] salt_length The length of the salt in bytes + * \param[in] salt The salt to use + * \return The hashed owner name rdf, without the domain name + */ +ldns_rdf *ldns_nsec3_hash_name(ldns_rdf *name, uint8_t algorithm, uint16_t iterations, uint8_t salt_length, uint8_t *salt); + +/** + * Sets all the NSEC3 options. The rr to set them in must be initialized with _new() and + * type LDNS_RR_TYPE_NSEC3 + * \param[in] *rr The RR to set the values in + * \param[in] algorithm The NSEC3 hash algorithm + * \param[in] flags The flags field + * \param[in] iterations The number of hash iterations + * \param[in] salt_length The length of the salt in bytes + * \param[in] salt The salt bytes + */ +void ldns_nsec3_add_param_rdfs(ldns_rr *rr, + uint8_t algorithm, + uint8_t flags, + uint16_t iterations, + uint8_t salt_length, + uint8_t *salt); + +/* this will NOT return the NSEC3 completed, you will have to run the + finalize function on the rrlist later! */ +ldns_rr * +ldns_create_nsec3(ldns_rdf *cur_owner, + ldns_rdf *cur_zone, + ldns_rr_list *rrs, + uint8_t algorithm, + uint8_t flags, + uint16_t iterations, + uint8_t salt_length, + uint8_t *salt, + bool emptynonterminal); + +/** + * Returns the hash algorithm used in the given NSEC3 RR + * \param[in] *nsec3_rr The RR to read from + * \return The algorithm identifier, or 0 on error + */ +uint8_t ldns_nsec3_algorithm(const ldns_rr *nsec3_rr); + +/** + * Returns flags field + */ +uint8_t +ldns_nsec3_flags(const ldns_rr *nsec3_rr); + +/** + * Returns true if the opt-out flag has been set in the given NSEC3 RR + * \param[in] *nsec3_rr The RR to read from + * \return true if the RR has type NSEC3 and the opt-out bit has been set, false otherwise + */ +bool ldns_nsec3_optout(const ldns_rr *nsec3_rr); + +/** + * Returns the number of hash iterations used in the given NSEC3 RR + * \param[in] *nsec3_rr The RR to read from + * \return The number of iterations + */ +uint16_t ldns_nsec3_iterations(const ldns_rr *nsec3_rr); + +/** + * Returns the salt used in the given NSEC3 RR + * \param[in] *nsec3_rr The RR to read from + * \return The salt rdf, or NULL on error + */ +ldns_rdf *ldns_nsec3_salt(const ldns_rr *nsec3_rr); + +/** + * Returns the length of the salt used in the given NSEC3 RR + * \param[in] *nsec3_rr The RR to read from + * \return The length of the salt in bytes + */ +uint8_t ldns_nsec3_salt_length(const ldns_rr *nsec3_rr); + +/** + * Returns the salt bytes used in the given NSEC3 RR + * \param[in] *nsec3_rr The RR to read from + * \return The salt in bytes, this is alloced, so you need to free it + */ +uint8_t *ldns_nsec3_salt_data(const ldns_rr *nsec3_rr); + +/** + * Returns the first label of the next ownername in the NSEC3 chain (ie. without the domain) + * \param[in] nsec3_rr The RR to read from + * \return The first label of the next owner name in the NSEC3 chain, or NULL on error + */ +ldns_rdf *ldns_nsec3_next_owner(const ldns_rr *nsec3_rr); + +/** + * Returns the bitmap specifying the covered types of the given NSEC3 RR + * \param[in] *nsec3_rr The RR to read from + * \return The covered type bitmap rdf + */ +ldns_rdf *ldns_nsec3_bitmap(const ldns_rr *nsec3_rr); + +/** + * Calculates the hashed name using the parameters of the given NSEC3 RR + * \param[in] *nsec The RR to use the parameters from + * \param[in] *name The owner name to calculate the hash for + * \return The hashed owner name rdf, without the domain name + */ +ldns_rdf *ldns_nsec3_hash_name_frm_nsec3(const ldns_rr *nsec, ldns_rdf *name); + +/** + * Checks coverage of NSEC RR type bitmap + * \param[in] nsec_bitmap The NSEC bitmap rdata field to check + * \param[in] type The type to check + * \return true if the NSEC RR covers the type + */ +bool ldns_nsec_bitmap_covers_type(const ldns_rdf *nsec_bitmap, ldns_rr_type type); + +/** + * Checks coverage of NSEC(3) RR name span + * Remember that nsec and name must both be in canonical form (ie use + * \ref ldns_rr2canonical and \ref ldns_dname2canonical prior to calling this + * function) + * + * \param[in] nsec The NSEC RR to check + * \param[in] name The owner dname to check, if the nsec record is a NSEC3 record, this should be the hashed name + * \return true if the NSEC RR covers the owner name + */ +bool ldns_nsec_covers_name(const ldns_rr *nsec, const ldns_rdf *name); + +#if LDNS_BUILD_CONFIG_HAVE_SSL +/** + * verify a packet + * \param[in] p the packet + * \param[in] t the rr set type to check + * \param[in] o the rr set name to check + * \param[in] k list of keys + * \param[in] s list of sigs (may be null) + * \param[out] good_keys keys which validated the packet + * \return status + * + */ +ldns_status ldns_pkt_verify(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o, ldns_rr_list *k, ldns_rr_list *s, ldns_rr_list *good_keys); + +/** + * verify a packet + * \param[in] p the packet + * \param[in] t the rr set type to check + * \param[in] o the rr set name to check + * \param[in] k list of keys + * \param[in] s list of sigs (may be null) + * \param[in] check_time the time for which the validation is performed + * \param[out] good_keys keys which validated the packet + * \return status + * + */ +ldns_status ldns_pkt_verify_time(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o, ldns_rr_list *k, ldns_rr_list *s, time_t check_time, ldns_rr_list *good_keys); + +#endif + +/** + * chains nsec3 list + */ +ldns_status +ldns_dnssec_chain_nsec3_list(ldns_rr_list *nsec3_rrs); + +/** + * compare for nsec3 sort + */ +int +qsort_rr_compare_nsec3(const void *a, const void *b); + +/** + * sort nsec3 list + */ +void +ldns_rr_list_sort_nsec3(ldns_rr_list *unsorted); + +/** + * Default callback function to always leave present signatures, and + * add new ones + * \param[in] sig The signature to check for removal (unused) + * \param[in] n Optional argument (unused) + * \return LDNS_SIGNATURE_LEAVE_ADD_NEW + */ +int ldns_dnssec_default_add_to_signatures(ldns_rr *sig, void *n); +/** + * Default callback function to always leave present signatures, and + * add no new ones for the keys of these signatures + * \param[in] sig The signature to check for removal (unused) + * \param[in] n Optional argument (unused) + * \return LDNS_SIGNATURE_LEAVE_NO_ADD + */ +int ldns_dnssec_default_leave_signatures(ldns_rr *sig, void *n); +/** + * Default callback function to always remove present signatures, but + * add no new ones + * \param[in] sig The signature to check for removal (unused) + * \param[in] n Optional argument (unused) + * \return LDNS_SIGNATURE_REMOVE_NO_ADD + */ +int ldns_dnssec_default_delete_signatures(ldns_rr *sig, void *n); +/** + * Default callback function to always leave present signatures, and + * add new ones + * \param[in] sig The signature to check for removal (unused) + * \param[in] n Optional argument (unused) + * \return LDNS_SIGNATURE_REMOVE_ADD_NEW + */ +int ldns_dnssec_default_replace_signatures(ldns_rr *sig, void *n); + +#if LDNS_BUILD_CONFIG_HAVE_SSL +/** + * Converts the DSA signature from ASN1 representation (RFC2459, as + * used by OpenSSL) to raw signature data as used in DNS (rfc2536) + * + * \param[in] sig The signature in RFC2459 format + * \param[in] sig_len The length of the signature + * \return a new rdf with the signature + */ +ldns_rdf * +ldns_convert_dsa_rrsig_asn12rdf(const ldns_buffer *sig, + const long sig_len); + +/** + * Converts the RRSIG signature RDF (in rfc2536 format) to a buffer + * with the signature in rfc2459 format + * + * \param[out] target_buffer buffer to place the signature data + * \param[in] sig_rdf The signature rdf to convert + * \return LDNS_STATUS_OK on success, error code otherwise + */ +ldns_status +ldns_convert_dsa_rrsig_rdf2asn1(ldns_buffer *target_buffer, + const ldns_rdf *sig_rdf); + +/** + * Converts the ECDSA signature from ASN1 representation (as + * used by OpenSSL) to raw signature data as used in DNS + * This routine is only present if ldns is compiled with ecdsa support. + * + * \param[in] sig The signature in ASN1 format + * \param[in] sig_len The length of the signature + * \return a new rdf with the signature + */ +ldns_rdf * +ldns_convert_ecdsa_rrsig_asn12rdf(const ldns_buffer *sig, const long sig_len); + +/** + * Converts the RRSIG signature RDF (from DNS) to a buffer with the + * signature in ASN1 format as openssl uses it. + * This routine is only present if ldns is compiled with ecdsa support. + * + * \param[out] target_buffer buffer to place the signature data in ASN1. + * \param[in] sig_rdf The signature rdf to convert + * \return LDNS_STATUS_OK on success, error code otherwise + */ +ldns_status +ldns_convert_ecdsa_rrsig_rdf2asn1(ldns_buffer *target_buffer, + const ldns_rdf *sig_rdf); + +#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ + +#ifdef __cplusplus +} +#endif + +#endif /* LDNS_DNSSEC_H */ diff --git a/ldns/dnssec_sign.h b/ldns/dnssec_sign.h new file mode 100644 index 00000000000..e77cb6959df --- /dev/null +++ b/ldns/dnssec_sign.h @@ -0,0 +1,383 @@ +/** dnssec_verify */ + +#ifndef LDNS_DNSSEC_SIGN_H +#define LDNS_DNSSEC_SIGN_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* sign functions */ + +/** Sign flag that makes DNSKEY type signed by all keys, not only by SEP keys*/ +#define LDNS_SIGN_DNSKEY_WITH_ZSK 1 + +/** + * Create an empty RRSIG RR (i.e. without the actual signature data) + * \param[in] rrset The RRset to create the signature for + * \param[in] key The key that will create the signature + * \return signature rr + */ +ldns_rr * +ldns_create_empty_rrsig(ldns_rr_list *rrset, + ldns_key *key); + +/** + * Sign the buffer which contains the wiredata of an rrset, and the + * corresponding empty rrsig rr with the given key + * \param[in] sign_buf the buffer with data to sign + * \param[in] key the key to sign with + * \return an rdata field with the signature data + */ +ldns_rdf * +ldns_sign_public_buffer(ldns_buffer *sign_buf, ldns_key *key); + +/** + * Sign an rrset + * \param[in] rrset the rrset + * \param[in] keys the keys to use + * \return a rr_list with the signatures + */ +ldns_rr_list *ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys); + +#if LDNS_BUILD_CONFIG_HAVE_SSL +/** + * Sign a buffer with the DSA key (hash with SHA1) + * \param[in] to_sign buffer with the data + * \param[in] key the key to use + * \return a ldns_rdf with the signed data + */ +ldns_rdf *ldns_sign_public_dsa(ldns_buffer *to_sign, DSA *key); + +/** + * Sign data with EVP (general method for different algorithms) + * + * \param[in] to_sign The ldns_buffer containing raw data that is + * to be signed + * \param[in] key The EVP_PKEY key structure to sign with + * \param[in] digest_type The digest algorithm to use in the creation of + * the signature + * \return ldns_rdf for the RRSIG ldns_rr + */ +ldns_rdf *ldns_sign_public_evp(ldns_buffer *to_sign, + EVP_PKEY *key, + const EVP_MD *digest_type); + +/** + * Sign a buffer with the RSA key (hash with SHA1) + * \param[in] to_sign buffer with the data + * \param[in] key the key to use + * \return a ldns_rdf with the signed data + */ +ldns_rdf *ldns_sign_public_rsasha1(ldns_buffer *to_sign, RSA *key); + +/** + * Sign a buffer with the RSA key (hash with MD5) + * \param[in] to_sign buffer with the data + * \param[in] key the key to use + * \return a ldns_rdf with the signed data + */ +ldns_rdf *ldns_sign_public_rsamd5(ldns_buffer *to_sign, RSA *key); +#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ + +/** + * Marks the names in the zone that are occluded. Those names will be skipped + * when walking the tree with the ldns_dnssec_name_node_next_nonglue() + * function. But watch out! Names that are partially occluded (like glue with + * the same name as the delegation) will not be marked and should specifically + * be taken into account seperately. + * + * When glue_list is given (not NULL), in the process of marking the names, all + * glue resource records will be pushed to that list, even glue at the delegation name. + * + * \param[in] zone the zone in which to mark the names + * \param[in] glue_list the list to which to push the glue rrs + * \return LDNS_STATUS_OK on success, an error code otherwise + */ +ldns_status +ldns_dnssec_zone_mark_and_get_glue( + ldns_dnssec_zone *zone, ldns_rr_list *glue_list); + +/** + * Marks the names in the zone that are occluded. Those names will be skipped + * when walking the tree with the ldns_dnssec_name_node_next_nonglue() + * function. But watch out! Names that are partially occluded (like glue with + * the same name as the delegation) will not be marked and should specifically + * be taken into account seperately. + * + * \param[in] zone the zone in which to mark the names + * \return LDNS_STATUS_OK on succesful completion + */ +ldns_status +ldns_dnssec_zone_mark_glue(ldns_dnssec_zone *zone); + +/** + * Finds the first dnssec_name node in the rbtree that is not occluded. + * It *does* return names that are partially occluded. + * + * \param[in] node the first node to check + * \return the first node that has not been marked as glue, or NULL + * if not found (TODO: make that LDNS_RBTREE_NULL?) + */ +ldns_rbnode_t *ldns_dnssec_name_node_next_nonglue(ldns_rbnode_t *node); + +/** + * Adds NSEC records to the given dnssec_zone + * + * \param[in] zone the zone to add the records to + * \param[in] new_rrs ldns_rr's created by this function are + * added to this rr list, so the caller can free them later + * \return LDNS_STATUS_OK on success, an error code otherwise + */ +ldns_status ldns_dnssec_zone_create_nsecs(ldns_dnssec_zone *zone, + ldns_rr_list *new_rrs); + +/** + * Adds NSEC3 records to the zone + */ +ldns_status +ldns_dnssec_zone_create_nsec3s(ldns_dnssec_zone *zone, + ldns_rr_list *new_rrs, + uint8_t algorithm, + uint8_t flags, + uint16_t iterations, + uint8_t salt_length, + uint8_t *salt); + +/** + * remove signatures if callback function tells to + * + * \param[in] signatures list of signatures to check, and + * possibly remove, depending on the value of the + * callback + * \param[in] key_list these are marked to be used or not, + * on the return value of the callback + * \param[in] func this function is called to specify what to + * do with each signature (and corresponding key) + * \param[in] arg Optional argument for the callback function + * \returns pointer to the new signatures rrs (the original + * passed to this function may have been removed) + */ +ldns_dnssec_rrs *ldns_dnssec_remove_signatures(ldns_dnssec_rrs *signatures, + ldns_key_list *key_list, + int (*func)(ldns_rr *, void *), + void *arg); + +/** + * Adds signatures to the zone + * + * \param[in] zone the zone to add RRSIG Resource Records to + * \param[in] new_rrs the RRSIG RRs that are created are also + * added to this list, so the caller can free them + * later + * \param[in] key_list list of keys to sign with. + * \param[in] func Callback function to decide what keys to + * use and what to do with old signatures + * \param[in] arg Optional argument for the callback function + * \param[in] flags option flags for signing process. 0 makes DNSKEY + * RRset signed with the minimal key set, that is only SEP keys are used + * for signing. If there are no SEP keys available, non-SEP keys will + * be used. LDNS_SIGN_DNSKEY_WITH_ZSK makes DNSKEY type signed with all + * keys. 0 is the default. + * \return LDNS_STATUS_OK on success, error otherwise + */ +ldns_status ldns_dnssec_zone_create_rrsigs_flg(ldns_dnssec_zone *zone, + ldns_rr_list *new_rrs, + ldns_key_list *key_list, + int (*func)(ldns_rr *, void*), + void *arg, + int flags); + +/** + * Adds signatures to the zone + * + * \param[in] zone the zone to add RRSIG Resource Records to + * \param[in] new_rrs the RRSIG RRs that are created are also + * added to this list, so the caller can free them + * later + * \param[in] key_list list of keys to sign with. + * \param[in] func Callback function to decide what keys to + * use and what to do with old signatures + * \param[in] arg Optional argument for the callback function + * \return LDNS_STATUS_OK on success, error otherwise + */ +ldns_status ldns_dnssec_zone_create_rrsigs(ldns_dnssec_zone *zone, + ldns_rr_list *new_rrs, + ldns_key_list *key_list, + int (*func)(ldns_rr *, void*), + void *arg); + +/** + * signs the given zone with the given keys + * + * \param[in] zone the zone to sign + * \param[in] key_list the list of keys to sign the zone with + * \param[in] new_rrs newly created resource records are added to this list, to free them later + * \param[in] func callback function that decides what to do with old signatures + * This function takes an ldns_rr* and an optional void *arg argument, and returns one of four values: + * LDNS_SIGNATURE_LEAVE_ADD_NEW: + * leave the signature and add a new one for the corresponding key + * LDNS_SIGNATURE_REMOVE_ADD_NEW: + * remove the signature and replace is with a new one from the same key + * LDNS_SIGNATURE_LEAVE_NO_ADD: + * leave the signature and do not add a new one with the corresponding key + * LDNS_SIGNATURE_REMOVE_NO_ADD: + * remove the signature and do not replace + * + * \param[in] arg optional argument for the callback function + * \param[in] flags option flags for signing process. 0 makes DNSKEY + * RRset signed with the minimal key set, that is only SEP keys are used + * for signing. If there are no SEP keys available, non-SEP keys will + * be used. LDNS_SIGN_DNSKEY_WITH_ZSK makes DNSKEY type signed with all + * keys. 0 is the default. + * \return LDNS_STATUS_OK on success, an error code otherwise + */ +ldns_status ldns_dnssec_zone_sign_flg(ldns_dnssec_zone *zone, + ldns_rr_list *new_rrs, + ldns_key_list *key_list, + int (*func)(ldns_rr *, void *), + void *arg, + int flags); + +/** + * signs the given zone with the given new zone, with NSEC3 + * + * \param[in] zone the zone to sign + * \param[in] key_list the list of keys to sign the zone with + * \param[in] new_rrs newly created resource records are added to this list, to free them later + * \param[in] func callback function that decides what to do with old signatures + * \param[in] arg optional argument for the callback function + * \param[in] algorithm the NSEC3 hashing algorithm to use + * \param[in] flags NSEC3 flags + * \param[in] iterations the number of NSEC3 hash iterations to use + * \param[in] salt_length the length (in octets) of the NSEC3 salt + * \param[in] salt the NSEC3 salt data + * \param[in] signflags option flags for signing process. 0 is the default. + * \return LDNS_STATUS_OK on success, an error code otherwise + */ +ldns_status ldns_dnssec_zone_sign_nsec3_flg(ldns_dnssec_zone *zone, + ldns_rr_list *new_rrs, + ldns_key_list *key_list, + int (*func)(ldns_rr *, void *), + void *arg, + uint8_t algorithm, + uint8_t flags, + uint16_t iterations, + uint8_t salt_length, + uint8_t *salt, + int signflags); + +/** + * signs the given zone with the given new zone, with NSEC3 + * + * \param[in] zone the zone to sign + * \param[in] key_list the list of keys to sign the zone with + * \param[in] new_rrs newly created resource records are added to this list, to free them later + * \param[in] func callback function that decides what to do with old signatures + * \param[in] arg optional argument for the callback function + * \param[in] algorithm the NSEC3 hashing algorithm to use + * \param[in] flags NSEC3 flags + * \param[in] iterations the number of NSEC3 hash iterations to use + * \param[in] salt_length the length (in octets) of the NSEC3 salt + * \param[in] salt the NSEC3 salt data + * \param[in] signflags option flags for signing process. 0 is the default. + * \param[out] map a referenced rbtree pointer variable. The newly created + * rbtree will contain mappings from hashed owner names to the + * unhashed name. + * \return LDNS_STATUS_OK on success, an error code otherwise + */ +ldns_status ldns_dnssec_zone_sign_nsec3_flg_mkmap(ldns_dnssec_zone *zone, + ldns_rr_list *new_rrs, + ldns_key_list *key_list, + int (*func)(ldns_rr *, void *), + void *arg, + uint8_t algorithm, + uint8_t flags, + uint16_t iterations, + uint8_t salt_length, + uint8_t *salt, + int signflags, + ldns_rbtree_t **map + ); + + +/** + * signs the given zone with the given keys + * + * \param[in] zone the zone to sign + * \param[in] key_list the list of keys to sign the zone with + * \param[in] new_rrs newly created resource records are added to this list, to free them later + * \param[in] func callback function that decides what to do with old signatures + * This function takes an ldns_rr* and an optional void *arg argument, and returns one of four values: + * LDNS_SIGNATURE_LEAVE_ADD_NEW: + * leave the signature and add a new one for the corresponding key + * LDNS_SIGNATURE_REMOVE_ADD_NEW: + * remove the signature and replace is with a new one from the same key + * LDNS_SIGNATURE_LEAVE_NO_ADD: + * leave the signature and do not add a new one with the corresponding key + * LDNS_SIGNATURE_REMOVE_NO_ADD: + * remove the signature and do not replace + * + * \param[in] arg optional argument for the callback function + * \return LDNS_STATUS_OK on success, an error code otherwise + */ +ldns_status ldns_dnssec_zone_sign(ldns_dnssec_zone *zone, + ldns_rr_list *new_rrs, + ldns_key_list *key_list, + int (*func)(ldns_rr *, void *), + void *arg); + +/** + * signs the given zone with the given new zone, with NSEC3 + * + * \param[in] zone the zone to sign + * \param[in] key_list the list of keys to sign the zone with + * \param[in] new_rrs newly created resource records are added to this list, to free them later + * \param[in] func callback function that decides what to do with old signatures + * \param[in] arg optional argument for the callback function + * \param[in] algorithm the NSEC3 hashing algorithm to use + * \param[in] flags NSEC3 flags + * \param[in] iterations the number of NSEC3 hash iterations to use + * \param[in] salt_length the length (in octets) of the NSEC3 salt + * \param[in] salt the NSEC3 salt data + * \return LDNS_STATUS_OK on success, an error code otherwise + */ +ldns_status ldns_dnssec_zone_sign_nsec3(ldns_dnssec_zone *zone, + ldns_rr_list *new_rrs, + ldns_key_list *key_list, + int (*func)(ldns_rr *, void *), + void *arg, + uint8_t algorithm, + uint8_t flags, + uint16_t iterations, + uint8_t salt_length, + uint8_t *salt); + +/** + * Signs the zone, and returns a newly allocated signed zone + * \param[in] zone the zone to sign + * \param[in] key_list list of keys to sign with + * \return signed zone + */ +ldns_zone *ldns_zone_sign(const ldns_zone *zone, ldns_key_list *key_list); + +/** + * Signs the zone with NSEC3, and returns a newly allocated signed zone + * \param[in] zone the zone to sign + * \param[in] key_list list of keys to sign with + * \param[in] algorithm the NSEC3 hashing algorithm to use + * \param[in] flags NSEC3 flags + * \param[in] iterations the number of NSEC3 hash iterations to use + * \param[in] salt_length the length (in octets) of the NSEC3 salt + * \param[in] salt the NSEC3 salt data + * \return signed zone + */ +ldns_zone *ldns_zone_sign_nsec3(ldns_zone *zone, ldns_key_list *key_list, uint8_t algorithm, uint8_t flags, uint16_t iterations, uint8_t salt_length, uint8_t *salt); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ldns/dnssec_verify.h b/ldns/dnssec_verify.h new file mode 100644 index 00000000000..32036a8c0b0 --- /dev/null +++ b/ldns/dnssec_verify.h @@ -0,0 +1,873 @@ +/** dnssec_verify */ + +#ifndef LDNS_DNSSEC_VERIFY_H +#define LDNS_DNSSEC_VERIFY_H + +#define LDNS_DNSSEC_TRUST_TREE_MAX_PARENTS 10 + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Chain structure that contains all DNSSEC data needed to + * verify an rrset + */ +typedef struct ldns_dnssec_data_chain_struct ldns_dnssec_data_chain; +struct ldns_dnssec_data_chain_struct +{ + ldns_rr_list *rrset; + ldns_rr_list *signatures; + ldns_rr_type parent_type; + ldns_dnssec_data_chain *parent; + ldns_pkt_rcode packet_rcode; + ldns_rr_type packet_qtype; + bool packet_nodata; +}; + +/** + * Creates a new dnssec_chain structure + * \return ldns_dnssec_data_chain * + */ +ldns_dnssec_data_chain *ldns_dnssec_data_chain_new(); + +/** + * Frees a dnssec_data_chain structure + * + * \param[in] *chain The chain to free + */ +void ldns_dnssec_data_chain_free(ldns_dnssec_data_chain *chain); + +/** + * Frees a dnssec_data_chain structure, and all data + * contained therein + * + * \param[in] *chain The dnssec_data_chain to free + */ +void ldns_dnssec_data_chain_deep_free(ldns_dnssec_data_chain *chain); + +/** + * Prints the dnssec_data_chain to the given file stream + * + * \param[in] *out The file stream to print to + * \param[in] *chain The dnssec_data_chain to print + */ +void ldns_dnssec_data_chain_print(FILE *out, const ldns_dnssec_data_chain *chain); + +/** + * Prints the dnssec_data_chain to the given file stream + * + * \param[in] *out The file stream to print to + * \param[in] *fmt The format of the textual representation + * \param[in] *chain The dnssec_data_chain to print + */ +void ldns_dnssec_data_chain_print_fmt(FILE *out, + const ldns_output_format *fmt, + const ldns_dnssec_data_chain *chain); + +/** + * Build an ldns_dnssec_data_chain, which contains all + * DNSSEC data that is needed to derive the trust tree later + * + * The data_set will be cloned + * + * \param[in] *res resolver structure for further needed queries + * \param[in] qflags resolution flags + * \param[in] *data_set The original rrset where the chain ends + * \param[in] *pkt optional, can contain the original packet + * (and hence the sigs and maybe the key) + * \param[in] *orig_rr The original Resource Record + * + * \return the DNSSEC data chain + */ +ldns_dnssec_data_chain *ldns_dnssec_build_data_chain(ldns_resolver *res, + const uint16_t qflags, + const ldns_rr_list *data_set, + const ldns_pkt *pkt, + ldns_rr *orig_rr); + +/** + * Tree structure that contains the relation of DNSSEC data, + * and their cryptographic status. + * + * This tree is derived from a data_chain, and can be used + * to look whether there is a connection between an RRSET + * and a trusted key. The tree only contains pointers to the + * data_chain, and therefore one should *never* free() the + * data_chain when there is still a trust tree derived from + * that chain. + * + * Example tree: + * key key key + * \ | / + * \ | / + * \ | / + * ds + * | + * key + * | + * key + * | + * rr + * + * For each signature there is a parent; if the parent + * pointer is null, it couldn't be found and there was no + * denial; otherwise is a tree which contains either a + * DNSKEY, a DS, or a NSEC rr + */ +typedef struct ldns_dnssec_trust_tree_struct ldns_dnssec_trust_tree; +struct ldns_dnssec_trust_tree_struct +{ + ldns_rr *rr; + /* the complete rrset this rr was in */ + ldns_rr_list *rrset; + ldns_dnssec_trust_tree *parents[LDNS_DNSSEC_TRUST_TREE_MAX_PARENTS]; + ldns_status parent_status[LDNS_DNSSEC_TRUST_TREE_MAX_PARENTS]; + /** for debugging, add signatures too (you might want + those if they contain errors) */ + ldns_rr *parent_signature[LDNS_DNSSEC_TRUST_TREE_MAX_PARENTS]; + size_t parent_count; +}; + +/** + * Creates a new (empty) dnssec_trust_tree structure + * + * \return ldns_dnssec_trust_tree * + */ +ldns_dnssec_trust_tree *ldns_dnssec_trust_tree_new(); + +/** + * Frees the dnssec_trust_tree recursively + * + * There is no deep free; all data in the trust tree + * consists of pointers to a data_chain + * + * \param[in] tree The tree to free + */ +void ldns_dnssec_trust_tree_free(ldns_dnssec_trust_tree *tree); + +/** + * returns the depth of the trust tree + * + * \param[in] tree tree to calculate the depth of + * \return The depth of the tree + */ +size_t ldns_dnssec_trust_tree_depth(ldns_dnssec_trust_tree *tree); + +/** + * Prints the dnssec_trust_tree structure to the given file + * stream. + * + * If a link status is not LDNS_STATUS_OK; the status and + * relevant signatures are printed too + * + * \param[in] *out The file stream to print to + * \param[in] tree The trust tree to print + * \param[in] tabs Prepend each line with tabs*2 spaces + * \param[in] extended If true, add little explanation lines to the output + */ +void ldns_dnssec_trust_tree_print(FILE *out, + ldns_dnssec_trust_tree *tree, + size_t tabs, + bool extended); + +/** + * Prints the dnssec_trust_tree structure to the given file + * stream. + * + * If a link status is not LDNS_STATUS_OK; the status and + * relevant signatures are printed too + * + * \param[in] *out The file stream to print to + * \param[in] *fmt The format of the textual representation + * \param[in] tree The trust tree to print + * \param[in] tabs Prepend each line with tabs*2 spaces + * \param[in] extended If true, add little explanation lines to the output + */ +void ldns_dnssec_trust_tree_print_fmt(FILE *out, + const ldns_output_format *fmt, + ldns_dnssec_trust_tree *tree, + size_t tabs, + bool extended); + +/** + * Adds a trust tree as a parent for the given trust tree + * + * \param[in] *tree The tree to add the parent to + * \param[in] *parent The parent tree to add + * \param[in] *parent_signature The RRSIG relevant to this parent/child + * connection + * \param[in] parent_status The DNSSEC status for this parent, child and RRSIG + * \return LDNS_STATUS_OK if the addition succeeds, error otherwise + */ +ldns_status ldns_dnssec_trust_tree_add_parent(ldns_dnssec_trust_tree *tree, + const ldns_dnssec_trust_tree *parent, + const ldns_rr *parent_signature, + const ldns_status parent_status); + +/** + * Generates a dnssec_trust_tree for the given rr from the + * given data_chain + * + * This does not clone the actual data; Don't free the + * data_chain before you are done with this tree + * + * \param[in] *data_chain The chain to derive the trust tree from + * \param[in] *rr The RR this tree will be about + * \return ldns_dnssec_trust_tree * + */ +ldns_dnssec_trust_tree *ldns_dnssec_derive_trust_tree( + ldns_dnssec_data_chain *data_chain, + ldns_rr *rr); + +/** + * Generates a dnssec_trust_tree for the given rr from the + * given data_chain + * + * This does not clone the actual data; Don't free the + * data_chain before you are done with this tree + * + * \param[in] *data_chain The chain to derive the trust tree from + * \param[in] *rr The RR this tree will be about + * \param[in] check_time the time for which the validation is performed + * \return ldns_dnssec_trust_tree * + */ +ldns_dnssec_trust_tree *ldns_dnssec_derive_trust_tree_time( + ldns_dnssec_data_chain *data_chain, + ldns_rr *rr, time_t check_time); + +/** + * Sub function for derive_trust_tree that is used for a 'normal' rrset + * + * \param[in] new_tree The trust tree that we are building + * \param[in] data_chain The data chain containing the data for the trust tree + * \param[in] cur_sig_rr The currently relevant signature + */ +void ldns_dnssec_derive_trust_tree_normal_rrset( + ldns_dnssec_trust_tree *new_tree, + ldns_dnssec_data_chain *data_chain, + ldns_rr *cur_sig_rr); + +/** + * Sub function for derive_trust_tree that is used for a 'normal' rrset + * + * \param[in] new_tree The trust tree that we are building + * \param[in] data_chain The data chain containing the data for the trust tree + * \param[in] cur_sig_rr The currently relevant signature + * \param[in] check_time the time for which the validation is performed + */ +void ldns_dnssec_derive_trust_tree_normal_rrset_time( + ldns_dnssec_trust_tree *new_tree, + ldns_dnssec_data_chain *data_chain, + ldns_rr *cur_sig_rr, time_t check_time); + + +/** + * Sub function for derive_trust_tree that is used for DNSKEY rrsets + * + * \param[in] new_tree The trust tree that we are building + * \param[in] data_chain The data chain containing the data for the trust tree + * \param[in] cur_rr The currently relevant DNSKEY RR + * \param[in] cur_sig_rr The currently relevant signature + */ +void ldns_dnssec_derive_trust_tree_dnskey_rrset( + ldns_dnssec_trust_tree *new_tree, + ldns_dnssec_data_chain *data_chain, + ldns_rr *cur_rr, + ldns_rr *cur_sig_rr); + +/** + * Sub function for derive_trust_tree that is used for DNSKEY rrsets + * + * \param[in] new_tree The trust tree that we are building + * \param[in] data_chain The data chain containing the data for the trust tree + * \param[in] cur_rr The currently relevant DNSKEY RR + * \param[in] cur_sig_rr The currently relevant signature + * \param[in] check_time the time for which the validation is performed + */ +void ldns_dnssec_derive_trust_tree_dnskey_rrset_time( + ldns_dnssec_trust_tree *new_tree, + ldns_dnssec_data_chain *data_chain, + ldns_rr *cur_rr, ldns_rr *cur_sig_rr, + time_t check_time); + + +/** + * Sub function for derive_trust_tree that is used for DNSKEY rrsets + * + * \param[in] new_tree The trust tree that we are building + * \param[in] data_chain The data chain containing the data for the trust tree + * \param[in] cur_rr The currently relevant DNSKEY RR + * \param[in] cur_sig_rr The currently relevant signature + * \param[in] check_time the time for which the validation is performed + */ +void ldns_dnssec_derive_trust_tree_dnskey_rrset_time( + ldns_dnssec_trust_tree *new_tree, + ldns_dnssec_data_chain *data_chain, + ldns_rr *cur_rr, ldns_rr *cur_sig_rr, + time_t check_time); + + +/** + * Sub function for derive_trust_tree that is used for DS rrsets + * + * \param[in] new_tree The trust tree that we are building + * \param[in] data_chain The data chain containing the data for the trust tree + * \param[in] cur_rr The currently relevant DS RR + */ +void ldns_dnssec_derive_trust_tree_ds_rrset( + ldns_dnssec_trust_tree *new_tree, + ldns_dnssec_data_chain *data_chain, + ldns_rr *cur_rr); + +/** + * Sub function for derive_trust_tree that is used for DS rrsets + * + * \param[in] new_tree The trust tree that we are building + * \param[in] data_chain The data chain containing the data for the trust tree + * \param[in] cur_rr The currently relevant DS RR + * \param[in] check_time the time for which the validation is performed + */ +void ldns_dnssec_derive_trust_tree_ds_rrset_time( + ldns_dnssec_trust_tree *new_tree, + ldns_dnssec_data_chain *data_chain, + ldns_rr *cur_rr, time_t check_time); + +/** + * Sub function for derive_trust_tree that is used when there are no + * signatures + * + * \param[in] new_tree The trust tree that we are building + * \param[in] data_chain The data chain containing the data for the trust tree + */ +void ldns_dnssec_derive_trust_tree_no_sig( + ldns_dnssec_trust_tree *new_tree, + ldns_dnssec_data_chain *data_chain); + +/** + * Sub function for derive_trust_tree that is used when there are no + * signatures + * + * \param[in] new_tree The trust tree that we are building + * \param[in] data_chain The data chain containing the data for the trust tree + * \param[in] check_time the time for which the validation is performed + */ +void ldns_dnssec_derive_trust_tree_no_sig_time( + ldns_dnssec_trust_tree *new_tree, + ldns_dnssec_data_chain *data_chain, + time_t check_time); + + +/** + * Returns OK if there is a trusted path in the tree to one of + * the DNSKEY or DS RRs in the given list + * + * \param *tree The trust tree so search + * \param *keys A ldns_rr_list of DNSKEY and DS rrs to look for + * \return LDNS_STATUS_OK if there is a trusted path to one of + * the keys, or the *first* error encountered + * if there were no paths + */ +ldns_status ldns_dnssec_trust_tree_contains_keys( + ldns_dnssec_trust_tree *tree, + ldns_rr_list *keys); + +/** + * Verifies a list of signatures for one rrset. + * + * \param[in] rrset the rrset to verify + * \param[in] rrsig a list of signatures to check + * \param[in] keys a list of keys to check with + * \param[out] good_keys if this is a (initialized) list, the pointer to keys + * from keys that validate one of the signatures + * are added to it + * \return status LDNS_STATUS_OK if there is at least one correct key + */ +ldns_status ldns_verify(ldns_rr_list *rrset, + ldns_rr_list *rrsig, + const ldns_rr_list *keys, + ldns_rr_list *good_keys); + +/** + * Verifies a list of signatures for one rrset. + * + * \param[in] rrset the rrset to verify + * \param[in] rrsig a list of signatures to check + * \param[in] keys a list of keys to check with + * \param[in] check_time the time for which the validation is performed + * \param[out] good_keys if this is a (initialized) list, the pointer to keys + * from keys that validate one of the signatures + * are added to it + * \return status LDNS_STATUS_OK if there is at least one correct key + */ +ldns_status ldns_verify_time(ldns_rr_list *rrset, + ldns_rr_list *rrsig, + const ldns_rr_list *keys, + time_t check_time, + ldns_rr_list *good_keys); + + +/** + * Verifies a list of signatures for one rrset, but disregard the time. + * Inception and Expiration are not checked. + * + * \param[in] rrset the rrset to verify + * \param[in] rrsig a list of signatures to check + * \param[in] keys a list of keys to check with + * \param[out] good_keys if this is a (initialized) list, the pointer to keys + * from keys that validate one of the signatures + * are added to it + * \return status LDNS_STATUS_OK if there is at least one correct key + */ +ldns_status ldns_verify_notime(ldns_rr_list *rrset, + ldns_rr_list *rrsig, + const ldns_rr_list *keys, + ldns_rr_list *good_keys); + +/** + * Tries to build an authentication chain from the given + * keys down to the queried domain. + * + * If we find a valid trust path, return the valid keys for the domain. + * + * \param[in] res the current resolver + * \param[in] domain the domain we want valid keys for + * \param[in] keys the current set of trusted keys + * \param[out] status pointer to the status variable where the result + * code will be stored + * \return the set of trusted keys for the domain, or NULL if no + * trust path could be built. + */ +ldns_rr_list *ldns_fetch_valid_domain_keys(const ldns_resolver * res, + const ldns_rdf * domain, + const ldns_rr_list * keys, + ldns_status *status); + +/** + * Tries to build an authentication chain from the given + * keys down to the queried domain. + * + * If we find a valid trust path, return the valid keys for the domain. + * + * \param[in] res the current resolver + * \param[in] domain the domain we want valid keys for + * \param[in] keys the current set of trusted keys + * \param[in] check_time the time for which the validation is performed + * \param[out] status pointer to the status variable where the result + * code will be stored + * \return the set of trusted keys for the domain, or NULL if no + * trust path could be built. + */ +ldns_rr_list *ldns_fetch_valid_domain_keys_time(const ldns_resolver * res, + const ldns_rdf * domain, const ldns_rr_list * keys, + time_t check_time, ldns_status *status); + + +/** + * Validates the DNSKEY RRset for the given domain using the provided + * trusted keys. + * + * \param[in] res the current resolver + * \param[in] domain the domain we want valid keys for + * \param[in] keys the current set of trusted keys + * \return the set of trusted keys for the domain, or NULL if the RRSET + * could not be validated + */ +ldns_rr_list *ldns_validate_domain_dnskey (const ldns_resolver *res, + const ldns_rdf *domain, + const ldns_rr_list *keys); + +/** + * Validates the DNSKEY RRset for the given domain using the provided + * trusted keys. + * + * \param[in] res the current resolver + * \param[in] domain the domain we want valid keys for + * \param[in] keys the current set of trusted keys + * \param[in] check_time the time for which the validation is performed + * \return the set of trusted keys for the domain, or NULL if the RRSET + * could not be validated + */ +ldns_rr_list *ldns_validate_domain_dnskey_time( + const ldns_resolver *res, const ldns_rdf *domain, + const ldns_rr_list *keys, time_t check_time); + + +/** + * Validates the DS RRset for the given domain using the provided trusted keys. + * + * \param[in] res the current resolver + * \param[in] domain the domain we want valid keys for + * \param[in] keys the current set of trusted keys + * \return the set of trusted keys for the domain, or NULL if the RRSET could not be validated + */ +ldns_rr_list *ldns_validate_domain_ds(const ldns_resolver *res, + const ldns_rdf * + domain, + const ldns_rr_list * keys); + +/** + * Validates the DS RRset for the given domain using the provided trusted keys. + * + * \param[in] res the current resolver + * \param[in] domain the domain we want valid keys for + * \param[in] keys the current set of trusted keys + * \param[in] check_time the time for which the validation is performed + * \return the set of trusted keys for the domain, or NULL if the RRSET could not be validated + */ +ldns_rr_list *ldns_validate_domain_ds_time( + const ldns_resolver *res, const ldns_rdf *domain, + const ldns_rr_list * keys, time_t check_time); + + +/** + * Verifies a list of signatures for one RRset using a valid trust path. + * + * \param[in] res the current resolver + * \param[in] rrset the rrset to verify + * \param[in] rrsigs a list of signatures to check + * \param[out] validating_keys if this is a (initialized) list, the + * keys from keys that validate one of + * the signatures are added to it + * \return status LDNS_STATUS_OK if there is at least one correct key + */ +ldns_status ldns_verify_trusted(ldns_resolver *res, + ldns_rr_list *rrset, + ldns_rr_list *rrsigs, + ldns_rr_list *validating_keys); + +/** + * Verifies a list of signatures for one RRset using a valid trust path. + * + * \param[in] res the current resolver + * \param[in] rrset the rrset to verify + * \param[in] rrsigs a list of signatures to check + * \param[in] check_time the time for which the validation is performed + * \param[out] validating_keys if this is a (initialized) list, the + * keys from keys that validate one of + * the signatures are added to it + * \return status LDNS_STATUS_OK if there is at least one correct key + */ +ldns_status ldns_verify_trusted_time( + ldns_resolver *res, ldns_rr_list *rrset, + ldns_rr_list *rrsigs, time_t check_time, + ldns_rr_list *validating_keys); + + +/** + * denial is not just a river in egypt + * + * \param[in] rr The (query) RR to check the denial of existence for + * \param[in] nsecs The list of NSEC RRs that are supposed to deny the + * existence of the RR + * \param[in] rrsigs The RRSIG RR covering the NSEC RRs + * \return LDNS_STATUS_OK if the NSEC RRs deny the existence, error code + * containing the reason they do not otherwise + */ +ldns_status ldns_dnssec_verify_denial(ldns_rr *rr, + ldns_rr_list *nsecs, + ldns_rr_list *rrsigs); + +/** + * Denial of existence using NSEC3 records + * Since NSEC3 is a bit more complicated than normal denial, some + * context arguments are needed + * + * \param[in] rr The (query) RR to check the denial of existence for + * \param[in] nsecs The list of NSEC3 RRs that are supposed to deny the + * existence of the RR + * \param[in] rrsigs The RRSIG rr covering the NSEC RRs + * \param[in] packet_rcode The RCODE value of the packet that provided the + * NSEC3 RRs + * \param[in] packet_qtype The original query RR type + * \param[in] packet_nodata True if the providing packet had an empty ANSWER + * section + * \return LDNS_STATUS_OK if the NSEC3 RRs deny the existence, error code + * containing the reason they do not otherwise + */ +ldns_status ldns_dnssec_verify_denial_nsec3(ldns_rr *rr, + ldns_rr_list *nsecs, + ldns_rr_list *rrsigs, + ldns_pkt_rcode packet_rcode, + ldns_rr_type packet_qtype, + bool packet_nodata); + +/** + * Same as ldns_status ldns_dnssec_verify_denial_nsec3 but also returns + * the nsec rr that matched. + * + * \param[in] rr The (query) RR to check the denial of existence for + * \param[in] nsecs The list of NSEC3 RRs that are supposed to deny the + * existence of the RR + * \param[in] rrsigs The RRSIG rr covering the NSEC RRs + * \param[in] packet_rcode The RCODE value of the packet that provided the + * NSEC3 RRs + * \param[in] packet_qtype The original query RR type + * \param[in] packet_nodata True if the providing packet had an empty ANSWER + * section + * \param[in] match On match, the given (reference to a) pointer will be set + * to point to the matching nsec resource record. + * \return LDNS_STATUS_OK if the NSEC3 RRs deny the existence, error code + * containing the reason they do not otherwise + */ +ldns_status ldns_dnssec_verify_denial_nsec3_match(ldns_rr *rr, + ldns_rr_list *nsecs, + ldns_rr_list *rrsigs, + ldns_pkt_rcode packet_rcode, + ldns_rr_type packet_qtype, + bool packet_nodata, + ldns_rr **match); +/** + * Verifies the already processed data in the buffers + * This function should probably not be used directly. + * + * \param[in] rawsig_buf Buffer containing signature data to use + * \param[in] verify_buf Buffer containing data to verify + * \param[in] key_buf Buffer containing key data to use + * \param[in] algo Signing algorithm + * \return status LDNS_STATUS_OK if the data verifies. Error if not. + */ +ldns_status ldns_verify_rrsig_buffers(ldns_buffer *rawsig_buf, + ldns_buffer *verify_buf, + ldns_buffer *key_buf, + uint8_t algo); + +/** + * Like ldns_verify_rrsig_buffers, but uses raw data. + * + * \param[in] sig signature data to use + * \param[in] siglen length of signature data to use + * \param[in] verify_buf Buffer containing data to verify + * \param[in] key key data to use + * \param[in] keylen length of key data to use + * \param[in] algo Signing algorithm + * \return status LDNS_STATUS_OK if the data verifies. Error if not. + */ +ldns_status ldns_verify_rrsig_buffers_raw(unsigned char* sig, + size_t siglen, + ldns_buffer *verify_buf, + unsigned char* key, + size_t keylen, + uint8_t algo); + +/** + * Verifies an rrsig. All keys in the keyset are tried. + * \param[in] rrset the rrset to check + * \param[in] rrsig the signature of the rrset + * \param[in] keys the keys to try + * \param[out] good_keys if this is a (initialized) list, the pointer to keys + * from keys that validate one of the signatures + * are added to it + * \return a list of keys which validate the rrsig + rrset. Returns + * status LDNS_STATUS_OK if at least one key matched. Else an error. + */ +ldns_status ldns_verify_rrsig_keylist(ldns_rr_list *rrset, + ldns_rr *rrsig, + const ldns_rr_list *keys, + ldns_rr_list *good_keys); + +/** + * Verifies an rrsig. All keys in the keyset are tried. + * \param[in] rrset the rrset to check + * \param[in] rrsig the signature of the rrset + * \param[in] keys the keys to try + * \param[in] check_time the time for which the validation is performed + * \param[out] good_keys if this is a (initialized) list, the pointer to keys + * from keys that validate one of the signatures + * are added to it + * \return a list of keys which validate the rrsig + rrset. Returns + * status LDNS_STATUS_OK if at least one key matched. Else an error. + */ +ldns_status ldns_verify_rrsig_keylist_time( + ldns_rr_list *rrset, ldns_rr *rrsig, + const ldns_rr_list *keys, time_t check_time, + ldns_rr_list *good_keys); + + +/** + * Verifies an rrsig. All keys in the keyset are tried. Time is not checked. + * \param[in] rrset the rrset to check + * \param[in] rrsig the signature of the rrset + * \param[in] keys the keys to try + * \param[out] good_keys if this is a (initialized) list, the pointer to keys + * from keys that validate one of the signatures + * are added to it + * \return a list of keys which validate the rrsig + rrset. Returns + * status LDNS_STATUS_OK if at least one key matched. Else an error. + */ +ldns_status ldns_verify_rrsig_keylist_notime(ldns_rr_list *rrset, + ldns_rr *rrsig, + const ldns_rr_list *keys, + ldns_rr_list *good_keys); + +/** + * verify an rrsig with 1 key + * \param[in] rrset the rrset + * \param[in] rrsig the rrsig to verify + * \param[in] key the key to use + * \return status message wether verification succeeded. + */ +ldns_status ldns_verify_rrsig(ldns_rr_list *rrset, + ldns_rr *rrsig, + ldns_rr *key); + + +/** + * verify an rrsig with 1 key + * \param[in] rrset the rrset + * \param[in] rrsig the rrsig to verify + * \param[in] key the key to use + * \param[in] check_time the time for which the validation is performed + * \return status message wether verification succeeded. + */ +ldns_status ldns_verify_rrsig_time( + ldns_rr_list *rrset, ldns_rr *rrsig, + ldns_rr *key, time_t check_time); + + +#if LDNS_BUILD_CONFIG_HAVE_SSL +/** + * verifies a buffer with signature data for a buffer with rrset data + * with an EVP_PKEY + * + * \param[in] sig the signature data + * \param[in] rrset the rrset data, sorted and processed for verification + * \param[in] key the EVP key structure + * \param[in] digest_type The digest type of the signature + */ +ldns_status ldns_verify_rrsig_evp(ldns_buffer *sig, + ldns_buffer *rrset, + EVP_PKEY *key, + const EVP_MD *digest_type); + +/** + * Like ldns_verify_rrsig_evp, but uses raw signature data. + * \param[in] sig the signature data, wireformat uncompressed + * \param[in] siglen length of the signature data + * \param[in] rrset the rrset data, sorted and processed for verification + * \param[in] key the EVP key structure + * \param[in] digest_type The digest type of the signature + */ +ldns_status ldns_verify_rrsig_evp_raw(unsigned char *sig, + size_t siglen, + ldns_buffer *rrset, + EVP_PKEY *key, + const EVP_MD *digest_type); +#endif + +/** + * verifies a buffer with signature data (DSA) for a buffer with rrset data + * with a buffer with key data. + * + * \param[in] sig the signature data + * \param[in] rrset the rrset data, sorted and processed for verification + * \param[in] key the key data + */ +ldns_status ldns_verify_rrsig_dsa(ldns_buffer *sig, + ldns_buffer *rrset, + ldns_buffer *key); + +/** + * verifies a buffer with signature data (RSASHA1) for a buffer with rrset data + * with a buffer with key data. + * + * \param[in] sig the signature data + * \param[in] rrset the rrset data, sorted and processed for verification + * \param[in] key the key data + */ +ldns_status ldns_verify_rrsig_rsasha1(ldns_buffer *sig, + ldns_buffer *rrset, + ldns_buffer *key); + +/** + * verifies a buffer with signature data (RSAMD5) for a buffer with rrset data + * with a buffer with key data. + * + * \param[in] sig the signature data + * \param[in] rrset the rrset data, sorted and processed for verification + * \param[in] key the key data + */ +ldns_status ldns_verify_rrsig_rsamd5(ldns_buffer *sig, + ldns_buffer *rrset, + ldns_buffer *key); + +/** + * Like ldns_verify_rrsig_dsa, but uses raw signature and key data. + * \param[in] sig raw uncompressed wireformat signature data + * \param[in] siglen length of signature data + * \param[in] rrset ldns buffer with prepared rrset data. + * \param[in] key raw uncompressed wireformat key data + * \param[in] keylen length of key data + */ +ldns_status ldns_verify_rrsig_dsa_raw(unsigned char* sig, + size_t siglen, + ldns_buffer* rrset, + unsigned char* key, + size_t keylen); + +/** + * Like ldns_verify_rrsig_rsasha1, but uses raw signature and key data. + * \param[in] sig raw uncompressed wireformat signature data + * \param[in] siglen length of signature data + * \param[in] rrset ldns buffer with prepared rrset data. + * \param[in] key raw uncompressed wireformat key data + * \param[in] keylen length of key data + */ +ldns_status ldns_verify_rrsig_rsasha1_raw(unsigned char* sig, + size_t siglen, + ldns_buffer* rrset, + unsigned char* key, + size_t keylen); + +/** + * Like ldns_verify_rrsig_rsasha256, but uses raw signature and key data. + * \param[in] sig raw uncompressed wireformat signature data + * \param[in] siglen length of signature data + * \param[in] rrset ldns buffer with prepared rrset data. + * \param[in] key raw uncompressed wireformat key data + * \param[in] keylen length of key data + */ + +ldns_status ldns_verify_rrsig_rsasha256_raw(unsigned char* sig, + size_t siglen, + ldns_buffer* rrset, + unsigned char* key, + size_t keylen); + +/** + * Like ldns_verify_rrsig_rsasha512, but uses raw signature and key data. + * \param[in] sig raw uncompressed wireformat signature data + * \param[in] siglen length of signature data + * \param[in] rrset ldns buffer with prepared rrset data. + * \param[in] key raw uncompressed wireformat key data + * \param[in] keylen length of key data + */ +ldns_status ldns_verify_rrsig_rsasha512_raw(unsigned char* sig, + size_t siglen, + ldns_buffer* rrset, + unsigned char* key, + size_t keylen); + +/** + * Like ldns_verify_rrsig_rsamd5, but uses raw signature and key data. + * \param[in] sig raw uncompressed wireformat signature data + * \param[in] siglen length of signature data + * \param[in] rrset ldns buffer with prepared rrset data. + * \param[in] key raw uncompressed wireformat key data + * \param[in] keylen length of key data + */ +ldns_status ldns_verify_rrsig_rsamd5_raw(unsigned char* sig, + size_t siglen, + ldns_buffer* rrset, + unsigned char* key, + size_t keylen); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/ldns/dnssec_zone.h b/ldns/dnssec_zone.h new file mode 100644 index 00000000000..4d2642fd1b4 --- /dev/null +++ b/ldns/dnssec_zone.h @@ -0,0 +1,476 @@ +/* + * special zone file structures and functions for better dnssec handling + * + * A zone contains a SOA dnssec_zone_rrset, and an AVL tree of 'normal' + * dnssec_zone_rrsets, indexed by name and type + */ + +#ifndef LDNS_DNSSEC_ZONE_H +#define LDNS_DNSSEC_ZONE_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Singly linked list of rrs + */ +typedef struct ldns_struct_dnssec_rrs ldns_dnssec_rrs; +struct ldns_struct_dnssec_rrs +{ + ldns_rr *rr; + ldns_dnssec_rrs *next; +}; + +/** + * Singly linked list of RRsets + */ +typedef struct ldns_struct_dnssec_rrsets ldns_dnssec_rrsets; +struct ldns_struct_dnssec_rrsets +{ + ldns_dnssec_rrs *rrs; + ldns_rr_type type; + ldns_dnssec_rrs *signatures; + ldns_dnssec_rrsets *next; +}; + +/** + * Structure containing all resource records for a domain name + * Including the derived NSEC3, if present + */ +typedef struct ldns_struct_dnssec_name ldns_dnssec_name; +struct ldns_struct_dnssec_name +{ + /** + * pointer to a dname containing the name. + * Usually points to the owner name of the first RR of the first RRset + */ + ldns_rdf *name; + /** + * Usually, the name is a pointer to the owner name of the first rr for + * this name, but sometimes there is no actual data to point to, + * for instance in + * names representing empty nonterminals. If so, set alloced to true to + * indicate that this data must also be freed when the name is freed + */ + bool name_alloced; + /** + * The rrsets for this name + */ + ldns_dnssec_rrsets *rrsets; + /** + * NSEC pointing to the next name (or NSEC3 pointing to the next NSEC3) + */ + ldns_rr *nsec; + /** + * signatures for the NSEC record + */ + ldns_dnssec_rrs *nsec_signatures; + /** + * Unlike what the name is_glue suggests, this field is set to true by + * ldns_dnssec_zone_mark_glue() or ldns_dnssec_zone_mark_and_get_glue() + * when the name, this dnssec_name struct represents, is occluded. + * Names that contain other occluded rrsets and records with glue on + * the delegation point will NOT have this bool set to true. + * This field should NOT be read directly, but only via the + * ldns_dnssec_name_is_glue() function! + */ + bool is_glue; + /** + * pointer to store the hashed name (only used when in an NSEC3 zone + */ + ldns_rdf *hashed_name; +}; + +/** + * Structure containing a dnssec zone + */ +struct ldns_struct_dnssec_zone { + /** points to the name containing the SOA RR */ + ldns_dnssec_name *soa; + /** tree of ldns_dnssec_names */ + ldns_rbtree_t *names; +}; +typedef struct ldns_struct_dnssec_zone ldns_dnssec_zone; + +/** + * Creates a new entry for 1 pointer to an rr and 1 pointer to the next rrs + * \return the allocated data + */ +ldns_dnssec_rrs *ldns_dnssec_rrs_new(); + +/** + * Frees the list of rrs, but *not* the individual ldns_rr records + * contained in the list + * + * \param[in] rrs the data structure to free + */ +void ldns_dnssec_rrs_free(ldns_dnssec_rrs *rrs); + +/** + * Frees the list of rrs, and the individual ldns_rr records + * contained in the list + * + * \param[in] rrs the data structure to free + */ +void ldns_dnssec_rrs_deep_free(ldns_dnssec_rrs *rrs); + +/** + * Adds an RR to the list of RRs. The list will remain ordered + * + * \param[in] rrs the list to add to + * \param[in] rr the RR to add + * \return LDNS_STATUS_OK on success + */ +ldns_status ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr); + +/** + * Prints the given rrs to the file descriptor + * + * \param[in] out the file descriptor to print to + * \param[in] rrs the list of RRs to print + */ +void ldns_dnssec_rrs_print(FILE *out, ldns_dnssec_rrs *rrs); + +/** + * Prints the given rrs to the file descriptor + * + * \param[in] out the file descriptor to print to + * \param[in] fmt the format of the textual representation + * \param[in] rrs the list of RRs to print + */ +void ldns_dnssec_rrs_print_fmt(FILE *out, + const ldns_output_format *fmt, ldns_dnssec_rrs *rrs); + +/** + * Creates a new list (entry) of RRsets + * \return the newly allocated structure + */ +ldns_dnssec_rrsets *ldns_dnssec_rrsets_new(); + +/** + * Frees the list of rrsets and their rrs, but *not* the ldns_rr + * records in the sets + * + * \param[in] rrsets the data structure to free + */ +void ldns_dnssec_rrsets_free(ldns_dnssec_rrsets *rrsets); + +/** + * Frees the list of rrsets and their rrs, and the ldns_rr + * records in the sets + * + * \param[in] rrsets the data structure to free + */ +void ldns_dnssec_rrsets_deep_free(ldns_dnssec_rrsets *rrsets); + +/** + * Returns the rr type of the rrset (that is head of the given list) + * + * \param[in] rrsets the rrset to get the type of + * \return the rr type + */ +ldns_rr_type ldns_dnssec_rrsets_type(ldns_dnssec_rrsets *rrsets); + +/** + * Sets the RR type of the rrset (that is head of the given list) + * + * \param[in] rrsets the rrset to set the type of + * \param[in] type the type to set + * \return LDNS_STATUS_OK on success + */ +ldns_status ldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets *rrsets, + ldns_rr_type type); + +/** + * Add an ldns_rr to the corresponding RRset in the given list of RRsets. + * If it is not present, add it as a new RRset with 1 record. + * + * \param[in] rrsets the list of rrsets to add the RR to + * \param[in] rr the rr to add to the list of rrsets + * \return LDNS_STATUS_OK on success + */ +ldns_status ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets *rrsets, ldns_rr *rr); + +/** + * Print the given list of rrsets to the fiven file descriptor + * + * \param[in] out the file descriptor to print to + * \param[in] rrsets the list of RRsets to print + * \param[in] follow if set to false, only print the first RRset + */ +void ldns_dnssec_rrsets_print(FILE *out, + ldns_dnssec_rrsets *rrsets, + bool follow); + +/** + * Print the given list of rrsets to the fiven file descriptor + * + * \param[in] out the file descriptor to print to + * \param[in] fmt the format of the textual representation + * \param[in] rrsets the list of RRsets to print + * \param[in] follow if set to false, only print the first RRset + */ +void ldns_dnssec_rrsets_print_fmt(FILE *out, + const ldns_output_format *fmt, + ldns_dnssec_rrsets *rrsets, + bool follow); + + +/** + * Create a new data structure for a dnssec name + * \return the allocated structure + */ +ldns_dnssec_name *ldns_dnssec_name_new(); + +/** + * Create a new data structure for a dnssec name for the given RR + * + * \param[in] rr the RR to derive properties from, and to add to the name + */ +ldns_dnssec_name *ldns_dnssec_name_new_frm_rr(ldns_rr *rr); + +/** + * Frees the name structure and its rrs and rrsets. + * Individual ldns_rr records therein are not freed + * + * \param[in] name the structure to free + */ +void ldns_dnssec_name_free(ldns_dnssec_name *name); + +/** + * Frees the name structure and its rrs and rrsets. + * Individual ldns_rr records contained in the name are also freed + * + * \param[in] name the structure to free + */ +void ldns_dnssec_name_deep_free(ldns_dnssec_name *name); + +/** + * Returns the domain name of the given dnssec_name structure + * + * \param[in] name the dnssec name to get the domain name from + * \return the domain name + */ +ldns_rdf *ldns_dnssec_name_name(ldns_dnssec_name *name); + + +/** + * Sets the domain name of the given dnssec_name structure + * + * \param[in] name the dnssec name to set the domain name of + * \param[in] dname the domain name to set it to. This data is *not* copied. + */ +void ldns_dnssec_name_set_name(ldns_dnssec_name *name, + ldns_rdf *dname); +/** + * Returns if dnssec_name structure is marked as glue. + * The ldns_dnssec_zone_mark_glue() function has to be called on a zone before + * using this function. + * Only names that have only glue rrsets will be marked. + * Names that have other occluded rrsets and names containing glue on the + * delegation point will NOT be marked! + * + * \param[in] name the dnssec name to get the domain name from + * \return true if the structure is marked as glue, false otherwise. + */ +bool ldns_dnssec_name_is_glue(ldns_dnssec_name *name); + +/** + * Sets the NSEC(3) RR of the given dnssec_name structure + * + * \param[in] name the dnssec name to set the domain name of + * \param[in] nsec the nsec rr to set it to. This data is *not* copied. + */ +void ldns_dnssec_name_set_nsec(ldns_dnssec_name *name, ldns_rr *nsec); + +/** + * Compares the domain names of the two arguments in their + * canonical ordening. + * + * \param[in] a The first dnssec_name to compare + * \param[in] b The second dnssec_name to compare + * \return -1 if the domain name of a comes before that of b in canonical + * ordening, 1 if it is the other way around, and 0 if they are + * equal + */ +int ldns_dnssec_name_cmp(const void *a, const void *b); + +/** + * Inserts the given rr at the right place in the current dnssec_name + * No checking is done whether the name matches + * + * \param[in] name The ldns_dnssec_name to add the RR to + * \param[in] rr The RR to add + * \return LDNS_STATUS_OK on success, error code otherwise + */ +ldns_status ldns_dnssec_name_add_rr(ldns_dnssec_name *name, + ldns_rr *rr); + +/** + * Find the RRset with the given type in within this name structure + * + * \param[in] name the name to find the RRset in + * \param[in] type the type of the RRset to find + * \return the RRset, or NULL if not present + */ +ldns_dnssec_rrsets *ldns_dnssec_name_find_rrset(ldns_dnssec_name *name, + ldns_rr_type type); + +/** + * Find the RRset with the given name and type in the zone + * + * \param[in] zone the zone structure to find the RRset in + * \param[in] dname the domain name of the RRset to find + * \param[in] type the type of the RRset to find + * \return the RRset, or NULL if not present + */ +ldns_dnssec_rrsets *ldns_dnssec_zone_find_rrset(ldns_dnssec_zone *zone, + ldns_rdf *dname, + ldns_rr_type type); + +/** + * Prints the RRs in the dnssec name structure to the given + * file descriptor + * + * \param[in] out the file descriptor to print to + * \param[in] name the name structure to print the contents of + */ +void ldns_dnssec_name_print(FILE *out, ldns_dnssec_name *name); + +/** + * Prints the RRs in the dnssec name structure to the given + * file descriptor + * + * \param[in] out the file descriptor to print to + * \param[in] fmt the format of the textual representation + * \param[in] name the name structure to print the contents of + */ +void ldns_dnssec_name_print_fmt(FILE *out, + const ldns_output_format *fmt, ldns_dnssec_name *name); + +/** + * Creates a new dnssec_zone structure + * \return the allocated structure + */ +ldns_dnssec_zone *ldns_dnssec_zone_new(); + +/** + * Create a new dnssec zone from a file. + * \param[out] z the new zone + * \param[in] *fp the filepointer to use + * \param[in] *origin the zones' origin + * \param[in] c default class to use (IN) + * \param[in] ttl default ttl to use + * + * \return ldns_status mesg with an error or LDNS_STATUS_OK + */ +ldns_status ldns_dnssec_zone_new_frm_fp(ldns_dnssec_zone** z, FILE* fp, + ldns_rdf* origin, uint32_t ttl, ldns_rr_class c); + +/** + * Create a new dnssec zone from a file, keep track of the line numbering + * \param[out] z the new zone + * \param[in] *fp the filepointer to use + * \param[in] *origin the zones' origin + * \param[in] ttl default ttl to use + * \param[in] c default class to use (IN) + * \param[out] line_nr used for error msg, to get to the line number + * + * \return ldns_status mesg with an error or LDNS_STATUS_OK + */ +ldns_status ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, + ldns_rdf* origin, uint32_t ttl, ldns_rr_class c, int* line_nr); + +/** + * Frees the given zone structure, and its rbtree of dnssec_names + * Individual ldns_rr RRs within those names are *not* freed + * \param[in] *zone the zone to free + */ +void ldns_dnssec_zone_free(ldns_dnssec_zone *zone); + +/** + * Frees the given zone structure, and its rbtree of dnssec_names + * Individual ldns_rr RRs within those names are also freed + * \param[in] *zone the zone to free + */ +void ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone); + +/** + * Adds the given RR to the zone. + * It find whether there is a dnssec_name with that name present. + * If so, add it to that, if not create a new one. + * Special handling of NSEC and RRSIG provided + * + * \param[in] zone the zone to add the RR to + * \param[in] rr The RR to add + * \return LDNS_STATUS_OK on success, an error code otherwise + */ +ldns_status ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, + ldns_rr *rr); + +/** + * Prints the rbtree of ldns_dnssec_name structures to the file descriptor + * + * \param[in] out the file descriptor to print the names to + * \param[in] tree the tree of ldns_dnssec_name structures to print + * \param[in] print_soa if true, print SOA records, if false, skip them + */ +void ldns_dnssec_zone_names_print(FILE *out, ldns_rbtree_t *tree, bool print_soa); + +/** + * Prints the rbtree of ldns_dnssec_name structures to the file descriptor + * + * \param[in] out the file descriptor to print the names to + * \param[in] fmt the format of the textual representation + * \param[in] tree the tree of ldns_dnssec_name structures to print + * \param[in] print_soa if true, print SOA records, if false, skip them + */ +void ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt, + ldns_rbtree_t *tree, bool print_soa); + +/** + * Prints the complete zone to the given file descriptor + * + * \param[in] out the file descriptor to print to + * \param[in] zone the dnssec_zone to print + */ +void ldns_dnssec_zone_print(FILE *out, ldns_dnssec_zone *zone); + +/** + * Prints the complete zone to the given file descriptor + * + * \param[in] out the file descriptor to print to + * \param[in] fmt the format of the textual representation + * \param[in] zone the dnssec_zone to print + */ +void ldns_dnssec_zone_print_fmt(FILE *out, + const ldns_output_format *fmt, ldns_dnssec_zone *zone); + +/** + * Adds explicit dnssec_name structures for the empty nonterminals + * in this zone. (this is needed for NSEC3 generation) + * + * \param[in] zone the zone to check for empty nonterminals + * return LDNS_STATUS_OK on success. + */ +ldns_status ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone); + +/** + * If a NSEC3PARAM is available in the apex, walks the zone and returns true + * on the first optout nsec3. + * + * \param[in] zone the zone to check for nsec3 optout records + * return true when the zone has at least one nsec3 optout record. + */ +bool ldns_dnssec_zone_is_nsec3_optout(ldns_dnssec_zone* zone); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ldns/duration.h b/ldns/duration.h new file mode 100644 index 00000000000..f12edc427cc --- /dev/null +++ b/ldns/duration.h @@ -0,0 +1,109 @@ +/* + * $Id: duration.h 4341 2011-01-31 15:21:09Z matthijs $ + * + * Copyright (c) 2009 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: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * + * This file is copied from the OpenDNSSEC source repository + * and only slightly adapted to make it fit. + */ + +/** + * + * Durations. + */ + +#ifndef LDNS_DURATION_H +#define LDNS_DURATION_H + +#include +#include + +/** + * Duration. + * + */ +typedef struct ldns_duration_struct ldns_duration_type; +struct ldns_duration_struct +{ + time_t years; + time_t months; + time_t weeks; + time_t days; + time_t hours; + time_t minutes; + time_t seconds; +}; + +/** + * Create a new 'instant' duration. + * \return ldns_duration_type* created duration + * + */ +ldns_duration_type* ldns_duration_create(void); + +/** + * Compare durations. + * \param[in] d1 one duration + * \param[in] d2 another duration + * \return int 0 if equal, -1 if d1 < d2, 1 if d2 < d1 + * + */ +int ldns_duration_compare(ldns_duration_type* d1, ldns_duration_type* d2); + +/** + * Create a duration from string. + * \param[in] str string-format duration + * \return ldns_duration_type* created duration + * + */ +ldns_duration_type* ldns_duration_create_from_string(const char* str); + +/** + * Convert a duration to a string. + * \param[in] duration duration to be converted + * \return char* string-format duration + * + */ +char* ldns_duration2string(ldns_duration_type* duration); + +/** + * Convert a duration to a time. + * \param[in] duration duration to be converted + * \return time_t time-format duration + * + */ +time_t ldns_duration2time(ldns_duration_type* duration); + +/** + * Clean up duration. + * \param[in] duration duration to be cleaned up + * + */ +void ldns_duration_cleanup(ldns_duration_type* duration); + +#endif /* LDNS_DURATION_H */ diff --git a/ldns/error.h b/ldns/error.h new file mode 100644 index 00000000000..6396a934664 --- /dev/null +++ b/ldns/error.h @@ -0,0 +1,123 @@ +/** + * \file error.h + * + * Defines error numbers and functions to translate those to a readable string. + * + */ + +/** + * a Net::DNS like library for C + * + * (c) NLnet Labs, 2005-2006 + * + * See the file LICENSE for the license + */ + +#ifndef LDNS_ERROR_H +#define LDNS_ERROR_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +enum ldns_enum_status { + LDNS_STATUS_OK, + LDNS_STATUS_EMPTY_LABEL, + LDNS_STATUS_LABEL_OVERFLOW, + LDNS_STATUS_DOMAINNAME_OVERFLOW, + LDNS_STATUS_DOMAINNAME_UNDERFLOW, + LDNS_STATUS_DDD_OVERFLOW, + LDNS_STATUS_PACKET_OVERFLOW, + LDNS_STATUS_INVALID_POINTER, + LDNS_STATUS_MEM_ERR, + LDNS_STATUS_INTERNAL_ERR, + LDNS_STATUS_SSL_ERR, + LDNS_STATUS_ERR, + LDNS_STATUS_INVALID_INT, + LDNS_STATUS_INVALID_IP4, + LDNS_STATUS_INVALID_IP6, + LDNS_STATUS_INVALID_STR, + LDNS_STATUS_INVALID_B32_EXT, + LDNS_STATUS_INVALID_B64, + LDNS_STATUS_INVALID_HEX, + LDNS_STATUS_INVALID_TIME, + LDNS_STATUS_NETWORK_ERR, + LDNS_STATUS_ADDRESS_ERR, + LDNS_STATUS_FILE_ERR, + LDNS_STATUS_UNKNOWN_INET, + LDNS_STATUS_NOT_IMPL, + LDNS_STATUS_NULL, + LDNS_STATUS_CRYPTO_UNKNOWN_ALGO, + LDNS_STATUS_CRYPTO_ALGO_NOT_IMPL, + LDNS_STATUS_CRYPTO_NO_RRSIG, + LDNS_STATUS_CRYPTO_NO_DNSKEY, + LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY, + LDNS_STATUS_CRYPTO_NO_DS, + LDNS_STATUS_CRYPTO_NO_TRUSTED_DS, + LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY, + LDNS_STATUS_CRYPTO_VALIDATED, + LDNS_STATUS_CRYPTO_BOGUS, + LDNS_STATUS_CRYPTO_SIG_EXPIRED, + LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED, + LDNS_STATUS_CRYPTO_TSIG_BOGUS, + LDNS_STATUS_CRYPTO_TSIG_ERR, + LDNS_STATUS_CRYPTO_EXPIRATION_BEFORE_INCEPTION, + LDNS_STATUS_CRYPTO_TYPE_COVERED_ERR, + LDNS_STATUS_ENGINE_KEY_NOT_LOADED, + LDNS_STATUS_NSEC3_ERR, + LDNS_STATUS_RES_NO_NS, + LDNS_STATUS_RES_QUERY, + LDNS_STATUS_WIRE_INCOMPLETE_HEADER, + LDNS_STATUS_WIRE_INCOMPLETE_QUESTION, + LDNS_STATUS_WIRE_INCOMPLETE_ANSWER, + LDNS_STATUS_WIRE_INCOMPLETE_AUTHORITY, + LDNS_STATUS_WIRE_INCOMPLETE_ADDITIONAL, + LDNS_STATUS_NO_DATA, + LDNS_STATUS_CERT_BAD_ALGORITHM, + LDNS_STATUS_SYNTAX_TYPE_ERR, + LDNS_STATUS_SYNTAX_CLASS_ERR, + LDNS_STATUS_SYNTAX_TTL_ERR, + LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL, + LDNS_STATUS_SYNTAX_RDATA_ERR, + LDNS_STATUS_SYNTAX_DNAME_ERR, + LDNS_STATUS_SYNTAX_VERSION_ERR, + LDNS_STATUS_SYNTAX_ALG_ERR, + LDNS_STATUS_SYNTAX_KEYWORD_ERR, + LDNS_STATUS_SYNTAX_TTL, + LDNS_STATUS_SYNTAX_ORIGIN, + LDNS_STATUS_SYNTAX_INCLUDE, + LDNS_STATUS_SYNTAX_EMPTY, + LDNS_STATUS_SYNTAX_ITERATIONS_OVERFLOW, + LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR, + LDNS_STATUS_SYNTAX_INTEGER_OVERFLOW, + LDNS_STATUS_SYNTAX_BAD_ESCAPE, + LDNS_STATUS_SOCKET_ERROR, + LDNS_STATUS_SYNTAX_ERR, + LDNS_STATUS_DNSSEC_EXISTENCE_DENIED, + LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED, + LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED, + LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND, + LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG, + LDNS_STATUS_MISSING_RDATA_FIELDS_KEY, + LDNS_STATUS_CRYPTO_SIG_EXPIRED_WITHIN_MARGIN, + LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED_WITHIN_MARGIN +}; +typedef enum ldns_enum_status ldns_status; + +extern ldns_lookup_table ldns_error_str[]; + +/** + * look up a descriptive text by each error. This function + * could use a better name + * \param[in] err ldns_status number + * \return the string for that error + */ +const char *ldns_get_errorstr_by_id(ldns_status err); + +#ifdef __cplusplus +} +#endif + +#endif /* LDNS_ERROR_H */ diff --git a/ldns/higher.h b/ldns/higher.h new file mode 100644 index 00000000000..597e1343a94 --- /dev/null +++ b/ldns/higher.h @@ -0,0 +1,113 @@ +/** + * \file higher.h + * + * Specifies some higher level functions that could + * be useful for certain applications + */ + +/* + * a Net::DNS like library for C + * + * (c) NLnet Labs, 2005-2006 + * + * See the file LICENSE for the license + */ + +#ifndef LDNS_HIGHER_H +#define LDNS_HIGHER_H + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Ask the resolver about name + * and return all address records + * \param[in] r the resolver to use + * \param[in] name the name to look for + * \param[in] c the class to use + * \param[in] flags give some optional flags to the query + */ +ldns_rr_list *ldns_get_rr_list_addr_by_name(ldns_resolver *r, ldns_rdf *name, ldns_rr_class c, uint16_t flags); + +/** + * ask the resolver about the address + * and return the name + * \param[in] r the resolver to use + * \param[in] addr the addr to look for + * \param[in] c the class to use + * \param[in] flags give some optional flags to the query + */ +ldns_rr_list *ldns_get_rr_list_name_by_addr(ldns_resolver *r, ldns_rdf *addr, ldns_rr_class c, uint16_t flags); + +/** + * wade through fp (a /etc/hosts like file) + * and return a rr_list containing all the + * defined hosts in there + * \param[in] fp the file pointer to use + * \return ldns_rr_list * with the names + */ +ldns_rr_list *ldns_get_rr_list_hosts_frm_fp(FILE *fp); + +/** + * wade through fp (a /etc/hosts like file) + * and return a rr_list containing all the + * defined hosts in there + * \param[in] fp the file pointer to use + * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes) + * \return ldns_rr_list * with the names + */ +ldns_rr_list *ldns_get_rr_list_hosts_frm_fp_l(FILE *fp, int *line_nr); + +/** + * wade through fp (a /etc/hosts like file) + * and return a rr_list containing all the + * defined hosts in there + * \param[in] filename the filename to use (NULL for /etc/hosts) + * \return ldns_rr_list * with the names + */ +ldns_rr_list *ldns_get_rr_list_hosts_frm_file(char *filename); + +/** + * This function is a wrapper function for ldns_get_rr_list_name_by_addr + * and ldns_get_rr_list_addr_by_name. It's name is from the getaddrinfo() + * library call. It tries to mimic that call, but without the lowlevel + * stuff. + * \param[in] res The resolver. If this value is NULL then a resolver will + * be created by ldns_getaddrinfo. + * \param[in] node the name or ip address to look up + * \param[in] c the class to look in + * \param[out] list put the found RR's in this list + * \return the number of RR found. + */ +uint16_t ldns_getaddrinfo(ldns_resolver *res, ldns_rdf *node, ldns_rr_class c, ldns_rr_list **list); + +/** + * Check if t is enumerated in the nsec type rdata + * \param[in] nsec the NSEC Record to look in + * \param[in] t the type to check for + * \return true when t is found, otherwise return false + */ +bool ldns_nsec_type_check(ldns_rr *nsec, ldns_rr_type t); + +/** + * Print a number of rdf's of the RR. The rdfnum-list must + * be ended by -1, otherwise unpredictable things might happen. + * rdfs may be printed multiple times + * \param[in] fp FILE * to write to + * \param[in] r RR to write + * \param[in] rdfnum a list of rdf to print. + */ +void ldns_print_rr_rdf(FILE *fp, ldns_rr *r, int rdfnum, ...); + +#ifdef __cplusplus +} +#endif + +#endif /* LDNS_HIGHER_H */ diff --git a/ldns/host2str.h b/ldns/host2str.h new file mode 100644 index 00000000000..f0a14a4304a --- /dev/null +++ b/ldns/host2str.h @@ -0,0 +1,759 @@ +/** + * host2str.h - txt presentation of RRs + * + * a Net::DNS like library for C + * + * (c) NLnet Labs, 2005-2006 + * + * See the file LICENSE for the license + */ + +/** + * \file + * + * Contains functions to translate the main structures to their text + * representation, as well as functions to print them. + */ + +#ifndef LDNS_HOST2STR_H +#define LDNS_HOST2STR_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ldns/util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define LDNS_APL_IP4 1 +#define LDNS_APL_IP6 2 +#define LDNS_APL_MASK 0x7f +#define LDNS_APL_NEGATION 0x80 + +/** + * Represent a NULL pointer (in stead of a pointer to a ldns_rr as "; (null)" + * as opposed to outputting nothing at all in such a case. + */ +#define LDNS_COMMENT_NULLS 0x0001 +/** Show key id with DNSKEY RR's as comment */ +#define LDNS_COMMENT_KEY_ID 0x0002 +/** Show if a DNSKEY is a ZSK or KSK as comment */ +#define LDNS_COMMENT_KEY_TYPE 0x0004 +/** Show DNSKEY key size as comment */ +#define LDNS_COMMENT_KEY_SIZE 0x0008 +/** Show key id, type and size as comment for DNSKEY RR's */ +#define LDNS_COMMENT_KEY (LDNS_COMMENT_KEY_ID \ + |LDNS_COMMENT_KEY_TYPE\ + |LDNS_COMMENT_KEY_SIZE) +/** Provide bubblebabble representation for DS RR's as comment */ +#define LDNS_COMMENT_BUBBLEBABBLE 0x0010 +/** Show when a NSEC3 RR has the optout flag set as comment */ +#define LDNS_COMMENT_FLAGS 0x0020 +/** Show the unhashed owner and next owner names for NSEC3 RR's as comment */ +#define LDNS_COMMENT_NSEC3_CHAIN 0x0040 +/** Print mark up */ +#define LDNS_COMMENT_LAYOUT 0x0080 +/** Also comment KEY_ID with RRSIGS **/ +#define LDNS_COMMENT_RRSIGS 0x0100 + +/** + * Output format specifier + * + * Determines how Packets, Resource Records and Resource record data fiels are + * formatted when printing or converting to string. + * Currently it is only used to specify what aspects of a Resource Record are + * annotated in the comment section of the textual representation the record. + * This is speciefed with flags and potential exra data (such as for example + * a lookup map of hashes to real names for annotation NSEC3 records). + */ +struct ldns_struct_output_format +{ + /** Specification of how RR's should be formatted in text */ + int flags; + /** Potential extra data to be used with formatting RR's in text */ + void *data; +}; +typedef struct ldns_struct_output_format ldns_output_format; + +/** + * Standard output format record that disables commenting in the textual + * representation of Resource Records completely. + */ +extern const ldns_output_format *ldns_output_format_nocomments; +/** + * Standard output format record that annotated only DNSKEY RR's with commenti + * text. + */ +extern const ldns_output_format *ldns_output_format_onlykeyids; +/** + * The default output format record. Same as ldns_output_format_onlykeyids. + */ +extern const ldns_output_format *ldns_output_format_default; +/** + * Standard output format record that shows all DNSKEY related information in + * the comment text, plus the optout flag when set with NSEC3's, plus the + * bubblebabble representation of DS RR's. + */ +extern const ldns_output_format *ldns_output_format_bubblebabble; + +/** + * Converts an ldns packet opcode value to its mnemonic, and adds that + * to the output buffer + * \param[in] *output the buffer to add the data to + * \param[in] opcode to find the string representation of + * \return LDNS_STATUS_OK on success, or a buffer failure mode on error + */ +ldns_status +ldns_pkt_opcode2buffer_str(ldns_buffer *output, ldns_pkt_opcode opcode); + +/** + * Converts an ldns packet rcode value to its mnemonic, and adds that + * to the output buffer + * \param[in] *output the buffer to add the data to + * \param[in] rcode to find the string representation of + * \return LDNS_STATUS_OK on success, or a buffer failure mode on error + */ +ldns_status +ldns_pkt_rcode2buffer_str(ldns_buffer *output, ldns_pkt_rcode rcode); + +/** + * Converts an ldns algorithm type to its mnemonic, and adds that + * to the output buffer + * \param[in] *output the buffer to add the data to + * \param[in] algorithm to find the string representation of + * \return LDNS_STATUS_OK on success, or a buffer failure mode on error + */ +ldns_status +ldns_algorithm2buffer_str(ldns_buffer *output, + ldns_algorithm algorithm); + +/** + * Converts an ldns certificate algorithm type to its mnemonic, + * and adds that to the output buffer + * \param[in] *output the buffer to add the data to + * \param[in] cert_algorithm to find the string representation of + * \return LDNS_STATUS_OK on success, or a buffer failure mode on error + */ +ldns_status +ldns_cert_algorithm2buffer_str(ldns_buffer *output, + ldns_cert_algorithm cert_algorithm); + + +/** + * Converts a packet opcode to its mnemonic and returns that as + * an allocated null-terminated string. + * Remember to free it. + * + * \param[in] opcode the opcode to convert to text + * \return null terminated char * data, or NULL on error + */ +char *ldns_pkt_opcode2str(ldns_pkt_opcode opcode); + +/** + * Converts a packet rcode to its mnemonic and returns that as + * an allocated null-terminated string. + * Remember to free it. + * + * \param[in] rcode the rcode to convert to text + * \return null terminated char * data, or NULL on error + */ +char *ldns_pkt_rcode2str(ldns_pkt_rcode rcode); + +/** + * Converts a signing algorithms to its mnemonic and returns that as + * an allocated null-terminated string. + * Remember to free it. + * + * \param[in] algorithm the algorithm to convert to text + * \return null terminated char * data, or NULL on error + */ +char *ldns_pkt_algorithm2str(ldns_algorithm algorithm); + +/** + * Converts a cert algorithm to its mnemonic and returns that as + * an allocated null-terminated string. + * Remember to free it. + * + * \param[in] cert_algorithm to convert to text + * \return null terminated char * data, or NULL on error + */ +char *ldns_pkt_cert_algorithm2str(ldns_cert_algorithm cert_algorithm); + +/** + * Converts an LDNS_RDF_TYPE_A rdata element to string format and adds it to the output buffer + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_a(ldns_buffer *output, const ldns_rdf *rdf); + +/** + * Converts an LDNS_RDF_TYPE_AAAA rdata element to string format and adds it to the output buffer + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_aaaa(ldns_buffer *output, const ldns_rdf *rdf); + +/** + * Converts an LDNS_RDF_TYPE_STR rdata element to string format and adds it to the output buffer + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_str(ldns_buffer *output, const ldns_rdf *rdf); + +/** + * Converts an LDNS_RDF_TYPE_B64 rdata element to string format and adds it to the output buffer + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_b64(ldns_buffer *output, const ldns_rdf *rdf); + +/** + * Converts an LDNS_RDF_TYPE_B32_EXT rdata element to string format and adds it to the output buffer + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_b32_ext(ldns_buffer *output, const ldns_rdf *rdf); + +/** + * Converts an LDNS_RDF_TYPE_HEX rdata element to string format and adds it to the output buffer + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_hex(ldns_buffer *output, const ldns_rdf *rdf); + +/** + * Converts an LDNS_RDF_TYPE_TYPE rdata element to string format and adds it to the output buffer + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_type(ldns_buffer *output, const ldns_rdf *rdf); + +/** + * Converts an LDNS_RDF_TYPE_CLASS rdata element to string format and adds it to the output buffer + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_class(ldns_buffer *output, const ldns_rdf *rdf); + +/** + * Converts an LDNS_RDF_TYPE_ALG rdata element to string format and adds it to the output buffer + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_alg(ldns_buffer *output, const ldns_rdf *rdf); + +/** + * Converts an ldns_rr_type value to its string representation, + * and places it in the given buffer + * \param[in] *output The buffer to add the data to + * \param[in] type the ldns_rr_type to convert + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rr_type2buffer_str(ldns_buffer *output, + const ldns_rr_type type); + +/** + * Converts an ldns_rr_type value to its string representation, + * and returns that string. For unknown types, the string + * "TYPE" is returned. This function allocates data that must be + * freed by the caller + * \param[in] type the ldns_rr_type to convert + * \return a newly allocated string + */ +char *ldns_rr_type2str(const ldns_rr_type type); + +/** + * Converts an ldns_rr_class value to its string representation, + * and places it in the given buffer + * \param[in] *output The buffer to add the data to + * \param[in] klass the ldns_rr_class to convert + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rr_class2buffer_str(ldns_buffer *output, + const ldns_rr_class klass); + +/** + * Converts an ldns_rr_class value to its string representation, + * and returns that string. For unknown types, the string + * "CLASS" is returned. This function allocates data that must be + * freed by the caller + * \param[in] klass the ldns_rr_class to convert + * \return a newly allocated string + */ +char *ldns_rr_class2str(const ldns_rr_class klass); + + +/** + * Converts an LDNS_RDF_TYPE_CERT rdata element to string format and adds it to the output buffer + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_cert_alg(ldns_buffer *output, const ldns_rdf *rdf); + +/** + * Converts an LDNS_RDF_TYPE_LOC rdata element to string format and adds it to the output buffer + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_loc(ldns_buffer *output, const ldns_rdf *rdf); + +/** + * Converts an LDNS_RDF_TYPE_UNKNOWN rdata element to string format and adds it to the output buffer + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_unknown(ldns_buffer *output, const ldns_rdf *rdf); + +/** + * Converts an LDNS_RDF_TYPE_NSAP rdata element to string format and adds it to the output buffer + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_nsap(ldns_buffer *output, const ldns_rdf *rdf); + +/** + * Converts an LDNS_RDF_TYPE_ATMA rdata element to string format and adds it to the output buffer + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_atma(ldns_buffer *output, const ldns_rdf *rdf); + +/** + * Converts an LDNS_RDF_TYPE_WKS rdata element to string format and adds it to the output buffer + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_wks(ldns_buffer *output, const ldns_rdf *rdf); + +/** + * Converts an LDNS_RDF_TYPE_NSEC rdata element to string format and adds it to the output buffer + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_nsec(ldns_buffer *output, const ldns_rdf *rdf); + +/** + * Converts an LDNS_RDF_TYPE_PERIOD rdata element to string format and adds it to the output buffer + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_period(ldns_buffer *output, const ldns_rdf *rdf); + +/** + * Converts an LDNS_RDF_TYPE_TSIGTIME rdata element to string format and adds it to the output buffer + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_tsigtime(ldns_buffer *output, const ldns_rdf *rdf); + +/** + * Converts an LDNS_RDF_TYPE_APL rdata element to string format and adds it to the output buffer + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_apl(ldns_buffer *output, const ldns_rdf *rdf); + +/** + * Converts an LDNS_RDF_TYPE_INT16_DATA rdata element to string format and adds it to the output buffer + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_int16_data(ldns_buffer *output, const ldns_rdf *rdf); + +/** + * Converts an LDNS_RDF_TYPE_IPSECKEY rdata element to string format and adds it to the output buffer + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_ipseckey(ldns_buffer *output, const ldns_rdf *rdf); + +/** + * Converts an LDNS_RDF_TYPE_TSIG rdata element to string format and adds it to the output buffer + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_tsig(ldns_buffer *output, const ldns_rdf *rdf); + + +/** + * Converts the data in the rdata field to presentation + * format (as char *) and appends it to the given buffer + * + * \param[in] output pointer to the buffer to append the data to + * \param[in] rdf the pointer to the rdafa field containing the data + * \return status + */ +ldns_status ldns_rdf2buffer_str(ldns_buffer *output, const ldns_rdf *rdf); + +/** + * Converts the data in the resource record to presentation + * format (as char *) and appends it to the given buffer. + * The presentation format of DNSKEY record is annotated with comments giving + * the id, type and size of the key. + * + * \param[in] output pointer to the buffer to append the data to + * \param[in] rr the pointer to the rr field to convert + * \return status + */ +ldns_status ldns_rr2buffer_str(ldns_buffer *output, const ldns_rr *rr); + +/** + * Converts the data in the resource record to presentation + * format (as char *) and appends it to the given buffer. + * The presentation format is annotated with comments giving + * additional information on the record. + * + * \param[in] output pointer to the buffer to append the data to + * \param[in] fmt how to format the textual representation of the + * resource record. + * \param[in] rr the pointer to the rr field to convert + * \return status + */ +ldns_status ldns_rr2buffer_str_fmt(ldns_buffer *output, + const ldns_output_format *fmt, const ldns_rr *rr); + +/** + * Converts the data in the DNS packet to presentation + * format (as char *) and appends it to the given buffer + * + * \param[in] output pointer to the buffer to append the data to + * \param[in] pkt the pointer to the packet to convert + * \return status + */ +ldns_status ldns_pkt2buffer_str(ldns_buffer *output, const ldns_pkt *pkt); + +/** + * Converts the data in the DNS packet to presentation + * format (as char *) and appends it to the given buffer + * + * \param[in] output pointer to the buffer to append the data to + * \param[in] fmt how to format the textual representation of the packet + * \param[in] pkt the pointer to the packet to convert + * \return status + */ +ldns_status ldns_pkt2buffer_str_fmt(ldns_buffer *output, + const ldns_output_format *fmt, const ldns_pkt *pkt); + +/** + * Converts an LDNS_RDF_TYPE_NSEC3_SALT rdata element to string format and adds it to the output buffer + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_nsec3_salt(ldns_buffer *output, const ldns_rdf *rdf); + + +/** + * Converts the data in the DNS packet to presentation + * format (as char *) and appends it to the given buffer + * + * \param[in] output pointer to the buffer to append the data to + * \param[in] k the pointer to the private key to convert + * \return status + */ +ldns_status ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k); + +/** + * Converts an LDNS_RDF_TYPE_INT8 rdata element to string format and adds it to the output buffer + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_int8(ldns_buffer *output, const ldns_rdf *rdf); + +/** + * Converts an LDNS_RDF_TYPE_INT16 rdata element to string format and adds it to the output buffer + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_int16(ldns_buffer *output, const ldns_rdf *rdf); + +/** + * Converts an LDNS_RDF_TYPE_INT32 rdata element to string format and adds it to the output buffer + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_int32(ldns_buffer *output, const ldns_rdf *rdf); + +/** + * Converts an LDNS_RDF_TYPE_TIME rdata element to string format and adds it to the output buffer + * \param[in] *rdf The rdata to convert + * \param[in] *output The buffer to add the data to + * \return LDNS_STATUS_OK on success, and error status on failure + */ +ldns_status ldns_rdf2buffer_str_time(ldns_buffer *output, const ldns_rdf *rdf); + +/** + * Converts the data in the rdata field to presentation format and + * returns that as a char *. + * Remember to free it. + * + * \param[in] rdf The rdata field to convert + * \return null terminated char * data, or NULL on error + */ +char *ldns_rdf2str(const ldns_rdf *rdf); + +/** + * Converts the data in the resource record to presentation format and + * returns that as a char *. + * Remember to free it. + * + * \param[in] rr The rdata field to convert + * \return null terminated char * data, or NULL on error + */ +char *ldns_rr2str(const ldns_rr *rr); + +/** + * Converts the data in the resource record to presentation format and + * returns that as a char *. + * Remember to free it. + * + * \param[in] fmt how to format the resource record + * \param[in] rr The rdata field to convert + * \return null terminated char * data, or NULL on error + */ +char *ldns_rr2str_fmt(const ldns_output_format *fmt, const ldns_rr *rr); + +/** + * Converts the data in the DNS packet to presentation format and + * returns that as a char *. + * Remember to free it. + * + * \param[in] pkt The rdata field to convert + * \return null terminated char * data, or NULL on error + */ +char *ldns_pkt2str(const ldns_pkt *pkt); + +/** + * Converts the data in the DNS packet to presentation format and + * returns that as a char *. + * Remember to free it. + * + * \param[in] fmt how to format the packet + * \param[in] pkt The rdata field to convert + * \return null terminated char * data, or NULL on error + */ +char *ldns_pkt2str_fmt(const ldns_output_format *fmt, const ldns_pkt *pkt); + +/** + * Converts a private key to the test presentation fmt and + * returns that as a char *. + * Remember to free it. + * + * \param[in] k the key to convert to text + * \return null terminated char * data, or NULL on error + */ +char *ldns_key2str(const ldns_key *k); + +/** + * Converts a list of resource records to presentation format + * and returns that as a char *. + * Remember to free it. + * + * \param[in] rr_list the rr_list to convert to text + * \return null terminated char * data, or NULL on error + */ +char *ldns_rr_list2str(const ldns_rr_list *rr_list); + +/** + * Converts a list of resource records to presentation format + * and returns that as a char *. + * Remember to free it. + * + * \param[in] fmt how to format the list of resource records + * \param[in] rr_list the rr_list to convert to text + * \return null terminated char * data, or NULL on error + */ +char *ldns_rr_list2str_fmt( + const ldns_output_format *fmt, const ldns_rr_list *rr_list); + +/** + * Returns the data in the buffer as a null terminated char * string + * Buffer data must be char * type, and must be freed by the caller + * + * \param[in] buffer buffer containing char * data + * \return null terminated char * data, or NULL on error + */ +char *ldns_buffer2str(ldns_buffer *buffer); + +/** + * Prints the data in the rdata field to the given file stream + * (in presentation format) + * + * \param[in] output the file stream to print to + * \param[in] rdf the rdata field to print + * \return void + */ +void ldns_rdf_print(FILE *output, const ldns_rdf *rdf); + +/** + * Prints the data in the resource record to the given file stream + * (in presentation format) + * + * \param[in] output the file stream to print to + * \param[in] rr the resource record to print + * \return void + */ +void ldns_rr_print(FILE *output, const ldns_rr *rr); + +/** + * Prints the data in the resource record to the given file stream + * (in presentation format) + * + * \param[in] output the file stream to print to + * \param[in] fmt format of the textual representation + * \param[in] rr the resource record to print + * \return void + */ +void ldns_rr_print_fmt(FILE *output, + const ldns_output_format *fmt, const ldns_rr *rr); + +/** + * Prints the data in the DNS packet to the given file stream + * (in presentation format) + * + * \param[in] output the file stream to print to + * \param[in] pkt the packet to print + * \return void + */ +void ldns_pkt_print(FILE *output, const ldns_pkt *pkt); + +/** + * Prints the data in the DNS packet to the given file stream + * (in presentation format) + * + * \param[in] output the file stream to print to + * \param[in] fmt format of the textual representation + * \param[in] pkt the packet to print + * \return void + */ +void ldns_pkt_print_fmt(FILE *output, + const ldns_output_format *fmt, const ldns_pkt *pkt); + +/** + * Converts a rr_list to presentation format and appends it to + * the output buffer + * \param[in] output the buffer to append output to + * \param[in] list the ldns_rr_list to print + * \return ldns_status + */ +ldns_status ldns_rr_list2buffer_str(ldns_buffer *output, const ldns_rr_list *list); + +/** + * Converts a rr_list to presentation format and appends it to + * the output buffer + * \param[in] output the buffer to append output to + * \param[in] fmt format of the textual representation + * \param[in] list the ldns_rr_list to print + * \return ldns_status + */ +ldns_status ldns_rr_list2buffer_str_fmt(ldns_buffer *output, + const ldns_output_format *fmt, const ldns_rr_list *list); + +/** + * Converts the header of a packet to presentation format and appends it to + * the output buffer + * \param[in] output the buffer to append output to + * \param[in] pkt the packet to convert the header of + * \return ldns_status + */ +ldns_status ldns_pktheader2buffer_str(ldns_buffer *output, const ldns_pkt *pkt); + +/** + * print a rr_list to output + * \param[in] output the fd to print to + * \param[in] list the rr_list to print + */ +void ldns_rr_list_print(FILE *output, const ldns_rr_list *list); + +/** + * print a rr_list to output + * \param[in] output the fd to print to + * \param[in] fmt format of the textual representation + * \param[in] list the rr_list to print + */ +void ldns_rr_list_print_fmt(FILE *output, + const ldns_output_format *fmt, const ldns_rr_list *list); + +/** + * Print a resolver (in sofar that is possible) state + * to output. + * \param[in] output the fd to print to + * \param[in] r the resolver to print + */ +void ldns_resolver_print(FILE *output, const ldns_resolver *r); + +/** + * Print a resolver (in sofar that is possible) state + * to output. + * \param[in] output the fd to print to + * \param[in] fmt format of the textual representation + * \param[in] r the resolver to print + */ +void ldns_resolver_print_fmt(FILE *output, + const ldns_output_format *fmt, const ldns_resolver *r); + +/** + * Print a zone structure * to output. Note the SOA record + * is included in this output + * \param[in] output the fd to print to + * \param[in] z the zone to print + */ +void ldns_zone_print(FILE *output, const ldns_zone *z); + +/** + * Print a zone structure * to output. Note the SOA record + * is included in this output + * \param[in] output the fd to print to + * \param[in] fmt format of the textual representation + * \param[in] z the zone to print + */ +void ldns_zone_print_fmt(FILE *output, + const ldns_output_format *fmt, const ldns_zone *z); + +/** + * Print the ldns_rdf containing a dname to the buffer + * \param[in] output the buffer to print to + * \param[in] dname the dname to print + * \return ldns_status message if the printing succeeded + */ +ldns_status ldns_rdf2buffer_str_dname(ldns_buffer *output, const ldns_rdf *dname); + +#ifdef __cplusplus +} +#endif + +#endif /* LDNS_HOST2STR_H */ diff --git a/ldns/host2wire.h b/ldns/host2wire.h new file mode 100644 index 00000000000..5eafe9ddc44 --- /dev/null +++ b/ldns/host2wire.h @@ -0,0 +1,164 @@ +/* + * host2wire.h - 2wire conversion routines + * + * a Net::DNS like library for C + * + * (c) NLnet Labs, 2005-2006 + * + * See the file LICENSE for the license + */ + +/** + * \file + * + * Contains all functions to translate the main structures to wire format + */ + +#ifndef LDNS_HOST2WIRE_H +#define LDNS_HOST2WIRE_H + +#include +#include +#include +#include +#include +#include +#include + +#include "ldns/util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Copies the dname data to the buffer in wire format + * \param[out] *buffer buffer to append the result to + * \param[in] *name rdata dname to convert + * \return ldns_status + */ +ldns_status ldns_dname2buffer_wire(ldns_buffer *buffer, const ldns_rdf *name); + +/** + * Copies the rdata data to the buffer in wire format + * \param[out] *output buffer to append the result to + * \param[in] *rdf rdata to convert + * \return ldns_status + */ +ldns_status ldns_rdf2buffer_wire(ldns_buffer *output, const ldns_rdf *rdf); + +/** + * Copies the rdata data to the buffer in wire format + * If the rdata is a dname, the letters will be lowercased + * during the conversion + * \param[out] *output buffer to append the result to + * \param[in] *rdf rdata to convert + * \return ldns_status + */ +ldns_status ldns_rdf2buffer_wire_canonical(ldns_buffer *output, + const ldns_rdf *rdf); + +/** + * Copies the rr data to the buffer in wire format + * \param[out] *output buffer to append the result to + * \param[in] *rr resource record to convert + * \param[in] section the section in the packet this rr is supposed to be in + * (to determine whether to add rdata or not) + * \return ldns_status + */ +ldns_status ldns_rr2buffer_wire(ldns_buffer *output, + const ldns_rr *rr, + int section); + +/** + * Copies the rr data to the buffer in wire format, in canonical format + * according to RFC3597 (every dname in rdata fields of RR's mentioned in + * that RFC will be lowercased) + * \param[out] *output buffer to append the result to + * \param[in] *rr resource record to convert + * \param[in] section the section in the packet this rr is supposed to be in + * (to determine whether to add rdata or not) + * \return ldns_status + */ +ldns_status ldns_rr2buffer_wire_canonical(ldns_buffer *output, + const ldns_rr *rr, + int section); + + +/** + * Converts a rrsig to wireformat BUT EXCLUDE the rrsig rdata + * This is needed in DNSSEC verification + * \param[out] output buffer to append the result to + * \param[in] sigrr signature rr to operate on + * \return ldns_status + */ +ldns_status ldns_rrsig2buffer_wire(ldns_buffer *output, const ldns_rr *sigrr); + +/** + * Converts an rr's rdata to wireformat, while excluding + * the ownername and all the stuff before the rdata. + * This is needed in DNSSEC keytag calculation, the ds + * calcalution from the key and maybe elsewhere. + * + * \param[out] *output buffer where to put the result + * \param[in] *rr rr to operate on + * \return ldns_status + */ +ldns_status ldns_rr_rdata2buffer_wire(ldns_buffer *output, const ldns_rr *rr); + +/** + * Copies the packet data to the buffer in wire format + * \param[out] *output buffer to append the result to + * \param[in] *pkt packet to convert + * \return ldns_status + */ +ldns_status ldns_pkt2buffer_wire(ldns_buffer *output, const ldns_pkt *pkt); + +/** + * Copies the rr_list data to the buffer in wire format + * \param[out] *output buffer to append the result to + * \param[in] *rrlist rr_list to to convert + * \return ldns_status + */ +ldns_status ldns_rr_list2buffer_wire(ldns_buffer *output, const ldns_rr_list *rrlist); + +/** + * Allocates an array of uint8_t at dest, and puts the wireformat of the + * given rdf in that array. The result_size value contains the + * length of the array, if it succeeds, and 0 otherwise (in which case + * the function also returns NULL) + * + * \param[out] dest pointer to the array of bytes to be created + * \param[in] rdf the rdata field to convert + * \param[out] size the size of the converted result + */ +ldns_status ldns_rdf2wire(uint8_t **dest, const ldns_rdf *rdf, size_t *size); + +/** + * Allocates an array of uint8_t at dest, and puts the wireformat of the + * given rr in that array. The result_size value contains the + * length of the array, if it succeeds, and 0 otherwise (in which case + * the function also returns NULL) + * + * If the section argument is LDNS_SECTION_QUESTION, data like ttl and rdata + * are not put into the result + * + * \param[out] dest pointer to the array of bytes to be created + * \param[in] rr the rr to convert + * \param[out] size the size of the converted result + */ +ldns_status ldns_rr2wire(uint8_t **dest, const ldns_rr *rr, int, size_t *size); + +/** + * Allocates an array of uint8_t at dest, and puts the wireformat of the + * given packet in that array. The result_size value contains the + * length of the array, if it succeeds, and 0 otherwise (in which case + * the function also returns NULL) + */ +ldns_status ldns_pkt2wire(uint8_t **dest, const ldns_pkt *p, size_t *size); + +#ifdef __cplusplus +} +#endif + +#endif /* LDNS_HOST2WIRE_H */ diff --git a/ldns/keys.h b/ldns/keys.h new file mode 100644 index 00000000000..c4bf536911f --- /dev/null +++ b/ldns/keys.h @@ -0,0 +1,603 @@ +/* + * + * keys.h + * + * priv key definitions + * + * a Net::DNS like library for C + * + * (c) NLnet Labs, 2005-2006 + * + * See the file LICENSE for the license + */ + +/** + * \file + * + * Addendum to \ref dnssec.h, this module contains key and algorithm definitions and functions. + */ + + +#ifndef LDNS_KEYS_H +#define LDNS_KEYS_H + +#include +#if LDNS_BUILD_CONFIG_HAVE_SSL +#include +#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern ldns_lookup_table ldns_signing_algorithms[]; + +#define LDNS_KEY_ZONE_KEY 0x0100 /* rfc 4034 */ +#define LDNS_KEY_SEP_KEY 0x0001 /* rfc 4034 */ +#define LDNS_KEY_REVOKE_KEY 0x0080 /* rfc 5011 */ + +/** + * Algorithms used in dns + */ +enum ldns_enum_algorithm +{ + LDNS_RSAMD5 = 1, /* RFC 4034,4035 */ + LDNS_DH = 2, + LDNS_DSA = 3, + LDNS_ECC = 4, + LDNS_RSASHA1 = 5, + LDNS_DSA_NSEC3 = 6, + LDNS_RSASHA1_NSEC3 = 7, + LDNS_RSASHA256 = 8, /* RFC 5702 */ + LDNS_RSASHA512 = 10, /* RFC 5702 */ + LDNS_ECC_GOST = 12, /* RFC 5933 */ + LDNS_ECDSAP256SHA256 = 13, /* RFC 6605 */ + LDNS_ECDSAP384SHA384 = 14, /* RFC 6605 */ + LDNS_INDIRECT = 252, + LDNS_PRIVATEDNS = 253, + LDNS_PRIVATEOID = 254 +}; +typedef enum ldns_enum_algorithm ldns_algorithm; + +/** + * Hashing algorithms used in the DS record + */ +enum ldns_enum_hash +{ + LDNS_SHA1 = 1, /* RFC 4034 */ + LDNS_SHA256 = 2, /* RFC 4509 */ + LDNS_HASH_GOST = 3, /* RFC 5933 */ + LDNS_SHA384 = 4 /* RFC 6605 */ +}; +typedef enum ldns_enum_hash ldns_hash; + +/** + * Algorithms used in dns for signing + */ +enum ldns_enum_signing_algorithm +{ + LDNS_SIGN_RSAMD5 = LDNS_RSAMD5, + LDNS_SIGN_RSASHA1 = LDNS_RSASHA1, + LDNS_SIGN_DSA = LDNS_DSA, + LDNS_SIGN_RSASHA1_NSEC3 = LDNS_RSASHA1_NSEC3, + LDNS_SIGN_RSASHA256 = LDNS_RSASHA256, + LDNS_SIGN_RSASHA512 = LDNS_RSASHA512, + LDNS_SIGN_DSA_NSEC3 = LDNS_DSA_NSEC3, + LDNS_SIGN_ECC_GOST = LDNS_ECC_GOST, + LDNS_SIGN_ECDSAP256SHA256 = LDNS_ECDSAP256SHA256, + LDNS_SIGN_ECDSAP384SHA384 = LDNS_ECDSAP384SHA384, + LDNS_SIGN_HMACMD5 = 157, /* not official! This type is for TSIG, not DNSSEC */ + LDNS_SIGN_HMACSHA1 = 158, /* not official! This type is for TSIG, not DNSSEC */ + LDNS_SIGN_HMACSHA256 = 159 /* ditto */ +}; +typedef enum ldns_enum_signing_algorithm ldns_signing_algorithm; + +/** + * General key structure, can contain all types of keys that + * are used in DNSSEC. Mostly used to store private keys, since + * public keys can also be stored in a \ref ldns_rr with type + * \ref LDNS_RR_TYPE_DNSKEY. + * + * This structure can also store some variables that influence the + * signatures generated by signing with this key, for instance the + * inception date. + */ +struct ldns_struct_key { + ldns_signing_algorithm _alg; + /** Whether to use this key when signing */ + bool _use; + /** Storage pointers for the types of keys supported */ + /* TODO remove unions? */ + struct { +#if LDNS_BUILD_CONFIG_HAVE_SSL +#ifndef S_SPLINT_S + /* The key can be an OpenSSL EVP Key + */ + EVP_PKEY *key; +#endif +#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ + /** + * The key can be an HMAC key + */ + struct { + unsigned char *key; + size_t size; + } hmac; + /** the key structure can also just point to some external + * key data + */ + void *external_key; + } _key; + /** Depending on the key we can have extra data */ + union { + /** Some values that influence generated signatures */ + struct { + /** The TTL of the rrset that is currently signed */ + uint32_t orig_ttl; + /** The inception date of signatures made with this key. */ + uint32_t inception; + /** The expiration date of signatures made with this key. */ + uint32_t expiration; + /** The keytag of this key. */ + uint16_t keytag; + /** The dnssec key flags as specified in RFC4035, like ZSK and KSK */ + uint16_t flags; + } dnssec; + } _extra; + /** Owner name of the key */ + ldns_rdf *_pubkey_owner; +}; +typedef struct ldns_struct_key ldns_key; + +/** + * Same as rr_list, but now for keys + */ +struct ldns_struct_key_list +{ + size_t _key_count; + ldns_key **_keys; +}; +typedef struct ldns_struct_key_list ldns_key_list; + + +/** + * Creates a new empty key list + * \return a new ldns_key_list structure pointer + */ +ldns_key_list *ldns_key_list_new(); + +/** + * Creates a new empty key structure + * \return a new ldns_key * structure + */ +ldns_key *ldns_key_new(); + +/** + * Creates a new key based on the algorithm + * + * \param[in] a The algorithm to use + * \param[in] size the number of bytes for the keysize + * \return a new ldns_key structure with the key + */ +ldns_key *ldns_key_new_frm_algorithm(ldns_signing_algorithm a, uint16_t size); + +/** + * Creates a new priv key based on the + * contents of the file pointed by fp. + * + * The file should be in Private-key-format v1.x. + * + * \param[out] k the new ldns_key structure + * \param[in] fp the file pointer to use + * \return an error or LDNS_STATUS_OK + */ +ldns_status ldns_key_new_frm_fp(ldns_key **k, FILE *fp); + +/** + * Creates a new private key based on the + * contents of the file pointed by fp + * + * The file should be in Private-key-format v1.x. + * + * \param[out] k the new ldns_key structure + * \param[in] fp the file pointer to use + * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes) + * \return an error or LDNS_STATUS_OK + */ +ldns_status ldns_key_new_frm_fp_l(ldns_key **k, FILE *fp, int *line_nr); + +#if LDNS_BUILD_CONFIG_HAVE_SSL +/** + * Read the key with the given id from the given engine and store it + * in the given ldns_key structure. The algorithm type is set + */ +ldns_status ldns_key_new_frm_engine(ldns_key **key, ENGINE *e, char *key_id, ldns_algorithm); + + +/** + * frm_fp helper function. This function parses the + * remainder of the (RSA) priv. key file generated from bind9 + * \param[in] fp the file to parse + * \return NULL on failure otherwise a RSA structure + */ +RSA *ldns_key_new_frm_fp_rsa(FILE *fp); +#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ + +#if LDNS_BUILD_CONFIG_HAVE_SSL +/** + * frm_fp helper function. This function parses the + * remainder of the (RSA) priv. key file generated from bind9 + * \param[in] fp the file to parse + * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes) + * \return NULL on failure otherwise a RSA structure + */ +RSA *ldns_key_new_frm_fp_rsa_l(FILE *fp, int *line_nr); +#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ + +#if LDNS_BUILD_CONFIG_HAVE_SSL +/** + * frm_fp helper function. This function parses the + * remainder of the (DSA) priv. key file + * \param[in] fp the file to parse + * \return NULL on failure otherwise a RSA structure + */ +DSA *ldns_key_new_frm_fp_dsa(FILE *fp); +#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ + +#if LDNS_BUILD_CONFIG_HAVE_SSL +/** + * frm_fp helper function. This function parses the + * remainder of the (DSA) priv. key file + * \param[in] fp the file to parse + * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes) + * \return NULL on failure otherwise a RSA structure + */ +DSA *ldns_key_new_frm_fp_dsa_l(FILE *fp, int *line_nr); +#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ + +#if LDNS_BUILD_CONFIG_HAVE_SSL +/** + * frm_fp helper function. This function parses the + * remainder of the (HMAC-MD5) key file + * This function allocated a buffer that needs to be freed + * \param[in] fp the file to parse + * \param[out] hmac_size the number of bits in the resulting buffer + * \return NULL on failure otherwise a newly allocated char buffer + */ +unsigned char *ldns_key_new_frm_fp_hmac(FILE *fp, size_t *hmac_size); +#endif + +#if LDNS_BUILD_CONFIG_HAVE_SSL +/** + * frm_fp helper function. This function parses the + * remainder of the (HMAC-MD5) key file + * This function allocated a buffer that needs to be freed + * \param[in] fp the file to parse + * \param[in] line_nr pointer to an integer containing the current line number (for error reporting purposes) + * \param[out] hmac_size the number of bits in the resulting buffer + * \return NULL on failure otherwise a newly allocated char buffer + */ +unsigned char *ldns_key_new_frm_fp_hmac_l(FILE *fp, int *line_nr, size_t *hmac_size); +#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ + +/* acces write functions */ +/** + * Set the key's algorithm + * \param[in] k the key + * \param[in] l the algorithm + */ +void ldns_key_set_algorithm(ldns_key *k, ldns_signing_algorithm l); +#if LDNS_BUILD_CONFIG_HAVE_SSL +/** + * Set the key's evp key + * \param[in] k the key + * \param[in] e the evp key + */ +void ldns_key_set_evp_key(ldns_key *k, EVP_PKEY *e); + +/** + * Set the key's rsa data + * \param[in] k the key + * \param[in] r the rsa data + */ +void ldns_key_set_rsa_key(ldns_key *k, RSA *r); +/** + * Set the key's dsa data + * \param[in] k the key + * \param[in] d the dsa data + */ +void ldns_key_set_dsa_key(ldns_key *k, DSA *d); + +/** + * Get the PKEY id for GOST, loads GOST into openssl as a side effect. + * Only available if GOST is compiled into the library and openssl. + * \return the gost id for EVP_CTX creation. + */ +int ldns_key_EVP_load_gost_id(void); + +/** Release the engine reference held for the GOST engine. */ +void ldns_key_EVP_unload_gost(void); +#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ + +/** + * Set the key's hmac data + * \param[in] k the key + * \param[in] hmac the raw key data + */ +void ldns_key_set_hmac_key(ldns_key *k, unsigned char *hmac); + +/** + * Set the key id data. This is used if the key points to + * some externally stored key data + * + * Only the pointer is set, the data there is not copied, + * and must be freed manually; ldns_key_deep_free() does + * *not* free this data + * \param[in] key the key + * \param[in] external_key key id data + */ +void ldns_key_set_external_key(ldns_key *key, void *external_key); + +/** + * Set the key's hmac size + * \param[in] k the key + * \param[in] hmac_size the size of the hmac data + */ +void ldns_key_set_hmac_size(ldns_key *k, size_t hmac_size); +/** + * Set the key's original ttl + * \param[in] k the key + * \param[in] t the ttl + */ +void ldns_key_set_origttl(ldns_key *k, uint32_t t); +/** + * Set the key's inception date (seconds after epoch) + * \param[in] k the key + * \param[in] i the inception + */ +void ldns_key_set_inception(ldns_key *k, uint32_t i); +/** + * Set the key's expiration date (seconds after epoch) + * \param[in] k the key + * \param[in] e the expiration + */ +void ldns_key_set_expiration(ldns_key *k, uint32_t e); +/** + * Set the key's pubkey owner + * \param[in] k the key + * \param[in] r the owner + */ +void ldns_key_set_pubkey_owner(ldns_key *k, ldns_rdf *r); +/** + * Set the key's key tag + * \param[in] k the key + * \param[in] tag the keytag + */ +void ldns_key_set_keytag(ldns_key *k, uint16_t tag); +/** + * Set the key's flags + * \param[in] k the key + * \param[in] flags the flags + */ +void ldns_key_set_flags(ldns_key *k, uint16_t flags); +/** + * Set the keylist's key count to count + * \param[in] key the key + * \param[in] count the cuont + */ +void ldns_key_list_set_key_count(ldns_key_list *key, size_t count); + +/** + * pushes a key to a keylist + * \param[in] key_list the key_list to push to + * \param[in] key the key to push + * \return false on error, otherwise true + */ +bool ldns_key_list_push_key(ldns_key_list *key_list, ldns_key *key); + +/** + * returns the number of keys in the key list + * \param[in] key_list the key_list + * \return the numbers of keys in the list + */ +size_t ldns_key_list_key_count(const ldns_key_list *key_list); + +/** + * returns a pointer to the key in the list at the given position + * \param[in] key the key + * \param[in] nr the position in the list + * \return the key + */ +ldns_key *ldns_key_list_key(const ldns_key_list *key, size_t nr); + +#if LDNS_BUILD_CONFIG_HAVE_SSL +/** + * returns the (openssl) RSA struct contained in the key + * \param[in] k the key to look in + * \return the RSA * structure in the key + */ +RSA *ldns_key_rsa_key(const ldns_key *k); +/** + * returns the (openssl) EVP struct contained in the key + * \param[in] k the key to look in + * \return the RSA * structure in the key + */ +EVP_PKEY *ldns_key_evp_key(const ldns_key *k); +#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ + +/** + * returns the (openssl) DSA struct contained in the key + */ +#if LDNS_BUILD_CONFIG_HAVE_SSL +DSA *ldns_key_dsa_key(const ldns_key *k); +#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ + +/** + * return the signing alg of the key + * \param[in] k the key + * \return the algorithm + */ +ldns_signing_algorithm ldns_key_algorithm(const ldns_key *k); +/** + * set the use flag + * \param[in] k the key + * \param[in] v the boolean value to set the _use field to + */ +void ldns_key_set_use(ldns_key *k, bool v); +/** + * return the use flag + * \param[in] k the key + * \return the boolean value of the _use field + */ +bool ldns_key_use(const ldns_key *k); +/** + * return the hmac key data + * \param[in] k the key + * \return the hmac key data + */ +unsigned char *ldns_key_hmac_key(const ldns_key *k); +/** + * return the key id key data + * \param[in] k the key + * \return the key id data + */ +void *ldns_key_external_key(const ldns_key *k); +/** + * return the hmac key size + * \param[in] k the key + * \return the hmac key size + */ +size_t ldns_key_hmac_size(const ldns_key *k); +/** + * return the original ttl of the key + * \param[in] k the key + * \return the original ttl + */ +uint32_t ldns_key_origttl(const ldns_key *k); +/** + * return the key's inception date + * \param[in] k the key + * \return the inception date + */ +uint32_t ldns_key_inception(const ldns_key *k); +/** + * return the key's expiration date + * \param[in] k the key + * \return the experiration date + */ +uint32_t ldns_key_expiration(const ldns_key *k); +/** + * return the keytag + * \param[in] k the key + * \return the keytag + */ +uint16_t ldns_key_keytag(const ldns_key *k); +/** + * return the public key's owner + * \param[in] k the key + * \return the owner + */ +ldns_rdf *ldns_key_pubkey_owner(const ldns_key *k); +/** + * Set the 'use' flag for all keys in the list + * \param[in] keys The key_list + * \param[in] v The value to set the use flags to + */ +void +ldns_key_list_set_use(ldns_key_list *keys, bool v); + +/** + * return the flag of the key + * \param[in] k the key + * \return the flag + */ +uint16_t ldns_key_flags(const ldns_key *k); + +/** + * pops the last rr from a keylist + * \param[in] key_list the rr_list to pop from + * \return NULL if nothing to pop. Otherwise the popped RR + */ +ldns_key *ldns_key_list_pop_key(ldns_key_list *key_list); + +/** + * converts a ldns_key to a public key rr + * If the key data exists at an external point, the corresponding + * rdata field must still be added with ldns_rr_rdf_push() to the + * result rr of this function + * + * \param[in] k the ldns_key to convert + * \return ldns_rr representation of the key + */ +ldns_rr *ldns_key2rr(const ldns_key *k); + +/** + * print a private key to the file ouput + * + * \param[in] output the FILE descriptor where to print to + * \param[in] k the ldns_key to print + */ +void ldns_key_print(FILE *output, const ldns_key *k); + +/** + * frees a key structure, but not its internal data structures + * + * \param[in] key the key object to free + */ +void ldns_key_free(ldns_key *key); + +/** + * frees a key structure and all its internal data structures, except + * the data set by ldns_key_set_external_key() + * + * \param[in] key the key object to free + */ +void ldns_key_deep_free(ldns_key *key); + +/** + * Frees a key list structure + * \param[in] key_list the key list object to free + */ +void ldns_key_list_free(ldns_key_list *key_list); + +/** + * Instantiates a DNSKEY or DS RR from file. + * \param[in] filename the file to read the record from + * \return the corresponding RR, or NULL if the parsing failed + */ +ldns_rr * ldns_read_anchor_file(const char *filename); + +/** + * Returns the 'default base name' for key files; + * IE. K\+\+\ + * (without the .key or .private) + * The memory for this is allocated by this function, + * and should be freed by the caller + * + * \param[in] key the key to get the file name from + * \returns A string containing the file base name + */ +char *ldns_key_get_file_base_name(ldns_key *key); + +/** + * See if a key algorithm is supported + * \param[in] algo the signing algorithm number. + * \returns true if supported. + */ +int ldns_key_algo_supported(int algo); + +/** + * Get signing algorithm by name. Comparison is case insensitive. + * \param[in] name string with the name. + * \returns 0 on parse failure or the algorithm number. + */ +ldns_signing_algorithm ldns_get_signing_algorithm_by_name(const char* name); + +#ifdef __cplusplus +} +#endif + +#endif /* LDNS_KEYS_H */ diff --git a/ldns/ldns.h b/ldns/ldns.h new file mode 100644 index 00000000000..79152543348 --- /dev/null +++ b/ldns/ldns.h @@ -0,0 +1,156 @@ +/* + * dns.h -- defines for the Domain Name System + * + * Copyright (c) 2005-2008, NLnet Labs. All rights reserved. + * + * See LICENSE for the license. + * + * This library was created by: + * Jelte Jansen, Erik Rozendaal and Miek Gieben + * + * A bunch of defines that are used in the DNS. + */ + + +/** +\mainpage LDNS Documentation + +\section introduction Introduction + +The goal of ldns is to simplify DNS programming, it supports recent RFCs +like the DNSSEC documents, and allow developers to easily create software +conforming to current RFCs, and experimental software for current Internet +drafts. A secondary benefit of using ldns is speed, because ldns is written +in C, and although it is not optimized for performance, it should be a lot +faster than Perl. + +The first main tool to use ldns is Drill, from which part of the library was +derived. From version 1.0.0 on, drill is included in the ldns release +and will not be distributed seperately anymore. The library also includes some +other examples and tools to show how it can be used. These can be found in the +examples/ directory in the tarball. + +ldns depends on OpenSSL for it's cryptographic functions. +Feature list + + - Transparent IPv4 and IPv6 support (overridable if necessary), + - TSIG support, + - DNSSEC support; signing and verification, + - small size, + - online documentation as well as manual pages. + +If you want to send us patches please use the code from subversion (trunk). + +\section using_ldns Using ldns + +Almost all interaction between an application and ldns goes through the ldns +data structures (\ref ldns_rr, \ref ldns_pkt, etc.). These are input or +output to the functions of ldns. For example, \ref ldns_zone_new_frm_fp +reads a zone from a \c FILE pointer, and returns an \ref ldns_zone +structure. + + +Let's use Drill as an example. Drill is a tool much like dig, whose most +basic function is to send 1 query to a nameserver and print the response. + +To be able to do this, drill uses the resolver module of ldns, which acts as +a stub resolver. The resolver module uses the net module to actually send +the query that drill requested. It then uses the wire2host module to +translate the response and place it in ldns' internal structures. These are +passed back to drill, which then uses the host2str module to print the +response in presentation format. + +\section gettingstarted Getting Started + +See the \ref design page for a very high level description of the design +choices made for ldns. + +For an overview of the functions and types ldns provides, you can check out +the \ref ldns ldns header file descriptions. + +If you want to see some libdns action, you can read our tutorials: + - \ref tutorial1_mx + - \ref tutorial2_zone + - \ref tutorial3_signzone + +Or you can just use the menu above to browse through the API docs. + +
+\image html LogoInGradientBar2-y100.png +
+*/ + +/** + * \file ldns.h + * + * Including this file will include all ldns files, and define some lookup tables. + */ + +#ifndef LDNS_DNS_H +#define LDNS_DNS_H + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define LDNS_IP4ADDRLEN (32/8) +#define LDNS_IP6ADDRLEN (128/8) +#define LDNS_PORT 53 +#define LDNS_ROOT_LABEL_STR "." +#define LDNS_DEFAULT_TTL 3600 + +/* lookup tables for standard DNS stuff */ + +/** Taken from RFC 2538, section 2.1. */ +extern ldns_lookup_table ldns_certificate_types[]; +/** Taken from RFC 2535, section 7. */ +extern ldns_lookup_table ldns_algorithms[]; +/** Taken from RFC 2538. */ +extern ldns_lookup_table ldns_cert_algorithms[]; +/** rr types */ +extern ldns_lookup_table ldns_rr_classes[]; +/** Response codes */ +extern ldns_lookup_table ldns_rcodes[]; +/** Operation codes */ +extern ldns_lookup_table ldns_opcodes[]; +/** EDNS flags */ +extern ldns_lookup_table ldns_edns_flags[]; + +#ifdef __cplusplus +} +#endif + +#endif /* LDNS_DNS_H */ diff --git a/ldns/net.h.in b/ldns/net.h.in new file mode 100644 index 00000000000..cd4cfdec9c6 --- /dev/null +++ b/ldns/net.h.in @@ -0,0 +1,208 @@ +/* + * net.h + * + * DNS Resolver definitions + * + * a Net::DNS like library for C + * + * (c) NLnet Labs, 2005-2006 + * + * See the file LICENSE for the license + */ + +#ifndef LDNS_NET_H +#define LDNS_NET_H + +#include +@include_sys_socket_h@ + +#ifdef __cplusplus +extern "C" { +#endif + +#define LDNS_DEFAULT_TIMEOUT_SEC 5 +#define LDNS_DEFAULT_TIMEOUT_USEC 0 + +/** + * \file + * + * Contains functions to send and receive packets over a network. + */ + +/** + * Sends a buffer to an ip using udp and return the respons as a ldns_pkt + * \param[in] qbin the ldns_buffer to be send + * \param[in] to the ip addr to send to + * \param[in] tolen length of the ip addr + * \param[in] timeout the timeout value for the network + * \param[out] answersize size of the packet + * \param[out] result packet with the answer + * \return status + */ +ldns_status ldns_udp_send(uint8_t **result, ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout, size_t *answersize); + +/** + * Send an udp query and don't wait for an answer but return + * the socket + * \param[in] qbin the ldns_buffer to be send + * \param[in] to the ip addr to send to + * \param[in] tolen length of the ip addr + * \param[in] timeout *unused*, was the timeout value for the network + * \return the socket used + */ + +int ldns_udp_bgsend(ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout); + +/** + * Send an tcp query and don't wait for an answer but return + * the socket + * \param[in] qbin the ldns_buffer to be send + * \param[in] to the ip addr to send to + * \param[in] tolen length of the ip addr + * \param[in] timeout the timeout value for the connect attempt + * \return the socket used + */ +int ldns_tcp_bgsend(ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout); + +/** + * Sends a buffer to an ip using tcp and return the respons as a ldns_pkt + * \param[in] qbin the ldns_buffer to be send + * \param[in] qbin the ldns_buffer to be send + * \param[in] to the ip addr to send to + * \param[in] tolen length of the ip addr + * \param[in] timeout the timeout value for the network + * \param[out] answersize size of the packet + * \param[out] result packet with the answer + * \return status + */ +ldns_status ldns_tcp_send(uint8_t **result, ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout, size_t *answersize); + +/** + * Sends ptk to the nameserver at the resolver object. Returns the data + * as a ldns_pkt + * + * \param[out] pkt packet received from the nameserver + * \param[in] r the resolver to use + * \param[in] query_pkt the query to send + * \return status + */ +ldns_status ldns_send(ldns_pkt **pkt, ldns_resolver *r, const ldns_pkt *query_pkt); + +/** + * Sends and ldns_buffer (presumably containing a packet to the nameserver at the resolver object. Returns the data + * as a ldns_pkt + * + * \param[out] pkt packet received from the nameserver + * \param[in] r the resolver to use + * \param[in] qb the buffer to send + * \param[in] tsig_mac the tsig MAC to authenticate the response with (NULL to do no TSIG authentication) + * \return status + */ +ldns_status ldns_send_buffer(ldns_pkt **pkt, ldns_resolver *r, ldns_buffer *qb, ldns_rdf *tsig_mac); + +/** + * Create a tcp socket to the specified address + * \param[in] to ip and family + * \param[in] tolen length of to + * \param[in] timeout timeout for the connect attempt + * \return a socket descriptor + */ +int ldns_tcp_connect(const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout); + +/** + * Create a udp socket to the specified address + * \param[in] to ip and family + * \param[in] timeout *unused*, was timeout for the socket + * \return a socket descriptor + */ +int ldns_udp_connect(const struct sockaddr_storage *to, struct timeval timeout); + +/** + * send a query via tcp to a server. Don't want for the answer + * + * \param[in] qbin the buffer to send + * \param[in] sockfd the socket to use + * \param[in] to which ip to send it + * \param[in] tolen socketlen + * \return number of bytes sent + */ +ssize_t ldns_tcp_send_query(ldns_buffer *qbin, int sockfd, const struct sockaddr_storage *to, socklen_t tolen); + +/** + * send a query via udp to a server. Don;t want for the answer + * + * \param[in] qbin the buffer to send + * \param[in] sockfd the socket to use + * \param[in] to which ip to send it + * \param[in] tolen socketlen + * \return number of bytes sent + */ +ssize_t ldns_udp_send_query(ldns_buffer *qbin, int sockfd, const struct sockaddr_storage *to, socklen_t tolen); + +/** + * Gives back a raw packet from the wire and reads the header data from the given + * socket. Allocates the data (of size size) itself, so don't forget to free + * + * \param[in] sockfd the socket to read from + * \param[out] size the number of bytes that are read + * \param[in] timeout the time allowed between packets. + * \return the data read + */ +uint8_t *ldns_tcp_read_wire_timeout(int sockfd, size_t *size, struct timeval timeout); + +/** + * This routine may block. Use ldns_tcp_read_wire_timeout, it checks timeouts. + * Gives back a raw packet from the wire and reads the header data from the given + * socket. Allocates the data (of size size) itself, so don't forget to free + * + * \param[in] sockfd the socket to read from + * \param[out] size the number of bytes that are read + * \return the data read + */ +uint8_t *ldns_tcp_read_wire(int sockfd, size_t *size); + +/** + * Gives back a raw packet from the wire and reads the header data from the given + * socket. Allocates the data (of size size) itself, so don't forget to free + * + * \param[in] sockfd the socket to read from + * \param[in] fr the address of the client (if applicable) + * \param[in] *frlen the lenght of the client's addr (if applicable) + * \param[out] size the number of bytes that are read + * \return the data read + */ +uint8_t *ldns_udp_read_wire(int sockfd, size_t *size, struct sockaddr_storage *fr, socklen_t *frlen); + +/** + * returns the native sockaddr representation from the rdf. + * \param[in] rd the ldns_rdf to operate on + * \param[in] port what port to use. 0 means; use default (53) + * \param[out] size what is the size of the sockaddr_storage + * \return struct sockaddr* the address in the format so other + * functions can use it (sendto) + */ +struct sockaddr_storage * ldns_rdf2native_sockaddr_storage(const ldns_rdf *rd, uint16_t port, size_t *size); + +/** + * returns an rdf with the sockaddr info. works for ip4 and ip6 + * \param[in] sock the struct sockaddr_storage to convert + * \param[in] port what port was used. When NULL this is not set + * \return ldns_rdf* wth the address + */ +ldns_rdf * ldns_sockaddr_storage2rdf(struct sockaddr_storage *sock, uint16_t *port); + +/** + * Prepares the resolver for an axfr query + * The query is sent and the answers can be read with ldns_axfr_next + * \param[in] resolver the resolver to use + * \param[in] domain the domain to exfr + * \param[in] c the class to use + * \return ldns_status the status of the transfer + */ +ldns_status ldns_axfr_start(ldns_resolver *resolver, ldns_rdf *domain, ldns_rr_class c); + +#ifdef __cplusplus +} +#endif + +#endif /* LDNS_NET_H */ diff --git a/ldns/packet.h b/ldns/packet.h new file mode 100644 index 00000000000..687a6a25957 --- /dev/null +++ b/ldns/packet.h @@ -0,0 +1,855 @@ +/* + * packet.h + * + * DNS packet definitions + * + * a Net::DNS like library for C + * + * (c) NLnet Labs, 2005-2006 + * + * See the file LICENSE for the license + */ + +/** + * \file + * + * Contains the definition of ldns_pkt and its parts, as well + * as functions to manipulate those. + */ + + +#ifndef LDNS_PACKET_H +#define LDNS_PACKET_H + +#define LDNS_MAX_PACKETLEN 65535 + +/* allow flags to be given to mk_query */ +#define LDNS_QR 1 /* QueRy - query flag */ +#define LDNS_AA 2 /* Authoritative Answer - server flag */ +#define LDNS_TC 4 /* TrunCated - server flag */ +#define LDNS_RD 8 /* Recursion Desired - query flag */ +#define LDNS_CD 16 /* Checking Disabled - query flag */ +#define LDNS_RA 32 /* Recursion Available - server flag */ +#define LDNS_AD 64 /* Authenticated Data - server flag */ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* opcodes for pkt's */ +enum ldns_enum_pkt_opcode { + LDNS_PACKET_QUERY = 0, + LDNS_PACKET_IQUERY = 1, + LDNS_PACKET_STATUS = 2, /* there is no 3?? DNS is weird */ + LDNS_PACKET_NOTIFY = 4, + LDNS_PACKET_UPDATE = 5 +}; +typedef enum ldns_enum_pkt_opcode ldns_pkt_opcode; + +/* rcodes for pkts */ +enum ldns_enum_pkt_rcode { + LDNS_RCODE_NOERROR = 0, + LDNS_RCODE_FORMERR = 1, + LDNS_RCODE_SERVFAIL = 2, + LDNS_RCODE_NXDOMAIN = 3, + LDNS_RCODE_NOTIMPL = 4, + LDNS_RCODE_REFUSED = 5, + LDNS_RCODE_YXDOMAIN = 6, + LDNS_RCODE_YXRRSET = 7, + LDNS_RCODE_NXRRSET = 8, + LDNS_RCODE_NOTAUTH = 9, + LDNS_RCODE_NOTZONE = 10 +}; +typedef enum ldns_enum_pkt_rcode ldns_pkt_rcode; + +/** + * Header of a dns packet + * + * Contains the information about the packet itself, as specified in RFC1035 +
+4.1.1. Header section format
+
+The header contains the following fields:
+
+                                    1  1  1  1  1  1
+      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    |                      ID                       |
+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    |QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |
+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    |                    QDCOUNT                    |
+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    |                    ANCOUNT                    |
+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    |                    NSCOUNT                    |
+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    |                    ARCOUNT                    |
+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+ID              A 16 bit identifier assigned by the program that
+                generates any kind of query.  This identifier is copied
+                the corresponding reply and can be used by the requester
+                to match up replies to outstanding queries.
+
+QR              A one bit field that specifies whether this message is a
+                query (0), or a response (1).
+
+OPCODE          A four bit field that specifies kind of query in this
+                message.  This value is set by the originator of a query
+                and copied into the response.  The values are:
+
+                0               a standard query (QUERY)
+
+                1               an inverse query (IQUERY)
+
+                2               a server status request (STATUS)
+
+                3-15            reserved for future use
+
+AA              Authoritative Answer - this bit is valid in responses,
+                and specifies that the responding name server is an
+                authority for the domain name in question section.
+
+                Note that the contents of the answer section may have
+                multiple owner names because of aliases.  The AA bit
+
+                corresponds to the name which matches the query name, or
+                the first owner name in the answer section.
+
+TC              TrunCation - specifies that this message was truncated
+                due to length greater than that permitted on the
+                transmission channel.
+
+RD              Recursion Desired - this bit may be set in a query and
+                is copied into the response.  If RD is set, it directs
+                the name server to pursue the query recursively.
+                Recursive query support is optional.
+
+RA              Recursion Available - this be is set or cleared in a
+                response, and denotes whether recursive query support is
+                available in the name server.
+
+Z               Reserved for future use.  Must be zero in all queries
+                and responses.
+
+RCODE           Response code - this 4 bit field is set as part of
+                responses.  The values have the following
+                interpretation:
+
+                0               No error condition
+
+                1               Format error - The name server was
+                                unable to interpret the query.
+
+                2               Server failure - The name server was
+                                unable to process this query due to a
+                                problem with the name server.
+
+                3               Name Error - Meaningful only for
+                                responses from an authoritative name
+                                server, this code signifies that the
+                                domain name referenced in the query does
+                                not exist.
+
+                4               Not Implemented - The name server does
+                                not support the requested kind of query.
+
+                5               Refused - The name server refuses to
+                                perform the specified operation for
+                                policy reasons.  For example, a name
+                                server may not wish to provide the
+                                information to the particular requester,
+                                or a name server may not wish to perform
+                                a particular operation (e.g., zone
+
+                                transfer) for particular data.
+
+                6-15            Reserved for future use.
+
+QDCOUNT         an unsigned 16 bit integer specifying the number of
+                entries in the question section.
+
+ANCOUNT         an unsigned 16 bit integer specifying the number of
+                resource records in the answer section.
+
+NSCOUNT         an unsigned 16 bit integer specifying the number of name
+                server resource records in the authority records
+                section.
+
+ARCOUNT         an unsigned 16 bit integer specifying the number of
+                resource records in the additional records section.
+
+
+ */ +struct ldns_struct_hdr +{ + /** Id of a packet */ + uint16_t _id; + /** Query bit (0=query, 1=answer) */ + bool _qr; + /** Authoritative answer */ + bool _aa; + /** Packet truncated */ + bool _tc; + /** Recursion desired */ + bool _rd; + /** Checking disabled */ + bool _cd; + /** Recursion available */ + bool _ra; + /** Authentic data */ + bool _ad; + /** Query type */ + ldns_pkt_opcode _opcode; /* XXX 8 bits? */ + /** Response code */ + uint8_t _rcode; + /** question sec */ + uint16_t _qdcount; + /** answer sec */ + uint16_t _ancount; + /** auth sec */ + uint16_t _nscount; + /** add sec */ + uint16_t _arcount; +}; +typedef struct ldns_struct_hdr ldns_hdr; + +/** + * DNS packet + * + * This structure contains a complete DNS packet (either a query or an answer) + * + * It is the complete representation of what you actually send to a + * nameserver, and what it sends back (assuming you are the client here). + */ +struct ldns_struct_pkt +{ + /** Header section */ + ldns_hdr *_header; + /* extra items needed in a packet */ + /** The size of the wire format of the packet in octets */ + ldns_rdf *_answerfrom; + /** Timestamp of the time the packet was sent or created */ + struct timeval timestamp; + /** The duration of the query this packet is an answer to */ + uint32_t _querytime; + /** The size of the wire format of the packet in octets */ + size_t _size; + /** Optional tsig rr */ + ldns_rr *_tsig_rr; + /** EDNS0 available buffer size, see RFC2671 */ + uint16_t _edns_udp_size; + /** EDNS0 Extended rcode */ + uint8_t _edns_extended_rcode; + /** EDNS Version */ + uint8_t _edns_version; + /** Reserved EDNS data bits */ + uint16_t _edns_z; + /** Arbitrary EDNS rdata */ + ldns_rdf *_edns_data; + /** Question section */ + ldns_rr_list *_question; + /** Answer section */ + ldns_rr_list *_answer; + /** Authority section */ + ldns_rr_list *_authority; + /** Additional section */ + ldns_rr_list *_additional; +}; +typedef struct ldns_struct_pkt ldns_pkt; + +/** + * The sections of a packet + */ +enum ldns_enum_pkt_section { + LDNS_SECTION_QUESTION = 0, + LDNS_SECTION_ANSWER = 1, + LDNS_SECTION_AUTHORITY = 2, + LDNS_SECTION_ADDITIONAL = 3, + /** bogus section, if not interested */ + LDNS_SECTION_ANY = 4, + /** used to get all non-question rrs from a packet */ + LDNS_SECTION_ANY_NOQUESTION = 5 +}; +typedef enum ldns_enum_pkt_section ldns_pkt_section; + +/** + * The different types of packets + */ +enum ldns_enum_pkt_type { + LDNS_PACKET_QUESTION, + LDNS_PACKET_REFERRAL, + LDNS_PACKET_ANSWER, + LDNS_PACKET_NXDOMAIN, + LDNS_PACKET_NODATA, + LDNS_PACKET_UNKNOWN +}; +typedef enum ldns_enum_pkt_type ldns_pkt_type; + +/* prototypes */ + +/* read */ + +/** + * Read the packet id + * \param[in] p the packet + * \return the packet id + */ +uint16_t ldns_pkt_id(const ldns_pkt *p); +/** + * Read the packet's qr bit + * \param[in] p the packet + * \return value of the bit + */ +bool ldns_pkt_qr(const ldns_pkt *p); +/** + * Read the packet's aa bit + * \param[in] p the packet + * \return value of the bit + */ +bool ldns_pkt_aa(const ldns_pkt *p); +/** + * Read the packet's tc bit + * \param[in] p the packet + * \return value of the bit + */ +bool ldns_pkt_tc(const ldns_pkt *p); +/** + * Read the packet's rd bit + * \param[in] p the packet + * \return value of the bit + */ +bool ldns_pkt_rd(const ldns_pkt *p); +/** + * Read the packet's cd bit + * \param[in] p the packet + * \return value of the bit + */ +bool ldns_pkt_cd(const ldns_pkt *p); +/** + * Read the packet's ra bit + * \param[in] p the packet + * \return value of the bit + */ +bool ldns_pkt_ra(const ldns_pkt *p); +/** + * Read the packet's ad bit + * \param[in] p the packet + * \return value of the bit + */ +bool ldns_pkt_ad(const ldns_pkt *p); +/** + * Read the packet's code + * \param[in] p the packet + * \return the opcode + */ +ldns_pkt_opcode ldns_pkt_get_opcode(const ldns_pkt *p); +/** + * Return the packet's respons code + * \param[in] p the packet + * \return the respons code + */ +ldns_pkt_rcode ldns_pkt_get_rcode(const ldns_pkt *p); +/** + * Return the packet's qd count + * \param[in] p the packet + * \return the qd count + */ +uint16_t ldns_pkt_qdcount(const ldns_pkt *p); +/** + * Return the packet's an count + * \param[in] p the packet + * \return the an count + */ +uint16_t ldns_pkt_ancount(const ldns_pkt *p); +/** + * Return the packet's ns count + * \param[in] p the packet + * \return the ns count + */ +uint16_t ldns_pkt_nscount(const ldns_pkt *p); +/** + * Return the packet's ar count + * \param[in] p the packet + * \return the ar count + */ +uint16_t ldns_pkt_arcount(const ldns_pkt *p); + +/** + * Return the packet's answerfrom + * \param[in] p packet + * \return the name of the server + */ +ldns_rdf *ldns_pkt_answerfrom(const ldns_pkt *p); + +/** + * Return the packet's timestamp + * \param[in] p the packet + * \return the timestamp + */ +struct timeval ldns_pkt_timestamp(const ldns_pkt *p); +/** + * Return the packet's querytime + * \param[in] p the packet + * \return the querytime + */ +uint32_t ldns_pkt_querytime(const ldns_pkt *p); + +/** + * Return the packet's size in bytes + * \param[in] p the packet + * \return the size + */ +size_t ldns_pkt_size(const ldns_pkt *p); + +/** + * Return the packet's tsig pseudo rr's + * \param[in] p the packet + * \return the tsig rr + */ +ldns_rr *ldns_pkt_tsig(const ldns_pkt *p); + +/** + * Return the packet's question section + * \param[in] p the packet + * \return the section + */ +ldns_rr_list *ldns_pkt_question(const ldns_pkt *p); +/** + * Return the packet's answer section + * \param[in] p the packet + * \return the section + */ +ldns_rr_list *ldns_pkt_answer(const ldns_pkt *p); +/** + * Return the packet's authority section + * \param[in] p the packet + * \return the section + */ +ldns_rr_list *ldns_pkt_authority(const ldns_pkt *p); +/** + * Return the packet's additional section + * \param[in] p the packet + * \return the section + */ +ldns_rr_list *ldns_pkt_additional(const ldns_pkt *p); +/** + * Return the packet's question, answer, authority and additional sections + * concatenated, in a new rr_list clone. + * \param[in] p the packet + * \return the rrs + */ +ldns_rr_list *ldns_pkt_all(const ldns_pkt *p); +/** + * Return the packet's answer, authority and additional sections concatenated, + * in a new rr_list clone. Like ldns_pkt_all but without the questions. + * \param[in] p the packet + * \return the rrs except the question rrs + */ +ldns_rr_list *ldns_pkt_all_noquestion(const ldns_pkt *p); + +/** + * return all the rr_list's in the packet. Clone the lists, instead + * of returning pointers. + * \param[in] p the packet to look in + * \param[in] s what section(s) to return + * \return ldns_rr_list with the rr's or NULL if none were found + */ +ldns_rr_list *ldns_pkt_get_section_clone(const ldns_pkt *p, ldns_pkt_section s); + +/** + * return all the rr with a specific name from a packet. Optionally + * specify from which section in the packet + * \param[in] p the packet + * \param[in] r the name + * \param[in] s the packet's section + * \return a list with the rr's or NULL if none were found + */ +ldns_rr_list *ldns_pkt_rr_list_by_name(ldns_pkt *p, ldns_rdf *r, ldns_pkt_section s); +/** + * return all the rr with a specific type from a packet. Optionally + * specify from which section in the packet + * \param[in] p the packet + * \param[in] t the type + * \param[in] s the packet's section + * \return a list with the rr's or NULL if none were found + */ +ldns_rr_list *ldns_pkt_rr_list_by_type(const ldns_pkt *p, ldns_rr_type t, ldns_pkt_section s); +/** + * return all the rr with a specific type and type from a packet. Optionally + * specify from which section in the packet + * \param[in] packet the packet + * \param[in] ownername the name + * \param[in] type the type + * \param[in] sec the packet's section + * \return a list with the rr's or NULL if none were found + */ +ldns_rr_list *ldns_pkt_rr_list_by_name_and_type(const ldns_pkt *packet, const ldns_rdf *ownername, ldns_rr_type type, ldns_pkt_section sec); + + +/** + * check to see if an rr exist in the packet + * \param[in] pkt the packet to examine + * \param[in] sec in which section to look + * \param[in] rr the rr to look for + */ +bool ldns_pkt_rr(ldns_pkt *pkt, ldns_pkt_section sec, ldns_rr *rr); + + +/** + * sets the flags in a packet. + * \param[in] pkt the packet to operate on + * \param[in] flags ORed values: LDNS_QR| LDNS_AR for instance + * \return true on success otherwise false + */ +bool ldns_pkt_set_flags(ldns_pkt *pkt, uint16_t flags); + +/** + * Set the packet's id + * \param[in] p the packet + * \param[in] id the id to set + */ +void ldns_pkt_set_id(ldns_pkt *p, uint16_t id); +/** + * Set the packet's id to a random value + * \param[in] p the packet + */ +void ldns_pkt_set_random_id(ldns_pkt *p); +/** + * Set the packet's qr bit + * \param[in] p the packet + * \param[in] b the value to set (boolean) + */ +void ldns_pkt_set_qr(ldns_pkt *p, bool b); +/** + * Set the packet's aa bit + * \param[in] p the packet + * \param[in] b the value to set (boolean) + */ +void ldns_pkt_set_aa(ldns_pkt *p, bool b); +/** + * Set the packet's tc bit + * \param[in] p the packet + * \param[in] b the value to set (boolean) + */ +void ldns_pkt_set_tc(ldns_pkt *p, bool b); +/** + * Set the packet's rd bit + * \param[in] p the packet + * \param[in] b the value to set (boolean) + */ +void ldns_pkt_set_rd(ldns_pkt *p, bool b); +/** + * Set the packet's cd bit + * \param[in] p the packet + * \param[in] b the value to set (boolean) + */ +void ldns_pkt_set_cd(ldns_pkt *p, bool b); +/** + * Set the packet's ra bit + * \param[in] p the packet + * \param[in] b the value to set (boolean) + */ +void ldns_pkt_set_ra(ldns_pkt *p, bool b); +/** + * Set the packet's ad bit + * \param[in] p the packet + * \param[in] b the value to set (boolean) + */ +void ldns_pkt_set_ad(ldns_pkt *p, bool b); + +/** + * Set the packet's opcode + * \param[in] p the packet + * \param[in] c the opcode + */ +void ldns_pkt_set_opcode(ldns_pkt *p, ldns_pkt_opcode c); +/** + * Set the packet's respons code + * \param[in] p the packet + * \param[in] c the rcode + */ +void ldns_pkt_set_rcode(ldns_pkt *p, uint8_t c); +/** + * Set the packet's qd count + * \param[in] p the packet + * \param[in] c the count + */ +void ldns_pkt_set_qdcount(ldns_pkt *p, uint16_t c); +/** + * Set the packet's an count + * \param[in] p the packet + * \param[in] c the count + */ +void ldns_pkt_set_ancount(ldns_pkt *p, uint16_t c); +/** + * Set the packet's ns count + * \param[in] p the packet + * \param[in] c the count + */ +void ldns_pkt_set_nscount(ldns_pkt *p, uint16_t c); +/** + * Set the packet's arcount + * \param[in] p the packet + * \param[in] c the count + */ +void ldns_pkt_set_arcount(ldns_pkt *p, uint16_t c); +/** + * Set the packet's answering server + * \param[in] p the packet + * \param[in] r the address + */ +void ldns_pkt_set_answerfrom(ldns_pkt *p, ldns_rdf *r); +/** + * Set the packet's query time + * \param[in] p the packet + * \param[in] t the querytime in msec + */ +void ldns_pkt_set_querytime(ldns_pkt *p, uint32_t t); +/** + * Set the packet's size + * \param[in] p the packet + * \param[in] s the size + */ +void ldns_pkt_set_size(ldns_pkt *p, size_t s); + +/** + * Set the packet's timestamp + * \param[in] p the packet + * \param[in] timeval the timestamp + */ +void ldns_pkt_set_timestamp(ldns_pkt *p, struct timeval timeval); +/** + * Set a packet's section count to x + * \param[in] p the packet + * \param[in] s the section + * \param[in] x the section count + */ +void ldns_pkt_set_section_count(ldns_pkt *p, ldns_pkt_section s, uint16_t x); +/** + * Set the packet's tsig rr + * \param[in] p the packet + * \param[in] t the tsig rr + */ +void ldns_pkt_set_tsig(ldns_pkt *p, ldns_rr *t); + +/** + * looks inside the packet to determine + * what kind of packet it is, AUTH, NXDOMAIN, REFERRAL, etc. + * \param[in] p the packet to examine + * \return the type of packet + */ +ldns_pkt_type ldns_pkt_reply_type(ldns_pkt *p); + +/** + * return the packet's edns udp size + * \param[in] packet the packet + * \return the size + */ +uint16_t ldns_pkt_edns_udp_size(const ldns_pkt *packet); +/** + * return the packet's edns extended rcode + * \param[in] packet the packet + * \return the rcode + */ +uint8_t ldns_pkt_edns_extended_rcode(const ldns_pkt *packet); +/** + * return the packet's edns version + * \param[in] packet the packet + * \return the version + */ +uint8_t ldns_pkt_edns_version(const ldns_pkt *packet); +/** + * return the packet's edns z value + * \param[in] packet the packet + * \return the z value + */ +uint16_t ldns_pkt_edns_z(const ldns_pkt *packet); +/** + * return the packet's edns data + * \param[in] packet the packet + * \return the data + */ +ldns_rdf *ldns_pkt_edns_data(const ldns_pkt *packet); + +/** + * return the packet's edns do bit + * \param[in] packet the packet + * \return the bit's value + */ +bool ldns_pkt_edns_do(const ldns_pkt *packet); +/** + * Set the packet's edns do bit + * \param[in] packet the packet + * \param[in] value the bit's new value + */ +void ldns_pkt_set_edns_do(ldns_pkt *packet, bool value); + +/** + * returns true if this packet needs and EDNS rr to be sent. + * At the moment the only reason is an expected packet + * size larger than 512 bytes, but for instance dnssec would + * be a good reason too. + * + * \param[in] packet the packet to check + * \return true if packet needs edns rr + */ +bool ldns_pkt_edns(const ldns_pkt *packet); + +/** + * Set the packet's edns udp size + * \param[in] packet the packet + * \param[in] s the size + */ +void ldns_pkt_set_edns_udp_size(ldns_pkt *packet, uint16_t s); +/** + * Set the packet's edns extended rcode + * \param[in] packet the packet + * \param[in] c the code + */ +void ldns_pkt_set_edns_extended_rcode(ldns_pkt *packet, uint8_t c); +/** + * Set the packet's edns version + * \param[in] packet the packet + * \param[in] v the version + */ +void ldns_pkt_set_edns_version(ldns_pkt *packet, uint8_t v); +/** + * Set the packet's edns z value + * \param[in] packet the packet + * \param[in] z the value + */ +void ldns_pkt_set_edns_z(ldns_pkt *packet, uint16_t z); +/** + * Set the packet's edns data + * \param[in] packet the packet + * \param[in] data the data + */ +void ldns_pkt_set_edns_data(ldns_pkt *packet, ldns_rdf *data); + +/** + * allocates and initializes a ldns_pkt structure. + * \return pointer to the new packet + */ +ldns_pkt *ldns_pkt_new(); + +/** + * frees the packet structure and all data that it contains. + * \param[in] packet The packet structure to free + * \return void + */ +void ldns_pkt_free(ldns_pkt *packet); + +/** + * creates a query packet for the given name, type, class. + * \param[out] p the packet to be returned + * \param[in] rr_name the name to query for (as string) + * \param[in] rr_type the type to query for + * \param[in] rr_class the class to query for + * \param[in] flags packet flags + * \return LDNS_STATUS_OK or a ldns_status mesg with the error + */ +ldns_status ldns_pkt_query_new_frm_str(ldns_pkt **p, const char *rr_name, ldns_rr_type rr_type, ldns_rr_class rr_class , uint16_t flags); + +/** + * creates a packet with a query in it for the given name, type and class. + * \param[in] rr_name the name to query for + * \param[in] rr_type the type to query for + * \param[in] rr_class the class to query for + * \param[in] flags packet flags + * \return ldns_pkt* a pointer to the new pkt + */ +ldns_pkt *ldns_pkt_query_new(ldns_rdf *rr_name, ldns_rr_type rr_type, ldns_rr_class rr_class, uint16_t flags); + +/** + * clones the given packet, creating a fully allocated copy + * + * \param[in] pkt the packet to clone + * \return ldns_pkt* pointer to the new packet + */ +ldns_pkt *ldns_pkt_clone(ldns_pkt *pkt); + +/** + * directly set the additional section + * \param[in] p packet to operate on + * \param[in] rr rrlist to set + */ +void ldns_pkt_set_additional(ldns_pkt *p, ldns_rr_list *rr); + +/** + * directly set the answer section + * \param[in] p packet to operate on + * \param[in] rr rrlist to set + */ +void ldns_pkt_set_answer(ldns_pkt *p, ldns_rr_list *rr); + +/** + * directly set the question section + * \param[in] p packet to operate on + * \param[in] rr rrlist to set + */ +void ldns_pkt_set_question(ldns_pkt *p, ldns_rr_list *rr); + +/** + * directly set the auhority section + * \param[in] p packet to operate on + * \param[in] rr rrlist to set + */ +void ldns_pkt_set_authority(ldns_pkt *p, ldns_rr_list *rr); + +/** + * push an rr on a packet + * \param[in] packet packet to operate on + * \param[in] section where to put it + * \param[in] rr rr to push + * \return a boolean which is true when the rr was added + */ +bool ldns_pkt_push_rr(ldns_pkt *packet, ldns_pkt_section section, ldns_rr *rr); + +/** + * push an rr on a packet, provided the RR is not there. + * \param[in] pkt packet to operate on + * \param[in] sec where to put it + * \param[in] rr rr to push + * \return a boolean which is true when the rr was added + */ +bool ldns_pkt_safe_push_rr(ldns_pkt *pkt, ldns_pkt_section sec, ldns_rr *rr); + +/** + * push a rr_list on a packet + * \param[in] packet packet to operate on + * \param[in] section where to put it + * \param[in] list the rr_list to push + * \return a boolean which is true when the rr was added + */ +bool ldns_pkt_push_rr_list(ldns_pkt *packet, ldns_pkt_section section, ldns_rr_list *list); + +/** + * push an rr_list to a packet, provided the RRs are not already there. + * \param[in] pkt packet to operate on + * \param[in] sec where to put it + * \param[in] list the rr_list to push + * \return a boolean which is true when the rr was added + */ +bool ldns_pkt_safe_push_rr_list(ldns_pkt *pkt, ldns_pkt_section sec, ldns_rr_list *list); + +/** + * check if a packet is empty + * \param[in] p packet + * \return true: empty, false: not empty + */ +bool ldns_pkt_empty(ldns_pkt *p); + +#ifdef __cplusplus +} +#endif + +#endif /* LDNS_PACKET_H */ diff --git a/ldns/parse.h b/ldns/parse.h new file mode 100644 index 00000000000..0e9034c3414 --- /dev/null +++ b/ldns/parse.h @@ -0,0 +1,167 @@ +/* + * parse.h + * + * a Net::DNS like library for C + * LibDNS Team @ NLnet Labs + * (c) NLnet Labs, 2005-2006 + * See the file LICENSE for the license + */ + +#ifndef LDNS_PARSE_H +#define LDNS_PARSE_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define LDNS_PARSE_SKIP_SPACE "\f\n\r\v" +#define LDNS_PARSE_NORMAL " \f\n\r\t\v" +#define LDNS_PARSE_NO_NL " \t" +#define LDNS_MAX_LINELEN 10230 +#define LDNS_MAX_KEYWORDLEN 32 + + +/** + * \file + * + * Contains some low-level parsing functions, mostly used in the _frm_str + * family of functions. + */ + +/** + * different type of directives in zone files + * We now deal with $TTL, $ORIGIN and $INCLUDE. + * The latter is not implemented in ldns (yet) + */ +enum ldns_enum_directive +{ + LDNS_DIR_TTL, + LDNS_DIR_ORIGIN, + LDNS_DIR_INCLUDE +}; +typedef enum ldns_enum_directive ldns_directive; + +/** + * returns a token/char from the stream F. + * This function deals with ( and ) in the stream, + * and ignores them when encountered + * \param[in] *f the file to read from + * \param[out] *token the read token is put here + * \param[in] *delim chars at which the parsing should stop + * \param[in] *limit how much to read. If 0 the builtin maximum is used + * \return 0 on error of EOF of the stream F. Otherwise return the length of what is read + */ +ssize_t ldns_fget_token(FILE *f, char *token, const char *delim, size_t limit); + +/** + * returns a token/char from the stream F. + * This function deals with ( and ) in the stream, + * and ignores when it finds them. + * \param[in] *f the file to read from + * \param[out] *token the token is put here + * \param[in] *delim chars at which the parsing should stop + * \param[in] *limit how much to read. If 0 use builtin maximum + * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes) + * \return 0 on error of EOF of F otherwise return the length of what is read + */ +ssize_t ldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *line_nr); + +/** + * returns a token/char from the buffer b. + * This function deals with ( and ) in the buffer, + * and ignores when it finds them. + * \param[in] *b the buffer to read from + * \param[out] *token the token is put here + * \param[in] *delim chars at which the parsing should stop + * \param[in] *limit how much to read. If 0 the builtin maximum is used + * \returns 0 on error of EOF of b. Otherwise return the length of what is read + */ +ssize_t ldns_bget_token(ldns_buffer *b, char *token, const char *delim, size_t limit); + +/* + * searches for keyword and delim in a file. Gives everything back + * after the keyword + k_del until we hit d_del + * \param[in] f file pointer to read from + * \param[in] keyword keyword to look for + * \param[in] k_del keyword delimeter + * \param[out] data the data found + * \param[in] d_del the data delimeter + * \param[in] data_limit maximum size the the data buffer + * \return the number of character read + */ +ssize_t ldns_fget_keyword_data(FILE *f, const char *keyword, const char *k_del, char *data, const char *d_del, size_t data_limit); + +/* + * searches for keyword and delim. Gives everything back + * after the keyword + k_del until we hit d_del + * \param[in] f file pointer to read from + * \param[in] keyword keyword to look for + * \param[in] k_del keyword delimeter + * \param[out] data the data found + * \param[in] d_del the data delimeter + * \param[in] data_limit maximum size the the data buffer + * \param[in] line_nr pointer to an integer containing the current line number (for +debugging purposes) + * \return the number of character read + */ +ssize_t ldns_fget_keyword_data_l(FILE *f, const char *keyword, const char *k_del, char *data, const char *d_del, size_t data_limit, int *line_nr); + +/* + * searches for keyword and delim in a buffer. Gives everything back + * after the keyword + k_del until we hit d_del + * \param[in] b buffer pointer to read from + * \param[in] keyword keyword to look for + * \param[in] k_del keyword delimeter + * \param[out] data the data found + * \param[in] d_del the data delimeter + * \param[in] data_limit maximum size the the data buffer + * \return the number of character read + */ +ssize_t ldns_bget_keyword_data(ldns_buffer *b, const char *keyword, const char *k_del, char *data, const char *d_del, size_t data_limit); + +/** + * returns the next character from a buffer. Advances the position pointer with 1. + * When end of buffer is reached returns EOF. This is the buffer's equivalent + * for getc(). + * \param[in] *buffer buffer to read from + * \return EOF on failure otherwise return the character + */ +int ldns_bgetc(ldns_buffer *buffer); + +/** + * skips all of the characters in the given string in the buffer, moving + * the position to the first character that is not in *s. + * \param[in] *buffer buffer to use + * \param[in] *s characters to skip + * \return void + */ +void ldns_bskipcs(ldns_buffer *buffer, const char *s); + +/** + * skips all of the characters in the given string in the fp, moving + * the position to the first character that is not in *s. + * \param[in] *fp file to use + * \param[in] *s characters to skip + * \return void + */ +void ldns_fskipcs(FILE *fp, const char *s); + + +/** + * skips all of the characters in the given string in the fp, moving + * the position to the first character that is not in *s. + * \param[in] *fp file to use + * \param[in] *s characters to skip + * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes) + * \return void + */ +void ldns_fskipcs_l(FILE *fp, const char *s, int *line_nr); + +#ifdef __cplusplus +} +#endif + +#endif /* LDNS_PARSE_H */ diff --git a/ldns/rbtree.h b/ldns/rbtree.h new file mode 100644 index 00000000000..98bd8803299 --- /dev/null +++ b/ldns/rbtree.h @@ -0,0 +1,230 @@ +/* + * rbtree.h -- generic red-black tree + * + * Copyright (c) 2001-2008, 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * \file + * Red black tree. Implementation taken from NSD 3.0.5, adjusted for use + * in unbound (memory allocation, logging and so on). + */ + +#ifndef LDNS_RBTREE_H_ +#define LDNS_RBTREE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * This structure must be the first member of the data structure in + * the rbtree. This allows easy casting between an rbnode_t and the + * user data (poor man's inheritance). + * Or you can use the data pointer member to get to your data item. + */ +typedef struct ldns_rbnode_t ldns_rbnode_t; +/** + * The rbnode_t struct definition. + */ +struct ldns_rbnode_t { + /** parent in rbtree, RBTREE_NULL for root */ + ldns_rbnode_t *parent; + /** left node (smaller items) */ + ldns_rbnode_t *left; + /** right node (larger items) */ + ldns_rbnode_t *right; + /** pointer to sorting key */ + const void *key; + /** pointer to data */ + const void *data; + /** colour of this node */ + uint8_t color; +}; + +/** The nullpointer, points to empty node */ +#define LDNS_RBTREE_NULL &ldns_rbtree_null_node +/** the global empty node */ +extern ldns_rbnode_t ldns_rbtree_null_node; + +/** An entire red black tree */ +typedef struct ldns_rbtree_t ldns_rbtree_t; +/** definition for tree struct */ +struct ldns_rbtree_t { + /** The root of the red-black tree */ + ldns_rbnode_t *root; + + /** The number of the nodes in the tree */ + size_t count; + + /** + * Key compare function. <0,0,>0 like strcmp. + * Return 0 on two NULL ptrs. + */ + int (*cmp) (const void *, const void *); +}; + +/** + * Create new tree (malloced) with given key compare function. + * @param cmpf: compare function (like strcmp) takes pointers to two keys. + * @return: new tree, empty. + */ +ldns_rbtree_t *ldns_rbtree_create(int (*cmpf)(const void *, const void *)); + +/** + * Free the complete tree (but not its keys) + * @param rbtree The tree to free + */ +void ldns_rbtree_free(ldns_rbtree_t *rbtree); + +/** + * Init a new tree (malloced by caller) with given key compare function. + * @param rbtree: uninitialised memory for new tree, returned empty. + * @param cmpf: compare function (like strcmp) takes pointers to two keys. + */ +void ldns_rbtree_init(ldns_rbtree_t *rbtree, int (*cmpf)(const void *, const void *)); + +/** + * Insert data into the tree. + * @param rbtree: tree to insert to. + * @param data: element to insert. + * @return: data ptr or NULL if key already present. + */ +ldns_rbnode_t *ldns_rbtree_insert(ldns_rbtree_t *rbtree, ldns_rbnode_t *data); + +/** + * Insert data into the tree (reversed arguments, for use as callback) + * \param[in] data element to insert + * \param[out] rbtree tree to insert in to + * \return data ptr or NULL if key is already present + */ +void ldns_rbtree_insert_vref(ldns_rbnode_t *data, void *rbtree); + +/** + * Delete element from tree. + * @param rbtree: tree to delete from. + * @param key: key of item to delete. + * @return: node that is now unlinked from the tree. User to delete it. + * returns 0 if node not present + */ +ldns_rbnode_t *ldns_rbtree_delete(ldns_rbtree_t *rbtree, const void *key); + +/** + * Find key in tree. Returns NULL if not found. + * @param rbtree: tree to find in. + * @param key: key that must match. + * @return: node that fits or NULL. + */ +ldns_rbnode_t *ldns_rbtree_search(ldns_rbtree_t *rbtree, const void *key); + +/** + * Find, but match does not have to be exact. + * @param rbtree: tree to find in. + * @param key: key to find position of. + * @param result: set to the exact node if present, otherwise to element that + * precedes the position of key in the tree. NULL if no smaller element. + * @return: true if exact match in result. Else result points to <= element, + * or NULL if key is smaller than the smallest key. + */ +int ldns_rbtree_find_less_equal(ldns_rbtree_t *rbtree, const void *key, + ldns_rbnode_t **result); + +/** + * Returns first (smallest) node in the tree + * @param rbtree: tree + * @return: smallest element or NULL if tree empty. + */ +ldns_rbnode_t *ldns_rbtree_first(ldns_rbtree_t *rbtree); + +/** + * Returns last (largest) node in the tree + * @param rbtree: tree + * @return: largest element or NULL if tree empty. + */ +ldns_rbnode_t *ldns_rbtree_last(ldns_rbtree_t *rbtree); + +/** + * Returns next larger node in the tree + * @param rbtree: tree + * @return: next larger element or NULL if no larger in tree. + */ +ldns_rbnode_t *ldns_rbtree_next(ldns_rbnode_t *rbtree); + +/** + * Returns previous smaller node in the tree + * @param rbtree: tree + * @return: previous smaller element or NULL if no previous in tree. + */ +ldns_rbnode_t *ldns_rbtree_previous(ldns_rbnode_t *rbtree); + +/** + * split off 'elements' number of elements from the start + * of the name tree and return a new tree containing those + * elements + */ +ldns_rbtree_t *ldns_rbtree_split(ldns_rbtree_t *tree, size_t elements); + +/** + * add all node from the second tree to the first (removing them from the + * second), and fix up nsec(3)s if present + */ +void ldns_rbtree_join(ldns_rbtree_t *tree1, ldns_rbtree_t *tree2); + +/** + * Call with node=variable of struct* with rbnode_t as first element. + * with type is the type of a pointer to that struct. + */ +#define LDNS_RBTREE_FOR(node, type, rbtree) \ + for(node=(type)ldns_rbtree_first(rbtree); \ + (ldns_rbnode_t*)node != LDNS_RBTREE_NULL; \ + node = (type)ldns_rbtree_next((ldns_rbnode_t*)node)) + +/** + * Call function for all elements in the redblack tree, such that + * leaf elements are called before parent elements. So that all + * elements can be safely free()d. + * Note that your function must not remove the nodes from the tree. + * Since that may trigger rebalances of the rbtree. + * @param tree: the tree + * @param func: function called with element and user arg. + * The function must not alter the rbtree. + * @param arg: user argument. + */ +void ldns_traverse_postorder(ldns_rbtree_t* tree, + void (*func)(ldns_rbnode_t*, void*), void* arg); + +#ifdef __cplusplus +} +#endif + +#endif /* UTIL_RBTREE_H_ */ diff --git a/ldns/rdata.h b/ldns/rdata.h new file mode 100644 index 00000000000..90dcbf13818 --- /dev/null +++ b/ldns/rdata.h @@ -0,0 +1,385 @@ +/* + * rdata.h + * + * rdata definitions + * + * a Net::DNS like library for C + * + * (c) NLnet Labs, 2005-2006 + * + * See the file LICENSE for the license + */ + + +/** + * \file + * + * Defines ldns_rdf and functions to manipulate those. + */ + + +#ifndef LDNS_RDATA_H +#define LDNS_RDATA_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define LDNS_MAX_RDFLEN 8192 + +#define LDNS_RDF_SIZE_BYTE 1 +#define LDNS_RDF_SIZE_WORD 2 +#define LDNS_RDF_SIZE_DOUBLEWORD 4 +#define LDNS_RDF_SIZE_6BYTES 6 +#define LDNS_RDF_SIZE_16BYTES 16 + +#define LDNS_NSEC3_VARS_OPTOUT_MASK 0x01 + +/** + * The different types of RDATA fields. + */ +enum ldns_enum_rdf_type +{ + /** none */ + LDNS_RDF_TYPE_NONE, + /** domain name */ + LDNS_RDF_TYPE_DNAME, + /** 8 bits */ + LDNS_RDF_TYPE_INT8, + /** 16 bits */ + LDNS_RDF_TYPE_INT16, + /** 32 bits */ + LDNS_RDF_TYPE_INT32, + /** A record */ + LDNS_RDF_TYPE_A, + /** AAAA record */ + LDNS_RDF_TYPE_AAAA, + /** txt string */ + LDNS_RDF_TYPE_STR, + /** apl data */ + LDNS_RDF_TYPE_APL, + /** b32 string */ + LDNS_RDF_TYPE_B32_EXT, + /** b64 string */ + LDNS_RDF_TYPE_B64, + /** hex string */ + LDNS_RDF_TYPE_HEX, + /** nsec type codes */ + LDNS_RDF_TYPE_NSEC, + /** a RR type */ + LDNS_RDF_TYPE_TYPE, + /** a class */ + LDNS_RDF_TYPE_CLASS, + /** certificate algorithm */ + LDNS_RDF_TYPE_CERT_ALG, + /** a key algorithm */ + LDNS_RDF_TYPE_ALG, + /** unknown types */ + LDNS_RDF_TYPE_UNKNOWN, + /** time (32 bits) */ + LDNS_RDF_TYPE_TIME, + /** period */ + LDNS_RDF_TYPE_PERIOD, + /** tsig time 48 bits */ + LDNS_RDF_TYPE_TSIGTIME, + LDNS_RDF_TYPE_TSIG, + /** variable length any type rdata where the length + is specified by the first 2 bytes */ + LDNS_RDF_TYPE_INT16_DATA, + /** protocol and port bitmaps */ + LDNS_RDF_TYPE_SERVICE, + /** location data */ + LDNS_RDF_TYPE_LOC, + /** well known services */ + LDNS_RDF_TYPE_WKS, + /** NSAP */ + LDNS_RDF_TYPE_NSAP, + /** ATMA */ + LDNS_RDF_TYPE_ATMA, + /** IPSECKEY */ + LDNS_RDF_TYPE_IPSECKEY, + /** nsec3 hash salt */ + LDNS_RDF_TYPE_NSEC3_SALT, + /** nsec3 base32 string (with length byte on wire */ + LDNS_RDF_TYPE_NSEC3_NEXT_OWNER +}; +typedef enum ldns_enum_rdf_type ldns_rdf_type; + +/** + * algorithms used in CERT rrs + */ +enum ldns_enum_cert_algorithm +{ + LDNS_CERT_PKIX = 1, + LDNS_CERT_SPKI = 2, + LDNS_CERT_PGP = 3, + LDNS_CERT_IPKIX = 4, + LDNS_CERT_ISPKI = 5, + LDNS_CERT_IPGP = 6, + LDNS_CERT_ACPKIX = 7, + LDNS_CERT_IACPKIX = 8, + LDNS_CERT_URI = 253, + LDNS_CERT_OID = 254 +}; +typedef enum ldns_enum_cert_algorithm ldns_cert_algorithm; + + + +/** + * Resource record data field. + * + * The data is a network ordered array of bytes, which size is specified by + * the (16-bit) size field. To correctly parse it, use the type + * specified in the (16-bit) type field with a value from \ref ldns_rdf_type. + */ +struct ldns_struct_rdf +{ + /** The size of the data (in octets) */ + size_t _size; + /** The type of the data */ + ldns_rdf_type _type; + /** Pointer to the data (raw octets) */ + void *_data; +}; +typedef struct ldns_struct_rdf ldns_rdf; + +/* prototypes */ + +/* write access functions */ + +/** + * sets the size of the rdf. + * \param[in] *rd the rdf to operate on + * \param[in] size the new size + * \return void + */ +void ldns_rdf_set_size(ldns_rdf *rd, size_t size); + +/** + * sets the size of the rdf. + * \param[in] *rd the rdf to operate on + * \param[in] type the new type + * \return void + */ +void ldns_rdf_set_type(ldns_rdf *rd, ldns_rdf_type type); + +/** + * sets the size of the rdf. + * \param[in] *rd the rdf to operate on + * \param[in] *data pointer to the new data + * \return void + */ +void ldns_rdf_set_data(ldns_rdf *rd, void *data); + +/* read access */ + +/** + * returns the size of the rdf. + * \param[in] *rd the rdf to read from + * \return uint16_t with the size + */ +size_t ldns_rdf_size(const ldns_rdf *rd); + +/** + * returns the type of the rdf. We need to insert _get_ + * here to prevent conflict the the rdf_type TYPE. + * \param[in] *rd the rdf to read from + * \return ldns_rdf_type with the type + */ +ldns_rdf_type ldns_rdf_get_type(const ldns_rdf *rd); + +/** + * returns the data of the rdf. + * \param[in] *rd the rdf to read from + * \return uint8_t* pointer to the rdf's data + */ +uint8_t *ldns_rdf_data(const ldns_rdf *rd); + +/* creator functions */ + +/** + * allocates a new rdf structure and fills it. + * This function DOES NOT copy the contents from + * the buffer, unlinke ldns_rdf_new_frm_data() + * \param[in] type type of the rdf + * \param[in] size size of the buffer + * \param[in] data pointer to the buffer to be copied + * \return the new rdf structure or NULL on failure + */ +ldns_rdf *ldns_rdf_new(ldns_rdf_type type, size_t size, void *data); + +/** + * allocates a new rdf structure and fills it. + * This function _does_ copy the contents from + * the buffer, unlinke ldns_rdf_new() + * \param[in] type type of the rdf + * \param[in] size size of the buffer + * \param[in] data pointer to the buffer to be copied + * \return the new rdf structure or NULL on failure + */ +ldns_rdf *ldns_rdf_new_frm_data(ldns_rdf_type type, size_t size, const void *data); + +/** + * creates a new rdf from a string. + * \param[in] type type to use + * \param[in] str string to use + * \return ldns_rdf* or NULL in case of an error + */ +ldns_rdf *ldns_rdf_new_frm_str(ldns_rdf_type type, const char *str); + +/** + * creates a new rdf from a file containing a string. + * \param[out] r the new rdf + * \param[in] type type to use + * \param[in] fp the file pointer to use + * \return LDNS_STATUS_OK or the error + */ +ldns_status ldns_rdf_new_frm_fp(ldns_rdf **r, ldns_rdf_type type, FILE *fp); + +/** + * creates a new rdf from a file containing a string. + * \param[out] r the new rdf + * \param[in] type type to use + * \param[in] fp the file pointer to use + * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes) + * \return LDNS_STATUS_OK or the error + */ +ldns_status ldns_rdf_new_frm_fp_l(ldns_rdf **r, ldns_rdf_type type, FILE *fp, int *line_nr); + +/* destroy functions */ + +/** + * frees a rdf structure, leaving the + * data pointer intact. + * \param[in] rd the pointer to be freed + * \return void + */ +void ldns_rdf_free(ldns_rdf *rd); + +/** + * frees a rdf structure _and_ frees the + * data. rdf should be created with _new_frm_data + * \param[in] rd the rdf structure to be freed + * \return void + */ +void ldns_rdf_deep_free(ldns_rdf *rd); + +/* conversion functions */ + +/** + * returns the rdf containing the native uint8_t repr. + * \param[in] type the ldns_rdf type to use + * \param[in] value the uint8_t to use + * \return ldns_rdf* with the converted value + */ +ldns_rdf *ldns_native2rdf_int8(ldns_rdf_type type, uint8_t value); + +/** + * returns the rdf containing the native uint16_t representation. + * \param[in] type the ldns_rdf type to use + * \param[in] value the uint16_t to use + * \return ldns_rdf* with the converted value + */ +ldns_rdf *ldns_native2rdf_int16(ldns_rdf_type type, uint16_t value); + +/** + * returns an rdf that contains the given int32 value. + * + * Because multiple rdf types can contain an int32, the + * type must be specified + * \param[in] type the ldns_rdf type to use + * \param[in] value the uint32_t to use + * \return ldns_rdf* with the converted value + */ +ldns_rdf *ldns_native2rdf_int32(ldns_rdf_type type, uint32_t value); + +/** + * returns an int16_data rdf that contains the data in the + * given array, preceded by an int16 specifying the length. + * + * The memory is copied, and an LDNS_RDF_TYPE_INT16DATA is returned + * \param[in] size the size of the data + * \param[in] *data pointer to the actual data + * \return ldns_rd* the rdf with the data + */ +ldns_rdf *ldns_native2rdf_int16_data(size_t size, uint8_t *data); + +/** + * reverses an rdf, only actually useful for AAAA and A records. + * The returned rdf has the type LDNS_RDF_TYPE_DNAME! + * \param[in] *rd rdf to be reversed + * \return the reversed rdf (a newly created rdf) + */ +ldns_rdf *ldns_rdf_address_reverse(ldns_rdf *rd); + +/** + * returns the native uint8_t representation from the rdf. + * \param[in] rd the ldns_rdf to operate on + * \return uint8_t the value extracted + */ +uint8_t ldns_rdf2native_int8(const ldns_rdf *rd); + +/** + * returns the native uint16_t representation from the rdf. + * \param[in] rd the ldns_rdf to operate on + * \return uint16_t the value extracted + */ +uint16_t ldns_rdf2native_int16(const ldns_rdf *rd); + +/** + * returns the native uint32_t representation from the rdf. + * \param[in] rd the ldns_rdf to operate on + * \return uint32_t the value extracted + */ +uint32_t ldns_rdf2native_int32(const ldns_rdf *rd); + +/** + * returns the native time_t representation from the rdf. + * \param[in] rd the ldns_rdf to operate on + * \return time_t the value extracted (32 bits currently) + */ +time_t ldns_rdf2native_time_t(const ldns_rdf *rd); + +/** + * converts a ttl value (like 5d2h) to a long. + * \param[in] nptr the start of the string + * \param[out] endptr points to the last char in case of error + * \return the convert duration value + */ +uint32_t ldns_str2period(const char *nptr, const char **endptr); + +/** + * removes \\DDD, \\[space] and other escapes from the input. + * See RFC 1035, section 5.1. + * \param[in] word what to check + * \param[in] length the string + * \return ldns_status mesg + */ +ldns_status ldns_octet(char *word, size_t *length); + +/** + * clones a rdf structure. The data is copied. + * \param[in] rd rdf to be copied + * \return a new rdf structure + */ +ldns_rdf *ldns_rdf_clone(const ldns_rdf *rd); + +/** + * compares two rdf's on their wire formats. + * (To order dnames according to rfc4034, use ldns_dname_compare) + * \param[in] rd1 the first one + * \param[in] rd2 the second one + * \return 0 if equal + * \return -1 if rd1 comes before rd2 + * \return +1 if rd2 comes before rd1 + */ +int ldns_rdf_compare(const ldns_rdf *rd1, const ldns_rdf *rd2); + +#ifdef __cplusplus +} +#endif + +#endif /* LDNS_RDATA_H */ diff --git a/ldns/resolver.h b/ldns/resolver.h new file mode 100644 index 00000000000..f887aaf676e --- /dev/null +++ b/ldns/resolver.h @@ -0,0 +1,721 @@ +/* + * resolver.h + * + * DNS Resolver definitions + * + * a Net::DNS like library for C + * + * (c) NLnet Labs, 2005-2006 + * + * See the file LICENSE for the license + */ + +/** + * \file + * + * Defines the ldns_resolver structure, a stub resolver that can send queries and parse answers. + * + */ + +#ifndef LDNS_RESOLVER_H +#define LDNS_RESOLVER_H + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** Default location of the resolv.conf file */ +#define LDNS_RESOLV_CONF "/etc/resolv.conf" +/** Default location of the hosts file */ +#define LDNS_RESOLV_HOSTS "/etc/hosts" + +#define LDNS_RESOLV_KEYWORD -1 +#define LDNS_RESOLV_DEFDOMAIN 0 +#define LDNS_RESOLV_NAMESERVER 1 +#define LDNS_RESOLV_SEARCH 2 +#define LDNS_RESOLV_SORTLIST 3 +#define LDNS_RESOLV_OPTIONS 4 +#define LDNS_RESOLV_ANCHOR 5 +#define LDNS_RESOLV_KEYWORDS 6 + +#define LDNS_RESOLV_INETANY 0 +#define LDNS_RESOLV_INET 1 +#define LDNS_RESOLV_INET6 2 + +#define LDNS_RESOLV_RTT_INF 0 /* infinity */ +#define LDNS_RESOLV_RTT_MIN 1 /* reachable */ + +/** + * DNS stub resolver structure + */ +struct ldns_struct_resolver +{ + /** Port to send queries to */ + uint16_t _port; + + /** Array of nameservers to query (IP addresses or dnames) */ + ldns_rdf **_nameservers; + /** Number of nameservers in \c _nameservers */ + size_t _nameserver_count; /* how many do we have */ + + /** Round trip time; 0 -> infinity. Unit: ms? */ + size_t *_rtt; + + /** Wether or not to be recursive */ + bool _recursive; + + /** Print debug information */ + bool _debug; + + /** Default domain to add to non fully qualified domain names */ + ldns_rdf *_domain; + + /** Searchlist array, add the names in this array if a query cannot be found */ + ldns_rdf **_searchlist; + + /** Number of entries in the searchlist array */ + size_t _searchlist_count; + + /** Number of times to retry before giving up */ + uint8_t _retry; + /** Time to wait before retrying */ + uint8_t _retrans; + /** Use new fallback mechanism (try EDNS, then do TCP) */ + bool _fallback; + + /** Whether to do DNSSEC */ + bool _dnssec; + /** Whether to set the CD bit on DNSSEC requests */ + bool _dnssec_cd; + /** Optional trust anchors for complete DNSSEC validation */ + ldns_rr_list * _dnssec_anchors; + /** Whether to use tcp or udp (tcp if the value is true)*/ + bool _usevc; + /** Whether to ignore the tc bit */ + bool _igntc; + /** Whether to use ip6, 0->does not matter, 1 is IPv4, 2 is IPv6 */ + uint8_t _ip6; + /** If true append the default domain */ + bool _defnames; + /** If true apply the search list */ + bool _dnsrch; + /** Timeout for socket connections */ + struct timeval _timeout; + /** Only try the first nameserver, and return with an error directly if it fails */ + bool _fail; + /** Randomly choose a nameserver */ + bool _random; + /** Keep some things to make AXFR possible */ + int _socket; + /** Count the number of LDNS_RR_TYPE_SOA RRs we have seen so far + * (the second one signifies the end of the AXFR) + */ + int _axfr_soa_count; + /* when axfring we get complete packets from the server + but we want to give the caller 1 rr at a time, so + keep the current pkt */ + /** Packet currently handled when doing part of an AXFR */ + ldns_pkt *_cur_axfr_pkt; + /** Counter for within the AXFR packets */ + uint16_t _axfr_i; + /* EDNS0 available buffer size */ + uint16_t _edns_udp_size; + + /* Optional tsig key for signing queries, + outgoing messages are signed if and only if both are set + */ + /** Name of the key to use with TSIG, if _tsig_keyname and _tsig_keydata both contain values, outgoing messages are automatically signed with TSIG. */ + char *_tsig_keyname; + /** Secret key data to use with TSIG, if _tsig_keyname and _tsig_keydata both contain values, outgoing messages are automatically signed with TSIG. */ + char *_tsig_keydata; + /** TSIG signing algorithm */ + char *_tsig_algorithm; +}; +typedef struct ldns_struct_resolver ldns_resolver; + +/* prototypes */ +/* read access functions */ + +/** + * Get the port the resolver should use + * \param[in] r the resolver + * \return the port number + */ +uint16_t ldns_resolver_port(const ldns_resolver *r); + +/** + * Is the resolver set to recurse + * \param[in] r the resolver + * \return true if so, otherwise false + */ +bool ldns_resolver_recursive(const ldns_resolver *r); + +/** + * Get the debug status of the resolver + * \param[in] r the resolver + * \return true if so, otherwise false + */ +bool ldns_resolver_debug(const ldns_resolver *r); + +/** + * Get the number of retries + * \param[in] r the resolver + * \return the number of retries + */ +uint8_t ldns_resolver_retry(const ldns_resolver *r); + +/** + * Get the retransmit interval + * \param[in] r the resolver + * \return the retransmit interval + */ +uint8_t ldns_resolver_retrans(const ldns_resolver *r); + +/** + * Get the truncation fallback status + * \param[in] r the resolver + * \return whether the truncation fallback mechanism is used + */ +bool ldns_resolver_fallback(const ldns_resolver *r); + +/** + * Does the resolver use ip6 or ip4 + * \param[in] r the resolver + * \return 0: both, 1: ip4, 2:ip6 + */ +uint8_t ldns_resolver_ip6(const ldns_resolver *r); + +/** + * Get the resolver's udp size + * \param[in] r the resolver + * \return the udp mesg size + */ +uint16_t ldns_resolver_edns_udp_size(const ldns_resolver *r); +/** + * Does the resolver use tcp or udp + * \param[in] r the resolver + * \return true: tcp, false: udp + */ +bool ldns_resolver_usevc(const ldns_resolver *r); +/** + * Does the resolver only try the first nameserver + * \param[in] r the resolver + * \return true: yes, fail, false: no, try the others + */ +bool ldns_resolver_fail(const ldns_resolver *r); +/** + * Does the resolver apply default domain name + * \param[in] r the resolver + * \return true: yes, false: no + */ +bool ldns_resolver_defnames(const ldns_resolver *r); +/** + * Does the resolver apply search list + * \param[in] r the resolver + * \return true: yes, false: no + */ +bool ldns_resolver_dnsrch(const ldns_resolver *r); +/** + * Does the resolver do DNSSEC + * \param[in] r the resolver + * \return true: yes, false: no + */ +bool ldns_resolver_dnssec(const ldns_resolver *r); +/** + * Does the resolver set the CD bit + * \param[in] r the resolver + * \return true: yes, false: no + */ +bool ldns_resolver_dnssec_cd(const ldns_resolver *r); +/** + * Get the resolver's DNSSEC anchors + * \param[in] r the resolver + * \return an rr_list containg trusted DNSSEC anchors + */ +ldns_rr_list * ldns_resolver_dnssec_anchors(const ldns_resolver *r); +/** + * Does the resolver ignore the TC bit (truncated) + * \param[in] r the resolver + * \return true: yes, false: no + */ +bool ldns_resolver_igntc(const ldns_resolver *r); +/** + * Does the resolver randomize the nameserver before usage + * \param[in] r the resolver + * \return true: yes, false: no + */ +bool ldns_resolver_random(const ldns_resolver *r); +/** + * How many nameserver are configured in the resolver + * \param[in] r the resolver + * \return number of nameservers + */ +size_t ldns_resolver_nameserver_count(const ldns_resolver *r); +/** + * What is the default dname to add to relative queries + * \param[in] r the resolver + * \return the dname which is added + */ +ldns_rdf *ldns_resolver_domain(const ldns_resolver *r); +/** + * What is the timeout on socket connections + * \param[in] r the resolver + * \return the timeout as struct timeval + */ +struct timeval ldns_resolver_timeout(const ldns_resolver *r); +/** + * What is the searchlist as used by the resolver + * \param[in] r the resolver + * \return a ldns_rdf pointer to a list of the addresses + */ +ldns_rdf** ldns_resolver_searchlist(const ldns_resolver *r); +/** + * Return the configured nameserver ip address + * \param[in] r the resolver + * \return a ldns_rdf pointer to a list of the addresses + */ +ldns_rdf** ldns_resolver_nameservers(const ldns_resolver *r); +/** + * Return the used round trip times for the nameservers + * \param[in] r the resolver + * \return a size_t* pointer to the list. + * yet) + */ +size_t * ldns_resolver_rtt(const ldns_resolver *r); +/** + * Return the used round trip time for a specific nameserver + * \param[in] r the resolver + * \param[in] pos the index to the nameserver + * \return the rrt, 0: infinite, >0: undefined (as of * yet) + */ +size_t ldns_resolver_nameserver_rtt(const ldns_resolver *r, size_t pos); +/** + * Return the tsig keyname as used by the nameserver + * \param[in] r the resolver + * \return the name used. + */ +char *ldns_resolver_tsig_keyname(const ldns_resolver *r); +/** + * Return the tsig algorithm as used by the nameserver + * \param[in] r the resolver + * \return the algorithm used. + */ +char *ldns_resolver_tsig_algorithm(const ldns_resolver *r); +/** + * Return the tsig keydata as used by the nameserver + * \param[in] r the resolver + * \return the keydata used. + */ +char *ldns_resolver_tsig_keydata(const ldns_resolver *r); +/** + * pop the last nameserver from the resolver. + * \param[in] r the resolver + * \return the popped address or NULL if empty + */ +ldns_rdf* ldns_resolver_pop_nameserver(ldns_resolver *r); + +/** + * Return the resolver's searchlist count + * \param[in] r the resolver + * \return the searchlist count + */ +size_t ldns_resolver_searchlist_count(const ldns_resolver *r); + +/* write access function */ +/** + * Set the port the resolver should use + * \param[in] r the resolver + * \param[in] p the port number + */ +void ldns_resolver_set_port(ldns_resolver *r, uint16_t p); + +/** + * Set the resolver recursion + * \param[in] r the resolver + * \param[in] b true: set to recurse, false: unset + */ +void ldns_resolver_set_recursive(ldns_resolver *r, bool b); + +/** + * Set the resolver debugging + * \param[in] r the resolver + * \param[in] b true: debug on: false debug off + */ +void ldns_resolver_set_debug(ldns_resolver *r, bool b); + +/** + * Incremental the resolver's nameserver count. + * \param[in] r the resolver + */ +void ldns_resolver_incr_nameserver_count(ldns_resolver *r); + +/** + * Decrement the resolver's nameserver count. + * \param[in] r the resolver + */ +void ldns_resolver_dec_nameserver_count(ldns_resolver *r); + +/** + * Set the resolver's nameserver count directly. + * \param[in] r the resolver + * \param[in] c the nameserver count + */ +void ldns_resolver_set_nameserver_count(ldns_resolver *r, size_t c); + +/** + * Set the resolver's nameserver count directly by using an rdf list + * \param[in] r the resolver + * \param[in] rd the resolver addresses + */ +void ldns_resolver_set_nameservers(ldns_resolver *r, ldns_rdf **rd); + +/** + * Set the resolver's default domain. This gets appended when no + * absolute name is given + * \param[in] r the resolver + * \param[in] rd the name to append + */ +void ldns_resolver_set_domain(ldns_resolver *r, ldns_rdf *rd); + +/** + * Set the resolver's socket time out when talking to remote hosts + * \param[in] r the resolver + * \param[in] timeout the timeout to use + */ +void ldns_resolver_set_timeout(ldns_resolver *r, struct timeval timeout); + +/** + * Push a new rd to the resolver's searchlist + * \param[in] r the resolver + * \param[in] rd to push + */ +void ldns_resolver_push_searchlist(ldns_resolver *r, ldns_rdf *rd); + +/** + * Whether the resolver uses the name set with _set_domain + * \param[in] r the resolver + * \param[in] b true: use the defaults, false: don't use them + */ +void ldns_resolver_set_defnames(ldns_resolver *r, bool b); + +/** + * Whether the resolver uses a virtual circuit (TCP) + * \param[in] r the resolver + * \param[in] b true: use TCP, false: don't use TCP + */ +void ldns_resolver_set_usevc(ldns_resolver *r, bool b); + +/** + * Whether the resolver uses the searchlist + * \param[in] r the resolver + * \param[in] b true: use the list, false: don't use the list + */ +void ldns_resolver_set_dnsrch(ldns_resolver *r, bool b); + +/** + * Whether the resolver uses DNSSEC + * \param[in] r the resolver + * \param[in] b true: use DNSSEC, false: don't use DNSSEC + */ +void ldns_resolver_set_dnssec(ldns_resolver *r, bool b); + +/** + * Whether the resolver uses the checking disable bit + * \param[in] r the resolver + * \param[in] b true: enable , false: don't use TCP + */ +void ldns_resolver_set_dnssec_cd(ldns_resolver *r, bool b); +/** + * Set the resolver's DNSSEC anchor list directly. RRs should be of type DS or DNSKEY. + * \param[in] r the resolver + * \param[in] l the list of RRs to use as trust anchors + */ +void ldns_resolver_set_dnssec_anchors(ldns_resolver *r, ldns_rr_list * l); + +/** + * Push a new trust anchor to the resolver. It must be a DS or DNSKEY rr + * \param[in] r the resolver. + * \param[in] rr the RR to add as a trust anchor. + * \return a status + */ +ldns_status ldns_resolver_push_dnssec_anchor(ldns_resolver *r, ldns_rr *rr); + +/** + * Set the resolver retrans timeout (in seconds) + * \param[in] r the resolver + * \param[in] re the retransmission interval in seconds + */ +void ldns_resolver_set_retrans(ldns_resolver *r, uint8_t re); + +/** + * Set whether the resolvers truncation fallback mechanism is used + * when ldns_resolver_query() is called. + * \param[in] r the resolver + * \param[in] fallback whether to use the fallback mechanism + */ +void ldns_resolver_set_fallback(ldns_resolver *r, bool fallback); + +/** + * Set the resolver retry interval (in seconds) + * \param[in] r the resolver + * \param[in] re the retry interval + */ +void ldns_resolver_set_retry(ldns_resolver *r, uint8_t re); + +/** + * Whether the resolver uses ip6 + * \param[in] r the resolver + * \param[in] i 0: no pref, 1: ip4, 2: ip6 + */ +void ldns_resolver_set_ip6(ldns_resolver *r, uint8_t i); + +/** + * Whether or not to fail after one failed query + * \param[in] r the resolver + * \param[in] b true: yes fail, false: continue with next nameserver + */ +void ldns_resolver_set_fail(ldns_resolver *r, bool b); + +/** + * Whether or not to ignore the TC bit + * \param[in] r the resolver + * \param[in] b true: yes ignore, false: don't ignore + */ +void ldns_resolver_set_igntc(ldns_resolver *r, bool b); + +/** + * Set maximum udp size + * \param[in] r the resolver + * \param[in] s the udp max size + */ +void ldns_resolver_set_edns_udp_size(ldns_resolver *r, uint16_t s); + +/** + * Set the tsig key name + * \param[in] r the resolver + * \param[in] tsig_keyname the tsig key name + */ +void ldns_resolver_set_tsig_keyname(ldns_resolver *r, char *tsig_keyname); + +/** + * Set the tsig algorithm + * \param[in] r the resolver + * \param[in] tsig_algorithm the tsig algorithm + */ +void ldns_resolver_set_tsig_algorithm(ldns_resolver *r, char *tsig_algorithm); + +/** + * Set the tsig key data + * \param[in] r the resolver + * \param[in] tsig_keydata the key data + */ +void ldns_resolver_set_tsig_keydata(ldns_resolver *r, char *tsig_keydata); + +/** + * Set round trip time for all nameservers. Note this currently + * differentiates between: unreachable and reachable. + * \param[in] r the resolver + * \param[in] rtt a list with the times + */ +void ldns_resolver_set_rtt(ldns_resolver *r, size_t *rtt); + +/** + * Set round trip time for a specific nameserver. Note this + * currently differentiates between: unreachable and reachable. + * \param[in] r the resolver + * \param[in] pos the nameserver position + * \param[in] value the rtt + */ +void ldns_resolver_set_nameserver_rtt(ldns_resolver *r, size_t pos, size_t value); + +/** + * Should the nameserver list be randomized before each use + * \param[in] r the resolver + * \param[in] b: true: randomize, false: don't + */ +void ldns_resolver_set_random(ldns_resolver *r, bool b); + +/** + * Push a new nameserver to the resolver. It must be an IP + * address v4 or v6. + * \param[in] r the resolver + * \param[in] n the ip address + * \return ldns_status a status + */ +ldns_status ldns_resolver_push_nameserver(ldns_resolver *r, ldns_rdf *n); + +/** + * Push a new nameserver to the resolver. It must be an + * A or AAAA RR record type + * \param[in] r the resolver + * \param[in] rr the resource record + * \return ldns_status a status + */ +ldns_status ldns_resolver_push_nameserver_rr(ldns_resolver *r, ldns_rr *rr); + +/** + * Push a new nameserver rr_list to the resolver. + * \param[in] r the resolver + * \param[in] rrlist the rr_list to push + * \return ldns_status a status + */ +ldns_status ldns_resolver_push_nameserver_rr_list(ldns_resolver *r, ldns_rr_list *rrlist); + +/** + * Send the query for using the resolver and take the search list into account + * The search algorithm is as follows: + * If the name is absolute, try it as-is, otherwise apply the search list + * \param[in] *r operate using this resolver + * \param[in] *rdf query for this name + * \param[in] t query for this type (may be 0, defaults to A) + * \param[in] c query for this class (may be 0, default to IN) + * \param[in] flags the query flags + * \return ldns_pkt* a packet with the reply from the nameserver + */ +ldns_pkt* ldns_resolver_search(const ldns_resolver *r, const ldns_rdf *rdf, ldns_rr_type t, ldns_rr_class c, uint16_t flags); + +/** + * Form a query packet from a resolver and name/type/class combo + * \param[out] **q a pointer to a ldns_pkt pointer (initialized by this function) + * \param[in] *r operate using this resolver + * \param[in] *name query for this name + * \param[in] t query for this type (may be 0, defaults to A) + * \param[in] c query for this class (may be 0, default to IN) + * \param[in] f the query flags + * \return ldns_pkt* a packet with the reply from the nameserver + */ +ldns_status ldns_resolver_prepare_query_pkt(ldns_pkt **q, ldns_resolver *r, const ldns_rdf *name, ldns_rr_type t, ldns_rr_class c, uint16_t f); + +/** + * Send the query for name as-is + * \param[out] **answer a pointer to a ldns_pkt pointer (initialized by this function) + * \param[in] *r operate using this resolver + * \param[in] *name query for this name + * \param[in] t query for this type (may be 0, defaults to A) + * \param[in] c query for this class (may be 0, default to IN) + * \param[in] flags the query flags + * \return ldns_pkt* a packet with the reply from the nameserver + */ +ldns_status ldns_resolver_send(ldns_pkt **answer, ldns_resolver *r, const ldns_rdf *name, ldns_rr_type t, ldns_rr_class c, uint16_t flags); + +/** + * Send the given packet to a nameserver + * \param[out] **answer a pointer to a ldns_pkt pointer (initialized by this function) + * \param[in] *r operate using this resolver + * \param[in] *query_pkt query + */ +ldns_status ldns_resolver_send_pkt(ldns_pkt **answer, ldns_resolver *r, ldns_pkt *query_pkt); + +/** + * Send a query to a nameserver + * \param[in] *r operate using this resolver + * \param[in] *name query for this name + * \param[in] *t query for this type (may be 0, defaults to A) + * \param[in] *c query for this class (may be 0, default to IN) + * \param[in] flags the query flags + * \return ldns_pkt* a packet with the reply from the nameserver + * if _defnames is true the default domain will be added + */ +ldns_pkt* ldns_resolver_query(const ldns_resolver *r, const ldns_rdf *name, ldns_rr_type t, ldns_rr_class c, uint16_t flags); + + +/** + * Create a new resolver structure + * \return ldns_resolver* pointer to new strcture + */ +ldns_resolver* ldns_resolver_new(void); + +/** + * Create a resolver structure from a file like /etc/resolv.conf + * \param[out] r the new resolver + * \param[in] fp file pointer to create new resolver from + * if NULL use /etc/resolv.conf + * \return LDNS_STATUS_OK or the error + */ +ldns_status ldns_resolver_new_frm_fp(ldns_resolver **r, FILE *fp); + +/** + * Create a resolver structure from a file like /etc/resolv.conf + * \param[out] r the new resolver + * \param[in] fp file pointer to create new resolver from + * if NULL use /etc/resolv.conf + * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes) + * \return LDNS_STATUS_OK or the error + */ +ldns_status ldns_resolver_new_frm_fp_l(ldns_resolver **r, FILE *fp, int *line_nr); + +/** + * Configure a resolver by means of a resolv.conf file + * The file may be NULL in which case there will be + * looked the RESOLV_CONF (defaults to /etc/resolv.conf + * \param[out] r the new resolver + * \param[in] filename the filename to use + * \return LDNS_STATUS_OK or the error + */ +ldns_status ldns_resolver_new_frm_file(ldns_resolver **r, const char *filename); + +/** + * Frees the allocated space for this resolver. Only frees the resolver pionter! You should probably be using _deep_free. + * \param res resolver to free + */ +void ldns_resolver_free(ldns_resolver *res); + +/** + * Frees the allocated space for this resolver and all it's data + * \param res resolver to free + */ +void ldns_resolver_deep_free(ldns_resolver *res); + +/** + * Get the next stream of RRs in a AXFR + * \param[in] resolver the resolver to use. First ldns_axfr_start() must be + * called + * \return ldns_rr the next RR from the AXFR stream + * After you get this returned RR (not NULL: on error), then check if + * ldns_axfr_complete() is true to see if the zone transfer has completed. + */ +ldns_rr* ldns_axfr_next(ldns_resolver *resolver); + +/** + * Returns true if the axfr transfer has completed (i.e. 2 SOA RRs and no errors were encountered + * \param[in] resolver the resolver that is used + * \return bool true if axfr transfer was completed without error + */ +bool ldns_axfr_complete(const ldns_resolver *resolver); + +/** + * Returns a pointer to the last ldns_pkt that was sent by the server in the AXFR transfer + * uasable for instance to get the error code on failure + * \param[in] res the resolver that was used in the axfr transfer + * \return ldns_pkt the last packet sent + */ +ldns_pkt *ldns_axfr_last_pkt(const ldns_resolver *res); + +/** + * Randomize the nameserver list in the resolver + * \param[in] r the resolver + */ +void ldns_resolver_nameservers_randomize(ldns_resolver *r); + +/** + * Returns true if at least one of the provided keys is a trust anchor + * \param[in] r the current resolver + * \param[in] keys the keyset to check + * \param[out] trusted_keys the subset of trusted keys in the 'keys' rrset + * \return true if at least one of the provided keys is a configured trust anchor + */ +bool ldns_resolver_trusted_key(const ldns_resolver *r, ldns_rr_list * keys, ldns_rr_list * trusted_keys); + +#ifdef __cplusplus +} +#endif + +#endif /* LDNS_RESOLVER_H */ diff --git a/ldns/rr.h b/ldns/rr.h new file mode 100644 index 00000000000..9882931b488 --- /dev/null +++ b/ldns/rr.h @@ -0,0 +1,887 @@ +/* + * rr.h - resource record definitions + * + * a Net::DNS like library for C + * + * (c) NLnet Labs, 2005-2006 + * + * See the file LICENSE for the license + */ + +/** + * \file + * + * Contains the definition of ldns_rr and functions to manipulate those. + */ + + +#ifndef LDNS_RR_H +#define LDNS_RR_H + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** Maximum length of a dname label */ +#define LDNS_MAX_LABELLEN 63 +/** Maximum length of a complete dname */ +#define LDNS_MAX_DOMAINLEN 255 +/** Maximum number of pointers in 1 dname */ +#define LDNS_MAX_POINTERS 65535 +/** The bytes TTL, CLASS and length use up in an rr */ +#define LDNS_RR_OVERHEAD 10 + +/* The first fields are 'common' and can be referenced instantly */ +#define LDNS_RDATA_FIELD_DESCRIPTORS_COMMON 52 + + + +/** + * The different RR classes. + */ +enum ldns_enum_rr_class +{ + /** the Internet */ + LDNS_RR_CLASS_IN = 1, + /** Chaos class */ + LDNS_RR_CLASS_CH = 3, + /** Hesiod (Dyer 87) */ + LDNS_RR_CLASS_HS = 4, + /** None class, dynamic update */ + LDNS_RR_CLASS_NONE = 254, + /** Any class */ + LDNS_RR_CLASS_ANY = 255, + + LDNS_RR_CLASS_FIRST = 0, + LDNS_RR_CLASS_LAST = 65535, + LDNS_RR_CLASS_COUNT = LDNS_RR_CLASS_LAST - LDNS_RR_CLASS_FIRST + 1 +}; +typedef enum ldns_enum_rr_class ldns_rr_class; + +/** + * Used to specify whether compression is allowed. + */ +enum ldns_enum_rr_compress +{ + /** compression is allowed */ + LDNS_RR_COMPRESS, + LDNS_RR_NO_COMPRESS +}; +typedef enum ldns_enum_rr_compress ldns_rr_compress; + +/** + * The different RR types. + */ +enum ldns_enum_rr_type +{ + /** a host address */ + LDNS_RR_TYPE_A = 1, + /** an authoritative name server */ + LDNS_RR_TYPE_NS = 2, + /** a mail destination (Obsolete - use MX) */ + LDNS_RR_TYPE_MD = 3, + /** a mail forwarder (Obsolete - use MX) */ + LDNS_RR_TYPE_MF = 4, + /** the canonical name for an alias */ + LDNS_RR_TYPE_CNAME = 5, + /** marks the start of a zone of authority */ + LDNS_RR_TYPE_SOA = 6, + /** a mailbox domain name (EXPERIMENTAL) */ + LDNS_RR_TYPE_MB = 7, + /** a mail group member (EXPERIMENTAL) */ + LDNS_RR_TYPE_MG = 8, + /** a mail rename domain name (EXPERIMENTAL) */ + LDNS_RR_TYPE_MR = 9, + /** a null RR (EXPERIMENTAL) */ + LDNS_RR_TYPE_NULL = 10, + /** a well known service description */ + LDNS_RR_TYPE_WKS = 11, + /** a domain name pointer */ + LDNS_RR_TYPE_PTR = 12, + /** host information */ + LDNS_RR_TYPE_HINFO = 13, + /** mailbox or mail list information */ + LDNS_RR_TYPE_MINFO = 14, + /** mail exchange */ + LDNS_RR_TYPE_MX = 15, + /** text strings */ + LDNS_RR_TYPE_TXT = 16, + /** RFC1183 */ + LDNS_RR_TYPE_RP = 17, + /** RFC1183 */ + LDNS_RR_TYPE_AFSDB = 18, + /** RFC1183 */ + LDNS_RR_TYPE_X25 = 19, + /** RFC1183 */ + LDNS_RR_TYPE_ISDN = 20, + /** RFC1183 */ + LDNS_RR_TYPE_RT = 21, + /** RFC1706 */ + LDNS_RR_TYPE_NSAP = 22, + /** RFC1348 */ + LDNS_RR_TYPE_NSAP_PTR = 23, + /** 2535typecode */ + LDNS_RR_TYPE_SIG = 24, + /** 2535typecode */ + LDNS_RR_TYPE_KEY = 25, + /** RFC2163 */ + LDNS_RR_TYPE_PX = 26, + /** RFC1712 */ + LDNS_RR_TYPE_GPOS = 27, + /** ipv6 address */ + LDNS_RR_TYPE_AAAA = 28, + /** LOC record RFC1876 */ + LDNS_RR_TYPE_LOC = 29, + /** 2535typecode */ + LDNS_RR_TYPE_NXT = 30, + /** draft-ietf-nimrod-dns-01.txt */ + LDNS_RR_TYPE_EID = 31, + /** draft-ietf-nimrod-dns-01.txt */ + LDNS_RR_TYPE_NIMLOC = 32, + /** SRV record RFC2782 */ + LDNS_RR_TYPE_SRV = 33, + /** http://www.jhsoft.com/rfc/af-saa-0069.000.rtf */ + LDNS_RR_TYPE_ATMA = 34, + /** RFC2915 */ + LDNS_RR_TYPE_NAPTR = 35, + /** RFC2230 */ + LDNS_RR_TYPE_KX = 36, + /** RFC2538 */ + LDNS_RR_TYPE_CERT = 37, + /** RFC2874 */ + LDNS_RR_TYPE_A6 = 38, + /** RFC2672 */ + LDNS_RR_TYPE_DNAME = 39, + /** dnsind-kitchen-sink-02.txt */ + LDNS_RR_TYPE_SINK = 40, + /** Pseudo OPT record... */ + LDNS_RR_TYPE_OPT = 41, + /** RFC3123 */ + LDNS_RR_TYPE_APL = 42, + /** draft-ietf-dnsext-delegation */ + LDNS_RR_TYPE_DS = 43, + /** SSH Key Fingerprint */ + LDNS_RR_TYPE_SSHFP = 44, /* RFC 4255 */ + /** IPsec Key */ + LDNS_RR_TYPE_IPSECKEY = 45, /* RFC 4025 */ + /** DNSSEC */ + LDNS_RR_TYPE_RRSIG = 46, /* RFC 4034 */ + LDNS_RR_TYPE_NSEC = 47, /* RFC 4034 */ + LDNS_RR_TYPE_DNSKEY = 48, /* RFC 4034 */ + + LDNS_RR_TYPE_DHCID = 49, /* RFC 4701 */ + /* NSEC3 */ + LDNS_RR_TYPE_NSEC3 = 50, /* RFC 5155 */ + LDNS_RR_TYPE_NSEC3PARAM = 51, /* RFC 5155 */ + LDNS_RR_TYPE_NSEC3PARAMS = 51, + + /** draft-ietf-dnsop-trust-history */ + LDNS_RR_TYPE_TALINK = 58, + + LDNS_RR_TYPE_SPF = 99, + + LDNS_RR_TYPE_UINFO = 100, + LDNS_RR_TYPE_UID = 101, + LDNS_RR_TYPE_GID = 102, + LDNS_RR_TYPE_UNSPEC = 103, + + LDNS_RR_TYPE_TSIG = 250, + LDNS_RR_TYPE_IXFR = 251, + LDNS_RR_TYPE_AXFR = 252, + /** A request for mailbox-related records (MB, MG or MR) */ + LDNS_RR_TYPE_MAILB = 253, + /** A request for mail agent RRs (Obsolete - see MX) */ + LDNS_RR_TYPE_MAILA = 254, + /** any type (wildcard) */ + LDNS_RR_TYPE_ANY = 255, + + /* RFC 4431, 5074, DNSSEC Lookaside Validation */ + LDNS_RR_TYPE_DLV = 32769, + + /* type codes from nsec3 experimental phase + LDNS_RR_TYPE_NSEC3 = 65324, + LDNS_RR_TYPE_NSEC3PARAMS = 65325, */ + LDNS_RR_TYPE_FIRST = 0, + LDNS_RR_TYPE_LAST = 65535, + LDNS_RR_TYPE_COUNT = LDNS_RR_TYPE_LAST - LDNS_RR_TYPE_FIRST + 1 +}; +typedef enum ldns_enum_rr_type ldns_rr_type; + +/** + * Resource Record + * + * This is the basic DNS element that contains actual data + * + * From RFC1035: + *
+3.2.1. Format
+
+All RRs have the same top level format shown below:
+
+                                    1  1  1  1  1  1
+      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    |                                               |
+    /                                               /
+    /                      NAME                     /
+    |                                               |
+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    |                      TYPE                     |
+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    |                     CLASS                     |
+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    |                      TTL                      |
+    |                                               |
+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+    |                   RDLENGTH                    |
+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
+    /                     RDATA                     /
+    /                                               /
+    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+NAME            an owner name, i.e., the name of the node to which this
+                resource record pertains.
+
+TYPE            two octets containing one of the RR TYPE codes.
+
+CLASS           two octets containing one of the RR CLASS codes.
+
+TTL             a 32 bit signed integer that specifies the time interval
+                that the resource record may be cached before the source
+                of the information should again be consulted.  Zero
+                values are interpreted to mean that the RR can only be
+                used for the transaction in progress, and should not be
+                cached.  For example, SOA records are always distributed
+                with a zero TTL to prohibit caching.  Zero values can
+                also be used for extremely volatile data.
+
+RDLENGTH        an unsigned 16 bit integer that specifies the length in
+                octets of the RDATA field.
+
+RDATA           a variable length string of octets that describes the
+                resource.  The format of this information varies
+                according to the TYPE and CLASS of the resource record.
+ * 
+ * + * The actual amount and type of rdata fields depend on the RR type of the + * RR, and can be found by using \ref ldns_rr_descriptor functions. + */ +struct ldns_struct_rr +{ + /** Owner name, uncompressed */ + ldns_rdf *_owner; + /** Time to live */ + uint32_t _ttl; + /** Number of data fields */ + size_t _rd_count; + /** the type of the RR. A, MX etc. */ + ldns_rr_type _rr_type; + /** Class of the resource record. */ + ldns_rr_class _rr_class; + /* everything in the rdata is in network order */ + /** The array of rdata's */ + ldns_rdf **_rdata_fields; + /** question rr [it would be nicer if thous is after _rd_count] + ABI change: Fix this in next major release + */ + bool _rr_question; +}; +typedef struct ldns_struct_rr ldns_rr; + +/** + * List or Set of Resource Records + * + * Contains a list of rr's
+ * No official RFC-like checks are made + */ +struct ldns_struct_rr_list +{ + size_t _rr_count; + size_t _rr_capacity; + ldns_rr **_rrs; +}; +typedef struct ldns_struct_rr_list ldns_rr_list; + +/** + * Contains all information about resource record types. + * + * This structure contains, for all rr types, the rdata fields that are defined. + */ +struct ldns_struct_rr_descriptor +{ + /** Type of the RR that is described here */ + ldns_rr_type _type; + /** Textual name of the RR type. */ + const char *_name; + /** Minimum number of rdata fields in the RRs of this type. */ + uint8_t _minimum; + /** Maximum number of rdata fields in the RRs of this type. */ + uint8_t _maximum; + /** Wireformat specification for the rr, i.e. the types of rdata fields in their respective order. */ + const ldns_rdf_type *_wireformat; + /** Special rdf types */ + ldns_rdf_type _variable; + /** Specifies whether compression can be used for dnames in this RR type. */ + ldns_rr_compress _compress; + /** The number of DNAMEs in the _wireformat string, for parsing. */ + uint8_t _dname_count; +}; +typedef struct ldns_struct_rr_descriptor ldns_rr_descriptor; + +/** + * creates a new rr structure. + * \return ldns_rr * + */ +ldns_rr* ldns_rr_new(void); + +/** + * creates a new rr structure, based on the given type. + * alloc enough space to hold all the rdf's + */ +ldns_rr* ldns_rr_new_frm_type(ldns_rr_type t); + +/** + * frees an RR structure + * \param[in] *rr the RR to be freed + * \return void + */ +void ldns_rr_free(ldns_rr *rr); + +/** + * creates an rr from a string. + * The string should be a fully filled-in rr, like + * ownername <space> TTL <space> CLASS <space> + * TYPE <space> RDATA. + * \param[out] n the rr to return + * \param[in] str the string to convert + * \param[in] default_ttl default ttl value for the rr. + * If 0 DEF_TTL will be used + * \param[in] origin when the owner is relative add this. + * The caller must ldns_rdf_deep_free it. + * \param[out] prev the previous ownername. if this value is not NULL, + * the function overwrites this with the ownername found in this + * string. The caller must then ldns_rdf_deep_free it. + * \return a status msg describing an error or LDNS_STATUS_OK + */ +ldns_status ldns_rr_new_frm_str(ldns_rr **n, const char *str, + uint32_t default_ttl, ldns_rdf *origin, + ldns_rdf **prev); + +/** + * creates an rr for the question section from a string, i.e. + * without RDATA fields + * Origin and previous RR functionality are the same as in + * ldns_rr_new_frm_str() + * \param[out] n the rr to return + * \param[in] str the string to convert + * \param[in] origin when the owner is relative add this. + * The caller must ldns_rdf_deep_free it. + * \param prev the previous ownername. the function overwrite this with + * the current found ownername. The caller must ldns_rdf_deep_free it. + * \return a status msg describing an error or LDNS_STATUS_OK + */ +ldns_status ldns_rr_new_question_frm_str(ldns_rr **n, const char *str, + ldns_rdf *origin, ldns_rdf **prev); + +/** + * creates a new rr from a file containing a string. + * \param[out] rr the new rr + * \param[in] fp the file pointer to use + * \param[in] default_ttl pointer to a default ttl for the rr. If NULL DEF_TTL will be used + * the pointer will be updated if the file contains a $TTL directive + * \param[in] origin when the owner is relative add this + * the pointer will be updated if the file contains a $ORIGIN directive + * The caller must ldns_rdf_deep_free it. + * \param[in] prev when the owner is whitespaces use this as the * ownername + * the pointer will be updated after the call + * The caller must ldns_rdf_deep_free it. + * \return a ldns_status with an error or LDNS_STATUS_OK + */ +ldns_status ldns_rr_new_frm_fp(ldns_rr **rr, FILE *fp, uint32_t *default_ttl, ldns_rdf **origin, ldns_rdf **prev); + +/** + * creates a new rr from a file containing a string. + * \param[out] rr the new rr + * \param[in] fp the file pointer to use + * \param[in] default_ttl a default ttl for the rr. If NULL DEF_TTL will be used + * the pointer will be updated if the file contains a $TTL directive + * \param[in] origin when the owner is relative add this + * the pointer will be updated if the file contains a $ORIGIN directive + * The caller must ldns_rdf_deep_free it. + * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes) + * \param[in] prev when the owner is whitespaces use this as the * ownername + * the pointer will be updated after the call + * The caller must ldns_rdf_deep_free it. + * \return a ldns_status with an error or LDNS_STATUS_OK + */ +ldns_status ldns_rr_new_frm_fp_l(ldns_rr **rr, FILE *fp, uint32_t *default_ttl, ldns_rdf **origin, ldns_rdf **prev, int *line_nr); + +/** + * sets the owner in the rr structure. + * \param[in] *rr rr to operate on + * \param[in] *owner set to this owner + * \return void + */ +void ldns_rr_set_owner(ldns_rr *rr, ldns_rdf *owner); + +/** + * sets the question flag in the rr structure. + * \param[in] *rr rr to operate on + * \param[in] question question flag + * \return void + */ +void ldns_rr_set_question(ldns_rr *rr, bool question); + +/** + * sets the ttl in the rr structure. + * \param[in] *rr rr to operate on + * \param[in] ttl set to this ttl + * \return void + */ +void ldns_rr_set_ttl(ldns_rr *rr, uint32_t ttl); + +/** + * sets the rd_count in the rr. + * \param[in] *rr rr to operate on + * \param[in] count set to this count + * \return void + */ +void ldns_rr_set_rd_count(ldns_rr *rr, size_t count); + +/** + * sets the type in the rr. + * \param[in] *rr rr to operate on + * \param[in] rr_type set to this type + * \return void + */ +void ldns_rr_set_type(ldns_rr *rr, ldns_rr_type rr_type); + +/** + * sets the class in the rr. + * \param[in] *rr rr to operate on + * \param[in] rr_class set to this class + * \return void + */ +void ldns_rr_set_class(ldns_rr *rr, ldns_rr_class rr_class); + +/** + * sets a rdf member, it will be set on the + * position given. The old value is returned, like pop. + * \param[in] *rr the rr to operate on + * \param[in] *f the rdf to set + * \param[in] position the position the set the rdf + * \return the old value in the rr, NULL on failyre + */ +ldns_rdf* ldns_rr_set_rdf(ldns_rr *rr, const ldns_rdf *f, size_t position); + +/** + * sets rd_field member, it will be + * placed in the next available spot. + * \param[in] *rr rr to operate on + * \param[in] *f the data field member to set + * \return bool + */ +bool ldns_rr_push_rdf(ldns_rr *rr, const ldns_rdf *f); + +/** + * removes a rd_field member, it will be + * popped from the last position. + * \param[in] *rr rr to operate on + * \return rdf which was popped (null if nothing) + */ +ldns_rdf* ldns_rr_pop_rdf(ldns_rr *rr); + +/** + * returns the rdata field member counter. + * \param[in] *rr rr to operate on + * \param[in] nr the number of the rdf to return + * \return ldns_rdf * + */ +ldns_rdf* ldns_rr_rdf(const ldns_rr *rr, size_t nr); + +/** + * returns the owner name of an rr structure. + * \param[in] *rr rr to operate on + * \return ldns_rdf * + */ +ldns_rdf* ldns_rr_owner(const ldns_rr *rr); + +/** + * returns the question flag of an rr structure. + * \param[in] *rr rr to operate on + * \return bool true if question + */ +bool ldns_rr_is_question(const ldns_rr *rr); + +/** + * returns the ttl of an rr structure. + * \param[in] *rr the rr to read from + * \return the ttl of the rr + */ +uint32_t ldns_rr_ttl(const ldns_rr *rr); + +/** + * returns the rd_count of an rr structure. + * \param[in] *rr the rr to read from + * \return the rd count of the rr + */ +size_t ldns_rr_rd_count(const ldns_rr *rr); + +/** + * returns the type of the rr. + * \param[in] *rr the rr to read from + * \return the type of the rr + */ +ldns_rr_type ldns_rr_get_type(const ldns_rr *rr); + +/** + * returns the class of the rr. + * \param[in] *rr the rr to read from + * \return the class of the rr + */ +ldns_rr_class ldns_rr_get_class(const ldns_rr *rr); + +/* rr_lists */ + +/** + * returns the number of rr's in an rr_list. + * \param[in] rr_list the rr_list to read from + * \return the number of rr's + */ +size_t ldns_rr_list_rr_count(const ldns_rr_list *rr_list); + +/** + * sets the number of rr's in an rr_list. + * \param[in] rr_list the rr_list to set the count on + * \param[in] count the number of rr in this list + * \return void + */ +void ldns_rr_list_set_rr_count(ldns_rr_list *rr_list, size_t count); + +/** + * set a rr on a specific index in a ldns_rr_list + * \param[in] rr_list the rr_list to use + * \param[in] r the rr to set + * \param[in] count index into the rr_list + * \return the old rr which was stored in the rr_list, or + * NULL is the index was too large + * set a specific rr */ +ldns_rr * ldns_rr_list_set_rr(ldns_rr_list *rr_list, const ldns_rr *r, size_t count); + +/** + * returns a specific rr of an rrlist. + * \param[in] rr_list the rr_list to read from + * \param[in] nr return this rr + * \return the rr at position nr + */ +ldns_rr* ldns_rr_list_rr(const ldns_rr_list *rr_list, size_t nr); + +/** + * creates a new rr_list structure. + * \return a new rr_list structure + */ +ldns_rr_list* ldns_rr_list_new(); + +/** + * frees an rr_list structure. + * \param[in] rr_list the list to free + */ +void ldns_rr_list_free(ldns_rr_list *rr_list); + +/** + * frees an rr_list structure and all rrs contained therein. + * \param[in] rr_list the list to free + */ +void ldns_rr_list_deep_free(ldns_rr_list *rr_list); + +/** + * concatenates two ldns_rr_lists together. This modifies + * *left (to extend it and add the pointers from *right). + * \param[in] left the leftside + * \param[in] right the rightside + * \return a left with right concatenated to it + */ +bool ldns_rr_list_cat(ldns_rr_list *left, ldns_rr_list *right); + +/** + * concatenates two ldns_rr_lists together, but makes clones of the rr's + * (instead of pointer copying). + * \param[in] left the leftside + * \param[in] right the rightside + * \return a new rr_list with leftside/rightside concatenated + */ +ldns_rr_list* ldns_rr_list_cat_clone(ldns_rr_list *left, ldns_rr_list *right); + +/** + * pushes an rr to an rrlist. + * \param[in] rr_list the rr_list to push to + * \param[in] rr the rr to push + * \return false on error, otherwise true + */ +bool ldns_rr_list_push_rr(ldns_rr_list *rr_list, const ldns_rr *rr); + +/** + * pushes an rr_list to an rrlist. + * \param[in] rr_list the rr_list to push to + * \param[in] push_list the rr_list to push + * \return false on error, otherwise true + */ +bool ldns_rr_list_push_rr_list(ldns_rr_list *rr_list, const ldns_rr_list *push_list); + +/** + * pops the last rr from an rrlist. + * \param[in] rr_list the rr_list to pop from + * \return NULL if nothing to pop. Otherwise the popped RR + */ +ldns_rr* ldns_rr_list_pop_rr(ldns_rr_list *rr_list); + +/** + * pops an rr_list of size s from an rrlist. + * \param[in] rr_list the rr_list to pop from + * \param[in] size the number of rr's to pop + * \return NULL if nothing to pop. Otherwise the popped rr_list + */ +ldns_rr_list* ldns_rr_list_pop_rr_list(ldns_rr_list *rr_list, size_t size); + +/** + * returns true if the given rr is one of the rrs in the + * list, or if it is equal to one + * \param[in] rr_list the rr_list to check + * \param[in] rr the rr to check + * \return true if rr_list contains rr, false otherwise + */ +bool ldns_rr_list_contains_rr(const ldns_rr_list *rr_list, ldns_rr *rr); + +/** + * checks if an rr_list is a rrset. + * \param[in] rr_list the rr_list to check + * \return true if it is an rrset otherwise false + */ +bool ldns_is_rrset(ldns_rr_list *rr_list); + +/** + * pushes an rr to an rrset (which really are rr_list's). + * \param[in] *rr_list the rrset to push the rr to + * \param[in] *rr the rr to push + * \return true if the push succeeded otherwise false + */ +bool ldns_rr_set_push_rr(ldns_rr_list *rr_list, ldns_rr *rr); + +/** + * pops the last rr from an rrset. This function is there only + * for the symmetry. + * \param[in] rr_list the rr_list to pop from + * \return NULL if nothing to pop. Otherwise the popped RR + * + */ +ldns_rr* ldns_rr_set_pop_rr(ldns_rr_list *rr_list); + +/** + * pops the first rrset from the list, + * the list must be sorted, so that all rr's from each rrset + * are next to each other + */ +ldns_rr_list *ldns_rr_list_pop_rrset(ldns_rr_list *rr_list); + + +/** + * retrieves a rrtype by looking up its name. + * \param[in] name a string with the name + * \return the type which corresponds with the name + */ +ldns_rr_type ldns_get_rr_type_by_name(const char *name); + +/** + * retrieves a class by looking up its name. + * \param[in] name string with the name + * \return the cass which corresponds with the name + */ +ldns_rr_class ldns_get_rr_class_by_name(const char *name); + +/** + * clones a rr and all its data + * \param[in] rr the rr to clone + * \return the new rr or NULL on failure + */ +ldns_rr* ldns_rr_clone(const ldns_rr *rr); + +/** + * clones an rrlist. + * \param[in] rrlist the rrlist to clone + * \return the cloned rr list + */ +ldns_rr_list* ldns_rr_list_clone(const ldns_rr_list *rrlist); + +/** + * sorts an rr_list (canonical wire format). the sorting is done inband. + * \param[in] unsorted the rr_list to be sorted + * \return void + */ +void ldns_rr_list_sort(ldns_rr_list *unsorted); + +/** + * compares two rrs. The TTL is not looked at. + * \param[in] rr1 the first one + * \param[in] rr2 the second one + * \return 0 if equal + * -1 if rr1 comes before rr2 + * +1 if rr2 comes before rr1 + */ +int ldns_rr_compare(const ldns_rr *rr1, const ldns_rr *rr2); + +/** + * compares two rrs, up to the rdata. + * \param[in] rr1 the first one + * \param[in] rr2 the second one + * \return 0 if equal + * -1 if rr1 comes before rr2 + * +1 if rr2 comes before rr1 + */ +int ldns_rr_compare_no_rdata(const ldns_rr *rr1, const ldns_rr *rr2); + +/** + * compares the wireformat of two rrs, contained in the given buffers. + * \param[in] rr1_buf the first one + * \param[in] rr2_buf the second one + * \return 0 if equal + * -1 if rr1_buf comes before rr2_buf + * +1 if rr2_buf comes before rr1_buf + */ +int ldns_rr_compare_wire(ldns_buffer *rr1_buf, ldns_buffer *rr2_buf); + +/** + * returns true of the given rr's are equal. + * Also returns true if one record is a DS that represents the + * same DNSKEY record as the other record + * \param[in] rr1 the first rr + * \param[in] rr2 the second rr + * \return true if equal otherwise false + */ +bool ldns_rr_compare_ds(const ldns_rr *rr1, const ldns_rr *rr2); + +/** + * compares two rr listss. + * \param[in] rrl1 the first one + * \param[in] rrl2 the second one + * \return 0 if equal + * -1 if rrl1 comes before rrl2 + * +1 if rrl2 comes before rrl1 + */ +int ldns_rr_list_compare(const ldns_rr_list *rrl1, const ldns_rr_list *rrl2); + +/** + * calculates the uncompressed size of an RR. + * \param[in] r the rr to operate on + * \return size of the rr + */ +size_t ldns_rr_uncompressed_size(const ldns_rr *r); + +/** + * converts each dname in a rr to its canonical form. + * \param[in] rr the rr to work on + * \return void + */ +void ldns_rr2canonical(ldns_rr *rr); + +/** + * converts each dname in each rr in a rr_list to its canonical form. + * \param[in] rr_list the rr_list to work on + * \return void + */ +void ldns_rr_list2canonical(ldns_rr_list *rr_list); + +/** + * counts the number of labels of the ownername. + * \param[in] rr count the labels of this rr + * \return the number of labels + */ +uint8_t ldns_rr_label_count(ldns_rr *rr); + +/** + * returns the resource record descriptor for the given rr type. + * + * \param[in] type the type value of the rr type + *\return the ldns_rr_descriptor for this type + */ +const ldns_rr_descriptor *ldns_rr_descript(uint16_t type); + +/** + * returns the minimum number of rdata fields of the rr type this descriptor describes. + * + * \param[in] descriptor for an rr type + * \return the minimum number of rdata fields + */ +size_t ldns_rr_descriptor_minimum(const ldns_rr_descriptor *descriptor); + +/** + * returns the maximum number of rdata fields of the rr type this descriptor describes. + * + * \param[in] descriptor for an rr type + * \return the maximum number of rdata fields + */ +size_t ldns_rr_descriptor_maximum(const ldns_rr_descriptor *descriptor); + +/** + * returns the rdf type for the given rdata field number of the rr type for the given descriptor. + * + * \param[in] descriptor for an rr type + * \param[in] field the field number + * \return the rdf type for the field + */ +ldns_rdf_type ldns_rr_descriptor_field_type(const ldns_rr_descriptor *descriptor, size_t field); + +/** + * Return the rr_list which matches the rdf at position field. Think + * type-covered stuff for RRSIG + * + * \param[in] l the rr_list to look in + * \param[in] r the rdf to use for the comparison + * \param[in] pos at which position can we find the rdf + * + * \return a new rr list with only the RRs that match + * + */ +ldns_rr_list *ldns_rr_list_subtype_by_rdf(ldns_rr_list *l, ldns_rdf *r, size_t pos); + +/** + * convert an rdf of type LDNS_RDF_TYPE_TYPE to an actual + * LDNS_RR_TYPE. This is usefull in the case when inspecting + * the rrtype covered field of an RRSIG. + * \param[in] rd the rdf to look at + * \return a ldns_rr_type with equivalent LDNS_RR_TYPE + * + */ +ldns_rr_type ldns_rdf2rr_type(const ldns_rdf *rd); + +/** + * Returns the type of the first element of the RR + * If there are no elements present, 0 is returned + * + * \param[in] rr_list The rr list + * \return rr_type of the first element, or 0 if the list is empty + */ +ldns_rr_type +ldns_rr_list_type(const ldns_rr_list *rr_list); + +/** + * Returns the owner domain name rdf of the first element of the RR + * If there are no elements present, NULL is returned + * + * \param[in] rr_list The rr list + * \return dname of the first element, or NULL if the list is empty + */ +ldns_rdf * +ldns_rr_list_owner(const ldns_rr_list *rr_list); + +#ifdef __cplusplus +} +#endif + +#endif /* LDNS_RR_H */ diff --git a/ldns/rr_functions.h b/ldns/rr_functions.h new file mode 100644 index 00000000000..09a28dd7f87 --- /dev/null +++ b/ldns/rr_functions.h @@ -0,0 +1,363 @@ +/* + * rr_functions.h + * + * the .h file with defs for the per rr + * functions + * + * a Net::DNS like library for C + * + * (c) NLnet Labs, 2005-2006 + * + * See the file LICENSE for the license + */ +#ifndef LDNS_RR_FUNCTIONS_H +#define LDNS_RR_FUNCTIONS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \file + * + * Defines some extra convenience functions for ldns_rr structures + */ + +/* A / AAAA */ +/** + * returns the address of a LDNS_RR_TYPE_A rr + * \param[in] r the resource record + * \return a ldns_rdf* with the address or NULL on failure + */ +ldns_rdf* ldns_rr_a_address(const ldns_rr *r); + +/** + * sets the address of a LDNS_RR_TYPE_A rr + * \param[in] r the rr to use + * \param[in] f the address to set + * \return true on success, false otherwise + */ +bool ldns_rr_a_set_address(ldns_rr *r, ldns_rdf *f); + +/* NS */ +/** + * returns the name of a LDNS_RR_TYPE_NS rr + * \param[in] r the resource record + * \return a ldns_rdf* with the name or NULL on failure + */ +ldns_rdf* ldns_rr_ns_nsdname(const ldns_rr *r); + +/* MX */ +/** + * returns the mx pref. of a LDNS_RR_TYPE_MX rr + * \param[in] r the resource record + * \return a ldns_rdf* with the preference or NULL on failure + */ +ldns_rdf* ldns_rr_mx_preference(const ldns_rr *r); +/** + * returns the mx host of a LDNS_RR_TYPE_MX rr + * \param[in] r the resource record + * \return a ldns_rdf* with the name of the MX host or NULL on failure + */ +ldns_rdf* ldns_rr_mx_exchange(const ldns_rr *r); + +/* RRSIG */ +/** + * returns the type covered of a LDNS_RR_TYPE_RRSIG rr + * \param[in] r the resource record + * \return a ldns_rdf* with the type covered or NULL on failure + */ +ldns_rdf* ldns_rr_rrsig_typecovered(const ldns_rr *r); +/** + * sets the typecovered of a LDNS_RR_TYPE_RRSIG rr + * \param[in] r the rr to use + * \param[in] f the typecovered to set + * \return true on success, false otherwise + */ +bool ldns_rr_rrsig_set_typecovered(ldns_rr *r, ldns_rdf *f); +/** + * returns the algorithm of a LDNS_RR_TYPE_RRSIG RR + * \param[in] r the resource record + * \return a ldns_rdf* with the algorithm or NULL on failure + */ +ldns_rdf* ldns_rr_rrsig_algorithm(const ldns_rr *r); +/** + * sets the algorithm of a LDNS_RR_TYPE_RRSIG rr + * \param[in] r the rr to use + * \param[in] f the algorithm to set + * \return true on success, false otherwise + */ +bool ldns_rr_rrsig_set_algorithm(ldns_rr *r, ldns_rdf *f); +/** + * returns the number of labels of a LDNS_RR_TYPE_RRSIG RR + * \param[in] r the resource record + * \return a ldns_rdf* with the number of labels or NULL on failure + */ +ldns_rdf *ldns_rr_rrsig_labels(const ldns_rr *r); +/** + * sets the number of labels of a LDNS_RR_TYPE_RRSIG rr + * \param[in] r the rr to use + * \param[in] f the number of labels to set + * \return true on success, false otherwise + */ +bool ldns_rr_rrsig_set_labels(ldns_rr *r, ldns_rdf *f); +/** + * returns the original TTL of a LDNS_RR_TYPE_RRSIG RR + * \param[in] r the resource record + * \return a ldns_rdf* with the original TTL or NULL on failure + */ +ldns_rdf* ldns_rr_rrsig_origttl(const ldns_rr *r); +/** + * sets the original TTL of a LDNS_RR_TYPE_RRSIG rr + * \param[in] r the rr to use + * \param[in] f the original TTL to set + * \return true on success, false otherwise + */ +bool ldns_rr_rrsig_set_origttl(ldns_rr *r, ldns_rdf *f); +/** + * returns the expiration time of a LDNS_RR_TYPE_RRSIG RR + * \param[in] r the resource record + * \return a ldns_rdf* with the expiration time or NULL on failure + */ +ldns_rdf* ldns_rr_rrsig_expiration(const ldns_rr *r); +/** + * sets the expireation date of a LDNS_RR_TYPE_RRSIG rr + * \param[in] r the rr to use + * \param[in] f the expireation date to set + * \return true on success, false otherwise + */ +bool ldns_rr_rrsig_set_expiration(ldns_rr *r, ldns_rdf *f); +/** + * returns the inception time of a LDNS_RR_TYPE_RRSIG RR + * \param[in] r the resource record + * \return a ldns_rdf* with the inception time or NULL on failure + */ +ldns_rdf* ldns_rr_rrsig_inception(const ldns_rr *r); +/** + * sets the inception date of a LDNS_RR_TYPE_RRSIG rr + * \param[in] r the rr to use + * \param[in] f the inception date to set + * \return true on success, false otherwise + */ +bool ldns_rr_rrsig_set_inception(ldns_rr *r, ldns_rdf *f); +/** + * returns the keytag of a LDNS_RR_TYPE_RRSIG RR + * \param[in] r the resource record + * \return a ldns_rdf* with the keytag or NULL on failure + */ +ldns_rdf* ldns_rr_rrsig_keytag(const ldns_rr *r); +/** + * sets the keytag of a LDNS_RR_TYPE_RRSIG rr + * \param[in] r the rr to use + * \param[in] f the keytag to set + * \return true on success, false otherwise + */ +bool ldns_rr_rrsig_set_keytag(ldns_rr *r, ldns_rdf *f); +/** + * returns the signers name of a LDNS_RR_TYPE_RRSIG RR + * \param[in] r the resource record + * \return a ldns_rdf* with the signers name or NULL on failure + */ +ldns_rdf* ldns_rr_rrsig_signame(const ldns_rr *r); +/** + * sets the signers name of a LDNS_RR_TYPE_RRSIG rr + * \param[in] r the rr to use + * \param[in] f the signers name to set + * \return true on success, false otherwise + */ +bool ldns_rr_rrsig_set_signame(ldns_rr *r, ldns_rdf *f); +/** + * returns the signature data of a LDNS_RR_TYPE_RRSIG RR + * \param[in] r the resource record + * \return a ldns_rdf* with the signature data or NULL on failure + */ +ldns_rdf* ldns_rr_rrsig_sig(const ldns_rr *r); +/** + * sets the signature data of a LDNS_RR_TYPE_RRSIG rr + * \param[in] r the rr to use + * \param[in] f the signature data to set + * \return true on success, false otherwise + */ +bool ldns_rr_rrsig_set_sig(ldns_rr *r, ldns_rdf *f); + +/* DNSKEY */ +/** + * returns the flags of a LDNS_RR_TYPE_DNSKEY rr + * \param[in] r the resource record + * \return a ldns_rdf* with the flags or NULL on failure + */ +ldns_rdf* ldns_rr_dnskey_flags(const ldns_rr *r); +/** + * sets the flags of a LDNS_RR_TYPE_DNSKEY rr + * \param[in] r the rr to use + * \param[in] f the flags to set + * \return true on success, false otherwise + */ +bool ldns_rr_dnskey_set_flags(ldns_rr *r, ldns_rdf *f); +/** + * returns the protocol of a LDNS_RR_TYPE_DNSKEY rr + * \param[in] r the resource record + * \return a ldns_rdf* with the protocol or NULL on failure + */ +ldns_rdf* ldns_rr_dnskey_protocol(const ldns_rr *r); +/** + * sets the protocol of a LDNS_RR_TYPE_DNSKEY rr + * \param[in] r the rr to use + * \param[in] f the protocol to set + * \return true on success, false otherwise + */ +bool ldns_rr_dnskey_set_protocol(ldns_rr *r, ldns_rdf *f); +/** + * returns the algorithm of a LDNS_RR_TYPE_DNSKEY rr + * \param[in] r the resource record + * \return a ldns_rdf* with the algorithm or NULL on failure + */ +ldns_rdf* ldns_rr_dnskey_algorithm(const ldns_rr *r); +/** + * sets the algorithm of a LDNS_RR_TYPE_DNSKEY rr + * \param[in] r the rr to use + * \param[in] f the algorithm to set + * \return true on success, false otherwise + */ +bool ldns_rr_dnskey_set_algorithm(ldns_rr *r, ldns_rdf *f); +/** + * returns the key data of a LDNS_RR_TYPE_DNSKEY rr + * \param[in] r the resource record + * \return a ldns_rdf* with the key data or NULL on failure + */ +ldns_rdf* ldns_rr_dnskey_key(const ldns_rr *r); +/** + * sets the key data of a LDNS_RR_TYPE_DNSKEY rr + * \param[in] r the rr to use + * \param[in] f the key data to set + * \return true on success, false otherwise + */ +bool ldns_rr_dnskey_set_key(ldns_rr *r, ldns_rdf *f); + +/** + * get the length of the keydata in bits + * \param[in] keydata the raw key data + * \param[in] len the length of the keydata + * \param[in] alg the cryptographic algorithm this is a key for + * \return the keysize in bits, or 0 on error + */ +size_t ldns_rr_dnskey_key_size_raw(const unsigned char *keydata, + const size_t len, + const ldns_algorithm alg); + +/** + * get the length of the keydata in bits + * \param[in] key the key rr to use + * \return the keysize in bits + */ +size_t ldns_rr_dnskey_key_size(const ldns_rr *key); + +/** + * The type of function to be passed to ldns_rr_soa_increment_func, + * ldns_rr_soa_increment_func_data or ldns_rr_soa_increment_int. + * The function will be called with as the first argument the current serial + * number of the SOA RR to be updated, and as the second argument a value + * given when calling ldns_rr_soa_increment_func_data or + * ldns_rr_soa_increment_int. With ldns_rr_soa_increment_int the pointer + * value holds the integer value passed to ldns_rr_soa_increment_int, + * and it should be cast to intptr_t to be used as an integer by the + * serial modifying function. + */ +typedef uint32_t (*ldns_soa_serial_increment_func_t)(uint32_t, void*); + +/** + * Function to be used with dns_rr_soa_increment_func_int, to set the soa + * serial number. + * \param[in] unused the (unused) current serial number. + * \param[in] data the serial number to be set. + */ +uint32_t ldns_soa_serial_identity(uint32_t unused, void *data); + +/** + * Function to be used with dns_rr_soa_increment_func, to increment the soa + * serial number with one. + * \param[in] s the current serial number. + * \param[in] unused unused. + */ +uint32_t ldns_soa_serial_increment(uint32_t s, void *unused); + +/** + * Function to be used with dns_rr_soa_increment_func_int, to increment the soa + * serial number with a certain amount. + * \param[in] s the current serial number. + * \param[in] data the amount to add to the current serial number. + */ +uint32_t ldns_soa_serial_increment_by(uint32_t s, void *data); + +/** + * Function to be used with ldns_rr_soa_increment_func or + * ldns_rr_soa_increment_func_int to set the soa serial to the number of + * seconds since unix epoch (1-1-1970 00:00). + * When data is given (i.e. the function is called via + * ldns_rr_soa_increment_func_int), it is used as the current time. + * When the resulting serial number is smaller than the current serial number, + * the current serial number is increased by one. + * \param[in] s the current serial number. + * \param[in] data the time in seconds since 1-1-1970 00:00 + */ +uint32_t ldns_soa_serial_unixtime(uint32_t s, void *data); + +/** + * Function to be used with ldns_rr_soa_increment_func or + * ldns_rr_soa_increment_func_int to set the soa serial to the current date + * succeeded by a two digit iteration (datecounter). + * When data is given (i.e. the function is called via + * ldns_rr_soa_increment_func_int), it is used as the current time. + * When the resulting serial number is smaller than the current serial number, + * the current serial number is increased by one. + * \param[in] s the current serial number. + * \param[in] data the time in seconds since 1-1-1970 00:00 + */ +uint32_t ldns_soa_serial_datecounter(uint32_t s, void *data); + +/** + * Increment the serial number of the given SOA by one. + * \param[in] soa The soa rr to be incremented + */ +void ldns_rr_soa_increment( + ldns_rr *soa); + +/** + * Increment the serial number of the given SOA with the given function. + * Included functions to be used here are: ldns_rr_soa_increment, + * ldns_soa_serial_unixtime and ldns_soa_serial_datecounter. + * \param[in] soa The soa rr to be incremented + * \param[in] f the function to use to increment the soa rr. + */ +void ldns_rr_soa_increment_func( + ldns_rr *soa, ldns_soa_serial_increment_func_t f); + +/** + * Increment the serial number of the given SOA with the given function + * passing it the given data argument. + * \param[in] soa The soa rr to be incremented + * \param[in] f the function to use to increment the soa rr. + * \param[in] data this argument will be passed to f as the second argument. + */ +void ldns_rr_soa_increment_func_data( + ldns_rr *soa, ldns_soa_serial_increment_func_t f, void *data); + +/** + * Increment the serial number of the given SOA with the given function + * using data as an argument for the function. + * Included functions to be used here are: ldns_soa_serial_identity, + * ldns_rr_soa_increment_by, ldns_soa_serial_unixtime and + * ldns_soa_serial_datecounter. + * \param[in] soa The soa rr to be incremented + * \param[in] f the function to use to increment the soa rr. + * \param[in] data this argument will be passed to f as the second argument + * (by casting it to void*). + */ +void ldns_rr_soa_increment_func_int( + ldns_rr *soa, ldns_soa_serial_increment_func_t f, int data); + +#ifdef __cplusplus +} +#endif + +#endif /* LDNS_RR_FUNCTIONS_H */ diff --git a/ldns/sha1.h b/ldns/sha1.h new file mode 100644 index 00000000000..d5b1082e670 --- /dev/null +++ b/ldns/sha1.h @@ -0,0 +1,38 @@ +#ifndef LDNS_SHA1_H +#define LDNS_SHA1_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define LDNS_SHA1_BLOCK_LENGTH 64 +#define LDNS_SHA1_DIGEST_LENGTH 20 + +typedef struct { + uint32_t state[5]; + uint64_t count; + unsigned char buffer[LDNS_SHA1_BLOCK_LENGTH]; +} ldns_sha1_ctx; + +void ldns_sha1_init(ldns_sha1_ctx * context); +void ldns_sha1_transform(uint32_t state[5], const unsigned char buffer[LDNS_SHA1_BLOCK_LENGTH]); +void ldns_sha1_update(ldns_sha1_ctx *context, const unsigned char *data, unsigned int len); +void ldns_sha1_final(unsigned char digest[LDNS_SHA1_DIGEST_LENGTH], ldns_sha1_ctx *context); + +/** + * Convenience function to digest a fixed block of data at once. + * + * \param[in] data the data to digest + * \param[in] data_len the length of data in bytes + * \param[out] digest the length of data in bytes + * This pointer MUST have LDNS_SHA1_DIGEST_LENGTH bytes + * available + * \return the SHA1 digest of the given data + */ +unsigned char *ldns_sha1(unsigned char *data, unsigned int data_len, unsigned char *digest); + +#ifdef __cplusplus +} +#endif + +#endif /* LDNS_SHA1_H */ diff --git a/ldns/sha2.h b/ldns/sha2.h new file mode 100644 index 00000000000..238767af45f --- /dev/null +++ b/ldns/sha2.h @@ -0,0 +1,149 @@ +/* + * FILE: sha2.h + * AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/ + * + * Copyright (c) 2000-2001, Aaron D. Gifford + * All rights reserved. + * + * Modified by Jelte Jansen to fit in ldns, and not clash with any + * system-defined SHA code. + * Changes: + * - Renamed (external) functions and constants to fit ldns style + * - Removed uintXX vs. u_intXX smartness, since ldns needs uintXX + * anyway + * - BYTE ORDER check replaced by simple ifdef as defined or not by + * configure.ac + * - Removed _End and _Data functions + * - Added ldns_shaX(data, len, digest) functions + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``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 CONTRIBUTOR(S) 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. + * + * $Id: sha2.h,v 1.1 2001/11/08 00:02:01 adg Exp adg $ + */ + +#ifndef __LDNS_SHA2_H__ +#define __LDNS_SHA2_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + * Import u_intXX_t size_t type definitions from system headers. You + * may need to change this, or define these things yourself in this + * file. + */ +#include + +#if LDNS_BUILD_CONFIG_HAVE_INTTYPES_H + +#include + +#endif /* LDNS_BUILD_CONFIG_HAVE_INTTYPES_H */ + + +/*** SHA-256/384/512 Various Length Definitions ***********************/ +#define LDNS_SHA256_BLOCK_LENGTH 64 +#define LDNS_SHA256_DIGEST_LENGTH 32 +#define LDNS_SHA256_DIGEST_STRING_LENGTH (LDNS_SHA256_DIGEST_LENGTH * 2 + 1) +#define LDNS_SHA384_BLOCK_LENGTH 128 +#define LDNS_SHA384_DIGEST_LENGTH 48 +#define LDNS_SHA384_DIGEST_STRING_LENGTH (LDNS_SHA384_DIGEST_LENGTH * 2 + 1) +#define LDNS_SHA512_BLOCK_LENGTH 128 +#define LDNS_SHA512_DIGEST_LENGTH 64 +#define LDNS_SHA512_DIGEST_STRING_LENGTH (LDNS_SHA512_DIGEST_LENGTH * 2 + 1) + + +/*** SHA-256/384/512 Context Structures *******************************/ + +typedef struct _ldns_sha256_CTX { + uint32_t state[8]; + uint64_t bitcount; + uint8_t buffer[LDNS_SHA256_BLOCK_LENGTH]; +} ldns_sha256_CTX; +typedef struct _ldns_sha512_CTX { + uint64_t state[8]; + uint64_t bitcount[2]; + uint8_t buffer[LDNS_SHA512_BLOCK_LENGTH]; +} ldns_sha512_CTX; + +typedef ldns_sha512_CTX ldns_sha384_CTX; + + +/*** SHA-256/384/512 Function Prototypes ******************************/ +void ldns_sha256_init(ldns_sha256_CTX *); +void ldns_sha256_update(ldns_sha256_CTX*, const uint8_t*, size_t); +void ldns_sha256_final(uint8_t[LDNS_SHA256_DIGEST_LENGTH], ldns_sha256_CTX*); + +void ldns_sha384_init(ldns_sha384_CTX*); +void ldns_sha384_update(ldns_sha384_CTX*, const uint8_t*, size_t); +void ldns_sha384_final(uint8_t[LDNS_SHA384_DIGEST_LENGTH], ldns_sha384_CTX*); + +void ldns_sha512_init(ldns_sha512_CTX*); +void ldns_sha512_update(ldns_sha512_CTX*, const uint8_t*, size_t); +void ldns_sha512_final(uint8_t[LDNS_SHA512_DIGEST_LENGTH], ldns_sha512_CTX*); + +/** + * Convenience function to digest a fixed block of data at once. + * + * \param[in] data the data to digest + * \param[in] data_len the length of data in bytes + * \param[out] digest the length of data in bytes + * This pointer MUST have LDNS_SHA256_DIGEST_LENGTH bytes + * available + * \return the SHA1 digest of the given data + */ +unsigned char *ldns_sha256(unsigned char *data, unsigned int data_len, unsigned char *digest); + +/** + * Convenience function to digest a fixed block of data at once. + * + * \param[in] data the data to digest + * \param[in] data_len the length of data in bytes + * \param[out] digest the length of data in bytes + * This pointer MUST have LDNS_SHA384_DIGEST_LENGTH bytes + * available + * \return the SHA1 digest of the given data + */ +unsigned char *ldns_sha384(unsigned char *data, unsigned int data_len, unsigned char *digest); + +/** + * Convenience function to digest a fixed block of data at once. + * + * \param[in] data the data to digest + * \param[in] data_len the length of data in bytes + * \param[out] digest the length of data in bytes + * This pointer MUST have LDNS_SHA512_DIGEST_LENGTH bytes + * available + * \return the SHA1 digest of the given data + */ +unsigned char *ldns_sha512(unsigned char *data, unsigned int data_len, unsigned char *digest); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __LDNS_SHA2_H__ */ diff --git a/ldns/str2host.h b/ldns/str2host.h new file mode 100644 index 00000000000..09416cd2252 --- /dev/null +++ b/ldns/str2host.h @@ -0,0 +1,251 @@ +/** + * str2host.h - conversion from str to the host fmt + * + * a Net::DNS like library for C + * + * (c) NLnet Labs, 2005-2006 + * + * See the file LICENSE for the license + */ + +#ifndef LDNS_2HOST_H +#define LDNS_2HOST_H + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \file + * + * Defines functions to convert dns data in presentation format or text files + * to internal structures. + */ + +/** + * convert a byte into wireformat + * \param[in] rd the rdf where to put the data + * \param[in] bytestr the string to be converted + * \return ldns_status + */ +ldns_status ldns_str2rdf_int8(ldns_rdf **rd, const char *bytestr); + +/** + * convert a string to a int16 in wireformat + * \param[in] rd the rdf where to put the data + * \param[in] shortstr the string to be converted + * \return ldns_status + */ +ldns_status ldns_str2rdf_int16(ldns_rdf **rd, const char *shortstr); + +/** + * convert a strings into a 4 byte int in wireformat + * \param[in] rd the rdf where to put the data + * \param[in] longstr the string to be converted + * \return ldns_status + */ +ldns_status ldns_str2rdf_int32(ldns_rdf **rd, const char *longstr); + +/** + * convert a time string to a time value in wireformat + * \param[in] rd the rdf where to put the data + * \param[in] time the string to be converted + * \return ldns_status + */ +ldns_status ldns_str2rdf_time(ldns_rdf **rd, const char *time); + +/* convert string with NSEC3 salt to wireformat) + * \param[in] rd the rdf where to put the data + * \param[in] str the string to be converted + * return ldns_status + */ +ldns_status ldns_str2rdf_nsec3_salt(ldns_rdf **rd, const char *nsec3_salt); + +/* convert a time period (think TTL's) to wireformat) + * \param[in] rd the rdf where to put the data + * \param[in] str the string to be converted + * return ldns_status + */ +ldns_status ldns_str2rdf_period(ldns_rdf **rd, const char *str); + +/** + * convert str with an A record into wireformat + * \param[in] rd the rdf where to put the data + * \param[in] str the string to be converted + * \return ldns_status + */ +ldns_status ldns_str2rdf_a(ldns_rdf **rd, const char *str); + +/** + * convert the str with an AAAA record into wireformat + * \param[in] rd the rdf where to put the data + * \param[in] str the string to be converted + * \return ldns_status + */ +ldns_status ldns_str2rdf_aaaa(ldns_rdf **rd, const char *str); + +/** + * convert a string into wireformat (think txt record) + * \param[in] rd the rdf where to put the data + * \param[in] str the string to be converted (NULL terminated) + * \return ldns_status + */ +ldns_status ldns_str2rdf_str(ldns_rdf **rd, const char *str); + +/** + * convert str with the apl record into wireformat + * \param[in] rd the rdf where to put the data + * \param[in] str the string to be converted + * \return ldns_status + */ +ldns_status ldns_str2rdf_apl(ldns_rdf **rd, const char *str); + +/** + * convert the string with the b64 data into wireformat + * \param[in] rd the rdf where to put the data + * \param[in] str the string to be converted + * \return ldns_status + */ +ldns_status ldns_str2rdf_b64(ldns_rdf **rd, const char *str); + +/** + * convert the string with the b32 ext hex data into wireformat + * \param[in] rd the rdf where to put the data + * \param[in] str the string to be converted + * \return ldns_status + */ +ldns_status ldns_str2rdf_b32_ext(ldns_rdf **rd, const char *str); + +/** + * convert a hex value into wireformat + * \param[in] rd the rdf where to put the data + * \param[in] str the string to be converted + * \return ldns_status + */ +ldns_status ldns_str2rdf_hex(ldns_rdf **rd, const char *str); + +/** + * convert string with nsec into wireformat + * \param[in] rd the rdf where to put the data + * \param[in] str the string to be converted + * \return ldns_status + */ +ldns_status ldns_str2rdf_nsec(ldns_rdf **rd, const char *str); + +/** + * convert a rrtype into wireformat + * \param[in] rd the rdf where to put the data + * \param[in] str the string to be converted + * \return ldns_status + */ +ldns_status ldns_str2rdf_type(ldns_rdf **rd, const char *str); + +/** + * convert string with a classname into wireformat + * \param[in] rd the rdf where to put the data + * \param[in] str the string to be converted + * \return ldns_status + */ +ldns_status ldns_str2rdf_class(ldns_rdf **rd, const char *str); + +/** + * convert an certificate algorithm value into wireformat + * \param[in] rd the rdf where to put the data + * \param[in] str the string to be converted + * \return ldns_status + */ +ldns_status ldns_str2rdf_cert_alg(ldns_rdf **rd, const char *str); + +/** + * convert and algorithm value into wireformat + * \param[in] rd the rdf where to put the data + * \param[in] str the string to be converted + * \return ldns_status + */ +ldns_status ldns_str2rdf_alg(ldns_rdf **rd, const char *str); + +/** + * convert a string with a unknown RR into wireformat + * \param[in] rd the rdf where to put the data + * \param[in] str the string to be converted + * \return ldns_status + */ +ldns_status ldns_str2rdf_unknown(ldns_rdf **rd, const char *str); + +/** + * convert string with a tsig? RR into wireformat + * \param[in] rd the rdf where to put the data + * \param[in] str the string to be converted + * \return ldns_status + */ +ldns_status ldns_str2rdf_tsig(ldns_rdf **rd, const char *str); + +/** + * convert string with a protocol service into wireformat + * \param[in] rd the rdf where to put the data + * \param[in] str the string to be converted + * \return ldns_status + */ +ldns_status ldns_str2rdf_service(ldns_rdf **rd, const char *str); + +/** + * convert a string with a LOC RR into wireformat + * \param[in] rd the rdf where to put the data + * \param[in] str the string to be converted + * \return ldns_status + */ +ldns_status ldns_str2rdf_loc(ldns_rdf **rd, const char *str); + +/** + * convert string with a WKS RR into wireformat + * \param[in] rd the rdf where to put the data + * \param[in] str the string to be converted + * \return ldns_status + */ +ldns_status ldns_str2rdf_wks(ldns_rdf **rd, const char *str); + +/** + * convert a str with a NSAP RR into wireformat + * \param[in] rd the rdf where to put the data + * \param[in] str the string to be converted + * \return ldns_status + */ +ldns_status ldns_str2rdf_nsap(ldns_rdf **rd, const char *str); + +/** + * convert a str with a ATMA RR into wireformat + * \param[in] rd the rdf where to put the data + * \param[in] str the string to be converted + * \return ldns_status + */ +ldns_status ldns_str2rdf_atma(ldns_rdf **rd, const char *str); + +/** + * convert a str with a IPSECKEY RR into wireformat + * \param[in] rd the rdf where to put the data + * \param[in] str the string to be converted + * \return ldns_status + */ +ldns_status ldns_str2rdf_ipseckey(ldns_rdf **rd, const char *str); + +/** + * convert a dname string into wireformat + * \param[in] rd the rdf where to put the data + * \param[in] str the string to be converted + * \return ldns_status + */ +ldns_status ldns_str2rdf_dname(ldns_rdf **rd, const char *str); + +#ifdef __cplusplus +} +#endif + +#endif /* LDNS_2HOST_H */ diff --git a/ldns/tsig.h b/ldns/tsig.h new file mode 100644 index 00000000000..676045fbb6b --- /dev/null +++ b/ldns/tsig.h @@ -0,0 +1,101 @@ +/* + * tsig.h -- defines for TSIG [RFC2845] + * + * Copyright (c) 2005-2008, NLnet Labs. All rights reserved. + * + * See LICENSE for the license. + */ + +#ifndef LDNS_TSIG_H +#define LDNS_TSIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \file + * + * Defines functions for TSIG usage + */ + + +/** + * Contains credentials for TSIG +*/ +typedef struct ldns_tsig_credentials_struct +{ + char *algorithm; + char *keyname; + char *keydata; + /* XXX More eventually. */ +} ldns_tsig_credentials; + +char *ldns_tsig_algorithm(ldns_tsig_credentials *); +char *ldns_tsig_keyname(ldns_tsig_credentials *); +char *ldns_tsig_keydata(ldns_tsig_credentials *); +char *ldns_tsig_keyname_clone(ldns_tsig_credentials *); +char *ldns_tsig_keydata_clone(ldns_tsig_credentials *); + +/** + * verifies the tsig rr for the given packet and key. + * The wire must be given too because tsig does not sign normalized packets. + * \param[in] pkt the packet to verify + * \param[in] wire needed to verify the mac + * \param[in] wire_size size of wire + * \param[in] key_name the name of the shared key + * \param[in] key_data the key in base 64 format + * \param[in] mac original mac + * \return true if tsig is correct, false if not, or if tsig is not set + */ +bool ldns_pkt_tsig_verify(ldns_pkt *pkt, uint8_t *wire, size_t wire_size, const char *key_name, const char *key_data, ldns_rdf *mac); + +/** + * verifies the tsig rr for the given packet and key. + * The wire must be given too because tsig does not sign normalized packets. + * \param[in] pkt the packet to verify + * \param[in] wire needed to verify the mac + * \param[in] wire_size size of wire + * \param[in] key_name the name of the shared key + * \param[in] key_data the key in base 64 format + * \param[in] mac original mac + * \param[in] tsig_timers_only must be zero for the first packet and positive for subsequent packets. If zero, all digest + components are used to verify the _mac. If non-zero, only the TSIG timers are used to verify the mac. + * \return true if tsig is correct, false if not, or if tsig is not set + */ +bool ldns_pkt_tsig_verify_next(ldns_pkt *pkt, uint8_t *wire, size_t wire_size, const char *key_name, const char *key_data, ldns_rdf *mac, + int tsig_timers_only); + +/** + * creates a tsig rr for the given packet and key. + * \param[in] pkt the packet to sign + * \param[in] key_name the name of the shared key + * \param[in] key_data the key in base 64 format + * \param[in] fudge seconds of error permitted in time signed + * \param[in] algorithm_name the name of the algorithm used + * \param[in] query_mac is added to the digest if not NULL (so NULL is for signing queries, not NULL is for signing answers) + * \return status (OK if success) + */ +ldns_status ldns_pkt_tsig_sign(ldns_pkt *pkt, const char *key_name, const char *key_data, uint16_t fudge, + const char *algorithm_name, ldns_rdf *query_mac); + +/** + * creates a tsig rr for the given packet and key. + * \param[in] pkt the packet to sign + * \param[in] key_name the name of the shared key + * \param[in] key_data the key in base 64 format + * \param[in] fudge seconds of error permitted in time signed + * \param[in] algorithm_name the name of the algorithm used + * \param[in] query_mac is added to the digest if not NULL (so NULL is for signing queries, not NULL is for signing answers) + * \param[in] tsig_timers_only must be zero for the first packet and positive for subsequent packets. If zero, all digest + components are used to create the query_mac. If non-zero, only the TSIG timers are used to create the query_mac. + * \return status (OK if success) + */ +ldns_status ldns_pkt_tsig_sign_next(ldns_pkt *pkt, const char *key_name, const char *key_data, uint16_t fudge, + const char *algorithm_name, ldns_rdf *query_mac, int tsig_timers_only); + +#ifdef __cplusplus +} +#endif + +#endif /* LDNS_TSIG_H */ diff --git a/ldns/update.h b/ldns/update.h new file mode 100644 index 00000000000..d3459d325e3 --- /dev/null +++ b/ldns/update.h @@ -0,0 +1,115 @@ +/* + * update.h + * + * Functions for RFC 2136 Dynamic Update + * + * Copyright (c) 2005-2008, NLnet Labs. All rights reserved. + * + * See LICENSE for the license. + */ + +/** + * \file + * + * Defines functions to perform UPDATE queries + */ + + +#ifndef LDNS_UPDATE_H +#define LDNS_UPDATE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * create an update packet from zone name, class and the rr lists + * \param[in] zone_rdf name of the zone + * \param[in] clas zone class + * \param[in] pr_rrlist list of Prerequisite Section RRs + * \param[in] up_rrlist list of Updates Section RRs + * \param[in] ad_rrlist list of Additional Data Section RRs (currently unused) + * \return the new packet + */ +ldns_pkt *ldns_update_pkt_new(ldns_rdf *zone_rdf, ldns_rr_class clas, ldns_rr_list *pr_rrlist, ldns_rr_list *up_rrlist, ldns_rr_list *ad_rrlist); + +/** + * add tsig credentials to + * a packet from a resolver + * \param[in] p packet to copy to + * \param[in] r resolver to copy from + * + * \return status wether successfull or not + */ +ldns_status ldns_update_pkt_tsig_add(ldns_pkt *p, ldns_resolver *r); + +/* access functions */ + +/** + * Get the zo count + * \param[in] p the packet + * \return the zo count + */ +uint16_t ldns_update_zocount(const ldns_pkt *p); +/** + * Get the zo count + * \param[in] p the packet + * \return the pr count + */ +uint16_t ldns_update_prcount(const ldns_pkt *p); +/** + * Get the zo count + * \param[in] p the packet + * \return the up count + */ +uint16_t ldns_update_upcount(const ldns_pkt *p); +/** + * Get the zo count + * \param[in] p the packet + * \return the ad count + */ +uint16_t ldns_update_ad(const ldns_pkt *p); +/** + * Set the zo count + * \param[in] p the packet + * \param[in] c the zo count to set + */ +void ldns_update_set_zo(ldns_pkt *p, uint16_t c); +/** + * Set the pr count + * \param[in] p the packet + * \param[in] c the pr count to set + */ +void ldns_update_set_prcount(ldns_pkt *p, uint16_t c); +/** + * Set the up count + * \param[in] p the packet + * \param[in] c the up count to set + */ +void ldns_update_set_upcount(ldns_pkt *p, uint16_t c); +/** + * Set the ad count + * \param[in] p the packet + * \param[in] c the ad count to set + */ +void ldns_update_set_adcount(ldns_pkt *p, uint16_t c); + +/* soa functions that need to be configured */ +/* + * Not sure if we want to keep these like this, therefore + * not documented + */ +ldns_status ldns_update_soa_mname(ldns_rdf *zone, ldns_resolver *r, ldns_rr_class c, ldns_rdf **mname); +/* + * Not sure if we want to keep these like this, therefore + * not documented + */ +ldns_status ldns_update_soa_zone_mname(const char *fqdn, ldns_resolver *r, ldns_rr_class c, ldns_rdf **zone_rdf, ldns_rdf **mname_rdf); + +#ifdef __cplusplus +} +#endif + +#endif /* LDNS_UPDATE_H */ diff --git a/ldns/util.h.in b/ldns/util.h.in new file mode 100644 index 00000000000..f9fb10420cc --- /dev/null +++ b/ldns/util.h.in @@ -0,0 +1,367 @@ +/* + * util.h + * + * helper function header file + * + * a Net::DNS like library for C + * + * (c) NLnet Labs, 2004 + * + * See the file LICENSE for the license + */ + +#ifndef _UTIL_H +#define _UTIL_H + +@include_inttypes_h@ +@include_systypes_h@ +@include_unistd_h@ +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define dprintf(X,Y) fprintf(stderr, (X), (Y)) +/* #define dprintf(X, Y) */ + +#define LDNS_VERSION "@PACKAGE_VERSION@" +#define LDNS_REVISION ((@LDNS_VERSION_MAJOR@<<16)|(@LDNS_VERSION_MINOR@<<8)|(@LDNS_VERSION_MICRO@)) + +/** + * splint static inline workaround + */ +#ifdef S_SPLINT_S +# define INLINE +#else +# ifdef SWIG +# define INLINE static +# else +# define INLINE static inline +# endif +#endif + +/** + * Memory management macros + */ +#define LDNS_MALLOC(type) LDNS_XMALLOC(type, 1) + +#define LDNS_XMALLOC(type, count) ((type *) malloc((count) * sizeof(type))) + +#define LDNS_CALLOC(type, count) ((type *) calloc((count), sizeof(type))) + +#define LDNS_REALLOC(ptr, type) LDNS_XREALLOC((ptr), type, 1) + +#define LDNS_XREALLOC(ptr, type, count) \ + ((type *) realloc((ptr), (count) * sizeof(type))) + +#define LDNS_FREE(ptr) \ + do { free((ptr)); (ptr) = NULL; } while (0) + +#define LDNS_DEP printf("DEPRECATED FUNCTION!\n"); + +/* + * Copy data allowing for unaligned accesses in network byte order + * (big endian). + */ +INLINE uint16_t +ldns_read_uint16(const void *src) +{ +#ifdef ALLOW_UNALIGNED_ACCESSES + return ntohs(*(uint16_t *) src); +#else + uint8_t *p = (uint8_t *) src; + return ((uint16_t) p[0] << 8) | (uint16_t) p[1]; +#endif +} + +INLINE uint32_t +ldns_read_uint32(const void *src) +{ +#ifdef ALLOW_UNALIGNED_ACCESSES + return ntohl(*(uint32_t *) src); +#else + uint8_t *p = (uint8_t *) src; + return ( ((uint32_t) p[0] << 24) + | ((uint32_t) p[1] << 16) + | ((uint32_t) p[2] << 8) + | (uint32_t) p[3]); +#endif +} + +/* + * Copy data allowing for unaligned accesses in network byte order + * (big endian). + */ +INLINE void +ldns_write_uint16(void *dst, uint16_t data) +{ +#ifdef ALLOW_UNALIGNED_ACCESSES + * (uint16_t *) dst = htons(data); +#else + uint8_t *p = (uint8_t *) dst; + p[0] = (uint8_t) ((data >> 8) & 0xff); + p[1] = (uint8_t) (data & 0xff); +#endif +} + +INLINE void +ldns_write_uint32(void *dst, uint32_t data) +{ +#ifdef ALLOW_UNALIGNED_ACCESSES + * (uint32_t *) dst = htonl(data); +#else + uint8_t *p = (uint8_t *) dst; + p[0] = (uint8_t) ((data >> 24) & 0xff); + p[1] = (uint8_t) ((data >> 16) & 0xff); + p[2] = (uint8_t) ((data >> 8) & 0xff); + p[3] = (uint8_t) (data & 0xff); +#endif +} + +/* warning. */ +INLINE void +ldns_write_uint64_as_uint48(void *dst, uint64_t data) +{ + uint8_t *p = (uint8_t *) dst; + p[0] = (uint8_t) ((data >> 40) & 0xff); + p[1] = (uint8_t) ((data >> 32) & 0xff); + p[2] = (uint8_t) ((data >> 24) & 0xff); + p[3] = (uint8_t) ((data >> 16) & 0xff); + p[4] = (uint8_t) ((data >> 8) & 0xff); + p[5] = (uint8_t) (data & 0xff); +} + + +/** + * Structure to do a Schwartzian-like transformation, for instance when + * sorting. If you need a transformation on the objects that are sorted, + * you can sue this to store the transformed values, so you do not + * need to do the transformation again for each comparison + */ +struct ldns_schwartzian_compare_struct { + void *original_object; + void *transformed_object; +}; + +/** A general purpose lookup table + * + * Lookup tables are arrays of (id, name) pairs, + * So you can for instance lookup the RCODE 3, which is "NXDOMAIN", + * and vice versa. The lookup tables themselves are defined wherever needed, + * for instance in \ref host2str.c + */ +struct ldns_struct_lookup_table { + int id; + const char *name; +}; +typedef struct ldns_struct_lookup_table ldns_lookup_table; + +/** + * Looks up the table entry by name, returns NULL if not found. + * \param[in] table the lookup table to search in + * \param[in] name what to search for + * \return the item found + */ +ldns_lookup_table *ldns_lookup_by_name(ldns_lookup_table table[], + const char *name); + +/** + * Looks up the table entry by id, returns NULL if not found. + * \param[in] table the lookup table to search in + * \param[in] id what to search for + * \return the item found + */ +ldns_lookup_table *ldns_lookup_by_id(ldns_lookup_table table[], int id); + +/** + * Returns the value of the specified bit + * The bits are counted from left to right, so bit #0 is the + * left most bit. + * \param[in] bits array holding the bits + * \param[in] index to the wanted bit + * \return + */ +int ldns_get_bit(uint8_t bits[], size_t index); + + +/** + * Returns the value of the specified bit + * The bits are counted from right to left, so bit #0 is the + * right most bit. + * \param[in] bits array holding the bits + * \param[in] index to the wanted bit + * \return 1 or 0 depending no the bit state + */ +int ldns_get_bit_r(uint8_t bits[], size_t index); + +/** + * sets the specified bit in the specified byte to + * 1 if value is true, 0 if false + * The bits are counted from right to left, so bit #0 is the + * right most bit. + * \param[in] byte the bit to set the bit in + * \param[in] bit_nr the bit to set (0 <= n <= 7) + * \param[in] value whether to set the bit to 1 or 0 + * \return 1 or 0 depending no the bit state + */ +void ldns_set_bit(uint8_t *byte, int bit_nr, bool value); + +/** + * Returns the value of a to the power of b + * (or 1 of b < 1) + */ +/*@unused@*/ +INLINE long +ldns_power(long a, long b) { + long result = 1; + while (b > 0) { + if (b & 1) { + result *= a; + if (b == 1) { + return result; + } + } + a *= a; + b /= 2; + } + return result; +} + +/** + * Returns the int value of the given (hex) digit + * \param[in] ch the hex char to convert + * \return the converted decimal value + */ +int ldns_hexdigit_to_int(char ch); + +/** + * Returns the char (hex) representation of the given int + * \param[in] ch the int to convert + * \return the converted hex char + */ +char ldns_int_to_hexdigit(int ch); + +/** + * Converts a hex string to binary data + * + * \param[out] data The binary result is placed here. + * At least strlen(str)/2 bytes should be allocated + * \param[in] str The hex string to convert. + * This string should not contain spaces + * \return The number of bytes of converted data, or -1 if one of the arguments * is NULL, or -2 if the string length is not an even number + */ +int +ldns_hexstring_to_data(uint8_t *data, const char *str); + +/** + * Show the internal library version + * \return a string with the version in it + */ +const char * ldns_version(void); + +/** + * Convert TM to seconds since epoch (midnight, January 1st, 1970). + * Like timegm(3), which is not always available. + * \param[in] tm a struct tm* with the date + * \return the seconds since epoch + */ +time_t mktime_from_utc(const struct tm *tm); + +/** + * The function interprets time as the number of seconds since epoch + * with respect to now using serial arithmitics (rfc1982). + * That number of seconds is then converted to broken-out time information. + * This is especially usefull when converting the inception and expiration + * fields of RRSIG records. + * + * \param[in] time number of seconds since epoch (midnight, January 1st, 1970) + * to be intepreted as a serial arithmitics number relative to now. + * \param[in] now number of seconds since epoch (midnight, January 1st, 1970) + * to which the time value is compared to determine the final value. + * \param[out] result the struct with the broken-out time information + * \return result on success or NULL on error + */ +struct tm * ldns_serial_arithmitics_gmtime_r(int32_t time, time_t now, struct tm *result); + +/** + * Seed the random function. + * If the file descriptor is specified, the random generator is seeded with + * data from that file. If not, /dev/urandom is used. + * + * applications should call this if they need entropy data within ldns + * If openSSL is available, it is automatically seeded from /dev/urandom + * or /dev/random. + * + * If you need more entropy, or have no openssl available, this function + * MUST be called at the start of the program + * + * If openssl *is* available, this function just adds more entropy + * + * \param[in] fd a file providing entropy data for the seed + * \param[in] size the number of bytes to use as entropy data. If this is 0, + * only the minimal amount is taken (usually 4 bytes) + * \return 0 if seeding succeeds, 1 if it fails + */ +int ldns_init_random(FILE *fd, unsigned int size); + +/** + * Get random number. + * \return random number. + * + */ +uint16_t ldns_get_random(void); + +/** + * Encode data as BubbleBabble + * + * \param[in] data a pointer to data to be encoded + * \param[in] len size the number of bytes of data + * \return a string of BubbleBabble + */ +char *ldns_bubblebabble(uint8_t *data, size_t len); + +#ifndef B32_NTOP +int ldns_b32_ntop(uint8_t const *src, size_t srclength, + char *target, size_t targsize); +int b32_ntop(uint8_t const *src, size_t srclength, + char *target, size_t targsize); +int ldns_b32_ntop_extended_hex(uint8_t const *src, size_t srclength, + char *target, size_t targsize); +int b32_ntop_extended_hex(uint8_t const *src, size_t srclength, + char *target, size_t targsize); +/** + * calculates the size needed to store the result of b32_ntop + */ +/*@unused@*/ +INLINE size_t ldns_b32_ntop_calculate_size(size_t srcsize) +{ + size_t result = ((((srcsize / 5) * 8) - 2) + 2); + return result; +} +#endif /* !B32_NTOP */ +#ifndef B32_PTON +int ldns_b32_pton(char const *src, size_t hashed_owner_str_len, uint8_t *target, size_t targsize); +int b32_pton(char const *src, size_t hashed_owner_str_len, uint8_t *target, size_t targsize); +int ldns_b32_pton_extended_hex(char const *src, size_t hashed_owner_str_len, uint8_t *target, size_t targsize); +int b32_pton_extended_hex(char const *src, size_t hashed_owner_str_len, uint8_t *target, size_t targsize); +/** + * calculates the size needed to store the result of b32_pton + */ +/*@unused@*/ +INLINE size_t ldns_b32_pton_calculate_size(size_t srcsize) +{ + size_t result = ((((srcsize) / 8) * 5)); + return result; +} +#endif /* !B32_PTON */ + +INLINE time_t ldns_time(time_t *t) { return time(t); } + +#ifdef __cplusplus +} +#endif + +#endif /* !_UTIL_H */ diff --git a/ldns/wire2host.h b/ldns/wire2host.h new file mode 100644 index 00000000000..53155b30668 --- /dev/null +++ b/ldns/wire2host.h @@ -0,0 +1,197 @@ +/* + * wire2host.h - from wire conversion routines + * + * a Net::DNS like library for C + * + * (c) NLnet Labs, 2005-2006 + * + * See the file LICENSE for the license + */ + +/** + * \file + * + * Contains functions that translate dns data from the wire format (as sent + * by servers and clients) to the internal structures. + */ + +#ifndef LDNS_WIRE2HOST_H +#define LDNS_WIRE2HOST_H + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* The length of the header */ +#define LDNS_HEADER_SIZE 12 + +/* First octet of flags */ +#define LDNS_RD_MASK 0x01U +#define LDNS_RD_SHIFT 0 +#define LDNS_RD_WIRE(wirebuf) (*(wirebuf+2) & LDNS_RD_MASK) +#define LDNS_RD_SET(wirebuf) (*(wirebuf+2) |= LDNS_RD_MASK) +#define LDNS_RD_CLR(wirebuf) (*(wirebuf+2) &= ~LDNS_RD_MASK) + +#define LDNS_TC_MASK 0x02U +#define LDNS_TC_SHIFT 1 +#define LDNS_TC_WIRE(wirebuf) (*(wirebuf+2) & LDNS_TC_MASK) +#define LDNS_TC_SET(wirebuf) (*(wirebuf+2) |= LDNS_TC_MASK) +#define LDNS_TC_CLR(wirebuf) (*(wirebuf+2) &= ~LDNS_TC_MASK) + +#define LDNS_AA_MASK 0x04U +#define LDNS_AA_SHIFT 2 +#define LDNS_AA_WIRE(wirebuf) (*(wirebuf+2) & LDNS_AA_MASK) +#define LDNS_AA_SET(wirebuf) (*(wirebuf+2) |= LDNS_AA_MASK) +#define LDNS_AA_CLR(wirebuf) (*(wirebuf+2) &= ~LDNS_AA_MASK) + +#define LDNS_OPCODE_MASK 0x78U +#define LDNS_OPCODE_SHIFT 3 +#define LDNS_OPCODE_WIRE(wirebuf) ((*(wirebuf+2) & LDNS_OPCODE_MASK) >> LDNS_OPCODE_SHIFT) +#define LDNS_OPCODE_SET(wirebuf, opcode) \ + (*(wirebuf+2) = ((*(wirebuf+2)) & ~LDNS_OPCODE_MASK) | ((opcode) << LDNS_OPCODE_SHIFT)) + +#define LDNS_QR_MASK 0x80U +#define LDNS_QR_SHIFT 7 +#define LDNS_QR_WIRE(wirebuf) (*(wirebuf+2) & LDNS_QR_MASK) +#define LDNS_QR_SET(wirebuf) (*(wirebuf+2) |= LDNS_QR_MASK) +#define LDNS_QR_CLR(wirebuf) (*(wirebuf+2) &= ~LDNS_QR_MASK) + +/* Second octet of flags */ +#define LDNS_RCODE_MASK 0x0fU +#define LDNS_RCODE_SHIFT 0 +#define LDNS_RCODE_WIRE(wirebuf) (*(wirebuf+3) & LDNS_RCODE_MASK) +#define LDNS_RCODE_SET(wirebuf, rcode) \ + (*(wirebuf+3) = ((*(wirebuf+3)) & ~LDNS_RCODE_MASK) | (rcode)) + +#define LDNS_CD_MASK 0x10U +#define LDNS_CD_SHIFT 4 +#define LDNS_CD_WIRE(wirebuf) (*(wirebuf+3) & LDNS_CD_MASK) +#define LDNS_CD_SET(wirebuf) (*(wirebuf+3) |= LDNS_CD_MASK) +#define LDNS_CD_CLR(wirebuf) (*(wirebuf+3) &= ~LDNS_CD_MASK) + +#define LDNS_AD_MASK 0x20U +#define LDNS_AD_SHIFT 5 +#define LDNS_AD_WIRE(wirebuf) (*(wirebuf+3) & LDNS_AD_MASK) +#define LDNS_AD_SET(wirebuf) (*(wirebuf+3) |= LDNS_AD_MASK) +#define LDNS_AD_CLR(wirebuf) (*(wirebuf+3) &= ~LDNS_AD_MASK) + +#define LDNS_Z_MASK 0x40U +#define LDNS_Z_SHIFT 6 +#define LDNS_Z_WIRE(wirebuf) (*(wirebuf+3) & LDNS_Z_MASK) +#define LDNS_Z_SET(wirebuf) (*(wirebuf+3) |= LDNS_Z_MASK) +#define LDNS_Z_CLR(wirebuf) (*(wirebuf+3) &= ~LDNS_Z_MASK) + +#define LDNS_RA_MASK 0x80U +#define LDNS_RA_SHIFT 7 +#define LDNS_RA_WIRE(wirebuf) (*(wirebuf+3) & LDNS_RA_MASK) +#define LDNS_RA_SET(wirebuf) (*(wirebuf+3) |= LDNS_RA_MASK) +#define LDNS_RA_CLR(wirebuf) (*(wirebuf+3) &= ~LDNS_RA_MASK) + +/* Query ID */ +#define LDNS_ID_WIRE(wirebuf) (ldns_read_uint16(wirebuf)) +#define LDNS_ID_SET(wirebuf, id) (ldns_write_uint16(wirebuf, id)) + +/* Counter of the question section */ +#define LDNS_QDCOUNT_OFF 4 +/* +#define QDCOUNT(wirebuf) (ntohs(*(uint16_t *)(wirebuf+QDCOUNT_OFF))) +*/ +#define LDNS_QDCOUNT(wirebuf) (ldns_read_uint16(wirebuf+LDNS_QDCOUNT_OFF)) + +/* Counter of the answer section */ +#define LDNS_ANCOUNT_OFF 6 +#define LDNS_ANCOUNT(wirebuf) (ldns_read_uint16(wirebuf+LDNS_ANCOUNT_OFF)) + +/* Counter of the authority section */ +#define LDNS_NSCOUNT_OFF 8 +#define LDNS_NSCOUNT(wirebuf) (ldns_read_uint16(wirebuf+LDNS_NSCOUNT_OFF)) + +/* Counter of the additional section */ +#define LDNS_ARCOUNT_OFF 10 +#define LDNS_ARCOUNT(wirebuf) (ldns_read_uint16(wirebuf+LDNS_ARCOUNT_OFF)) + +/** + * converts the data on the uint8_t bytearray (in wire format) to a DNS packet. + * This function will initialize and allocate memory space for the packet + * structure. + * + * \param[in] packet pointer to the structure to hold the packet + * \param[in] data pointer to the buffer with the data + * \param[in] len the length of the data buffer (in bytes) + * \return LDNS_STATUS_OK if everything succeeds, error otherwise + */ +ldns_status ldns_wire2pkt(ldns_pkt **packet, const uint8_t *data, size_t len); + +/** + * converts the data on the uint8_t bytearray (in wire format) to a DNS packet. + * This function will initialize and allocate memory space for the packet + * structure. + * + * \param[in] packet pointer to the structure to hold the packet + * \param[in] buffer the buffer with the data + * \return LDNS_STATUS_OK if everything succeeds, error otherwise + */ +ldns_status ldns_buffer2pkt_wire(ldns_pkt **packet, ldns_buffer *buffer); + +/** + * converts the data on the uint8_t bytearray (in wire format) to a DNS + * dname rdata field. This function will initialize and allocate memory + * space for the dname structure. The length of the wiredata of this rdf + * is added to the *pos value. + * + * \param[in] dname pointer to the structure to hold the rdata value + * \param[in] wire pointer to the buffer with the data + * \param[in] max the length of the data buffer (in bytes) + * \param[in] pos the position of the rdf in the buffer (ie. the number of bytes + * from the start of the buffer) + * \return LDNS_STATUS_OK if everything succeeds, error otherwise + */ +ldns_status ldns_wire2dname(ldns_rdf **dname, const uint8_t *wire, size_t max, size_t *pos); + +/** + * converts the data on the uint8_t bytearray (in wire format) to DNS + * rdata fields, and adds them to the list of rdfs of the given rr. + * This function will initialize and allocate memory space for the dname + * structures. + * The length of the wiredata of these rdfs is added to the *pos value. + * + * All rdfs belonging to the RR are read; the rr should have no rdfs + * yet. An error is returned if the format cannot be parsed. + * + * \param[in] rr pointer to the ldns_rr structure to hold the rdata value + * \param[in] wire pointer to the buffer with the data + * \param[in] max the length of the data buffer (in bytes) + * \param[in] pos the position of the rdf in the buffer (ie. the number of bytes + * from the start of the buffer) + * \return LDNS_STATUS_OK if everything succeeds, error otherwise + */ +ldns_status ldns_wire2rdf(ldns_rr *rr, const uint8_t *wire, size_t max, size_t *pos); + +/** + * converts the data on the uint8_t bytearray (in wire format) to a DNS + * resource record. + * This function will initialize and allocate memory space for the rr + * structure. + * The length of the wiredata of this rr is added to the *pos value. + * + * \param[in] rr pointer to the structure to hold the rdata value + * \param[in] wire pointer to the buffer with the data + * \param[in] max the length of the data buffer (in bytes) + * \param[in] pos the position of the rr in the buffer (ie. the number of bytes + * from the start of the buffer) + * \param[in] section the section in the packet the rr is meant for + * \return LDNS_STATUS_OK if everything succeeds, error otherwise + */ +ldns_status ldns_wire2rr(ldns_rr **rr, const uint8_t *wire, size_t max, size_t *pos, ldns_pkt_section section); + +#ifdef __cplusplus +} +#endif + +#endif /* LDNS_WIRE2HOST_H */ diff --git a/ldns/zone.h b/ldns/zone.h new file mode 100644 index 00000000000..0d129a0c38a --- /dev/null +++ b/ldns/zone.h @@ -0,0 +1,176 @@ +/** + * zone.h + * + * zone definitions + * - what is it + * - get_glue function + * - search etc + * + * a Net::DNS like library for C + * + * (c) NLnet Labs, 2005-2006 + * + * See the file LICENSE for the license + */ + +/** + * \file + * + * Defines the ldns_zone structure and functions to manipulate it. + */ + + +#ifndef LDNS_ZONE_H +#define LDNS_ZONE_H + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * DNS Zone + * + * A list of RR's with some + * extra information which comes from the SOA RR + * Note: nothing has been done to make this efficient (yet). + */ +struct ldns_struct_zone +{ + /** the soa defines a zone */ + ldns_rr *_soa; + /* basicly a zone is a list of rr's */ + ldns_rr_list *_rrs; + /* we could change this to be a b-tree etc etc todo */ +}; +typedef struct ldns_struct_zone ldns_zone; + +/** + * create a new ldns_zone structure + * \return a pointer to a ldns_zone structure + */ +ldns_zone * ldns_zone_new(void); + +/** + * Return the soa record of a zone + * \param[in] z the zone to read from + * \return the soa record in the zone + */ +ldns_rr * ldns_zone_soa(const ldns_zone *z); + +/** + * Returns the number of resource records in the zone, NOT counting the SOA record + * \param[in] z the zone to read from + * \return the number of rr's in the zone + */ +size_t ldns_zone_rr_count(const ldns_zone *z); + +/** + * Set the zone's soa record + * \param[in] z the zone to put the new soa in + * \param[in] soa the soa to set + */ +void ldns_zone_set_soa(ldns_zone *z, ldns_rr *soa); + +/** + * Get a list of a zone's content. Note that the SOA + * isn't included in this list. You need to get the + * with ldns_zone_soa. + * \param[in] z the zone to read from + * \return the rrs from this zone + */ +ldns_rr_list * ldns_zone_rrs(const ldns_zone *z); + +/** + * Set the zone's contents + * \param[in] z the zone to put the new soa in + * \param[in] rrlist the rrlist to use + */ +void ldns_zone_set_rrs(ldns_zone *z, ldns_rr_list *rrlist); + +/** + * push an rrlist to a zone structure. This function use pointer + * copying, so the rr_list structure inside z is modified! + * \param[in] z the zone to add to + * \param[in] list the list to add + * \return a true on succes otherwise falsed + */ +bool ldns_zone_push_rr_list(ldns_zone *z, ldns_rr_list *list); + +/** + * push an single rr to a zone structure. This function use pointer + * copying, so the rr_list structure inside z is modified! + * \param[in] z the zone to add to + * \param[in] rr the rr to add + * \return a true on succes otherwise falsed + */ +bool ldns_zone_push_rr(ldns_zone *z, ldns_rr *rr); + +/** + * Retrieve all resource records from the zone that are glue + * records. The resulting list does are pointer references + * to the zone's data. + * + * Due to the current zone implementation (as a list of rr's), this + * function is extremely slow. Another (probably better) way to do this + * is to use an ldns_dnssec_zone structure and the + * ldns_dnssec_mark_and_get_glue() function. + * + * \param[in] z the zone to look for glue + * \return the rr_list with the glue + */ +ldns_rr_list *ldns_zone_glue_rr_list(const ldns_zone *z); + +/** + * Create a new zone from a file + * \param[out] z the new zone + * \param[in] *fp the filepointer to use + * \param[in] *origin the zones' origin + * \param[in] ttl default ttl to use + * \param[in] c default class to use (IN) + * + * \return ldns_status mesg with an error or LDNS_STATUS_OK + */ +ldns_status ldns_zone_new_frm_fp(ldns_zone **z, FILE *fp, ldns_rdf *origin, uint32_t ttl, ldns_rr_class c); + +/** + * Create a new zone from a file, keep track of the line numbering + * \param[out] z the new zone + * \param[in] *fp the filepointer to use + * \param[in] *origin the zones' origin + * \param[in] ttl default ttl to use + * \param[in] c default class to use (IN) + * \param[out] line_nr used for error msg, to get to the line number + * + * \return ldns_status mesg with an error or LDNS_STATUS_OK + */ +ldns_status ldns_zone_new_frm_fp_l(ldns_zone **z, FILE *fp, ldns_rdf *origin, uint32_t ttl, ldns_rr_class c, int *line_nr); + +/** + * Frees the allocated memory for the zone, and the rr_list structure in it + * \param[in] zone the zone to free + */ +void ldns_zone_free(ldns_zone *zone); + +/** + * Frees the allocated memory for the zone, the soa rr in it, + * and the rr_list structure in it, including the rr's in that. etc. + * \param[in] zone the zone to free + */ +void ldns_zone_deep_free(ldns_zone *zone); + +/** + * Sort the rrs in a zone, with the current impl. this is slow + * \param[in] zone the zone to sort + */ +void ldns_zone_sort(ldns_zone *zone); + +#ifdef __cplusplus +} +#endif + +#endif /* LDNS_ZONE_H */ diff --git a/ldns_symbols.def b/ldns_symbols.def new file mode 100644 index 00000000000..1ed0f9e2137 --- /dev/null +++ b/ldns_symbols.def @@ -0,0 +1,783 @@ +ldns_algorithm2buffer_str +ldns_algorithms +ldns_axfr_complete +ldns_axfr_last_pkt +ldns_axfr_next +ldns_axfr_start +ldns_b32_ntop +ldns_b32_ntop_ar +ldns_b32_ntop_extended_hex +ldns_b32_pton +ldns_b32_pton_ar +ldns_b32_pton_extended_hex +ldns_b64_ntop +ldns_b64_pton +ldns_bgetc +ldns_bget_keyword_data +ldns_bget_token +ldns_bskipc +ldns_bskipcs +ldns_bubblebabble +ldns_buffer2pkt_wire +ldns_buffer2str +ldns_buffer_copy +ldns_buffer_export +ldns_buffer_free +ldns_buffer_new +ldns_buffer_new_frm_data +ldns_buffer_printf +ldns_buffer_reserve +ldns_buffer_set_capacity +ldns_calc_keytag +ldns_calc_keytag_raw +ldns_cert_algorithm2buffer_str +ldns_cert_algorithms +ldns_convert_dsa_rrsig_asn12rdf +ldns_convert_dsa_rrsig_rdf2asn1 +ldns_convert_ecdsa_rrsig_asn12rdf +ldns_convert_ecdsa_rrsig_rdf2asn1 +ldns_create_empty_rrsig +ldns_create_nsec +ldns_create_nsec3 +ldns_digest_evp +ldns_directive_types +ldns_dname2buffer_wire +ldns_dname2canonical +ldns_dname_cat +ldns_dname_cat_clone +ldns_dname_clone_from +ldns_dname_compare +ldns_dname_compare_v +ldns_dname_interval +ldns_dname_is_subdomain +ldns_dname_is_wildcard +ldns_dname_label +ldns_dname_label_count +ldns_dname_left_chop +ldns_dname_match_wildcard +ldns_dname_new +ldns_dname_new_frm_data +ldns_dname_new_frm_str +ldns_dname_reverse +ldns_dname_str_absolute +ldns_dnssec_build_data_chain +ldns_dnssec_build_data_chain_nokeyname +ldns_dnssec_chain_nsec3_list +ldns_dnssec_create_nsec +ldns_dnssec_create_nsec3 +ldns_dnssec_create_nsec_bitmap +ldns_dnssec_data_chain_deep_free +ldns_dnssec_data_chain_free +ldns_dnssec_data_chain_new +ldns_dnssec_data_chain_print +ldns_dnssec_data_chain_print_fmt +ldns_dnssec_default_add_to_signatures +ldns_dnssec_default_delete_signatures +ldns_dnssec_default_leave_signatures +ldns_dnssec_default_replace_signatures +ldns_dnssec_derive_trust_tree +ldns_dnssec_derive_trust_tree_dnskey_rrset +ldns_dnssec_derive_trust_tree_dnskey_rrset_time +ldns_dnssec_derive_trust_tree_ds_rrset +ldns_dnssec_derive_trust_tree_ds_rrset_time +ldns_dnssec_derive_trust_tree_normal_rrset +ldns_dnssec_derive_trust_tree_normal_rrset_time +ldns_dnssec_derive_trust_tree_no_sig +ldns_dnssec_derive_trust_tree_no_sig_time +ldns_dnssec_derive_trust_tree_time +ldns_dnssec_get_dnskey_for_rrsig +ldns_dnssec_get_rrsig_for_name_and_type +ldns_dnssec_name_add_rr +ldns_dnssec_name_cmp +ldns_dnssec_name_deep_free +ldns_dnssec_name_find_rrset +ldns_dnssec_name_free +ldns_dnssec_name_is_glue +ldns_dnssec_name_name +ldns_dnssec_name_new +ldns_dnssec_name_new_frm_rr +ldns_dnssec_name_node_deep_free +ldns_dnssec_name_node_free +ldns_dnssec_name_node_next_nonglue +ldns_dnssec_name_nsec +ldns_dnssec_name_print +ldns_dnssec_name_print_fmt +ldns_dnssec_name_print_soa +ldns_dnssec_name_print_soa_fmt +ldns_dnssec_name_set_name +ldns_dnssec_name_set_nsec +ldns_dnssec_nsec3_closest_encloser +ldns_dnssec_pkt_get_rrsigs_for_name_and_type +ldns_dnssec_pkt_get_rrsigs_for_type +ldns_dnssec_pkt_has_rrsigs +ldns_dnssec_remove_signatures +ldns_dnssec_rrs_add_rr +ldns_dnssec_rrs_deep_free +ldns_dnssec_rrsets_add_rr +ldns_dnssec_rrsets_contains_type +ldns_dnssec_rrsets_deep_free +ldns_dnssec_rrsets_free +ldns_dnssec_rrsets_new +ldns_dnssec_rrsets_new_frm_rr +ldns_dnssec_rrsets_print +ldns_dnssec_rrsets_print_fmt +ldns_dnssec_rrsets_print_soa +ldns_dnssec_rrsets_print_soa_fmt +ldns_dnssec_rrsets_set_type +ldns_dnssec_rrsets_type +ldns_dnssec_rrs_free +ldns_dnssec_rrs_new +ldns_dnssec_rrs_print +ldns_dnssec_rrs_print_fmt +ldns_dnssec_trust_tree_add_parent +ldns_dnssec_trust_tree_contains_keys +ldns_dnssec_trust_tree_depth +ldns_dnssec_trust_tree_free +ldns_dnssec_trust_tree_new +ldns_dnssec_trust_tree_print +ldns_dnssec_trust_tree_print_fmt +ldns_dnssec_trust_tree_print_sm +ldns_dnssec_trust_tree_print_sm_fmt +ldns_dnssec_verify_denial +ldns_dnssec_verify_denial_nsec3 +ldns_dnssec_zone_add_empty_nonterminals +ldns_dnssec_zone_add_rr +ldns_dnssec_zone_create_nsec3s +ldns_dnssec_zone_create_nsecs +ldns_dnssec_zone_create_rrsigs +ldns_dnssec_zone_create_rrsigs_flg +ldns_dnssec_zone_deep_free +ldns_dnssec_zone_find_nsec3_original +ldns_dnssec_zone_find_rrset +ldns_dnssec_zone_free +ldns_dnssec_zone_is_nsec3_optout +ldns_dnssec_zone_mark_and_get_glue +ldns_dnssec_zone_mark_glue +ldns_dnssec_zone_names_print +ldns_dnssec_zone_names_print_fmt +ldns_dnssec_zone_new +ldns_dnssec_zone_new_frm_fp +ldns_dnssec_zone_new_frm_fp_l +ldns_dnssec_zone_print +ldns_dnssec_zone_print_fmt +ldns_dnssec_zone_sign +ldns_dnssec_zone_sign_flg +ldns_dnssec_zone_sign_nsec3 +ldns_dnssec_zone_sign_nsec3_flg +ldns_dnssec_zone_sign_nsec3_flg_mkmap +ldns_ecdsa2pkey_raw +ldns_edns_flags +ldns_error_str +ldns_fetch_valid_domain_keys +ldns_fetch_valid_domain_keys_time +ldns_fget_keyword_data +ldns_fget_keyword_data_l +ldns_fget_token +ldns_fget_token_l +ldns_fskipc +ldns_fskipcs +ldns_fskipcs_l +ldns_getaddrinfo +ldns_get_bit +ldns_get_bit_r +ldns_get_errorstr_by_id +ldns_get_random +ldns_get_rr_class_by_name +ldns_get_rr_list_addr_by_name +ldns_get_rr_list_hosts_frm_file +ldns_get_rr_list_hosts_frm_fp +ldns_get_rr_list_hosts_frm_fp_l +ldns_get_rr_list_name_by_addr +ldns_get_rr_type_by_name +ldns_get_signing_algorithm_by_name +ldns_gost2pkey_raw +ldns_hexdigit_to_int +ldns_hexstring_to_data +ldns_init_random +ldns_int_to_hexdigit +ldns_is_rrset +ldns_key2buffer_str +ldns_key2rr +ldns_key2str +ldns_key_algorithm +ldns_key_algo_supported +ldns_key_buf2dsa +ldns_key_buf2dsa_raw +ldns_key_buf2rsa +ldns_key_buf2rsa_raw +ldns_key_deep_free +ldns_key_dsa_key +ldns_key_evp_key +ldns_key_EVP_load_gost_id +ldns_key_EVP_unload_gost +ldns_key_expiration +ldns_key_external_key +ldns_key_flags +ldns_key_free +ldns_key_get_file_base_name +ldns_key_hmac_key +ldns_key_hmac_size +ldns_key_inception +ldns_key_keytag +ldns_key_list_free +ldns_key_list_key +ldns_key_list_key_count +ldns_key_list_new +ldns_key_list_pop_key +ldns_key_list_push_key +ldns_key_list_set_key_count +ldns_key_list_set_use +ldns_key_new +ldns_key_new_frm_algorithm +ldns_key_new_frm_engine +ldns_key_new_frm_fp +ldns_key_new_frm_fp_dsa +ldns_key_new_frm_fp_dsa_l +ldns_key_new_frm_fp_hmac +ldns_key_new_frm_fp_hmac_l +ldns_key_new_frm_fp_l +ldns_key_new_frm_fp_rsa +ldns_key_new_frm_fp_rsa_l +ldns_key_origttl +ldns_key_print +ldns_key_pubkey_owner +ldns_key_rr2ds +ldns_key_rsa_key +ldns_key_set_algorithm +ldns_key_set_dsa_key +ldns_key_set_evp_key +ldns_key_set_expiration +ldns_key_set_external_key +ldns_key_set_flags +ldns_key_set_hmac_key +ldns_key_set_hmac_size +ldns_key_set_inception +ldns_key_set_keytag +ldns_key_set_origttl +ldns_key_set_pubkey_owner +ldns_key_set_rsa_key +ldns_key_set_use +ldns_key_use +ldns_lookup_by_id +ldns_lookup_by_name +ldns_native2rdf_int16 +ldns_native2rdf_int16_data +ldns_native2rdf_int32 +ldns_native2rdf_int8 +ldns_nsec3_add_param_rdfs +ldns_nsec3_algorithm +ldns_nsec3_bitmap +ldns_nsec3_flags +ldns_nsec3_hash_name +ldns_nsec3_hash_name_frm_nsec3 +ldns_nsec3_iterations +ldns_nsec3_next_owner +ldns_nsec3_optout +ldns_nsec3_salt +ldns_nsec3_salt_data +ldns_nsec3_salt_length +ldns_nsec_bitmap_covers_type +ldns_nsec_covers_name +ldns_nsec_get_bitmap +ldns_nsec_type_check +ldns_octet +ldns_opcodes +ldns_pkt2buffer_str +ldns_pkt2buffer_str_fmt +ldns_pkt2buffer_wire +ldns_pkt2str +ldns_pkt2str_fmt +ldns_pkt2wire +ldns_pkt_aa +ldns_pkt_ad +ldns_pkt_additional +ldns_pkt_algorithm2str +ldns_pkt_all +ldns_pkt_all_noquestion +ldns_pkt_ancount +ldns_pkt_answer +ldns_pkt_answerfrom +ldns_pkt_arcount +ldns_pkt_authority +ldns_pkt_cd +ldns_pkt_cert_algorithm2str +ldns_pkt_clone +ldns_pkt_edns +ldns_pkt_edns_data +ldns_pkt_edns_do +ldns_pkt_edns_extended_rcode +ldns_pkt_edns_udp_size +ldns_pkt_edns_version +ldns_pkt_edns_z +ldns_pkt_empty +ldns_pkt_free +ldns_pkt_get_opcode +ldns_pkt_get_rcode +ldns_pkt_get_section_clone +ldns_pktheader2buffer_str +ldns_pkt_id +ldns_pkt_new +ldns_pkt_nscount +ldns_pkt_opcode2buffer_str +ldns_pkt_opcode2str +ldns_pkt_print +ldns_pkt_print_fmt +ldns_pkt_push_rr +ldns_pkt_push_rr_list +ldns_pkt_qdcount +ldns_pkt_qr +ldns_pkt_query_new +ldns_pkt_query_new_frm_str +ldns_pkt_querytime +ldns_pkt_question +ldns_pkt_ra +ldns_pkt_rcode2buffer_str +ldns_pkt_rcode2str +ldns_pkt_rd +ldns_pkt_reply_type +ldns_pkt_rr +ldns_pkt_rr_list_by_name +ldns_pkt_rr_list_by_name_and_type +ldns_pkt_rr_list_by_type +ldns_pkt_safe_push_rr +ldns_pkt_safe_push_rr_list +ldns_pkt_section_count +ldns_pkt_set_aa +ldns_pkt_set_ad +ldns_pkt_set_additional +ldns_pkt_set_ancount +ldns_pkt_set_answer +ldns_pkt_set_answerfrom +ldns_pkt_set_arcount +ldns_pkt_set_authority +ldns_pkt_set_cd +ldns_pkt_set_edns_data +ldns_pkt_set_edns_do +ldns_pkt_set_edns_extended_rcode +ldns_pkt_set_edns_udp_size +ldns_pkt_set_edns_version +ldns_pkt_set_edns_z +ldns_pkt_set_flags +ldns_pkt_set_id +ldns_pkt_set_nscount +ldns_pkt_set_opcode +ldns_pkt_set_qdcount +ldns_pkt_set_qr +ldns_pkt_set_querytime +ldns_pkt_set_question +ldns_pkt_set_ra +ldns_pkt_set_random_id +ldns_pkt_set_rcode +ldns_pkt_set_rd +ldns_pkt_set_section_count +ldns_pkt_set_size +ldns_pkt_set_tc +ldns_pkt_set_timestamp +ldns_pkt_set_tsig +ldns_pkt_size +ldns_pkt_tc +ldns_pkt_timestamp +ldns_pkt_tsig +ldns_pkt_tsig_sign +ldns_pkt_tsig_sign_next +ldns_pkt_tsig_verify +ldns_pkt_tsig_verify_next +ldns_pkt_verify +ldns_pkt_verify_time +ldns_print_rr_rdf +ldns_rbtree_create +ldns_rbtree_delete +ldns_rbtree_find_less_equal +ldns_rbtree_first +ldns_rbtree_free +ldns_rbtree_init +ldns_rbtree_insert +ldns_rbtree_insert_vref +ldns_rbtree_join +ldns_rbtree_last +ldns_rbtree_next +ldns_rbtree_null_node +ldns_rbtree_previous +ldns_rbtree_search +ldns_rbtree_split +ldns_rcodes +ldns_rdf2buffer_str +ldns_rdf2buffer_str_a +ldns_rdf2buffer_str_aaaa +ldns_rdf2buffer_str_alg +ldns_rdf2buffer_str_apl +ldns_rdf2buffer_str_b32_ext +ldns_rdf2buffer_str_b64 +ldns_rdf2buffer_str_cert_alg +ldns_rdf2buffer_str_class +ldns_rdf2buffer_str_dname +ldns_rdf2buffer_str_hex +ldns_rdf2buffer_str_int16 +ldns_rdf2buffer_str_int16_data +ldns_rdf2buffer_str_int32 +ldns_rdf2buffer_str_int8 +ldns_rdf2buffer_str_ipseckey +ldns_rdf2buffer_str_loc +ldns_rdf2buffer_str_nsap +ldns_rdf2buffer_str_nsec +ldns_rdf2buffer_str_nsec3_salt +ldns_rdf2buffer_str_period +ldns_rdf2buffer_str_str +ldns_rdf2buffer_str_time +ldns_rdf2buffer_str_tsig +ldns_rdf2buffer_str_tsigtime +ldns_rdf2buffer_str_type +ldns_rdf2buffer_str_unknown +ldns_rdf2buffer_str_wks +ldns_rdf2buffer_wire +ldns_rdf2buffer_wire_canonical +ldns_rdf2native_int16 +ldns_rdf2native_int32 +ldns_rdf2native_int8 +ldns_rdf2native_sockaddr_storage +ldns_rdf2native_time_t +ldns_rdf2rr_type +ldns_rdf2str +ldns_rdf2wire +ldns_rdf_address_reverse +ldns_rdf_clone +ldns_rdf_compare +ldns_rdf_data +ldns_rdf_deep_free +ldns_rdf_free +ldns_rdf_get_type +ldns_rdf_new +ldns_rdf_new_frm_data +ldns_rdf_new_frm_fp +ldns_rdf_new_frm_fp_l +ldns_rdf_new_frm_str +ldns_rdf_print +ldns_rdf_set_data +ldns_rdf_set_size +ldns_rdf_set_type +ldns_rdf_size +ldns_read_anchor_file +ldns_resolver_debug +ldns_resolver_dec_nameserver_count +ldns_resolver_deep_free +ldns_resolver_defnames +ldns_resolver_dnsrch +ldns_resolver_dnssec +ldns_resolver_dnssec_anchors +ldns_resolver_dnssec_cd +ldns_resolver_domain +ldns_resolver_edns_udp_size +ldns_resolver_fail +ldns_resolver_fallback +ldns_resolver_free +ldns_resolver_igntc +ldns_resolver_incr_nameserver_count +ldns_resolver_ip6 +ldns_resolver_nameserver_count +ldns_resolver_nameserver_rtt +ldns_resolver_nameservers +ldns_resolver_nameservers_randomize +ldns_resolver_new +ldns_resolver_new_frm_file +ldns_resolver_new_frm_fp +ldns_resolver_new_frm_fp_l +ldns_resolver_pop_nameserver +ldns_resolver_port +ldns_resolver_prepare_query_pkt +ldns_resolver_print +ldns_resolver_print_fmt +ldns_resolver_push_dnssec_anchor +ldns_resolver_push_nameserver +ldns_resolver_push_nameserver_rr +ldns_resolver_push_nameserver_rr_list +ldns_resolver_push_searchlist +ldns_resolver_query +ldns_resolver_random +ldns_resolver_recursive +ldns_resolver_retrans +ldns_resolver_retry +ldns_resolver_rtt +ldns_resolver_search +ldns_resolver_searchlist +ldns_resolver_searchlist_count +ldns_resolver_send +ldns_resolver_send_pkt +ldns_resolver_set_debug +ldns_resolver_set_defnames +ldns_resolver_set_dnsrch +ldns_resolver_set_dnssec +ldns_resolver_set_dnssec_anchors +ldns_resolver_set_dnssec_cd +ldns_resolver_set_domain +ldns_resolver_set_edns_udp_size +ldns_resolver_set_fail +ldns_resolver_set_fallback +ldns_resolver_set_igntc +ldns_resolver_set_ip6 +ldns_resolver_set_nameserver_count +ldns_resolver_set_nameserver_rtt +ldns_resolver_set_nameservers +ldns_resolver_set_port +ldns_resolver_set_random +ldns_resolver_set_recursive +ldns_resolver_set_retrans +ldns_resolver_set_retry +ldns_resolver_set_rtt +ldns_resolver_set_searchlist_count +ldns_resolver_set_timeout +ldns_resolver_set_tsig_algorithm +ldns_resolver_set_tsig_keydata +ldns_resolver_set_tsig_keyname +ldns_resolver_set_usevc +ldns_resolver_timeout +ldns_resolver_trusted_key +ldns_resolver_tsig_algorithm +ldns_resolver_tsig_keydata +ldns_resolver_tsig_keyname +ldns_resolver_usevc +ldns_rr2buffer_str +ldns_rr2buffer_str_fmt +ldns_rr2buffer_wire +ldns_rr2buffer_wire_canonical +ldns_rr2canonical +ldns_rr2str +ldns_rr2str_fmt +ldns_rr2wire +ldns_rr_a_address +ldns_rr_a_set_address +ldns_rr_class2buffer_str +ldns_rr_class2str +ldns_rr_classes +ldns_rr_clone +ldns_rr_compare +ldns_rr_compare_ds +ldns_rr_compare_no_rdata +ldns_rr_compare_wire +ldns_rr_descript +ldns_rr_descriptor_field_type +ldns_rr_descriptor_maximum +ldns_rr_descriptor_minimum +ldns_rr_dnskey_algorithm +ldns_rr_dnskey_flags +ldns_rr_dnskey_key +ldns_rr_dnskey_key_size +ldns_rr_dnskey_key_size_raw +ldns_rr_dnskey_protocol +ldns_rr_dnskey_set_algorithm +ldns_rr_dnskey_set_flags +ldns_rr_dnskey_set_key +ldns_rr_dnskey_set_protocol +ldns_rr_free +ldns_rr_get_class +ldns_rr_get_type +ldns_rr_label_count +ldns_rr_list2buffer_str +ldns_rr_list2buffer_str_fmt +ldns_rr_list2buffer_wire +ldns_rr_list2canonical +ldns_rr_list2str +ldns_rr_list2str_fmt +ldns_rr_list_cat +ldns_rr_list_cat_clone +ldns_rr_list_clone +ldns_rr_list_compare +ldns_rr_list_contains_rr +ldns_rr_list_deep_free +ldns_rr_list_free +ldns_rr_list_new +ldns_rr_list_owner +ldns_rr_list_pop_rr +ldns_rr_list_pop_rr_list +ldns_rr_list_pop_rrset +ldns_rr_list_print +ldns_rr_list_print_fmt +ldns_rr_list_push_rr +ldns_rr_list_push_rr_list +ldns_rr_list_rr +ldns_rr_list_rr_count +ldns_rr_list_set_rr +ldns_rr_list_set_rr_count +ldns_rr_list_sort +ldns_rr_list_sort_nsec3 +ldns_rr_list_subtype_by_rdf +ldns_rr_list_type +ldns_rr_mx_exchange +ldns_rr_mx_preference +ldns_rr_new +ldns_rr_new_frm_fp +ldns_rr_new_frm_fp_l +ldns_rr_new_frm_str +ldns_rr_new_frm_type +ldns_rr_new_question_frm_str +ldns_rr_ns_nsdname +ldns_rr_owner +ldns_rr_pop_rdf +ldns_rr_print +ldns_rr_print_fmt +ldns_rr_push_rdf +ldns_rr_rdata2buffer_wire +ldns_rr_rd_count +ldns_rr_rdf +ldns_rr_rrsig_algorithm +ldns_rr_rrsig_expiration +ldns_rr_rrsig_inception +ldns_rr_rrsig_keytag +ldns_rr_rrsig_labels +ldns_rr_rrsig_origttl +ldns_rr_rrsig_set_algorithm +ldns_rr_rrsig_set_expiration +ldns_rr_rrsig_set_inception +ldns_rr_rrsig_set_keytag +ldns_rr_rrsig_set_labels +ldns_rr_rrsig_set_origttl +ldns_rr_rrsig_set_sig +ldns_rr_rrsig_set_signame +ldns_rr_rrsig_set_typecovered +ldns_rr_rrsig_sig +ldns_rr_rrsig_signame +ldns_rr_rrsig_typecovered +ldns_rr_set_class +ldns_rr_set_owner +ldns_rr_set_pop_rr +ldns_rr_set_push_rr +ldns_rr_set_rd_count +ldns_rr_set_rdf +ldns_rr_set_ttl +ldns_rr_set_type +ldns_rr_soa_increment +ldns_rr_soa_increment_func +ldns_rr_soa_increment_func_data +ldns_rr_soa_increment_func_int +ldns_rrsig2buffer_wire +ldns_rr_ttl +ldns_rr_type2buffer_str +ldns_rr_type2str +ldns_rr_uncompressed_size +ldns_send +ldns_send_buffer +ldns_serial_arithmitics_gmtime_r +ldns_set_bit +ldns_sha1 +ldns_sha1_final +ldns_sha1_init +ldns_sha1_transform +ldns_sha1_update +ldns_signing_algorithms +ldns_sign_public +ldns_sign_public_buffer +ldns_sign_public_dsa +ldns_sign_public_evp +ldns_sign_public_rsamd5 +ldns_sign_public_rsasha1 +ldns_soa_serial_datecounter +ldns_soa_serial_identity +ldns_soa_serial_increment +ldns_soa_serial_increment_by +ldns_soa_serial_unixtime +ldns_sockaddr_storage2rdf +ldns_str2period +ldns_str2rdf_a +ldns_str2rdf_aaaa +ldns_str2rdf_alg +ldns_str2rdf_apl +ldns_str2rdf_b32_ext +ldns_str2rdf_b64 +ldns_str2rdf_cert_alg +ldns_str2rdf_class +ldns_str2rdf_dname +ldns_str2rdf_hex +ldns_str2rdf_int16 +ldns_str2rdf_int32 +ldns_str2rdf_int8 +ldns_str2rdf_loc +ldns_str2rdf_nsap +ldns_str2rdf_nsec +ldns_str2rdf_nsec3_salt +ldns_str2rdf_period +ldns_str2rdf_service +ldns_str2rdf_str +ldns_str2rdf_time +ldns_str2rdf_tsig +ldns_str2rdf_type +ldns_str2rdf_unknown +ldns_str2rdf_wks +ldns_tcp_bgsend +ldns_tcp_connect +ldns_tcp_read_wire +ldns_tcp_read_wire_timeout +ldns_tcp_send +ldns_tcp_send_query +ldns_traverse_postorder +ldns_tsig_algorithm +ldns_tsig_keydata +ldns_tsig_keydata_clone +ldns_tsig_keyname +ldns_tsig_keyname_clone +ldns_tsig_prepare_pkt_wire +ldns_udp_bgsend +ldns_udp_connect +ldns_udp_read_wire +ldns_udp_send +ldns_udp_send_query +ldns_update_ad +ldns_update_pkt_new +ldns_update_pkt_tsig_add +ldns_update_prcount +ldns_update_set_adcount +ldns_update_set_prcount +ldns_update_set_upcount +ldns_update_set_zo +ldns_update_soa_mname +ldns_update_soa_zone_mname +ldns_update_upcount +ldns_update_zocount +ldns_validate_domain_dnskey +ldns_validate_domain_dnskey_time +ldns_validate_domain_ds +ldns_validate_domain_ds_time +ldns_verify +ldns_verify_notime +ldns_verify_rrsig +ldns_verify_rrsig_buffers +ldns_verify_rrsig_buffers_raw +ldns_verify_rrsig_dsa +ldns_verify_rrsig_dsa_raw +ldns_verify_rrsig_evp +ldns_verify_rrsig_evp_raw +ldns_verify_rrsig_keylist +ldns_verify_rrsig_keylist_notime +ldns_verify_rrsig_keylist_time +ldns_verify_rrsig_rsamd5 +ldns_verify_rrsig_rsamd5_raw +ldns_verify_rrsig_rsasha1 +ldns_verify_rrsig_rsasha1_raw +ldns_verify_rrsig_rsasha256_raw +ldns_verify_rrsig_rsasha512_raw +ldns_verify_rrsig_time +ldns_verify_time +ldns_verify_trusted +ldns_verify_trusted_time +ldns_version +ldns_wire2dname +ldns_wire2pkt +ldns_wire2rdf +ldns_wire2rr +ldns_zone_deep_free +ldns_zone_free +ldns_zone_glue_rr_list +ldns_zone_new +ldns_zone_new_frm_fp +ldns_zone_new_frm_fp_l +ldns_zone_print +ldns_zone_print_fmt +ldns_zone_push_rr +ldns_zone_push_rr_list +ldns_zone_rr_count +ldns_zone_rrs +ldns_zone_set_rrs +ldns_zone_set_soa +ldns_zone_sign +ldns_zone_sign_nsec3 +ldns_zone_soa +ldns_zone_sort +ldns_zone_strip_glue_rrs diff --git a/libdns.doxygen b/libdns.doxygen new file mode 100644 index 00000000000..3325db94af4 --- /dev/null +++ b/libdns.doxygen @@ -0,0 +1,1684 @@ +# Doxyfile 1.7.3 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" "). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = ldns + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = 1.6.7 + +# Using the PROJECT_BRIEF tag one can provide an optional one line description for a project that appears at the top of each page and should give viewer a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = doc/ + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful if your file system +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also makes the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penalty. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will roughly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols + +SYMBOL_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespaces are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = NO + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even if there is only one candidate or it is obvious which candidate to choose by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or macro consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and macros in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = NO + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. The create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_NO_PARAMDOC option can be enabled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "doxygen: $file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = . \ + ldns/ \ + doc/ \ + examples/ldns-mx.c \ + examples/ldns-read-zone.c \ + examples/ldns-signzone.c + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = examples + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = doc/images + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty or if +# non of the patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 3 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = ldns_ + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = doc/header.html + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the stylesheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +#
+# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [0,1..20]) +# that doxygen will group on one line in the generated HTML documentation. +# Note that a value of 0 will completely suppress the enum values from appearing in the overview section. + +ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX = NO + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the mathjax.org site, so you can quickly see the result without installing +# MathJax, but it is strongly recommended to install a local copy of MathJax +# before deployment. + +MATHJAX_RELPATH = http://www.mathjax.org/mathjax + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = NO + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvantages are that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = YES + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = YES + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = HAVE_SSL + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition that overrules the definition found in the source code. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these will confuse the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will write a font called Helvetica to the output +# directory and reference it in all dot files that doxygen generates. +# When you want a differently looking font you can specify the font name +# using DOT_FONTNAME. You need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = Helvetica + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = YES + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will generate a graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, svg, gif or svg. +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). + +MSCFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = YES + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/libdns.vim b/libdns.vim new file mode 100644 index 00000000000..c757eacd12d --- /dev/null +++ b/libdns.vim @@ -0,0 +1,459 @@ +" Vim syntax file +" Language: C libdns +" Maintainer: miekg +" Last change: 2011-09-15 + +" ldns/util.h +syn keyword ldnsMacro LDNS_MALLOC +syn keyword ldnsMacro LDNS_XMALLOC +syn keyword ldnsMacro LDNS_CALLOC +syn keyword ldnsMacro LDNS_REALLOC +syn keyword ldnsMacro LDNS_XREALLOC +syn keyword ldnsMacro LDNS_FREE +syn keyword ldnsMacro LDNS_DEP +syn keyword ldnsMacro LDNS_VERSION +syn keyword ldnsMacro LDNS_REVISION + +" ldns/dname.h +syn keyword ldnsMacro LDNS_DNAME_NORMALIZE + +" ldns/tsig.h +syn keyword ldnsType ldns_tsig_credentials + +" ldns/update.h +" -- + +" ldns/rdata.h +syn keyword ldnsType ldns_rdf +syn keyword ldnsType ldns_rdf_type +syn keyword ldnsType ldns_cert_algorithm +syn keyword ldnsConstant LDNS_RDF_TYPE_NONE +syn keyword ldnsConstant LDNS_RDF_TYPE_DNAME +syn keyword ldnsConstant LDNS_RDF_TYPE_INT8 +syn keyword ldnsConstant LDNS_RDF_TYPE_INT16 +syn keyword ldnsConstant LDNS_RDF_TYPE_INT16_DATA +syn keyword ldnsConstant LDNS_RDF_TYPE_INT32 +syn keyword ldnsConstant LDNS_RDF_TYPE_A +syn keyword ldnsConstant LDNS_RDF_TYPE_AAAA +syn keyword ldnsConstant LDNS_RDF_TYPE_STR +syn keyword ldnsConstant LDNS_RDF_TYPE_APL +syn keyword ldnsConstant LDNS_RDF_TYPE_B32_EXT +syn keyword ldnsConstant LDNS_RDF_TYPE_B64 +syn keyword ldnsConstant LDNS_RDF_TYPE_HEX +syn keyword ldnsConstant LDNS_RDF_TYPE_NSEC +syn keyword ldnsConstant LDNS_RDF_TYPE_TYPE +syn keyword ldnsConstant LDNS_RDF_TYPE_CLASS +syn keyword ldnsConstant LDNS_RDF_TYPE_CERT +syn keyword ldnsConstant LDNS_RDF_TYPE_CERT_ALG +syn keyword ldnsConstant LDNS_RDF_TYPE_ALG +syn keyword ldnsConstant LDNS_RDF_TYPE_UNKNOWN +syn keyword ldnsConstant LDNS_RDF_TYPE_TIME +syn keyword ldnsConstant LDNS_RDF_TYPE_PERIOD +syn keyword ldnsConstant LDNS_RDF_TYPE_TSIGTIME +syn keyword ldnsConstant LDNS_RDF_TYPE_SERVICE +syn keyword ldnsConstant LDNS_RDF_TYPE_LOC +syn keyword ldnsConstant LDNS_RDF_TYPE_WKS +syn keyword ldnsConstant LDNS_RDF_TYPE_NSAP +syn keyword ldnsConstant LDNS_RDF_TYPE_ATMA +syn keyword ldnsConstant LDNS_RDF_TYPE_NSEC3_SALT +syn keyword ldnsConstant LDNS_RDF_TYPE_NSEC3_NEXT_OWNER +syn keyword ldnsConstant LDNS_RDF_TYPE_IPSECKEY +syn keyword ldnsConstant LDNS_RDF_TYPE_TSIG +syn keyword ldnsConstant LDNS_MAX_RDFLEN +syn keyword ldnsConstant LDNS_RDF_SIZE_BYTE +syn keyword ldnsConstant LDNS_RDF_SIZE_WORD +syn keyword ldnsConstant LDNS_RDF_SIZE_DOUBLEWORD +syn keyword ldnsConstant LDNS_RDF_SIZE_6BYTES +syn keyword ldnsConstant LDNS_RDF_SIZE_16BYTES +syn keyword ldnsConstant LDNS_NSEC3_VARS_OPTOUT_MASK + +syn keyword ldnsConstant LDNS_CERT_PKIX +syn keyword ldnsConstant LDNS_CERT_SPKI +syn keyword ldnsConstant LDNS_CERT_PGP +syn keyword ldnsConstant LDNS_CERT_IPKIX +syn keyword ldnsConstant LDNS_CERT_ISPKI +syn keyword ldnsConstant LDNS_CERT_IPGP +syn keyword ldnsConstant LDNS_CERT_ACPKIX +syn keyword ldnsConstant LDNS_CERT_IACPKIX +syn keyword ldnsConstant LDNS_CERT_URI +syn keyword ldnsConstant LDNS_CERT_OID + +" ldns/ldns.h +syn keyword ldnsConstant LDNS_PORT +syn keyword ldnsConstant LDNS_IP4ADDRLEN +syn keyword ldnsConstant LDNS_IP6ADDRLEN +syn keyword ldnsConstant LDNS_ROOT_LABEL_STR +syn keyword ldnsConstant LDNS_DEFAULT_TTL + +" ldns/packet.h +syn keyword ldnsType ldns_pkt +syn keyword ldnsType ldns_pkt_section +syn keyword ldnsType ldns_pkt_type +syn keyword ldnsType ldns_pkt_opcode +syn keyword ldnsType ldns_pkt_rcode +syn keyword ldnsType ldns_hdr +syn keyword ldnsConstant LDNS_QR +syn keyword ldnsConstant LDNS_AA +syn keyword ldnsConstant LDNS_TC +syn keyword ldnsConstant LDNS_RD +syn keyword ldnsConstant LDNS_CD +syn keyword ldnsConstant LDNS_RA +syn keyword ldnsConstant LDNS_AD +syn keyword ldnsConstant LDNS_MAX_PACKETLEN +syn keyword ldnsConstant LDNS_PACKET_QUESTION +syn keyword ldnsConstant LDNS_PACKET_REFERRAL +syn keyword ldnsConstant LDNS_PACKET_ANSWER +syn keyword ldnsConstant LDNS_PACKET_NXDOMAIN +syn keyword ldnsConstant LDNS_PACKET_NODATA +syn keyword ldnsConstant LDNS_PACKET_UNKNOWN +syn keyword ldnsConstant LDNS_SECTION_QUESTION +syn keyword ldnsConstant LDNS_SECTION_ANSWER +syn keyword ldnsConstant LDNS_SECTION_AUTHORITY +syn keyword ldnsConstant LDNS_SECTION_ADDITIONAL +syn keyword ldnsConstant LDNS_SECTION_ANY +syn keyword ldnsConstant LDNS_SECTION_ANY_NOQUESTION +syn keyword ldnsConstant LDNS_PACKET_QUERY +syn keyword ldnsConstant LDNS_PACKET_IQUERY +syn keyword ldnsConstant LDNS_PACKET_STATUS +syn keyword ldnsConstant LDNS_PACKET_NOTIFY +syn keyword ldnsConstant LDNS_PACKET_UPDATE + +syn keyword ldnsConstant LDNS_RCODE_NOERROR +syn keyword ldnsConstant LDNS_RCODE_FORMERR +syn keyword ldnsConstant LDNS_RCODE_SERVFAIL +syn keyword ldnsConstant LDNS_RCODE_NXDOMAIN +syn keyword ldnsConstant LDNS_RCODE_NOTIMPL +syn keyword ldnsConstant LDNS_RCODE_REFUSED +syn keyword ldnsConstant LDNS_RCODE_YXDOMAIN +syn keyword ldnsConstant LDNS_RCODE_YXRRSET +syn keyword ldnsConstant LDNS_RCODE_NXRRSET +syn keyword ldnsConstant LDNS_RCODE_NOTAUTH +syn keyword ldnsConstant LDNS_RCODE_NOTZONE + +" dns/error.h +syn keyword ldnsConstant LDNS_STATUS_OK +syn keyword ldnsConstant LDNS_STATUS_EMPTY_LABEL +syn keyword ldnsConstant LDNS_STATUS_LABEL_OVERFLOW +syn keyword ldnsConstant LDNS_STATUS_DOMAINNAME_OVERFLOW +syn keyword ldnsConstant LDNS_STATUS_DOMAINNAME_UNDERFLOW +syn keyword ldnsConstant LDNS_STATUS_DDD_OVERFLOW +syn keyword ldnsConstant LDNS_STATUS_PACKET_OVERFLOW +syn keyword ldnsConstant LDNS_STATUS_INVALID_POINTER +syn keyword ldnsConstant LDNS_STATUS_MEM_ERR +syn keyword ldnsConstant LDNS_STATUS_INTERNAL_ERR +syn keyword ldnsConstant LDNS_STATUS_SSL_ERR +syn keyword ldnsConstant LDNS_STATUS_ERR +syn keyword ldnsConstant LDNS_STATUS_INVALID_INT +syn keyword ldnsConstant LDNS_STATUS_INVALID_IP4 +syn keyword ldnsConstant LDNS_STATUS_INVALID_IP6 +syn keyword ldnsConstant LDNS_STATUS_INVALID_STR +syn keyword ldnsConstant LDNS_STATUS_INVALID_B32_EXT +syn keyword ldnsConstant LDNS_STATUS_INVALID_B64 +syn keyword ldnsConstant LDNS_STATUS_INVALID_HEX +syn keyword ldnsConstant LDNS_STATUS_INVALID_TIME +syn keyword ldnsConstant LDNS_STATUS_NETWORK_ERR +syn keyword ldnsConstant LDNS_STATUS_ADDRESS_ERR +syn keyword ldnsConstant LDNS_STATUS_FILE_ERR +syn keyword ldnsConstant LDNS_STATUS_UNKNOWN_INET +syn keyword ldnsConstant LDNS_STATUS_NOT_IMPL +syn keyword ldnsConstant LDNS_STATUS_NULL +syn keyword ldnsConstant LDNS_STATUS_CRYPTO_UNKNOWN_ALGO +syn keyword ldnsConstant LDNS_STATUS_CRYPTO_ALGO_NOT_IMPL +syn keyword ldnsConstant LDNS_STATUS_CRYPTO_NO_RRSIG +syn keyword ldnsConstant LDNS_STATUS_CRYPTO_NO_DNSKEY +syn keyword ldnsConstant LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY +syn keyword ldnsConstant LDNS_STATUS_CRYPTO_NO_DS +syn keyword ldnsConstant LDNS_STATUS_CRYPTO_NO_TRUSTED_DS +syn keyword ldnsConstant LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY +syn keyword ldnsConstant LDNS_STATUS_CRYPTO_VALIDATED +syn keyword ldnsConstant LDNS_STATUS_CRYPTO_BOGUS +syn keyword ldnsConstant LDNS_STATUS_CRYPTO_SIG_EXPIRED +syn keyword ldnsConstant LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED +syn keyword ldnsConstant LDNS_STATUS_CRYPTO_TSIG_BOGUS +syn keyword ldnsConstant LDNS_STATUS_CRYPTO_TSIG_ERR +syn keyword ldnsConstant LDNS_STATUS_CRYPTO_EXPIRATION_BEFORE_INCEPTION +syn keyword ldnsConstant LDNS_STATUS_CRYPTO_TYPE_COVERED_ERR +syn keyword ldnsConstant LDNS_STATUS_ENGINE_KEY_NOT_LOADED +syn keyword ldnsConstant LDNS_STATUS_NSEC3_ERR +syn keyword ldnsConstant LDNS_STATUS_RES_NO_NS +syn keyword ldnsConstant LDNS_STATUS_RES_QUERY +syn keyword ldnsConstant LDNS_STATUS_WIRE_INCOMPLETE_HEADER +syn keyword ldnsConstant LDNS_STATUS_WIRE_INCOMPLETE_QUESTION +syn keyword ldnsConstant LDNS_STATUS_WIRE_INCOMPLETE_ANSWER +syn keyword ldnsConstant LDNS_STATUS_WIRE_INCOMPLETE_AUTHORITY +syn keyword ldnsConstant LDNS_STATUS_WIRE_INCOMPLETE_ADDITIONAL +syn keyword ldnsConstant LDNS_STATUS_NO_DATA +syn keyword ldnsConstant LDNS_STATUS_CERT_BAD_ALGORITHM +syn keyword ldnsConstant LDNS_STATUS_SYNTAX_TYPE_ERR +syn keyword ldnsConstant LDNS_STATUS_SYNTAX_CLASS_ERR +syn keyword ldnsConstant LDNS_STATUS_SYNTAX_TTL_ERR +syn keyword ldnsConstant LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL +syn keyword ldnsConstant LDNS_STATUS_SYNTAX_RDATA_ERR +syn keyword ldnsConstant LDNS_STATUS_SYNTAX_DNAME_ERR +syn keyword ldnsConstant LDNS_STATUS_SYNTAX_VERSION_ERR +syn keyword ldnsConstant LDNS_STATUS_SYNTAX_ALG_ERR +syn keyword ldnsConstant LDNS_STATUS_SYNTAX_KEYWORD_ERR +syn keyword ldnsConstant LDNS_STATUS_SYNTAX_TTL +syn keyword ldnsConstant LDNS_STATUS_SYNTAX_ORIGIN +syn keyword ldnsConstant LDNS_STATUS_SYNTAX_INCLUDE +syn keyword ldnsConstant LDNS_STATUS_SYNTAX_EMPTY +syn keyword ldnsConstant LDNS_STATUS_SYNTAX_ITERATIONS_OVERFLOW +syn keyword ldnsConstant LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR +syn keyword ldnsConstant LDNS_STATUS_SYNTAX_INTEGER_OVERFLOW +syn keyword ldnsConstant LDNS_STATUS_SYNTAX_BAD_ESCAPE +syn keyword ldnsConstant LDNS_STATUS_SOCKET_ERROR +syn keyword ldnsConstant LDNS_STATUS_SYNTAX_ERR +syn keyword ldnsConstant LDNS_STATUS_DNSSEC_EXISTENCE_DENIED +syn keyword ldnsConstant LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED +syn keyword ldnsConstant LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED +syn keyword ldnsConstant LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND +syn keyword ldnsConstant LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG +syn keyword ldnsConstant LDNS_STATUS_MISSING_RDATA_FIELDS_KEY + + +" ldns/resolver.h +syn keyword ldnsType ldns_resolver +syn keyword ldnsConstant LDNS_RESOLV_CONF +syn keyword ldnsConstant LDNS_RESOLV_HOSTS +syn keyword ldnsConstant LDNS_RESOLV_KEYWORD +syn keyword ldnsConstant LDNS_RESOLV_DEFDOMAIN +syn keyword ldnsConstant LDNS_RESOLV_NAMESERVER +syn keyword ldnsConstant LDNS_RESOLV_SEARCH +syn keyword ldnsConstant LDNS_RESOLV_SORTLIST +syn keyword ldnsConstant LDNS_RESOLV_OPTIONS +syn keyword ldnsConstant LDNS_RESOLV_ANCHOR +syn keyword ldnsConstant LDNS_RESOLV_KEYWORDS +syn keyword ldnsConstant LDNS_RESOLV_INETANY +syn keyword ldnsConstant LDNS_RESOLV_INET +syn keyword ldnsConstant LDNS_RESOLV_INET6 +syn keyword ldnsConstant LDNS_RESOLV_RTT_INF +syn keyword ldnsConstant LDNS_RESOLV_RTT_MIN + +" ldns/zone.h +syn keyword ldnsType ldns_zone + +" ldns/dnssec.h +syn keyword ldnsConstant LDNS_NSEC3_MAX_ITERATIONS +syn keyword ldnsConstant LDNS_DEFAULT_EXP_TIME +syn keyword ldnsConstant LDNS_DNSSEC_KEYPROTO +syn keyword ldnsConstant LDNS_MAX_KEYLEN +" ldns/dnssec_sign.h +" -- +" ldns/dnssec_zone.h +syn keyword ldnsType ldns_dnssec_rrs +syn keyword ldnsType ldns_dnssec_rrsets +syn keyword ldnsType ldns_dnssec_name +syn keyword ldnsType ldns_dnssec_zone +" ldns/dnssec_verify.h +syn keyword ldnsType ldns_dnssec_data_chain +syn keyword ldnsType ldns_dnssec_trust_tree + +" ldns/rr.h +syn keyword ldnsType ldns_rr_list +syn keyword ldnsType ldns_rr_descriptor +syn keyword ldnsType ldns_rr +syn keyword ldnsType ldns_rr_type +syn keyword ldnsType ldns_rr_class +syn keyword ldnsType ldns_rr_compress + +syn keyword ldnsConstant LDNS_MAX_LABELLEN +syn keyword ldnsConstant LDNS_MAX_DOMAINLEN +syn keyword ldnsConstant LDNS_RR_COMPRESS +syn keyword ldnsConstant LDNS_RR_NO_COMPRESS + +syn keyword ldnsConstant LDNS_RR_CLASS_IN +syn keyword ldnsConstant LDNS_RR_CLASS_CH +syn keyword ldnsConstant LDNS_RR_CLASS_HS +syn keyword ldnsConstant LDNS_RR_CLASS_NONE +syn keyword ldnsConstant LDNS_RR_CLASS_ANY + +syn keyword ldnsConstant LDNS_RR_TYPE_A +syn keyword ldnsConstant LDNS_RR_TYPE_A6 +syn keyword ldnsConstant LDNS_RR_TYPE_AAAA +syn keyword ldnsConstant LDNS_RR_TYPE_AFSDB +syn keyword ldnsConstant LDNS_RR_TYPE_ANY +syn keyword ldnsConstant LDNS_RR_TYPE_APL +syn keyword ldnsConstant LDNS_RR_TYPE_ATMA +syn keyword ldnsConstant LDNS_RR_TYPE_AXFR +syn keyword ldnsConstant LDNS_RR_TYPE_CERT +syn keyword ldnsConstant LDNS_RR_TYPE_CNAME +syn keyword ldnsConstant LDNS_RR_TYPE_COUNT +syn keyword ldnsConstant LDNS_RR_TYPE_DHCID +syn keyword ldnsConstant LDNS_RR_TYPE_DLV +syn keyword ldnsConstant LDNS_RR_TYPE_DNAME +syn keyword ldnsConstant LDNS_RR_TYPE_DNSKEY +syn keyword ldnsConstant LDNS_RR_TYPE_DS +syn keyword ldnsConstant LDNS_RR_TYPE_EID +syn keyword ldnsConstant LDNS_RR_TYPE_FIRST +syn keyword ldnsConstant LDNS_RR_TYPE_GID +syn keyword ldnsConstant LDNS_RR_TYPE_GPOS +syn keyword ldnsConstant LDNS_RR_TYPE_HINFO +syn keyword ldnsConstant LDNS_RR_TYPE_IPSECKEY +syn keyword ldnsConstant LDNS_RR_TYPE_ISDN +syn keyword ldnsConstant LDNS_RR_TYPE_IXFR +syn keyword ldnsConstant LDNS_RR_TYPE_KEY +syn keyword ldnsConstant LDNS_RR_TYPE_KX +syn keyword ldnsConstant LDNS_RR_TYPE_LAST +syn keyword ldnsConstant LDNS_RR_TYPE_LOC +syn keyword ldnsConstant LDNS_RR_TYPE_MAILA +syn keyword ldnsConstant LDNS_RR_TYPE_MAILB +syn keyword ldnsConstant LDNS_RR_TYPE_MB +syn keyword ldnsConstant LDNS_RR_TYPE_MD +syn keyword ldnsConstant LDNS_RR_TYPE_MF +syn keyword ldnsConstant LDNS_RR_TYPE_MG +syn keyword ldnsConstant LDNS_RR_TYPE_MINFO +syn keyword ldnsConstant LDNS_RR_TYPE_MR +syn keyword ldnsConstant LDNS_RR_TYPE_MX +syn keyword ldnsConstant LDNS_RR_TYPE_NAPTR +syn keyword ldnsConstant LDNS_RR_TYPE_NIMLOC +syn keyword ldnsConstant LDNS_RR_TYPE_NS +syn keyword ldnsConstant LDNS_RR_TYPE_NSAP +syn keyword ldnsConstant LDNS_RR_TYPE_NSAP_PTR +syn keyword ldnsConstant LDNS_RR_TYPE_NSEC +syn keyword ldnsConstant LDNS_RR_TYPE_NSEC3 +syn keyword ldnsConstant LDNS_RR_TYPE_NSEC3 +syn keyword ldnsConstant LDNS_RR_TYPE_NSEC3PARAM +syn keyword ldnsConstant LDNS_RR_TYPE_NSEC3PARAMS +syn keyword ldnsConstant LDNS_RR_TYPE_NSEC3PARAMS +syn keyword ldnsConstant LDNS_RR_TYPE_NULL +syn keyword ldnsConstant LDNS_RR_TYPE_NXT +syn keyword ldnsConstant LDNS_RR_TYPE_OPT +syn keyword ldnsConstant LDNS_RR_TYPE_PTR +syn keyword ldnsConstant LDNS_RR_TYPE_PX +syn keyword ldnsConstant LDNS_RR_TYPE_RP +syn keyword ldnsConstant LDNS_RR_TYPE_RRSIG +syn keyword ldnsConstant LDNS_RR_TYPE_RT +syn keyword ldnsConstant LDNS_RR_TYPE_SIG +syn keyword ldnsConstant LDNS_RR_TYPE_SINK +syn keyword ldnsConstant LDNS_RR_TYPE_SOA +syn keyword ldnsConstant LDNS_RR_TYPE_SPF +syn keyword ldnsConstant LDNS_RR_TYPE_SRV +syn keyword ldnsConstant LDNS_RR_TYPE_SSHFP +syn keyword ldnsConstant LDNS_RR_TYPE_TALINK +syn keyword ldnsConstant LDNS_RR_TYPE_TSIG +syn keyword ldnsConstant LDNS_RR_TYPE_TXT +syn keyword ldnsConstant LDNS_RR_TYPE_UID +syn keyword ldnsConstant LDNS_RR_TYPE_UINFO +syn keyword ldnsConstant LDNS_RR_TYPE_UNSPEC +syn keyword ldnsConstant LDNS_RR_TYPE_WKS +syn keyword ldnsConstant LDNS_RR_TYPE_X25 + +" ldns/buffer.h +syn keyword ldnsType ldns_buffer +syn keyword ldnsConstant LDNS_MIN_BUFLEN + +" ldns/host2str.h +syn keyword ldnsConstant LDNS_APL_IP4 +syn keyword ldnsConstant LDNS_APL_IP6 +syn keyword ldnsConstant LDNS_APL_MASK +syn keyword ldnsConstant LDNS_APL_NEGATION + +" ldns/keys.h +syn keyword ldnsType ldns_key +syn keyword ldnsType ldns_key_list +syn keyword ldnsType ldns_signing_algorithm +syn keyword ldnsType ldns_hash +syn keyword ldnsType ldns_algorithm +syn keyword ldnsConstant LDNS_KEY_ZONE_KEY +syn keyword ldnsConstant LDNS_KEY_SEP_KEY +syn keyword ldnsConstant LDNS_KEY_REVOKE_KEY +syn keyword ldnsConstant LDNS_SHA1 +syn keyword ldnsConstant LDNS_SHA256 +syn keyword ldnsConstant LDNS_HASH_GOST +syn keyword ldnsConstant LDNS_SHA384 + +syn keyword ldnsConstant LDNS_SIGN_RSAMD5 +syn keyword ldnsConstant LDNS_SIGN_RSASHA1 +syn keyword ldnsConstant LDNS_SIGN_DSA +syn keyword ldnsConstant LDNS_SIGN_RSASHA1_NSEC3 +syn keyword ldnsConstant LDNS_SIGN_RSASHA256 +syn keyword ldnsConstant LDNS_SIGN_RSASHA512 +syn keyword ldnsConstant LDNS_SIGN_DSA_NSEC3 +syn keyword ldnsConstant LDNS_SIGN_ECC_GOST +syn keyword ldnsConstant LDNS_SIGN_ECDSAP256SHA256 +syn keyword ldnsConstant LDNS_SIGN_ECDSAP384SHA384 +syn keyword ldnsConstant LDNS_SIGN_HMACMD5 +syn keyword ldnsConstant LDNS_SIGN_HMACSHA1 +syn keyword ldnsConstant LDNS_SIGN_HMACSHA256 + +" ldns/wire2host.h +syn keyword ldnsMacro LDNS_WIRE2HOST_H +syn keyword ldnsMacro LDNS_HEADER_SIZE +syn keyword ldnsMacro LDNS_RD_MASK +syn keyword ldnsMacro LDNS_RD_SHIFT +syn keyword ldnsMacro LDNS_RD_WIRE +syn keyword ldnsMacro LDNS_RD_SET +syn keyword ldnsMacro LDNS_RD_CLR +syn keyword ldnsMacro LDNS_TC_MASK +syn keyword ldnsMacro LDNS_TC_SHIFT +syn keyword ldnsMacro LDNS_TC_WIRE +syn keyword ldnsMacro LDNS_TC_SET +syn keyword ldnsMacro LDNS_TC_CLR +syn keyword ldnsMacro LDNS_AA_MASK +syn keyword ldnsMacro LDNS_AA_SHIFT +syn keyword ldnsMacro LDNS_AA_WIRE +syn keyword ldnsMacro LDNS_AA_SET +syn keyword ldnsMacro LDNS_AA_CLR +syn keyword ldnsMacro LDNS_OPCODE_MASK +syn keyword ldnsMacro LDNS_OPCODE_SHIFT +syn keyword ldnsMacro LDNS_OPCODE_WIRE +syn keyword ldnsMacro LDNS_OPCODE_SET +syn keyword ldnsMacro LDNS_QR_MASK +syn keyword ldnsMacro LDNS_QR_SHIFT +syn keyword ldnsMacro LDNS_QR_WIRE +syn keyword ldnsMacro LDNS_QR_SET +syn keyword ldnsMacro LDNS_QR_CLR +syn keyword ldnsMacro LDNS_RCODE_MASK +syn keyword ldnsMacro LDNS_RCODE_SHIFT +syn keyword ldnsMacro LDNS_RCODE_WIRE +syn keyword ldnsMacro LDNS_RCODE_SET +syn keyword ldnsMacro LDNS_CD_MASK +syn keyword ldnsMacro LDNS_CD_SHIFT +syn keyword ldnsMacro LDNS_CD_WIRE +syn keyword ldnsMacro LDNS_CD_SET +syn keyword ldnsMacro LDNS_CD_CLR +syn keyword ldnsMacro LDNS_AD_MASK +syn keyword ldnsMacro LDNS_AD_SHIFT +syn keyword ldnsMacro LDNS_AD_WIRE +syn keyword ldnsMacro LDNS_AD_SET +syn keyword ldnsMacro LDNS_AD_CLR +syn keyword ldnsMacro LDNS_Z_MASK +syn keyword ldnsMacro LDNS_Z_SHIFT +syn keyword ldnsMacro LDNS_Z_WIRE +syn keyword ldnsMacro LDNS_Z_SET +syn keyword ldnsMacro LDNS_Z_CLR +syn keyword ldnsMacro LDNS_RA_MASK +syn keyword ldnsMacro LDNS_RA_SHIFT +syn keyword ldnsMacro LDNS_RA_WIRE +syn keyword ldnsMacro LDNS_RA_SET +syn keyword ldnsMacro LDNS_RA_CLR +syn keyword ldnsMacro LDNS_ID_WIRE +syn keyword ldnsMacro LDNS_ID_SET +syn keyword ldnsMacro LDNS_QDCOUNT_OFF +syn keyword ldnsMacro QDCOUNT +syn keyword ldnsMacro LDNS_QDCOUNT +syn keyword ldnsMacro LDNS_ANCOUNT_OFF +syn keyword ldnsMacro LDNS_ANCOUNT +syn keyword ldnsMacro LDNS_NSCOUNT_OFF +syn keyword ldnsMacro LDNS_NSCOUNT +syn keyword ldnsMacro LDNS_ARCOUNT_OFF +syn keyword ldnsMacro LDNS_ARCOUNT + +" ldns/host2wire.h +" -- + +" ldns/* -- All functions +" Created with: +" Get all the functions that start with 'ldns_' +" egrep '^[a-z_]+ [*a-z_0-9]+\(' *.h | sed -e 's/(.*$//' | awk '{print $2}' | \ +" sed 's/^\*//' | grep '^ldns' | sort +" Not included, but could be added...? + +" Default highlighting +command -nargs=+ HiLink hi def link +HiLink ldnsType Type +" Currently no functions are defined +HiLink ldnsFunction Function +HiLink ldnsMacro Macro +HiLink ldnsConstant Constant +delcommand HiLink diff --git a/linktest.c b/linktest.c new file mode 100644 index 00000000000..c21753a53f7 --- /dev/null +++ b/linktest.c @@ -0,0 +1,13 @@ + +#include "ldns/config.h" +#include + +int +main(void) +{ + ldns_rr *rr = ldns_rr_new(); + + ldns_rr_free(rr); + return 0; +} + diff --git a/ltmain.sh b/ltmain.sh new file mode 100755 index 00000000000..c2852d85613 --- /dev/null +++ b/ltmain.sh @@ -0,0 +1,9661 @@ + +# libtool (GNU libtool) 2.4.2 +# Written by Gordon Matzigkeit , 1996 + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, +# 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, +# or obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +# Usage: $progname [OPTION]... [MODE-ARG]... +# +# Provide generalized library-building support services. +# +# --config show all configuration variables +# --debug enable verbose shell tracing +# -n, --dry-run display commands without modifying any files +# --features display basic configuration information and exit +# --mode=MODE use operation mode MODE +# --preserve-dup-deps don't remove duplicate dependency libraries +# --quiet, --silent don't print informational messages +# --no-quiet, --no-silent +# print informational messages (default) +# --no-warn don't display warning messages +# --tag=TAG use configuration variables from tag TAG +# -v, --verbose print more informational messages than default +# --no-verbose don't print the extra informational messages +# --version print version information +# -h, --help, --help-all print short, long, or detailed help message +# +# MODE must be one of the following: +# +# clean remove files from the build directory +# compile compile a source file into a libtool object +# execute automatically set library path, then run a program +# finish complete the installation of libtool libraries +# install install libraries or executables +# link create a library or an executable +# uninstall remove libraries from an installed directory +# +# MODE-ARGS vary depending on the MODE. When passed as first option, +# `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that. +# Try `$progname --help --mode=MODE' for a more detailed description of MODE. +# +# When reporting a bug, please describe a test case to reproduce it and +# include the following information: +# +# host-triplet: $host +# shell: $SHELL +# compiler: $LTCC +# compiler flags: $LTCFLAGS +# linker: $LD (gnu? $with_gnu_ld) +# $progname: (GNU libtool) 2.4.2 Debian-2.4.2-1ubuntu1 +# automake: $automake_version +# autoconf: $autoconf_version +# +# Report bugs to . +# GNU libtool home page: . +# General help using GNU software: . + +PROGRAM=libtool +PACKAGE=libtool +VERSION="2.4.2 Debian-2.4.2-1ubuntu1" +TIMESTAMP="" +package_revision=1.3337 + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + +# NLS nuisances: We save the old values to restore during execute mode. +lt_user_locale= +lt_safe_locale= +for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +do + eval "if test \"\${$lt_var+set}\" = set; then + save_$lt_var=\$$lt_var + $lt_var=C + export $lt_var + lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" + lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" + fi" +done +LC_ALL=C +LANGUAGE=C +export LANGUAGE LC_ALL + +$lt_unset CDPATH + + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath="$0" + + + +: ${CP="cp -f"} +test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'} +: ${MAKE="make"} +: ${MKDIR="mkdir"} +: ${MV="mv -f"} +: ${RM="rm -f"} +: ${SHELL="${CONFIG_SHELL-/bin/sh}"} +: ${Xsed="$SED -e 1s/^X//"} + +# Global variables: +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. + +exit_status=$EXIT_SUCCESS + +# Make sure IFS has a sensible default +lt_nl=' +' +IFS=" $lt_nl" + +dirname="s,/[^/]*$,," +basename="s,^.*/,," + +# func_dirname file append nondir_replacement +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +func_dirname () +{ + func_dirname_result=`$ECHO "${1}" | $SED "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi +} # func_dirname may be replaced by extended shell implementation + + +# func_basename file +func_basename () +{ + func_basename_result=`$ECHO "${1}" | $SED "$basename"` +} # func_basename may be replaced by extended shell implementation + + +# func_dirname_and_basename file append nondir_replacement +# perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# Implementation must be kept synchronized with func_dirname +# and func_basename. For efficiency, we do not delegate to +# those functions but instead duplicate the functionality here. +func_dirname_and_basename () +{ + # Extract subdirectory from the argument. + func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi + func_basename_result=`$ECHO "${1}" | $SED -e "$basename"` +} # func_dirname_and_basename may be replaced by extended shell implementation + + +# func_stripname prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# func_strip_suffix prefix name +func_stripname () +{ + case ${2} in + .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; + esac +} # func_stripname may be replaced by extended shell implementation + + +# These SED scripts presuppose an absolute path with a trailing slash. +pathcar='s,^/\([^/]*\).*$,\1,' +pathcdr='s,^/[^/]*,,' +removedotparts=':dotsl + s@/\./@/@g + t dotsl + s,/\.$,/,' +collapseslashes='s@/\{1,\}@/@g' +finalslash='s,/*$,/,' + +# func_normal_abspath PATH +# Remove doubled-up and trailing slashes, "." path components, +# and cancel out any ".." path components in PATH after making +# it an absolute path. +# value returned in "$func_normal_abspath_result" +func_normal_abspath () +{ + # Start from root dir and reassemble the path. + func_normal_abspath_result= + func_normal_abspath_tpath=$1 + func_normal_abspath_altnamespace= + case $func_normal_abspath_tpath in + "") + # Empty path, that just means $cwd. + func_stripname '' '/' "`pwd`" + func_normal_abspath_result=$func_stripname_result + return + ;; + # The next three entries are used to spot a run of precisely + # two leading slashes without using negated character classes; + # we take advantage of case's first-match behaviour. + ///*) + # Unusual form of absolute path, do nothing. + ;; + //*) + # Not necessarily an ordinary path; POSIX reserves leading '//' + # and for example Cygwin uses it to access remote file shares + # over CIFS/SMB, so we conserve a leading double slash if found. + func_normal_abspath_altnamespace=/ + ;; + /*) + # Absolute path, do nothing. + ;; + *) + # Relative path, prepend $cwd. + func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath + ;; + esac + # Cancel out all the simple stuff to save iterations. We also want + # the path to end with a slash for ease of parsing, so make sure + # there is one (and only one) here. + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"` + while :; do + # Processed it all yet? + if test "$func_normal_abspath_tpath" = / ; then + # If we ascended to the root using ".." the result may be empty now. + if test -z "$func_normal_abspath_result" ; then + func_normal_abspath_result=/ + fi + break + fi + func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$pathcar"` + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$pathcdr"` + # Figure out what to do with it + case $func_normal_abspath_tcomponent in + "") + # Trailing empty path component, ignore it. + ;; + ..) + # Parent dir; strip last assembled component from result. + func_dirname "$func_normal_abspath_result" + func_normal_abspath_result=$func_dirname_result + ;; + *) + # Actual path component, append it. + func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent + ;; + esac + done + # Restore leading double-slash if one was found on entry. + func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result +} + +# func_relative_path SRCDIR DSTDIR +# generates a relative path from SRCDIR to DSTDIR, with a trailing +# slash if non-empty, suitable for immediately appending a filename +# without needing to append a separator. +# value returned in "$func_relative_path_result" +func_relative_path () +{ + func_relative_path_result= + func_normal_abspath "$1" + func_relative_path_tlibdir=$func_normal_abspath_result + func_normal_abspath "$2" + func_relative_path_tbindir=$func_normal_abspath_result + + # Ascend the tree starting from libdir + while :; do + # check if we have found a prefix of bindir + case $func_relative_path_tbindir in + $func_relative_path_tlibdir) + # found an exact match + func_relative_path_tcancelled= + break + ;; + $func_relative_path_tlibdir*) + # found a matching prefix + func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" + func_relative_path_tcancelled=$func_stripname_result + if test -z "$func_relative_path_result"; then + func_relative_path_result=. + fi + break + ;; + *) + func_dirname $func_relative_path_tlibdir + func_relative_path_tlibdir=${func_dirname_result} + if test "x$func_relative_path_tlibdir" = x ; then + # Have to descend all the way to the root! + func_relative_path_result=../$func_relative_path_result + func_relative_path_tcancelled=$func_relative_path_tbindir + break + fi + func_relative_path_result=../$func_relative_path_result + ;; + esac + done + + # Now calculate path; take care to avoid doubling-up slashes. + func_stripname '' '/' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + func_stripname '/' '/' "$func_relative_path_tcancelled" + if test "x$func_stripname_result" != x ; then + func_relative_path_result=${func_relative_path_result}/${func_stripname_result} + fi + + # Normalisation. If bindir is libdir, return empty string, + # else relative path ending with a slash; either way, target + # file name can be directly appended. + if test ! -z "$func_relative_path_result"; then + func_stripname './' '' "$func_relative_path_result/" + func_relative_path_result=$func_stripname_result + fi +} + +# The name of this program: +func_dirname_and_basename "$progpath" +progname=$func_basename_result + +# Make sure we have an absolute path for reexecution: +case $progpath in + [\\/]*|[A-Za-z]:\\*) ;; + *[\\/]*) + progdir=$func_dirname_result + progdir=`cd "$progdir" && pwd` + progpath="$progdir/$progname" + ;; + *) + save_IFS="$IFS" + IFS=${PATH_SEPARATOR-:} + for progdir in $PATH; do + IFS="$save_IFS" + test -x "$progdir/$progname" && break + done + IFS="$save_IFS" + test -n "$progdir" || progdir=`pwd` + progpath="$progdir/$progname" + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed="${SED}"' -e 1s/^X//' +sed_quote_subst='s/\([`"$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution that turns a string into a regex matching for the +# string literally. +sed_make_literal_regex='s,[].[^$\\*\/],\\&,g' + +# Sed substitution that converts a w32 file name or path +# which contains forward slashes, into one that contains +# (escaped) backslashes. A very naive implementation. +lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + +# Re-`\' parameter expansions in output of double_quote_subst that were +# `\'-ed in input to the same. If an odd number of `\' preceded a '$' +# in input to double_quote_subst, that '$' was protected from expansion. +# Since each input `\' is now two `\'s, look for any number of runs of +# four `\'s followed by two `\'s and then a '$'. `\' that '$'. +bs='\\' +bs2='\\\\' +bs4='\\\\\\\\' +dollar='\$' +sed_double_backslash="\ + s/$bs4/&\\ +/g + s/^$bs2$dollar/$bs&/ + s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g + s/\n//g" + +# Standard options: +opt_dry_run=false +opt_help=false +opt_quiet=false +opt_verbose=false +opt_warning=: + +# func_echo arg... +# Echo program name prefixed message, along with the current mode +# name if it has been set yet. +func_echo () +{ + $ECHO "$progname: ${opt_mode+$opt_mode: }$*" +} + +# func_verbose arg... +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $opt_verbose && func_echo ${1+"$@"} + + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + +# func_error arg... +# Echo program name prefixed message to standard error. +func_error () +{ + $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 +} + +# func_warning arg... +# Echo program name prefixed warning message to standard error. +func_warning () +{ + $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 + + # bash bug again: + : +} + +# func_fatal_error arg... +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + func_error ${1+"$@"} + exit $EXIT_FAILURE +} + +# func_fatal_help arg... +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () +{ + func_error ${1+"$@"} + func_fatal_error "$help" +} +help="Try \`$progname --help' for more information." ## default + + +# func_grep expression filename +# Check whether EXPRESSION matches any line of FILENAME, without output. +func_grep () +{ + $GREP "$1" "$2" >/dev/null 2>&1 +} + + +# func_mkdir_p directory-path +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ + my_directory_path="$1" + my_dir_list= + + if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then + + # Protect directory names starting with `-' + case $my_directory_path in + -*) my_directory_path="./$my_directory_path" ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$my_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + my_dir_list="$my_directory_path:$my_dir_list" + + # If the last portion added has no slash in it, the list is done + case $my_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"` + done + my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'` + + save_mkdir_p_IFS="$IFS"; IFS=':' + for my_dir in $my_dir_list; do + IFS="$save_mkdir_p_IFS" + # mkdir can fail with a `File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$my_dir" 2>/dev/null || : + done + IFS="$save_mkdir_p_IFS" + + # Bail out if we (or some other process) failed to create a directory. + test -d "$my_directory_path" || \ + func_fatal_error "Failed to create \`$1'" + fi +} + + +# func_mktempdir [string] +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, STRING is the basename for that directory. +func_mktempdir () +{ + my_template="${TMPDIR-/tmp}/${1-$progname}" + + if test "$opt_dry_run" = ":"; then + # Return a directory name, but don't create it in dry-run mode + my_tmpdir="${my_template}-$$" + else + + # If mktemp works, use that first and foremost + my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` + + if test ! -d "$my_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + my_tmpdir="${my_template}-${RANDOM-0}$$" + + save_mktempdir_umask=`umask` + umask 0077 + $MKDIR "$my_tmpdir" + umask $save_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$my_tmpdir" || \ + func_fatal_error "cannot create temporary directory \`$my_tmpdir'" + fi + + $ECHO "$my_tmpdir" +} + + +# func_quote_for_eval arg +# Aesthetically quote ARG to be evaled later. +# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT +# is double-quoted, suitable for a subsequent eval, whereas +# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters +# which are still active within double quotes backslashified. +func_quote_for_eval () +{ + case $1 in + *[\\\`\"\$]*) + func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;; + *) + func_quote_for_eval_unquoted_result="$1" ;; + esac + + case $func_quote_for_eval_unquoted_result in + # Double-quote args containing shell metacharacters to delay + # word splitting, command substitution and and variable + # expansion for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" + ;; + *) + func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" + esac +} + + +# func_quote_for_expand arg +# Aesthetically quote ARG to be evaled later; same as above, +# but do not quote variable references. +func_quote_for_expand () +{ + case $1 in + *[\\\`\"]*) + my_arg=`$ECHO "$1" | $SED \ + -e "$double_quote_subst" -e "$sed_double_backslash"` ;; + *) + my_arg="$1" ;; + esac + + case $my_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting and command substitution for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + my_arg="\"$my_arg\"" + ;; + esac + + func_quote_for_expand_result="$my_arg" +} + + +# func_show_eval cmd [fail_exp] +# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + my_cmd="$1" + my_fail_exp="${2-:}" + + ${opt_silent-false} || { + func_quote_for_expand "$my_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + if ${opt_dry_run-false}; then :; else + eval "$my_cmd" + my_status=$? + if test "$my_status" -eq 0; then :; else + eval "(exit $my_status); $my_fail_exp" + fi + fi +} + + +# func_show_eval_locale cmd [fail_exp] +# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () +{ + my_cmd="$1" + my_fail_exp="${2-:}" + + ${opt_silent-false} || { + func_quote_for_expand "$my_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + if ${opt_dry_run-false}; then :; else + eval "$lt_user_locale + $my_cmd" + my_status=$? + eval "$lt_safe_locale" + if test "$my_status" -eq 0; then :; else + eval "(exit $my_status); $my_fail_exp" + fi + fi +} + +# func_tr_sh +# Turn $1 into a string suitable for a shell variable name. +# Result is stored in $func_tr_sh_result. All characters +# not in the set a-zA-Z0-9_ are replaced with '_'. Further, +# if $1 begins with a digit, a '_' is prepended as well. +func_tr_sh () +{ + case $1 in + [0-9]* | *[!a-zA-Z0-9_]*) + func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'` + ;; + * ) + func_tr_sh_result=$1 + ;; + esac +} + + +# func_version +# Echo version message to standard output and exit. +func_version () +{ + $opt_debug + + $SED -n '/(C)/!b go + :more + /\./!{ + N + s/\n# / / + b more + } + :go + /^# '$PROGRAM' (GNU /,/# warranty; / { + s/^# // + s/^# *$// + s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ + p + }' < "$progpath" + exit $? +} + +# func_usage +# Echo short help message to standard output and exit. +func_usage () +{ + $opt_debug + + $SED -n '/^# Usage:/,/^# *.*--help/ { + s/^# // + s/^# *$// + s/\$progname/'$progname'/ + p + }' < "$progpath" + echo + $ECHO "run \`$progname --help | more' for full usage" + exit $? +} + +# func_help [NOEXIT] +# Echo long help message to standard output and exit, +# unless 'noexit' is passed as argument. +func_help () +{ + $opt_debug + + $SED -n '/^# Usage:/,/# Report bugs to/ { + :print + s/^# // + s/^# *$// + s*\$progname*'$progname'* + s*\$host*'"$host"'* + s*\$SHELL*'"$SHELL"'* + s*\$LTCC*'"$LTCC"'* + s*\$LTCFLAGS*'"$LTCFLAGS"'* + s*\$LD*'"$LD"'* + s/\$with_gnu_ld/'"$with_gnu_ld"'/ + s/\$automake_version/'"`(${AUTOMAKE-automake} --version) 2>/dev/null |$SED 1q`"'/ + s/\$autoconf_version/'"`(${AUTOCONF-autoconf} --version) 2>/dev/null |$SED 1q`"'/ + p + d + } + /^# .* home page:/b print + /^# General help using/b print + ' < "$progpath" + ret=$? + if test -z "$1"; then + exit $ret + fi +} + +# func_missing_arg argname +# Echo program name prefixed message to standard error and set global +# exit_cmd. +func_missing_arg () +{ + $opt_debug + + func_error "missing argument for $1." + exit_cmd=exit +} + + +# func_split_short_opt shortopt +# Set func_split_short_opt_name and func_split_short_opt_arg shell +# variables after splitting SHORTOPT after the 2nd character. +func_split_short_opt () +{ + my_sed_short_opt='1s/^\(..\).*$/\1/;q' + my_sed_short_rest='1s/^..\(.*\)$/\1/;q' + + func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"` + func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"` +} # func_split_short_opt may be replaced by extended shell implementation + + +# func_split_long_opt longopt +# Set func_split_long_opt_name and func_split_long_opt_arg shell +# variables after splitting LONGOPT at the `=' sign. +func_split_long_opt () +{ + my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q' + my_sed_long_arg='1s/^--[^=]*=//' + + func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"` + func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"` +} # func_split_long_opt may be replaced by extended shell implementation + +exit_cmd=: + + + + + +magic="%%%MAGIC variable%%%" +magic_exe="%%%MAGIC EXE variable%%%" + +# Global variables. +nonopt= +preserve_args= +lo2o="s/\\.lo\$/.${objext}/" +o2lo="s/\\.${objext}\$/.lo/" +extracted_archives= +extracted_serial=0 + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + +# func_append var value +# Append VALUE to the end of shell variable VAR. +func_append () +{ + eval "${1}=\$${1}\${2}" +} # func_append may be replaced by extended shell implementation + +# func_append_quoted var value +# Quote VALUE and append to the end of shell variable VAR, separated +# by a space. +func_append_quoted () +{ + func_quote_for_eval "${2}" + eval "${1}=\$${1}\\ \$func_quote_for_eval_result" +} # func_append_quoted may be replaced by extended shell implementation + + +# func_arith arithmetic-term... +func_arith () +{ + func_arith_result=`expr "${@}"` +} # func_arith may be replaced by extended shell implementation + + +# func_len string +# STRING may not start with a hyphen. +func_len () +{ + func_len_result=`expr "${1}" : ".*" 2>/dev/null || echo $max_cmd_len` +} # func_len may be replaced by extended shell implementation + + +# func_lo2o object +func_lo2o () +{ + func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"` +} # func_lo2o may be replaced by extended shell implementation + + +# func_xform libobj-or-source +func_xform () +{ + func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'` +} # func_xform may be replaced by extended shell implementation + + +# func_fatal_configuration arg... +# Echo program name prefixed message to standard error, followed by +# a configuration failure hint, and exit. +func_fatal_configuration () +{ + func_error ${1+"$@"} + func_error "See the $PACKAGE documentation for more information." + func_fatal_error "Fatal configuration error." +} + + +# func_config +# Display the configuration for all the tags in this script. +func_config () +{ + re_begincf='^# ### BEGIN LIBTOOL' + re_endcf='^# ### END LIBTOOL' + + # Default configuration. + $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" + + # Now print the configurations for the tags. + for tagname in $taglist; do + $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" + done + + exit $? +} + +# func_features +# Display the features supported by this script. +func_features () +{ + echo "host: $host" + if test "$build_libtool_libs" = yes; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test "$build_old_libs" = yes; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + + exit $? +} + +# func_enable_tag tagname +# Verify that TAGNAME is valid, and either flag an error and exit, or +# enable the TAGNAME tag. We also add TAGNAME to the global $taglist +# variable here. +func_enable_tag () +{ + # Global variable: + tagname="$1" + + re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" + re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" + sed_extractcf="/$re_begincf/,/$re_endcf/p" + + # Validate tagname. + case $tagname in + *[!-_A-Za-z0-9,/]*) + func_fatal_error "invalid tag name: $tagname" + ;; + esac + + # Don't test for the "default" C tag, as we know it's + # there but not specially marked. + case $tagname in + CC) ;; + *) + if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then + taglist="$taglist $tagname" + + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac +} + +# func_check_version_match +# Ensure that we are using m4 macros, and libtool script from the same +# release of libtool. +func_check_version_match () +{ + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from an older release. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + fi + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, +$progname: but the definition of this LT_INIT comes from revision $macro_revision. +$progname: You should recreate aclocal.m4 with macros from revision $package_revision +$progname: of $PACKAGE $VERSION and run autoconf again. +_LT_EOF + fi + + exit $EXIT_MISMATCH + fi +} + + +# Shorthand for --mode=foo, only valid as the first argument +case $1 in +clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; +compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; +execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; +finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; +install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; +link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; +uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; +esac + + + +# Option defaults: +opt_debug=: +opt_dry_run=false +opt_config=false +opt_preserve_dup_deps=false +opt_features=false +opt_finish=false +opt_help=false +opt_help_all=false +opt_silent=: +opt_warning=: +opt_verbose=: +opt_silent=false +opt_verbose=false + + +# Parse options once, thoroughly. This comes as soon as possible in the +# script to make things like `--version' happen as quickly as we can. +{ + # this just eases exit handling + while test $# -gt 0; do + opt="$1" + shift + case $opt in + --debug|-x) opt_debug='set -x' + func_echo "enabling shell trace mode" + $opt_debug + ;; + --dry-run|--dryrun|-n) + opt_dry_run=: + ;; + --config) + opt_config=: +func_config + ;; + --dlopen|-dlopen) + optarg="$1" + opt_dlopen="${opt_dlopen+$opt_dlopen +}$optarg" + shift + ;; + --preserve-dup-deps) + opt_preserve_dup_deps=: + ;; + --features) + opt_features=: +func_features + ;; + --finish) + opt_finish=: +set dummy --mode finish ${1+"$@"}; shift + ;; + --help) + opt_help=: + ;; + --help-all) + opt_help_all=: +opt_help=': help-all' + ;; + --mode) + test $# = 0 && func_missing_arg $opt && break + optarg="$1" + opt_mode="$optarg" +case $optarg in + # Valid mode arguments: + clean|compile|execute|finish|install|link|relink|uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $opt" + exit_cmd=exit + break + ;; +esac + shift + ;; + --no-silent|--no-quiet) + opt_silent=false +func_append preserve_args " $opt" + ;; + --no-warning|--no-warn) + opt_warning=false +func_append preserve_args " $opt" + ;; + --no-verbose) + opt_verbose=false +func_append preserve_args " $opt" + ;; + --silent|--quiet) + opt_silent=: +func_append preserve_args " $opt" + opt_verbose=false + ;; + --verbose|-v) + opt_verbose=: +func_append preserve_args " $opt" +opt_silent=false + ;; + --tag) + test $# = 0 && func_missing_arg $opt && break + optarg="$1" + opt_tag="$optarg" +func_append preserve_args " $opt $optarg" +func_enable_tag "$optarg" + shift + ;; + + -\?|-h) func_usage ;; + --help) func_help ;; + --version) func_version ;; + + # Separate optargs to long options: + --*=*) + func_split_long_opt "$opt" + set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"} + shift + ;; + + # Separate non-argument short options: + -\?*|-h*|-n*|-v*) + func_split_short_opt "$opt" + set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + --) break ;; + -*) func_fatal_help "unrecognized option \`$opt'" ;; + *) set dummy "$opt" ${1+"$@"}; shift; break ;; + esac + done + + # Validate options: + + # save first non-option argument + if test "$#" -gt 0; then + nonopt="$opt" + shift + fi + + # preserve --debug + test "$opt_debug" = : || func_append preserve_args " --debug" + + case $host in + *cygwin* | *mingw* | *pw32* | *cegcc*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps + ;; + esac + + $opt_help || { + # Sanity checks first: + func_check_version_match + + if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then + func_fatal_configuration "not configured to build any kind of library" + fi + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$opt_dlopen" && test "$opt_mode" != execute; then + func_error "unrecognized option \`-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$progname --help --mode=$opt_mode' for more information." + } + + + # Bail if the options were screwed + $exit_cmd $EXIT_FAILURE +} + + + + +## ----------- ## +## Main. ## +## ----------- ## + +# func_lalib_p file +# True iff FILE is a libtool `.la' library or `.lo' object file. +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_lalib_p () +{ + test -f "$1" && + $SED -e 4q "$1" 2>/dev/null \ + | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + +# func_lalib_unsafe_p file +# True iff FILE is a libtool `.la' library or `.lo' object file. +# This function implements the same check as func_lalib_p without +# resorting to external programs. To this end, it redirects stdin and +# closes it afterwards, without saving the original file descriptor. +# As a safety measure, use it only where a negative result would be +# fatal anyway. Works if `file' does not exist. +func_lalib_unsafe_p () +{ + lalib_p=no + if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then + for lalib_p_l in 1 2 3 4 + do + read lalib_p_line + case "$lalib_p_line" in + \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; + esac + done + exec 0<&5 5<&- + fi + test "$lalib_p" = yes +} + +# func_ltwrapper_script_p file +# True iff FILE is a libtool wrapper script +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_script_p () +{ + func_lalib_p "$1" +} + +# func_ltwrapper_executable_p file +# True iff FILE is a libtool wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_executable_p () +{ + func_ltwrapper_exec_suffix= + case $1 in + *.exe) ;; + *) func_ltwrapper_exec_suffix=.exe ;; + esac + $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 +} + +# func_ltwrapper_scriptname file +# Assumes file is an ltwrapper_executable +# uses $file to determine the appropriate filename for a +# temporary ltwrapper_script. +func_ltwrapper_scriptname () +{ + func_dirname_and_basename "$1" "" "." + func_stripname '' '.exe' "$func_basename_result" + func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" +} + +# func_ltwrapper_p file +# True iff FILE is a libtool wrapper script or wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_p () +{ + func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" +} + + +# func_execute_cmds commands fail_cmd +# Execute tilde-delimited COMMANDS. +# If FAIL_CMD is given, eval that upon failure. +# FAIL_CMD may read-access the current command in variable CMD! +func_execute_cmds () +{ + $opt_debug + save_ifs=$IFS; IFS='~' + for cmd in $1; do + IFS=$save_ifs + eval cmd=\"$cmd\" + func_show_eval "$cmd" "${2-:}" + done + IFS=$save_ifs +} + + +# func_source file +# Source FILE, adding directory component if necessary. +# Note that it is not necessary on cygwin/mingw to append a dot to +# FILE even if both FILE and FILE.exe exist: automatic-append-.exe +# behavior happens only for exec(3), not for open(2)! Also, sourcing +# `FILE.' does not work on cygwin managed mounts. +func_source () +{ + $opt_debug + case $1 in + */* | *\\*) . "$1" ;; + *) . "./$1" ;; + esac +} + + +# func_resolve_sysroot PATH +# Replace a leading = in PATH with a sysroot. Store the result into +# func_resolve_sysroot_result +func_resolve_sysroot () +{ + func_resolve_sysroot_result=$1 + case $func_resolve_sysroot_result in + =*) + func_stripname '=' '' "$func_resolve_sysroot_result" + func_resolve_sysroot_result=$lt_sysroot$func_stripname_result + ;; + esac +} + +# func_replace_sysroot PATH +# If PATH begins with the sysroot, replace it with = and +# store the result into func_replace_sysroot_result. +func_replace_sysroot () +{ + case "$lt_sysroot:$1" in + ?*:"$lt_sysroot"*) + func_stripname "$lt_sysroot" '' "$1" + func_replace_sysroot_result="=$func_stripname_result" + ;; + *) + # Including no sysroot. + func_replace_sysroot_result=$1 + ;; + esac +} + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + $opt_debug + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case "$@ " in + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + func_echo "unable to infer tagged configuration" + func_fatal_error "specify a tag with \`--tag'" +# else +# func_verbose "using $tagname tagged configuration" + fi + ;; + esac + fi +} + + + +# func_write_libtool_object output_name pic_name nonpic_name +# Create a libtool object file (analogous to a ".la" file), +# but don't create it if we're doing a dry run. +func_write_libtool_object () +{ + write_libobj=${1} + if test "$build_libtool_libs" = yes; then + write_lobj=\'${2}\' + else + write_lobj=none + fi + + if test "$build_old_libs" = yes; then + write_oldobj=\'${3}\' + else + write_oldobj=none + fi + + $opt_dry_run || { + cat >${write_libobj}T </dev/null` + if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then + func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | + $SED -e "$lt_sed_naive_backslashify"` + else + func_convert_core_file_wine_to_w32_result= + fi + fi +} +# end: func_convert_core_file_wine_to_w32 + + +# func_convert_core_path_wine_to_w32 ARG +# Helper function used by path conversion functions when $build is *nix, and +# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly +# configured wine environment available, with the winepath program in $build's +# $PATH. Assumes ARG has no leading or trailing path separator characters. +# +# ARG is path to be converted from $build format to win32. +# Result is available in $func_convert_core_path_wine_to_w32_result. +# Unconvertible file (directory) names in ARG are skipped; if no directory names +# are convertible, then the result may be empty. +func_convert_core_path_wine_to_w32 () +{ + $opt_debug + # unfortunately, winepath doesn't convert paths, only file names + func_convert_core_path_wine_to_w32_result="" + if test -n "$1"; then + oldIFS=$IFS + IFS=: + for func_convert_core_path_wine_to_w32_f in $1; do + IFS=$oldIFS + func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" + if test -n "$func_convert_core_file_wine_to_w32_result" ; then + if test -z "$func_convert_core_path_wine_to_w32_result"; then + func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result" + else + func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" + fi + fi + done + IFS=$oldIFS + fi +} +# end: func_convert_core_path_wine_to_w32 + + +# func_cygpath ARGS... +# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when +# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) +# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or +# (2), returns the Cygwin file name or path in func_cygpath_result (input +# file name or path is assumed to be in w32 format, as previously converted +# from $build's *nix or MSYS format). In case (3), returns the w32 file name +# or path in func_cygpath_result (input file name or path is assumed to be in +# Cygwin format). Returns an empty string on error. +# +# ARGS are passed to cygpath, with the last one being the file name or path to +# be converted. +# +# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH +# environment variable; do not put it in $PATH. +func_cygpath () +{ + $opt_debug + if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then + func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` + if test "$?" -ne 0; then + # on failure, ensure result is empty + func_cygpath_result= + fi + else + func_cygpath_result= + func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'" + fi +} +#end: func_cygpath + + +# func_convert_core_msys_to_w32 ARG +# Convert file name or path ARG from MSYS format to w32 format. Return +# result in func_convert_core_msys_to_w32_result. +func_convert_core_msys_to_w32 () +{ + $opt_debug + # awkward: cmd appends spaces to result + func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | + $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"` +} +#end: func_convert_core_msys_to_w32 + + +# func_convert_file_check ARG1 ARG2 +# Verify that ARG1 (a file name in $build format) was converted to $host +# format in ARG2. Otherwise, emit an error message, but continue (resetting +# func_to_host_file_result to ARG1). +func_convert_file_check () +{ + $opt_debug + if test -z "$2" && test -n "$1" ; then + func_error "Could not determine host file name corresponding to" + func_error " \`$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback: + func_to_host_file_result="$1" + fi +} +# end func_convert_file_check + + +# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH +# Verify that FROM_PATH (a path in $build format) was converted to $host +# format in TO_PATH. Otherwise, emit an error message, but continue, resetting +# func_to_host_file_result to a simplistic fallback value (see below). +func_convert_path_check () +{ + $opt_debug + if test -z "$4" && test -n "$3"; then + func_error "Could not determine the host path corresponding to" + func_error " \`$3'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback. This is a deliberately simplistic "conversion" and + # should not be "improved". See libtool.info. + if test "x$1" != "x$2"; then + lt_replace_pathsep_chars="s|$1|$2|g" + func_to_host_path_result=`echo "$3" | + $SED -e "$lt_replace_pathsep_chars"` + else + func_to_host_path_result="$3" + fi + fi +} +# end func_convert_path_check + + +# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG +# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT +# and appending REPL if ORIG matches BACKPAT. +func_convert_path_front_back_pathsep () +{ + $opt_debug + case $4 in + $1 ) func_to_host_path_result="$3$func_to_host_path_result" + ;; + esac + case $4 in + $2 ) func_append func_to_host_path_result "$3" + ;; + esac +} +# end func_convert_path_front_back_pathsep + + +################################################## +# $build to $host FILE NAME CONVERSION FUNCTIONS # +################################################## +# invoked via `$to_host_file_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# Result will be available in $func_to_host_file_result. + + +# func_to_host_file ARG +# Converts the file name ARG from $build format to $host format. Return result +# in func_to_host_file_result. +func_to_host_file () +{ + $opt_debug + $to_host_file_cmd "$1" +} +# end func_to_host_file + + +# func_to_tool_file ARG LAZY +# converts the file name ARG from $build format to toolchain format. Return +# result in func_to_tool_file_result. If the conversion in use is listed +# in (the comma separated) LAZY, no conversion takes place. +func_to_tool_file () +{ + $opt_debug + case ,$2, in + *,"$to_tool_file_cmd",*) + func_to_tool_file_result=$1 + ;; + *) + $to_tool_file_cmd "$1" + func_to_tool_file_result=$func_to_host_file_result + ;; + esac +} +# end func_to_tool_file + + +# func_convert_file_noop ARG +# Copy ARG to func_to_host_file_result. +func_convert_file_noop () +{ + func_to_host_file_result="$1" +} +# end func_convert_file_noop + + +# func_convert_file_msys_to_w32 ARG +# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_file_result. +func_convert_file_msys_to_w32 () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_to_host_file_result="$func_convert_core_msys_to_w32_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_w32 + + +# func_convert_file_cygwin_to_w32 ARG +# Convert file name ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_file_cygwin_to_w32 () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + # because $build is cygwin, we call "the" cygpath in $PATH; no need to use + # LT_CYGPATH in this case. + func_to_host_file_result=`cygpath -m "$1"` + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_cygwin_to_w32 + + +# func_convert_file_nix_to_w32 ARG +# Convert file name ARG from *nix to w32 format. Requires a wine environment +# and a working winepath. Returns result in func_to_host_file_result. +func_convert_file_nix_to_w32 () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + func_convert_core_file_wine_to_w32 "$1" + func_to_host_file_result="$func_convert_core_file_wine_to_w32_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_w32 + + +# func_convert_file_msys_to_cygwin ARG +# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_file_msys_to_cygwin () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_cygpath -u "$func_convert_core_msys_to_w32_result" + func_to_host_file_result="$func_cygpath_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_cygwin + + +# func_convert_file_nix_to_cygwin ARG +# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed +# in a wine environment, working winepath, and LT_CYGPATH set. Returns result +# in func_to_host_file_result. +func_convert_file_nix_to_cygwin () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. + func_convert_core_file_wine_to_w32 "$1" + func_cygpath -u "$func_convert_core_file_wine_to_w32_result" + func_to_host_file_result="$func_cygpath_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_cygwin + + +############################################# +# $build to $host PATH CONVERSION FUNCTIONS # +############################################# +# invoked via `$to_host_path_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# The result will be available in $func_to_host_path_result. +# +# Path separators are also converted from $build format to $host format. If +# ARG begins or ends with a path separator character, it is preserved (but +# converted to $host format) on output. +# +# All path conversion functions are named using the following convention: +# file name conversion function : func_convert_file_X_to_Y () +# path conversion function : func_convert_path_X_to_Y () +# where, for any given $build/$host combination the 'X_to_Y' value is the +# same. If conversion functions are added for new $build/$host combinations, +# the two new functions must follow this pattern, or func_init_to_host_path_cmd +# will break. + + +# func_init_to_host_path_cmd +# Ensures that function "pointer" variable $to_host_path_cmd is set to the +# appropriate value, based on the value of $to_host_file_cmd. +to_host_path_cmd= +func_init_to_host_path_cmd () +{ + $opt_debug + if test -z "$to_host_path_cmd"; then + func_stripname 'func_convert_file_' '' "$to_host_file_cmd" + to_host_path_cmd="func_convert_path_${func_stripname_result}" + fi +} + + +# func_to_host_path ARG +# Converts the path ARG from $build format to $host format. Return result +# in func_to_host_path_result. +func_to_host_path () +{ + $opt_debug + func_init_to_host_path_cmd + $to_host_path_cmd "$1" +} +# end func_to_host_path + + +# func_convert_path_noop ARG +# Copy ARG to func_to_host_path_result. +func_convert_path_noop () +{ + func_to_host_path_result="$1" +} +# end func_convert_path_noop + + +# func_convert_path_msys_to_w32 ARG +# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_path_result. +func_convert_path_msys_to_w32 () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # Remove leading and trailing path separator characters from ARG. MSYS + # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; + # and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result="$func_convert_core_msys_to_w32_result" + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_msys_to_w32 + + +# func_convert_path_cygwin_to_w32 ARG +# Convert path ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_path_cygwin_to_w32 () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_cygwin_to_w32 + + +# func_convert_path_nix_to_w32 ARG +# Convert path ARG from *nix to w32 format. Requires a wine environment and +# a working winepath. Returns result in func_to_host_file_result. +func_convert_path_nix_to_w32 () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result="$func_convert_core_path_wine_to_w32_result" + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_nix_to_w32 + + +# func_convert_path_msys_to_cygwin ARG +# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_path_msys_to_cygwin () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_msys_to_w32_result" + func_to_host_path_result="$func_cygpath_result" + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_msys_to_cygwin + + +# func_convert_path_nix_to_cygwin ARG +# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a +# a wine environment, working winepath, and LT_CYGPATH set. Returns result in +# func_to_host_file_result. +func_convert_path_nix_to_cygwin () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # Remove leading and trailing path separator characters from + # ARG. msys behavior is inconsistent here, cygpath turns them + # into '.;' and ';.', and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" + func_to_host_path_result="$func_cygpath_result" + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_nix_to_cygwin + + +# func_mode_compile arg... +func_mode_compile () +{ + $opt_debug + # Get the compilation command and the source file. + base_compile= + srcfile="$nonopt" # always keep a non-empty value in "srcfile" + suppress_opt=yes + suppress_output= + arg_mode=normal + libobj= + later= + pie_flag= + + for arg + do + case $arg_mode in + arg ) + # do not "continue". Instead, add this to base_compile + lastarg="$arg" + arg_mode=normal + ;; + + target ) + libobj="$arg" + arg_mode=normal + continue + ;; + + normal ) + # Accept any command-line options. + case $arg in + -o) + test -n "$libobj" && \ + func_fatal_error "you cannot specify \`-o' more than once" + arg_mode=target + continue + ;; + + -pie | -fpie | -fPIE) + func_append pie_flag " $arg" + continue + ;; + + -shared | -static | -prefer-pic | -prefer-non-pic) + func_append later " $arg" + continue + ;; + + -no-suppress) + suppress_opt=no + continue + ;; + + -Xcompiler) + arg_mode=arg # the next one goes into the "base_compile" arg list + continue # The current "srcfile" will either be retained or + ;; # replaced later. I would guess that would be a bug. + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + lastarg= + save_ifs="$IFS"; IFS=',' + for arg in $args; do + IFS="$save_ifs" + func_append_quoted lastarg "$arg" + done + IFS="$save_ifs" + func_stripname ' ' '' "$lastarg" + lastarg=$func_stripname_result + + # Add the arguments to base_compile. + func_append base_compile " $lastarg" + continue + ;; + + *) + # Accept the current argument as the source file. + # The previous "srcfile" becomes the current argument. + # + lastarg="$srcfile" + srcfile="$arg" + ;; + esac # case $arg + ;; + esac # case $arg_mode + + # Aesthetically quote the previous argument. + func_append_quoted base_compile "$lastarg" + done # for arg + + case $arg_mode in + arg) + func_fatal_error "you must specify an argument for -Xcompile" + ;; + target) + func_fatal_error "you must specify a target with \`-o'" + ;; + *) + # Get the name of the library object. + test -z "$libobj" && { + func_basename "$srcfile" + libobj="$func_basename_result" + } + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + case $libobj in + *.[cCFSifmso] | \ + *.ada | *.adb | *.ads | *.asm | \ + *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ + *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) + func_xform "$libobj" + libobj=$func_xform_result + ;; + esac + + case $libobj in + *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; + *) + func_fatal_error "cannot determine name of library object from \`$libobj'" + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -shared) + test "$build_libtool_libs" != yes && \ + func_fatal_configuration "can not build a shared library" + build_old_libs=no + continue + ;; + + -static) + build_libtool_libs=no + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + func_quote_for_eval "$libobj" + test "X$libobj" != "X$func_quote_for_eval_result" \ + && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && func_warning "libobj name \`$libobj' may not contain shell special characters." + func_dirname_and_basename "$obj" "/" "" + objname="$func_basename_result" + xdir="$func_dirname_result" + lobj=${xdir}$objdir/$objname + + test -z "$base_compile" && \ + func_fatal_help "you must specify a compilation command" + + # Delete any leftover library objects. + if test "$build_old_libs" = yes; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2* | cegcc*) + pic_mode=default + ;; + esac + if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test "$compiler_c_o" = no; then + output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext} + lockfile="$output_obj.lock" + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test "$need_locks" = yes; then + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + elif test "$need_locks" = warn; then + if test -f "$lockfile"; then + $ECHO "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + func_append removelist " $output_obj" + $ECHO "$srcfile" > "$lockfile" + fi + + $opt_dry_run || $RM $removelist + func_append removelist " $lockfile" + trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 + + func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 + srcfile=$func_to_tool_file_result + func_quote_for_eval "$srcfile" + qsrcfile=$func_quote_for_eval_result + + # Only build a PIC object if we are building libtool libraries. + if test "$build_libtool_libs" = yes; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test "$pic_mode" != no; then + command="$base_compile $qsrcfile $pic_flag" + else + # Don't build PIC code + command="$base_compile $qsrcfile" + fi + + func_mkdir_p "$xdir$objdir" + + if test -z "$output_obj"; then + # Place PIC objects in $objdir + func_append command " -o $lobj" + fi + + func_show_eval_locale "$command" \ + 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' + + if test "$need_locks" = warn && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + func_show_eval '$MV "$output_obj" "$lobj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + + # Allow error messages only from the first compilation. + if test "$suppress_opt" = yes; then + suppress_output=' >/dev/null 2>&1' + fi + fi + + # Only build a position-dependent object if we build old libraries. + if test "$build_old_libs" = yes; then + if test "$pic_mode" != yes; then + # Don't build PIC code + command="$base_compile $qsrcfile$pie_flag" + else + command="$base_compile $qsrcfile $pic_flag" + fi + if test "$compiler_c_o" = yes; then + func_append command " -o $obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + func_append command "$suppress_output" + func_show_eval_locale "$command" \ + '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' + + if test "$need_locks" = warn && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + func_show_eval '$MV "$output_obj" "$obj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + fi + + $opt_dry_run || { + func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" + + # Unlock the critical section if it was locked + if test "$need_locks" != no; then + removelist=$lockfile + $RM "$lockfile" + fi + } + + exit $EXIT_SUCCESS +} + +$opt_help || { + test "$opt_mode" = compile && func_mode_compile ${1+"$@"} +} + +func_mode_help () +{ + # We need to display help for each of the modes. + case $opt_mode in + "") + # Generic help is extracted from the usage comments + # at the start of this file. + func_help + ;; + + clean) + $ECHO \ +"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + + compile) + $ECHO \ +"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -no-suppress do not suppress compiler output for multiple passes + -prefer-pic try to build PIC objects only + -prefer-non-pic try to build non-PIC objects only + -shared do not build a \`.o' file suitable for static linking + -static only build a \`.o' file suitable for static linking + -Wc,FLAG pass FLAG directly to the compiler + +COMPILE-COMMAND is a command to be used in creating a \`standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix \`.c' with the +library object suffix, \`.lo'." + ;; + + execute) + $ECHO \ +"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to \`-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + + finish) + $ECHO \ +"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the \`--dry-run' option if you just want to see what would be executed." + ;; + + install) + $ECHO \ +"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the \`install' or \`cp' program. + +The following components of INSTALL-COMMAND are treated specially: + + -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + + link) + $ECHO \ +"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -bindir BINDIR specify path to binaries directory (for systems where + libraries must be found in the PATH setting at runtime) + -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE Use a list of object files found in FILE to specify objects + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -shared only do dynamic linking of libtool libraries + -shrext SUFFIX override the standard shared library file extension + -static do not do any dynamic linking of uninstalled libtool libraries + -static-libtool-libs + do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + -weak LIBNAME declare that the target provides the LIBNAME interface + -Wc,FLAG + -Xcompiler FLAG pass linker-specific FLAG directly to the compiler + -Wl,FLAG + -Xlinker FLAG pass linker-specific FLAG directly to the linker + -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) + +All other options (arguments beginning with \`-') are ignored. + +Every other argument is treated as a filename. Files ending in \`.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in \`.la', then a libtool library is created, +only library objects (\`.lo' files) may be specified, and \`-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created +using \`ar' and \`ranlib', or on Windows using \`lib'. + +If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file +is created, otherwise an executable program is created." + ;; + + uninstall) + $ECHO \ +"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + + *) + func_fatal_help "invalid operation mode \`$opt_mode'" + ;; + esac + + echo + $ECHO "Try \`$progname --help' for more information about other modes." +} + +# Now that we've collected a possible --mode arg, show help if necessary +if $opt_help; then + if test "$opt_help" = :; then + func_mode_help + else + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + func_mode_help + done + } | sed -n '1p; 2,$s/^Usage:/ or: /p' + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + echo + func_mode_help + done + } | + sed '1d + /^When reporting/,/^Report/{ + H + d + } + $x + /information about other modes/d + /more detailed .*MODE/d + s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' + fi + exit $? +fi + + +# func_mode_execute arg... +func_mode_execute () +{ + $opt_debug + # The first argument is the command name. + cmd="$nonopt" + test -z "$cmd" && \ + func_fatal_help "you must specify a COMMAND" + + # Handle -dlopen flags immediately. + for file in $opt_dlopen; do + test -f "$file" \ + || func_fatal_help "\`$file' is not a file" + + dir= + case $file in + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "\`$lib' is not a valid libtool archive" + + # Read the libtool library. + dlname= + library_names= + func_source "$file" + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && \ + func_warning "\`$file' was not linked with \`-export-dynamic'" + continue + fi + + func_dirname "$file" "" "." + dir="$func_dirname_result" + + if test -f "$dir/$objdir/$dlname"; then + func_append dir "/$objdir" + else + if test ! -f "$dir/$dlname"; then + func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" + fi + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + func_dirname "$file" "" "." + dir="$func_dirname_result" + ;; + + *) + func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir="$absdir" + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic="$magic" + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -* | *.la | *.lo ) ;; + *) + # Do a test to see if this is really a libtool program. + if func_ltwrapper_script_p "$file"; then + func_source "$file" + # Transform arg to wrapped name. + file="$progdir/$program" + elif func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + func_source "$func_ltwrapper_scriptname_result" + # Transform arg to wrapped name. + file="$progdir/$program" + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + func_append_quoted args "$file" + done + + if test "X$opt_dry_run" = Xfalse; then + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + do + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + else + $lt_unset $lt_var + fi" + done + + # Now prepare to actually exec the command. + exec_cmd="\$cmd$args" + else + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + echo "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS + fi +} + +test "$opt_mode" = execute && func_mode_execute ${1+"$@"} + + +# func_mode_finish arg... +func_mode_finish () +{ + $opt_debug + libs= + libdirs= + admincmds= + + for opt in "$nonopt" ${1+"$@"} + do + if test -d "$opt"; then + func_append libdirs " $opt" + + elif test -f "$opt"; then + if func_lalib_unsafe_p "$opt"; then + func_append libs " $opt" + else + func_warning "\`$opt' is not a valid libtool archive" + fi + + else + func_fatal_error "invalid argument \`$opt'" + fi + done + + if test -n "$libs"; then + if test -n "$lt_sysroot"; then + sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` + sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" + else + sysroot_cmd= + fi + + # Remove sysroot references + if $opt_dry_run; then + for lib in $libs; do + echo "removing references to $lt_sysroot and \`=' prefixes from $lib" + done + else + tmpdir=`func_mktempdir` + for lib in $libs; do + sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ + > $tmpdir/tmp-la + mv -f $tmpdir/tmp-la $lib + done + ${RM}r "$tmpdir" + fi + fi + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + func_execute_cmds "$finish_cmds" 'admincmds="$admincmds +'"$cmd"'"' + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $opt_dry_run || eval "$cmds" || func_append admincmds " + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + $opt_silent && exit $EXIT_SUCCESS + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + echo "----------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + $ECHO " $libdir" + done + echo + echo "If you ever happen to want to link against installed libraries" + echo "in a given directory, LIBDIR, you must either use libtool, and" + echo "specify the full pathname of the library, or use the \`-LLIBDIR'" + echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the \`$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the \`$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $ECHO " - use the \`$flag' linker flag" + fi + if test -n "$admincmds"; then + $ECHO " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + fi + echo + + echo "See any operating system documentation about shared libraries for" + case $host in + solaris2.[6789]|solaris2.1[0-9]) + echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" + echo "pages." + ;; + *) + echo "more information, such as the ld(1) and ld.so(8) manual pages." + ;; + esac + echo "----------------------------------------------------------------------" + fi + exit $EXIT_SUCCESS +} + +test "$opt_mode" = finish && func_mode_finish ${1+"$@"} + + +# func_mode_install arg... +func_mode_install () +{ + $opt_debug + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || + # Allow the use of GNU shtool's install command. + case $nonopt in *shtool*) :;; *) false;; esac; then + # Aesthetically quote it. + func_quote_for_eval "$nonopt" + install_prog="$func_quote_for_eval_result " + arg=$1 + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + func_quote_for_eval "$arg" + func_append install_prog "$func_quote_for_eval_result" + install_shared_prog=$install_prog + case " $install_prog " in + *[\\\ /]cp\ *) install_cp=: ;; + *) install_cp=false ;; + esac + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=no + stripme= + no_mode=: + for arg + do + arg2= + if test -n "$dest"; then + func_append files " $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=yes ;; + -f) + if $install_cp; then :; else + prev=$arg + fi + ;; + -g | -m | -o) + prev=$arg + ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + if test "x$prev" = x-m && test -n "$install_override_mode"; then + arg2=$install_override_mode + no_mode=false + fi + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + func_quote_for_eval "$arg" + func_append install_prog " $func_quote_for_eval_result" + if test -n "$arg2"; then + func_quote_for_eval "$arg2" + fi + func_append install_shared_prog " $func_quote_for_eval_result" + done + + test -z "$install_prog" && \ + func_fatal_help "you must specify an install program" + + test -n "$prev" && \ + func_fatal_help "the \`$prev' option requires an argument" + + if test -n "$install_override_mode" && $no_mode; then + if $install_cp; then :; else + func_quote_for_eval "$install_override_mode" + func_append install_shared_prog " -m $func_quote_for_eval_result" + fi + fi + + if test -z "$files"; then + if test -z "$dest"; then + func_fatal_help "no file or destination specified" + else + func_fatal_help "you must specify a destination" + fi + fi + + # Strip any trailing slash from the destination. + func_stripname '' '/' "$dest" + dest=$func_stripname_result + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=yes + if test "$isdir" = yes; then + destdir="$dest" + destname= + else + func_dirname_and_basename "$dest" "" "." + destdir="$func_dirname_result" + destname="$func_basename_result" + + # Not a directory, so check to see that there is only one file specified. + set dummy $files; shift + test "$#" -gt 1 && \ + func_fatal_help "\`$dest' is not a directory" + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + func_fatal_help "\`$destdir' must be an absolute directory name" + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + func_append staticlibs " $file" + ;; + + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "\`$file' is not a valid libtool archive" + + library_names= + old_library= + relink_command= + func_source "$file" + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) func_append current_libdirs " $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) func_append future_libdirs " $libdir" ;; + esac + fi + + func_dirname "$file" "/" "" + dir="$func_dirname_result" + func_append dir "$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + test "$inst_prefix_dir" = "$destdir" && \ + func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` + fi + + func_warning "relinking \`$file'" + func_show_eval "$relink_command" \ + 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' + fi + + # See the names of the shared library. + set dummy $library_names; shift + if test -n "$1"; then + realname="$1" + shift + + srcname="$realname" + test -n "$relink_command" && srcname="$realname"T + + # Install the shared library and build the symlinks. + func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ + 'exit $?' + tstripme="$stripme" + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + case $realname in + *.dll.a) + tstripme="" + ;; + esac + ;; + esac + if test -n "$tstripme" && test -n "$striplib"; then + func_show_eval "$striplib $destdir/$realname" 'exit $?' + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try `ln -sf' first, because the `ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + test "$linkname" != "$realname" \ + && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" + done + fi + + # Do each command in the postinstall commands. + lib="$destdir/$realname" + func_execute_cmds "$postinstall_cmds" 'exit $?' + fi + + # Install the pseudo-library for information purposes. + func_basename "$file" + name="$func_basename_result" + instname="$dir/$name"i + func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' + + # Maybe install the static library, too. + test -n "$old_library" && func_append staticlibs " $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + func_basename "$file" + destfile="$func_basename_result" + destfile="$destdir/$destfile" + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + func_lo2o "$destfile" + staticdest=$func_lo2o_result + ;; + *.$objext) + staticdest="$destfile" + destfile= + ;; + *) + func_fatal_help "cannot copy a libtool object to \`$destfile'" + ;; + esac + + # Install the libtool object if requested. + test -n "$destfile" && \ + func_show_eval "$install_prog $file $destfile" 'exit $?' + + # Install the old object if enabled. + if test "$build_old_libs" = yes; then + # Deduce the name of the old-style object file. + func_lo2o "$file" + staticobj=$func_lo2o_result + func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + func_basename "$file" + destfile="$func_basename_result" + destfile="$destdir/$destfile" + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext="" + case $file in + *.exe) + if test ! -f "$file"; then + func_stripname '' '.exe' "$file" + file=$func_stripname_result + stripped_ext=".exe" + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin* | *mingw*) + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + wrapper=$func_ltwrapper_scriptname_result + else + func_stripname '' '.exe' "$file" + wrapper=$func_stripname_result + fi + ;; + *) + wrapper=$file + ;; + esac + if func_ltwrapper_script_p "$wrapper"; then + notinst_deplibs= + relink_command= + + func_source "$wrapper" + + # Check the variables that should have been set. + test -z "$generated_by_libtool_version" && \ + func_fatal_error "invalid libtool wrapper script \`$wrapper'" + + finalize=yes + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + func_source "$lib" + fi + libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test + if test -n "$libdir" && test ! -f "$libfile"; then + func_warning "\`$lib' has not been installed in \`$libdir'" + finalize=no + fi + done + + relink_command= + func_source "$wrapper" + + outputname= + if test "$fast_install" = no && test -n "$relink_command"; then + $opt_dry_run || { + if test "$finalize" = yes; then + tmpdir=`func_mktempdir` + func_basename "$file$stripped_ext" + file="$func_basename_result" + outputname="$tmpdir/$file" + # Replace the output file specification. + relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` + + $opt_silent || { + func_quote_for_expand "$relink_command" + eval "func_echo $func_quote_for_expand_result" + } + if eval "$relink_command"; then : + else + func_error "error: relink \`$file' with the above command before installing it" + $opt_dry_run || ${RM}r "$tmpdir" + continue + fi + file="$outputname" + else + func_warning "cannot relink \`$file'" + fi + } + else + # Install the binary that we compiled earlier. + file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + func_stripname '' '.exe' "$destfile" + destfile=$func_stripname_result + ;; + esac + ;; + esac + func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' + $opt_dry_run || if test -n "$outputname"; then + ${RM}r "$tmpdir" + fi + ;; + esac + done + + for file in $staticlibs; do + func_basename "$file" + name="$func_basename_result" + + # Set up the ranlib parameters. + oldlib="$destdir/$name" + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + + func_show_eval "$install_prog \$file \$oldlib" 'exit $?' + + if test -n "$stripme" && test -n "$old_striplib"; then + func_show_eval "$old_striplib $tool_oldlib" 'exit $?' + fi + + # Do each command in the postinstall commands. + func_execute_cmds "$old_postinstall_cmds" 'exit $?' + done + + test -n "$future_libdirs" && \ + func_warning "remember to run \`$progname --finish$future_libdirs'" + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + $opt_dry_run && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi +} + +test "$opt_mode" = install && func_mode_install ${1+"$@"} + + +# func_generate_dlsyms outputname originator pic_p +# Extract symbols from dlprefiles and create ${outputname}S.o with +# a dlpreopen symbol table. +func_generate_dlsyms () +{ + $opt_debug + my_outputname="$1" + my_originator="$2" + my_pic_p="${3-no}" + my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` + my_dlsyms= + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + my_dlsyms="${my_outputname}S.c" + else + func_error "not configured to extract global symbols from dlpreopened files" + fi + fi + + if test -n "$my_dlsyms"; then + case $my_dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist="$output_objdir/${my_outputname}.nm" + + func_show_eval "$RM $nlist ${nlist}S ${nlist}T" + + # Parse the name list into a source file. + func_verbose "creating $output_objdir/$my_dlsyms" + + $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ +/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +#if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) +#pragma GCC diagnostic ignored \"-Wstrict-prototypes\" +#endif + +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +/* DATA imports from DLLs on WIN32 con't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined(__osf__) +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +/* External symbol declarations for the compiler. */\ +" + + if test "$dlself" = yes; then + func_verbose "generating symbol list for \`$output'" + + $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` + for progfile in $progfiles; do + func_to_tool_file "$progfile" func_convert_file_msys_to_w32 + func_verbose "extracting global C symbols from \`$func_to_tool_file_result'" + $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $opt_dry_run || { + eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + if test -n "$export_symbols_regex"; then + $opt_dry_run || { + eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols="$output_objdir/$outputname.exp" + $opt_dry_run || { + $RM $export_symbols + eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + } + else + $opt_dry_run || { + eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + } + fi + fi + + for dlprefile in $dlprefiles; do + func_verbose "extracting global C symbols from \`$dlprefile'" + func_basename "$dlprefile" + name="$func_basename_result" + case $host in + *cygwin* | *mingw* | *cegcc* ) + # if an import library, we need to obtain dlname + if func_win32_import_lib_p "$dlprefile"; then + func_tr_sh "$dlprefile" + eval "curr_lafile=\$libfile_$func_tr_sh_result" + dlprefile_dlbasename="" + if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then + # Use subshell, to avoid clobbering current variable values + dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` + if test -n "$dlprefile_dlname" ; then + func_basename "$dlprefile_dlname" + dlprefile_dlbasename="$func_basename_result" + else + # no lafile. user explicitly requested -dlpreopen . + $sharedlib_from_linklib_cmd "$dlprefile" + dlprefile_dlbasename=$sharedlib_from_linklib_result + fi + fi + $opt_dry_run || { + if test -n "$dlprefile_dlbasename" ; then + eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' + else + func_warning "Could not compute DLL name from $name" + eval '$ECHO ": $name " >> "$nlist"' + fi + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | + $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" + } + else # not an import lib + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + fi + ;; + *) + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + ;; + esac + done + + $opt_dry_run || { + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $MV "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if $GREP -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + $GREP -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' + else + echo '/* NONE */' >> "$output_objdir/$my_dlsyms" + fi + + echo >> "$output_objdir/$my_dlsyms" "\ + +/* The mapping between symbol names and symbols. */ +typedef struct { + const char *name; + void *address; +} lt_dlsymlist; +extern LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[]; +LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[] = +{\ + { \"$my_originator\", (void *) 0 }," + + case $need_lib_prefix in + no) + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + *) + eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + esac + echo >> "$output_objdir/$my_dlsyms" "\ + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_${my_prefix}_LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + } # !$opt_dry_run + + pic_flag_for_symtable= + case "$compile_command " in + *" -static "*) ;; + *) + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; + *-*-hpux*) + pic_flag_for_symtable=" $pic_flag" ;; + *) + if test "X$my_pic_p" != Xno; then + pic_flag_for_symtable=" $pic_flag" + fi + ;; + esac + ;; + esac + symtab_cflags= + for arg in $LTCFLAGS; do + case $arg in + -pie | -fpie | -fPIE) ;; + *) func_append symtab_cflags " $arg" ;; + esac + done + + # Now compile the dynamic symbol file. + func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' + + # Clean up the generated files. + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' + + # Transform the symbol file into the correct name. + symfileobj="$output_objdir/${my_outputname}S.$objext" + case $host in + *cygwin* | *mingw* | *cegcc* ) + if test -f "$output_objdir/$my_outputname.def"; then + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + else + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + fi + ;; + *) + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + ;; + esac + ;; + *) + func_fatal_error "unknown suffix for \`$my_dlsyms'" + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` + fi +} + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +# Despite the name, also deal with 64 bit binaries. +func_win32_libid () +{ + $opt_debug + win32_libid_type="unknown" + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | + $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then + func_to_tool_file "$1" func_convert_file_msys_to_w32 + win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | + $SED -n -e ' + 1,100{ + / I /{ + s,.*,import, + p + q + } + }'` + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $ECHO "$win32_libid_type" +} + +# func_cygming_dll_for_implib ARG +# +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib () +{ + $opt_debug + sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` +} + +# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs +# +# The is the core of a fallback implementation of a +# platform-specific function to extract the name of the +# DLL associated with the specified import library LIBNAME. +# +# SECTION_NAME is either .idata$6 or .idata$7, depending +# on the platform and compiler that created the implib. +# +# Echos the name of the DLL associated with the +# specified import library. +func_cygming_dll_for_implib_fallback_core () +{ + $opt_debug + match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` + $OBJDUMP -s --section "$1" "$2" 2>/dev/null | + $SED '/^Contents of section '"$match_literal"':/{ + # Place marker at beginning of archive member dllname section + s/.*/====MARK====/ + p + d + } + # These lines can sometimes be longer than 43 characters, but + # are always uninteresting + /:[ ]*file format pe[i]\{,1\}-/d + /^In archive [^:]*:/d + # Ensure marker is printed + /^====MARK====/p + # Remove all lines with less than 43 characters + /^.\{43\}/!d + # From remaining lines, remove first 43 characters + s/^.\{43\}//' | + $SED -n ' + # Join marker and all lines until next marker into a single line + /^====MARK====/ b para + H + $ b para + b + :para + x + s/\n//g + # Remove the marker + s/^====MARK====// + # Remove trailing dots and whitespace + s/[\. \t]*$// + # Print + /./p' | + # we now have a list, one entry per line, of the stringified + # contents of the appropriate section of all members of the + # archive which possess that section. Heuristic: eliminate + # all those which have a first or second character that is + # a '.' (that is, objdump's representation of an unprintable + # character.) This should work for all archives with less than + # 0x302f exports -- but will fail for DLLs whose name actually + # begins with a literal '.' or a single character followed by + # a '.'. + # + # Of those that remain, print the first one. + $SED -e '/^\./d;/^.\./d;q' +} + +# func_cygming_gnu_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is a GNU/binutils-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_gnu_implib_p () +{ + $opt_debug + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` + test -n "$func_cygming_gnu_implib_tmp" +} + +# func_cygming_ms_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is an MS-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_ms_implib_p () +{ + $opt_debug + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` + test -n "$func_cygming_ms_implib_tmp" +} + +# func_cygming_dll_for_implib_fallback ARG +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# +# This fallback implementation is for use when $DLLTOOL +# does not support the --identify-strict option. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib_fallback () +{ + $opt_debug + if func_cygming_gnu_implib_p "$1" ; then + # binutils import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` + elif func_cygming_ms_implib_p "$1" ; then + # ms-generated import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` + else + # unknown + sharedlib_from_linklib_result="" + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + $opt_debug + f_ex_an_ar_dir="$1"; shift + f_ex_an_ar_oldlib="$1" + if test "$lock_old_archive_extraction" = yes; then + lockfile=$f_ex_an_ar_oldlib.lock + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + fi + func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ + 'stat=$?; rm -f "$lockfile"; exit $stat' + if test "$lock_old_archive_extraction" = yes; then + $opt_dry_run || rm -f "$lockfile" + fi + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" + fi +} + + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + $opt_debug + my_gentop="$1"; shift + my_oldlibs=${1+"$@"} + my_oldobjs="" + my_xlib="" + my_xabs="" + my_xdir="" + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + func_basename "$my_xlib" + my_xlib="$func_basename_result" + my_xlib_u=$my_xlib + while :; do + case " $extracted_archives " in + *" $my_xlib_u "*) + func_arith $extracted_serial + 1 + extracted_serial=$func_arith_result + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac + done + extracted_archives="$extracted_archives $my_xlib_u" + my_xdir="$my_gentop/$my_xlib_u" + + func_mkdir_p "$my_xdir" + + case $host in + *-darwin*) + func_verbose "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + $opt_dry_run || { + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + darwin_base_archive=`basename "$darwin_archive"` + darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` + if test -n "$darwin_arches"; then + darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches ; do + func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" + $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" + cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" + func_extract_an_archive "`pwd`" "${darwin_base_archive}" + cd "$darwin_curdir" + $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" + done # $darwin_arches + ## Okay now we've a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` + $LIPO -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + $RM -rf unfat-$$ + cd "$darwin_orig_dir" + else + cd $darwin_orig_dir + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + } # !$opt_dry_run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` + done + + func_extract_archives_result="$my_oldobjs" +} + + +# func_emit_wrapper [arg=no] +# +# Emit a libtool wrapper script on stdout. +# Don't directly open a file because we may want to +# incorporate the script contents within a cygwin/mingw +# wrapper executable. Must ONLY be called from within +# func_mode_link because it depends on a number of variables +# set therein. +# +# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR +# variable will take. If 'yes', then the emitted script +# will assume that the directory in which it is stored is +# the $objdir directory. This is a cygwin/mingw-specific +# behavior. +func_emit_wrapper () +{ + func_emit_wrapper_arg1=${1-no} + + $ECHO "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='$sed_quote_subst' + +# Be Bourne compatible +if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + generated_by_libtool_version='$macro_version' + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$ECHO are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + file=\"\$0\"" + + qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` + $ECHO "\ + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + ECHO=\"$qECHO\" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ which is used only on +# windows platforms, and (c) all begin with the string "--lt-" +# (application programs are unlikely to have options which match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's $0 value, followed by "$@". +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=\$0 + shift + for lt_opt + do + case \"\$lt_opt\" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` + test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. + lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` + cat \"\$lt_dump_D/\$lt_dump_F\" + exit 0 + ;; + --lt-*) + \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n \"\$lt_option_debug\"; then + echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\" + lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2* | *-cegcc*) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $ECHO "\ + \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from \$@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case \" \$* \" in + *\\ --lt-*) + for lt_wr_arg + do + case \$lt_wr_arg in + --lt-*) ;; + *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; + esac + shift + done ;; + esac + func_exec_program_core \${1+\"\$@\"} +} + + # Parse options + func_parse_lt_options \"\$0\" \${1+\"\$@\"} + + # Find the directory that this script lives in. + thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 + if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then + # special case for '.' + if test \"\$thisdir\" = \".\"; then + thisdir=\`pwd\` + fi + # remove .libs from thisdir + case \"\$thisdir\" in + *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; + $objdir ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test "$fast_install" = yes; then + $ECHO "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $MKDIR \"\$progdir\" + else + $RM \"\$progdir/\$file\" + fi" + + $ECHO "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + $ECHO \"\$relink_command_output\" >&2 + $RM \"\$progdir/\$file\" + exit 1 + fi + fi + + $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $RM \"\$progdir/\$program\"; + $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $RM \"\$progdir/\$file\" + fi" + else + $ECHO "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $ECHO "\ + + if test -f \"\$progdir/\$program\"; then" + + # fixup the dll searchpath if we need to. + # + # Fix the DLL searchpath if we need to. Do this before prepending + # to shlibpath, because on Windows, both are PATH and uninstalled + # libraries must come first. + if test -n "$dllsearchpath"; then + $ECHO "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + # Export our shlibpath_var if we have one. + if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $ECHO "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` + + export $shlibpath_var +" + fi + + $ECHO "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. + func_exec_program \${1+\"\$@\"} + fi + else + # The program doesn't exist. + \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 + \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" +} + + +# func_emit_cwrapperexe_src +# emit the source code for a wrapper executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_cwrapperexe_src () +{ + cat < +#include +#ifdef _MSC_VER +# include +# include +# include +#else +# include +# include +# ifdef __CYGWIN__ +# include +# endif +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +/* declarations of non-ANSI functions */ +#if defined(__MINGW32__) +# ifdef __STRICT_ANSI__ +int _putenv (const char *); +# endif +#elif defined(__CYGWIN__) +# ifdef __STRICT_ANSI__ +char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); +# endif +/* #elif defined (other platforms) ... */ +#endif + +/* portability defines, excluding path handling macros */ +#if defined(_MSC_VER) +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +# define S_IXUSR _S_IEXEC +# ifndef _INTPTR_T_DEFINED +# define _INTPTR_T_DEFINED +# define intptr_t int +# endif +#elif defined(__MINGW32__) +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +#elif defined(__CYGWIN__) +# define HAVE_SETENV +# define FOPEN_WB "wb" +/* #elif defined (other platforms) ... */ +#endif + +#if defined(PATH_MAX) +# define LT_PATHMAX PATH_MAX +#elif defined(MAXPATHLEN) +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef S_IXOTH +# define S_IXOTH 0 +#endif +#ifndef S_IXGRP +# define S_IXGRP 0 +#endif + +/* path handling portability macros */ +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ + defined (__OS2__) +# define HAVE_DOS_BASED_FILE_SYSTEM +# define FOPEN_WB "wb" +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#ifndef FOPEN_WB +# define FOPEN_WB "w" +#endif +#ifndef _O_BINARY +# define _O_BINARY 0 +#endif + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free ((void *) stale); stale = 0; } \ +} while (0) + +#if defined(LT_DEBUGWRAPPER) +static int lt_debug = 1; +#else +static int lt_debug = 0; +#endif + +const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ + +void *xmalloc (size_t num); +char *xstrdup (const char *string); +const char *base_name (const char *name); +char *find_executable (const char *wrapper); +char *chase_symlinks (const char *pathspec); +int make_executable (const char *path); +int check_executable (const char *path); +char *strendzap (char *str, const char *pat); +void lt_debugprintf (const char *file, int line, const char *fmt, ...); +void lt_fatal (const char *file, int line, const char *message, ...); +static const char *nonnull (const char *s); +static const char *nonempty (const char *s); +void lt_setenv (const char *name, const char *value); +char *lt_extend_str (const char *orig_value, const char *add, int to_end); +void lt_update_exe_path (const char *name, const char *value); +void lt_update_lib_path (const char *name, const char *value); +char **prepare_spawn (char **argv); +void lt_dump_script (FILE *f); +EOF + + cat <= 0) + && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) + return 1; + else + return 0; +} + +int +make_executable (const char *path) +{ + int rval = 0; + struct stat st; + + lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", + nonempty (path)); + if ((!path) || (!*path)) + return 0; + + if (stat (path, &st) >= 0) + { + rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); + } + return rval; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise + Does not chase symlinks, even on platforms that support them. +*/ +char * +find_executable (const char *wrapper) +{ + int has_slash = 0; + const char *p; + const char *p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + int tmp_len; + char *concat_name; + + lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", + nonempty (wrapper)); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char *path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char *q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR (*q)) + break; + p_len = q - p; + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = + XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = + XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + return NULL; +} + +char * +chase_symlinks (const char *pathspec) +{ +#ifndef S_ISLNK + return xstrdup (pathspec); +#else + char buf[LT_PATHMAX]; + struct stat s; + char *tmp_pathspec = xstrdup (pathspec); + char *p; + int has_symlinks = 0; + while (strlen (tmp_pathspec) && !has_symlinks) + { + lt_debugprintf (__FILE__, __LINE__, + "checking path component for symlinks: %s\n", + tmp_pathspec); + if (lstat (tmp_pathspec, &s) == 0) + { + if (S_ISLNK (s.st_mode) != 0) + { + has_symlinks = 1; + break; + } + + /* search backwards for last DIR_SEPARATOR */ + p = tmp_pathspec + strlen (tmp_pathspec) - 1; + while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + p--; + if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + { + /* no more DIR_SEPARATORS left */ + break; + } + *p = '\0'; + } + else + { + lt_fatal (__FILE__, __LINE__, + "error accessing file \"%s\": %s", + tmp_pathspec, nonnull (strerror (errno))); + } + } + XFREE (tmp_pathspec); + + if (!has_symlinks) + { + return xstrdup (pathspec); + } + + tmp_pathspec = realpath (pathspec, buf); + if (tmp_pathspec == 0) + { + lt_fatal (__FILE__, __LINE__, + "could not follow symlinks for %s", pathspec); + } + return xstrdup (tmp_pathspec); +#endif +} + +char * +strendzap (char *str, const char *pat) +{ + size_t len, patlen; + + assert (str != NULL); + assert (pat != NULL); + + len = strlen (str); + patlen = strlen (pat); + + if (patlen <= len) + { + str += len - patlen; + if (strcmp (str, pat) == 0) + *str = '\0'; + } + return str; +} + +void +lt_debugprintf (const char *file, int line, const char *fmt, ...) +{ + va_list args; + if (lt_debug) + { + (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); + va_start (args, fmt); + (void) vfprintf (stderr, fmt, args); + va_end (args); + } +} + +static void +lt_error_core (int exit_status, const char *file, + int line, const char *mode, + const char *message, va_list ap) +{ + fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *file, int line, const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); + va_end (ap); +} + +static const char * +nonnull (const char *s) +{ + return s ? s : "(null)"; +} + +static const char * +nonempty (const char *s) +{ + return (s && !*s) ? "(empty)" : nonnull (s); +} + +void +lt_setenv (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_setenv) setting '%s' to '%s'\n", + nonnull (name), nonnull (value)); + { +#ifdef HAVE_SETENV + /* always make a copy, for consistency with !HAVE_SETENV */ + char *str = xstrdup (value); + setenv (name, str, 1); +#else + int len = strlen (name) + 1 + strlen (value) + 1; + char *str = XMALLOC (char, len); + sprintf (str, "%s=%s", name, value); + if (putenv (str) != EXIT_SUCCESS) + { + XFREE (str); + } +#endif + } +} + +char * +lt_extend_str (const char *orig_value, const char *add, int to_end) +{ + char *new_value; + if (orig_value && *orig_value) + { + int orig_value_len = strlen (orig_value); + int add_len = strlen (add); + new_value = XMALLOC (char, add_len + orig_value_len + 1); + if (to_end) + { + strcpy (new_value, orig_value); + strcpy (new_value + orig_value_len, add); + } + else + { + strcpy (new_value, add); + strcpy (new_value + add_len, orig_value); + } + } + else + { + new_value = xstrdup (add); + } + return new_value; +} + +void +lt_update_exe_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + /* some systems can't cope with a ':'-terminated path #' */ + int len = strlen (new_value); + while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) + { + new_value[len-1] = '\0'; + } + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +void +lt_update_lib_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +EOF + case $host_os in + mingw*) + cat <<"EOF" + +/* Prepares an argument vector before calling spawn(). + Note that spawn() does not by itself call the command interpreter + (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : + ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&v); + v.dwPlatformId == VER_PLATFORM_WIN32_NT; + }) ? "cmd.exe" : "command.com"). + Instead it simply concatenates the arguments, separated by ' ', and calls + CreateProcess(). We must quote the arguments since Win32 CreateProcess() + interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a + special way: + - Space and tab are interpreted as delimiters. They are not treated as + delimiters if they are surrounded by double quotes: "...". + - Unescaped double quotes are removed from the input. Their only effect is + that within double quotes, space and tab are treated like normal + characters. + - Backslashes not followed by double quotes are not special. + - But 2*n+1 backslashes followed by a double quote become + n backslashes followed by a double quote (n >= 0): + \" -> " + \\\" -> \" + \\\\\" -> \\" + */ +#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +char ** +prepare_spawn (char **argv) +{ + size_t argc; + char **new_argv; + size_t i; + + /* Count number of arguments. */ + for (argc = 0; argv[argc] != NULL; argc++) + ; + + /* Allocate new argument vector. */ + new_argv = XMALLOC (char *, argc + 1); + + /* Put quoted arguments into the new argument vector. */ + for (i = 0; i < argc; i++) + { + const char *string = argv[i]; + + if (string[0] == '\0') + new_argv[i] = xstrdup ("\"\""); + else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) + { + int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); + size_t length; + unsigned int backslashes; + const char *s; + char *quoted_string; + char *p; + + length = 0; + backslashes = 0; + if (quote_around) + length++; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + length += backslashes + 1; + length++; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + length += backslashes + 1; + + quoted_string = XMALLOC (char, length + 1); + + p = quoted_string; + backslashes = 0; + if (quote_around) + *p++ = '"'; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + { + unsigned int j; + for (j = backslashes + 1; j > 0; j--) + *p++ = '\\'; + } + *p++ = c; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + { + unsigned int j; + for (j = backslashes; j > 0; j--) + *p++ = '\\'; + *p++ = '"'; + } + *p = '\0'; + + new_argv[i] = quoted_string; + } + else + new_argv[i] = (char *) string; + } + new_argv[argc] = NULL; + + return new_argv; +} +EOF + ;; + esac + + cat <<"EOF" +void lt_dump_script (FILE* f) +{ +EOF + func_emit_wrapper yes | + $SED -n -e ' +s/^\(.\{79\}\)\(..*\)/\1\ +\2/ +h +s/\([\\"]\)/\\\1/g +s/$/\\n/ +s/\([^\n]*\).*/ fputs ("\1", f);/p +g +D' + cat <<"EOF" +} +EOF +} +# end: func_emit_cwrapperexe_src + +# func_win32_import_lib_p ARG +# True if ARG is an import lib, as indicated by $file_magic_cmd +func_win32_import_lib_p () +{ + $opt_debug + case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in + *import*) : ;; + *) false ;; + esac +} + +# func_mode_link arg... +func_mode_link () +{ + $opt_debug + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # which system we are compiling for in order to pass an extra + # flag for every libtool invocation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll which has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args=$nonopt + base_compile="$nonopt $@" + compile_command=$nonopt + finalize_command=$nonopt + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + new_inherited_linker_flags= + + avoid_version=no + bindir= + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + non_pic_objects= + precious_files_regex= + prefer_static_libs=no + preload=no + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + vinfo_number=no + weak_libs= + single_module="${wl}-single_module" + func_infer_tag $base_compile + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -shared) + test "$build_libtool_libs" != yes && \ + func_fatal_configuration "can not build a shared library" + build_old_libs=no + break + ;; + -all-static | -static | -static-libtool-libs) + case $arg in + -all-static) + if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then + func_warning "complete static linking is impossible in this configuration" + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + -static) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + ;; + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg="$1" + shift + func_quote_for_eval "$arg" + qarg=$func_quote_for_eval_unquoted_result + func_append libtool_args " $func_quote_for_eval_result" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + func_append compile_command " @OUTPUT@" + func_append finalize_command " @OUTPUT@" + ;; + esac + + case $prev in + bindir) + bindir="$arg" + prev= + continue + ;; + dlfiles|dlprefiles) + if test "$preload" = no; then + # Add the symbol object into the linking commands. + func_append compile_command " @SYMFILE@" + func_append finalize_command " @SYMFILE@" + preload=yes + fi + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test "$dlself" = no; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test "$prev" = dlprefiles; then + dlself=yes + elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test "$prev" = dlfiles; then + func_append dlfiles " $arg" + else + func_append dlprefiles " $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols="$arg" + test -f "$arg" \ + || func_fatal_error "symbol file \`$arg' does not exist" + prev= + continue + ;; + expsyms_regex) + export_symbols_regex="$arg" + prev= + continue + ;; + framework) + case $host in + *-*-darwin*) + case "$deplibs " in + *" $qarg.ltframework "*) ;; + *) func_append deplibs " $qarg.ltframework" # this is fixed later + ;; + esac + ;; + esac + prev= + continue + ;; + inst_prefix) + inst_prefix_dir="$arg" + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat "$save_arg"` + do +# func_append moreargs " $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test "$pic_object" = none && + test "$non_pic_object" = none; then + func_fatal_error "cannot find name of object for \`$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "\`$arg' is not a valid libtool object" + fi + fi + done + else + func_fatal_error "link input file \`$arg' does not exist" + fi + arg=$save_arg + prev= + continue + ;; + precious_regex) + precious_files_regex="$arg" + prev= + continue + ;; + release) + release="-$arg" + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + if test "$prev" = rpath; then + case "$rpath " in + *" $arg "*) ;; + *) func_append rpath " $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) func_append xrpath " $arg" ;; + esac + fi + prev= + continue + ;; + shrext) + shrext_cmds="$arg" + prev= + continue + ;; + weak) + func_append weak_libs " $arg" + prev= + continue + ;; + xcclinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xcompiler) + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xlinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $wl$qarg" + prev= + func_append compile_command " $wl$qarg" + func_append finalize_command " $wl$qarg" + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg="$arg" + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + # See comment for -static flag below, for more details. + func_append compile_command " $link_static_flag" + func_append finalize_command " $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + func_fatal_error "\`-allow-undefined' must not be used because it is the default" + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -bindir) + prev=bindir + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + func_fatal_error "more than one -exported-symbols argument is not allowed" + fi + if test "X$arg" = "X-export-symbols"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework) + prev=framework + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + func_append compile_command " $arg" + func_append finalize_command " $arg" + ;; + esac + continue + ;; + + -L*) + func_stripname "-L" '' "$arg" + if test -z "$func_stripname_result"; then + if test "$#" -gt 0; then + func_fatal_error "require no space between \`-L' and \`$1'" + else + func_fatal_error "need path for \`-L' option" + fi + fi + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + test -z "$absdir" && \ + func_fatal_error "cannot determine absolute directory name of \`$dir'" + dir="$absdir" + ;; + esac + case "$deplibs " in + *" -L$dir "* | *" $arg "*) + # Will only happen for absolute or sysroot arguments + ;; + *) + # Preserve sysroot, but never include relative directories + case $dir in + [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; + *) func_append deplibs " -L$dir" ;; + esac + func_append lib_search_path " $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + ::) dllsearchpath=$dir;; + *) func_append dllsearchpath ":$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test "X$arg" = "X-lc" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + test "X$arg" = "X-lc" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + func_append deplibs " System.ltframework" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test "X$arg" = "X-lc" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test "X$arg" = "X-lc" && continue + ;; + esac + elif test "X$arg" = "X-lc_r"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + func_append deplibs " $arg" + continue + ;; + + -module) + module=yes + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + # Darwin uses the -arch flag to determine output architecture. + -model|-arch|-isysroot|--sysroot) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case "$new_inherited_linker_flags " in + *" $arg "*) ;; + * ) func_append new_inherited_linker_flags " $arg" ;; + esac + continue + ;; + + -multi_module) + single_module="${wl}-multi_module" + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) + # The PATH hackery in wrapper scripts is required on Windows + # and Darwin in order for the loader to find any dlls it needs. + func_warning "\`-no-install' is ignored for $host" + func_warning "assuming \`-no-fast-install' instead" + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + func_stripname '-R' '' "$arg" + dir=$func_stripname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + =*) + func_stripname '=' '' "$dir" + dir=$lt_sysroot$func_stripname_result + ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + continue + ;; + + -shared) + # The effects of -shared are defined in a previous loop. + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -static | -static-libtool-libs) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -weak) + prev=weak + continue + ;; + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + func_quote_for_eval "$flag" + func_append arg " $func_quote_for_eval_result" + func_append compiler_flags " $func_quote_for_eval_result" + done + IFS="$save_ifs" + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Wl,*) + func_stripname '-Wl,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + func_quote_for_eval "$flag" + func_append arg " $wl$func_quote_for_eval_result" + func_append compiler_flags " $wl$func_quote_for_eval_result" + func_append linker_flags " $func_quote_for_eval_result" + done + IFS="$save_ifs" + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # -msg_* for osf cc + -msg_*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + + # Flags to be passed through unchanged, with rationale: + # -64, -mips[0-9] enable 64-bit mode for the SGI compiler + # -r[0-9][0-9]* specify processor for the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler + # +DA*, +DD* enable 64-bit mode for the HP compiler + # -q* compiler args for the IBM compiler + # -m*, -t[45]*, -txscale* architecture-specific flags for GCC + # -F/path path to uninstalled frameworks, gcc on darwin + # -p, -pg, --coverage, -fprofile-* profiling flags for GCC + # @file GCC response files + # -tp=* Portland pgcc target processor selection + # --sysroot=* for sysroot support + # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ + -O*|-flto*|-fwhopr*|-fuse-linker-plugin) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + func_append compile_command " $arg" + func_append finalize_command " $arg" + func_append compiler_flags " $arg" + continue + ;; + + # Some other compiler flag. + -* | +*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + + *.$objext) + # A standard object. + func_append objs " $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test "$pic_object" = none && + test "$non_pic_object" = none; then + func_fatal_error "cannot find name of object for \`$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "\`$arg' is not a valid libtool object" + fi + fi + ;; + + *.$libext) + # An archive. + func_append deplibs " $arg" + func_append old_deplibs " $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + func_resolve_sysroot "$arg" + if test "$prev" = dlfiles; then + # This library was specified with -dlopen. + func_append dlfiles " $func_resolve_sysroot_result" + prev= + elif test "$prev" = dlprefiles; then + # The library was specified with -dlpreopen. + func_append dlprefiles " $func_resolve_sysroot_result" + prev= + else + func_append deplibs " $func_resolve_sysroot_result" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + done # argument parsing loop + + test -n "$prev" && \ + func_fatal_help "the \`$prevarg' option requires an argument" + + if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + func_basename "$output" + outputname="$func_basename_result" + libobjs_save="$libobjs" + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + func_dirname "$output" "/" "" + output_objdir="$func_dirname_result$objdir" + func_to_tool_file "$output_objdir/" + tool_output_objdir=$func_to_tool_file_result + # Create the object directory. + func_mkdir_p "$output_objdir" + + # Determine the type of output + case $output in + "") + func_fatal_help "you must specify an output file" + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if $opt_preserve_dup_deps ; then + case "$libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append libs " $deplib" + done + + if test "$linkmode" = lib; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if $opt_duplicate_compiler_generated_deps; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; + esac + func_append pre_post_deps " $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + + case $linkmode in + lib) + passes="conv dlpreopen link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=no + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + + for pass in $passes; do + # The preopen pass in lib mode reverses $deplibs; put it back here + # so that -L comes before libs that need it for instance... + if test "$linkmode,$pass" = "lib,link"; then + ## FIXME: Find the place where the list is rebuilt in the wrong + ## order, and fix it there properly + tmp_deplibs= + for deplib in $deplibs; do + tmp_deplibs="$deplib $tmp_deplibs" + done + deplibs="$tmp_deplibs" + fi + + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan"; then + libs="$deplibs" + deplibs= + fi + if test "$linkmode" = prog; then + case $pass in + dlopen) libs="$dlfiles" ;; + dlpreopen) libs="$dlprefiles" ;; + link) + libs="$deplibs %DEPLIBS%" + test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" + ;; + esac + fi + if test "$linkmode,$pass" = "lib,dlpreopen"; then + # Collect and forward deplibs of preopened libtool libs + for lib in $dlprefiles; do + # Ignore non-libtool-libs + dependency_libs= + func_resolve_sysroot "$lib" + case $lib in + *.la) func_source "$func_resolve_sysroot_result" ;; + esac + + # Collect preopened libtool deplibs, except any this library + # has declared as weak libs + for deplib in $dependency_libs; do + func_basename "$deplib" + deplib_base=$func_basename_result + case " $weak_libs " in + *" $deplib_base "*) ;; + *) func_append deplibs " $deplib" ;; + esac + done + done + libs="$dlprefiles" + fi + if test "$pass" = dlopen; then + # Collect dlpreopened libraries + save_deplibs="$deplibs" + deplibs= + fi + + for deplib in $libs; do + lib= + found=no + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append compiler_flags " $deplib" + if test "$linkmode" = lib ; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -l*) + if test "$linkmode" != lib && test "$linkmode" != prog; then + func_warning "\`-l' is ignored for archives/objects" + continue + fi + func_stripname '-l' '' "$deplib" + name=$func_stripname_result + if test "$linkmode" = lib; then + searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" + else + searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" + fi + for searchdir in $searchdirs; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib="$searchdir/lib${name}${search_ext}" + if test -f "$lib"; then + if test "$search_ext" = ".la"; then + found=yes + else + found=no + fi + break 2 + fi + done + done + if test "$found" != yes; then + # deplib doesn't seem to be a libtool library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + else # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $deplib "*) + if func_lalib_p "$lib"; then + library_names= + old_library= + func_source "$lib" + for l in $old_library $library_names; do + ll="$l" + done + if test "X$ll" = "X$old_library" ; then # only static version available + found=no + func_dirname "$lib" "" "." + ladir="$func_dirname_result" + lib=$ladir/$old_library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + fi + ;; # -l + *.ltframework) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + if test "$linkmode" = lib ; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test "$pass" = conv && continue + newdependency_libs="$deplib $newdependency_libs" + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + prog) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + if test "$pass" = scan; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + *) + func_warning "\`-L' is ignored for archives/objects" + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test "$pass" = link; then + func_stripname '-R' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) + func_resolve_sysroot "$deplib" + lib=$func_resolve_sysroot_result + ;; + *.$libext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + # Linking convenience modules into shared libraries is allowed, + # but linking other static libraries is non-portable. + case " $dlpreconveniencelibs " in + *" $deplib "*) ;; + *) + valid_a_lib=no + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=yes + fi + ;; + pass_all) + valid_a_lib=yes + ;; + esac + if test "$valid_a_lib" != yes; then + echo + $ECHO "*** Warning: Trying to link with static lib archive $deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because the file extensions .$libext of this argument makes me believe" + echo "*** that it is just a static archive that I should not use here." + else + echo + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + fi + ;; + esac + continue + ;; + prog) + if test "$pass" != link; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + elif test "$linkmode" = prog; then + if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + func_append newdlprefiles " $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append newdlfiles " $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=yes + continue + ;; + esac # case $deplib + + if test "$found" = yes || test -f "$lib"; then : + else + func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" + fi + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$lib" \ + || func_fatal_error "\`$lib' is not a valid libtool archive" + + func_dirname "$lib" "" "." + ladir="$func_dirname_result" + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + inherited_linker_flags= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + func_source "$lib" + + # Convert "-framework foo" to "foo.ltframework" + if test -n "$inherited_linker_flags"; then + tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` + for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do + case " $new_inherited_linker_flags " in + *" $tmp_inherited_linker_flag "*) ;; + *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; + esac + done + fi + dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan" || + { test "$linkmode" != prog && test "$linkmode" != lib; }; then + test -n "$dlopen" && func_append dlfiles " $dlopen" + test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" + fi + + if test "$pass" = conv; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + func_fatal_error "cannot find name of link library for \`$lib'" + fi + # It is a libtool convenience library, so add in its objects. + func_append convenience " $ladir/$objdir/$old_library" + func_append old_convenience " $ladir/$objdir/$old_library" + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_preserve_dup_deps ; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done + elif test "$linkmode" != prog && test "$linkmode" != lib; then + func_fatal_error "\`$lib' is not a convenience library" + fi + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + if test -n "$old_library" && + { test "$prefer_static_libs" = yes || + test "$prefer_static_libs,$installed" = "built,no"; }; then + linklib=$old_library + else + for l in $old_library $library_names; do + linklib="$l" + done + fi + if test -z "$linklib"; then + func_fatal_error "cannot find name of link library for \`$lib'" + fi + + # This library was specified with -dlopen. + if test "$pass" = dlopen; then + if test -z "$libdir"; then + func_fatal_error "cannot -dlopen a convenience library: \`$lib'" + fi + if test -z "$dlname" || + test "$dlopen_support" != yes || + test "$build_libtool_libs" = no; then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + func_append dlprefiles " $lib $dependency_libs" + else + func_append newdlfiles " $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + func_warning "cannot determine absolute directory name of \`$ladir'" + func_warning "passing it literally to the linker, although it might fail" + abs_ladir="$ladir" + fi + ;; + esac + func_basename "$lib" + laname="$func_basename_result" + + # Find the relevant object directory and library name. + if test "X$installed" = Xyes; then + if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + func_warning "library \`$lib' was moved." + dir="$ladir" + absdir="$abs_ladir" + libdir="$abs_ladir" + else + dir="$lt_sysroot$libdir" + absdir="$lt_sysroot$libdir" + fi + test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir="$ladir" + absdir="$abs_ladir" + # Remove this search path later + func_append notinst_path " $abs_ladir" + else + dir="$ladir/$objdir" + absdir="$abs_ladir/$objdir" + # Remove this search path later + func_append notinst_path " $abs_ladir" + fi + fi # $installed = yes + func_stripname 'lib' '.la' "$laname" + name=$func_stripname_result + + # This library was specified with -dlpreopen. + if test "$pass" = dlpreopen; then + if test -z "$libdir" && test "$linkmode" = prog; then + func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" + fi + case "$host" in + # special handling for platforms with PE-DLLs. + *cygwin* | *mingw* | *cegcc* ) + # Linker will automatically link against shared library if both + # static and shared are present. Therefore, ensure we extract + # symbols from the import library if a shared library is present + # (otherwise, the dlopen module name will be incorrect). We do + # this by putting the import library name into $newdlprefiles. + # We recover the dlopen module name by 'saving' the la file + # name in a special purpose variable, and (later) extracting the + # dlname from the la file. + if test -n "$dlname"; then + func_tr_sh "$dir/$linklib" + eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" + func_append newdlprefiles " $dir/$linklib" + else + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + fi + ;; + * ) + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + func_append newdlprefiles " $dir/$dlname" + else + func_append newdlprefiles " $dir/$linklib" + fi + ;; + esac + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test "$linkmode" = lib; then + deplibs="$dir/$old_library $deplibs" + elif test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test "$linkmode" = prog && test "$pass" != link; then + func_append newlib_search_path " $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=no + if test "$link_all_deplibs" != no || test -z "$library_names" || + test "$build_libtool_libs" = no; then + linkalldeplibs=yes + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + esac + # Need to link against all dependency_libs? + if test "$linkalldeplibs" = yes; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if $opt_preserve_dup_deps ; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test "$linkmode,$pass" = "prog,link"; then + if test -n "$library_names" && + { { test "$prefer_static_libs" = no || + test "$prefer_static_libs,$installed" = "built,yes"; } || + test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then + # Make sure the rpath contains only unique directories. + case "$temp_rpath:" in + *"$absdir:"*) ;; + *) func_append temp_rpath "$absdir:" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if test "$alldeplibs" = yes && + { test "$deplibs_check_method" = pass_all || + { test "$build_libtool_libs" = yes && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test "$use_static_libs" = built && test "$installed" = yes; then + use_static_libs=no + fi + if test -n "$library_names" && + { test "$use_static_libs" = no || test -z "$old_library"; }; then + case $host in + *cygwin* | *mingw* | *cegcc*) + # No point in relinking DLLs because paths are not encoded + func_append notinst_deplibs " $lib" + need_relink=no + ;; + *) + if test "$installed" = no; then + func_append notinst_deplibs " $lib" + need_relink=yes + fi + ;; + esac + # This is a shared library + + # Warn about portability, can't link against -module's on some + # systems (darwin). Don't bleat about dlopened modules though! + dlopenmodule="" + for dlpremoduletest in $dlprefiles; do + if test "X$dlpremoduletest" = "X$lib"; then + dlopenmodule="$dlpremoduletest" + break + fi + done + if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then + echo + if test "$linkmode" = prog; then + $ECHO "*** Warning: Linking the executable $output against the loadable module" + else + $ECHO "*** Warning: Linking the shared library $output against the loadable module" + fi + $ECHO "*** $linklib is not portable!" + fi + if test "$linkmode" = lib && + test "$hardcode_into_libs" = yes; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + shift + realname="$1" + shift + libname=`eval "\\$ECHO \"$libname_spec\""` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname="$dlname" + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw* | *cegcc*) + func_arith $current - $age + major=$func_arith_result + versuffix="-$major" + ;; + esac + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot="$soname" + func_basename "$soroot" + soname="$func_basename_result" + func_stripname 'lib' '.dll' "$soname" + newlib=libimp-$func_stripname_result.a + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + func_verbose "extracting exported symbol list from \`$soname'" + func_execute_cmds "$extract_expsyms_cmds" 'exit $?' + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + func_verbose "generating import library for \`$soname'" + func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test "$linkmode" = prog || test "$opt_mode" != relink; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test "$hardcode_direct" = no; then + add="$dir/$linklib" + case $host in + *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; + *-*-sysv4*uw2*) add_dir="-L$dir" ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir="-L$dir" ;; + *-*-darwin* ) + # if the lib is a (non-dlopened) module then we can not + # link against it, someone is ignoring the earlier warnings + if /usr/bin/file -L $add 2> /dev/null | + $GREP ": [^:]* bundle" >/dev/null ; then + if test "X$dlopenmodule" != "X$lib"; then + $ECHO "*** Warning: lib $linklib is a module, not a shared library" + if test -z "$old_library" ; then + echo + echo "*** And there doesn't seem to be a static archive available" + echo "*** The link will probably fail, sorry" + else + add="$dir/$old_library" + fi + elif test -n "$old_library"; then + add="$dir/$old_library" + fi + fi + esac + elif test "$hardcode_minus_L" = no; then + case $host in + *-*-sunos*) add_shlibpath="$dir" ;; + esac + add_dir="-L$dir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = no; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + relink) + if test "$hardcode_direct" = yes && + test "$hardcode_direct_absolute" = no; then + add="$dir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$absdir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test "$lib_linked" != yes; then + func_fatal_configuration "unsupported hardcode properties" + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) func_append compile_shlibpath "$add_shlibpath:" ;; + esac + fi + if test "$linkmode" = prog; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test "$hardcode_direct" != yes && + test "$hardcode_minus_L" != yes && + test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + fi + fi + fi + + if test "$linkmode" = prog || test "$opt_mode" = relink; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test "$hardcode_direct" = yes && + test "$hardcode_direct_absolute" = no; then + add="$libdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$libdir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + add="-l$name" + elif test "$hardcode_automatic" = yes; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib" ; then + add="$inst_prefix_dir$libdir/$linklib" + else + add="$libdir/$linklib" + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir="-L$libdir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + fi + + if test "$linkmode" = prog; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test "$linkmode" = prog; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test "$hardcode_direct" != unsupported; then + test -n "$old_library" && linklib="$old_library" + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test "$build_libtool_libs" = yes; then + # Not a shared library + if test "$deplibs_check_method" != pass_all; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + echo + $ECHO "*** Warning: This system can not link to static lib archive $lib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + if test "$module" = yes; then + echo "*** But as you try to build a module library, libtool will still create " + echo "*** a static module, that should work as long as the dlopening application" + echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test "$linkmode" = lib; then + if test -n "$dependency_libs" && + { test "$hardcode_into_libs" != yes || + test "$build_old_libs" = yes || + test "$link_static" = yes; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) func_stripname '-R' '' "$libdir" + temp_xrpath=$func_stripname_result + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) func_append xrpath " $temp_xrpath";; + esac;; + *) func_append temp_deplibs " $libdir";; + esac + done + dependency_libs="$temp_deplibs" + fi + + func_append newlib_search_path " $absdir" + # Link against this library + test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result";; + *) func_resolve_sysroot "$deplib" ;; + esac + if $opt_preserve_dup_deps ; then + case "$tmp_libs " in + *" $func_resolve_sysroot_result "*) + func_append specialdeplibs " $func_resolve_sysroot_result" ;; + esac + fi + func_append tmp_libs " $func_resolve_sysroot_result" + done + + if test "$link_all_deplibs" != no; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + path= + case $deplib in + -L*) path="$deplib" ;; + *.la) + func_resolve_sysroot "$deplib" + deplib=$func_resolve_sysroot_result + func_dirname "$deplib" "" "." + dir=$func_dirname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + func_warning "cannot determine absolute directory name of \`$dir'" + absdir="$dir" + fi + ;; + esac + if $GREP "^installed=no" $deplib > /dev/null; then + case $host in + *-*-darwin*) + depdepl= + eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names" ; then + for tmp in $deplibrary_names ; do + depdepl=$tmp + done + if test -f "$absdir/$objdir/$depdepl" ; then + depdepl="$absdir/$objdir/$depdepl" + darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -z "$darwin_install_name"; then + darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + fi + func_append compiler_flags " ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" + func_append linker_flags " -dylib_file ${darwin_install_name}:${depdepl}" + path= + fi + fi + ;; + *) + path="-L$absdir/$objdir" + ;; + esac + else + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "\`$deplib' is not a valid libtool archive" + test "$absdir" != "$libdir" && \ + func_warning "\`$deplib' seems to be moved" + + path="-L$absdir" + fi + ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test "$pass" = link; then + if test "$linkmode" = "prog"; then + compile_deplibs="$new_inherited_linker_flags $compile_deplibs" + finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" + else + compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + fi + fi + dependency_libs="$newdependency_libs" + if test "$pass" = dlpreopen; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test "$pass" != dlopen; then + if test "$pass" != conv; then + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) func_append lib_search_path " $dir" ;; + esac + done + newlib_search_path= + fi + + if test "$linkmode,$pass" != "prog,link"; then + vars="deplibs" + else + vars="compile_deplibs finalize_deplibs" + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) func_append tmp_libs " $deplib" ;; + esac + ;; + *) func_append tmp_libs " $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs ; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i="" + ;; + esac + if test -n "$i" ; then + func_append tmp_libs " $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test "$linkmode" = prog; then + dlfiles="$newdlfiles" + fi + if test "$linkmode" = prog || test "$linkmode" = lib; then + dlprefiles="$newdlprefiles" + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + func_warning "\`-dlopen' is ignored for archives" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "\`-l' and \`-L' are ignored for archives" ;; + esac + + test -n "$rpath" && \ + func_warning "\`-rpath' is ignored for archives" + + test -n "$xrpath" && \ + func_warning "\`-R' is ignored for archives" + + test -n "$vinfo" && \ + func_warning "\`-version-info/-version-number' is ignored for archives" + + test -n "$release" && \ + func_warning "\`-release' is ignored for archives" + + test -n "$export_symbols$export_symbols_regex" && \ + func_warning "\`-export-symbols' is ignored for archives" + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs="$output" + func_append objs "$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form `libNAME.la'. + case $outputname in + lib*) + func_stripname 'lib' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + test "$module" = no && \ + func_fatal_help "libtool library \`$output' must begin with \`lib'" + + if test "$need_lib_prefix" != no; then + # Add the "lib" prefix for modules if required + func_stripname '' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + func_stripname '' '.la' "$outputname" + libname=$func_stripname_result + fi + ;; + esac + + if test -n "$objs"; then + if test "$deplibs_check_method" != pass_all; then + func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" + else + echo + $ECHO "*** Warning: Linking the shared library $output against the non-libtool" + $ECHO "*** objects $objs is not portable!" + func_append libobjs " $objs" + fi + fi + + test "$dlself" != no && \ + func_warning "\`-dlopen self' is ignored for libtool libraries" + + set dummy $rpath + shift + test "$#" -gt 1 && \ + func_warning "ignoring multiple \`-rpath's for a libtool library" + + install_libdir="$1" + + oldlibs= + if test -z "$rpath"; then + if test "$build_libtool_libs" = yes; then + # Building a libtool convenience library. + # Some compilers have problems with a `.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + test -n "$vinfo" && \ + func_warning "\`-version-info/-version-number' is ignored for convenience libraries" + + test -n "$release" && \ + func_warning "\`-release' is ignored for convenience libraries" + else + + # Parse the version information argument. + save_ifs="$IFS"; IFS=':' + set dummy $vinfo 0 0 0 + shift + IFS="$save_ifs" + + test -n "$7" && \ + func_fatal_help "too many parameters to \`-version-info'" + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major="$1" + number_minor="$2" + number_revision="$3" + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # which has an extra 1 added just for fun + # + case $version_type in + # correct linux to gnu/linux during the next big refactor + darwin|linux|osf|windows|none) + func_arith $number_major + $number_minor + current=$func_arith_result + age="$number_minor" + revision="$number_revision" + ;; + freebsd-aout|freebsd-elf|qnx|sunos) + current="$number_major" + revision="$number_minor" + age="0" + ;; + irix|nonstopux) + func_arith $number_major + $number_minor + current=$func_arith_result + age="$number_minor" + revision="$number_minor" + lt_irix_increment=no + ;; + *) + func_fatal_configuration "$modename: unknown library version type \`$version_type'" + ;; + esac + ;; + no) + current="$1" + revision="$2" + age="$3" + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "CURRENT \`$current' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "REVISION \`$revision' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "AGE \`$age' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + if test "$age" -gt "$current"; then + func_error "AGE \`$age' is greater than the current interface number \`$current'" + func_fatal_error "\`$vinfo' is not valid version information" + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + func_arith $current - $age + major=.$func_arith_result + versuffix="$major.$age.$revision" + # Darwin ld doesn't like 0 for these options... + func_arith $current + 1 + minor_current=$func_arith_result + xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + + freebsd-aout) + major=".$current" + versuffix=".$current.$revision"; + ;; + + freebsd-elf) + major=".$current" + versuffix=".$current" + ;; + + irix | nonstopux) + if test "X$lt_irix_increment" = "Xno"; then + func_arith $current - $age + else + func_arith $current - $age + 1 + fi + major=$func_arith_result + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring="$verstring_prefix$major.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test "$loop" -ne 0; do + func_arith $revision - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring="$verstring_prefix$major.$iface:$verstring" + done + + # Before this point, $major must not contain `.'. + major=.$major + versuffix="$major.$revision" + ;; + + linux) # correct to gnu/linux during the next big refactor + func_arith $current - $age + major=.$func_arith_result + versuffix="$major.$age.$revision" + ;; + + osf) + func_arith $current - $age + major=.$func_arith_result + versuffix=".$current.$age.$revision" + verstring="$current.$age.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$age + while test "$loop" -ne 0; do + func_arith $current - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring="$verstring:${iface}.0" + done + + # Make executables depend on our current version. + func_append verstring ":${current}.0" + ;; + + qnx) + major=".$current" + versuffix=".$current" + ;; + + sunos) + major=".$current" + versuffix=".$current.$revision" + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 filesystems. + func_arith $current - $age + major=$func_arith_result + versuffix="-$major" + ;; + + *) + func_fatal_configuration "unknown library version type \`$version_type'" + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring="0.0" + ;; + esac + if test "$need_version" = no; then + versuffix= + else + versuffix=".0.0" + fi + fi + + # Remove version info from name if versioning should be avoided + if test "$avoid_version" = yes && test "$need_version" = no; then + major= + versuffix= + verstring="" + fi + + # Check to see if the archive will have undefined symbols. + if test "$allow_undefined" = yes; then + if test "$allow_undefined_flag" = unsupported; then + func_warning "undefined symbols not allowed in $host shared libraries" + build_libtool_libs=no + build_old_libs=yes + fi + else + # Don't allow undefined symbols. + allow_undefined_flag="$no_undefined_flag" + fi + + fi + + func_generate_dlsyms "$libname" "$libname" "yes" + func_append libobjs " $symfileobj" + test "X$libobjs" = "X " && libobjs= + + if test "$opt_mode" != relink; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$ECHO "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext | *.gcno) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) + if test "X$precious_files_regex" != "X"; then + if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + func_append removelist " $p" + ;; + *) ;; + esac + done + test -n "$removelist" && \ + func_show_eval "${RM}r \$removelist" + fi + + # Now set the variables for building old libraries. + if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then + func_append oldlibs " $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + #for path in $notinst_path; do + # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` + # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` + # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` + #done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + func_replace_sysroot "$libdir" + func_append temp_xrpath " -R$func_replace_sysroot_result" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles="$dlfiles" + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) func_append dlfiles " $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles="$dlprefiles" + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) func_append dlprefiles " $lib" ;; + esac + done + + if test "$build_libtool_libs" = yes; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + func_append deplibs " System.ltframework" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test "$build_libtool_need_lc" = "yes"; then + func_append deplibs " -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release="" + versuffix="" + major="" + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $opt_dry_run || $RM conftest.c + cat > conftest.c </dev/null` + $nocaseglob + else + potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` + fi + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null | + $GREP " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib="$potent_lib" + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; + *) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | + $SED -e 10q | + $EGREP "$file_magic_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $ECHO "*** with $libname but no candidates were found. (...for file magic test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a file magic. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $a_deplib "*) + func_append newdeplibs " $a_deplib" + a_deplib="" + ;; + esac + fi + if test -n "$a_deplib" ; then + libname=`eval "\\$ECHO \"$libname_spec\""` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib="$potent_lib" # see symlink-check above in file_magic test + if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ + $EGREP "$match_pattern_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a regex pattern. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs="" + tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + for i in $predeps $postdeps ; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"` + done + fi + case $tmp_deplibs in + *[!\ \ ]*) + echo + if test "X$deplibs_check_method" = "Xnone"; then + echo "*** Warning: inter-library dependencies are not supported in this platform." + else + echo "*** Warning: inter-library dependencies are not known to be supported." + fi + echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + ;; + esac + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library with the System framework + newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + if test "$droppeddeps" = yes; then + if test "$module" = yes; then + echo + echo "*** Warning: libtool could not satisfy all declared inter-library" + $ECHO "*** dependencies of module $libname. Therefore, libtool will create" + echo "*** a static module, that should work as long as the dlopening" + echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + echo "*** The inter-library dependencies that have been dropped here will be" + echo "*** automatically added whenever a program is linked with this library" + echo "*** or is declared to -dlopen it." + + if test "$allow_undefined" = no; then + echo + echo "*** Since this library must not contain undefined symbols," + echo "*** because either the platform does not support them or" + echo "*** it was explicitly requested with -no-undefined," + echo "*** libtool will only create a static version of it." + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + case $host in + *-*-darwin*) + newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + deplibs="$new_libs" + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test "$build_libtool_libs" = yes; then + # Remove ${wl} instances when linking with ld. + # FIXME: should test the right _cmds variable. + case $archive_cmds in + *\$LD\ *) wl= ;; + esac + if test "$hardcode_into_libs" = yes; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath="$finalize_rpath" + test "$opt_mode" != relink && rpath="$compile_rpath$rpath" + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + func_replace_sysroot "$libdir" + libdir=$func_replace_sysroot_result + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append dep_rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath="$finalize_shlibpath" + test "$opt_mode" != relink && shlibpath="$compile_shlibpath$shlibpath" + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + shift + realname="$1" + shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib="$output_objdir/$realname" + linknames= + for link + do + func_append linknames " $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` + test "X$libobjs" = "X " && libobjs= + + delfiles= + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" + export_symbols="$output_objdir/$libname.uexp" + func_append delfiles " $export_symbols" + fi + + orig_export_symbols= + case $host_os in + cygwin* | mingw* | cegcc*) + if test -n "$export_symbols" && test -z "$export_symbols_regex"; then + # exporting using user supplied symfile + if test "x`$SED 1q $export_symbols`" != xEXPORTS; then + # and it's NOT already a .def file. Must figure out + # which of the given symbols are data symbols and tag + # them as such. So, trigger use of export_symbols_cmds. + # export_symbols gets reassigned inside the "prepare + # the list of exported symbols" if statement, so the + # include_expsyms logic still works. + orig_export_symbols="$export_symbols" + export_symbols= + always_export_symbols=yes + fi + fi + ;; + esac + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $opt_dry_run || $RM $export_symbols + cmds=$export_symbols_cmds + save_ifs="$IFS"; IFS='~' + for cmd1 in $cmds; do + IFS="$save_ifs" + # Take the normal branch if the nm_file_list_spec branch + # doesn't work or if tool conversion is not needed. + case $nm_file_list_spec~$to_tool_file_cmd in + *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) + try_normal_branch=yes + eval cmd=\"$cmd1\" + func_len " $cmd" + len=$func_len_result + ;; + *) + try_normal_branch=no + ;; + esac + if test "$try_normal_branch" = yes \ + && { test "$len" -lt "$max_cmd_len" \ + || test "$max_cmd_len" -le -1; } + then + func_show_eval "$cmd" 'exit $?' + skipped_export=false + elif test -n "$nm_file_list_spec"; then + func_basename "$output" + output_la=$func_basename_result + save_libobjs=$libobjs + save_output=$output + output=${output_objdir}/${output_la}.nm + func_to_tool_file "$output" + libobjs=$nm_file_list_spec$func_to_tool_file_result + func_append delfiles " $output" + func_verbose "creating $NM input file list: $output" + for obj in $save_libobjs; do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > "$output" + eval cmd=\"$cmd1\" + func_show_eval "$cmd" 'exit $?' + output=$save_output + libobjs=$save_libobjs + skipped_export=false + else + # The command line is too long to execute in one step. + func_verbose "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS="$save_ifs" + if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols="$export_symbols" + test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + func_append tmp_deplibs " $test_deplib" + ;; + esac + done + deplibs="$tmp_deplibs" + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec" && + test "$compiler_needs_object" = yes && + test -z "$libobjs"; then + # extract the archives, so we have objects to list. + # TODO: could optimize this to just extract one archive. + whole_archive_flag_spec= + fi + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + else + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + fi + + if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + func_append linker_flags " $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test "$opt_mode" = relink; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test "X$skipped_export" != "X:" && + func_len " $test_cmds" && + len=$func_len_result && + test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise + # or, if using GNU ld and skipped_export is not :, use a linker + # script. + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + func_basename "$output" + output_la=$func_basename_result + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + last_robj= + k=1 + + if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then + output=${output_objdir}/${output_la}.lnkscript + func_verbose "creating GNU ld script: $output" + echo 'INPUT (' > $output + for obj in $save_libobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + echo ')' >> $output + func_append delfiles " $output" + func_to_tool_file "$output" + output=$func_to_tool_file_result + elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then + output=${output_objdir}/${output_la}.lnk + func_verbose "creating linker input file list: $output" + : > $output + set x $save_libobjs + shift + firstobj= + if test "$compiler_needs_object" = yes; then + firstobj="$1 " + shift + fi + for obj + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + func_append delfiles " $output" + func_to_tool_file "$output" + output=$firstobj\"$file_list_spec$func_to_tool_file_result\" + else + if test -n "$save_libobjs"; then + func_verbose "creating reloadable object files..." + output=$output_objdir/$output_la-${k}.$objext + eval test_cmds=\"$reload_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + if test "X$objlist" = X || + test "$len" -lt "$max_cmd_len"; then + func_append objlist " $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test "$k" -eq 1 ; then + # The first file doesn't have a previous command to add. + reload_objs=$objlist + eval concat_cmds=\"$reload_cmds\" + else + # All subsequent reloadable object files will link in + # the last one created. + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" + fi + last_robj=$output_objdir/$output_la-${k}.$objext + func_arith $k + 1 + k=$func_arith_result + output=$output_objdir/$output_la-${k}.$objext + objlist=" $obj" + func_len " $last_robj" + func_arith $len0 + $func_len_result + len=$func_arith_result + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\${concat_cmds}$reload_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" + fi + func_append delfiles " $output" + + else + output= + fi + + if ${skipped_export-false}; then + func_verbose "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $opt_dry_run || $RM $export_symbols + libobjs=$output + # Append the command to create the export file. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + fi + + test -n "$save_libobjs" && + func_verbose "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs="$IFS"; IFS='~' + for cmd in $concat_cmds; do + IFS="$save_ifs" + $opt_silent || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$opt_mode" = relink; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + if test -n "$export_symbols_regex" && ${skipped_export-false}; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + + if ${skipped_export-false}; then + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols="$export_symbols" + test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + fi + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + fi + + if test -n "$delfiles"; then + # Append the command to remove temporary files to $cmds. + eval cmds=\"\$cmds~\$RM $delfiles\" + fi + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $opt_silent || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$opt_mode" = relink; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + # Restore the uninstalled library and exit + if test "$opt_mode" = relink; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + func_show_eval '${RM}r "$gentop"' + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test "$module" = yes || test "$export_dynamic" = yes; then + # On all known operating systems, these are identical. + dlname="$soname" + fi + fi + ;; + + obj) + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + func_warning "\`-dlopen' is ignored for objects" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "\`-l' and \`-L' are ignored for objects" ;; + esac + + test -n "$rpath" && \ + func_warning "\`-rpath' is ignored for objects" + + test -n "$xrpath" && \ + func_warning "\`-R' is ignored for objects" + + test -n "$vinfo" && \ + func_warning "\`-version-info' is ignored for objects" + + test -n "$release" && \ + func_warning "\`-release' is ignored for objects" + + case $output in + *.lo) + test -n "$objs$old_deplibs" && \ + func_fatal_error "cannot build library object \`$output' from non-libtool objects" + + libobj=$output + func_lo2o "$libobj" + obj=$func_lo2o_result + ;; + *) + libobj= + obj="$output" + ;; + esac + + # Delete the old objects. + $opt_dry_run || $RM $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # reload_cmds runs $LD directly, so let us get rid of + # -Wl from whole_archive_flag_spec and hope we can get by with + # turning comma into space.. + wl= + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" + reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` + else + gentop="$output_objdir/${obj}x" + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # If we're not building shared, we need to use non_pic_objs + test "$build_libtool_libs" != yes && libobjs="$non_pic_objects" + + # Create the old-style object. + reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test + + output="$obj" + func_execute_cmds "$reload_cmds" 'exit $?' + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + fi + + if test "$build_libtool_libs" != yes; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + fi + + if test -n "$pic_flag" || test "$pic_mode" != default; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output="$libobj" + func_execute_cmds "$reload_cmds" 'exit $?' + fi + + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) func_stripname '' '.exe' "$output" + output=$func_stripname_result.exe;; + esac + test -n "$vinfo" && \ + func_warning "\`-version-info' is ignored for programs" + + test -n "$release" && \ + func_warning "\`-release' is ignored for programs" + + test "$preload" = yes \ + && test "$dlopen_support" = unknown \ + && test "$dlopen_self" = unknown \ + && test "$dlopen_self_static" = unknown && \ + func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + case $host in + *-*-darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + # But is supposedly fixed on 10.4 or later (yay!). + if test "$tagname" = CXX ; then + case ${MACOSX_DEPLOYMENT_TARGET-10.0} in + 10.[0123]) + func_append compile_command " ${wl}-bind_at_load" + func_append finalize_command " ${wl}-bind_at_load" + ;; + esac + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + compile_deplibs="$new_libs" + + + func_append compile_command " $compile_deplibs" + func_append finalize_command " $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + ::) dllsearchpath=$libdir;; + *) func_append dllsearchpath ":$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath="$rpath" + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) func_append finalize_perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath="$rpath" + + if test -n "$libobjs" && test "$build_old_libs" = yes; then + # Transform all the library objects into standard objects. + compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + fi + + func_generate_dlsyms "$outputname" "@PROGRAM@" "no" + + # template prelinking step + if test -n "$prelink_cmds"; then + func_execute_cmds "$prelink_cmds" 'exit $?' + fi + + wrappers_required=yes + case $host in + *cegcc* | *mingw32ce*) + # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. + wrappers_required=no + ;; + *cygwin* | *mingw* ) + if test "$build_libtool_libs" != yes; then + wrappers_required=no + fi + ;; + *) + if test "$need_relink" = no || test "$build_libtool_libs" != yes; then + wrappers_required=no + fi + ;; + esac + if test "$wrappers_required" = no; then + # Replace the output file specification. + compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + link_command="$compile_command$compile_rpath" + + # We have no uninstalled library dependencies, so finalize right now. + exit_status=0 + func_show_eval "$link_command" 'exit_status=$?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Delete the generated files. + if test -f "$output_objdir/${outputname}S.${objext}"; then + func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' + fi + + exit $exit_status + fi + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + func_append rpath "$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test "$no_install" = yes; then + # We don't need to create a wrapper script. + link_command="$compile_var$compile_command$compile_rpath" + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $opt_dry_run || $RM $output + # Link the executable and exit + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + exit $EXIT_SUCCESS + fi + + if test "$hardcode_action" = relink; then + # Fast installation is not supported + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + + func_warning "this platform does not like uninstalled shared libraries" + func_warning "\`$output' will be relinked during installation" + else + if test "$fast_install" != no; then + link_command="$finalize_var$compile_command$finalize_rpath" + if test "$fast_install" = yes; then + relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` + else + # fast_install is set to needless + relink_command= + fi + else + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + fi + fi + + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname + + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output_objdir/$outputname" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Now create the wrapper script. + func_verbose "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + fi + + # Only actually do things if not in dry run mode. + $opt_dry_run || { + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) func_stripname '' '.exe' "$output" + output=$func_stripname_result ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + func_stripname '' '.exe' "$outputname" + outputname=$func_stripname_result ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + func_dirname_and_basename "$output" "" "." + output_name=$func_basename_result + output_path=$func_dirname_result + cwrappersource="$output_path/$objdir/lt-$output_name.c" + cwrapper="$output_path/$output_name.exe" + $RM $cwrappersource $cwrapper + trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + func_emit_cwrapperexe_src > $cwrappersource + + # The wrapper executable is built using the $host compiler, + # because it contains $host paths and files. If cross- + # compiling, it, like the target executable, must be + # executed on the $host or under an emulation environment. + $opt_dry_run || { + $LTCC $LTCFLAGS -o $cwrapper $cwrappersource + $STRIP $cwrapper + } + + # Now, create the wrapper script for func_source use: + func_ltwrapper_scriptname $cwrapper + $RM $func_ltwrapper_scriptname_result + trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 + $opt_dry_run || { + # note: this script will not be executed, so do not chmod. + if test "x$build" = "x$host" ; then + $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result + else + func_emit_wrapper no > $func_ltwrapper_scriptname_result + fi + } + ;; + * ) + $RM $output + trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 + + func_emit_wrapper no > $output + chmod +x $output + ;; + esac + } + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + if test "$build_libtool_libs" = convenience; then + oldobjs="$libobjs_save $symfileobj" + addlibs="$convenience" + build_libtool_libs=no + else + if test "$build_libtool_libs" = module; then + oldobjs="$libobjs_save" + build_libtool_libs=no + else + oldobjs="$old_deplibs $non_pic_objects" + if test "$preload" = yes && test -f "$symfileobj"; then + func_append oldobjs " $symfileobj" + fi + fi + addlibs="$old_convenience" + fi + + if test -n "$addlibs"; then + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $addlibs + func_append oldobjs " $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then + cmds=$old_archive_from_new_cmds + else + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append oldobjs " $func_extract_archives_result" + fi + + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + func_basename "$obj" + $ECHO "$func_basename_result" + done | sort | sort -uc >/dev/null 2>&1); then + : + else + echo "copying selected object files to avoid basename conflicts..." + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + func_mkdir_p "$gentop" + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + func_basename "$obj" + objbase="$func_basename_result" + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + func_arith $counter + 1 + counter=$func_arith_result + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + func_append oldobjs " $gentop/$newobj" + ;; + *) func_append oldobjs " $obj" ;; + esac + done + fi + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + eval cmds=\"$old_archive_cmds\" + + func_len " $cmds" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + elif test -n "$archiver_list_spec"; then + func_verbose "using command file archive linking..." + for obj in $oldobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > $output_objdir/$libname.libcmd + func_to_tool_file "$output_objdir/$libname.libcmd" + oldobjs=" $archiver_list_spec$func_to_tool_file_result" + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + func_verbose "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + oldobjs= + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + eval test_cmds=\"$old_archive_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + for obj in $save_oldobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + func_append objlist " $obj" + if test "$len" -lt "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj" ; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" + objlist= + len=$len0 + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test "X$oldobjs" = "X" ; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + func_execute_cmds "$cmds" 'exit $?' + done + + test -n "$generated" && \ + func_show_eval "${RM}r$generated" + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test "$build_old_libs" = yes && old_library="$libname.$libext" + func_verbose "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + if test "$hardcode_automatic" = yes ; then + relink_command= + fi + + # Only create the output if not a dry run. + $opt_dry_run || { + for installed in no yes; do + if test "$installed" = yes; then + if test -z "$install_libdir"; then + break + fi + output="$output_objdir/$outputname"i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + func_basename "$deplib" + name="$func_basename_result" + func_resolve_sysroot "$deplib" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` + test -z "$libdir" && \ + func_fatal_error "\`$deplib' is not a valid libtool archive" + func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" + ;; + -L*) + func_stripname -L '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -L$func_replace_sysroot_result" + ;; + -R*) + func_stripname -R '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -R$func_replace_sysroot_result" + ;; + *) func_append newdependency_libs " $deplib" ;; + esac + done + dependency_libs="$newdependency_libs" + newdlfiles= + + for lib in $dlfiles; do + case $lib in + *.la) + func_basename "$lib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "\`$lib' is not a valid libtool archive" + func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" + ;; + *) func_append newdlfiles " $lib" ;; + esac + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + *.la) + # Only pass preopened files to the pseudo-archive (for + # eventual linking with the app. that links it) if we + # didn't already link the preopened objects directly into + # the library: + func_basename "$lib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "\`$lib' is not a valid libtool archive" + func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" + ;; + esac + done + dlprefiles="$newdlprefiles" + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlfiles " $abs" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlprefiles " $abs" + done + dlprefiles="$newdlprefiles" + fi + $RM $output + # place dlname in correct position for cygwin + # In fact, it would be nice if we could use this code for all target + # systems that can't hard-code library paths into their executables + # and that have no shared library path variable independent of PATH, + # but it turns out we can't easily determine that from inspecting + # libtool variables, so we have to hard-code the OSs to which it + # applies here; at the moment, that means platforms that use the PE + # object format with DLL files. See the long comment at the top of + # tests/bindir.at for full details. + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) + # If a -bindir argument was supplied, place the dll there. + if test "x$bindir" != x ; + then + func_relative_path "$install_libdir" "$bindir" + tdlname=$func_relative_path_result$dlname + else + # Otherwise fall back on heuristic. + tdlname=../bin/$dlname + fi + ;; + esac + $ECHO > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Linker flags that can not go in dependency_libs. +inherited_linker_flags='$new_inherited_linker_flags' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Names of additional weak libraries provided by this library +weak_library_names='$weak_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test "$installed" = no && test "$need_relink" = yes; then + $ECHO >> $output "\ +relink_command=\"$relink_command\"" + fi + done + } + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' + ;; + esac + exit $EXIT_SUCCESS +} + +{ test "$opt_mode" = link || test "$opt_mode" = relink; } && + func_mode_link ${1+"$@"} + + +# func_mode_uninstall arg... +func_mode_uninstall () +{ + $opt_debug + RM="$nonopt" + files= + rmforce= + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + for arg + do + case $arg in + -f) func_append RM " $arg"; rmforce=yes ;; + -*) func_append RM " $arg" ;; + *) func_append files " $arg" ;; + esac + done + + test -z "$RM" && \ + func_fatal_help "you must specify an RM program" + + rmdirs= + + for file in $files; do + func_dirname "$file" "" "." + dir="$func_dirname_result" + if test "X$dir" = X.; then + odir="$objdir" + else + odir="$dir/$objdir" + fi + func_basename "$file" + name="$func_basename_result" + test "$opt_mode" = uninstall && odir="$dir" + + # Remember odir for removal later, being careful to avoid duplicates + if test "$opt_mode" = clean; then + case " $rmdirs " in + *" $odir "*) ;; + *) func_append rmdirs " $odir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if { test -L "$file"; } >/dev/null 2>&1 || + { test -h "$file"; } >/dev/null 2>&1 || + test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif test "$rmforce" = yes; then + continue + fi + + rmfiles="$file" + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if func_lalib_p "$file"; then + func_source $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + func_append rmfiles " $odir/$n" + done + test -n "$old_library" && func_append rmfiles " $odir/$old_library" + + case "$opt_mode" in + clean) + case " $library_names " in + *" $dlname "*) ;; + *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; + esac + test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if func_lalib_p "$file"; then + + # Read the .lo file + func_source $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" && + test "$pic_object" != none; then + func_append rmfiles " $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" && + test "$non_pic_object" != none; then + func_append rmfiles " $dir/$non_pic_object" + fi + fi + ;; + + *) + if test "$opt_mode" = clean ; then + noexename=$name + case $file in + *.exe) + func_stripname '' '.exe' "$file" + file=$func_stripname_result + func_stripname '' '.exe' "$name" + noexename=$func_stripname_result + # $file with .exe has already been added to rmfiles, + # add $file without .exe + func_append rmfiles " $file" + ;; + esac + # Do a test to see if this is a libtool program. + if func_ltwrapper_p "$file"; then + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + relink_command= + func_source $func_ltwrapper_scriptname_result + func_append rmfiles " $func_ltwrapper_scriptname_result" + else + relink_command= + func_source $dir/$noexename + fi + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + func_append rmfiles " $odir/$name $odir/${name}S.${objext}" + if test "$fast_install" = yes && test -n "$relink_command"; then + func_append rmfiles " $odir/lt-$name" + fi + if test "X$noexename" != "X$name" ; then + func_append rmfiles " $odir/lt-${noexename}.c" + fi + fi + fi + ;; + esac + func_show_eval "$RM $rmfiles" 'exit_status=1' + done + + # Try to remove the ${objdir}s in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + func_show_eval "rmdir $dir >/dev/null 2>&1" + fi + done + + exit $exit_status +} + +{ test "$opt_mode" = uninstall || test "$opt_mode" = clean; } && + func_mode_uninstall ${1+"$@"} + +test -z "$opt_mode" && { + help="$generic_help" + func_fatal_help "you must specify a MODE" +} + +test -z "$exec_cmd" && \ + func_fatal_help "invalid operation mode \`$opt_mode'" + +if test -n "$exec_cmd"; then + eval exec "$exec_cmd" + exit $EXIT_FAILURE +fi + +exit $exit_status + + +# The TAGs below are defined such that we never get into a situation +# in which we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +build_libtool_libs=no +build_old_libs=yes +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: +# vi:sw=2 + diff --git a/net.c b/net.c new file mode 100644 index 00000000000..870511a75b2 --- /dev/null +++ b/net.c @@ -0,0 +1,907 @@ +/* + * net.c + * + * Network implementation + * All network related functions are grouped here + * + * a Net::DNS like library for C + * + * (c) NLnet Labs, 2004-2006 + * + * See the file LICENSE for the license + */ + +#include + +#include + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#include +#include +#include + +ldns_status +ldns_send(ldns_pkt **result_packet, ldns_resolver *r, const ldns_pkt *query_pkt) +{ + ldns_buffer *qb; + ldns_status result; + ldns_rdf *tsig_mac = NULL; + + qb = ldns_buffer_new(LDNS_MIN_BUFLEN); + + if (query_pkt && ldns_pkt_tsig(query_pkt)) { + tsig_mac = ldns_rr_rdf(ldns_pkt_tsig(query_pkt), 3); + } + + if (!query_pkt || + ldns_pkt2buffer_wire(qb, query_pkt) != LDNS_STATUS_OK) { + result = LDNS_STATUS_ERR; + } else { + result = ldns_send_buffer(result_packet, r, qb, tsig_mac); + } + + ldns_buffer_free(qb); + + return result; +} + +ldns_status +ldns_send_buffer(ldns_pkt **result, ldns_resolver *r, ldns_buffer *qb, ldns_rdf *tsig_mac) +{ + uint8_t i; + + struct sockaddr_storage *ns; + size_t ns_len; + struct timeval tv_s; + struct timeval tv_e; + + ldns_rdf **ns_array; + size_t *rtt; + ldns_pkt *reply; + bool all_servers_rtt_inf; + uint8_t retries; + + uint8_t *reply_bytes = NULL; + size_t reply_size = 0; + ldns_status status, send_status; + + assert(r != NULL); + + status = LDNS_STATUS_OK; + rtt = ldns_resolver_rtt(r); + ns_array = ldns_resolver_nameservers(r); + reply = NULL; + ns_len = 0; + + all_servers_rtt_inf = true; + + if (ldns_resolver_random(r)) { + ldns_resolver_nameservers_randomize(r); + } + + /* loop through all defined nameservers */ + for (i = 0; i < ldns_resolver_nameserver_count(r); i++) { + if (rtt[i] == LDNS_RESOLV_RTT_INF) { + /* not reachable nameserver! */ + continue; + } + + /* maybe verbosity setting? + printf("Sending to "); + ldns_rdf_print(stdout, ns_array[i]); + printf("\n"); + */ + ns = ldns_rdf2native_sockaddr_storage(ns_array[i], + ldns_resolver_port(r), &ns_len); + + +#ifndef S_SPLINT_S + if ((ns->ss_family == AF_INET) && + (ldns_resolver_ip6(r) == LDNS_RESOLV_INET6)) { + /* not reachable */ + continue; + } + + if ((ns->ss_family == AF_INET6) && + (ldns_resolver_ip6(r) == LDNS_RESOLV_INET)) { + /* not reachable */ + continue; + } +#endif + + all_servers_rtt_inf = false; + + gettimeofday(&tv_s, NULL); + + send_status = LDNS_STATUS_ERR; + + /* reply_bytes implicitly handles our error */ + if (1 == ldns_resolver_usevc(r)) { + for (retries = ldns_resolver_retry(r); retries > 0; retries--) { + send_status = + ldns_tcp_send(&reply_bytes, qb, ns, + (socklen_t)ns_len, ldns_resolver_timeout(r), + &reply_size); + if (send_status == LDNS_STATUS_OK) { + break; + } + } + } else { + for (retries = ldns_resolver_retry(r); retries > 0; retries--) { + /* ldns_rdf_print(stdout, ns_array[i]); */ + send_status = + ldns_udp_send(&reply_bytes, qb, ns, + (socklen_t)ns_len, ldns_resolver_timeout(r), + &reply_size); + + if (send_status == LDNS_STATUS_OK) { + break; + } + } + } + + if (send_status != LDNS_STATUS_OK) { + ldns_resolver_set_nameserver_rtt(r, i, LDNS_RESOLV_RTT_INF); + status = send_status; + } + + /* obey the fail directive */ + if (!reply_bytes) { + /* the current nameserver seems to have a problem, blacklist it */ + if (ldns_resolver_fail(r)) { + LDNS_FREE(ns); + return LDNS_STATUS_ERR; + } else { + LDNS_FREE(ns); + continue; + } + } + + status = ldns_wire2pkt(&reply, reply_bytes, reply_size); + if (status != LDNS_STATUS_OK) { + LDNS_FREE(reply_bytes); + LDNS_FREE(ns); + return status; + } + + LDNS_FREE(ns); + gettimeofday(&tv_e, NULL); + + if (reply) { + ldns_pkt_set_querytime(reply, (uint32_t) + ((tv_e.tv_sec - tv_s.tv_sec) * 1000) + + (tv_e.tv_usec - tv_s.tv_usec) / 1000); + ldns_pkt_set_answerfrom(reply, ns_array[i]); + ldns_pkt_set_timestamp(reply, tv_s); + ldns_pkt_set_size(reply, reply_size); + break; + } else { + if (ldns_resolver_fail(r)) { + /* if fail is set bail out, after the first + * one */ + break; + } + } + + /* wait retrans seconds... */ + sleep((unsigned int) ldns_resolver_retrans(r)); + } + + if (all_servers_rtt_inf) { + LDNS_FREE(reply_bytes); + return LDNS_STATUS_RES_NO_NS; + } +#ifdef HAVE_SSL + if (tsig_mac && reply_bytes) { + if (!ldns_pkt_tsig_verify(reply, + reply_bytes, + reply_size, + ldns_resolver_tsig_keyname(r), + ldns_resolver_tsig_keydata(r), tsig_mac)) { + status = LDNS_STATUS_CRYPTO_TSIG_BOGUS; + } + } +#else + (void)tsig_mac; +#endif /* HAVE_SSL */ + + LDNS_FREE(reply_bytes); + if (result) { + *result = reply; + } + + return status; +} + +/** best effort to set nonblocking */ +static void +ldns_sock_nonblock(int sockfd) +{ +#ifdef HAVE_FCNTL + int flag; + if((flag = fcntl(sockfd, F_GETFL)) != -1) { + flag |= O_NONBLOCK; + if(fcntl(sockfd, F_SETFL, flag) == -1) { + /* ignore error, continue blockingly */ + } + } +#elif defined(HAVE_IOCTLSOCKET) + unsigned long on = 1; + if(ioctlsocket(sockfd, FIONBIO, &on) != 0) { + /* ignore error, continue blockingly */ + } +#endif +} + +/** best effort to set blocking */ +static void +ldns_sock_block(int sockfd) +{ +#ifdef HAVE_FCNTL + int flag; + if((flag = fcntl(sockfd, F_GETFL)) != -1) { + flag &= ~O_NONBLOCK; + if(fcntl(sockfd, F_SETFL, flag) == -1) { + /* ignore error, continue */ + } + } +#elif defined(HAVE_IOCTLSOCKET) + unsigned long off = 0; + if(ioctlsocket(sockfd, FIONBIO, &off) != 0) { + /* ignore error, continue */ + } +#endif +} + +/** wait for a socket to become ready */ +static int +ldns_sock_wait(int sockfd, struct timeval timeout, int write) +{ + int ret; +#ifndef S_SPLINT_S + fd_set fds; + FD_ZERO(&fds); + FD_SET(FD_SET_T sockfd, &fds); + if(write) + ret = select(sockfd+1, NULL, &fds, NULL, &timeout); + else + ret = select(sockfd+1, &fds, NULL, NULL, &timeout); +#endif + if(ret == 0) + /* timeout expired */ + return 0; + else if(ret == -1) + /* error */ + return 0; + return 1; +} + +ldns_status +ldns_udp_send(uint8_t **result, ldns_buffer *qbin, const struct sockaddr_storage *to, + socklen_t tolen, struct timeval timeout, size_t *answer_size) +{ + int sockfd; + uint8_t *answer; + + sockfd = ldns_udp_bgsend(qbin, to, tolen, timeout); + + if (sockfd == 0) { + return LDNS_STATUS_SOCKET_ERROR; + } + + /* wait for an response*/ + if(!ldns_sock_wait(sockfd, timeout, 0)) { +#ifndef USE_WINSOCK + close(sockfd); +#else + closesocket(sockfd); +#endif + return LDNS_STATUS_NETWORK_ERR; + } + + /* set to nonblocking, so if the checksum is bad, it becomes + * an EGAIN error and the ldns_udp_send function does not block, + * but returns a 'NETWORK_ERROR' much like a timeout. */ + ldns_sock_nonblock(sockfd); + + answer = ldns_udp_read_wire(sockfd, answer_size, NULL, NULL); +#ifndef USE_WINSOCK + close(sockfd); +#else + closesocket(sockfd); +#endif + + if (*answer_size == 0) { + /* oops */ + return LDNS_STATUS_NETWORK_ERR; + } + + *result = answer; + return LDNS_STATUS_OK; +} + +int +ldns_udp_bgsend(ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen, + struct timeval timeout) +{ + int sockfd; + + sockfd = ldns_udp_connect(to, timeout); + + if (sockfd == 0) { + return 0; + } + + if (ldns_udp_send_query(qbin, sockfd, to, tolen) == 0) { +#ifndef USE_WINSOCK + close(sockfd); +#else + closesocket(sockfd); +#endif + return 0; + } + return sockfd; +} + +int +ldns_udp_connect(const struct sockaddr_storage *to, struct timeval ATTR_UNUSED(timeout)) +{ + int sockfd; + +#ifndef S_SPLINT_S + if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_DGRAM, + IPPROTO_UDP)) + == -1) { + return 0; + } +#endif + return sockfd; +} + +int +ldns_tcp_connect(const struct sockaddr_storage *to, socklen_t tolen, + struct timeval timeout) +{ + int sockfd; + +#ifndef S_SPLINT_S + if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_STREAM, + IPPROTO_TCP)) == -1) { + return 0; + } +#endif + + /* perform nonblocking connect, to be able to wait with select() */ + ldns_sock_nonblock(sockfd); + if (connect(sockfd, (struct sockaddr*)to, tolen) == -1) { +#ifndef USE_WINSOCK +#ifdef EINPROGRESS + if(errno != EINPROGRESS) { +#else + if(1) { +#endif + close(sockfd); + return 0; + } +#else /* USE_WINSOCK */ + if(WSAGetLastError() != WSAEINPROGRESS && + WSAGetLastError() != WSAEWOULDBLOCK) { + closesocket(sockfd); + return 0; + } +#endif + /* error was only telling us that it would block */ + } + + /* wait(write) until connected or error */ + while(1) { + int error = 0; + socklen_t len = (socklen_t)sizeof(error); + + if(!ldns_sock_wait(sockfd, timeout, 1)) { +#ifndef USE_WINSOCK + close(sockfd); +#else + closesocket(sockfd); +#endif + return 0; + } + + /* check if there is a pending error for nonblocking connect */ + if(getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void*)&error, + &len) < 0) { +#ifndef USE_WINSOCK + error = errno; /* on solaris errno is error */ +#else + error = WSAGetLastError(); +#endif + } +#ifndef USE_WINSOCK +#if defined(EINPROGRESS) && defined(EWOULDBLOCK) + if(error == EINPROGRESS || error == EWOULDBLOCK) + continue; /* try again */ +#endif + else if(error != 0) { + close(sockfd); + /* error in errno for our user */ + errno = error; + return 0; + } +#else /* USE_WINSOCK */ + if(error == WSAEINPROGRESS) + continue; + else if(error == WSAEWOULDBLOCK) + continue; + else if(error != 0) { + closesocket(sockfd); + errno = error; + return 0; + } +#endif /* USE_WINSOCK */ + /* connected */ + break; + } + + /* set the socket blocking again */ + ldns_sock_block(sockfd); + + return sockfd; +} + +ssize_t +ldns_tcp_send_query(ldns_buffer *qbin, int sockfd, + const struct sockaddr_storage *to, socklen_t tolen) +{ + uint8_t *sendbuf; + ssize_t bytes; + + /* add length of packet */ + sendbuf = LDNS_XMALLOC(uint8_t, ldns_buffer_position(qbin) + 2); + if(!sendbuf) return 0; + ldns_write_uint16(sendbuf, ldns_buffer_position(qbin)); + memcpy(sendbuf + 2, ldns_buffer_export(qbin), ldns_buffer_position(qbin)); + + bytes = sendto(sockfd, (void*)sendbuf, + ldns_buffer_position(qbin) + 2, 0, (struct sockaddr *)to, tolen); + + LDNS_FREE(sendbuf); + + if (bytes == -1 || (size_t) bytes != ldns_buffer_position(qbin) + 2 ) { + return 0; + } + return bytes; +} + +/* don't wait for an answer */ +ssize_t +ldns_udp_send_query(ldns_buffer *qbin, int sockfd, const struct sockaddr_storage *to, + socklen_t tolen) +{ + ssize_t bytes; + + bytes = sendto(sockfd, (void*)ldns_buffer_begin(qbin), + ldns_buffer_position(qbin), 0, (struct sockaddr *)to, tolen); + + if (bytes == -1 || (size_t)bytes != ldns_buffer_position(qbin)) { + return 0; + } + if ((size_t) bytes != ldns_buffer_position(qbin)) { + return 0; + } + return bytes; +} + +uint8_t * +ldns_udp_read_wire(int sockfd, size_t *size, struct sockaddr_storage *from, + socklen_t *fromlen) +{ + uint8_t *wire, *wireout; + ssize_t wire_size; + + wire = LDNS_XMALLOC(uint8_t, LDNS_MAX_PACKETLEN); + if (!wire) { + *size = 0; + return NULL; + } + + wire_size = recvfrom(sockfd, (void*)wire, LDNS_MAX_PACKETLEN, 0, + (struct sockaddr *)from, fromlen); + + /* recvfrom can also return 0 */ + if (wire_size == -1 || wire_size == 0) { + *size = 0; + LDNS_FREE(wire); + return NULL; + } + + *size = (size_t)wire_size; + wireout = LDNS_XREALLOC(wire, uint8_t, (size_t)wire_size); + if(!wireout) LDNS_FREE(wire); + + return wireout; +} + +uint8_t * +ldns_tcp_read_wire_timeout(int sockfd, size_t *size, struct timeval timeout) +{ + uint8_t *wire; + uint16_t wire_size; + ssize_t bytes = 0, rc = 0; + + wire = LDNS_XMALLOC(uint8_t, 2); + if (!wire) { + *size = 0; + return NULL; + } + + while (bytes < 2) { + if(!ldns_sock_wait(sockfd, timeout, 0)) { + *size = 0; + LDNS_FREE(wire); + return NULL; + } + rc = recv(sockfd, (void*) (wire + bytes), + (size_t) (2 - bytes), 0); + if (rc == -1 || rc == 0) { + *size = 0; + LDNS_FREE(wire); + return NULL; + } + bytes += rc; + } + + wire_size = ldns_read_uint16(wire); + + LDNS_FREE(wire); + wire = LDNS_XMALLOC(uint8_t, wire_size); + if (!wire) { + *size = 0; + return NULL; + } + bytes = 0; + + while (bytes < (ssize_t) wire_size) { + if(!ldns_sock_wait(sockfd, timeout, 0)) { + *size = 0; + LDNS_FREE(wire); + return NULL; + } + rc = recv(sockfd, (void*) (wire + bytes), + (size_t) (wire_size - bytes), 0); + if (rc == -1 || rc == 0) { + LDNS_FREE(wire); + *size = 0; + return NULL; + } + bytes += rc; + } + + *size = (size_t) bytes; + return wire; +} + +uint8_t * +ldns_tcp_read_wire(int sockfd, size_t *size) +{ + uint8_t *wire; + uint16_t wire_size; + ssize_t bytes = 0, rc = 0; + + wire = LDNS_XMALLOC(uint8_t, 2); + if (!wire) { + *size = 0; + return NULL; + } + + while (bytes < 2) { + rc = recv(sockfd, (void*) (wire + bytes), + (size_t) (2 - bytes), 0); + if (rc == -1 || rc == 0) { + *size = 0; + LDNS_FREE(wire); + return NULL; + } + bytes += rc; + } + + wire_size = ldns_read_uint16(wire); + + LDNS_FREE(wire); + wire = LDNS_XMALLOC(uint8_t, wire_size); + if (!wire) { + *size = 0; + return NULL; + } + bytes = 0; + + while (bytes < (ssize_t) wire_size) { + rc = recv(sockfd, (void*) (wire + bytes), + (size_t) (wire_size - bytes), 0); + if (rc == -1 || rc == 0) { + LDNS_FREE(wire); + *size = 0; + return NULL; + } + bytes += rc; + } + + *size = (size_t) bytes; + return wire; +} + +/* keep in mind that in DNS tcp messages the first 2 bytes signal the + * amount data to expect + */ +ldns_status +ldns_tcp_send(uint8_t **result, ldns_buffer *qbin, const struct sockaddr_storage *to, + socklen_t tolen, struct timeval timeout, size_t *answer_size) +{ + int sockfd; + uint8_t *answer; + + sockfd = ldns_tcp_bgsend(qbin, to, tolen, timeout); + + if (sockfd == 0) { + return LDNS_STATUS_ERR; + } + + answer = ldns_tcp_read_wire_timeout(sockfd, answer_size, timeout); +#ifndef USE_WINSOCK + close(sockfd); +#else + closesocket(sockfd); +#endif + + if (*answer_size == 0) { + /* oops */ + return LDNS_STATUS_NETWORK_ERR; + } + + /* resize accordingly */ + *result = (uint8_t*)LDNS_XREALLOC(answer, uint8_t *, (size_t)*answer_size); + if(!*result) { + LDNS_FREE(answer); + return LDNS_STATUS_MEM_ERR; + } + return LDNS_STATUS_OK; +} + +int +ldns_tcp_bgsend(ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen, + struct timeval timeout) +{ + int sockfd; + + sockfd = ldns_tcp_connect(to, tolen, timeout); + + if (sockfd == 0) { + return 0; + } + + if (ldns_tcp_send_query(qbin, sockfd, to, tolen) == 0) { +#ifndef USE_WINSOCK + close(sockfd); +#else + closesocket(sockfd); +#endif + return 0; + } + + return sockfd; +} + +/* code from rdata.c */ +struct sockaddr_storage * +ldns_rdf2native_sockaddr_storage(const ldns_rdf *rd, uint16_t port, size_t *size) +{ + struct sockaddr_storage *data; + struct sockaddr_in *data_in; + struct sockaddr_in6 *data_in6; + + data = LDNS_MALLOC(struct sockaddr_storage); + if (!data) { + return NULL; + } + /* zero the structure for portability */ + memset(data, 0, sizeof(struct sockaddr_storage)); + if (port == 0) { + port = LDNS_PORT; + } + + switch(ldns_rdf_get_type(rd)) { + case LDNS_RDF_TYPE_A: +#ifndef S_SPLINT_S + data->ss_family = AF_INET; +#endif + data_in = (struct sockaddr_in*) data; + data_in->sin_port = (in_port_t)htons(port); + memcpy(&(data_in->sin_addr), ldns_rdf_data(rd), ldns_rdf_size(rd)); + *size = sizeof(struct sockaddr_in); + return data; + case LDNS_RDF_TYPE_AAAA: +#ifndef S_SPLINT_S + data->ss_family = AF_INET6; +#endif + data_in6 = (struct sockaddr_in6*) data; + data_in6->sin6_port = (in_port_t)htons(port); + memcpy(&data_in6->sin6_addr, ldns_rdf_data(rd), ldns_rdf_size(rd)); + *size = sizeof(struct sockaddr_in6); + return data; + default: + LDNS_FREE(data); + return NULL; + } +} + +#ifndef S_SPLINT_S +ldns_rdf * +ldns_sockaddr_storage2rdf(struct sockaddr_storage *sock, uint16_t *port) +{ + ldns_rdf *addr; + struct sockaddr_in *data_in; + struct sockaddr_in6 *data_in6; + + switch(sock->ss_family) { + case AF_INET: + data_in = (struct sockaddr_in*)sock; + if (port) { + *port = ntohs((uint16_t)data_in->sin_port); + } + addr = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_A, + LDNS_IP4ADDRLEN, &data_in->sin_addr); + break; + case AF_INET6: + data_in6 = (struct sockaddr_in6*)sock; + if (port) { + *port = ntohs((uint16_t)data_in6->sin6_port); + } + addr = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_AAAA, + LDNS_IP6ADDRLEN, &data_in6->sin6_addr); + break; + default: + if (port) { + *port = 0; + } + return NULL; + } + return addr; +} +#endif + +/* code from resolver.c */ +ldns_status +ldns_axfr_start(ldns_resolver *resolver, ldns_rdf *domain, ldns_rr_class class) +{ + ldns_pkt *query; + ldns_buffer *query_wire; + + struct sockaddr_storage *ns = NULL; + size_t ns_len = 0; + size_t ns_i; + ldns_status status; + + if (!resolver || ldns_resolver_nameserver_count(resolver) < 1) { + return LDNS_STATUS_ERR; + } + + query = ldns_pkt_query_new(ldns_rdf_clone(domain), LDNS_RR_TYPE_AXFR, class, 0); + + if (!query) { + return LDNS_STATUS_ADDRESS_ERR; + } + /* For AXFR, we have to make the connection ourselves */ + /* try all nameservers (which usually would mean v4 fallback if + * @hostname is used */ + for (ns_i = 0; + ns_i < ldns_resolver_nameserver_count(resolver) && + resolver->_socket == 0; + ns_i++) { + ns = ldns_rdf2native_sockaddr_storage( + resolver->_nameservers[ns_i], + ldns_resolver_port(resolver), &ns_len); + + resolver->_socket = ldns_tcp_connect(ns, (socklen_t)ns_len, + ldns_resolver_timeout(resolver)); + } + + if (resolver->_socket == 0) { + ldns_pkt_free(query); + LDNS_FREE(ns); + return LDNS_STATUS_NETWORK_ERR; + } + +#ifdef HAVE_SSL + if (ldns_resolver_tsig_keyname(resolver) && ldns_resolver_tsig_keydata(resolver)) { + status = ldns_pkt_tsig_sign(query, + ldns_resolver_tsig_keyname(resolver), + ldns_resolver_tsig_keydata(resolver), + 300, ldns_resolver_tsig_algorithm(resolver), NULL); + if (status != LDNS_STATUS_OK) { + /* RoRi: to prevent problems on subsequent calls to ldns_axfr_start + we have to close the socket here! */ +#ifndef USE_WINSOCK + close(resolver->_socket); +#else + closesocket(resolver->_socket); +#endif + resolver->_socket = 0; + + return LDNS_STATUS_CRYPTO_TSIG_ERR; + } + } +#endif /* HAVE_SSL */ + + /* Convert the query to a buffer + * Is this necessary? + */ + query_wire = ldns_buffer_new(LDNS_MAX_PACKETLEN); + if(!query_wire) { + ldns_pkt_free(query); + LDNS_FREE(ns); +#ifndef USE_WINSOCK + close(resolver->_socket); +#else + closesocket(resolver->_socket); +#endif + resolver->_socket = 0; + + return LDNS_STATUS_MEM_ERR; + } + status = ldns_pkt2buffer_wire(query_wire, query); + if (status != LDNS_STATUS_OK) { + ldns_pkt_free(query); + ldns_buffer_free(query_wire); + LDNS_FREE(ns); + + /* RoRi: to prevent problems on subsequent calls to ldns_axfr_start + we have to close the socket here! */ +#ifndef USE_WINSOCK + close(resolver->_socket); +#else + closesocket(resolver->_socket); +#endif + resolver->_socket = 0; + + return status; + } + /* Send the query */ + if (ldns_tcp_send_query(query_wire, resolver->_socket, ns, + (socklen_t)ns_len) == 0) { + ldns_pkt_free(query); + ldns_buffer_free(query_wire); + LDNS_FREE(ns); + + /* RoRi: to prevent problems on subsequent calls to ldns_axfr_start + we have to close the socket here! */ + +#ifndef USE_WINSOCK + close(resolver->_socket); +#else + closesocket(resolver->_socket); +#endif + resolver->_socket = 0; + + return LDNS_STATUS_NETWORK_ERR; + } + + ldns_pkt_free(query); + ldns_buffer_free(query_wire); + LDNS_FREE(ns); + + /* + * The AXFR is done once the second SOA record is sent + */ + resolver->_axfr_soa_count = 0; + return LDNS_STATUS_OK; +} diff --git a/packaging/fedora/ldns.spec b/packaging/fedora/ldns.spec new file mode 100644 index 00000000000..6658d011a00 --- /dev/null +++ b/packaging/fedora/ldns.spec @@ -0,0 +1,212 @@ +%{?!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: Lowlevel DNS(SEC) library with API +Name: ldns +Version: 1.6.13 +Release: 1%{?dist} +License: BSD +Url: http://www.nlnetlabs.nl/%{name}/ +Source: http://www.nlnetlabs.nl/downloads/%{%name}/%{name}-%{version}.tar.gz +Group: System Environment/Libraries +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) +BuildRequires: perl, libpcap-devel, openssl-devel , gcc-c++, doxygen, +# Only needed for builds from svn snapshot +# BuildRequires: libtool, autoconf, automake + +%if %{with_python} +BuildRequires: python-devel, swig +%endif + +%description +ldns is a library with the aim to simplify DNS programing in C. All +lowlevel DNS/DNSSEC operations are supported. We also define a higher +level API which allows a programmer to (for instance) create or sign +packets. + +%package devel +Summary: Development package that includes the ldns header files +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} + +%description devel +The devel package contains the ldns library and the include files + +%if %{with_python} +%package python +Summary: Python extensions for ldns +Group: Applications/System +Requires: %{name} = %{version}-%{release} + +%description python +Python extensions for ldns +%endif + +%prep +%setup -q +# To built svn snapshots +# rm config.guess config.sub ltmain.sh +# aclocal +# libtoolize -c +# autoreconf + +%build +%configure --disable-rpath --disable-static --with-sha2 --disable-gost \ +%if %{with_python} + --with-pyldns +%endif + +(cd drill ; %configure --disable-rpath --disable-static --with-sha2 --disable-gost --with-ldns=%{buildroot}/lib/ ) +(cd examples ; %configure --disable-rpath --disable-static --with-sha2 --disable-gost --with-ldns=%{buildroot}/lib/ ) + +make %{?_smp_mflags} +( cd drill ; make %{?_smp_mflags} ) +( cd examples ; make %{?_smp_mflags} ) +make %{?_smp_mflags} doc + +%install +rm -rf %{buildroot} + +make DESTDIR=%{buildroot} INSTALL="%{__install} -p" install +make DESTDIR=%{buildroot} INSTALL="%{__install} -p" install-doc + +# don't install another set of man pages from doc/ +rm -rf doc/man/ + +# don't package building script for install-doc in doc section +rm doc/doxyparse.pl + +# remove .la files +rm -rf %{buildroot}%{_libdir}/*.la %{buildroot}%{python_sitearch}/*.la +(cd drill ; make DESTDIR=%{buildroot} install) +(cd examples; make DESTDIR=%{buildroot} install) + +%clean +rm -rf %{buildroot} + +%files +%defattr(-,root,root) +%{_libdir}/libldns*so.* +%{_bindir}/drill +%{_bindir}/ldnsd +%{_bindir}/ldns-chaos +%{_bindir}/ldns-compare-zones +%{_bindir}/ldns-[d-z]* +%doc README LICENSE +%{_mandir}/*/* + +%files devel +%defattr(-,root,root,-) +%{_libdir}/libldns*so +%{_bindir}/ldns-config +%dir %{_includedir}/ldns +%{_includedir}/ldns/*.h +%doc doc Changelog README + +%if %{with_python} +%files python +%defattr(-,root,root) +%{python_sitearch}/* +%endif + +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig + +%changelog +* Thu Sep 22 2011 Paul Wouters - 1.6.11-1 +- Updated to 1.6.11 +- Cleanup spec for +- Python goes into sitearch, not sitelib + +* Wed Jun 08 2011 Paul Wouters - 1.6.10-1 +- Updated to 1.6.10 +- commented out build dependancies for svn snapshots + +* Sun Mar 27 2011 Paul Wouters - 1.6.9-1 +- Updated to 1.6.9 + +* Mon Jan 24 2011 Paul Wouters - 1.6.8-1 +- Updated to 1.6.8 + +* Thu Aug 26 2010 Paul Wouters - 1.6.6-1 +- Upgraded to 1.6.6 + +* Mon Apr 26 2010 Paul Wouters - 1.6.4-4 +- Disable a debug line that was added to find the LOC issue that causes + unexpected output for automated tools using ldns-read-zone + +* Thu Feb 11 2010 Paul Wouters - 1.6.4-3 +- Applied fix svn 3186 for LOC record parsing + +* Fri Jan 22 2010 Paul Wouters - 1.6.4-2 +- libtool on EL-5 does not take --install as argument + +* Fri Jan 22 2010 Paul Wouters - 1.6.4-1 +- Upgraded to 1.6.4 +- Added ldns-python sub package +- Patch for installing ldns-python files +- Patch for rpath in ldns-python + +* Sun Aug 16 2009 Paul Wouters - 1.6.1-2 +- Bump version, sources file was not updated. + +* Sun Aug 16 2009 Paul Wouters - 1.6.1-1 +-Updated to 1.6.1 + +* Sat Jul 11 2009 Paul Wouters - 1.6.0-1 +- Updated to 1.6.0 + +* Thu Apr 16 2009 Paul Wouters - 1.5.1-2 +- Memory management bug when generating a sha256 key, see: + https://bugzilla.redhat.com/show_bug.cgi?id=493953 + +* Fri Feb 13 2009 Paul Wouters - 1.5.1-1 +- Upgrade to 1.5.1 (1.5.0 was a dud release) + +* Sun Nov 9 2008 Paul Wouters - 1.4.0-2 +- libldns.so was missing in files section. + +* Sun Nov 9 2008 Paul Wouters - 1.4.0-1 +- Updated to 1.4.0 +- enable SHA2 functionality + +* Mon Jun 30 2008 Paul Wouters - 1.3.0-1 +- Updated to latest release + +* Thu Nov 29 2007 Paul Wouters - 1.2.2-1 +- Upgraded to 1.2.2. + +* Mon Sep 11 2006 Paul Wouters 1.0.1-4 +- Commented out 1.1.0 make targets, put make 1.0.1 targets. + +* Mon Sep 11 2006 Paul Wouters 1.0.1-3 +- Fixed changelog typo in date +- Rebuild requested for PT_GNU_HASH support from gcc +- Did not upgrade to 1.1.0 due to compile issues on x86_64 + +* Fri Jan 6 2006 Paul Wouters 1.0.1-1 +- Upgraded to 1.0.1. Removed temporary clean hack from spec file. + +* Sun Dec 18 2005 Paul Wouters 1.0.0-8 +- Cannot use make clean because there are no Makefiles. Use hardcoded rm. + +* Sun Dec 18 2005 Paul Wouters 1.0.0-7 +- Patched 'make clean' target to get rid of object files shipped with 1.0.0 + +* Sun Dec 13 2005 Paul Wouters 1.0.0-6 +- added a make clean for 2.3.3 since .o files were left behind upstream, + causing failure on ppc platform + +* Sun Dec 11 2005 Tom "spot" Callaway 1.0.0-5 +- minor cleanups + +* Wed Oct 5 2005 Paul Wouters 0.70_1205 +- reworked for svn version + +* Sun Sep 25 2005 Paul Wouters - 0.70 +- Initial version diff --git a/packaging/ldns-config.1 b/packaging/ldns-config.1 new file mode 100644 index 00000000000..c5a00a1eb38 --- /dev/null +++ b/packaging/ldns-config.1 @@ -0,0 +1,43 @@ +.TH ldns-config 1 "22 Sep 2011" +.SH NAME +ldns-config \- show compiler and linker flags for ldns usage. +.SH SYNOPSIS +.B ldns-config +[ +.IR OPTIONS +] + +.SH DESCRIPTION +When writing programs using ldns, you have to tell the compiler +where to look for include files and what libraries from which location +to link to. \fBldns-config\fR can be used to find out what flags to use +with the C compiler and the linker. + +.SH OPTIONS +.TP +\fB--cflags\fR +Show the C compiler flags needed to compile with ldns + +.TP +\fB--libs\fR +Show the flags to be used to link with ldns + +.TP +\fB--version\fR +Shows the version of the installed ldns library + +.TP +\fB--help\fR +Show \fBldns-config\fR usage description + +.SH AUTHOR +Written by the ldns team. + +.SH REPORTING BUGS +Report bugs to . + +.SH COPYRIGHT +Copyright (C) 2011 NLnet Labs. This is free software. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. + diff --git a/packaging/ldns-config.in b/packaging/ldns-config.in new file mode 100755 index 00000000000..b728ba544e1 --- /dev/null +++ b/packaging/ldns-config.in @@ -0,0 +1,31 @@ +#!/bin/sh + +prefix="@prefix@" +exec_prefix="@exec_prefix@" +VERSION="@PACKAGE_VERSION@" +CFLAGS="@CFLAGS@" +CPPFLAGS="@CPPFLAGS@ @LIBSSL_CPPFLAGS@ @PYTHON_CPPFLAGS@" +LDFLAGS="@LDFLAGS@ @LIBSSL_LDFLAGS@ @PYTHON_LDFLAGS@" +LIBS="@LIBS@ @LIBSSL_LIBS@" +LIBDIR="@libdir@" +INCLUDEDIR="@includedir@" + +for arg in $@ +do + if [ $arg = "--cflags" ] + then + echo "-I${INCLUDEDIR}" + fi + if [ $arg = "--libs" ] + then + echo "${LDFLAGS} -L${LIBDIR} ${LIBS} -lldns" + fi + if [ $arg = "-h" ] || [ $arg = "--help" ] + then + echo "Usage: $0 [--cflags] [--libs] [--version]" + fi + if [ $arg = "--version" ] + then + echo "${VERSION}" + fi +done diff --git a/packaging/libldns.pc.in b/packaging/libldns.pc.in new file mode 100644 index 00000000000..923b688379d --- /dev/null +++ b/packaging/libldns.pc.in @@ -0,0 +1,13 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: ldns +Description: Library for DNS programming +URL: http://www.nlnetlabs.nl/projects/ldns +Version: @PACKAGE_VERSION@ +Requires: +Libs: -L${libdir} -lldns +Libs.private: @LDFLAGS@ +Cflags: -I${includedir} diff --git a/packet.c b/packet.c new file mode 100644 index 00000000000..0ac5ca8ba31 --- /dev/null +++ b/packet.c @@ -0,0 +1,1007 @@ +/* + * packet.c + * + * dns packet implementation + * + * a Net::DNS like library for C + * + * (c) NLnet Labs, 2004-2006 + * + * See the file LICENSE for the license + */ + +#include + +#include + +#include +#include + +#ifdef HAVE_SSL +#include +#endif + +/* Access functions + * do this as functions to get type checking + */ + +#define LDNS_EDNS_MASK_DO_BIT 0x8000 + +/* TODO defines for 3600 */ +/* convert to and from numerical flag values */ +ldns_lookup_table ldns_edns_flags[] = { + { 3600, "do"}, + { 0, NULL} +}; + +/* read */ +uint16_t +ldns_pkt_id(const ldns_pkt *packet) +{ + return packet->_header->_id; +} + +bool +ldns_pkt_qr(const ldns_pkt *packet) +{ + return packet->_header->_qr; +} + +bool +ldns_pkt_aa(const ldns_pkt *packet) +{ + return packet->_header->_aa; +} + +bool +ldns_pkt_tc(const ldns_pkt *packet) +{ + return packet->_header->_tc; +} + +bool +ldns_pkt_rd(const ldns_pkt *packet) +{ + return packet->_header->_rd; +} + +bool +ldns_pkt_cd(const ldns_pkt *packet) +{ + return packet->_header->_cd; +} + +bool +ldns_pkt_ra(const ldns_pkt *packet) +{ + return packet->_header->_ra; +} + +bool +ldns_pkt_ad(const ldns_pkt *packet) +{ + return packet->_header->_ad; +} + +ldns_pkt_opcode +ldns_pkt_get_opcode(const ldns_pkt *packet) +{ + return packet->_header->_opcode; +} + +ldns_pkt_rcode +ldns_pkt_get_rcode(const ldns_pkt *packet) +{ + return packet->_header->_rcode; +} + +uint16_t +ldns_pkt_qdcount(const ldns_pkt *packet) +{ + return packet->_header->_qdcount; +} + +uint16_t +ldns_pkt_ancount(const ldns_pkt *packet) +{ + return packet->_header->_ancount; +} + +uint16_t +ldns_pkt_nscount(const ldns_pkt *packet) +{ + return packet->_header->_nscount; +} + +uint16_t +ldns_pkt_arcount(const ldns_pkt *packet) +{ + return packet->_header->_arcount; +} + +ldns_rr_list * +ldns_pkt_question(const ldns_pkt *packet) +{ + return packet->_question; +} + +ldns_rr_list * +ldns_pkt_answer(const ldns_pkt *packet) +{ + return packet->_answer; +} + +ldns_rr_list * +ldns_pkt_authority(const ldns_pkt *packet) +{ + return packet->_authority; +} + +ldns_rr_list * +ldns_pkt_additional(const ldns_pkt *packet) +{ + return packet->_additional; +} + +/* return ALL section concatenated */ +ldns_rr_list * +ldns_pkt_all(const ldns_pkt *packet) +{ + ldns_rr_list *all, *prev_all; + + all = ldns_rr_list_cat_clone( + ldns_pkt_question(packet), + ldns_pkt_answer(packet)); + prev_all = all; + all = ldns_rr_list_cat_clone(all, + ldns_pkt_authority(packet)); + ldns_rr_list_deep_free(prev_all); + prev_all = all; + all = ldns_rr_list_cat_clone(all, + ldns_pkt_additional(packet)); + ldns_rr_list_deep_free(prev_all); + return all; +} + +ldns_rr_list * +ldns_pkt_all_noquestion(const ldns_pkt *packet) +{ + ldns_rr_list *all, *all2; + + all = ldns_rr_list_cat_clone( + ldns_pkt_answer(packet), + ldns_pkt_authority(packet)); + all2 = ldns_rr_list_cat_clone(all, + ldns_pkt_additional(packet)); + + ldns_rr_list_deep_free(all); + return all2; +} + +size_t +ldns_pkt_size(const ldns_pkt *packet) +{ + return packet->_size; +} + +uint32_t +ldns_pkt_querytime(const ldns_pkt *packet) +{ + return packet->_querytime; +} + +ldns_rdf * +ldns_pkt_answerfrom(const ldns_pkt *packet) +{ + return packet->_answerfrom; +} + +struct timeval +ldns_pkt_timestamp(const ldns_pkt *packet) +{ + return packet->timestamp; +} + +uint16_t +ldns_pkt_edns_udp_size(const ldns_pkt *packet) +{ + return packet->_edns_udp_size; +} + +uint8_t +ldns_pkt_edns_extended_rcode(const ldns_pkt *packet) +{ + return packet->_edns_extended_rcode; +} + +uint8_t +ldns_pkt_edns_version(const ldns_pkt *packet) +{ + return packet->_edns_version; +} + +uint16_t +ldns_pkt_edns_z(const ldns_pkt *packet) +{ + return packet->_edns_z; +} + +bool +ldns_pkt_edns_do(const ldns_pkt *packet) +{ + return (packet->_edns_z & LDNS_EDNS_MASK_DO_BIT); +} + +void +ldns_pkt_set_edns_do(ldns_pkt *packet, bool value) +{ + if (value) { + packet->_edns_z = packet->_edns_z | LDNS_EDNS_MASK_DO_BIT; + } else { + packet->_edns_z = packet->_edns_z & ~LDNS_EDNS_MASK_DO_BIT; + } +} + +ldns_rdf * +ldns_pkt_edns_data(const ldns_pkt *packet) +{ + return packet->_edns_data; +} + +/* return only those rr that share the ownername */ +ldns_rr_list * +ldns_pkt_rr_list_by_name(ldns_pkt *packet, + ldns_rdf *ownername, + ldns_pkt_section sec) +{ + ldns_rr_list *rrs; + ldns_rr_list *new; + ldns_rr_list *ret; + uint16_t i; + + if (!packet) { + return NULL; + } + + rrs = ldns_pkt_get_section_clone(packet, sec); + new = ldns_rr_list_new(); + ret = NULL; + + for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) { + if (ldns_rdf_compare(ldns_rr_owner( + ldns_rr_list_rr(rrs, i)), + ownername) == 0) { + /* owner names match */ + ldns_rr_list_push_rr(new, ldns_rr_list_rr(rrs, i)); + ret = new; + } + } + return ret; +} + +/* return only those rr that share a type */ +ldns_rr_list * +ldns_pkt_rr_list_by_type(const ldns_pkt *packet, + ldns_rr_type type, + ldns_pkt_section sec) +{ + ldns_rr_list *rrs; + ldns_rr_list *new; + uint16_t i; + + if(!packet) { + return NULL; + } + + rrs = ldns_pkt_get_section_clone(packet, sec); + new = ldns_rr_list_new(); + + for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) { + if (type == ldns_rr_get_type(ldns_rr_list_rr(rrs, i))) { + /* types match */ + ldns_rr_list_push_rr(new, + ldns_rr_clone( + ldns_rr_list_rr(rrs, i)) + ); + } + } + ldns_rr_list_deep_free(rrs); + + if (ldns_rr_list_rr_count(new) == 0) { + ldns_rr_list_free(new); + return NULL; + } else { + return new; + } +} + +/* return only those rrs that share name and type */ +ldns_rr_list * +ldns_pkt_rr_list_by_name_and_type(const ldns_pkt *packet, + const ldns_rdf *ownername, + ldns_rr_type type, + ldns_pkt_section sec) +{ + ldns_rr_list *rrs; + ldns_rr_list *new; + ldns_rr_list *ret; + uint16_t i; + + if(!packet) { + return NULL; + } + + rrs = ldns_pkt_get_section_clone(packet, sec); + new = ldns_rr_list_new(); + ret = NULL; + + for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) { + if (type == ldns_rr_get_type(ldns_rr_list_rr(rrs, i)) && + ldns_rdf_compare(ldns_rr_owner(ldns_rr_list_rr(rrs, i)), + ownername + ) == 0 + ) { + /* types match */ + ldns_rr_list_push_rr(new, ldns_rr_clone(ldns_rr_list_rr(rrs, i))); + ret = new; + } + } + ldns_rr_list_deep_free(rrs); + if (!ret) { + ldns_rr_list_free(new); + } + return ret; +} + +bool +ldns_pkt_rr(ldns_pkt *pkt, ldns_pkt_section sec, ldns_rr *rr) +{ + bool result = false; + + switch (sec) { + case LDNS_SECTION_QUESTION: + return ldns_rr_list_contains_rr(ldns_pkt_question(pkt), rr); + case LDNS_SECTION_ANSWER: + return ldns_rr_list_contains_rr(ldns_pkt_answer(pkt), rr); + case LDNS_SECTION_AUTHORITY: + return ldns_rr_list_contains_rr(ldns_pkt_authority(pkt), rr); + case LDNS_SECTION_ADDITIONAL: + return ldns_rr_list_contains_rr(ldns_pkt_additional(pkt), rr); + case LDNS_SECTION_ANY: + result = ldns_rr_list_contains_rr(ldns_pkt_question(pkt), rr); + case LDNS_SECTION_ANY_NOQUESTION: + result = result + || ldns_rr_list_contains_rr(ldns_pkt_answer(pkt), rr) + || ldns_rr_list_contains_rr(ldns_pkt_authority(pkt), rr) + || ldns_rr_list_contains_rr(ldns_pkt_additional(pkt), rr); + } + + return result; +} + +uint16_t +ldns_pkt_section_count(const ldns_pkt *packet, ldns_pkt_section s) +{ + switch(s) { + case LDNS_SECTION_QUESTION: + return ldns_pkt_qdcount(packet); + case LDNS_SECTION_ANSWER: + return ldns_pkt_ancount(packet); + case LDNS_SECTION_AUTHORITY: + return ldns_pkt_nscount(packet); + case LDNS_SECTION_ADDITIONAL: + return ldns_pkt_arcount(packet); + case LDNS_SECTION_ANY: + return ldns_pkt_qdcount(packet) + + ldns_pkt_ancount(packet) + + ldns_pkt_nscount(packet) + + ldns_pkt_arcount(packet); + case LDNS_SECTION_ANY_NOQUESTION: + return ldns_pkt_ancount(packet) + + ldns_pkt_nscount(packet) + + ldns_pkt_arcount(packet); + default: + return 0; + } +} + +bool +ldns_pkt_empty(ldns_pkt *p) +{ + if (!p) { + return true; /* NULL is empty? */ + } + if (ldns_pkt_section_count(p, LDNS_SECTION_ANY) > 0) { + return false; + } else { + return true; + } +} + + +ldns_rr_list * +ldns_pkt_get_section_clone(const ldns_pkt *packet, ldns_pkt_section s) +{ + switch(s) { + case LDNS_SECTION_QUESTION: + return ldns_rr_list_clone(ldns_pkt_question(packet)); + case LDNS_SECTION_ANSWER: + return ldns_rr_list_clone(ldns_pkt_answer(packet)); + case LDNS_SECTION_AUTHORITY: + return ldns_rr_list_clone(ldns_pkt_authority(packet)); + case LDNS_SECTION_ADDITIONAL: + return ldns_rr_list_clone(ldns_pkt_additional(packet)); + case LDNS_SECTION_ANY: + /* these are already clones */ + return ldns_pkt_all(packet); + case LDNS_SECTION_ANY_NOQUESTION: + return ldns_pkt_all_noquestion(packet); + default: + return NULL; + } +} + +ldns_rr *ldns_pkt_tsig(const ldns_pkt *pkt) { + return pkt->_tsig_rr; +} + +/* write */ +void +ldns_pkt_set_id(ldns_pkt *packet, uint16_t id) +{ + packet->_header->_id = id; +} + +void +ldns_pkt_set_random_id(ldns_pkt *packet) +{ + uint16_t rid = ldns_get_random(); + ldns_pkt_set_id(packet, rid); +} + + +void +ldns_pkt_set_qr(ldns_pkt *packet, bool qr) +{ + packet->_header->_qr = qr; +} + +void +ldns_pkt_set_aa(ldns_pkt *packet, bool aa) +{ + packet->_header->_aa = aa; +} + +void +ldns_pkt_set_tc(ldns_pkt *packet, bool tc) +{ + packet->_header->_tc = tc; +} + +void +ldns_pkt_set_rd(ldns_pkt *packet, bool rd) +{ + packet->_header->_rd = rd; +} + +void +ldns_pkt_set_additional(ldns_pkt *p, ldns_rr_list *rr) +{ + p->_additional = rr; +} + +void +ldns_pkt_set_question(ldns_pkt *p, ldns_rr_list *rr) +{ + p->_question = rr; +} + +void +ldns_pkt_set_answer(ldns_pkt *p, ldns_rr_list *rr) +{ + p->_answer = rr; +} + +void +ldns_pkt_set_authority(ldns_pkt *p, ldns_rr_list *rr) +{ + p->_authority = rr; +} + +void +ldns_pkt_set_cd(ldns_pkt *packet, bool cd) +{ + packet->_header->_cd = cd; +} + +void +ldns_pkt_set_ra(ldns_pkt *packet, bool ra) +{ + packet->_header->_ra = ra; +} + +void +ldns_pkt_set_ad(ldns_pkt *packet, bool ad) +{ + packet->_header->_ad = ad; +} + +void +ldns_pkt_set_opcode(ldns_pkt *packet, ldns_pkt_opcode opcode) +{ + packet->_header->_opcode = opcode; +} + +void +ldns_pkt_set_rcode(ldns_pkt *packet, uint8_t rcode) +{ + packet->_header->_rcode = rcode; +} + +void +ldns_pkt_set_qdcount(ldns_pkt *packet, uint16_t qdcount) +{ + packet->_header->_qdcount = qdcount; +} + +void +ldns_pkt_set_ancount(ldns_pkt *packet, uint16_t ancount) +{ + packet->_header->_ancount = ancount; +} + +void +ldns_pkt_set_nscount(ldns_pkt *packet, uint16_t nscount) +{ + packet->_header->_nscount = nscount; +} + +void +ldns_pkt_set_arcount(ldns_pkt *packet, uint16_t arcount) +{ + packet->_header->_arcount = arcount; +} + +void +ldns_pkt_set_querytime(ldns_pkt *packet, uint32_t time) +{ + packet->_querytime = time; +} + +void +ldns_pkt_set_answerfrom(ldns_pkt *packet, ldns_rdf *answerfrom) +{ + packet->_answerfrom = answerfrom; +} + +void +ldns_pkt_set_timestamp(ldns_pkt *packet, struct timeval timeval) +{ + packet->timestamp.tv_sec = timeval.tv_sec; + packet->timestamp.tv_usec = timeval.tv_usec; +} + +void +ldns_pkt_set_size(ldns_pkt *packet, size_t s) +{ + packet->_size = s; +} + +void +ldns_pkt_set_edns_udp_size(ldns_pkt *packet, uint16_t s) +{ + packet->_edns_udp_size = s; +} + +void +ldns_pkt_set_edns_extended_rcode(ldns_pkt *packet, uint8_t c) +{ + packet->_edns_extended_rcode = c; +} + +void +ldns_pkt_set_edns_version(ldns_pkt *packet, uint8_t v) +{ + packet->_edns_version = v; +} + +void +ldns_pkt_set_edns_z(ldns_pkt *packet, uint16_t z) +{ + packet->_edns_z = z; +} + +void +ldns_pkt_set_edns_data(ldns_pkt *packet, ldns_rdf *data) +{ + packet->_edns_data = data; +} + +void +ldns_pkt_set_section_count(ldns_pkt *packet, ldns_pkt_section s, uint16_t count) +{ + switch(s) { + case LDNS_SECTION_QUESTION: + ldns_pkt_set_qdcount(packet, count); + break; + case LDNS_SECTION_ANSWER: + ldns_pkt_set_ancount(packet, count); + break; + case LDNS_SECTION_AUTHORITY: + ldns_pkt_set_nscount(packet, count); + break; + case LDNS_SECTION_ADDITIONAL: + ldns_pkt_set_arcount(packet, count); + break; + case LDNS_SECTION_ANY: + case LDNS_SECTION_ANY_NOQUESTION: + break; + } +} + +void ldns_pkt_set_tsig(ldns_pkt *pkt, ldns_rr *rr) +{ + pkt->_tsig_rr = rr; +} + +bool +ldns_pkt_push_rr(ldns_pkt *packet, ldns_pkt_section section, ldns_rr *rr) +{ + switch(section) { + case LDNS_SECTION_QUESTION: + ldns_rr_list_push_rr(ldns_pkt_question(packet), rr); + ldns_pkt_set_qdcount(packet, ldns_pkt_qdcount(packet) + 1); + break; + case LDNS_SECTION_ANSWER: + ldns_rr_list_push_rr(ldns_pkt_answer(packet), rr); + ldns_pkt_set_ancount(packet, ldns_pkt_ancount(packet) + 1); + break; + case LDNS_SECTION_AUTHORITY: + ldns_rr_list_push_rr(ldns_pkt_authority(packet), rr); + ldns_pkt_set_nscount(packet, ldns_pkt_nscount(packet) + 1); + break; + case LDNS_SECTION_ADDITIONAL: + ldns_rr_list_push_rr(ldns_pkt_additional(packet), rr); + ldns_pkt_set_arcount(packet, ldns_pkt_arcount(packet) + 1); + break; + case LDNS_SECTION_ANY: + case LDNS_SECTION_ANY_NOQUESTION: + /* shouldn't this error? */ + break; + } + return true; +} + +bool +ldns_pkt_safe_push_rr(ldns_pkt *pkt, ldns_pkt_section sec, ldns_rr *rr) +{ + + /* check to see if its there */ + if (ldns_pkt_rr(pkt, sec, rr)) { + /* already there */ + return false; + } + return ldns_pkt_push_rr(pkt, sec, rr); +} + +bool +ldns_pkt_push_rr_list(ldns_pkt *p, ldns_pkt_section s, ldns_rr_list *list) +{ + size_t i; + for(i = 0; i < ldns_rr_list_rr_count(list); i++) { + if (!ldns_pkt_push_rr(p, s, ldns_rr_list_rr(list, i))) { + return false; + } + } + return true; +} + +bool +ldns_pkt_safe_push_rr_list(ldns_pkt *p, ldns_pkt_section s, ldns_rr_list *list) +{ + size_t i; + for(i = 0; i < ldns_rr_list_rr_count(list); i++) { + if (!ldns_pkt_safe_push_rr(p, s, ldns_rr_list_rr(list, i))) { + return false; + } + } + return true; +} + +bool +ldns_pkt_edns(const ldns_pkt *pkt) { + return (ldns_pkt_edns_udp_size(pkt) > 0 || + ldns_pkt_edns_extended_rcode(pkt) > 0 || + ldns_pkt_edns_data(pkt) || + ldns_pkt_edns_do(pkt) + ); +} + + +/* Create/destroy/convert functions + */ +ldns_pkt * +ldns_pkt_new() +{ + ldns_pkt *packet; + packet = LDNS_MALLOC(ldns_pkt); + if (!packet) { + return NULL; + } + + packet->_header = LDNS_MALLOC(ldns_hdr); + if (!packet->_header) { + LDNS_FREE(packet); + return NULL; + } + + packet->_question = ldns_rr_list_new(); + packet->_answer = ldns_rr_list_new(); + packet->_authority = ldns_rr_list_new(); + packet->_additional = ldns_rr_list_new(); + + /* default everything to false */ + ldns_pkt_set_qr(packet, false); + ldns_pkt_set_aa(packet, false); + ldns_pkt_set_tc(packet, false); + ldns_pkt_set_rd(packet, false); + ldns_pkt_set_ra(packet, false); + ldns_pkt_set_ad(packet, false); + ldns_pkt_set_cd(packet, false); + + ldns_pkt_set_opcode(packet, LDNS_PACKET_QUERY); + ldns_pkt_set_rcode(packet, 0); + ldns_pkt_set_id(packet, 0); + ldns_pkt_set_size(packet, 0); + ldns_pkt_set_querytime(packet, 0); + memset(&packet->timestamp, 0, sizeof(packet->timestamp)); + ldns_pkt_set_answerfrom(packet, NULL); + ldns_pkt_set_section_count(packet, LDNS_SECTION_QUESTION, 0); + ldns_pkt_set_section_count(packet, LDNS_SECTION_ANSWER, 0); + ldns_pkt_set_section_count(packet, LDNS_SECTION_AUTHORITY, 0); + ldns_pkt_set_section_count(packet, LDNS_SECTION_ADDITIONAL, 0); + + ldns_pkt_set_edns_udp_size(packet, 0); + ldns_pkt_set_edns_extended_rcode(packet, 0); + ldns_pkt_set_edns_version(packet, 0); + ldns_pkt_set_edns_z(packet, 0); + ldns_pkt_set_edns_data(packet, NULL); + + ldns_pkt_set_tsig(packet, NULL); + + return packet; +} + +void +ldns_pkt_free(ldns_pkt *packet) +{ + if (packet) { + LDNS_FREE(packet->_header); + ldns_rr_list_deep_free(packet->_question); + ldns_rr_list_deep_free(packet->_answer); + ldns_rr_list_deep_free(packet->_authority); + ldns_rr_list_deep_free(packet->_additional); + ldns_rr_free(packet->_tsig_rr); + ldns_rdf_deep_free(packet->_edns_data); + LDNS_FREE(packet); + } +} + +bool +ldns_pkt_set_flags(ldns_pkt *packet, uint16_t flags) +{ + if (!packet) { + return false; + } + if ((flags & LDNS_QR) == LDNS_QR) { + ldns_pkt_set_qr(packet, true); + } + if ((flags & LDNS_AA) == LDNS_AA) { + ldns_pkt_set_aa(packet, true); + } + if ((flags & LDNS_RD) == LDNS_RD) { + ldns_pkt_set_rd(packet, true); + } + if ((flags & LDNS_TC) == LDNS_TC) { + ldns_pkt_set_tc(packet, true); + } + if ((flags & LDNS_CD) == LDNS_CD) { + ldns_pkt_set_cd(packet, true); + } + if ((flags & LDNS_RA) == LDNS_RA) { + ldns_pkt_set_ra(packet, true); + } + if ((flags & LDNS_AD) == LDNS_AD) { + ldns_pkt_set_ad(packet, true); + } + return true; +} + +ldns_status +ldns_pkt_query_new_frm_str(ldns_pkt **p, const char *name, ldns_rr_type rr_type, + ldns_rr_class rr_class, uint16_t flags) +{ + ldns_pkt *packet; + ldns_rr *question_rr; + ldns_rdf *name_rdf; + + packet = ldns_pkt_new(); + if (!packet) { + return LDNS_STATUS_MEM_ERR; + } + + if (!ldns_pkt_set_flags(packet, flags)) { + return LDNS_STATUS_ERR; + } + + question_rr = ldns_rr_new(); + if (!question_rr) { + return LDNS_STATUS_MEM_ERR; + } + + if (rr_type == 0) { + rr_type = LDNS_RR_TYPE_A; + } + if (rr_class == 0) { + rr_class = LDNS_RR_CLASS_IN; + } + + if (ldns_str2rdf_dname(&name_rdf, name) == LDNS_STATUS_OK) { + ldns_rr_set_owner(question_rr, name_rdf); + ldns_rr_set_type(question_rr, rr_type); + ldns_rr_set_class(question_rr, rr_class); + ldns_rr_set_question(question_rr, true); + + ldns_pkt_push_rr(packet, LDNS_SECTION_QUESTION, question_rr); + } else { + ldns_rr_free(question_rr); + ldns_pkt_free(packet); + return LDNS_STATUS_ERR; + } + + packet->_tsig_rr = NULL; + + ldns_pkt_set_answerfrom(packet, NULL); + if (p) { + *p = packet; + return LDNS_STATUS_OK; + } else { + return LDNS_STATUS_NULL; + } +} + +ldns_pkt * +ldns_pkt_query_new(ldns_rdf *rr_name, ldns_rr_type rr_type, ldns_rr_class rr_class, + uint16_t flags) +{ + ldns_pkt *packet; + ldns_rr *question_rr; + + packet = ldns_pkt_new(); + if (!packet) { + return NULL; + } + + if (!ldns_pkt_set_flags(packet, flags)) { + return NULL; + } + + question_rr = ldns_rr_new(); + if (!question_rr) { + return NULL; + } + + if (rr_type == 0) { + rr_type = LDNS_RR_TYPE_A; + } + if (rr_class == 0) { + rr_class = LDNS_RR_CLASS_IN; + } + + ldns_rr_set_owner(question_rr, rr_name); + ldns_rr_set_type(question_rr, rr_type); + ldns_rr_set_class(question_rr, rr_class); + ldns_rr_set_question(question_rr, true); + + packet->_tsig_rr = NULL; + + ldns_pkt_push_rr(packet, LDNS_SECTION_QUESTION, question_rr); + + return packet; +} + +ldns_pkt_type +ldns_pkt_reply_type(ldns_pkt *p) +{ + ldns_rr_list *tmp; + + if (!p) { + return LDNS_PACKET_UNKNOWN; + } + + if (ldns_pkt_get_rcode(p) == LDNS_RCODE_NXDOMAIN) { + return LDNS_PACKET_NXDOMAIN; + } + + if (ldns_pkt_ancount(p) == 0 && ldns_pkt_arcount(p) == 0 + && ldns_pkt_nscount(p) == 1) { + + /* check for SOA */ + tmp = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_SOA, + LDNS_SECTION_AUTHORITY); + if (tmp) { + ldns_rr_list_deep_free(tmp); + return LDNS_PACKET_NODATA; + } else { + /* I have no idea ... */ + } + } + + if (ldns_pkt_ancount(p) == 0 && ldns_pkt_nscount(p) > 0) { + tmp = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_NS, + LDNS_SECTION_AUTHORITY); + if (tmp) { + /* there are nameservers here */ + ldns_rr_list_deep_free(tmp); + return LDNS_PACKET_REFERRAL; + } else { + /* I have no idea */ + } + ldns_rr_list_deep_free(tmp); + } + + /* if we cannot determine the packet type, we say it's an + * answer... + */ + return LDNS_PACKET_ANSWER; +} + +ldns_pkt * +ldns_pkt_clone(ldns_pkt *pkt) +{ + ldns_pkt *new_pkt; + + if (!pkt) { + return NULL; + } + new_pkt = ldns_pkt_new(); + + ldns_pkt_set_id(new_pkt, ldns_pkt_id(pkt)); + ldns_pkt_set_qr(new_pkt, ldns_pkt_qr(pkt)); + ldns_pkt_set_aa(new_pkt, ldns_pkt_aa(pkt)); + ldns_pkt_set_tc(new_pkt, ldns_pkt_tc(pkt)); + ldns_pkt_set_rd(new_pkt, ldns_pkt_rd(pkt)); + ldns_pkt_set_cd(new_pkt, ldns_pkt_cd(pkt)); + ldns_pkt_set_ra(new_pkt, ldns_pkt_ra(pkt)); + ldns_pkt_set_ad(new_pkt, ldns_pkt_ad(pkt)); + ldns_pkt_set_opcode(new_pkt, ldns_pkt_get_opcode(pkt)); + ldns_pkt_set_rcode(new_pkt, ldns_pkt_get_rcode(pkt)); + ldns_pkt_set_qdcount(new_pkt, ldns_pkt_qdcount(pkt)); + ldns_pkt_set_ancount(new_pkt, ldns_pkt_ancount(pkt)); + ldns_pkt_set_nscount(new_pkt, ldns_pkt_nscount(pkt)); + ldns_pkt_set_arcount(new_pkt, ldns_pkt_arcount(pkt)); + ldns_pkt_set_answerfrom(new_pkt, ldns_pkt_answerfrom(pkt)); + ldns_pkt_set_querytime(new_pkt, ldns_pkt_querytime(pkt)); + ldns_pkt_set_size(new_pkt, ldns_pkt_size(pkt)); + ldns_pkt_set_tsig(new_pkt, ldns_rr_clone(ldns_pkt_tsig(pkt))); + + ldns_pkt_set_edns_udp_size(new_pkt, ldns_pkt_edns_udp_size(pkt)); + ldns_pkt_set_edns_extended_rcode(new_pkt, + ldns_pkt_edns_extended_rcode(pkt)); + ldns_pkt_set_edns_version(new_pkt, ldns_pkt_edns_version(pkt)); + ldns_pkt_set_edns_z(new_pkt, ldns_pkt_edns_z(pkt)); + if(ldns_pkt_edns_data(pkt)) + ldns_pkt_set_edns_data(new_pkt, + ldns_rdf_clone(ldns_pkt_edns_data(pkt))); + ldns_pkt_set_edns_do(new_pkt, ldns_pkt_edns_do(pkt)); + + ldns_rr_list_deep_free(new_pkt->_question); + ldns_rr_list_deep_free(new_pkt->_answer); + ldns_rr_list_deep_free(new_pkt->_authority); + ldns_rr_list_deep_free(new_pkt->_additional); + new_pkt->_question = ldns_rr_list_clone(ldns_pkt_question(pkt)); + new_pkt->_answer = ldns_rr_list_clone(ldns_pkt_answer(pkt)); + new_pkt->_authority = ldns_rr_list_clone(ldns_pkt_authority(pkt)); + new_pkt->_additional = ldns_rr_list_clone(ldns_pkt_additional(pkt)); + return new_pkt; +} diff --git a/parse.c b/parse.c new file mode 100644 index 00000000000..ac9bdbdd556 --- /dev/null +++ b/parse.c @@ -0,0 +1,448 @@ +/* + * a generic (simple) parser. Use to parse rr's, private key + * information and /etc/resolv.conf files + * + * a Net::DNS like library for C + * LibDNS Team @ NLnet Labs + * (c) NLnet Labs, 2005-2006 + * See the file LICENSE for the license + */ +#include +#include + +#include +#include + +ldns_lookup_table ldns_directive_types[] = { + { LDNS_DIR_TTL, "$TTL" }, + { LDNS_DIR_ORIGIN, "$ORIGIN" }, + { LDNS_DIR_INCLUDE, "$INCLUDE" }, + { 0, NULL } +}; + +/* add max_limit here? */ +ssize_t +ldns_fget_token(FILE *f, char *token, const char *delim, size_t limit) +{ + return ldns_fget_token_l(f, token, delim, limit, NULL); +} + +ssize_t +ldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *line_nr) +{ + int c, prev_c; + int p; /* 0 -> no parenthese seen, >0 nr of ( seen */ + int com, quoted; + char *t; + size_t i; + const char *d; + const char *del; + + /* standard delimeters */ + if (!delim) { + /* from isspace(3) */ + del = LDNS_PARSE_NORMAL; + } else { + del = delim; + } + + p = 0; + i = 0; + com = 0; + quoted = 0; + prev_c = 0; + t = token; + if (del[0] == '"') { + quoted = 1; + } + while ((c = getc(f)) != EOF) { + if (c == '\r') /* carriage return */ + c = ' '; + if (c == '(' && prev_c != '\\' && !quoted) { + /* this only counts for non-comments */ + if (com == 0) { + p++; + } + prev_c = c; + continue; + } + + if (c == ')' && prev_c != '\\' && !quoted) { + /* this only counts for non-comments */ + if (com == 0) { + p--; + } + prev_c = c; + continue; + } + + if (p < 0) { + /* more ) then ( - close off the string */ + *t = '\0'; + return 0; + } + + /* do something with comments ; */ + if (c == ';' && quoted == 0) { + if (prev_c != '\\') { + com = 1; + } + } + if (c == '\"' && com == 0 && prev_c != '\\') { + quoted = 1 - quoted; + } + + if (c == '\n' && com != 0) { + /* comments */ + com = 0; + *t = ' '; + if (line_nr) { + *line_nr = *line_nr + 1; + } + if (p == 0 && i > 0) { + goto tokenread; + } else { + prev_c = c; + continue; + } + } + + if (com == 1) { + *t = ' '; + prev_c = c; + continue; + } + + if (c == '\n' && p != 0 && t > token) { + /* in parentheses */ + if (line_nr) { + *line_nr = *line_nr + 1; + } + *t++ = ' '; + prev_c = c; + continue; + } + + /* check if we hit the delim */ + for (d = del; *d; d++) { + if (c == *d && i > 0 && prev_c != '\\' && p == 0) { + if (c == '\n' && line_nr) { + *line_nr = *line_nr + 1; + } + goto tokenread; + } + } + if (c != '\0' && c != '\n') { + i++; + } + if (limit > 0 && i >= limit) { + *t = '\0'; + return -1; + } + if (c != '\0' && c != '\n') { + *t++ = c; + } + if (c == '\\' && prev_c == '\\') + prev_c = 0; + else prev_c = c; + } + *t = '\0'; + if (c == EOF) { + return (ssize_t)i; + } + + if (i == 0) { + /* nothing read */ + return -1; + } + if (p != 0) { + return -1; + } + return (ssize_t)i; + +tokenread: + ldns_fskipcs_l(f, delim, line_nr); + *t = '\0'; + if (p != 0) { + return -1; + } + + return (ssize_t)i; +} + +ssize_t +ldns_fget_keyword_data(FILE *f, const char *keyword, const char *k_del, char *data, + const char *d_del, size_t data_limit) +{ + return ldns_fget_keyword_data_l(f, keyword, k_del, data, d_del, + data_limit, NULL); +} + +ssize_t +ldns_fget_keyword_data_l(FILE *f, const char *keyword, const char *k_del, char *data, + const char *d_del, size_t data_limit, int *line_nr) +{ + /* we assume: keyword|sep|data */ + char *fkeyword; + ssize_t i; + + if(strlen(keyword) >= LDNS_MAX_KEYWORDLEN) + return -1; + fkeyword = LDNS_XMALLOC(char, LDNS_MAX_KEYWORDLEN); + if(!fkeyword) + return -1; + + i = ldns_fget_token(f, fkeyword, k_del, LDNS_MAX_KEYWORDLEN); + if(i==0 || i==-1) { + LDNS_FREE(fkeyword); + return -1; + } + + /* case??? i instead of strlen? */ + if (strncmp(fkeyword, keyword, LDNS_MAX_KEYWORDLEN - 1) == 0) { + /* whee! */ + /* printf("%s\n%s\n", "Matching keyword", fkeyword); */ + i = ldns_fget_token_l(f, data, d_del, data_limit, line_nr); + LDNS_FREE(fkeyword); + return i; + } else { + /*printf("no match for %s (read: %s)\n", keyword, fkeyword);*/ + LDNS_FREE(fkeyword); + return -1; + } +} + + +ssize_t +ldns_bget_token(ldns_buffer *b, char *token, const char *delim, size_t limit) +{ + int c, lc; + int p; /* 0 -> no parenthese seen, >0 nr of ( seen */ + int com, quoted; + char *t; + size_t i; + const char *d; + const char *del; + + /* standard delimiters */ + if (!delim) { + /* from isspace(3) */ + del = LDNS_PARSE_NORMAL; + } else { + del = delim; + } + + p = 0; + i = 0; + com = 0; + quoted = 0; + t = token; + lc = 0; + if (del[0] == '"') { + quoted = 1; + } + + while ((c = ldns_bgetc(b)) != EOF) { + if (c == '\r') /* carriage return */ + c = ' '; + if (c == '(' && lc != '\\' && !quoted) { + /* this only counts for non-comments */ + if (com == 0) { + p++; + } + lc = c; + continue; + } + + if (c == ')' && lc != '\\' && !quoted) { + /* this only counts for non-comments */ + if (com == 0) { + p--; + } + lc = c; + continue; + } + + if (p < 0) { + /* more ) then ( */ + *t = '\0'; + return 0; + } + + /* do something with comments ; */ + if (c == ';' && quoted == 0) { + if (lc != '\\') { + com = 1; + } + } + if (c == '"' && com == 0 && lc != '\\') { + quoted = 1 - quoted; + } + + if (c == '\n' && com != 0) { + /* comments */ + com = 0; + *t = ' '; + lc = c; + continue; + } + + if (com == 1) { + *t = ' '; + lc = c; + continue; + } + + if (c == '\n' && p != 0) { + /* in parentheses */ + *t++ = ' '; + lc = c; + continue; + } + + /* check if we hit the delim */ + for (d = del; *d; d++) { + if (c == *d && lc != '\\' && p == 0) { + goto tokenread; + } + } + + i++; + if (limit > 0 && i >= limit) { + *t = '\0'; + return -1; + } + *t++ = c; + + if (c == '\\' && lc == '\\') { + lc = 0; + } else { + lc = c; + } + } + *t = '\0'; + if (i == 0) { + /* nothing read */ + return -1; + } + if (p != 0) { + return -1; + } + return (ssize_t)i; + +tokenread: + ldns_bskipcs(b, delim); + *t = '\0'; + + if (p != 0) { + return -1; + } + return (ssize_t)i; +} + +void +ldns_bskipc(ldns_buffer *buffer, char c) +{ + while (c == (char) ldns_buffer_read_u8_at(buffer, ldns_buffer_position(buffer))) { + if (ldns_buffer_available_at(buffer, + buffer->_position + sizeof(char), sizeof(char))) { + buffer->_position += sizeof(char); + } else { + return; + } + } +} + +void +ldns_bskipcs(ldns_buffer *buffer, const char *s) +{ + bool found; + char c; + const char *d; + + while(ldns_buffer_available_at(buffer, buffer->_position, sizeof(char))) { + c = (char) ldns_buffer_read_u8_at(buffer, buffer->_position); + found = false; + for (d = s; *d; d++) { + if (*d == c) { + found = true; + } + } + if (found && buffer->_limit > buffer->_position) { + buffer->_position += sizeof(char); + } else { + return; + } + } +} + +void +ldns_fskipc(ATTR_UNUSED(FILE *fp), ATTR_UNUSED(char c)) +{ +} + + +void +ldns_fskipcs(FILE *fp, const char *s) +{ + ldns_fskipcs_l(fp, s, NULL); +} + +void +ldns_fskipcs_l(FILE *fp, const char *s, int *line_nr) +{ + bool found; + int c; + const char *d; + + while ((c = fgetc(fp)) != EOF) { + if (line_nr && c == '\n') { + *line_nr = *line_nr + 1; + } + found = false; + for (d = s; *d; d++) { + if (*d == c) { + found = true; + } + } + if (!found) { + /* with getc, we've read too far */ + ungetc(c, fp); + return; + } + } +} + +ssize_t +ldns_bget_keyword_data(ldns_buffer *b, const char *keyword, const char *k_del, char +*data, const char *d_del, size_t data_limit) +{ + /* we assume: keyword|sep|data */ + char *fkeyword; + ssize_t i; + + if(strlen(keyword) >= LDNS_MAX_KEYWORDLEN) + return -1; + fkeyword = LDNS_XMALLOC(char, LDNS_MAX_KEYWORDLEN); + if(!fkeyword) + return -1; /* out of memory */ + + i = ldns_bget_token(b, fkeyword, k_del, data_limit); + if(i==0 || i==-1) { + LDNS_FREE(fkeyword); + return -1; /* nothing read */ + } + + /* case??? */ + if (strncmp(fkeyword, keyword, strlen(keyword)) == 0) { + LDNS_FREE(fkeyword); + /* whee, the match! */ + /* retrieve it's data */ + i = ldns_bget_token(b, data, d_del, 0); + return i; + } else { + LDNS_FREE(fkeyword); + return -1; + } +} + diff --git a/rbtree.c b/rbtree.c new file mode 100644 index 00000000000..4fbc067eb70 --- /dev/null +++ b/rbtree.c @@ -0,0 +1,670 @@ +/* + * rbtree.c -- generic red black tree + * + * Taken from Unbound, modified for ldns + * + * Copyright (c) 2001-2008, 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * \file + * Implementation of a redblack tree. + */ + +#include +#include +#include +#include + +/** Node colour black */ +#define BLACK 0 +/** Node colour red */ +#define RED 1 + +/** the NULL node, global alloc */ +ldns_rbnode_t ldns_rbtree_null_node = { + LDNS_RBTREE_NULL, /* Parent. */ + LDNS_RBTREE_NULL, /* Left. */ + LDNS_RBTREE_NULL, /* Right. */ + NULL, /* Key. */ + NULL, /* Data. */ + BLACK /* Color. */ +}; + +/** rotate subtree left (to preserve redblack property) */ +static void ldns_rbtree_rotate_left(ldns_rbtree_t *rbtree, ldns_rbnode_t *node); +/** rotate subtree right (to preserve redblack property) */ +static void ldns_rbtree_rotate_right(ldns_rbtree_t *rbtree, ldns_rbnode_t *node); +/** Fixup node colours when insert happened */ +static void ldns_rbtree_insert_fixup(ldns_rbtree_t *rbtree, ldns_rbnode_t *node); +/** Fixup node colours when delete happened */ +static void ldns_rbtree_delete_fixup(ldns_rbtree_t* rbtree, ldns_rbnode_t* child, ldns_rbnode_t* child_parent); + +/* + * Creates a new red black tree, intializes and returns a pointer to it. + * + * Return NULL on failure. + * + */ +ldns_rbtree_t * +ldns_rbtree_create (int (*cmpf)(const void *, const void *)) +{ + ldns_rbtree_t *rbtree; + + /* Allocate memory for it */ + rbtree = (ldns_rbtree_t *) LDNS_MALLOC(ldns_rbtree_t); + if (!rbtree) { + return NULL; + } + + /* Initialize it */ + ldns_rbtree_init(rbtree, cmpf); + + return rbtree; +} + +void +ldns_rbtree_init(ldns_rbtree_t *rbtree, int (*cmpf)(const void *, const void *)) +{ + /* Initialize it */ + rbtree->root = LDNS_RBTREE_NULL; + rbtree->count = 0; + rbtree->cmp = cmpf; +} + +void +ldns_rbtree_free(ldns_rbtree_t *rbtree) +{ + LDNS_FREE(rbtree); +} + +/* + * Rotates the node to the left. + * + */ +static void +ldns_rbtree_rotate_left(ldns_rbtree_t *rbtree, ldns_rbnode_t *node) +{ + ldns_rbnode_t *right = node->right; + node->right = right->left; + if (right->left != LDNS_RBTREE_NULL) + right->left->parent = node; + + right->parent = node->parent; + + if (node->parent != LDNS_RBTREE_NULL) { + if (node == node->parent->left) { + node->parent->left = right; + } else { + node->parent->right = right; + } + } else { + rbtree->root = right; + } + right->left = node; + node->parent = right; +} + +/* + * Rotates the node to the right. + * + */ +static void +ldns_rbtree_rotate_right(ldns_rbtree_t *rbtree, ldns_rbnode_t *node) +{ + ldns_rbnode_t *left = node->left; + node->left = left->right; + if (left->right != LDNS_RBTREE_NULL) + left->right->parent = node; + + left->parent = node->parent; + + if (node->parent != LDNS_RBTREE_NULL) { + if (node == node->parent->right) { + node->parent->right = left; + } else { + node->parent->left = left; + } + } else { + rbtree->root = left; + } + left->right = node; + node->parent = left; +} + +static void +ldns_rbtree_insert_fixup(ldns_rbtree_t *rbtree, ldns_rbnode_t *node) +{ + ldns_rbnode_t *uncle; + + /* While not at the root and need fixing... */ + while (node != rbtree->root && node->parent->color == RED) { + /* If our parent is left child of our grandparent... */ + if (node->parent == node->parent->parent->left) { + uncle = node->parent->parent->right; + + /* If our uncle is red... */ + if (uncle->color == RED) { + /* Paint the parent and the uncle black... */ + node->parent->color = BLACK; + uncle->color = BLACK; + + /* And the grandparent red... */ + node->parent->parent->color = RED; + + /* And continue fixing the grandparent */ + node = node->parent->parent; + } else { /* Our uncle is black... */ + /* Are we the right child? */ + if (node == node->parent->right) { + node = node->parent; + ldns_rbtree_rotate_left(rbtree, node); + } + /* Now we're the left child, repaint and rotate... */ + node->parent->color = BLACK; + node->parent->parent->color = RED; + ldns_rbtree_rotate_right(rbtree, node->parent->parent); + } + } else { + uncle = node->parent->parent->left; + + /* If our uncle is red... */ + if (uncle->color == RED) { + /* Paint the parent and the uncle black... */ + node->parent->color = BLACK; + uncle->color = BLACK; + + /* And the grandparent red... */ + node->parent->parent->color = RED; + + /* And continue fixing the grandparent */ + node = node->parent->parent; + } else { /* Our uncle is black... */ + /* Are we the right child? */ + if (node == node->parent->left) { + node = node->parent; + ldns_rbtree_rotate_right(rbtree, node); + } + /* Now we're the right child, repaint and rotate... */ + node->parent->color = BLACK; + node->parent->parent->color = RED; + ldns_rbtree_rotate_left(rbtree, node->parent->parent); + } + } + } + rbtree->root->color = BLACK; +} + +void +ldns_rbtree_insert_vref(ldns_rbnode_t *data, void *rbtree) +{ + (void) ldns_rbtree_insert((ldns_rbtree_t *) rbtree, + data); +} + +/* + * Inserts a node into a red black tree. + * + * Returns NULL on failure or the pointer to the newly added node + * otherwise. + */ +ldns_rbnode_t * +ldns_rbtree_insert (ldns_rbtree_t *rbtree, ldns_rbnode_t *data) +{ + /* XXX Not necessary, but keeps compiler quiet... */ + int r = 0; + + /* We start at the root of the tree */ + ldns_rbnode_t *node = rbtree->root; + ldns_rbnode_t *parent = LDNS_RBTREE_NULL; + + /* Lets find the new parent... */ + while (node != LDNS_RBTREE_NULL) { + /* Compare two keys, do we have a duplicate? */ + if ((r = rbtree->cmp(data->key, node->key)) == 0) { + return NULL; + } + parent = node; + + if (r < 0) { + node = node->left; + } else { + node = node->right; + } + } + + /* Initialize the new node */ + data->parent = parent; + data->left = data->right = LDNS_RBTREE_NULL; + data->color = RED; + rbtree->count++; + + /* Insert it into the tree... */ + if (parent != LDNS_RBTREE_NULL) { + if (r < 0) { + parent->left = data; + } else { + parent->right = data; + } + } else { + rbtree->root = data; + } + + /* Fix up the red-black properties... */ + ldns_rbtree_insert_fixup(rbtree, data); + + return data; +} + +/* + * Searches the red black tree, returns the data if key is found or NULL otherwise. + * + */ +ldns_rbnode_t * +ldns_rbtree_search (ldns_rbtree_t *rbtree, const void *key) +{ + ldns_rbnode_t *node; + + if (ldns_rbtree_find_less_equal(rbtree, key, &node)) { + return node; + } else { + return NULL; + } +} + +/** helpers for delete: swap node colours */ +static void swap_int8(uint8_t* x, uint8_t* y) +{ + uint8_t t = *x; *x = *y; *y = t; +} + +/** helpers for delete: swap node pointers */ +static void swap_np(ldns_rbnode_t** x, ldns_rbnode_t** y) +{ + ldns_rbnode_t* t = *x; *x = *y; *y = t; +} + +/** Update parent pointers of child trees of 'parent' */ +static void change_parent_ptr(ldns_rbtree_t* rbtree, ldns_rbnode_t* parent, ldns_rbnode_t* old, ldns_rbnode_t* new) +{ + if(parent == LDNS_RBTREE_NULL) + { + if(rbtree->root == old) rbtree->root = new; + return; + } + if(parent->left == old) parent->left = new; + if(parent->right == old) parent->right = new; +} +/** Update parent pointer of a node 'child' */ +static void change_child_ptr(ldns_rbnode_t* child, ldns_rbnode_t* old, ldns_rbnode_t* new) +{ + if(child == LDNS_RBTREE_NULL) return; + if(child->parent == old) child->parent = new; +} + +ldns_rbnode_t* +ldns_rbtree_delete(ldns_rbtree_t *rbtree, const void *key) +{ + ldns_rbnode_t *to_delete; + ldns_rbnode_t *child; + if((to_delete = ldns_rbtree_search(rbtree, key)) == 0) return 0; + rbtree->count--; + + /* make sure we have at most one non-leaf child */ + if(to_delete->left != LDNS_RBTREE_NULL && + to_delete->right != LDNS_RBTREE_NULL) + { + /* swap with smallest from right subtree (or largest from left) */ + ldns_rbnode_t *smright = to_delete->right; + while(smright->left != LDNS_RBTREE_NULL) + smright = smright->left; + /* swap the smright and to_delete elements in the tree, + * but the ldns_rbnode_t is first part of user data struct + * so cannot just swap the keys and data pointers. Instead + * readjust the pointers left,right,parent */ + + /* swap colors - colors are tied to the position in the tree */ + swap_int8(&to_delete->color, &smright->color); + + /* swap child pointers in parents of smright/to_delete */ + change_parent_ptr(rbtree, to_delete->parent, to_delete, smright); + if(to_delete->right != smright) + change_parent_ptr(rbtree, smright->parent, smright, to_delete); + + /* swap parent pointers in children of smright/to_delete */ + change_child_ptr(smright->left, smright, to_delete); + change_child_ptr(smright->left, smright, to_delete); + change_child_ptr(smright->right, smright, to_delete); + change_child_ptr(smright->right, smright, to_delete); + change_child_ptr(to_delete->left, to_delete, smright); + if(to_delete->right != smright) + change_child_ptr(to_delete->right, to_delete, smright); + if(to_delete->right == smright) + { + /* set up so after swap they work */ + to_delete->right = to_delete; + smright->parent = smright; + } + + /* swap pointers in to_delete/smright nodes */ + swap_np(&to_delete->parent, &smright->parent); + swap_np(&to_delete->left, &smright->left); + swap_np(&to_delete->right, &smright->right); + + /* now delete to_delete (which is at the location where the smright previously was) */ + } + + if(to_delete->left != LDNS_RBTREE_NULL) child = to_delete->left; + else child = to_delete->right; + + /* unlink to_delete from the tree, replace to_delete with child */ + change_parent_ptr(rbtree, to_delete->parent, to_delete, child); + change_child_ptr(child, to_delete, to_delete->parent); + + if(to_delete->color == RED) + { + /* if node is red then the child (black) can be swapped in */ + } + else if(child->color == RED) + { + /* change child to BLACK, removing a RED node is no problem */ + if(child!=LDNS_RBTREE_NULL) child->color = BLACK; + } + else ldns_rbtree_delete_fixup(rbtree, child, to_delete->parent); + + /* unlink completely */ + to_delete->parent = LDNS_RBTREE_NULL; + to_delete->left = LDNS_RBTREE_NULL; + to_delete->right = LDNS_RBTREE_NULL; + to_delete->color = BLACK; + return to_delete; +} + +static void ldns_rbtree_delete_fixup(ldns_rbtree_t* rbtree, ldns_rbnode_t* child, ldns_rbnode_t* child_parent) +{ + ldns_rbnode_t* sibling; + int go_up = 1; + + /* determine sibling to the node that is one-black short */ + if(child_parent->right == child) sibling = child_parent->left; + else sibling = child_parent->right; + + while(go_up) + { + if(child_parent == LDNS_RBTREE_NULL) + { + /* removed parent==black from root, every path, so ok */ + return; + } + + if(sibling->color == RED) + { /* rotate to get a black sibling */ + child_parent->color = RED; + sibling->color = BLACK; + if(child_parent->right == child) + ldns_rbtree_rotate_right(rbtree, child_parent); + else ldns_rbtree_rotate_left(rbtree, child_parent); + /* new sibling after rotation */ + if(child_parent->right == child) sibling = child_parent->left; + else sibling = child_parent->right; + } + + if(child_parent->color == BLACK + && sibling->color == BLACK + && sibling->left->color == BLACK + && sibling->right->color == BLACK) + { /* fixup local with recolor of sibling */ + if(sibling != LDNS_RBTREE_NULL) + sibling->color = RED; + + child = child_parent; + child_parent = child_parent->parent; + /* prepare to go up, new sibling */ + if(child_parent->right == child) sibling = child_parent->left; + else sibling = child_parent->right; + } + else go_up = 0; + } + + if(child_parent->color == RED + && sibling->color == BLACK + && sibling->left->color == BLACK + && sibling->right->color == BLACK) + { + /* move red to sibling to rebalance */ + if(sibling != LDNS_RBTREE_NULL) + sibling->color = RED; + child_parent->color = BLACK; + return; + } + + /* get a new sibling, by rotating at sibling. See which child + of sibling is red */ + if(child_parent->right == child + && sibling->color == BLACK + && sibling->right->color == RED + && sibling->left->color == BLACK) + { + sibling->color = RED; + sibling->right->color = BLACK; + ldns_rbtree_rotate_left(rbtree, sibling); + /* new sibling after rotation */ + if(child_parent->right == child) sibling = child_parent->left; + else sibling = child_parent->right; + } + else if(child_parent->left == child + && sibling->color == BLACK + && sibling->left->color == RED + && sibling->right->color == BLACK) + { + sibling->color = RED; + sibling->left->color = BLACK; + ldns_rbtree_rotate_right(rbtree, sibling); + /* new sibling after rotation */ + if(child_parent->right == child) sibling = child_parent->left; + else sibling = child_parent->right; + } + + /* now we have a black sibling with a red child. rotate and exchange colors. */ + sibling->color = child_parent->color; + child_parent->color = BLACK; + if(child_parent->right == child) + { + sibling->left->color = BLACK; + ldns_rbtree_rotate_right(rbtree, child_parent); + } + else + { + sibling->right->color = BLACK; + ldns_rbtree_rotate_left(rbtree, child_parent); + } +} + +int +ldns_rbtree_find_less_equal(ldns_rbtree_t *rbtree, const void *key, ldns_rbnode_t **result) +{ + int r; + ldns_rbnode_t *node; + + /* We start at root... */ + node = rbtree->root; + + *result = NULL; + + /* While there are children... */ + while (node != LDNS_RBTREE_NULL) { + r = rbtree->cmp(key, node->key); + if (r == 0) { + /* Exact match */ + *result = node; + return 1; + } + if (r < 0) { + node = node->left; + } else { + /* Temporary match */ + *result = node; + node = node->right; + } + } + return 0; +} + +/* + * Finds the first element in the red black tree + * + */ +ldns_rbnode_t * +ldns_rbtree_first (ldns_rbtree_t *rbtree) +{ + ldns_rbnode_t *node = rbtree->root; + + if (rbtree->root != LDNS_RBTREE_NULL) { + for (node = rbtree->root; node->left != LDNS_RBTREE_NULL; node = node->left); + } + return node; +} + +ldns_rbnode_t * +ldns_rbtree_last (ldns_rbtree_t *rbtree) +{ + ldns_rbnode_t *node = rbtree->root; + + if (rbtree->root != LDNS_RBTREE_NULL) { + for (node = rbtree->root; node->right != LDNS_RBTREE_NULL; node = node->right); + } + return node; +} + +/* + * Returns the next node... + * + */ +ldns_rbnode_t * +ldns_rbtree_next (ldns_rbnode_t *node) +{ + ldns_rbnode_t *parent; + + if (node->right != LDNS_RBTREE_NULL) { + /* One right, then keep on going left... */ + for (node = node->right; + node->left != LDNS_RBTREE_NULL; + node = node->left); + } else { + parent = node->parent; + while (parent != LDNS_RBTREE_NULL && node == parent->right) { + node = parent; + parent = parent->parent; + } + node = parent; + } + return node; +} + +ldns_rbnode_t * +ldns_rbtree_previous(ldns_rbnode_t *node) +{ + ldns_rbnode_t *parent; + + if (node->left != LDNS_RBTREE_NULL) { + /* One left, then keep on going right... */ + for (node = node->left; + node->right != LDNS_RBTREE_NULL; + node = node->right); + } else { + parent = node->parent; + while (parent != LDNS_RBTREE_NULL && node == parent->left) { + node = parent; + parent = parent->parent; + } + node = parent; + } + return node; +} + +/** + * split off elements number of elements from the start + * of the name tree and return a new tree + */ +ldns_rbtree_t * +ldns_rbtree_split(ldns_rbtree_t *tree, + size_t elements) +{ + ldns_rbtree_t *new_tree; + ldns_rbnode_t *cur_node; + ldns_rbnode_t *move_node; + size_t count = 0; + + new_tree = ldns_rbtree_create(tree->cmp); + + cur_node = ldns_rbtree_first(tree); + while (count < elements && cur_node != LDNS_RBTREE_NULL) { + move_node = ldns_rbtree_delete(tree, cur_node->key); + (void)ldns_rbtree_insert(new_tree, move_node); + cur_node = ldns_rbtree_first(tree); + count++; + } + + return new_tree; +} + +/* + * add all node from the second tree to the first (removing them from the + * second), and fix up nsec(3)s if present + */ +void +ldns_rbtree_join(ldns_rbtree_t *tree1, ldns_rbtree_t *tree2) +{ + ldns_traverse_postorder(tree2, ldns_rbtree_insert_vref, tree1); +} + +/** recursive descent traverse */ +static void +traverse_post(void (*func)(ldns_rbnode_t*, void*), void* arg, + ldns_rbnode_t* node) +{ + if(!node || node == LDNS_RBTREE_NULL) + return; + /* recurse */ + traverse_post(func, arg, node->left); + traverse_post(func, arg, node->right); + /* call user func */ + (*func)(node, arg); +} + +void +ldns_traverse_postorder(ldns_rbtree_t* tree, + void (*func)(ldns_rbnode_t*, void*), void* arg) +{ + traverse_post(func, arg, tree->root); +} diff --git a/rdata.c b/rdata.c new file mode 100644 index 00000000000..8af16a13a1c --- /dev/null +++ b/rdata.c @@ -0,0 +1,675 @@ +/* + * rdata.c + * + * rdata implementation + * + * a Net::DNS like library for C + * + * (c) NLnet Labs, 2004-2006 + * + * See the file LICENSE for the license + */ + +#include + +#include + +/* + * Access functions + * do this as functions to get type checking + */ + +/* read */ +size_t +ldns_rdf_size(const ldns_rdf *rd) +{ + assert(rd != NULL); + return rd->_size; +} + +ldns_rdf_type +ldns_rdf_get_type(const ldns_rdf *rd) +{ + assert(rd != NULL); + return rd->_type; +} + +uint8_t * +ldns_rdf_data(const ldns_rdf *rd) +{ + assert(rd != NULL); + return rd->_data; +} + +/* write */ +void +ldns_rdf_set_size(ldns_rdf *rd, size_t size) +{ + assert(rd != NULL); + rd->_size = size; +} + +void +ldns_rdf_set_type(ldns_rdf *rd, ldns_rdf_type type) +{ + assert(rd != NULL); + rd->_type = type; +} + +void +ldns_rdf_set_data(ldns_rdf *rd, void *data) +{ + /* only copy the pointer */ + assert(rd != NULL); + rd->_data = data; +} + +/* for types that allow it, return + * the native/host order type */ +uint8_t +ldns_rdf2native_int8(const ldns_rdf *rd) +{ + uint8_t data; + + /* only allow 8 bit rdfs */ + if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_BYTE) { + return 0; + } + + memcpy(&data, ldns_rdf_data(rd), sizeof(data)); + return data; +} + +uint16_t +ldns_rdf2native_int16(const ldns_rdf *rd) +{ + uint16_t data; + + /* only allow 16 bit rdfs */ + if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_WORD) { + return 0; + } + + memcpy(&data, ldns_rdf_data(rd), sizeof(data)); + return ntohs(data); +} + +uint32_t +ldns_rdf2native_int32(const ldns_rdf *rd) +{ + uint32_t data; + + /* only allow 32 bit rdfs */ + if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_DOUBLEWORD) { + return 0; + } + + memcpy(&data, ldns_rdf_data(rd), sizeof(data)); + return ntohl(data); +} + +time_t +ldns_rdf2native_time_t(const ldns_rdf *rd) +{ + uint32_t data; + + switch(ldns_rdf_get_type(rd)) { + case LDNS_RDF_TYPE_TIME: + memcpy(&data, ldns_rdf_data(rd), sizeof(data)); + return (time_t)ntohl(data); + default: + return 0; + } +} + +ldns_rdf * +ldns_native2rdf_int8(ldns_rdf_type type, uint8_t value) +{ + return ldns_rdf_new_frm_data(type, LDNS_RDF_SIZE_BYTE, &value); +} + +ldns_rdf * +ldns_native2rdf_int16(ldns_rdf_type type, uint16_t value) +{ + uint16_t *rdf_data = LDNS_XMALLOC(uint16_t, 1); + ldns_rdf* rdf; + if (!rdf_data) { + return NULL; + } + ldns_write_uint16(rdf_data, value); + rdf = ldns_rdf_new(type, LDNS_RDF_SIZE_WORD, rdf_data); + if(!rdf) + LDNS_FREE(rdf_data); + return rdf; +} + +ldns_rdf * +ldns_native2rdf_int32(ldns_rdf_type type, uint32_t value) +{ + uint32_t *rdf_data = LDNS_XMALLOC(uint32_t, 1); + ldns_rdf* rdf; + if (!rdf_data) { + return NULL; + } + ldns_write_uint32(rdf_data, value); + rdf = ldns_rdf_new(type, LDNS_RDF_SIZE_DOUBLEWORD, rdf_data); + if(!rdf) + LDNS_FREE(rdf_data); + return rdf; +} + +ldns_rdf * +ldns_native2rdf_int16_data(size_t size, uint8_t *data) +{ + uint8_t *rdf_data = LDNS_XMALLOC(uint8_t, size + 2); + ldns_rdf* rdf; + if (!rdf_data) { + return NULL; + } + ldns_write_uint16(rdf_data, size); + memcpy(rdf_data + 2, data, size); + rdf = ldns_rdf_new(LDNS_RDF_TYPE_INT16_DATA, size + 2, rdf_data); + if(!rdf) + LDNS_FREE(rdf_data); + return rdf; +} + +/* note: data must be allocated memory */ +ldns_rdf * +ldns_rdf_new(ldns_rdf_type type, size_t size, void *data) +{ + ldns_rdf *rd; + rd = LDNS_MALLOC(ldns_rdf); + if (!rd) { + return NULL; + } + ldns_rdf_set_size(rd, size); + ldns_rdf_set_type(rd, type); + ldns_rdf_set_data(rd, data); + return rd; +} + +ldns_rdf * +ldns_rdf_new_frm_data(ldns_rdf_type type, size_t size, const void *data) +{ + ldns_rdf *rdf; + + /* if the size is too big, fail */ + if (size > LDNS_MAX_RDFLEN) { + return NULL; + } + + /* allocate space */ + rdf = LDNS_MALLOC(ldns_rdf); + if (!rdf) { + return NULL; + } + rdf->_data = LDNS_XMALLOC(uint8_t, size); + if (!rdf->_data) { + LDNS_FREE(rdf); + return NULL; + } + + /* set the values */ + ldns_rdf_set_type(rdf, type); + ldns_rdf_set_size(rdf, size); + memcpy(rdf->_data, data, size); + + return rdf; +} + +ldns_rdf * +ldns_rdf_clone(const ldns_rdf *rd) +{ + assert(rd != NULL); + return (ldns_rdf_new_frm_data( ldns_rdf_get_type(rd), + ldns_rdf_size(rd), ldns_rdf_data(rd))); +} + +void +ldns_rdf_deep_free(ldns_rdf *rd) +{ + if (rd) { + if (rd->_data) { + LDNS_FREE(rd->_data); + } + LDNS_FREE(rd); + } +} + +void +ldns_rdf_free(ldns_rdf *rd) +{ + if (rd) { + LDNS_FREE(rd); + } +} + +ldns_rdf * +ldns_rdf_new_frm_str(ldns_rdf_type type, const char *str) +{ + ldns_rdf *rdf = NULL; + ldns_status status; + + switch (type) { + case LDNS_RDF_TYPE_DNAME: + status = ldns_str2rdf_dname(&rdf, str); + break; + case LDNS_RDF_TYPE_INT8: + status = ldns_str2rdf_int8(&rdf, str); + break; + case LDNS_RDF_TYPE_INT16: + status = ldns_str2rdf_int16(&rdf, str); + break; + case LDNS_RDF_TYPE_INT32: + status = ldns_str2rdf_int32(&rdf, str); + break; + case LDNS_RDF_TYPE_A: + status = ldns_str2rdf_a(&rdf, str); + break; + case LDNS_RDF_TYPE_AAAA: + status = ldns_str2rdf_aaaa(&rdf, str); + break; + case LDNS_RDF_TYPE_STR: + status = ldns_str2rdf_str(&rdf, str); + break; + case LDNS_RDF_TYPE_APL: + status = ldns_str2rdf_apl(&rdf, str); + break; + case LDNS_RDF_TYPE_B64: + status = ldns_str2rdf_b64(&rdf, str); + break; + case LDNS_RDF_TYPE_B32_EXT: + status = ldns_str2rdf_b32_ext(&rdf, str); + break; + case LDNS_RDF_TYPE_HEX: + status = ldns_str2rdf_hex(&rdf, str); + break; + case LDNS_RDF_TYPE_NSEC: + status = ldns_str2rdf_nsec(&rdf, str); + break; + case LDNS_RDF_TYPE_TYPE: + status = ldns_str2rdf_type(&rdf, str); + break; + case LDNS_RDF_TYPE_CLASS: + status = ldns_str2rdf_class(&rdf, str); + break; + case LDNS_RDF_TYPE_CERT_ALG: + status = ldns_str2rdf_cert_alg(&rdf, str); + break; + case LDNS_RDF_TYPE_ALG: + status = ldns_str2rdf_alg(&rdf, str); + break; + case LDNS_RDF_TYPE_UNKNOWN: + status = ldns_str2rdf_unknown(&rdf, str); + break; + case LDNS_RDF_TYPE_TIME: + status = ldns_str2rdf_time(&rdf, str); + break; + case LDNS_RDF_TYPE_PERIOD: + status = ldns_str2rdf_period(&rdf, str); + break; + case LDNS_RDF_TYPE_TSIG: + status = ldns_str2rdf_tsig(&rdf, str); + break; + case LDNS_RDF_TYPE_SERVICE: + status = ldns_str2rdf_service(&rdf, str); + break; + case LDNS_RDF_TYPE_LOC: + status = ldns_str2rdf_loc(&rdf, str); + break; + case LDNS_RDF_TYPE_WKS: + status = ldns_str2rdf_wks(&rdf, str); + break; + case LDNS_RDF_TYPE_NSAP: + status = ldns_str2rdf_nsap(&rdf, str); + break; + case LDNS_RDF_TYPE_ATMA: + status = ldns_str2rdf_atma(&rdf, str); + break; + case LDNS_RDF_TYPE_IPSECKEY: + status = ldns_str2rdf_ipseckey(&rdf, str); + break; + case LDNS_RDF_TYPE_NSEC3_SALT: + status = ldns_str2rdf_nsec3_salt(&rdf, str); + break; + case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER: + status = ldns_str2rdf_b32_ext(&rdf, str); + break; + case LDNS_RDF_TYPE_NONE: + default: + /* default default ??? */ + status = LDNS_STATUS_ERR; + break; + } + if (LDNS_STATUS_OK == status) { + ldns_rdf_set_type(rdf, type); + return rdf; + } + if (rdf) { + LDNS_FREE(rdf); + } + return NULL; +} + +ldns_status +ldns_rdf_new_frm_fp(ldns_rdf **rdf, ldns_rdf_type type, FILE *fp) +{ + return ldns_rdf_new_frm_fp_l(rdf, type, fp, NULL); +} + +ldns_status +ldns_rdf_new_frm_fp_l(ldns_rdf **rdf, ldns_rdf_type type, FILE *fp, int *line_nr) +{ + char *line; + ldns_rdf *r; + ssize_t t; + + line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1); + if (!line) { + return LDNS_STATUS_MEM_ERR; + } + + /* read an entire line in from the file */ + if ((t = ldns_fget_token_l(fp, line, LDNS_PARSE_SKIP_SPACE, 0, line_nr)) == -1 || t == 0) { + LDNS_FREE(line); + return LDNS_STATUS_SYNTAX_RDATA_ERR; + } + r = ldns_rdf_new_frm_str(type, (const char*) line); + LDNS_FREE(line); + if (rdf) { + *rdf = r; + return LDNS_STATUS_OK; + } else { + return LDNS_STATUS_NULL; + } +} + +ldns_rdf * +ldns_rdf_address_reverse(ldns_rdf *rd) +{ + uint8_t buf_4[LDNS_IP4ADDRLEN]; + uint8_t buf_6[LDNS_IP6ADDRLEN * 2]; + ldns_rdf *rev; + ldns_rdf *in_addr; + ldns_rdf *ret_dname; + uint8_t octet; + uint8_t nnibble; + uint8_t nibble; + uint8_t i, j; + + char *char_dname; + int nbit; + + if (ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_A && + ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_AAAA) { + return NULL; + } + + in_addr = NULL; + ret_dname = NULL; + + switch(ldns_rdf_get_type(rd)) { + case LDNS_RDF_TYPE_A: + /* the length of the buffer is 4 */ + buf_4[3] = ldns_rdf_data(rd)[0]; + buf_4[2] = ldns_rdf_data(rd)[1]; + buf_4[1] = ldns_rdf_data(rd)[2]; + buf_4[0] = ldns_rdf_data(rd)[3]; + in_addr = ldns_dname_new_frm_str("in-addr.arpa."); + if (!in_addr) { + return NULL; + } + /* make a new rdf and convert that back */ + rev = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_A, + LDNS_IP4ADDRLEN, (void*)&buf_4); + if (!rev) { + LDNS_FREE(in_addr); + return NULL; + } + + /* convert rev to a string */ + char_dname = ldns_rdf2str(rev); + if (!char_dname) { + LDNS_FREE(in_addr); + ldns_rdf_deep_free(rev); + return NULL; + } + /* transform back to rdf with type dname */ + ret_dname = ldns_dname_new_frm_str(char_dname); + if (!ret_dname) { + LDNS_FREE(in_addr); + ldns_rdf_deep_free(rev); + LDNS_FREE(char_dname); + return NULL; + } + /* not needed anymore */ + ldns_rdf_deep_free(rev); + LDNS_FREE(char_dname); + break; + case LDNS_RDF_TYPE_AAAA: + /* some foo magic to reverse the nibbles ... */ + + for (nbit = 127; nbit >= 0; nbit = nbit - 4) { + /* calculate octett (8 bit) */ + octet = ( ((unsigned int) nbit) & 0x78) >> 3; + /* calculate nibble */ + nnibble = ( ((unsigned int) nbit) & 0x04) >> 2; + /* extract nibble */ + nibble = (ldns_rdf_data(rd)[octet] & ( 0xf << (4 * (1 - + nnibble)) ) ) >> ( 4 * (1 - + nnibble)); + + buf_6[(LDNS_IP6ADDRLEN * 2 - 1) - + (octet * 2 + nnibble)] = + (uint8_t)ldns_int_to_hexdigit((int)nibble); + } + + char_dname = LDNS_XMALLOC(char, (LDNS_IP6ADDRLEN * 4)); + if (!char_dname) { + return NULL; + } + char_dname[LDNS_IP6ADDRLEN * 4 - 1] = '\0'; /* closure */ + + /* walk the string and add . 's */ + for (i = 0, j = 0; i < LDNS_IP6ADDRLEN * 2; i++, j = j + 2) { + char_dname[j] = (char)buf_6[i]; + if (i != LDNS_IP6ADDRLEN * 2 - 1) { + char_dname[j + 1] = '.'; + } + } + in_addr = ldns_dname_new_frm_str("ip6.arpa."); + if (!in_addr) { + LDNS_FREE(char_dname); + return NULL; + } + + /* convert rev to a string */ + ret_dname = ldns_dname_new_frm_str(char_dname); + LDNS_FREE(char_dname); + if (!ret_dname) { + ldns_rdf_deep_free(in_addr); + return NULL; + } + break; + default: + break; + } + /* add the suffix */ + rev = ldns_dname_cat_clone(ret_dname, in_addr); + + ldns_rdf_deep_free(ret_dname); + ldns_rdf_deep_free(in_addr); + return rev; +} + +ldns_status +ldns_octet(char *word, size_t *length) +{ + char *s; + char *p; + *length = 0; + + for (s = p = word; *s != '\0'; s++,p++) { + switch (*s) { + case '.': + if (s[1] == '.') { + return LDNS_STATUS_EMPTY_LABEL; + } + *p = *s; + (*length)++; + break; + case '\\': + if ('0' <= s[1] && s[1] <= '9' && + '0' <= s[2] && s[2] <= '9' && + '0' <= s[3] && s[3] <= '9') { + /* \DDD seen */ + int val = ((s[1] - '0') * 100 + + (s[2] - '0') * 10 + (s[3] - '0')); + + if (0 <= val && val <= 255) { + /* this also handles \0 */ + s += 3; + *p = val; + (*length)++; + } else { + return LDNS_STATUS_DDD_OVERFLOW; + } + } else { + /* an espaced character, like \ ? + * remove the '\' keep the rest */ + *p = *++s; + (*length)++; + } + break; + case '\"': + /* non quoted " Is either first or the last character in + * the string */ + + *p = *++s; /* skip it */ + (*length)++; + /* I'm not sure if this is needed in libdns... MG */ + if ( *s == '\0' ) { + /* ok, it was the last one */ + *p = '\0'; + return LDNS_STATUS_OK; + } + break; + default: + *p = *s; + (*length)++; + break; + } + } + *p = '\0'; + return LDNS_STATUS_OK; +} + +int +ldns_rdf_compare(const ldns_rdf *rd1, const ldns_rdf *rd2) +{ + uint16_t i1, i2, i; + uint8_t *d1, *d2; + + /* only when both are not NULL we can say anything about them */ + if (!rd1 && !rd2) { + return 0; + } + if (!rd1 || !rd2) { + return -1; + } + i1 = ldns_rdf_size(rd1); + i2 = ldns_rdf_size(rd2); + + if (i1 < i2) { + return -1; + } else if (i1 > i2) { + return +1; + } else { + d1 = (uint8_t*)ldns_rdf_data(rd1); + d2 = (uint8_t*)ldns_rdf_data(rd2); + for(i = 0; i < i1; i++) { + if (d1[i] < d2[i]) { + return -1; + } else if (d1[i] > d2[i]) { + return +1; + } + } + } + return 0; +} + +uint32_t +ldns_str2period(const char *nptr, const char **endptr) +{ + int sign = 0; + uint32_t i = 0; + uint32_t seconds = 0; + + for(*endptr = nptr; **endptr; (*endptr)++) { + switch (**endptr) { + case ' ': + case '\t': + break; + case '-': + if(sign == 0) { + sign = -1; + } else { + return seconds; + } + break; + case '+': + if(sign == 0) { + sign = 1; + } else { + return seconds; + } + break; + case 's': + case 'S': + seconds += i; + i = 0; + break; + case 'm': + case 'M': + seconds += i * 60; + i = 0; + break; + case 'h': + case 'H': + seconds += i * 60 * 60; + i = 0; + break; + case 'd': + case 'D': + seconds += i * 60 * 60 * 24; + i = 0; + break; + case 'w': + case 'W': + seconds += i * 60 * 60 * 24 * 7; + i = 0; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + i *= 10; + i += (**endptr - '0'); + break; + default: + seconds += i; + /* disregard signedness */ + return seconds; + } + } + seconds += i; + /* disregard signedness */ + return seconds; +} diff --git a/resolver.c b/resolver.c new file mode 100644 index 00000000000..1a788a363fe --- /dev/null +++ b/resolver.c @@ -0,0 +1,1350 @@ +/* + * resolver.c + * + * resolver implementation + * + * a Net::DNS like library for C + * + * (c) NLnet Labs, 2004-2006 + * + * See the file LICENSE for the license + */ + +#include + +#include +#include + +/* Access function for reading + * and setting the different Resolver + * options */ + +/* read */ +uint16_t +ldns_resolver_port(const ldns_resolver *r) +{ + return r->_port; +} + +uint16_t +ldns_resolver_edns_udp_size(const ldns_resolver *r) +{ + return r->_edns_udp_size; +} + +uint8_t +ldns_resolver_retry(const ldns_resolver *r) +{ + return r->_retry; +} + +uint8_t +ldns_resolver_retrans(const ldns_resolver *r) +{ + return r->_retrans; +} + +bool +ldns_resolver_fallback(const ldns_resolver *r) +{ + return r->_fallback; +} + +uint8_t +ldns_resolver_ip6(const ldns_resolver *r) +{ + return r->_ip6; +} + +bool +ldns_resolver_recursive(const ldns_resolver *r) +{ + return r->_recursive; +} + +bool +ldns_resolver_debug(const ldns_resolver *r) +{ + return r->_debug; +} + +bool +ldns_resolver_dnsrch(const ldns_resolver *r) +{ + return r->_dnsrch; +} + +bool +ldns_resolver_fail(const ldns_resolver *r) +{ + return r->_fail; +} + +bool +ldns_resolver_defnames(const ldns_resolver *r) +{ + return r->_defnames; +} + +ldns_rdf * +ldns_resolver_domain(const ldns_resolver *r) +{ + return r->_domain; +} + +ldns_rdf ** +ldns_resolver_searchlist(const ldns_resolver *r) +{ + return r->_searchlist; +} + +ldns_rdf ** +ldns_resolver_nameservers(const ldns_resolver *r) +{ + return r->_nameservers; +} + +size_t +ldns_resolver_nameserver_count(const ldns_resolver *r) +{ + return r->_nameserver_count; +} + +bool +ldns_resolver_dnssec(const ldns_resolver *r) +{ + return r->_dnssec; +} + +bool +ldns_resolver_dnssec_cd(const ldns_resolver *r) +{ + return r->_dnssec_cd; +} + +ldns_rr_list * +ldns_resolver_dnssec_anchors(const ldns_resolver *r) +{ + return r->_dnssec_anchors; +} + +bool +ldns_resolver_trusted_key(const ldns_resolver *r, ldns_rr_list * keys, ldns_rr_list * trusted_keys) +{ + size_t i; + bool result = false; + + ldns_rr_list * trust_anchors; + ldns_rr * cur_rr; + + if (!r || !keys) { return false; } + + trust_anchors = ldns_resolver_dnssec_anchors(r); + + if (!trust_anchors) { return false; } + + for (i = 0; i < ldns_rr_list_rr_count(keys); i++) { + + cur_rr = ldns_rr_list_rr(keys, i); + if (ldns_rr_list_contains_rr(trust_anchors, cur_rr)) { + if (trusted_keys) { ldns_rr_list_push_rr(trusted_keys, cur_rr); } + result = true; + } + } + + return result; +} + +bool +ldns_resolver_igntc(const ldns_resolver *r) +{ + return r->_igntc; +} + +bool +ldns_resolver_usevc(const ldns_resolver *r) +{ + return r->_usevc; +} + +size_t * +ldns_resolver_rtt(const ldns_resolver *r) +{ + return r->_rtt; +} + +size_t +ldns_resolver_nameserver_rtt(const ldns_resolver *r, size_t pos) +{ + size_t *rtt; + + assert(r != NULL); + + rtt = ldns_resolver_rtt(r); + + if (pos >= ldns_resolver_nameserver_count(r)) { + /* error ?*/ + return 0; + } else { + return rtt[pos]; + } + +} + +struct timeval +ldns_resolver_timeout(const ldns_resolver *r) +{ + return r->_timeout; +} + +char * +ldns_resolver_tsig_keyname(const ldns_resolver *r) +{ + return r->_tsig_keyname; +} + +char * +ldns_resolver_tsig_algorithm(const ldns_resolver *r) +{ + return r->_tsig_algorithm; +} + +char * +ldns_resolver_tsig_keydata(const ldns_resolver *r) +{ + return r->_tsig_keydata; +} + +bool +ldns_resolver_random(const ldns_resolver *r) +{ + return r->_random; +} + +size_t +ldns_resolver_searchlist_count(const ldns_resolver *r) +{ + return r->_searchlist_count; +} + +/* write */ +void +ldns_resolver_set_port(ldns_resolver *r, uint16_t p) +{ + r->_port = p; +} + +ldns_rdf * +ldns_resolver_pop_nameserver(ldns_resolver *r) +{ + ldns_rdf **nameservers; + ldns_rdf *pop; + size_t ns_count; + size_t *rtt; + + assert(r != NULL); + + ns_count = ldns_resolver_nameserver_count(r); + nameservers = ldns_resolver_nameservers(r); + rtt = ldns_resolver_rtt(r); + if (ns_count == 0 || !nameservers) { + return NULL; + } + + pop = nameservers[ns_count - 1]; + + nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *, (ns_count - 1)); + rtt = LDNS_XREALLOC(rtt, size_t, (ns_count - 1)); + + if(nameservers) + ldns_resolver_set_nameservers(r, nameservers); + if(rtt) + ldns_resolver_set_rtt(r, rtt); + /* decr the count */ + ldns_resolver_dec_nameserver_count(r); + return pop; +} + +ldns_status +ldns_resolver_push_nameserver(ldns_resolver *r, ldns_rdf *n) +{ + ldns_rdf **nameservers; + size_t ns_count; + size_t *rtt; + + if (ldns_rdf_get_type(n) != LDNS_RDF_TYPE_A && + ldns_rdf_get_type(n) != LDNS_RDF_TYPE_AAAA) { + return LDNS_STATUS_ERR; + } + + ns_count = ldns_resolver_nameserver_count(r); + nameservers = ldns_resolver_nameservers(r); + rtt = ldns_resolver_rtt(r); + + /* make room for the next one */ + if (ns_count == 0) { + nameservers = LDNS_XMALLOC(ldns_rdf *, 1); + } else { + nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *, (ns_count + 1)); + } + if(!nameservers) + return LDNS_STATUS_MEM_ERR; + + /* set the new value in the resolver */ + ldns_resolver_set_nameservers(r, nameservers); + + /* don't forget the rtt */ + if (ns_count == 0) { + rtt = LDNS_XMALLOC(size_t, 1); + } else { + rtt = LDNS_XREALLOC(rtt, size_t, (ns_count + 1)); + } + if(!rtt) + return LDNS_STATUS_MEM_ERR; + + /* slide n in its slot. */ + /* we clone it here, because then we can free the original + * rr's where it stood */ + nameservers[ns_count] = ldns_rdf_clone(n); + rtt[ns_count] = LDNS_RESOLV_RTT_MIN; + ldns_resolver_incr_nameserver_count(r); + ldns_resolver_set_rtt(r, rtt); + return LDNS_STATUS_OK; +} + +ldns_status +ldns_resolver_push_nameserver_rr(ldns_resolver *r, ldns_rr *rr) +{ + ldns_rdf *address; + if ((!rr) || (ldns_rr_get_type(rr) != LDNS_RR_TYPE_A && + ldns_rr_get_type(rr) != LDNS_RR_TYPE_AAAA)) { + return LDNS_STATUS_ERR; + } + address = ldns_rr_rdf(rr, 0); /* extract the ip number */ + if (address) { + return ldns_resolver_push_nameserver(r, address); + } else { + return LDNS_STATUS_ERR; + } +} + +ldns_status +ldns_resolver_push_nameserver_rr_list(ldns_resolver *r, ldns_rr_list *rrlist) +{ + ldns_rr *rr; + ldns_status stat; + size_t i; + + stat = LDNS_STATUS_OK; + if (rrlist) { + for(i = 0; i < ldns_rr_list_rr_count(rrlist); i++) { + rr = ldns_rr_list_rr(rrlist, i); + if (ldns_resolver_push_nameserver_rr(r, rr) != LDNS_STATUS_OK) { + stat = LDNS_STATUS_ERR; + break; + } + } + return stat; + } else { + return LDNS_STATUS_ERR; + } +} + +void +ldns_resolver_set_edns_udp_size(ldns_resolver *r, uint16_t s) +{ + r->_edns_udp_size = s; +} + +void +ldns_resolver_set_recursive(ldns_resolver *r, bool re) +{ + r->_recursive = re; +} + +void +ldns_resolver_set_dnssec(ldns_resolver *r, bool d) +{ + r->_dnssec = d; +} + +void +ldns_resolver_set_dnssec_cd(ldns_resolver *r, bool d) +{ + r->_dnssec_cd = d; +} + +void +ldns_resolver_set_dnssec_anchors(ldns_resolver *r, ldns_rr_list * l) +{ + r->_dnssec_anchors = l; +} + +ldns_status +ldns_resolver_push_dnssec_anchor(ldns_resolver *r, ldns_rr *rr) +{ + ldns_rr_list * trust_anchors; + + if ((!rr) || (ldns_rr_get_type(rr) != LDNS_RR_TYPE_DNSKEY)) { + return LDNS_STATUS_ERR; + } + + if (!(trust_anchors = ldns_resolver_dnssec_anchors(r))) { /* Initialize */ + trust_anchors = ldns_rr_list_new(); + ldns_resolver_set_dnssec_anchors(r, trust_anchors); + } + + return (ldns_rr_list_push_rr(trust_anchors, ldns_rr_clone(rr))) ? LDNS_STATUS_OK : LDNS_STATUS_ERR; +} + +void +ldns_resolver_set_igntc(ldns_resolver *r, bool i) +{ + r->_igntc = i; +} + +void +ldns_resolver_set_usevc(ldns_resolver *r, bool vc) +{ + r->_usevc = vc; +} + +void +ldns_resolver_set_debug(ldns_resolver *r, bool d) +{ + r->_debug = d; +} + +void +ldns_resolver_set_ip6(ldns_resolver *r, uint8_t ip6) +{ + r->_ip6 = ip6; +} + +void +ldns_resolver_set_fail(ldns_resolver *r, bool f) +{ + r->_fail =f; +} + +void +ldns_resolver_set_searchlist_count(ldns_resolver *r, size_t c) +{ + r->_searchlist_count = c; +} + +void +ldns_resolver_set_nameserver_count(ldns_resolver *r, size_t c) +{ + r->_nameserver_count = c; +} + +void +ldns_resolver_set_dnsrch(ldns_resolver *r, bool d) +{ + r->_dnsrch = d; +} + +void +ldns_resolver_set_retry(ldns_resolver *r, uint8_t retry) +{ + r->_retry = retry; +} + +void +ldns_resolver_set_retrans(ldns_resolver *r, uint8_t retrans) +{ + r->_retrans = retrans; +} + +void +ldns_resolver_set_fallback(ldns_resolver *r, bool fallback) +{ + r->_fallback = fallback; +} + +void +ldns_resolver_set_nameservers(ldns_resolver *r, ldns_rdf **n) +{ + r->_nameservers = n; +} + +void +ldns_resolver_set_defnames(ldns_resolver *r, bool d) +{ + r->_defnames = d; +} + +void +ldns_resolver_set_rtt(ldns_resolver *r, size_t *rtt) +{ + r->_rtt = rtt; +} + +void +ldns_resolver_set_nameserver_rtt(ldns_resolver *r, size_t pos, size_t value) +{ + size_t *rtt; + + assert(r != NULL); + + rtt = ldns_resolver_rtt(r); + + if (pos >= ldns_resolver_nameserver_count(r)) { + /* error ?*/ + } else { + rtt[pos] = value; + } + +} + +void +ldns_resolver_incr_nameserver_count(ldns_resolver *r) +{ + size_t c; + + c = ldns_resolver_nameserver_count(r); + ldns_resolver_set_nameserver_count(r, ++c); +} + +void +ldns_resolver_dec_nameserver_count(ldns_resolver *r) +{ + size_t c; + + c = ldns_resolver_nameserver_count(r); + if (c == 0) { + return; + } else { + ldns_resolver_set_nameserver_count(r, --c); + } +} + +void +ldns_resolver_set_domain(ldns_resolver *r, ldns_rdf *d) +{ + r->_domain = d; +} + +void +ldns_resolver_set_timeout(ldns_resolver *r, struct timeval timeout) +{ + r->_timeout.tv_sec = timeout.tv_sec; + r->_timeout.tv_usec = timeout.tv_usec; +} + +void +ldns_resolver_push_searchlist(ldns_resolver *r, ldns_rdf *d) +{ + ldns_rdf **searchlist; + size_t list_count; + + if (ldns_rdf_get_type(d) != LDNS_RDF_TYPE_DNAME) { + return; + } + + list_count = ldns_resolver_searchlist_count(r); + searchlist = ldns_resolver_searchlist(r); + + searchlist = LDNS_XREALLOC(searchlist, ldns_rdf *, (list_count + 1)); + if (searchlist) { + r->_searchlist = searchlist; + + searchlist[list_count] = ldns_rdf_clone(d); + ldns_resolver_set_searchlist_count(r, list_count + 1); + } /* no way to report mem err */ +} + +void +ldns_resolver_set_tsig_keyname(ldns_resolver *r, char *tsig_keyname) +{ + LDNS_FREE(r->_tsig_keyname); + r->_tsig_keyname = strdup(tsig_keyname); +} + +void +ldns_resolver_set_tsig_algorithm(ldns_resolver *r, char *tsig_algorithm) +{ + LDNS_FREE(r->_tsig_algorithm); + r->_tsig_algorithm = strdup(tsig_algorithm); +} + +void +ldns_resolver_set_tsig_keydata(ldns_resolver *r, char *tsig_keydata) +{ + LDNS_FREE(r->_tsig_keydata); + r->_tsig_keydata = strdup(tsig_keydata); +} + +void +ldns_resolver_set_random(ldns_resolver *r, bool b) +{ + r->_random = b; +} + +/* more sophisticated functions */ +ldns_resolver * +ldns_resolver_new(void) +{ + ldns_resolver *r; + + r = LDNS_MALLOC(ldns_resolver); + if (!r) { + return NULL; + } + + r->_searchlist = NULL; + r->_nameservers = NULL; + r->_rtt = NULL; + + /* defaults are filled out */ + ldns_resolver_set_searchlist_count(r, 0); + ldns_resolver_set_nameserver_count(r, 0); + ldns_resolver_set_usevc(r, 0); + ldns_resolver_set_port(r, LDNS_PORT); + ldns_resolver_set_domain(r, NULL); + ldns_resolver_set_defnames(r, false); + ldns_resolver_set_retry(r, 3); + ldns_resolver_set_retrans(r, 2); + ldns_resolver_set_fallback(r, true); + ldns_resolver_set_fail(r, false); + ldns_resolver_set_edns_udp_size(r, 0); + ldns_resolver_set_dnssec(r, false); + ldns_resolver_set_dnssec_cd(r, false); + ldns_resolver_set_dnssec_anchors(r, NULL); + ldns_resolver_set_ip6(r, LDNS_RESOLV_INETANY); + ldns_resolver_set_igntc(r, false); + ldns_resolver_set_recursive(r, false); + ldns_resolver_set_dnsrch(r, true); + + /* randomize the nameserver to be queried + * when there are multiple + */ + ldns_resolver_set_random(r, true); + + ldns_resolver_set_debug(r, 0); + + r->_timeout.tv_sec = LDNS_DEFAULT_TIMEOUT_SEC; + r->_timeout.tv_usec = LDNS_DEFAULT_TIMEOUT_USEC; + + /* TODO: fd=0 is actually a valid socket (stdin), + replace with -1 */ + r->_socket = 0; + r->_axfr_soa_count = 0; + r->_axfr_i = 0; + r->_cur_axfr_pkt = NULL; + + r->_tsig_keyname = NULL; + r->_tsig_keydata = NULL; + r->_tsig_algorithm = NULL; + return r; +} + +ldns_status +ldns_resolver_new_frm_fp(ldns_resolver **res, FILE *fp) +{ + return ldns_resolver_new_frm_fp_l(res, fp, NULL); +} + +ldns_status +ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr) +{ + ldns_resolver *r; + const char *keyword[LDNS_RESOLV_KEYWORDS]; + char word[LDNS_MAX_LINELEN + 1]; + int8_t expect; + uint8_t i; + ldns_rdf *tmp; +#ifdef HAVE_SSL + ldns_rr *tmp_rr; +#endif + ssize_t gtr, bgtr; + ldns_buffer *b; + int lnr = 0, oldline; + if(!line_nr) line_nr = &lnr; + + /* do this better + * expect = + * 0: keyword + * 1: default domain dname + * 2: NS aaaa or a record + */ + + /* recognized keywords */ + keyword[LDNS_RESOLV_NAMESERVER] = "nameserver"; + keyword[LDNS_RESOLV_DEFDOMAIN] = "domain"; + keyword[LDNS_RESOLV_SEARCH] = "search"; + /* these two are read but not used atm TODO */ + keyword[LDNS_RESOLV_SORTLIST] = "sortlist"; + keyword[LDNS_RESOLV_OPTIONS] = "options"; + keyword[LDNS_RESOLV_ANCHOR] = "anchor"; + expect = LDNS_RESOLV_KEYWORD; + + r = ldns_resolver_new(); + if (!r) { + return LDNS_STATUS_MEM_ERR; + } + + gtr = 1; + word[0] = 0; + oldline = *line_nr; + expect = LDNS_RESOLV_KEYWORD; + while (gtr > 0) { + /* check comments */ + if (word[0] == '#') { + word[0]='x'; + if(oldline == *line_nr) { + /* skip until end of line */ + int c; + do { + c = fgetc(fp); + } while(c != EOF && c != '\n'); + if(c=='\n' && line_nr) (*line_nr)++; + } + /* and read next to prepare for further parsing */ + oldline = *line_nr; + continue; + } + oldline = *line_nr; + switch(expect) { + case LDNS_RESOLV_KEYWORD: + /* keyword */ + gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr); + if (gtr != 0) { + if(word[0] == '#') continue; + for(i = 0; i < LDNS_RESOLV_KEYWORDS; i++) { + if (strcasecmp(keyword[i], word) == 0) { + /* chosen the keyword and + * expect values carefully + */ + expect = i; + break; + } + } + /* no keyword recognized */ + if (expect == LDNS_RESOLV_KEYWORD) { + /* skip line */ + /* + ldns_resolver_deep_free(r); + return LDNS_STATUS_SYNTAX_KEYWORD_ERR; + */ + } + } + break; + case LDNS_RESOLV_DEFDOMAIN: + /* default domain dname */ + gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr); + if (gtr == 0) { + return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR; + } + if(word[0] == '#') { + expect = LDNS_RESOLV_KEYWORD; + continue; + } + tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word); + if (!tmp) { + ldns_resolver_deep_free(r); + return LDNS_STATUS_SYNTAX_DNAME_ERR; + } + + /* DOn't free, because we copy the pointer */ + ldns_resolver_set_domain(r, tmp); + expect = LDNS_RESOLV_KEYWORD; + break; + case LDNS_RESOLV_NAMESERVER: + /* NS aaaa or a record */ + gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr); + if (gtr == 0) { + return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR; + } + if(word[0] == '#') { + expect = LDNS_RESOLV_KEYWORD; + continue; + } + if(strchr(word, '%')) { + /* snip off interface labels, + * fe80::222:19ff:fe31:4222%eth0 */ + strchr(word, '%')[0]=0; + } + tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, word); + if (!tmp) { + /* try ip4 */ + tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, word); + } + /* could not parse it, exit */ + if (!tmp) { + ldns_resolver_deep_free(r); + return LDNS_STATUS_SYNTAX_ERR; + } + (void)ldns_resolver_push_nameserver(r, tmp); + ldns_rdf_deep_free(tmp); + expect = LDNS_RESOLV_KEYWORD; + break; + case LDNS_RESOLV_SEARCH: + /* search list domain dname */ + gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr); + b = LDNS_MALLOC(ldns_buffer); + if(!b) { + ldns_resolver_deep_free(r); + return LDNS_STATUS_MEM_ERR; + } + + ldns_buffer_new_frm_data(b, word, (size_t) gtr); + if(ldns_buffer_status(b) != LDNS_STATUS_OK) { + LDNS_FREE(b); + ldns_resolver_deep_free(r); + return LDNS_STATUS_MEM_ERR; + } + bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL, (size_t) gtr + 1); + while (bgtr > 0) { + gtr -= bgtr; + if(word[0] == '#') { + expect = LDNS_RESOLV_KEYWORD; + ldns_buffer_free(b); + continue; + } + tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word); + if (!tmp) { + ldns_resolver_deep_free(r); + ldns_buffer_free(b); + return LDNS_STATUS_SYNTAX_DNAME_ERR; + } + + ldns_resolver_push_searchlist(r, tmp); + + ldns_rdf_deep_free(tmp); + bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL, + (size_t) gtr + 1); + } + ldns_buffer_free(b); + gtr = 1; + expect = LDNS_RESOLV_KEYWORD; + break; + case LDNS_RESOLV_SORTLIST: + gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr); + /* sortlist not implemented atm */ + expect = LDNS_RESOLV_KEYWORD; + break; + case LDNS_RESOLV_OPTIONS: + gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr); + /* options not implemented atm */ + expect = LDNS_RESOLV_KEYWORD; + break; + case LDNS_RESOLV_ANCHOR: + /* a file containing a DNSSEC trust anchor */ + gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr); + if (gtr == 0) { + ldns_resolver_deep_free(r); + return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR; + } + if(word[0] == '#') { + expect = LDNS_RESOLV_KEYWORD; + continue; + } + +#ifdef HAVE_SSL + tmp_rr = ldns_read_anchor_file(word); + (void) ldns_resolver_push_dnssec_anchor(r, tmp_rr); + ldns_rr_free(tmp_rr); +#endif + expect = LDNS_RESOLV_KEYWORD; + break; + } + } + + if (res) { + *res = r; + return LDNS_STATUS_OK; + } else { + ldns_resolver_deep_free(r); + return LDNS_STATUS_NULL; + } +} + +ldns_status +ldns_resolver_new_frm_file(ldns_resolver **res, const char *filename) +{ + ldns_resolver *r; + FILE *fp; + ldns_status s; + + if (!filename) { + fp = fopen(LDNS_RESOLV_CONF, "r"); + + } else { + fp = fopen(filename, "r"); + } + if (!fp) { + return LDNS_STATUS_FILE_ERR; + } + + s = ldns_resolver_new_frm_fp(&r, fp); + fclose(fp); + if (s == LDNS_STATUS_OK) { + if (res) { + *res = r; + return LDNS_STATUS_OK; + } else { + return LDNS_STATUS_NULL; + } + } + return s; +} + +void +ldns_resolver_free(ldns_resolver *res) +{ + LDNS_FREE(res); +} + +void +ldns_resolver_deep_free(ldns_resolver *res) +{ + size_t i; + + if (res) { + if (res->_searchlist) { + for (i = 0; i < ldns_resolver_searchlist_count(res); i++) { + ldns_rdf_deep_free(res->_searchlist[i]); + } + LDNS_FREE(res->_searchlist); + } + if (res->_nameservers) { + for (i = 0; i < res->_nameserver_count; i++) { + ldns_rdf_deep_free(res->_nameservers[i]); + } + LDNS_FREE(res->_nameservers); + } + if (ldns_resolver_domain(res)) { + ldns_rdf_deep_free(ldns_resolver_domain(res)); + } + if (res->_tsig_keyname) { + LDNS_FREE(res->_tsig_keyname); + } + if (res->_tsig_keydata) { + LDNS_FREE(res->_tsig_keydata); + } + if (res->_tsig_algorithm) { + LDNS_FREE(res->_tsig_algorithm); + } + + if (res->_cur_axfr_pkt) { + ldns_pkt_free(res->_cur_axfr_pkt); + } + + if (res->_rtt) { + LDNS_FREE(res->_rtt); + } + if (res->_dnssec_anchors) { + ldns_rr_list_deep_free(res->_dnssec_anchors); + } + LDNS_FREE(res); + } +} + +ldns_pkt * +ldns_resolver_search(const ldns_resolver *r,const ldns_rdf *name, + ldns_rr_type t, ldns_rr_class c, uint16_t flags) +{ + + char *str_dname; + ldns_rdf *new_name; + ldns_rdf **search_list; + size_t i; + ldns_pkt *p; + + str_dname = ldns_rdf2str(name); + + if (ldns_dname_str_absolute(str_dname)) { + /* query as-is */ + return ldns_resolver_query(r, name, t, c, flags); + } else if (ldns_resolver_dnsrch(r)) { + search_list = ldns_resolver_searchlist(r); + for (i = 0; i < ldns_resolver_searchlist_count(r); i++) { + new_name = ldns_dname_cat_clone(name, search_list[i]); + + p = ldns_resolver_query(r, new_name, t, c, flags); + ldns_rdf_free(new_name); + if (p) { + if (ldns_pkt_get_rcode(p) == LDNS_RCODE_NOERROR) { + return p; + } else { + ldns_pkt_free(p); + p = NULL; + } + } + } + } + return NULL; +} + +ldns_pkt * +ldns_resolver_query(const ldns_resolver *r, const ldns_rdf *name, + ldns_rr_type t, ldns_rr_class c, uint16_t flags) +{ + ldns_rdf *newname; + ldns_pkt *pkt; + ldns_status status; + + pkt = NULL; + + if (!ldns_resolver_defnames(r)) { + status = ldns_resolver_send(&pkt, (ldns_resolver *)r, name, + t, c, flags); + if (status == LDNS_STATUS_OK) { + return pkt; + } else { + if (pkt) { + ldns_pkt_free(pkt); + } + return NULL; + } + } + + if (!ldns_resolver_domain(r)) { + /* _defnames is set, but the domain is not....?? */ + status = ldns_resolver_send(&pkt, (ldns_resolver *)r, name, + t, c, flags); + if (status == LDNS_STATUS_OK) { + return pkt; + } else { + if (pkt) { + ldns_pkt_free(pkt); + } + return NULL; + } + } + + newname = ldns_dname_cat_clone((const ldns_rdf*)name, ldns_resolver_domain(r)); + if (!newname) { + if (pkt) { + ldns_pkt_free(pkt); + } + return NULL; + } + + (void)ldns_resolver_send(&pkt, (ldns_resolver *)r, newname, t, c, + flags); + + ldns_rdf_free(newname); + + return pkt; +} + +static size_t * +ldns_resolver_backup_rtt(ldns_resolver *r) +{ + size_t *new_rtt; + size_t *old_rtt = ldns_resolver_rtt(r); + + if (old_rtt && ldns_resolver_nameserver_count(r)) { + new_rtt = LDNS_XMALLOC(size_t + , ldns_resolver_nameserver_count(r)); + memcpy(new_rtt, old_rtt, sizeof(size_t) + * ldns_resolver_nameserver_count(r)); + ldns_resolver_set_rtt(r, new_rtt); + return old_rtt; + } + return NULL; +} + +static void +ldns_resolver_restore_rtt(ldns_resolver *r, size_t *old_rtt) +{ + size_t *cur_rtt = ldns_resolver_rtt(r); + + if (cur_rtt) { + LDNS_FREE(cur_rtt); + } + ldns_resolver_set_rtt(r, old_rtt); +} + +ldns_status +ldns_resolver_send_pkt(ldns_pkt **answer, ldns_resolver *r, + ldns_pkt *query_pkt) +{ + ldns_pkt *answer_pkt = NULL; + ldns_status stat = LDNS_STATUS_OK; + size_t *rtt; + + stat = ldns_send(&answer_pkt, (ldns_resolver *)r, query_pkt); + if (stat != LDNS_STATUS_OK) { + if(answer_pkt) { + ldns_pkt_free(answer_pkt); + answer_pkt = NULL; + } + } else { + /* if tc=1 fall back to EDNS and/or TCP */ + /* check for tcp first (otherwise we don't care about tc=1) */ + if (!ldns_resolver_usevc(r) && ldns_resolver_fallback(r)) { + if (ldns_pkt_tc(answer_pkt)) { + /* was EDNS0 set? */ + if (ldns_pkt_edns_udp_size(query_pkt) == 0) { + ldns_pkt_set_edns_udp_size(query_pkt + , 4096); + ldns_pkt_free(answer_pkt); + /* Nameservers should not become + * unreachable because fragments are + * dropped (network error). We might + * still have success with TCP. + * Therefore maintain reachability + * statuses of the nameservers by + * backup and restore the rtt list. + */ + rtt = ldns_resolver_backup_rtt(r); + stat = ldns_send(&answer_pkt, r + , query_pkt); + ldns_resolver_restore_rtt(r, rtt); + } + /* either way, if it is still truncated, use TCP */ + if (stat != LDNS_STATUS_OK || + ldns_pkt_tc(answer_pkt)) { + ldns_resolver_set_usevc(r, true); + ldns_pkt_free(answer_pkt); + stat = ldns_send(&answer_pkt, r, query_pkt); + ldns_resolver_set_usevc(r, false); + } + } + } + } + + if (answer) { + *answer = answer_pkt; + } + + return stat; +} + +ldns_status +ldns_resolver_prepare_query_pkt(ldns_pkt **query_pkt, ldns_resolver *r, + const ldns_rdf *name, ldns_rr_type t, + ldns_rr_class c, uint16_t flags) +{ + struct timeval now; + + /* prepare a question pkt from the parameters + * and then send this */ + *query_pkt = ldns_pkt_query_new(ldns_rdf_clone(name), t, c, flags); + if (!*query_pkt) { + return LDNS_STATUS_ERR; + } + + /* set DO bit if necessary */ + if (ldns_resolver_dnssec(r)) { + if (ldns_resolver_edns_udp_size(r) == 0) { + ldns_resolver_set_edns_udp_size(r, 4096); + } + ldns_pkt_set_edns_do(*query_pkt, true); + if (ldns_resolver_dnssec_cd(r) || (flags & LDNS_CD)) { + ldns_pkt_set_cd(*query_pkt, true); + } + } + + /* transfer the udp_edns_size from the resolver to the packet */ + if (ldns_resolver_edns_udp_size(r) != 0) { + ldns_pkt_set_edns_udp_size(*query_pkt, ldns_resolver_edns_udp_size(r)); + } + + /* set the timestamp */ + now.tv_sec = time(NULL); + now.tv_usec = 0; + ldns_pkt_set_timestamp(*query_pkt, now); + + + if (ldns_resolver_debug(r)) { + ldns_pkt_print(stdout, *query_pkt); + } + + /* only set the id if it is not set yet */ + if (ldns_pkt_id(*query_pkt) == 0) { + ldns_pkt_set_random_id(*query_pkt); + } + + return LDNS_STATUS_OK; +} + + +ldns_status +ldns_resolver_send(ldns_pkt **answer, ldns_resolver *r, const ldns_rdf *name, + ldns_rr_type t, ldns_rr_class c, uint16_t flags) +{ + ldns_pkt *query_pkt; + ldns_pkt *answer_pkt; + ldns_status status; + + assert(r != NULL); + assert(name != NULL); + + answer_pkt = NULL; + + /* do all the preprocessing here, then fire of an query to + * the network */ + + if (0 == t) { + t= LDNS_RR_TYPE_A; + } + if (0 == c) { + c= LDNS_RR_CLASS_IN; + } + if (0 == ldns_resolver_nameserver_count(r)) { + return LDNS_STATUS_RES_NO_NS; + } + if (ldns_rdf_get_type(name) != LDNS_RDF_TYPE_DNAME) { + return LDNS_STATUS_RES_QUERY; + } + + status = ldns_resolver_prepare_query_pkt(&query_pkt, r, name, + t, c, flags); + if (status != LDNS_STATUS_OK) { + return status; + } + + /* if tsig values are set, tsign it */ + /* TODO: make last 3 arguments optional too? maybe make complete + rr instead of seperate values in resolver (and packet) + Jelte + should this go in pkt_prepare? + */ + if (ldns_resolver_tsig_keyname(r) && ldns_resolver_tsig_keydata(r)) { +#ifdef HAVE_SSL + status = ldns_pkt_tsig_sign(query_pkt, + ldns_resolver_tsig_keyname(r), + ldns_resolver_tsig_keydata(r), + 300, ldns_resolver_tsig_algorithm(r), NULL); + if (status != LDNS_STATUS_OK) { + return LDNS_STATUS_CRYPTO_TSIG_ERR; + } +#else + return LDNS_STATUS_CRYPTO_TSIG_ERR; +#endif /* HAVE_SSL */ + } + + status = ldns_resolver_send_pkt(&answer_pkt, r, query_pkt); + ldns_pkt_free(query_pkt); + + /* allows answer to be NULL when not interested in return value */ + if (answer) { + *answer = answer_pkt; + } + return status; +} + +ldns_rr * +ldns_axfr_next(ldns_resolver *resolver) +{ + ldns_rr *cur_rr; + uint8_t *packet_wire; + size_t packet_wire_size; + ldns_lookup_table *rcode; + ldns_status status; + + /* check if start() has been called */ + if (!resolver || resolver->_socket == 0) { + return NULL; + } + + if (resolver->_cur_axfr_pkt) { + if (resolver->_axfr_i == ldns_pkt_ancount(resolver->_cur_axfr_pkt)) { + ldns_pkt_free(resolver->_cur_axfr_pkt); + resolver->_cur_axfr_pkt = NULL; + return ldns_axfr_next(resolver); + } + cur_rr = ldns_rr_clone(ldns_rr_list_rr( + ldns_pkt_answer(resolver->_cur_axfr_pkt), + resolver->_axfr_i)); + resolver->_axfr_i++; + if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SOA) { + resolver->_axfr_soa_count++; + if (resolver->_axfr_soa_count >= 2) { +#ifndef USE_WINSOCK + close(resolver->_socket); +#else + closesocket(resolver->_socket); +#endif + resolver->_socket = 0; + ldns_pkt_free(resolver->_cur_axfr_pkt); + resolver->_cur_axfr_pkt = NULL; + } + } + return cur_rr; + } else { + packet_wire = ldns_tcp_read_wire(resolver->_socket, &packet_wire_size); + if(!packet_wire) + return NULL; + + status = ldns_wire2pkt(&resolver->_cur_axfr_pkt, packet_wire, + packet_wire_size); + LDNS_FREE(packet_wire); + + resolver->_axfr_i = 0; + if (status != LDNS_STATUS_OK) { + /* TODO: make status return type of this function (...api change) */ + fprintf(stderr, "Error parsing rr during AXFR: %s\n", ldns_get_errorstr_by_id(status)); + + /* RoRi: we must now also close the socket, otherwise subsequent uses of the + same resolver structure will fail because the link is still open or + in an undefined state */ +#ifndef USE_WINSOCK + close(resolver->_socket); +#else + closesocket(resolver->_socket); +#endif + resolver->_socket = 0; + + return NULL; + } else if (ldns_pkt_get_rcode(resolver->_cur_axfr_pkt) != 0) { + rcode = ldns_lookup_by_id(ldns_rcodes, (int) ldns_pkt_get_rcode(resolver->_cur_axfr_pkt)); + fprintf(stderr, "Error in AXFR: %s\n", rcode->name); + + /* RoRi: we must now also close the socket, otherwise subsequent uses of the + same resolver structure will fail because the link is still open or + in an undefined state */ +#ifndef USE_WINSOCK + close(resolver->_socket); +#else + closesocket(resolver->_socket); +#endif + resolver->_socket = 0; + + return NULL; + } else { + return ldns_axfr_next(resolver); + } + + } + +} + +bool +ldns_axfr_complete(const ldns_resolver *res) +{ + /* complete when soa count is 2? */ + return res->_axfr_soa_count == 2; +} + +ldns_pkt * +ldns_axfr_last_pkt(const ldns_resolver *res) +{ + return res->_cur_axfr_pkt; +} + +/* random isn't really that good */ +void +ldns_resolver_nameservers_randomize(ldns_resolver *r) +{ + uint16_t i, j; + ldns_rdf **ns, *tmp; + + /* should I check for ldns_resolver_random?? */ + assert(r != NULL); + + ns = ldns_resolver_nameservers(r); + for (i = 0; i < ldns_resolver_nameserver_count(r); i++) { + j = ldns_get_random() % ldns_resolver_nameserver_count(r); + tmp = ns[i]; + ns[i] = ns[j]; + ns[j] = tmp; + } + ldns_resolver_set_nameservers(r, ns); +} + diff --git a/rr.c b/rr.c new file mode 100644 index 00000000000..8f4ce85c7eb --- /dev/null +++ b/rr.c @@ -0,0 +1,2426 @@ +/* rr.c + * + * access functions for ldns_rr - + * a Net::DNS like library for C + * LibDNS Team @ NLnet Labs + * + * (c) NLnet Labs, 2004-2006 + * See the file LICENSE for the license + */ +#include + +#include + +#include +#include + +#include + +#define LDNS_SYNTAX_DATALEN 16 +#define LDNS_TTL_DATALEN 21 +#define LDNS_RRLIST_INIT 8 + +ldns_rr * +ldns_rr_new(void) +{ + ldns_rr *rr; + rr = LDNS_MALLOC(ldns_rr); + if (!rr) { + return NULL; + } + + ldns_rr_set_owner(rr, NULL); + ldns_rr_set_question(rr, false); + ldns_rr_set_rd_count(rr, 0); + rr->_rdata_fields = NULL; + ldns_rr_set_class(rr, LDNS_RR_CLASS_IN); + ldns_rr_set_ttl(rr, LDNS_DEFAULT_TTL); + return rr; +} + +ldns_rr * +ldns_rr_new_frm_type(ldns_rr_type t) +{ + ldns_rr *rr; + const ldns_rr_descriptor *desc; + size_t i; + + rr = LDNS_MALLOC(ldns_rr); + if (!rr) { + return NULL; + } + + desc = ldns_rr_descript(t); + + rr->_rdata_fields = LDNS_XMALLOC(ldns_rdf *, ldns_rr_descriptor_minimum(desc)); + if(!rr->_rdata_fields) { + LDNS_FREE(rr); + return NULL; + } + for (i = 0; i < ldns_rr_descriptor_minimum(desc); i++) { + rr->_rdata_fields[i] = NULL; + } + + ldns_rr_set_owner(rr, NULL); + ldns_rr_set_question(rr, false); + /* set the count to minimum */ + ldns_rr_set_rd_count(rr, ldns_rr_descriptor_minimum(desc)); + ldns_rr_set_class(rr, LDNS_RR_CLASS_IN); + ldns_rr_set_ttl(rr, LDNS_DEFAULT_TTL); + ldns_rr_set_type(rr, t); + return rr; +} + +void +ldns_rr_free(ldns_rr *rr) +{ + size_t i; + if (rr) { + if (ldns_rr_owner(rr)) { + ldns_rdf_deep_free(ldns_rr_owner(rr)); + } + for (i = 0; i < ldns_rr_rd_count(rr); i++) { + ldns_rdf_deep_free(ldns_rr_rdf(rr, i)); + } + LDNS_FREE(rr->_rdata_fields); + LDNS_FREE(rr); + } +} + +/* + * trailing spaces are allowed + * leading spaces are not allowed + * allow ttl to be optional + * class is optional too + * if ttl is missing, and default_ttl is 0, use DEF_TTL + * allow ttl to be written as 1d3h + * So the RR should look like. e.g. + * miek.nl. 3600 IN MX 10 elektron.atoom.net + * or + * miek.nl. 1h IN MX 10 elektron.atoom.net + * or + * miek.nl. IN MX 10 elektron.atoom.net + */ +static ldns_status +ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, + uint32_t default_ttl, ldns_rdf *origin, + ldns_rdf **prev, bool question) +{ + ldns_rr *new; + const ldns_rr_descriptor *desc; + ldns_rr_type rr_type; + ldns_buffer *rr_buf = NULL; + ldns_buffer *rd_buf = NULL; + uint32_t ttl_val; + char *owner = NULL; + char *ttl = NULL; + ldns_rr_class clas_val; + char *clas = NULL; + char *type = NULL; + char *rdata = NULL; + char *rd = NULL; + char *b64 = NULL; + size_t rd_strlen; + const char *delimiters; + ssize_t c; + ldns_rdf *owner_dname; + const char* endptr; + int was_unknown_rr_format = 0; + ldns_status status = LDNS_STATUS_OK; + + /* used for types with unknown number of rdatas */ + bool done; + bool quoted; + + ldns_rdf *r = NULL; + uint16_t r_cnt; + uint16_t r_min; + uint16_t r_max; + size_t pre_data_pos; + + new = ldns_rr_new(); + + owner = LDNS_XMALLOC(char, LDNS_MAX_DOMAINLEN + 1); + ttl = LDNS_XMALLOC(char, LDNS_TTL_DATALEN); + clas = LDNS_XMALLOC(char, LDNS_SYNTAX_DATALEN); + rdata = LDNS_XMALLOC(char, LDNS_MAX_PACKETLEN + 1); + rr_buf = LDNS_MALLOC(ldns_buffer); + rd_buf = LDNS_MALLOC(ldns_buffer); + rd = LDNS_XMALLOC(char, LDNS_MAX_RDFLEN); + b64 = LDNS_XMALLOC(char, LDNS_MAX_RDFLEN); + if (!new || !owner || !ttl || !clas || !rdata || !rr_buf || !rd_buf || !rd || !b64 ) { + status = LDNS_STATUS_MEM_ERR; + LDNS_FREE(rr_buf); + goto ldnserror; + } + + ldns_buffer_new_frm_data(rr_buf, (char*)str, strlen(str)); + + /* split the rr in its parts -1 signals trouble */ + if (ldns_bget_token(rr_buf, owner, "\t\n ", LDNS_MAX_DOMAINLEN) == -1) { + status = LDNS_STATUS_SYNTAX_ERR; + ldns_buffer_free(rr_buf); + goto ldnserror; + } + + if (ldns_bget_token(rr_buf, ttl, "\t\n ", LDNS_TTL_DATALEN) == -1) { + status = LDNS_STATUS_SYNTAX_TTL_ERR; + ldns_buffer_free(rr_buf); + goto ldnserror; + } + ttl_val = (uint32_t) ldns_str2period(ttl, &endptr); + + if (strlen(ttl) > 0 && !isdigit((int) ttl[0])) { + /* ah, it's not there or something */ + if (default_ttl == 0) { + ttl_val = LDNS_DEFAULT_TTL; + } else { + ttl_val = default_ttl; + } + /* we not ASSUMING the TTL is missing and that + * the rest of the RR is still there. That is + * CLASS TYPE RDATA + * so ttl value we read is actually the class + */ + clas_val = ldns_get_rr_class_by_name(ttl); + /* class can be left out too, assume IN, current + * token must be type + */ + if (clas_val == 0) { + clas_val = LDNS_RR_CLASS_IN; + type = LDNS_XMALLOC(char, strlen(ttl) + 1); + if(!type) { + status = LDNS_STATUS_MEM_ERR; + ldns_buffer_free(rr_buf); + goto ldnserror; + } + strncpy(type, ttl, strlen(ttl) + 1); + } + } else { + if (ldns_bget_token(rr_buf, clas, "\t\n ", LDNS_SYNTAX_DATALEN) == -1) { + status = LDNS_STATUS_SYNTAX_CLASS_ERR; + ldns_buffer_free(rr_buf); + goto ldnserror; + } + clas_val = ldns_get_rr_class_by_name(clas); + /* class can be left out too, assume IN, current + * token must be type + */ + if (clas_val == 0) { + clas_val = LDNS_RR_CLASS_IN; + type = LDNS_XMALLOC(char, strlen(clas) + 1); + if(!type) { + status = LDNS_STATUS_MEM_ERR; + ldns_buffer_free(rr_buf); + goto ldnserror; + } + strncpy(type, clas, strlen(clas) + 1); + } + } + /* the rest should still be waiting for us */ + + if (!type) { + type = LDNS_XMALLOC(char, LDNS_SYNTAX_DATALEN); + if(!type) { + status = LDNS_STATUS_MEM_ERR; + ldns_buffer_free(rr_buf); + goto ldnserror; + } + if (ldns_bget_token(rr_buf, type, "\t\n ", LDNS_SYNTAX_DATALEN) == -1) { + status = LDNS_STATUS_SYNTAX_TYPE_ERR; + ldns_buffer_free(rr_buf); + goto ldnserror; + } + } + + if (ldns_bget_token(rr_buf, rdata, "\0", LDNS_MAX_PACKETLEN) == -1) { + /* apparently we are done, and it's only a question RR + * so do not set status and go to ldnserror here + */ + } + + ldns_buffer_new_frm_data(rd_buf, rdata, strlen(rdata)); + + if (strlen(owner) <= 1 && strncmp(owner, "@", 1) == 0) { + if (origin) { + ldns_rr_set_owner(new, ldns_rdf_clone(origin)); + } else if (prev && *prev) { + ldns_rr_set_owner(new, ldns_rdf_clone(*prev)); + } else { + /* default to root */ + ldns_rr_set_owner(new, ldns_dname_new_frm_str(".")); + } + + /* @ also overrides prev */ + if (prev) { + ldns_rdf_deep_free(*prev); + *prev = ldns_rdf_clone(ldns_rr_owner(new)); + if (!*prev) { + status = LDNS_STATUS_MEM_ERR; + ldns_buffer_free(rr_buf); + goto ldnserror; + } + } + } else { + if (strlen(owner) == 0) { + /* no ownername was given, try prev, if that fails + * origin, else default to root */ + if (prev && *prev) { + ldns_rr_set_owner(new, ldns_rdf_clone(*prev)); + } else if (origin) { + ldns_rr_set_owner(new, ldns_rdf_clone(origin)); + } else { + ldns_rr_set_owner(new, ldns_dname_new_frm_str(".")); + } + if(!ldns_rr_owner(new)) { + status = LDNS_STATUS_MEM_ERR; + ldns_buffer_free(rr_buf); + goto ldnserror; + } + } else { + owner_dname = ldns_dname_new_frm_str(owner); + if (!owner_dname) { + status = LDNS_STATUS_SYNTAX_ERR; + ldns_buffer_free(rr_buf); + goto ldnserror; + } + + ldns_rr_set_owner(new, owner_dname); + if (!ldns_dname_str_absolute(owner) && origin) { + if(ldns_dname_cat(ldns_rr_owner(new), + origin) != LDNS_STATUS_OK) { + status = LDNS_STATUS_SYNTAX_ERR; + ldns_buffer_free(rr_buf); + goto ldnserror; + } + } + if (prev) { + ldns_rdf_deep_free(*prev); + *prev = ldns_rdf_clone(ldns_rr_owner(new)); + if(!*prev) { + status = LDNS_STATUS_MEM_ERR; + ldns_buffer_free(rr_buf); + goto ldnserror; + } + } + } + } + LDNS_FREE(owner); + owner = NULL; + + ldns_rr_set_question(new, question); + + ldns_rr_set_ttl(new, ttl_val); + LDNS_FREE(ttl); + ttl = NULL; + + ldns_rr_set_class(new, clas_val); + LDNS_FREE(clas); + clas = NULL; + + rr_type = ldns_get_rr_type_by_name(type); + LDNS_FREE(type); + type = NULL; + + desc = ldns_rr_descript((uint16_t)rr_type); + ldns_rr_set_type(new, rr_type); + if (desc) { + /* only the rdata remains */ + r_max = ldns_rr_descriptor_maximum(desc); + r_min = ldns_rr_descriptor_minimum(desc); + } else { + r_min = 0; + r_max = 1; + } + + /* depending on the rr_type we need to extract + * the rdata differently, e.g. NSEC/NSEC3 */ + switch(rr_type) { + default: + done = false; + + for (r_cnt = 0; !done && r_cnt < r_max; r_cnt++) { + quoted = false; + /* if type = B64, the field may contain spaces */ + if (ldns_rr_descriptor_field_type(desc, + r_cnt) == LDNS_RDF_TYPE_B64 || + ldns_rr_descriptor_field_type(desc, + r_cnt) == LDNS_RDF_TYPE_HEX || + ldns_rr_descriptor_field_type(desc, + r_cnt) == LDNS_RDF_TYPE_LOC || + ldns_rr_descriptor_field_type(desc, + r_cnt) == LDNS_RDF_TYPE_WKS || + ldns_rr_descriptor_field_type(desc, + r_cnt) == LDNS_RDF_TYPE_IPSECKEY || + ldns_rr_descriptor_field_type(desc, + r_cnt) == LDNS_RDF_TYPE_NSEC) { + delimiters = "\n\t"; + } else { + delimiters = "\n\t "; + } + + if (ldns_rr_descriptor_field_type(desc, + r_cnt) == LDNS_RDF_TYPE_STR && + ldns_buffer_remaining(rd_buf) > 0) { + /* skip spaces */ + while (*(ldns_buffer_current(rd_buf)) == ' ') { + ldns_buffer_skip(rd_buf, 1); + } + + if (*(ldns_buffer_current(rd_buf)) == '\"') { + delimiters = "\"\0"; + ldns_buffer_skip(rd_buf, 1); + quoted = true; + } + } + + /* because number of fields can be variable, we can't + rely on _maximum() only */ + /* skip spaces */ + while (ldns_buffer_position(rd_buf) < ldns_buffer_limit(rd_buf) && + *(ldns_buffer_current(rd_buf)) == ' ' && !quoted + ) { + ldns_buffer_skip(rd_buf, 1); + } + + pre_data_pos = ldns_buffer_position(rd_buf); + if ((c = ldns_bget_token(rd_buf, rd, delimiters, + LDNS_MAX_RDFLEN)) != -1) { + /* hmmz, rfc3597 specifies that any type can be represented with + * \# method, which can contain spaces... + * it does specify size though... + */ + rd_strlen = strlen(rd); + + /* unknown RR data */ + if (strncmp(rd, "\\#", 2) == 0 && !quoted && (rd_strlen == 2 || rd[2]==' ')) { + uint16_t hex_data_size; + char *hex_data_str; + uint16_t cur_hex_data_size; + + was_unknown_rr_format = 1; + /* go back to before \# and skip it while setting delimiters better */ + ldns_buffer_set_position(rd_buf, pre_data_pos); + delimiters = "\n\t "; + (void)ldns_bget_token(rd_buf, rd, delimiters, LDNS_MAX_RDFLEN); + /* read rdata octet length */ + c = ldns_bget_token(rd_buf, rd, delimiters, LDNS_MAX_RDFLEN); + if (c == -1) { + /* something goes very wrong here */ + LDNS_FREE(rd); + LDNS_FREE(b64); + ldns_buffer_free(rd_buf); + ldns_buffer_free(rr_buf); + LDNS_FREE(rdata); + ldns_rr_free(new); + return LDNS_STATUS_SYNTAX_RDATA_ERR; + } + hex_data_size = (uint16_t) atoi(rd); + /* copy the hex chars into hex str (which is 2 chars per byte) */ + hex_data_str = LDNS_XMALLOC(char, 2 * hex_data_size + 1); + if (!hex_data_str) { + /* malloc error */ + LDNS_FREE(rd); + LDNS_FREE(b64); + ldns_buffer_free(rd_buf); + ldns_buffer_free(rr_buf); + LDNS_FREE(rdata); + ldns_rr_free(new); + return LDNS_STATUS_SYNTAX_RDATA_ERR; + } + cur_hex_data_size = 0; + while(cur_hex_data_size < 2 * hex_data_size) { + c = ldns_bget_token(rd_buf, rd, delimiters, LDNS_MAX_RDFLEN); + if (c != -1) { + rd_strlen = strlen(rd); + } + if (c == -1 || (size_t)cur_hex_data_size + rd_strlen > 2 * (size_t)hex_data_size) { + LDNS_FREE(hex_data_str); + LDNS_FREE(rd); + LDNS_FREE(b64); + ldns_buffer_free(rd_buf); + ldns_buffer_free(rr_buf); + LDNS_FREE(rdata); + ldns_rr_free(new); + return LDNS_STATUS_SYNTAX_RDATA_ERR; + } + strncpy(hex_data_str + cur_hex_data_size, rd, rd_strlen); + cur_hex_data_size += rd_strlen; + } + hex_data_str[cur_hex_data_size] = '\0'; + + /* correct the rdf type */ + /* if *we* know the type, interpret it as wireformat */ + if (desc) { + size_t hex_pos = 0; + uint8_t *hex_data = LDNS_XMALLOC(uint8_t, hex_data_size + 2); + ldns_status s; + if(!hex_data) { + LDNS_FREE(hex_data_str); + LDNS_FREE(rd); + LDNS_FREE(b64); + ldns_buffer_free(rd_buf); + ldns_buffer_free(rr_buf); + LDNS_FREE(rdata); + ldns_rr_free(new); + return LDNS_STATUS_MEM_ERR; + } + ldns_write_uint16(hex_data, hex_data_size); + ldns_hexstring_to_data(hex_data + 2, hex_data_str); + s = ldns_wire2rdf(new, hex_data, + hex_data_size+2, &hex_pos); + if(s != LDNS_STATUS_OK) { + LDNS_FREE(hex_data_str); + LDNS_FREE(rd); + LDNS_FREE(b64); + ldns_buffer_free(rd_buf); + ldns_buffer_free(rr_buf); + LDNS_FREE(rdata); + ldns_rr_free(new); + return s; + } + LDNS_FREE(hex_data); + } else { + r = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_HEX, hex_data_str); + if(!r) { + LDNS_FREE(hex_data_str); + LDNS_FREE(rd); + LDNS_FREE(b64); + ldns_buffer_free(rd_buf); + ldns_buffer_free(rr_buf); + LDNS_FREE(rdata); + ldns_rr_free(new); + return LDNS_STATUS_MEM_ERR; + } + ldns_rdf_set_type(r, LDNS_RDF_TYPE_UNKNOWN); + if(!ldns_rr_push_rdf(new, r)) { + LDNS_FREE(hex_data_str); + LDNS_FREE(rd); + LDNS_FREE(b64); + ldns_buffer_free(rd_buf); + ldns_buffer_free(rr_buf); + LDNS_FREE(rdata); + ldns_rr_free(new); + return LDNS_STATUS_MEM_ERR; + } + } + LDNS_FREE(hex_data_str); + } else { + /* Normal RR */ + switch(ldns_rr_descriptor_field_type(desc, r_cnt)) { + case LDNS_RDF_TYPE_HEX: + case LDNS_RDF_TYPE_B64: + /* can have spaces, and will always be the last + * record of the rrdata. Read in the rest */ + if ((c = ldns_bget_token(rd_buf, + b64, + "\n", + LDNS_MAX_RDFLEN)) + != -1) { + rd = strncat(rd, + b64, + LDNS_MAX_RDFLEN + - strlen(rd) - 1); + } + r = ldns_rdf_new_frm_str( + ldns_rr_descriptor_field_type(desc, r_cnt), + rd); + break; + case LDNS_RDF_TYPE_DNAME: + r = ldns_rdf_new_frm_str( + ldns_rr_descriptor_field_type(desc, r_cnt), + rd); + + /* check if the origin should be used or concatenated */ + if (r && ldns_rdf_size(r) > 1 && ldns_rdf_data(r)[0] == 1 + && ldns_rdf_data(r)[1] == '@') { + ldns_rdf_deep_free(r); + if (origin) { + r = ldns_rdf_clone(origin); + } else { + /* if this is the SOA, use its own owner name */ + if (rr_type == LDNS_RR_TYPE_SOA) { + r = ldns_rdf_clone(ldns_rr_owner(new)); + } else { + r = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, "."); + } + } + } else if (r && rd_strlen >= 1 && !ldns_dname_str_absolute(rd) && origin) { + if (ldns_dname_cat(r, origin) != LDNS_STATUS_OK) { + LDNS_FREE(rd); + LDNS_FREE(b64); + ldns_buffer_free(rd_buf); + ldns_buffer_free(rr_buf); + LDNS_FREE(rdata); + ldns_rr_free(new); + return LDNS_STATUS_ERR; + } + } + break; + default: + r = ldns_rdf_new_frm_str( + ldns_rr_descriptor_field_type(desc, r_cnt), + rd); + break; + } + if (r) { + ldns_rr_push_rdf(new, r); + } else { + LDNS_FREE(rd); + LDNS_FREE(b64); + ldns_buffer_free(rd_buf); + ldns_buffer_free(rr_buf); + LDNS_FREE(rdata); + ldns_rr_free(new); + return LDNS_STATUS_SYNTAX_RDATA_ERR; + } + } + if (quoted) { + if (ldns_buffer_available(rd_buf, 1)) { + ldns_buffer_skip(rd_buf, 1); + } else { + done = true; + } + } + } else { + done = true; + } + } + } + LDNS_FREE(rd); + LDNS_FREE(b64); + ldns_buffer_free(rd_buf); + ldns_buffer_free(rr_buf); + LDNS_FREE(rdata); + + if (!question && desc && !was_unknown_rr_format && ldns_rr_rd_count(new) < r_min) { + ldns_rr_free(new); + return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR; + } + + if (newrr) { + *newrr = new; + } + return LDNS_STATUS_OK; + +ldnserror: + LDNS_FREE(type); + LDNS_FREE(owner); + LDNS_FREE(ttl); + LDNS_FREE(clas); + LDNS_FREE(rdata); + LDNS_FREE(rd); + LDNS_FREE(rd_buf); + LDNS_FREE(b64); + ldns_rr_free(new); + return status; +} + +ldns_status +ldns_rr_new_frm_str(ldns_rr **newrr, const char *str, + uint32_t default_ttl, ldns_rdf *origin, + ldns_rdf **prev) +{ + return ldns_rr_new_frm_str_internal(newrr, + str, + default_ttl, + origin, + prev, + false); +} + +ldns_status +ldns_rr_new_question_frm_str(ldns_rr **newrr, const char *str, + ldns_rdf *origin, ldns_rdf **prev) +{ + return ldns_rr_new_frm_str_internal(newrr, + str, + 0, + origin, + prev, + true); +} + +ldns_status +ldns_rr_new_frm_fp(ldns_rr **newrr, FILE *fp, uint32_t *ttl, ldns_rdf **origin, ldns_rdf **prev) +{ + return ldns_rr_new_frm_fp_l(newrr, fp, ttl, origin, prev, NULL); +} + +ldns_status +ldns_rr_new_frm_fp_l(ldns_rr **newrr, FILE *fp, uint32_t *default_ttl, ldns_rdf **origin, ldns_rdf **prev, int *line_nr) +{ + char *line; + const char *endptr; /* unused */ + ldns_rr *rr; + uint32_t ttl; + ldns_rdf *tmp; + ldns_status s; + ssize_t size; + int offset = 0; + + if (default_ttl) { + ttl = *default_ttl; + } else { + ttl = 0; + } + + line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1); + if (!line) { + return LDNS_STATUS_MEM_ERR; + } + + /* read an entire line in from the file */ + if ((size = ldns_fget_token_l(fp, line, LDNS_PARSE_SKIP_SPACE, LDNS_MAX_LINELEN, line_nr)) == -1) { + LDNS_FREE(line); + /* if last line was empty, we are now at feof, which is not + * always a parse error (happens when for instance last line + * was a comment) + */ + return LDNS_STATUS_SYNTAX_ERR; + } + + /* we can have the situation, where we've read ok, but still got + * no bytes to play with, in this case size is 0 + */ + if (size == 0) { + LDNS_FREE(line); + return LDNS_STATUS_SYNTAX_EMPTY; + } + + if (strncmp(line, "$ORIGIN", 7) == 0 && isspace(line[7])) { + if (*origin) { + ldns_rdf_deep_free(*origin); + *origin = NULL; + } + offset = 8; + while (isspace(line[offset])) { + offset++; + } + tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, line + offset); + if (!tmp) { + /* could not parse what next to $ORIGIN */ + LDNS_FREE(line); + return LDNS_STATUS_SYNTAX_DNAME_ERR; + } + *origin = tmp; + s = LDNS_STATUS_SYNTAX_ORIGIN; + } else if (strncmp(line, "$TTL", 4) == 0 && isspace(line[4])) { + offset = 5; + while (isspace(line[offset])) { + offset++; + } + if (default_ttl) { + *default_ttl = ldns_str2period(line + offset, &endptr); + } + s = LDNS_STATUS_SYNTAX_TTL; + } else if (strncmp(line, "$INCLUDE", 8) == 0) { + s = LDNS_STATUS_SYNTAX_INCLUDE; + } else { + if (origin && *origin) { + s = ldns_rr_new_frm_str(&rr, (const char*) line, ttl, *origin, prev); + } else { + s = ldns_rr_new_frm_str(&rr, (const char*) line, ttl, NULL, prev); + } + } + LDNS_FREE(line); + if (newrr && s == LDNS_STATUS_OK) { + *newrr = rr; + } + return s; +} + +void +ldns_rr_set_owner(ldns_rr *rr, ldns_rdf *owner) +{ + rr->_owner = owner; +} + +void +ldns_rr_set_question(ldns_rr *rr, bool question) +{ + rr->_rr_question = question; +} + +void +ldns_rr_set_ttl(ldns_rr *rr, uint32_t ttl) +{ + rr->_ttl = ttl; +} + +void +ldns_rr_set_rd_count(ldns_rr *rr, size_t count) +{ + rr->_rd_count = count; +} + +void +ldns_rr_set_type(ldns_rr *rr, ldns_rr_type rr_type) +{ + rr->_rr_type = rr_type; +} + +void +ldns_rr_set_class(ldns_rr *rr, ldns_rr_class rr_class) +{ + rr->_rr_class = rr_class; +} + +ldns_rdf * +ldns_rr_set_rdf(ldns_rr *rr, const ldns_rdf *f, size_t position) +{ + size_t rd_count; + ldns_rdf *pop; + + rd_count = ldns_rr_rd_count(rr); + if (position < rd_count) { + /* dicard the old one */ + pop = rr->_rdata_fields[position]; + rr->_rdata_fields[position] = (ldns_rdf*)f; + return pop; + } else { + return NULL; + } +} + +bool +ldns_rr_push_rdf(ldns_rr *rr, const ldns_rdf *f) +{ + size_t rd_count; + ldns_rdf **rdata_fields; + + rd_count = ldns_rr_rd_count(rr); + + /* grow the array */ + rdata_fields = LDNS_XREALLOC( + rr->_rdata_fields, ldns_rdf *, rd_count + 1); + if (!rdata_fields) { + return false; + } + + /* add the new member */ + rr->_rdata_fields = rdata_fields; + rr->_rdata_fields[rd_count] = (ldns_rdf*)f; + + ldns_rr_set_rd_count(rr, rd_count + 1); + return true; +} + +ldns_rdf * +ldns_rr_pop_rdf(ldns_rr *rr) +{ + size_t rd_count; + ldns_rdf *pop; + ldns_rdf** newrd; + + rd_count = ldns_rr_rd_count(rr); + + if (rd_count == 0) { + return NULL; + } + + pop = rr->_rdata_fields[rd_count - 1]; + + /* try to shrink the array */ + if(rd_count > 1) { + newrd = LDNS_XREALLOC( + rr->_rdata_fields, ldns_rdf *, rd_count - 1); + if(newrd) + rr->_rdata_fields = newrd; + } else { + LDNS_FREE(rr->_rdata_fields); + } + + ldns_rr_set_rd_count(rr, rd_count - 1); + return pop; +} + +ldns_rdf * +ldns_rr_rdf(const ldns_rr *rr, size_t nr) +{ + if (rr && nr < ldns_rr_rd_count(rr)) { + return rr->_rdata_fields[nr]; + } else { + return NULL; + } +} + +ldns_rdf * +ldns_rr_owner(const ldns_rr *rr) +{ + return rr->_owner; +} + +bool +ldns_rr_is_question(const ldns_rr *rr) +{ + return rr->_rr_question; +} + +uint32_t +ldns_rr_ttl(const ldns_rr *rr) +{ + return rr->_ttl; +} + +size_t +ldns_rr_rd_count(const ldns_rr *rr) +{ + return rr->_rd_count; +} + +ldns_rr_type +ldns_rr_get_type(const ldns_rr *rr) +{ + return rr->_rr_type; +} + +ldns_rr_class +ldns_rr_get_class(const ldns_rr *rr) +{ + return rr->_rr_class; +} + +/* rr_lists */ + +size_t +ldns_rr_list_rr_count(const ldns_rr_list *rr_list) +{ + if (rr_list) { + return rr_list->_rr_count; + } else { + return 0; + } +} + +ldns_rr * +ldns_rr_list_set_rr(ldns_rr_list *rr_list, const ldns_rr *r, size_t count) +{ + ldns_rr *old; + + if (count > ldns_rr_list_rr_count(rr_list)) { + return NULL; + } + + old = ldns_rr_list_rr(rr_list, count); + + /* overwrite old's pointer */ + rr_list->_rrs[count] = (ldns_rr*)r; + return old; +} + +void +ldns_rr_list_set_rr_count(ldns_rr_list *rr_list, size_t count) +{ + assert(count <= rr_list->_rr_capacity); + rr_list->_rr_count = count; +} + +ldns_rr * +ldns_rr_list_rr(const ldns_rr_list *rr_list, size_t nr) +{ + if (nr < ldns_rr_list_rr_count(rr_list)) { + return rr_list->_rrs[nr]; + } else { + return NULL; + } +} + +ldns_rr_list * +ldns_rr_list_new() +{ + ldns_rr_list *rr_list = LDNS_MALLOC(ldns_rr_list); + if(!rr_list) return NULL; + rr_list->_rr_count = 0; + rr_list->_rr_capacity = 0; + rr_list->_rrs = NULL; + return rr_list; +} + +void +ldns_rr_list_free(ldns_rr_list *rr_list) +{ + if (rr_list) { + LDNS_FREE(rr_list->_rrs); + LDNS_FREE(rr_list); + } +} + +void +ldns_rr_list_deep_free(ldns_rr_list *rr_list) +{ + size_t i; + + if (rr_list) { + for (i=0; i < ldns_rr_list_rr_count(rr_list); i++) { + ldns_rr_free(ldns_rr_list_rr(rr_list, i)); + } + LDNS_FREE(rr_list->_rrs); + LDNS_FREE(rr_list); + } +} + + +/* add right to left. So we modify *left! */ +bool +ldns_rr_list_cat(ldns_rr_list *left, ldns_rr_list *right) +{ + size_t r_rr_count; + size_t i; + + if (!left) { + return false; + } + + if (right) { + r_rr_count = ldns_rr_list_rr_count(right); + } else { + r_rr_count = 0; + } + + /* push right to left */ + for(i = 0; i < r_rr_count; i++) { + ldns_rr_list_push_rr(left, ldns_rr_list_rr(right, i)); + } + return true; +} + +ldns_rr_list * +ldns_rr_list_cat_clone(ldns_rr_list *left, ldns_rr_list *right) +{ + size_t l_rr_count; + size_t r_rr_count; + size_t i; + ldns_rr_list *cat; + + if (left) { + l_rr_count = ldns_rr_list_rr_count(left); + } else { + return ldns_rr_list_clone(right); + } + + if (right) { + r_rr_count = ldns_rr_list_rr_count(right); + } else { + r_rr_count = 0; + } + + cat = ldns_rr_list_new(); + + if (!cat) { + return NULL; + } + + /* left */ + for(i = 0; i < l_rr_count; i++) { + ldns_rr_list_push_rr(cat, + ldns_rr_clone(ldns_rr_list_rr(left, i))); + } + /* right */ + for(i = 0; i < r_rr_count; i++) { + ldns_rr_list_push_rr(cat, + ldns_rr_clone(ldns_rr_list_rr(right, i))); + } + return cat; +} + +ldns_rr_list * +ldns_rr_list_subtype_by_rdf(ldns_rr_list *l, ldns_rdf *r, size_t pos) +{ + size_t i; + ldns_rr_list *subtyped; + ldns_rdf *list_rdf; + + subtyped = ldns_rr_list_new(); + + for(i = 0; i < ldns_rr_list_rr_count(l); i++) { + list_rdf = ldns_rr_rdf( + ldns_rr_list_rr(l, i), + pos); + if (!list_rdf) { + /* pos is too large or any other error */ + ldns_rr_list_deep_free(subtyped); + return NULL; + } + + if (ldns_rdf_compare(list_rdf, r) == 0) { + /* a match */ + ldns_rr_list_push_rr(subtyped, + ldns_rr_clone(ldns_rr_list_rr(l, i))); + } + } + + if (ldns_rr_list_rr_count(subtyped) > 0) { + return subtyped; + } else { + ldns_rr_list_free(subtyped); + return NULL; + } +} + +bool +ldns_rr_list_push_rr(ldns_rr_list *rr_list, const ldns_rr *rr) +{ + size_t rr_count; + size_t cap; + + rr_count = ldns_rr_list_rr_count(rr_list); + cap = rr_list->_rr_capacity; + + /* grow the array */ + if(rr_count+1 > cap) { + ldns_rr **rrs; + + if(cap == 0) + cap = LDNS_RRLIST_INIT; /* initial list size */ + else cap *= 2; + rrs = LDNS_XREALLOC(rr_list->_rrs, ldns_rr *, cap); + if (!rrs) { + return false; + } + rr_list->_rrs = rrs; + rr_list->_rr_capacity = cap; + } + + /* add the new member */ + rr_list->_rrs[rr_count] = (ldns_rr*)rr; + + ldns_rr_list_set_rr_count(rr_list, rr_count + 1); + return true; +} + +bool +ldns_rr_list_push_rr_list(ldns_rr_list *rr_list, const ldns_rr_list *push_list) +{ + size_t i; + + for(i = 0; i < ldns_rr_list_rr_count(push_list); i++) { + if (!ldns_rr_list_push_rr(rr_list, + ldns_rr_list_rr(push_list, i))) { + return false; + } + } + return true; +} + +ldns_rr * +ldns_rr_list_pop_rr(ldns_rr_list *rr_list) +{ + size_t rr_count; + size_t cap; + ldns_rr *pop; + + rr_count = ldns_rr_list_rr_count(rr_list); + + if (rr_count == 0) { + return NULL; + } + + cap = rr_list->_rr_capacity; + pop = ldns_rr_list_rr(rr_list, rr_count - 1); + + /* shrink the array */ + if(cap > LDNS_RRLIST_INIT && rr_count-1 <= cap/2) { + ldns_rr** a; + cap /= 2; + a = LDNS_XREALLOC(rr_list->_rrs, ldns_rr *, cap); + if(a) { + rr_list->_rrs = a; + rr_list->_rr_capacity = cap; + } + } + + ldns_rr_list_set_rr_count(rr_list, rr_count - 1); + + return pop; +} + +ldns_rr_list * +ldns_rr_list_pop_rr_list(ldns_rr_list *rr_list, size_t howmany) +{ + /* pop a number of rr's and put them in a rr_list */ + ldns_rr_list *popped; + ldns_rr *p; + size_t i = howmany; + + popped = ldns_rr_list_new(); + + if (!popped) { + return NULL; + } + + + while(i > 0 && + (p = ldns_rr_list_pop_rr(rr_list)) != NULL) { + ldns_rr_list_push_rr(popped, p); + i--; + } + + if (i == howmany) { + return NULL; + } else { + return popped; + } +} + + +bool +ldns_rr_list_contains_rr(const ldns_rr_list *rr_list, ldns_rr *rr) +{ + size_t i; + + if (!rr_list || !rr || ldns_rr_list_rr_count(rr_list) == 0) { + return false; + } + + for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) { + if (rr == ldns_rr_list_rr(rr_list, i)) { + return true; + } else if (ldns_rr_compare(rr, ldns_rr_list_rr(rr_list, i)) == 0) { + return true; + } + } + return false; +} + +bool +ldns_is_rrset(ldns_rr_list *rr_list) +{ + ldns_rr_type t; + ldns_rr_class c; + ldns_rdf *o; + ldns_rr *tmp; + size_t i; + + if (!rr_list || ldns_rr_list_rr_count(rr_list) == 0) { + return false; + } + + tmp = ldns_rr_list_rr(rr_list, 0); + + t = ldns_rr_get_type(tmp); + c = ldns_rr_get_class(tmp); + o = ldns_rr_owner(tmp); + + /* compare these with the rest of the rr_list, start with 1 */ + for (i = 1; i < ldns_rr_list_rr_count(rr_list); i++) { + tmp = ldns_rr_list_rr(rr_list, i); + if (t != ldns_rr_get_type(tmp)) { + return false; + } + if (c != ldns_rr_get_class(tmp)) { + return false; + } + if (ldns_rdf_compare(o, ldns_rr_owner(tmp)) != 0) { + return false; + } + } + return true; +} + +bool +ldns_rr_set_push_rr(ldns_rr_list *rr_list, ldns_rr *rr) +{ + size_t rr_count; + size_t i; + ldns_rr *last; + + assert(rr != NULL); + + rr_count = ldns_rr_list_rr_count(rr_list); + + if (rr_count == 0) { + /* nothing there, so checking it is + * not needed */ + return ldns_rr_list_push_rr(rr_list, rr); + } else { + /* check with the final rr in the rr_list */ + last = ldns_rr_list_rr(rr_list, rr_count - 1); + + if (ldns_rr_get_class(last) != ldns_rr_get_class(rr)) { + return false; + } + if (ldns_rr_get_type(last) != ldns_rr_get_type(rr)) { + return false; + } + /* only check if not equal to RRSIG */ + if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_RRSIG) { + if (ldns_rr_ttl(last) != ldns_rr_ttl(rr)) { + return false; + } + } + if (ldns_rdf_compare(ldns_rr_owner(last), + ldns_rr_owner(rr)) != 0) { + return false; + } + /* ok, still alive - check if the rr already + * exists - if so, dont' add it */ + for(i = 0; i < rr_count; i++) { + if(ldns_rr_compare( + ldns_rr_list_rr(rr_list, i), rr) == 0) { + return false; + } + } + /* it's safe, push it */ + return ldns_rr_list_push_rr(rr_list, rr); + } +} + +ldns_rr * +ldns_rr_set_pop_rr(ldns_rr_list *rr_list) +{ + return ldns_rr_list_pop_rr(rr_list); +} + +ldns_rr_list * +ldns_rr_list_pop_rrset(ldns_rr_list *rr_list) +{ + ldns_rr_list *rrset; + ldns_rr *last_rr = NULL; + ldns_rr *next_rr; + + if (!rr_list) { + return NULL; + } + + rrset = ldns_rr_list_new(); + if (!last_rr) { + last_rr = ldns_rr_list_pop_rr(rr_list); + if (!last_rr) { + ldns_rr_list_free(rrset); + return NULL; + } else { + ldns_rr_list_push_rr(rrset, last_rr); + } + } + + if (ldns_rr_list_rr_count(rr_list) > 0) { + next_rr = ldns_rr_list_rr(rr_list, ldns_rr_list_rr_count(rr_list) - 1); + } else { + next_rr = NULL; + } + + while (next_rr) { + if ( + ldns_rdf_compare(ldns_rr_owner(next_rr), + ldns_rr_owner(last_rr)) == 0 + && + ldns_rr_get_type(next_rr) == ldns_rr_get_type(last_rr) + && + ldns_rr_get_class(next_rr) == ldns_rr_get_class(last_rr) + ) { + ldns_rr_list_push_rr(rrset, ldns_rr_list_pop_rr(rr_list)); + if (ldns_rr_list_rr_count(rr_list) > 0) { + last_rr = next_rr; + next_rr = ldns_rr_list_rr(rr_list, ldns_rr_list_rr_count(rr_list) - 1); + } else { + next_rr = NULL; + } + } else { + next_rr = NULL; + } + } + + return rrset; +} + +ldns_rr * +ldns_rr_clone(const ldns_rr *rr) +{ + size_t i; + ldns_rr *new_rr; + + if (!rr) { + return NULL; + } + + new_rr = ldns_rr_new(); + if (!new_rr) { + return NULL; + } + if (ldns_rr_owner(rr)) { + ldns_rr_set_owner(new_rr, ldns_rdf_clone(ldns_rr_owner(rr))); + } + ldns_rr_set_ttl(new_rr, ldns_rr_ttl(rr)); + ldns_rr_set_type(new_rr, ldns_rr_get_type(rr)); + ldns_rr_set_class(new_rr, ldns_rr_get_class(rr)); + ldns_rr_set_question(new_rr, ldns_rr_is_question(rr)); + + for (i = 0; i < ldns_rr_rd_count(rr); i++) { + if (ldns_rr_rdf(rr,i)) { + ldns_rr_push_rdf(new_rr, ldns_rdf_clone(ldns_rr_rdf(rr, i))); + } + } + + return new_rr; +} + +ldns_rr_list * +ldns_rr_list_clone(const ldns_rr_list *rrlist) +{ + size_t i; + ldns_rr_list *new_list; + ldns_rr *r; + + if (!rrlist) { + return NULL; + } + + new_list = ldns_rr_list_new(); + if (!new_list) { + return NULL; + } + for (i = 0; i < ldns_rr_list_rr_count(rrlist); i++) { + r = ldns_rr_clone( + ldns_rr_list_rr(rrlist, i) + ); + if (!r) { + /* huh, failure in cloning */ + ldns_rr_list_deep_free(new_list); + return NULL; + } + ldns_rr_list_push_rr(new_list, r); + } + return new_list; +} + + +int +qsort_rr_compare(const void *a, const void *b) +{ + const ldns_rr *rr1 = * (const ldns_rr **) a; + const ldns_rr *rr2 = * (const ldns_rr **) b; + + if (rr1 == NULL && rr2 == NULL) { + return 0; + } + if (rr1 == NULL) { + return -1; + } + if (rr2 == NULL) { + return 1; + } + return ldns_rr_compare(rr1, rr2); +} + +int +qsort_schwartz_rr_compare(const void *a, const void *b) +{ + int result = 0; + ldns_rr *rr1, *rr2; + ldns_buffer *rr1_buf, *rr2_buf; + struct ldns_schwartzian_compare_struct *sa = *(struct ldns_schwartzian_compare_struct **) a; + struct ldns_schwartzian_compare_struct *sb = *(struct ldns_schwartzian_compare_struct **) b; + /* if we are doing 2wire, we need to do lowercasing on the dname (and maybe on the rdata) + * this must be done for comparison only, so we need to have a temp var for both buffers, + * which is only used when the transformed object value isn't there yet + */ + ldns_rr *canonical_a, *canonical_b; + + rr1 = (ldns_rr *) sa->original_object; + rr2 = (ldns_rr *) sb->original_object; + + result = ldns_rr_compare_no_rdata(rr1, rr2); + + if (result == 0) { + if (!sa->transformed_object) { + canonical_a = ldns_rr_clone(sa->original_object); + ldns_rr2canonical(canonical_a); + sa->transformed_object = ldns_buffer_new(ldns_rr_uncompressed_size(canonical_a)); + if (ldns_rr2buffer_wire(sa->transformed_object, canonical_a, LDNS_SECTION_ANY) != LDNS_STATUS_OK) { + ldns_buffer_free((ldns_buffer *)sa->transformed_object); + sa->transformed_object = NULL; + ldns_rr_free(canonical_a); + return 0; + } + ldns_rr_free(canonical_a); + } + if (!sb->transformed_object) { + canonical_b = ldns_rr_clone(sb->original_object); + ldns_rr2canonical(canonical_b); + sb->transformed_object = ldns_buffer_new(ldns_rr_uncompressed_size(canonical_b)); + if (ldns_rr2buffer_wire(sb->transformed_object, canonical_b, LDNS_SECTION_ANY) != LDNS_STATUS_OK) { + ldns_buffer_free((ldns_buffer *)sa->transformed_object); + ldns_buffer_free((ldns_buffer *)sb->transformed_object); + sa->transformed_object = NULL; + sb->transformed_object = NULL; + ldns_rr_free(canonical_b); + return 0; + } + ldns_rr_free(canonical_b); + } + rr1_buf = (ldns_buffer *) sa->transformed_object; + rr2_buf = (ldns_buffer *) sb->transformed_object; + + result = ldns_rr_compare_wire(rr1_buf, rr2_buf); + } + + return result; +} + +void +ldns_rr_list_sort(ldns_rr_list *unsorted) +{ + struct ldns_schwartzian_compare_struct **sortables; + size_t item_count; + size_t i; + + if (unsorted) { + item_count = ldns_rr_list_rr_count(unsorted); + + sortables = LDNS_XMALLOC(struct ldns_schwartzian_compare_struct *, + item_count); + if(!sortables) return; /* no way to return error */ + for (i = 0; i < item_count; i++) { + sortables[i] = LDNS_XMALLOC(struct ldns_schwartzian_compare_struct, 1); + if(!sortables[i]) { + /* free the allocated parts */ + while(i>0) { + i--; + LDNS_FREE(sortables[i]); + } + /* no way to return error */ + return; + } + sortables[i]->original_object = ldns_rr_list_rr(unsorted, i); + sortables[i]->transformed_object = NULL; + } + qsort(sortables, + item_count, + sizeof(struct ldns_schwartzian_compare_struct *), + qsort_schwartz_rr_compare); + for (i = 0; i < item_count; i++) { + unsorted->_rrs[i] = sortables[i]->original_object; + if (sortables[i]->transformed_object) { + ldns_buffer_free(sortables[i]->transformed_object); + } + LDNS_FREE(sortables[i]); + } + LDNS_FREE(sortables); + } +} + +int +ldns_rr_compare_no_rdata(const ldns_rr *rr1, const ldns_rr *rr2) +{ + size_t rr1_len; + size_t rr2_len; + size_t offset; + + assert(rr1 != NULL); + assert(rr2 != NULL); + + rr1_len = ldns_rr_uncompressed_size(rr1); + rr2_len = ldns_rr_uncompressed_size(rr2); + + if (ldns_dname_compare(ldns_rr_owner(rr1), ldns_rr_owner(rr2)) < 0) { + return -1; + } else if (ldns_dname_compare(ldns_rr_owner(rr1), ldns_rr_owner(rr2)) > 0) { + return 1; + } + + /* should return -1 if rr1 comes before rr2, so need to do rr1 - rr2, not rr2 - rr1 */ + if (ldns_rr_get_class(rr1) != ldns_rr_get_class(rr2)) { + return ldns_rr_get_class(rr1) - ldns_rr_get_class(rr2); + } + + /* should return -1 if rr1 comes before rr2, so need to do rr1 - rr2, not rr2 - rr1 */ + if (ldns_rr_get_type(rr1) != ldns_rr_get_type(rr2)) { + return ldns_rr_get_type(rr1) - ldns_rr_get_type(rr2); + } + + /* offset is the owername length + ttl + type + class + rdlen == start of wire format rdata */ + offset = ldns_rdf_size(ldns_rr_owner(rr1)) + 4 + 2 + 2 + 2; + /* if either record doesn't have any RDATA... */ + if (offset > rr1_len || offset > rr2_len) { + if (rr1_len == rr2_len) { + return 0; + } + return ((int) rr2_len - (int) rr1_len); + } + + return 0; +} + +int ldns_rr_compare_wire(ldns_buffer *rr1_buf, ldns_buffer *rr2_buf) +{ + size_t rr1_len, rr2_len, min_len, i, offset; + + rr1_len = ldns_buffer_capacity(rr1_buf); + rr2_len = ldns_buffer_capacity(rr2_buf); + + /* jump past dname (checked in earlier part) + * and especially past TTL */ + offset = 0; + while (offset < rr1_len && *ldns_buffer_at(rr1_buf, offset) != 0) { + offset += *ldns_buffer_at(rr1_buf, offset) + 1; + } + /* jump to rdata section (PAST the rdata length field, otherwise + rrs with different lengths might be sorted erroneously */ + offset += 11; + min_len = (rr1_len < rr2_len) ? rr1_len : rr2_len; + /* Compare RRs RDATA byte for byte. */ + for(i = offset; i < min_len; i++) { + if (*ldns_buffer_at(rr1_buf,i) < *ldns_buffer_at(rr2_buf,i)) { + return -1; + } else if (*ldns_buffer_at(rr1_buf,i) > *ldns_buffer_at(rr2_buf,i)) { + return +1; + } + } + + /* If both RDATAs are the same up to min_len, then the shorter one sorts first. */ + if (rr1_len < rr2_len) { + return -1; + } else if (rr1_len > rr2_len) { + return +1; + } + /* The RDATAs are equal. */ + return 0; + +} + +int +ldns_rr_compare(const ldns_rr *rr1, const ldns_rr *rr2) +{ + int result; + size_t rr1_len, rr2_len; + + ldns_buffer *rr1_buf; + ldns_buffer *rr2_buf; + + result = ldns_rr_compare_no_rdata(rr1, rr2); + if (result == 0) { + rr1_len = ldns_rr_uncompressed_size(rr1); + rr2_len = ldns_rr_uncompressed_size(rr2); + + rr1_buf = ldns_buffer_new(rr1_len); + rr2_buf = ldns_buffer_new(rr2_len); + + if (ldns_rr2buffer_wire_canonical(rr1_buf, + rr1, + LDNS_SECTION_ANY) + != LDNS_STATUS_OK) { + ldns_buffer_free(rr1_buf); + ldns_buffer_free(rr2_buf); + return 0; + } + if (ldns_rr2buffer_wire_canonical(rr2_buf, + rr2, + LDNS_SECTION_ANY) + != LDNS_STATUS_OK) { + ldns_buffer_free(rr1_buf); + ldns_buffer_free(rr2_buf); + return 0; + } + + result = ldns_rr_compare_wire(rr1_buf, rr2_buf); + + ldns_buffer_free(rr1_buf); + ldns_buffer_free(rr2_buf); + } + + return result; +} + +/* convert dnskey to a ds with the given algorithm, + * then compare the result with the given ds */ +static int +ldns_rr_compare_ds_dnskey(ldns_rr *ds, + ldns_rr *dnskey) +{ + ldns_rr *ds_gen; + bool result = false; + ldns_hash algo; + + if (!dnskey || !ds || + ldns_rr_get_type(ds) != LDNS_RR_TYPE_DS || + ldns_rr_get_type(dnskey) != LDNS_RR_TYPE_DNSKEY) { + return false; + } + + if (ldns_rr_rdf(ds, 2) == NULL) { + return false; + } + algo = ldns_rdf2native_int8(ldns_rr_rdf(ds, 2)); + + ds_gen = ldns_key_rr2ds(dnskey, algo); + if (ds_gen) { + result = ldns_rr_compare(ds, ds_gen) == 0; + ldns_rr_free(ds_gen); + } + return result; +} + +bool +ldns_rr_compare_ds(const ldns_rr *orr1, const ldns_rr *orr2) +{ + bool result; + ldns_rr *rr1 = ldns_rr_clone(orr1); + ldns_rr *rr2 = ldns_rr_clone(orr2); + + /* set ttls to zero */ + ldns_rr_set_ttl(rr1, 0); + ldns_rr_set_ttl(rr2, 0); + + if (ldns_rr_get_type(rr1) == LDNS_RR_TYPE_DS && + ldns_rr_get_type(rr2) == LDNS_RR_TYPE_DNSKEY) { + result = ldns_rr_compare_ds_dnskey(rr1, rr2); + } else if (ldns_rr_get_type(rr1) == LDNS_RR_TYPE_DNSKEY && + ldns_rr_get_type(rr2) == LDNS_RR_TYPE_DS) { + result = ldns_rr_compare_ds_dnskey(rr2, rr1); + } else { + result = (ldns_rr_compare(rr1, rr2) == 0); + } + + ldns_rr_free(rr1); + ldns_rr_free(rr2); + + return result; +} + +int +ldns_rr_list_compare(const ldns_rr_list *rrl1, const ldns_rr_list *rrl2) +{ + size_t i = 0; + int rr_cmp; + + assert(rrl1 != NULL); + assert(rrl2 != NULL); + + for (i = 0; i < ldns_rr_list_rr_count(rrl1) && i < ldns_rr_list_rr_count(rrl2); i++) { + rr_cmp = ldns_rr_compare(ldns_rr_list_rr(rrl1, i), ldns_rr_list_rr(rrl2, i)); + if (rr_cmp != 0) { + return rr_cmp; + } + } + + if (i == ldns_rr_list_rr_count(rrl1) && + i != ldns_rr_list_rr_count(rrl2)) { + return 1; + } else if (i == ldns_rr_list_rr_count(rrl2) && + i != ldns_rr_list_rr_count(rrl1)) { + return -1; + } else { + return 0; + } +} + +size_t +ldns_rr_uncompressed_size(const ldns_rr *r) +{ + size_t rrsize; + size_t i; + + rrsize = 0; + /* add all the rdf sizes */ + for(i = 0; i < ldns_rr_rd_count(r); i++) { + rrsize += ldns_rdf_size(ldns_rr_rdf(r, i)); + } + /* ownername */ + rrsize += ldns_rdf_size(ldns_rr_owner(r)); + rrsize += LDNS_RR_OVERHEAD; + return rrsize; +} + +void +ldns_rr2canonical(ldns_rr *rr) +{ + uint16_t i; + + if (!rr) { + return; + } + + ldns_dname2canonical(ldns_rr_owner(rr)); + + /* + * lowercase the rdata dnames if the rr type is one + * of the list in chapter 7 of RFC3597 + * Also added RRSIG, because a "Signer's Name" should be canonicalized + * too. See dnssec-bis-updates-16. We can add it to this list because + * the "Signer's Name" is the only dname type rdata field in a RRSIG. + */ + switch(ldns_rr_get_type(rr)) { + case LDNS_RR_TYPE_NS: + case LDNS_RR_TYPE_MD: + case LDNS_RR_TYPE_MF: + case LDNS_RR_TYPE_CNAME: + case LDNS_RR_TYPE_SOA: + case LDNS_RR_TYPE_MB: + case LDNS_RR_TYPE_MG: + case LDNS_RR_TYPE_MR: + case LDNS_RR_TYPE_PTR: + case LDNS_RR_TYPE_MINFO: + case LDNS_RR_TYPE_MX: + case LDNS_RR_TYPE_RP: + case LDNS_RR_TYPE_AFSDB: + case LDNS_RR_TYPE_RT: + case LDNS_RR_TYPE_SIG: + case LDNS_RR_TYPE_PX: + case LDNS_RR_TYPE_NXT: + case LDNS_RR_TYPE_NAPTR: + case LDNS_RR_TYPE_KX: + case LDNS_RR_TYPE_SRV: + case LDNS_RR_TYPE_DNAME: + case LDNS_RR_TYPE_A6: + case LDNS_RR_TYPE_RRSIG: + for (i = 0; i < ldns_rr_rd_count(rr); i++) { + ldns_dname2canonical(ldns_rr_rdf(rr, i)); + } + return; + default: + /* do nothing */ + return; + } +} + +void +ldns_rr_list2canonical(ldns_rr_list *rr_list) +{ + size_t i; + for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) { + ldns_rr2canonical(ldns_rr_list_rr(rr_list, i)); + } +} + +uint8_t +ldns_rr_label_count(ldns_rr *rr) +{ + if (!rr) { + return 0; + } + return ldns_dname_label_count( + ldns_rr_owner(rr)); +} + +/** \cond */ +static const ldns_rdf_type type_0_wireformat[] = { LDNS_RDF_TYPE_UNKNOWN }; +static const ldns_rdf_type type_a_wireformat[] = { LDNS_RDF_TYPE_A }; +static const ldns_rdf_type type_ns_wireformat[] = { LDNS_RDF_TYPE_DNAME }; +static const ldns_rdf_type type_md_wireformat[] = { LDNS_RDF_TYPE_DNAME }; +static const ldns_rdf_type type_mf_wireformat[] = { LDNS_RDF_TYPE_DNAME }; +static const ldns_rdf_type type_cname_wireformat[] = { LDNS_RDF_TYPE_DNAME }; +static const ldns_rdf_type type_soa_wireformat[] = { + LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_INT32, + LDNS_RDF_TYPE_PERIOD, LDNS_RDF_TYPE_PERIOD, LDNS_RDF_TYPE_PERIOD, + LDNS_RDF_TYPE_PERIOD +}; +static const ldns_rdf_type type_mb_wireformat[] = { LDNS_RDF_TYPE_DNAME }; +static const ldns_rdf_type type_mg_wireformat[] = { LDNS_RDF_TYPE_DNAME }; +static const ldns_rdf_type type_mr_wireformat[] = { LDNS_RDF_TYPE_DNAME }; +static const ldns_rdf_type type_wks_wireformat[] = { + LDNS_RDF_TYPE_A, LDNS_RDF_TYPE_WKS +}; +static const ldns_rdf_type type_ptr_wireformat[] = { LDNS_RDF_TYPE_DNAME }; +static const ldns_rdf_type type_hinfo_wireformat[] = { + LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR +}; +static const ldns_rdf_type type_minfo_wireformat[] = { + LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_DNAME +}; +static const ldns_rdf_type type_mx_wireformat[] = { + LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME +}; +static const ldns_rdf_type type_rp_wireformat[] = { + LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_DNAME +}; +static const ldns_rdf_type type_afsdb_wireformat[] = { + LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME +}; +static const ldns_rdf_type type_x25_wireformat[] = { LDNS_RDF_TYPE_STR }; +static const ldns_rdf_type type_isdn_wireformat[] = { + LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR +}; +static const ldns_rdf_type type_rt_wireformat[] = { + LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME +}; +static const ldns_rdf_type type_nsap_wireformat[] = { + LDNS_RDF_TYPE_NSAP +}; +static const ldns_rdf_type type_nsap_ptr_wireformat[] = { + LDNS_RDF_TYPE_STR +}; +static const ldns_rdf_type type_sig_wireformat[] = { + LDNS_RDF_TYPE_TYPE, LDNS_RDF_TYPE_ALG, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT32, + LDNS_RDF_TYPE_TIME, LDNS_RDF_TYPE_TIME, LDNS_RDF_TYPE_INT16, + LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_B64 +}; +static const ldns_rdf_type type_key_wireformat[] = { + LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_B64 +}; +static const ldns_rdf_type type_px_wireformat[] = { + LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_DNAME +}; +static const ldns_rdf_type type_gpos_wireformat[] = { + LDNS_RDF_TYPE_STR, + LDNS_RDF_TYPE_STR, + LDNS_RDF_TYPE_STR +}; +static const ldns_rdf_type type_aaaa_wireformat[] = { LDNS_RDF_TYPE_AAAA }; +static const ldns_rdf_type type_loc_wireformat[] = { LDNS_RDF_TYPE_LOC }; +static const ldns_rdf_type type_nxt_wireformat[] = { + LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_UNKNOWN +}; +static const ldns_rdf_type type_eid_wireformat[] = { + LDNS_RDF_TYPE_HEX +}; +static const ldns_rdf_type type_nimloc_wireformat[] = { + LDNS_RDF_TYPE_HEX +}; +static const ldns_rdf_type type_srv_wireformat[] = { + LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME +}; +static const ldns_rdf_type type_atma_wireformat[] = { + LDNS_RDF_TYPE_ATMA +}; +static const ldns_rdf_type type_naptr_wireformat[] = { + LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_DNAME +}; +static const ldns_rdf_type type_kx_wireformat[] = { + LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME +}; +static const ldns_rdf_type type_cert_wireformat[] = { + LDNS_RDF_TYPE_CERT_ALG, LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_ALG, LDNS_RDF_TYPE_B64 +}; +static const ldns_rdf_type type_a6_wireformat[] = { LDNS_RDF_TYPE_UNKNOWN }; +static const ldns_rdf_type type_dname_wireformat[] = { LDNS_RDF_TYPE_DNAME }; +static const ldns_rdf_type type_sink_wireformat[] = { LDNS_RDF_TYPE_INT8, + LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_B64 +}; +static const ldns_rdf_type type_apl_wireformat[] = { + LDNS_RDF_TYPE_APL +}; +static const ldns_rdf_type type_ds_wireformat[] = { + LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_ALG, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_HEX +}; +static const ldns_rdf_type type_sshfp_wireformat[] = { + LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_HEX +}; +static const ldns_rdf_type type_ipseckey_wireformat[] = { + LDNS_RDF_TYPE_IPSECKEY +}; +static const ldns_rdf_type type_rrsig_wireformat[] = { + LDNS_RDF_TYPE_TYPE, LDNS_RDF_TYPE_ALG, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT32, + LDNS_RDF_TYPE_TIME, LDNS_RDF_TYPE_TIME, LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_B64 +}; +static const ldns_rdf_type type_nsec_wireformat[] = { + LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_NSEC +}; +static const ldns_rdf_type type_dhcid_wireformat[] = { + LDNS_RDF_TYPE_B64 +}; +static const ldns_rdf_type type_talink_wireformat[] = { + LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_DNAME +}; +/* nsec3 is some vars, followed by same type of data of nsec */ +static const ldns_rdf_type type_nsec3_wireformat[] = { +/* LDNS_RDF_TYPE_NSEC3_VARS, LDNS_RDF_TYPE_NSEC3_NEXT_OWNER, LDNS_RDF_TYPE_NSEC*/ + LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_NSEC3_SALT, LDNS_RDF_TYPE_NSEC3_NEXT_OWNER, LDNS_RDF_TYPE_NSEC +}; + +static const ldns_rdf_type type_nsec3param_wireformat[] = { +/* LDNS_RDF_TYPE_NSEC3_PARAMS_VARS*/ + LDNS_RDF_TYPE_INT8, + LDNS_RDF_TYPE_INT8, + LDNS_RDF_TYPE_INT16, + LDNS_RDF_TYPE_NSEC3_SALT +}; + +static const ldns_rdf_type type_dnskey_wireformat[] = { + LDNS_RDF_TYPE_INT16, + LDNS_RDF_TYPE_INT8, + LDNS_RDF_TYPE_ALG, + LDNS_RDF_TYPE_B64 +}; +static const ldns_rdf_type type_tsig_wireformat[] = { + LDNS_RDF_TYPE_DNAME, + LDNS_RDF_TYPE_TSIGTIME, + LDNS_RDF_TYPE_INT16, + LDNS_RDF_TYPE_INT16_DATA, + LDNS_RDF_TYPE_INT16, + LDNS_RDF_TYPE_INT16, + LDNS_RDF_TYPE_INT16_DATA +}; +/** \endcond */ + +/** \cond */ +/* All RR's defined in 1035 are well known and can thus + * be compressed. See RFC3597. These RR's are: + * CNAME HINFO MB MD MF MG MINFO MR MX NULL NS PTR SOA TXT + */ +static ldns_rr_descriptor rdata_field_descriptors[] = { + /* 0 */ + { 0, NULL, 0, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + /* 1 */ + {LDNS_RR_TYPE_A, "A", 1, 1, type_a_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + /* 2 */ + {LDNS_RR_TYPE_NS, "NS", 1, 1, type_ns_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 }, + /* 3 */ + {LDNS_RR_TYPE_MD, "MD", 1, 1, type_md_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 }, + /* 4 */ + {LDNS_RR_TYPE_MF, "MF", 1, 1, type_mf_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 }, + /* 5 */ + {LDNS_RR_TYPE_CNAME, "CNAME", 1, 1, type_cname_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 }, + /* 6 */ + {LDNS_RR_TYPE_SOA, "SOA", 7, 7, type_soa_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 2 }, + /* 7 */ + {LDNS_RR_TYPE_MB, "MB", 1, 1, type_mb_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 }, + /* 8 */ + {LDNS_RR_TYPE_MG, "MG", 1, 1, type_mg_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 }, + /* 9 */ + {LDNS_RR_TYPE_MR, "MR", 1, 1, type_mr_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 }, + /* 10 */ + {LDNS_RR_TYPE_NULL, "NULL", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + /* 11 */ + {LDNS_RR_TYPE_WKS, "WKS", 2, 2, type_wks_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + /* 12 */ + {LDNS_RR_TYPE_PTR, "PTR", 1, 1, type_ptr_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 }, + /* 13 */ + {LDNS_RR_TYPE_HINFO, "HINFO", 2, 2, type_hinfo_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + /* 14 */ + {LDNS_RR_TYPE_MINFO, "MINFO", 2, 2, type_minfo_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 2 }, + /* 15 */ + {LDNS_RR_TYPE_MX, "MX", 2, 2, type_mx_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 }, + /* 16 */ + {LDNS_RR_TYPE_TXT, "TXT", 1, 0, NULL, LDNS_RDF_TYPE_STR, LDNS_RR_NO_COMPRESS, 0 }, + /* 17 */ + {LDNS_RR_TYPE_RP, "RP", 2, 2, type_rp_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 2 }, + /* 18 */ + {LDNS_RR_TYPE_AFSDB, "AFSDB", 2, 2, type_afsdb_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 }, + /* 19 */ + {LDNS_RR_TYPE_X25, "X25", 1, 1, type_x25_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + /* 20 */ + {LDNS_RR_TYPE_ISDN, "ISDN", 1, 2, type_isdn_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + /* 21 */ + {LDNS_RR_TYPE_RT, "RT", 2, 2, type_rt_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 }, + /* 22 */ + {LDNS_RR_TYPE_NSAP, "NSAP", 1, 1, type_nsap_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + /* 23 */ + {LDNS_RR_TYPE_NSAP_PTR, "NSAP-PTR", 1, 1, type_nsap_ptr_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + /* 24 */ + {LDNS_RR_TYPE_SIG, "SIG", 9, 9, type_sig_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 }, + /* 25 */ + {LDNS_RR_TYPE_KEY, "KEY", 4, 4, type_key_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + /* 26 */ + {LDNS_RR_TYPE_PX, "PX", 3, 3, type_px_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 2 }, + /* 27 */ + {LDNS_RR_TYPE_GPOS, "GPOS", 1, 1, type_gpos_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + /* 28 */ + {LDNS_RR_TYPE_AAAA, "AAAA", 1, 1, type_aaaa_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + /* 29 */ + {LDNS_RR_TYPE_LOC, "LOC", 1, 1, type_loc_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + /* 30 */ + {LDNS_RR_TYPE_NXT, "NXT", 2, 2, type_nxt_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 }, + /* 31 */ + {LDNS_RR_TYPE_EID, "EID", 1, 1, type_eid_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + /* 32 */ + {LDNS_RR_TYPE_NIMLOC, "NIMLOC", 1, 1, type_nimloc_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + /* 33 */ + {LDNS_RR_TYPE_SRV, "SRV", 4, 4, type_srv_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 }, + /* 34 */ + {LDNS_RR_TYPE_ATMA, "ATMA", 1, 1, type_atma_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + /* 35 */ + {LDNS_RR_TYPE_NAPTR, "NAPTR", 6, 6, type_naptr_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 }, + /* 36 */ + {LDNS_RR_TYPE_KX, "KX", 2, 2, type_kx_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 }, + /* 37 */ + {LDNS_RR_TYPE_CERT, "CERT", 4, 4, type_cert_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + /* 38 */ + {LDNS_RR_TYPE_A6, "A6", 1, 1, type_a6_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + /* 39 */ + {LDNS_RR_TYPE_DNAME, "DNAME", 1, 1, type_dname_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 }, + /* 40 */ + {LDNS_RR_TYPE_SINK, "SINK", 1, 1, type_sink_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + /* 41 */ + {LDNS_RR_TYPE_OPT, "OPT", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + /* 42 */ + {LDNS_RR_TYPE_APL, "APL", 0, 0, type_apl_wireformat, LDNS_RDF_TYPE_APL, LDNS_RR_NO_COMPRESS, 0 }, + /* 43 */ + {LDNS_RR_TYPE_DS, "DS", 4, 4, type_ds_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + /* 44 */ + {LDNS_RR_TYPE_SSHFP, "SSHFP", 3, 3, type_sshfp_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + /* 45 */ + {LDNS_RR_TYPE_IPSECKEY, "IPSECKEY", 1, 1, type_ipseckey_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + /* 46 */ + {LDNS_RR_TYPE_RRSIG, "RRSIG", 9, 9, type_rrsig_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 }, + /* 47 */ + {LDNS_RR_TYPE_NSEC, "NSEC", 1, 2, type_nsec_wireformat, LDNS_RDF_TYPE_NSEC, LDNS_RR_NO_COMPRESS, 1 }, + /* 48 */ + {LDNS_RR_TYPE_DNSKEY, "DNSKEY", 4, 4, type_dnskey_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + /* 49 */ +{LDNS_RR_TYPE_DHCID, "DHCID", 1, 1, type_dhcid_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + /* 50 */ + {LDNS_RR_TYPE_NSEC3, "NSEC3", 5, 6, type_nsec3_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + /* 51 */ +{LDNS_RR_TYPE_NSEC3PARAM, "NSEC3PARAM", 4, 4, type_nsec3param_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + /* 52 */ +{LDNS_RR_TYPE_NULL, "TYPE52", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE53", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE54", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE55", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE56", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE57", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + /* 58 */ +{LDNS_RR_TYPE_TALINK, "TALINK", 2, 2, type_talink_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 2 }, +{LDNS_RR_TYPE_NULL, "TYPE59", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE60", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE61", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE62", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE63", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE64", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE65", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE66", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE67", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE68", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE69", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE70", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE71", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE72", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE73", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE74", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE75", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE76", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE77", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE78", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE79", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE80", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE81", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE82", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE83", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE84", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE85", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE86", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE87", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE88", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE89", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE90", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE91", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE92", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE93", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE94", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE95", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE96", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE97", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE98", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_SPF, "SPF", 1, 0, NULL, LDNS_RDF_TYPE_STR, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE100", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE101", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE102", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE103", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE104", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE105", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE106", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE107", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE108", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE109", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE110", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE111", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE112", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE113", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE114", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE115", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE116", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE117", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE118", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE119", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE120", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE121", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE122", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE123", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE124", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE125", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE126", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE127", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE128", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE129", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE130", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE131", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE132", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE133", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE134", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE135", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE136", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE137", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE138", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE139", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE140", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE141", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE142", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE143", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE144", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE145", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE146", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE147", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE148", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE149", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE150", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE151", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE152", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE153", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE154", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE155", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE156", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE157", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE158", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE159", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE160", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE161", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE162", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE163", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE164", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE165", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE166", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE167", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE168", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE169", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE170", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE171", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE172", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE173", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE174", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE175", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE176", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE177", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE178", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE179", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE180", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE181", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE182", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE183", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE184", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE185", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE186", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE187", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE188", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE189", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE190", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE191", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE192", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE193", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE194", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE195", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE196", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE197", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE198", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE199", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE200", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE201", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE202", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE203", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE204", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE205", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE206", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE207", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE208", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE209", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE210", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE211", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE212", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE213", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE214", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE215", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE216", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE217", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE218", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE219", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE220", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE221", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE222", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE223", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE224", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE225", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE226", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE227", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE228", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE229", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE230", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE231", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE232", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE233", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE234", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE235", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE236", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE237", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE238", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE239", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE240", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE241", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE242", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE243", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE244", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE245", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE246", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE247", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE248", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +{LDNS_RR_TYPE_NULL, "TYPE249", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +/* LDNS_RDF_TYPE_INT16_DATA essentially takes two fields (length and data) and + * makes them into one. So, while in rfc 2845 is specified that a TSIG may have + * 8 or 9 rdata fields, by this implementation, the min/max are 7 each. + */ +{LDNS_RR_TYPE_TSIG, "TSIG", 7, 7, type_tsig_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, +/* split in array, no longer contiguous */ +{LDNS_RR_TYPE_DLV, "DLV", 4, 4, type_ds_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 } +}; +/** \endcond */ + +/** + * \def LDNS_RDATA_FIELD_DESCRIPTORS_COUNT + * computes the number of rdata fields + */ +#define LDNS_RDATA_FIELD_DESCRIPTORS_COUNT \ + (sizeof(rdata_field_descriptors)/sizeof(rdata_field_descriptors[0])) + +const ldns_rr_descriptor * +ldns_rr_descript(uint16_t type) +{ + size_t i; + if (type <= LDNS_RDATA_FIELD_DESCRIPTORS_COMMON) { + return &rdata_field_descriptors[type]; + } else { + /* because not all array index equals type code */ + for (i = LDNS_RDATA_FIELD_DESCRIPTORS_COMMON; + i < LDNS_RDATA_FIELD_DESCRIPTORS_COUNT; + i++) { + if (rdata_field_descriptors[i]._type == type) { + return &rdata_field_descriptors[i]; + } + } + return &rdata_field_descriptors[0]; + } +} + +size_t +ldns_rr_descriptor_minimum(const ldns_rr_descriptor *descriptor) +{ + if (descriptor) { + return descriptor->_minimum; + } else { + return 0; + } +} + +size_t +ldns_rr_descriptor_maximum(const ldns_rr_descriptor *descriptor) +{ + if (descriptor) { + if (descriptor->_variable != LDNS_RDF_TYPE_NONE) { + /* Should really be SIZE_MAX... bad FreeBSD. */ + return UINT_MAX; + } else { + return descriptor->_maximum; + } + } else { + return 0; + } +} + +ldns_rdf_type +ldns_rr_descriptor_field_type(const ldns_rr_descriptor *descriptor, + size_t index) +{ + assert(descriptor != NULL); + assert(index < descriptor->_maximum + || descriptor->_variable != LDNS_RDF_TYPE_NONE); + if (index < descriptor->_maximum) { + return descriptor->_wireformat[index]; + } else { + return descriptor->_variable; + } +} + +ldns_rr_type +ldns_get_rr_type_by_name(const char *name) +{ + unsigned int i; + const char *desc_name; + const ldns_rr_descriptor *desc; + + /* TYPEXX representation */ + if (strlen(name) > 4 && strncasecmp(name, "TYPE", 4) == 0) { + return atoi(name + 4); + } + + /* Normal types */ + for (i = 0; i < (unsigned int) LDNS_RDATA_FIELD_DESCRIPTORS_COUNT; i++) { + desc = &rdata_field_descriptors[i]; + desc_name = desc->_name; + if(desc_name && + strlen(name) == strlen(desc_name) && + strncasecmp(name, desc_name, strlen(desc_name)) == 0) { + /* because not all array index equals type code */ + return desc->_type; + } + } + + /* special cases for query types */ + if (strlen(name) == 4 && strncasecmp(name, "IXFR", 4) == 0) { + return 251; + } else if (strlen(name) == 4 && strncasecmp(name, "AXFR", 4) == 0) { + return 252; + } else if (strlen(name) == 5 && strncasecmp(name, "MAILB", 5) == 0) { + return 253; + } else if (strlen(name) == 5 && strncasecmp(name, "MAILA", 5) == 0) { + return 254; + } else if (strlen(name) == 3 && strncasecmp(name, "ANY", 3) == 0) { + return 255; + } + + return 0; +} + +ldns_rr_class +ldns_get_rr_class_by_name(const char *name) +{ + ldns_lookup_table *lt; + + /* CLASSXX representation */ + if (strlen(name) > 5 && strncasecmp(name, "CLASS", 5) == 0) { + return atoi(name + 5); + } + + /* Normal types */ + lt = ldns_lookup_by_name(ldns_rr_classes, name); + + if (lt) { + return lt->id; + } + return 0; +} + + +ldns_rr_type +ldns_rdf2rr_type(const ldns_rdf *rd) +{ + ldns_rr_type r; + + if (!rd) { + return 0; + } + + if (ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_TYPE) { + return 0; + } + + r = (ldns_rr_type) ldns_rdf2native_int16(rd); + return r; +} + +ldns_rr_type +ldns_rr_list_type(const ldns_rr_list *rr_list) +{ + if (rr_list && ldns_rr_list_rr_count(rr_list) > 0) { + return ldns_rr_get_type(ldns_rr_list_rr(rr_list, 0)); + } else { + return 0; + } +} + +ldns_rdf * +ldns_rr_list_owner(const ldns_rr_list *rr_list) +{ + if (rr_list && ldns_rr_list_rr_count(rr_list) > 0) { + return ldns_rr_owner(ldns_rr_list_rr(rr_list, 0)); + } else { + return NULL; + } +} diff --git a/rr_functions.c b/rr_functions.c new file mode 100644 index 00000000000..b03751b01ec --- /dev/null +++ b/rr_functions.c @@ -0,0 +1,419 @@ +/* + * rr_function.c + * + * function that operate on specific rr types + * + * (c) NLnet Labs, 2004-2006 + * See the file LICENSE for the license + */ + +/* + * These come strait from perldoc Net::DNS::RR::xxx + * first the read variant, then the write. This is + * not complete. + */ + +#include + +#include + +#include +#include + +/** + * return a specific rdf + * \param[in] type type of RR + * \param[in] rr the rr itself + * \param[in] pos at which postion to get it + * \return the rdf sought + */ +static ldns_rdf * +ldns_rr_function(ldns_rr_type type, const ldns_rr *rr, size_t pos) +{ + if (!rr || ldns_rr_get_type(rr) != type) { + return NULL; + } + return ldns_rr_rdf(rr, pos); +} + +/** + * set a specific rdf + * \param[in] type type of RR + * \param[in] rr the rr itself + * \param[in] rdf the rdf to set + * \param[in] pos at which postion to set it + * \return true or false + */ +static bool +ldns_rr_set_function(ldns_rr_type type, ldns_rr *rr, ldns_rdf *rdf, size_t pos) +{ + ldns_rdf *pop; + if (!rr || ldns_rr_get_type(rr) != type) { + return false; + } + pop = ldns_rr_set_rdf(rr, rdf, pos); + ldns_rdf_deep_free(pop); + return true; +} + +/* A/AAAA records */ +ldns_rdf * +ldns_rr_a_address(const ldns_rr *r) +{ + /* 2 types to check, cannot use the macro */ + if (!r || (ldns_rr_get_type(r) != LDNS_RR_TYPE_A && + ldns_rr_get_type(r) != LDNS_RR_TYPE_AAAA)) { + return NULL; + } + return ldns_rr_rdf(r, 0); +} + +bool +ldns_rr_a_set_address(ldns_rr *r, ldns_rdf *f) +{ + /* 2 types to check, cannot use the macro... */ + ldns_rdf *pop; + if (!r || (ldns_rr_get_type(r) != LDNS_RR_TYPE_A && + ldns_rr_get_type(r) != LDNS_RR_TYPE_AAAA)) { + return false; + } + pop = ldns_rr_set_rdf(r, f, 0); + if (pop) { + LDNS_FREE(pop); + return true; + } else { + return false; + } +} + +/* NS record */ +ldns_rdf * +ldns_rr_ns_nsdname(const ldns_rr *r) +{ + return ldns_rr_function(LDNS_RR_TYPE_NS, r, 0); +} + +/* MX record */ +ldns_rdf * +ldns_rr_mx_preference(const ldns_rr *r) +{ + return ldns_rr_function(LDNS_RR_TYPE_MX, r, 0); +} + +ldns_rdf * +ldns_rr_mx_exchange(const ldns_rr *r) +{ + return ldns_rr_function(LDNS_RR_TYPE_MX, r, 1); +} + +/* RRSIG record */ +ldns_rdf * +ldns_rr_rrsig_typecovered(const ldns_rr *r) +{ + return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 0); +} + +bool +ldns_rr_rrsig_set_typecovered(ldns_rr *r, ldns_rdf *f) +{ + return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 0); +} + +ldns_rdf * +ldns_rr_rrsig_algorithm(const ldns_rr *r) +{ + return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 1); +} + +bool +ldns_rr_rrsig_set_algorithm(ldns_rr *r, ldns_rdf *f) +{ + return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 1); +} + +ldns_rdf * +ldns_rr_rrsig_labels(const ldns_rr *r) +{ + return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 2); +} + +bool +ldns_rr_rrsig_set_labels(ldns_rr *r, ldns_rdf *f) +{ + return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 2); +} + +ldns_rdf * +ldns_rr_rrsig_origttl(const ldns_rr *r) +{ + return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 3); +} + +bool +ldns_rr_rrsig_set_origttl(ldns_rr *r, ldns_rdf *f) +{ + return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 3); +} + +ldns_rdf * +ldns_rr_rrsig_expiration(const ldns_rr *r) +{ + return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 4); +} + +bool +ldns_rr_rrsig_set_expiration(ldns_rr *r, ldns_rdf *f) +{ + return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 4); +} + +ldns_rdf * +ldns_rr_rrsig_inception(const ldns_rr *r) +{ + return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 5); +} + +bool +ldns_rr_rrsig_set_inception(ldns_rr *r, ldns_rdf *f) +{ + return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 5); +} + +ldns_rdf * +ldns_rr_rrsig_keytag(const ldns_rr *r) +{ + return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 6); +} + +bool +ldns_rr_rrsig_set_keytag(ldns_rr *r, ldns_rdf *f) +{ + return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 6); +} + +ldns_rdf * +ldns_rr_rrsig_signame(const ldns_rr *r) +{ + return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 7); +} + +bool +ldns_rr_rrsig_set_signame(ldns_rr *r, ldns_rdf *f) +{ + return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 7); +} + +ldns_rdf * +ldns_rr_rrsig_sig(const ldns_rr *r) +{ + return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 8); +} + +bool +ldns_rr_rrsig_set_sig(ldns_rr *r, ldns_rdf *f) +{ + return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 8); +} + +/* DNSKEY record */ +ldns_rdf * +ldns_rr_dnskey_flags(const ldns_rr *r) +{ + return ldns_rr_function(LDNS_RR_TYPE_DNSKEY, r, 0); +} + +bool +ldns_rr_dnskey_set_flags(ldns_rr *r, ldns_rdf *f) +{ + return ldns_rr_set_function(LDNS_RR_TYPE_DNSKEY, r, f, 0); +} + +ldns_rdf * +ldns_rr_dnskey_protocol(const ldns_rr *r) +{ + return ldns_rr_function(LDNS_RR_TYPE_DNSKEY, r, 1); +} + +bool +ldns_rr_dnskey_set_protocol(ldns_rr *r, ldns_rdf *f) +{ + return ldns_rr_set_function(LDNS_RR_TYPE_DNSKEY, r, f, 1); +} + +ldns_rdf * +ldns_rr_dnskey_algorithm(const ldns_rr *r) +{ + return ldns_rr_function(LDNS_RR_TYPE_DNSKEY, r, 2); +} + +bool +ldns_rr_dnskey_set_algorithm(ldns_rr *r, ldns_rdf *f) +{ + return ldns_rr_set_function(LDNS_RR_TYPE_DNSKEY, r, f, 2); +} + +ldns_rdf * +ldns_rr_dnskey_key(const ldns_rr *r) +{ + return ldns_rr_function(LDNS_RR_TYPE_DNSKEY, r, 3); +} + +bool +ldns_rr_dnskey_set_key(ldns_rr *r, ldns_rdf *f) +{ + return ldns_rr_set_function(LDNS_RR_TYPE_DNSKEY, r, f, 3); +} + +size_t +ldns_rr_dnskey_key_size_raw(const unsigned char* keydata, + const size_t len, + const ldns_algorithm alg) +{ + /* for DSA keys */ + uint8_t t; + + /* for RSA keys */ + uint16_t exp; + uint16_t int16; + + switch ((ldns_signing_algorithm)alg) { + case LDNS_SIGN_DSA: + case LDNS_SIGN_DSA_NSEC3: + if (len > 0) { + t = keydata[0]; + return (64 + t*8)*8; + } else { + return 0; + } + break; + case LDNS_SIGN_RSAMD5: + case LDNS_SIGN_RSASHA1: + case LDNS_SIGN_RSASHA1_NSEC3: +#ifdef USE_SHA2 + case LDNS_SIGN_RSASHA256: + case LDNS_SIGN_RSASHA512: +#endif + if (len > 0) { + if (keydata[0] == 0) { + /* big exponent */ + if (len > 3) { + memmove(&int16, keydata + 1, 2); + exp = ntohs(int16); + return (len - exp - 3)*8; + } else { + return 0; + } + } else { + exp = keydata[0]; + return (len-exp-1)*8; + } + } else { + return 0; + } + break; +#ifdef USE_GOST + case LDNS_SIGN_ECC_GOST: + return 512; +#endif +#ifdef USE_ECDSA + case LDNS_SIGN_ECDSAP256SHA256: + return 256; + case LDNS_SIGN_ECDSAP384SHA384: + return 384; +#endif + case LDNS_SIGN_HMACMD5: + return len; + default: + return 0; + } +} + +size_t +ldns_rr_dnskey_key_size(const ldns_rr *key) +{ + if (!key || !ldns_rr_dnskey_key(key) + || !ldns_rr_dnskey_algorithm(key)) { + return 0; + } + return ldns_rr_dnskey_key_size_raw((unsigned char*)ldns_rdf_data(ldns_rr_dnskey_key(key)), + ldns_rdf_size(ldns_rr_dnskey_key(key)), + ldns_rdf2native_int8(ldns_rr_dnskey_algorithm(key)) + ); +} + +uint32_t ldns_soa_serial_identity(uint32_t ATTR_UNUSED(unused), void *data) +{ + return (uint32_t) (intptr_t) data; +} + +uint32_t ldns_soa_serial_increment(uint32_t s, void *ATTR_UNUSED(unused)) +{ + return ldns_soa_serial_increment_by(s, (void *)1); +} + +uint32_t ldns_soa_serial_increment_by(uint32_t s, void *data) +{ + return s + (intptr_t) data; +} + +uint32_t ldns_soa_serial_datecounter(uint32_t s, void *data) +{ + struct tm tm; + char s_str[11]; + int32_t new_s; + time_t t = data ? (time_t) (intptr_t) data : ldns_time(NULL); + + (void) strftime(s_str, 11, "%Y%m%d00", localtime_r(&t, &tm)); + new_s = (int32_t) atoi(s_str); + return new_s - ((int32_t) s) <= 0 ? s+1 : ((uint32_t) new_s); +} + +uint32_t ldns_soa_serial_unixtime(uint32_t s, void *data) +{ + int32_t new_s = data ? (int32_t) (intptr_t) data + : (int32_t) ldns_time(NULL); + return new_s - ((int32_t) s) <= 0 ? s+1 : ((uint32_t) new_s); +} + +void +ldns_rr_soa_increment(ldns_rr *soa) +{ + ldns_rr_soa_increment_func_data(soa, ldns_soa_serial_increment, NULL); +} + +void +ldns_rr_soa_increment_func(ldns_rr *soa, ldns_soa_serial_increment_func_t f) +{ + ldns_rr_soa_increment_func_data(soa, f, NULL); +} + +void +ldns_rr_soa_increment_func_data(ldns_rr *soa, + ldns_soa_serial_increment_func_t f, void *data) +{ + ldns_rdf *prev_soa_serial_rdf; + if ( !soa || !f || ldns_rr_get_type(soa) != LDNS_RR_TYPE_SOA + || !ldns_rr_rdf(soa, 2)) { + return; + } + prev_soa_serial_rdf = ldns_rr_set_rdf( + soa + , ldns_native2rdf_int32( + LDNS_RDF_TYPE_INT32 + , (*f)( ldns_rdf2native_int32( + ldns_rr_rdf(soa, 2)) + , data + ) + ) + , 2 + ); + LDNS_FREE(prev_soa_serial_rdf); +} + +void +ldns_rr_soa_increment_func_int(ldns_rr *soa, + ldns_soa_serial_increment_func_t f, int data) +{ + ldns_rr_soa_increment_func_data(soa, f, (void *) (intptr_t) data); +} + diff --git a/sha1.c b/sha1.c new file mode 100644 index 00000000000..5dec680a1b7 --- /dev/null +++ b/sha1.c @@ -0,0 +1,177 @@ +/* + * modified for ldns by Jelte Jansen, original taken from OpenBSD: + * + * SHA-1 in C + * By Steve Reid + * 100% Public Domain + * + * Test Vectors (from FIPS PUB 180-1) + * "abc" + * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D + * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 + * A million repetitions of "a" + * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F +*/ + +/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */ +/* #define SHA1HANDSOFF * Copies data before messing with it. */ + +#include +#include +#include + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +/* blk0() and blk() perform the initial expand. */ +/* I got the idea of expanding during the round function from SSLeay */ +#if BYTE_ORDER == LITTLE_ENDIAN +#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ + |(rol(block->l[i],8)&0x00FF00FF)) +#else +#define blk0(i) block->l[i] +#endif +#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ + ^block->l[(i+2)&15]^block->l[i&15],1)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); +#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); +#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); + +/* Hash a single 512-bit block. This is the core of the algorithm. */ + +void +ldns_sha1_transform(uint32_t state[5], const unsigned char buffer[LDNS_SHA1_BLOCK_LENGTH]) +{ + uint32_t a, b, c, d, e; + typedef union { + unsigned char c[64]; + unsigned int l[16]; + } CHAR64LONG16; + CHAR64LONG16* block; +#ifdef SHA1HANDSOFF + unsigned char workspace[LDNS_SHA1_BLOCK_LENGTH]; + + block = (CHAR64LONG16 *)workspace; + memmove(block, buffer, LDNS_SHA1_BLOCK_LENGTH); +#else + block = (CHAR64LONG16 *)buffer; +#endif + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); + R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); + + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + /* Wipe variables */ + a = b = c = d = e = 0; +} + + +/* SHA1Init - Initialize new context */ + +void +ldns_sha1_init(ldns_sha1_ctx *context) +{ + /* SHA1 initialization constants */ + context->count = 0; + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; +} + + +/* Run your data through this. */ + +void +ldns_sha1_update(ldns_sha1_ctx *context, const unsigned char *data, unsigned int len) +{ + unsigned int i; + unsigned int j; + + j = (unsigned)(uint32_t)((context->count >> 3) & 63); + context->count += (len << 3); + if ((j + len) > 63) { + memmove(&context->buffer[j], data, (i = 64 - j)); + ldns_sha1_transform(context->state, context->buffer); + for ( ; i + 63 < len; i += 64) { + ldns_sha1_transform(context->state, &data[i]); + } + j = 0; + } + else i = 0; + memmove(&context->buffer[j], &data[i], len - i); +} + + +/* Add padding and return the message digest. */ + +void +ldns_sha1_final(unsigned char digest[LDNS_SHA1_DIGEST_LENGTH], ldns_sha1_ctx *context) +{ + unsigned int i; + unsigned char finalcount[8]; + + for (i = 0; i < 8; i++) { + finalcount[i] = (unsigned char)((context->count >> + ((7 - (i & 7)) * 8)) & 255); /* Endian independent */ + } + ldns_sha1_update(context, (unsigned char *)"\200", 1); + while ((context->count & 504) != 448) { + ldns_sha1_update(context, (unsigned char *)"\0", 1); + } + ldns_sha1_update(context, finalcount, 8); /* Should cause a SHA1Transform() */ + + if (digest != NULL) + for (i = 0; i < LDNS_SHA1_DIGEST_LENGTH; i++) { + digest[i] = (unsigned char)((context->state[i >> 2] >> + ((3 - (i & 3)) * 8)) & 255); + } +#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite its own static vars */ + ldns_sha1_transform(context->state, context->buffer); +#endif +} + +unsigned char * +ldns_sha1(unsigned char *data, unsigned int data_len, unsigned char *digest) +{ + ldns_sha1_ctx ctx; + ldns_sha1_init(&ctx); + ldns_sha1_update(&ctx, data, data_len); + ldns_sha1_final(digest, &ctx); + return digest; +} diff --git a/sha2.c b/sha2.c new file mode 100644 index 00000000000..6ba4ab5cb1e --- /dev/null +++ b/sha2.c @@ -0,0 +1,982 @@ +/* + * FILE: sha2.c + * AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/ + * + * Copyright (c) 2000-2001, Aaron D. Gifford + * All rights reserved. + * + * Modified by Jelte Jansen to fit in ldns, and not clash with any + * system-defined SHA code. + * Changes: + * - Renamed (external) functions and constants to fit ldns style + * - Removed _End and _Data functions + * - Added ldns_shaX(data, len, digest) convenience functions + * - Removed prototypes of _Transform functions and made those static + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``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 CONTRIBUTOR(S) 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. + * + * $Id: sha2.c,v 1.1 2001/11/08 00:01:51 adg Exp adg $ + */ + +#include +#include /* memcpy()/memset() or bcopy()/bzero() */ +#include /* assert() */ +#include + +/* + * ASSERT NOTE: + * Some sanity checking code is included using assert(). On my FreeBSD + * system, this additional code can be removed by compiling with NDEBUG + * defined. Check your own systems manpage on assert() to see how to + * compile WITHOUT the sanity checking code on your system. + * + * UNROLLED TRANSFORM LOOP NOTE: + * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform + * loop version for the hash transform rounds (defined using macros + * later in this file). Either define on the command line, for example: + * + * cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c + * + * or define below: + * + * #define SHA2_UNROLL_TRANSFORM + * + */ + + +/*** SHA-256/384/512 Machine Architecture Definitions *****************/ +/* + * BYTE_ORDER NOTE: + * + * Please make sure that your system defines BYTE_ORDER. If your + * architecture is little-endian, make sure it also defines + * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are + * equivilent. + * + * If your system does not define the above, then you can do so by + * hand like this: + * + * #define LITTLE_ENDIAN 1234 + * #define BIG_ENDIAN 4321 + * + * And for little-endian machines, add: + * + * #define BYTE_ORDER LITTLE_ENDIAN + * + * Or for big-endian machines: + * + * #define BYTE_ORDER BIG_ENDIAN + * + * The FreeBSD machine this was written on defines BYTE_ORDER + * appropriately by including (which in turn includes + * where the appropriate definitions are actually + * made). + */ +#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN) +#error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN +#endif + +typedef uint8_t sha2_byte; /* Exactly 1 byte */ +typedef uint32_t sha2_word32; /* Exactly 4 bytes */ +#ifdef S_SPLINT_S +typedef unsigned long long sha2_word64; /* lint 8 bytes */ +#else +typedef uint64_t sha2_word64; /* Exactly 8 bytes */ +#endif + +/*** SHA-256/384/512 Various Length Definitions ***********************/ +/* NOTE: Most of these are in sha2.h */ +#define ldns_sha256_SHORT_BLOCK_LENGTH (LDNS_SHA256_BLOCK_LENGTH - 8) +#define ldns_sha384_SHORT_BLOCK_LENGTH (LDNS_SHA384_BLOCK_LENGTH - 16) +#define ldns_sha512_SHORT_BLOCK_LENGTH (LDNS_SHA512_BLOCK_LENGTH - 16) + + +/*** ENDIAN REVERSAL MACROS *******************************************/ +#if BYTE_ORDER == LITTLE_ENDIAN +#define REVERSE32(w,x) { \ + sha2_word32 tmp = (w); \ + tmp = (tmp >> 16) | (tmp << 16); \ + (x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \ +} +#ifndef S_SPLINT_S +#define REVERSE64(w,x) { \ + sha2_word64 tmp = (w); \ + tmp = (tmp >> 32) | (tmp << 32); \ + tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \ + ((tmp & 0x00ff00ff00ff00ffULL) << 8); \ + (x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \ + ((tmp & 0x0000ffff0000ffffULL) << 16); \ +} +#else /* splint */ +#define REVERSE64(w,x) /* splint */ +#endif /* splint */ +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ + +/* + * Macro for incrementally adding the unsigned 64-bit integer n to the + * unsigned 128-bit integer (represented using a two-element array of + * 64-bit words): + */ +#define ADDINC128(w,n) { \ + (w)[0] += (sha2_word64)(n); \ + if ((w)[0] < (n)) { \ + (w)[1]++; \ + } \ +} +#ifdef S_SPLINT_S +#undef ADDINC128 +#define ADDINC128(w,n) /* splint */ +#endif + +/* + * Macros for copying blocks of memory and for zeroing out ranges + * of memory. Using these macros makes it easy to switch from + * using memset()/memcpy() and using bzero()/bcopy(). + * + * Please define either SHA2_USE_MEMSET_MEMCPY or define + * SHA2_USE_BZERO_BCOPY depending on which function set you + * choose to use: + */ +#if !defined(SHA2_USE_MEMSET_MEMCPY) && !defined(SHA2_USE_BZERO_BCOPY) +/* Default to memset()/memcpy() if no option is specified */ +#define SHA2_USE_MEMSET_MEMCPY 1 +#endif +#if defined(SHA2_USE_MEMSET_MEMCPY) && defined(SHA2_USE_BZERO_BCOPY) +/* Abort with an error if BOTH options are defined */ +#error Define either SHA2_USE_MEMSET_MEMCPY or SHA2_USE_BZERO_BCOPY, not both! +#endif + +#ifdef SHA2_USE_MEMSET_MEMCPY +#define MEMSET_BZERO(p,l) memset((p), 0, (l)) +#define MEMCPY_BCOPY(d,s,l) memcpy((d), (s), (l)) +#endif +#ifdef SHA2_USE_BZERO_BCOPY +#define MEMSET_BZERO(p,l) bzero((p), (l)) +#define MEMCPY_BCOPY(d,s,l) bcopy((s), (d), (l)) +#endif + + +/*** THE SIX LOGICAL FUNCTIONS ****************************************/ +/* + * Bit shifting and rotation (used by the six SHA-XYZ logical functions: + * + * NOTE: The naming of R and S appears backwards here (R is a SHIFT and + * S is a ROTATION) because the SHA-256/384/512 description document + * (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this + * same "backwards" definition. + */ +/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */ +#define R(b,x) ((x) >> (b)) +/* 32-bit Rotate-right (used in SHA-256): */ +#define S32(b,x) (((x) >> (b)) | ((x) << (32 - (b)))) +/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */ +#define S64(b,x) (((x) >> (b)) | ((x) << (64 - (b)))) + +/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */ +#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) +#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) + +/* Four of six logical functions used in SHA-256: */ +#define Sigma0_256(x) (S32(2, (x)) ^ S32(13, (x)) ^ S32(22, (x))) +#define Sigma1_256(x) (S32(6, (x)) ^ S32(11, (x)) ^ S32(25, (x))) +#define sigma0_256(x) (S32(7, (x)) ^ S32(18, (x)) ^ R(3 , (x))) +#define sigma1_256(x) (S32(17, (x)) ^ S32(19, (x)) ^ R(10, (x))) + +/* Four of six logical functions used in SHA-384 and SHA-512: */ +#define Sigma0_512(x) (S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x))) +#define Sigma1_512(x) (S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x))) +#define sigma0_512(x) (S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7, (x))) +#define sigma1_512(x) (S64(19, (x)) ^ S64(61, (x)) ^ R( 6, (x))) + +/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/ +/* Hash constant words K for SHA-256: */ +static const sha2_word32 K256[64] = { + 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, + 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, + 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, + 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, + 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, + 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, + 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, + 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, + 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, + 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, + 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, + 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, + 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, + 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, + 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, + 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL +}; + +/* initial hash value H for SHA-256: */ +static const sha2_word32 ldns_sha256_initial_hash_value[8] = { + 0x6a09e667UL, + 0xbb67ae85UL, + 0x3c6ef372UL, + 0xa54ff53aUL, + 0x510e527fUL, + 0x9b05688cUL, + 0x1f83d9abUL, + 0x5be0cd19UL +}; + +/* Hash constant words K for SHA-384 and SHA-512: */ +static const sha2_word64 K512[80] = { + 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, + 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, + 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, + 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, + 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, + 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, + 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, + 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, + 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, + 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, + 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, + 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, + 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, + 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, + 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, + 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, + 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, + 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, + 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, + 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, + 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, + 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, + 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, + 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, + 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, + 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, + 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, + 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, + 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, + 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, + 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, + 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, + 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, + 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL +}; + +/* initial hash value H for SHA-384 */ +static const sha2_word64 sha384_initial_hash_value[8] = { + 0xcbbb9d5dc1059ed8ULL, + 0x629a292a367cd507ULL, + 0x9159015a3070dd17ULL, + 0x152fecd8f70e5939ULL, + 0x67332667ffc00b31ULL, + 0x8eb44a8768581511ULL, + 0xdb0c2e0d64f98fa7ULL, + 0x47b5481dbefa4fa4ULL +}; + +/* initial hash value H for SHA-512 */ +static const sha2_word64 sha512_initial_hash_value[8] = { + 0x6a09e667f3bcc908ULL, + 0xbb67ae8584caa73bULL, + 0x3c6ef372fe94f82bULL, + 0xa54ff53a5f1d36f1ULL, + 0x510e527fade682d1ULL, + 0x9b05688c2b3e6c1fULL, + 0x1f83d9abfb41bd6bULL, + 0x5be0cd19137e2179ULL +}; + +/*** SHA-256: *********************************************************/ +void ldns_sha256_init(ldns_sha256_CTX* context) { + if (context == (ldns_sha256_CTX*)0) { + return; + } + MEMCPY_BCOPY(context->state, ldns_sha256_initial_hash_value, LDNS_SHA256_DIGEST_LENGTH); + MEMSET_BZERO(context->buffer, LDNS_SHA256_BLOCK_LENGTH); + context->bitcount = 0; +} + +#ifdef SHA2_UNROLL_TRANSFORM + +/* Unrolled SHA-256 round macros: */ + +#if BYTE_ORDER == LITTLE_ENDIAN + +#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \ + REVERSE32(*data++, W256[j]); \ + T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \ + K256[j] + W256[j]; \ + (d) += T1; \ + (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ + j++ + + +#else /* BYTE_ORDER == LITTLE_ENDIAN */ + +#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \ + T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \ + K256[j] + (W256[j] = *data++); \ + (d) += T1; \ + (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ + j++ + +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ + +#define ROUND256(a,b,c,d,e,f,g,h) \ + s0 = W256[(j+1)&0x0f]; \ + s0 = sigma0_256(s0); \ + s1 = W256[(j+14)&0x0f]; \ + s1 = sigma1_256(s1); \ + T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \ + (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \ + (d) += T1; \ + (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ + j++ + +static void ldns_sha256_Transform(ldns_sha256_CTX* context, + const sha2_word32* data) { + sha2_word32 a, b, c, d, e, f, g, h, s0, s1; + sha2_word32 T1, *W256; + int j; + + W256 = (sha2_word32*)context->buffer; + + /* initialize registers with the prev. intermediate value */ + a = context->state[0]; + b = context->state[1]; + c = context->state[2]; + d = context->state[3]; + e = context->state[4]; + f = context->state[5]; + g = context->state[6]; + h = context->state[7]; + + j = 0; + do { + /* Rounds 0 to 15 (unrolled): */ + ROUND256_0_TO_15(a,b,c,d,e,f,g,h); + ROUND256_0_TO_15(h,a,b,c,d,e,f,g); + ROUND256_0_TO_15(g,h,a,b,c,d,e,f); + ROUND256_0_TO_15(f,g,h,a,b,c,d,e); + ROUND256_0_TO_15(e,f,g,h,a,b,c,d); + ROUND256_0_TO_15(d,e,f,g,h,a,b,c); + ROUND256_0_TO_15(c,d,e,f,g,h,a,b); + ROUND256_0_TO_15(b,c,d,e,f,g,h,a); + } while (j < 16); + + /* Now for the remaining rounds to 64: */ + do { + ROUND256(a,b,c,d,e,f,g,h); + ROUND256(h,a,b,c,d,e,f,g); + ROUND256(g,h,a,b,c,d,e,f); + ROUND256(f,g,h,a,b,c,d,e); + ROUND256(e,f,g,h,a,b,c,d); + ROUND256(d,e,f,g,h,a,b,c); + ROUND256(c,d,e,f,g,h,a,b); + ROUND256(b,c,d,e,f,g,h,a); + } while (j < 64); + + /* Compute the current intermediate hash value */ + context->state[0] += a; + context->state[1] += b; + context->state[2] += c; + context->state[3] += d; + context->state[4] += e; + context->state[5] += f; + context->state[6] += g; + context->state[7] += h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = 0; +} + +#else /* SHA2_UNROLL_TRANSFORM */ + +static void ldns_sha256_Transform(ldns_sha256_CTX* context, + const sha2_word32* data) { + sha2_word32 a, b, c, d, e, f, g, h, s0, s1; + sha2_word32 T1, T2, *W256; + int j; + + W256 = (sha2_word32*)context->buffer; + + /* initialize registers with the prev. intermediate value */ + a = context->state[0]; + b = context->state[1]; + c = context->state[2]; + d = context->state[3]; + e = context->state[4]; + f = context->state[5]; + g = context->state[6]; + h = context->state[7]; + + j = 0; + do { +#if BYTE_ORDER == LITTLE_ENDIAN + /* Copy data while converting to host byte order */ + REVERSE32(*data++,W256[j]); + /* Apply the SHA-256 compression function to update a..h */ + T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j]; +#else /* BYTE_ORDER == LITTLE_ENDIAN */ + /* Apply the SHA-256 compression function to update a..h with copy */ + T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++); +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ + T2 = Sigma0_256(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 16); + + do { + /* Part of the message block expansion: */ + s0 = W256[(j+1)&0x0f]; + s0 = sigma0_256(s0); + s1 = W256[(j+14)&0x0f]; + s1 = sigma1_256(s1); + + /* Apply the SHA-256 compression function to update a..h */ + T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + + (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); + T2 = Sigma0_256(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 64); + + /* Compute the current intermediate hash value */ + context->state[0] += a; + context->state[1] += b; + context->state[2] += c; + context->state[3] += d; + context->state[4] += e; + context->state[5] += f; + context->state[6] += g; + context->state[7] += h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = T2 = 0; +} + +#endif /* SHA2_UNROLL_TRANSFORM */ + +void ldns_sha256_update(ldns_sha256_CTX* context, const sha2_byte *data, size_t len) { + size_t freespace, usedspace; + + if (len == 0) { + /* Calling with no data is valid - we do nothing */ + return; + } + + /* Sanity check: */ + assert(context != (ldns_sha256_CTX*)0 && data != (sha2_byte*)0); + + usedspace = (context->bitcount >> 3) % LDNS_SHA256_BLOCK_LENGTH; + if (usedspace > 0) { + /* Calculate how much free space is available in the buffer */ + freespace = LDNS_SHA256_BLOCK_LENGTH - usedspace; + + if (len >= freespace) { + /* Fill the buffer completely and process it */ + MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace); + context->bitcount += freespace << 3; + len -= freespace; + data += freespace; + ldns_sha256_Transform(context, (sha2_word32*)context->buffer); + } else { + /* The buffer is not yet full */ + MEMCPY_BCOPY(&context->buffer[usedspace], data, len); + context->bitcount += len << 3; + /* Clean up: */ + usedspace = freespace = 0; + return; + } + } + while (len >= LDNS_SHA256_BLOCK_LENGTH) { + /* Process as many complete blocks as we can */ + ldns_sha256_Transform(context, (sha2_word32*)data); + context->bitcount += LDNS_SHA256_BLOCK_LENGTH << 3; + len -= LDNS_SHA256_BLOCK_LENGTH; + data += LDNS_SHA256_BLOCK_LENGTH; + } + if (len > 0) { + /* There's left-overs, so save 'em */ + MEMCPY_BCOPY(context->buffer, data, len); + context->bitcount += len << 3; + } + /* Clean up: */ + usedspace = freespace = 0; +} + +void ldns_sha256_final(sha2_byte digest[], ldns_sha256_CTX* context) { + sha2_word32 *d = (sha2_word32*)digest; + size_t usedspace; + + /* Sanity check: */ + assert(context != (ldns_sha256_CTX*)0); + + /* If no digest buffer is passed, we don't bother doing this: */ + if (digest != (sha2_byte*)0) { + usedspace = (context->bitcount >> 3) % LDNS_SHA256_BLOCK_LENGTH; +#if BYTE_ORDER == LITTLE_ENDIAN + /* Convert FROM host byte order */ + REVERSE64(context->bitcount,context->bitcount); +#endif + if (usedspace > 0) { + /* Begin padding with a 1 bit: */ + context->buffer[usedspace++] = 0x80; + + if (usedspace <= ldns_sha256_SHORT_BLOCK_LENGTH) { + /* Set-up for the last transform: */ + MEMSET_BZERO(&context->buffer[usedspace], ldns_sha256_SHORT_BLOCK_LENGTH - usedspace); + } else { + if (usedspace < LDNS_SHA256_BLOCK_LENGTH) { + MEMSET_BZERO(&context->buffer[usedspace], LDNS_SHA256_BLOCK_LENGTH - usedspace); + } + /* Do second-to-last transform: */ + ldns_sha256_Transform(context, (sha2_word32*)context->buffer); + + /* And set-up for the last transform: */ + MEMSET_BZERO(context->buffer, ldns_sha256_SHORT_BLOCK_LENGTH); + } + } else { + /* Set-up for the last transform: */ + MEMSET_BZERO(context->buffer, ldns_sha256_SHORT_BLOCK_LENGTH); + + /* Begin padding with a 1 bit: */ + *context->buffer = 0x80; + } + /* Set the bit count: */ + *(sha2_word64*)&context->buffer[ldns_sha256_SHORT_BLOCK_LENGTH] = context->bitcount; + + /* final transform: */ + ldns_sha256_Transform(context, (sha2_word32*)context->buffer); + +#if BYTE_ORDER == LITTLE_ENDIAN + { + /* Convert TO host byte order */ + int j; + for (j = 0; j < 8; j++) { + REVERSE32(context->state[j],context->state[j]); + *d++ = context->state[j]; + } + } +#else + MEMCPY_BCOPY(d, context->state, LDNS_SHA256_DIGEST_LENGTH); +#endif + } + + /* Clean up state data: */ + MEMSET_BZERO(context, sizeof(ldns_sha256_CTX)); + usedspace = 0; +} + +unsigned char * +ldns_sha256(unsigned char *data, unsigned int data_len, unsigned char *digest) +{ + ldns_sha256_CTX ctx; + ldns_sha256_init(&ctx); + ldns_sha256_update(&ctx, data, data_len); + ldns_sha256_final(digest, &ctx); + return digest; +} + +/*** SHA-512: *********************************************************/ +void ldns_sha512_init(ldns_sha512_CTX* context) { + if (context == (ldns_sha512_CTX*)0) { + return; + } + MEMCPY_BCOPY(context->state, sha512_initial_hash_value, LDNS_SHA512_DIGEST_LENGTH); + MEMSET_BZERO(context->buffer, LDNS_SHA512_BLOCK_LENGTH); + context->bitcount[0] = context->bitcount[1] = 0; +} + +#ifdef SHA2_UNROLL_TRANSFORM + +/* Unrolled SHA-512 round macros: */ +#if BYTE_ORDER == LITTLE_ENDIAN + +#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \ + REVERSE64(*data++, W512[j]); \ + T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \ + K512[j] + W512[j]; \ + (d) += T1, \ + (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)), \ + j++ + + +#else /* BYTE_ORDER == LITTLE_ENDIAN */ + +#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \ + T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \ + K512[j] + (W512[j] = *data++); \ + (d) += T1; \ + (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \ + j++ + +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ + +#define ROUND512(a,b,c,d,e,f,g,h) \ + s0 = W512[(j+1)&0x0f]; \ + s0 = sigma0_512(s0); \ + s1 = W512[(j+14)&0x0f]; \ + s1 = sigma1_512(s1); \ + T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + \ + (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \ + (d) += T1; \ + (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \ + j++ + +static void ldns_sha512_Transform(ldns_sha512_CTX* context, + const sha2_word64* data) { + sha2_word64 a, b, c, d, e, f, g, h, s0, s1; + sha2_word64 T1, *W512 = (sha2_word64*)context->buffer; + int j; + + /* initialize registers with the prev. intermediate value */ + a = context->state[0]; + b = context->state[1]; + c = context->state[2]; + d = context->state[3]; + e = context->state[4]; + f = context->state[5]; + g = context->state[6]; + h = context->state[7]; + + j = 0; + do { + ROUND512_0_TO_15(a,b,c,d,e,f,g,h); + ROUND512_0_TO_15(h,a,b,c,d,e,f,g); + ROUND512_0_TO_15(g,h,a,b,c,d,e,f); + ROUND512_0_TO_15(f,g,h,a,b,c,d,e); + ROUND512_0_TO_15(e,f,g,h,a,b,c,d); + ROUND512_0_TO_15(d,e,f,g,h,a,b,c); + ROUND512_0_TO_15(c,d,e,f,g,h,a,b); + ROUND512_0_TO_15(b,c,d,e,f,g,h,a); + } while (j < 16); + + /* Now for the remaining rounds up to 79: */ + do { + ROUND512(a,b,c,d,e,f,g,h); + ROUND512(h,a,b,c,d,e,f,g); + ROUND512(g,h,a,b,c,d,e,f); + ROUND512(f,g,h,a,b,c,d,e); + ROUND512(e,f,g,h,a,b,c,d); + ROUND512(d,e,f,g,h,a,b,c); + ROUND512(c,d,e,f,g,h,a,b); + ROUND512(b,c,d,e,f,g,h,a); + } while (j < 80); + + /* Compute the current intermediate hash value */ + context->state[0] += a; + context->state[1] += b; + context->state[2] += c; + context->state[3] += d; + context->state[4] += e; + context->state[5] += f; + context->state[6] += g; + context->state[7] += h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = 0; +} + +#else /* SHA2_UNROLL_TRANSFORM */ + +static void ldns_sha512_Transform(ldns_sha512_CTX* context, + const sha2_word64* data) { + sha2_word64 a, b, c, d, e, f, g, h, s0, s1; + sha2_word64 T1, T2, *W512 = (sha2_word64*)context->buffer; + int j; + + /* initialize registers with the prev. intermediate value */ + a = context->state[0]; + b = context->state[1]; + c = context->state[2]; + d = context->state[3]; + e = context->state[4]; + f = context->state[5]; + g = context->state[6]; + h = context->state[7]; + + j = 0; + do { +#if BYTE_ORDER == LITTLE_ENDIAN + /* Convert TO host byte order */ + REVERSE64(*data++, W512[j]); + /* Apply the SHA-512 compression function to update a..h */ + T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j]; +#else /* BYTE_ORDER == LITTLE_ENDIAN */ + /* Apply the SHA-512 compression function to update a..h with copy */ + T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = *data++); +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ + T2 = Sigma0_512(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 16); + + do { + /* Part of the message block expansion: */ + s0 = W512[(j+1)&0x0f]; + s0 = sigma0_512(s0); + s1 = W512[(j+14)&0x0f]; + s1 = sigma1_512(s1); + + /* Apply the SHA-512 compression function to update a..h */ + T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + + (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); + T2 = Sigma0_512(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 80); + + /* Compute the current intermediate hash value */ + context->state[0] += a; + context->state[1] += b; + context->state[2] += c; + context->state[3] += d; + context->state[4] += e; + context->state[5] += f; + context->state[6] += g; + context->state[7] += h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = T2 = 0; +} + +#endif /* SHA2_UNROLL_TRANSFORM */ + +void ldns_sha512_update(ldns_sha512_CTX* context, const sha2_byte *data, size_t len) { + size_t freespace, usedspace; + + if (len == 0) { + /* Calling with no data is valid - we do nothing */ + return; + } + + /* Sanity check: */ + assert(context != (ldns_sha512_CTX*)0 && data != (sha2_byte*)0); + + usedspace = (context->bitcount[0] >> 3) % LDNS_SHA512_BLOCK_LENGTH; + if (usedspace > 0) { + /* Calculate how much free space is available in the buffer */ + freespace = LDNS_SHA512_BLOCK_LENGTH - usedspace; + + if (len >= freespace) { + /* Fill the buffer completely and process it */ + MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace); + ADDINC128(context->bitcount, freespace << 3); + len -= freespace; + data += freespace; + ldns_sha512_Transform(context, (sha2_word64*)context->buffer); + } else { + /* The buffer is not yet full */ + MEMCPY_BCOPY(&context->buffer[usedspace], data, len); + ADDINC128(context->bitcount, len << 3); + /* Clean up: */ + usedspace = freespace = 0; + return; + } + } + while (len >= LDNS_SHA512_BLOCK_LENGTH) { + /* Process as many complete blocks as we can */ + ldns_sha512_Transform(context, (sha2_word64*)data); + ADDINC128(context->bitcount, LDNS_SHA512_BLOCK_LENGTH << 3); + len -= LDNS_SHA512_BLOCK_LENGTH; + data += LDNS_SHA512_BLOCK_LENGTH; + } + if (len > 0) { + /* There's left-overs, so save 'em */ + MEMCPY_BCOPY(context->buffer, data, len); + ADDINC128(context->bitcount, len << 3); + } + /* Clean up: */ + usedspace = freespace = 0; +} + +static void ldns_sha512_Last(ldns_sha512_CTX* context) { + size_t usedspace; + + usedspace = (context->bitcount[0] >> 3) % LDNS_SHA512_BLOCK_LENGTH; +#if BYTE_ORDER == LITTLE_ENDIAN + /* Convert FROM host byte order */ + REVERSE64(context->bitcount[0],context->bitcount[0]); + REVERSE64(context->bitcount[1],context->bitcount[1]); +#endif + if (usedspace > 0) { + /* Begin padding with a 1 bit: */ + context->buffer[usedspace++] = 0x80; + + if (usedspace <= ldns_sha512_SHORT_BLOCK_LENGTH) { + /* Set-up for the last transform: */ + MEMSET_BZERO(&context->buffer[usedspace], ldns_sha512_SHORT_BLOCK_LENGTH - usedspace); + } else { + if (usedspace < LDNS_SHA512_BLOCK_LENGTH) { + MEMSET_BZERO(&context->buffer[usedspace], LDNS_SHA512_BLOCK_LENGTH - usedspace); + } + /* Do second-to-last transform: */ + ldns_sha512_Transform(context, (sha2_word64*)context->buffer); + + /* And set-up for the last transform: */ + MEMSET_BZERO(context->buffer, LDNS_SHA512_BLOCK_LENGTH - 2); + } + } else { + /* Prepare for final transform: */ + MEMSET_BZERO(context->buffer, ldns_sha512_SHORT_BLOCK_LENGTH); + + /* Begin padding with a 1 bit: */ + *context->buffer = 0x80; + } + /* Store the length of input data (in bits): */ + *(sha2_word64*)&context->buffer[ldns_sha512_SHORT_BLOCK_LENGTH] = context->bitcount[1]; + *(sha2_word64*)&context->buffer[ldns_sha512_SHORT_BLOCK_LENGTH+8] = context->bitcount[0]; + + /* final transform: */ + ldns_sha512_Transform(context, (sha2_word64*)context->buffer); +} + +void ldns_sha512_final(sha2_byte digest[], ldns_sha512_CTX* context) { + sha2_word64 *d = (sha2_word64*)digest; + + /* Sanity check: */ + assert(context != (ldns_sha512_CTX*)0); + + /* If no digest buffer is passed, we don't bother doing this: */ + if (digest != (sha2_byte*)0) { + ldns_sha512_Last(context); + + /* Save the hash data for output: */ +#if BYTE_ORDER == LITTLE_ENDIAN + { + /* Convert TO host byte order */ + int j; + for (j = 0; j < 8; j++) { + REVERSE64(context->state[j],context->state[j]); + *d++ = context->state[j]; + } + } +#else + MEMCPY_BCOPY(d, context->state, LDNS_SHA512_DIGEST_LENGTH); +#endif + } + + /* Zero out state data */ + MEMSET_BZERO(context, sizeof(ldns_sha512_CTX)); +} + +unsigned char * +ldns_sha512(unsigned char *data, unsigned int data_len, unsigned char *digest) +{ + ldns_sha512_CTX ctx; + ldns_sha512_init(&ctx); + ldns_sha512_update(&ctx, data, data_len); + ldns_sha512_final(digest, &ctx); + return digest; +} + +/*** SHA-384: *********************************************************/ +void ldns_sha384_init(ldns_sha384_CTX* context) { + if (context == (ldns_sha384_CTX*)0) { + return; + } + MEMCPY_BCOPY(context->state, sha384_initial_hash_value, LDNS_SHA512_DIGEST_LENGTH); + MEMSET_BZERO(context->buffer, LDNS_SHA384_BLOCK_LENGTH); + context->bitcount[0] = context->bitcount[1] = 0; +} + +void ldns_sha384_update(ldns_sha384_CTX* context, const sha2_byte* data, size_t len) { + ldns_sha512_update((ldns_sha512_CTX*)context, data, len); +} + +void ldns_sha384_final(sha2_byte digest[], ldns_sha384_CTX* context) { + sha2_word64 *d = (sha2_word64*)digest; + + /* Sanity check: */ + assert(context != (ldns_sha384_CTX*)0); + + /* If no digest buffer is passed, we don't bother doing this: */ + if (digest != (sha2_byte*)0) { + ldns_sha512_Last((ldns_sha512_CTX*)context); + + /* Save the hash data for output: */ +#if BYTE_ORDER == LITTLE_ENDIAN + { + /* Convert TO host byte order */ + int j; + for (j = 0; j < 6; j++) { + REVERSE64(context->state[j],context->state[j]); + *d++ = context->state[j]; + } + } +#else + MEMCPY_BCOPY(d, context->state, LDNS_SHA384_DIGEST_LENGTH); +#endif + } + + /* Zero out state data */ + MEMSET_BZERO(context, sizeof(ldns_sha384_CTX)); +} + +unsigned char * +ldns_sha384(unsigned char *data, unsigned int data_len, unsigned char *digest) +{ + ldns_sha384_CTX ctx; + ldns_sha384_init(&ctx); + ldns_sha384_update(&ctx, data, data_len); + ldns_sha384_final(digest, &ctx); + return digest; +} diff --git a/str2host.c b/str2host.c new file mode 100644 index 00000000000..2783f0805a4 --- /dev/null +++ b/str2host.c @@ -0,0 +1,1320 @@ +/* + * str2host.c + * + * conversion routines from the presentation format + * to the host format + * + * a Net::DNS like library for C + * + * (c) NLnet Labs, 2004-2006 + * + * See the file LICENSE for the license + */ +#include + +#include + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#include + +#include +#ifdef HAVE_NETDB_H +#include +#endif + +#include +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +ldns_status +ldns_str2rdf_int16(ldns_rdf **rd, const char *shortstr) +{ + char *end = NULL; + uint16_t *r; + r = LDNS_MALLOC(uint16_t); + if(!r) return LDNS_STATUS_MEM_ERR; + + *r = htons((uint16_t)strtol((char *)shortstr, &end, 10)); + + if(*end != 0) { + LDNS_FREE(r); + return LDNS_STATUS_INVALID_INT; + } else { + *rd = ldns_rdf_new_frm_data( + LDNS_RDF_TYPE_INT16, sizeof(uint16_t), r); + LDNS_FREE(r); + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; + } +} + +ldns_status +ldns_str2rdf_time(ldns_rdf **rd, const char *time) +{ + /* convert a time YYYYDDMMHHMMSS to wireformat */ + uint16_t *r = NULL; + struct tm tm; + uint32_t l; + char *end; + + /* Try to scan the time... */ + r = (uint16_t*)LDNS_MALLOC(uint32_t); + if(!r) return LDNS_STATUS_MEM_ERR; + + memset(&tm, 0, sizeof(tm)); + + if (strlen(time) == 14 && + sscanf(time, "%4d%2d%2d%2d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) == 6 + ) { + tm.tm_year -= 1900; + tm.tm_mon--; + /* Check values */ + if (tm.tm_year < 70) { + goto bad_format; + } + if (tm.tm_mon < 0 || tm.tm_mon > 11) { + goto bad_format; + } + if (tm.tm_mday < 1 || tm.tm_mday > 31) { + goto bad_format; + } + + if (tm.tm_hour < 0 || tm.tm_hour > 23) { + goto bad_format; + } + + if (tm.tm_min < 0 || tm.tm_min > 59) { + goto bad_format; + } + + if (tm.tm_sec < 0 || tm.tm_sec > 59) { + goto bad_format; + } + + l = htonl(mktime_from_utc(&tm)); + memcpy(r, &l, sizeof(uint32_t)); + *rd = ldns_rdf_new_frm_data( + LDNS_RDF_TYPE_TIME, sizeof(uint32_t), r); + LDNS_FREE(r); + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; + } else { + /* handle it as 32 bits timestamp */ + l = htonl((uint32_t)strtol((char*)time, &end, 10)); + if(*end != 0) { + LDNS_FREE(r); + return LDNS_STATUS_ERR; + } else { + memcpy(r, &l, sizeof(uint32_t)); + *rd = ldns_rdf_new_frm_data( + LDNS_RDF_TYPE_INT32, sizeof(uint32_t), r); + LDNS_FREE(r); + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; + } + } + + bad_format: + LDNS_FREE(r); + return LDNS_STATUS_INVALID_TIME; +} + +ldns_status +ldns_str2rdf_nsec3_salt(ldns_rdf **rd, const char *salt_str) +{ + uint8_t salt_length; + int c; + int salt_length_str; + + uint8_t *salt; + uint8_t *data; + if(rd == NULL) { + return LDNS_STATUS_NULL; + } + + salt_length_str = (int)strlen(salt_str); + if (salt_length_str == 1 && salt_str[0] == '-') { + salt_length_str = 0; + } else if (salt_length_str % 2 != 0) { + return LDNS_STATUS_INVALID_HEX; + } + if (salt_length_str > 512) { + return LDNS_STATUS_INVALID_HEX; + } + + salt = LDNS_XMALLOC(uint8_t, salt_length_str / 2); + if(!salt) { + return LDNS_STATUS_MEM_ERR; + } + for (c = 0; c < salt_length_str; c += 2) { + if (isxdigit((int) salt_str[c]) && isxdigit((int) salt_str[c+1])) { + salt[c/2] = (uint8_t) ldns_hexdigit_to_int(salt_str[c]) * 16 + + ldns_hexdigit_to_int(salt_str[c+1]); + } else { + LDNS_FREE(salt); + return LDNS_STATUS_INVALID_HEX; + } + } + salt_length = (uint8_t) (salt_length_str / 2); + + data = LDNS_XMALLOC(uint8_t, 1 + salt_length); + if(!data) { + LDNS_FREE(salt); + return LDNS_STATUS_MEM_ERR; + } + data[0] = salt_length; + memcpy(&data[1], salt, salt_length); + *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_NSEC3_SALT, 1 + salt_length, data); + LDNS_FREE(data); + LDNS_FREE(salt); + + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; +} + +ldns_status +ldns_str2rdf_period(ldns_rdf **rd,const char *period) +{ + uint32_t p; + const char *end; + + /* Allocate required space... */ + p = ldns_str2period(period, &end); + + if (*end != 0) { + return LDNS_STATUS_ERR; + } else { + p = (uint32_t) htonl(p); + *rd = ldns_rdf_new_frm_data( + LDNS_RDF_TYPE_PERIOD, sizeof(uint32_t), &p); + } + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; +} + +ldns_status +ldns_str2rdf_int32(ldns_rdf **rd, const char *longstr) +{ + char *end; + uint16_t *r = NULL; + uint32_t l; + + r = (uint16_t*)LDNS_MALLOC(uint32_t); + if(!r) return LDNS_STATUS_MEM_ERR; + errno = 0; /* must set to zero before call, + note race condition on errno */ + if(*longstr == '-') + l = htonl((uint32_t)strtol((char*)longstr, &end, 10)); + else l = htonl((uint32_t)strtoul((char*)longstr, &end, 10)); + + if(*end != 0) { + LDNS_FREE(r); + return LDNS_STATUS_ERR; + } else { + if (errno == ERANGE) { + LDNS_FREE(r); + return LDNS_STATUS_SYNTAX_INTEGER_OVERFLOW; + } + memcpy(r, &l, sizeof(uint32_t)); + *rd = ldns_rdf_new_frm_data( + LDNS_RDF_TYPE_INT32, sizeof(uint32_t), r); + LDNS_FREE(r); + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; + } +} + +ldns_status +ldns_str2rdf_int8(ldns_rdf **rd, const char *bytestr) +{ + char *end; + uint8_t *r = NULL; + + r = LDNS_MALLOC(uint8_t); + if(!r) return LDNS_STATUS_MEM_ERR; + + *r = (uint8_t)strtol((char*)bytestr, &end, 10); + + if(*end != 0) { + LDNS_FREE(r); + return LDNS_STATUS_ERR; + } else { + *rd = ldns_rdf_new_frm_data( + LDNS_RDF_TYPE_INT8, sizeof(uint8_t), r); + LDNS_FREE(r); + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; + } +} + + +/* + * Checks whether the escaped value at **s is an octal value or + * a 'normally' escaped character (and not eos) + * + * The string pointer at *s is increased by either 0 (on error), 1 (on + * normal escapes), or 3 (on octals) + * + * Returns the number of bytes read from the escaped string, or + * 0 on error + */ +static int +parse_escape(uint8_t *s, uint8_t *q) { + uint16_t val; + if (strlen((char *)s) > 3 && + isdigit((int) s[1]) && + isdigit((int) s[2]) && + isdigit((int) s[3])) { + /* cast this so it fits */ + val = (uint16_t) ldns_hexdigit_to_int((char) s[1]) * 100 + + ldns_hexdigit_to_int((char) s[2]) * 10 + + ldns_hexdigit_to_int((char) s[3]); + if (val > 255) { + /* outside range */ + return 0; + } + *q = (uint8_t) val; + return 3; + } else { + s++; + if (*s == '\0' || isdigit((int) *s)) { + /* apparently the string terminator + * or a digit has been escaped... + */ + return 0; + } + *q = *s; + return 1; + } +} + +/* + * No special care is taken, all dots are translated into + * label seperators. + * Could be made more efficient....we do 3 memcpy's in total... + */ +ldns_status +ldns_str2rdf_dname(ldns_rdf **d, const char *str) +{ + size_t len; + + int esc; + uint8_t *s, *q, *pq, label_len; + uint8_t buf[LDNS_MAX_DOMAINLEN + 1]; + *d = NULL; + + len = strlen((char*)str); + /* octet representation can make strings a lot longer than actual length */ + if (len > LDNS_MAX_DOMAINLEN * 4) { + return LDNS_STATUS_DOMAINNAME_OVERFLOW; + } + if (0 == len) { + return LDNS_STATUS_DOMAINNAME_UNDERFLOW; + } + + /* root label */ + if (1 == len && *str == '.') { + *d = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, 1, "\0"); + return LDNS_STATUS_OK; + } + + /* get on with the rest */ + + /* s is on the current character in the string + * pq points to where the labellength is going to go + * label_len keeps track of the current label's length + * q builds the dname inside the buf array + */ + len = 0; + q = buf+1; + pq = buf; + label_len = 0; + for (s = (uint8_t *)str; *s; s++, q++) { + if (q > buf + LDNS_MAX_DOMAINLEN) { + return LDNS_STATUS_DOMAINNAME_OVERFLOW; + } + *q = 0; + switch (*s) { + case '.': + if (label_len > LDNS_MAX_LABELLEN) { + return LDNS_STATUS_LABEL_OVERFLOW; + } + if (label_len == 0) { + return LDNS_STATUS_EMPTY_LABEL; + } + len += label_len + 1; + *pq = label_len; + label_len = 0; + pq = q; + break; + case '\\': + /* octet value or literal char */ + esc = parse_escape(s, q); + if (esc > 0) { + s += esc; + label_len++; + } else { + return LDNS_STATUS_SYNTAX_BAD_ESCAPE; + } + break; + default: + *q = *s; + label_len++; + } + } + + /* add root label if last char was not '.' */ + if (!ldns_dname_str_absolute(str)) { + if (q > buf + LDNS_MAX_DOMAINLEN) { + return LDNS_STATUS_DOMAINNAME_OVERFLOW; + } + if (label_len > LDNS_MAX_LABELLEN) { + return LDNS_STATUS_LABEL_OVERFLOW; + } + if (label_len == 0) { /* label_len 0 but not . at end? */ + return LDNS_STATUS_EMPTY_LABEL; + } + len += label_len + 1; + *pq = label_len; + *q = 0; + } + len++; + + *d = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, len, buf); + return LDNS_STATUS_OK; +} + +ldns_status +ldns_str2rdf_a(ldns_rdf **rd, const char *str) +{ + in_addr_t address; + if (inet_pton(AF_INET, (char*)str, &address) != 1) { + return LDNS_STATUS_INVALID_IP4; + } else { + *rd = ldns_rdf_new_frm_data( + LDNS_RDF_TYPE_A, sizeof(address), &address); + } + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; +} + +ldns_status +ldns_str2rdf_aaaa(ldns_rdf **rd, const char *str) +{ + uint8_t address[LDNS_IP6ADDRLEN + 1]; + + if (inet_pton(AF_INET6, (char*)str, address) != 1) { + return LDNS_STATUS_INVALID_IP6; + } else { + *rd = ldns_rdf_new_frm_data( + LDNS_RDF_TYPE_AAAA, sizeof(address) - 1, &address); + } + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; +} + +ldns_status +ldns_str2rdf_str(ldns_rdf **rd, const char *str) +{ + uint8_t *data; + size_t i, str_i, esc_i; + + if (strlen(str) > 255) { + return LDNS_STATUS_INVALID_STR; + } + + data = LDNS_XMALLOC(uint8_t, strlen(str) + 1); + if(!data) return LDNS_STATUS_MEM_ERR; + i = 1; + + for (str_i = 0; str_i < strlen(str); str_i++) { + if (str[str_i] == '\\') { + /* octet value or literal char */ + esc_i = (size_t) parse_escape((uint8_t*) &str[str_i], (uint8_t*) &data[i]); + if (esc_i == 0) { + LDNS_FREE(data); + return LDNS_STATUS_SYNTAX_BAD_ESCAPE; + } + str_i += esc_i; + } else { + data[i] = (uint8_t) str[str_i]; + } + i++; + } + data[0] = i - 1; + *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_STR, i, data); + + LDNS_FREE(data); + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; +} + +ldns_status +ldns_str2rdf_apl(ldns_rdf **rd, const char *str) +{ + const char *my_str = str; + + char *my_ip_str; + size_t ip_str_len; + + uint16_t family; + bool negation; + uint8_t afdlength = 0; + uint8_t *afdpart; + uint8_t prefix; + + uint8_t *data; + + size_t i = 0; + + /* [!]afi:address/prefix */ + if (strlen(my_str) < 2 + || strchr(my_str, ':') == NULL + || strchr(my_str, '/') == NULL + || strchr(my_str, ':') > strchr(my_str, '/')) { + return LDNS_STATUS_INVALID_STR; + } + + if (my_str[0] == '!') { + negation = true; + my_str += 1; + } else { + negation = false; + } + + family = (uint16_t) atoi(my_str); + + my_str = strchr(my_str, ':') + 1; + + /* need ip addr and only ip addr for inet_pton */ + ip_str_len = (size_t) (strchr(my_str, '/') - my_str); + my_ip_str = LDNS_XMALLOC(char, ip_str_len + 1); + if(!my_ip_str) return LDNS_STATUS_MEM_ERR; + strncpy(my_ip_str, my_str, ip_str_len + 1); + my_ip_str[ip_str_len] = '\0'; + + if (family == 1) { + /* ipv4 */ + afdpart = LDNS_XMALLOC(uint8_t, 4); + if(!afdpart) { + LDNS_FREE(my_ip_str); + return LDNS_STATUS_MEM_ERR; + } + if (inet_pton(AF_INET, my_ip_str, afdpart) == 0) { + LDNS_FREE(my_ip_str); + LDNS_FREE(afdpart); + return LDNS_STATUS_INVALID_STR; + } + for (i = 0; i < 4; i++) { + if (afdpart[i] != 0) { + afdlength = i + 1; + } + } + } else if (family == 2) { + /* ipv6 */ + afdpart = LDNS_XMALLOC(uint8_t, 16); + if(!afdpart) { + LDNS_FREE(my_ip_str); + return LDNS_STATUS_MEM_ERR; + } + if (inet_pton(AF_INET6, my_ip_str, afdpart) == 0) { + LDNS_FREE(my_ip_str); + LDNS_FREE(afdpart); + return LDNS_STATUS_INVALID_STR; + } + for (i = 0; i < 16; i++) { + if (afdpart[i] != 0) { + afdlength = i + 1; + } + } + } else { + /* unknown family */ + LDNS_FREE(my_ip_str); + return LDNS_STATUS_INVALID_STR; + } + + my_str = strchr(my_str, '/') + 1; + prefix = (uint8_t) atoi(my_str); + + data = LDNS_XMALLOC(uint8_t, 4 + afdlength); + if(!data) { + LDNS_FREE(my_ip_str); + return LDNS_STATUS_INVALID_STR; + } + ldns_write_uint16(data, family); + data[2] = prefix; + data[3] = afdlength; + if (negation) { + /* set bit 1 of byte 3 */ + data[3] = data[3] | 0x80; + } + + memcpy(data + 4, afdpart, afdlength); + + *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_APL, afdlength + 4, data); + LDNS_FREE(afdpart); + LDNS_FREE(data); + LDNS_FREE(my_ip_str); + + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; +} + +ldns_status +ldns_str2rdf_b64(ldns_rdf **rd, const char *str) +{ + uint8_t *buffer; + int16_t i; + + buffer = LDNS_XMALLOC(uint8_t, ldns_b64_ntop_calculate_size(strlen(str))); + if(!buffer) { + return LDNS_STATUS_MEM_ERR; + } + + i = (uint16_t)ldns_b64_pton((const char*)str, buffer, + ldns_b64_ntop_calculate_size(strlen(str))); + if (-1 == i) { + LDNS_FREE(buffer); + return LDNS_STATUS_INVALID_B64; + } else { + *rd = ldns_rdf_new_frm_data( + LDNS_RDF_TYPE_B64, (uint16_t) i, buffer); + } + LDNS_FREE(buffer); + + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; +} + +ldns_status +ldns_str2rdf_b32_ext(ldns_rdf **rd, const char *str) +{ + uint8_t *buffer; + int i; + /* first byte contains length of actual b32 data */ + uint8_t len = ldns_b32_pton_calculate_size(strlen(str)); + buffer = LDNS_XMALLOC(uint8_t, len + 1); + if(!buffer) { + return LDNS_STATUS_MEM_ERR; + } + buffer[0] = len; + + i = ldns_b32_pton_extended_hex((const char*)str, strlen(str), buffer + 1, + ldns_b32_ntop_calculate_size(strlen(str))); + if (i < 0) { + LDNS_FREE(buffer); + return LDNS_STATUS_INVALID_B32_EXT; + } else { + *rd = ldns_rdf_new_frm_data( + LDNS_RDF_TYPE_B32_EXT, (uint16_t) i + 1, buffer); + } + LDNS_FREE(buffer); + + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; +} + +ldns_status +ldns_str2rdf_hex(ldns_rdf **rd, const char *str) +{ + uint8_t *t, *t_orig; + int i; + size_t len; + + len = strlen(str); + + if (len > LDNS_MAX_RDFLEN * 2) { + return LDNS_STATUS_LABEL_OVERFLOW; + } else { + t = LDNS_XMALLOC(uint8_t, (len / 2) + 1); + if(!t) { + return LDNS_STATUS_MEM_ERR; + } + t_orig = t; + /* Now process octet by octet... */ + while (*str) { + *t = 0; + if (isspace((int) *str)) { + str++; + } else { + for (i = 16; i >= 1; i -= 15) { + while (*str && isspace((int) *str)) { str++; } + if (*str) { + if (isxdigit((int) *str)) { + *t += ldns_hexdigit_to_int(*str) * i; + } else { + LDNS_FREE(t_orig); + return LDNS_STATUS_ERR; + } + ++str; + } + } + ++t; + } + } + *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX, + (size_t) (t - t_orig), + t_orig); + LDNS_FREE(t_orig); + } + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; +} + +ldns_status +ldns_str2rdf_nsec(ldns_rdf **rd, const char *str) +{ + const char *delimiters = "\n\t "; + char *token = LDNS_XMALLOC(char, LDNS_MAX_RDFLEN); + ldns_buffer *str_buf; + ssize_t c; + uint16_t cur_type; + size_t type_count = 0; + ldns_rr_type type_list[65536]; + if(!token) return LDNS_STATUS_MEM_ERR; + if(rd == NULL) { + LDNS_FREE(token); + return LDNS_STATUS_NULL; + } + + str_buf = LDNS_MALLOC(ldns_buffer); + if(!str_buf) { + LDNS_FREE(token); + return LDNS_STATUS_MEM_ERR; + } + ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str)); + if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) { + LDNS_FREE(str_buf); + LDNS_FREE(token); + return LDNS_STATUS_MEM_ERR; + } + + while ((c = ldns_bget_token(str_buf, token, delimiters, LDNS_MAX_RDFLEN)) != -1 && c != 0) { + if(type_count >= sizeof(type_list)) { + LDNS_FREE(str_buf); + LDNS_FREE(token); + return LDNS_STATUS_ERR; + } + cur_type = ldns_get_rr_type_by_name(token); + type_list[type_count] = cur_type; + type_count++; + } + + *rd = ldns_dnssec_create_nsec_bitmap(type_list, + type_count, + LDNS_RR_TYPE_NSEC); + + LDNS_FREE(token); + ldns_buffer_free(str_buf); + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; +} + +ldns_status +ldns_str2rdf_type(ldns_rdf **rd, const char *str) +{ + uint16_t type; + type = htons(ldns_get_rr_type_by_name(str)); + /* ldns_rr_type is a 16 bit value */ + *rd = ldns_rdf_new_frm_data( + LDNS_RDF_TYPE_TYPE, sizeof(uint16_t), &type); + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; +} + +ldns_status +ldns_str2rdf_class(ldns_rdf **rd, const char *str) +{ + uint16_t klass; + klass = htons(ldns_get_rr_class_by_name(str)); + /* class is 16 bit */ + *rd = ldns_rdf_new_frm_data( + LDNS_RDF_TYPE_CLASS, sizeof(uint16_t), &klass); + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; +} + +/* An certificate alg field can either be specified as a 8 bits number + * or by its symbolic name. Handle both + */ +ldns_status +ldns_str2rdf_cert_alg(ldns_rdf **rd, const char *str) +{ + ldns_lookup_table *lt; + ldns_status st; + uint8_t idd[2]; + lt = ldns_lookup_by_name(ldns_cert_algorithms, str); + st = LDNS_STATUS_OK; + + if (lt) { + ldns_write_uint16(idd, (uint16_t) lt->id); + *rd = ldns_rdf_new_frm_data( + LDNS_RDF_TYPE_INT16, sizeof(uint16_t), idd); + if (!*rd) { + st = LDNS_STATUS_ERR; + } + } else { + /* try as-is (a number) */ + st = ldns_str2rdf_int16(rd, str); + if (st == LDNS_STATUS_OK && + ldns_rdf2native_int16(*rd) == 0) { + st = LDNS_STATUS_CERT_BAD_ALGORITHM; + } + } + + return st; +} + +/* An alg field can either be specified as a 8 bits number + * or by its symbolic name. Handle both + */ +ldns_status +ldns_str2rdf_alg(ldns_rdf **rd, const char *str) +{ + ldns_lookup_table *lt; + ldns_status st; + + lt = ldns_lookup_by_name(ldns_algorithms, str); + st = LDNS_STATUS_OK; + + if (lt) { + /* it was given as a integer */ + *rd = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, (uint8_t) lt->id); + if (!*rd) { + st = LDNS_STATUS_ERR; + } + } else { + /* try as-is (a number) */ + st = ldns_str2rdf_int8(rd, str); + } + return st; +} + +ldns_status +ldns_str2rdf_unknown( ATTR_UNUSED(ldns_rdf **rd) + , ATTR_UNUSED(const char *str) + ) +{ + /* this should be caught in an earlier time (general str2host for + rr's */ + return LDNS_STATUS_NOT_IMPL; +} + +ldns_status +ldns_str2rdf_tsig( ATTR_UNUSED(ldns_rdf **rd) + , ATTR_UNUSED(const char *str) + ) +{ + /* there is no string representation for TSIG rrs */ + return LDNS_STATUS_NOT_IMPL; +} + +ldns_status +ldns_str2rdf_service( ATTR_UNUSED(ldns_rdf **rd) + , ATTR_UNUSED(const char *str) + ) +{ + /* is this used? is this actually WKS? or SRV? */ + return LDNS_STATUS_NOT_IMPL; +} + +static int +loc_parse_cm(char* my_str, char** endstr, uint8_t* m, uint8_t* e) +{ + /* read [.][mM] */ + /* into mantissa exponent format for LOC type */ + uint32_t meters = 0, cm = 0, val; + while (isblank(*my_str)) { + my_str++; + } + meters = (uint32_t)strtol(my_str, &my_str, 10); + if (*my_str == '.') { + my_str++; + cm = (uint32_t)strtol(my_str, &my_str, 10); + } + if (meters >= 1) { + *e = 2; + val = meters; + } else { + *e = 0; + val = cm; + } + while(val >= 10) { + (*e)++; + val /= 10; + } + *m = (uint8_t)val; + + if (*e > 9) + return 0; + if (*my_str == 'm' || *my_str == 'M') { + my_str++; + } + *endstr = my_str; + return 1; +} + +ldns_status +ldns_str2rdf_loc(ldns_rdf **rd, const char *str) +{ + uint32_t latitude = 0; + uint32_t longitude = 0; + uint32_t altitude = 0; + + uint8_t *data; + uint32_t equator = (uint32_t) ldns_power(2, 31); + + uint32_t h = 0; + uint32_t m = 0; + uint8_t size_b = 1, size_e = 2; + uint8_t horiz_pre_b = 1, horiz_pre_e = 6; + uint8_t vert_pre_b = 1, vert_pre_e = 3; + + double s = 0.0; + bool northerness; + bool easterness; + + char *my_str = (char *) str; + + /* only support version 0 */ + if (isdigit((int) *my_str)) { + h = (uint32_t) strtol(my_str, &my_str, 10); + } else { + return LDNS_STATUS_INVALID_STR; + } + + while (isblank((int) *my_str)) { + my_str++; + } + + if (isdigit((int) *my_str)) { + m = (uint32_t) strtol(my_str, &my_str, 10); + } else if (*my_str == 'N' || *my_str == 'S') { + goto north; + } else { + return LDNS_STATUS_INVALID_STR; + } + + while (isblank((int) *my_str)) { + my_str++; + } + + if (isdigit((int) *my_str)) { + s = strtod(my_str, &my_str); + } +north: + while (isblank((int) *my_str)) { + my_str++; + } + + if (*my_str == 'N') { + northerness = true; + } else if (*my_str == 'S') { + northerness = false; + } else { + return LDNS_STATUS_INVALID_STR; + } + + my_str++; + + /* store number */ + s = 1000.0 * s; + /* add a little to make floor in conversion a round */ + s += 0.0005; + latitude = (uint32_t) s; + latitude += 1000 * 60 * m; + latitude += 1000 * 60 * 60 * h; + if (northerness) { + latitude = equator + latitude; + } else { + latitude = equator - latitude; + } + while (isblank(*my_str)) { + my_str++; + } + + if (isdigit((int) *my_str)) { + h = (uint32_t) strtol(my_str, &my_str, 10); + } else { + return LDNS_STATUS_INVALID_STR; + } + + while (isblank((int) *my_str)) { + my_str++; + } + + if (isdigit((int) *my_str)) { + m = (uint32_t) strtol(my_str, &my_str, 10); + } else if (*my_str == 'E' || *my_str == 'W') { + goto east; + } else { + return LDNS_STATUS_INVALID_STR; + } + + while (isblank(*my_str)) { + my_str++; + } + + if (isdigit((int) *my_str)) { + s = strtod(my_str, &my_str); + } + +east: + while (isblank(*my_str)) { + my_str++; + } + + if (*my_str == 'E') { + easterness = true; + } else if (*my_str == 'W') { + easterness = false; + } else { + return LDNS_STATUS_INVALID_STR; + } + + my_str++; + + /* store number */ + s *= 1000.0; + /* add a little to make floor in conversion a round */ + s += 0.0005; + longitude = (uint32_t) s; + longitude += 1000 * 60 * m; + longitude += 1000 * 60 * 60 * h; + + if (easterness) { + longitude += equator; + } else { + longitude = equator - longitude; + } + + altitude = (uint32_t)(strtod(my_str, &my_str)*100.0 + + 10000000.0 + 0.5); + if (*my_str == 'm' || *my_str == 'M') { + my_str++; + } + + if (strlen(my_str) > 0) { + if(!loc_parse_cm(my_str, &my_str, &size_b, &size_e)) + return LDNS_STATUS_INVALID_STR; + } + + if (strlen(my_str) > 0) { + if(!loc_parse_cm(my_str, &my_str, &horiz_pre_b, &horiz_pre_e)) + return LDNS_STATUS_INVALID_STR; + } + + if (strlen(my_str) > 0) { + if(!loc_parse_cm(my_str, &my_str, &vert_pre_b, &vert_pre_e)) + return LDNS_STATUS_INVALID_STR; + } + + data = LDNS_XMALLOC(uint8_t, 16); + if(!data) { + return LDNS_STATUS_MEM_ERR; + } + data[0] = 0; + data[1] = 0; + data[1] = ((size_b << 4) & 0xf0) | (size_e & 0x0f); + data[2] = ((horiz_pre_b << 4) & 0xf0) | (horiz_pre_e & 0x0f); + data[3] = ((vert_pre_b << 4) & 0xf0) | (vert_pre_e & 0x0f); + ldns_write_uint32(data + 4, latitude); + ldns_write_uint32(data + 8, longitude); + ldns_write_uint32(data + 12, altitude); + + *rd = ldns_rdf_new_frm_data( + LDNS_RDF_TYPE_LOC, 16, data); + + LDNS_FREE(data); + return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; +} + +ldns_status +ldns_str2rdf_wks(ldns_rdf **rd, const char *str) +{ + uint8_t *bitmap = NULL; + uint8_t *data; + int bm_len = 0; + + struct protoent *proto = NULL; + struct servent *serv = NULL; + int serv_port; + + ldns_buffer *str_buf; + + char *proto_str = NULL; + char *token; + if(strlen(str) == 0) + token = LDNS_XMALLOC(char, 50); + else token = LDNS_XMALLOC(char, strlen(str)+2); + if(!token) return LDNS_STATUS_MEM_ERR; + + str_buf = LDNS_MALLOC(ldns_buffer); + if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;} + ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str)); + if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) { + LDNS_FREE(str_buf); + LDNS_FREE(token); + return LDNS_STATUS_MEM_ERR; + } + + while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) { + if (!proto_str) { + proto_str = strdup(token); + if (!proto_str) { + LDNS_FREE(bitmap); + LDNS_FREE(token); + ldns_buffer_free(str_buf); + return LDNS_STATUS_INVALID_STR; + } + } else { + serv = getservbyname(token, proto_str); + if (serv) { + serv_port = (int) ntohs((uint16_t) serv->s_port); + } else { + serv_port = atoi(token); + } + if (serv_port / 8 >= bm_len) { + uint8_t *b2 = LDNS_XREALLOC(bitmap, uint8_t, (serv_port / 8) + 1); + if(!b2) { + LDNS_FREE(bitmap); + LDNS_FREE(token); + ldns_buffer_free(str_buf); + free(proto_str); + return LDNS_STATUS_INVALID_STR; + } + bitmap = b2; + /* set to zero to be sure */ + for (; bm_len <= serv_port / 8; bm_len++) { + bitmap[bm_len] = 0; + } + } + ldns_set_bit(bitmap + (serv_port / 8), 7 - (serv_port % 8), true); + } + } + + if (!proto_str || !bitmap) { + LDNS_FREE(bitmap); + LDNS_FREE(token); + ldns_buffer_free(str_buf); + free(proto_str); + return LDNS_STATUS_INVALID_STR; + } + + data = LDNS_XMALLOC(uint8_t, bm_len + 1); + if(!data) { + LDNS_FREE(token); + ldns_buffer_free(str_buf); + LDNS_FREE(bitmap); + free(proto_str); + return LDNS_STATUS_INVALID_STR; + } + if (proto_str) + proto = getprotobyname(proto_str); + if (proto) { + data[0] = (uint8_t) proto->p_proto; + } else if (proto_str) { + data[0] = (uint8_t) atoi(proto_str); + } else { + data[0] = 0; + } + memcpy(data + 1, bitmap, (size_t) bm_len); + + *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_WKS, (uint16_t) (bm_len + 1), data); + + LDNS_FREE(data); + LDNS_FREE(token); + ldns_buffer_free(str_buf); + LDNS_FREE(bitmap); + free(proto_str); +#ifdef HAVE_ENDSERVENT + endservent(); +#endif +#ifdef HAVE_ENDPROTOENT + endprotoent(); +#endif + + if(!*rd) return LDNS_STATUS_MEM_ERR; + + return LDNS_STATUS_OK; +} + +ldns_status +ldns_str2rdf_nsap(ldns_rdf **rd, const char *str) +{ + size_t len, i; + char* nsap_str = (char*) str; + + /* just a hex string with optional dots? */ + if (str[0] != '0' || str[1] != 'x') { + return LDNS_STATUS_INVALID_STR; + } else { + len = strlen(str); + for (i=0; i < len; i++) { + if (nsap_str[i] == '.') + nsap_str[i] = ' '; + } + return ldns_str2rdf_hex(rd, str+2); + } +} + +ldns_status +ldns_str2rdf_atma(ldns_rdf **rd, const char *str) +{ + size_t len, i; + char* atma_str = (char*) str; + ldns_status status; + + /* just a hex string with optional dots? */ + len = strlen(str); + for (i=0; i < len; i++) { + if (atma_str[i] == '.') + atma_str[i] = ' '; + } + status = ldns_str2rdf_hex(rd, str); + if (status != LDNS_STATUS_OK) { + ; /* probably in e.164 format than */ + } + return status; +} + +ldns_status +ldns_str2rdf_ipseckey(ldns_rdf **rd, const char *str) +{ + uint8_t precedence = 0; + uint8_t gateway_type = 0; + uint8_t algorithm = 0; + char* gateway = NULL; + char* publickey = NULL; + uint8_t *data; + ldns_buffer *str_buf; + char *token; + int token_count = 0; + int ipseckey_len = 0; + ldns_rdf* gateway_rdf = NULL; + ldns_rdf* publickey_rdf = NULL; + ldns_status status = LDNS_STATUS_OK; + + if(strlen(str) == 0) + token = LDNS_XMALLOC(char, 256); + else token = LDNS_XMALLOC(char, strlen(str)+2); + if(!token) return LDNS_STATUS_MEM_ERR; + + str_buf = LDNS_MALLOC(ldns_buffer); + if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;} + ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str)); + if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) { + LDNS_FREE(str_buf); + LDNS_FREE(token); + return LDNS_STATUS_MEM_ERR; + } + while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) { + switch (token_count) { + case 0: + precedence = (uint8_t)atoi(token); + break; + case 1: + gateway_type = (uint8_t)atoi(token); + break; + case 2: + algorithm = (uint8_t)atoi(token); + break; + case 3: + gateway = strdup(token); + if (!gateway || (gateway_type == 0 && + (token[0] != '.' || token[1] != '\0'))) { + LDNS_FREE(gateway); + LDNS_FREE(token); + ldns_buffer_free(str_buf); + return LDNS_STATUS_INVALID_STR; + } + break; + case 4: + publickey = strdup(token); + break; + default: + LDNS_FREE(token); + ldns_buffer_free(str_buf); + return LDNS_STATUS_INVALID_STR; + break; + } + token_count++; + } + + if (!gateway || !publickey) { + if (gateway) + LDNS_FREE(gateway); + if (publickey) + LDNS_FREE(publickey); + LDNS_FREE(token); + ldns_buffer_free(str_buf); + return LDNS_STATUS_INVALID_STR; + } + + if (gateway_type == 1) { + status = ldns_str2rdf_a(&gateway_rdf, gateway); + } else if (gateway_type == 2) { + status = ldns_str2rdf_aaaa(&gateway_rdf, gateway); + } else if (gateway_type == 3) { + status = ldns_str2rdf_dname(&gateway_rdf, gateway); + } + + if (status != LDNS_STATUS_OK) { + if (gateway) + LDNS_FREE(gateway); + if (publickey) + LDNS_FREE(publickey); + LDNS_FREE(token); + ldns_buffer_free(str_buf); + return LDNS_STATUS_INVALID_STR; + } + + status = ldns_str2rdf_b64(&publickey_rdf, publickey); + + if (status != LDNS_STATUS_OK) { + if (gateway) + LDNS_FREE(gateway); + if (publickey) + LDNS_FREE(publickey); + LDNS_FREE(token); + ldns_buffer_free(str_buf); + if (gateway_rdf) ldns_rdf_free(gateway_rdf); + return LDNS_STATUS_INVALID_STR; + } + + /* now copy all into one ipseckey rdf */ + if (gateway_type) + ipseckey_len = 3 + (int)ldns_rdf_size(gateway_rdf) + (int)ldns_rdf_size(publickey_rdf); + else + ipseckey_len = 3 + (int)ldns_rdf_size(publickey_rdf); + + data = LDNS_XMALLOC(uint8_t, ipseckey_len); + if(!data) { + if (gateway) + LDNS_FREE(gateway); + if (publickey) + LDNS_FREE(publickey); + LDNS_FREE(token); + ldns_buffer_free(str_buf); + if (gateway_rdf) ldns_rdf_free(gateway_rdf); + if (publickey_rdf) ldns_rdf_free(publickey_rdf); + return LDNS_STATUS_MEM_ERR; + } + + data[0] = precedence; + data[1] = gateway_type; + data[2] = algorithm; + + if (gateway_type) { + memcpy(data + 3, + ldns_rdf_data(gateway_rdf), ldns_rdf_size(gateway_rdf)); + memcpy(data + 3 + ldns_rdf_size(gateway_rdf), + ldns_rdf_data(publickey_rdf), ldns_rdf_size(publickey_rdf)); + } else { + memcpy(data + 3, + ldns_rdf_data(publickey_rdf), ldns_rdf_size(publickey_rdf)); + } + + *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_IPSECKEY, (uint16_t) ipseckey_len, data); + + if (gateway) + LDNS_FREE(gateway); + if (publickey) + LDNS_FREE(publickey); + LDNS_FREE(token); + ldns_buffer_free(str_buf); + ldns_rdf_free(gateway_rdf); + ldns_rdf_free(publickey_rdf); + LDNS_FREE(data); + if(!*rd) return LDNS_STATUS_MEM_ERR; + return LDNS_STATUS_OK; +} diff --git a/tsig.c b/tsig.c new file mode 100644 index 00000000000..90c20a03ea0 --- /dev/null +++ b/tsig.c @@ -0,0 +1,472 @@ +/* + * tsig.c + * + * contains the functions needed for TSIG [RFC2845] + * + * (c) 2005-2006 NLnet Labs + * See the file LICENSE for the license + */ + +#include + +#include + +#include + +#ifdef HAVE_SSL +#include +#include +#endif /* HAVE_SSL */ + +char * +ldns_tsig_algorithm(ldns_tsig_credentials *tc) +{ + return tc->algorithm; +} + +char * +ldns_tsig_keyname(ldns_tsig_credentials *tc) +{ + return tc->keyname; +} + +char * +ldns_tsig_keydata(ldns_tsig_credentials *tc) +{ + return tc->keydata; +} + +char * +ldns_tsig_keyname_clone(ldns_tsig_credentials *tc) +{ + return strdup(tc->keyname); +} + +char * +ldns_tsig_keydata_clone(ldns_tsig_credentials *tc) +{ + return strdup(tc->keydata); +} + +/* + * Makes an exact copy of the wire, but with the tsig rr removed + */ +uint8_t * +ldns_tsig_prepare_pkt_wire(uint8_t *wire, size_t wire_len, size_t *result_len) +{ + uint8_t *wire2 = NULL; + uint16_t qd_count; + uint16_t an_count; + uint16_t ns_count; + uint16_t ar_count; + ldns_rr *rr; + + size_t pos; + uint16_t i; + + ldns_status status; + + if(wire_len < LDNS_HEADER_SIZE) { + return NULL; + } + /* fake parse the wire */ + qd_count = LDNS_QDCOUNT(wire); + an_count = LDNS_ANCOUNT(wire); + ns_count = LDNS_NSCOUNT(wire); + ar_count = LDNS_ARCOUNT(wire); + + if (ar_count > 0) { + ar_count--; + } else { + return NULL; + } + + pos = LDNS_HEADER_SIZE; + + for (i = 0; i < qd_count; i++) { + status = ldns_wire2rr(&rr, wire, wire_len, &pos, LDNS_SECTION_QUESTION); + if (status != LDNS_STATUS_OK) { + return NULL; + } + ldns_rr_free(rr); + } + + for (i = 0; i < an_count; i++) { + status = ldns_wire2rr(&rr, wire, wire_len, &pos, LDNS_SECTION_ANSWER); + if (status != LDNS_STATUS_OK) { + return NULL; + } + ldns_rr_free(rr); + } + + for (i = 0; i < ns_count; i++) { + status = ldns_wire2rr(&rr, wire, wire_len, &pos, LDNS_SECTION_AUTHORITY); + if (status != LDNS_STATUS_OK) { + return NULL; + } + ldns_rr_free(rr); + } + + for (i = 0; i < ar_count; i++) { + status = ldns_wire2rr(&rr, wire, wire_len, &pos, + LDNS_SECTION_ADDITIONAL); + if (status != LDNS_STATUS_OK) { + return NULL; + } + ldns_rr_free(rr); + } + + *result_len = pos; + wire2 = LDNS_XMALLOC(uint8_t, *result_len); + if(!wire2) { + return NULL; + } + memcpy(wire2, wire, *result_len); + + ldns_write_uint16(wire2 + LDNS_ARCOUNT_OFF, ar_count); + + return wire2; +} + +#ifdef HAVE_SSL +static const EVP_MD * +ldns_digest_function(char *name) +{ + /* these are the mandatory algorithms from RFC4635 */ + /* The optional algorithms are not yet implemented */ + if (strlen(name) == 12 + && strncasecmp(name, "hmac-sha256.", 11) == 0) { +#ifdef HAVE_EVP_SHA256 + return EVP_sha256(); +#else + return NULL; +#endif + } else if (strlen(name) == 10 + && strncasecmp(name, "hmac-sha1.", 9) == 0) { + return EVP_sha1(); + } else if (strlen(name) == 25 + && strncasecmp(name, "hmac-md5.sig-alg.reg.int.", 25) + == 0) { + return EVP_md5(); + } else { + return NULL; + } +} +#endif + +#ifdef HAVE_SSL +static ldns_status +ldns_tsig_mac_new(ldns_rdf **tsig_mac, uint8_t *pkt_wire, size_t pkt_wire_size, + const char *key_data, ldns_rdf *key_name_rdf, ldns_rdf *fudge_rdf, + ldns_rdf *algorithm_rdf, ldns_rdf *time_signed_rdf, ldns_rdf *error_rdf, + ldns_rdf *other_data_rdf, ldns_rdf *orig_mac_rdf, int tsig_timers_only) +{ + ldns_status status; + char *wireformat; + int wiresize; + unsigned char *mac_bytes = NULL; + unsigned char *key_bytes = NULL; + int key_size; + const EVP_MD *digester; + char *algorithm_name = NULL; + unsigned int md_len = EVP_MAX_MD_SIZE; + ldns_rdf *result = NULL; + ldns_buffer *data_buffer = NULL; + ldns_rdf *canonical_key_name_rdf = NULL; + ldns_rdf *canonical_algorithm_rdf = NULL; + + if (key_name_rdf == NULL || algorithm_rdf == NULL) { + return LDNS_STATUS_NULL; + } + canonical_key_name_rdf = ldns_rdf_clone(key_name_rdf); + canonical_algorithm_rdf = ldns_rdf_clone(algorithm_rdf); + + if (canonical_key_name_rdf == NULL + || canonical_algorithm_rdf == NULL) { + return LDNS_STATUS_MEM_ERR; + } + /* + * prepare the digestable information + */ + data_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN); + if (!data_buffer) { + status = LDNS_STATUS_MEM_ERR; + goto clean; + } + /* if orig_mac is not NULL, add it too */ + if (orig_mac_rdf) { + (void) ldns_rdf2buffer_wire(data_buffer, orig_mac_rdf); + } + ldns_buffer_write(data_buffer, pkt_wire, pkt_wire_size); + if (!tsig_timers_only) { + ldns_dname2canonical(canonical_key_name_rdf); + (void)ldns_rdf2buffer_wire(data_buffer, + canonical_key_name_rdf); + ldns_buffer_write_u16(data_buffer, LDNS_RR_CLASS_ANY); + ldns_buffer_write_u32(data_buffer, 0); + ldns_dname2canonical(canonical_algorithm_rdf); + (void)ldns_rdf2buffer_wire(data_buffer, + canonical_algorithm_rdf); + } + (void)ldns_rdf2buffer_wire(data_buffer, time_signed_rdf); + (void)ldns_rdf2buffer_wire(data_buffer, fudge_rdf); + if (!tsig_timers_only) { + (void)ldns_rdf2buffer_wire(data_buffer, error_rdf); + (void)ldns_rdf2buffer_wire(data_buffer, other_data_rdf); + } + + wireformat = (char *) data_buffer->_data; + wiresize = (int) ldns_buffer_position(data_buffer); + + algorithm_name = ldns_rdf2str(algorithm_rdf); + if(!algorithm_name) { + status = LDNS_STATUS_MEM_ERR; + goto clean; + } + + /* prepare the key */ + key_bytes = LDNS_XMALLOC(unsigned char, + ldns_b64_pton_calculate_size(strlen(key_data))); + if(!key_bytes) { + status = LDNS_STATUS_MEM_ERR; + goto clean; + } + key_size = ldns_b64_pton(key_data, key_bytes, + ldns_b64_pton_calculate_size(strlen(key_data))); + if (key_size < 0) { + status = LDNS_STATUS_INVALID_B64; + goto clean; + } + /* hmac it */ + /* 2 spare bytes for the length */ + mac_bytes = LDNS_XMALLOC(unsigned char, md_len+2); + if(!mac_bytes) { + status = LDNS_STATUS_MEM_ERR; + goto clean; + } + memset(mac_bytes, 0, md_len+2); + + digester = ldns_digest_function(algorithm_name); + + if (digester) { + (void) HMAC(digester, key_bytes, key_size, (void *)wireformat, + (size_t) wiresize, mac_bytes + 2, &md_len); + + ldns_write_uint16(mac_bytes, md_len); + result = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT16_DATA, md_len + 2, + mac_bytes); + } else { + status = LDNS_STATUS_CRYPTO_UNKNOWN_ALGO; + goto clean; + } + *tsig_mac = result; + status = LDNS_STATUS_OK; + clean: + LDNS_FREE(mac_bytes); + LDNS_FREE(key_bytes); + LDNS_FREE(algorithm_name); + ldns_buffer_free(data_buffer); + ldns_rdf_free(canonical_algorithm_rdf); + ldns_rdf_free(canonical_key_name_rdf); + return status; +} +#endif /* HAVE_SSL */ + + +#ifdef HAVE_SSL +bool +ldns_pkt_tsig_verify(ldns_pkt *pkt, uint8_t *wire, size_t wirelen, const char *key_name, + const char *key_data, ldns_rdf *orig_mac_rdf) +{ + return ldns_pkt_tsig_verify_next(pkt, wire, wirelen, key_name, key_data, orig_mac_rdf, 0); +} + +bool +ldns_pkt_tsig_verify_next(ldns_pkt *pkt, uint8_t *wire, size_t wirelen, const char* key_name, + const char *key_data, ldns_rdf *orig_mac_rdf, int tsig_timers_only) +{ + ldns_rdf *fudge_rdf; + ldns_rdf *algorithm_rdf; + ldns_rdf *time_signed_rdf; + ldns_rdf *orig_id_rdf; + ldns_rdf *error_rdf; + ldns_rdf *other_data_rdf; + ldns_rdf *pkt_mac_rdf; + ldns_rdf *my_mac_rdf; + ldns_rdf *key_name_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, key_name); + uint16_t pkt_id, orig_pkt_id; + ldns_status status; + + uint8_t *prepared_wire = NULL; + size_t prepared_wire_size = 0; + + ldns_rr *orig_tsig = ldns_pkt_tsig(pkt); + + if (!orig_tsig || ldns_rr_rd_count(orig_tsig) <= 6) { + ldns_rdf_deep_free(key_name_rdf); + return false; + } + algorithm_rdf = ldns_rr_rdf(orig_tsig, 0); + time_signed_rdf = ldns_rr_rdf(orig_tsig, 1); + fudge_rdf = ldns_rr_rdf(orig_tsig, 2); + pkt_mac_rdf = ldns_rr_rdf(orig_tsig, 3); + orig_id_rdf = ldns_rr_rdf(orig_tsig, 4); + error_rdf = ldns_rr_rdf(orig_tsig, 5); + other_data_rdf = ldns_rr_rdf(orig_tsig, 6); + + /* remove temporarily */ + ldns_pkt_set_tsig(pkt, NULL); + /* temporarily change the id to the original id */ + pkt_id = ldns_pkt_id(pkt); + orig_pkt_id = ldns_rdf2native_int16(orig_id_rdf); + ldns_pkt_set_id(pkt, orig_pkt_id); + + prepared_wire = ldns_tsig_prepare_pkt_wire(wire, wirelen, &prepared_wire_size); + + status = ldns_tsig_mac_new(&my_mac_rdf, prepared_wire, prepared_wire_size, + key_data, key_name_rdf, fudge_rdf, algorithm_rdf, + time_signed_rdf, error_rdf, other_data_rdf, orig_mac_rdf, tsig_timers_only); + + LDNS_FREE(prepared_wire); + + if (status != LDNS_STATUS_OK) { + ldns_rdf_deep_free(key_name_rdf); + return false; + } + /* Put back the values */ + ldns_pkt_set_tsig(pkt, orig_tsig); + ldns_pkt_set_id(pkt, pkt_id); + + ldns_rdf_deep_free(key_name_rdf); + + if (ldns_rdf_compare(pkt_mac_rdf, my_mac_rdf) == 0) { + ldns_rdf_deep_free(my_mac_rdf); + return true; + } else { + ldns_rdf_deep_free(my_mac_rdf); + return false; + } +} +#endif /* HAVE_SSL */ + +#ifdef HAVE_SSL +ldns_status +ldns_pkt_tsig_sign(ldns_pkt *pkt, const char *key_name, const char *key_data, + uint16_t fudge, const char *algorithm_name, ldns_rdf *query_mac) +{ + return ldns_pkt_tsig_sign_next(pkt, key_name, key_data, fudge, algorithm_name, query_mac, 0); +} + +ldns_status +ldns_pkt_tsig_sign_next(ldns_pkt *pkt, const char *key_name, const char *key_data, + uint16_t fudge, const char *algorithm_name, ldns_rdf *query_mac, int tsig_timers_only) +{ + ldns_rr *tsig_rr; + ldns_rdf *key_name_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, key_name); + ldns_rdf *fudge_rdf = NULL; + ldns_rdf *orig_id_rdf = NULL; + ldns_rdf *algorithm_rdf; + ldns_rdf *error_rdf = NULL; + ldns_rdf *mac_rdf = NULL; + ldns_rdf *other_data_rdf = NULL; + + ldns_status status = LDNS_STATUS_OK; + + uint8_t *pkt_wire = NULL; + size_t pkt_wire_len; + + struct timeval tv_time_signed; + uint8_t *time_signed = NULL; + ldns_rdf *time_signed_rdf = NULL; + + algorithm_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, algorithm_name); + if(!key_name_rdf || !algorithm_rdf) { + status = LDNS_STATUS_MEM_ERR; + goto clean; + } + + /* eww don't have create tsigtime rdf yet :( */ + /* bleh :p */ + if (gettimeofday(&tv_time_signed, NULL) == 0) { + time_signed = LDNS_XMALLOC(uint8_t, 6); + if(!time_signed) { + status = LDNS_STATUS_MEM_ERR; + goto clean; + } + ldns_write_uint64_as_uint48(time_signed, + (uint64_t)tv_time_signed.tv_sec); + } else { + status = LDNS_STATUS_INTERNAL_ERR; + goto clean; + } + + time_signed_rdf = ldns_rdf_new(LDNS_RDF_TYPE_TSIGTIME, 6, time_signed); + if(!time_signed_rdf) { + LDNS_FREE(time_signed); + status = LDNS_STATUS_MEM_ERR; + goto clean; + } + + fudge_rdf = ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, fudge); + + orig_id_rdf = ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, ldns_pkt_id(pkt)); + + error_rdf = ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, 0); + + other_data_rdf = ldns_native2rdf_int16_data(0, NULL); + + if(!fudge_rdf || !orig_id_rdf || !error_rdf || !other_data_rdf) { + status = LDNS_STATUS_MEM_ERR; + goto clean; + } + + if (ldns_pkt2wire(&pkt_wire, pkt, &pkt_wire_len) != LDNS_STATUS_OK) { + status = LDNS_STATUS_ERR; + goto clean; + } + + status = ldns_tsig_mac_new(&mac_rdf, pkt_wire, pkt_wire_len, + key_data, key_name_rdf, fudge_rdf, algorithm_rdf, + time_signed_rdf, error_rdf, other_data_rdf, query_mac, tsig_timers_only); + + if (!mac_rdf) { + goto clean; + } + + LDNS_FREE(pkt_wire); + + /* Create the TSIG RR */ + tsig_rr = ldns_rr_new(); + if(!tsig_rr) { + status = LDNS_STATUS_MEM_ERR; + goto clean; + } + ldns_rr_set_owner(tsig_rr, key_name_rdf); + ldns_rr_set_class(tsig_rr, LDNS_RR_CLASS_ANY); + ldns_rr_set_type(tsig_rr, LDNS_RR_TYPE_TSIG); + ldns_rr_set_ttl(tsig_rr, 0); + + ldns_rr_push_rdf(tsig_rr, algorithm_rdf); + ldns_rr_push_rdf(tsig_rr, time_signed_rdf); + ldns_rr_push_rdf(tsig_rr, fudge_rdf); + ldns_rr_push_rdf(tsig_rr, mac_rdf); + ldns_rr_push_rdf(tsig_rr, orig_id_rdf); + ldns_rr_push_rdf(tsig_rr, error_rdf); + ldns_rr_push_rdf(tsig_rr, other_data_rdf); + + ldns_pkt_set_tsig(pkt, tsig_rr); + + return status; + + clean: + LDNS_FREE(pkt_wire); + ldns_rdf_free(key_name_rdf); + ldns_rdf_free(algorithm_rdf); + ldns_rdf_free(time_signed_rdf); + ldns_rdf_free(fudge_rdf); + ldns_rdf_free(orig_id_rdf); + ldns_rdf_free(error_rdf); + ldns_rdf_free(other_data_rdf); + return status; +} +#endif /* HAVE_SSL */ diff --git a/update.c b/update.c new file mode 100644 index 00000000000..96f72ce199b --- /dev/null +++ b/update.c @@ -0,0 +1,318 @@ +/* update.c + * + * Functions for RFC 2136 Dynamic Update + * + * Copyright (c) 2005-2008, NLnet Labs. All rights reserved. + * + * See LICENSE for the license. + */ + +#include + +#include + +#include +#include +#include + +/* + * RFC 2136 sections mapped to RFC 1035: + * zone/ZO -- QD/question + * prerequisites/PR -- AN/answers + * updates/UP -- NS/authority records + * additional data/AD -- AR/additional records + */ + +ldns_pkt * +ldns_update_pkt_new(ldns_rdf *zone_rdf, ldns_rr_class c, + ldns_rr_list *pr_rrlist, ldns_rr_list *up_rrlist, ldns_rr_list *ad_rrlist) +{ + ldns_pkt *p; + + if (!zone_rdf || !up_rrlist) { + return NULL; + } + + if (c == 0) { + c = LDNS_RR_CLASS_IN; + } + + /* Create packet, fill in Zone Section. */ + p = ldns_pkt_query_new(zone_rdf, LDNS_RR_TYPE_SOA, c, LDNS_RD); + if (!p) { + return NULL; + } + zone_rdf = NULL; /* No longer safe to use. */ + + ldns_pkt_set_opcode(p, LDNS_PACKET_UPDATE); + + ldns_rr_list_deep_free(p->_authority); + + ldns_pkt_set_authority(p, ldns_rr_list_clone(up_rrlist)); + + ldns_update_set_upcount(p, ldns_rr_list_rr_count(up_rrlist)); + + if (pr_rrlist) { + ldns_rr_list_deep_free(p->_answer); /*XXX access function */ + ldns_pkt_set_answer(p, ldns_rr_list_clone(pr_rrlist)); + ldns_update_set_prcount(p, ldns_rr_list_rr_count(pr_rrlist)); + } + + if (ad_rrlist) { + ldns_rr_list_deep_free(p->_additional); + ldns_pkt_set_additional(p, ldns_rr_list_clone(ad_rrlist)); + ldns_update_set_adcount(p, ldns_rr_list_rr_count(ad_rrlist)); + } + return p; +} + +ldns_status +ldns_update_pkt_tsig_add(ldns_pkt *p, ldns_resolver *r) +{ +#ifdef HAVE_SSL + uint16_t fudge = 300; /* Recommended fudge. [RFC2845 6.4] */ + if (ldns_resolver_tsig_keyname(r) && ldns_resolver_tsig_keydata(r)) + return ldns_pkt_tsig_sign(p, ldns_resolver_tsig_keyname(r), + ldns_resolver_tsig_keydata(r), fudge, + ldns_resolver_tsig_algorithm(r), NULL); +#else + /* do nothing */ + (void)p; + (void)r; +#endif /* HAVE_SSL */ + /* No TSIG to do. */ + return LDNS_STATUS_OK; +} + +/* Move to higher.c or similar? */ +/* XXX doc */ +ldns_status +ldns_update_soa_mname(ldns_rdf *zone, ldns_resolver *r, + ldns_rr_class c, ldns_rdf **mname) +{ + ldns_rr *soa_rr; + ldns_pkt *query, *resp; + + /* Nondestructive, so clone 'zone' here */ + query = ldns_pkt_query_new(ldns_rdf_clone(zone), LDNS_RR_TYPE_SOA, + c, LDNS_RD); + if (!query) { + return LDNS_STATUS_ERR; + } + + ldns_pkt_set_random_id(query); + if (ldns_resolver_send_pkt(&resp, r, query) != LDNS_STATUS_OK) { + ldns_pkt_free(query); + return LDNS_STATUS_ERR; + } + ldns_pkt_free(query); + if (!resp) { + return LDNS_STATUS_ERR; + } + + /* Expect a SOA answer. */ + *mname = NULL; + while ((soa_rr = ldns_rr_list_pop_rr(ldns_pkt_answer(resp)))) { + if (ldns_rr_get_type(soa_rr) != LDNS_RR_TYPE_SOA + || ldns_rr_rdf(soa_rr, 0) == NULL) + continue; + /* [RFC1035 3.3.13] */ + *mname = ldns_rdf_clone(ldns_rr_rdf(soa_rr, 0)); + break; + } + ldns_pkt_free(resp); + + return *mname ? LDNS_STATUS_OK : LDNS_STATUS_ERR; +} + +/* Try to get zone and MNAME from SOA queries. */ +ldns_status +ldns_update_soa_zone_mname(const char *fqdn, ldns_resolver *r, + ldns_rr_class c, ldns_rdf **zone_rdf, ldns_rdf **mname_rdf) +{ + ldns_rr *soa_rr, *rr; + ldns_rdf *soa_zone = NULL, *soa_mname = NULL; + ldns_rdf *ipaddr, *fqdn_rdf, *tmp; + ldns_rdf **nslist; + ldns_pkt *query, *resp; + size_t i; + + /* + * XXX Ok, this cannot be the best way to find this...? + * XXX (I run into weird cache-related stuff here) + */ + + /* Step 1 - first find a nameserver that should know *something* */ + fqdn_rdf = ldns_dname_new_frm_str(fqdn); + query = ldns_pkt_query_new(fqdn_rdf, LDNS_RR_TYPE_SOA, c, LDNS_RD); + if (!query) { + return LDNS_STATUS_ERR; + } + fqdn_rdf = NULL; + + ldns_pkt_set_random_id(query); + if (ldns_resolver_send_pkt(&resp, r, query) != LDNS_STATUS_OK) { + ldns_pkt_free(query); + return LDNS_STATUS_ERR; + } + ldns_pkt_free(query); + if (!resp) { + return LDNS_STATUS_ERR; + } + + /* XXX Is it safe to only look in authority section here? */ + while ((soa_rr = ldns_rr_list_pop_rr(ldns_pkt_authority(resp)))) { + if (ldns_rr_get_type(soa_rr) != LDNS_RR_TYPE_SOA + || ldns_rr_rdf(soa_rr, 0) == NULL) + continue; + /* [RFC1035 3.3.13] */ + soa_mname = ldns_rdf_clone(ldns_rr_rdf(soa_rr, 0)); + break; + } + ldns_pkt_free(resp); + if (!soa_rr) { + return LDNS_STATUS_ERR; + } + + /* Step 2 - find SOA MNAME IP address, add to resolver */ + query = ldns_pkt_query_new(soa_mname, LDNS_RR_TYPE_A, c, LDNS_RD); + if (!query) { + return LDNS_STATUS_ERR; + } + soa_mname = NULL; + + ldns_pkt_set_random_id(query); + if (ldns_resolver_send_pkt(&resp, r, query) != LDNS_STATUS_OK) { + ldns_pkt_free(query); + return LDNS_STATUS_ERR; + } + ldns_pkt_free(query); + if (!resp) { + return LDNS_STATUS_ERR; + } + + if (ldns_pkt_ancount(resp) == 0) { + ldns_pkt_free(resp); + return LDNS_STATUS_ERR; + } + + /* XXX There may be more than one answer RR here. */ + rr = ldns_rr_list_pop_rr(ldns_pkt_answer(resp)); + ipaddr = ldns_rr_rdf(rr, 0); + + /* Put the SOA mname IP first in the nameserver list. */ + nslist = ldns_resolver_nameservers(r); + for (i = 0; i < ldns_resolver_nameserver_count(r); i++) { + if (ldns_rdf_compare(ipaddr, nslist[i]) == 0) { + if (i) { + tmp = nslist[0]; + nslist[0] = nslist[i]; + nslist[i] = tmp; + } + break; + } + } + if (i >= ldns_resolver_nameserver_count(r)) { + /* SOA mname was not part of the resolver so add it first. */ + (void) ldns_resolver_push_nameserver(r, ipaddr); + nslist = ldns_resolver_nameservers(r); + i = ldns_resolver_nameserver_count(r) - 1; + tmp = nslist[0]; + nslist[0] = nslist[i]; + nslist[i] = tmp; + } + ldns_pkt_free(resp); + + /* Make sure to ask the first in the list, i.e SOA mname */ + ldns_resolver_set_random(r, false); + + /* Step 3 - Redo SOA query, sending to SOA MNAME directly. */ + fqdn_rdf = ldns_dname_new_frm_str(fqdn); + query = ldns_pkt_query_new(fqdn_rdf, LDNS_RR_TYPE_SOA, c, LDNS_RD); + if (!query) { + return LDNS_STATUS_ERR; + } + fqdn_rdf = NULL; + + ldns_pkt_set_random_id(query); + if (ldns_resolver_send_pkt(&resp, r, query) != LDNS_STATUS_OK) { + ldns_pkt_free(query); + return LDNS_STATUS_ERR; + } + ldns_pkt_free(query); + if (!resp) { + return LDNS_STATUS_ERR; + } + + /* XXX Is it safe to only look in authority section here, too? */ + while ((soa_rr = ldns_rr_list_pop_rr(ldns_pkt_authority(resp)))) { + if (ldns_rr_get_type(soa_rr) != LDNS_RR_TYPE_SOA + || ldns_rr_rdf(soa_rr, 0) == NULL) + continue; + /* [RFC1035 3.3.13] */ + soa_mname = ldns_rdf_clone(ldns_rr_rdf(soa_rr, 0)); + soa_zone = ldns_rdf_clone(ldns_rr_owner(soa_rr)); + break; + } + ldns_pkt_free(resp); + if (!soa_rr) { + return LDNS_STATUS_ERR; + } + + /* That seems to have worked, pass results to caller. */ + *zone_rdf = soa_zone; + *mname_rdf = soa_mname; + return LDNS_STATUS_OK; +} + +/* + * ldns_update_{get,set}_{zo,pr,up,ad}count + */ + +uint16_t +ldns_update_zocount(const ldns_pkt *p) +{ + return ldns_pkt_qdcount(p); +} + +uint16_t +ldns_update_prcount(const ldns_pkt *p) +{ + return ldns_pkt_ancount(p); +} + +uint16_t +ldns_update_upcount(const ldns_pkt *p) +{ + return ldns_pkt_nscount(p); +} + +uint16_t +ldns_update_ad(const ldns_pkt *p) +{ + return ldns_pkt_arcount(p); +} + +void +ldns_update_set_zo(ldns_pkt *p, uint16_t v) +{ + ldns_pkt_set_qdcount(p, v); +} + +void +ldns_update_set_prcount(ldns_pkt *p, uint16_t v) +{ + ldns_pkt_set_ancount(p, v); +} + +void +ldns_update_set_upcount(ldns_pkt *p, uint16_t v) +{ + ldns_pkt_set_nscount(p, v); +} + +void +ldns_update_set_adcount(ldns_pkt *p, uint16_t v) +{ + ldns_pkt_set_arcount(p, v); +} diff --git a/util.c b/util.c new file mode 100644 index 00000000000..a7ab96080ce --- /dev/null +++ b/util.c @@ -0,0 +1,492 @@ +/* + * util.c + * + * some general memory functions + * + * a Net::DNS like library for C + * + * (c) NLnet Labs, 2004-2006 + * + * See the file LICENSE for the license + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_SSL +#include +#endif + +/* put this here tmp. for debugging */ +void +xprintf_rdf(ldns_rdf *rd) +{ + /* assume printable string */ + fprintf(stderr, "size\t:%u\n", (unsigned int)ldns_rdf_size(rd)); + fprintf(stderr, "type\t:%u\n", (unsigned int)ldns_rdf_get_type(rd)); + fprintf(stderr, "data\t:[%.*s]\n", (int)ldns_rdf_size(rd), + (char*)ldns_rdf_data(rd)); +} + +void +xprintf_rr(ldns_rr *rr) +{ + /* assume printable string */ + uint16_t count, i; + + count = ldns_rr_rd_count(rr); + + for(i = 0; i < count; i++) { + fprintf(stderr, "print rd %u\n", (unsigned int) i); + xprintf_rdf(rr->_rdata_fields[i]); + } +} + +void xprintf_hex(uint8_t *data, size_t len) +{ + size_t i; + for (i = 0; i < len; i++) { + if (i > 0 && i % 20 == 0) { + printf("\t; %u - %u\n", (unsigned int) i - 19, (unsigned int) i); + } + printf("%02x ", (unsigned int) data[i]); + } + printf("\n"); +} + +ldns_lookup_table * +ldns_lookup_by_name(ldns_lookup_table *table, const char *name) +{ + while (table->name != NULL) { + if (strcasecmp(name, table->name) == 0) + return table; + table++; + } + return NULL; +} + +ldns_lookup_table * +ldns_lookup_by_id(ldns_lookup_table *table, int id) +{ + while (table->name != NULL) { + if (table->id == id) + return table; + table++; + } + return NULL; +} + +int +ldns_get_bit(uint8_t bits[], size_t index) +{ + /* + * The bits are counted from left to right, so bit #0 is the + * left most bit. + */ + return (int) (bits[index / 8] & (1 << (7 - index % 8))); +} + +int +ldns_get_bit_r(uint8_t bits[], size_t index) +{ + /* + * The bits are counted from right to left, so bit #0 is the + * right most bit. + */ + return (int) bits[index / 8] & (1 << (index % 8)); +} + +void +ldns_set_bit(uint8_t *byte, int bit_nr, bool value) +{ + /* + * The bits are counted from right to left, so bit #0 is the + * right most bit. + */ + if (bit_nr >= 0 && bit_nr < 8) { + if (value) { + *byte = *byte | (0x01 << bit_nr); + } else { + *byte = *byte & ~(0x01 << bit_nr); + } + } +} + +int +ldns_hexdigit_to_int(char ch) +{ + switch (ch) { + case '0': return 0; + case '1': return 1; + case '2': return 2; + case '3': return 3; + case '4': return 4; + case '5': return 5; + case '6': return 6; + case '7': return 7; + case '8': return 8; + case '9': return 9; + case 'a': case 'A': return 10; + case 'b': case 'B': return 11; + case 'c': case 'C': return 12; + case 'd': case 'D': return 13; + case 'e': case 'E': return 14; + case 'f': case 'F': return 15; + default: + return -1; + } +} + +char +ldns_int_to_hexdigit(int i) +{ + switch (i) { + case 0: return '0'; + case 1: return '1'; + case 2: return '2'; + case 3: return '3'; + case 4: return '4'; + case 5: return '5'; + case 6: return '6'; + case 7: return '7'; + case 8: return '8'; + case 9: return '9'; + case 10: return 'a'; + case 11: return 'b'; + case 12: return 'c'; + case 13: return 'd'; + case 14: return 'e'; + case 15: return 'f'; + default: + abort(); + } +} + +int +ldns_hexstring_to_data(uint8_t *data, const char *str) +{ + size_t i; + + if (!str || !data) { + return -1; + } + + if (strlen(str) % 2 != 0) { + return -2; + } + + for (i = 0; i < strlen(str) / 2; i++) { + data[i] = + 16 * (uint8_t) ldns_hexdigit_to_int(str[i*2]) + + (uint8_t) ldns_hexdigit_to_int(str[i*2 + 1]); + } + + return (int) i; +} + +const char * +ldns_version(void) +{ + return (char*)LDNS_VERSION; +} + +/* Number of days per month (except for February in leap years). */ +static const int mdays[] = { + 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 +}; + +#define LDNS_MOD(x,y) (((x) % (y) < 0) ? ((x) % (y) + (y)) : ((x) % (y))) +#define LDNS_DIV(x,y) (((x) % (y) < 0) ? ((x) / (y) - 1 ) : ((x) / (y))) + +static int +is_leap_year(int year) +{ + return LDNS_MOD(year, 4) == 0 && (LDNS_MOD(year, 100) != 0 + || LDNS_MOD(year, 400) == 0); +} + +static int +leap_days(int y1, int y2) +{ + --y1; + --y2; + return (LDNS_DIV(y2, 4) - LDNS_DIV(y1, 4)) - + (LDNS_DIV(y2, 100) - LDNS_DIV(y1, 100)) + + (LDNS_DIV(y2, 400) - LDNS_DIV(y1, 400)); +} + +/* + * Code adapted from Python 2.4.1 sources (Lib/calendar.py). + */ +time_t +mktime_from_utc(const struct tm *tm) +{ + int year = 1900 + tm->tm_year; + time_t days = 365 * ((time_t) year - 1970) + leap_days(1970, year); + time_t hours; + time_t minutes; + time_t seconds; + int i; + + for (i = 0; i < tm->tm_mon; ++i) { + days += mdays[i]; + } + if (tm->tm_mon > 1 && is_leap_year(year)) { + ++days; + } + days += tm->tm_mday - 1; + + hours = days * 24 + tm->tm_hour; + minutes = hours * 60 + tm->tm_min; + seconds = minutes * 60 + tm->tm_sec; + + return seconds; +} + +#if SIZEOF_TIME_T <= 4 + +static void +ldns_year_and_yday_from_days_since_epoch(int64_t days, struct tm *result) +{ + int year = 1970; + int new_year; + + while (days < 0 || days >= (int64_t) (is_leap_year(year) ? 366 : 365)) { + new_year = year + (int) LDNS_DIV(days, 365); + days -= (new_year - year) * 365; + days -= leap_days(year, new_year); + year = new_year; + } + result->tm_year = year; + result->tm_yday = (int) days; +} + +/* Number of days per month in a leap year. */ +static const int leap_year_mdays[] = { + 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 +}; + +static void +ldns_mon_and_mday_from_year_and_yday(struct tm *result) +{ + int idays = result->tm_yday; + const int *mon_lengths = is_leap_year(result->tm_year) ? + leap_year_mdays : mdays; + + result->tm_mon = 0; + while (idays >= mon_lengths[result->tm_mon]) { + idays -= mon_lengths[result->tm_mon++]; + } + result->tm_mday = idays + 1; +} + +static void +ldns_wday_from_year_and_yday(struct tm *result) +{ + result->tm_wday = 4 /* 1-1-1970 was a thursday */ + + LDNS_MOD((result->tm_year - 1970), 7) * LDNS_MOD(365, 7) + + leap_days(1970, result->tm_year) + + result->tm_yday; + result->tm_wday = LDNS_MOD(result->tm_wday, 7); + if (result->tm_wday < 0) { + result->tm_wday += 7; + } +} + +static struct tm * +ldns_gmtime64_r(int64_t clock, struct tm *result) +{ + result->tm_isdst = 0; + result->tm_sec = (int) LDNS_MOD(clock, 60); + clock = LDNS_DIV(clock, 60); + result->tm_min = (int) LDNS_MOD(clock, 60); + clock = LDNS_DIV(clock, 60); + result->tm_hour = (int) LDNS_MOD(clock, 24); + clock = LDNS_DIV(clock, 24); + + ldns_year_and_yday_from_days_since_epoch(clock, result); + ldns_mon_and_mday_from_year_and_yday(result); + ldns_wday_from_year_and_yday(result); + result->tm_year -= 1900; + + return result; +} + +#endif /* SIZEOF_TIME_T <= 4 */ + +static int64_t +ldns_serial_arithmitics_time(int32_t time, time_t now) +{ + int32_t offset = time - (int32_t) now; + return (int64_t) now + offset; +} + + +struct tm * +ldns_serial_arithmitics_gmtime_r(int32_t time, time_t now, struct tm *result) +{ +#if SIZEOF_TIME_T <= 4 + int64_t secs_since_epoch = ldns_serial_arithmitics_time(time, now); + return ldns_gmtime64_r(secs_since_epoch, result); +#else + time_t secs_since_epoch = ldns_serial_arithmitics_time(time, now); + return gmtime_r(&secs_since_epoch, result); +#endif +} + +/** + * Init the random source + * applications should call this if they need entropy data within ldns + * If openSSL is available, it is automatically seeded from /dev/urandom + * or /dev/random + * + * If you need more entropy, or have no openssl available, this function + * MUST be called at the start of the program + * + * If openssl *is* available, this function just adds more entropy + **/ +int +ldns_init_random(FILE *fd, unsigned int size) +{ + /* if fp is given, seed srandom with data from file + otherwise use /dev/urandom */ + FILE *rand_f; + uint8_t *seed; + size_t read = 0; + unsigned int seed_i; + struct timeval tv; + + /* we'll need at least sizeof(unsigned int) bytes for the + standard prng seed */ + if (size < (unsigned int) sizeof(seed_i)){ + size = (unsigned int) sizeof(seed_i); + } + + seed = LDNS_XMALLOC(uint8_t, size); + if(!seed) { + return 1; + } + + if (!fd) { + if ((rand_f = fopen("/dev/urandom", "r")) == NULL) { + /* no readable /dev/urandom, try /dev/random */ + if ((rand_f = fopen("/dev/random", "r")) == NULL) { + /* no readable /dev/random either, and no entropy + source given. we'll have to improvise */ + for (read = 0; read < size; read++) { + gettimeofday(&tv, NULL); + seed[read] = (uint8_t) (tv.tv_usec % 256); + } + } else { + read = fread(seed, 1, size, rand_f); + } + } else { + read = fread(seed, 1, size, rand_f); + } + } else { + rand_f = fd; + read = fread(seed, 1, size, rand_f); + } + + if (read < size) { + LDNS_FREE(seed); + return 1; + } else { +#ifdef HAVE_SSL + /* Seed the OpenSSL prng (most systems have it seeded + automatically, in that case this call just adds entropy */ + RAND_seed(seed, (int) size); +#else + /* Seed the standard prng, only uses the first + * unsigned sizeof(unsiged int) bytes found in the entropy pool + */ + memcpy(&seed_i, seed, sizeof(seed_i)); + srandom(seed_i); +#endif + LDNS_FREE(seed); + } + + if (!fd) { + if (rand_f) fclose(rand_f); + } + + return 0; +} + +/** + * Get random number. + * + */ +uint16_t +ldns_get_random(void) +{ + uint16_t rid = 0; +#ifdef HAVE_SSL + if (RAND_bytes((unsigned char*)&rid, 2) != 1) { + rid = (uint16_t) random(); + } +#else + rid = (uint16_t) random(); +#endif + return rid; +} + +/* + * BubbleBabble code taken from OpenSSH + * Copyright (c) 2001 Carsten Raskgaard. All rights reserved. + */ +char * +ldns_bubblebabble(uint8_t *data, size_t len) +{ + char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' }; + char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm', + 'n', 'p', 'r', 's', 't', 'v', 'z', 'x' }; + size_t i, j = 0, rounds, seed = 1; + char *retval; + + rounds = (len / 2) + 1; + retval = LDNS_XMALLOC(char, rounds * 6); + if(!retval) return NULL; + retval[j++] = 'x'; + for (i = 0; i < rounds; i++) { + size_t idx0, idx1, idx2, idx3, idx4; + if ((i + 1 < rounds) || (len % 2 != 0)) { + idx0 = (((((size_t)(data[2 * i])) >> 6) & 3) + + seed) % 6; + idx1 = (((size_t)(data[2 * i])) >> 2) & 15; + idx2 = ((((size_t)(data[2 * i])) & 3) + + (seed / 6)) % 6; + retval[j++] = vowels[idx0]; + retval[j++] = consonants[idx1]; + retval[j++] = vowels[idx2]; + if ((i + 1) < rounds) { + idx3 = (((size_t)(data[(2 * i) + 1])) >> 4) & 15; + idx4 = (((size_t)(data[(2 * i) + 1]))) & 15; + retval[j++] = consonants[idx3]; + retval[j++] = '-'; + retval[j++] = consonants[idx4]; + seed = ((seed * 5) + + ((((size_t)(data[2 * i])) * 7) + + ((size_t)(data[(2 * i) + 1])))) % 36; + } + } else { + idx0 = seed % 6; + idx1 = 16; + idx2 = seed / 6; + retval[j++] = vowels[idx0]; + retval[j++] = consonants[idx1]; + retval[j++] = vowels[idx2]; + } + } + retval[j++] = 'x'; + retval[j++] = '\0'; + return retval; +} diff --git a/wire2host.c b/wire2host.c new file mode 100644 index 00000000000..e87fcdf5df6 --- /dev/null +++ b/wire2host.c @@ -0,0 +1,456 @@ +/* + * wire2host.c + * + * conversion routines from the wire to the host + * format. + * This will usually just a re-ordering of the + * data (as we store it in network format) + * + * a Net::DNS like library for C + * + * (c) NLnet Labs, 2004-2006 + * + * See the file LICENSE for the license + */ + + +#include + +#include +/*#include */ + +#include +#include + + + +/* + * Set of macro's to deal with the dns message header as specified + * in RFC1035 in portable way. + * + */ + +/* + * + * 1 1 1 1 1 1 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | ID | + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * |QR| Opcode |AA|TC|RD|RA| Z|AD|CD| RCODE | + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | QDCOUNT | + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | ANCOUNT | + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | NSCOUNT | + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * | ARCOUNT | + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * + */ + + +/* allocates memory to *dname! */ +ldns_status +ldns_wire2dname(ldns_rdf **dname, const uint8_t *wire, size_t max, size_t *pos) +{ + uint8_t label_size; + uint16_t pointer_target; + uint8_t pointer_target_buf[2]; + size_t dname_pos = 0; + size_t uncompressed_length = 0; + size_t compression_pos = 0; + uint8_t tmp_dname[LDNS_MAX_DOMAINLEN]; + unsigned int pointer_count = 0; + + if (*pos >= max) { + return LDNS_STATUS_PACKET_OVERFLOW; + } + + label_size = wire[*pos]; + while (label_size > 0) { + /* compression */ + while (label_size >= 192) { + if (compression_pos == 0) { + compression_pos = *pos + 2; + } + + pointer_count++; + + /* remove first two bits */ + if (*pos + 2 > max) { + return LDNS_STATUS_PACKET_OVERFLOW; + } + pointer_target_buf[0] = wire[*pos] & 63; + pointer_target_buf[1] = wire[*pos + 1]; + pointer_target = ldns_read_uint16(pointer_target_buf); + + if (pointer_target == 0) { + return LDNS_STATUS_INVALID_POINTER; + } else if (pointer_target >= max) { + return LDNS_STATUS_INVALID_POINTER; + } else if (pointer_count > LDNS_MAX_POINTERS) { + return LDNS_STATUS_INVALID_POINTER; + } + *pos = pointer_target; + label_size = wire[*pos]; + } + if(label_size == 0) + break; /* break from pointer to 0 byte */ + if (label_size > LDNS_MAX_LABELLEN) { + return LDNS_STATUS_LABEL_OVERFLOW; + } + if (*pos + 1 + label_size > max) { + return LDNS_STATUS_LABEL_OVERFLOW; + } + + /* check space for labelcount itself */ + if (dname_pos + 1 > LDNS_MAX_DOMAINLEN) { + return LDNS_STATUS_DOMAINNAME_OVERFLOW; + } + tmp_dname[dname_pos] = label_size; + if (label_size > 0) { + dname_pos++; + } + *pos = *pos + 1; + if (dname_pos + label_size > LDNS_MAX_DOMAINLEN) { + return LDNS_STATUS_DOMAINNAME_OVERFLOW; + } + memcpy(&tmp_dname[dname_pos], &wire[*pos], label_size); + uncompressed_length += label_size + 1; + dname_pos += label_size; + *pos = *pos + label_size; + + if (*pos < max) { + label_size = wire[*pos]; + } + } + + if (compression_pos > 0) { + *pos = compression_pos; + } else { + *pos = *pos + 1; + } + + if (dname_pos >= LDNS_MAX_DOMAINLEN) { + return LDNS_STATUS_DOMAINNAME_OVERFLOW; + } + + tmp_dname[dname_pos] = 0; + dname_pos++; + + *dname = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, + (uint16_t) dname_pos, tmp_dname); + if (!*dname) { + return LDNS_STATUS_MEM_ERR; + } + return LDNS_STATUS_OK; +} + +/* maybe make this a goto error so data can be freed or something/ */ +#define LDNS_STATUS_CHECK_RETURN(st) {if (st != LDNS_STATUS_OK) { return st; }} +#define LDNS_STATUS_CHECK_GOTO(st, label) {if (st != LDNS_STATUS_OK) { /*printf("STG %s:%d: status code %d\n", __FILE__, __LINE__, st);*/ goto label; }} + +ldns_status +ldns_wire2rdf(ldns_rr *rr, const uint8_t *wire, size_t max, size_t *pos) +{ + size_t end; + size_t cur_rdf_length; + uint8_t rdf_index; + uint8_t *data; + uint16_t rd_length; + ldns_rdf *cur_rdf = NULL; + ldns_rdf_type cur_rdf_type; + const ldns_rr_descriptor *descriptor = ldns_rr_descript(ldns_rr_get_type(rr)); + ldns_status status; + + if (*pos + 2 > max) { + return LDNS_STATUS_PACKET_OVERFLOW; + } + + rd_length = ldns_read_uint16(&wire[*pos]); + *pos = *pos + 2; + + if (*pos + rd_length > max) { + return LDNS_STATUS_PACKET_OVERFLOW; + } + + end = *pos + (size_t) rd_length; + + for (rdf_index = 0; + rdf_index < ldns_rr_descriptor_maximum(descriptor); rdf_index++) { + if (*pos >= end) { + break; + } + cur_rdf_length = 0; + + cur_rdf_type = ldns_rr_descriptor_field_type(descriptor, rdf_index); + /* handle special cases immediately, set length + for fixed length rdata and do them below */ + switch (cur_rdf_type) { + case LDNS_RDF_TYPE_DNAME: + status = ldns_wire2dname(&cur_rdf, wire, max, pos); + LDNS_STATUS_CHECK_RETURN(status); + break; + case LDNS_RDF_TYPE_CLASS: + case LDNS_RDF_TYPE_ALG: + case LDNS_RDF_TYPE_INT8: + cur_rdf_length = LDNS_RDF_SIZE_BYTE; + break; + case LDNS_RDF_TYPE_TYPE: + case LDNS_RDF_TYPE_INT16: + case LDNS_RDF_TYPE_CERT_ALG: + cur_rdf_length = LDNS_RDF_SIZE_WORD; + break; + case LDNS_RDF_TYPE_TIME: + case LDNS_RDF_TYPE_INT32: + case LDNS_RDF_TYPE_A: + case LDNS_RDF_TYPE_PERIOD: + cur_rdf_length = LDNS_RDF_SIZE_DOUBLEWORD; + break; + case LDNS_RDF_TYPE_TSIGTIME: + cur_rdf_length = LDNS_RDF_SIZE_6BYTES; + break; + case LDNS_RDF_TYPE_AAAA: + cur_rdf_length = LDNS_RDF_SIZE_16BYTES; + break; + case LDNS_RDF_TYPE_STR: + case LDNS_RDF_TYPE_NSEC3_SALT: + /* len is stored in first byte + * it should be in the rdf too, so just + * copy len+1 from this position + */ + cur_rdf_length = ((size_t) wire[*pos]) + 1; + break; + case LDNS_RDF_TYPE_INT16_DATA: + cur_rdf_length = (size_t) ldns_read_uint16(&wire[*pos]) + 2; + break; + case LDNS_RDF_TYPE_B32_EXT: + case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER: + /* length is stored in first byte */ + cur_rdf_length = ((size_t) wire[*pos]) + 1; + break; + case LDNS_RDF_TYPE_APL: + case LDNS_RDF_TYPE_B64: + case LDNS_RDF_TYPE_HEX: + case LDNS_RDF_TYPE_NSEC: + case LDNS_RDF_TYPE_UNKNOWN: + case LDNS_RDF_TYPE_SERVICE: + case LDNS_RDF_TYPE_LOC: + case LDNS_RDF_TYPE_WKS: + case LDNS_RDF_TYPE_NSAP: + case LDNS_RDF_TYPE_ATMA: + case LDNS_RDF_TYPE_IPSECKEY: + case LDNS_RDF_TYPE_TSIG: + case LDNS_RDF_TYPE_NONE: + /* + * Read to end of rr rdata + */ + cur_rdf_length = end - *pos; + break; + } + + /* fixed length rdata */ + if (cur_rdf_length > 0) { + if (cur_rdf_length + *pos > end) { + return LDNS_STATUS_PACKET_OVERFLOW; + } + data = LDNS_XMALLOC(uint8_t, rd_length); + if (!data) { + return LDNS_STATUS_MEM_ERR; + } + memcpy(data, &wire[*pos], cur_rdf_length); + + cur_rdf = ldns_rdf_new(cur_rdf_type, cur_rdf_length, data); + *pos = *pos + cur_rdf_length; + } + + if (cur_rdf) { + ldns_rr_push_rdf(rr, cur_rdf); + cur_rdf = NULL; + } + } + + return LDNS_STATUS_OK; +} + + +/* TODO: + can *pos be incremented at READ_INT? or maybe use something like + RR_CLASS(wire)? + uhhm Jelte?? +*/ +ldns_status +ldns_wire2rr(ldns_rr **rr_p, const uint8_t *wire, size_t max, + size_t *pos, ldns_pkt_section section) +{ + ldns_rdf *owner = NULL; + ldns_rr *rr = ldns_rr_new(); + ldns_status status; + + status = ldns_wire2dname(&owner, wire, max, pos); + LDNS_STATUS_CHECK_GOTO(status, status_error); + + ldns_rr_set_owner(rr, owner); + + if (*pos + 4 > max) { + status = LDNS_STATUS_PACKET_OVERFLOW; + goto status_error; + } + + ldns_rr_set_type(rr, ldns_read_uint16(&wire[*pos])); + *pos = *pos + 2; + + ldns_rr_set_class(rr, ldns_read_uint16(&wire[*pos])); + *pos = *pos + 2; + + if (section != LDNS_SECTION_QUESTION) { + if (*pos + 4 > max) { + status = LDNS_STATUS_PACKET_OVERFLOW; + goto status_error; + } + ldns_rr_set_ttl(rr, ldns_read_uint32(&wire[*pos])); + + *pos = *pos + 4; + status = ldns_wire2rdf(rr, wire, max, pos); + + LDNS_STATUS_CHECK_GOTO(status, status_error); + ldns_rr_set_question(rr, false); + } else { + ldns_rr_set_question(rr, true); + } + + *rr_p = rr; + return LDNS_STATUS_OK; + +status_error: + ldns_rr_free(rr); + return status; +} + +static ldns_status +ldns_wire2pkt_hdr(ldns_pkt *packet, const uint8_t *wire, size_t max, size_t *pos) +{ + if (*pos + LDNS_HEADER_SIZE > max) { + return LDNS_STATUS_WIRE_INCOMPLETE_HEADER; + } else { + ldns_pkt_set_id(packet, LDNS_ID_WIRE(wire)); + ldns_pkt_set_qr(packet, LDNS_QR_WIRE(wire)); + ldns_pkt_set_opcode(packet, LDNS_OPCODE_WIRE(wire)); + ldns_pkt_set_aa(packet, LDNS_AA_WIRE(wire)); + ldns_pkt_set_tc(packet, LDNS_TC_WIRE(wire)); + ldns_pkt_set_rd(packet, LDNS_RD_WIRE(wire)); + ldns_pkt_set_ra(packet, LDNS_RA_WIRE(wire)); + ldns_pkt_set_ad(packet, LDNS_AD_WIRE(wire)); + ldns_pkt_set_cd(packet, LDNS_CD_WIRE(wire)); + ldns_pkt_set_rcode(packet, LDNS_RCODE_WIRE(wire)); + + ldns_pkt_set_qdcount(packet, LDNS_QDCOUNT(wire)); + ldns_pkt_set_ancount(packet, LDNS_ANCOUNT(wire)); + ldns_pkt_set_nscount(packet, LDNS_NSCOUNT(wire)); + ldns_pkt_set_arcount(packet, LDNS_ARCOUNT(wire)); + + *pos += LDNS_HEADER_SIZE; + + return LDNS_STATUS_OK; + } +} + +ldns_status +ldns_buffer2pkt_wire(ldns_pkt **packet, ldns_buffer *buffer) +{ + /* lazy */ + return ldns_wire2pkt(packet, ldns_buffer_begin(buffer), + ldns_buffer_limit(buffer)); + +} + +ldns_status +ldns_wire2pkt(ldns_pkt **packet_p, const uint8_t *wire, size_t max) +{ + size_t pos = 0; + uint16_t i; + ldns_rr *rr; + ldns_pkt *packet = ldns_pkt_new(); + ldns_status status = LDNS_STATUS_OK; + int have_edns = 0; + + uint8_t data[4]; + + status = ldns_wire2pkt_hdr(packet, wire, max, &pos); + LDNS_STATUS_CHECK_GOTO(status, status_error); + + for (i = 0; i < ldns_pkt_qdcount(packet); i++) { + + status = ldns_wire2rr(&rr, wire, max, &pos, LDNS_SECTION_QUESTION); + if (status == LDNS_STATUS_PACKET_OVERFLOW) { + status = LDNS_STATUS_WIRE_INCOMPLETE_QUESTION; + } + LDNS_STATUS_CHECK_GOTO(status, status_error); + if (!ldns_rr_list_push_rr(ldns_pkt_question(packet), rr)) { + ldns_pkt_free(packet); + return LDNS_STATUS_INTERNAL_ERR; + } + } + for (i = 0; i < ldns_pkt_ancount(packet); i++) { + status = ldns_wire2rr(&rr, wire, max, &pos, LDNS_SECTION_ANSWER); + if (status == LDNS_STATUS_PACKET_OVERFLOW) { + status = LDNS_STATUS_WIRE_INCOMPLETE_ANSWER; + } + LDNS_STATUS_CHECK_GOTO(status, status_error); + if (!ldns_rr_list_push_rr(ldns_pkt_answer(packet), rr)) { + ldns_pkt_free(packet); + return LDNS_STATUS_INTERNAL_ERR; + } + } + for (i = 0; i < ldns_pkt_nscount(packet); i++) { + status = ldns_wire2rr(&rr, wire, max, &pos, LDNS_SECTION_AUTHORITY); + if (status == LDNS_STATUS_PACKET_OVERFLOW) { + status = LDNS_STATUS_WIRE_INCOMPLETE_AUTHORITY; + } + LDNS_STATUS_CHECK_GOTO(status, status_error); + if (!ldns_rr_list_push_rr(ldns_pkt_authority(packet), rr)) { + ldns_pkt_free(packet); + return LDNS_STATUS_INTERNAL_ERR; + } + } + for (i = 0; i < ldns_pkt_arcount(packet); i++) { + status = ldns_wire2rr(&rr, wire, max, &pos, LDNS_SECTION_ADDITIONAL); + if (status == LDNS_STATUS_PACKET_OVERFLOW) { + status = LDNS_STATUS_WIRE_INCOMPLETE_ADDITIONAL; + } + LDNS_STATUS_CHECK_GOTO(status, status_error); + + if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_OPT) { + ldns_pkt_set_edns_udp_size(packet, ldns_rr_get_class(rr)); + ldns_write_uint32(data, ldns_rr_ttl(rr)); + ldns_pkt_set_edns_extended_rcode(packet, data[0]); + ldns_pkt_set_edns_version(packet, data[1]); + ldns_pkt_set_edns_z(packet, ldns_read_uint16(&data[2])); + /* edns might not have rdfs */ + if (ldns_rr_rdf(rr, 0)) { + ldns_pkt_set_edns_data(packet, ldns_rdf_clone(ldns_rr_rdf(rr, 0))); + } + ldns_rr_free(rr); + have_edns += 1; + } else if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_TSIG) { + ldns_pkt_set_tsig(packet, rr); + ldns_pkt_set_arcount(packet, ldns_pkt_arcount(packet) - 1); + } else if (!ldns_rr_list_push_rr(ldns_pkt_additional(packet), rr)) { + ldns_pkt_free(packet); + return LDNS_STATUS_INTERNAL_ERR; + } + } + ldns_pkt_set_size(packet, max); + if(have_edns) + ldns_pkt_set_arcount(packet, ldns_pkt_arcount(packet) + - have_edns); + + *packet_p = packet; + return status; + +status_error: + ldns_pkt_free(packet); + return status; +} diff --git a/zone.c b/zone.c new file mode 100644 index 00000000000..0616a141b55 --- /dev/null +++ b/zone.c @@ -0,0 +1,431 @@ +/* zone.c + * + * Functions for ldns_zone structure + * a Net::DNS like library for C + * + * (c) NLnet Labs, 2005-2006 + * See the file LICENSE for the license + */ +#include + +#include + +#include +#include + +ldns_rr * +ldns_zone_soa(const ldns_zone *z) +{ + return z->_soa; +} + +size_t +ldns_zone_rr_count(const ldns_zone *z) +{ + return ldns_rr_list_rr_count(z->_rrs); +} + +void +ldns_zone_set_soa(ldns_zone *z, ldns_rr *soa) +{ + z->_soa = soa; +} + +ldns_rr_list * +ldns_zone_rrs(const ldns_zone *z) +{ + return z->_rrs; +} + +void +ldns_zone_set_rrs(ldns_zone *z, ldns_rr_list *rrlist) +{ + z->_rrs = rrlist; +} + +bool +ldns_zone_push_rr_list(ldns_zone *z, ldns_rr_list *list) +{ + return ldns_rr_list_cat(ldns_zone_rrs(z), list); + +} + +bool +ldns_zone_push_rr(ldns_zone *z, ldns_rr *rr) +{ + return ldns_rr_list_push_rr( ldns_zone_rrs(z), rr); +} + +/* return a clone of the given rr list, without the glue records + * rr list should be the complete zone + * if present, stripped records are added to the list *glue_records + */ +ldns_rr_list * +ldns_zone_strip_glue_rrs(const ldns_rdf *zone_name, const ldns_rr_list *rrs, ldns_rr_list *glue_rrs) +{ + ldns_rr_list *new_list; + + /* when do we find glue? It means we find an IP address + * (AAAA/A) for a nameserver listed in the zone + * + * Alg used here: + * first find all the zonecuts (NS records) + * find all the AAAA or A records (can be done it the + * above loop). + * + * Check if the aaaa/a list are subdomains under the + * NS domains. + * If yes -> glue, if no -> not glue + */ + + ldns_rr_list *zone_cuts; + ldns_rr_list *addr; + ldns_rr *r, *ns, *a; + ldns_rdf *dname_a, *ns_owner; + uint16_t i,j; + + new_list = NULL; + zone_cuts = NULL; + addr = NULL; + + new_list = ldns_rr_list_new(); + if (!new_list) goto memory_error; + zone_cuts = ldns_rr_list_new(); + if (!zone_cuts) goto memory_error; + addr = ldns_rr_list_new(); + if (!addr) goto memory_error; + + for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) { + r = ldns_rr_list_rr(rrs, i); + if (ldns_rr_get_type(r) == LDNS_RR_TYPE_A || + ldns_rr_get_type(r) == LDNS_RR_TYPE_AAAA) { + /* possibly glue */ + if (!ldns_rr_list_push_rr(addr, r)) goto memory_error; + continue; + } + if (ldns_rr_get_type(r) == LDNS_RR_TYPE_NS) { + /* multiple zones will end up here - + * for now; not a problem + */ + /* don't add NS records for the current zone itself */ + if (ldns_rdf_compare(ldns_rr_owner(r), + zone_name) != 0) { + if (!ldns_rr_list_push_rr(zone_cuts, r)) goto memory_error; + } + continue; + } + } + + /* will sorting make it quicker ?? */ + for(i = 0; i < ldns_rr_list_rr_count(zone_cuts); i++) { + ns = ldns_rr_list_rr(zone_cuts, i); + ns_owner = ldns_rr_owner(ns); + for(j = 0; j < ldns_rr_list_rr_count(addr); j++) { + a = ldns_rr_list_rr(addr, j); + dname_a = ldns_rr_owner(a); + + if (ldns_dname_is_subdomain(dname_a, ns_owner)) { + /* GLUE! */ + if (glue_rrs) { + if (!ldns_rr_list_push_rr(glue_rrs, a)) goto memory_error; + } + break; + } else { + if (!ldns_rr_list_push_rr(new_list, a)) goto memory_error; + } + } + } + + ldns_rr_list_free(addr); + ldns_rr_list_free(zone_cuts); + + return new_list; + +memory_error: + if (new_list) { + ldns_rr_list_free(new_list); + } + if (zone_cuts) { + ldns_rr_list_free(zone_cuts); + } + if (addr) { + ldns_rr_list_free(addr); + } + return NULL; +} + +/* + * Get the list of glue records in a zone + * XXX: there should be a way for this to return error, other than NULL, + * since NULL is a valid return + */ +ldns_rr_list * +ldns_zone_glue_rr_list(const ldns_zone *z) +{ + /* when do we find glue? It means we find an IP address + * (AAAA/A) for a nameserver listed in the zone + * + * Alg used here: + * first find all the zonecuts (NS records) + * find all the AAAA or A records (can be done it the + * above loop). + * + * Check if the aaaa/a list are subdomains under the + * NS domains. + * If yes -> glue, if no -> not glue + */ + + ldns_rr_list *zone_cuts; + ldns_rr_list *addr; + ldns_rr_list *glue; + ldns_rr *r, *ns, *a; + ldns_rdf *dname_a, *ns_owner; + size_t i,j; + + zone_cuts = NULL; + addr = NULL; + glue = NULL; + + /* we cannot determine glue in a 'zone' without a SOA */ + if (!ldns_zone_soa(z)) { + return NULL; + } + + zone_cuts = ldns_rr_list_new(); + if (!zone_cuts) goto memory_error; + addr = ldns_rr_list_new(); + if (!addr) goto memory_error; + glue = ldns_rr_list_new(); + if (!glue) goto memory_error; + + for(i = 0; i < ldns_zone_rr_count(z); i++) { + r = ldns_rr_list_rr(ldns_zone_rrs(z), i); + if (ldns_rr_get_type(r) == LDNS_RR_TYPE_A || + ldns_rr_get_type(r) == LDNS_RR_TYPE_AAAA) { + /* possibly glue */ + if (!ldns_rr_list_push_rr(addr, r)) goto memory_error; + continue; + } + if (ldns_rr_get_type(r) == LDNS_RR_TYPE_NS) { + /* multiple zones will end up here - + * for now; not a problem + */ + /* don't add NS records for the current zone itself */ + if (ldns_rdf_compare(ldns_rr_owner(r), + ldns_rr_owner(ldns_zone_soa(z))) != 0) { + if (!ldns_rr_list_push_rr(zone_cuts, r)) goto memory_error; + } + continue; + } + } + + /* will sorting make it quicker ?? */ + for(i = 0; i < ldns_rr_list_rr_count(zone_cuts); i++) { + ns = ldns_rr_list_rr(zone_cuts, i); + ns_owner = ldns_rr_owner(ns); + + for(j = 0; j < ldns_rr_list_rr_count(addr); j++) { + a = ldns_rr_list_rr(addr, j); + dname_a = ldns_rr_owner(a); + + if (ldns_dname_is_subdomain(dname_a, ns_owner) || + ldns_dname_compare(dname_a, ns_owner) == 0) { + /* GLUE! */ + if (!ldns_rr_list_push_rr(glue, a)) goto memory_error; + } + } + } + + ldns_rr_list_free(addr); + ldns_rr_list_free(zone_cuts); + + if (ldns_rr_list_rr_count(glue) == 0) { + ldns_rr_list_free(glue); + return NULL; + } else { + return glue; + } + +memory_error: + if (zone_cuts) { + LDNS_FREE(zone_cuts); + } + if (addr) { + ldns_rr_list_free(addr); + } + if (glue) { + ldns_rr_list_free(glue); + } + return NULL; +} + +ldns_zone * +ldns_zone_new(void) +{ + ldns_zone *z; + + z = LDNS_MALLOC(ldns_zone); + if (!z) { + return NULL; + } + + z->_rrs = ldns_rr_list_new(); + if (!z->_rrs) { + LDNS_FREE(z); + return NULL; + } + ldns_zone_set_soa(z, NULL); + return z; +} + +/* we regocnize: + * $TTL, $ORIGIN + */ +ldns_status +ldns_zone_new_frm_fp(ldns_zone **z, FILE *fp, ldns_rdf *origin, uint32_t ttl, ldns_rr_class c) +{ + return ldns_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL); +} + +/* XXX: class is never used */ +ldns_status +ldns_zone_new_frm_fp_l(ldns_zone **z, FILE *fp, ldns_rdf *origin, uint32_t ttl, + ldns_rr_class ATTR_UNUSED(c), int *line_nr) +{ + ldns_zone *newzone; + ldns_rr *rr; + uint32_t my_ttl; + ldns_rdf *my_origin; + ldns_rdf *my_prev; + bool soa_seen = false; /* 2 soa are an error */ + ldns_status s; + ldns_status ret; + + /* most cases of error are memory problems */ + ret = LDNS_STATUS_MEM_ERR; + + newzone = NULL; + my_origin = NULL; + my_prev = NULL; + + my_ttl = ttl; + + if (origin) { + my_origin = ldns_rdf_clone(origin); + if (!my_origin) goto error; + /* also set the prev */ + my_prev = ldns_rdf_clone(origin); + if (!my_prev) goto error; + } + + newzone = ldns_zone_new(); + if (!newzone) goto error; + + while(!feof(fp)) { + s = ldns_rr_new_frm_fp_l(&rr, fp, &my_ttl, &my_origin, &my_prev, line_nr); + switch (s) { + case LDNS_STATUS_OK: + if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) { + if (soa_seen) { + /* second SOA + * just skip, maybe we want to say + * something??? */ + ldns_rr_free(rr); + continue; + } + soa_seen = true; + ldns_zone_set_soa(newzone, rr); + /* set origin to soa if not specified */ + if (!my_origin) { + my_origin = ldns_rdf_clone(ldns_rr_owner(rr)); + } + continue; + } + + /* a normal RR - as sofar the DNS is normal */ + if (!ldns_zone_push_rr(newzone, rr)) goto error; + + case LDNS_STATUS_SYNTAX_EMPTY: + /* empty line was seen */ + case LDNS_STATUS_SYNTAX_TTL: + /* the function set the ttl */ + break; + case LDNS_STATUS_SYNTAX_ORIGIN: + /* the function set the origin */ + break; + case LDNS_STATUS_SYNTAX_INCLUDE: + ret = LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL; + break; + default: + ret = s; + goto error; + } + } + + if (my_origin) { + ldns_rdf_deep_free(my_origin); + } + if (my_prev) { + ldns_rdf_deep_free(my_prev); + } + if (z) { + *z = newzone; + } else { + ldns_zone_free(newzone); + } + + return LDNS_STATUS_OK; + +error: + if (my_origin) { + ldns_rdf_deep_free(my_origin); + } + if (my_prev) { + ldns_rdf_deep_free(my_prev); + } + if (newzone) { + ldns_zone_free(newzone); + } + return ret; +} + +void +ldns_zone_sort(ldns_zone *zone) +{ + ldns_rr_list *zrr; + assert(zone != NULL); + + zrr = ldns_zone_rrs(zone); + ldns_rr_list_sort(zrr); +} + +#if 0 +/** + * ixfr function. Work on a ldns_zone and remove and add + * the rrs from the rrlist + * \param[in] z the zone to work on + * \param[in] del rr_list to remove from the zone + * \param[in] add rr_list to add to the zone + * \return Tja, wat zouden we eens returnen TODO + */ +void +ldns_zone_ixfr_del_add(ldns_zone *z, ldns_rr_list *del, ldns_rr_list *add) +{ + +} +#endif + +void +ldns_zone_free(ldns_zone *zone) +{ + ldns_rr_list_free(zone->_rrs); + LDNS_FREE(zone); +} + +void +ldns_zone_deep_free(ldns_zone *zone) +{ + ldns_rr_free(zone->_soa); + ldns_rr_list_deep_free(zone->_rrs); + LDNS_FREE(zone); +} From afb79913ce00d885b8b43f7478e1e054edadb567 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Wed, 4 Jul 2012 14:24:26 +0000 Subject: [PATCH 0002/1476] import unbound 1.4.17 --- LICENSE | 30 + Makefile.in | 1193 + README | 10 + ac_pkg_swig.m4 | 122 + aclocal.m4 | 8444 ++ acx_nlnetlabs.m4 | 1370 + acx_pthread.m4 | 280 + acx_python.m4 | 200 + compat/ctime_r.c | 42 + compat/fake-rfc2553.c | 227 + compat/fake-rfc2553.h | 174 + compat/gmtime_r.c | 107 + compat/inet_aton.c | 182 + compat/inet_ntop.c | 218 + compat/inet_pton.c | 230 + compat/malloc.c | 19 + compat/memcmp.c | 25 + compat/memcmp.h | 16 + compat/memmove.c | 43 + compat/snprintf.c | 792 + compat/strlcpy.c | 57 + compat/strptime.c | 345 + config.guess | 1501 + config.h.in | 899 + config.sub | 1705 + configure | 20265 ++++ configure.ac | 1197 + contrib/README | 17 + contrib/build-unbound-localzone-from-hosts.pl | 67 + contrib/parseunbound.pl | 140 + contrib/rc_d_unbound | 25 + contrib/selinux/unbound.fc | 4 + contrib/selinux/unbound.te | 42 + contrib/unbound-host.nagios.patch | 134 + contrib/unbound.init | 139 + contrib/unbound.init_fedora | 119 + contrib/unbound.plist | 42 + contrib/unbound.spec | 112 + contrib/unbound.spec_fedora | 440 + contrib/unbound_cacti.tar.gz | Bin 0 -> 71269 bytes contrib/unbound_munin_ | 555 + contrib/update-anchor.sh | 158 + contrib/validation-reporter.sh | 117 + daemon/acl_list.c | 176 + daemon/acl_list.h | 125 + daemon/cachedump.c | 986 + daemon/cachedump.h | 107 + daemon/daemon.c | 589 + daemon/daemon.h | 150 + daemon/remote.c | 2179 + daemon/remote.h | 192 + daemon/stats.c | 303 + daemon/stats.h | 235 + daemon/unbound.c | 748 + daemon/worker.c | 1377 + daemon/worker.h | 234 + doc/CREDITS | 21 + doc/Changelog | 4780 + doc/FEATURES | 100 + doc/LICENSE | 30 + doc/README | 150 + doc/README.svn | 17 + doc/README.tests | 24 + doc/TODO | 76 + doc/control_proto_spec.txt | 70 + doc/example.conf.in | 536 + doc/ietf67-design-02.odp | Bin 0 -> 331530 bytes doc/ietf67-design-02.pdf | Bin 0 -> 630129 bytes doc/libunbound.3.in | 383 + doc/requirements.txt | 294 + doc/unbound-anchor.8.in | 174 + doc/unbound-checkconf.8.in | 49 + doc/unbound-control.8.in | 450 + doc/unbound-host.1 | 116 + doc/unbound.8.in | 51 + doc/unbound.conf.5.in | 1094 + doc/unbound.doxygen | 1648 + install-sh | 520 + iterator/iter_delegpt.c | 640 + iterator/iter_delegpt.h | 411 + iterator/iter_donotq.c | 153 + iterator/iter_donotq.h | 101 + iterator/iter_fwd.c | 508 + iterator/iter_fwd.h | 189 + iterator/iter_hints.c | 534 + iterator/iter_hints.h | 161 + iterator/iter_priv.c | 263 + iterator/iter_priv.h | 110 + iterator/iter_resptype.c | 286 + iterator/iter_resptype.h | 127 + iterator/iter_scrub.c | 751 + iterator/iter_scrub.h | 69 + iterator/iter_utils.c | 1034 + iterator/iter_utils.h | 334 + iterator/iterator.c | 2897 + iterator/iterator.h | 375 + libunbound/context.c | 400 + libunbound/context.h | 345 + libunbound/libunbound.c | 1124 + libunbound/libworker.c | 920 + libunbound/libworker.h | 170 + libunbound/python/LICENSE | 28 + libunbound/python/Makefile | 75 + libunbound/python/doc/_static/readme | 1 + libunbound/python/doc/conf.py | 181 + libunbound/python/doc/examples/example1a.rst | 26 + libunbound/python/doc/examples/example1b.rst | 33 + libunbound/python/doc/examples/example2.rst | 41 + libunbound/python/doc/examples/example3.rst | 36 + libunbound/python/doc/examples/example4.rst | 34 + libunbound/python/doc/examples/example5.rst | 29 + libunbound/python/doc/examples/example6-1.py | 27 + libunbound/python/doc/examples/example6.rst | 11 + libunbound/python/doc/examples/example7-1.py | 17 + libunbound/python/doc/examples/example7-2.py | 16 + libunbound/python/doc/examples/example7.rst | 18 + libunbound/python/doc/examples/example8-1.py | 31 + libunbound/python/doc/examples/example8.rst | 28 + libunbound/python/doc/examples/index.rst | 14 + libunbound/python/doc/index.rst | 27 + libunbound/python/doc/install.rst | 31 + libunbound/python/doc/intro.rst | 39 + libunbound/python/doc/modules/unbound.rst | 167 + libunbound/python/examples/async-lookup.py | 56 + libunbound/python/examples/dns-lookup.py | 44 + libunbound/python/examples/dnssec-valid.py | 59 + libunbound/python/examples/dnssec_test.py | 35 + libunbound/python/examples/example8-1.py | 61 + libunbound/python/examples/idn-lookup.py | 62 + libunbound/python/examples/mx-lookup.py | 53 + libunbound/python/examples/ns-lookup.py | 47 + libunbound/python/examples/reverse-lookup.py | 43 + libunbound/python/libunbound.i | 941 + libunbound/ubsyms.def | 29 + libunbound/unbound.h | 556 + ltmain.sh | 9636 ++ pythonmod/LICENSE | 28 + pythonmod/Makefile | 58 + pythonmod/doc/_static/readme | 1 + pythonmod/doc/conf.py | 179 + pythonmod/doc/examples/example0-1.py | 37 + pythonmod/doc/examples/example0.rst | 129 + pythonmod/doc/examples/example1.rst | 42 + pythonmod/doc/examples/example2.rst | 46 + pythonmod/doc/examples/example3.rst | 63 + pythonmod/doc/examples/example4.rst | 164 + pythonmod/doc/examples/index.rst | 15 + pythonmod/doc/index.rst | 34 + pythonmod/doc/install.rst | 59 + pythonmod/doc/modules/config.rst | 350 + pythonmod/doc/modules/env.rst | 412 + pythonmod/doc/modules/functions.rst | 120 + pythonmod/doc/modules/index.rst | 11 + pythonmod/doc/modules/struct.rst | 427 + pythonmod/doc/usecase.rst | 38 + pythonmod/examples/calc.py | 77 + pythonmod/examples/dict.py | 121 + pythonmod/examples/dict_data.txt | 6 + pythonmod/examples/log.py | 119 + pythonmod/examples/resgen.py | 73 + pythonmod/examples/resip.py | 96 + pythonmod/examples/resmod.py | 88 + pythonmod/interface.i | 889 + pythonmod/pythonmod.c | 383 + pythonmod/pythonmod.h | 68 + pythonmod/pythonmod_utils.c | 177 + pythonmod/pythonmod_utils.h | 89 + pythonmod/test-calc.conf | 18 + pythonmod/test-dict.conf | 18 + pythonmod/test-log.conf | 17 + pythonmod/test-resgen.conf | 18 + pythonmod/test-resip.conf | 18 + pythonmod/test-resmod.conf | 19 + pythonmod/ubmodule-msg.py | 156 + pythonmod/ubmodule-tst.py | 149 + services/cache/dns.c | 796 + services/cache/dns.h | 182 + services/cache/infra.c | 564 + services/cache/infra.h | 309 + services/cache/rrset.c | 416 + services/cache/rrset.h | 231 + services/listen_dnsport.c | 944 + services/listen_dnsport.h | 196 + services/localzone.c | 1353 + services/localzone.h | 318 + services/mesh.c | 1186 + services/mesh.h | 571 + services/modstack.c | 212 + services/modstack.h | 113 + services/outbound_list.c | 89 + services/outbound_list.h | 105 + services/outside_network.c | 1994 + services/outside_network.h | 538 + smallapp/unbound-anchor.c | 2165 + smallapp/unbound-checkconf.c | 517 + smallapp/unbound-control-setup.sh | 162 + smallapp/unbound-control.c | 426 + smallapp/unbound-host.c | 514 + smallapp/worker_cb.c | 242 + testcode/asynclook.c | 517 + testcode/checklocks.c | 834 + testcode/checklocks.h | 343 + testcode/delayer.c | 1185 + testcode/do-tests.sh | 61 + testcode/fake_event.c | 1413 + testcode/fake_event.h | 75 + testcode/harvest.c | 857 + testcode/ldns-testpkts.c | 881 + testcode/ldns-testpkts.h | 255 + testcode/lock_verify.c | 418 + testcode/memstats.c | 248 + testcode/mini_tpkg.sh | 128 + testcode/perf.c | 654 + testcode/petal.c | 618 + testcode/pktview.c | 201 + testcode/readhex.c | 83 + testcode/readhex.h | 52 + testcode/replay.c | 1026 + testcode/replay.h | 461 + testcode/signit.c | 250 + testcode/streamtcp.c | 417 + testcode/testbed.sh | 133 + testcode/testbed.txt | 38 + testcode/testbound.c | 445 + testcode/unitanchor.c | 136 + testcode/unitdname.c | 862 + testcode/unitlruhash.c | 499 + testcode/unitmain.c | 599 + testcode/unitmain.h | 76 + testcode/unitmsgparse.c | 624 + testcode/unitneg.c | 542 + testcode/unitregional.c | 244 + testcode/unitslabhash.c | 376 + testcode/unitverify.c | 531 + testdata/00-lint.tpkg | Bin 0 -> 530 bytes testdata/01-doc.tpkg | Bin 0 -> 902 bytes testdata/02-unittest.tpkg | Bin 0 -> 640 bytes testdata/03-testbound.tpkg | Bin 0 -> 1282 bytes testdata/04-checkconf.tpkg | Bin 0 -> 5127 bytes testdata/05-asynclook.tpkg | Bin 0 -> 1950 bytes testdata/06-ianaports.tpkg | Bin 0 -> 690 bytes testdata/07-confroot.tpkg | Bin 0 -> 1189 bytes testdata/08-host-lib.tpkg | Bin 0 -> 1908 bytes testdata/09-unbound-control.tpkg | Bin 0 -> 6961 bytes testdata/10-unbound-anchor.tpkg | Bin 0 -> 12318 bytes testdata/Kexample.com.+003+02854.ds | 1 + testdata/Kexample.com.+003+02854.key | 1 + testdata/Kexample.com.+003+02854.private | 7 + testdata/Kexample.com.+005+16486.ds | 1 + testdata/Kexample.com.+005+16486.key | 1 + testdata/Kexample.com.+005+16486.private | 10 + testdata/Kexample.com.+005+30899.ds | 1 + testdata/Kexample.com.+005+30899.key | 1 + testdata/Kexample.com.+005+30899.private | 10 + testdata/Kexample.com.+005+55582.ds | 1 + testdata/Kexample.com.+005+55582.key | 1 + testdata/Kexample.com.+005+55582.private | 10 + testdata/Kexample.com.+005+60946.ds | 1 + testdata/Kexample.com.+005+60946.key | 1 + testdata/Kexample.com.+005+60946.private | 10 + testdata/Kexample.com.+007+57024.ds | 1 + testdata/Kexample.com.+007+57024.key | 1 + testdata/Kexample.com.+007+57024.private | 10 + testdata/Kexample.com.+008+01443.ds | 1 + testdata/Kexample.com.+008+01443.key | 1 + testdata/Kexample.com.+008+01443.private | 10 + testdata/Kexample.com.+009+48886.ds | 1 + testdata/Kexample.com.+009+48886.key | 1 + testdata/Kexample.com.+009+48886.private | 10 + testdata/Kexample.com.+012+60385.ds | 1 + testdata/Kexample.com.+012+60385.key | 1 + testdata/Kexample.com.+012+60385.private | 3 + testdata/acl.rpl | 52 + testdata/autotrust_10key.rpl | 144 + testdata/autotrust_addpend_2exceed.rpl | 304 + testdata/autotrust_addpend_early.rpl | 240 + testdata/autotrust_addpend_nosign.rpl | 222 + testdata/autotrust_addpend_nosignnew.rpl | 223 + testdata/autotrust_addpend_once.rpl | 276 + testdata/autotrust_addpend_twice.rpl | 307 + testdata/autotrust_init.rpl | 181 + testdata/autotrust_init_ds.rpl | 180 + testdata/autotrust_init_fail.rpl | 179 + testdata/autotrust_init_failsig.rpl | 166 + testdata/autotrust_init_legacy.rpl | 84 + testdata/autotrust_init_sigs.rpl | 183 + testdata/autotrust_init_zsk.rpl | 180 + testdata/autotrust_missing.rpl | 318 + testdata/autotrust_missing_all.rpl | 316 + testdata/autotrust_missing_returns.rpl | 317 + testdata/autotrust_probefail.rpl | 163 + testdata/autotrust_probefailsig.rpl | 163 + testdata/autotrust_revoked_use.rpl | 403 + testdata/autotrust_revoked_with_invalid.rpl | 128 + testdata/autotrust_revtp.rpl | 148 + testdata/autotrust_revtp_read.rpl | 109 + testdata/autotrust_revtp_use.rpl | 143 + testdata/autotrust_rollalgo.rpl | 314 + testdata/autotrust_rollalgo_unknown.rpl | 323 + testdata/autotrust_rollover.rpl | 323 + testdata/autotrust_valid_use.rpl | 310 + testdata/black_data.rpl | 303 + testdata/black_dnskey.rpl | 506 + testdata/black_ds.rpl | 416 + testdata/black_ds_entry.rpl | 626 + testdata/black_ent.rpl | 449 + testdata/black_key_entry.rpl | 608 + testdata/black_prime.rpl | 303 + testdata/black_prime_entry.rpl | 311 + testdata/common.sh | 256 + testdata/dlv_anchor.rpl | 275 + testdata/dlv_ask_higher.rpl | 350 + testdata/dlv_below_ta.rpl | 351 + testdata/dlv_delegation.rpl | 331 + testdata/dlv_ds_lookup.rpl | 278 + testdata/dlv_insecure.rpl | 250 + testdata/dlv_insecure_negcache.rpl | 307 + testdata/dlv_keyretry.rpl | 284 + testdata/dlv_negnx.rpl | 402 + testdata/dlv_optout.rpl | 437 + testdata/dlv_unused.rpl | 274 + testdata/domain_insec_dlv.rpl | 276 + testdata/domain_insec_ds.rpl | 212 + testdata/edns_cache.tpkg | Bin 0 -> 1830 bytes testdata/edns_lame.tpkg | Bin 0 -> 1362 bytes testdata/fetch_glue.rpl | 209 + testdata/fetch_glue_cname.rpl | 221 + testdata/fwd.rpl | 42 + testdata/fwd_ancil.tpkg | Bin 0 -> 1689 bytes testdata/fwd_bogus.tpkg | Bin 0 -> 4096 bytes testdata/fwd_cached.rpl | 73 + testdata/fwd_capsid.tpkg | Bin 0 -> 1351 bytes testdata/fwd_capsid_fallback.tpkg | Bin 0 -> 1461 bytes testdata/fwd_compress_c00c.tpkg | Bin 0 -> 1786 bytes testdata/fwd_droptoomany.rpl | 90 + testdata/fwd_edns_bksec.tpkg | Bin 0 -> 2278 bytes testdata/fwd_edns_probe.tpkg | Bin 0 -> 1522 bytes testdata/fwd_error.rpl | 27 + testdata/fwd_jostle.rpl | 110 + testdata/fwd_jostle_out.rpl | 113 + testdata/fwd_lrudrop.rpl | 122 + testdata/fwd_no_edns.tpkg | Bin 0 -> 1370 bytes testdata/fwd_notcached.rpl | 87 + testdata/fwd_oneport.tpkg | Bin 0 -> 2017 bytes testdata/fwd_tcp.tpkg | Bin 0 -> 1353 bytes testdata/fwd_tcp_tc.tpkg | Bin 0 -> 1368 bytes testdata/fwd_tcp_tc6.tpkg | Bin 0 -> 1415 bytes testdata/fwd_three.tpkg | Bin 0 -> 1653 bytes testdata/fwd_three_service.tpkg | Bin 0 -> 1646 bytes testdata/fwd_timeout.rpl | 27 + testdata/fwd_ttlexpire.tpkg | Bin 0 -> 1392 bytes testdata/fwd_two.rpl | 89 + testdata/fwd_udp.tpkg | Bin 0 -> 1357 bytes testdata/fwd_udptmout.tpkg | Bin 0 -> 1953 bytes testdata/fwd_waitudp.tpkg | Bin 0 -> 1722 bytes testdata/fwd_zero.tpkg | Bin 0 -> 1479 bytes testdata/fwddlv_parse.rpl | 131 + testdata/host_file.template | 5 + testdata/hostsfileosx.tpkg | Bin 0 -> 1642 bytes testdata/iter_class_any.rpl | 150 + testdata/iter_cname_cache.rpl | 298 + testdata/iter_cname_double.rpl | 163 + testdata/iter_cname_nx.rpl | 157 + testdata/iter_cname_qnamecopy.rpl | 198 + testdata/iter_cycle.rpl | 178 + testdata/iter_cycle_noh.rpl | 225 + testdata/iter_dnsseclame_bug.rpl | 465 + testdata/iter_dnsseclame_ds.rpl | 414 + testdata/iter_dnsseclame_ds_ok.rpl | 367 + testdata/iter_dnsseclame_ta.rpl | 327 + testdata/iter_dnsseclame_ta_ok.rpl | 303 + testdata/iter_domain_sale.rpl | 272 + testdata/iter_domain_sale_nschange.rpl | 340 + testdata/iter_donotq127.rpl | 134 + testdata/iter_dp_turnsuseless.rpl | 166 + testdata/iter_ds_locate_ns.rpl | 145 + testdata/iter_ds_locate_ns_cname.rpl | 155 + testdata/iter_ds_locate_ns_nosoa.rpl | 145 + testdata/iter_emptydp.rpl | 263 + testdata/iter_emptydp_for_glue.rpl | 493 + testdata/iter_fwdfirst.rpl | 157 + testdata/iter_fwdstub.rpl | 218 + testdata/iter_fwdstubroot.rpl | 175 + testdata/iter_got6only.rpl | 135 + testdata/iter_hint_lame.rpl | 120 + testdata/iter_lame_aaaa.rpl | 181 + testdata/iter_lame_noaa.rpl | 201 + testdata/iter_lame_nosoa.rpl | 290 + testdata/iter_lamescrub.rpl | 149 + testdata/iter_mod.rpl | 121 + testdata/iter_ns_badip.rpl | 237 + testdata/iter_ns_spoof.rpl | 278 + testdata/iter_pc_a.rpl | 233 + testdata/iter_pc_aaaa.rpl | 233 + testdata/iter_pcdiff.rpl | 213 + testdata/iter_pcdirect.rpl | 246 + testdata/iter_pclame.rpl | 191 + testdata/iter_pcname.rpl | 277 + testdata/iter_pcnamech.rpl | 424 + testdata/iter_pcnamechrec.rpl | 403 + testdata/iter_pcnamerec.rpl | 278 + testdata/iter_pcttl.rpl | 245 + testdata/iter_prefetch.rpl | 226 + testdata/iter_prefetch_change.rpl | 364 + testdata/iter_prefetch_change2.rpl | 313 + testdata/iter_prefetch_childns.rpl | 227 + testdata/iter_prefetch_ns.rpl | 314 + testdata/iter_primenoglue.rpl | 383 + testdata/iter_privaddr.rpl | 246 + testdata/iter_ranoaa_lame.rpl | 293 + testdata/iter_reclame_one.rpl | 165 + testdata/iter_reclame_two.rpl | 182 + testdata/iter_recurse.rpl | 227 + testdata/iter_req_qname.rpl | 118 + testdata/iter_resolve.rpl | 120 + testdata/iter_scrub_cname_an.rpl | 181 + testdata/iter_scrub_dname_insec.rpl | 250 + testdata/iter_scrub_dname_sec.rpl | 212 + testdata/iter_scrub_ns.rpl | 103 + testdata/iter_scrub_ns_fwd.rpl | 103 + testdata/iter_scrub_ns_side.rpl | 103 + testdata/iter_soamin.rpl | 208 + testdata/iter_stub_noroot.rpl | 64 + testdata/iter_stubfirst.rpl | 157 + testdata/iter_timeout_ra_aaaa.rpl | 244 + testdata/local_nodefault.rpl | 60 + testdata/local_nodefault.tpkg | Bin 0 -> 1569 bytes testdata/local_norec.tpkg | Bin 0 -> 1501 bytes testdata/local_nosnoop.tpkg | Bin 0 -> 1605 bytes testdata/local_transparent_sametype.rpl | 78 + testdata/local_typetransparent.rpl | 109 + testdata/localdata.rpl | 357 + testdata/net_signed_servfail.rpl | 1374 + testdata/nomem_cnametopos.rpl | 296 + testdata/pylib.tpkg | Bin 0 -> 4209 bytes testdata/pymod.tpkg | Bin 0 -> 4072 bytes testdata/pymod_thread.tpkg | Bin 0 -> 4248 bytes testdata/refuse_xfr.rpl | 37 + testdata/remote-threaded.tpkg | Bin 0 -> 7039 bytes testdata/root_anchor.tpkg | Bin 0 -> 1001 bytes testdata/root_hints.tpkg | Bin 0 -> 1036 bytes testdata/rrset_rettl.rpl | 118 + testdata/rrset_untrusted.rpl | 119 + testdata/rrset_updated.rpl | 123 + testdata/speed_cache.tpkg | Bin 0 -> 2153 bytes testdata/speed_local.tpkg | Bin 0 -> 1351 bytes testdata/stat_timer.tpkg | Bin 0 -> 1460 bytes testdata/stop_nxdomain.rpl | 93 + testdata/stream_ssl.tpkg | Bin 0 -> 3732 bytes testdata/stream_tcp.tpkg | Bin 0 -> 1520 bytes testdata/stub_udp.tpkg | Bin 0 -> 1517 bytes testdata/stub_udp6.tpkg | Bin 0 -> 1529 bytes testdata/tcp_sigpipe.tpkg | Bin 0 -> 1576 bytes testdata/test_ds.sha1 | 33 + testdata/test_ds.sha384 | 45 + testdata/test_nsec3_hash.1 | 180 + testdata/test_packets.1 | 80000 ++++++++++++++++ testdata/test_packets.2 | 50 + testdata/test_packets.3 | 496 + testdata/test_packets.4 | 929 + testdata/test_packets.5 | 70 + testdata/test_packets.6 | 22 + testdata/test_packets.7 | 37 + testdata/test_packets.8 | 13 + testdata/test_packets.9 | 23 + testdata/test_signatures.1 | 605 + testdata/test_signatures.2 | 23 + testdata/test_signatures.3 | 48 + testdata/test_signatures.4 | 47 + testdata/test_signatures.5 | 48 + testdata/test_signatures.6 | 48 + testdata/test_signatures.7 | 32 + testdata/test_signatures.8 | 83 + testdata/test_sigs.ecdsa_p256 | 23 + testdata/test_sigs.ecdsa_p384 | 23 + testdata/test_sigs.gost | 40 + testdata/test_sigs.hinfo | 55 + testdata/test_sigs.revoked | 24 + testdata/test_sigs.rsasha256 | 23 + testdata/test_sigs.rsasha256_draft | 23 + testdata/test_sigs.rsasha512_draft | 23 + testdata/test_sigs.sha1_and_256 | 56 + testdata/trust_cname_chain.rpl | 153 + testdata/ttl_max.rpl | 212 + testdata/ttl_min.rpl | 213 + testdata/ttl_msg.rpl | 491 + testdata/val_adbit.rpl | 170 + testdata/val_adcopy.rpl | 170 + testdata/val_anchor_nx.rpl | 217 + testdata/val_anchor_nx_nosig.rpl | 216 + testdata/val_ans_dsent.rpl | 244 + testdata/val_ans_nx.rpl | 246 + testdata/val_any.rpl | 200 + testdata/val_any_cname.rpl | 161 + testdata/val_any_dname.rpl | 204 + testdata/val_cname_loop1.rpl | 144 + testdata/val_cname_loop2.rpl | 153 + testdata/val_cname_loop3.rpl | 166 + testdata/val_cnameinsectopos.rpl | 289 + testdata/val_cnamenx_dblnsec.rpl | 176 + testdata/val_cnamenx_rcodenx.rpl | 234 + testdata/val_cnameqtype.rpl | 228 + testdata/val_cnametocloser.rpl | 103 + testdata/val_cnametocloser_nosig.rpl | 96 + testdata/val_cnametodname.rpl | 230 + testdata/val_cnametodnametocnametopos.rpl | 418 + testdata/val_cnametoinsecure.rpl | 137 + testdata/val_cnametonodata.rpl | 230 + testdata/val_cnametonsec.rpl | 158 + testdata/val_cnametonx.rpl | 234 + testdata/val_cnametooptin.rpl | 162 + testdata/val_cnametooptout.rpl | 110 + testdata/val_cnametopos.rpl | 230 + testdata/val_cnametoposnowc.rpl | 262 + testdata/val_cnametoposwc.rpl | 236 + testdata/val_cnamewctonodata.rpl | 234 + testdata/val_cnamewctonx.rpl | 238 + testdata/val_cnamewctoposwc.rpl | 242 + testdata/val_dnametoolong.rpl | 255 + testdata/val_dnametopos.rpl | 234 + testdata/val_dnametoposwc.rpl | 238 + testdata/val_dnamewc.rpl | 265 + testdata/val_ds_afterprime.rpl | 177 + testdata/val_ds_cname.rpl | 202 + testdata/val_ds_gost.crpl | 206 + testdata/val_ds_gost_downgrade.crpl | 244 + testdata/val_ds_sha2.crpl | 201 + testdata/val_ds_sha2_downgrade.crpl | 224 + testdata/val_dsnsec.rpl | 285 + testdata/val_entds.rpl | 275 + testdata/val_faildnskey.rpl | 168 + testdata/val_faildnskey_ok.rpl | 177 + testdata/val_fwdds.rpl | 457 + testdata/val_keyprefetch.rpl | 212 + testdata/val_keyprefetch_verify.rpl | 245 + testdata/val_mal_wc.rpl | 149 + testdata/val_negcache_ds.rpl | 213 + testdata/val_negcache_dssoa.rpl | 253 + testdata/val_noadwhennodo.rpl | 149 + testdata/val_nodata.rpl | 147 + testdata/val_nodata_ent.rpl | 153 + testdata/val_nodata_entwc.rpl | 153 + testdata/val_nodata_failsig.rpl | 161 + testdata/val_nodata_hasdata.rpl | 161 + testdata/val_nodata_zonecut.rpl | 159 + testdata/val_nodatawc.rpl | 149 + testdata/val_nodatawc_badce.rpl | 161 + testdata/val_nodatawc_nodeny.rpl | 161 + testdata/val_nodatawc_one.rpl | 144 + testdata/val_nokeyprime.rpl | 161 + testdata/val_nsec3_b1_nameerror.rpl | 131 + testdata/val_nsec3_b1_nameerror_noce.rpl | 141 + testdata/val_nsec3_b1_nameerror_nonc.rpl | 143 + testdata/val_nsec3_b1_nameerror_nowc.rpl | 148 + testdata/val_nsec3_b21_nodataent.rpl | 114 + testdata/val_nsec3_b21_nodataent_wr.rpl | 132 + testdata/val_nsec3_b2_nodata.rpl | 114 + testdata/val_nsec3_b2_nodata_nons.rpl | 137 + testdata/val_nsec3_b3_optout.rpl | 211 + testdata/val_nsec3_b3_optout_negcache.rpl | 213 + testdata/val_nsec3_b3_optout_noce.rpl | 252 + testdata/val_nsec3_b3_optout_nonc.rpl | 253 + testdata/val_nsec3_b4_wild.rpl | 152 + testdata/val_nsec3_b4_wild_wr.rpl | 163 + testdata/val_nsec3_b5_wcnodata.rpl | 153 + testdata/val_nsec3_b5_wcnodata_noce.rpl | 162 + testdata/val_nsec3_b5_wcnodata_nonc.rpl | 162 + testdata/val_nsec3_b5_wcnodata_nowc.rpl | 164 + testdata/val_nsec3_cname_ds.rpl | 211 + testdata/val_nsec3_cname_par.rpl | 215 + testdata/val_nsec3_cname_sub.rpl | 225 + testdata/val_nsec3_iter_high.rpl | 162 + testdata/val_nsec3_nodatawccname.rpl | 167 + testdata/val_nsec3_nods.rpl | 218 + testdata/val_nsec3_nods_badopt.rpl | 246 + testdata/val_nsec3_nods_badsig.rpl | 235 + testdata/val_nsec3_nods_negcache.rpl | 219 + testdata/val_nsec3_nods_soa.rpl | 251 + testdata/val_nsec3_optout_ad.rpl | 359 + testdata/val_nsec3_optout_cache.rpl | 278 + testdata/val_nsec3_wcany.rpl | 159 + testdata/val_nsec3_wcany_nodeny.rpl | 168 + testdata/val_nx.rpl | 152 + testdata/val_nx_nodeny.rpl | 162 + testdata/val_nx_nowc.rpl | 162 + testdata/val_nx_nsec3_collision.rpl | 185 + testdata/val_nx_nsec3_params.rpl | 161 + testdata/val_nx_overreach.rpl | 163 + testdata/val_pos_truncns.rpl | 148 + testdata/val_positive.rpl | 150 + testdata/val_positive_nosigs.rpl | 179 + testdata/val_positive_wc.rpl | 159 + testdata/val_positive_wc_nodeny.rpl | 166 + testdata/val_qds_badanc.rpl | 221 + testdata/val_qds_oneanc.rpl | 220 + testdata/val_qds_twoanc.rpl | 221 + testdata/val_refer_unsignadd.rpl | 350 + testdata/val_referd.rpl | 172 + testdata/val_referglue.rpl | 297 + testdata/val_rrsig.rpl | 167 + testdata/val_secds.rpl | 211 + testdata/val_secds_nosig.rpl | 230 + testdata/val_stub_noroot.rpl | 83 + testdata/val_stubds.rpl | 456 + testdata/val_ta_algo_dnskey.rpl | 181 + testdata/val_ta_algo_missing.rpl | 171 + testdata/val_twocname.rpl | 132 + testdata/val_unalgo_anchor.rpl | 150 + testdata/val_unalgo_dlv.rpl | 280 + testdata/val_unalgo_ds.rpl | 200 + testdata/val_unsec_cname.rpl | 359 + testdata/val_unsecds.rpl | 191 + testdata/val_unsecds_negcache.rpl | 192 + testdata/val_unsecds_qtypeds.rpl | 207 + testdata/val_wild_pos.rpl | 159 + testdata/version_bind.rpl | 74 + testdata/version_bind_hide.rpl | 71 + util/alloc.c | 642 + util/alloc.h | 214 + util/config_file.c | 1489 + util/config_file.h | 651 + util/configlexer.c | 3912 + util/configlexer.lex | 340 + util/configparser.c | 3892 + util/configparser.h | 322 + util/configparser.y | 1278 + util/configyyrename.h | 88 + util/data/dname.c | 781 + util/data/dname.h | 303 + util/data/msgencode.c | 843 + util/data/msgencode.h | 130 + util/data/msgparse.c | 1018 + util/data/msgparse.h | 299 + util/data/msgreply.c | 838 + util/data/msgreply.h | 417 + util/data/packed_rrset.c | 488 + util/data/packed_rrset.h | 434 + util/fptr_wlist.c | 401 + util/fptr_wlist.h | 359 + util/iana_ports.inc | 5347 ++ util/locks.c | 264 + util/locks.h | 293 + util/log.c | 453 + util/log.h | 198 + util/mini_event.c | 394 + util/mini_event.h | 177 + util/module.c | 71 + util/module.h | 402 + util/net_help.c | 699 + util/net_help.h | 372 + util/netevent.c | 2137 + util/netevent.h | 684 + util/random.c | 203 + util/random.h | 93 + util/rbtree.c | 620 + util/rbtree.h | 192 + util/regional.c | 223 + util/regional.h | 150 + util/rtt.c | 120 + util/rtt.h | 107 + util/storage/dnstree.c | 282 + util/storage/dnstree.h | 192 + util/storage/lookup3.c | 1011 + util/storage/lookup3.h | 71 + util/storage/lruhash.c | 544 + util/storage/lruhash.h | 414 + util/storage/slabhash.c | 219 + util/storage/slabhash.h | 211 + util/timehist.c | 246 + util/timehist.h | 134 + util/tube.c | 726 + util/tube.h | 273 + util/winsock_event.c | 692 + util/winsock_event.h | 264 + validator/autotrust.c | 2203 + validator/autotrust.h | 205 + validator/val_anchor.c | 1263 + validator/val_anchor.h | 218 + validator/val_kcache.c | 172 + validator/val_kcache.h | 118 + validator/val_kentry.c | 412 + validator/val_kentry.h | 220 + validator/val_neg.c | 1455 + validator/val_neg.h | 314 + validator/val_nsec.c | 603 + validator/val_nsec.h | 182 + validator/val_nsec3.c | 1446 + validator/val_nsec3.h | 378 + validator/val_sigcrypt.c | 1824 + validator/val_sigcrypt.h | 311 + validator/val_utils.c | 1082 + validator/val_utils.h | 403 + validator/validator.c | 2958 + validator/validator.h | 294 + winrc/README.txt | 110 + winrc/anchor-update.c | 159 + winrc/combined.ico | Bin 0 -> 10534 bytes winrc/gen_msg.bin | Bin 0 -> 116 bytes winrc/gen_msg.mc | 44 + winrc/rsrc_anchorupd.rc | 40 + winrc/rsrc_svcinst.rc | 45 + winrc/rsrc_svcuninst.rc | 45 + winrc/rsrc_unbound.rc | 48 + winrc/rsrc_unbound_anchor.rc | 37 + winrc/rsrc_unbound_checkconf.rc | 37 + winrc/rsrc_unbound_control.rc | 37 + winrc/rsrc_unbound_host.rc | 37 + winrc/service.conf | 13 + winrc/setup.nsi | 226 + winrc/setup_left.bmp | Bin 0 -> 154542 bytes winrc/setup_top.bmp | Bin 0 -> 25818 bytes winrc/unbound-service-install.c | 65 + winrc/unbound-service-remove.c | 65 + winrc/unbound-website.url | 3 + winrc/unbound16.ico | Bin 0 -> 894 bytes winrc/unbound32.ico | Bin 0 -> 3262 bytes winrc/unbound48.ico | Bin 0 -> 7358 bytes winrc/unbound64.ico | Bin 0 -> 12862 bytes winrc/unbound64.png | Bin 0 -> 6240 bytes winrc/vista_admin.manifest | 16 + winrc/vista_user.manifest | 16 + winrc/w_inst.c | 308 + winrc/w_inst.h | 80 + winrc/win_svc.c | 617 + winrc/win_svc.h | 90 + 725 files changed, 318761 insertions(+) create mode 100644 LICENSE create mode 100644 Makefile.in create mode 100644 README create mode 100644 ac_pkg_swig.m4 create mode 100644 aclocal.m4 create mode 100644 acx_nlnetlabs.m4 create mode 100644 acx_pthread.m4 create mode 100644 acx_python.m4 create mode 100644 compat/ctime_r.c create mode 100644 compat/fake-rfc2553.c create mode 100644 compat/fake-rfc2553.h create mode 100644 compat/gmtime_r.c create mode 100644 compat/inet_aton.c create mode 100644 compat/inet_ntop.c create mode 100644 compat/inet_pton.c create mode 100644 compat/malloc.c create mode 100644 compat/memcmp.c create mode 100644 compat/memcmp.h create mode 100644 compat/memmove.c create mode 100644 compat/snprintf.c create mode 100644 compat/strlcpy.c create mode 100644 compat/strptime.c create mode 100755 config.guess create mode 100644 config.h.in create mode 100755 config.sub create mode 100755 configure create mode 100644 configure.ac create mode 100644 contrib/README create mode 100755 contrib/build-unbound-localzone-from-hosts.pl create mode 100755 contrib/parseunbound.pl create mode 100755 contrib/rc_d_unbound create mode 100644 contrib/selinux/unbound.fc create mode 100644 contrib/selinux/unbound.te create mode 100644 contrib/unbound-host.nagios.patch create mode 100644 contrib/unbound.init create mode 100644 contrib/unbound.init_fedora create mode 100644 contrib/unbound.plist create mode 100644 contrib/unbound.spec create mode 100644 contrib/unbound.spec_fedora create mode 100644 contrib/unbound_cacti.tar.gz create mode 100755 contrib/unbound_munin_ create mode 100755 contrib/update-anchor.sh create mode 100755 contrib/validation-reporter.sh create mode 100644 daemon/acl_list.c create mode 100644 daemon/acl_list.h create mode 100644 daemon/cachedump.c create mode 100644 daemon/cachedump.h create mode 100644 daemon/daemon.c create mode 100644 daemon/daemon.h create mode 100644 daemon/remote.c create mode 100644 daemon/remote.h create mode 100644 daemon/stats.c create mode 100644 daemon/stats.h create mode 100644 daemon/unbound.c create mode 100644 daemon/worker.c create mode 100644 daemon/worker.h create mode 100644 doc/CREDITS create mode 100644 doc/Changelog create mode 100644 doc/FEATURES create mode 100644 doc/LICENSE create mode 100644 doc/README create mode 100644 doc/README.svn create mode 100644 doc/README.tests create mode 100644 doc/TODO create mode 100644 doc/control_proto_spec.txt create mode 100644 doc/example.conf.in create mode 100644 doc/ietf67-design-02.odp create mode 100644 doc/ietf67-design-02.pdf create mode 100644 doc/libunbound.3.in create mode 100644 doc/requirements.txt create mode 100644 doc/unbound-anchor.8.in create mode 100644 doc/unbound-checkconf.8.in create mode 100644 doc/unbound-control.8.in create mode 100644 doc/unbound-host.1 create mode 100644 doc/unbound.8.in create mode 100644 doc/unbound.conf.5.in create mode 100644 doc/unbound.doxygen create mode 100755 install-sh create mode 100644 iterator/iter_delegpt.c create mode 100644 iterator/iter_delegpt.h create mode 100644 iterator/iter_donotq.c create mode 100644 iterator/iter_donotq.h create mode 100644 iterator/iter_fwd.c create mode 100644 iterator/iter_fwd.h create mode 100644 iterator/iter_hints.c create mode 100644 iterator/iter_hints.h create mode 100644 iterator/iter_priv.c create mode 100644 iterator/iter_priv.h create mode 100644 iterator/iter_resptype.c create mode 100644 iterator/iter_resptype.h create mode 100644 iterator/iter_scrub.c create mode 100644 iterator/iter_scrub.h create mode 100644 iterator/iter_utils.c create mode 100644 iterator/iter_utils.h create mode 100644 iterator/iterator.c create mode 100644 iterator/iterator.h create mode 100644 libunbound/context.c create mode 100644 libunbound/context.h create mode 100644 libunbound/libunbound.c create mode 100644 libunbound/libworker.c create mode 100644 libunbound/libworker.h create mode 100644 libunbound/python/LICENSE create mode 100644 libunbound/python/Makefile create mode 100644 libunbound/python/doc/_static/readme create mode 100644 libunbound/python/doc/conf.py create mode 100644 libunbound/python/doc/examples/example1a.rst create mode 100644 libunbound/python/doc/examples/example1b.rst create mode 100644 libunbound/python/doc/examples/example2.rst create mode 100644 libunbound/python/doc/examples/example3.rst create mode 100644 libunbound/python/doc/examples/example4.rst create mode 100644 libunbound/python/doc/examples/example5.rst create mode 100644 libunbound/python/doc/examples/example6-1.py create mode 100644 libunbound/python/doc/examples/example6.rst create mode 100644 libunbound/python/doc/examples/example7-1.py create mode 100644 libunbound/python/doc/examples/example7-2.py create mode 100644 libunbound/python/doc/examples/example7.rst create mode 100644 libunbound/python/doc/examples/example8-1.py create mode 100644 libunbound/python/doc/examples/example8.rst create mode 100644 libunbound/python/doc/examples/index.rst create mode 100644 libunbound/python/doc/index.rst create mode 100644 libunbound/python/doc/install.rst create mode 100644 libunbound/python/doc/intro.rst create mode 100644 libunbound/python/doc/modules/unbound.rst create mode 100644 libunbound/python/examples/async-lookup.py create mode 100644 libunbound/python/examples/dns-lookup.py create mode 100644 libunbound/python/examples/dnssec-valid.py create mode 100644 libunbound/python/examples/dnssec_test.py create mode 100644 libunbound/python/examples/example8-1.py create mode 100644 libunbound/python/examples/idn-lookup.py create mode 100644 libunbound/python/examples/mx-lookup.py create mode 100644 libunbound/python/examples/ns-lookup.py create mode 100644 libunbound/python/examples/reverse-lookup.py create mode 100644 libunbound/python/libunbound.i create mode 100644 libunbound/ubsyms.def create mode 100644 libunbound/unbound.h create mode 100755 ltmain.sh create mode 100644 pythonmod/LICENSE create mode 100644 pythonmod/Makefile create mode 100644 pythonmod/doc/_static/readme create mode 100644 pythonmod/doc/conf.py create mode 100644 pythonmod/doc/examples/example0-1.py create mode 100644 pythonmod/doc/examples/example0.rst create mode 100644 pythonmod/doc/examples/example1.rst create mode 100644 pythonmod/doc/examples/example2.rst create mode 100644 pythonmod/doc/examples/example3.rst create mode 100644 pythonmod/doc/examples/example4.rst create mode 100644 pythonmod/doc/examples/index.rst create mode 100644 pythonmod/doc/index.rst create mode 100644 pythonmod/doc/install.rst create mode 100644 pythonmod/doc/modules/config.rst create mode 100644 pythonmod/doc/modules/env.rst create mode 100644 pythonmod/doc/modules/functions.rst create mode 100644 pythonmod/doc/modules/index.rst create mode 100644 pythonmod/doc/modules/struct.rst create mode 100644 pythonmod/doc/usecase.rst create mode 100644 pythonmod/examples/calc.py create mode 100644 pythonmod/examples/dict.py create mode 100644 pythonmod/examples/dict_data.txt create mode 100644 pythonmod/examples/log.py create mode 100644 pythonmod/examples/resgen.py create mode 100644 pythonmod/examples/resip.py create mode 100644 pythonmod/examples/resmod.py create mode 100644 pythonmod/interface.i create mode 100644 pythonmod/pythonmod.c create mode 100644 pythonmod/pythonmod.h create mode 100644 pythonmod/pythonmod_utils.c create mode 100644 pythonmod/pythonmod_utils.h create mode 100644 pythonmod/test-calc.conf create mode 100644 pythonmod/test-dict.conf create mode 100644 pythonmod/test-log.conf create mode 100644 pythonmod/test-resgen.conf create mode 100644 pythonmod/test-resip.conf create mode 100644 pythonmod/test-resmod.conf create mode 100644 pythonmod/ubmodule-msg.py create mode 100644 pythonmod/ubmodule-tst.py create mode 100644 services/cache/dns.c create mode 100644 services/cache/dns.h create mode 100644 services/cache/infra.c create mode 100644 services/cache/infra.h create mode 100644 services/cache/rrset.c create mode 100644 services/cache/rrset.h create mode 100644 services/listen_dnsport.c create mode 100644 services/listen_dnsport.h create mode 100644 services/localzone.c create mode 100644 services/localzone.h create mode 100644 services/mesh.c create mode 100644 services/mesh.h create mode 100644 services/modstack.c create mode 100644 services/modstack.h create mode 100644 services/outbound_list.c create mode 100644 services/outbound_list.h create mode 100644 services/outside_network.c create mode 100644 services/outside_network.h create mode 100644 smallapp/unbound-anchor.c create mode 100644 smallapp/unbound-checkconf.c create mode 100755 smallapp/unbound-control-setup.sh create mode 100644 smallapp/unbound-control.c create mode 100644 smallapp/unbound-host.c create mode 100644 smallapp/worker_cb.c create mode 100644 testcode/asynclook.c create mode 100644 testcode/checklocks.c create mode 100644 testcode/checklocks.h create mode 100644 testcode/delayer.c create mode 100755 testcode/do-tests.sh create mode 100644 testcode/fake_event.c create mode 100644 testcode/fake_event.h create mode 100644 testcode/harvest.c create mode 100644 testcode/ldns-testpkts.c create mode 100644 testcode/ldns-testpkts.h create mode 100644 testcode/lock_verify.c create mode 100644 testcode/memstats.c create mode 100755 testcode/mini_tpkg.sh create mode 100644 testcode/perf.c create mode 100644 testcode/petal.c create mode 100644 testcode/pktview.c create mode 100644 testcode/readhex.c create mode 100644 testcode/readhex.h create mode 100644 testcode/replay.c create mode 100644 testcode/replay.h create mode 100644 testcode/signit.c create mode 100644 testcode/streamtcp.c create mode 100755 testcode/testbed.sh create mode 100644 testcode/testbed.txt create mode 100644 testcode/testbound.c create mode 100644 testcode/unitanchor.c create mode 100644 testcode/unitdname.c create mode 100644 testcode/unitlruhash.c create mode 100644 testcode/unitmain.c create mode 100644 testcode/unitmain.h create mode 100644 testcode/unitmsgparse.c create mode 100644 testcode/unitneg.c create mode 100644 testcode/unitregional.c create mode 100644 testcode/unitslabhash.c create mode 100644 testcode/unitverify.c create mode 100644 testdata/00-lint.tpkg create mode 100644 testdata/01-doc.tpkg create mode 100644 testdata/02-unittest.tpkg create mode 100644 testdata/03-testbound.tpkg create mode 100644 testdata/04-checkconf.tpkg create mode 100644 testdata/05-asynclook.tpkg create mode 100644 testdata/06-ianaports.tpkg create mode 100644 testdata/07-confroot.tpkg create mode 100644 testdata/08-host-lib.tpkg create mode 100644 testdata/09-unbound-control.tpkg create mode 100644 testdata/10-unbound-anchor.tpkg create mode 100644 testdata/Kexample.com.+003+02854.ds create mode 100644 testdata/Kexample.com.+003+02854.key create mode 100644 testdata/Kexample.com.+003+02854.private create mode 100644 testdata/Kexample.com.+005+16486.ds create mode 100644 testdata/Kexample.com.+005+16486.key create mode 100644 testdata/Kexample.com.+005+16486.private create mode 100644 testdata/Kexample.com.+005+30899.ds create mode 100644 testdata/Kexample.com.+005+30899.key create mode 100644 testdata/Kexample.com.+005+30899.private create mode 100644 testdata/Kexample.com.+005+55582.ds create mode 100644 testdata/Kexample.com.+005+55582.key create mode 100644 testdata/Kexample.com.+005+55582.private create mode 100644 testdata/Kexample.com.+005+60946.ds create mode 100644 testdata/Kexample.com.+005+60946.key create mode 100644 testdata/Kexample.com.+005+60946.private create mode 100644 testdata/Kexample.com.+007+57024.ds create mode 100644 testdata/Kexample.com.+007+57024.key create mode 100644 testdata/Kexample.com.+007+57024.private create mode 100644 testdata/Kexample.com.+008+01443.ds create mode 100644 testdata/Kexample.com.+008+01443.key create mode 100644 testdata/Kexample.com.+008+01443.private create mode 100644 testdata/Kexample.com.+009+48886.ds create mode 100644 testdata/Kexample.com.+009+48886.key create mode 100644 testdata/Kexample.com.+009+48886.private create mode 100644 testdata/Kexample.com.+012+60385.ds create mode 100644 testdata/Kexample.com.+012+60385.key create mode 100644 testdata/Kexample.com.+012+60385.private create mode 100644 testdata/acl.rpl create mode 100644 testdata/autotrust_10key.rpl create mode 100644 testdata/autotrust_addpend_2exceed.rpl create mode 100644 testdata/autotrust_addpend_early.rpl create mode 100644 testdata/autotrust_addpend_nosign.rpl create mode 100644 testdata/autotrust_addpend_nosignnew.rpl create mode 100644 testdata/autotrust_addpend_once.rpl create mode 100644 testdata/autotrust_addpend_twice.rpl create mode 100644 testdata/autotrust_init.rpl create mode 100644 testdata/autotrust_init_ds.rpl create mode 100644 testdata/autotrust_init_fail.rpl create mode 100644 testdata/autotrust_init_failsig.rpl create mode 100644 testdata/autotrust_init_legacy.rpl create mode 100644 testdata/autotrust_init_sigs.rpl create mode 100644 testdata/autotrust_init_zsk.rpl create mode 100644 testdata/autotrust_missing.rpl create mode 100644 testdata/autotrust_missing_all.rpl create mode 100644 testdata/autotrust_missing_returns.rpl create mode 100644 testdata/autotrust_probefail.rpl create mode 100644 testdata/autotrust_probefailsig.rpl create mode 100644 testdata/autotrust_revoked_use.rpl create mode 100644 testdata/autotrust_revoked_with_invalid.rpl create mode 100644 testdata/autotrust_revtp.rpl create mode 100644 testdata/autotrust_revtp_read.rpl create mode 100644 testdata/autotrust_revtp_use.rpl create mode 100644 testdata/autotrust_rollalgo.rpl create mode 100644 testdata/autotrust_rollalgo_unknown.rpl create mode 100644 testdata/autotrust_rollover.rpl create mode 100644 testdata/autotrust_valid_use.rpl create mode 100644 testdata/black_data.rpl create mode 100644 testdata/black_dnskey.rpl create mode 100644 testdata/black_ds.rpl create mode 100644 testdata/black_ds_entry.rpl create mode 100644 testdata/black_ent.rpl create mode 100644 testdata/black_key_entry.rpl create mode 100644 testdata/black_prime.rpl create mode 100644 testdata/black_prime_entry.rpl create mode 100755 testdata/common.sh create mode 100644 testdata/dlv_anchor.rpl create mode 100644 testdata/dlv_ask_higher.rpl create mode 100644 testdata/dlv_below_ta.rpl create mode 100644 testdata/dlv_delegation.rpl create mode 100644 testdata/dlv_ds_lookup.rpl create mode 100644 testdata/dlv_insecure.rpl create mode 100644 testdata/dlv_insecure_negcache.rpl create mode 100644 testdata/dlv_keyretry.rpl create mode 100644 testdata/dlv_negnx.rpl create mode 100644 testdata/dlv_optout.rpl create mode 100644 testdata/dlv_unused.rpl create mode 100644 testdata/domain_insec_dlv.rpl create mode 100644 testdata/domain_insec_ds.rpl create mode 100644 testdata/edns_cache.tpkg create mode 100644 testdata/edns_lame.tpkg create mode 100644 testdata/fetch_glue.rpl create mode 100644 testdata/fetch_glue_cname.rpl create mode 100644 testdata/fwd.rpl create mode 100644 testdata/fwd_ancil.tpkg create mode 100644 testdata/fwd_bogus.tpkg create mode 100644 testdata/fwd_cached.rpl create mode 100644 testdata/fwd_capsid.tpkg create mode 100644 testdata/fwd_capsid_fallback.tpkg create mode 100644 testdata/fwd_compress_c00c.tpkg create mode 100644 testdata/fwd_droptoomany.rpl create mode 100644 testdata/fwd_edns_bksec.tpkg create mode 100644 testdata/fwd_edns_probe.tpkg create mode 100644 testdata/fwd_error.rpl create mode 100644 testdata/fwd_jostle.rpl create mode 100644 testdata/fwd_jostle_out.rpl create mode 100644 testdata/fwd_lrudrop.rpl create mode 100644 testdata/fwd_no_edns.tpkg create mode 100644 testdata/fwd_notcached.rpl create mode 100644 testdata/fwd_oneport.tpkg create mode 100644 testdata/fwd_tcp.tpkg create mode 100644 testdata/fwd_tcp_tc.tpkg create mode 100644 testdata/fwd_tcp_tc6.tpkg create mode 100644 testdata/fwd_three.tpkg create mode 100644 testdata/fwd_three_service.tpkg create mode 100644 testdata/fwd_timeout.rpl create mode 100644 testdata/fwd_ttlexpire.tpkg create mode 100644 testdata/fwd_two.rpl create mode 100644 testdata/fwd_udp.tpkg create mode 100644 testdata/fwd_udptmout.tpkg create mode 100644 testdata/fwd_waitudp.tpkg create mode 100644 testdata/fwd_zero.tpkg create mode 100644 testdata/fwddlv_parse.rpl create mode 100644 testdata/host_file.template create mode 100644 testdata/hostsfileosx.tpkg create mode 100644 testdata/iter_class_any.rpl create mode 100644 testdata/iter_cname_cache.rpl create mode 100644 testdata/iter_cname_double.rpl create mode 100644 testdata/iter_cname_nx.rpl create mode 100644 testdata/iter_cname_qnamecopy.rpl create mode 100644 testdata/iter_cycle.rpl create mode 100644 testdata/iter_cycle_noh.rpl create mode 100644 testdata/iter_dnsseclame_bug.rpl create mode 100644 testdata/iter_dnsseclame_ds.rpl create mode 100644 testdata/iter_dnsseclame_ds_ok.rpl create mode 100644 testdata/iter_dnsseclame_ta.rpl create mode 100644 testdata/iter_dnsseclame_ta_ok.rpl create mode 100644 testdata/iter_domain_sale.rpl create mode 100644 testdata/iter_domain_sale_nschange.rpl create mode 100644 testdata/iter_donotq127.rpl create mode 100644 testdata/iter_dp_turnsuseless.rpl create mode 100644 testdata/iter_ds_locate_ns.rpl create mode 100644 testdata/iter_ds_locate_ns_cname.rpl create mode 100644 testdata/iter_ds_locate_ns_nosoa.rpl create mode 100644 testdata/iter_emptydp.rpl create mode 100644 testdata/iter_emptydp_for_glue.rpl create mode 100644 testdata/iter_fwdfirst.rpl create mode 100644 testdata/iter_fwdstub.rpl create mode 100644 testdata/iter_fwdstubroot.rpl create mode 100644 testdata/iter_got6only.rpl create mode 100644 testdata/iter_hint_lame.rpl create mode 100644 testdata/iter_lame_aaaa.rpl create mode 100644 testdata/iter_lame_noaa.rpl create mode 100644 testdata/iter_lame_nosoa.rpl create mode 100644 testdata/iter_lamescrub.rpl create mode 100644 testdata/iter_mod.rpl create mode 100644 testdata/iter_ns_badip.rpl create mode 100644 testdata/iter_ns_spoof.rpl create mode 100644 testdata/iter_pc_a.rpl create mode 100644 testdata/iter_pc_aaaa.rpl create mode 100644 testdata/iter_pcdiff.rpl create mode 100644 testdata/iter_pcdirect.rpl create mode 100644 testdata/iter_pclame.rpl create mode 100644 testdata/iter_pcname.rpl create mode 100644 testdata/iter_pcnamech.rpl create mode 100644 testdata/iter_pcnamechrec.rpl create mode 100644 testdata/iter_pcnamerec.rpl create mode 100644 testdata/iter_pcttl.rpl create mode 100644 testdata/iter_prefetch.rpl create mode 100644 testdata/iter_prefetch_change.rpl create mode 100644 testdata/iter_prefetch_change2.rpl create mode 100644 testdata/iter_prefetch_childns.rpl create mode 100644 testdata/iter_prefetch_ns.rpl create mode 100644 testdata/iter_primenoglue.rpl create mode 100644 testdata/iter_privaddr.rpl create mode 100644 testdata/iter_ranoaa_lame.rpl create mode 100644 testdata/iter_reclame_one.rpl create mode 100644 testdata/iter_reclame_two.rpl create mode 100644 testdata/iter_recurse.rpl create mode 100644 testdata/iter_req_qname.rpl create mode 100644 testdata/iter_resolve.rpl create mode 100644 testdata/iter_scrub_cname_an.rpl create mode 100644 testdata/iter_scrub_dname_insec.rpl create mode 100644 testdata/iter_scrub_dname_sec.rpl create mode 100644 testdata/iter_scrub_ns.rpl create mode 100644 testdata/iter_scrub_ns_fwd.rpl create mode 100644 testdata/iter_scrub_ns_side.rpl create mode 100644 testdata/iter_soamin.rpl create mode 100644 testdata/iter_stub_noroot.rpl create mode 100644 testdata/iter_stubfirst.rpl create mode 100644 testdata/iter_timeout_ra_aaaa.rpl create mode 100644 testdata/local_nodefault.rpl create mode 100644 testdata/local_nodefault.tpkg create mode 100644 testdata/local_norec.tpkg create mode 100644 testdata/local_nosnoop.tpkg create mode 100644 testdata/local_transparent_sametype.rpl create mode 100644 testdata/local_typetransparent.rpl create mode 100644 testdata/localdata.rpl create mode 100644 testdata/net_signed_servfail.rpl create mode 100644 testdata/nomem_cnametopos.rpl create mode 100644 testdata/pylib.tpkg create mode 100644 testdata/pymod.tpkg create mode 100644 testdata/pymod_thread.tpkg create mode 100644 testdata/refuse_xfr.rpl create mode 100644 testdata/remote-threaded.tpkg create mode 100644 testdata/root_anchor.tpkg create mode 100644 testdata/root_hints.tpkg create mode 100644 testdata/rrset_rettl.rpl create mode 100644 testdata/rrset_untrusted.rpl create mode 100644 testdata/rrset_updated.rpl create mode 100644 testdata/speed_cache.tpkg create mode 100644 testdata/speed_local.tpkg create mode 100644 testdata/stat_timer.tpkg create mode 100644 testdata/stop_nxdomain.rpl create mode 100644 testdata/stream_ssl.tpkg create mode 100644 testdata/stream_tcp.tpkg create mode 100644 testdata/stub_udp.tpkg create mode 100644 testdata/stub_udp6.tpkg create mode 100644 testdata/tcp_sigpipe.tpkg create mode 100644 testdata/test_ds.sha1 create mode 100644 testdata/test_ds.sha384 create mode 100644 testdata/test_nsec3_hash.1 create mode 100644 testdata/test_packets.1 create mode 100644 testdata/test_packets.2 create mode 100644 testdata/test_packets.3 create mode 100644 testdata/test_packets.4 create mode 100644 testdata/test_packets.5 create mode 100644 testdata/test_packets.6 create mode 100644 testdata/test_packets.7 create mode 100644 testdata/test_packets.8 create mode 100644 testdata/test_packets.9 create mode 100644 testdata/test_signatures.1 create mode 100644 testdata/test_signatures.2 create mode 100644 testdata/test_signatures.3 create mode 100644 testdata/test_signatures.4 create mode 100644 testdata/test_signatures.5 create mode 100644 testdata/test_signatures.6 create mode 100644 testdata/test_signatures.7 create mode 100644 testdata/test_signatures.8 create mode 100644 testdata/test_sigs.ecdsa_p256 create mode 100644 testdata/test_sigs.ecdsa_p384 create mode 100644 testdata/test_sigs.gost create mode 100644 testdata/test_sigs.hinfo create mode 100644 testdata/test_sigs.revoked create mode 100644 testdata/test_sigs.rsasha256 create mode 100644 testdata/test_sigs.rsasha256_draft create mode 100644 testdata/test_sigs.rsasha512_draft create mode 100644 testdata/test_sigs.sha1_and_256 create mode 100644 testdata/trust_cname_chain.rpl create mode 100644 testdata/ttl_max.rpl create mode 100644 testdata/ttl_min.rpl create mode 100644 testdata/ttl_msg.rpl create mode 100644 testdata/val_adbit.rpl create mode 100644 testdata/val_adcopy.rpl create mode 100644 testdata/val_anchor_nx.rpl create mode 100644 testdata/val_anchor_nx_nosig.rpl create mode 100644 testdata/val_ans_dsent.rpl create mode 100644 testdata/val_ans_nx.rpl create mode 100644 testdata/val_any.rpl create mode 100644 testdata/val_any_cname.rpl create mode 100644 testdata/val_any_dname.rpl create mode 100644 testdata/val_cname_loop1.rpl create mode 100644 testdata/val_cname_loop2.rpl create mode 100644 testdata/val_cname_loop3.rpl create mode 100644 testdata/val_cnameinsectopos.rpl create mode 100644 testdata/val_cnamenx_dblnsec.rpl create mode 100644 testdata/val_cnamenx_rcodenx.rpl create mode 100644 testdata/val_cnameqtype.rpl create mode 100644 testdata/val_cnametocloser.rpl create mode 100644 testdata/val_cnametocloser_nosig.rpl create mode 100644 testdata/val_cnametodname.rpl create mode 100644 testdata/val_cnametodnametocnametopos.rpl create mode 100644 testdata/val_cnametoinsecure.rpl create mode 100644 testdata/val_cnametonodata.rpl create mode 100644 testdata/val_cnametonsec.rpl create mode 100644 testdata/val_cnametonx.rpl create mode 100644 testdata/val_cnametooptin.rpl create mode 100644 testdata/val_cnametooptout.rpl create mode 100644 testdata/val_cnametopos.rpl create mode 100644 testdata/val_cnametoposnowc.rpl create mode 100644 testdata/val_cnametoposwc.rpl create mode 100644 testdata/val_cnamewctonodata.rpl create mode 100644 testdata/val_cnamewctonx.rpl create mode 100644 testdata/val_cnamewctoposwc.rpl create mode 100644 testdata/val_dnametoolong.rpl create mode 100644 testdata/val_dnametopos.rpl create mode 100644 testdata/val_dnametoposwc.rpl create mode 100644 testdata/val_dnamewc.rpl create mode 100644 testdata/val_ds_afterprime.rpl create mode 100644 testdata/val_ds_cname.rpl create mode 100644 testdata/val_ds_gost.crpl create mode 100644 testdata/val_ds_gost_downgrade.crpl create mode 100644 testdata/val_ds_sha2.crpl create mode 100644 testdata/val_ds_sha2_downgrade.crpl create mode 100644 testdata/val_dsnsec.rpl create mode 100644 testdata/val_entds.rpl create mode 100644 testdata/val_faildnskey.rpl create mode 100644 testdata/val_faildnskey_ok.rpl create mode 100644 testdata/val_fwdds.rpl create mode 100644 testdata/val_keyprefetch.rpl create mode 100644 testdata/val_keyprefetch_verify.rpl create mode 100644 testdata/val_mal_wc.rpl create mode 100644 testdata/val_negcache_ds.rpl create mode 100644 testdata/val_negcache_dssoa.rpl create mode 100644 testdata/val_noadwhennodo.rpl create mode 100644 testdata/val_nodata.rpl create mode 100644 testdata/val_nodata_ent.rpl create mode 100644 testdata/val_nodata_entwc.rpl create mode 100644 testdata/val_nodata_failsig.rpl create mode 100644 testdata/val_nodata_hasdata.rpl create mode 100644 testdata/val_nodata_zonecut.rpl create mode 100644 testdata/val_nodatawc.rpl create mode 100644 testdata/val_nodatawc_badce.rpl create mode 100644 testdata/val_nodatawc_nodeny.rpl create mode 100644 testdata/val_nodatawc_one.rpl create mode 100644 testdata/val_nokeyprime.rpl create mode 100644 testdata/val_nsec3_b1_nameerror.rpl create mode 100644 testdata/val_nsec3_b1_nameerror_noce.rpl create mode 100644 testdata/val_nsec3_b1_nameerror_nonc.rpl create mode 100644 testdata/val_nsec3_b1_nameerror_nowc.rpl create mode 100644 testdata/val_nsec3_b21_nodataent.rpl create mode 100644 testdata/val_nsec3_b21_nodataent_wr.rpl create mode 100644 testdata/val_nsec3_b2_nodata.rpl create mode 100644 testdata/val_nsec3_b2_nodata_nons.rpl create mode 100644 testdata/val_nsec3_b3_optout.rpl create mode 100644 testdata/val_nsec3_b3_optout_negcache.rpl create mode 100644 testdata/val_nsec3_b3_optout_noce.rpl create mode 100644 testdata/val_nsec3_b3_optout_nonc.rpl create mode 100644 testdata/val_nsec3_b4_wild.rpl create mode 100644 testdata/val_nsec3_b4_wild_wr.rpl create mode 100644 testdata/val_nsec3_b5_wcnodata.rpl create mode 100644 testdata/val_nsec3_b5_wcnodata_noce.rpl create mode 100644 testdata/val_nsec3_b5_wcnodata_nonc.rpl create mode 100644 testdata/val_nsec3_b5_wcnodata_nowc.rpl create mode 100644 testdata/val_nsec3_cname_ds.rpl create mode 100644 testdata/val_nsec3_cname_par.rpl create mode 100644 testdata/val_nsec3_cname_sub.rpl create mode 100644 testdata/val_nsec3_iter_high.rpl create mode 100644 testdata/val_nsec3_nodatawccname.rpl create mode 100644 testdata/val_nsec3_nods.rpl create mode 100644 testdata/val_nsec3_nods_badopt.rpl create mode 100644 testdata/val_nsec3_nods_badsig.rpl create mode 100644 testdata/val_nsec3_nods_negcache.rpl create mode 100644 testdata/val_nsec3_nods_soa.rpl create mode 100644 testdata/val_nsec3_optout_ad.rpl create mode 100644 testdata/val_nsec3_optout_cache.rpl create mode 100644 testdata/val_nsec3_wcany.rpl create mode 100644 testdata/val_nsec3_wcany_nodeny.rpl create mode 100644 testdata/val_nx.rpl create mode 100644 testdata/val_nx_nodeny.rpl create mode 100644 testdata/val_nx_nowc.rpl create mode 100644 testdata/val_nx_nsec3_collision.rpl create mode 100644 testdata/val_nx_nsec3_params.rpl create mode 100644 testdata/val_nx_overreach.rpl create mode 100644 testdata/val_pos_truncns.rpl create mode 100644 testdata/val_positive.rpl create mode 100644 testdata/val_positive_nosigs.rpl create mode 100644 testdata/val_positive_wc.rpl create mode 100644 testdata/val_positive_wc_nodeny.rpl create mode 100644 testdata/val_qds_badanc.rpl create mode 100644 testdata/val_qds_oneanc.rpl create mode 100644 testdata/val_qds_twoanc.rpl create mode 100644 testdata/val_refer_unsignadd.rpl create mode 100644 testdata/val_referd.rpl create mode 100644 testdata/val_referglue.rpl create mode 100644 testdata/val_rrsig.rpl create mode 100644 testdata/val_secds.rpl create mode 100644 testdata/val_secds_nosig.rpl create mode 100644 testdata/val_stub_noroot.rpl create mode 100644 testdata/val_stubds.rpl create mode 100644 testdata/val_ta_algo_dnskey.rpl create mode 100644 testdata/val_ta_algo_missing.rpl create mode 100644 testdata/val_twocname.rpl create mode 100644 testdata/val_unalgo_anchor.rpl create mode 100644 testdata/val_unalgo_dlv.rpl create mode 100644 testdata/val_unalgo_ds.rpl create mode 100644 testdata/val_unsec_cname.rpl create mode 100644 testdata/val_unsecds.rpl create mode 100644 testdata/val_unsecds_negcache.rpl create mode 100644 testdata/val_unsecds_qtypeds.rpl create mode 100644 testdata/val_wild_pos.rpl create mode 100644 testdata/version_bind.rpl create mode 100644 testdata/version_bind_hide.rpl create mode 100644 util/alloc.c create mode 100644 util/alloc.h create mode 100644 util/config_file.c create mode 100644 util/config_file.h create mode 100644 util/configlexer.c create mode 100644 util/configlexer.lex create mode 100644 util/configparser.c create mode 100644 util/configparser.h create mode 100644 util/configparser.y create mode 100644 util/configyyrename.h create mode 100644 util/data/dname.c create mode 100644 util/data/dname.h create mode 100644 util/data/msgencode.c create mode 100644 util/data/msgencode.h create mode 100644 util/data/msgparse.c create mode 100644 util/data/msgparse.h create mode 100644 util/data/msgreply.c create mode 100644 util/data/msgreply.h create mode 100644 util/data/packed_rrset.c create mode 100644 util/data/packed_rrset.h create mode 100644 util/fptr_wlist.c create mode 100644 util/fptr_wlist.h create mode 100644 util/iana_ports.inc create mode 100644 util/locks.c create mode 100644 util/locks.h create mode 100644 util/log.c create mode 100644 util/log.h create mode 100644 util/mini_event.c create mode 100644 util/mini_event.h create mode 100644 util/module.c create mode 100644 util/module.h create mode 100644 util/net_help.c create mode 100644 util/net_help.h create mode 100644 util/netevent.c create mode 100644 util/netevent.h create mode 100644 util/random.c create mode 100644 util/random.h create mode 100644 util/rbtree.c create mode 100644 util/rbtree.h create mode 100644 util/regional.c create mode 100644 util/regional.h create mode 100644 util/rtt.c create mode 100644 util/rtt.h create mode 100644 util/storage/dnstree.c create mode 100644 util/storage/dnstree.h create mode 100644 util/storage/lookup3.c create mode 100644 util/storage/lookup3.h create mode 100644 util/storage/lruhash.c create mode 100644 util/storage/lruhash.h create mode 100644 util/storage/slabhash.c create mode 100644 util/storage/slabhash.h create mode 100644 util/timehist.c create mode 100644 util/timehist.h create mode 100644 util/tube.c create mode 100644 util/tube.h create mode 100644 util/winsock_event.c create mode 100644 util/winsock_event.h create mode 100644 validator/autotrust.c create mode 100644 validator/autotrust.h create mode 100644 validator/val_anchor.c create mode 100644 validator/val_anchor.h create mode 100644 validator/val_kcache.c create mode 100644 validator/val_kcache.h create mode 100644 validator/val_kentry.c create mode 100644 validator/val_kentry.h create mode 100644 validator/val_neg.c create mode 100644 validator/val_neg.h create mode 100644 validator/val_nsec.c create mode 100644 validator/val_nsec.h create mode 100644 validator/val_nsec3.c create mode 100644 validator/val_nsec3.h create mode 100644 validator/val_sigcrypt.c create mode 100644 validator/val_sigcrypt.h create mode 100644 validator/val_utils.c create mode 100644 validator/val_utils.h create mode 100644 validator/validator.c create mode 100644 validator/validator.h create mode 100644 winrc/README.txt create mode 100644 winrc/anchor-update.c create mode 100644 winrc/combined.ico create mode 100644 winrc/gen_msg.bin create mode 100644 winrc/gen_msg.mc create mode 100644 winrc/rsrc_anchorupd.rc create mode 100644 winrc/rsrc_svcinst.rc create mode 100644 winrc/rsrc_svcuninst.rc create mode 100644 winrc/rsrc_unbound.rc create mode 100644 winrc/rsrc_unbound_anchor.rc create mode 100644 winrc/rsrc_unbound_checkconf.rc create mode 100644 winrc/rsrc_unbound_control.rc create mode 100644 winrc/rsrc_unbound_host.rc create mode 100644 winrc/service.conf create mode 100644 winrc/setup.nsi create mode 100644 winrc/setup_left.bmp create mode 100644 winrc/setup_top.bmp create mode 100644 winrc/unbound-service-install.c create mode 100644 winrc/unbound-service-remove.c create mode 100644 winrc/unbound-website.url create mode 100644 winrc/unbound16.ico create mode 100644 winrc/unbound32.ico create mode 100644 winrc/unbound48.ico create mode 100644 winrc/unbound64.ico create mode 100644 winrc/unbound64.png create mode 100644 winrc/vista_admin.manifest create mode 100644 winrc/vista_user.manifest create mode 100644 winrc/w_inst.c create mode 100644 winrc/w_inst.h create mode 100644 winrc/win_svc.c create mode 100644 winrc/win_svc.h diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000000..c248049fb8d --- /dev/null +++ b/LICENSE @@ -0,0 +1,30 @@ +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 REGENTS OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 00000000000..af9fba80656 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,1193 @@ +# Copyright 2007 NLnet Labs +# See the file LICENSE for the license + +SHELL=@SHELL@ +VERSION=@PACKAGE_VERSION@ +srcdir=@srcdir@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +bindir=@bindir@ +sbindir=@sbindir@ +mandir=@mandir@ +libdir=@libdir@ +# datarootdir is here to please some checkers, use datadir. +datarootdir=@datarootdir@ +datadir=@datadir@ +includedir=@includedir@ +doxygen=@doxygen@ +libtool=@libtool@ +ldnsdir=@ldnsdir@ +staticexe=@staticexe@ +EXEEXT=@EXEEXT@ +configfile=@ub_conf_file@ +UNBOUND_RUN_DIR=@UNBOUND_RUN_DIR@ +CHECKLOCK_SRC=testcode/checklocks.c +CHECKLOCK_OBJ=@CHECKLOCK_OBJ@ +WITH_PYTHONMODULE=@WITH_PYTHONMODULE@ +WITH_PYUNBOUND=@WITH_PYUNBOUND@ +PYTHON_SITE_PKG=@PYTHON_SITE_PKG@ +PYTHONMOD_INSTALL=@PYTHONMOD_INSTALL@ +PYTHONMOD_UNINSTALL=@PYTHONMOD_UNINSTALL@ +PYUNBOUND_INSTALL=@PYUNBOUND_INSTALL@ +PYUNBOUND_UNINSTALL=@PYUNBOUND_UNINSTALL@ + +# _unbound.la if pyunbound enabled. +PYUNBOUND_TARGET=@PYUNBOUND_TARGET@ + +# override $U variable which is used by autotools for deansification (for +# K&R C compilers), but causes problems if $U is defined in the env). +U= + +SWIG=@SWIG@ +YACC=@YACC@ +LEX=@LEX@ +STRIP=@STRIP@ +CC=@CC@ +CPPFLAGS=-I. @CPPFLAGS@ +CFLAGS=@CFLAGS@ +LDFLAGS=@LDFLAGS@ +LIBS=@LIBS@ +LIBOBJS=@LIBOBJS@ +# filter out ctime_r from compat obj. +LIBOBJ_WITHOUT_CTIME=@LIBOBJ_WITHOUT_CTIME@ +RUNTIME_PATH=@RUNTIME_PATH@ +DEPFLAG=@DEPFLAG@ +DATE=@CONFIG_DATE@ +LIBTOOL=$(libtool) +BUILD=build/ +UBSYMS=@UBSYMS@ +EXTRALINK=@EXTRALINK@ + +WINDRES=@WINDRES@ +LINT=splint +LINTFLAGS=+quiet -weak -warnposix -unrecog -Din_addr_t=uint32_t -Du_int=unsigned -Du_char=uint8_t -preproc -Drlimit=rlimit64 -D__gnuc_va_list=va_list +#-Dglob64=glob -Dglobfree64=globfree +# compat with openssl linux edition. +LINTFLAGS+="-DBN_ULONG=unsigned long" -Dkrb5_int32=int "-Dkrb5_ui_4=unsigned int" -DPQ_64BIT=uint64_t -DRC4_INT=unsigned -fixedformalarray -D"ENGINE=unsigned" -D"RSA=unsigned" -D"DSA=unsigned" -D"EVP_PKEY=unsigned" -D"EVP_MD=unsigned" -D"SSL=unsigned" -D"SSL_CTX=unsigned" -D"X509=unsigned" -D"RC4_KEY=unsigned" -D"EVP_MD_CTX=unsigned" -D"ECDSA_SIG=DSA_SIG" +# compat with NetBSD +LINTFLAGS+=@NETBSD_LINTFLAGS@ +# compat with OpenBSD +LINTFLAGS+="-Dsigset_t=long" +# FreeBSD8 +LINTFLAGS+="-D__uint16_t=uint16_t" + +INSTALL=$(srcdir)/install-sh + +#pythonmod.c is not here, it is mentioned by itself in its own rules, +#makedepend fails on missing interface.h otherwise. +PYTHONMOD_SRC=pythonmod/pythonmod_utils.c +# pythonmod.lo pythonmod_utils.lo if python mod enabled. +PYTHONMOD_OBJ=@PYTHONMOD_OBJ@ +PYTHONMOD_HEADER=@PYTHONMOD_HEADER@ +# libunbound/python/libunbound_wrap.c is dealt with by its own rules. +PYUNBOUND_SRC= +# libunbound_wrap.lo if python libunbound wrapper enabled. +PYUNBOUND_OBJ=@PYUNBOUND_OBJ@ +COMMON_SRC=services/cache/dns.c services/cache/infra.c services/cache/rrset.c \ +util/data/dname.c util/data/msgencode.c util/data/msgparse.c \ +util/data/msgreply.c util/data/packed_rrset.c iterator/iterator.c \ +iterator/iter_delegpt.c iterator/iter_donotq.c iterator/iter_fwd.c \ +iterator/iter_hints.c iterator/iter_priv.c iterator/iter_resptype.c \ +iterator/iter_scrub.c iterator/iter_utils.c services/listen_dnsport.c \ +services/localzone.c services/mesh.c services/modstack.c \ +services/outbound_list.c services/outside_network.c util/alloc.c \ +util/config_file.c util/configlexer.c util/configparser.c \ +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_sigcrypt.c validator/val_utils.c $(CHECKLOCK_SRC) +COMMON_OBJ_WITHOUT_NETCALL=dns.lo infra.lo rrset.lo dname.lo msgencode.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 \ +iter_scrub.lo iter_utils.lo localzone.lo mesh.lo modstack.lo \ +outbound_list.lo alloc.lo config_file.lo configlexer.lo configparser.lo \ +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_sigcrypt.lo val_utils.lo $(PYTHONMOD_OBJ) $(CHECKLOCK_OBJ) +COMMON_OBJ=$(COMMON_OBJ_WITHOUT_NETCALL) netevent.lo listen_dnsport.lo \ +outside_network.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 \ +compat/inet_aton.c compat/inet_ntop.c compat/inet_pton.c compat/malloc.c \ +compat/memcmp.c compat/memmove.c compat/snprintf.c compat/strlcpy.c \ +compat/strptime.c +COMPAT_OBJ=$(LIBOBJS:.o=.lo) +COMPAT_OBJ_WITHOUT_CTIME=$(LIBOBJ_WITHOUT_CTIME:.o=.lo) +UNITTEST_SRC=testcode/unitanchor.c testcode/unitdname.c \ +testcode/unitlruhash.c testcode/unitmain.c testcode/unitmsgparse.c \ +testcode/unitneg.c testcode/unitregional.c testcode/unitslabhash.c \ +testcode/unitverify.c testcode/readhex.c testcode/ldns-testpkts.c +UNITTEST_OBJ=unitanchor.lo unitdname.lo unitlruhash.lo unitmain.lo \ +unitmsgparse.lo unitneg.lo unitregional.lo unitslabhash.lo unitverify.lo \ +readhex.lo ldns-testpkts.lo +UNITTEST_OBJ_LINK=$(UNITTEST_OBJ) worker_cb.lo $(COMMON_OBJ) $(COMPAT_OBJ) +DAEMON_SRC=daemon/acl_list.c daemon/cachedump.c daemon/daemon.c \ +daemon/remote.c daemon/stats.c daemon/unbound.c daemon/worker.c @WIN_DAEMON_SRC@ +DAEMON_OBJ=acl_list.lo cachedump.lo daemon.lo remote.lo stats.lo unbound.lo \ +worker.lo @WIN_DAEMON_OBJ@ +DAEMON_OBJ_LINK=$(DAEMON_OBJ) $(COMMON_OBJ_ALL_SYMBOLS) \ +$(COMPAT_OBJ) @WIN_DAEMON_OBJ_LINK@ +CHECKCONF_SRC=smallapp/unbound-checkconf.c smallapp/worker_cb.c +CHECKCONF_OBJ=unbound-checkconf.lo worker_cb.lo +CHECKCONF_OBJ_LINK=$(CHECKCONF_OBJ) $(COMMON_OBJ_ALL_SYMBOLS) \ +$(COMPAT_OBJ) @WIN_CHECKCONF_OBJ_LINK@ +CONTROL_SRC=smallapp/unbound-control.c +CONTROL_OBJ=unbound-control.lo +CONTROL_OBJ_LINK=$(CONTROL_OBJ) worker_cb.lo $(COMMON_OBJ_ALL_SYMBOLS) \ +$(COMPAT_OBJ) @WIN_CONTROL_OBJ_LINK@ +HOST_SRC=smallapp/unbound-host.c +HOST_OBJ=unbound-host.lo +HOST_OBJ_LINK=$(HOST_OBJ) $(COMPAT_OBJ_WITHOUT_CTIME) @WIN_HOST_OBJ_LINK@ +UBANCHOR_SRC=smallapp/unbound-anchor.c +UBANCHOR_OBJ=unbound-anchor.lo +UBANCHOR_OBJ_LINK=$(UBANCHOR_OBJ) \ +$(COMPAT_OBJ_WITHOUT_CTIME) @WIN_UBANCHOR_OBJ_LINK@ +TESTBOUND_SRC=testcode/testbound.c testcode/ldns-testpkts.c \ +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) ldns-testpkts.lo worker.lo acl_list.lo \ +daemon.lo stats.lo $(COMMON_OBJ_WITHOUT_NETCALL) $(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) +PETAL_SRC=testcode/petal.c +PETAL_OBJ=petal.lo +PETAL_OBJ_LINK=$(PETAL_OBJ) $(COMPAT_OBJ_WITHOUT_CTIME) +PKTVIEW_SRC=testcode/pktview.c testcode/readhex.c +PKTVIEW_OBJ=pktview.lo +PKTVIEW_OBJ_LINK=$(PKTVIEW_OBJ) worker_cb.lo readhex.lo $(COMMON_OBJ) \ +$(COMPAT_OBJ) +SIGNIT_SRC=testcode/signit.c +SIGNIT_OBJ=signit.lo +SIGNIT_OBJ_LINK=$(SIGNIT_OBJ) worker_cb.lo $(COMMON_OBJ) $(COMPAT_OBJ) +MEMSTATS_SRC=testcode/memstats.c +MEMSTATS_OBJ=memstats.lo +MEMSTATS_OBJ_LINK=$(MEMSTATS_OBJ) worker_cb.lo $(COMMON_OBJ) $(COMPAT_OBJ) +ASYNCLOOK_SRC=testcode/asynclook.c +ASYNCLOOK_OBJ=asynclook.lo +ASYNCLOOK_OBJ_LINK=$(ASYNCLOOK_OBJ) log.lo locks.lo $(COMPAT_OBJ) +STREAMTCP_SRC=testcode/streamtcp.c +STREAMTCP_OBJ=streamtcp.lo +STREAMTCP_OBJ_LINK=$(STREAMTCP_OBJ) worker_cb.lo $(COMMON_OBJ) $(COMPAT_OBJ) +PERF_SRC=testcode/perf.c +PERF_OBJ=perf.lo +PERF_OBJ_LINK=$(PERF_OBJ) worker_cb.lo $(COMMON_OBJ) $(COMPAT_OBJ) +DELAYER_SRC=testcode/delayer.c +DELAYER_OBJ=delayer.lo +DELAYER_OBJ_LINK=$(DELAYER_OBJ) worker_cb.lo $(COMMON_OBJ) $(COMPAT_OBJ) +HARVEST_SRC=testcode/harvest.c +HARVEST_OBJ=harvest.lo +HARVEST_OBJ_LINK=$(HARVEST_OBJ) $(COMPAT_OBJ_WITHOUT_CTIME) +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) $(COMPAT_OBJ) + +# win apps or "" if not on windows +WINAPPS=@WINAPPS@ +WIN_DAEMON_THE_SRC=winrc/win_svc.c winrc/w_inst.c +SVCINST_SRC=winrc/unbound-service-install.c +SVCINST_OBJ=unbound-service-install.lo +SVCINST_OBJ_LINK=$(SVCINST_OBJ) w_inst.lo rsrc_svcinst.o $(COMPAT_OBJ_WITHOUT_CTIME) +SVCUNINST_SRC=winrc/unbound-service-remove.c +SVCUNINST_OBJ=unbound-service-remove.lo +SVCUNINST_OBJ_LINK=$(SVCUNINST_OBJ) w_inst.lo rsrc_svcuninst.o \ +$(COMPAT_OBJ_WITHOUT_CTIME) +ANCHORUPD_SRC=winrc/anchor-update.c +ANCHORUPD_OBJ=anchor-update.lo +ANCHORUPD_OBJ_LINK=$(ANCHORUPD_OBJ) rsrc_anchorupd.o $(COMPAT_OBJ_WITHOUT_CTIME) +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 + +ALL_SRC=$(COMMON_SRC) $(UNITTEST_SRC) $(DAEMON_SRC) \ + $(TESTBOUND_SRC) $(LOCKVERIFY_SRC) $(PKTVIEW_SRC) $(SIGNIT_SRC) \ + $(MEMSTATS_SRC) $(CHECKCONF_SRC) $(LIBUNBOUND_SRC) $(HOST_SRC) \ + $(ASYNCLOOK_SRC) $(STREAMTCP_SRC) $(PERF_SRC) $(DELAYER_SRC) \ + $(HARVEST_SRC) $(CONTROL_SRC) $(UBANCHOR_SRC) $(PETAL_SRC) \ + $(PYTHONMOD_SRC) $(PYUNBOUND_SRC) $(WIN_DAEMON_THE_SRC)\ + $(SVCINST_SRC) $(SVCUNINST_SRC) $(ANCHORUPD_SRC) +ALL_OBJ=$(COMMON_OBJ) $(UNITTEST_OBJ) $(DAEMON_OBJ) \ + $(TESTBOUND_OBJ) $(LOCKVERIFY_OBJ) $(PKTVIEW_OBJ) $(SIGNIT_OBJ) \ + $(MEMSTATS_OBJ) $(CHECKCONF_OBJ) $(LIBUNBOUND_OBJ) $(HOST_OBJ) \ + $(ASYNCLOOK_OBJ) $(STREAMTCP_OBJ) $(PERF_OBJ) $(DELAYER_OBJ) \ + $(HARVEST_OBJ) $(CONTROL_OBJ) $(UBANCHOR_OBJ) $(PETAL_OBJ) \ + $(COMPAT_OBJ) $(PYUNBOUND_OBJ) \ + $(SVCINST_OBJ) $(SVCUNINST_OBJ) $(ANCHORUPD_OBJ) + +COMPILE=$(LIBTOOL) --tag=CC --mode=compile $(CC) $(CPPFLAGS) $(CFLAGS) +LINK=$(LIBTOOL) --tag=CC --mode=link $(CC) $(staticexe) $(RUNTIME_PATH) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) +LINK_LIB=$(LIBTOOL) --tag=CC --mode=link $(CC) $(RUNTIME_PATH) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(staticexe) -version-info @LIBUNBOUND_CURRENT@:@LIBUNBOUND_REVISION@:@LIBUNBOUND_AGE@ -no-undefined + +.PHONY: clean realclean doc lint all install uninstall tests test strip lib longtest longcheck check + +all: $(COMMON_OBJ) unbound$(EXEEXT) unbound-checkconf$(EXEEXT) lib unbound-host$(EXEEXT) unbound-control$(EXEEXT) unbound-anchor$(EXEEXT) unbound-control-setup $(WINAPPS) $(PYUNBOUND_TARGET) + +# compat with BSD make, register suffix, and an implicit rule to actualise it. +.SUFFIXES: .lo +.c.lo: + $(COMPILE) -o $@ -c $< + +$(ALL_OBJ): + @@SOURCEDETERMINE@ + $(COMPILE) -o $@ -c @SOURCEFILE@ + +$(RSRC_OBJ): + @@SOURCEDETERMINE@ + $(WINDRES) $(CPPFLAGS) @SOURCEFILE@ $@ + +rsrc_svcinst.o: $(srcdir)/winrc/rsrc_svcinst.rc config.h +rsrc_svcuninst.o: $(srcdir)/winrc/rsrc_svcuninst.rc config.h +rsrc_anchorupd.o: $(srcdir)/winrc/rsrc_anchorupd.rc config.h +rsrc_unbound.o: $(srcdir)/winrc/rsrc_unbound.rc config.h +rsrc_unbound_host.o: $(srcdir)/winrc/rsrc_unbound_host.rc config.h +rsrc_unbound_anchor.o: $(srcdir)/winrc/rsrc_unbound_anchor.rc config.h +rsrc_unbound_control.o: $(srcdir)/winrc/rsrc_unbound_control.rc config.h +rsrc_unbound_checkconf.o: $(srcdir)/winrc/rsrc_unbound_checkconf.rc config.h + +TEST_BIN=asynclook$(EXEEXT) delayer$(EXEEXT) harvest$(EXEEXT) \ + lock-verify$(EXEEXT) memstats$(EXEEXT) perf$(EXEEXT) \ + petal$(EXEEXT) pktview$(EXEEXT) signit$(EXEEXT) streamtcp$(EXEEXT) \ + testbound$(EXEEXT) unittest$(EXEEXT) +tests: all $(TEST_BIN) + +check: test +longcheck: longtest + +test: unittest$(EXEEXT) testbound$(EXEEXT) + ./unittest$(EXEEXT) + ./testbound$(EXEEXT) -s + for x in testdata/*.rpl; do echo -n "$$x "; if ./testbound$(EXEEXT) -p $$x >/dev/null 2>&1; then echo OK; else echo failed; exit 1; fi done + @echo test OK + +longtest: tests + if test -x "`which bash`"; then bash testcode/do-tests.sh; else sh testcode/do-tests.sh; fi + +lib: libunbound.la + +libunbound.la: $(LIBUNBOUND_OBJ_LINK) + $(LINK_LIB) $(UBSYMS) -o $@ $(LIBUNBOUND_OBJ_LINK) -rpath $(libdir) -lssl $(LIBS) + +unbound$(EXEEXT): $(DAEMON_OBJ_LINK) libunbound.la + $(LINK) -o $@ $(DAEMON_OBJ_LINK) $(EXTRALINK) -lssl $(LIBS) + +unbound-checkconf$(EXEEXT): $(CHECKCONF_OBJ_LINK) libunbound.la + $(LINK) -o $@ $(CHECKCONF_OBJ_LINK) $(EXTRALINK) -lssl $(LIBS) + +unbound-control$(EXEEXT): $(CONTROL_OBJ_LINK) libunbound.la + $(LINK) -o $@ $(CONTROL_OBJ_LINK) $(EXTRALINK) -lssl $(LIBS) + +unbound-host$(EXEEXT): $(HOST_OBJ_LINK) libunbound.la + $(LINK) -o $@ $(HOST_OBJ_LINK) -L. -L.libs -lunbound $(LIBS) + +unbound-anchor$(EXEEXT): $(UBANCHOR_OBJ_LINK) libunbound.la + $(LINK) -o $@ $(UBANCHOR_OBJ_LINK) -L. -L.libs -lunbound -lexpat -lssl $(LIBS) + +unbound-service-install$(EXEEXT): $(SVCINST_OBJ_LINK) + $(LINK) -o $@ $(SVCINST_OBJ_LINK) $(LIBS) + +unbound-service-remove$(EXEEXT): $(SVCUNINST_OBJ_LINK) + $(LINK) -o $@ $(SVCUNINST_OBJ_LINK) $(LIBS) + +anchor-update$(EXEEXT): $(ANCHORUPD_OBJ_LINK) libunbound.la + $(LINK) -o $@ $(ANCHORUPD_OBJ_LINK) -L. -L.libs -lunbound $(LIBS) + +unittest$(EXEEXT): $(UNITTEST_OBJ_LINK) + $(LINK) -o $@ $(UNITTEST_OBJ_LINK) -lssl $(LIBS) + +testbound$(EXEEXT): $(TESTBOUND_OBJ_LINK) + $(LINK) -o $@ $(TESTBOUND_OBJ_LINK) -lssl $(LIBS) + +lock-verify$(EXEEXT): $(LOCKVERIFY_OBJ_LINK) + $(LINK) -o $@ $(LOCKVERIFY_OBJ_LINK) -lssl $(LIBS) + +petal$(EXEEXT): $(PETAL_OBJ_LINK) + $(LINK) -o $@ $(PETAL_OBJ_LINK) -lssl $(LIBS) + +pktview$(EXEEXT): $(PKTVIEW_OBJ_LINK) + $(LINK) -o $@ $(PKTVIEW_OBJ_LINK) -lssl $(LIBS) + +signit$(EXEEXT): $(SIGNIT_OBJ_LINK) + $(LINK) -o $@ $(SIGNIT_OBJ_LINK) -lssl $(LIBS) + +memstats$(EXEEXT): $(MEMSTATS_OBJ_LINK) + $(LINK) -o $@ $(MEMSTATS_OBJ_LINK) -lssl $(LIBS) + +asynclook$(EXEEXT): $(ASYNCLOOK_OBJ_LINK) libunbound.la + $(LINK) -o $@ $(ASYNCLOOK_OBJ_LINK) $(LIBS) -L. -L.libs -lunbound + +streamtcp$(EXEEXT): $(STREAMTCP_OBJ_LINK) + $(LINK) -o $@ $(STREAMTCP_OBJ_LINK) -lssl $(LIBS) + +perf$(EXEEXT): $(PERF_OBJ_LINK) + $(LINK) -o $@ $(PERF_OBJ_LINK) -lssl $(LIBS) + +delayer$(EXEEXT): $(DELAYER_OBJ_LINK) + $(LINK) -o $@ $(DELAYER_OBJ_LINK) -lssl $(LIBS) + +harvest$(EXEEXT): $(HARVEST_OBJ_LINK) libunbound.la + $(LINK) -o $@ $(HARVEST_OBJ_LINK) $(LIBS) -L. -L.libs -lunbound + +unbound-control-setup: $(srcdir)/smallapp/unbound-control-setup.sh + sed -e 's:^DESTDIR=.*$$:DESTDIR=$(UNBOUND_RUN_DIR):' < $(srcdir)/smallapp/unbound-control-setup.sh > $@ + -chmod +x $@ + +#testcode/ldns-testpkts.c: $(ldnsdir)/examples/ldns-testpkts.c \ +# $(ldnsdir)/examples/ldns-testpkts.h +# cp $(ldnsdir)/examples/ldns-testpkts.c testcode/ldns-testpkts.c +# cp $(ldnsdir)/examples/ldns-testpkts.h testcode/ldns-testpkts.h + +# Python Module +pythonmod.lo pythonmod.o: $(srcdir)/pythonmod/pythonmod.c config.h \ + pythonmod/interface.h \ + $(srcdir)/pythonmod/pythonmod.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)/services/outbound_list.h $(srcdir)/util/config_file.h \ + $(srcdir)/pythonmod/pythonmod_utils.h $(srcdir)/util/netevent.h \ + $(srcdir)/util/regional.h $(srcdir)/util/data/dname.h \ + $(srcdir)/services/cache/dns.h $(srcdir)/services/mesh.h \ + $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h + +pythonmod/interface.h: $(srcdir)/pythonmod/interface.i $(srcdir)/config.h + @-if test ! -d pythonmod; then $(INSTALL) -d pythonmod; fi + $(SWIG) $(CPPFLAGS) -o $@ -python $(srcdir)/pythonmod/interface.i + +libunbound_wrap.lo libunbound_wrap.o: libunbound/python/libunbound_wrap.c \ + $(srcdir)/libunbound/unbound.h +libunbound/python/libunbound_wrap.c: $(srcdir)/libunbound/python/libunbound.i $(srcdir)/libunbound/unbound.h + @-if test ! -d libunbound/python; then $(INSTALL) -d libunbound/python; fi + $(SWIG) -python -o $@ $(CPPFLAGS) $(srcdir)/libunbound/python/libunbound.i + +# Pyunbound python unbound wrapper +_unbound.la: libunbound_wrap.lo libunbound.la + $(LIBTOOL) --tag=CC --mode=link $(CC) $(RUNTIME_PATH) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -module -version-info @LIBUNBOUND_CURRENT@:@LIBUNBOUND_REVISION@:@LIBUNBOUND_AGE@ -no-undefined -o $@ libunbound_wrap.lo -rpath $(PYTHON_SITE_PKG) L. -L.libs -lunbound $(LIBS) + +util/config_file.c: util/configparser.h +util/configlexer.c: $(srcdir)/util/configlexer.lex util/configparser.h + @-if test ! -d util; then $(INSTALL) -d util; fi + if test "$(LEX)" != ":"; then \ + echo "#include \"config.h\"" > $@ ;\ + echo "#include \"util/configyyrename.h\"" >> $@ ;\ + $(LEX) -t $(srcdir)/util/configlexer.lex >> $@ ;\ + fi + +util/configparser.c util/configparser.h: $(srcdir)/util/configparser.y + @-if test ! -d util; then $(INSTALL) -d util; fi + $(YACC) -d -o util/configparser.c $(srcdir)/util/configparser.y + +clean: + rm -f *.o *.d *.lo *~ tags + rm -f unbound$(EXEEXT) unbound-checkconf$(EXEEXT) unbound-host$(EXEEXT) unbound-control$(EXEEXT) unbound-anchor$(EXEEXT) unbound-control-setup libunbound.la + rm -f $(ALL_SRC:.c=.lint) + rm -rf autom4te.cache .libs build doc/html doc/xml + +realclean: clean + rm -f config.status config.log config.h.in config.h + rm -f configure config.sub config.guess ltmain.sh aclocal.m4 libtool + rm -f util/configlexer.c util/configparser.c util/configparser.h + rm -f $(TEST_BIN) + rm -f Makefile + +.SUFFIXES: .lint +.c.lint: + $(LINT) $(LINTFLAGS) -I. -I$(srcdir) -I$(ldnsdir)/include $< + touch $@ + +util/configparser.lint util/configlexer.lint pythonmod/pythonmod.lint libunbound/python/libunbound_wrap.lint: + # skip lint for generated code + touch $@ + +winrc/win_svc.lint winrc/w_inst.lint winrc/unbound-service-install.lint winrc/unbound-service-remove.lint: + # skip lint for windows types + touch $@ + +lint: $(ALL_SRC:.c=.lint) + +tags: $(srcdir)/*.[ch] $(srcdir)/*/*.[ch] + ctags -f $(srcdir)/tags $(srcdir)/*.[ch] $(srcdir)/*/*.[ch] + +doc: + if test -n "$(doxygen)"; then \ + $(doxygen) $(srcdir)/doc/unbound.doxygen; fi + if test "$(WITH_PYUNBOUND)" = "yes" -o "$(WITH_PYTHONMODULE)" = "yes"; \ + then if test -x "`which sphinx-build 2>&1`"; then \ + sphinx-build -b html pythonmod/doc doc/html/pythonmod; \ + sphinx-build -b html libunbound/python/doc doc/html/pyunbound;\ + fi ;\ + fi + +strip: + $(STRIP) unbound$(EXEEXT) + $(STRIP) unbound-checkconf$(EXEEXT) + $(STRIP) unbound-control$(EXEEXT) + $(STRIP) unbound-host$(EXEEXT) + $(STRIP) unbound-anchor$(EXEEXT) + +pythonmod-install: + $(INSTALL) -m 755 -d $(DESTDIR)$(PYTHON_SITE_PKG) + $(INSTALL) -c -m 644 pythonmod/unboundmodule.py $(DESTDIR)$(PYTHON_SITE_PKG)/unboundmodule.py + +pyunbound-install: + $(INSTALL) -m 755 -d $(DESTDIR)$(PYTHON_SITE_PKG) + $(INSTALL) -c -m 644 libunbound/python/unbound.py $(DESTDIR)$(PYTHON_SITE_PKG)/unbound.py + $(LIBTOOL) --mode=install cp _unbound.la $(DESTDIR)$(PYTHON_SITE_PKG) + $(LIBTOOL) --mode=finish $(DESTDIR)$(PYTHON_SITE_PKG) + +install: all $(PYTHONMOD_INSTALL) $(PYUNBOUND_INSTALL) + $(INSTALL) -m 755 -d $(DESTDIR)$(sbindir) + $(INSTALL) -m 755 -d $(DESTDIR)$(mandir) + $(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man8 + $(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man5 + $(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man3 + $(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man1 + $(INSTALL) -m 755 -d $(DESTDIR)$(libdir) + $(INSTALL) -m 755 -d $(DESTDIR)$(includedir) + $(LIBTOOL) --mode=install cp unbound$(EXEEXT) $(DESTDIR)$(sbindir)/unbound$(EXEEXT) + $(LIBTOOL) --mode=install cp unbound-checkconf$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-checkconf$(EXEEXT) + $(LIBTOOL) --mode=install cp unbound-control$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-control$(EXEEXT) + $(LIBTOOL) --mode=install cp unbound-host$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-host$(EXEEXT) + $(LIBTOOL) --mode=install cp unbound-anchor$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-anchor$(EXEEXT) + $(INSTALL) -c -m 644 doc/unbound.8 $(DESTDIR)$(mandir)/man8 + $(INSTALL) -c -m 644 doc/unbound-checkconf.8 $(DESTDIR)$(mandir)/man8 + $(INSTALL) -c -m 644 doc/unbound-control.8 $(DESTDIR)$(mandir)/man8 + $(INSTALL) -c -m 644 doc/unbound-anchor.8 $(DESTDIR)$(mandir)/man8 + $(INSTALL) -c -m 644 doc/unbound.conf.5 $(DESTDIR)$(mandir)/man5 + $(INSTALL) -c -m 644 $(srcdir)/doc/unbound-host.1 $(DESTDIR)$(mandir)/man1 + $(INSTALL) -c -m 644 doc/libunbound.3 $(DESTDIR)$(mandir)/man3 + $(INSTALL) -c -m 755 unbound-control-setup $(DESTDIR)$(sbindir)/unbound-control-setup + if test ! -e $(DESTDIR)$(configfile); then $(INSTALL) -d `dirname $(DESTDIR)$(configfile)`; $(INSTALL) -c -m 644 doc/example.conf $(DESTDIR)$(configfile); fi + $(LIBTOOL) --mode=install cp $(srcdir)/libunbound/unbound.h $(DESTDIR)$(includedir)/unbound.h + $(LIBTOOL) --mode=install cp libunbound.la $(DESTDIR)$(libdir) + $(LIBTOOL) --mode=finish $(DESTDIR)$(libdir) + +pythonmod-uninstall: + rm -f -- $(DESTDIR)$(PYTHON_SITE_PKG)/unboundmodule.py + +pyunbound-uninstall: + rm -f -- $(DESTDIR)$(PYTHON_SITE_PKG)/unbound.py + $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(PYTHON_SITE_PKG)/_unbound.la + +uninstall: $(PYTHONMOD_UNINSTALL) $(PYUNBOUND_UNINSTALL) + rm -f -- $(DESTDIR)$(sbindir)/unbound$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-checkconf$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-host$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-control$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-anchor$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-control-setup + rm -f -- $(DESTDIR)$(mandir)/man8/unbound.8 $(DESTDIR)$(mandir)/man8/unbound-checkconf.8 $(DESTDIR)$(mandir)/man5/unbound.conf.5 $(DESTDIR)$(mandir)/man8/unbound-control.8 $(DESTDIR)$(mandir)/man8/unbound-anchor.8 + rm -f -- $(DESTDIR)$(mandir)/man1/unbound-host.1 $(DESTDIR)$(mandir)/man3/libunbound.3 + rm -f -- $(DESTDIR)$(includedir)/unbound.h + $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/libunbound.la + @echo + @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 + if file port-numbers.tmp | grep 'gzip' >/dev/null; then zcat port-numbers.tmp; else cat port-numbers.tmp; fi | awk '// {p=0;} /udp/ {p=1;} /[^u]/ {p=0;} /Decomissioned|Decommissioned|Removed|De-registered|unassigned|Unassigned|Reserved/ {u=1;} // { 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 + +# dependency generation +DEPEND_TMP=depend1073.tmp +DEPEND_TMP2=depend1074.tmp +DEPEND_TARGET=Makefile +DEPEND_TARGET2=Makefile.in +# actions: generate deplines from gcc, +# then, filter out home/xx, /usr/xx and /opt/xx lines (some cc already do this) +# then, remove empty " \" lines +# then, add srcdir before .c and .h in deps. +# then, remove srcdir from the (generated) parser and lexer. +# and mention the .lo +depend: + (cd $(srcdir) ; $(CC) $(DEPFLAG) $(CPPFLAGS) $(CFLAGS) $(ALL_SRC) $(COMPAT_SRC)) | \ + sed -e 's!'$$HOME'[^ ]* !!g' -e 's!'$$HOME'[^ ]*$$!!g' \ + -e 's!/usr[^ ]* !!g' -e 's!/usr[^ ]*$$!!g' \ + -e 's!/opt[^ ]* !!g' -e 's!/opt[^ ]*$$!!g' | \ + sed -e '/^ \\$$/d' | \ + sed -e 's? *\([^ ]*\.[ch]\)? $$(srcdir)/\1?g' | \ + sed -e 's? *\([^ ]*\.inc\)? $$(srcdir)/\1?g' | \ + sed -e 's?$$(srcdir)/config.h?config.h?g' \ + -e 's?$$(srcdir)/util/configlexer.c?util/configlexer.c?g' \ + -e 's?$$(srcdir)/util/configparser.c?util/configparser.c?g' \ + -e 's?$$(srcdir)/util/configparser.h?util/configparser.h?g' \ + -e 's?$$(srcdir)/pythonmod/pythonmod.h?$$(PYTHONMOD_HEADER)?g' \ + -e 's!\(.*\)\.o[ :]*!\1.lo \1.o: !g' \ + > $(DEPEND_TMP) + cp $(DEPEND_TARGET) $(DEPEND_TMP2) + head -`egrep -n "# Dependencies" $(DEPEND_TARGET) | tail -1 | sed -e 's/:.*$$//'` $(DEPEND_TMP2) > $(DEPEND_TARGET) + cat $(DEPEND_TMP) >> $(DEPEND_TARGET) + @if diff $(DEPEND_TARGET) $(DEPEND_TMP2); then echo " $(DEPEND_TARGET) unchanged"; else echo " Updated $(DEPEND_TARGET))"; fi + @if test -f $(DEPEND_TARGET2); then \ + cp $(DEPEND_TARGET2) $(DEPEND_TMP2); \ + head -`egrep -n "# Dependencies" $(DEPEND_TARGET2) | tail -1 | sed -e 's/:.*$$//'` $(DEPEND_TMP2) > $(DEPEND_TARGET2); \ + cat $(DEPEND_TMP) >> $(DEPEND_TARGET2); \ + if diff $(DEPEND_TARGET2) $(DEPEND_TMP2); then echo " $(DEPEND_TARGET2) unchanged"; else echo " Updated $(DEPEND_TARGET2))"; fi; \ + fi + rm -f $(DEPEND_TMP) $(DEPEND_TMP2) + +# Dependencies +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 $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \ + $(srcdir)/util/data/dname.h $(srcdir)/util/module.h $(srcdir)/util/data/msgparse.h \ + $(srcdir)/util/net_help.h \ + $(srcdir)/util/regional.h $(srcdir)/util/config_file.h +infra.lo infra.o: $(srcdir)/services/cache/infra.c config.h \ + $(srcdir)/services/cache/infra.h \ + $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/rtt.h \ + $(srcdir)/util/storage/slabhash.h $(srcdir)/util/storage/lookup3.h $(srcdir)/util/data/dname.h \ + $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h $(srcdir)/iterator/iterator.h \ + $(srcdir)/services/outbound_list.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \ + $(srcdir)/util/module.h $(srcdir)/util/data/msgparse.h \ + +rrset.lo rrset.o: $(srcdir)/services/cache/rrset.c config.h $(srcdir)/services/cache/rrset.h \ + $(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)/util/config_file.h \ + $(srcdir)/util/data/msgreply.h $(srcdir)/util/regional.h $(srcdir)/util/alloc.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)/util/storage/lookup3.h +msgencode.lo msgencode.o: $(srcdir)/util/data/msgencode.c config.h \ + $(srcdir)/util/data/msgencode.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/data/msgparse.h $(srcdir)/util/data/dname.h \ + $(srcdir)/util/regional.h $(srcdir)/util/net_help.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)/util/net_help.h \ + $(srcdir)/util/data/dname.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lookup3.h \ + $(srcdir)/util/regional.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 \ + $(srcdir)/util/data/dname.h $(srcdir)/util/regional.h $(srcdir)/util/data/msgparse.h \ + $(srcdir)/util/data/msgencode.h +packed_rrset.lo packed_rrset.o: $(srcdir)/util/data/packed_rrset.c config.h \ + $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \ + $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lookup3.h $(srcdir)/util/alloc.h $(srcdir)/util/regional.h \ + $(srcdir)/util/net_help.h +iterator.lo iterator.o: $(srcdir)/iterator/iterator.c config.h \ + $(srcdir)/iterator/iterator.h \ + $(srcdir)/services/outbound_list.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/module.h \ + $(srcdir)/util/data/msgparse.h $(srcdir)/iterator/iter_utils.h $(srcdir)/iterator/iter_resptype.h \ + $(srcdir)/iterator/iter_hints.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h \ + $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_donotq.h $(srcdir)/iterator/iter_delegpt.h \ + $(srcdir)/iterator/iter_scrub.h $(srcdir)/iterator/iter_priv.h $(srcdir)/validator/val_neg.h \ + $(srcdir)/services/cache/dns.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/util/netevent.h \ + $(srcdir)/util/net_help.h $(srcdir)/util/regional.h $(srcdir)/util/data/dname.h $(srcdir)/util/data/msgencode.h \ + $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h \ + $(srcdir)/util/config_file.h +iter_delegpt.lo iter_delegpt.o: $(srcdir)/iterator/iter_delegpt.c config.h $(srcdir)/iterator/iter_delegpt.h \ + $(srcdir)/util/log.h \ + $(srcdir)/services/cache/dns.h \ + $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/data/msgreply.h \ + $(srcdir)/util/data/packed_rrset.h \ + $(srcdir)/util/regional.h \ + $(srcdir)/util/data/dname.h $(srcdir)/util/net_help.h +iter_donotq.lo iter_donotq.o: $(srcdir)/iterator/iter_donotq.c config.h $(srcdir)/iterator/iter_donotq.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 +iter_fwd.lo iter_fwd.o: $(srcdir)/iterator/iter_fwd.c config.h \ + $(srcdir)/iterator/iter_fwd.h \ + $(srcdir)/util/rbtree.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/util/log.h $(srcdir)/util/config_file.h \ + $(srcdir)/util/net_help.h $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h +iter_hints.lo iter_hints.o: $(srcdir)/iterator/iter_hints.c config.h \ + $(srcdir)/iterator/iter_hints.h \ + $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/util/log.h \ + $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h $(srcdir)/util/data/dname.h \ + $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h +iter_priv.lo iter_priv.o: $(srcdir)/iterator/iter_priv.c config.h \ + $(srcdir)/iterator/iter_priv.h \ + $(srcdir)/util/rbtree.h \ + $(srcdir)/util/regional.h $(srcdir)/util/log.h $(srcdir)/util/config_file.h $(srcdir)/util/data/dname.h \ + $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/data/msgparse.h \ + $(srcdir)/util/net_help.h \ + $(srcdir)/util/storage/dnstree.h +iter_resptype.lo iter_resptype.o: $(srcdir)/iterator/iter_resptype.c config.h \ + $(srcdir)/iterator/iter_resptype.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/util/log.h \ + $(srcdir)/services/cache/dns.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \ + $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/net_help.h \ + $(srcdir)/util/data/dname.h +iter_scrub.lo iter_scrub.o: $(srcdir)/iterator/iter_scrub.c config.h $(srcdir)/iterator/iter_scrub.h \ + $(srcdir)/iterator/iterator.h \ + $(srcdir)/services/outbound_list.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/module.h \ + $(srcdir)/util/data/msgparse.h \ + $(srcdir)/iterator/iter_priv.h $(srcdir)/util/rbtree.h $(srcdir)/services/cache/rrset.h \ + $(srcdir)/util/storage/slabhash.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h \ + $(srcdir)/util/config_file.h $(srcdir)/util/data/dname.h $(srcdir)/util/alloc.h +iter_utils.lo iter_utils.o: $(srcdir)/iterator/iter_utils.c config.h $(srcdir)/iterator/iter_utils.h \ + $(srcdir)/iterator/iter_resptype.h \ + $(srcdir)/iterator/iterator.h \ + $(srcdir)/services/outbound_list.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/module.h \ + $(srcdir)/util/data/msgparse.h \ + $(srcdir)/iterator/iter_hints.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h \ + $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_donotq.h $(srcdir)/iterator/iter_delegpt.h \ + $(srcdir)/iterator/iter_priv.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h \ + $(srcdir)/services/cache/dns.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \ + $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h $(srcdir)/util/regional.h $(srcdir)/util/data/dname.h \ + $(srcdir)/util/random.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/util/tube.h \ + $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h $(srcdir)/validator/val_anchor.h \ + $(srcdir)/validator/val_kcache.h $(srcdir)/validator/val_kentry.h $(srcdir)/validator/val_utils.h +listen_dnsport.lo listen_dnsport.o: $(srcdir)/services/listen_dnsport.c config.h \ + $(srcdir)/services/listen_dnsport.h $(srcdir)/util/netevent.h \ + $(srcdir)/services/outside_network.h $(srcdir)/util/rbtree.h $(srcdir)/util/log.h $(srcdir)/util/config_file.h \ + $(srcdir)/util/net_help.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)/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/data/msgreply.h \ + $(srcdir)/util/data/msgparse.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)/util/module.h \ + $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/services/modstack.h \ + $(srcdir)/services/outbound_list.h $(srcdir)/services/cache/dns.h $(srcdir)/util/net_help.h \ + $(srcdir)/util/regional.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/timehist.h $(srcdir)/util/fptr_wlist.h \ + $(srcdir)/util/tube.h $(srcdir)/util/alloc.h $(srcdir)/util/config_file.h +modstack.lo modstack.o: $(srcdir)/services/modstack.c config.h $(srcdir)/services/modstack.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)/util/fptr_wlist.h \ + $(srcdir)/util/netevent.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \ + $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/validator/validator.h \ + $(srcdir)/validator/val_utils.h $(PYTHONMOD_HEADER) +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 \ + +outside_network.lo outside_network.o: $(srcdir)/services/outside_network.c config.h \ + $(srcdir)/services/outside_network.h $(srcdir)/util/rbtree.h $(srcdir)/util/netevent.h \ + $(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/lruhash.h \ + $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/rtt.h $(srcdir)/util/data/msgparse.h \ + $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgencode.h \ + $(srcdir)/util/data/dname.h $(srcdir)/util/net_help.h $(srcdir)/util/random.h $(srcdir)/util/fptr_wlist.h \ + $(srcdir)/util/module.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h \ + +alloc.lo alloc.o: $(srcdir)/util/alloc.c config.h $(srcdir)/util/alloc.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \ + $(srcdir)/util/regional.h \ + $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \ + $(srcdir)/util/fptr_wlist.h \ + $(srcdir)/util/netevent.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h \ + $(srcdir)/util/tube.h \ + $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h +config_file.lo config_file.o: $(srcdir)/util/config_file.c config.h \ + $(srcdir)/util/log.h \ + $(srcdir)/util/configyyrename.h $(srcdir)/util/config_file.h util/configparser.h \ + $(srcdir)/util/net_help.h $(srcdir)/util/data/msgparse.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/regional.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/data/dname.h \ + $(srcdir)/util/iana_ports.inc +configlexer.lo configlexer.o: util/configlexer.c config.h $(srcdir)/util/configyyrename.h \ + $(srcdir)/util/config_file.h util/configparser.h +configparser.lo configparser.o: util/configparser.c config.h $(srcdir)/util/configyyrename.h \ + $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h $(srcdir)/util/log.h \ + +fptr_wlist.lo fptr_wlist.o: $(srcdir)/util/fptr_wlist.c config.h $(srcdir)/util/fptr_wlist.h \ + $(srcdir)/util/netevent.h \ + $(srcdir)/util/storage/lruhash.h \ + $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \ + $(srcdir)/util/data/packed_rrset.h \ + $(srcdir)/util/data/msgparse.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)/daemon/worker.h $(srcdir)/util/alloc.h $(srcdir)/daemon/stats.h \ + $(srcdir)/util/timehist.h $(srcdir)/daemon/remote.h \ + $(srcdir)/services/outside_network.h $(srcdir)/services/localzone.h $(srcdir)/services/cache/infra.h \ + $(srcdir)/util/rtt.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.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)/util/storage/dnstree.h \ + $(srcdir)/libunbound/libworker.h $(srcdir)/libunbound/context.h $(srcdir)/libunbound/unbound.h \ + $(srcdir)/util/config_file.h $(PYTHONMOD_HEADER) +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 +mini_event.lo mini_event.o: $(srcdir)/util/mini_event.c config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \ + $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h \ + $(srcdir)/util/storage/lruhash.h \ + $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \ + $(srcdir)/util/data/packed_rrset.h \ + $(srcdir)/util/data/msgparse.h \ + $(srcdir)/util/tube.h \ + $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h +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 \ + +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 \ + $(srcdir)/util/data/msgparse.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 +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 $(srcdir)/util/regional.h \ + +random.lo random.o: $(srcdir)/util/random.c config.h $(srcdir)/util/random.h $(srcdir)/util/log.h \ + +rbtree.lo rbtree.o: $(srcdir)/util/rbtree.c config.h $(srcdir)/util/log.h \ + $(srcdir)/util/fptr_wlist.h \ + $(srcdir)/util/netevent.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \ + $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \ + $(srcdir)/util/data/msgparse.h \ + $(srcdir)/util/tube.h \ + $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h +regional.lo regional.o: $(srcdir)/util/regional.c config.h $(srcdir)/util/log.h \ + $(srcdir)/util/regional.h +rtt.lo rtt.o: $(srcdir)/util/rtt.c config.h $(srcdir)/util/rtt.h $(srcdir)/util/log.h \ + +dnstree.lo dnstree.o: $(srcdir)/util/storage/dnstree.c config.h $(srcdir)/util/storage/dnstree.h \ + $(srcdir)/util/rbtree.h $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \ + $(srcdir)/util/log.h \ + $(srcdir)/util/net_help.h +lookup3.lo lookup3.o: $(srcdir)/util/storage/lookup3.c config.h $(srcdir)/util/storage/lookup3.h +lruhash.lo lruhash.o: $(srcdir)/util/storage/lruhash.c config.h $(srcdir)/util/storage/lruhash.h \ + $(srcdir)/util/locks.h $(srcdir)/util/log.h \ + $(srcdir)/util/fptr_wlist.h \ + $(srcdir)/util/netevent.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \ + $(srcdir)/util/data/packed_rrset.h \ + $(srcdir)/util/data/msgparse.h \ + $(srcdir)/util/tube.h \ + $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h +slabhash.lo slabhash.o: $(srcdir)/util/storage/slabhash.c config.h $(srcdir)/util/storage/slabhash.h \ + $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \ + +timehist.lo timehist.o: $(srcdir)/util/timehist.c config.h $(srcdir)/util/timehist.h $(srcdir)/util/log.h \ + +tube.lo tube.o: $(srcdir)/util/tube.c config.h $(srcdir)/util/tube.h $(srcdir)/util/log.h \ + $(srcdir)/util/net_help.h \ + $(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)/services/mesh.h \ + $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.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 \ + $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/validator/val_anchor.h $(srcdir)/validator/val_utils.h \ + $(srcdir)/validator/val_sigcrypt.h $(srcdir)/util/data/dname.h $(srcdir)/util/module.h \ + $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/util/net_help.h \ + $(srcdir)/util/config_file.h $(srcdir)/util/regional.h $(srcdir)/util/random.h $(srcdir)/services/mesh.h \ + $(srcdir)/util/netevent.h $(srcdir)/services/modstack.h $(srcdir)/services/cache/rrset.h \ + $(srcdir)/util/storage/slabhash.h $(srcdir)/validator/val_kcache.h +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 +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 \ + $(srcdir)/validator/val_utils.h $(srcdir)/validator/val_anchor.h $(srcdir)/util/rbtree.h \ + $(srcdir)/validator/val_kcache.h $(srcdir)/util/storage/slabhash.h $(srcdir)/validator/val_kentry.h \ + $(srcdir)/validator/val_nsec.h $(srcdir)/validator/val_nsec3.h $(srcdir)/validator/val_neg.h \ + $(srcdir)/validator/val_sigcrypt.h $(srcdir)/validator/autotrust.h $(srcdir)/services/cache/dns.h \ + $(srcdir)/util/data/dname.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h \ + $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h \ + $(srcdir)/services/modstack.h +val_kcache.lo val_kcache.o: $(srcdir)/validator/val_kcache.c config.h $(srcdir)/validator/val_kcache.h \ + $(srcdir)/util/storage/slabhash.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \ + $(srcdir)/validator/val_kentry.h \ + $(srcdir)/util/config_file.h $(srcdir)/util/data/dname.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \ + $(srcdir)/util/data/packed_rrset.h \ + $(srcdir)/util/data/msgparse.h \ + +val_kentry.lo val_kentry.o: $(srcdir)/validator/val_kentry.c config.h \ + $(srcdir)/validator/val_kentry.h \ + $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/packed_rrset.h \ + $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lookup3.h $(srcdir)/util/regional.h $(srcdir)/util/net_help.h +val_neg.lo val_neg.o: $(srcdir)/validator/val_neg.c config.h \ + $(srcdir)/validator/val_neg.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \ + $(srcdir)/util/rbtree.h \ + $(srcdir)/validator/val_nsec.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \ + $(srcdir)/validator/val_nsec3.h \ + $(srcdir)/validator/val_utils.h $(srcdir)/util/data/dname.h $(srcdir)/util/data/msgreply.h \ + $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h $(srcdir)/services/cache/rrset.h \ + $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/dns.h +val_nsec3.lo val_nsec3.o: $(srcdir)/validator/val_nsec3.c config.h \ + $(srcdir)/validator/val_nsec3.h $(srcdir)/util/rbtree.h $(srcdir)/util/data/packed_rrset.h \ + $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \ + $(srcdir)/validator/validator.h \ + $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h \ + $(srcdir)/validator/val_utils.h \ + $(srcdir)/validator/val_kentry.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \ + $(srcdir)/util/regional.h $(srcdir)/util/net_help.h $(srcdir)/util/data/dname.h $(srcdir)/validator/val_nsec.h +val_nsec.lo val_nsec.o: $(srcdir)/validator/val_nsec.c config.h \ + $(srcdir)/validator/val_nsec.h \ + $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \ + $(srcdir)/validator/val_utils.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/dname.h \ + $(srcdir)/util/net_help.h $(srcdir)/util/module.h $(srcdir)/util/data/msgparse.h \ + $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h +val_sigcrypt.lo val_sigcrypt.o: $(srcdir)/validator/val_sigcrypt.c config.h \ + $(srcdir)/validator/val_sigcrypt.h \ + $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \ + $(srcdir)/validator/validator.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \ + $(srcdir)/util/data/msgparse.h $(srcdir)/validator/val_utils.h $(srcdir)/util/data/dname.h \ + $(srcdir)/util/rbtree.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h \ + +val_utils.lo val_utils.o: $(srcdir)/validator/val_utils.c config.h $(srcdir)/validator/val_utils.h \ + $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \ + $(srcdir)/validator/validator.h \ + $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h \ + $(srcdir)/validator/val_kentry.h \ + $(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/config_file.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 $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \ + $(srcdir)/testcode/unitmain.h $(srcdir)/validator/val_anchor.h $(srcdir)/util/rbtree.h +unitdname.lo unitdname.o: $(srcdir)/testcode/unitdname.c config.h \ + $(srcdir)/util/log.h \ + $(srcdir)/testcode/unitmain.h $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lruhash.h \ + $(srcdir)/util/locks.h +unitlruhash.lo unitlruhash.o: $(srcdir)/testcode/unitlruhash.c config.h $(srcdir)/testcode/unitmain.h \ + $(srcdir)/util/log.h \ + $(srcdir)/util/storage/lruhash.h \ + $(srcdir)/util/locks.h $(srcdir)/util/storage/slabhash.h +unitmain.lo unitmain.o: $(srcdir)/testcode/unitmain.c config.h \ + $(srcdir)/util/log.h \ + $(srcdir)/testcode/unitmain.h $(srcdir)/util/alloc.h $(srcdir)/util/locks.h $(srcdir)/util/net_help.h \ + $(srcdir)/util/config_file.h $(srcdir)/util/rtt.h $(srcdir)/services/cache/infra.h \ + $(srcdir)/util/storage/lruhash.h $(srcdir)/util/random.h +unitmsgparse.lo unitmsgparse.o: $(srcdir)/testcode/unitmsgparse.c config.h \ + $(srcdir)/util/log.h \ + $(srcdir)/testcode/unitmain.h $(srcdir)/util/data/msgparse.h $(srcdir)/util/storage/lruhash.h \ + $(srcdir)/util/locks.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \ + $(srcdir)/util/data/msgencode.h $(srcdir)/util/data/dname.h $(srcdir)/util/alloc.h $(srcdir)/util/regional.h \ + $(srcdir)/util/net_help.h $(srcdir)/testcode/readhex.h +unitneg.lo unitneg.o: $(srcdir)/testcode/unitneg.c config.h $(srcdir)/util/log.h \ + $(srcdir)/util/net_help.h \ + $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \ + $(srcdir)/util/data/dname.h \ + $(srcdir)/testcode/unitmain.h $(srcdir)/validator/val_neg.h $(srcdir)/util/rbtree.h +unitregional.lo unitregional.o: $(srcdir)/testcode/unitregional.c config.h $(srcdir)/testcode/unitmain.h \ + $(srcdir)/util/log.h \ + $(srcdir)/util/regional.h +unitslabhash.lo unitslabhash.o: $(srcdir)/testcode/unitslabhash.c config.h $(srcdir)/testcode/unitmain.h \ + $(srcdir)/util/log.h \ + $(srcdir)/util/storage/slabhash.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h +unitverify.lo unitverify.o: $(srcdir)/testcode/unitverify.c config.h $(srcdir)/util/log.h \ + $(srcdir)/testcode/unitmain.h \ + $(srcdir)/validator/val_sigcrypt.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \ + $(srcdir)/util/locks.h \ + $(srcdir)/validator/val_nsec.h \ + $(srcdir)/validator/val_nsec3.h $(srcdir)/util/rbtree.h $(srcdir)/validator/validator.h $(srcdir)/util/module.h \ + $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h \ + $(srcdir)/validator/val_utils.h \ + $(srcdir)/testcode/ldns-testpkts.h \ + $(srcdir)/util/data/dname.h \ + $(srcdir)/util/regional.h $(srcdir)/util/alloc.h $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h +readhex.lo readhex.o: $(srcdir)/testcode/readhex.c config.h $(srcdir)/testcode/readhex.h \ + $(srcdir)/util/log.h +ldns-testpkts.lo ldns-testpkts.o: $(srcdir)/testcode/ldns-testpkts.c config.h \ + $(srcdir)/testcode/ldns-testpkts.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 +cachedump.lo cachedump.o: $(srcdir)/daemon/cachedump.c config.h \ + $(srcdir)/daemon/cachedump.h \ + $(srcdir)/daemon/remote.h $(srcdir)/daemon/worker.h $(srcdir)/util/netevent.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \ + $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/storage/lruhash.h \ + $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/daemon/stats.h \ + $(srcdir)/util/timehist.h $(srcdir)/util/module.h $(srcdir)/daemon/daemon.h $(srcdir)/services/modstack.h \ + $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/dns.h \ + $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/util/regional.h $(srcdir)/util/net_help.h \ + $(srcdir)/util/data/dname.h $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h \ + $(srcdir)/iterator/iter_delegpt.h $(srcdir)/iterator/iter_utils.h $(srcdir)/iterator/iter_resptype.h \ + $(srcdir)/iterator/iter_fwd.h $(srcdir)/util/rbtree.h $(srcdir)/iterator/iter_hints.h \ + $(srcdir)/util/storage/dnstree.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)/util/netevent.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/storage/lruhash.h \ + $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/daemon/stats.h \ + $(srcdir)/util/timehist.h $(srcdir)/util/module.h $(srcdir)/daemon/remote.h $(srcdir)/daemon/acl_list.h \ + $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/config_file.h \ + $(srcdir)/util/storage/lookup3.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/listen_dnsport.h \ + $(srcdir)/services/cache/rrset.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h \ + $(srcdir)/services/localzone.h $(srcdir)/util/random.h $(srcdir)/util/tube.h +remote.lo remote.o: $(srcdir)/daemon/remote.c config.h \ + $(srcdir)/daemon/remote.h \ + $(srcdir)/daemon/worker.h $(srcdir)/util/netevent.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/alloc.h \ + $(srcdir)/util/data/msgreply.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/packed_rrset.h \ + $(srcdir)/util/data/msgparse.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/util/module.h \ + $(srcdir)/daemon/daemon.h $(srcdir)/services/modstack.h $(srcdir)/daemon/cachedump.h \ + $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h $(srcdir)/services/listen_dnsport.h \ + $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/infra.h \ + $(srcdir)/util/rtt.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/localzone.h \ + $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/util/data/dname.h $(srcdir)/validator/validator.h \ + $(srcdir)/validator/val_utils.h $(srcdir)/validator/val_kcache.h $(srcdir)/validator/val_kentry.h \ + $(srcdir)/validator/val_anchor.h $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h \ + $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h $(srcdir)/util/storage/dnstree.h \ + $(srcdir)/iterator/iter_delegpt.h $(srcdir)/services/outside_network.h +stats.lo stats.o: $(srcdir)/daemon/stats.c config.h \ + $(srcdir)/daemon/stats.h \ + $(srcdir)/util/timehist.h $(srcdir)/daemon/worker.h $(srcdir)/util/netevent.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \ + $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/storage/lruhash.h \ + $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/util/module.h \ + $(srcdir)/daemon/daemon.h $(srcdir)/services/modstack.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \ + $(srcdir)/services/outside_network.h $(srcdir)/util/config_file.h $(srcdir)/util/tube.h \ + $(srcdir)/util/net_help.h $(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h +unbound.lo unbound.o: $(srcdir)/daemon/unbound.c config.h $(srcdir)/util/log.h \ + $(srcdir)/daemon/daemon.h \ + $(srcdir)/util/locks.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h $(srcdir)/daemon/remote.h \ + $(srcdir)/util/config_file.h $(srcdir)/util/storage/slabhash.h $(srcdir)/util/storage/lruhash.h \ + $(srcdir)/services/listen_dnsport.h $(srcdir)/util/netevent.h $(srcdir)/services/cache/rrset.h \ + $(srcdir)/util/data/packed_rrset.h \ + $(srcdir)/services/cache/infra.h \ + $(srcdir)/util/rtt.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/module.h $(srcdir)/util/data/msgparse.h \ + $(srcdir)/util/net_help.h \ + $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.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)/util/netevent.h \ + $(srcdir)/util/locks.h $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/storage/lruhash.h \ + $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/daemon/stats.h \ + $(srcdir)/util/timehist.h $(srcdir)/util/module.h $(srcdir)/daemon/daemon.h $(srcdir)/services/modstack.h \ + $(srcdir)/daemon/remote.h \ + $(srcdir)/daemon/acl_list.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h \ + $(srcdir)/util/config_file.h $(srcdir)/util/regional.h $(srcdir)/util/storage/slabhash.h \ + $(srcdir)/services/listen_dnsport.h $(srcdir)/services/outside_network.h \ + $(srcdir)/services/outbound_list.h $(srcdir)/services/cache/rrset.h $(srcdir)/services/cache/infra.h \ + $(srcdir)/util/rtt.h $(srcdir)/services/cache/dns.h $(srcdir)/services/mesh.h $(srcdir)/services/localzone.h \ + $(srcdir)/util/data/msgencode.h $(srcdir)/util/data/dname.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h \ + $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h $(srcdir)/validator/autotrust.h \ + $(srcdir)/validator/val_anchor.h +testbound.lo testbound.o: $(srcdir)/testcode/testbound.c config.h $(srcdir)/testcode/ldns-testpkts.h \ + $(srcdir)/testcode/replay.h \ + $(srcdir)/util/netevent.h $(srcdir)/util/rbtree.h $(srcdir)/testcode/fake_event.h $(srcdir)/daemon/remote.h \ + $(srcdir)/util/config_file.h $(srcdir)/daemon/unbound.c $(srcdir)/util/log.h $(srcdir)/daemon/daemon.h \ + $(srcdir)/util/locks.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h $(srcdir)/util/storage/slabhash.h \ + $(srcdir)/util/storage/lruhash.h $(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/rrset.h \ + $(srcdir)/util/data/packed_rrset.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h \ + $(srcdir)/util/data/msgreply.h $(srcdir)/util/module.h $(srcdir)/util/data/msgparse.h $(srcdir)/util/net_help.h \ + $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h +ldns-testpkts.lo ldns-testpkts.o: $(srcdir)/testcode/ldns-testpkts.c config.h \ + $(srcdir)/testcode/ldns-testpkts.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)/util/netevent.h \ + $(srcdir)/util/locks.h $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/storage/lruhash.h \ + $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/daemon/stats.h \ + $(srcdir)/util/timehist.h $(srcdir)/util/module.h $(srcdir)/daemon/daemon.h $(srcdir)/services/modstack.h \ + $(srcdir)/daemon/remote.h \ + $(srcdir)/daemon/acl_list.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h \ + $(srcdir)/util/config_file.h $(srcdir)/util/regional.h $(srcdir)/util/storage/slabhash.h \ + $(srcdir)/services/listen_dnsport.h $(srcdir)/services/outside_network.h \ + $(srcdir)/services/outbound_list.h $(srcdir)/services/cache/rrset.h $(srcdir)/services/cache/infra.h \ + $(srcdir)/util/rtt.h $(srcdir)/services/cache/dns.h $(srcdir)/services/mesh.h $(srcdir)/services/localzone.h \ + $(srcdir)/util/data/msgencode.h $(srcdir)/util/data/dname.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h \ + $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h $(srcdir)/validator/autotrust.h \ + $(srcdir)/validator/val_anchor.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 +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)/util/netevent.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/storage/lruhash.h \ + $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/daemon/stats.h \ + $(srcdir)/util/timehist.h $(srcdir)/util/module.h $(srcdir)/daemon/remote.h $(srcdir)/daemon/acl_list.h \ + $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/config_file.h \ + $(srcdir)/util/storage/lookup3.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/listen_dnsport.h \ + $(srcdir)/services/cache/rrset.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h \ + $(srcdir)/services/localzone.h $(srcdir)/util/random.h $(srcdir)/util/tube.h +stats.lo stats.o: $(srcdir)/daemon/stats.c config.h \ + $(srcdir)/daemon/stats.h \ + $(srcdir)/util/timehist.h $(srcdir)/daemon/worker.h $(srcdir)/util/netevent.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \ + $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/storage/lruhash.h \ + $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/util/module.h \ + $(srcdir)/daemon/daemon.h $(srcdir)/services/modstack.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \ + $(srcdir)/services/outside_network.h $(srcdir)/util/config_file.h $(srcdir)/util/tube.h \ + $(srcdir)/util/net_help.h $(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h +replay.lo replay.o: $(srcdir)/testcode/replay.c config.h $(srcdir)/util/log.h \ + $(srcdir)/util/net_help.h \ + $(srcdir)/util/config_file.h $(srcdir)/testcode/replay.h $(srcdir)/util/netevent.h \ + $(srcdir)/testcode/ldns-testpkts.h \ + $(srcdir)/util/rbtree.h \ + $(srcdir)/testcode/fake_event.h +fake_event.lo fake_event.o: $(srcdir)/testcode/fake_event.c config.h $(srcdir)/testcode/fake_event.h \ + $(srcdir)/util/netevent.h \ + $(srcdir)/util/net_help.h \ + $(srcdir)/util/log.h $(srcdir)/util/data/msgparse.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \ + $(srcdir)/util/data/msgreply.h \ + $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/data/dname.h \ + $(srcdir)/util/config_file.h $(srcdir)/services/listen_dnsport.h $(srcdir)/services/outside_network.h \ + $(srcdir)/util/rbtree.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/testcode/replay.h \ + $(srcdir)/testcode/ldns-testpkts.h \ + $(srcdir)/util/fptr_wlist.h \ + $(srcdir)/util/module.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h +lock_verify.lo lock_verify.o: $(srcdir)/testcode/lock_verify.c config.h $(srcdir)/util/log.h \ + $(srcdir)/util/rbtree.h \ + $(srcdir)/util/locks.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/util/storage/lruhash.h \ + $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \ + $(srcdir)/util/data/msgparse.h \ + $(srcdir)/util/tube.h \ + $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h +pktview.lo pktview.o: $(srcdir)/testcode/pktview.c config.h \ + $(srcdir)/util/log.h \ + $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \ + $(srcdir)/util/data/msgparse.h $(srcdir)/testcode/unitmain.h $(srcdir)/testcode/readhex.h +readhex.lo readhex.o: $(srcdir)/testcode/readhex.c config.h $(srcdir)/testcode/readhex.h \ + $(srcdir)/util/log.h +signit.lo signit.o: $(srcdir)/testcode/signit.c config.h \ + $(srcdir)/util/log.h \ + $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h +memstats.lo memstats.o: $(srcdir)/testcode/memstats.c config.h $(srcdir)/util/log.h \ + $(srcdir)/util/rbtree.h \ + $(srcdir)/util/locks.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/util/storage/lruhash.h \ + $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \ + $(srcdir)/util/data/msgparse.h \ + $(srcdir)/util/tube.h \ + $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h +unbound-checkconf.lo unbound-checkconf.o: $(srcdir)/smallapp/unbound-checkconf.c config.h $(srcdir)/util/log.h \ + $(srcdir)/util/config_file.h \ + $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/data/msgreply.h \ + $(srcdir)/util/data/packed_rrset.h \ + $(srcdir)/util/data/msgparse.h \ + $(srcdir)/util/net_help.h \ + $(srcdir)/util/regional.h $(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 $(PYTHONMOD_HEADER) +worker_cb.lo worker_cb.o: $(srcdir)/smallapp/worker_cb.c config.h $(srcdir)/util/log.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/module.h \ + $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/services/modstack.h +context.lo context.o: $(srcdir)/libunbound/context.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 \ + $(srcdir)/util/module.h \ + $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.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/rtt.h +libunbound.lo libunbound.o: $(srcdir)/libunbound/libunbound.c $(srcdir)/libunbound/unbound.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)/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/rtt.h \ + $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.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 $(srcdir)/libunbound/unbound.h $(srcdir)/services/outside_network.h \ + $(srcdir)/util/netevent.h $(srcdir)/services/mesh.h $(srcdir)/util/data/msgparse.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/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)/util/tube.h $(srcdir)/iterator/iter_fwd.h \ + $(srcdir)/iterator/iter_hints.h $(srcdir)/util/storage/dnstree.h +unbound-host.lo unbound-host.o: $(srcdir)/smallapp/unbound-host.c config.h $(srcdir)/libunbound/unbound.h \ + +asynclook.lo asynclook.o: $(srcdir)/testcode/asynclook.c config.h $(srcdir)/libunbound/unbound.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 \ + +streamtcp.lo streamtcp.o: $(srcdir)/testcode/streamtcp.c config.h \ + $(srcdir)/util/locks.h $(srcdir)/util/log.h \ + $(srcdir)/util/net_help.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/data/msgparse.h \ + $(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \ + $(srcdir)/util/data/dname.h \ + +perf.lo perf.o: $(srcdir)/testcode/perf.c config.h \ + $(srcdir)/util/log.h $(srcdir)/util/locks.h \ + $(srcdir)/util/net_help.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/data/msgreply.h \ + $(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h +delayer.lo delayer.o: $(srcdir)/testcode/delayer.c config.h $(srcdir)/util/net_help.h $(srcdir)/util/log.h \ + $(srcdir)/util/config_file.h +harvest.lo harvest.o: $(srcdir)/testcode/harvest.c config.h \ + $(srcdir)/libunbound/unbound.h +unbound-control.lo unbound-control.o: $(srcdir)/smallapp/unbound-control.c config.h \ + $(srcdir)/util/log.h \ + $(srcdir)/util/config_file.h \ + $(srcdir)/util/locks.h $(srcdir)/util/net_help.h +unbound-anchor.lo unbound-anchor.o: $(srcdir)/smallapp/unbound-anchor.c config.h $(srcdir)/libunbound/unbound.h \ + +petal.lo petal.o: $(srcdir)/testcode/petal.c config.h \ + +pythonmod_utils.lo pythonmod_utils.o: $(srcdir)/pythonmod/pythonmod_utils.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)/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 \ + +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)/util/netevent.h $(srcdir)/util/data/msgreply.h \ + $(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/packed_rrset.h \ + $(srcdir)/util/data/msgparse.h \ + $(srcdir)/daemon/stats.h \ + $(srcdir)/util/timehist.h $(srcdir)/util/module.h $(srcdir)/daemon/remote.h \ + $(srcdir)/util/config_file.h $(srcdir)/util/winsock_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 +unbound-service-remove.lo unbound-service-remove.o: $(srcdir)/winrc/unbound-service-remove.c config.h \ + $(srcdir)/winrc/w_inst.h +anchor-update.lo anchor-update.o: $(srcdir)/winrc/anchor-update.c config.h \ + $(srcdir)/libunbound/unbound.h +ctime_r.lo ctime_r.o: $(srcdir)/compat/ctime_r.c config.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \ + +fake-rfc2553.lo fake-rfc2553.o: $(srcdir)/compat/fake-rfc2553.c $(srcdir)/compat/fake-rfc2553.h config.h +gmtime_r.lo gmtime_r.o: $(srcdir)/compat/gmtime_r.c config.h +inet_aton.lo inet_aton.o: $(srcdir)/compat/inet_aton.c config.h +inet_ntop.lo inet_ntop.o: $(srcdir)/compat/inet_ntop.c config.h +inet_pton.lo inet_pton.o: $(srcdir)/compat/inet_pton.c config.h +malloc.lo malloc.o: $(srcdir)/compat/malloc.c config.h +memcmp.lo memcmp.o: $(srcdir)/compat/memcmp.c config.h +memmove.lo memmove.o: $(srcdir)/compat/memmove.c config.h +snprintf.lo snprintf.o: $(srcdir)/compat/snprintf.c config.h +strlcpy.lo strlcpy.o: $(srcdir)/compat/strlcpy.c config.h +strptime.lo strptime.o: $(srcdir)/compat/strptime.c config.h diff --git a/README b/README new file mode 100644 index 00000000000..85f9182288d --- /dev/null +++ b/README @@ -0,0 +1,10 @@ +Unbound README +* ./configure && make && make install +* You can use libevent if you want. libevent is useful when using + many (10000) outgoing ports. By default max 256 ports are opened at + the same time and the builtin alternative is equally capable and a + little faster. +* More detailed README, README.svn, README.tests in doc directory +* manual pages can be found in doc directory, and are installed, unbound(8). +* example configuration file doc/example.conf + diff --git a/ac_pkg_swig.m4 b/ac_pkg_swig.m4 new file mode 100644 index 00000000000..738f69d45ea --- /dev/null +++ b/ac_pkg_swig.m4 @@ -0,0 +1,122 @@ +# =========================================================================== +# http://autoconf-archive.cryp.to/ac_pkg_swig.html +# =========================================================================== +# +# SYNOPSIS +# +# AC_PROG_SWIG([major.minor.micro]) +# +# DESCRIPTION +# +# This macro searches for a SWIG installation on your system. If found you +# should call SWIG via $(SWIG). You can use the optional first argument to +# check if the version of the available SWIG is greater than or equal to +# the value of the argument. It should have the format: N[.N[.N]] (N is a +# number between 0 and 999. Only the first N is mandatory.) +# +# If the version argument is given (e.g. 1.3.17), AC_PROG_SWIG checks that +# the swig package is this version number or higher. +# +# In configure.in, use as: +# +# AC_PROG_SWIG(1.3.17) +# SWIG_ENABLE_CXX +# SWIG_MULTI_MODULE_SUPPORT +# SWIG_PYTHON +# +# LAST MODIFICATION +# +# 2008-04-12 +# +# COPYLEFT +# +# Copyright (c) 2008 Sebastian Huber +# Copyright (c) 2008 Alan W. Irwin +# Copyright (c) 2008 Rafael Laboissiere +# Copyright (c) 2008 Andrew Collier +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Macro Archive. When you make and +# distribute a modified version of the Autoconf Macro, you may extend this +# special exception to the GPL to apply to your modified version as well. + +AC_DEFUN([AC_PROG_SWIG],[ + AC_PATH_PROG([SWIG],[swig]) + if test -z "$SWIG" ; then + AC_MSG_WARN([cannot find 'swig' program. You should look at http://www.swig.org]) + SWIG='echo "Error: SWIG is not installed. You should look at http://www.swig.org" ; false' + elif test -n "$1" ; then + AC_MSG_CHECKING([for SWIG version]) + [swig_version=`$SWIG -version 2>&1 | grep 'SWIG Version' | sed 's/.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/g'`] + AC_MSG_RESULT([$swig_version]) + if test -n "$swig_version" ; then + # Calculate the required version number components + [required=$1] + [required_major=`echo $required | sed 's/[^0-9].*//'`] + if test -z "$required_major" ; then + [required_major=0] + fi + [required=`echo $required | sed 's/[0-9]*[^0-9]//'`] + [required_minor=`echo $required | sed 's/[^0-9].*//'`] + if test -z "$required_minor" ; then + [required_minor=0] + fi + [required=`echo $required | sed 's/[0-9]*[^0-9]//'`] + [required_patch=`echo $required | sed 's/[^0-9].*//'`] + if test -z "$required_patch" ; then + [required_patch=0] + fi + # Calculate the available version number components + [available=$swig_version] + [available_major=`echo $available | sed 's/[^0-9].*//'`] + if test -z "$available_major" ; then + [available_major=0] + fi + [available=`echo $available | sed 's/[0-9]*[^0-9]//'`] + [available_minor=`echo $available | sed 's/[^0-9].*//'`] + if test -z "$available_minor" ; then + [available_minor=0] + fi + [available=`echo $available | sed 's/[0-9]*[^0-9]//'`] + [available_patch=`echo $available | sed 's/[^0-9].*//'`] + if test -z "$available_patch" ; then + [available_patch=0] + fi + if test $available_major -ne $required_major \ + -o $available_minor -ne $required_minor \ + -o $available_patch -lt $required_patch ; then + AC_MSG_WARN([SWIG version >= $1 is required. You have $swig_version. You should look at http://www.swig.org]) + SWIG='echo "Error: SWIG version >= $1 is required. You have '"$swig_version"'. You should look at http://www.swig.org" ; false' + else + AC_MSG_NOTICE([SWIG executable is '$SWIG']) + SWIG_LIB=`$SWIG -swiglib` + AC_MSG_NOTICE([SWIG library directory is '$SWIG_LIB']) + fi + else + AC_MSG_WARN([cannot determine SWIG version]) + SWIG='echo "Error: Cannot determine SWIG version. You should look at http://www.swig.org" ; false' + fi + fi + AC_SUBST([SWIG_LIB]) +]) diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 00000000000..de630d85b48 --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,8444 @@ +# generated automatically by aclocal 1.11.1 -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008, 2009, 2010 Free Software Foundation, +# Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +m4_define([_LT_COPYING], [dnl +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008, 2009, 2010 Free Software Foundation, +# Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is part of GNU Libtool. +# +# GNU Libtool is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, or +# obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +]) + +# serial 57 LT_INIT + + +# LT_PREREQ(VERSION) +# ------------------ +# Complain and exit if this libtool version is less that VERSION. +m4_defun([LT_PREREQ], +[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, + [m4_default([$3], + [m4_fatal([Libtool version $1 or higher is required], + 63)])], + [$2])]) + + +# _LT_CHECK_BUILDDIR +# ------------------ +# Complain if the absolute build directory name contains unusual characters +m4_defun([_LT_CHECK_BUILDDIR], +[case `pwd` in + *\ * | *\ *) + AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; +esac +]) + + +# LT_INIT([OPTIONS]) +# ------------------ +AC_DEFUN([LT_INIT], +[AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT +AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +AC_BEFORE([$0], [LT_LANG])dnl +AC_BEFORE([$0], [LT_OUTPUT])dnl +AC_BEFORE([$0], [LTDL_INIT])dnl +m4_require([_LT_CHECK_BUILDDIR])dnl + +dnl Autoconf doesn't catch unexpanded LT_ macros by default: +m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl +m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl +dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 +dnl unless we require an AC_DEFUNed macro: +AC_REQUIRE([LTOPTIONS_VERSION])dnl +AC_REQUIRE([LTSUGAR_VERSION])dnl +AC_REQUIRE([LTVERSION_VERSION])dnl +AC_REQUIRE([LTOBSOLETE_VERSION])dnl +m4_require([_LT_PROG_LTMAIN])dnl + +_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) + +dnl Parse OPTIONS +_LT_SET_OPTIONS([$0], [$1]) + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ltmain" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +_LT_SETUP + +# Only expand once: +m4_define([LT_INIT]) +])# LT_INIT + +# Old names: +AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) +AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PROG_LIBTOOL], []) +dnl AC_DEFUN([AM_PROG_LIBTOOL], []) + + +# _LT_CC_BASENAME(CC) +# ------------------- +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +m4_defun([_LT_CC_BASENAME], +[for cc_temp in $1""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +]) + + +# _LT_FILEUTILS_DEFAULTS +# ---------------------- +# It is okay to use these file commands and assume they have been set +# sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'. +m4_defun([_LT_FILEUTILS_DEFAULTS], +[: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} +])# _LT_FILEUTILS_DEFAULTS + + +# _LT_SETUP +# --------- +m4_defun([_LT_SETUP], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl + +_LT_DECL([], [host_alias], [0], [The host system])dnl +_LT_DECL([], [host], [0])dnl +_LT_DECL([], [host_os], [0])dnl +dnl +_LT_DECL([], [build_alias], [0], [The build system])dnl +_LT_DECL([], [build], [0])dnl +_LT_DECL([], [build_os], [0])dnl +dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +dnl +AC_REQUIRE([AC_PROG_LN_S])dnl +test -z "$LN_S" && LN_S="ln -s" +_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl +dnl +AC_REQUIRE([LT_CMD_MAX_LEN])dnl +_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl +_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl +dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl +m4_require([_LT_CMD_RELOAD])dnl +m4_require([_LT_CHECK_MAGIC_METHOD])dnl +m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl +m4_require([_LT_CMD_OLD_ARCHIVE])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_WITH_SYSROOT])dnl + +_LT_CONFIG_LIBTOOL_INIT([ +# See if we are running on zsh, and set the options which allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi +]) +if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + +_LT_CHECK_OBJDIR + +m4_require([_LT_TAG_COMPILER])dnl + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld="$lt_cv_prog_gnu_ld" + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + _LT_PATH_MAGIC + fi + ;; +esac + +# Use C for the default configuration in the libtool script +LT_SUPPORTED_TAG([CC]) +_LT_LANG_C_CONFIG +_LT_LANG_DEFAULT_CONFIG +_LT_CONFIG_COMMANDS +])# _LT_SETUP + + +# _LT_PREPARE_SED_QUOTE_VARS +# -------------------------- +# Define a few sed substitution that help us do robust quoting. +m4_defun([_LT_PREPARE_SED_QUOTE_VARS], +[# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([["`\\]]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' +]) + +# _LT_PROG_LTMAIN +# --------------- +# Note that this code is called both from `configure', and `config.status' +# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, +# `config.status' has no value for ac_aux_dir unless we are using Automake, +# so we pass a copy along to make sure it has a sensible value anyway. +m4_defun([_LT_PROG_LTMAIN], +[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl +_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) +ltmain="$ac_aux_dir/ltmain.sh" +])# _LT_PROG_LTMAIN + + + +# So that we can recreate a full libtool script including additional +# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS +# in macros and then make a single call at the end using the `libtool' +# label. + + +# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) +# ---------------------------------------- +# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL_INIT], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_INIT], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_INIT]) + + +# _LT_CONFIG_LIBTOOL([COMMANDS]) +# ------------------------------ +# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) + + +# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) +# ----------------------------------------------------- +m4_defun([_LT_CONFIG_SAVE_COMMANDS], +[_LT_CONFIG_LIBTOOL([$1]) +_LT_CONFIG_LIBTOOL_INIT([$2]) +]) + + +# _LT_FORMAT_COMMENT([COMMENT]) +# ----------------------------- +# Add leading comment marks to the start of each line, and a trailing +# full-stop to the whole comment if one is not present already. +m4_define([_LT_FORMAT_COMMENT], +[m4_ifval([$1], [ +m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], + [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) +)]) + + + + + +# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) +# ------------------------------------------------------------------- +# CONFIGNAME is the name given to the value in the libtool script. +# VARNAME is the (base) name used in the configure script. +# VALUE may be 0, 1 or 2 for a computed quote escaped value based on +# VARNAME. Any other value will be used directly. +m4_define([_LT_DECL], +[lt_if_append_uniq([lt_decl_varnames], [$2], [, ], + [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], + [m4_ifval([$1], [$1], [$2])]) + lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) + m4_ifval([$4], + [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) + lt_dict_add_subkey([lt_decl_dict], [$2], + [tagged?], [m4_ifval([$5], [yes], [no])])]) +]) + + +# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) +# -------------------------------------------------------- +m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) + + +# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_tag_varnames], +[_lt_decl_filter([tagged?], [yes], $@)]) + + +# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) +# --------------------------------------------------------- +m4_define([_lt_decl_filter], +[m4_case([$#], + [0], [m4_fatal([$0: too few arguments: $#])], + [1], [m4_fatal([$0: too few arguments: $#: $1])], + [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], + [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], + [lt_dict_filter([lt_decl_dict], $@)])[]dnl +]) + + +# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) +# -------------------------------------------------- +m4_define([lt_decl_quote_varnames], +[_lt_decl_filter([value], [1], $@)]) + + +# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_dquote_varnames], +[_lt_decl_filter([value], [2], $@)]) + + +# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_varnames_tagged], +[m4_assert([$# <= 2])dnl +_$0(m4_quote(m4_default([$1], [[, ]])), + m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), + m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) +m4_define([_lt_decl_varnames_tagged], +[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) + + +# lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_all_varnames], +[_$0(m4_quote(m4_default([$1], [[, ]])), + m4_if([$2], [], + m4_quote(lt_decl_varnames), + m4_quote(m4_shift($@))))[]dnl +]) +m4_define([_lt_decl_all_varnames], +[lt_join($@, lt_decl_varnames_tagged([$1], + lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl +]) + + +# _LT_CONFIG_STATUS_DECLARE([VARNAME]) +# ------------------------------------ +# Quote a variable value, and forward it to `config.status' so that its +# declaration there will have the same value as in `configure'. VARNAME +# must have a single quote delimited value for this to work. +m4_define([_LT_CONFIG_STATUS_DECLARE], +[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) + + +# _LT_CONFIG_STATUS_DECLARATIONS +# ------------------------------ +# We delimit libtool config variables with single quotes, so when +# we write them to config.status, we have to be sure to quote all +# embedded single quotes properly. In configure, this macro expands +# each variable declared with _LT_DECL (and _LT_TAGDECL) into: +# +# ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' +m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], +[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), + [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAGS +# ---------------- +# Output comment and list of tags supported by the script +m4_defun([_LT_LIBTOOL_TAGS], +[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl +available_tags="_LT_TAGS"dnl +]) + + +# _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) +# ----------------------------------- +# Extract the dictionary values for VARNAME (optionally with TAG) and +# expand to a commented shell variable setting: +# +# # Some comment about what VAR is for. +# visible_name=$lt_internal_name +m4_define([_LT_LIBTOOL_DECLARE], +[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], + [description])))[]dnl +m4_pushdef([_libtool_name], + m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl +m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), + [0], [_libtool_name=[$]$1], + [1], [_libtool_name=$lt_[]$1], + [2], [_libtool_name=$lt_[]$1], + [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl +m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl +]) + + +# _LT_LIBTOOL_CONFIG_VARS +# ----------------------- +# Produce commented declarations of non-tagged libtool config variables +# suitable for insertion in the LIBTOOL CONFIG section of the `libtool' +# script. Tagged libtool config variables (even for the LIBTOOL CONFIG +# section) are produced by _LT_LIBTOOL_TAG_VARS. +m4_defun([_LT_LIBTOOL_CONFIG_VARS], +[m4_foreach([_lt_var], + m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAG_VARS(TAG) +# ------------------------- +m4_define([_LT_LIBTOOL_TAG_VARS], +[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) + + +# _LT_TAGVAR(VARNAME, [TAGNAME]) +# ------------------------------ +m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) + + +# _LT_CONFIG_COMMANDS +# ------------------- +# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of +# variables for single and double quote escaping we saved from calls +# to _LT_DECL, we can put quote escaped variables declarations +# into `config.status', and then the shell code to quote escape them in +# for loops in `config.status'. Finally, any additional code accumulated +# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. +m4_defun([_LT_CONFIG_COMMANDS], +[AC_PROVIDE_IFELSE([LT_OUTPUT], + dnl If the libtool generation code has been placed in $CONFIG_LT, + dnl instead of duplicating it all over again into config.status, + dnl then we will have config.status run $CONFIG_LT later, so it + dnl needs to know what name is stored there: + [AC_CONFIG_COMMANDS([libtool], + [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], + dnl If the libtool generation code is destined for config.status, + dnl expand the accumulated commands and init code now: + [AC_CONFIG_COMMANDS([libtool], + [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) +])#_LT_CONFIG_COMMANDS + + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], +[ + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +_LT_CONFIG_STATUS_DECLARATIONS +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$[]1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_quote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_dquote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +_LT_OUTPUT_LIBTOOL_INIT +]) + +# _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) +# ------------------------------------ +# Generate a child script FILE with all initialization necessary to +# reuse the environment learned by the parent script, and make the +# file executable. If COMMENT is supplied, it is inserted after the +# `#!' sequence but before initialization text begins. After this +# macro, additional text can be appended to FILE to form the body of +# the child script. The macro ends with non-zero status if the +# file could not be fully written (such as if the disk is full). +m4_ifdef([AS_INIT_GENERATED], +[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], +[m4_defun([_LT_GENERATED_FILE_INIT], +[m4_require([AS_PREPARE])]dnl +[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl +[lt_write_fail=0 +cat >$1 <<_ASEOF || lt_write_fail=1 +#! $SHELL +# Generated by $as_me. +$2 +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$1 <<\_ASEOF || lt_write_fail=1 +AS_SHELL_SANITIZE +_AS_PREPARE +exec AS_MESSAGE_FD>&1 +_ASEOF +test $lt_write_fail = 0 && chmod +x $1[]dnl +m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT + +# LT_OUTPUT +# --------- +# This macro allows early generation of the libtool script (before +# AC_OUTPUT is called), incase it is used in configure for compilation +# tests. +AC_DEFUN([LT_OUTPUT], +[: ${CONFIG_LT=./config.lt} +AC_MSG_NOTICE([creating $CONFIG_LT]) +_LT_GENERATED_FILE_INIT(["$CONFIG_LT"], +[# Run this file to recreate a libtool stub with the current configuration.]) + +cat >>"$CONFIG_LT" <<\_LTEOF +lt_cl_silent=false +exec AS_MESSAGE_LOG_FD>>config.log +{ + echo + AS_BOX([Running $as_me.]) +} >&AS_MESSAGE_LOG_FD + +lt_cl_help="\ +\`$as_me' creates a local libtool stub from the current configuration, +for use in further configure time tests before the real libtool is +generated. + +Usage: $[0] [[OPTIONS]] + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + +Report bugs to ." + +lt_cl_version="\ +m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl +m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) +configured by $[0], generated by m4_PACKAGE_STRING. + +Copyright (C) 2010 Free Software Foundation, Inc. +This config.lt script is free software; the Free Software Foundation +gives unlimited permision to copy, distribute and modify it." + +while test $[#] != 0 +do + case $[1] in + --version | --v* | -V ) + echo "$lt_cl_version"; exit 0 ;; + --help | --h* | -h ) + echo "$lt_cl_help"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --quiet | --q* | --silent | --s* | -q ) + lt_cl_silent=: ;; + + -*) AC_MSG_ERROR([unrecognized option: $[1] +Try \`$[0] --help' for more information.]) ;; + + *) AC_MSG_ERROR([unrecognized argument: $[1] +Try \`$[0] --help' for more information.]) ;; + esac + shift +done + +if $lt_cl_silent; then + exec AS_MESSAGE_FD>/dev/null +fi +_LTEOF + +cat >>"$CONFIG_LT" <<_LTEOF +_LT_OUTPUT_LIBTOOL_COMMANDS_INIT +_LTEOF + +cat >>"$CONFIG_LT" <<\_LTEOF +AC_MSG_NOTICE([creating $ofile]) +_LT_OUTPUT_LIBTOOL_COMMANDS +AS_EXIT(0) +_LTEOF +chmod +x "$CONFIG_LT" + +# configure is writing to config.log, but config.lt does its own redirection, +# appending to config.log, which fails on DOS, as config.log is still kept +# open by configure. Here we exec the FD to /dev/null, effectively closing +# config.log, so it can be properly (re)opened and appended to by config.lt. +lt_cl_success=: +test "$silent" = yes && + lt_config_lt_args="$lt_config_lt_args --quiet" +exec AS_MESSAGE_LOG_FD>/dev/null +$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false +exec AS_MESSAGE_LOG_FD>>config.log +$lt_cl_success || AS_EXIT(1) +])# LT_OUTPUT + + +# _LT_CONFIG(TAG) +# --------------- +# If TAG is the built-in tag, create an initial libtool script with a +# default configuration from the untagged config vars. Otherwise add code +# to config.status for appending the configuration named by TAG from the +# matching tagged config vars. +m4_defun([_LT_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_CONFIG_SAVE_COMMANDS([ + m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl + m4_if(_LT_TAG, [C], [ + # See if we are running on zsh, and set the options which allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + + cfgfile="${ofile}T" + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL + +# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +_LT_COPYING +_LT_LIBTOOL_TAGS + +# ### BEGIN LIBTOOL CONFIG +_LT_LIBTOOL_CONFIG_VARS +_LT_LIBTOOL_TAG_VARS +# ### END LIBTOOL CONFIG + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + _LT_PROG_LTMAIN + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + _LT_PROG_REPLACE_SHELLFNS + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +], +[cat <<_LT_EOF >> "$ofile" + +dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded +dnl in a comment (ie after a #). +# ### BEGIN LIBTOOL TAG CONFIG: $1 +_LT_LIBTOOL_TAG_VARS(_LT_TAG) +# ### END LIBTOOL TAG CONFIG: $1 +_LT_EOF +])dnl /m4_if +], +[m4_if([$1], [], [ + PACKAGE='$PACKAGE' + VERSION='$VERSION' + TIMESTAMP='$TIMESTAMP' + RM='$RM' + ofile='$ofile'], []) +])dnl /_LT_CONFIG_SAVE_COMMANDS +])# _LT_CONFIG + + +# LT_SUPPORTED_TAG(TAG) +# --------------------- +# Trace this macro to discover what tags are supported by the libtool +# --tag option, using: +# autoconf --trace 'LT_SUPPORTED_TAG:$1' +AC_DEFUN([LT_SUPPORTED_TAG], []) + + +# C support is built-in for now +m4_define([_LT_LANG_C_enabled], []) +m4_define([_LT_TAGS], []) + + +# LT_LANG(LANG) +# ------------- +# Enable libtool support for the given language if not already enabled. +AC_DEFUN([LT_LANG], +[AC_BEFORE([$0], [LT_OUTPUT])dnl +m4_case([$1], + [C], [_LT_LANG(C)], + [C++], [_LT_LANG(CXX)], + [Java], [_LT_LANG(GCJ)], + [Fortran 77], [_LT_LANG(F77)], + [Fortran], [_LT_LANG(FC)], + [Windows Resource], [_LT_LANG(RC)], + [m4_ifdef([_LT_LANG_]$1[_CONFIG], + [_LT_LANG($1)], + [m4_fatal([$0: unsupported language: "$1"])])])dnl +])# LT_LANG + + +# _LT_LANG(LANGNAME) +# ------------------ +m4_defun([_LT_LANG], +[m4_ifdef([_LT_LANG_]$1[_enabled], [], + [LT_SUPPORTED_TAG([$1])dnl + m4_append([_LT_TAGS], [$1 ])dnl + m4_define([_LT_LANG_]$1[_enabled], [])dnl + _LT_LANG_$1_CONFIG($1)])dnl +])# _LT_LANG + + +# _LT_LANG_DEFAULT_CONFIG +# ----------------------- +m4_defun([_LT_LANG_DEFAULT_CONFIG], +[AC_PROVIDE_IFELSE([AC_PROG_CXX], + [LT_LANG(CXX)], + [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) + +AC_PROVIDE_IFELSE([AC_PROG_F77], + [LT_LANG(F77)], + [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) + +AC_PROVIDE_IFELSE([AC_PROG_FC], + [LT_LANG(FC)], + [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) + +dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal +dnl pulling things in needlessly. +AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([LT_PROG_GCJ], + [LT_LANG(GCJ)], + [m4_ifdef([AC_PROG_GCJ], + [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([A][M_PROG_GCJ], + [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([LT_PROG_GCJ], + [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) + +AC_PROVIDE_IFELSE([LT_PROG_RC], + [LT_LANG(RC)], + [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) +])# _LT_LANG_DEFAULT_CONFIG + +# Obsolete macros: +AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) +AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) +AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) +AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) +AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_CXX], []) +dnl AC_DEFUN([AC_LIBTOOL_F77], []) +dnl AC_DEFUN([AC_LIBTOOL_FC], []) +dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) +dnl AC_DEFUN([AC_LIBTOOL_RC], []) + + +# _LT_TAG_COMPILER +# ---------------- +m4_defun([_LT_TAG_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl +_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl +_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl +_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_TAG_COMPILER + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +m4_defun([_LT_COMPILER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +m4_defun([_LT_LINKER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* +])# _LT_LINKER_BOILERPLATE + +# _LT_REQUIRED_DARWIN_CHECKS +# ------------------------- +m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ + case $host_os in + rhapsody* | darwin*) + AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) + AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) + AC_CHECK_TOOL([LIPO], [lipo], [:]) + AC_CHECK_TOOL([OTOOL], [otool], [:]) + AC_CHECK_TOOL([OTOOL64], [otool64], [:]) + _LT_DECL([], [DSYMUTIL], [1], + [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) + _LT_DECL([], [NMEDIT], [1], + [Tool to change global to local symbols on Mac OS X]) + _LT_DECL([], [LIPO], [1], + [Tool to manipulate fat objects and archives on Mac OS X]) + _LT_DECL([], [OTOOL], [1], + [ldd/readelf like tool for Mach-O binaries on Mac OS X]) + _LT_DECL([], [OTOOL64], [1], + [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) + + AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], + [lt_cv_apple_cc_single_mod=no + if test -z "${LT_MULTI_MODULE}"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi]) + AC_CACHE_CHECK([for -exported_symbols_list linker flag], + [lt_cv_ld_exported_symbols_list], + [lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [lt_cv_ld_exported_symbols_list=yes], + [lt_cv_ld_exported_symbols_list=no]) + LDFLAGS="$save_LDFLAGS" + ]) + AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], + [lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD + echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD + $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD + echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD + $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -f conftest && test ! -s conftest.err && test $_lt_result = 0 && $GREP forced_load conftest 2>&1 >/dev/null; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + ]) + case $host_os in + rhapsody* | darwin1.[[012]]) + _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + 10.[[012]]*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test "$lt_cv_apple_cc_single_mod" = "yes"; then + _lt_dar_single_mod='$single_module' + fi + if test "$lt_cv_ld_exported_symbols_list" = "yes"; then + _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac +]) + + +# _LT_DARWIN_LINKER_FEATURES +# -------------------------- +# Checks for linker and compiler features on darwin +m4_defun([_LT_DARWIN_LINKER_FEATURES], +[ + m4_require([_LT_REQUIRED_DARWIN_CHECKS]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_automatic, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + if test "$lt_cv_ld_force_load" = "yes"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='' + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" + case $cc_basename in + ifort*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test "$_lt_dar_can_shared" = "yes"; then + output_verbose_link_cmd=func_echo_all + _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + m4_if([$1], [CXX], +[ if test "$lt_cv_apple_cc_single_mod" != "yes"; then + _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" + fi +],[]) + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi +]) + +# _LT_SYS_MODULE_PATH_AIX([TAGNAME]) +# ---------------------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +# Store the results from the different compilers for each TAGNAME. +# Allow to override them for all tags through lt_cv_aix_libpath. +m4_defun([_LT_SYS_MODULE_PATH_AIX], +[m4_require([_LT_DECL_SED])dnl +if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], + [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ + lt_aix_libpath_sed='[ + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }]' + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi],[]) + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])="/usr/lib:/lib" + fi + ]) + aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) +fi +])# _LT_SYS_MODULE_PATH_AIX + + +# _LT_SHELL_INIT(ARG) +# ------------------- +m4_define([_LT_SHELL_INIT], +[m4_divert_text([M4SH-INIT], [$1 +])])# _LT_SHELL_INIT + + + +# _LT_PROG_ECHO_BACKSLASH +# ----------------------- +# Find how we can fake an echo command that does not interpret backslash. +# In particular, with Autoconf 2.60 or later we add some code to the start +# of the generated configure script which will find a shell with a builtin +# printf (which we can use as an echo command). +m4_defun([_LT_PROG_ECHO_BACKSLASH], +[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +AC_MSG_CHECKING([how to print strings]) +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$[]1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + +case "$ECHO" in + printf*) AC_MSG_RESULT([printf]) ;; + print*) AC_MSG_RESULT([print -r]) ;; + *) AC_MSG_RESULT([cat]) ;; +esac + +m4_ifdef([_AS_DETECT_SUGGESTED], +[_AS_DETECT_SUGGESTED([ + test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test "X`printf %s $ECHO`" = "X$ECHO" \ + || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) + +_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) +_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) +])# _LT_PROG_ECHO_BACKSLASH + + +# _LT_WITH_SYSROOT +# ---------------- +AC_DEFUN([_LT_WITH_SYSROOT], +[AC_MSG_CHECKING([for sysroot]) +AC_ARG_WITH([sysroot], +[ --with-sysroot[=DIR] Search for dependent libraries within DIR + (or the compiler's sysroot if not specified).], +[], [with_sysroot=no]) + +dnl lt_sysroot will always be passed unquoted. We quote it here +dnl in case the user passed a directory name. +lt_sysroot= +case ${with_sysroot} in #( + yes) + if test "$GCC" = yes; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + AC_MSG_RESULT([${with_sysroot}]) + AC_MSG_ERROR([The sysroot must be an absolute path.]) + ;; +esac + + AC_MSG_RESULT([${lt_sysroot:-no}]) +_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl +[dependent libraries, and in which our libraries should be installed.])]) + +# _LT_ENABLE_LOCK +# --------------- +m4_defun([_LT_ENABLE_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AS_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +sparc*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) LD="${LD-ld} -m elf64_sparc" ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks="$enable_libtool_lock" +])# _LT_ENABLE_LOCK + + +# _LT_PROG_AR +# ----------- +m4_defun([_LT_PROG_AR], +[AC_CHECK_TOOLS(AR, [ar], false) +: ${AR=ar} +: ${AR_FLAGS=cru} +_LT_DECL([], [AR], [1], [The archiver]) +_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) + +AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], + [lt_cv_ar_at_file=no + AC_COMPILE_IFELSE([AC_LANG_PROGRAM], + [echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([lt_ar_try]) + if test "$ac_status" -eq 0; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + AC_TRY_EVAL([lt_ar_try]) + if test "$ac_status" -ne 0; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + ]) + ]) + +if test "x$lt_cv_ar_at_file" = xno; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi +_LT_DECL([], [archiver_list_spec], [1], + [How to feed a file listing to the archiver]) +])# _LT_PROG_AR + + +# _LT_CMD_OLD_ARCHIVE +# ------------------- +m4_defun([_LT_CMD_OLD_ARCHIVE], +[_LT_PROG_AR + +AC_CHECK_TOOL(STRIP, strip, :) +test -z "$STRIP" && STRIP=: +_LT_DECL([], [STRIP], [1], [A symbol stripping program]) + +AC_CHECK_TOOL(RANLIB, ranlib, :) +test -z "$RANLIB" && RANLIB=: +_LT_DECL([], [RANLIB], [1], + [Commands used to install an old-style archive]) + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac +_LT_DECL([], [old_postinstall_cmds], [2]) +_LT_DECL([], [old_postuninstall_cmds], [2]) +_LT_TAGDECL([], [old_archive_cmds], [2], + [Commands used to build an old-style archive]) +_LT_DECL([], [lock_old_archive_extraction], [0], + [Whether to use a lock for old archive extraction]) +])# _LT_CMD_OLD_ARCHIVE + + +# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([_LT_COMPILER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $RM conftest* +]) + +if test x"[$]$2" = xyes; then + m4_if([$5], , :, [$5]) +else + m4_if([$6], , :, [$6]) +fi +])# _LT_COMPILER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) + + +# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------- +# Check whether the given linker option works +AC_DEFUN([_LT_LINKER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $3" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" +]) + +if test x"[$]$2" = xyes; then + m4_if([$4], , :, [$4]) +else + m4_if([$5], , :, [$5]) +fi +])# _LT_LINKER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) + + +# LT_CMD_MAX_LEN +#--------------- +AC_DEFUN([LT_CMD_MAX_LEN], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8 ; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test "X"`func_fallback_echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac +]) +if test -n $lt_cv_sys_max_cmd_len ; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +max_cmd_len=$lt_cv_sys_max_cmd_len +_LT_DECL([], [max_cmd_len], [0], + [What is the maximum length of a command?]) +])# LT_CMD_MAX_LEN + +# Old name: +AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) + + +# _LT_HEADER_DLFCN +# ---------------- +m4_defun([_LT_HEADER_DLFCN], +[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl +])# _LT_HEADER_DLFCN + + +# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# ---------------------------------------------------------------- +m4_defun([_LT_TRY_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test "$cross_compiling" = yes; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +[#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +}] +_LT_EOF + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_TRY_DLOPEN_SELF + + +# LT_SYS_DLOPEN_SELF +# ------------------ +AC_DEFUN([LT_SYS_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen="shl_load"], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen="dlopen"], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +_LT_DECL([dlopen_support], [enable_dlopen], [0], + [Whether dlopen is supported]) +_LT_DECL([dlopen_self], [enable_dlopen_self], [0], + [Whether dlopen of programs is supported]) +_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], + [Whether dlopen of statically linked programs is supported]) +])# LT_SYS_DLOPEN_SELF + +# Old name: +AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) + + +# _LT_COMPILER_C_O([TAGNAME]) +# --------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler. +# This macro does not hard code the compiler like AC_PROG_CC_C_O. +m4_defun([_LT_COMPILER_C_O], +[m4_require([_LT_DECL_SED])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* +]) +_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], + [Does compiler simultaneously support -c and -o options?]) +])# _LT_COMPILER_C_O + + +# _LT_COMPILER_FILE_LOCKS([TAGNAME]) +# ---------------------------------- +# Check to see if we can do hard links to lock some files if needed +m4_defun([_LT_COMPILER_FILE_LOCKS], +[m4_require([_LT_ENABLE_LOCK])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_COMPILER_C_O([$1]) + +hard_links="nottested" +if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test "$hard_links" = no; then + AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) +])# _LT_COMPILER_FILE_LOCKS + + +# _LT_CHECK_OBJDIR +# ---------------- +m4_defun([_LT_CHECK_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +_LT_DECL([], [objdir], [0], + [The name of the directory that contains temporary libtool files])dnl +m4_pattern_allow([LT_OBJDIR])dnl +AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/", + [Define to the sub-directory in which libtool stores uninstalled libraries.]) +])# _LT_CHECK_OBJDIR + + +# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) +# -------------------------------------- +# Check hardcoding attributes. +m4_defun([_LT_LINKER_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || + test -n "$_LT_TAGVAR(runpath_var, $1)" || + test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then + + # We can hardcode non-existent directories. + if test "$_LT_TAGVAR(hardcode_direct, $1)" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no && + test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then + # Linking always hardcodes the temporary library directory. + _LT_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) + +if test "$_LT_TAGVAR(hardcode_action, $1)" = relink || + test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi +_LT_TAGDECL([], [hardcode_action], [0], + [How to hardcode a shared library path into an executable]) +])# _LT_LINKER_HARDCODE_LIBPATH + + +# _LT_CMD_STRIPLIB +# ---------------- +m4_defun([_LT_CMD_STRIPLIB], +[m4_require([_LT_DECL_EGREP]) +striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +_LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) +_LT_DECL([], [striplib], [1]) +])# _LT_CMD_STRIPLIB + + +# _LT_SYS_DYNAMIC_LINKER([TAG]) +# ----------------------------- +# PORTME Fill in your ld.so characteristics +m4_defun([_LT_SYS_DYNAMIC_LINKER], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_OBJDUMP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +AC_MSG_CHECKING([dynamic linker characteristics]) +m4_if([$1], + [], [ +if test "$GCC" = yes; then + case $host_os in + darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; + *) lt_awk_arg="/^libraries:/" ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq="s,=\([[A-Za-z]]:\),\1,g" ;; + *) lt_sed_strip_eq="s,=/,/,g" ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary. + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path/$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" + else + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS=" "; FS="/|\n";} { + lt_foo=""; + lt_count=0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo="/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[[lt_foo]]++; } + if (lt_freq[[lt_foo]] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's,/\([[A-Za-z]]:\),\1,g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix[[4-9]]*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + library_names_spec='${libname}.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec="$LIB" + if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[123]]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +haiku*) + version_type=linux + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=yes + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[[3-9]]*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], + [lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ + LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], + [lt_cv_shlibpath_overrides_runpath=yes])]) + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + ]) + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Add ABI-specific directories to the system library path. + sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" + + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[[89]] | openbsd2.[[89]].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +fi +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" +fi + +_LT_DECL([], [variables_saved_for_relink], [1], + [Variables whose values should be saved in libtool wrapper scripts and + restored at link time]) +_LT_DECL([], [need_lib_prefix], [0], + [Do we need the "lib" prefix for modules?]) +_LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) +_LT_DECL([], [version_type], [0], [Library versioning type]) +_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) +_LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) +_LT_DECL([], [shlibpath_overrides_runpath], [0], + [Is shlibpath searched before the hard-coded library search path?]) +_LT_DECL([], [libname_spec], [1], [Format of library name prefix]) +_LT_DECL([], [library_names_spec], [1], + [[List of archive names. First name is the real one, the rest are links. + The last name is the one that the linker finds with -lNAME]]) +_LT_DECL([], [soname_spec], [1], + [[The coded name of the library, if different from the real name]]) +_LT_DECL([], [install_override_mode], [1], + [Permission mode override for installation of shared libraries]) +_LT_DECL([], [postinstall_cmds], [2], + [Command to use after installation of a shared archive]) +_LT_DECL([], [postuninstall_cmds], [2], + [Command to use after uninstallation of a shared archive]) +_LT_DECL([], [finish_cmds], [2], + [Commands used to finish a libtool library installation in a directory]) +_LT_DECL([], [finish_eval], [1], + [[As "finish_cmds", except a single script fragment to be evaled but + not shown]]) +_LT_DECL([], [hardcode_into_libs], [0], + [Whether we should hardcode library paths into libraries]) +_LT_DECL([], [sys_lib_search_path_spec], [2], + [Compile-time system search path for libraries]) +_LT_DECL([], [sys_lib_dlsearch_path_spec], [2], + [Run-time system search path for libraries]) +])# _LT_SYS_DYNAMIC_LINKER + + +# _LT_PATH_TOOL_PREFIX(TOOL) +# -------------------------- +# find a file program which can recognize shared library +AC_DEFUN([_LT_PATH_TOOL_PREFIX], +[m4_require([_LT_DECL_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="m4_if([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$1; then + lt_cv_path_MAGIC_CMD="$ac_dir/$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac]) +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +_LT_DECL([], [MAGIC_CMD], [0], + [Used to examine libraries when file_magic_cmd begins with "file"])dnl +])# _LT_PATH_TOOL_PREFIX + +# Old name: +AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) + + +# _LT_PATH_MAGIC +# -------------- +# find a file program which can recognize a shared library +m4_defun([_LT_PATH_MAGIC], +[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# _LT_PATH_MAGIC + + +# LT_PATH_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([LT_PATH_LD], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PROG_ECHO_BACKSLASH])dnl + +AC_ARG_WITH([gnu-ld], + [AS_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test "$withval" = no || with_gnu_ld=yes], + [with_gnu_ld=no])dnl + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[[3-9]]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + +_LT_DECL([], [deplibs_check_method], [1], + [Method to check whether dependent libraries are shared objects]) +_LT_DECL([], [file_magic_cmd], [1], + [Command to use when deplibs_check_method = "file_magic"]) +_LT_DECL([], [file_magic_glob], [1], + [How to find potential files when deplibs_check_method = "file_magic"]) +_LT_DECL([], [want_nocaseglob], [1], + [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) +])# _LT_CHECK_MAGIC_METHOD + + +# LT_PATH_NM +# ---------- +# find the pathname to a BSD- or MS-compatible name lister +AC_DEFUN([LT_PATH_NM], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + : ${lt_cv_path_NM=no} +fi]) +if test "$lt_cv_path_NM" != "no"; then + NM="$lt_cv_path_NM" +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) + case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols" + ;; + *) + DUMPBIN=: + ;; + esac + fi + AC_SUBST([DUMPBIN]) + if test "$DUMPBIN" != ":"; then + NM="$DUMPBIN" + fi +fi +test -z "$NM" && NM=nm +AC_SUBST([NM]) +_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl + +AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], + [lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) + cat conftest.out >&AS_MESSAGE_LOG_FD + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest*]) +])# LT_PATH_NM + +# Old names: +AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) +AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_PROG_NM], []) +dnl AC_DEFUN([AC_PROG_NM], []) + +# _LT_CHECK_SHAREDLIB_FROM_LINKLIB +# -------------------------------- +# how to determine the name of the shared library +# associated with a specific link library. +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +m4_require([_LT_DECL_DLLTOOL]) +AC_CACHE_CHECK([how to associate runtime and link libraries], +lt_cv_sharedlib_from_linklib_cmd, +[lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh + # decide which to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd="$ECHO" + ;; +esac +]) +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + +_LT_DECL([], [sharedlib_from_linklib_cmd], [1], + [Command to associate shared and link libraries]) +])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB + + +# _LT_PATH_MANIFEST_TOOL +# ---------------------- +# locate the manifest tool +m4_defun([_LT_PATH_MANIFEST_TOOL], +[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], + [lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&AS_MESSAGE_LOG_FD + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest*]) +if test "x$lt_cv_path_mainfest_tool" != xyes; then + MANIFEST_TOOL=: +fi +_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl +])# _LT_PATH_MANIFEST_TOOL + + +# LT_LIB_M +# -------- +# check for math library +AC_DEFUN([LT_LIB_M], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM="-lm") + ;; +esac +AC_SUBST([LIBM]) +])# LT_LIB_M + +# Old name: +AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_CHECK_LIBM], []) + + +# _LT_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------- +m4_defun([_LT_COMPILER_NO_RTTI], +[m4_require([_LT_TAG_COMPILER])dnl + +_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test "$GCC" = yes; then + case $cc_basename in + nvcc*) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; + *) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; + esac + + _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], + [Compiler flag to turn off builtin functions]) +])# _LT_COMPILER_NO_RTTI + + +# _LT_CMD_GLOBAL_SYMBOLS +# ---------------------- +m4_defun([_LT_CMD_GLOBAL_SYMBOLS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([LT_PATH_NM])dnl +AC_REQUIRE([LT_PATH_LD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_TAG_COMPILER])dnl + +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) + if test "$host_cpu" = ia64; then + symcode='[[ABCDEGRST]]' + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function + # and D for any global variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK ['"\ +" {last_section=section; section=\$ 3};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ +" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ +" s[1]~/^[@?]/{print s[1], s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx]" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + nlist=conftest.nm + if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +/* DATA imports from DLLs on WIN32 con't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT@&t@_DLSYM_CONST +#elif defined(__osf__) +/* This system does not cope well with relocations in const data. */ +# define LT@&t@_DLSYM_CONST +#else +# define LT@&t@_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT@&t@_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[[]] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + +_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], + [Take the output of nm and produce a listing of raw symbols and C names]) +_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], + [Transform the output of nm in a proper C declaration]) +_LT_DECL([global_symbol_to_c_name_address], + [lt_cv_sys_global_symbol_to_c_name_address], [1], + [Transform the output of nm in a C name address pair]) +_LT_DECL([global_symbol_to_c_name_address_lib_prefix], + [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], + [Transform the output of nm in a C name address pair when lib prefix is needed]) +_LT_DECL([], [nm_file_list_spec], [1], + [Specify filename containing input files for $NM]) +]) # _LT_CMD_GLOBAL_SYMBOLS + + +# _LT_COMPILER_PIC([TAGNAME]) +# --------------------------- +m4_defun([_LT_COMPILER_PIC], +[m4_require([_LT_TAG_COMPILER])dnl +_LT_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_TAGVAR(lt_prog_compiler_static, $1)= + +m4_if([$1], [CXX], [ + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix[[4-9]]*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + if test "$host_cpu" != ia64; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + ecpc* ) + # old Intel C++ for x86_64 which still supported -KPIC. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) + # IBM XL 8.0, 9.0 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test "$GCC" = yes; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Xcompiler -fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + + hpux9* | hpux10* | hpux11*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + # old Intel for x86_64 which still supported -KPIC. + ecc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' + _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' + ;; + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ F* | *Sun*Fortran*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='' + ;; + *Sun\ C*) + # Sun C 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + esac + ;; + esac + ;; + + newsos6) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + rdos*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" + ;; +esac + +AC_CACHE_CHECK([for $compiler option to produce PIC], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) +_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], + [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], + [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], + [Additional compiler flags for building library objects]) + +_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], + [How to pass a linker flag through the compiler]) +# +# Check to make sure the static flag actually works. +# +wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" +_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) +_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], + [Compiler flag to prevent dynamic linking]) +])# _LT_COMPILER_PIC + + +# _LT_LINKER_SHLIBS([TAGNAME]) +# ---------------------------- +# See if the linker supports building shared libraries. +m4_defun([_LT_LINKER_SHLIBS], +[AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +m4_if([$1], [CXX], [ + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + case $host_os in + aix[[4-9]]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global defined + # symbols, whereas GNU nm marks them as "W". + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" + ;; + cygwin* | mingw* | cegcc*) + case $cc_basename in + cl*) ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + ;; + esac + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +], [ + runpath_var= + _LT_TAGVAR(allow_undefined_flag, $1)= + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(archive_cmds, $1)= + _LT_TAGVAR(archive_expsym_cmds, $1)= + _LT_TAGVAR(compiler_needs_object, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(hardcode_automatic, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= + _LT_TAGVAR(hardcode_libdir_separator, $1)= + _LT_TAGVAR(hardcode_minus_L, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_TAGVAR(inherit_rpath, $1)=no + _LT_TAGVAR(link_all_deplibs, $1)=unknown + _LT_TAGVAR(module_cmds, $1)= + _LT_TAGVAR(module_expsym_cmds, $1)= + _LT_TAGVAR(old_archive_from_new_cmds, $1)= + _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_TAGVAR(thread_safe_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. +dnl Note also adjust exclude_expsyms for C++ above. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + _LT_TAGVAR(ld_shlibs, $1)=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test "$with_gnu_ld" = yes; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; + *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test "$lt_use_gnu_ld_interface" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[[3-9]]*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test "$host_os" = linux-dietlibc; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test "$tmp_diet" = no + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + _LT_TAGVAR(whole_archive_flag_spec, $1)= + tmp_sharedflag='--shared' ;; + xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' + _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then + runpath_var= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix[[4-9]]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global + # defined symbols, whereas GNU nm marks them as "W". + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' + + if test "$GCC" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + bsdi[[45]]*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + esac + ;; + + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + freebsd1*) + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + m4_if($1, [], [ + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + _LT_LINKER_OPTION([if $CC understands -b], + _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], + [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) + ;; + esac + fi + if test "$with_gnu_ld" = no; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], + [lt_cv_irix_exported_symbol], + [save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" + AC_LINK_IFELSE( + [AC_LANG_SOURCE( + [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], + [C++], [[int foo (void) { return 0; }]], + [Fortran 77], [[ + subroutine foo + end]], + [Fortran], [[ + subroutine foo + end]])])], + [lt_cv_irix_exported_symbol=yes], + [lt_cv_irix_exported_symbol=no]) + LDFLAGS="$save_LDFLAGS"]) + if test "$lt_cv_irix_exported_symbol" = yes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' + fi + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *nto* | *qnx*) + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + else + case $host_os in + openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + ;; + esac + fi + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' + if test "$GCC" = yes; then + wlarc='${wl}' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='${wl}' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. GCC discards it without `$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test "$GCC" = yes; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + fi + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + if test x$host_vendor = xsni; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym' + ;; + esac + fi + fi +]) +AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) +test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld + +_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl +_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl +_LT_DECL([], [extract_expsyms_cmds], [2], + [The commands to extract the exported symbol list from a shared archive]) + +# +# Do we need to explicitly link libc? +# +case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $_LT_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_CACHE_CHECK([whether -lc should be explicitly linked in], + [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), + [$RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) + _LT_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) + then + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no + else + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + ]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) + ;; + esac + fi + ;; +esac + +_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], + [Whether or not to add -lc for building shared libraries]) +_LT_TAGDECL([allow_libtool_libs_with_static_runtimes], + [enable_shared_with_static_runtimes], [0], + [Whether or not to disallow shared libs when runtime libs are static]) +_LT_TAGDECL([], [export_dynamic_flag_spec], [1], + [Compiler flag to allow reflexive dlopens]) +_LT_TAGDECL([], [whole_archive_flag_spec], [1], + [Compiler flag to generate shared objects directly from archives]) +_LT_TAGDECL([], [compiler_needs_object], [1], + [Whether the compiler copes with passing no objects directly]) +_LT_TAGDECL([], [old_archive_from_new_cmds], [2], + [Create an old-style archive from a shared archive]) +_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], + [Create a temporary old-style archive to link instead of a shared archive]) +_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) +_LT_TAGDECL([], [archive_expsym_cmds], [2]) +_LT_TAGDECL([], [module_cmds], [2], + [Commands used to build a loadable module if different from building + a shared archive.]) +_LT_TAGDECL([], [module_expsym_cmds], [2]) +_LT_TAGDECL([], [with_gnu_ld], [1], + [Whether we are building with GNU ld or not]) +_LT_TAGDECL([], [allow_undefined_flag], [1], + [Flag that allows shared libraries with undefined symbols to be built]) +_LT_TAGDECL([], [no_undefined_flag], [1], + [Flag that enforces no undefined symbols]) +_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], + [Flag to hardcode $libdir into a binary during linking. + This must work even if $libdir does not exist]) +_LT_TAGDECL([], [hardcode_libdir_flag_spec_ld], [1], + [[If ld is used when linking, flag to hardcode $libdir into a binary + during linking. This must work even if $libdir does not exist]]) +_LT_TAGDECL([], [hardcode_libdir_separator], [1], + [Whether we need a single "-rpath" flag with a separated argument]) +_LT_TAGDECL([], [hardcode_direct], [0], + [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes + DIR into the resulting binary]) +_LT_TAGDECL([], [hardcode_direct_absolute], [0], + [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes + DIR into the resulting binary and the resulting library dependency is + "absolute", i.e impossible to change by setting ${shlibpath_var} if the + library is relocated]) +_LT_TAGDECL([], [hardcode_minus_L], [0], + [Set to "yes" if using the -LDIR flag during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_shlibpath_var], [0], + [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_automatic], [0], + [Set to "yes" if building a shared library automatically hardcodes DIR + into the library and all subsequent libraries and executables linked + against it]) +_LT_TAGDECL([], [inherit_rpath], [0], + [Set to yes if linker adds runtime paths of dependent libraries + to runtime path list]) +_LT_TAGDECL([], [link_all_deplibs], [0], + [Whether libtool must link a program against all its dependency libraries]) +_LT_TAGDECL([], [always_export_symbols], [0], + [Set to "yes" if exported symbols are required]) +_LT_TAGDECL([], [export_symbols_cmds], [2], + [The commands to list exported symbols]) +_LT_TAGDECL([], [exclude_expsyms], [1], + [Symbols that should not be listed in the preloaded symbols]) +_LT_TAGDECL([], [include_expsyms], [1], + [Symbols that must always be exported]) +_LT_TAGDECL([], [prelink_cmds], [2], + [Commands necessary for linking programs (against libraries) with templates]) +_LT_TAGDECL([], [postlink_cmds], [2], + [Commands necessary for finishing linking programs]) +_LT_TAGDECL([], [file_list_spec], [1], + [Specify filename containing input files]) +dnl FIXME: Not yet implemented +dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], +dnl [Compiler flag to generate thread safe objects]) +])# _LT_LINKER_SHLIBS + + +# _LT_LANG_C_CONFIG([TAG]) +# ------------------------ +# Ensure that the configuration variables for a C compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to `libtool'. +m4_defun([_LT_LANG_C_CONFIG], +[m4_require([_LT_DECL_EGREP])dnl +lt_save_CC="$CC" +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + +_LT_TAG_COMPILER +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + LT_SYS_DLOPEN_SELF + _LT_CMD_STRIPLIB + + # Report which library types will actually be built + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[[4-9]]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_CONFIG($1) +fi +AC_LANG_POP +CC="$lt_save_CC" +])# _LT_LANG_C_CONFIG + + +# _LT_LANG_CXX_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a C++ compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to `libtool'. +m4_defun([_LT_LANG_CXX_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_PROG_CXXCPP +else + _lt_caught_CXX_error=yes +fi + +AC_LANG_PUSH(C++) +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(compiler_needs_object, $1)=no +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the CXX compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_caught_CXX_error" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests + lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_CFLAGS=$CFLAGS + lt_save_LD=$LD + lt_save_GCC=$GCC + GCC=$GXX + lt_save_with_gnu_ld=$with_gnu_ld + lt_save_path_LD=$lt_cv_path_LD + if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx + else + $as_unset lt_cv_prog_gnu_ld + fi + if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX + else + $as_unset lt_cv_path_LD + fi + test -z "${LDCXX+set}" || LD=$LDCXX + CC=${CXX-"c++"} + CFLAGS=$CXXFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + # We don't want -fno-exception when compiling C++ code, so set the + # no_builtin_flag separately + if test "$GXX" = yes; then + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + else + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + fi + + if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + LT_PATH_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test "$with_gnu_ld" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | + $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + GXX=no + with_gnu_ld=no + wlarc= + fi + + # PORTME: fill in a description of your system's C++ link characteristics + AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) + _LT_TAGVAR(ld_shlibs, $1)=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aix[[4-9]]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' + + if test "$GXX" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to + # export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty + # executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared + # libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32* | cegcc*) + case $GXX,$cc_basename in + ,cl* | no,cl*) + # Native MSVC + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # g++ + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + freebsd[[12]]*) + # C++ shared libraries reported to be fairly broken before + # switch to ELF + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + freebsd-elf*) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + gnu*) + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + hpux9*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' + fi + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc* | ecpc* ) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + case `$CC -V` in + *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) + _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' + _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + ;; + *) # Version 6 and above use weak symbols + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + ;; + xl* | mpixl* | bgxl*) + # IBM XL 8.0 on PPC, with GNU ld + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + + lynxos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + m88k*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + + *nto* | *qnx*) + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + openbsd2*) + # C++ shared libraries are fairly broken + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + fi + output_verbose_link_cmd=func_echo_all + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + case $host in + osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; + *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; + esac + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + case $host in + osf3*) + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + ;; + *) + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ + $RM $lib.exp' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + case $host in + osf3*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + psos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' + if $CC --version | $GREP -v '^2\.7' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + fi + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ + '"$_LT_TAGVAR(old_archive_cmds, $1)" + _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ + '"$_LT_TAGVAR(reload_cmds, $1)" + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + vxworks*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) + test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + + _LT_TAGVAR(GCC, $1)="$GXX" + _LT_TAGVAR(LD, $1)="$LD" + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS + LDCXX=$LD + LD=$lt_save_LD + GCC=$lt_save_GCC + with_gnu_ld=$lt_save_with_gnu_ld + lt_cv_path_LDCXX=$lt_cv_path_LD + lt_cv_path_LD=$lt_save_path_LD + lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld + lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +fi # test "$_lt_caught_CXX_error" != yes + +AC_LANG_POP +])# _LT_LANG_CXX_CONFIG + + +# _LT_FUNC_STRIPNAME_CNF +# ---------------------- +# func_stripname_cnf prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# +# This function is identical to the (non-XSI) version of func_stripname, +# except this one can be used by m4 code that may be executed by configure, +# rather than the libtool script. +m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl +AC_REQUIRE([_LT_DECL_SED]) +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) +func_stripname_cnf () +{ + case ${2} in + .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; + esac +} # func_stripname_cnf +])# _LT_FUNC_STRIPNAME_CNF + +# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) +# --------------------------------- +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +m4_defun([_LT_SYS_HIDDEN_LIBDEPS], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl +# Dependencies to place before and after the object being linked: +_LT_TAGVAR(predep_objects, $1)= +_LT_TAGVAR(postdep_objects, $1)= +_LT_TAGVAR(predeps, $1)= +_LT_TAGVAR(postdeps, $1)= +_LT_TAGVAR(compiler_lib_search_path, $1)= + +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF +int a; +void foo (void) { a = 0; } +_LT_EOF +], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +_LT_EOF +], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer*4 a + a=0 + return + end +_LT_EOF +], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer a + a=0 + return + end +_LT_EOF +], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF +public class foo { + private int a; + public void bar (void) { + a = 0; + } +}; +_LT_EOF +]) + +_lt_libdeps_save_CFLAGS=$CFLAGS +case "$CC $CFLAGS " in #( +*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; +*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; +esac + +dnl Parse the compiler output and extract the necessary +dnl objects, libraries and library flags. +if AC_TRY_EVAL(ac_compile); then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + for p in `eval "$output_verbose_link_cmd"`; do + case ${prev}${p} in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test $p = "-L" || + test $p = "-R"; then + prev=$p + continue + fi + + # Expand the sysroot to ease extracting the directories later. + if test -z "$prev"; then + case $p in + -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; + -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; + -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; + esac + fi + case $p in + =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; + esac + if test "$pre_test_object_deps_done" = no; then + case ${prev} in + -L | -R) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then + _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" + else + _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$_LT_TAGVAR(postdeps, $1)"; then + _LT_TAGVAR(postdeps, $1)="${prev}${p}" + else + _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}" + fi + fi + prev= + ;; + + *.lto.$objext) ;; # Ignore GCC LTO objects + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test "$pre_test_object_deps_done" = no; then + if test -z "$_LT_TAGVAR(predep_objects, $1)"; then + _LT_TAGVAR(predep_objects, $1)="$p" + else + _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" + fi + else + if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then + _LT_TAGVAR(postdep_objects, $1)="$p" + else + _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling $1 test program" +fi + +$RM -f confest.$objext +CFLAGS=$_lt_libdeps_save_CFLAGS + +# PORTME: override above test on systems where it is broken +m4_if([$1], [CXX], +[case $host_os in +interix[[3-9]]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + _LT_TAGVAR(predep_objects,$1)= + _LT_TAGVAR(postdep_objects,$1)= + _LT_TAGVAR(postdeps,$1)= + ;; + +linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + if test "$solaris_use_stlport4" != yes; then + _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' + fi + ;; + esac + ;; + +solaris*) + case $cc_basename in + CC* | sunCC*) + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + # Adding this requires a known-good setup of shared libraries for + # Sun compiler versions before 5.6, else PIC objects from an old + # archive will be linked into the output, leading to subtle bugs. + if test "$solaris_use_stlport4" != yes; then + _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' + fi + ;; + esac + ;; +esac +]) + +case " $_LT_TAGVAR(postdeps, $1) " in +*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; +esac + _LT_TAGVAR(compiler_lib_search_dirs, $1)= +if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then + _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` +fi +_LT_TAGDECL([], [compiler_lib_search_dirs], [1], + [The directories searched by this compiler when creating a shared library]) +_LT_TAGDECL([], [predep_objects], [1], + [Dependencies to place before and after the objects being linked to + create a shared library]) +_LT_TAGDECL([], [postdep_objects], [1]) +_LT_TAGDECL([], [predeps], [1]) +_LT_TAGDECL([], [postdeps], [1]) +_LT_TAGDECL([], [compiler_lib_search_path], [1], + [The library search path used internally by the compiler when linking + a shared library]) +])# _LT_SYS_HIDDEN_LIBDEPS + + +# _LT_LANG_F77_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a Fortran 77 compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_F77_CONFIG], +[AC_LANG_PUSH(Fortran 77) +if test -z "$F77" || test "X$F77" = "Xno"; then + _lt_disable_F77=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the F77 compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_disable_F77" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC="$CC" + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${F77-"f77"} + CFLAGS=$FFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + GCC=$G77 + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)="$G77" + _LT_TAGVAR(LD, $1)="$LD" + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC="$lt_save_CC" + CFLAGS="$lt_save_CFLAGS" +fi # test "$_lt_disable_F77" != yes + +AC_LANG_POP +])# _LT_LANG_F77_CONFIG + + +# _LT_LANG_FC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for a Fortran compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_FC_CONFIG], +[AC_LANG_PUSH(Fortran) + +if test -z "$FC" || test "X$FC" = "Xno"; then + _lt_disable_FC=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for fc test sources. +ac_ext=${ac_fc_srcext-f} + +# Object file extension for compiled fc test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the FC compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_disable_FC" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC="$CC" + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${FC-"f95"} + CFLAGS=$FCFLAGS + compiler=$CC + GCC=$ac_cv_fc_compiler_gnu + + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu" + _LT_TAGVAR(LD, $1)="$LD" + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test "$_lt_disable_FC" != yes + +AC_LANG_POP +])# _LT_LANG_FC_CONFIG + + +# _LT_LANG_GCJ_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Java Compiler compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_GCJ_CONFIG], +[AC_REQUIRE([LT_PROG_GCJ])dnl +AC_LANG_SAVE + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GCJ-"gcj"} +CFLAGS=$GCJFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)="$LD" +_LT_CC_BASENAME([$compiler]) + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GCJ_CONFIG + + +# _LT_LANG_RC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for the Windows resource compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_RC_CONFIG], +[AC_REQUIRE([LT_PROG_RC])dnl +AC_LANG_SAVE + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' + +# Code to be used in simple link tests +lt_simple_link_test_code="$lt_simple_compile_test_code" + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC= +CC=${RC-"windres"} +CFLAGS= +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) +_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + +if test -n "$compiler"; then + : + _LT_CONFIG($1) +fi + +GCC=$lt_save_GCC +AC_LANG_RESTORE +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_RC_CONFIG + + +# LT_PROG_GCJ +# ----------- +AC_DEFUN([LT_PROG_GCJ], +[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], + [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], + [AC_CHECK_TOOL(GCJ, gcj,) + test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS)])])[]dnl +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_GCJ], []) + + +# LT_PROG_RC +# ---------- +AC_DEFUN([LT_PROG_RC], +[AC_CHECK_TOOL(RC, windres,) +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_RC], []) + + +# _LT_DECL_EGREP +# -------------- +# If we don't have a new enough Autoconf to choose the best grep +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_EGREP], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_REQUIRE([AC_PROG_FGREP])dnl +test -z "$GREP" && GREP=grep +_LT_DECL([], [GREP], [1], [A grep program that handles long lines]) +_LT_DECL([], [EGREP], [1], [An ERE matcher]) +_LT_DECL([], [FGREP], [1], [A literal string matcher]) +dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too +AC_SUBST([GREP]) +]) + + +# _LT_DECL_OBJDUMP +# -------------- +# If we don't have a new enough Autoconf to choose the best objdump +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_OBJDUMP], +[AC_CHECK_TOOL(OBJDUMP, objdump, false) +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) +AC_SUBST([OBJDUMP]) +]) + +# _LT_DECL_DLLTOOL +# ---------------- +# Ensure DLLTOOL variable is set. +m4_defun([_LT_DECL_DLLTOOL], +[AC_CHECK_TOOL(DLLTOOL, dlltool, false) +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program]) +AC_SUBST([DLLTOOL]) +]) + +# _LT_DECL_SED +# ------------ +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +m4_defun([_LT_DECL_SED], +[AC_PROG_SED +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" +_LT_DECL([], [SED], [1], [A sed program that does not truncate output]) +_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], + [Sed that helps us avoid accidentally triggering echo(1) options like -n]) +])# _LT_DECL_SED + +m4_ifndef([AC_PROG_SED], [ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # + +m4_defun([AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +IFS=$as_save_IFS +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f $lt_ac_sed && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test $lt_ac_count -gt 10 && break + lt_ac_count=`expr $lt_ac_count + 1` + if test $lt_ac_count -gt $lt_ac_max; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_SUBST([SED]) +AC_MSG_RESULT([$SED]) +])#AC_PROG_SED +])#m4_ifndef + +# Old name: +AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_SED], []) + + +# _LT_CHECK_SHELL_FEATURES +# ------------------------ +# Find out whether the shell is Bourne or XSI compatible, +# or has some other useful features. +m4_defun([_LT_CHECK_SHELL_FEATURES], +[AC_MSG_CHECKING([whether the shell understands some XSI constructs]) +# Try some XSI features +xsi_shell=no +( _lt_dummy="a/b/c" + test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ + = c,a/b,b/c, \ + && eval 'test $(( 1 + 1 )) -eq 2 \ + && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ + && xsi_shell=yes +AC_MSG_RESULT([$xsi_shell]) +_LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell']) + +AC_MSG_CHECKING([whether the shell understands "+="]) +lt_shell_append=no +( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \ + >/dev/null 2>&1 \ + && lt_shell_append=yes +AC_MSG_RESULT([$lt_shell_append]) +_LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append']) + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi +_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac +_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl +_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl +])# _LT_CHECK_SHELL_FEATURES + + +# _LT_PROG_FUNCTION_REPLACE (FUNCNAME, REPLACEMENT-BODY) +# ------------------------------------------------------ +# In `$cfgfile', look for function FUNCNAME delimited by `^FUNCNAME ()$' and +# '^} FUNCNAME ', and replace its body with REPLACEMENT-BODY. +m4_defun([_LT_PROG_FUNCTION_REPLACE], +[dnl { +sed -e '/^$1 ()$/,/^} # $1 /c\ +$1 ()\ +{\ +m4_bpatsubsts([$2], [$], [\\], [^\([ ]\)], [\\\1]) +} # Extended-shell $1 implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: +]) + + +# _LT_PROG_REPLACE_SHELLFNS +# ------------------------- +# Replace existing portable implementations of several shell functions with +# equivalent extended shell implementations where those features are available.. +m4_defun([_LT_PROG_REPLACE_SHELLFNS], +[if test x"$xsi_shell" = xyes; then + _LT_PROG_FUNCTION_REPLACE([func_dirname], [dnl + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac]) + + _LT_PROG_FUNCTION_REPLACE([func_basename], [dnl + func_basename_result="${1##*/}"]) + + _LT_PROG_FUNCTION_REPLACE([func_dirname_and_basename], [dnl + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac + func_basename_result="${1##*/}"]) + + _LT_PROG_FUNCTION_REPLACE([func_stripname], [dnl + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary parameter first. + func_stripname_result=${3} + func_stripname_result=${func_stripname_result#"${1}"} + func_stripname_result=${func_stripname_result%"${2}"}]) + + _LT_PROG_FUNCTION_REPLACE([func_split_long_opt], [dnl + func_split_long_opt_name=${1%%=*} + func_split_long_opt_arg=${1#*=}]) + + _LT_PROG_FUNCTION_REPLACE([func_split_short_opt], [dnl + func_split_short_opt_arg=${1#??} + func_split_short_opt_name=${1%"$func_split_short_opt_arg"}]) + + _LT_PROG_FUNCTION_REPLACE([func_lo2o], [dnl + case ${1} in + *.lo) func_lo2o_result=${1%.lo}.${objext} ;; + *) func_lo2o_result=${1} ;; + esac]) + + _LT_PROG_FUNCTION_REPLACE([func_xform], [ func_xform_result=${1%.*}.lo]) + + _LT_PROG_FUNCTION_REPLACE([func_arith], [ func_arith_result=$(( $[*] ))]) + + _LT_PROG_FUNCTION_REPLACE([func_len], [ func_len_result=${#1}]) +fi + +if test x"$lt_shell_append" = xyes; then + _LT_PROG_FUNCTION_REPLACE([func_append], [ eval "${1}+=\\${2}"]) + + _LT_PROG_FUNCTION_REPLACE([func_append_quoted], [dnl + func_quote_for_eval "${2}" +dnl m4 expansion turns \\\\ into \\, and then the shell eval turns that into \ + eval "${1}+=\\\\ \\$func_quote_for_eval_result"]) + + # Save a `func_append' function call where possible by direct use of '+=' + sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +else + # Save a `func_append' function call even when '+=' is not available + sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +fi + +if test x"$_lt_function_replace_fail" = x":"; then + AC_MSG_WARN([Unable to substitute extended shell functions in $ofile]) +fi +]) + +# _LT_PATH_CONVERSION_FUNCTIONS +# ----------------------------- +# Determine which file name conversion functions should be used by +# func_to_host_file (and, implicitly, by func_to_host_path). These are needed +# for certain cross-compile configurations and native mingw. +m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_MSG_CHECKING([how to convert $build file names to $host format]) +AC_CACHE_VAL(lt_cv_to_host_file_cmd, +[case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac +]) +to_host_file_cmd=$lt_cv_to_host_file_cmd +AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) +_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], + [0], [convert $build file names to $host format])dnl + +AC_MSG_CHECKING([how to convert $build file names to toolchain format]) +AC_CACHE_VAL(lt_cv_to_tool_file_cmd, +[#assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac +]) +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) +_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], + [0], [convert $build files to toolchain format])dnl +])# _LT_PATH_CONVERSION_FUNCTIONS + +# Helper functions for option handling. -*- Autoconf -*- +# +# Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 7 ltoptions.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) + + +# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) +# ------------------------------------------ +m4_define([_LT_MANGLE_OPTION], +[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) + + +# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) +# --------------------------------------- +# Set option OPTION-NAME for macro MACRO-NAME, and if there is a +# matching handler defined, dispatch to it. Other OPTION-NAMEs are +# saved as a flag. +m4_define([_LT_SET_OPTION], +[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl +m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), + _LT_MANGLE_DEFUN([$1], [$2]), + [m4_warning([Unknown $1 option `$2'])])[]dnl +]) + + +# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) +# ------------------------------------------------------------ +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +m4_define([_LT_IF_OPTION], +[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) + + +# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) +# ------------------------------------------------------- +# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME +# are set. +m4_define([_LT_UNLESS_OPTIONS], +[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), + [m4_define([$0_found])])])[]dnl +m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 +])[]dnl +]) + + +# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) +# ---------------------------------------- +# OPTION-LIST is a space-separated list of Libtool options associated +# with MACRO-NAME. If any OPTION has a matching handler declared with +# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about +# the unknown option and exit. +m4_defun([_LT_SET_OPTIONS], +[# Set options +m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [_LT_SET_OPTION([$1], _LT_Option)]) + +m4_if([$1],[LT_INIT],[ + dnl + dnl Simply set some default values (i.e off) if boolean options were not + dnl specified: + _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no + ]) + _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no + ]) + dnl + dnl If no reference was made to various pairs of opposing options, then + dnl we run the default mode handler for the pair. For example, if neither + dnl `shared' nor `disable-shared' was passed, we enable building of shared + dnl archives by default: + _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) + _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], + [_LT_ENABLE_FAST_INSTALL]) + ]) +])# _LT_SET_OPTIONS + + + +# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) +# ----------------------------------------- +m4_define([_LT_MANGLE_DEFUN], +[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) + + +# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) +# ----------------------------------------------- +m4_define([LT_OPTION_DEFINE], +[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl +])# LT_OPTION_DEFINE + + +# dlopen +# ------ +LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes +]) + +AU_DEFUN([AC_LIBTOOL_DLOPEN], +[_LT_SET_OPTION([LT_INIT], [dlopen]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the `dlopen' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) + + +# win32-dll +# --------- +# Declare package support for building win32 dll's. +LT_OPTION_DEFINE([LT_INIT], [win32-dll], +[enable_win32_dll=yes + +case $host in +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; +esac + +test -z "$AS" && AS=as +_LT_DECL([], [AS], [1], [Assembler program])dnl + +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl + +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl +])# win32-dll + +AU_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +_LT_SET_OPTION([LT_INIT], [win32-dll]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the `win32-dll' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) + + +# _LT_ENABLE_SHARED([DEFAULT]) +# ---------------------------- +# implement the --enable-shared flag, and supports the `shared' and +# `disable-shared' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +m4_define([_LT_ENABLE_SHARED], +[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([shared], + [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) + + _LT_DECL([build_libtool_libs], [enable_shared], [0], + [Whether or not to build shared libraries]) +])# _LT_ENABLE_SHARED + +LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) +]) + +AC_DEFUN([AC_DISABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], [disable-shared]) +]) + +AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_SHARED], []) +dnl AC_DEFUN([AM_DISABLE_SHARED], []) + + + +# _LT_ENABLE_STATIC([DEFAULT]) +# ---------------------------- +# implement the --enable-static flag, and support the `static' and +# `disable-static' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +m4_define([_LT_ENABLE_STATIC], +[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([static], + [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_static=]_LT_ENABLE_STATIC_DEFAULT) + + _LT_DECL([build_old_libs], [enable_static], [0], + [Whether or not to build static libraries]) +])# _LT_ENABLE_STATIC + +LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) +]) + +AC_DEFUN([AC_DISABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], [disable-static]) +]) + +AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_STATIC], []) +dnl AC_DEFUN([AM_DISABLE_STATIC], []) + + + +# _LT_ENABLE_FAST_INSTALL([DEFAULT]) +# ---------------------------------- +# implement the --enable-fast-install flag, and support the `fast-install' +# and `disable-fast-install' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +m4_define([_LT_ENABLE_FAST_INSTALL], +[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([fast-install], + [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) + +_LT_DECL([fast_install], [enable_fast_install], [0], + [Whether or not to optimize for fast installation])dnl +])# _LT_ENABLE_FAST_INSTALL + +LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) + +# Old names: +AU_DEFUN([AC_ENABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the `fast-install' option into LT_INIT's first parameter.]) +]) + +AU_DEFUN([AC_DISABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], [disable-fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the `disable-fast-install' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) +dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) + + +# _LT_WITH_PIC([MODE]) +# -------------------- +# implement the --with-pic flag, and support the `pic-only' and `no-pic' +# LT_INIT options. +# MODE is either `yes' or `no'. If omitted, it defaults to `both'. +m4_define([_LT_WITH_PIC], +[AC_ARG_WITH([pic], + [AS_HELP_STRING([--with-pic], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [pic_mode="$withval"], + [pic_mode=default]) + +test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) + +_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl +])# _LT_WITH_PIC + +LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) + +# Old name: +AU_DEFUN([AC_LIBTOOL_PICMODE], +[_LT_SET_OPTION([LT_INIT], [pic-only]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the `pic-only' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) + + +m4_define([_LTDL_MODE], []) +LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], + [m4_define([_LTDL_MODE], [nonrecursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [recursive], + [m4_define([_LTDL_MODE], [recursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [subproject], + [m4_define([_LTDL_MODE], [subproject])]) + +m4_define([_LTDL_TYPE], []) +LT_OPTION_DEFINE([LTDL_INIT], [installable], + [m4_define([_LTDL_TYPE], [installable])]) +LT_OPTION_DEFINE([LTDL_INIT], [convenience], + [m4_define([_LTDL_TYPE], [convenience])]) + +# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- +# +# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 6 ltsugar.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) + + +# lt_join(SEP, ARG1, [ARG2...]) +# ----------------------------- +# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their +# associated separator. +# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier +# versions in m4sugar had bugs. +m4_define([lt_join], +[m4_if([$#], [1], [], + [$#], [2], [[$2]], + [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) +m4_define([_lt_join], +[m4_if([$#$2], [2], [], + [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) + + +# lt_car(LIST) +# lt_cdr(LIST) +# ------------ +# Manipulate m4 lists. +# These macros are necessary as long as will still need to support +# Autoconf-2.59 which quotes differently. +m4_define([lt_car], [[$1]]) +m4_define([lt_cdr], +[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], + [$#], 1, [], + [m4_dquote(m4_shift($@))])]) +m4_define([lt_unquote], $1) + + +# lt_append(MACRO-NAME, STRING, [SEPARATOR]) +# ------------------------------------------ +# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. +# Note that neither SEPARATOR nor STRING are expanded; they are appended +# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). +# No SEPARATOR is output if MACRO-NAME was previously undefined (different +# than defined and empty). +# +# This macro is needed until we can rely on Autoconf 2.62, since earlier +# versions of m4sugar mistakenly expanded SEPARATOR but not STRING. +m4_define([lt_append], +[m4_define([$1], + m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) + + + +# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) +# ---------------------------------------------------------- +# Produce a SEP delimited list of all paired combinations of elements of +# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list +# has the form PREFIXmINFIXSUFFIXn. +# Needed until we can rely on m4_combine added in Autoconf 2.62. +m4_define([lt_combine], +[m4_if(m4_eval([$# > 3]), [1], + [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl +[[m4_foreach([_Lt_prefix], [$2], + [m4_foreach([_Lt_suffix], + ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, + [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) + + +# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) +# ----------------------------------------------------------------------- +# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited +# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. +m4_define([lt_if_append_uniq], +[m4_ifdef([$1], + [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], + [lt_append([$1], [$2], [$3])$4], + [$5])], + [lt_append([$1], [$2], [$3])$4])]) + + +# lt_dict_add(DICT, KEY, VALUE) +# ----------------------------- +m4_define([lt_dict_add], +[m4_define([$1($2)], [$3])]) + + +# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) +# -------------------------------------------- +m4_define([lt_dict_add_subkey], +[m4_define([$1($2:$3)], [$4])]) + + +# lt_dict_fetch(DICT, KEY, [SUBKEY]) +# ---------------------------------- +m4_define([lt_dict_fetch], +[m4_ifval([$3], + m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), + m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) + + +# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) +# ----------------------------------------------------------------- +m4_define([lt_if_dict_fetch], +[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], + [$5], + [$6])]) + + +# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) +# -------------------------------------------------------------- +m4_define([lt_dict_filter], +[m4_if([$5], [], [], + [lt_join(m4_quote(m4_default([$4], [[, ]])), + lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), + [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl +]) + +# ltversion.m4 -- version numbers -*- Autoconf -*- +# +# Copyright (C) 2004 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# @configure_input@ + +# serial 3293 ltversion.m4 +# This file is part of GNU Libtool + +m4_define([LT_PACKAGE_VERSION], [2.4]) +m4_define([LT_PACKAGE_REVISION], [1.3293]) + +AC_DEFUN([LTVERSION_VERSION], +[macro_version='2.4' +macro_revision='1.3293' +_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) +_LT_DECL(, macro_revision, 0) +]) + +# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- +# +# Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004. +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 5 lt~obsolete.m4 + +# These exist entirely to fool aclocal when bootstrapping libtool. +# +# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) +# which have later been changed to m4_define as they aren't part of the +# exported API, or moved to Autoconf or Automake where they belong. +# +# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN +# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us +# using a macro with the same name in our local m4/libtool.m4 it'll +# pull the old libtool.m4 in (it doesn't see our shiny new m4_define +# and doesn't know about Autoconf macros at all.) +# +# So we provide this file, which has a silly filename so it's always +# included after everything else. This provides aclocal with the +# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything +# because those macros already exist, or will be overwritten later. +# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. +# +# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. +# Yes, that means every name once taken will need to remain here until +# we give up compatibility with versions before 1.7, at which point +# we need to keep only those names which we still refer to. + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) + +m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) +m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) +m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) +m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) +m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) +m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) +m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) +m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) +m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) +m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) +m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) +m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) +m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) +m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) +m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) +m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) +m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) +m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) +m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) +m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) +m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) +m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) +m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) +m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) +m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) +m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) +m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) +m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) +m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) +m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) +m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) +m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) +m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) +m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) +m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) +m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) +m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) +m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) +m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) +m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) +m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) +m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) +m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) +m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) +m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) +m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) +m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) +m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) +m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) +m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) + diff --git a/acx_nlnetlabs.m4 b/acx_nlnetlabs.m4 new file mode 100644 index 00000000000..e90c81ea02a --- /dev/null +++ b/acx_nlnetlabs.m4 @@ -0,0 +1,1370 @@ +# acx_nlnetlabs.m4 - common macros for configure checks +# Copyright 2009, Wouter Wijngaards, NLnet Labs. +# BSD licensed. +# +# Version 21 +# 2012-02-09 Fix AHX_MEMCMP_BROKEN with undef in compat/memcmp.h. +# 2012-01-20 Fix COMPILER_FLAGS_UNBOUND for gcc 4.6.2 assigned-not-used-warns. +# 2011-12-05 Fix getaddrinfowithincludes on windows with fedora16 mingw32-gcc. +# Fix ACX_MALLOC for redefined malloc error. +# Fix GETADDRINFO_WITH_INCLUDES to add -lws2_32 +# 2011-11-10 Fix FLTO test to not drop a.out in current directory. +# 2011-11-01 Fix FLTO test for llvm on Lion. +# 2011-08-01 Fix nonblock test (broken at v13). +# 2011-08-01 Fix autoconf 2.68 warnings +# 2011-06-23 Add ACX_CHECK_FLTO to check -flto. +# 2010-08-16 Fix FLAG_OMITTED for AS_TR_CPP changes in autoconf-2.66. +# 2010-07-02 Add check for ss_family (for minix). +# 2010-04-26 Fix to use CPPFLAGS for CHECK_COMPILER_FLAGS. +# 2010-03-01 Fix RPATH using CONFIG_COMMANDS to run at the very end. +# 2010-02-18 WITH_SSL outputs the LIBSSL_LDFLAGS, LIBS, CPPFLAGS seperate, -ldl +# 2010-02-01 added ACX_CHECK_MEMCMP_SIGNED, AHX_MEMCMP_BROKEN +# 2010-01-20 added AHX_COONFIG_STRLCAT +# 2009-07-14 U_CHAR detection improved for windows crosscompile. +# added ACX_FUNC_MALLOC +# fixup some #if to #ifdef +# NONBLOCKING test for mingw crosscompile. +# 2009-07-13 added ACX_WITH_SSL_OPTIONAL +# 2009-07-03 fixup LDFLAGS for empty ssl dir. +# +# Automates some of the checking constructs. Aims at portability for POSIX. +# Documentation for functions is below. +# +# the following macro's are provided in this file: +# (see below for details on each macro). +# +# ACX_ESCAPE_BACKSLASH - escape backslashes in var for C-preproc. +# ACX_RSRC_VERSION - create windows resource version number. +# ACX_CHECK_COMPILER_FLAG - see if cc supports a flag. +# ACX_CHECK_ERROR_FLAGS - see which flag is -werror (used below). +# ACX_CHECK_COMPILER_FLAG_NEEDED - see if flags make the code compile cleanly. +# ACX_DEPFLAG - find cc dependency flags. +# ACX_DETERMINE_EXT_FLAGS_UNBOUND - find out which flags enable BSD and POSIX. +# ACX_CHECK_FORMAT_ATTRIBUTE - find cc printf format syntax. +# ACX_CHECK_UNUSED_ATTRIBUTE - find cc variable unused syntax. +# ACX_CHECK_FLTO - see if cc supports -flto and use it if so. +# ACX_LIBTOOL_C_ONLY - create libtool for C only, improved. +# ACX_TYPE_U_CHAR - u_char type. +# ACX_TYPE_RLIM_T - rlim_t type. +# ACX_TYPE_SOCKLEN_T - socklen_t type. +# ACX_TYPE_IN_ADDR_T - in_addr_t type. +# ACX_TYPE_IN_PORT_T - in_port_t type. +# ACX_ARG_RPATH - add --disable-rpath option. +# ACX_WITH_SSL - add --with-ssl option, link -lcrypto. +# ACX_WITH_SSL_OPTIONAL - add --with-ssl option, link -lcrypto, +# where --without-ssl is also accepted +# ACX_LIB_SSL - setup to link -lssl. +# ACX_SYS_LARGEFILE - improved sys_largefile, fseeko, >2G files. +# ACX_CHECK_GETADDRINFO_WITH_INCLUDES - find getaddrinfo, portably. +# ACX_FUNC_DEPRECATED - see if func is deprecated. +# ACX_CHECK_NONBLOCKING_BROKEN - see if nonblocking sockets really work. +# ACX_MKDIR_ONE_ARG - determine mkdir(2) number of arguments. +# ACX_FUNC_IOCTLSOCKET - find ioctlsocket, portably. +# ACX_FUNC_MALLOC - check malloc, define replacement . +# AHX_CONFIG_FORMAT_ATTRIBUTE - config.h text for format. +# AHX_CONFIG_UNUSED_ATTRIBUTE - config.h text for unused. +# AHX_CONFIG_FSEEKO - define fseeko, ftello fallback. +# AHX_CONFIG_RAND_MAX - define RAND_MAX if needed. +# AHX_CONFIG_MAXHOSTNAMELEN - define MAXHOSTNAMELEN if needed. +# AHX_CONFIG_IPV6_MIN_MTU - define IPV6_MIN_MTU if needed. +# AHX_CONFIG_SNPRINTF - snprintf compat prototype +# AHX_CONFIG_INET_PTON - inet_pton compat prototype +# AHX_CONFIG_INET_NTOP - inet_ntop compat prototype +# AHX_CONFIG_INET_ATON - inet_aton compat prototype +# AHX_CONFIG_MEMMOVE - memmove compat prototype +# AHX_CONFIG_STRLCAT - strlcat compat prototype +# AHX_CONFIG_STRLCPY - strlcpy compat prototype +# AHX_CONFIG_GMTIME_R - gmtime_r compat prototype +# AHX_CONFIG_W32_SLEEP - w32 compat for sleep +# AHX_CONFIG_W32_USLEEP - w32 compat for usleep +# AHX_CONFIG_W32_RANDOM - w32 compat for random +# AHX_CONFIG_W32_SRANDOM - w32 compat for srandom +# AHX_CONFIG_W32_FD_SET_T - w32 detection of FD_SET_T. +# ACX_CFLAGS_STRIP - strip one flag from CFLAGS +# ACX_STRIP_EXT_FLAGS - strip extension flags from CFLAGS +# AHX_CONFIG_FLAG_OMITTED - define omitted flag +# AHX_CONFIG_FLAG_EXT - define omitted extension flag +# AHX_CONFIG_EXT_FLAGS - define the stripped extension flags +# ACX_CHECK_MEMCMP_SIGNED - check if memcmp uses signed characters. +# AHX_MEMCMP_BROKEN - replace memcmp func for CHECK_MEMCMP_SIGNED. +# ACX_CHECK_SS_FAMILY - check for sockaddr_storage.ss_family +# + +dnl Escape backslashes as \\, for C:\ paths, for the C preprocessor defines. +dnl for example, ACX_ESCAPE_BACKSLASH($from_var, to_var) +dnl $1: the text to change. +dnl $2: the result. +AC_DEFUN([ACX_ESCAPE_BACKSLASH], [$2="`echo $1 | sed -e 's/\\\\/\\\\\\\\/g'`" +]) + +dnl Calculate comma separated windows-resource numbers from package version. +dnl Picks the first three(,0) or four numbers out of the name. +dnl $1: variable for the result +AC_DEFUN([ACX_RSRC_VERSION], +[$1=[`echo $PACKAGE_VERSION | sed -e 's/^[^0-9]*\([0-9]\)[^0-9]*\([0-9]\)[^0-9]*\([0-9]\)[^0-9]*\([0-9]\).*$/\1,\2,\3,\4/' -e 's/^[^0-9]*\([0-9]\)[^0-9]*\([0-9]\)[^0-9]*\([0-9]\)[^0-9]*$/\1,\2,\3,0/' `] +]) + +dnl Routine to help check for compiler flags. +dnl Checks if the compiler will accept the flag. +dnl $1: the flag without a - in front, so g to check -g. +dnl $2: executed if yes +dnl $3: executed if no +AC_DEFUN([ACX_CHECK_COMPILER_FLAG], +[ +AC_REQUIRE([AC_PROG_CC]) +AC_MSG_CHECKING(whether $CC supports -$1) +cache=`echo $1 | sed 'y%.=/+-%___p_%'` +AC_CACHE_VAL(cv_prog_cc_flag_$cache, +[ +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -$1 -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c +]) +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +AC_MSG_RESULT(yes) +: +$2 +else +AC_MSG_RESULT(no) +: +$3 +fi +]) + +dnl setup flags for ACX_CHECK_COMPILER_FLAG_NEEDED +dnl ERRFLAG: result, compiler flag to turn warnings into errors +AC_DEFUN([ACX_CHECK_ERROR_FLAGS], +[ +ACX_CHECK_COMPILER_FLAG(Werror, [ERRFLAG="-Werror"], [ERRFLAG="-errwarn"]) +ACX_CHECK_COMPILER_FLAG(Wall, [ERRFLAG="$ERRFLAG -Wall"], + [ERRFLAG="$ERRFLAG -errfmt"]) +]) + +dnl Routine to help check for needed compiler flags. +dnl $1: flags for CC +dnl $2: the includes and code +dnl $3: if the given code only compiles with the flag, execute argument 3 +dnl $4: if the given code compiles without the flag, execute argument 4 +dnl $5: with and without flag the compile fails, execute argument 5. +AC_DEFUN([ACX_CHECK_COMPILER_FLAG_NEEDED], +[ +AC_REQUIRE([AC_PROG_CC]) +AC_REQUIRE([ACX_CHECK_ERROR_FLAGS]) +AC_MSG_CHECKING(whether we need $1 as a flag for $CC) +cache=AS_TR_SH($1) +dnl cache=`echo $1 | sed 'y%.=/+- %___p__%'` +AC_CACHE_VAL(cv_prog_cc_flag_needed_$cache, +[ +echo '$2' > conftest.c +echo 'void f(){}' >>conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=no" +else +[ +if test -z "`$CC $CPPFLAGS $CFLAGS $1 $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=yes" +else +eval "cv_prog_cc_flag_needed_$cache=fail" +#echo 'Test with flag fails too!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS $1 $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS $1 $ERRFLAG -c conftest.c 2>&1` +#exit 1 +fi +] +fi +rm -f conftest conftest.c conftest.o +]) +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = yes"; then +AC_MSG_RESULT(yes) +: +$3 +else +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = no"; then +AC_MSG_RESULT(no) +#echo 'Test with flag is no!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS $1 $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS $1 $ERRFLAG -c conftest.c 2>&1` +#exit 1 +: +$4 +else +AC_MSG_RESULT(failed) +: +$5 +fi +fi +]) + +dnl Check for CC dependency flag +dnl DEPFLAG: set to flag that generates dependencies. +AC_DEFUN([ACX_DEPFLAG], +[ +AC_MSG_CHECKING([$CC dependency flag]) +echo 'void f(){}' >conftest.c +if test "`$CC -MM conftest.c 2>&1`" = "conftest.o: conftest.c"; then + DEPFLAG="-MM" +else + if test "`$CC -xM1 conftest.c 2>&1`" = "conftest.o: conftest.c"; then + DEPFLAG="-xM1" + else + DEPFLAG="-MM" # dunno do something + fi +fi +AC_MSG_RESULT($DEPFLAG) +rm -f conftest.c +AC_SUBST(DEPFLAG) +]) + +dnl Determine flags that gives POSIX and BSD functionality. +dnl CFLAGS is modified for the result. +AC_DEFUN([ACX_DETERMINE_EXT_FLAGS_UNBOUND], +[ +ACX_CHECK_COMPILER_FLAG(std=c99, [C99FLAG="-std=c99"]) +ACX_CHECK_COMPILER_FLAG(xc99, [C99FLAG="-xc99"]) + +AC_CHECK_HEADERS([getopt.h time.h],,, [AC_INCLUDES_DEFAULT]) + +ACX_CHECK_COMPILER_FLAG_NEEDED($C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_ALL_SOURCE, +[ +#include "confdefs.h" +#include +#include +#include +#ifdef HAVE_TIME_H +#include +#endif +#include +#include +#ifdef HAVE_GETOPT_H +#include +#endif + +int test() { + int a; + char **opts = NULL; + struct timeval tv; + char *t; + time_t time = 0; + char *buf = NULL; + const char* str = NULL; + struct msghdr msg; + msg.msg_control = 0; + t = ctime_r(&time, buf); + tv.tv_usec = 10; + srandom(32); + a = getopt(2, opts, "a"); + a = isascii(32); + str = gai_strerror(0); + if(str && t && tv.tv_usec && msg.msg_control) + a = 0; + return a; +} +], [CFLAGS="$CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_ALL_SOURCE"]) + +ACX_CHECK_COMPILER_FLAG_NEEDED($C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE, +[ +#include "confdefs.h" +#include +#include +#include +#ifdef HAVE_TIME_H +#include +#endif +#include +#include +#ifdef HAVE_GETOPT_H +#include +#endif + +int test() { + int a; + char **opts = NULL; + struct timeval tv; + char *t; + time_t time = 0; + char *buf = NULL; + const char* str = NULL; + struct msghdr msg; + msg.msg_control = 0; + t = ctime_r(&time, buf); + tv.tv_usec = 10; + srandom(32); + a = getopt(2, opts, "a"); + a = isascii(32); + str = gai_strerror(0); + if(str && t && tv.tv_usec && msg.msg_control) + a = 0; + return a; +} +], [CFLAGS="$CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE"]) + +ACX_CHECK_COMPILER_FLAG_NEEDED($C99FLAG, +[ +#include +#include +int test() { + int a = 0; + return a; +} +], [CFLAGS="$CFLAGS $C99FLAG"]) + +ACX_CHECK_COMPILER_FLAG_NEEDED(-D_BSD_SOURCE, +[ +#include + +int test() { + int a; + a = isascii(32); + return a; +} +], [CFLAGS="$CFLAGS -D_BSD_SOURCE"]) + +ACX_CHECK_COMPILER_FLAG_NEEDED(-D_GNU_SOURCE, +[ +#include + +int test() { + struct in6_pktinfo inf; + int a = (int)sizeof(inf); + return a; +} +], [CFLAGS="$CFLAGS -D_GNU_SOURCE"]) + +# check again for GNU_SOURCE for setresgid. May fail if setresgid +# is not available at all. -D_FRSRESGID is to make this check unique. +# otherwise we would get the previous cached result. +ACX_CHECK_COMPILER_FLAG_NEEDED(-D_GNU_SOURCE -D_FRSRESGID, +[ +#include + +int test() { + int a = setresgid(0,0,0); + a = setresuid(0,0,0); + return a; +} +], [CFLAGS="$CFLAGS -D_GNU_SOURCE"]) + +ACX_CHECK_COMPILER_FLAG_NEEDED(-D_POSIX_C_SOURCE=200112, +[ +#include "confdefs.h" +#ifdef HAVE_TIME_H +#include +#endif +#include + +int test() { + int a = 0; + char *t; + time_t time = 0; + char *buf = NULL; + const char* str = NULL; + t = ctime_r(&time, buf); + str = gai_strerror(0); + if(t && str) + a = 0; + return a; +} +], [CFLAGS="$CFLAGS -D_POSIX_C_SOURCE=200112"]) + +ACX_CHECK_COMPILER_FLAG_NEEDED(-D__EXTENSIONS__, +[ +#include "confdefs.h" +#include +#include +#include +#ifdef HAVE_TIME_H +#include +#endif +#include +#ifdef HAVE_GETOPT_H +#include +#endif + +int test() { + int a; + char **opts = NULL; + struct timeval tv; + tv.tv_usec = 10; + srandom(32); + a = getopt(2, opts, "a"); + a = isascii(32); + if(tv.tv_usec) + a = 0; + return a; +} +], [CFLAGS="$CFLAGS -D__EXTENSIONS__"]) + +])dnl End of ACX_DETERMINE_EXT_FLAGS_UNBOUND + +dnl Check if CC supports -flto. +dnl in a way that supports clang and suncc (that flag does something else, +dnl but fails to link). It sets it in CFLAGS if it works. +AC_DEFUN([ACX_CHECK_FLTO], +[AC_MSG_CHECKING([if $CC supports -flto]) +BAKCFLAGS="$CFLAGS" +CFLAGS="$CFLAGS -flto" +AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])], [ + if $CC $CFLAGS -o conftest conftest.c 2>&1 | grep "warning: no debug symbols in executable" >/dev/null; then + CFLAGS="$BAKCFLAGS" + AC_MSG_RESULT(no) + else + AC_MSG_RESULT(yes) + fi + rm -f conftest conftest.c conftest.o +], [CFLAGS="$BAKCFLAGS" ; AC_MSG_RESULT(no)]) +]) + +dnl Check the printf-format attribute (if any) +dnl result in HAVE_ATTR_FORMAT. +dnl Make sure you also include the AHX_CONFIG_FORMAT_ATTRIBUTE. +AC_DEFUN([ACX_CHECK_FORMAT_ATTRIBUTE], +[AC_REQUIRE([AC_PROG_CC]) +AC_MSG_CHECKING(whether the C compiler (${CC-cc}) accepts the "format" attribute) +AC_CACHE_VAL(ac_cv_c_format_attribute, +[ac_cv_c_format_attribute=no +AC_TRY_COMPILE( +[#include +void f (char *format, ...) __attribute__ ((format (printf, 1, 2))); +void (*pf) (char *format, ...) __attribute__ ((format (printf, 1, 2))); +], [ + f ("%s", "str"); +], +[ac_cv_c_format_attribute="yes"], +[ac_cv_c_format_attribute="no"]) +]) + +AC_MSG_RESULT($ac_cv_c_format_attribute) +if test $ac_cv_c_format_attribute = yes; then + AC_DEFINE(HAVE_ATTR_FORMAT, 1, [Whether the C compiler accepts the "format" attribute]) +fi +])dnl End of ACX_CHECK_FORMAT_ATTRIBUTE + +dnl Setup ATTR_FORMAT config.h parts. +dnl make sure you call ACX_CHECK_FORMAT_ATTRIBUTE also. +AC_DEFUN([AHX_CONFIG_FORMAT_ATTRIBUTE], +[ +#ifdef HAVE_ATTR_FORMAT +# define ATTR_FORMAT(archetype, string_index, first_to_check) \ + __attribute__ ((format (archetype, string_index, first_to_check))) +#else /* !HAVE_ATTR_FORMAT */ +# define ATTR_FORMAT(archetype, string_index, first_to_check) /* empty */ +#endif /* !HAVE_ATTR_FORMAT */ +]) + +dnl Check how to mark function arguments as unused. +dnl result in HAVE_ATTR_UNUSED. +dnl Make sure you include AHX_CONFIG_UNUSED_ATTRIBUTE also. +AC_DEFUN([ACX_CHECK_UNUSED_ATTRIBUTE], +[AC_REQUIRE([AC_PROG_CC]) +AC_MSG_CHECKING(whether the C compiler (${CC-cc}) accepts the "unused" attribute) +AC_CACHE_VAL(ac_cv_c_unused_attribute, +[ac_cv_c_unused_attribute=no +AC_TRY_COMPILE( +[#include +void f (char *u __attribute__((unused))); +], [ + f ("x"); +], +[ac_cv_c_unused_attribute="yes"], +[ac_cv_c_unused_attribute="no"]) +]) + +dnl Setup ATTR_UNUSED config.h parts. +dnl make sure you call ACX_CHECK_UNUSED_ATTRIBUTE also. +AC_DEFUN([AHX_CONFIG_UNUSED_ATTRIBUTE], +[ +#if defined(DOXYGEN) +# define ATTR_UNUSED(x) x +#elif defined(__cplusplus) +# define ATTR_UNUSED(x) +#elif defined(HAVE_ATTR_UNUSED) +# define ATTR_UNUSED(x) x __attribute__((unused)) +#else /* !HAVE_ATTR_UNUSED */ +# define ATTR_UNUSED(x) x +#endif /* !HAVE_ATTR_UNUSED */ +]) + +AC_MSG_RESULT($ac_cv_c_unused_attribute) +if test $ac_cv_c_unused_attribute = yes; then + AC_DEFINE(HAVE_ATTR_UNUSED, 1, [Whether the C compiler accepts the "unused" attribute]) +fi +])dnl + +dnl Pre-fun for ACX_LIBTOOL_C_ONLY +AC_DEFUN([ACX_LIBTOOL_C_PRE], [ +# skip these tests, we do not need them. +AC_DEFUN([AC_PROG_F77], [:]) +AC_DEFUN([AC_PROG_FC], [:]) +AC_DEFUN([AC_PROG_CXX], [:]) +AC_DEFUN([AC_PROG_CXXCPP], [:]) +AC_DEFUN([AC_PROG_OBJC], [:]) +AC_DEFUN([AC_PROG_OBJCCPP], [:]) +AC_DEFUN([AC_LIBTOOL_CXX], [:]) +AC_DEFUN([AC_LIBTOOL_F77], [:]) +# always use ./libtool unless override from commandline (libtool=mylibtool) +if test -z "$libtool"; then + libtool="./libtool" +fi +AC_SUBST(libtool) +# avoid libtool max commandline length test on systems that fork slowly. +AC_CANONICAL_HOST +if echo "$host_os" | grep "sunos4" >/dev/null; then + lt_cv_sys_max_cmd_len=32750; +fi +AC_PATH_TOOL(AR, ar, [false]) +if test $AR = false; then + AC_MSG_ERROR([Cannot find 'ar', please extend PATH to include it]) +fi +]) + +dnl Perform libtool check, portably, only for C +AC_DEFUN([ACX_LIBTOOL_C_ONLY], [ +dnl as a requirement so that is gets called before LIBTOOL +dnl because libtools 'AC_REQUIRE' names are right after this one, before +dnl this function contents. +AC_REQUIRE([ACX_LIBTOOL_C_PRE]) +AC_PROG_LIBTOOL +]) + +dnl Detect if u_char type is defined, otherwise define it. +AC_DEFUN([ACX_TYPE_U_CHAR], +[AC_CHECK_TYPE([u_char], , + [AC_DEFINE([u_char], [unsigned char], [Define to 'unsigned char if not defined])], [ +AC_INCLUDES_DEFAULT +#ifdef HAVE_WINSOCK2_H +# include +#endif +]) ]) + +dnl Detect if rlim_t type is defined, otherwise define it. +AC_DEFUN([ACX_TYPE_RLIM_T], +[AC_CHECK_TYPE(rlim_t, , + [AC_DEFINE([rlim_t], [unsigned long], [Define to 'int' if not defined])], [ +AC_INCLUDES_DEFAULT +#ifdef HAVE_SYS_RESOURCE_H +# include +#endif +]) ]) + +dnl Detect if socklen_t type is defined, otherwise define it. +AC_DEFUN([ACX_TYPE_SOCKLEN_T], +[ +AC_CHECK_TYPE(socklen_t, , + [AC_DEFINE([socklen_t], [int], [Define to 'int' if not defined])], [ +AC_INCLUDES_DEFAULT +#ifdef HAVE_SYS_SOCKET_H +# include +#endif +#ifdef HAVE_WS2TCPIP_H +# include +#endif +]) ]) + +dnl Detect if in_addr_t type is defined, otherwise define it. +AC_DEFUN([ACX_TYPE_IN_ADDR_T], +[ AC_CHECK_TYPE(in_addr_t, [], [AC_DEFINE([in_addr_t], [uint32_t], [in_addr_t])], [ +AC_INCLUDES_DEFAULT +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_NETINET_IN_H +# include +#endif +]) ]) + +dnl Detect if in_port_t type is defined, otherwise define it. +AC_DEFUN([ACX_TYPE_IN_PORT_T], +[ AC_CHECK_TYPE(in_port_t, [], [AC_DEFINE([in_port_t], [uint16_t], [in_port_t])], [ +AC_INCLUDES_DEFAULT +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_NETINET_IN_H +# include +#endif +]) ]) + +dnl Add option to disable the evil rpath. Check whether to use rpath or not. +dnl Adds the --disable-rpath option. Uses trick to edit the ./libtool. +AC_DEFUN([ACX_ARG_RPATH], +[ +AC_ARG_ENABLE(rpath, + [ --disable-rpath disable hardcoded rpath (default=enabled)], + enable_rpath=$enableval, enable_rpath=yes) +if test "x$enable_rpath" = xno; then + dnl AC_MSG_RESULT([Fixing libtool for -rpath problems.]) + AC_CONFIG_COMMANDS([disable-rpath], [ + sed < libtool > libtool-2 \ + 's/^hardcode_libdir_flag_spec.*$'/'hardcode_libdir_flag_spec=" -D__LIBTOOL_RPATH_SED__ "/' + mv libtool-2 libtool + chmod 755 libtool + libtool="./libtool" + ]) +fi +]) + +dnl Add a -R to the RUNTIME_PATH. Only if rpath is enabled and it is +dnl an absolute path. +dnl $1: the pathname to add. +AC_DEFUN([ACX_RUNTIME_PATH_ADD], [ + if test "x$enable_rpath" = xyes; then + if echo "$1" | grep "^/" >/dev/null; then + RUNTIME_PATH="$RUNTIME_PATH -R$1" + fi + fi +]) + +dnl Common code for both ACX_WITH_SSL and ACX_WITH_SSL_OPTIONAL +dnl Takes one argument; the withval checked in those 2 functions +dnl sets up the environment for the given openssl path +AC_DEFUN([ACX_SSL_CHECKS], [ + withval=$1 + if test x_$withval != x_no; then + AC_MSG_CHECKING(for SSL) + if test x_$withval = x_ -o x_$withval = x_yes; then + withval="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw /usr" + fi + for dir in $withval; do + ssldir="$dir" + if test -f "$dir/include/openssl/ssl.h"; then + found_ssl="yes" + AC_DEFINE_UNQUOTED([HAVE_SSL], [], [Define if you have the SSL libraries installed.]) + dnl assume /usr/include is already in the include-path. + if test "$ssldir" != "/usr"; then + CPPFLAGS="$CPPFLAGS -I$ssldir/include" + LIBSSL_CPPFLAGS="$LIBSSL_CPPFLAGS -I$ssldir/include" + fi + break; + fi + done + if test x_$found_ssl != x_yes; then + AC_MSG_ERROR(Cannot find the SSL libraries in $withval) + else + AC_MSG_RESULT(found in $ssldir) + HAVE_SSL=yes + dnl assume /usr is already in the lib and dynlib paths. + if test "$ssldir" != "/usr" -a "$ssldir" != ""; then + LDFLAGS="$LDFLAGS -L$ssldir/lib" + LIBSSL_LDFLAGS="$LIBSSL_LDFLAGS -L$ssldir/lib" + ACX_RUNTIME_PATH_ADD([$ssldir/lib]) + fi + + AC_MSG_CHECKING([for HMAC_CTX_init in -lcrypto]) + LIBS="$LIBS -lcrypto" + LIBSSL_LIBS="$LIBSSL_LIBS -lcrypto" + AC_TRY_LINK(, [ + int HMAC_CTX_init(void); + (void)HMAC_CTX_init(); + ], [ + AC_MSG_RESULT(yes) + AC_DEFINE([HAVE_HMAC_CTX_INIT], 1, + [If you have HMAC_CTX_init]) + ], [ + AC_MSG_RESULT(no) + # check if -lwsock32 or -lgdi32 are needed. + BAKLIBS="$LIBS" + BAKSSLLIBS="$LIBSSL_LIBS" + LIBS="$LIBS -lgdi32" + LIBSSL_LIBS="$LIBSSL_LIBS -lgdi32" + AC_MSG_CHECKING([if -lcrypto needs -lgdi32]) + AC_TRY_LINK([], [ + int HMAC_CTX_init(void); + (void)HMAC_CTX_init(); + ],[ + AC_DEFINE([HAVE_HMAC_CTX_INIT], 1, + [If you have HMAC_CTX_init]) + AC_MSG_RESULT(yes) + ],[ + AC_MSG_RESULT(no) + LIBS="$BAKLIBS" + LIBSSL_LIBS="$BAKSSLLIBS" + LIBS="$LIBS -ldl" + LIBSSL_LIBS="$LIBSSL_LIBS -ldl" + AC_MSG_CHECKING([if -lcrypto needs -ldl]) + AC_TRY_LINK([], [ + int HMAC_CTX_init(void); + (void)HMAC_CTX_init(); + ],[ + AC_DEFINE([HAVE_HMAC_CTX_INIT], 1, + [If you have HMAC_CTX_init]) + AC_MSG_RESULT(yes) + ],[ + AC_MSG_RESULT(no) + AC_MSG_ERROR([OpenSSL found in $ssldir, but version 0.9.7 or higher is required]) + ]) + ]) + ]) + fi + AC_SUBST(HAVE_SSL) + AC_SUBST(RUNTIME_PATH) + # openssl engine functionality needs dlopen(). + BAKLIBS="$LIBS" + AC_SEARCH_LIBS([dlopen], [dl]) + if test "$LIBS" != "$BAKLIBS"; then + LIBSSL_LIBS="$LIBSSL_LIBS -ldl" + fi + fi +AC_CHECK_HEADERS([openssl/ssl.h],,, [AC_INCLUDES_DEFAULT]) +AC_CHECK_HEADERS([openssl/err.h],,, [AC_INCLUDES_DEFAULT]) +AC_CHECK_HEADERS([openssl/rand.h],,, [AC_INCLUDES_DEFAULT]) +])dnl End of ACX_SSL_CHECKS + +dnl Check for SSL, where SSL is mandatory +dnl Adds --with-ssl option, searches for openssl and defines HAVE_SSL if found +dnl Setup of CPPFLAGS, CFLAGS. Adds -lcrypto to LIBS. +dnl Checks main header files of SSL. +dnl +AC_DEFUN([ACX_WITH_SSL], +[ +AC_ARG_WITH(ssl, AC_HELP_STRING([--with-ssl=pathname], + [enable SSL (will check /usr/local/ssl + /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw /usr)]),[ + ],[ + withval="yes" + ]) + if test x_$withval = x_no; then + AC_MSG_ERROR([Need SSL library to do digital signature cryptography]) + fi + ACX_SSL_CHECKS($withval) +])dnl End of ACX_WITH_SSL + +dnl Check for SSL, where ssl is optional (--without-ssl is allowed) +dnl Adds --with-ssl option, searches for openssl and defines HAVE_SSL if found +dnl Setup of CPPFLAGS, CFLAGS. Adds -lcrypto to LIBS. +dnl Checks main header files of SSL. +dnl +AC_DEFUN([ACX_WITH_SSL_OPTIONAL], +[ +AC_ARG_WITH(ssl, AC_HELP_STRING([--with-ssl=pathname], + [enable SSL (will check /usr/local/ssl + /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw /usr)]),[ + ],[ + withval="yes" + ]) + ACX_SSL_CHECKS($withval) +])dnl End of ACX_WITH_SSL_OPTIONAL + +dnl Setup to use -lssl +dnl To use -lcrypto, use the ACX_WITH_SSL setup (before this one). +AC_DEFUN([ACX_LIB_SSL], +[ +# check if libssl needs libdl +BAKLIBS="$LIBS" +LIBS="-lssl $LIBS" +AC_MSG_CHECKING([if libssl needs libdl]) +AC_TRY_LINK_FUNC([SSL_CTX_new], [ + AC_MSG_RESULT([no]) + LIBS="$BAKLIBS" +] , [ + AC_MSG_RESULT([yes]) + LIBS="$BAKLIBS" + AC_SEARCH_LIBS([dlopen], [dl]) +]) ])dnl End of ACX_LIB_SSL + +dnl Setup to use very large files (>2Gb). +dnl setups fseeko and its own +AC_DEFUN([ACX_SYS_LARGEFILE], +[ +AC_SYS_LARGEFILE +dnl try to see if an additional _LARGEFILE_SOURCE 1 is needed to get fseeko +ACX_CHECK_COMPILER_FLAG_NEEDED(-D_LARGEFILE_SOURCE=1, +[ +#include +int test() { + int a = fseeko(stdin, 0, 0); + return a; +} +], [CFLAGS="$CFLAGS -D_LARGEFILE_SOURCE=1"]) +]) + +dnl Check getaddrinfo. +dnl Works on linux, solaris, bsd and windows(links winsock). +dnl defines HAVE_GETADDRINFO, USE_WINSOCK. +AC_DEFUN([ACX_CHECK_GETADDRINFO_WITH_INCLUDES], +[AC_REQUIRE([AC_PROG_CC]) +AC_MSG_CHECKING(for getaddrinfo) +ac_cv_func_getaddrinfo=no +AC_LINK_IFELSE( +[AC_LANG_SOURCE([[ +#ifdef __cplusplus +extern "C" +{ +#endif +char* getaddrinfo(); +char* (*f) () = getaddrinfo; +#ifdef __cplusplus +} +#endif +int main() { + ; + return 0; +} +]])], +dnl this case on linux, solaris, bsd +[ac_cv_func_getaddrinfo="yes" +dnl see if on windows +if test "$ac_cv_header_windows_h" = "yes"; then + AC_DEFINE(USE_WINSOCK, 1, [Whether the windows socket API is used]) + USE_WINSOCK="1" + LIBS="$LIBS -lws2_32" +fi +], +dnl no quick getaddrinfo, try mingw32 and winsock2 library. +ORIGLIBS="$LIBS" +LIBS="$LIBS -lws2_32" +AC_LINK_IFELSE( +[AC_LANG_PROGRAM( +[ +#ifdef HAVE_WS2TCPIP_H +#include +#endif +], +[ + (void)getaddrinfo(NULL, NULL, NULL, NULL); +] +)], +[ +ac_cv_func_getaddrinfo="yes" +dnl already: LIBS="$LIBS -lws2_32" +AC_DEFINE(USE_WINSOCK, 1, [Whether the windows socket API is used]) +USE_WINSOCK="1" +], +[ +ac_cv_func_getaddrinfo="no" +LIBS="$ORIGLIBS" +]) +) + +AC_MSG_RESULT($ac_cv_func_getaddrinfo) +if test $ac_cv_func_getaddrinfo = yes; then + AC_DEFINE(HAVE_GETADDRINFO, 1, [Whether getaddrinfo is available]) +fi +])dnl Endof AC_CHECK_GETADDRINFO_WITH_INCLUDES + +dnl check if a function is deprecated. defines DEPRECATED_func in config.h. +dnl $1: function name +dnl $2: C-statement that calls the function. +dnl $3: includes for the program. +dnl $4: executes if yes +dnl $5: executes if no +AC_DEFUN([ACX_FUNC_DEPRECATED], +[ +AC_REQUIRE([AC_PROG_CC]) +AC_MSG_CHECKING(if $1 is deprecated) +cache=`echo $1 | sed 'y%.=/+-%___p_%'` +AC_CACHE_VAL(cv_cc_deprecated_$cache, +[ +echo '$3' >conftest.c +echo 'void f(){ $2 }' >>conftest.c +if test -z "`$CC -c conftest.c 2>&1 | grep deprecated`"; then +eval "cv_cc_deprecated_$cache=no" +else +eval "cv_cc_deprecated_$cache=yes" +fi +rm -f conftest conftest.o conftest.c +]) +if eval "test \"`echo '$cv_cc_deprecated_'$cache`\" = yes"; then +AC_MSG_RESULT(yes) +AC_DEFINE_UNQUOTED(AS_TR_CPP([DEPRECATED_$1]), 1, [Whether $1 is deprecated]) +: +$4 +else +AC_MSG_RESULT(no) +: +$5 +fi +])dnl end of ACX_FUNC_DEPRECATED + +dnl check if select and nonblocking sockets actually work. +dnl Needs fork(2) and select(2). +dnl defines NONBLOCKING_IS_BROKEN, and if that is true multiple reads from +dnl a nonblocking socket do not work, a new call to select is necessary. +AC_DEFUN([ACX_CHECK_NONBLOCKING_BROKEN], +[ +AC_MSG_CHECKING([if nonblocking sockets work]) +if echo $target | grep mingw32 >/dev/null; then + AC_MSG_RESULT([no (windows)]) + AC_DEFINE([NONBLOCKING_IS_BROKEN], 1, [Define if the network stack does not fully support nonblocking io (causes lower performance).]) +else +AC_RUN_IFELSE([ +AC_LANG_SOURCE([[ +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_TIME_H +#include +#endif + +int main(void) +{ + int port; + int sfd, cfd; + int num = 10; + int i, p; + struct sockaddr_in a; + /* test if select and nonblocking reads work well together */ + /* open port. + fork child to send 10 messages. + select to read. + then try to nonblocking read the 10 messages + then, nonblocking read must give EAGAIN + */ + + port = 12345 + (time(0)%32); + sfd = socket(PF_INET, SOCK_DGRAM, 0); + if(sfd == -1) { + perror("socket"); + return 1; + } + memset(&a, 0, sizeof(a)); + a.sin_family = AF_INET; + a.sin_port = htons(port); + a.sin_addr.s_addr = inet_addr("127.0.0.1"); + if(bind(sfd, (struct sockaddr*)&a, sizeof(a)) < 0) { + perror("bind"); + return 1; + } + if(fcntl(sfd, F_SETFL, O_NONBLOCK) == -1) { + perror("fcntl"); + return 1; + } + + cfd = socket(PF_INET, SOCK_DGRAM, 0); + if(cfd == -1) { + perror("client socket"); + return 1; + } + a.sin_port = 0; + if(bind(cfd, (struct sockaddr*)&a, sizeof(a)) < 0) { + perror("client bind"); + return 1; + } + a.sin_port = htons(port); + + /* no handler, causes exit in 10 seconds */ + alarm(10); + + /* send and receive on the socket */ + if((p=fork()) == 0) { + for(i=0; i +#include +#ifdef HAVE_WINSOCK2_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +], [ + (void)mkdir("directory"); +], +AC_MSG_RESULT(yes) +AC_DEFINE(MKDIR_HAS_ONE_ARG, 1, [Define if mkdir has one argument.]) +, +AC_MSG_RESULT(no) +) +])dnl end of ACX_MKDIR_ONE_ARG + +dnl Check for ioctlsocket function. works on mingw32 too. +AC_DEFUN([ACX_FUNC_IOCTLSOCKET], +[ +# check ioctlsocket +AC_MSG_CHECKING(for ioctlsocket) +AC_LINK_IFELSE([AC_LANG_PROGRAM([ +#ifdef HAVE_WINSOCK2_H +#include +#endif +], [ + (void)ioctlsocket(0, 0, NULL); +])], [ +AC_MSG_RESULT(yes) +AC_DEFINE(HAVE_IOCTLSOCKET, 1, [if the function 'ioctlsocket' is available]) +],[AC_MSG_RESULT(no)]) +])dnl end of ACX_FUNC_IOCTLSOCKET + +dnl detect malloc and provide malloc compat prototype. +dnl $1: unique name for compat code +AC_DEFUN([ACX_FUNC_MALLOC], +[ + AC_MSG_CHECKING([for GNU libc compatible malloc]) + AC_RUN_IFELSE([AC_LANG_PROGRAM( +[[#if defined STDC_HEADERS || defined HAVE_STDLIB_H +#include +#else +char *malloc (); +#endif +]], [ if(malloc(0) != 0) return 1;]) +], + [AC_MSG_RESULT([no]) + AC_LIBOBJ(malloc) + AC_DEFINE_UNQUOTED([malloc], [rpl_malloc_$1], [Define if replacement function should be used.])] , + [AC_MSG_RESULT([yes]) + AC_DEFINE([HAVE_MALLOC], 1, [If have GNU libc compatible malloc])], + [AC_MSG_RESULT([no (crosscompile)]) + AC_LIBOBJ(malloc) + AC_DEFINE_UNQUOTED([malloc], [rpl_malloc_$1], [Define if replacement function should be used.])] ) +]) + +dnl Define fallback for fseeko and ftello if needed. +AC_DEFUN([AHX_CONFIG_FSEEKO], +[ +#ifndef HAVE_FSEEKO +#define fseeko fseek +#define ftello ftell +#endif /* HAVE_FSEEKO */ +]) + +dnl Define RAND_MAX if not defined +AC_DEFUN([AHX_CONFIG_RAND_MAX], +[ +#ifndef RAND_MAX +#define RAND_MAX 2147483647 +#endif +]) + +dnl Define MAXHOSTNAMELEN if not defined +AC_DEFUN([AHX_CONFIG_MAXHOSTNAMELEN], +[ +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 256 +#endif +]) + +dnl Define IPV6_MIN_MTU if not defined +AC_DEFUN([AHX_CONFIG_IPV6_MIN_MTU], +[ +#ifndef IPV6_MIN_MTU +#define IPV6_MIN_MTU 1280 +#endif /* IPV6_MIN_MTU */ +]) + +dnl provide snprintf, vsnprintf compat prototype +dnl $1: unique name for compat code +AC_DEFUN([AHX_CONFIG_SNPRINTF], +[ +#ifndef HAVE_SNPRINTF +#define snprintf snprintf_$1 +#define vsnprintf vsnprintf_$1 +#include +int snprintf (char *str, size_t count, const char *fmt, ...); +int vsnprintf (char *str, size_t count, const char *fmt, va_list arg); +#endif /* HAVE_SNPRINTF */ +]) + +dnl provide inet_pton compat prototype. +dnl $1: unique name for compat code +AC_DEFUN([AHX_CONFIG_INET_PTON], +[ +#ifndef HAVE_INET_PTON +#define inet_pton inet_pton_$1 +int inet_pton(int af, const char* src, void* dst); +#endif /* HAVE_INET_PTON */ +]) + +dnl provide inet_ntop compat prototype. +dnl $1: unique name for compat code +AC_DEFUN([AHX_CONFIG_INET_NTOP], +[ +#ifndef HAVE_INET_NTOP +#define inet_ntop inet_ntop_$1 +const char *inet_ntop(int af, const void *src, char *dst, size_t size); +#endif +]) + +dnl provide inet_aton compat prototype. +dnl $1: unique name for compat code +AC_DEFUN([AHX_CONFIG_INET_ATON], +[ +#ifndef HAVE_INET_ATON +#define inet_aton inet_aton_$1 +int inet_aton(const char *cp, struct in_addr *addr); +#endif +]) + +dnl provide memmove compat prototype. +dnl $1: unique name for compat code +AC_DEFUN([AHX_CONFIG_MEMMOVE], +[ +#ifndef HAVE_MEMMOVE +#define memmove memmove_$1 +void *memmove(void *dest, const void *src, size_t n); +#endif +]) + +dnl provide strlcat compat prototype. +dnl $1: unique name for compat code +AC_DEFUN([AHX_CONFIG_STRLCAT], +[ +#ifndef HAVE_STRLCAT +#define strlcat strlcat_$1 +size_t strlcat(char *dst, const char *src, size_t siz); +#endif +]) + +dnl provide strlcpy compat prototype. +dnl $1: unique name for compat code +AC_DEFUN([AHX_CONFIG_STRLCPY], +[ +#ifndef HAVE_STRLCPY +#define strlcpy strlcpy_$1 +size_t strlcpy(char *dst, const char *src, size_t siz); +#endif +]) + +dnl provide gmtime_r compat prototype. +dnl $1: unique name for compat code +AC_DEFUN([AHX_CONFIG_GMTIME_R], +[ +#ifndef HAVE_GMTIME_R +#define gmtime_r gmtime_r_$1 +struct tm *gmtime_r(const time_t *timep, struct tm *result); +#endif +]) + +dnl provide w32 compat definition for sleep +AC_DEFUN([AHX_CONFIG_W32_SLEEP], +[ +#ifndef HAVE_SLEEP +#define sleep(x) Sleep((x)*1000) /* on win32 */ +#endif /* HAVE_SLEEP */ +]) + +dnl provide w32 compat definition for usleep +AC_DEFUN([AHX_CONFIG_W32_USLEEP], +[ +#ifndef HAVE_USLEEP +#define usleep(x) Sleep((x)/1000 + 1) /* on win32 */ +#endif /* HAVE_USLEEP */ +]) + +dnl provide w32 compat definition for random +AC_DEFUN([AHX_CONFIG_W32_RANDOM], +[ +#ifndef HAVE_RANDOM +#define random rand /* on win32, for tests only (bad random) */ +#endif /* HAVE_RANDOM */ +]) + +dnl provide w32 compat definition for srandom +AC_DEFUN([AHX_CONFIG_W32_SRANDOM], +[ +#ifndef HAVE_SRANDOM +#define srandom(x) srand(x) /* on win32, for tests only (bad random) */ +#endif /* HAVE_SRANDOM */ +]) + +dnl provide w32 compat definition for FD_SET_T +AC_DEFUN([AHX_CONFIG_W32_FD_SET_T], +[ +/* detect if we need to cast to unsigned int for FD_SET to avoid warnings */ +#ifdef HAVE_WINSOCK2_H +#define FD_SET_T (u_int) +#else +#define FD_SET_T +#endif +]) + +dnl Remove an extension flag from CFLAGS, define replacement to be made. +dnl Used by ACX_STRIP_EXT_FLAGS. +dnl $1: the name of the flag, for example -D_GNU_SOURCE. +AC_DEFUN([ACX_CFLAGS_STRIP], +[ + if echo $CFLAGS | grep " $1" >/dev/null 2>&1; then + CFLAGS="`echo $CFLAGS | sed -e 's/ $1//g'`" + AC_DEFINE(m4_bpatsubst(OMITTED_$1,[[-=]],_), 1, Put $1 define in config.h) + fi +]) + +dnl Remove EXT flags from the CFLAGS and set them to be defined in config.h +dnl use with ACX_DETERMINE_EXT_FLAGS. +AC_DEFUN([ACX_STRIP_EXT_FLAGS], +[ + AC_MSG_NOTICE([Stripping extension flags...]) + ACX_CFLAGS_STRIP(-D_GNU_SOURCE) + ACX_CFLAGS_STRIP(-D_BSD_SOURCE) + ACX_CFLAGS_STRIP(-D__EXTENSIONS__) + ACX_CFLAGS_STRIP(-D_POSIX_C_SOURCE=200112) + ACX_CFLAGS_STRIP(-D_XOPEN_SOURCE=600) + ACX_CFLAGS_STRIP(-D_XOPEN_SOURCE_EXTENDED=1) + ACX_CFLAGS_STRIP(-D_ALL_SOURCE) + ACX_CFLAGS_STRIP(-D_LARGEFILE_SOURCE=1) +]) dnl End of ACX_STRIP_EXT_FLAGS + +dnl define one omitted flag for config.h +dnl $1: flag name. -D_GNU_SOURCE +dnl $2: replacement define. _GNU_SOURCE +dnl $3: define value, 1 +AC_DEFUN([AHX_CONFIG_FLAG_OMITTED], +[#if defined($1) && !defined($2) +#define $2 $3 +[#]endif ]) + +dnl Wrapper for AHX_CONFIG_FLAG_OMITTED for -D style flags +dnl $1: the -DNAME or -DNAME=value string. +AC_DEFUN([AHX_CONFIG_FLAG_EXT], +[AHX_CONFIG_FLAG_OMITTED(m4_bpatsubst(OMITTED_$1,[[-=]],_),m4_bpatsubst(m4_bpatsubst($1,-D,),=.*$,),m4_if(m4_bregexp($1,=),-1,1,m4_bpatsubst($1,^.*=,))) +]) + +dnl config.h part to define omitted cflags, use with ACX_STRIP_EXT_FLAGS. +AC_DEFUN([AHX_CONFIG_EXT_FLAGS], +[AHX_CONFIG_FLAG_EXT(-D_GNU_SOURCE) +AHX_CONFIG_FLAG_EXT(-D_BSD_SOURCE) +AHX_CONFIG_FLAG_EXT(-D__EXTENSIONS__) +AHX_CONFIG_FLAG_EXT(-D_POSIX_C_SOURCE=200112) +AHX_CONFIG_FLAG_EXT(-D_XOPEN_SOURCE=600) +AHX_CONFIG_FLAG_EXT(-D_XOPEN_SOURCE_EXTENDED=1) +AHX_CONFIG_FLAG_EXT(-D_ALL_SOURCE) +AHX_CONFIG_FLAG_EXT(-D_LARGEFILE_SOURCE=1) +]) + +dnl check if memcmp is using signed characters and replace if so. +AC_DEFUN([ACX_CHECK_MEMCMP_SIGNED], +[AC_MSG_CHECKING([if memcmp compares unsigned]) +AC_RUN_IFELSE([AC_LANG_SOURCE([[ +#include +#include +#include +int main(void) +{ + char a = 255, b = 0; + if(memcmp(&a, &b, 1) < 0) + return 1; + return 0; +} +]])], [AC_MSG_RESULT([yes]) ], +[ AC_MSG_RESULT([no]) + AC_DEFINE([MEMCMP_IS_BROKEN], [1], [Define if memcmp() does not compare unsigned bytes]) + AC_LIBOBJ([memcmp]) +], [ AC_MSG_RESULT([cross-compile no]) + AC_DEFINE([MEMCMP_IS_BROKEN], [1], [Define if memcmp() does not compare unsigned bytes]) + AC_LIBOBJ([memcmp]) +]) ]) + +dnl define memcmp to its replacement, pass unique id for program as arg +AC_DEFUN([AHX_MEMCMP_BROKEN], [ +#ifdef MEMCMP_IS_BROKEN +#include "compat/memcmp.h" +#define memcmp memcmp_$1 +int memcmp(const void *x, const void *y, size_t n); +#endif +]) + +dnl ACX_CHECK_SS_FAMILY - check for sockaddr_storage.ss_family +AC_DEFUN([ACX_CHECK_SS_FAMILY], +[AC_CHECK_MEMBER([struct sockaddr_storage.ss_family], [], [ + AC_CHECK_MEMBER([struct sockaddr_storage.__ss_family], [ + AC_DEFINE([ss_family], [__ss_family], [Fallback member name for socket family in struct sockaddr_storage]) + ],, [AC_INCLUDES_DEFAULT +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif + ]) +], [AC_INCLUDES_DEFAULT +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +]) ]) + +dnl End of file diff --git a/acx_pthread.m4 b/acx_pthread.m4 new file mode 100644 index 00000000000..7ac8ffddc5b --- /dev/null +++ b/acx_pthread.m4 @@ -0,0 +1,280 @@ +##### http://autoconf-archive.cryp.to/acx_pthread.html +# +# SYNOPSIS +# +# ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) +# +# DESCRIPTION +# +# This macro figures out how to build C programs using POSIX threads. +# It sets the PTHREAD_LIBS output variable to the threads library and +# linker flags, and the PTHREAD_CFLAGS output variable to any special +# C compiler flags that are needed. (The user can also force certain +# compiler flags/libs to be tested by setting these environment +# variables.) +# +# Also sets PTHREAD_CC to any special C compiler that is needed for +# multi-threaded programs (defaults to the value of CC otherwise). +# (This is necessary on AIX to use the special cc_r compiler alias.) +# +# NOTE: You are assumed to not only compile your program with these +# flags, but also link it with them as well. e.g. you should link +# with $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS +# $LIBS +# +# If you are only building threads programs, you may wish to use +# these variables in your default LIBS, CFLAGS, and CC: +# +# LIBS="$PTHREAD_LIBS $LIBS" +# CFLAGS="$CFLAGS $PTHREAD_CFLAGS" +# CC="$PTHREAD_CC" +# +# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute +# constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to +# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). +# +# ACTION-IF-FOUND is a list of shell commands to run if a threads +# library is found, and ACTION-IF-NOT-FOUND is a list of commands to +# run it if it is not found. If ACTION-IF-FOUND is not specified, the +# default action will define HAVE_PTHREAD. +# +# Please let the authors know if this macro fails on any platform, or +# if you have any other suggestions or comments. This macro was based +# on work by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) +# (with help from M. Frigo), as well as ac_pthread and hb_pthread +# macros posted by Alejandro Forero Cuervo to the autoconf macro +# repository. We are also grateful for the helpful feedback of +# numerous users. +# +# LAST MODIFICATION +# +# 2006-05-29 +# +# COPYLEFT +# +# Copyright (c) 2006 Steven G. Johnson +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. +# +# As a special exception, the respective Autoconf Macro's copyright +# owner gives unlimited permission to copy, distribute and modify the +# configure scripts that are the output of Autoconf when processing +# the Macro. You need not follow the terms of the GNU General Public +# License when using or distributing such scripts, even though +# portions of the text of the Macro appear in them. The GNU General +# Public License (GPL) does govern all other use of the material that +# constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the +# Autoconf Macro released by the Autoconf Macro Archive. When you +# make and distribute a modified version of the Autoconf Macro, you +# may extend this special exception to the GPL to apply to your +# modified version as well. + +AC_DEFUN([ACX_PTHREAD], [ +AC_REQUIRE([AC_CANONICAL_HOST]) +AC_LANG_SAVE +AC_LANG_C +acx_pthread_ok=no + +# We used to check for pthread.h first, but this fails if pthread.h +# requires special compiler flags (e.g. on True64 or Sequent). +# It gets checked for in the link test anyway. + +# First of all, check if the user has set any of the PTHREAD_LIBS, +# etcetera environment variables, and if threads linking works using +# them: +if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) + AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes) + AC_MSG_RESULT($acx_pthread_ok) + if test x"$acx_pthread_ok" = xno; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" +fi + +# We must check for the threads library under a number of different +# names; the ordering is very important because some systems +# (e.g. DEC) have both -lpthread and -lpthreads, where one of the +# libraries is broken (non-POSIX). + +# Create a list of thread flags to try. Items starting with a "-" are +# C compiler flags, and other items are library names, except for "none" +# which indicates that we try without any flags at all, and "pthread-config" +# which is a program returning the flags for the Pth emulation library. + +acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" + +# The ordering *is* (sometimes) important. Some notes on the +# individual items follow: + +# pthreads: AIX (must check this before -lpthread) +# none: in case threads are in libc; should be tried before -Kthread and +# other compiler flags to prevent continual compiler warnings +# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) +# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) +# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) +# -pthreads: Solaris/gcc +# -mthreads: Mingw32/gcc, Lynx/gcc +# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it +# doesn't hurt to check since this sometimes defines pthreads too; +# also defines -D_REENTRANT) +# ... -mt is also the pthreads flag for HP/aCC +# pthread: Linux, etcetera +# --thread-safe: KAI C++ +# pthread-config: use pthread-config program (for GNU Pth library) + +case "${host_cpu}-${host_os}" in + *solaris*) + + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (We need to link with -pthreads/-mt/ + # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather + # a function called by this macro, so we could check for that, but + # who knows whether they'll stub that too in a future libc.) So, + # we'll just look for -pthreads and -lpthread first: + + acx_pthread_flags="-pthreads pthread -mt -pthread $acx_pthread_flags" + ;; +esac + +if test x"$acx_pthread_ok" = xno; then +for flag in $acx_pthread_flags; do + + case $flag in + none) + AC_MSG_CHECKING([whether pthreads work without any flags]) + ;; + + -*) + AC_MSG_CHECKING([whether pthreads work with $flag]) + PTHREAD_CFLAGS="$flag" + ;; + + pthread-config) + AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no) + if test x"$acx_pthread_config" = xno; then continue; fi + PTHREAD_CFLAGS="`pthread-config --cflags`" + PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" + ;; + + *) + AC_MSG_CHECKING([for the pthreads library -l$flag]) + PTHREAD_LIBS="-l$flag" + ;; + esac + + save_LIBS="$LIBS" + save_CFLAGS="$CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + AC_TRY_LINK([#include ], + [pthread_t th; pthread_join(th, 0); + pthread_attr_init(0); pthread_cleanup_push(0, 0); + pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], + [acx_pthread_ok=yes]) + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + AC_MSG_RESULT($acx_pthread_ok) + if test "x$acx_pthread_ok" = xyes; then + break; + fi + + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" +done +fi + +# Various other checks: +if test "x$acx_pthread_ok" = xyes; then + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + + # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. + AC_MSG_CHECKING([for joinable pthread attribute]) + attr_name=unknown + for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + AC_TRY_LINK([#include ], [int attr=$attr; return attr;], + [attr_name=$attr; break]) + done + AC_MSG_RESULT($attr_name) + if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then + AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name, + [Define to necessary symbol if this constant + uses a non-standard name on your system.]) + fi + + AC_MSG_CHECKING([if more special flags are required for pthreads]) + flag=no + case "${host_cpu}-${host_os}" in + *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";; + *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; + esac + AC_MSG_RESULT(${flag}) + if test "x$flag" != xno; then + PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" + fi + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + # More AIX lossage: must compile with xlc_r or cc_r + if test x"$GCC" != xyes; then + AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC}) + else + PTHREAD_CC=$CC + fi +else + PTHREAD_CC="$CC" +fi + +AC_SUBST(PTHREAD_LIBS) +AC_SUBST(PTHREAD_CFLAGS) +AC_SUBST(PTHREAD_CC) + +# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: +if test x"$acx_pthread_ok" = xyes; then + ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) + : +else + acx_pthread_ok=no + $2 +fi +AC_LANG_RESTORE +])dnl ACX_PTHREAD diff --git a/acx_python.m4 b/acx_python.m4 new file mode 100644 index 00000000000..6fa925af168 --- /dev/null +++ b/acx_python.m4 @@ -0,0 +1,200 @@ +AC_DEFUN([AC_PYTHON_DEVEL],[ + # + # Allow the use of a (user set) custom python version + # + AC_ARG_VAR([PYTHON_VERSION],[The installed Python + version to use, for example '2.3'. This string + will be appended to the Python interpreter + canonical name.]) + + AC_PATH_PROG([PYTHON],[python[$PYTHON_VERSION]]) + if test -z "$PYTHON"; then + AC_MSG_ERROR([Cannot find python$PYTHON_VERSION in your system path]) + PYTHON_VERSION="" + fi + + if test -z "$PYTHON_VERSION"; then + PYTHON_VERSION=`$PYTHON -c "import sys, string; \ + print string.split(sys.version)[[0]]"` + fi + + # + # Check for a version of Python >= 2.1.0 + # + AC_MSG_CHECKING([for a version of Python >= '2.1.0']) + ac_supports_python_ver=`$PYTHON -c "import sys, string; \ + ver = string.split(sys.version)[[0]]; \ + print ver >= '2.1.0'"` + if test "$ac_supports_python_ver" != "True"; then + if test -z "$PYTHON_NOVERSIONCHECK"; then + AC_MSG_RESULT([no]) + AC_MSG_FAILURE([ +This version of the AC@&t@_PYTHON_DEVEL macro +doesn't work properly with versions of Python before +2.1.0. You may need to re-run configure, setting the +variables PYTHON_CPPFLAGS, PYTHON_LDFLAGS, PYTHON_SITE_PKG, +PYTHON_EXTRA_LIBS and PYTHON_EXTRA_LDFLAGS by hand. +Moreover, to disable this check, set PYTHON_NOVERSIONCHECK +to something else than an empty string. +]) + else + AC_MSG_RESULT([skip at user request]) + fi + else + AC_MSG_RESULT([yes]) + fi + + # + # if the macro parameter ``version'' is set, honour it + # + if test -n "$1"; then + AC_MSG_CHECKING([for a version of Python $1]) + ac_supports_python_ver=`$PYTHON -c "import sys, string; \ + ver = string.split(sys.version)[[0]]; \ + print ver $1"` + if test "$ac_supports_python_ver" = "True"; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + AC_MSG_ERROR([this package requires Python $1. +If you have it installed, but it isn't the default Python +interpreter in your system path, please pass the PYTHON_VERSION +variable to configure. See ``configure --help'' for reference. +]) + PYTHON_VERSION="" + fi + fi + + # + # Check if you have distutils, else fail + # + AC_MSG_CHECKING([for the distutils Python package]) + ac_distutils_result=`$PYTHON -c "import distutils" 2>&1` + if test -z "$ac_distutils_result"; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + AC_MSG_ERROR([cannot import Python module "distutils". +Please check your Python installation. The error was: +$ac_distutils_result]) + PYTHON_VERSION="" + fi + + # + # Check for Python include path + # + AC_MSG_CHECKING([for Python include path]) + if test -z "$PYTHON_CPPFLAGS"; then + python_path=`$PYTHON -c "import distutils.sysconfig; \ + print distutils.sysconfig.get_python_inc();"` + if test -n "${python_path}"; then + python_path="-I$python_path" + fi + PYTHON_CPPFLAGS=$python_path + fi + AC_MSG_RESULT([$PYTHON_CPPFLAGS]) + AC_SUBST([PYTHON_CPPFLAGS]) + + # + # Check for Python library path + # + AC_MSG_CHECKING([for Python library path]) + if test -z "$PYTHON_LDFLAGS"; then + # (makes two attempts to ensure we've got a version number + # from the interpreter) + py_version=`$PYTHON -c "from distutils.sysconfig import *; \ + from string import join; \ + print join(get_config_vars('VERSION'))"` + if test "$py_version" = "[None]"; then + if test -n "$PYTHON_VERSION"; then + py_version=$PYTHON_VERSION + else + py_version=`$PYTHON -c "import sys; \ + print sys.version[[:3]]"` + fi + fi + + PYTHON_LDFLAGS=`$PYTHON -c "from distutils.sysconfig import *; \ + from string import join; \ + print '-L' + get_python_lib(0,1), \ + '-L' + os.path.dirname(get_python_lib(0,1)), \ + '-lpython';"`$py_version + fi + AC_MSG_RESULT([$PYTHON_LDFLAGS]) + AC_SUBST([PYTHON_LDFLAGS]) + + # + # Check for site packages + # + AC_MSG_CHECKING([for Python site-packages path]) + if test -z "$PYTHON_SITE_PKG"; then + PYTHON_SITE_PKG=`$PYTHON -c "import distutils.sysconfig; \ + print distutils.sysconfig.get_python_lib(1,0);"` + fi + AC_MSG_RESULT([$PYTHON_SITE_PKG]) + AC_SUBST([PYTHON_SITE_PKG]) + + # + # libraries which must be linked in when embedding + # + AC_MSG_CHECKING(python extra libraries) + if test -z "$PYTHON_EXTRA_LIBS"; then + PYTHON_EXTRA_LIBS=`$PYTHON -c "import distutils.sysconfig; \ + conf = distutils.sysconfig.get_config_var; \ + print conf('LOCALMODLIBS'), conf('LIBS')"` + fi + AC_MSG_RESULT([$PYTHON_EXTRA_LIBS]) + AC_SUBST(PYTHON_EXTRA_LIBS) + + # + # linking flags needed when embedding + # + AC_MSG_CHECKING(python extra linking flags) + if test -z "$PYTHON_EXTRA_LDFLAGS"; then + PYTHON_EXTRA_LDFLAGS=`$PYTHON -c "import distutils.sysconfig; \ + conf = distutils.sysconfig.get_config_var; \ + print conf('LINKFORSHARED')"` + fi + AC_MSG_RESULT([$PYTHON_EXTRA_LDFLAGS]) + AC_SUBST(PYTHON_EXTRA_LDFLAGS) + + # + # final check to see if everything compiles alright + # + AC_MSG_CHECKING([consistency of all components of python development environment]) + AC_LANG_PUSH([C]) + # save current global flags + LIBS="$ac_save_LIBS $PYTHON_LDFLAGS" + CPPFLAGS="$ac_save_CPPFLAGS $PYTHON_CPPFLAGS" + AC_TRY_LINK([ + #include + ],[ + Py_Initialize(); + ],[pythonexists=yes],[pythonexists=no]) + + AC_MSG_RESULT([$pythonexists]) + + if test ! "$pythonexists" = "yes"; then + AC_MSG_ERROR([ + Could not link test program to Python. Maybe the main Python library has been + installed in some non-standard library path. If so, pass it to configure, + via the LDFLAGS environment variable. + Example: ./configure LDFLAGS="-L/usr/non-standard-path/python/lib" + ============================================================================ + ERROR! + You probably have to install the development version of the Python package + for your distribution. The exact name of this package varies among them. + ============================================================================ + ]) + PYTHON_VERSION="" + fi + AC_LANG_POP + # turn back to default flags + CPPFLAGS="$ac_save_CPPFLAGS" + LIBS="$ac_save_LIBS" + + # + # all done! + # +]) + diff --git a/compat/ctime_r.c b/compat/ctime_r.c new file mode 100644 index 00000000000..2594dc17e76 --- /dev/null +++ b/compat/ctime_r.c @@ -0,0 +1,42 @@ +/* taken from ldns 1.6.1 */ +#include "config.h" +#ifdef HAVE_TIME_H +#include +#endif +#include "util/locks.h" + +/** the lock for ctime buffer */ +static lock_basic_t ctime_lock; +/** has it been inited */ +static int ctime_r_init = 0; + +/** cleanup ctime_r on exit */ +static void +ctime_r_cleanup(void) +{ + if(ctime_r_init) { + ctime_r_init = 0; + lock_basic_destroy(&ctime_lock); + } +} + +char *ctime_r(const time_t *timep, char *buf) +{ + char* result; + if(!ctime_r_init) { + /* still small race where this init can be done twice, + * which is mostly harmless */ + ctime_r_init = 1; + lock_basic_init(&ctime_lock); + atexit(&ctime_r_cleanup); + } + lock_basic_lock(&ctime_lock); + result = ctime(timep); + if(buf && result) { + if(strlen(result) > 10 && result[7]==' ' && result[8]=='0') + result[8]=' '; /* fix error in windows ctime */ + strcpy(buf, result); + } + lock_basic_unlock(&ctime_lock); + return result; +} diff --git a/compat/fake-rfc2553.c b/compat/fake-rfc2553.c new file mode 100644 index 00000000000..91ddf8a809b --- /dev/null +++ b/compat/fake-rfc2553.c @@ -0,0 +1,227 @@ +/* From openssh 4.3p2 filename openbsd-compat/fake-rfc2553.h */ +/* + * Copyright (C) 2000-2003 Damien Miller. All rights reserved. + * Copyright (C) 1999 WIDE Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Pseudo-implementation of RFC2553 name / address resolution functions + * + * But these functions are not implemented correctly. The minimum subset + * is implemented for ssh use only. For example, this routine assumes + * that ai_family is AF_INET. Don't use it for another purpose. + */ + +#include +#include +#include +#include +#include "compat/fake-rfc2553.h" + +#ifndef HAVE_GETNAMEINFO +int getnameinfo(const struct sockaddr *sa, size_t ATTR_UNUSED(salen), char *host, + size_t hostlen, char *serv, size_t servlen, int flags) +{ + struct sockaddr_in *sin = (struct sockaddr_in *)sa; + struct hostent *hp; + char tmpserv[16]; + + if (serv != NULL) { + snprintf(tmpserv, sizeof(tmpserv), "%d", ntohs(sin->sin_port)); + if (strlcpy(serv, tmpserv, servlen) >= servlen) + return (EAI_MEMORY); + } + + if (host != NULL) { + if (flags & NI_NUMERICHOST) { + if (strlcpy(host, inet_ntoa(sin->sin_addr), + hostlen) >= hostlen) + return (EAI_MEMORY); + else + return (0); + } else { + hp = gethostbyaddr((char *)&sin->sin_addr, + sizeof(struct in_addr), AF_INET); + if (hp == NULL) + return (EAI_NODATA); + + if (strlcpy(host, hp->h_name, hostlen) >= hostlen) + return (EAI_MEMORY); + else + return (0); + } + } + return (0); +} +#endif /* !HAVE_GETNAMEINFO */ + +#ifndef HAVE_GAI_STRERROR +#ifdef HAVE_CONST_GAI_STRERROR_PROTO +const char * +#else +char * +#endif +gai_strerror(int err) +{ + switch (err) { + case EAI_NODATA: + return ("no address associated with name"); + case EAI_MEMORY: + return ("memory allocation failure."); + case EAI_NONAME: + return ("nodename nor servname provided, or not known"); + default: + return ("unknown/invalid error."); + } +} +#endif /* !HAVE_GAI_STRERROR */ + +#ifndef HAVE_FREEADDRINFO +void +freeaddrinfo(struct addrinfo *ai) +{ + struct addrinfo *next; + + for(; ai != NULL;) { + next = ai->ai_next; + free(ai); + ai = next; + } +} +#endif /* !HAVE_FREEADDRINFO */ + +#ifndef HAVE_GETADDRINFO +static struct +addrinfo *malloc_ai(int port, u_long addr, const struct addrinfo *hints) +{ + struct addrinfo *ai; + + ai = malloc(sizeof(*ai) + sizeof(struct sockaddr_in)); + if (ai == NULL) + return (NULL); + + memset(ai, '\0', sizeof(*ai) + sizeof(struct sockaddr_in)); + + ai->ai_addr = (struct sockaddr *)(ai + 1); + /* XXX -- ssh doesn't use sa_len */ + ai->ai_addrlen = sizeof(struct sockaddr_in); + ai->ai_addr->sa_family = ai->ai_family = AF_INET; + + ((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port; + ((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr; + + /* XXX: the following is not generally correct, but does what we want */ + if (hints->ai_socktype) + ai->ai_socktype = hints->ai_socktype; + else + ai->ai_socktype = SOCK_STREAM; + + if (hints->ai_protocol) + ai->ai_protocol = hints->ai_protocol; + + return (ai); +} + +int +getaddrinfo(const char *hostname, const char *servname, + const struct addrinfo *hints, struct addrinfo **res) +{ + struct hostent *hp; + struct servent *sp; + struct in_addr in; + int i; + long int port; + u_long addr; + + port = 0; + if (servname != NULL) { + char *cp; + + port = strtol(servname, &cp, 10); + if (port > 0 && port <= 65535 && *cp == '\0') + port = htons(port); + else if ((sp = getservbyname(servname, NULL)) != NULL) + port = sp->s_port; + else + port = 0; + } + + if (hints && hints->ai_flags & AI_PASSIVE) { + addr = htonl(0x00000000); + if (hostname && inet_aton(hostname, &in) != 0) + addr = in.s_addr; + *res = malloc_ai(port, addr, hints); + if (*res == NULL) + return (EAI_MEMORY); + return (0); + } + + if (!hostname) { + *res = malloc_ai(port, htonl(0x7f000001), hints); + if (*res == NULL) + return (EAI_MEMORY); + return (0); + } + + if (inet_aton(hostname, &in)) { + *res = malloc_ai(port, in.s_addr, hints); + if (*res == NULL) + return (EAI_MEMORY); + return (0); + } + + /* Don't try DNS if AI_NUMERICHOST is set */ + if (hints && hints->ai_flags & AI_NUMERICHOST) + return (EAI_NONAME); + + hp = gethostbyname(hostname); + if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) { + struct addrinfo *cur, *prev; + + cur = prev = *res = NULL; + for (i = 0; hp->h_addr_list[i]; i++) { + struct in_addr *in = (struct in_addr *)hp->h_addr_list[i]; + + cur = malloc_ai(port, in->s_addr, hints); + if (cur == NULL) { + if (*res != NULL) + freeaddrinfo(*res); + return (EAI_MEMORY); + } + if (prev) + prev->ai_next = cur; + else + *res = cur; + + prev = cur; + } + return (0); + } + + return (EAI_NODATA); +} +#endif /* !HAVE_GETADDRINFO */ diff --git a/compat/fake-rfc2553.h b/compat/fake-rfc2553.h new file mode 100644 index 00000000000..466c0e663dd --- /dev/null +++ b/compat/fake-rfc2553.h @@ -0,0 +1,174 @@ +/* From openssh 4.3p2 filename openbsd-compat/fake-rfc2553.h */ +/* + * Copyright (C) 2000-2003 Damien Miller. All rights reserved. + * Copyright (C) 1999 WIDE Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Pseudo-implementation of RFC2553 name / address resolution functions + * + * But these functions are not implemented correctly. The minimum subset + * is implemented for ssh use only. For example, this routine assumes + * that ai_family is AF_INET. Don't use it for another purpose. + */ + +#ifndef _FAKE_RFC2553_H +#define _FAKE_RFC2553_H + +#include +#include +#include +#include +#include + +/* + * First, socket and INET6 related definitions + */ +#ifndef HAVE_STRUCT_SOCKADDR_STORAGE +# define _SS_MAXSIZE 128 /* Implementation specific max size */ +# define _SS_PADSIZE (_SS_MAXSIZE - sizeof (struct sockaddr)) +struct sockaddr_storage { + struct sockaddr ss_sa; + char __ss_pad2[_SS_PADSIZE]; +}; +# define ss_family ss_sa.sa_family +#endif /* !HAVE_STRUCT_SOCKADDR_STORAGE */ + +#ifndef IN6_IS_ADDR_LOOPBACK +# define IN6_IS_ADDR_LOOPBACK(a) \ + (((uint32_t *)(a))[0] == 0 && ((uint32_t *)(a))[1] == 0 && \ + ((uint32_t *)(a))[2] == 0 && ((uint32_t *)(a))[3] == htonl(1)) +#endif /* !IN6_IS_ADDR_LOOPBACK */ + +#ifndef HAVE_STRUCT_IN6_ADDR +struct in6_addr { + uint8_t s6_addr[16]; +}; +#endif /* !HAVE_STRUCT_IN6_ADDR */ + +#ifndef HAVE_STRUCT_SOCKADDR_IN6 +struct sockaddr_in6 { + unsigned short sin6_family; + uint16_t sin6_port; + uint32_t sin6_flowinfo; + struct in6_addr sin6_addr; +}; +#endif /* !HAVE_STRUCT_SOCKADDR_IN6 */ + +#ifndef AF_INET6 +/* Define it to something that should never appear */ +#define AF_INET6 AF_MAX +#endif + +/* + * Next, RFC2553 name / address resolution API + */ + +#ifndef NI_NUMERICHOST +# define NI_NUMERICHOST (1) +#endif +#ifndef NI_NAMEREQD +# define NI_NAMEREQD (1<<1) +#endif +#ifndef NI_NUMERICSERV +# define NI_NUMERICSERV (1<<2) +#endif + +#ifndef AI_PASSIVE +# define AI_PASSIVE (1) +#endif +#ifndef AI_CANONNAME +# define AI_CANONNAME (1<<1) +#endif +#ifndef AI_NUMERICHOST +# define AI_NUMERICHOST (1<<2) +#endif + +#ifndef NI_MAXSERV +# define NI_MAXSERV 32 +#endif /* !NI_MAXSERV */ +#ifndef NI_MAXHOST +# define NI_MAXHOST 1025 +#endif /* !NI_MAXHOST */ + +#ifndef INT_MAX +#define INT_MAX 0xffffffff +#endif + +#ifndef EAI_NODATA +# define EAI_NODATA (INT_MAX - 1) +#endif +#ifndef EAI_MEMORY +# define EAI_MEMORY (INT_MAX - 2) +#endif +#ifndef EAI_NONAME +# define EAI_NONAME (INT_MAX - 3) +#endif +#ifndef EAI_SYSTEM +# define EAI_SYSTEM (INT_MAX - 4) +#endif + +#ifndef HAVE_STRUCT_ADDRINFO +struct addrinfo { + int ai_flags; /* AI_PASSIVE, AI_CANONNAME */ + int ai_family; /* PF_xxx */ + int ai_socktype; /* SOCK_xxx */ + int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ + size_t ai_addrlen; /* length of ai_addr */ + char *ai_canonname; /* canonical name for hostname */ + struct sockaddr *ai_addr; /* binary address */ + struct addrinfo *ai_next; /* next structure in linked list */ +}; +#endif /* !HAVE_STRUCT_ADDRINFO */ + +#ifndef HAVE_GETADDRINFO +#ifdef getaddrinfo +# undef getaddrinfo +#endif +#define getaddrinfo(a,b,c,d) (getaddrinfo_unbound(a,b,c,d)) +int getaddrinfo(const char *, const char *, + const struct addrinfo *, struct addrinfo **); +#endif /* !HAVE_GETADDRINFO */ + +#if !defined(HAVE_GAI_STRERROR) && !defined(HAVE_CONST_GAI_STRERROR_PROTO) +#define gai_strerror(a) (gai_strerror_unbound(a)) +char *gai_strerror(int); +#endif /* !HAVE_GAI_STRERROR */ + +#ifndef HAVE_FREEADDRINFO +#define freeaddrinfo(a) (freeaddrinfo_unbound(a)) +void freeaddrinfo(struct addrinfo *); +#endif /* !HAVE_FREEADDRINFO */ + +#ifndef HAVE_GETNAMEINFO +#define getnameinfo(a,b,c,d,e,f,g) (getnameinfo_unbound(a,b,c,d,e,f,g)) +int getnameinfo(const struct sockaddr *, size_t, char *, size_t, + char *, size_t, int); +#endif /* !HAVE_GETNAMEINFO */ + +#endif /* !_FAKE_RFC2553_H */ + diff --git a/compat/gmtime_r.c b/compat/gmtime_r.c new file mode 100644 index 00000000000..19eb637e3c9 --- /dev/null +++ b/compat/gmtime_r.c @@ -0,0 +1,107 @@ +/* + * Taken from FreeBSD src / lib / libc / stdtime / localtime.c 1.43 revision. + * localtime.c 7.78. + * tzfile.h 1.8 + * adapted to be replacement gmtime_r. + */ +#include "config.h" + +#ifdef HAVE_TIME_H +#include +#endif + +#define MONSPERYEAR 12 +#define DAYSPERNYEAR 365 +#define DAYSPERLYEAR 366 +#define SECSPERMIN 60 +#define SECSPERHOUR (60*60) +#define SECSPERDAY (24*60*60) +#define DAYSPERWEEK 7 +#define TM_SUNDAY 0 +#define TM_MONDAY 1 +#define TM_TUESDAY 2 +#define TM_WEDNESDAY 3 +#define TM_THURSDAY 4 +#define TM_FRIDAY 5 +#define TM_SATURDAY 6 + +#define TM_YEAR_BASE 1900 + +#define EPOCH_YEAR 1970 +#define EPOCH_WDAY TM_THURSDAY + +#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0)) + +static const int mon_lengths[2][MONSPERYEAR] = { + { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, + { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } +}; + +static const int year_lengths[2] = { + DAYSPERNYEAR, DAYSPERLYEAR +}; + +static void +timesub(timep, offset, tmp) +const time_t * const timep; +const long offset; +struct tm * const tmp; +{ + long days; + long rem; + long y; + int yleap; + const int * ip; + + days = *timep / SECSPERDAY; + rem = *timep % SECSPERDAY; + rem += (offset); + while (rem < 0) { + rem += SECSPERDAY; + --days; + } + while (rem >= SECSPERDAY) { + rem -= SECSPERDAY; + ++days; + } + tmp->tm_hour = (int) (rem / SECSPERHOUR); + rem = rem % SECSPERHOUR; + tmp->tm_min = (int) (rem / SECSPERMIN); + /* + ** A positive leap second requires a special + ** representation. This uses "... ??:59:60" et seq. + */ + tmp->tm_sec = (int) (rem % SECSPERMIN) ; + tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK); + if (tmp->tm_wday < 0) + tmp->tm_wday += DAYSPERWEEK; + y = EPOCH_YEAR; +#define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400) + while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) { + long newy; + + newy = y + days / DAYSPERNYEAR; + if (days < 0) + --newy; + days -= (newy - y) * DAYSPERNYEAR + + LEAPS_THRU_END_OF(newy - 1) - + LEAPS_THRU_END_OF(y - 1); + y = newy; + } + tmp->tm_year = y - TM_YEAR_BASE; + tmp->tm_yday = (int) days; + ip = mon_lengths[yleap]; + for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon)) + days = days - (long) ip[tmp->tm_mon]; + tmp->tm_mday = (int) (days + 1); + tmp->tm_isdst = 0; +} + +/* +* Re-entrant version of gmtime. +*/ +struct tm * gmtime_r(const time_t* timep, struct tm *tm) +{ + timesub(timep, 0L, tm); + return tm; +} diff --git a/compat/inet_aton.c b/compat/inet_aton.c new file mode 100644 index 00000000000..33c323d9986 --- /dev/null +++ b/compat/inet_aton.c @@ -0,0 +1,182 @@ +/* From openssh4.3p2 compat/inet_aton.c */ +/* + * Copyright (c) 1983, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * - + * Portions Copyright (c) 1993 by Digital Equipment Corporation. + * + * 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, and that + * the name of Digital Equipment Corporation not be used in advertising or + * publicity pertaining to distribution of the document or software without + * specific, written prior permission. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION 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. + * - + * --Copyright-- + */ + +/* OPENBSD ORIGINAL: lib/libc/net/inet_addr.c */ + +#include + +#if !defined(HAVE_INET_ATON) + +#include +#include +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#include + +#if 0 +/* + * Ascii internet address interpretation routine. + * The value returned is in network order. + */ +in_addr_t +inet_addr(const char *cp) +{ + struct in_addr val; + + if (inet_aton(cp, &val)) + return (val.s_addr); + return (INADDR_NONE); +} +#endif + +/* + * Check whether "cp" is a valid ascii representation + * of an Internet address and convert to a binary address. + * Returns 1 if the address is valid, 0 if not. + * This replaces inet_addr, the return value from which + * cannot distinguish between failure and a local broadcast address. + */ +int +inet_aton(const char *cp, struct in_addr *addr) +{ + uint32_t val; + int base, n; + char c; + unsigned int parts[4]; + unsigned int *pp = parts; + + c = *cp; + for (;;) { + /* + * Collect number up to ``.''. + * Values are specified as for C: + * 0x=hex, 0=octal, isdigit=decimal. + */ + if (!isdigit(c)) + return (0); + val = 0; base = 10; + if (c == '0') { + c = *++cp; + if (c == 'x' || c == 'X') + base = 16, c = *++cp; + else + base = 8; + } + for (;;) { + if (isascii(c) && isdigit(c)) { + val = (val * base) + (c - '0'); + c = *++cp; + } else if (base == 16 && isascii(c) && isxdigit(c)) { + val = (val << 4) | + (c + 10 - (islower(c) ? 'a' : 'A')); + c = *++cp; + } else + break; + } + if (c == '.') { + /* + * Internet format: + * a.b.c.d + * a.b.c (with c treated as 16 bits) + * a.b (with b treated as 24 bits) + */ + if (pp >= parts + 3) + return (0); + *pp++ = val; + c = *++cp; + } else + break; + } + /* + * Check for trailing characters. + */ + if (c != '\0' && (!isascii(c) || !isspace(c))) + return (0); + /* + * Concoct the address according to + * the number of parts specified. + */ + n = pp - parts + 1; + switch (n) { + + case 0: + return (0); /* initial nondigit */ + + case 1: /* a -- 32 bits */ + break; + + case 2: /* a.b -- 8.24 bits */ + if ((val > 0xffffff) || (parts[0] > 0xff)) + return (0); + val |= parts[0] << 24; + break; + + case 3: /* a.b.c -- 8.8.16 bits */ + if ((val > 0xffff) || (parts[0] > 0xff) || (parts[1] > 0xff)) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16); + break; + + case 4: /* a.b.c.d -- 8.8.8.8 bits */ + if ((val > 0xff) || (parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff)) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); + break; + } + if (addr) + addr->s_addr = htonl(val); + return (1); +} + +#endif /* !defined(HAVE_INET_ATON) */ diff --git a/compat/inet_ntop.c b/compat/inet_ntop.c new file mode 100644 index 00000000000..bd418ae7ddf --- /dev/null +++ b/compat/inet_ntop.c @@ -0,0 +1,218 @@ +/* From openssh 4.3p2 compat/inet_ntop.c */ +/* Copyright (c) 1996 by Internet Software Consortium. + * + * 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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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. + */ + +/* OPENBSD ORIGINAL: lib/libc/net/inet_ntop.c */ + +#include + +#ifndef HAVE_INET_NTOP + +#include +#include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#include +#include +#include + +#ifndef IN6ADDRSZ +#define IN6ADDRSZ 16 /* IPv6 T_AAAA */ +#endif + +#ifndef INT16SZ +#define INT16SZ 2 /* for systems without 16-bit ints */ +#endif + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + +static const char *inet_ntop4(const u_char *src, char *dst, size_t size); +static const char *inet_ntop6(const u_char *src, char *dst, size_t size); + +/* char * + * inet_ntop(af, src, dst, size) + * convert a network format address to presentation format. + * return: + * pointer to presentation format address (`dst'), or NULL (see errno). + * author: + * Paul Vixie, 1996. + */ +const char * +inet_ntop(int af, const void *src, char *dst, size_t size) +{ + switch (af) { + case AF_INET: + return (inet_ntop4(src, dst, size)); + case AF_INET6: + return (inet_ntop6(src, dst, size)); + default: +#ifdef EAFNOSUPPORT + errno = EAFNOSUPPORT; +#else + errno = ENOSYS; +#endif + return (NULL); + } + /* NOTREACHED */ +} + +/* const char * + * inet_ntop4(src, dst, size) + * format an IPv4 address, more or less like inet_ntoa() + * return: + * `dst' (as a const) + * notes: + * (1) uses no statics + * (2) takes a u_char* not an in_addr as input + * author: + * Paul Vixie, 1996. + */ +static const char * +inet_ntop4(const u_char *src, char *dst, size_t size) +{ + static const char fmt[] = "%u.%u.%u.%u"; + char tmp[sizeof "255.255.255.255"]; + int l; + + l = snprintf(tmp, size, fmt, src[0], src[1], src[2], src[3]); + if (l <= 0 || l >= (int)size) { + errno = ENOSPC; + return (NULL); + } + strlcpy(dst, tmp, size); + return (dst); +} + +/* const char * + * inet_ntop6(src, dst, size) + * convert IPv6 binary address into presentation (printable) format + * author: + * Paul Vixie, 1996. + */ +static const char * +inet_ntop6(const u_char *src, char *dst, size_t size) +{ + /* + * Note that int32_t and int16_t need only be "at least" large enough + * to contain a value of the specified size. On some systems, like + * Crays, there is no such thing as an integer variable with 16 bits. + * Keep this in mind if you think this function should have been coded + * to use pointer overlays. All the world's not a VAX. + */ + char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; + char *tp, *ep; + struct { int base, len; } best, cur; + u_int words[IN6ADDRSZ / INT16SZ]; + int i; + int advance; + + /* + * Preprocess: + * Copy the input (bytewise) array into a wordwise array. + * Find the longest run of 0x00's in src[] for :: shorthanding. + */ + memset(words, '\0', sizeof words); + for (i = 0; i < IN6ADDRSZ; i++) + words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); + best.base = -1; + best.len = 0; + cur.base = -1; + cur.len = 0; + for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { + if (words[i] == 0) { + if (cur.base == -1) + cur.base = i, cur.len = 1; + else + cur.len++; + } else { + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + cur.base = -1; + } + } + } + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + } + if (best.base != -1 && best.len < 2) + best.base = -1; + + /* + * Format the result. + */ + tp = tmp; + ep = tmp + sizeof(tmp); + for (i = 0; i < (IN6ADDRSZ / INT16SZ) && tp < ep; i++) { + /* Are we inside the best run of 0x00's? */ + if (best.base != -1 && i >= best.base && + i < (best.base + best.len)) { + if (i == best.base) { + if (tp + 1 >= ep) + return (NULL); + *tp++ = ':'; + } + continue; + } + /* Are we following an initial run of 0x00s or any real hex? */ + if (i != 0) { + if (tp + 1 >= ep) + return (NULL); + *tp++ = ':'; + } + /* Is this address an encapsulated IPv4? */ + if (i == 6 && best.base == 0 && + (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { + if (!inet_ntop4(src+12, tp, (size_t)(ep - tp))) + return (NULL); + tp += strlen(tp); + break; + } + advance = snprintf(tp, ep - tp, "%x", words[i]); + if (advance <= 0 || advance >= ep - tp) + return (NULL); + tp += advance; + } + /* Was it a trailing run of 0x00's? */ + if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) { + if (tp + 1 >= ep) + return (NULL); + *tp++ = ':'; + } + if (tp + 1 >= ep) + return (NULL); + *tp++ = '\0'; + + /* + * Check for overflow, copy, and we're done. + */ + if ((size_t)(tp - tmp) > size) { + errno = ENOSPC; + return (NULL); + } + strlcpy(dst, tmp, size); + return (dst); +} + +#endif /* !HAVE_INET_NTOP */ diff --git a/compat/inet_pton.c b/compat/inet_pton.c new file mode 100644 index 00000000000..15780d0b7a1 --- /dev/null +++ b/compat/inet_pton.c @@ -0,0 +1,230 @@ +/* $KAME: inet_pton.c,v 1.5 2001/08/20 02:32:40 itojun Exp $ */ + +/* Copyright (c) 1996 by Internet Software Consortium. + * + * 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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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. + */ + +#include + +#include +#include +#include + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + +static int inet_pton4 (const char *src, uint8_t *dst); +static int inet_pton6 (const char *src, uint8_t *dst); + +/* + * + * The definitions we might miss. + * + */ +#ifndef NS_INT16SZ +#define NS_INT16SZ 2 +#endif + +#ifndef NS_IN6ADDRSZ +#define NS_IN6ADDRSZ 16 +#endif + +#ifndef NS_INADDRSZ +#define NS_INADDRSZ 4 +#endif + +/* int + * inet_pton(af, src, dst) + * convert from presentation format (which usually means ASCII printable) + * to network format (which is usually some kind of binary format). + * return: + * 1 if the address was valid for the specified address family + * 0 if the address wasn't valid (`dst' is untouched in this case) + * -1 if some other error occurred (`dst' is untouched in this case, too) + * author: + * Paul Vixie, 1996. + */ +int +inet_pton(af, src, dst) + int af; + const char *src; + void *dst; +{ + switch (af) { + case AF_INET: + return (inet_pton4(src, dst)); + case AF_INET6: + return (inet_pton6(src, dst)); + default: +#ifdef EAFNOSUPPORT + errno = EAFNOSUPPORT; +#else + errno = ENOSYS; +#endif + return (-1); + } + /* NOTREACHED */ +} + +/* int + * inet_pton4(src, dst) + * like inet_aton() but without all the hexadecimal and shorthand. + * return: + * 1 if `src' is a valid dotted quad, else 0. + * notice: + * does not touch `dst' unless it's returning 1. + * author: + * Paul Vixie, 1996. + */ +static int +inet_pton4(src, dst) + const char *src; + uint8_t *dst; +{ + static const char digits[] = "0123456789"; + int saw_digit, octets, ch; + uint8_t tmp[NS_INADDRSZ], *tp; + + saw_digit = 0; + octets = 0; + *(tp = tmp) = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + if ((pch = strchr(digits, ch)) != NULL) { + uint32_t new = *tp * 10 + (pch - digits); + + if (new > 255) + return (0); + *tp = new; + if (! saw_digit) { + if (++octets > 4) + return (0); + saw_digit = 1; + } + } else if (ch == '.' && saw_digit) { + if (octets == 4) + return (0); + *++tp = 0; + saw_digit = 0; + } else + return (0); + } + if (octets < 4) + return (0); + + memcpy(dst, tmp, NS_INADDRSZ); + return (1); +} + +/* int + * inet_pton6(src, dst) + * convert presentation level address to network order binary form. + * return: + * 1 if `src' is a valid [RFC1884 2.2] address, else 0. + * notice: + * (1) does not touch `dst' unless it's returning 1. + * (2) :: in a full address is silently ignored. + * credit: + * inspired by Mark Andrews. + * author: + * Paul Vixie, 1996. + */ +static int +inet_pton6(src, dst) + const char *src; + uint8_t *dst; +{ + static const char xdigits_l[] = "0123456789abcdef", + xdigits_u[] = "0123456789ABCDEF"; + uint8_t tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; + const char *xdigits, *curtok; + int ch, saw_xdigit; + uint32_t val; + + memset((tp = tmp), '\0', NS_IN6ADDRSZ); + endp = tp + NS_IN6ADDRSZ; + colonp = NULL; + /* Leading :: requires some special handling. */ + if (*src == ':') + if (*++src != ':') + return (0); + curtok = src; + saw_xdigit = 0; + val = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) + pch = strchr((xdigits = xdigits_u), ch); + if (pch != NULL) { + val <<= 4; + val |= (pch - xdigits); + if (val > 0xffff) + return (0); + saw_xdigit = 1; + continue; + } + if (ch == ':') { + curtok = src; + if (!saw_xdigit) { + if (colonp) + return (0); + colonp = tp; + continue; + } + if (tp + NS_INT16SZ > endp) + return (0); + *tp++ = (uint8_t) (val >> 8) & 0xff; + *tp++ = (uint8_t) val & 0xff; + saw_xdigit = 0; + val = 0; + continue; + } + if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && + inet_pton4(curtok, tp) > 0) { + tp += NS_INADDRSZ; + saw_xdigit = 0; + break; /* '\0' was seen by inet_pton4(). */ + } + return (0); + } + if (saw_xdigit) { + if (tp + NS_INT16SZ > endp) + return (0); + *tp++ = (uint8_t) (val >> 8) & 0xff; + *tp++ = (uint8_t) val & 0xff; + } + if (colonp != NULL) { + /* + * Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + const int n = tp - colonp; + int i; + + for (i = 1; i <= n; i++) { + endp[- i] = colonp[n - i]; + colonp[n - i] = 0; + } + tp = endp; + } + if (tp != endp) + return (0); + memcpy(dst, tmp, NS_IN6ADDRSZ); + return (1); +} diff --git a/compat/malloc.c b/compat/malloc.c new file mode 100644 index 00000000000..559aa100dd2 --- /dev/null +++ b/compat/malloc.c @@ -0,0 +1,19 @@ +/* Just a replacement, if the original malloc is not + GNU-compliant. See autoconf documentation. */ + +#include "config.h" +#undef malloc +#include + +void *malloc (); + +/* Allocate an N-byte block of memory from the heap. + If N is zero, allocate a 1-byte block. */ + +void * +rpl_malloc_unbound (size_t n) +{ + if (n == 0) + n = 1; + return malloc (n); +} diff --git a/compat/memcmp.c b/compat/memcmp.c new file mode 100644 index 00000000000..9446276f410 --- /dev/null +++ b/compat/memcmp.c @@ -0,0 +1,25 @@ +/* + * memcmp.c: memcmp compat implementation. + * + * Copyright (c) 2010, NLnet Labs. All rights reserved. + * + * See LICENSE for the license. +*/ + +#include + +int memcmp(const void *x, const void *y, size_t n); + +int memcmp(const void *x, const void *y, size_t n) +{ + const uint8_t* x8 = (const uint8_t*)x; + const uint8_t* y8 = (const uint8_t*)y; + size_t i; + for(i=0; i y8[i]) + return 1; + } + return 0; +} diff --git a/compat/memcmp.h b/compat/memcmp.h new file mode 100644 index 00000000000..c1d195ccf4a --- /dev/null +++ b/compat/memcmp.h @@ -0,0 +1,16 @@ +/* + * memcmp.h: undef memcmp for compat. + * + * Copyright (c) 2012, NLnet Labs. All rights reserved. + * + * See LICENSE for the license. +*/ +#ifndef COMPAT_MEMCMP_H +#define COMPAT_MEMCMP_H + +#ifdef memcmp +/* undef here otherwise autoheader messes it up in config.h */ +# undef memcmp +#endif + +#endif /* COMPAT_MEMCMP_H */ diff --git a/compat/memmove.c b/compat/memmove.c new file mode 100644 index 00000000000..0035bbf7533 --- /dev/null +++ b/compat/memmove.c @@ -0,0 +1,43 @@ +/* + * memmove.c: memmove compat implementation. + * + * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. + * + * See LICENSE for the license. +*/ + +#include +#include + +void *memmove(void *dest, const void *src, size_t n); + +void *memmove(void *dest, const void *src, size_t n) +{ + uint8_t* from = (uint8_t*) src; + uint8_t* to = (uint8_t*) dest; + + if (from == to || n == 0) + return dest; + if (to > from && to-from < (int)n) { + /* to overlaps with from */ + /* */ + /* */ + /* copy in reverse, to avoid overwriting from */ + int i; + for(i=n-1; i>=0; i--) + to[i] = from[i]; + return dest; + } + if (from > to && from-to < (int)n) { + /* to overlaps with from */ + /* */ + /* */ + /* copy forwards, to avoid overwriting from */ + size_t i; + for(i=0; i + +#ifndef HAVE_SNPRINTF + +#include +#include + +/* Define this as a fall through, HAVE_STDARG_H is probably already set */ + +#define HAVE_VARARGS_H + +/************************************************************** + * Original: + * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 + * A bombproof version of doprnt (dopr) included. + * Sigh. This sort of thing is always nasty do deal with. Note that + * the version here does not include floating point... + * + * snprintf() is used instead of sprintf() as it does limit checks + * for string length. This covers a nasty loophole. + * + * The other functions are there to prevent NULL pointers from + * causing nast effects. + * + * More Recently: + * Brandon Long (blong@fiction.net) 9/15/96 for mutt 0.43 + * This was ugly. It is still ugly. I opted out of floating point + * numbers, but the formatter understands just about everything + * from the normal C string format, at least as far as I can tell from + * the Solaris 2.5 printf(3S) man page. + * + * Brandon Long (blong@fiction.net) 10/22/97 for mutt 0.87.1 + * Ok, added some minimal floating point support, which means this + * probably requires libm on most operating systems. Don't yet + * support the exponent (e,E) and sigfig (g,G). Also, fmtint() + * was pretty badly broken, it just wasn't being exercised in ways + * which showed it, so that's been fixed. Also, formated the code + * to mutt conventions, and removed dead code left over from the + * original. Also, there is now a builtin-test, just compile with: + * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm + * and run snprintf for results. + * + * Wouter Wijngaards(wouter@nlnetlabs.nl) 2/09/2010 for unbound. + * Limited support for %g. Does not do the exponents for the before-dot. + * + **************************************************************/ + + +/* varargs declarations: */ + +#if defined(HAVE_STDARG_H) +# include +# define HAVE_STDARGS /* let's hope that works everywhere (mj) */ +# define VA_LOCAL_DECL va_list ap +# define VA_START(f) va_start(ap, f) +# define VA_SHIFT(v,t) ; /* no-op for ANSI */ +# define VA_END va_end(ap) +#else +# if defined(HAVE_VARARGS_H) +# include +# undef HAVE_STDARGS +# define VA_LOCAL_DECL va_list ap +# define VA_START(f) va_start(ap) /* f is ignored! */ +# define VA_SHIFT(v,t) v = va_arg(ap,t) +# define VA_END va_end(ap) +# else +/*XX ** NO VARARGS ** XX*/ +# endif +#endif + +int snprintf (char *str, size_t count, const char *fmt, ...); +int vsnprintf (char *str, size_t count, const char *fmt, va_list arg); + +static void dopr (char *buffer, size_t maxlen, const char *format, + va_list args); +static void fmtstr (char *buffer, size_t *currlen, size_t maxlen, + char *value, int flags, int min, int max); +static void fmtint (char *buffer, size_t *currlen, size_t maxlen, + long value, int base, int min, int max, int flags); +static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, + long double fvalue, int min, int max, int flags, int conv); +static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c ); + +int vsnprintf (char *str, size_t count, const char *fmt, va_list args) +{ + str[0] = 0; + dopr(str, count, fmt, args); + return(strlen(str)); +} + +/* VARARGS3 */ +#ifdef HAVE_STDARGS +int snprintf (char *str,size_t count,const char *fmt,...) +#else +int snprintf (va_alist) va_dcl +#endif +{ +#ifndef HAVE_STDARGS + char *str; + size_t count; + char *fmt; +#endif + VA_LOCAL_DECL; + + VA_START (fmt); + VA_SHIFT (str, char *); + VA_SHIFT (count, size_t ); + VA_SHIFT (fmt, char *); + (void) vsnprintf(str, count, fmt, ap); + VA_END; + return(strlen(str)); +} + +/* + * dopr(): poor man's version of doprintf + */ + +/* format read states */ +#define DP_S_DEFAULT 0 +#define DP_S_FLAGS 1 +#define DP_S_MIN 2 +#define DP_S_DOT 3 +#define DP_S_MAX 4 +#define DP_S_MOD 5 +#define DP_S_CONV 6 +#define DP_S_DONE 7 + +/* format flags - Bits */ +#define DP_F_MINUS 1 +#define DP_F_PLUS 2 +#define DP_F_SPACE 4 +#define DP_F_NUM 8 +#define DP_F_ZERO 16 +#define DP_F_UP 32 + +/* Conversion Flags */ +#define DP_C_SHORT 1 +#define DP_C_LONG 2 +#define DP_C_LDOUBLE 3 + +#define char_to_int(p) (p - '0') +#ifndef MAX +#define MAX(p,q) ((p >= q) ? p : q) +#endif + +static void dopr (char *buffer, size_t maxlen, const char *format, va_list args) +{ + char ch; + long value; + long double fvalue; + char *strvalue; + int min; + int max; + int state; + int flags; + int cflags; + size_t currlen; + + state = DP_S_DEFAULT; + currlen = flags = cflags = min = 0; + max = -1; + ch = *format++; + + while (state != DP_S_DONE) + { + if ((ch == '\0') || (currlen >= maxlen)) + state = DP_S_DONE; + + switch(state) + { + case DP_S_DEFAULT: + if (ch == '%') + state = DP_S_FLAGS; + else + dopr_outch (buffer, &currlen, maxlen, ch); + ch = *format++; + break; + case DP_S_FLAGS: + switch (ch) + { + case '-': + flags |= DP_F_MINUS; + ch = *format++; + break; + case '+': + flags |= DP_F_PLUS; + ch = *format++; + break; + case ' ': + flags |= DP_F_SPACE; + ch = *format++; + break; + case '#': + flags |= DP_F_NUM; + ch = *format++; + break; + case '0': + flags |= DP_F_ZERO; + ch = *format++; + break; + default: + state = DP_S_MIN; + break; + } + break; + case DP_S_MIN: + if (isdigit(ch)) + { + min = 10*min + char_to_int (ch); + ch = *format++; + } + else if (ch == '*') + { + min = va_arg (args, int); + ch = *format++; + state = DP_S_DOT; + } + else + state = DP_S_DOT; + break; + case DP_S_DOT: + if (ch == '.') + { + state = DP_S_MAX; + ch = *format++; + } + else + state = DP_S_MOD; + break; + case DP_S_MAX: + if (isdigit(ch)) + { + if (max < 0) + max = 0; + max = 10*max + char_to_int (ch); + ch = *format++; + } + else if (ch == '*') + { + max = va_arg (args, int); + ch = *format++; + state = DP_S_MOD; + } + else + state = DP_S_MOD; + break; + case DP_S_MOD: + /* Currently, we don't support Long Long, bummer */ + switch (ch) + { + case 'h': + cflags = DP_C_SHORT; + ch = *format++; + break; + case 'l': + cflags = DP_C_LONG; + ch = *format++; + break; + case 'L': + cflags = DP_C_LDOUBLE; + ch = *format++; + break; + default: + break; + } + state = DP_S_CONV; + break; + case DP_S_CONV: + switch (ch) + { + case 'd': + case 'i': + if (cflags == DP_C_SHORT) + value = va_arg (args, int); + else if (cflags == DP_C_LONG) + value = va_arg (args, long int); + else + value = va_arg (args, int); + fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); + break; + case 'o': + flags &= ~DP_F_PLUS; + if (cflags == DP_C_SHORT) + value = va_arg (args, unsigned int); + else if (cflags == DP_C_LONG) + value = va_arg (args, unsigned long int); + else + value = va_arg (args, unsigned int); + fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags); + break; + case 'u': + flags &= ~DP_F_PLUS; + if (cflags == DP_C_SHORT) + value = va_arg (args, unsigned int); + else if (cflags == DP_C_LONG) + value = va_arg (args, unsigned long int); + else + value = va_arg (args, unsigned int); + fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); + break; + case 'X': + flags |= DP_F_UP; + case 'x': + flags &= ~DP_F_PLUS; + if (cflags == DP_C_SHORT) + value = va_arg (args, unsigned int); + else if (cflags == DP_C_LONG) + value = va_arg (args, unsigned long int); + else + value = va_arg (args, unsigned int); + fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags); + break; + case 'f': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg (args, long double); + else + fvalue = va_arg (args, double); + /* um, floating point? */ + fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags, 'f'); + break; + case 'E': + flags |= DP_F_UP; + case 'e': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg (args, long double); + else + fvalue = va_arg (args, double); + break; + case 'G': + flags |= DP_F_UP; + case 'g': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg (args, long double); + else + fvalue = va_arg (args, double); + fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags, 'g'); + break; + case 'c': + dopr_outch (buffer, &currlen, maxlen, va_arg (args, int)); + break; + case 's': + strvalue = va_arg (args, char *); + if (max < 0) + max = maxlen; /* ie, no max */ + fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max); + break; + case 'p': + strvalue = va_arg (args, void *); + fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags); + break; + case 'n': + if (cflags == DP_C_SHORT) + { + short int *num; + num = va_arg (args, short int *); + *num = currlen; + } + else if (cflags == DP_C_LONG) + { + long int *num; + num = va_arg (args, long int *); + *num = currlen; + } + else + { + int *num; + num = va_arg (args, int *); + *num = currlen; + } + break; + case '%': + dopr_outch (buffer, &currlen, maxlen, ch); + break; + case 'w': + /* not supported yet, treat as next char */ + ch = *format++; + break; + default: + /* Unknown, skip */ + break; + } + ch = *format++; + state = DP_S_DEFAULT; + flags = cflags = min = 0; + max = -1; + break; + case DP_S_DONE: + break; + default: + /* hmm? */ + break; /* some picky compilers need this */ + } + } + if (currlen < maxlen - 1) + buffer[currlen] = '\0'; + else + buffer[maxlen - 1] = '\0'; +} + +static void fmtstr (char *buffer, size_t *currlen, size_t maxlen, + char *value, int flags, int min, int max) +{ + int padlen, strln; /* amount to pad */ + int cnt = 0; + + if (value == 0) + { + value = ""; + } + + for (strln = 0; value[strln]; ++strln); /* strlen */ + padlen = min - strln; + if (padlen < 0) + padlen = 0; + if (flags & DP_F_MINUS) + padlen = -padlen; /* Left Justify */ + + while ((padlen > 0) && (cnt < max)) + { + dopr_outch (buffer, currlen, maxlen, ' '); + --padlen; + ++cnt; + } + while (*value && (cnt < max)) + { + dopr_outch (buffer, currlen, maxlen, *value++); + ++cnt; + } + while ((padlen < 0) && (cnt < max)) + { + dopr_outch (buffer, currlen, maxlen, ' '); + ++padlen; + ++cnt; + } +} + +/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */ + +static void fmtint (char *buffer, size_t *currlen, size_t maxlen, + long value, int base, int min, int max, int flags) +{ + int signvalue = 0; + unsigned long uvalue; + char convert[20]; + int place = 0; + int spadlen = 0; /* amount to space pad */ + int zpadlen = 0; /* amount to zero pad */ + int caps = 0; + + if (max < 0) + max = 0; + + uvalue = value; + if( value < 0 ) { + signvalue = '-'; + uvalue = -value; + } + else + if (flags & DP_F_PLUS) /* Do a sign (+/i) */ + signvalue = '+'; + else + if (flags & DP_F_SPACE) + signvalue = ' '; + + if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ + + do { + convert[place++] = + (caps? "0123456789ABCDEF":"0123456789abcdef") + [uvalue % (unsigned)base ]; + uvalue = (uvalue / (unsigned)base ); + } while(uvalue && (place < 20)); + if (place == 20) place--; + convert[place] = 0; + + zpadlen = max - place; + spadlen = min - MAX (max, place) - (signvalue ? 1 : 0); + if (zpadlen < 0) zpadlen = 0; + if (spadlen < 0) spadlen = 0; + if (flags & DP_F_ZERO) + { + zpadlen = MAX(zpadlen, spadlen); + spadlen = 0; + } + if (flags & DP_F_MINUS) + spadlen = -spadlen; /* Left Justifty */ + +#ifdef DEBUG_SNPRINTF + dprint (1, (debugfile, "zpad: %d, spad: %d, min: %d, max: %d, place: %d\n", + zpadlen, spadlen, min, max, place)); +#endif + + /* Spaces */ + while (spadlen > 0) + { + dopr_outch (buffer, currlen, maxlen, ' '); + --spadlen; + } + + /* Sign */ + if (signvalue) + dopr_outch (buffer, currlen, maxlen, signvalue); + + /* Zeros */ + if (zpadlen > 0) + { + while (zpadlen > 0) + { + dopr_outch (buffer, currlen, maxlen, '0'); + --zpadlen; + } + } + + /* Digits */ + while (place > 0) + dopr_outch (buffer, currlen, maxlen, convert[--place]); + + /* Left Justified spaces */ + while (spadlen < 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + ++spadlen; + } +} + +static long double abs_val (long double value) +{ + long double result = value; + + if (value < 0) + result = -value; + + return result; +} + +static long double compat_pow10 (int exp) +{ + long double result = 1; + + while (exp) + { + result *= 10; + exp--; + } + + return result; +} + +static long compat_round (long double value) +{ + long intpart; + + intpart = value; + value = value - intpart; + if (value >= 0.5) + intpart++; + + return intpart; +} + +static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, + long double fvalue, int min, int max, int flags, int conv) +{ + int signvalue = 0; + long double ufvalue; + char iconvert[20]; + char fconvert[20]; + int iplace = 0; + int fplace = 0; + int padlen = 0; /* amount to pad */ + int zpadlen = 0; + int caps = 0; + long intpart; + long fracpart; + + /* + * AIX manpage says the default is 0, but Solaris says the default + * is 6, and sprintf on AIX defaults to 6 + */ + if (max < 0) + max = 6; + + ufvalue = abs_val (fvalue); + + if (fvalue < 0) + signvalue = '-'; + else + if (flags & DP_F_PLUS) /* Do a sign (+/i) */ + signvalue = '+'; + else + if (flags & DP_F_SPACE) + signvalue = ' '; + +#if 0 + if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ +#endif + + intpart = ufvalue; + + /* + * Sorry, we only support 9 digits past the decimal because of our + * conversion method + */ + if (max > 9) + max = 9; + + /* We "cheat" by converting the fractional part to integer by + * multiplying by a factor of 10 + */ + fracpart = compat_round ((compat_pow10 (max)) * (ufvalue - intpart)); + + if (fracpart >= compat_pow10 (max)) + { + intpart++; + fracpart -= compat_pow10 (max); + } + +#ifdef DEBUG_SNPRINTF + dprint (1, (debugfile, "fmtfp: %f =? %d.%d\n", fvalue, intpart, fracpart)); +#endif + + /* Convert integer part */ + do { + iconvert[iplace++] = + (caps? "0123456789ABCDEF":"0123456789abcdef")[intpart % 10]; + intpart = (intpart / 10); + } while(intpart && (iplace < 20)); + if (iplace == 20) iplace--; + iconvert[iplace] = 0; + + /* Convert fractional part */ + do { + fconvert[fplace++] = + (caps? "0123456789ABCDEF":"0123456789abcdef")[fracpart % 10]; + fracpart = (fracpart / 10); + if(conv == 'g' && fplace == 1 && fconvert[0] == '0') { + fplace = 0; /* skip trailing zeroes for %g */ + zpadlen ++; + } + } while(fracpart && (fplace < 20)); + if (fplace == 20) fplace--; + fconvert[fplace] = 0; + + if(conv == 'f') { + /* -1 for decimal point, another -1 if we are printing a sign */ + padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); + zpadlen = max - fplace; + } else if(conv == 'g') { + /* zpadlen contains number of trailing zeroes removed */ + padlen = min - iplace - (max-zpadlen) - 1 - ((signvalue) ? 1 : 0); + if(fplace == 0) { + padlen += 1; /* add the decimal dot suppressed */ + zpadlen = 0; + } else zpadlen = (max-zpadlen) - fplace; + } + if (zpadlen < 0) + zpadlen = 0; + if (padlen < 0) + padlen = 0; + if (flags & DP_F_MINUS) + padlen = -padlen; /* Left Justifty */ + + if ((flags & DP_F_ZERO) && (padlen > 0)) + { + if (signvalue) + { + dopr_outch (buffer, currlen, maxlen, signvalue); + --padlen; + signvalue = 0; + } + while (padlen > 0) + { + dopr_outch (buffer, currlen, maxlen, '0'); + --padlen; + } + } + while (padlen > 0) + { + dopr_outch (buffer, currlen, maxlen, ' '); + --padlen; + } + if (signvalue) + dopr_outch (buffer, currlen, maxlen, signvalue); + + while (iplace > 0) + dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]); + + /* for %g do not output decimal point if no fraction is present */ + if(conv == 'f' || (conv == 'g' && fplace > 0)) { + /* + * Decimal point. This should probably use locale to find the correct + * char to print out. + */ + dopr_outch (buffer, currlen, maxlen, '.'); + } + + while (zpadlen > 0) + { + dopr_outch (buffer, currlen, maxlen, '0'); + --zpadlen; + } + + while (fplace > 0) + dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]); + + while (padlen < 0) + { + dopr_outch (buffer, currlen, maxlen, ' '); + ++padlen; + } +} + +static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c) +{ + if (*currlen < maxlen) + buffer[(*currlen)++] = c; +} + +#ifdef TEST_SNPRINTF +#ifndef LONG_STRING +#define LONG_STRING 1024 +#endif +int main (void) +{ + char buf1[LONG_STRING]; + char buf2[LONG_STRING]; + char *fp_fmt[] = { + "%-1.5f", + "%1.5f", + "%123.9f", + "%10.5f", + "% 10.5f", + "%+22.9f", + "%+4.9f", + "%01.3f", + "%4f", + "%3.1f", + "%3.2f", + NULL + }; + double fp_nums[] = { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996, + 0.9996, 1.996, 4.136, 0}; + char *int_fmt[] = { + "%-1.5d", + "%1.5d", + "%123.9d", + "%5.5d", + "%10.5d", + "% 10.5d", + "%+22.33d", + "%01.3d", + "%4d", + NULL + }; + long int_nums[] = { -1, 134, 91340, 341, 0203, 0}; + int x, y; + int fail = 0; + int num = 0; + + printf ("Testing snprintf format codes against system sprintf...\n"); + + for (x = 0; fp_fmt[x] != NULL ; x++) + for (y = 0; fp_nums[y] != 0 ; y++) + { + snprintf (buf1, sizeof (buf1), fp_fmt[x], fp_nums[y]); + sprintf (buf2, fp_fmt[x], fp_nums[y]); + if (strcmp (buf1, buf2)) + { + printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n", + fp_fmt[x], buf1, buf2); + fail++; + } + num++; + } + + for (x = 0; int_fmt[x] != NULL ; x++) + for (y = 0; int_nums[y] != 0 ; y++) + { + snprintf (buf1, sizeof (buf1), int_fmt[x], int_nums[y]); + sprintf (buf2, int_fmt[x], int_nums[y]); + if (strcmp (buf1, buf2)) + { + printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n", + int_fmt[x], buf1, buf2); + fail++; + } + num++; + } + printf ("%d tests failed out of %d.\n", fail, num); +} +#endif /* SNPRINTF_TEST */ + +#endif /* !HAVE_SNPRINTF */ diff --git a/compat/strlcpy.c b/compat/strlcpy.c new file mode 100644 index 00000000000..acd306a151c --- /dev/null +++ b/compat/strlcpy.c @@ -0,0 +1,57 @@ +/* from openssh 4.3p2 compat/strlcpy.c */ +/* + * Copyright (c) 1998 Todd C. Miller + * + * 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. + */ + +/* OPENBSD ORIGINAL: lib/libc/string/strlcpy.c */ + +#include +#ifndef HAVE_STRLCPY + +#include +#include + +/* + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +size_t +strlcpy(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0 && --n != 0) { + do { + if ((*d++ = *s++) == 0) + break; + } while (--n != 0); + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + + return(s - src - 1); /* count does not include NUL */ +} + +#endif /* !HAVE_STRLCPY */ diff --git a/compat/strptime.c b/compat/strptime.c new file mode 100644 index 00000000000..9a0caa53574 --- /dev/null +++ b/compat/strptime.c @@ -0,0 +1,345 @@ +/** strptime workaround (for oa macos leopard) + * This strptime follows the man strptime (2001-11-12) + * conforming to SUSv2, POSIX.1-2001 + * + * This very simple version of strptime has no: + * - E alternatives + * - O alternatives + * - Glibc additions + * - Does not process week numbers + * - Does not properly processes year day + * + * LICENSE + * Copyright (c) 2008, NLnet Labs, Matthijs Mekking + * 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" + +#ifndef HAVE_CONFIG_H +#include +#endif + +#ifndef STRPTIME_WORKS + +#define TM_YEAR_BASE 1900 + +#include +#include + +static const char *abb_weekdays[] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL +}; +static const char *full_weekdays[] = { + "Sunday", "Monday", "Tuesday", "Wednesday", + "Thursday", "Friday", "Saturday", NULL +}; +static const char *abb_months[] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL +}; +static const char *full_months[] = { + "January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December", NULL +}; +static const char *ampm[] = { + "am", "pm", NULL +}; + +static int +match_string(const char **buf, const char **strs) +{ + int i = 0; + + for (i = 0; strs[i] != NULL; i++) { + int len = strlen(strs[i]); + if (strncasecmp (*buf, strs[i], len) == 0) { + *buf += len; + return i; + } + } + return -1; +} + +static int +str2int(const char **buf, int max) +{ + int ret=0, count=0; + + while (*buf[0] != '\0' && isdigit(*buf[0]) && counttm_wday = ret; + break; + case 'b': /* month name, abbreviated or full */ + case 'B': + case 'h': + ret = match_string(&s, full_months); + if (ret < 0) + ret = match_string(&s, abb_months); + if (ret < 0) { + return NULL; + } + tm->tm_mon = ret; + break; + case 'c': /* date and time representation */ + if (!(s = unbound_strptime(s, "%x %X", tm))) { + return NULL; + } + break; + case 'C': /* century number */ + ret = str2int(&s, 2); + if (ret < 0 || ret > 99) { /* must be in [00,99] */ + return NULL; + } + + if (split_year) { + tm->tm_year = ret*100 + (tm->tm_year%100); + } + else { + tm->tm_year = ret*100 - TM_YEAR_BASE; + split_year = 1; + } + break; + case 'd': /* day of month */ + case 'e': + ret = str2int(&s, 2); + if (ret < 1 || ret > 31) { /* must be in [01,31] */ + return NULL; + } + tm->tm_mday = ret; + break; + case 'D': /* equivalent to %m/%d/%y */ + if (!(s = unbound_strptime(s, "%m/%d/%y", tm))) { + return NULL; + } + break; + case 'H': /* hour */ + ret = str2int(&s, 2); + if (ret < 0 || ret > 23) { /* must be in [00,23] */ + return NULL; + } + tm->tm_hour = ret; + break; + case 'I': /* 12hr clock hour */ + ret = str2int(&s, 2); + if (ret < 1 || ret > 12) { /* must be in [01,12] */ + return NULL; + } + if (ret == 12) /* actually [0,11] */ + ret = 0; + tm->tm_hour = ret; + break; + case 'j': /* day of year */ + ret = str2int(&s, 2); + if (ret < 1 || ret > 366) { /* must be in [001,366] */ + return NULL; + } + tm->tm_yday = ret; + break; + case 'm': /* month */ + ret = str2int(&s, 2); + if (ret < 1 || ret > 12) { /* must be in [01,12] */ + return NULL; + } + /* months go from 0-11 */ + tm->tm_mon = (ret-1); + break; + case 'M': /* minute */ + ret = str2int(&s, 2); + if (ret < 0 || ret > 59) { /* must be in [00,59] */ + return NULL; + } + tm->tm_min = ret; + break; + case 'n': /* arbitrary whitespace */ + case 't': + while (isspace(*s)) + s++; + break; + case 'p': /* am pm */ + ret = match_string(&s, ampm); + if (ret < 0) { + return NULL; + } + if (tm->tm_hour < 0 || tm->tm_hour > 11) { /* %I */ + return NULL; + } + + if (ret == 1) /* pm */ + tm->tm_hour += 12; + break; + case 'r': /* equivalent of %I:%M:%S %p */ + if (!(s = unbound_strptime(s, "%I:%M:%S %p", tm))) { + return NULL; + } + break; + case 'R': /* equivalent of %H:%M */ + if (!(s = unbound_strptime(s, "%H:%M", tm))) { + return NULL; + } + break; + case 'S': /* seconds */ + ret = str2int(&s, 2); + /* 60 may occur for leap seconds */ + /* earlier 61 was also allowed */ + if (ret < 0 || ret > 60) { /* must be in [00,60] */ + return NULL; + } + tm->tm_sec = ret; + break; + case 'T': /* equivalent of %H:%M:%S */ + if (!(s = unbound_strptime(s, "%H:%M:%S", tm))) { + return NULL; + } + break; + case 'U': /* week number, with the first Sun of Jan being w1 */ + ret = str2int(&s, 2); + if (ret < 0 || ret > 53) { /* must be in [00,53] */ + return NULL; + } + /** it is hard (and not necessary for nsd) to determine time + * data from week number. + **/ + break; + case 'w': /* day of week */ + ret = str2int(&s, 1); + if (ret < 0 || ret > 6) { /* must be in [0,6] */ + return NULL; + } + tm->tm_wday = ret; + break; + case 'W': /* week number, with the first Mon of Jan being w1 */ + ret = str2int(&s, 2); + if (ret < 0 || ret > 53) { /* must be in [00,53] */ + return NULL; + } + /** it is hard (and not necessary for nsd) to determine time + * data from week number. + **/ + break; + case 'x': /* date format */ + if (!(s = unbound_strptime(s, "%m/%d/%y", tm))) { + return NULL; + } + break; + case 'X': /* time format */ + if (!(s = unbound_strptime(s, "%H:%M:%S", tm))) { + return NULL; + } + break; + case 'y': /* last two digits of a year */ + ret = str2int(&s, 2); + if (ret < 0 || ret > 99) { /* must be in [00,99] */ + return NULL; + } + if (split_year) { + tm->tm_year = ((tm->tm_year/100) * 100) + ret; + } + else { + split_year = 1; + + /** currently: + * if in [0,68] we are in 21th century, + * if in [69,99] we are in 20th century. + **/ + if (ret < 69) /* 2000 */ + ret += 100; + tm->tm_year = ret; + } + break; + case 'Y': /* year */ + ret = str2int(&s, 4); + if (ret < 0 || ret > 9999) { + return NULL; + } + tm->tm_year = ret - TM_YEAR_BASE; + break; + case '\0': + default: /* unsupported, cannot match format */ + return NULL; + break; + } + } + else { /* literal */ + /* if input cannot match format, return NULL */ + if (*s != c) + return NULL; + s++; + } + + format++; + } + + /* return pointer to remainder of s */ + return (char*) s; +} + +#endif /* STRPTIME_WORKS */ diff --git a/config.guess b/config.guess new file mode 100755 index 00000000000..dc84c68ef79 --- /dev/null +++ b/config.guess @@ -0,0 +1,1501 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 +# Free Software Foundation, Inc. + +timestamp='2009-11-20' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner. Please send patches (context +# diff format) to and include a ChangeLog +# entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[456]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + case ${UNAME_MACHINE} in + pc98) + echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + LIBC=gnu + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-gnu + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + i386) + eval $set_cc_for_build + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + UNAME_PROCESSOR="x86_64" + fi + fi ;; + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/config.h.in b/config.h.in new file mode 100644 index 00000000000..cacf294b908 --- /dev/null +++ b/config.h.in @@ -0,0 +1,899 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Directory to chroot to */ +#undef CHROOT_DIR + +/* Pathname to the Unbound configuration file */ +#undef CONFIGFILE + +/* configure flags */ +#undef CONFIGURE_BUILD_WITH + +/* configure date */ +#undef CONFIGURE_DATE + +/* configure target system */ +#undef CONFIGURE_TARGET + +/* Define this if on macOSX10.4-darwin8 and setreuid and setregid do not work + */ +#undef DARWIN_BROKEN_SETREUID + +/* Whether daemon is deprecated */ +#undef DEPRECATED_DAEMON + +/* Define if you want to use debug lock checking (slow). */ +#undef ENABLE_LOCK_CHECKS + +/* Define this if you enabled-allsymbols from libunbound to link binaries to + it for smaller install size, but the libunbound export table is polluted by + internal symbols */ +#undef EXPORT_ALL_SYMBOLS + +/* Define to 1 if you have the header file. */ +#undef HAVE_ARPA_INET_H + +/* Whether the C compiler accepts the "format" attribute */ +#undef HAVE_ATTR_FORMAT + +/* Whether the C compiler accepts the "unused" attribute */ +#undef HAVE_ATTR_UNUSED + +/* Define to 1 if your system has a working `chown' function. */ +#undef HAVE_CHOWN + +/* Define to 1 if you have the `chroot' function. */ +#undef HAVE_CHROOT + +/* Define to 1 if you have the `ctime_r' function. */ +#undef HAVE_CTIME_R + +/* Define to 1 if you have the `daemon' function. */ +#undef HAVE_DAEMON + +/* Define to 1 if you have the declaration of `NID_secp384r1', and to 0 if you + don't. */ +#undef HAVE_DECL_NID_SECP384R1 + +/* Define to 1 if you have the declaration of `NID_X9_62_prime256v1', and to 0 + if you don't. */ +#undef HAVE_DECL_NID_X9_62_PRIME256V1 + +/* Define to 1 if you have the declaration of `sk_SSL_COMP_pop_free', and to 0 + if you don't. */ +#undef HAVE_DECL_SK_SSL_COMP_POP_FREE + +/* Define to 1 if you have the declaration of + `SSL_COMP_get_compression_methods', and to 0 if you don't. */ +#undef HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the `event_base_free' function. */ +#undef HAVE_EVENT_BASE_FREE + +/* Define to 1 if you have the `event_base_get_method' function. */ +#undef HAVE_EVENT_BASE_GET_METHOD + +/* Define to 1 if you have the `event_base_new' function. */ +#undef HAVE_EVENT_BASE_NEW + +/* Define to 1 if you have the `event_base_once' function. */ +#undef HAVE_EVENT_BASE_ONCE + +/* Define to 1 if you have the header file. */ +#undef HAVE_EVENT_H + +/* Define to 1 if you have the `EVP_sha1' function. */ +#undef HAVE_EVP_SHA1 + +/* Define to 1 if you have the `EVP_sha256' function. */ +#undef HAVE_EVP_SHA256 + +/* Define to 1 if you have the `EVP_sha512' function. */ +#undef HAVE_EVP_SHA512 + +/* Define to 1 if you have the `ev_default_loop' function. */ +#undef HAVE_EV_DEFAULT_LOOP + +/* Define to 1 if you have the `ev_loop' function. */ +#undef HAVE_EV_LOOP + +/* Define to 1 if you have the header file. */ +#undef HAVE_EXPAT_H + +/* Define to 1 if you have the `fcntl' function. */ +#undef HAVE_FCNTL + +/* Define to 1 if you have the `fork' function. */ +#undef HAVE_FORK + +/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ +#undef HAVE_FSEEKO + +/* Whether getaddrinfo is available */ +#undef HAVE_GETADDRINFO + +/* Define to 1 if you have the header file. */ +#undef HAVE_GETOPT_H + +/* Define to 1 if you have the `getpwnam' function. */ +#undef HAVE_GETPWNAM + +/* Define to 1 if you have the `getrlimit' function. */ +#undef HAVE_GETRLIMIT + +/* Define to 1 if you have the `glob' function. */ +#undef HAVE_GLOB + +/* Define to 1 if you have the header file. */ +#undef HAVE_GLOB_H + +/* Define to 1 if you have the `gmtime_r' function. */ +#undef HAVE_GMTIME_R + +/* Define to 1 if you have the header file. */ +#undef HAVE_GRP_H + +/* If you have HMAC_CTX_init */ +#undef HAVE_HMAC_CTX_INIT + +/* Define to 1 if you have the `inet_aton' function. */ +#undef HAVE_INET_ATON + +/* Define to 1 if you have the `inet_ntop' function. */ +#undef HAVE_INET_NTOP + +/* Define to 1 if you have the `inet_pton' function. */ +#undef HAVE_INET_PTON + +/* Define to 1 if you have the `initgroups' function. */ +#undef HAVE_INITGROUPS + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* if the function 'ioctlsocket' is available */ +#undef HAVE_IOCTLSOCKET + +/* Define to 1 if you have the header file. */ +#undef HAVE_IPHLPAPI_H + +/* Define to 1 if you have the `kill' function. */ +#undef HAVE_KILL + +/* Define to 1 if you have the `ldns_key_EVP_unload_gost' function. */ +#undef HAVE_LDNS_KEY_EVP_UNLOAD_GOST + +/* Define to 1 if you have the header file. */ +#undef HAVE_LDNS_LDNS_H + +/* Define to 1 if you have the `ldns' library (-lldns). */ +#undef HAVE_LIBLDNS + +/* Define to 1 if you have the `localtime_r' function. */ +#undef HAVE_LOCALTIME_R + +/* Define to 1 if you have the header file. */ +#undef HAVE_LOGIN_CAP_H + +/* If have GNU libc compatible malloc */ +#undef HAVE_MALLOC + +/* Define to 1 if you have the `memmove' function. */ +#undef HAVE_MEMMOVE + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETDB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IN_H + +/* Define to 1 if you have the `OPENSSL_config' function. */ +#undef HAVE_OPENSSL_CONFIG + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_CONF_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_ENGINE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_ERR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_RAND_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_SSL_H + +/* Define if you have POSIX threads libraries and header files. */ +#undef HAVE_PTHREAD + +/* Define to 1 if the system has the type `pthread_rwlock_t'. */ +#undef HAVE_PTHREAD_RWLOCK_T + +/* Define to 1 if the system has the type `pthread_spinlock_t'. */ +#undef HAVE_PTHREAD_SPINLOCK_T + +/* Define to 1 if you have the header file. */ +#undef HAVE_PWD_H + +/* Define if you have Python libraries and header files. */ +#undef HAVE_PYTHON + +/* Define to 1 if you have the `random' function. */ +#undef HAVE_RANDOM + +/* Define to 1 if you have the `recvmsg' function. */ +#undef HAVE_RECVMSG + +/* Define to 1 if you have the `sbrk' function. */ +#undef HAVE_SBRK + +/* Define to 1 if you have the `sendmsg' function. */ +#undef HAVE_SENDMSG + +/* Define to 1 if you have the `setregid' function. */ +#undef HAVE_SETREGID + +/* Define to 1 if you have the `setresgid' function. */ +#undef HAVE_SETRESGID + +/* Define to 1 if you have the `setresuid' function. */ +#undef HAVE_SETRESUID + +/* Define to 1 if you have the `setreuid' function. */ +#undef HAVE_SETREUID + +/* Define to 1 if you have the `setrlimit' function. */ +#undef HAVE_SETRLIMIT + +/* Define to 1 if you have the `setsid' function. */ +#undef HAVE_SETSID + +/* Define to 1 if you have the `setusercontext' function. */ +#undef HAVE_SETUSERCONTEXT + +/* Define to 1 if you have the `sigprocmask' function. */ +#undef HAVE_SIGPROCMASK + +/* Define to 1 if you have the `sleep' function. */ +#undef HAVE_SLEEP + +/* Define to 1 if you have the `snprintf' function. */ +#undef HAVE_SNPRINTF + +/* Define to 1 if you have the `socketpair' function. */ +#undef HAVE_SOCKETPAIR + +/* Using Solaris threads */ +#undef HAVE_SOLARIS_THREADS + +/* Define to 1 if you have the `srandom' function. */ +#undef HAVE_SRANDOM + +/* Define if you have the SSL libraries installed. */ +#undef HAVE_SSL + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDARG_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDBOOL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the `strftime' function. */ +#undef HAVE_STRFTIME + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strlcpy' function. */ +#undef HAVE_STRLCPY + +/* Define to 1 if you have the `strptime' function. */ +#undef HAVE_STRPTIME + +/* Define to 1 if `ipi_spec_dst' is a member of `struct in_pktinfo'. */ +#undef HAVE_STRUCT_IN_PKTINFO_IPI_SPEC_DST + +/* Define if you have Swig libraries and header files. */ +#undef HAVE_SWIG + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYSLOG_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_RESOURCE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SOCKET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_UIO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_WAIT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_TIME_H + +/* Define to 1 if you have the `tzset' function. */ +#undef HAVE_TZSET + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the `usleep' function. */ +#undef HAVE_USLEEP + +/* Define to 1 if you have the `vfork' function. */ +#undef HAVE_VFORK + +/* Define to 1 if you have the header file. */ +#undef HAVE_VFORK_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_WINDOWS_H + +/* Using Windows threads */ +#undef HAVE_WINDOWS_THREADS + +/* Define to 1 if you have the header file. */ +#undef HAVE_WINSOCK2_H + +/* Define to 1 if `fork' works. */ +#undef HAVE_WORKING_FORK + +/* Define to 1 if `vfork' works. */ +#undef HAVE_WORKING_VFORK + +/* Define to 1 if you have the `writev' function. */ +#undef HAVE_WRITEV + +/* Define to 1 if you have the header file. */ +#undef HAVE_WS2TCPIP_H + +/* Define to 1 if you have the `_beginthreadex' function. */ +#undef HAVE__BEGINTHREADEX + +/* if lex has yylex_destroy */ +#undef LEX_HAS_YYLEX_DESTROY + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#undef LT_OBJDIR + +/* Define to the maximum message length to pass to syslog. */ +#undef MAXSYSLOGMSGLEN + +/* Define if memcmp() does not compare unsigned bytes */ +#undef MEMCMP_IS_BROKEN + +/* Define if mkdir has one argument. */ +#undef MKDIR_HAS_ONE_ARG + +/* Define if the network stack does not fully support nonblocking io (causes + lower performance). */ +#undef NONBLOCKING_IS_BROKEN + +/* Put -D_ALL_SOURCE define in config.h */ +#undef OMITTED__D_ALL_SOURCE + +/* Put -D_BSD_SOURCE define in config.h */ +#undef OMITTED__D_BSD_SOURCE + +/* Put -D_GNU_SOURCE define in config.h */ +#undef OMITTED__D_GNU_SOURCE + +/* Put -D_LARGEFILE_SOURCE=1 define in config.h */ +#undef OMITTED__D_LARGEFILE_SOURCE_1 + +/* Put -D_POSIX_C_SOURCE=200112 define in config.h */ +#undef OMITTED__D_POSIX_C_SOURCE_200112 + +/* Put -D_XOPEN_SOURCE=600 define in config.h */ +#undef OMITTED__D_XOPEN_SOURCE_600 + +/* Put -D_XOPEN_SOURCE_EXTENDED=1 define in config.h */ +#undef OMITTED__D_XOPEN_SOURCE_EXTENDED_1 + +/* Put -D__EXTENSIONS__ define in config.h */ +#undef OMITTED__D__EXTENSIONS__ + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* default pidfile location */ +#undef PIDFILE + +/* Define to necessary symbol if this constant uses a non-standard name on + your system. */ +#undef PTHREAD_CREATE_JOINABLE + +/* Define as the return type of signal handlers (`int' or `void'). */ +#undef RETSIGTYPE + +/* default rootkey location */ +#undef ROOT_ANCHOR_FILE + +/* default rootcert location */ +#undef ROOT_CERT_FILE + +/* version number for resource files */ +#undef RSRC_PACKAGE_VERSION + +/* Directory to chdir to */ +#undef RUN_DIR + +/* Shared data */ +#undef SHARE_DIR + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* use default strptime. */ +#undef STRPTIME_WORKS + +/* Use win32 resources and API */ +#undef UB_ON_WINDOWS + +/* default username */ +#undef UB_USERNAME + +/* use to enable lightweight alloc assertions, for debug use */ +#undef UNBOUND_ALLOC_LITE + +/* use malloc not regions, for debug use */ +#undef UNBOUND_ALLOC_NONREGIONAL + +/* use statistics for allocs and frees, for debug use */ +#undef UNBOUND_ALLOC_STATS + +/* define this to enable debug checks. */ +#undef UNBOUND_DEBUG + +/* Define this to enable ECDSA support. */ +#undef USE_ECDSA + +/* Define this to enable an EVP workaround for older openssl */ +#undef USE_ECDSA_EVP_WORKAROUND + +/* Define this to enable GOST support. */ +#undef USE_GOST + +/* Define if you want to use internal select based events */ +#undef USE_MINI_EVENT + +/* Define this to enable SHA256 and SHA512 support. */ +#undef USE_SHA2 + +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# undef _ALL_SOURCE +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# undef _GNU_SOURCE +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# undef _POSIX_PTHREAD_SEMANTICS +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# undef _TANDEM_SOURCE +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# undef __EXTENSIONS__ +#endif + + +/* Whether the windows socket API is used */ +#undef USE_WINSOCK + +/* the version of the windows API enabled */ +#undef WINVER + +/* Define if you want Python module. */ +#undef WITH_PYTHONMODULE + +/* Define if you want PyUnbound. */ +#undef WITH_PYUNBOUND + +/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a + `char[]'. */ +#undef YYTEXT_POINTER + +/* Number of bits in a file offset, on hosts where this is settable. */ +#undef _FILE_OFFSET_BITS + +/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ +#undef _LARGEFILE_SOURCE + +/* Define for large files, on AIX-style hosts. */ +#undef _LARGE_FILES + +/* Define to 1 if on MINIX. */ +#undef _MINIX + +/* Define to 2 if the system does not provide POSIX.1 features except with + this defined. */ +#undef _POSIX_1_SOURCE + +/* Define to 1 if you need to in order for `stat' and other things to work. */ +#undef _POSIX_SOURCE + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to `int' if doesn't define. */ +#undef gid_t + +/* in_addr_t */ +#undef in_addr_t + +/* in_port_t */ +#undef in_port_t + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +#undef inline +#endif + +/* Define to `short' if does not define. */ +#undef int16_t + +/* Define to `int' if does not define. */ +#undef int32_t + +/* Define to `long long' if does not define. */ +#undef int64_t + +/* Define to `signed char' if does not define. */ +#undef int8_t + +/* Define if replacement function should be used. */ +#undef malloc + +/* Define to `long int' if does not define. */ +#undef off_t + +/* Define to `int' if does not define. */ +#undef pid_t + +/* Define to 'int' if not defined */ +#undef rlim_t + +/* Define to `unsigned int' if does not define. */ +#undef size_t + +/* Define to 'int' if not defined */ +#undef socklen_t + +/* Define to `int' if does not define. */ +#undef ssize_t + +/* Define to 'unsigned char if not defined */ +#undef u_char + +/* Define to `int' if doesn't define. */ +#undef uid_t + +/* Define to `unsigned short' if does not define. */ +#undef uint16_t + +/* Define to `unsigned int' if does not define. */ +#undef uint32_t + +/* Define to `unsigned long long' if does not define. */ +#undef uint64_t + +/* Define to `unsigned char' if does not define. */ +#undef uint8_t + +/* Define as `fork' if `vfork' does not work. */ +#undef vfork + +#if defined(OMITTED__D_GNU_SOURCE) && !defined(_GNU_SOURCE) +#define _GNU_SOURCE 1 +#endif + +#if defined(OMITTED__D_BSD_SOURCE) && !defined(_BSD_SOURCE) +#define _BSD_SOURCE 1 +#endif + +#if defined(OMITTED__D__EXTENSIONS__) && !defined(__EXTENSIONS__) +#define __EXTENSIONS__ 1 +#endif + +#if defined(OMITTED__D_POSIX_C_SOURCE_200112) && !defined(_POSIX_C_SOURCE) +#define _POSIX_C_SOURCE 200112 +#endif + +#if defined(OMITTED__D_XOPEN_SOURCE_600) && !defined(_XOPEN_SOURCE) +#define _XOPEN_SOURCE 600 +#endif + +#if defined(OMITTED__D_XOPEN_SOURCE_EXTENDED_1) && !defined(_XOPEN_SOURCE_EXTENDED) +#define _XOPEN_SOURCE_EXTENDED 1 +#endif + +#if defined(OMITTED__D_ALL_SOURCE) && !defined(_ALL_SOURCE) +#define _ALL_SOURCE 1 +#endif + +#if defined(OMITTED__D_LARGEFILE_SOURCE_1) && !defined(_LARGEFILE_SOURCE) +#define _LARGEFILE_SOURCE 1 +#endif + + + + +#ifndef UNBOUND_DEBUG +# define NDEBUG +#endif + +#include +#include +#include +#include + +#if STDC_HEADERS +#include +#include +#endif + +#ifdef HAVE_STDINT_H +#include +#endif + +#include + +#if HAVE_SYS_PARAM_H +#include +#endif + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef HAVE_SYS_UIO_H +#include +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#ifdef HAVE_WINSOCK2_H +#include +#endif + +#ifdef HAVE_WS2TCPIP_H +#include +#endif + + + +#ifdef HAVE_ATTR_FORMAT +# define ATTR_FORMAT(archetype, string_index, first_to_check) \ + __attribute__ ((format (archetype, string_index, first_to_check))) +#else /* !HAVE_ATTR_FORMAT */ +# define ATTR_FORMAT(archetype, string_index, first_to_check) /* empty */ +#endif /* !HAVE_ATTR_FORMAT */ + + +#if defined(DOXYGEN) +# define ATTR_UNUSED(x) x +#elif defined(__cplusplus) +# define ATTR_UNUSED(x) +#elif defined(HAVE_ATTR_UNUSED) +# define ATTR_UNUSED(x) x __attribute__((unused)) +#else /* !HAVE_ATTR_UNUSED */ +# define ATTR_UNUSED(x) x +#endif /* !HAVE_ATTR_UNUSED */ + + +#ifndef HAVE_FSEEKO +#define fseeko fseek +#define ftello ftell +#endif /* HAVE_FSEEKO */ + + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 256 +#endif + + +#ifndef HAVE_SNPRINTF +#define snprintf snprintf_unbound +#define vsnprintf vsnprintf_unbound +#include +int snprintf (char *str, size_t count, const char *fmt, ...); +int vsnprintf (char *str, size_t count, const char *fmt, va_list arg); +#endif /* HAVE_SNPRINTF */ + + +#ifndef HAVE_INET_PTON +#define inet_pton inet_pton_unbound +int inet_pton(int af, const char* src, void* dst); +#endif /* HAVE_INET_PTON */ + + +#ifndef HAVE_INET_NTOP +#define inet_ntop inet_ntop_unbound +const char *inet_ntop(int af, const void *src, char *dst, size_t size); +#endif + + +#ifndef HAVE_INET_ATON +#define inet_aton inet_aton_unbound +int inet_aton(const char *cp, struct in_addr *addr); +#endif + + +#ifndef HAVE_MEMMOVE +#define memmove memmove_unbound +void *memmove(void *dest, const void *src, size_t n); +#endif + + +#ifndef HAVE_STRLCPY +#define strlcpy strlcpy_unbound +size_t strlcpy(char *dst, const char *src, size_t siz); +#endif + + +#ifndef HAVE_GMTIME_R +#define gmtime_r gmtime_r_unbound +struct tm *gmtime_r(const time_t *timep, struct tm *result); +#endif + + +#ifndef HAVE_SLEEP +#define sleep(x) Sleep((x)*1000) /* on win32 */ +#endif /* HAVE_SLEEP */ + + +#ifndef HAVE_USLEEP +#define usleep(x) Sleep((x)/1000 + 1) /* on win32 */ +#endif /* HAVE_USLEEP */ + + +#ifndef HAVE_RANDOM +#define random rand /* on win32, for tests only (bad random) */ +#endif /* HAVE_RANDOM */ + + +#ifndef HAVE_SRANDOM +#define srandom(x) srand(x) /* on win32, for tests only (bad random) */ +#endif /* HAVE_SRANDOM */ + + +/* detect if we need to cast to unsigned int for FD_SET to avoid warnings */ +#ifdef HAVE_WINSOCK2_H +#define FD_SET_T (u_int) +#else +#define FD_SET_T +#endif + + +#ifndef IPV6_MIN_MTU +#define IPV6_MIN_MTU 1280 +#endif /* IPV6_MIN_MTU */ + + +#ifdef MEMCMP_IS_BROKEN +#include "compat/memcmp.h" +#define memcmp memcmp_unbound +int memcmp(const void *x, const void *y, size_t n); +#endif + + + +#ifndef HAVE_CTIME_R +#define ctime_r unbound_ctime_r +char *ctime_r(const time_t *timep, char *buf); +#endif + +#if !defined(HAVE_STRPTIME) || !defined(STRPTIME_WORKS) +#define strptime unbound_strptime +struct tm; +char *strptime(const char *s, const char *format, struct tm *tm); +#endif + +#if defined(HAVE_EVENT_H) && !defined(HAVE_EVENT_BASE_ONCE) && !(defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)) && (defined(HAVE_PTHREAD) || defined(HAVE_SOLARIS_THREADS)) + /* using version of libevent that is not threadsafe. */ +# define LIBEVENT_SIGNAL_PROBLEM 1 +#endif + +#ifndef CHECKED_INET6 +# define CHECKED_INET6 +# ifdef AF_INET6 +# define INET6 +# else +# define AF_INET6 28 +# endif +#endif /* CHECKED_INET6 */ + +/* maximum nesting of included files */ +#define MAXINCLUDES 10 +#ifndef HAVE_GETADDRINFO +struct sockaddr_storage; +#include "compat/fake-rfc2553.h" +#endif + +#ifdef UNBOUND_ALLOC_STATS +# define malloc(s) unbound_stat_malloc_log(s, __FILE__, __LINE__, __func__) +# define calloc(n,s) unbound_stat_calloc_log(n, s, __FILE__, __LINE__, __func__) +# define free(p) unbound_stat_free_log(p, __FILE__, __LINE__, __func__) +# define realloc(p,s) unbound_stat_realloc_log(p, s, __FILE__, __LINE__, __func__) +void *unbound_stat_malloc(size_t size); +void *unbound_stat_calloc(size_t nmemb, size_t size); +void unbound_stat_free(void *ptr); +void *unbound_stat_realloc(void *ptr, size_t size); +void *unbound_stat_malloc_log(size_t size, const char* file, int line, + const char* func); +void *unbound_stat_calloc_log(size_t nmemb, size_t size, const char* file, + int line, const char* func); +void unbound_stat_free_log(void *ptr, const char* file, int line, + const char* func); +void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file, + int line, const char* func); +#elif defined(UNBOUND_ALLOC_LITE) +# include "util/alloc.h" +#endif /* UNBOUND_ALLOC_LITE and UNBOUND_ALLOC_STATS */ + +/** default port for DNS traffic. */ +#define UNBOUND_DNS_PORT 53 +/** default port for unbound control traffic, registered port with IANA, + ub-dns-control 8953/tcp unbound dns nameserver control */ +#define UNBOUND_CONTROL_PORT 8953 +/** the version of unbound-control that this software implements */ +#define UNBOUND_CONTROL_VERSION 1 + + diff --git a/config.sub b/config.sub new file mode 100755 index 00000000000..2a55a50751c --- /dev/null +++ b/config.sub @@ -0,0 +1,1705 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 +# Free Software Foundation, Inc. + +timestamp='2009-11-20' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted GNU ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ + uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nios | nios2 \ + | ns16k | ns32k \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e \ + | we32k \ + | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12 | picochip) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze) + basic_machine=microblaze-xilinx + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + tile*) + basic_machine=tile-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/configure b/configure new file mode 100755 index 00000000000..14bd38173d6 --- /dev/null +++ b/configure @@ -0,0 +1,20265 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.68 for unbound 1.4.17. +# +# Report bugs to . +# +# +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software +# Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1 + + test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ + || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + # We cannot yet assume a decent shell, so we have to provide a + # neutralization value for shells without unset; and this also + # works around shells that cannot unset nonexistent variables. + # Preserve -v and -x to the replacement shell. + BASH_ENV=/dev/null + ENV=/dev/null + (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV + export CONFIG_SHELL + case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; + esac + exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"} +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org and +$0: unbound-bugs@nlnetlabs.nl about your system, including +$0: any error possibly output before this message. Then +$0: install a modern shell, or manually run the script +$0: under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + +SHELL=${CONFIG_SHELL-/bin/sh} + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='unbound' +PACKAGE_TARNAME='unbound' +PACKAGE_VERSION='1.4.17' +PACKAGE_STRING='unbound 1.4.17' +PACKAGE_BUGREPORT='unbound-bugs@nlnetlabs.nl' +PACKAGE_URL='' + +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='LTLIBOBJS +ldnsdir +SOURCEFILE +SOURCEDETERMINE +UBSYMS +EXTRALINK +COMMON_OBJ_ALL_SYMBOLS +LIBOBJ_WITHOUT_CTIME +WIN_CHECKCONF_OBJ_LINK +WIN_CONTROL_OBJ_LINK +WIN_UBANCHOR_OBJ_LINK +WIN_HOST_OBJ_LINK +WIN_DAEMON_OBJ_LINK +WIN_DAEMON_OBJ +WIN_DAEMON_SRC +WINAPPS +WINDRES +CHECKLOCK_OBJ +staticexe +HAVE_SSL +CONFIG_DATE +NETBSD_LINTFLAGS +PYUNBOUND_UNINSTALL +PYUNBOUND_INSTALL +PYUNBOUND_TARGET +PYUNBOUND_OBJ +WITH_PYUNBOUND +PYTHONMOD_UNINSTALL +PYTHONMOD_INSTALL +PYTHONMOD_HEADER +PYTHONMOD_OBJ +WITH_PYTHONMODULE +swig +SWIG_LIB +SWIG +PYTHON_EXTRA_LDFLAGS +PYTHON_EXTRA_LIBS +PYTHON_SITE_PKG +PYTHON_LDFLAGS +PYTHON_CPPFLAGS +PYTHON +PYTHON_VERSION +PTHREAD_CFLAGS +PTHREAD_LIBS +PTHREAD_CC +acx_pthread_config +RUNTIME_PATH +LIBOBJS +OTOOL64 +OTOOL +LIPO +NMEDIT +DSYMUTIL +MANIFEST_TOOL +AWK +RANLIB +ac_ct_AR +DLLTOOL +OBJDUMP +LN_S +NM +ac_ct_DUMPBIN +DUMPBIN +LD +FGREP +SED +LIBTOOL +AR +libtool +STRIP +doxygen +YFLAGS +YACC +LEXLIB +LEX_OUTPUT_ROOT +LEX +debug_enabled +DEPFLAG +UNBOUND_USERNAME +UNBOUND_ROOTCERT_FILE +UNBOUND_ROOTKEY_FILE +UNBOUND_PIDFILE +UNBOUND_SHARE_DIR +UNBOUND_CHROOT_DIR +UNBOUND_RUN_DIR +ub_conf_file +EGREP +GREP +CPP +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +target_os +target_vendor +target_cpu +target +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +LIBUNBOUND_AGE +LIBUNBOUND_REVISION +LIBUNBOUND_CURRENT +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +with_conf_file +with_run_dir +with_chroot_dir +with_share_dir +with_pidfile +with_rootkey_file +with_rootcert_file +with_username +enable_checking +enable_debug +enable_shared +enable_static +with_pic +enable_fast_install +with_gnu_ld +with_sysroot +enable_libtool_lock +enable_rpath +enable_largefile +enable_alloc_checks +enable_alloc_lite +enable_alloc_nonregional +with_pthreads +with_solaris_threads +with_pyunbound +with_pythonmodule +with_ssl +enable_sha2 +enable_gost +enable_ecdsa +with_libevent +with_libexpat +enable_static_exe +enable_lock_checks +enable_allsymbols +with_ldns +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP +YACC +YFLAGS +PYTHON_VERSION' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used" >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +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.4.17 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/unbound] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] + --target=TARGET configure for building compilers for TARGET [HOST] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of unbound 1.4.17:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-checking Enable warnings, asserts, makefile-dependencies + --enable-debug same as enable-checking + --enable-shared[=PKGS] build shared libraries [default=yes] + --enable-static[=PKGS] build static libraries [default=yes] + --enable-fast-install[=PKGS] + optimize for fast installation [default=yes] + --disable-libtool-lock avoid locking (might break parallel builds) + --disable-rpath disable hardcoded rpath (default=enabled) + --disable-largefile omit support for large files + --enable-alloc-checks enable to memory allocation statistics, for debug + purposes + --enable-alloc-lite enable for lightweight alloc assertions, for debug + purposes + --enable-alloc-nonregional + enable nonregional allocs, slow but exposes regional + allocations to other memory purifiers, for debug + purposes + --disable-sha2 Disable SHA256 and SHA512 RRSIG support + --disable-gost Disable GOST support + --disable-ecdsa Disable ECDSA support + --enable-static-exe enable to compile executables statically against + event, ldns libs, for debug purposes + --enable-lock-checks enable to check lock and unlock calls, for debug + purposes + --enable-allsymbols export all symbols from libunbound and link binaries + to it, smaller install size but libunbound export + table is polluted by internal symbols + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-conf-file=path Pathname to the Unbound configuration file + --with-run-dir=path set default directory to chdir to (by default dir + part of cfg file) + --with-chroot-dir=path set default directory to chroot to (by default same + as run-dir) + --with-share-dir=path set default directory with shared data (by default + same as share/unbound) + --with-pidfile=filename set default pathname to unbound pidfile (default + run-dir/unbound.pid) + --with-rootkey-file=filename + set default pathname to root key file (default + run-dir/root.key). This file is read and written. + --with-rootcert-file=filename + set default pathname to root update certificate file + (default run-dir/icannbundle.pem). This file need + not exist if you are content with the builtin. + --with-username=user set default user that unbound changes to (default + user is unbound) + --with-pic try to use only PIC/non-PIC objects [default=use + both] + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-sysroot=DIR Search for dependent libraries within DIR + (or the compiler's sysroot if not specified). + --with-pthreads use pthreads library, or --without-pthreads to + disable threading support. + --with-solaris-threads use solaris native thread library. + --with-pyunbound build PyUnbound, or --without-pyunbound to skip it. + (default=no) + --with-pythonmodule build Python module, or --without-pythonmodule to + disable script engine. (default=no) + --with-ssl=pathname enable SSL (will check /usr/local/ssl /usr/lib/ssl + /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw + /usr) + --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. + --with-libexpat=path specify explicit path for libexpat. + --with-ldns=PATH specify prefix of path of ldns library to use + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CPP C preprocessor + YACC The `Yet Another Compiler Compiler' implementation to use. + Defaults to the first program found out of: `bison -y', `byacc', + `yacc'. + YFLAGS The list of arguments that will be passed by default to $YACC. + This script will default YFLAGS to the empty string to avoid a + default value of `-d' given by some make applications. + PYTHON_VERSION + The installed Python version to use, for example '2.3'. This + string will be appended to the Python interpreter canonical + name. + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to . +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +unbound configure 1.4.17 +generated by GNU Autoconf 2.68 + +Copyright (C) 2010 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} +( $as_echo "## ---------------------------------------- ## +## Report this to unbound-bugs@nlnetlabs.nl ## +## ---------------------------------------- ##" + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* 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 $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func + +# ac_fn_c_check_type LINENO TYPE VAR INCLUDES +# ------------------------------------------- +# Tests whether TYPE exists after having included INCLUDES, setting cache +# variable VAR accordingly. +ac_fn_c_check_type () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof ($2)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof (($2))) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + eval "$3=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_type + +# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES +# --------------------------------------------- +# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR +# accordingly. +ac_fn_c_check_decl () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + as_decl_name=`echo $2|sed 's/ *(.*//'` + as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 +$as_echo_n "checking whether $as_decl_name is declared... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +#ifndef $as_decl_name +#ifdef __cplusplus + (void) $as_decl_use; +#else + (void) $as_decl_name; +#endif +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_decl + +# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES +# ---------------------------------------------------- +# Tries to find if the field MEMBER exists in type AGGR, after including +# INCLUDES, setting cache variable VAR accordingly. +ac_fn_c_check_member () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 +$as_echo_n "checking for $2.$3... " >&6; } +if eval \${$4+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main () +{ +static $2 ac_aggr; +if (ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$4=yes" +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main () +{ +static $2 ac_aggr; +if (sizeof ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$4=yes" +else + eval "$4=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$4 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_member +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.4.17, which was +generated by GNU Autoconf 2.68. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +LIBUNBOUND_CURRENT=3 +LIBUNBOUND_REVISION=1 +LIBUNBOUND_AGE=1 +# 1.0.0 had 0:12:0 +# 1.0.1 had 0:13:0 +# 1.0.2 had 0:14:0 +# 1.1.0 had 0:15:0 +# 1.1.1 had 0:16:0 +# 1.2.0 had 0:17:0 +# 1.2.1 had 0:18:0 +# 1.3.0 had 1:0:0 # ub_cancel and -export-symbols. +# 1.3.1 had 1:1:0 +# 1.3.2 had 1:2:0 +# 1.3.3 had 1:3:0 +# 1.3.4 had 1:4:0 +# 1.4.0-snapshots had 1:5:0 +# 1.4.0 had 1:5:0 (not 2:0:0) # ub_result.why_bogus +# 1.4.1 had 2:1:0 +# 1.4.2 had 2:2:0 +# 1.4.3 had 2:3:0 +# 1.4.4 had 2:4:0 +# 1.4.5 had 2:5:0 +# 1.4.6 had 2:6:0 +# 1.4.7 had 2:7:0 +# 1.4.8 had 2:8:0 +# 1.4.9 had 2:9:0 +# 1.4.10 had 2:10:0 +# 1.4.11 had 2:11:0 +# 1.4.12 had 2:12:0 +# 1.4.13 had 2:13:0 +# and 1.4.13p1 and 1.4.13.p2 +# 1.4.14 had 2:14:0 +# 1.4.15 had 3:0:1 # adds ub_version() +# 1.4.16 had 3:1:1 +# 1.4.17 had 3:2:1 + +# Current -- the number of the binary API that we're implementing +# Revision -- which iteration of the implementation of the binary +# API are we supplying? +# Age -- How many previous binary API versions do we also +# support? +# +# If we release a new version that does not change the binary API, +# increment Revision. +# +# If we release a new version that changes the binary API, but does +# not break programs compiled against the old binary API, increment +# Current and Age. Set Revision to 0, since this is the first +# implementation of the new API. +# +# Otherwise, we're changing the binary API and breaking bakward +# compatibility with old binaries. Increment Current. Set Age to 0, +# since we're backward compatible with no previous APIs. Set Revision +# to 0 too. + + + + +pretty_cmdline() { + cmdline="" + while test -n "$1"; do + cmdline="$cmdline '"`echo $1 | sed -e 's/\\\\/\\\\\\\\/g' | sed -e 's/"/\\\\"/g' `"'" + shift + done +} +pretty_cmdline $@ + +cat >>confdefs.h <<_ACEOF +#define CONFIGURE_BUILD_WITH "$cmdline" +_ACEOF + +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5 +$as_echo_n "checking target system type... " >&6; } +if ${ac_cv_target+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$target_alias" = x; then + ac_cv_target=$ac_cv_host +else + ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5 +$as_echo "$ac_cv_target" >&6; } +case $ac_cv_target in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;; +esac +target=$ac_cv_target +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_target +shift +target_cpu=$1 +target_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +target_os=$* +IFS=$ac_save_IFS +case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac + + +# The aliases save the names the user supplied, while $host etc. +# will get canonicalized. +test -n "$target_alias" && + test "$program_prefix$program_suffix$program_transform_name" = \ + NONENONEs,x,x, && + program_prefix=${target_alias}- + +cat >>confdefs.h <<_ACEOF +#define CONFIGURE_TARGET "$target" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define CONFIGURE_DATE "`date`" +_ACEOF + + +CFLAGS="$CFLAGS" +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + 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 eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default" +if test "x$ac_cv_header_minix_config_h" = xyes; then : + MINIX=yes +else + MINIX= +fi + + + if test "$MINIX" = yes; then + +$as_echo "#define _POSIX_SOURCE 1" >>confdefs.h + + +$as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h + + +$as_echo "#define _MINIX 1" >>confdefs.h + + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5 +$as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; } +if ${ac_cv_safe_to_define___extensions__+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +# define __EXTENSIONS__ 1 + $ac_includes_default +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_safe_to_define___extensions__=yes +else + ac_cv_safe_to_define___extensions__=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5 +$as_echo "$ac_cv_safe_to_define___extensions__" >&6; } + test $ac_cv_safe_to_define___extensions__ = yes && + $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h + + $as_echo "#define _ALL_SOURCE 1" >>confdefs.h + + $as_echo "#define _GNU_SOURCE 1" >>confdefs.h + + $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h + + $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h + + + + +case "$prefix" in + NONE) + prefix="/usr/local" + ;; +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" + else on_mingw="no"; fi +fi + +# +# Determine configuration file +# the eval is to evaluate shell expansion twice +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" +fi + +# Check whether --with-conf_file was given. +if test "${with_conf_file+set}" = set; then : + withval=$with_conf_file; ub_conf_file="$withval" +fi + + +hdr_config="`echo $ub_conf_file | sed -e 's/\\\\/\\\\\\\\/g'`" + + +cat >>confdefs.h <<_ACEOF +#define CONFIGFILE "$hdr_config" +_ACEOF + + +# Determine run, chroot directory and pidfile locations + +# Check whether --with-run-dir was given. +if test "${with_run_dir+set}" = set; then : + withval=$with_run_dir; UNBOUND_RUN_DIR="$withval" +else + if test $on_mingw = no; then + UNBOUND_RUN_DIR=`dirname "$ub_conf_file"` +else + UNBOUND_RUN_DIR="" +fi + +fi + + +hdr_run="`echo $UNBOUND_RUN_DIR | sed -e 's/\\\\/\\\\\\\\/g'`" + + +cat >>confdefs.h <<_ACEOF +#define RUN_DIR "$hdr_run" +_ACEOF + + + +# Check whether --with-chroot-dir was given. +if test "${with_chroot_dir+set}" = set; then : + withval=$with_chroot_dir; UNBOUND_CHROOT_DIR="$withval" +else + if test $on_mingw = no; then + UNBOUND_CHROOT_DIR="$UNBOUND_RUN_DIR" +else + UNBOUND_CHROOT_DIR="" +fi + +fi + + +hdr_chroot="`echo $UNBOUND_CHROOT_DIR | sed -e 's/\\\\/\\\\\\\\/g'`" + + +cat >>confdefs.h <<_ACEOF +#define CHROOT_DIR "$hdr_chroot" +_ACEOF + + + +# Check whether --with-share-dir was given. +if test "${with_share_dir+set}" = set; then : + withval=$with_share_dir; UNBOUND_SHARE_DIR="$withval" +else + UNBOUND_SHARE_DIR="$UNBOUND_RUN_DIR" +fi + + + +cat >>confdefs.h <<_ACEOF +#define SHARE_DIR "$UNBOUND_SHARE_DIR" +_ACEOF + + + +# Check whether --with-pidfile was given. +if test "${with_pidfile+set}" = set; then : + withval=$with_pidfile; UNBOUND_PIDFILE="$withval" +else + if test $on_mingw = no; then + UNBOUND_PIDFILE="$UNBOUND_RUN_DIR/unbound.pid" +else + UNBOUND_PIDFILE="" +fi + +fi + + +hdr_pid="`echo $UNBOUND_PIDFILE | sed -e 's/\\\\/\\\\\\\\/g'`" + + +cat >>confdefs.h <<_ACEOF +#define PIDFILE "$hdr_pid" +_ACEOF + + + +# Check whether --with-rootkey-file was given. +if test "${with_rootkey_file+set}" = set; then : + withval=$with_rootkey_file; UNBOUND_ROOTKEY_FILE="$withval" +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" +fi + +fi + + +hdr_rkey="`echo $UNBOUND_ROOTKEY_FILE | sed -e 's/\\\\/\\\\\\\\/g'`" + + +cat >>confdefs.h <<_ACEOF +#define ROOT_ANCHOR_FILE "$hdr_rkey" +_ACEOF + + + +# Check whether --with-rootcert-file was given. +if test "${with_rootcert_file+set}" = set; then : + withval=$with_rootcert_file; UNBOUND_ROOTCERT_FILE="$withval" +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" +fi + +fi + + +hdr_rpem="`echo $UNBOUND_ROOTCERT_FILE | sed -e 's/\\\\/\\\\\\\\/g'`" + + +cat >>confdefs.h <<_ACEOF +#define ROOT_CERT_FILE "$hdr_rpem" +_ACEOF + + + +# Check whether --with-username was given. +if test "${with_username+set}" = set; then : + withval=$with_username; UNBOUND_USERNAME="$withval" +else + UNBOUND_USERNAME="unbound" +fi + + + +cat >>confdefs.h <<_ACEOF +#define UB_USERNAME "$UNBOUND_USERNAME" +_ACEOF + + + +$as_echo "#define WINVER 0x0502" >>confdefs.h + +wnvs=`echo $PACKAGE_VERSION | sed -e 's/^[^0-9]*\([0-9]\)[^0-9]*\([0-9]\)[^0-9]*\([0-9]\)[^0-9]*\([0-9]\).*$/\1,\2,\3,\4/' -e 's/^[^0-9]*\([0-9]\)[^0-9]*\([0-9]\)[^0-9]*\([0-9]\)[^0-9]*$/\1,\2,\3,0/' ` + + +cat >>confdefs.h <<_ACEOF +#define RSRC_PACKAGE_VERSION $wnvs +_ACEOF + + +# Checks for typedefs, structures, and compiler characteristics. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 +$as_echo_n "checking for an ANSI C-conforming const... " >&6; } +if ${ac_cv_c_const+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +/* FIXME: Include the comments suggested by Paul. */ +#ifndef __cplusplus + /* Ultrix mips cc rejects this. */ + typedef int charset[2]; + const charset cs; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *pcpcc; + char **ppc; + /* NEC SVR4.0.2 mips cc rejects this. */ + struct point {int x, y;}; + static struct point const zero = {0,0}; + /* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in + an arm of an if-expression whose if-part is not a constant + expression */ + const char *g = "string"; + pcpcc = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++pcpcc; + ppc = (char**) pcpcc; + pcpcc = (char const *const *) ppc; + { /* SCO 3.2v4 cc rejects this. */ + char *t; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; + if (s) return 0; + } + { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; + } + { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; + } + { /* AIX XL C 1.02.0.0 rejects this saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; }; + struct s *b; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + if (!foo) return 0; + } + return !cs[0] && !zero.x; +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_const=yes +else + ac_cv_c_const=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_const" >&5 +$as_echo "$ac_cv_c_const" >&6; } +if test $ac_cv_c_const = no; then + +$as_echo "#define const /**/" >>confdefs.h + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -g" >&5 +$as_echo_n "checking whether $CC supports -g... " >&6; } +cache=`echo g | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -g -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +CFLAGS="$CFLAGS -g" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: + +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -O2" >&5 +$as_echo_n "checking whether $CC supports -O2... " >&6; } +cache=`echo O2 | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -O2 -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +CFLAGS="$CFLAGS -O2" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $CC dependency flag" >&5 +$as_echo_n "checking $CC dependency flag... " >&6; } +echo 'void f(){}' >conftest.c +if test "`$CC -MM conftest.c 2>&1`" = "conftest.o: conftest.c"; then + DEPFLAG="-MM" +else + if test "`$CC -xM1 conftest.c 2>&1`" = "conftest.o: conftest.c"; then + DEPFLAG="-xM1" + else + DEPFLAG="-MM" # dunno do something + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $DEPFLAG" >&5 +$as_echo "$DEPFLAG" >&6; } +rm -f conftest.c + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Werror" >&5 +$as_echo_n "checking whether $CC supports -Werror... " >&6; } +cache=`echo Werror | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -Werror -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +ERRFLAG="-Werror" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: +ERRFLAG="-errwarn" +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wall" >&5 +$as_echo_n "checking whether $CC supports -Wall... " >&6; } +cache=`echo Wall | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -Wall -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +ERRFLAG="$ERRFLAG -Wall" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: +ERRFLAG="$ERRFLAG -errfmt" +fi + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -std=c99" >&5 +$as_echo_n "checking whether $CC supports -std=c99... " >&6; } +cache=`echo std=c99 | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -std=c99 -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +C99FLAG="-std=c99" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: + +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -xc99" >&5 +$as_echo_n "checking whether $CC supports -xc99... " >&6; } +cache=`echo xc99 | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -xc99 -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +C99FLAG="-xc99" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: + +fi + + +for ac_header in getopt.h time.h +do : + 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 eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we need $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_ALL_SOURCE as a flag for $CC" >&5 +$as_echo_n "checking whether we need $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_ALL_SOURCE as a flag for $CC... " >&6; } +cache=`$as_echo "$C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_ALL_SOURCE" | $as_tr_sh` +if eval \${cv_prog_cc_flag_needed_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo ' +#include "confdefs.h" +#include +#include +#include +#ifdef HAVE_TIME_H +#include +#endif +#include +#include +#ifdef HAVE_GETOPT_H +#include +#endif + +int test() { + int a; + char **opts = NULL; + struct timeval tv; + char *t; + time_t time = 0; + char *buf = NULL; + const char* str = NULL; + struct msghdr msg; + msg.msg_control = 0; + t = ctime_r(&time, buf); + tv.tv_usec = 10; + srandom(32); + a = getopt(2, opts, "a"); + a = isascii(32); + str = gai_strerror(0); + if(str && t && tv.tv_usec && msg.msg_control) + a = 0; + return a; +} +' > conftest.c +echo 'void f(){}' >>conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=no" +else + +if test -z "`$CC $CPPFLAGS $CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_ALL_SOURCE $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=yes" +else +eval "cv_prog_cc_flag_needed_$cache=fail" +#echo 'Test with flag fails too!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_ALL_SOURCE $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_ALL_SOURCE $ERRFLAG -c conftest.c 2>&1` +#exit 1 +fi + +fi +rm -f conftest conftest.c conftest.o + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +CFLAGS="$CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_ALL_SOURCE" +else +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = no"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +#echo 'Test with flag is no!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_ALL_SOURCE $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_ALL_SOURCE $ERRFLAG -c conftest.c 2>&1` +#exit 1 +: + +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +: + +fi +fi + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we need $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE as a flag for $CC" >&5 +$as_echo_n "checking whether we need $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE as a flag for $CC... " >&6; } +cache=`$as_echo "$C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE" | $as_tr_sh` +if eval \${cv_prog_cc_flag_needed_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo ' +#include "confdefs.h" +#include +#include +#include +#ifdef HAVE_TIME_H +#include +#endif +#include +#include +#ifdef HAVE_GETOPT_H +#include +#endif + +int test() { + int a; + char **opts = NULL; + struct timeval tv; + char *t; + time_t time = 0; + char *buf = NULL; + const char* str = NULL; + struct msghdr msg; + msg.msg_control = 0; + t = ctime_r(&time, buf); + tv.tv_usec = 10; + srandom(32); + a = getopt(2, opts, "a"); + a = isascii(32); + str = gai_strerror(0); + if(str && t && tv.tv_usec && msg.msg_control) + a = 0; + return a; +} +' > conftest.c +echo 'void f(){}' >>conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=no" +else + +if test -z "`$CC $CPPFLAGS $CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=yes" +else +eval "cv_prog_cc_flag_needed_$cache=fail" +#echo 'Test with flag fails too!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE $ERRFLAG -c conftest.c 2>&1` +#exit 1 +fi + +fi +rm -f conftest conftest.c conftest.o + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +CFLAGS="$CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE" +else +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = no"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +#echo 'Test with flag is no!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE $ERRFLAG -c conftest.c 2>&1` +#exit 1 +: + +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +: + +fi +fi + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we need $C99FLAG as a flag for $CC" >&5 +$as_echo_n "checking whether we need $C99FLAG as a flag for $CC... " >&6; } +cache=`$as_echo "$C99FLAG" | $as_tr_sh` +if eval \${cv_prog_cc_flag_needed_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo ' +#include +#include +int test() { + int a = 0; + return a; +} +' > conftest.c +echo 'void f(){}' >>conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=no" +else + +if test -z "`$CC $CPPFLAGS $CFLAGS $C99FLAG $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=yes" +else +eval "cv_prog_cc_flag_needed_$cache=fail" +#echo 'Test with flag fails too!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS $C99FLAG $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS $C99FLAG $ERRFLAG -c conftest.c 2>&1` +#exit 1 +fi + +fi +rm -f conftest conftest.c conftest.o + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +CFLAGS="$CFLAGS $C99FLAG" +else +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = no"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +#echo 'Test with flag is no!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS $C99FLAG $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS $C99FLAG $ERRFLAG -c conftest.c 2>&1` +#exit 1 +: + +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +: + +fi +fi + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we need -D_BSD_SOURCE as a flag for $CC" >&5 +$as_echo_n "checking whether we need -D_BSD_SOURCE as a flag for $CC... " >&6; } +cache=_D_BSD_SOURCE +if eval \${cv_prog_cc_flag_needed_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo ' +#include + +int test() { + int a; + a = isascii(32); + return a; +} +' > conftest.c +echo 'void f(){}' >>conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=no" +else + +if test -z "`$CC $CPPFLAGS $CFLAGS -D_BSD_SOURCE $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=yes" +else +eval "cv_prog_cc_flag_needed_$cache=fail" +#echo 'Test with flag fails too!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS -D_BSD_SOURCE $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS -D_BSD_SOURCE $ERRFLAG -c conftest.c 2>&1` +#exit 1 +fi + +fi +rm -f conftest conftest.c conftest.o + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +CFLAGS="$CFLAGS -D_BSD_SOURCE" +else +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = no"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +#echo 'Test with flag is no!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS -D_BSD_SOURCE $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS -D_BSD_SOURCE $ERRFLAG -c conftest.c 2>&1` +#exit 1 +: + +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +: + +fi +fi + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we need -D_GNU_SOURCE as a flag for $CC" >&5 +$as_echo_n "checking whether we need -D_GNU_SOURCE as a flag for $CC... " >&6; } +cache=_D_GNU_SOURCE +if eval \${cv_prog_cc_flag_needed_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo ' +#include + +int test() { + struct in6_pktinfo inf; + int a = (int)sizeof(inf); + return a; +} +' > conftest.c +echo 'void f(){}' >>conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=no" +else + +if test -z "`$CC $CPPFLAGS $CFLAGS -D_GNU_SOURCE $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=yes" +else +eval "cv_prog_cc_flag_needed_$cache=fail" +#echo 'Test with flag fails too!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS -D_GNU_SOURCE $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS -D_GNU_SOURCE $ERRFLAG -c conftest.c 2>&1` +#exit 1 +fi + +fi +rm -f conftest conftest.c conftest.o + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +CFLAGS="$CFLAGS -D_GNU_SOURCE" +else +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = no"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +#echo 'Test with flag is no!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS -D_GNU_SOURCE $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS -D_GNU_SOURCE $ERRFLAG -c conftest.c 2>&1` +#exit 1 +: + +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +: + +fi +fi + + +# check again for GNU_SOURCE for setresgid. May fail if setresgid +# is not available at all. -D_FRSRESGID is to make this check unique. +# otherwise we would get the previous cached result. + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we need -D_GNU_SOURCE -D_FRSRESGID as a flag for $CC" >&5 +$as_echo_n "checking whether we need -D_GNU_SOURCE -D_FRSRESGID as a flag for $CC... " >&6; } +cache=_D_GNU_SOURCE__D_FRSRESGID +if eval \${cv_prog_cc_flag_needed_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo ' +#include + +int test() { + int a = setresgid(0,0,0); + a = setresuid(0,0,0); + return a; +} +' > conftest.c +echo 'void f(){}' >>conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=no" +else + +if test -z "`$CC $CPPFLAGS $CFLAGS -D_GNU_SOURCE -D_FRSRESGID $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=yes" +else +eval "cv_prog_cc_flag_needed_$cache=fail" +#echo 'Test with flag fails too!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS -D_GNU_SOURCE -D_FRSRESGID $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS -D_GNU_SOURCE -D_FRSRESGID $ERRFLAG -c conftest.c 2>&1` +#exit 1 +fi + +fi +rm -f conftest conftest.c conftest.o + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +CFLAGS="$CFLAGS -D_GNU_SOURCE" +else +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = no"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +#echo 'Test with flag is no!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS -D_GNU_SOURCE -D_FRSRESGID $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS -D_GNU_SOURCE -D_FRSRESGID $ERRFLAG -c conftest.c 2>&1` +#exit 1 +: + +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +: + +fi +fi + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we need -D_POSIX_C_SOURCE=200112 as a flag for $CC" >&5 +$as_echo_n "checking whether we need -D_POSIX_C_SOURCE=200112 as a flag for $CC... " >&6; } +cache=`$as_echo "-D_POSIX_C_SOURCE=200112" | $as_tr_sh` +if eval \${cv_prog_cc_flag_needed_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo ' +#include "confdefs.h" +#ifdef HAVE_TIME_H +#include +#endif +#include + +int test() { + int a = 0; + char *t; + time_t time = 0; + char *buf = NULL; + const char* str = NULL; + t = ctime_r(&time, buf); + str = gai_strerror(0); + if(t && str) + a = 0; + return a; +} +' > conftest.c +echo 'void f(){}' >>conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=no" +else + +if test -z "`$CC $CPPFLAGS $CFLAGS -D_POSIX_C_SOURCE=200112 $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=yes" +else +eval "cv_prog_cc_flag_needed_$cache=fail" +#echo 'Test with flag fails too!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS -D_POSIX_C_SOURCE=200112 $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS -D_POSIX_C_SOURCE=200112 $ERRFLAG -c conftest.c 2>&1` +#exit 1 +fi + +fi +rm -f conftest conftest.c conftest.o + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +CFLAGS="$CFLAGS -D_POSIX_C_SOURCE=200112" +else +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = no"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +#echo 'Test with flag is no!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS -D_POSIX_C_SOURCE=200112 $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS -D_POSIX_C_SOURCE=200112 $ERRFLAG -c conftest.c 2>&1` +#exit 1 +: + +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +: + +fi +fi + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we need -D__EXTENSIONS__ as a flag for $CC" >&5 +$as_echo_n "checking whether we need -D__EXTENSIONS__ as a flag for $CC... " >&6; } +cache=_D__EXTENSIONS__ +if eval \${cv_prog_cc_flag_needed_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo ' +#include "confdefs.h" +#include +#include +#include +#ifdef HAVE_TIME_H +#include +#endif +#include +#ifdef HAVE_GETOPT_H +#include +#endif + +int test() { + int a; + char **opts = NULL; + struct timeval tv; + tv.tv_usec = 10; + srandom(32); + a = getopt(2, opts, "a"); + a = isascii(32); + if(tv.tv_usec) + a = 0; + return a; +} +' > conftest.c +echo 'void f(){}' >>conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=no" +else + +if test -z "`$CC $CPPFLAGS $CFLAGS -D__EXTENSIONS__ $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=yes" +else +eval "cv_prog_cc_flag_needed_$cache=fail" +#echo 'Test with flag fails too!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS -D__EXTENSIONS__ $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS -D__EXTENSIONS__ $ERRFLAG -c conftest.c 2>&1` +#exit 1 +fi + +fi +rm -f conftest conftest.c conftest.o + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +CFLAGS="$CFLAGS -D__EXTENSIONS__" +else +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = no"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +#echo 'Test with flag is no!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS -D__EXTENSIONS__ $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS -D__EXTENSIONS__ $ERRFLAG -c conftest.c 2>&1` +#exit 1 +: + +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +: + +fi +fi + + + + +# debug mode flags warnings +# Check whether --enable-checking was given. +if test "${enable_checking+set}" = set; then : + enableval=$enable_checking; +fi + +# Check whether --enable-debug was given. +if test "${enable_debug+set}" = set; then : + enableval=$enable_debug; +fi + +if test "$enable_debug" = "yes"; then debug_enabled="$enable_debug"; +else debug_enabled="$enable_checking"; fi + +case "$debug_enabled" in + yes) + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -W" >&5 +$as_echo_n "checking whether $CC supports -W... " >&6; } +cache=`echo W | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -W -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +CFLAGS="$CFLAGS -W" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: + +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wall" >&5 +$as_echo_n "checking whether $CC supports -Wall... " >&6; } +cache=`echo Wall | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -Wall -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +CFLAGS="$CFLAGS -Wall" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: + +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wextra" >&5 +$as_echo_n "checking whether $CC supports -Wextra... " >&6; } +cache=`echo Wextra | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -Wextra -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +CFLAGS="$CFLAGS -Wextra" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: + +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wdeclaration-after-statement" >&5 +$as_echo_n "checking whether $CC supports -Wdeclaration-after-statement... " >&6; } +cache=`echo Wdeclaration-after-statement | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -Wdeclaration-after-statement -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +CFLAGS="$CFLAGS -Wdeclaration-after-statement" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: + +fi + + +$as_echo "#define UNBOUND_DEBUG /**/" >>confdefs.h + + ;; + no|*) + # nothing to do. + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports -flto" >&5 +$as_echo_n "checking if $CC supports -flto... " >&6; } +BAKCFLAGS="$CFLAGS" +CFLAGS="$CFLAGS -flto" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + if $CC $CFLAGS -o conftest conftest.c 2>&1 | grep "warning: no debug symbols in executable" >/dev/null; then + CFLAGS="$BAKCFLAGS" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + fi + rm -f conftest conftest.c conftest.o + +else + CFLAGS="$BAKCFLAGS" ; { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 +$as_echo_n "checking for inline... " >&6; } +if ${ac_cv_c_inline+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __cplusplus +typedef int foo_t; +static $ac_kw foo_t static_foo () {return 0; } +$ac_kw foo_t foo () {return 0; } +#endif + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_inline=$ac_kw +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test "$ac_cv_c_inline" != no && break +done + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 +$as_echo "$ac_cv_c_inline" >&6; } + +case $ac_cv_c_inline in + inline | yes) ;; + *) + case $ac_cv_c_inline in + no) ac_val=;; + *) ac_val=$ac_cv_c_inline;; + esac + cat >>confdefs.h <<_ACEOF +#ifndef __cplusplus +#define inline $ac_val +#endif +_ACEOF + ;; +esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler (${CC-cc}) accepts the \"format\" attribute" >&5 +$as_echo_n "checking whether the C compiler (${CC-cc}) accepts the \"format\" attribute... " >&6; } +if ${ac_cv_c_format_attribute+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_format_attribute=no +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +void f (char *format, ...) __attribute__ ((format (printf, 1, 2))); +void (*pf) (char *format, ...) __attribute__ ((format (printf, 1, 2))); + +int +main () +{ + + f ("%s", "str"); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_format_attribute="yes" +else + ac_cv_c_format_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_format_attribute" >&5 +$as_echo "$ac_cv_c_format_attribute" >&6; } +if test $ac_cv_c_format_attribute = yes; then + +$as_echo "#define HAVE_ATTR_FORMAT 1" >>confdefs.h + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler (${CC-cc}) accepts the \"unused\" attribute" >&5 +$as_echo_n "checking whether the C compiler (${CC-cc}) accepts the \"unused\" attribute... " >&6; } +if ${ac_cv_c_unused_attribute+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_unused_attribute=no +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +void f (char *u __attribute__((unused))); + +int +main () +{ + + f ("x"); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_unused_attribute="yes" +else + ac_cv_c_unused_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_unused_attribute" >&5 +$as_echo "$ac_cv_c_unused_attribute" >&6; } +if test $ac_cv_c_unused_attribute = yes; then + +$as_echo "#define HAVE_ATTR_UNUSED 1" >>confdefs.h + +fi + + +if test "$srcdir" != "."; then + CPPFLAGS="$CPPFLAGS -I$srcdir" +fi + + + +for ac_prog in flex lex +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LEX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LEX"; then + ac_cv_prog_LEX="$LEX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_LEX="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LEX=$ac_cv_prog_LEX +if test -n "$LEX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LEX" >&5 +$as_echo "$LEX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$LEX" && break +done +test -n "$LEX" || LEX=":" + +if test "x$LEX" != "x:"; then + cat >conftest.l <<_ACEOF +%% +a { ECHO; } +b { REJECT; } +c { yymore (); } +d { yyless (1); } +e { yyless (input () != 0); } +f { unput (yytext[0]); } +. { BEGIN INITIAL; } +%% +#ifdef YYTEXT_POINTER +extern char *yytext; +#endif +int +main (void) +{ + return ! yylex () + ! yywrap (); +} +_ACEOF +{ { ac_try="$LEX conftest.l" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$LEX conftest.l") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking lex output file root" >&5 +$as_echo_n "checking lex output file root... " >&6; } +if ${ac_cv_prog_lex_root+:} false; then : + $as_echo_n "(cached) " >&6 +else + +if test -f lex.yy.c; then + ac_cv_prog_lex_root=lex.yy +elif test -f lexyy.c; then + ac_cv_prog_lex_root=lexyy +else + as_fn_error $? "cannot find output from $LEX; giving up" "$LINENO" 5 +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_root" >&5 +$as_echo "$ac_cv_prog_lex_root" >&6; } +LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root + +if test -z "${LEXLIB+set}"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking lex library" >&5 +$as_echo_n "checking lex library... " >&6; } +if ${ac_cv_lib_lex+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ac_save_LIBS=$LIBS + ac_cv_lib_lex='none needed' + for ac_lib in '' -lfl -ll; do + LIBS="$ac_lib $ac_save_LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +`cat $LEX_OUTPUT_ROOT.c` +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_lex=$ac_lib +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + test "$ac_cv_lib_lex" != 'none needed' && break + done + LIBS=$ac_save_LIBS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lex" >&5 +$as_echo "$ac_cv_lib_lex" >&6; } + test "$ac_cv_lib_lex" != 'none needed' && LEXLIB=$ac_cv_lib_lex +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether yytext is a pointer" >&5 +$as_echo_n "checking whether yytext is a pointer... " >&6; } +if ${ac_cv_prog_lex_yytext_pointer+:} false; then : + $as_echo_n "(cached) " >&6 +else + # POSIX says lex can declare yytext either as a pointer or an array; the +# default is implementation-dependent. Figure out which it is, since +# not all implementations provide the %pointer and %array declarations. +ac_cv_prog_lex_yytext_pointer=no +ac_save_LIBS=$LIBS +LIBS="$LEXLIB $ac_save_LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #define YYTEXT_POINTER 1 +`cat $LEX_OUTPUT_ROOT.c` +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_prog_lex_yytext_pointer=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_save_LIBS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_yytext_pointer" >&5 +$as_echo "$ac_cv_prog_lex_yytext_pointer" >&6; } +if test $ac_cv_prog_lex_yytext_pointer = yes; then + +$as_echo "#define YYTEXT_POINTER 1" >>confdefs.h + +fi +rm -f conftest.l $LEX_OUTPUT_ROOT.c + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for yylex_destroy" >&5 +$as_echo_n "checking for yylex_destroy... " >&6; } + if echo %% | $LEX -t 2>&1 | grep yylex_destroy >/dev/null 2>&1; then + +$as_echo "#define LEX_HAS_YYLEX_DESTROY 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; }; fi + +for ac_prog in 'bison -y' byacc +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_YACC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$YACC"; then + ac_cv_prog_YACC="$YACC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_YACC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +YACC=$ac_cv_prog_YACC +if test -n "$YACC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $YACC" >&5 +$as_echo "$YACC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$YACC" && break +done +test -n "$YACC" || YACC="yacc" + +# Extract the first word of "doxygen", so it can be a program name with args. +set dummy doxygen; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_doxygen+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$doxygen"; then + ac_cv_prog_doxygen="$doxygen" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_doxygen="doxygen" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +doxygen=$ac_cv_prog_doxygen +if test -n "$doxygen"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $doxygen" >&5 +$as_echo "$doxygen" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + + +# skip these tests, we do not need them. + + + + + + + + +# always use ./libtool unless override from commandline (libtool=mylibtool) +if test -z "$libtool"; then + libtool="./libtool" +fi + +# avoid libtool max commandline length test on systems that fork slowly. + +if echo "$host_os" | grep "sunos4" >/dev/null; then + lt_cv_sys_max_cmd_len=32750; +fi +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. +set dummy ${ac_tool_prefix}ar; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $AR in + [\\/]* | ?:[\\/]*) + ac_cv_path_AR="$AR" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_AR="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +AR=$ac_cv_path_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_AR"; then + ac_pt_AR=$AR + # Extract the first word of "ar", so it can be a program name with args. +set dummy ar; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_AR in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_AR="$ac_pt_AR" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_ac_pt_AR="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_AR=$ac_cv_path_ac_pt_AR +if test -n "$ac_pt_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_AR" >&5 +$as_echo "$ac_pt_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_pt_AR + fi +else + AR="$ac_cv_path_AR" +fi + +if test $AR = false; then + as_fn_error $? "Cannot find 'ar', please extend PATH to include it" "$LINENO" 5 +fi + +case `pwd` in + *\ * | *\ *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 +$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; +esac + + + +macro_version='2.4' +macro_revision='1.3293' + + + + + + + + + + + + + +ltmain="$ac_aux_dir/ltmain.sh" + +# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 +$as_echo_n "checking how to print strings... " >&6; } +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "" +} + +case "$ECHO" in + printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 +$as_echo "printf" >&6; } ;; + print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 +$as_echo "print -r" >&6; } ;; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 +$as_echo "cat" >&6; } ;; +esac + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_SED" && $as_test_x "$ac_path_SED"; } || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 +$as_echo_n "checking for fgrep... " >&6; } +if ${ac_cv_path_FGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 + then ac_cv_path_FGREP="$GREP -F" + else + if test -z "$FGREP"; then + ac_path_FGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in fgrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_FGREP" && $as_test_x "$ac_path_FGREP"; } || continue +# Check for GNU ac_path_FGREP and select it if it is found. + # Check for GNU $ac_path_FGREP +case `"$ac_path_FGREP" --version 2>&1` in +*GNU*) + ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'FGREP' >> "conftest.nl" + "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_FGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_FGREP="$ac_path_FGREP" + ac_path_FGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_FGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_FGREP"; then + as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_FGREP=$FGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 +$as_echo "$ac_cv_path_FGREP" >&6; } + FGREP="$ac_cv_path_FGREP" + + +test -z "$GREP" && GREP=grep + + + + + + + + + + + + + + + + + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${lt_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${lt_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 +$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } +if ${lt_cv_path_NM+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + : ${lt_cv_path_NM=no} +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 +$as_echo "$lt_cv_path_NM" >&6; } +if test "$lt_cv_path_NM" != "no"; then + NM="$lt_cv_path_NM" +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + if test -n "$ac_tool_prefix"; then + for ac_prog in dumpbin "link -dump" + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DUMPBIN"; then + ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DUMPBIN=$ac_cv_prog_DUMPBIN +if test -n "$DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 +$as_echo "$DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$DUMPBIN" && break + done +fi +if test -z "$DUMPBIN"; then + ac_ct_DUMPBIN=$DUMPBIN + for ac_prog in dumpbin "link -dump" +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DUMPBIN"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN +if test -n "$ac_ct_DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 +$as_echo "$ac_ct_DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_DUMPBIN" && break +done + + if test "x$ac_ct_DUMPBIN" = x; then + DUMPBIN=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DUMPBIN=$ac_ct_DUMPBIN + fi +fi + + case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols" + ;; + *) + DUMPBIN=: + ;; + esac + fi + + if test "$DUMPBIN" != ":"; then + NM="$DUMPBIN" + fi +fi +test -z "$NM" && NM=nm + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 +$as_echo_n "checking the name lister ($NM) interface... " >&6; } +if ${lt_cv_nm_interface+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: output\"" >&5) + cat conftest.out >&5 + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 +$as_echo "$lt_cv_nm_interface" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 +$as_echo_n "checking whether ln -s works... " >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 +$as_echo "no, using $LN_S" >&6; } +fi + +# find the maximum length of command line arguments +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 +$as_echo_n "checking the maximum length of command line arguments... " >&6; } +if ${lt_cv_sys_max_cmd_len+:} false; then : + $as_echo_n "(cached) " >&6 +else + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8 ; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test "X"`func_fallback_echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac + +fi + +if test -n $lt_cv_sys_max_cmd_len ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 +$as_echo "$lt_cv_sys_max_cmd_len" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } +fi +max_cmd_len=$lt_cv_sys_max_cmd_len + + + + + + +: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 +$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } +# Try some XSI features +xsi_shell=no +( _lt_dummy="a/b/c" + test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ + = c,a/b,b/c, \ + && eval 'test $(( 1 + 1 )) -eq 2 \ + && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ + && xsi_shell=yes +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 +$as_echo "$xsi_shell" >&6; } + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 +$as_echo_n "checking whether the shell understands \"+=\"... " >&6; } +lt_shell_append=no +( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ + >/dev/null 2>&1 \ + && lt_shell_append=yes +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 +$as_echo "$lt_shell_append" >&6; } + + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi + + + + + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 +$as_echo_n "checking how to convert $build file names to $host format... " >&6; } +if ${lt_cv_to_host_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac + +fi + +to_host_file_cmd=$lt_cv_to_host_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 +$as_echo "$lt_cv_to_host_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 +$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } +if ${lt_cv_to_tool_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + #assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac + +fi + +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 +$as_echo "$lt_cv_to_tool_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 +$as_echo_n "checking for $LD option to reload object files... " >&6; } +if ${lt_cv_ld_reload_flag+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_reload_flag='-r' +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 +$as_echo "$lt_cv_ld_reload_flag" >&6; } +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + if test "$GCC" != yes; then + reload_cmds=false + fi + ;; + darwin*) + if test "$GCC" = yes; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' + else + reload_cmds='$LD$reload_flag -o $output$reload_objs' + fi + ;; +esac + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + +test -z "$OBJDUMP" && OBJDUMP=objdump + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 +$as_echo_n "checking how to recognize dependent libraries... " >&6; } +if ${lt_cv_deplibs_check_method+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# `unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# which responds to the $file_magic_cmd with a given extended regex. +# If you have `file' or equivalent on your system and you're not sure +# whether `pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[4-9]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[45]*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. + if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[3-9]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 +$as_echo "$lt_cv_deplibs_check_method" >&6; } + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + + + + + + + + + + + + + + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DLLTOOL=$ac_cv_prog_DLLTOOL +if test -n "$DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 +$as_echo "$DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DLLTOOL"; then + ac_ct_DLLTOOL=$DLLTOOL + # Extract the first word of "dlltool", so it can be a program name with args. +set dummy dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DLLTOOL"; then + ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_DLLTOOL="dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL +if test -n "$ac_ct_DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 +$as_echo "$ac_ct_DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DLLTOOL" = x; then + DLLTOOL="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DLLTOOL=$ac_ct_DLLTOOL + fi +else + DLLTOOL="$ac_cv_prog_DLLTOOL" +fi + +test -z "$DLLTOOL" && DLLTOOL=dlltool + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 +$as_echo_n "checking how to associate runtime and link libraries... " >&6; } +if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh + # decide which to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd="$ECHO" + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 +$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + + + + + + + +if test -n "$ac_tool_prefix"; then + for ac_prog in ar + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AR="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AR" && break + done +fi +if test -z "$AR"; then + ac_ct_AR=$AR + for ac_prog in ar +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_AR="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_AR" && break +done + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +fi + +: ${AR=ar} +: ${AR_FLAGS=cru} + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 +$as_echo_n "checking for archiver @FILE support... " >&6; } +if ${lt_cv_ar_at_file+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ar_at_file=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test "$ac_status" -eq 0; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test "$ac_status" -ne 0; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 +$as_echo "$lt_cv_ar_at_file" >&6; } + +if test "x$lt_cv_ar_at_file" = xno; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +test -z "$STRIP" && STRIP=: + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +test -z "$RANLIB" && RANLIB=: + + + + + + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac + + + + + + + + + + + + + + + + + + + + + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + + + + + + + + + + + + + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 +$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } +if ${lt_cv_sys_global_symbol_pipe+:} false; then : + $as_echo_n "(cached) " >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[ABCDGISTW]' + ;; +hpux*) + if test "$host_cpu" = ia64; then + symcode='[ABCDEGRST]' + fi + ;; +irix* | nonstopux*) + symcode='[BCDEGRST]' + ;; +osf*) + symcode='[BCDEGQRST]' + ;; +solaris*) + symcode='[BDRT]' + ;; +sco3.2v5*) + symcode='[DT]' + ;; +sysv4.2uw2*) + symcode='[DT]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[ABDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function + # and D for any global variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK '"\ +" {last_section=section; section=\$ 3};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ +" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ +" s[1]~/^[@?]/{print s[1], s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Now try to grab the symbols. + nlist=conftest.nm + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 + (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +/* DATA imports from DLLs on WIN32 con't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined(__osf__) +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 +$as_echo_n "checking for sysroot... " >&6; } + +# Check whether --with-sysroot was given. +if test "${with_sysroot+set}" = set; then : + withval=$with_sysroot; +else + with_sysroot=no +fi + + +lt_sysroot= +case ${with_sysroot} in #( + yes) + if test "$GCC" = yes; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${with_sysroot}" >&5 +$as_echo "${with_sysroot}" >&6; } + as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 + ;; +esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 +$as_echo "${lt_sysroot:-no}" >&6; } + + + + + +# Check whether --enable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then : + enableval=$enable_libtool_lock; +fi + +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 +$as_echo_n "checking whether the C compiler needs -belf... " >&6; } +if ${lt_cv_cc_needs_belf+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_cc_needs_belf=yes +else + lt_cv_cc_needs_belf=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 +$as_echo "$lt_cv_cc_needs_belf" >&6; } + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +sparc*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) LD="${LD-ld} -m elf64_sparc" ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks="$enable_libtool_lock" + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. +set dummy ${ac_tool_prefix}mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$MANIFEST_TOOL"; then + ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL +if test -n "$MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 +$as_echo "$MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_MANIFEST_TOOL"; then + ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL + # Extract the first word of "mt", so it can be a program name with args. +set dummy mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_MANIFEST_TOOL"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL +if test -n "$ac_ct_MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 +$as_echo "$ac_ct_MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_MANIFEST_TOOL" = x; then + MANIFEST_TOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL + fi +else + MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" +fi + +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 +$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } +if ${lt_cv_path_mainfest_tool+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&5 + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 +$as_echo "$lt_cv_path_mainfest_tool" >&6; } +if test "x$lt_cv_path_mainfest_tool" != xyes; then + MANIFEST_TOOL=: +fi + + + + + + + case $host_os in + rhapsody* | darwin*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. +set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DSYMUTIL"; then + ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DSYMUTIL=$ac_cv_prog_DSYMUTIL +if test -n "$DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 +$as_echo "$DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DSYMUTIL"; then + ac_ct_DSYMUTIL=$DSYMUTIL + # Extract the first word of "dsymutil", so it can be a program name with args. +set dummy dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DSYMUTIL"; then + ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL +if test -n "$ac_ct_DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 +$as_echo "$ac_ct_DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DSYMUTIL" = x; then + DSYMUTIL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DSYMUTIL=$ac_ct_DSYMUTIL + fi +else + DSYMUTIL="$ac_cv_prog_DSYMUTIL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. +set dummy ${ac_tool_prefix}nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NMEDIT"; then + ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +NMEDIT=$ac_cv_prog_NMEDIT +if test -n "$NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 +$as_echo "$NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_NMEDIT"; then + ac_ct_NMEDIT=$NMEDIT + # Extract the first word of "nmedit", so it can be a program name with args. +set dummy nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_NMEDIT"; then + ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_NMEDIT="nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT +if test -n "$ac_ct_NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 +$as_echo "$ac_ct_NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_NMEDIT" = x; then + NMEDIT=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + NMEDIT=$ac_ct_NMEDIT + fi +else + NMEDIT="$ac_cv_prog_NMEDIT" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. +set dummy ${ac_tool_prefix}lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LIPO"; then + ac_cv_prog_LIPO="$LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_LIPO="${ac_tool_prefix}lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LIPO=$ac_cv_prog_LIPO +if test -n "$LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 +$as_echo "$LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_LIPO"; then + ac_ct_LIPO=$LIPO + # Extract the first word of "lipo", so it can be a program name with args. +set dummy lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_LIPO"; then + ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_LIPO="lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO +if test -n "$ac_ct_LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 +$as_echo "$ac_ct_LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_LIPO" = x; then + LIPO=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + LIPO=$ac_ct_LIPO + fi +else + LIPO="$ac_cv_prog_LIPO" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL"; then + ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_OTOOL="${ac_tool_prefix}otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL=$ac_cv_prog_OTOOL +if test -n "$OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 +$as_echo "$OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL"; then + ac_ct_OTOOL=$OTOOL + # Extract the first word of "otool", so it can be a program name with args. +set dummy otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL"; then + ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_OTOOL="otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL +if test -n "$ac_ct_OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 +$as_echo "$ac_ct_OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL" = x; then + OTOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL=$ac_ct_OTOOL + fi +else + OTOOL="$ac_cv_prog_OTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL64"; then + ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL64=$ac_cv_prog_OTOOL64 +if test -n "$OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 +$as_echo "$OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL64"; then + ac_ct_OTOOL64=$OTOOL64 + # Extract the first word of "otool64", so it can be a program name with args. +set dummy otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL64"; then + ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_OTOOL64="otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 +if test -n "$ac_ct_OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 +$as_echo "$ac_ct_OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL64" = x; then + OTOOL64=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL64=$ac_ct_OTOOL64 + fi +else + OTOOL64="$ac_cv_prog_OTOOL64" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 +$as_echo_n "checking for -single_module linker flag... " >&6; } +if ${lt_cv_apple_cc_single_mod+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_apple_cc_single_mod=no + if test -z "${LT_MULTI_MODULE}"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&5 + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 +$as_echo "$lt_cv_apple_cc_single_mod" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 +$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } +if ${lt_cv_ld_exported_symbols_list+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_ld_exported_symbols_list=yes +else + lt_cv_ld_exported_symbols_list=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 +$as_echo "$lt_cv_ld_exported_symbols_list" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 +$as_echo_n "checking for -force_load linker flag... " >&6; } +if ${lt_cv_ld_force_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 + echo "$AR cru libconftest.a conftest.o" >&5 + $AR cru libconftest.a conftest.o 2>&5 + echo "$RANLIB libconftest.a" >&5 + $RANLIB libconftest.a 2>&5 + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -f conftest && test ! -s conftest.err && test $_lt_result = 0 && $GREP forced_load conftest 2>&1 >/dev/null; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&5 + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 +$as_echo "$lt_cv_ld_force_load" >&6; } + case $host_os in + rhapsody* | darwin1.[012]) + _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[91]*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + 10.[012]*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test "$lt_cv_apple_cc_single_mod" = "yes"; then + _lt_dar_single_mod='$single_module' + fi + if test "$lt_cv_ld_exported_symbols_list" = "yes"; then + _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac + +for ac_header in dlfcn.h +do : + ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default +" +if test "x$ac_cv_header_dlfcn_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DLFCN_H 1 +_ACEOF + +fi + +done + + + + + + + +# Set options + + + + enable_dlopen=no + + + enable_win32_dll=no + + + # Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then : + enableval=$enable_shared; p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_shared=yes +fi + + + + + + + + + + # Check whether --enable-static was given. +if test "${enable_static+set}" = set; then : + enableval=$enable_static; p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_static=yes +fi + + + + + + + + + + +# Check whether --with-pic was given. +if test "${with_pic+set}" = set; then : + withval=$with_pic; pic_mode="$withval" +else + pic_mode=default +fi + + +test -z "$pic_mode" && pic_mode=default + + + + + + + + # Check whether --enable-fast-install was given. +if test "${enable_fast_install+set}" = set; then : + enableval=$enable_fast_install; p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_fast_install=yes +fi + + + + + + + + + + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ltmain" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + + + + + + + + + + + + + + + + + + + + + + + + + + +test -z "$LN_S" && LN_S="ln -s" + + + + + + + + + + + + + + +if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 +$as_echo_n "checking for objdir... " >&6; } +if ${lt_cv_objdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 +$as_echo "$lt_cv_objdir" >&6; } +objdir=$lt_cv_objdir + + + + + +cat >>confdefs.h <<_ACEOF +#define LT_OBJDIR "$lt_cv_objdir/" +_ACEOF + + + + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld="$lt_cv_prog_gnu_ld" + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` + + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 +$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/${ac_tool_prefix}file; then + lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + + +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 +$as_echo_n "checking for file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/file; then + lt_cv_path_MAGIC_CMD="$ac_dir/file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + else + MAGIC_CMD=: + fi +fi + + fi + ;; +esac + +# Use C for the default configuration in the libtool script + +lt_save_CC="$CC" +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +objext=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* + +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* + + +if test -n "$compiler"; then + +lt_prog_compiler_no_builtin_flag= + +if test "$GCC" = yes; then + case $cc_basename in + nvcc*) + lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; + *) + lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } +if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } + +if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then + lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" +else + : +fi + +fi + + + + + + + lt_prog_compiler_wl= +lt_prog_compiler_pic= +lt_prog_compiler_static= + + + if test "$GCC" = yes; then + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_static='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + lt_prog_compiler_pic='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + lt_prog_compiler_static= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + ;; + + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic=-Kconform_pic + fi + ;; + + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + lt_prog_compiler_wl='-Xlinker ' + lt_prog_compiler_pic='-Xcompiler -fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + else + lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + # old Intel for x86_64 which still supported -KPIC. + ecc*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='--shared' + lt_prog_compiler_static='--static' + ;; + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-qpic' + lt_prog_compiler_static='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ F* | *Sun*Fortran*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='' + ;; + *Sun\ C*) + # Sun C 5.9 + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Wl,' + ;; + esac + ;; + esac + ;; + + newsos6) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + + rdos*) + lt_prog_compiler_static='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + lt_prog_compiler_wl='-Qoption ld ';; + *) + lt_prog_compiler_wl='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl='-Qoption ld ' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + lt_prog_compiler_pic='-Kconform_pic' + lt_prog_compiler_static='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_can_build_shared=no + ;; + + uts4*) + lt_prog_compiler_pic='-pic' + lt_prog_compiler_static='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared=no + ;; + esac + fi + +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic= + ;; + *) + lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" + ;; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } +if ${lt_cv_prog_compiler_pic+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic=$lt_prog_compiler_pic +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 +$as_echo "$lt_cv_prog_compiler_pic" >&6; } +lt_prog_compiler_pic=$lt_cv_prog_compiler_pic + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 +$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } +if ${lt_cv_prog_compiler_pic_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_works=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_pic_works=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 +$as_echo "$lt_cv_prog_compiler_pic_works" >&6; } + +if test x"$lt_cv_prog_compiler_pic_works" = xyes; then + case $lt_prog_compiler_pic in + "" | " "*) ;; + *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; + esac +else + lt_prog_compiler_pic= + lt_prog_compiler_can_build_shared=no +fi + +fi + + + + + + + + + + + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if ${lt_cv_prog_compiler_static_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_static_works=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_static_works=yes + fi + else + lt_cv_prog_compiler_static_works=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 +$as_echo "$lt_cv_prog_compiler_static_works" >&6; } + +if test x"$lt_cv_prog_compiler_static_works" = xyes; then + : +else + lt_prog_compiler_static= +fi + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +$as_echo_n "checking if we can lock with hard links... " >&6; } + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +$as_echo "$hard_links" >&6; } + if test "$hard_links" = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + + runpath_var= + allow_undefined_flag= + always_export_symbols=no + archive_cmds= + archive_expsym_cmds= + compiler_needs_object=no + enable_shared_with_static_runtimes=no + export_dynamic_flag_spec= + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + hardcode_automatic=no + hardcode_direct=no + hardcode_direct_absolute=no + hardcode_libdir_flag_spec= + hardcode_libdir_flag_spec_ld= + hardcode_libdir_separator= + hardcode_minus_L=no + hardcode_shlibpath_var=unsupported + inherit_rpath=no + link_all_deplibs=unknown + module_cmds= + module_expsym_cmds= + old_archive_from_new_cmds= + old_archive_from_expsyms_cmds= + thread_safe_flag_spec= + whole_archive_flag_spec= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + ld_shlibs=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test "$with_gnu_ld" = yes; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; + *\ \(GNU\ Binutils\)\ [3-9]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test "$lt_use_gnu_ld_interface" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + export_dynamic_flag_spec='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec= + fi + supports_anon_versioning=no + case `$LD -v 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[3-9]*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + export_dynamic_flag_spec='${wl}--export-all-symbols' + allow_undefined_flag=unsupported + always_export_symbols=no + enable_shared_with_static_runtimes=yes + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs=no + fi + ;; + + haiku*) + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + link_all_deplibs=yes + ;; + + interix[3-9]*) + hardcode_direct=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test "$host_os" = linux-dietlibc; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test "$tmp_diet" = no + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + whole_archive_flag_spec= + tmp_sharedflag='--shared' ;; + xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + compiler_needs_object=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + compiler_needs_object=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test "x$supports_anon_versioning" = xyes; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' + hardcode_libdir_flag_spec= + hardcode_libdir_flag_spec_ld='-rpath $libdir' + archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + ld_shlibs=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test "$ld_shlibs" = no; then + runpath_var= + hardcode_libdir_flag_spec= + export_dynamic_flag_spec= + whole_archive_flag_spec= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix[4-9]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global + # defined symbols, whereas GNU nm marks them as "W". + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds='' + hardcode_direct=yes + hardcode_direct_absolute=yes + hardcode_libdir_separator=':' + link_all_deplibs=yes + file_list_spec='${wl}-f,' + + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + export_dynamic_flag_spec='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_="/usr/lib:/lib" + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag="-z nodefs" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_="/usr/lib:/lib" + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag=' ${wl}-bernotok' + allow_undefined_flag=' ${wl}-berok' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' + fi + archive_cmds_need_lc=yes + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + bsdi[45]*) + export_dynamic_flag_spec=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + always_export_symbols=yes + file_list_spec='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, )='true' + enable_shared_with_static_runtimes=yes + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + old_postinstall_cmds='chmod 644 $oldlib' + postlink_cmds='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_from_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' + enable_shared_with_static_runtimes=yes + ;; + esac + ;; + + darwin* | rhapsody*) + + + archive_cmds_need_lc=no + hardcode_direct=no + hardcode_automatic=yes + hardcode_shlibpath_var=unsupported + if test "$lt_cv_ld_force_load" = "yes"; then + whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + else + whole_archive_flag_spec='' + fi + link_all_deplibs=yes + allow_undefined_flag="$_lt_dar_allow_undefined" + case $cc_basename in + ifort*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test "$_lt_dar_can_shared" = "yes"; then + output_verbose_link_cmd=func_echo_all + archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + + else + ld_shlibs=no + fi + + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + freebsd1*) + ld_shlibs=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + if test "$GCC" = yes; then + archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + export_dynamic_flag_spec='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_flag_spec_ld='+b $libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='${wl}-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 +$as_echo_n "checking if $CC understands -b... " >&6; } +if ${lt_cv_prog_compiler__b+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler__b=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -b" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler__b=yes + fi + else + lt_cv_prog_compiler__b=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 +$as_echo "$lt_cv_prog_compiler__b" >&6; } + +if test x"$lt_cv_prog_compiler__b" = xyes; then + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' +else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' +fi + + ;; + esac + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct=no + hardcode_shlibpath_var=no + ;; + *) + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 +$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } +if ${lt_cv_irix_exported_symbol+:} false; then : + $as_echo_n "(cached) " >&6 +else + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int foo (void) { return 0; } +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_irix_exported_symbol=yes +else + lt_cv_irix_exported_symbol=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 +$as_echo "$lt_cv_irix_exported_symbol" >&6; } + if test "$lt_cv_irix_exported_symbol" = yes; then + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' + fi + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + inherit_rpath=yes + link_all_deplibs=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + newsos6) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_shlibpath_var=no + ;; + + *nto* | *qnx*) + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + hardcode_shlibpath_var=no + hardcode_direct_absolute=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + else + case $host_os in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-R$libdir' + ;; + *) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + esac + fi + else + ld_shlibs=no + fi + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + archive_cmds_need_lc='no' + hardcode_libdir_separator=: + ;; + + solaris*) + no_undefined_flag=' -z defs' + if test "$GCC" = yes; then + wlarc='${wl}' + archive_cmds='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='${wl}' + archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. GCC discards it without `$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test "$GCC" = yes; then + whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + else + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' + fi + ;; + esac + link_all_deplibs=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds='$CC -r -o $output$reload_objs' + hardcode_direct=no + ;; + motorola) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag='${wl}-z,text' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag='${wl}-z,text' + allow_undefined_flag='${wl}-z,nodefs' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='${wl}-R,$libdir' + hardcode_libdir_separator=':' + link_all_deplibs=yes + export_dynamic_flag_spec='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac + + if test x$host_vendor = xsni; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + export_dynamic_flag_spec='${wl}-Blargedynsym' + ;; + esac + fi + fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 +$as_echo "$ld_shlibs" >&6; } +test "$ld_shlibs" = no && can_build_shared=no + +with_gnu_ld=$with_gnu_ld + + + + + + + + + + + + + + + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } +if ${lt_cv_archive_cmds_need_lc+:} false; then : + $as_echo_n "(cached) " >&6 +else + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl + pic_flag=$lt_prog_compiler_pic + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + then + lt_cv_archive_cmds_need_lc=no + else + lt_cv_archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 +$as_echo "$lt_cv_archive_cmds_need_lc" >&6; } + archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc + ;; + esac + fi + ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +$as_echo_n "checking dynamic linker characteristics... " >&6; } + +if test "$GCC" = yes; then + case $host_os in + darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; + *) lt_awk_arg="/^libraries:/" ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;; + *) lt_sed_strip_eq="s,=/,/,g" ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary. + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path/$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" + else + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS=" "; FS="/|\n";} { + lt_foo=""; + lt_count=0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo="/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[lt_foo]++; } + if (lt_freq[lt_foo] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's,/\([A-Za-z]:\),\1,g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix[4-9]*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + library_names_spec='${libname}.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec="$LIB" + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +haiku*) + version_type=linux + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=yes + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[3-9]*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + if ${lt_cv_shlibpath_overrides_runpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : + lt_cv_shlibpath_overrides_runpath=yes +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + +fi + + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Add ABI-specific directories to the system library path. + sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" + + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +$as_echo "$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +fi +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +$as_echo_n "checking how to hardcode library paths into programs... " >&6; } +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || + test -n "$runpath_var" || + test "X$hardcode_automatic" = "Xyes" ; then + + # We can hardcode non-existent directories. + if test "$hardcode_direct" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && + test "$hardcode_minus_L" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 +$as_echo "$hardcode_action" >&6; } + +if test "$hardcode_action" = relink || + test "$inherit_rpath" = yes; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + + + + + + if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +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 dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + +fi + + ;; + + *) + ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" +if test "x$ac_cv_func_shl_load" = xyes; then : + lt_cv_dlopen="shl_load" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 +$as_echo_n "checking for shl_load in -ldld... " >&6; } +if ${ac_cv_lib_dld_shl_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +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 shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_shl_load=yes +else + ac_cv_lib_dld_shl_load=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 +$as_echo "$ac_cv_lib_dld_shl_load" >&6; } +if test "x$ac_cv_lib_dld_shl_load" = xyes; then : + lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" +else + ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" +if test "x$ac_cv_func_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +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 dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 +$as_echo_n "checking for dlopen in -lsvld... " >&6; } +if ${ac_cv_lib_svld_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +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 dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_svld_dlopen=yes +else + ac_cv_lib_svld_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 +$as_echo "$ac_cv_lib_svld_dlopen" >&6; } +if test "x$ac_cv_lib_svld_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 +$as_echo_n "checking for dld_link in -ldld... " >&6; } +if ${ac_cv_lib_dld_dld_link+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +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 dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_dld_link=yes +else + ac_cv_lib_dld_dld_link=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 +$as_echo "$ac_cv_lib_dld_dld_link" >&6; } +if test "x$ac_cv_lib_dld_dld_link" = xyes; then : + lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" +fi + + +fi + + +fi + + +fi + + +fi + + +fi + + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 +$as_echo_n "checking whether a program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 +$as_echo "$lt_cv_dlopen_self" >&6; } + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 +$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self_static+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self_static=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self_static=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 +$as_echo "$lt_cv_dlopen_self_static" >&6; } + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + + + + + + + + + + + + + + + + + +striplib= +old_striplib= +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 +$as_echo_n "checking whether stripping libraries is possible... " >&6; } +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + { $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; } + fi + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +fi + + + + + + + + + + + + + # Report which library types will actually be built + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 +$as_echo_n "checking if libtool supports shared libraries... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 +$as_echo "$can_build_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 +$as_echo_n "checking whether to build shared libraries... " >&6; } + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[4-9]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 +$as_echo "$enable_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 +$as_echo_n "checking whether to build static libraries... " >&6; } + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 +$as_echo "$enable_static" >&6; } + + + + +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC="$lt_save_CC" + + + + + + + + + + + + + + ac_config_commands="$ac_config_commands libtool" + + + + +# Only expand once: + + + + +# Checks for header files. +for ac_header in stdarg.h stdbool.h netinet/in.h sys/param.h sys/socket.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h +do : + 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 eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +# check for types. +# Using own tests for int64* because autoconf builtin only give 32bit. +ac_fn_c_check_type "$LINENO" "int8_t" "ac_cv_type_int8_t" "$ac_includes_default" +if test "x$ac_cv_type_int8_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define int8_t signed char +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "int16_t" "ac_cv_type_int16_t" "$ac_includes_default" +if test "x$ac_cv_type_int16_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define int16_t short +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "int32_t" "ac_cv_type_int32_t" "$ac_includes_default" +if test "x$ac_cv_type_int32_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define int32_t int +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "int64_t" "ac_cv_type_int64_t" "$ac_includes_default" +if test "x$ac_cv_type_int64_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define int64_t long long +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "uint8_t" "ac_cv_type_uint8_t" "$ac_includes_default" +if test "x$ac_cv_type_uint8_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define uint8_t unsigned char +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "uint16_t" "ac_cv_type_uint16_t" "$ac_includes_default" +if test "x$ac_cv_type_uint16_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define uint16_t unsigned short +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "uint32_t" "ac_cv_type_uint32_t" "$ac_includes_default" +if test "x$ac_cv_type_uint32_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define uint32_t unsigned int +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "uint64_t" "ac_cv_type_uint64_t" "$ac_includes_default" +if test "x$ac_cv_type_uint64_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define uint64_t unsigned long long +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" +if test "x$ac_cv_type_size_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned int +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "ssize_t" "ac_cv_type_ssize_t" "$ac_includes_default" +if test "x$ac_cv_type_ssize_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define ssize_t int +_ACEOF + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uid_t in sys/types.h" >&5 +$as_echo_n "checking for uid_t in sys/types.h... " >&6; } +if ${ac_cv_type_uid_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "uid_t" >/dev/null 2>&1; then : + ac_cv_type_uid_t=yes +else + ac_cv_type_uid_t=no +fi +rm -f conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_uid_t" >&5 +$as_echo "$ac_cv_type_uid_t" >&6; } +if test $ac_cv_type_uid_t = no; then + +$as_echo "#define uid_t int" >>confdefs.h + + +$as_echo "#define gid_t int" >>confdefs.h + +fi + +ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default" +if test "x$ac_cv_type_pid_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define pid_t int +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "off_t" "ac_cv_type_off_t" "$ac_includes_default" +if test "x$ac_cv_type_off_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define off_t long int +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "u_char" "ac_cv_type_u_char" " +$ac_includes_default +#ifdef HAVE_WINSOCK2_H +# include +#endif + +" +if test "x$ac_cv_type_u_char" = xyes; then : + +else + +$as_echo "#define u_char unsigned char" >>confdefs.h + +fi + +ac_fn_c_check_type "$LINENO" "rlim_t" "ac_cv_type_rlim_t" " +$ac_includes_default +#ifdef HAVE_SYS_RESOURCE_H +# include +#endif + +" +if test "x$ac_cv_type_rlim_t" = xyes; then : + +else + +$as_echo "#define rlim_t unsigned long" >>confdefs.h + +fi + + +ac_fn_c_check_type "$LINENO" "socklen_t" "ac_cv_type_socklen_t" " +$ac_includes_default +#ifdef HAVE_SYS_SOCKET_H +# include +#endif +#ifdef HAVE_WS2TCPIP_H +# include +#endif + +" +if test "x$ac_cv_type_socklen_t" = xyes; then : + +else + +$as_echo "#define socklen_t int" >>confdefs.h + +fi + + ac_fn_c_check_type "$LINENO" "in_addr_t" "ac_cv_type_in_addr_t" " +$ac_includes_default +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_NETINET_IN_H +# include +#endif + +" +if test "x$ac_cv_type_in_addr_t" = xyes; then : + +else + +$as_echo "#define in_addr_t uint32_t" >>confdefs.h + +fi + + ac_fn_c_check_type "$LINENO" "in_port_t" "ac_cv_type_in_port_t" " +$ac_includes_default +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_NETINET_IN_H +# include +#endif + +" +if test "x$ac_cv_type_in_port_t" = xyes; then : + +else + +$as_echo "#define in_port_t uint16_t" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if memcmp compares unsigned" >&5 +$as_echo_n "checking if memcmp compares unsigned... " >&6; } +if test "$cross_compiling" = yes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: cross-compile no" >&5 +$as_echo "cross-compile no" >&6; } + +$as_echo "#define MEMCMP_IS_BROKEN 1" >>confdefs.h + + case " $LIBOBJS " in + *" memcmp.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS memcmp.$ac_objext" + ;; +esac + + +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +#include +int main(void) +{ + char a = 255, b = 0; + if(memcmp(&a, &b, 1) < 0) + return 1; + return 0; +} + +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + { $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_echo "#define MEMCMP_IS_BROKEN 1" >>confdefs.h + + case " $LIBOBJS " in + *" memcmp.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS memcmp.$ac_objext" + ;; +esac + + +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + +# add option to disable the evil rpath + +# Check whether --enable-rpath was given. +if test "${enable_rpath+set}" = set; then : + enableval=$enable_rpath; enable_rpath=$enableval +else + enable_rpath=yes +fi + +if test "x$enable_rpath" = xno; then + ac_config_commands="$ac_config_commands disable-rpath" + +fi + + + +# check to see if libraries are needed for these functions. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing inet_pton" >&5 +$as_echo_n "checking for library containing inet_pton... " >&6; } +if ${ac_cv_search_inet_pton+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +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 inet_pton (); +int +main () +{ +return inet_pton (); + ; + return 0; +} +_ACEOF +for ac_lib in '' nsl; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_inet_pton=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_inet_pton+:} false; then : + break +fi +done +if ${ac_cv_search_inet_pton+:} false; then : + +else + ac_cv_search_inet_pton=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_inet_pton" >&5 +$as_echo "$ac_cv_search_inet_pton" >&6; } +ac_res=$ac_cv_search_inet_pton +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing socket" >&5 +$as_echo_n "checking for library containing socket... " >&6; } +if ${ac_cv_search_socket+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +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 socket (); +int +main () +{ +return socket (); + ; + return 0; +} +_ACEOF +for ac_lib in '' socket; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_socket=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_socket+:} false; then : + break +fi +done +if ${ac_cv_search_socket+:} false; then : + +else + ac_cv_search_socket=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_socket" >&5 +$as_echo "$ac_cv_search_socket" >&6; } +ac_res=$ac_cv_search_socket +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + + +# check wether strptime also works + +# check some functions of the OS before linking libs (while still runnable). +for ac_header in unistd.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "unistd.h" "ac_cv_header_unistd_h" "$ac_includes_default" +if test "x$ac_cv_header_unistd_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_UNISTD_H 1 +_ACEOF + +fi + +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working chown" >&5 +$as_echo_n "checking for working chown... " >&6; } +if ${ac_cv_func_chown_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_chown_works=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +#include + +int +main () +{ + char *f = "conftest.chown"; + struct stat before, after; + + if (creat (f, 0600) < 0) + return 1; + if (stat (f, &before) < 0) + return 1; + if (chown (f, (uid_t) -1, (gid_t) -1) == -1) + return 1; + if (stat (f, &after) < 0) + return 1; + return ! (before.st_uid == after.st_uid && before.st_gid == after.st_gid); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_chown_works=yes +else + ac_cv_func_chown_works=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +rm -f conftest.chown + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_chown_works" >&5 +$as_echo "$ac_cv_func_chown_works" >&6; } +if test $ac_cv_func_chown_works = yes; then + +$as_echo "#define HAVE_CHOWN 1" >>confdefs.h + +fi + +for ac_header in vfork.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "vfork.h" "ac_cv_header_vfork_h" "$ac_includes_default" +if test "x$ac_cv_header_vfork_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_VFORK_H 1 +_ACEOF + +fi + +done + +for ac_func in fork vfork +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 : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +if test "x$ac_cv_func_fork" = xyes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working fork" >&5 +$as_echo_n "checking for working fork... " >&6; } +if ${ac_cv_func_fork_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_fork_works=cross +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* By Ruediger Kuhlmann. */ + return fork () < 0; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_fork_works=yes +else + ac_cv_func_fork_works=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_fork_works" >&5 +$as_echo "$ac_cv_func_fork_works" >&6; } + +else + ac_cv_func_fork_works=$ac_cv_func_fork +fi +if test "x$ac_cv_func_fork_works" = xcross; then + case $host in + *-*-amigaos* | *-*-msdosdjgpp*) + # Override, as these systems have only a dummy fork() stub + ac_cv_func_fork_works=no + ;; + *) + ac_cv_func_fork_works=yes + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&5 +$as_echo "$as_me: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&2;} +fi +ac_cv_func_vfork_works=$ac_cv_func_vfork +if test "x$ac_cv_func_vfork" = xyes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working vfork" >&5 +$as_echo_n "checking for working vfork... " >&6; } +if ${ac_cv_func_vfork_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_vfork_works=cross +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Thanks to Paul Eggert for this test. */ +$ac_includes_default +#include +#ifdef HAVE_VFORK_H +# include +#endif +/* On some sparc systems, changes by the child to local and incoming + argument registers are propagated back to the parent. The compiler + is told about this with #include , but some compilers + (e.g. gcc -O) don't grok . Test for this by using a + static variable whose address is put into a register that is + clobbered by the vfork. */ +static void +#ifdef __cplusplus +sparc_address_test (int arg) +# else +sparc_address_test (arg) int arg; +#endif +{ + static pid_t child; + if (!child) { + child = vfork (); + if (child < 0) { + perror ("vfork"); + _exit(2); + } + if (!child) { + arg = getpid(); + write(-1, "", 0); + _exit (arg); + } + } +} + +int +main () +{ + pid_t parent = getpid (); + pid_t child; + + sparc_address_test (0); + + child = vfork (); + + if (child == 0) { + /* Here is another test for sparc vfork register problems. This + test uses lots of local variables, at least as many local + variables as main has allocated so far including compiler + temporaries. 4 locals are enough for gcc 1.40.3 on a Solaris + 4.1.3 sparc, but we use 8 to be safe. A buggy compiler should + reuse the register of parent for one of the local variables, + since it will think that parent can't possibly be used any more + in this routine. Assigning to the local variable will thus + munge parent in the parent process. */ + pid_t + p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(), + p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid(); + /* Convince the compiler that p..p7 are live; otherwise, it might + use the same hardware register for all 8 local variables. */ + if (p != p1 || p != p2 || p != p3 || p != p4 + || p != p5 || p != p6 || p != p7) + _exit(1); + + /* On some systems (e.g. IRIX 3.3), vfork doesn't separate parent + from child file descriptors. If the child closes a descriptor + before it execs or exits, this munges the parent's descriptor + as well. Test for this by closing stdout in the child. */ + _exit(close(fileno(stdout)) != 0); + } else { + int status; + struct stat st; + + while (wait(&status) != child) + ; + return ( + /* Was there some problem with vforking? */ + child < 0 + + /* Did the child fail? (This shouldn't happen.) */ + || status + + /* Did the vfork/compiler bug occur? */ + || parent != getpid() + + /* Did the file descriptor bug occur? */ + || fstat(fileno(stdout), &st) != 0 + ); + } +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_vfork_works=yes +else + ac_cv_func_vfork_works=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_vfork_works" >&5 +$as_echo "$ac_cv_func_vfork_works" >&6; } + +fi; +if test "x$ac_cv_func_fork_works" = xcross; then + ac_cv_func_vfork_works=$ac_cv_func_vfork + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&5 +$as_echo "$as_me: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&2;} +fi + +if test "x$ac_cv_func_vfork_works" = xyes; then + +$as_echo "#define HAVE_WORKING_VFORK 1" >>confdefs.h + +else + +$as_echo "#define vfork fork" >>confdefs.h + +fi +if test "x$ac_cv_func_fork_works" = xyes; then + +$as_echo "#define HAVE_WORKING_FORK 1" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking return type of signal handlers" >&5 +$as_echo_n "checking return type of signal handlers... " >&6; } +if ${ac_cv_type_signal+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include + +int +main () +{ +return *(signal (0, 0)) (0) == 1; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_type_signal=int +else + ac_cv_type_signal=void +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_signal" >&5 +$as_echo "$ac_cv_type_signal" >&6; } + +cat >>confdefs.h <<_ACEOF +#define RETSIGTYPE $ac_cv_type_signal +_ACEOF + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGEFILE_SOURCE value needed for large files" >&5 +$as_echo_n "checking for _LARGEFILE_SOURCE value needed for large files... " >&6; } +if ${ac_cv_sys_largefile_source+:} false; then : + $as_echo_n "(cached) " >&6 +else + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include /* for off_t */ + #include +int +main () +{ +int (*fp) (FILE *, off_t, int) = fseeko; + return fseeko (stdin, 0, 0) && fp (stdin, 0, 0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_sys_largefile_source=no; break +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define _LARGEFILE_SOURCE 1 +#include /* for off_t */ + #include +int +main () +{ +int (*fp) (FILE *, off_t, int) = fseeko; + return fseeko (stdin, 0, 0) && fp (stdin, 0, 0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_sys_largefile_source=1; break +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_cv_sys_largefile_source=unknown + break +done +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_source" >&5 +$as_echo "$ac_cv_sys_largefile_source" >&6; } +case $ac_cv_sys_largefile_source in #( + no | unknown) ;; + *) +cat >>confdefs.h <<_ACEOF +#define _LARGEFILE_SOURCE $ac_cv_sys_largefile_source +_ACEOF +;; +esac +rm -rf conftest* + +# We used to try defining _XOPEN_SOURCE=500 too, to work around a bug +# in glibc 2.1.3, but that breaks too many other things. +# If you want fseeko and ftello with glibc, upgrade to a fixed glibc. +if test $ac_cv_sys_largefile_source != unknown; then + +$as_echo "#define HAVE_FSEEKO 1" >>confdefs.h + +fi + + +# Check whether --enable-largefile was given. +if test "${enable_largefile+set}" = set; then : + enableval=$enable_largefile; +fi + +if test "$enable_largefile" != no; then + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5 +$as_echo_n "checking for special C compiler options needed for large files... " >&6; } +if ${ac_cv_sys_largefile_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_sys_largefile_CC=no + if test "$GCC" != yes; then + ac_save_CC=$CC + while :; do + # IRIX 6.2 and later do not support large files by default, + # so use the C compiler's -n32 option if that helps. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF + if ac_fn_c_try_compile "$LINENO"; then : + break +fi +rm -f core conftest.err conftest.$ac_objext + CC="$CC -n32" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_largefile_CC=' -n32'; break +fi +rm -f core conftest.err conftest.$ac_objext + break + done + CC=$ac_save_CC + rm -f conftest.$ac_ext + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5 +$as_echo "$ac_cv_sys_largefile_CC" >&6; } + if test "$ac_cv_sys_largefile_CC" != no; then + CC=$CC$ac_cv_sys_largefile_CC + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5 +$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; } +if ${ac_cv_sys_file_offset_bits+:} false; then : + $as_echo_n "(cached) " >&6 +else + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_file_offset_bits=no; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define _FILE_OFFSET_BITS 64 +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_file_offset_bits=64; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cv_sys_file_offset_bits=unknown + break +done +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5 +$as_echo "$ac_cv_sys_file_offset_bits" >&6; } +case $ac_cv_sys_file_offset_bits in #( + no | unknown) ;; + *) +cat >>confdefs.h <<_ACEOF +#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits +_ACEOF +;; +esac +rm -rf conftest* + if test $ac_cv_sys_file_offset_bits = unknown; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5 +$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; } +if ${ac_cv_sys_large_files+:} false; then : + $as_echo_n "(cached) " >&6 +else + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_large_files=no; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define _LARGE_FILES 1 +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_large_files=1; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cv_sys_large_files=unknown + break +done +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5 +$as_echo "$ac_cv_sys_large_files" >&6; } +case $ac_cv_sys_large_files in #( + no | unknown) ;; + *) +cat >>confdefs.h <<_ACEOF +#define _LARGE_FILES $ac_cv_sys_large_files +_ACEOF +;; +esac +rm -rf conftest* + fi +fi + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we need -D_LARGEFILE_SOURCE=1 as a flag for $CC" >&5 +$as_echo_n "checking whether we need -D_LARGEFILE_SOURCE=1 as a flag for $CC... " >&6; } +cache=`$as_echo "-D_LARGEFILE_SOURCE=1" | $as_tr_sh` +if eval \${cv_prog_cc_flag_needed_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo ' +#include +int test() { + int a = fseeko(stdin, 0, 0); + return a; +} +' > conftest.c +echo 'void f(){}' >>conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=no" +else + +if test -z "`$CC $CPPFLAGS $CFLAGS -D_LARGEFILE_SOURCE=1 $ERRFLAG -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_needed_$cache=yes" +else +eval "cv_prog_cc_flag_needed_$cache=fail" +#echo 'Test with flag fails too!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS -D_LARGEFILE_SOURCE=1 $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS -D_LARGEFILE_SOURCE=1 $ERRFLAG -c conftest.c 2>&1` +#exit 1 +fi + +fi +rm -f conftest conftest.c conftest.o + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +CFLAGS="$CFLAGS -D_LARGEFILE_SOURCE=1" +else +if eval "test \"`echo '$cv_prog_cc_flag_needed_'$cache`\" = no"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +#echo 'Test with flag is no!' +#cat conftest.c +#echo "$CC $CPPFLAGS $CFLAGS -D_LARGEFILE_SOURCE=1 $ERRFLAG -c conftest.c 2>&1" +#echo `$CC $CPPFLAGS $CFLAGS -D_LARGEFILE_SOURCE=1 $ERRFLAG -c conftest.c 2>&1` +#exit 1 +: + +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +: + +fi +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if nonblocking sockets work" >&5 +$as_echo_n "checking if nonblocking sockets work... " >&6; } +if echo $target | grep mingw32 >/dev/null; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no (windows)" >&5 +$as_echo "no (windows)" >&6; } + +$as_echo "#define NONBLOCKING_IS_BROKEN 1" >>confdefs.h + +else +if test "$cross_compiling" = yes; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: crosscompile(yes)" >&5 +$as_echo "crosscompile(yes)" >&6; } + +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_TIME_H +#include +#endif + +int main(void) +{ + int port; + int sfd, cfd; + int num = 10; + int i, p; + struct sockaddr_in a; + /* test if select and nonblocking reads work well together */ + /* open port. + fork child to send 10 messages. + select to read. + then try to nonblocking read the 10 messages + then, nonblocking read must give EAGAIN + */ + + port = 12345 + (time(0)%32); + sfd = socket(PF_INET, SOCK_DGRAM, 0); + if(sfd == -1) { + perror("socket"); + return 1; + } + memset(&a, 0, sizeof(a)); + a.sin_family = AF_INET; + a.sin_port = htons(port); + a.sin_addr.s_addr = inet_addr("127.0.0.1"); + if(bind(sfd, (struct sockaddr*)&a, sizeof(a)) < 0) { + perror("bind"); + return 1; + } + if(fcntl(sfd, F_SETFL, O_NONBLOCK) == -1) { + perror("fcntl"); + return 1; + } + + cfd = socket(PF_INET, SOCK_DGRAM, 0); + if(cfd == -1) { + perror("client socket"); + return 1; + } + a.sin_port = 0; + if(bind(cfd, (struct sockaddr*)&a, sizeof(a)) < 0) { + perror("client bind"); + return 1; + } + a.sin_port = htons(port); + + /* no handler, causes exit in 10 seconds */ + alarm(10); + + /* send and receive on the socket */ + if((p=fork()) == 0) { + for(i=0; i&5 +$as_echo "yes" >&6; } + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +$as_echo "#define NONBLOCKING_IS_BROKEN 1" >>confdefs.h + + +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether mkdir has one arg" >&5 +$as_echo_n "checking whether mkdir has one arg... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +#ifdef HAVE_WINSOCK2_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif + +int +main () +{ + + (void)mkdir("directory"); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define MKDIR_HAS_ONE_ARG 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +for ac_func in strptime +do : + ac_fn_c_check_func "$LINENO" "strptime" "ac_cv_func_strptime" +if test "x$ac_cv_func_strptime" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STRPTIME 1 +_ACEOF + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether strptime works" >&5 +$as_echo_n "checking whether strptime works... " >&6; } +if test c${cross_compiling} = cno; then +if test "$cross_compiling" = yes; then : + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run test program while cross compiling +See \`config.log' for more details" "$LINENO" 5; } +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define _XOPEN_SOURCE +#include +int main(void) { struct tm tm; char *res; +res = strptime("2010-07-15T00:00:00+00:00", "%t%Y%t-%t%m%t-%t%d%tT%t%H%t:%t%M%t:%t%S%t", &tm); +if (!res) return 2; +res = strptime("20070207111842", "%Y%m%d%H%M%S", &tm); +if (!res) return 1; return 0; } + +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + eval "ac_cv_c_strptime_works=yes" +else + eval "ac_cv_c_strptime_works=no" +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +else +eval "ac_cv_c_strptime_works=maybe" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_strptime_works" >&5 +$as_echo "$ac_cv_c_strptime_works" >&6; } +if test $ac_cv_c_strptime_works = no; then +case " $LIBOBJS " in + *" strptime.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS strptime.$ac_objext" + ;; +esac + +else + +cat >>confdefs.h <<_ACEOF +#define STRPTIME_WORKS 1 +_ACEOF + +fi + +else + case " $LIBOBJS " in + *" strptime.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS strptime.$ac_objext" + ;; +esac + +fi +done + + +# set memory allocation checking if requested +# Check whether --enable-alloc-checks was given. +if test "${enable_alloc_checks+set}" = set; then : + enableval=$enable_alloc_checks; +fi + +# Check whether --enable-alloc-lite was given. +if test "${enable_alloc_lite+set}" = set; then : + enableval=$enable_alloc_lite; +fi + +# Check whether --enable-alloc-nonregional was given. +if test "${enable_alloc_nonregional+set}" = set; then : + enableval=$enable_alloc_nonregional; +fi + +if test x_$enable_alloc_nonregional = x_yes; then + +$as_echo "#define UNBOUND_ALLOC_NONREGIONAL 1" >>confdefs.h + +fi +if test x_$enable_alloc_checks = x_yes; then + +$as_echo "#define UNBOUND_ALLOC_STATS 1" >>confdefs.h + +else + if test x_$enable_alloc_lite = x_yes; then + +$as_echo "#define UNBOUND_ALLOC_LITE 1" >>confdefs.h + + else + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible malloc" >&5 +$as_echo_n "checking for GNU libc compatible malloc... " >&6; } + if test "$cross_compiling" = yes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no (crosscompile)" >&5 +$as_echo "no (crosscompile)" >&6; } + case " $LIBOBJS " in + *" malloc.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS malloc.$ac_objext" + ;; +esac + + +cat >>confdefs.h <<_ACEOF +#define malloc rpl_malloc_unbound +_ACEOF + +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#if defined STDC_HEADERS || defined HAVE_STDLIB_H +#include +#else +char *malloc (); +#endif + +int +main () +{ + if(malloc(0) != 0) return 1; + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + case " $LIBOBJS " in + *" malloc.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS malloc.$ac_objext" + ;; +esac + + +cat >>confdefs.h <<_ACEOF +#define malloc rpl_malloc_unbound +_ACEOF + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE_MALLOC 1" >>confdefs.h + +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + + fi +fi + +# check windows threads (we use them, not pthreads, on windows). +if test "$on_mingw" = "yes"; then +# check windows threads + for ac_header in windows.h +do : + ac_fn_c_check_header_compile "$LINENO" "windows.h" "ac_cv_header_windows_h" "$ac_includes_default +" +if test "x$ac_cv_header_windows_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_WINDOWS_H 1 +_ACEOF + +fi + +done + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CreateThread" >&5 +$as_echo_n "checking for CreateThread... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#ifdef HAVE_WINDOWS_H +#include +#endif + +int +main () +{ + + HANDLE t = CreateThread(NULL, 0, NULL, NULL, 0, NULL); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE_WINDOWS_THREADS 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +else +# not on mingw, check thread libraries. + +# check for thread library. +# check this first, so that the pthread lib does not get linked in via +# libssl or libpython, and thus distorts the tests, and we end up using +# the non-threadsafe C libraries. + +# Check whether --with-pthreads was given. +if test "${with_pthreads+set}" = set; then : + withval=$with_pthreads; +else + withval="yes" +fi + +ub_have_pthreads=no +if test x_$withval != x_no; then + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +acx_pthread_ok=no + +# We used to check for pthread.h first, but this fails if pthread.h +# requires special compiler flags (e.g. on True64 or Sequent). +# It gets checked for in the link test anyway. + +# First of all, check if the user has set any of the PTHREAD_LIBS, +# etcetera environment variables, and if threads linking works using +# them: +if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS" >&5 +$as_echo_n "checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS... " >&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 pthread_join (); +int +main () +{ +return pthread_join (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + acx_pthread_ok=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_pthread_ok" >&5 +$as_echo "$acx_pthread_ok" >&6; } + if test x"$acx_pthread_ok" = xno; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" +fi + +# We must check for the threads library under a number of different +# names; the ordering is very important because some systems +# (e.g. DEC) have both -lpthread and -lpthreads, where one of the +# libraries is broken (non-POSIX). + +# Create a list of thread flags to try. Items starting with a "-" are +# C compiler flags, and other items are library names, except for "none" +# which indicates that we try without any flags at all, and "pthread-config" +# which is a program returning the flags for the Pth emulation library. + +acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" + +# The ordering *is* (sometimes) important. Some notes on the +# individual items follow: + +# pthreads: AIX (must check this before -lpthread) +# none: in case threads are in libc; should be tried before -Kthread and +# other compiler flags to prevent continual compiler warnings +# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) +# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) +# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) +# -pthreads: Solaris/gcc +# -mthreads: Mingw32/gcc, Lynx/gcc +# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it +# doesn't hurt to check since this sometimes defines pthreads too; +# also defines -D_REENTRANT) +# ... -mt is also the pthreads flag for HP/aCC +# pthread: Linux, etcetera +# --thread-safe: KAI C++ +# pthread-config: use pthread-config program (for GNU Pth library) + +case "${host_cpu}-${host_os}" in + *solaris*) + + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (We need to link with -pthreads/-mt/ + # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather + # a function called by this macro, so we could check for that, but + # who knows whether they'll stub that too in a future libc.) So, + # we'll just look for -pthreads and -lpthread first: + + acx_pthread_flags="-pthreads pthread -mt -pthread $acx_pthread_flags" + ;; +esac + +if test x"$acx_pthread_ok" = xno; then +for flag in $acx_pthread_flags; do + + case $flag in + none) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work without any flags" >&5 +$as_echo_n "checking whether pthreads work without any flags... " >&6; } + ;; + + -*) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with $flag" >&5 +$as_echo_n "checking whether pthreads work with $flag... " >&6; } + PTHREAD_CFLAGS="$flag" + ;; + + pthread-config) + # Extract the first word of "pthread-config", so it can be a program name with args. +set dummy pthread-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_acx_pthread_config+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$acx_pthread_config"; then + ac_cv_prog_acx_pthread_config="$acx_pthread_config" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_acx_pthread_config="yes" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_acx_pthread_config" && ac_cv_prog_acx_pthread_config="no" +fi +fi +acx_pthread_config=$ac_cv_prog_acx_pthread_config +if test -n "$acx_pthread_config"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_pthread_config" >&5 +$as_echo "$acx_pthread_config" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test x"$acx_pthread_config" = xno; then continue; fi + PTHREAD_CFLAGS="`pthread-config --cflags`" + PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" + ;; + + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the pthreads library -l$flag" >&5 +$as_echo_n "checking for the pthreads library -l$flag... " >&6; } + PTHREAD_LIBS="-l$flag" + ;; + esac + + save_LIBS="$LIBS" + save_CFLAGS="$CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +pthread_t th; pthread_join(th, 0); + pthread_attr_init(0); pthread_cleanup_push(0, 0); + pthread_create(0,0,0,0); pthread_cleanup_pop(0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + acx_pthread_ok=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_pthread_ok" >&5 +$as_echo "$acx_pthread_ok" >&6; } + if test "x$acx_pthread_ok" = xyes; then + break; + fi + + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" +done +fi + +# Various other checks: +if test "x$acx_pthread_ok" = xyes; then + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + + # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for joinable pthread attribute" >&5 +$as_echo_n "checking for joinable pthread attribute... " >&6; } + attr_name=unknown + for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +int attr=$attr; return attr; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + attr_name=$attr; break +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + done + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $attr_name" >&5 +$as_echo "$attr_name" >&6; } + if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then + +cat >>confdefs.h <<_ACEOF +#define PTHREAD_CREATE_JOINABLE $attr_name +_ACEOF + + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if more special flags are required for pthreads" >&5 +$as_echo_n "checking if more special flags are required for pthreads... " >&6; } + flag=no + case "${host_cpu}-${host_os}" in + *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";; + *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${flag}" >&5 +$as_echo "${flag}" >&6; } + if test "x$flag" != xno; then + PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" + fi + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + # More AIX lossage: must compile with xlc_r or cc_r + if test x"$GCC" != xyes; then + for ac_prog in xlc_r cc_r +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_PTHREAD_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$PTHREAD_CC"; then + ac_cv_prog_PTHREAD_CC="$PTHREAD_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_PTHREAD_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PTHREAD_CC=$ac_cv_prog_PTHREAD_CC +if test -n "$PTHREAD_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PTHREAD_CC" >&5 +$as_echo "$PTHREAD_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$PTHREAD_CC" && break +done +test -n "$PTHREAD_CC" || PTHREAD_CC="${CC}" + + else + PTHREAD_CC=$CC + fi +else + PTHREAD_CC="$CC" +fi + + + + + +# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: +if test x"$acx_pthread_ok" = xyes; then + + +$as_echo "#define HAVE_PTHREAD 1" >>confdefs.h + + LIBS="$PTHREAD_LIBS $LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + CC="$PTHREAD_CC" + ub_have_pthreads=yes + ac_fn_c_check_type "$LINENO" "pthread_spinlock_t" "ac_cv_type_pthread_spinlock_t" "#include +" +if test "x$ac_cv_type_pthread_spinlock_t" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_PTHREAD_SPINLOCK_T 1 +_ACEOF + + +fi +ac_fn_c_check_type "$LINENO" "pthread_rwlock_t" "ac_cv_type_pthread_rwlock_t" "#include +" +if test "x$ac_cv_type_pthread_rwlock_t" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_PTHREAD_RWLOCK_T 1 +_ACEOF + + +fi + + + : +else + acx_pthread_ok=no + +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi + +# check solaris thread library + +# Check whether --with-solaris-threads was given. +if test "${with_solaris_threads+set}" = set; then : + withval=$with_solaris_threads; +else + withval="no" +fi + +ub_have_sol_threads=no +if test x_$withval != x_no; then + if test x_$ub_have_pthreads != x_no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Have pthreads already, ignoring --with-solaris-threads" >&5 +$as_echo "$as_me: WARNING: Have pthreads already, ignoring --with-solaris-threads" >&2;} + else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing thr_create" >&5 +$as_echo_n "checking for library containing thr_create... " >&6; } +if ${ac_cv_search_thr_create+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +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 thr_create (); +int +main () +{ +return thr_create (); + ; + return 0; +} +_ACEOF +for ac_lib in '' thread; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_thr_create=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_thr_create+:} false; then : + break +fi +done +if ${ac_cv_search_thr_create+:} false; then : + +else + ac_cv_search_thr_create=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_thr_create" >&5 +$as_echo "$ac_cv_search_thr_create" >&6; } +ac_res=$ac_cv_search_thr_create +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + + +$as_echo "#define HAVE_SOLARIS_THREADS 1" >>confdefs.h + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -mt" >&5 +$as_echo_n "checking whether $CC supports -mt... " >&6; } +cache=`echo mt | sed 'y%.=/+-%___p_%'` +if eval \${cv_prog_cc_flag_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo 'void f(){}' >conftest.c +if test -z "`$CC $CPPFLAGS $CFLAGS -mt -c conftest.c 2>&1`"; then +eval "cv_prog_cc_flag_$cache=yes" +else +eval "cv_prog_cc_flag_$cache=no" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +: +CFLAGS="$CFLAGS -mt" +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: +CFLAGS="$CFLAGS -D_REENTRANT" +fi + + ub_have_sol_threads=yes + +else + + as_fn_error $? "no solaris threads found." "$LINENO" 5 + +fi + + fi +fi + +fi # end of non-mingw check of thread libraries + +# Check for PyUnbound + +# Check whether --with-pyunbound was given. +if test "${with_pyunbound+set}" = set; then : + withval=$with_pyunbound; +else + withval="no" +fi + + +ub_test_python=no +ub_with_pyunbound=no +if test x_$withval != x_no; then + ub_with_pyunbound=yes + ub_test_python=yes +fi + +# Check for Python module + +# Check whether --with-pythonmodule was given. +if test "${with_pythonmodule+set}" = set; then : + withval=$with_pythonmodule; +else + withval="no" +fi + + +ub_with_pythonmod=no +if test x_$withval != x_no; then + ub_with_pythonmod=yes + ub_test_python=yes +fi + +# Check for Python & SWIG only on PyUnbound or PyModule +if test x_$ub_test_python != x_no; then + + # Check for Python + ub_have_python=no + ac_save_LIBS="$LIBS" + # + # Allow the use of a (user set) custom python version + # + + + # Extract the first word of "python[$PYTHON_VERSION]", so it can be a program name with args. +set dummy python$PYTHON_VERSION; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PYTHON+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PYTHON in + [\\/]* | ?:[\\/]*) + ac_cv_path_PYTHON="$PYTHON" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_PYTHON="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PYTHON=$ac_cv_path_PYTHON +if test -n "$PYTHON"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON" >&5 +$as_echo "$PYTHON" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test -z "$PYTHON"; then + as_fn_error $? "Cannot find python$PYTHON_VERSION in your system path" "$LINENO" 5 + PYTHON_VERSION="" + fi + + if test -z "$PYTHON_VERSION"; then + PYTHON_VERSION=`$PYTHON -c "import sys, string; \ + print string.split(sys.version)[0]"` + fi + + # + # Check for a version of Python >= 2.1.0 + # + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a version of Python >= '2.1.0'" >&5 +$as_echo_n "checking for a version of Python >= '2.1.0'... " >&6; } + ac_supports_python_ver=`$PYTHON -c "import sys, string; \ + ver = string.split(sys.version)[0]; \ + print ver >= '2.1.0'"` + if test "$ac_supports_python_ver" != "True"; then + if test -z "$PYTHON_NOVERSIONCHECK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? " +This version of the AC_PYTHON_DEVEL macro +doesn't work properly with versions of Python before +2.1.0. You may need to re-run configure, setting the +variables PYTHON_CPPFLAGS, PYTHON_LDFLAGS, PYTHON_SITE_PKG, +PYTHON_EXTRA_LIBS and PYTHON_EXTRA_LDFLAGS by hand. +Moreover, to disable this check, set PYTHON_NOVERSIONCHECK +to something else than an empty string. + +See \`config.log' for more details" "$LINENO" 5; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: skip at user request" >&5 +$as_echo "skip at user request" >&6; } + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + fi + + # + # if the macro parameter ``version'' is set, honour it + # + if test -n ""; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a version of Python " >&5 +$as_echo_n "checking for a version of Python ... " >&6; } + ac_supports_python_ver=`$PYTHON -c "import sys, string; \ + ver = string.split(sys.version)[0]; \ + print ver "` + if test "$ac_supports_python_ver" = "True"; then + { $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 $? "this package requires Python . +If you have it installed, but it isn't the default Python +interpreter in your system path, please pass the PYTHON_VERSION +variable to configure. See \`\`configure --help'' for reference. +" "$LINENO" 5 + PYTHON_VERSION="" + fi + fi + + # + # Check if you have distutils, else fail + # + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the distutils Python package" >&5 +$as_echo_n "checking for the distutils Python package... " >&6; } + ac_distutils_result=`$PYTHON -c "import distutils" 2>&1` + if test -z "$ac_distutils_result"; then + { $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 $? "cannot import Python module \"distutils\". +Please check your Python installation. The error was: +$ac_distutils_result" "$LINENO" 5 + PYTHON_VERSION="" + fi + + # + # Check for Python include path + # + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python include path" >&5 +$as_echo_n "checking for Python include path... " >&6; } + if test -z "$PYTHON_CPPFLAGS"; then + python_path=`$PYTHON -c "import distutils.sysconfig; \ + print distutils.sysconfig.get_python_inc();"` + if test -n "${python_path}"; then + python_path="-I$python_path" + fi + PYTHON_CPPFLAGS=$python_path + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_CPPFLAGS" >&5 +$as_echo "$PYTHON_CPPFLAGS" >&6; } + + + # + # Check for Python library path + # + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python library path" >&5 +$as_echo_n "checking for Python library path... " >&6; } + if test -z "$PYTHON_LDFLAGS"; then + # (makes two attempts to ensure we've got a version number + # from the interpreter) + py_version=`$PYTHON -c "from distutils.sysconfig import *; \ + from string import join; \ + print join(get_config_vars('VERSION'))"` + if test "$py_version" = "None"; then + if test -n "$PYTHON_VERSION"; then + py_version=$PYTHON_VERSION + else + py_version=`$PYTHON -c "import sys; \ + print sys.version[:3]"` + fi + fi + + PYTHON_LDFLAGS=`$PYTHON -c "from distutils.sysconfig import *; \ + from string import join; \ + print '-L' + get_python_lib(0,1), \ + '-L' + os.path.dirname(get_python_lib(0,1)), \ + '-lpython';"`$py_version + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_LDFLAGS" >&5 +$as_echo "$PYTHON_LDFLAGS" >&6; } + + + # + # Check for site packages + # + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python site-packages path" >&5 +$as_echo_n "checking for Python site-packages path... " >&6; } + if test -z "$PYTHON_SITE_PKG"; then + PYTHON_SITE_PKG=`$PYTHON -c "import distutils.sysconfig; \ + print distutils.sysconfig.get_python_lib(1,0);"` + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_SITE_PKG" >&5 +$as_echo "$PYTHON_SITE_PKG" >&6; } + + + # + # libraries which must be linked in when embedding + # + { $as_echo "$as_me:${as_lineno-$LINENO}: checking python extra libraries" >&5 +$as_echo_n "checking python extra libraries... " >&6; } + if test -z "$PYTHON_EXTRA_LIBS"; then + PYTHON_EXTRA_LIBS=`$PYTHON -c "import distutils.sysconfig; \ + conf = distutils.sysconfig.get_config_var; \ + print conf('LOCALMODLIBS'), conf('LIBS')"` + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_EXTRA_LIBS" >&5 +$as_echo "$PYTHON_EXTRA_LIBS" >&6; } + + + # + # linking flags needed when embedding + # + { $as_echo "$as_me:${as_lineno-$LINENO}: checking python extra linking flags" >&5 +$as_echo_n "checking python extra linking flags... " >&6; } + if test -z "$PYTHON_EXTRA_LDFLAGS"; then + PYTHON_EXTRA_LDFLAGS=`$PYTHON -c "import distutils.sysconfig; \ + conf = distutils.sysconfig.get_config_var; \ + print conf('LINKFORSHARED')"` + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_EXTRA_LDFLAGS" >&5 +$as_echo "$PYTHON_EXTRA_LDFLAGS" >&6; } + + + # + # final check to see if everything compiles alright + # + { $as_echo "$as_me:${as_lineno-$LINENO}: checking consistency of all components of python development environment" >&5 +$as_echo_n "checking consistency of all components of python development environment... " >&6; } + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + # save current global flags + LIBS="$ac_save_LIBS $PYTHON_LDFLAGS" + CPPFLAGS="$ac_save_CPPFLAGS $PYTHON_CPPFLAGS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + +int +main () +{ + + Py_Initialize(); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + pythonexists=yes +else + pythonexists=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $pythonexists" >&5 +$as_echo "$pythonexists" >&6; } + + if test ! "$pythonexists" = "yes"; then + as_fn_error $? " + Could not link test program to Python. Maybe the main Python library has been + installed in some non-standard library path. If so, pass it to configure, + via the LDFLAGS environment variable. + Example: ./configure LDFLAGS=\"-L/usr/non-standard-path/python/lib\" + ============================================================================ + ERROR! + You probably have to install the development version of the Python package + for your distribution. The exact name of this package varies among them. + ============================================================================ + " "$LINENO" 5 + PYTHON_VERSION="" + fi + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + # turn back to default flags + CPPFLAGS="$ac_save_CPPFLAGS" + LIBS="$ac_save_LIBS" + + # + # all done! + # + + if test ! -z "$PYTHON_VERSION"; then + if test `$PYTHON -c "print '$PYTHON_VERSION' >= '2.4.0'"` = "False"; then + as_fn_error $? "Python version >= 2.4.0 is required" "$LINENO" 5 + fi + + # Have Python + +$as_echo "#define HAVE_PYTHON 1" >>confdefs.h + + LIBS="$PYTHON_LDFLAGS $LIBS" + CPPFLAGS="$CPPFLAGS $PYTHON_CPPFLAGS" + ub_have_python=yes + + # Check for SWIG + ub_have_swig=no + + # Extract the first word of "swig", so it can be a program name with args. +set dummy swig; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_SWIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $SWIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_SWIG="$SWIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_SWIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +SWIG=$ac_cv_path_SWIG +if test -n "$SWIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SWIG" >&5 +$as_echo "$SWIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test -z "$SWIG" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cannot find 'swig' program. You should look at http://www.swig.org" >&5 +$as_echo "$as_me: WARNING: cannot find 'swig' program. You should look at http://www.swig.org" >&2;} + SWIG='echo "Error: SWIG is not installed. You should look at http://www.swig.org" ; false' + elif test -n "" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SWIG version" >&5 +$as_echo_n "checking for SWIG version... " >&6; } + swig_version=`$SWIG -version 2>&1 | grep 'SWIG Version' | sed 's/.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/g'` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $swig_version" >&5 +$as_echo "$swig_version" >&6; } + if test -n "$swig_version" ; then + # Calculate the required version number components + required= + required_major=`echo $required | sed 's/[^0-9].*//'` + if test -z "$required_major" ; then + required_major=0 + fi + required=`echo $required | sed 's/[0-9]*[^0-9]//'` + required_minor=`echo $required | sed 's/[^0-9].*//'` + if test -z "$required_minor" ; then + required_minor=0 + fi + required=`echo $required | sed 's/[0-9]*[^0-9]//'` + required_patch=`echo $required | sed 's/[^0-9].*//'` + if test -z "$required_patch" ; then + required_patch=0 + fi + # Calculate the available version number components + available=$swig_version + available_major=`echo $available | sed 's/[^0-9].*//'` + if test -z "$available_major" ; then + available_major=0 + fi + available=`echo $available | sed 's/[0-9]*[^0-9]//'` + available_minor=`echo $available | sed 's/[^0-9].*//'` + if test -z "$available_minor" ; then + available_minor=0 + fi + available=`echo $available | sed 's/[0-9]*[^0-9]//'` + available_patch=`echo $available | sed 's/[^0-9].*//'` + if test -z "$available_patch" ; then + available_patch=0 + fi + if test $available_major -ne $required_major \ + -o $available_minor -ne $required_minor \ + -o $available_patch -lt $required_patch ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: SWIG version >= is required. You have $swig_version. You should look at http://www.swig.org" >&5 +$as_echo "$as_me: WARNING: SWIG version >= is required. You have $swig_version. You should look at http://www.swig.org" >&2;} + SWIG='echo "Error: SWIG version >= is required. You have '"$swig_version"'. You should look at http://www.swig.org" ; false' + else + { $as_echo "$as_me:${as_lineno-$LINENO}: SWIG executable is '$SWIG'" >&5 +$as_echo "$as_me: SWIG executable is '$SWIG'" >&6;} + SWIG_LIB=`$SWIG -swiglib` + { $as_echo "$as_me:${as_lineno-$LINENO}: SWIG library directory is '$SWIG_LIB'" >&5 +$as_echo "$as_me: SWIG library directory is '$SWIG_LIB'" >&6;} + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cannot determine SWIG version" >&5 +$as_echo "$as_me: WARNING: cannot determine SWIG version" >&2;} + SWIG='echo "Error: Cannot determine SWIG version. You should look at http://www.swig.org" ; false' + fi + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking SWIG" >&5 +$as_echo_n "checking SWIG... " >&6; } + if test ! -x "$SWIG"; then + as_fn_error $? "failed to find swig tool, install it, or do not build Python module and PyUnbound" "$LINENO" 5 + else + +$as_echo "#define HAVE_SWIG 1" >>confdefs.h + + swig="$SWIG" + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: present" >&5 +$as_echo "present" >&6; } + + # If have Python & SWIG + # Declare PythonMod + if test x_$ub_with_pythonmod != x_no; then + +$as_echo "#define WITH_PYTHONMODULE 1" >>confdefs.h + + WITH_PYTHONMODULE=yes + + PYTHONMOD_OBJ="pythonmod.lo pythonmod_utils.lo" + + PYTHONMOD_HEADER='$(srcdir)/pythonmod/pythonmod.h' + + PYTHONMOD_INSTALL=pythonmod-install + + PYTHONMOD_UNINSTALL=pythonmod-uninstall + + fi + + # Declare PyUnbound + if test x_$ub_with_pyunbound != x_no; then + +$as_echo "#define WITH_PYUNBOUND 1" >>confdefs.h + + WITH_PYUNBOUND=yes + + PYUNBOUND_OBJ="libunbound_wrap.lo" + + PYUNBOUND_TARGET="_unbound.la" + + PYUNBOUND_INSTALL=pyunbound-install + + PYUNBOUND_UNINSTALL=pyunbound-uninstall + + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: *** Python libraries not found, won't build PythonMod or PyUnbound ***" >&5 +$as_echo "*** Python libraries not found, won't build PythonMod or PyUnbound ***" >&6; } + ub_with_pyunbound=no + ub_with_pythonmod=no + fi +fi + +if test "`uname`" = "NetBSD"; then + NETBSD_LINTFLAGS='"-D__RENAME(x)=" -D_NETINET_IN_H_' + +fi +CONFIG_DATE=`date +%Y%m%d` + + +# Checks for libraries. + + +# Check whether --with-ssl was given. +if test "${with_ssl+set}" = set; then : + withval=$with_ssl; + +else + + withval="yes" + +fi + + if test x_$withval = x_no; then + as_fn_error $? "Need SSL library to do digital signature cryptography" "$LINENO" 5 + fi + + withval=$withval + if test x_$withval != x_no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL" >&5 +$as_echo_n "checking for SSL... " >&6; } + if test x_$withval = x_ -o x_$withval = x_yes; then + withval="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw /usr" + fi + for dir in $withval; do + ssldir="$dir" + if test -f "$dir/include/openssl/ssl.h"; then + found_ssl="yes" + +cat >>confdefs.h <<_ACEOF +#define HAVE_SSL /**/ +_ACEOF + + if test "$ssldir" != "/usr"; then + CPPFLAGS="$CPPFLAGS -I$ssldir/include" + LIBSSL_CPPFLAGS="$LIBSSL_CPPFLAGS -I$ssldir/include" + fi + break; + fi + done + if test x_$found_ssl != x_yes; then + as_fn_error $? "Cannot find the SSL libraries in $withval" "$LINENO" 5 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in $ssldir" >&5 +$as_echo "found in $ssldir" >&6; } + HAVE_SSL=yes + if test "$ssldir" != "/usr" -a "$ssldir" != ""; then + LDFLAGS="$LDFLAGS -L$ssldir/lib" + LIBSSL_LDFLAGS="$LIBSSL_LDFLAGS -L$ssldir/lib" + + if test "x$enable_rpath" = xyes; then + if echo "$ssldir/lib" | grep "^/" >/dev/null; then + RUNTIME_PATH="$RUNTIME_PATH -R$ssldir/lib" + fi + fi + + 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; } + LIBS="$LIBS -lcrypto" + LIBSSL_LIBS="$LIBSSL_LIBS -lcrypto" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + int HMAC_CTX_init(void); + (void)HMAC_CTX_init(); + + ; + return 0; +} +_ACEOF +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 + + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + # check if -lwsock32 or -lgdi32 are needed. + BAKLIBS="$LIBS" + BAKSSLLIBS="$LIBSSL_LIBS" + LIBS="$LIBS -lgdi32" + LIBSSL_LIBS="$LIBSSL_LIBS -lgdi32" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if -lcrypto needs -lgdi32" >&5 +$as_echo_n "checking if -lcrypto needs -lgdi32... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + int HMAC_CTX_init(void); + (void)HMAC_CTX_init(); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + +$as_echo "#define HAVE_HMAC_CTX_INIT 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; } + LIBS="$BAKLIBS" + LIBSSL_LIBS="$BAKSSLLIBS" + LIBS="$LIBS -ldl" + LIBSSL_LIBS="$LIBSSL_LIBS -ldl" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if -lcrypto needs -ldl" >&5 +$as_echo_n "checking if -lcrypto needs -ldl... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + int HMAC_CTX_init(void); + (void)HMAC_CTX_init(); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + +$as_echo "#define HAVE_HMAC_CTX_INIT 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 \ + conftest$ac_exeext conftest.$ac_ext + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + fi + + + # openssl engine functionality needs dlopen(). + BAKLIBS="$LIBS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5 +$as_echo_n "checking for library containing dlopen... " >&6; } +if ${ac_cv_search_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +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 dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +for ac_lib in '' dl; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_dlopen=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_dlopen+:} false; then : + break +fi +done +if ${ac_cv_search_dlopen+:} false; then : + +else + ac_cv_search_dlopen=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5 +$as_echo "$ac_cv_search_dlopen" >&6; } +ac_res=$ac_cv_search_dlopen +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + + if test "$LIBS" != "$BAKLIBS"; then + LIBSSL_LIBS="$LIBSSL_LIBS -ldl" + fi + fi +for ac_header in openssl/ssl.h +do : + ac_fn_c_check_header_compile "$LINENO" "openssl/ssl.h" "ac_cv_header_openssl_ssl_h" "$ac_includes_default +" +if test "x$ac_cv_header_openssl_ssl_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OPENSSL_SSL_H 1 +_ACEOF + +fi + +done + +for ac_header in openssl/err.h +do : + ac_fn_c_check_header_compile "$LINENO" "openssl/err.h" "ac_cv_header_openssl_err_h" "$ac_includes_default +" +if test "x$ac_cv_header_openssl_err_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OPENSSL_ERR_H 1 +_ACEOF + +fi + +done + +for ac_header in openssl/rand.h +do : + ac_fn_c_check_header_compile "$LINENO" "openssl/rand.h" "ac_cv_header_openssl_rand_h" "$ac_includes_default +" +if test "x$ac_cv_header_openssl_rand_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OPENSSL_RAND_H 1 +_ACEOF + +fi + +done + + + + +# check if libssl needs libdl +BAKLIBS="$LIBS" +LIBS="-lssl $LIBS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if libssl needs libdl" >&5 +$as_echo_n "checking if libssl needs libdl... " >&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 SSL_CTX_new (); +int +main () +{ +return SSL_CTX_new (); + ; + 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" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5 +$as_echo_n "checking for library containing dlopen... " >&6; } +if ${ac_cv_search_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +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 dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +for ac_lib in '' dl; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_dlopen=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_dlopen+:} false; then : + break +fi +done +if ${ac_cv_search_dlopen+:} false; then : + +else + ac_cv_search_dlopen=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5 +$as_echo "$ac_cv_search_dlopen" >&6; } +ac_res=$ac_cv_search_dlopen +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +for ac_header in openssl/conf.h +do : + ac_fn_c_check_header_compile "$LINENO" "openssl/conf.h" "ac_cv_header_openssl_conf_h" "$ac_includes_default +" +if test "x$ac_cv_header_openssl_conf_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OPENSSL_CONF_H 1 +_ACEOF + +fi + +done + +for ac_header in openssl/engine.h +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 : + cat >>confdefs.h <<_ACEOF +#define HAVE_OPENSSL_ENGINE_H 1 +_ACEOF + +fi + +done + +for ac_func in OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 +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 : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +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 +#include +#endif + +#ifdef HAVE_OPENSSL_RAND_H +#include +#endif + +#ifdef HAVE_OPENSSL_CONF_H +#include +#endif + +#ifdef HAVE_OPENSSL_ENGINE_H +#include +#endif +#include +#include + +" +if test "x$ac_cv_have_decl_SSL_COMP_get_compression_methods" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "sk_SSL_COMP_pop_free" "ac_cv_have_decl_sk_SSL_COMP_pop_free" " +$ac_includes_default +#ifdef HAVE_OPENSSL_ERR_H +#include +#endif + +#ifdef HAVE_OPENSSL_RAND_H +#include +#endif + +#ifdef HAVE_OPENSSL_CONF_H +#include +#endif + +#ifdef HAVE_OPENSSL_ENGINE_H +#include +#endif +#include +#include + +" +if test "x$ac_cv_have_decl_sk_SSL_COMP_pop_free" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_SK_SSL_COMP_POP_FREE $ac_have_decl +_ACEOF + + +# Check whether --enable-sha2 was given. +if test "${enable_sha2+set}" = set; then : + enableval=$enable_sha2; +fi + +case "$enable_sha2" in + no) + ;; + yes|*) + +$as_echo "#define USE_SHA2 1" >>confdefs.h + + ;; +esac + +# check wether gost also works + +# Check whether --enable-gost was given. +if test "${enable_gost+set}" = set; then : + enableval=$enable_gost; +fi + +use_gost="no" +case "$enable_gost" in + no) + ;; + *) + ac_fn_c_check_func "$LINENO" "EVP_PKEY_set_type_str" "ac_cv_func_EVP_PKEY_set_type_str" +if test "x$ac_cv_func_EVP_PKEY_set_type_str" = xyes; then : + : +else + as_fn_error $? "OpenSSL 1.0.0 is needed for GOST support" "$LINENO" 5 +fi + + ac_fn_c_check_func "$LINENO" "EC_KEY_new" "ac_cv_func_EC_KEY_new" +if test "x$ac_cv_func_EC_KEY_new" = xyes; then : + +else + as_fn_error $? "OpenSSL does not support ECC, needed for GOST support" "$LINENO" 5 +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if GOST works" >&5 +$as_echo_n "checking if GOST works... " >&6; } +if test c${cross_compiling} = cno; then +BAKCFLAGS="$CFLAGS" +if test -n "$ssldir"; then + CFLAGS="$CFLAGS -Wl,-rpath,$ssldir/lib" +fi +if test "$cross_compiling" = yes; then : + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run test program while cross compiling +See \`config.log' for more details" "$LINENO" 5; } +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +#include +#include +#include +/* routine to load gost from ldns */ +int load_gost_id(void) +{ + static int gost_id = 0; + const EVP_PKEY_ASN1_METHOD* meth; + ENGINE* e; + + if(gost_id) return gost_id; + + /* see if configuration loaded gost implementation from other engine*/ + meth = EVP_PKEY_asn1_find_str(NULL, "gost2001", -1); + if(meth) { + EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth); + return gost_id; + } + + /* see if engine can be loaded already */ + e = ENGINE_by_id("gost"); + if(!e) { + /* load it ourself, in case statically linked */ + ENGINE_load_builtin_engines(); + ENGINE_load_dynamic(); + e = ENGINE_by_id("gost"); + } + if(!e) { + /* no gost engine in openssl */ + return 0; + } + if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) { + ENGINE_finish(e); + ENGINE_free(e); + return 0; + } + + meth = EVP_PKEY_asn1_find_str(&e, "gost2001", -1); + if(!meth) { + /* algo not found */ + ENGINE_finish(e); + ENGINE_free(e); + return 0; + } + EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth); + return gost_id; +} +int main(void) { + EVP_MD_CTX* ctx; + const EVP_MD* md; + unsigned char digest[64]; /* its a 256-bit digest, so uses 32 bytes */ + const char* str = "Hello world"; + const unsigned char check[] = { + 0x40 , 0xed , 0xf8 , 0x56 , 0x5a , 0xc5 , 0x36 , 0xe1 , + 0x33 , 0x7c , 0x7e , 0x87 , 0x62 , 0x1c , 0x42 , 0xe0 , + 0x17 , 0x1b , 0x5e , 0xce , 0xa8 , 0x46 , 0x65 , 0x4d , + 0x8d , 0x3e , 0x22 , 0x9b , 0xe1 , 0x30 , 0x19 , 0x9d + }; + OPENSSL_config(NULL); + (void)load_gost_id(); + md = EVP_get_digestbyname("md_gost94"); + if(!md) return 1; + memset(digest, 0, sizeof(digest)); + ctx = EVP_MD_CTX_create(); + if(!ctx) return 2; + if(!EVP_DigestInit_ex(ctx, md, NULL)) return 3; + if(!EVP_DigestUpdate(ctx, str, 10)) return 4; + if(!EVP_DigestFinal_ex(ctx, digest, NULL)) return 5; + /* uncomment to see the hash calculated. + {int i; + for(i=0; i<32; i++) + printf(" %2.2x", (int)digest[i]); + printf("\n");} + */ + if(memcmp(digest, check, sizeof(check)) != 0) + return 6; + return 0; +} + +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + eval "ac_cv_c_gost_works=yes" +else + eval "ac_cv_c_gost_works=no" +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +CFLAGS="$BAKCFLAGS" +else +eval "ac_cv_c_gost_works=maybe" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_gost_works" >&5 +$as_echo "$ac_cv_c_gost_works" >&6; } + + if test $ac_cv_c_gost_works != no; then + use_gost="yes" + +$as_echo "#define USE_GOST 1" >>confdefs.h + + fi + ;; +esac + +# Check whether --enable-ecdsa was given. +if test "${enable_ecdsa+set}" = set; then : + enableval=$enable_ecdsa; +fi + +use_ecdsa="no" +case "$enable_ecdsa" in + no) + ;; + *) + ac_fn_c_check_func "$LINENO" "ECDSA_sign" "ac_cv_func_ECDSA_sign" +if test "x$ac_cv_func_ECDSA_sign" = xyes; then : + +else + as_fn_error $? "OpenSSL does not support ECDSA: please upgrade or rerun with --disable-ecdsa" "$LINENO" 5 +fi + + ac_fn_c_check_func "$LINENO" "SHA384_Init" "ac_cv_func_SHA384_Init" +if test "x$ac_cv_func_SHA384_Init" = xyes; then : + +else + as_fn_error $? "OpenSSL does not support SHA384: please upgrade or rerun with --disable-ecdsa" "$LINENO" 5 +fi + + ac_fn_c_check_decl "$LINENO" "NID_X9_62_prime256v1" "ac_cv_have_decl_NID_X9_62_prime256v1" "$ac_includes_default +#include + +" +if test "x$ac_cv_have_decl_NID_X9_62_prime256v1" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_NID_X9_62_PRIME256V1 $ac_have_decl +_ACEOF +if test $ac_have_decl = 1; then : + +else + as_fn_error $? "OpenSSL does not support the ECDSA curves: please upgrade or rerun with --disable-ecdsa" "$LINENO" 5 +fi +ac_fn_c_check_decl "$LINENO" "NID_secp384r1" "ac_cv_have_decl_NID_secp384r1" "$ac_includes_default +#include + +" +if test "x$ac_cv_have_decl_NID_secp384r1" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_NID_SECP384R1 $ac_have_decl +_ACEOF +if test $ac_have_decl = 1; then : + +else + as_fn_error $? "OpenSSL does not support the ECDSA curves: please upgrade or rerun with --disable-ecdsa" "$LINENO" 5 +fi + + # see if OPENSSL 1.0.0 or later (has EVP MD and Verify independency) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if openssl supports SHA2 and ECDSA with EVP" >&5 +$as_echo_n "checking if openssl supports SHA2 and ECDSA with EVP... " >&6; } + if grep OPENSSL_VERSION_NUMBER $ssldir/include/openssl/opensslv.h | grep 0x0 >/dev/null; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +cat >>confdefs.h <<_ACEOF +#define USE_ECDSA_EVP_WORKAROUND 1 +_ACEOF + + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + fi + # we now know we have ECDSA and the required curves. + +cat >>confdefs.h <<_ACEOF +#define USE_ECDSA 1 +_ACEOF + + use_ecdsa="yes" + ;; +esac + +# check for libevent + +# Check whether --with-libevent was given. +if test "${with_libevent+set}" = set; then : + withval=$with_libevent; +else + withval="no" +fi + +if test x_$withval = x_yes -o x_$withval != x_no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libevent" >&5 +$as_echo_n "checking for libevent... " >&6; } + if test x_$withval = x_ -o x_$withval = x_yes; then + withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr" + fi + for dir in $withval; do + thedir="$dir" + if test -f "$dir/include/event.h"; then + found_libevent="yes" + if test "$thedir" != "/usr"; then + CPPFLAGS="$CPPFLAGS -I$thedir/include" + fi + break; + fi + done + if test x_$found_libevent != x_yes; then + if test -f "$dir/event.h" -a \( -f "$dir/libevent.la" -o -f "$dir/libev.la" \) ; then + # libevent source directory + { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in $thedir" >&5 +$as_echo "found in $thedir" >&6; } + CPPFLAGS="$CPPFLAGS -I$thedir -I$thedir/include" + BAK_LDFLAGS_SET="1" + BAK_LDFLAGS="$LDFLAGS" + # remove evdns from linking + mkdir build >/dev/null 2>&1 + mkdir build/libevent >/dev/null 2>&1 + mkdir build/libevent/.libs >/dev/null 2>&1 + ev_files_o=`ls $thedir/*.o | grep -v evdns\.o | grep -v bufferevent_openssl\.o` + ev_files_lo=`ls $thedir/*.lo | grep -v evdns\.lo | grep -v bufferevent_openssl\.lo` + ev_files_libso=`ls $thedir/.libs/*.o | grep -v evdns\.o | grep -v bufferevent_openssl\.o` + cp $ev_files_o build/libevent + cp $ev_files_lo build/libevent + cp $ev_files_libso build/libevent/.libs + LATE_LDFLAGS="build/libevent/*.lo -lm" + LDFLAGS="build/libevent/*.o $LDFLAGS -lm" + else + as_fn_error $? "Cannot find the libevent library in $withval +You can restart ./configure --with-libevent=no to use a builtin alternative. +Please note that this alternative is not as capable as libevent when using +large outgoing port ranges. " "$LINENO" 5 + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in $thedir" >&5 +$as_echo "found in $thedir" >&6; } + if test "$thedir" != "/usr" -a "$thedir" != ""; then + LDFLAGS="$LDFLAGS -L$thedir/lib" + + if test "x$enable_rpath" = xyes; then + if echo "$thedir/lib" | grep "^/" >/dev/null; then + RUNTIME_PATH="$RUNTIME_PATH -R$thedir/lib" + fi + fi + + fi + fi + # check for library used by libevent after 1.3c + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5 +$as_echo_n "checking for library containing clock_gettime... " >&6; } +if ${ac_cv_search_clock_gettime+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +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 clock_gettime (); +int +main () +{ +return clock_gettime (); + ; + return 0; +} +_ACEOF +for ac_lib in '' rt; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_clock_gettime=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_clock_gettime+:} false; then : + break +fi +done +if ${ac_cv_search_clock_gettime+:} false; then : + +else + ac_cv_search_clock_gettime=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_clock_gettime" >&5 +$as_echo "$ac_cv_search_clock_gettime" >&6; } +ac_res=$ac_cv_search_clock_gettime +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + + + # is the event.h header libev or libevent? + for ac_header in event.h +do : + ac_fn_c_check_header_compile "$LINENO" "event.h" "ac_cv_header_event_h" "$ac_includes_default +" +if test "x$ac_cv_header_event_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_EVENT_H 1 +_ACEOF + +fi + +done + + ac_fn_c_check_decl "$LINENO" "EV_VERSION_MAJOR" "ac_cv_have_decl_EV_VERSION_MAJOR" "$ac_includes_default +#include + +" +if test "x$ac_cv_have_decl_EV_VERSION_MAJOR" = xyes; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing event_set" >&5 +$as_echo_n "checking for library containing event_set... " >&6; } +if ${ac_cv_search_event_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +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 event_set (); +int +main () +{ +return event_set (); + ; + return 0; +} +_ACEOF +for ac_lib in '' ev; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_event_set=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_event_set+:} false; then : + break +fi +done +if ${ac_cv_search_event_set+:} false; then : + +else + ac_cv_search_event_set=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_event_set" >&5 +$as_echo "$ac_cv_search_event_set" >&6; } +ac_res=$ac_cv_search_event_set +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing event_set" >&5 +$as_echo_n "checking for library containing event_set... " >&6; } +if ${ac_cv_search_event_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +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 event_set (); +int +main () +{ +return event_set (); + ; + return 0; +} +_ACEOF +for ac_lib in '' event; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_event_set=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_event_set+:} false; then : + break +fi +done +if ${ac_cv_search_event_set+:} false; then : + +else + ac_cv_search_event_set=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_event_set" >&5 +$as_echo "$ac_cv_search_event_set" >&6; } +ac_res=$ac_cv_search_event_set +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + + +fi + + for ac_func in event_base_free +do : + ac_fn_c_check_func "$LINENO" "event_base_free" "ac_cv_func_event_base_free" +if test "x$ac_cv_func_event_base_free" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_EVENT_BASE_FREE 1 +_ACEOF + +fi +done + # only in libevent 1.2 and later + for ac_func in event_base_once +do : + ac_fn_c_check_func "$LINENO" "event_base_once" "ac_cv_func_event_base_once" +if test "x$ac_cv_func_event_base_once" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_EVENT_BASE_ONCE 1 +_ACEOF + +fi +done + # only in libevent 1.4.1 and later + for ac_func in event_base_new +do : + ac_fn_c_check_func "$LINENO" "event_base_new" "ac_cv_func_event_base_new" +if test "x$ac_cv_func_event_base_new" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_EVENT_BASE_NEW 1 +_ACEOF + +fi +done + # only in libevent 1.4.1 and later + for ac_func in event_base_get_method +do : + ac_fn_c_check_func "$LINENO" "event_base_get_method" "ac_cv_func_event_base_get_method" +if test "x$ac_cv_func_event_base_get_method" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_EVENT_BASE_GET_METHOD 1 +_ACEOF + +fi +done + # only in libevent 1.4.3 and later + for ac_func in ev_loop +do : + ac_fn_c_check_func "$LINENO" "ev_loop" "ac_cv_func_ev_loop" +if test "x$ac_cv_func_ev_loop" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_EV_LOOP 1 +_ACEOF + +fi +done + # only in libev. (tested on 3.51) + for ac_func in ev_default_loop +do : + ac_fn_c_check_func "$LINENO" "ev_default_loop" "ac_cv_func_ev_default_loop" +if test "x$ac_cv_func_ev_default_loop" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_EV_DEFAULT_LOOP 1 +_ACEOF + +fi +done + # only in libev. (tested on 4.00) + if test -n "$BAK_LDFLAGS_SET"; then + LDFLAGS="$BAK_LDFLAGS" + fi +else + +$as_echo "#define USE_MINI_EVENT 1" >>confdefs.h + +fi + +# check for libexpat + +# Check whether --with-libexpat was given. +if test "${with_libexpat+set}" = set; then : + withval=$with_libexpat; +else + withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libexpat" >&5 +$as_echo_n "checking for libexpat... " >&6; } +found_libexpat="no" +for dir in $withval ; do + if test -f "$dir/include/expat.h"; then + found_libexpat="yes" + if test "$dir" != "/usr"; then + CPPFLAGS="$CPPFLAGS -I$dir/include" + LDFLAGS="$LDFLAGS -L$dir/lib" + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in $dir" >&5 +$as_echo "found in $dir" >&6; } + break; + fi +done +if test x_$found_libexpat != x_yes; then + as_fn_error $? "Could not find libexpat, expat.h" "$LINENO" 5 +fi +for ac_header in expat.h +do : + ac_fn_c_check_header_compile "$LINENO" "expat.h" "ac_cv_header_expat_h" "$ac_includes_default +" +if test "x$ac_cv_header_expat_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_EXPAT_H 1 +_ACEOF + +fi + +done + + +# set static linking if requested + +staticexe="" +# Check whether --enable-static-exe was given. +if test "${enable_static_exe+set}" = set; then : + enableval=$enable_static_exe; +fi + +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 + fi +fi + +# set lock checking if requested +# Check whether --enable-lock_checks was given. +if test "${enable_lock_checks+set}" = set; then : + enableval=$enable_lock_checks; +fi + +if test x_$enable_lock_checks = x_yes; then + +$as_echo "#define ENABLE_LOCK_CHECKS 1" >>confdefs.h + + CHECKLOCK_OBJ="checklocks.lo" + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for getaddrinfo" >&5 +$as_echo_n "checking for getaddrinfo... " >&6; } +ac_cv_func_getaddrinfo=no +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#ifdef __cplusplus +extern "C" +{ +#endif +char* getaddrinfo(); +char* (*f) () = getaddrinfo; +#ifdef __cplusplus +} +#endif +int main() { + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_func_getaddrinfo="yes" +if test "$ac_cv_header_windows_h" = "yes"; then + +$as_echo "#define USE_WINSOCK 1" >>confdefs.h + + USE_WINSOCK="1" + LIBS="$LIBS -lws2_32" +fi + +else + ORIGLIBS="$LIBS" +LIBS="$LIBS -lws2_32" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#ifdef HAVE_WS2TCPIP_H +#include +#endif + +int +main () +{ + + (void)getaddrinfo(NULL, NULL, NULL, NULL); + + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + +ac_cv_func_getaddrinfo="yes" + +$as_echo "#define USE_WINSOCK 1" >>confdefs.h + +USE_WINSOCK="1" + +else + +ac_cv_func_getaddrinfo="no" +LIBS="$ORIGLIBS" + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_getaddrinfo" >&5 +$as_echo "$ac_cv_func_getaddrinfo" >&6; } +if test $ac_cv_func_getaddrinfo = yes; then + +$as_echo "#define HAVE_GETADDRINFO 1" >>confdefs.h + +fi + +if test "$USE_WINSOCK" = 1; then + +$as_echo "#define UB_ON_WINDOWS 1" >>confdefs.h + + for ac_header in iphlpapi.h +do : + ac_fn_c_check_header_compile "$LINENO" "iphlpapi.h" "ac_cv_header_iphlpapi_h" "$ac_includes_default +#include + +" +if test "x$ac_cv_header_iphlpapi_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_IPHLPAPI_H 1 +_ACEOF + +fi + +done + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}windres", so it can be a program name with args. +set dummy ${ac_tool_prefix}windres; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_WINDRES+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$WINDRES"; then + ac_cv_prog_WINDRES="$WINDRES" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_WINDRES="${ac_tool_prefix}windres" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +WINDRES=$ac_cv_prog_WINDRES +if test -n "$WINDRES"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WINDRES" >&5 +$as_echo "$WINDRES" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_WINDRES"; then + ac_ct_WINDRES=$WINDRES + # Extract the first word of "windres", so it can be a program name with args. +set dummy windres; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_WINDRES+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_WINDRES"; then + ac_cv_prog_ac_ct_WINDRES="$ac_ct_WINDRES" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_WINDRES="windres" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_WINDRES=$ac_cv_prog_ac_ct_WINDRES +if test -n "$ac_ct_WINDRES"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_WINDRES" >&5 +$as_echo "$ac_ct_WINDRES" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_WINDRES" = x; then + WINDRES="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + WINDRES=$ac_ct_WINDRES + fi +else + WINDRES="$ac_cv_prog_WINDRES" +fi + + LIBS="$LIBS -liphlpapi" + WINAPPS="unbound-service-install.exe unbound-service-remove.exe anchor-update.exe" + + WIN_DAEMON_SRC="winrc/win_svc.c winrc/w_inst.c" + + WIN_DAEMON_OBJ="win_svc.lo w_inst.lo" + + WIN_DAEMON_OBJ_LINK="rsrc_unbound.o" + + WIN_HOST_OBJ_LINK="rsrc_unbound_host.o" + + WIN_UBANCHOR_OBJ_LINK="rsrc_unbound_anchor.o log.lo locks.lo" + + WIN_CONTROL_OBJ_LINK="rsrc_unbound_control.o" + + WIN_CHECKCONF_OBJ_LINK="rsrc_unbound_checkconf.o" + +fi +if test $ac_cv_func_getaddrinfo = no; then + case " $LIBOBJS " in + *" fake-rfc2553.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS fake-rfc2553.$ac_objext" + ;; +esac + +fi +# check after getaddrinfo for its libraries + +# check ioctlsocket +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ioctlsocket" >&5 +$as_echo_n "checking for ioctlsocket... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#ifdef HAVE_WINSOCK2_H +#include +#endif + +int +main () +{ + + (void)ioctlsocket(0, 0, NULL); + + ; + return 0; +} +_ACEOF +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_IOCTLSOCKET 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + +# see if daemon(3) exists, and if it is deprecated. +for ac_func in daemon +do : + ac_fn_c_check_func "$LINENO" "daemon" "ac_cv_func_daemon" +if test "x$ac_cv_func_daemon" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DAEMON 1 +_ACEOF + +fi +done + +if test $ac_cv_func_daemon = yes; then + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if daemon is deprecated" >&5 +$as_echo_n "checking if daemon is deprecated... " >&6; } +cache=`echo daemon | sed 'y%.=/+-%___p_%'` +if eval \${cv_cc_deprecated_$cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + +echo ' +#include +' >conftest.c +echo 'void f(){ (void)daemon(0, 0); }' >>conftest.c +if test -z "`$CC -c conftest.c 2>&1 | grep deprecated`"; then +eval "cv_cc_deprecated_$cache=no" +else +eval "cv_cc_deprecated_$cache=yes" +fi +rm -f conftest conftest.o conftest.c + +fi + +if eval "test \"`echo '$cv_cc_deprecated_'$cache`\" = yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +cat >>confdefs.h <<_ACEOF +#define DEPRECATED_DAEMON 1 +_ACEOF + +: + +else +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +: + +fi + +fi + +ac_fn_c_check_member "$LINENO" "struct in_pktinfo" "ipi_spec_dst" "ac_cv_member_struct_in_pktinfo_ipi_spec_dst" " +$ac_includes_default +#if HAVE_SYS_PARAM_H +#include +#endif + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef HAVE_SYS_UIO_H +#include +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#ifdef HAVE_WINSOCK2_H +#include +#endif + +#ifdef HAVE_WS2TCPIP_H +#include +#endif + +" +if test "x$ac_cv_member_struct_in_pktinfo_ipi_spec_dst" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_IN_PKTINFO_IPI_SPEC_DST 1 +_ACEOF + + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing setusercontext" >&5 +$as_echo_n "checking for library containing setusercontext... " >&6; } +if ${ac_cv_search_setusercontext+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +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 setusercontext (); +int +main () +{ +return setusercontext (); + ; + return 0; +} +_ACEOF +for ac_lib in '' util; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_setusercontext=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_setusercontext+:} false; then : + break +fi +done +if ${ac_cv_search_setusercontext+:} false; then : + +else + ac_cv_search_setusercontext=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_setusercontext" >&5 +$as_echo "$ac_cv_search_setusercontext" >&6; } +ac_res=$ac_cv_search_setusercontext +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +for ac_func in tzset sigprocmask fcntl getpwnam getrlimit setrlimit setsid sbrk chroot kill sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex +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 : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in setresuid +do : + ac_fn_c_check_func "$LINENO" "setresuid" "ac_cv_func_setresuid" +if test "x$ac_cv_func_setresuid" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SETRESUID 1 +_ACEOF + +else + for ac_func in setreuid +do : + ac_fn_c_check_func "$LINENO" "setreuid" "ac_cv_func_setreuid" +if test "x$ac_cv_func_setreuid" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SETREUID 1 +_ACEOF + +fi +done + +fi +done + +for ac_func in setresgid +do : + ac_fn_c_check_func "$LINENO" "setresgid" "ac_cv_func_setresgid" +if test "x$ac_cv_func_setresgid" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SETRESGID 1 +_ACEOF + +else + for ac_func in setregid +do : + ac_fn_c_check_func "$LINENO" "setregid" "ac_cv_func_setregid" +if test "x$ac_cv_func_setregid" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SETREGID 1 +_ACEOF + +fi +done + +fi +done + + +# check if setreuid en setregid fail, on MacOSX10.4(darwin8). +if echo $build_os | grep darwin8 > /dev/null; then + +$as_echo "#define DARWIN_BROKEN_SETREUID 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "inet_aton" "ac_cv_func_inet_aton" +if test "x$ac_cv_func_inet_aton" = xyes; then : + $as_echo "#define HAVE_INET_ATON 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" inet_aton.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS inet_aton.$ac_objext" + ;; +esac + +fi + + +ac_fn_c_check_func "$LINENO" "inet_pton" "ac_cv_func_inet_pton" +if test "x$ac_cv_func_inet_pton" = xyes; then : + $as_echo "#define HAVE_INET_PTON 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" inet_pton.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS inet_pton.$ac_objext" + ;; +esac + +fi + + +ac_fn_c_check_func "$LINENO" "inet_ntop" "ac_cv_func_inet_ntop" +if test "x$ac_cv_func_inet_ntop" = xyes; then : + $as_echo "#define HAVE_INET_NTOP 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" inet_ntop.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS inet_ntop.$ac_objext" + ;; +esac + +fi + + +ac_fn_c_check_func "$LINENO" "snprintf" "ac_cv_func_snprintf" +if test "x$ac_cv_func_snprintf" = xyes; then : + $as_echo "#define HAVE_SNPRINTF 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" snprintf.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS snprintf.$ac_objext" + ;; +esac + +fi + + +ac_fn_c_check_func "$LINENO" "strlcpy" "ac_cv_func_strlcpy" +if test "x$ac_cv_func_strlcpy" = xyes; then : + $as_echo "#define HAVE_STRLCPY 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" strlcpy.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS strlcpy.$ac_objext" + ;; +esac + +fi + + +ac_fn_c_check_func "$LINENO" "memmove" "ac_cv_func_memmove" +if test "x$ac_cv_func_memmove" = xyes; then : + $as_echo "#define HAVE_MEMMOVE 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" memmove.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS memmove.$ac_objext" + ;; +esac + +fi + + +ac_fn_c_check_func "$LINENO" "gmtime_r" "ac_cv_func_gmtime_r" +if test "x$ac_cv_func_gmtime_r" = xyes; then : + $as_echo "#define HAVE_GMTIME_R 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" gmtime_r.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS gmtime_r.$ac_objext" + ;; +esac + +fi + + +LIBOBJ_WITHOUT_CTIME="$LIBOBJS" + +ac_fn_c_check_func "$LINENO" "ctime_r" "ac_cv_func_ctime_r" +if test "x$ac_cv_func_ctime_r" = xyes; then : + $as_echo "#define HAVE_CTIME_R 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" ctime_r.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS ctime_r.$ac_objext" + ;; +esac + +fi + + + +# Check whether --enable-allsymbols was given. +if test "${enable_allsymbols+set}" = set; then : + enableval=$enable_allsymbols; +fi + +case "$enable_allsymbols" in + yes) + COMMON_OBJ_ALL_SYMBOLS="" + UBSYMS="" + EXTRALINK="-L. -L.libs -lunbound" + +$as_echo "#define EXPORT_ALL_SYMBOLS 1" >>confdefs.h + + ;; + no|*) + COMMON_OBJ_ALL_SYMBOLS='$(COMMON_OBJ)' + UBSYMS='-export-symbols $(srcdir)/libunbound/ubsyms.def' + EXTRALINK="" + ;; +esac + + + +if test x_$enable_lock_checks = x_yes; then + UBSYMS="-export-symbols clubsyms.def" + cp ${srcdir}/libunbound/ubsyms.def clubsyms.def + echo lock_protect >> clubsyms.def + echo lock_unprotect >> clubsyms.def + echo lock_get_mem >> clubsyms.def + echo checklock_start >> clubsyms.def + echo checklock_stop >> clubsyms.def + echo checklock_lock >> clubsyms.def + echo checklock_unlock >> clubsyms.def + echo checklock_init >> clubsyms.def + echo checklock_thrcreate >> clubsyms.def + echo checklock_thrjoin >> clubsyms.def +fi + +{ $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. +# on Solaris, it does not work ($? is changed sources, $^ lists dependencies). +# gmake works. +cat >conftest.make </dev/null +rm -f conftest.make conftest.c conftest.dir/conftest.c +rm -rf conftest.dir +if test ! -f conftest.lo; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SOURCEDETERMINE='echo "$^" | awk "-F " "{print \$$1;}" > .source' + SOURCEFILE='`cat .source`' +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SOURCEDETERMINE=':' + SOURCEFILE='$<' +fi +rm -f conftest.lo + + + +# check this after all other compilation checks, since the linking of the lib +# may break checks after this. + +# Check whether --with-ldns was given. +if test "${with_ldns+set}" = set; then : + withval=$with_ldns; + if test "$withval" != "yes"; then + if test "$withval" != "/usr" -a "$withval" != ""; then + CPPFLAGS="-I$withval/include $CPPFLAGS" + LDFLAGS="-L$withval/lib $LDFLAGS" + + if test "x$enable_rpath" = xyes; then + if echo "$withval/lib" | grep "^/" >/dev/null; then + RUNTIME_PATH="$RUNTIME_PATH -R$withval/lib" + fi + fi + + fi + ldnsdir="$withval" + + fi + +fi + + +# check if ldns is good enough +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ldns_rr_new in -lldns" >&5 +$as_echo_n "checking for ldns_rr_new in -lldns... " >&6; } +if ${ac_cv_lib_ldns_ldns_rr_new+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lldns $LIBS" +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 ldns_rr_new (); +int +main () +{ +return ldns_rr_new (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_ldns_ldns_rr_new=yes +else + ac_cv_lib_ldns_ldns_rr_new=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ldns_ldns_rr_new" >&5 +$as_echo "$ac_cv_lib_ldns_ldns_rr_new" >&6; } +if test "x$ac_cv_lib_ldns_ldns_rr_new" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBLDNS 1 +_ACEOF + + LIBS="-lldns $LIBS" + +else + + as_fn_error $? "No ldns library found, install the ldns library into system lib dir or use --with-ldns=path to other location. The --with-ldns can point to the make-dir of ldns. Install the package ldns or download source http://www.nlnetlabs.nl/projects/ldns" "$LINENO" 5 + +fi + +ac_fn_c_check_func "$LINENO" "ldns_buffer_copy" "ac_cv_func_ldns_buffer_copy" +if test "x$ac_cv_func_ldns_buffer_copy" = xyes; then : + +fi + +ac_fn_c_check_func "$LINENO" "ldns_key_buf2rsa_raw" "ac_cv_func_ldns_key_buf2rsa_raw" +if test "x$ac_cv_func_ldns_key_buf2rsa_raw" = xyes; then : + +fi + +ac_fn_c_check_func "$LINENO" "ldns_get_random" "ac_cv_func_ldns_get_random" +if test "x$ac_cv_func_ldns_get_random" = xyes; then : + +fi + +ac_fn_c_check_func "$LINENO" "ldns_b32_ntop_extended_hex" "ac_cv_func_ldns_b32_ntop_extended_hex" +if test "x$ac_cv_func_ldns_b32_ntop_extended_hex" = xyes; then : + +fi + +if test x$use_gost = xyes; then + ac_fn_c_check_func "$LINENO" "ldns_key_EVP_load_gost_id" "ac_cv_func_ldns_key_EVP_load_gost_id" +if test "x$ac_cv_func_ldns_key_EVP_load_gost_id" = xyes; then : + +fi + + for ac_func in ldns_key_EVP_unload_gost +do : + ac_fn_c_check_func "$LINENO" "ldns_key_EVP_unload_gost" "ac_cv_func_ldns_key_EVP_unload_gost" +if test "x$ac_cv_func_ldns_key_EVP_unload_gost" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LDNS_KEY_EVP_UNLOAD_GOST 1 +_ACEOF + +fi +done + +else + ac_cv_func_ldns_key_EVP_load_gost_id="yes" +fi +if test x$use_ecdsa = xyes; then + ac_fn_c_check_decl "$LINENO" "LDNS_ECDSAP384SHA384" "ac_cv_have_decl_LDNS_ECDSAP384SHA384" " +$ac_includes_default +#ifdef HAVE_SYS_SOCKET_H +# include +#endif +#ifdef HAVE_WS2TCPIP_H +# include +#endif +#include + +" +if test "x$ac_cv_have_decl_LDNS_ECDSAP384SHA384" = xyes; then : + +fi + +else + ac_cv_have_decl_LDNS_ECDSAP384SHA384="yes" +fi +for ac_header in ldns/ldns.h +do : + ac_fn_c_check_header_compile "$LINENO" "ldns/ldns.h" "ac_cv_header_ldns_ldns_h" "$ac_includes_default +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#ifdef HAVE_WINSOCK2_H +#include +#endif + +#ifdef HAVE_WS2TCPIP_H +#include +#endif + +" +if test "x$ac_cv_header_ldns_ldns_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LDNS_LDNS_H 1 +_ACEOF + +else + + as_fn_error $? "No ldns include file found, install the ldns library development files. Install package ldns-dev or ldns-devel or download source http://www.nlnetlabs.nl/projects/ldns" "$LINENO" 5 + +fi + +done + +if test $ac_cv_func_ldns_buffer_copy = yes \ + -a $ac_cv_func_ldns_key_buf2rsa_raw = yes \ + -a $ac_cv_func_ldns_get_random = yes \ + -a $ac_cv_header_ldns_ldns_h = yes \ + -a $ac_cv_func_ldns_b32_ntop_extended_hex = yes \ + -a $ac_cv_func_ldns_key_EVP_load_gost_id = yes \ + -a $ac_cv_have_decl_LDNS_ECDSAP384SHA384 = yes; then + : +else + as_fn_error $? "ldns library is not recent, update the ldns library, install it into system lib dir or use --with-ldns=path to other location. The --with-ldns can point to the make-dir of ldns. Package libldns or download source http://www.nlnetlabs.nl/projects/ldns" "$LINENO" 5 +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: Stripping extension flags..." >&5 +$as_echo "$as_me: Stripping extension flags..." >&6;} + + if echo $CFLAGS | grep " -D_GNU_SOURCE" >/dev/null 2>&1; then + CFLAGS="`echo $CFLAGS | sed -e 's/ -D_GNU_SOURCE//g'`" + +$as_echo "#define OMITTED__D_GNU_SOURCE 1" >>confdefs.h + + fi + + + if echo $CFLAGS | grep " -D_BSD_SOURCE" >/dev/null 2>&1; then + CFLAGS="`echo $CFLAGS | sed -e 's/ -D_BSD_SOURCE//g'`" + +$as_echo "#define OMITTED__D_BSD_SOURCE 1" >>confdefs.h + + fi + + + if echo $CFLAGS | grep " -D__EXTENSIONS__" >/dev/null 2>&1; then + CFLAGS="`echo $CFLAGS | sed -e 's/ -D__EXTENSIONS__//g'`" + +$as_echo "#define OMITTED__D__EXTENSIONS__ 1" >>confdefs.h + + fi + + + if echo $CFLAGS | grep " -D_POSIX_C_SOURCE=200112" >/dev/null 2>&1; then + CFLAGS="`echo $CFLAGS | sed -e 's/ -D_POSIX_C_SOURCE=200112//g'`" + +$as_echo "#define OMITTED__D_POSIX_C_SOURCE_200112 1" >>confdefs.h + + fi + + + if echo $CFLAGS | grep " -D_XOPEN_SOURCE=600" >/dev/null 2>&1; then + CFLAGS="`echo $CFLAGS | sed -e 's/ -D_XOPEN_SOURCE=600//g'`" + +$as_echo "#define OMITTED__D_XOPEN_SOURCE_600 1" >>confdefs.h + + fi + + + if echo $CFLAGS | grep " -D_XOPEN_SOURCE_EXTENDED=1" >/dev/null 2>&1; then + CFLAGS="`echo $CFLAGS | sed -e 's/ -D_XOPEN_SOURCE_EXTENDED=1//g'`" + +$as_echo "#define OMITTED__D_XOPEN_SOURCE_EXTENDED_1 1" >>confdefs.h + + fi + + + if echo $CFLAGS | grep " -D_ALL_SOURCE" >/dev/null 2>&1; then + CFLAGS="`echo $CFLAGS | sed -e 's/ -D_ALL_SOURCE//g'`" + +$as_echo "#define OMITTED__D_ALL_SOURCE 1" >>confdefs.h + + fi + + + if echo $CFLAGS | grep " -D_LARGEFILE_SOURCE=1" >/dev/null 2>&1; then + CFLAGS="`echo $CFLAGS | sed -e 's/ -D_LARGEFILE_SOURCE=1//g'`" + +$as_echo "#define OMITTED__D_LARGEFILE_SOURCE_1 1" >>confdefs.h + + fi + + +LDFLAGS="$LATE_LDFLAGS $LDFLAGS" + + +cat >>confdefs.h <<_ACEOF +#define MAXSYSLOGMSGLEN 10240 +_ACEOF + + + + +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" + +ac_config_headers="$ac_config_headers config.h" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# 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.4.17, which was +generated by GNU Autoconf 2.68. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to ." + +_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.4.17 +configured by $0, generated by GNU Autoconf 2.68, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2010 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# + + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' +macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' +enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' +enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' +pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' +enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' +SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' +ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' +host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' +host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' +host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' +build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' +build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' +build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' +SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' +Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' +GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' +EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' +FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' +LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' +NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' +LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' +max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' +ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' +exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' +lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' +lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' +lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' +lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' +lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' +reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' +reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' +OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' +deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' +file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' +file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' +want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' +DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' +sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' +AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' +AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' +archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' +STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' +RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' +old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' +old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' +lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' +CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' +CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' +compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' +GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' +nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' +lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' +objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' +MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' +need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' +MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' +DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' +NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' +LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' +OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' +OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' +libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' +shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' +extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' +compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' +module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' +with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' +no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec_ld='`$ECHO "$hardcode_libdir_flag_spec_ld" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' +hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' +hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' +inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' +link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' +always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' +exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' +include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' +prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' +postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' +file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' +variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' +need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' +need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' +version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' +runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' +libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' +library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' +soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' +install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' +postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' +postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' +finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' +hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' +sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' +sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`' +hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' +enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' +old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' +striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' + +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in SHELL \ +ECHO \ +SED \ +GREP \ +EGREP \ +FGREP \ +LD \ +NM \ +LN_S \ +lt_SP2NL \ +lt_NL2SP \ +reload_flag \ +OBJDUMP \ +deplibs_check_method \ +file_magic_cmd \ +file_magic_glob \ +want_nocaseglob \ +DLLTOOL \ +sharedlib_from_linklib_cmd \ +AR \ +AR_FLAGS \ +archiver_list_spec \ +STRIP \ +RANLIB \ +CC \ +CFLAGS \ +compiler \ +lt_cv_sys_global_symbol_pipe \ +lt_cv_sys_global_symbol_to_cdecl \ +lt_cv_sys_global_symbol_to_c_name_address \ +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ +nm_file_list_spec \ +lt_prog_compiler_no_builtin_flag \ +lt_prog_compiler_pic \ +lt_prog_compiler_wl \ +lt_prog_compiler_static \ +lt_cv_prog_compiler_c_o \ +need_locks \ +MANIFEST_TOOL \ +DSYMUTIL \ +NMEDIT \ +LIPO \ +OTOOL \ +OTOOL64 \ +shrext_cmds \ +export_dynamic_flag_spec \ +whole_archive_flag_spec \ +compiler_needs_object \ +with_gnu_ld \ +allow_undefined_flag \ +no_undefined_flag \ +hardcode_libdir_flag_spec \ +hardcode_libdir_flag_spec_ld \ +hardcode_libdir_separator \ +exclude_expsyms \ +include_expsyms \ +file_list_spec \ +variables_saved_for_relink \ +libname_spec \ +library_names_spec \ +soname_spec \ +install_override_mode \ +finish_eval \ +old_striplib \ +striplib; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in reload_cmds \ +old_postinstall_cmds \ +old_postuninstall_cmds \ +old_archive_cmds \ +extract_expsyms_cmds \ +old_archive_from_new_cmds \ +old_archive_from_expsyms_cmds \ +archive_cmds \ +archive_expsym_cmds \ +module_cmds \ +module_expsym_cmds \ +export_symbols_cmds \ +prelink_cmds \ +postlink_cmds \ +postinstall_cmds \ +postuninstall_cmds \ +finish_cmds \ +sys_lib_search_path_spec \ +sys_lib_dlsearch_path_spec; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +ac_aux_dir='$ac_aux_dir' +xsi_shell='$xsi_shell' +lt_shell_append='$lt_shell_append' + +# See if we are running on zsh, and set the options which allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + + + PACKAGE='$PACKAGE' + VERSION='$VERSION' + TIMESTAMP='$TIMESTAMP' + RM='$RM' + ofile='$ofile' + + + + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; + "disable-rpath") CONFIG_COMMANDS="$CONFIG_COMMANDS disable-rpath" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "doc/example.conf") CONFIG_FILES="$CONFIG_FILES doc/example.conf" ;; + "doc/libunbound.3") CONFIG_FILES="$CONFIG_FILES doc/libunbound.3" ;; + "doc/unbound.8") CONFIG_FILES="$CONFIG_FILES doc/unbound.8" ;; + "doc/unbound-anchor.8") CONFIG_FILES="$CONFIG_FILES doc/unbound-anchor.8" ;; + "doc/unbound-checkconf.8") CONFIG_FILES="$CONFIG_FILES doc/unbound-checkconf.8" ;; + "doc/unbound.conf.5") CONFIG_FILES="$CONFIG_FILES doc/unbound.conf.5" ;; + "doc/unbound-control.8") CONFIG_FILES="$CONFIG_FILES doc/unbound-control.8" ;; + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi + ;; + + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "libtool":C) + + # See if we are running on zsh, and set the options which allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + + cfgfile="${ofile}T" + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL + +# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008, 2009, 2010 Free Software Foundation, +# Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is part of GNU Libtool. +# +# GNU Libtool is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, or +# obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +# The names of the tagged configurations supported by this script. +available_tags="" + +# ### BEGIN LIBTOOL CONFIG + +# Which release of libtool.m4 was used? +macro_version=$macro_version +macro_revision=$macro_revision + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# What type of objects to build. +pic_mode=$pic_mode + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# An echo program that protects backslashes. +ECHO=$lt_ECHO + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="\$SED -e 1s/^X//" + +# A grep program that handles long lines. +GREP=$lt_GREP + +# An ERE matcher. +EGREP=$lt_EGREP + +# A literal string matcher. +FGREP=$lt_FGREP + +# A BSD- or MS-compatible name lister. +NM=$lt_NM + +# Whether we need soft or hard links. +LN_S=$lt_LN_S + +# What is the maximum length of a command? +max_cmd_len=$max_cmd_len + +# Object file suffix (normally "o"). +objext=$ac_objext + +# Executable file suffix (normally ""). +exeext=$exeext + +# whether the shell understands "unset". +lt_unset=$lt_unset + +# turn spaces into newlines. +SP2NL=$lt_lt_SP2NL + +# turn newlines into spaces. +NL2SP=$lt_lt_NL2SP + +# convert \$build file names to \$host format. +to_host_file_cmd=$lt_cv_to_host_file_cmd + +# convert \$build files to toolchain format. +to_tool_file_cmd=$lt_cv_to_tool_file_cmd + +# An object symbol dumper. +OBJDUMP=$lt_OBJDUMP + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method = "file_magic". +file_magic_cmd=$lt_file_magic_cmd + +# How to find potential files when deplibs_check_method = "file_magic". +file_magic_glob=$lt_file_magic_glob + +# Find potential files using nocaseglob when deplibs_check_method = "file_magic". +want_nocaseglob=$lt_want_nocaseglob + +# DLL creation program. +DLLTOOL=$lt_DLLTOOL + +# Command to associate shared and link libraries. +sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd + +# The archiver. +AR=$lt_AR + +# Flags to create an archive. +AR_FLAGS=$lt_AR_FLAGS + +# How to feed a file listing to the archiver. +archiver_list_spec=$lt_archiver_list_spec + +# A symbol stripping program. +STRIP=$lt_STRIP + +# Commands used to install an old-style archive. +RANLIB=$lt_RANLIB +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Whether to use a lock for old archive extraction. +lock_old_archive_extraction=$lock_old_archive_extraction + +# A C compiler. +LTCC=$lt_CC + +# LTCC compiler flags. +LTCFLAGS=$lt_CFLAGS + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration. +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair. +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# Transform the output of nm in a C name address pair when lib prefix is needed. +global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix + +# Specify filename containing input files for \$NM. +nm_file_list_spec=$lt_nm_file_list_spec + +# The root where to search for dependent libraries,and in which our libraries should be installed. +lt_sysroot=$lt_sysroot + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# Used to examine libraries when file_magic_cmd begins with "file". +MAGIC_CMD=$MAGIC_CMD + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Manifest tool. +MANIFEST_TOOL=$lt_MANIFEST_TOOL + +# Tool to manipulate archived DWARF debug symbol files on Mac OS X. +DSYMUTIL=$lt_DSYMUTIL + +# Tool to change global to local symbols on Mac OS X. +NMEDIT=$lt_NMEDIT + +# Tool to manipulate fat objects and archives on Mac OS X. +LIPO=$lt_LIPO + +# ldd/readelf like tool for Mach-O binaries on Mac OS X. +OTOOL=$lt_OTOOL + +# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. +OTOOL64=$lt_OTOOL64 + +# Old archive suffix (normally "a"). +libext=$libext + +# Shared library suffix (normally ".so"). +shrext_cmds=$lt_shrext_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at link time. +variables_saved_for_relink=$lt_variables_saved_for_relink + +# Do we need the "lib" prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Library versioning type. +version_type=$version_type + +# Shared library runtime path variable. +runpath_var=$runpath_var + +# Shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Permission mode override for installation of shared libraries. +install_override_mode=$lt_install_override_mode + +# Command to use after installation of a shared archive. +postinstall_cmds=$lt_postinstall_cmds + +# Command to use after uninstallation of a shared archive. +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# As "finish_cmds", except a single script fragment to be evaled but +# not shown. +finish_eval=$lt_finish_eval + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Compile-time system search path for libraries. +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries. +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + + +# The linker used to build libraries. +LD=$lt_LD + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds + +# A language specific compiler. +CC=$lt_compiler + +# Is the compiler the GNU compiler? +with_gcc=$GCC + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds +module_expsym_cmds=$lt_module_expsym_cmds + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec + +# If ld is used when linking, flag to hardcode \$libdir into a binary +# during linking. This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \${shlibpath_var} if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds + +# Commands necessary for finishing linking programs. +postlink_cmds=$lt_postlink_cmds + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# ### END LIBTOOL CONFIG + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + +ltmain="$ac_aux_dir/ltmain.sh" + + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + if test x"$xsi_shell" = xyes; then + sed -e '/^func_dirname ()$/,/^} # func_dirname /c\ +func_dirname ()\ +{\ +\ case ${1} in\ +\ */*) func_dirname_result="${1%/*}${2}" ;;\ +\ * ) func_dirname_result="${3}" ;;\ +\ esac\ +} # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_basename ()$/,/^} # func_basename /c\ +func_basename ()\ +{\ +\ func_basename_result="${1##*/}"\ +} # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\ +func_dirname_and_basename ()\ +{\ +\ case ${1} in\ +\ */*) func_dirname_result="${1%/*}${2}" ;;\ +\ * ) func_dirname_result="${3}" ;;\ +\ esac\ +\ func_basename_result="${1##*/}"\ +} # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_stripname ()$/,/^} # func_stripname /c\ +func_stripname ()\ +{\ +\ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\ +\ # positional parameters, so assign one to ordinary parameter first.\ +\ func_stripname_result=${3}\ +\ func_stripname_result=${func_stripname_result#"${1}"}\ +\ func_stripname_result=${func_stripname_result%"${2}"}\ +} # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\ +func_split_long_opt ()\ +{\ +\ func_split_long_opt_name=${1%%=*}\ +\ func_split_long_opt_arg=${1#*=}\ +} # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\ +func_split_short_opt ()\ +{\ +\ func_split_short_opt_arg=${1#??}\ +\ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\ +} # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\ +func_lo2o ()\ +{\ +\ case ${1} in\ +\ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\ +\ *) func_lo2o_result=${1} ;;\ +\ esac\ +} # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_xform ()$/,/^} # func_xform /c\ +func_xform ()\ +{\ + func_xform_result=${1%.*}.lo\ +} # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_arith ()$/,/^} # func_arith /c\ +func_arith ()\ +{\ + func_arith_result=$(( $* ))\ +} # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_len ()$/,/^} # func_len /c\ +func_len ()\ +{\ + func_len_result=${#1}\ +} # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + +fi + +if test x"$lt_shell_append" = xyes; then + sed -e '/^func_append ()$/,/^} # func_append /c\ +func_append ()\ +{\ + eval "${1}+=\\${2}"\ +} # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\ +func_append_quoted ()\ +{\ +\ func_quote_for_eval "${2}"\ +\ eval "${1}+=\\\\ \\$func_quote_for_eval_result"\ +} # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + # Save a `func_append' function call where possible by direct use of '+=' + sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +else + # Save a `func_append' function call even when '+=' is not available + sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +fi + +if test x"$_lt_function_replace_fail" = x":"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5 +$as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;} +fi + + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" + + ;; + "disable-rpath":C) + sed < libtool > libtool-2 \ + 's/^hardcode_libdir_flag_spec.*$'/'hardcode_libdir_flag_spec=" -D__LIBTOOL_RPATH_SED__ "/' + mv libtool-2 libtool + chmod 755 libtool + libtool="./libtool" + ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + diff --git a/configure.ac b/configure.ac new file mode 100644 index 00000000000..92877285d47 --- /dev/null +++ b/configure.ac @@ -0,0 +1,1197 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. +AC_PREREQ(2.56) +sinclude(acx_nlnetlabs.m4) +sinclude(acx_pthread.m4) +sinclude(acx_python.m4) +sinclude(ac_pkg_swig.m4) + +AC_INIT(unbound, 1.4.17, unbound-bugs@nlnetlabs.nl, unbound) + +LIBUNBOUND_CURRENT=3 +LIBUNBOUND_REVISION=1 +LIBUNBOUND_AGE=1 +# 1.0.0 had 0:12:0 +# 1.0.1 had 0:13:0 +# 1.0.2 had 0:14:0 +# 1.1.0 had 0:15:0 +# 1.1.1 had 0:16:0 +# 1.2.0 had 0:17:0 +# 1.2.1 had 0:18:0 +# 1.3.0 had 1:0:0 # ub_cancel and -export-symbols. +# 1.3.1 had 1:1:0 +# 1.3.2 had 1:2:0 +# 1.3.3 had 1:3:0 +# 1.3.4 had 1:4:0 +# 1.4.0-snapshots had 1:5:0 +# 1.4.0 had 1:5:0 (not 2:0:0) # ub_result.why_bogus +# 1.4.1 had 2:1:0 +# 1.4.2 had 2:2:0 +# 1.4.3 had 2:3:0 +# 1.4.4 had 2:4:0 +# 1.4.5 had 2:5:0 +# 1.4.6 had 2:6:0 +# 1.4.7 had 2:7:0 +# 1.4.8 had 2:8:0 +# 1.4.9 had 2:9:0 +# 1.4.10 had 2:10:0 +# 1.4.11 had 2:11:0 +# 1.4.12 had 2:12:0 +# 1.4.13 had 2:13:0 +# and 1.4.13p1 and 1.4.13.p2 +# 1.4.14 had 2:14:0 +# 1.4.15 had 3:0:1 # adds ub_version() +# 1.4.16 had 3:1:1 +# 1.4.17 had 3:2:1 + +# Current -- the number of the binary API that we're implementing +# Revision -- which iteration of the implementation of the binary +# API are we supplying? +# Age -- How many previous binary API versions do we also +# support? +# +# If we release a new version that does not change the binary API, +# increment Revision. +# +# If we release a new version that changes the binary API, but does +# not break programs compiled against the old binary API, increment +# Current and Age. Set Revision to 0, since this is the first +# implementation of the new API. +# +# Otherwise, we're changing the binary API and breaking bakward +# compatibility with old binaries. Increment Current. Set Age to 0, +# since we're backward compatible with no previous APIs. Set Revision +# to 0 too. +AC_SUBST(LIBUNBOUND_CURRENT) +AC_SUBST(LIBUNBOUND_REVISION) +AC_SUBST(LIBUNBOUND_AGE) + +pretty_cmdline() { + cmdline="" + while test -n "$1"; do + cmdline="$cmdline '"`echo $1 | sed -e 's/\\\\/\\\\\\\\/g' | sed -e 's/"/\\\\"/g' `"'" + shift + done +} +pretty_cmdline $@ +AC_DEFINE_UNQUOTED(CONFIGURE_BUILD_WITH, ["$cmdline"], [configure flags]) +AC_CANONICAL_TARGET +AC_DEFINE_UNQUOTED(CONFIGURE_TARGET, ["$target"], [configure target system]) +AC_DEFINE_UNQUOTED(CONFIGURE_DATE, ["`date`"], [configure date]) + +CFLAGS="$CFLAGS" +AC_AIX + +dnl +dnl By default set prefix to /usr/local +dnl +case "$prefix" in + NONE) + prefix="/usr/local" + ;; +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" + else on_mingw="no"; fi +fi + +# +# Determine configuration file +# the eval is to evaluate shell expansion twice +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" +fi +AC_ARG_WITH([conf_file], + AC_HELP_STRING([--with-conf-file=path], + [Pathname to the Unbound configuration file]), + [ub_conf_file="$withval"]) +AC_SUBST(ub_conf_file) +ACX_ESCAPE_BACKSLASH($ub_conf_file, hdr_config) +AC_DEFINE_UNQUOTED(CONFIGFILE, ["$hdr_config"], [Pathname to the Unbound configuration file]) + +# Determine run, chroot directory and pidfile locations +AC_ARG_WITH(run-dir, + AC_HELP_STRING([--with-run-dir=path], + [set default directory to chdir to (by default dir part of cfg file)]), + UNBOUND_RUN_DIR="$withval", +if test $on_mingw = no; then + UNBOUND_RUN_DIR=`dirname "$ub_conf_file"` +else + UNBOUND_RUN_DIR="" +fi +) +AC_SUBST(UNBOUND_RUN_DIR) +ACX_ESCAPE_BACKSLASH($UNBOUND_RUN_DIR, hdr_run) +AC_DEFINE_UNQUOTED(RUN_DIR, ["$hdr_run"], [Directory to chdir to]) + +AC_ARG_WITH(chroot-dir, + AC_HELP_STRING([--with-chroot-dir=path], + [set default directory to chroot to (by default same as run-dir)]), + UNBOUND_CHROOT_DIR="$withval", +if test $on_mingw = no; then + UNBOUND_CHROOT_DIR="$UNBOUND_RUN_DIR" +else + UNBOUND_CHROOT_DIR="" +fi +) +AC_SUBST(UNBOUND_CHROOT_DIR) +ACX_ESCAPE_BACKSLASH($UNBOUND_CHROOT_DIR, hdr_chroot) +AC_DEFINE_UNQUOTED(CHROOT_DIR, ["$hdr_chroot"], [Directory to chroot to]) + +AC_ARG_WITH(share-dir, + AC_HELP_STRING([--with-share-dir=path], + [set default directory with shared data (by default same as share/unbound)]), + UNBOUND_SHARE_DIR="$withval", + UNBOUND_SHARE_DIR="$UNBOUND_RUN_DIR") +AC_SUBST(UNBOUND_SHARE_DIR) +AC_DEFINE_UNQUOTED(SHARE_DIR, ["$UNBOUND_SHARE_DIR"], [Shared data]) + +AC_ARG_WITH(pidfile, + AC_HELP_STRING([--with-pidfile=filename], + [set default pathname to unbound pidfile (default run-dir/unbound.pid)]), + UNBOUND_PIDFILE="$withval", +if test $on_mingw = no; then + UNBOUND_PIDFILE="$UNBOUND_RUN_DIR/unbound.pid" +else + UNBOUND_PIDFILE="" +fi +) +AC_SUBST(UNBOUND_PIDFILE) +ACX_ESCAPE_BACKSLASH($UNBOUND_PIDFILE, hdr_pid) +AC_DEFINE_UNQUOTED(PIDFILE, ["$hdr_pid"], [default pidfile location]) + +AC_ARG_WITH(rootkey-file, + AC_HELP_STRING([--with-rootkey-file=filename], + [set default pathname to root key file (default run-dir/root.key). This file is read and written.]), + UNBOUND_ROOTKEY_FILE="$withval", +if test $on_mingw = no; then + UNBOUND_ROOTKEY_FILE="$UNBOUND_RUN_DIR/root.key" +else + UNBOUND_ROOTKEY_FILE="C:\\Program Files\\Unbound\\root.key" +fi +) +AC_SUBST(UNBOUND_ROOTKEY_FILE) +ACX_ESCAPE_BACKSLASH($UNBOUND_ROOTKEY_FILE, hdr_rkey) +AC_DEFINE_UNQUOTED(ROOT_ANCHOR_FILE, ["$hdr_rkey"], [default rootkey location]) + +AC_ARG_WITH(rootcert-file, + AC_HELP_STRING([--with-rootcert-file=filename], + [set default pathname to root update certificate file (default run-dir/icannbundle.pem). This file need not exist if you are content with the builtin.]), + UNBOUND_ROOTCERT_FILE="$withval", +if test $on_mingw = no; then + UNBOUND_ROOTCERT_FILE="$UNBOUND_RUN_DIR/icannbundle.pem" +else + UNBOUND_ROOTCERT_FILE="C:\\Program Files\\Unbound\\icannbundle.pem" +fi +) +AC_SUBST(UNBOUND_ROOTCERT_FILE) +ACX_ESCAPE_BACKSLASH($UNBOUND_ROOTCERT_FILE, hdr_rpem) +AC_DEFINE_UNQUOTED(ROOT_CERT_FILE, ["$hdr_rpem"], [default rootcert location]) + +AC_ARG_WITH(username, + AC_HELP_STRING([--with-username=user], + [set default user that unbound changes to (default user is unbound)]), + UNBOUND_USERNAME="$withval", + UNBOUND_USERNAME="unbound") +AC_SUBST(UNBOUND_USERNAME) +AC_DEFINE_UNQUOTED(UB_USERNAME, ["$UNBOUND_USERNAME"], [default username]) + +AC_DEFINE(WINVER, 0x0502, [the version of the windows API enabled]) +ACX_RSRC_VERSION(wnvs) +AC_DEFINE_UNQUOTED(RSRC_PACKAGE_VERSION, [$wnvs], [version number for resource files]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_LANG_C +ACX_CHECK_COMPILER_FLAG(g, [CFLAGS="$CFLAGS -g"]) +ACX_CHECK_COMPILER_FLAG(O2, [CFLAGS="$CFLAGS -O2"]) +AC_PROG_CC +ACX_DEPFLAG +ACX_DETERMINE_EXT_FLAGS_UNBOUND + +# debug mode flags warnings +AC_ARG_ENABLE(checking, AC_HELP_STRING([--enable-checking], [Enable warnings, asserts, makefile-dependencies])) +AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug], [same as enable-checking])) +if test "$enable_debug" = "yes"; then debug_enabled="$enable_debug"; +else debug_enabled="$enable_checking"; fi +AC_SUBST(debug_enabled) +case "$debug_enabled" in + yes) + ACX_CHECK_COMPILER_FLAG(W, [CFLAGS="$CFLAGS -W"]) + ACX_CHECK_COMPILER_FLAG(Wall, [CFLAGS="$CFLAGS -Wall"]) + ACX_CHECK_COMPILER_FLAG(Wextra, [CFLAGS="$CFLAGS -Wextra"]) + ACX_CHECK_COMPILER_FLAG(Wdeclaration-after-statement, [CFLAGS="$CFLAGS -Wdeclaration-after-statement"]) + AC_DEFINE([UNBOUND_DEBUG], [], [define this to enable debug checks.]) + ;; + no|*) + # nothing to do. + ;; +esac +ACX_CHECK_FLTO + +AC_C_INLINE +ACX_CHECK_FORMAT_ATTRIBUTE +ACX_CHECK_UNUSED_ATTRIBUTE + +if test "$srcdir" != "."; then + CPPFLAGS="$CPPFLAGS -I$srcdir" +fi + +AC_DEFUN([ACX_YYLEX_DESTROY], [ + AC_MSG_CHECKING([for yylex_destroy]) + if echo %% | $LEX -t 2>&1 | grep yylex_destroy >/dev/null 2>&1; then + AC_DEFINE(LEX_HAS_YYLEX_DESTROY, 1, [if lex has yylex_destroy]) + AC_MSG_RESULT(yes) + else AC_MSG_RESULT(no); fi +]) + +AC_PROG_LEX +ACX_YYLEX_DESTROY +AC_PROG_YACC +AC_CHECK_PROG(doxygen, doxygen, doxygen) +AC_CHECK_TOOL(STRIP, strip) +ACX_LIBTOOL_C_ONLY + +# Checks for header files. +AC_CHECK_HEADERS([stdarg.h stdbool.h netinet/in.h sys/param.h sys/socket.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h],,, [AC_INCLUDES_DEFAULT]) + +# check for types. +# Using own tests for int64* because autoconf builtin only give 32bit. +AC_CHECK_TYPE(int8_t, signed char) +AC_CHECK_TYPE(int16_t, short) +AC_CHECK_TYPE(int32_t, int) +AC_CHECK_TYPE(int64_t, long long) +AC_CHECK_TYPE(uint8_t, unsigned char) +AC_CHECK_TYPE(uint16_t, unsigned short) +AC_CHECK_TYPE(uint32_t, unsigned int) +AC_CHECK_TYPE(uint64_t, unsigned long long) +AC_TYPE_SIZE_T +AC_CHECK_TYPE(ssize_t, int) +AC_TYPE_UID_T +AC_TYPE_PID_T +AC_TYPE_OFF_T +ACX_TYPE_U_CHAR +ACX_TYPE_RLIM_T +ACX_TYPE_SOCKLEN_T +ACX_TYPE_IN_ADDR_T +ACX_TYPE_IN_PORT_T +ACX_CHECK_MEMCMP_SIGNED + +# add option to disable the evil rpath +ACX_ARG_RPATH +AC_SUBST(RUNTIME_PATH) + +# check to see if libraries are needed for these functions. +AC_SEARCH_LIBS([inet_pton], [nsl]) +AC_SEARCH_LIBS([socket], [socket]) + +# check wether strptime also works +AC_DEFUN([AC_CHECK_STRPTIME_WORKS], +[AC_REQUIRE([AC_PROG_CC]) +AC_MSG_CHECKING(whether strptime works) +if test c${cross_compiling} = cno; then +AC_RUN_IFELSE([AC_LANG_SOURCE([[ +#define _XOPEN_SOURCE +#include +int main(void) { struct tm tm; char *res; +res = strptime("2010-07-15T00:00:00+00:00", "%t%Y%t-%t%m%t-%t%d%tT%t%H%t:%t%M%t:%t%S%t", &tm); +if (!res) return 2; +res = strptime("20070207111842", "%Y%m%d%H%M%S", &tm); +if (!res) return 1; return 0; } +]])] , [eval "ac_cv_c_strptime_works=yes"], [eval "ac_cv_c_strptime_works=no"]) +else +eval "ac_cv_c_strptime_works=maybe" +fi +AC_MSG_RESULT($ac_cv_c_strptime_works) +if test $ac_cv_c_strptime_works = no; then +AC_LIBOBJ(strptime) +else +AC_DEFINE_UNQUOTED([STRPTIME_WORKS], 1, [use default strptime.]) +fi +])dnl + +# check some functions of the OS before linking libs (while still runnable). +AC_FUNC_CHOWN +AC_FUNC_FORK +AC_TYPE_SIGNAL +AC_FUNC_FSEEKO +ACX_SYS_LARGEFILE +ACX_CHECK_NONBLOCKING_BROKEN +ACX_MKDIR_ONE_ARG +AC_CHECK_FUNCS([strptime],[AC_CHECK_STRPTIME_WORKS],[AC_LIBOBJ([strptime])]) + +# set memory allocation checking if requested +AC_ARG_ENABLE(alloc-checks, AC_HELP_STRING([--enable-alloc-checks], + [ enable to memory allocation statistics, for debug purposes ]), + , ) +AC_ARG_ENABLE(alloc-lite, AC_HELP_STRING([--enable-alloc-lite], + [ enable for lightweight alloc assertions, for debug purposes ]), + , ) +AC_ARG_ENABLE(alloc-nonregional, AC_HELP_STRING([--enable-alloc-nonregional], + [ enable nonregional allocs, slow but exposes regional allocations to other memory purifiers, for debug purposes ]), + , ) +if test x_$enable_alloc_nonregional = x_yes; then + AC_DEFINE(UNBOUND_ALLOC_NONREGIONAL, 1, [use malloc not regions, for debug use]) +fi +if test x_$enable_alloc_checks = x_yes; then + AC_DEFINE(UNBOUND_ALLOC_STATS, 1, [use statistics for allocs and frees, for debug use]) +else + if test x_$enable_alloc_lite = x_yes; then + AC_DEFINE(UNBOUND_ALLOC_LITE, 1, [use to enable lightweight alloc assertions, for debug use]) + else + ACX_FUNC_MALLOC([unbound]) + fi +fi + +# check windows threads (we use them, not pthreads, on windows). +if test "$on_mingw" = "yes"; then +# check windows threads + AC_CHECK_HEADERS([windows.h],,, [AC_INCLUDES_DEFAULT]) + AC_MSG_CHECKING([for CreateThread]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([ +#ifdef HAVE_WINDOWS_H +#include +#endif +], [ + HANDLE t = CreateThread(NULL, 0, NULL, NULL, 0, NULL); +])], + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_WINDOWS_THREADS, 1, [Using Windows threads]) +, + AC_MSG_RESULT(no) +) + +else +# not on mingw, check thread libraries. + +# check for thread library. +# check this first, so that the pthread lib does not get linked in via +# libssl or libpython, and thus distorts the tests, and we end up using +# the non-threadsafe C libraries. +AC_ARG_WITH(pthreads, AC_HELP_STRING([--with-pthreads], + [use pthreads library, or --without-pthreads to disable threading support.]), + [ ],[ withval="yes" ]) +ub_have_pthreads=no +if test x_$withval != x_no; then + ACX_PTHREAD([ + AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]) + LIBS="$PTHREAD_LIBS $LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + CC="$PTHREAD_CC" + ub_have_pthreads=yes + AC_CHECK_TYPES([pthread_spinlock_t, pthread_rwlock_t],,,[#include ]) + ]) +fi + +# check solaris thread library +AC_ARG_WITH(solaris-threads, AC_HELP_STRING([--with-solaris-threads], + [use solaris native thread library.]), [ ],[ withval="no" ]) +ub_have_sol_threads=no +if test x_$withval != x_no; then + if test x_$ub_have_pthreads != x_no; then + AC_WARN([Have pthreads already, ignoring --with-solaris-threads]) + else + AC_SEARCH_LIBS(thr_create, [thread], + [ + AC_DEFINE(HAVE_SOLARIS_THREADS, 1, [Using Solaris threads]) + + ACX_CHECK_COMPILER_FLAG(mt, [CFLAGS="$CFLAGS -mt"], + [CFLAGS="$CFLAGS -D_REENTRANT"]) + ub_have_sol_threads=yes + ] , [ + AC_ERROR([no solaris threads found.]) + ]) + fi +fi + +fi # end of non-mingw check of thread libraries + +# Check for PyUnbound +AC_ARG_WITH(pyunbound, + AC_HELP_STRING([--with-pyunbound], + [build PyUnbound, or --without-pyunbound to skip it. (default=no)]), + [], [ withval="no" ]) + +ub_test_python=no +ub_with_pyunbound=no +if test x_$withval != x_no; then + ub_with_pyunbound=yes + ub_test_python=yes +fi + +# Check for Python module +AC_ARG_WITH(pythonmodule, + AC_HELP_STRING([--with-pythonmodule], + [build Python module, or --without-pythonmodule to disable script engine. (default=no)]), + [], [ withval="no" ]) + +ub_with_pythonmod=no +if test x_$withval != x_no; then + ub_with_pythonmod=yes + ub_test_python=yes +fi + +# Check for Python & SWIG only on PyUnbound or PyModule +if test x_$ub_test_python != x_no; then + + # Check for Python + ub_have_python=no + ac_save_LIBS="$LIBS" dnl otherwise AC_PYTHON_DEVEL thrashes $LIBS + AC_PYTHON_DEVEL + if test ! -z "$PYTHON_VERSION"; then + if test `$PYTHON -c "print '$PYTHON_VERSION' >= '2.4.0'"` = "False"; then + AC_ERROR([Python version >= 2.4.0 is required]) + fi + + # Have Python + AC_DEFINE(HAVE_PYTHON,1,[Define if you have Python libraries and header files.]) + LIBS="$PYTHON_LDFLAGS $LIBS" + CPPFLAGS="$CPPFLAGS $PYTHON_CPPFLAGS" + ub_have_python=yes + + # Check for SWIG + ub_have_swig=no + AC_PROG_SWIG + AC_MSG_CHECKING(SWIG) + if test ! -x "$SWIG"; then + AC_ERROR([failed to find swig tool, install it, or do not build Python module and PyUnbound]) + else + AC_DEFINE(HAVE_SWIG, 1, [Define if you have Swig libraries and header files.]) + AC_SUBST(swig, "$SWIG") + AC_MSG_RESULT(present) + + # If have Python & SWIG + # Declare PythonMod + if test x_$ub_with_pythonmod != x_no; then + AC_DEFINE(WITH_PYTHONMODULE, 1, [Define if you want Python module.]) + WITH_PYTHONMODULE=yes + AC_SUBST(WITH_PYTHONMODULE) + PYTHONMOD_OBJ="pythonmod.lo pythonmod_utils.lo" + AC_SUBST(PYTHONMOD_OBJ) + PYTHONMOD_HEADER='$(srcdir)/pythonmod/pythonmod.h' + AC_SUBST(PYTHONMOD_HEADER) + PYTHONMOD_INSTALL=pythonmod-install + AC_SUBST(PYTHONMOD_INSTALL) + PYTHONMOD_UNINSTALL=pythonmod-uninstall + AC_SUBST(PYTHONMOD_UNINSTALL) + fi + + # Declare PyUnbound + if test x_$ub_with_pyunbound != x_no; then + AC_DEFINE(WITH_PYUNBOUND, 1, [Define if you want PyUnbound.]) + WITH_PYUNBOUND=yes + AC_SUBST(WITH_PYUNBOUND) + PYUNBOUND_OBJ="libunbound_wrap.lo" + AC_SUBST(PYUNBOUND_OBJ) + PYUNBOUND_TARGET="_unbound.la" + AC_SUBST(PYUNBOUND_TARGET) + PYUNBOUND_INSTALL=pyunbound-install + AC_SUBST(PYUNBOUND_INSTALL) + PYUNBOUND_UNINSTALL=pyunbound-uninstall + AC_SUBST(PYUNBOUND_UNINSTALL) + fi + fi + else + AC_MSG_RESULT([*** Python libraries not found, won't build PythonMod or PyUnbound ***]) + ub_with_pyunbound=no + ub_with_pythonmod=no + fi +fi + +if test "`uname`" = "NetBSD"; then + NETBSD_LINTFLAGS='"-D__RENAME(x)=" -D_NETINET_IN_H_' + AC_SUBST(NETBSD_LINTFLAGS) +fi +CONFIG_DATE=`date +%Y%m%d` +AC_SUBST(CONFIG_DATE) + +# Checks for libraries. +ACX_WITH_SSL +ACX_LIB_SSL +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]) +AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free], [], [], [ +AC_INCLUDES_DEFAULT +#ifdef HAVE_OPENSSL_ERR_H +#include +#endif + +#ifdef HAVE_OPENSSL_RAND_H +#include +#endif + +#ifdef HAVE_OPENSSL_CONF_H +#include +#endif + +#ifdef HAVE_OPENSSL_ENGINE_H +#include +#endif +#include +#include +]) + +AC_ARG_ENABLE(sha2, AC_HELP_STRING([--disable-sha2], [Disable SHA256 and SHA512 RRSIG support])) +case "$enable_sha2" in + no) + ;; + yes|*) + AC_DEFINE([USE_SHA2], [1], [Define this to enable SHA256 and SHA512 support.]) + ;; +esac + +# check wether gost also works +AC_DEFUN([AC_CHECK_GOST_WORKS], +[AC_REQUIRE([AC_PROG_CC]) +AC_MSG_CHECKING([if GOST works]) +if test c${cross_compiling} = cno; then +BAKCFLAGS="$CFLAGS" +if test -n "$ssldir"; then + CFLAGS="$CFLAGS -Wl,-rpath,$ssldir/lib" +fi +AC_RUN_IFELSE([AC_LANG_SOURCE([[ +#include +#include +#include +#include +#include +/* routine to load gost from ldns */ +int load_gost_id(void) +{ + static int gost_id = 0; + const EVP_PKEY_ASN1_METHOD* meth; + ENGINE* e; + + if(gost_id) return gost_id; + + /* see if configuration loaded gost implementation from other engine*/ + meth = EVP_PKEY_asn1_find_str(NULL, "gost2001", -1); + if(meth) { + EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth); + return gost_id; + } + + /* see if engine can be loaded already */ + e = ENGINE_by_id("gost"); + if(!e) { + /* load it ourself, in case statically linked */ + ENGINE_load_builtin_engines(); + ENGINE_load_dynamic(); + e = ENGINE_by_id("gost"); + } + if(!e) { + /* no gost engine in openssl */ + return 0; + } + if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) { + ENGINE_finish(e); + ENGINE_free(e); + return 0; + } + + meth = EVP_PKEY_asn1_find_str(&e, "gost2001", -1); + if(!meth) { + /* algo not found */ + ENGINE_finish(e); + ENGINE_free(e); + return 0; + } + EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth); + return gost_id; +} +int main(void) { + EVP_MD_CTX* ctx; + const EVP_MD* md; + unsigned char digest[64]; /* its a 256-bit digest, so uses 32 bytes */ + const char* str = "Hello world"; + const unsigned char check[] = { + 0x40 , 0xed , 0xf8 , 0x56 , 0x5a , 0xc5 , 0x36 , 0xe1 , + 0x33 , 0x7c , 0x7e , 0x87 , 0x62 , 0x1c , 0x42 , 0xe0 , + 0x17 , 0x1b , 0x5e , 0xce , 0xa8 , 0x46 , 0x65 , 0x4d , + 0x8d , 0x3e , 0x22 , 0x9b , 0xe1 , 0x30 , 0x19 , 0x9d + }; + OPENSSL_config(NULL); + (void)load_gost_id(); + md = EVP_get_digestbyname("md_gost94"); + if(!md) return 1; + memset(digest, 0, sizeof(digest)); + ctx = EVP_MD_CTX_create(); + if(!ctx) return 2; + if(!EVP_DigestInit_ex(ctx, md, NULL)) return 3; + if(!EVP_DigestUpdate(ctx, str, 10)) return 4; + if(!EVP_DigestFinal_ex(ctx, digest, NULL)) return 5; + /* uncomment to see the hash calculated. + {int i; + for(i=0; i<32; i++) + printf(" %2.2x", (int)digest[i]); + printf("\n");} + */ + if(memcmp(digest, check, sizeof(check)) != 0) + return 6; + return 0; +} +]])] , [eval "ac_cv_c_gost_works=yes"], [eval "ac_cv_c_gost_works=no"]) +CFLAGS="$BAKCFLAGS" +else +eval "ac_cv_c_gost_works=maybe" +fi +AC_MSG_RESULT($ac_cv_c_gost_works) +])dnl + +AC_ARG_ENABLE(gost, AC_HELP_STRING([--disable-gost], [Disable GOST support])) +use_gost="no" +case "$enable_gost" in + no) + ;; + *) + AC_CHECK_FUNC(EVP_PKEY_set_type_str, [:],[AC_MSG_ERROR([OpenSSL 1.0.0 is needed for GOST support])]) + AC_CHECK_FUNC(EC_KEY_new, [], [AC_MSG_ERROR([OpenSSL does not support ECC, needed for GOST support])]) + AC_CHECK_GOST_WORKS + if test $ac_cv_c_gost_works != no; then + use_gost="yes" + AC_DEFINE([USE_GOST], [1], [Define this to enable GOST support.]) + fi + ;; +esac + +AC_ARG_ENABLE(ecdsa, AC_HELP_STRING([--disable-ecdsa], [Disable ECDSA support])) +use_ecdsa="no" +case "$enable_ecdsa" in + no) + ;; + *) + AC_CHECK_FUNC(ECDSA_sign, [], [AC_MSG_ERROR([OpenSSL does not support ECDSA: please upgrade or rerun with --disable-ecdsa])]) + AC_CHECK_FUNC(SHA384_Init, [], [AC_MSG_ERROR([OpenSSL does not support SHA384: please upgrade or rerun with --disable-ecdsa])]) + AC_CHECK_DECLS([NID_X9_62_prime256v1, NID_secp384r1], [], [AC_MSG_ERROR([OpenSSL does not support the ECDSA curves: please upgrade or rerun with --disable-ecdsa])], [AC_INCLUDES_DEFAULT +#include + ]) + # see if OPENSSL 1.0.0 or later (has EVP MD and Verify independency) + AC_MSG_CHECKING([if openssl supports SHA2 and ECDSA with EVP]) + if grep OPENSSL_VERSION_NUMBER $ssldir/include/openssl/opensslv.h | grep 0x0 >/dev/null; then + AC_MSG_RESULT([no]) + AC_DEFINE_UNQUOTED([USE_ECDSA_EVP_WORKAROUND], [1], [Define this to enable an EVP workaround for older openssl]) + else + AC_MSG_RESULT([yes]) + fi + # we now know we have ECDSA and the required curves. + AC_DEFINE_UNQUOTED([USE_ECDSA], [1], [Define this to enable ECDSA support.]) + use_ecdsa="yes" + ;; +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.]), + [ ],[ withval="no" ]) +if test x_$withval = x_yes -o x_$withval != x_no; then + AC_MSG_CHECKING(for libevent) + if test x_$withval = x_ -o x_$withval = x_yes; then + withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr" + fi + for dir in $withval; do + thedir="$dir" + if test -f "$dir/include/event.h"; then + found_libevent="yes" + dnl assume /usr is in default path. + if test "$thedir" != "/usr"; then + CPPFLAGS="$CPPFLAGS -I$thedir/include" + fi + break; + fi + done + if test x_$found_libevent != x_yes; then + if test -f "$dir/event.h" -a \( -f "$dir/libevent.la" -o -f "$dir/libev.la" \) ; then + # libevent source directory + AC_MSG_RESULT(found in $thedir) + CPPFLAGS="$CPPFLAGS -I$thedir -I$thedir/include" + BAK_LDFLAGS_SET="1" + BAK_LDFLAGS="$LDFLAGS" + # remove evdns from linking + mkdir build >/dev/null 2>&1 + mkdir build/libevent >/dev/null 2>&1 + mkdir build/libevent/.libs >/dev/null 2>&1 + ev_files_o=`ls $thedir/*.o | grep -v evdns\.o | grep -v bufferevent_openssl\.o` + ev_files_lo=`ls $thedir/*.lo | grep -v evdns\.lo | grep -v bufferevent_openssl\.lo` + ev_files_libso=`ls $thedir/.libs/*.o | grep -v evdns\.o | grep -v bufferevent_openssl\.o` + cp $ev_files_o build/libevent + cp $ev_files_lo build/libevent + cp $ev_files_libso build/libevent/.libs + LATE_LDFLAGS="build/libevent/*.lo -lm" + LDFLAGS="build/libevent/*.o $LDFLAGS -lm" + else + AC_MSG_ERROR([Cannot find the libevent library in $withval +You can restart ./configure --with-libevent=no to use a builtin alternative. +Please note that this alternative is not as capable as libevent when using +large outgoing port ranges. ]) + fi + else + AC_MSG_RESULT(found in $thedir) + dnl assume /usr is in default path, do not add "". + if test "$thedir" != "/usr" -a "$thedir" != ""; then + LDFLAGS="$LDFLAGS -L$thedir/lib" + ACX_RUNTIME_PATH_ADD([$thedir/lib]) + fi + fi + # check for library used by libevent after 1.3c + AC_SEARCH_LIBS([clock_gettime], [rt]) + + # is the event.h header libev or libevent? + AC_CHECK_HEADERS([event.h],,, [AC_INCLUDES_DEFAULT]) + AC_CHECK_DECL(EV_VERSION_MAJOR, [ + AC_SEARCH_LIBS(event_set, [ev]) + ],[ + AC_SEARCH_LIBS(event_set, [event]) + ],[AC_INCLUDES_DEFAULT +#include + ]) + AC_CHECK_FUNCS([event_base_free]) # only in libevent 1.2 and later + AC_CHECK_FUNCS([event_base_once]) # only in libevent 1.4.1 and later + AC_CHECK_FUNCS([event_base_new]) # only in libevent 1.4.1 and later + AC_CHECK_FUNCS([event_base_get_method]) # only in libevent 1.4.3 and later + AC_CHECK_FUNCS([ev_loop]) # only in libev. (tested on 3.51) + AC_CHECK_FUNCS([ev_default_loop]) # only in libev. (tested on 4.00) + if test -n "$BAK_LDFLAGS_SET"; then + LDFLAGS="$BAK_LDFLAGS" + fi +else + AC_DEFINE(USE_MINI_EVENT, 1, [Define if you want to use internal select based events]) +fi + +# check for libexpat +AC_ARG_WITH(libexpat, AC_HELP_STRING([--with-libexpat=path], + [specify explicit path for libexpat.]), + [ ],[ withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr" ]) +AC_MSG_CHECKING(for libexpat) +found_libexpat="no" +for dir in $withval ; do + if test -f "$dir/include/expat.h"; then + found_libexpat="yes" + dnl assume /usr is in default path. + if test "$dir" != "/usr"; then + CPPFLAGS="$CPPFLAGS -I$dir/include" + LDFLAGS="$LDFLAGS -L$dir/lib" + fi + AC_MSG_RESULT(found in $dir) + break; + fi +done +if test x_$found_libexpat != x_yes; then + AC_ERROR([Could not find libexpat, expat.h]) +fi +AC_CHECK_HEADERS([expat.h],,, [AC_INCLUDES_DEFAULT]) + +# set static linking if requested +AC_SUBST(staticexe) +staticexe="" +AC_ARG_ENABLE(static-exe, AC_HELP_STRING([--enable-static-exe], + [ enable to compile executables statically against event, ldns libs, for debug purposes ]), + , ) +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 + fi +fi + +# set lock checking if requested +AC_ARG_ENABLE(lock_checks, AC_HELP_STRING([--enable-lock-checks], + [ enable to check lock and unlock calls, for debug purposes ]), + , ) +if test x_$enable_lock_checks = x_yes; then + AC_DEFINE(ENABLE_LOCK_CHECKS, 1, [Define if you want to use debug lock checking (slow).]) + CHECKLOCK_OBJ="checklocks.lo" + AC_SUBST(CHECKLOCK_OBJ) +fi + +ACX_CHECK_GETADDRINFO_WITH_INCLUDES +if test "$USE_WINSOCK" = 1; then + AC_DEFINE(UB_ON_WINDOWS, 1, [Use win32 resources and API]) + AC_CHECK_HEADERS([iphlpapi.h],,, [AC_INCLUDES_DEFAULT +#include + ]) + AC_CHECK_TOOL(WINDRES, windres) + LIBS="$LIBS -liphlpapi" + WINAPPS="unbound-service-install.exe unbound-service-remove.exe anchor-update.exe" + AC_SUBST(WINAPPS) + WIN_DAEMON_SRC="winrc/win_svc.c winrc/w_inst.c" + AC_SUBST(WIN_DAEMON_SRC) + WIN_DAEMON_OBJ="win_svc.lo w_inst.lo" + AC_SUBST(WIN_DAEMON_OBJ) + WIN_DAEMON_OBJ_LINK="rsrc_unbound.o" + AC_SUBST(WIN_DAEMON_OBJ_LINK) + WIN_HOST_OBJ_LINK="rsrc_unbound_host.o" + AC_SUBST(WIN_HOST_OBJ_LINK) + WIN_UBANCHOR_OBJ_LINK="rsrc_unbound_anchor.o log.lo locks.lo" + AC_SUBST(WIN_UBANCHOR_OBJ_LINK) + WIN_CONTROL_OBJ_LINK="rsrc_unbound_control.o" + AC_SUBST(WIN_CONTROL_OBJ_LINK) + WIN_CHECKCONF_OBJ_LINK="rsrc_unbound_checkconf.o" + AC_SUBST(WIN_CHECKCONF_OBJ_LINK) +fi +if test $ac_cv_func_getaddrinfo = no; then + AC_LIBOBJ([fake-rfc2553]) +fi +# check after getaddrinfo for its libraries +ACX_FUNC_IOCTLSOCKET + +# see if daemon(3) exists, and if it is deprecated. +AC_CHECK_FUNCS([daemon]) +if test $ac_cv_func_daemon = yes; then + ACX_FUNC_DEPRECATED([daemon], [(void)daemon(0, 0);], [ +#include +]) +fi + +AC_CHECK_MEMBERS([struct in_pktinfo.ipi_spec_dst],,,[ +AC_INCLUDES_DEFAULT +#if HAVE_SYS_PARAM_H +#include +#endif + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef HAVE_SYS_UIO_H +#include +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#ifdef HAVE_WINSOCK2_H +#include +#endif + +#ifdef HAVE_WS2TCPIP_H +#include +#endif +]) +AC_SEARCH_LIBS([setusercontext], [util]) +AC_CHECK_FUNCS([tzset sigprocmask fcntl getpwnam getrlimit setrlimit setsid sbrk chroot kill sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex]) +AC_CHECK_FUNCS([setresuid],,[AC_CHECK_FUNCS([setreuid])]) +AC_CHECK_FUNCS([setresgid],,[AC_CHECK_FUNCS([setregid])]) + +# check if setreuid en setregid fail, on MacOSX10.4(darwin8). +if echo $build_os | grep darwin8 > /dev/null; then + AC_DEFINE(DARWIN_BROKEN_SETREUID, 1, [Define this if on macOSX10.4-darwin8 and setreuid and setregid do not work]) +fi +AC_REPLACE_FUNCS(inet_aton) +AC_REPLACE_FUNCS(inet_pton) +AC_REPLACE_FUNCS(inet_ntop) +AC_REPLACE_FUNCS(snprintf) +AC_REPLACE_FUNCS(strlcpy) +AC_REPLACE_FUNCS(memmove) +AC_REPLACE_FUNCS(gmtime_r) +LIBOBJ_WITHOUT_CTIME="$LIBOBJS" +AC_SUBST(LIBOBJ_WITHOUT_CTIME) +AC_REPLACE_FUNCS(ctime_r) + +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 + yes) + COMMON_OBJ_ALL_SYMBOLS="" + UBSYMS="" + EXTRALINK="-L. -L.libs -lunbound" + AC_DEFINE(EXPORT_ALL_SYMBOLS, 1, [Define this if you enabled-allsymbols from libunbound to link binaries to it for smaller install size, but the libunbound export table is polluted by internal symbols]) + ;; + no|*) + COMMON_OBJ_ALL_SYMBOLS='$(COMMON_OBJ)' + UBSYMS='-export-symbols $(srcdir)/libunbound/ubsyms.def' + EXTRALINK="" + ;; +esac +AC_SUBST(COMMON_OBJ_ALL_SYMBOLS) +AC_SUBST(EXTRALINK) +AC_SUBST(UBSYMS) +if test x_$enable_lock_checks = x_yes; then + UBSYMS="-export-symbols clubsyms.def" + cp ${srcdir}/libunbound/ubsyms.def clubsyms.def + echo lock_protect >> clubsyms.def + echo lock_unprotect >> clubsyms.def + echo lock_get_mem >> clubsyms.def + echo checklock_start >> clubsyms.def + echo checklock_stop >> clubsyms.def + echo checklock_lock >> clubsyms.def + echo checklock_unlock >> clubsyms.def + echo checklock_init >> clubsyms.def + echo checklock_thrcreate >> clubsyms.def + echo checklock_thrjoin >> clubsyms.def +fi + +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). +# gmake works. +cat >conftest.make </dev/null +rm -f conftest.make conftest.c conftest.dir/conftest.c +rm -rf conftest.dir +if test ! -f conftest.lo; then + AC_MSG_RESULT(no) + SOURCEDETERMINE='echo "$^" | awk "-F " "{print \$$1;}" > .source' + SOURCEFILE='`cat .source`' +else + AC_MSG_RESULT(yes) + SOURCEDETERMINE=':' + SOURCEFILE='$<' +fi +rm -f conftest.lo +AC_SUBST(SOURCEDETERMINE) +AC_SUBST(SOURCEFILE) + +# check this after all other compilation checks, since the linking of the lib +# may break checks after this. +AC_ARG_WITH(ldns, AC_HELP_STRING([--with-ldns=PATH], + [specify prefix of path of ldns library to use]), + [ + if test "$withval" != "yes"; then + if test "$withval" != "/usr" -a "$withval" != ""; then + CPPFLAGS="-I$withval/include $CPPFLAGS" + LDFLAGS="-L$withval/lib $LDFLAGS" + ACX_RUNTIME_PATH_ADD([$withval/lib]) + fi + ldnsdir="$withval" + AC_SUBST(ldnsdir) + fi +]) + +# check if ldns is good enough +AC_CHECK_LIB(ldns, ldns_rr_new,,[ + AC_MSG_ERROR([No ldns library found, install the ldns library into system lib dir or use --with-ldns=path to other location. The --with-ldns can point to the make-dir of ldns. Install the package ldns or download source http://www.nlnetlabs.nl/projects/ldns]) +]) +AC_CHECK_FUNC(ldns_buffer_copy) +AC_CHECK_FUNC(ldns_key_buf2rsa_raw) +AC_CHECK_FUNC(ldns_get_random) +AC_CHECK_FUNC(ldns_b32_ntop_extended_hex) +if test x$use_gost = xyes; then + AC_CHECK_FUNC(ldns_key_EVP_load_gost_id) + AC_CHECK_FUNCS([ldns_key_EVP_unload_gost]) +else + ac_cv_func_ldns_key_EVP_load_gost_id="yes" +fi +if test x$use_ecdsa = xyes; then + AC_CHECK_DECL([LDNS_ECDSAP384SHA384], [], [], [ +AC_INCLUDES_DEFAULT +#ifdef HAVE_SYS_SOCKET_H +# include +#endif +#ifdef HAVE_WS2TCPIP_H +# include +#endif +#include + ]) +else + ac_cv_have_decl_LDNS_ECDSAP384SHA384="yes" +fi +AC_CHECK_HEADERS([ldns/ldns.h],,[ + AC_MSG_ERROR([No ldns include file found, install the ldns library development files. Install package ldns-dev or ldns-devel or download source http://www.nlnetlabs.nl/projects/ldns]) + ], [AC_INCLUDES_DEFAULT +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#ifdef HAVE_WINSOCK2_H +#include +#endif + +#ifdef HAVE_WS2TCPIP_H +#include +#endif +]) +if test $ac_cv_func_ldns_buffer_copy = yes \ + -a $ac_cv_func_ldns_key_buf2rsa_raw = yes \ + -a $ac_cv_func_ldns_get_random = yes \ + -a $ac_cv_header_ldns_ldns_h = yes \ + -a $ac_cv_func_ldns_b32_ntop_extended_hex = yes \ + -a $ac_cv_func_ldns_key_EVP_load_gost_id = yes \ + -a $ac_cv_have_decl_LDNS_ECDSAP384SHA384 = yes; then + dnl ldns was found + : +else + AC_MSG_ERROR([ldns library is not recent, update the ldns library, install it into system lib dir or use --with-ldns=path to other location. The --with-ldns can point to the make-dir of ldns. Package libldns or download source http://www.nlnetlabs.nl/projects/ldns]) +fi + +ACX_STRIP_EXT_FLAGS +LDFLAGS="$LATE_LDFLAGS $LDFLAGS" + +AC_DEFINE_UNQUOTED([MAXSYSLOGMSGLEN], [10240], [Define to the maximum message length to pass to syslog.]) + +AH_BOTTOM( +dnl this must be first AH_CONFIG, to define the flags before any includes. +AHX_CONFIG_EXT_FLAGS + +dnl includes +[ +#ifndef UNBOUND_DEBUG +# define NDEBUG +#endif + +#include +#include +#include +#include + +#if STDC_HEADERS +#include +#include +#endif + +#ifdef HAVE_STDINT_H +#include +#endif + +#include + +#if HAVE_SYS_PARAM_H +#include +#endif + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef HAVE_SYS_UIO_H +#include +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#ifdef HAVE_WINSOCK2_H +#include +#endif + +#ifdef HAVE_WS2TCPIP_H +#include +#endif +] + +AHX_CONFIG_FORMAT_ATTRIBUTE +AHX_CONFIG_UNUSED_ATTRIBUTE +AHX_CONFIG_FSEEKO +AHX_CONFIG_MAXHOSTNAMELEN +AHX_CONFIG_SNPRINTF(unbound) +AHX_CONFIG_INET_PTON(unbound) +AHX_CONFIG_INET_NTOP(unbound) +AHX_CONFIG_INET_ATON(unbound) +AHX_CONFIG_MEMMOVE(unbound) +AHX_CONFIG_STRLCPY(unbound) +AHX_CONFIG_GMTIME_R(unbound) +AHX_CONFIG_W32_SLEEP +AHX_CONFIG_W32_USLEEP +AHX_CONFIG_W32_RANDOM +AHX_CONFIG_W32_SRANDOM +AHX_CONFIG_W32_FD_SET_T +AHX_CONFIG_IPV6_MIN_MTU +AHX_MEMCMP_BROKEN(unbound) + +[ +#ifndef HAVE_CTIME_R +#define ctime_r unbound_ctime_r +char *ctime_r(const time_t *timep, char *buf); +#endif + +#if !defined(HAVE_STRPTIME) || !defined(STRPTIME_WORKS) +#define strptime unbound_strptime +struct tm; +char *strptime(const char *s, const char *format, struct tm *tm); +#endif + +#if defined(HAVE_EVENT_H) && !defined(HAVE_EVENT_BASE_ONCE) && !(defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)) && (defined(HAVE_PTHREAD) || defined(HAVE_SOLARIS_THREADS)) + /* using version of libevent that is not threadsafe. */ +# define LIBEVENT_SIGNAL_PROBLEM 1 +#endif + +#ifndef CHECKED_INET6 +# define CHECKED_INET6 +# ifdef AF_INET6 +# define INET6 +# else +# define AF_INET6 28 +# endif +#endif /* CHECKED_INET6 */ + +/* maximum nesting of included files */ +#define MAXINCLUDES 10 +#ifndef HAVE_GETADDRINFO +struct sockaddr_storage; +#include "compat/fake-rfc2553.h" +#endif + +#ifdef UNBOUND_ALLOC_STATS +# define malloc(s) unbound_stat_malloc_log(s, __FILE__, __LINE__, __func__) +# define calloc(n,s) unbound_stat_calloc_log(n, s, __FILE__, __LINE__, __func__) +# define free(p) unbound_stat_free_log(p, __FILE__, __LINE__, __func__) +# define realloc(p,s) unbound_stat_realloc_log(p, s, __FILE__, __LINE__, __func__) +void *unbound_stat_malloc(size_t size); +void *unbound_stat_calloc(size_t nmemb, size_t size); +void unbound_stat_free(void *ptr); +void *unbound_stat_realloc(void *ptr, size_t size); +void *unbound_stat_malloc_log(size_t size, const char* file, int line, + const char* func); +void *unbound_stat_calloc_log(size_t nmemb, size_t size, const char* file, + int line, const char* func); +void unbound_stat_free_log(void *ptr, const char* file, int line, + const char* func); +void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file, + int line, const char* func); +#elif defined(UNBOUND_ALLOC_LITE) +# include "util/alloc.h" +#endif /* UNBOUND_ALLOC_LITE and UNBOUND_ALLOC_STATS */ + +/** default port for DNS traffic. */ +#define UNBOUND_DNS_PORT 53 +/** default port for unbound control traffic, registered port with IANA, + ub-dns-control 8953/tcp unbound dns nameserver control */ +#define UNBOUND_CONTROL_PORT 8953 +/** the version of unbound-control that this software implements */ +#define UNBOUND_CONTROL_VERSION 1 + +]) + +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]) +AC_CONFIG_HEADER([config.h]) +AC_OUTPUT diff --git a/contrib/README b/contrib/README new file mode 100644 index 00000000000..f5123fc6c8a --- /dev/null +++ b/contrib/README @@ -0,0 +1,17 @@ +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. diff --git a/contrib/build-unbound-localzone-from-hosts.pl b/contrib/build-unbound-localzone-from-hosts.pl new file mode 100755 index 00000000000..c11bbc33079 --- /dev/null +++ b/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 = ) { + + # 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/parseunbound.pl b/contrib/parseunbound.pl new file mode 100755 index 00000000000..6a6a76d6fb2 --- /dev/null +++ b/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/rc_d_unbound b/contrib/rc_d_unbound new file mode 100755 index 00000000000..56516147f23 --- /dev/null +++ b/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/selinux/unbound.fc b/contrib/selinux/unbound.fc new file mode 100644 index 00000000000..f7e63eada11 --- /dev/null +++ b/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/selinux/unbound.te b/contrib/selinux/unbound.te new file mode 100644 index 00000000000..d407ed351f4 --- /dev/null +++ b/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-host.nagios.patch b/contrib/unbound-host.nagios.patch new file mode 100644 index 00000000000..5b249b636b1 --- /dev/null +++ b/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 + ++/** 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.init b/contrib/unbound.init new file mode 100644 index 00000000000..747f94e932d --- /dev/null +++ b/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.init_fedora b/contrib/unbound.init_fedora new file mode 100644 index 00000000000..9f7e4422b21 --- /dev/null +++ b/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.plist b/contrib/unbound.plist new file mode 100644 index 00000000000..15e1162be23 --- /dev/null +++ b/contrib/unbound.plist @@ -0,0 +1,42 @@ + + + + + + Label + unbound + + ProgramArguments + + unbound + + + UserName + unbound + + RootDirectory + /usr/local/etc/unbound + + WorkingDirectory + /usr/local/etc/unbound + + KeepAlive + + + RunAtLoad + + + + diff --git a/contrib/unbound.spec b/contrib/unbound.spec new file mode 100644 index 00000000000..60643027393 --- /dev/null +++ b/contrib/unbound.spec @@ -0,0 +1,112 @@ +Summary: Validating, recursive, and caching DNS resolver +Name: unbound +Version: 1.4.8 +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 - 1.4.8 +- ldns required and ldns-devel required for build, no more ldns-builtin. + +* Thu Mar 17 2011 Wouter Wijngaards - 1.4.8 +- removed --disable-gost, assume recent openssl on the destination platform. + +* Wed Mar 16 2011 Harold Jones - 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 - 1.0.0 +- contrib changes from Patrick Vande Walle. + +* Thu Apr 25 2008 Wouter Wijngaards - 0.12 +- Using parts from ports collection entry by Jaap Akkerhuis. +- Using Fedoraproject wiki guidelines. + +* Wed Apr 23 2008 Wouter Wijngaards - 0.11 +- Initial version. diff --git a/contrib/unbound.spec_fedora b/contrib/unbound.spec_fedora new file mode 100644 index 00000000000..6e02a0964c4 --- /dev/null +++ b/contrib/unbound.spec_fedora @@ -0,0 +1,440 @@ +# 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 +Source6: dlv.isc.org.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}/dlv.isc.org.key +%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} +# dnssec-conf used to contain our DLV key, but now we include it via unbound +# If unbound had previously been configured with dnssec-configure, we need +# to migrate the location of the DLV key file (to keep DLV enabled, and because +# unbound won't start with a bad location for a DLV key file. +sed -i "s:/etc/pki/dnssec-keys[/]*dlv:/etc/unbound:" %{_sysconfdir}/unbound/unbound.conf + +%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 - 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 - 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 - 1.4.12-1 +- Updated to 1.4.12 + +* Sun Jul 03 2011 Paul Wouters - 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 - 1.4.10-1 +- Added ghost for /var/run/unbound (bz#656710) + +* Mon Jun 06 2011 Paul Wouters - 1.4.9-3 +- rebuilt + +* Wed May 25 2011 Paul Wouters - 1.4.9-2 +- Applied patch for CVE-2011-1922 DoS vulnerability + +* Sun Mar 27 2011 Paul Wouters - 1.4.9-1 +- Updated to 1.4.9 + +* Sat Feb 12 2011 Paul Wouters - 1.4.8-2 +- rebuilt + +* Tue Jan 25 2011 Paul Wouters - 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 - 1.4.5-4 +- Revert last build - it was on the wrong branch + +* Tue Oct 26 2010 Paul Wouters - 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 - 1.4.5-2 +- Bump release - forgot to upload the new tar ball. + +* Tue Jun 15 2010 Paul Wouters - 1.4.5-1 +- Upgraded to 1.4.5 + +* Mon May 31 2010 Paul Wouters - 1.4.4-2 +- Added accidentally omitted svn patches to cvs + +* Mon May 31 2010 Paul Wouters - 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 - 1.4.3-1 +- Update to 1.4.3 that fixes 64bit crasher + +* Tue Mar 09 2010 Paul Wouters - 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 - 1.4.1-5 +- Overriding -D_GNU_SOURCE is no longer needed. This fixes DSO issues + with pthreads + +* Wed Feb 24 2010 Paul Wouters - 1.4.1-3 +- Change make/configure lines to attempt to fix -lphtread linking issue + +* Thu Feb 18 2010 Paul Wouters - 1.4.1-2 +- Removed dependancy 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 - 1.4.1-1 +- Updated to 1.4.1 +- Changed %%define to %%global + +* Thu Oct 08 2009 Paul Wouters - 1.3.4-2 +- Bump version + +* Thu Oct 08 2009 Paul Wouters - 1.3.4-1 +- Upgraded to 1.3.4. Security fix with validating NSEC3 records + +* Fri Aug 21 2009 Tomas Mraz - 1.3.3-2 +- rebuilt with new openssl + +* Mon Aug 17 2009 Paul Wouters - 1.3.3-1 +- Updated to 1.3.3 + +* Sun Jul 26 2009 Fedora Release Engineering - 1.3.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Sat Jun 20 2009 Paul Wouters - 1.3.0-2 +- Added missing glob patch to cvs +- Place python macros within the %%with_python check + +* Sat Jun 20 2009 Paul Wouters - 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 - 1.2.1-7 +- unbound-iterator.patch was not commited + +* Wed May 20 2009 Paul Wouters - 1.2.1-6 +- Fix for https://bugzilla.redhat.com/show_bug.cgi?id=499793 + +* Tue Mar 17 2009 Paul Wouters - 1.2.1-5 +- Use --nocheck to avoid giving an error on missing unbound-remote certs/keys + +* Tue Mar 10 2009 Adam Tkac - 1.2.1-4 +- enable DNSSEC only if it is enabled in sysconfig/dnssec + +* Mon Mar 09 2009 Adam Tkac - 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 - 1.2.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild + +* Tue Feb 10 2009 Paul Wouters - 1.2.0-2 +- rebuild with new openssl + +* Wed Jan 14 2009 Paul Wouters - 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 - 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 - 1.1.1-4 +- Added Requires: for selinux-policy >= 3.5.13-33 for proper SElinux rules. + +* Mon Dec 1 2008 Paul Wouters - 1.1.1-3 +- We did not own the /etc/unbound directory (#474020) +- Fixed cvs anomalies + +* Fri Nov 28 2008 Adam Tkac - 1.1.1-2 +- removed all obsolete chroot related stuff +- label control certs after generation correctly + +* Thu Nov 20 2008 Paul Wouters - 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 - 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 - 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 - 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 - 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 - 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 - 1.0.2-3 +- Split off unbound-libs, make build verbose + +* Thu Oct 9 2008 Paul Wouters - 1.0.2-2 +- FSB compliance, chroot fixes, initscript fixes + +* Thu Sep 11 2008 Paul Wouters - 1.0.2-1 +- Upgraded to 1.0.2 + +* Wed Jul 16 2008 Paul Wouters - 1.0.1-1 +- upgraded to new release + +* Wed May 21 2008 Paul Wouters - 1.0.0-2 +- Build against ldns-1.3.0 + +* Wed May 21 2008 Paul Wouters - 1.0.0-1 +- Split of -devel package, fixed dependancies, make rpmlint happy + +* Thu Apr 25 2008 Wouter Wijngaards - 0.12 +- Using parts from ports collection entry by Jaap Akkerhuis. +- Using Fedoraproject wiki guidelines. + +* Wed Apr 23 2008 Wouter Wijngaards - 0.11 +- Initial version. diff --git a/contrib/unbound_cacti.tar.gz b/contrib/unbound_cacti.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..b4d0a79c114e157e6667d857f59de27f71d62eaa GIT binary patch literal 71269 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�Jq}qdDCPs$pbCSW9PP5I&@cb$|MgV0fgCrW~~E6Y8a_E zViK2Em5XCo7qCBJ^~2;~CJ-<9NW~HLnxt}_g_F!XaokWce_%{t4-6%K-aW)l|G{{Qe?Es-inJ{Y}@H;`62Bg^K;G+{^d)BShh>Q)>K;5iA-7C z4C?^<-;6~M1Wt*+(rr#N?6Gs9pEl&{1wkk>U_OO+Iie0GvQa`rM9D{C*q*?qeV0@D z*Mdy|xgbggx$2LVlZ05E5DGggq>MDWg>ZO-fuGBCw-&`t7OJDX$94>*;pk}6Suzep z6}+pUk~sP2gwM7Sy__yo)adU-7Plc1yu2_?*)T!sWvC@wPIN$v;7CG$ZEHg2P&dY6 zh=7Et+1dCgoNuMh7&;O8G(x?M4(XB9lt%|u8>mBu$Q#TXj+et)b;%uAq00zloB+;; zHp~S~?DhCM^k6GXK#6SwrVdg3pBsE?r-z8c+^@i&7ynf<`EaJ8ut6asWdVjsa5zbt zu}r}~vw=Qg)S?y~m3b!DT&^Z_$mfJHdtn!Fm}Ck6AUdsNMJ$x7%*N2$37SbZ#r3vI zKe0cwvbP>QBDlDcv89lDx%1)KR?;x<=O_HDC2w?Z!zcBH+eG3&NKKl<$v`ylAH`OSXU^yr2tfT&zh})-U|=@wIcIj*NuH&bAQZ5 zzVTjqhL9z%WVnh#V8_QS?t=_8)lPDSD)tlM(9>d+O^k4EKw=}%!wX3y#B!bDs`IK-BWLGv zpkRj$eoXWw@lR0)rVxpO4+1@Vuoja~I3|N3Bt6aG&J^*{Et9=HQ((c1v~Zq;Eztq4 z(<9d32#Ugq5m{*u~THSb&IMaYA2VW;`7%Nz~MloJuLR_lx z)x&A`!Le%e#LjGZ=|I}u6|r*n%y~3xCv%@6zaifVmq*K+9+ r4AUvEF!am>#Iyl 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/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" + 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 +} + +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 / second" + echo "graph_category DNS" + for x in thread0.num.queries thread1.num.queries \ + thread2.num.queries thread3.num.queries thread4.num.queries \ + thread5.num.queries thread6.num.queries thread7.num.queries; do + exist_config $x "queries handled by `basename $x .num.queries`" + done + p_config "total.num.queries" "total queries from clients" + p_config "total.num.cachehits" "cache hits" + p_config "total.num.prefetch" "cache prefetch" + p_config "num.query.tcp" "TCP queries" + p_config "num.query.ipv6" "IPv6 queries" + p_config "unwanted.queries" "queries that failed acl" + p_config "unwanted.replies" "unwanted or unsolicited replies" + 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_category DNS" + p_config "total.requestlist.avg" "Average size of queue on insert" + p_config "total.requestlist.max" "Max size of queue (in 5 min)" + p_config "total.requestlist.overwritten" "Number of queries replaced by new ones" + p_config "total.requestlist.exceeded" "Number of queries dropped due to lack of space" + 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" + p_config "mem.cache.rrset" "RRset cache memory" + p_config "mem.cache.message" "Message cache memory" + p_config "mem.mod.iterator" "Iterator module memory" + p_config "mem.mod.validator" "Validator module and key cache memory" + 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 / second" + 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" + 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 / second" + 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" + 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 / second" + 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" + 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 / second" + 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" + done + p_config "num.answer.secure" "answer secure" + p_config "num.answer.bogus" "answer bogus" + p_config "num.rrset.bogus" "num rrsets marked bogus" + echo "graph_info answers sorted by return value. rrsets bogus is the number of rrsets marked bogus per second 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 / second" + echo "graph_category DNS" + p_config "num.query.flags.QR" "QR (query reply) flag" + p_config "num.query.flags.AA" "AA (auth answer) flag" + p_config "num.query.flags.TC" "TC (truncated) flag" + p_config "num.query.flags.RD" "RD (recursion desired) flag" + p_config "num.query.flags.RA" "RA (rec avail) flag" + p_config "num.query.flags.Z" "Z (zero) flag" + p_config "num.query.flags.AD" "AD (auth data) flag" + p_config "num.query.flags.CD" "CD (check disabled) flag" + p_config "num.query.edns.present" "EDNS OPT present" + p_config "num.query.edns.DO" "DO (DNSSEC OK) flag" + 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 / second" + echo "graph_category DNS" + echo hcache.label "cache hits" + echo hcache.min 0 + echo hcache.draw AREA + echo hcache.colour 999999 + echo h64ms.label "0 msec - 66 msec" + echo h64ms.min 0 + echo h64ms.draw STACK + echo h64ms.colour 0000FF + echo h128ms.label "66 msec - 131 msec" + echo h128ms.min 0 + echo h128ms.colour 1F00DF + echo h128ms.draw STACK + echo h256ms.label "131 msec - 262 msec" + echo h256ms.min 0 + echo h256ms.draw STACK + echo h256ms.colour 3F00BF + echo h512ms.label "262 msec - 524 msec" + echo h512ms.min 0 + echo h512ms.draw STACK + echo h512ms.colour 5F009F + echo h1s.label "524 msec - 1 sec" + echo h1s.min 0 + echo h1s.draw STACK + echo h1s.colour 7F007F + echo h2s.label "1 sec - 2 sec" + echo h2s.min 0 + echo h2s.draw STACK + echo h2s.colour 9F005F + echo h4s.label "2 sec - 4 sec" + echo h4s.min 0 + echo h4s.draw STACK + echo h4s.colour BF003F + echo h8s.label "4 sec - 8 sec" + echo h8s.min 0 + echo h8s.draw STACK + echo h8s.colour DF001F + echo h16s.label "8 sec - ..." + echo h16s.min 0 + 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 / elapsed +print_qps ( ) { + mn=`echo $1 | sed $ABBREV | tr . _` + get_value $1 + echo "$mn.value" `echo scale=6';' $value / $elapsed | bc ` +} + +# print qps if line already found in $2 +print_qps_line ( ) { + mn=`echo $1 | sed $ABBREV | tr . _` + value="`echo $2 | sed -e 's/^.*=//'`" + echo "$mn.value" `echo scale=6';' $value / $elapsed | bc ` +} + +# print value for $1 +print_value ( ) { + mn=`echo $1 | sed $ABBREV | tr . _` + get_value $1 + echo "$mn.value" $value +} + +case $id in +hits) + for x in thread0.num.queries thread1.num.queries thread2.num.queries \ + thread3.num.queries thread4.num.queries thread5.num.queries \ + thread6.num.queries thread7.num.queries total.num.queries \ + total.num.cachehits total.num.prefetch num.query.tcp \ + num.query.ipv6 unwanted.queries unwanted.replies; do + if grep "^"$x"=" $state >/dev/null 2>&1; then + print_qps $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; do + print_value $x + done + ;; +by_type) + for x in `grep "^num.query.type" $state`; do + nm=`echo $x | sed -e 's/=.*$//'` + print_qps_line $nm $x + done + ;; +by_class) + for x in `grep "^num.query.class" $state`; do + nm=`echo $x | sed -e 's/=.*$//'` + print_qps_line $nm $x + done + ;; +by_opcode) + for x in `grep "^num.query.opcode" $state`; do + nm=`echo $x | sed -e 's/=.*$//'` + print_qps_line $nm $x + done + ;; +by_rcode) + for x in `grep "^num.answer.rcode" $state`; do + nm=`echo $x | sed -e 's/=.*$//'` + print_qps_line $nm $x + done + print_qps "num.answer.secure" + print_qps "num.answer.bogus" + print_qps "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_qps $x + done + ;; +histogram) + get_value total.num.cachehits + echo hcache.value `echo scale=6';' $value / $elapsed | bc ` + 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 `echo scale=6';' $r / $elapsed | bc ` + get_value histogram.000000.065536.to.000000.131072 + echo h128ms.value `echo scale=6';' $value / $elapsed | bc ` + get_value histogram.000000.131072.to.000000.262144 + echo h256ms.value `echo scale=6';' $value / $elapsed | bc ` + get_value histogram.000000.262144.to.000000.524288 + echo h512ms.value `echo scale=6';' $value / $elapsed | bc ` + get_value histogram.000000.524288.to.000001.000000 + echo h1s.value `echo scale=6';' $value / $elapsed | bc ` + get_value histogram.000001.000000.to.000002.000000 + echo h2s.value `echo scale=6';' $value / $elapsed | bc ` + get_value histogram.000002.000000.to.000004.000000 + echo h4s.value `echo scale=6';' $value / $elapsed | bc ` + get_value histogram.000004.000000.to.000008.000000 + echo h8s.value `echo scale=6';' $value / $elapsed | bc ` + 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 `echo scale=6';' $r / $elapsed | bc ` + ;; +esac diff --git a/contrib/update-anchor.sh b/contrib/update-anchor.sh new file mode 100755 index 00000000000..95032a082c6 --- /dev/null +++ b/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] " + 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 .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="$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/validation-reporter.sh b/contrib/validation-reporter.sh new file mode 100755 index 00000000000..7c1a4218bd1 --- /dev/null +++ b/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 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/daemon/acl_list.c b/daemon/acl_list.c new file mode 100644 index 00000000000..48c8e0fe4db --- /dev/null +++ b/daemon/acl_list.c @@ -0,0 +1,176 @@ +/* + * daemon/acl_list.h - client access control storage for the server. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file helps the server keep out queries from outside sources, that + * should not be answered. + */ +#include "config.h" +#include "daemon/acl_list.h" +#include "util/regional.h" +#include "util/log.h" +#include "util/config_file.h" +#include "util/net_help.h" + +struct acl_list* +acl_list_create(void) +{ + struct acl_list* acl = (struct acl_list*)calloc(1, + sizeof(struct acl_list)); + if(!acl) + return NULL; + acl->region = regional_create(); + if(!acl->region) { + acl_list_delete(acl); + return NULL; + } + return acl; +} + +void +acl_list_delete(struct acl_list* acl) +{ + if(!acl) + return; + regional_destroy(acl->region); + free(acl); +} + +/** insert new address into acl_list structure */ +static int +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, + sizeof(struct acl_addr)); + if(!node) + return 0; + 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; +} + +/** apply acl_list string */ +static int +acl_list_str_cfg(struct acl_list* acl, const char* str, const char* s2, + int complain_duplicates) +{ + struct sockaddr_storage addr; + int net; + socklen_t addrlen; + enum acl_access control; + if(strcmp(s2, "allow") == 0) + control = acl_allow; + else if(strcmp(s2, "deny") == 0) + control = acl_deny; + else if(strcmp(s2, "refuse") == 0) + control = acl_refuse; + else if(strcmp(s2, "allow_snoop") == 0) + control = acl_allow_snoop; + else { + log_err("access control type %s unknown", str); + return 0; + } + if(!netblockstrtoaddr(str, UNBOUND_DNS_PORT, &addr, &addrlen, &net)) { + log_err("cannot parse access control: %s %s", str, s2); + return 0; + } + if(!acl_list_insert(acl, &addr, addrlen, net, control, + complain_duplicates)) { + 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) +{ + struct config_str2list* p; + for(p = cfg->acls; p; p = p->next) { + log_assert(p->str && p->str2); + if(!acl_list_str_cfg(acl, p->str, p->str2, 1)) + return 0; + } + return 1; +} + +int +acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg) +{ + regional_free_all(acl->region); + addr_tree_init(&acl->tree); + if(!read_acl_list(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; + if(!acl_list_str_cfg(acl, "127.0.0.0/8", "allow", 0)) + return 0; + if(cfg->do_ip6) { + if(!acl_list_str_cfg(acl, "::0/0", "refuse", 0)) + return 0; + if(!acl_list_str_cfg(acl, "::1", "allow", 0)) + return 0; + if(!acl_list_str_cfg(acl, "::ffff:127.0.0.1", "allow", 0)) + return 0; + } + addr_tree_init_parents(&acl->tree); + return 1; +} + +enum acl_access +acl_list_lookup(struct acl_list* acl, struct sockaddr_storage* addr, + socklen_t addrlen) +{ + struct acl_addr* r = (struct acl_addr*)addr_tree_lookup(&acl->tree, + addr, addrlen); + if(r) return r->control; + return acl_deny; +} + +size_t +acl_list_get_mem(struct acl_list* acl) +{ + if(!acl) return 0; + return sizeof(*acl) + regional_get_mem(acl->region); +} diff --git a/daemon/acl_list.h b/daemon/acl_list.h new file mode 100644 index 00000000000..03ac301bf32 --- /dev/null +++ b/daemon/acl_list.h @@ -0,0 +1,125 @@ +/* + * daemon/acl_list.h - client access control storage for the server. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file keeps track of the list of clients that are allowed to + * access the server. + */ + +#ifndef DAEMON_ACL_LIST_H +#define DAEMON_ACL_LIST_H +#include "util/storage/dnstree.h" +struct config_file; +struct regional; + +/** + * Enumeration of access control options for an address range. + * Allow or deny access. + */ +enum acl_access { + /** disallow any access whatsoever, drop it */ + acl_deny = 0, + /** disallow access, send a polite 'REFUSED' reply */ + acl_refuse, + /** allow full access for recursion (+RD) queries */ + acl_allow, + /** allow full access for all queries, recursion and cache snooping */ + acl_allow_snoop +}; + +/** + * Access control storage structure + */ +struct acl_list { + /** regional for allocation */ + struct regional* region; + /** + * Tree of the addresses that are allowed/blocked. + * contents of type acl_addr. + */ + rbtree_t tree; +}; + +/** + * + * An address span with access control information + */ +struct acl_addr { + /** node in address tree */ + struct addr_tree_node node; + /** access control on this netblock */ + enum acl_access control; +}; + +/** + * Create acl structure + * @return new structure or NULL on error. + */ +struct acl_list* acl_list_create(void); + +/** + * Delete acl structure. + * @param acl: to delete. + */ +void acl_list_delete(struct acl_list* acl); + +/** + * Process access control config. + * @param acl: where to store. + * @param cfg: config options. + * @return 0 on error. + */ +int acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg); + +/** + * Lookup address to see its access control status. + * @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. + */ +enum acl_access acl_list_lookup(struct acl_list* acl, + struct sockaddr_storage* addr, socklen_t addrlen); + +/** + * Get memory used by acl structure. + * @param acl: structure for address storage. + * @return bytes in use. + */ +size_t acl_list_get_mem(struct acl_list* acl); + +#endif /* DAEMON_ACL_LIST_H */ diff --git a/daemon/cachedump.c b/daemon/cachedump.c new file mode 100644 index 00000000000..988e247352e --- /dev/null +++ b/daemon/cachedump.c @@ -0,0 +1,986 @@ +/* + * daemon/cachedump.c - dump the cache to text format. + * + * Copyright (c) 2008, 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions to read and write the cache(s) + * to text format. + */ +#include "config.h" +#include +#include "daemon/cachedump.h" +#include "daemon/remote.h" +#include "daemon/worker.h" +#include "daemon/daemon.h" +#include "services/cache/rrset.h" +#include "services/cache/dns.h" +#include "services/cache/infra.h" +#include "services/modstack.h" +#include "util/data/msgreply.h" +#include "util/regional.h" +#include "util/net_help.h" +#include "util/data/dname.h" +#include "iterator/iterator.h" +#include "iterator/iter_delegpt.h" +#include "iterator/iter_utils.h" +#include "iterator/iter_fwd.h" +#include "iterator/iter_hints.h" + +/** convert to ldns rr */ +static ldns_rr* +to_rr(struct ub_packed_rrset_key* k, struct packed_rrset_data* d, + uint32_t now, size_t i, uint16_t type) +{ + ldns_rr* rr = ldns_rr_new(); + ldns_rdf* rdf; + ldns_status status; + size_t pos; + log_assert(i < d->count + d->rrsig_count); + if(!rr) { + return NULL; + } + ldns_rr_set_type(rr, type); + ldns_rr_set_class(rr, ntohs(k->rk.rrset_class)); + if(d->rr_ttl[i] < now) + ldns_rr_set_ttl(rr, 0); + else ldns_rr_set_ttl(rr, d->rr_ttl[i] - now); + pos = 0; + status = ldns_wire2dname(&rdf, k->rk.dname, k->rk.dname_len, &pos); + if(status != LDNS_STATUS_OK) { + /* we drop detailed error in status */ + ldns_rr_free(rr); + return NULL; + } + ldns_rr_set_owner(rr, rdf); + pos = 0; + status = ldns_wire2rdf(rr, d->rr_data[i], d->rr_len[i], &pos); + if(status != LDNS_STATUS_OK) { + /* we drop detailed error in status */ + ldns_rr_free(rr); + return NULL; + } + return rr; +} + +/** dump one rrset zonefile line */ +static int +dump_rrset_line(SSL* ssl, struct ub_packed_rrset_key* k, + struct packed_rrset_data* d, uint32_t now, size_t i, uint16_t type) +{ + char* s; + ldns_rr* rr = to_rr(k, d, now, i, type); + if(!rr) { + return ssl_printf(ssl, "BADRR\n"); + } + s = ldns_rr2str(rr); + ldns_rr_free(rr); + if(!s) { + return ssl_printf(ssl, "BADRR\n"); + } + if(!ssl_printf(ssl, "%s", s)) { + free(s); + return 0; + } + free(s); + return 1; +} + +/** dump rrset key and data info */ +static int +dump_rrset(SSL* ssl, struct ub_packed_rrset_key* k, + struct packed_rrset_data* d, uint32_t now) +{ + size_t i; + /* rd lock held by caller */ + if(!k || !d) return 1; + if(d->ttl < now) return 1; /* expired */ + + /* meta line */ + if(!ssl_printf(ssl, ";rrset%s %u %u %u %d %d\n", + (k->rk.flags & PACKED_RRSET_NSEC_AT_APEX)?" nsec_apex":"", + (unsigned)(d->ttl - now), + (unsigned)d->count, (unsigned)d->rrsig_count, + (int)d->trust, (int)d->security + )) + return 0; + for(i=0; icount; i++) { + if(!dump_rrset_line(ssl, k, d, now, i, ntohs(k->rk.type))) + return 0; + } + for(i=0; irrsig_count; i++) { + if(!dump_rrset_line(ssl, k, d, now, i+d->count, + LDNS_RR_TYPE_RRSIG)) + return 0; + } + + return 1; +} + +/** dump lruhash rrset cache */ +static int +dump_rrset_lruhash(SSL* ssl, struct lruhash* h, uint32_t now) +{ + struct lruhash_entry* e; + /* lruhash already locked by caller */ + /* walk in order of lru; best first */ + for(e=h->lru_start; e; e = e->lru_next) { + lock_rw_rdlock(&e->lock); + if(!dump_rrset(ssl, (struct ub_packed_rrset_key*)e->key, + (struct packed_rrset_data*)e->data, now)) { + lock_rw_unlock(&e->lock); + return 0; + } + lock_rw_unlock(&e->lock); + } + return 1; +} + +/** dump rrset cache */ +static int +dump_rrset_cache(SSL* ssl, struct worker* worker) +{ + struct rrset_cache* r = worker->env.rrset_cache; + size_t slab; + if(!ssl_printf(ssl, "START_RRSET_CACHE\n")) return 0; + for(slab=0; slabtable.size; slab++) { + lock_quick_lock(&r->table.array[slab]->lock); + if(!dump_rrset_lruhash(ssl, r->table.array[slab], + *worker->env.now)) { + lock_quick_unlock(&r->table.array[slab]->lock); + return 0; + } + lock_quick_unlock(&r->table.array[slab]->lock); + } + return ssl_printf(ssl, "END_RRSET_CACHE\n"); +} + +/** dump message to rrset reference */ +static int +dump_msg_ref(SSL* ssl, struct ub_packed_rrset_key* k) +{ + ldns_rdf* rdf; + ldns_status status; + size_t pos; + char* nm, *tp, *cl; + + pos = 0; + status = ldns_wire2dname(&rdf, k->rk.dname, k->rk.dname_len, &pos); + if(status != LDNS_STATUS_OK) { + return ssl_printf(ssl, "BADREF\n"); + } + nm = ldns_rdf2str(rdf); + ldns_rdf_deep_free(rdf); + tp = ldns_rr_type2str(ntohs(k->rk.type)); + cl = ldns_rr_class2str(ntohs(k->rk.rrset_class)); + if(!nm || !cl || !tp) { + free(nm); + free(tp); + free(cl); + return ssl_printf(ssl, "BADREF\n"); + } + if(!ssl_printf(ssl, "%s %s %s %d\n", nm, cl, tp, (int)k->rk.flags)) { + free(nm); + free(tp); + free(cl); + return 0; + } + free(nm); + free(tp); + free(cl); + + return 1; +} + +/** dump message entry */ +static int +dump_msg(SSL* ssl, struct query_info* k, struct reply_info* d, + uint32_t now) +{ + size_t i; + char* nm, *tp, *cl; + ldns_rdf* rdf; + ldns_status status; + size_t pos; + if(!k || !d) return 1; + if(d->ttl < now) return 1; /* expired */ + + pos = 0; + status = ldns_wire2dname(&rdf, k->qname, k->qname_len, &pos); + if(status != LDNS_STATUS_OK) { + return 1; /* skip this entry */ + } + nm = ldns_rdf2str(rdf); + ldns_rdf_deep_free(rdf); + tp = ldns_rr_type2str(k->qtype); + cl = ldns_rr_class2str(k->qclass); + if(!nm || !tp || !cl) { + free(nm); + free(tp); + free(cl); + return 1; /* skip this entry */ + } + if(!rrset_array_lock(d->ref, d->rrset_count, now)) { + /* rrsets have timed out or do not exist */ + free(nm); + free(tp); + free(cl); + return 1; /* skip this entry */ + } + + /* meta line */ + if(!ssl_printf(ssl, "msg %s %s %s %d %d %u %d %u %u %u\n", + nm, cl, tp, + (int)d->flags, (int)d->qdcount, + (unsigned)(d->ttl-now), (int)d->security, + (unsigned)d->an_numrrsets, + (unsigned)d->ns_numrrsets, + (unsigned)d->ar_numrrsets)) { + free(nm); + free(tp); + free(cl); + rrset_array_unlock(d->ref, d->rrset_count); + return 0; + } + free(nm); + free(tp); + free(cl); + + for(i=0; irrset_count; i++) { + if(!dump_msg_ref(ssl, d->rrsets[i])) { + rrset_array_unlock(d->ref, d->rrset_count); + return 0; + } + } + rrset_array_unlock(d->ref, d->rrset_count); + + return 1; +} + +/** copy msg to worker pad */ +static int +copy_msg(struct regional* region, struct lruhash_entry* e, + struct query_info** k, struct reply_info** d) +{ + struct reply_info* rep = (struct reply_info*)e->data; + *d = (struct reply_info*)regional_alloc_init(region, e->data, + sizeof(struct reply_info) + + sizeof(struct rrset_ref) * (rep->rrset_count-1) + + sizeof(struct ub_packed_rrset_key*) * rep->rrset_count); + if(!*d) + return 0; + (*d)->rrsets = (struct ub_packed_rrset_key**)( + (uint8_t*)(&((*d)->ref[0])) + + sizeof(struct rrset_ref) * rep->rrset_count); + *k = (struct query_info*)regional_alloc_init(region, + e->key, sizeof(struct query_info)); + if(!*k) + return 0; + (*k)->qname = regional_alloc_init(region, + (*k)->qname, (*k)->qname_len); + return (*k)->qname != NULL; +} + +/** dump lruhash msg cache */ +static int +dump_msg_lruhash(SSL* ssl, struct worker* worker, struct lruhash* h) +{ + struct lruhash_entry* e; + struct query_info* k; + struct reply_info* d; + + /* lruhash already locked by caller */ + /* walk in order of lru; best first */ + for(e=h->lru_start; e; e = e->lru_next) { + regional_free_all(worker->scratchpad); + lock_rw_rdlock(&e->lock); + /* make copy of rrset in worker buffer */ + if(!copy_msg(worker->scratchpad, e, &k, &d)) { + lock_rw_unlock(&e->lock); + return 0; + } + lock_rw_unlock(&e->lock); + /* release lock so we can lookup the rrset references + * in the rrset cache */ + if(!dump_msg(ssl, k, d, *worker->env.now)) { + return 0; + } + } + return 1; +} + +/** dump msg cache */ +static int +dump_msg_cache(SSL* ssl, struct worker* worker) +{ + struct slabhash* sh = worker->env.msg_cache; + size_t slab; + if(!ssl_printf(ssl, "START_MSG_CACHE\n")) return 0; + for(slab=0; slabsize; slab++) { + lock_quick_lock(&sh->array[slab]->lock); + if(!dump_msg_lruhash(ssl, worker, sh->array[slab])) { + lock_quick_unlock(&sh->array[slab]->lock); + return 0; + } + lock_quick_unlock(&sh->array[slab]->lock); + } + return ssl_printf(ssl, "END_MSG_CACHE\n"); +} + +int +dump_cache(SSL* ssl, struct worker* worker) +{ + if(!dump_rrset_cache(ssl, worker)) + return 0; + if(!dump_msg_cache(ssl, worker)) + return 0; + return ssl_printf(ssl, "EOF\n"); +} + +/** read a line from ssl into buffer */ +static int +ssl_read_buf(SSL* ssl, ldns_buffer* buf) +{ + return ssl_read_line(ssl, (char*)ldns_buffer_begin(buf), + ldns_buffer_capacity(buf)); +} + +/** check fixed text on line */ +static int +read_fixed(SSL* ssl, ldns_buffer* buf, const char* str) +{ + if(!ssl_read_buf(ssl, buf)) return 0; + return (strcmp((char*)ldns_buffer_begin(buf), str) == 0); +} + +/** load an RR into rrset */ +static int +load_rr(SSL* ssl, ldns_buffer* buf, struct regional* region, + struct ub_packed_rrset_key* rk, struct packed_rrset_data* d, + unsigned int i, int is_rrsig, int* go_on, uint32_t now) +{ + ldns_rr* rr; + ldns_status status; + + /* read the line */ + if(!ssl_read_buf(ssl, buf)) + return 0; + if(strncmp((char*)ldns_buffer_begin(buf), "BADRR\n", 6) == 0) { + *go_on = 0; + return 1; + } + status = ldns_rr_new_frm_str(&rr, (char*)ldns_buffer_begin(buf), + LDNS_DEFAULT_TTL, NULL, NULL); + if(status != LDNS_STATUS_OK) { + log_warn("error cannot parse rr: %s: %s", + ldns_get_errorstr_by_id(status), + (char*)ldns_buffer_begin(buf)); + return 0; + } + if(is_rrsig && ldns_rr_get_type(rr) != LDNS_RR_TYPE_RRSIG) { + log_warn("error expected rrsig but got %s", + (char*)ldns_buffer_begin(buf)); + return 0; + } + + /* convert ldns rr into packed_rr */ + d->rr_ttl[i] = ldns_rr_ttl(rr) + now; + ldns_buffer_clear(buf); + ldns_buffer_skip(buf, 2); + status = ldns_rr_rdata2buffer_wire(buf, rr); + if(status != LDNS_STATUS_OK) { + log_warn("error cannot rr2wire: %s", + ldns_get_errorstr_by_id(status)); + ldns_rr_free(rr); + return 0; + } + ldns_buffer_flip(buf); + ldns_buffer_write_u16_at(buf, 0, ldns_buffer_limit(buf) - 2); + + d->rr_len[i] = ldns_buffer_limit(buf); + d->rr_data[i] = (uint8_t*)regional_alloc_init(region, + ldns_buffer_begin(buf), ldns_buffer_limit(buf)); + if(!d->rr_data[i]) { + ldns_rr_free(rr); + log_warn("error out of memory"); + return 0; + } + + /* if first entry, fill the key structure */ + if(i==0) { + rk->rk.type = htons(ldns_rr_get_type(rr)); + rk->rk.rrset_class = htons(ldns_rr_get_class(rr)); + ldns_buffer_clear(buf); + status = ldns_dname2buffer_wire(buf, ldns_rr_owner(rr)); + if(status != LDNS_STATUS_OK) { + log_warn("error cannot dname2buffer: %s", + ldns_get_errorstr_by_id(status)); + ldns_rr_free(rr); + return 0; + } + ldns_buffer_flip(buf); + rk->rk.dname_len = ldns_buffer_limit(buf); + rk->rk.dname = regional_alloc_init(region, + ldns_buffer_begin(buf), ldns_buffer_limit(buf)); + if(!rk->rk.dname) { + log_warn("error out of memory"); + ldns_rr_free(rr); + return 0; + } + } + ldns_rr_free(rr); + + return 1; +} + +/** move entry into cache */ +static int +move_into_cache(struct ub_packed_rrset_key* k, + struct packed_rrset_data* d, struct worker* worker) +{ + struct ub_packed_rrset_key* ak; + struct packed_rrset_data* ad; + size_t s, i, num = d->count + d->rrsig_count; + struct rrset_ref ref; + uint8_t* p; + + ak = alloc_special_obtain(&worker->alloc); + if(!ak) { + log_warn("error out of memory"); + return 0; + } + ak->entry.data = NULL; + ak->rk = k->rk; + ak->entry.hash = rrset_key_hash(&k->rk); + ak->rk.dname = (uint8_t*)memdup(k->rk.dname, k->rk.dname_len); + if(!ak->rk.dname) { + log_warn("error out of memory"); + ub_packed_rrset_parsedelete(ak, &worker->alloc); + return 0; + } + s = sizeof(*ad) + (sizeof(size_t) + sizeof(uint8_t*) + + sizeof(uint32_t))* num; + for(i=0; irr_len[i]; + ad = (struct packed_rrset_data*)malloc(s); + if(!ad) { + log_warn("error out of memory"); + ub_packed_rrset_parsedelete(ak, &worker->alloc); + return 0; + } + p = (uint8_t*)ad; + memmove(p, d, sizeof(*ad)); + p += sizeof(*ad); + memmove(p, &d->rr_len[0], sizeof(size_t)*num); + p += sizeof(size_t)*num; + memmove(p, &d->rr_data[0], sizeof(uint8_t*)*num); + p += sizeof(uint8_t*)*num; + memmove(p, &d->rr_ttl[0], sizeof(uint32_t)*num); + p += sizeof(uint32_t)*num; + for(i=0; irr_data[i], d->rr_len[i]); + p += d->rr_len[i]; + } + packed_rrset_ptr_fixup(ad); + + ak->entry.data = ad; + + ref.key = ak; + ref.id = ak->id; + (void)rrset_cache_update(worker->env.rrset_cache, &ref, + &worker->alloc, *worker->env.now); + return 1; +} + +/** load an rrset entry */ +static int +load_rrset(SSL* ssl, ldns_buffer* buf, struct worker* worker) +{ + char* s = (char*)ldns_buffer_begin(buf); + struct regional* region = worker->scratchpad; + struct ub_packed_rrset_key* rk; + struct packed_rrset_data* d; + unsigned int ttl, rr_count, rrsig_count, trust, security; + unsigned int i; + int go_on = 1; + regional_free_all(region); + + rk = (struct ub_packed_rrset_key*)regional_alloc_zero(region, + sizeof(*rk)); + d = (struct packed_rrset_data*)regional_alloc_zero(region, sizeof(*d)); + if(!rk || !d) { + log_warn("error out of memory"); + return 0; + } + + if(strncmp(s, ";rrset", 6) != 0) { + log_warn("error expected ';rrset' but got %s", s); + return 0; + } + s += 6; + if(strncmp(s, " nsec_apex", 10) == 0) { + s += 10; + rk->rk.flags |= PACKED_RRSET_NSEC_AT_APEX; + } + if(sscanf(s, " %u %u %u %u %u", &ttl, &rr_count, &rrsig_count, + &trust, &security) != 5) { + log_warn("error bad rrset spec %s", s); + return 0; + } + if(rr_count == 0 && rrsig_count == 0) { + log_warn("bad rrset without contents"); + return 0; + } + d->count = (size_t)rr_count; + d->rrsig_count = (size_t)rrsig_count; + d->security = (enum sec_status)security; + d->trust = (enum rrset_trust)trust; + d->ttl = (uint32_t)ttl + *worker->env.now; + + d->rr_len = regional_alloc_zero(region, + sizeof(size_t)*(d->count+d->rrsig_count)); + d->rr_ttl = regional_alloc_zero(region, + sizeof(uint32_t)*(d->count+d->rrsig_count)); + d->rr_data = regional_alloc_zero(region, + sizeof(uint8_t*)*(d->count+d->rrsig_count)); + if(!d->rr_len || !d->rr_ttl || !d->rr_data) { + log_warn("error out of memory"); + return 0; + } + + /* read the rr's themselves */ + for(i=0; ienv.now)) { + log_warn("could not read rr %u", i); + return 0; + } + } + for(i=0; ienv.now)) { + log_warn("could not read rrsig %u", i); + return 0; + } + } + if(!go_on) { + /* skip this entry */ + return 1; + } + + return move_into_cache(rk, d, worker); +} + +/** load rrset cache */ +static int +load_rrset_cache(SSL* ssl, struct worker* worker) +{ + ldns_buffer* buf = worker->env.scratch_buffer; + if(!read_fixed(ssl, buf, "START_RRSET_CACHE")) return 0; + while(ssl_read_buf(ssl, buf) && + strcmp((char*)ldns_buffer_begin(buf), "END_RRSET_CACHE")!=0) { + if(!load_rrset(ssl, buf, worker)) + return 0; + } + return 1; +} + +/** read qinfo from next three words */ +static char* +load_qinfo(char* str, struct query_info* qinfo, ldns_buffer* buf, + struct regional* region) +{ + /* s is part of the buf */ + char* s = str; + ldns_rr* rr; + ldns_status status; + + /* skip three words */ + s = strchr(str, ' '); + if(s) s = strchr(s+1, ' '); + if(s) s = strchr(s+1, ' '); + if(!s) { + log_warn("error line too short, %s", str); + return NULL; + } + s[0] = 0; + s++; + + /* parse them */ + status = ldns_rr_new_question_frm_str(&rr, str, NULL, NULL); + if(status != LDNS_STATUS_OK) { + log_warn("error cannot parse: %s %s", + ldns_get_errorstr_by_id(status), str); + return NULL; + } + qinfo->qtype = ldns_rr_get_type(rr); + qinfo->qclass = ldns_rr_get_class(rr); + ldns_buffer_clear(buf); + status = ldns_dname2buffer_wire(buf, ldns_rr_owner(rr)); + ldns_rr_free(rr); + if(status != LDNS_STATUS_OK) { + log_warn("error cannot dname2wire: %s", + ldns_get_errorstr_by_id(status)); + return NULL; + } + ldns_buffer_flip(buf); + qinfo->qname_len = ldns_buffer_limit(buf); + qinfo->qname = (uint8_t*)regional_alloc_init(region, + ldns_buffer_begin(buf), ldns_buffer_limit(buf)); + if(!qinfo->qname) { + log_warn("error out of memory"); + return NULL; + } + + return s; +} + +/** load a msg rrset reference */ +static int +load_ref(SSL* ssl, ldns_buffer* buf, struct worker* worker, + struct regional *region, struct ub_packed_rrset_key** rrset, + int* go_on) +{ + char* s = (char*)ldns_buffer_begin(buf); + struct query_info qinfo; + unsigned int flags; + struct ub_packed_rrset_key* k; + + /* read line */ + if(!ssl_read_buf(ssl, buf)) + return 0; + if(strncmp(s, "BADREF", 6) == 0) { + *go_on = 0; /* its bad, skip it and skip message */ + return 1; + } + + s = load_qinfo(s, &qinfo, buf, region); + if(!s) { + return 0; + } + if(sscanf(s, " %u", &flags) != 1) { + log_warn("error cannot parse flags: %s", s); + return 0; + } + + /* lookup in cache */ + k = rrset_cache_lookup(worker->env.rrset_cache, qinfo.qname, + qinfo.qname_len, qinfo.qtype, qinfo.qclass, + (uint32_t)flags, *worker->env.now, 0); + if(!k) { + /* not found or expired */ + *go_on = 0; + return 1; + } + + /* store in result */ + *rrset = packed_rrset_copy_region(k, region, *worker->env.now); + lock_rw_unlock(&k->entry.lock); + + return (*rrset != NULL); +} + +/** load a msg entry */ +static int +load_msg(SSL* ssl, ldns_buffer* buf, struct worker* worker) +{ + struct regional* region = worker->scratchpad; + struct query_info qinf; + struct reply_info rep; + char* s = (char*)ldns_buffer_begin(buf); + unsigned int flags, qdcount, ttl, security, an, ns, ar; + size_t i; + int go_on = 1; + + regional_free_all(region); + + if(strncmp(s, "msg ", 4) != 0) { + log_warn("error expected msg but got %s", s); + return 0; + } + s += 4; + s = load_qinfo(s, &qinf, buf, region); + if(!s) { + return 0; + } + + /* read remainder of line */ + if(sscanf(s, " %u %u %u %u %u %u %u", &flags, &qdcount, &ttl, + &security, &an, &ns, &ar) != 7) { + log_warn("error cannot parse numbers: %s", s); + return 0; + } + rep.flags = (uint16_t)flags; + rep.qdcount = (uint16_t)qdcount; + rep.ttl = (uint32_t)ttl; + rep.prefetch_ttl = PREFETCH_TTL_CALC(rep.ttl); + rep.security = (enum sec_status)security; + rep.an_numrrsets = (size_t)an; + rep.ns_numrrsets = (size_t)ns; + rep.ar_numrrsets = (size_t)ar; + rep.rrset_count = (size_t)an+(size_t)ns+(size_t)ar; + rep.rrsets = (struct ub_packed_rrset_key**)regional_alloc_zero( + region, sizeof(struct ub_packed_rrset_key*)*rep.rrset_count); + + /* fill repinfo with references */ + for(i=0; ienv, &qinf, &rep, 0, 0, 0, NULL)) { + log_warn("error out of memory"); + return 0; + } + return 1; +} + +/** load msg cache */ +static int +load_msg_cache(SSL* ssl, struct worker* worker) +{ + ldns_buffer* buf = worker->env.scratch_buffer; + if(!read_fixed(ssl, buf, "START_MSG_CACHE")) return 0; + while(ssl_read_buf(ssl, buf) && + strcmp((char*)ldns_buffer_begin(buf), "END_MSG_CACHE")!=0) { + if(!load_msg(ssl, buf, worker)) + return 0; + } + return 1; +} + +int +load_cache(SSL* ssl, struct worker* worker) +{ + if(!load_rrset_cache(ssl, worker)) + return 0; + if(!load_msg_cache(ssl, worker)) + return 0; + return read_fixed(ssl, worker->env.scratch_buffer, "EOF"); +} + +/** print details on a delegation point */ +static void +print_dp_details(SSL* ssl, struct worker* worker, struct delegpt* dp) +{ + char buf[257]; + struct delegpt_addr* a; + int lame, dlame, rlame, rto, edns_vs, to, delay, entry_ttl, + tA = 0, tAAAA = 0, tother = 0; + struct rtt_info ri; + uint8_t edns_lame_known; + for(a = dp->target_list; a; a = a->next_target) { + addr_to_str(&a->addr, a->addrlen, buf, sizeof(buf)); + if(!ssl_printf(ssl, "%-16s\t", buf)) + return; + if(a->bogus) { + if(!ssl_printf(ssl, "Address is BOGUS. ")) + return; + } + /* lookup in infra cache */ + delay=0; + entry_ttl = infra_get_host_rto(worker->env.infra_cache, + &a->addr, a->addrlen, dp->name, dp->namelen, + &ri, &delay, *worker->env.now, &tA, &tAAAA, &tother); + if(entry_ttl == -2 && ri.rto >= USEFUL_SERVER_TOP_TIMEOUT) { + if(!ssl_printf(ssl, "expired, rto %d msec, tA %d " + "tAAAA %d tother %d.\n", ri.rto, tA, tAAAA, + tother)) + return; + continue; + } + if(entry_ttl == -1 || entry_ttl == -2) { + if(!ssl_printf(ssl, "not in infra cache.\n")) + return; + continue; /* skip stuff not in infra cache */ + } + + /* uses type_A because most often looked up, but other + * lameness won't be reported then */ + if(!infra_get_lame_rtt(worker->env.infra_cache, + &a->addr, a->addrlen, dp->name, dp->namelen, + LDNS_RR_TYPE_A, &lame, &dlame, &rlame, &rto, + *worker->env.now)) { + if(!ssl_printf(ssl, "not in infra cache.\n")) + return; + continue; /* skip stuff not in infra cache */ + } + if(!ssl_printf(ssl, "%s%s%s%srto %d msec, ttl %d, ping %d " + "var %d rtt %d, tA %d, tAAAA %d, tother %d", + lame?"LAME ":"", dlame?"NoDNSSEC ":"", + a->lame?"AddrWasParentSide ":"", + rlame?"NoAuthButRecursive ":"", rto, entry_ttl, + ri.srtt, ri.rttvar, rtt_notimeout(&ri), + tA, tAAAA, tother)) + return; + if(delay) + if(!ssl_printf(ssl, ", probedelay %d", delay)) + return; + if(infra_host(worker->env.infra_cache, &a->addr, a->addrlen, + dp->name, dp->namelen, *worker->env.now, &edns_vs, + &edns_lame_known, &to)) { + if(edns_vs == -1) { + if(!ssl_printf(ssl, ", noEDNS%s.", + edns_lame_known?" probed":" assumed")) + return; + } else { + if(!ssl_printf(ssl, ", EDNS %d%s.", edns_vs, + edns_lame_known?" probed":" assumed")) + return; + } + } + if(!ssl_printf(ssl, "\n")) + return; + } +} + +/** print main dp info */ +static void +print_dp_main(SSL* ssl, struct delegpt* dp, struct dns_msg* msg) +{ + size_t i, n_ns, n_miss, n_addr, n_res, n_avail; + + /* print the dp */ + if(msg) + for(i=0; irep->rrset_count; i++) { + struct ub_packed_rrset_key* k = msg->rep->rrsets[i]; + struct packed_rrset_data* d = + (struct packed_rrset_data*)k->entry.data; + if(d->security == sec_status_bogus) { + if(!ssl_printf(ssl, "Address is BOGUS:\n")) + return; + } + if(!dump_rrset(ssl, k, d, 0)) + return; + } + delegpt_count_ns(dp, &n_ns, &n_miss); + delegpt_count_addr(dp, &n_addr, &n_res, &n_avail); + /* since dp has not been used by iterator, all are available*/ + if(!ssl_printf(ssl, "Delegation with %d names, of which %d " + "can be examined to query further addresses.\n" + "%sIt provides %d IP addresses.\n", + (int)n_ns, (int)n_miss, (dp->bogus?"It is BOGUS. ":""), + (int)n_addr)) + return; +} + +int print_deleg_lookup(SSL* ssl, struct worker* worker, uint8_t* nm, + size_t nmlen, int ATTR_UNUSED(nmlabs)) +{ + /* deep links into the iterator module */ + struct delegpt* dp; + struct dns_msg* msg; + struct regional* region = worker->scratchpad; + char b[260]; + struct query_info qinfo; + struct iter_hints_stub* stub; + regional_free_all(region); + qinfo.qname = nm; + qinfo.qname_len = nmlen; + qinfo.qtype = LDNS_RR_TYPE_A; + qinfo.qclass = LDNS_RR_CLASS_IN; + + dname_str(nm, b); + if(!ssl_printf(ssl, "The following name servers are used for lookup " + "of %s\n", b)) + return 0; + + dp = forwards_lookup(worker->env.fwds, nm, qinfo.qclass); + if(dp) { + if(!ssl_printf(ssl, "forwarding request:\n")) + return 0; + print_dp_main(ssl, dp, NULL); + print_dp_details(ssl, worker, dp); + return 1; + } + + while(1) { + dp = dns_cache_find_delegation(&worker->env, nm, nmlen, + qinfo.qtype, qinfo.qclass, region, &msg, + *worker->env.now); + if(!dp) { + return ssl_printf(ssl, "no delegation from " + "cache; goes to configured roots\n"); + } + /* go up? */ + if(iter_dp_is_useless(&qinfo, BIT_RD, dp)) { + print_dp_main(ssl, dp, msg); + print_dp_details(ssl, worker, dp); + if(!ssl_printf(ssl, "cache delegation was " + "useless (no IP addresses)\n")) + return 0; + if(dname_is_root(nm)) { + /* goes to root config */ + return ssl_printf(ssl, "no delegation from " + "cache; goes to configured roots\n"); + } else { + /* useless, goes up */ + nm = dp->name; + nmlen = dp->namelen; + dname_remove_label(&nm, &nmlen); + dname_str(nm, b); + if(!ssl_printf(ssl, "going up, lookup %s\n", b)) + return 0; + continue; + } + } + stub = hints_lookup_stub(worker->env.hints, nm, qinfo.qclass, + dp); + if(stub) { + if(stub->noprime) { + if(!ssl_printf(ssl, "The noprime stub servers " + "are used:\n")) + return 0; + } else { + if(!ssl_printf(ssl, "The stub is primed " + "with servers:\n")) + return 0; + } + print_dp_main(ssl, stub->dp, NULL); + print_dp_details(ssl, worker, stub->dp); + } else { + print_dp_main(ssl, dp, msg); + print_dp_details(ssl, worker, dp); + } + break; + } + + return 1; +} diff --git a/daemon/cachedump.h b/daemon/cachedump.h new file mode 100644 index 00000000000..da9804ff1e0 --- /dev/null +++ b/daemon/cachedump.h @@ -0,0 +1,107 @@ +/* + * daemon/cachedump.h - dump the cache to text format. + * + * Copyright (c) 2008, 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions to read and write the cache(s) + * to text format. + * + * The format of the file is as follows: + * [RRset cache] + * [Message cache] + * EOF -- fixed string "EOF" before end of the file. + * + * The RRset cache is: + * START_RRSET_CACHE + * [rrset]* + * END_RRSET_CACHE + * + * rrset is: + * ;rrset [nsec_apex] TTL rr_count rrsig_count trust security + * resource records, one per line, in zonefile format + * rrsig records, one per line, in zonefile format + * If the text conversion fails, BADRR is printed on the line. + * + * The Message cache is: + * START_MSG_CACHE + * [msg]* + * END_MSG_CACHE + * + * msg is: + * msg name class type flags qdcount ttl security an ns ar + * list of rrset references, one per line. If conversion fails, BADREF + * reference is: + * name class type flags + * + * Expired cache entries are not printed. + */ + +#ifndef DAEMON_DUMPCACHE_H +#define DAEMON_DUMPCACHE_H +struct worker; + +/** + * Dump cache(s) to text + * @param ssl: to print to + * @param worker: worker that is available (buffers, etc) and has + * ptrs to the caches. + * @return false on ssl print error. + */ +int dump_cache(SSL* ssl, struct worker* worker); + +/** + * Load cache(s) from text + * @param ssl: to read from + * @param worker: worker that is available (buffers, etc) and has + * ptrs to the caches. + * @return false on ssl error. + */ +int load_cache(SSL* ssl, struct worker* worker); + +/** + * Print the delegation used to lookup for this name. + * @param ssl: to read from + * @param worker: worker that is available (buffers, etc) and has + * ptrs to the caches. + * @param nm: name to lookup + * @param nmlen: length of name. + * @param nmlabs: labels in name. + * @return false on ssl error. + */ +int print_deleg_lookup(SSL* ssl, struct worker* worker, uint8_t* nm, + size_t nmlen, int nmlabs); + +#endif /* DAEMON_DUMPCACHE_H */ diff --git a/daemon/daemon.c b/daemon/daemon.c new file mode 100644 index 00000000000..9d6ce9fe47f --- /dev/null +++ b/daemon/daemon.c @@ -0,0 +1,589 @@ +/* + * daemon/daemon.c - collection of workers that handles requests. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * The daemon consists of global settings and a number of workers. + */ + +#include "config.h" +#ifdef HAVE_OPENSSL_ERR_H +#include +#endif + +#ifdef HAVE_OPENSSL_RAND_H +#include +#endif + +#ifdef HAVE_OPENSSL_CONF_H +#include +#endif + +#ifdef HAVE_OPENSSL_ENGINE_H +#include +#endif +#include +#include "daemon/daemon.h" +#include "daemon/worker.h" +#include "daemon/remote.h" +#include "daemon/acl_list.h" +#include "util/log.h" +#include "util/config_file.h" +#include "util/data/msgreply.h" +#include "util/storage/lookup3.h" +#include "util/storage/slabhash.h" +#include "services/listen_dnsport.h" +#include "services/cache/rrset.h" +#include "services/cache/infra.h" +#include "services/localzone.h" +#include "services/modstack.h" +#include "util/module.h" +#include "util/random.h" +#include "util/tube.h" +#include + +/** How many quit requests happened. */ +static int sig_record_quit = 0; +/** How many reload requests happened. */ +static int sig_record_reload = 0; + +#if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS +/** cleaner ssl memory freeup */ +static void* comp_meth = NULL; +#endif +#ifdef LEX_HAS_YYLEX_DESTROY +/** remove buffers for parsing and init */ +int ub_c_lex_destroy(void); +#endif + +/** used when no other sighandling happens, so we don't die + * when multiple signals in quick succession are sent to us. + * @param sig: signal number. + * @return signal handler return type (void or int). + */ +static RETSIGTYPE record_sigh(int sig) +{ +#ifdef LIBEVENT_SIGNAL_PROBLEM + verbose(VERB_OPS, "quit on signal, no cleanup and statistics, " + "because installed libevent version is not threadsafe"); + exit(0); +#endif + switch(sig) + { + case SIGTERM: +#ifdef SIGQUIT + case SIGQUIT: +#endif +#ifdef SIGBREAK + case SIGBREAK: +#endif + case SIGINT: + sig_record_quit++; + break; +#ifdef SIGHUP + case SIGHUP: + sig_record_reload++; + break; +#endif +#ifdef SIGPIPE + case SIGPIPE: + break; +#endif + default: + log_err("ignoring signal %d", sig); + } +} + +/** + * Signal handling during the time when netevent is disabled. + * Stores signals to replay later. + */ +static void +signal_handling_record(void) +{ + if( signal(SIGTERM, record_sigh) == SIG_ERR || +#ifdef SIGQUIT + signal(SIGQUIT, record_sigh) == SIG_ERR || +#endif +#ifdef SIGBREAK + signal(SIGBREAK, record_sigh) == SIG_ERR || +#endif +#ifdef SIGHUP + signal(SIGHUP, record_sigh) == SIG_ERR || +#endif +#ifdef SIGPIPE + signal(SIGPIPE, SIG_IGN) == SIG_ERR || +#endif + signal(SIGINT, record_sigh) == SIG_ERR + ) + log_err("install sighandler: %s", strerror(errno)); +} + +/** + * Replay old signals. + * @param wrk: worker that handles signals. + */ +static void +signal_handling_playback(struct worker* wrk) +{ +#ifdef SIGHUP + if(sig_record_reload) + worker_sighandler(SIGHUP, wrk); +#endif + if(sig_record_quit) + worker_sighandler(SIGTERM, wrk); + sig_record_quit = 0; + sig_record_reload = 0; +} + +struct daemon* +daemon_init(void) +{ + struct daemon* daemon = (struct daemon*)calloc(1, + sizeof(struct daemon)); +#ifdef USE_WINSOCK + int r; + WSADATA wsa_data; +#endif + if(!daemon) + return NULL; +#ifdef USE_WINSOCK + r = WSAStartup(MAKEWORD(2,2), &wsa_data); + if(r != 0) { + fatal_exit("could not init winsock. WSAStartup: %s", + wsa_strerror(r)); + } +#endif /* USE_WINSOCK */ + signal_handling_record(); + checklock_start(); + ERR_load_crypto_strings(); + ERR_load_SSL_strings(); +#ifdef HAVE_OPENSSL_CONFIG + OPENSSL_config("unbound"); +#endif +#ifdef USE_GOST + (void)ldns_key_EVP_load_gost_id(); +#endif + OpenSSL_add_all_algorithms(); +#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 + (void)SSL_library_init(); +#ifdef HAVE_TZSET + /* init timezone info while we are not chrooted yet */ + tzset(); +#endif + /* open /dev/random if needed */ + ub_systemseed((unsigned)time(NULL)^(unsigned)getpid()^0xe67); + daemon->need_to_exit = 0; + modstack_init(&daemon->mods); + if(!(daemon->env = (struct module_env*)calloc(1, + sizeof(*daemon->env)))) { + free(daemon); + return NULL; + } + alloc_init(&daemon->superalloc, NULL, 0); + daemon->acl = acl_list_create(); + if(!daemon->acl) { + free(daemon->env); + free(daemon); + return NULL; + } + if(gettimeofday(&daemon->time_boot, NULL) < 0) + log_err("gettimeofday: %s", strerror(errno)); + daemon->time_last_stat = daemon->time_boot; + return daemon; +} + +int +daemon_open_shared_ports(struct daemon* daemon) +{ + log_assert(daemon); + if(daemon->cfg->port != daemon->listening_port) { + listening_ports_free(daemon->ports); + if(!(daemon->ports=listening_ports_open(daemon->cfg))) + return 0; + daemon->listening_port = daemon->cfg->port; + } + if(!daemon->cfg->remote_control_enable && daemon->rc_port) { + listening_ports_free(daemon->rc_ports); + daemon->rc_ports = NULL; + daemon->rc_port = 0; + } + if(daemon->cfg->remote_control_enable && + daemon->cfg->control_port != daemon->rc_port) { + listening_ports_free(daemon->rc_ports); + if(!(daemon->rc_ports=daemon_remote_open_ports(daemon->cfg))) + return 0; + daemon->rc_port = daemon->cfg->control_port; + } + return 1; +} + +/** + * Setup modules. setup module stack. + * @param daemon: the daemon + */ +static void daemon_setup_modules(struct daemon* daemon) +{ + daemon->env->cfg = daemon->cfg; + daemon->env->alloc = &daemon->superalloc; + daemon->env->worker = NULL; + daemon->env->need_to_validate = 0; /* set by module init below */ + if(!modstack_setup(&daemon->mods, daemon->cfg->module_conf, + daemon->env)) { + fatal_exit("failed to setup modules"); + } +} + +/** + * Obtain allowed port numbers, concatenate the list, and shuffle them + * (ready to be handed out to threads). + * @param daemon: the daemon. Uses rand and cfg. + * @param shufport: the portlist output. + * @return number of ports available. + */ +static int daemon_get_shufport(struct daemon* daemon, int* shufport) +{ + int i, n, k, temp; + int avail = 0; + for(i=0; i<65536; i++) { + if(daemon->cfg->outgoing_avail_ports[i]) { + shufport[avail++] = daemon->cfg-> + outgoing_avail_ports[i]; + } + } + if(avail == 0) + fatal_exit("no ports are permitted for UDP, add " + "with outgoing-port-permit"); + /* Knuth shuffle */ + n = avail; + while(--n > 0) { + k = ub_random_max(daemon->rand, n+1); /* 0<= k<= n */ + temp = shufport[k]; + shufport[k] = shufport[n]; + shufport[n] = temp; + } + return avail; +} + +/** + * Allocate empty worker structures. With backptr and thread-number, + * from 0..numthread initialised. Used as user arguments to new threads. + * Creates the daemon random generator if it does not exist yet. + * The random generator stays existing between reloads with a unique state. + * @param daemon: the daemon with (new) config settings. + */ +static void +daemon_create_workers(struct daemon* daemon) +{ + int i, numport; + int* shufport; + log_assert(daemon && daemon->cfg); + if(!daemon->rand) { + unsigned int seed = (unsigned int)time(NULL) ^ + (unsigned int)getpid() ^ 0x438; + daemon->rand = ub_initstate(seed, NULL); + if(!daemon->rand) + fatal_exit("could not init random generator"); + } + hash_set_raninit((uint32_t)ub_random(daemon->rand)); + shufport = (int*)calloc(65536, sizeof(int)); + if(!shufport) + fatal_exit("out of memory during daemon init"); + numport = daemon_get_shufport(daemon, shufport); + verbose(VERB_ALGO, "total of %d outgoing ports available", numport); + + daemon->num = (daemon->cfg->num_threads?daemon->cfg->num_threads:1); + daemon->workers = (struct worker**)calloc((size_t)daemon->num, + sizeof(struct worker*)); + for(i=0; inum; i++) { + if(!(daemon->workers[i] = worker_create(daemon, i, + shufport+numport*i/daemon->num, + numport*(i+1)/daemon->num - numport*i/daemon->num))) + /* the above is not ports/numthr, due to rounding */ + fatal_exit("could not create worker"); + } + free(shufport); +} + +#ifdef THREADS_DISABLED +/** + * Close all pipes except for the numbered thread. + * @param daemon: daemon to close pipes in. + * @param thr: thread number 0..num-1 of thread to skip. + */ +static void close_other_pipes(struct daemon* daemon, int thr) +{ + int i; + for(i=0; inum; i++) + if(i!=thr) { + if(i==0) { + /* only close read part, need to write stats */ + tube_close_read(daemon->workers[i]->cmd); + } else { + /* complete close channel to others */ + tube_delete(daemon->workers[i]->cmd); + daemon->workers[i]->cmd = NULL; + } + } +} +#endif /* THREADS_DISABLED */ + +/** + * Function to start one thread. + * @param arg: user argument. + * @return: void* user return value could be used for thread_join results. + */ +static void* +thread_start(void* arg) +{ + struct worker* worker = (struct worker*)arg; + log_thread_set(&worker->thread_num); + ub_thread_blocksigs(); +#ifdef THREADS_DISABLED + /* close pipe ends used by main */ + tube_close_write(worker->cmd); + close_other_pipes(worker->daemon, worker->thread_num); +#endif + if(!worker_init(worker, worker->daemon->cfg, worker->daemon->ports, 0)) + fatal_exit("Could not initialize thread"); + + worker_work(worker); + return NULL; +} + +/** + * Fork and init the other threads. Main thread returns for special handling. + * @param daemon: the daemon with other threads to fork. + */ +static void +daemon_start_others(struct daemon* daemon) +{ + int i; + log_assert(daemon); + verbose(VERB_ALGO, "start threads"); + /* skip i=0, is this thread */ + for(i=1; inum; i++) { + ub_thread_create(&daemon->workers[i]->thr_id, + thread_start, daemon->workers[i]); +#ifdef THREADS_DISABLED + /* close pipe end of child */ + tube_close_read(daemon->workers[i]->cmd); +#endif /* no threads */ + } +} + +/** + * Stop the other threads. + * @param daemon: the daemon with other threads. + */ +static void +daemon_stop_others(struct daemon* daemon) +{ + int i; + log_assert(daemon); + verbose(VERB_ALGO, "stop threads"); + /* skip i=0, is this thread */ + /* use i=0 buffer for sending cmds; because we are #0 */ + for(i=1; inum; i++) { + worker_send_cmd(daemon->workers[i], worker_cmd_quit); + } + /* wait for them to quit */ + for(i=1; inum; i++) { + /* join it to make sure its dead */ + verbose(VERB_ALGO, "join %d", i); + ub_thread_join(daemon->workers[i]->thr_id); + verbose(VERB_ALGO, "join success %d", i); + } +} + +void +daemon_fork(struct daemon* daemon) +{ + log_assert(daemon); + if(!acl_list_apply_cfg(daemon->acl, daemon->cfg)) + fatal_exit("Could not setup access control list"); + if(!(daemon->local_zones = local_zones_create())) + fatal_exit("Could not create local zones: out of memory"); + if(!local_zones_apply_cfg(daemon->local_zones, daemon->cfg)) + fatal_exit("Could not set up local zones"); + + /* setup modules */ + daemon_setup_modules(daemon); + + /* first create all the worker structures, so we can pass + * them to the newly created threads. + */ + daemon_create_workers(daemon); + +#if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP) + /* in libev the first inited base gets signals */ + if(!worker_init(daemon->workers[0], daemon->cfg, daemon->ports, 1)) + fatal_exit("Could not initialize main thread"); +#endif + + /* Now create the threads and init the workers. + * By the way, this is thread #0 (the main thread). + */ + daemon_start_others(daemon); + + /* Special handling for the main thread. This is the thread + * that handles signals and remote control. + */ +#if !(defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)) + /* libevent has the last inited base get signals (or any base) */ + if(!worker_init(daemon->workers[0], daemon->cfg, daemon->ports, 1)) + fatal_exit("Could not initialize main thread"); +#endif + signal_handling_playback(daemon->workers[0]); + + /* Start resolver service on main thread. */ + log_info("start of service (%s).", PACKAGE_STRING); + worker_work(daemon->workers[0]); + log_info("service stopped (%s).", PACKAGE_STRING); + + /* we exited! a signal happened! Stop other threads */ + daemon_stop_others(daemon); + + daemon->need_to_exit = daemon->workers[0]->need_to_exit; +} + +void +daemon_cleanup(struct daemon* daemon) +{ + int i; + log_assert(daemon); + /* before stopping main worker, handle signals ourselves, so we + don't die on multiple reload signals for example. */ + signal_handling_record(); + 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 */ + 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() */ + daemon_remote_clear(daemon->rc); + for(i=0; inum; i++) + worker_delete(daemon->workers[i]); + free(daemon->workers); + daemon->workers = NULL; + daemon->num = 0; + daemon->cfg = NULL; +} + +void +daemon_delete(struct daemon* daemon) +{ + if(!daemon) + return; + modstack_desetup(&daemon->mods, daemon->env); + daemon_remote_delete(daemon->rc); + listening_ports_free(daemon->ports); + listening_ports_free(daemon->rc_ports); + if(daemon->env) { + slabhash_delete(daemon->env->msg_cache); + rrset_cache_delete(daemon->env->rrset_cache); + infra_delete(daemon->env->infra_cache); + } + ub_randfree(daemon->rand); + alloc_clear(&daemon->superalloc); + acl_list_delete(daemon->acl); + free(daemon->chroot); + free(daemon->pidfile); + free(daemon->env); + SSL_CTX_free((SSL_CTX*)daemon->listen_sslctx); + SSL_CTX_free((SSL_CTX*)daemon->connect_sslctx); + free(daemon); +#ifdef LEX_HAS_YYLEX_DESTROY + /* lex cleanup */ + ub_c_lex_destroy(); +#endif + /* libcrypto cleanup */ +#if defined(USE_GOST) && defined(HAVE_LDNS_KEY_EVP_UNLOAD_GOST) + ldns_key_EVP_unload_gost(); +#endif +#if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS && HAVE_DECL_SK_SSL_COMP_POP_FREE +#ifndef S_SPLINT_S + sk_SSL_COMP_pop_free(comp_meth, (void(*)())CRYPTO_free); +#endif +#endif +#ifdef HAVE_OPENSSL_CONFIG + EVP_cleanup(); + ENGINE_cleanup(); + CONF_modules_free(); +#endif + CRYPTO_cleanup_all_ex_data(); /* safe, no more threads right now */ + ERR_remove_state(0); + ERR_free_strings(); + RAND_cleanup(); + checklock_stop(); +#ifdef USE_WINSOCK + if(WSACleanup() != 0) { + log_err("Could not WSACleanup: %s", + wsa_strerror(WSAGetLastError())); + } +#endif +} + +void daemon_apply_cfg(struct daemon* daemon, struct config_file* cfg) +{ + daemon->cfg = cfg; + config_apply(cfg); + if(!daemon->env->msg_cache || + cfg->msg_cache_size != slabhash_get_size(daemon->env->msg_cache) || + cfg->msg_cache_slabs != daemon->env->msg_cache->size) { + slabhash_delete(daemon->env->msg_cache); + daemon->env->msg_cache = slabhash_create(cfg->msg_cache_slabs, + HASH_DEFAULT_STARTARRAY, cfg->msg_cache_size, + msgreply_sizefunc, query_info_compare, + query_entry_delete, reply_info_delete, NULL); + if(!daemon->env->msg_cache) { + fatal_exit("malloc failure updating config settings"); + } + } + if((daemon->env->rrset_cache = rrset_cache_adjust( + daemon->env->rrset_cache, cfg, &daemon->superalloc)) == 0) + fatal_exit("malloc failure updating config settings"); + if((daemon->env->infra_cache = infra_adjust(daemon->env->infra_cache, + cfg))==0) + fatal_exit("malloc failure updating config settings"); +} diff --git a/daemon/daemon.h b/daemon/daemon.h new file mode 100644 index 00000000000..8e47ea00b9e --- /dev/null +++ b/daemon/daemon.h @@ -0,0 +1,150 @@ +/* + * daemon/daemon.h - collection of workers that handles requests. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * The daemon consists of global settings and a number of workers. + */ + +#ifndef DAEMON_H +#define DAEMON_H + +#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; +struct slabhash; +struct module_env; +struct rrset_cache; +struct acl_list; +struct local_zones; +struct ub_randstate; +struct daemon_remote; + +/** + * Structure holding worker list. + * Holds globally visible information. + */ +struct daemon { + /** The config settings */ + struct config_file* cfg; + /** the chroot dir in use, NULL if none */ + char* chroot; + /** pidfile that is used */ + char* pidfile; + /** port number that has ports opened. */ + int listening_port; + /** listening ports, opened, to be shared by threads */ + struct listen_port* ports; + /** port number for remote that has ports opened. */ + int rc_port; + /** listening ports for remote control */ + struct listen_port* rc_ports; + /** remote control connections management (for first worker) */ + struct daemon_remote* rc; + /** ssl context for listening to dnstcp over ssl, and connecting ssl */ + void* listen_sslctx, *connect_sslctx; + /** num threads allocated */ + int num; + /** the worker entries */ + struct worker** workers; + /** do we need to exit unbound (or is it only a reload?) */ + int need_to_exit; + /** master random table ; used for port div between threads on reload*/ + struct ub_randstate* rand; + /** master allocation cache */ + struct alloc_cache superalloc; + /** the module environment master value, copied and changed by threads*/ + struct module_env* env; + /** stack of module callbacks */ + struct module_stack mods; + /** access control, which client IPs are allowed to connect */ + struct acl_list* acl; + /** local authority zones */ + struct local_zones* local_zones; + /** last time of statistics printout */ + struct timeval time_last_stat; + /** time when daemon started */ + struct timeval time_boot; +}; + +/** + * Initialize daemon structure. + * @return: The daemon structure, or NULL on error. + */ +struct daemon* daemon_init(void); + +/** + * Open shared listening ports (if needed). + * The cfg member pointer must have been set for the daemon. + * @param daemon: the daemon. + * @return: false on error. + */ +int daemon_open_shared_ports(struct daemon* daemon); + +/** + * Fork workers and start service. + * When the routine exits, it is no longer forked. + * @param daemon: the daemon. + */ +void daemon_fork(struct daemon* daemon); + +/** + * Close off the worker thread information. + * Bring the daemon back into state ready for daemon_fork again. + * @param daemon: the daemon. + */ +void daemon_cleanup(struct daemon* daemon); + +/** + * Delete workers, close listening ports. + * @param daemon: the daemon. + */ +void daemon_delete(struct daemon* daemon); + +/** + * Apply config settings. + * @param daemon: the daemon. + * @param cfg: new config settings. + */ +void daemon_apply_cfg(struct daemon* daemon, struct config_file* cfg); + +#endif /* DAEMON_H */ diff --git a/daemon/remote.c b/daemon/remote.c new file mode 100644 index 00000000000..38ca15c85cd --- /dev/null +++ b/daemon/remote.c @@ -0,0 +1,2179 @@ +/* + * daemon/remote.c - remote control for the unbound daemon. + * + * Copyright (c) 2008, 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains the remote control functionality for the daemon. + * The remote control can be performed using either the commandline + * unbound-control tool, or a SSLv3/TLS capable web browser. + * The channel is secured using SSLv3 or TLSv1, and certificates. + * Both the server and the client(control tool) have their own keys. + */ +#include "config.h" +#ifdef HAVE_OPENSSL_ERR_H +#include +#endif +#include +#include +#include "daemon/remote.h" +#include "daemon/worker.h" +#include "daemon/daemon.h" +#include "daemon/stats.h" +#include "daemon/cachedump.h" +#include "util/log.h" +#include "util/config_file.h" +#include "util/net_help.h" +#include "util/module.h" +#include "services/listen_dnsport.h" +#include "services/cache/rrset.h" +#include "services/cache/infra.h" +#include "services/mesh.h" +#include "services/localzone.h" +#include "util/storage/slabhash.h" +#include "util/fptr_wlist.h" +#include "util/data/dname.h" +#include "validator/validator.h" +#include "validator/val_kcache.h" +#include "validator/val_kentry.h" +#include "validator/val_anchor.h" +#include "iterator/iterator.h" +#include "iterator/iter_fwd.h" +#include "iterator/iter_hints.h" +#include "iterator/iter_delegpt.h" +#include "services/outbound_list.h" +#include "services/outside_network.h" + +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_NETDB_H +#include +#endif + +/* just for portability */ +#ifdef SQ +#undef SQ +#endif + +/** what to put on statistics lines between var and value, ": " or "=" */ +#define SQ "=" +/** if true, inhibits a lot of =0 lines from the stats output */ +static const int inhibit_zero = 1; + +/** subtract timers and the values do not overflow or become negative */ +static void +timeval_subtract(struct timeval* d, const struct timeval* end, + const struct timeval* start) +{ +#ifndef S_SPLINT_S + time_t end_usec = end->tv_usec; + d->tv_sec = end->tv_sec - start->tv_sec; + if(end_usec < start->tv_usec) { + end_usec += 1000000; + d->tv_sec--; + } + d->tv_usec = end_usec - start->tv_usec; +#endif +} + +/** divide sum of timers to get average */ +static void +timeval_divide(struct timeval* avg, const struct timeval* sum, size_t d) +{ +#ifndef S_SPLINT_S + size_t leftover; + if(d == 0) { + avg->tv_sec = 0; + avg->tv_usec = 0; + return; + } + avg->tv_sec = sum->tv_sec / d; + avg->tv_usec = sum->tv_usec / d; + /* handle fraction from seconds divide */ + leftover = sum->tv_sec - avg->tv_sec*d; + avg->tv_usec += (leftover*1000000)/d; +#endif +} + +struct daemon_remote* +daemon_remote_create(struct config_file* cfg) +{ + char* s_cert; + char* s_key; + struct daemon_remote* rc = (struct daemon_remote*)calloc(1, + sizeof(*rc)); + if(!rc) { + log_err("out of memory in daemon_remote_create"); + return NULL; + } + rc->max_active = 10; + + if(!cfg->remote_control_enable) { + rc->ctx = NULL; + return rc; + } + rc->ctx = SSL_CTX_new(SSLv23_server_method()); + if(!rc->ctx) { + log_crypto_err("could not SSL_CTX_new"); + free(rc); + return NULL; + } + /* no SSLv2 because has defects */ + if(!(SSL_CTX_set_options(rc->ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)){ + log_crypto_err("could not set SSL_OP_NO_SSLv2"); + daemon_remote_delete(rc); + return NULL; + } + s_cert = fname_after_chroot(cfg->server_cert_file, cfg, 1); + s_key = fname_after_chroot(cfg->server_key_file, cfg, 1); + if(!s_cert || !s_key) { + log_err("out of memory in remote control fname"); + goto setup_error; + } + verbose(VERB_ALGO, "setup SSL certificates"); + if (!SSL_CTX_use_certificate_file(rc->ctx,s_cert,SSL_FILETYPE_PEM)) { + log_err("Error for server-cert-file: %s", s_cert); + log_crypto_err("Error in SSL_CTX use_certificate_file"); + goto setup_error; + } + if(!SSL_CTX_use_PrivateKey_file(rc->ctx,s_key,SSL_FILETYPE_PEM)) { + log_err("Error for server-key-file: %s", s_key); + log_crypto_err("Error in SSL_CTX use_PrivateKey_file"); + goto setup_error; + } + if(!SSL_CTX_check_private_key(rc->ctx)) { + log_err("Error for server-key-file: %s", s_key); + log_crypto_err("Error in SSL_CTX check_private_key"); + goto setup_error; + } + if(!SSL_CTX_load_verify_locations(rc->ctx, s_cert, NULL)) { + log_crypto_err("Error setting up SSL_CTX verify locations"); + setup_error: + free(s_cert); + free(s_key); + daemon_remote_delete(rc); + return NULL; + } + SSL_CTX_set_client_CA_list(rc->ctx, SSL_load_client_CA_file(s_cert)); + SSL_CTX_set_verify(rc->ctx, SSL_VERIFY_PEER, NULL); + free(s_cert); + free(s_key); + + return rc; +} + +void daemon_remote_clear(struct daemon_remote* rc) +{ + struct rc_state* p, *np; + if(!rc) return; + /* but do not close the ports */ + listen_list_delete(rc->accept_list); + rc->accept_list = NULL; + /* do close these sockets */ + p = rc->busy_list; + while(p) { + np = p->next; + if(p->ssl) + SSL_free(p->ssl); + comm_point_delete(p->c); + free(p); + p = np; + } + rc->busy_list = NULL; + rc->active = 0; + rc->worker = NULL; +} + +void daemon_remote_delete(struct daemon_remote* rc) +{ + if(!rc) return; + daemon_remote_clear(rc); + if(rc->ctx) { + SSL_CTX_free(rc->ctx); + } + free(rc); +} + +/** + * Add and open a new control port + * @param ip: ip str + * @param nr: port nr + * @param list: list head + * @param noproto_is_err: if lack of protocol support is an error. + * @return false on failure. + */ +static int +add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err) +{ + struct addrinfo hints; + struct addrinfo* res; + struct listen_port* n; + int noproto; + int fd, r; + char port[15]; + snprintf(port, sizeof(port), "%d", nr); + port[sizeof(port)-1]=0; + memset(&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; + if((r = getaddrinfo(ip, port, &hints, &res)) != 0 || !res) { +#ifdef USE_WINSOCK + if(!noproto_is_err && r == EAI_NONAME) { + /* tried to lookup the address as name */ + return 1; /* return success, but do nothing */ + } +#endif /* USE_WINSOCK */ + log_err("control interface %s:%s getaddrinfo: %s %s", + ip?ip:"default", port, gai_strerror(r), +#ifdef EAI_SYSTEM + r==EAI_SYSTEM?(char*)strerror(errno):"" +#else + "" +#endif + ); + return 0; + } + + /* open fd */ + fd = create_tcp_accept_sock(res, 1, &noproto); + freeaddrinfo(res); + if(fd == -1 && noproto) { + if(!noproto_is_err) + return 1; /* return success, but do nothing */ + log_err("cannot open control interface %s %d : " + "protocol not supported", ip, nr); + return 0; + } + if(fd == -1) { + log_err("cannot open control interface %s %d", ip, nr); + return 0; + } + + /* alloc */ + n = (struct listen_port*)calloc(1, sizeof(*n)); + if(!n) { +#ifndef USE_WINSOCK + close(fd); +#else + closesocket(fd); +#endif + log_err("out of memory"); + return 0; + } + n->next = *list; + *list = n; + n->fd = fd; + return 1; +} + +struct listen_port* daemon_remote_open_ports(struct config_file* cfg) +{ + struct listen_port* l = NULL; + log_assert(cfg->remote_control_enable && cfg->control_port); + if(cfg->control_ifs) { + struct config_strlist* p; + for(p = cfg->control_ifs; p; p = p->next) { + if(!add_open(p->str, cfg->control_port, &l, 1)) { + listening_ports_free(l); + return NULL; + } + } + } else { + /* defaults */ + if(cfg->do_ip6 && + !add_open("::1", cfg->control_port, &l, 0)) { + listening_ports_free(l); + return NULL; + } + if(cfg->do_ip4 && + !add_open("127.0.0.1", cfg->control_port, &l, 1)) { + listening_ports_free(l); + return NULL; + } + } + return l; +} + +/** open accept commpoint */ +static int +accept_open(struct daemon_remote* rc, int fd) +{ + struct listen_list* n = (struct listen_list*)malloc(sizeof(*n)); + if(!n) { + log_err("out of memory"); + return 0; + } + n->next = rc->accept_list; + rc->accept_list = n; + /* open commpt */ + n->com = comm_point_create_raw(rc->worker->base, fd, 0, + &remote_accept_callback, rc); + if(!n->com) + return 0; + /* keep this port open, its fd is kept in the rc portlist */ + n->com->do_not_close = 1; + return 1; +} + +int daemon_remote_open_accept(struct daemon_remote* rc, + struct listen_port* ports, struct worker* worker) +{ + struct listen_port* p; + rc->worker = worker; + for(p = ports; p; p = p->next) { + if(!accept_open(rc, p->fd)) { + log_err("could not create accept comm point"); + return 0; + } + } + return 1; +} + +void daemon_remote_stop_accept(struct daemon_remote* rc) +{ + struct listen_list* p; + for(p=rc->accept_list; p; p=p->next) { + comm_point_stop_listening(p->com); + } +} + +void daemon_remote_start_accept(struct daemon_remote* rc) +{ + struct listen_list* p; + for(p=rc->accept_list; p; p=p->next) { + comm_point_start_listening(p->com, -1, -1); + } +} + +int remote_accept_callback(struct comm_point* c, void* arg, int err, + struct comm_reply* ATTR_UNUSED(rep)) +{ + struct daemon_remote* rc = (struct daemon_remote*)arg; + struct sockaddr_storage addr; + socklen_t addrlen; + int newfd; + struct rc_state* n; + if(err != NETEVENT_NOERROR) { + log_err("error %d on remote_accept_callback", err); + return 0; + } + /* perform the accept */ + newfd = comm_point_perform_accept(c, &addr, &addrlen); + if(newfd == -1) + return 0; + /* create new commpoint unless we are servicing already */ + if(rc->active >= rc->max_active) { + log_warn("drop incoming remote control: too many connections"); + close_exit: +#ifndef USE_WINSOCK + close(newfd); +#else + closesocket(newfd); +#endif + return 0; + } + + /* setup commpoint to service the remote control command */ + n = (struct rc_state*)calloc(1, sizeof(*n)); + if(!n) { + log_err("out of memory"); + goto close_exit; + } + /* start in reading state */ + n->c = comm_point_create_raw(rc->worker->base, newfd, 0, + &remote_control_callback, n); + if(!n->c) { + log_err("out of memory"); + free(n); + goto close_exit; + } + log_addr(VERB_QUERY, "new control connection from", &addr, addrlen); + n->c->do_not_close = 0; + comm_point_stop_listening(n->c); + comm_point_start_listening(n->c, -1, REMOTE_CONTROL_TCP_TIMEOUT); + memcpy(&n->c->repinfo.addr, &addr, addrlen); + n->c->repinfo.addrlen = addrlen; + n->shake_state = rc_hs_read; + n->ssl = SSL_new(rc->ctx); + if(!n->ssl) { + log_crypto_err("could not SSL_new"); + comm_point_delete(n->c); + free(n); + goto close_exit; + } + SSL_set_accept_state(n->ssl); + (void)SSL_set_mode(n->ssl, SSL_MODE_AUTO_RETRY); + if(!SSL_set_fd(n->ssl, newfd)) { + log_crypto_err("could not SSL_set_fd"); + SSL_free(n->ssl); + comm_point_delete(n->c); + free(n); + goto close_exit; + } + + n->rc = rc; + n->next = rc->busy_list; + rc->busy_list = n; + rc->active ++; + + /* perform the first nonblocking read already, for windows, + * so it can return wouldblock. could be faster too. */ + (void)remote_control_callback(n->c, n, NETEVENT_NOERROR, NULL); + return 0; +} + +/** delete from list */ +static void +state_list_remove_elem(struct rc_state** list, struct comm_point* c) +{ + while(*list) { + if( (*list)->c == c) { + *list = (*list)->next; + return; + } + list = &(*list)->next; + } +} + +/** decrease active count and remove commpoint from busy list */ +static void +clean_point(struct daemon_remote* rc, struct rc_state* s) +{ + state_list_remove_elem(&rc->busy_list, s->c); + rc->active --; + if(s->ssl) { + SSL_shutdown(s->ssl); + SSL_free(s->ssl); + } + comm_point_delete(s->c); + free(s); +} + +int +ssl_print_text(SSL* ssl, const char* text) +{ + int r; + if(!ssl) + return 0; + ERR_clear_error(); + if((r=SSL_write(ssl, text, (int)strlen(text))) <= 0) { + if(SSL_get_error(ssl, r) == SSL_ERROR_ZERO_RETURN) { + verbose(VERB_QUERY, "warning, in SSL_write, peer " + "closed connection"); + return 0; + } + log_crypto_err("could not SSL_write"); + return 0; + } + return 1; +} + +/** print text over the ssl connection */ +static int +ssl_print_vmsg(SSL* ssl, const char* format, va_list args) +{ + char msg[1024]; + vsnprintf(msg, sizeof(msg), format, args); + return ssl_print_text(ssl, msg); +} + +/** printf style printing to the ssl connection */ +int ssl_printf(SSL* ssl, const char* format, ...) +{ + va_list args; + int ret; + va_start(args, format); + ret = ssl_print_vmsg(ssl, format, args); + va_end(args); + return ret; +} + +int +ssl_read_line(SSL* ssl, char* buf, size_t max) +{ + int r; + size_t len = 0; + if(!ssl) + return 0; + while(len < max) { + ERR_clear_error(); + if((r=SSL_read(ssl, buf+len, 1)) <= 0) { + if(SSL_get_error(ssl, r) == SSL_ERROR_ZERO_RETURN) { + buf[len] = 0; + return 1; + } + log_crypto_err("could not SSL_read"); + return 0; + } + if(buf[len] == '\n') { + /* return string without \n */ + buf[len] = 0; + return 1; + } + len++; + } + buf[max-1] = 0; + log_err("control line too long (%d): %s", (int)max, buf); + return 0; +} + +/** skip whitespace, return new pointer into string */ +static char* +skipwhite(char* str) +{ + /* EOS \0 is not a space */ + while( isspace(*str) ) + str++; + return str; +} + +/** send the OK to the control client */ +static void send_ok(SSL* ssl) +{ + (void)ssl_printf(ssl, "ok\n"); +} + +/** do the stop command */ +static void +do_stop(SSL* ssl, struct daemon_remote* rc) +{ + rc->worker->need_to_exit = 1; + comm_base_exit(rc->worker->base); + send_ok(ssl); +} + +/** do the reload command */ +static void +do_reload(SSL* ssl, struct daemon_remote* rc) +{ + rc->worker->need_to_exit = 0; + comm_base_exit(rc->worker->base); + send_ok(ssl); +} + +/** do the verbosity command */ +static void +do_verbosity(SSL* ssl, char* str) +{ + int val = atoi(str); + if(val == 0 && strcmp(str, "0") != 0) { + ssl_printf(ssl, "error in verbosity number syntax: %s\n", str); + return; + } + verbosity = val; + send_ok(ssl); +} + +/** print stats from statinfo */ +static int +print_stats(SSL* ssl, const char* nm, struct stats_info* s) +{ + struct timeval avg; + if(!ssl_printf(ssl, "%s.num.queries"SQ"%u\n", nm, + (unsigned)s->svr.num_queries)) return 0; + if(!ssl_printf(ssl, "%s.num.cachehits"SQ"%u\n", nm, + (unsigned)(s->svr.num_queries + - s->svr.num_queries_missed_cache))) return 0; + if(!ssl_printf(ssl, "%s.num.cachemiss"SQ"%u\n", nm, + (unsigned)s->svr.num_queries_missed_cache)) return 0; + if(!ssl_printf(ssl, "%s.num.prefetch"SQ"%u\n", nm, + (unsigned)s->svr.num_queries_prefetch)) return 0; + if(!ssl_printf(ssl, "%s.num.recursivereplies"SQ"%u\n", nm, + (unsigned)s->mesh_replies_sent)) return 0; + if(!ssl_printf(ssl, "%s.requestlist.avg"SQ"%g\n", nm, + (s->svr.num_queries_missed_cache+s->svr.num_queries_prefetch)? + (double)s->svr.sum_query_list_size/ + (s->svr.num_queries_missed_cache+ + s->svr.num_queries_prefetch) : 0.0)) return 0; + if(!ssl_printf(ssl, "%s.requestlist.max"SQ"%u\n", nm, + (unsigned)s->svr.max_query_list_size)) return 0; + if(!ssl_printf(ssl, "%s.requestlist.overwritten"SQ"%u\n", nm, + (unsigned)s->mesh_jostled)) return 0; + if(!ssl_printf(ssl, "%s.requestlist.exceeded"SQ"%u\n", nm, + (unsigned)s->mesh_dropped)) return 0; + if(!ssl_printf(ssl, "%s.requestlist.current.all"SQ"%u\n", nm, + (unsigned)s->mesh_num_states)) return 0; + if(!ssl_printf(ssl, "%s.requestlist.current.user"SQ"%u\n", nm, + (unsigned)s->mesh_num_reply_states)) return 0; + timeval_divide(&avg, &s->mesh_replies_sum_wait, s->mesh_replies_sent); + if(!ssl_printf(ssl, "%s.recursion.time.avg"SQ"%d.%6.6d\n", nm, + (int)avg.tv_sec, (int)avg.tv_usec)) return 0; + if(!ssl_printf(ssl, "%s.recursion.time.median"SQ"%g\n", nm, + s->mesh_time_median)) return 0; + return 1; +} + +/** print stats for one thread */ +static int +print_thread_stats(SSL* ssl, int i, struct stats_info* s) +{ + char nm[16]; + snprintf(nm, sizeof(nm), "thread%d", i); + nm[sizeof(nm)-1]=0; + return print_stats(ssl, nm, s); +} + +/** print long number */ +static int +print_longnum(SSL* ssl, char* desc, size_t x) +{ + if(x > 1024*1024*1024) { + /* more than a Gb */ + size_t front = x / (size_t)1000000; + size_t back = x % (size_t)1000000; + return ssl_printf(ssl, "%s%u%6.6u\n", desc, + (unsigned)front, (unsigned)back); + } else { + return ssl_printf(ssl, "%s%u\n", desc, (unsigned)x); + } +} + +/** print mem stats */ +static int +print_mem(SSL* ssl, struct worker* worker, struct daemon* daemon) +{ + int m; + size_t msg, rrset, val, iter; +#ifdef HAVE_SBRK + extern void* unbound_start_brk; + void* cur = sbrk(0); + if(!print_longnum(ssl, "mem.total.sbrk"SQ, + (size_t)((char*)cur - (char*)unbound_start_brk))) return 0; +#endif /* HAVE_SBRK */ + msg = slabhash_get_mem(daemon->env->msg_cache); + rrset = slabhash_get_mem(&daemon->env->rrset_cache->table); + val=0; + iter=0; + m = modstack_find(&worker->env.mesh->mods, "validator"); + if(m != -1) { + fptr_ok(fptr_whitelist_mod_get_mem(worker->env.mesh-> + mods.mod[m]->get_mem)); + val = (*worker->env.mesh->mods.mod[m]->get_mem) + (&worker->env, m); + } + m = modstack_find(&worker->env.mesh->mods, "iterator"); + if(m != -1) { + fptr_ok(fptr_whitelist_mod_get_mem(worker->env.mesh-> + mods.mod[m]->get_mem)); + iter = (*worker->env.mesh->mods.mod[m]->get_mem) + (&worker->env, m); + } + + if(!print_longnum(ssl, "mem.cache.rrset"SQ, rrset)) + return 0; + if(!print_longnum(ssl, "mem.cache.message"SQ, msg)) + return 0; + if(!print_longnum(ssl, "mem.mod.iterator"SQ, iter)) + return 0; + if(!print_longnum(ssl, "mem.mod.validator"SQ, val)) + return 0; + return 1; +} + +/** print uptime stats */ +static int +print_uptime(SSL* ssl, struct worker* worker, int reset) +{ + struct timeval now = *worker->env.now_tv; + struct timeval up, dt; + timeval_subtract(&up, &now, &worker->daemon->time_boot); + timeval_subtract(&dt, &now, &worker->daemon->time_last_stat); + if(reset) + worker->daemon->time_last_stat = now; + if(!ssl_printf(ssl, "time.now"SQ"%d.%6.6d\n", + (unsigned)now.tv_sec, (unsigned)now.tv_usec)) return 0; + if(!ssl_printf(ssl, "time.up"SQ"%d.%6.6d\n", + (unsigned)up.tv_sec, (unsigned)up.tv_usec)) return 0; + if(!ssl_printf(ssl, "time.elapsed"SQ"%d.%6.6d\n", + (unsigned)dt.tv_sec, (unsigned)dt.tv_usec)) return 0; + return 1; +} + +/** print extended histogram */ +static int +print_hist(SSL* ssl, struct stats_info* s) +{ + struct timehist* hist; + size_t i; + hist = timehist_setup(); + if(!hist) { + log_err("out of memory"); + return 0; + } + timehist_import(hist, s->svr.hist, NUM_BUCKETS_HIST); + for(i=0; inum; i++) { + if(!ssl_printf(ssl, + "histogram.%6.6d.%6.6d.to.%6.6d.%6.6d=%u\n", + (int)hist->buckets[i].lower.tv_sec, + (int)hist->buckets[i].lower.tv_usec, + (int)hist->buckets[i].upper.tv_sec, + (int)hist->buckets[i].upper.tv_usec, + (unsigned)hist->buckets[i].count)) { + timehist_delete(hist); + return 0; + } + } + timehist_delete(hist); + return 1; +} + +/** print extended stats */ +static int +print_ext(SSL* ssl, struct stats_info* s) +{ + int i; + char nm[16]; + const ldns_rr_descriptor* desc; + const ldns_lookup_table* lt; + /* TYPE */ + for(i=0; isvr.qtype[i] == 0) + continue; + desc = ldns_rr_descript((uint16_t)i); + if(desc && desc->_name) { + snprintf(nm, sizeof(nm), "%s", desc->_name); + } else if (i == LDNS_RR_TYPE_IXFR) { + snprintf(nm, sizeof(nm), "IXFR"); + } else if (i == LDNS_RR_TYPE_AXFR) { + snprintf(nm, sizeof(nm), "AXFR"); + } else if (i == LDNS_RR_TYPE_MAILA) { + snprintf(nm, sizeof(nm), "MAILA"); + } else if (i == LDNS_RR_TYPE_MAILB) { + snprintf(nm, sizeof(nm), "MAILB"); + } else if (i == LDNS_RR_TYPE_ANY) { + snprintf(nm, sizeof(nm), "ANY"); + } else { + snprintf(nm, sizeof(nm), "TYPE%d", i); + } + if(!ssl_printf(ssl, "num.query.type.%s"SQ"%u\n", + nm, (unsigned)s->svr.qtype[i])) return 0; + } + if(!inhibit_zero || s->svr.qtype_big) { + if(!ssl_printf(ssl, "num.query.type.other"SQ"%u\n", + (unsigned)s->svr.qtype_big)) return 0; + } + /* CLASS */ + for(i=0; isvr.qclass[i] == 0) + continue; + lt = ldns_lookup_by_id(ldns_rr_classes, i); + if(lt && lt->name) { + snprintf(nm, sizeof(nm), "%s", lt->name); + } else { + snprintf(nm, sizeof(nm), "CLASS%d", i); + } + if(!ssl_printf(ssl, "num.query.class.%s"SQ"%u\n", + nm, (unsigned)s->svr.qclass[i])) return 0; + } + if(!inhibit_zero || s->svr.qclass_big) { + if(!ssl_printf(ssl, "num.query.class.other"SQ"%u\n", + (unsigned)s->svr.qclass_big)) return 0; + } + /* OPCODE */ + for(i=0; isvr.qopcode[i] == 0) + continue; + lt = ldns_lookup_by_id(ldns_opcodes, i); + if(lt && lt->name) { + snprintf(nm, sizeof(nm), "%s", lt->name); + } else { + snprintf(nm, sizeof(nm), "OPCODE%d", i); + } + if(!ssl_printf(ssl, "num.query.opcode.%s"SQ"%u\n", + nm, (unsigned)s->svr.qopcode[i])) return 0; + } + /* transport */ + if(!ssl_printf(ssl, "num.query.tcp"SQ"%u\n", + (unsigned)s->svr.qtcp)) return 0; + if(!ssl_printf(ssl, "num.query.ipv6"SQ"%u\n", + (unsigned)s->svr.qipv6)) return 0; + /* flags */ + if(!ssl_printf(ssl, "num.query.flags.QR"SQ"%u\n", + (unsigned)s->svr.qbit_QR)) return 0; + if(!ssl_printf(ssl, "num.query.flags.AA"SQ"%u\n", + (unsigned)s->svr.qbit_AA)) return 0; + if(!ssl_printf(ssl, "num.query.flags.TC"SQ"%u\n", + (unsigned)s->svr.qbit_TC)) return 0; + if(!ssl_printf(ssl, "num.query.flags.RD"SQ"%u\n", + (unsigned)s->svr.qbit_RD)) return 0; + if(!ssl_printf(ssl, "num.query.flags.RA"SQ"%u\n", + (unsigned)s->svr.qbit_RA)) return 0; + if(!ssl_printf(ssl, "num.query.flags.Z"SQ"%u\n", + (unsigned)s->svr.qbit_Z)) return 0; + if(!ssl_printf(ssl, "num.query.flags.AD"SQ"%u\n", + (unsigned)s->svr.qbit_AD)) return 0; + if(!ssl_printf(ssl, "num.query.flags.CD"SQ"%u\n", + (unsigned)s->svr.qbit_CD)) return 0; + if(!ssl_printf(ssl, "num.query.edns.present"SQ"%u\n", + (unsigned)s->svr.qEDNS)) return 0; + if(!ssl_printf(ssl, "num.query.edns.DO"SQ"%u\n", + (unsigned)s->svr.qEDNS_DO)) return 0; + + /* RCODE */ + for(i=0; isvr.ans_rcode[i] == 0) + continue; + lt = ldns_lookup_by_id(ldns_rcodes, i); + if(lt && lt->name) { + snprintf(nm, sizeof(nm), "%s", lt->name); + } else { + snprintf(nm, sizeof(nm), "RCODE%d", i); + } + if(!ssl_printf(ssl, "num.answer.rcode.%s"SQ"%u\n", + nm, (unsigned)s->svr.ans_rcode[i])) return 0; + } + if(!inhibit_zero || s->svr.ans_rcode_nodata) { + if(!ssl_printf(ssl, "num.answer.rcode.nodata"SQ"%u\n", + (unsigned)s->svr.ans_rcode_nodata)) return 0; + } + /* validation */ + if(!ssl_printf(ssl, "num.answer.secure"SQ"%u\n", + (unsigned)s->svr.ans_secure)) return 0; + if(!ssl_printf(ssl, "num.answer.bogus"SQ"%u\n", + (unsigned)s->svr.ans_bogus)) return 0; + if(!ssl_printf(ssl, "num.rrset.bogus"SQ"%u\n", + (unsigned)s->svr.rrset_bogus)) return 0; + /* threat detection */ + if(!ssl_printf(ssl, "unwanted.queries"SQ"%u\n", + (unsigned)s->svr.unwanted_queries)) return 0; + if(!ssl_printf(ssl, "unwanted.replies"SQ"%u\n", + (unsigned)s->svr.unwanted_replies)) return 0; + return 1; +} + +/** do the stats command */ +static void +do_stats(SSL* ssl, struct daemon_remote* rc, int reset) +{ + struct daemon* daemon = rc->worker->daemon; + struct stats_info total; + struct stats_info s; + int i; + log_assert(daemon->num > 0); + /* gather all thread statistics in one place */ + for(i=0; inum; i++) { + server_stats_obtain(rc->worker, daemon->workers[i], &s, reset); + if(!print_thread_stats(ssl, i, &s)) + return; + if(i == 0) + total = s; + else server_stats_add(&total, &s); + } + /* print the thread statistics */ + total.mesh_time_median /= (double)daemon->num; + if(!print_stats(ssl, "total", &total)) + return; + if(!print_uptime(ssl, rc->worker, reset)) + return; + if(daemon->cfg->stat_extended) { + if(!print_mem(ssl, rc->worker, daemon)) + return; + if(!print_hist(ssl, &total)) + return; + if(!print_ext(ssl, &total)) + return; + } +} + +/** parse commandline argument domain name */ +static int +parse_arg_name(SSL* ssl, char* str, uint8_t** res, size_t* len, int* labs) +{ + ldns_rdf* rdf; + *res = NULL; + *len = 0; + *labs = 0; + rdf = ldns_dname_new_frm_str(str); + if(!rdf) { + ssl_printf(ssl, "error cannot parse name %s\n", str); + return 0; + } + *res = memdup(ldns_rdf_data(rdf), ldns_rdf_size(rdf)); + ldns_rdf_deep_free(rdf); + if(!*res) { + ssl_printf(ssl, "error out of memory\n"); + return 0; + } + *labs = dname_count_size_labels(*res, len); + return 1; +} + +/** find second argument, modifies string */ +static int +find_arg2(SSL* ssl, char* arg, char** arg2) +{ + char* as = strchr(arg, ' '); + char* at = strchr(arg, '\t'); + if(as && at) { + if(at < as) + as = at; + as[0]=0; + *arg2 = skipwhite(as+1); + } else if(as) { + as[0]=0; + *arg2 = skipwhite(as+1); + } else if(at) { + at[0]=0; + *arg2 = skipwhite(at+1); + } else { + ssl_printf(ssl, "error could not find next argument " + "after %s\n", arg); + return 0; + } + return 1; +} + +/** Add a new zone */ +static void +do_zone_add(SSL* ssl, struct worker* worker, char* arg) +{ + uint8_t* nm; + int nmlabs; + size_t nmlen; + char* arg2; + enum localzone_type t; + struct local_zone* z; + if(!find_arg2(ssl, arg, &arg2)) + return; + if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs)) + return; + if(!local_zone_str2type(arg2, &t)) { + ssl_printf(ssl, "error not a zone type. %s\n", arg2); + free(nm); + return; + } + lock_quick_lock(&worker->daemon->local_zones->lock); + if((z=local_zones_find(worker->daemon->local_zones, nm, nmlen, + nmlabs, LDNS_RR_CLASS_IN))) { + /* already present in tree */ + lock_rw_wrlock(&z->lock); + z->type = t; /* update type anyway */ + lock_rw_unlock(&z->lock); + free(nm); + lock_quick_unlock(&worker->daemon->local_zones->lock); + send_ok(ssl); + return; + } + if(!local_zones_add_zone(worker->daemon->local_zones, nm, nmlen, + nmlabs, LDNS_RR_CLASS_IN, t)) { + lock_quick_unlock(&worker->daemon->local_zones->lock); + ssl_printf(ssl, "error out of memory\n"); + return; + } + lock_quick_unlock(&worker->daemon->local_zones->lock); + send_ok(ssl); +} + +/** Remove a zone */ +static void +do_zone_remove(SSL* ssl, struct worker* worker, char* arg) +{ + uint8_t* nm; + int nmlabs; + size_t nmlen; + struct local_zone* z; + if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs)) + return; + lock_quick_lock(&worker->daemon->local_zones->lock); + if((z=local_zones_find(worker->daemon->local_zones, nm, nmlen, + nmlabs, LDNS_RR_CLASS_IN))) { + /* present in tree */ + local_zones_del_zone(worker->daemon->local_zones, z); + } + lock_quick_unlock(&worker->daemon->local_zones->lock); + free(nm); + send_ok(ssl); +} + +/** Add new RR data */ +static void +do_data_add(SSL* ssl, struct worker* worker, char* arg) +{ + if(!local_zones_add_RR(worker->daemon->local_zones, arg, + worker->env.scratch_buffer)) { + ssl_printf(ssl,"error in syntax or out of memory, %s\n", arg); + return; + } + send_ok(ssl); +} + +/** Remove RR data */ +static void +do_data_remove(SSL* ssl, struct worker* worker, char* arg) +{ + uint8_t* nm; + int nmlabs; + size_t nmlen; + if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs)) + return; + local_zones_del_data(worker->daemon->local_zones, nm, + nmlen, nmlabs, LDNS_RR_CLASS_IN); + free(nm); + send_ok(ssl); +} + +/** cache lookup of nameservers */ +static void +do_lookup(SSL* ssl, struct worker* worker, char* arg) +{ + uint8_t* nm; + int nmlabs; + size_t nmlen; + if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs)) + return; + (void)print_deleg_lookup(ssl, worker, nm, nmlen, nmlabs); + free(nm); +} + +/** flush something from rrset and msg caches */ +static void +do_cache_remove(struct worker* worker, uint8_t* nm, size_t nmlen, + uint16_t t, uint16_t c) +{ + hashvalue_t h; + struct query_info k; + rrset_cache_remove(worker->env.rrset_cache, nm, nmlen, t, c, 0); + if(t == LDNS_RR_TYPE_SOA) + rrset_cache_remove(worker->env.rrset_cache, nm, nmlen, t, c, + PACKED_RRSET_SOA_NEG); + k.qname = nm; + k.qname_len = nmlen; + k.qtype = t; + k.qclass = c; + h = query_info_hash(&k); + slabhash_remove(worker->env.msg_cache, h, &k); +} + +/** flush a type */ +static void +do_flush_type(SSL* ssl, struct worker* worker, char* arg) +{ + uint8_t* nm; + int nmlabs; + size_t nmlen; + char* arg2; + uint16_t t; + if(!find_arg2(ssl, arg, &arg2)) + return; + if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs)) + return; + t = ldns_get_rr_type_by_name(arg2); + do_cache_remove(worker, nm, nmlen, t, LDNS_RR_CLASS_IN); + + free(nm); + send_ok(ssl); +} + +/** flush statistics */ +static void +do_flush_stats(SSL* ssl, struct worker* worker) +{ + worker_stats_clear(worker); + send_ok(ssl); +} + +/** + * Local info for deletion functions + */ +struct del_info { + /** worker */ + struct worker* worker; + /** name to delete */ + uint8_t* name; + /** length */ + size_t len; + /** labels */ + int labs; + /** now */ + uint32_t now; + /** time to invalidate to */ + uint32_t expired; + /** number of rrsets removed */ + size_t num_rrsets; + /** number of msgs removed */ + size_t num_msgs; + /** number of key entries removed */ + size_t num_keys; + /** length of addr */ + socklen_t addrlen; + /** socket address for host deletion */ + struct sockaddr_storage addr; +}; + +/** callback to delete hosts in infra cache */ +static void +infra_del_host(struct lruhash_entry* e, void* arg) +{ + /* entry is locked */ + struct del_info* inf = (struct del_info*)arg; + struct infra_key* k = (struct infra_key*)e->key; + if(sockaddr_cmp(&inf->addr, inf->addrlen, &k->addr, k->addrlen) == 0) { + struct infra_data* d = (struct infra_data*)e->data; + d->probedelay = 0; + d->timeout_A = 0; + d->timeout_AAAA = 0; + d->timeout_other = 0; + rtt_init(&d->rtt); + if(d->ttl >= inf->now) { + d->ttl = inf->expired; + inf->num_keys++; + } + } +} + +/** flush infra cache */ +static void +do_flush_infra(SSL* ssl, struct worker* worker, char* arg) +{ + struct sockaddr_storage addr; + socklen_t len; + struct del_info inf; + if(strcmp(arg, "all") == 0) { + slabhash_clear(worker->env.infra_cache->hosts); + send_ok(ssl); + return; + } + if(!ipstrtoaddr(arg, UNBOUND_DNS_PORT, &addr, &len)) { + (void)ssl_printf(ssl, "error parsing ip addr: '%s'\n", arg); + return; + } + /* delete all entries from cache */ + /* what we do is to set them all expired */ + inf.worker = worker; + inf.name = 0; + inf.len = 0; + inf.labs = 0; + inf.now = *worker->env.now; + inf.expired = *worker->env.now; + inf.expired -= 3; /* handle 3 seconds skew between threads */ + inf.num_rrsets = 0; + inf.num_msgs = 0; + inf.num_keys = 0; + inf.addrlen = len; + memmove(&inf.addr, &addr, len); + slabhash_traverse(worker->env.infra_cache->hosts, 1, &infra_del_host, + &inf); + send_ok(ssl); +} + +/** flush requestlist */ +static void +do_flush_requestlist(SSL* ssl, struct worker* worker) +{ + mesh_delete_all(worker->env.mesh); + send_ok(ssl); +} + +/** callback to delete rrsets in a zone */ +static void +zone_del_rrset(struct lruhash_entry* e, void* arg) +{ + /* entry is locked */ + struct del_info* inf = (struct del_info*)arg; + struct ub_packed_rrset_key* k = (struct ub_packed_rrset_key*)e->key; + if(dname_subdomain_c(k->rk.dname, inf->name)) { + struct packed_rrset_data* d = + (struct packed_rrset_data*)e->data; + if(d->ttl >= inf->now) { + d->ttl = inf->expired; + inf->num_rrsets++; + } + } +} + +/** callback to delete messages in a zone */ +static void +zone_del_msg(struct lruhash_entry* e, void* arg) +{ + /* entry is locked */ + struct del_info* inf = (struct del_info*)arg; + struct msgreply_entry* k = (struct msgreply_entry*)e->key; + if(dname_subdomain_c(k->key.qname, inf->name)) { + struct reply_info* d = (struct reply_info*)e->data; + if(d->ttl >= inf->now) { + d->ttl = inf->expired; + inf->num_msgs++; + } + } +} + +/** callback to delete keys in zone */ +static void +zone_del_kcache(struct lruhash_entry* e, void* arg) +{ + /* entry is locked */ + struct del_info* inf = (struct del_info*)arg; + struct key_entry_key* k = (struct key_entry_key*)e->key; + if(dname_subdomain_c(k->name, inf->name)) { + struct key_entry_data* d = (struct key_entry_data*)e->data; + if(d->ttl >= inf->now) { + d->ttl = inf->expired; + inf->num_keys++; + } + } +} + +/** remove all rrsets and keys from zone from cache */ +static void +do_flush_zone(SSL* ssl, struct worker* worker, char* arg) +{ + uint8_t* nm; + int nmlabs; + size_t nmlen; + struct del_info inf; + if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs)) + return; + /* delete all RRs and key entries from zone */ + /* what we do is to set them all expired */ + inf.worker = worker; + inf.name = nm; + inf.len = nmlen; + inf.labs = nmlabs; + inf.now = *worker->env.now; + inf.expired = *worker->env.now; + inf.expired -= 3; /* handle 3 seconds skew between threads */ + inf.num_rrsets = 0; + inf.num_msgs = 0; + inf.num_keys = 0; + slabhash_traverse(&worker->env.rrset_cache->table, 1, + &zone_del_rrset, &inf); + + slabhash_traverse(worker->env.msg_cache, 1, &zone_del_msg, &inf); + + /* and validator cache */ + if(worker->env.key_cache) { + slabhash_traverse(worker->env.key_cache->slab, 1, + &zone_del_kcache, &inf); + } + + free(nm); + + (void)ssl_printf(ssl, "ok removed %u rrsets, %u messages " + "and %u key entries\n", (unsigned)inf.num_rrsets, + (unsigned)inf.num_msgs, (unsigned)inf.num_keys); +} + +/** remove name rrset from cache */ +static void +do_flush_name(SSL* ssl, struct worker* w, char* arg) +{ + uint8_t* nm; + int nmlabs; + size_t nmlen; + if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs)) + return; + do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_A, LDNS_RR_CLASS_IN); + do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_AAAA, LDNS_RR_CLASS_IN); + do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_NS, LDNS_RR_CLASS_IN); + do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_SOA, LDNS_RR_CLASS_IN); + do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_CNAME, LDNS_RR_CLASS_IN); + do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_DNAME, LDNS_RR_CLASS_IN); + do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_MX, LDNS_RR_CLASS_IN); + do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_PTR, LDNS_RR_CLASS_IN); + do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_SRV, LDNS_RR_CLASS_IN); + do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_NAPTR, LDNS_RR_CLASS_IN); + + free(nm); + send_ok(ssl); +} + +/** printout a delegation point info */ +static int +ssl_print_name_dp(SSL* ssl, char* str, uint8_t* nm, uint16_t dclass, + struct delegpt* dp) +{ + char buf[257]; + struct delegpt_ns* ns; + struct delegpt_addr* a; + int f = 0; + if(str) { /* print header for forward, stub */ + char* c = ldns_rr_class2str(dclass); + dname_str(nm, buf); + if(!ssl_printf(ssl, "%s %s %s: ", buf, c, str)) { + free(c); + return 0; + } + free(c); + } + for(ns = dp->nslist; ns; ns = ns->next) { + dname_str(ns->name, buf); + if(!ssl_printf(ssl, "%s%s", (f?" ":""), buf)) + return 0; + f = 1; + } + for(a = dp->target_list; a; a = a->next_target) { + addr_to_str(&a->addr, a->addrlen, buf, sizeof(buf)); + if(!ssl_printf(ssl, "%s%s", (f?" ":""), buf)) + return 0; + f = 1; + } + return ssl_printf(ssl, "\n"); +} + + +/** print root forwards */ +static int +print_root_fwds(SSL* ssl, struct iter_forwards* fwds, uint8_t* root) +{ + struct delegpt* dp; + dp = forwards_lookup(fwds, root, LDNS_RR_CLASS_IN); + if(!dp) + return ssl_printf(ssl, "off (using root hints)\n"); + /* if dp is returned it must be the root */ + log_assert(query_dname_compare(dp->name, root)==0); + return ssl_print_name_dp(ssl, NULL, root, LDNS_RR_CLASS_IN, dp); +} + +/** parse args into delegpt */ +static struct delegpt* +parse_delegpt(SSL* ssl, char* args, uint8_t* nm, int allow_names) +{ + /* parse args and add in */ + char* p = args; + char* todo; + struct delegpt* dp = delegpt_create_mlc(nm); + struct sockaddr_storage addr; + socklen_t addrlen; + if(!dp) { + (void)ssl_printf(ssl, "error out of memory\n"); + return NULL; + } + while(p) { + todo = p; + p = strchr(p, ' '); /* find next spot, if any */ + if(p) { + *p++ = 0; /* end this spot */ + p = skipwhite(p); /* position at next spot */ + } + /* parse address */ + if(!extstrtoaddr(todo, &addr, &addrlen)) { + if(allow_names) { + uint8_t* n = NULL; + size_t ln; + int lb; + if(!parse_arg_name(ssl, todo, &n, &ln, &lb)) { + (void)ssl_printf(ssl, "error cannot " + "parse IP address or name " + "'%s'\n", todo); + delegpt_free_mlc(dp); + return NULL; + } + if(!delegpt_add_ns_mlc(dp, n, 0)) { + (void)ssl_printf(ssl, "error out of memory\n"); + delegpt_free_mlc(dp); + return NULL; + } + free(n); + + } else { + (void)ssl_printf(ssl, "error cannot parse" + " IP address '%s'\n", todo); + delegpt_free_mlc(dp); + return NULL; + } + } else { + /* add address */ + if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0)) { + (void)ssl_printf(ssl, "error out of memory\n"); + delegpt_free_mlc(dp); + return NULL; + } + } + } + return dp; +} + +/** do the status command */ +static void +do_forward(SSL* ssl, struct worker* worker, char* args) +{ + struct iter_forwards* fwd = worker->env.fwds; + uint8_t* root = (uint8_t*)"\000"; + if(!fwd) { + (void)ssl_printf(ssl, "error: structure not allocated\n"); + return; + } + if(args == NULL || args[0] == 0) { + (void)print_root_fwds(ssl, fwd, root); + return; + } + /* set root forwards for this thread. since we are in remote control + * the actual mesh is not running, so we can freely edit it. */ + /* delete all the existing queries first */ + mesh_delete_all(worker->env.mesh); + if(strcmp(args, "off") == 0) { + forwards_delete_zone(fwd, LDNS_RR_CLASS_IN, root); + } else { + struct delegpt* dp; + if(!(dp = parse_delegpt(ssl, args, root, 0))) + return; + if(!forwards_add_zone(fwd, LDNS_RR_CLASS_IN, dp)) { + (void)ssl_printf(ssl, "error out of memory\n"); + delegpt_free_mlc(dp); + return; + } + } + send_ok(ssl); +} + +static int +parse_fs_args(SSL* ssl, char* args, uint8_t** nm, struct delegpt** dp, + int* insecure, int* prime) +{ + char* zonename; + char* rest; + size_t nmlen; + int nmlabs; + /* parse all -x args */ + while(args[0] == '+') { + if(!find_arg2(ssl, args, &rest)) + return 0; + while(*(++args) != 0) { + if(*args == 'i' && insecure) + *insecure = 1; + else if(*args == 'p' && prime) + *prime = 1; + else { + (void)ssl_printf(ssl, "error: unknown option %s\n", args); + return 0; + } + } + args = rest; + } + /* parse name */ + if(dp) { + if(!find_arg2(ssl, args, &rest)) + return 0; + zonename = args; + args = rest; + } else zonename = args; + if(!parse_arg_name(ssl, zonename, nm, &nmlen, &nmlabs)) + return 0; + + /* parse dp */ + if(dp) { + if(!(*dp = parse_delegpt(ssl, args, *nm, 1))) { + free(*nm); + return 0; + } + } + return 1; +} + +/** do the forward_add command */ +static void +do_forward_add(SSL* ssl, struct worker* worker, char* args) +{ + struct iter_forwards* fwd = worker->env.fwds; + int insecure = 0; + uint8_t* nm = NULL; + struct delegpt* dp = NULL; + if(!parse_fs_args(ssl, args, &nm, &dp, &insecure, NULL)) + return; + if(insecure) { + if(!anchors_add_insecure(worker->env.anchors, LDNS_RR_CLASS_IN, + nm)) { + (void)ssl_printf(ssl, "error out of memory\n"); + delegpt_free_mlc(dp); + free(nm); + return; + } + } + if(!forwards_add_zone(fwd, LDNS_RR_CLASS_IN, dp)) { + (void)ssl_printf(ssl, "error out of memory\n"); + delegpt_free_mlc(dp); + free(nm); + return; + } + free(nm); + send_ok(ssl); +} + +/** do the forward_remove command */ +static void +do_forward_remove(SSL* ssl, struct worker* worker, char* args) +{ + struct iter_forwards* fwd = worker->env.fwds; + int insecure = 0; + uint8_t* nm = NULL; + if(!parse_fs_args(ssl, args, &nm, NULL, &insecure, NULL)) + return; + if(insecure) + anchors_delete_insecure(worker->env.anchors, LDNS_RR_CLASS_IN, + nm); + forwards_delete_zone(fwd, LDNS_RR_CLASS_IN, nm); + free(nm); + send_ok(ssl); +} + +/** do the stub_add command */ +static void +do_stub_add(SSL* ssl, struct worker* worker, char* args) +{ + struct iter_forwards* fwd = worker->env.fwds; + int insecure = 0, prime = 0; + uint8_t* nm = NULL; + struct delegpt* dp = NULL; + if(!parse_fs_args(ssl, args, &nm, &dp, &insecure, &prime)) + return; + if(insecure) { + if(!anchors_add_insecure(worker->env.anchors, LDNS_RR_CLASS_IN, + nm)) { + (void)ssl_printf(ssl, "error out of memory\n"); + delegpt_free_mlc(dp); + free(nm); + return; + } + } + if(!forwards_add_stub_hole(fwd, LDNS_RR_CLASS_IN, nm)) { + if(insecure) anchors_delete_insecure(worker->env.anchors, + LDNS_RR_CLASS_IN, nm); + (void)ssl_printf(ssl, "error out of memory\n"); + delegpt_free_mlc(dp); + free(nm); + return; + } + if(!hints_add_stub(worker->env.hints, LDNS_RR_CLASS_IN, dp, !prime)) { + (void)ssl_printf(ssl, "error out of memory\n"); + forwards_delete_stub_hole(fwd, LDNS_RR_CLASS_IN, nm); + if(insecure) anchors_delete_insecure(worker->env.anchors, + LDNS_RR_CLASS_IN, nm); + delegpt_free_mlc(dp); + free(nm); + return; + } + free(nm); + send_ok(ssl); +} + +/** do the stub_remove command */ +static void +do_stub_remove(SSL* ssl, struct worker* worker, char* args) +{ + struct iter_forwards* fwd = worker->env.fwds; + int insecure = 0; + uint8_t* nm = NULL; + if(!parse_fs_args(ssl, args, &nm, NULL, &insecure, NULL)) + return; + if(insecure) + anchors_delete_insecure(worker->env.anchors, LDNS_RR_CLASS_IN, + nm); + forwards_delete_stub_hole(fwd, LDNS_RR_CLASS_IN, nm); + hints_delete_stub(worker->env.hints, LDNS_RR_CLASS_IN, nm); + free(nm); + send_ok(ssl); +} + +/** do the status command */ +static void +do_status(SSL* ssl, struct worker* worker) +{ + int i; + time_t uptime; + if(!ssl_printf(ssl, "version: %s\n", PACKAGE_VERSION)) + return; + if(!ssl_printf(ssl, "verbosity: %d\n", verbosity)) + return; + if(!ssl_printf(ssl, "threads: %d\n", worker->daemon->num)) + return; + if(!ssl_printf(ssl, "modules: %d [", worker->daemon->mods.num)) + return; + for(i=0; idaemon->mods.num; i++) { + if(!ssl_printf(ssl, " %s", worker->daemon->mods.mod[i]->name)) + return; + } + if(!ssl_printf(ssl, " ]\n")) + return; + uptime = (time_t)time(NULL) - (time_t)worker->daemon->time_boot.tv_sec; + if(!ssl_printf(ssl, "uptime: %u seconds\n", (unsigned)uptime)) + return; + if(!ssl_printf(ssl, "unbound (pid %d) is running...\n", + (int)getpid())) + return; +} + +/** get age for the mesh state */ +static void +get_mesh_age(struct mesh_state* m, char* buf, size_t len, + struct module_env* env) +{ + if(m->reply_list) { + struct timeval d; + struct mesh_reply* r = m->reply_list; + /* last reply is the oldest */ + while(r && r->next) + r = r->next; + timeval_subtract(&d, env->now_tv, &r->start_time); + snprintf(buf, len, "%d.%6.6d", (int)d.tv_sec, (int)d.tv_usec); + } else { + snprintf(buf, len, "-"); + } +} + +/** get status of a mesh state */ +static void +get_mesh_status(struct mesh_area* mesh, struct mesh_state* m, + char* buf, size_t len) +{ + enum module_ext_state s = m->s.ext_state[m->s.curmod]; + const char *modname = mesh->mods.mod[m->s.curmod]->name; + size_t l; + if(strcmp(modname, "iterator") == 0 && s == module_wait_reply && + m->s.minfo[m->s.curmod]) { + /* break into iterator to find out who its waiting for */ + struct iter_qstate* qstate = (struct iter_qstate*) + m->s.minfo[m->s.curmod]; + struct outbound_list* ol = &qstate->outlist; + struct outbound_entry* e; + snprintf(buf, len, "%s wait for", modname); + l = strlen(buf); + buf += l; len -= l; + if(ol->first == NULL) + snprintf(buf, len, " (empty_list)"); + for(e = ol->first; e; e = e->next) { + snprintf(buf, len, " "); + l = strlen(buf); + buf += l; len -= l; + addr_to_str(&e->qsent->addr, e->qsent->addrlen, + buf, len); + l = strlen(buf); + buf += l; len -= l; + } + } else if(s == module_wait_subquery) { + /* look in subs from mesh state to see what */ + char nm[257]; + struct mesh_state_ref* sub; + snprintf(buf, len, "%s wants", modname); + l = strlen(buf); + buf += l; len -= l; + if(m->sub_set.count == 0) + snprintf(buf, len, " (empty_list)"); + RBTREE_FOR(sub, struct mesh_state_ref*, &m->sub_set) { + char* t = ldns_rr_type2str(sub->s->s.qinfo.qtype); + char* c = ldns_rr_class2str(sub->s->s.qinfo.qclass); + dname_str(sub->s->s.qinfo.qname, nm); + snprintf(buf, len, " %s %s %s", t, c, nm); + l = strlen(buf); + buf += l; len -= l; + free(t); + free(c); + } + } else { + snprintf(buf, len, "%s is %s", modname, strextstate(s)); + } +} + +/** do the dump_requestlist command */ +static void +do_dump_requestlist(SSL* ssl, struct worker* worker) +{ + struct mesh_area* mesh; + struct mesh_state* m; + int num = 0; + char buf[257]; + char timebuf[32]; + char statbuf[10240]; + if(!ssl_printf(ssl, "thread #%d\n", worker->thread_num)) + return; + if(!ssl_printf(ssl, "# type cl name seconds module status\n")) + return; + /* show worker mesh contents */ + mesh = worker->env.mesh; + if(!mesh) return; + RBTREE_FOR(m, struct mesh_state*, &mesh->all) { + char* t = ldns_rr_type2str(m->s.qinfo.qtype); + char* c = ldns_rr_class2str(m->s.qinfo.qclass); + dname_str(m->s.qinfo.qname, buf); + get_mesh_age(m, timebuf, sizeof(timebuf), &worker->env); + get_mesh_status(mesh, m, statbuf, sizeof(statbuf)); + if(!ssl_printf(ssl, "%3d %4s %2s %s %s %s\n", + num, t, c, buf, timebuf, statbuf)) { + free(t); + free(c); + return; + } + num++; + free(t); + free(c); + } +} + +/** structure for argument data for dump infra host */ +struct infra_arg { + /** the infra cache */ + struct infra_cache* infra; + /** the SSL connection */ + SSL* ssl; + /** the time now */ + uint32_t now; +}; + +/** callback for every host element in the infra cache */ +static void +dump_infra_host(struct lruhash_entry* e, void* arg) +{ + struct infra_arg* a = (struct infra_arg*)arg; + struct infra_key* k = (struct infra_key*)e->key; + struct infra_data* d = (struct infra_data*)e->data; + char ip_str[1024]; + char name[257]; + addr_to_str(&k->addr, k->addrlen, ip_str, sizeof(ip_str)); + dname_str(k->zonename, name); + /* skip expired stuff (only backed off) */ + if(d->ttl < a->now) { + if(d->rtt.rto >= USEFUL_SERVER_TOP_TIMEOUT) { + if(!ssl_printf(a->ssl, "%s %s expired rto %d\n", ip_str, + name, d->rtt.rto)) return; + } + return; + } + if(!ssl_printf(a->ssl, "%s %s ttl %d ping %d var %d rtt %d rto %d " + "tA %d tAAAA %d tother %d " + "ednsknown %d edns %d delay %d lame dnssec %d rec %d A %d " + "other %d\n", ip_str, name, (int)(d->ttl - a->now), + d->rtt.srtt, d->rtt.rttvar, rtt_notimeout(&d->rtt), d->rtt.rto, + d->timeout_A, d->timeout_AAAA, d->timeout_other, + (int)d->edns_lame_known, (int)d->edns_version, + (int)(a->nowprobedelay?d->probedelay-a->now:0), + (int)d->isdnsseclame, (int)d->rec_lame, (int)d->lame_type_A, + (int)d->lame_other)) + return; +} + +/** do the dump_infra command */ +static void +do_dump_infra(SSL* ssl, struct worker* worker) +{ + struct infra_arg arg; + arg.infra = worker->env.infra_cache; + arg.ssl = ssl; + arg.now = *worker->env.now; + slabhash_traverse(arg.infra->hosts, 0, &dump_infra_host, (void*)&arg); +} + +/** do the log_reopen command */ +static void +do_log_reopen(SSL* ssl, struct worker* worker) +{ + struct config_file* cfg = worker->env.cfg; + send_ok(ssl); + log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir); +} + +/** do the set_option command */ +static void +do_set_option(SSL* ssl, struct worker* worker, char* arg) +{ + char* arg2; + if(!find_arg2(ssl, arg, &arg2)) + return; + if(!config_set_option(worker->env.cfg, arg, arg2)) { + (void)ssl_printf(ssl, "error setting option\n"); + return; + } + send_ok(ssl); +} + +/* routine to printout option values over SSL */ +void remote_get_opt_ssl(char* line, void* arg) +{ + SSL* ssl = (SSL*)arg; + (void)ssl_printf(ssl, "%s\n", line); +} + +/** do the get_option command */ +static void +do_get_option(SSL* ssl, struct worker* worker, char* arg) +{ + int r; + r = config_get_option(worker->env.cfg, arg, remote_get_opt_ssl, ssl); + if(!r) { + (void)ssl_printf(ssl, "error unknown option\n"); + return; + } +} + +/** do the list_forwards command */ +static void +do_list_forwards(SSL* ssl, struct worker* worker) +{ + /* since its a per-worker structure no locks needed */ + struct iter_forwards* fwds = worker->env.fwds; + struct iter_forward_zone* z; + RBTREE_FOR(z, struct iter_forward_zone*, fwds->tree) { + if(!z->dp) continue; /* skip empty marker for stub */ + if(!ssl_print_name_dp(ssl, "forward", z->name, z->dclass, + z->dp)) + return; + } +} + +/** do the list_stubs command */ +static void +do_list_stubs(SSL* ssl, struct worker* worker) +{ + struct iter_hints_stub* z; + RBTREE_FOR(z, struct iter_hints_stub*, &worker->env.hints->tree) { + if(!ssl_print_name_dp(ssl, + z->noprime?"stub noprime":"stub prime", z->node.name, + z->node.dclass, z->dp)) + return; + } +} + +/** do the list_local_zones command */ +static void +do_list_local_zones(SSL* ssl, struct worker* worker) +{ + struct local_zones* zones = worker->daemon->local_zones; + struct local_zone* z; + char buf[257]; + lock_quick_lock(&zones->lock); + RBTREE_FOR(z, struct local_zone*, &zones->ztree) { + lock_rw_rdlock(&z->lock); + dname_str(z->name, buf); + (void)ssl_printf(ssl, "%s %s\n", buf, + local_zone_type2str(z->type)); + lock_rw_unlock(&z->lock); + } + lock_quick_unlock(&zones->lock); +} + +/** do the list_local_data command */ +static void +do_list_local_data(SSL* ssl, struct worker* worker) +{ + struct local_zones* zones = worker->daemon->local_zones; + struct local_zone* z; + struct local_data* d; + struct local_rrset* p; + lock_quick_lock(&zones->lock); + RBTREE_FOR(z, struct local_zone*, &zones->ztree) { + lock_rw_rdlock(&z->lock); + RBTREE_FOR(d, struct local_data*, &z->data) { + for(p = d->rrsets; p; p = p->next) { + ldns_rr_list* rr = packed_rrset_to_rr_list( + p->rrset, worker->env.scratch_buffer); + char* str = ldns_rr_list2str(rr); + (void)ssl_printf(ssl, "%s", str); + free(str); + ldns_rr_list_free(rr); + } + } + lock_rw_unlock(&z->lock); + } + lock_quick_unlock(&zones->lock); +} + +/** tell other processes to execute the command */ +static void +distribute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd) +{ + int i; + if(!cmd || !ssl) + return; + /* skip i=0 which is me */ + for(i=1; iworker->daemon->num; i++) { + worker_send_cmd(rc->worker->daemon->workers[i], + worker_cmd_remote); + if(!tube_write_msg(rc->worker->daemon->workers[i]->cmd, + (uint8_t*)cmd, strlen(cmd)+1, 0)) { + ssl_printf(ssl, "error could not distribute cmd\n"); + return; + } + } +} + +/** check for name with end-of-string, space or tab after it */ +static int +cmdcmp(char* p, const char* cmd, size_t len) +{ + return strncmp(p,cmd,len)==0 && (p[len]==0||p[len]==' '||p[len]=='\t'); +} + +/** execute a remote control command */ +static void +execute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd, + struct worker* worker) +{ + char* p = skipwhite(cmd); + /* compare command */ + if(cmdcmp(p, "stop", 4)) { + do_stop(ssl, rc); + return; + } else if(cmdcmp(p, "reload", 6)) { + do_reload(ssl, rc); + return; + } else if(cmdcmp(p, "stats_noreset", 13)) { + do_stats(ssl, rc, 0); + return; + } else if(cmdcmp(p, "stats", 5)) { + do_stats(ssl, rc, 1); + return; + } else if(cmdcmp(p, "status", 6)) { + do_status(ssl, worker); + return; + } else if(cmdcmp(p, "dump_cache", 10)) { + (void)dump_cache(ssl, worker); + return; + } else if(cmdcmp(p, "load_cache", 10)) { + if(load_cache(ssl, worker)) send_ok(ssl); + return; + } else if(cmdcmp(p, "list_forwards", 13)) { + do_list_forwards(ssl, worker); + return; + } else if(cmdcmp(p, "list_stubs", 10)) { + do_list_stubs(ssl, worker); + return; + } else if(cmdcmp(p, "list_local_zones", 16)) { + do_list_local_zones(ssl, worker); + return; + } else if(cmdcmp(p, "list_local_data", 15)) { + do_list_local_data(ssl, worker); + return; + } else if(cmdcmp(p, "stub_add", 8)) { + /* must always distribute this cmd */ + if(rc) distribute_cmd(rc, ssl, cmd); + do_stub_add(ssl, worker, skipwhite(p+8)); + return; + } else if(cmdcmp(p, "stub_remove", 11)) { + /* must always distribute this cmd */ + if(rc) distribute_cmd(rc, ssl, cmd); + do_stub_remove(ssl, worker, skipwhite(p+11)); + return; + } else if(cmdcmp(p, "forward_add", 11)) { + /* must always distribute this cmd */ + if(rc) distribute_cmd(rc, ssl, cmd); + do_forward_add(ssl, worker, skipwhite(p+11)); + return; + } else if(cmdcmp(p, "forward_remove", 14)) { + /* must always distribute this cmd */ + if(rc) distribute_cmd(rc, ssl, cmd); + do_forward_remove(ssl, worker, skipwhite(p+14)); + return; + } else if(cmdcmp(p, "forward", 7)) { + /* must always distribute this cmd */ + if(rc) distribute_cmd(rc, ssl, cmd); + do_forward(ssl, worker, skipwhite(p+7)); + return; + } else if(cmdcmp(p, "flush_stats", 11)) { + /* must always distribute this cmd */ + if(rc) distribute_cmd(rc, ssl, cmd); + do_flush_stats(ssl, worker); + return; + } else if(cmdcmp(p, "flush_requestlist", 17)) { + /* must always distribute this cmd */ + if(rc) distribute_cmd(rc, ssl, cmd); + do_flush_requestlist(ssl, worker); + return; + } else if(cmdcmp(p, "lookup", 6)) { + do_lookup(ssl, worker, skipwhite(p+6)); + return; + } + +#ifdef THREADS_DISABLED + /* other processes must execute the command as well */ + /* commands that should not be distributed, returned above. */ + if(rc) { /* only if this thread is the master (rc) thread */ + /* done before the code below, which may split the string */ + distribute_cmd(rc, ssl, cmd); + } +#endif + if(cmdcmp(p, "verbosity", 9)) { + do_verbosity(ssl, skipwhite(p+9)); + } else if(cmdcmp(p, "local_zone_remove", 17)) { + do_zone_remove(ssl, worker, skipwhite(p+17)); + } else if(cmdcmp(p, "local_zone", 10)) { + do_zone_add(ssl, worker, skipwhite(p+10)); + } else if(cmdcmp(p, "local_data_remove", 17)) { + do_data_remove(ssl, worker, skipwhite(p+17)); + } else if(cmdcmp(p, "local_data", 10)) { + do_data_add(ssl, worker, skipwhite(p+10)); + } else if(cmdcmp(p, "flush_zone", 10)) { + do_flush_zone(ssl, worker, skipwhite(p+10)); + } else if(cmdcmp(p, "flush_type", 10)) { + do_flush_type(ssl, worker, skipwhite(p+10)); + } else if(cmdcmp(p, "flush_infra", 11)) { + do_flush_infra(ssl, worker, skipwhite(p+11)); + } else if(cmdcmp(p, "flush", 5)) { + do_flush_name(ssl, worker, skipwhite(p+5)); + } else if(cmdcmp(p, "dump_requestlist", 16)) { + do_dump_requestlist(ssl, worker); + } else if(cmdcmp(p, "dump_infra", 10)) { + do_dump_infra(ssl, worker); + } else if(cmdcmp(p, "log_reopen", 10)) { + do_log_reopen(ssl, worker); + } else if(cmdcmp(p, "set_option", 10)) { + do_set_option(ssl, worker, skipwhite(p+10)); + } else if(cmdcmp(p, "get_option", 10)) { + do_get_option(ssl, worker, skipwhite(p+10)); + } else { + (void)ssl_printf(ssl, "error unknown command '%s'\n", p); + } +} + +void +daemon_remote_exec(struct worker* worker) +{ + /* read the cmd string */ + uint8_t* msg = NULL; + uint32_t len = 0; + if(!tube_read_msg(worker->cmd, &msg, &len, 0)) { + log_err("daemon_remote_exec: tube_read_msg failed"); + return; + } + verbose(VERB_ALGO, "remote exec distributed: %s", (char*)msg); + execute_cmd(NULL, NULL, (char*)msg, worker); + free(msg); +} + +/** handle remote control request */ +static void +handle_req(struct daemon_remote* rc, struct rc_state* s, SSL* ssl) +{ + int r; + char pre[10]; + char magic[7]; + char buf[1024]; +#ifdef USE_WINSOCK + /* makes it possible to set the socket blocking again. */ + /* basically removes it from winsock_event ... */ + WSAEventSelect(s->c->fd, NULL, 0); +#endif + fd_set_block(s->c->fd); + + /* try to read magic UBCT[version]_space_ string */ + ERR_clear_error(); + if((r=SSL_read(ssl, magic, (int)sizeof(magic)-1)) <= 0) { + if(SSL_get_error(ssl, r) == SSL_ERROR_ZERO_RETURN) + return; + log_crypto_err("could not SSL_read"); + return; + } + magic[6] = 0; + if( r != 6 || strncmp(magic, "UBCT", 4) != 0) { + verbose(VERB_QUERY, "control connection has bad magic string"); + /* probably wrong tool connected, ignore it completely */ + return; + } + + /* read the command line */ + if(!ssl_read_line(ssl, buf, sizeof(buf))) { + return; + } + snprintf(pre, sizeof(pre), "UBCT%d ", UNBOUND_CONTROL_VERSION); + if(strcmp(magic, pre) != 0) { + verbose(VERB_QUERY, "control connection had bad " + "version %s, cmd: %s", magic, buf); + ssl_printf(ssl, "error version mismatch\n"); + return; + } + verbose(VERB_DETAIL, "control cmd: %s", buf); + + /* figure out what to do */ + execute_cmd(rc, ssl, buf, rc->worker); +} + +int remote_control_callback(struct comm_point* c, void* arg, int err, + struct comm_reply* ATTR_UNUSED(rep)) +{ + struct rc_state* s = (struct rc_state*)arg; + struct daemon_remote* rc = s->rc; + int r; + if(err != NETEVENT_NOERROR) { + if(err==NETEVENT_TIMEOUT) + log_err("remote control timed out"); + clean_point(rc, s); + return 0; + } + /* (continue to) setup the SSL connection */ + ERR_clear_error(); + r = SSL_do_handshake(s->ssl); + if(r != 1) { + int r2 = SSL_get_error(s->ssl, r); + if(r2 == SSL_ERROR_WANT_READ) { + if(s->shake_state == rc_hs_read) { + /* try again later */ + return 0; + } + s->shake_state = rc_hs_read; + comm_point_listen_for_rw(c, 1, 0); + return 0; + } else if(r2 == SSL_ERROR_WANT_WRITE) { + if(s->shake_state == rc_hs_write) { + /* try again later */ + return 0; + } + s->shake_state = rc_hs_write; + comm_point_listen_for_rw(c, 0, 1); + return 0; + } else { + if(r == 0) + log_err("remote control connection closed prematurely"); + log_addr(1, "failed connection from", + &s->c->repinfo.addr, s->c->repinfo.addrlen); + log_crypto_err("remote control failed ssl"); + clean_point(rc, s); + return 0; + } + } + s->shake_state = rc_none; + + /* once handshake has completed, check authentication */ + if(SSL_get_verify_result(s->ssl) == X509_V_OK) { + X509* x = SSL_get_peer_certificate(s->ssl); + if(!x) { + verbose(VERB_DETAIL, "remote control connection " + "provided no client certificate"); + clean_point(rc, s); + return 0; + } + verbose(VERB_ALGO, "remote control connection authenticated"); + X509_free(x); + } else { + verbose(VERB_DETAIL, "remote control connection failed to " + "authenticate with client certificate"); + clean_point(rc, s); + return 0; + } + + /* if OK start to actually handle the request */ + handle_req(rc, s, s->ssl); + + verbose(VERB_ALGO, "remote control operation completed"); + clean_point(rc, s); + return 0; +} diff --git a/daemon/remote.h b/daemon/remote.h new file mode 100644 index 00000000000..5919be4f2a3 --- /dev/null +++ b/daemon/remote.h @@ -0,0 +1,192 @@ +/* + * daemon/remote.h - remote control for the unbound daemon. + * + * Copyright (c) 2008, 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains the remote control functionality for the daemon. + * The remote control can be performed using either the commandline + * unbound-control tool, or a SSLv3/TLS capable web browser. + * The channel is secured using SSLv3 or TLSv1, and certificates. + * Both the server and the client(control tool) have their own keys. + */ + +#ifndef DAEMON_REMOTE_H +#define DAEMON_REMOTE_H +#ifdef HAVE_OPENSSL_SSL_H +#include "openssl/ssl.h" +#endif +struct config_file; +struct listen_list; +struct listen_port; +struct worker; +struct comm_reply; +struct comm_point; +struct daemon_remote; + +/** number of seconds timeout on incoming remote control handshake */ +#define REMOTE_CONTROL_TCP_TIMEOUT 120 + +/** + * a busy control command connection, SSL state + */ +struct rc_state { + /** the next item in list */ + struct rc_state* next; + /** the commpoint */ + struct comm_point* c; + /** in the handshake part */ + enum { rc_none, rc_hs_read, rc_hs_write } shake_state; + /** the ssl state */ + SSL* ssl; + /** the rc this is part of */ + struct daemon_remote* rc; +}; + +/** + * The remote control tool state. + * The state is only created for the first thread, other threads + * are called from this thread. Only the first threads listens to + * the control port. The other threads do not, but are called on the + * command channel(pipe) from the first thread. + */ +struct daemon_remote { + /** the worker for this remote control */ + struct worker* worker; + /** commpoints for accepting remote control connections */ + struct listen_list* accept_list; + /** number of active commpoints that are handling remote control */ + int active; + /** max active commpoints */ + int max_active; + /** current commpoints busy; should be a short list, malloced */ + struct rc_state* busy_list; + /** the SSL context for creating new SSL streams */ + SSL_CTX* ctx; +}; + +/** + * Create new remote control state for the daemon. + * @param cfg: config file with key file settings. + * @return new state, or NULL on failure. + */ +struct daemon_remote* daemon_remote_create(struct config_file* cfg); + +/** + * remote control state to delete. + * @param rc: state to delete. + */ +void daemon_remote_delete(struct daemon_remote* rc); + +/** + * remote control state to clear up. Busy and accept points are closed. + * Does not delete the rc itself, or the ssl context (with its keys). + * @param rc: state to clear. + */ +void daemon_remote_clear(struct daemon_remote* rc); + +/** + * Open and create listening ports for remote control. + * @param cfg: config options. + * @return list of ports or NULL on failure. + * can be freed with listening_ports_free(). + */ +struct listen_port* daemon_remote_open_ports(struct config_file* cfg); + +/** + * Setup comm points for accepting remote control connections. + * @param rc: state + * @param ports: already opened ports. + * @param worker: worker with communication base. and links to command channels. + * @return false on error. + */ +int daemon_remote_open_accept(struct daemon_remote* rc, + struct listen_port* ports, struct worker* worker); + +/** + * Stop accept handlers for TCP (until enabled again) + * @param rc: state + */ +void daemon_remote_stop_accept(struct daemon_remote* rc); + +/** + * Stop accept handlers for TCP (until enabled again) + * @param rc: state + */ +void daemon_remote_start_accept(struct daemon_remote* rc); + +/** + * Handle nonthreaded remote cmd execution. + * @param worker: this worker (the remote worker). + */ +void daemon_remote_exec(struct worker* worker); + +/** handle remote control accept callbacks */ +int remote_accept_callback(struct comm_point*, void*, int, struct comm_reply*); + +/** handle remote control data callbacks */ +int remote_control_callback(struct comm_point*, void*, int, struct comm_reply*); + +/** + * Print fixed line of text over ssl connection in blocking mode + * @param ssl: print to + * @param text: the text. + * @return false on connection failure. + */ +int ssl_print_text(SSL* ssl, const char* text); + +/** + * printf style printing to the ssl connection + * @param ssl: the SSL connection to print to. Blocking. + * @param format: printf style format string. + * @return success or false on a network failure. + */ +int ssl_printf(SSL* ssl, const char* format, ...) + ATTR_FORMAT(printf, 2, 3); + +/** + * Read until \n is encountered + * If SSL signals EOF, the string up to then is returned (without \n). + * @param ssl: the SSL connection to read from. blocking. + * @param buf: buffer to read to. + * @param max: size of buffer. + * @return false on connection failure. + */ +int ssl_read_line(SSL* ssl, char* buf, size_t max); + +/** routine to printout option values over SSL */ +void remote_get_opt_ssl(char* line, void* arg); + +#endif /* DAEMON_REMOTE_H */ diff --git a/daemon/stats.c b/daemon/stats.c new file mode 100644 index 00000000000..9a1a7d2617e --- /dev/null +++ b/daemon/stats.c @@ -0,0 +1,303 @@ +/* + * daemon/stats.c - collect runtime performance indicators. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file describes the data structure used to collect runtime performance + * numbers. These 'statistics' may be of interest to the operator. + */ +#include "config.h" +#include +#include "daemon/stats.h" +#include "daemon/worker.h" +#include "daemon/daemon.h" +#include "services/mesh.h" +#include "services/outside_network.h" +#include "util/config_file.h" +#include "util/tube.h" +#include "util/timehist.h" +#include "util/net_help.h" +#include "validator/validator.h" + +/** add timers and the values do not overflow or become negative */ +static void +timeval_add(struct timeval* d, const struct timeval* add) +{ +#ifndef S_SPLINT_S + d->tv_sec += add->tv_sec; + d->tv_usec += add->tv_usec; + if(d->tv_usec > 1000000) { + d->tv_usec -= 1000000; + d->tv_sec++; + } +#endif +} + +void server_stats_init(struct server_stats* stats, struct config_file* cfg) +{ + memset(stats, 0, sizeof(*stats)); + stats->extended = cfg->stat_extended; +} + +void server_stats_querymiss(struct server_stats* stats, struct worker* worker) +{ + stats->num_queries_missed_cache++; + stats->sum_query_list_size += worker->env.mesh->all.count; + if(worker->env.mesh->all.count > stats->max_query_list_size) + stats->max_query_list_size = worker->env.mesh->all.count; +} + +void server_stats_prefetch(struct server_stats* stats, struct worker* worker) +{ + stats->num_queries_prefetch++; + /* changes the query list size so account that, like a querymiss */ + stats->sum_query_list_size += worker->env.mesh->all.count; + if(worker->env.mesh->all.count > stats->max_query_list_size) + stats->max_query_list_size = worker->env.mesh->all.count; +} + +void server_stats_log(struct server_stats* stats, struct worker* worker, + int threadnum) +{ + log_info("server stats for thread %d: %u queries, " + "%u answers from cache, %u recursions, %u prefetch", + threadnum, (unsigned)stats->num_queries, + (unsigned)(stats->num_queries - + stats->num_queries_missed_cache), + (unsigned)stats->num_queries_missed_cache, + (unsigned)stats->num_queries_prefetch); + log_info("server stats for thread %d: requestlist max %u avg %g " + "exceeded %u jostled %u", threadnum, + (unsigned)stats->max_query_list_size, + (stats->num_queries_missed_cache+stats->num_queries_prefetch)? + (double)stats->sum_query_list_size/ + (stats->num_queries_missed_cache+ + stats->num_queries_prefetch) : 0.0, + (unsigned)worker->env.mesh->stats_dropped, + (unsigned)worker->env.mesh->stats_jostled); +} + +/** get rrsets bogus number from validator */ +static size_t +get_rrset_bogus(struct worker* worker) +{ + int m = modstack_find(&worker->env.mesh->mods, "validator"); + struct val_env* ve; + size_t r; + if(m == -1) + return 0; + ve = (struct val_env*)worker->env.modinfo[m]; + lock_basic_lock(&ve->bogus_lock); + r = ve->num_rrset_bogus; + if(!worker->env.cfg->stat_cumulative) + ve->num_rrset_bogus = 0; + lock_basic_unlock(&ve->bogus_lock); + return r; +} + +void +server_stats_compile(struct worker* worker, struct stats_info* s, int reset) +{ + int i; + + s->svr = worker->stats; + s->mesh_num_states = worker->env.mesh->all.count; + s->mesh_num_reply_states = worker->env.mesh->num_reply_states; + s->mesh_jostled = worker->env.mesh->stats_jostled; + s->mesh_dropped = worker->env.mesh->stats_dropped; + s->mesh_replies_sent = worker->env.mesh->replies_sent; + s->mesh_replies_sum_wait = worker->env.mesh->replies_sum_wait; + s->mesh_time_median = timehist_quartile(worker->env.mesh->histogram, + 0.50); + + /* add in the values from the mesh */ + s->svr.ans_secure += worker->env.mesh->ans_secure; + s->svr.ans_bogus += worker->env.mesh->ans_bogus; + s->svr.ans_rcode_nodata += worker->env.mesh->ans_nodata; + for(i=0; i<16; i++) + s->svr.ans_rcode[i] += worker->env.mesh->ans_rcode[i]; + timehist_export(worker->env.mesh->histogram, s->svr.hist, + NUM_BUCKETS_HIST); + /* values from outside network */ + s->svr.unwanted_replies = worker->back->unwanted_replies; + + /* get and reset validator rrset bogus number */ + s->svr.rrset_bogus = get_rrset_bogus(worker); + + if(reset && !worker->env.cfg->stat_cumulative) { + worker_stats_clear(worker); + } +} + +void server_stats_obtain(struct worker* worker, struct worker* who, + struct stats_info* s, int reset) +{ + uint8_t *reply = NULL; + uint32_t len = 0; + if(worker == who) { + /* just fill it in */ + server_stats_compile(worker, s, reset); + return; + } + /* communicate over tube */ + verbose(VERB_ALGO, "write stats cmd"); + if(reset) + worker_send_cmd(who, worker_cmd_stats); + else worker_send_cmd(who, worker_cmd_stats_noreset); + verbose(VERB_ALGO, "wait for stats reply"); + if(!tube_read_msg(worker->cmd, &reply, &len, 0)) + fatal_exit("failed to read stats over cmd channel"); + if(len != (uint32_t)sizeof(*s)) + fatal_exit("stats on cmd channel wrong length %d %d", + (int)len, (int)sizeof(*s)); + memcpy(s, reply, (size_t)len); + free(reply); +} + +void server_stats_reply(struct worker* worker, int reset) +{ + struct stats_info s; + server_stats_compile(worker, &s, reset); + verbose(VERB_ALGO, "write stats replymsg"); + if(!tube_write_msg(worker->daemon->workers[0]->cmd, + (uint8_t*)&s, sizeof(s), 0)) + fatal_exit("could not write stat values over cmd channel"); +} + +void server_stats_add(struct stats_info* total, struct stats_info* a) +{ + total->svr.num_queries += a->svr.num_queries; + total->svr.num_queries_missed_cache += a->svr.num_queries_missed_cache; + total->svr.num_queries_prefetch += a->svr.num_queries_prefetch; + total->svr.sum_query_list_size += a->svr.sum_query_list_size; + /* the max size reached is upped to higher of both */ + if(a->svr.max_query_list_size > total->svr.max_query_list_size) + total->svr.max_query_list_size = a->svr.max_query_list_size; + + if(a->svr.extended) { + int i; + total->svr.qtype_big += a->svr.qtype_big; + total->svr.qclass_big += a->svr.qclass_big; + total->svr.qtcp += a->svr.qtcp; + total->svr.qipv6 += a->svr.qipv6; + total->svr.qbit_QR += a->svr.qbit_QR; + total->svr.qbit_AA += a->svr.qbit_AA; + total->svr.qbit_TC += a->svr.qbit_TC; + total->svr.qbit_RD += a->svr.qbit_RD; + total->svr.qbit_RA += a->svr.qbit_RA; + total->svr.qbit_Z += a->svr.qbit_Z; + total->svr.qbit_AD += a->svr.qbit_AD; + total->svr.qbit_CD += a->svr.qbit_CD; + total->svr.qEDNS += a->svr.qEDNS; + total->svr.qEDNS_DO += a->svr.qEDNS_DO; + total->svr.ans_rcode_nodata += a->svr.ans_rcode_nodata; + total->svr.ans_secure += a->svr.ans_secure; + total->svr.ans_bogus += a->svr.ans_bogus; + total->svr.rrset_bogus += a->svr.rrset_bogus; + total->svr.unwanted_replies += a->svr.unwanted_replies; + total->svr.unwanted_queries += a->svr.unwanted_queries; + for(i=0; isvr.qtype[i] += a->svr.qtype[i]; + for(i=0; isvr.qclass[i] += a->svr.qclass[i]; + for(i=0; isvr.qopcode[i] += a->svr.qopcode[i]; + for(i=0; isvr.ans_rcode[i] += a->svr.ans_rcode[i]; + for(i=0; isvr.hist[i] += a->svr.hist[i]; + } + + total->mesh_num_states += a->mesh_num_states; + total->mesh_num_reply_states += a->mesh_num_reply_states; + total->mesh_jostled += a->mesh_jostled; + total->mesh_dropped += a->mesh_dropped; + total->mesh_replies_sent += a->mesh_replies_sent; + timeval_add(&total->mesh_replies_sum_wait, &a->mesh_replies_sum_wait); + /* the medians are averaged together, this is not as accurate as + * taking the median over all of the data, but is good and fast + * added up here, division later*/ + total->mesh_time_median += a->mesh_time_median; +} + +void server_stats_insquery(struct server_stats* stats, struct comm_point* c, + uint16_t qtype, uint16_t qclass, struct edns_data* edns, + struct comm_reply* repinfo) +{ + uint16_t flags = ldns_buffer_read_u16_at(c->buffer, 2); + if(qtype < STATS_QTYPE_NUM) + stats->qtype[qtype]++; + else stats->qtype_big++; + if(qclass < STATS_QCLASS_NUM) + stats->qclass[qclass]++; + else stats->qclass_big++; + stats->qopcode[ LDNS_OPCODE_WIRE(ldns_buffer_begin(c->buffer)) ]++; + if(c->type != comm_udp) + stats->qtcp++; + if(repinfo && addr_is_ip6(&repinfo->addr, repinfo->addrlen)) + stats->qipv6++; + if( (flags&BIT_QR) ) + stats->qbit_QR++; + if( (flags&BIT_AA) ) + stats->qbit_AA++; + if( (flags&BIT_TC) ) + stats->qbit_TC++; + if( (flags&BIT_RD) ) + stats->qbit_RD++; + if( (flags&BIT_RA) ) + stats->qbit_RA++; + if( (flags&BIT_Z) ) + stats->qbit_Z++; + if( (flags&BIT_AD) ) + stats->qbit_AD++; + if( (flags&BIT_CD) ) + stats->qbit_CD++; + if(edns->edns_present) { + stats->qEDNS++; + if( (edns->bits & EDNS_DO) ) + stats->qEDNS_DO++; + } +} + +void server_stats_insrcode(struct server_stats* stats, ldns_buffer* buf) +{ + if(stats->extended && ldns_buffer_limit(buf) != 0) { + int r = (int)LDNS_RCODE_WIRE( ldns_buffer_begin(buf) ); + stats->ans_rcode[r] ++; + if(r == 0 && LDNS_ANCOUNT( ldns_buffer_begin(buf) ) == 0) + stats->ans_rcode_nodata ++; + } +} diff --git a/daemon/stats.h b/daemon/stats.h new file mode 100644 index 00000000000..c0fc1cc1544 --- /dev/null +++ b/daemon/stats.h @@ -0,0 +1,235 @@ +/* + * daemon/stats.h - collect runtime performance indicators. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file describes the data structure used to collect runtime performance + * numbers. These 'statistics' may be of interest to the operator. + */ + +#ifndef DAEMON_STATS_H +#define DAEMON_STATS_H +#include "util/timehist.h" +#include +struct worker; +struct config_file; +struct comm_point; +struct comm_reply; +struct edns_data; + +/** number of qtype that is stored for in array */ +#define STATS_QTYPE_NUM 256 +/** number of qclass that is stored for in array */ +#define STATS_QCLASS_NUM 256 +/** number of rcodes in stats */ +#define STATS_RCODE_NUM 16 +/** number of opcodes in stats */ +#define STATS_OPCODE_NUM 16 + +/** per worker statistics */ +struct server_stats { + /** number of queries from clients received. */ + size_t num_queries; + /** number of queries that had a cache-miss. */ + size_t num_queries_missed_cache; + /** number of prefetch queries - cachehits with prefetch */ + size_t num_queries_prefetch; + + /** + * Sum of the querylistsize of the worker for + * every query that missed cache. To calculate average. + */ + size_t sum_query_list_size; + /** max value of query list size reached. */ + size_t max_query_list_size; + + /** Extended stats below (bool) */ + int extended; + + /** qtype stats */ + size_t qtype[STATS_QTYPE_NUM]; + /** bigger qtype values not in array */ + size_t qtype_big; + /** qclass stats */ + size_t qclass[STATS_QCLASS_NUM]; + /** bigger qclass values not in array */ + size_t qclass_big; + /** query opcodes */ + size_t qopcode[STATS_OPCODE_NUM]; + /** number of queries over TCP */ + size_t qtcp; + /** number of queries over IPv6 */ + size_t qipv6; + /** number of queries with QR bit */ + size_t qbit_QR; + /** number of queries with AA bit */ + size_t qbit_AA; + /** number of queries with TC bit */ + size_t qbit_TC; + /** number of queries with RD bit */ + size_t qbit_RD; + /** number of queries with RA bit */ + size_t qbit_RA; + /** number of queries with Z bit */ + size_t qbit_Z; + /** number of queries with AD bit */ + size_t qbit_AD; + /** number of queries with CD bit */ + size_t qbit_CD; + /** number of queries with EDNS OPT record */ + size_t qEDNS; + /** number of queries with EDNS with DO flag */ + size_t qEDNS_DO; + /** answer rcodes */ + size_t ans_rcode[STATS_RCODE_NUM]; + /** answers with pseudo rcode 'nodata' */ + size_t ans_rcode_nodata; + /** answers that were secure (AD) */ + size_t ans_secure; + /** answers that were bogus (withheld as SERVFAIL) */ + size_t ans_bogus; + /** rrsets marked bogus by validator */ + size_t rrset_bogus; + /** unwanted traffic received on server-facing ports */ + size_t unwanted_replies; + /** unwanted traffic received on client-facing ports */ + size_t unwanted_queries; + + /** histogram data exported to array + * if the array is the same size, no data is lost, and + * if all histograms are same size (is so by default) then + * adding up works well. */ + size_t hist[NUM_BUCKETS_HIST]; +}; + +/** + * Statistics to send over the control pipe when asked + * This struct is made to be memcpied, sent in binary. + */ +struct stats_info { + /** the thread stats */ + struct server_stats svr; + + /** mesh stats: current number of states */ + size_t mesh_num_states; + /** mesh stats: current number of reply (user) states */ + size_t mesh_num_reply_states; + /** mesh stats: number of reply states overwritten with a new one */ + size_t mesh_jostled; + /** mesh stats: number of incoming queries dropped */ + size_t mesh_dropped; + /** mesh stats: replies sent */ + size_t mesh_replies_sent; + /** mesh stats: sum of waiting times for the replies */ + struct timeval mesh_replies_sum_wait; + /** mesh stats: median of waiting times for replies (in sec) */ + double mesh_time_median; +}; + +/** + * Initialize server stats to 0. + * @param stats: what to init (this is alloced by the caller). + * @param cfg: with extended statistics option. + */ +void server_stats_init(struct server_stats* stats, struct config_file* cfg); + +/** add query if it missed the cache */ +void server_stats_querymiss(struct server_stats* stats, struct worker* worker); + +/** add query if was cached and also resulted in a prefetch */ +void server_stats_prefetch(struct server_stats* stats, struct worker* worker); + +/** display the stats to the log */ +void server_stats_log(struct server_stats* stats, struct worker* worker, + int threadnum); + +/** + * Obtain the stats info for a given thread. Uses pipe to communicate. + * @param worker: the worker that is executing (the first worker). + * @param who: on who to get the statistics info. + * @param s: the stats block to fill in. + * @param reset: if stats can be reset. + */ +void server_stats_obtain(struct worker* worker, struct worker* who, + struct stats_info* s, int reset); + +/** + * Compile stats into structure for this thread worker. + * Also clears the statistics counters (if that is set by config file). + * @param worker: the worker to compile stats for, also the executing worker. + * @param s: stats block. + * @param reset: if true, depending on config stats are reset. + * if false, statistics are not reset. + */ +void server_stats_compile(struct worker* worker, struct stats_info* s, + int reset); + +/** + * Send stats over comm tube in reply to query cmd + * @param worker: this worker. + * @param reset: if true, depending on config stats are reset. + * if false, statistics are not reset. + */ +void server_stats_reply(struct worker* worker, int reset); + +/** + * Addup stat blocks. + * @param total: sum of the two entries. + * @param a: to add to it. + */ +void server_stats_add(struct stats_info* total, struct stats_info* a); + +/** + * Add stats for this query + * @param stats: the stats + * @param c: commpoint with type and buffer. + * @param qtype: query type + * @param qclass: query class + * @param edns: edns record + * @param repinfo: reply info with remote address + */ +void server_stats_insquery(struct server_stats* stats, struct comm_point* c, + uint16_t qtype, uint16_t qclass, struct edns_data* edns, + struct comm_reply* repinfo); + +/** + * Add rcode for this query. + * @param stats: the stats + * @param buf: buffer with rcode. If buffer is length0: not counted. + */ +void server_stats_insrcode(struct server_stats* stats, ldns_buffer* buf); + +#endif /* DAEMON_STATS_H */ diff --git a/daemon/unbound.c b/daemon/unbound.c new file mode 100644 index 00000000000..6d87a4f6d5c --- /dev/null +++ b/daemon/unbound.c @@ -0,0 +1,748 @@ +/* + * daemon/unbound.c - main program for unbound DNS resolver daemon. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * \file + * + * Main program to start the DNS resolver daemon. + */ + +#include "config.h" +#ifdef HAVE_GETOPT_H +#include +#endif +#include +#include "util/log.h" +#include "daemon/daemon.h" +#include "daemon/remote.h" +#include "util/config_file.h" +#include "util/storage/slabhash.h" +#include "services/listen_dnsport.h" +#include "services/cache/rrset.h" +#include "services/cache/infra.h" +#include "util/data/msgreply.h" +#include "util/module.h" +#include "util/net_help.h" +#include +#include +#include +#ifdef HAVE_PWD_H +#include +#endif +#ifdef HAVE_GRP_H +#include +#endif + +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif +#ifdef HAVE_LOGIN_CAP_H +#include +#endif + +#ifdef USE_MINI_EVENT +# ifdef USE_WINSOCK +# include "util/winsock_event.h" +# else +# include "util/mini_event.h" +# endif +#else +# include +#endif + +#ifdef UB_ON_WINDOWS +# include "winrc/win_svc.h" +#endif + +/** global debug value to keep track of heap memory allocation */ +void* unbound_start_brk = 0; + +#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() +{ + const char** m; + const char *evnm="event", *evsys="", *evmethod=""; + printf("usage: unbound [options]\n"); + printf(" start unbound daemon DNS resolver.\n"); + printf("-h this help\n"); + printf("-c file config file to read instead of %s\n", CONFIGFILE); + printf(" file format is described in unbound.conf(5).\n"); + printf("-d do not fork into the background.\n"); + printf("-v verbose (more times to increase verbosity)\n"); +#ifdef UB_ON_WINDOWS + printf("-w opt windows option: \n"); + printf(" install, remove - manage the services entry\n"); + printf(" service - used to start from services control panel\n"); +#endif + printf("Version %s\n", PACKAGE_VERSION); + get_event_sys(&evnm, &evsys, &evmethod); + printf("linked libs: %s %s (it uses %s), ldns %s, %s\n", + evnm, evsys, evmethod, ldns_version(), + SSLeay_version(SSLEAY_VERSION)); + printf("linked modules:"); + for(m = module_list_avail(); *m; m++) + printf(" %s", *m); + printf("\n"); + printf("configured for %s on %s with options:%s\n", + CONFIGURE_TARGET, CONFIGURE_DATE, CONFIGURE_BUILD_WITH); + printf("BSD licensed, see LICENSE in source package for details.\n"); + printf("Report bugs to %s\n", PACKAGE_BUGREPORT); +} + +#ifndef unbound_testbound +int replay_var_compare(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b)) +{ + log_assert(0); + return 0; +} +#endif + +/** check file descriptor count */ +static void +checkrlimits(struct config_file* cfg) +{ +#ifdef HAVE_GETRLIMIT + /* list has number of ports to listen to, ifs number addresses */ + int list = ((cfg->do_udp?1:0) + (cfg->do_tcp?1 + + (int)cfg->incoming_num_tcp:0)); + size_t listen_ifs = (size_t)(cfg->num_ifs==0? + ((cfg->do_ip4 && !cfg->if_automatic?1:0) + + (cfg->do_ip6?1:0)):cfg->num_ifs); + size_t listen_num = list*listen_ifs; + size_t outudpnum = (size_t)cfg->outgoing_num_ports; + size_t outtcpnum = cfg->outgoing_num_tcp; + size_t misc = 4; /* logfile, pidfile, stdout... */ + size_t perthread_noudp = listen_num + outtcpnum + + 2/*cmdpipe*/ + 2/*libevent*/ + misc; + size_t perthread = perthread_noudp + outudpnum; + +#if !defined(HAVE_PTHREAD) && !defined(HAVE_SOLARIS_THREADS) + int numthread = 1; /* it forks */ +#else + int numthread = (cfg->num_threads?cfg->num_threads:1); +#endif + size_t total = numthread * perthread + misc; + size_t avail; + struct rlimit rlim; + + if(total > 1024 && + strncmp(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"); + if(numthread*perthread_noudp+15 > 1024) + fatal_exit("too much tcp. not enough fds."); + cfg->outgoing_num_ports = (int)((1024 + - numthread*perthread_noudp + - 10 /* safety margin */) /numthread); + log_warn("continuing with less udp ports: %u", + cfg->outgoing_num_ports); + total = 1024; + } + if(perthread > 64 && + strncmp(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"); + if(perthread_noudp+2 > 64) + fatal_exit("too much tcp. not enough fds."); + cfg->outgoing_num_ports = (int)((64 + - perthread_noudp + - 2/* safety margin */)); + log_warn("continuing with less udp ports: %u", + cfg->outgoing_num_ports); + total = numthread*(perthread_noudp+ + (size_t)cfg->outgoing_num_ports)+misc; + } + if(getrlimit(RLIMIT_NOFILE, &rlim) < 0) { + log_warn("getrlimit: %s", strerror(errno)); + return; + } + if(rlim.rlim_cur == (rlim_t)RLIM_INFINITY) + return; + if((size_t)rlim.rlim_cur < total) { + avail = (size_t)rlim.rlim_cur; + rlim.rlim_cur = (rlim_t)(total + 10); + rlim.rlim_max = (rlim_t)(total + 10); +#ifdef HAVE_SETRLIMIT + if(setrlimit(RLIMIT_NOFILE, &rlim) < 0) { + log_warn("setrlimit: %s", strerror(errno)); +#else + if(1) { +#endif + log_warn("cannot increase max open fds from %u to %u", + (unsigned)avail, (unsigned)total+10); + /* check that calculation below does not underflow, + * with 15 as margin */ + if(numthread*perthread_noudp+15 > avail) + fatal_exit("too much tcp. not enough fds."); + cfg->outgoing_num_ports = (int)((avail + - numthread*perthread_noudp + - 10 /* safety margin */) /numthread); + log_warn("continuing with less udp ports: %u", + cfg->outgoing_num_ports); + log_warn("increase ulimit or decrease threads, " + "ports in config to remove this warning"); + return; + } + log_warn("increased limit(open files) from %u to %u", + (unsigned)avail, (unsigned)total+10); + } +#else + (void)cfg; +#endif /* HAVE_GETRLIMIT */ +} + +/** set verbosity, check rlimits, cache settings */ +static void +apply_settings(struct daemon* daemon, struct config_file* cfg, + int cmdline_verbose) +{ + /* apply if they have changed */ + verbosity = cmdline_verbose + cfg->verbosity; + daemon_apply_cfg(daemon, cfg); + checkrlimits(cfg); +} + +#ifdef HAVE_KILL +/** Read existing pid from pidfile. + * @param file: file name of pid file. + * @return: the pid from the file or -1 if none. + */ +static pid_t +readpid (const char* file) +{ + int fd; + pid_t pid; + char pidbuf[32]; + char* t; + ssize_t l; + + if ((fd = open(file, O_RDONLY)) == -1) { + if(errno != ENOENT) + log_err("Could not read pidfile %s: %s", + file, strerror(errno)); + return -1; + } + + if (((l = read(fd, pidbuf, sizeof(pidbuf)))) == -1) { + if(errno != ENOENT) + log_err("Could not read pidfile %s: %s", + file, strerror(errno)); + close(fd); + return -1; + } + + close(fd); + + /* Empty pidfile means no pidfile... */ + if (l == 0) { + return -1; + } + + pidbuf[sizeof(pidbuf)-1] = 0; + pid = (pid_t)strtol(pidbuf, &t, 10); + + if (*t && *t != '\n') { + return -1; + } + return pid; +} + +/** write pid to file. + * @param pidfile: file name of pid file. + * @param pid: pid to write to file. + */ +static void +writepid (const char* pidfile, pid_t pid) +{ + FILE* f; + + if ((f = fopen(pidfile, "w")) == NULL ) { + log_err("cannot open pidfile %s: %s", + pidfile, strerror(errno)); + return; + } + if(fprintf(f, "%lu\n", (unsigned long)pid) < 0) { + log_err("cannot write to pidfile %s: %s", + pidfile, strerror(errno)); + } + fclose(f); +} + +/** + * check old pid file. + * @param pidfile: the file name of the pid file. + * @param inchroot: if pidfile is inchroot and we can thus expect to + * be able to delete it. + */ +static void +checkoldpid(char* pidfile, int inchroot) +{ + pid_t old; + if((old = readpid(pidfile)) != -1) { + /* see if it is still alive */ + if(kill(old, 0) == 0 || errno == EPERM) + log_warn("unbound is already running as pid %u.", + (unsigned)old); + else if(inchroot) + log_warn("did not exit gracefully last time (%u)", + (unsigned)old); + } +} +#endif /* HAVE_KILL */ + +/** detach from command line */ +static void +detach(void) +{ +#if defined(HAVE_DAEMON) && !defined(DEPRECATED_DAEMON) + /* use POSIX daemon(3) function */ + if(daemon(1, 0) != 0) + fatal_exit("daemon failed: %s", strerror(errno)); +#else /* no HAVE_DAEMON */ +#ifdef HAVE_FORK + int fd; + /* Take off... */ + switch (fork()) { + case 0: + break; + case -1: + fatal_exit("fork failed: %s", strerror(errno)); + default: + /* exit interactive session */ + exit(0); + } + /* detach */ +#ifdef HAVE_SETSID + if(setsid() == -1) + fatal_exit("setsid() failed: %s", strerror(errno)); +#endif + if ((fd = open("/dev/null", O_RDWR, 0)) != -1) { + (void)dup2(fd, STDIN_FILENO); + (void)dup2(fd, STDOUT_FILENO); + (void)dup2(fd, STDERR_FILENO); + if (fd > 2) + (void)close(fd); + } +#endif /* HAVE_FORK */ +#endif /* HAVE_DAEMON */ +} + +/** daemonize, drop user priviliges and chroot if needed */ +static void +perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode, + const char** cfgfile) +{ +#ifdef HAVE_GETPWNAM + struct passwd *pwd = NULL; + uid_t uid; + gid_t gid; + /* initialize, but not to 0 (root) */ + memset(&uid, 112, sizeof(uid)); + memset(&gid, 112, sizeof(gid)); + log_assert(cfg); + + if(cfg->username && cfg->username[0]) { + if((pwd = getpwnam(cfg->username)) == NULL) + fatal_exit("user '%s' does not exist.", cfg->username); + uid = pwd->pw_uid; + gid = pwd->pw_gid; + /* endpwent below, in case we need pwd for setusercontext */ + } +#endif + + /* init syslog (as root) if needed, before daemonize, otherwise + * a fork error could not be printed since daemonize closed stderr.*/ + if(cfg->use_syslog) { + log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir); + } + /* if using a logfile, we cannot open it because the logfile would + * be created with the wrong permissions, we cannot chown it because + * we cannot chown system logfiles, so we do not open at all. + * So, using a logfile, the user does not see errors unless -d is + * given to unbound on the commandline. */ + + /* read ssl keys while superuser and outside chroot */ + if(!(daemon->rc = daemon_remote_create(cfg))) + fatal_exit("could not set up remote-control"); + if(cfg->ssl_service_key && cfg->ssl_service_key[0]) { + if(!(daemon->listen_sslctx = listen_sslctx_create( + cfg->ssl_service_key, cfg->ssl_service_pem, NULL))) + fatal_exit("could not set up listen SSL_CTX"); + } + if(!(daemon->connect_sslctx = connect_sslctx_create(NULL, NULL, NULL))) + fatal_exit("could not set up connect SSL_CTX"); + +#ifdef HAVE_KILL + /* check old pid file before forking */ + if(cfg->pidfile && cfg->pidfile[0]) { + /* calculate position of pidfile */ + if(cfg->pidfile[0] == '/') + daemon->pidfile = strdup(cfg->pidfile); + else daemon->pidfile = fname_after_chroot(cfg->pidfile, + cfg, 1); + if(!daemon->pidfile) + fatal_exit("pidfile alloc: out of memory"); + checkoldpid(daemon->pidfile, + /* true if pidfile is inside chrootdir, or nochroot */ + !(cfg->chrootdir && cfg->chrootdir[0]) || + (cfg->chrootdir && cfg->chrootdir[0] && + strncmp(daemon->pidfile, cfg->chrootdir, + strlen(cfg->chrootdir))==0)); + } +#endif + + /* daemonize because pid is needed by the writepid func */ + if(!debug_mode && cfg->do_daemonize) { + detach(); + } + + /* write new pidfile (while still root, so can be outside chroot) */ +#ifdef HAVE_KILL + if(cfg->pidfile && cfg->pidfile[0]) { + writepid(daemon->pidfile, getpid()); + if(!(cfg->chrootdir && cfg->chrootdir[0]) || + (cfg->chrootdir && cfg->chrootdir[0] && + strncmp(daemon->pidfile, cfg->chrootdir, + strlen(cfg->chrootdir))==0)) { + /* delete of pidfile could potentially work, + * chown to get permissions */ + if(cfg->username && cfg->username[0]) { + if(chown(daemon->pidfile, uid, gid) == -1) { + log_err("cannot chown %u.%u %s: %s", + (unsigned)uid, (unsigned)gid, + daemon->pidfile, strerror(errno)); + } + } + } + } +#else + (void)daemon; +#endif + + /* Set user context */ +#ifdef HAVE_GETPWNAM + if(cfg->username && cfg->username[0]) { +#ifdef HAVE_SETUSERCONTEXT + /* setusercontext does initgroups, setuid, setgid, and + * also resource limits from login config, but we + * still call setresuid, setresgid to be sure to set all uid*/ + if(setusercontext(NULL, pwd, uid, + LOGIN_SETALL & ~LOGIN_SETUSER & ~LOGIN_SETGROUP) != 0) + log_warn("unable to setusercontext %s: %s", + cfg->username, strerror(errno)); +#endif /* HAVE_SETUSERCONTEXT */ + } +#endif /* HAVE_GETPWNAM */ + + /* box into the chroot */ +#ifdef HAVE_CHROOT + if(cfg->chrootdir && cfg->chrootdir[0]) { + if(chdir(cfg->chrootdir)) { + fatal_exit("unable to chdir to chroot %s: %s", + cfg->chrootdir, strerror(errno)); + } + verbose(VERB_QUERY, "chdir to %s", cfg->chrootdir); + if(chroot(cfg->chrootdir)) + fatal_exit("unable to chroot to %s: %s", + cfg->chrootdir, strerror(errno)); + verbose(VERB_QUERY, "chroot to %s", cfg->chrootdir); + if(strncmp(*cfgfile, cfg->chrootdir, + strlen(cfg->chrootdir)) == 0) + (*cfgfile) += strlen(cfg->chrootdir); + + /* adjust stored pidfile for chroot */ + if(daemon->pidfile && daemon->pidfile[0] && + strncmp(daemon->pidfile, cfg->chrootdir, + strlen(cfg->chrootdir))==0) { + char* old = daemon->pidfile; + daemon->pidfile = strdup(old+strlen(cfg->chrootdir)); + free(old); + if(!daemon->pidfile) + log_err("out of memory in pidfile adjust"); + } + daemon->chroot = strdup(cfg->chrootdir); + if(!daemon->chroot) + log_err("out of memory in daemon chroot dir storage"); + } +#else + (void)cfgfile; +#endif + /* change to working directory inside chroot */ + if(cfg->directory && cfg->directory[0]) { + char* dir = cfg->directory; + if(cfg->chrootdir && cfg->chrootdir[0] && + strncmp(dir, cfg->chrootdir, + strlen(cfg->chrootdir)) == 0) + dir += strlen(cfg->chrootdir); + if(dir[0]) { + if(chdir(dir)) { + fatal_exit("Could not chdir to %s: %s", + dir, strerror(errno)); + } + verbose(VERB_QUERY, "chdir to %s", dir); + } + } + + /* drop permissions after chroot, getpwnam, pidfile, syslog done*/ +#ifdef HAVE_GETPWNAM + if(cfg->username && cfg->username[0]) { +# ifdef HAVE_INITGROUPS + if(initgroups(cfg->username, gid) != 0) + log_warn("unable to initgroups %s: %s", + cfg->username, strerror(errno)); +# endif /* HAVE_INITGROUPS */ + endpwent(); + +#ifdef HAVE_SETRESGID + if(setresgid(gid,gid,gid) != 0) +#elif defined(HAVE_SETREGID) && !defined(DARWIN_BROKEN_SETREUID) + if(setregid(gid,gid) != 0) +#else /* use setgid */ + if(setgid(gid) != 0) +#endif /* HAVE_SETRESGID */ + fatal_exit("unable to set group id of %s: %s", + cfg->username, strerror(errno)); +#ifdef HAVE_SETRESUID + if(setresuid(uid,uid,uid) != 0) +#elif defined(HAVE_SETREUID) && !defined(DARWIN_BROKEN_SETREUID) + if(setreuid(uid,uid) != 0) +#else /* use setuid */ + if(setuid(uid) != 0) +#endif /* HAVE_SETRESUID */ + fatal_exit("unable to set user id of %s: %s", + cfg->username, strerror(errno)); + verbose(VERB_QUERY, "drop user privileges, run as %s", + cfg->username); + } +#endif /* HAVE_GETPWNAM */ + /* file logging inited after chroot,chdir,setuid is done so that + * it would succeed on SIGHUP as well */ + if(!cfg->use_syslog) + log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir); +} + +/** + * Run the daemon. + * @param cfgfile: the config file name. + * @param cmdline_verbose: verbosity resulting from commandline -v. + * These increase verbosity as specified in the config file. + * @param debug_mode: if set, do not daemonize. + */ +static void +run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode) +{ + struct config_file* cfg = NULL; + struct daemon* daemon = NULL; + int done_setup = 0; + + if(!(daemon = daemon_init())) + fatal_exit("alloc failure"); + while(!daemon->need_to_exit) { + if(done_setup) + verbose(VERB_OPS, "Restart of %s.", PACKAGE_STRING); + else verbose(VERB_OPS, "Start of %s.", PACKAGE_STRING); + + /* config stuff */ + if(!(cfg = config_create())) + fatal_exit("Could not alloc config defaults"); + if(!config_read(cfg, cfgfile, daemon->chroot)) { + if(errno != ENOENT) + fatal_exit("Could not read config file: %s", + cfgfile); + log_warn("Continuing with default config settings"); + } + apply_settings(daemon, cfg, cmdline_verbose); + + /* prepare */ + if(!daemon_open_shared_ports(daemon)) + fatal_exit("could not open ports"); + if(!done_setup) { + perform_setup(daemon, cfg, debug_mode, &cfgfile); + done_setup = 1; + } else { + /* reopen log after HUP to facilitate log rotation */ + if(!cfg->use_syslog) + log_init(cfg->logfile, 0, cfg->chrootdir); + } + /* work */ + daemon_fork(daemon); + + /* clean up for restart */ + verbose(VERB_ALGO, "cleanup."); + daemon_cleanup(daemon); + config_delete(cfg); + } + verbose(VERB_ALGO, "Exit cleanup."); + /* this unlink may not work if the pidfile is located outside + * of the chroot/workdir or we no longer have permissions */ + if(daemon->pidfile) { + int fd; + /* truncate pidfile */ + fd = open(daemon->pidfile, O_WRONLY | O_TRUNC, 0644); + if(fd != -1) + close(fd); + /* delete pidfile */ + unlink(daemon->pidfile); + } + daemon_delete(daemon); +} + +/** getopt global, in case header files fail to declare it. */ +extern int optind; +/** getopt global, in case header files fail to declare it. */ +extern char* optarg; + +/** + * main program. Set options given commandline arguments. + * @param argc: number of commandline arguments. + * @param argv: array of commandline arguments. + * @return: exit status of the program. + */ +int +main(int argc, char* argv[]) +{ + int c; + const char* cfgfile = CONFIGFILE; + const char* winopt = NULL; + int cmdline_verbose = 0; + int debug_mode = 0; +#ifdef UB_ON_WINDOWS + int cmdline_cfg = 0; +#endif + +#ifdef HAVE_SBRK + /* take debug snapshot of heap */ + unbound_start_brk = sbrk(0); +#endif + + log_init(NULL, 0, NULL); + /* parse the options */ + while( (c=getopt(argc, argv, "c:dhvw:")) != -1) { + switch(c) { + case 'c': + cfgfile = optarg; +#ifdef UB_ON_WINDOWS + cmdline_cfg = 1; +#endif + break; + case 'v': + cmdline_verbose ++; + verbosity++; + break; + case 'd': + debug_mode = 1; + break; + case 'w': + winopt = optarg; + break; + case '?': + case 'h': + default: + usage(); + return 1; + } + } + argc -= optind; + argv += optind; + + if(winopt) { +#ifdef UB_ON_WINDOWS + wsvc_command_option(winopt, cfgfile, cmdline_verbose, + cmdline_cfg); +#else + fatal_exit("option not supported"); +#endif + } + + if(argc != 0) { + usage(); + return 1; + } + + run_daemon(cfgfile, cmdline_verbose, debug_mode); + log_init(NULL, 0, NULL); /* close logfile */ + return 0; +} diff --git a/daemon/worker.c b/daemon/worker.c new file mode 100644 index 00000000000..832278fc3d5 --- /dev/null +++ b/daemon/worker.c @@ -0,0 +1,1377 @@ +/* + * daemon/worker.c - worker that handles a pending list of requests. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file implements the worker that handles callbacks on events, for + * pending requests. + */ +#include "config.h" +#include +#include "util/log.h" +#include "util/net_help.h" +#include "util/random.h" +#include "daemon/worker.h" +#include "daemon/daemon.h" +#include "daemon/remote.h" +#include "daemon/acl_list.h" +#include "util/netevent.h" +#include "util/config_file.h" +#include "util/module.h" +#include "util/regional.h" +#include "util/storage/slabhash.h" +#include "services/listen_dnsport.h" +#include "services/outside_network.h" +#include "services/outbound_list.h" +#include "services/cache/rrset.h" +#include "services/cache/infra.h" +#include "services/cache/dns.h" +#include "services/mesh.h" +#include "services/localzone.h" +#include "util/data/msgparse.h" +#include "util/data/msgencode.h" +#include "util/data/dname.h" +#include "util/fptr_wlist.h" +#include "util/tube.h" +#include "iterator/iter_fwd.h" +#include "iterator/iter_hints.h" +#include "validator/autotrust.h" +#include "validator/val_anchor.h" + +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#include +#ifdef UB_ON_WINDOWS +#include "winrc/win_svc.h" +#endif + +/** Size of an UDP datagram */ +#define NORMAL_UDP_SIZE 512 /* bytes */ + +/** + * seconds to add to prefetch leeway. This is a TTL that expires old rrsets + * earlier than they should in order to put the new update into the cache. + * This additional value is to make sure that if not all TTLs are equal in + * the message to be updated(and replaced), that rrsets with up to this much + * extra TTL are also replaced. This means that the resulting new message + * will have (most likely) this TTL at least, avoiding very small 'split + * second' TTLs due to operators choosing relative primes for TTLs (or so). + * Also has to be at least one to break ties (and overwrite cached entry). + */ +#define PREFETCH_EXPIRY_ADD 60 + +#ifdef UNBOUND_ALLOC_STATS +/** measure memory leakage */ +static void +debug_memleak(size_t accounted, size_t heap, + size_t total_alloc, size_t total_free) +{ + static int init = 0; + static size_t base_heap, base_accounted, base_alloc, base_free; + size_t base_af, cur_af, grow_af, grow_acc; + if(!init) { + init = 1; + base_heap = heap; + base_accounted = accounted; + base_alloc = total_alloc; + base_free = total_free; + } + base_af = base_alloc - base_free; + cur_af = total_alloc - total_free; + grow_af = cur_af - base_af; + grow_acc = accounted - base_accounted; + log_info("Leakage: %d leaked. growth: %u use, %u acc, %u heap", + (int)(grow_af - grow_acc), (unsigned)grow_af, + (unsigned)grow_acc, (unsigned)(heap - base_heap)); +} + +/** give debug heap size indication */ +static void +debug_total_mem(size_t calctotal) +{ +#ifdef HAVE_SBRK + extern void* unbound_start_brk; + extern size_t unbound_mem_alloc, unbound_mem_freed; + void* cur = sbrk(0); + int total = cur-unbound_start_brk; + log_info("Total heap memory estimate: %u total-alloc: %u " + "total-free: %u", (unsigned)total, + (unsigned)unbound_mem_alloc, (unsigned)unbound_mem_freed); + debug_memleak(calctotal, (size_t)total, + unbound_mem_alloc, unbound_mem_freed); +#else + (void)calctotal; +#endif /* HAVE_SBRK */ +} +#endif /* UNBOUND_ALLOC_STATS */ + +/** Report on memory usage by this thread and global */ +static void +worker_mem_report(struct worker* ATTR_UNUSED(worker), + struct serviced_query* ATTR_UNUSED(cur_serv)) +{ +#ifdef UNBOUND_ALLOC_STATS + /* debug func in validator module */ + size_t total, front, back, mesh, msg, rrset, infra, ac, superac; + size_t me, iter, val, anch; + int i; + if(verbosity < VERB_ALGO) + return; + front = listen_get_mem(worker->front); + back = outnet_get_mem(worker->back); + msg = slabhash_get_mem(worker->env.msg_cache); + rrset = slabhash_get_mem(&worker->env.rrset_cache->table); + infra = infra_get_mem(worker->env.infra_cache); + mesh = mesh_get_mem(worker->env.mesh); + ac = alloc_get_mem(&worker->alloc); + superac = alloc_get_mem(&worker->daemon->superalloc); + anch = anchors_get_mem(worker->env.anchors); + iter = 0; + val = 0; + for(i=0; ienv.mesh->mods.num; i++) { + fptr_ok(fptr_whitelist_mod_get_mem(worker->env.mesh-> + mods.mod[i]->get_mem)); + if(strcmp(worker->env.mesh->mods.mod[i]->name, "validator")==0) + val += (*worker->env.mesh->mods.mod[i]->get_mem) + (&worker->env, i); + else iter += (*worker->env.mesh->mods.mod[i]->get_mem) + (&worker->env, i); + } + me = sizeof(*worker) + sizeof(*worker->base) + sizeof(*worker->comsig) + + comm_point_get_mem(worker->cmd_com) + + sizeof(worker->rndstate) + + regional_get_mem(worker->scratchpad) + + sizeof(*worker->env.scratch_buffer) + + ldns_buffer_capacity(worker->env.scratch_buffer) + + forwards_get_mem(worker->env.fwds) + + hints_get_mem(worker->env.hints); + if(worker->thread_num == 0) + me += acl_list_get_mem(worker->daemon->acl); + if(cur_serv) { + me += serviced_get_mem(cur_serv); + } + total = front+back+mesh+msg+rrset+infra+iter+val+ac+superac+me; + log_info("Memory conditions: %u front=%u back=%u mesh=%u msg=%u " + "rrset=%u infra=%u iter=%u val=%u anchors=%u " + "alloccache=%u globalalloccache=%u me=%u", + (unsigned)total, (unsigned)front, (unsigned)back, + (unsigned)mesh, (unsigned)msg, (unsigned)rrset, + (unsigned)infra, (unsigned)iter, (unsigned)val, (unsigned)anch, + (unsigned)ac, (unsigned)superac, (unsigned)me); + debug_total_mem(total); +#else /* no UNBOUND_ALLOC_STATS */ + size_t val = 0; + int i; + if(verbosity < VERB_QUERY) + return; + for(i=0; ienv.mesh->mods.num; i++) { + fptr_ok(fptr_whitelist_mod_get_mem(worker->env.mesh-> + mods.mod[i]->get_mem)); + if(strcmp(worker->env.mesh->mods.mod[i]->name, "validator")==0) + val += (*worker->env.mesh->mods.mod[i]->get_mem) + (&worker->env, i); + } + verbose(VERB_QUERY, "cache memory msg=%u rrset=%u infra=%u val=%u", + (unsigned)slabhash_get_mem(worker->env.msg_cache), + (unsigned)slabhash_get_mem(&worker->env.rrset_cache->table), + (unsigned)infra_get_mem(worker->env.infra_cache), + (unsigned)val); +#endif /* UNBOUND_ALLOC_STATS */ +} + +void +worker_send_cmd(struct worker* worker, enum worker_commands cmd) +{ + uint32_t c = (uint32_t)htonl(cmd); + if(!tube_write_msg(worker->cmd, (uint8_t*)&c, sizeof(c), 0)) { + log_err("worker send cmd %d failed", (int)cmd); + } +} + +int +worker_handle_reply(struct comm_point* c, void* arg, int error, + struct comm_reply* reply_info) +{ + struct module_qstate* q = (struct module_qstate*)arg; + struct worker* worker = q->env->worker; + struct outbound_entry e; + e.qstate = q; + e.qsent = NULL; + + if(error != 0) { + mesh_report_reply(worker->env.mesh, &e, reply_info, error); + worker_mem_report(worker, NULL); + return 0; + } + /* sanity check. */ + if(!LDNS_QR_WIRE(ldns_buffer_begin(c->buffer)) + || LDNS_OPCODE_WIRE(ldns_buffer_begin(c->buffer)) != + LDNS_PACKET_QUERY + || LDNS_QDCOUNT(ldns_buffer_begin(c->buffer)) > 1) { + /* error becomes timeout for the module as if this reply + * never arrived. */ + mesh_report_reply(worker->env.mesh, &e, reply_info, + NETEVENT_TIMEOUT); + worker_mem_report(worker, NULL); + return 0; + } + mesh_report_reply(worker->env.mesh, &e, reply_info, NETEVENT_NOERROR); + worker_mem_report(worker, NULL); + return 0; +} + +int +worker_handle_service_reply(struct comm_point* c, void* arg, int error, + struct comm_reply* reply_info) +{ + struct outbound_entry* e = (struct outbound_entry*)arg; + struct worker* worker = e->qstate->env->worker; + struct serviced_query *sq = e->qsent; + + verbose(VERB_ALGO, "worker svcd callback for qstate %p", e->qstate); + if(error != 0) { + mesh_report_reply(worker->env.mesh, e, reply_info, error); + worker_mem_report(worker, sq); + return 0; + } + /* sanity check. */ + if(!LDNS_QR_WIRE(ldns_buffer_begin(c->buffer)) + || LDNS_OPCODE_WIRE(ldns_buffer_begin(c->buffer)) != + LDNS_PACKET_QUERY + || LDNS_QDCOUNT(ldns_buffer_begin(c->buffer)) > 1) { + /* error becomes timeout for the module as if this reply + * never arrived. */ + verbose(VERB_ALGO, "worker: bad reply handled as timeout"); + mesh_report_reply(worker->env.mesh, e, reply_info, + NETEVENT_TIMEOUT); + worker_mem_report(worker, sq); + return 0; + } + mesh_report_reply(worker->env.mesh, e, reply_info, NETEVENT_NOERROR); + worker_mem_report(worker, sq); + return 0; +} + +/** check request sanity. + * @param pkt: the wire packet to examine for sanity. + * @param worker: parameters for checking. + * @return error code, 0 OK, or -1 discard. +*/ +static int +worker_check_request(ldns_buffer* pkt, struct worker* worker) +{ + if(ldns_buffer_limit(pkt) < LDNS_HEADER_SIZE) { + verbose(VERB_QUERY, "request too short, discarded"); + return -1; + } + if(ldns_buffer_limit(pkt) > NORMAL_UDP_SIZE && + worker->daemon->cfg->harden_large_queries) { + verbose(VERB_QUERY, "request too large, discarded"); + return -1; + } + if(LDNS_QR_WIRE(ldns_buffer_begin(pkt))) { + verbose(VERB_QUERY, "request has QR bit on, discarded"); + return -1; + } + if(LDNS_TC_WIRE(ldns_buffer_begin(pkt))) { + LDNS_TC_CLR(ldns_buffer_begin(pkt)); + verbose(VERB_QUERY, "request bad, has TC bit on"); + return LDNS_RCODE_FORMERR; + } + if(LDNS_OPCODE_WIRE(ldns_buffer_begin(pkt)) != LDNS_PACKET_QUERY) { + verbose(VERB_QUERY, "request unknown opcode %d", + LDNS_OPCODE_WIRE(ldns_buffer_begin(pkt))); + return LDNS_RCODE_NOTIMPL; + } + if(LDNS_QDCOUNT(ldns_buffer_begin(pkt)) != 1) { + verbose(VERB_QUERY, "request wrong nr qd=%d", + LDNS_QDCOUNT(ldns_buffer_begin(pkt))); + return LDNS_RCODE_FORMERR; + } + if(LDNS_ANCOUNT(ldns_buffer_begin(pkt)) != 0) { + verbose(VERB_QUERY, "request wrong nr an=%d", + LDNS_ANCOUNT(ldns_buffer_begin(pkt))); + return LDNS_RCODE_FORMERR; + } + if(LDNS_NSCOUNT(ldns_buffer_begin(pkt)) != 0) { + verbose(VERB_QUERY, "request wrong nr ns=%d", + LDNS_NSCOUNT(ldns_buffer_begin(pkt))); + return LDNS_RCODE_FORMERR; + } + if(LDNS_ARCOUNT(ldns_buffer_begin(pkt)) > 1) { + verbose(VERB_QUERY, "request wrong nr ar=%d", + LDNS_ARCOUNT(ldns_buffer_begin(pkt))); + return LDNS_RCODE_FORMERR; + } + return 0; +} + +void +worker_handle_control_cmd(struct tube* ATTR_UNUSED(tube), uint8_t* msg, + size_t len, int error, void* arg) +{ + struct worker* worker = (struct worker*)arg; + enum worker_commands cmd; + if(error != NETEVENT_NOERROR) { + free(msg); + if(error == NETEVENT_CLOSED) + comm_base_exit(worker->base); + else log_info("control event: %d", error); + return; + } + if(len != sizeof(uint32_t)) { + fatal_exit("bad control msg length %d", (int)len); + } + cmd = ldns_read_uint32(msg); + free(msg); + switch(cmd) { + case worker_cmd_quit: + verbose(VERB_ALGO, "got control cmd quit"); + comm_base_exit(worker->base); + break; + case worker_cmd_stats: + verbose(VERB_ALGO, "got control cmd stats"); + server_stats_reply(worker, 1); + break; + case worker_cmd_stats_noreset: + verbose(VERB_ALGO, "got control cmd stats_noreset"); + server_stats_reply(worker, 0); + break; + case worker_cmd_remote: + verbose(VERB_ALGO, "got control cmd remote"); + daemon_remote_exec(worker); + break; + default: + log_err("bad command %d", (int)cmd); + break; + } +} + +/** check if a delegation is secure */ +static enum sec_status +check_delegation_secure(struct reply_info *rep) +{ + /* return smallest security status */ + size_t i; + enum sec_status sec = sec_status_secure; + enum sec_status s; + size_t num = rep->an_numrrsets + rep->ns_numrrsets; + /* check if answer and authority are OK */ + for(i=0; irrsets[i]->entry.data) + ->security; + if(s < sec) + sec = s; + } + /* in additional, only unchecked triggers revalidation */ + for(i=num; irrset_count; i++) { + s = ((struct packed_rrset_data*)rep->rrsets[i]->entry.data) + ->security; + if(s == sec_status_unchecked) + return s; + } + return sec; +} + +/** remove nonsecure from a delegation referral additional section */ +static void +deleg_remove_nonsecure_additional(struct reply_info* rep) +{ + /* we can simply edit it, since we are working in the scratch region */ + size_t i; + enum sec_status s; + + for(i = rep->an_numrrsets+rep->ns_numrrsets; irrset_count; i++) { + s = ((struct packed_rrset_data*)rep->rrsets[i]->entry.data) + ->security; + if(s != sec_status_secure) { + memmove(rep->rrsets+i, rep->rrsets+i+1, + sizeof(struct ub_packed_rrset_key*)* + (rep->rrset_count - i - 1)); + rep->ar_numrrsets--; + rep->rrset_count--; + i--; + } + } +} + +/** answer nonrecursive query from the cache */ +static int +answer_norec_from_cache(struct worker* worker, struct query_info* qinfo, + uint16_t id, uint16_t flags, struct comm_reply* repinfo, + struct edns_data* edns) +{ + /* for a nonrecursive query return either: + * o an error (servfail; we try to avoid this) + * o a delegation (closest we have; this routine tries that) + * o the answer (checked by answer_from_cache) + * + * So, grab a delegation from the rrset cache. + * Then check if it needs validation, if so, this routine fails, + * so that iterator can prime and validator can verify rrsets. + */ + uint16_t udpsize = edns->udp_size; + int secure = 0; + uint32_t timenow = *worker->env.now; + int must_validate = (!(flags&BIT_CD) || worker->env.cfg->ignore_cd) + && worker->env.need_to_validate; + struct dns_msg *msg = NULL; + struct delegpt *dp; + + dp = dns_cache_find_delegation(&worker->env, qinfo->qname, + 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) { + switch(check_delegation_secure(msg->rep)) { + 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 */ + edns->edns_version = EDNS_ADVERTISED_VERSION; + edns->udp_size = EDNS_ADVERTISED_SIZE; + edns->ext_rcode = 0; + edns->bits &= EDNS_DO; + 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]++; + } + return 1; + case sec_status_secure: + /* all rrsets are secure */ + /* remove non-secure rrsets from the add. section*/ + if(worker->env.cfg->val_clean_additional) + deleg_remove_nonsecure_additional(msg->rep); + secure = 1; + break; + case sec_status_indeterminate: + case sec_status_insecure: + default: + /* not secure */ + secure = 0; + break; + } + } + /* return this delegation from the cache */ + edns->edns_version = EDNS_ADVERTISED_VERSION; + edns->udp_size = EDNS_ADVERTISED_SIZE; + edns->ext_rcode = 0; + edns->bits &= EDNS_DO; + 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, + udpsize, edns, (int)(edns->bits & EDNS_DO), secure)) { + 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); + } + return 1; +} + +/** answer query from the cache */ +static int +answer_from_cache(struct worker* worker, struct query_info* qinfo, + struct reply_info* rep, uint16_t id, uint16_t flags, + struct comm_reply* repinfo, struct edns_data* edns) +{ + uint32_t timenow = *worker->env.now; + uint16_t udpsize = edns->udp_size; + int secure; + int must_validate = (!(flags&BIT_CD) || worker->env.cfg->ignore_cd) + && worker->env.need_to_validate; + /* see if it is possible */ + if(rep->ttl < timenow) { + /* the rrsets may have been updated in the meantime. + * we will refetch the message format from the + * authoritative server + */ + return 0; + } + if(!rrset_array_lock(rep->ref, rep->rrset_count, timenow)) + return 0; + /* locked and ids and ttls are OK. */ + /* check CNAME chain (if any) */ + if(rep->an_numrrsets > 0 && (rep->rrsets[0]->rk.type == + htons(LDNS_RR_TYPE_CNAME) || rep->rrsets[0]->rk.type == + htons(LDNS_RR_TYPE_DNAME))) { + if(!reply_check_cname_chain(rep)) { + /* cname chain invalid, redo iterator steps */ + verbose(VERB_ALGO, "Cache reply: cname chain broken"); + bail_out: + rrset_array_unlock_touch(worker->env.rrset_cache, + worker->scratchpad, rep->ref, rep->rrset_count); + regional_free_all(worker->scratchpad); + return 0; + } + } + /* check security status of the cached answer */ + if( rep->security == sec_status_bogus && must_validate) { + /* BAD cached */ + edns->edns_version = EDNS_ADVERTISED_VERSION; + edns->udp_size = EDNS_ADVERTISED_SIZE; + edns->ext_rcode = 0; + edns->bits &= EDNS_DO; + 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] ++; + } + return 1; + } else if( rep->security == sec_status_unchecked && must_validate) { + verbose(VERB_ALGO, "Cache reply: unchecked entry needs " + "validation"); + goto bail_out; /* need to validate cache entry first */ + } else if(rep->security == sec_status_secure) { + if(reply_all_rrsets_secure(rep)) + secure = 1; + else { + if(must_validate) { + verbose(VERB_ALGO, "Cache reply: secure entry" + " changed status"); + goto bail_out; /* rrset changed, re-verify */ + } + secure = 0; + } + } else secure = 0; + + edns->edns_version = EDNS_ADVERTISED_VERSION; + edns->udp_size = EDNS_ADVERTISED_SIZE; + edns->ext_rcode = 0; + edns->bits &= EDNS_DO; + if(!reply_info_answer_encode(qinfo, rep, id, flags, + repinfo->c->buffer, timenow, 1, worker->scratchpad, + udpsize, edns, (int)(edns->bits & EDNS_DO), secure)) { + error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL, + qinfo, id, flags, edns); + } + /* cannot send the reply right now, because blocking network syscall + * 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); + } + /* go and return this buffer to the client */ + return 1; +} + +/** Reply to client and perform prefetch to keep cache up to date */ +static void +reply_and_prefetch(struct worker* worker, struct query_info* qinfo, + uint16_t flags, struct comm_reply* repinfo, uint32_t leeway) +{ + /* first send answer to client to keep its latency + * as small as a cachereply */ + comm_point_send_reply(repinfo); + server_stats_prefetch(&worker->stats, worker); + + /* create the prefetch in the mesh as a normal lookup without + * client addrs waiting, which has the cache blacklisted (to bypass + * the cache and go to the network for the data). */ + /* this (potentially) runs the mesh for the new query */ + mesh_new_prefetch(worker->env.mesh, qinfo, flags, leeway + + PREFETCH_EXPIRY_ADD); +} + +/** + * Fill CH class answer into buffer. Keeps query. + * @param pkt: buffer + * @param str: string to put into text record (<255). + * @param edns: edns reply information. + */ +static void +chaos_replystr(ldns_buffer* pkt, const char* str, struct edns_data* edns) +{ + size_t len = strlen(str); + unsigned int rd = LDNS_RD_WIRE(ldns_buffer_begin(pkt)); + unsigned int cd = LDNS_CD_WIRE(ldns_buffer_begin(pkt)); + if(len>255) len=255; /* cap size of TXT record */ + ldns_buffer_clear(pkt); + ldns_buffer_skip(pkt, (ssize_t)sizeof(uint16_t)); /* skip id */ + ldns_buffer_write_u16(pkt, (uint16_t)(BIT_QR|BIT_RA)); + if(rd) LDNS_RD_SET(ldns_buffer_begin(pkt)); + if(cd) LDNS_CD_SET(ldns_buffer_begin(pkt)); + ldns_buffer_write_u16(pkt, 1); /* qdcount */ + ldns_buffer_write_u16(pkt, 1); /* ancount */ + ldns_buffer_write_u16(pkt, 0); /* nscount */ + ldns_buffer_write_u16(pkt, 0); /* arcount */ + (void)query_dname_len(pkt); /* skip qname */ + ldns_buffer_skip(pkt, (ssize_t)sizeof(uint16_t)); /* skip qtype */ + ldns_buffer_skip(pkt, (ssize_t)sizeof(uint16_t)); /* skip qclass */ + ldns_buffer_write_u16(pkt, 0xc00c); /* compr ptr to query */ + ldns_buffer_write_u16(pkt, LDNS_RR_TYPE_TXT); + ldns_buffer_write_u16(pkt, LDNS_RR_CLASS_CH); + ldns_buffer_write_u32(pkt, 0); /* TTL */ + ldns_buffer_write_u16(pkt, sizeof(uint8_t) + len); + ldns_buffer_write_u8(pkt, len); + ldns_buffer_write(pkt, str, len); + ldns_buffer_flip(pkt); + edns->edns_version = EDNS_ADVERTISED_VERSION; + edns->udp_size = EDNS_ADVERTISED_SIZE; + edns->bits &= EDNS_DO; + attach_edns_record(pkt, edns); +} + +/** + * Answer CH class queries. + * @param w: worker + * @param qinfo: query info. Pointer into packet buffer. + * @param edns: edns info from query. + * @param pkt: packet buffer. + * @return: true if a reply is to be sent. + */ +static int +answer_chaos(struct worker* w, struct query_info* qinfo, + struct edns_data* edns, ldns_buffer* pkt) +{ + struct config_file* cfg = w->env.cfg; + if(qinfo->qtype != LDNS_RR_TYPE_ANY && qinfo->qtype != LDNS_RR_TYPE_TXT) + return 0; + if(query_dname_compare(qinfo->qname, + (uint8_t*)"\002id\006server") == 0 || + query_dname_compare(qinfo->qname, + (uint8_t*)"\010hostname\004bind") == 0) + { + if(cfg->hide_identity) + return 0; + if(cfg->identity==NULL || cfg->identity[0]==0) { + char buf[MAXHOSTNAMELEN+1]; + if (gethostname(buf, MAXHOSTNAMELEN) == 0) { + buf[MAXHOSTNAMELEN] = 0; + chaos_replystr(pkt, buf, edns); + } else { + log_err("gethostname: %s", strerror(errno)); + chaos_replystr(pkt, "no hostname", edns); + } + } + else chaos_replystr(pkt, cfg->identity, edns); + return 1; + } + if(query_dname_compare(qinfo->qname, + (uint8_t*)"\007version\006server") == 0 || + query_dname_compare(qinfo->qname, + (uint8_t*)"\007version\004bind") == 0) + { + 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); + return 1; + } + return 0; +} + +int +worker_handle_request(struct comm_point* c, void* arg, int error, + struct comm_reply* repinfo) +{ + struct worker* worker = (struct worker*)arg; + int ret; + hashvalue_t h; + struct lruhash_entry* e; + struct query_info qinfo; + struct edns_data edns; + enum acl_access acl; + + if(error != NETEVENT_NOERROR) { + /* some bad tcp query DNS formats give these error calls */ + verbose(VERB_ALGO, "handle request called with err=%d", error); + return 0; + } + acl = acl_list_lookup(worker->daemon->acl, &repinfo->addr, + repinfo->addrlen); + if(acl == acl_deny) { + comm_point_drop_reply(repinfo); + if(worker->stats.extended) + worker->stats.unwanted_queries++; + return 0; + } else if(acl == acl_refuse) { + log_addr(VERB_ALGO, "refused query from", + &repinfo->addr, repinfo->addrlen); + log_buf(VERB_ALGO, "refuse", c->buffer); + if(worker->stats.extended) + worker->stats.unwanted_queries++; + if(worker_check_request(c->buffer, worker) == -1) { + comm_point_drop_reply(repinfo); + return 0; /* discard this */ + } + ldns_buffer_set_limit(c->buffer, LDNS_HEADER_SIZE); + ldns_buffer_write_at(c->buffer, 4, + (uint8_t*)"\0\0\0\0\0\0\0\0", 8); + LDNS_QR_SET(ldns_buffer_begin(c->buffer)); + LDNS_RCODE_SET(ldns_buffer_begin(c->buffer), + LDNS_RCODE_REFUSED); + return 1; + } + if((ret=worker_check_request(c->buffer, worker)) != 0) { + verbose(VERB_ALGO, "worker check request: bad query."); + log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen); + if(ret != -1) { + LDNS_QR_SET(ldns_buffer_begin(c->buffer)); + LDNS_RCODE_SET(ldns_buffer_begin(c->buffer), ret); + return 1; + } + comm_point_drop_reply(repinfo); + return 0; + } + worker->stats.num_queries++; + /* see if query is in the cache */ + if(!query_info_parse(&qinfo, c->buffer)) { + verbose(VERB_ALGO, "worker parse request: formerror."); + log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen); + ldns_buffer_rewind(c->buffer); + LDNS_QR_SET(ldns_buffer_begin(c->buffer)); + LDNS_RCODE_SET(ldns_buffer_begin(c->buffer), + LDNS_RCODE_FORMERR); + server_stats_insrcode(&worker->stats, c->buffer); + return 1; + } + if(worker->env.cfg->log_queries) { + char ip[128]; + addr_to_str(&repinfo->addr, repinfo->addrlen, ip, sizeof(ip)); + log_nametypeclass(0, ip, qinfo.qname, qinfo.qtype, qinfo.qclass); + } + if(qinfo.qtype == LDNS_RR_TYPE_AXFR || + qinfo.qtype == LDNS_RR_TYPE_IXFR) { + verbose(VERB_ALGO, "worker request: refused zone transfer."); + log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen); + ldns_buffer_rewind(c->buffer); + LDNS_QR_SET(ldns_buffer_begin(c->buffer)); + LDNS_RCODE_SET(ldns_buffer_begin(c->buffer), + LDNS_RCODE_REFUSED); + if(worker->stats.extended) { + worker->stats.qtype[qinfo.qtype]++; + server_stats_insrcode(&worker->stats, c->buffer); + } + return 1; + } + if((ret=parse_edns_from_pkt(c->buffer, &edns)) != 0) { + verbose(VERB_ALGO, "worker parse edns: formerror."); + log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen); + ldns_buffer_rewind(c->buffer); + LDNS_QR_SET(ldns_buffer_begin(c->buffer)); + LDNS_RCODE_SET(ldns_buffer_begin(c->buffer), ret); + server_stats_insrcode(&worker->stats, c->buffer); + return 1; + } + if(edns.edns_present && edns.edns_version != 0) { + edns.ext_rcode = (uint8_t)(EDNS_RCODE_BADVERS>>4); + edns.edns_version = EDNS_ADVERTISED_VERSION; + edns.udp_size = EDNS_ADVERTISED_SIZE; + edns.bits &= EDNS_DO; + 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*)ldns_buffer_begin(c->buffer), + ldns_buffer_read_u16_at(c->buffer, 2), NULL); + attach_edns_record(c->buffer, &edns); + return 1; + } + if(edns.edns_present && edns.udp_size < NORMAL_UDP_SIZE && + worker->daemon->cfg->harden_short_bufsize) { + verbose(VERB_QUERY, "worker request: EDNS bufsize %d ignored", + (int)edns.udp_size); + log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen); + edns.udp_size = NORMAL_UDP_SIZE; + } + if(edns.edns_present && edns.udp_size < LDNS_HEADER_SIZE) { + verbose(VERB_ALGO, "worker request: edns is too small."); + log_addr(VERB_CLIENT, "from", &repinfo->addr, repinfo->addrlen); + LDNS_QR_SET(ldns_buffer_begin(c->buffer)); + LDNS_TC_SET(ldns_buffer_begin(c->buffer)); + LDNS_RCODE_SET(ldns_buffer_begin(c->buffer), + LDNS_RCODE_SERVFAIL); + ldns_buffer_set_position(c->buffer, LDNS_HEADER_SIZE); + ldns_buffer_write_at(c->buffer, 4, + (uint8_t*)"\0\0\0\0\0\0\0\0", 8); + ldns_buffer_flip(c->buffer); + return 1; + } + if(worker->stats.extended) + server_stats_insquery(&worker->stats, c, qinfo.qtype, + qinfo.qclass, &edns, repinfo); + if(c->type != comm_udp) + edns.udp_size = 65535; /* max size for TCP replies */ + if(qinfo.qclass == LDNS_RR_CLASS_CH && answer_chaos(worker, &qinfo, + &edns, c->buffer)) { + server_stats_insrcode(&worker->stats, c->buffer); + return 1; + } + if(local_zones_answer(worker->daemon->local_zones, &qinfo, &edns, + c->buffer, worker->scratchpad)) { + regional_free_all(worker->scratchpad); + if(ldns_buffer_limit(c->buffer) == 0) { + comm_point_drop_reply(repinfo); + return 0; + } + server_stats_insrcode(&worker->stats, c->buffer); + return 1; + } + if(!(LDNS_RD_WIRE(ldns_buffer_begin(c->buffer))) && + acl != acl_allow_snoop ) { + ldns_buffer_set_limit(c->buffer, LDNS_HEADER_SIZE); + ldns_buffer_write_at(c->buffer, 4, + (uint8_t*)"\0\0\0\0\0\0\0\0", 8); + LDNS_QR_SET(ldns_buffer_begin(c->buffer)); + LDNS_RCODE_SET(ldns_buffer_begin(c->buffer), + LDNS_RCODE_REFUSED); + ldns_buffer_flip(c->buffer); + server_stats_insrcode(&worker->stats, c->buffer); + log_addr(VERB_ALGO, "refused nonrec (cache snoop) query from", + &repinfo->addr, repinfo->addrlen); + return 1; + } + h = query_info_hash(&qinfo); + if((e=slabhash_lookup(worker->env.msg_cache, h, &qinfo, 0))) { + /* answer from cache - we have acquired a readlock on it */ + if(answer_from_cache(worker, &qinfo, + (struct reply_info*)e->data, + *(uint16_t*)ldns_buffer_begin(c->buffer), + ldns_buffer_read_u16_at(c->buffer, 2), repinfo, + &edns)) { + /* prefetch it if the prefetch TTL expired */ + if(worker->env.cfg->prefetch && *worker->env.now >= + ((struct reply_info*)e->data)->prefetch_ttl) { + uint32_t leeway = ((struct reply_info*)e-> + data)->ttl - *worker->env.now; + lock_rw_unlock(&e->lock); + reply_and_prefetch(worker, &qinfo, + ldns_buffer_read_u16_at(c->buffer, 2), + repinfo, leeway); + return 0; + } + lock_rw_unlock(&e->lock); + return 1; + } + verbose(VERB_ALGO, "answer from the cache failed"); + lock_rw_unlock(&e->lock); + } + if(!LDNS_RD_WIRE(ldns_buffer_begin(c->buffer))) { + if(answer_norec_from_cache(worker, &qinfo, + *(uint16_t*)ldns_buffer_begin(c->buffer), + ldns_buffer_read_u16_at(c->buffer, 2), repinfo, + &edns)) { + return 1; + } + verbose(VERB_ALGO, "answer norec from cache -- " + "need to validate or not primed"); + } + ldns_buffer_rewind(c->buffer); + server_stats_querymiss(&worker->stats, worker); + + if(verbosity >= VERB_CLIENT) { + if(c->type == comm_udp) + log_addr(VERB_CLIENT, "udp request from", + &repinfo->addr, repinfo->addrlen); + else log_addr(VERB_CLIENT, "tcp request from", + &repinfo->addr, repinfo->addrlen); + } + + /* grab a work request structure for this new request */ + mesh_new_client(worker->env.mesh, &qinfo, + ldns_buffer_read_u16_at(c->buffer, 2), + &edns, repinfo, *(uint16_t*)ldns_buffer_begin(c->buffer)); + worker_mem_report(worker, NULL); + return 0; +} + +void +worker_sighandler(int sig, void* arg) +{ + /* note that log, print, syscalls here give race conditions. */ + /* we still print DETAIL logs, because this is extensive per message + * logging anyway, and the operator may then have an interest + * in the cause for unbound to exit */ + struct worker* worker = (struct worker*)arg; + switch(sig) { +#ifdef SIGHUP + case SIGHUP: + verbose(VERB_QUERY, "caught signal SIGHUP"); + comm_base_exit(worker->base); + break; +#endif + case SIGINT: + verbose(VERB_QUERY, "caught signal SIGINT"); + worker->need_to_exit = 1; + comm_base_exit(worker->base); + break; +#ifdef SIGQUIT + case SIGQUIT: + verbose(VERB_QUERY, "caught signal SIGQUIT"); + worker->need_to_exit = 1; + comm_base_exit(worker->base); + break; +#endif + case SIGTERM: + verbose(VERB_QUERY, "caught signal SIGTERM"); + worker->need_to_exit = 1; + comm_base_exit(worker->base); + break; + default: + log_err("unknown signal: %d, ignored", sig); + break; + } +} + +/** restart statistics timer for worker, if enabled */ +static void +worker_restart_timer(struct worker* worker) +{ + if(worker->env.cfg->stat_interval > 0) { + struct timeval tv; +#ifndef S_SPLINT_S + tv.tv_sec = worker->env.cfg->stat_interval; + tv.tv_usec = 0; +#endif + comm_timer_set(worker->stat_timer, &tv); + } +} + +void worker_stat_timer_cb(void* arg) +{ + struct worker* worker = (struct worker*)arg; + server_stats_log(&worker->stats, worker, worker->thread_num); + mesh_stats(worker->env.mesh, "mesh has"); + worker_mem_report(worker, NULL); + if(!worker->daemon->cfg->stat_cumulative) { + worker_stats_clear(worker); + } + /* start next timer */ + worker_restart_timer(worker); +} + +void worker_probe_timer_cb(void* arg) +{ + struct worker* worker = (struct worker*)arg; + struct timeval tv; +#ifndef S_SPLINT_S + tv.tv_sec = (time_t)autr_probe_timer(&worker->env); + tv.tv_usec = 0; +#endif + if(tv.tv_sec != 0) + comm_timer_set(worker->env.probe_timer, &tv); +} + +struct worker* +worker_create(struct daemon* daemon, int id, int* ports, int n) +{ + unsigned int seed; + struct worker* worker = (struct worker*)calloc(1, + sizeof(struct worker)); + if(!worker) + return NULL; + worker->numports = n; + worker->ports = (int*)memdup(ports, sizeof(int)*n); + if(!worker->ports) { + free(worker); + return NULL; + } + worker->daemon = daemon; + worker->thread_num = id; + if(!(worker->cmd = tube_create())) { + free(worker->ports); + free(worker); + return NULL; + } + /* create random state here to avoid locking trouble in RAND_bytes */ + seed = (unsigned int)time(NULL) ^ (unsigned int)getpid() ^ + (((unsigned int)worker->thread_num)<<17); + /* shift thread_num so it does not match out pid bits */ + if(!(worker->rndstate = ub_initstate(seed, daemon->rand))) { + seed = 0; + log_err("could not init random numbers."); + tube_delete(worker->cmd); + free(worker->ports); + free(worker); + return NULL; + } + seed = 0; + return worker; +} + +int +worker_init(struct worker* worker, struct config_file *cfg, + struct listen_port* ports, int do_sigs) +{ + worker->need_to_exit = 0; + worker->base = comm_base_create(do_sigs); + if(!worker->base) { + log_err("could not create event handling base"); + worker_delete(worker); + return 0; + } + comm_base_set_slow_accept_handlers(worker->base, &worker_stop_accept, + &worker_start_accept, worker); + if(do_sigs) { +#ifdef SIGHUP + ub_thread_sig_unblock(SIGHUP); +#endif + ub_thread_sig_unblock(SIGINT); +#ifdef SIGQUIT + ub_thread_sig_unblock(SIGQUIT); +#endif + ub_thread_sig_unblock(SIGTERM); +#ifndef LIBEVENT_SIGNAL_PROBLEM + worker->comsig = comm_signal_create(worker->base, + worker_sighandler, worker); + if(!worker->comsig +#ifdef SIGHUP + || !comm_signal_bind(worker->comsig, SIGHUP) +#endif +#ifdef SIGQUIT + || !comm_signal_bind(worker->comsig, SIGQUIT) +#endif + || !comm_signal_bind(worker->comsig, SIGTERM) + || !comm_signal_bind(worker->comsig, SIGINT)) { + log_err("could not create signal handlers"); + worker_delete(worker); + return 0; + } +#endif /* LIBEVENT_SIGNAL_PROBLEM */ + if(!daemon_remote_open_accept(worker->daemon->rc, + worker->daemon->rc_ports, worker)) { + worker_delete(worker); + return 0; + } +#ifdef UB_ON_WINDOWS + wsvc_setup_worker(worker); +#endif /* UB_ON_WINDOWS */ + } else { /* !do_sigs */ + worker->comsig = NULL; + } + worker->front = listen_create(worker->base, ports, + cfg->msg_buffer_size, (int)cfg->incoming_num_tcp, + worker->daemon->listen_sslctx, worker_handle_request, worker); + if(!worker->front) { + log_err("could not create listening sockets"); + worker_delete(worker); + return 0; + } + worker->back = outside_network_create(worker->base, + cfg->msg_buffer_size, (size_t)cfg->outgoing_num_ports, + cfg->out_ifs, cfg->num_out_ifs, cfg->do_ip4, cfg->do_ip6, + cfg->do_tcp?cfg->outgoing_num_tcp:0, + worker->daemon->env->infra_cache, worker->rndstate, + cfg->use_caps_bits_for_id, worker->ports, worker->numports, + cfg->unwanted_threshold, &worker_alloc_cleanup, worker, + cfg->do_udp, worker->daemon->connect_sslctx); + if(!worker->back) { + log_err("could not create outgoing sockets"); + worker_delete(worker); + return 0; + } + /* start listening to commands */ + if(!tube_setup_bg_listen(worker->cmd, worker->base, + &worker_handle_control_cmd, worker)) { + log_err("could not create control compt."); + worker_delete(worker); + return 0; + } + worker->stat_timer = comm_timer_create(worker->base, + worker_stat_timer_cb, worker); + if(!worker->stat_timer) { + log_err("could not create statistics timer"); + } + + /* we use the msg_buffer_size as a good estimate for what the + * user wants for memory usage sizes */ + worker->scratchpad = regional_create_custom(cfg->msg_buffer_size); + if(!worker->scratchpad) { + log_err("malloc failure"); + worker_delete(worker); + return 0; + } + + server_stats_init(&worker->stats, cfg); + alloc_init(&worker->alloc, &worker->daemon->superalloc, + worker->thread_num); + alloc_set_id_cleanup(&worker->alloc, &worker_alloc_cleanup, worker); + worker->env = *worker->daemon->env; + comm_base_timept(worker->base, &worker->env.now, &worker->env.now_tv); + if(worker->thread_num == 0) + log_set_time(worker->env.now); + worker->env.worker = worker; + worker->env.send_query = &worker_send_query; + worker->env.alloc = &worker->alloc; + worker->env.rnd = worker->rndstate; + worker->env.scratch = worker->scratchpad; + worker->env.mesh = mesh_create(&worker->daemon->mods, &worker->env); + worker->env.detach_subs = &mesh_detach_subs; + worker->env.attach_sub = &mesh_attach_sub; + worker->env.kill_sub = &mesh_state_delete; + worker->env.detect_cycle = &mesh_detect_cycle; + worker->env.scratch_buffer = ldns_buffer_new(cfg->msg_buffer_size); + if(!(worker->env.fwds = forwards_create()) || + !forwards_apply_cfg(worker->env.fwds, cfg)) { + log_err("Could not set forward zones"); + worker_delete(worker); + return 0; + } + if(!(worker->env.hints = hints_create()) || + !hints_apply_cfg(worker->env.hints, cfg)) { + log_err("Could not set root or stub hints"); + worker_delete(worker); + return 0; + } + /* one probe timer per process -- if we have 5011 anchors */ + if(autr_get_num_anchors(worker->env.anchors) > 0 +#ifndef THREADS_DISABLED + && worker->thread_num == 0 +#endif + ) { + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 0; + worker->env.probe_timer = comm_timer_create(worker->base, + worker_probe_timer_cb, worker); + if(!worker->env.probe_timer) { + log_err("could not create 5011-probe timer"); + } else { + /* let timer fire, then it can reset itself */ + comm_timer_set(worker->env.probe_timer, &tv); + } + } + if(!worker->env.mesh || !worker->env.scratch_buffer) { + worker_delete(worker); + return 0; + } + worker_mem_report(worker, NULL); + /* if statistics enabled start timer */ + if(worker->env.cfg->stat_interval > 0) { + verbose(VERB_ALGO, "set statistics interval %d secs", + worker->env.cfg->stat_interval); + worker_restart_timer(worker); + } + return 1; +} + +void +worker_work(struct worker* worker) +{ + comm_base_dispatch(worker->base); +} + +void +worker_delete(struct worker* worker) +{ + if(!worker) + return; + if(worker->env.mesh && verbosity >= VERB_OPS) { + server_stats_log(&worker->stats, worker, worker->thread_num); + mesh_stats(worker->env.mesh, "mesh has"); + worker_mem_report(worker, NULL); + } + outside_network_quit_prepare(worker->back); + mesh_delete(worker->env.mesh); + ldns_buffer_free(worker->env.scratch_buffer); + forwards_delete(worker->env.fwds); + hints_delete(worker->env.hints); + listen_delete(worker->front); + outside_network_delete(worker->back); + comm_signal_delete(worker->comsig); + tube_delete(worker->cmd); + comm_timer_delete(worker->stat_timer); + comm_timer_delete(worker->env.probe_timer); + free(worker->ports); + if(worker->thread_num == 0) { + log_set_time(NULL); +#ifdef UB_ON_WINDOWS + wsvc_desetup_worker(worker); +#endif /* UB_ON_WINDOWS */ + } + comm_base_delete(worker->base); + ub_randfree(worker->rndstate); + alloc_clear(&worker->alloc); + regional_destroy(worker->scratchpad); + free(worker); +} + +/** compare outbound entry qstates */ +static int +outbound_entry_compare(void* a, void* b) +{ + struct outbound_entry* e1 = (struct outbound_entry*)a; + struct outbound_entry* e2 = (struct outbound_entry*)b; + if(e1->qstate == e2->qstate) + return 1; + return 0; +} + +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, + 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( + q->region, sizeof(*e)); + if(!e) + return NULL; + e->qstate = q; + e->qsent = outnet_serviced_query(worker->back, qname, + qnamelen, qtype, qclass, flags, dnssec, want_dnssec, + q->env->cfg->tcp_upstream, q->env->cfg->ssl_upstream, addr, + addrlen, zone, zonelen, worker_handle_service_reply, e, + worker->back->udp_buff, &outbound_entry_compare); + if(!e->qsent) { + return NULL; + } + return e; +} + +void +worker_alloc_cleanup(void* arg) +{ + struct worker* worker = (struct worker*)arg; + slabhash_clear(&worker->env.rrset_cache->table); + slabhash_clear(worker->env.msg_cache); +} + +void worker_stats_clear(struct worker* worker) +{ + server_stats_init(&worker->stats, worker->env.cfg); + mesh_stats_clear(worker->env.mesh); + worker->back->unwanted_replies = 0; +} + +void worker_start_accept(void* arg) +{ + struct worker* worker = (struct worker*)arg; + listen_start_accept(worker->front); + if(worker->thread_num == 0) + daemon_remote_start_accept(worker->daemon->rc); +} + +void worker_stop_accept(void* arg) +{ + struct worker* worker = (struct worker*)arg; + listen_stop_accept(worker->front); + if(worker->thread_num == 0) + daemon_remote_stop_accept(worker->daemon->rc); +} + +/* --- fake callbacks for fptr_wlist to work --- */ +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), + struct sockaddr_storage* ATTR_UNUSED(addr), + socklen_t ATTR_UNUSED(addrlen), struct module_qstate* ATTR_UNUSED(q)) +{ + log_assert(0); + return 0; +} + +int libworker_handle_reply(struct comm_point* ATTR_UNUSED(c), + void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), + struct comm_reply* ATTR_UNUSED(reply_info)) +{ + log_assert(0); + return 0; +} + +int libworker_handle_service_reply(struct comm_point* ATTR_UNUSED(c), + void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), + struct comm_reply* ATTR_UNUSED(reply_info)) +{ + log_assert(0); + return 0; +} + +void libworker_handle_control_cmd(struct tube* ATTR_UNUSED(tube), + uint8_t* ATTR_UNUSED(buffer), size_t ATTR_UNUSED(len), + int ATTR_UNUSED(error), void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + +void libworker_fg_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode), + ldns_buffer* ATTR_UNUSED(buf), enum sec_status ATTR_UNUSED(s), + char* ATTR_UNUSED(why_bogus)) +{ + log_assert(0); +} + +void libworker_bg_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode), + ldns_buffer* ATTR_UNUSED(buf), enum sec_status ATTR_UNUSED(s), + char* ATTR_UNUSED(why_bogus)) +{ + log_assert(0); +} + +int context_query_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b)) +{ + log_assert(0); + return 0; +} + +int order_lock_cmp(const void* ATTR_UNUSED(e1), const void* ATTR_UNUSED(e2)) +{ + log_assert(0); + return 0; +} + +int codeline_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b)) +{ + log_assert(0); + return 0; +} + diff --git a/daemon/worker.h b/daemon/worker.h new file mode 100644 index 00000000000..c510ebfd735 --- /dev/null +++ b/daemon/worker.h @@ -0,0 +1,234 @@ +/* + * daemon/worker.h - worker that handles a pending list of requests. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file describes the worker structure that holds a list of + * pending requests and handles them. + */ + +#ifndef DAEMON_WORKER_H +#define DAEMON_WORKER_H + +#include "util/netevent.h" +#include "util/locks.h" +#include "util/alloc.h" +#include "util/data/msgreply.h" +#include "util/data/msgparse.h" +#include "daemon/stats.h" +#include "util/module.h" +struct listen_dnsport; +struct outside_network; +struct config_file; +struct daemon; +struct listen_port; +struct ub_randstate; +struct regional; +struct tube; +struct daemon_remote; + +/** worker commands */ +enum worker_commands { + /** make the worker quit */ + worker_cmd_quit, + /** obtain statistics */ + worker_cmd_stats, + /** obtain statistics without statsclear */ + worker_cmd_stats_noreset, + /** execute remote control command */ + worker_cmd_remote +}; + +/** + * Structure holding working information for unbound. + * Holds globally visible information. + */ +struct worker { + /** the thread number (in daemon array). First in struct for debug. */ + int thread_num; + /** global shared daemon structure */ + struct daemon* daemon; + /** thread id */ + ub_thread_t thr_id; + /** pipe, for commands for this worker */ + struct tube* cmd; + /** the event base this worker works with */ + struct comm_base* base; + /** the frontside listening interface where request events come in */ + struct listen_dnsport* front; + /** the backside outside network interface to the auth servers */ + struct outside_network* back; + /** ports to be used by this worker. */ + int* ports; + /** number of ports for this worker */ + int numports; + /** the signal handler */ + struct comm_signal* comsig; + /** commpoint to listen to commands. */ + struct comm_point* cmd_com; + /** timer for statistics */ + struct comm_timer* stat_timer; + + /** random() table for this worker. */ + struct ub_randstate* rndstate; + /** do we need to restart or quit (on signal) */ + int need_to_exit; + /** allocation cache for this thread */ + struct alloc_cache alloc; + /** per thread statistics */ + struct server_stats stats; + /** thread scratch regional */ + struct regional* scratchpad; + + /** module environment passed to modules, changed for this thread */ + struct module_env env; +}; + +/** + * Create the worker structure. Bare bones version, zeroed struct, + * with backpointers only. Use worker_init on it later. + * @param daemon: the daemon that this worker thread is part of. + * @param id: the thread number from 0.. numthreads-1. + * @param ports: the ports it is allowed to use, array. + * @param n: the number of ports. + * @return: the new worker or NULL on alloc failure. + */ +struct worker* worker_create(struct daemon* daemon, int id, int* ports, int n); + +/** + * Initialize worker. + * Allocates event base, listens to ports + * @param worker: worker to initialize, created with worker_create. + * @param cfg: configuration settings. + * @param ports: list of shared query ports. + * @param do_sigs: if true, worker installs signal handlers. + * @return: false on error. + */ +int worker_init(struct worker* worker, struct config_file *cfg, + struct listen_port* ports, int do_sigs); + +/** + * Make worker work. + */ +void worker_work(struct worker* worker); + +/** + * Delete worker. + */ +void worker_delete(struct worker* worker); + +/** + * Send a command to a worker. Uses blocking writes. + * @param worker: worker to send command to. + * @param cmd: command to send. + */ +void worker_send_cmd(struct worker* worker, enum worker_commands cmd); + +/** + * Worker signal handler function. User argument is the worker itself. + * @param sig: signal number. + * @param arg: the worker (main worker) that handles signals. + */ +void worker_sighandler(int sig, void* arg); + +/** + * Worker service routine to send serviced queries to authoritative servers. + * @param qname: query name. (host order) + * @param qnamelen: length in bytes of qname, including trailing 0. + * @param qtype: query type. (host order) + * @param qclass: query class. (host order) + * @param flags: host order flags word, with opcode and CD bit. + * @param dnssec: if set, EDNS record will have DO bit set. + * @param want_dnssec: signatures needed. + * @param addr: where to. + * @param addrlen: length of addr. + * @param zone: wireformat dname of the zone. + * @param zonelen: length of zone name. + * @param q: wich query state to reactivate upon return. + * @return: false on failure (memory or socket related). no query was + * sent. + */ +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, 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 + * command message. + * @param tube: tube control message came on. + * @param msg: message contents. Is freed. + * @param len: length of message. + * @param error: if error (NETEVENT_*) happened. + * @param arg: user argument + */ +void worker_handle_control_cmd(struct tube* tube, uint8_t* msg, size_t len, + int error, void* arg); + +/** handles callbacks from listening event interface */ +int worker_handle_request(struct comm_point* c, void* arg, int error, + struct comm_reply* repinfo); + +/** process incoming replies from the network */ +int worker_handle_reply(struct comm_point* c, void* arg, int error, + struct comm_reply* reply_info); + +/** process incoming serviced query replies from the network */ +int worker_handle_service_reply(struct comm_point* c, void* arg, int error, + struct comm_reply* reply_info); + +/** cleanup the cache to remove all rrset IDs from it, arg is worker */ +void worker_alloc_cleanup(void* arg); + +/** + * Init worker stats - includes server_stats_init, outside network and mesh. + * @param worker: the worker to init + */ +void worker_stats_clear(struct worker* worker); + +/** statistics timer callback handler */ +void worker_stat_timer_cb(void* arg); + +/** probe timer callback handler */ +void worker_probe_timer_cb(void* arg); + +/** start accept callback handler */ +void worker_start_accept(void* arg); + +/** stop accept callback handler */ +void worker_stop_accept(void* arg); + +#endif /* DAEMON_WORKER_H */ diff --git a/doc/CREDITS b/doc/CREDITS new file mode 100644 index 00000000000..429a799d6b0 --- /dev/null +++ b/doc/CREDITS @@ -0,0 +1,21 @@ +Unbound was developed at NLnet Labs by Wouter Wijngaards. + +Unbound was architected in January of 2004 by Jakob Schlyter of Kirei +and Roy Arends of Nominet. VeriSign and EP.Net funded development of +the prototype, which was built by David Blacka and Matt Larson of VeriSign. +Late in 2006, NLnet Labs joined the effort, writing an implementation in C +based on the existing prototype and using experience NLnet Labs gained +during the development of NSD, an authoritative DNS server. + +At NLnet Labs, Jelte Jansen, Mark Santcroos and Matthijs Mekking +reviewed the unbound C sources. + +Jakob Schlyter - for advice on secure settings, random numbers and blacklists. +Ondřej Surý - running coverity analysis tool on 0.9 dev version. +Alexander Gall - multihomed, anycast testing of unbound resolver server. +Zdenek Vasicek and Marek Vavrusa - python module. +cz.nic - sponsoring 'summer of code' development by Zdenek and Marek. +Brett Carr - windows beta testing. +Luca Bruno - patch for windows support in libunbound hosts and resolvconf(). +Tom Hendrikx - contributed split-itar.sh a useful script to 5011-track ITAR. +Daisuke HIGASHI - patch for rrset-roundrobin and minimal-responses. diff --git a/doc/Changelog b/doc/Changelog new file mode 100644 index 00000000000..3b2753f818d --- /dev/null +++ b/doc/Changelog @@ -0,0 +1,4780 @@ +24 May 2012: Wouter + - tag for 1.4.17 release. + +18 May 2012: Wouter + - Review comments, removed duplicate memset to zero in delegpt. + +16 May 2012: Wouter + - Updated doc/FEATURES with RFCs that are implemented but not listed. + - Protect if statements in val_anchor for compile without locks. + - tag for 1.4.17rc1. + +15 May 2012: Wouter + - fix configure ECDSA support in ldns detection for windows compile. + - fix possible uninitialised variable in windows pipe implementation. + +9 May 2012: Wouter + - Fix alignment problem in util/random on sparc64/freebsd. + +8 May 2012: Wouter + - Fix for accept spinning reported by OpenBSD. + - iana portlist updated. + +2 May 2012: Wouter + - Fix validation of nodata for DS query in NSEC zones, reported by + Ondrej Mikle. + +13 April 2012: Wouter + - ECDSA support (RFC 6605) by default. Use --disable-ecdsa for older + openssl. + +10 April 2012: Wouter + - Applied patch from Daisuke HIGASHI for rrset-roundrobin and + minimal-responses features. + - iana portlist updated. + +5 April 2012: Wouter + - fix bug #443: --with-chroot-dir not honoured by configure. + - fix bug #444: setusercontext was called too late (thanks Bjorn + Ketelaars). + +27 March 2012: Wouter + - fix bug #442: Fix that Makefile depends on pythonmod headers + even using --without-pythonmodule. + +22 March 2012: Wouter + - contrib/validation-reporter follows rotated log file (patch from + Augie Schwer). + +21 March 2012: Wouter + - new approach to NS fetches for DS lookup that works with + cornercases, and is more robust and considers forwarders. + +19 March 2012: Wouter + - iana portlist updated. + - fix to locate nameservers for DS lookup with NS fetches. + +16 March 2012: Wouter + - Patch for access to full DNS packet data in unbound python module + from Ondrej Mikle. + +9 March 2012: Wouter + - Applied line-buffer patch from Augie Schwer to validation.reporter.sh. + +2 March 2012: Wouter + - flush_infra cleans timeouted servers from the cache too. + - removed warning from --enable-ecdsa. + +1 March 2012: Wouter + - forward-first option. Tries without forward if a query fails. + Also stub-first option that is similar. + +28 February 2012: Wouter + - Fix from code review, if EINPROGRESS not defined chain if statement + differently. + +27 February 2012: Wouter + - Fix bug#434: on windows check registry for config file location + for unbound-control.exe, and unbound-checkconf.exe. + +23 February 2012: Wouter + - Fix to squelch 'network unreachable' errors from tcp connect in + logs, high verbosity will show them. + +16 February 2012: Wouter + - iter_hints is now thread-owned in module env, and thus threadsafe. + - Fix prefetch and sticky NS, now the prefetch works. It picks + nameservers that 'would be valid in the future', and if this makes + the NS timeout, it updates that NS by asking delegation from the + parent again. If child NS has longer TTL, that TTL does not get + refreshed from the lookup to the child nameserver. + +15 February 2012: Wouter + - Fix forward-zone memory, uses malloc and frees original root dp. + - iter hints (stubs) uses malloc inside for more dynamicity. + - unbound-control forward_add, forward_remove, stub_add, stub_remove + can modify stubs and forwards for running unbound (on mobile computer) + they can also add and remove domain-insecure for the zone. + +14 February 2012: Wouter + - Fix sticky NS (ghost domain problem) if prefetch is yes. + - iter forwards uses malloc inside for more dynamicity. + +13 February 2012: Wouter + - RT#2955. Fix for cygwin compilation. + - iana portlist updated. + +10 February 2012: Wouter + - Slightly smaller critical region in one case in infra cache. + - Fix timeouts to keep track of query type, A, AAAA and other, if + another has caused timeout blacklist, different type can still probe. + - unit test fix for nomem_cnametopos.rpl race condition. + +9 February 2012: Wouter + - Fix AHX_BROKEN_MEMCMP for autoheader mess up of #undef in config.h. + +8 February 2012: Wouter + - implement draft-ietf-dnsext-ecdsa-04; which is in IETF LC; This + implementation is experimental at this time and not recommended + for use on the public internet (the protocol numbers have not + been assigned). Needs recent ldns with --enable-ecdsa. + - fix memory leak in errorcase for DSA signatures. + - iana portlist updated. + - workaround for openssl 0.9.8 ecdsa sha2 and evp problem. + +3 February 2012: Wouter + - fix for windows, rename() is not posix compliant on windows. + +2 February 2012: Wouter + - 1.4.16 release tag. + - svn trunk is 1.4.17 in development. + - iana portlist updated. + +1 February 2012: Wouter + - Fix validation failures (like: validation failure xx: no NSEC3 + closest encloser from yy for DS zz. while building chain of trust, + because of a bug in the TTL-fix in 1.4.15, it picked the wrong rdata + for an NSEC3. Now it does not change rdata, and fixes TTL. + +30 January 2012: Wouter + - Fix version-number in libtool to be version-info so it produces + libunbound.so.2 like it should. + +26 January 2012: Wouter + - Tag 1.4.15 (same as 1.4.15rc1), for 1.4.15 release. + - trunk 1.4.16; includes changes memset testcode, #424 openindiana, + and keyfile write fixup. + - applied patch to support outgoing-interface with ub_ctx_set_option. + +23 January 2012: Wouter + - Fix memset in test code. + +20 January 2012: Wouter + - Fix bug #424: compile on OpenIndiana OS with gcc 4.6.2. + +19 January 2012: Wouter + - Fix to write key files completely to a temporary file, and if that + succeeds, replace the real key file. So failures leave a useful file. + +18 January 2012: Wouter + - tag 1.4.15rc1 created + - updated libunbound/ubsyms.def and remade tag 1.4.15rc1. + +17 January 2012: Wouter + - Fix bug where canonical_compare of RRSIG did not downcase the + signer-name. This is mostly harmless because RRSIGs do not have + to be sorted in canonical order, usually. + +12 January 2012: Wouter + - bug#428: add ub_version() call to libunbound. API version increase, + with (binary) backwards compatibility for the previous version. + +10 January 2012: Wouter + - Fix bug #425: unbound reports wrong TTL in reply, it reports a TTL + that would be permissible by the RFCs but it is not the TTL in the + cache. + - iana portlist updated. + - uninitialised variable in reprobe for rtt blocked domains fixed. + - lintfix and new flex output. + +2 January 2012: Wouter + - Fix to randomize hash function, based on 28c3 congress, reported + by Peter van Dijk. + +24 December 2011: Wouter + - Fix for memory leak (about 20 bytes when a tcp or udp send operation + towards authority servers failed, takes about 50.000 such failures to + leak one Mb, such failures are also usually logged), reported by + Robert Fleischmann. + - iana portlist updated. + +19 December 2011: Wouter + - Fix for VU#209659 CVE-2011-4528: Unbound denial of service + vulnerabilities from nonstandard redirection and denial of existence + http://www.unbound.net/downloads/CVE-2011-4528.txt + - robust checks for next-closer NSEC3s. + - tag 1.4.14 created. + - trunk has 1.4.15 in development. + +15 December 2011: Wouter + - remove uninit warning from cachedump code. + - Fix parse error on negative SOA RRSIGs if badly ordered in the packet. + +13 December 2011: Wouter + - iana portlist updated. + - svn tag 1.4.14rc1 + - fix infra cache comparison. + - Fix to constrain signer_name to be a parent of the lookupname. + +5 December 2011: Wouter + - Fix getaddrinfowithincludes on windows with fedora16 mingw32-gcc. + - Fix warnings with gcc 4.6 in compat/inet_ntop.c. + - Fix warning unused in compat/strptime.c. + - Fix malloc detection and double defintion. + +2 December 2011: Wouter + - configure generated with autoconf 2.68. + +30 November 2011: Wouter + - Fix for tcp-upstream and ssl-upstream for if a laptop sleeps, causes + SERVFAILs. Also fixed for UDP (but less likely). + +28 November 2011: Wouter + - Fix quartile time estimate, it was too low, (thanks Jan Komissar). + - iana ports updated. + +11 November 2011: Wouter + - Makefile compat with SunOS make, BSD make and GNU make. + - iana ports updated. + +10 November 2011: Wouter + - Makefile changed for BSD make compatibility. + +9 November 2011: Wouter + - added unit test for SSL service and SSL-upstream. + +8 November 2011: Wouter + - can configure ssl service to one port number, and not on others. + - fixup windows compile with ssl support. + - Fix double free in unbound-host, reported by Steve Grubb. + - iana portlist updated. + +1 November 2011: Wouter + - dns over ssl support as a client, ssl-upstream yes turns it on. + It performs an SSL transaction for every DNS query (250 msec). + - documentation for new options: ssl-upstream, ssl-service-key and + ssl-service.pem. + - iana portlist updated. + - fix -flto detection on Lion for llvm-gcc. + +31 October 2011: Wouter + - dns over ssl support, ssl-service-pem and ssl-service-key files + can be given and then TCP queries are serviced wrapped in SSL. + +27 October 2011: Wouter + - lame-ttl and lame-size options no longer exist, it is integrated + with the host info. They are ignored (with verbose warning) if + encountered to keep the config file backwards compatible. + - fix iana-update for changing gzip compression of results. + - fix export-all-symbols on OSX. + +26 October 2011: Wouter + - iana portlist updated. + - Infra cache stores information about ping and lameness per IP, zone. + This fixes bug #416. + - fix iana_update target for gzipped file on iana site. + +24 October 2011: Wouter + - Fix resolve of partners.extranet.microsoft.com with a fix for the + server selection for choosing out of a (particular) list of bad + choices. (bug#415) + - Fix make_new_space function so that the incoming query is not + overwritten if a jostled out query causes a waiting query to be + resumed that then fails and sends an error message. (Thanks to + Matthew Lee). + +21 October 2011: Wouter + - fix --enable-allsymbols, fptr wlist is disabled on windows with this + option enabled because of memory layout exe vs dll. + +19 October 2011: Wouter + - fix unbound-anchor for broken strptime on OSX lion, detected + in configure. + - Detect if GOST really works, openssl1.0 on OSX fails. + - Implement ipv6%interface notation for scope_id usage. + +17 October 2011: Wouter + - better documentation for inform_super (Thanks Yang Zhe). + +14 October 2011: Wouter + - Fix for out-of-memory condition in libunbound (thanks + Robert Fleischman). + +13 October 2011: Wouter + - Fix --enable-allsymbols, it depended on link specifics of the + target platform, or fptr_wlist assertion failures could occur. + +12 October 2011: Wouter + - updated contrib/unbound_munin_ to family=auto so that it works with + munin-node-configure automatically (if installed as + /usr/local/share/munin/plugins/unbound_munin_ ). + +27 September 2011: Wouter + - unbound.exe -w windows option for start and stop service. + +23 September 2011: Wouter + - TCP-upstream calculates tcp-ping so server selection works if there + are alternatives. + +20 September 2011: Wouter + - Fix classification of NS set in answer section, where there is a + parent-child server, and the answer has the AA flag for dir.slb.com. + Thanks to Amanda Constant from Secure64. + +16 September 2011: Wouter + - fix bug #408: accept patch from Steve Snyder that comments out + unused functions in lookup3.c. + - iana portlist updated. + - fix EDNS1480 change memleak and TCP fallback. + - fix various compiler warnings (reported by Paul Wouters). + - max sent count. EDNS1480 only for rtt < 5000. No promiscuous + fetch if sentcount > 3, stop query if sentcount > 16. Count is + reset when referral or CNAME happens. This makes unbound better + at managing large NS sets, they are explored when there is continued + interest (in the form of queries). + +15 September 2011: Wouter + - release 1.4.13. + - trunk contains 1.4.14 in development. + - Unbound probes at EDNS1480 if there an EDNS0 timeout. + +12 September 2011: Wouter + - Reverted dns EDNS backoff fix, it did not help and needs + fragmentation fixes instead. + - tag 1.4.13rc2 + +7 September 2011: Wouter + - Fix operation in ipv6 only (do-ip4: no) mode. + +6 September 2011: Wouter + - fedora specfile updated. + +5 September 2011: Wouter + - tag 1.4.13rc1 + +2 September 2011: Wouter + - iana portlist updated. + +26 August 2011: Wouter + - Fix num-threads 0 does not segfault, reported by Simon Deziel. + - Fix validation failures due to EDNS backoff retries, the retry + for fetch of data has want_dnssec because the iter_indicate_dnssec + function returns true when validation failure retry happens, and + then the serviced query code does not fallback to noEDNS, even if + the cache says it has this. This helps for DLV deployment when + the DNSSEC status is not known for sure before the lookup concludes. + +24 August 2011: Wouter + - Applied patch from Karel Slany that fixes a memory leak in the + unbound python module, in string conversions. + +22 August 2011: Wouter + - Fix validation of qtype ANY responses with CNAMEs (thanks Cathy + Zhang and Luo Ce). Unbound responds with the RR types that are + available at the name for qtype ANY and validates those RR types. + It does not test for completeness (i.e. with NSEC or NSEC3 query), + and it does not follow the CNAME or DNAME to another name (with + even more data for the already large response). + - Fix that internally, CNAMEs with NXDOMAIN have that as rcode. + - Documented the options that work with control set_option command. + - tcp-upstream yes/no option (works with set_option) for tunnels. + +18 August 2011: Wouter + - fix autoconf call in makedist crosscompile to RC or snapshot. + +17 August 2011: Wouter + - Fix validation of . DS query. + - new xml format at IANA, new awk for iana_update. + - iana portlist updated. + +10 August 2011: Wouter + - Fix python site-packages path to /usr/lib64. + - updated patch from Tom. + - fix memory and fd leak after out-of-memory condition. + +9 August 2011: Wouter + - patch from Tom Hendrikx fixes load of python modules. + +8 August 2011: Wouter + - make clean had ldns-src reference, removed. + +1 August 2011: Wouter + - Fix autoconf 2.68 warnings + +14 July 2011: Wouter + - Unbound implements RFC6303 (since version 1.4.7). + - tag 1.4.12rc1 is released as 1.4.12 (without the other fixes in the + meantime, those are for 1.4.13). + - iana portlist updated. + +13 July 2011: Wouter + - Quick fix for contrib/unbound.spec example, no ldns-builtin any more. + +11 July 2011: Wouter + - Fix wildcard expansion no-data reply under an optout NSEC3 zone is + validated as insecure, reported by Jia Li (lijia@cnnic.cn). + +4 July 2011: Wouter + - 1.4.12rc1 tag created. + +1 July 2011: Wouter + - version number in example config file. + - fix that --enable-static-exe does not complain about it unknown. + +30 June 2011: Wouter + - tag relase 1.4.11, trunk is 1.4.12 development. + - iana portlist updated. + - fix bug#395: id bits of other query may leak out under conditions + - fix replyaddr count wrong after jostled queries, which leads to + eventual starvation where the daemon has no replyaddrs left to use. + - fix comment about rndc port, that referred to the old port number. + - fix that the listening socket is not closed when too many remote + control connections are made at the same time. + - removed ldns-src tarball inside the unbound tarball. + +23 June 2011: Wouter + - Changed -flto check to support clang compiler. + - tag 1.4.11rc3 created. + +17 June 2011: Wouter + - tag 1.4.11rc1 created. + - remove warning about signed/unsigned from flex (other flex version). + - updated aclocal.m4 and libtool to match. + - tag 1.4.11rc2 created. + +16 June 2011: Wouter + - log-queries: yesno option, default is no, prints querylog. + - version is 1.4.11. + +14 June 2011: Wouter + - Use -flto compiler flag for link time optimization, if supported. + - iana portlist updated. + +12 June 2011: Wouter + - IPv6 service address for d.root-servers.net (2001:500:2D::D). + +10 June 2011: Wouter + - unbound-control has version number in the header, + UBCT[version]_space_ is the header sent by the client now. + - Unbound control port number is registered with IANA: + ub-dns-control 8953/tcp unbound dns nameserver control + This is the new default for the control-port config setting. + - statistics-interval prints the number of jostled queries to log. + +30 May 2011: Wouter + - Fix Makefile for U in environment, since wrong U is more common than + deansification necessity. + - iana portlist updated. + - updated ldns tarball to 1.6.10rc2 snapshot of today. + +25 May 2011: Wouter + - Fix assertion failure when unbound generates an empty error reply + in response to a query, CVE-2011-1922 VU#531342. + - This fix is in tag 1.4.10. + - defense in depth against the above bug, an error is printed to log + instead of an assertion failure. + +10 May 2011: Wouter + - bug#386: --enable-allsymbols option links all binaries to libunbound + and reduces install size significantly. + - feature, ignore-cd-flag: yesno to provide dnssec to legacy servers. + - iana portlist updated. + - Fix TTL of SOA so negative TTL is separately cached from normal TTL. + +14 April 2011: Wouter + - configure created with newer autoconf 2.66. + +12 April 2011: Wouter + - bug#378: Fix that configure checks for ldns_get_random presence. + +8 April 2011: Wouter + - iana portlist updated. + - queries with CD flag set cause DNSSEC validation, but the answer is + not withheld if it is bogus. Thus, unbound will retry if it is bad + and curb the TTL if it is bad, thus protecting the cache for use by + downstream validators. + - val-override-date: -1 ignores dates entirely, for NTP usage. + +29 March 2011: Wouter + - harden-below-nxdomain: changed so that it activates when the + cached nxdomain is dnssec secure. This avoids backwards + incompatibility because those old servers do not have dnssec. + +24 March 2011: Wouter + - iana portlist updated. + - release 1.4.9. + - trunk is 1.5.0 + +17 March 2011: Wouter + - bug#370: new unbound.spec for CentOS 5.x from Harold Jones. + Applied but did not do the --disable-gost. + +10 March 2011: Wouter + - tag 1.4.9 release candidate 1 created. + +3 March 2011: Wouter + - updated ldns to today. + +1 March 2011: Wouter + - Fix no ADflag for NXDOMAIN in NSEC3 optout. And wildcard in optout. + - give config parse error for multiple names on a stub or forward zone. + - updated ldns tarball to 1.6.9(todays snapshot). + +24 February 2011: Wouter + - bug #361: Fix, time.elapsed variable not reset with stats_noreset. + +23 February 2011: Wouter + - iana portlist updated. + - common.sh to version 3. + +18 February 2011: Wouter + - common.sh in testdata updated to version 2. + +15 February 2011: Wouter + - Added explicit note on unbound-anchor usage: + Please note usage of unbound-anchor root anchor is at your own risk + and under the terms of our LICENSE (see that file in the source). + +11 February 2011: Wouter + - iana portlist updated. + - tpkg updated with common.sh for common functionality. + +7 February 2011: Wouter + - Added regression test for addition of a .net DS to the root, and + cache effects with different TTL for glue and DNSKEY. + - iana portlist updated. + +28 January 2011: Wouter + - Fix remove private address does not throw away entire response. + +24 January 2011: Wouter + - release 1.4.8 + +19 January 2011: Wouter + - fix bug#349: no -L/usr for ldns. + +18 January 2011: Wouter + - ldns 1.6.8 tarball included. + - release 1.4.8rc1. + +17 January 2011: Wouter + - add get and set option for harden-below-nxdomain feature. + - iana portlist updated. + +14 January 2011: Wouter + - Fix so a changed NS RRset does not get moved name stuck on old + server, for type NS the TTL is not increased. + +13 January 2011: Wouter + - Fix prefetch so it does not get stuck on old server for moved names. + +12 January 2011: Wouter + - iana portlist updated. + +11 January 2011: Wouter + - Fix insecure CNAME sequence marked as secure, reported by Bert + Hubert. + +10 January 2011: Wouter + - faster lruhash get_mem routine. + +4 January 2011: Wouter + - bug#346: remove ITAR scripts from contrib, the service is discontinued, use the root. + - iana portlist updated. + +23 December 2010: Wouter + - Fix in infra cache that could cause rto larger than TOP_TIMEOUT kept. + +21 December 2010: Wouter + - algorithm compromise protection using the algorithms signalled in + the DS record. Also, trust anchors, DLV, and RFC5011 receive this, + and thus, if you have multiple algorithms in your trust-anchor-file + then it will now behave different than before. Also, 5011 rollover + for algorithms needs to be double-signature until the old algorithm + is revoked. + It is not an option, because I see no use to turn the security off. + - iana portlist updated. + +17 December 2010: Wouter + - squelch 'tcp connect: bla' in logfile, (set verbosity 2 to see them). + - fix validation in this case: CNAME to nodata for co-hosted opt-in + NSEC3 insecure delegation, was bogus, fixed to be insecure. + +16 December 2010: Wouter + - Fix our 'BDS' license (typo reported by Xavier Belanger). + +10 December 2010: Wouter + - iana portlist updated. + - review changes for unbound-anchor. + +2 December 2010: Wouter + - feature typetransparent localzone, does not block other RR types. + +1 December 2010: Wouter + - Fix bug#338: print address when socket creation fails. + +30 November 2010: Wouter + - Fix storage of EDNS failures in the infra cache. + - iana portlist updated. + +18 November 2010: Wouter + - harden-below-nxdomain option, default off (because very old + software may be incompatible). We could enable it by default in + the future. + +17 November 2010: Wouter + - implement draft-vixie-dnsext-resimprove-00, we stop on NXDOMAIN. + - make test output nicer. + +15 November 2010: Wouter + - silence 'tcp connect: broken pipe' and 'net down' at low verbosity. + - iana portlist updated. + - so-sndbuf option for very busy servers, a bit like so-rcvbuf. + +9 November 2010: Wouter + - unbound-anchor compiles with openssl 0.9.7. + +8 November 2010: Wouter + - release tag 1.4.7. + - trunk is version 1.4.8. + - Be lenient and accept imgw.pl malformed packet (like BIND). + +5 November 2010: Wouter + - do not synthesize a CNAME message from cache for qtype DS. + +4 November 2010: Wouter + - Use central entropy to seed threads. + +3 November 2010: Wouter + - Change the rtt used to probe EDNS-timeout hosts to 1000 msec. + +2 November 2010: Wouter + - tag 1.4.7rc1. + - code review. + +1 November 2010: Wouter + - GOST code enabled by default (RFC 5933). + +27 October 2010: Wouter + - Fix uninit value in dump_infra print. + - Fix validation failure for parent and child on same server with an + insecure childzone and a CNAME from parent to child. + - Configure detects libev-4.00. + +26 October 2010: Wouter + - dump_infra and flush_infra commands for unbound-control. + - no timeout backoff if meanwhile a query succeeded. + - Change of timeout code. No more lost and backoff in blockage. + At 12sec timeout (and at least 2x lost before) one probe per IP + is allowed only. At 120sec, the IP is blocked. After 15min, a + 120sec entry has a single retry packet. + +25 October 2010: Wouter + - Configure errors if ldns is not found. + +22 October 2010: Wouter + - Windows 7 fix for the installer. + +21 October 2010: Wouter + - Fix bug where fallback_tcp causes wrong roundtrip and edns + observation to be noted in cache. Fix bug where EDNSprobe halted + exponential backoff if EDNS status unknown. + - new unresponsive host method, exponentially increasing block backoff. + - iana portlist updated. + +20 October 2010: Wouter + - interface automatic works for some people with ip6 disabled. + Therefore the error check is removed, so they can use the option. + +19 October 2010: Wouter + - Fix for request list growth, if a server has long timeout but the + lost counter is low, then its effective rtt is the one without + exponential backoff applied. Because the backoff is not working. + The lost counter can then increase and the server is blacklisted, + or the lost counter does not increase and the server is working + for some queries. + +18 October 2010: Wouter + - iana portlist updated. + +13 October 2010: Wouter + - Fix TCP so it uses a random outgoing-interface. + - unbound-anchor handles ADDPEND keystate. + +11 October 2010: Wouter + - Fix bug when DLV below a trust-anchor that uses NSEC3 optout where + the zone has a secure delegation hosted on the same server did not + verify as secure (it was insecure by mistake). + - iana portlist updated. + - ldns tarball updated (for reading cachedumps with bad RR data). + +1 October 2010: Wouter + - test for unbound-anchor. fix for reading certs. + - Fix alloc_reg_release for longer uptime in out of memory conditions. + +28 September 2010: Wouter + - unbound-anchor working, it creates or updates a root.key file. + Use it before you start the validator (e.g. at system boot time). + +27 September 2010: Wouter + - iana portlist updated. + +24 September 2010: Wouter + - bug#329: in example.conf show correct ipv4 link-local 169.254/16. + +23 September 2010: Wouter + - unbound-anchor app, unbound requires libexpat (xml parser library). + +22 September 2010: Wouter + - compliance with draft-ietf-dnsop-default-local-zones-14, removed + reverse ipv6 orchid prefix from builtin list. + - iana portlist updated. + +17 September 2010: Wouter + - DLV has downgrade protection again, because the RFC says so. + - iana portlist updated. + +16 September 2010: Wouter + - Algorithm rollover operational reality intrudes, for trust-anchor, + 5011-store, and DLV-anchor if one key matches it's good enough. + - iana portlist updated. + - Fix reported validation error in out of memory condition. + +15 September 2010: Wouter + - Abide RFC5155 section 9.2: no AD flag for replies with NSEC3 optout. + +14 September 2010: Wouter + - increased mesh-max-activation from 1000 to 3000 for crazy domains + like _tcp.slb.com with 262 servers. + - iana portlist updated. + +13 September 2010: Wouter + - bug#327: Fix for cannot access stub zones until the root is primed. + +9 September 2010: Wouter + - unresponsive servers are not completely blacklisted (because of + firewalls), but also not probed all the time (because of the request + list size it generates). The probe rate is 1%. + - iana portlist updated. + +20 August 2010: Wouter + - openbsd-lint fixes: acl_list_get_mem used if debug-alloc enabled. + iterator get_mem includes priv_get_mem. delegpt nodup removed. + listen_pushback, query_info_allocqname, write_socket, send_packet, + comm_point_set_cb_arg and listen_resume removed. + +19 August 2010: Wouter + - Fix bug#321: resolution of rs.ripe.net artifacts with 0x20. + Delegpt structures checked for duplicates always. + No more nameserver lookups generated when depth is full anyway. + - example.conf notes how to do DNSSEC validation and track the root. + - iana portlist updated. + +18 August 2010: Wouter + - Fix bug#322: configure does not respect CFLAGS on Solaris. + Pass CFLAGS="-xO4 -xtarget=generic" on the configure command line + if use sun-cc, but some systems need different flags. + +16 August 2010: Wouter + - Fix acx_nlnetlabs.m4 configure output for autoconf-2.66 AS_TR_CPP + changes, uses m4_bpatsubst now. + - make test (or make check) should be more portable and run the unit + test and testbound scripts. (make longtest has special requirements). + +13 August 2010: Wouter + - More pleasant remote control command parsing. + - documentation added for return values reported by doxygen 1.7.1. + - iana portlist updated. + +9 August 2010: Wouter + - Fix name of rrset printed that failed validation. + +5 August 2010: Wouter + - Return NXDOMAIN after chain of CNAMEs ends at name-not-found. + +4 August 2010: Wouter + - Fix validation in case a trust anchor enters into a zone with + unsupported algorithms. + +3 August 2010: Wouter + - updated ldns tarball with bugfixes. + - release tag 1.4.6. + - trunk becomes 1.4.7 develop. + - iana portlist updated. + +22 July 2010: Wouter + - more error details on failed remote control connection. + +15 July 2010: Wouter + - rlimit adjustments for select and ulimit can happen at the same time. + +14 July 2010: Wouter + - Donation text added to README. + - Fix integer underflow in prefetch ttl creation from cache. This + fixes a potential negative prefetch ttl. + +12 July 2010: Wouter + - Changed the defaults for num-queries-per-thread/outgoing-range. + For builtin-select: 512/960, for libevent 1024/4096 and for + windows 24/48 (because of win api). This makes the ratio this way + to improve resilience under heavy load. For high performance, use + libevent and possibly higher numbers. + +10 July 2010: Wouter + - GOST enabled if SSL is recent and ldns has GOST enabled too. + - ldns tarball updated. + +9 July 2010: Wouter + - iana portlist updated. + - Fix validation of qtype DNSKEY when a key-cache entry exists but + no rr-cache entry is used (it expired or prefetch), it then goes + back up to the DS or trust-anchor to validate the DNSKEY. + +7 July 2010: Wouter + - Neat function prototypes, unshadowed local declarations. + +6 July 2010: Wouter + - failure to chown the pidfile is not fatal any more. + - testbound uses UTC timezone. + - ldns tarball updated (ports and works on Minix 3.1.7). On Minix, add + /usr/gnu/bin to PATH, use ./configure AR=/usr/gnu/bin/gar and gmake. + +5 July 2010: Wouter + - log if a server is skipped because it is on the donotquery list, + at verbosity 4, to enable diagnosis why no queries to 127.0.0.1. + - added feature to print configure date, target and options with -h. + - added feature to print event backend system details with -h. + - wdiff is not actually required by make test, updated requirements. + +1 July 2010: Wouter + - Fix RFC4035 compliance with 2.2 statement that the DNSKEY at apex + must be signed with all algorithms from the DS rrset at the parent. + This is now checked and becomes bogus if not. + +28 June 2010: Wouter + - Fix jostle list bug found by Vince (luoce@cnnic), it caused the qps + in overload situations to be about 5 qps for the class of shortly + serviced queries. + The capacity of the resolver is then about (numqueriesperthread / 2) + / (average time for such long queries) qps for long queries. + And about (numqueriesperthread / 2)/(jostletimeout in whole seconds) + qps for short queries, per thread. + - Fix the max number of reply-address count to be applied for duplicate + queries, and not for new query list entries. This raises the memory + usage to a max of (16+1)*numqueriesperthread reply addresses. + +25 June 2010: Wouter + - Fix handling of corner case reply from lame server, follows rfc2308. + It could lead to a nodata reply getting into the cache if the search + for a non-lame server turned up other misconfigured servers. + - unbound.h has extern "C" statement for easier include in c++. + +23 June 2010: Wouter + - iana portlist updated. + - makedist upgraded cross compile openssl option, like this: + ./makedist.sh -s -wssl openssl-1.0.0a.tar.gz -w --enable-gost + +22 June 2010: Wouter + - Unbound reports libev or libevent correctly in logs in verbose mode. + - Fix to unload gost dynamic library module for leak testing. + +18 June 2010: Wouter + - iana portlist updated. + +17 June 2010: Wouter + - Add AAAA to root hints for I.ROOT-SERVERS.NET. + +16 June 2010: Wouter + - Fix assertion failure reported by Kai Storbeck from XS4ALL, the + assertion was wrong. + - updated ldns tarball. + +15 June 2010: Wouter + - tag 1.4.5 created. + - trunk contains 1.4.6 in development. + - Fix TCPreply on systems with no writev, if just 1 byte could be sent. + - Fix to use one pointer less for iterator query state store_parent_NS. + - makedist crosscompile to windows uses builtin ldns not host ldns. + - Max referral count from 30 to 130, because 128 one character domains + is valid DNS. + - added documentation for the histogram printout to syslog. + +11 June 2010: Wouter + - When retry to parent the retrycount is not wiped, so failed + nameservers are not tried again. + - iana portlist updated. + +10 June 2010: Wouter + - Fix bug where a long loop could be entered, now cycle detection + has a loop-counter and maximum search amount. + +4 June 2010: Wouter + - iana portlist updated. + - 1.4.5rc1 tag created. + +3 June 2010: Wouter + - ldns tarball updated, 1.6.5. + - review comments, split dependency cycle tracking for parentside + last resort lookups for A and AAAA so there are more lookup options. + +2 June 2010: Wouter + - Fix compile warning if compiled without threads. + - updated ldns-tarball with current ldns svn (pre 1.6.5). + - GOST disabled-by-default, the algorithm number is allocated but the + RFC is still has to pass AUTH48 at the IETF. + +1 June 2010: Wouter + - Ignore Z flag in incoming messages too. + - Fix storage of negative parent glue if that last resort fails. + - libtoolize 2.2.6b, autoconf 2.65 applied to configure. + - new splint flags for newer splint install. + +31 May 2010: Wouter + - Fix AD flag handling, it could in some cases mistakenly copy the AD + flag from upstream servers. + - alloc_special_obtain out of memory is not a fatal error any more, + enabling unbound to continue longer in out of memory conditions. + - parentside names are dispreferred but not said to be dnssec-lame. + - parentside check for cached newname glue. + - fix parentside and querytargets modulestate, for dump_requestlist. + - unbound-control-setup makes keys -rw-r--- so not all users permitted. + - fix parentside from cache to be marked dispreferred for bad names. + +28 May 2010: Wouter + - iana portlist updated. + - parent-child disagreement approach altered. Older fixes are + removed in place of a more exhaustive search for misconfigured data + available via the parent of a delegation. + This is designed to be throttled by cache entries, with TTL from the + parent if possible. Additionally the loop-counter is used. + It also tests for NS RRset differences between parent and child. + The fetch of misconfigured data should be more reliable and thorough. + It should work reliably even with no or only partial data in cache. + Data received from the child (as always) is deemed more + authoritative than information received from the delegation parent. + The search for misconfigured data is not performed normally. + +26 May 2010: Wouter + - Contribution from Migiel de Vos (Surfnet): nagios patch for + unbound-host, in contrib/ (in the source tarball). Makes + unbound-host suitable for monitoring dnssec(-chain) status. + +21 May 2010: Wouter + - EDNS timeout code will not fire if EDNS status already known. + - EDNS failure not stored if EDNS status known to work. + +19 May 2010: Wouter + - Fix resolution for domains like safesvc.com.cn. If the iterator + can not recurse further and it finds the delegation in a state + where it would otherwise have rejected it outhand if so received + from a cache lookup, then it can try to ask higherup (with loop + protection). + - Fix comments in iter_utils:dp_is_useless. + +18 May 2010: Wouter + - Fix various compiler warnings from the clang llvm compiler. + - iana portlist updated. + +6 May 2010: Wouter + - Fix bug#308: spelling error in variable name in parser and lexer. + +4 May 2010: Wouter + - Fix dnssec-missing detection that was turned off by server selection. + - Conforms to draft-ietf-dnsop-default-local-zones-13. Added default + reverse lookup blocks for IPv4 test nets 100.51.198.in-addr.arpa, + 113.0.203.in-addr.arpa and Orchid prefix 0.1.1.0.0.2.ip6.arpa. + +29 April 2010: Wouter + - Fix for dnssec lameness detection to use the key cache. + - infra cache entries that are expired are wiped clean. Previously + it was possible to not expire host data (if accessed often). + +28 April 2010: Wouter + - ldns tarball updated and GOST support is detected and then enabled. + - iana portlist updated. + - Fix detection of gost support in ldns (reported by Chris Smith). + +27 April 2010: Wouter + - unbound-control get_option domain-insecure shows config file items. + - fix retry sequence if prime hints are recursion-lame. + - autotrust anchor file can be initialized with a ZSK key as well. + - harden-referral-path does not result in failures due to max-depth. + You can increase the max-depth by adding numbers (' 0') after the + target-fetch-policy, this increases the depth to which is checked. + +26 April 2010: Wouter + - Compile fix using Sun Studio 12 compiler on Solaris 5.9, use + CPPFLAGS during configure process. + - if libev is installed on the base system (not libevent), detect + it from the event.h header file and link with -lev. + - configlexer.lex gets config.h, and configyyrename.h added by make, + no more double include. + - More strict scrubber (Thanks to George Barwood for the idea): + NS set must be pertinent to the query (qname subdomain nsname). + - Fix bug#307: In 0x20 backoff fix fallback so the number of + outstanding queries does not become -1 and block the request. + Fixed handling of recursion-lame in combination with 0x20 fallback. + Fix so RRsets are compared canonicalized and sorted if the immediate + comparison fails, this makes it work around round-robin sites. + +23 April 2010: Wouter + - Squelch log message: sendto failed permission denied for + 255.255.255.255, it is visible in VERB_DETAIL (verbosity 2). + - Fix to fetch data as last resort more tenaciously. When cycle + targets cause the server selection to believe there are more options + when they really are not there, the server selection is reinitiated. + - Fix fetch from blacklisted dnssec lame servers as last resort. The + server's IP address is then given in validator errors as well. + - Fix local-zone type redirect that did not use the query name for + the answer rrset. + +22 April 2010: Wouter + - tag 1.4.4. + - trunk contains 1.4.5 in development. + - Fix validation failure for qtype ANY caused by a RRSIG parse failure. + The validator error message was 'no signatures from ...'. + +16 April 2010: Wouter + - more portability defines for CMSG_SPACE, CMSG_ALIGN, CMSG_LEN. + - tag 1.4.4rc1. + +15 April 2010: Wouter + - ECC-GOST algorithm number 12 that is assigned by IANA. New test + example key and signatures for GOST. GOST requires openssl-1.0.0. + GOST is still disabled by default. + +9 April 2010: Wouter + - Fix bug#305: pkt_dname_tolower could read beyond end of buffer or + get into an endless loop, if 0x20 was enabled, and buffers are small + or particular broken packets are received. + - Fix chain of trust with CNAME at an intermediate step, for the DS + processing proof. + +8 April 2010: Wouter + - Fix validation of queries with wildcard names (*.example). + +6 April 2010: Wouter + - Fix EDNS probe for .de DNSSEC testbed failure, where the infra + cache timeout coincided with a server update, the current EDNS + backoff is less sensitive, and does not cache the backoff unless + the backoff actually works and the domain is not expecting DNSSEC. + - GOST support with correct algorithm numbers. + +1 April 2010: Wouter + - iana portlist updated. + +24 March 2010: Wouter + - unbound control flushed items are not counted when flushed again. + +23 March 2010: Wouter + - iana portlist updated. + +22 March 2010: Wouter + - unbound-host disables use-syslog from config file so that the + config file for the main server can be used more easily. + - fix bug#301: unbound-checkconf could not parse interface + '0.0.0.0@5353', even though unbound itself worked fine. + +19 March 2010: Wouter + - fix fwd_ancil test to pass if the socket options are not supported. + +18 March 2010: Wouter + - Fixed random numbers for port, interface and server selection. + Removed very small bias. + - Refer to the listing in unbound-control man page in the extended + statistics entry in the unbound.conf man page. + +16 March 2010: Wouter + - Fix interface-automatic for OpenBSD: msg.controllen was too small, + also assertions on ancillary data buffer. + - check for IP_SENDSRCADDR for interface-automatic or IP_PKTINFO. + - for NSEC3 check if signatures are cached. + +15 March 2010: Wouter + - unit test for util/regional.c. + +12 March 2010: Wouter + - Reordered configure checks so fork and -lnsl -lsocket checks are + earlier, and thus later checks benefit from and do not hinder them. + - iana portlist updated. + - ldns tarball updated. + - Fix python use when multithreaded. + - Fix solaris python compile. + - Include less in config.h and include per code file for ldns, ssl. + +11 March 2010: Wouter + - another memory allocation option: --enable-alloc-nonregional. + exposes the regional allocations to other memory purifiers. + - fix for memory alignment in struct sock_list allocation. + - Fix for MacPorts ldns without ssl default, unbound checks if ldns + has dnssec functionality and uses the builtin if not. + - Fix daemonize on Solaris 10, it did not detach from terminal. + - tag 1.4.3 created. + - trunk is 1.4.4 in development. + - spelling fix in validation error involving cnames. + +10 March 2010: Wouter + - --enable-alloc-lite works with test set. + - portability in the testset: printf format conversions, prototypes. + +9 March 2010: Wouter + - tag 1.4.2 created. + - trunk is 1.4.3 in development. + - --enable-alloc-lite debug option. + +8 March 2010: Wouter + - iana portlist updated. + +4 March 2010: Wouter + - Fix crash in control channel code. + +3 March 2010: Wouter + - better casts in pipe code, brackets placed wrongly. + - iana portlist updated. + +1 March 2010: Wouter + - make install depends on make all. + - Fix 5011 auto-trust-anchor-file initial read to skip RRSIGs. + - --enable-checking: enables assertions but does not look nonproduction. + - nicer VERB_DETAIL (verbosity 2, unbound-host -d) output, with + nxdomain and nodata distinguished. + - ldns tarball updated. + - --disable-rpath fixed for libtool not found errors. + - new fedora specfile from Fedora13 in contrib from Paul Wouters. + +26 February 2010: Wouter + - Fixup prototype for lexer cleanup in daemon code. + - unbound-control list_stubs, list_forwards, list_local_zones and + list_local_data. + +24 February 2010: Wouter + - Fix scrubber bug that potentially let NS records through. Reported + by Amanda Constant. + - Also delete potential poison references from additional. + - Fix: no classification of a forwarder as lame, throw away instead. + +23 February 2010: Wouter + - libunbound ub_ctx_get_option() added. + - unbound-control set_option and get_option commands. + - iana portlist updated. + +18 February 2010: Wouter + - A little more strict DS scrubbing. + - No more blacklisting of unresponsive servers, a 2 minute timeout + is backed off to. + - RD flag not enabled for dnssec-blacklisted tries, unless necessary. + - pickup ldns compile fix, libdl for libcrypto. + - log 'tcp connect: connection timed out' only in high verbosity. + - unbound-control log_reopen command. + - moved get_option code from unbound-checkconf to util/config_file.c + +17 February 2010: Wouter + - Disregard DNSKEY from authority section for chain of trust. + DS records that are irrelevant to a referral scrubbed. Anti-poison. + - iana portlist updated. + +16 February 2010: Wouter + - Check for 'no space left on device' (or other errors) when + writing updated autotrust anchors and print errno to log. + +15 February 2010: Wouter + - Fixed the requery protection, the TTL was 0, it is now 900 seconds, + hardcoded. We made the choice to send out more conservatively, + protecting against an aggregate effect more than protecting a + single user (from their own folly, perhaps in case of misconfig). + +12 February 2010: Wouter + - Re-query pattern changed on validation failure. To protect troubled + authority servers, unbound caches a failure for the DNSKEY or DS + records for the entire zone, and only retries that 900 seconds later. + This implies that only a handful of packets are sent extra to the + authority if the zone fails. + +11 February 2010: Wouter + - ldns tarball update for long label length syntax error fix. + - iana portlist updated. + +9 February 2010: Wouter + - Fixup in compat snprintf routine, %f 1.02 and %g support. + - include math.h for testbound test compile portability. + +2 February 2010: Wouter + - Updated url of IANA itar, interim trust anchor repository, in script. + +1 February 2010: Wouter + - iana portlist updated. + - configure test for memcmp portability. + +27 January 2010: Wouter + - removed warning on format string in validator error log statement. + - iana portlist updated. + +22 January 2010: Wouter + - libtool finish the install of unbound python dynamic library. + +21 January 2010: Wouter + - acx_nlnetlabs.m4 synchronised with nsd's version. + +20 January 2010: Wouter + - Fixup lookup trouble for parent-child domains on the first query. + +14 January 2010: Wouter + - Fixup ldns detection to also check for header files. + +13 January 2010: Wouter + - prefetch-key option that performs DNSKEY queries earlier in the + validation process, and that could halve the latency on DNSSEC + queries. It takes some extra processing (CPU, a cache is needed). + +12 January 2010: Wouter + - Fix unbound-checkconf for auto-trust-anchor-file present checks. + +8 January 2010: Wouter + - Fix for parent-child disagreement code which could have trouble + when (a) ipv6 was disabled and (b) the TTL for parent and child + were different. There were two bugs, the parent-side information + is fixed to no longer block lookup of child side information and + the iterator is fixed to no longer attempt to get ipv6 when it is + not enabled and then give up in failure. + - test and fixes to make prefetch actually store the answer in the + cache. Considers some rrsets 'already expired' but does not allow + overwriting of rrsets considered more secure. + +7 January 2010: Wouter + - Fixup python documentation (thanks Leo Vandewoestijne). + - Work on cache prefetch feature. + - Stats for prefetch, in log print stats, unbound-control stats + and in unbound_munin plugin. + +6 January 2010: Wouter + - iana portlist updated. + - bug#291: DNS wireformat max is 255. dname_valid allowed 256 length. + - verbose output includes parent-side-address notion for lameness. + - documented val-log-level: 2 setting in example.conf and man page. + - change unbound-control-setup from 1024(sha1) to 1536(sha256). + +1 January 2010: Wouter + - iana portlist updated. + +22 December 2009: Wouter + - configure with newer libtool 2.2.6b. + +17 December 2009: Wouter + - review comments. + - tag 1.4.1. + - trunk to version 1.4.2. + +15 December 2009: Wouter + - Answer to qclass=ANY queries, with class IN contents. + Test that validation also works. + - updated ldns snapshot tarball with latest fixes (parsing records). + +11 December 2009: Wouter + - on IPv4 UDP turn off DF flag. + +10 December 2009: Wouter + - requirements.txt updated with design choice explanations. + - Reading fixes: fix to set unlame when child confirms parent glue, + and fix to avoid duplicate addresses in delegation point. + - verify_rrsig routine checks expiration last. + +9 December 2009: Wouter + - Fix Bug#287(reopened): update of ldns tarball with fix for parse + errors generated for domain names like '.example.com'. + - Fix SOA excluded from negative DS responses. Reported by Hauke + Lampe. The negative cache did not include proper SOA records for + negative qtype DS responses which makes BIND barf on it, such + responses are now only used internally. + - Fix negative cache lookup of closestencloser check of DS type bit. + +8 December 2009: Wouter + - Fix for lookup of parent-child disagreement domains, where the + parent-side glue works but it does not provide proper NS, A or AAAA + for itself, fixing domains such as motorcaravanners.eu. + - Feature: you can specify a port number in the interface: line, so + you can bind the same interface multiple times at different ports. + +7 December 2009: Wouter + - Bug#287: Fix segfault when unbound-control remove nonexistent local + data. Added check to tests. + +1 December 2009: Wouter + - Fix crash with module-config "iterator". + - Added unit test that has "iterator" module-config. + +30 November 2009: Wouter + - bug#284: fix parse of # without end-of-line at end-of-file. + +26 November 2009: Wouter + - updated ldns with release candidate for version 1.6.3. + - tag for 1.4.0 release. + - 1.4.1 version in trunk. + - Fixup major libtool version to 2 because of why_bogus change. + It was 1:5:0 but should have been 2:0:0. + +23 November 2009: Wouter + - Patch from David Hubbard for libunbound manual page. + - Fixup endless spinning in unbound-control stats reported by + Attila Nagy. Probably caused by clock reversal. + +20 November 2009: Wouter + - contrib/split-itar.sh contributed by Tom Hendrikx. + +19 November 2009: Wouter + - better argument help for unbound-control. + - iana portlist updated. + +17 November 2009: Wouter + - noted multiple entries for multiple domain names in example.conf. + - iana portlist updated. + +16 November 2009: Wouter + - Fixed signer detection of CNAME responses without signatures. + - Fix#282 libunbound memleak on error condition by Eric Sesterhenn. + - Tests for CNAMEs to deeper trust anchors, secure and bogus. + - svn tag 1.4.0rc1 made. + +13 November 2009: Wouter + - Fixed validation failure for CNAME to optout NSEC3 nodata answer. + - unbound-host does not fail on type ANY. + - Fixed wireparse failure to put RRSIGs together with data in some + long ANY mix cases, which fixes validation failures. + +12 November 2009: Wouter + - iana portlist updated. + - fix manpage errors reported by debian lintian. + - review comments. + - fixup very long vallog2 level error strings. + +11 November 2009: Wouter + - ldns tarball updated (to 1.6.2). + - review comments. + +10 November 2009: Wouter + - Thanks to Surfnet found bug in new dnssec-retry code that failed + to combine well when combined with DLV and a particular failure. + - Fixed unbound-control -h output about argument optionality. + - review comments. + +5 November 2009: Wouter + - lint fixes and portability tests. + - better error text for multiple domain keys in one autotrust file. + +2 November 2009: Wouter + - Fix bug where autotrust does not work when started with a DS. + - Updated GOST unit tests for unofficial algorithm number 249 + and DNSKEY-format changes in draft version -01. + +29 October 2009: Wouter + - iana portlist updated. + - edns-buffer-size option, default 4096. + - fixed do-udp: no. + +28 October 2009: Wouter + - removed abort on prealloc failure, error still printed but softfail. + - iana portlist updated. + - RFC 5702: RSASHA256 and RSASHA512 support enabled by default. + - ldns tarball updated (which also enables rsasha256 support). + +27 October 2009: Wouter + - iana portlist updated. + +8 October 2009: Wouter + - please doxygen + - add val-log-level print to corner case (nameserver.epost.bg). + - more detail to errors from insecure delegation checks. + - Fix double time subtraction in negative cache reported by + Amanda Constant and Hugh Mahon. + - Made new validator error string available from libunbound for + applications. It is in result->why_bogus, a zero-terminated string. + unbound-host prints it by default if a result is bogus. + Also the errinf is public in module_qstate (for other modules). + +7 October 2009: Wouter + - retry for validation failure in DS and prime results. Less mem use. + unit test. Provisioning in other tests for requeries. + - retry for validation failure in DNSKEY in middle of chain of trust. + unit test. + - retry for empty non terminals in chain of trust and unit test. + - Fixed security bug where the signatures for NSEC3 records were not + checked when checking for absence of DS records. This could have + enabled the substitution of an insecure delegation. + - moved version number to 1.4.0 because of 1.3.4 release with only + the NSEC3 patch from the entry above. + - val-log-level: 2 shows extended error information for validation + failures, but still one (longish) line per failure. For example: + validation failure : signature expired from + 192.0.2.4 for trust anchor example.com. while building chain of trust + validation failure : no signatures from + 192.0.2.6 for key example.com. while building chain of trust + +6 October 2009: Wouter + - Test set updated to provide additional ns lookup result. + The retry would attempt to fetch the data from other nameservers + for bogus data, and this needed to be provisioned in the tests. + +5 October 2009: Wouter + - first validation failure retry code. Retries for data failures. + And unit test. + +2 October 2009: Wouter + - improve 5011 modularization. + - fix unbound-host so -d can be given before -C. + - iana portlist updated. + +28 September 2009: Wouter + - autotrust-anchor-file can read multiline input and $ORIGIN. + - prevent integer overflow in holddown calculation. review fixes. + - fixed race condition in trust point revocation. review fix. + - review fixes to comments, removed unused code. + +25 September 2009: Wouter + - so-rcvbuf: 4m option added. Set this on large busy servers to not + drop the occasional packet in spikes due to full socket buffers. + netstat -su keeps a counter of UDP dropped due to full buffers. + - review of validator/autotrust.c, small fixes and comments. + +23 September 2009: Wouter + - 5011 query failed counts verification failures, not lookup failures. + - 5011 probe failure handling fixup. + - test unbound reading of original autotrust data. + The metadata per-key, such as key state (PENDING, MISSING, VALID) is + picked up, otherwise performs initial probe like usual. + +22 September 2009: Wouter + - autotrust test with algorithm rollover, new ordering of checks + assists in orderly rollover. + - autotrust test with algorithm rollover to unknown algorithm. + checks if new keys are supported before adding them. + - autotrust test with trust point revocation, becomes unsigned. + - fix DNSSEC-missing-signature detection for minimal responses + for qtype DNSKEY (assumes DNSKEY occurs at zone apex). + +18 September 2009: Wouter + - autotrust tests, fix trustpoint timer deletion code. + fix count of valid anchors during missing remove. + - autotrust: pick up REVOKE even if not signed with known other keys. + +17 September 2009: Wouter + - fix compile of unbound-host when --enable-alloc-checks. + - Fix lookup problem reported by Koh-ichi Ito and Jaap Akkerhuis. + - Manual page fixes reported by Tony Finch. + +16 September 2009: Wouter + - Fix memory leak reported by Tao Ma. + - Fix memstats test tool for log-time-ascii log format. + +15 September 2009: Wouter + - iana portlist updated. + +10 September 2009: Wouter + - increased MAXSYSLOGLEN so .bg key can be printed in debug output. + - use linebuffering for log-file: output, this can be significantly + faster than the previous fflush method and enable some class of + resolvers to use high verbosity (for short periods). + Not on windows, because line buffering does not work there. + +9 September 2009: Wouter + - Fix bug where DNSSEC-bogus messages were marked with too high TTL. + The RRsets would still expire at the normal time, but this would + keep messages bogus in the cache for too long. + - regression test for that bug. + - documented that load_cache is meant for debugging. + +8 September 2009: Wouter + - fixup printing errors when load_cache, they were printed to the + SSL connection which broke, now to the log. + - new ldns - with fixed parse of large SOA values. + +7 September 2009: Wouter + - autotrust testbound scenarios. + - autotrust fix that failure count is written to file. + - autotrust fix that keys may become valid after add holddown time + alone, before the probe returns. + +4 September 2009: Wouter + - Changes to make unbound work with libevent-2.0.3 alpha. (in + configure detection due to new ssl dependency in libevent) + - do not call sphinx for documentation when python is disabled. + - remove EV_PERSIST from libevent timeout code to make the code + compatible with the libevent-2.0. Works with older libevent too. + - fix memory leak in python code. + +3 September 2009: Wouter + - Got a patch from Luca Bruno for libunbound support on windows to + pick up the system resolvconf nameservers and hosts there. + - included ldns updated (enum warning fixed). + - makefile fix for parallel makes. + - Patch from Zdenek Vasicek and Attila Nagy for using the source IP + from python scripts. See pythonmod/examples/resip.py. + - doxygen comment fixes. + +2 September 2009: Wouter + - TRAFFIC keyword for testbound. Simplifies test generation. + ${range lower val upper} to check probe timeout values. + - test with 5011-prepublish rollover and revocation. + - fix revocation of RR for autotrust, stray exclamation mark. + +1 September 2009: Wouter + - testbound variable arithmetic. + - autotrust probe time is randomised. + - autotrust: the probe is active and does not fetch from cache. + +31 August 2009: Wouter + - testbound variable processing. + +28 August 2009: Wouter + - fixup unbound-control lookup to print forward and stub servers. + +27 August 2009: Wouter + - autotrust: mesh answer callback is empty. + +26 August 2009: Wouter + - autotrust probing. + - iana portlist updated. + +25 August 2009: Wouter + - fixup memleak in trust anchor unsupported algorithm check. + - iana portlist updated. + - autotrust options: add-holddown, del-holddown, keep-missing. + - autotrust store revoked status of trust points. + - ctime_r compat definition. + - detect yylex_destroy() in configure. + - detect SSL_get_compression_methods declaration in configure. + - fixup DS lookup at anchor point with unsigned parent. + - fixup DLV lookup for DS queries to unsigned domains. + +24 August 2009: Wouter + - cleaner memory allocation on exit. autotrust test routines. + - free all memory on program exit, fix for ssl and flex. + +21 August 2009: Wouter + - autotrust: debug routines. Read,write and conversions work. + +20 August 2009: Wouter + - autotrust: save and read trustpoint variables. + +19 August 2009: Wouter + - autotrust: state table updates. + - iana portlist updated. + +17 August 2009: Wouter + - autotrust: process events. + +17 August 2009: Wouter + - Fix so that servers are only blacklisted if they fail to reply + to 16 queries in a row and the timeout gets above 2 minutes. + - autotrust work, split up DS verification of DNSKEYs. + +14 August 2009: Wouter + - unbound-control lookup prints out infra cache information, like RTT. + - Fix bug in DLV lookup reported by Amanda from Secure64. + It could sometimes wrongly classify a domain as unsigned, which + does not give the AD bit on replies. + +13 August 2009: Wouter + - autotrust read anchor files. locked trust anchors. + +12 August 2009: Wouter + - autotrust import work. + +11 August 2009: Wouter + - Check for openssl compatible with gost if enabled. + - updated unit test for GOST=211 code. + Nicer naming of test files. + - iana portlist updated. + +7 August 2009: Wouter + - call OPENSSL_config() in unbound and unit test so that the + operator can use openssl.cnf for configuration options. + - removed small memory leak from config file reader. + +6 August 2009: Wouter + - configure --enable-gost for GOST support, experimental + implementation of draft-dolmatov-dnsext-dnssec-gost-01. + - iana portlist updated. + - ldns tarball updated (with GOST support). + +5 August 2009: Wouter + - trunk moved to 1.3.4. + +4 August 2009: Wouter + - Added test that the examples from draft rsasha256-14 verify. + - iana portlist updated. + - tagged 1.3.3 + +3 August 2009: Wouter + - nicer warning when algorithm not supported, tells you to upgrade. + - iana portlist updated. + +27 July 2009: Wouter + - Updated unbound-cacti contribution from Dmitriy Demidov, with + the queue statistics displayed in its own graph. + - iana portlist updated. + +22 July 2009: Wouter + - Fix bug found by Michael Tokarev where unbound would try to + prime the root servers even though forwarders are configured for + the root. + - tagged 1.3.3rc1 + +21 July 2009: Wouter + - Fix server selection, so that it waits for open target queries when + faced with lameness. + +20 July 2009: Wouter + - Ignore transient sendto errors, no route to host, and host, net down. + - contrib/update-anchor.sh has -r option for root-hints. + - feature val-log-level: 1 prints validation failures so you can + keep track of them during dnssec deployment. + +16 July 2009: Wouter + - fix replacement malloc code. Used in crosscompile. + - makedist -w creates crosscompiled setup.exe on fedora11. + +15 July 2009: Wouter + - dependencies for compat items, for crosscompile. + - mingw32 crosscompile changes, dependencies and zipfile creation. + and with System.dll from the windows NSIS you can make setup.exe. + - package libgcc_s_sjlj exception handler for NSISdl.dll. + +14 July 2009: Wouter + - updated ldns tarball for solaris x64 compile assistance. + - no need to define RAND_MAX from config.h. + - iana portlist updated. + - configure changes and ldns update for mingw32 crosscompile. + +13 July 2009: Wouter + - Fix for crash at start on windows. + - tag for release 1.3.2. + - trunk has version 1.3.3. + - Fix for ID bits on windows to use all 16. RAND_MAX was not + defined like you'd expect on mingw. Reported by Mees de Roo. + +9 July 2009: Wouter + - tag for release 1.3.1. + - trunk has version 1.3.2. + +7 July 2009: Wouter + - iana portlist updated. + +6 July 2009: Wouter + - prettier error handling in SSL setup. + - makedist.sh uname fix (same as ldns). + - updated fedora spec file. + +3 July 2009: Wouter + - fixup linking when ldnsdir is "". + +30 June 2009: Wouter + - more lenient truncation checks. + +29 June 2009: Wouter + - ldns trunk r2959 imported as tarball, because of solaris cc compile + support for c99. r2960 for better configure. + - better wrongly_truncated check. + - On Linux, fragment IPv6 datagrams to the IPv6 minimum MTU, to + avoid dropped packets at routers. + +26 June 2009: Wouter + - Fix EDNS fallback when EDNS works for short answers but long answers + are dropped. + +22 June 2009: Wouter + - fixup iter priv strict aliasing while preserving size of sockaddr. + - iana portlist updated. (one less port allocated, one more fraction + of a bit for security!) + - updated fedora specfile in contrib from Paul Wouters. + +19 June 2009: Wouter + - Fixup strict aliasing warning in iter priv code. + and config_file code. + - iana portlist updated. + - harden-referral-path: handle cases where NS is in answer section. + +18 June 2009: Wouter + - Fix of message parse bug where (specifically) an NSEC and RRSIG + in the wrong order would be parsed, but put wrongly into internal + structures so that later validation would fail. + - Extreme lenience for wrongly truncated replies where a positive + reply has an NS in the authority but no signatures. They are + turned into minimal responses with only the (secure) answer. + - autoconf 2.63 for configure. + - python warnings suppress. Keep python API away from header files. + +17 June 2009: Wouter + - CREDITS entry for cz.nic, sponsoring a 'summer of code' that was + used for the python code in unbound. (http://www.nic.cz/vip/ in cz). + +16 June 2009: Wouter + - Fixup opportunistic target query generation to it does not + generate queries that are known to fail. + - Touchup on munin total memory report. + - messages picked out of the cache by the iterator are checked + if their cname chain is still correct and if validation status + has to be reexamined. + +15 June 2009: Wouter + - iana portlist updated. + +14 June 2009: Wouter + - Fixed bug where cached responses would lose their security + status on second validation, which especially impacted dlv + lookups. Reported by Hauke Lampe. + +13 June 2009: Wouter + - bug #254. removed random whitespace from example.conf. + +12 June 2009: Wouter + - Fixup potential wrong NSEC picked out of the cache. + - If unfulfilled callbacks are deleted they are called with an error. + - fptr wlist checks for mesh callbacks. + - fwd above stub in configuration works. + +11 June 2009: Wouter + - Fix queries for type DS when forward or stub zones are there. + They are performed to higherup domains, and thus treated as if + going to higher zones when looking up the right forward or stub + server. This makes a stub pointing to a local server that has + a local view of example.com signed with the same keys as are + publicly used work. Reported by Johan Ihren. + - Added build-unbound-localzone-from-hosts.pl to contrib, from + Dennis DeDonatis. It converts /etc/hosts into config statements. + - same thing fixed for forward-zone and DS, chain of trust from + public internet into the forward-zone works now. Added unit test. + +9 June 2009: Wouter + - openssl key files are opened apache-style, when user is root and + before chrooting. This makes permissions on remote-control key + files easier to set up. Fixes bug #251. + - flush_type and flush_name remove msg cache entries. + - codereview - dp copy bogus setting fix. + +8 June 2009: Wouter + - Removed RFC5011 REVOKE flag support. Partial 5011 support may cause + inadvertant behaviour. + - 1.3.0 tarball for release created. + - 1.3.1 development in svn trunk. + - iana portlist updated. + - fix lint from complaining on ldns/sha.h. + - help compiler figure out aliasing in priv_rrset_bad() routine. + - fail to configure with python if swig is not found. + - unbound_munin_ in contrib uses ps to show rss if sbrk does not work. + +3 June 2009: Wouter + - fixup bad free() when wrongly encoded DSA signature is seen. + Reported by Paul Wouters. + - review comments from Matthijs. + +2 June 2009: Wouter + - --enable-sha2 option. The draft rsasha256 changed its algorithm + numbers too often. Therefore it is more prudent to disable the + RSASHA256 and RSASHA512 support by default. + - ldns trunk included as new tarball. + - recreated the 1.3.0 tag in svn. rc1 tarball generated at this point. + +29 May 2009: Wouter + - fixup doc bug in README reported by Matthew Dempsky. + +28 May 2009: Wouter + - update iana port list + - update ldns lib tarball + +27 May 2009: Wouter + - detect lack of IPv6 support on XP (with a different error code). + - Fixup a crash-on-exit which was triggered by a very long queue. + Unbound would try to re-use ports that came free, but this is + of course not really possible because everything is deleted. + Most easily triggered on XP (not Vista), maybe because of the + network stack encouraging large messages backlogs. + - change in debug statements. + - Fixed bug that could cause a crash if root prime failed when there + were message backlogs. + +26 May 2009: Wouter + - Thanks again to Brett Carr, found an assertion that was not true. + Assertion checked if recursion parent query still existed. + +29 April 2009: Wouter + - Thanks to Brett Carr, caught windows resource leak, use + closesocket() and not close() on sockets or else the network stack + starts to leak handles. + - Removed usage of windows Mutex because windows cannot handle enough + mutexes open. Provide own mutex implementation using primitives. + +28 April 2009: Wouter + - created svn tag for 1.3.0. + +27 April 2009: Wouter + - optimised cname from cache. + - ifdef windows functions in testbound. + +23 April 2009: Wouter + - fix for threadsafety in solaris thr_key_create() in tests. + - iana portlist updated. + - fix pylib test for Darwin. + - fix pymod test for Darwin and a python threading bug in pymod init. + - check python >= 2.4 in configure. + - -ldl check for libcrypto 1.0.0beta. + +21 April 2009: Wouter + - fix for build outside sourcedir. + - fix for configure script swig detection. + +17 April 2009: Wouter + - Fix reentrant in minievent handler for unix. Could have resulted + in spurious event callbacks. + - timers do not take up a fd slot for winsock handler. + - faster fix for winsock reentrant check. + - fix rsasha512 unit test for new (interim) algorithm number. + - fix test:ldns doesn't like DOS line endings in keyfiles on unix. + - fix compile warning on ubuntu (configlexer fwrite return value). + - move python include directives into CPPFLAGS instead of CFLAGS. + +16 April 2009: Wouter + - winsock event handler exit very quickly on signal, even if + under heavy load. + - iana portlist updated. + - fixup windows winsock handler reentrant problem. + +14 April 2009: Wouter + - bug #245: fix munin plugin, perform cleanup of stale lockfiles. + - makedist.sh; better help text. + - cache-min-ttl option and tests. + - mingw detect error condition on TCP sockets (NOTCONN). + +9 April 2009: Wouter + - Fix for removal of RSASHA256_NSEC3 protonumber from ldns. + - ldns tarball updated. + - iana portlist update. + - detect GOST support in openssl-1.0.0-beta1, and fix compile problem + because that openssl defines the name STRING for itself. + +6 April 2009: Wouter + - windows compile fix. + - Detect FreeBSD jail without ipv6 addresses assigned. + - python libunbound wrapper unit test. + - installs the following files. Default is to not build them. + from configure --with-pythonmodule: + /usr/lib/python2.x/site-packages/unboundmodule.py + from configure --with-pyunbound: + /usr/lib/python2.x/site-packages/unbound.py + /usr/lib/python2.x/site-packages/_unbound.so* + The example python scripts (pythonmod/examples and + libunbound/python/examples) are not installed. + - python invalidate routine respects packed rrset ids and locks. + - clock skew checks in unbound, config statements. + - nxdomain ttl considerations in requirements.txt + +3 April 2009: Wouter + - Fixed a bug that caused messages to be stored in the cache too + long. Hard to trigger, but NXDOMAINs for nameservers or CNAME + targets have been more vulnerable to the TTL miscalculation bug. + - documentation test fixed for python addition. + +2 April 2009: Wouter + - pyunbound (libunbound python plugin) compiles using libtool. + - documentation for pythonmod and pyunbound is generated in doc/html. + - iana portlist updated. + - fixed bug in unbound-control flush_zone where it would not flush + every message in the target domain. This especially impacted + NXDOMAIN messages which could remain in the cache regardless. + - python module test package. + +1 April 2009: Wouter + - suppress errors when trying to contact authority servers that gave + ipv6 AAAA records for their nameservers with ipv4 mapped contents. + Still tries to do so, could work when deployed in intranet. + Higher verbosity shows the error. + - new libunbound calls documented. + - pyunbound in libunbound/python. Removed compile warnings. + Makefile to make it. + +30 March 2009: Wouter + - Fixup LDFLAGS from libevent sourcedir compile configure restore. + - Fixup so no non-absolute rpaths are added. + - Fixup validation of RRSIG queries, they are let through. + - read /dev/random before chroot + - checkconf fix no python checks when no python module enabled. + - fix configure, pthread first, so other libs do not change outcome. + +27 March 2009: Wouter + - nicer -h output. report linked libraries and modules. + - prints modules in intuitive order (config file friendly). + - python compiles easily on BSD. + +26 March 2009: Wouter + - ignore swig varargs warnings with gcc. + - remove duplicate example.conf text from python example configs. + - outofdir compile fix for python. + - pyunbound works. + - print modules compiled in on -h. manpage. + +25 March 2009: Wouter + - initial import of the python contribution from Zdenek Vasicek and + Marek Vavrusa. + - pythonmod in Makefile; changes to remove warnings/errors for 1.3.0. + +24 March 2009: Wouter + - more neat configure.ac. Removed duplicate config.h includes. + - neater config.h.in. + - iana portlist updated. + - fix util/configlexer.c and solaris -std=c99 flag. + - fix postcommit aclocal errors. + - spaces stripped. Makefile cleaner, /usr omitted from -I, -L, -R. + - swap order of host detect and libtool generation. + +23 March 2009: Wouter + - added launchd plist example file for MacOSX to contrib. + - deprecation test for daemon(3). + - moved common configure actions to m4 include, prettier Makefile. + +20 March 2009: Wouter + - bug #239: module-config entries order is important. Documented. + - build fix for test asynclook. + +19 March 2009: Wouter + - winrc/README.txt dos-format text file. + - iana portlist updated. + - use _beginthreadex() when available (performs stack alignment). + - defaults for windows baked into configure.ac (used if on mingw). + +18 March 2009: Wouter + - Added tests, unknown algorithms become insecure. fallback works. + - Fix for and test for unknown algorithms in a trust anchor + definition. Trust anchors with no supported algos are ignored. + This means a (higher)DS or DLV entry for them could succeed, and + otherwise they are treated as insecure. + - domain-insecure: "example.com" statement added. Sets domain + insecure regardless of chain of trust DSs or DLVs. The inverse + of a trust-anchor. + +17 March 2009: Wouter + - unit test for unsupported algorithm in anchor warning. + - fixed so queries do not fail on opportunistic target queries. + +16 March 2009: Wouter + - fixup diff error printout in contrib/update-itar.sh. + - added contrib/unbound_cacti for statistics support in cacti, + contributed by Dmitriy Demidov. + +13 March 2009: Wouter + - doxygen and lex/yacc on linux. + - strip update-anchor on makedist -w. + - fix testbound on windows. + - default log to syslog for windows. + - uninstaller can stop unbound - changed text on it to reflect that. + - remove debugging from windows 'cron' actions. + +12 March 2009: Wouter + - log to App.logs on windows prints executable identity. + - fixup tests. + - munin plugin fix benign locking error printout. + - anchor-update for windows, called every 24 hours; unbound reloads. + +11 March 2009: Wouter + - winsock event handler resets WSAevents after signalled. + - winsock event handler tests if signals are really signalled. + - install and service with log to file works on XP and Vista on + default install location. + - on windows logging to the Application logbook works (as a service). + - fix RUN_DIR on windows compile setting in makedist. + - windows registry has Software\Unbound\ConfigFile element. + If does not exist, the default is used. The -c switch overrides it. + - fix makedist version cleanup function. + +10 March 2009: Wouter + - makedist -w strips out old rc.. and snapshot info from version. + - setup.exe starts and stops unbound after install, before uninstall. + - unbound-checkconf recognizes absolute pathnames on windows (C:...). + +9 March 2009: Wouter + - Nullsoft NSIS installer creation script. + +5 March 2009: Wouter + - fixup memory leak introduced on 18feb in mesh reentrant fix. + +3 March 2009: Wouter + - combined icon with 16x16(4) 32x32(4) 48x48(8) 64x64(8). + - service works on xp/vista, no config necessary (using defaults). + - windows registry settings. + +2 March 2009: Wouter + - fixup --export-symbols to be -export-symbls for libtool. + This should fix extraneous symbols exported from libunbound. + Thanks to Ondrej Sury and Robert Edmonds for finding it. + - iana portlist updated. + - document FAQ entry on stub/forward zones and default blocking. + - fix asynclook test app for libunbound not exporting symbols. + - service install and remove utils that work with vista UAC. + +27 February 2009: Wouter + - Fixup lexer, to not give warnings about fwrite. Appeared in + new lexer features. + - makedistro functionality for mingw. Has RC support. + - support spaces and backslashes in configured defaults paths. + - register, deregister in service control manager. + +25 February 2009: Wouter + - windres usage for application resources. + +24 February 2009: Wouter + - isc moved their dlv key download location. + - fixup warning on vista/mingw. + - makedist -w for window zip distribution first version. + +20 February 2009: Wouter + - Fixup contrib/update-itar.sh, the exit codes 1 and 0 were swapped. + Nicer script layout. Added url to site in -h output. + +19 February 2009: Wouter + - unbound-checkconf and unbound print warnings when trust anchors + have unsupported algorithms. + - added contrib/update-itar.sh This script is similar to + update-anchor.sh, and updates from the IANA ITAR repository. + You can provide your own PGP key and trust repo, or can use the + builtin. The program uses wget and gpg to work. + - iana portlist updated. + - update-itar.sh: using ftp:// urls because https godaddy certificate + is not available everywhere and then gives fatal errors. The + security is provided by pgp signature. + +18 February 2009: Wouter + - more cycle detection. Also for target queries. + - fixup bug where during deletion of the mesh queries the callbacks + that were reentrant caused assertion failures. Keep the mesh in + a reentrant safe state. Affects libunbound, reload of server, + on quit and flush_requestlist. + - iana portlist updated. + +13 February 2009: Wouter + - forwarder information now per-thread duplicated. + This keeps it read only for speed, with no locking necessary. + - forward command for unbound control to change forwarders to use + on the fly. + - document that unbound-host reads no config file by default. + - updated iana portlist. + +12 February 2009: Wouter + - call setusercontext if available (on BSD). + - small refactor of stats clearing. + - #227: flush_stats feature for unbound-control. + - stats_noreset feature for unbound-control. + - flush_requestlist feature for unbound-control. + - libunbound version upped API (was changed 5 feb). + - unbound-control status shows if root forwarding is in use. + - slightly nicer memory management in iter-fwd code. + +10 February 2009: Wouter + - keys with rfc5011 REVOKE flag are skipped and not considered when + validating data. + - iana portlist updated + - #226: dump_requestlist feature for unbound-control. + +6 February 2009: Wouter + - contrib contains specfile for fedora 1.2.1 (from Paul Wouters). + - iana portlist updated. + - fixup EOL in include directive (reported by Paul Wouters). + You can no longer specify newlines in the names of included files. + - config parser changed. Gives some syntax errors closer to where they + occurred. Does not enforce a space after keyword anymore. + Does not allow literal newlines inside quoted strings anymore. + - verbosity level 5 logs customer IP for new requestlist entries. + - test fix, lexer and cancel test. + - new option log-time-ascii: yes if you enable it prints timestamps + in the log file as Feb 06 13:45:26 (like syslog does). + - detect event_base_new in libevent-1.4.1 and later and use it. + - #231 unbound-checkconf -o option prints that value from config file. + Useful for scripting in management scripts and the like. + +5 February 2009: Wouter + - ldns 1.5.0 rc as tarball included. + - 1.3.0 development continues: + change in libunbound API: ub_cancel can return an error, that + the async_id did not exist, or that it was already delivered. + The result could have been delivered just before the cancel + routine managed to acquire the lock, so a caller may get the + result at the same time they call cancel. For this case, + ub_cancel tries to return an error code. + Fixes race condition in ub_cancel() libunbound function. + - MacOSX Leopard cleaner text output from configure. + - initgroups(3) is called to drop secondary group permissions, if + applicable. + - configure option --with-ldns-builtin forces the use of the + inluded ldns package with the unbound source. The -I include + is put before the others, so it avoids bad include files from + an older ldns install. + - daemon(3) posix call is used when available. + - testbound test for older fix added. + +4 February 2009: Wouter + - tag for release 1.2.1. + - trunk setup for 1.3.0 development. + +3 February 2009: Wouter + - noted feature requests in doc/TODO. + - printout more detailed errors on ssl certificate loading failures. + - updated IANA portlist. + +16 January 2009: Wouter + - more quiet about ipv6 network failures, i.e. when ipv6 is not + available (network unreachable). Debug still printed on high + verbosity. + - unbound-host -4 and -6 options. Stops annoying ipv6 errors when + debugging with unbound-host -4 -d ... + - more cycle detection for NS-check, addr-check, root-prime and + stub-prime queries in the iterator. Avoids possible deadlock + when priming fails. + +15 January 2009: Wouter + - bug #229: fixup configure checks for compilation with Solaris + Sun cc compiler, ./configure CC=/opt/SUNWspro/bin/cc + - fixup suncc warnings. + - fix bug where unbound could crash using libevent 1.3 and older. + - update testset for recent retry change. + +14 January 2009: Wouter + - 1.2.1 feature: negative caching for failed queries. + Queries that failed are cached for 5 seconds (NORR_TTL). + If the failure is local, like out of memory, it is not cached. + - the TTL comparison for the cache used different comparisons, + causing many cache responses that used the iterator and validator + state machines unnecessarily. + - retry from 4 to 5 so that EDNS drop retry is part of the first + query resolve attempt, and cached error does not stop EDNS fallback. + - remove debug prints that protect against bad referrals. + - honor QUIET=no on make commandline (or QUIET=yes ). + +13 January 2009: Wouter + - fixed bug in lameness marking, removed printouts. + - find NS rrset more cleanly for qtype NS. + - Moved changes to 1.2.0 for release. Thanks to Mark Zealey for + reporting and logs. + - 1.2.1 feature: stops resolving AAAAs promiscuously when they + are in the negative cache. + +12 January 2009: Wouter + - fixed bug in infrastructure lameness cache, did not lowercase + name of zone to hash when setting lame. + - lameness debugging printouts. + +9 January 2009: Wouter + - created svn tag for 1.2.0 release. + - svn trunk contains 1.2.1 version number. + - iana portlist updated for todays list. + - removed debug print. + +8 January 2009: Wouter + - new version of ldns-trunk (today) included as tarball, fixed + bug #224, building with -j race condition. + - remove possible race condition in the test for race conditions. + +7 January 2009: Wouter + - version 1.2.0 in preparation. + - feature to allow wildcards (*, ?, [], {}. ~) in trusted-keys-file + statements. (Adapted from patch by Paul Wouters). + - typo fix and iana portlist updated. + - porting testsuite; unused var warning, and type fixup. + +6 January 2009: Wouter + - fixup packet-of-death when compiled with --enable-debug. + A malformed packet could cause an internal assertion failure. + - added test for HINFO canonicalisation behaviour. + - fixup reported problem with transparent local-zone data where + queries with different type could get nxdomain. Now queries + with a different name get resolved normally, with different type + get a correct NOERROR/NODATA answer. + - HINFO no longer downcased for validation, making unbound compatible + with bind and ldns. + - fix reading included config files when chrooted. + Give full path names for include files. + Relative path names work if the start dir equals the working dir. + - fix libunbound message transport when no packet buffer is available. + +5 January 2009: Wouter + - fixup getaddrinfo failure handling for remote control port. + - added L.ROOT-SERVERS.NET. AAAA 2001:500:3::42 to builtin root hints. + - fixup so it works with libev-3.51 from http://dist.schmorp.de/libev/ + - comm_timer_set performs base_set operation after event_add. + +18 December 2008: Wouter + - fixed bug reported by Duane Wessels: error in DLV lookup, would make + some zones that had correct DLV keys as insecure. + - follows -rc makedist from ldns changes (no _rc). + - ldns tarball updated with 1.4.1rc for DLV unit test. + - verbose prints about recursion lame detection and server selection. + - fixup BSD port for infra host storage. It hashed wrongly. + - fixup makedist snapshot name generation. + - do not reopen syslog to avoid dev/log dependency. + +17 December 2008: Wouter + - follows ldns makedist.sh. -rc option. autom4te dir removed. + - unbound-control status command. + - extended statistics has a number of ipv6 queries counter. + contrib/unbound_munin_ was updated to draw ipv6 in the hits graph. + +16 December 2008: Wouter + - follow makedist improvements from ldns, for maintainers prereleases. + - snapshot version uses _ not - to help rpm distinguish the + version number. + +11 December 2008: Wouter + - better fix for bug #219: use LOG_NDELAY with openlog() call. + Thanks to Tamas Tevesz. + +9 December 2008: Wouter + - bug #221 fixed: unbound checkconf checks if key files exist if + remote control is enabled. Also fixed NULL printf when not chrooted. + - iana portlist updated. + +3 December 2008: Wouter + - Fix problem reported by Jaco Engelbrecht where unbound-control stats + freezes up unbound if this was compiled without threading, and + was using multiple processes. + - iana portlist updated. + - test for remote control with interprocess communication. + - created command distribution mechanism so that remote control + commands other than 'stats' work on all processes in a nonthreaded + compiled version. dump/load cache work, on the first process. + - fixup remote control local_data addition memory corruption bug. + +1 December 2008: Wouter + - SElinux policy files in contrib/selinux for the unbound daemon, + by Paul Wouters and Adam Tkac. + +25 November 2008: Wouter + - configure complains when --without-ssl is given (bug #220). + - skip unsupported feature tests on vista/mingw. + - fixup testcode/streamtcp to work on vista/mingw. + - root-hints test checks version of dig required. + - blacklisted servers are polled at a low rate (1%) to see if they + come back up. But not if there is some other working server. + +24 November 2008: Wouter + - document that the user of the server daemon needs read privileges + on the keys and certificates generated by unbound-control-setup. + This is different per system or distribution, usually, running the + script under the same username as the server uses suffices. + i.e. sudo -u unbound unbound-control-setup + - testset port to vista/mingw. + - tcp_sigpipe to freebsd port. + +21 November 2008: Wouter + - fixed tcp accept, errors were printed when they should not. + - unbound-control-setup.sh removes read/write permissions other + from the keys it creates (as suggested by Dmitriy Demidov). + +20 November 2008: Wouter + - fixup fatal error due to faulty error checking after tcp accept. + - add check in rlimit to avoid integer underflow. + - rlimit check with new formula; better estimate for number interfaces + - nicer comments in rlimit check. + - tag 1.1.1 created in svn. + - trunk label is 1.1.2 + +19 November 2008: Wouter + - bug #219: fixed so that syslog which delays opening until the first + log line is written, gets a log line while not chroot'ed yet. + +18 November 2008: Wouter + - iana portlist updated. + - removed cast in unit test debug print that was not 64bit safe. + - trunk back to 1.1.0; copied to tags 1.1.0 release. + - trunk to has version number 1.1.1 again. + - in 1.1.1; make clean nicer. grammar in manpage. + +17 November 2008: Wouter + - theoretical fix for problems reported on mailing list. + If a delegation point has no A but only AAAA and do-ip6 is no, + resolution would fail. Fixed to ask for the A and AAAA records. + It has to ask for both always, so that it can fail quietly, from + TLD perspective, when a zone is only reachable on one transport. + - test for above, only AAAA and doip6 is no. Fix causes A record + for nameserver to be fetched. + - fixup address duplication on cache fillup for delegation points. + - testset updated for new query answer requirements. + +14 November 2008: Wouter + - created 1.1.0 release tag in svn. + - trunk moved to 1.1.1 + - fixup unittest-neg for locking. + +13 November 2008: Wouter + - added fedora init and specfile to contrib (by Paul Wouters). + - added configure check for ldns 1.4.0 (using its compat funcs). + - neater comments in worker.h. + - removed doc/plan and updated doc/TODO. + - silenced EHOSTDOWN (verbosity 2 or higher to see it). + - review comments from Jelte, Matthijs. Neater code. + +12 November 2008: Wouter + - add unbound-control manpage to makedist replace list. + +11 November 2008: Wouter + - unit test for negative cache, stress tests the refcounting. + - fix for refcounting error that could cause fptr_wlist fatal exit + in the negative cache rbtree (upcoming 1.1 feature). (Thanks to + Attila Nagy for testing). + - nicer comments in cachedump about failed RR to string conversion. + - fix 32bit wrap around when printing large (4G and more) mem usage + for extended statistics. + +10 November 2008: Wouter + - fixup the getaddrinfo compat code rename. + +8 November 2008: Wouter + - added configure check for eee build warning. + +7 November 2008: Wouter + - fix bug 217: fixed, setreuid and setregid do not work on MacOSX10.4. + - detect nonblocking problems in network stack in configure script. + +6 November 2008: Wouter + - dname_priv must decompress the name before comparison. + - iana portlist updated. + +5 November 2008: Wouter + - fixed possible memory leak in key_entry_key deletion. + Would leak a couple bytes when trust anchors were replaced. + - if query and reply qname overlap, the bytes are skipped not copied. + - fixed file descriptor leak when messages were jostled out that + had outstanding (TCP) replies. + - DNAMEs used from cache have their synthesized CNAMEs initialized + properly. + - fixed file descriptor leak for localzone type deny (for TCP). + - fixed memleak at exit for nsec3 negative cached zones. + - fixed memleak for the keyword 'nodefault' when reading config. + - made verbosity of 'edns incapable peer' warning higher, so you + do not get spammed by it. + - caught elusive Bad file descriptor error bug, that would print the + error while unnecessarily try to listen to a closed fd. Fixed. + +4 November 2008: Wouter + - fixed -Wwrite-strings warnings that result in better code. + +3 November 2008: Wouter + - fixup build process for Mac OSX linker, use ldns b32 compat funcs. + - generated configure with autoconf-2.61. + - iana portlist updated. + - detect if libssl needs libdl. For static linking with libssl. + - changed to use new algorithm identifiers for sha256/sha512 + from ldns 1.4.0 (need very latest version). + - updated the included ldns tarball. + - proper detection of SHA256 and SHA512 functions (not just sizes). + +23 October 2008: Wouter + - a little more debug info for failure on signer names. prints names. + +22 October 2008: Wouter + - CFLAGS are picked up by configure from the environment. + - iana portlist updated. + - updated ldns to use 1.4.0-pre20081022 so it picks up CFLAGS too. + - new stub-prime: yesno option. Default is off, so it does not prime. + can be turned on to get same behaviour as previous unbound release. + - made automated test that checks if builtin root hints are uptodate. + - finished draft-wijngaards-dnsext-resolver-side-mitigation + implementation. The unwanted-reply-threshold can be set. + - fixup so fptr_whitelist test in alloc.c works. + +21 October 2008: Wouter + - fix update-anchors.sh, so it does not report different RR order + as an update. Sorts the keys in the file. Updated copyright. + - fixup testbound on windows, the command control pipe doesn't exist. + - skip 08hostlib test on windows, no fork() available. + - made unbound-remote work on windows. + +20 October 2008: Wouter + - quench a log message that is debug only. + - iana portlist updated. + - do not query bogus nameservers. It is like nameservers that have + the NS or A or AAAA record bogus are listed as donotquery. + - if server selection is faced with only bad choices, it will + attempt to get more options to be fetched. + - changed bogus-ttl default value from 900 to 60 seconds. + In anticipation that operator caused failures are more likely than + actual attacks at this time. And thus repeated validation helps + the operators get the problem fixed sooner. It makes validation + failures go away sooner (60 seconds after the zone is fixed). + Also it is likely to try different nameserver targets every minute, + so that if a zone is bad on one server but not another, it is + likely to pick up the 'correct' one after a couple minutes, + and if the TTL is big enough that solves validation for the zone. + - fixup unbound-control compilation on windows. + +17 October 2008: Wouter + - port Leopard/G5: fixup type conversion size_t/uint32. + please ranlib, stop file without symbols warning. + - harden referral path now also validates the root after priming. + It looks up the root NS authoritatively as well as the root servers + and attemps to validate the entries. + +16 October 2008: Wouter + - Fixup negative TTL values appearing (reported by Attila Nagy). + +15 October 2008: Wouter + - better documentation for 0x20; remove fallback TODO, it is done. + - harden-referral-path feature includes A, AAAA queries for glue, + as well as very careful NS caching (only when doing NS query). + A, AAAA use the delegation from the NS-query. + +14 October 2008: Wouter + - fwd_three.tpkg test was flaky. If the three requests hit the + wrong threads by chance (or bad OS) then the test would fail. + Made less flaky by increasing number of retries. + - stub_udp.tpkg changed to work, give root hints. fixed ldns_dname_abs. + - ldns tarball is snapshot of ldns r2759 (1.4.0-pre-20081014). + Which includes the ldns_dname_absolute fix. + - fwd_three test remains flaky now that unbound does not stop + listening when full. Thus, removed timeout problem. + It may be serviced by three threads, or maybe by one. + Mostly only useful for lock-check testing now. + +13 October 2008: Wouter + - fixed recursion servers deployed as authoritative detection, so + that as a last resort, a +RD query is sent there to get the + correct answer. + - iana port list update. + - ldns tarball is snapshot of ldns r2759 (1.4.0-pre-20081013). + +10 October 2008: Wouter + - fixup tests - the negative cache contained the correct NSEC3s for + two tests that are supposed to fail to validate. + +9 October 2008: Wouter + - negative cache caps max iterations of NSEC3 done. + - NSEC3 negative cache for qtype DS works. + +8 October 2008: Wouter + - NSEC negative cache for DS. + +6 October 2008: Wouter + - jostle-timeout option, so you can config for slow links. + - 0x20 fallback code. Tries 3xnumber of nameserver addresses + queries that must all be the same. Sent to random nameservers. + - documented choices for DoS, EDNS, 0x20. + +2 October 2008: Wouter + - fixup unlink of pidfile. + - fixup SHA256 algorithm collation code. + - contrib/update-anchor.sh does not overwrite anchors if not needed. + exits 0 when a restart is needed, other values if not. + so, update-anchor.sh -d mydir && /etc/rc.d/unbound restart + can restart unbound exactly when needed. + +30 September 2008: Wouter + - fixup SHA256 DS downgrade, no longer possible to downgrade to SHA1. + - tests for sha256 support and downgrade resistance. + - RSASHA256 and RSASHA512 support (using the draft in dnsext), + using the drafted protocol numbers. + - when using stub on localhost (127.0.0.1@10053) unbound works. + Like when running NSD to host a local zone, on the same machine. + The noprime feature. manpages more explanation. Added a test for it. + - shorthand for reverse PTR, local-data-ptr: "1.2.3.4 www.ex.com" + +29 September 2008: Wouter + - EDNS lameness detection, if EDNS packets are dropped this is + detected, eventually. + - multiple query timeout rtt backoff does not backoff too much. + +26 September 2008: Wouter + - tests for remote-control. + - small memory leak in exception during remote control fixed. + - fixup for lock checking but not unchecking in remote control. + - iana portlist updated. + +23 September 2008: Wouter + - Msg cache is loaded. A cache load enables cache responses. + - unbound-control flush [name], flush_type and flush_zone. + +22 September 2008: Wouter + - dump_cache and load_cache statements in unbound-control. + RRsets are dumped and loaded correctly. + Msg cache is dumped. + +19 September 2008: Wouter + - locking on the localdata structure. + - add and remove local zone and data with unbound-control. + - ldns trunk snapshot updated, make tests work again. + +18 September 2008: Wouter + - fixup error in time calculation. + - munin plugin improvements. + - nicer abbreviations for high query types values (ixfr, axfr, any...) + - documented the statistics output in unbound-control man page. + - extended statistics prints out histogram, over unbound-control. + +17 September 2008: Wouter + - locking for threadsafe bogus rrset counter. + - ldns trunk no longer exports b32 functions, provide compat. + - ldns tarball updated. + - testcode/ldns-testpkts.c const fixups. + - fixed rcode stat printout. + - munin plugin in contrib. + - stats always printout uptime, because stats plugins need it. + +16 September 2008: Wouter + - extended-statistics: yesno config option. + - unwanted replies spoof nearmiss detector. + - iana portlist updated. + +15 September 2008: Wouter + - working start, stop, reload commands for unbound-control. + - test for unbound-control working; better exit value for control. + - verbosity control via unbound-control. + - unbound-control stats. + +12 September 2008: Wouter + - removed browser control mentions. Proto speccy. + +11 September 2008: Wouter + - set nonblocking on new TCP streams, because linux does not inherit + the socket options to the accepted socket. + - fix TCP timeouts. + - SSL protected connection between server and unbound-control. + +10 September 2008: Wouter + - remove memleak in privacy addresses on reloads and quits. + - remote control work. + +9 September 2008: Wouter + - smallapp/unbound-control-setup.sh script to set up certificates. + +4 September 2008: Wouter + - scrubber scrubs away private addresses. + - test for private addresses. man page entry. + - code refactored for name and address tree lookups. + +3 September 2008: Wouter + - options for 'DNS Rebinding' protection: private-address and + private-domain. + - dnstree for reuse of routines that help with domain, addr lookups. + - private-address and private-domain config option read, stored. + +2 September 2008: Wouter + - DoS protection features. Queries are jostled out to make room. + - testbound can pass time, increasing the internal timer. + - do not mark unsigned additionals bogus, leave unchecked, which + is removed too. + +1 September 2008: Wouter + - disallow nonrecursive queries for cache snooping by default. + You can allow is using access-control: allow_snoop. + The defaults do allow access no authoritative data without RD bit. + - two tests for it and fixups of tests for nonrec refused. + +29 August 2008: Wouter + - version 1.1 number in trunk. + - harden-referral-path option for query for NS records. + Default turns off expensive, experimental option. + +28 August 2008: Wouter + - fixup logfile handling; it is created with correct permissions + again. (from bugfix#199). + Some errors are not written to logfile (pidfile writing, forking), + and these are only visible by using the -d commandline flag. + +27 August 2008: Wouter + - daemon(3) is causing problems for people. Reverting the patch. + bug#200, and 199 and 203 contain sideline discussion on it. + - bug#199 fixed: pidfile can be outside chroot. openlog is done before + chroot and drop permissions. + - config option to set size of aggressive negative cache, + neg-cache-size. + - bug#203 fixed: dlv has been implemented. + +26 August 2008: Wouter + - test for insecure zone when DLV is in use, also does negative cache. + - test for trustanchor when DLV is in use (the anchor works). + - test for DLV used for a zone below a trustanchor. + - added scrub filter for overreaching NSEC records and unit test. + - iana portlist update + - use of setresuid or setreuid when available. + - use daemon(3) if available. + +25 August 2008: Wouter + - realclean patch from Robert Edmonds. + +22 August 2008: Wouter + - nicer debuglogging of DLV. + - test with secure delegation inside the DLV repository. + +21 August 2008: Wouter + - negative cache code linked into validator, for DLV use. + negative cache works for DLV. + - iana portlist update. + - dlv-anchor option for unit tests. + - fixup NSEC_AT_APEX classification for short typemaps. + - ldns-testns has subdomain checks, for unit tests. + +20 August 2008: Wouter + - negative cache code, reviewed. + +18 August 2008: Wouter + - changes info: in logfile to notice: info: or debug: depending on + the verbosity of the statements. Better logfile message + classification. + - bug #208: extra rc.d unbound flexibility for freebsd/nanobsd. + +15 August 2008: Wouter + - DLV nsec code fixed for better detection of closest existing + enclosers from NSEC responses. + - DLV works, straight to the dlv repository, so not for production. + - Iana port update. + +14 August 2008: Wouter + - synthesize DLV messages from the rrset cache, like done for DS. + +13 August 2008: Wouter + - bug #203: nicer do-auto log message when user sets incompatible + options. + - bug #204: variable name ameliorated in log.c. + - bug #206: in iana_update, no egrep, but awk use. + - ldns snapshot r2699 taken (includes DLV type). + - DLV work, config file element, trust anchor read in. + +12 August 2008: Wouter + - finished adjusting testset to provide qtype NS answers. + +11 August 2008: Wouter + - Fixup rrset security updates overwriting 2181 trust status. + This makes validated to be insecure data just as worthless as + nonvalidated data, and 2181 rules prevent cache overwrites to them. + - Fix assertion fail on bogus key handling. + - dnssec lameness detection works on first query at trust apex. + - NS queries get proper cache and dnssec lameness treatment. + - fixup compilation without pthreads on linux. + +8 August 2008: Wouter + - NS queries are done after every referral. + validator is used on those NS records (if anchors enabled). + +7 August 2008: Wouter + - Scrubber more strict. CNAME chains, DNAMEs from cache, other + irrelevant rrsets removed. + - 1.0.2 released from 1.0 support branch. + - fixup update-anchor.sh to work both in BSD shell and bash. + +5 August 2008: Wouter + - fixup DS test so apex nodata works again. + +4 August 2008: Wouter + - iana port update. + - TODO update. + - fix bug 201: null ptr deref on cleanup while udp pkts wait for port. + - added explanatory text for outgoing-port-permit in manpage. + +30 July 2008: Wouter + - fixup bug qtype DS for unsigned zone and signed parent validation. + +25 July 2008: Wouter + - added original copyright statement of OpenBSD arc4random code. + - created tube signaling solution on windows, as a pipe replacement. + this makes background asynchronous resolution work on windows. + - removed very insecure socketpair compat code. It also did not + work with event_waiting. Solved by pipe replacement. + - unbound -h prints openssl version number as well. + +22 July 2008: Wouter + - moved pipe actions to util/tube.c. easier porting and shared code. + - check _raw() commpoint callbacks with fptr_wlist. + - iana port update. + +21 July 2008: Wouter + - #198: nicer entropy warning message. manpage OS hints. + +19 July 2008: Wouter + - #198: fixup man page to suggest chroot entropy fix. + +18 July 2008: Wouter + - branch for 1.0 support. + - trunk work on tube.c. + +17 July 2008: Wouter + - fix bug #196, compile outside source tree. + - fix bug #195, add --with-username=user configure option. + - print error and exit if started with config that requires more + fds than the builtin minievent can handle. + +16 July 2008: Wouter + - made svn tag 1.0.1, trunk now 1.0.2 + - sha256 checksums enabled in makedist.sh + +15 July 2008: Wouter + - Follow draft-ietf-dnsop-default-local-zones-06 added reverse + IPv6 example prefix to AS112 default blocklist. + - fixup lookup of DS records by client with trustanchor for same. + - libunbound ub_resolve, fix handling of error condition during setup. + - lowered log_hex blocksize to fit through BSD syslog linesize. + - no useless initialisation if getpwnam not available. + - iana, ldns snapshot updated. + +3 July 2008: Wouter + - Matthijs fixed memory leaks in root hints file reading. + +26 June 2008: Wouter + - fixup streamtcp bounds setting for udp mode, in the test framework. + - contrib item for updating trust anchors. + +25 June 2008: Wouter + - fixup fwd_ancil test typos. + - Fix for newegg lameness : ok for qtype=A, but lame for others. + - fixup unit test for infra cache, test lame merging. + - porting to mingw, bind, listen, getsockopt and setsockopt error + handling. + +24 June 2008: Wouter + - removed testcode/checklocks from production code compilation path. + - streamtcp can use UDP mode (connected UDP socket), for testing IPv6 + on windows. + - fwd_ancil test fails if platform support is lacking. + +23 June 2008: Wouter + - fixup minitpkg to cleanup on windows with its file locking troubles. + - minitpkg shows skipped tests in report. + - skip ipv6 tests on ipv4 only hosts (requires only ipv6 localhost not + ipv6 connectivity). + - winsock event handler keeps track of sticky TCP events, that have + not been fully handled yet. when interest in the event(s) resumes, + they are sent again. When WOULDBLOCK is returned events are cleared. + - skip tests that need signals when testing on mingw. + +18 June 2008: Wouter + - open testbound replay files in binary mode, because fseek/ftell + do not work in ascii-mode on windows. The b does nothing on unix. + unittest and testbound tests work on windows (xp too). + - ioctlsocket prints nicer error message. + - fixed up some TCP porting for winsock. + - lack of IPv6 gives a warning, no fatal error. + - use WSAGetLastError() on windows instead of errno for some errors. + +17 June 2008: Wouter + - outgoing num fds 32 by default on windows ; it supports less + fds for waiting on than unixes. + - winsock_event minievent handler for windows. (you could also + attempt to link with libevent/libev ports for windows). + - neater crypto check and gdi32 detection. + - unbound.exe works to resolve and validate www.nlnetlabs.nl on vista. + +16 June 2008: Wouter + - on windows, use windows threads, mutex and thread-local-storage(Tls). + - detect if openssl needs gdi32. + - if no threading, THREADS_DISABLED is defined for use in the code. + - sets USE_WINSOCK if using ws2_32 on windows. + - wsa_strerror() function for more readable errors. + - WSA Startup and Cleanup called in unbound.exe. + +13 June 2008: Wouter + - port mingw32, more signal ifdefs, detect sleep, usleep, + random, srandom (used inside the tests). + - signed or unsigned FD_SET is cast. + +10 June 2008: Wouter + - fixup warnings compiling on eeepc xandros linux. + +9 June 2008: Wouter + - in iteration response type code + * first check for SOA record (negative answer) before NS record + and lameness. + * check if no AA bit for non-forwarder, and thus lame zone. + In response to error report by Richard Doty for mail.opusnet.com. + - fixup unput warning from lexer on freeBSD. + - bug#183. pidfile, rundir, and chroot configure options. Also the + example.conf and manual pages get the configured defaults. + You can use: (or accept the defaults to /usr/local/etc/unbound/) + --with-conf-file=filename + --with-pidfile=filename + --with-run-dir=path + --with-chroot-dir=path + +8 June 2008: Wouter + - if multiple CNAMEs, use the first one. Fixup akamai CNAME bug. + Reported by Robert Edmonds. + - iana port updated. + +4 June 2008: Wouter + - updated libtool files with newer version. + - iana portlist updated. + +3 June 2008: Wouter + - fixup local-zone: "30.172.in-addr.arpa." nodefault, so that the + trailing dot is not used during comparison. + +2 June 2008: Wouter + - Jelte fixed bugs in my absence + - bug 178: fixed unportable shell usage in configure (relied on + bash shell). + - bug 180: fixed buffer overflow in unbound-checkconf use of strncat. + - bug 181: fixed buffer overflow in ldns (called by unbound to parse + config file parts). + - fixes by Wouter + - bug 177: fixed compilation failure on opensuse, the + --disable-static configure flag caused problems. (Patch from + Klaus Singvogel) + - bug 179: same fix as 177. + - bug 185: --disable-shared not passed along to ldns included with + unbound. Fixed so that configure parameters are passed to the + subdir configure script. + fixed that ./libtool is used always, you can still override + manually with ./configure libtool=mylibtool or set $libtool in + the environment. + - update of the ldns tarball to current ldns svn version (fix 181). + - bug 184: -r option for unbound-host, read resolv.conf for + forwarder. (Note that forwarder must support DNSSEC for validation + to succeed). + +23 May 2008: Wouter + - mingw32 porting. + - test for sys/wait.h + - WSAEWOULDBLOCK test after nonblocking TCP connect. + - write_iov_buffer removed: unused and no struct iov on windows. + - signed/unsigned warning fixup mini_event. + - use ioctlsocket to set nonblocking I/O if fnctl is unavailable. + - skip signals that are not defined + - detect pwd.h. + - detect getpwnam, getrlimit, setsid, sbrk, chroot. + - default config has no chroot if chroot() unavailable. + - if no kill() then no pidfile is read or written. + - gmtime_r is replaced by nonthreadsafe alternative if unavail. + used in rrsig time validation errors. + +22 May 2008: Wouter + - contrib unbound.spec from Patrick Vande Walle. + - fixup bug#175: call tzset before chroot to have correct timestamps + in system log. + - do not generate lex input and lex unput functions. + - mingw port. replacement functions labelled _unbound. + - fix bug 174 - check for tcp_sigpipe that ldns-testns is installed. + +19 May 2008: Wouter + - fedora 9, check in6_pktinfo define in configure. + - CREDITS fixup of history. + - ignore ldns-1.2.2 if installed, use builtin 1.3.0-pre alternative. + +16 May 2008: Wouter + - fixup for MacOSX hosts file reading (reported by John Dickinson). + - created 1.0.0 svn tag. + - trunk version 1.0.1. + +14 May 2008: Wouter + - accepted patch from Ondrej Sury for library version libtool option. + - configure --disable-rpath fixes up libtool for rpath trouble. + Adapted from debian package patch file. + +13 May 2008: Wouter + - Added root ipv6 addresses to builtin root hints. + - TODO modified for post 1.0 plans. + - trunk version set to 1.0.0. + - no unnecessary linking with librt (only when libevent/libev used). + +7 May 2008: Wouter + - fixup no-ip4 problem with error callback in outside network. + +25 April 2008: Wouter + - DESTDIR is honored by the Makefile for rpms. + - contrib files unbound.spec and unbound.init, builds working RPM + on FC7 Linux, a chrooted caching resolver, and libunbound. + - iana ports update. + +24 April 2008: Wouter + - chroot checks improved. working directory relative to chroot. + checks if config file path is inside chroot. Documentation on it. + - nicer example.conf text. + - created 0.11 tag. + +23 April 2008: Wouter + - parseunbound.pl contrib update from Kai Storbeck for threads. + - iana ports update + +22 April 2008: Wouter + - ignore SIGPIPE. + - unit test for SIGPIPE ignore. + +21 April 2008: Wouter + - FEATURES document. + - fixup reread of config file if it was given as a full path + and chroot was used. + +16 April 2008: Wouter + - requirements doc, updated clean query returns. + - parseunbound.pl update from Kai Storbeck. + - sunos4 porting changes. + +15 April 2008: Wouter + - fixup default rc.d pidfile location to /usr/local/etc. + - iana ports updated. + - copyright updated in ldns-testpkts to keep same as in ldns. + - fixup checkconf chroot tests a bit more, chdir must be inside + chroot dir. + - documented 'gcc: unrecognized -KPIC option' errors on Solaris. + - example.conf values changed to /usr/local/etc/unbound + - DSA test work. + - DSA signatures: unbound is compatible with both encodings found. + It will detect and convert when necessary. + +14 April 2008: Wouter + - got update for parseunbound.pl statistics script from Kai Storbeck. + - tpkg tests for udp wait list. + - documented 0x20 status. + - fixup chroot and checkconf, it is much smarter now. + - fixup DSA EVP signature decoding. Solution that Jelte found copied. + - and check first sig byte for the encoding type. + +11 April 2008: Wouter + - random port selection out of the configged ports. + - fixup threadsafety for libevent-1.4.3+ (event_base_get_method). + - removed base_port. + - created 256-port ephemeral space for the OS, 59802 available. + - fixup consistency of port_if out array during heavy use. + +10 April 2008: Wouter + - --with-libevent works with latest libevent 1.4.99-trunk. + - added log file statistics perl script to contrib. + - automatic iana ports update from makefile. 60058 available. + +9 April 2008: Wouter + - configure can detect libev(from its build directory) when passed + --with-libevent=/home/wouter/libev-3.2 + libev-3.2 is a little faster than libevent-1.4.3-stable (about 5%). + - unused commpoints not listed in epoll list. + - statistics-cumulative option so that the values are not reset. + - config creates array of available ports, 61841 available, + it excludes <1024 and iana assigned numbers. + config statements to modify the available port numbers. + +8 April 2008: Wouter + - unbound tries to set the ulimit fds when started as server. + if that does not work, it will scale back its requirements. + +27 March 2008: Wouter + - documented /dev/random symlink from chrootdir as FAQ entry. + +26 March 2008: Wouter + - implemented AD bit signaling. If a query sets AD bit (but not DO) + then the AD bit is set in the reply if the answer validated. + Without including DNSSEC signatures. Useful if you have a trusted + path from the client to the resolver. Follows dnssec-updates draft. + +25 March 2008: Wouter + - implemented check that for NXDOMAIN and NOERROR answers a query + section must be present in the reply (by the scrubber). And it must + be equal to the question sent, at least lowercase folded. + Previously this feature happened because the cache code refused + to store such messages. However blocking by the scrubber makes + sure nothing gets into the RRset cache. Also, this looks like a + timeout (instead of an allocation failure) and this retries are + done (which is useful in a spoofing situation). + - RTT banding. Band size 400 msec, this makes band around zero (fast) + include unknown servers. This makes unbound explore unknown servers. + +7 March 2008: Wouter + - -C config feature for harvest program. + - harvest handles CNAMEs too. + +5 March 2008: Wouter + - patch from Hugo Koji Kobayashi for iterator logs spelling. + +4 March 2008: Wouter + - From report by Jinmei Tatuya, rfc2181 trust value for remainder + of a cname trust chain is lower; not full answer_AA. + - test for this fix. + - default config file location is /usr/local/etc/unbound. + Thus prefix is used to determine the location. This is also the + chroot and pidfile default location. + +3 March 2008: Wouter + - Create 0.10 svn tag. + - 0.11 version in trunk. + - indentation nicer. + +29 February 2008: Wouter + - documentation update. + - fixup port to Solaris of perf test tool. + - updated ldns-tarball with decl-after-statement fixes. + +28 February 2008: Wouter + - fixed memory leaks in libunbound (during cancellation and wait). + - libunbound returns the answer packet in full. + - snprintf compat update. + - harvest performs lookup. + - ldns-tarball update with fix for ldns_dname_label. + - installs to sbin by default. + - install all manual pages (unbound-host and libunbound too). + +27 February 2008: Wouter + - option to use caps for id randomness. + - config file option use-caps-for-id: yes + - harvest debug tool + +26 February 2008: Wouter + - delay utility delays TCP as well. If the server that is forwarded + to has a TCP error, the delay utility closes the connection. + - delay does REUSE_ADDR, and can handle a server that closes its end. + - answers use casing from query. + +25 February 2008: Wouter + - delay utility works. Gets decent thoughput too (>20000). + +22 February 2008: Wouter + - +2% for recursions, if identical queries (except for destination + and query ID) in the reply list, avoid re-encoding the answer. + - removed TODO items for optimizations that do not show up in + profile reports. + - default is now minievent - not libevent. As its faster and + not needed for regular installs, only for very large port ranges. + - loop check different speedup pkt-dname-reading, 1% faster for + nocache-recursion check. + - less hashing during msg parse, 4% for recursion. + - small speed fix for dname_count_size_labels, +1 or +2% recursion. + - some speed results noted: + optimization resulted in +40% for recursion (cache miss) and + +70 to +80 for cache hits, and +96% for version.bind. + zone nsec3 example, 100 NXDOMAIN queries, NSD 35182.8 Ub 36048.4 + www.nlnetlabs.nl from cache: BIND 8987.99 Ub 31218.3 + www with DO bit set : BIND 8269.31 Ub 28735.6 qps. + So, unbound can be about equal qps to NSD in cache hits. + And about 3.4x faster than BIND in cache performance. + - delay utility for testing. + +21 February 2008: Wouter + - speedup of root-delegation message encoding by 15%. + - minor speedup of compress tree_lookup, maybe 1%. + - speedup of dname_lab_cmp and memlowercmp - the top functions in + profiler output, maybe a couple percent when it matters. + +20 February 2008: Wouter + - setup speec_cache for need-ldns-testns in dotests. + - check number of queued replies on incoming queries to avoid overload + on that account. + - fptr whitelist checks are not disabled in optimize mode. + - do-daemonize config file option. + - minievent time share initializes time at start. + - updated testdata for nsec3 new algorithm numbers (6, 7). + - small performance test of packet encoding (root delegation). + +19 February 2008: Wouter + - applied patch to unbound-host man page from Jan-Piet Mens. + - fix donotquery-localhost: yes default (it erroneously was switched + to default 'no'). + - time is only gotten once and the value is shared across unbound. + - unittest cleans up crypto, so that it has no memory leaks. + - mini_event shares the time value with unbound this results in + +3% speed for cache responses and +9% for recursions. + - ldns tarball update with new NSEC3 sign code numbers. + - perform several reads per UDP operation. This improves performance + in DoS conditions, and costs very little in normal conditions. + improves cache response +50%, and recursions +10%. + - modified asynclook test. because the callback from async is not + in any sort of lock (and thus can use all library functions freely), + this causes a tiny race condition window when the last lock is + released for a callback and a new cancel() for that callback. + The only way to remove this is by putting callbacks into some + lock window. I'd rather have the small possibility of a callback + for a cancelled function then no use of library functions in + callbacks. Could be possible to only outlaw process(), wait(), + cancel() from callbacks, by adding another lock, but I'd rather not. + +18 February 2008: Wouter + - patch to unbound-host from Jan-Piet Mens. + - unbound host prints errors if fails to configure context. + - fixup perf to resend faster, so that long waiting requests do + not hold up the queue, they become lost packets or SERVFAILs, + or can be sent a little while later (i.e. processing time may + take long, but throughput has to be high). + - fixup iterator operating in no cache conditions (RD flag unset + after a CNAME). + - streamlined code for RD flag setting. + - profiled code and changed dname compares to be faster. + The speedup is about +3% to +8% (depending on the test). + - minievent tests for eintr and eagain. + +15 February 2008: Wouter + - added FreeBSD rc.d script to contrib. + - --prefix option for configure also changes directory: pidfile: + and chroot: defaults in config file. + - added cache speed test, for cache size OK and cache too small. + +14 February 2008: Wouter + - start without a config file (will complain, but start with + defaults). + - perf test program works. + +13 February 2008: Wouter + - 0.9 released. + - 1.0 development. Printout ldns version on unbound -h. + - start of perf tool. + - bugfix to read empty lines from /etc/hosts. + +12 February 2008: Wouter + - fixup problem with configure calling itself if ldns-src tarball + is not present. + +11 February 2008: Wouter + - changed library to use ub_ instead of ub_val_ as prefix. + - statistics output text nice. + - etc/hosts handling. + - library function to put logging to a stream. + - set any option interface. + +8 February 2008: Wouter + - test program for multiple queries over a TCP channel. + - tpkg test for stream tcp queries. + - unbound replies to multiple TCP queries on a TCP channel. + - fixup misclassification of root referral with NS in answer + when validating a nonrec query. + - tag 0.9 + - layout of manpages, spelling fix in header, manpages process by + makedist, list asynclook and tcpstream tests as ldns-testns + required. + +7 February 2008: Wouter + - moved up all current level 2 to be level 3. And 3 to 4. + to make room for new debug level 2 for detailed information + for operators. + - verbosity level 2. Describes recursion and validation. + - cleaner configure script and fixes for libevent solaris. + - signedness for log output memory sizes in high verbosity. + +6 February 2008: Wouter + - clearer explanation of threading configure options. + - fixup asynclook test for nothreading (it creates only one process + to do the extended test). + - changed name of ub_val_result_free to ub_val_resolve_free. + - removes warning message during library linking, renamed + libunbound/unbound.c -> libunbound.c and worker to libworker. + - fallback without EDNS if result is NOTIMPL as well as on FORMERR. + +5 February 2008: Wouter + - statistics-interval: seconds option added. + - test for statistics option + - ignore errors making directories, these can occur in parallel builds + - fixup Makefile strip command and libunbound docs typo. + +31 January 2008: Wouter + - bg thread/process reads and writes the pipe nonblocking all the time + so that even if the pipe is buffered or so, the bg thread does not + block, and services both pipes and queries. + +30 January 2008: Wouter + - check trailing / on chrootdir in checkconf. + - check if root hints and anchor files are in chrootdir. + - no route to host tcp error is verbosity level 2. + - removed unused send_reply_iov. and its configure check. + - added prints of 'remote address is 1.2.3.4 port 53' to errors + from netevent; the basic socket errors. + +28 January 2008: Wouter + - fixup uninit use of buffer by libunbound (query id, flags) for + local_zone answers. + - fixup uninit warning from random.c; also seems to fix sporadic + sigFPE coming out of openssl. + - made openssl entropy warning more silent for library use. Needs + verbosity 1 now. + - fixup forgotten locks for rbtree_searches on ctx->query tree. + - random generator cleanup - RND_STATE_SIZE removed, and instead + a super-rnd can be passed at init to chain init random states. + - test also does lock checks if available. + - protect config access in libworker_setup(). + - libevent doesn't like comm_base_exit outside of runloop. + - close fds after removing commpoints only (for epoll, kqueue). + +25 January 2008: Wouter + - added tpkg for asynclook and library use. + - allows localhost to be queried when as a library. + - fixup race condition between cancel and answer (in case of + really fast answers that beat the cancel). + - please doxygen, put doxygen comment in one place. + - asynclook -b blocking mode and test. + - refactor asynclook, nicer code. + - fixup race problems from opensll in rand init from library, with + a mutex around the rand init. + - fix pass async_id=NULL to _async resolve(). + - rewrote _wait() routine, so that it is threadsafe. + - cancelation is threadsafe. + - asynclook extended test in tpkg. + - fixed two races where forked bg process waits for (somehow shared?) + locks, so does not service the query pipe on the bg side. + Now those locks are only held for fg_threads and for bg_as_a_thread. + +24 January 2008: Wouter + - tested the cancel() function. + - asynclook -c (cancel) feature. + - fix fail to allocate context actions. + - make pipe nonblocking at start. + - update plane for retry mode with caution to limit bandwidth. + - fix Makefile for concurrent make of unbound-host. + - renamed ub_val_ctx_wait/poll/process/fd to ub_val*. + - new calls to set forwarding added to header and docs. + +23 January 2008: Wouter + - removed debug prints from if-auto, verb-algo enables some. + - libunbound QUIT setup, remove memory leaks, when using threads + will share memory for passing results instead of writing it over + the pipe, only writes ID number over the pipe (towards the handler + thread that does process() ). + +22 January 2008: Wouter + - library code for async in libunbound/unbound.c. + - fix link testbound. + - fixup exit bug in mini_event. + - background worker query enter and result functions. + - bg query test application asynclook, it looks up multiple + hostaddresses (A records) at the same time. + +21 January 2008: Wouter + - libworker work, netevent raw commpoints, write_msg, serialize. + +18 January 2008: Wouter + - touch up of manpage for libunbound. + - support for IP_RECVDSTADDR (for *BSD ip4). + - fix for BSD, do not use ip4to6 mapping, make two sockets, once + ip6 and once ip4, uses socket options. + - goodbye ip4to6 mapping. + - update ldns-testpkts with latest version from ldns-trunk. + - updated makedist for relative ldns pathnames. + - library API with more information inside the result structure. + - work on background resolves. + +17 January 2008: Wouter + - fixup configure in case -lldns is installed. + - fixup a couple of doxygen warnings, about enum variables. + - interface-automatic now copies the interface address from the + PKT_INFO structure as well. + - manual page with library API, all on one page 'man libunbound'. + - rewrite of PKTINFO structure, it also captures IP4 PKTINFO. + +16 January 2008: Wouter + - incoming queries to the server with TC bit on are replied FORMERR. + - interface-automatic replied the wrong source address on localhost + queries. Seems to be due to ifnum=0 in recvmsg PKTINFO. Trying + to use ifnum=-1 to mean 'no interface, use kernel route'. + +15 January 2008: Wouter + - interface-automatic feature. experimental. Nice for anycast. + - tpkg test for ip6 ancillary data. + - removed debug prints. + - porting experience, define for Solaris, test refined for BSD + compatibility. The feature probably will not work on OpenBSD. + - makedist fixup for ldns-src in build-dir. + +14 January 2008: Wouter + - in no debug sets NDEBUG to remove asserts. + - configure --enable-debug is needed for dependency generation + for assertions and for compiler warnings. + - ldns.tgz updated with ldns-trunk (where buffer.h is updated). + - fix lint, unit test in optimize mode. + - default access control allows ::ffff:127.0.0.1 v6mapped localhost. + +11 January 2008: Wouter + - man page, warning removed. + - added text describing the use of stub zones for private zones. + - checkconf tests for bad hostnames (IP address), and for doubled + interface lines. + - memory sizes can be given with 'k', 'Kb', or M or G appended. + +10 January 2008: Wouter + - typo in example.conf. + - made using ldns-src that is included the package more portable + by linking with .lo instead of .o files in the ldns package. + - nicer do-ip6: yes/no documentation. + - nicer linking of libevent .o files. + - man pages render correctly on solaris. + +9 January 2008: Wouter + - fixup openssl RAND problem, when the system is not configured to + give entropy, and the rng needs to be seeded. + +8 January 2008: Wouter + - print median and quartiles with extensive logging. + +4 January 2008: Wouter + - document misconfiguration in private network. + +2 January 2008: Wouter + - fixup typo in requirements. + - document that 'refused' is a better choice than 'drop' for + the access control list, as refused will stop retries. + +7 December 2007: Wouter + - unbound-host has a -d option to show what happens. This can help + with debugging (why do I get this answer). + - fixup CNAME handling, on nodata, sets and display canonname. + - dot removed from CNAME display. + - respect -v for NXDOMAINs. + - updated ldns-src.tar.gz with ldns-trunk today (1.2.2 fixes). + - size_t to int for portability of the header file. + - fixup bogus handling. + - dependencies and lint for unbound-host. + +6 December 2007: Wouter + - library resolution works in foreground mode, unbound-host app + receives data. + - unbound-host prints rdata using ldns. + - unbound-host accepts trust anchors, and prints validation + information when you give -v. + +5 December 2007: Wouter + - locking in context_new() inside the function. + - setup of libworker. + +4 December 2007: Wouter + - minor Makefile fixup. + - moved module-stack code out of daemon/daemon into services/modstack, + preparing for code-reuse. + - move context into own header file. + - context query structure. + - removed unused variable pwd from checkconf. + - removed unused assignment from outside netw. + - check timeval length of string. + - fixup error in val_utils getsigner. + - fixup same (*var) error in netblocktostr. + - fixup memleak on parse error in localzone. + - fixup memleak on packet parse error. + - put ; after union in parser.y. + - small hardening in iter_operate against iq==NULL. + - hardening, if error reply with rcode=0 (noerror) send servfail. + - fixup same (*var) error in find_rrset in msgparse, was harmless. + - check return value of evtimer_add(). + - fixup lockorder in lruhash_reclaim(), building up a list of locked + entries one at a time. Instead they are removed and unlocked. + - fptr_wlist for markdelfunc. + - removed is_locked param from lruhash delkeyfunc. + - moved bin_unlock during bin_split purely to please. + +3 December 2007: Wouter + - changed checkconf/ to smallapp/ to make room for more support tools. + (such as unbound-host). + - install dirs created with -m 755 because they need to be accessible. + - library extensive featurelist added to TODO. + - please doxygen, lint. + - library test application, with basic functionality. + - fix for building in a subdirectory. + - link lib fix for Leopard. + +30 November 2007: Wouter + - makefile that creates libunbound.la, basic file or libunbound.a + when creating static executables (no libtool). + - more API setup. + +29 November 2007: Wouter + - 0.9 public API start. + +28 November 2007: Wouter + - Changeup plan for 0.8 - no complication needed, a simple solution + has been chosen for authoritative features. + - you can use single quotes in the config file, so it is possible + to specify TXT records in local data. + - fixup small memory problem in implicit transparent zone creation. + - test for implicit zone creation and multiple RR RRsets local data. + - local-zone nodefault test. + - show testbound testlist on commit. + - iterator normalizer changes CNAME chains ending in NXDOMAIN where + the packet got rcode NXDOMAIN into rcode NOERROR. (since the initial + domain exists). + - nicer verbosity: 0 and 1 levels. + - lower nonRDquery chance of eliciting wrongly typed validation + requiring message from the cache. + - fix for nonRDquery validation typing; nodata is detected when + SOA record in auth section (all validation-requiring nodata messages + have a SOA record in authority, so this is OK for the validator), + and NS record is needed to be a referral. + - duplicate checking when adding NSECs for a CNAME, and test. + - created svn tag 0.8, after completing testbed tests. + +27 November 2007: Wouter + - per suggestion in rfc2308, replaced default max-ttl value with 1 day. + - set size of msgparse lookup table to 32, from 1024, so that its size + is below the 2048 regional large size threshold, and does not cause + a call to malloc when a message is parsed. + - update of memstats tool to print number of allocation calls. + This is what is taking time (not space) and indicates the avg size + of the allocations as well. region_alloc stat is removed. + +22 November 2007: Wouter + - noted EDNS in-the-middle dropping trouble as a TODO. + At this point theoretical, no user trouble has been reported. + - added all default AS112 zones. + - answers from local zone content. + * positive answer, the rrset in question + * nodata answer (exist, but not that type). + * nxdomain answer (domain does not exist). + * empty-nonterminal answer. + * But not: wildcard, nsec, referral, rrsig, cname/dname, + or additional section processing, NS put in auth. + - test for correct working of static and transparent and couple + of important defaults (localhost, as112, reverses). + Also checks deny and refuse settings. + - fixup implicit zone generation and AA bit for NXDOMAIN on localdata. + +21 November 2007: Wouter + - local zone internal data setup. + +20 November 2007: Wouter + - 0.8 - str2list config support for double string config options. + - local-zone and local-data options, config storage and documentation. + +19 November 2007: Wouter + - do not downcase NSEC and RRSIG for verification. Follows + draft-ietf-dnsext-dnssec-bis-updates-06.txt. + - fixup leaking unbound daemons at end of tests. + - README file updated. + - nice libevent not found error. + - README talks about gnu make. + - 0.8: unit test for addr_mask and fixups for it. + and unit test for addr_in_common(). + - 0.8: access-control config file element. + and unit test rpl replay file. + - 0.8: fixup address reporting from netevent. + +16 November 2007: Wouter + - privilege separation is not needed in unbound at this time. + TODO item marked as such. + - created beta-0.7 branch for support. + - tagged 0.7 for beta release. + - moved trunk to 0.8 for 0.8(auth features) development. + - 0.8: access control list setup. + +15 November 2007: Wouter + - review fixups from Jelte. + +14 November 2007: Wouter + - testbed script does not recreate configure, since its in svn now. + - fixup checkconf test so that it does not test + /etc/unbound/unbound.conf. + - tag 0.6. + +13 November 2007: Wouter + - remove debug print. + - fixup testbound exit when LIBEVENT_SIGNAL_PROBLEM exists. + +12 November 2007: Wouter + - fixup signal handling where SIGTERM could be ignored if a SIGHUP + arrives later on. + - bugreports to unbound-bugs@nlnetlabs.nl + - fixup testbound so it exits cleanly. + - cleanup the caches on a reload, so that rrsetID numbers won't clash. + +9 November 2007: Wouter + - took ldns snapshot in repo. + - default config file is /etc/unbound/unbound.conf. + If it doesn't exist, it is installed with the doc/example.conf file. + The file is not deleted on uninstall. + - default listening is not all, but localhost interfaces. + +8 November 2007: Wouter + - Fixup chroot and drop user privileges. + - new L root ip address in default hints. + +1 November 2007: Wouter + - Fixup of crash on reload, due to anchors in env not NULLed after + dealloc during deinit. + - Fixup of chroot call. Happens after privileges are dropped, so + that checking the passwd entry still works. + - minor touch up of clear() hashtable function. + - VERB_DETAIL prints out what chdir, username, chroot is being done. + - when id numbers run out, caches are cleared, as in design notes. + Tested with a mock setup with very few bits in id, it worked. + - harden-dnssec-stripped: yes is now default. It insists on dnssec + data for trust anchors. Included tests for the feature. + +31 October 2007: Wouter + - cache-max-ttl config option. + - building outside sourcedir works again. + - defaults more secure: + username: "unbound" + chroot: "/etc/unbound" + The operator can override them to be less secure ("") if necessary. + - fix horrible oversight in sorting rrset references in a message, + sort per reference key pointer, not on referencepointer itself. + - pidfile: "/etc/unbound/unbound.pid" is now the default. + - tests changed to reflect the updated default. + - created hashtable clear() function that respects locks. + +30 October 2007: Wouter + - fixup assertion failure that relied on compressed names to be + smaller than uncompressed names. A packet from comrite.com was seen + to be compressed to a larger size. Added it as unit test. + - quieter logging at low verbosity level for common tcp messages. + - no greedy TTL update. + +23 October 2007: Wouter + - fixup (grand-)parent problem for dnssec-lameness detection. + - fixup tests to do additional section processing for lame replies, + since the detection needs that. + - no longer trust in query section in reply during dnssec lame detect. + - dnssec lameness does not make the server never ever queried, but + non-preferred. If no other servers exist or answer, the dnssec lame + server is used; the fastest dnssec lame server is chosen. + - added test then when trust anchor cannot be primed (nodata), the + insecure mode from unbound works. + - Fixup max queries per thread, any more are dropped. + +22 October 2007: Wouter + - added donotquerylocalhost config option. Can be turned off for + out test cases. + - ISO C compat changes. + - detect RA-no-AA lameness, as LAME. + - DNSSEC-lameness detection, as LAME. + See notes in requirements.txt for choices made. + - tests for lameness detection. + - added all to make test target; need unbound for fwd tests. + - testbound does not pollute /etc/unbound. + +19 October 2007: Wouter + - added configure (and its files) to svn, so that the trunk is easier + to use. ./configure, config.guess, config.sub, ltmain.sh, + and config.h.in. + - added yacc/lex generated files, util/configlexer.c, + util/configparser.c util/configparser.h, to svn. + - without lex no attempt to use it. + - unsecure response validation collated into one block. + - remove warning about const cast of cfgfile name. + - outgoing-interfaces can be different from service interfaces. + - ldns-src configure is done during unbound configure and + ldns-src make is done during unbound make, and so inherits the + make arguments from the unbound make invocation. + - nicer error when libevent problem causes instant exit on signal. + - read root hints from a root hint file (like BIND does). + +18 October 2007: Wouter + - addresses are logged with errors. + - fixup testcode fake event to remove pending before callback + since the callback may create new pending items. + - tests updated because retries are now in iterator module. + - ldns-testpkts code is checked for differences between unbound + and ldns by makedist.sh. + - ldns trunk from today added in svn repo for fallback in case + no ldns is installed on the system. + make download_ldns refreshes the tarball with ldns svn trunk. + - ldns-src.tar.gz is used if no ldns is found on the system, and + statically linked into unbound. + - start of regional allocator code. + - regional uses less memory and variables, simplified code. + - remove of region-allocator. + - alloc cache keeps a cache of recently released regional blocks, + up to a maximum. + - make unit test cleanly free memory. + +17 October 2007: Wouter + - fixup another cycle detect and ns-addr timeout resolution bug. + This time by refusing delegations from the cache without addresses + when resolving a mandatory-glue nameserver-address for that zone. + We're going to have to ask a TLD server anyway; might as well be + the TLD server for this name. And this resolves a lot of cases where + the other nameserver names lead to cycles or are not available. + - changed random generator from random(3) clone to arc4random wrapped + for thread safety. The random generator is initialised with + entropy from the system. + - fix crash where failure to prime DNSKEY tried to print null pointer + in the log message. + - removed some debug prints, only verb_algo (4) enables them. + - fixup test; new random generator took new paths; such as one + where no scripted answer was available. + - mark insecure RRs as insecure. + - fixup removal of nonsecure items from the additional. + - reduced timeout values to more realistic, 376 msec (262 msec has + 90% of roundtrip times, 512 msec has 99% of roundtrip times.) + - server selection failover to next server after timeout (376 msec). + +16 October 2007: Wouter + - no malloc in log_hex. + - assertions around system calls. + - protect against gethostname without ending zero. + - ntop output is null terminated by unbound. + - pidfile content null termination + - various snprintf use sizeof(stringbuf) instead of fixed constant. + - changed loopdetect % 8 with & 0x7 since % can become negative for + weird negative input and particular interpretation of integer math. + - dname_pkt_copy checks length of result, to protect result buffers. + prints an error, this should not happen. Bad strings should have + been rejected earlier in the program. + - remove a size_t underflow from msgreply size func. + +15 October 2007: Wouter + - nicer warning. + - fix IP6 TCP, wrong definition check. With test package. + - fixup the fact that the query section was not compressed to, + the code was there but was called by value instead of by reference. + And test for the case, uses xxd and nc. + - more portable ip6 check for sockaddr types. + +8 October 2007: Wouter + - --disable-rpath option in configure for 64bit systems with + several dynamic lib dirs. + +7 October 2007: Wouter + - fixup tests for no AD bit in non-DO queries. + - test that makes sure AD bit is not set on non-DO query. + +6 October 2007: Wouter + - removed logfile open early. It did not have the proper permissions; + it was opened as root instead of the user. And we cannot change user + id yet, since chroot and bind ports need to be done. + - callback checks for event callbacks done from mini_event. Because + of deletions cannot do this from netevent. This means when using + libevent the protection does not work on event-callbacks. + - fixup too small reply (did not zero counts). + - fixup reply no longer AD bit when query without DO bit. + +5 October 2007: Wouter + - function pointer whitelist. + +4 October 2007: Wouter + - overwrite sensitive random seed value after use. + - switch to logfile very soon if not -d (console attached). + - error messages do not reveal the trustanchor contents. + - start work on function pointer whitelists. + +3 October 2007: Wouter + - fix for multiple empty nonterminals, after multiple DSes in the + chain of trust. + - mesh checks if modules are looping, and stops them. + - refetch with CNAMEd nameserver address regression test added. + - fixup line count bug in testcode, so testbound prints correct line + number with parse errors. + - unit test for multiple ENT case. + - fix for cname out of validated unsec zone. + - fixup nasty id=0 reuse. Also added assertions to detect its + return (the assertion catches in the existing test cases). + +1 October 2007: Wouter + - skip F77, CXX, objC tests in configure step. + - fixup crash in refetch glue after a CNAME. + and protection against similar failures (with error print). + +28 September 2007: Wouter + - test case for unbound-checkconf, fixed so it also checks the + interface: statements. + +26 September 2007: Wouter + - SIGHUP will reopen the log file. + - Option to log to syslog. + - please lint, fixup tests (that went to syslog on open, oops). + - config check program. + +25 September 2007: Wouter + - tests for NSEC3. Fixup bitmap checks for NSEC3. + - positive ANY response needs to check if wildcard expansion, and + check that original data did not exist. + - tests for NSEC3 that wrong use of OPTOUT is bad. For insecure + delegation, for abuse of child zone apex nsec3. + - create 0.5 release tag. + +24 September 2007: Wouter + - do not make test programs by default. + - But 'make test' will perform all of the tests. + - Advertise builtin select libevent alternative when no libevent + is found. + - signit can generate NSEC3 hashes, for generating tests. + - multiple nsec3 paramaters in message test. + - too high nsec3 iterations becomes insecure test. + +21 September 2007: Wouter + - fixup empty_DS_name allocated in wrong region (port DEC Alpha). + - fixup testcode lock safety (port FreeBSD). + - removes subscript has type char warnings (port Solaris 9). + - fixup of field with format type to int (port MacOS/X intel). + - added test for infinite loop case in nonRD answer validation. + It was a more general problem, but hard to reproduce. When an + unsigned rrset is being validated and the key fetched, the DS + sequence is followed, but if the final name has no DS, then no + proof is possible - the signature has been stripped off. + +20 September 2007: Wouter + - fixup and test for NSEC wildcard with empty nonterminals. + - makedist.sh fixup for svn info. + - acl features request in plan. + - improved DS empty nonterminal handling. + - compat with ANS nxdomain for empty nonterminals. Attempts the nodata + proof anyway, which succeeds in ANS failure case. + - striplab protection in case it becomes -1. + - plans for static and blacklist config. + +19 September 2007: Wouter + - comments about non-packed usage. + - plan for overload support in 0.6. + - added testbound tests for a failed resolution from the logs + and for failed prime when missing glue. + - fixup so useless delegation points are not returned from the + cache. Also the safety belt is used if priming fails to complete. + - fixup NSEC rdata not to be lowercased, bind compat. + +18 September 2007: Wouter + - wildcard nsec3 testcases, and fixup to get correct wildcard name. + - validator prints subtype classification for debug. + +17 September 2007: Wouter + - NSEC3 hash cache unit test. + - validator nsec3 nameerror test. + +14 September 2007: Wouter + - nsec3 nodata proof, nods proof, wildcard proof. + - nsec3 support for cname chain ending in noerror or nodata. + - validator calls nsec3 proof routines if no NSECs prove anything. + - fixup iterator bug where it stored the answer to a cname under + the wrong qname into the cache. When prepending the cnames, the + qname has to be reset to the original qname. + +13 September 2007: Wouter + - nsec3 find matching and covering, ce proof, prove namerror msg. + +12 September 2007: Wouter + - fixup of manual page warnings, like for NSD bugreport. + - nsec3 work, config, max iterations, filter, and hash cache. + +6 September 2007: Wouter + - fixup to find libevent on mac port install. + - fixup size_t vs unsigned portability in validator/sigcrypt. + - please compiler on different platforms, for unreachable code. + - val_nsec3 file. + - pthread_rwlock type is optional, in case of old pthread libs. + +5 September 2007: Wouter + - cname, name error validator tests. + - logging of qtype ANY works. + - ANY type answers get RRSIG in answer section of replies (but not + in other sections, unless DO bit is on). + - testbound can replay a TCP query (set MATCH TCP in the QUERY). + - DS and noDS referral validation test. + - if you configure many trust anchors, parent trust anchors can + securely deny existance of child trust anchors, if validated. + - not all *.name NSECs are present because a wildcard was matched, + and *.name NSECs can prove nodata for empty nonterminals. + Also, for wildcard name NSECs, check they are not from the parent + zone (for wildcarded zone cuts), and check absence of CNAME bit, + for a nodata proof. + - configure option for memory allocation debugging. + - port configure option for memory allocation to solaris10. + +4 September 2007: Wouter + - fixup of Leakage warning when serviced queries processed multiple + callbacks for the same query from the same server. + - testbound removes config file from /tmp on failed exit. + - fixup for referral cleanup of the additional section. + - tests for cname, referral validation. + - neater testbound tpkg output. + - DNAMEs no longer match their apex when synthesized from the cache. + - find correct signer name for DNAME responses. + - wildcarded DNAME test and fixup code to detect. + - prepend NSEC and NSEC3 rrsets in the iterator while chasing CNAMEs. + So that wildcarded CNAMEs get their NSEC with them to the answer. + - test for a CNAME to a DNAME to a CNAME to an answer, all from + different domains, for key fetching and signature checking of + CNAME'd messages. + +3 September 2007: Wouter + - Fixed error in iterator that would cause assertion failure in + validator. CNAME to a NXDOMAIN response was collated into a response + with both a CNAME and the NXDOMAIN rcode. Added a test that the + rcode is changed to NOERROR (because of the CNAME). + - timeout on tcp does not lead to spurious leakage detect. + - account memory for name of lame zones, so that memory leakages does + not show lame cache growth as a leakage growth. + - config setting for lameness cache expressed in bytes, instead of + number of entries. + - tool too summarize allocations per code line. + +31 August 2007: Wouter + - can read bind trusted-keys { ... }; files, in a compatibility mode. + - iterator should not detach target queries that it still could need. + the protection against multiple outstanding queries is moved to a + current_query num check. + - validator nodata, positive, referral tests. + - dname print can print '*' wildcard. + +30 August 2007: Wouter + - fixup override date config option. + - config options to control memory usage. + - caught bad free of un-alloced data in worker_send error case. + - memory accounting for key cache (trust anchors and temporary cache). + - memory accounting fixup for outside network tcp pending waits. + - memory accounting fixup for outside network tcp callbacks. + - memory accounting for iterator fixed storage. + - key cache size and slabs config options. + - lib crypto cleanups at exit. + +29 August 2007: Wouter + - test tool to sign rrsets for testing validator with. + - added RSA and DSA test keys, public and private pairs, 512 bits. + - default configuration is with validation enabled. + Only a trust-anchor needs to be configured for DNSSEC to work. + - do not convert to DER for DSA signature verification. + - validator replay test file, for a DS to DNSKEY DSA key prime and + positive response. + +28 August 2007: Wouter + - removed double use for udp buffers, that could fail, + instead performs a malloc to do the backup. + - validator validates referral messages, by validating all the rrsets + and stores the rrsets in the cache. Further referral (nonRD queries) + replies are made from the rrset cache directly. Unless unchecked + rrsets are encountered, there are then validated. + - enforce that signing is done by a parent domain (or same domain). + - adjust TTL downwards if rrset TTL bigger than signature allows. + - permissive mode feature, sets AD bit for secure, but bogus does + not give servfail (bogus is changed into indeterminate). + - optimization of rrset verification. rr canonical sorting is reused, + for the same rrset. canonical rrset image in buffer is reused for + the same signature. + - if the rrset is too big (64k exactly + large owner name) the + canonicalization routine will fail if it does not fit in buffer. + - faster verification for large sigsets. + - verb_detail mode reports validation failures, but not the entire + algorithm for validation. Key prime failures are reported as + verb_ops level. + +27 August 2007: Wouter + - do not garble the edns if a cache answer fails. + - answer norecursive from cache if possible. + - honor clean_additional setting when returning secure non-recursive + referrals. + - do not store referral in msg cache for nonRD queries. + - store verification status in the rrset cache to speed up future + verification. + - mark rrsets indeterminate and insecure if they are found to be so. + and store this in the cache. + +24 August 2007: Wouter + - message is bogus if unsecure authority rrsets are present. + - val-clean-additional option, so you can turn it off. + - move rrset verification out of the specific proof types into one + routine. This makes the proof routines prettier. + - fixup cname handling in validator, cname-to-positive and cname-to- + nodata work. + - Do not synthesize DNSKEY and DS responses from the rrset cache if + the rrset is from the additional section. Signatures may have + fallen off the packet, and cause validation failure. + - more verbose signature date errors (with the date attached). + - increased default infrastructure cache size. It is important for + performance, and 1000 entries are only 212k (or a 400 k total cache + size). To 10000 entries (for 2M entries, 4M cache size). + +23 August 2007: Wouter + - CNAME handling - move needs_validation to before val_new(). + val_new() setups the chase-reply to be an edited copy of the msg. + new classification, and find signer can find for it. + removal of unsigned crap from additional, and query restart for + cname. + - refuse to follow wildcarded DNAMEs when validating. + But you can query for qtype ANY, or qtype DNAME and validate that. + +22 August 2007: Wouter + - bogus TTL. + - review - use val_error(). + +21 August 2007: Wouter + - ANY response validation. + - store security status in cache. + - check cache security status and either send the query to be + validated, return the query to client, or send servfail to client. + Sets AD bit on validated replies. + - do not examine security status on an error reply in mesh_done. + - construct DS, DNSKEY messages from rrset cache. + - manual page entry for override-date. + +20 August 2007: Wouter + - validate and positive validation, positive wildcard NSEC validation. + - nodata validation, nxdomain validation. + +18 August 2007: Wouter + - process DNSKEY response in FINDKEY state. + +17 August 2007: Wouter + - work on DS2KE routine. + - val_nsec.c for validator NSEC proofs. + - unit test for NSEC bitmap reading. + - dname iswild and canonical_compare with unit tests. + +16 August 2007: Wouter + - DS sig unit test. + - latest release libevent 1.3c and 1.3d have threading fixed. + - key entry fixup data pointer and ttl absolute. + - This makes a key-prime succeed in validator, with DS or DNSKEY as + trust-anchor. + - fixup canonical compare byfield routine, fix bug and also neater. + - fixed iterator response type classification for queries of type + ANY and NS. + dig ANY gives sometimes NS rrset in AN and NS section, and parser + removes the NS section duplicate. dig NS gives sometimes the NS + in the answer section, as referral. + - validator FINDKEY state. + +15 August 2007: Wouter + - crypto calls to verify signatures. + - unit test for rrsig verification. + +14 August 2007: Wouter + - default outgoing ports changed to avoid port 2049 by default. + This port is widely blocked by firewalls. + - count infra lameness cache in memory size. + - accounting of memory improved + - outbound entries are allocated in the query region they are for. + - extensive debugging for memory allocations. + - --enable-lock-checks can be used to enable lock checking. + - protect undefs in config.h from autoheaders ministrations. + - print all received udp packets. log hex will print on multiple + lines if needed. + - fixed error in parser with backwards rrsig references. + - mark cycle targets for iterator did not have CD flag so failed + its task. + +13 August 2007: Wouter + - fixup makefile, if lexer is missing give nice error and do not + mess up the dependencies. + - canonical compare routine updated. + - canonical hinfo compare. + - printout list of the queries that the mesh is working on. + +10 August 2007: Wouter + - malloc and free overrides that track total allocation and frees. + for memory debugging. + - work on canonical sort. + +9 August 2007: Wouter + - canonicalization, signature checks + - dname signature label count and unit test. + - added debug heap size print to memory printout. + - typo fixup in worker.c + - -R needed on solaris. + - validator override option for date check testing. + +8 August 2007: Wouter + - ldns _raw routines created (in ldns trunk). + - sigcrypt DS digest routines + - val_utils uses sigcrypt to perform signature cryptography. + - sigcrypt keyset processing + +7 August 2007: Wouter + - security status type. + - security status is copied when rdata is equal for rrsets. + - rrset id is updated to invalidate all the message cache entries + that refer to NSEC, NSEC3, DNAME rrsets that have changed. + - val_util work + - val_sigcrypt file for validator signature checks. + +6 August 2007: Wouter + - key cache for validator. + - moved isroot and dellabel to own dname routines, with unit test. + +3 August 2007: Wouter + - replanning. + - scrubber check section of lame NS set. + - trust anchors can be in config file or read from zone file, + DS and DNSKEY entries. + - unit test trust anchor storage. + - trust anchors converted to packed rrsets. + - key entry definition. + +2 August 2007: Wouter + - configure change for latest libevent trunk version (needs -lrt). + - query_done and walk_supers are moved out of module interface. + - fixup delegation point duplicates. + - fixup iterator scrubber; lame NS set is let through the scrubber + so that the classification is lame. + - validator module exists, and does nothing but pass through, + with calling of next module and return. + - validator work. + +1 August 2007: Wouter + - set version to 0.5 + - module work for module to module interconnections. + - config of modules. + - detect cycle takes flags. + +31 July 2007: Wouter + - updated plan + - release 0.4 tag. + +30 July 2007: Wouter + - changed random state init, so that sequential process IDs are not + cancelled out by sequential thread-ids in the random number seed. + - the fwd_three test, which sends three queries to unbound, and + unbound is kept waiting by ldns-testns for 3 seconds, failed + because the retry timeout for default by unbound is 3 seconds too, + it would hit that timeout and fail the test. Changed so that unbound + is kept waiting for 2 seconds instead. + +27 July 2007: Wouter + - removed useless -C debug option. It did not work. + - text edit of documentation. + - added doc/CREDITS file, referred to by the manpages. + - updated planning. + +26 July 2007: Wouter + - cycle detection, for query state dependencies. Will attempt to + circumvent the cycle, but if no other targets available fails. + - unit test for AXFR, IXFR response. + - test for cycle detection. + +25 July 2007: Wouter + - testbound read ADDRESS and check it. + - test for version.bind and friends. + - test for iterator chaining through several referrals. + - test and fixup for refetch for glue. Refetch fails if glue + is still not provided. + +24 July 2007: Wouter + - Example section in config manual. + - Addr stored for range and moment in replay. + +20 July 2007: Wouter + - Check CNAME chain before returning cache entry with CNAMEs. + - Option harden-glue, default is on. It will discard out of zone + data. If disabled, performance is faster, but spoofing attempts + become a possibility. Note that still normalize scrubbing is done, + and that the potentially spoofed data is used for infrastructure + and not returned to the client. + - if glue times out, refetch by asking parent of delegation again. + Much like asking for DS at the parent side. + - TODO items from forgery-resilience draft. + and on memory handling improvements. + - renamed module_event_timeout to module_event_noreply. + - memory reporting code; reports on memory usage after handling + a network packet (not on cache replies). + +19 July 2007: Wouter + - shuffle NS selection when getting nameserver target addresses. + - fixup of deadlock warnings, yield cpu in checklock code so that + freebsd scheduler selects correct process to run. + - added identity and version config options and replies. + - store cname messages complete answers. + +18 July 2007: Wouter + - do not query addresses, 127.0.0.1, and ::1 by default. + +17 July 2007: Wouter + - forward zone options in config file. + - forward per zone in iterator. takes precendence over stubs. + - fixup commithooks. + - removed forward-to and forward-to-port features, subsumed by + new forward zones. + - fix parser to handle absent server: clause. + - change untrusted rrset test to account for scrubber that is now + applied during the test (which removes the poison, by the way). + - feature, addresses can be specified with @portnumber, like nsd.conf. + - test config files changed over to new forwarder syntax. + +27 June 2007: Wouter + - delete of mesh does a postorder traverse of the tree. + - found and fixed a memory leak. For TTL=0 messages, that would + not be cached, instead the msg-replyinfo structure was leaked. + - changed server selection so it will filter out hosts that are + unresponsive. This is defined as a host with the maximum rto value. + This means that unbound tried the host for retries up to 120 secs. + The rto value will time out after host-ttl seconds from the cache. + This keeps such unresolvable queries from taking up resources. + - utility for keeping histogram. + +26 June 2007: Wouter + - mesh is called by worker, and iterator uses it. + This removes the hierarchical code. + QueryTargets state and Finished state are merged for iterator. + - forwarder mode no longer sets AA bit on first reply. + - rcode in walk_supers is not needed. + +25 June 2007: Wouter + - more mesh work. + - error encode routine for ease. + +22 June 2007: Wouter + - removed unused _node iterator value from rbtree_t. Takes up space. + - iterator can handle querytargets state without a delegation point + set, so that a priming(stub) subquery error can be handled. + - iterator stores if it is priming or not. + - log_query_info() neater logging. + - changed iterator so that it does not alter module_qstate.qinfo + but keeps a chase query info. Also query_flags are not altered, + the iterator uses chase_flags. + - fixup crash in case no ports for the family exist. + +21 June 2007: Wouter + - Fixup secondary buffer in case of error callback. + - cleanup slumber list of runnable states. + - module_subreq_depth fails to work in slumber list. + - fixup query release for cached results to sub targets. + - neater error for tcp connection failure, shows addr in verbose. + - rbtree_init so that it can be used with preallocated memory. + +20 June 2007: Wouter + - new -C option to enable coredumps after forking away. + - doc update. + - fixup CNAME generation by scrubber, and memory allocation of it. + - fixup deletion of serviced queries when all callbacks delete too. + - set num target queries to 0 when you move them to slumber list. + - typo in check caused subquery errors to be ignored, fixed. + - make lint happy about rlim_t. + - freeup of modules after freeup of module-states. + - duplicate replies work, this uses secondary udp buffer in outnet. + +19 June 2007: Wouter + - nicer layout in stats.c, review 0.3 change. + - spelling improvement, review 0.3 change. + - uncapped timeout for server selection, so that very fast or slow + servers will stand out from the rest. + - target-fetch-policy: "3 2 1 0 0" config setting. + - fixup queries answered without RD bit (for root prime results). + - refuse AXFR and IXFR requests. + - fixup RD flag in error reply from iterator. fixup RA flag from + worker error reply. + - fixup encoding of very short edns buffer sizes, now sets TC bit. + - config options harden-short-bufsize and harden-large-queries. + +18 June 2007: Wouter + - same, move subqueries to slumber list when first has resolved. + - fixup last fix for duplicate callbacks. + - another offbyone in targetcounter. Also in Java prototype by the way. + +15 June 2007: Wouter + - if a query asks to be notified of the same serviced query result + multiple times, this will succeed. Only one callback will happen; + multiple outbound-list entries result (but the double cleanup of it + will not matter). + - when iterator moves on due to CNAME or referral, it will remove + the subqueries (for other targets). These are put on the slumber + list. + - state module wait subq is OK with no new subqs, an old one may have + stopped, with an error, and it is still waiting for other ones. + - if a query loops, halt entire query (easy way to clean up properly). + +14 June 2007: Wouter + - num query targets was > 0 , not >= 0 compared, so that fetch + policy of 0 did nothing. + +13 June 2007: Wouter + - debug option: configure --enable-static-exe for compile where + ldns and libevent are linked statically. Default is off. + - make install and make uninstall. Works with static-exe and without. + installation of unbound binary and manual pages. + - alignement problem fix on solaris 64. + - fixup address in case of TCP error. + +12 June 2007: Wouter + - num target queries was set to 0 at a bad time. Default it to 0 and + increase as target queries are done. + - synthesize CNAME and DNAME responses from the cache. + - Updated doxygen config for doxygen 1.5. + - aclocal newer version. + - doxygen 1.5 fixes for comments (for the strict check on docs). + +11 June 2007: Wouter + - replies on TCP queries have the address field set in replyinfo, + for serviced queries, because the initiator does not know that + a TCP fallback has occured. + - omit DNSSEC types from nonDO replies, except if qtype is ANY or + if qtype directly queries for the type (and then only show that + 'unknown type' in the answer section). + - fixed message parsing where rrsigs on their own would be put + in the signature list over the rrsig type. + +7 June 2007: Wouter + - fixup error in double linked list insertion for subqueries and + for outbound list of serviced queries for iterator module. + - nicer printout of outgoing port selection. + - fixup cname target readout. + - nicer debug output. + - fixup rrset counts when prepending CNAMEs to the answer. + - fixup rrset TTL for prepended CNAMEs. + - process better check for looping modules, and which submodule to + run next. + - subreq insertion code fixup for slumber list. + - VERB_DETAIL, verbosity: 2 level gives short but readable output. + VERB_ALGO, verbosity: 3 gives extensive output. + - fixup RA bit in cached replies. + - fixup CNAME responses from the cache no longer partial response. + - error in network send handled without leakage. + - enable ip6 from config, and try ip6 addresses if available, + if ip6 is not connected, skips to next server. + +5 June 2007: Wouter + - iterator state finished. + - subrequests without parent store in cache and stop. + - worker slumber list for ongoing promiscuous queries. + - subrequest error handling. + - priming failure returns SERVFAIL. + - priming gives LAME result, returns SERVFAIL. + - debug routine to print dns_msg as handled by iterator. + - memleak in config file stubs fixup. + - more small bugs, in scrubber, query compare no ID for lookup, + in dname validation for NS targets. + - sets entry.key for new special allocs. + - lognametypeclass can display unknown types and classes. + +4 June 2007: Wouter + - random selection of equally preferred nameserver targets. + - reply info copy routine. Reuses existing code. + - cache lameness in response handling. + - do not touch qstate after worker_process_query because it may have + been deleted by that routine. + - Prime response state. + - Process target response state. + - some memcmp changed to dname_compare for case preservation. + +1 June 2007: Wouter + - normalize incoming messages. Like unbound-java, with CNAME chain + checked, DNAME checked, CNAME's synthesized, glue checked. + - sanitize incoming messages. + - split msgreply encode functions into own file msgencode.c. + - msg_parse to queryinfo/replyinfo conversion more versatile. + - process_response, classify response, delegpt_from_message. + +31 May 2007: Wouter + - querytargets state. + - dname_subdomain_c() routine. + - server selection, based on RTT. ip6 is filtered out if not available, + and lameness is checked too. + - delegation point copy routine. + +30 May 2007: Wouter + - removed FLAG_CD from message and rrset caches. This was useful for + an agnostic forwarder, but not for a sophisticated (trust value per + rrset enabled) cache. + - iterator reponse typing. + - iterator cname handle. + - iterator prime start. + - subquery work. + - processInitRequest and processInitRequest2. + - cache synthesizes referral messages, with DS and NSEC. + - processInitRequest3. + - if a request creates multiple subrequests these are all activated. + +29 May 2007: Wouter + - routines to lock and unlock array of rrsets moved to cache/rrset. + - lookup message from msg cache (and copy to region). + - fixed cast error in dns msg lookup. + - message with duplicate rrset does not increase its TTLs twice. + - 'qnamesize' changed to 'qname_len' for similar naming scheme. + +25 May 2007: Wouter + - Acknowledge use of unbound-java code in iterator. Nicer readme. + - services/cache/dns.c DNS Cache. Hybrid cache uses msgcache and + rrset cache from module environment. + - packed rrset key has type and class as easily accessable struct + members. They are still kept in network format for fast msg encode. + - dns cache find_delegation routine. + - iterator main functions setup. + - dns cache lookup setup. + +24 May 2007: Wouter + - small changes to prepare for subqueries. + - iterator forwarder feature separated out. + - iterator hints stub code, config file stub code, so that first + testing can proceed locally. + - replay tests now have config option to enable forwarding mode. + +23 May 2007: Wouter + - outside network does precise timers for roundtrip estimates for rtt + and for setting timeout for UDP. Pending_udp takes milliseconds. + - cleaner iterator sockaddr conversion of forwarder address. + - iterator/iter_utils and iter_delegpt setup. + - root hints. + +22 May 2007: Wouter + - outbound query list for modules and support to callback with the + outbound entry to the module. + - testbound support for new serviced queries. + - test for retry to TCP cannot use testbound any longer. + - testns test for EDNS fallback, test for TCP fallback already exists. + - fixes for no-locking compile. + - mini_event timer precision and fix for change in timeouts during + timeout callback. Fix for fwd_three tests, performed nonexit query. + +21 May 2007: Wouter + - small comment on hash table locking. + - outside network serviced queries, contain edns and tcp fallback, + and udp retries and rtt timing. + +16 May 2007: Wouter + - lruhash_touch() would cause locking order problems. Fixup in + lock-verify in case locking cycle is found. + - services/cache/rrset.c for rrset cache code. + - special rrset_cache LRU updating function that uses the rrset id. + - no dependencies calculation when make clean is called. + - config settings for infra cache. + - daemon code slightly cleaner, only creates caches once. + +15 May 2007: Wouter + - host cache code. + - unit test for host cache. + +14 May 2007: Wouter + - Port to OS/X and Dec Alpha. Printf format and alignment fixes. + - extensive lock debug report on join timeout. + - proper RTT calculation, in utility code. + - setup of services/cache/infra, host cache. + +11 May 2007: Wouter + - iterator/iterator.c module. + - fixup to pass reply_info in testcode and in netevent. + +10 May 2007: Wouter + - created release-0.3 svn tag. + - util/module.h + - fixed compression - no longer compresses root name. + +9 May 2007: Wouter + - outside network cleans up waiting tcp queries on exit. + - fallback to TCP. + - testbound replay with retry in TCP mode. + - tpkg test for retry in TCP mode, against ldns-testns server. + - daemon checks max number of open files and complains if not enough. + - test where data expires in the cache. + - compiletests: fixed empty body ifstatements in alloc.c, in case + locks are disabled. + +8 May 2007: Wouter + - outgoing network keeps list of available tcp buffers for outgoing + tcp queries. + - outgoing-num-tcp config option. + - outgoing network keeps waiting list of queries waiting for buffer. + - netevent supports outgoing tcp commpoints, nonblocking connects. + +7 May 2007: Wouter + - EDNS read from query, used to make reply smaller. + - advertised edns value constants. + - EDNS BADVERS response, if asked for too high edns version. + - EDNS extended error reponses once the EDNS record from the query + has successfully been parsed. + +4 May 2007: Wouter + - msgreply sizefunc is more accurate. + - config settings for rrset cache size and slabs. + - hashtable insert takes argument so that a thread can use its own + alloc cache to store released keys. + - alloc cache special_release() locks if necessary. + - rrset trustworthiness type added. + - thread keeps a scratchpad region for handling messages. + - writev used in netevent to write tcp length and data after another. + This saves a roundtrip on tcp replies. + - test for one rrset updated in the cache. + - test for one rrset which is not updated, as it is not deemed + trustworthy enough. + - test for TTL refreshed in rrset. + +3 May 2007: Wouter + - fill refs. Use new parse and encode to answer queries. + - stores rrsets in cache. + - uses new msgreply format in cache. + +2 May 2007: Wouter + - dname unit tests in own file and spread out neatly in functions. + - more dname unit tests. + - message encoding creates truncated TC flagged messages if they do + not fit, and will leave out (whole)rrsets from additional if needed. + +1 May 2007: Wouter + - decompress query section, extremely lenient acceptance. + But only for answers from other servers, not for plain queries. + - compression and decompression test cases. + - some stats added. + - example.conf interface: line is changed from 127.0.0.1 which leads + to problems if used (restricting communication to the localhost), + to a documentation and test address. + +27 April 2007: Wouter + - removed iov usage, it is not good for dns message encoding. + - owner name compression more optimal. + - rrsig owner name compression. + - rdata domain name compression. + +26 April 2007: Wouter + - floating point exception fix in lock-verify. + - lint uses make dependency + - fixup lint in dname owner domain name compression code. + - define for offset range that can be compressed to. + +25 April 2007: Wouter + - prettier code; parse_rrset->type kept in host byte order. + - datatype used for hashvalue of converted rrsig structure. + - unit test compares edns section data too. + +24 April 2007: Wouter + - ttl per RR, for RRSIG rrsets and others. + - dname_print debug function. + - if type is not known, size calc will skip DNAME decompression. + - RRSIG parsing and storing and putting in messages. + - dnssec enabled unit tests (from nlnetlabs.nl and se queries). + - EDNS extraction routine. + +20 April 2007: Wouter + - code comes through all of the unit tests now. + - disabled warning about spurious extra data. + - documented the RRSIG parse plan in msgparse.h. + - rrsig reading and outputting. + +19 April 2007: Wouter + - fix unit test to actually to tests. + - fix write iov helper, and fakevent code. + - extra builtin testcase (small packet). + - ttl converted to network format in packets. + - flags converted correctly + - rdatalen off by 2 error fixup. + - uses less iov space for header. + +18 April 2007: Wouter + - review of msgparse code. + - smaller test cases. + +17 April 2007: Wouter + - copy and decompress dnames. + - store calculated hash value too. + - routine to create message out of stored information. + - util/data/msgparse.c for message parsing code. + - unit test, and first fixes because of test. + * forgot rrset_count addition. + * did & of ptr on stack for memory position calculation. + * dname_pkt_copy forgot to read next label length. + - test from file and fixes + * double frees fixed in error conditions. + * types with less than full rdata allowed by parser. + Some dynamic update packets seem to use it. + +16 April 2007: Wouter + - following a small change in LDNS, parsing code calculates the + memory size to allocate for rrs. + - code to handle ID creation. + +13 April 2007: Wouter + - parse routines. Code that parses rrsets, rrs. + +12 April 2007: Wouter + - dname compare routine that preserves case, with unit tests. + +11 April 2007: Wouter + - parse work - dname packet parse, msgparse, querysection parse, + start of sectionparse. + +10 April 2007: Wouter + - Improved alignment of reply_info packet, nice for 32 and 64 bit. + - Put RRset counts in reply_info, because the number of RRs can change + due to RRset updates. + - import of region-allocator code from nsd. + - set alloc special type to ub_packed_rrset_key. + Uses lruhash entry overflow chain next pointer in alloc cache. + - doxygen documentation for region-allocator. + - setup for parse scratch data. + +5 April 2007: Wouter + - discussed packed rrset with Jelte. + +4 April 2007: Wouter + - moved to version 0.3. + - added util/data/dname.c + - layout of memory for rrsets. + +3 April 2007: Wouter + - detect sign of msghdr.msg_iovlen so that the cast to that type + in netevent (which is there to please lint) can be correct. + The type on several OSes ranges from int, int32, uint32, size_t. + Detects unsigned or signed using math trick. + - constants for DNS flags. + - compilation without locks fixup. + - removed include of unportable header from lookup3.c. + - more portable use of struct msghdr. + - casts for printf warning portability. + - tweaks to tests to port them to the testbed. + - 0.2 tag created. + +2 April 2007: Wouter + - check sizes of udp received messages, not too short. + - review changes. Some memmoves can be memcpys: 4byte aligned. + set id correctly on cached answers. + - review changes msgreply.c, memleak on error condition. AA flag + clear on cached reply. Lowercase queries on hashing. + unit test on lowercasing. Test AA bit not set on cached reply. + Note that no TTLs are managed. + +29 March 2007: Wouter + - writev or sendmsg used when answering from cache. + This avoids a copy of the data. + - do not do useless byteswap on query id. Store reply flags in uint16 + for easier access (and no repeated byteswapping). + - reviewed code. + - configure detects and config.h includes sys/uio.h for writev decl. + +28 March 2007: Wouter + - new config option: num-queries-per-thread. + - added tpkg test for answering three queries at the same time + using one thread (from the query service list). + +27 March 2007: Wouter + - added test for cache and not cached answers, in testbound replays. + - testbound can give config file and commandline options from the + replay file to unbound. + - created test that checks if items drop out of the cache. + - added word 'partitioned hash table' to documentation on slab hash. + A slab hash is a partitioned hash table. + - worker can handle multiple queries at a time. + +26 March 2007: Wouter + - config settings for slab hash message cache. + - test for cached answer. + - Fixup deleting fake answer from testbound list. + +23 March 2007: Wouter + - review of yesterday's commits. + - covered up memory leak of the entry locks. + - answers from the cache correctly. Copies flags correctly. + - sanity check for incoming query replies. + - slabbed hash table. Much nicer contention, need dual cpu to see. + +22 March 2007: Wouter + - AIX configure check. + - lock-verify can handle references to locks that are created + in files it has not yet read in. + - threaded hash table test. + - unit test runs lock-verify afterwards and checks result. + - need writelock to update data on hash_insert. + - message cache code, msgreply code. + +21 March 2007: Wouter + - unit test of hash table, fixup locking problem in table_grow(). + - fixup accounting of sizes for removing items from hashtable. + - unit test for hash table, single threaded test of integrity. + - lock-verify reports errors nicely. More quiet in operation. + +16 March 2007: Wouter + - lock-verifier, checks consistent order of locking. + +14 March 2007: Wouter + - hash table insert (and subroutines) and lookup implemented. + - hash table remove. + - unit tests for hash internal bin, lru functions. + +13 March 2007: Wouter + - lock_unprotect in checklocks. + - util/storage/lruhash.h for LRU hash table structure. + +12 March 2007: Wouter + - configure.ac moved to 0.2. + - query_info and replymsg util/data structure. + +9 March 2007: Wouter + - added rwlock writelock checking. + So it will keep track of the writelock, and readlocks are enforced + to not change protected memory areas. + - log_hex function to dump hex strings to the logfile. + - checklocks zeroes its destroyed lock after checking memory areas. + - unit test for alloc. + - identifier for union in checklocks to please older compilers. + - created 0.1 tag. + +8 March 2007: Wouter + - Reviewed checklock code. + +7 March 2007: Wouter + - created a wrapper around thread calls that performs some basic + checking for data race and deadlock, and basic performance + contention measurement. + +6 March 2007: Wouter + - Testbed works with threading (different machines, different options). + - alloc work, does the special type. + +2 March 2007: Wouter + - do not compile fork funcs unless needed. Otherwise will give + type errors as their typedefs have not been enabled. + - log shows thread numbers much more nicely (and portably). + - even on systems with nonthreadsafe libevent signal handling, + unbound will exit if given a signal. + Reloads will not work, and exit is not graceful. + - start of alloc framework layout. + +1 March 2007: Wouter + - Signals, libevent and threads work well, with libevent patch and + changes to code (close after event_del). + - set ipc pipes nonblocking. + +27 February 2007: Wouter + - ub_thread_join portable definition. + - forking is used if no threading is available. + Tested, it works, since pipes work across processes as well. + Thread_join is replaced with waitpid. + - During reloads the daemon will temporarily handle signals, + so that they do not result in problems. + - Also randomize the outgoing port range for tests. + - If query list is full, will stop selecting listening ports for read. + This makes all threads service incoming requests, instead of one. + No memory is leaking during reloads, service of queries, etc. + - test that uses ldns-testns -f to test threading. Have to answer + three queries at the same time. + - with verbose=0 operates quietly. + +26 February 2007: Wouter + - ub_random code used to select ID and port. + - log code prints thread id. + - unbound can thread itself, with reload(HUP) and quit working + correctly. + - don't open pipes for #0, doesn't need it. + - listens to SIGTERM, SIGQUIT, SIGINT (all quit) and SIGHUP (reload). + +23 February 2007: Wouter + - Can do reloads on sigHUP. Everything is stopped, and freed, + except the listening ports. Then the config file is reread. + And everything is started again (and listening ports if needed). + - Ports for queries are shared. + - config file added interface:, chroot: and username:. + - config file: directory, logfile, pidfile. And they work too. + - will daemonize by default now. Use -d to stay in the foreground. + - got BSD random[256 state] code, made it threadsafe. util/random. + +22 February 2007: Wouter + - Have a config file. Removed commandline options, moved to config. + - tests use config file. + +21 February 2007: Wouter + - put -c option in man page. + - minievent fd array capped by FD_SETSIZE. + +20 February 2007: Wouter + - Added locks code and pthread spinlock detection. + - can use no locks, or solaris native thread library. + - added yacc and lex configure, and config file parsing code. + also makedist.sh, and manpage. + - put include errno.h in config.h + +19 February 2007: Wouter + - Created 0.0 svn tag. + - added acx_pthread.m4 autoconf check for pthreads from + the autoconf archive. It is GPL-with-autoconf-exception Licensed. + You can specify --with-pthreads, or --without-pthreads to configure. + +16 February 2007: Wouter + - Updated testbed script, works better by using make on remote end. + - removed check decls, we can compile without them. + - makefile supports LIBOBJ replacements. + - docs checks ignore compat code. + - added util/mini-event.c and .h, a select based alternative used with + ./configure --with-libevent=no + It is limited to 1024 file descriptors, and has less features. + - will not create ip6 sockets if ip6 not on the machine. + +15 February 2007: Wouter + - port to FreeBSD 4.11 Dec Alpha. Also works on Solaris 10 sparc64, + Solaris 9, FreeBSD 6, Linux i386 and OSX powerpc. + - malloc rndstate, so that it is aligned for access. + - fixed rbtree cleanup with postorder traverse. + - fixed pending messages are deleted when handled. + - You can control verbosity; default is not verbose, every -v + adds more verbosity. + +14 February 2007: Wouter + - Included configure.ac changes from ldns. + - detect (some) headers before the standards check. + - do not use isblank to test c99, since its not available on solaris9. + - review of testcode. + * entries in a RANGE are no longer reversed. + * print name of file with replay entry parse errors. + - port to OSX: cast to int for some prints of sizet. + - Makefile copies ldnstestpkts.c before doing dependencies on it. + +13 February 2007: Wouter + - work on fake events, first fwd replay works. + - events can do timeouts and errors on queries to servers. + - test package that runs replay scenarios. + +12 February 2007: Wouter + - work on fake events. + +9 February 2007: Wouter + - replay file reading. + - fake event setup, it creates fake structures, and teardowns, + added signal callbacks to reply to be able to fake those, + and main structure of event replay routines. + +8 February 2007: Wouter + - added tcp test. + - replay storage. + - testcode/fake_event work. + +7 February 2007: Wouter + - return answer with the same ID as query was sent with. + - created udp forwarder test. I've done some effort to make it perform + quickly. After servers are created, no big sleep statements but + it checks the logfiles to see if servers have come up. Takes 0.14s. + - set addrlen value when calling recvfrom. + - comparison of addrs more portable. + - LIBEVENT option for testbed to set libevent directory. + - work on tcp input. + +6 February 2007: Wouter + - reviewed code and improved in places. + +5 February 2007: Wouter + - Picked up stdc99 and other define tests from ldns. Improved + POSIX define test to include getaddrinfo. + - defined constants for netevent callback error code. + - unit test for strisip6. + +2 February 2007: Wouter + - Created udp4 and udp6 port arrays to provide service for both + address families. + - uses IPV6_USE_MIN_MTU for udp6 ,IPV6_V6ONLY to make ip6 sockets. + - listens on both ip4 and ip6 ports to provide correct return address. + - worker fwder address filled correctly. + - fixup timer code. + - forwards udp queries and sends answer. + +1 February 2007: Wouter + - outside network more UDP work. + - moved * closer to type. + - comm_timer object and events. + +31 January 2007: Wouter + - Added makedist.sh script to make release tarball. + - Removed listen callback layer, did not add anything. + - Added UDP recv to netevent, worker callback for udp. + - netevent communication reply storage structure. + - minimal query header sanity checking for worker. + - copied over rbtree implementation from NSD (BSD licensed too). + - outgoing network query service work. + +30 January 2007: Wouter + - links in example/ldns-testpkts.c and .h for premade packet support. + - added callback argument to listen_dnsport and daemon/worker. + +29 January 2007: Wouter + - unbound.8 a short manpage. + +26 January 2007: Wouter + - fixed memleak. + - make lint works on BSD and Linux (openssl defines). + - make tags works. + - testbound program start. + +25 January 2007: Wouter + - fixed lint so it may work on BSD. + - put license into header of every file. + - created verbosity flag. + - fixed libevent configure flag. + - detects event_base_free() in new libevent 1.2 version. + - getopt in daemon. fatal_exit() and verbose() logging funcs. + - created log_assert, that throws assertions to the logfile. + - listen_dnsport service. Binds ports. + +24 January 2007: Wouter + - cleaned up configure.ac. + +23 January 2007: Wouter + - added libevent to configure to link with. + - util/netevent setup work. + - configure searches for libevent. + - search for libs at end of configure (when other headers and types + have been found). + - doxygen works with ATTR_UNUSED(). + - util/netevent implementation. + +22 January 2007: Wouter + - Designed header file for network communication. + +16 January 2007: Wouter + - added readme.svn and readme.tests. + +4 January 2007: Wouter + - Testbed script (run on multiple platforms the test set). + Works on Sunos9, Sunos10, FreeBSD 6.1, Fedora core 5. + - added unit test tpkg. + +3 January 2007: Wouter + - committed first set of files into subversion repository. + svn co svn+ssh://unbound.net/svn/unbound + You need a ssh login. There is no https access yet. + - Added LICENSE, the BSD license. + - Added doc/README with compile help. + - main program stub and quiet makefile. + - minimal logging service (to stderr). + - added postcommit hook that serves emails. + - added first test 00-lint. postcommit also checks if build succeeds. + - 01-doc: doxygen doc target added for html docs. And stringent test + on documented files, functions and parameters. + +15 December 2006: Wouter + - Created Makefile.in and configure.ac. diff --git a/doc/FEATURES b/doc/FEATURES new file mode 100644 index 00000000000..b695eeb9d48 --- /dev/null +++ b/doc/FEATURES @@ -0,0 +1,100 @@ +Unbound Features + +(C) Copyright 2008, Wouter Wijngaards, NLnet Labs. + + +This document describes the features and RFCs that unbound +adheres to, and which ones are decided to be out of scope. + + +Big Features +------------ +Recursive service. +Caching service. +Forwarding and stub zones. +Very limited authoritative service. +DNSSEC Validation options. +EDNS0, NSEC3, IPv6, DNAME, Unknown-RR-types. +RSASHA256, GOST, ECDSA, SHA384 DNSSEC algorithms. + +Details +------- +Processing support +RFC 1034-1035: as a recursive, caching server. Not authoritative. + including CNAMEs, referrals, wildcards, classes, ... + AAAA type, and IP6 dual stack support. + type ANY queries are supported, class ANY queries are supported. +RFC 4033-4035: as a validating caching server (unbound daemon). + as a validating stub (libunbound). +RFC 1918. +RFC 1995, 1996, 2136: not authoritative, so no AXFR, IXFR, NOTIFY or + dynamic update services are appropriate. +RFC 2181: completely, including the trust model, keeping rrsets together. +RFC 2308: TTL directive, and the rest of the RFC too. +RFC 2671: EDNS0 support, default advertisement 4Kb size. +RFC 2672: DNAME support. +RFC 3597: Unknown RR type support. +RFC 4343: case insensitive handling of domain names. +RFC 4509: SHA256 DS hash. +RFC 4592: wildcards. +RFC 4697: No DNS Resolution Misbehavior. +RFC 5011: update of trust anchors with timers. +RFC 5155: NSEC3, NSEC3PARAM types +RFC 5358: reflectors-are-evil: access control list for recursive + service. In fact for all DNS service so cache snooping is halted. +RFC 5452: forgery resilience. all recommendations followed. +RFC 5702: RSASHA256 signature algorithm. +RFC 5933: GOST signature algorithm. +RFC 6303: default local zones. + It is possible to block zones or return an address for localhost. + This is a very limited authoritative service. Defaults as in draft. +RFC 6604: xNAME RCODE and status bits. +RFC 6605: ECDSA signature algorithm, SHA384 DS hash. + +chroot and drop-root-privileges support, default enabled in config file. + +AD bit in query can be used to request AD bit in response (w/o using DO bit). +CD bit in query can be used to request bogus data. +UDP and TCP service is provided downstream. +UDP and TCP are used to request from upstream servers. +SSL wrapped TCP service can be used upstream and provided downstream. +Multiple queries can be made over a TCP stream. + +No TSIG support at this time. +No SIG0 support at this time. +No dTLS support at this time. +This is not a DNS statistics package, but some operationally useful +values are provided via unbound-control stats. +TXT RRs from the Chaos class (id.server, hostname.bind, ...) are supported. + +draft-0x20: implemented, use caps-for-id option to enable use. + Also implements bitwise echo of the query to support downstream 0x20. +draft-ietf-dnsop-resolver-priming(-00): can prime and can fallback to + a safety belt list. +draft-ietf-dnsop-dnssec-trust-anchor(-01): DS records can be configured + as trust anchors. Also DNSKEYs are allowed, by the way. +draft-ietf-dnsext-dnssec-bis-updates: supported. + +Record type syntax support, extensive, from lib ldns. +For these types only syntax and parsing support is needed. +RFC 1034-1035: basic RR types. +RFC 1183: RP, AFSDB, X25, ISDN, RT +RFC 1706: NSAP +RFC 2535: KEY, SIG, NXT: treated as unknown data, syntax is parsed (obsolete). +2163: PX +AAAA type +1876: LOC type +2782: SRV type +2915: NAPTR type. +2230: KX type. +2538: CERT type. +2672: DNAME type. +OPT type +3123: APL +SSHFP type +4025: IPSECKEY +4033-4035: DS, RRSIG, NSEC, DNSKEY +4701: DHCID +5155: NSEC3, NSEC3PARAM +4408: SPF + diff --git a/doc/LICENSE b/doc/LICENSE new file mode 100644 index 00000000000..c248049fb8d --- /dev/null +++ b/doc/LICENSE @@ -0,0 +1,30 @@ +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 REGENTS OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/doc/README b/doc/README new file mode 100644 index 00000000000..c150f7bd677 --- /dev/null +++ b/doc/README @@ -0,0 +1,150 @@ +README for Unbound 1.4.17 +Copyright 2007 NLnet Labs +http://unbound.net + +This software is under BSD license, see LICENSE for details. + +* Download the latest release version of this software from + http://unbound.net + or get a beta version from the svn repository at + http://unbound.net/svn/ + +* Uses the following libraries; + * ldns http://www.nlnetlabs.nl/ldns/ (BSD license) + (required) can use ldns build directory directly with --with-ldns=path. + * libevent http://www.monkey.org/~provos/libevent/ (BSD license) + (optional) can use builtin alternative instead. + +* Make and install: ./configure; make; make install + * --with-ldns=/path/to/ldns + It will dynamically link against it. + * --with-libevent=/path/to/libevent + Can be set to either the system install or the build directory. + --with-libevent=no (default) gives a builtin alternative + implementation. libevent is useful when having many (thousands) + of outgoing ports. This improves randomization and spoof + resistance. For the default of 16 ports the builtin alternative + works well and is a little faster. + * --with-libexpat=/path/to/libexpat + Can be set to the install directory of libexpat. + * --without-pthreads + This disables pthreads. Without this option the pthreads library + is detected automatically. Use this option to disable threading + altogether, or, on Solaris, also use --with(out)-solaris-threads. + * --enable-checking + This enables assertions in the code that guard against a variety of + programming errors, among which buffer overflows. The program exits + with an error if an assertion fails (but the buffer did not overflow). + * --enable-static-exe + This enables a debug option to statically link, against ldns and + libevent libraries. + * --enable-lock-checks + This enables a debug option to check lock and unlock calls. It needs + a recent pthreads library to work. + * --enable-alloc-checks + This enables a debug option to check malloc (calloc, realloc, free). + The server periodically checks if the amount of memory used fits with + the amount of memory it thinks it should be using, and reports + memory usage in detail. + * --with-conf-file=filename + Set default location of config file, + the default is /usr/local/etc/unbound/unbound.conf. + * --with-pidfile=filename + Set default location of pidfile, + the default is /usr/local/etc/unbound/unbound.pid. + * --with-run-dir=path + Set default working directory, + the default is /usr/local/etc/unbound. + * --with-chroot-dir=path + Set default chroot directory, + the default is /usr/local/etc/unbound. + * --with-rootkey-file=path + Set the default root.key path. This file is read and written. + the default is /usr/local/etc/unbound/root.key + * --with-rootcert-file=path + Set the default root update certificate path. A builtin certificate + is used if this file is empty or does not exist. + the default is /usr/local/etc/unbound/icannbundle.pem + * --with-username=user + Set default user name to change to, + the default is the "unbound" user. + * --with-pyunbound + Create libunbound wrapper usable from python. + Needs python-devel and swig development tools. + * --with-pythonmodule + Compile the python module that processes responses in the server. + * --disable-sha2 + Disable support for RSASHA256 and RSASHA512 crypto. + * --disable-gost + Disable support for GOST crypto, RFC 5933. + +* 'make test' runs a series of self checks. + +Known issues +------------ +o If there are no replies for a forward or stub zone, for a reverse zone, + you may need to add a local-zone: name transparent or nodefault to the + server: section of the config file to unblock the reverse zone. + Only happens for (sub)zones that are blocked by default; e.g. 10.in-addr.arpa +o If libevent is older (before 1.3c), unbound will exit instead of reload + on sighup. On a restart 'did not exit gracefully last time' warning is + printed. Perform ./configure --with-libevent=no or update libevent, rerun + configure and recompile unbound to make sighup work correctly. + It is strongly suggested to use a recent version of libevent. +o If you are not receiving the correct source IP address on replies (e.g. + you are running a multihomed, anycast server), the interface-automatic + option can be enabled to set socket options to achieve the correct + source IP address on UDP replies. Listing all IP addresses explicitly in + the config file is an alternative. The interface-automatic option uses + non portable socket options, Linux and FreeBSD should work fine. +o The warning 'openssl has no entropy, seeding with time', with chroot + enabled, may be solved with a symbolic link to /dev/random from . +o On Solaris 5.10 some libtool packages from repositories do not work with + gcc, showing errors gcc: unrecognized option `-KPIC' + To solve this do ./configure libtool=./libtool [your options...]. + On Solaris you may pass CFLAGS="-xO4 -xtarget=generic" if you use sun-cc. +o If unbound-control (or munin graphs) do not work, this can often be because + the unbound-control-setup script creates the keys with restricted + permissions, and the files need to be made readable or ownered by both the + unbound daemon and unbound-control. +o Crosscompile seems to hang. You tried to install unbound under wine. + wine regedit and remove all the unbound entries from the registry or + delete .wine/drive_c. + +Acknowledgements +---------------- +o Unbound was written in portable C by Wouter Wijngaards (NLnet Labs). +o Thanks to David Blacka and Matt Larson (Verisign) for the unbound-java + prototype. Design and code from that prototype has been used to create + this program. Such as the iterator state machine and the cache design. +o Other code origins are from the NSD (NLnet Labs) and LDNS (NLnet Labs) + projects. Such as buffer, region-allocator and red-black tree code. +o See Credits file for contributors. + + +Your Support +------------ +NLnet Labs offers all of its software products as open source, most are +published under a BSD license. You can download them, not only from the +NLnet Labs website but also through the various OS distributions for +which NSD, ldns, and Unbound are packaged. We therefore have little idea +who uses our software in production environments and have no direct ties +with 'our customers'. + +Therefore, we ask you to contact us at users@NLnetLabs.nl and tell us +whether you use one of our products in your production environment, +what that environment looks like, and maybe even share some praise. +We would like to refer to the fact that your organization is using our +products. We will only do that if you explicitly allow us. In all other +cases we will keep the information you share with us to ourselves. + +In addition to the moral support you can also support us +financially. NLnet Labs is a recognized not-for-profit charity foundation +that is chartered to develop open-source software and open-standards +for the Internet. If you use our software to satisfaction please express +that by giving us a donation. For small donations PayPal can be used. For +larger and regular donations please contact us at users@NLnetLabs.nl. Also +see http://www.nlnetlabs.nl/labs/contributors/. + + +* mailto:unbound-bugs@nlnetlabs.nl diff --git a/doc/README.svn b/doc/README.svn new file mode 100644 index 00000000000..7f188987b09 --- /dev/null +++ b/doc/README.svn @@ -0,0 +1,17 @@ +README.svn + +For a svn checkout +* configure script, aclocal.m4, as well as yacc/lex output files are + committed to the repository. +* use --enable-debug flag for configure to enable dependency tracking and + assertions, otherwise, use make clean; make after svn update. + +* Note changes in the Changelog. +* Every check-in a postcommit hook is run + (the postcommit hook is in the svn/unbound/hooks directory). + * generates commit email with your changes and comment. + * compiles and runs the tests (with testcode/do-tests.sh). + * If build errors or test errors happen + * Please fix your errors and commit again. + +* Use gnu make to compile, make or 'gmake'. diff --git a/doc/README.tests b/doc/README.tests new file mode 100644 index 00000000000..5385e2b2221 --- /dev/null +++ b/doc/README.tests @@ -0,0 +1,24 @@ +README unbound tests + +For a quick test that runs unit tests and state machine tests, use + make test + +There is a long test setup for unbound that needs tools installed. Use + make longtest +To make and run the long tests. The results are summarized at the end. + +You need to have the following programs installed and in your PATH. +* dig - from the bind-tools package. Used to send DNS queries. +* splint (optional) - for lint test +* doxygen (optional) - for doc completeness test +* ldns-testns - from ldns examples. Used as DNS auth server. +* xxd and nc (optional) - for (malformed) packet transmission. +The optional programs are detected and can be omitted. + +testdata/ contains the data for tests. +testcode/ contains scripts and c code for the tests. + +do-tests.sh : runs all the tests in the testdata directory. +testbed.sh : compiles on a set of (user specific) hosts and runs do-tests. + +Tests are run using testcode/mini_tpkg.sh. diff --git a/doc/TODO b/doc/TODO new file mode 100644 index 00000000000..bfeef4aa47b --- /dev/null +++ b/doc/TODO @@ -0,0 +1,76 @@ +TODO items. These are interesting todo items. +o understand synthesized DNAMEs, so those TTL=0 packets are cached properly. +o NSEC/NSEC3 aggressive negative caching, so that updates to NSEC/NSEC3 + will result in proper negative responses. +o (option) where port 53 is used for send and receive, no other ports are used. +o (option) to not send replies to clients after a timeout of (say 5 secs) has + passed, but keep task active for later retries by client. +o (option) private TTL feature (always report TTL x in answers). +o (option) pretend-dnssec-unaware, and pretend-edns-unaware modes for workshops. +o delegpt use rbtree for ns-list, to avoid slowdown for very large NS sets. +o (option) reprime and refresh oft used data before timeout. +o (option) retain prime results in a overlaid roothints file. +o (option) store primed key data in a overlaid keyhints file (sort of like drafttimers). +o windows version, auto update feature, a query to check for the version. +o command the server with TSIG inband. get-config, clearcache, + get stats, get memstats, get ..., reload, clear one zone from cache +o NSID rfc 5001 support. +o timers rfc 5011 support. +o Treat YXDOMAIN from a DNAME properly, in iterator (not throwaway), validator. +o make timeout backoffs randomized (a couple percent random) to spread traffic. +o inspect date on executable, then warn user in log if its more than 1 year. +o (option) proactively prime root, stubs and trust anchors, feature. + early failure, faster on first query, but more traffic. +o library add convenience functions for A, AAAA, PTR, getaddrinfo, libresolve. +o library add function to validate input from app that is signed. +o add dynamic-update requests (making a dynupd request) to libunbound api. +o SIG(0) and TSIG. +o support OPT record placement on recv anywhere in the additional section. +o add local-file: config with authority features. +o (option) to make local-data answers be secure for libunbound (default=no) +o (option) to make chroot: copy all needed files into jail (or make jail) + perhaps also print reminder to link /dev/random and sysloghack. +o overhaul outside-network servicedquery to merge with udpwait and tcpwait, + to make timers in servicedquery independent of udpwait queues. +o check into rebinding ports for efficiency, configure time test. +o EVP hardware crypto support. +o option to ignore all inception and expiration dates for rrsigs. +o cleaner code; return and func statements on newline. +o memcached module that sits before validator module; checks for memcached + data (on local lan), stores recursion lookup. Provides one cache for multiple resolver machines, coherent reply content in anycast setup. +o no openssl_add_all_algorithms, but only the ones necessary, less space. +o listen to NOTIFY messages for zones and flush the cache for that zone + if received. Useful when also having a stub to that auth server. + Needs proper protection, TSIG, in place. +o winevent - do not go more than 64 fds (by polling with select one by + one), win95/98 have 100fd limit in the kernel, so this ruins w9x portability. + +*** Features features, for later +* dTLS, TLS, look to need special port numbers, cert storage, recent libssl. +* aggressive negative caching for NSEC, NSEC3. +* multiple queries per question, server exploration, server selection. +* support TSIG on queries, for validating resolver deployment. +* retry-mode, where a bogus result triggers a retry-mode query, where a list + of responses over a time interval is collected, and each is validated. + or try in TCP mode. Do not 'try all servers several times', since we must + not create packet storms with operator errors. +o on windows version, implement that OS ancillary data capabilities for + interface-automatic. IPPKTINFO, IP6PKTINFO for WSARecvMsg, WSASendMsg. +o local-zone directive with authority service, full authority server + is a non-goal. +o infra and lame cache: easier size config (in Mb), show usage in graphs. +- store time of dump in cachedumps, so that on a load the ttls can be + compared to the absolute time, and now-expired items can be dealt with. + +later +- selective verbosity; ubcontrol trace example.com +- cache fork-dump, pre-load +- for fwds, send queries to N servers in fwd-list, use first reply. + document high scalable, high available unbound setup onepager. +- prefetch DNSKEY when DS in delegation seen (nonCD, underTA). +- use libevent if available on system by default(?), default outgoing 256to1024 + +[1] BIND-like query logging to see who's looking up what and when +[2] more logging about stuff like SERVFAIL and REFUSED responses +[3] a Makefile that works without gnumake + diff --git a/doc/control_proto_spec.txt b/doc/control_proto_spec.txt new file mode 100644 index 00000000000..d26258f1ea9 --- /dev/null +++ b/doc/control_proto_spec.txt @@ -0,0 +1,70 @@ + +Specification for the unbound-control protocol. + +Server listens on 8953 TCP (localhost by default). Client connects, +SSLv3 or TLSv1 connection setup (server selfsigned certificate, +client has cert signed by server certificate). + +Port 8953 is registered with IANA as: +ub-dns-control 8953/tcp unbound dns nameserver control +# Wouter Wijngaards 10 May 2011 +On may 11 2011, ticket [IANA #442315]. + +Query and Response +------------------ +Client sends + UBCT[version] [commandline] \n + fixed string UBCT1 (for version 1), then an ascii text line, + with a command, some whitespace allowed. Line ends with '\n'. + +Server executes command. And sends reply in ascii text over channel, +closes the channel when done. + in case of error the first line of the response is: + error \n + or the remainder is data of the response, for many commands the + response is 'ok\n'. + +Queries and responses +--------------------- +stop + stops the server. +reload + reloads the config file, and flushes the cache. +verbosity + Change logging verbosity to new value. +stats + output is a list of [name]=[value] lines. + clears the counters. +dump_cache + output is a text representation of the cache contents. + data ends with a line 'EOF' before connection close. +load_cache + client sends cache contents (like from dump_cache), which is stored + in the cache. end of data indicated with a line with 'EOF' on it. + The data is sent after the query line. +flush + flushes some information regarding the name from the cache. + removes the A, AAAA, NS, SOA, CNAME, DNAME, MX, PTR, SRV, NAPTR types. + Does not remove other types. +flush_type + removes rrtype entry from the cache. +flush_zone + removes name and everything below that name from the cache. + has to search through the cache item by item, so this is slow. +lookup + see what servers would be queried for a lookup of the given name. +local_zone_remove + the local-zone entry is removed. + All data from the local zone is also deleted. + If it did not exist, nothing happens. +local_zone + As the config file entry. Adds new local zone or updates + existing zone type. +local_data_remove + Removes local-data (all types) name. +local_data + Add new local data record (on the rest of the line). + local_data_add www.example.com. IN A 192.0.2.2 + if no local_zone exists for it; a transparent zone with the same + name as the data is created. +Other commands in the unbound-control manual page. diff --git a/doc/example.conf.in b/doc/example.conf.in new file mode 100644 index 00000000000..0378d045e43 --- /dev/null +++ b/doc/example.conf.in @@ -0,0 +1,536 @@ +# +# Example configuration file. +# +# See unbound.conf(5) man page, version 1.4.17. +# +# this is a comment. + +#Use this to include other text into the file. +#include: "otherfile.conf" + +# The server clause sets the main parameters. +server: + # whitespace is not necessary, but looks cleaner. + + # verbosity number, 0 is least verbose. 1 is default. + verbosity: 1 + + # print statistics to the log (for every thread) every N seconds. + # Set to "" or 0 to disable. Default is disabled. + # statistics-interval: 0 + + # enable cumulative statistics, without clearing them after printing. + # statistics-cumulative: no + + # enable extended statistics (query types, answer codes, status) + # printed from unbound-control. default off, because of speed. + # extended-statistics: no + + # number of threads to create. 1 disables threading. + # num-threads: 1 + + # specify the interfaces to answer queries from by ip-address. + # The default is to listen to localhost (127.0.0.1 and ::1). + # specify 0.0.0.0 and ::0 to bind to all available interfaces. + # specify every interface[@port] on a new 'interface:' labelled line. + # The listen interfaces are not changed on reload, only on restart. + # interface: 192.0.2.153 + # interface: 192.0.2.154 + # interface: 192.0.2.154@5003 + # interface: 2001:DB8::5 + + # enable this feature to copy the source address of queries to reply. + # Socket options are not supported on all platforms. experimental. + # interface-automatic: no + + # port to answer queries from + # port: 53 + + # specify the interfaces to send outgoing queries to authoritative + # server from by ip-address. If none, the default (all) interface + # is used. Specify every interface on a 'outgoing-interface:' line. + # outgoing-interface: 192.0.2.153 + # outgoing-interface: 2001:DB8::5 + # outgoing-interface: 2001:DB8::6 + + # number of ports to allocate per thread, determines the size of the + # port range that can be open simultaneously. About double the + # num-queries-per-thread, or, use as many as the OS will allow you. + # outgoing-range: 4096 + + # permit unbound to use this port number or port range for + # making outgoing queries, using an outgoing interface. + # outgoing-port-permit: 32768 + + # deny unbound the use this of port number or port range for + # making outgoing queries, using an outgoing interface. + # Use this to make sure unbound does not grab a UDP port that some + # other server on this computer needs. The default is to avoid + # IANA-assigned port numbers. + # outgoing-port-avoid: "3200-3208" + + # number of outgoing simultaneous tcp buffers to hold per thread. + # outgoing-num-tcp: 10 + + # number of incoming simultaneous tcp buffers to hold per thread. + # incoming-num-tcp: 10 + + # buffer size for UDP port 53 incoming (SO_RCVBUF socket option). + # 0 is system default. Use 4m to catch query spikes for busy servers. + # so-rcvbuf: 0 + + # buffer size for UDP port 53 outgoing (SO_SNDBUF socket option). + # 0 is system default. Use 4m to handle spikes on very busy servers. + # so-sndbuf: 0 + + # 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 + + # buffer size for handling DNS data. No messages larger than this + # size can be sent or received, by UDP or TCP. In bytes. + # msg-buffer-size: 65552 + + # the amount of memory to use for the message cache. + # plain value in bytes or you can append k, m or G. default is "4Mb". + # msg-cache-size: 4m + + # the number of slabs to use for the message cache. + # the number of slabs must be a power of 2. + # more slabs reduce lock contention, but fragment memory usage. + # msg-cache-slabs: 4 + + # the number of queries that a thread gets to service. + # num-queries-per-thread: 1024 + + # if very busy, 50% queries run to completion, 50% get timeout in msec + # jostle-timeout: 200 + + # the amount of memory to use for the RRset cache. + # plain value in bytes or you can append k, m or G. default is "4Mb". + # rrset-cache-size: 4m + + # the number of slabs to use for the RRset cache. + # the number of slabs must be a power of 2. + # more slabs reduce lock contention, but fragment memory usage. + # rrset-cache-slabs: 4 + + # the time to live (TTL) value lower bound, in seconds. Default 0. + # If more than an hour could easily give trouble due to stale data. + # cache-min-ttl: 0 + + # the time to live (TTL) value cap for RRsets and messages in the + # cache. Items are not cached for longer. In seconds. + # cache-max-ttl: 86400 + + # the time to live (TTL) value for cached roundtrip times, lameness and + # EDNS version information for hosts. In seconds. + # infra-host-ttl: 900 + + # the number of slabs to use for the Infrastructure cache. + # the number of slabs must be a power of 2. + # more slabs reduce lock contention, but fragment memory usage. + # infra-cache-slabs: 4 + + # the maximum number of hosts that are cached (roundtrip, EDNS, lame). + # infra-cache-numhosts: 10000 + + # Enable IPv4, "yes" or "no". + # do-ip4: yes + + # Enable IPv6, "yes" or "no". + # do-ip6: yes + + # Enable UDP, "yes" or "no". + # do-udp: yes + + # Enable TCP, "yes" or "no". + # do-tcp: yes + + # upstream connections use TCP only (and no UDP), "yes" or "no" + # useful for tunneling scenarios, default no. + # tcp-upstream: no + + # Detach from the terminal, run in background, "yes" or "no". + # do-daemonize: yes + + # control which clients are allowed to make (recursive) queries + # to this server. Specify classless netblocks with /size and action. + # By default everything is refused, except for localhost. + # Choose deny (drop message), refuse (polite error reply), + # allow (recursive ok), allow_snoop (recursive and nonrecursive ok) + # access-control: 0.0.0.0/0 refuse + # access-control: 127.0.0.0/8 allow + # access-control: ::0/0 refuse + # access-control: ::1 allow + # access-control: ::ffff:127.0.0.1 allow + + # 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. + # + # If chroot is enabled, you should pass the configfile (from the + # commandline) as a full path from the original root. After the + # chroot has been performed the now defunct portion of the config + # file path is removed to be able to reread the config after a reload. + # + # All other file paths (working dir, logfile, roothints, and + # key files) can be specified in several ways: + # o as an absolute path relative to the new root. + # o as a relative path to the working directory. + # o as an absolute path relative to the original root. + # In the last case the path is adjusted to remove the unused portion. + # + # The pid file can be absolute and outside of the chroot, it is + # written just prior to performing the chroot and dropping permissions. + # + # Additionally, unbound may need to access /dev/random (for entropy). + # How to do this is specific to your OS. + # + # If you give "" no chroot is performed. The path must not end in a /. + # chroot: "@UNBOUND_CHROOT_DIR@" + + # if given, user privileges are dropped (after binding port), + # and the given username is assumed. Default is user "unbound". + # If you give "" no privileges are dropped. + # username: "@UNBOUND_USERNAME@" + + # the working directory. The relative files in this config are + # relative to this directory. If you give "" the working directory + # is not changed. + # directory: "@UNBOUND_RUN_DIR@" + + # the log file, "" means log to stderr. + # Use of this option sets use-syslog to "no". + # logfile: "" + + # Log to syslog(3) if yes. The log facility LOG_DAEMON is used to + # log to, with identity "unbound". If yes, it overrides the logfile. + # use-syslog: yes + + # print UTC timestamp in ascii to logfile, default is epoch in seconds. + # log-time-ascii: no + + # print one line with time, IP, name, type, class for every query. + # log-queries: no + + # the pid file. Can be an absolute path outside of chroot/work dir. + # pidfile: "@UNBOUND_PIDFILE@" + + # file to read root hints from. + # get one from ftp://FTP.INTERNIC.NET/domain/named.cache + # root-hints: "" + + # enable to not answer id.server and hostname.bind queries. + # hide-identity: no + + # enable to not answer version.server and version.bind queries. + # hide-version: no + + # the identity to report. Leave "" or default to return hostname. + # identity: "" + + # the version to report. Leave "" or default to return package version. + # version: "" + + # the target fetch policy. + # series of integers describing the policy per dependency depth. + # The number of values in the list determines the maximum dependency + # depth the recursor will pursue before giving up. Each integer means: + # -1 : fetch all targets opportunistically, + # 0: fetch on demand, + # positive value: fetch that many targets opportunistically. + # Enclose the list of numbers between quotes (""). + # target-fetch-policy: "3 2 1 0 0" + + # Harden against very small EDNS buffer sizes. + # harden-short-bufsize: no + + # Harden against unseemly large queries. + # harden-large-queries: no + + # Harden against out of zone rrsets, to avoid spoofing attempts. + # harden-glue: yes + + # Harden against receiving dnssec-stripped data. If you turn it + # off, failing to validate dnskey data for a trustanchor will + # trigger insecure mode for that zone (like without a trustanchor). + # Default on, which insists on dnssec data for trust-anchored zones. + # harden-dnssec-stripped: yes + + # Harden against queries that fall under dnssec-signed nxdomain names. + # harden-below-nxdomain: no + + # Harden the referral path by performing additional queries for + # infrastructure data. Validates the replies (if possible). + # Default off, because the lookups burden the server. Experimental + # implementation of draft-wijngaards-dnsext-resolver-side-mitigation. + # harden-referral-path: no + + # Use 0x20-encoded random bits in the query to foil spoof attempts. + # This feature is an experimental implementation of draft dns-0x20. + # use-caps-for-id: no + + # Enforce privacy of these addresses. Strips them away from answers. + # It may cause DNSSEC validation to additionally mark it as bogus. + # Protects against 'DNS Rebinding' (uses browser as network proxy). + # Only 'private-domain' and 'local-data' names are allowed to have + # these private addresses. No default. + # private-address: 10.0.0.0/8 + # private-address: 172.16.0.0/12 + # private-address: 192.168.0.0/16 + # private-address: 169.254.0.0/16 + # private-address: fd00::/8 + # private-address: fe80::/10 + + # Allow the domain (and its subdomains) to contain private addresses. + # local-data statements are allowed to contain private addresses too. + # private-domain: "example.com" + + # If nonzero, unwanted replies are not only reported in statistics, + # but also a running total is kept per thread. If it reaches the + # threshold, a warning is printed and a defensive action is taken, + # the cache is cleared to flush potential poison out of it. + # A suggested value is 10000000, the default is 0 (turned off). + # unwanted-reply-threshold: 0 + + # Do not query the following addresses. No DNS queries are sent there. + # List one address per entry. List classless netblocks with /size, + # do-not-query-address: 127.0.0.1/8 + # do-not-query-address: ::1 + + # if yes, the above default do-not-query-address entries are present. + # if no, localhost can be queried (for testing and debugging). + # do-not-query-localhost: yes + + # if yes, perform prefetching of almost expired message cache entries. + # prefetch: no + + # if yes, perform key lookups adjacent to normal lookups. + # prefetch-key: no + + # if yes, Unbound rotates RRSet order in response. + # rrset-roundrobin: no + + # if yes, Unbound doesn't insert authority/additional sections + # into response messages when those sections are not required. + # minimal-responses: no + + # module configuration of the server. A string with identifiers + # separated by spaces. "iterator" or "validator iterator" + # module-config: "validator iterator" + + # File with trusted keys, kept uptodate using RFC5011 probes, + # initial file like trust-anchor-file, then it stores metadata. + # Use several entries, one per domain name, to track multiple zones. + # + # If you want to perform DNSSEC validation, run unbound-anchor before + # you start unbound (i.e. in the system boot scripts). And enable: + # Please note usage of unbound-anchor root anchor is at your own risk + # and under the terms of our LICENSE (see that file in the source). + # auto-trust-anchor-file: "@UNBOUND_ROOTKEY_FILE@" + + # File with DLV trusted keys. Same format as trust-anchor-file. + # There can be only one DLV configured, it is trusted from root down. + # Download http://ftp.isc.org/www/dlv/dlv.isc.org.key + # dlv-anchor-file: "dlv.isc.org.key" + + # File with trusted keys for validation. Specify more than one file + # with several entries, one file per entry. + # Zone file format, with DS and DNSKEY entries. + # Note this gets out of date, use auto-trust-anchor-file please. + # trust-anchor-file: "" + + # Trusted key for validation. DS or DNSKEY. specify the RR on a + # single line, surrounded by "". TTL is ignored. class is IN default. + # Note this gets out of date, use auto-trust-anchor-file please. + # (These examples are from August 2007 and may not be valid anymore). + # trust-anchor: "nlnetlabs.nl. DNSKEY 257 3 5 AQPzzTWMz8qSWIQlfRnPckx2BiVmkVN6LPupO3mbz7FhLSnm26n6iG9N Lby97Ji453aWZY3M5/xJBSOS2vWtco2t8C0+xeO1bc/d6ZTy32DHchpW 6rDH1vp86Ll+ha0tmwyy9QP7y2bVw5zSbFCrefk8qCUBgfHm9bHzMG1U BYtEIQ==" + # trust-anchor: "jelte.nlnetlabs.nl. DS 42860 5 1 14D739EB566D2B1A5E216A0BA4D17FA9B038BE4A" + + # File with trusted keys for validation. Specify more than one file + # with several entries, one file per entry. Like trust-anchor-file + # but has a different file format. Format is BIND-9 style format, + # the trusted-keys { name flag proto algo "key"; }; clauses are read. + # you need external update procedures to track changes in keys. + # trusted-keys-file: "" + + # Ignore chain of trust. Domain is treated as insecure. + # domain-insecure: "example.com" + + # Override the date for validation with a specific fixed date. + # Do not set this unless you are debugging signature inception + # and expiration. "" or "0" turns the feature off. -1 ignores date. + # val-override-date: "" + + # The time to live for bogus data, rrsets and messages. This avoids + # some of the revalidation, until the time interval expires. in secs. + # val-bogus-ttl: 60 + + # The signature inception and expiration dates are allowed to be off + # by 10% of the signature lifetime (expir-incep) from our local clock. + # This leeway is capped with a minimum and a maximum. In seconds. + # val-sig-skew-min: 3600 + # val-sig-skew-max: 86400 + + # Should additional section of secure message also be kept clean of + # unsecure data. Useful to shield the users of this validator from + # potential bogus data in the additional section. All unsigned data + # in the additional section is removed from secure messages. + # val-clean-additional: yes + + # Turn permissive mode on to permit bogus messages. Thus, messages + # for which security checks failed will be returned to clients, + # instead of SERVFAIL. It still performs the security checks, which + # result in interesting log files and possibly the AD bit in + # replies if the message is found secure. The default is off. + # val-permissive-mode: no + + # Ignore the CD flag in incoming queries and refuse them bogus data. + # Enable it if the only clients of unbound are legacy servers (w2008) + # that set CD but cannot validate themselves. + # ignore-cd-flag: no + + # Have the validator log failed validations for your diagnosis. + # 0: off. 1: A line per failed user query. 2: With reason and bad IP. + # val-log-level: 0 + + # It is possible to configure NSEC3 maximum iteration counts per + # keysize. Keep this table very short, as linear search is done. + # A message with an NSEC3 with larger count is marked insecure. + # List in ascending order the keysize and count values. + # val-nsec3-keysize-iterations: "1024 150 2048 500 4096 2500" + + # instruct the auto-trust-anchor-file probing to add anchors after ttl. + # add-holddown: 2592000 # 30 days + + # instruct the auto-trust-anchor-file probing to del anchors after ttl. + # del-holddown: 2592000 # 30 days + + # auto-trust-anchor-file probing removes missing anchors after ttl. + # If the value 0 is given, missing anchors are not removed. + # keep-missing: 31622400 # 366 days + + # the amount of memory to use for the key cache. + # plain value in bytes or you can append k, m or G. default is "4Mb". + # key-cache-size: 4m + + # the number of slabs to use for the key cache. + # the number of slabs must be a power of 2. + # more slabs reduce lock contention, but fragment memory usage. + # key-cache-slabs: 4 + + # the amount of memory to use for the negative cache (used for DLV). + # plain value in bytes or you can append k, m or G. default is "1Mb". + # neg-cache-size: 1m + + # a number of locally served zones can be configured. + # local-zone: + # local-data: "" + # o deny serves local data (if any), else, drops queries. + # o refuse serves local data (if any), else, replies with error. + # o static serves local data, else, nxdomain or nodata answer. + # o transparent gives local data, but resolves normally for other names + # o redirect serves the zone data for any subdomain in the zone. + # o nodefault can be used to normally resolve AS112 zones. + # o typetransparent resolves normally for other types and other names + # + # defaults are localhost address, reverse for 127.0.0.1 and ::1 + # and nxdomain for AS112 zones. If you configure one of these zones + # the default content is omitted, or you can omit it with 'nodefault'. + # + # If you configure local-data without specifying local-zone, by + # default a transparent local-zone is created for the data. + # + # You can add locally served data with + # local-zone: "local." static + # local-data: "mycomputer.local. IN A 192.0.2.51" + # local-data: 'mytext.local TXT "content of text record"' + # + # You can override certain queries with + # local-data: "adserver.example.com A 127.0.0.1" + # + # You can redirect a domain to a fixed address with + # (this makes example.com, www.example.com, etc, all go to 192.0.2.3) + # local-zone: "example.com" redirect + # local-data: "example.com A 192.0.2.3" + # + # Shorthand to make PTR records, "IPv4 name" or "IPv6 name". + # You can also add PTR records using local-data directly, but then + # you need to do the reverse notation yourself. + # local-data-ptr: "192.0.2.3 www.example.com" + + # 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. + # ssl-service-key: "path/to/privatekeyfile.key" + # ssl-service-pem: "path/to/publiccertfile.pem" + # ssl-port: 443 + + # request upstream over SSL (with plain DNS inside the SSL stream). + # Default is no. Can be turned on and off with unbound-control. + # ssl-upstream: no + +# Python config section. To enable: +# o use --with-pythonmodule to configure before compiling. +# o list python in the module-config string (above) to enable. +# o and give a python-script to run. +python: + # Script file to load + # python-script: "@UNBOUND_SHARE_DIR@/ubmodule-tst.py" + +# Remote control config section. +remote-control: + # Enable remote control with unbound-control(8) here. + # set up the keys and certificates with unbound-control-setup. + # control-enable: no + + # what interfaces are listened to for remote control. + # give 0.0.0.0 and ::0 to listen to all interfaces. + # control-interface: 127.0.0.1 + # control-interface: ::1 + + # port number for remote control operations. + # control-port: 8953 + + # unbound server key file. + # server-key-file: "@UNBOUND_RUN_DIR@/unbound_server.key" + + # unbound server certificate file. + # server-cert-file: "@UNBOUND_RUN_DIR@/unbound_server.pem" + + # unbound-control key file. + # control-key-file: "@UNBOUND_RUN_DIR@/unbound_control.key" + + # unbound-control certificate file. + # control-cert-file: "@UNBOUND_RUN_DIR@/unbound_control.pem" + +# Stub zones. +# Create entries like below, to make all queries for 'example.com' and +# 'example.org' go to the given list of nameservers. list zero or more +# nameservers by hostname or by ipaddress. If you set stub-prime to yes, +# the list is treated as priming hints (default is no). +# With stub-first yes, it attempts without the stub if it fails. +# stub-zone: +# name: "example.com" +# stub-addr: 192.0.2.68 +# stub-prime: no +# stub-first: no +# stub-zone: +# name: "example.org" +# stub-host: ns.example.com. + +# Forward zones +# Create entries like below, to make all queries for 'example.com' and +# 'example.org' go to the given list of servers. These servers have to handle +# recursion to other nameservers. List zero or more nameservers by hostname +# or by ipaddress. Use an entry with name "." to forward all queries. +# If you enable forward-first, it attempts without the forward if it fails. +# forward-zone: +# name: "example.com" +# forward-addr: 192.0.2.68 +# forward-addr: 192.0.2.73@5355 # forward to port 5355. +# forward-first: no +# forward-zone: +# name: "example.org" +# forward-host: fwd.example.com diff --git a/doc/ietf67-design-02.odp b/doc/ietf67-design-02.odp new file mode 100644 index 0000000000000000000000000000000000000000..4be2c7d4e5d718fd123c5671cb032a046cba71e7 GIT binary patch literal 331530 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

    Z@nSf;x>qbI6UCUYt#=oY$%xa9J2 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 z zheJ9=QgRV@i=0YKdj>(7~62I+=W}_{YjvI{V#KY}&7xSDX zYFtjUmO)J^fCB+(3x~t1t`@rEz|m_7d}KmF;S{;A8s!n2r-26+AcXs}&tD^1(9cbz;50Apr) z8UV(~&~UzpaL&Ym0|C4diS|AJjTg(!=I8&%{}18W=&(=C-@JI?!ms}3Z>?=@oxgJB z>1RID+vgUhXMgDvzxefk|K=O-zWa|~{fg0U8}%Cj7PCghjwBvCa71lF z^8J@zD(18M_fP04Ol;L#I8yNt2o1$htcEZ)1g^!EIy?ulJSiXnY!A)oS)wN)eQwHt zu?9v2^F?#j?z9_VOp1p@s$K9aLYIKhFX<_wXQDeIE_N}9u@btJx_t|Td}ODKRBEse zS}l~pfVADflc3~zJw@^@9tgAC5j8TVqiKeudxF$x*Gyi0waTHhVlB*!ht*pp5eMc= zYika>cXoQEkWa$ePfgu;?}InIUMGp~SWN@9LbsS}dt6?lrCY4U;q|y3l<*r0MJzxF z>{j&z4fg4Fx;VeI-sIZpowU)wL?a%HRXaKg&g zjvk8iy0u&`Z?m~`1x^Fximn0t1)PBQbjd^xo=(T~3Z>2Pz<^jNbh_BU$R2>0TrzWW zVG{^k$k{RjXA(pkYid?FTpk4 zN7SA#fYo3~YfGDUyTk7e&;ZmhvMYes2g{a30i7b@6`d(0?vcsl)ch%wFdzx4-h|m6wp(5KTqzNY8;y>`hYyk@@WO^K+K0B;@q;65KLq^-_NF82ud)x+-wOnlg7KT|-@~3DRcBN7Q9|iymTuUmS z*C;I|!BciRnO2jx+wB7bLwptKB2~G%(PUu}DrE|#V!2c?bvibS$$+w9(Gh(vlee1e zl%~GAx-5$FAOGPWCDKKk#rei-KR$49A`}k(*8@O+jg@CcgLH zxkdva96<1&`1mIwD6Vg;9y)ZWQZB-}eDj;%gemmwJ2W#hGZ>BBcjuiy`N>bNUcNjv zGkM_X!T9n#tRwhKc>HRusDd>3CyXJzlLBB+t2g5D7)3Kig7kP@A%7G&md$FpcIo2S z*cg%ShZ==W{)I&-mCtU&v%If`z+XA(k=j>}+>h?P8%I zi;~4;Y&RRgjr5E$TS%8m1)I|d+Xk@gb|SWazZozm%o~7*NF<^*omcA(A!wkCLaiR4 z3h+QxijhE~ht>|l?u3e(a0qGu6Bs=(9+LqAl+I$-H@TXY(s_LT&9%*eXkWE9x4O2B z6Kr233~++Ruy6hQH&Uq->H@mI4gE#U(~lSyXbJZ@IgG8OaOhXmFapFxhg=(OG`^8 zmi763;5C3>!X~uU8b(q((l=l*8J~Re$y29JX(;mYs{ zprdJxLc@XTXtjWrG@T9)pY3)_IW-6VkET$?m+I}gO1;$@F6_1r8A?k7uZXHZFqFoo z{PC?aCM8*kP&%-~eo(p&fN6I1dN6t|yfYZhZl@9KmNFC?n?Yx>nH&W&x3sh{e{&jK zbG=?orV@!*Mol&~7{T{97#3c#o5^jBj_hkws7DdH`4Vvm3%H`U17JLrO2U3a5xHJf z8rGn^{cHw}*6;NNd@e1m+1gxhG;4cCM;2!srD>q{ zMb(+w3H zqh-wCHA0bSqPzmL4nH($nNqIU*B@DKHzCY7$1 zs^BTXxGOOw{5?fj6_yQtqBdp*5~mm? zy1ftt;A$fLQ_->|;CP8btZXr%|z3G8JFAIT?>{Xmuo5W~<#$RF5kdE)p7v z(1=!>)#Y-w`DQL#=(JH6Pz*%ML29Gu%TM9l1Y~!I=dZqu3pV$({85?P;Y-Uq9L*2kwGwp$>|$6rmx?5_wmEW z58t?PRU||RXD~VGbXrXiQ1X%9Zwxj(qIrKdLvGFHcWL2M56;0s^5KL#|N%i@*2_tKI7lM!?Di zstF+i9Vc)#Ns(xUSTWc)$SFlZ2M-?HiN_TSLA>YErAr30izF~$BeOG8Fo8>JtLNW; z7qv}ev;gGHRujyg$zpEtof_AYG0oiUg4gdwO@2kmX|re3DT~djXK1I@2t$J1`{_^r z(#Gmqe0#gewJKcW4}a~qZgs^(NoY!p5R{TAzSS<*3aV#Cr*v)9Do&|_*N_BSRQ0r< zyq$iEj`5`~p>%`CZxuk_>Wi#q(A~=ER4z_c@kg*_<SrWDG^|i-~v-=RQAd;7BFwA({#E5g4jUJ5uGYBfU(fkk&MA#DfdP_9Rm)i zhk7|H@+SaQT^=Ja#cHiWQ%r*sve_K`JRFE}mFjw}B#AA**9m3|yU^qG1l;{|^Ruwq z+RauzQ-bF-8oTWtXFrL+{-Ycjb5P`a8g06njjv+($1qvPw-hTUSE|VoyEU1bo zp|()BFLKm!b=766p7NGLi6E${9%_i+72!cq4C#B5>eZ;+5!5`?UFBQVI*HpIx>y4B z76LP-(Gf5@`jn8=-mR_%U8VmEfVt)6<%NX>q{%@v!D_)z*loygv*{`4hxn^XPsWcW;a*LO=JhYJ`JG*e*u8f z>a``dH${PSdo8q%AZySynjH8xcq#CF!-GSx@zj$LaH5rR`O!xo9Xxah+_uZ< z1n>-2o7qX+ao_*|k2l_ld3>Hd6MLs-XZG0lBcx3sK_6C-SC&>;qh2*9yWPq+8{5gm z&c@cr$S4d0HU@0AQ>Pv(6iQdGPlER%chxvX=0s*}`n_+7xN-Vfa>ir48#5m$@lRmnTG0tAUQQwA{2csvfi6SgTt z3iV(i=+?Db&0G#KN|)0D?+iA#9gmfpGyq2k-*&s1WsO{2z^t50mB6K0Asl#8kLRvkR3*=);a3)}JR zP9kNunGB2p18~`FiFz7l%HcAG!^6{)t1rL&%Flh|lOw}>EjEW%OD!&5QmG-h9Ei5) zM00gDo6Vv-SfznM2X#jVh=qFEMx%Y(@q|v#z$OFc1pbd8Y1U{kTP?I)RjM+2^+pYX zgD4aA#xzAS`}XWDWOH?{y|J|jh>)RmU|;EY9P9?R?%MKFD2PNS_w3p8#V>yGmw)+} z@7#A_^(H#T?~6v~=jJ~6;Db|7KV!Doh#Ccc@zT{B-~!-%yY7ZDWhc3VmKJ-NeIfrPTPuYz_Wxy0X6yk>8GFOS;p)4g#y7J{@|sz-+XH@+IR2W z_k82)FL*-kV@HpVj*qRbuN^#e%={9!)DTxV$npCCI*YuxNu;gw4H6& zI(nMkzjrK^h*gU*v)*MyskWk)>a-eZmLXZMlOow-C)om&E49q#$l?9Ru3Y}GQ5Gd;XGL#7LPh>r|o zv>5G^H>Ou+r}pjJZwMVWTP$0t8{uG|#bgHLH+k)5O z8XFj9+rPZmz7DG}OfC=z2PH_ft=N?_005dCX}u zf>ZOm1H=6XUi;CjURVFtW?Zk+xy*)AHrcM#_l%8$rw7dJbcb-AW&UOiAhahic;=&@ zn%~&AvCRMZ;y>&g898|9#7=zYTocWR|_ zSHL@MAzR2(2L187?@a8pv-ud>MI*e20ag-?Mr)M%EMVgvifFaM!6Abs|;zj|eAHosEHq>}Y&4JHZ#I<27ro;vJKk;G9# zEUi}(S@={c1p}~HY`J_&?H{dHJ;441j)JmM7;=4meQ0n5oaoBR3P6YlAAIoW(c@f) znVOmcvp#w9Gz|6Xl}qqnNUEvRR@2Y``3(<7!C3&%JaX&~gWqj6TVjjzsuCa&$})I? zQaNBVFHYXvJ1}tm{P`!Icw(p8`rh}x#}Wpb?Z8T1zI?f*ToJjfR=~U0u3UZM$wvX$ zum)6Vn9XK}M@L~DU;O63AHVP6Y%zaxel8LTFna3zh4;LEPX`RGNF6ih7Xa;yyL*rZ985+1i zz}FDK*VcMn(QdYSyrE{ZU2AgLLWUDO?K+_<%6i;B7-g|gtCTqcYcwUf)$HP3(qu9h zid$Z<+2^-ztblKlA(pO{x4=*g1~Y^Vr^`^OC3R+|Tq%}H4l`>6v#3|{jYi9ZJ0~U{ zpM3f4LH|&KU0vPSMmNGH^60U{<#q#hpwH!YS{yIF`28<^;qSwtAuDTL%%swZ?MAK6 z=*fbBIud~)wo%C|JbFu~>i|(}Hd~cS6<9gA0ISu^ao|fu127s!+d^vK4W!enMK|EU z9f4Y)i|lGuJv)mGjl(LM4eW^%CxE`Z{ni_5vj?3PhDMa~0J1%NN6Z$At842vyCbNz z!=8_X!&0Np=;-6ek8`rjI_&S9{pv7M7qe;##iK`$it|gc)s(@m_l3L=tiS&JSK=G% zR-?Jh)c|<7e4ZXgXm#jF8?|tuH5Ri0b`GGIQlqA!$Y5V+eQkE~#^t4z`DZ`zsXLDy zd-d#Fun(1bS`vJmdRznJbbzOCwN~OO%AmXBxhS)) z3!g|_1NBeuD(R!r?roEDR*G6lt0s#WeHVwBVs&&R*q_g%%D|PSn{#v5Q^_rGJPw;# zXx33m6HodAUIU|_nO%tQ#4!y%?Dy1bTr8eyw>+<$~cr*%3G9z2*y=fHb`rJ|F_<>eD6?urZ{1wX6F2=fe(9qa%W9`)rA zI)0D)t<(;H)N9wS1%lzlmDOY>d!)h>nCx@A;wv}+fWyr@7dJO3gURLeQKWWpaj8d> zga*6kp1ZX8)KG9}X=VD(V_>vLZ_Z3Z1n8mUTwo?AUmES!&wlQ|z4+oc)>c-&`TW;6x8v#@!oE`PmQV|;Dw0zB%fJ1H_uhTq z6P81fKC9ifu(=c&j@38^4Vt-~k<7k<{$W)P)b;YN7sGqQ%7EMAyg~D3Wrxf?L~L)oM8s4%V7A8SC!Z zyEo*t6btoY1*zgwI<47mX$vh_q&<5_+HKg`=wuN-k#wuoIXE~xzm^b%9?BOhIrkp` z0z`NC(*FH>vKd~@y@%i~N{IQxO2D53XjYogWf)3pw_0fmC>mcXRUAI@(Z?qK@_&Bj zOaJ_>7r*=JH(vPWefK^1+0Xn^6YGqR?=c#z`CJLr3sUlX7tb8=P z3p`l_gbz`m+Y>ET8`dKfL24P^w2S1VGbNO7Dsfy5crnZvEP&td1-2_HlMDvhYPHQ~ zly}mvd;rB!V>(29_ywTb7Ly4fE2%6?D3L<#rS!l94^*o4`T6;+jrDRagSDFAW-$U_ zMy*mR_Io_0zJc?vzV?w*4}W;$GWe~%C+=EaS?u#g!BYZt4hDl@Pe+a&YjU+W-gpfb zY|rp$qt#3#w*f{4{NC8c28H(q`a|!(`RbFW?o*86AH3%tMV@6<||` zZy^~`)WitCRjL7trvf8MgW~vZr%*we2K0WYWY=SgY9ETou9iZ$7FGX(ElcPG zlq7IUNg`1apD>leqw5yA2OjIfJMUb*c5!=q1%QOvs6$>@>d69Lsux53L12{0g{^%P zeMUw6DeU%j@wU!vwAgJL5-FNHt+qtl^l;<+7o!JFB*1x z{CdC`rDCp>?{r&gPZh+3a80F>fSmx309!>7;Iu)w7sWQLgp%3Rgk3Ckg-oUZcvR1z zUQO4o-GJG9>Zzw7bbjxL-v{dfGo7BERt4u_epK11x8HbO64A-Y-FM&3HCnl1snO<( zh1~3oNhhm2d~l*ttu8Mu0MvQnu}8o4{J#J`4u_*xXQtqdzWdr6`$iA^%fCGLE1&*F z068#eBu!at))wECHMm4zo}mAox86=BVkp;65`i+04)<3|c_U5UdF049fACUtV7S$m z0I456dRL)P63VEfje7nFHULWlgNH$`uWeH_zPzxQFXirg;AH>c5ZFtt%DwykJHtam zC-1(iUX|bY@v9flUj)ElHJPX6o21%mRy_(;4?dAK!b=mRB+0wSM(C(P$*32k7P3DI zqX`E74jmf_DlkPgaU@Pq%7qUyVx>J&S3RFn1RNC&99?WHIWxKN>JPsI3!~Nc2ofP- z^qM#g!J88rg4`Jx=^q%vd>(H$o9(nZ#hvVOaa|PfmBo~fLKRoA0X#Ox!LgCpPTFAf zz*?%ZjHuuf0uslCBR(U5AFmgF23ullYZJ)+VqxXLp$Q22W(%U$Nb7-S^^DQw^zyw< zAmGyyx^|sch_Q9F8uvJJXhp8ufO}9k3O<@&mOAM;13>| z_~b8sYJF>KWqHBp({uH5H~<*c$C{iHreXA^o`$G2ODwCcw#p<4!My=i2z#05TQrR> zm{8fE(~d;mP*p((_59S5Z61CH%^TQ?MHRBs>-~N|Z~*W|y9btFqkf;4#IZu50AO@+ zVIHVGgi8zT$#P|WVG-5IfJLBGbOPW(A`zdQyE$~|NPKGx474xW|N85%!#nODx+h*P zoj!f)nMarf_hgMC9V*IQ zBAd;ZOZA>saM)QGDN6pJX@|v(itjY?cB~zsr43^H@kgFX^vpY@{9pau=U#vQ&&#j5 zT*1(#X58+)`{16ZI}HaRt>jaaAG~+2uYVMHtJouDlE{`aT&Ly>xcBVelg|}18FZ5G zcKgGj2!tsDC$m`~7IsBk6(|7@qf)N;TLXirx$XMe=IZJyx&kDS(sVFrP!4gaY${2S z=spjiYO{{+7c!}xP$)!eb+94l7FM49m0xYO`F2OtY7x8w^aY46;Pp`kr1!MEyaZ;g z!w8l&()BXD-Lua=J3c&q=FG!$b93-IdR7NPA2kTA0h-zixB@Wlr#|`dLOz36xFuQir)&3E;B;uKDN~Z-BffrlF zP}pm;Tes(842y*VED{N;lxvm7kI$ZG83SX*^+vmzu8-y-lQSAMk)hDi&G~#gZ893Q zgXr9#4ZhA`$z<};iIH=Ymliir8^a>lX>?n|I8D=Zx+0I zX=~4jqtWV>Dm#mbS*ye2iwp?3m@C)2q@KGtj~a|K4!(u!v_S1S*nw*E3DnduUxYmj zo>D{T^g1hJWiY&w*v@E4<6ytHR7%vuLVSDfwV%9NY3bGeaU3V9JOM!+h-Mhs#nCG) zt*%7-`d|&Cg8`uAKRo-Y(PkJA2G&;>QE!m(aXqcE8ubICdtdwR*Y*tf14F*YpZG+f z*e-7rzw>Wj`{Td;o8|S*Q}^Ec^yw#8XBUIf(89t>C=xZgt^yq}S)87M37*%}Iwx1> z#|Or)#bb~E>aUyazPXJQp|b!71)RDvH<<@)YG4En_WJpEj~qGj@|&+6ICRKpvu$OU zFMn{(BzG+uL#-#=dG{H-B@{Ok!H~!4vK&5gz~ivJ^zHB8cjBIEv9c52whx9$weM07 z@H8P3I4@JOa?eR19XJhjJB1!q!YQ)}*!0%L(r!Avdew=9fq1?npb}@)u13Bk2T3Rm z(A^dbe1GoE*FSvs{ceZXYN=|afelGV=YY6`LIIP}4nf=`pjE$deX1p)8e)wia0-yF zD<%Y?#Wf@i%UZ2ATY%Or!pa1-y+_*B; zY&MNiV=S>}EK7ASjCXlv=9(oAI z)5EdjCr-dqPt8p0SpEFs;(8)}-_wt+t*u!o#sQGLKSZM@irP>hJUBd*$|rkWS!dBT zt97se1Fn>C0%B~-O_&a~{*WdaRXkC-jwjS^@)V7_R^F=TR3f;l*MKRlMU*-wFnL0Q z(k5gT<{Avfo~sK{10wP4^i(>P2zq=Fr({ykcUskI9sWp^fV=bzM#k;2g(rsQ=H|g` z7YYFSvj*O@vAzb@o2#}o$|=E0dj(vt()+W0{l>-Ua1hwB(a-_gT3lQT1_Ous4y>%K z7!5W+F7HCHJquv=rdIpN&{fe-{EuHG;Q4LTj_g8@$srckSK z9Ra15&Rm(&;$4^B+bjqJgCh=?XZnK+KCd&K<^>6BwrB^=&MnW2T`8X4YITx4Z}a#Z z@YEdNs-nA14Ql{M(o{htY)A-#U}PxqK>1LwOMpkKDG*?+@pv3{I&8^+&T$I$fK;*v zC4d1y{J|Vy?Ulq+iz@yPF9m;FD;9)K8yM35y?cTI-|Wq4yVYFhs^g<$>vJ~&yp9bF zXj$Zg4;?zRu)dkx*z%e+jM-Y}P~xdfV2s&F=;6U@Cr_S?L?S<)nSrn1m|uPCb(hB} z@$&lm2K>3%YD&gqHisRl4%*$#<}}1!Knp-jhlU1kT)p=8+i#8z4MwBUS6+GLBR~K1 z14DygsqoJiUU=cxe(l#_=U@%KnJ>56u;}>m>dNuG2f96Zb0HQC`djt(_SPoKw6vP~ z`}XtEFdz#A-vIALYYYGZl^*FdI4U(q9b6_DrCM~a&L>P7{2Y8L!&tid zE>JpND53T&IJ&CoN*HTqQLCyR^1^2KU;2Rqoj9%w**qa=8;*R6-#P-P0P$rXZ zaUAKu0e6>c)s5H|e6{fHsmaL?-}}I0vR69N(Eg#7tvGDOch0?qy0^>ivuDpf{LpES z%?1GU?tAV;je2n$MkqD;fHypR&*0+x+}8FMU_rAxD_doam`1>FJ=qyS}vs$HkC7DhQ`a-83J=3DFnb}#n$uD1Rt@{17_3h zah^GI225>zeI3?#Yb&O7RYYS@6>ecaK;$YFii4vEQF0Jad$S#^Q|Z^;g}ugcP53#C zKN>}v&hT(xQm6|zW;8Lj2G83A;YL?e%9fn|Xtmj)^d=2ulnGXlwY)6S6s9$pthC-> z^+*`1K|p6@3}ZA~dql6(=GDpqwQ~@X*Hi9Y0BoqqG(dE`UX(bYp4bDoFdEIIMg}aD z$>-3NlG=7lB5+o%YX$1Ao{}nN-Gd(<4DCY=!Makb$w9n&_>nU!>uazK>0}b9u+Qh? zMPX!o?9kC;wMy0NcJrkgt|h@Q0Ho`*n-UPVUN@UbJ^l34OACwRgM;9(7Zw&CeE1Zg z$)%M=zbz1n^np8k>80lEz^qcWVs|;WH&@cREQKz7P^5-+%oj2}tOwYv##JB~ zBK2{gN&p%WuP1sa8w6#LYEY6WNj7SNQvNQ286lxN5l0PZ;5U1?s{5eg(cMB#HKSBX zDm3Io7)fk?qODh7ZE0|S61K#8Y}9+Md(>q&0MQUCXF zsNHI)jhW2`1REe?HCr6K)a4H^G`Je8*8vQM?fUMU=Xa6`gP!7=br?gTSWGXhw(1R> z#5{fvOc6lvomlLFM?YeuwF4ge$up1s@a$_1rP~;-B~z&sjBsdZ2#9GmlU4gZMxtRD z`Mv{(JRaZt+@IZf=iN^|^$gO+zjS41XZyeY`lr`dmSKSaLcsIB_uhMV+;ImCY-t67 zG)LGUiiA^ZTbr>hquB&zFLUk3pLqQG>`g#-CbOZ_5OEm~di|A3IiD(+WQLTnw$hJ| zQ1ow5&jyrYf)t?mt|AYPRPMT%a>ps)giH|({xdCQcPo&syDO5FVz;uD^+%Xir$P`8x7~};IoNpMgjkasd^2n$hSnN% zR-_QCRDeOCSBhj1@`I@Z52v1h?sfb85B2Ar{|6xPy|q1$0~l!Ijp>V%{2 zbrh8;`@CY`Kt=?$? z3k{4pHjtOj@@yTO9{Dj3UKX1XHLhrw|W=> zk>bLoYfnG@bHDM~-?e-Ev1DdpW#MaIMI~Zq&Yb$2zx=y>`}XamQh-O59>JQ2AAT72 z=gs-K?VUs<6oe-YMk4T}^H(RYT)(EZnA^Y`;X5j^mV@{U|905y zrOdX&=kT~3H?CZi&6<7s{R{)3Lf_$gfGe;b1>wx)_cYt3a-q`SHxlrA(uo|z-1tW7 z@R0+e)X3#Bdnbk>(a^%&W+qe6;Oyl~S5G~3UoM|q-&g_A?R47Te;;7QyP=V&OJ}p% z%;V$ZGm|%HT30Ej_-2A+DL@E)(SCpyl7xE1!#Gh-PNaSdI38*6fd@tX&kc+qbchO0 zQ~FT9WhYs%7+uYJ=hB5M;b6#P2FGRH#V?6DvS zOeT|?n|1J`0QeAikh|bV>(vVQB*6L*7Fv8e7TerOCBb9^j(#NV!SkczW3UiYQ!_^n z9PhNHo7>Cl3tRg~L-3A+0|SYzt>~d6WEbi29y@Xr+}`}m4A?Y`u&=KV25;5)V4Z8t z^1#4@7cQM2AKPazTh_O>;!{^oKmNoIfAYq$yY7AX)I+EOHkCU4;C%qSu3Wh?I5?Qe zX3w8L4@13j?HU;Cy^lV0{hbf``}<3kN_}}*>~;ZxtX`k_KmY6V8|&*M{lj2ovDM9F zEVXiTHQ)$n3_Y@5ssrfJ&|0J)E=w9xCtL6n5H1VGE!vuG&`C0n%`ogh|_ zJRW&VAXjZkuke5xN|Mr|>v)(rnB{OFg8cuh-<8W*vL|h=q+MtlKBwDj zcWQejkJC!qC${6Ma=8NdRuXj8l3d8Pj~{)&=A%}YH?&&)`bwc(1_EBSdz=*AGqb%? zz9zQYB*wIxb%!$mP`}Y>k~X`;5YeF;DPG{3#wEE7C z8&ePgBYl84j4Nw5(Yc$zm&(A3x&b9O8TQP9gZm-o)GKA!GuixhFw|#rhL)GNbD5ob zM-1=ZKe@CN@VFgFIhHze^5pf)m(nZCcRlp5&1QS^?Q?dA!|t#zEN&<|w8!SArod>x z`uUomktl=KxW2Xu3-=qJ`{UK+Yd5!&4x29(uQLqlrd2n{v5oot2L~(dVwtc0!aetj zys$C5;dXgBLt%J)07AsIt8;f8c>rS0*;mev4-eme*8u9s#jt=l*0(a@;c@RsWJf5b z%bR!Hcd*&$m~4iV_uc>P|9ENY+T!p1?&n^4@jt9CTmSw&;OIX0yPq2!9Y1{V(4C+8 zosd0Rh*vue%;5-`&0cUcc~JlpZ;!>Cjqy+c5KGxKSi2{-F@!`> z^K=c+X;RCWHEJcDdKJ5iM^%*=Rm5Js;;$&}2f%FrH`1YOapZte3xzf+Ey`DF2B2$Z z7P+pb*sNCxS#;T9u|)MZTvUH3$LMsWe4)mnVjz+4K)9Ws zzHBh+#`g4+RFtbXbGeu(^L^2=*iK?>Y^+qOPEJnxe5g}pt6hu5SBr(3+wDbJ@rC;A z{6eWx)M!!uf2%EE42BN*NnO6#DHIE(9;OF&Z8X5dR4dJBGz^ee5wb+N0U?_Mu#m}U zA#kowZP2~dsNg#gE z_uh6@cUOBiJ>Cx-2@oUz9zj`(q`0R$9ku(1BK8y^a~t|YtI#oGC9QaOij%0-21Nr} zQ6xavff+vojOm$a@4LFZcUhHLnOS+?%LH-T0Zg>1%F2B2_rBlvz4tSPV(#w!_b%VK z{K6ML{e>@nvESlKnVi#Pd3gWc=;#=R}(tyS%Ng!{$apcGm+z;%2V`Jm|nU_XJ zrgPa2{6Hd=Jau9*5O)*`xy6O!KX~Ow48zXO9JzD*w$ov`aQ;*#vwN_&kL%#Q-}=@+ zedQ}(Id<#>7V0lwd*dKic=E|7>#g?FPe1wY<;x%5zCJfSC3PFMQkk*aND`w=$s81} z+$UKzpn+zS)nws~J%g?zc6t0#A`Ln);(D_)s5y7dMm1upxvft!L$tz+U`XIbhq*(B z)tRi8z8YcGfjb9PiWG4?o&ax-(WI!nw@5w(-}mA*(4d+g@w7@y^T^i8;ge$!#e?gH<1peeS)2-;v)JWe)U~wS86TgFL}HBwi2%YN zzzf^$_9Kh)*RS14r!%Kco(C;DJj`xwYykEOg_0=oE#C&#jAcyfjBadL^rVlq zHd$B<;5opKKmOxCjwPa`TXMhO=`=@15>|)*{hJ@WefhG~A&0T`M(f1FLMEHRDy7M8 zBX#%whZIHDLq4Ak1bn#XWD-0962nxlHbsFHT6Q_DLZ7RYcwTH-`?e=8eM%+Dm0$ky zHQ)tB58iwKjq!;TDERH0H?d%zeCFx7nT4CTZjO$RwFUa-hxaO_VtQ})=9SBH6QeLt za4)yj%2+KfmSy@fiNY1dK0XzC&SWvljLTx+tww-cN94PT*jHo$^o!$cS{)I!?gOKp zh^l>TX)TWwul1K_74k(M&P9pPJ3Zv7~4IuojR(nH`3Z=S2 z?+XHFbGX%T!xl^j?~(_6EbjmC#%+(!Yqi_!;Eu9P(g+7~x==7H-9n)W!p3pCJ-#FG zVyDBA&M7vf)xzlz)1i$I_>H^7*X`5|!xL%4P!9-Y#6hlMx zCt?Q72PU;rY7-Qx<{b{-^Ur_2*{Wa~?k_zAeI+d%0PsK$zk1L*9g~FwTgjB*^4eI& z$Z@?|twAc?k>e;E{*=w+>$SEr(Dz8tD}F3MOJU4_rqQ?$m;`Kt_27aSNqD4WGFixG zB+`vl(2n$AtRH^(q0b+^c>es>+G@LABYmKGK3mA^2D01h#mh*?9Isam_O)?6QrrvX z7)TCl1=uu7rs2q)J9i$h9eP|2M%T{f_NJ%KeCc;TpLlindq4gcBc(5vig+z0%H39T zXM5f4@FLR#p%^ZB{PyCDEb2Le9e zw%#aHwAJAxZEpDvO}frX0>#5) zwZUBa(tw}{@A7yhsSCxRRypMcgFc+T$Ln{x-3m>)++H`SpwEZ{xl*h4+9s317Y&UH zVyoTE*hnxt94OiRQX5}e;Qm0!7LLq;L*Kah{$z3n7r=C?%_e1`-|IIeykL548jl9* zs?a)`!Z?^=8a+YWKisEv6mFnc$qyx>^=8LtVsiQFP<%9=h(p8e?rn~Zjqn2BXmzJ& z=MT3lc)MCS($;JmXq~c8z7AYYlDAnX6u1s4Tma6R$>gvMB9Sou)yO?~Jl=*e#LKia z+E1d|z{0fs|9Ck1*=L`7>y6j9i+TLMRw>pR^|6VR=Ep5It7eg;-9jV+w8NF*SXHYc z<;w6I`2BzQhkwxPJSR>iO*Vk3P;XS~t@`P6XAjDUP$qD=xb3}68aLeOcG|591~aT3=cI;Jx=I zC&y2mIFTA286Qnuy?Ra2(UDO2&g~E3j23gTUORc>*!KEr_VA$3wG#1YHl0qy zW0i7=B%eXisfnGWS-p`&g(@V3ksQW4cb**6t9{nB znoytY>f?L-*6Vk{`Kw33W|lGZc)@J3QsjunVs?>MN1aZK%J0=1&f6;KE>{^jgP0g-Huv-SH@HUu;G_6Tws~NcHrFf#JI+qWRi^|YVGDv zo;AhoYn@q5JW?z!qWaTCuk?XU^RE;0g>Bi}2E=OB%}JA`sfO zvQ#Tq_-;EA4me$wjqTO3xy7&jyWjiXxBf{o>U~~!esxvH=tKdmpR*d7mpo28fhII8rZVX<4k73tpFqvjaLh`}2FJ3nFj6R*%9V77t79&s3klo0N#NzB zrN`=S$leQ*V<$HWzYBsr6r)MbZH4+e(xw5?GS2U2e!?+>dK*gu4Z*A&2G$IXZ!iiZuvF5@jS%livcefy?cjfG zbFciWX_LibRW+}m*()AEO@V0hQbTR9PBxrjz|BV6XdwP5=pL#!Yh8{sYKM05_#GRY z%X|AefT*=}>Rj`VMUHUOHet!^B48bi?-Ziz(8*Bb{rdxQSKX12^88@_$#=GHD@ zhtqRI7L&VJNa5=^ zurLaP!m^6l!Ulp~k~YQA;-Jc!+~R;6jgM%qhU&{RvkQM(7|`zE-~gBk$Z^?i zT$l8GSE!G>th5>(n3tZS8>G8EDHQ{+qN8c7RkFPEgwg5^EPezFDpxCbvDIe7q+rov zq2e1YEE*00s{(4rX0;|pJUcrZGHqWxky?7Zw4K=-S(xc6lHF{an4PW^vT*lsE}N?> ziKD0Ryzjj84lad}92*-0@WX}r{Z2hYg#zCB*~xCNfBw>^H#YZowsJas-|u%1CE`2@ z($#NorNPhqz6e}km+yV~%U`y;++C4WPWbiT`pq}qeEY2r-u=tJ{L5Efc|~)}!C>gi zU;W)T-+Z$(=rWYf!IN?}eS=Y^t+Hh7kq&PP!&NvuzZ&c@Fq5PYg8=2m3l5(J7RW&Q z(t1j!2a?X9vwIwt9$gnCIqZ)@;+YLrtI1KyH1wjSru4>wVW-dCZCCv^=Y^TkL9g$1 zx{3@(OZ{}_pw*%b;IUSh-JWPP4kcQ*cbL%vCM1cEhyDB8t3jV5q}Cd#H5-*oqg-u0 z^USl5y6bB@rTn4GYIj=Pg>=nga!Flg3 z{@8G>o;f(&Hk%EkGR#n*Q5Vcc^FUYM+dpu+LKEXtl^QUwd63>ZdFE)d;`O*aCdFdW z8EahKtkXF>j*|e@4d?&uXi*x z%ov&st88uGb-6+t8;8$5I}euv*`wFF4Mx-K+`LY$Rx&c0f(Hj3ayXod(uGVp%oZ!v zhTZ0M*j?pPBOLMm{onoP=bn3RYvtaHFTS|Bxe4e^rBYaFw29}TM=9r{hnp|G^!bl& zJp}NZ^z?Lm`0?7RBVa368?|2l*r`;{F)UEp;I^2%kkG5PU^ZZEaC*S(-fTWNo&cIVZsFH)@zNlr` zQM6v*$*~U&994t8u{!l81Mpw%FhfH1^lE4+Ifo)Kc%-DgiLt4hqqN#au}doy+?mkt zSd471Ns<9Xt|xbT2E0{PI=ya{rgFIw-aj)#a*p@*b^r`hQxkjJkK65TBof3gM@L6V zb4Rn89L8*HyWBRX!|n38pL>2zl69q0dva=Y`SF!dFhYVpi)F8u0+m!KsZhv>rB1cd zh{uN2fHxmLKcCM)%LB>k_44S*SiMmm9v)d=BOS9PaS#c|46L=)hVp7utCe2AOR6$8 zyLwYh)# z%*k`-Pu#w9gC+Us*{}TW@18n$>E`W^3YGf%S8rUoc^5JWL+AH+Z(O+wgoYZu{=pR( ziJ7D?8A;DBl1wjv-tdY%U}@5KOA#fS!MAGDB+~gqPxA5xq}H;I8L&`4q`5goYC7?v z8W;r~!%8B_fh56*qNEH&QR>oqKIHUBuznI9$@aQE%1Fu?H8I{Y9rAlf8%Z^&R;N&` zP7fB3*>XBkIWw9*$bj9GhHR8jDmPp%Pp8v07ug~RLcAMK^ z=vqk-v>Qv-YH{Xrc{uHEw}s2v9i|RPn@L`)sV{Qd+Z%B1SR}bzW+)NSDRh%m?HVC% zGsnmAC$&ILxY;Bfc6N4l+N~~hTP|C4yS&$LT(#LPpw3v;(B`lSyclazOQP3K?TsF? zMH&djpx)}u-jO3mBuRm@jzmJ6JKI1I$YJnKe<%pS)b7F%+tX9YdaWZ51Smq>M!QpI z^sLq8dhqzM%jK`S7;?CS!9KSv zErUeyTsIO5^;#Xj*Ngk}1`d^#LW#FDi@B;J#BTid&P2Z!Sx z`|8SykzvEZ5ZCMO9~>kT38BYB4Kt+eu^RUYd+W73JuAoP%{o~DH6>(DZN@+X?ZM6@ zSuLMSgSYC{L`P1oSfFi`8cYtbC$J@f?Iign=?WzDuIFn1NpB1gR7IG9CoW&*z5>vhE*LL5M|B23I?BWPWF7 z-wD=HD7)R}LcZXfAPvAtQ9i3#XbNE1nOxTGvhYF&BpC7nN{DpgvsommFNu7w+Xk90 z9+~&~-TV8yK99HE?2ry2tR8D`XLoCHak1TQfmUKJBcV~;WVup2e*CDK5f7>@l}bgz zxz)<7q*=0h!UW_1mJmwn@)%5(dV_@X0bk)>s?%|G(lXu)ke^|*Ze5=;px+-;orA6w_Gmw6=&62=ElUnqN#DGe0@ifRM5%bc35=lKqxy$!Cfou2L+S!tMKx1@FtPZS| z(Lp8P-T1u@mi01kx3B-i0W4RZK z8K=`h=xnVvk}zR9?KY2&Hn9w;|7A;ANq99yTP=<@$AeS$gnq5j3Ws8?W-l7?srkWX zttb#aLd(FOo0({~>U_5~H#3RL7P2`Q*53XO9D1!*!RO-jK+}VReOjlGtx7fEUn}nj zw}7Dlf~uXzMA8vhtzy?xL({brW_*L^+Sxm#bu8BZ!9l)SZ3Kd0(p<06_~IA8s5P{J zY`=T=F1`ZPthox%9TGf&pb^78Vd)L7CN^e!0YXj=I% zfBQFo{^x&QYk+!mNr|1oAe%}1y}o+6U}E$T73a>J1&F@??t8!#+78%XamO|XmoK1r{kLkl;&HmL7(TkcQmS`>(7{+pZ96S%hf+omv%bK~qJv>tjV3q% z)<67j?l2>$$*hj)*;B`l>>OreZqL!UqBL-N~K0qY_-y+2Dw1o$qV3- z%F60vtuP5be<(g$D3k^=l^UJc+1~GR{oUQ&*}1W7Hq&YAFt6dbA9n6=0$f~>Ad#?j zdwU-^C-8kJ0I^ST9kJQS;G0A|WCejy2F+R(4>dnCYqwaBE*vphNcbFS3OW$MC~!@< zT|5GKf;`}Db~BcH<}f!tK9S3oNj_kdC?Oy*RxeDjMz$10ZI2ngdw6sL>a|#InoJI_ zH?Y04*Q(dt4(Ia2M<5BYaOBR-TR;}rlhta++87y)8;lGo;pPu}+>s*-ekjHFu3SxL zb5A|}OugF1Tw9D5q1Sgh92;v70at3&tdk;@Y@?V-Fcyq|sZi985hjd7I7p zH-G(Kk1n41#m`^I{TGd-maWU~5SpUowwDigpu7s4a_hzo{0AS^>2_gQjaIAPYhx&ulB8_NbiuoL<*R&EDRY+ zrO&WxJKBL>&3s~jYj&f7q(SyYtU_>efVR)=p$CLo>}+ihBx*R3Bt>8{^>kez4<9{9Z)5BVg*|!=-_tWRG#PF$9G-gk@Zs?A@L|57EnU()mm0*> zFTkY7Yj;-2X)*q1S;NA@;-iPl9M{|0+9Idwfxr__Jb__+@ZbS{1WSQx{NRJDu_1XV zF|xgVFP$zV5+lU(2!hpUx_R~5v17+3Q)5@JUiCPf5Ps0w%galEAE=XRwT1;hKIWq- z!}Q$zkAC!{YNhrE|Ni&?k3aj%iK)qR=Ps~%Jy>j|Sn_);w{F}tn2Z=_cyNQB0S(RM zb9jWraFU!O(ll^{5PF|)Zg%1B{d|M5@$WOH|Cdutcd z@tyB}_ka1HzZ&sJuaX*i!CXFb{N#z*`Gt+m-O<#H*z@jeZv%Q#$)We(f8Xn{I4vgd zD{Cn7gYUl*RO7j>UAuPS!UdRLHlGXmXBoTQC<^pIG%$+Z#F+FV(<-$aQlr3Eh@4Us zK_V!M@4*l7)ovHnmLSj;Mu>(!4=1WO8H_?lN({}mxK6HG#rp0x!NRKpNvLr(&?`zY zb(;NZgM%}&IjKUUXr#?|KYD1fnC9kVrD_GjBAE(+9Ew#PMz+>c_R_nh0_NTn36EB) zxn7Tl1%RrCLy`ThBBQs8LM!YZ+N%_bEn)Y~dmek(NeZV`OlEO&;6b+dw-Xg`r&YBYjyqjk;UWBoGG>o zSKfT<)Z(Jh5bj?8=)}T>_pe;#rF1lG)zh7qKKtn-3&+kLpFiAQ`?VLJ|Hps+>(uzL z!ASdJky@qRYjdfX!*5_VD%t7rk*%F=MnBj;*wX2-NWxZ|Ve`SV5ko&W3&;q1oNTXa z*6W>mw$jPAxcU#i_kRO%=Tbo|Y^TYz{NS<7<%Z*lsge1`$tUjKTVA@eJ2pNFhT7_v zC4)ZKsJ6HJj%eu3n>Utrcd!N~k4`0zj=%gHzZr~1e@*&&YH|u7{npOP@yR13i*uk; zvlvAHVxJ@ZZA7Ur7Wp zY4v1riC`|0Kyt&?6MPU6Jwv%{(8{C=7vYc?{=T3#R&01<(Mq`iHa(E_fq*yY_hM#% zNtZ5N!e0XcAJ=WcOL{#)w<}a@Wa~<=)9&%SESN~6_km*II=m#Cmp;5ZJ3i?TxDC_* z{>yB(b(+1U^_6}fFXr|SFfLsZW)}32=JlQS{rmTEhw-7P)8Pj5Bdf7P67VbaQm-dK z205HIkK3n4BMd6FLn~>WN)p?Fk+Eo;=Sk(Qd-v|S6V7C8_~HFEJXbosFH1d^0n-sM zbO1{X3nWgr+p#0*c;nW>{4wP2*Jh8Ha%(o=W%EyBLQsXO7UCY`bS41j2oDqoU%I|U4h4^tgWwuu{?X`(%izl z&0;mNhJ3LA2og<}&`_*F^)UOS=;_1+7#bKY{)MGVI(Iylc=OFSyFFMC+ZCE_zuD~2 zl`_1h5y2?_?(hCis|okcJMUaLcjWY$bFrbg!{ZT3JMW0!5O<%|tqo&n{Q}Zm-|Pg86|3X0it+ z6EiZFB3p5N{^F%G;9En92D~jq_r3e8^C#y+fhgZ?*z7uA$Ve-4rzlX0y<4q?jxFRf zS-p;eQ?Aw!6+RL8}xpmm|tFA2J6KT!9L*ZFdC}K4n{{u@#%0HU5-~2Jxud3U96O= z!^spmC1)9j%h}-Cqhl$!LR>TA4|)UshfAxaBFv8)o0ud;`4sB@!{x~6kjZE_n;g|j z#bI|<#qzc5AHbMieCaa^P33cGC`;1r%xV+5{d}eb6mZg!EAPL*u(()PcXn}Qe=q$q>u%|a^!;LSj21)5D1KMC9HKuWJO>UD;CyG8MrX?D~ zg!RAyYguxs7pqOa6 z=_x>q*8}7srMv(+kY6sR7s~zE+-#V3i??HSq9X_9TFc7^y=dt5+gMne!VZZ<2&f`ZbUXN>k z_ke5m&YnA+n41HC1ypbE?(QAz1FC0cW&o4*VtHlh(ZI;~qv0sf&h5fd@z|ZVZ5Jke zkF>Sm7>2dk?2C&>@tDnGNze9=9y|8Tr=K1kAL-JqdaE)qpOX8wM=Q%e|M}0q@r`fb z@$D|>2iLAX|H9{f_S5foNjbiro;4@-+_*1^y zfmhe-NaZt0q>N-!$L_S-dR(Uqu>)smHsd0_4o5S3S?ZD)JW60#+H5x3?DkY@BoOpA zTa~4y!tvue%vQ6(!SiI(2Z4}dpo41GjDS}3l*M7O80mw(T?jxt2Eag)l?V5$HnXYH z0QA)0UJ2z72G!yVq-?6iC+R_; zCWo9lb)wO%cRDgg9g;a3BOTYY`0FFI}?sZZ4SrL`ZVulJr-nR1e{3vucj+MzE}2X~fu+;C!y`jaKmFwO8&`k);~!tV`22|z zr~6{}>Id(LeI5wfX?35Sc{Y$7{^A#2K5}$%d3A;B^>F32<&~|CP35pwX*FVFBirfy z>4iBAHI|mzmtrxUPLGa`frs?_m0&RJa(NO7=So)|9ZCJpS5MYEHLlP7yWjs>p<33n z`f|D(iO0@gx(G=6*)M+n^2;x~yqrXc8q7?Lzh=`?Yc-IuslqO?LaecB>*$ z;AfFUa`dg&Uri(^2KSvo0M&kw!wIVzz@w>)}kBTq_uI zAEfsHOVNNo8KESOt5sWlfh6RU+_z)`&K;#`y%gTup; zMLkR+^=w@(EDS9EMw9F`ftlrmvbMLcRTu^cXoc&w?N!+8-H#qP>^??s-re1GI^7W6 z7*sg=bms8afAcrocE^n?S98U}cYpHVoOa8vz5K#Ye)LMQTz&4dpJQ!ylRI$x)wlBn z-S~Ja9*?I|V^dQzw{G3R=w12X+OfqW;Czpk;GJEd?CUG*q{wZx`sFWusY60?%TqJc z>zkX~n_Fj3oxbtfJFLr=m>y5(a~7Mm-E6sR_ORO*@Q0Qkuaf4PW*Zi>)nbR!PYexD zOw7ni-wEvJs>>T|DgESOzMxR_Xk-kc@TsSsdhp=E>GS7)_UbQyrk;SmCrZU?4ba?d zws>&>n}OZW%*^#=4jz-EbWlwSDTWI_3so&EI)xdiPFzbvCMmQen1UFq7YtSX(o&i} zasAo}iq&CfjD{|)V}ij*ganH?-DE#p;=1sz011VJN|68nallt=HKEHHKBl*%rX-AY zGBw)qJ%G&!v0kR>rwDd3*8CDpK#=u}Cwbs-cBz-O7JD1&OjZCvu z#TsW#ETo{_;ph8uB;dp~v2K&eB#5=P4+@uBtG3n1lF~pSVUYN}Tm1@#1JG+DBO{Q2 zSS_$okYl`lcW2XTxA!Gr3X_@`r$pHR9lg9fHlEC+ce~`+Ph44Dzx3(P7#T~e&4(jC zQg+6m8^yp15-eUv8$-ePg9i`4{q67AolL9MaXD?FU=XwY=+V-Yj$|%CUFD19oR(HA zoRKbJGCe#xVs$!-4xTkUko`Ej>vV2talYvhQV z)=8KlQgRH2MKQ7r4l0q5ORclLmMRa&4ZBrsRIS>j*ZR+XqT+E|UWW_n%I0*CQ`5d^ zph#s@vbSup)@p^m*mBxU7KfGWa>}&HWM+(Xjj!O&Y$_yc?Q*zI$7VF!T-LDPmnmi* zuGOu@W;~JN$xIW{3p1FXKLP~hyRtd#I@r&-y-J(w8`%Ia=qn}8Y}fh2Hk$3r4CVKE ztv18Z5FZNoTh)5l7fByv%x35K_|*05-CmiXQ@}av(vtOZC9`IvJ3QF6x@@%G zAc*q9;&IaRLm;(~0HW}WP)H`T5x|Bkld~M7ktElLgBS#0Eo=e<^61f{jrFaUUV3?Y zdV1->s#^1hMB{t?zHVOtJ$?GQPs5U?QsX13(T$bW03>$3^4e>^7#SP!`NLL=lhPT# z_x+zz<&DpL=Cc^udcAhApYeDClM}Q1`v-P=_B-GCjz8e=`)t908_(-ut)(C@!|`SLSQK0P@%BS_+8b$b2r3atMAosYyuXZDFFqS3gflDl1K zb`nW_?b?m$(HRWm`uaw&8*oR0lteq7A!%S@j3US@+~&!XC-Kx6jUz{n;6d~T#_4hA zGdXy+zFLjz!iB|+jjh-I^>v1Bd|cB3%lt>I-?@$Sy9o!Vp+X$KnmtdfCZAm zB1klG*R-rkeW^!+`bajT+7P={Z<6jd0}6U7kcb<7?qX?IBvH=>qXBx(uk$IDB1m9f zstB>53z`>xwq9=+^NmVdrW9}6ObfF3@a|(tpjhoXxjfanyWV&0a zr`_>afBYXFFF$(ct+!jf{^hsd`L&l{wppxet9MDSI$h_~@tJ5eIzK-Tn)}nA{!|bR z9>0HnX5{BTe^nV!i*vK?_;4T;dH8T;`{8zKG`h0-=+cGfyyo!J7e@~>d$v%!C~||F z*FY{mymf0YeE@%7s~f;W4vYKM{JrgTdOdykhkyE~PKVD%GXgJX)0yCS2!6rkaIP<} zyIuaUJHB*t+3ECU`WZXlDVIy5u_P$XK{i+A8akIbHZ#s>LdT+hX^|zQUntMl2eJll zAD@D%-dt_i_;Jxj`d1yowdzhE7jf2_*HhFd1))f5d-V&KB?4t2!N22A9*?&#i2Hko zERkM}(FBEL04|d^TMh5?Y({cwO((mu5O$=cQ#)s z0mL6aUcqfxtxk;fd+)#F^E(yF4%pA_=SyYYVRw7nj=Q(B9!Ipz>3Bsn>2=`8Bw9~V z>{h4EDo3LxzhA%;+iX@yL7*nr0UH)P?%>`&X}T8*MW7~u^tewbB)H&a)6pZ9bV)fo zl2$;z!uZY5Pz>LZ@cy2l)gAz@sCjd~`}avvT#P4-cx!X-`n5Z7b3;Q(wF8bDP=sg4 zipBRppm@w8^-1m79;{%*1_SEm&6|~4 zY{zFw^~SJ#%oI(%Nz6qA&?Xg71|^f$lxP0+T7>z z#{c)P{q~WQC;!jC{HxKq`3Ea&t#%LO>csKmT(czigv3y?(;-1~CX;1yb_T0m3nRc!CkU{q%}_gMv|VkqCfsWzxtq-K=*UzH-GK5heU z_(WHcV|t1<=ov{Nug5nQqp2>-cuh)kgg3iUg8cYV5 zPFJ=JWJ=q&f{k{&9fu8(Ocqr^(^#kY|htpcAmGjlcXMm9yG<<`9Z{50;NW@`MSmYo8 zHk$?Vu2?J^jHD)6r84AnS?)jhkQ9AjEwBbs4%c9)kw|+d3`pw+W;F6%uiNeP?CoYj z!9gAXy&!2dQYXxI?#vVG>*-g%|C3t1bMc8Mj4Txm!T7Ro+}`@n-}tL&YPiey?%%(^ zv$HcXlDc-~Dx~MITE%X3c%;*6m5Zfry8}DM2WdreV53^E3oZYI)mbT})8$CJht;h$ zgVl&-6G;ZFb|-7FU%hfG9FA8TRfQUm^EJJmZ$ULix&rTTIiY~}_V-`;-uFQ_f9>U8 z4<{1isWI>e2s?+_9&q_=Ks3g*mMaYf<9I;UY$}#39g$48*yaX&-{$9DGt7k5nX6n>AVt`cKN`X}NVD*Mu4rOl4 zaM~>7JU4AKm~5nvmOdIBz|sZr|{ za&-tkZI0D+!oke!l+nbfuBMBJip7R>Gy{|}7)Z5IumX4v5*3g=jK>pd#GPqtYXh*# zvd)Q#iE8zzMiXuZ?x6lf_n6pq9qbH``1xsuoG3r9m9k8^MD zz`&Yv`6AG*-fA8_as2N6duwZJKvwvWO11j@v(E)hti@r!^8VGx$Z#k=1i$BXd;aaG zKN<1|LN0$S7~R<0Q5fBRE@OreRes68x@^jA)iIVz}UYb$YFbiQH=Ta0T!MpU39+xrkBIGK>;Sa3~hLcKc>H z9%n3;`;Q(k96Qb!*rkp1Qg^4*p`Lv%GBO%#wQE`wCd>NFHap+t%|_k!&U!MLs5ROH z#Sjig$)cirLSF=@7pX?R^AZKP~FcS58 z8CnX$HXKM|Oo(Huw@8yhs~wQJu&_|6=GvX6POV2rsS&vOd={@C9-f(+8e3j@01vC~ zZRJR(!$7dzCN;CnW)cK3Q2G#FtyWW##1~~i8@Sz$W~;79VlWzc#JV|zues140wGWyE7S!>+wJg3tMc~8)r_P0w0Zq zBaa_HhWfx#(HaurN7(Do&=AmcbA4T>p3X2V8y^}vcIu?nWiJ$SJTF4vj!ljAAVL($ zZZ&4|xm0TG#OYHes|6RqGQ(m9dnpx){$NPzwk0axPm1sgA}%2YWTR=}36k>4J(kmWpMNV>9_8b(8CLE)ej6ax5)9u-Z(l zfzm2m5CWiPX=-%_!1=npTBA`jTZ~xIm5KsZ1HCLuWLbhp08pQN>eAxkVj=&g78FMs zps{3I02g$TTo=V3@CJkaYOw?-Q?1wWS-jA$)l135D4-ynI{^59^C?01O8g_{fogAMydh{rWlNNmkbA^kao1Mg;@OW4=upvUt z?RFRdIX}}=28$^*HmX1)Fvh)f2E1@?;u!QcAg|dzbh>T+ppO@T`sPf2Z)JVW>vAVU zAoMwY$*@WF-i=c7Z3MzamOoST^iZS6_??)o~k zrp{)qw_7@rdCL;w!Hebn4BHiPtBh8V@e?!EYG|otaoA64JN~NHIC1e>+_6?cSlbc& zxF4=MXLuPNReOPE-z0IFM6gR*8Zil_BFC=cKp{yfG_BSy9gtQK%0Q)H9xdE*NrMzh009sZ#922;3g~KnRM0Nb3hqhpXLb zkW+YFV!6Ve^7*2Ao=h_4FbMfV7NibN z3EyM6K6>=1*{pWB7MLR0y3gf6eB14w-R7`Z&3k)WZjU38j5eDjD+{ZIr5KWL&2u`v zJ~3Q!noA=ONhPQb|2ymf@PMa-kS-2TmP7H+6je|NYiKzV_N{U~)sTI551| z;d+gBI-Q1-#f^nj8*(}vd)qr&XJM_PK5kE|WrD}Svqb$tcsHllJ2g8c(K-=U+TlV` zmogwx-oSM{qT55>IGh|c8m&Ih*w)q-V>BFQGOc=Jaee{71lJs$7&F(a28V6bF%d|_ zlCkL4>iWHh_k|`YxHLIAH8whY`N})M*Ji76@#Lv&t=JKIW&>+50>%;jrMyjr=FOvJkYjF9X7jF?XOJ0voDf9 zPlVTkdr&4&IXy|yP@{@Up`g|6_SdW3Rts_jl9_~@N|F$YhGEQF2!YE*?gRt%g4r=L1?_rs5>9YzrBqSTt134}sHkWs8Wzu&)gxSNRhW+#WPzkg$X zZo*);>U3r^N~D34~b271u>)Laupv3DjbWE0c^EelT*X6(b3V==H_;%eSjea zD7svp<;U0IKgTDAZ``0x1mBbUG6^2)aa~Xd;5r25{@&j3Py#M{ zfi#C$x49gdLKYJ`IXAPvwbkdOW~aTqy8}k_uRrIM{qF$uqJwPBzO3yXKI|Jz3HFcyhY1F75TFh*0m z)o?kS^**IH*b9|%wbH;6a5^Kn)We6%_P7fgkFOM`lkua|!^q(JdC|}(61O?gAYj@gmg9-TK?_R#!>oR?@ZL#uRlhMMG$b81EZ*=)iVb^Un zWiz`C6L;y-r8nRBXlTeM>xFu29gE?mr(fzad)5Ay(WSe3<4SU9Xe2&rWz1X4D>^&d zl7xWWwY78m!r4%Ayli(+nfy4`MzyA9C{6Z`g z1ScUWn(bz4SU0!ekH`FsZoFCs`Ab%6O`Fr;_EXhL8hS-fo43~UEbFC}{^rJkA~7bj zyH+osI6iav@_SOR`{@3y^!DSg{%^nk;NE?`(Xh3*JDwcL7E1kYE;TaR?^K6lr{|`o z?%e+9t+(C|`8_qh{x^U9jmInbBlB^K#rN&+ejB3U$a&Mu`Lj8pQ=*C%#w}CkR=w+T z(CvEG?FbgL?Pjlf<<`w-o_$U)^z{bg&9~o4rw?s*dvI*x@#>nMq9HSK2ZtBVp6iv! zMt7li2!K2?J#RATx3<^ECMPX^_o;Jdv#n~OUIAePIX=C35{hafH5rU26*H5vAd0jeVOu>kp2L&@ceCX*Gk z6>tlLhQHq1OXK3Q(2oucDI!UK?e$3%+&~!^Y0}AlZ)zyc(o6T3?p=NVgW<8^&ph{Bv$N0D z2HEXlo+&0AMQ5h;} z)2wz3BaLHNqR(|QO_B2`8Rka<(-bw=IT9Uu^mtY14=fglCxsvIX0uUkR4{@o;O1;r zJ0w=E*3{`Km&;MhR%B9Bn&L>xp4{Up4+Of+<~9p(0}L&-U}Xv`4s^|4pT{6kX0BaO z6j70RNIt98JTfv2Eqw3xZjGex2=So^R)}85DpcR$Vu$=gkj4;dhv_U$>HC5-GMsWb zJwm%1DeU?>?Tr)vXI_?;;AQhb~g^Q`!=Ub($U3IM$eEAlzyYz zkGu#GKh|W?Co7QXiAl1mJhtqD0#rK7&ytEo^iRBSSXu zfCDBnEMR-Q$!xOOEUg+hIhDeE-@kt!pgTJ|3-4^V^&Z{4wY$CJak*llNUPCw*~zXp z$8(_w)>{TMl}e36r=@pEj@RA0_Wy3Ifd@2ks34RX*8;&RN*M67xfZwj zU`P`BHm9@I?V4GGK}SElcehq4c|Go+*GCPKj22}_Sfi@OA^Y_PRzpqAKtG9c(qix| zdW*Un^>HULg>*|Mb;>Me(?BM@HuNM6N*2`)m0<3v@oCT9r5@KLnSDAMV2fqY;@U=N zH%cj&Dh0WS8M0VNbEa(Wz{0=|NowDKW)wYZv4Kfix?E=I{s7rwplDVtRouwuijd)Mrz;v6+TPhPSZRxmb$cytUkvLNpV;dO ztyZVq=EldJKzbOcnK4LeNmBR|2wP6zJAMAr(bLjEUfWm?2i)mHU8gs=0aRIf9I*L- zosb$mzE!K!iDU#mvBM=mtSgmzu~4RHDH;nJjC8GD1OS8igd$OoJ8+QB6WwWX!FN@w z^~uy!K3Ae>_!AdJTN=#@z#ebxwaEqx;A(So-R<^*M=n3!09LJU?Rwqra4-Z4QOxJb zG&kz_(cy4b(>aXWrAtqOjEcQ3{F1!wpW7R# z)tfM$aMTCj8J`>*035n}AP~BC<9aw6Ti@8K*PFlnJ74-QfAzP2^hba6xzB$FKz8-k zhqpiakQ0Q&SgM#V)@vQ9%Yk zQavf8_i;NLwWG}^&BN8^OFBveV8Xa1fiw#ofVsk22b7wI51CHs@q^;=guK4sdbw;e zaXN-2J)dZ$ClH9j^#R{@yVYVbsq{G0o!D2C5Z5Rr&d%v-<1sCb@hTzI^Bg7vldbnenZUeFo4)$<;3@GMU z&7dGX>meQVJWtYotyWXVw7Y*G$Pfn%$>KQJH`~k>Gqb<90Utg!5!+nflm*J*Wq2N9 zIS59xySwl627Es6*48GN3F!dQ@0%?wu2!w(d4W^YU|JrZ-|aF$M_X+Us~Y+UtRfYb zrM_OT(7FM`=+z_&KA)?F1Ef|NMax?1CaGXxHj91W)6m%1n9$?3Moq-yDT6>XEC{WU zkx?u*kK4Diy=OLC+fXHq_K$w}3ZCMtU;E0f4{!Z{T)hX7B-eQ+n3blgvb^`zRqcD) zjOp>184N&Jf+Qe{1SCo)QrcbZ?P~9&6W3{_h`Za>!n&byPzt=OQ zERlHn!o?@Az5gZ{_(}JuKjaUD1C9CsoXi_Q_1}0hr zUyU-DF%;`-9x-c=!=A`PBzkxR4+Pz)uwwx;hpL$9D$ffjc~k(y&VxxuvB@NX8Rbe* z3DTh!49At#)egfsX{*_$1fZVW*WtpTH&as+@W)%*nC9-mIqWfAt3`>Y{M8&2iFv`P`ur{&cLBz&RvV&#oja4Y+gu<$ z2m5XC+yD?6sRM-F;SA#h+K82g)PU!}ZVDnQd&`R&Ck$wg1%Uu*OU4u6p#|(2Sfs2@Gp_0}Mwf-`XaaP2h_r0eol%QuI-Fn}D(&dCmr+ z4xX2?s|3|yTC`#b`#oT`X}_m0sZ0-Wo&XlY>+-rCej6rp{lQ2!;Bwn=LbBUv;B}gc zWkym1p#|~>P8K}T>Fnulx6O10fuJ`M_4fP3=H^y^;Dj+EEu_@!XuQ>Qfqoy9i<$ID zDv_8On=rGAkDpyE6!$aZ>A|qe_n86Hr*J#VuzJ*Ox48#>sb?2lF0ZZ)L;+x`RT^@} z#+*eE1)W2?ByLv#u5)DC2Se@mcw9o|TCFHa%wlvs<=vhbO~W7d6-BpMfh5>%6iPG9 zWHOpAgAkyA0o)E(1+}q~oz7%BJvK3M_wHTLc0iGL?=DfO6Pg>~L9K$i zjU^(<*%?%S3Klb+jDL9TN;n$&`mg+QS0nZ}EB;UzrpwIex7uynd%L<3X>j?;r(2z_ zs-tGuFvj2i{r~f?U;lwKlk8r1db`yWVz2!jL|dh6CL0R8n^Cm2f= z3#G1=AvAREjjMWL?*IrEh2c`4ugfU-!7Q8xmohSQFhE~vuMg&be|3%ErAi@x>f}No z61Li{KYrr_(&R?wfhXD!#fZZK&8BFYA5|u+_xZUllE@BIpk6;-4aCt-3FkgTM73(r6g0s_Y4+a>l(1VA| zp`c9~BJ&>##=xKgkC~d9$`=qP)pRV8jF|BWy?$3#1l8h_jS}VPyp7{P>0v^>v@?=Q z?BurWZaR^O4;Xl+;e`uN9_*JkY6rVJIdHGLJ9&z-Wiq38?%XpkclVP!$$0$fOP6n6zj^AJW9f7}7Kpt6 z?t1`*+nd`K%nEkl-sVGKd!S}8q}|?f1SK@a^4ei&>Bya0y1wY6nd zrdfe|JX-$hSAQ-P4&uN~K+<@X?>G7;Lju)wI;>8kqMm9&mKBvNGwR^tsIeJ_{P&;< z3Wv7nHMz%&U@R>*XCUUma0_Leq=CdrLlHPV*j5e9go`5`-l>_fQf`m$2#H`^llx+; z1J=A)KLCn->4|gbyrkY*zLSeboS}Ivp3IcX-Fm4u5{nI_!OCVnp7I?(GA!-~SMRUe zyx5s%MvEnJ@1XM33k$bCToE`JbKw4s-BYK=gKlfHx+jXAkOw<4Kee;H=SX_;2e*B0 zMG>t`vtHU~;t6Uzot?~1SIP~M*KHSVq^GKp<4EpzOb? zshOQ^lp=Ea^vQeo?)Ul~+7_6Zo%98L`}xAy%=D=zpL+l5wX>glzBL@)yZ-S=CcVA( z;KJE+a-Zup+ARy&Y&I5;AAk60nfAB@NmUG@@ROguUu!By7v>2t&4Y&Bma!9ouzOh9 z+pL9Rv2X<7BWP4Cl~xJM{jIg*$B);y?;JmV`ggwh8&}_b%k80$ElhYE(y4`btx`X8 z@>H!>d+PaT+s)?W)ad(f{RHg&7he86z(^yYyF50TJ#~6UV8SRfARt+~#J54&T;S~1i zkL5Ezrin&{!i*zLc*kx>X-l}#Zh1I#il`^HhKiONVS5fY?Q#3!@dT)Qvs^-Mj=(`Q zTTBVK{KQ1I*XM@dz7!?`ttG~O^yM9p#3$|N0?=~;qKjT zbI|8Og8;lL3_mgg{>Qq8G7$p)V6)#n zd2&o1Dxx3>0=K)j36C>7H`(oQAXv=?(`VE`(ADmC%N5D*cjk6-XU?9lHCqbUVg+k8 zs~(qqV{7O9F(BZZK&8L%g^~63bpS2EX90$$l9`Q-jYv2Ks8P{ySUg!nT_pgPA@78t z9PYz#v%#Qev%1nLKdOCuhQ$WiYjkxtoeeG)2B}ZI|SSF?6c4Q?VtbY z)0duvI|2&)(krikrR?&(h4cwKO+;eR)vXNxe|vj-6Jz7Q_)A}_*6X)!t=zeN3t)u_ zi<`}6r`epDnK5XwZuZbwSy>sMm~1r~Km5TPeupKN9uEbhnbGlhBzpA3;{BV~qrouX z`P}XvEZhe-J^@h%vzjOEIK;)f48)**FJYF{=?#zRDlA;f*i61r!Gx!c}GJ3F} zil$LEWOTuM;sj;4Ie_2~1{A80jo<+iZWPfc3O;`@oyv3?4MbI(gsf_V9_DgjK938C zGgxjF8wR63T^GI1Ah1^ewJsNOK^8*k(-b&`9*f})$&^d@vDx}C^6l+ykJlmasE#;6 zVHQGU*yh-HMj8%mR-9vvic}f_PQ=(iv%+BNwJvZbm(vUA4VJCbVKjZ{aOn=&Gk@gx z_3Iyk#)0`~x(!&ZSS-RaHfzAC3@J_3;|XuQU1~Jjku(iphIYUL3vRbJ9C8Z-jWEO0^gW`0Nf#yD@+n7bVf@L`986VHk}@yIpoXo$)waFxM9^UTiU) ze7U%A`lQ|G+1Xg39BAth#Ko*T{-u|`xb*P;$&*k1;QOyXT)GE(0y7D=oa=Vd>2$w` zjz&@BgOz%)y!`cVe8cJSHe0Pbw{Otyh|^oYaQTwk>1r`tt;LRyPd2*;`@8%0`FSu% z)6>({R^#a6iTe*8U`-_+i)TixojA(ea=W~MJwV$5JtNsb&F2a5@{%HZ-5xN*>E!In z{fGJx?{PfJH&ll!t4kQEID8(`6iQP@59`~boq7CcaiZo%sQJFdc=NN7rY5^Gf}d2g zbto87K%MAZK$bgQ9>?kdw|{(UvQa5F>jfa}0BlDyZdfg*(*|Pebd$l5L)B%5?IvTB zs)o`|C>ssJglQ^;qY_aFmC4pdqvd2Ihsy)E1Kt3_=W;nn5~WH@a$mQA5ma1m6td~_ z#X_OL?%sC3P{9dXJRVliu?+)KMLVnxhYKVFmc;FGqUcGL3;4o70$Yvt$y3K*NFdOP z3L-8zXfLi)C>l%CNm_P!F}EM6l8{V>0X-LssC<1Q9=20B+vBonACQKzu~8t@z|+UZ zVxwc}O0@vo6eb4{B#JeuR(JOcQ`57s62(F}6hNo{AZ+G54^b;&RmT*H^s>wVsHZNX zOdQfy+{La$#ZN>eUZPRl9!mTE0|-S^eJkzklt<^`}1f zba{1I81(F&Hki^>Dy156z$=d)DdOBOS&bfA3V798z0zql z1{^z-q;scEMWZn*ZQnh}{n|hKdbL#h5C8Vxr^De=xuFl0ewTf)w3J9CxqfeSV!YmM zA5==C;gH`SFxny6(IEmVs;rZwL|Um&Zrv=`tEvT?w9f1u>|=6uxs)4u&lhaYr-m1Po%UY~8Zo2bH!BG?_S4$}rg zR%tLmyU>XjuA*SjLEmbW@^iasLi2&y6NKKu!9lf3jgF5`On8^?Za5q$RUgcuri(NU zL$dUGieO>qj~**ls?~Zc8Vi#)2iM_s3pqDG1waDiwOpzsQ!$thx7z{hVI!z!t*XjW zG#osX`dwAFolPd2 z4Rk(Pt(L*S1DOTh0}OqBe%59UKUjW5k+w{B9GoD?H(|Ab%L83Roh>8*F;Y?=4p9Sk z5M~0SYBd;PlwsT8D?{N}rBbw7gYkIa)*Wzy0=SEKYJ7QR11v%;nrICeAfrc*AIpx7 zPE^a_=!d|dtyDY-^d>$&ISF`!?RMc(fAj5c1N?Zne$WC0!!QBApJ_GBMo?(o?bx8+ z2eRK`x}l)|y|;c^ELZHm^;;*-J$ZNOj?-ZSHtllS`&{?r^Do$Nt4v${^;)r33CClA zG%zd4%Mx4)B~$cx0CnK3;NtM$NSZLBfqI?{Bw41NsCMyCl%{5;{XQSt>{FzpR4ax< zXoCVQEATCthn<}~Ng4H<9v?LsLCt2eJfS_#05Qc>{ZvL#H((<{lpt{QZ2~vHFN&CX zGz!-Prw=gS$d|B7y2EboIo)1VbY##k2SHo zIGk3m+YY!0a4Ja>;92Z;m(3;_HAbxf=|KfrRRnH;IX0`Pp$rTU#v`ESZZyO69kgw4 z4`40t^0;MH;d%nl5||mV5I*l95OM~CS(f1hepo8i;PPPM8mKtGV7KAjcB|EFs>%>V zO$TMiQBDESdEE|tW1wInf!jMRB^n-pge9Vpo44*tA|DO10rI$?2pz0F!ZnNCHH%oX}Je4zwiRh>`KRJU)k`2kX645NEQHF4JgXom4u8I*<8-^;#>H93M#ATYH;BNr}ee zdwctRUiEk*C}5VVW0pW9G7b9LYIW`{-Szog+0nEtaaKQoA4eg#3$%L3D;xPOSSp9l z686SR`wa|J`~lDQL9dXnQFy3UuLpyE9@M}=gaST!D7alT4t7u%dwnUD@&m4@RH{sO zFp?f;8PvuGwW{~}VQl~sQ0RNNi!sVxwZo1XxF)Tn`>R(1an4a^z6c!$Z?%mJ3HJYO~S~ z2RG=OO?csP^7;J3`wx=IRDZyrz5Gb5T&fbdbtvg>uLJlQ`QIhbnQ0-2u`5H6d<+E} zKaPM#h4E2pGf3-Wb8F@^8K+Nx5R4cU{BfEnO4M|rSP)L?+9-RkgW`8U-J|iO+vDkU z1|AwbOAmasaT1djgetH!j*~4o*mZRD3NTC%MA~MDu`unf*5e&USK@McAmvKA9CqU5 zVscE%L{2_)A8ozOeg)4{pPdU~K>*J7~{HdSY|^V0M0D`N8Je z`bs)Ek%*@P{xA?4j_Y}SbSxeKI9RRJ&!4{lqk8aQJsi^P#2}JFbxm-ly z{iJhaV?!De{!k3CCgpN`^_PAzw|{W$qYvTNdbx7@#wWcl^USj^7Yc=DyEQd6wXwFw zb(usg4#IKg&YgHHN?R#&hXlkC5C}MH8Ay!Z2OG+&IxoJKaH+1v|^w9y|Gm9sr@b^$a5 zrtZj*BM2y>ejY}x20&7hI5jmHkHl9Vu8@QsjA$?rEs(n;MFMT6jXGhdR2Txb1nSQu zTNG5y0aGc$s*{Q2>f%sHqkev!l2j0u_PKQFs+9>TPUD0T)5r$T;p8df0Z? zO?!GnrcfxRMyD^oVEgWOz9U+Cp+q3Jp9hc-PbDX_5g_Rx=@W5}(}{sFEgYM4kS;~T zdZH{_@pvc;qwq1{QJq$Tn3|BrM!+ur{W)oj$uHXKX%U0tP)3!=x7_Pc_Pk(qq{;JuxX zz=PR!AsGvF+ts^wZYD>@Uik7WPM2@_(Q2)-jfee2!BfsxdkrO>839mH659{AmO_E> z!rZZlF9OTAFn#1N|Lm{g;Jl8d!8*MC)3=XI&tl*rajI4CoI86~!<{_=i^MXTj)Q+& zm_Je}<=9Sxv=2uz(NnXh-~GvZjY`!+gTQqvrTaEVkTkf-rPW?pUp`AEZ={e zH}aY65%UL>#=L?__RS+Dgu#up1T!59Gg^ql48mgUt?t_G1gNaqVo;CNy?vlQpsjv?y)hHjm~lC?9_}(bU1CJW7(~ZoYe+CK?BgKsRYXi z6i$XiJ~4xG${2=)FEeaY5PQ5p2ZA278%0~;O)&hW;%>9i#c9+RtJh ze^wtxqe1Yeb92)$CxA5_c5k)XgazpL8J1?XiYJ7a-%Ed2y$?c>wne_I?I!H+FpkSlWk^RwQ(;vKjRccGP zMJH{fhA9BZ>`uyS@sMU7h*^HjtTAS8;}iJL_U+A6`^USdq#?~F<^Ocs->d;)%JE^Q zp7~cUqg$|K#GRNT4oC&2QtD-zjanoewNX}|+a-xuX2h3FM0+kI+`d4F;d=gnztv$- zBAY14Jisi}Bb4WPBXNoV#%|=eNig<&fpa)8(}b(4MHKXIkBLNVPLCU>@S%#ex*cf< z5FWV|RKZ5!%~*|OB5htU;0pn0+u80JohNme5Ww$#zjq=S1+TZW$C>F$3?qfc9I=@7 zV7~wcFB(gV5@#Mj3nB~b)o%BJK&vVWt5cP}StA2(K@dKYutp+LBM*l_m8nGzv%p|H z=H@7-7FbfCcFQ9_|CSN!hpa34BTrMS&s0j#| zk>c*=y&E5bni+{JsTZEQ2;SUn#jpM2PusAsuq1kL4 z?C(Z`fqJD1V!$!5zQIH?T|21ktZs})v$045pn=tGo0yv^)hcYcMVbO?xM|#sEihA) zNn>)&<9HMKni6(sSust0yfgLb9_nGDvuga9VN+&ytgfhL{FG@;Q4Ipe`Kup%aF8#% z99EWP2@+#FO-<&3W};j(38)k@9q_mCDcA2!jz;qNQnQHxZ8wS?M?jW5ZvTMqqFo3A z1G=VTC`p`U`d+VJ8mje12W+~-<@N<>8FfFwjkd&SCm-Zh)npTVqq@T`ze=K~Lv{Zs zitlqM`L(q*c{n_M>S(cuPRqL8zSCs~Brgau>X_}cd%Yf@8VuWq zn=UM*_xJaG-T>Tje0&@Xb~F-%dreG?@8=GjF30NX3h)e|@E&&U8@bJ9ab>O?KZ;Aw8KNw z4oOtEHg{Inx8iH4E=y<7y?gU^qg-t@oA5t8(NBN+(_E>T@VWgizsKPgc>dn~doFL_ zpW7^#HaPmNfIB0X)=dO}Ezr zN=ezQAeW#=;Gk^+>Q`>1Y)*#5e%0Pt+bUH16 zC)JQr&@thpBWqJuGXM)<7wBHmjplXr|JMF3SR9 zb9?Nx1B|!gbOltcgj%BvhjyBl6^$URV9kv(K{9;JijyE%jd}}h7UNjgN0eA~6EjZ+yHwJD&u-?hhD;%VDR3f>0uHnja`E2mcLBq*N>x zVdS+cmrgsjwzl9kPD;3{FWvuSd}11ea$(_UrPczepb4<+ii&z;^@AZVJQ2zpvAF{N zxTeaLavR6N&+s7sx;8`!QQa1RIY0$0*K)d0^f|1O$L&)jjpcf^dIRKYY`qN8f;c-dX?FwxgWbIO@klxe z`1s(UFfuZttN705*5%7jgX#|?3BG^n(&f#KZJX8k+Sh*B>9CdRQ${FjW7vz!P%r*w0#jn=)!LAzk~~;r*fOH}jYQlNrIFeX~4-NtMit%P8^! zRT%)73(^UK(q(#)SRx)vcbY|`p_B+%SQPpu&xpp8Y_D%dxS2`)FfN-N^-p&>eQVxzD=};%lZ~}nOb@l8ci0?MpGP$sz|I3@VHw^$mxCes{2o-| zD-wY>5ngmqW*RrBuNi}EWKR1El|2AK@Qkro0^X_DTSgR!&JFtM6d8@CjbiPXD5#y* z01%5m7;*CK6EH=! zMx)+ldcqLUO{WJ!Ptc-M*DRz(kp@FuQWMDt@FKV==(8^n0idiZxB_4vLz}X&1ifAd z7T)dlf}!uU+Td+49P_!{9K!~DK2=6t-z8ZF6S%Rp4J7ZS7hiO^oB#ms-M;m?ix*#b z;f3$NeP!vvC-p}8m6u<_F>NTyiFk&#TVajaZl~600tN#z05fB?+Jhm-{Pft)=9(Z6 z!F8Z2A-u(Hb@r4&qgEnKp){jNO{IBU8wb-r3jhu!Qa7sNW1sQ(hmgROQIIgF;kV4x zdw30oQxGK!ra5T4s>nwCo(3=($K>&;$=i)QXc$PZEObR4prp4{VqKm=t=5`3GDX>F zQ5-g!%?sxyS+@7^K{Xly9*w#(QzX5&R|fn)M9F;wh?k`DwR$<789M-i>DR)cC}~ye z^)gH-O~Yb(`#ql2WSgCUaRPz_9|Y`J6lxMu5Cyf;!Z4JDGc^H%$acG9W7$kLoja(2 z3ayc0v@AVnG&9iv&XfC(EySv|N zGDl|SjW6?xiglUhojbR|+a^Mnsn`GFwAogI9!HB}(RT=eZ0vrIu-#Cat32`W(0+r?@dp(Y4xK67D zE}R|on{3za_vH3=o`3mEk|UPc3e(u3K@Uw7-Au{33XEMHvEu0#EYv)6Zxs z_U=3HJon7A9j03@7Ut%UO;1k)1}l{+9x4zp(C({Z(J6-=e1=Y-LnZ>X2t&pOCJ5C%Q+QB! zm}@(2_jqY=rl>wCIQAiG+z9H9N=l(}B^Ju*l2O1;Uza7YGe8>;w%1~@S-Z=!zP6i5 z(q39{l5{#06gwSXJmR0B&`W1VD54sTrMn!XQ92#8dU%4gk< z9<^BuSuiI(D3|I$FGjOdOm$;^Vd2)D4-+vjIR0{_JUKQlDRQUT1_6pkyyBqap(Rb? z3E2a7Vr6X;XoDd4y)v70$HNhDi?TQ1EEXHQC?%7V%|4~*Xy+_A71;$uYCR7#j|_G-Sh-11foTS^>8$tz01VJ&vmP~GR=&;Os zA?8OW6Egics)u7l=^L)0$MxFgCXSh3X1Zxqs>BFNH^U;$Q&ux~PmnFXfal2E(LUSW zQI=8DDvL@{7%%bhbc`VJUaOZ%B`^XjRhu>&rs&q*0GNl(EC|4h0%^0JJbAiS%7YPY zHagjK_F!*c#_g?c!yWPN>}*d?%rIRPnF^XC4F`*h$HB_N-MvnPt8@)Ln1!GiVbJNZ zC$gjcf!Gbg`oz(*iZD3X;FH#hdCrY7JSPoA9L*w{#?lY;?^3d8}VU>KMUcrhGm zC_`746UmejSfd*e5R@bV+R^NGRD`EmD)|H9nIqnzB2`O8zb|y@iL)Pm_+cs%qjXei z9q?JL+3@;(tk4(oxfh;$_PgKx?&m-Md3b+KRgND&-fGlg+^HRiupn`5?Oz=f{%~JqCrd( zCnm-ORvXBormLV-Pn6EFvQl3#qg>5j&Fb-}S`#x=G&~YbyS>3sBrzN`0wK2r z11v3jJPvsHT74Le0cN*3U06Du!b#uzS5`q-392;>q*4-_fPH%dht0}>2PdqGPSXBJ zvB8P58gcqFS+6J!3dJ1isxg(W)(Xi~44nvjqM%+Ku!I9ZCLJRd2e;5PkUDUeEui^c zpi-fBw*`*UPT4qCXf=o9W4OoT1ME>M=P8?Jqp?sRW|kBNB}YvZ#xsu#5m2c61UL+E z%2pe$>1IC+i_7lGBvW3GUs07>y{3vii{|9o6|e+$9H%LgV>%4S35v)Hy*hAhoB!h* zA1xf6Te^Q2rnlLum&yfDiL)oadiU;aSO}0#!0HSGB83WMZEqGqh+zrV4)%{Nkg>=p zI@wm+D6)H~=^Cyom<1!jjUlYcFaUOq@#{{9%j{JIa34jE8n(%-{ADf{JROR;X`mn} zBbOC*=71Fh6ApHLuaE;{G!jd|q=AVo)c4tD`|{<>A(yvVs?JXz*nuNdbneNE zIz=p=IG2nk2#ZxRQXNUsGU&Ayj!s>8;)%cin}1;1y;M8_2&>twO9BOaOAtG#Igoi{ zn8ft)Ww>tqEOEd)t*q+Hwv}!s4^j^OOx9zeW4O3$Y3*dBMJb{qU>-TgzQYu9NTcsU{ zh~x?&D>ULlI4%vOXf(N>E6pw(zj6DPH|Q=jxo6JK0CU>tutQ0yH(8H2Kv}K)VBmJShP7lUzKycPLO!>Lmc>3m z^}_yswNVGRK*0Z2veRc<-S&~mng*)FbU{@!0wni zISEF6nzp)*=!O`a)rk&(~r5ss*ps8-gVDtfavi zfhy_}KVUmDiJ@&EE9HXqfJXoVK~e~-z*@s2iy~*bAXpxwr7s2E10FeyT4p*iY=Aa; zEHH0YV;V`HH?+02Ls^TX6XUR``CJj)pVLVXhhnwLaf7}u7{D=fUNw*gswU_5w1oQxlh%Dd(n=ndZGPv-`q4sM2hE;97~+0 zSV+R{_V{-;`C5Y`EUY499w!YPSP&Ie!z)#o4RvzL)9wi1eC#B>x!Lr1F;J;cC<3&7 zb7My)l&P7yVxblZhPtiBxf4gXcGqQ}n`QWV4IR^&Mh;+^s^Eb@NRk;D2lgfbqD8f* zaok2&0RqaJ0*){Q49$k>N``|D;C?RJ)$Mms8w-No-79*$_HwzJ9*Lu-r-rVYh9nk? z!Q_AhAZ|oDJnkT-Q@Tcqf~v^qY_{K%Lf#-o*con+%a?##pg25PDU>UyI*Qej2zo#! z*j|tCqmos@NVr|=STN6{<@?}g`2lzD?k$&-ZZxWP)Ve9s>oF|b0p!JickJ~tnT*3p ztgfx3QmOXs3Ow(|=0kq~^$a3$Ppe&(hW-8heHNt?T8t7H(P04?tOV)}%g1p{JP!T= zoT|gD%x}iNnT8X_0~!v(2agG23gEaU9(vr_mI$-2b<>6k(oMYe#bagc3_|RG0iYC zx|(d_1o+h~!eL@lkWtg(nkdKA1i0ovZIU=Gt2U4}k^nyt5c#3Yqg!w~7_!%DOsDgp zTmk*Yg24m;itU~9ky&zL(rv-5;KW@Xf3w+|n3$@U55Sj!jM5aY@qHgnxGV}Cat@^M z!{v>izWL7R*ofa3E)}aH2&T{pjaorE*go56G=WCgtqw{f;=XW4WK>xUdcEeMKfr%Q zwD>(ii_M@2!+s(GV(X&qu6mUL`vEHr-VL6yTrR_xIU|kO3ybBDy*Rv5M0RU#GhWx&KK7Z`kF|bJ> z9H<_IgZ8;y-cX>|XLZ0r@d$7`c;N?z10OhpFMsJ(7|%QJykoa{rzRJGMQv^7B5}7U z^%PYQL@pW&fN=!@0*_ZNv#YDCsF6dY+wHKRYyblsPP9D?7SXgdW)mqher;)K30_Q0 zOrQe1BO_+9G1hpVe6PMmn~X!(af{?SM_v$M9* ztv5m6jvbp!jfA(imT}C|X|+i#5EvbY7b7F7NGP1!DblDnaUkRmlxvkhWZK~|a_%sr z2CgN=zUBxX_on^nO25iIIYPd zA+mZP820(YiFmr0XLU^m5;{FS2?n54YTNCWfIk5G0$eT7E@;|zPdjDV9w7bH)&M11iM!x9)BiTgoCS5{V^d-jD!qct@(bN%{_bb8b* z`v&U-k_u+bbTvk{EUM!G>;$#_G&J0Nc84cyRK<6PBEc@l-g~${7+_%(zl%H!iQ!yV zcG`hhy(;t-?Hf^WXey`2Ozx9^2!t z-}o4$dG6=}pqFyB0@?@@{L*tTv|BBJs{i6QzP|EsC7y`18|@cfctMdAD@DmLih9H6 z_plkRr2+8D!be6P8~V2wz})Edbk#VD!N=y z-7e4UbarcFA2~!BuXA8Ah~W@L*0Fk-opHeC}R8cVxm)6=UAy;7f+nH zxW`myPn_QK>=etzIlHT;41Kh(J?sX8(SfKdINpA zr@NfAc=}QcodIeqJ5`1B@fQ8({)ZQm({q5v*e)|Vk^v3>qd)qiSTyRkD_&pRL3^jh z7ke$`rHfM{SG#`YEhfA0-h1!o`JpZizxLIyOpaz{#nS1p$s@#`yytf+uGXJ%*+he6EusswYxSkF%yZ!mmh7s_LX0D*xY~n z*T1uH4t!byx5r$m?Pv_veQ|H=>WPa@&7C9x!({?Whk3Gn`iI-nG4ha+Do>6#vmMZpF)>P=L3&?xj`ZV!X6Y`40a)}|d^l0Z0K9HJ&} zCr_UKr@#7ZzHof7w*uVj+}S5?-@AL`*6pK5k3aRfr(yg|u?jBUcR36o%g81z8oAUl zwj*4+@YKfoHtO=|a^3voV^I7jFP&?&_uhN&y%Wcd!xY!+b+6ll8*K~nrP}D|D9k`U zU;LGC{L{6KjdV6Ml$4P1bLIW_Nt`%w^w@9z_HToM{Ht$$i%>WMv;5_^zxCg~{hbSE z&YwO$%Qkb*y!?f){Pyqv^dH~+A7x)BP}vYPOOzJnnl&b z0hY(u)co`?2E{>vezv^^JanNzOZ7eg8rr^V#df1&khVL0UMEO4?Vwn;4e%70zTB1Qh=&*Y71L<(bh3)kj z7M4Sp7#kl?XRhA;5GG}7cc;rTUXLf69?@0p`iCFET!AMY%}#-g!gMuJ;X$+tk#Kr? z^62~T-T7V})WP5=%; z@xBYYfwmbZf|M5RvegEo} z58gU5H@7f9y>xfI59GMt2YwccL>w-3xEP7WYW4ifUwrlT*MA@mc%RSPXqF{j$c#oN z#unHnHa3xb@~J7Du-&`enw&~iTlZU6+{-rFGxsi(!PmSDB%cpJZK5KUm zqwdWlC)19avi|tUiXhG1V7S;}1{T_5v!E>Kp*qwoq|@UZ8=t)K;aeJJqimQz5UN(| zf;6<+?frq!Xttd$&u9SE2%egr;CjGhoruK5(+ty*`-H<`2Vn&QVYgd>nZo7aY2tyf zN`0(dHU4icfb30s=~kf?vInv)aet8`+Iw5&z{98^5LC3XU?2idT<|* zrOW9V8=YD_b@H9}-uHO@6lDW50T>+!P$UwaojDTl`un{eVD4;o6zg?{qWtAoe?B%g z{+-vq7moR=mHc+C_K*MY_PKNC_V;&_>E!SJ?(YH&1cLv>Q-!~%LnSX`o@izw(;Qpq9HZ8q!GP}p59bMPXQ zjVVK0yUTF>`poR;PF^nbb|1%-97^h8kf<5!d1wyJGZl0H_Hn${r=I2Qgt8`nULdoZe6trm~R&E^xI24#a?vl`K{gf7TN89(^I zf@4l}YXuP+)DE2jGY|jT+I@zyA_fUY3kB5+0z&DS+7T3xIUUnTN+(D=DuDm^heky% zhC_n1V#b*q$_~IJtJOY4r}Vs$(hbZL7_|gbBF$!ZcVjERy>sjC zJ@A7x?abvs5GU^3x#y%Eu>8l5&445Ut%*bu_wL<0b7m1}J}`P&bmaDOnN(&hlidO< z`e5nk(K#^xy)H91HwW(C+@#EokFoupsK^1@`RLK=tFIopdgU6d1JJ%$(r$(f0W7gu zX@=o0Uw%614}5at7BI`1XzJsSKS@kXb-8vV86L@|X_x&Vw+BOd^ym?ogG3_EOM# z!9yeOCyPJ?2@;!}8tpN9F28l+)XBY_DsV4R;YjPTvu7^e{^%-vWrd}7tz7g=o zsETH@(G*2nDci8eqsg#hb{Z8zLNS*TXrSuxV<o;PvgUidmd!+YD{i2?UoPh`EFE{CotEB3RAcy$zU$WOO>0+xL0gfQ4399s=V@Cr7~Ia&69TwSm=C zq#+nxug|xg6(6@89|Df7dJlb({IgPu~8W-}}8-EF$tK#_iXB?HeC| zbairSDi(`ZYE{4A{jG2R-RU#ud;GxT^NvqWeC~6fo1dFsezbh__%RSrfZ7hi{`OmM z!c3xlNn=+&n;Dy#o`1NMSJZ*qV-*J;x3i~7U0G#M9KDn)=Ey@MYKo=_q0DU*^Q7L~ zkU!is#Xgf~_c&VbQ<42_OtdMZrgH}*XI8pWH58%reNHKfcehM|b!9N={%63OM;V6ss_yNv=b z5A4U73h~Cxr59d$`uO5$ZlK*;T6a2K#a#aEi4&Jzem0#>-@17-5{+-JZ-oQFcr;cj zl#P06C=m+G=b?*3fv){d{$S_Ci4&mhsvHOfo@mxOd{2n@0&6R)eIC3GJ~=a8Y19=> zg&}o1T^MKXpx|_S0D+JcItv^Oc$lR-ckVFlPB<8X5jMFdfCNbpC+B8)Wq9||60a*? z`RbP+K76?PVC7?%?}=w$zWreJ+@%YcMgQpP6?G_u0)cxU-^`Z|M5){AB+s3{fZ<3~ zE_S4%41YtOjgu2quR_ZAQTI0X70%aJg(CpkNV`iL}|KC^M4X+1a6O z8JhA8xW2BDZods9to=coq-EO>0H4F$j)fNo2M1=YHWjyl9qJDxx0A5w8ppJnHFnSw z=>Ql=i`(r2$yiwKlfYoWd^Q?QbGpD-0P<5R@XNE)o=bL z%+l)G^2EfHf6>eL2S54oo3Qp^5w2ai`oa3z*wh4!U)F{;9M8s6Dks)+rQiEM{`b}8 zN5A|FuWdeB$?xu@^>^`pMh><&XdD(duTYSRG9T zfK*+%as?*gw|?`t>Ww;#e|u;9PygRPPR0}P(WNIYJ@f2y!r;Gz{3u-na1*$W{rrAD zR|Z$*4A>%3f3;i-%%w@Y4HcGG6$#T(WUHo1is7}bb^;f4nHL8Fphg-ek#QD>13QMQ zJXr|C0HZecric^$Py6MWB~K11El%lXD2>^2+_bf_qG7Tc0E~u{OqUac;gPvxz%Hp^ zqS?*MLyIh^QeU*-Hc=uK-0lrVF{Ou7N?~tT;@RM-MXM#sbrhN&QPd``lWuQ%eQoFb z$b=;Cmul@yCfVc~Bbk({la&TOU5#Of3Rz32|{Cf5=iYp z8hQdKJYp~$m{}#G;~~E{&~7ShgLe^5wj*(^TsoPmbX$OcjPA~$z&4j7G92I=D@EPH zJDddAPgKIX&&h)UFo|R!oZIP?cgi-x+wAOb9OR<$*mEyEyR-7}|N77W`u5G`_ujd6 z{0kS7*`w`FZFT+j)Y)laXmNM~VA51Vz4+XdTZMyT=P$he`s;J!p>Xhmq73u(LZMvo zb1|#UzTPaK9*qT3epfPR4SLse`LT()t+gE6VRfgb+sMUpXBeK}-QQU}dHnjdYoHYt zOl>r3HivDqxYuRcCl`*1Twha$(U>=1*qa!i#%-=#f%*8xtynB16WTAlaLy&O6Y*%$ z8~k3iaqQ&c{=r6OHgWpm=Rmf=Cw})kKgdL5|KI=ppKO%%$@%$ifB(&Q?xj*=l5Bb7 zAAfZ6)On3^{r_CO2b3h&btRaQ5$U}z?_HN^SMAW~Zgj(u00F`Y1VFbk)R2-!Zbo}{ zXEi(L?986om9%?g#z>SXu1JC)M9=^r3ByKvw5#@A-utS|N^c`0!|i?XtBb9vgHx!^ zii-I0|NHmd_x>}Q&W8h9Z+9K9D?jWfb#Y@9aPPfitNf9Pj-(~qpDKC8^K41 zv7nO7Bjd7BmZxOI8Lh9ck^@qtRzq$#wOnaxYQkmEHK1saJW72orZ6tKw#`iNer}K5 za4NYNy}=y}W8C>5M5ZK|0js>v8*thjr9x3GW8YSwtfBhLrJPE&ge)+~N=8R*yWK+7 zTF6Cemuu840Q5O8mf0bALtWkK@*-%TT&r$mx7;3TL4Eb=RagPZWa_cUPWrc#;De)icfeDRAn?%e+0{{8>H5e^(a zcC;u~<6Ft4<@H1R4qRAUw3y6wjV+i2m^*+BOiMPKKX~9U{@L78-`l?n#wgYTFpT&8 z=>4C=Fxu4?h3x@&o?qF-yuJGRYxi#7*xXo)M(dt>>N6CKH@Ccd_t4DD%+W`W3=ZyI zPGruUJNwx26TkcW|2h$mFE1|jbao9642-W&_UzibwzhHh6neWIWvf>t*1XbbcbHs)*>1y2&=WgA)gRQu0*ARsG z-1(2&+8g^TeRcJXykK36C(>KVzTV#Y*4CmVm! zs(fVOGa2&f;sTW_C{e&+JRWCpGk&L^H>=PP4^AR#vLa#vg26BwA={QL+#73Y)M#LQ z#tinXm^i`i(0L)7Oj1~a&1n(1np9vRLO#Do&r2pA9F}7Tab}C)1Ep~}wR9dg8NGKO zFDHv)Hl48A%xfDfo;vEuHa95!Ju^Q)=XBXT?x0|`)HT#!yK)s{#0JB30H|)= zzx%ltUM!X?3kwV7Qe|Rn(#%_4dG6)?JqIp+dLgsA;0r};R{kHp{mooFp;QXP(YgZ% z4jejoGt;Kci(-tv$GSnWIVnFWim9h2kUbC_U*>@_7;vxR6|Bh zylZhWzO|LxJGj>_@R`J>Ns(_~xp3t0DX5uXFx1%CFg-Kw^#>Z7`h!9LM?bkH*Gw1B zU;T}*|HjzZUC5}e)D9m$D#3U)Kd76>q>}~Y6WXZ+T~^C>XJy$iU3H^&F89#a&N0=) zH6R!VU~1iBckCpbY}YU|eBciQFvDq9^*kDmlyX_6TG3S5W_R*7!DJD1lZ@TG4%9Sk zHdcfU!z)!P4Ur~@6Q1w$xy$7O>|Tr-#-77thQR?{2C0R{#OyaVHc}&WnX}ogJ8@VK z&J<*p7s28Xs3f-02%W%2r7RAhuBvmen*d0)k^vP_rLG5+SgVVO(t>oP}e7)OzdtysOf4Zo5UWACsrC7>Nevm z0e{Hiu>0(`Ql32jV0%A%|NV}(c8Ra}{K05LV~gG1($*FY#~=ZK_M10v4fYQUPEVmy zjny?|G8EkT!VAyyx;8a6^?SefdlxT!iuWBJ9)_}JaixsdfR^Ap47DxK7Ty{pr!nlg zdinD6U;OfBsRF72>ArgAlmFvS|Mc?pk=MTPMq^X`g^OnsTN}UiTVLD1@4(2&h$<^9 zOUtjk@(K_g+XkBIna@2-g}m=f#5dP5b(r2zxdggzxefY=TA2@)JJ2% znK^B7alY5uyRk6=!=S0L#pUwY$?HdjKcGoPQF42O!p=d_!$zztwSwuR%ppkRAl%4do6{e_ehG9T^TP7+XJFOtj=8@~yA9>{D`sz|3;_lwn zIkVV&>eQ+A_03SoR}u3)eeF_J#-_q{vN?>=D)O#@{%Wy&3l_&Pd)WSs+f{B{k?bJH|zYyMk2Ag*1CH?_UFZm7x4}hYopcj$2o+13~S%O`bOKWaoma}W`fyz^5*91c#Q2m$FgHbGjiF#6lY~{- z)4R*>^Yjl5jgOB4M;aPKzdZfn+}zCm{Ri6HdcOC)?>B~8JYLtqgTvTVpoDrMQRQ}RTSs1TP`)&=NR6%)-Ha>LS8CfXjyOP0WW{E6na!9zovI&dChBXiD7d~LR~50sS9m%CHCw!P zrve0))f(*wuck^s0*Bpd;q^ix+tb$x>WOiJThA}dbai%PLXFV+ipA?TYDiTfvdgpc z*vs>CbNIgh*draColb|lv9bB~?Ylqx=O2}el^0)lX*Ry%^tcuG5+0u0R63Z>Iz^QC*E<92UoeqpMMeq`n6GT+mxUcuW~YkSPC`99uirU*+72W&^z4pTb%&KcY(g=- zWX{ow5uCwD9=kcy`&7ZpLdCagL?WpB7WRcy)l3ePRj@d1Fp4!QZ3>9DTLq_6s@g+7 zx5ccL@+p!wY#cLnf`q-f8DCR%YKq|Z`!g8|c7(WNv;a{65@+PNLc!smMj6TqpxcPo zR`3ZBSyN4rEtki|k`5kL`uJO_Jj$6>Q#PJRZe=ncqb{#cHcnrGc>-_6V6eKN$k>XM z4DK{#GkK5-P3OFBpUq+wbW$vmsyN&(k2{>tq$#{Nlev5UPJ4F~lo~}3IAF=u#A@Zy zqbKHOmr|*;6*FcbGcjA0?%cW46syl9Q%X$+=l-#^@HB-;w zeHVZEfd=bRsy_MTlhgOc&iwM+?|uCn0C-sIKmF-Xzy9^#!Gk{i^wWR!+uy*`J33pg zj$C(nJvOHUfF1VwckkZ)_Wkc`&Gi_^{(}ep`Qu-%ZEjF8>s&tI^EWrQeDLA>j~v~P zg?sbO?+Uyfw>|dgsbl*O{P7?EF(9LV&(P}1O0>SNe`xT_ufOruKmM(e(XPPkJ9+8} zdf(A;4D9?b-rGuUZYHFrriRYWZs?HHA79DmD&c?)Lb0`#Fj}dXHPw9c?meH=YYP$* zs5?N&z8KVrhB<7a)GhM*?3_RGg1!?=kH6c=FyXA8sw!hkRmCzCFLu1HR5`T*0%*WEM;e%HjltNbj@P72=+Z>uCue463OQ+gVRLqB z`nSLK>mHl^mmmM4v%MAeLveF!{Q5{PnS%Joyq>1kmZOJ;zxmB?{!!i6mhN9U`sk^d zwRklL-Q|7y!&i(1SZy|;L$SlaRjg?x%CPzXDL zd8P;PpgS6$QAuV^v(P80R%QWvJEitmxW26DJ5tVRCc%gqHUG;pW)C0qliN=e$sehb z>NhNC$}AQ0CEfyHv#FdJI?-XZDQXQMPEGq1dnqk?-8O)h#~%QYI-nw_W-yY(#wPa6 z{L&(TB$dmO@4da5xH2OPGnqS_kEFxrW9lUSu=A%9(hN$LI6A zfMLta^VIa5f56lgDu>~6IY5AgxI$u3-tiD=SNVeLWw2d^(>m-M)3FrMU}tJ9q9}rBWE$JuopbQ7(xG z_Z`0S>6P`BbzBTqdg;=oJ%h9?7uGRQ!AD{c) z_rBNM8pd)fnx4+)J2|1Rf57f?ZftIjjZM7p(ux?4@0f|n92GN{+qR;sZn z3|kF%!$R!Yvj?i6tE=nUwQGYteKXVZb#--Mv3-4gtcYxH-|nI)Dwmol01^z001 zS4UT;-C?o1^E`VkU?R03tEsx?usNtWyrx=g_}m87gV6{5Zi~Q`as@%+iWQM}x)sQ*6Ua@K zrYrfP?6l9#&2{zmSX~ac4T8v6Z=qDq%ZeqFNf{n7E99FM3c$QmPzcXMEMP#ynnN%u zRn1bO?tSFTgk43H)J?V4Af~mNLOGQM$>oHOA!1`BFhPqezaKoz z>EHgz|MEwF^oLa?=?MgvR@PS6H=#ol=|oMV0}DtR=P`jNfY9&Wx0gF!eDf=>d~wgdz3Yih6L0Pchp=Rw-QC4}f$=(AIXZR+FI6mvM<01? z&z^nh%tqcQj)~cZM1u9QcFXB(L6Y^Z#>SFZ0s_@ktJ~|oKQ?LN_+q}sn;rEHby&w} zEQ~+I56!*3+cuN_P?=^Xi!55=;qxSR0so-Y*iIb&gTLC2zT-@qS|i^(rXEP?3d$toO#>A#mDvTn#pdz)VbQ0lk{JLQTo8t~9tu&VLhRslG0(%!$mYC0 z9~PIF>ABF|Vol=Alq}_RxfGqk&MDW{q&75$7Zw%@ML(v@<7uF@X}g`}Qtz}Y01|)? zL?XaNRjP>wfwp1~LdURRnnJ$9o7GCWMx2x{^Jc4H1*}r%UX!ZXT@IJip{v-js-H6& z9Vxoeo@$#Eu@vWAj*1SMg*3RSq*fuLC9&uY(9@0N%mVYuaYo~{bUHb__lvmy@e?Q4 z*4M|TrW;z?Jb@4>8h+Nz)VX0~5w6xr~b^|aUjr!b9 z$4f8$+Wq_Y=jRuW9z8laIT?#ZAS;)zTnGn!ef>j~s!|_qY>38|XJ_y>P!ZXD9x}SC zW7o$YUxZ+}RL$X{w5|H)mVrINci(+iRkZt~^W`hQ>vm#~&J#a#itWX4}!v+~G zm$3h8y0)#z9`>8=ggLYFQbZVxeZq=FNKU@Kt`3wESC)&E&SB;)4yUbF#adQC7Za&; zQ=|b_a3JJ|l&o*%`E+t{XlNsu2nPdYBm5IajKxG<471r36xZ}j#p$%lRKbdLJ$osL zEH#z@czQgzax=XQDamAVc#%*rV$3XVlkkUI6Y(5m&f^X`9B!`{njKWfDpQ9s()MN( zSc%1KxYUgL%eDv7xf3`GF}1MG&%jlaYs@`IjXR74OPF-PR6G=O3nhO2`t_c+J_r-^ zqol~MeBq6s{NyKxjvmJ+g>;@vY{kOCP&C49iT2j!P{8xd^Dmw`eGYsY&%ATzRwk9a zc_ZD^*;G+@3YyVP0R3Vyzi0Puo82NyHDKP+V~;J|zOQpaKAXLFV*~?$bF1vN_P4*CNM`_wZZB9$tR~j(-?TNNt` zbo$g1-k=bgoyS)KmP+ddJWTtL%AU`j@{Hm;)EH+0uoh?_(ZJn*S zVIr02=;%r-RbeNPdB@Xf-tJo`@927_*;!erGBw@V4uE2k$L1ZfO1F>%h2Y`DyJOtLNXewgJ|N)bTX00R?~HVAi(Qpt4#<*>s3MU zdfm$#E7$|D$2?JrRLV=0)s1ybD>gK2G@Hf+!V$pP`o?M`<^e5qQZ}`nB9&B;ZEjp? zGAjEqDWP~gYJTU2zP8!yg+e)>D}#V06BS9Mt!NQstHlm8mkt6rbG2mnF-+iTG*wmL zDV3M6mSw#nmf3ct>KK~LYKtb5m}K5!b+AJ$s#PtDoS<9m4n~Wor>A4F7&JaZZjaju zDb$55q&(Gnx!~6HHu5E;4QHR$JhFyY13sU3vIXz(E z39!|)$;hei?aeN)jNBY~^((JJf84lpXZOB+@y$(`l`!n?-nn<>^40#nJ@NPkHnXac zKcrNw$~AKMfCnEra%6CD5FiRF^~4iT0L7`|gez#XI`Lbo8SSt={`iw^t=$2C=s*AY z{~L*h3Z>%G%3@o4%i89$pxAkf06Y>NR`jNaN{TW`+HubBIHXt>IWwnr(9xiJ0;>_k zbUpMJL&_aN-(jLVxp-xx0EVWhCaRLWP2eC0nhA1m2?oQwiNlTueBz(=p>Tauvu?H5 zx3n!R&Na3)moi&khsECzn_FFuC%2$?SC?0MySn9aC1iI?vRW$V6aek|ir43i$2W2F zbULd@84QU@180=P$CjldCAYo4-VAFAHd8()0z@%3%-z}sbwa~Cfr(lyH825)AV-C% zs?>JHq|uR_R)d(TGN;JI7Q~7K{;H}}UV+mx?tS;~PvDIx3f}1fH;|!~H7Y)w$!_91K=++@-f3%V+rOXk z2)te|C)haNQmT|z@7x0P8rjDd)x>}P#aF@j#wVt8-%$FAQ_+%t+v zK~h;rhpb6_o~OnTAcal`c9L9FtCW6Gh&DCnD{A*Z_uS%Kb5rYNCXQVh&!ln{F(_7= zo15b+Yd*JUeRjcVcVu}%)kIRJg=}+kzJToeMFVUh4~DD3t4GwA|_a%L;Zlp_)e>n2$gi-Ltjj^4{AzLpXv$)va-Ggn@ z*=e1gnXA^6^~vdDhYrn5O?0)lf`aEW36I_7cRN4)@E7}@eW9+g0q;T;NuPXTb!i&f z>80QJ^3|(Xd%F9eBa_J_p8MKsufiND6^eTf?Emni)9HLEnaVocuAyDM3rmY!TMNcL zH8pj0X0fw#u&|nF@Os11esGUaBn->pZ~yM^u<(cX9~c1}>Fk2=t*&CUbd(JsFoJy> z1s=LWSl?K9;gwhZ%U}NG%*@Om|M4H=o{(2SsoUd&qVMk+NT%pi<;{FN{N zR$pI#RVoI8&aKoc2%vEsT{&~+3>H*y_$WFUR!g-aO3>r1*Mh~W)D$xi!lX+|jT$xK z7ou7gD{|RL6t>%}cJe)$4N_K9WJ`5Jr2h3)R(nS^3d#in{wg`=A)QnV7N`m-G&=2x zMX3Vm#KwYjmJ7vlu_PGf_1qpHu41>itOCq@)nW-+E#^vDP(s$NOga{;*DB@VfuZrS z>9+R65He3O?(OO$eJ$kz9`DTDtl)9#7E8IX2`JJ`oSE}4E#_6lv$T}K@RC-KB>AWr zLpp1E5Z(n$mla5uH4+J>^45)H4x~NW)PQj|HmQ*aAq1pa*DX-=5J8B(*H4VLv7tE- zh}^t!3#6^HqkAp2)iKaMy|fsOMF9H(&w;4QwX9gFX40FUP}FV{(uqy0-FoQYBaN|+ zdt;+jKHu5iWH#yLWa+U-k4)XWzk6`+Pk;K;iK+X4@CSbc_LkY&+_Ue{$c;O_Ege#Q z%lcNlrK3}@@-vI`O_W)MfH|~ubbsc#mtia)I=Tx&@R_HcJ#+p-AzSEZZoGZ@{9sq(?9|^nhxu}ia{k3C73r}Pf+t~My#F3pq0MdreVSuDH$|?5*_r{$nBt0VdWB- z2{bZi5ggmGS%S{PLZd3xOmPqp@&YJtgt24`mCYcx8GAcL#@5S2GV!7g2S#XvQlXGq zonA1N0@?y`<#5=wXV0EzpM5r4RyNnxOU1(K$_mCF3Q}cspNE3XaL=*PQ3qJB&9N{) zziZb3h^kv~*g5OQM%=<%pr)N}?^=9=Cx3%oQ83wM>~8Q&pnkrPE0rtmfV)yDh5hwC zJ$)N1^QriT*B4k>Ti^Al7fN|~VIGqJ-YHkbTeogS!r^qWG(0>Eiita7?O|Ml_yVfi z+uNI3+n#><>9p|$@-uI<;Sa&@{Jx-EGao*DcxG;CZGGj`smGR=m$3O^5@j~GZrr#5 zTMG6NFbG5zJGQ=_8t37*c+gW%Jq2!xC2nYmjgOBXI&=so+PP0oQ<sby;BrWf_yH+Ja@@d#_tau7~Z?Nv2p+Y{f34HSSMKcryqYJ8Q%oehKypR zSv^h0E-)c10tWX~mzN9W3P?rJ=f$+JXfL-Xu(q~-^vJ1q-+S-c$gQvc&No0FHa6BV z)zN5lePJ1|gr7GyH;XlK_x^pQYysLF8vwEe8Vv-+7^rmFYFt&!z_FV*M=%woa$$XK zqpPD`m8~_2ld4*GcP|*f#cJN#igUbj>cmNGp(V!>_U+ic`=C87EiI|U*6^W&!oy6| z^iYl{vo19<*Lm&%n>2)2V^X-|jbedzKztV0$NU47l5eqTM)%u?<4$&t>{*-uJ?lXb z6~kA%BS3Yb3l*_aG&(n1gF$NhUa7d5hs)>#0Tr$*YOPSrR5eBBbhF(G5wA0nS20b* zI~`6eBv6hjpiA^DO3$hlOeWAl8F%7&&KN%j;%&F{`K(kb<~2;Ag*Ti>vPA&H#QUlh z?2jr{K!KQ2%`m}KrV^gpJvU%O0^qUs7cN}DIP=*|O%m-kOTgzbgUq_um|9?Z#Zff+XL5 zDuWGRvpPx@8YRv!ga|L6boe>U%;BF@Zh#Qc3gN3g(yCr@FhFnWIe z^Pm6bZ~i70qNk^a#pNVY>1)?Vn3FiZxk9dGTX0w3&^Q17TLZiH_x5$-{WIC*&6_tU ztg$L$Ut#j`=P=lpS5|!CP+wnPYI6%9{n%rVz5e>^moHxigM_Zfm}8MTiqD4Qj+uIMMQpG}1^!g}37AqsxN*0N`a``f_bNA2?BqtG%I~|U;)>enz zJ~cWf>~s{-9|~J$KKz=I=wt%MYJ@jb*D4TDMT#;6I6qt%f}~XoF&l_kQOxnlrLQP>z9EqDzL7W^?ng|72D&$PMOeM#>e*Bs`(Rj)CDa#7zELBhxs6iVT zPuU27$NjxFd$ggEIxS_hfDn((h0h}~$a|hun#P)0QZ`-{Ib)b+5D-eaCpLjkd>((b zQYK3g;WvzmeAcPp1oM(jET{@Dn*ZPWmgVq5Vc3<3a5b6dCDVW$RV z)U`|nV8!AY&-7az}A3Sz~Ed=vd;7ZIbMujcP zY+oSU-~HX+LHQ024pNEJav7kD?~rm_%zCX*L&Sj|n0EX39fXn8+}hIK(R}&JwF8Ha z0DLOd3g}#Ov|f>AT)c1JzQN(WYX({$KYqNwzyIF7d!Kyr3Dyz&!En0qRF}`|>F(|* z=Cd}N<@29^@%?w-Ywzr?N)?SWC)3$tSxjstO=dyWO?GU4LlTPRO0`U}4mYolfMMG~ z;aN}!+k8;o+=Ebjmd&H+8jC?T*2Cs-Idw^9M^Fq7w*^!XV0&A(Ehv@wQ<)#QW^CDq z1NnB`t5%~nv|#2jCfH2Iv6~`M#BD~FM338Pl=F1ds#Pqo$754ujUBRs6kv>YyA?dr zrjQkBYy&F>2$`lpPf6BmRH@M6ba{P#3TlxmZm$dfQQFaia+bK8L5OvwrdoN$W)WZt zQaNtk>@+gDbkNb739Lug$QhSO=Vj_f%>xrXg+xO@ISxvqt&$yXyMKEc);tMn_rd`lT;|Z{K~7Pd@++qfE&I3 z;wz^=xaf3H!KreI1PGc1dkiq#-QDSNy5?tQ6Y(w3(`=4{xWDw3-+cdP@3G`3%skYH z#Z0Y~G0~71P(8dapbl(rb#--pef`v_Q_KtY=%bHbyLPRZ%N{s*@Y6FNf&dirCZ8{q z$!vXc=CnT;1e#(Kiy}CHJGmJrAGxkW*0DyAY}jFLoAZe$o&aNJH7Icbh5;1&_@ndT zu)ka>H8w;mrJTz}_Q3G);i_C&-&}XPT=Vh9D;wR8u(cZN8?cd7 zS=rUw*VNJ^?3^u88*q)R8zxCi-CImpK@H@LCE5d}1pBt$XYCo-q>x1N0!OmQt0vh* zdXxe^L8l-9J7M_@s#(6MO{0#@q~F0eHC+;^x+K**uU0X|I%Ny#QdJhqRba1~!(PgZ zVug&E8hB%osxJv(6ntGI#(aT8j)FeyNcmgpb8Om%qT#$IapP7 zp0C10V6L=uCP|qsHbJIQ*NplZ93)#7%`m)-kZn^gt7vK&YtNgl=@ezFc|HD0r3xW{ zWnjenRpOhgkSCb+Ubm}|uMt%1Dnx&IVVM`e9n3BmO-`4iRwkRt z#s+lygSb{Khc62~vV7bDJi?FdG{t%WG!iw()4jcd( z#cW^eTRNeAme%HcAy2+k?CR>dHgcn-wKtu)Q&(RX z3el|~HW;&Rr1#*jdUo|akWtV=oe0;CjPBU@R2jdfD-Yn%W<(h?e$B%5S;yu7p~xt6 zsp1;5!0otQ8DO)Jj+zO=|Eq%KwEqm(m2L*`1DjMxs-~K&73%NdcG*j%9AmK+I+Rj? zpl&xMRW`OXvjZ?v-zLiIfb>ERm{mkBwQ9La!7CJ)!to}lqToLnG*;2onn|ZX5aufP8FuRnU?vAg%~9XoR5+T~CG_Amc@c#wE% zBA#q*ZG(~xMRzYQFX|>URJqZcDF=EmGde+Mf%*Kt{rf>1j-NcaG`BD^GP1I=0_&cV zt~icWCw>0;7tUWeok(nUb~NK$9R?xDR{;?9m;@y(3O zVQX$|f?TdHuLOMlx@c^EcJA)&JM(Kx0xkkMkabR0^r~#AU@Mfqpi2c3DUMP!9TeH? zCY34)MY+Uq3)ViaR%K1Mn#lZcK;}#}h0gNHjy6M+yP=?qQh`d*P{=OCU4sZfz-3Xd zO61{Z5l@;-ttvRfMUcjQ7@DgDOZrHBBjKcd7B0+QxZ#6 z&g*rTYbGksWOq4Tkiv?j*CI}#R8f=ZVnc)fNMAPv9cS`h*aR_3=v!EtES0mc?;r$F z_jbE`ae2(^hwWc06r`rcHm}Q*OcbXk7x5SM%^hbiTqsCNbMLOj_4StK$ZD}PI&x8$ ziXF|dP|#D?Sf5CzzW?JNKMsy4rKe{Sh9{DzBTLeSvjSaTv^j4 zDYunMZYD6jM}`lVpmGvLY)ELnY9SYPxkm2YRrl_*goB%_OEBYLci$Tu-MxQ!@812N zj@-OIdF|NaM>R#uW~xn*j*vTC&g6glkAC+*{D(hVTwLngw>vND4o`#49=d+{=1^b1 z*Fp@fR4ayB8youvp8fK#`-0(*uiWdci@o%PuM8bNdglC@(ea5#hKCbtt7=914eMbTw7du^3-SgyY{^E-4AyU4R1}4N-ZkTK?nd18d{;EpoZZs;Xj|t28_e!cxS97b@C%$s$gW{8b_ci z)G3wnpl(DOCziK+`9J~Ek4z!g6$6{edtlb>YRz1wv-=|LH;wien2RjcSgIh%Zprv! z?W2m-G6jWL%vOz)YbvAE)UD9rVEtd9@-Q8_JhkF&Ym10g1!MGhWOmL@q{3mvW!O|e z0z3k+L~X!XfQc--oF1_EGGTDp8WVTk zy?ZxQ2k0ZNr{ix}hozF!?f^@h7$1evH+ugrM%p`Y6d<>>wDRn;&#D@kwjX}{@#5mL z#jftzJ&3_WtphT5b#?(V?~jii?`)%{_Ivggie>y3%=rEH->14!A}+w|ltR5@q#d%$Z# z42&#>0@eakkxb^8H`C1PL8>Yp@Ohd9t3cjtlabQS>Aa>f|0s`%CO7rAsZKs`orIMK zNn*|>kW9dtLMA!v^jcYDGAiN&o5{wR9Tuy}%$sG+0cuA~0J@6hIq8%XCD;Yk@Kq59 z5PlUK1yaJCU#u%3a|qxXr!C+FxY^t_Nj07#!s4UUC2I&e+^7>)HUv%uiKcu(l@8L? z8hPWHGhy2{FICJ`mI%y5mpRtxhZ_8`<5}j2Q4}KIFq*J7^9!p~QWyML({s73v8ilO zFpzjmE|qsQSPY=h0)c^YfEq z;|`n6@AYDNHrI`wkv5wU40d;RUcP=E_r${E{>5TG6b{_GJBs_m;(-(%IdTM|9FD|p z+_=H|&<(V8%uG%l*tfr}xdrSaS{IAf*V*j$si`Rp3@{Iaku^WTJlwy3zw7Zw7N=)l zeD!c$UCU;Cy}PS!dES2U+EoY;v?d-3>e<`ZkL8dm5^nOu<4;1=M#rbAB)3xg`~Uvm zUi;FQu^!`h?q%}1M@}4-4SOFn29%&B)-baXuhhi0uFkjK{OKgBvW-<-OifbFMu}5GJw_2=#h4V6 zCh%6lD1pXq1+~r+i5OpIptX|}WjM1eKx;siZqlqa-c|$Q1l(#$)xwA`EUKDZ(I9x7 zZss+Qo$}?W*HEb>8rGPiv-nq=N+|=9j62b36ZQQ7vXY}J5&=MhQ{ttu%k6fueDM^6 z^JqrP07^2kQ$wQ)>mtrvk~(+~no z6tH%1pzqqvJ1h>rqobp}y)zPa{y%^5XS}Kd-Kjo2^p-_Pq>>H&bWjZ9yQ_cj(v{1= zEtuh-Ub+0q2WMhIs8Kx}@qc*w=b7X>aOuNey!+*6Us+sT6HO{>dx4H{d_~$Prmpsg6fAk68-E z{0nn)O#!^6+q9XaL;0F$w?LCyVzEdq0d+1ya!Ta_sJ7efibTkp>9RY8Y&yLYC(k`d zem9~=y$=HLdCFckVSy=snJOljEGEihmcaZJwOW(4azzh@1000|f*+VnoVFudU_2~L zTCmxm{~Z+U4%>ydcr8}L0P{c$zj%U`lh0&X$~?>5V75Q&SH|QIW22zy3Q=U3+qy|% z&aYCjsw-)g&V?YLWkr>!c8^BkFI6f>vh9eaubRY;!JG~coe)&YkZ+5{M%ziJASOJH z<=h!3q5|7I)J5DAfOe*wZOZGfna!l@OXVC()$oydqUVilp$yA1pD-Rq3$EB7GHTmR|Phmq>rEZH;#aSh>B8UJuoSU z-R019I*7|;Q&=j-!zgf5F-}cE7X%~4RHt6kq{n3wNCV-hjod?arvn<=>GLQi$!_%0 zh55`J_=4d^UsX;!=s z3{jbRKw;BEKoyG1Rt=}DPL2bhsA?m_jt2rlfB606`qp$M5b#0aQw;)>W;AwkV{DiT z<4}Ww?x3{yGqaez5 z!yP;b^dMH(P#5t*;P9Hu3yZXOjl)u`*xcM)v0SP*%3gpN+`D(r#PJ}S%+C!D&1Lf{ zXUdlgqa&XJ--mYX+E`lJ-8-;2K0!d|cJJD?3!ux2^<6r9{?#{L9~c+}XBZzF17m53 z#DM6X&CU1(8lzaH#z`0(Ms@b=S=dZpYlwEYcl_*!KgQEBa*LUR#;z1oj+XjjDPPyr z=?evTswiFYIP8f;Tr<02LgOY7Du3)st|jd@RSN7g!0=U^$XTP=1VqrlTAW)7;^0@-$3IQhYO{kFs3M#(=G zj%wvFsAFh}jrg>pKbU7VXsZEZo|Kq2tk!NEb+hYolwaKg&s5^xlF8&7OtN?Kc6j~zWs*-Kkn zhYt;Za{iLT>9*QKM-T72bARUi*>f=2uuctiG0674(NXZ0ruqg7m-cx6{vW^n#FJ0g zH8x-~w6?aNId|5sa$UQJtS%d9&d|U>CcYK(N0#RoFyM5)fJa~_Jonslp+M;J#mlgS zz=oX;_ottJ3XSD)x>8$l2mq&2HRo(0Z}&K09j>goi&H=-I1k;^frW%E}_{K&`Co_SV+ULUv1VSl!0a z&^DdgDR(cbtS|%&k17?KQ>s#pxd8L!GRIog8|U)i22R-Vg<{(2a5;1z&tmpKLrq{i zW(Q0rszahMvlpmJ{G?j-2iY z!5+;QeMUr&1PJi?Y#{f!T!JFj?5@s^E}O-AbLtkhiO=o91_f^bXkGsF)7M{rJ(W!Q zyxv4S&X(hqS6+eiE-uZkt}dt2Nhfau%6{;{2LKp|HPEr8t-V^Sz4OkG)~Cl$Ja&vi zW3w5&1^9r^Pf-LfKl2QR_w>_G@7}X-a%Q@vwVlP3+_-xEwO{`dR1h?*-|P9WfBqN$ z{@?zuXC|f&9Nx2)$tL4*+-hK8U}|CtsPe`eZ>(-?4h`+Oc=000;>3gvlUQG0=kd6^ zy1ZkP6PV8!47io+1Kr(^KKiI8*0wg*XD6l$nS3l1P9^1q*|Ab3QOu|DA`}V~-4X3QS5^Q(AId8{rgmdIXr$HG%xq zF5Swh7S87J(q#eS$Y5vzpA`y@9qW^wEj!CK&T8iEUYjD95?g8f7M6!%2^Xa@Hml2Q z)fFf!vV{CzpINTL3=y!)9rl{rDOO6@VOEE=VyDDY) zUmufe>g>$I%*5=K8y`ON!V{M-*?#%aN3et(R-)sbJ+1kLvd!Ttl&e4e@wh42ZGffS>#mu!K!dNbq4|+hr~Ll#u_vFuaclIQAN{nV^KCtq zg_-MLdF^w4SIDI*c%`-N87pNX9jTJpONT#n{sR!TP|9dcRv0A(co;EJ5Eoextdz)Mw1&ZV zYRKns!Cql;Cm_@iS|e2)+(3tp6RUKNY`BC>HJRK&#ggKt0wGYNijiI-xSU?n>?&8K zdfq^Hhh&$knn+DT%qEMKV>^e1th00W2cdwJlBFs&qY5~0G@8*QRbofA+C!Bn)d!s* zAO7c#+eqN8Dz6)!U31N59LgI{;RKV_BHQh*x>(G}&DSYnw3w+$Cb6P|c=Kj5upo`` z#Cklj3U-*79-vO_EJl%VR3nVdSdeNr#};l#NK}UhYN*d zdwV;c%Tm!{q+?Xj^<0^6@9YRiBd5;0Sm`rkSnk*3D>uYK)b9o%~; z8mT{X;nVKE{@?lP*WP>cAJ~~QZ~+iY30Q{h3!wxzW%*mII3`AmXZ7`V;r-KFNhrvn z-d(3op2W}4!RJ2uc0*&^%*x;auWYd}P(Xm84)78}r)iF0e0~)S# zrpp&D;cgzI_43@}(pSIw)$!>mhsTLonwy@lkHw&Kusy(8A#n5a6VT&;e~@NSd5omL zzn{fY#nV)Fw5zKNbQZ!hIXO8rGz9ox-rNv&7D;=kUO0Ke%~Yy}ts+I7kjGCoaz-hE zlSR|m45Npc@X+K;0`OH8B_n$o>X?qND2blbs?0!_TuUaZQ(|}wU`k7nGq2ar`awdU zI;?iyA%M$jHOgjEjSNh&yq#joV*gnthOsLwz%X!H%8L=m&Lc9+nI7h{JHcEm4nccR zAnoB(Ukh(D>Wq?0%i%DZ@M@G2=x}+;C0SD`WR`Y_T;&BYTG8+G+ifnBi8%-O`i3ac zQ!`Y8YbrJQ+_TT#x;}FE_MN;DRixD9=H4C*AP|X}c!$lt5d|@Aj2+oOxVe=e%vf1r zt*-%oc(1*C_qOipdHYB2OwBJodg3un=i{ktJiX})`xfUnhx+=Z>gCDFDKZ9YWv7e( z$xpuz)l!kFIU~IrDnn9a-b&SaK@&$uM_G(4!~$z)R2<5rE?uXz`9eudr_~hjA6G#1_px^FF z$5V2pCPaj;u8t?4esXMP0unYgF;O3_-?Mk9zM*c$AOpTY_=Oj~@WCe|n0f3LO6oFN zEnrj_9=<~;!7je_t#4spH8eEf=@{qe)hhxJ6#r4>8x3ra))_34>?gAk52Q#&in#!F zN^NW?x|s!JRDeW+Kt2MhTx@h4Wo~do7=UfMQ7g()$YohTZn;=s5q+2}2!dFVjFb~I zHD@$ptf8PQ<*L=@BHgWVHrQ5zMKxFCYE`V3#nQGsF<#4D5Jm`sfxo2BS@~LU0P>Wv zO5rS{jR`3KpmB=!pj8_CVuGu(pnMg}N<0+;L&yEH*&;YfMM#Cif2XefD$DLM}m{fPa9ZTeogu%)58*wgfy5mun3uVzo3hHbdV{Ok+{h7oLCZ z```I)EZQ6ikk;O}f6!((#WSgvP$Q5M$N+4sR4K}_vAN0Z^{|Q(SU7+aGmG)=xYA{| zD3xkDz6F2`*F{}EucWK_^wyvJhyQr_{Kd7|h1<7Anxes<|M&+jEseoQP_fz<=H?-z z0e>`;&vkcq`vU${I$cfV>Z0}Soo#Nv@9y}$E7vaPi+PvdQ`y`YJT(9tt5nL#is*E? zZr!>2^k@H_&C>{&zkmNe2D7@ldiCm6ObcWYLIp~C?bFks^t6;-_W{!YO*S5Rl5YTZjT&Sr4 zojg?~fn}K*(W5%K-Kp9qXO_VnC>(^-AcD+|Unu6oR%fk>>5_oUkWmw$S1i>CCY{XL z$%3s|j2~tC%RGg_Z~~on8To)ltP{r$RGD9lZ5{^0JAr~b$hsYWOl5K>2w$hftvaXCh3mOS2adq*$s zj6bnEZTUjM8+0$MtOKWV`66edtb-r@=trSw$i|ym+Bzo3#^USi_&7oZ6Qs5EKB1y?alELQp%<`_t3Y#^JNJzkNUCH6D+{U;+Wa57@VOR)|x{*-MK}ebyClQ|wxT zRg*5l4pwCi>t)hvN{yZUKt{9Kg24-2teeMnkZ7%D(t*NO<3HR+hq(s*NUb{^ZnyJS z?Mhgmci6HPyJ%zxIgEDpSz0ZFVuGv^I?6x<5wK>~VGmgZlg(tcGA|WtV7?PE&06sq zWo|ViDpV$cC9vEc7&{N!E~vH*^S}Dq;W@Zo*BQ?-8Hc~n61>AOv!aSlo73&_6be+FqExDMckde?n`XedFgF+UQ-PMcNK{jZR2<$vG&?m4m2>dG zVVZ=pXcBBw^W(`(8cPMC!OgMuENBR5+TPs_`>B{o=WTW<&&%h}LzTn)KX>kvFMa8Y z_wU@kd-M8ZCyxUtnwwhhj*S*dMV&fEf*$iVMP@&&tgXh267ET{r3NSL>v*$K~8uTdwcznBI!}>ccpIL3(|s65;4Yl3XZs63|@tD-8x#!-q}sRBd9Y7LfBS?5%{Q_$3^fy9a?QW1P6?#W)3APQq`~QwA4;4m z#!IzAO|JNDZps76=kdB`&cJP<0-9*Uh%1zpkDDJkeEjz9+f6Nf5Od56<++E#Z7r=g zZ``0XruL@!@zITy#dKTy=2mKHZ5;xY%M}`8eppBt72pIL73e~=H4vy|iVgc>)vg}w zp&Qq(_Vo4iwzlY!c;Mh(XqTz!F$2zppa1N`=U#l?H!4n|Uj5aRC{ZmX_Xq_g!#S(2s)$53&`>K!t|G7#q|G$PeTd1BUi5 zLh$qlU6k1A4rm;+NJM#?U+S8PRSdQ08nio12W)yQ7^D+h0q@Vsen1S2LOX;_Oh&1+ zCndsF7;#i(Raeaxv)%3R0Ub+PoHeyzrvR9D3zZplniUWLUa48c646r%d1DaB zJ*dpX#=|J4s_0cfzD%c-HgYov(90BbB5xOrW;rd)G~9Vp^+8+I9UET|Y%KViPJJsn zOAQ4NF>$hLRH-6PB0>q2&7jJ39t*2ov08<4rDU@@1>Qb1xcBCbdw#DMO3Lf@T$-8f z>ga^TFawrTq%XhmYBH0bm>3gPQ?5{9z9&cqtEJCEJYh6MA`vW4UwiM?W<0*S-qY7x zt5m=pBLP3KVr6w<{9X>~736qjd9A*_G2jn>{LOE@^5XLxSiV&C`h5^M*g#azIvkQr zcC0$k1hB-E74wZuFU`9gPM?vh2=oHu#vtp$QH$AETwfWzG(9}nkMTrXT1Rf)nV4I6 z=J*M)YFJCq#b5c#7w(NuJA97z&JKULHJ?uLy1G0^L0E?m9;%fJHLhC7mxl%i7iMQW zdONXIp8Nc(@4k2X!0=HB54a5^r=_JuHR>gT+Wz7fzvvqpU`Ik!Hz1#<;>y`9m_Tz! z3m7G5vIsn96-AYU*&!3*!w>0XhO)>FrzsIKRhD3B%bMNIYYLVspUR}ug|w(td7Uq1 zD^*FR>%CqEjm!k6Lj?^4Vp~Lr8cGr@CX35qE^%VnB$e_N@*dR6r6P-GiAY~S8^qDU5-A+@aA35x(U zR6*6_u>ohvmbcl-^=qYO51C9AaESRyCbnEotJfPTl?qfEN!5+a8FQ?@{@&>L>u-Fi ze^0-pNfj;I*3)q7=3UMq^b8J}t?s9ue(5{k`5rjTv7_~E9i6SMZQ$7om4Pe(K}R=N z(wPKygqhkWG&VQ42)uP|b)$Q52uoEJOrs0a-e@4!+OUy|uWzg#Kk)QaO7yux4o4=j zmD#udP*bF-IoR;dJ3n~gg_mw#8wt7ny^nQ^o8_XU*mY}CFC02_2ye~0tgzUf_V#v= zKU*C+XYez0E0tXh1j=GX_3)C%dv7J7nCh9^UP|G2!mRzh~rAT-1vW=b7>^jB&`G;CcGo0RrSlw(qlpLlGqHqo>t)I%^HKCvZLRetT$;Tgm413wg9s$EH zV9A@B8thh=RF-;rx=Q(#jd;RpwRg0(;SNxdA#W?RZtt+Gdw*rnJ?t<#MZWEJZ0p@HCFsvxm~_+`ivxs@4xrn zVDEq^%0YidF%K3ld&mZEkMP zBvTb^Y*jsUcprrVhQpvDflxS^NK8-9zVPD9*G8^y%+o>C=H~kS(Yx*Kt$X+GxqSJu zU@`YKhtjFSlTUm$lcgTv6|t~?c=wNg`p#pAA8%}I#GgRpV^JWlY>i}D?`Uhke{W)8 zeraG=e^o3`jE?p8_L@AdU-h(QQpHx3tqn{1Vd0xhz0#p6IU}p!cQ9(`?A>9fa`!eH zWRy9EnCP&YiA?TyxZ}eTW`rFVlQ0{n_b|jDar_BGdNbke8y!oL{5=PFxiE$f>k2EBnQ37V|F$7X6>p%^K0u&^r z>Q*~72whoQ^9RH8^YcIX$xoV^S}4+>Dnn!;K(}t+R3y#og3JxQ{r3M))_Xw7b)9E| zRWH=5dX+%ktQ= zXi1c0i=>!95(J4vgbo0@(db6!T-}v(u2*lr|K08)JX@y^PNBNG>b-ma`~BaaZ`9P) z+1)NtHYT*vOj-h+Dw~{*4RVzy)7IARa9CGX7s8R9FMs8QY(Xu>lGSxhPETDhN`-P?Px^$@FQ zU;#xODk#~KHr8i*dm9%Ch5ph@FAeneT)grbZBtg)-qzF9*g7(NVENuO43)t8sQ{GqdvsiJ!iE%jP&#Rtq?dSY*%-NYTK+0E=#7JvVkDbN7~Oy!F|1^7@UdwKX1- zEEJVgXe%aEY={abF(E7M4ZW;n!tYLm(Ts1|Vi6^fF(Wt-Q=_6*lf-gQEBucYH#1q{!jg5A%jYuMyha+7tm10e@D#j_m-M@NA$yt8Octq mK;ii3&r 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%0AYh)GCDu<^*q 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%0AEomQEU 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

    ygoP<}>=Qt&>=+%8 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Ξ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%0Dq-k*4i)+>SvQ*Y)P#` zUu+@da?IN0t~f{c$hB3NTSdf=aj+I4f6mTIcFd5ApYWu6#Bt^4B}1yhgQh5|Y+w0| z8uM!Gs2KRzXES_D~76$trRzRLBz= zpI&3nNd#h(fCer&&3WZku=>q3T>pM6MSOZ-97#po85G`V4M6e&$Ol(&sY;`T{&=;E zNn?9)^G1>0-%u6$8KzW%PsG@Cz&sHEke(JE_jcs@PwvYgo1gT<22)oG^T6Kk>62;T z)bLPd4^d)00Uj?Ez~zKj^S9tc)1?iR*1lci?&+4|ikQDGz}qDz@?nQg(yFPYn0dW-QUY5slPd?1 zV{60@&40V<*QgTnxppj4VT&UdE_4JC-QdPBkuUfSjtCqglRG=?I{=(e#Zu@fC0z0? zJs+hh^A(Mu9U)t0lwf`w-X-W=W9xKe7HU3Su8z{T$PW$4T!EJVS=R-i*gu5%`&Cfc z_Q@^}Ke5U-q_3f2@l;W&=C_RGdfklb`!n*mm?AI+rBLfqOr1pej4&+rqr*3~-x$~! zku4=JAN`$q`}L@RxhvzUur(A%2qmhCdBQnQ+2jx8OX-@`(VD%(%}{Y{14PBni1UX! z8_KP1OR!M+s)&5ysj)a_liIJFo|O6yJODIj&4&zx@-1`>GxAFF?K-0YH4`306x6z1 z6(A0$+qMouI5y=NY7dJ|*N#Us<kU7dNdaDVe_B;CgFi%~Cy ztI<)-OKr`c2dsV!d1Y0ZNxM+}6O$Lhl{_%h?mt98STz$F#^3C5!>;?xf?tDnTzR*I zDyf&r+i!Uvz%iK0b&k$Y)$?^1LR|JH1au7IoW>PpWc6t75G!_5`(U)eVcrhTSI}Y= z?cSKI>IUtb`!K`dsN`#ay_+$YXK(9lyHZfPLb*bHy8wpYZ~?*jqy;QD&=Xt)dkGCvG`rW|>q+aH6_bp|k0P%eeS&6L3N$e@dTs`0KUrm|Q1 zYKI|cn?jDrS&kVzO}R=rXh4)q(^U2xozz|;G{w>9-<$^VfMk-_LuD&O8(p#FQMHCm=~m9{|&;G>|jv5>lXP-VmKmmkAe z@?FUa#6~lQD-b4-%y(k{#GMsXo(d61WETl0%r2j3ei)Tm?RmR8EPn@98%nG2*7uF{ z>9G3xaf%o#fyvn7rrxaA-nleW@GM$y#T=+x?mdkM|c(nGu< z;^nGLmV}!tezWIe84j?#uXfvB0ma-a36H4cLzLXvxY=4yZVo8ND&d=ImgCUQ6pQh& zGlnHoS4Dky%_qTKheI4(l-;V*Q~xuM>{+w2@}mIx5mIMoc-0&lu@%+UrKG`+;)AV5 z{RD5l!2)ji=!%j{W~PEJdZ=l+;;!{%^wO_(bIPoQ!~R(aY{(z-%;Rh2x;j=S20xlq z#{<^}clj0mf?k&|KU5;o#{IEzLazWPOB(q1pU8+_8DKtT7=U}G(;K_Ftr%-X`HdeM z_QQy`3~rkSCd67ltZPXkTz(ED3lF1>EY}fuu8z*q$o^0K5S#Yzbo{w>*Z>CwPEc1bn}K>y`A^}Y=?$N zRY8nF1k|9pgyp)>D0Y*jySfU?S~y>$g;$#p?u!rTk%HkHBHfNe*KtnXvAlZoRAw_q z6U4{z^8T_nN)$(>*>~8Q0)?6VwBD;Ca$xSs{{L7wU$l&`OjMNr>wdPpN=!SL5 ztZazuNSZNArmJH_U=iP>i|PYUe@iW~T6p*;%Qar1r`$X2E|htbgR0bPZu^fdNz?@Y zKH^JnhxUzwEhWvpH08FntuB6eR$zIKtWSDN&sb5D<4G=OK9>xVNDMqc zvmid8MlE-V$aVHJ5G!>+qEfU;vcxwne{)#%@z6W^c#JBjS)wD>^`F-`H+9vqR@K%;4?)rn%JD=hpJ;ujdCkyQ^@ieb<1@a3HOGIKG1OHfb z5b1p-|IU#MKb4PV$);9SjXW{N^Ub2Lv3mM*9xe<4Fq?aEr3qM)Du1^BZstjKXu>6v zmfw|>bwTTNqFWqjzj#W`izq#2igt?E?k2mQ`3k2}Y~5I>b=0*8PGm9*9oJ0jGzY{% zT-zj{xhIa1EzvVaB$DcccwiLyNg)&|c5K!|ji~&b^44Y9F{He<6=J39u}*T0^BLjs z(!=AF$DttePOgv>zccNwgwCp6IR)=;jaFhCP#cK}hzw0D`{Gg=Q)9y*2rPpuA{pL| z)lW{Il)C`%X9deBvuYZJ8gm(5vZR<^Ze0|x8!2&8HLviBfuS7hAM239G1Z#REeSD7 zO^bMGB%dg!+vu~?r_j1P4F-)$vI$~7NH8fb1m{~YO~3LA-p`6APa5ZL*(!R{_mhm$ z`433Fr5_-Juo7q>R2`~2dEGZB0V*D@778gB zY?lVdf`UyOh^GM5PO)Jzc48&iGf>P=0xUHJT6_#dxETCD=WJbVo z^iopHg~Z|68l@7;KN-V#zq3~;!$HO6Ov}U%HC`@IMbH0%`=4FLO1~D&`MWU<99sMu z+Dwsp6UM5A^0x#u`4XagAa;8Pdm}m*)cmGPhwuNBUHPZ&pq?KJ*MBf=gAr-AI0=9DDI9yP<~l?Z?B$yq#``7QiW^in%BDf*BTM{6 z*ofC#v7^Z?6tJCX*qSkn;Y=+^tV6-$M2RQNbRRtz%Ee=Qeh? zMSvqYt$c~dTOd(Y$3iSzSUy^>`U9himM!ht&Un3bB)*5i2F!Z7_wJxxZg@o`(chS| zq6Te#iwE^ehi)A$dUpO^PJ+vl$6xqzaDSp%|B)?;iadsu_d$gR4(Fngn?jDMTIPjr zlazr*6WkKu6dM{SI{Yv}vg!+L$3+=^t7d-fmt0FvHz=x*W;_M5!0+mb46A4pCxjRX z(kW(D$F$kgNS6I6BJqT97$9ZB8K%Z}4?u|48+RtzTW@dK$VQQ0!Fwo=FMthY$Nw4A zfos7UYtHs}7Ju++qii#jSn_eRSH*HCKCL_V!Lv4kOvK65Im~{e(=M-kpMEqIgit`V zjpK=3D&N`E!l@v%MZUjo^}{S@Z#_F)XN8a{>p(2$Jg}l*o&jzzl9k@GueZZq$|T^O z8;?VcMEB-i($NDg9c2a)Mk1c6IC3x#)5_rTwO8R73lSUX#y{5VKUHc@l{)`5J*AiB zuo?c)#Qze5E9SL}v-Lil+>`MF7k2M>tDM~_EA1CCU?YT>ZDM^mm!I=D&A?$kkf##= zy~PyS0P{m2-Zy3d0H{Rrqy5S6OW^k1j&DkuC9j5DIzv#?T_o^9ECq;ijdY?hMZuEP zysRY??!|JFMVX}=8$_9;E!@hJcx+$#5#heKMJcNI2C`}7SC>ROs zH~9b2W|Iywl(~-{bC9W|q;4nbkaNgUs%016Sl8!+WahQX%5P&<-nW_;G=V|MkVI;rl1N732%u-m@&`J+R!Q=Niq4Ej+2vyz z)0szP$T%fQ`yQx7hO*R^tfamEu}h%SnOde2%MIU~>g?(h8j;(H1gJ>02mc=NBVF>% zy1Tu7;*;2g_wc~oaR&}tENWKS=>3N2v;_n`;<%)Vp|ukGcQ@=*YfQN*yw~Q|CU5<^ zVNxk^7=vUIqZqczG6rGUMUm(iwrv3a2|@#l+7IVT)7N%(1|;!92U4yRyUC`H>QLb9p60d7{ay<+SY^~HX%6m zkN?7a+LnTVxzsBaOyYx8fthFh-sW9Qs#j&z1}sh-D$j;?{6Xo0Vdf&%n4^ef+jmj& z(Eo67acx4!Tox{DdbVdS_Q;bRDM?;YFCI};t?}X-tb2z__3?vodthn2CX*H`xv@zN z+4oE~MFo5q*y~>ksmsVD+(G@Mxqy>3DtiJ1PW9-9M_>O_=7bCxvzMKih|IsQ{``%!{Z^qbY~h~jW?hU#TwM1=%J}t9 z7IM|bRwAD=Uu6VG-Jg5IX1Be2>$HqpNy=1cs5L+Q$g+XncPW=cEF}$0xp<}`j5c= z!p@qwjHwQWu^{uv7;Sa(9kEwPyNuZ-Y=x{v|7|WJnk1inv%p0D5rH(#t)V&#hBR3TEyb;#vzfcwzKk;cJamHM;@qqv~Ee zULwqX%ns5AMfd6KL~`xAb8vmbTPs6EZOYXB1=EQJedg_Nwt4tk zf>aThC)q@j^YmTB*K}N{Pr|9q3Le=^xH11~O`Y+V zI{UeFO2C(|1cPQQosXoN#6kJSbE6qq-0}|Ln95np_sl~#TQO$bNon)|shX~&x14dq zVXqjRrSuH)H6(zsnYQaZ4lA({48*r#8ZG7%9(K>w5}9Agj(4I@foc;q#((2gR`W-y7qOfA1Y5T*^nU_?{M3p^DmQDDZAfEOFv6F`S+XFu_b9Behc2F}|!q}BQM#Rbk8&acxR z2YVB^rcgx@>P#`X$A>Uz4bLs;g$*RPXlR>C8)h0__E1M&s~)#2npN1D|D|_0W)7(j z978-+ra$_M@CV$coh|651_zcx8Y#_>tu3C=1OVU~*zJd4VW26TTFzuj@KyqPBj`)l zB61he1#qC4GBZPxc1jb1KsPyBK4kZ62SHK}1s53uiaI8nBHVcx)IVIJC(mQSJEN}x z$r3ewytHFt5p&AYe0tou&i3Cz8{*J*3rCo`2>FfCtL06^Rt)mhVY~+opJuc>aro%z z`hjIVwejif)Rlu_txhenOMLP#%se}S1a;1Vq8$PA_|p9NbWW7Pvey7~iu+?7_}Mh2 z?<60X5CE0frSs6R>Brt1kWq}*(;T}X6hK-aKXQpH z%FU@tFYCpZC_NaW4YfA!d3W}W_}@%OI}1Y;Hx-FVoX8}bJwsU}3qB(ugYtt7m{fdi zaYUbG2Ay5ksxR~O^tQJQxo%D}y;6iGHy)9a7J02i&2wf9jZlT$t@O^^0(qE z>v1v$h@ySkcy3KtM~j`C<%odmcDts0z8@D}(cd${3G+K_?ViSB`7+K1Z5!%|r1ZJX zVU_;25%_eDJmQDr<_B(};GYs6K^i#nYG~3b9+FcXz2Q^Sh-*KfYMjm~bJk-^Qx1+% ze;`_^P>)_H&TD1U%P^9|o^juw88oMEnN5NhcX6HmR-X_M=%{9EFG}+7x2@bQ4U9?R zWZJ-0J z%s`IXz^g4*3qYi8wKmhw-n~tcCmLXjZ_oRB@Tk%FM+mX5)^qoidu#}xOqz;LI)UJ! zL!+fxm8jV|se?rFuY8xn;(h^|Gcw}s-}ivhW!>#ytP7AxpIDVmf+V3rTQ21;>GZT= zh2&iGA|5ZLzlRH?IQYU&kzr0o1^W%@b3KuI6=)#M^_d?3`?cx^-q@Wza{tVE@B{A~ z8z;S*o}2dlMnymyB`J>0?KLcX+Bz>nO^v4QvpOpDqp;z-yc>9JP$V`Z0l2nU1CQmu zZ=34pM!JR##0=4X(~I9Z;2)_z`Teuqa8?aey8SJ8krkaFUZ&qx0)n?| zY<%WRfH?5u&&5UL<^_O#u_6JEtzUn!*Cz}JFD+8E1vsf37^Q_i(dp%5R~=I^c5Zm9 z7vb@jZQle|7({SN+L=wdp;RXnCU8fPctx=#+6z?1nB z7@A_gC! zZ5iAwJ_or+psn9&M5p)Vje&@82$G0xZGp>(eZWsdOt{P-l;pl?Bv)F$a$p zk*BLV*L@ld288J#hDIXoc?z8q@vuFy6jc%uRvzj^gg$ zjX_2_!?)EQMQ-2`keu>t${ov|$*ME)4@k5!MVvdnRb+2s9vLw|Y(IIF>N$}%6P128 zMbmV)9KU2KbsYb=)TnRt$o7xv93#1JQ+l8}FN#0&drkFw>AaYDadx_Us40lVehPOrN|5BS0Rdn|n_qDR_aOj}f zGQD80--;U|;l*I$rZpw*uN;tn9KMF4mP3VoZm4Wkk!f8yf6UeKTAd~T53(@I!^SnG z55IR-8Zn?$iPxZZx$duzicyb)kJQrxC;YlXls)a+gX|5xjxybj^2Y#mtKYZ!%0mODIKu|l8Eh0P7diD(eTXXpoPPch7wl(b%rjUmQi$Z{-AMkGMn0w7T^J5p{v^jE- zG*=613KOhn@-b|@E6Xp(09x>EV1yE~zv*XqtJk$44OXk*hVzn* z%F6R{XzKB=6mbnsv-_ER8k+dc)~^u2Yfmq6A>|68g1?EXImP{Ta+O9uTBs-G#y_st z{A(uH|CC$&N`9dKU``;6fbFX=A}i-(*G*+?;^5;$!o;k4j=BWdwg2{O?cG~Z zx6L7rXL8gZVA}-5@u)dK%HKypB_60#N-s4+EWA%Rp+lf>jjaGK9Dp6d8t-E-UgkL) z-?Spe$Ru9bv79thV8Te>%Y+|O2k4MYz|f=nmR-n}ueYDzJ8*PjM8_r6X~YHSuM#aFnAt*q)UWf2 z`rSo@w>}59h%~v(pi7NxZkJLl#Mi_cJxaQbKofd;8C4Y(b>PUi zhUyCiPP5UGB=YtdU%KHYju0nKuFNc<>#7y_Z^GQ%o{b5(j{UmBB;}oEG|dvk zun#Da`+!ENabuS~c3Ld>a}JZ=O1@y_JWD9!FSAR2ibA8OP_8_@`xQe9-EXiBWz|W? zBs;)aSyFP_0i$YE;PGiPGp5o3uuyvlU++NqssioaDXHHfoT#!TjhvRHA?=PjqG-|>xia2a@6);t>f@T>o1(YK}X2o~K-VWH70#T%sq$%UN3 z3Y&FaevW2HrMQ^l>B2=(e2#9SJE z2Q-I_r}AA148iXFS+))xr+%vR0ur;zSyG~=i=kIt|Fo=gHE6!DS^xX!COoAr;TmcxQ+afTho*hwGFAivWp0` zi4>Hq(XBV~9^Brdhn?jNgYD>oxDE3TWe6ikA<22^8d?T?e4v~xC{RU*vU#b0SQUd& zx#*1=*$xA><=SD6Q*BD1J?#`?_&9`u5>6?hy%kjkSgA7{~qtib7= z5Jj(nbpjcKZI}Q;rL*!1wppQFh-EIhN|WB`U(YR5UXbHzJ#DL^V?VH^`%P3a^kHsu z0nmSFV7tOu353dD=wsm;G%fXW5{g_IXIMI`ubfd7=L;gy6!2D0JA^0k2@pFh%Lrb{ zT=Un(@WqJXba9P5r{y;i?l=1ecO_+!tGWAzGBEQzLlGL%o@v|o&0e)b|!8w=Kil#UKvz%)ngkT>UzWHk@zE4zT1xQeE7 z8S7se!W;42_pnp*Q_&<^vZezZJOODw89|sml6fN7?Zo)1>hYFIF0Nt6SqPnQSze$4 z?8N!r%87fch@LB_obNHP(MEK>T&8$YF!75z5UL>vJbweYp}EI-Y$GSMo>3&a-OU*^GW`UxhPHkV ze@J~oyBFR0OLqx^bn%-9Ug=bD+rfY!0h4;EF;Q>qWDmf4x`VI>LYRUi=_iL(%K^Rd z87Zfg$-v__rp56g`FvOl6^&vzsJD{&wV!RC;CDYf__t!`)9t>x7rKp-#!t&Z#Pm(Q z5IGFFz97d7-6F*Y;5d1ImrmHGiW8APe}Fp7eBo=mNs5d_V_W6hKl$}2vMQXFu0qb_ z>d!Pih-DBT*Eo)=&~Z-UqD83$`v@#GV?DI5LZ#=ZD4qwW1NH6dLTdq7bd6)wI9MT4 z1ad>#QC#hGikZg0QQmuo8=Wqs-DBRI9Hr3De;0jPh9#p#-or{9xh?Id>k zDzdwM`5lX}i7)hg4s)dew&DXRW{uF1xZBIc;q2d9t1VKB16gG0fJmebIGkTP&N=nW zpTR2c2Wpx#S^#*}^&i-}c{NVY7F^d7<4|!*c;-i_E+5g;eS!zP1J~+@JK#x}p{^e^ zW2flHR}B?!H*S*3T->f89Y#6?qh)9vkZuHajPBj&kSg@?#q(?68dKKJ>t39TWw5tG z-!!4m%fbeu`D=I|Vo5Gh{b{xWeQG4kQ11+i#6Hx?{fE!TqyDgMl!p!ZY(qNeshUL?7HxKP=XQ*C}1^Y_J5$w4fs zcN(-0-&~7cf`FJka&)QEZ+NSRuqK?gDsy>hWRm~`0yngh64c-)NsyK!sD~r{7pT}C z5a{3U0Nr3Q=3J`yRh4NLr=HirZCKgy1#j!_um8HSpOa-67BR?Ei_;u=wlx*bpxgQa z@E#NPxl(>mljdHOEPbtTi57_^08v1$zZU?P^m-bprrLT!+xZz+N>Q}4b+1?s&dc7rz~~92B1hscZgJEw zDn9?7LLm=pe*;d*IJ1%Q?>pQ`0-s?_xd|{|YX^cu^!t^jWV-qmhk*a5MjITg%Had|?sw zosNxmuEQ$(kuyt@e`kEhqojfAi!C+kmm0ttgaaZ&OLK|6tLl<;gfHCd1QBFd3zuh@ z{I4G+Jh0jrv|(s0#IR2!-;ezanF0P-2&GXLE_g`J!Zm5E6^mxA6FUFZ8Ur+@u&$IO zu%Hqr2U?@i6uFkFj}Z>;-x!IX8r0wXV44QET|O9gmtiOr?_z40qP`1bbMYAm9qw~Yv{?+c9$d+9r`x_1107K~1o76V!Z}-V z?Jj{F${sf+fC|?a?IbaAE{>ciTpQbRdk|TtXPt1pC0xpf24|-quOTJH#WE3$g#7GSGA_BGBP|r$%FlzY>w}*g-%zhFW?t+&!f|<4nAaSs8J8 z97P?vrmACqQu$UM9ASz}q{JBM(-1BiEYZ(7K!fo@1t|gi)-VH`a*0TO@znn&zTZ%i zooOpRm8{||HYVf!&pVA}fjbJ4RfPovpXfQ0m)t7lZdOeKs}A_#0qv63qxi$W;9{{>(jS!-6J|G>AWOx&8g7ARz*oOC+9*$8B|v2i7ay_&74Mul>Lu8#nRAR` zA#yd`Y0-Q-jLvC9uv84s@{qR8?^iit0}YqJlS2t*-s*wB{|b2J{;!gz$YxxCp!xy} zkWN^!y>>Kph8puN4!Nu4%GGzSTYno|NERYc(^tWHyM@MaI&%}bg!vucIfXz7k@26L z$mS3L3~CEtv~g(bAFjgCiEm@zcI0`)w1W$uOxcIOM3DPn?`B${SLedUnopF%AuXC` zGNZ5vvX`0aSOu*BU@i8tHxv(P3F-*)lAfHkSF6#SIeMLv=sGwbeciqNCy=m{Y0!zK zr|Jod7wIz1=YtO6pAz^)9SY~7Pcj39F$+)DPhh)`t)3d(V~71c7ydVU7@loq)OvNv za%v1|Nk&P0yHCs>FQfOL#p>|6Ks9S`l@UmQzhStXHQI^QB&X4jvwKwda##0;rKPd~ zk;^VV>ehCwWO;|h^Q3*nKPwgBF?sEaV`HH~LNTQW-kgr#5hY&97_D^NSiP;~rDbJA z8sYL+nvPL*A>-{6uzl{zR=CZIJV+$jyJ$VbM^_;g)h(pX3;4PKWyg}Al=3a7_Ql30 z>u`olkyek>`pMC_VNw1h!?_VSD40LH>=U<~T36m0-Edn!IIqTV5&uayfrPp`nRKzKr(Dlw(g6^9Yl0=GY;Jjxss${U2hldg)u8{5{r(I{&;leoP*%gDJ;#Y_7R zJ1eJ6Amv8ryMQgQq0o{}bZy*=XivmK9?lYO_1m%mmk(2Bf}AJtI%$@0v0hU7>{(i9$oK&WG`9I=5j|pB>2YO565~{f`#}ghgEM~|zMj6MT+Dhy-~mJDvq>mj zr+Q|&4dO>w<~0*&MMO1+FWrWuw(0s*%UXVJP>!qjVBG- zXo#i=vXg$+zNOYy9I}S(a(fp8PcPlkwPiYup~KnC-HgBcMc>|1fI$z7ViR4{pmm&3 zYTN<|_R7Ml9qW|{)l0~C&2(j1@WH8h`D$56@3*+e8JIjymJk-Yn?rSvX9E4CLP6Mz z8CV`%)c&OLW;luBSRF#S6XeSn?nJC?Hv1e>K@?>_Lfxl0k+OnUD@F&GQPdj^bUjy6 ztcz<44;T>$k2FGoGQ9Le?BWq4rpst(Nx}N+I-MhB2VL6z3-mOv{f&nAE-HC_wOLg^ z%3(eaa9osM*qNvwWe?uA9Pk{e87CFeDaFqM0={NGsq z2&#jalT=V+9>PvK!Ia4cGP*QM4I|I-htc@)=F54McRV2{4zrx+emBV@w-Q%Xv>b%n z(&eE)oEuhjJGw{Y0rh;+{h3is_@f<@0Y~80o}Qhr&{kJ2_DW-7f+2;477EKBJjIg{|z6I>>!k>S7GO% zeNUpqr~J*nPphF{L--fuh_bOT9j~AmT|0ReLmPyoItkIM#Oe=fRgFLDpiHuifG+!w zv_goHbuE2)QWwU9M-3QoU!b0r(`sU}C)pGFGXel;KZr9JnnNHL7U>oZ@4@UCNqe<> z>8u|UNBK;m&95JAhyG5MSpcu^IQc&?wxEv0sof(EK26Z! zVjIPFramm@NPVBIYvb=_8dY>C+#A$FqX`59C<^vHp_WRn)6tDp%sc!|SBVRD=4_F- z%<%xkXvkcS^N^Abfd!5u2x0l0M9#~8U^!A<_$3X_g)&BsVEpWgF9@=wbsr3C0W=(U z)tfeO%Lkcsw~?dbG@G0HHuQ!`euOa3?V{?3OBLWwo%yj9;2B>?q#5(X2->Y(%n<96 z-U|5P1JIttirkE$7(ct^JMWrtKSif7lV4nF6%jVzDPMZgJ_irzebgWmPgw^CGm$X* zw%nWOP|puFD#s2r1r0dxX_y2K0}Ea8zUA;_*)gkNJzyew6a3h#$TwiT(L-|Egl7Z# zRb0{H{4zLzJj@(E)MK5)8HCS+@oKQSB;Rt^4P zSY$QzorHl3OEdyGtvE(RV3K`errR1&=)Gn;f*-{iF%AYv_-}^grG`|S&)5_34Dv)Y zi-ilKC@gT9#ucJDH&`53yUxcSIC&}G6P<$I@Io8aFQ1%N*?-j5Esokm(3Pii#n#meLZFK8( zZ`kLzHQmgqQ4g*+=i4%kbu+TeZ)PSnD$Tcr^l@3R*38@hmUAMV>a_} z9N1txxHXS;P6I{|(l(R}q@L{=+ZPu%4`_WXkVVLBHBlPEt4?}(7YHe~0K46uzgBGI z7a$|15ICeuqo5uI8{UK9JLXPwqQ-vL7FbiYW5fki*C{lDM@PxZg>ag0b6x5m{l_fM z&4ZQ4C4Mc&XLl!vgTKgK88kfLehhSrTP`GpTYU;ArN3uMD#j*suR@|>5lG*6=6Gvj zD-;a;QGvRPUw(va#j7wb8#39Bz)Cr zja(1o9j7yoID*E!2$_QxbmnbKy5+cumQK1>(W(OW%QJnkX4l$ABkA`MjDO#r6rr7vA@yRXM9=UT5SRyra;r1XJ+s+V#_r0^oakmuykzbFGmC)Cn|| zLfTP5U3s)j5Iw$Q9m2xY>P3D8H_;;WG2rTUzOJEu`=<{6zAE7WxZ`ZS!WT6K#pRz9 zN%r-vNS_k#hN#e`TNT&q(D_MImV~$OU$d37l|Bz-C}24xr~KI%96Z$EfB_b z6Nt}V?0Jn;&2bDmioe3>uQ5Wb$$$Thho~|~8PxONICIGV;Am>COq6>ZT1OWZ7yc8_ z&wVi+et!JZT_~r>hdF2{k)$v*?{awHXfpk6O+!fO_j(BT! z?fzO*(206yCpA2n-h}aA+PqbtttoMb#jtuN_g{+@^~Q!%Cg>1zrYPF064H$q(>RXNtfte1^az-_(O7vi8^?XYX|)v}Sx+dBKTPUJ`^ z`1w)T%2GPll&JwNT<|U6W=%FlKmwNOnlU#fU*trjYsU4lI37-dlFXECnU6Kv80ONf zK4yiLg3=)(;eC_qS%@#)eswB$1GWGs9MN=dYE1~ed}tydN`TtuR|1*V>O&Jl8+|_W zLQWLWVezuJPHvB_{CPPD;F|1F)v+$z3KrCF=*+)5|G09;maDkphHM^butIK&gdkVy zV-yYqIUXbk=4fP3S+V*6iZ9sY_;T>aR7dz{r-jp~URnu-!+e7hSO+V`)dVaKdqpQC z{;4~;(`im%lJh}$5+6K%fZxQ1poM)I5h?&==dZ*By-z3N{;p~IwyHvm^<$z0tR#h~ z?|AwGuj5d0jtIBKN}-Kd@-reyoCtRJB|RA&GbFkPm;0AhnU$jpxjV>SP9J%dlenEx z2StxYGyXr%!%0XH{JT8op*4dyw_cH2rheqdG7+TF)9wlBbHZU5FZ=l&Reoc#Ohgpe zr)K}FgFbtJaFWGhw5VL;5HS3GSF;*o_hqP4OrzpJt|#%KWT4`0MgovP{`~pR)2`UL z`8CU0`-J8pA#j=o9`!x-T^&w0w|Y`A&l&Lo1XOPmpCP73Gz#})n{q-i38(EDm4_$) zKnP-*l-;CKBkq9L#)p>Rq!Bz14Ah!?(R2#DcwcOsrs11cfSn!kGAt4tU$*dN4VaO8 zDLn-u)rEC#-ri#|-N^N5d`tK3*5CH;`Yd^zjvYXny1R+ZhAN~$3)^8ZZEG}jpJNR^ z?`-FRN~Zbh>AKk;m9)n(wrb)k!L7 zRxa~JQIHfti~nIkH)1O7I_k!p zv(zrGC~c67A6dBYF;y__c(4FMbIk?qG)CVi1fNGGh^UdmjtP0 z%rqU`qx{`(aU~62o#PPtNp$)7ve=R~u9`w(fsmKmM(`U^omV;0vFJ57ETcR?7 zQ6@0FMdi9dD`&cvAyje9lIL~9_IfndWB#b+B269Sy8n%jyTAKWBF=J+zFvrt$>&xa zkIg!Z@2?8zMS6Hf&vBJgy8ta#4EQfA=&#|Nk@+)N0o6EBctxWt1B>bOs!I{{T`4h;D40({ z%9#a!1+5T@*KpLfEb!}LfuPhhoIk`S%y-KA%R(@iv&bbWnF#rB{j=+1?QO7@@vCQP z9v#A$7I5b9v$neU`f;)s0Qi-GPHwDwvCBkMBZ_rwGvl2WOF~anP zVoankrInu)aV#-a5E8mi(YN2d#wZix4IVXRQ+arZo)ByY5!q2JIOoh4Zp?6=?Yjcp z?pM7yZimD;(>`EEo0dO)Y=ixL3GADZ@oN>MbsW-<8encFX++yTUs=;=AK*2_LfEZ`QVciilHxONDfvorNaOlFG>`Kksl5m;f5MB|0P(Q{|eT^39zht ziN8;|DY1viv#I)tx{L5U2$5)XrjN;HoC-YP+nLw)PXd{l&LDtnKTsx=ZLZ%bcpzkY zf1#VaJK~08!GQYAQIVX9-=DPlO{`$LpbnJ)5S&EErBtC935Dkm707TLlX!KdRH2c3 z3&reG#d|SKOejWum~alxl+Y$_2u<)fm?aHZA-t7Eye79d8t=47oVn811#F4m9@^F> zOgy>n`v(g~YmS8Qux|OR-vIrRyUwUmCbsKf0necu)>T}4pH}RN?0ehHD_>Y#{7hUv zlFtbi8L_&>nC!D9ATh*um(MHG%3h<_gNe0Wgd}r$R0@Ui&UYYN^%{*pHInm2U6LF6 zjScNuhk!KL`;1%s`!!vrW#1Q{lk+Xu$x zn(&Jpmu(A_h_5$*NjmLM{FrkEvu`PW$l`!}^>m=|PM&QUoghM^FOHBeVV6S(<_WEH z$rmH=1usHhyiWRwRk;DB#Cqroi9T)u^0Ba1qmOH59+dkse#sgXkrWfjKp_he^b&5@ zR%p6KZxC(BPOSA2ZjKkd;KRJfWV4_erAk(>gT?wGKzGZD&Yv2b+SE3Fgy1R)e^dWL zkZA9p2STK3nP&UKe?HpLE#7)45hNX-T}_U95WJ?-=|MUr@^?KGlxu5LgIsiDkvPr< zQ3qarJtF#l)MiKkfpWv26-lSM2C>%dIep<^vz=SGLM+)wzx5eAsNSX4)Y40P)i?U9 z+kKdg*-^YlGYl+jPrt!$(x^9+3e%&xKO_8Z5!x}Rbx z(Pn7H(aMQ!?6vn2bH{Hik(v$cN*n;o2ZpRAm|Qma-}8(op(ji9)WU_l?~%X!^08Jc z{9IcDjbps{EfqsGQmV~lh^53@rp$E_fl}`Fh}v2Lb9>I_R5K$&OX#ouwbo~lRI6RX zMj;CF-ocx*6n~=yA(*4b+(wzRl$nNXasXzZQoLIpsl2cVwBv%!(@3wfJopjOyul)| zThaJE)hB$&=aBvD$myclprig9bM=`{-IIq~yR99SYjxtq4jB5bfQ9&mY+@Sz$MmQ| znQLeGue;J)73olUyOGpH7cMVPxElrcfW=D)1qG&jhxuH(e>>d;W*M!+^&#k@W*-aD zLW$Yuiwc@QjP|O;|G6bT^lS8WNzo<-m0>+#c}QC9d)090N$;Tl8XRR(t9&4S1A6^4 zVcAlWFgg7z&tfr4OUckZehfJ&RL>gVF6;qjoD7G+N)pXvO^H7DjPm7BoOXYG@`qNU z5pzu7Y^*=m$F^Ggn9zj$mt-B+&gXj-B8)^PszGnL)8rQ(p zq2PN~6a?Y3{ST=h718cN2KbN#A0C(WrACJ^E`aEFJZ3b}M&LGYymD zynmY(!juO@Xe3T*FFq9_s?Z+V)hL^PGbt&Su=4i+>Gw?qFhYgn9>-v%ybMabZlh8a znflwR`4>B+2nIxnljH~4>OSF|;-1`#ap{yyt$!{4gmbPEg&Rr*i}IyNxHa}FZJon8 z09Ofb`AiUQrKjy=60Lm#sPMOJ4j7LVNnA{@=5z2aOSAXVws`^nuTf)-)*d5yuh&Y@ z$AR=1Ub!i@@VkgzNT94x=Ii4ipy}7t0ql96o9r9OOL1i_tI2RHJr25hn=VwKD{`hg zKgx+SW6&HQF2~6yr!aUale5r{kT{%_@5Cr_Xh5h#XN!$Z>}3OdfoOx{oO)P87l~~- zp10k*X~L0*k(ZK4(6|adNE2@Iy&oa!qm5#^Ll@<=_GXRl^H*DZZ=-Y1V0uze$}74A1C8t+hzx&Z7a>1q>Pvfgbg22~__;Z%6KPG@aoLulpGu96}>kv?NV^{+2O z46V4H={

    *L~vx^d@>0hTF=R+5Mrp0NkZQNlS{o88tmW(FF?F86!$`L#ci7Szb}U zhjJ_#e21yVv4>dpwr~t&I=VNX^0O*y1_b7Lvy|+Ducm^^jvsDQxvYaL#v=)PT2qL9 z8))UuO)Nr+ElV-df^N$`r)_9~|LB;8W&5GJ_VB~=ZExEvFlPea_&Jhof@2S&MEZa3 znQF&B6i8|#_DJ$%GtV`;yp9t&>Z9X~-Z&pfSrbt#9kp-a7Hj_bzp=cm?w?*|%yk4Z z@U?{~UZXl19T7aH@Gi!V5Eh_j>Pd)MVXdv2K40hXq2Ol~_Nb+|HemIf52^XZ)0R6$ zPKCx`$b4x+nF=mm`1C0lGWMY>{0agjc9!rh#LuF-WqGX2H7K;^i&qqvAsC5UFQN}^Ks{&kQ~W}s4Bb_EYrp9 zw0W{6r()O$8o0Ki$2*j%ssxNJOf}L7{GQu-nM4ZmPN$$zq?0&=hg4hk2T6{_!xASZ zXNXzB>8!dehzY+jo~(TNgQ?v2aldgrY;6cj1W%{#)>gJq3%pN+HXLjDGN>v)sH4I9 zV8%dyt4E5F1`=Yopv^S~{ucWyR|+3Jm9;hXh>rs#yJUFk6m|@jq}S8gXI`ZYYIQij zT>!GY!SKXB1sEH$2KPmU4mRH?;`EMe3 zUMOSp9nX#e{%fBFVC~Z6j008h9C2xA*OdWVG?qS2Ta9iGNGkvNWL`3;qsZ)F9Y5{A zM2yt;NoJ*sx7;PRBzLmDi#2Rwj!qt#00}_$zm%n{F>49<+Y!dmIC>(?a$dQ=6~iF^?4WT}sz8(f`90qdh~$=V0~$(=Z;sSWg=k_T7U3nwtzPeuyN2 zNe}o)!!~dvVpbS}sdFKGc9O>W%_>arP{JWvhI|~J~>=qX%Guj z7f49A4(o+8I&njeC_vr~&XteU<8dYFdaXREL!TdL zPVpr8K)UXnl2-$|AvX*W93lP(uwuQ`-#xR^FJx9&lHnVbF%WZ}NUPdE#MMqT1@tgy z1$4FAr?Gf@{yQlPGQ&kkeK8;YJk`UV)I)h~|B~c^}J2WpV>sYN^k(t6PU(p4YZ?96&iJKdRyEaGl}9q`LCwrzarO zRUz90=@%wE3&+5e@!arfAcBfUq~S`D3_CRMZE{r#Rkk0Eqi;D$=nvC7F)QZn@#pZQ zzdQ*0;F-_#bWcA)B48ka&|dM`KpM+>5TvqTHcyoFoRo-Kn&*sf9;PP$B2aFOqG|tl zJT*Eu%V2%ygUFs1hNg>*@${o^iM92pAW+2X$`>G|*zxDz?{c7xA7dx&>_7;@UCi6N zZ!@fq8@OTW40xsc>bW3DPcM!PFKN9;pmg-z*$U_vGWTN7B+BhoRQDTxzbQqqp0y4L z#nb^O95)UAX)6uNbVgj?n6)8m_0_7yt07gK-*c(ySXwJr2|~%~U7pD5W}#}PdGJ~G zwr_NK1Nj+<-C?HU494oHnTYuTTN@n}Ic{9I}fs8HZm^!T@gu92hEDGQuJ%&6aq zsl7Nd0?Uic*Xy@SE>Vs>4s@F2hIX&b2R;{qiNXCNTc<0yelKno?^usxMqDE_Y^w&z zo$c;ns2figlplP)cny)HFt<;^K2DcvMTZ$psRxWB;FSV!pm-UgoXTKEB@yAx1%Kh& zqaZto(#}Yj^%$_P)&V*yV^dm<=l3P|-8>v^EyxW(ndbwMu*vNJ5AH2Gy(Te{5C$I?20ETJSvM6CAr7$C~WAvfw9SIQxxa?-!24EyLqoHbRL`%VIkafw%%%X?YF~8yk`Rk2LuJC&ga_jN337 z^=}KVA2=&4QMs+pdq9HVGn?;kW!B#x7|c;V>P&8@w52DnLLQyWQ$Q|KmbR6ucH)n^ zOKQ{8Nhe*dVvm}oCIOSS&7Z(^OVN}3BuR_8!pfTGb4W9N;T^*~|CY3%5&({(^~ee^ z7kC2WR58@^QVIY_K8lYdyNGOTgK53TZzF-RcmjSU&2;d>U=Yh?LyhXC8T_=(bUBzt?8W z^Bi1Z=%Lm$ANs^Pk}B?jqbo}F@%Py}Z{%&FHMY;n^~5y71b}c%wt0doy8Rdmr`uar zt2@JzIAI^yPhbLJGtLV~gGG-{Mhu92tSy~k1ARnp@-9#t z=hdH}g&-nE*sZ1_Wrv{(9yv?oOb-W-fkAp%Q>>IeWU=-d88@(H!(?3VUfb`CBz`w+ z4lO0&fD0Jes*`oaVK@o=@B__0<8_2B6->n!yjSq}XLu{(ck;Utl|=r;I^_qnegD)7 zs%~;Xs0%qWUa`4~ZZpT-MsGa=ErxLjmb}a`p?pwLAPHGYuV}VGg0pf6b!|oPJ&Cg! z%9RFR_d^~eenR!*)>*Y<&-Xeaxvh89aF0cYYRwzwM3hdX?SUCbF@G)RAVWG(p-ph? z&TZl6F5h|jDErN?LDQ)d%j6_G8jZI8Foum`916(@I$D2jA~FX{M(l{vIdS#c+?->V zJ-0L-Z#G#R8-t7X4Po!cjUgbHMJ|%Sw=DLW-XVAsF8v@Fec7=LlKOIh?wVqxBd0)z zaF8U&mU8d{*hO5UMyYPY*}%w%=X>;L$A)8Ltg%dpC)c+{t|jI}As zn#vC@$uBlJqC+$(G31;~y@mV<1UO$@gXjMDX!HU!(nO8X_tQov-m>ZTU}^($H z^)yCkH5%;<;|BV+!~u02@t`@_zVOIiTUC^LEp6my@JR}(iR*$kmv@c`tCHgk8e-XL z_0?K$%_nD(-=NS-ofl-4UA$(PjRz#{j8+;f6Pjic<|qHKRv~$7uWND{4!URool%#3 zUvX3XGrsrlte79u_hNSdbBIl_li?#wlD(~?FL2_RY5=>m{BQY*6a#W7`H&8D^8T6` z`}K$?sP@btoK(mMt9)oQ@2ohMUgiquZ8Q87A&t@1nzm9q7(}Tj-^&kAE7MN~HQU`E z2SP2{l;a#3Sm-Z4inHsufAspWA_A7vN}+Tm)?x9qML-^5vk*PI71AWMb|Q@K3$fd5 zPgtoESldLbbWFF<#@}inaf7Z&cmYPd=7#Ly2Jpag5K-%r$I=Dd_EuodK3rS2TEou99tGcr@roc;0u(M40j&@0o8H@wXy49!IBJ zy|>tYX>#(iR8F;m5-^%MyU$ukTEr`TyxlOIP-GbfGc+`q?9H~!UeRwcJ0me9s*F}` zqsaXIZjlXu1%D+du8;M8f5|9SNUQmphm8IyS_-R7v>1H3&gr^y++Kzp48LN@S{?-3=I0&J(l&8OQBKfG4ZuDg5If6@XD0Pq`_YuNc{c0gY&?5 zglX=1Z?m9P0$Ar(@4MRK!-Ql26)1_c1U4Ch(sDn#vO}w};90K5%Us^tHyE!E@{2~s zNC;OLZcRuU#aQ}TTaL*GKKdw&lyOP2EnF&rzh1riZfqk1W#+L3CHa)gRG4dH{t_;@ zcsIZe4Q9U1tsn~QGs!Hth)}IqP2Gkc=TikJ-Sgq8?7du52`b~&L zse1Dg=ObQ%vK%hwOAs>aF9@127r;|g(TAr*6uJXuxvAMru@`r+`<@=Go7yNa&mA;b1ilXrvY4~%pzaFWOq1Fx3XjR+DfKE<;gbPsU59c(i~noJd?2&#-Z1gw?5 zR1$`=ed(6^*{4M2dEqf-!l2AY+gB|!pO2xE%MNV-2H~{B`z|;knH0#;`NymxRO#i! zW0u13mr?dAF^=)}##F~U*i@t9wNs4O;o(+5@ptryM=KPzw$%UbK;RbD!?HaOf4b88 zB2@)Yblj+{v-19!g{ZrroN78>c_0)2Wbn*I{h5iK4) zL12wf{pEmXc%5=#)gd zV}y$v1w9!}C`HUC{5XxSGRs{1!GJ5h+m(6LrFjF@*9%Qu;c^d_Eb6}P9vOy2^kk-`fzg7N>(-IM6OhWc7$dodbX!j9T6GySX6+6-Xoy0 z5F!T9eK1zfwZdaFjMczl9z<6+tnFk;K^LOk_b(pH&m_2l_p`L6@_lg-LIV4N#sNKi zm-(9EO#?n0u);59l&~DM*(vkuUUO(st6&%NZNvKlfm$}SnIQr5RglB`%q9TX>6j>69hBV^gz> zh~Xsam0z?6*6X=$Es?V?T=1t*Wv;HEm`L{~OWpo+GBIC3YT_vkynX65ZGm<<d*=(+IOWV}s2PKWt~6s>)jW6qbFt-giCpp+)G z#r2GwSa_OoD--uE>&n2#N{7A~UyC9k`oFDm#UU(m2wyF@aC74e&F7};0?3J<>p)}T?61MV+4WYV?jwV3!;YnAN)4(D%o*kI)m|cVaq;y_S9!Wqp zxA&Q3T7X60Y=&L353?fEbRb!B1S36H;9D9PokRSW+26tALtU3XUC_75!t4PzDRjl_>$2<^xxp@h$JYZBtL~;)~(X4UGK5f{27S@WyobUOFM|8Co}@p5a%q)IOX-ZP9tR zb%dHk56|5XLc>avX?GYA-EpuvgqKoB13%AE%faIL4Cu#MdtPAxfUZ&aTD zsLk3&y^8PqR2ad0C<)ER-T;zKET$$Jb}*%l<#tci}#Jl;COUzwQ7p}P!#l%jYu z>fr^4keJkfMF}Q0WQo1C1!K||-VHKFE$3jRPemnpT!n2Di-qnhIDeawH$#bbV#z76 z{IU~rDM{x2-Tk@W^h2vs@I3m>Dw>_&r31<8=BiRQ4gejIs{iMQI8To;1d(p<@9v|J z^{$3>3l}IN9|%Qpg+Wj$xiWf+LB{e~m7fN>RNWdqrymBF5mGSi{Z%*8hRPK0xn>6(@JHfH7%S;E2 zwqR*>gOJx!-7sb{x1})NBj{s&u|*q%*x$rN>d=<4>74&@!;*Anr({p5BC*pVE|^no z%zI;C^GJ^tng9#X*&RtAK8F9K=@)>^-KBo!I9&_hKe2T_rpxe+JoI)?(d&5NY6f6{ z@Gww}`xU^<5~oVGf~Nk}V>aSXmk&KTU+jvYTL{IkF}#`z%!XUvBe1$*l|~h_`@P(< zU214GE;P9*SZbUf=Wtgw!RMoj|C1j}>TIQsSVYW{Lce=sJxlcDaK1q1a8^V!w^?Zo zW+5B45&iXf)Eqoy95T_n-y8yheuDU&$Qf0|VsxE(QF+Koi@+NgS*+;#p2eLL`Zhm=^Pk9wUdl%k@&hauK|Wb_1|C}Wobq8$nhMj` zdz>&w9x*pQJ)PbnGQAoMd|W3jVl|T_Ud0!~H2H+36!sP<+0Zx^B&P>5Nny=!R85Ca zUcxa-X?@@u$RYPVlDbO_uLOV6U2^+{d>RdLZsHs=ep<*T6$Iz6Ghi(g8zh-e5>DP7xpdK z27nVQcxh+jIPAA$+8r*pCz!{Ka;U=BA#7*R2UB%Cblxrv4ds#|ShdA`@tE&Jf*YxQe#Y$byY1h0VSZLy&3rhb<>pmSsOSo@|*e-zLQ% zU=uOMco*;~XG!?rX((-wou~n$cX0g-p*?vo$ble-s+dQ&tq%TJPX6S9ccJZSXl6XTv73|Zj#+CJ zbAMbemR|rlK*qnL12}p^W>l&-6B?@2L>O}LwdI$21TMVyJelYtHF$LD8cCT z@wi;|&=jv2v0j2G!W!cUOjg?g^fy{PaM`N50`n}2H*u3N&-J1g#(io=sF%D#3DVon zZ@_uO$d^NBfmBucyX*(+Xa0EY@SaPiXqOg=f+K=*oIH^#mL7>BscWqYwURXVL?`U95FK% za2(OZ7PrncuV$_D(t*oF?t#gI4ETq4B*}yC{`tfTc!0OB~3nngrHzf`TIQYWj0MH^4X=L|9Gu|lio>YAey zwaWKw$~Lx^xv0jdF?QRO#knQ&3%)*H+$>}-?k4?Lmg6f-Vw>bt^(a(hXSCHE1U#5e z5Jb#4r6^ChCDD;=vg#6y!X!Ff?Ni2+u&}+3c=IA4YLxD2j|_HH;S={SZZGQjRlH{! zU>s>A=NiLaN}cx6F0lU6QPV1tKsfPWfzzS%XIoy=hxfYQjnE?9g9e0o7i3vZY*IO%p<*Ws_c`@O0xc-+ytA;1{(0dv$gQ&@WJzqkR(U8OKHEDxH59$$?~tsKP@v1f zwhVA*TL_nI5L*G#y296oGQ~XkCOm`?wL6Qbhtw<8^8ukn0d5Q3(V3kR7pQ^3jT1*Lo*azh(f-JU3fQl?oH zlBR@$%q*RB-P3=5jFa1il{!0Zera}Aya-5hrkTb+{YAht%SjIP+nyJGn~CK_XIR5C z9U`RjS^ljZ)|bE8{auWPf@1s=hKn51Qa+q05HAIqvECFrg_3SpyuU!%0-= zEs=@o(MrvSvS15QOhMcW+s1?Mqv_67)xQhH0D79K=hfXXIS3yVF~ink3zi85Wb`fC zV0<0~Ls?}>xqK^3l|S0wRbB-mK4b*5oM_12;#Xgv)afLCbMF~#R*N3Nye73e0U2~< zREaO@_V!x~ITCF#std+7)DxCc*WIEGd&dJJ?JblgRvD6|o@%1GVrj({P&_v@CyAnT zuxEn=5aY$=^9P0dXCq48xM$=NIAkbxYas#kmIA}`4s%hajb_1n60^l)p zTfTbHi3TPQkMz@=Xt}_Sts~yWDHIN4sR|6Oi0%J5rc-vQiY7?vbHiutwC*e~WKK%D zqVl3CMjDJ5Jj+a84DQVNu$JQExu%jHh}b9+gLLs3YkPzg05Tzlyojln9N#*UBe;64 zW!~TqH<)Pu=Nt&j!Od)j8kF@jh@sfcu~p57sj6Wph^FF0U4ikgmONeRH6uM#mA8b! ziMx3&7A`Jo+;1=Pwquktvxe7J0~AFIdOaicclnZDJPf0tHU~v)3uf(C`Vp$dD#Sk{ z;yu|N5s>E7>W-AO1Ol_z%;%(plF+tj&bh8?Ny=afIU=2~`xc*>NNc9=^Be7ruElHV z1~>8Dw>=h*g4{*d=D>Tuq)hjN%D9o} zfNpq08wqex@45^K86}& zgn_lN$om|=kR+Z=0W7>8SiR3EGWDP;yTG`sR8aB}knQ1Ywz9J67iO!l_d<1i1JPM8 zKNDM7aMIu!)T%oS)f^DdB0YC-gE_c~Gnybl1MXAL(4`J*%b*s9(gtNm`H0ehrR`##(Qsd!EF&twpEOzX8hM}7R@kG5X1iZHv z>vY8%aL@<~HJU&1f-CL9H(!-;{L~8NwS*F*hGL!?SdaBwq7mbJ_h0qZARq)uJm2>a z^~XGSb$jQZqI~;9o_P|G!91eM9fzj{Nszc=H@jb|;;G5pOh5{l=$(%2nNn?A>fR#U z4(op4yRs;+e`2~3YDneJJ zTjK`M4bIX64$uXTM0*AqywGzhT(GwCI4e$BWz~cFOvW{HW!c=ezNF%nXTuPBAcWeQ zbREGoDs$1szd_eyf9fabI%d(Xar+CRx%r)w2o>p;RjW67mmBfPHKoO4`u=4?@~EEo zYUU!(u!7UrR=k-zAWesPftdvuGWi^JP?`pv=uO*rna)`Q z?LpL$S!0+3=S%m`w82_;^z+ATW)?>W;XUn&HpH_JLw#V9?)2l84%+|NBaN#EBY47f z*6Gwfi9#Hi56OW1Cr&IY7&sQ>W+1 zUjj6ZN^>G=qBkWGpH6S6&KY_hU2)!4t?V$U?iO0C{&;?)%3E)v-^=jwVZm%Oy~e1QgO$^cJo>)k%8# z+R35hlA!ABX5QAF?9j_GOu9GX3 zzg;hL89A}$6pdKi-fI)h94*`#ypYGQ#e(RmV`pKu}Kt7n7+}bP=Xd9E_ z_lSawhhA$4xCEry@voauP85>q+cobcQ6&~Mk6cNaiO#wVAWN1prkTZk?ILYx?wT~q z)l9B7Wvcp5FM)XdPl#l1hijN=AxE%DM%p$1;&OeGo0K@XMkQzzuW z8{-8n8w3g%E!ZIjn}A@GyZ~OMUKblH^c$&`XCL|@p!0}en<*0+?=k{Y_l_<|@$rsq zP@mPFP-B;F;6N1@c6nqs`z1~e6TEJ-IYz^l1BQdjOtVQU&-M^hS1u-Fj@RKGAx_4> zLQ_+Wzy19pgt7$H^egt;n{AA~C%bCf$z6sm^LfLYAdnPDp%9-)EtyrJs~7@ zYcl>Hk+TP79}CKpeN6&jsP?X^;Q?E+^>E(6(*>Qq4oc918j*Y$*g9U_WFbxSchycc zvG@H*(5v!D^sGMW+CwT+JR@6Net`FL+G6A^87a6a-;v}dIvYY)tUBas#(L7KUBbgc zC;h%exnZz2S#FrZf*w$pN4j*yTPM&)yx4JSz|eg_50;nLO3aKtz$seP`LRa)l*wNf z7LvIT*#xsnojDNl?BMa-3E@}wf#KUs=hm7)ItdThSLn|YEBkDR$k`o>(fw{j+ihTO zx~&e7o*5QCTTrkJS^zZTk%6zguI^1y+Fz{A2bJPHPfCz-t>2Ez0IF;+tohKi&Z%xs_KkYJcEfN3~@kgV3XqAv&SS!AFx` z>u+2mPDyQxY>@Io)*ig;1C5Q3zbH~Z61tga_GXZeo3b$3Yd+R`(3~I%Ubg1Xi;CXL z`!(VCfP;4DvALP6p&;y#7Q*@RngaislSH5~-Jx^xbDYyl37cw)(~EXHHw3p8Q*K+_ z3vwM`JVfbeG+c>j8~(pC6(0Lz8@xg2i`nRN_asy5>0m4$#IO3=$d-aJ-NC!;x?#_+rv>g@2fZ88GoPb*v=a zzJCIq>l|fS|8TngBMU*-RE3btIlxkvK?iT9Tga)`Eq&v*KB6H-mJ^eTNvEXpkXWR3c(u@>g2N6V9xGxw=7tR{ z&nb3Ek0+Tnwhst8#J;W0UEV@)lH=lt9vBRC5*I9Pnvg$Z1eTCNHAg`UxHh5tdMDE+g`ma{Ox#_e8^rk}9# zzFfLa;O}_^$0*;Gz0}{N*ev;H!XHebX3Y1&0>7z|d=tS+7fR2>1Yj(ujHbCZI|@a?__cMK#WNBvI^jf3u_V0uQl ztiSi!zGOs?rPm3$%2{0ed$yZFzWA564@)Jb_TBm}{)=qw1L~d<^4;@L# zT$H;ntTgiKVV2?ID}fTOdaw2#xd`5C87OjaQ_y}i_^{!nr=a7Ib0<9S_nX^7=(@Q4 zo~{VcW^uXR1m!gTQ|-d}iHszM3Se3Dk=6W8U9cb!>6 zjE!I83gEko#nom8)6;VHrPe2f@&rd+WLNHH{Lm4b*tM~pE2_$7SD#|y6)qtLjY^xR zkLj0A^|&PdFRRp0+Co!=CJtEu{jQw<=2v?s>(Ze{F`D-)_0{*oV&Z@!+-J=m`En$+Zm3>i{lo`{kbct})(shmI_-W zI0Ok7EyX9#BsHtj@sK6Y4iCh~y1`VLsE;Be^*)E>hy4?|cA&Hix)t*txCgLWc(S#h z4LWB7+8!8tSgQY&a@jz&eTu}l*dKV)AO~!mUidW3U#YTfeD?feOCqntR9s(0mfL~T z449nAu}Fv@4=M|3u^^z>$zJ63$$ACL;5rVLFgGzQHFC03!_87rO}VX+2`*F1xt#9n z`WPOUxs`yb0dIeGU`%>)cwQjue~G1Dkk0>54z@9EQJz7|Y-J9P3i+8_B$p$TN`Tft z=~3}Ux~gcSrRTkF;bcgaR*FSnS}=fyfN-LvUpI^W5Oi<((6&74>qU@aFlN(B7uZOD ztFtwl9ENz&Wpt;+8u*8A0KmC}{JKp)4h`@SC>DJ?`i3b^Aoa`mgio2_uakm;P1{_j zN(CHtyL*42os*8}ja~pDx6}&HQ~?iUZerc#3k|Z+dM=}T)rCNni`HH8^}^A5!0ll# zRkU2S&a)oYQ!(?#bR)zcwA8kF^s&4p8m(Ufr;$GL@V!0Qk^yv8FWq5}_uS9zGF?s0 zAweC_4!WtSXZu$#K8h{tU+fjb`F0&%xZKmt(`ur@{TVuu(!@Ayi`WG}OdU)Z&g(y{ zV#Ri&!iJ1B8!hy>3?cNqRUym9^=lkm*X?&2ya_2K)D8|M6%{PtBH4NjB&K^hVpoP8 z-0>M_cz8HF(@Da+khq@N8DMaK-GsJ;WK_h4aixBQ6P2;@_3Zs+G84|S&!Q@l zH5IR_*P%ddpny;R1k$`XB&xdc(`(P{0liK*Tyi_2^7HCU?P-(4%SE-iNGN|Vk}My~ z5PCJgvw@q&P8?iP6);xSFjv3iIeVs{*;xl+&?k>e#hujBQqmL(<kFE-$x{sFjp;7!5SlCKYr!*a-4kQ~ zIx@yM7u!o!wS7A&>LgBJjLmB`%#Y-bs;S%9YQX!pbtmo>QSeD>Kn&s8uBuRQFZBp7 z%jjiwOlR!K_L@v$YJhy0TP5rp2d#-T)YJd|oWFEPpeGi46on2haJ~L1Y?Q~$)b!EU zc*csgQ)(Wndi8(frDuYU5w8=PYNe;mvNKzE{6NYNA$Me+B9!+FkOUH;)7lNq6mMiY zH1_ymuku|X0_g5j;IDwKt-IO_zY%9x7WYIgXd((qis@|pPY6>fK=1AO1^~sv{2s~niM$?Z$;c;^B^<5T26%$#V(LRkfskSC+@qiQZLCg@mh2;nd=m8H^Ea|Y6(B~Zmj;QQW9v&w-@VSe zV$(qZgg01X=eJ7;oFW?D`-I@uEGKpza*ul@-l{wedP4e-Be4CMv-%^01=MgeXDsv5 zd}0gIL%+CTIl*geBkQs&5FUBbUd)$n8Z#P{?+JL#wlcLu6?=$NxC^dk5cG$H2k%1C zK|has)qW9ZbxXB;kc@zkZc!B0uWNXJNI9~AK_ep1&z6Z#7ymdZxIJYX`KImn@;!Uo zJX#j{MAlTZy$;7#p(Ji!9QSW@TP`cPcIb;x#{@Hg;h0I{m*L<`dz(29KV9)7gc)T# zl2l8y~&ZpG)faHmzaGbmY562oaAVW`JK^tx)EO zAe^qkG+N%>`Uf}_HYyYz6w@kg{Q6f>Y=P5dcYtGzPqck(B&5nZy6j?-hm?DSa&K^J z_Wrq=HB8byM{>bfbieV9BrvuW9=MBt-uZMr)B=Ji1Oytb?bN#O{LQef@~4)@*^qht zXe`YUAcc98E-&?=-q@bG=~`SA z1^prAX5+W7;izvjE_(^SDk4e?`9&B`8xSFI!NX8?wvA7|dAo@lY)7G59*g_=Sxx1M z`Zq1W3xrsMEMh#d@lJ5qWZ-811F2Xdp?h==l2S#Ybrt2k@j*F{!9@iAynK%9n$No9 z`hUPMBzZ?t+=$1G^?x@dl?KpYT*86%HfGL53W;~-^!V}mBrc#D795w(n%m$svT1S3 z;P64(Ujtc(FE6(Eyw)>yiuNQ#)m&TE%J;RG6GAoVUE0H@1Lxt&MhOw(?WHvS(yuiO zl+7g$W<*Ypy;?mC0kiFIUi1$D@!UCL;zuX&s%;Mge-o1Wy_yDdwmwfZ=@l{?bpx5 zCUVjddSsja(lwEPOUb~8LxsPwG=rmsi({vpdjq6Z{ki2Jk~vTWRO#gb04X_<0ZeV4+&a7PL!&y>vSPN+luMU^L);Hg-t}>_HQ3QCf6E zqu8J^>XQ}>{~0XbhHbW>ZrntSJT`Y!zA~eV0zo!*f`pK@{sOra(;A5cWT8%O4oC22 zhcw{cFeht%kdKdr62p2VdEl{gV~`@-hJL)5=vY`76pzWje&#|kp3mdnDxQ3%%C_su zzTRn;jjD5}tM))xk+}|-`caQ&RwM~h538}wv4?1FgW&v}TBs)-qEV$~MbCq`1iqal z*wazXq!RSCDhLczZ2-9 zCk1tG&;&lDzhsGBmN1tr_=60XxmIfbZ3?3~=;;H#EDAqz?^T0n_Rl73yz)G>TB8on z>|-+$rPXoc*Z%2Yq<3uAj-~0?pFV#|>e$byI|g;n@`VMZ1xxAR0R)b*V)X)BQzU|h z5-$##x0X)4PQdmoLX$wVm4DuaaTUR}iyuMWCy8FbC-vzERO_>nTY*}<-R^}q-OLRy z$wIKCi*3r4_2K*t`n5_bL~erL!Kf{JpQl3%?wA6R$pjtja{Vl_;B?yugXwT3Y+d{? zE1S0~Q15w142`n5HOH@w%u)1HrOd#5{)V_sZiXn2rm5oK*w)RN<&h8ykAWAvaaxfn+GGWOcM4{{-#$FxVtKjCpzIP{g_ZD(XraH9T zEMa+azG@bszfjFe$VP1J?80cJHf5r6T`MAca`G~GyM3re#p~m-AvXXi!Kw1rQfpPVSg0Llj9e_FuYdQv}%UY3APj&6H;`{R*p*36u z+C<}Bp;zgY>Lr};hVTQL()WO;6NE1>Mna4Z_dSkt_z-sYFz#5|GTg8o-UIO~#fd!7 zV5=Zzp%2&WVZV)WFY3*@kn1N1?LR{lzy@ONP-JS*p!nlCHSYP<yTUtY+(bLDr@hzV}!m5XHx0=-^aBdU{xozxCZ{R8IU(Ajvh#GRy z`p^xhZr#6(>AyUw4F(nEUW_}MNkZVTk)f!}Zlb5!*)Nv8qaW%mCQAwdsJ>EGsvOO} zUw9dwdCO3mo9WDXm*<(><{?w-V!B$YraE-e=PGVQT~9Z@E*AN9p^3^-{p0zUgd6GG z3%|uXwumN<=V+{vr5Y?gBt}h})O-OT7>f9d_e7{r1OsSEeaviPc(QQAC=`1gEc7n| zG2_P0BG?>I{28T*a(^TM6I5-;GhiiN!z=mH zkZKq577+N{ERZ*9FFy_=A^J_>E z0Hw*Z!fASpCF5Pj(Y1~ABJE7yzC9vkYh|l1%OZ$D@Sqp` zP4$a2$nL9m2ov8RW!d~A zf=ikC^r^qld7o?!rYrBp?Iv2s#(xlboN2XNkne+mlz&cZ6Uu09!DbZ(#8`zZ0F!{p zxeA6Xmh@6Y&g4MM4J}C=?`=oATLB}l0HzAXa)af9s*O;hIn#03f&XpF)6$8u&k!h~}(x3wLv_|a1YZ$UTD#-$pn z8fWi}hDPQ$V@c9HMQlmARATwjpAd(#Tq@8A1$C)MWm|XHf#uaqm{hP=n-3p@0OWGQ z|106~?@$w}!Rn;;c>IG6`%76}H?3TCD1;|h6E&1ITWys#NP$E&!vRcs#^Yr|gQL)& zD$bh_kx*L@8P5>KX=M}&)Pj$^tZjhB+Ml)BD+C4rjFqt}748=p zzG>6Z9+(h(u%GM++Q^4vJMzPb@jXyW?#hC2h}*fJ1LBAl@7=R`VH~&JP9)=Hm)Fo0 zN5U5I39mUVBGv%S#I3q_`#c)_m1R=3rG2oRE8uIpq=}dDOo^+R#m)c_z$Nq#Tks&5 zmJv~Qijc+E3YMa*5cZS;k?V$$U*J1my%2yp2WTQysU9RoFJ%>|=Gmg_6?$Ky_o(m+ zT2f9;R2g)%tFs%Wuv%-R*;=b>lYnt z1ZGZ9Bt6#ApX`3K)8>!AOjX{HO_x8M#5rEkcAtqXzY%x4Y);vlu8IEN_G})|4X)FP zR8@*3G#Aojv96ZCEo?kBNJunqB_Th>(%E0)z4z%|-Guox{_;2A!{^tYJ=uV1y3;Ip zEBBbOsy~XNU{6 z{Nra83E=zLwT?M@?b0Nw_#dgap#|q9b_jlCQD2hOq}FngYwL!(!mSEVMPFV32|)J0 zdWaRxJK#j^)LgK9u7s8#hs)&^z*~h^Wy*ZS3*JF`<0s&p*cu(-=lG<9v(;o=LvjlX z8fgJP)=_)A*anFhv9XYIpt)NZqoroEDb7BCmQc4Ca;>x7IVhOE z@)yZWL8{=u{G+W-hsPtt#aVM6!a}vbk=4Qvp098cCFD(~Q_>>Y!#das7AT+aPYaIh z8%eI-_<#UEDD7v~Pi};!)_*YiKlnv78%KQkjKY7zsLT=*BICk{WPmO#8`UXG_Jh_J zgZAaGr#P65YcEQ6r%I0d-0F=j?r!R`(%h)DNKp zg@J=&>C+xE>wew^bwa)6G>(zArpv^DMZRJ0(p&v>^2dY|=`xog={vl*99~q;HpET- zA(6dvJ+HHAmyY>C{~OEiphgq1JRIaF4Tr*hwN^5y<-%N5(J4j(cJvP#;Q2$tm>H*b zLv-x^!MGvjh{Z_>P}Un}o_HM97)fFcdX3YCx%2+FIkEU_(EN(siXpr0@UfOPMi$X; zEuvmYL?13h#R5$Hx&>{TL?NM6Az)KZ=M1g~i1>FD=+hR?A{%ohA$j2SH4~iK8vcts zY-it8lrBiBFO9e(Pjm&Ik3W&xf@6%Oo+hCE5Bs}UP(Jlt7mh@_TYsr5pco=4v`+_F_A5Ql&>D8gnnYh^pa&6HN=^4N(-`J(*P1QhH7dL z`koAwdRB(P_6DLCIac@uS5toHhtf8*TU}7*%-XmE;t~gVUe3c=C!7(h@zq-!R<;;E zLtpnCHT2J{;#KBez5O^CIT|yspEafU76{3jVsPJbW~`K@axyThslG^DPW#+I>hNV;4shs?vvDtO*Fu#bQCu0C%`0_)qe1ltBs*i zOY6vz0lTrGvbAQwm(C7A0X>eAM( z+=0EIL-_cYc{@|EMCfF2OEvzo_VD-AD;@{h8`BG zR$(va)*geKoyd$vWy*=(?Los%=kBBmUG_x8&*C2875);4Ldnz|}5IL9$KAcx(3>OV`2gu-%AA(c4)7}>Le5U7FgmVF)7AcndsJjSr zN3|j-WpR>Akn!Be)@ML^23)ckeGFpXEqoYJ?ubGd zYMNJUulo_tv_a=mIVdJ?rwi=+>CTMy*jp)rXRrmJda^>HBsqR6u8rbZna|jsPB7}# zlLclY$5+(5Rjr1L97bE&Wh>0&G?|DCJ-l761rTciXHl{V%nSxD;z5`#7M^b2sY@Mw z(<83M#pU0Fi=r2a&K7pzqXC;!)!Db5grlT?e|r_+)ohh4-m^eB^9_Y$TV01Q$(-mM z#irRwyepz8S>_Zb+1*(=^*V$kLY~g%P}_#ODLpI1?0nSHi89l5DCFIE>e}*{VfJn& zHw>T~XEl)*lOu0XUPO7DP}F{&_;*b1Uz1D@(CBfOO4$*y$MIP-!kYkNEPsr_0++ck zjG~Ex1I4IKc6bE05-jF%;keL)Pt%fQ`oQw>W4j%77)Swfx1`Er3Hp^TQr53Lo?_e? zZ>dfW|l@+!vY_SOh~g09atoLuJcl3ITXkfOQM}q zh8UK&EJS_oy6fgit6P%axZ>P=(#1aW2o`&-+qCsJIq&c?E*EE1oY&cLW^91#qL312(9KuZd(&UV!z zeC8MVHlEHK?K*qYzJM%S904Ug?<42=XWs=Pqt{P}*l4MG0pZoIi%Sq62;NyLyc!Js z4>xXmHCfDG6Yp`*1+_6=Pr|rGx4FB?MzAGRd3{Dj%*X^s-5vm)8${Ge%=Ttu?=wy2 zrQPKZRMi!~_AN{JWNl3(#uvgSJz=sRDQsqe7CX}?VICD;X3V3vkz1JcStvj1h#r;D zGAn#i7LEEX)&ZoQX-t?VDdSQtU;1vjq7^>+UflmQ*EA!8{PYSbZJ0Hnj1VuD9x5F% ztVp7>t(^j;6O7PN*HfNuo|e zSn~e%W2k)a(>&{r6T2x&0ki~+r-V`mb1-5JEhDB*G$m<=jAXEje4u?+C>!=?a)AXl z7LWcCks?(|NOD}Hf`9Yl?M_0(yULRxxUVmvtHOy05H26V<6?BVBe)dO9nmp+-Tzio zs2|)Q`w6YaK!s~LhCK!38Owy*VJ)*)LdV_Ze4|*;4&Tk$q<6q8wXMH%sMB-n-ivzr z`1RfSci_C<8+}A8>lR!$l+KKW7f4W2W;y%5NJ`6dBGccdX&~PpHYx-q*&BaNh(}$A z#gh!cEdl2*!hhI=a~Ox5UQ&t7#Omgn)Y*F7HIH=5x zXp2`$mhL62*vZJodHqlS1B(-A5N*p~?=d@#VTV1ulX=8h%7?8;O!_4y3{dJ2+Yp<% ztN?OPzHoGId#^u`;4m}bfMQZ0YgXJO&YyMH^zZI55{9$1{VbQkg~{^CIe4dU(^ixf zNav!V-lhBk;E2HRVJ;M0Uy}xbAeznUO6>HD$>(Ldf8^0cCGh7w9bD z7ArOKcbS0C+Ft2)Fy4p_XpAgiKzkNb%}1q0`84y~9ww$xZM4M_4B?d4(ZpBCLd}CG zjpO{6K%5|@`Tmx-+uj_-^VdoDjz3&u=*e_+r6#5Qik@qtwY2=ElB0`U-}-maP(+ln z;WLcswVKHKge3_I3lTkY)DXwUAEgw@o#>9GgiWk(arghcrAGqCO|(w6wN;IFRQh8+ zzxfw}c~(h8HNBPFyWIEzfU^k$?+$nJ1GXY=9(sy%tQ`5Y4}^G4>sV4pDD2?0{XMdZ zcj++;q`%v&K^RwLP&Q)_g2F)JA0XRm6Lzd3|$cYo-9I+FCmCYCd;GlQ0guE1dKC=oNc^-TUpX}fBj9NFn3pW(Jq|= z`6%7Ywu{GUP=U7a*>%s^(p;9imAu^t)0Yps zZ$_)TO+5S9C277P7g_?d5C^t4&>N2Rj6@Yj(}1=7f9W+lRi$A9=4~ z_v+KImVFhj+RaYIv72&?b*!BKYbd_9W|BGc!DV%AuA77#apxC|JNk6`Km^Mq6w8;9 z!hgfZ2gnRBYf~VIA+n3Rx{jcXH|!N)y}UcBuRF|!o?nS>t~jzyA;JjvUT=BStQ53& zBUJ2Mzg3ym60xPdF+Iss7cPx>rzuFWkC&lMMWB*xUTux8RXYu<(^!8a6|Nn!`{Lh+ z0aD6KtmWa2R*vdn!g2yBdIY+ipnDiI;*o9dkiH?~yuV*xBiRiFZFtQJu!mA@JW}~8 zb(fl$;^8d*{V`pu>Y=PNcjbaa_CrA!C)WlqgTX`~?7s0Z9J8?2fG9tD<258YEW1)z zt&e`a24Z^d0JVc53PF_*1*Z5?wUdyV40Zsgf z{)x*Ku`1kHsYNJmKF^IVmVe1^>;edzsJ#*0$%YyKj z_vhz<$RBEiF$-%wXAG_vJdYp(*;{eKH-77#389 z&bz{>1#`iy&P$Q;0hw>Gtl^Z?q@na{cF^svRR5+yZda5#%5oTcD%|fpe|58b^87j~ zZCx?4dhZPIbS**{`wYZCt>ZpsGrqD7+k$Q9#R_|dC-w=>p&vUDSC=LMiactp@=Jq0 z3t<>AYUb$CM^dMv?^a&3Dw)Kgc#Om3$PfIfn4R49PwC}!+JCJVRXGOWTnb%42Y5k^ zHfRdE>J@VbgS7NeH&a29H;r-ASPjYRp)&Isd{{67Il75OFUQX3^#6xhrj}zGwp*H6 z@@~@{=)RLOBk9`NqjN+a`*Sw$7bg(TiL>tADhE|wSvvr6P!Kt@+|Ss`efv-P>8bw@ zrKsOF!Y^k^R(YOhoBy|cy#+n+P#~RU0vL2@Uewfph;z(_V=FYO5{DQX2;lMR z{k~ez+hJc>$X`k!=UPW9{U;7#W%&N>&lp{Z+N?*W$n)XBLB{t}eNl+1&3E~xuKS-! z=*iCcfkz3FXzNmPo(4&OUL|Krf4C4&cBX{~#AJ`Da0SEb-APhA?)0zM8GdAIojXGm z;&&E3!w2~-(kH^y>k??X82n}i5B|*LV$t0vyLxu)+K%|~zBf?h|7{ua87=-&a?i0r zC)M79s0V)56ptuGm$zUv8NlrC#hkwt=Ixq@zx^$GFBS>Vk7Z@NC zeybacPyIH7K@lbhflKWqoB~qkAur}Or4LIs4rj3axL-dTC@FWuu$Z=GdD59z4C;Qm z?JXmF3m00BY3v5f%_S%BT?UAnN{orxU5>M>&tg|IwC(TVKBlr92{Q-OyVk*ADW1>n zdJxcJf@W2>lb#sLzr5XAiGMdo*yk?=`Lpdw;D#(qs0}??NN9-_W_FGlIU3x_OPLM1 zu%O?*kVo7(?Gf3M=~!uK{H9SGWn1(uMNwsa3iQ8o%Re78o9Cj_S9}N|9fSnej&eah zmC)FG4|Fob{k$i^Rz*2jVBuA_z(#%?cRaUzTOPAr>4t6v;uUp+kh29b+@G{-_2PMv zoL9T<2hXw~zN`@@H5Zl9Q!aGXPW7Op;I`#4Iek#!>0&nwW+=`xj2_%d-9R&UWe+e^B0l#gl$JW>4mRDUVVEOBWx7=?&&M1kTI8&RaLanRvP&2WKugVSj}8b zotS>avfMWqe1Q31uJ91VVA@)*yCenA`d|*40?bWc@@psp$devue>`h*e7sc>VCdBU zl3HYZ>JRXYVs_0}@E4rke;E>*VFki%HjBXC``#f#19{_@%}82cgh**leZqMM{4_^M zQBCDXI}g0EfaxYgF&$HP>=X-BQ#pOk{g$1(j({t-WFI#hIJb^>qfCS)a5eH?LG>~- zBTaMIBQ3Wc+J8@J_5_O)?Qa#Yd&W;XtY{rZ&7GHktSDIJrIf9da4B^0F0W$w346Q2 z=b)iAwX|uEHrIy}uOatcJYX>wh$pCXqy)caR-A;W%FH(~SV6&W1HN~3%^?_`EO`<7 zh(_-l{UgO@FWN|M`a)n>#IA3C5Trwx8b>AlGzA;S{RnhZglg|cob1!cp%a}Jt7+4I zkK=)Au-HZ|43aTbR)i#DLTEtnZZKmHazc?hbrY(i=b;3 z6-ypD0lIu9P?ncVWas4BmP(;q1tvt{NXq*eKfh|%oYi^`z$5CSGbhxm1;Vm+p|tX2`v^$tD}h04J3lJF|9;Uo7RBP zMnnhJ#j=z=4zp5;lv(o68H)NgOj~x6thWDCRB_LT8o1YfNr)Li;_-uxxo8^fgl(v^ z1-_~{-~XTFHr0hp+koPsn(jR00Lz=i3dK7-$QMJzK|+c7CkfPAEZ1_K;+esOW9`}9 zZ^hEX_UahjoTsnb4+GD_LEgkSH`+D?32|ufulCZ(dV8J4{d^<^_`%r$wJ}wWbY^y; z%1sq@*vVQBmkro%yz%!L^a$dUz)+r2hVUI;}&WDf9(u%TS-3w}vgz0(j)7IJ7 zcX5p*^%{u;Z)LNZ^2&5b&YeN^IZo%#PP%$woIrBx_lVf{xaMC{i61!kouogHJ?WCX z%+Ff23d&l}vL9+F4~EdedaU7zD;w>nbT}s=ssCbB<0AFALV?+Naf4s7VCh$raXr{hTlL{eYAp z+uJfa@5UbMoCd=DX)cT3fBdA>!bGgClVknd;cq zoea_FcInl0U*X6s{gy^aPif`D*I)dYF-K`cmtR-PnZvTEVEtsu@I}Is#_Xeed!L6> z@N+gG_k0wa2}b7|(Sd$p$$~U{05w3$zxK`X0vG4Wn?91)Z;j55%l}?HaD5F%+rnN7 z3FX~t$rFsK!p3~^8IBFr(AFd+cN!$F0Ns?BbEM&(!KYe^XAAXF?eJwjB8Sr@C!hudwhQcw1{UC|<>M0EB5^$Wu&=Pm+h0>VYmUrRKk7cRnKN<^VyD^I%3+Ts2~45>HI+Zf^vpSjh7Y6jKX& zqXdacXr0LtT;Tvy`HDHSy~);$L1Hy#Lvksv(Hz*?{P68e!wWK4$s>##GwuW3E5^D* z=!G=!ttMDCS(iEbNmU?H+x%@;^A0EK!(+jO#`5w~q|^(VbC!(jl{Qt*u1TW7m@l*O zzBO|ep@Xc^7p}2(nsH|__!X$K1ze6S8vo0w%#I6U`$a#(3>K;?$Ph zm6KglrsvE*r54?&=?40e#PW()hnH)*mzrIFeYrC(i3!!JzB3nFL_x{mYanJ+I(r&U z*|jz(Uber~F3%yl;}P+>$p+6v7JtuAD(8FiZga7Wnb{pVsTqDB!4@_I6NBqu<$0zB z_>^BCp=n9yk&xV@Hhy|OFN7q9$blZpxX$r>w1u%9U<~jbELtU}YQ1f@?|HY0ZP8FtAtN@aH z?|8N3c%U?|YX;syj-$7<%5eMIJ2V^cp+wZaQpMp&BH708JQU(m?Mf=N^h^9erz+0t znnlOx)lulSC0iHjXVX>*S?`$Cg{n+c2=BM8z#he&SoucdtSkrYG!7^xq&2Tm-C+RD zEl@fueA_qSRVgZ<)~#66thQG&_f4w&-POwi+)+u2B*Q-wW+T)?c|MCvo4z&P1h>f8 zDq>IvOI}!MRVk)fd;zCYKL}0+3^jdzSe+^yyFemVK3FwK9sce7TFZ^{t%XZpgRm#G z4@v2)z`ehPAp)I$V=xjqN6uK8u@>_Ss&CCyW$tkvS^Obs3$Me9N)r&KGZ#iroq4}F z$B4lFaE9myu$tHGA$VpU;h+NMY|m;kpTZII?AgC)S;|v5>|JRCp)AoJos03}fJiwf zuV;}qZ~S-6cZxM7^uOILo|RtJxh7V2AKrk6QmvI#p10MAT$h$1+nO$+*hC<;!obVH z;Ng22*ezhd6f5TEED6oAtD~Ra%^fwDNq~UgBo1Tr=8zgfnZc4aa{w@UcRkohPAgTH zzMp)UgB+T{N*`(mM_tZ{>*T0tn@`}PDxE)SwX9|jYs5YqgCXq=`$%IlSZmseDCG@6 zga$LKwH$!?LX0l>b=1PG_eD8Djl%pw7Vc!f}p zU%NZwE?BoWx~q5DMiey$e;7iUaFwP8!&EW(xwR4wg{ek128d9}PtTfy&%A?t!5Vyt zGkkb@?5<R&W!hB~ORAq5fBrP#Z>w-d*R9dROCNV6$i#(;K?iYZWLsyUZzXKZNN2 zz^Y{8xPtG%z59U^3YBn)59#t-Fe$)$3k&HLSPfYQnVSgsX_ldiv6R?S#o0-sQK&(4 zicb?gPs(fH3aybzR8sC)W*>Ri{A#wXQk0g{79eMw+G&WmwuiMI#pjx6N>DB-*9c1r zBDer4$?Uw<9*@y)@>w+mbS?NQSzxSFY^daErZ)$hM0&{I5CT~2yPIa43o4qMm=$JU z$yU;C$v|>n0pM{M|AtU@<`&c2lL)?3h$;zGF@e4ox|bPN-)cN;Wxa$(DJ36b>oG@_ zb7cR(SY~sp2AdlQR;&xYBY^Hn0t^e}slZw;8NY7&dmOJI_GGK)q{~11Q8jSzI@#Ee zrY@cZ?BcqWGh;PW9YCCB2I4JD$FtA^42F$tK*%L4>@i16KfrY26{ozDC~I8aQk>JO zi7%K7)GAFkNrIl=pb}_ILpuyV>PSd9NF7GY4wS-;v~)#C^vttE zITH`o3*akTna+7Ihu{Zb|R_~S_<6| ziEkztv&d#E zECzzd> zE*6hhzRs%5Z*ru0v!~xd@dA@|ZmZOuY=*!R*|=bOx1!=t6%7qbtNxP!UZ!z`3 zs4=!{A;X`(aawgY%jn|H>q0jKX5WQ|-w%J_+#En3(>nAaM4_A>CT@S;OVCIsoN7x; zDbElNUC>j_A|VB;Hd?q+;aTZso!ad%rVod>WMa8gp(D2p8Eb8xm&IgBanUO1Y{>36 zYa$i*yKF_r-&2;Bl6g%bbINz|GVmh!!wu_1>pCLp0=E_usXkx-mJ$S$qr+ySghyzw`z{rqxOw$Hzggy$=jfZ|ue9p@XD zEu|~I54XPBgrDAk^vplKi?DDjhDnsZPzoAh z_CI|iJUDBBIB%w~;wZ7H$*CGDW>8drqzT($w2B7~iQHRCxRafSjX`vV08{vvSSYdj z%-HZMX`*`S4q&oBy#HDGh4 z>&?o@4c6&zu{hAhuyA^rU2R-Q?X+~pU>sAU%{cOm*_<#m%1%T^2jVxUR(rfHpAR>l zQ?a#1ReW3~9b$D~2S0I*6?#*3&bX%=fP3h;9$o=IBi%#43%26Y-7Y_z*!894^Siv4 z9j&!P`7*0P_PTw7rofx$;&KtKanm2|BWsG@BQ?6soB97KG}b;^rQW%q(~V;|5%9%o z;+n8jEjC)otqDIth19=;=F^Z2Jm}xHSxEPeB;>Jr23JVk1rJT>VJ}9~Qv)k?tqX-T zUas9*_~MsY`_>G#2?JmaN=UIYVvX)3aKNiB88a(O-L*wWsjh7C486xC1>bAQ%2G60%1WjdPS8@(_c}QBi1j;Ez>wviF;lgI%2Ht~-bJxVVi2~9B>(3zh8G(}s4_osN zePm7Y4Iw`|H5nJU&v;>fNp8daR{Eli&u}5r+EBR=GMH787arP29XAbAxQRV6WXpry zxLz?C9X~7&>cLqqH+rF9+}gi-igqfL7OnfMnXrY@ic-89Y-aiz!89cqiQ&Z7 zJUjs0fpL$3a`H$nU4BM61Ch$M?`^cQ=4>RPdDyxNA?j-yRw=Y1-H@zf{a}&jCT~C$ z$=-Mjk>wj9n)+O^_*H;|v?>G1kJ2q$Vj{Q1aDaIgZX6tZ_JGbXO|0p9pqdxpX}Ja) zL9zWNK!VG1_F+ru(D#LvHpnk;4{!5WA<==f0=i9@h;1eN%*|X%$5ALe^Y}$a7VcyG zjLfqKDMl`H!%XVunG>*FmDrjTgjUV^iYuW|hSt$SGNyz@qnPf*jIB#&l^&HCz;!n6 z19u8A3N1c}j{d0DcC6|0p+aptuPm%Y@vwkTx`EDQ7J4GjUa?#&C1 z)+0+V*n}H4+RT)Zq{*$E6yC=Vj3LQ@1>D_i4&oZSUNfWG$kD+D(}tpf$|3ctwx5uzrZmp}?QpjnTF;rl;p&a))n1aW#VbM#+JUpXeI zgJ%$De^*ECnlW%9pjHYVB-JwNTnZN51`l5|yVGp2AiwX2pgvgKmDXDKszlDv9h;dN z#OTFmD&RhdVw4EL;N|0QD4#iF)-yZJ1qKwYLq5pLAtRrr7;)7*fjBCY@Iw>J!f(I( zB{zy2u-)};J^xxWN|47%pJFQ{zXxLS*2%^c4cuHDbZ?HWx#S1KR8CHOnw)@^oq+b@ zw)Wzm{pie;ywMIp3g}q=c>U%ncz^t}7A>Xs$}A;mhiYemng{JDf(MX=%J(!&1B{vM z;7arN#60JLHskwI@w!>6YVn!#|3XJ$1f{h5a6}cs_x9jKmtCE>Lju0`;BI8D&XV0& z`;cu#W1uBVGIi{;hrI~17#J^#j|cY#G>_aCLB`MaIKVz!JogD3#)OG);y|#T9_B*$ z#n}_3;4tLG$2*pKhb2>+B}{jHJG4fWOI(z{VtV8>| zH;$Bk`@r67izLn7Hzyd!(_7WCKOg~SGL|RC|7aU+C)=!E`OcxI9gOijW>uy&+@Mv07sJo%lCA3Q3mjyW9@-;haE81PRL z>f3t%+FbKC1Lftyc+Z4%2g}_IU1VA#g@)G+ey|tXVkVdf3Av!JkP?Ai5Dl*Py$VtI zm)#P=k(;+c!Fnc;J{$gG`8nK7dIJJnzOTZ7S0dCyZ~>b0>%9`Zpqo)yDin=zE!~m& zBTIypCA>r^SQtI93lFh-UwO3|!M*T(N|e!?R!T$dURcZ@_M_ zeQO9Mq^TpXaracvN#^tt65}_{(6wB?u(-TaSO}x!#Rqx0b@2QpP1!|{~L=@M0WY=uVd@r+v$*lBALpp<7?iI{P-~NQp!Nkjxd_ zS_oHclAeU30EQ9KkzhIb9`N*nFYWgXQn%IqE^0Fy^!fKHtG>fKN{r zPG8tvqD#TTF8<=W$%W8s-^H%f!^V_8NKbTa%P2QR$qGjKLu^=-1FQ-6f)#hLNH!w2BF2#DpQJQ)QcF>bON zNmkb<32V4Zum?QLlvl5f;FEJp{v;S8lO(i@2o8RbRH(p|G}2OfBzR5Pu}86T0?oE%;!}$WN z*8~PH7XA^Y^GzPxwcr0}2nkUjIsS+MTNG8(SYg2G2D<}_VqkQI*Km(!uJ`7GOg_?? z+7;IJi~>Wdk%8Mgf3FUOQwXjqun;re416|V`p}T%`Eb-d`DzssnFZbSM4p6n^Diq? zGh*UKY3qfZ*D%~D7(gq%&l8SWE&gf15?4P>cyub+IlT}-PP`V8e&ulA28RHWQCKlX znMn7I<8#M*7Lv^Q_JuzMSUY}&5s^e1p zx}*WH57+$P!4r2iEdi+D2Rz*|+_^zWD;R`Osb5wA5?`Sg+S#yTyoaFUPOIga-qcp7*Zym6xUkZu;&llr3yB{g-)+`a zOcel#aTi^Iau3L6pR5iYvo6wc;9aOqT$$uYm9I>PTdHh|ZA=VxVCiYt8q4i;l1;~{ zUJc{Umxjad{1gIkufdX+Wy?(Bneu0hL;M(LV~RFY-?UE_GOYx?0D_PLZ!^XJ;oDkV zf#TX5AtSL>=3WICxYHtArpNW9{vS-S8QIEBaiAerj>sRh`AT!9p&>doL2J*GY0dE3 zhM*L8kriU-zYXW>MpdxK%qk1#85v*~Qp7c*;lZy}${_jAz2Zz(E~-6NOlG8OU{#!4nDR0XIXm9YQ4|jcUPTAbb|{j0H`jhsAV*#!b50z z#rWMpSC3q;7J3hE5BRQChyf}$9BfM9qVlKY#ll}RZd7MHGtezlbNk(TzTSK!8N!QF zXumm5_&Yswey6pDc4FaKT`bA2m3o!(m=>*${2a^Wr(hY3;~9AcX~8edIb-OYYNUIC z1gD#VlbrYcP{}wgorv?8oG16w6Wny`wh$4DYwoNh;yNsMl={lR3CE<6QprC}(k#K- z487ijA(@n(&`wMlYawjvx8rPV7R{3ejh>BFC}Upc2NsR{b~&EfrTCb;b$XJ92MhLo z02OqR)zbQuVL`r8*KhTDYt#{DIcxb_BfE2(lzhAf#nw67cQ>d>Q)M8-qfZ%yJfXjJ zt2#I?OW_nNil%8I6c_#Ib441X?yv13;T{6ANFq_Nq>>oOTq^oE0&s>dy(O%38NGtm zzA#C~Ak>~M^j)3=e*hjv2qtBAMhxaHQju@?ksvHhv}B28T#utgsG1P^8S=%KB7@K5 zlghncj)@Tmza=Z^&{&gI$xY8O+V)ytujI&YWHdc@RePP{SYN3+{CwCv) zC&KjU^+jsmV_*NWHrG>aTI&2PF)_m;&*C_UZ^~U(0tx-;L6tRL!2kwazNm z)JMQ>5UYp0=H+{SVR=dI~YNgwA!3G9~LNT#nz9xhdm#~n#hI=25f(`T2!aE{_2_lCe#SezZaL&(=OXo2om8plO=m!P-fk~u-3I}`G z7nhUNsLQeXUyr&*U+P`D+f!~KF)FbU^})a`pOs_&Uq=2+X`ha9HEJD##?w)bMl%sl zYy=v0`DYZd&meW|9SW*XyTM&jg-fbDIzj3)1bZYw7Lba#UC7bn+Vf)~9hDaq^~g%& z=SZsjiXw0$BwA6%?^ns->yoo}H~mlUmb#~9v8FFK$IIY7RSELjHfW?V64#UCCSdI4 zaz~?S9+*#%dNZu91y0dwH|XtIT`Z)&jvVr3Nx$Bl2`=o^{h~)7&i?MzN{P+dhA7HI z;ZmpgZ#j}RaF6{m+C_$~l73dQ$j0z49)d1UcIB1t8AqvXVaU-i+1H zqn{uQFGjsz$p^O%E)dMT+2Kg7*NXaMEWkQu zQ|x#6ukA?qrszB1U6lD>gqZz{dyr(3OV3g0RR7^Kq)PPs!E8XRwqosE7lo$TuMDf< zh$tPTeF38tqw6@xxR9C^L4ec;X;f*w$ed`zZVpZBodj>mzro9uVq8iiOT`gx^>NNV zGs4Q}wZk{%hCCKr(|-MzCXa-rP$72ksaK~sPL$-emdJ&nmH6O72>*Sf?7U{^M8rC# zZYqs)hGnx)1G~IxjdE2i1~?lV>GuhI(~oXCM>1*nNM6UlqM(C%4G+V(ecw43;c`v{ zmG-`ad*<4u#9_3 zI%`al2b+Uh@m~qV5XXu?QfCHFO5Iqy1h#|LwR|jhlx~4xu7BgF3@4y;8v5rBQgjj{ z*6A=1gbZecc25d|vb5{bMPk^Fc}5p21hAtm0SwF0ZQEi|4W;Qv(Q8c_*M>+QgTVKW zll>(OEevMbp8Y1kRF*JXTinK!cuK%+a+jLQq#LiSf6kj!>NV@DJBa&pDpJiX#xoh* z-yyN*5X>6ockeVw|J=4 z%77Apv=)canUl|P=7%zn1~KtU+WcF4j8`F#^$wYaUe4o+;%4=eXS;bIz7Vp6q-*WU za;yo_@*Boaov{;Pk!)aj`%qG8O5qD{GISH>37hj_Wme-zN_S{*5gb?D?LDhvhmz+m zR(#>H3>YDVW00Q=3dha@@?WOHf~;%!~8tvbGA$ z*0os<39patpH_Bhn%b`{a2)B=Ttx?U1L4j{e^q+p9g75pErJEbaT{*T?oAXm2x|sP zJz52ohg!~1FuKO1)Q;VH`;v_?Wu*LrXMsHWAs8yUcpIJFfd4B@jHd7VI+&c^uxXwQ zb@k>?JBut*#Vq$&jt(6uQyifQ)nHZBbRXM(KEsp9bOe{@%m9!) z-xawQ;-n^~TquE9`qJ5rvo^^=c74Vw%nuH2nM#`Lj6pRKQ!nm3%{(o?pcshM1AyHtatHHcnkZ|r zmNGp7RLe?lY>-!-y0)WQOiRv?JBBxlPSCGPmM-v;4dC~o+n+~7e^I_W;%A@hdJ`gB z57?FeA5dTYF^Y10@BZf10F|E9TlD?mU-P+B{%8Wd)2`CL$lk%{xG7muvF!XDetc{_|TQZC@l zYs4HR^9tHNsB^WFFU@r&?y2)tF@D?QNZ$=kQu$%skRpXRc9Q_AB&qn)e7y@^%8Pn!HT0NpM9$Bor*@vA}WT|(l1cLX+ zOKkVAccgnleRWd=`3RP?u?f|bgw^EwHH%1_?Fl8G1e@`XYQM4K4bIOva^(o*H^-TZ zcTheqhbxYyh6ZF%d{W{U@;`sSv7uRqw`*Yh}qm-g8fsN9mo(pa8IvuLX4n(*Ql@g{}%g!-?grL>aPpY3MRYytUZu z>@XR}e$i$@A;9@h6Ql$BQ9^h|sokn`ayjfpxl8ZIV%dWaE083ra&9R481dNv!nQ% zwW}(Fzj-V$TSc)J5=TQRJ;`~E(`3=l*(1Kkfb)urEf!PHqVmcFdwC^?8TmGd8<0TH z^l>4)vX8>`o@DX=$sQV;!BL8HGDexBf}>k?JwhhaT)eBaKVXPez`#H`p|DxnqD?f~ zjDa^vj?x{4&IbfR5AtJb`!!8+_GbZWZRU`&Kz%o`bZ9VeL-~g7lk!koa5r%=_VlD@ z9%C5S*wL^mVy=P`o<922JxfQ<{}QQeTs8}K1b z#8<)Bpij)9LwqO8sz=m4VaEP8f%T^%js%Ie=AMNw^}?bo8G9WXi0Pl|rWTvxW3fEX zmmexGXvHh0u zi1GdWzW?MnXs(j6ep=Ea6Nfv_4XG{s0d1C?US>gKr0?FzuJ`)qLtlPcP_8?xgx?rE z7vb>d-rHd;zn*?|EZa^6+D2-x1M7cwt!rLIoWEIf`IAKUrN&C~q77M2-85hp^a!<$ zdA5bMBjW0&);WZ4+fPk&1g^o+6Ocu+RU2<;%@uY3SwmEdN^k+SXQ{@7AlVdPVZgA z+|~noX83h_O^)Q@hGV(~c!qItDaf%e0pwU4#xD}833fC1w1EclC**Vip_=;XbJ1;IWl0#)h`r@?%kgB z)0Pj3EY&QrRh5h`e^xD?kB9O-kH4VJ z{WShhup+1D7vjgC|`XROyrh}+;N?9>6&Vqw7>vCh&oaxd2OHkhr&tb z9rR!4i|(Wl)5w!=nYvMnOFy618%J{)fb-X>PVW$TpH0AGms2TP(x@B#`%SqN%PF1< z`*W#I>7_AEz17t1v@lc3vWd*c1EjIC@aR9>4c2uAPA&r`_`#sS0Ey3%iQjHF0{G5k z^a(Vy$7bpa%PgVEfGVIIYpb9BfQ>K=E1`QF=wrjk&x6^-?sx4FjZUwo;QU8gI-&Nn zS}68n?=a;~;Fc4#ZBm69ju^3~AcKm1!mej}CCbPg+x?|l*!d4!Ilr2d*b0%Y{b>DN z(A{)DZGu=CNhTmLpA4vtXMUJ?C~tDsf0llUZpB@@i{kcnndfZtA;|mrrj>X^lWO`e zHEq3a_x@OJo0<1fky<=mTr}goSSg8+wmhY~rMWg~+@a1>{V=4+lIyGI@~{FRA%Tq% zf(BtbXDq2MeM4@xwj@~_lr^Nbtm%FQ#$eRvn?A4rlxU_^jOD)h+!dr9yCi}h8>oIHzuF=w*NO(Avs zK@VNu$p{i#RZvTJlrvY>AfU?yfK?^Pi2V`Gn{%*lC%Odl&tD;pT~lxBAVhDa4Szb9^><`}6~gq)T?w2PB%Wq> z{_K~kn0~Am!q-YWSsE}~|4HGp0gcRruNW!{yb1l6670YoJg@}C+>0KHz37Y5*j)1? z#-Iv*&{tD5j80Erlcp%bXs-u?u5&84a9dA2f|I;+;FO!JE&5#(p0!#ov$Ez|f@zEW zz!U_-zQ`eWarN^)XULXd(OeuP-g=Q$ksuT5(ATh!KDF%jajZ9_cL*&Kq|Lzg3JRo7 zBbZZM#_Y<|o1!aNDdhJS+Q%r@F!<3HKm;W>5Y%-^$UBMSs=-?qyWU;=3dG^CqJ1IlA|m&4jKSDJ4(pL~MM|qhr~8vKr`v>SB$FWRhWTyHE)gS8 z6FoLem$BL%4gLyZaxM)iwFpp@86_Q|7}rGD3>%)05mofN*7QZcNPX({hVeV0XuzsCoH7zwvX zA#g2N9&~vx5Nb@ZW9DleU%s}pG4dn&SLYV#>^?8%5Jpz@6DtSx8CV#2Io!tCuh}*I zleq>|vD4|v>x%{!#GA$f$i>fSF6no$TK=Xa(#%KMlz53ggIcE?!Oy^%LhY@4lr$u< z7d6QwqMXZGxXWsB?2`a<>4D+7O9gdkq@k4ONW;Jq;QrKvVQZ|i#J6-Ho$7t*hD2c2 zlO>~o_jbyKKHm*S0@4Fa<=sMx7BNpm{pbkbwSP$$y@C<{Fl|Jag(59l2xHtk zCqFelw;aypwaCjz%QDk{C9#gKV#fvjKKWGUhUn+tQe0a%E)58^I7uz;mIzf21N}1@ z{HYAD%#_T37Jt<8PQU0$!K`>52;x>zmF7O?A5g%b@?w`Zv_`_{5a8&!8S|}4uDNSz zXiN+b^LR~E7#gbPFf_AL>rZ<{nem^Tnfx(AbF+xEp{w$)Lkt}aijmaB>MU81!s@;40ZjjiB^Jmta!35YH zxC;%$Wdfzy>V!PSldF~Z67zkt&Nw6gqn>7T2lTF&D{xv})-Ck^%{`gGVq2voah34X?sKx7|JqWEosTpow zu~vkAIEYmJ8K*+iyjZU(T~HAkv7~($7#seLk3QA_S#`| zfBP%8{?VtUA)QKGtjz8&V>~*Ho-`9*_NUQ&Hc9GM{3(-f`L}scEj|^Jx#wTL7g<9; z<#~ULMm5tqGxzE$^1pS0zbpk!S{63<3veJ7eY253t1mPL`p%S;wYiP!XEJQrG4344 z#-2n;WK}UP`04oD|3@F{OxXO#V7fz3?ydq5%xjok=*B`G+n-ZZvFB^0Mu;>-NoYtx%QO#dn*h`LkY1_P#@cXJa6?&%I#iD0>T~T?iCgqpa55 zLJ8$wk+fppH5BPPNo_ZCw4H@&S*>@J!%aKC?Vij!+LY%OI(l$Ka5HyO*FpZO}O7Gv}W;)Ms~oGEx` z$J#y=-Dh4Wd)T5H2~oG6ap1h3C`aI|eX!Y{m2Hz|I_g~7WDqbWZK#kWX}Hm=3wRH@ z%H3Rm?D3SQY%^4QC95%nbLv*sKE){aYgOi=M zO%sUU$OZkq*o~{=Z78}1i`A8VKGvc8JfSrH(}$`yzfHYux(3ylUBATy{UAyX@QtSm zhCk0;0na!%h2XRIj%NpZKk2RJjFW`lRx9=brHqV3ch-zgnv52Ma$qmfh8@JS@pNZv^4If5c?{WU_QrhMC`U%m${MIYpJh8~}WqZT`Ej^Z_0!BHaZ}YpPOYv?;ARbp_f0Jm+gVq`&`c|!BH74ytMG1i&a6oi9<2WBAwvG- z9u+7ajPOA#&19U*-^pe0zp_J9bCnC`veN}_PxI2x28$xtKJ#1{IAO8>O5z2pKJ*;! z9cSMZksQ`Da_H0q-Ss-+%)2JAAtr3w%b0yl$gz(4yrY=x+24VGcA!;x^m6xItGsG~ zvUuDP_Yf@seT63OzFeA0u9v&LN1A1kOlk_;^0NIm=v7-FkZC2-Nv<7ps(=atKcP8d$MgLY&%=9^FUeLeH@7tYEl z2bU~3Wqr~`@JLCEwUH<@k_uJV>IMGaovThu3R#sVr-+rx+UeZyY1K^@H46;t_Azj1 zL)?iUM;%Mv5EbWh;hCtc11aNhzc=a~G9YWSZ2aU|dGP5Mr zrtfa=ymaT3a0Q8TvRnRi;Y{4@PSy6e%z^0A&%fr*JG#05af9r?)W2q5=2(Vtr@+UY zO2n=oIWA);@Pr)fz0JO^8l4RG=6NjL`!D|jyAC71-)_)puE->(s;Q263&~*{HEPGv zhtq5N#b08;55Bus+$@TB>X_S7=hw-Yb>uqExXsvZ%wjEtAdqFdK7UU2pZWt@>R{m( zSx^5eH-xTSU8howuA)Ez_KX&CsycDjtmE<64J|LN3I7-`@NoLDN5Lr|LPmVMP|Leh zeoP$cUg`TcSs6%Dpe89|sCyIkEdpBJi+J$~eB8(tGtAZj6KQdnenwC$IB*2#Ba5_S zh+_%Q+A~G=ik$qG!bIFiWJ#d>5TPb7zznK&KtdM*AGA;Dl@LF8A0y^N4UV%#mCdVJIvk zp1Ayo-9{HWF8V>mO(0!;0ly!YMRGRW1Doo}>BH4ZV1iIuhi4lRUEXZbyQ>a7*dU^< zmHYkVF4EKbKYmKum!?W;mA+_Y@$^m~&0B8}A6Usx^Y=x;Hk;KLLhTui z_b4ETDvdgo2_V`O=&z%=2{^G?IDL|2+TIr$U^$=<=}$nx*Fvd!p*L|cc8LG=LyV8y z%W7D-QRB`M>o7VwBl4{w1bV|d0MSvm(~ASI+0@p??&7cfs6H-ND^2u9K3|oIkomGG zvd3Gyg?@Z6S368P6bJtP6U+;z%*daQZb~#nyJh*Cdhw-CJbiZHZjc10g7_}!evts zws112&KR?l$yncfp)pkk9ryn&gBz%V?tm$rl(&)dvG=RH2mI1Lr3ie?vyU5XXsR*Y z#r(xn2dCDy%h=bAv(iI}^6&MwqH3(G3hSk?^b^&4p1nscf63sP1p!3hBB+ALSo6C% zQ1FxXMEeu{J%ZK8D)FY^v=zLD)9&o)YrHop!ILeW+5UNCY`cieepgjXy?AfWUSPR5 zGNsZ2odnd_L--={|NGEG-%eq8qu3HQ|H@*)Ii9K^G8{XJBO7nuZteweJB&{3@ABNYNsqheeI4$7pyyW#Ux9^zs(rW0(Z)XnkCxe2 z$r)SCttK8#GmBqS%nHmwrX=%5wK4FgUE_N8l2o?i3b}SFic8Ou0i66KPTS}jAN*7C zC!bO{pS*oa5+OEapl3M00n7<^U0~_@C{$(b3$L@H%;mg@3K1GnIHxl46M9|=U8de+3-m-gC86f z6A9+jWW*yjmikF6ng_2Ah!r@3@R>%UFVJ#Wb~Dd!L#{3q3MF-jO<5^gT2J>46NANm zk1abP{Za2cQFVcW6h4h`o@#6Zp{ts+jsFTJ0bMl~o9=oNb6g&}7HVQ4#DO&d5qhkHlG7J_Cv6$?{F z9I!CKlJ(G;8qcd8Ia#V5FOkQEB^#S>k&=5@bqOj=e@sV5YNXfR2&0Rc^m|UsdP9iK zW{L*Tx~0BdY;iRm|KiHci#7Cnzxzo<<{+M6(=6jWZm%gAD7&O|Oug^Jh{RS^DHlp# z@2)OXh?en)Bk_92HZUhp0dpDre}<)ReB;kEM7>kef|N-uPu@d-s2hxOj2Lffb0T;U z>Td0dGA6vPsg|qE>1mm})NaSnp^6s#y;HAAcL_B2W>(iHYrXuM5BOy}gH=oob-1KX zVkAK7pVmQwpwZzh8heCpimG2E!2p43D*qK`;QF&8UM!C1NxA3rC;keV>OFB$N|&Ml z?7WY{M5jt{m%UWw)3_wLX_8T<5*~lui7j_>4+5e)yz*&xVc>s4FOkEts>t8PwhVy= zEe)-`(A9MYS(Ikq3%ZS4j-TtJAQ(wEw1WxjU#vjcxqt;j0^ue0bgtRXwIbw$%m%vm}*T%EfSer-$yJf zMdM5a?Tj%6kzy)X=m9O$E7ILvsvty~; z_1DLKy*D_`J3C1DQ>P7u=8Si*_?MqBN3gj(vAI>?y0!3}eotEqeaDw-4Ds*D#as6y_!H9{>N9 zf)qISXOhxGeY(U_ttFZ&7tK6CYWG&2-7frhf$IvYC=da*H!ynxyKMVzkLVk2i2u$a zZoKp27q$zF`#dc3NlQ(1*sze|8Xqzk`9E{i=h;_bm9;sit0qI(TCxjf{1Rc`bvRM3 zENh1u-;Lz<%HzW#770rt780ny%~U8WVa{T#O{4%fK*+yMzN&0nws&zbWY{Ru4n-|n zFFsWZ9(BrGzESbnKh^<)8@z$x=y}h81bP@UnJ>>~&%GozObYFHXo#TLEo1fpz#}Ai zGg79ziCNGuV5hwB)BYx|#f-wUJ4#gI`zx&DT;^zVLq!+RMC4(XAp#K%gv$s~>L~jJ z(HIc)Hk2`S{0bBR%=pJ?CpMY)sLM#a{#s|K%vqbW;CK`hR?N7K#F*(arONA%*Y`GZ z>1ktXm#{81b5{qF2?4_mT~Pis4nF;O>;ZKye@?>~;=eE(SRvzC-cGE)|8rFmD3||@ z=`{7+7Pa1XN5T?vdJ%&8qDyI~4WXPm5GxgI;A|*?)(4>=709&W9nX&aub~ml|2o5v z(vMnq&mDK5aO!m5G73I19b#GI7OvG)K?>=**1PptB{20WhUXM?NbsJGYz&#OSyJTS zo6|kG?+QFCePw-n)>HG25B8rg>nnq##7K39N8nnZUfWx9FINO~#1W6rG4g~Ys&ASq zi<7dORs6Y(#f4DYGh%lb$i@4mGPFP~1o@(B9!BA9rrz>ew#s{{$$nHUC_lvQJuAI4 zEsw#Z`Zt`pduGZ~(H~#?rUAvBb?h>TI_)&i1Wat0q+lLt2hzt|tk&CMfVYrvA_)ai zJ9lcuP5iM9r&;ySLCi}I)#5;=LcolAzv&f~PXDGoZ^Z_;?C+0w-r0KgBsT@g@TCWW zYWnc2{N@W0XX6#BA6;@>mx&2FL}9?iq=%lu$iQtn&@h6Af+dLml_5Fpj+C)#c8cB< zhv^lsZn6${4VLHhjI+jH(&!DQR#U{{I}XG!rO{DUS2pus-LFyDJ<(tNlO} zw=kx)t!B}P>gv{s`8V#SbmH-QRjgj~2!HUYF~1qe&a5hume9ToY&u}L4kW28V~?T= zIgHKQd`-JarTmO@$p?^O?{%ICU#gM{aen6kUsK&(=1f-Smm>%P%CWg|0$Q2tfY)V^ z+{lClx^zE~WJ9Ol-06cS#I+$#;U{BbVoiip@pKRqooOeOxO|)iJt5U_(rthNDod^W zkI5F}mEc<@Bg8A$74u|qBHEdY&fobaJVMgiGTD2E&|-8V>sbZHJ|UWf*sUVth$%6S zXkd0qr6AxdP1766c<&hF(4mWuQp+iBN21YP`hBkg*SC>Ra<^c}b`v)V4H9rNl(O1S zm@HuWKqrX;gI;u$V#aX}T0$6dS>m(?wu0>0%nlc(rY<0cIg+I2+HMbrN3yMJ1~Jr8 zAyDjo;jXZ;Jm8CIIg(~}j0g(rP=bhUs|t1y8ev?%)ouE4vkA0*U&Qy)$j<$gp^L*( zKJ{3B2T?c-Xu#B9X7l$Zlr50>0lUwshnw+p6EfBYZN8T+^k~hFW{U0DS6O)mF|g-; z-=zw+mhg63^EuCGsf92xKYCNANsU8fRjk6zR?ResBB4{n)_+@i(t*u$?f@5XB>fMEJe`2J3&yOp@5p9WRe4_RG?+gHk%1rg~YiRF-ci z;4$GOaAqhEayyN+Qct@=(r3?r$mc@4iZ}B@gxkih85v|3J}e3M z1Vl9Ne%Jf)I4i0F9Kb^s!|OTVy_*NtS9++l;k`R;`dFN3>H3;=!x0E`Rk1S9KwD@A zCAw`$8*a6fQsDAy2Qa;%pggWsS^?s0sg3_<@{$Yf+1bmZdF4>rL9WRj{1gb2&)zYj zq&C!(uT#d|_#$6{emSUI!{}4j&xSbX-UG*YQ4mtN0GwgoRySmLVq*daLB62qYFykq z*k^twsrRhT!$6X;;)g}StRHQbR6L|sg8@p4*s~AJ0pyY6mx&EIYge}4tnlNQo0Dpe z;&`)r6lOL+C=v3hLZ|GeqWmuy6IGj#(D{h*6MzW^UL8Wgc(EPuTAk(2q;=w%Ejq2s z0ka+zDkR=mFc=sW3803LWR{%g(8dY;vZl?@tGHK-wmQu_`$`LI1s&O}UOacMM!yLd)H^3c1))%IN8b8?l6ALRV}5vIkq9=a-Z)Lo&@~3V;fR^Hilfh)#l2Mi;-G?Jz4|2iM%p#D?&5@b5<_ZP=NT1Cfqi)SVj zem2aNGXzyD`UQ1XO#8zww4r+R+`(tfg`DkN4As z$M&1oqL5O#el2axO=E(=Djor>>4^N~@1gy-(cT4MtEPszvPpJR9j@_mA9fy%MEyUo zjP`__Ct)?D2qYh$KFN?jQXZ$YI`hvKFe zN5sN^_9Bnm5T#^ILE{0>M2pv_l}?+#YpUvBkg)>p>lIZMe=6&s!rtH&}caN=y% zGl6jC1AZR9Dw8WlbQI*Z-;j|kD{cJq#Dz9j;7SE;QL#RFO4oEt3NH6jbY_sk{y}l8?8&g@GuW!nMKXd3hY8lnq8< zcbBF5Q`5ntR6rl3J8?xML$9)N)(SCEpTrJBPH}~eTuP~AmLJ%NIApx+4Q@u}sICRM z@i?avy-y4*o6ePI=AeV-*WRF=ON0^ZC%}J(e>n8$J5Z^xx7cKt{BF^aV6*T2h;+(O zuWH>NV|S9*rTTw@ZcNe(tf!n08v;?!Is-|unwjOHawTdHFiydAP)^1_E1oYE{Sd?) zs5r^hWp;$meQ z_+5{la0)7vy9X{qDZcnQYCWUMj&qx-%hA#Fd2F0@-TX10`H(~ug-PD2FHor1fIJlb z(VFi3@5sac8F8zBfCIwsp?z=w>?K6x;@1+IMwUnJF+G{c=x01ZrL0J&+DT)zD`v9H(8j2H z%@z;K_1OPFO$AAr0Xd@=0p9w4EGXE7CwE%{8%>vw}j zM-xs7SSJ~shQlgr@>+oA5o`@Bi=x~bd?bq-IGsx>JIQY=PdH<=##~NCnIC?cyL;{o zv?cwHzh$GF>Hc`|0e*~8*zpG@M;ER>$=R1-n)-UlqjFj=^kDV~DW9u7iBNgn<+V}m zWSukSJfS8}Fl0?gsMlc&c*YU63!IFyQ8mu!VYLF~y{h+%8i^k)+1_?O9WDTd8DHNm z2^xnkTnRO|tn_}Y^q=gw+O%g*JItjmlkDazT658yNglpVnT1>8I)iemmmu^F8k_4W z#wvRuoW!DGQFrro;Kd(op_GFe2`CQS96p@NzDUfim%rXflh@W6NT_!!)_vNVGbO=x zf{SXe%nFgjKNqS)YjOR5ZL(jEPQ>^tZ^>P5|M?B?xWKbipKqPJbn!*q)vzY;DOcE4 z*@={cBxXytc>pVc7j;b`n7BGri)}=&r2#`_{8#4fu4}(ljKM1uj zDb}_hzFDfP7OK~lU2{j`l`+F?6XS2COQDC|vc`^`mO@>+ZXO*YJRP6+!s#+@(3gvy~Bam6D?5FCA! z8OCVL!yJ(>9^0Pi4$~iLI?93_J8%qpK$p(K9^4O+x11StY^_-p%{m~_moi@j{(#+$ zC)GqucuQ}2%;14X>VpXuun`b@;(LLj5@knz+J~R3eH^Jk-EAjq0t}&r;7IH-JZTBp zSbk*?w3pMSVgz&xBF2gKZVjkNX4GbzrWYN@WPA3W(|XPM7=HA_@i4A4 z=5%M)pd*n}K9B&rLFMfu8P5~h>$iaK7HP&LZ)6nwhOj&Ek?gn-NwBim5Z;fu3*3Y+ z9e{-Ue42uG#pc)Scq~ti$5SkAC?l+OjFoOAJ9DrV&_F7Gb!uB+DB4y0h2I)Pf0kqy z3w@2sqF!o2>L_-pd74+(hu98ZKC$Rf>hDcCKm%hIU-N?0xJm!dR5DYVfFJ*(^PZ0w+XF}A==M43UXnP^!I^@Qrj zp~P7ecr%%$Y3=#qylenVP~fFRhp0kG@;MGK2Id^)B-DRTbCDPY8~G!%7?XS6JWS;`^b&JkLS z6D`k??zb=wJovMGo-g&BS%OYnd(kzB{kI%xLQBDT)eS6L?WkO*O)(Tt{5iF9ph~Wq zzwm%ul__Zc^Oq`&H#C~nI8gpU4jIL7O!m4mLizcPg-fQf+lwR<&DJBTgEZODgp(+p zvN$qK{-QUoUZwg9GeH@wt=~taKM;=j{?J)lMJn^Y?N_KbCNi2%784|66;tBqe3W7( z<;FD?qE9qx)B^5CUXfx;B^)oHOpw(yH8qEghnTc<49MV2tm5!FGJIlqDW5m%@bGE@ zqyPkk!=rvS!U*&eHUu~%nFRW|sO;#ZTVqOsPhY}u(jGLuOs>_qNzj-XXhtxT>6-l1 zRQm2bNKK|a4#T#Bmd&J{f*5jRw>A0;&@=IGKM1rkEqg_=hnJjzExG+eXs}_uj3b@7 z@f}ODoe%S+ewYNPO#>Qozz`@!6UCcJ0z2R?yA@*QF)3}{1|SUEdPH6*nWvV`y>*%RxGJsQk_JDD#Sef>T}`w2 zs(`>o$D&U1cU|N!b*{kB8taRN)tFX z&2FZg=gL_I?Rwe`KieP!43zeqpfkveRY(GB_?K--mkYE6C8z<}F~C1Z(#+H0^i_?u zlVIWA1)`tL3~F`=@p$04mn;%H4t9dD*CjT&M&{PjMv8V!sxtmheqISlo*~)PH5=rg z3MOaQWkr-Jft*$txJj6|M^gGLPlA(0(E_yu$GCfRpxBBw8f9{1@GLS9a8WBAE^r62 zCBG|+uzUoEjcQ|$-9$Erv7KXGztiYq%?uP)&y=>;!j8HEM!(#YA!4rY_^5Tzp75R# zb~?5=sL@4uI&A@t6T62X@2Z-q-KH_^BVC_2h2Z(Myx&DJJbSFFK9TG+oB0&*dD|aU z69aix(2{{S=sTy|?R(y{Dtj0vR|`UaHOA+6IIs{JIf)y^Mj{=U(Kk;$nQMngQUHbU zT#GDDXt==WGdJW;s^EdJmn*UpOLlWwlHbaps|y&|HBKBH1s6U-Ep%2vm6)MaXa0Q@ z5yK%=iwq(=?C~cg{HlH%Q=#Ad`EVUIFIDBW&0imN(@!6v6cl>Ke(eTN4k<5s8#KYy zIeEnn-lZ!LRvuDEZTnXyRH%(MmObzC;^$@f@Qzw&#^E?cAq`wQQqby4XSPimT@e|_ z31cfYUPr*{885__#)L-C&_6{gO!bIUU0)E)u;l{nmszC|e|vZ#WNe}$q#;lq|1r40 zwecMB!638KuMGd$FUfU!kW3s}gEQDjqnE=aA*yuw+6oH4MA0kodMmW1xzeD z5Ez%q!z;JLsUdqE!Zz^zJ{E!Fqr#m01;}4+Q$vuFFgwx1)FUC8fVkJ`8(h-bJ~w7Z zHlhoQ1)iSw;QM?HN$>xOk1HjaQ2s=ni-aNoC3p3(Uu@Xok<=3~bc`ihp-boLM&^`% zD&6Znl5e&hRLw5fs^)VCBI@@h9@CarH5O3JJ@59y^5n}M*y9MJ?h{{_=E)1RV+ZTR zc)@DH=}F41=;vOm2e3V`>U762P+jvT^6+4wV8;Ac>yXmeN4?jWew*28-DIj8ut_mJ z-azDSqVFaiAfM0RryiZ0Gvsmm%fVDH1kx{(3jaSkum>R#F0*%}R`7jH8jg#I_M93T&HTanRNTh8vz+)d&#B;Od*_ZJo`Y7guLFeuaBc* z*4Yd+H}wc1&?hkbyihSycbt56MsGEIyXHv>^M;X?nF}4}j%v|(kl}jhLHTaNCRUGl z5>}HI=nqljm3vd<>!ilWNq`CJ-uJgY)rlZ&JWmRq7DgRln+Qsv=sK%E$A<31 ziR~^b5E&1Y50Zb?hIms(YYo)y0=`0VYSs3mGiP^%Dr5OelFaHjftCzJZ$sLudrBu4 zno8u41*}ohG#Y49HCIzLTr)xzgKhuzU=2yEo*Hq?9W~E1E*UwQ3)qD;J^FqM?8&`~ zIZ5Zq%w}B;)y9@piOH55S-(w%gQcpuL$jnLy;N=!_>K$)Df5PUJn&RL}n?UzGUnQtWxFc2A@^6 zgg4u6Oq(-zRM{6ei}?iev>fpl%W>dM_;oE%hMidv#i!io$wP!IEWNheFVd4I7)!DN5n+& z{EGAx^OZ6WXJrSBS$JKodO((bTXSbiX%x)awhjf{OF|+6ul0|DUe2(jeM5}jiTd)E zJ(j+sjq7mFVW|3>^o*TjzXeY_tLIA_uOl;}zdq_T7TO$d`i40j`FVPgj#>ZnNIV?) z)*Cyh3aU%{`bk$%r1p$NaI}10$s4nefdU~UoM&dBFCHw)?m0ExL<@KXuzjM zeU^jyrh?=DmK-uXgjURD+S#Ut6cfeIRx<1~s~9PjS_#fK6ec!sBS_ANdO85F?^`eK z$H~_zdIAmjORYeYO(@qTwvg^Tcb}jzG)53$Hk3mt>w^xHh1NWvkcs+6#>(6EcnB+R zT@DNqvn7V=AC?tvXY{k+S}P=F=Hb>1a+8kpUwxEVNJzTNZD+}P>(2k?=GW2m!sURY zm4@Q3=|pAU;6@RORD%4hWmqiJ=^ZTpeez7P4B5nV}AHR z70rpB+M!}BV1R4#YOuEfTa|ATR(x{K>56Wn$ zx;rV+%UsTfBL=Wo1puLuS$Lb35?|QGre^X6m?Wl*-S3}FGXg;1?Oyf&2|zW&$BxKE zK`rH#vKSA`w@{-fbK30YFt^vG z86OdJFS>k{#(BG(T6Rkg*2tGQ_fj5XwbivExju@@Mhg3durkLlP<4DsBYg$RP&&Vj+QG(3zGi6~g>~v#w%U$9@@xm_Va%gEdTC@T3C*Zuo z=}gNkz#0(U8V8_;|Jols$IR1#pmL7${SS9dVAAqG z8ku6Qqn41XYUC`ckh&;L9wK-!Lv6ujZ=aq-PyDDS6A)>_wuB*nRYW2(aTv2OD5UgUaJ&g=oyyXt_i}dT7VHq-K!q)s*uv?~_)Q&So z63TqV5za>j9-p?h63_OUmKIcuTZ^cvbkEms9r$0Rjm3fkY-fr8bkmWkwyd|WMv2&t z>}!_o))iP!wTvR;nDtlZ5Hj?LQnzXy&@7`F_WZ9Un=Ns|odaOgOtUkhXDth^tiLJg zHfeVoeobqiWC8JIngQ9ec1<@?EO`wu(fTX9oM-4HKjQp-gedoDbYR*ksHpMBZ){4G zVK9A#oA!2a3v9g$N4cRlJsaWn*vv05yt!>awnhjGVujW_qBjcb84=;Ws1BVIxEvt0 z6+aq}pV_@eV`6(tcNOh8?{KwSQ^%R(sSKOvM}qP8LgcDJ!a%Ei=JZTZSz#VdmdVNA zjB)w>e`0_nYGZ7<0U{h4iC0U0lSbbKpQc5y?jf@xNTA3`?&zJH2#x5f(hW&)1oV?t zpJ`XMsX+&gXQe&@qwoyN*KcqN^62(WF8E=nmeu~>_6rxB%D=AG{{(ad(mrzC*RSi5 z6mpNzI-_Wy52XGv^59P#2r#Xxb6Mn8v67U=jKJU=LCTsDcTyfh)2u-fXQ6wV{d0TN zCHKZ!V%$&r!F%XJfai;FKz=KSrVFrrx|Gg27*7Tro5PsDuMffWvc&@t>0^~t( zsurVCPxxSf%~O5BBBIr7<4>di`Wf}iP(!GBx^M>_gww(pBG3ii-_o+`vbSOj5u5hi z6!47cJnoB?=n3pKeATNvLz=GL6*)k=Ks2od{G9#+y;|z&cEzy5M%t|SE_B+71>VE# zhgkESd`p2V3<3Fcw+yei6OQy)pQuHMWi<%yKZ^=lQDmy1f}+ImHamvCCOZOcr-rB# zNm&KF`LNT5KykCnJtn@Bx`F^koK&uO4a!mPL2;AnxFDBjwDE_=LWZd!=)4Ft&$gwk z2P=k5X+o4qYi)!&Q0mz+Ol@?Jhes*Uu;XvseNlRJ@$e~FRz+n8kd50UPTW*)kk{ng z=uOp+t&bgAw=TfqZCNB31!1%BX5J3A>^EFV>&#v$e4>%#V-*|}2lxB9cYDb|-4M=A z8#gePoCJ3&iwp%xUABApaDSloxlVfc1R^&yiJHGCD6jEt=9A)<2$Akbr4Yqpew8CR zupMD?I5^HJv}HR=un98gGNE_bJd&~!oVeQ@cVnwas`e!ue7TL10x||IgcugrSAm%l zT6C{M50%xEPXx0>0pQU1U~csJ9)5c`)R9bsTC=I-{8_h58La)CiqRL-yH5N1%gOmG8`}(cS}2ok ztvYPLuF7nM^~eGqW+YbrNolD;O`AefJ$#b&^&I+FJvciU5DqFn2n$w_MawHCj%tmF zT;@(AGgUOl=WzLW^L&CutrzOy2Nidg99dT_VQ+-j%Mgi7y2$CK-kFFG|&WFcm?nKpJLhf3Hdw z(1`%R#v77Gb>PXFL9UQRw@l!zb_@-`b~(gXP``9V4c`lJ!DZ8;gEE$Tl}A}tvk?dB zDKddGcGVeh>P2*D_H07)%S;veB;Q^?UM6lJ9D((MUi9Cw3ZMMIv}}4JET~D#U3`w* zHC7(CjR$T(Y3A5i7f6iW=j)Txz5t zsw4zAp|ogRc3VU?>6*~Y4BuIt{}f!h8P9K*o&imz|?`I=Bl`7Fb_ z$K$WliW~Qe{odLYNj{pgYuW4lST;?3X+^y;l`I;Ed0{_1pSi+0ml#dw7uc7!i@eQ~ zve%sLu6}|~&Whg$$4eo4nv3rrNJmem(T$t^e|o35<%X%bW!k}FJ9W^h(jsX!%}ywY zjop%f2F@EBNU$Xw+j#{9;F|Sk9Bqx{aB;(g?xm@t|Ind*=AJpJv^?je3}NKGFIa3B zu;}sl>63FX8+wMjA%ipR1^RL4@Luu?#9hGJto8+^$eLSzw^q6&TDZDDN&j*~JF~~Q zh3IZq>Z(?_=K5e0+yLMg<0A*Aj+sHs#??33S$MqFBgA;yHpw{pbCyQwYG;Dvmv0q) z{vi}LkKImSc|I=rOF#44mj{GN5kKc#;&BnaN($}ki_J{_^FG?WjM>hh8Ts&F1vH}T z9C9K}pr$7hg}k4P;J#GkPsqBc{r!N>3K46YDljk`a-Gg0_kJ_aD2=+q)#Ob4W*m&|4$VNQor!%Unn zvJvYIErm;cjjY(03a8`3h!9wr}^Cju~ z7yf#uTklx7{2X)X>=^tVmBsGt4>Pl}zF6E5eR`f%oWl<34%HaXT?(xbYf$)Mq+WJx zha<3@uL8|}py**ea+JZlg(R?6$g~61?t-TDxtyLi%g2QP^#U8-SS1h^ z+qn8*cUF-=84GVa!9?a^X!C?o1~GEHsNrGVJ%Fw*!;gnd9#9biZ~jnSAU7zwF(6-aix$B+j5{;BNyjXBzS}O|*S_AV;!xN32a_?$R4;z5t~@6mxc;`FoeiOG8h7LeL^`bJHu!JF zkasJq1jJ7sxg=~o=~dhUYK`B(Sv$K1J?j8#g&C=^c5Z|8G3?_iW?OkGN*ocrY)sGK z)MGH+<}vKLt5XKZ&h~y;t&6m#=*1bz2RBttZ2?m4#LZHXe~^T} z!#SYYK-DZy?=)3t$2En45gtAEDTFr3u9*m3Ld5g^RBQ~?WVb>(%mUgY$7~G8pln)t zzmGTALt*fA01^|AgG$d{w{WfSgJPc;XSw&uk!CQJA~FjSNQL~RW@n#lL9DLH+r-Cg zH_Km?NSav@nmDPTm6d}Sm+lm25B|=PSdF!1lmBm|?L9k3`~l&h$^sBW`8DKk|!Z%U(=L$BGkNn-fbJ z*7W~;-+z{~x6v_g@z5$*!#dgP=0hDiC}`wLGbbodKH&Y-H)?ymv*r$koCQ$Nf*Ds3 zHBRj5;q~_Pd191KCKlgZ!PPu_%{89NB>I3`0~kcje0|5b8v;+9^!_5Q9n^$a{E%Cd zpoA3oi668eHk4GA*8A?=TQ%Kw4d$I&lC{=&xS<_7a()5fO)h22f>n))s)AqG;aF7b zV+^r=aRJlI%kA$+-6-kT5!DZB&gWL6W}>mKw^`lKij+H38XaGJ3Vbufur6FRF8#LQ6r>JmU7=I)wpp<{HXN795^WsG(*UHRfLfri@#YEH0;|#l2Ild~lHf+o z(hZqbYb^$ip*Onc)(nOyU5AA=@Yqb}pm^eHtw^v5exwe;*9ZSiKpvvBTXU9;!RBIt zEG09A2U^uLWfe6ow;(PbMw{AmmGt-KNxpCnSYV&hb*ns~O>Daog>rvcqpZKC!)`rk zN7x-|?cCQ8E)^E7tAM`)B7rYtK)L;mlQ)6WQOw#zJhbI~ut&)*n-_*7>WaGB9Blf* z6v-k_G7YWkmA!=8Ne2C@FgS!$QWTUN! z@oI)}))v!)OotUDt-F+27}lbdsr1@023}etah3BOHym!8ukRf3 zLn@h%E}sV#FRt$ME*5gYUzcpFDo(U|rJ~z!U=zW01b3~nh6~c6Y1%7-(2-leLFKd zKQ9xLr$|Ux!w^tJzLLLP;syTgq$xpnu(Vq2K7vy6gw&PD**xCIgFsX$)>JUQt^W0Y z(86K%39s+PLWMu}LH`)a#ob%!(L&yW)a8o~OSpxHGaf!Jnzrv{cdfSf+yW|ybu&=6 zHU-cYj$?zn`*LHpT4DK1XBMdDo@ePf%6wh`SKyr+_6b6!o-WACo&Q}Dj^_A#t3`iN zTPS{?uEY46wNa*_0DxLIjHrN1nQpRqF>UV@fwnW^UE7LLDC51vyF9c`tf>%!Y7v%X zQ%(d+MIMZv*2|>pLx{1IcmocUd3;@5SR$wRr#2FCC*Qo*B9y)OFxzFXTd93e13z`W z+RGrTYnRLiq80=<842%W7)g%A;%%(Hi9b=iuZ8(>B7N2C-1`8o^&zGYOw%jm7HD)1 zWp%uy!ZNp>^YMWs2&MF+N87X36iIB0UFhsIy25|HA#-T;^lXAkYeRHCHM>Zh_bm6d zJ?VhF#Y`K40jv0ajzLb{4rlj1LZiz)L@KSMY4N7qtiU8rheY4;Fx}1I4c8shE>I5| zMA7e7?rG1#Rm;^91=}dxG#mv*sX6RrMQYJ;fq_FNOEUxLFDE-ZuuSQ)`k%$q=k1Nz z#zZ+tFnzzLgZlRY+}VfJLcbJCg@7ZNWzX1Dikd3BW$nD+1&_s^vDz)bg{d>K)Xq2$qr~~FATWe zv?^C&RFRkAte=L9o%M--oOrY4C3q5og(}Yb(9SwZwEk|3Gp?n=sNy!dae}!DR zl+nhRZ`q|b09@LFkCQ<*Xv}IyISFfrL|x8q+S?D%7s96W0N^0a1*ZmsXBcrHxOK2_ zJQ>`QaEmI3X9i90 zwQ}LfcS|Om6o+^eb{Uf`eHAr4UvA)&GH3`v0ZlmY22Sb1t&eaDnuOOmCC}q>%lzHW zfoA0$v@msSm?dzt%s@u$InQI3G}{y%t~G>ennUQv?2XXIwG=_iy8?#7gqrdjP=A01 zTmm6s^_5T*1XeIY?0u2OkVuJp<7-yk=veXj?TJ_mb3Z0kyw{xn5|VLp7RMtRM}1D= zR%zF_uI&EGFofTy5?70qgU)3?%0vYoPXr%Y=6nti*C?hM>OV{OGV)j7Okk=CwW$25 zUwqEyV@i%&AT>s8?eWy-51houm22aF{btu)>LrCcnH1?N>v@qhA9c_1 z@y5Y`EkXP2%GgdQ@P{6?96EOU>nzOPrpA98MQi&{qLgV@Cx_&YDgi34c=By3Arpy924Pch z5H=85SZso)V`Zho+J*C!82rQ$o~Gw*bg{2^5=-;gP-kq{o1N3KoXnbF5huQ{*p=2pqEcS0WJC#tUb14#Loq(LH$fv zmvSqfDw6oC_4fEIGjBo{Z>&vAhRql02Xd_kB>{_0sk{yeq(>#fDcQ+qZa7Xvw%FIC z2`E=ba#G#Llt0imHCJvK{vW>(dspRF@!sQ=gB3`s3QotomFB1e*L|w#Ow#lAUP{s4 zvf*flv_X)bBTxCb>rUo8iN%g1Y$B&Snhj$%QS4iiq13SWurL5m1RykBGxnv6$rr0r zN#dQZFZ1M&FEH$W-(b7Nh_CK!ISU!jDy9*G;GZ_ptOP&#{3dl}Z_Eghh2L$4Epz(o z=#dCiOR0j#Lnl_3x&;;R3`@J({sU1wte747#}HCg&Mlj17ow{1 zT$6PVPA7o$jnne>&$lPQS1L0(z}qf$y;=+DA5R5NXKUcIb#apRhamu?D)z4sT~==y z7D}mHZyBzS*Zn6OeI;PbaL{*idi&{OOXj@tv4#-lG@ok@ugW2A3&MyjI<%#_eNo-=2HT_Qoy!+ z2@#VN886$&{z`UgiZuj0=HmA%Jx{coS#B=!CH7c>ipsS~lJA&9*QH_>DjODgV zggNI~q);1|$XBHrZTQliV54=mI8p+&UVD5Zg?TUMcJg)qz!xpmczBJ61eNKcOdylC zv2CPIDb;ADm#{269p;?@hec?xyl}DnVfD7Z$ep!E)40J1hh`QSk*|V~%$GcFWQSR{ zHSF_Bv0BitU?5?nNz5W|Wzj%TLz{S$PBsVMsOw}^=KEUtG>UZU(0e{0Gp@d{&OF65 z+%(G|Lik@9yw+sBw1d(j)anFl2OVd3-p$Jvg;nt|L>+eSS=tk(d-DY3myp55WbC6D=~Je=^bw45;>pzYTOeX)~9E7|>_Iy}DBmnvz-b z8){=SqC(yYc%e31oN5RW=dTU%Bw1*DSLKU>FGi~og#})qB4_1X$&p`N2X={C_w4?? zDQ9G$0d7i!vsnJAor!?;^Kf&uzhPdzJ%_`5ac&Awrv#@@P@~))a-@lB zWmvY;xJ$}CEhPA!*VteMwYK?tn%qgALlDniX~d+<%fBTgCmi6BAM(TKK_hR`SJW0T zFHb8S7plx+H?}~sgzJKZd!o%Q^+TMo$9&(H)$jER_aacN_=FrHIhn7E2=~>kHRLyg@_tf% zpf?Re5A6}lqH<=Ys{<1<%z=SXJ(@ZoVmA7&q98=5|s zCw~D^X7V0>Xhq!J1$m3Y6yM7EeyUq6k-Prhs|ee6p9PGm5>Hz-bg&$(gIYRd(Jx*k za3gwNec*rBO$75MVWo^}jnwvK)q^wTE;PJ_xQ8v&2`M8AmQf*MzvG^I4fSbuBp?-J zi7^YBJ%<%Npc_7kFy^1mj)0E4yCo48RX^%?_=x}Y7ec1$Tut1zTTe*5)9>HC+=`u& zE!hYJ4Ot(4__P$h&Ddb*&pR7UN9qXXzV1b$P-vIzNbL4n7lDg|RKyyv$faN|E4m_n zwQ{X+#H>QjtG)n%_M0@}C~JGav$|1R=-T>rFFJ@d@+ZlPG@}z_S)p!ni=0|B^E-$g z%61w+@xvEjAqrbQ;c4*j{QnI~rCR9yEPoFC%Muw9$Cg>x8(B9 zjOMGzgNv@aD>jm{i2p7uhaIv#1G?r>z1pOv1z5>XQa|g?f5|f(fJCMq2s#W9dM| zp}B6k;ziHIucP%X#UzS;#nZ@U$*Vu&94g1~-GphckP={1sR6Qi&hu8DVN5P(-RVui z%a$zEm?moNp^{=t+)naASWl1=jW<;j+*gyVz*D7ahlzO|IIVCd+T0 zj3eNybk$bYI>b+`p7;06)nSQ(YR-TrOR{UW4a!jJKchYcT4rU;AO}EQ%TAXe6HMOh zoA+J&zNBVq*2Co}izm#?Cg@~%f#na;A`!8V-wqc-1>}PIZy!U@7^psWQ9FxjslEih!B+;GAWL$U*7mja6hG4^iZn$U1ZyK!I8!#^Qz(&?e#HI=xEADhJhM|@YK z7{_z00p3M6fS|NdQIG~#@OrMR%OBT6I^P~@6d3(p=ClIT)pOdz?c~cdZre-qYAX?{ zUq2T>+F>2ns;)Z&x(kgJrOv-xhti_1Lyh@r4*SNM-4iN=G5eS0HX?dAuNf85xnc}N zm+e1$-K*Vy7|y2Etqc?pMo5ou<51Us++jf#Zs5T>-k`e0pPQ|_W3U9hTWp~d9MK$& zC{5m4RQsXtueIqAQ!CE(ULo*?R@D(dxT zHY~DxVOU_e2JE=hVcBNuY)mKYW|t3gS`smX$^HdyQFOX|VR=28o5VrV(TTL#2M4gNywSj^E)y|Ie5Hc)XSIcN9HF zWoV=Bwn^ZSq$VX4W*U$FnoFBPG8xc+4~a2n3?(+Bwr)p)JoO*?Iy@3Eqey4a%#G>t zMa>H=Y!5r7>rtL}j4)K3ke3mygR;^)6!OP#Nv^_{0qfB;Hf{*-92|wId&D9{=$Rwuaq~I8n9N8au_c%I0ld7*qNw zA$J3tM4}oT68!oV&Ytu3>Wz0Oe#kd~x{%VVYQS*HS>!(i2hX?L#n!|s1&uWaLT*^S zydx&RLEKJpwKW^qwqq$|Usrv79g>r}SAy`gOkvrrw(tkjP0LJ)F{z z%ht_8Q@wp?Cd{t#$FSLq510yFwJvv#_fu=6@kl3QY>4YFAA!-5v@(n~DThTAVL^b) z@GSZ@>}0?>-|x7*m>B~+Pw!{Bdyk6(>F{BxX=q=*Ev2DDSn>0 ze9fKX@Sj$XjBAj11sQCM?)_#6Ck1$(1IYC7x&@_Ja1%ZC))q;0GV-1)plv%UGW4g2 z%|X=a*yLpy;3F=-BLT(eyzW>q7f>2OmD~xDx~O9{=GW6(8vBqeD@kc3Y6piJwv$O`95Wb-`9?oP7M)h7V~$g@pVU2&_}VNqxad0Fs<^lrQTBySM2@yly` zoLG^#lX${B22xSrHDB!8Lx7e!%$`){i+wVnnK&OpbaVgDK1CWj$Ha=nagIUfnQ?ih zjaJ|RZF5v>{mSYRKdHO31+zeC=PpMJ&$t8?O+4*Pn!Xzh{z?fpIO#9YifD(wq{cbPrgqcc|e_6qo>KBsV`*W6Q)u!yqnh6|MI%iXRa9M+%lYPY`e!72citB zB4;PNmW_A`bQ|cty~57_DtfdpU!sbVCV()rh8KwQFv$IhGfN89cXl?~(D#Q{uhXeW zix>pORF%tNdz5^<#A!a7)qhz{`a@nNxk8XX5Xt#OPeSRx2KHV+z$JWe+YY0rL5F)Z zVlZ9jg7{NoE>Dj*y?}md$_UXMU}D4sCw3LK6jD=E2PGNY-CjT^NmX;u*DUk13dhh) zjdS{$YHGsCCcIV^id1QRT|Q^{4SwO4U+G)h9P2?mS=4)e5r5PiU8$8^v17KkqXovb{WCOgS!lwF=~PH^e+C8-j_X z)5bVKlfP_=CP90B2++{R?0mq+BkSwPm%9RCd;@s~2)(o%{!;vly5KPkyweJQYXzpj z18|BdJG#|Tfjy3ga0hE zz_I_qu8*NS{pnH2fn2b&Y8KE5Xj-jPMOx+Te(|786vOLsY=c5|GT-OIal2x)BVdL0 z?UV^njzT$D56R)H!;Ch_5mX<|l?d8y`(g+nAP!~O(o{#}wwtOH$sxx;c)3L}u5kLl z#r5cSE9J0*a{@inT8#o0lIaD>6@CCeP0#^gti5`f_aB@E?Er$s4Gst6w!^4P3Lq?{ zg8sv}8iurQ{B?Jt=+9M!ne@u$q3urbPiEm74X;ttEd-&BuaSeMVX~S4Pe&rr;vKkG zRY4FeYb;480U-&{157tQKh81U?SZXe=F2!=>hE$aTQmVeHGUL0zWkQlHYwc2eweVE zah^ZX;&RZQoasD3X>&);FgMQ&LgM(VeY`@@wlT_QfXmHPdx}5bqIX^IJjQ1Lef7x z{=4jxP?{}JW|jgN6D6bQBKv6ywk0sLmE5K#O)TC=ir7x8@QV@Z3uujDKp3$(zu1)v zR-rAG{o)5wIg&PDz(DSn=xYo9^?fM4wd$}1HI*w4w{*f%0;4lxm^i>Jw={(_|7dLbd`WHPi5~k;bf_Ypsb03kX|s zsBsI{>({pv(x4$B6__S>w02$|qoykd`~|Bi_?Gmei>OvLcyzMFZ-cKA9u|_0m|jrAEVb)8_=SBFlS`lai$Y<&|~? zTnb2QzFZwv&YyzXT*5OYwp-X+=EuCny)C#{*&``syNY2N13>@BfB{vi6jrNI)={2k zJWcC9G#-6Y@jXl+Jd9q=Q13&mMM5Zg9e0Jga4^v)vrwj|5;PNtAV-X0K0Ev~2T^|C zgs7AH&>iYh1jhJ>AW86MtU%Wj_PmeuFdfEOp~|BZdHu0ANAi4B&o|L>WU`E=wS6d^ z>i|J>x(Py9{gA}pHSns zY=Vrfe|s_&Ryv8Q2%Rv0Cxr*?9duPKDz3yOiZDjk)`66Nt-llw;zxH}&tGR3aR#N) z6Vrmh3-;^qu2>)klp?^I^rO7rUOw6}}0D@`BT8?}xr9$BVnhMcv4#HuZn4s2e zBg&+1WnxGb_aoaNJ7%1fF^C8(cYTQOB6=4J(c50BW=VY(2i%&u-fYk$`x-3Rp@wM( zK8W)M?e&!K7ZEQ-So=gboYNwQXhqn<6NR-snA39)&q^m$6&NaxJ6y8=i)>a^$rb-) zbaf@$Ga-8^3b0TB2cGL2eIRLKC4|h4M?Bm{&w=PP9O|*1!iy3udm|tDis^*H?KkBz z)ZFU$w>5sQL4=w1t>d{w+zqN9`=P{D&2lDH^;`=Vr({MWLQPOcup+8?2F1T-MbVVV zJ&U@;iven?W`g=7mpsODVg#aZv% zOq>``(cMf@62Y33KP;Ygj#}s`R`_#F*r#>g?i3n~ees7bMAa`VH>@fLXyndU%dXm9 zi@>-4gBdba4_GKRcmIi-A=|FXF7e8A)EwHw;4B3M9Iadk4FbuC>Kh68qEb+FqFmet z2i=7Kc@+Mx7i%ODfWxa5GjsrY3V!1yXWhwIu^wGdxuilKbs&3N%)|iw)b#8^3c2Hn zlirkB*VM*o==;X<18s z2K(ob2xg{JBie7fcJE7MeiuS$I@BZPP{w8=Ik%NyLk|)^tkdO}+ofvaMY|P{HK}yq z5b(;IovHa^!nnC#qmj;4H~+#O=sZV4s%rc-arMI&dn@PHtw<(u@7){P7kIzP6|D{Y zcUmwf4=5jdLVPFsj~kH0QR1g`r1;{Bep;7_*g`WbQ=xs%BWY$-qNmD^?(Q3-5WWf_ zvxmhcvUJ`WpcY{*jzSq|VeZr_mvVBK%lXD%l%$q6YLN2WVjUM7T_SnjC`3{KqFX$4c<3;0LpzKy*w8{LJ;Qeic zKS{-c3_?;SmCGLmDe`BqSuv==uHNZ&Prb!o0=?y7f+I#Sx-G9L?=Fv(@UruS0KUmm zant$q_yhc)JN?aEVwo=Z8NZL-xul5@mYqsMeaUu?DI*B!^zmkcY}sEs@rD6+AhXP3Od95U#s&8yTM+zw|6+{ z*P$GB)Y0cK*EeJS++sKaNnm06AP#xE5F850^XfL#Ri?(I=!;W8+6cCAnfJzpxlKt) zu-LRBWkrT9T3ZQkH7>p~l6Y%SNnKsC?mjpr1~9LS38JkT_R z&+NCg`PhqvqqHB2GYkyqgG8S5fZGDh!9MEeXW^zz&bsl zBA#m!$;(EZtPUXKj#Tut-ou$`RDxw+JdS|}^^2Y=FNU9hCdn~8K{?HO-=M*|c$q(` z%hf{lk2LYnq-`Dix}tN$#h#vMAkD)f-*cB&NTOPOC%7V?H-(*P{(B~_2A@&acF`xT z1OSkDkx}?m6fTXy72_K$OIZwC*X>)JiwVRwS038%X+1;{R1|o8TYHJ4=3b}8g>Q<@ zw{|LSg}^L#7B+b7)NVIy3nE{Y=xO1WYm`c*iC`7%}7RXxSjt9B|WFe<0*TG{T%#xX`(XfsLcN@-=jw5nPAqDWaJxV{pu zV||P=TCCWKCv<{$!HNg2Z4wQfbYfXTH!qOCxt{f>pvbG3MrT!KYADZ2%4;KJjKxY& zx9e##?3@#I1#9p93e^A8T_HOtH>68+Z2peWar%#v8h;8%-WduDNkB((q?3 z*67W?FmoFx{?>6pZKW&?epox;x#1X7B0m-@34e=7`=DTDF&2`&IxQi<+&c=d4~~N} z%0Ec@!vssf$MFMDT@+n$eW=`$C{2p_b}e13A`xdK{}zN4zWk89g&oIYi4)|^BPZrH zQxsDPzRxAcB0c+6i^geDp`Z;MsnK+`kA?TY&R5eWC3AFxHRD@qAr?7m`7qydW@p!(b&IpM&~1>3D|xmTi5qPLN?)}vzqo5!Vz3WE^XDY&7a&Svn9><9;FPzrQVIQtE_ z1MFw-=T`0Gde$EgIEOAEr_8*R6$R3Pa!sg&{ALsng*mHR&$x9voaUS~7@IVT@OXG=Uy;ESP}sib3Rms{8s^Xuu6)Di@6_OUz_ zb1WCT3vp<`)OL4rx~!TPASS1g6vuLg9q#7DUtz!(V86+M*m?#&#Ex=d6Z%VloGHfR znd#oT;h=>m4%QgfR>o#+#AM2%IZ-XZxzqK|v{LLCj2+0MGIsba|usU2@0W!S{%)Dpz>DP+5^*z?YFC z$Gx|VLT?x4o(UG!+DR1O@Zxm&!b=@!gKb02@b5g9RCyt2$#l?16)0>Ka~m12iAz;W zqiIN9>25@C^7m$af4Xr2^_{jcySN9@r2iG$BIyO%pxv~siM$S1IW2T}VP(U)6xr}Y ztRl5YV=0O)J#X6Vn(kPiD0R8h#|8P#B@q9!3viT?0n7Y`O3=&L3M)FLd|--RynJpz z*96h$2+*6iJ>7vsVSu33P&tX}V@Wt>Qq82K0cb#+DRy@6bT4YeI%QPt>3BMrxcZ*Ra7}|iVn?az(aqR7GPX9 z1!_K{Ed+m1&hX1Sbr;(R3*qcGM1D|S|6KVwR9RnB3N*QeKv1nf zBT$3Qtz<2}G`aT0QfWJ=rj!76A*}$mMmZT@ckq=xLQd?4dkCsQmIn`R8pjkP!P}3W z0&NBxcQ_8>-)UauC^TkpqN9!)xBC9=XzV7pC68-Y(bF_-V>X~$SW3ylNaUg<{k!>n z3?tph^4J{)o3jb7O@Jsm&a^3vjAfolBMXquE~d07Oe-O>I?4 z_o(9ZgE%>lKHhRyFBVTi$7?hQ-K(r`kN49m-}s-ru%U2=TMVTO_nDXn>bzLvJH2l4 z;q<0kx);>+^~uv#72q24%Nr9*QY>BpO?@*9flQ^&=oJu8gOV}jf>>_ub=K;0{V9up zBo~%{ROt>@C96a>9?RN+xX>py5OzHzal?|61+Bqe-RUd=0m4RD<6aoVB=+h(f46*` zc%eO(BzImHP(||0oFQ&h|m75D&($?rwU!&9>R=1HEOFkAE-A(-WL_B^E=_F1b&(HadpZId)vrv*3YIXVsr zx$PCXUNeOWKi{I5CzWDsP>=;RnNGf12bOQzkGYXUuPm0RP;|mtD|V{X;tmHWp7m@8 zb`bH6GCbMS;A5aCyK^@Dmthv~e*8keV!SpM-`|EW{*J7$qE^RRcok!|oB5NsaUtMo zM>=-BjkkBA@wA3<2`;A1T(1VB{D7uRw@;=njI(jTzZK#hBIIcPTkI|65N5R0ZTU6j zb5Udz$Y0oXb)nC>0l7_OMHifyuhU^_&BDtnW!Sq=-&Q%ad20oJSXmp1*Qd%?i6p+YNSZi`-hrH$*7VUas$ihnnSC9yw^Os1HucYabw;Km%$|%0o-s%AF`GYqCrMs-yYI?h>JnEAOa#tPIhKja%D% zoalzU(d_9W3(Q6K-O3)ND0-YTLYXTk+2mQl5vFj|=qz`r;KB(bS1r?&Kvr<0vNj!+ z!{t{;j_LwCeUNEDC7ezF-n_0#frG0#BVCRPv*DoGs(?+1w#>#ORGpoa33vsqk%<;A z+SKBa@LBTo&I~tG4M+R=mA2Pj&BYK5ZZ1)Ry(~ylDNNW<>3IYLF1iWb zlkI18l!Vfh#T=DhHZ1Y-!Aao}tr$Oyh44{pb^$RKd@Kvm-d-Af)SsbhK05?kAFO4y zH={vCnDcHFKy8lPMFH$5fMD28DSX@>Mjz%%3!C32YZ_~UAz>o16xJ)M_f{5 zI`%(_=A?b71LG5H5sqeG6LIj+dkjCinnEZudNmD4xx}^@zUbeU=NMKr&+k(o|N34_ zK5@wy#->wyX~=csp4+(9sZJQFP%^KQTXhVIzcY)sG!}Y9({%;@u2ysgM*LV(I{;xb1K4p;7wz~*REU63zA`{a z#UtpULR7!mELO_}I5-ei9rVmS-~HhB^341nEJoGIXVAW+1aHn|Z^$?y0m^WMs6WX# zARg?|rw)UI4c<1Aq!fgBew z^L@(SuK&eX>nHigPex9qV?PU$1r8-4N>-?-y7(LGx1PLs zMxj&Q)PadtNJ@oAr&}rdiBr734cRz6h{jxl`3keS9!PFkDPy@0jf)JlE=_t6C416s z+A>KloA|aAbNjAiJ#+uxwSYo}%6^|d0$6%YjsAKrm}zUTs|NaFD*jjCHRG?G0Rmfw zt!d(oSQ)^rMk6)H`%MQgzgGEs*)iPAzQt=RXQ_^bZeDYCqxg}%9GDDw3_2((1uy3X zO6Bxy0olnDRr!xyP4#(G6gk`JjL;3nC}O`yC6LMvrFm7X2Yr(?fh7aS!!PUvX!s34`EK6S_94Jd)qjB7&xJVwx~+OQ7EtfIF9cKM7!+5@t%q&3)_9C>P0vjN3?_M=DM zC5DV+oBz*l^g3J-^I=u=>T(vkzavbaSoXO0rvC%%Kw5L|NASg3&kiqtiSDXSf=kHU z__ycDk^ykvJo+^K?;Q38%6AqBE35yP@-oOVW{;zf%#$+hpooq{ShT(v!~rIRi;;kL z(|ul`pYLZfK4@!rxkXNd!^vU$Ca?MK%Y(DcPZ&u>`~8(QLEIgkai|Lm?I9t1p&}uD zNV5~_yyGEY4OJw7&(c@x4BmC<*gO-lwh4+Kj$&{nF%R1H(?aO$2>C!Uk;wNkw80hdJaRwc}&^sA9%fq=!h+_Xq1n zA3l5)XT_Q&@GKH9$qocku129Qa<31;4z;_U?n$qUoQMI-`^l6dblp&YsmXR_;?iCA z%PMnYoqnMy?NYIcCH-b3k*@aTyrPecR8P}zR$qtweEl3<@N4Uu>bA#(uF!Rs+ZQtp z%wBURgR04vo32-fmJg$Eu#w`P9ufQePmEjwN_w(zj5W^x1sB7uS-w~1rn{ci4Of+A zm4TQ-&!|*gJyF;Vs~caI!Q$~LcQC1Mlc9?JOr8E|ygZjNmdY*iGG8@SA`?_^5N9z> zKbG6C$aF3nN(EBngMg5gP|xon=2>$`<6D)-rAy=&ifyt8wy3(;VkER#6Y`aA4J%jB zD~>{LS~jt)l~*+HjxuvZk!ALDOen*(69hhq5U9{^L*I-2P0357_2IdofrM~@;p*kv zGeDpvV(w%czxujIG<%T|wT$}y%SG?6XY)W`fW>8`@HtODczPAZ zdqiw^k?-R%pG4n5WLE}U-xNSv6)$(opn`ow-JiMI3TGv>1as`VkSphLB{e5%H=vFQ zIl=z2h1$3V&Nq8QA%ElJ+7qlMj`(eu9RqWDy3sRJ@5xRPMz| z5wM2~CoQhT7!m>Vyeiu$0+lQfua?&B||@M<{OZTs0?%N8dlxDLtu zCKI|kYO~ILfcsdwxWg3CTrT%SuyzZws{@oL%F| zX=rFMJH)SJ+HeUvo!xoqiT;fa(gMVmXI>=^@x0zs9+ramlb!Wp+u##YuIk~?FlTf8BYFpn%^h5;`AYWFQmZv z!2GS!vH!NpVH9xY;StB?W#i+q{x#ATKOT5UD;Z|aBB*u*&oEI6nE$4d@Z3d3k#QZQ zKZ`&#)GUPr7utEO$DG7eCF+eSd@A`qJ8`UCP<*w6BTp&9w#*=656ZH1+-0k?Li&)# zIgu+J#*}>5DK-bEOf{Ii!|uf4Dxmt1EC<%dC7J&&8dn7*rQt%OZRf%NFmFNFhud$Q z#0ZOw`k$+hU@S(k4$ve14Z=BkR{7fGc`JE6`Wy6~;0uFcD6qDO&vB=~it9-h_-zRN z&E;(zxWlb6<}wzpNA<~k!q+Rq73UD(&EoPE?e$T6b9)a*O~X8KI@-K5uwmZ}?N*zH zNK7ASUpT!GC~kR3{87mx79xQ$PtraFM>9G;>V{yRf`C^5ZLCBGOFEr82{OZf0~~e& z?1*s-6GR;|q{@Dkd2-~wdq2t!?8LCO{VH?jD#hR8-W0@e&1KRg@iBHEzBW2W>NJ^!%ge@S@+%FJedcNOoM z-K6rNVxqbL$+3()^YT)J4{}F81daUbg13qhXg%AQ*MxDP{hTa1b&`qj8l~&id;kp3 z@Wbv1%b_R~xXd9%x12JxP>XwQkCKK&DyXdRVf|vS+$InygN#(gvpD>WZ1zW^kA;OLm*;Zp!iE&)=CX9f?OL7X~pHEhPO0vfk} z7}js8=KPD*8z{8=S_ z5>Tvi5mS}&Udgp<+?E2piqO6CYx*-HTveZT#M<2IQANua5T~$G=|P1i_`LVmN_aMr zxVafw>(!otiO+(uw134#on*2#9c^No+#!YxR^6A8Oi~MBMF|shk0FdRr(wvu zjAA6DL-))66a&o%LFN=U=Jjg91iTP>VdWhbu8pslc4R9mYt_(=_=pLloM8Oy-qkTZ zia1DmXtwp*H$t}!fmV>hS3>Xa$~9vhkuPEU*>drPiWi>+b#*_kQhe_Lf@4hTxQhQe zQ0~h%=zY5hTv$e_WOEp8L<3tfY>b*+Z?~k@c66t^;ovDS2oOJ5BCvWPL`WMf`>se)j`B+KW@mcPzDZWdxS}?RI?oEh5gY%MF zAt2CpZW}#J=seMJgO6+ypHWQAxx$Z=7&D?ZSv`{q?@1$wP(~Q3p(taptw&xy7aLYu z!(X-WNjjQMDi&o?PttMN_>$VXq=GP1P?q6xfz_PdP0z`FXJIJBtfxZuoa({NEIQ|4 zDcC!w@e zpXbH{la0(M(l{ZZ7p9E!vFwQ>p+6S53urix*N;98F4#)*N zI!P>SvkIUeu+RD3%E!x-UykG+eBHZ0y#+&iGu8&&8t~{Je7z7f+5w_BN3mDL4dQh- zipn6AYy7WUf0O*Jf@zj_cIYq)?=UE~xf`-(BViXHD<<}a0p-Kft%L%^F#zh0gq)c@Ap`&j4#8m3 z6eMK>%NaFNQ(rrIiUQ;k6+LG97X(m%y9=MsUk?(EpvCZ1?rR*oHM;y|)P~D)>g_`- zw_uIb2JwehuzVX^hzdv6x$z(0sXN<3>6dCd-{o|t_Q!eC%5AeE%7 zgBj2Nl6i4fG}w5@sKvBYwC6W~ABGQ|UWIiVsX@0&IPRq}s2s~yK5;iD@&ARe%geO0Ex7GBwpOXaO5+?-~~^*(ivqcc`q$(l<$X4#bT zfJ>e6EFBKr|8Z?JU~r|li~4!bf2?Hq?J=--JW0vD*A5ygYD^k~?8DBPLB%X%Tk7nJ zu~OLM61ZdaWWg&86k+y?5uOQ#4JVbdNX@!doQ>+Eu_PZGo8_82On zU(SkAya?d(YW_G;2_qjkEg%%H?S5g4_{^lRX;{xa%{H)y#choVf}qA_#Cuwvr)v*s zI%nGHB5JFEwKd0r%F-Da|5K~{SmA%F0G0FA1L)PtQ%ht+W=LoNCWwSXsj0r5-lQz! z2`<)uva+ZO73#p)?Ge|C*wbS*e_KAzLVcOEt{fLsgb{b~5PQ##68x!=BG$E}mVknQ z6wG{AYhUn$@3Q=F_l-;YaeD^P)~o7>x5}(eca0R}-c(lcgTvAUw;}aV;$M8soT_5J zt39VDcYqXUfEhY`Bof!O?G|r^zqH$WA~YF=`u4NhP?E50rWyCd`jpHc$BWK_4qz?d zTcj+uLaZMIq{W=j8FT-R3&9cY1M;wdp#m}hQqTj7+jiw|k7J<9?1;Fhj03_iP|N4+ zVnM3-%Z&t&q#88apW}VsB?UYZ_$5qVo>HSoh^C z>nC|W=2GkKg?G09lqLRlowAhd_Qwc?Q5-`PB$eB=gy57gZ3nwacfYV;{}nB*5&HDM z23;!}ezRq7@0@#cI6MLw50@%b95(-E^nueR~6p%5S&0#+s9l87)X z$-#%#sxj%!Dw>_&r7d2pH6L?u_gW#`B3}x#w|K!Wq4d=1_Z&+M`(V$(@1mM(dC)JZ zY)=iuOOxjrPEJomH7&LZ^ZLeTWMuZuMVgYhgg=&p(>AG*V=0z!P_}NcI32(03a;&@%rA3H{u!3?5B!)=3(9CHH2= zJQswW*@%q1xG36J!FZz`B2peA@Ob=NNvciURv~LyjNe!D_S*tUP={)qz%nF0`Uyi! zJtEPl9$EkF75tm|tX9dC6Nd^t!eSm7W!EEbr$gs}G$Pzf)IZ6@y-6gNqh3XyG1!LB ztU6YQ%CE7(ac?5$c*bIJ2^DwMS8s;Uv0?@T3FRFnx9jp?Gp7cE_Em3LgLpX`U+%!} zy-!`?kv>{XDZadmhY=-4xSI3J5B}shI9IzMJaUm@l|5?ILX?qG>SQ0jjI_0e?l0!) zibt%2UR@CqrsVs#wUU+puA!?ng+IVE1W|9o%sip-w~j~^C@?uZ?Czb({LFnQe1}I+ zWYv@Oe1#y_B`4`+)v*3R;Aqy^4*x9}Na4ge$Ol^z0eDM_ zM-|7pR59WpBNPg=Dpy?`#pF{jat;G~ntn91RtOvyjaav#$w?jz9>#m}?xc)!xdv^y6iEc_R`*H5n|&_a`%FKP%@BDfEj~k zd!b2dKgLR5i5W)>Bx*pZ#oLDOX=*PrNfd|eU*}fqB;w4Ox!1$9Q}w_ps8w0NOvHQE z5UCcPe7<;|{NkyE^&TlmQ>M=44b7dorHoj%mT+%+pY7!nLphs zM)ZO$*o6;0qFhZ$hx@s(R=BCb;OrB^X1cDj(Nt*EGfT~5h1`p2Lh%}3U;#Zt8|Bvk z<-0I)7D%vEhWE#R7C5gMzIE$)QvvO=QJ-x{tq{Gq9TzaT=Ka}CNXJ~|nXhP7Ia*we zBxE9#kO0K?%y%ny{e5d250nh!RX5KI`(>M{1_utuXPs_+O#Bq`R?fp*miT=xGq91< z4YoOl$kK4Po1+EzK37ilRbZBxhG0qmv2nG}Gx*!K=%W`}lfMSiA|Clg1C{5o z0$#5LFej(ANssYRSU!$l^ z4VUoG&l06-dEF$t{R;l%av>6Gj1 z7;u`Kk^kNiNJ^H~^N(_-+DKBqWPY(TFMCLo&Eo&YmbwF#1!=xFLALYD2@rl`LiQOw zH?e4K{UPet7_7TB(*p{x82n40r{knmSyicjX8p1t9K!*Vj3BC?Qv_vhI!>a$*Fhk4dBbBbR<8r>BOi%)W|^NM&TsIamFsKuA%OK5bWpca-N| z7zmRFjWODj@w0fEM`*b?SHqxxaV0(pj*Qw>V(*p;KD{7l0q+J1Z{H!BB?2qX zdaR0;$WdWfiH&bGkV0{{!ix@_-O81>W$Gqg0z^~dHi?EvE!2yURC6LT|fxU`_q(Y6cfXKK%OY9reyvN!61 z7M=2obIILu_&ZweLoLBEw}fX`eR{cGbD`FL435kZ77!sl<5d7(2u zx3>ul|H91IBzO-CIVd8g7{-pv5?Pa=@0v3>-wzv;r$W^6olkh9<=8#>#7BoAOn6>+ z*nko^8jdX>z4hjH3@L9|1T57UsY`34ZxQ!6~#cUVP)3u4k55cT%v@#@ySpS;#To^TF2+07X zx=81El3wvV=Cf1LtKCfYIk1G!BG)i|GCxl zrX_|uLNjHrP7*9B41-E-9K zCI7ahZJ6FPj@;F(m_kM}5dy2Y7~jy5woe`6?u1bYIAYYjoH|Dfe&d1~_1julL_$T3 zzj{W(PK4qFjR85oQgyqKw041{9HC{QifmMfqp< zwd6`N_gsC*n9W7Ba^Umx2KQPzvE*gRXrzap3hy8l768)(a6e@=#t(10)PdMi&BdeT z9bkt=@qTP9Tv%)0MHa(G*oo$)oF(8(s~5Vm(_0@r&>hVoEYIhD{BTzTyJ--N@qmSh z=CZsN7ho7~ft;i0-WIDJ_m5J-94TEed`>xiCnXE*M%D?vlTv$Eta?LPid9?atIsl1 zpnG>E5XQ`$=H{%_CZ=#3sdDtm9bZn+kxn%xPdzLQ9apcxXCylmids-f7pxrG!aj>+ zTkaZuSzPQq{MS3D64NNc%X}}yeLh|vm4_6(Y|u|rc8rVo2r(EeipiO%=u^Jb1Y#X~ z=?jWPy^grYwa*4JOCv7xLfH6)@*mYY zLSqh%rDfl=f`&9YG8?Pynog$Bm&p_lGZqjQu{7C*_0|XfA39 z+-kM$>%M!iZ^&=hriVxY+34v}+KSh2vaK{k*~&m)XT{I|&iNq+I&kImr?|AL<>SMg zk1*9wb^Hb{B*j|WO#LK-2#u1Tme>D^41??gl>= z5B@6O(P|O>kzceY;gQy>L3@wNwNa~rjmQPXSQtpA{SHx0X2EZ_1`81ZM9(lLcI8`G z3!yVZRuyPSg%qoyrim6}P#Ig$iKCkz{Z+2VYo99YYPL2$-Q2vQBS!jM1nD}sO>5TJ zAQCg$&N{)S@%cP>K1pXq5&XuW=8IQtY`)b7V_Nz7t^%C26*Yka46@mJ%FNl6XgIzz z)UbhojuW3^IfdES=p`&aV+e}2qd9VZxvDdZ#O7MVID$_3Ax$hW4Q=rT1w-UAg5&srY;Opu z#_6?6LsbFu-;O8XsiUw8f+$c1@^b`@-h&qC>x=2Bo-$~^M^b?|rQT6e`!!Qy3mR=B zO=a;hrPtF3Wu|NhgBbNob)6V{PLzoQD~ay3waQmFwbAb)0d5f}m?abrJ~$qlZ7elq z1khN~16Vr*K8>M+l~N%7gK2nw!7agNCKNR^KRq7nwA7dZAB!~Y`Vfv`ZG2s3>D#;y zAs6&(*n)2D+VhLJ@}Np-S*yk;DmqT86&U3Tkc{AD%uW1_zm0`}U7olCOlX5paS1mx z@n8Wl=9Ag70mX9B@vN@{&;{}RlF+lmrC{o9Dyp;A^0H3u;T~m`Goo~(BhaSNH-olIuw&=%q#E!aaKro^m|uIKa#H88T32a> zyJv?XqVljx%9yDX(#dLwzhU@{A6P+iZQt{rX1qU$2RSi^s3C50a}xpRgob zF%vu>OD;@1FIO`}|DYuX?5u$fBvD}b=9eiJ9bgHIg2^VmfFZ;)sH$h_9Z zN3BrZBAs_tXjwhvBNd$%!dDxY3-;RMn5Zvh)6}SF$SQ2*Ly+m%R*@93uV5?(MoT&b z&P?~usXMeG{pWV6@3NZQgh6h@YS&NYNdj$2Ea5a;wV==MoJN&nbHcZu!EZTJSO#Kj z7N2NBgLBbk41-y{SD1A1Z1)1??(;WDB;`vqJQwpmKl~!lhmw2fjKH?*LTIU_m{}`B z!Jh-?&3d{Do|v+EO?+_#JJ9C2@KVvlFl=W)N;1$N0`}KrijN!D-)7WpMDnU5d06A? z+L$XCaz+2R^bB8-vOpf?N}-?Uy$QeXyJAC5PUslWieWw5 z@1tpCqF#CV{u1AF8PM~%ehfod;XLqVC8JNQR234H*uA1oT?Yxn)%*pQ#e~q)GgSXD zT*Vo(oW@{0cx@fiAP>aIp?7(4S7apq>phN}@-^ART2H!XncrWI<`9=RE~a*Y&9X|6 z4-3Ig*WG}w?{inW5a9I~{v?#5n|m3VBvIkbbo&AM57Z5wr zIO6A`2#z&Z(``OD%#7{l2i`;0zXCGgLRc6zRl_?63;HYLmS4-GBUzv#VtpF%%@xli zfIYWoQzD&d-}Q|4fSbusd}8tQzvmQnIwYmt{J?f;5hu@|gp*IM;c|&AgQpFo-m)`S z$o$1>Wptklo+W9)07^i$zvJSo=PLSo-=UECZU&%*ISW$7C6M-?OQoG+lf$<~wFQ4f zb55G3`Eq(=HJeo^%gGRDAR?06UE(fixK~-q1ETS+jSm(OQ`8BJLtJY%oQKBn7yZRN zN$c3%?XNfLnu8LIvV2s&@9rJOUoRl;+Nyc(ZpYfHLxoiM^j6aI3=L;BksV9q6ZW$- z-gy&edtO|KH*yM}$hu>o(Xa7I1xBGD+5z_CyzT8cBTC#MR#5CJH@~U>S++I%eNng$B$H2NvMEeTnq?zG&Px-^m}1487-0pHZ^zjauMjOKkXuTqMo?u$RT zJL9e>^O06t&|gWff<4R=mR6)cuJ;GAF(mzrAm7i#DO3I;P%Rgfr>Gy4)5C5tam zrQZgtMCfB6ZFbR#o;nklG>%n2kyYciVRM{^!2zQ}|FUA6F;Let9RDf!H* zMbYqPhLr13{q#dX=cRT>gn_5BcZH(+-?$f!dixF6h64IZ_nFFF$Ar*^@~M zx+*~{T}M-nQZRImeE0&|7AS59=A$hQ{(}?GcCG&ATZOHt-)Jc4=>~dgk>C!|^qZ7< z&SZNHS+scI2Vy$tY=NJ>+VBWom5ELe)HioxkFJx2FzdnVs2qn|f2RXD0`)~^FwEI6 zD@~+Ep0%2Q;*g@cN~1`ixYBFQNCg*pUB7{p&+ zxGL(IRFKrxU>b0G5LIn`nrHSRYGf@*Y@Nm8?wY~v_h)KtF6&oQZa%|QX?BZqG8nfj z2xE0>G*@Ku%201^{#qfbq@*1_>-CckQ2e-RQa2e?V9%g@Dv3|@Ci*4-;}MBq?RBuG z%gvNm->6JJ(_e9XRdr+nM?IJ%#ebQZ{@Ce>D3+}&Obzem;j~)im~bA^s4K(Y%d7!B zdQ03(172hBl#)uvOKM}Dp$reUV7c+4&Ks=ZLinswyY_Vl%DHJOdDvL=pKmSx^8g9A zZ!i2&hTui@mERyZEG3luP*Omj@TZU7)nPZ<;oq+78g@gqNa-#^-1ki$+{||5gZ)fE zwyU&G{T>gJnC}w+tQX%v9IoBT=bZ8!s9BbSw*_+T4jsa4X^ALcv+04(|20g)%Auz9 z#lE5&WwYiwgBQ|iR6KX5y5y$skk*V?$Gw@!h53MmM3n|P`yM{8lBuHa^5&Dvp{FVR zgJZ9*cm$jU14c6O={?4ik(M*pAC>Krvods=Z-=F3&ewu2{5I-ng+H{)%~ahN*x1KO zkm2j+Msf@E%$PuZ21R~hX3MX(O30C=-+B?}96xkL8KLQZ*4fZ%zn4T`I(cno&Vdje zKBvUzWcF@wu9wkPjh5y1(s_-#&|(WUtGwLlw3&>S)l) z0A>Yh#@7_E_FO8dg>Qy}(#ok}YHQLD2otBNKRZ;ag>E8Ss>IW2ipPtPIkjh2HXt&* zx*DU5bLz`bD}JSB{$R>yQxou=v6fNUhs|aWxTsoR)dCQPMAHfgVofG)iV6>ckL>u8 znkM5}gR@EB^!?v)h|jmktz>Pg9QeCV2HF@`s_qd~xVZ{FJXdvgo5^214$XX<*P~cK z*!cd$4UmXvOY0f`j&$37Cnk`6hJ<|4F@2hUb z*ju&Lp~q%$0P!4R(^hs6VppXYuH;4oFWOXpbvM+Qjp^(RP)M1AVfrsEMfdL=a|{Pyd+Ii^@0( zQCvCoaF*+a3TF^+2U5dJZ^8>-UrliJ#Q+vgn^b_zq!_2 zB#Xzq~p%imz`p6pl7qpt*RLiH2 z9;Mpo6y`e(SGXjcEDLa%!mOj1#*Eb4e8H*~6fFWdK9<5Vj^+P&#G)Z-w)}=b)pUp4isDAgAgtHB6uFEm zE!#gG$^4K?*!bWFJ~-b(qwzy4dr;(!7fIhWtDaeSzZ3u5f*3V*&-ez1vTfHhV<#^{ z0e3*FBeO?=$)Pk7Tk)PW5%%hE;%HJ@H*h7is~fh7j-7uR4cZBgv>|C+o@n`P_^T4D zLw(tqFr*0cqC1J962g2Aw@nOZYtsaGSh=j%D8f;Wng7AzxMIPwKs84>3}=6p+RB5< zF;pi?#VLM7>1~7dy%O+;D35kXR3rM!xk}x{jryYIf6vBpo!%qAG^p3CM z7pE4ZUfcvK16$X#o@})9rGvB&$C^oRZ#Z%Q*}>2hb|#btQ;_#Em;Sl(U!@z!rttoZ zGk2XIAMVQ-o=2`lMc`S3q!%md1flF*)NJXYp7R@8sYpVLkw=cKU=B4%E8`}tezJ_| zd;tfzQ1^22h$B-sy}d7s_N4HH(nf$uQUw}DM{TG@{%8e+T=A0*{|!xV`Z^W=5a2dm zaz`jwFVu%HRY^{}F(~8=wCR#^C+JQT;bci{)&|KAeW4@Dqky=mJFKGz!jkTWXugZQ zdbJH>2a}!b1fae2!_8KR=sBxQkjbAcr_?@W3ph*1eQHEB%5V{9d3*8Jo3xt78}m<` z61+mTS-h0Y)8O)IZOut$x!Ct_GP#T}tE22*B5;Lk6%rt|be~3}gFX5b=c-GyE}PnL z&a_g=$|*}&j|Y1sIGT+kHH`*ZX%2u6J(U_&zuc4`fs0@k6K}uH+!maY2!eLueYqeF zrv`FNk=VTX=fJ`e?7bEHwEiUsvr-+0<#DeID4$EqxVm;M4XV0;7yQY~q-nY_1IDEI z;{j#Nv(J$5t4DNliBmKNd_>;^l58|bY93N_x(YLBTaZ4CVx=5MvpZv=twPF{SdRM0 z$YYBe`4%wTq>K0!C7e>etLZ0mA7aNX;Jn?3sG$EU{)#`r)RTUw-GuS}l09svxy5U$ zHBK)*41?O+!r7~U4aZz>`B)+Kv%DqoLfFng^Ua+#Qsn6g2{fn3d)lsY1D?TBB_FEe z>uN(kW2*mw^LRFkgziT6l9dQX-a@-09r@?^(Z z`1=0jJ|*}vW5*~E4TbKyM?O%i`>;#QR*$>p&+f{>K?*aLeDp1?Eu~sUCLpppT#cnm zN3M3B)Qv^jHbt}rgimNdNu%ZK*nclGDy6^3LRRd@Ym<2tiz-J5&^L4>8u>en9G!yeCI4wWv z=AsPlywj1`!FiqJ^Fu5ApNx>dxCp=d8e2k*MDN!a2shHVVcpCekRz2cRESm_KS43<^Ybh_bx%y%FJ>^+cdC zdP|b!1Cqwqdyv%x?u9F3m31x|SLo@>6wO$keUM8pye87R3;khQ(i_ zX^KpG>nPU<3@km}_1KjXg)S^QG_3$Tov&rss98uOg;8{W9!BIneavUL9UIDZNIm%{ z$$H#9FGC5Gv?tSn*@%RR7Cb>$n^5ABvHNTrptEW%Jzc)U_NrI&2QG*3w}z`+)al-1 z5E8oY)}^uZzV6F{kXTfSp-4VSvy0`7=D>Ppp;FH5-nx>=1ny--Ne1r4?1i6o?p^&abFKuL*r1;%iCVcOCBVFtmr z?YGE>)?&k1Jl1n1psX9Yp4sdZXW;37;b?b-GX%^y)GecoH#m#jdNQE#re#-hjDMBd zWdx*{Vy+a--gb)(+8w3=EiajrB1^d_Md(u zT)ZGrQTlQ1Q$JuOD;HqFcclbs-*$E2N!;xJCcw@$OFwU)mG=tt~U*2RgZ+u(`^S zyjGWEPCZb@S^CPf$4LuxzmU?_rn2*}K>^rIsO)4+R6?9RPLiFpS6(stDjgbDnaN<2 zg;o>`m6;m|duNM@?qh7QZ5mXQm_wOLC{_L(YunMDD2)DCnRDh`nIM9Dn_jHe60HPi(c8U%# z0N*o=ldlE{S#%**&L~8~7Wyy;{q&!Hd_-~S%fm5}%HYDHWj4@^?yT`Zx<_Jdtl|MM zqNX$)=GH#!2r58|p3a+v6UyPg+Zwjqf0tQQ<~6JHCaP#E z#xZ_4*&p*1e899!B=h_}mwiBg0{RX>0x&~VG&#yJy7YUgp0>AYns+a>_-O&@Yjb8&nB>_Thtp{S)aKxxxEhJE5{RAFPp4#)6a!Q? z0EE!ZI!126sxhFxp`*4BGN4E-0Vp06bSBQ|Zp_f%I;<>bykzJylE#Gg{cbbDESHcS zrA7H#44{~OV1F3*huJ8NqWAL)Nw%F2QeLQ&F9O_}atY*%0%#JN6!8<=y$V9;ZFi^l z1dVdNI3N;y4~1pMU*B4qfe0ZJ#dh1N`gpTZ&>KchrM#77N5a3&-qap55SCu?Pt&6~ ziz9dmppSpdvR`^_FQCqX>z&zkCyH{`mGTsDHnCHz)vqyasFmbc!lT$8WY`j#;Fi^G z^;vZBL&CKUP0ENO*;H^`kWC*!_5L|jVz;qN-Ao1C4~s9`%p6~sBfIylCS3I8VrXk? zPpbfb3^B&$BC3WQlQZ8r-t%>9c_4j6=d+XJSm8L3 zWX0?~2=yj3EAM15DK9;cMcc%_;g}@qg*l@Jk3tsE!-5?`|K^0fL9R zl$pW-TMsS=AO~OPH*x>03#TBHlTfAxu~?eE6PZygl)-wJ2z*fyktCEp@7U}qA!U$H za%&9n&AE)#MbUE8BY$UmJGngrtlbfNyR0!nw^*j%8I_b9m1UF(O5dWM^OL8js3G&` zxH^pdnPGm?>!<(V$(Qn8>vb)wmn`x^nq~L$-v6ItVL2829Fc7KwGzOUA_yT!!%0QY z@LQ%Gm&a5y7cX;VeA>s}wiMM;@teC!UhiaO_SiD$U@B+JS6>4yIcclnt7B?fbI8mf z@;oTAXj$lXL;bian^K6lWk6rzV2)#^g817T;o)ApHGw*5wD|0e3kxw4q*ky%6Iops zeE;`iWH=T_$B=MV*hh%TBL_izHBa5Xr&C6CsN=2Jt~^~n>f-Y~I=@td)ckEF%Df}w zvi3bJmtzVf6``cqxhU1?gBUN4r8u*M=)v?=A6AI&)ORP-i?UVYgV^eSgDU>!lNs|( zIHKYH>TrPkO5;&mcjx{nt4fyyk*#mlrUQ@@$uA z9IA!`V_v4FvT8e3gFB=aKaf)g7x_F}?eX2SAZJq_lVm=}w0UcdPMj7F?|(HfSKXz5 zEe4c@z!3Axp$|v#m*9Kyr-7`$93ExK)Gw_r^Ihdaq+q>AogMNz2fIFA%D0g(q!GfI zZ@Ve~ISxg>XDoH1Ym!0=c-yP82T~|8cVmI~Ya}ir@u0BwJJ?{1xydpAq#6GxsT@F~ zU4o`Z(2K=`|H)^Gx{xGaa29OkF|ItpA-g%P0Q`;T?w8}7^0z3wG)l*+1)R8d%UH0x z%cS|ejR~NXbos?nc(Id9dudUGzI3g%@#Yv&dwb-@%SpB^&7&ziQ#>MRk9&(_&G@Tm zB&>t8=PjSSNchqb!vl1dflZI};{EirYr`DC&VzLeLf6ORPw{|2@M}cjXO3gcudh?t zzc;*E8mUBsqSskC1^iW09)?z*|1*lpB*ptj^Sem9Y)xHed?1>juFCl%idF~=4|_@i zVFq;Aok3=r>Q`bX)Ol7bR{eeyP(wm(u0c?AiRmNr0#Z1kch$vIAJ{a~jGjYZa&G(c z`_1KTH@{N;z<1o(_7h7xoOOSwx2ui)6^D~G#?=W7VvRO~*)&k0L7kU*?;cbG6n zLXU#IZzzm#I`b~RkVOL}R(8~?Z%*Jta+qGv?IzrOFZHt;Lnq!(2U*Ed>m|tC=)Q@b z;gtdXl$h8}1kyX&;%hbi_JOZF6;6M`-eBeFQxX!ct);=(@)f+3JTaDNV%9`FyLCBD zpDDYMZ_rSGDbKk;N^)Rm#y%$A)3vfhtI%}`&@=6+76vQ!X$>+l?qQc!1){nvHm2LB zoEyvc`9V0t&hiQnBqhXlAHE&Q$qW#Y6w1p zkCE}@!Z)}X*}ZZJ4M+OD`+bIkO8^kX{%TtpTi$|&KrF)k3Cr`D6(93q5Pb@B5NL`u*3RDDTxJ?>K zxU0E^vwfA=G3An!8V_BhrYHd#b)#S_E&15kNoLHG8EF_R&OC`mUEiS3IUlZX=xRm= zaO2o12>aSS@n3(QyJlc=#%SpvtjjJg%y^Un1_Hi;G>YTP_xs`vTw*_iRndyZ9Za!8 z_GnrPkib~<21ToI535B0;yf>kNlCm3+4*qAV?VV##wJ;8>E36sXf$cQv7jh$OJ`PR zulM=CoBi`pRP7IXk|I0DTuEvViMC9+c4^xYvl@nZ5_IpPAtn4sTWQ`=I8qCl>4*@= ztMTq&7S2U7q0DMTNA}U&k^Q+YH5`S>KI3mcpSWCNb@3xD^o!i}k@-DTU=EHnPVNg8 zrJ@fD0ltC3zL?-grWBG&l1;1qRDk)$ZL0ZjrF4hRn_!srML`mRH72FELx{Q!x`JtA z9Ls_zY4pyA!!ak-1`Mp*@;TYzh7H_vYHL;=yu7yG%LhfFegVR!hAc)_*M zU~wd|kBL++I4tY>w*Md#Yb!OnNg-f~Fx!)#W0M!#c;HyXLx3GYU%B*~-1kmD>Za75 z6dt)2!cm=ue2Ms>#uyz?{z+bURf~pSY!{AqC@hISi&HG-$j}d_j>5H719SMi;{Eg{ zr{V0N_?v>0{)){sKw2ReV#1|61{5(|zSh-Gp{wiM1+r-NPO$R={<`-Nm=eV(?YsiDTIeID~m?^m27{%VQ=M9gfp;Rs?Xk$=_86s zps)_R_%MFrRk`HR*pT^n*!e#>(kMKjSZxVj@CM$|?|Fceg*HAaT6oHAb;To9f=DBn ziUZcIPi#>fjpKIu#<3oZ`~n)Ph0+t-15~fMUoppg6q+=amcnB9>{Z#qbSa@5m3pjD zD~<>Ix;FlI(=w2LFMLGF94$v`A6cKYa+X%5TFAnX?TDObN6QRTAO|wqH)j`rYswrrLxs5+MsiS z86Xw_Mt|^;*U~qTdVPLBj3I?bA7ACBWqeo-a`g^BLr1L=1NWHY#V`ZUm+)L$k27l9 zuu)?;$(+TiWzxFVMgx1~>9dRbg*rUEh%l7NM)0cUskUNpMfKa+hdKgMkLT0XuZet5fI_*Z7@wfr^?;XKdTc1;aMl;D|uT zDi&#lk%`>0y@?Z(=|NsnyrPJQrV;a_#^`Z4*#E0dis&%ePj4)7tpKeNrHM^}32RMr za~%y-bJ8Xw%nnfxbMz_UoWf&q&YU%{>u%PjfYpC^qslqp zJ}}>l?f7w``99G-5Nr{Aj#fBK1F%t@!lpofOUgjQ_bx;J5r0s>tn6yTp80PFJ4BJY->&(-Iw95X&P` z1%|A(Z%@J-+(hCimdbwW(#>014Y#MZpT+H|FD*u%fQk~7qULeqZy7-UlRbbXL-6L? zC)t(~p=D(hkAx~ChGHGuNM?e_18je*q^_WvJIdeg{2@d>8<7* zp0-mxu8XL_R;OwB;npFPaKUX0(mQKo!{huJ0N*ufxmH9b_VUlrUn#%Fh!K5U^x2mUYe~cCnpQL&`aS4qy(38J(5Rsw$|GY=ZJ64w541rvRr(RQ zWRpn-)Z?wY`v)XUnMdHtK`U3IDtHd%O4hdEK)hqE0_38k1NsF3>FV2`*X5Pn8l@k( z160ILRSWG^bq4-0it?%i0El5N^trO?mz2r)QSu|10dmE>IFyPvgYswvKk{D?1G^_Q zW5@T)V}ouvhw{?cYq3Fa0e4LF=$@;g3pfe@2nf2~48mf1Sdl8xNxC+&q(j5~FILDD z+rYP3z#1mTR2@Vb%)WD5Wp>o>j;HJ3+rcjJ_A5XM6HfQlKNmSG1`^&{E^3(T#I~d) zI8sa0O)Vv|zqJcRRveB>qQX*ynkZFNbnR@ueufm-8wz^b+-U_v2ByZ71sV*2AH=q> zUy3l?0gTc6%rpfQe^HdFpZN5=z$!|aAQy``Z|U3WBtG|2|ztul^~6+k`ghJtlAVtcWWt8TSh32Bb>wtyKFY zQ~xP$(;f{}&w&}GT$^}rk*6aE`vvq+N7&f}$yoDi&kwFSvU6!%vGym8t;N;}9FbHr z?5-#SiQJnQry&}+Vd7Z}Jf2~>kIxU+-IQ(J?*cc8=e=+N>qMUN&?hA#H6URnrPcsS zj7yD4%*n+FYrRq|VY4u(m%F#dDt(jE6LbeF(U(YnDt=?+F=i%umG98e#%eb?#S~_wm8~GO#?8e$T(W-a%Osrx%le#<`0!LOC z2K9nX-0L3(;rbVd`(k|sKgYxvje`)~uqUf;PD+bX6=MCz73!6inoOAlRp-}b7Y}*v` zV6{Hqt-xCMxD$}g5aQA_E_l`ErgCZP(wiKF!-1e76dGZ_ZgP5a+KHAXzlF^gk{WQYyZ$3u{rWRe{cLG< zEK&r)1V?Z2>EU5rL;j)S!v^Cn{&zTUaw)7jIAdWg8#^RN^mFe%b3aAlokVjoxmjIC zXA)MY-18$NaIVLwdYsQ=k02ae=O7jU9_jB+T{wQ?tbX;+jsQjtonXroJ1Fn%)??-n z5-TZ)GO$?Q;7kB|3LKEfB;-07qROiCEb@`MdkI{rVE(aiH4sds4~g{$z_iKo}Q z+`CL(ZD<2PSIq#D6u00^>)?C2rf9-pIFMpwF=fjC?N**r&@nS7y z>vQ=C)%2Z827`8+OkOzuGVdENZ&{WV4W_zK;v^rGLu37eeXyA}+hK0q0qH`rg{*yw zzDo^_5<>9wYNA7&sXRyZk}Ry;Q&?8+)mp0ij#&R7gyx+vT1zo?H7ef5!2%IrG|C${ zzHNgU@(njXcw}bvi5kY$gGt0Y2693rV(t}tuXgWS73Lv>0~CYHtw%|i#6F(Ufx*T# zgFPSpzRUIZdVXGgGrNDtdo?A|P;X>ZRK3J&Io>%9B$<)^!$%tn>%aR*c+4=Wc{IN9 zn9@(3A=mw_>E0<+bY?cGcxqOnAHBTtr(4fqDW`RwJme<$G<{K!Gw6ZG>4?hG4b)q9 zSVE0<%oaNzV5_K5RzVUWAbNviw;(hpCCt6|o|Hm=Yr(P+skE@7s-p_|97x38bMCGs z0MX&O$AKP+IgRXk523^jj*A78tHvfIN+_Ef%b@YP3PS{@D|Lf%Z-d+)f#!_qkxOY(%@%3G&^=cwmSv!Z%*>953M0Yg-^O_&(k57be z9pw1`XLy&v%$?ol$ev=GdvpP(0erPu=fEGQ13&gTQqxr9T}-0sX z%4F4pCrCVano1aeFZ&`{D;~UO{?@wCLAj*X?f64Ycs6aOH~=2ofbIgFi;o6(p0?yV z69=z37|W11z&mVZno?oI?yxkZl-o&pZ>9K zPyf8U107Gz5VanKLXDjmfIOE(;M1Ng=?GmXxks>&6rzv$jPPcKd&}1S=1<+SmXnIH z8euGkA8XZI(pk@!4gIZ#y;8L>l>cCMi);PHj5}{R$*FDdBNnJKec{_&5zpv`;1kNH ztP)7Gz50EI9suae|Ina6t?$sgE_I(fo20@tUp%wiHK`Ar%9X3dpYTz_p)?^7y`5u6 zqeu?LYiN3q(IB}zx#jDX*#XrrD$q#v9@7gD{B6-SJp!h2^E-_q__$3y#SGOJziSO| z;OU-UIoL=vclY(Gv{k3qh{t07ynNfTLpd#*Cka?s6`8kCQs+L4K$e#jXy18(C%<&z z;#cf`*VNY^?x_{jE^U*;ih1tlt)dA8IMdiexpv7FEt86C?reuUa!jr1@j+68kI#1|-{h{dp)POwumFkXS1XXkFvLpm z6*_6e(Otwa13vHmV}x>=VR8*bX#r~ymQ&y$Qd6qZd67!G-LBC%)Sc#jKS5^!usLe?9|;kx_p-Q1DnsY zHdC{G{quDIj1cjHu@`5~U`h7#nmya`QV3D<64Ive)wfRªh^b6o%1$` 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 +.LP +\fIstruct ub_ctx *\fR +\fBub_ctx_create\fR(\fIvoid\fR); +.LP +\fIvoid\fR +\fBub_ctx_delete\fR(\fIstruct ub_ctx*\fR ctx); +.LP +\fIint\fR +\fBub_ctx_set_option\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR opt, \fIchar*\fR val); +.LP +\fIint\fR +\fBub_ctx_get_option\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR opt, \fIchar**\fR val); +.LP +\fIint\fR +\fBub_ctx_config\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname); +.LP +\fIint\fR +\fBub_ctx_set_fwd\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR addr); +.LP +\fIint\fR +\fBub_ctx_resolvconf\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname); +.LP +\fIint\fR +\fBub_ctx_hosts\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname); +.LP +\fIint\fR +\fBub_ctx_add_ta\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR ta); +.LP +\fIint\fR +\fBub_ctx_add_ta_file\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname); +.LP +\fIint\fR +\fBub_ctx_trustedkeys\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname); +.LP +\fIint\fR +\fBub_ctx_debugout\fR(\fIstruct ub_ctx*\fR ctx, \fIFILE*\fR out); +.LP +\fIint\fR +\fBub_ctx_debuglevel\fR(\fIstruct ub_ctx*\fR ctx, \fIint\fR d); +.LP +\fIint\fR +\fBub_ctx_async\fR(\fIstruct ub_ctx*\fR ctx, \fIint\fR dothread); +.LP +\fIint\fR +\fBub_poll\fR(\fIstruct ub_ctx*\fR ctx); +.LP +\fIint\fR +\fBub_wait\fR(\fIstruct ub_ctx*\fR ctx); +.LP +\fIint\fR +\fBub_fd\fR(\fIstruct ub_ctx*\fR ctx); +.LP +\fIint\fR +\fBub_process\fR(\fIstruct ub_ctx*\fR ctx); +.LP +\fIint\fR +\fBub_resolve\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR name, +.br + \fIint\fR rrtype, \fIint\fR rrclass, \fIstruct ub_result**\fR result); +.LP +\fIint\fR +\fBub_resolve_async\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR name, +.br + \fIint\fR rrtype, \fIint\fR rrclass, \fIvoid*\fR mydata, +.br + \fIub_callback_t\fR callback, \fIint*\fR async_id); +.LP +\fIint\fR +\fBub_cancel\fR(\fIstruct ub_ctx*\fR ctx, \fIint\fR async_id); +.LP +\fIvoid\fR +\fBub_resolve_free\fR(\fIstruct ub_result*\fR result); +.LP +\fIconst char *\fR +\fBub_strerror\fR(\fIint\fR err); +.LP +\fIint\fR +\fBub_ctx_print_local_zones\fR(\fIstruct ub_ctx*\fR ctx); +.LP +\fIint\fR +\fBub_ctx_zone_add\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR zone_name, \fIchar*\fR zone_type); +.LP +\fIint\fR +\fBub_ctx_zone_remove\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR zone_name); +.LP +\fIint\fR +\fBub_ctx_data_add\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR data); +.LP +\fIint\fR +\fBub_ctx_data_remove\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR data); +.SH "DESCRIPTION" +.LP +.B Unbound +is an implementation of a DNS resolver, that does caching and +DNSSEC validation. This is the library API, for using the \-lunbound library. +The server daemon is described in \fIunbound\fR(8). +The library can be used to convert hostnames to ip addresses, and back, +and obtain other information from the DNS. The library performs public\-key +validation of results with DNSSEC. +.P +The library uses a variable of type \fIstruct ub_ctx\fR to keep context +between calls. The user must maintain it, creating it with +.B ub_ctx_create +and deleting it with +.B ub_ctx_delete\fR. +It can be created and deleted at any time. Creating it anew removes any +previous configuration (such as trusted keys) and clears any cached results. +.P +The functions are thread\-safe, and a context an be used in a threaded (as +well as in a non\-threaded) environment. Also resolution (and validation) +can be performed blocking and non\-blocking (also called asynchronous). +The async method returns from the call immediately, so that processing +can go on, while the results become available later. +.P +The functions are discussed in turn below. +.SH "FUNCTIONS" +.TP +.B ub_ctx_create +Create a new context, initialised with defaults. +The information from /etc/resolv.conf and /etc/hosts is not utilised +by default. Use +.B ub_ctx_resolvconf +and +.B ub_ctx_hosts +to read them. +.TP +.B ub_ctx_delete +Delete validation context and free associated resources. +Outstanding async queries are killed and callbacks are not called for them. +.TP +.B ub_ctx_set_option +A power\-user interface that lets you specify one of the options from the +config file format, see \fIunbound.conf\fR(5). Not all options are +relevant. For some specific options, such as adding trust anchors, special +routines exist. Pass the option name with the trailing ':'. +.TP +.B ub_ctx_get_option +A power\-user interface that gets an option value. Some options cannot be +gotten, and others return a newline separated list. Pass the option name +without trailing ':'. The returned value must be free(2)d by the caller. +.TP +.B ub_ctx_config +A power\-user interface that lets you specify an unbound config file, see +\fIunbound.conf\fR(5), which is read for configuration. Not all options are +relevant. For some specific options, such as adding trust anchors, special +routines exist. +.TP +.B ub_ctx_set_fwd +Set machine to forward DNS queries to, the caching resolver to use. +IP4 or IP6 address. Forwards all DNS requests to that machine, which +is expected to run a recursive resolver. If the proxy is not +DNSSEC capable, validation may fail. Can be called several times, in +that case the addresses are used as backup servers. +At this time it is only possible to set configuration before the +first resolve is done. +.TP +.B ub_ctx_resolvconf +Read list of nameservers to use from the filename given. +Usually "/etc/resolv.conf". Uses those nameservers as caching proxies. +If they do not support DNSSEC, validation may fail. +Only nameservers are picked up, the searchdomain, ndots and other +settings from \fIresolv.conf\fR(5) are ignored. +If fname NULL is passed, "/etc/resolv.conf" is used (if on Windows, +the system\-wide configured nameserver is picked instead). +At this time it is only possible to set configuration before the +first resolve is done. +.TP +.B ub_ctx_hosts +Read list of hosts from the filename given. +Usually "/etc/hosts". When queried for, these addresses are not marked +DNSSEC secure. If fname NULL is passed, "/etc/hosts" is used +(if on Windows, etc/hosts from WINDIR is picked instead). +At this time it is only possible to set configuration before the +first resolve is done. +.TP +.B +ub_ctx_add_ta +Add a trust anchor to the given context. +At this time it is only possible to add trusted keys before the +first resolve is done. +The format is a string, similar to the zone\-file format, +[domainname] [type] [rdata contents]. Both DS and DNSKEY records are accepted. +.TP +.B ub_ctx_add_ta_file +Add trust anchors to the given context. +Pass name of a file with DS and DNSKEY records in zone file format. +At this time it is only possible to add trusted keys before the +first resolve is done. +.TP +.B ub_ctx_trustedkeys +Add trust anchors to the given context. +Pass the name of a bind\-style config file with trusted\-keys{}. +At this time it is only possible to add trusted keys before the +first resolve is done. +.TP +.B ub_ctx_debugout +Set debug and error log output to the given stream. Pass NULL to disable +output. Default is stderr. File\-names or using syslog can be enabled +using config options, this routine is for using your own stream. +.TP +.B ub_ctx_debuglevel +Set debug verbosity for the context. Output is directed to stderr. +Higher debug level gives more output. +.TP +.B ub_ctx_async +Set a context behaviour for asynchronous action. +if set to true, enables threading and a call to +.B ub_resolve_async +creates a thread to handle work in the background. +If false, a process is forked to handle work in the background. +Changes to this setting after +.B ub_resolve_async +calls have been made have no effect (delete and re\-create the context +to change). +.TP +.B ub_poll +Poll a context to see if it has any new results. +Do not poll in a loop, instead extract the fd below to poll for readiness, +and then check, or wait using the wait routine. +Returns 0 if nothing to read, or nonzero if a result is available. +If nonzero, call +.B ub_process +to do callbacks. +.TP +.B ub_wait +Wait for a context to finish with results. Calls +.B ub_process +after the wait for you. After the wait, there are no more outstanding +asynchronous queries. +.TP +.B ub_fd +Get file descriptor. Wait for it to become readable, at this point +answers are returned from the asynchronous validating resolver. +Then call the \fBub_process\fR to continue processing. +.TP +.B ub_process +Call this routine to continue processing results from the validating +resolver (when the fd becomes readable). +Will perform necessary callbacks. +.TP +.B ub_resolve +Perform resolution and validation of the target name. +The name is a domain name in a zero terminated text string. +The rrtype and rrclass are DNS type and class codes. +The result structure is newly allocated with the resulting data. +.TP +.B ub_resolve_async +Perform asynchronous resolution and validation of the target name. +Arguments mean the same as for \fBub_resolve\fR except no +data is returned immediately, instead a callback is called later. +The callback receives a copy of the mydata pointer, that you can use to pass +information to the callback. The callback type is a function pointer to +a function declared as +.IP +void my_callback_function(void* my_arg, int err, +.br + struct ub_result* result); +.IP +The async_id is returned so you can (at your option) decide to track it +and cancel the request if needed. If you pass a NULL pointer the async_id +is not returned. +.TP +.B ub_cancel +Cancel an async query in progress. This may return an error if the query +does not exist, or the query is already being delivered, in that case you +may still get a callback for the query. +.TP +.B ub_resolve_free +Free struct ub_result contents after use. +.TP +.B ub_strerror +Convert error value from one of the unbound library functions +to a human readable string. +.TP +.B ub_ctx_print_local_zones +Debug printout the local authority information to debug output. +.TP +.B ub_ctx_zone_add +Add new zone to local authority info, like local\-zone \fIunbound.conf\fR(5) +statement. +.TP +.B ub_ctx_zone_remove +Delete zone from local authority info. +.TP +.B ub_ctx_data_add +Add resource record data to local authority info, like local\-data +\fIunbound.conf\fR(5) statement. +.TP +.B ub_ctx_data_remove +Delete local authority data from the name given. +.SH "RESULT DATA STRUCTURE" +.LP +The result of the DNS resolution and validation is returned as +\fIstruct ub_result\fR. The result structure contains the following entries. +.P +.nf + struct ub_result { + char* qname; /* text string, original question */ + int qtype; /* type code asked for */ + int qclass; /* class code asked for */ + char** data; /* array of rdata items, NULL terminated*/ + int* len; /* array with lengths of rdata items */ + char* canonname; /* canonical name of result */ + int rcode; /* additional error code in case of no data */ + void* answer_packet; /* full network format answer packet */ + int answer_len; /* length of packet in octets */ + int havedata; /* true if there is data */ + int nxdomain; /* true if nodata because name does not exist */ + int secure; /* true if result is secure */ + int bogus; /* true if a security failure happened */ + char* why_bogus; /* string with error if bogus */ + }; +.fi +.P +If both secure and bogus are false, security was not enabled for the +domain of the query. +.SH "RETURN VALUES" +Many routines return an error code. The value 0 (zero) denotes no error +happened. Other values can be passed to +.B ub_strerror +to obtain a readable error string. +.B ub_strerror +returns a zero terminated string. +.B ub_ctx_create +returns NULL on an error (a malloc failure). +.B ub_poll +returns true if some information may be available, false otherwise. +.B ub_fd +returns a file descriptor or \-1 on error. +.SH "SEE ALSO" +\fIunbound.conf\fR(5), +\fIunbound\fR(8). +.SH "AUTHORS" +.B Unbound +developers are mentioned in the CREDITS file in the distribution. diff --git a/doc/requirements.txt b/doc/requirements.txt new file mode 100644 index 00000000000..a66962d4a40 --- /dev/null +++ b/doc/requirements.txt @@ -0,0 +1,294 @@ +Requirements for Recursive Caching Resolver + (a.k.a. Treeshrew, Unbound-C) +By W.C.A. Wijngaards, NLnet Labs, October 2006. + +Contents +1. Introduction +2. History +3. Goals +4. Non-Goals + + +1. Introduction +--------------- +This is the requirements document for a DNS name server and aims to +document the goals and non-goals of the project. The DNS (the Domain +Name System) is a global, replicated database that uses a hierarchical +structure for queries. + +Data in the DNS is stored in Resource Record sets (RR sets), and has a +time to live (TTL). During this time the data can be cached. It is +thus useful to cache data to speed up future lookups. A server that +looks up data in the DNS for clients and caches previous answers to +speed up processing is called a caching, recursive nameserver. + +This project aims to develop such a nameserver in modular components, so +that also DNSSEC (secure DNS) validation and stub-resolvers (that do not +run as a server, but a linked into an application) are easily possible. + +The main components are the Validator that validates the security +fingerprints on data sets, the Iterator that sends queries to the +hierarchical DNS servers that own the data and the Cache that stores +data from previous queries. The networking and query management code +then interface with the modules to perform the necessary processing. + +In Section 2 the origins of the Unbound project are documented. Section +3 lists the goals, while Section 4 lists the explicit non-goals of the +project. Section 5 discusses choices made during development. + + +2. History +---------- +The unbound resolver project started by Bill Manning, David Blacka, and +Matt Larson (from the University of California and from Verisign), that +created a Java based prototype resolver called Unbound. The basic +design decisions of clean modules was executed. + +The Java prototype worked very well, with contributions from Geoff +Sisson and Roy Arends from Nominet. Around 2006 the idea came to create +a full-fledged C implementation ready for deployed use. NLnet Labs +volunteered to write this implementation. + + +3. Goals +-------- +o A validating recursive DNS resolver. +o Code diversity in the DNS resolver monoculture. +o Drop-in replacement for BIND apart from config. +o DNSSEC support. +o Fully RFC compliant. +o High performance + * even with validation. +o Used as + * stub resolver. + * full caching name server. + * resolver library. +o Elegant design of validator, resolver, cache modules. + * provide the ability to pick and choose modules. +o Robust. +o In C, open source: The BSD license. +o Highly portable, targets include modern Unix systems, such as *BSD, +solaris, linux, and maybe also the windows platform. +o Smallest as possible component that does the job. +o Stub-zones can be configured (local data or AS112 zones). + + +4. Non-Goals +------------ +o An authoritative name server. +o Too many Features. + + +5. Choices +---------- +o rfc2181 decourages duplicates RRs in RRsets. unbound does not create + duplicates, but when presented with duplicates on the wire from the + authoritative servers, does not perform duplicate removal. + It does do some rrsig duplicate removal, in the msgparser, for dnssec qtype + rrsig and any, because of special rrsig processing in the msgparser. +o The harden-glue feature, when yes all out of zone glue is deleted, when + no out of zone glue is used for further resolving, is more complicated + than that, see below. + Main points: + * rfc2182 trust handling is used. + * data is let through only in very specific cases + * spoofability remains possible. + Not all glue is let through (despite the name of the option). Only glue + which is present in a delegation, of type A and AAAA, where the name is + present in the NS record in the authority section is let through. + The glue that is let through is stored in the cache (marked as 'from the + additional section'). And will then be used for sending queries to. It + will not be present in the reply to the client (if RD is off). + A direct query for that name will attempt to get a msg into the message + cache. Since A and AAAA queries are not synthesized by the unbound cache, + this query will be (eventually) sent to the authoritative server and its + answer will be put in the cache, marked as 'from the answer section' and + thus remove the 'from the additional section' data, and this record is + returned to the client. + The message has a TTL smaller or equal to the TTL of the answer RR. + If the cache memory is low; the answer RR may be dropped, and a glue + RR may be inserted, within the message TTL time, and thus return the + spoofed glue to a client. When the message expires, it is refetched and + the cached RR is updated with the correct content. + The server can be spoofed by getting it to visit a especially prepared + domain. This domain then inserts an address for another authoritative + server into the cache, when visiting that other domain, this address may + then be used to send queries to. And fake answers may be returned. + If the other domain is signed by DNSSEC, the fakes will be detected. + + In summary, the harden glue feature presents a security risk if + disabled. Disabling the feature leads to possible better performance + as more glue is present for the recursive service to use. The feature + is implemented so as to minimise the security risk, while trying to + keep this performance gain. +o The method by which dnssec-lameness is detected is not secure. DNSSEC lame + is when a server has the zone in question, but lacks dnssec data, such as + signatures. The method to detect dnssec lameness looks at nonvalidated + data from the parent of a zone. This can be used, by spoofing the parent, + to create a false sense of dnssec-lameness in the child, or a false sense + or dnssec-non-lameness in the child. The first results in the server marked + lame, and not used for 900 seconds, and the second will result in a + validator failure (SERVFAIL again), when the query is validated later on. + + Concluding, a spoof of the parent delegation can be used for many cases + of denial of service. I.e. a completely different NS set could be returned, + or the information withheld. All of these alterations can be caught by + the validator if the parent is signed, and result in 900 seconds bogus. + The dnssec-lameness detection is used to detect operator failures, + before the validator will properly verify the messages. + + Also for zones for which no chain of trust exists, but a DS is given by the + parent, dnssec-lameness detection enables. This delivers dnssec to our + clients when possible (for client validators). + + The following issue needs to be resolved: + a server that serves both a parent and child zone, where + parent is signed, but child is not. The server must not be marked + lame for the parent zone, because the child answer is not signed. + Instead of a false positive, we want false negatives; failure to + detect dnssec-lameness is less of a problem than marking honest + servers lame. dnssec-lameness is a config error and deserves the trouble. + So, only messages that identify the zone are used to mark the zone + lame. The zone is identified by SOA or NS RRsets in the answer/auth. + That includes almost all negative responses and also A, AAAA qtypes. + That would be most responses from servers. + For referrals, delegations that add a single label can be checked to be + from their zone, this covers most delegation-centric zones. + + So possibly, for complicated setups, with multiple (parent-child) zones + on a server, dnssec-lameness detection does not work - no dnssec-lameness + is detected. Instead the zone that is dnssec-lame becomes bogus. + +o authority features. + This is a recursive server, and authority features are out of scope. + However, some authority features are expected in a recursor. Things like + localhost, reverse lookup for 127.0.0.1, or blocking AS112 traffic. + Also redirection of domain names with fixed data is needed by service + providers. Limited support is added specifically to address this. + + Adding full authority support, requires much more code, and more complex + maintenance. + + The limited support allows adding some static data (for localhost and so), + and to respond with a fixed rcode (NXDOMAIN) for domains (such as AS112). + + You can put authority data on a separate server, and set the server in + unbound.conf as stub for those zones, this allows clients to access data + from the server without making unbound authoritative for the zones. + +o the access control denies queries before any other processing. + This denies queries that are not authoritative, or version.bind, or any. + And thus prevents cache-snooping (denied hosts cannot make non-recursive + queries and get answers from the cache). + +o If a client makes a query without RD bit, in the case of a returned + message from cache which is: + answer section: empty + auth section: NS record present, no SOA record, no DS record, + maybe NSEC or NSEC3 records present. + additional: A records or other relevant records. + A SOA record would indicate that this was a NODATA answer. + A DS records would indicate a referral. + Absence of NS record would indicate a NODATA answer as well. + + Then the receiver does not know whether this was a referral + with attempt at no-DS proof) or a nodata answer with attempt + at no-data proof. It could be determined by attempting to prove + either condition; and looking if only one is valid, but both + proofs could be valid, or neither could be valid, which creates + doubt. This case is validated by unbound as a 'referral' which + ascertains that RRSIGs are OK (and not omitted), but does not + check NSEC/NSEC3. + +o Case preservation + Unbound preserves the casing received from authority servers as best + as possible. It compresses without case, so case can get lost there. + The casing from the query name is used in preference to the casing + of the authority server. This is the same as BIND. RFC4343 allows either + behaviour. + +o Denial of service protection + If many queries are made, and they are made to names for which the + authority servers do not respond, then the requestlist for unbound + fills up fast. This results in denial of service for new queries. + To combat this the first 50% of the requestlist can run to completion. + The last 50% of the requestlist get (200 msec) at least and are replaced + by newer queries when older (LIFO). + When a new query comes in, and a place in the first 50% is available, this + is preferred. Otherwise, it can replace older queries out of the last 50%. + Thus, even long queries get a 50% chance to be resolved. And many 'short' + one or two round-trip resolves can be done in the last 50% of the list. + The timeout can be configured. + +o EDNS fallback. Is done according to the EDNS RFC (and update draft-00). + Unbound assumes EDNS 0 support for the first query. Then it can detect + support (if the servers replies) or non-support (on a NOTIMPL or FORMERR). + Some middleboxes drop EDNS 0 queries, mainly when forwarding, not when + routing packets. To detect this, when timeouts keep happening, as the + timeout approached 5-10 seconds, and EDNS status has not been detected yet, + a single probe query is sent. This probe has a sub-second timeout, and + if the server responds (quickly) without EDNS, this is cached for 15 min. + This works very well when detecting an address that you use much - like + a forwarder address - which is where the middleboxes need to be detected. + Otherwise, it results in a 5 second wait time before EDNS timeout is + detected, which is slow but it works at least. + It minimizes the chances of a dropped query making a (DNSSEC) EDNS server + falsely EDNS-nonsupporting, and thus DNSSEC-bogus, works well with + middleboxes, and can detect the occasional authority that drops EDNS. + For some boxes it is necessary to probe for every failing query, a + reassurance that the DNS server does EDNS does not mean that path can + take large DNS answers. + +o 0x20 backoff. + The draft describes to back off to the next server, and go through all + servers several times. Unbound goes on get the full list of nameserver + addresses, and then makes 3 * number of addresses queries. + They are sent to a random server, but no one address more than 4 times. + It succeeds if one has 0x20 intact, or else all are equal. + Otherwise, servfail is returned to the client. + +o NXDOMAIN and SOA serial numbers. + Unbound keeps TTL values for message formats, and thus rcodes, such + as NXDOMAIN. Also it keeps the latest rrsets in the rrset cache. + So it will faithfully negative cache for the exact TTL as originally + specified for an NXDOMAIN message, but send a newer SOA record if + this has been found in the mean time. In point, this could lead to a + negative cached NXDOMAIN reply with a SOA RR where the serial number + indicates a zone version where this domain is not any longer NXDOMAIN. + These situations become consistent once the original TTL expires. + If the domain is DNSSEC signed, by the way, then NSEC records are + updated more carefully. If one of the NSEC records in an NXDOMAIN is + updated from another query, the NXDOMAIN is dropped from the cache, + and queried for again, so that its proof can be checked again. + +o SOA records in negative cached answers for DS queries. + The current unbound code uses a negative cache for queries for type DS. + This speeds up building chains of trust, and uses NSEC and NSEC3 + (optout) information to speed up lookups. When used internally, + the bare NSEC(3) information is sufficient, probably picked up from + a referral. When answering to clients, a SOA record is needed for + the correct message format, a SOA record is picked from the cache + (and may not actually match the serial number of the SOA for which the + NSEC and NSEC3 records were obtained) if available otherwise network + queries are performed to get the data. + +o Parent and child with different nameserver information. + A misconfiguration that sometimes happens is where the parent and child + have different NS, glue information. The child is authoritative, and + unbound will not trust information from the parent nameservers as the + final answer. To help lookups, unbound will however use the parent-side + version of the glue as a last resort lookup. This resolves lookups for + those misconfigured domains where the servers reported by the parent + are the only ones working, and servers reported by the child do not. + +o Failure of validation and probing. + Retries on a validation failure are now 5x to a different nameserver IP + (if possible), and then it gives up, for one name, type, class entry in + the message cache. If a DNSKEY or DS fails in the chain of trust in the + key cache additionally, after the probing, a bad key entry is created that + makes the entire zone bogus for 900 seconds. This is a fixed value at + this time and is conservative in sending probes. It makes the compound + effect of many resolvers less and easier to handle, but penalizes + individual resolvers by having less probes and a longer time before fixes + are picked up. + diff --git a/doc/unbound-anchor.8.in b/doc/unbound-anchor.8.in new file mode 100644 index 00000000000..b7f0bdaa43e --- /dev/null +++ b/doc/unbound-anchor.8.in @@ -0,0 +1,174 @@ +.TH "unbound-anchor" "8" "May 24, 2012" "NLnet Labs" "unbound 1.4.17" +.\" +.\" unbound-anchor.8 -- unbound anchor maintenance utility manual +.\" +.\" Copyright (c) 2008, NLnet Labs. All rights reserved. +.\" +.\" See LICENSE for the license. +.\" +.\" +.SH "NAME" +.LP +.B unbound\-anchor +\- Unbound anchor utility. +.SH "SYNOPSIS" +.B unbound\-anchor +.RB [ opts ] +.SH "DESCRIPTION" +.B Unbound\-anchor +performs setup or update of the root trust anchor for DNSSEC validation. +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 +Suggested usage: +.P +.nf + # in the init scripts. + # provide or update the root anchor (if necessary) + unbound-anchor -a "@UNBOUND_ROOTKEY_FILE@" + # Please note usage of this root anchor is at your own risk + # and under the terms of our LICENSE (see source). + # + # start validating resolver + # the unbound.conf contains: + # auto-trust-anchor-file: "@UNBOUND_ROOTKEY_FILE@" + unbound -c unbound.conf +.fi +.P +This tool provides builtin default contents for the root anchor and root +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 +the root anchor file is unchanged. It performs RFC5011 tracking if the +DNSSEC information available via the DNS makes that possible. +.P +If does not perform an update if the certificate is expired, if the network +is down or other errors occur. +.P +The available options are: +.TP +.B \-a \fIfile +The root anchor key file, that is read in and written out. +Default is @UNBOUND_ROOTKEY_FILE@. +If the file does not exist, or is empty, a builtin root key is written to it. +.TP +.B \-c \fIfile +The root update certificate file, that is read in. +Default is @UNBOUND_ROOTCERT_FILE@. +If the file does not exist, or is empty, a builtin certificate is used. +.TP +.B \-l +List the builtin root key and builtin root update certificate on stdout. +.TP +.B \-u \fIname +The server name, it connects to https://name. Specify without https:// prefix. +The default is "data.iana.org". It connects to the port specified with \-P. +You can pass an IPv4 addres or IPv6 address (no brackets) if you want. +.TP +.B \-x \fIpath +The pathname to the root\-anchors.xml file on the server. (forms URL with \-u). +The default is /root\-anchors/root\-anchors.xml. +.TP +.B \-s \fIpath +The pathname to the root\-anchors.p7s file on the server. (forms URL with \-u). +The default is /root\-anchors/root\-anchors.p7s. This file has to be a PKCS7 +signature over the xml file, using the pem file (\-c) as trust anchor. +.TP +.B \-4 +Use IPv4 for domain resolution and contacting the server on https. Default is +to use IPv4 and IPv6 where appropriate. +.TP +.B \-6 +Use IPv6 for domain resolution and contacting the server on https. Default is +to use IPv4 and IPv6 where appropriate. +.TP +.B \-f \fIresolv.conf +Use the given resolv.conf file. Not enabled by default, but you could try to +pass /etc/resolv.conf on some systems. It contains the IP addresses of the +recursive nameservers to use. However, since this tool could be used to +bootstrap that very recursive nameserver, it would not be useful (since +that server is not up yet, since we are bootstrapping it). It could be +useful in a situation where you know an upstream cache is deployed (and +running) and in captive portal situations. +.TP +.B \-r \fIroot.hints +Use the given root.hints file (same syntax as the BIND and Unbound root hints +file) to bootstrap domain resolution. By default a list of builtin root +hints is used. Unbound\-anchor goes to the network itself for these roots, +to resolve the server (\-u option) and to check the root DNSKEY records. +It does so, because the tool when used for bootstrapping the recursive +resolver, cannot use that recursive resolver itself because it is bootstrapping +that server. +.TP +.B \-v +More verbose. Once prints informational messages, multiple times may enable +large debug amounts (such as full certificates or byte\-dumps of downloaded +files). By default it prints almost nothing. It also prints nothing on +errors by default; in that case the original root anchor file is simply +left undisturbed, so that a recursive server can start right after it. +.TP +.B \-C \fIunbound.conf +Debug option to read unbound.conf into the resolver process used. +.TP +.B \-P \fIport +Set the port number to use for the https connection. The default is 443. +.TP +.B \-F +Debug option to force update of the root anchor through downloading the xml +file and verifying it with the certificate. By default it first tries to +update by contacting the DNS, which uses much less bandwidth, is much +faster (200 msec not 2 sec), and is nicer to the deployed infrastructure. +With this option, it still attempts to do so (and may verbosely tell you), +but then ignores the result and goes on to use the xml fallback method. +.TP +.B \-h +Show the version and commandline option help. +.TP +.B \-v +More verbose. Prints output detailing what happens. +.SH "EXIT CODE" +This tool exits with value 1 if the root anchor was updated using the +certificate or if the builtin root-anchor was used. It exits with code +0 if no update was necessary, if the update was possible with RFC5011 +tracking, or if an error occurred. +.P +You can check the exit value in this manner: +.nf + unbound-anchor -a "root.key" || logger "Please check root.key" +.fi +Or something more suitable for your operational environment. +.SH "TRUST" +The root keys and update certificate included in this tool +are provided for convenience and under the terms of our +license (see the LICENSE file in the source distribution or +http://unbound.nlnetlabs.nl/svn/trunk/LICENSE) and might be stale or +not suitable to your purpose. +.P +By running "unbound\-anchor \-l" the keys and certificate that are +configured in the code are printed for your convenience. +.P +The build\-in configuration can be overridden by providing a root\-cert +file and a rootkey file. +.SH "FILES" +.TP +.I @UNBOUND_ROOTKEY_FILE@ +The root anchor file, updated with 5011 tracking, and read and written to. +The file is created if it does not exist. +.TP +.I @UNBOUND_ROOTCERT_FILE@ +The trusted self\-signed certificate that is used to verify the downloaded +DNSSEC root trust anchor. You can update it by fetching it from +https://data.iana.org/root\-anchors/icannbundle.pem (and validate it). +If the file does not exist or is empty, a builtin version is used. +.TP +.I https://data.iana.org/root\-anchors/root\-anchors.xml +Source for the root key information. +.TP +.I https://data.iana.org/root\-anchors/root\-anchors.p7s +Signature on the root key information. +.SH "SEE ALSO" +\fIunbound.conf\fR(5), +\fIunbound\fR(8). diff --git a/doc/unbound-checkconf.8.in b/doc/unbound-checkconf.8.in new file mode 100644 index 00000000000..fdd7528a4fb --- /dev/null +++ b/doc/unbound-checkconf.8.in @@ -0,0 +1,49 @@ +.TH "unbound-checkconf" "8" "May 24, 2012" "NLnet Labs" "unbound 1.4.17" +.\" +.\" unbound-checkconf.8 -- unbound configuration checker manual +.\" +.\" Copyright (c) 2007, NLnet Labs. All rights reserved. +.\" +.\" See LICENSE for the license. +.\" +.\" +.SH "NAME" +.LP +unbound\-checkconf +\- Check unbound configuration file for errors. +.SH "SYNOPSIS" +.B unbound\-checkconf +.RB [ \-h ] +.RB [ \-o +.IR option ] +.RI [ cfgfile ] +.SH "DESCRIPTION" +.B Unbound\-checkconf +checks the configuration file for the +\fIunbound\fR(8) +DNS resolver for syntax and other errors. +The config file syntax is described in +\fIunbound.conf\fR(5). +.P +The available options are: +.TP +.B \-h +Show the version and commandline option help. +.TP +.B \-o\fI option +If given, after checking the config file the value of this option is +printed to stdout. For "" (disabled) options an empty line is printed. +.TP +.I cfgfile +The config file to read with settings for unbound. It is checked. +If omitted, the config file at the default location is checked. +.SH "EXIT CODE" +The unbound\-checkconf program exits with status code 1 on error, +0 for a correct config file. +.SH "FILES" +.TP +.I @ub_conf_file@ +unbound configuration file. +.SH "SEE ALSO" +\fIunbound.conf\fR(5), +\fIunbound\fR(8). diff --git a/doc/unbound-control.8.in b/doc/unbound-control.8.in new file mode 100644 index 00000000000..575f897829d --- /dev/null +++ b/doc/unbound-control.8.in @@ -0,0 +1,450 @@ +.TH "unbound-control" "8" "May 24, 2012" "NLnet Labs" "unbound 1.4.17" +.\" +.\" unbound-control.8 -- unbound remote control manual +.\" +.\" Copyright (c) 2008, NLnet Labs. All rights reserved. +.\" +.\" See LICENSE for the license. +.\" +.\" +.SH "NAME" +.LP +.B unbound\-control, +.B unbound\-control\-setup +\- Unbound remote server control utility. +.SH "SYNOPSIS" +.B unbound\-control +.RB [ \-h ] +.RB [ \-c +.IR cfgfile ] +.RB [ \-s +.IR server ] +.IR command +.SH "DESCRIPTION" +.B Unbound\-control +performs remote administration on the \fIunbound\fR(8) DNS server. +It reads the configuration file, contacts the unbound server over SSL +sends the command and displays the result. +.P +The available options are: +.TP +.B \-h +Show the version and commandline option help. +.TP +.B \-c \fIcfgfile +The config file to read with settings. If not given the default +config file @ub_conf_file@ is used. +.TP +.B \-s \fIserver[@port] +IPv4 or IPv6 address of the server to contact. If not given, the +address is read from the config file. +.SH "COMMANDS" +There are several commands that the server understands. +.TP +.B start +Start the server. Simply execs \fIunbound\fR(8). The unbound executable +is searched for in the \fBPATH\fR set in the environment. It is started +with the config file specified using \fI\-c\fR or the default config file. +.TP +.B stop +Stop the server. The server daemon exits. +.TP +.B reload +Reload the server. This flushes the cache and reads the config file fresh. +.TP +.B verbosity \fInumber +Change verbosity value for logging. Same values as \fBverbosity\fR keyword in +\fIunbound.conf\fR(5). This new setting lasts until the server is issued +a reload (taken from config file again), or the next verbosity control command. +.TP +.B log_reopen +Reopen the logfile, close and open it. Useful for logrotation to make the +daemon release the file it is logging to. If you are using syslog it will +attempt to close and open the syslog (which may not work if chrooted). +.TP +.B stats +Print statistics. Resets the internal counters to zero, this can be +controlled using the \fBstatistics\-cumulative\fR config statement. +Statistics are printed with one [name]: [value] per line. +.TP +.B stats_noreset +Peek at statistics. Prints them like the \fBstats\fR command does, but does not +reset the internal counters to zero. +.TP +.B status +Display server status. Exit code 3 if not running (the connection to the +port is refused), 1 on error, 0 if running. +.TP +.B local_zone \fIname\fR \fItype +Add new local zone with name and type. Like \fBlocal\-zone\fR config statement. +If the zone already exists, the type is changed to the given argument. +.TP +.B local_zone_remove \fIname +Remove the local zone with the given name. Removes all local data inside +it. If the zone does not exist, the command succeeds. +.TP +.B local_data \fIRR data... +Add new local data, the given resource record. Like \fBlocal\-data\fR +config statement, except for when no covering zone exists. In that case +this remote control command creates a transparent zone with the same +name as this record. This command is not good at returning detailed syntax +errors. +.TP +.B local_data_remove \fIname +Remove all RR data from local name. If the name already has no items, +nothing happens. Often results in NXDOMAIN for the name (in a static zone), +but if the name has become an empty nonterminal (there is still data in +domain names below the removed name), NOERROR nodata answers are the +result for that name. +.TP +.B dump_cache +The contents of the cache is printed in a text format to stdout. You can +redirect it to a file to store the cache in a file. +.TP +.B load_cache +The contents of the cache is loaded from stdin. Uses the same format as +dump_cache uses. Loading the cache with old, or wrong data can result +in old or wrong data returned to clients. Loading data into the cache +in this way is supported in order to aid with debugging. +.TP +.B lookup \fIname +Print to stdout the name servers that would be used to look up the +name specified. +.TP +.B flush \fIname +Remove the name from the cache. Removes the types +A, AAAA, NS, SOA, CNAME, DNAME, MX, PTR, SRV and NAPTR. +Because that is fast to do. Other record types can be removed using +.B flush_type +or +.B flush_zone\fR. +.TP +.B flush_type \fIname\fR \fItype +Remove the name, type information from the cache. +.TP +.B flush_zone \fIname +Remove all information at or below the name from the cache. +The rrsets and key entries are removed so that new lookups will be performed. +This needs to walk and inspect the entire cache, and is a slow operation. +.TP +.B flush_stats +Reset statistics to zero. +.TP +.B flush_requestlist +Drop the queries that are worked on. Stops working on the queries that the +server is working on now. The cache is unaffected. No reply is sent for +those queries, probably making those users request again later. +Useful to make the server restart working on queries with new settings, +such as a higher verbosity level. +.TP +.B dump_requestlist +Show what is worked on. Prints all queries that the server is currently +working on. Prints the time that users have been waiting. For internal +requests, no time is printed. And then prints out the module status. +.TP +.B flush_infra \fIall|IP +If all then entire infra cache is emptied. If a specific IP address, the +entry for that address is removed from the cache. It contains EDNS, ping +and lameness data. +.TP +.B dump_infra +Show the contents of the infra cache. +.TP +.B set_option \fIopt: val +Set the option to the given value without a reload. The cache is +therefore not flushed. The option must end with a ':' and whitespace +must be between the option and the value. Some values may not have an +effect if set this way, the new values are not written to the config file, +not all options are supported. This is different from the set_option call +in libunbound, where all values work because unbound has not been inited. +.IP +The values that work are: statistics\-interval, statistics\-cumulative, +do\-not\-query\-localhost, harden\-short\-bufsize, harden\-large\-queries, +harden\-glue, harden\-dnssec\-stripped, harden\-below\-nxdomain, +harden\-referral\-path, prefetch, prefetch\-key, log\-queries, +hide\-identity, hide\-version, identity, version, val\-log\-level, +val\-log\-squelch, ignore\-cd\-flag, add\-holddown, del\-holddown, +keep\-missing, tcp\-upstream, ssl\-upstream. +.TP +.B get_option \fIopt +Get the value of the option. Give the option name without a trailing ':'. +The value is printed. If the value is "", nothing is printed +and the connection closes. On error 'error ...' is printed (it gives +a syntax error on unknown option). For some options a list of values, +one on each line, is printed. The options are shown from the config file +as modified with set_option. For some options an override may have been +taken that does not show up with this command, not results from e.g. the +verbosity and forward control commands. Not all options work, see list_stubs, +list_forwards, list_local_zones and list_local_data for those. +.TP +.B list_stubs +List the stub zones in use. These are printed one by one to the output. +This includes the root hints in use. +.TP +.B list_forwards +List the forward zones in use. These are printed zone by zone to the output. +.TP +.B list_local_zones +List the local zones in use. These are printed one per line with zone type. +.TP +.B list_local_data +List the local data RRs in use. The resource records are printed. +.TP +.B forward_add \fR[\fI+i\fR] \fIzone addr ... +Add a new forward zone to running unbound. With +i option also adds a +\fIdomain\-insecure\fR for the zone (so it can resolve insecurely if you have +a DNSSEC root trust anchor configured for other names). +The addr can be IP4, IP6 or nameserver names, like \fIforward-zone\fR config +in unbound.conf. +.TP +.B forward_remove \fR[\fI+i\fR] \fIzone +Remove a forward zone from running unbound. The +i also removes a +\fIdomain\-insecure\fR for the zone. +.TP +.B stub_add \fR[\fI+ip\fR] \fIzone addr ... +Add a new stub zone to running unbound. With +i option also adds a +\fIdomain\-insecure\fR for the zone. With +p the stub zone is set to prime, +without it it is set to notprime. The addr can be IP4, IP6 or nameserver +names, like the \fIstub-zone\fR config in unbound.conf. +.TP +.B stub_remove \fR[\fI+i\fR] \fIzone +Remove a stub zone from running unbound. The +i also removes a +\fIdomain\-insecure\fR for the zone. +.TP +.B forward \fR[\fIoff\fR | \fIaddr ...\fR ] +Setup forwarding mode. Configures if the server should ask other upstream +nameservers, should go to the internet root nameservers itself, or show +the current config. You could pass the nameservers after a DHCP update. +.IP +Without arguments the current list of addresses used to forward all queries +to is printed. On startup this is from the forward\-zone "." configuration. +Afterwards it shows the status. It prints off when no forwarding is used. +.IP +If \fIoff\fR is passed, forwarding is disabled and the root nameservers +are used. This can be used to avoid to avoid buggy or non\-DNSSEC supporting +nameservers returned from DHCP. But may not work in hotels or hotspots. +.IP +If one or more IPv4 or IPv6 addresses are given, those are then used to forward +queries to. The addresses must be separated with spaces. With '@port' the +port number can be set explicitly (default port is 53 (DNS)). +.IP +By default the forwarder information from the config file for the root "." is +used. The config file is not changed, so after a reload these changes are +gone. Other forward zones from the config file are not affected by this command. +.SH "EXIT CODE" +The unbound\-control program exits with status code 1 on error, 0 on success. +.SH "SET UP" +The setup requires a self\-signed certificate and private keys for both +the server and client. The script \fIunbound\-control\-setup\fR generates +these in the default run directory, or with \-d in another directory. +If you change the access control permissions on the key files you can decide +who can use unbound\-control, by default owner and group but not all users. +Run the script under the same username as you have configured in unbound.conf +or as root, so that the daemon is permitted to read the files, for example with: +.nf + sudo \-u unbound unbound\-control\-setup +.fi +If you have not configured +a username in unbound.conf, the keys need read permission for the user +credentials under which the daemon is started. +The script preserves private keys present in the directory. +After running the script as root, turn on \fBcontrol\-enable\fR in +\fIunbound.conf\fR. +.SH "STATISTIC COUNTERS" +The \fIstats\fR command shows a number of statistic counters. +.TP +.I threadX.num.queries +number of queries received by thread +.TP +.I threadX.num.cachehits +number of queries that were successfully answered using a cache lookup +.TP +.I threadX.num.cachemiss +number of queries that needed recursive processing +.TP +.I threadX.num.prefetch +number of cache prefetches performed. This number is included in +cachehits, as the original query had the unprefetched answer from cache, +and resulted in recursive processing, taking a slot in the requestlist. +Not part of the recursivereplies (or the histogram thereof) or cachemiss, +as a cache response was sent. +.TP +.I threadX.num.recursivereplies +The number of replies sent to queries that needed recursive processing. Could be smaller than threadX.num.cachemiss if due to timeouts no replies were sent for some queries. +.TP +.I threadX.requestlist.avg +The average number of requests in the internal recursive processing request list on insert of a new incoming recursive processing query. +.TP +.I threadX.requestlist.max +Maximum size attained by the internal recursive processing request list. +.TP +.I threadX.requestlist.overwritten +Number of requests in the request list that were overwritten by newer entries. This happens if there is a flood of queries that recursive processing and the server has a hard time. +.TP +.I threadX.requestlist.exceeded +Queries that were dropped because the request list was full. This happens if a flood of queries need recursive processing, and the server can not keep up. +.TP +.I threadX.requestlist.current.all +Current size of the request list, includes internally generated queries (such +as priming queries and glue lookups). +.TP +.I threadX.requestlist.current.user +Current size of the request list, only the requests from client queries. +.TP +.I threadX.recursion.time.avg +Average time it took to answer queries that needed recursive processing. Note that queries that were answered from the cache are not in this average. +.TP +.I threadX.recursion.time.median +The median of the time it took to answer queries that needed recursive +processing. The median means that 50% of the user queries were answered in +less than this time. Because of big outliers (usually queries to non +responsive servers), the average can be bigger than the median. This median +has been calculated by interpolation from a histogram. +.TP +.I total.num.queries +summed over threads. +.TP +.I total.num.cachehits +summed over threads. +.TP +.I total.num.cachemiss +summed over threads. +.TP +.I total.num.prefetch +summed over threads. +.TP +.I total.num.recursivereplies +summed over threads. +.TP +.I total.requestlist.avg +averaged over threads. +.TP +.I total.requestlist.max +the maximum of the thread requestlist.max values. +.TP +.I total.requestlist.overwritten +summed over threads. +.TP +.I total.requestlist.exceeded +summed over threads. +.TP +.I total.requestlist.current.all +summed over threads. +.TP +.I total.recursion.time.median +averaged over threads. +.TP +.I time.now +current time in seconds since 1970. +.TP +.I time.up +uptime since server boot in seconds. +.TP +.I time.elapsed +time since last statistics printout, in seconds. +.SH EXTENDED STATISTICS +.TP +.I mem.total.sbrk +If sbrk(2) is available, an estimate of the heap size of the program in number of bytes. Close to the total memory used by the program, as reported by top and ps. Could be wrong if the OS allocates memory non\-contiguously. +.TP +.I mem.cache.rrset +Memory in bytes in use by the RRset cache. +.TP +.I mem.cache.message +Memory in bytes in use by the message cache. +.TP +.I mem.mod.iterator +Memory in bytes in use by the iterator module. +.TP +.I mem.mod.validator +Memory in bytes in use by the validator module. Includes the key cache and +negative cache. +.TP +.I histogram...to.. +Shows a histogram, summed over all threads. Every element counts the +recursive queries whose reply time fit between the lower and upper bound. +Times larger or equal to the lowerbound, and smaller than the upper bound. +There are 40 buckets, with bucket sizes doubling. +.TP +.I num.query.type.A +The total number of queries over all threads with query type A. +Printed for the other query types as well, but only for the types for which +queries were received, thus =0 entries are omitted for brevity. +.TP +.I num.query.type.other +Number of queries with query types 256\-65535. +.TP +.I num.query.class.IN +The total number of queries over all threads with query class IN (internet). +Also printed for other classes (such as CH (CHAOS) sometimes used for +debugging), or NONE, ANY, used by dynamic update. +num.query.class.other is printed for classes 256\-65535. +.TP +.I num.query.opcode.QUERY +The total number of queries over all threads with query opcode QUERY. +Also printed for other opcodes, UPDATE, ... +.TP +.I num.query.tcp +Number of queries that were made using TCP towards the unbound server. +.TP +.I num.query.ipv6 +Number of queries that were made using IPv6 towards the unbound server. +.TP +.I num.query.flags.RD +The number of queries that had the RD flag set in the header. +Also printed for flags QR, AA, TC, RA, Z, AD, CD. +Note that queries with flags QR, AA or TC may have been rejected +because of that. +.TP +.I num.query.edns.present +number of queries that had an EDNS OPT record present. +.TP +.I num.query.edns.DO +number of queries that had an EDNS OPT record with the DO (DNSSEC OK) bit set. +These queries are also included in the num.query.edns.present number. +.TP +.I num.answer.rcode.NXDOMAIN +The number of answers to queries, from cache or from recursion, that had the +return code NXDOMAIN. Also printed for the other return codes. +.TP +.I num.answer.rcode.nodata +The number of answers to queries that had the pseudo return code nodata. +This means the actual return code was NOERROR, but additionally, no data was +carried in the answer (making what is called a NOERROR/NODATA answer). +These queries are also included in the num.answer.rcode.NOERROR number. +Common for AAAA lookups when an A record exists, and no AAAA. +.TP +.I num.answer.secure +Number of answers that were secure. The answer validated correctly. +The AD bit might have been set in some of these answers, where the client +signalled (with DO or AD bit in the query) that they were ready to accept +the AD bit in the answer. +.TP +.I num.answer.bogus +Number of answers that were bogus. These answers resulted in SERVFAIL +to the client because the answer failed validation. +.TP +.I num.rrset.bogus +The number of rrsets marked bogus by the validator. Increased for every +RRset inspection that fails. +.TP +.I unwanted.queries +Number of queries that were refused or dropped because they failed the +access control settings. +.TP +.I unwanted.replies +Replies that were unwanted or unsolicited. Could have been random traffic, +delayed duplicates, very late answers, or could be spoofing attempts. +Some low level of late answers and delayed duplicates are to be expected +with the UDP protocol. Very high values could indicate a threat (spoofing). +.SH "FILES" +.TP +.I @ub_conf_file@ +unbound configuration file. +.TP +.I @UNBOUND_RUN_DIR@ +directory with private keys (unbound_server.key and unbound_control.key) and +self\-signed certificates (unbound_server.pem and unbound_control.pem). +.SH "SEE ALSO" +\fIunbound.conf\fR(5), +\fIunbound\fR(8). diff --git a/doc/unbound-host.1 b/doc/unbound-host.1 new file mode 100644 index 00000000000..3848e5c3f19 --- /dev/null +++ b/doc/unbound-host.1 @@ -0,0 +1,116 @@ +.TH "unbound\-host" "1" "May 24, 2012" "NLnet Labs" "unbound 1.4.17" +.\" +.\" unbound-host.1 -- unbound DNS lookup utility +.\" +.\" Copyright (c) 2007, NLnet Labs. All rights reserved. +.\" +.\" See LICENSE for the license. +.\" +.\" +.SH "NAME" +.LP +.B unbound\-host +\- unbound DNS lookup utility +.SH "SYNOPSIS" +.LP +.B unbound\-host +.RB [ \-vdhr46 ] +.RB [ \-c +.IR class ] +.RB [ \-t +.IR type ] +.I hostname +.RB [ \-y +.IR key ] +.RB [ \-f +.IR keyfile ] +.RB [ \-F +.IR namedkeyfile ] +.RB [ \-C +.IR configfile ] +.SH "DESCRIPTION" +.LP +.B Unbound\-host +uses the unbound validating resolver to query for the hostname and display +results. With the \fB\-v\fR option it displays validation +status: secure, insecure, bogus (security failure). +.P +By default it reads no configuration file whatsoever. It attempts to reach +the internet root servers. With \fB\-C\fR an unbound config file and with +\fB\-r\fR resolv.conf can be read. +.P +The available options are: +.TP +.I hostname +This name is resolved (looked up in the DNS). +If a IPv4 or IPv6 address is given, a reverse lookup is performed. +.TP +.B \-h +Show the version and commandline option help. +.TP +.B \-v +Enable verbose output and it shows validation results, on every line. +Secure means that the NXDOMAIN (no such domain name), nodata (no such data) +or positive data response validated correctly with one of the keys. +Insecure means that that domain name has no security set up for it. +Bogus (security failure) means that the response failed one or more checks, +it is likely wrong, outdated, tampered with, or broken. +.TP +.B \-d +Enable debug output to stderr. One \-d shows what the resolver and validator +are doing and may tell you what is going on. More times, \-d \-d, gives a +lot of output, with every packet sent and received. +.TP +.B \-c \fIclass +Specify the class to lookup for, the default is IN the internet class. +.TP +.B \-t \fItype +Specify the type of data to lookup. The default looks for IPv4, IPv6 and +mail handler data, or domain name pointers for reverse queries. +.TP +.B \-y \fIkey +Specify a public key to use as trust anchor. This is the base for a chain +of trust that is built up from the trust anchor to the response, in order +to validate the response message. Can be given as a DS or DNSKEY record. +For example \-y "example.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546CD". +.TP +.B \-f \fIkeyfile +Reads keys from a file. Every line has a DS or DNSKEY record, in the format +as for \-y. The zone file format, the same as dig and drill produce. +.TP +.B \-F \fInamedkeyfile +Reads keys from a BIND\-style named.conf file. Only the trusted\-key {}; entries +are read. +.TP +.B \-C \fIconfigfile +Uses the specified unbound.conf to prime +.IR libunbound (3). +.TP +.B \-r +Read /etc/resolv.conf, and use the forward DNS servers from there (those could +have been set by DHCP). More info in +.IR resolv.conf (5). +Breaks validation if those servers do not support DNSSEC. +.TP +.B \-4 +Use solely the IPv4 network for sending packets. +.TP +.B \-6 +Use solely the IPv6 network for sending packets. +.SH "EXAMPLES" +.LP +Some examples of use. The keys shown below are fakes, thus a security failure +is encountered. +.P +$ unbound\-host www.example.com +.P +$ unbound\-host \-v \-y "example.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546CD" www.example.com +.P +$ unbound\-host \-v \-y "example.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546CD" 192.0.2.153 +.SH "EXIT CODE" +The unbound\-host program exits with status code 1 on error, +0 on no error. The data may not be available on exit code 0, exit code 1 +means the lookup encountered a fatal error. +.SH "SEE ALSO" +\fIunbound.conf\fR(5), +\fIunbound\fR(8). diff --git a/doc/unbound.8.in b/doc/unbound.8.in new file mode 100644 index 00000000000..06cf588d026 --- /dev/null +++ b/doc/unbound.8.in @@ -0,0 +1,51 @@ +.TH "unbound" "8" "May 24, 2012" "NLnet Labs" "unbound 1.4.17" +.\" +.\" unbound.8 -- unbound manual +.\" +.\" Copyright (c) 2007, NLnet Labs. All rights reserved. +.\" +.\" See LICENSE for the license. +.\" +.\" +.SH "NAME" +.LP +.B unbound +\- Unbound DNS validating resolver 1.4.17. +.SH "SYNOPSIS" +.LP +.B unbound +.RB [ \-h ] +.RB [ \-d ] +.RB [ \-v ] +.RB [ \-c +.IR cfgfile ] +.SH "DESCRIPTION" +.LP +.B Unbound +is an implementation of a DNS resolver, that does caching and +DNSSEC validation. +.P +The available options are: +.TP +.B \-h +Show the version and commandline option help. +.TP +.B \-c\fI cfgfile +Set the config file with settings for unbound to read instead of reading the +file at the default location, @ub_conf_file@. The syntax is +described in \fIunbound.conf\fR(5). +.TP +.B \-d +Debug flag, do not fork into the background, but stay attached to the +console. This flag will also delay writing to the logfile until the +thread\-spawn time. So that most config and setup errors appear on stderr. +.TP +.B \-v +Increase verbosity. If given multiple times, more information is logged. +This is in addition to the verbosity (if any) from the config file. +.SH "SEE ALSO" +\fIunbound.conf\fR(5), +\fIunbound\-checkconf\fR(8). +.SH "AUTHORS" +.B Unbound +developers are mentioned in the CREDITS file in the distribution. diff --git a/doc/unbound.conf.5.in b/doc/unbound.conf.5.in new file mode 100644 index 00000000000..32188752c70 --- /dev/null +++ b/doc/unbound.conf.5.in @@ -0,0 +1,1094 @@ +.TH "unbound.conf" "5" "May 24, 2012" "NLnet Labs" "unbound 1.4.17" +.\" +.\" unbound.conf.5 -- unbound.conf manual +.\" +.\" Copyright (c) 2007, NLnet Labs. All rights reserved. +.\" +.\" See LICENSE for the license. +.\" +.\" +.SH "NAME" +.LP +.B unbound.conf +\- Unbound configuration file. +.SH "SYNOPSIS" +.LP +.B unbound.conf +.SH "DESCRIPTION" +.LP +.B unbound.conf +is used to configure +\fIunbound\fR(8). +The file format has attributes and values. Some attributes have attributes inside them. +The notation is: attribute: value. +.P +Comments start with # and last to the end of line. Empty lines are +ignored as is whitespace at the beginning of a line. +.P +The utility +\fIunbound\-checkconf\fR(8) +can be used to check unbound.conf prior to usage. +.SH "EXAMPLE" +An example config file is shown below. Copy this to /etc/unbound/unbound.conf +and start the server with: +.P +.nf + $ unbound \-c /etc/unbound/unbound.conf +.fi +.P +Most settings are the defaults. Stop the server with: +.P +.nf + $ kill `cat /etc/unbound/unbound.pid` +.fi +.P +Below is a minimal config file. The source distribution contains an extensive +example.conf file with all the options. +.P +.nf +# unbound.conf(5) config file for unbound(8). +server: + directory: "/etc/unbound" + username: unbound + # make sure unbound can access entropy from inside the chroot. + # e.g. on linux the use these commands (on BSD, devfs(8) is used): + # mount \-\-bind \-n /dev/random /etc/unbound/dev/random + # and mount \-\-bind \-n /dev/log /etc/unbound/dev/log + chroot: "/etc/unbound" + # logfile: "/etc/unbound/unbound.log" #uncomment to use logfile. + pidfile: "/etc/unbound/unbound.pid" + # verbosity: 1 # uncomment and increase to get more logging. + # listen on all interfaces, answer queries from the local subnet. + interface: 0.0.0.0 + interface: ::0 + access\-control: 10.0.0.0/8 allow + access\-control: 2001:DB8::/64 allow +.fi +.SH "FILE FORMAT" +.LP +There must be whitespace between keywords. Attribute keywords end with a colon ':'. An attribute +is followed by its containing attributes, or a value. +.P +Files can be included using the +.B include: +directive. It can appear anywhere, and takes a single filename as an argument. +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. +.SS "Server Options" +These options are part of the +.B server: +clause. +.TP +.B verbosity: \fI +The verbosity number, level 0 means no verbosity, only errors. Level 1 +gives operational information. Level 2 gives detailed operational +information. Level 3 gives query level information, output per query. +Level 4 gives algorithm level information. Level 5 logs client +identification for cache misses. Default is level 1. +The verbosity can also be increased from the commandline, see \fIunbound\fR(8). +.TP +.B statistics\-interval: \fI +The number of seconds between printing statistics to the log for every thread. +Disable with value 0 or "". Default is disabled. The histogram statistics +are only printed if replies were sent during the statistics interval, +requestlist statistics are printed for every interval (but can be 0). +This is because the median calculation requires data to be present. +.TP +.B statistics\-cumulative: \fI +If enabled, statistics are cumulative since starting unbound, without clearing +the statistics counters after logging the statistics. Default is no. +.TP +.B extended\-statistics: \fI +If enabled, extended statistics are printed from \fIunbound\-control\fR(8). +Default is off, because keeping track of more statistics takes time. The +counters are listed in \fIunbound\-control\fR(8). +.TP +.B num\-threads: \fI +The number of threads to create to serve clients. Use 1 for no threading. +.TP +.B port: \fI +The port number, default 53, on which the server responds to queries. +.TP +.B interface: \fI +Interface to use to connect to the network. This interface is listened to +for queries from clients, and answers to clients are given from it. +Can be given multiple times to work on several interfaces. If none are +given the default is to listen to localhost. +The interfaces are not changed on a reload (kill \-HUP) but only on restart. +A port number can be specified with @port (without spaces between +interface and port number), if not specified the default port (from +\fBport\fR) is used. +.TP +.B interface\-automatic: \fI +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 +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 +default (all) is used. You can specify the same interfaces in +.B interface: +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. +.TP +.B outgoing\-range: \fI +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. +.TP +.B outgoing\-port\-permit: \fI +Permit unbound to open this port or range of ports for use to send queries. +A larger number of permitted outgoing ports increases resilience against +spoofing attempts. Make sure these ports are not needed by other daemons. +By default only ports above 1024 that have not been assigned by IANA are used. +Give a port number or a range of the form "low\-high", without spaces. +.IP +The \fBoutgoing\-port\-permit\fR and \fBoutgoing\-port\-avoid\fR statements +are processed in the line order of the config file, adding the permitted ports +and subtracting the avoided ports from the set of allowed ports. The +processing starts with the non IANA allocated ports above 1024 in the set +of allowed ports. +.TP +.B outgoing\-port\-avoid: \fI +Do not permit unbound to open this port or range of ports for use to send +queries. Use this to make sure unbound does not grab a port that another +daemon needs. The port is avoided on all outgoing interfaces, both IP4 and IP6. +By default only ports above 1024 that have not been assigned by IANA are used. +Give a port number or a range of the form "low\-high", without spaces. +.TP +.B outgoing\-num\-tcp: \fI +Number of outgoing TCP buffers to allocate per thread. Default is 10. If set +to 0, or if do_tcp is "no", no TCP queries to authoritative servers are done. +.TP +.B incoming\-num\-tcp: \fI +Number of incoming TCP buffers to allocate per thread. Default is 10. If set +to 0, or if do_tcp is "no", no TCP queries from clients are accepted. +.TP +.B edns\-buffer\-size: \fI +Number of bytes size to advertise as the EDNS reassembly buffer size. +This is the value put into datagrams over UDP towards peers. The actual +buffer size is determined by msg\-buffer\-size (both for TCP and UDP). Do +not set lower than that value. Default is 4096 which is RFC recommended. +If you have fragmentation reassembly problems, usually seen as timeouts, +then a value of 1480 can fix it. Setting to 512 bypasses even the most +stringent path MTU problems, but is seen as extreme, since the amount +of TCP fallback generated is excessive (probably also for this resolver, +consider tuning the outgoing tcp number). +.TP +.B msg\-buffer\-size: \fI +Number of bytes size of the message buffers. Default is 65552 bytes, enough +for 64 Kb packets, the maximum DNS message size. No message larger than this +can be sent or received. Can be reduced to use less memory, but some requests +for DNS data, such as for huge resource records, will result in a SERVFAIL +reply to the client. +.TP +.B msg\-cache\-size: \fI +Number of bytes size of the message cache. Default is 4 megabytes. +A plain number is in bytes, append 'k', 'm' or 'g' for kilobytes, megabytes +or gigabytes (1024*1024 bytes in a megabyte). +.TP +.B msg\-cache\-slabs: \fI +Number of slabs in the message cache. Slabs reduce lock contention by threads. +Must be set to a power of 2. Setting (close) to the number of cpus is a +reasonable guess. +.TP +.B num\-queries\-per\-thread: \fI +The number of queries that every thread will service simultaneously. +If more queries arrive that need servicing, and no queries can be jostled out +(see \fIjostle\-timeout\fR), then the queries are dropped. This forces +the client to resend after a timeout; allowing the server time to work on +the existing queries. Default depends on compile options, 512 or 1024. +.TP +.B jostle\-timeout: \fI +Timeout used when the server is very busy. Set to a value that usually +results in one roundtrip to the authority servers. If too many queries +arrive, then 50% of the queries are allowed to run to completion, and +the other 50% are replaced with the new incoming query if they have already +spent more than their allowed time. This protects against denial of +service by slow queries or high query rates. Default 200 milliseconds. +The effect is that the qps for long-lasting queries is about +(numqueriesperthread / 2) / (average time for such long queries) qps. +The qps for short queries can be about (numqueriesperthread / 2) +/ (jostletimeout in whole seconds) qps per thread, about (1024/2)*5 = 2560 +qps by default. +.TP +.B so\-rcvbuf: \fI +If not 0, then set the SO_RCVBUF socket option to get more buffer +space on UDP port 53 incoming queries. So that short spikes on busy +servers do not drop packets (see counter in netstat \-su). Default is +0 (use system value). Otherwise, the number of bytes to ask for, try +"4m" on a busy server. The OS caps it at a maximum, on linux unbound +needs root permission to bypass the limit, or the admin can use sysctl +net.core.rmem_max. On BSD change kern.ipc.maxsockbuf in /etc/sysctl.conf. +On OpenBSD change header and recompile kernel. On Solaris ndd \-set +/dev/udp udp_max_buf 8388608. +.TP +.B so\-sndbuf: \fI +If not 0, then set the SO_SNDBUF socket option to get more buffer space on +UDP port 53 outgoing queries. This for very busy servers handles spikes +in answer traffic, otherwise 'send: resource temporarily unavailable' +can get logged, the buffer overrun is also visible by netstat \-su. +Default is 0 (use system value). Specify the number of bytes to ask +for, try "4m" on a very busy server. The OS caps it at a maximum, on +linux unbound needs root permission to bypass the limit, or the admin +can use sysctl net.core.wmem_max. On BSD, Solaris changes are similar +to so\-rcvbuf. +.TP +.B rrset\-cache\-size: \fI +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 +or gigabytes (1024*1024 bytes in a megabyte). +.TP +.B rrset\-cache\-slabs: \fI +Number of slabs in the RRset cache. Slabs reduce lock contention by threads. +Must be set to a power of 2. +.TP +.B cache\-max\-ttl: \fI +Time to live maximum for RRsets and messages in the cache. Default is +86400 seconds (1 day). If the maximum kicks in, responses to clients +still get decrementing TTLs based on the original (larger) values. +When the internal TTL expires, the cache item has expired. +Can be set lower to force the resolver to query for data often, and not +trust (very large) TTL values. +.TP +.B cache\-min\-ttl: \fI +Time to live minimum for RRsets and messages in the cache. Default is 0. +If the the minimum kicks in, the data is cached for longer than the domain +owner intended, and thus less queries are made to look up the data. +Zero makes sure the data in the cache is as the domain owner intended, +higher values, especially more than an hour or so, can lead to trouble as +the data in the cache does not match up with the actual data any more. +.TP +.B infra\-host\-ttl: \fI +Time to live for entries in the host cache. The host cache contains +roundtrip timing, lameness and EDNS support information. Default is 900. +.TP +.B infra\-cache\-slabs: \fI +Number of slabs in the infrastructure cache. Slabs reduce lock contention +by threads. Must be set to a power of 2. +.TP +.B infra\-cache\-numhosts: \fI +Number of hosts for which information is cached. Default is 10000. +.TP +.B do\-ip4: \fI +Enable or disable whether ip4 queries are answered or issued. Default is yes. +.TP +.B do\-ip6: \fI +Enable or disable whether ip6 queries are answered or issued. Default is yes. +If disabled, queries are not answered on IPv6, and queries are not sent on +IPv6 to the internet nameservers. +.TP +.B do\-udp: \fI +Enable or disable whether UDP queries are answered or issued. Default is yes. +.TP +.B do\-tcp: \fI +Enable or disable whether TCP queries are answered or issued. Default is yes. +.TP +.B tcp\-upstream: \fI +Enable or disable whether the upstream queries use TCP only for transport. +Default is no. Useful in tunneling scenarios. +.TP +.B ssl\-upstream: \fI +Enabled or disable whether the upstream queries use SSL only for transport. +Default is no. Useful in tunneling scenarios. The SSL contains plain DNS in +TCP wireformat. The other server must support this (see \fBssl\-service\-key\fR). +.TP +.B ssl\-service-key: \fI +If enabled, the server provider SSL service on its TCP sockets. The clients +have to use ssl\-upstream: yes. The file is the private key for the TLS +session. The public certificate is in the ssl\-service\-pem file. Default +is "", turned off. Requires a restart (a reload is not enough) if changed, +because the private key is read while root permissions are held and before +chroot (if any). Normal DNS TCP service is not provided and gives errors, +this service is best run with a different \fBport:\fR config or \fI@port\fR +suffixes in the \fBinterface\fR config. +.TP +.B ssl\-service\-pem: \fI +The public key certificate pem file for the ssl service. Default is "", +turned off. +.TP +.B ssl\-port: \fI +The port number on which to provide TCP SSL service, default 443, only +interfaces configured with that port number as @number get the SSL service. +.TP +.B do\-daemonize: \fI +Enable or disable whether the unbound server forks into the background as +a daemon. Default is yes. +.TP +.B access\-control: \fI +The netblock is given as an IP4 or IP6 address with /size appended for a +classless network block. The action can be \fIdeny\fR, \fIrefuse\fR, +\fIallow\fR or \fIallow_snoop\fR. +.IP +The action \fIdeny\fR stops queries from hosts from that netblock. +.IP +The action \fIrefuse\fR stops queries too, but sends a DNS rcode REFUSED +error message back. +.IP +The action \fIallow\fR gives access to clients from that netblock. +It gives only access for recursion clients (which is +what almost all clients need). Nonrecursive queries are refused. +.IP +The \fIallow\fR action does allow nonrecursive queries to access the +local\-data that is configured. The reason is that this does not involve +the unbound server recursive lookup algorithm, and static data is served +in the reply. This supports normal operations where nonrecursive queries +are made for the authoritative data. For nonrecursive queries any replies +from the dynamic cache are refused. +.IP +The action \fIallow_snoop\fR gives nonrecursive access too. This give +both recursive and non recursive access. The name \fIallow_snoop\fR refers +to cache snooping, a technique to use nonrecursive queries to examine +the cache contents (for malicious acts). However, nonrecursive queries can +also be a valuable debugging tool (when you want to examine the cache +contents). In that case use \fIallow_snoop\fR for your administration host. +.IP +By default only localhost is \fIallow\fRed, the rest is \fIrefuse\fRd. +The default is \fIrefuse\fRd, because that is protocol\-friendly. The DNS +protocol is not designed to handle dropped packets due to policy, and +dropping may result in (possibly excessive) retried queries. +.TP +.B chroot: \fI +If chroot is enabled, you should pass the configfile (from the +commandline) as a full path from the original root. After the +chroot has been performed the now defunct portion of the config +file path is removed to be able to reread the config after a reload. +.IP +All other file paths (working dir, logfile, roothints, and +key files) can be specified in several ways: +as an absolute path relative to the new root, +as a relative path to the working directory, or +as an absolute path relative to the original root. +In the last case the path is adjusted to remove the unused portion. +.IP +The pidfile can be either a relative path to the working directory, or +an absolute path relative to the original root. It is written just prior +to chroot and dropping permissions. This allows the pidfile to be +/var/run/unbound.pid and the chroot to be /var/unbound, for example. +.IP +Additionally, unbound may need to access /dev/random (for entropy) +from inside the chroot. +.IP +If given a chroot is done to the given directory. The default is +"@UNBOUND_CHROOT_DIR@". If you give "" no chroot is performed. +.TP +.B username: \fI +If given, after binding the port the user privileges are dropped. Default is +"@UNBOUND_USERNAME@". If you give username: "" no user change is performed. +.IP +If this user is not capable of binding the +port, reloads (by signal HUP) will still retain the opened ports. +If you change the port number in the config file, and that new port number +requires privileges, then a reload will fail; a restart is needed. +.TP +.B directory: \fI +Sets the working directory for the program. Default is "@UNBOUND_RUN_DIR@". +.TP +.B logfile: \fI +If "" is given, logging goes to stderr, or nowhere once daemonized. +The logfile is appended to, in the following format: +.nf +[seconds since 1970] unbound[pid:tid]: type: message. +.fi +If this option is given, the use\-syslog is option is set to "no". +The logfile is reopened (for append) when the config file is reread, on +SIGHUP. +.TP +.B use\-syslog: \fI +Sets unbound to send log messages to the syslogd, using +\fIsyslog\fR(3). +The log facility LOG_DAEMON is used, with identity "unbound". +The logfile setting is overridden when use\-syslog is turned on. +The default is to log to syslog. +.TP +.B log\-time\-ascii: \fI +Sets logfile lines to use a timestamp in UTC ascii. Default is no, which +prints the seconds since 1970 in brackets. No effect if using syslog, in +that case syslog formats the timestamp printed into the log files. +.TP +.B log\-queries: \fI +Prints one line per query to the log, with the log timestamp and IP address, +name, type and class. Default is no. Note that it takes time to print these +lines which makes the server (significantly) slower. Odd (nonprintable) +characters in names are printed as '?'. +.TP +.B pidfile: \fI +The process id is written to the file. Default is "@UNBOUND_PIDFILE@". +So, +.nf +kill \-HUP `cat @UNBOUND_PIDFILE@` +.fi +triggers a reload, +.nf +kill \-QUIT `cat @UNBOUND_PIDFILE@` +.fi +gracefully terminates. +.TP +.B root\-hints: \fI +Read the root hints from this file. Default is nothing, using builtin hints +for the IN class. The file has the format of zone files, with root +nameserver names and addresses only. The default may become outdated, +when servers change, therefore it is good practice to use a root\-hints file. +.TP +.B hide\-identity: \fI +If enabled id.server and hostname.bind queries are refused. +.TP +.B identity: \fI +Set the identity to report. If set to "", the default, then the hostname +of the server is returned. +.TP +.B hide\-version: \fI +If enabled version.server and version.bind queries are refused. +.TP +.B version: \fI +Set the version to report. If set to "", the default, then the package +version is returned. +.TP +.B target\-fetch\-policy: \fI<"list of numbers"> +Set the target fetch policy used by unbound to determine if it should fetch +nameserver target addresses opportunistically. The policy is described per +dependency depth. +.IP +The number of values determines the maximum dependency depth +that unbound will pursue in answering a query. +A value of \-1 means to fetch all targets opportunistically for that dependency +depth. A value of 0 means to fetch on demand only. A positive value fetches +that many targets opportunistically. +.IP +Enclose the list between quotes ("") and put spaces between numbers. +The default is "3 2 1 0 0". Setting all zeroes, "0 0 0 0 0" gives behaviour +closer to that of BIND 9, while setting "\-1 \-1 \-1 \-1 \-1" gives behaviour +rumoured to be closer to that of BIND 8. +.TP +.B harden\-short\-bufsize: \fI +Very small EDNS buffer sizes from queries are ignored. Default is off, since +it is legal protocol wise to send these, and unbound tries to give very +small answers to these queries, where possible. +.TP +.B harden\-large\-queries: \fI +Very large queries are ignored. Default is off, since it is legal protocol +wise to send these, and could be necessary for operation if TSIG or EDNS +payload is very large. +.TP +.B harden\-glue: \fI +Will trust glue only if it is within the servers authority. Default is on. +.TP +.B harden\-dnssec\-stripped: \fI +Require DNSSEC data for trust\-anchored zones, if such data is absent, +the zone becomes bogus. If turned off, and no DNSSEC data is received +(or the DNSKEY data fails to validate), then the zone is made insecure, +this behaves like there is no trust anchor. You could turn this off if +you are sometimes behind an intrusive firewall (of some sort) that +removes DNSSEC data from packets, or a zone changes from signed to +unsigned to badly signed often. If turned off you run the risk of a +downgrade attack that disables security for a zone. Default is on. +.TP +.B harden\-below\-nxdomain: \fI +From draft-vixie-dnsext-resimprove, returns nxdomain to queries for a name +below another name that is already known to be nxdomain. DNSSEC mandates +noerror for empty nonterminals, hence this is possible. Very old software +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. +.TP +.B harden\-referral\-path: \fI +Harden the referral path by performing additional queries for +infrastructure data. Validates the replies if trust anchors are configured +and the zones are signed. This enforces DNSSEC validation on nameserver +NS sets and the nameserver addresses that are encountered on the referral +path to the answer. +Default off, because it burdens the authority servers, and it is +not RFC standard, and could lead to performance problems because of the +extra query load that is generated. Experimental option. +If you enable it consider adding more numbers after the target\-fetch\-policy +to increase the max depth that is checked to. +.TP +.B use\-caps\-for\-id: \fI +Use 0x20\-encoded random bits in the query to foil spoof attempts. +This perturbs the lowercase and uppercase of query names sent to +authority servers and checks if the reply still has the correct casing. +Disabled by default. +This feature is an experimental implementation of draft dns\-0x20. +.TP +.B private\-address: \fI +Give IPv4 of IPv6 addresses or classless subnets. These are addresses +on your private network, and are not allowed to be returned for public +internet names. Any occurence of such addresses are removed from +DNS answers. Additionally, the DNSSEC validator may mark the answers +bogus. This protects against so\-called DNS Rebinding, where a user browser +is turned into a network proxy, allowing remote access through the browser +to other parts of your private network. Some names can be allowed to +contain your private addresses, by default all the \fBlocal\-data\fR +that you configured is allowed to, and you can specify additional +names using \fBprivate\-domain\fR. No private addresses are enabled +by default. We consider to enable this for the RFC1918 private IP +address space by default in later releases. That would enable private +addresses for 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 169.254.0.0/16 +fd00::/8 and fe80::/10, since the RFC standards say these addresses +should not be visible on the public internet. Turning on 127.0.0.0/8 +would hinder many spamblocklists as they use that. +.TP +.B private\-domain: \fI +Allow this domain, and all its subdomains to contain private addresses. +Give multiple times to allow multiple domain names to contain private +addresses. Default is none. +.TP +.B unwanted\-reply\-threshold: \fI +If set, a total number of unwanted replies is kept track of in every thread. +When it reaches the threshold, a defensive action is taken and a warning +is printed to the log. The defensive action is to clear the rrset and +message caches, hopefully flushing away any poison. A value of 10 million +is suggested. Default is 0 (turned off). +.TP +.B do\-not\-query\-address: \fI +Do not query the given IP address. Can be IP4 or IP6. Append /num to +indicate a classless delegation netblock, for example like +10.2.3.4/24 or 2001::11/64. +.TP +.B do\-not\-query\-localhost: \fI +If yes, localhost is added to the do\-not\-query\-address entries, both +IP6 ::1 and IP4 127.0.0.1/8. If no, then localhost can be used to send +queries to. Default is yes. +.TP +.B prefetch: \fI +If yes, message cache elements are prefetched before they expire to +keep the cache up to date. Default is no. Turning it on gives about +10 percent more traffic and load on the machine, but popular items do +not expire from the cache. +.TP +.B prefetch-key: \fI +If yes, fetch the DNSKEYs earlier in the validation process, when a DS +record is encountered. This lowers the latency of requests. It does use +a little more CPU. Also if the cache is set to 0, it is no use. Default is no. +.TP +.B rrset-roundrobin: \fI +If yes, Unbound rotates RRSet order in response (the random number is taken +from the query ID, for speed and thread safety). Default is no. +.TP +.B minimal-responses: \fI +If yes, Unbound doesn't insert authority/additional sections into response +messages when those sections are not required. This reduces response +size significantly, and may avoid TCP fallback for some responses. +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 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. +Setting this to "iterator" will result in a non\-validating server. +Setting this to "validator iterator" will turn on DNSSEC validation. +The ordering of the modules is important. +You must also set trust\-anchors for validation to be useful. +.TP +.B trust\-anchor\-file: \fI +File with trusted keys for validation. Both DS and DNSKEY entries can appear +in the file. The format of the file is the standard DNS Zone file format. +Default is "", or no trust anchor file. +.TP +.B auto\-trust\-anchor\-file: \fI +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. +.TP +.B trust\-anchor: \fI<"Resource Record"> +A DS or DNSKEY RR for a key to use for validation. Multiple entries can be +given to specify multiple trusted keys, in addition to the trust\-anchor\-files. +The resource record is entered in the same format as 'dig' or 'drill' prints +them, the same format as in the zone file. Has to be on a single line, with +"" around it. A TTL can be specified for ease of cut and paste, but is ignored. +A class can be specified, but class IN is default. +.TP +.B trusted\-keys\-file: \fI +File with trusted keys for validation. Specify more than one file +with several entries, one file per entry. Like \fBtrust\-anchor\-file\fR +but has a different file format. Format is BIND\-9 style format, +the trusted\-keys { name flag proto algo "key"; }; clauses are read. +It is possible to use wildcards with this statement, the wildcard is +expanded on start and on reload. +.TP +.B dlv\-anchor\-file: \fI +File with trusted keys for DLV (DNSSEC Lookaside Validation). Both DS and +DNSKEY entries can be used in the file, in the same format as for +\fItrust\-anchor\-file:\fR statements. Only one DLV can be configured, more +would be slow. The DLV configured is used as a root trusted DLV, this +means that it is a lookaside for the root. Default is "", or no dlv anchor file. +.TP +.B dlv\-anchor: \fI<"Resource Record"> +Much like trust\-anchor, this is a DLV anchor with the DS or DNSKEY inline. +.TP +.B domain\-insecure: \fI +Sets domain name to be insecure, DNSSEC chain of trust is ignored towards +the domain name. So a trust anchor above the domain name can not make the +domain secure with a DS record, such a DS record is then ignored. +Also keys from DLV are ignored for the domain. Can be given multiple times +to specify multiple domains that are treated as if unsigned. If you set +trust anchors for the domain they override this setting (and the domain +is secured). +.IP +This can be useful if you want to make sure a trust anchor for external +lookups does not affect an (unsigned) internal domain. A DS record +externally can create validation failures for that internal domain. +.TP +.B val\-override\-date: \fI +Default is "" or "0", which disables this debugging feature. If enabled by +giving a RRSIG style date, that date is used for verifying RRSIG inception +and expiration dates, instead of the current date. Do not set this unless +you are debugging signature inception and expiration. The value \-1 ignores +the date altogether, useful for some special applications. +.TP +.B val\-sig\-skew\-min: \fI +Minimum number of seconds of clock skew to apply to validated signatures. +A value of 10% of the signature lifetime (expiration \- inception) is +used, capped by this setting. Default is 3600 (1 hour) which allows for +daylight savings differences. Lower this value for more strict checking +of short lived signatures. +.TP +.B val\-sig\-skew\-max: \fI +Maximum number of seconds of clock skew to apply to validated signatures. +A value of 10% of the signature lifetime (expiration \- inception) +is used, capped by this setting. Default is 86400 (24 hours) which +allows for timezone setting problems in stable domains. Setting both +min and max very low disables the clock skew allowances. Setting both +min and max very high makes the validator check the signature timestamps +less strictly. +.TP +.B val\-bogus\-ttl: \fI +The time to live for bogus data. This is data that has failed validation; +due to invalid signatures or other checks. The TTL from that data cannot be +trusted, and this value is used instead. The value is in seconds, default 60. +The time interval prevents repeated revalidation of bogus data. +.TP +.B val\-clean\-additional: \fI +Instruct the validator to remove data from the additional section of secure +messages that are not signed properly. Messages that are insecure, bogus, +indeterminate or unchecked are not affected. Default is yes. Use this setting +to protect the users that rely on this validator for authentication from +protentially bad data in the additional section. +.TP +.B val\-log\-level: \fI +Have the validator print validation failures to the log. Regardless of +the verbosity setting. Default is 0, off. At 1, for every user query +that fails a line is printed to the logs. This way you can monitor what +happens with validation. Use a diagnosis tool, such as dig or drill, +to find out why validation is failing for these queries. At 2, not only +the query that failed is printed but also the reason why unbound thought +it was wrong and which server sent the faulty data. +.TP +.B val\-permissive\-mode: \fI +Instruct the validator to mark bogus messages as indeterminate. The security +checks are performed, but if the result is bogus (failed security), the +reply is not withheld from the client with SERVFAIL as usual. The client +receives the bogus data. For messages that are found to be secure the AD bit +is set in replies. Also logging is performed as for full validation. +The default value is "no". +.TP +.B ignore\-cd\-flag: \fI +Instruct unbound to ignore the CD flag from clients and refuse to +return bogus answers to them. Thus, the CD (Checking Disabled) flag +does not disable checking any more. This is useful if legacy (w2008) +servers that set the CD flag but cannot validate DNSSEC themselves are +the clients, and then unbound provides them with DNSSEC protection. +The default value is "no". +.TP +.B val\-nsec3\-keysize\-iterations: \fI<"list of values"> +List of keysize and iteration count values, separated by spaces, surrounded +by quotes. Default is "1024 150 2048 500 4096 2500". This determines the +maximum allowed NSEC3 iteration count before a message is simply marked +insecure instead of performing the many hashing iterations. The list must +be in ascending order and have at least one entry. If you set it to +"1024 65535" there is no restriction to NSEC3 iteration values. +This table must be kept short; a very long list could cause slower operation. +.TP +.B add\-holddown: \fI +Instruct the \fBauto\-trust\-anchor\-file\fR probe mechanism for RFC5011 +autotrust updates to add new trust anchors only after they have been +visible for this time. Default is 30 days as per the RFC. +.TP +.B del\-holddown: \fI +Instruct the \fBauto\-trust\-anchor\-file\fR probe mechanism for RFC5011 +autotrust updates to remove revoked trust anchors after they have been +kept in the revoked list for this long. Default is 30 days as per +the RFC. +.TP +.B keep\-missing: \fI +Instruct the \fBauto\-trust\-anchor\-file\fR probe mechanism for RFC5011 +autotrust updates to remove missing trust anchors after they have been +unseen for this long. This cleans up the state file if the target zone +does not perform trust anchor revocation, so this makes the auto probe +mechanism work with zones that perform regular (non\-5011) rollovers. +The default is 366 days. The value 0 does not remove missing anchors, +as per the RFC. +.TP +.B key\-cache\-size: \fI +Number of bytes size of the key cache. Default is 4 megabytes. +A plain number is in bytes, append 'k', 'm' or 'g' for kilobytes, megabytes +or gigabytes (1024*1024 bytes in a megabyte). +.TP +.B key\-cache\-slabs: \fI +Number of slabs in the key cache. Slabs reduce lock contention by threads. +Must be set to a power of 2. Setting (close) to the number of cpus is a +reasonable guess. +.TP +.B neg\-cache\-size: \fI +Number of bytes size of the aggressive negative cache. Default is 1 megabyte. +A plain number is in bytes, append 'k', 'm' or 'g' for kilobytes, megabytes +or gigabytes (1024*1024 bytes in a megabyte). +.TP +.B local\-zone: \fI +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, 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. +.IP +If you need more complicated authoritative data, with referrals, wildcards, +CNAME/DNAME support, or DNSSEC authoritative service, setup a stub\-zone for +it as detailed in the stub zone section below. +.TP 10 +\h'5'\fIdeny\fR +Do not send an answer, drop the query. +If there is a match from local data, the query is answered. +.TP 10 +\h'5'\fIrefuse\fR +Send an error message reply, with rcode REFUSED. +If there is a match from local data, the query is answered. +.TP 10 +\h'5'\fIstatic\fR +If there is a match from local data, the query is answered. +Otherwise, the query is answered with nodata or nxdomain. +For a negative answer a SOA is included in the answer if present +as local\-data for the zone apex domain. +.TP 10 +\h'5'\fItransparent\fR +If there is a match from local data, the query is answered. +Otherwise if the query has a different name, the query is resolved normally. +If the query is for a name given in localdata but no such type of data is +given in localdata, then a noerror nodata answer is returned. +If no local\-zone is given local\-data causes a transparent zone +to be created by default. +.TP 10 +\h'5'\fItypetransparent\fR +If there is a match from local data, the query is answered. If the query +is for a different name, or for the same name but for a different type, +the query is resolved normally. So, similar to transparent but types +that are not listed in local data are resolved normally, so if an A record +is in the local data that does not cause a nodata reply for AAAA queries. +.TP 10 +\h'5'\fIredirect\fR +The query is answered from the local data for the zone name. +There may be no local data beneath the zone name. +This answers queries for the zone, and all subdomains of the zone +with the local data for the zone. +It can be used to redirect a domain to return a different address record +to the end user, with +local\-zone: "example.com." redirect and +local\-data: "example.com. A 127.0.0.1" +queries for www.example.com and www.foo.example.com are redirected, so +that users with web browsers cannot access sites with suffix example.com. +.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 +has no other effect than turning off default contents for the +given zone. +.P +The default zones are localhost, reverse 127.0.0.1 and ::1, and the AS112 +zones. The AS112 zones are reverse DNS zones for private use and reserved +IP addresses for which the servers on the internet cannot provide correct +answers. They are configured by default to give nxdomain (no reverse +information) answers. The defaults can be turned off by specifying your +own local\-zone of that name, or using the 'nodefault' type. Below is a +list of the default zone contents. +.TP 10 +\h'5'\fIlocalhost\fR +The IP4 and IP6 localhost information is given. NS and SOA records are provided +for completeness and to satisfy some DNS update tools. Default content: +.nf +local\-zone: "localhost." static +local\-data: "localhost. 10800 IN NS localhost." +local\-data: "localhost. 10800 IN + SOA localhost. nobody.invalid. 1 3600 1200 604800 10800" +local\-data: "localhost. 10800 IN A 127.0.0.1" +local\-data: "localhost. 10800 IN AAAA ::1" +.fi +.TP 10 +\h'5'\fIreverse IPv4 loopback\fR +Default content: +.nf +local\-zone: "127.in\-addr.arpa." static +local\-data: "127.in\-addr.arpa. 10800 IN NS localhost." +local\-data: "127.in\-addr.arpa. 10800 IN + SOA localhost. nobody.invalid. 1 3600 1200 604800 10800" +local\-data: "1.0.0.127.in\-addr.arpa. 10800 IN + PTR localhost." +.fi +.TP 10 +\h'5'\fIreverse IPv6 loopback\fR +Default content: +.nf +local\-zone: "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0. + 0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa." static +local\-data: "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0. + 0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN + NS localhost." +local\-data: "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0. + 0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN + SOA localhost. nobody.invalid. 1 3600 1200 604800 10800" +local\-data: "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0. + 0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN + PTR localhost." +.fi +.TP 10 +\h'5'\fIreverse RFC1918 local use zones\fR +Reverse data for zones 10.in\-addr.arpa, 16.172.in\-addr.arpa to +31.172.in\-addr.arpa, 168.192.in\-addr.arpa. +The \fBlocal\-zone:\fR is set static and as \fBlocal\-data:\fR SOA and NS +records are provided. +.TP 10 +\h'5'\fIreverse RFC3330 IP4 this, link\-local, testnet and broadcast\fR +Reverse data for zones 0.in\-addr.arpa, 254.169.in\-addr.arpa, +2.0.192.in\-addr.arpa (TEST NET 1), 100.51.198.in\-addr.arpa (TEST NET 2), +113.0.203.in\-addr.arpa (TEST NET 3), 255.255.255.255.in\-addr.arpa. +.TP 10 +\h'5'\fIreverse RFC4291 IP6 unspecified\fR +Reverse data for zone +.nf +0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0. +0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. +.fi +.TP 10 +\h'5'\fIreverse RFC4193 IPv6 Locally Assigned Local Addresses\fR +Reverse data for zone D.F.ip6.arpa. +.TP 10 +\h'5'\fIreverse RFC4291 IPv6 Link Local Addresses\fR +Reverse data for zones 8.E.F.ip6.arpa to B.E.F.ip6.arpa. +.TP 10 +\h'5'\fIreverse IPv6 Example Prefix\fR +Reverse data for zone 8.B.D.0.1.0.0.2.ip6.arpa. This zone is used for +tutorials and examples. You can remove the block on this zone with: +.nf + local\-zone: 8.B.D.0.1.0.0.2.ip6.arpa. nodefault +.fi +You can also selectively unblock a part of the zone by making that part +transparent with a local\-zone statement. +This also works with the other default zones. +.\" End of local-zone listing. +.TP 5 +.B local\-data: \fI"" +Configure local data, which is served in reply to queries for it. +The query has to match exactly unless you configure the local\-zone as +redirect. If not matched exactly, the local\-zone type determines +further processing. If local\-data is configured that is not a subdomain of +a local\-zone, a transparent local\-zone is configured. +For record types such as TXT, use single quotes, as in +local\-data: 'example. TXT "text"'. +.IP +If you need more complicated authoritative data, with referrals, wildcards, +CNAME/DNAME support, or DNSSEC authoritative service, setup a stub\-zone for +it as detailed in the stub zone section below. +.TP 5 +.B local\-data\-ptr: \fI"IPaddr name" +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" +.SS "Remote Control Options" +In the +.B remote\-control: +clause are the declarations for the remote control facility. If this is +enabled, the \fIunbound\-control\fR(8) utility can be used to send +commands to the running unbound server. The server uses these clauses +to setup SSLv3 / TLSv1 security for the connection. The +\fIunbound\-control\fR(8) utility also reads the \fBremote\-control\fR +section for options. To setup the correct self\-signed certificates use the +\fIunbound\-control\-setup\fR(8) utility. +.TP 5 +.B control\-enable: \fI +The option is used to enable remote control, default is "no". +If turned off, the server does not listen for control commands. +.TP 5 +.B control\-interface: +Give IPv4 or IPv6 addresses to listen on for control commands. +By default localhost (127.0.0.1 and ::1) is listened to. +Use 0.0.0.0 and ::0 to listen to all interfaces. +.TP 5 +.B control\-port: +The port number to listen on for control commands, default is 8953. +If you change this port number, and permissions have been dropped, +a reload is not sufficient to open the port again, you must then restart. +.TP 5 +.B server\-key\-file: "" +Path to the server private key, by default unbound_server.key. +This file is generated by the \fIunbound\-control\-setup\fR utility. +This file is used by the unbound server, but not by \fIunbound\-control\fR. +.TP 5 +.B server\-cert\-file: "" +Path to the server self signed certificate, by default unbound_server.pem. +This file is generated by the \fIunbound\-control\-setup\fR utility. +This file is used by the unbound server, and also by \fIunbound\-control\fR. +.TP 5 +.B control\-key\-file: "" +Path to the control client private key, by default unbound_control.key. +This file is generated by the \fIunbound\-control\-setup\fR utility. +This file is used by \fIunbound\-control\fR. +.TP 5 +.B control\-cert\-file: "" +Path to the control client certificate, by default unbound_control.pem. +This certificate has to be signed with the server certificate. +This file is generated by the \fIunbound\-control\-setup\fR utility. +This file is used by \fIunbound\-control\fR. +.SS "Stub Zone Options" +.LP +There may be multiple +.B stub\-zone: +clauses. Each with a name: and zero or more hostnames or IP addresses. +For the stub zone this list of nameservers is used. Class IN is assumed. +The servers should be authority servers, not recursors; unbound performs +the recursive processing itself for stub zones. +.P +The stub zone can be used to configure authoritative data to be used +by the resolver that cannot be accessed using the public internet servers. +This is useful for company\-local data or private zones. Setup an +authoritative server on a different host (or different port). Enter a config +entry for unbound with +.B stub\-addr: +. +The unbound resolver can then access the data, without referring to the +public internet for it. +.P +This setup allows DNSSEC signed zones to be served by that +authoritative server, in which case a trusted key entry with the public key +can be put in config, so that unbound can validate the data and set the AD +bit on replies for the private zone (authoritative servers do not set the +AD bit). This setup makes unbound capable of answering queries for the +private zone, and can even set the AD bit ('authentic'), but the AA +('authoritative') bit is not set on these replies. +.TP +.B name: \fI +Name of the stub zone. +.TP +.B stub\-host: \fI +Name of stub zone nameserver. Is itself resolved before it is used. +.TP +.B stub\-addr: \fI +IP address of stub zone nameserver. Can be IP 4 or IP 6. +To use a nondefault port for DNS communication append '@' with the port number. +.TP +.B stub\-prime: \fI +This option is by default off. If enabled it performs NS set priming, +which is similar to root hints, where it starts using the list of nameservers +currently published by the zone. Thus, if the hint list is slightly outdated, +the resolver picks up a correct list online. +.TP +.B stub\-first: \fI +If enabled, a query is attempted without the stub clause if it fails. +The default is no. +.SS "Forward Zone Options" +.LP +There may be multiple +.B forward\-zone: +clauses. Each with a \fBname:\fR and zero or more hostnames or IP +addresses. For the forward zone this list of nameservers is used to +forward the queries to. The servers listed as \fBforward\-host:\fR and +\fBforward\-addr:\fR have to handle further recursion for the query. Thus, +those servers are not authority servers, but are (just like unbound is) +recursive servers too; unbound does not perform recursion itself for the +forward zone, it lets the remote server do it. Class IN is assumed. +A forward\-zone entry with name "." and a forward\-addr target will +forward all queries to that other server (unless it can answer from +the cache). +.TP +.B name: \fI +Name of the forward zone. +.TP +.B forward\-host: \fI +Name of server to forward to. Is itself resolved before it is used. +.TP +.B forward\-addr: \fI +IP address of server to forward to. Can be IP 4 or IP 6. +To use a nondefault port for DNS communication append '@' with the port number. +.TP +.B forward\-first: \fI +If enabled, a query is attempted without the forward clause if it fails. +The default is no. +.SS "Python Module Options" +.LP +The +.B python: +clause gives the settings for the \fIpython\fR(1) script module. This module +acts like the iterator and validator modules do, on queries and answers. +To enable the script module it has to be compiled into the daemon, +and the word "python" has to be put in the \fBmodule\-config:\fR option +(usually first, or between the validator and iterator). +.TP +.B python\-script: \fI\fR +The script file to load. +.SH "MEMORY CONTROL EXAMPLE" +In the example config settings below memory usage is reduced. Some service +levels are lower, notable very large data and a high TCP load are no longer +supported. Very large data and high TCP loads are exceptional for the DNS. +DNSSEC validation is enabled, just add trust anchors. +If you do not have to worry about programs using more than 3 Mb of memory, +the below example is not for you. Use the defaults to receive full service, +which on BSD\-32bit tops out at 30\-40 Mb after heavy usage. +.P +.nf +# example settings that reduce memory usage +server: + num\-threads: 1 + outgoing\-num\-tcp: 1 # this limits TCP service, uses less buffers. + incoming\-num\-tcp: 1 + outgoing\-range: 60 # uses less memory, but less performance. + msg\-buffer\-size: 8192 # note this limits service, 'no huge stuff'. + msg\-cache\-size: 100k + msg\-cache\-slabs: 1 + rrset\-cache\-size: 100k + rrset\-cache\-slabs: 1 + infra\-cache\-numhosts: 200 + infra\-cache\-slabs: 1 + key\-cache\-size: 100k + key\-cache\-slabs: 1 + neg\-cache\-size: 10k + num\-queries\-per\-thread: 30 + target\-fetch\-policy: "2 1 0 0 0 0" + harden\-large\-queries: "yes" + harden\-short\-bufsize: "yes" +.fi +.SH "FILES" +.TP +.I @UNBOUND_RUN_DIR@ +default unbound working directory. +.TP +.I @UNBOUND_CHROOT_DIR@ +default +\fIchroot\fR(2) +location. +.TP +.I @ub_conf_file@ +unbound configuration file. +.TP +.I @UNBOUND_PIDFILE@ +default unbound pidfile with process ID of the running daemon. +.TP +.I unbound.log +unbound log file. default is to log to +\fIsyslog\fR(3). +.SH "SEE ALSO" +\fIunbound\fR(8), +\fIunbound\-checkconf\fR(8). +.SH "AUTHORS" +.B Unbound +was written by NLnet Labs. Please see CREDITS file +in the distribution for further details. diff --git a/doc/unbound.doxygen b/doc/unbound.doxygen new file mode 100644 index 00000000000..b32316b72a4 --- /dev/null +++ b/doc/unbound.doxygen @@ -0,0 +1,1648 @@ +# Doxyfile 1.7.1 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = unbound + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = 0.1 + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = doc + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen to replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penality. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will rougly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols + +SYMBOL_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = YES + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = NO + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. The create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = NO + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = YES + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = . + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = ./build \ + ./compat \ + util/configparser.c \ + util/configparser.h \ + util/configlexer.c \ + util/locks.h \ + pythonmod/unboundmodule.py \ + pythonmod/interface.h \ + pythonmod/examples/resgen.py \ + pythonmod/examples/resmod.py \ + pythonmod/examples/resip.py \ + libunbound/python/unbound.py \ + libunbound/python/libunbound_wrap.c \ + ./ldns-src + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# If the HTML_TIMESTAMP tag is set to YES then the generated HTML +# documentation will contain the timesstamp. + +HTML_TIMESTAMP = NO + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the stylesheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +#HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +#HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +#HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +#DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +#DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +#EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +#FORMULA_TRANSPARENT = YES + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = NO + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvances is that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = YES + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = YES + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = YES + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = *.h + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = DOXYGEN + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = ATTR_UNUSED + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +#DOT_NUM_THREADS = 0 + +# By default doxygen will write a font called FreeSans.ttf to the output +# directory and reference it in all dot files that doxygen generates. This +# font does not include all possible unicode characters however, so when you need +# these (or just want a differently looking font) you can specify the font name +# using DOT_FONTNAME. You need need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = FreeSans.ttf + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/install-sh b/install-sh new file mode 100755 index 00000000000..6781b987bdb --- /dev/null +++ b/install-sh @@ -0,0 +1,520 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2009-04-28.21; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +nl=' +' +IFS=" "" $nl" + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +no_target_directory= + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) dst_arg=$2 + shift;; + + -T) no_target_directory=true;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + trap '(exit $?); exit' 1 2 13 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dst_arg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writeable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + -*) prefix='./';; + *) prefix='';; + esac + + eval "$initialize_posix_glob" + + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir + shift + $posix_glob set +f + IFS=$oIFS + + prefixes= + + for d + do + test -z "$d" && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && + + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/iterator/iter_delegpt.c b/iterator/iter_delegpt.c new file mode 100644 index 00000000000..d2f5d73335d --- /dev/null +++ b/iterator/iter_delegpt.c @@ -0,0 +1,640 @@ +/* + * iterator/iter_delegpt.c - delegation point with NS and address information. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file implements the Delegation Point. It contains a list of name servers + * and their addresses if known. + */ +#include "config.h" +#include "iterator/iter_delegpt.h" +#include "services/cache/dns.h" +#include "util/regional.h" +#include "util/data/dname.h" +#include "util/data/packed_rrset.h" +#include "util/data/msgreply.h" +#include "util/net_help.h" + +struct delegpt* +delegpt_create(struct regional* region) +{ + struct delegpt* dp=(struct delegpt*)regional_alloc( + region, sizeof(*dp)); + if(!dp) + return NULL; + memset(dp, 0, sizeof(*dp)); + return dp; +} + +struct delegpt* delegpt_copy(struct delegpt* dp, struct regional* region) +{ + struct delegpt* copy = delegpt_create(region); + struct delegpt_ns* ns; + struct delegpt_addr* a; + if(!copy) + return NULL; + if(!delegpt_set_name(copy, region, dp->name)) + return NULL; + copy->bogus = dp->bogus; + copy->has_parent_side_NS = dp->has_parent_side_NS; + for(ns = dp->nslist; ns; ns = ns->next) { + if(!delegpt_add_ns(copy, region, ns->name, (int)ns->lame)) + return NULL; + copy->nslist->resolved = ns->resolved; + copy->nslist->got4 = ns->got4; + copy->nslist->got6 = ns->got6; + copy->nslist->done_pside4 = ns->done_pside4; + copy->nslist->done_pside6 = ns->done_pside6; + } + for(a = dp->target_list; a; a = a->next_target) { + if(!delegpt_add_addr(copy, region, &a->addr, a->addrlen, + a->bogus, a->lame)) + return NULL; + } + return copy; +} + +int +delegpt_set_name(struct delegpt* dp, struct regional* region, uint8_t* name) +{ + log_assert(!dp->dp_type_mlc); + dp->namelabs = dname_count_size_labels(name, &dp->namelen); + dp->name = regional_alloc_init(region, name, dp->namelen); + return dp->name != 0; +} + +int +delegpt_add_ns(struct delegpt* dp, struct regional* region, uint8_t* name, + int lame) +{ + struct delegpt_ns* ns; + size_t len; + (void)dname_count_size_labels(name, &len); + log_assert(!dp->dp_type_mlc); + /* slow check for duplicates to avoid counting failures when + * adding the same server as a dependency twice */ + if(delegpt_find_ns(dp, name, len)) + return 1; + ns = (struct delegpt_ns*)regional_alloc(region, + sizeof(struct delegpt_ns)); + if(!ns) + return 0; + ns->next = dp->nslist; + ns->namelen = len; + dp->nslist = ns; + ns->name = regional_alloc_init(region, name, ns->namelen); + ns->resolved = 0; + ns->got4 = 0; + ns->got6 = 0; + ns->lame = (uint8_t)lame; + ns->done_pside4 = 0; + ns->done_pside6 = 0; + return ns->name != 0; +} + +struct delegpt_ns* +delegpt_find_ns(struct delegpt* dp, uint8_t* name, size_t namelen) +{ + struct delegpt_ns* p = dp->nslist; + while(p) { + if(namelen == p->namelen && + query_dname_compare(name, p->name) == 0) { + return p; + } + p = p->next; + } + return NULL; +} + +struct delegpt_addr* +delegpt_find_addr(struct delegpt* dp, struct sockaddr_storage* addr, + socklen_t addrlen) +{ + struct delegpt_addr* p = dp->target_list; + while(p) { + if(sockaddr_cmp_addr(addr, addrlen, &p->addr, p->addrlen)==0) { + return p; + } + p = p->next_target; + } + return NULL; +} + +int +delegpt_add_target(struct delegpt* dp, struct regional* region, + uint8_t* name, size_t namelen, struct sockaddr_storage* addr, + socklen_t addrlen, int bogus, int lame) +{ + struct delegpt_ns* ns = delegpt_find_ns(dp, name, namelen); + log_assert(!dp->dp_type_mlc); + if(!ns) { + /* ignore it */ + return 1; + } + if(!lame) { + if(addr_is_ip6(addr, addrlen)) + ns->got6 = 1; + else ns->got4 = 1; + if(ns->got4 && ns->got6) + ns->resolved = 1; + } + return delegpt_add_addr(dp, region, addr, addrlen, bogus, lame); +} + +int +delegpt_add_addr(struct delegpt* dp, struct regional* region, + struct sockaddr_storage* addr, socklen_t addrlen, int bogus, + int lame) +{ + struct delegpt_addr* a; + log_assert(!dp->dp_type_mlc); + /* check for duplicates */ + if((a = delegpt_find_addr(dp, addr, addrlen))) { + if(bogus) + a->bogus = bogus; + if(!lame) + a->lame = 0; + return 1; + } + + a = (struct delegpt_addr*)regional_alloc(region, + sizeof(struct delegpt_addr)); + if(!a) + return 0; + a->next_target = dp->target_list; + dp->target_list = a; + a->next_result = 0; + a->next_usable = dp->usable_list; + dp->usable_list = a; + memcpy(&a->addr, addr, addrlen); + a->addrlen = addrlen; + a->attempts = 0; + a->bogus = bogus; + a->lame = lame; + return 1; +} + +void +delegpt_count_ns(struct delegpt* dp, size_t* numns, size_t* missing) +{ + struct delegpt_ns* ns; + *numns = 0; + *missing = 0; + for(ns = dp->nslist; ns; ns = ns->next) { + (*numns)++; + if(!ns->resolved) + (*missing)++; + } +} + +void +delegpt_count_addr(struct delegpt* dp, size_t* numaddr, size_t* numres, + size_t* numavail) +{ + struct delegpt_addr* a; + *numaddr = 0; + *numres = 0; + *numavail = 0; + for(a = dp->target_list; a; a = a->next_target) { + (*numaddr)++; + } + for(a = dp->result_list; a; a = a->next_result) { + (*numres)++; + } + for(a = dp->usable_list; a; a = a->next_usable) { + (*numavail)++; + } +} + +void delegpt_log(enum verbosity_value v, struct delegpt* dp) +{ + char buf[LDNS_MAX_DOMAINLEN+1]; + struct delegpt_ns* ns; + struct delegpt_addr* a; + size_t missing=0, numns=0, numaddr=0, numres=0, numavail=0; + if(verbosity < v) + return; + dname_str(dp->name, buf); + if(dp->nslist == NULL && dp->target_list == NULL) { + log_info("DelegationPoint<%s>: empty", buf); + return; + } + delegpt_count_ns(dp, &numns, &missing); + delegpt_count_addr(dp, &numaddr, &numres, &numavail); + log_info("DelegationPoint<%s>: %u names (%u missing), " + "%u addrs (%u result, %u avail)%s", + buf, (unsigned)numns, (unsigned)missing, + (unsigned)numaddr, (unsigned)numres, (unsigned)numavail, + (dp->has_parent_side_NS?" parentNS":" cacheNS")); + if(verbosity >= VERB_ALGO) { + for(ns = dp->nslist; ns; ns = ns->next) { + dname_str(ns->name, buf); + log_info(" %s %s%s%s%s%s%s%s", buf, + (ns->resolved?"*":""), + (ns->got4?" A":""), (ns->got6?" AAAA":""), + (dp->bogus?" BOGUS":""), (ns->lame?" PARENTSIDE":""), + (ns->done_pside4?" PSIDE_A":""), + (ns->done_pside6?" PSIDE_AAAA":"")); + } + for(a = dp->target_list; a; a = a->next_target) { + const char* str = " "; + if(a->bogus && a->lame) str = " BOGUS ADDR_LAME "; + else if(a->bogus) str = " BOGUS "; + else if(a->lame) str = " ADDR_LAME "; + log_addr(VERB_ALGO, str, &a->addr, a->addrlen); + } + } +} + +void +delegpt_add_unused_targets(struct delegpt* dp) +{ + struct delegpt_addr* usa = dp->usable_list; + dp->usable_list = NULL; + while(usa) { + usa->next_result = dp->result_list; + dp->result_list = usa; + usa = usa->next_usable; + } +} + +size_t +delegpt_count_targets(struct delegpt* dp) +{ + struct delegpt_addr* a; + size_t n = 0; + for(a = dp->target_list; a; a = a->next_target) + n++; + return n; +} + +size_t +delegpt_count_missing_targets(struct delegpt* dp) +{ + struct delegpt_ns* ns; + size_t n = 0; + for(ns = dp->nslist; ns; ns = ns->next) + if(!ns->resolved) + n++; + return n; +} + +/** find NS rrset in given list */ +static struct ub_packed_rrset_key* +find_NS(struct reply_info* rep, size_t from, size_t to) +{ + size_t i; + for(i=from; irrsets[i]->rk.type) == LDNS_RR_TYPE_NS) + return rep->rrsets[i]; + } + return NULL; +} + +struct delegpt* +delegpt_from_message(struct dns_msg* msg, struct regional* region) +{ + struct ub_packed_rrset_key* ns_rrset = NULL; + struct delegpt* dp; + size_t i; + /* look for NS records in the authority section... */ + ns_rrset = find_NS(msg->rep, msg->rep->an_numrrsets, + msg->rep->an_numrrsets+msg->rep->ns_numrrsets); + + /* In some cases (even legitimate, perfectly legal cases), the + * NS set for the "referral" might be in the answer section. */ + if(!ns_rrset) + ns_rrset = find_NS(msg->rep, 0, msg->rep->an_numrrsets); + + /* If there was no NS rrset in the authority section, then this + * wasn't a referral message. (It might not actually be a + * referral message anyway) */ + if(!ns_rrset) + return NULL; + + /* If we found any, then Yay! we have a delegation point. */ + dp = delegpt_create(region); + if(!dp) + return NULL; + dp->has_parent_side_NS = 1; /* created from message */ + if(!delegpt_set_name(dp, region, ns_rrset->rk.dname)) + return NULL; + if(!delegpt_rrset_add_ns(dp, region, ns_rrset, 0)) + return NULL; + + /* add glue, A and AAAA in answer and additional section */ + for(i=0; irep->rrset_count; i++) { + struct ub_packed_rrset_key* s = msg->rep->rrsets[i]; + /* skip auth section. FIXME really needed?*/ + if(msg->rep->an_numrrsets <= i && + i < (msg->rep->an_numrrsets+msg->rep->ns_numrrsets)) + continue; + + if(ntohs(s->rk.type) == LDNS_RR_TYPE_A) { + if(!delegpt_add_rrset_A(dp, region, s, 0)) + return NULL; + } else if(ntohs(s->rk.type) == LDNS_RR_TYPE_AAAA) { + if(!delegpt_add_rrset_AAAA(dp, region, s, 0)) + return NULL; + } + } + return dp; +} + +int +delegpt_rrset_add_ns(struct delegpt* dp, struct regional* region, + struct ub_packed_rrset_key* ns_rrset, int lame) +{ + struct packed_rrset_data* nsdata = (struct packed_rrset_data*) + ns_rrset->entry.data; + size_t i; + log_assert(!dp->dp_type_mlc); + if(nsdata->security == sec_status_bogus) + dp->bogus = 1; + for(i=0; icount; i++) { + if(nsdata->rr_len[i] < 2+1) continue; /* len + root label */ + if(dname_valid(nsdata->rr_data[i]+2, nsdata->rr_len[i]-2) != + (size_t)ldns_read_uint16(nsdata->rr_data[i])) + continue; /* bad format */ + /* add rdata of NS (= wirefmt dname), skip rdatalen bytes */ + if(!delegpt_add_ns(dp, region, nsdata->rr_data[i]+2, lame)) + return 0; + } + return 1; +} + +int +delegpt_add_rrset_A(struct delegpt* dp, struct regional* region, + struct ub_packed_rrset_key* ak, int lame) +{ + struct packed_rrset_data* d=(struct packed_rrset_data*)ak->entry.data; + size_t i; + struct sockaddr_in sa; + socklen_t len = (socklen_t)sizeof(sa); + log_assert(!dp->dp_type_mlc); + memset(&sa, 0, len); + sa.sin_family = AF_INET; + sa.sin_port = (in_port_t)htons(UNBOUND_DNS_PORT); + for(i=0; icount; i++) { + if(d->rr_len[i] != 2 + INET_SIZE) + continue; + memmove(&sa.sin_addr, d->rr_data[i]+2, INET_SIZE); + if(!delegpt_add_target(dp, region, ak->rk.dname, + ak->rk.dname_len, (struct sockaddr_storage*)&sa, + len, (d->security==sec_status_bogus), lame)) + return 0; + } + return 1; +} + +int +delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* region, + struct ub_packed_rrset_key* ak, int lame) +{ + struct packed_rrset_data* d=(struct packed_rrset_data*)ak->entry.data; + size_t i; + struct sockaddr_in6 sa; + socklen_t len = (socklen_t)sizeof(sa); + log_assert(!dp->dp_type_mlc); + memset(&sa, 0, len); + sa.sin6_family = AF_INET6; + sa.sin6_port = (in_port_t)htons(UNBOUND_DNS_PORT); + for(i=0; icount; i++) { + if(d->rr_len[i] != 2 + INET6_SIZE) /* rdatalen + len of IP6 */ + continue; + memmove(&sa.sin6_addr, d->rr_data[i]+2, INET6_SIZE); + if(!delegpt_add_target(dp, region, ak->rk.dname, + ak->rk.dname_len, (struct sockaddr_storage*)&sa, + len, (d->security==sec_status_bogus), lame)) + return 0; + } + return 1; +} + +int +delegpt_add_rrset(struct delegpt* dp, struct regional* region, + struct ub_packed_rrset_key* rrset, int lame) +{ + if(!rrset) + return 1; + if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_NS) + return delegpt_rrset_add_ns(dp, region, rrset, lame); + else if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_A) + return delegpt_add_rrset_A(dp, region, rrset, lame); + else if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_AAAA) + return delegpt_add_rrset_AAAA(dp, region, rrset, lame); + log_warn("Unknown rrset type added to delegpt"); + return 1; +} + +void delegpt_add_neg_msg(struct delegpt* dp, struct msgreply_entry* msg) +{ + struct reply_info* rep = (struct reply_info*)msg->entry.data; + if(!rep) return; + + /* if error or no answers */ + if(FLAGS_GET_RCODE(rep->flags) != 0 || rep->an_numrrsets == 0) { + struct delegpt_ns* ns = delegpt_find_ns(dp, msg->key.qname, + msg->key.qname_len); + if(ns) { + if(msg->key.qtype == LDNS_RR_TYPE_A) + ns->got4 = 1; + else if(msg->key.qtype == LDNS_RR_TYPE_AAAA) + ns->got6 = 1; + if(ns->got4 && ns->got6) + ns->resolved = 1; + } + } +} + +void delegpt_no_ipv6(struct delegpt* dp) +{ + struct delegpt_ns* ns; + for(ns = dp->nslist; ns; ns = ns->next) { + /* no ipv6, so only ipv4 is enough to resolve a nameserver */ + if(ns->got4) + ns->resolved = 1; + } +} + +void delegpt_no_ipv4(struct delegpt* dp) +{ + struct delegpt_ns* ns; + for(ns = dp->nslist; ns; ns = ns->next) { + /* no ipv4, so only ipv6 is enough to resolve a nameserver */ + if(ns->got6) + ns->resolved = 1; + } +} + +struct delegpt* delegpt_create_mlc(uint8_t* name) +{ + struct delegpt* dp=(struct delegpt*)calloc(1, sizeof(*dp)); + if(!dp) + return NULL; + dp->dp_type_mlc = 1; + if(name) { + dp->namelabs = dname_count_size_labels(name, &dp->namelen); + dp->name = memdup(name, dp->namelen); + if(!dp->name) { + free(dp); + return NULL; + } + } + return dp; +} + +void delegpt_free_mlc(struct delegpt* dp) +{ + struct delegpt_ns* n, *nn; + struct delegpt_addr* a, *na; + if(!dp) return; + log_assert(dp->dp_type_mlc); + n = dp->nslist; + while(n) { + nn = n->next; + free(n->name); + free(n); + n = nn; + } + a = dp->target_list; + while(a) { + na = a->next_target; + free(a); + a = na; + } + free(dp->name); + free(dp); +} + +int delegpt_set_name_mlc(struct delegpt* dp, uint8_t* name) +{ + log_assert(dp->dp_type_mlc); + dp->namelabs = dname_count_size_labels(name, &dp->namelen); + dp->name = memdup(name, dp->namelen); + return (dp->name != NULL); +} + +int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, int lame) +{ + struct delegpt_ns* ns; + size_t len; + (void)dname_count_size_labels(name, &len); + log_assert(dp->dp_type_mlc); + /* slow check for duplicates to avoid counting failures when + * adding the same server as a dependency twice */ + if(delegpt_find_ns(dp, name, len)) + return 1; + ns = (struct delegpt_ns*)malloc(sizeof(struct delegpt_ns)); + if(!ns) + return 0; + ns->namelen = len; + ns->name = memdup(name, ns->namelen); + if(!ns->name) { + free(ns); + return 0; + } + ns->next = dp->nslist; + dp->nslist = ns; + ns->resolved = 0; + ns->got4 = 0; + ns->got6 = 0; + ns->lame = (uint8_t)lame; + ns->done_pside4 = 0; + ns->done_pside6 = 0; + return 1; +} + +int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr, + socklen_t addrlen, int bogus, int lame) +{ + struct delegpt_addr* a; + log_assert(dp->dp_type_mlc); + /* check for duplicates */ + if((a = delegpt_find_addr(dp, addr, addrlen))) { + if(bogus) + a->bogus = bogus; + if(!lame) + a->lame = 0; + return 1; + } + + a = (struct delegpt_addr*)malloc(sizeof(struct delegpt_addr)); + if(!a) + return 0; + a->next_target = dp->target_list; + dp->target_list = a; + a->next_result = 0; + a->next_usable = dp->usable_list; + dp->usable_list = a; + memcpy(&a->addr, addr, addrlen); + a->addrlen = addrlen; + a->attempts = 0; + a->bogus = bogus; + a->lame = lame; + return 1; +} + +int delegpt_add_target_mlc(struct delegpt* dp, uint8_t* name, size_t namelen, + struct sockaddr_storage* addr, socklen_t addrlen, int bogus, int lame) +{ + struct delegpt_ns* ns = delegpt_find_ns(dp, name, namelen); + log_assert(dp->dp_type_mlc); + if(!ns) { + /* ignore it */ + return 1; + } + if(!lame) { + if(addr_is_ip6(addr, addrlen)) + ns->got6 = 1; + else ns->got4 = 1; + if(ns->got4 && ns->got6) + ns->resolved = 1; + } + return delegpt_add_addr_mlc(dp, addr, addrlen, bogus, lame); +} + +size_t delegpt_get_mem(struct delegpt* dp) +{ + struct delegpt_ns* ns; + size_t s; + if(!dp) return 0; + s = sizeof(*dp) + dp->namelen + + delegpt_count_targets(dp)*sizeof(struct delegpt_addr); + for(ns=dp->nslist; ns; ns=ns->next) + s += sizeof(*ns)+ns->namelen; + return s; +} diff --git a/iterator/iter_delegpt.h b/iterator/iter_delegpt.h new file mode 100644 index 00000000000..7728031aa99 --- /dev/null +++ b/iterator/iter_delegpt.h @@ -0,0 +1,411 @@ +/* + * iterator/iter_delegpt.h - delegation point with NS and address information. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file implements the Delegation Point. It contains a list of name servers + * and their addresses if known. + */ + +#ifndef ITERATOR_ITER_DELEGPT_H +#define ITERATOR_ITER_DELEGPT_H +#include "util/log.h" +struct regional; +struct delegpt_ns; +struct delegpt_addr; +struct dns_msg; +struct ub_packed_rrset_key; +struct msgreply_entry; + +/** + * Delegation Point. + * For a domain name, the NS rrset, and the A and AAAA records for those. + */ +struct delegpt { + /** the domain name of the delegation point. */ + uint8_t* name; + /** length of the delegation point name */ + size_t namelen; + /** number of labels in delegation point */ + int namelabs; + + /** the nameservers, names from the NS RRset rdata. */ + struct delegpt_ns* nslist; + /** the target addresses for delegation */ + struct delegpt_addr* target_list; + /** the list of usable targets; subset of target_list + * the items in this list are not part of the result list. */ + struct delegpt_addr* usable_list; + /** the list of returned targets; subset of target_list */ + struct delegpt_addr* result_list; + + /** if true, the NS RRset was bogus. All info is bad. */ + int bogus; + /** if true, the parent-side NS record has been applied: + * its names have been added and their addresses can follow later. + * Also true if the delegationpoint was created from a delegation + * message and thus contains the parent-side-info already. */ + uint8_t has_parent_side_NS; + /** for assertions on type of delegpt */ + uint8_t dp_type_mlc; +}; + +/** + * Nameservers for a delegation point. + */ +struct delegpt_ns { + /** next in list */ + struct delegpt_ns* next; + /** name of nameserver */ + uint8_t* name; + /** length of name */ + size_t namelen; + /** + * If the name has been resolved. false if not queried for yet. + * true if the A, AAAA queries have been generated. + * marked true if those queries fail. + * and marked true if got4 and got6 are both true. + */ + int resolved; + /** if the ipv4 address is in the delegpt */ + uint8_t got4; + /** if the ipv6 address is in the delegpt */ + uint8_t got6; + /** + * If the name is parent-side only and thus dispreferred. + * Its addresses become dispreferred as well + */ + uint8_t lame; + /** if the parent-side ipv4 address has been looked up (last resort). + * Also enabled if a parent-side cache entry exists, or a parent-side + * negative-cache entry exists. */ + uint8_t done_pside4; + /** if the parent-side ipv6 address has been looked up (last resort). + * Also enabled if a parent-side cache entry exists, or a parent-side + * negative-cache entry exists. */ + uint8_t done_pside6; +}; + +/** + * Address of target nameserver in delegation point. + */ +struct delegpt_addr { + /** next delegation point in results */ + struct delegpt_addr* next_result; + /** next delegation point in usable list */ + struct delegpt_addr* next_usable; + /** next delegation point in all targets list */ + struct delegpt_addr* next_target; + + /** delegation point address */ + struct sockaddr_storage addr; + /** length of addr */ + socklen_t addrlen; + /** number of attempts for this addr */ + int attempts; + /** rtt stored here in the selection algorithm */ + int sel_rtt; + /** if true, the A or AAAA RR was bogus, so this address is bad. + * Also check the dp->bogus to see if everything is bogus. */ + int bogus; + /** if true, this address is dispreferred: it is a lame IP address */ + int lame; +}; + +/** + * Create new delegation point. + * @param regional: where to allocate it. + * @return new delegation point or NULL on error. + */ +struct delegpt* delegpt_create(struct regional* regional); + +/** + * Create a copy of a delegation point. + * @param dp: delegation point to copy. + * @param regional: where to allocate it. + * @return new delegation point or NULL on error. + */ +struct delegpt* delegpt_copy(struct delegpt* dp, struct regional* regional); + +/** + * Set name of delegation point. + * @param dp: delegation point. + * @param regional: where to allocate the name copy. + * @param name: name to use. + * @return false on error. + */ +int delegpt_set_name(struct delegpt* dp, struct regional* regional, + uint8_t* name); + +/** + * Add a name to the delegation point. + * @param dp: delegation point. + * @param regional: where to allocate the info. + * @param name: domain name in wire format. + * @param lame: name is lame, disprefer it. + * @return false on error. + */ +int delegpt_add_ns(struct delegpt* dp, struct regional* regional, + uint8_t* name, int lame); + +/** + * Add NS rrset; calls add_ns repeatedly. + * @param dp: delegation point. + * @param regional: where to allocate the info. + * @param ns_rrset: NS rrset. + * @param lame: rrset is lame, disprefer it. + * @return 0 on alloc error. + */ +int delegpt_rrset_add_ns(struct delegpt* dp, struct regional* regional, + struct ub_packed_rrset_key* ns_rrset, int lame); + +/** + * Add target address to the delegation point. + * @param dp: delegation point. + * @param regional: where to allocate the info. + * @param name: name for which target was found (must be in nslist). + * This name is marked resolved. + * @param namelen: length of name. + * @param addr: the address. + * @param addrlen: the length of addr. + * @param bogus: security status for the address, pass true if bogus. + * @param lame: address is lame. + * @return false on error. + */ +int delegpt_add_target(struct delegpt* dp, struct regional* regional, + uint8_t* name, size_t namelen, struct sockaddr_storage* addr, + socklen_t addrlen, int bogus, int lame); + +/** + * Add A RRset to delegpt. + * @param dp: delegation point. + * @param regional: where to allocate the info. + * @param rrset: RRset A to add. + * @param lame: rrset is lame, disprefer it. + * @return 0 on alloc error. + */ +int delegpt_add_rrset_A(struct delegpt* dp, struct regional* regional, + struct ub_packed_rrset_key* rrset, int lame); + +/** + * Add AAAA RRset to delegpt. + * @param dp: delegation point. + * @param regional: where to allocate the info. + * @param rrset: RRset AAAA to add. + * @param lame: rrset is lame, disprefer it. + * @return 0 on alloc error. + */ +int delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* regional, + struct ub_packed_rrset_key* rrset, int lame); + +/** + * Add any RRset to delegpt. + * Does not check for duplicates added. + * @param dp: delegation point. + * @param regional: where to allocate the info. + * @param rrset: RRset to add, NS, A, AAAA. + * @param lame: rrset is lame, disprefer it. + * @return 0 on alloc error. + */ +int delegpt_add_rrset(struct delegpt* dp, struct regional* regional, + struct ub_packed_rrset_key* rrset, int lame); + +/** + * Add address to the delegation point. No servername is associated or checked. + * @param dp: delegation point. + * @param regional: where to allocate the info. + * @param addr: the address. + * @param addrlen: the length of addr. + * @param bogus: if address is bogus. + * @param lame: if address is lame. + * @return false on error. + */ +int delegpt_add_addr(struct delegpt* dp, struct regional* regional, + struct sockaddr_storage* addr, socklen_t addrlen, int bogus, int lame); + +/** + * Find NS record in name list of delegation point. + * @param dp: delegation point. + * @param name: name of nameserver to look for, uncompressed wireformat. + * @param namelen: length of name. + * @return the ns structure or NULL if not found. + */ +struct delegpt_ns* delegpt_find_ns(struct delegpt* dp, uint8_t* name, + size_t namelen); + +/** + * Find address record in total list of delegation point. + * @param dp: delegation point. + * @param addr: address + * @param addrlen: length of addr + * @return the addr structure or NULL if not found. + */ +struct delegpt_addr* delegpt_find_addr(struct delegpt* dp, + struct sockaddr_storage* addr, socklen_t addrlen); + +/** + * Print the delegation point to the log. For debugging. + * @param v: verbosity value that is needed to emit to log. + * @param dp: delegation point. + */ +void delegpt_log(enum verbosity_value v, struct delegpt* dp); + +/** count NS and number missing for logging */ +void delegpt_count_ns(struct delegpt* dp, size_t* numns, size_t* missing); + +/** count addresses, and number in result and available lists, for logging */ +void delegpt_count_addr(struct delegpt* dp, size_t* numaddr, size_t* numres, + size_t* numavail); + +/** + * Add all usable targets to the result list. + * @param dp: delegation point. + */ +void delegpt_add_unused_targets(struct delegpt* dp); + +/** + * Count number of missing targets. These are ns names with no resolved flag. + * @param dp: delegation point. + * @return number of missing targets (or 0). + */ +size_t delegpt_count_missing_targets(struct delegpt* dp); + +/** count total number of targets in dp */ +size_t delegpt_count_targets(struct delegpt* dp); + +/** + * Create new delegation point from a dns message + * + * Note that this method does not actually test to see if the message is an + * actual referral. It really is just checking to see if it can construct a + * delegation point, so the message could be of some other type (some ANSWER + * messages, some CNAME messages, generally.) Note that the resulting + * DelegationPoint will contain targets for all "relevant" glue (i.e., + * address records whose ownernames match the target of one of the NS + * records), so if policy dictates that some glue should be discarded beyond + * that, discard it before calling this method. Note that this method will + * find "glue" in either the ADDITIONAL section or the ANSWER section. + * + * @param msg: the dns message, referral. + * @param regional: where to allocate delegation point. + * @return new delegation point or NULL on alloc error, or if the + * message was not appropriate. + */ +struct delegpt* delegpt_from_message(struct dns_msg* msg, + struct regional* regional); + +/** + * Add negative message to delegation point. + * @param dp: delegation point. + * @param msg: the message added, marks off A or AAAA from an NS entry. + */ +void delegpt_add_neg_msg(struct delegpt* dp, struct msgreply_entry* msg); + +/** + * Register the fact that there is no ipv6 and thus AAAAs are not going + * to be queried for or be useful. + * @param dp: the delegation point. Updated to reflect no ipv6. + */ +void delegpt_no_ipv6(struct delegpt* dp); + +/** + * Register the fact that there is no ipv4 and thus As are not going + * to be queried for or be useful. + * @param dp: the delegation point. Updated to reflect no ipv4. + */ +void delegpt_no_ipv4(struct delegpt* dp); + +/** + * create malloced delegation point, with the given name + * @param name: uncompressed wireformat of degegpt name. + * @return NULL on alloc failure + */ +struct delegpt* delegpt_create_mlc(uint8_t* name); + +/** + * free malloced delegation point. + * @param dp: must have been created with delegpt_create_mlc, free'd. + */ +void delegpt_free_mlc(struct delegpt* dp); + +/** + * Set name of delegation point. + * @param dp: delegation point. malloced. + * @param name: name to use. + * @return false on error. + */ +int delegpt_set_name_mlc(struct delegpt* dp, uint8_t* name); + +/** + * add a name to malloced delegation point. + * @param dp: must have been created with delegpt_create_mlc. + * @param name: the name to add. + * @param lame: the name is lame, disprefer. + * @return false on error. + */ +int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, int lame); + +/** + * add an address to a malloced delegation point. + * @param dp: must have been created with delegpt_create_mlc. + * @param addr: the address. + * @param addrlen: the length of addr. + * @param bogus: if address is bogus. + * @param lame: if address is lame. + * @return false on error. + */ +int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr, + socklen_t addrlen, int bogus, int lame); + +/** + * Add target address to the delegation point. + * @param dp: must have been created with delegpt_create_mlc. + * @param name: name for which target was found (must be in nslist). + * This name is marked resolved. + * @param namelen: length of name. + * @param addr: the address. + * @param addrlen: the length of addr. + * @param bogus: security status for the address, pass true if bogus. + * @param lame: address is lame. + * @return false on error. + */ +int delegpt_add_target_mlc(struct delegpt* dp, uint8_t* name, size_t namelen, + struct sockaddr_storage* addr, socklen_t addrlen, int bogus, int lame); + +/** get memory in use by dp */ +size_t delegpt_get_mem(struct delegpt* dp); + +#endif /* ITERATOR_ITER_DELEGPT_H */ diff --git a/iterator/iter_donotq.c b/iterator/iter_donotq.c new file mode 100644 index 00000000000..bd606335bcd --- /dev/null +++ b/iterator/iter_donotq.c @@ -0,0 +1,153 @@ +/* + * iterator/iter_donotq.c - iterative resolver donotqueryaddresses storage. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions to assist the iterator module. + * The donotqueryaddresses are stored and looked up. These addresses + * (like 127.0.0.1) must not be used to send queries to, and can be + * discarded immediately from the server selection. + */ +#include "config.h" +#include "iterator/iter_donotq.h" +#include "util/regional.h" +#include "util/log.h" +#include "util/config_file.h" +#include "util/net_help.h" + +struct iter_donotq* +donotq_create(void) +{ + struct iter_donotq* dq = (struct iter_donotq*)calloc(1, + sizeof(struct iter_donotq)); + if(!dq) + return NULL; + dq->region = regional_create(); + if(!dq->region) { + donotq_delete(dq); + return NULL; + } + return dq; +} + +void +donotq_delete(struct iter_donotq* dq) +{ + if(!dq) + return; + regional_destroy(dq->region); + free(dq); +} + +/** insert new address into donotq structure */ +static int +donotq_insert(struct iter_donotq* dq, struct sockaddr_storage* addr, + socklen_t addrlen, int net) +{ + struct addr_tree_node* node = (struct addr_tree_node*)regional_alloc( + dq->region, sizeof(*node)); + if(!node) + return 0; + if(!addr_tree_insert(&dq->tree, node, addr, addrlen, net)) { + verbose(VERB_QUERY, "duplicate donotquery address ignored."); + } + return 1; +} + +/** apply donotq string */ +static int +donotq_str_cfg(struct iter_donotq* dq, const char* str) +{ + struct sockaddr_storage addr; + int net; + socklen_t addrlen; + verbose(VERB_ALGO, "donotq: %s", str); + if(!netblockstrtoaddr(str, UNBOUND_DNS_PORT, &addr, &addrlen, &net)) { + log_err("cannot parse donotquery netblock: %s", str); + return 0; + } + if(!donotq_insert(dq, &addr, addrlen, net)) { + log_err("out of memory"); + return 0; + } + return 1; +} + +/** read donotq config */ +static int +read_donotq(struct iter_donotq* dq, struct config_file* cfg) +{ + struct config_strlist* p; + for(p = cfg->donotqueryaddrs; p; p = p->next) { + log_assert(p->str); + if(!donotq_str_cfg(dq, p->str)) + return 0; + } + return 1; +} + +int +donotq_apply_cfg(struct iter_donotq* dq, struct config_file* cfg) +{ + regional_free_all(dq->region); + addr_tree_init(&dq->tree); + if(!read_donotq(dq, cfg)) + return 0; + if(cfg->donotquery_localhost) { + if(!donotq_str_cfg(dq, "127.0.0.0/8")) + return 0; + if(cfg->do_ip6) { + if(!donotq_str_cfg(dq, "::1")) + return 0; + } + } + addr_tree_init_parents(&dq->tree); + return 1; +} + +int +donotq_lookup(struct iter_donotq* donotq, struct sockaddr_storage* addr, + socklen_t addrlen) +{ + return addr_tree_lookup(&donotq->tree, addr, addrlen) != NULL; +} + +size_t +donotq_get_mem(struct iter_donotq* donotq) +{ + if(!donotq) return 0; + return sizeof(*donotq) + regional_get_mem(donotq->region); +} diff --git a/iterator/iter_donotq.h b/iterator/iter_donotq.h new file mode 100644 index 00000000000..4c4fcb289dc --- /dev/null +++ b/iterator/iter_donotq.h @@ -0,0 +1,101 @@ +/* + * iterator/iter_donotq.h - iterative resolver donotqueryaddresses storage. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions to assist the iterator module. + * Keep track of the donotquery addresses and lookup fast. + */ + +#ifndef ITERATOR_ITER_DONOTQ_H +#define ITERATOR_ITER_DONOTQ_H +#include "util/storage/dnstree.h" +struct iter_env; +struct config_file; +struct regional; + +/** + * Iterator donotqueryaddresses structure + */ +struct iter_donotq { + /** regional for allocation */ + struct regional* region; + /** + * Tree of the address spans that are blocked. + * contents of type addr_tree_node. Each node is an address span + * that must not be used to send queries to. + */ + rbtree_t tree; +}; + +/** + * Create donotqueryaddresses structure + * @return new structure or NULL on error. + */ +struct iter_donotq* donotq_create(void); + +/** + * Delete donotqueryaddresses structure. + * @param donotq: to delete. + */ +void donotq_delete(struct iter_donotq* donotq); + +/** + * Process donotqueryaddresses config. + * @param donotq: where to store. + * @param cfg: config options. + * @return 0 on error. + */ +int donotq_apply_cfg(struct iter_donotq* donotq, struct config_file* cfg); + +/** + * See if an address is blocked. + * @param donotq: structure for address storage. + * @param addr: address to check + * @param addrlen: length of addr. + * @return: true if the address must not be queried. false if unlisted. + */ +int donotq_lookup(struct iter_donotq* donotq, struct sockaddr_storage* addr, + socklen_t addrlen); + +/** + * Get memory used by donotqueryaddresses structure. + * @param donotq: structure for address storage. + * @return bytes in use. + */ +size_t donotq_get_mem(struct iter_donotq* donotq); + +#endif /* ITERATOR_ITER_DONOTQ_H */ diff --git a/iterator/iter_fwd.c b/iterator/iter_fwd.c new file mode 100644 index 00000000000..04976db18b8 --- /dev/null +++ b/iterator/iter_fwd.c @@ -0,0 +1,508 @@ +/* + * iterator/iter_fwd.c - iterative resolver module forward zones. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions to assist the iterator module. + * Keep track of forward zones and config settings. + */ +#include "config.h" +#include +#include +#include +#include "iterator/iter_fwd.h" +#include "iterator/iter_delegpt.h" +#include "util/log.h" +#include "util/config_file.h" +#include "util/net_help.h" +#include "util/data/dname.h" + +int +fwd_cmp(const void* k1, const void* k2) +{ + int m; + struct iter_forward_zone* n1 = (struct iter_forward_zone*)k1; + struct iter_forward_zone* n2 = (struct iter_forward_zone*)k2; + if(n1->dclass != n2->dclass) { + if(n1->dclass < n2->dclass) + return -1; + return 1; + } + return dname_lab_cmp(n1->name, n1->namelabs, n2->name, n2->namelabs, + &m); +} + +struct iter_forwards* +forwards_create(void) +{ + struct iter_forwards* fwd = (struct iter_forwards*)calloc(1, + sizeof(struct iter_forwards)); + if(!fwd) + return NULL; + return fwd; +} + +static void fwd_zone_free(struct iter_forward_zone* n) +{ + if(!n) return; + delegpt_free_mlc(n->dp); + free(n->name); + free(n); +} + +static void delfwdnode(rbnode_t* n, void* ATTR_UNUSED(arg)) +{ + struct iter_forward_zone* node = (struct iter_forward_zone*)n; + fwd_zone_free(node); +} + +static void fwd_del_tree(struct iter_forwards* fwd) +{ + if(fwd->tree) + traverse_postorder(fwd->tree, &delfwdnode, NULL); + free(fwd->tree); +} + +void +forwards_delete(struct iter_forwards* fwd) +{ + if(!fwd) + return; + fwd_del_tree(fwd); + free(fwd); +} + +/** insert info into forward structure */ +static int +forwards_insert_data(struct iter_forwards* fwd, uint16_t c, uint8_t* nm, + size_t nmlen, int nmlabs, struct delegpt* dp) +{ + struct iter_forward_zone* node = (struct iter_forward_zone*)malloc( + sizeof(struct iter_forward_zone)); + if(!node) { + delegpt_free_mlc(dp); + return 0; + } + node->node.key = node; + node->dclass = c; + node->name = memdup(nm, nmlen); + if(!node->name) { + delegpt_free_mlc(dp); + free(node); + return 0; + } + node->namelen = nmlen; + node->namelabs = nmlabs; + node->dp = dp; + if(!rbtree_insert(fwd->tree, &node->node)) { + log_err("duplicate forward zone ignored."); + delegpt_free_mlc(dp); + free(node->name); + free(node); + } + return 1; +} + +/** insert new info into forward structure given dp */ +static int +forwards_insert(struct iter_forwards* fwd, uint16_t c, struct delegpt* dp) +{ + return forwards_insert_data(fwd, c, dp->name, dp->namelen, + dp->namelabs, dp); +} + +/** initialise parent pointers in the tree */ +static void +fwd_init_parents(struct iter_forwards* fwd) +{ + struct iter_forward_zone* node, *prev = NULL, *p; + int m; + RBTREE_FOR(node, struct iter_forward_zone*, fwd->tree) { + node->parent = NULL; + if(!prev || prev->dclass != node->dclass) { + prev = node; + continue; + } + (void)dname_lab_cmp(prev->name, prev->namelabs, node->name, + node->namelabs, &m); /* we know prev is smaller */ + /* sort order like: . com. bla.com. zwb.com. net. */ + /* find the previous, or parent-parent-parent */ + for(p = prev; p; p = p->parent) + /* looking for name with few labels, a parent */ + if(p->namelabs <= m) { + /* ==: since prev matched m, this is closest*/ + /* <: prev matches more, but is not a parent, + * this one is a (grand)parent */ + node->parent = p; + break; + } + prev = node; + } +} + +/** set zone name */ +static struct delegpt* +read_fwds_name(struct config_stub* s) +{ + struct delegpt* dp; + ldns_rdf* rdf; + if(!s->name) { + log_err("forward zone without a name (use name \".\" to forward everything)"); + return NULL; + } + rdf = ldns_dname_new_frm_str(s->name); + if(!rdf) { + log_err("cannot parse forward zone name %s", s->name); + return NULL; + } + if(!(dp=delegpt_create_mlc(ldns_rdf_data(rdf)))) { + ldns_rdf_deep_free(rdf); + log_err("out of memory"); + return NULL; + } + ldns_rdf_deep_free(rdf); + return dp; +} + +/** set fwd host names */ +static int +read_fwds_host(struct config_stub* s, struct delegpt* dp) +{ + struct config_strlist* p; + ldns_rdf* rdf; + for(p = s->hosts; p; p = p->next) { + log_assert(p->str); + rdf = ldns_dname_new_frm_str(p->str); + if(!rdf) { + log_err("cannot parse forward %s server name: '%s'", + s->name, p->str); + return 0; + } + if(!delegpt_add_ns_mlc(dp, ldns_rdf_data(rdf), 0)) { + ldns_rdf_deep_free(rdf); + log_err("out of memory"); + return 0; + } + ldns_rdf_deep_free(rdf); + } + return 1; +} + +/** set fwd server addresses */ +static int +read_fwds_addr(struct config_stub* s, struct delegpt* dp) +{ + struct config_strlist* p; + struct sockaddr_storage addr; + socklen_t addrlen; + for(p = s->addrs; p; p = p->next) { + log_assert(p->str); + if(!extstrtoaddr(p->str, &addr, &addrlen)) { + log_err("cannot parse forward %s ip address: '%s'", + s->name, p->str); + return 0; + } + if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0)) { + log_err("out of memory"); + return 0; + } + } + return 1; +} + +/** read forwards config */ +static int +read_forwards(struct iter_forwards* fwd, struct config_file* cfg) +{ + struct config_stub* s; + for(s = cfg->forwards; s; s = s->next) { + struct delegpt* dp; + if(!(dp=read_fwds_name(s)) || + !read_fwds_host(s, dp) || + !read_fwds_addr(s, dp)) + return 0; + /* set flag that parent side NS information is included. + * Asking a (higher up) server on the internet is not useful */ + /* the flag is turned off for 'forward-first' so that the + * last resort will ask for parent-side NS record and thus + * fallback to the internet name servers on a failure */ + dp->has_parent_side_NS = (uint8_t)!s->isfirst; + if(!forwards_insert(fwd, LDNS_RR_CLASS_IN, dp)) + return 0; + verbose(VERB_QUERY, "Forward zone server list:"); + delegpt_log(VERB_QUERY, dp); + } + return 1; +} + +/** see if zone needs to have a hole inserted */ +static int +need_hole_insert(rbtree_t* tree, struct iter_forward_zone* zone) +{ + struct iter_forward_zone k; + if(rbtree_search(tree, zone)) + return 0; /* exact match exists */ + k = *zone; + k.node.key = &k; + /* search up the tree */ + do { + dname_remove_label(&k.name, &k.namelen); + k.namelabs --; + if(rbtree_search(tree, &k)) + return 1; /* found an upper forward zone, need hole */ + } while(k.namelabs > 1); + return 0; /* no forwards above, no holes needed */ +} + +/** insert a stub hole (if necessary) for stub name */ +static int +fwd_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm) +{ + struct iter_forward_zone key; + key.node.key = &key; + key.dclass = c; + key.name = nm; + key.namelabs = dname_count_size_labels(key.name, &key.namelen); + if(need_hole_insert(fwd->tree, &key)) { + return forwards_insert_data(fwd, key.dclass, key.name, + key.namelen, key.namelabs, NULL); + } + return 1; +} + +/** make NULL entries for stubs */ +static int +make_stub_holes(struct iter_forwards* fwd, struct config_file* cfg) +{ + struct config_stub* s; + for(s = cfg->stubs; s; s = s->next) { + ldns_rdf* rdf = ldns_dname_new_frm_str(s->name); + if(!rdf) { + log_err("cannot parse stub name '%s'", s->name); + return 0; + } + if(!fwd_add_stub_hole(fwd, LDNS_RR_CLASS_IN, + ldns_rdf_data(rdf))) { + ldns_rdf_deep_free(rdf); + log_err("out of memory"); + return 0; + } + ldns_rdf_deep_free(rdf); + } + return 1; +} + +int +forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg) +{ + fwd_del_tree(fwd); + fwd->tree = rbtree_create(fwd_cmp); + if(!fwd->tree) + return 0; + + /* read forward zones */ + if(!read_forwards(fwd, cfg)) + return 0; + if(!make_stub_holes(fwd, cfg)) + return 0; + fwd_init_parents(fwd); + return 1; +} + +struct delegpt* +forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass) +{ + /* lookup the forward zone in the tree */ + rbnode_t* res = NULL; + struct iter_forward_zone *result; + struct iter_forward_zone key; + key.node.key = &key; + key.dclass = qclass; + key.name = qname; + key.namelabs = dname_count_size_labels(qname, &key.namelen); + if(rbtree_find_less_equal(fwd->tree, &key, &res)) { + /* exact */ + result = (struct iter_forward_zone*)res; + } else { + /* smaller element (or no element) */ + int m; + result = (struct iter_forward_zone*)res; + if(!result || result->dclass != qclass) + 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 stub */ + if(result->namelabs <= m) + break; + result = result->parent; + } + } + if(result) + return result->dp; + return NULL; +} + +struct delegpt* +forwards_lookup_root(struct iter_forwards* fwd, uint16_t qclass) +{ + uint8_t root = 0; + return forwards_lookup(fwd, &root, qclass); +} + +int +forwards_next_root(struct iter_forwards* fwd, uint16_t* dclass) +{ + struct iter_forward_zone key; + rbnode_t* n; + struct iter_forward_zone* p; + if(*dclass == 0) { + /* first root item is first item in tree */ + n = rbtree_first(fwd->tree); + if(n == RBTREE_NULL) + return 0; + p = (struct iter_forward_zone*)n; + if(dname_is_root(p->name)) { + *dclass = p->dclass; + return 1; + } + /* root not first item? search for higher items */ + *dclass = p->dclass + 1; + return forwards_next_root(fwd, dclass); + } + /* find class n in tree, we may get a direct hit, or if we don't + * this is the last item of the previous class so rbtree_next() takes + * us to the next root (if any) */ + key.node.key = &key; + key.name = (uint8_t*)"\000"; + key.namelen = 1; + key.namelabs = 0; + key.dclass = *dclass; + n = NULL; + if(rbtree_find_less_equal(fwd->tree, &key, &n)) { + /* exact */ + return 1; + } else { + /* smaller element */ + if(!n || n == RBTREE_NULL) + return 0; /* nothing found */ + n = rbtree_next(n); + if(n == RBTREE_NULL) + return 0; /* no higher */ + p = (struct iter_forward_zone*)n; + if(dname_is_root(p->name)) { + *dclass = p->dclass; + return 1; + } + /* not a root node, return next higher item */ + *dclass = p->dclass+1; + return forwards_next_root(fwd, dclass); + } +} + +size_t +forwards_get_mem(struct iter_forwards* fwd) +{ + struct iter_forward_zone* p; + size_t s; + if(!fwd) + return 0; + s = sizeof(*fwd) + sizeof(*fwd->tree); + RBTREE_FOR(p, struct iter_forward_zone*, fwd->tree) { + s += sizeof(*p) + p->namelen + delegpt_get_mem(p->dp); + } + return s; +} + +static struct iter_forward_zone* +fwd_zone_find(struct iter_forwards* fwd, uint16_t c, uint8_t* nm) +{ + struct iter_forward_zone key; + key.node.key = &key; + key.dclass = c; + key.name = nm; + key.namelabs = dname_count_size_labels(nm, &key.namelen); + return (struct iter_forward_zone*)rbtree_search(fwd->tree, &key); +} + +int +forwards_add_zone(struct iter_forwards* fwd, uint16_t c, struct delegpt* dp) +{ + struct iter_forward_zone *z; + if((z=fwd_zone_find(fwd, c, dp->name)) != NULL) { + (void)rbtree_delete(fwd->tree, &z->node); + fwd_zone_free(z); + } + if(!forwards_insert(fwd, c, dp)) + return 0; + fwd_init_parents(fwd); + return 1; +} + +void +forwards_delete_zone(struct iter_forwards* fwd, uint16_t c, uint8_t* nm) +{ + struct iter_forward_zone *z; + if(!(z=fwd_zone_find(fwd, c, nm))) + return; /* nothing to do */ + (void)rbtree_delete(fwd->tree, &z->node); + fwd_zone_free(z); + fwd_init_parents(fwd); +} + +int +forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm) +{ + if(!fwd_add_stub_hole(fwd, c, nm)) { + return 0; + } + fwd_init_parents(fwd); + return 1; +} + +void +forwards_delete_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm) +{ + struct iter_forward_zone *z; + if(!(z=fwd_zone_find(fwd, c, nm))) + return; /* nothing to do */ + if(z->dp != NULL) + return; /* not a stub hole */ + (void)rbtree_delete(fwd->tree, &z->node); + fwd_zone_free(z); + fwd_init_parents(fwd); +} + diff --git a/iterator/iter_fwd.h b/iterator/iter_fwd.h new file mode 100644 index 00000000000..dbb84f22612 --- /dev/null +++ b/iterator/iter_fwd.h @@ -0,0 +1,189 @@ +/* + * iterator/iter_fwd.h - iterative resolver module forward zones. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions to assist the iterator module. + * Keep track of forward zones, and read those from config. + */ + +#ifndef ITERATOR_ITER_FWD_H +#define ITERATOR_ITER_FWD_H +#include "util/rbtree.h" +struct config_file; +struct delegpt; + +/** + * Iterator forward zones structure + */ +struct iter_forwards { + /** + * Zones are stored in this tree. Sort order is specially chosen. + * first sorted on qclass. Then on dname in nsec-like order, so that + * a lookup on class, name will return an exact match or the closest + * match which gives the ancestor needed. + * contents of type iter_forward_zone. + */ + rbtree_t* tree; +}; + +/** + * Iterator forward servers for a particular zone. + */ +struct iter_forward_zone { + /** redblacktree node, key is this structure: class and name */ + rbnode_t node; + /** name */ + uint8_t* name; + /** length of name */ + size_t namelen; + /** number of labels in name */ + int namelabs; + /** delegation point with forward server information for this zone. + * If NULL then this forward entry is used to indicate that a + * stub-zone with the same name exists, and should be used. + * This delegation point is malloced. + */ + struct delegpt* dp; + /** pointer to parent in tree (or NULL if none) */ + struct iter_forward_zone* parent; + /** class. host order. */ + uint16_t dclass; +}; + +/** + * Create forwards + * @return new forwards or NULL on error. + */ +struct iter_forwards* forwards_create(void); + +/** + * Delete forwards. + * @param fwd: to delete. + */ +void forwards_delete(struct iter_forwards* fwd); + +/** + * Process forwards config. + * @param fwd: where to store. + * @param cfg: config options. + * @return 0 on error. + */ +int forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg); + +/** + * Find forward zone information + * For this qname/qclass find forward zone information, returns delegation + * point with server names and addresses, or NULL if no forwarding is needed. + * + * @param fwd: forward storage. + * @param qname: The qname of the query. + * @param qclass: The qclass of the query. + * @return: A delegation point if the query has to be forwarded to that list, + * otherwise null. + */ +struct delegpt* forwards_lookup(struct iter_forwards* fwd, + uint8_t* qname, uint16_t qclass); + +/** + * Same as forwards_lookup, but for the root only + * @param fwd: forward storage. + * @param qclass: The qclass of the query. + * @return: A delegation point if root forward exists, otherwise null. + */ +struct delegpt* forwards_lookup_root(struct iter_forwards* fwd, + uint16_t qclass); + +/** + * Find next root item in forwards lookup tree. + * @param fwd: the forward storage + * @param qclass: class to look at next, or higher. + * @return false if none found, or if true stored in qclass. + */ +int forwards_next_root(struct iter_forwards* fwd, uint16_t* qclass); + +/** + * Get memory in use by forward storage + * @param fwd: forward storage. + * @return bytes in use + */ +size_t forwards_get_mem(struct iter_forwards* fwd); + +/** compare two fwd entries */ +int fwd_cmp(const void* k1, const void* k2); + +/** + * Add zone to forward structure. For external use since it recalcs + * the tree parents. + * @param fwd: the forward data structure + * @param c: class of zone + * @param dp: delegation point with name and target nameservers for new + * forward zone. malloced. + * @return false on failure (out of memory); + */ +int forwards_add_zone(struct iter_forwards* fwd, uint16_t c, + struct delegpt* dp); + +/** + * Remove zone from forward structure. For external use since it + * recalcs the tree parents. + * @param fwd: the forward data structure + * @param c: class of zone + * @param nm: name of zone (in uncompressed wireformat). + */ +void forwards_delete_zone(struct iter_forwards* fwd, uint16_t c, uint8_t* nm); + +/** + * Add stub hole (empty entry in forward table, that makes resolution skip + * a forward-zone because the stub zone should override the forward zone). + * Does not add one if not necessary. + * @param fwd: the forward data structure + * @param c: class of zone + * @param nm: name of zone (in uncompressed wireformat). + * @return false on failure (out of memory); + */ +int forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm); + +/** + * Remove stub hole, if one exists. + * @param fwd: the forward data structure + * @param c: class of zone + * @param nm: name of zone (in uncompressed wireformat). + */ +void forwards_delete_stub_hole(struct iter_forwards* fwd, uint16_t c, + uint8_t* nm); + +#endif /* ITERATOR_ITER_FWD_H */ diff --git a/iterator/iter_hints.c b/iterator/iter_hints.c new file mode 100644 index 00000000000..cfb9db7abb8 --- /dev/null +++ b/iterator/iter_hints.c @@ -0,0 +1,534 @@ +/* + * iterator/iter_hints.c - iterative resolver module stub and root hints. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions to assist the iterator module. + * Keep track of stub and root hints, and read those from config. + */ +#include "config.h" +#include +#include +#include "iterator/iter_hints.h" +#include "iterator/iter_delegpt.h" +#include "util/log.h" +#include "util/config_file.h" +#include "util/net_help.h" +#include "util/data/dname.h" + +struct iter_hints* +hints_create(void) +{ + struct iter_hints* hints = (struct iter_hints*)calloc(1, + sizeof(struct iter_hints)); + if(!hints) + return NULL; + return hints; +} + +static void hints_stub_free(struct iter_hints_stub* s) +{ + if(!s) return; + delegpt_free_mlc(s->dp); + free(s); +} + +static void delhintnode(rbnode_t* n, void* ATTR_UNUSED(arg)) +{ + struct iter_hints_stub* node = (struct iter_hints_stub*)n; + hints_stub_free(node); +} + +static void hints_del_tree(struct iter_hints* hints) +{ + traverse_postorder(&hints->tree, &delhintnode, NULL); +} + +void +hints_delete(struct iter_hints* hints) +{ + if(!hints) + return; + hints_del_tree(hints); + free(hints); +} + +/** add hint to delegation hints */ +static int +ah(struct delegpt* dp, const char* sv, const char* ip) +{ + struct sockaddr_storage addr; + socklen_t addrlen; + ldns_rdf* rdf = ldns_dname_new_frm_str(sv); + if(!rdf) { + log_err("could not parse %s", sv); + return 0; + } + if(!delegpt_add_ns_mlc(dp, ldns_rdf_data(rdf), 0) || + !extstrtoaddr(ip, &addr, &addrlen) || + !delegpt_add_target_mlc(dp, ldns_rdf_data(rdf), ldns_rdf_size(rdf), + &addr, addrlen, 0, 0)) { + ldns_rdf_deep_free(rdf); + return 0; + } + ldns_rdf_deep_free(rdf); + return 1; +} + +/** obtain compiletime provided root hints */ +static struct delegpt* +compile_time_root_prime(int do_ip4, int do_ip6) +{ + /* from: + ; This file is made available by InterNIC + ; under anonymous FTP as + ; file /domain/named.cache + ; on server FTP.INTERNIC.NET + ; -OR- RS.INTERNIC.NET + ; + ; related version of root zone: 2010061700 + */ + struct delegpt* dp = delegpt_create_mlc((uint8_t*)"\000"); + if(!dp) + return NULL; + dp->has_parent_side_NS = 1; + if(do_ip4) { + if(!ah(dp, "A.ROOT-SERVERS.NET.", "198.41.0.4")) return 0; + if(!ah(dp, "B.ROOT-SERVERS.NET.", "192.228.79.201")) return 0; + if(!ah(dp, "C.ROOT-SERVERS.NET.", "192.33.4.12")) return 0; + if(!ah(dp, "D.ROOT-SERVERS.NET.", "128.8.10.90")) return 0; + if(!ah(dp, "E.ROOT-SERVERS.NET.", "192.203.230.10")) return 0; + if(!ah(dp, "F.ROOT-SERVERS.NET.", "192.5.5.241")) return 0; + if(!ah(dp, "G.ROOT-SERVERS.NET.", "192.112.36.4")) return 0; + if(!ah(dp, "H.ROOT-SERVERS.NET.", "128.63.2.53")) return 0; + if(!ah(dp, "I.ROOT-SERVERS.NET.", "192.36.148.17")) return 0; + if(!ah(dp, "J.ROOT-SERVERS.NET.", "192.58.128.30")) return 0; + if(!ah(dp, "K.ROOT-SERVERS.NET.", "193.0.14.129")) return 0; + if(!ah(dp, "L.ROOT-SERVERS.NET.", "199.7.83.42")) return 0; + if(!ah(dp, "M.ROOT-SERVERS.NET.", "202.12.27.33")) return 0; + } + if(do_ip6) { + if(!ah(dp, "A.ROOT-SERVERS.NET.", "2001:503:ba3e::2:30")) return 0; + if(!ah(dp, "D.ROOT-SERVERS.NET.", "2001:500:2d::d")) return 0; + if(!ah(dp, "F.ROOT-SERVERS.NET.", "2001:500:2f::f")) return 0; + if(!ah(dp, "H.ROOT-SERVERS.NET.", "2001:500:1::803f:235")) return 0; + if(!ah(dp, "I.ROOT-SERVERS.NET.", "2001:7fe::53")) return 0; + if(!ah(dp, "J.ROOT-SERVERS.NET.", "2001:503:c27::2:30")) return 0; + if(!ah(dp, "K.ROOT-SERVERS.NET.", "2001:7fd::1")) return 0; + if(!ah(dp, "L.ROOT-SERVERS.NET.", "2001:500:3::42")) return 0; + if(!ah(dp, "M.ROOT-SERVERS.NET.", "2001:dc3::35")) return 0; + } + return dp; +} + +/** insert new hint info into hint structure */ +static int +hints_insert(struct iter_hints* hints, uint16_t c, struct delegpt* dp, + int noprime) +{ + struct iter_hints_stub* node = (struct iter_hints_stub*)malloc( + sizeof(struct iter_hints_stub)); + if(!node) { + delegpt_free_mlc(dp); + return 0; + } + node->dp = dp; + node->noprime = (uint8_t)noprime; + if(!name_tree_insert(&hints->tree, &node->node, dp->name, dp->namelen, + dp->namelabs, c)) { + log_err("second hints ignored."); + delegpt_free_mlc(dp); + free(node); + } + return 1; +} + +/** set stub name */ +static struct delegpt* +read_stubs_name(struct config_stub* s) +{ + struct delegpt* dp; + ldns_rdf* rdf; + if(!s->name) { + log_err("stub zone without a name"); + return NULL; + } + rdf = ldns_dname_new_frm_str(s->name); + if(!rdf) { + log_err("cannot parse stub zone name %s", s->name); + return NULL; + } + if(!(dp=delegpt_create_mlc(ldns_rdf_data(rdf)))) { + ldns_rdf_deep_free(rdf); + log_err("out of memory"); + return NULL; + } + ldns_rdf_deep_free(rdf); + return dp; +} + +/** set stub host names */ +static int +read_stubs_host(struct config_stub* s, struct delegpt* dp) +{ + struct config_strlist* p; + ldns_rdf* rdf; + for(p = s->hosts; p; p = p->next) { + log_assert(p->str); + rdf = ldns_dname_new_frm_str(p->str); + if(!rdf) { + log_err("cannot parse stub %s nameserver name: '%s'", + s->name, p->str); + return 0; + } + if(!delegpt_add_ns_mlc(dp, ldns_rdf_data(rdf), 0)) { + ldns_rdf_deep_free(rdf); + log_err("out of memory"); + return 0; + } + ldns_rdf_deep_free(rdf); + } + return 1; +} + +/** set stub server addresses */ +static int +read_stubs_addr(struct config_stub* s, struct delegpt* dp) +{ + struct config_strlist* p; + struct sockaddr_storage addr; + socklen_t addrlen; + for(p = s->addrs; p; p = p->next) { + log_assert(p->str); + if(!extstrtoaddr(p->str, &addr, &addrlen)) { + log_err("cannot parse stub %s ip address: '%s'", + s->name, p->str); + return 0; + } + if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0)) { + log_err("out of memory"); + return 0; + } + } + return 1; +} + +/** read stubs config */ +static int +read_stubs(struct iter_hints* hints, struct config_file* cfg) +{ + struct config_stub* s; + struct delegpt* dp; + for(s = cfg->stubs; s; s = s->next) { + if(!(dp=read_stubs_name(s)) || + !read_stubs_host(s, dp) || + !read_stubs_addr(s, dp)) + return 0; + /* the flag is turned off for 'stub-first' so that the + * last resort will ask for parent-side NS record and thus + * fallback to the internet name servers on a failure */ + dp->has_parent_side_NS = (uint8_t)!s->isfirst; + if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp, !s->isprime)) + return 0; + delegpt_log(VERB_QUERY, dp); + } + return 1; +} + +/** read root hints from file */ +static int +read_root_hints(struct iter_hints* hints, char* fname) +{ + int lineno = 0; + uint32_t default_ttl = 0; + ldns_rdf* origin = NULL; + ldns_rdf* prev_rr = NULL; + struct delegpt* dp; + ldns_rr* rr = NULL; + ldns_status status; + uint16_t c = LDNS_RR_CLASS_IN; + FILE* f = fopen(fname, "r"); + if(!f) { + log_err("could not read root hints %s: %s", + fname, strerror(errno)); + return 0; + } + dp = delegpt_create_mlc(NULL); + if(!dp) { + log_err("out of memory reading root hints"); + fclose(f); + return 0; + } + verbose(VERB_QUERY, "Reading root hints from %s", fname); + dp->has_parent_side_NS = 1; + while(!feof(f)) { + status = ldns_rr_new_frm_fp_l(&rr, f, + &default_ttl, &origin, &prev_rr, &lineno); + if(status == LDNS_STATUS_SYNTAX_EMPTY || + status == LDNS_STATUS_SYNTAX_TTL || + status == LDNS_STATUS_SYNTAX_ORIGIN) + continue; + if(status != LDNS_STATUS_OK) { + log_err("reading root hints %s %d: %s", fname, + lineno, ldns_get_errorstr_by_id(status)); + goto stop_read; + } + if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_NS) { + if(!delegpt_add_ns_mlc(dp, + ldns_rdf_data(ldns_rr_rdf(rr, 0)), 0)) { + log_err("out of memory reading root hints"); + goto stop_read; + } + c = ldns_rr_get_class(rr); + if(!dp->name) { + if(!delegpt_set_name_mlc(dp, + ldns_rdf_data(ldns_rr_owner(rr)))){ + log_err("out of memory."); + goto stop_read; + } + } + } else if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_A) { + struct sockaddr_in sa; + socklen_t len = (socklen_t)sizeof(sa); + memset(&sa, 0, len); + sa.sin_family = AF_INET; + sa.sin_port = (in_port_t)htons(UNBOUND_DNS_PORT); + memmove(&sa.sin_addr, + ldns_rdf_data(ldns_rr_rdf(rr, 0)), INET_SIZE); + if(!delegpt_add_target_mlc(dp, + ldns_rdf_data(ldns_rr_owner(rr)), + ldns_rdf_size(ldns_rr_owner(rr)), + (struct sockaddr_storage*)&sa, len, + 0, 0)) { + log_err("out of memory reading root hints"); + goto stop_read; + } + } else if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_AAAA) { + struct sockaddr_in6 sa; + socklen_t len = (socklen_t)sizeof(sa); + memset(&sa, 0, len); + sa.sin6_family = AF_INET6; + sa.sin6_port = (in_port_t)htons(UNBOUND_DNS_PORT); + memmove(&sa.sin6_addr, + ldns_rdf_data(ldns_rr_rdf(rr, 0)), INET6_SIZE); + if(!delegpt_add_target_mlc(dp, + ldns_rdf_data(ldns_rr_owner(rr)), + ldns_rdf_size(ldns_rr_owner(rr)), + (struct sockaddr_storage*)&sa, len, + 0, 0)) { + log_err("out of memory reading root hints"); + goto stop_read; + } + } else { + log_warn("root hints %s:%d skipping type %d", + fname, lineno, ldns_rr_get_type(rr)); + } + + ldns_rr_free(rr); + } + + if (origin) + ldns_rdf_deep_free(origin); + if (prev_rr) + ldns_rdf_deep_free(prev_rr); + fclose(f); + if(!dp->name) { + log_warn("root hints %s: no NS content", fname); + delegpt_free_mlc(dp); + return 1; + } + if(!hints_insert(hints, c, dp, 0)) { + return 0; + } + delegpt_log(VERB_QUERY, dp); + return 1; + +stop_read: + if (origin) + ldns_rdf_deep_free(origin); + if (prev_rr) + ldns_rdf_deep_free(prev_rr); + delegpt_free_mlc(dp); + fclose(f); + return 0; +} + +/** read root hints list */ +static int +read_root_hints_list(struct iter_hints* hints, struct config_file* cfg) +{ + struct config_strlist* p; + for(p = cfg->root_hints; p; p = p->next) { + log_assert(p->str); + if(p->str && p->str[0]) { + char* f = p->str; + if(cfg->chrootdir && cfg->chrootdir[0] && + strncmp(p->str, cfg->chrootdir, + strlen(cfg->chrootdir)) == 0) + f += strlen(cfg->chrootdir); + if(!read_root_hints(hints, f)) + return 0; + } + } + return 1; +} + +int +hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg) +{ + hints_del_tree(hints); + name_tree_init(&hints->tree); + + /* read root hints */ + if(!read_root_hints_list(hints, cfg)) + return 0; + + /* read stub hints */ + if(!read_stubs(hints, cfg)) + return 0; + + /* use fallback compiletime root hints */ + if(!hints_lookup_root(hints, LDNS_RR_CLASS_IN)) { + struct delegpt* dp = compile_time_root_prime(cfg->do_ip4, + cfg->do_ip6); + verbose(VERB_ALGO, "no config, using builtin root hints."); + if(!dp) + return 0; + if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp, 0)) + return 0; + } + + name_tree_init_parents(&hints->tree); + return 1; +} + +struct delegpt* +hints_lookup_root(struct iter_hints* hints, uint16_t qclass) +{ + uint8_t rootlab = 0; + struct iter_hints_stub *stub; + stub = (struct iter_hints_stub*)name_tree_find(&hints->tree, + &rootlab, 1, 1, qclass); + if(!stub) + return NULL; + return stub->dp; +} + +struct iter_hints_stub* +hints_lookup_stub(struct iter_hints* hints, uint8_t* qname, + uint16_t qclass, struct delegpt* cache_dp) +{ + size_t len; + int labs; + struct iter_hints_stub *r; + + /* first lookup the stub */ + labs = dname_count_size_labels(qname, &len); + r = (struct iter_hints_stub*)name_tree_lookup(&hints->tree, qname, + len, labs, qclass); + if(!r) return NULL; + + /* If there is no cache (root prime situation) */ + if(cache_dp == NULL) { + if(r->dp->namelabs != 1) + return r; /* no cache dp, use any non-root stub */ + return NULL; + } + + /* + * If the stub is same as the delegation we got + * And has noprime set, we need to 'prime' to use this stub instead. + */ + if(r->noprime && query_dname_compare(cache_dp->name, r->dp->name)==0) + return r; /* use this stub instead of cached dp */ + + /* + * If our cached delegation point is above the hint, we need to prime. + */ + if(dname_strict_subdomain(r->dp->name, r->dp->namelabs, + cache_dp->name, cache_dp->namelabs)) + return r; /* need to prime this stub */ + return NULL; +} + +int hints_next_root(struct iter_hints* hints, uint16_t* qclass) +{ + return name_tree_next_root(&hints->tree, qclass); +} + +size_t +hints_get_mem(struct iter_hints* hints) +{ + size_t s; + struct iter_hints_stub* p; + if(!hints) return 0; + s = sizeof(*hints); + RBTREE_FOR(p, struct iter_hints_stub*, &hints->tree) { + s += sizeof(*p) + delegpt_get_mem(p->dp); + } + return s; +} + +int +hints_add_stub(struct iter_hints* hints, uint16_t c, struct delegpt* dp, + int noprime) +{ + struct iter_hints_stub *z; + if((z=(struct iter_hints_stub*)name_tree_find(&hints->tree, + dp->name, dp->namelen, dp->namelabs, c)) != NULL) { + (void)rbtree_delete(&hints->tree, &z->node); + hints_stub_free(z); + } + if(!hints_insert(hints, c, dp, noprime)) + return 0; + name_tree_init_parents(&hints->tree); + return 1; +} + +void +hints_delete_stub(struct iter_hints* hints, uint16_t c, uint8_t* nm) +{ + struct iter_hints_stub *z; + size_t len; + int labs = dname_count_size_labels(nm, &len); + if(!(z=(struct iter_hints_stub*)name_tree_find(&hints->tree, + nm, len, labs, c))) + return; /* nothing to do */ + (void)rbtree_delete(&hints->tree, &z->node); + hints_stub_free(z); + name_tree_init_parents(&hints->tree); +} + diff --git a/iterator/iter_hints.h b/iterator/iter_hints.h new file mode 100644 index 00000000000..7cac811ecd1 --- /dev/null +++ b/iterator/iter_hints.h @@ -0,0 +1,161 @@ +/* + * iterator/iter_hints.h - iterative resolver module stub and root hints. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions to assist the iterator module. + * Keep track of stub and root hints, and read those from config. + */ + +#ifndef ITERATOR_ITER_HINTS_H +#define ITERATOR_ITER_HINTS_H +#include "util/storage/dnstree.h" +struct iter_env; +struct config_file; +struct delegpt; + +/** + * Iterator hints structure + */ +struct iter_hints { + /** + * Hints are stored in this tree. Sort order is specially chosen. + * first sorted on qclass. Then on dname in nsec-like order, so that + * a lookup on class, name will return an exact match or the closest + * match which gives the ancestor needed. + * contents of type iter_hints_stub. The class IN root is in here. + * uses name_tree_node from dnstree.h. + */ + rbtree_t tree; +}; + +/** + * Iterator hints for a particular stub. + */ +struct iter_hints_stub { + /** tree sorted by name, class */ + struct name_tree_node node; + /** delegation point with hint information for this stub. malloced. */ + struct delegpt* dp; + /** does the stub need to forego priming (like on other ports) */ + uint8_t noprime; +}; + +/** + * Create hints + * @return new hints or NULL on error. + */ +struct iter_hints* hints_create(void); + +/** + * Delete hints. + * @param hints: to delete. + */ +void hints_delete(struct iter_hints* hints); + +/** + * Process hints config. Sets default values for root hints if no config. + * @param hints: where to store. + * @param cfg: config options. + * @return 0 on error. + */ +int hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg); + +/** + * Find root hints for the given class. + * @param hints: hint storage. + * @param qclass: class for which root hints are requested. host order. + * @return: NULL if no hints, or a ptr to stored hints. + */ +struct delegpt* hints_lookup_root(struct iter_hints* hints, uint16_t qclass); + +/** + * Find next root hints (to cycle through all root hints). + * @param hints: hint storage + * @param qclass: class for which root hints are sought. + * 0 means give the first available root hints class. + * x means, give class x or a higher class if any. + * returns the found class in this variable. + * @return true if a root hint class is found. + * false if not root hint class is found (qclass may have been changed). + */ +int hints_next_root(struct iter_hints* hints, uint16_t* qclass); + +/** + * Given a qname/qclass combination, and the delegation point from the cache + * for this qname/qclass, determine if this combination indicates that a + * stub hint exists and must be primed. + * + * @param hints: hint storage. + * @param qname: The qname that generated the delegation point. + * @param qclass: The qclass that generated the delegation point. + * @param dp: The cache generated delegation point. + * @return: A priming delegation point if there is a stub hint that must + * be primed, otherwise null. + */ +struct iter_hints_stub* hints_lookup_stub(struct iter_hints* hints, + uint8_t* qname, uint16_t qclass, struct delegpt* dp); + +/** + * Get memory in use by hints + * @param hints: hint storage. + * @return bytes in use + */ +size_t hints_get_mem(struct iter_hints* hints); + +/** + * Add stub to hints structure. For external use since it recalcs + * the tree parents. + * @param hints: the hints data structure + * @param c: class of zone + * @param dp: delegation point with name and target nameservers for new + * hints stub. malloced. + * @param noprime: set noprime option to true or false on new hint stub. + * @return false on failure (out of memory); + */ +int hints_add_stub(struct iter_hints* hints, uint16_t c, struct delegpt* dp, + int noprime); + +/** + * Remove stub from hints structure. For external use since it + * recalcs the tree parents. + * @param hints: the hints data structure + * @param c: class of stub zone + * @param nm: name of stub zone (in uncompressed wireformat). + */ +void hints_delete_stub(struct iter_hints* hints, uint16_t c, uint8_t* nm); + +#endif /* ITERATOR_ITER_HINTS_H */ diff --git a/iterator/iter_priv.c b/iterator/iter_priv.c new file mode 100644 index 00000000000..db7dbe5faa6 --- /dev/null +++ b/iterator/iter_priv.c @@ -0,0 +1,263 @@ +/* + * iterator/iter_priv.c - iterative resolver private address and domain store + * + * Copyright (c) 2008, 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions to assist the iterator module. + * Keep track of the private addresses and lookup fast. + */ + +#include "config.h" +#include +#include "iterator/iter_priv.h" +#include "util/regional.h" +#include "util/log.h" +#include "util/config_file.h" +#include "util/data/dname.h" +#include "util/data/msgparse.h" +#include "util/net_help.h" +#include "util/storage/dnstree.h" + +struct iter_priv* priv_create(void) +{ + struct iter_priv* priv = (struct iter_priv*)calloc(1, sizeof(*priv)); + if(!priv) + return NULL; + priv->region = regional_create(); + if(!priv->region) { + priv_delete(priv); + return NULL; + } + addr_tree_init(&priv->a); + name_tree_init(&priv->n); + return priv; +} + +void priv_delete(struct iter_priv* priv) +{ + if(!priv) return; + regional_destroy(priv->region); + free(priv); +} + +/** Read private-addr declarations from config */ +static int read_addrs(struct iter_priv* priv, struct config_file* cfg) +{ + /* parse addresses, report errors, insert into tree */ + struct config_strlist* p; + struct addr_tree_node* n; + struct sockaddr_storage addr; + int net; + socklen_t addrlen; + + for(p = cfg->private_address; p; p = p->next) { + log_assert(p->str); + if(!netblockstrtoaddr(p->str, UNBOUND_DNS_PORT, &addr, + &addrlen, &net)) { + log_err("cannot parse private-address: %s", p->str); + return 0; + } + n = (struct addr_tree_node*)regional_alloc(priv->region, + sizeof(*n)); + if(!n) { + log_err("out of memory"); + return 0; + } + if(!addr_tree_insert(&priv->a, n, &addr, addrlen, net)) { + verbose(VERB_QUERY, "ignoring duplicate " + "private-address: %s", p->str); + } + } + return 1; +} + +/** Read private-domain declarations from config */ +static int read_names(struct iter_priv* priv, struct config_file* cfg) +{ + /* parse names, report errors, insert into tree */ + struct config_strlist* p; + struct name_tree_node* n; + uint8_t* nm; + size_t nm_len; + int nm_labs; + ldns_rdf* rdf; + + for(p = cfg->private_domain; p; p = p->next) { + log_assert(p->str); + rdf = ldns_dname_new_frm_str(p->str); + if(!rdf) { + log_err("cannot parse private-domain: %s", p->str); + return 0; + } + nm = ldns_rdf_data(rdf); + nm_labs = dname_count_size_labels(nm, &nm_len); + nm = (uint8_t*)regional_alloc_init(priv->region, nm, nm_len); + ldns_rdf_deep_free(rdf); + if(!nm) { + log_err("out of memory"); + return 0; + } + n = (struct name_tree_node*)regional_alloc(priv->region, + sizeof(*n)); + if(!n) { + log_err("out of memory"); + return 0; + } + if(!name_tree_insert(&priv->n, n, nm, nm_len, nm_labs, + LDNS_RR_CLASS_IN)) { + verbose(VERB_QUERY, "ignoring duplicate " + "private-domain: %s", p->str); + } + } + return 1; +} + +int priv_apply_cfg(struct iter_priv* priv, struct config_file* cfg) +{ + /* empty the current contents */ + regional_free_all(priv->region); + addr_tree_init(&priv->a); + name_tree_init(&priv->n); + + /* read new contents */ + if(!read_addrs(priv, cfg)) + return 0; + if(!read_names(priv, cfg)) + return 0; + + /* prepare for lookups */ + addr_tree_init_parents(&priv->a); + name_tree_init_parents(&priv->n); + return 1; +} + +/** + * See if an address is blocked. + * @param priv: structure for address storage. + * @param addr: address to check + * @param addrlen: length of addr. + * @return: true if the address must not be queried. false if unlisted. + */ +static int +priv_lookup_addr(struct iter_priv* priv, struct sockaddr_storage* addr, + socklen_t addrlen) +{ + return addr_tree_lookup(&priv->a, addr, addrlen) != NULL; +} + +/** + * See if a name is whitelisted. + * @param priv: structure for address storage. + * @param pkt: the packet (for compression ptrs). + * @param name: name to check. + * @param name_len: uncompressed length of the name to check. + * @param dclass: class to check. + * @return: true if the name is OK. false if unlisted. + */ +static int +priv_lookup_name(struct iter_priv* priv, ldns_buffer* pkt, + uint8_t* name, size_t name_len, uint16_t dclass) +{ + size_t len; + uint8_t decomp[256]; + int labs; + if(name_len >= sizeof(decomp)) + return 0; + dname_pkt_copy(pkt, decomp, name); + labs = dname_count_size_labels(decomp, &len); + log_assert(name_len == len); + return name_tree_lookup(&priv->n, decomp, len, labs, dclass) != NULL; +} + +size_t priv_get_mem(struct iter_priv* priv) +{ + if(!priv) return 0; + return sizeof(*priv) + regional_get_mem(priv->region); +} + +int priv_rrset_bad(struct iter_priv* priv, ldns_buffer* pkt, + struct rrset_parse* rrset) +{ + if(priv->a.count == 0) + return 0; /* there are no blocked addresses */ + + /* see if it is a private name, that is allowed to have any */ + if(priv_lookup_name(priv, pkt, rrset->dname, rrset->dname_len, + ntohs(rrset->rrset_class))) { + return 0; + } else { + /* so its a public name, check the address */ + socklen_t len; + struct rr_parse* rr; + if(rrset->type == LDNS_RR_TYPE_A) { + struct sockaddr_storage addr; + struct sockaddr_in sa; + + len = (socklen_t)sizeof(sa); + memset(&sa, 0, len); + sa.sin_family = AF_INET; + sa.sin_port = (in_port_t)htons(UNBOUND_DNS_PORT); + for(rr = rrset->rr_first; rr; rr = rr->next) { + if(ldns_read_uint16(rr->ttl_data+4) + != INET_SIZE) + continue; + memmove(&sa.sin_addr, rr->ttl_data+4+2, + INET_SIZE); + memmove(&addr, &sa, len); + if(priv_lookup_addr(priv, &addr, len)) + return 1; + } + } else if(rrset->type == LDNS_RR_TYPE_AAAA) { + struct sockaddr_storage addr; + struct sockaddr_in6 sa; + len = (socklen_t)sizeof(sa); + memset(&sa, 0, len); + sa.sin6_family = AF_INET6; + sa.sin6_port = (in_port_t)htons(UNBOUND_DNS_PORT); + for(rr = rrset->rr_first; rr; rr = rr->next) { + if(ldns_read_uint16(rr->ttl_data+4) + != INET6_SIZE) + continue; + memmove(&sa.sin6_addr, rr->ttl_data+4+2, + INET6_SIZE); + memmove(&addr, &sa, len); + if(priv_lookup_addr(priv, &addr, len)) + return 1; + } + } + } + return 0; +} diff --git a/iterator/iter_priv.h b/iterator/iter_priv.h new file mode 100644 index 00000000000..f6264f8d0c9 --- /dev/null +++ b/iterator/iter_priv.h @@ -0,0 +1,110 @@ +/* + * iterator/iter_priv.h - iterative resolver private address and domain store + * + * Copyright (c) 2008, 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions to assist the iterator module. + * Keep track of the private addresses and lookup fast. + */ + +#ifndef ITERATOR_ITER_PRIV_H +#define ITERATOR_ITER_PRIV_H +#include "util/rbtree.h" +#include +struct iter_env; +struct config_file; +struct regional; +struct rrset_parse; + +/** + * Iterator priv structure + */ +struct iter_priv { + /** regional for allocation */ + struct regional* region; + /** + * Tree of the address spans that are blocked. + * contents of type addr_tree_node. + * No further data need, only presence or absence. + */ + rbtree_t a; + /** + * Tree of the domains spans that are allowed to contain + * the blocked address spans. + * contents of type name_tree_node. + * No further data need, only presence or absence. + */ + rbtree_t n; +}; + +/** + * Create priv structure + * @return new structure or NULL on error. + */ +struct iter_priv* priv_create(void); + +/** + * Delete priv structure. + * @param priv: to delete. + */ +void priv_delete(struct iter_priv* priv); + +/** + * Process priv config. + * @param priv: where to store. + * @param cfg: config options. + * @return 0 on error. + */ +int priv_apply_cfg(struct iter_priv* priv, struct config_file* cfg); + +/** + * See if rrset is bad. + * @param priv: structure for private address storage. + * @param pkt: packet to decompress rrset name in. + * @param rrset: the rrset to examine, A or AAAA. + * @return true if the rrset is bad and should be removed. + */ +int priv_rrset_bad(struct iter_priv* priv, ldns_buffer* pkt, + struct rrset_parse* rrset); + +/** + * Get memory used by priv structure. + * @param priv: structure for address storage. + * @return bytes in use. + */ +size_t priv_get_mem(struct iter_priv* priv); + +#endif /* ITERATOR_ITER_PRIV_H */ diff --git a/iterator/iter_resptype.c b/iterator/iter_resptype.c new file mode 100644 index 00000000000..2cdc5fcfc3d --- /dev/null +++ b/iterator/iter_resptype.c @@ -0,0 +1,286 @@ +/* + * iterator/iter_resptype.c - response type information and classification. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file defines the response type. DNS Responses can be classified as + * one of the response types. + */ +#include "config.h" +#include +#include "iterator/iter_resptype.h" +#include "iterator/iter_delegpt.h" +#include "services/cache/dns.h" +#include "util/net_help.h" +#include "util/data/dname.h" + +enum response_type +response_type_from_cache(struct dns_msg* msg, + struct query_info* request) +{ + /* If the message is NXDOMAIN, then it is an ANSWER. */ + if(FLAGS_GET_RCODE(msg->rep->flags) == LDNS_RCODE_NXDOMAIN) + return RESPONSE_TYPE_ANSWER; + if(request->qtype == LDNS_RR_TYPE_ANY) + return RESPONSE_TYPE_ANSWER; + + /* First we look at the answer section. This can tell us if this is + * CNAME or positive ANSWER. */ + if(msg->rep->an_numrrsets > 0) { + /* Now look at the answer section first. 3 states: + * o our answer is there directly, + * o our answer is there after a cname, + * o or there is just a cname. */ + uint8_t* mname = request->qname; + size_t mname_len = request->qname_len; + size_t i; + for(i=0; irep->an_numrrsets; i++) { + struct ub_packed_rrset_key* s = msg->rep->rrsets[i]; + + /* If we have encountered an answer (before or + * after a CNAME), then we are done! Note that + * if qtype == CNAME then this will be noted as + * an ANSWER before it gets treated as a CNAME, + * as it should */ + if(ntohs(s->rk.type) == request->qtype && + ntohs(s->rk.rrset_class) == request->qclass && + query_dname_compare(mname, s->rk.dname) == 0) { + return RESPONSE_TYPE_ANSWER; + } + + /* If we have encountered a CNAME, make sure that + * it is relevant. */ + if(ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME && + query_dname_compare(mname, s->rk.dname) == 0) { + get_cname_target(s, &mname, &mname_len); + } + } + + /* if we encountered a CNAME (or a bunch of CNAMEs), and + * still got to here, then it is a CNAME response. (i.e., + * the CNAME chain didn't terminate in an answer rrset.) */ + if(mname != request->qname) { + return RESPONSE_TYPE_CNAME; + } + } + + /* At this point, since we don't need to detect REFERRAL or LAME + * messages, it can only be an ANSWER. */ + return RESPONSE_TYPE_ANSWER; +} + +enum response_type +response_type_from_server(int rdset, + struct dns_msg* msg, struct query_info* request, struct delegpt* dp) +{ + uint8_t* origzone = (uint8_t*)"\000"; /* the default */ + struct ub_packed_rrset_key* s; + size_t i; + + if(!msg || !request) + return RESPONSE_TYPE_THROWAWAY; + + /* If the message is NXDOMAIN, then it answers the question. */ + if(FLAGS_GET_RCODE(msg->rep->flags) == LDNS_RCODE_NXDOMAIN) { + /* make sure its not recursive when we don't want it to */ + if( (msg->rep->flags&BIT_RA) && + !(msg->rep->flags&BIT_AA) && !rdset) + return RESPONSE_TYPE_REC_LAME; + /* it could be a CNAME with NXDOMAIN rcode */ + for(i=0; irep->an_numrrsets; i++) { + s = msg->rep->rrsets[i]; + if(ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME && + query_dname_compare(request->qname, + s->rk.dname) == 0) { + return RESPONSE_TYPE_CNAME; + } + } + return RESPONSE_TYPE_ANSWER; + } + + /* Other response codes mean (so far) to throw the response away as + * meaningless and move on to the next nameserver. */ + if(FLAGS_GET_RCODE(msg->rep->flags) != LDNS_RCODE_NOERROR) + return RESPONSE_TYPE_THROWAWAY; + + /* Note: TC bit has already been handled */ + + if(dp) { + origzone = dp->name; + } + + /* First we look at the answer section. This can tell us if this is a + * CNAME or ANSWER or (provisional) ANSWER. */ + if(msg->rep->an_numrrsets > 0) { + uint8_t* mname = request->qname; + size_t mname_len = request->qname_len; + + /* Now look at the answer section first. 3 states: our + * answer is there directly, our answer is there after + * a cname, or there is just a cname. */ + for(i=0; irep->an_numrrsets; i++) { + s = msg->rep->rrsets[i]; + + /* if the answer section has NS rrset, and qtype ANY + * and the delegation is lower, and no CNAMEs followed, + * this is a referral where the NS went to AN section */ + if((request->qtype == LDNS_RR_TYPE_ANY || + request->qtype == LDNS_RR_TYPE_NS) && + ntohs(s->rk.type) == LDNS_RR_TYPE_NS && + ntohs(s->rk.rrset_class) == request->qclass && + dname_strict_subdomain_c(s->rk.dname, + origzone)) { + if((msg->rep->flags&BIT_AA)) + return RESPONSE_TYPE_ANSWER; + return RESPONSE_TYPE_REFERRAL; + } + + /* If we have encountered an answer (before or + * after a CNAME), then we are done! Note that + * if qtype == CNAME then this will be noted as an + * ANSWER before it gets treated as a CNAME, as + * it should. */ + if(ntohs(s->rk.type) == request->qtype && + ntohs(s->rk.rrset_class) == request->qclass && + query_dname_compare(mname, s->rk.dname) == 0) { + if((msg->rep->flags&BIT_AA)) + return RESPONSE_TYPE_ANSWER; + /* If the AA bit isn't on, and we've seen + * the answer, we only provisionally say + * 'ANSWER' -- it very well could be a + * REFERRAL. */ + break; + } + + /* If we have encountered a CNAME, make sure that + * it is relevant. */ + if(ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME && + query_dname_compare(mname, s->rk.dname) == 0) { + get_cname_target(s, &mname, &mname_len); + } + } + /* not a referral, and qtype any, thus an answer */ + if(request->qtype == LDNS_RR_TYPE_ANY) + return RESPONSE_TYPE_ANSWER; + /* if we encountered a CNAME (or a bunch of CNAMEs), and + * still got to here, then it is a CNAME response. + * (This is regardless of the AA bit at this point) */ + if(mname != request->qname) { + return RESPONSE_TYPE_CNAME; + } + } + + /* Looking at the authority section, we just look and see if + * there is a SOA record, that means a NOERROR/NODATA */ + for(i = msg->rep->an_numrrsets; i < (msg->rep->an_numrrsets + + msg->rep->ns_numrrsets); i++) { + s = msg->rep->rrsets[i]; + + /* The normal way of detecting NOERROR/NODATA. */ + if(ntohs(s->rk.type) == LDNS_RR_TYPE_SOA && + dname_subdomain_c(request->qname, s->rk.dname)) { + /* we do our own recursion, thank you */ + if( (msg->rep->flags&BIT_RA) && + !(msg->rep->flags&BIT_AA) && !rdset) + return RESPONSE_TYPE_REC_LAME; + return RESPONSE_TYPE_ANSWER; + } + } + /* Looking at the authority section, we just look and see if + * there is a delegation NS set, turning it into a delegation. + * Otherwise, we will have to conclude ANSWER (either it is + * NOERROR/NODATA, or an non-authoritative answer). */ + for(i = msg->rep->an_numrrsets; i < (msg->rep->an_numrrsets + + msg->rep->ns_numrrsets); i++) { + s = msg->rep->rrsets[i]; + + /* Detect REFERRAL/LAME/ANSWER based on the relationship + * of the NS set to the originating zone name. */ + if(ntohs(s->rk.type) == LDNS_RR_TYPE_NS) { + /* If we are getting an NS set for the zone we + * thought we were contacting, then it is an answer.*/ + if(query_dname_compare(s->rk.dname, origzone) == 0) { + /* see if mistakenly a recursive server was + * deployed and is responding nonAA */ + if( (msg->rep->flags&BIT_RA) && + !(msg->rep->flags&BIT_AA) && !rdset) + return RESPONSE_TYPE_REC_LAME; + /* Or if a lame server is deployed, + * which gives ns==zone delegation from cache + * without AA bit as well, with nodata nosoa*/ + /* real answer must be +AA and SOA RFC(2308), + * so this is wrong, and we SERVFAIL it if + * this is the only possible reply, if it + * is misdeployed the THROWAWAY makes us pick + * the next server from the selection */ + if(msg->rep->an_numrrsets==0 && + !(msg->rep->flags&BIT_AA) && !rdset) + return RESPONSE_TYPE_THROWAWAY; + return RESPONSE_TYPE_ANSWER; + } + /* If we are getting a referral upwards (or to + * the same zone), then the server is 'lame'. */ + if(dname_subdomain_c(origzone, s->rk.dname)) { + if(rdset) /* forward or reclame not LAME */ + return RESPONSE_TYPE_THROWAWAY; + return RESPONSE_TYPE_LAME; + } + /* If the NS set is below the delegation point we + * are on, and it is non-authoritative, then it is + * a referral, otherwise it is an answer. */ + if(dname_subdomain_c(s->rk.dname, origzone)) { + /* NOTE: I no longer remember in what case + * we would like this to be an answer. + * NODATA should have a SOA or nothing, + * not an NS rrset. + * True, referrals should not have the AA + * bit set, but... */ + + /* if((msg->rep->flags&BIT_AA)) + return RESPONSE_TYPE_ANSWER; */ + return RESPONSE_TYPE_REFERRAL; + } + /* Otherwise, the NS set is irrelevant. */ + } + } + + /* If we've gotten this far, this is NOERROR/NODATA (which could + * be an entirely empty message) */ + /* check if recursive answer; saying it has empty cache */ + if( (msg->rep->flags&BIT_RA) && !(msg->rep->flags&BIT_AA) && !rdset) + return RESPONSE_TYPE_REC_LAME; + return RESPONSE_TYPE_ANSWER; +} diff --git a/iterator/iter_resptype.h b/iterator/iter_resptype.h new file mode 100644 index 00000000000..3bb3eedb2ef --- /dev/null +++ b/iterator/iter_resptype.h @@ -0,0 +1,127 @@ +/* + * iterator/iter_resptype.h - response type information and classification. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file defines the response type. DNS Responses can be classified as + * one of the response types. + */ + +#ifndef ITERATOR_ITER_RESPTYPE_H +#define ITERATOR_ITER_RESPTYPE_H +struct dns_msg; +struct query_info; +struct delegpt; + +/** + * The response type is used to interpret the response. + */ +enum response_type { + /** + * 'untyped' means that the type of this response hasn't been + * assigned. + */ + RESPONSE_TYPE_UNTYPED = 0, + + /** + * 'answer' means that the response terminates the resolution + * process. + */ + RESPONSE_TYPE_ANSWER, + + /** 'delegation' means that the response is a delegation. */ + RESPONSE_TYPE_REFERRAL, + + /** + * 'cname' means that the response is a cname without the final + * answer, and thus must be restarted. + */ + RESPONSE_TYPE_CNAME, + + /** + * 'throwaway' means that this particular response should be + * discarded and the next nameserver should be contacted + */ + RESPONSE_TYPE_THROWAWAY, + + /** + * 'lame' means that this particular response indicates that + * the nameserver knew nothing about the question. + */ + RESPONSE_TYPE_LAME, + + /** + * Recursion lame means that the nameserver is some sort of + * open recursor, and not authoritative for the question. + * It may know something, but not authoritatively. + */ + RESPONSE_TYPE_REC_LAME +}; + +/** + * Classifies a response message from cache based on the current request. + * Note that this routine assumes that THROWAWAY or LAME responses will not + * occur. Also, it will not detect REFERRAL type messages, since those are + * (currently) automatically classified based on how they came from the + * cache (findDelegation() instead of lookup()). + * + * @param msg: the message from the cache. + * @param request: the request that generated the response. + * @return the response type (CNAME or ANSWER). + */ +enum response_type response_type_from_cache(struct dns_msg* msg, + struct query_info* request); + +/** + * Classifies a response message (from the wire) based on the current + * request. + * + * NOTE: currently this routine uses the AA bit in the response to help + * distinguish between some non-standard referrals and answers. It also + * relies somewhat on the originating zone to be accurate (for lameness + * detection, mostly). + * + * @param rdset: if RD bit was sent in query sent by unbound. + * @param msg: the message from the cache. + * @param request: the request that generated the response. + * @param dp: The delegation point that was being queried + * when the response was returned. + * @return the response type (CNAME or ANSWER). + */ +enum response_type response_type_from_server(int rdset, + struct dns_msg* msg, struct query_info* request, struct delegpt* dp); + +#endif /* ITERATOR_ITER_RESPTYPE_H */ diff --git a/iterator/iter_scrub.c b/iterator/iter_scrub.c new file mode 100644 index 00000000000..6147c96a9e3 --- /dev/null +++ b/iterator/iter_scrub.c @@ -0,0 +1,751 @@ +/* + * iterator/iter_scrub.c - scrubbing, normalization, sanitization of DNS msgs. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file has routine(s) for cleaning up incoming DNS messages from + * possible useless or malicious junk in it. + */ +#include "config.h" +#include "iterator/iter_scrub.h" +#include "iterator/iterator.h" +#include "iterator/iter_priv.h" +#include "services/cache/rrset.h" +#include "util/log.h" +#include "util/net_help.h" +#include "util/regional.h" +#include "util/config_file.h" +#include "util/module.h" +#include "util/data/msgparse.h" +#include "util/data/dname.h" +#include "util/data/msgreply.h" +#include "util/alloc.h" + +/** RRset flag used during scrubbing. The RRset is OK. */ +#define RRSET_SCRUB_OK 0x80 + +/** remove rrset, update loop variables */ +static void +remove_rrset(const char* str, ldns_buffer* pkt, struct msg_parse* msg, + struct rrset_parse* prev, struct rrset_parse** rrset) +{ + if(verbosity >= VERB_QUERY + && (*rrset)->dname_len <= LDNS_MAX_DOMAINLEN) { + uint8_t buf[LDNS_MAX_DOMAINLEN+1]; + dname_pkt_copy(pkt, buf, (*rrset)->dname); + log_nametypeclass(VERB_QUERY, str, buf, + (*rrset)->type, ntohs((*rrset)->rrset_class)); + } + if(prev) + prev->rrset_all_next = (*rrset)->rrset_all_next; + else msg->rrset_first = (*rrset)->rrset_all_next; + if(msg->rrset_last == *rrset) + msg->rrset_last = prev; + msg->rrset_count --; + switch((*rrset)->section) { + case LDNS_SECTION_ANSWER: msg->an_rrsets--; break; + case LDNS_SECTION_AUTHORITY: msg->ns_rrsets--; break; + case LDNS_SECTION_ADDITIONAL: msg->ar_rrsets--; break; + default: log_assert(0); + } + msgparse_bucket_remove(msg, *rrset); + *rrset = (*rrset)->rrset_all_next; +} + +/** return true if rr type has additional names in it */ +static int +has_additional(uint16_t t) +{ + switch(t) { + case LDNS_RR_TYPE_MB: + case LDNS_RR_TYPE_MD: + case LDNS_RR_TYPE_MF: + case LDNS_RR_TYPE_NS: + case LDNS_RR_TYPE_MX: + case LDNS_RR_TYPE_KX: + case LDNS_RR_TYPE_SRV: + return 1; + case LDNS_RR_TYPE_NAPTR: + /* TODO: NAPTR not supported, glue stripped off */ + return 0; + } + return 0; +} + +/** get additional name from rrset RR, return false if no name present */ +static int +get_additional_name(struct rrset_parse* rrset, struct rr_parse* rr, + uint8_t** nm, size_t* nmlen, ldns_buffer* pkt) +{ + size_t offset = 0; + size_t len, oldpos; + switch(rrset->type) { + case LDNS_RR_TYPE_MB: + case LDNS_RR_TYPE_MD: + case LDNS_RR_TYPE_MF: + case LDNS_RR_TYPE_NS: + offset = 0; + break; + case LDNS_RR_TYPE_MX: + case LDNS_RR_TYPE_KX: + offset = 2; + break; + case LDNS_RR_TYPE_SRV: + offset = 6; + break; + case LDNS_RR_TYPE_NAPTR: + /* TODO: NAPTR not supported, glue stripped off */ + return 0; + default: + return 0; + } + len = ldns_read_uint16(rr->ttl_data+sizeof(uint32_t)); + if(len < offset+1) + return 0; /* rdata field too small */ + *nm = rr->ttl_data+sizeof(uint32_t)+sizeof(uint16_t)+offset; + oldpos = ldns_buffer_position(pkt); + ldns_buffer_set_position(pkt, (size_t)(*nm - ldns_buffer_begin(pkt))); + *nmlen = pkt_dname_len(pkt); + ldns_buffer_set_position(pkt, oldpos); + if(*nmlen == 0) + return 0; + return 1; +} + +/** Place mark on rrsets in additional section they are OK */ +static void +mark_additional_rrset(ldns_buffer* pkt, struct msg_parse* msg, + struct rrset_parse* rrset) +{ + /* Mark A and AAAA for NS as appropriate additional section info. */ + uint8_t* nm = NULL; + size_t nmlen = 0; + struct rr_parse* rr; + + if(!has_additional(rrset->type)) + return; + for(rr = rrset->rr_first; rr; rr = rr->next) { + if(get_additional_name(rrset, rr, &nm, &nmlen, pkt)) { + /* mark A */ + hashvalue_t h = pkt_hash_rrset(pkt, nm, LDNS_RR_TYPE_A, + rrset->rrset_class, 0); + struct rrset_parse* r = msgparse_hashtable_lookup( + msg, pkt, h, 0, nm, nmlen, + LDNS_RR_TYPE_A, rrset->rrset_class); + if(r && r->section == LDNS_SECTION_ADDITIONAL) { + r->flags |= RRSET_SCRUB_OK; + } + + /* mark AAAA */ + h = pkt_hash_rrset(pkt, nm, LDNS_RR_TYPE_AAAA, + rrset->rrset_class, 0); + r = msgparse_hashtable_lookup(msg, pkt, h, 0, nm, + nmlen, LDNS_RR_TYPE_AAAA, rrset->rrset_class); + if(r && r->section == LDNS_SECTION_ADDITIONAL) { + r->flags |= RRSET_SCRUB_OK; + } + } + } +} + +/** Get target name of a CNAME */ +static int +parse_get_cname_target(struct rrset_parse* rrset, uint8_t** sname, + size_t* snamelen) +{ + if(rrset->rr_count != 1) { + struct rr_parse* sig; + verbose(VERB_ALGO, "Found CNAME rrset with " + "size > 1: %u", (unsigned)rrset->rr_count); + /* use the first CNAME! */ + rrset->rr_count = 1; + rrset->size = rrset->rr_first->size; + for(sig=rrset->rrsig_first; sig; sig=sig->next) + rrset->size += sig->size; + rrset->rr_last = rrset->rr_first; + rrset->rr_first->next = NULL; + } + if(rrset->rr_first->size < sizeof(uint16_t)+1) + return 0; /* CNAME rdata too small */ + *sname = rrset->rr_first->ttl_data + sizeof(uint32_t) + + sizeof(uint16_t); /* skip ttl, rdatalen */ + *snamelen = rrset->rr_first->size - sizeof(uint16_t); + return 1; +} + +/** Synthesize CNAME from DNAME, false if too long */ +static int +synth_cname(uint8_t* qname, size_t qnamelen, struct rrset_parse* dname_rrset, + uint8_t* alias, size_t* aliaslen, ldns_buffer* pkt) +{ + /* we already know that sname is a strict subdomain of DNAME owner */ + uint8_t* dtarg = NULL; + size_t dtarglen; + if(!parse_get_cname_target(dname_rrset, &dtarg, &dtarglen)) + return 0; + log_assert(qnamelen > dname_rrset->dname_len); + /* DNAME from com. to net. with qname example.com. -> example.net. */ + /* so: \3com\0 to \3net\0 and qname \7example\3com\0 */ + *aliaslen = qnamelen + dtarglen - dname_rrset->dname_len; + if(*aliaslen > LDNS_MAX_DOMAINLEN) + return 0; /* should have been RCODE YXDOMAIN */ + /* decompress dnames into buffer, we know it fits */ + dname_pkt_copy(pkt, alias, qname); + dname_pkt_copy(pkt, alias+(qnamelen-dname_rrset->dname_len), dtarg); + return 1; +} + +/** synthesize a CNAME rrset */ +static struct rrset_parse* +synth_cname_rrset(uint8_t** sname, size_t* snamelen, uint8_t* alias, + size_t aliaslen, struct regional* region, struct msg_parse* msg, + struct rrset_parse* rrset, struct rrset_parse* prev, + struct rrset_parse* nx, ldns_buffer* pkt) +{ + struct rrset_parse* cn = (struct rrset_parse*)regional_alloc(region, + sizeof(struct rrset_parse)); + if(!cn) + return NULL; + memset(cn, 0, sizeof(*cn)); + cn->rr_first = (struct rr_parse*)regional_alloc(region, + sizeof(struct rr_parse)); + if(!cn->rr_first) + return NULL; + cn->rr_last = cn->rr_first; + /* CNAME from sname to alias */ + cn->dname = (uint8_t*)regional_alloc(region, *snamelen); + if(!cn->dname) + return NULL; + dname_pkt_copy(pkt, cn->dname, *sname); + cn->dname_len = *snamelen; + cn->type = LDNS_RR_TYPE_CNAME; + cn->section = rrset->section; + cn->rrset_class = rrset->rrset_class; + cn->rr_count = 1; + cn->size = sizeof(uint16_t) + aliaslen; + cn->hash=pkt_hash_rrset(pkt, cn->dname, cn->type, cn->rrset_class, 0); + /* allocate TTL + rdatalen + uncompressed dname */ + memset(cn->rr_first, 0, sizeof(struct rr_parse)); + cn->rr_first->outside_packet = 1; + cn->rr_first->ttl_data = (uint8_t*)regional_alloc(region, + sizeof(uint32_t)+sizeof(uint16_t)+aliaslen); + if(!cn->rr_first->ttl_data) + return NULL; + ldns_write_uint32(cn->rr_first->ttl_data, 0); /* TTL = 0 */ + ldns_write_uint16(cn->rr_first->ttl_data+4, aliaslen); + memmove(cn->rr_first->ttl_data+6, alias, aliaslen); + cn->rr_first->size = sizeof(uint16_t)+aliaslen; + + /* link it in */ + cn->rrset_all_next = nx; + if(prev) + prev->rrset_all_next = cn; + else msg->rrset_first = cn; + if(nx == NULL) + msg->rrset_last = cn; + msg->rrset_count ++; + msg->an_rrsets++; + /* it is not inserted in the msg hashtable. */ + + *sname = cn->rr_first->ttl_data + sizeof(uint32_t)+sizeof(uint16_t); + *snamelen = aliaslen; + return cn; +} + +/** check if DNAME applies to a name */ +static int +pkt_strict_sub(ldns_buffer* pkt, uint8_t* sname, uint8_t* dr) +{ + uint8_t buf1[LDNS_MAX_DOMAINLEN+1]; + uint8_t buf2[LDNS_MAX_DOMAINLEN+1]; + /* decompress names */ + dname_pkt_copy(pkt, buf1, sname); + dname_pkt_copy(pkt, buf2, dr); + return dname_strict_subdomain_c(buf1, buf2); +} + +/** check subdomain with decompression */ +static int +pkt_sub(ldns_buffer* pkt, uint8_t* comprname, uint8_t* zone) +{ + uint8_t buf[LDNS_MAX_DOMAINLEN+1]; + dname_pkt_copy(pkt, buf, comprname); + return dname_subdomain_c(buf, zone); +} + +/** check subdomain with decompression, compressed is parent */ +static int +sub_of_pkt(ldns_buffer* pkt, uint8_t* zone, uint8_t* comprname) +{ + uint8_t buf[LDNS_MAX_DOMAINLEN+1]; + dname_pkt_copy(pkt, buf, comprname); + return dname_subdomain_c(zone, buf); +} + +/** + * This routine normalizes a response. This includes removing "irrelevant" + * records from the answer and additional sections and (re)synthesizing + * CNAMEs from DNAMEs, if present. + * + * @param pkt: packet. + * @param msg: msg to normalize. + * @param qinfo: original query. + * @param region: where to allocate synthesized CNAMEs. + * @return 0 on error. + */ +static int +scrub_normalize(ldns_buffer* pkt, struct msg_parse* msg, + struct query_info* qinfo, struct regional* region) +{ + uint8_t* sname = qinfo->qname; + size_t snamelen = qinfo->qname_len; + struct rrset_parse* rrset, *prev, *nsset=NULL; + + if(FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NOERROR && + FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NXDOMAIN) + return 1; + + /* For the ANSWER section, remove all "irrelevant" records and add + * synthesized CNAMEs from DNAMEs + * This will strip out-of-order CNAMEs as well. */ + + /* walk through the parse packet rrset list, keep track of previous + * for insert and delete ease, and examine every RRset */ + prev = NULL; + rrset = msg->rrset_first; + while(rrset && rrset->section == LDNS_SECTION_ANSWER) { + if(rrset->type == LDNS_RR_TYPE_DNAME && + pkt_strict_sub(pkt, sname, rrset->dname)) { + /* check if next rrset is correct CNAME. else, + * synthesize a CNAME */ + struct rrset_parse* nx = rrset->rrset_all_next; + uint8_t alias[LDNS_MAX_DOMAINLEN+1]; + size_t aliaslen = 0; + if(rrset->rr_count != 1) { + verbose(VERB_ALGO, "Found DNAME rrset with " + "size > 1: %u", + (unsigned)rrset->rr_count); + return 0; + } + if(!synth_cname(sname, snamelen, rrset, alias, + &aliaslen, pkt)) { + verbose(VERB_ALGO, "synthesized CNAME " + "too long"); + return 0; + } + if(nx && nx->type == LDNS_RR_TYPE_CNAME && + dname_pkt_compare(pkt, sname, nx->dname) == 0) { + /* check next cname */ + uint8_t* t = NULL; + size_t tlen = 0; + if(!parse_get_cname_target(rrset, &t, &tlen)) + return 0; + if(dname_pkt_compare(pkt, alias, t) == 0) { + /* it's OK and better capitalized */ + prev = rrset; + rrset = nx; + continue; + } + /* synth ourselves */ + } + /* synth a CNAME rrset */ + prev = synth_cname_rrset(&sname, &snamelen, alias, + aliaslen, region, msg, rrset, rrset, nx, pkt); + if(!prev) { + log_err("out of memory synthesizing CNAME"); + return 0; + } + /* FIXME: resolve the conflict between synthesized + * CNAME ttls and the cache. */ + rrset = nx; + continue; + + } + + /* The only records in the ANSWER section not allowed to */ + if(dname_pkt_compare(pkt, sname, rrset->dname) != 0) { + remove_rrset("normalize: removing irrelevant RRset:", + pkt, msg, prev, &rrset); + continue; + } + + /* Follow the CNAME chain. */ + if(rrset->type == LDNS_RR_TYPE_CNAME) { + uint8_t* oldsname = sname; + if(!parse_get_cname_target(rrset, &sname, &snamelen)) + return 0; + prev = rrset; + rrset = rrset->rrset_all_next; + /* in CNAME ANY response, can have data after CNAME */ + if(qinfo->qtype == LDNS_RR_TYPE_ANY) { + while(rrset && rrset->section == + LDNS_SECTION_ANSWER && + dname_pkt_compare(pkt, oldsname, + rrset->dname) == 0) { + prev = rrset; + rrset = rrset->rrset_all_next; + } + } + continue; + } + + /* Otherwise, make sure that the RRset matches the qtype. */ + if(qinfo->qtype != LDNS_RR_TYPE_ANY && + qinfo->qtype != rrset->type) { + remove_rrset("normalize: removing irrelevant RRset:", + pkt, msg, prev, &rrset); + continue; + } + + /* Mark the additional names from relevant rrset as OK. */ + /* only for RRsets that match the query name, other ones + * will be removed by sanitize, so no additional for them */ + if(dname_pkt_compare(pkt, qinfo->qname, rrset->dname) == 0) + mark_additional_rrset(pkt, msg, rrset); + + prev = rrset; + rrset = rrset->rrset_all_next; + } + + /* Mark additional names from AUTHORITY */ + while(rrset && rrset->section == LDNS_SECTION_AUTHORITY) { + if(rrset->type==LDNS_RR_TYPE_DNAME || + rrset->type==LDNS_RR_TYPE_CNAME || + rrset->type==LDNS_RR_TYPE_A || + rrset->type==LDNS_RR_TYPE_AAAA) { + remove_rrset("normalize: removing irrelevant " + "RRset:", pkt, msg, prev, &rrset); + continue; + } + /* only one NS set allowed in authority section */ + if(rrset->type==LDNS_RR_TYPE_NS) { + /* NS set must be pertinent to the query */ + if(!sub_of_pkt(pkt, qinfo->qname, rrset->dname)) { + remove_rrset("normalize: removing irrelevant " + "RRset:", pkt, msg, prev, &rrset); + continue; + } + if(nsset == NULL) { + nsset = rrset; + } else { + remove_rrset("normalize: removing irrelevant " + "RRset:", pkt, msg, prev, &rrset); + continue; + } + } + mark_additional_rrset(pkt, msg, rrset); + prev = rrset; + rrset = rrset->rrset_all_next; + } + + /* For each record in the additional section, remove it if it is an + * address record and not in the collection of additional names + * found in ANSWER and AUTHORITY. */ + /* These records have not been marked OK previously */ + while(rrset && rrset->section == LDNS_SECTION_ADDITIONAL) { + /* FIXME: what about other types? */ + if(rrset->type==LDNS_RR_TYPE_A || + rrset->type==LDNS_RR_TYPE_AAAA) + { + if((rrset->flags & RRSET_SCRUB_OK)) { + /* remove flag to clean up flags variable */ + rrset->flags &= ~RRSET_SCRUB_OK; + } else { + remove_rrset("normalize: removing irrelevant " + "RRset:", pkt, msg, prev, &rrset); + continue; + } + } + if(rrset->type==LDNS_RR_TYPE_DNAME || + rrset->type==LDNS_RR_TYPE_CNAME || + rrset->type==LDNS_RR_TYPE_NS) { + remove_rrset("normalize: removing irrelevant " + "RRset:", pkt, msg, prev, &rrset); + continue; + } + prev = rrset; + rrset = rrset->rrset_all_next; + } + + return 1; +} + +/** + * Store potential poison in the cache (only if hardening disabled). + * The rrset is stored in the cache but removed from the message. + * So that it will be used for infrastructure purposes, but not be + * returned to the client. + * @param pkt: packet + * @param msg: message parsed + * @param env: environment with cache + * @param rrset: to store. + */ +static void +store_rrset(ldns_buffer* pkt, struct msg_parse* msg, struct module_env* env, + struct rrset_parse* rrset) +{ + struct ub_packed_rrset_key* k; + struct packed_rrset_data* d; + struct rrset_ref ref; + uint32_t now = *env->now; + + k = alloc_special_obtain(env->alloc); + if(!k) + return; + k->entry.data = NULL; + if(!parse_copy_decompress_rrset(pkt, msg, rrset, NULL, k)) { + alloc_special_release(env->alloc, k); + return; + } + d = (struct packed_rrset_data*)k->entry.data; + packed_rrset_ttl_add(d, now); + ref.key = k; + ref.id = k->id; + /*ignore ret: it was in the cache, ref updated */ + (void)rrset_cache_update(env->rrset_cache, &ref, env->alloc, now); +} + +/** Check if there are SOA records in the authority section (negative) */ +static int +soa_in_auth(struct msg_parse* msg) +{ + struct rrset_parse* rrset; + for(rrset = msg->rrset_first; rrset; rrset = rrset->rrset_all_next) + if(rrset->type == LDNS_RR_TYPE_SOA && + rrset->section == LDNS_SECTION_AUTHORITY) + return 1; + return 0; +} + +/** + * Check if right hand name in NSEC is within zone + * @param rrset: the NSEC rrset + * @param zonename: the zone name. + * @return true if BAD. + */ +static int sanitize_nsec_is_overreach(struct rrset_parse* rrset, + uint8_t* zonename) +{ + struct rr_parse* rr; + uint8_t* rhs; + size_t len; + log_assert(rrset->type == LDNS_RR_TYPE_NSEC); + for(rr = rrset->rr_first; rr; rr = rr->next) { + rhs = rr->ttl_data+4+2; + len = ldns_read_uint16(rr->ttl_data+4); + if(!dname_valid(rhs, len)) { + /* malformed domain name in rdata */ + return 1; + } + if(!dname_subdomain_c(rhs, zonename)) { + /* overreaching */ + return 1; + } + } + /* all NSEC RRs OK */ + 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" + * RRsets have already been removed, CNAMEs are in order, etc. + * + * @param pkt: packet. + * @param msg: msg to normalize. + * @param qinfo: the question originally asked. + * @param zonename: name of server zone. + * @param env: module environment with config and cache. + * @param ie: iterator environment with private address data. + * @return 0 on error. + */ +static int +scrub_sanitize(ldns_buffer* pkt, struct msg_parse* msg, + struct query_info* qinfo, uint8_t* zonename, struct module_env* env, + struct iter_env* ie) +{ + 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; + prev = NULL; + rrset = msg->rrset_first; + + /* the first DNAME is allowed to stay. It needs checking before + * it can be used from the cache. After normalization, an initial + * DNAME will have a correctly synthesized CNAME after it. */ + if(rrset && rrset->type == LDNS_RR_TYPE_DNAME && + rrset->section == LDNS_SECTION_ANSWER && + pkt_strict_sub(pkt, qinfo->qname, rrset->dname) && + pkt_sub(pkt, rrset->dname, zonename)) { + prev = rrset; /* DNAME allowed to stay in answer section */ + rrset = rrset->rrset_all_next; + } + + /* remove all records from the answer section that are + * not the same domain name as the query domain name. + * The answer section should contain rrsets with the same name + * as the question. For DNAMEs a CNAME has been synthesized. + * Wildcards have the query name in answer section. + * ANY queries get query name in answer section. + * Remainders of CNAME chains are cut off and resolved by iterator. */ + while(rrset && rrset->section == LDNS_SECTION_ANSWER) { + if(dname_pkt_compare(pkt, qinfo->qname, rrset->dname) != 0) { + if(has_additional(rrset->type)) del_addi = 1; + remove_rrset("sanitize: removing extraneous answer " + "RRset:", pkt, msg, prev, &rrset); + continue; + } + prev = rrset; + rrset = rrset->rrset_all_next; + } + + /* 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 + * authoritative for the originating zone. It, of course, MAY + * be authoriative for any other zones, and of course, MAY + * NOT be authoritative for some subdomains of the originating + * zone. */ + prev = NULL; + rrset = msg->rrset_first; + while(rrset) { + + /* remove private addresses */ + if( (rrset->type == LDNS_RR_TYPE_A || + rrset->type == LDNS_RR_TYPE_AAAA) && + priv_rrset_bad(ie->priv, pkt, rrset)) { + + /* do not set servfail since this leads to too + * many drops of other people using rfc1918 space */ + remove_rrset("sanitize: removing public name with " + "private address", pkt, msg, prev, &rrset); + continue; + } + + /* skip DNAME records -- they will always be followed by a + * synthesized CNAME, which will be relevant. + * FIXME: should this do something differently with DNAME + * rrsets NOT in Section.ANSWER? */ + /* But since DNAME records are also subdomains of the zone, + * same check can be used */ + + if(!pkt_sub(pkt, rrset->dname, zonename)) { + if(msg->an_rrsets == 0 && + rrset->type == LDNS_RR_TYPE_NS && + rrset->section == LDNS_SECTION_AUTHORITY && + FLAGS_GET_RCODE(msg->flags) == + LDNS_RCODE_NOERROR && !soa_in_auth(msg) && + sub_of_pkt(pkt, zonename, rrset->dname)) { + /* noerror, nodata and this NS rrset is above + * the zone. This is LAME! + * Leave in the NS for lame classification. */ + /* remove everything from the additional + * (we dont want its glue that was approved + * during the normalize action) */ + del_addi = 1; + } else if(!env->cfg->harden_glue) { + /* store in cache! Since it is relevant + * (from normalize) it will be picked up + * from the cache to be used later */ + store_rrset(pkt, msg, env, rrset); + remove_rrset("sanitize: storing potential " + "poison RRset:", pkt, msg, prev, &rrset); + continue; + } else { + if(has_additional(rrset->type)) del_addi = 1; + remove_rrset("sanitize: removing potential " + "poison RRset:", pkt, msg, prev, &rrset); + continue; + } + } + if(del_addi && rrset->section == LDNS_SECTION_ADDITIONAL) { + remove_rrset("sanitize: removing potential " + "poison reference RRset:", pkt, msg, prev, &rrset); + continue; + } + /* check if right hand side of NSEC is within zone */ + if(rrset->type == LDNS_RR_TYPE_NSEC && + sanitize_nsec_is_overreach(rrset, zonename)) { + remove_rrset("sanitize: removing overreaching NSEC " + "RRset:", pkt, msg, prev, &rrset); + continue; + } + prev = rrset; + rrset = rrset->rrset_all_next; + } + return 1; +} + +int +scrub_message(ldns_buffer* pkt, struct msg_parse* msg, + struct query_info* qinfo, uint8_t* zonename, struct regional* region, + struct module_env* env, struct iter_env* ie) +{ + /* basic sanity checks */ + log_nametypeclass(VERB_ALGO, "scrub for", zonename, LDNS_RR_TYPE_NS, + qinfo->qclass); + if(msg->qdcount > 1) + return 0; + if( !(msg->flags&BIT_QR) ) + return 0; + msg->flags &= ~(BIT_AD|BIT_Z); /* force off bit AD and Z */ + + /* make sure that a query is echoed back when NOERROR or NXDOMAIN */ + /* this is not required for basic operation but is a forgery + * resistance (security) feature */ + if((FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NOERROR || + FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NXDOMAIN) && + msg->qdcount == 0) + return 0; + + /* if a query is echoed back, make sure it is correct. Otherwise, + * this may be not a reply to our query. */ + if(msg->qdcount == 1) { + if(dname_pkt_compare(pkt, msg->qname, qinfo->qname) != 0) + return 0; + if(msg->qtype != qinfo->qtype || msg->qclass != qinfo->qclass) + return 0; + } + + /* normalize the response, this cleans up the additional. */ + if(!scrub_normalize(pkt, msg, qinfo, region)) + return 0; + /* delete all out-of-zone information */ + if(!scrub_sanitize(pkt, msg, qinfo, zonename, env, ie)) + return 0; + return 1; +} diff --git a/iterator/iter_scrub.h b/iterator/iter_scrub.h new file mode 100644 index 00000000000..6b7274e4ac3 --- /dev/null +++ b/iterator/iter_scrub.h @@ -0,0 +1,69 @@ +/* + * iterator/iter_scrub.h - scrubbing, normalization, sanitization of DNS msgs. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file has routine(s) for cleaning up incoming DNS messages from + * possible useless or malicious junk in it. + */ + +#ifndef ITERATOR_ITER_SCRUB_H +#define ITERATOR_ITER_SCRUB_H +#include +struct msg_parse; +struct query_info; +struct regional; +struct module_env; +struct iter_env; + +/** + * Cleanup the passed dns message. + * @param pkt: the packet itself, for resolving name compression pointers. + * the packet buffer is unaltered. + * @param msg: the parsed packet, this structure is cleaned up. + * @param qinfo: the query info that was sent to the server. Checked. + * @param zonename: the name of the last delegation point. + * Used to determine out of bailiwick information. + * @param regional: where to allocate (new) parts of the message. + * @param env: module environment with config settings and cache. + * @param ie: iterator module environment data. + * @return: false if the message is total waste. true if scrubbed with success. + */ +int scrub_message(ldns_buffer* pkt, struct msg_parse* msg, + struct query_info* qinfo, uint8_t* zonename, struct regional* regional, + struct module_env* env, struct iter_env* ie); + +#endif /* ITERATOR_ITER_SCRUB_H */ diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c new file mode 100644 index 00000000000..c7a3f4f5295 --- /dev/null +++ b/iterator/iter_utils.c @@ -0,0 +1,1034 @@ +/* + * iterator/iter_utils.c - iterative resolver module utility 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions to assist the iterator module. + * Configuration options. Forward zones. + */ +#include "config.h" +#include "iterator/iter_utils.h" +#include "iterator/iterator.h" +#include "iterator/iter_hints.h" +#include "iterator/iter_fwd.h" +#include "iterator/iter_donotq.h" +#include "iterator/iter_delegpt.h" +#include "iterator/iter_priv.h" +#include "services/cache/infra.h" +#include "services/cache/dns.h" +#include "services/cache/rrset.h" +#include "util/net_help.h" +#include "util/module.h" +#include "util/log.h" +#include "util/config_file.h" +#include "util/regional.h" +#include "util/data/msgparse.h" +#include "util/data/dname.h" +#include "util/random.h" +#include "util/fptr_wlist.h" +#include "validator/val_anchor.h" +#include "validator/val_kcache.h" +#include "validator/val_kentry.h" +#include "validator/val_utils.h" + +/** time when nameserver glue is said to be 'recent' */ +#define SUSPICION_RECENT_EXPIRY 86400 +/** penalty to validation failed blacklisted IPs */ +#define BLACKLIST_PENALTY (USEFUL_SERVER_TOP_TIMEOUT*4) + +/** fillup fetch policy array */ +static void +fetch_fill(struct iter_env* ie, const char* str) +{ + char* s = (char*)str, *e; + int i; + for(i=0; imax_dependency_depth+1; i++) { + ie->target_fetch_policy[i] = strtol(s, &e, 10); + if(s == e) + fatal_exit("cannot parse fetch policy number %s", s); + s = e; + } +} + +/** Read config string that represents the target fetch policy */ +static int +read_fetch_policy(struct iter_env* ie, const char* str) +{ + int count = cfg_count_numbers(str); + if(count < 1) { + log_err("Cannot parse target fetch policy: \"%s\"", str); + return 0; + } + ie->max_dependency_depth = count - 1; + ie->target_fetch_policy = (int*)calloc( + (size_t)ie->max_dependency_depth+1, sizeof(int)); + if(!ie->target_fetch_policy) { + log_err("alloc fetch policy: out of memory"); + return 0; + } + fetch_fill(ie, str); + return 1; +} + +int +iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg) +{ + int i; + /* target fetch policy */ + if(!read_fetch_policy(iter_env, cfg->target_fetch_policy)) + return 0; + for(i=0; imax_dependency_depth+1; i++) + verbose(VERB_QUERY, "target fetch policy for level %d is %d", + i, iter_env->target_fetch_policy[i]); + + if(!iter_env->donotq) + iter_env->donotq = donotq_create(); + if(!iter_env->donotq || !donotq_apply_cfg(iter_env->donotq, cfg)) { + log_err("Could not set donotqueryaddresses"); + return 0; + } + if(!iter_env->priv) + iter_env->priv = priv_create(); + if(!iter_env->priv || !priv_apply_cfg(iter_env->priv, cfg)) { + log_err("Could not set private addresses"); + return 0; + } + iter_env->supports_ipv6 = cfg->do_ip6; + iter_env->supports_ipv4 = cfg->do_ip4; + return 1; +} + +/** filter out unsuitable targets + * @param iter_env: iterator environment with ipv6-support flag. + * @param env: module environment with infra cache. + * @param name: zone name + * @param namelen: length of name + * @param qtype: query type (host order). + * @param now: current time + * @param a: address in delegation point we are examining. + * @return an integer that signals the target suitability. + * as follows: + * -1: The address should be omitted from the list. + * Because: + * o The address is bogus (DNSSEC validation failure). + * o Listed as donotquery + * o is ipv6 but no ipv6 support (in operating system). + * o is ipv4 but no ipv4 support (in operating system). + * o is lame + * Otherwise, an rtt in milliseconds. + * 0 .. USEFUL_SERVER_TOP_TIMEOUT-1 + * The roundtrip time timeout estimate. less than 2 minutes. + * Note that util/rtt.c has a MIN_TIMEOUT of 50 msec, thus + * values 0 .. 49 are not used, unless that is changed. + * USEFUL_SERVER_TOP_TIMEOUT + * This value exactly is given for unresponsive blacklisted. + * USEFUL_SERVER_TOP_TIMEOUT+1 + * For non-blacklisted servers: huge timeout, but has traffic. + * USEFUL_SERVER_TOP_TIMEOUT*1 .. + * parent-side lame servers get this penalty. A dispreferential + * server. (lame in delegpt). + * USEFUL_SERVER_TOP_TIMEOUT*2 .. + * dnsseclame servers get penalty + * USEFUL_SERVER_TOP_TIMEOUT*3 .. + * recursion lame servers get penalty + * UNKNOWN_SERVER_NICENESS + * If no information is known about the server, this is + * returned. 376 msec or so. + * +BLACKLIST_PENALTY (of USEFUL_TOP_TIMEOUT*4) for dnssec failed IPs. + * + * When a final value is chosen that is dnsseclame ; dnsseclameness checking + * is turned off (so we do not discard the reply). + * When a final value is chosen that is recursionlame; RD bit is set on query. + * Because of the numbers this means recursionlame also have dnssec lameness + * checking turned off. + */ +static int +iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env, + uint8_t* name, size_t namelen, uint16_t qtype, uint32_t now, + struct delegpt_addr* a) +{ + int rtt, lame, reclame, dnsseclame; + if(a->bogus) + return -1; /* address of server is bogus */ + if(donotq_lookup(iter_env->donotq, &a->addr, a->addrlen)) { + log_addr(VERB_ALGO, "skip addr on the donotquery list", + &a->addr, a->addrlen); + return -1; /* server is on the donotquery list */ + } + if(!iter_env->supports_ipv6 && addr_is_ip6(&a->addr, a->addrlen)) { + return -1; /* there is no ip6 available */ + } + if(!iter_env->supports_ipv4 && !addr_is_ip6(&a->addr, a->addrlen)) { + return -1; /* there is no ip4 available */ + } + /* check lameness - need zone , class info */ + if(infra_get_lame_rtt(env->infra_cache, &a->addr, a->addrlen, + name, namelen, qtype, &lame, &dnsseclame, &reclame, + &rtt, now)) { + log_addr(VERB_ALGO, "servselect", &a->addr, a->addrlen); + verbose(VERB_ALGO, " rtt=%d%s%s%s%s", rtt, + lame?" LAME":"", + dnsseclame?" DNSSEC_LAME":"", + reclame?" REC_LAME":"", + a->lame?" ADDR_LAME":""); + if(lame) + return -1; /* server is lame */ + else if(rtt >= USEFUL_SERVER_TOP_TIMEOUT) + /* server is unresponsive, + * we used to return TOP_TIMOUT, but fairly useless, + * because if == TOP_TIMEOUT is dropped because + * blacklisted later, instead, remove it here, so + * other choices (that are not blacklisted) can be + * tried */ + return -1; + /* select remainder from worst to best */ + else if(reclame) + return rtt+USEFUL_SERVER_TOP_TIMEOUT*3; /* nonpref */ + else if(dnsseclame ) + return rtt+USEFUL_SERVER_TOP_TIMEOUT*2; /* nonpref */ + else if(a->lame) + return rtt+USEFUL_SERVER_TOP_TIMEOUT+1; /* nonpref */ + else return rtt; + } + /* no server information present */ + if(a->lame) + return USEFUL_SERVER_TOP_TIMEOUT+1+UNKNOWN_SERVER_NICENESS; /* nonpref */ + return UNKNOWN_SERVER_NICENESS; +} + +/** lookup RTT information, and also store fastest rtt (if any) */ +static int +iter_fill_rtt(struct iter_env* iter_env, struct module_env* env, + uint8_t* name, size_t namelen, uint16_t qtype, uint32_t now, + struct delegpt* dp, int* best_rtt, struct sock_list* blacklist) +{ + int got_it = 0; + struct delegpt_addr* a; + if(dp->bogus) + return 0; /* NS bogus, all bogus, nothing found */ + for(a=dp->result_list; a; a = a->next_result) { + a->sel_rtt = iter_filter_unsuitable(iter_env, env, + name, namelen, qtype, now, a); + if(a->sel_rtt != -1) { + if(sock_list_find(blacklist, &a->addr, a->addrlen)) + a->sel_rtt += BLACKLIST_PENALTY; + + if(!got_it) { + *best_rtt = a->sel_rtt; + got_it = 1; + } else if(a->sel_rtt < *best_rtt) { + *best_rtt = a->sel_rtt; + } + } + } + return got_it; +} + +/** filter the addres list, putting best targets at front, + * returns number of best targets (or 0, no suitable targets) */ +static int +iter_filter_order(struct iter_env* iter_env, struct module_env* env, + uint8_t* name, size_t namelen, uint16_t qtype, uint32_t now, + struct delegpt* dp, int* selected_rtt, int open_target, + struct sock_list* blacklist) +{ + int got_num = 0, low_rtt = 0, swap_to_front; + struct delegpt_addr* a, *n, *prev=NULL; + + /* fillup sel_rtt and find best rtt in the bunch */ + got_num = iter_fill_rtt(iter_env, env, name, namelen, qtype, now, dp, + &low_rtt, blacklist); + if(got_num == 0) + return 0; + if(low_rtt >= USEFUL_SERVER_TOP_TIMEOUT && + (delegpt_count_missing_targets(dp) > 0 || open_target > 0)) { + verbose(VERB_ALGO, "Bad choices, trying to get more choice"); + return 0; /* we want more choice. The best choice is a bad one. + return 0 to force the caller to fetch more */ + } + + got_num = 0; + a = dp->result_list; + while(a) { + /* skip unsuitable targets */ + if(a->sel_rtt == -1) { + prev = a; + a = a->next_result; + continue; + } + /* classify the server address and determine what to do */ + swap_to_front = 0; + if(a->sel_rtt >= low_rtt && a->sel_rtt - low_rtt <= RTT_BAND) { + got_num++; + swap_to_front = 1; + } else if(a->sel_rttsel_rtt<=RTT_BAND) { + got_num++; + swap_to_front = 1; + } + /* swap to front if necessary, 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; + } + } + *selected_rtt = low_rtt; + return got_num; +} + +struct delegpt_addr* +iter_server_selection(struct iter_env* iter_env, + struct module_env* env, struct delegpt* dp, + uint8_t* name, size_t namelen, uint16_t qtype, int* dnssec_lame, + int* chase_to_rd, int open_target, struct sock_list* blacklist) +{ + int sel; + int selrtt; + struct delegpt_addr* a, *prev; + int num = iter_filter_order(iter_env, env, name, namelen, qtype, + *env->now, dp, &selrtt, open_target, blacklist); + + if(num == 0) + return NULL; + verbose(VERB_ALGO, "selrtt %d", selrtt); + if(selrtt > BLACKLIST_PENALTY) { + if(selrtt-BLACKLIST_PENALTY > USEFUL_SERVER_TOP_TIMEOUT*3) { + verbose(VERB_ALGO, "chase to " + "blacklisted recursion lame server"); + *chase_to_rd = 1; + } + if(selrtt-BLACKLIST_PENALTY > USEFUL_SERVER_TOP_TIMEOUT*2) { + verbose(VERB_ALGO, "chase to " + "blacklisted dnssec lame server"); + *dnssec_lame = 1; + } + } else { + if(selrtt > USEFUL_SERVER_TOP_TIMEOUT*3) { + verbose(VERB_ALGO, "chase to recursion lame server"); + *chase_to_rd = 1; + } + if(selrtt > USEFUL_SERVER_TOP_TIMEOUT*2) { + verbose(VERB_ALGO, "chase to dnssec lame server"); + *dnssec_lame = 1; + } + if(selrtt == USEFUL_SERVER_TOP_TIMEOUT) { + verbose(VERB_ALGO, "chase to blacklisted lame server"); + return NULL; + } + } + + if(num == 1) { + a = dp->result_list; + if(++a->attempts < OUTBOUND_MSG_RETRY) + return a; + dp->result_list = a->next_result; + return a; + } + + /* randomly select a target from the list */ + log_assert(num > 1); + /* grab secure random number, to pick unexpected server. + * also we need it to be threadsafe. */ + sel = ub_random_max(env->rnd, num); + a = dp->result_list; + prev = NULL; + while(sel > 0 && a) { + prev = a; + a = a->next_result; + sel--; + } + if(!a) /* robustness */ + return NULL; + if(++a->attempts < OUTBOUND_MSG_RETRY) + return a; + /* remove it from the delegation point result list */ + if(prev) + prev->next_result = a->next_result; + else dp->result_list = a->next_result; + return a; +} + +struct dns_msg* +dns_alloc_msg(ldns_buffer* pkt, struct msg_parse* msg, + struct regional* region) +{ + struct dns_msg* m = (struct dns_msg*)regional_alloc(region, + sizeof(struct dns_msg)); + if(!m) + return NULL; + memset(m, 0, sizeof(*m)); + if(!parse_create_msg(pkt, msg, NULL, &m->qinfo, &m->rep, region)) { + log_err("malloc failure: allocating incoming dns_msg"); + return NULL; + } + return m; +} + +struct dns_msg* +dns_copy_msg(struct dns_msg* from, struct regional* region) +{ + struct dns_msg* m = (struct dns_msg*)regional_alloc(region, + sizeof(struct dns_msg)); + if(!m) + return NULL; + m->qinfo = from->qinfo; + if(!(m->qinfo.qname = regional_alloc_init(region, from->qinfo.qname, + from->qinfo.qname_len))) + return NULL; + if(!(m->rep = reply_info_copy(from->rep, NULL, region))) + return NULL; + return m; +} + +int +iter_dns_store(struct module_env* env, struct query_info* msgqinf, + struct reply_info* msgrep, int is_referral, uint32_t leeway, int pside, + struct regional* region) +{ + return dns_cache_store(env, msgqinf, msgrep, is_referral, leeway, + pside, region); +} + +int +iter_ns_probability(struct ub_randstate* rnd, int n, int m) +{ + int sel; + if(n == m) /* 100% chance */ + return 1; + /* we do not need secure random numbers here, but + * we do need it to be threadsafe, so we use this */ + sel = ub_random_max(rnd, m); + return (sel < n); +} + +/** detect dependency cycle for query and target */ +static int +causes_cycle(struct module_qstate* qstate, uint8_t* name, size_t namelen, + uint16_t t, uint16_t c) +{ + struct query_info qinf; + qinf.qname = name; + qinf.qname_len = namelen; + qinf.qtype = t; + qinf.qclass = c; + fptr_ok(fptr_whitelist_modenv_detect_cycle( + qstate->env->detect_cycle)); + return (*qstate->env->detect_cycle)(qstate, &qinf, + (uint16_t)(BIT_RD|BIT_CD), qstate->is_priming); +} + +void +iter_mark_cycle_targets(struct module_qstate* qstate, struct delegpt* dp) +{ + struct delegpt_ns* ns; + for(ns = dp->nslist; ns; ns = ns->next) { + if(ns->resolved) + continue; + /* see if this ns as target causes dependency cycle */ + if(causes_cycle(qstate, ns->name, ns->namelen, + LDNS_RR_TYPE_AAAA, qstate->qinfo.qclass) || + causes_cycle(qstate, ns->name, ns->namelen, + LDNS_RR_TYPE_A, qstate->qinfo.qclass)) { + log_nametypeclass(VERB_QUERY, "skipping target due " + "to dependency cycle (harden-glue: no may " + "fix some of the cycles)", + ns->name, LDNS_RR_TYPE_A, + qstate->qinfo.qclass); + ns->resolved = 1; + } + } +} + +void +iter_mark_pside_cycle_targets(struct module_qstate* qstate, struct delegpt* dp) +{ + struct delegpt_ns* ns; + for(ns = dp->nslist; ns; ns = ns->next) { + if(ns->done_pside4 && ns->done_pside6) + continue; + /* see if this ns as target causes dependency cycle */ + if(causes_cycle(qstate, ns->name, ns->namelen, + LDNS_RR_TYPE_A, qstate->qinfo.qclass)) { + log_nametypeclass(VERB_QUERY, "skipping target due " + "to dependency cycle", ns->name, + LDNS_RR_TYPE_A, qstate->qinfo.qclass); + ns->done_pside4 = 1; + } + if(causes_cycle(qstate, ns->name, ns->namelen, + LDNS_RR_TYPE_AAAA, qstate->qinfo.qclass)) { + log_nametypeclass(VERB_QUERY, "skipping target due " + "to dependency cycle", ns->name, + LDNS_RR_TYPE_AAAA, qstate->qinfo.qclass); + ns->done_pside6 = 1; + } + } +} + +int +iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags, + struct delegpt* dp) +{ + struct delegpt_ns* ns; + /* check: + * o RD qflag is on. + * o no addresses are provided. + * o all NS items are required glue. + * OR + * o RD qflag is on. + * o no addresses are provided. + * o the query is for one of the nameservers in dp, + * and that nameserver is a glue-name for this dp. + */ + if(!(qflags&BIT_RD)) + return 0; + /* either available or unused targets */ + if(dp->usable_list || dp->result_list) + return 0; + + /* see if query is for one of the nameservers, which is glue */ + if( (qinfo->qtype == LDNS_RR_TYPE_A || + qinfo->qtype == LDNS_RR_TYPE_AAAA) && + dname_subdomain_c(qinfo->qname, dp->name) && + delegpt_find_ns(dp, qinfo->qname, qinfo->qname_len)) + return 1; + + for(ns = dp->nslist; ns; ns = ns->next) { + if(ns->resolved) /* skip failed targets */ + continue; + if(!dname_subdomain_c(ns->name, dp->name)) + return 0; /* one address is not required glue */ + } + return 1; +} + +int +iter_indicates_dnssec(struct module_env* env, struct delegpt* dp, + struct dns_msg* msg, uint16_t dclass) +{ + struct trust_anchor* a; + /* information not available, !env->anchors can be common */ + if(!env || !env->anchors || !dp || !dp->name) + return 0; + /* a trust anchor exists with this name, RRSIGs expected */ + if((a=anchor_find(env->anchors, dp->name, dp->namelabs, dp->namelen, + dclass))) { + lock_basic_unlock(&a->lock); + return 1; + } + /* see if DS rrset was given, in AUTH section */ + if(msg && msg->rep && + reply_find_rrset_section_ns(msg->rep, dp->name, dp->namelen, + LDNS_RR_TYPE_DS, dclass)) + return 1; + /* look in key cache */ + if(env->key_cache) { + struct key_entry_key* kk = key_cache_obtain(env->key_cache, + dp->name, dp->namelen, dclass, env->scratch, *env->now); + if(kk) { + if(query_dname_compare(kk->name, dp->name) == 0) { + if(key_entry_isgood(kk) || key_entry_isbad(kk)) { + regional_free_all(env->scratch); + return 1; + } else if(key_entry_isnull(kk)) { + regional_free_all(env->scratch); + return 0; + } + } + regional_free_all(env->scratch); + } + } + return 0; +} + +int +iter_msg_has_dnssec(struct dns_msg* msg) +{ + size_t i; + if(!msg || !msg->rep) + return 0; + for(i=0; irep->an_numrrsets + msg->rep->ns_numrrsets; i++) { + if(((struct packed_rrset_data*)msg->rep->rrsets[i]-> + entry.data)->rrsig_count > 0) + return 1; + } + /* empty message has no DNSSEC info, with DNSSEC the reply is + * not empty (NSEC) */ + return 0; +} + +int iter_msg_from_zone(struct dns_msg* msg, struct delegpt* dp, + enum response_type type, uint16_t dclass) +{ + if(!msg || !dp || !msg->rep || !dp->name) + return 0; + /* SOA RRset - always from reply zone */ + if(reply_find_rrset_section_an(msg->rep, dp->name, dp->namelen, + LDNS_RR_TYPE_SOA, dclass) || + reply_find_rrset_section_ns(msg->rep, dp->name, dp->namelen, + LDNS_RR_TYPE_SOA, dclass)) + return 1; + if(type == RESPONSE_TYPE_REFERRAL) { + size_t i; + /* if it adds a single label, i.e. we expect .com, + * and referral to example.com. NS ... , then origin zone + * is .com. For a referral to sub.example.com. NS ... then + * we do not know, since example.com. may be in between. */ + for(i=0; irep->an_numrrsets+msg->rep->ns_numrrsets; + i++) { + struct ub_packed_rrset_key* s = msg->rep->rrsets[i]; + if(ntohs(s->rk.type) == LDNS_RR_TYPE_NS && + ntohs(s->rk.rrset_class) == dclass) { + int l = dname_count_labels(s->rk.dname); + if(l == dp->namelabs + 1 && + dname_strict_subdomain(s->rk.dname, + l, dp->name, dp->namelabs)) + return 1; + } + } + return 0; + } + log_assert(type==RESPONSE_TYPE_ANSWER || type==RESPONSE_TYPE_CNAME); + /* not a referral, and not lame delegation (upwards), so, + * any NS rrset must be from the zone itself */ + if(reply_find_rrset_section_an(msg->rep, dp->name, dp->namelen, + LDNS_RR_TYPE_NS, dclass) || + reply_find_rrset_section_ns(msg->rep, dp->name, dp->namelen, + LDNS_RR_TYPE_NS, dclass)) + return 1; + /* a DNSKEY set is expected at the zone apex as well */ + /* this is for 'minimal responses' for DNSKEYs */ + if(reply_find_rrset_section_an(msg->rep, dp->name, dp->namelen, + LDNS_RR_TYPE_DNSKEY, dclass)) + return 1; + return 0; +} + +/** + * check equality of two rrsets + * @param k1: rrset + * @param k2: rrset + * @return true if equal + */ +static int +rrset_equal(struct ub_packed_rrset_key* k1, struct ub_packed_rrset_key* k2) +{ + struct packed_rrset_data* d1 = (struct packed_rrset_data*) + k1->entry.data; + struct packed_rrset_data* d2 = (struct packed_rrset_data*) + k2->entry.data; + size_t i, t; + if(k1->rk.dname_len != k2->rk.dname_len || + k1->rk.flags != k2->rk.flags || + k1->rk.type != k2->rk.type || + k1->rk.rrset_class != k2->rk.rrset_class || + query_dname_compare(k1->rk.dname, k2->rk.dname) != 0) + return 0; + if(d1->ttl != d2->ttl || + d1->count != d2->count || + d1->rrsig_count != d2->rrsig_count || + d1->trust != d2->trust || + d1->security != d2->security) + return 0; + t = d1->count + d1->rrsig_count; + for(i=0; irr_len[i] != d2->rr_len[i] || + d1->rr_ttl[i] != d2->rr_ttl[i] || + memcmp(d1->rr_data[i], d2->rr_data[i], + d1->rr_len[i]) != 0) + return 0; + } + return 1; +} + +int +reply_equal(struct reply_info* p, struct reply_info* q, ldns_buffer* scratch) +{ + size_t i; + if(p->flags != q->flags || + p->qdcount != q->qdcount || + p->ttl != q->ttl || + p->prefetch_ttl != q->prefetch_ttl || + p->security != q->security || + p->an_numrrsets != q->an_numrrsets || + p->ns_numrrsets != q->ns_numrrsets || + p->ar_numrrsets != q->ar_numrrsets || + p->rrset_count != q->rrset_count) + return 0; + for(i=0; irrset_count; i++) { + if(!rrset_equal(p->rrsets[i], q->rrsets[i])) { + /* fallback procedure: try to sort and canonicalize */ + ldns_rr_list* pl, *ql; + pl = packed_rrset_to_rr_list(p->rrsets[i], scratch); + ql = packed_rrset_to_rr_list(q->rrsets[i], scratch); + if(!pl || !ql) { + ldns_rr_list_deep_free(pl); + ldns_rr_list_deep_free(ql); + return 0; + } + ldns_rr_list2canonical(pl); + ldns_rr_list2canonical(ql); + ldns_rr_list_sort(pl); + ldns_rr_list_sort(ql); + if(ldns_rr_list_compare(pl, ql) != 0) { + ldns_rr_list_deep_free(pl); + ldns_rr_list_deep_free(ql); + return 0; + } + ldns_rr_list_deep_free(pl); + ldns_rr_list_deep_free(ql); + continue; + } + } + return 1; +} + +void +iter_store_parentside_rrset(struct module_env* env, + struct ub_packed_rrset_key* rrset) +{ + struct rrset_ref ref; + rrset = packed_rrset_copy_alloc(rrset, env->alloc, *env->now); + if(!rrset) { + log_err("malloc failure in store_parentside_rrset"); + return; + } + rrset->rk.flags |= PACKED_RRSET_PARENT_SIDE; + rrset->entry.hash = rrset_key_hash(&rrset->rk); + ref.key = rrset; + ref.id = rrset->id; + /* ignore ret: if it was in the cache, ref updated */ + (void)rrset_cache_update(env->rrset_cache, &ref, env->alloc, *env->now); +} + +/** fetch NS record from reply, if any */ +static struct ub_packed_rrset_key* +reply_get_NS_rrset(struct reply_info* rep) +{ + size_t i; + for(i=0; irrset_count; i++) { + if(rep->rrsets[i]->rk.type == htons(LDNS_RR_TYPE_NS)) { + return rep->rrsets[i]; + } + } + return NULL; +} + +void +iter_store_parentside_NS(struct module_env* env, struct reply_info* rep) +{ + struct ub_packed_rrset_key* rrset = reply_get_NS_rrset(rep); + if(rrset) { + log_rrset_key(VERB_ALGO, "store parent-side NS", rrset); + iter_store_parentside_rrset(env, rrset); + } +} + +void iter_store_parentside_neg(struct module_env* env, + struct query_info* qinfo, struct reply_info* rep) +{ + /* TTL: NS from referral in iq->deleg_msg, + * or first RR from iq->response, + * or servfail5secs if !iq->response */ + uint32_t ttl = NORR_TTL; + struct ub_packed_rrset_key* neg; + struct packed_rrset_data* newd; + if(rep) { + struct ub_packed_rrset_key* rrset = reply_get_NS_rrset(rep); + if(!rrset && rep->rrset_count != 0) rrset = rep->rrsets[0]; + if(rrset) ttl = ub_packed_rrset_ttl(rrset); + } + /* create empty rrset to store */ + neg = (struct ub_packed_rrset_key*)regional_alloc(env->scratch, + sizeof(struct ub_packed_rrset_key)); + if(!neg) { + log_err("out of memory in store_parentside_neg"); + return; + } + memset(&neg->entry, 0, sizeof(neg->entry)); + neg->entry.key = neg; + neg->rk.type = htons(qinfo->qtype); + neg->rk.rrset_class = htons(qinfo->qclass); + neg->rk.flags = 0; + neg->rk.dname = regional_alloc_init(env->scratch, qinfo->qname, + qinfo->qname_len); + if(!neg->rk.dname) { + log_err("out of memory in store_parentside_neg"); + return; + } + neg->rk.dname_len = qinfo->qname_len; + neg->entry.hash = rrset_key_hash(&neg->rk); + newd = (struct packed_rrset_data*)regional_alloc_zero(env->scratch, + sizeof(struct packed_rrset_data) + sizeof(size_t) + + sizeof(uint8_t*) + sizeof(uint32_t) + sizeof(uint16_t)); + if(!newd) { + log_err("out of memory in store_parentside_neg"); + return; + } + neg->entry.data = newd; + newd->ttl = ttl; + /* entry must have one RR, otherwise not valid in cache. + * put in one RR with empty rdata: those are ignored as nameserver */ + newd->count = 1; + newd->rrsig_count = 0; + newd->trust = rrset_trust_ans_noAA; + newd->rr_len = (size_t*)((uint8_t*)newd + + sizeof(struct packed_rrset_data)); + newd->rr_len[0] = 0 /* zero len rdata */ + sizeof(uint16_t); + packed_rrset_ptr_fixup(newd); + newd->rr_ttl[0] = newd->ttl; + ldns_write_uint16(newd->rr_data[0], 0 /* zero len rdata */); + /* store it */ + log_rrset_key(VERB_ALGO, "store parent-side negative", neg); + iter_store_parentside_rrset(env, neg); +} + +int +iter_lookup_parent_NS_from_cache(struct module_env* env, struct delegpt* dp, + struct regional* region, struct query_info* qinfo) +{ + struct ub_packed_rrset_key* akey; + akey = rrset_cache_lookup(env->rrset_cache, dp->name, + dp->namelen, LDNS_RR_TYPE_NS, qinfo->qclass, + PACKED_RRSET_PARENT_SIDE, *env->now, 0); + if(akey) { + log_rrset_key(VERB_ALGO, "found parent-side NS in cache", akey); + dp->has_parent_side_NS = 1; + /* and mark the new names as lame */ + if(!delegpt_rrset_add_ns(dp, region, akey, 1)) { + lock_rw_unlock(&akey->entry.lock); + return 0; + } + lock_rw_unlock(&akey->entry.lock); + } + return 1; +} + +int iter_lookup_parent_glue_from_cache(struct module_env* env, + struct delegpt* dp, struct regional* region, struct query_info* qinfo) +{ + struct ub_packed_rrset_key* akey; + struct delegpt_ns* ns; + size_t num = delegpt_count_targets(dp); + for(ns = dp->nslist; ns; ns = ns->next) { + /* get cached parentside A */ + akey = rrset_cache_lookup(env->rrset_cache, ns->name, + ns->namelen, LDNS_RR_TYPE_A, qinfo->qclass, + PACKED_RRSET_PARENT_SIDE, *env->now, 0); + if(akey) { + log_rrset_key(VERB_ALGO, "found parent-side", akey); + ns->done_pside4 = 1; + /* a negative-cache-element has no addresses it adds */ + if(!delegpt_add_rrset_A(dp, region, akey, 1)) + log_err("malloc failure in lookup_parent_glue"); + lock_rw_unlock(&akey->entry.lock); + } + /* get cached parentside AAAA */ + akey = rrset_cache_lookup(env->rrset_cache, ns->name, + ns->namelen, LDNS_RR_TYPE_AAAA, qinfo->qclass, + PACKED_RRSET_PARENT_SIDE, *env->now, 0); + if(akey) { + log_rrset_key(VERB_ALGO, "found parent-side", akey); + ns->done_pside6 = 1; + /* a negative-cache-element has no addresses it adds */ + if(!delegpt_add_rrset_AAAA(dp, region, akey, 1)) + log_err("malloc failure in lookup_parent_glue"); + lock_rw_unlock(&akey->entry.lock); + } + } + /* see if new (but lame) addresses have become available */ + return delegpt_count_targets(dp) != num; +} + +int +iter_get_next_root(struct iter_hints* hints, struct iter_forwards* fwd, + uint16_t* c) +{ + uint16_t c1 = *c, c2 = *c; + int r1 = hints_next_root(hints, &c1); + int r2 = forwards_next_root(fwd, &c2); + if(!r1 && !r2) /* got none, end of list */ + return 0; + else if(!r1) /* got one, return that */ + *c = c2; + else if(!r2) + *c = c1; + else if(c1 < c2) /* got both take smallest */ + *c = c1; + else *c = c2; + return 1; +} + +void +iter_scrub_ds(struct dns_msg* msg, struct ub_packed_rrset_key* ns, uint8_t* z) +{ + /* Only the DS record for the delegation itself is expected. + * We allow DS for everything between the bailiwick and the + * zonecut, thus DS records must be at or above the zonecut. + * And the DS records must be below the server authority zone. + * The answer section is already scrubbed. */ + size_t i = msg->rep->an_numrrsets; + while(i < (msg->rep->an_numrrsets + msg->rep->ns_numrrsets)) { + struct ub_packed_rrset_key* s = msg->rep->rrsets[i]; + if(ntohs(s->rk.type) == LDNS_RR_TYPE_DS && + (!ns || !dname_subdomain_c(ns->rk.dname, s->rk.dname) + || query_dname_compare(z, s->rk.dname) == 0)) { + log_nametypeclass(VERB_ALGO, "removing irrelevant DS", + s->rk.dname, ntohs(s->rk.type), + ntohs(s->rk.rrset_class)); + memmove(msg->rep->rrsets+i, msg->rep->rrsets+i+1, + sizeof(struct ub_packed_rrset_key*) * + (msg->rep->rrset_count-i-1)); + msg->rep->ns_numrrsets--; + msg->rep->rrset_count--; + /* stay at same i, but new record */ + continue; + } + i++; + } +} + +void iter_dec_attempts(struct delegpt* dp, int d) +{ + struct delegpt_addr* a; + for(a=dp->target_list; a; a = a->next_target) { + if(a->attempts >= OUTBOUND_MSG_RETRY) { + /* add back to result list */ + a->next_result = dp->result_list; + dp->result_list = a; + } + if(a->attempts > d) + a->attempts -= d; + else a->attempts = 0; + } +} + +void iter_merge_retry_counts(struct delegpt* dp, struct delegpt* old) +{ + struct delegpt_addr* a, *o, *prev; + for(a=dp->target_list; a; a = a->next_target) { + o = delegpt_find_addr(old, &a->addr, a->addrlen); + if(o) { + log_addr(VERB_ALGO, "copy attempt count previous dp", + &a->addr, a->addrlen); + a->attempts = o->attempts; + } + } + prev = NULL; + a = dp->usable_list; + while(a) { + if(a->attempts >= OUTBOUND_MSG_RETRY) { + log_addr(VERB_ALGO, "remove from usable list dp", + &a->addr, a->addrlen); + /* remove from result list */ + if(prev) + prev->next_usable = a->next_usable; + else dp->usable_list = a->next_usable; + /* prev stays the same */ + a = a->next_usable; + continue; + } + prev = a; + a = a->next_usable; + } +} + +int +iter_ds_toolow(struct dns_msg* msg, struct delegpt* dp) +{ + /* if for query example.com, there is example.com SOA or a subdomain + * of example.com, then we are too low and need to fetch NS. */ + size_t i; + /* if we have a DNAME or CNAME we are probably wrong */ + /* if we have a qtype DS in the answer section, its fine */ + for(i=0; i < msg->rep->an_numrrsets; i++) { + struct ub_packed_rrset_key* s = msg->rep->rrsets[i]; + if(ntohs(s->rk.type) == LDNS_RR_TYPE_DNAME || + ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME) { + /* not the right answer, maybe too low, check the + * RRSIG signer name (if there is any) for a hint + * that it is from the dp zone anyway */ + uint8_t* sname; + size_t slen; + val_find_rrset_signer(s, &sname, &slen); + if(sname && query_dname_compare(dp->name, sname)==0) + return 0; /* it is fine, from the right dp */ + return 1; + } + if(ntohs(s->rk.type) == LDNS_RR_TYPE_DS) + return 0; /* fine, we have a DS record */ + } + for(i=msg->rep->an_numrrsets; + i < msg->rep->an_numrrsets + msg->rep->ns_numrrsets; i++) { + struct ub_packed_rrset_key* s = msg->rep->rrsets[i]; + if(ntohs(s->rk.type) == LDNS_RR_TYPE_SOA) { + if(dname_subdomain_c(s->rk.dname, msg->qinfo.qname)) + return 1; /* point is too low */ + if(query_dname_compare(s->rk.dname, dp->name)==0) + return 0; /* right dp */ + } + if(ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC || + ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC3) { + uint8_t* sname; + size_t slen; + val_find_rrset_signer(s, &sname, &slen); + if(sname && query_dname_compare(dp->name, sname)==0) + return 0; /* it is fine, from the right dp */ + return 1; + } + } + /* we do not know */ + return 1; +} + +int iter_dp_cangodown(struct query_info* qinfo, struct delegpt* dp) +{ + /* no delegation point, do not see how we can go down, + * robust check, it should really exist */ + if(!dp) return 0; + + /* see if dp equals the qname, then we cannot go down further */ + if(query_dname_compare(qinfo->qname, dp->name) == 0) + return 0; + /* if dp is one label above the name we also cannot go down further */ + if(dname_count_labels(qinfo->qname) == dp->namelabs+1) + return 0; + return 1; +} diff --git a/iterator/iter_utils.h b/iterator/iter_utils.h new file mode 100644 index 00000000000..4fb8b005c19 --- /dev/null +++ b/iterator/iter_utils.h @@ -0,0 +1,334 @@ +/* + * iterator/iter_utils.h - iterative resolver module utility 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions to assist the iterator module. + * Configuration options. Forward zones. + */ + +#ifndef ITERATOR_ITER_UTILS_H +#define ITERATOR_ITER_UTILS_H +#include "iterator/iter_resptype.h" +#include +struct iter_env; +struct iter_hints; +struct iter_forwards; +struct config_file; +struct module_env; +struct delegpt_addr; +struct delegpt; +struct regional; +struct msg_parse; +struct ub_randstate; +struct query_info; +struct reply_info; +struct module_qstate; +struct sock_list; +struct ub_packed_rrset_key; + +/** + * Process config options and set iterator module state. + * Sets default values if no config is found. + * @param iter_env: iterator module state. + * @param cfg: config options. + * @return 0 on error. + */ +int iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg); + +/** + * Select a valid, nice target to send query to. + * Sorting and removing unsuitable targets is combined. + * + * @param iter_env: iterator module global state, with ip6 enabled and + * do-not-query-addresses. + * @param env: environment with infra cache (lameness, rtt info). + * @param dp: delegation point with result list. + * @param name: zone name (for lameness check). + * @param namelen: length of name. + * @param qtype: query type that we want to send. + * @param dnssec_lame: set to 1, if a known dnssec-lame server is selected + * these are not preferred, but are used as a last resort. + * @param chase_to_rd: set to 1 if a known recursion lame server is selected + * these are not preferred, but are used as a last resort. + * @param open_target: number of currently outstanding target queries. + * If we wait for these, perhaps more server addresses become available. + * @param blacklist: the IP blacklist to use. + * @return best target or NULL if no target. + * if not null, that target is removed from the result list in the dp. + */ +struct delegpt_addr* iter_server_selection(struct iter_env* iter_env, + struct module_env* env, struct delegpt* dp, uint8_t* name, + size_t namelen, uint16_t qtype, int* dnssec_lame, + int* chase_to_rd, int open_target, struct sock_list* blacklist); + +/** + * Allocate dns_msg from parsed msg, in regional. + * @param pkt: packet. + * @param msg: parsed message (cleaned and ready for regional allocation). + * @param regional: regional to use for allocation. + * @return newly allocated dns_msg, or NULL on memory error. + */ +struct dns_msg* dns_alloc_msg(ldns_buffer* pkt, struct msg_parse* msg, + struct regional* regional); + +/** + * Copy a dns_msg to this regional. + * @param from: dns message, also in regional. + * @param regional: regional to use for allocation. + * @return newly allocated dns_msg, or NULL on memory error. + */ +struct dns_msg* dns_copy_msg(struct dns_msg* from, struct regional* regional); + +/** + * Allocate a dns_msg with malloc/alloc structure and store in dns cache. + * @param env: environment, with alloc structure and dns cache. + * @param qinf: query info, the query for which answer is stored. + * @param rep: reply in dns_msg from dns_alloc_msg for example. + * @param is_referral: If true, then the given message to be stored is a + * referral. The cache implementation may use this as a hint. + * @param leeway: prefetch TTL leeway to expire old rrsets quicker. + * @param pside: true if dp is parentside, thus message is 'fresh' and NS + * can be prefetch-updates. + * @param region: to copy modified (cache is better) rrs back to. + * @return 0 on alloc error (out of memory). + */ +int iter_dns_store(struct module_env* env, struct query_info* qinf, + struct reply_info* rep, int is_referral, uint32_t leeway, int pside, + struct regional* region); + +/** + * Select randomly with n/m probability. + * For shuffle NS records for address fetching. + * @param rnd: random table + * @param n: probability. + * @param m: divisor for probability. + * @return true with n/m probability. + */ +int iter_ns_probability(struct ub_randstate* rnd, int n, int m); + +/** + * Mark targets that result in a dependency cycle as done, so they + * will not get selected as targets. + * @param qstate: query state. + * @param dp: delegpt to mark ns in. + */ +void iter_mark_cycle_targets(struct module_qstate* qstate, struct delegpt* dp); + +/** + * Mark targets that result in a dependency cycle as done, so they + * will not get selected as targets. For the parent-side lookups. + * @param qstate: query state. + * @param dp: delegpt to mark ns in. + */ +void iter_mark_pside_cycle_targets(struct module_qstate* qstate, + struct delegpt* dp); + +/** + * See if delegation is useful or offers immediately no targets for + * further recursion. + * @param qinfo: query name and type + * @param qflags: query flags with RD flag + * @param dp: delegpt to check. + * @return true if dp is useless. + */ +int iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags, + struct delegpt* dp); + +/** + * 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. + * @param env: module env with trust anchors. + * @param dp: delegation point. + * @param msg: delegation message, with DS if a secure referral. + * @param dclass: class of query. + * @return 1 if dnssec is expected, 0 if not. + */ +int iter_indicates_dnssec(struct module_env* env, struct delegpt* dp, + struct dns_msg* msg, uint16_t dclass); + +/** + * See if a message contains DNSSEC. + * This is examined by looking for RRSIGs. With DNSSEC a valid answer, + * nxdomain, nodata, referral or cname reply has RRSIGs in answer or auth + * sections, sigs on answer data, SOA, DS, or NSEC/NSEC3 records. + * @param msg: message to examine. + * @return true if DNSSEC information was found. + */ +int iter_msg_has_dnssec(struct dns_msg* msg); + +/** + * See if a message is known to be from a certain zone. + * This looks for SOA or NS rrsets, for answers. + * For referrals, when one label is delegated, the zone is detected. + * Does not look at signatures. + * @param msg: the message to inspect. + * @param dp: delegation point with zone name to look for. + * @param type: type of message. + * @param dclass: class of query. + * @return true if message is certain to be from zone in dp->name. + * false if not sure (empty msg), or not from the zone. + */ +int iter_msg_from_zone(struct dns_msg* msg, struct delegpt* dp, + enum response_type type, uint16_t dclass); + +/** + * Check if two replies are equal + * For fallback procedures + * @param p: reply one. The reply has rrset data pointers in region. + * Does not check rrset-IDs + * @param q: reply two + * @param buf: scratch buffer. + * @return if one and two are equal. + */ +int reply_equal(struct reply_info* p, struct reply_info* q, ldns_buffer* buf); + +/** + * Store parent-side rrset in seperate rrset cache entries for later + * last-resort * lookups in case the child-side versions of this information + * fails. + * @param env: environment with cache, time, ... + * @param rrset: the rrset to store (copied). + * Failure to store is logged, but otherwise ignored. + */ +void iter_store_parentside_rrset(struct module_env* env, + struct ub_packed_rrset_key* rrset); + +/** + * Store parent-side NS records from a referral message + * @param env: environment with cache, time, ... + * @param rep: response with NS rrset. + * Failure to store is logged, but otherwise ignored. + */ +void iter_store_parentside_NS(struct module_env* env, struct reply_info* rep); + +/** + * Store parent-side negative element, the parentside rrset does not exist, + * creates an rrset with empty rdata in the rrset cache with PARENTSIDE flag. + * @param env: environment with cache, time, ... + * @param qinfo: the identity of the rrset that is missing. + * @param rep: delegation response or answer response, to glean TTL from. + * (malloc) failure is logged but otherwise ignored. + */ +void iter_store_parentside_neg(struct module_env* env, + struct query_info* qinfo, struct reply_info* rep); + +/** + * Add parent NS record if that exists in the cache. This is both new + * information and acts like a timeout throttle on retries. + * @param env: query env with rrset cache and time. + * @param dp: delegation point to store result in. Also this dp is used to + * see which NS name is needed. + * @param region: region to alloc result in. + * @param qinfo: pertinent information, the qclass. + * @return false on malloc failure. + * if true, the routine worked and if such cached information + * existed dp->has_parent_side_NS is set true. + */ +int iter_lookup_parent_NS_from_cache(struct module_env* env, + struct delegpt* dp, struct regional* region, struct query_info* qinfo); + +/** + * Add parent-side glue if that exists in the cache. This is both new + * information and acts like a timeout throttle on retries to fetch them. + * @param env: query env with rrset cache and time. + * @param dp: delegation point to store result in. Also this dp is used to + * see which NS name is needed. + * @param region: region to alloc result in. + * @param qinfo: pertinent information, the qclass. + * @return: true, it worked, no malloc failures, and new addresses (lame) + * have been added, giving extra options as query targets. + */ +int iter_lookup_parent_glue_from_cache(struct module_env* env, + struct delegpt* dp, struct regional* region, struct query_info* qinfo); + +/** + * Lookup next root-hint or root-forward entry. + * @param hints: the hints. + * @param fwd: the forwards. + * @param c: the class to start searching at. 0 means find first one. + * @return false if no classes found, true if found and returned in c. + */ +int iter_get_next_root(struct iter_hints* hints, struct iter_forwards* fwd, + uint16_t* c); + +/** + * Remove DS records that are inappropriate before they are cached. + * @param msg: the response to scrub. + * @param ns: RRSET that is the NS record for the referral. + * if NULL, then all DS records are removed from the authority section. + * @param z: zone name that the response is from. + */ +void iter_scrub_ds(struct dns_msg* msg, struct ub_packed_rrset_key* ns, + uint8_t* z); + +/** + * Remove query attempts from all available ips. For 0x20. + * @param dp: delegpt. + * @param d: decrease. + */ +void iter_dec_attempts(struct delegpt* dp, int d); + +/** + * Add retry counts from older delegpt to newer delegpt. + * Does not waste time on timeout'd (or other failing) addresses. + * @param dp: new delegationpoint. + * @param old: old delegationpoint. + */ +void iter_merge_retry_counts(struct delegpt* dp, struct delegpt* old); + +/** + * See if a DS response (type ANSWER) is too low: a nodata answer with + * a SOA record in the authority section at-or-below the qchase.qname. + * Also returns true if we are not sure (i.e. empty message, CNAME nosig). + * @param msg: the response. + * @param dp: the dp name is used to check if the RRSIG gives a clue that + * it was originated from the correct nameserver. + * @return true if too low. + */ +int iter_ds_toolow(struct dns_msg* msg, struct delegpt* dp); + +/** + * See if delegpt can go down a step to the qname or not + * @param qinfo: the query name looked up. + * @param dp: checked if the name can go lower to the qname + * @return true if can go down, false if that would not be possible. + * the current response seems to be the one and only, best possible, response. + */ +int iter_dp_cangodown(struct query_info* qinfo, struct delegpt* dp); + +#endif /* ITERATOR_ITER_UTILS_H */ diff --git a/iterator/iterator.c b/iterator/iterator.c new file mode 100644 index 00000000000..af20c4261b7 --- /dev/null +++ b/iterator/iterator.c @@ -0,0 +1,2897 @@ +/* + * iterator/iterator.c - iterative resolver DNS query response module + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains a module that performs recusive iterative DNS query + * processing. + */ + +#include "config.h" +#include +#include "iterator/iterator.h" +#include "iterator/iter_utils.h" +#include "iterator/iter_hints.h" +#include "iterator/iter_fwd.h" +#include "iterator/iter_donotq.h" +#include "iterator/iter_delegpt.h" +#include "iterator/iter_resptype.h" +#include "iterator/iter_scrub.h" +#include "iterator/iter_priv.h" +#include "validator/val_neg.h" +#include "services/cache/dns.h" +#include "services/cache/infra.h" +#include "util/module.h" +#include "util/netevent.h" +#include "util/net_help.h" +#include "util/regional.h" +#include "util/data/dname.h" +#include "util/data/msgencode.h" +#include "util/fptr_wlist.h" +#include "util/config_file.h" + +int +iter_init(struct module_env* env, int id) +{ + struct iter_env* iter_env = (struct iter_env*)calloc(1, + sizeof(struct iter_env)); + if(!iter_env) { + log_err("malloc failure"); + return 0; + } + env->modinfo[id] = (void*)iter_env; + if(!iter_apply_cfg(iter_env, env->cfg)) { + log_err("iterator: could not apply configuration settings."); + return 0; + } + return 1; +} + +void +iter_deinit(struct module_env* env, int id) +{ + struct iter_env* iter_env; + if(!env || !env->modinfo[id]) + return; + iter_env = (struct iter_env*)env->modinfo[id]; + free(iter_env->target_fetch_policy); + priv_delete(iter_env->priv); + donotq_delete(iter_env->donotq); + free(iter_env); + env->modinfo[id] = NULL; +} + +/** new query for iterator */ +static int +iter_new(struct module_qstate* qstate, int id) +{ + struct iter_qstate* iq = (struct iter_qstate*)regional_alloc( + qstate->region, sizeof(struct iter_qstate)); + qstate->minfo[id] = iq; + if(!iq) + return 0; + memset(iq, 0, sizeof(*iq)); + iq->state = INIT_REQUEST_STATE; + iq->final_state = FINISHED_STATE; + iq->an_prepend_list = NULL; + iq->an_prepend_last = NULL; + iq->ns_prepend_list = NULL; + iq->ns_prepend_last = NULL; + iq->dp = NULL; + iq->depth = 0; + iq->num_target_queries = 0; + iq->num_current_queries = 0; + iq->query_restart_count = 0; + iq->referral_count = 0; + iq->sent_count = 0; + iq->wait_priming_stub = 0; + iq->refetch_glue = 0; + iq->dnssec_expected = 0; + iq->dnssec_lame_query = 0; + iq->chase_flags = qstate->query_flags; + /* Start with the (current) qname. */ + iq->qchase = qstate->qinfo; + outbound_list_init(&iq->outlist); + return 1; +} + +/** + * Transition to the next state. This can be used to advance a currently + * processing event. It cannot be used to reactivate a forEvent. + * + * @param iq: iterator query state + * @param nextstate The state to transition to. + * @return true. This is so this can be called as the return value for the + * actual process*State() methods. (Transitioning to the next state + * implies further processing). + */ +static int +next_state(struct iter_qstate* iq, enum iter_state nextstate) +{ + /* If transitioning to a "response" state, make sure that there is a + * response */ + if(iter_state_is_responsestate(nextstate)) { + if(iq->response == NULL) { + log_err("transitioning to response state sans " + "response."); + } + } + iq->state = nextstate; + return 1; +} + +/** + * Transition an event to its final state. Final states always either return + * a result up the module chain, or reactivate a dependent event. Which + * final state to transtion to is set in the module state for the event when + * it was created, and depends on the original purpose of the event. + * + * The response is stored in the qstate->buf buffer. + * + * @param iq: iterator query state + * @return false. This is so this method can be used as the return value for + * the processState methods. (Transitioning to the final state + */ +static int +final_state(struct iter_qstate* iq) +{ + return next_state(iq, iq->final_state); +} + +/** + * Callback routine to handle errors in parent query states + * @param qstate: query state that failed. + * @param id: module id. + * @param super: super state. + */ +static void +error_supers(struct module_qstate* qstate, int id, struct module_qstate* super) +{ + struct iter_qstate* super_iq = (struct iter_qstate*)super->minfo[id]; + + if(qstate->qinfo.qtype == LDNS_RR_TYPE_A || + qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA) { + /* mark address as failed. */ + struct delegpt_ns* dpns = NULL; + 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, "subq error, but not interested"); + log_query_info(VERB_ALGO, "superq", &super->qinfo); + if(super_iq->dp) + delegpt_log(VERB_ALGO, super_iq->dp); + log_assert(0); + return; + } else { + /* 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("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 */ + super_iq->dp = NULL; + } + /* evaluate targets again */ + super_iq->state = QUERYTARGETS_STATE; + /* super becomes runnable, and will process this change */ +} + +/** + * Return an error to the client + * @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", + ldns_lookup_by_id(ldns_rcodes, rcode)? + ldns_lookup_by_id(ldns_rcodes, rcode)->name:"??"); + qstate->return_rcode = rcode; + qstate->return_msg = NULL; + qstate->ext_state[id] = module_finished; + return 0; +} + +/** + * Return an error to the client and cache the error code in the + * message cache (so per qname, qtype, qclass). + * @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_cache(struct module_qstate* qstate, int id, int rcode) +{ + /* store in cache */ + struct reply_info err; + memset(&err, 0, sizeof(err)); + err.flags = (uint16_t)(BIT_QR | BIT_RA); + FLAGS_SET_RCODE(err.flags, rcode); + err.qdcount = 1; + err.ttl = NORR_TTL; + err.prefetch_ttl = PREFETCH_TTL_CALC(err.ttl); + /* do not waste time trying to validate this servfail */ + err.security = sec_status_indeterminate; + verbose(VERB_ALGO, "store error response in message cache"); + if(!iter_dns_store(qstate->env, &qstate->qinfo, &err, 0, 0, 0, NULL)) { + log_err("error_response_cache: could not store error (nomem)"); + } + return error_response(qstate, id, rcode); +} + +/** check if prepend item is duplicate item */ +static int +prepend_is_duplicate(struct ub_packed_rrset_key** sets, size_t to, + struct ub_packed_rrset_key* dup) +{ + size_t i; + for(i=0; irk.type == dup->rk.type && + sets[i]->rk.rrset_class == dup->rk.rrset_class && + sets[i]->rk.dname_len == dup->rk.dname_len && + query_dname_compare(sets[i]->rk.dname, dup->rk.dname) + == 0) + return 1; + } + return 0; +} + +/** prepend the prepend list in the answer and authority section of dns_msg */ +static int +iter_prepend(struct iter_qstate* iq, struct dns_msg* msg, + struct regional* region) +{ + struct iter_prep_list* p; + struct ub_packed_rrset_key** sets; + size_t num_an = 0, num_ns = 0;; + for(p = iq->an_prepend_list; p; p = p->next) + num_an++; + for(p = iq->ns_prepend_list; p; p = p->next) + num_ns++; + if(num_an + num_ns == 0) + return 1; + verbose(VERB_ALGO, "prepending %d rrsets", (int)num_an + (int)num_ns); + sets = regional_alloc(region, (num_an+num_ns+msg->rep->rrset_count) * + sizeof(struct ub_packed_rrset_key*)); + if(!sets) + return 0; + /* ANSWER section */ + num_an = 0; + for(p = iq->an_prepend_list; p; p = p->next) { + sets[num_an++] = p->rrset; + } + memcpy(sets+num_an, msg->rep->rrsets, msg->rep->an_numrrsets * + sizeof(struct ub_packed_rrset_key*)); + /* AUTH section */ + num_ns = 0; + for(p = iq->ns_prepend_list; p; p = p->next) { + if(prepend_is_duplicate(sets+msg->rep->an_numrrsets+num_an, + num_ns, p->rrset) || prepend_is_duplicate( + msg->rep->rrsets+msg->rep->an_numrrsets, + msg->rep->ns_numrrsets, p->rrset)) + continue; + sets[msg->rep->an_numrrsets + num_an + num_ns++] = p->rrset; + } + memcpy(sets + num_an + msg->rep->an_numrrsets + num_ns, + msg->rep->rrsets + msg->rep->an_numrrsets, + (msg->rep->ns_numrrsets + msg->rep->ar_numrrsets) * + sizeof(struct ub_packed_rrset_key*)); + + /* NXDOMAIN rcode can stay if we prepended DNAME/CNAMEs, because + * this is what recursors should give. */ + msg->rep->rrset_count += num_an + num_ns; + msg->rep->an_numrrsets += num_an; + msg->rep->ns_numrrsets += num_ns; + msg->rep->rrsets = sets; + return 1; +} + +/** + * Add rrset to ANSWER prepend list + * @param qstate: query state. + * @param iq: iterator query state. + * @param rrset: rrset to add. + * @return false on failure (malloc). + */ +static int +iter_add_prepend_answer(struct module_qstate* qstate, struct iter_qstate* iq, + struct ub_packed_rrset_key* rrset) +{ + struct iter_prep_list* p = (struct iter_prep_list*)regional_alloc( + qstate->region, sizeof(struct iter_prep_list)); + if(!p) + return 0; + p->rrset = rrset; + p->next = NULL; + /* add at end */ + if(iq->an_prepend_last) + iq->an_prepend_last->next = p; + else iq->an_prepend_list = p; + iq->an_prepend_last = p; + return 1; +} + +/** + * Add rrset to AUTHORITY prepend list + * @param qstate: query state. + * @param iq: iterator query state. + * @param rrset: rrset to add. + * @return false on failure (malloc). + */ +static int +iter_add_prepend_auth(struct module_qstate* qstate, struct iter_qstate* iq, + struct ub_packed_rrset_key* rrset) +{ + struct iter_prep_list* p = (struct iter_prep_list*)regional_alloc( + qstate->region, sizeof(struct iter_prep_list)); + if(!p) + return 0; + p->rrset = rrset; + p->next = NULL; + /* add at end */ + if(iq->ns_prepend_last) + iq->ns_prepend_last->next = p; + else iq->ns_prepend_list = p; + iq->ns_prepend_last = p; + return 1; +} + +/** + * Given a CNAME response (defined as a response containing a CNAME or DNAME + * that does not answer the request), process the response, modifying the + * state as necessary. This follows the CNAME/DNAME chain and returns the + * final query name. + * + * sets the new query name, after following the CNAME/DNAME chain. + * @param qstate: query state. + * @param iq: iterator query state. + * @param msg: the response. + * @param mname: returned target new query name. + * @param mname_len: length of mname. + * @return false on (malloc) error. + */ +static int +handle_cname_response(struct module_qstate* qstate, struct iter_qstate* iq, + struct dns_msg* msg, uint8_t** mname, size_t* mname_len) +{ + size_t i; + /* Start with the (current) qname. */ + *mname = iq->qchase.qname; + *mname_len = iq->qchase.qname_len; + + /* Iterate over the ANSWER rrsets in order, looking for CNAMEs and + * DNAMES. */ + for(i=0; irep->an_numrrsets; i++) { + struct ub_packed_rrset_key* r = msg->rep->rrsets[i]; + /* If there is a (relevant) DNAME, add it to the list. + * We always expect there to be CNAME that was generated + * by this DNAME following, so we don't process the DNAME + * directly. */ + if(ntohs(r->rk.type) == LDNS_RR_TYPE_DNAME && + dname_strict_subdomain_c(*mname, r->rk.dname)) { + if(!iter_add_prepend_answer(qstate, iq, r)) + return 0; + continue; + } + + if(ntohs(r->rk.type) == LDNS_RR_TYPE_CNAME && + query_dname_compare(*mname, r->rk.dname) == 0) { + /* Add this relevant CNAME rrset to the prepend list.*/ + if(!iter_add_prepend_answer(qstate, iq, r)) + return 0; + get_cname_target(r, mname, mname_len); + } + + /* Other rrsets in the section are ignored. */ + } + /* add authority rrsets to authority prepend, for wildcarded CNAMEs */ + for(i=msg->rep->an_numrrsets; irep->an_numrrsets + + msg->rep->ns_numrrsets; i++) { + struct ub_packed_rrset_key* r = msg->rep->rrsets[i]; + /* only add NSEC/NSEC3, as they may be needed for validation */ + if(ntohs(r->rk.type) == LDNS_RR_TYPE_NSEC || + ntohs(r->rk.type) == LDNS_RR_TYPE_NSEC3) { + if(!iter_add_prepend_auth(qstate, iq, r)) + return 0; + } + } + return 1; +} + +/** + * Generate a subrequest. + * Generate a local request event. Local events are tied to this module, and + * have a correponding (first tier) event that is waiting for this event to + * resolve to continue. + * + * @param qname The query name for this request. + * @param qnamelen length of qname + * @param qtype The query type for this request. + * @param qclass The query class for this request. + * @param qstate The event that is generating this event. + * @param id: module id. + * @param iq: The iterator state that is generating this event. + * @param initial_state The initial response state (normally this + * is QUERY_RESP_STATE, unless it is known that the request won't + * need iterative processing + * @param finalstate The final state for the response to this request. + * @param subq_ret: if newly allocated, the subquerystate, or NULL if it does + * not need initialisation. + * @param v: if true, validation is done on the subquery. + * @return false on error (malloc). + */ +static int +generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype, + uint16_t qclass, struct module_qstate* qstate, int id, + struct iter_qstate* iq, enum iter_state initial_state, + enum iter_state finalstate, struct module_qstate** subq_ret, int v) +{ + struct module_qstate* subq = NULL; + struct iter_qstate* subiq = NULL; + uint16_t qflags = 0; /* OPCODE QUERY, no flags */ + struct query_info qinf; + int prime = (finalstate == PRIME_RESP_STATE)?1:0; + qinf.qname = qname; + qinf.qname_len = qnamelen; + qinf.qtype = qtype; + qinf.qclass = qclass; + + /* RD should be set only when sending the query back through the INIT + * state. */ + if(initial_state == INIT_REQUEST_STATE) + qflags |= BIT_RD; + /* We set the CD flag so we can send this through the "head" of + * the resolution chain, which might have a validator. We are + * uninterested in validating things not on the direct resolution + * path. */ + if(!v) + qflags |= BIT_CD; + + /* attach subquery, lookup existing or make a new one */ + fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub)); + if(!(*qstate->env->attach_sub)(qstate, &qinf, qflags, prime, &subq)) { + return 0; + } + *subq_ret = subq; + if(subq) { + /* initialise the new subquery */ + subq->curmod = id; + subq->ext_state[id] = module_state_initial; + subq->minfo[id] = regional_alloc(subq->region, + sizeof(struct iter_qstate)); + if(!subq->minfo[id]) { + log_err("init subq: out of memory"); + fptr_ok(fptr_whitelist_modenv_kill_sub( + qstate->env->kill_sub)); + (*qstate->env->kill_sub)(subq); + return 0; + } + subiq = (struct iter_qstate*)subq->minfo[id]; + memset(subiq, 0, sizeof(*subiq)); + subiq->num_target_queries = 0; + subiq->num_current_queries = 0; + subiq->depth = iq->depth+1; + outbound_list_init(&subiq->outlist); + subiq->state = initial_state; + subiq->final_state = finalstate; + subiq->qchase = subq->qinfo; + subiq->chase_flags = subq->query_flags; + subiq->refetch_glue = 0; + } + return 1; +} + +/** + * Generate and send a root priming request. + * @param qstate: the qtstate that triggered the need to prime. + * @param iq: iterator query state. + * @param id: module id. + * @param qclass: the class to prime. + * @return 0 on failure + */ +static int +prime_root(struct module_qstate* qstate, struct iter_qstate* iq, int id, + uint16_t qclass) +{ + struct delegpt* dp; + struct module_qstate* subq; + verbose(VERB_DETAIL, "priming . %s NS", + ldns_lookup_by_id(ldns_rr_classes, (int)qclass)? + ldns_lookup_by_id(ldns_rr_classes, (int)qclass)->name:"??"); + dp = hints_lookup_root(qstate->env->hints, qclass); + if(!dp) { + verbose(VERB_ALGO, "Cannot prime due to lack of hints"); + return 0; + } + /* Priming requests start at the QUERYTARGETS state, skipping + * the normal INIT state logic (which would cause an infloop). */ + if(!generate_sub_request((uint8_t*)"\000", 1, LDNS_RR_TYPE_NS, + qclass, qstate, id, iq, QUERYTARGETS_STATE, PRIME_RESP_STATE, + &subq, 0)) { + verbose(VERB_ALGO, "could not prime root"); + return 0; + } + if(subq) { + struct iter_qstate* subiq = + (struct iter_qstate*)subq->minfo[id]; + /* Set the initial delegation point to the hint. + * copy dp, it is now part of the root prime query. + * dp was part of in the fixed hints structure. */ + subiq->dp = delegpt_copy(dp, subq->region); + if(!subiq->dp) { + log_err("out of memory priming root, copydp"); + fptr_ok(fptr_whitelist_modenv_kill_sub( + qstate->env->kill_sub)); + (*qstate->env->kill_sub)(subq); + return 0; + } + /* there should not be any target queries. */ + subiq->num_target_queries = 0; + subiq->dnssec_expected = iter_indicates_dnssec( + qstate->env, subiq->dp, NULL, subq->qinfo.qclass); + } + + /* this module stops, our submodule starts, and does the query. */ + qstate->ext_state[id] = module_wait_subquery; + return 1; +} + +/** + * Generate and process a stub priming request. This method tests for the + * need to prime a stub zone, so it is safe to call for every request. + * + * @param qstate: the qtstate that triggered the need to prime. + * @param iq: iterator query state. + * @param id: module id. + * @param qname: request name. + * @param qclass: request class. + * @return true if a priming subrequest was made, false if not. The will only + * issue a priming request if it detects an unprimed stub. + * Uses value of 2 to signal during stub-prime in root-prime situation + * that a noprime-stub is available and resolution can continue. + */ +static int +prime_stub(struct module_qstate* qstate, struct iter_qstate* iq, int id, + uint8_t* qname, uint16_t qclass) +{ + /* Lookup the stub hint. This will return null if the stub doesn't + * need to be re-primed. */ + struct iter_hints_stub* stub; + struct delegpt* stub_dp; + struct module_qstate* subq; + + if(!qname) return 0; + stub = hints_lookup_stub(qstate->env->hints, qname, qclass, iq->dp); + /* The stub (if there is one) does not need priming. */ + if(!stub) + return 0; + stub_dp = stub->dp; + + /* is it a noprime stub (always use) */ + if(stub->noprime) { + int r = 0; + if(iq->dp == NULL) r = 2; + /* copy the dp out of the fixed hints structure, so that + * it can be changed when servicing this query */ + iq->dp = delegpt_copy(stub_dp, qstate->region); + if(!iq->dp) { + log_err("out of memory priming stub"); + (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL); + return 1; /* return 1 to make module stop, with error */ + } + log_nametypeclass(VERB_DETAIL, "use stub", stub_dp->name, + LDNS_RR_TYPE_NS, qclass); + return r; + } + + /* Otherwise, we need to (re)prime the stub. */ + log_nametypeclass(VERB_DETAIL, "priming stub", stub_dp->name, + LDNS_RR_TYPE_NS, qclass); + + /* Stub priming events start at the QUERYTARGETS state to avoid the + * redundant INIT state processing. */ + if(!generate_sub_request(stub_dp->name, stub_dp->namelen, + LDNS_RR_TYPE_NS, qclass, qstate, id, iq, + QUERYTARGETS_STATE, PRIME_RESP_STATE, &subq, 0)) { + verbose(VERB_ALGO, "could not prime stub"); + (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL); + return 1; /* return 1 to make module stop, with error */ + } + if(subq) { + struct iter_qstate* subiq = + (struct iter_qstate*)subq->minfo[id]; + + /* Set the initial delegation point to the hint. */ + /* make copy to avoid use of stub dp by different qs/threads */ + subiq->dp = delegpt_copy(stub_dp, subq->region); + if(!subiq->dp) { + log_err("out of memory priming stub, copydp"); + fptr_ok(fptr_whitelist_modenv_kill_sub( + qstate->env->kill_sub)); + (*qstate->env->kill_sub)(subq); + (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL); + return 1; /* return 1 to make module stop, with error */ + } + /* there should not be any target queries -- although there + * wouldn't be anyway, since stub hints never have + * missing targets. */ + subiq->num_target_queries = 0; + subiq->wait_priming_stub = 1; + subiq->dnssec_expected = iter_indicates_dnssec( + qstate->env, subiq->dp, NULL, subq->qinfo.qclass); + } + + /* this module stops, our submodule starts, and does the query. */ + qstate->ext_state[id] = module_wait_subquery; + return 1; +} + +/** + * Generate A and AAAA checks for glue that is in-zone for the referral + * we just got to obtain authoritative information on the adresses. + * + * @param qstate: the qtstate that triggered the need to prime. + * @param iq: iterator query state. + * @param id: module id. + */ +static void +generate_a_aaaa_check(struct module_qstate* qstate, struct iter_qstate* iq, + int id) +{ + struct iter_env* ie = (struct iter_env*)qstate->env->modinfo[id]; + struct module_qstate* subq; + size_t i; + struct reply_info* rep = iq->response->rep; + struct ub_packed_rrset_key* s; + log_assert(iq->dp); + + if(iq->depth == ie->max_dependency_depth) + return; + /* walk through additional, and check if in-zone, + * only relevant A, AAAA are left after scrub anyway */ + for(i=rep->an_numrrsets+rep->ns_numrrsets; irrset_count; i++) { + s = rep->rrsets[i]; + /* check *ALL* addresses that are transmitted in additional*/ + /* is it an address ? */ + if( !(ntohs(s->rk.type)==LDNS_RR_TYPE_A || + ntohs(s->rk.type)==LDNS_RR_TYPE_AAAA)) { + continue; + } + /* is this query the same as the A/AAAA check for it */ + if(qstate->qinfo.qtype == ntohs(s->rk.type) && + qstate->qinfo.qclass == ntohs(s->rk.rrset_class) && + query_dname_compare(qstate->qinfo.qname, + s->rk.dname)==0 && + (qstate->query_flags&BIT_RD) && + !(qstate->query_flags&BIT_CD)) + continue; + + /* generate subrequest for it */ + log_nametypeclass(VERB_ALGO, "schedule addr fetch", + s->rk.dname, ntohs(s->rk.type), + ntohs(s->rk.rrset_class)); + if(!generate_sub_request(s->rk.dname, s->rk.dname_len, + ntohs(s->rk.type), ntohs(s->rk.rrset_class), + qstate, id, iq, + INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1)) { + verbose(VERB_ALGO, "could not generate addr check"); + return; + } + /* ignore subq - not need for more init */ + } +} + +/** + * Generate a NS check request to obtain authoritative information + * on an NS rrset. + * + * @param qstate: the qtstate that triggered the need to prime. + * @param iq: iterator query state. + * @param id: module id. + */ +static void +generate_ns_check(struct module_qstate* qstate, struct iter_qstate* iq, int id) +{ + struct iter_env* ie = (struct iter_env*)qstate->env->modinfo[id]; + struct module_qstate* subq; + log_assert(iq->dp); + + if(iq->depth == ie->max_dependency_depth) + return; + /* is this query the same as the nscheck? */ + if(qstate->qinfo.qtype == LDNS_RR_TYPE_NS && + query_dname_compare(iq->dp->name, qstate->qinfo.qname)==0 && + (qstate->query_flags&BIT_RD) && !(qstate->query_flags&BIT_CD)){ + /* spawn off A, AAAA queries for in-zone glue to check */ + generate_a_aaaa_check(qstate, iq, id); + return; + } + + log_nametypeclass(VERB_ALGO, "schedule ns fetch", + iq->dp->name, LDNS_RR_TYPE_NS, iq->qchase.qclass); + if(!generate_sub_request(iq->dp->name, iq->dp->namelen, + LDNS_RR_TYPE_NS, iq->qchase.qclass, qstate, id, iq, + INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1)) { + verbose(VERB_ALGO, "could not generate ns check"); + return; + } + if(subq) { + struct iter_qstate* subiq = + (struct iter_qstate*)subq->minfo[id]; + + /* make copy to avoid use of stub dp by different qs/threads */ + /* refetch glue to start higher up the tree */ + subiq->refetch_glue = 1; + subiq->dp = delegpt_copy(iq->dp, subq->region); + if(!subiq->dp) { + log_err("out of memory generating ns check, copydp"); + fptr_ok(fptr_whitelist_modenv_kill_sub( + qstate->env->kill_sub)); + (*qstate->env->kill_sub)(subq); + return; + } + } +} + +/** + * Generate a DNSKEY prefetch query to get the DNSKEY for the DS record we + * just got in a referral (where we have dnssec_expected, thus have trust + * anchors above it). Note that right after calling this routine the + * iterator detached subqueries (because of following the referral), and thus + * the DNSKEY query becomes detached, its return stored in the cache for + * later lookup by the validator. This cache lookup by the validator avoids + * the roundtrip incurred by the DNSKEY query. The DNSKEY query is now + * performed at about the same time the original query is sent to the domain, + * thus the two answers are likely to be returned at about the same time, + * saving a roundtrip from the validated lookup. + * + * @param qstate: the qtstate that triggered the need to prime. + * @param iq: iterator query state. + * @param id: module id. + */ +static void +generate_dnskey_prefetch(struct module_qstate* qstate, + struct iter_qstate* iq, int id) +{ + struct module_qstate* subq; + log_assert(iq->dp); + + /* is this query the same as the prefetch? */ + if(qstate->qinfo.qtype == LDNS_RR_TYPE_DNSKEY && + query_dname_compare(iq->dp->name, qstate->qinfo.qname)==0 && + (qstate->query_flags&BIT_RD) && !(qstate->query_flags&BIT_CD)){ + return; + } + + /* if the DNSKEY is in the cache this lookup will stop quickly */ + log_nametypeclass(VERB_ALGO, "schedule dnskey prefetch", + iq->dp->name, LDNS_RR_TYPE_DNSKEY, iq->qchase.qclass); + if(!generate_sub_request(iq->dp->name, iq->dp->namelen, + LDNS_RR_TYPE_DNSKEY, iq->qchase.qclass, qstate, id, iq, + INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0)) { + /* we'll be slower, but it'll work */ + verbose(VERB_ALGO, "could not generate dnskey prefetch"); + return; + } + if(subq) { + struct iter_qstate* subiq = + (struct iter_qstate*)subq->minfo[id]; + /* this qstate has the right delegation for the dnskey lookup*/ + /* make copy to avoid use of stub dp by different qs/threads */ + subiq->dp = delegpt_copy(iq->dp, subq->region); + /* if !subiq->dp, it'll start from the cache, no problem */ + } +} + +/** + * See if the query needs forwarding. + * + * @param qstate: query state. + * @param iq: iterator query state. + * @return true if the request is forwarded, false if not. + * If returns true but, iq->dp is NULL then a malloc failure occurred. + */ +static int +forward_request(struct module_qstate* qstate, struct iter_qstate* iq) +{ + struct delegpt* dp; + uint8_t* delname = iq->qchase.qname; + size_t delnamelen = iq->qchase.qname_len; + if(iq->refetch_glue) { + delname = iq->dp->name; + delnamelen = iq->dp->namelen; + } + /* strip one label off of DS query to lookup higher for it */ + if( (iq->qchase.qtype == LDNS_RR_TYPE_DS || iq->refetch_glue) + && !dname_is_root(iq->qchase.qname)) + dname_remove_label(&delname, &delnamelen); + dp = forwards_lookup(qstate->env->fwds, delname, iq->qchase.qclass); + if(!dp) + return 0; + /* send recursion desired to forward addr */ + iq->chase_flags |= BIT_RD; + iq->dp = delegpt_copy(dp, qstate->region); + /* iq->dp checked by caller */ + verbose(VERB_ALGO, "forwarding request"); + return 1; +} + +/** + * Process the initial part of the request handling. This state roughly + * corresponds to resolver algorithms steps 1 (find answer in cache) and 2 + * (find the best servers to ask). + * + * Note that all requests start here, and query restarts revisit this state. + * + * This state either generates: 1) a response, from cache or error, 2) a + * priming event, or 3) forwards the request to the next state (init2, + * generally). + * + * @param qstate: query state. + * @param iq: iterator query state. + * @param ie: iterator shared global environment. + * @param id: module id. + * @return true if the event needs more request processing immediately, + * false if not. + */ +static int +processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq, + struct iter_env* ie, int id) +{ + uint8_t* delname; + size_t delnamelen; + struct dns_msg* msg; + + log_query_info(VERB_DETAIL, "resolving", &qstate->qinfo); + /* check effort */ + + /* We enforce a maximum number of query restarts. This is primarily a + * cheap way to prevent CNAME loops. */ + if(iq->query_restart_count > MAX_RESTART_COUNT) { + verbose(VERB_QUERY, "request has exceeded the maximum number" + " of query restarts with %d", iq->query_restart_count); + return error_response(qstate, id, LDNS_RCODE_SERVFAIL); + } + + /* We enforce a maximum recursion/dependency depth -- in general, + * this is unnecessary for dependency loops (although it will + * catch those), but it provides a sensible limit to the amount + * of work required to answer a given query. */ + verbose(VERB_ALGO, "request has dependency depth of %d", iq->depth); + if(iq->depth > ie->max_dependency_depth) { + verbose(VERB_QUERY, "request has exceeded the maximum " + "dependency depth with depth of %d", iq->depth); + return error_response(qstate, id, LDNS_RCODE_SERVFAIL); + } + + /* If the request is qclass=ANY, setup to generate each class */ + if(qstate->qinfo.qclass == LDNS_RR_CLASS_ANY) { + iq->qchase.qclass = 0; + return next_state(iq, COLLECT_CLASS_STATE); + } + + /* Resolver Algorithm Step 1 -- Look for the answer in local data. */ + + /* This either results in a query restart (CNAME cache response), a + * terminating response (ANSWER), or a cache miss (null). */ + + if(qstate->blacklist) { + /* if cache, or anything else, was blacklisted then + * getting older results from cache is a bad idea, no cache */ + verbose(VERB_ALGO, "cache blacklisted, going to the network"); + msg = NULL; + } else { + msg = dns_cache_lookup(qstate->env, iq->qchase.qname, + iq->qchase.qname_len, iq->qchase.qtype, + iq->qchase.qclass, 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, &iq->qchase, + qstate->region, qstate->env->rrset_cache, + qstate->env->scratch_buffer, + *qstate->env->now, 1/*add SOA*/, NULL); + } + /* item taken from cache does not match our query name, thus + * security needs to be re-examined later */ + if(msg && query_dname_compare(qstate->qinfo.qname, + iq->qchase.qname) != 0) + msg->rep->security = sec_status_unchecked; + } + if(msg) { + /* handle positive cache response */ + enum response_type type = response_type_from_cache(msg, + &iq->qchase); + if(verbosity >= VERB_ALGO) { + log_dns_msg("msg from cache lookup", &msg->qinfo, + msg->rep); + verbose(VERB_ALGO, "msg ttl is %d, prefetch ttl %d", + (int)msg->rep->ttl, + (int)msg->rep->prefetch_ttl); + } + + if(type == RESPONSE_TYPE_CNAME) { + uint8_t* sname = 0; + size_t slen = 0; + verbose(VERB_ALGO, "returning CNAME response from " + "cache"); + if(!handle_cname_response(qstate, iq, msg, + &sname, &slen)) + return error_response(qstate, id, + LDNS_RCODE_SERVFAIL); + iq->qchase.qname = sname; + iq->qchase.qname_len = slen; + /* This *is* a query restart, even if it is a cheap + * one. */ + iq->dp = NULL; + iq->refetch_glue = 0; + iq->query_restart_count++; + iq->sent_count = 0; + sock_list_insert(&qstate->reply_origin, NULL, 0, qstate->region); + return next_state(iq, INIT_REQUEST_STATE); + } + + /* if from cache, NULL, else insert 'cache IP' len=0 */ + if(qstate->reply_origin) + sock_list_insert(&qstate->reply_origin, NULL, 0, qstate->region); + /* it is an answer, response, to final state */ + verbose(VERB_ALGO, "returning answer from cache."); + iq->response = msg; + return final_state(iq); + } + + /* attempt to forward the request */ + if(forward_request(qstate, iq)) + { + if(!iq->dp) { + log_err("alloc failure for forward dp"); + return error_response(qstate, id, LDNS_RCODE_SERVFAIL); + } + iq->refetch_glue = 0; + /* the request has been forwarded. + * forwarded requests need to be immediately sent to the + * next state, QUERYTARGETS. */ + return next_state(iq, QUERYTARGETS_STATE); + } + + /* Resolver Algorithm Step 2 -- find the "best" servers. */ + + /* first, adjust for DS queries. To avoid the grandparent problem, + * we just look for the closest set of server to the parent of qname. + * When re-fetching glue we also need to ask the parent. + */ + if(iq->refetch_glue) { + if(!iq->dp) { + log_err("internal or malloc fail: no dp for refetch"); + return error_response(qstate, id, LDNS_RCODE_SERVFAIL); + } + delname = iq->dp->name; + delnamelen = iq->dp->namelen; + } else { + delname = iq->qchase.qname; + delnamelen = iq->qchase.qname_len; + } + if(iq->qchase.qtype == LDNS_RR_TYPE_DS || iq->refetch_glue || + (iq->qchase.qtype == LDNS_RR_TYPE_NS && qstate->prefetch_leeway)) { + /* remove first label from delname, root goes to hints, + * but only to fetch glue, not for qtype=DS. */ + /* also when prefetching an NS record, fetch it again from + * its parent, just as if it expired, so that you do not + * get stuck on an older nameserver that gives old NSrecords */ + if(dname_is_root(delname) && (iq->refetch_glue || + (iq->qchase.qtype == LDNS_RR_TYPE_NS && + qstate->prefetch_leeway))) + delname = NULL; /* go to root priming */ + else dname_remove_label(&delname, &delnamelen); + } + /* delname is the name to lookup a delegation for. If NULL rootprime */ + while(1) { + + /* Lookup the delegation in the cache. If null, then the + * cache needs to be primed for the qclass. */ + if(delname) + iq->dp = dns_cache_find_delegation(qstate->env, delname, + delnamelen, iq->qchase.qtype, iq->qchase.qclass, + qstate->region, &iq->deleg_msg, + *qstate->env->now+qstate->prefetch_leeway); + else iq->dp = NULL; + + /* If the cache has returned nothing, then we have a + * root priming situation. */ + if(iq->dp == NULL) { + /* if there is a stub, then no root prime needed */ + int r = prime_stub(qstate, iq, id, delname, + iq->qchase.qclass); + if(r == 2) + break; /* got noprime-stub-zone, continue */ + else if(r) + return 0; /* stub prime request made */ + if(forwards_lookup_root(qstate->env->fwds, + iq->qchase.qclass)) { + /* forward zone root, no root prime needed */ + /* fill in some dp - safety belt */ + iq->dp = hints_lookup_root(qstate->env->hints, + iq->qchase.qclass); + if(!iq->dp) { + log_err("internal error: no hints dp"); + return error_response(qstate, id, + LDNS_RCODE_SERVFAIL); + } + iq->dp = delegpt_copy(iq->dp, qstate->region); + if(!iq->dp) { + log_err("out of memory in safety belt"); + return error_response(qstate, id, + LDNS_RCODE_SERVFAIL); + } + return next_state(iq, INIT_REQUEST_2_STATE); + } + /* Note that the result of this will set a new + * DelegationPoint based on the result of priming. */ + if(!prime_root(qstate, iq, id, iq->qchase.qclass)) + return error_response(qstate, id, + LDNS_RCODE_REFUSED); + + /* priming creates and sends a subordinate query, with + * this query as the parent. So further processing for + * this event will stop until reactivated by the + * results of priming. */ + return 0; + } + + /* see if this dp not useless. + * It is useless if: + * o all NS items are required glue. + * or the query is for NS item that is required glue. + * o no addresses are provided. + * o RD qflag is on. + * Instead, go up one level, and try to get even further + * If the root was useless, use safety belt information. + * Only check cache returns, because replies for servers + * could be useless but lead to loops (bumping into the + * same server reply) if useless-checked. + */ + if(iter_dp_is_useless(&qstate->qinfo, qstate->query_flags, + iq->dp)) { + if(dname_is_root(iq->dp->name)) { + /* use safety belt */ + verbose(VERB_QUERY, "Cache has root NS but " + "no addresses. Fallback to the safety belt."); + iq->dp = hints_lookup_root(qstate->env->hints, + iq->qchase.qclass); + /* note deleg_msg is from previous lookup, + * but RD is on, so it is not used */ + if(!iq->dp) { + log_err("internal error: no hints dp"); + return error_response(qstate, id, + LDNS_RCODE_REFUSED); + } + iq->dp = delegpt_copy(iq->dp, qstate->region); + if(!iq->dp) { + log_err("out of memory in safety belt"); + return error_response(qstate, id, + LDNS_RCODE_SERVFAIL); + } + break; + } else { + verbose(VERB_ALGO, + "cache delegation was useless:"); + delegpt_log(VERB_ALGO, iq->dp); + /* go up */ + delname = iq->dp->name; + delnamelen = iq->dp->namelen; + dname_remove_label(&delname, &delnamelen); + } + } else break; + } + + verbose(VERB_ALGO, "cache delegation returns delegpt"); + delegpt_log(VERB_ALGO, iq->dp); + + /* Otherwise, set the current delegation point and move on to the + * next state. */ + return next_state(iq, INIT_REQUEST_2_STATE); +} + +/** + * Process the second part of the initial request handling. This state + * basically exists so that queries that generate root priming events have + * the same init processing as ones that do not. Request events that reach + * this state must have a valid currentDelegationPoint set. + * + * This part is primarly handling stub zone priming. Events that reach this + * state must have a current delegation point. + * + * @param qstate: query state. + * @param iq: iterator query state. + * @param id: module id. + * @return true if the event needs more request processing immediately, + * false if not. + */ +static int +processInitRequest2(struct module_qstate* qstate, struct iter_qstate* iq, + int id) +{ + uint8_t* delname; + size_t delnamelen; + log_query_info(VERB_QUERY, "resolving (init part 2): ", + &qstate->qinfo); + + if(iq->refetch_glue) { + if(!iq->dp) { + log_err("internal or malloc fail: no dp for refetch"); + return error_response(qstate, id, LDNS_RCODE_SERVFAIL); + } + delname = iq->dp->name; + delnamelen = iq->dp->namelen; + } else { + delname = iq->qchase.qname; + delnamelen = iq->qchase.qname_len; + } + if(iq->qchase.qtype == LDNS_RR_TYPE_DS || iq->refetch_glue) { + if(!dname_is_root(delname)) + dname_remove_label(&delname, &delnamelen); + iq->refetch_glue = 0; /* if CNAME causes restart, no refetch */ + } + /* Check to see if we need to prime a stub zone. */ + if(prime_stub(qstate, iq, id, delname, iq->qchase.qclass)) { + /* A priming sub request was made */ + return 0; + } + + /* most events just get forwarded to the next state. */ + return next_state(iq, INIT_REQUEST_3_STATE); +} + +/** + * Process the third part of the initial request handling. This state exists + * as a separate state so that queries that generate stub priming events + * will get the tail end of the init process but not repeat the stub priming + * check. + * + * @param qstate: query state. + * @param iq: iterator query state. + * @param id: module id. + * @return true, advancing the event to the QUERYTARGETS_STATE. + */ +static int +processInitRequest3(struct module_qstate* qstate, struct iter_qstate* iq, + int id) +{ + log_query_info(VERB_QUERY, "resolving (init part 3): ", + &qstate->qinfo); + /* if the cache reply dp equals a validation anchor or msg has DS, + * then DNSSEC RRSIGs are expected in the reply */ + iq->dnssec_expected = iter_indicates_dnssec(qstate->env, iq->dp, + iq->deleg_msg, iq->qchase.qclass); + + /* If the RD flag wasn't set, then we just finish with the + * cached referral as the response. */ + if(!(qstate->query_flags & BIT_RD)) { + iq->response = iq->deleg_msg; + if(verbosity >= VERB_ALGO) + log_dns_msg("no RD requested, using delegation msg", + &iq->response->qinfo, iq->response->rep); + if(qstate->reply_origin) + sock_list_insert(&qstate->reply_origin, NULL, 0, qstate->region); + return final_state(iq); + } + /* After this point, unset the RD flag -- this query is going to + * be sent to an auth. server. */ + iq->chase_flags &= ~BIT_RD; + + /* if dnssec expected, fetch key for the trust-anchor or cached-DS */ + if(iq->dnssec_expected && qstate->env->cfg->prefetch_key && + !(qstate->query_flags&BIT_CD)) { + generate_dnskey_prefetch(qstate, iq, id); + fptr_ok(fptr_whitelist_modenv_detach_subs( + qstate->env->detach_subs)); + (*qstate->env->detach_subs)(qstate); + } + + /* Jump to the next state. */ + return next_state(iq, QUERYTARGETS_STATE); +} + +/** + * Given a basic query, generate a parent-side "target" query. + * These are subordinate queries for missing delegation point target addresses, + * for which only the parent of the delegation provides correct IP addresses. + * + * @param qstate: query state. + * @param iq: iterator query state. + * @param id: module id. + * @param name: target qname. + * @param namelen: target qname length. + * @param qtype: target qtype (either A or AAAA). + * @param qclass: target qclass. + * @return true on success, false on failure. + */ +static int +generate_parentside_target_query(struct module_qstate* qstate, + struct iter_qstate* iq, int id, uint8_t* name, size_t namelen, + uint16_t qtype, uint16_t qclass) +{ + struct module_qstate* subq; + if(!generate_sub_request(name, namelen, qtype, qclass, qstate, + id, iq, INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0)) + return 0; + if(subq) { + struct iter_qstate* subiq = + (struct iter_qstate*)subq->minfo[id]; + /* blacklist the cache - we want to fetch parent stuff */ + sock_list_insert(&subq->blacklist, NULL, 0, subq->region); + subiq->query_for_pside_glue = 1; + if(dname_subdomain_c(name, iq->dp->name)) { + subiq->dp = delegpt_copy(iq->dp, subq->region); + subiq->dnssec_expected = iter_indicates_dnssec( + qstate->env, subiq->dp, NULL, + subq->qinfo.qclass); + subiq->refetch_glue = 1; + } else { + subiq->dp = dns_cache_find_delegation(qstate->env, + name, namelen, qtype, qclass, subq->region, + &subiq->deleg_msg, + *qstate->env->now+subq->prefetch_leeway); + /* if no dp, then it's from root, refetch unneeded */ + if(subiq->dp) { + subiq->dnssec_expected = iter_indicates_dnssec( + qstate->env, subiq->dp, NULL, + subq->qinfo.qclass); + subiq->refetch_glue = 1; + } + } + } + log_nametypeclass(VERB_QUERY, "new pside target", name, qtype, qclass); + return 1; +} + +/** + * Given a basic query, generate a "target" query. These are subordinate + * queries for missing delegation point target addresses. + * + * @param qstate: query state. + * @param iq: iterator query state. + * @param id: module id. + * @param name: target qname. + * @param namelen: target qname length. + * @param qtype: target qtype (either A or AAAA). + * @param qclass: target qclass. + * @return true on success, false on failure. + */ +static int +generate_target_query(struct module_qstate* qstate, struct iter_qstate* iq, + int id, uint8_t* name, size_t namelen, uint16_t qtype, uint16_t qclass) +{ + struct module_qstate* subq; + if(!generate_sub_request(name, namelen, qtype, qclass, qstate, + id, iq, INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0)) + return 0; + log_nametypeclass(VERB_QUERY, "new target", name, qtype, qclass); + return 1; +} + +/** + * Given an event at a certain state, generate zero or more target queries + * for it's current delegation point. + * + * @param qstate: query state. + * @param iq: iterator query state. + * @param ie: iterator shared global environment. + * @param id: module id. + * @param maxtargets: The maximum number of targets to query for. + * if it is negative, there is no maximum number of targets. + * @param num: returns the number of queries generated and processed, + * which may be zero if there were no missing targets. + * @return false on error. + */ +static int +query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq, + struct iter_env* ie, int id, int maxtargets, int* num) +{ + int query_count = 0; + struct delegpt_ns* ns; + int missing; + int toget = 0; + + if(iq->depth == ie->max_dependency_depth) + return 0; + + iter_mark_cycle_targets(qstate, iq->dp); + missing = (int)delegpt_count_missing_targets(iq->dp); + log_assert(maxtargets != 0); /* that would not be useful */ + + /* Generate target requests. Basically, any missing targets + * are queried for here, regardless if it is necessary to do + * so to continue processing. */ + if(maxtargets < 0 || maxtargets > missing) + toget = missing; + else toget = maxtargets; + if(toget == 0) { + *num = 0; + return 1; + } + /* select 'toget' items from the total of 'missing' items */ + log_assert(toget <= missing); + + /* loop over missing targets */ + for(ns = iq->dp->nslist; ns; ns = ns->next) { + if(ns->resolved) + continue; + + /* randomly select this item with probability toget/missing */ + if(!iter_ns_probability(qstate->env->rnd, toget, missing)) { + /* do not select this one, next; select toget number + * of items from a list one less in size */ + missing --; + continue; + } + + if(ie->supports_ipv6 && !ns->got6) { + /* Send the AAAA request. */ + if(!generate_target_query(qstate, iq, id, + ns->name, ns->namelen, + LDNS_RR_TYPE_AAAA, iq->qchase.qclass)) { + *num = query_count; + if(query_count > 0) + qstate->ext_state[id] = module_wait_subquery; + return 0; + } + query_count++; + } + /* Send the A request. */ + if(ie->supports_ipv4 && !ns->got4) { + if(!generate_target_query(qstate, iq, id, + ns->name, ns->namelen, + LDNS_RR_TYPE_A, iq->qchase.qclass)) { + *num = query_count; + if(query_count > 0) + qstate->ext_state[id] = module_wait_subquery; + return 0; + } + query_count++; + } + + /* mark this target as in progress. */ + ns->resolved = 1; + missing--; + toget--; + if(toget == 0) + break; + } + *num = query_count; + if(query_count > 0) + qstate->ext_state[id] = module_wait_subquery; + + return 1; +} + +/** + * Called by processQueryTargets when it would like extra targets to query + * but it seems to be out of options. At last resort some less appealing + * options are explored. If there are no more options, the result is SERVFAIL + * + * @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. + */ +static int +processLastResort(struct module_qstate* qstate, struct iter_qstate* iq, + struct iter_env* ie, int id) +{ + struct delegpt_ns* ns; + int query_count = 0; + verbose(VERB_ALGO, "No more query targets, attempting last resort"); + log_assert(iq->dp); + + if(!iq->dp->has_parent_side_NS) { + if(!iter_lookup_parent_NS_from_cache(qstate->env, iq->dp, + qstate->region, &qstate->qinfo) + || !iq->dp->has_parent_side_NS) { + /* if: malloc failure in lookup go up to try */ + /* if: no parent NS in cache - go up one level */ + verbose(VERB_ALGO, "try to grab parent NS"); + iq->store_parent_NS = iq->dp; + iq->deleg_msg = NULL; + iq->refetch_glue = 1; + iq->query_restart_count++; + iq->sent_count = 0; + return next_state(iq, INIT_REQUEST_STATE); + } + } + /* see if that makes new names available */ + if(!cache_fill_missing(qstate->env, iq->qchase.qclass, + qstate->region, iq->dp)) + log_err("out of memory in cache_fill_missing"); + if(iq->dp->usable_list) { + verbose(VERB_ALGO, "try parent-side-name, w. glue from cache"); + return next_state(iq, QUERYTARGETS_STATE); + } + /* try to fill out parent glue from cache */ + if(iter_lookup_parent_glue_from_cache(qstate->env, iq->dp, + qstate->region, &qstate->qinfo)) { + /* got parent stuff from cache, see if we can continue */ + verbose(VERB_ALGO, "try parent-side glue from cache"); + return next_state(iq, QUERYTARGETS_STATE); + } + /* query for an extra name added by the parent-NS record */ + if(delegpt_count_missing_targets(iq->dp) > 0) { + int qs = 0; + verbose(VERB_ALGO, "try parent-side target name"); + if(!query_for_targets(qstate, iq, ie, id, 1, &qs)) { + return error_response(qstate, id, LDNS_RCODE_SERVFAIL); + } + iq->num_target_queries += qs; + if(qs != 0) { + qstate->ext_state[id] = module_wait_subquery; + return 0; /* and wait for them */ + } + } + if(iq->depth == ie->max_dependency_depth) { + verbose(VERB_QUERY, "maxdepth and need more nameservers, fail"); + return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL); + } + /* mark cycle targets for parent-side lookups */ + iter_mark_pside_cycle_targets(qstate, iq->dp); + /* see if we can issue queries to get nameserver addresses */ + /* this lookup is not randomized, but sequential. */ + for(ns = iq->dp->nslist; ns; ns = ns->next) { + /* query for parent-side A and AAAA for nameservers */ + if(ie->supports_ipv6 && !ns->done_pside6) { + /* Send the AAAA request. */ + if(!generate_parentside_target_query(qstate, iq, id, + ns->name, ns->namelen, + LDNS_RR_TYPE_AAAA, iq->qchase.qclass)) + return error_response(qstate, id, + LDNS_RCODE_SERVFAIL); + ns->done_pside6 = 1; + query_count++; + } + if(ie->supports_ipv4 && !ns->done_pside4) { + /* Send the A request. */ + if(!generate_parentside_target_query(qstate, iq, id, + ns->name, ns->namelen, + LDNS_RR_TYPE_A, iq->qchase.qclass)) + return error_response(qstate, id, + LDNS_RCODE_SERVFAIL); + ns->done_pside4 = 1; + query_count++; + } + if(query_count != 0) { /* suspend to await results */ + verbose(VERB_ALGO, "try parent-side glue lookup"); + iq->num_target_queries += query_count; + qstate->ext_state[id] = module_wait_subquery; + return 0; + } + } + + /* if this was a parent-side glue query itself, then store that + * failure in cache. */ + if(iq->query_for_pside_glue && !iq->pside_glue) + iter_store_parentside_neg(qstate->env, &qstate->qinfo, + iq->deleg_msg?iq->deleg_msg->rep: + (iq->response?iq->response->rep:NULL)); + + verbose(VERB_QUERY, "out of query targets -- returning SERVFAIL"); + /* fail -- no more targets, no more hope of targets, no hope + * of a response. */ + return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL); +} + +/** + * Try to find the NS record set that will resolve a qtype DS query. Due + * to grandparent/grandchild reasons we did not get a proper lookup right + * away. We need to create type NS queries until we get the right parent + * for this lookup. We remove labels from the query to find the right point. + * If we end up at the old dp name, then there is no solution. + * + * @param qstate: query state. + * @param iq: iterator query state. + * @param id: module id. + * @return true if the event requires more immediate processing, false if + * not. This is generally only true when forwarding the request to + * the final state (i.e., on answer). + */ +static int +processDSNSFind(struct module_qstate* qstate, struct iter_qstate* iq, + int id) +{ + struct module_qstate* subq = NULL; + verbose(VERB_ALGO, "processDSNSFind"); + + if(!iq->dsns_point) { + /* initialize */ + iq->dsns_point = iq->qchase.qname; + iq->dsns_point_len = iq->qchase.qname_len; + } + /* robustcheck for internal error: we are not underneath the dp */ + if(!dname_subdomain_c(iq->dsns_point, iq->dp->name)) { + return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL); + } + + /* go up one (more) step, until we hit the dp, if so, end */ + dname_remove_label(&iq->dsns_point, &iq->dsns_point_len); + if(query_dname_compare(iq->dsns_point, iq->dp->name) == 0) { + /* there was no inbetween nameserver, use the old delegation + * point again. And this time, because dsns_point is nonNULL + * we are going to accept the (bad) result */ + iq->state = QUERYTARGETS_STATE; + return 1; + } + iq->state = DSNS_FIND_STATE; + + /* spawn NS lookup (validation not needed, this is for DS lookup) */ + log_nametypeclass(VERB_ALGO, "fetch nameservers", + iq->dsns_point, LDNS_RR_TYPE_NS, iq->qchase.qclass); + if(!generate_sub_request(iq->dsns_point, iq->dsns_point_len, + LDNS_RR_TYPE_NS, iq->qchase.qclass, qstate, id, iq, + INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0)) { + return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL); + } + + return 0; +} + +/** + * This is the request event state where the request will be sent to one of + * its current query targets. This state also handles issuing target lookup + * queries for missing target IP addresses. Queries typically iterate on + * this state, both when they are just trying different targets for a given + * delegation point, and when they change delegation points. This state + * roughly corresponds to RFC 1034 algorithm steps 3 and 4. + * + * @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 +processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, + struct iter_env* ie, int id) +{ + int tf_policy; + struct delegpt_addr* target; + struct outbound_entry* outq; + + /* NOTE: a request will encounter this state for each target it + * needs to send a query to. That is, at least one per referral, + * more if some targets timeout or return throwaway answers. */ + + log_query_info(VERB_QUERY, "processQueryTargets:", &qstate->qinfo); + verbose(VERB_ALGO, "processQueryTargets: targetqueries %d, " + "currentqueries %d sentcount %d", iq->num_target_queries, + iq->num_current_queries, iq->sent_count); + + /* Make sure that we haven't run away */ + /* FIXME: is this check even necessary? */ + if(iq->referral_count > MAX_REFERRAL_COUNT) { + verbose(VERB_QUERY, "request has exceeded the maximum " + "number of referrrals with %d", iq->referral_count); + return error_response(qstate, id, LDNS_RCODE_SERVFAIL); + } + if(iq->sent_count > MAX_SENT_COUNT) { + verbose(VERB_QUERY, "request has exceeded the maximum " + "number of sends with %d", iq->sent_count); + return error_response(qstate, id, LDNS_RCODE_SERVFAIL); + } + + /* Make sure we have a delegation point, otherwise priming failed + * or another failure occurred */ + if(!iq->dp) { + verbose(VERB_QUERY, "Failed to get a delegation, giving up"); + return error_response(qstate, id, LDNS_RCODE_SERVFAIL); + } + if(!ie->supports_ipv6) + delegpt_no_ipv6(iq->dp); + if(!ie->supports_ipv4) + delegpt_no_ipv4(iq->dp); + delegpt_log(VERB_ALGO, iq->dp); + + if(iq->num_current_queries>0) { + /* already busy answering a query, this restart is because + * more delegpt addrs became available, wait for existing + * query. */ + verbose(VERB_ALGO, "woke up, but wait for outstanding query"); + qstate->ext_state[id] = module_wait_reply; + return 0; + } + + tf_policy = 0; + /* < not <=, because although the array is large enough for <=, the + * generated query will immediately be discarded due to depth and + * that servfail is cached, which is not good as opportunism goes. */ + if(iq->depth < ie->max_dependency_depth + && iq->sent_count < TARGET_FETCH_STOP) { + tf_policy = ie->target_fetch_policy[iq->depth]; + } + + /* if in 0x20 fallback get as many targets as possible */ + if(iq->caps_fallback) { + int extra = 0; + size_t naddr, nres, navail; + if(!query_for_targets(qstate, iq, ie, id, -1, &extra)) { + return error_response(qstate, id, LDNS_RCODE_SERVFAIL); + } + iq->num_target_queries += extra; + if(iq->num_target_queries > 0) { + /* wait to get all targets, we want to try em */ + verbose(VERB_ALGO, "wait for all targets for fallback"); + qstate->ext_state[id] = module_wait_reply; + return 0; + } + /* did we do enough fallback queries already? */ + delegpt_count_addr(iq->dp, &naddr, &nres, &navail); + /* the current caps_server is the number of fallbacks sent. + * the original query is one that matched too, so we have + * caps_server+1 number of matching queries now */ + if(iq->caps_server+1 >= naddr*3 || + iq->caps_server+1 >= MAX_SENT_COUNT) { + /* we're done, process the response */ + verbose(VERB_ALGO, "0x20 fallback had %d responses " + "match for %d wanted, done.", + (int)iq->caps_server+1, (int)naddr*3); + iq->caps_fallback = 0; + iter_dec_attempts(iq->dp, 3); /* space for fallback */ + iq->num_current_queries++; /* RespState decrements it*/ + iq->referral_count++; /* make sure we don't loop */ + iq->sent_count = 0; + iq->state = QUERY_RESP_STATE; + return 1; + } + verbose(VERB_ALGO, "0x20 fallback number %d", + (int)iq->caps_server); + + /* if there is a policy to fetch missing targets + * opportunistically, do it. we rely on the fact that once a + * query (or queries) for a missing name have been issued, + * they will not show up again. */ + } else if(tf_policy != 0) { + int extra = 0; + verbose(VERB_ALGO, "attempt to get extra %d targets", + tf_policy); + (void)query_for_targets(qstate, iq, ie, id, tf_policy, &extra); + /* errors ignored, these targets are not strictly necessary for + * this result, we do not have to reply with SERVFAIL */ + iq->num_target_queries += extra; + } + + /* Add the current set of unused targets to our queue. */ + delegpt_add_unused_targets(iq->dp); + + /* Select the next usable target, filtering out unsuitable targets. */ + target = iter_server_selection(ie, qstate->env, iq->dp, + iq->dp->name, iq->dp->namelen, iq->qchase.qtype, + &iq->dnssec_lame_query, &iq->chase_to_rd, + iq->num_target_queries, qstate->blacklist); + + /* If no usable target was selected... */ + if(!target) { + /* Here we distinguish between three states: generate a new + * target query, just wait, or quit (with a SERVFAIL). + * We have the following information: number of active + * target queries, number of active current queries, + * the presence of missing targets at this delegation + * point, and the given query target policy. */ + + /* Check for the wait condition. If this is true, then + * an action must be taken. */ + if(iq->num_target_queries==0 && iq->num_current_queries==0) { + /* If there is nothing to wait for, then we need + * to distinguish between generating (a) new target + * query, or failing. */ + if(delegpt_count_missing_targets(iq->dp) > 0) { + int qs = 0; + verbose(VERB_ALGO, "querying for next " + "missing target"); + if(!query_for_targets(qstate, iq, ie, id, + 1, &qs)) { + return error_response(qstate, id, + LDNS_RCODE_SERVFAIL); + } + if(qs == 0 && + delegpt_count_missing_targets(iq->dp) == 0){ + /* it looked like there were missing + * targets, but they did not turn up. + * Try the bad choices again (if any), + * when we get back here missing==0, + * so this is not a loop. */ + return 1; + } + iq->num_target_queries += qs; + } + /* Since a target query might have been made, we + * need to check again. */ + if(iq->num_target_queries == 0) { + return processLastResort(qstate, iq, ie, id); + } + } + + /* otherwise, we have no current targets, so submerge + * until one of the target or direct queries return. */ + if(iq->num_target_queries>0 && iq->num_current_queries>0) { + verbose(VERB_ALGO, "no current targets -- waiting " + "for %d targets to resolve or %d outstanding" + " queries to respond", iq->num_target_queries, + iq->num_current_queries); + qstate->ext_state[id] = module_wait_reply; + } else if(iq->num_target_queries>0) { + verbose(VERB_ALGO, "no current targets -- waiting " + "for %d targets to resolve.", + iq->num_target_queries); + qstate->ext_state[id] = module_wait_subquery; + } else { + verbose(VERB_ALGO, "no current targets -- waiting " + "for %d outstanding queries to respond.", + iq->num_current_queries); + qstate->ext_state[id] = module_wait_reply; + } + return 0; + } + + /* We have a valid target. */ + if(verbosity >= VERB_QUERY) { + log_query_info(VERB_QUERY, "sending query:", &iq->qchase); + log_name_addr(VERB_QUERY, "sending to target:", iq->dp->name, + &target->addr, target->addrlen); + verbose(VERB_ALGO, "dnssec status: %s%s", + iq->dnssec_expected?"expected": "not expected", + iq->dnssec_lame_query?" but lame_query anyway": ""); + } + fptr_ok(fptr_whitelist_modenv_send_query(qstate->env->send_query)); + outq = (*qstate->env->send_query)( + iq->qchase.qname, iq->qchase.qname_len, + iq->qchase.qtype, iq->qchase.qclass, + iq->chase_flags | (iq->chase_to_rd?BIT_RD:0), EDNS_DO|BIT_CD, + iq->dnssec_expected, &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); + return next_state(iq, QUERYTARGETS_STATE); + } + outbound_list_insert(&iq->outlist, outq); + iq->num_current_queries++; + iq->sent_count++; + qstate->ext_state[id] = module_wait_reply; + + return 0; +} + +/** find NS rrset in given list */ +static struct ub_packed_rrset_key* +find_NS(struct reply_info* rep, size_t from, size_t to) +{ + size_t i; + for(i=from; irrsets[i]->rk.type) == LDNS_RR_TYPE_NS) + return rep->rrsets[i]; + } + return NULL; +} + + +/** + * Process the query response. All queries end up at this state first. This + * process generally consists of analyzing the response and routing the + * event to the next state (either bouncing it back to a request state, or + * terminating the processing for this event). + * + * @param qstate: query state. + * @param iq: iterator query state. + * @param id: module id. + * @return true if the event requires more immediate processing, false if + * not. This is generally only true when forwarding the request to + * the final state (i.e., on answer). + */ +static int +processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, + int id) +{ + int dnsseclame = 0; + enum response_type type; + iq->num_current_queries--; + if(iq->response == NULL) { + iq->chase_to_rd = 0; + iq->dnssec_lame_query = 0; + verbose(VERB_ALGO, "query response was timeout"); + return next_state(iq, QUERYTARGETS_STATE); + } + type = response_type_from_server( + (int)((iq->chase_flags&BIT_RD) || iq->chase_to_rd), + iq->response, &iq->qchase, iq->dp); + iq->chase_to_rd = 0; + if(type == RESPONSE_TYPE_REFERRAL && (iq->chase_flags&BIT_RD)) { + /* When forwarding (RD bit is set), we handle referrals + * differently. No queries should be sent elsewhere */ + type = RESPONSE_TYPE_ANSWER; + } + if(iq->dnssec_expected && !iq->dnssec_lame_query && + !(iq->chase_flags&BIT_RD) + && type != RESPONSE_TYPE_LAME + && type != RESPONSE_TYPE_REC_LAME + && type != RESPONSE_TYPE_THROWAWAY + && type != RESPONSE_TYPE_UNTYPED) { + /* a possible answer, see if it is missing DNSSEC */ + /* but not when forwarding, so we dont mark fwder lame */ + /* also make sure the answer is from the zone we expected, + * otherwise, (due to parent,child on same server), we + * might mark the server,zone lame inappropriately */ + if(!iter_msg_has_dnssec(iq->response) && + iter_msg_from_zone(iq->response, iq->dp, type, + iq->qchase.qclass)) { + type = RESPONSE_TYPE_LAME; + dnsseclame = 1; + } + } else iq->dnssec_lame_query = 0; + /* see if referral brings us close to the target */ + if(type == RESPONSE_TYPE_REFERRAL) { + struct ub_packed_rrset_key* ns = find_NS( + iq->response->rep, iq->response->rep->an_numrrsets, + iq->response->rep->an_numrrsets + + iq->response->rep->ns_numrrsets); + if(!ns) ns = find_NS(iq->response->rep, 0, + iq->response->rep->an_numrrsets); + if(!ns || !dname_strict_subdomain_c(ns->rk.dname, iq->dp->name) + || !dname_subdomain_c(iq->qchase.qname, ns->rk.dname)){ + verbose(VERB_ALGO, "bad referral, throwaway"); + type = RESPONSE_TYPE_THROWAWAY; + } else + iter_scrub_ds(iq->response, ns, iq->dp->name); + } else iter_scrub_ds(iq->response, NULL, NULL); + + /* handle each of the type cases */ + if(type == RESPONSE_TYPE_ANSWER) { + /* ANSWER type responses terminate the query algorithm, + * so they sent on their */ + if(verbosity >= VERB_DETAIL) { + verbose(VERB_DETAIL, "query response was %s", + FLAGS_GET_RCODE(iq->response->rep->flags) + ==LDNS_RCODE_NXDOMAIN?"NXDOMAIN ANSWER": + (iq->response->rep->an_numrrsets?"ANSWER": + "nodata ANSWER")); + } + /* if qtype is DS, check we have the right level of answer, + * like grandchild answer but we need the middle, reject it */ + if(iq->qchase.qtype == LDNS_RR_TYPE_DS && !iq->dsns_point + && !(iq->chase_flags&BIT_RD) + && iter_ds_toolow(iq->response, iq->dp) + && iter_dp_cangodown(&iq->qchase, iq->dp)) + return processDSNSFind(qstate, iq, id); + if(!iter_dns_store(qstate->env, &iq->response->qinfo, + iq->response->rep, 0, qstate->prefetch_leeway, + iq->dp&&iq->dp->has_parent_side_NS, + qstate->region)) + return error_response(qstate, id, LDNS_RCODE_SERVFAIL); + /* close down outstanding requests to be discarded */ + outbound_list_clear(&iq->outlist); + iq->num_current_queries = 0; + fptr_ok(fptr_whitelist_modenv_detach_subs( + qstate->env->detach_subs)); + (*qstate->env->detach_subs)(qstate); + iq->num_target_queries = 0; + if(qstate->reply) + sock_list_insert(&qstate->reply_origin, + &qstate->reply->addr, qstate->reply->addrlen, + qstate->region); + return final_state(iq); + } else if(type == RESPONSE_TYPE_REFERRAL) { + /* REFERRAL type responses get a reset of the + * delegation point, and back to the QUERYTARGETS_STATE. */ + verbose(VERB_DETAIL, "query response was REFERRAL"); + + /* if hardened, only store referral if we asked for it */ + if(!qstate->env->cfg->harden_referral_path || + ( qstate->qinfo.qtype == LDNS_RR_TYPE_NS + && (qstate->query_flags&BIT_RD) + && !(qstate->query_flags&BIT_CD) + /* we know that all other NS rrsets are scrubbed + * away, thus on referral only one is left. + * see if that equals the query name... */ + && ( /* auth section, but sometimes in answer section*/ + reply_find_rrset_section_ns(iq->response->rep, + iq->qchase.qname, iq->qchase.qname_len, + LDNS_RR_TYPE_NS, iq->qchase.qclass) + || reply_find_rrset_section_an(iq->response->rep, + iq->qchase.qname, iq->qchase.qname_len, + LDNS_RR_TYPE_NS, iq->qchase.qclass) + ) + )) { + /* Store the referral under the current query */ + /* no prefetch-leeway, since its not the answer */ + if(!iter_dns_store(qstate->env, &iq->response->qinfo, + iq->response->rep, 1, 0, 0, NULL)) + return error_response(qstate, id, + LDNS_RCODE_SERVFAIL); + if(iq->store_parent_NS) + iter_store_parentside_NS(qstate->env, + iq->response->rep); + if(qstate->env->neg_cache) + val_neg_addreferral(qstate->env->neg_cache, + iq->response->rep, iq->dp->name); + } + /* store parent-side-in-zone-glue, if directly queried for */ + if(iq->query_for_pside_glue && !iq->pside_glue) { + iq->pside_glue = reply_find_rrset(iq->response->rep, + iq->qchase.qname, iq->qchase.qname_len, + iq->qchase.qtype, iq->qchase.qclass); + if(iq->pside_glue) { + log_rrset_key(VERB_ALGO, "found parent-side " + "glue", iq->pside_glue); + iter_store_parentside_rrset(qstate->env, + iq->pside_glue); + } + } + + /* Reset the event state, setting the current delegation + * point to the referral. */ + iq->deleg_msg = iq->response; + iq->dp = delegpt_from_message(iq->response, qstate->region); + if(!iq->dp) + return error_response(qstate, id, LDNS_RCODE_SERVFAIL); + if(!cache_fill_missing(qstate->env, iq->qchase.qclass, + qstate->region, iq->dp)) + return error_response(qstate, id, LDNS_RCODE_SERVFAIL); + if(iq->store_parent_NS && query_dname_compare(iq->dp->name, + iq->store_parent_NS->name) == 0) + iter_merge_retry_counts(iq->dp, iq->store_parent_NS); + delegpt_log(VERB_ALGO, iq->dp); + /* Count this as a referral. */ + iq->referral_count++; + iq->sent_count = 0; + /* see if the next dp is a trust anchor, or a DS was sent + * along, indicating dnssec is expected for next zone */ + iq->dnssec_expected = iter_indicates_dnssec(qstate->env, + iq->dp, iq->response, iq->qchase.qclass); + /* if dnssec, validating then also fetch the key for the DS */ + if(iq->dnssec_expected && qstate->env->cfg->prefetch_key && + !(qstate->query_flags&BIT_CD)) + generate_dnskey_prefetch(qstate, iq, id); + + /* spawn off NS and addr to auth servers for the NS we just + * got in the referral. This gets authoritative answer + * (answer section trust level) rrset. + * right after, we detach the subs, answer goes to cache. */ + if(qstate->env->cfg->harden_referral_path) + generate_ns_check(qstate, iq, id); + + /* stop current outstanding queries. + * FIXME: should the outstanding queries be waited for and + * handled? Say by a subquery that inherits the outbound_entry. + */ + outbound_list_clear(&iq->outlist); + iq->num_current_queries = 0; + fptr_ok(fptr_whitelist_modenv_detach_subs( + qstate->env->detach_subs)); + (*qstate->env->detach_subs)(qstate); + iq->num_target_queries = 0; + verbose(VERB_ALGO, "cleared outbound list for next round"); + return next_state(iq, QUERYTARGETS_STATE); + } else if(type == RESPONSE_TYPE_CNAME) { + uint8_t* sname = NULL; + size_t snamelen = 0; + /* CNAME type responses get a query restart (i.e., get a + * reset of the query state and go back to INIT_REQUEST_STATE). + */ + verbose(VERB_DETAIL, "query response was CNAME"); + if(verbosity >= VERB_ALGO) + log_dns_msg("cname msg", &iq->response->qinfo, + iq->response->rep); + /* if qtype is DS, check we have the right level of answer, + * like grandchild answer but we need the middle, reject it */ + if(iq->qchase.qtype == LDNS_RR_TYPE_DS && !iq->dsns_point + && !(iq->chase_flags&BIT_RD) + && iter_ds_toolow(iq->response, iq->dp) + && iter_dp_cangodown(&iq->qchase, iq->dp)) + return processDSNSFind(qstate, iq, id); + /* Process the CNAME response. */ + if(!handle_cname_response(qstate, iq, iq->response, + &sname, &snamelen)) + return error_response(qstate, id, LDNS_RCODE_SERVFAIL); + /* cache the CNAME response under the current query */ + /* NOTE : set referral=1, so that rrsets get stored but not + * the partial query answer (CNAME only). */ + /* prefetchleeway applied because this updates answer parts */ + if(!iter_dns_store(qstate->env, &iq->response->qinfo, + iq->response->rep, 1, qstate->prefetch_leeway, + iq->dp&&iq->dp->has_parent_side_NS, NULL)) + return error_response(qstate, id, LDNS_RCODE_SERVFAIL); + /* set the current request's qname to the new value. */ + iq->qchase.qname = sname; + iq->qchase.qname_len = snamelen; + /* Clear the query state, since this is a query restart. */ + iq->deleg_msg = NULL; + iq->dp = NULL; + iq->dsns_point = NULL; + /* Note the query restart. */ + iq->query_restart_count++; + iq->sent_count = 0; + + /* stop current outstanding queries. + * FIXME: should the outstanding queries be waited for and + * handled? Say by a subquery that inherits the outbound_entry. + */ + outbound_list_clear(&iq->outlist); + iq->num_current_queries = 0; + fptr_ok(fptr_whitelist_modenv_detach_subs( + qstate->env->detach_subs)); + (*qstate->env->detach_subs)(qstate); + iq->num_target_queries = 0; + if(qstate->reply) + sock_list_insert(&qstate->reply_origin, + &qstate->reply->addr, qstate->reply->addrlen, + qstate->region); + verbose(VERB_ALGO, "cleared outbound list for query restart"); + /* go to INIT_REQUEST_STATE for new qname. */ + return next_state(iq, INIT_REQUEST_STATE); + } else if(type == RESPONSE_TYPE_LAME) { + /* Cache the LAMEness. */ + verbose(VERB_DETAIL, "query response was %sLAME", + dnsseclame?"DNSSEC ":""); + if(!dname_subdomain_c(iq->qchase.qname, iq->dp->name)) { + log_err("mark lame: mismatch in qname and dpname"); + /* throwaway this reply below */ + } else if(qstate->reply) { + /* need addr for lameness cache, but we may have + * gotten this from cache, so test to be sure */ + if(!infra_set_lame(qstate->env->infra_cache, + &qstate->reply->addr, qstate->reply->addrlen, + iq->dp->name, iq->dp->namelen, + *qstate->env->now, dnsseclame, 0, + iq->qchase.qtype)) + log_err("mark host lame: out of memory"); + } else log_err("%slame response from cache", + dnsseclame?"DNSSEC ":""); + } else if(type == RESPONSE_TYPE_REC_LAME) { + /* Cache the LAMEness. */ + verbose(VERB_DETAIL, "query response REC_LAME: " + "recursive but not authoritative server"); + if(!dname_subdomain_c(iq->qchase.qname, iq->dp->name)) { + log_err("mark rec_lame: mismatch in qname and dpname"); + /* throwaway this reply below */ + } else if(qstate->reply) { + /* need addr for lameness cache, but we may have + * gotten this from cache, so test to be sure */ + verbose(VERB_DETAIL, "mark as REC_LAME"); + if(!infra_set_lame(qstate->env->infra_cache, + &qstate->reply->addr, qstate->reply->addrlen, + iq->dp->name, iq->dp->namelen, + *qstate->env->now, 0, 1, iq->qchase.qtype)) + log_err("mark host lame: out of memory"); + } + } else if(type == RESPONSE_TYPE_THROWAWAY) { + /* LAME and THROWAWAY responses are handled the same way. + * In this case, the event is just sent directly back to + * the QUERYTARGETS_STATE without resetting anything, + * because, clearly, the next target must be tried. */ + verbose(VERB_DETAIL, "query response was THROWAWAY"); + } else { + log_warn("A query response came back with an unknown type: %d", + (int)type); + } + + /* LAME, THROWAWAY and "unknown" all end up here. + * Recycle to the QUERYTARGETS state to hopefully try a + * different target. */ + return next_state(iq, QUERYTARGETS_STATE); +} + +/** + * Return priming query results to interestes super querystates. + * + * Sets the delegation point and delegation message (not nonRD queries). + * This is a callback from walk_supers. + * + * @param qstate: priming query state that finished. + * @param id: module id. + * @param forq: the qstate for which priming has been done. + */ +static void +prime_supers(struct module_qstate* qstate, int id, struct module_qstate* forq) +{ + struct iter_qstate* foriq = (struct iter_qstate*)forq->minfo[id]; + struct delegpt* dp = NULL; + + log_assert(qstate->is_priming || foriq->wait_priming_stub); + log_assert(qstate->return_rcode == LDNS_RCODE_NOERROR); + /* Convert our response to a delegation point */ + dp = delegpt_from_message(qstate->return_msg, forq->region); + if(!dp) { + /* if there is no convertable delegation point, then + * the ANSWER type was (presumably) a negative answer. */ + verbose(VERB_ALGO, "prime response was not a positive " + "ANSWER; failing"); + foriq->dp = NULL; + foriq->state = QUERYTARGETS_STATE; + return; + } + + log_query_info(VERB_DETAIL, "priming successful for", &qstate->qinfo); + delegpt_log(VERB_ALGO, dp); + foriq->dp = dp; + foriq->deleg_msg = dns_copy_msg(qstate->return_msg, forq->region); + if(!foriq->deleg_msg) { + log_err("copy prime response: out of memory"); + foriq->dp = NULL; + foriq->state = QUERYTARGETS_STATE; + return; + } + + /* root priming responses go to init stage 2, priming stub + * responses to to stage 3. */ + if(foriq->wait_priming_stub) { + foriq->state = INIT_REQUEST_3_STATE; + foriq->wait_priming_stub = 0; + } else foriq->state = INIT_REQUEST_2_STATE; + /* because we are finished, the parent will be reactivated */ +} + +/** + * This handles the response to a priming query. This is used to handle both + * root and stub priming responses. This is basically the equivalent of the + * QUERY_RESP_STATE, but will not handle CNAME responses and will treat + * REFERRALs as ANSWERS. It will also update and reactivate the originating + * event. + * + * @param qstate: query state. + * @param id: module id. + * @return true if the event needs more immediate processing, false if not. + * This state always returns false. + */ +static int +processPrimeResponse(struct module_qstate* qstate, int id) +{ + struct iter_qstate* iq = (struct iter_qstate*)qstate->minfo[id]; + enum response_type type; + iq->response->rep->flags &= ~(BIT_RD|BIT_RA); /* ignore rec-lame */ + type = response_type_from_server( + (int)((iq->chase_flags&BIT_RD) || iq->chase_to_rd), + iq->response, &iq->qchase, iq->dp); + if(type == RESPONSE_TYPE_ANSWER) { + qstate->return_rcode = LDNS_RCODE_NOERROR; + qstate->return_msg = iq->response; + } else { + qstate->return_rcode = LDNS_RCODE_SERVFAIL; + qstate->return_msg = NULL; + } + + /* validate the root or stub after priming (if enabled). + * This is the same query as the prime query, but with validation. + * Now that we are primed, the additional queries that validation + * may need can be resolved, such as DLV. */ + if(qstate->env->cfg->harden_referral_path) { + struct module_qstate* subq = NULL; + log_nametypeclass(VERB_ALGO, "schedule prime validation", + qstate->qinfo.qname, qstate->qinfo.qtype, + qstate->qinfo.qclass); + if(!generate_sub_request(qstate->qinfo.qname, + qstate->qinfo.qname_len, qstate->qinfo.qtype, + qstate->qinfo.qclass, qstate, id, iq, + INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1)) { + verbose(VERB_ALGO, "could not generate prime check"); + } + generate_a_aaaa_check(qstate, iq, id); + } + + /* This event is finished. */ + qstate->ext_state[id] = module_finished; + return 0; +} + +/** + * Do final processing on responses to target queries. Events reach this + * state after the iterative resolution algorithm terminates. This state is + * responsible for reactiving the original event, and housekeeping related + * to received target responses (caching, updating the current delegation + * point, etc). + * Callback from walk_supers for every super state that is interested in + * the results from this query. + * + * @param qstate: query state. + * @param id: module id. + * @param forq: super query state. + */ +static void +processTargetResponse(struct module_qstate* qstate, int id, + struct module_qstate* forq) +{ + struct iter_qstate* iq = (struct iter_qstate*)qstate->minfo[id]; + struct iter_qstate* foriq = (struct iter_qstate*)forq->minfo[id]; + struct ub_packed_rrset_key* rrset; + struct delegpt_ns* dpns; + log_assert(qstate->return_rcode == LDNS_RCODE_NOERROR); + + foriq->state = QUERYTARGETS_STATE; + log_query_info(VERB_ALGO, "processTargetResponse", &qstate->qinfo); + log_query_info(VERB_ALGO, "processTargetResponse super", &forq->qinfo); + + /* check to see if parent event is still interested (in orig name). */ + if(!foriq->dp) { + verbose(VERB_ALGO, "subq: parent not interested, was reset"); + return; /* not interested anymore */ + } + dpns = delegpt_find_ns(foriq->dp, qstate->qinfo.qname, + qstate->qinfo.qname_len); + if(!dpns) { + /* If not interested, just stop processing this event */ + verbose(VERB_ALGO, "subq: parent not interested anymore"); + /* could be because parent was jostled out of the cache, + and a new identical query arrived, that does not want it*/ + 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, + * the done_pside is already set when created and a cache + * entry created in processFinished so nothing to do here */ + log_rrset_key(VERB_ALGO, "add parentside glue to dp", + iq->pside_glue); + if(!delegpt_add_rrset(foriq->dp, forq->region, + iq->pside_glue, 1)) + log_err("out of memory adding pside glue"); + } + + /* This response is relevant to the current query, so we + * add (attempt to add, anyway) this target(s) and reactivate + * the original event. + * NOTE: we could only look for the AnswerRRset if the + * response type was ANSWER. */ + rrset = reply_find_answer_rrset(&iq->qchase, qstate->return_msg->rep); + if(rrset) { + /* if CNAMEs have been followed - add new NS to delegpt. */ + /* BTW. RFC 1918 says NS should not have got CNAMEs. Robust. */ + if(!delegpt_find_ns(foriq->dp, rrset->rk.dname, + rrset->rk.dname_len)) { + /* if dpns->lame then set newcname ns lame too */ + if(!delegpt_add_ns(foriq->dp, forq->region, + rrset->rk.dname, (int)dpns->lame)) + log_err("out of memory adding cnamed-ns"); + } + /* if dpns->lame then set the address(es) lame too */ + if(!delegpt_add_rrset(foriq->dp, forq->region, rrset, + (int)dpns->lame)) + log_err("out of memory adding targets"); + verbose(VERB_ALGO, "added target response"); + delegpt_log(VERB_ALGO, foriq->dp); + } else { + verbose(VERB_ALGO, "iterator TargetResponse failed"); + dpns->resolved = 1; /* fail the target */ + } +} + +/** + * Process response for DS NS Find queries, that attempt to find the delegation + * point where we ask the DS query from. + * + * @param qstate: query state. + * @param id: module id. + * @param forq: super query state. + */ +static void +processDSNSResponse(struct module_qstate* qstate, int id, + struct module_qstate* forq) +{ + struct iter_qstate* foriq = (struct iter_qstate*)forq->minfo[id]; + + /* if the finished (iq->response) query has no NS set: continue + * up to look for the right dp; nothing to change, do DPNSstate */ + if(qstate->return_rcode != LDNS_RCODE_NOERROR) + return; /* seek further */ + /* find the NS RRset (without allowing CNAMEs) */ + if(!reply_find_rrset(qstate->return_msg->rep, qstate->qinfo.qname, + qstate->qinfo.qname_len, LDNS_RR_TYPE_NS, + qstate->qinfo.qclass)){ + return; /* seek further */ + } + + /* else, store as DP and continue at querytargets */ + foriq->state = QUERYTARGETS_STATE; + foriq->dp = delegpt_from_message(qstate->return_msg, forq->region); + if(!foriq->dp) { + log_err("out of memory in dsns dp alloc"); + return; /* dp==NULL in QUERYTARGETS makes SERVFAIL */ + } + /* success, go query the querytargets in the new dp (and go down) */ +} + +/** + * Process response for qclass=ANY queries for a particular class. + * Append to result or error-exit. + * + * @param qstate: query state. + * @param id: module id. + * @param forq: super query state. + */ +static void +processClassResponse(struct module_qstate* qstate, int id, + struct module_qstate* forq) +{ + struct iter_qstate* foriq = (struct iter_qstate*)forq->minfo[id]; + struct dns_msg* from = qstate->return_msg; + log_query_info(VERB_ALGO, "processClassResponse", &qstate->qinfo); + log_query_info(VERB_ALGO, "processClassResponse super", &forq->qinfo); + if(qstate->return_rcode != LDNS_RCODE_NOERROR) { + /* cause servfail for qclass ANY query */ + foriq->response = NULL; + foriq->state = FINISHED_STATE; + return; + } + /* append result */ + if(!foriq->response) { + /* allocate the response: copy RCODE, sec_state */ + foriq->response = dns_copy_msg(from, forq->region); + if(!foriq->response) { + log_err("malloc failed for qclass ANY response"); + foriq->state = FINISHED_STATE; + return; + } + foriq->response->qinfo.qclass = forq->qinfo.qclass; + /* qclass ANY does not receive the AA flag on replies */ + foriq->response->rep->authoritative = 0; + } else { + struct dns_msg* to = foriq->response; + /* add _from_ this response _to_ existing collection */ + /* if there are records, copy RCODE */ + /* lower sec_state if this message is lower */ + if(from->rep->rrset_count != 0) { + size_t n = from->rep->rrset_count+to->rep->rrset_count; + struct ub_packed_rrset_key** dest, **d; + /* copy appropriate rcode */ + to->rep->flags = from->rep->flags; + /* copy rrsets */ + dest = regional_alloc(forq->region, sizeof(dest[0])*n); + if(!dest) { + log_err("malloc failed in collect ANY"); + foriq->state = FINISHED_STATE; + return; + } + d = dest; + /* copy AN */ + memcpy(dest, to->rep->rrsets, to->rep->an_numrrsets + * sizeof(dest[0])); + dest += to->rep->an_numrrsets; + memcpy(dest, from->rep->rrsets, from->rep->an_numrrsets + * sizeof(dest[0])); + dest += from->rep->an_numrrsets; + /* copy NS */ + memcpy(dest, to->rep->rrsets+to->rep->an_numrrsets, + to->rep->ns_numrrsets * sizeof(dest[0])); + dest += to->rep->ns_numrrsets; + memcpy(dest, from->rep->rrsets+from->rep->an_numrrsets, + from->rep->ns_numrrsets * sizeof(dest[0])); + dest += from->rep->ns_numrrsets; + /* copy AR */ + memcpy(dest, to->rep->rrsets+to->rep->an_numrrsets+ + to->rep->ns_numrrsets, + to->rep->ar_numrrsets * sizeof(dest[0])); + dest += to->rep->ar_numrrsets; + memcpy(dest, from->rep->rrsets+from->rep->an_numrrsets+ + from->rep->ns_numrrsets, + from->rep->ar_numrrsets * sizeof(dest[0])); + /* update counts */ + to->rep->rrsets = d; + to->rep->an_numrrsets += from->rep->an_numrrsets; + to->rep->ns_numrrsets += from->rep->ns_numrrsets; + to->rep->ar_numrrsets += from->rep->ar_numrrsets; + to->rep->rrset_count = n; + } + if(from->rep->security < to->rep->security) /* lowest sec */ + to->rep->security = from->rep->security; + if(from->rep->qdcount != 0) /* insert qd if appropriate */ + to->rep->qdcount = from->rep->qdcount; + if(from->rep->ttl < to->rep->ttl) /* use smallest TTL */ + to->rep->ttl = from->rep->ttl; + if(from->rep->prefetch_ttl < to->rep->prefetch_ttl) + to->rep->prefetch_ttl = from->rep->prefetch_ttl; + } + /* are we done? */ + foriq->num_current_queries --; + if(foriq->num_current_queries == 0) + foriq->state = FINISHED_STATE; +} + +/** + * Collect class ANY responses and make them into one response. This + * state is started and it creates queries for all classes (that have + * root hints). The answers are then collected. + * + * @param qstate: query state. + * @param id: module id. + * @return true if the event needs more immediate processing, false if not. + */ +static int +processCollectClass(struct module_qstate* qstate, int id) +{ + struct iter_qstate* iq = (struct iter_qstate*)qstate->minfo[id]; + struct module_qstate* subq; + /* If qchase.qclass == 0 then send out queries for all classes. + * Otherwise, do nothing (wait for all answers to arrive and the + * processClassResponse to put them together, and that moves us + * towards the Finished state when done. */ + if(iq->qchase.qclass == 0) { + uint16_t c = 0; + iq->qchase.qclass = LDNS_RR_CLASS_ANY; + while(iter_get_next_root(qstate->env->hints, + qstate->env->fwds, &c)) { + /* generate query for this class */ + log_nametypeclass(VERB_ALGO, "spawn collect query", + qstate->qinfo.qname, qstate->qinfo.qtype, c); + if(!generate_sub_request(qstate->qinfo.qname, + qstate->qinfo.qname_len, qstate->qinfo.qtype, + c, qstate, id, iq, INIT_REQUEST_STATE, + FINISHED_STATE, &subq, + (int)!(qstate->query_flags&BIT_CD))) { + return error_response(qstate, id, + LDNS_RCODE_SERVFAIL); + } + /* ignore subq, no special init required */ + iq->num_current_queries ++; + if(c == 0xffff) + break; + else c++; + } + /* if no roots are configured at all, return */ + if(iq->num_current_queries == 0) { + verbose(VERB_ALGO, "No root hints or fwds, giving up " + "on qclass ANY"); + return error_response(qstate, id, LDNS_RCODE_REFUSED); + } + /* return false, wait for queries to return */ + } + /* if woke up here because of an answer, wait for more answers */ + return 0; +} + +/** + * This handles the final state for first-tier responses (i.e., responses to + * externally generated queries). + * + * @param qstate: query state. + * @param iq: iterator query state. + * @param id: module id. + * @return true if the event needs more processing, false if not. Since this + * is the final state for an event, it always returns false. + */ +static int +processFinished(struct module_qstate* qstate, struct iter_qstate* iq, + int id) +{ + log_query_info(VERB_QUERY, "finishing processing for", + &qstate->qinfo); + + /* store negative cache element for parent side glue. */ + if(iq->query_for_pside_glue && !iq->pside_glue) + iter_store_parentside_neg(qstate->env, &qstate->qinfo, + iq->deleg_msg?iq->deleg_msg->rep: + (iq->response?iq->response->rep:NULL)); + if(!iq->response) { + verbose(VERB_ALGO, "No response is set, servfail"); + return error_response(qstate, id, LDNS_RCODE_SERVFAIL); + } + + /* Make sure that the RA flag is set (since the presence of + * this module means that recursion is available) */ + iq->response->rep->flags |= BIT_RA; + + /* Clear the AA flag */ + /* FIXME: does this action go here or in some other module? */ + iq->response->rep->flags &= ~BIT_AA; + + /* make sure QR flag is on */ + iq->response->rep->flags |= BIT_QR; + + /* we have finished processing this query */ + qstate->ext_state[id] = module_finished; + + /* TODO: we are using a private TTL, trim the response. */ + /* if (mPrivateTTL > 0){IterUtils.setPrivateTTL(resp, mPrivateTTL); } */ + + /* prepend any items we have accumulated */ + if(iq->an_prepend_list || iq->ns_prepend_list) { + if(!iter_prepend(iq, iq->response, qstate->region)) { + log_err("prepend rrsets: out of memory"); + return error_response(qstate, id, LDNS_RCODE_SERVFAIL); + } + /* reset the query name back */ + iq->response->qinfo = qstate->qinfo; + /* the security state depends on the combination */ + iq->response->rep->security = sec_status_unchecked; + /* store message with the finished prepended items, + * but only if we did recursion. The nonrecursion referral + * from cache does not need to be stored in the msg cache. */ + if(qstate->query_flags&BIT_RD) { + if(!iter_dns_store(qstate->env, &qstate->qinfo, + iq->response->rep, 0, qstate->prefetch_leeway, + iq->dp&&iq->dp->has_parent_side_NS, + qstate->region)) + return error_response(qstate, id, + LDNS_RCODE_SERVFAIL); + } + } + qstate->return_rcode = LDNS_RCODE_NOERROR; + qstate->return_msg = iq->response; + return 0; +} + +/* + * Return priming query results to interestes super querystates. + * + * Sets the delegation point and delegation message (not nonRD queries). + * This is a callback from walk_supers. + * + * @param qstate: query state that finished. + * @param id: module id. + * @param super: the qstate to inform. + */ +void +iter_inform_super(struct module_qstate* qstate, int id, + struct module_qstate* super) +{ + if(!qstate->is_priming && super->qinfo.qclass == LDNS_RR_CLASS_ANY) + processClassResponse(qstate, id, super); + 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(qstate->return_rcode != LDNS_RCODE_NOERROR) + error_supers(qstate, id, super); + else if(qstate->is_priming) + prime_supers(qstate, id, super); + else processTargetResponse(qstate, id, super); +} + +/** + * Handle iterator state. + * Handle events. This is the real processing loop for events, responsible + * for moving events through the various states. If a processing method + * returns true, then it will be advanced to the next state. If false, then + * processing will stop. + * + * @param qstate: query state. + * @param ie: iterator shared global environment. + * @param iq: iterator query state. + * @param id: module id. + */ +static void +iter_handle(struct module_qstate* qstate, struct iter_qstate* iq, + struct iter_env* ie, int id) +{ + int cont = 1; + while(cont) { + verbose(VERB_ALGO, "iter_handle processing q with state %s", + iter_state_to_string(iq->state)); + switch(iq->state) { + case INIT_REQUEST_STATE: + cont = processInitRequest(qstate, iq, ie, id); + break; + case INIT_REQUEST_2_STATE: + cont = processInitRequest2(qstate, iq, id); + break; + case INIT_REQUEST_3_STATE: + cont = processInitRequest3(qstate, iq, id); + break; + case QUERYTARGETS_STATE: + cont = processQueryTargets(qstate, iq, ie, id); + break; + case QUERY_RESP_STATE: + cont = processQueryResponse(qstate, iq, id); + break; + case PRIME_RESP_STATE: + cont = processPrimeResponse(qstate, id); + break; + case COLLECT_CLASS_STATE: + cont = processCollectClass(qstate, id); + break; + case DSNS_FIND_STATE: + cont = processDSNSFind(qstate, iq, id); + break; + case FINISHED_STATE: + cont = processFinished(qstate, iq, id); + break; + default: + log_warn("iterator: invalid state: %d", + iq->state); + cont = 0; + break; + } + } +} + +/** + * This is the primary entry point for processing request events. Note that + * this method should only be used by external modules. + * @param qstate: query state. + * @param ie: iterator shared global environment. + * @param iq: iterator query state. + * @param id: module id. + */ +static void +process_request(struct module_qstate* qstate, struct iter_qstate* iq, + struct iter_env* ie, int id) +{ + /* external requests start in the INIT state, and finish using the + * FINISHED state. */ + iq->state = INIT_REQUEST_STATE; + iq->final_state = FINISHED_STATE; + verbose(VERB_ALGO, "process_request: new external request event"); + iter_handle(qstate, iq, ie, id); +} + +/** process authoritative server reply */ +static void +process_response(struct module_qstate* qstate, struct iter_qstate* iq, + struct iter_env* ie, int id, struct outbound_entry* outbound, + enum module_ev event) +{ + struct msg_parse* prs; + struct edns_data edns; + ldns_buffer* pkt; + + verbose(VERB_ALGO, "process_response: new external response event"); + iq->response = NULL; + iq->state = QUERY_RESP_STATE; + if(event == module_event_noreply || event == module_event_error) { + goto handle_it; + } + if( (event != module_event_reply && event != module_event_capsfail) + || !qstate->reply) { + log_err("Bad event combined with response"); + outbound_list_remove(&iq->outlist, outbound); + (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL); + return; + } + + /* parse message */ + prs = (struct msg_parse*)regional_alloc(qstate->env->scratch, + sizeof(struct msg_parse)); + if(!prs) { + log_err("out of memory on incoming message"); + /* like packet got dropped */ + goto handle_it; + } + memset(prs, 0, sizeof(*prs)); + memset(&edns, 0, sizeof(edns)); + pkt = qstate->reply->c->buffer; + ldns_buffer_set_position(pkt, 0); + if(parse_packet(pkt, prs, qstate->env->scratch) != LDNS_RCODE_NOERROR) { + verbose(VERB_ALGO, "parse error on reply packet"); + goto handle_it; + } + /* edns is not examined, but removed from message to help cache */ + if(parse_extract_edns(prs, &edns) != LDNS_RCODE_NOERROR) + goto handle_it; + /* remove CD-bit, we asked for in case we handle validation ourself */ + prs->flags &= ~BIT_CD; + + /* normalize and sanitize: easy to delete items from linked lists */ + if(!scrub_message(pkt, prs, &iq->qchase, iq->dp->name, + qstate->env->scratch, qstate->env, ie)) + goto handle_it; + + /* allocate response dns_msg in region */ + iq->response = dns_alloc_msg(pkt, prs, qstate->region); + if(!iq->response) + goto handle_it; + log_query_info(VERB_DETAIL, "response for", &qstate->qinfo); + log_name_addr(VERB_DETAIL, "reply from", iq->dp->name, + &qstate->reply->addr, qstate->reply->addrlen); + if(verbosity >= VERB_ALGO) + log_dns_msg("incoming scrubbed packet:", &iq->response->qinfo, + iq->response->rep); + + if(event == module_event_capsfail) { + if(!iq->caps_fallback) { + /* start fallback */ + iq->caps_fallback = 1; + iq->caps_server = 0; + iq->caps_reply = iq->response->rep; + iq->state = QUERYTARGETS_STATE; + iq->num_current_queries--; + verbose(VERB_DETAIL, "Capsforid: starting fallback"); + goto handle_it; + } else { + /* check if reply is the same, otherwise, fail */ + if(!reply_equal(iq->response->rep, iq->caps_reply, + qstate->env->scratch_buffer)) { + verbose(VERB_DETAIL, "Capsforid fallback: " + "getting different replies, failed"); + outbound_list_remove(&iq->outlist, outbound); + (void)error_response(qstate, id, + LDNS_RCODE_SERVFAIL); + return; + } + /* continue the fallback procedure at next server */ + iq->caps_server++; + iq->state = QUERYTARGETS_STATE; + iq->num_current_queries--; + verbose(VERB_DETAIL, "Capsforid: reply is equal. " + "go to next fallback"); + goto handle_it; + } + } + iq->caps_fallback = 0; /* if we were in fallback, 0x20 is OK now */ + +handle_it: + outbound_list_remove(&iq->outlist, outbound); + iter_handle(qstate, iq, ie, id); +} + +void +iter_operate(struct module_qstate* qstate, enum module_ev event, int id, + struct outbound_entry* outbound) +{ + struct iter_env* ie = (struct iter_env*)qstate->env->modinfo[id]; + struct iter_qstate* iq = (struct iter_qstate*)qstate->minfo[id]; + verbose(VERB_QUERY, "iterator[module %d] operate: extstate:%s event:%s", + id, strextstate(qstate->ext_state[id]), strmodulevent(event)); + if(iq) log_query_info(VERB_QUERY, "iterator operate: query", + &qstate->qinfo); + if(iq && qstate->qinfo.qname != iq->qchase.qname) + log_query_info(VERB_QUERY, "iterator operate: chased to", + &iq->qchase); + + /* perform iterator state machine */ + if((event == module_event_new || event == module_event_pass) && + iq == NULL) { + if(!iter_new(qstate, id)) { + (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL); + return; + } + iq = (struct iter_qstate*)qstate->minfo[id]; + process_request(qstate, iq, ie, id); + return; + } + if(iq && event == module_event_pass) { + iter_handle(qstate, iq, ie, id); + return; + } + if(iq && outbound) { + 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 iterator"); + (void)error_response(qstate, id, LDNS_RCODE_SERVFAIL); +} + +void +iter_clear(struct module_qstate* qstate, int id) +{ + struct iter_qstate* iq; + if(!qstate) + return; + iq = (struct iter_qstate*)qstate->minfo[id]; + if(iq) { + outbound_list_clear(&iq->outlist); + iq->num_current_queries = 0; + } + qstate->minfo[id] = NULL; +} + +size_t +iter_get_mem(struct module_env* env, int id) +{ + struct iter_env* ie = (struct iter_env*)env->modinfo[id]; + if(!ie) + return 0; + return sizeof(*ie) + sizeof(int)*((size_t)ie->max_dependency_depth+1) + + donotq_get_mem(ie->donotq) + priv_get_mem(ie->priv); +} + +/** + * The iterator function block + */ +static struct module_func_block iter_block = { + "iterator", + &iter_init, &iter_deinit, &iter_operate, &iter_inform_super, + &iter_clear, &iter_get_mem +}; + +struct module_func_block* +iter_get_funcblock(void) +{ + return &iter_block; +} + +const char* +iter_state_to_string(enum iter_state state) +{ + switch (state) + { + case INIT_REQUEST_STATE : + return "INIT REQUEST STATE"; + case INIT_REQUEST_2_STATE : + return "INIT REQUEST STATE (stage 2)"; + case INIT_REQUEST_3_STATE: + return "INIT REQUEST STATE (stage 3)"; + case QUERYTARGETS_STATE : + return "QUERY TARGETS STATE"; + case PRIME_RESP_STATE : + return "PRIME RESPONSE STATE"; + case COLLECT_CLASS_STATE : + return "COLLECT CLASS STATE"; + case DSNS_FIND_STATE : + return "DSNS FIND STATE"; + case QUERY_RESP_STATE : + return "QUERY RESPONSE STATE"; + case FINISHED_STATE : + return "FINISHED RESPONSE STATE"; + default : + return "UNKNOWN ITER STATE"; + } +} + +int +iter_state_is_responsestate(enum iter_state s) +{ + switch(s) { + case INIT_REQUEST_STATE : + case INIT_REQUEST_2_STATE : + case INIT_REQUEST_3_STATE : + case QUERYTARGETS_STATE : + case COLLECT_CLASS_STATE : + return 0; + default: + break; + } + return 1; +} diff --git a/iterator/iterator.h b/iterator/iterator.h new file mode 100644 index 00000000000..eb333157a4f --- /dev/null +++ b/iterator/iterator.h @@ -0,0 +1,375 @@ +/* + * iterator/iterator.h - iterative resolver DNS query response module + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains a module that performs recusive iterative DNS query + * processing. + */ + +#ifndef ITERATOR_ITERATOR_H +#define ITERATOR_ITERATOR_H +#include "services/outbound_list.h" +#include "util/data/msgreply.h" +#include "util/module.h" +struct delegpt; +struct iter_hints; +struct iter_forwards; +struct iter_donotq; +struct iter_prep_list; +struct iter_priv; + +/** max number of query restarts. Determines max number of CNAME chain. */ +#define MAX_RESTART_COUNT 8 +/** max number of referrals. Makes sure resolver does not run away */ +#define MAX_REFERRAL_COUNT 130 +/** max number of queries-sent-out. Make sure large NS set does not loop */ +#define MAX_SENT_COUNT 16 +/** 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 + * Equals rtt initial timeout value. + */ +#define UNKNOWN_SERVER_NICENESS 376 +/** maximum timeout before a host is deemed unsuitable, in msec. + * After host_ttl this will be timed out and the host will be tried again. + * Equals RTT_MAX_TIMEOUT + */ +#define USEFUL_SERVER_TOP_TIMEOUT 120000 +/** Number of lost messages in a row that get a host blacklisted. + * With 16, a couple different queries have to time out and no working + * queries are happening */ +#define USEFUL_SERVER_MAX_LOST 16 +/** number of retries on outgoing queries */ +#define OUTBOUND_MSG_RETRY 5 +/** RTT band, within this amount from the best, servers are chosen randomly. + * Chosen so that the UNKNOWN_SERVER_NICENESS falls within the band of a + * fast server, this causes server exploration as a side benefit. msec. */ +#define RTT_BAND 400 +/** Start value for blacklisting a host, 2*USEFUL_SERVER_TOP_TIMEOUT in sec */ +#define INFRA_BACKOFF_INITIAL 240 + +/** + * Global state for the iterator. + */ +struct iter_env { + /** A flag to indicate whether or not we have an IPv6 route */ + int supports_ipv6; + + /** A flag to indicate whether or not we have an IPv4 route */ + int supports_ipv4; + + /** A set of inetaddrs that should never be queried. */ + struct iter_donotq* donotq; + + /** private address space and private domains */ + struct iter_priv* priv; + + /** The maximum dependency depth that this resolver will pursue. */ + int max_dependency_depth; + + /** + * The target fetch policy for each dependency level. This is + * described as a simple number (per dependency level): + * negative numbers (usually just -1) mean fetch-all, + * 0 means only fetch on demand, and + * positive numbers mean to fetch at most that many targets. + * array of max_dependency_depth+1 size. + */ + int* target_fetch_policy; +}; + +/** + * State of the iterator for a query. + */ +enum iter_state { + /** + * Externally generated queries start at this state. Query restarts are + * reset to this state. + */ + INIT_REQUEST_STATE = 0, + + /** + * Root priming events reactivate here, most other events pass + * through this naturally as the 2nd part of the INIT_REQUEST_STATE. + */ + INIT_REQUEST_2_STATE, + + /** + * Stub priming events reactivate here, most other events pass + * through this naturally as the 3rd part of the INIT_REQUEST_STATE. + */ + INIT_REQUEST_3_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 + * nameserver targets. + */ + QUERYTARGETS_STATE, + + /** + * Responses to queries start at this state. This state handles + * the decision tree associated with handling responses. + */ + QUERY_RESP_STATE, + + /** Responses to priming queries finish at this state. */ + PRIME_RESP_STATE, + + /** Collecting query class information, for qclass=ANY, when + * it spawns off queries for every class, it returns here. */ + COLLECT_CLASS_STATE, + + /** Find NS record to resolve DS record from, walking to the right + * NS spot until we find it */ + DSNS_FIND_STATE, + + /** Responses that are to be returned upstream end at this state. + * As well as responses to target queries. */ + FINISHED_STATE +}; + +/** + * Per query state for the iterator module. + */ +struct iter_qstate { + /** + * State of the iterator module. + * This is the state that event is in or should sent to -- all + * requests should start with the INIT_REQUEST_STATE. All + * responses should start with QUERY_RESP_STATE. Subsequent + * processing of the event will change this state. + */ + enum iter_state state; + + /** + * Final state for the iterator module. + * This is the state that responses should be routed to once the + * response is final. For externally initiated queries, this + * will be FINISHED_STATE, locally initiated queries will have + * different final states. + */ + enum iter_state final_state; + + /** + * The depth of this query, this means the depth of recursion. + * This address is needed for another query, which is an address + * needed for another query, etc. Original client query has depth 0. + */ + int depth; + + /** + * The response + */ + struct dns_msg* response; + + /** + * This is a list of RRsets that must be prepended to the + * ANSWER section of a response before being sent upstream. + */ + struct iter_prep_list* an_prepend_list; + /** Last element of the prepend list */ + struct iter_prep_list* an_prepend_last; + + /** + * This is the list of RRsets that must be prepended to the + * AUTHORITY section of the response before being sent upstream. + */ + struct iter_prep_list* ns_prepend_list; + /** Last element of the authority prepend list */ + struct iter_prep_list* ns_prepend_last; + + /** query name used for chasing the results. Initially the same as + * the state qinfo, but after CNAMEs this will be different. + * The query info used to elicit the results needed. */ + struct query_info qchase; + /** query flags to use when chasing the answer (i.e. RD flag) */ + uint16_t chase_flags; + /** true if we set RD bit because of last resort recursion lame query*/ + int chase_to_rd; + + /** + * This is the current delegation point for an in-progress query. This + * object retains state as to which delegation targets need to be + * (sub)queried for vs which ones have already been visited. + */ + struct delegpt* dp; + + /** state for 0x20 fallback when capsfail happens, 0 not a fallback */ + int caps_fallback; + /** state for capsfail: current server number to try */ + size_t caps_server; + /** state for capsfail: stored query for comparisons */ + struct reply_info* caps_reply; + + /** Current delegation message - returned for non-RD queries */ + struct dns_msg* deleg_msg; + + /** number of outstanding target sub queries */ + int num_target_queries; + + /** outstanding direct queries */ + int num_current_queries; + + /** the number of times this query has been restarted. */ + int query_restart_count; + + /** the number of times this query as followed a referral. */ + int referral_count; + + /** number of queries fired off */ + int sent_count; + + /** + * The query must store NS records from referrals as parentside RRs + * Enabled once it hits resolution problems, to throttle retries. + * If enabled it is the pointer to the old delegation point with + * the old retry counts for bad-nameserver-addresses. + */ + struct delegpt* store_parent_NS; + + /** + * The query is for parent-side glue(A or AAAA) for a nameserver. + * If the item is seen as glue in a referral, and pside_glue is NULL, + * then it is stored in pside_glue for later. + * If it was never seen, at the end, then a negative caching element + * must be created. + * The (data or negative) RR cache element then throttles retries. + */ + int query_for_pside_glue; + /** the parent-side-glue element (NULL if none, its first match) */ + struct ub_packed_rrset_key* pside_glue; + + /** If nonNULL we are walking upwards from DS query to find NS */ + uint8_t* dsns_point; + /** length of the dname in dsns_point */ + size_t dsns_point_len; + + /** + * expected dnssec information for this iteration step. + * If dnssec rrsigs are expected and not given, the server is marked + * lame (dnssec-lame). + */ + int dnssec_expected; + + /** + * We are expecting dnssec information, but we also know the server + * is DNSSEC lame. The response need not be marked dnssec-lame again. + */ + int dnssec_lame_query; + + /** + * This is flag that, if true, means that this event is + * waiting for a stub priming query. + */ + int wait_priming_stub; + + /** + * This is a flag that, if true, means that this query is + * for (re)fetching glue from a zone. Since the address should + * have been glue, query again to the servers that should have + * been returning it as glue. + * The delegation point must be set to the one that should *not* + * be used when creating the state. A higher one will be attempted. + */ + int refetch_glue; + + /** list of pending queries to authoritative servers. */ + struct outbound_list outlist; +}; + +/** + * List of prepend items + */ +struct iter_prep_list { + /** next in list */ + struct iter_prep_list* next; + /** rrset */ + struct ub_packed_rrset_key* rrset; +}; + +/** + * Get the iterator function block. + * @return: function block with function pointers to iterator methods. + */ +struct module_func_block* iter_get_funcblock(void); + +/** + * Get iterator state as a string + * @param state: to convert + * @return constant string that is printable. + */ +const char* iter_state_to_string(enum iter_state state); + +/** + * See if iterator state is a response state + * @param s: to inspect + * @return true if response state. + */ +int iter_state_is_responsestate(enum iter_state s); + +/** iterator init */ +int iter_init(struct module_env* env, int id); + +/** iterator deinit */ +void iter_deinit(struct module_env* env, int id); + +/** iterator operate on a query */ +void iter_operate(struct module_qstate* qstate, enum module_ev event, int id, + struct outbound_entry* outbound); + +/** + * Return priming query results to interestes super querystates. + * + * Sets the delegation point and delegation message (not nonRD queries). + * This is a callback from walk_supers. + * + * @param qstate: query state that finished. + * @param id: module id. + * @param super: the qstate to inform. + */ +void iter_inform_super(struct module_qstate* qstate, int id, + struct module_qstate* super); + +/** iterator cleanup query state */ +void iter_clear(struct module_qstate* qstate, int id); + +/** iterator alloc size routine */ +size_t iter_get_mem(struct module_env* env, int id); + +#endif /* ITERATOR_ITERATOR_H */ diff --git a/libunbound/context.c b/libunbound/context.c new file mode 100644 index 00000000000..f28307971b4 --- /dev/null +++ b/libunbound/context.c @@ -0,0 +1,400 @@ +/* + * libunbound/context.c - validating context for unbound internal use + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains the validator context structure. + */ +#include "config.h" +#include "libunbound/context.h" +#include "util/module.h" +#include "util/config_file.h" +#include "util/net_help.h" +#include "services/modstack.h" +#include "services/localzone.h" +#include "services/cache/rrset.h" +#include "services/cache/infra.h" +#include "util/data/msgreply.h" +#include "util/storage/slabhash.h" + +int +context_finalize(struct ub_ctx* ctx) +{ + struct config_file* cfg = ctx->env->cfg; + verbosity = cfg->verbosity; + if(ctx->logfile_override) + log_file(ctx->log_out); + else log_init(cfg->logfile, cfg->use_syslog, NULL); + config_apply(cfg); + if(!modstack_setup(&ctx->mods, cfg->module_conf, ctx->env)) + return UB_INITFAIL; + ctx->local_zones = local_zones_create(); + if(!ctx->local_zones) + return UB_NOMEM; + if(!local_zones_apply_cfg(ctx->local_zones, cfg)) + return UB_INITFAIL; + if(!ctx->env->msg_cache || + cfg->msg_cache_size != slabhash_get_size(ctx->env->msg_cache) || + cfg->msg_cache_slabs != ctx->env->msg_cache->size) { + slabhash_delete(ctx->env->msg_cache); + ctx->env->msg_cache = slabhash_create(cfg->msg_cache_slabs, + HASH_DEFAULT_STARTARRAY, cfg->msg_cache_size, + msgreply_sizefunc, query_info_compare, + query_entry_delete, reply_info_delete, NULL); + if(!ctx->env->msg_cache) + return UB_NOMEM; + } + ctx->env->rrset_cache = rrset_cache_adjust(ctx->env->rrset_cache, + ctx->env->cfg, ctx->env->alloc); + if(!ctx->env->rrset_cache) + return UB_NOMEM; + ctx->env->infra_cache = infra_adjust(ctx->env->infra_cache, cfg); + if(!ctx->env->infra_cache) + return UB_NOMEM; + ctx->finalized = 1; + return UB_NOERROR; +} + +int context_query_cmp(const void* a, const void* b) +{ + if( *(int*)a < *(int*)b ) + return -1; + if( *(int*)a > *(int*)b ) + return 1; + return 0; +} + +void +context_query_delete(struct ctx_query* q) +{ + if(!q) return; + ub_resolve_free(q->res); + free(q->msg); + free(q); +} + +/** How many times to try to find an unused query-id-number for async */ +#define NUM_ID_TRIES 100000 +/** find next useful id number of 0 on error */ +static int +find_id(struct ub_ctx* ctx, int* id) +{ + size_t tries = 0; + ctx->next_querynum++; + while(rbtree_search(&ctx->queries, &ctx->next_querynum)) { + ctx->next_querynum++; /* numerical wraparound is fine */ + if(tries++ > NUM_ID_TRIES) + return 0; + } + *id = ctx->next_querynum; + return 1; +} + +struct ctx_query* +context_new(struct ub_ctx* ctx, char* name, int rrtype, int rrclass, + ub_callback_t cb, void* cbarg) +{ + struct ctx_query* q = (struct ctx_query*)calloc(1, sizeof(*q)); + if(!q) return NULL; + lock_basic_lock(&ctx->cfglock); + if(!find_id(ctx, &q->querynum)) { + lock_basic_unlock(&ctx->cfglock); + free(q); + return NULL; + } + lock_basic_unlock(&ctx->cfglock); + q->node.key = &q->querynum; + q->async = (cb != NULL); + q->cb = cb; + q->cb_arg = cbarg; + q->res = (struct ub_result*)calloc(1, sizeof(*q->res)); + if(!q->res) { + free(q); + return NULL; + } + q->res->qname = strdup(name); + if(!q->res->qname) { + free(q->res); + free(q); + return NULL; + } + q->res->qtype = rrtype; + q->res->qclass = rrclass; + + /* add to query list */ + lock_basic_lock(&ctx->cfglock); + if(q->async) + ctx->num_async ++; + (void)rbtree_insert(&ctx->queries, &q->node); + lock_basic_unlock(&ctx->cfglock); + return q; +} + +struct alloc_cache* +context_obtain_alloc(struct ub_ctx* ctx, int locking) +{ + struct alloc_cache* a; + int tnum = 0; + if(locking) { + lock_basic_lock(&ctx->cfglock); + } + a = ctx->alloc_list; + if(a) + ctx->alloc_list = a->super; /* snip off list */ + else tnum = ctx->thr_next_num++; + if(locking) { + lock_basic_unlock(&ctx->cfglock); + } + if(a) { + a->super = &ctx->superalloc; + return a; + } + a = (struct alloc_cache*)calloc(1, sizeof(*a)); + if(!a) + return NULL; + alloc_init(a, &ctx->superalloc, tnum); + return a; +} + +void +context_release_alloc(struct ub_ctx* ctx, struct alloc_cache* alloc, + int locking) +{ + if(!ctx || !alloc) + return; + if(locking) { + lock_basic_lock(&ctx->cfglock); + } + alloc->super = ctx->alloc_list; + ctx->alloc_list = alloc; + if(locking) { + lock_basic_unlock(&ctx->cfglock); + } +} + +uint8_t* +context_serialize_new_query(struct ctx_query* q, uint32_t* len) +{ + /* format for new query is + * o uint32 cmd + * o uint32 id + * o uint32 type + * o uint32 class + * o rest queryname (string) + */ + uint8_t* p; + size_t slen = strlen(q->res->qname) + 1/*end of string*/; + *len = sizeof(uint32_t)*4 + slen; + p = (uint8_t*)malloc(*len); + if(!p) return NULL; + ldns_write_uint32(p, UB_LIBCMD_NEWQUERY); + ldns_write_uint32(p+sizeof(uint32_t), (uint32_t)q->querynum); + ldns_write_uint32(p+2*sizeof(uint32_t), (uint32_t)q->res->qtype); + ldns_write_uint32(p+3*sizeof(uint32_t), (uint32_t)q->res->qclass); + memmove(p+4*sizeof(uint32_t), q->res->qname, slen); + return p; +} + +struct ctx_query* +context_deserialize_new_query(struct ub_ctx* ctx, uint8_t* p, uint32_t len) +{ + struct ctx_query* q = (struct ctx_query*)calloc(1, sizeof(*q)); + if(!q) return NULL; + if(len < 4*sizeof(uint32_t)+1) { + free(q); + return NULL; + } + log_assert( ldns_read_uint32(p) == UB_LIBCMD_NEWQUERY); + q->querynum = (int)ldns_read_uint32(p+sizeof(uint32_t)); + q->node.key = &q->querynum; + q->async = 1; + q->res = (struct ub_result*)calloc(1, sizeof(*q->res)); + if(!q->res) { + free(q); + return NULL; + } + q->res->qtype = (int)ldns_read_uint32(p+2*sizeof(uint32_t)); + q->res->qclass = (int)ldns_read_uint32(p+3*sizeof(uint32_t)); + q->res->qname = strdup((char*)(p+4*sizeof(uint32_t))); + if(!q->res->qname) { + free(q->res); + free(q); + return NULL; + } + + /** add to query list */ + ctx->num_async++; + (void)rbtree_insert(&ctx->queries, &q->node); + return q; +} + +struct ctx_query* +context_lookup_new_query(struct ub_ctx* ctx, uint8_t* p, uint32_t len) +{ + struct ctx_query* q; + int querynum; + if(len < 4*sizeof(uint32_t)+1) { + return NULL; + } + log_assert( ldns_read_uint32(p) == UB_LIBCMD_NEWQUERY); + querynum = (int)ldns_read_uint32(p+sizeof(uint32_t)); + q = (struct ctx_query*)rbtree_search(&ctx->queries, &querynum); + if(!q) { + return NULL; + } + log_assert(q->async); + return q; +} + +uint8_t* +context_serialize_answer(struct ctx_query* q, int err, ldns_buffer* pkt, + uint32_t* len) +{ + /* answer format + * o uint32 cmd + * o uint32 id + * o uint32 error_code + * o uint32 msg_security + * o uint32 length of why_bogus string (+1 for eos); 0 absent. + * o why_bogus_string + * o the remainder is the answer msg from resolver lookup. + * remainder can be length 0. + */ + size_t pkt_len = pkt?ldns_buffer_remaining(pkt):0; + size_t wlen = (pkt&&q->res->why_bogus)?strlen(q->res->why_bogus)+1:0; + uint8_t* p; + *len = sizeof(uint32_t)*5 + pkt_len + wlen; + p = (uint8_t*)malloc(*len); + if(!p) return NULL; + ldns_write_uint32(p, UB_LIBCMD_ANSWER); + ldns_write_uint32(p+sizeof(uint32_t), (uint32_t)q->querynum); + ldns_write_uint32(p+2*sizeof(uint32_t), (uint32_t)err); + ldns_write_uint32(p+3*sizeof(uint32_t), (uint32_t)q->msg_security); + ldns_write_uint32(p+4*sizeof(uint32_t), (uint32_t)wlen); + if(wlen > 0) + memmove(p+5*sizeof(uint32_t), q->res->why_bogus, wlen); + if(pkt_len > 0) + memmove(p+5*sizeof(uint32_t)+wlen, + ldns_buffer_begin(pkt), pkt_len); + return p; +} + +struct ctx_query* +context_deserialize_answer(struct ub_ctx* ctx, + uint8_t* p, uint32_t len, int* err) +{ + struct ctx_query* q = NULL ; + int id; + size_t wlen; + if(len < 5*sizeof(uint32_t)) return NULL; + log_assert( ldns_read_uint32(p) == UB_LIBCMD_ANSWER); + id = (int)ldns_read_uint32(p+sizeof(uint32_t)); + q = (struct ctx_query*)rbtree_search(&ctx->queries, &id); + if(!q) return NULL; + *err = (int)ldns_read_uint32(p+2*sizeof(uint32_t)); + q->msg_security = ldns_read_uint32(p+3*sizeof(uint32_t)); + wlen = (size_t)ldns_read_uint32(p+4*sizeof(uint32_t)); + if(len > 5*sizeof(uint32_t) && wlen > 0) { + if(len >= 5*sizeof(uint32_t)+wlen) + q->res->why_bogus = (char*)memdup( + p+5*sizeof(uint32_t), wlen); + if(!q->res->why_bogus) { + /* pass malloc failure to the user callback */ + q->msg_len = 0; + *err = UB_NOMEM; + return q; + } + q->res->why_bogus[wlen-1] = 0; /* zero terminated for sure */ + } + if(len > 5*sizeof(uint32_t)+wlen) { + q->msg_len = len - 5*sizeof(uint32_t) - wlen; + q->msg = (uint8_t*)memdup(p+5*sizeof(uint32_t)+wlen, + q->msg_len); + if(!q->msg) { + /* pass malloc failure to the user callback */ + q->msg_len = 0; + *err = UB_NOMEM; + return q; + } + } + return q; +} + +uint8_t* +context_serialize_cancel(struct ctx_query* q, uint32_t* len) +{ + /* format of cancel: + * o uint32 cmd + * o uint32 async-id */ + uint8_t* p = (uint8_t*)malloc(2*sizeof(uint32_t)); + if(!p) return NULL; + *len = 2*sizeof(uint32_t); + ldns_write_uint32(p, UB_LIBCMD_CANCEL); + ldns_write_uint32(p+sizeof(uint32_t), (uint32_t)q->querynum); + return p; +} + +struct ctx_query* context_deserialize_cancel(struct ub_ctx* ctx, + uint8_t* p, uint32_t len) +{ + struct ctx_query* q; + int id; + if(len != 2*sizeof(uint32_t)) return NULL; + log_assert( ldns_read_uint32(p) == UB_LIBCMD_CANCEL); + id = (int)ldns_read_uint32(p+sizeof(uint32_t)); + q = (struct ctx_query*)rbtree_search(&ctx->queries, &id); + return q; +} + +uint8_t* +context_serialize_quit(uint32_t* len) +{ + uint8_t* p = (uint8_t*)malloc(sizeof(uint32_t)); + if(!p) + return NULL; + *len = sizeof(uint32_t); + ldns_write_uint32(p, UB_LIBCMD_QUIT); + return p; +} + +enum ub_ctx_cmd context_serial_getcmd(uint8_t* p, uint32_t len) +{ + uint32_t v; + if((size_t)len < sizeof(v)) + return UB_LIBCMD_QUIT; + v = ldns_read_uint32(p); + return v; +} diff --git a/libunbound/context.h b/libunbound/context.h new file mode 100644 index 00000000000..8898f3ebfdf --- /dev/null +++ b/libunbound/context.h @@ -0,0 +1,345 @@ +/* + * libunbound/context.h - validating context for unbound internal use + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains the validator context structure. + */ +#ifndef LIBUNBOUND_CONTEXT_H +#define LIBUNBOUND_CONTEXT_H +#include "util/locks.h" +#include "util/alloc.h" +#include "util/rbtree.h" +#include "services/modstack.h" +#include "libunbound/unbound.h" +#include "util/data/packed_rrset.h" +struct libworker; +struct tube; + +/** + * The context structure + * + * Contains two pipes for async service + * qq : write queries to the async service pid/tid. + * rr : read results from the async service pid/tid. + */ +struct ub_ctx { + /* --- pipes --- */ + /** mutex on query write pipe */ + lock_basic_t qqpipe_lock; + /** the query write pipe */ + struct tube* qq_pipe; + /** mutex on result read pipe */ + lock_basic_t rrpipe_lock; + /** the result read pipe */ + struct tube* rr_pipe; + + /* --- shared data --- */ + /** mutex for access to env.cfg, finalized and dothread */ + lock_basic_t cfglock; + /** + * The context has been finalized + * This is after config when the first resolve is done. + * The modules are inited (module-init()) and shared caches created. + */ + int finalized; + + /** is bg worker created yet ? */ + int created_bg; + /** pid of bg worker process */ + pid_t bg_pid; + /** tid of bg worker thread */ + ub_thread_t bg_tid; + + /** do threading (instead of forking) for async resolution */ + int dothread; + /** next thread number for new threads */ + int thr_next_num; + /** if logfile is overriden */ + int logfile_override; + /** what logfile to use instead */ + FILE* log_out; + /** + * List of alloc-cache-id points per threadnum for notinuse threads. + * Simply the entire struct alloc_cache with the 'super' member used + * to link a simply linked list. Reset super member to the superalloc + * before use. + */ + struct alloc_cache* alloc_list; + + /** shared caches, and so on */ + struct alloc_cache superalloc; + /** module env master value */ + struct module_env* env; + /** module stack */ + struct module_stack mods; + /** local authority zones */ + struct local_zones* local_zones; + /** random state used to seed new random state structures */ + struct ub_randstate* seed_rnd; + + /** next query number (to try) to use */ + int next_querynum; + /** number of async queries outstanding */ + size_t num_async; + /** + * Tree of outstanding queries. Indexed by querynum + * Used when results come in for async to lookup. + * Used when cancel is done for lookup (and delete). + * Used to see if querynum is free for use. + * Content of type ctx_query. + */ + rbtree_t queries; +}; + +/** + * The queries outstanding for the libunbound resolver. + * These are outstanding for async resolution. + * But also, outstanding for sync resolution by one of the threads that + * has joined the threadpool. + */ +struct ctx_query { + /** node in rbtree, must be first entry, key is ptr to the querynum */ + struct rbnode_t node; + /** query id number, key for node */ + int querynum; + /** was this an async query? */ + int async; + /** was this query cancelled (for bg worker) */ + int cancelled; + + /** for async query, the callback function */ + ub_callback_t cb; + /** for async query, the callback user arg */ + void* cb_arg; + + /** answer message, result from resolver lookup. */ + uint8_t* msg; + /** resulting message length. */ + size_t msg_len; + /** validation status on security */ + enum sec_status msg_security; + /** store libworker that is handling this query */ + struct libworker* w; + + /** result structure, also contains original query, type, class. + * malloced ptr ready to hand to the client. */ + struct ub_result* res; +}; + +/** + * The error constants + */ +enum ub_ctx_err { + /** no error */ + UB_NOERROR = 0, + /** socket operation. Set to -1, so that if an error from _fd() is + * passed (-1) it gives a socket error. */ + UB_SOCKET = -1, + /** alloc failure */ + UB_NOMEM = -2, + /** syntax error */ + UB_SYNTAX = -3, + /** DNS service failed */ + UB_SERVFAIL = -4, + /** fork() failed */ + UB_FORKFAIL = -5, + /** cfg change after finalize() */ + UB_AFTERFINAL = -6, + /** initialization failed (bad settings) */ + UB_INITFAIL = -7, + /** error in pipe communication with async bg worker */ + UB_PIPE = -8, + /** error reading from file (resolv.conf) */ + UB_READFILE = -9, + /** error async_id does not exist or result already been delivered */ + UB_NOID = -10 +}; + +/** + * Command codes for libunbound pipe. + * + * Serialization looks like this: + * o length (of remainder) uint32. + * o uint32 command code. + * o per command format. + */ +enum ub_ctx_cmd { + /** QUIT */ + UB_LIBCMD_QUIT = 0, + /** New query, sent to bg worker */ + UB_LIBCMD_NEWQUERY, + /** Cancel query, sent to bg worker */ + UB_LIBCMD_CANCEL, + /** Query result, originates from bg worker */ + UB_LIBCMD_ANSWER +}; + +/** + * finalize a context. + * @param ctx: context to finalize. creates shared data. + * @return 0 if OK, or errcode. + */ +int context_finalize(struct ub_ctx* ctx); + +/** compare two ctx_query elements */ +int context_query_cmp(const void* a, const void* b); + +/** + * delete context query + * @param q: query to delete, including message packet and prealloc result + */ +void context_query_delete(struct ctx_query* q); + +/** + * Create new query in context, add to querynum list. + * @param ctx: context + * @param name: query name + * @param rrtype: type + * @param rrclass: class + * @param cb: callback for async, or NULL for sync. + * @param cbarg: user arg for async queries. + * @return new ctx_query or NULL for malloc failure. + */ +struct ctx_query* context_new(struct ub_ctx* ctx, char* name, int rrtype, + int rrclass, ub_callback_t cb, void* cbarg); + +/** + * Get a new alloc. Creates a new one or uses a cached one. + * @param ctx: context + * @param locking: if true, cfglock is locked while getting alloc. + * @return an alloc, or NULL on mem error. + */ +struct alloc_cache* context_obtain_alloc(struct ub_ctx* ctx, int locking); + +/** + * Release an alloc. Puts it into the cache. + * @param ctx: context + * @param locking: if true, cfglock is locked while releasing alloc. + * @param alloc: alloc to relinquish. + */ +void context_release_alloc(struct ub_ctx* ctx, struct alloc_cache* alloc, + int locking); + +/** + * Serialize a context query that questions data. + * This serializes the query name, type, ... + * As well as command code 'new_query'. + * @param q: context query + * @param len: the length of the allocation is returned. + * @return: an alloc, or NULL on mem error. + */ +uint8_t* context_serialize_new_query(struct ctx_query* q, uint32_t* len); + +/** + * Serialize a context_query result to hand back to user. + * This serializes the query name, type, ..., and result. + * As well as command code 'answer'. + * @param q: context query + * @param err: error code to pass to client. + * @param pkt: the packet to add, can be NULL. + * @param len: the length of the allocation is returned. + * @return: an alloc, or NULL on mem error. + */ +uint8_t* context_serialize_answer(struct ctx_query* q, int err, + ldns_buffer* pkt, uint32_t* len); + +/** + * Serialize a query cancellation. Serializes query async id + * as well as command code 'cancel' + * @param q: context query + * @param len: the length of the allocation is returned. + * @return: an alloc, or NULL on mem error. + */ +uint8_t* context_serialize_cancel(struct ctx_query* q, uint32_t* len); + +/** + * Serialize a 'quit' command. + * @param len: the length of the allocation is returned. + * @return: an alloc, or NULL on mem error. + */ +uint8_t* context_serialize_quit(uint32_t* len); + +/** + * Obtain command code from serialized buffer + * @param p: buffer serialized. + * @param len: length of buffer. + * @return command code or QUIT on error. + */ +enum ub_ctx_cmd context_serial_getcmd(uint8_t* p, uint32_t len); + +/** + * Lookup query from new_query buffer. + * @param ctx: context + * @param p: buffer serialized. + * @param len: length of buffer. + * @return looked up ctx_query or NULL for malloc failure. + */ +struct ctx_query* context_lookup_new_query(struct ub_ctx* ctx, + uint8_t* p, uint32_t len); + +/** + * Deserialize a new_query buffer. + * @param ctx: context + * @param p: buffer serialized. + * @param len: length of buffer. + * @return new ctx_query or NULL for malloc failure. + */ +struct ctx_query* context_deserialize_new_query(struct ub_ctx* ctx, + uint8_t* p, uint32_t len); + +/** + * Deserialize an answer buffer. + * @param ctx: context + * @param p: buffer serialized. + * @param len: length of buffer. + * @param err: error code to be returned to client is passed. + * @return ctx_query with answer added or NULL for malloc failure. + */ +struct ctx_query* context_deserialize_answer(struct ub_ctx* ctx, + uint8_t* p, uint32_t len, int* err); + +/** + * Deserialize a cancel buffer. + * @param ctx: context + * @param p: buffer serialized. + * @param len: length of buffer. + * @return ctx_query to cancel or NULL for failure. + */ +struct ctx_query* context_deserialize_cancel(struct ub_ctx* ctx, + uint8_t* p, uint32_t len); + +#endif /* LIBUNBOUND_CONTEXT_H */ diff --git a/libunbound/libunbound.c b/libunbound/libunbound.c new file mode 100644 index 00000000000..10d00ddc521 --- /dev/null +++ b/libunbound/libunbound.c @@ -0,0 +1,1124 @@ +/* + * unbound.c - unbound validating resolver public API implementation + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions to resolve DNS queries and + * validate the answers. Synchonously and asynchronously. + * + */ + +/* include the public api first, it should be able to stand alone */ +#include "libunbound/unbound.h" +#include "config.h" +#include +#include "libunbound/context.h" +#include "libunbound/libworker.h" +#include "util/locks.h" +#include "util/config_file.h" +#include "util/alloc.h" +#include "util/module.h" +#include "util/regional.h" +#include "util/log.h" +#include "util/random.h" +#include "util/net_help.h" +#include "util/tube.h" +#include "services/modstack.h" +#include "services/localzone.h" +#include "services/cache/infra.h" +#include "services/cache/rrset.h" + +#if defined(UB_ON_WINDOWS) && defined (HAVE_WINDOWS_H) +#include +#include +#endif /* UB_ON_WINDOWS */ + +struct ub_ctx* +ub_ctx_create(void) +{ + struct ub_ctx* ctx; + unsigned int seed; +#ifdef USE_WINSOCK + int r; + WSADATA wsa_data; +#endif + + log_init(NULL, 0, NULL); /* logs to stderr */ + log_ident_set("libunbound"); +#ifdef USE_WINSOCK + if((r = WSAStartup(MAKEWORD(2,2), &wsa_data)) != 0) { + log_err("could not init winsock. WSAStartup: %s", + wsa_strerror(r)); + return NULL; + } +#endif + verbosity = 0; /* errors only */ + checklock_start(); + ctx = (struct ub_ctx*)calloc(1, sizeof(*ctx)); + if(!ctx) { + errno = ENOMEM; + return NULL; + } + alloc_init(&ctx->superalloc, NULL, 0); + seed = (unsigned int)time(NULL) ^ (unsigned int)getpid(); + if(!(ctx->seed_rnd = ub_initstate(seed, NULL))) { + seed = 0; + ub_randfree(ctx->seed_rnd); + free(ctx); + errno = ENOMEM; + return NULL; + } + seed = 0; + if((ctx->qq_pipe = tube_create()) == NULL) { + int e = errno; + ub_randfree(ctx->seed_rnd); + free(ctx); + errno = e; + return NULL; + } + if((ctx->rr_pipe = tube_create()) == NULL) { + int e = errno; + tube_delete(ctx->qq_pipe); + ub_randfree(ctx->seed_rnd); + free(ctx); + errno = e; + return NULL; + } + lock_basic_init(&ctx->qqpipe_lock); + lock_basic_init(&ctx->rrpipe_lock); + lock_basic_init(&ctx->cfglock); + ctx->env = (struct module_env*)calloc(1, sizeof(*ctx->env)); + if(!ctx->env) { + tube_delete(ctx->qq_pipe); + tube_delete(ctx->rr_pipe); + ub_randfree(ctx->seed_rnd); + free(ctx); + errno = ENOMEM; + return NULL; + } + ctx->env->cfg = config_create_forlib(); + if(!ctx->env->cfg) { + tube_delete(ctx->qq_pipe); + tube_delete(ctx->rr_pipe); + free(ctx->env); + ub_randfree(ctx->seed_rnd); + free(ctx); + errno = ENOMEM; + return NULL; + } + ctx->env->alloc = &ctx->superalloc; + ctx->env->worker = NULL; + ctx->env->need_to_validate = 0; + modstack_init(&ctx->mods); + rbtree_init(&ctx->queries, &context_query_cmp); + return ctx; +} + +/** delete q */ +static void +delq(rbnode_t* n, void* ATTR_UNUSED(arg)) +{ + struct ctx_query* q = (struct ctx_query*)n; + context_query_delete(q); +} + +void +ub_ctx_delete(struct ub_ctx* ctx) +{ + struct alloc_cache* a, *na; + if(!ctx) return; + /* stop the bg thread */ + lock_basic_lock(&ctx->cfglock); + if(ctx->created_bg) { + uint8_t* msg; + uint32_t len; + uint32_t cmd = UB_LIBCMD_QUIT; + lock_basic_unlock(&ctx->cfglock); + lock_basic_lock(&ctx->qqpipe_lock); + (void)tube_write_msg(ctx->qq_pipe, (uint8_t*)&cmd, + (uint32_t)sizeof(cmd), 0); + lock_basic_unlock(&ctx->qqpipe_lock); + lock_basic_lock(&ctx->rrpipe_lock); + while(tube_read_msg(ctx->rr_pipe, &msg, &len, 0)) { + /* discard all results except a quit confirm */ + if(context_serial_getcmd(msg, len) == UB_LIBCMD_QUIT) { + free(msg); + break; + } + free(msg); + } + lock_basic_unlock(&ctx->rrpipe_lock); + + /* if bg worker is a thread, wait for it to exit, so that all + * resources are really gone. */ + lock_basic_lock(&ctx->cfglock); + if(ctx->dothread) { + lock_basic_unlock(&ctx->cfglock); + ub_thread_join(ctx->bg_tid); + } else { + lock_basic_unlock(&ctx->cfglock); + } + } + else { + lock_basic_unlock(&ctx->cfglock); + } + + + modstack_desetup(&ctx->mods, ctx->env); + a = ctx->alloc_list; + while(a) { + na = a->super; + a->super = &ctx->superalloc; + alloc_clear(a); + free(a); + a = na; + } + local_zones_delete(ctx->local_zones); + lock_basic_destroy(&ctx->qqpipe_lock); + lock_basic_destroy(&ctx->rrpipe_lock); + lock_basic_destroy(&ctx->cfglock); + tube_delete(ctx->qq_pipe); + tube_delete(ctx->rr_pipe); + if(ctx->env) { + slabhash_delete(ctx->env->msg_cache); + rrset_cache_delete(ctx->env->rrset_cache); + infra_delete(ctx->env->infra_cache); + config_delete(ctx->env->cfg); + free(ctx->env); + } + ub_randfree(ctx->seed_rnd); + alloc_clear(&ctx->superalloc); + traverse_postorder(&ctx->queries, delq, NULL); + free(ctx); +#ifdef USE_WINSOCK + WSACleanup(); +#endif +} + +int +ub_ctx_set_option(struct ub_ctx* ctx, char* opt, char* val) +{ + lock_basic_lock(&ctx->cfglock); + if(ctx->finalized) { + lock_basic_unlock(&ctx->cfglock); + return UB_AFTERFINAL; + } + if(!config_set_option(ctx->env->cfg, opt, val)) { + lock_basic_unlock(&ctx->cfglock); + return UB_SYNTAX; + } + lock_basic_unlock(&ctx->cfglock); + return UB_NOERROR; +} + +int +ub_ctx_get_option(struct ub_ctx* ctx, char* opt, char** str) +{ + int r; + lock_basic_lock(&ctx->cfglock); + r = config_get_option_collate(ctx->env->cfg, opt, str); + lock_basic_unlock(&ctx->cfglock); + if(r == 0) r = UB_NOERROR; + else if(r == 1) r = UB_SYNTAX; + else if(r == 2) r = UB_NOMEM; + return r; +} + +int +ub_ctx_config(struct ub_ctx* ctx, char* fname) +{ + lock_basic_lock(&ctx->cfglock); + if(ctx->finalized) { + lock_basic_unlock(&ctx->cfglock); + return UB_AFTERFINAL; + } + if(!config_read(ctx->env->cfg, fname, NULL)) { + lock_basic_unlock(&ctx->cfglock); + return UB_SYNTAX; + } + lock_basic_unlock(&ctx->cfglock); + return UB_NOERROR; +} + +int +ub_ctx_add_ta(struct ub_ctx* ctx, char* ta) +{ + char* dup = strdup(ta); + if(!dup) return UB_NOMEM; + lock_basic_lock(&ctx->cfglock); + if(ctx->finalized) { + lock_basic_unlock(&ctx->cfglock); + free(dup); + return UB_AFTERFINAL; + } + if(!cfg_strlist_insert(&ctx->env->cfg->trust_anchor_list, dup)) { + lock_basic_unlock(&ctx->cfglock); + free(dup); + return UB_NOMEM; + } + lock_basic_unlock(&ctx->cfglock); + return UB_NOERROR; +} + +int +ub_ctx_add_ta_file(struct ub_ctx* ctx, char* fname) +{ + char* dup = strdup(fname); + if(!dup) return UB_NOMEM; + lock_basic_lock(&ctx->cfglock); + if(ctx->finalized) { + lock_basic_unlock(&ctx->cfglock); + free(dup); + return UB_AFTERFINAL; + } + if(!cfg_strlist_insert(&ctx->env->cfg->trust_anchor_file_list, dup)) { + lock_basic_unlock(&ctx->cfglock); + free(dup); + return UB_NOMEM; + } + lock_basic_unlock(&ctx->cfglock); + return UB_NOERROR; +} + +int +ub_ctx_trustedkeys(struct ub_ctx* ctx, char* fname) +{ + char* dup = strdup(fname); + if(!dup) return UB_NOMEM; + lock_basic_lock(&ctx->cfglock); + if(ctx->finalized) { + lock_basic_unlock(&ctx->cfglock); + free(dup); + return UB_AFTERFINAL; + } + if(!cfg_strlist_insert(&ctx->env->cfg->trusted_keys_file_list, dup)) { + lock_basic_unlock(&ctx->cfglock); + free(dup); + return UB_NOMEM; + } + lock_basic_unlock(&ctx->cfglock); + return UB_NOERROR; +} + +int +ub_ctx_debuglevel(struct ub_ctx* ctx, int d) +{ + lock_basic_lock(&ctx->cfglock); + verbosity = d; + ctx->env->cfg->verbosity = d; + lock_basic_unlock(&ctx->cfglock); + return UB_NOERROR; +} + +int ub_ctx_debugout(struct ub_ctx* ctx, void* out) +{ + lock_basic_lock(&ctx->cfglock); + log_file((FILE*)out); + ctx->logfile_override = 1; + ctx->log_out = out; + lock_basic_unlock(&ctx->cfglock); + return UB_NOERROR; +} + +int +ub_ctx_async(struct ub_ctx* ctx, int dothread) +{ +#ifdef THREADS_DISABLED + if(dothread) /* cannot do threading */ + return UB_NOERROR; +#endif + lock_basic_lock(&ctx->cfglock); + if(ctx->finalized) { + lock_basic_unlock(&ctx->cfglock); + return UB_AFTERFINAL; + } + ctx->dothread = dothread; + lock_basic_unlock(&ctx->cfglock); + return UB_NOERROR; +} + +int +ub_poll(struct ub_ctx* ctx) +{ + /* no need to hold lock while testing for readability. */ + return tube_poll(ctx->rr_pipe); +} + +int +ub_fd(struct ub_ctx* ctx) +{ + return tube_read_fd(ctx->rr_pipe); +} + +/** process answer from bg worker */ +static int +process_answer_detail(struct ub_ctx* ctx, uint8_t* msg, uint32_t len, + ub_callback_t* cb, void** cbarg, int* err, + struct ub_result** res) +{ + struct ctx_query* q; + if(context_serial_getcmd(msg, len) != UB_LIBCMD_ANSWER) { + log_err("error: bad data from bg worker %d", + (int)context_serial_getcmd(msg, len)); + return 0; + } + + lock_basic_lock(&ctx->cfglock); + q = context_deserialize_answer(ctx, msg, len, err); + if(!q) { + lock_basic_unlock(&ctx->cfglock); + /* probably simply the lookup that failed, i.e. + * response returned before cancel was sent out, so noerror */ + return 1; + } + log_assert(q->async); + + /* grab cb while locked */ + if(q->cancelled) { + *cb = NULL; + *cbarg = NULL; + } else { + *cb = q->cb; + *cbarg = q->cb_arg; + } + if(*err) { + *res = NULL; + ub_resolve_free(q->res); + } else { + /* parse the message, extract rcode, fill result */ + ldns_buffer* buf = ldns_buffer_new(q->msg_len); + struct regional* region = regional_create(); + *res = q->res; + (*res)->rcode = LDNS_RCODE_SERVFAIL; + if(region && buf) { + ldns_buffer_clear(buf); + ldns_buffer_write(buf, q->msg, q->msg_len); + ldns_buffer_flip(buf); + libworker_enter_result(*res, buf, region, + q->msg_security); + } + (*res)->answer_packet = q->msg; + (*res)->answer_len = (int)q->msg_len; + q->msg = NULL; + ldns_buffer_free(buf); + regional_destroy(region); + } + q->res = NULL; + /* delete the q from list */ + (void)rbtree_delete(&ctx->queries, q->node.key); + ctx->num_async--; + context_query_delete(q); + lock_basic_unlock(&ctx->cfglock); + + if(*cb) return 2; + ub_resolve_free(*res); + return 1; +} + +/** process answer from bg worker */ +static int +process_answer(struct ub_ctx* ctx, uint8_t* msg, uint32_t len) +{ + int err; + ub_callback_t cb; + void* cbarg; + struct ub_result* res; + int r; + + r = process_answer_detail(ctx, msg, len, &cb, &cbarg, &err, &res); + + /* no locks held while calling callback, so that library is + * re-entrant. */ + if(r == 2) + (*cb)(cbarg, err, res); + + return r; +} + +int +ub_process(struct ub_ctx* ctx) +{ + int r; + uint8_t* msg; + uint32_t len; + while(1) { + msg = NULL; + lock_basic_lock(&ctx->rrpipe_lock); + r = tube_read_msg(ctx->rr_pipe, &msg, &len, 1); + lock_basic_unlock(&ctx->rrpipe_lock); + if(r == 0) + return UB_PIPE; + else if(r == -1) + break; + if(!process_answer(ctx, msg, len)) { + free(msg); + return UB_PIPE; + } + free(msg); + } + return UB_NOERROR; +} + +int +ub_wait(struct ub_ctx* ctx) +{ + int err; + ub_callback_t cb; + void* cbarg; + struct ub_result* res; + int r; + uint8_t* msg; + uint32_t len; + /* this is basically the same loop as _process(), but with changes. + * holds the rrpipe lock and waits with tube_wait */ + while(1) { + lock_basic_lock(&ctx->rrpipe_lock); + lock_basic_lock(&ctx->cfglock); + if(ctx->num_async == 0) { + lock_basic_unlock(&ctx->cfglock); + lock_basic_unlock(&ctx->rrpipe_lock); + break; + } + lock_basic_unlock(&ctx->cfglock); + + /* keep rrpipe locked, while + * o waiting for pipe readable + * o parsing message + * o possibly decrementing num_async + * do callback without lock + */ + r = tube_wait(ctx->rr_pipe); + if(r) { + r = tube_read_msg(ctx->rr_pipe, &msg, &len, 1); + if(r == 0) { + lock_basic_unlock(&ctx->rrpipe_lock); + return UB_PIPE; + } + if(r == -1) { + lock_basic_unlock(&ctx->rrpipe_lock); + continue; + } + r = process_answer_detail(ctx, msg, len, + &cb, &cbarg, &err, &res); + lock_basic_unlock(&ctx->rrpipe_lock); + free(msg); + if(r == 0) + return UB_PIPE; + if(r == 2) + (*cb)(cbarg, err, res); + } else { + lock_basic_unlock(&ctx->rrpipe_lock); + } + } + return UB_NOERROR; +} + +int +ub_resolve(struct ub_ctx* ctx, char* name, int rrtype, + int rrclass, struct ub_result** result) +{ + struct ctx_query* q; + int r; + *result = NULL; + + lock_basic_lock(&ctx->cfglock); + if(!ctx->finalized) { + r = context_finalize(ctx); + if(r) { + lock_basic_unlock(&ctx->cfglock); + return r; + } + } + /* create new ctx_query and attempt to add to the list */ + lock_basic_unlock(&ctx->cfglock); + q = context_new(ctx, name, rrtype, rrclass, NULL, NULL); + if(!q) + return UB_NOMEM; + /* become a resolver thread for a bit */ + + r = libworker_fg(ctx, q); + if(r) { + lock_basic_lock(&ctx->cfglock); + (void)rbtree_delete(&ctx->queries, q->node.key); + context_query_delete(q); + lock_basic_unlock(&ctx->cfglock); + return r; + } + q->res->answer_packet = q->msg; + q->res->answer_len = (int)q->msg_len; + q->msg = NULL; + *result = q->res; + q->res = NULL; + + lock_basic_lock(&ctx->cfglock); + (void)rbtree_delete(&ctx->queries, q->node.key); + context_query_delete(q); + lock_basic_unlock(&ctx->cfglock); + return UB_NOERROR; +} + +int +ub_resolve_async(struct ub_ctx* ctx, char* name, int rrtype, + int rrclass, void* mydata, ub_callback_t callback, int* async_id) +{ + struct ctx_query* q; + uint8_t* msg = NULL; + uint32_t len = 0; + + if(async_id) + *async_id = 0; + lock_basic_lock(&ctx->cfglock); + if(!ctx->finalized) { + int r = context_finalize(ctx); + if(r) { + lock_basic_unlock(&ctx->cfglock); + return r; + } + } + if(!ctx->created_bg) { + int r; + ctx->created_bg = 1; + lock_basic_unlock(&ctx->cfglock); + r = libworker_bg(ctx); + if(r) { + lock_basic_lock(&ctx->cfglock); + ctx->created_bg = 0; + lock_basic_unlock(&ctx->cfglock); + return r; + } + } else { + lock_basic_unlock(&ctx->cfglock); + } + + /* create new ctx_query and attempt to add to the list */ + q = context_new(ctx, name, rrtype, rrclass, callback, mydata); + if(!q) + return UB_NOMEM; + + /* write over pipe to background worker */ + lock_basic_lock(&ctx->cfglock); + msg = context_serialize_new_query(q, &len); + if(!msg) { + (void)rbtree_delete(&ctx->queries, q->node.key); + ctx->num_async--; + context_query_delete(q); + lock_basic_unlock(&ctx->cfglock); + return UB_NOMEM; + } + if(async_id) + *async_id = q->querynum; + lock_basic_unlock(&ctx->cfglock); + + lock_basic_lock(&ctx->qqpipe_lock); + if(!tube_write_msg(ctx->qq_pipe, msg, len, 0)) { + lock_basic_unlock(&ctx->qqpipe_lock); + free(msg); + return UB_PIPE; + } + lock_basic_unlock(&ctx->qqpipe_lock); + free(msg); + return UB_NOERROR; +} + +int +ub_cancel(struct ub_ctx* ctx, int async_id) +{ + struct ctx_query* q; + uint8_t* msg = NULL; + uint32_t len = 0; + lock_basic_lock(&ctx->cfglock); + q = (struct ctx_query*)rbtree_search(&ctx->queries, &async_id); + if(!q || !q->async) { + /* it is not there, so nothing to do */ + lock_basic_unlock(&ctx->cfglock); + return UB_NOID; + } + log_assert(q->async); + q->cancelled = 1; + + /* delete it */ + if(!ctx->dothread) { /* if forked */ + (void)rbtree_delete(&ctx->queries, q->node.key); + ctx->num_async--; + msg = context_serialize_cancel(q, &len); + context_query_delete(q); + lock_basic_unlock(&ctx->cfglock); + if(!msg) { + return UB_NOMEM; + } + /* send cancel to background worker */ + lock_basic_lock(&ctx->qqpipe_lock); + if(!tube_write_msg(ctx->qq_pipe, msg, len, 0)) { + lock_basic_unlock(&ctx->qqpipe_lock); + free(msg); + return UB_PIPE; + } + lock_basic_unlock(&ctx->qqpipe_lock); + free(msg); + } else { + lock_basic_unlock(&ctx->cfglock); + } + return UB_NOERROR; +} + +void +ub_resolve_free(struct ub_result* result) +{ + char** p; + if(!result) return; + free(result->qname); + if(result->canonname != result->qname) + free(result->canonname); + if(result->data) + for(p = result->data; *p; p++) + free(*p); + free(result->data); + free(result->len); + free(result->answer_packet); + free(result->why_bogus); + free(result); +} + +const char* +ub_strerror(int err) +{ + switch(err) { + case UB_NOERROR: return "no error"; + case UB_SOCKET: return "socket io error"; + case UB_NOMEM: return "out of memory"; + case UB_SYNTAX: return "syntax error"; + case UB_SERVFAIL: return "server failure"; + case UB_FORKFAIL: return "could not fork"; + case UB_INITFAIL: return "initialization failure"; + case UB_AFTERFINAL: return "setting change after finalize"; + case UB_PIPE: return "error in pipe communication with async"; + case UB_READFILE: return "error reading file"; + case UB_NOID: return "error async_id does not exist"; + default: return "unknown error"; + } +} + +int +ub_ctx_set_fwd(struct ub_ctx* ctx, char* addr) +{ + struct sockaddr_storage storage; + socklen_t stlen; + struct config_stub* s; + char* dupl; + lock_basic_lock(&ctx->cfglock); + if(ctx->finalized) { + lock_basic_unlock(&ctx->cfglock); + errno=EINVAL; + return UB_AFTERFINAL; + } + if(!addr) { + /* disable fwd mode - the root stub should be first. */ + if(ctx->env->cfg->forwards && + strcmp(ctx->env->cfg->forwards->name, ".") == 0) { + s = ctx->env->cfg->forwards; + ctx->env->cfg->forwards = s->next; + s->next = NULL; + config_delstubs(s); + } + lock_basic_unlock(&ctx->cfglock); + return UB_NOERROR; + } + lock_basic_unlock(&ctx->cfglock); + + /* check syntax for addr */ + if(!extstrtoaddr(addr, &storage, &stlen)) { + errno=EINVAL; + return UB_SYNTAX; + } + + /* it parses, add root stub in front of list */ + lock_basic_lock(&ctx->cfglock); + if(!ctx->env->cfg->forwards || + strcmp(ctx->env->cfg->forwards->name, ".") != 0) { + s = calloc(1, sizeof(*s)); + if(!s) { + lock_basic_unlock(&ctx->cfglock); + errno=ENOMEM; + return UB_NOMEM; + } + s->name = strdup("."); + if(!s->name) { + free(s); + lock_basic_unlock(&ctx->cfglock); + errno=ENOMEM; + return UB_NOMEM; + } + s->next = ctx->env->cfg->forwards; + ctx->env->cfg->forwards = s; + } else { + log_assert(ctx->env->cfg->forwards); + s = ctx->env->cfg->forwards; + } + dupl = strdup(addr); + if(!dupl) { + lock_basic_unlock(&ctx->cfglock); + errno=ENOMEM; + return UB_NOMEM; + } + if(!cfg_strlist_insert(&s->addrs, dupl)) { + free(dupl); + lock_basic_unlock(&ctx->cfglock); + errno=ENOMEM; + return UB_NOMEM; + } + lock_basic_unlock(&ctx->cfglock); + return UB_NOERROR; +} + +int +ub_ctx_resolvconf(struct ub_ctx* ctx, char* fname) +{ + FILE* in; + int numserv = 0; + char buf[1024]; + char* parse, *addr; + int r; + + if(fname == NULL) { +#if !defined(UB_ON_WINDOWS) || !defined(HAVE_WINDOWS_H) + fname = "/etc/resolv.conf"; +#else + FIXED_INFO *info; + ULONG buflen = sizeof(*info); + IP_ADDR_STRING *ptr; + + info = (FIXED_INFO *) malloc(sizeof (FIXED_INFO)); + if (info == NULL) + return UB_READFILE; + + if (GetNetworkParams(info, &buflen) == ERROR_BUFFER_OVERFLOW) { + free(info); + info = (FIXED_INFO *) malloc(buflen); + if (info == NULL) + return UB_READFILE; + } + + if (GetNetworkParams(info, &buflen) == NO_ERROR) { + int retval=0; + ptr = &(info->DnsServerList); + while (ptr) { + numserv++; + if((retval=ub_ctx_set_fwd(ctx, + ptr->IpAddress.String)!=0)) { + free(info); + return retval; + } + ptr = ptr->Next; + } + free(info); + if (numserv==0) + return UB_READFILE; + return UB_NOERROR; + } + free(info); + return UB_READFILE; +#endif /* WINDOWS */ + } + in = fopen(fname, "r"); + if(!in) { + /* error in errno! perror(fname) */ + return UB_READFILE; + } + while(fgets(buf, (int)sizeof(buf), in)) { + buf[sizeof(buf)-1] = 0; + parse=buf; + while(*parse == ' ' || *parse == '\t') + parse++; + if(strncmp(parse, "nameserver", 10) == 0) { + numserv++; + parse += 10; /* skip 'nameserver' */ + /* skip whitespace */ + while(*parse == ' ' || *parse == '\t') + parse++; + addr = parse; + /* skip [0-9a-fA-F.:]*, i.e. IP4 and IP6 address */ + while(isxdigit(*parse) || *parse=='.' || *parse==':') + parse++; + /* terminate after the address, remove newline */ + *parse = 0; + + if((r = ub_ctx_set_fwd(ctx, addr)) != UB_NOERROR) { + fclose(in); + return r; + } + } + } + fclose(in); + if(numserv == 0) { + /* from resolv.conf(5) if none given, use localhost */ + return ub_ctx_set_fwd(ctx, "127.0.0.1"); + } + return UB_NOERROR; +} + +int +ub_ctx_hosts(struct ub_ctx* ctx, char* fname) +{ + FILE* in; + char buf[1024], ldata[1024]; + char* parse, *addr, *name, *ins; + lock_basic_lock(&ctx->cfglock); + if(ctx->finalized) { + lock_basic_unlock(&ctx->cfglock); + errno=EINVAL; + return UB_AFTERFINAL; + } + lock_basic_unlock(&ctx->cfglock); + if(fname == NULL) { +#if defined(UB_ON_WINDOWS) && defined(HAVE_WINDOWS_H) + /* + * If this is Windows NT/XP/2K it's in + * %WINDIR%\system32\drivers\etc\hosts. + * If this is Windows 95/98/Me it's in %WINDIR%\hosts. + */ + name = getenv("WINDIR"); + if (name != NULL) { + int retval=0; + snprintf(buf, sizeof(buf), "%s%s", name, + "\\system32\\drivers\\etc\\hosts"); + if((retval=ub_ctx_hosts(ctx, buf)) !=0 ) { + snprintf(buf, sizeof(buf), "%s%s", name, + "\\hosts"); + retval=ub_ctx_hosts(ctx, buf); + } + free(name); + return retval; + } + return UB_READFILE; +#else + fname = "/etc/hosts"; +#endif /* WIN32 */ + } + in = fopen(fname, "r"); + if(!in) { + /* error in errno! perror(fname) */ + return UB_READFILE; + } + while(fgets(buf, (int)sizeof(buf), in)) { + buf[sizeof(buf)-1] = 0; + parse=buf; + while(*parse == ' ' || *parse == '\t') + parse++; + if(*parse == '#') + continue; /* skip comment */ + /* format: spaces spaces ... */ + addr = parse; + /* skip addr */ + while(isxdigit(*parse) || *parse == '.' || *parse == ':') + parse++; + if(*parse == '\n' || *parse == 0) + continue; + if(*parse == '%') + continue; /* ignore macOSX fe80::1%lo0 localhost */ + if(*parse != ' ' && *parse != '\t') { + /* must have whitespace after address */ + fclose(in); + errno=EINVAL; + return UB_SYNTAX; + } + *parse++ = 0; /* end delimiter for addr ... */ + /* go to names and add them */ + while(*parse) { + while(*parse == ' ' || *parse == '\t' || *parse=='\n') + parse++; + if(*parse == 0 || *parse == '#') + break; + /* skip name, allows (too) many printable characters */ + name = parse; + while('!' <= *parse && *parse <= '~') + parse++; + if(*parse) + *parse++ = 0; /* end delimiter for name */ + snprintf(ldata, sizeof(ldata), "%s %s %s", + name, str_is_ip6(addr)?"AAAA":"A", addr); + ins = strdup(ldata); + if(!ins) { + /* out of memory */ + fclose(in); + errno=ENOMEM; + return UB_NOMEM; + } + lock_basic_lock(&ctx->cfglock); + if(!cfg_strlist_insert(&ctx->env->cfg->local_data, + ins)) { + lock_basic_unlock(&ctx->cfglock); + fclose(in); + free(ins); + errno=ENOMEM; + return UB_NOMEM; + } + lock_basic_unlock(&ctx->cfglock); + } + } + fclose(in); + return UB_NOERROR; +} + +/** finalize the context, if not already finalized */ +static int ub_ctx_finalize(struct ub_ctx* ctx) +{ + int res = 0; + lock_basic_lock(&ctx->cfglock); + if (!ctx->finalized) { + res = context_finalize(ctx); + } + lock_basic_unlock(&ctx->cfglock); + return res; +} + +/* Print local zones and RR data */ +int ub_ctx_print_local_zones(struct ub_ctx* ctx) +{ + int res = ub_ctx_finalize(ctx); + if (res) return res; + + local_zones_print(ctx->local_zones); + + return UB_NOERROR; +} + +/* Add a new zone */ +int ub_ctx_zone_add(struct ub_ctx* ctx, char *zone_name, char *zone_type) +{ + enum localzone_type t; + struct local_zone* z; + uint8_t* nm; + int nmlabs; + size_t nmlen; + + int res = ub_ctx_finalize(ctx); + if (res) return res; + + if(!local_zone_str2type(zone_type, &t)) { + return UB_SYNTAX; + } + + if(!parse_dname(zone_name, &nm, &nmlen, &nmlabs)) { + return UB_SYNTAX; + } + + lock_quick_lock(&ctx->local_zones->lock); + if((z=local_zones_find(ctx->local_zones, nm, nmlen, nmlabs, + LDNS_RR_CLASS_IN))) { + /* already present in tree */ + lock_rw_wrlock(&z->lock); + z->type = t; /* update type anyway */ + lock_rw_unlock(&z->lock); + lock_quick_unlock(&ctx->local_zones->lock); + free(nm); + return UB_NOERROR; + } + if(!local_zones_add_zone(ctx->local_zones, nm, nmlen, nmlabs, + LDNS_RR_CLASS_IN, t)) { + lock_quick_unlock(&ctx->local_zones->lock); + return UB_NOMEM; + } + lock_quick_unlock(&ctx->local_zones->lock); + return UB_NOERROR; +} + +/* Remove zone */ +int ub_ctx_zone_remove(struct ub_ctx* ctx, char *zone_name) +{ + struct local_zone* z; + uint8_t* nm; + int nmlabs; + size_t nmlen; + + int res = ub_ctx_finalize(ctx); + if (res) return res; + + if(!parse_dname(zone_name, &nm, &nmlen, &nmlabs)) { + return UB_SYNTAX; + } + + lock_quick_lock(&ctx->local_zones->lock); + if((z=local_zones_find(ctx->local_zones, nm, nmlen, nmlabs, + LDNS_RR_CLASS_IN))) { + /* present in tree */ + local_zones_del_zone(ctx->local_zones, z); + } + lock_quick_unlock(&ctx->local_zones->lock); + free(nm); + return UB_NOERROR; +} + +/* Add new RR data */ +int ub_ctx_data_add(struct ub_ctx* ctx, char *data) +{ + ldns_buffer* buf; + int res = ub_ctx_finalize(ctx); + if (res) return res; + + lock_basic_lock(&ctx->cfglock); + buf = ldns_buffer_new(ctx->env->cfg->msg_buffer_size); + lock_basic_unlock(&ctx->cfglock); + if(!buf) return UB_NOMEM; + + res = local_zones_add_RR(ctx->local_zones, data, buf); + + ldns_buffer_free(buf); + return (!res) ? UB_NOMEM : UB_NOERROR; +} + +/* Remove RR data */ +int ub_ctx_data_remove(struct ub_ctx* ctx, char *data) +{ + uint8_t* nm; + int nmlabs; + size_t nmlen; + int res = ub_ctx_finalize(ctx); + if (res) return res; + + if(!parse_dname(data, &nm, &nmlen, &nmlabs)) + return UB_SYNTAX; + + local_zones_del_data(ctx->local_zones, nm, nmlen, nmlabs, + LDNS_RR_CLASS_IN); + + free(nm); + return UB_NOERROR; +} + +const char* ub_version(void) +{ + return PACKAGE_VERSION; +} diff --git a/libunbound/libworker.c b/libunbound/libworker.c new file mode 100644 index 00000000000..917a9106d07 --- /dev/null +++ b/libunbound/libworker.c @@ -0,0 +1,920 @@ +/* + * libunbound/worker.c - worker thread or process that resolves + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains the worker process or thread that performs + * the DNS resolving and validation. The worker is called by a procedure + * and if in the background continues until exit, if in the foreground + * returns from the procedure when done. + */ +#include "config.h" +#include +#include +#include +#include "libunbound/libworker.h" +#include "libunbound/context.h" +#include "libunbound/unbound.h" +#include "services/outside_network.h" +#include "services/mesh.h" +#include "services/localzone.h" +#include "services/cache/rrset.h" +#include "services/outbound_list.h" +#include "util/module.h" +#include "util/regional.h" +#include "util/random.h" +#include "util/config_file.h" +#include "util/netevent.h" +#include "util/storage/lookup3.h" +#include "util/storage/slabhash.h" +#include "util/net_help.h" +#include "util/data/dname.h" +#include "util/data/msgreply.h" +#include "util/data/msgencode.h" +#include "util/tube.h" +#include "iterator/iter_fwd.h" +#include "iterator/iter_hints.h" + +/** handle new query command for bg worker */ +static void handle_newq(struct libworker* w, uint8_t* buf, uint32_t len); + +/** delete libworker struct */ +static void +libworker_delete(struct libworker* w) +{ + if(!w) return; + if(w->env) { + outside_network_quit_prepare(w->back); + mesh_delete(w->env->mesh); + context_release_alloc(w->ctx, w->env->alloc, + !w->is_bg || w->is_bg_thread); + ldns_buffer_free(w->env->scratch_buffer); + regional_destroy(w->env->scratch); + forwards_delete(w->env->fwds); + hints_delete(w->env->hints); + ub_randfree(w->env->rnd); + free(w->env); + } + SSL_CTX_free(w->sslctx); + outside_network_delete(w->back); + comm_base_delete(w->base); + free(w); +} + +/** setup fresh libworker struct */ +static struct libworker* +libworker_setup(struct ub_ctx* ctx, int is_bg) +{ + unsigned int seed; + struct libworker* w = (struct libworker*)calloc(1, sizeof(*w)); + struct config_file* cfg = ctx->env->cfg; + int* ports; + int numports; + if(!w) return NULL; + w->is_bg = is_bg; + w->ctx = ctx; + w->env = (struct module_env*)malloc(sizeof(*w->env)); + if(!w->env) { + free(w); + return NULL; + } + *w->env = *ctx->env; + w->env->alloc = context_obtain_alloc(ctx, !w->is_bg || w->is_bg_thread); + if(!w->env->alloc) { + libworker_delete(w); + return NULL; + } + w->thread_num = w->env->alloc->thread_num; + alloc_set_id_cleanup(w->env->alloc, &libworker_alloc_cleanup, w); + if(!w->is_bg || w->is_bg_thread) { + lock_basic_lock(&ctx->cfglock); + } + w->env->scratch = regional_create_custom(cfg->msg_buffer_size); + w->env->scratch_buffer = ldns_buffer_new(cfg->msg_buffer_size); + w->env->fwds = forwards_create(); + if(w->env->fwds && !forwards_apply_cfg(w->env->fwds, cfg)) { + forwards_delete(w->env->fwds); + w->env->fwds = NULL; + } + w->env->hints = hints_create(); + if(w->env->hints && !hints_apply_cfg(w->env->hints, cfg)) { + hints_delete(w->env->hints); + w->env->hints = NULL; + } + if(cfg->ssl_upstream) { + w->sslctx = connect_sslctx_create(NULL, NULL, NULL); + if(!w->sslctx) { + /* to make the setup fail after unlock */ + hints_delete(w->env->hints); + w->env->hints = NULL; + } + } + if(!w->is_bg || w->is_bg_thread) { + lock_basic_unlock(&ctx->cfglock); + } + if(!w->env->scratch || !w->env->scratch_buffer || !w->env->fwds || + !w->env->hints) { + libworker_delete(w); + return NULL; + } + w->env->worker = (struct worker*)w; + w->env->probe_timer = NULL; + seed = (unsigned int)time(NULL) ^ (unsigned int)getpid() ^ + (((unsigned int)w->thread_num)<<17); + seed ^= (unsigned int)w->env->alloc->next_id; + if(!w->is_bg || w->is_bg_thread) { + lock_basic_lock(&ctx->cfglock); + } + if(!(w->env->rnd = ub_initstate(seed, ctx->seed_rnd))) { + if(!w->is_bg || w->is_bg_thread) { + lock_basic_unlock(&ctx->cfglock); + } + seed = 0; + libworker_delete(w); + return NULL; + } + if(!w->is_bg || w->is_bg_thread) { + lock_basic_unlock(&ctx->cfglock); + } + if(1) { + /* primitive lockout for threading: if it overwrites another + * thread it is like wiping the cache (which is likely empty + * at the start) */ + /* note we are holding the ctx lock in normal threaded + * cases so that is solved properly, it is only for many ctx + * in different threads that this may clash */ + static int done_raninit = 0; + if(!done_raninit) { + done_raninit = 1; + hash_set_raninit((uint32_t)ub_random(w->env->rnd)); + } + } + seed = 0; + + w->base = comm_base_create(0); + if(!w->base) { + libworker_delete(w); + return NULL; + } + if(!w->is_bg || w->is_bg_thread) { + lock_basic_lock(&ctx->cfglock); + } + numports = cfg_condense_ports(cfg, &ports); + if(numports == 0) { + libworker_delete(w); + return NULL; + } + w->back = outside_network_create(w->base, cfg->msg_buffer_size, + (size_t)cfg->outgoing_num_ports, cfg->out_ifs, + cfg->num_out_ifs, cfg->do_ip4, cfg->do_ip6, + cfg->do_tcp?cfg->outgoing_num_tcp:0, + w->env->infra_cache, w->env->rnd, cfg->use_caps_bits_for_id, + ports, numports, cfg->unwanted_threshold, + &libworker_alloc_cleanup, w, cfg->do_udp, w->sslctx); + if(!w->is_bg || w->is_bg_thread) { + lock_basic_unlock(&ctx->cfglock); + } + free(ports); + if(!w->back) { + libworker_delete(w); + return NULL; + } + w->env->mesh = mesh_create(&ctx->mods, w->env); + if(!w->env->mesh) { + libworker_delete(w); + return NULL; + } + w->env->send_query = &libworker_send_query; + w->env->detach_subs = &mesh_detach_subs; + w->env->attach_sub = &mesh_attach_sub; + w->env->kill_sub = &mesh_state_delete; + w->env->detect_cycle = &mesh_detect_cycle; + comm_base_timept(w->base, &w->env->now, &w->env->now_tv); + return w; +} + +/** handle cancel command for bg worker */ +static void +handle_cancel(struct libworker* w, uint8_t* buf, uint32_t len) +{ + struct ctx_query* q; + if(w->is_bg_thread) { + lock_basic_lock(&w->ctx->cfglock); + q = context_deserialize_cancel(w->ctx, buf, len); + lock_basic_unlock(&w->ctx->cfglock); + } else { + q = context_deserialize_cancel(w->ctx, buf, len); + } + if(!q) { + /* probably simply lookup failed, i.e. the message had been + * processed and answered before the cancel arrived */ + return; + } + q->cancelled = 1; + free(buf); +} + +/** do control command coming into bg server */ +static void +libworker_do_cmd(struct libworker* w, uint8_t* msg, uint32_t len) +{ + switch(context_serial_getcmd(msg, len)) { + default: + case UB_LIBCMD_ANSWER: + log_err("unknown command for bg worker %d", + (int)context_serial_getcmd(msg, len)); + /* and fall through to quit */ + case UB_LIBCMD_QUIT: + free(msg); + comm_base_exit(w->base); + break; + case UB_LIBCMD_NEWQUERY: + handle_newq(w, msg, len); + break; + case UB_LIBCMD_CANCEL: + handle_cancel(w, msg, len); + break; + } +} + +/** handle control command coming into server */ +void +libworker_handle_control_cmd(struct tube* ATTR_UNUSED(tube), + uint8_t* msg, size_t len, int err, void* arg) +{ + struct libworker* w = (struct libworker*)arg; + + if(err != 0) { + free(msg); + /* it is of no use to go on, exit */ + comm_base_exit(w->base); + return; + } + libworker_do_cmd(w, msg, len); /* also frees the buf */ +} + +/** the background thread func */ +static void* +libworker_dobg(void* arg) +{ + /* setup */ + uint32_t m; + struct libworker* w = (struct libworker*)arg; + struct ub_ctx* ctx; + if(!w) { + log_err("libunbound bg worker init failed, nomem"); + return NULL; + } + ctx = w->ctx; + log_thread_set(&w->thread_num); +#ifdef THREADS_DISABLED + /* we are forked */ + w->is_bg_thread = 0; + /* close non-used parts of the pipes */ + tube_close_write(ctx->qq_pipe); + tube_close_read(ctx->rr_pipe); +#endif + if(!tube_setup_bg_listen(ctx->qq_pipe, w->base, + libworker_handle_control_cmd, w)) { + log_err("libunbound bg worker init failed, no bglisten"); + return NULL; + } + if(!tube_setup_bg_write(ctx->rr_pipe, w->base)) { + log_err("libunbound bg worker init failed, no bgwrite"); + return NULL; + } + + /* do the work */ + comm_base_dispatch(w->base); + + /* cleanup */ + m = UB_LIBCMD_QUIT; + tube_remove_bg_listen(w->ctx->qq_pipe); + tube_remove_bg_write(w->ctx->rr_pipe); + libworker_delete(w); + (void)tube_write_msg(ctx->rr_pipe, (uint8_t*)&m, + (uint32_t)sizeof(m), 0); +#ifdef THREADS_DISABLED + /* close pipes from forked process before exit */ + tube_close_read(ctx->qq_pipe); + tube_close_write(ctx->rr_pipe); +#endif + return NULL; +} + +int libworker_bg(struct ub_ctx* ctx) +{ + struct libworker* w; + /* fork or threadcreate */ + lock_basic_lock(&ctx->cfglock); + if(ctx->dothread) { + lock_basic_unlock(&ctx->cfglock); + w = libworker_setup(ctx, 1); + if(!w) return UB_NOMEM; + w->is_bg_thread = 1; +#ifdef ENABLE_LOCK_CHECKS + w->thread_num = 1; /* for nicer DEBUG checklocks */ +#endif + ub_thread_create(&ctx->bg_tid, libworker_dobg, w); + } else { + lock_basic_unlock(&ctx->cfglock); +#ifndef HAVE_FORK + /* no fork on windows */ + return UB_FORKFAIL; +#else /* HAVE_FORK */ + switch((ctx->bg_pid=fork())) { + case 0: + w = libworker_setup(ctx, 1); + if(!w) fatal_exit("out of memory"); + /* close non-used parts of the pipes */ + tube_close_write(ctx->qq_pipe); + tube_close_read(ctx->rr_pipe); + (void)libworker_dobg(w); + exit(0); + break; + case -1: + return UB_FORKFAIL; + default: + break; + } +#endif /* HAVE_FORK */ + } + return UB_NOERROR; +} + +/** get msg reply struct (in temp region) */ +static struct reply_info* +parse_reply(ldns_buffer* pkt, struct regional* region, struct query_info* qi) +{ + struct reply_info* rep; + struct msg_parse* msg; + if(!(msg = regional_alloc(region, sizeof(*msg)))) { + return NULL; + } + memset(msg, 0, sizeof(*msg)); + ldns_buffer_set_position(pkt, 0); + if(parse_packet(pkt, msg, region) != 0) + return 0; + if(!parse_create_msg(pkt, msg, NULL, qi, &rep, region)) { + return 0; + } + return rep; +} + +/** insert canonname */ +static int +fill_canon(struct ub_result* res, uint8_t* s) +{ + char buf[255+2]; + dname_str(s, buf); + res->canonname = strdup(buf); + return res->canonname != 0; +} + +/** fill data into result */ +static int +fill_res(struct ub_result* res, struct ub_packed_rrset_key* answer, + uint8_t* finalcname, struct query_info* rq) +{ + size_t i; + struct packed_rrset_data* data; + if(!answer) { + if(finalcname) { + if(!fill_canon(res, finalcname)) + return 0; /* out of memory */ + } + res->data = (char**)calloc(1, sizeof(char*)); + res->len = (int*)calloc(1, sizeof(int)); + return (res->data && res->len); + } + data = (struct packed_rrset_data*)answer->entry.data; + if(query_dname_compare(rq->qname, answer->rk.dname) != 0) { + if(!fill_canon(res, answer->rk.dname)) + return 0; /* out of memory */ + } else res->canonname = NULL; + res->data = (char**)calloc(data->count+1, sizeof(char*)); + res->len = (int*)calloc(data->count+1, sizeof(int)); + if(!res->data || !res->len) + return 0; /* out of memory */ + for(i=0; icount; i++) { + /* remove rdlength from rdata */ + res->len[i] = (int)(data->rr_len[i] - 2); + res->data[i] = memdup(data->rr_data[i]+2, (size_t)res->len[i]); + if(!res->data[i]) + return 0; /* out of memory */ + } + res->data[data->count] = NULL; + res->len[data->count] = 0; + return 1; +} + +/** fill result from parsed message, on error fills servfail */ +void +libworker_enter_result(struct ub_result* res, ldns_buffer* buf, + struct regional* temp, enum sec_status msg_security) +{ + struct query_info rq; + struct reply_info* rep; + res->rcode = LDNS_RCODE_SERVFAIL; + rep = parse_reply(buf, temp, &rq); + if(!rep) { + log_err("cannot parse buf"); + return; /* error parsing buf, or out of memory */ + } + if(!fill_res(res, reply_find_answer_rrset(&rq, rep), + reply_find_final_cname_target(&rq, rep), &rq)) + return; /* out of memory */ + /* rcode, havedata, nxdomain, secure, bogus */ + res->rcode = (int)FLAGS_GET_RCODE(rep->flags); + if(res->data && res->data[0]) + res->havedata = 1; + if(res->rcode == LDNS_RCODE_NXDOMAIN) + res->nxdomain = 1; + if(msg_security == sec_status_secure) + res->secure = 1; + if(msg_security == sec_status_bogus) + res->bogus = 1; +} + +/** fillup fg results */ +static void +libworker_fillup_fg(struct ctx_query* q, int rcode, ldns_buffer* buf, + enum sec_status s, char* why_bogus) +{ + if(why_bogus) + q->res->why_bogus = strdup(why_bogus); + if(rcode != 0) { + q->res->rcode = rcode; + q->msg_security = s; + return; + } + + q->res->rcode = LDNS_RCODE_SERVFAIL; + q->msg_security = 0; + q->msg = memdup(ldns_buffer_begin(buf), ldns_buffer_limit(buf)); + q->msg_len = ldns_buffer_limit(buf); + if(!q->msg) { + return; /* the error is in the rcode */ + } + + /* canonname and results */ + q->msg_security = s; + libworker_enter_result(q->res, buf, q->w->env->scratch, s); +} + +void +libworker_fg_done_cb(void* arg, int rcode, ldns_buffer* buf, enum sec_status s, + char* why_bogus) +{ + struct ctx_query* q = (struct ctx_query*)arg; + /* fg query is done; exit comm base */ + comm_base_exit(q->w->base); + + libworker_fillup_fg(q, rcode, buf, s, why_bogus); +} + +/** setup qinfo and edns */ +static int +setup_qinfo_edns(struct libworker* w, struct ctx_query* q, + struct query_info* qinfo, struct edns_data* edns) +{ + ldns_rdf* rdf; + qinfo->qtype = (uint16_t)q->res->qtype; + qinfo->qclass = (uint16_t)q->res->qclass; + rdf = ldns_dname_new_frm_str(q->res->qname); + if(!rdf) { + return 0; + } +#ifdef UNBOUND_ALLOC_LITE + qinfo->qname = memdup(ldns_rdf_data(rdf), ldns_rdf_size(rdf)); + qinfo->qname_len = ldns_rdf_size(rdf); + ldns_rdf_deep_free(rdf); + rdf = 0; +#else + qinfo->qname = ldns_rdf_data(rdf); + qinfo->qname_len = ldns_rdf_size(rdf); +#endif + edns->edns_present = 1; + edns->ext_rcode = 0; + edns->edns_version = 0; + edns->bits = EDNS_DO; + if(ldns_buffer_capacity(w->back->udp_buff) < 65535) + edns->udp_size = (uint16_t)ldns_buffer_capacity( + w->back->udp_buff); + else edns->udp_size = 65535; + ldns_rdf_free(rdf); + return 1; +} + +int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q) +{ + struct libworker* w = libworker_setup(ctx, 0); + uint16_t qflags, qid; + struct query_info qinfo; + struct edns_data edns; + if(!w) + return UB_INITFAIL; + if(!setup_qinfo_edns(w, q, &qinfo, &edns)) { + libworker_delete(w); + return UB_SYNTAX; + } + qid = 0; + qflags = BIT_RD; + q->w = w; + /* see if there is a fixed answer */ + ldns_buffer_write_u16_at(w->back->udp_buff, 0, qid); + ldns_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)) { + regional_free_all(w->env->scratch); + libworker_fillup_fg(q, LDNS_RCODE_NOERROR, + w->back->udp_buff, sec_status_insecure, NULL); + libworker_delete(w); + free(qinfo.qname); + return UB_NOERROR; + } + /* process new query */ + if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns, + w->back->udp_buff, qid, libworker_fg_done_cb, q)) { + free(qinfo.qname); + return UB_NOMEM; + } + free(qinfo.qname); + + /* wait for reply */ + comm_base_dispatch(w->base); + + libworker_delete(w); + return UB_NOERROR; +} + +/** add result to the bg worker result queue */ +static void +add_bg_result(struct libworker* w, struct ctx_query* q, ldns_buffer* pkt, + int err, char* reason) +{ + uint8_t* msg = NULL; + uint32_t len = 0; + + /* serialize and delete unneeded q */ + if(w->is_bg_thread) { + lock_basic_lock(&w->ctx->cfglock); + if(reason) + q->res->why_bogus = strdup(reason); + if(pkt) { + q->msg_len = ldns_buffer_remaining(pkt); + q->msg = memdup(ldns_buffer_begin(pkt), q->msg_len); + if(!q->msg) + msg = context_serialize_answer(q, UB_NOMEM, + NULL, &len); + else msg = context_serialize_answer(q, err, + NULL, &len); + } else msg = context_serialize_answer(q, err, NULL, &len); + lock_basic_unlock(&w->ctx->cfglock); + } else { + if(reason) + q->res->why_bogus = strdup(reason); + msg = context_serialize_answer(q, err, pkt, &len); + (void)rbtree_delete(&w->ctx->queries, q->node.key); + w->ctx->num_async--; + context_query_delete(q); + } + + if(!msg) { + log_err("out of memory for async answer"); + return; + } + if(!tube_queue_item(w->ctx->rr_pipe, msg, len)) { + log_err("out of memory for async answer"); + return; + } +} + +void +libworker_bg_done_cb(void* arg, int rcode, ldns_buffer* buf, enum sec_status s, + char* why_bogus) +{ + struct ctx_query* q = (struct ctx_query*)arg; + + if(q->cancelled) { + if(q->w->is_bg_thread) { + /* delete it now */ + struct ub_ctx* ctx = q->w->ctx; + lock_basic_lock(&ctx->cfglock); + (void)rbtree_delete(&ctx->queries, q->node.key); + ctx->num_async--; + context_query_delete(q); + lock_basic_unlock(&ctx->cfglock); + } + /* cancelled, do not give answer */ + return; + } + q->msg_security = s; + if(rcode != 0) { + error_encode(buf, rcode, NULL, 0, BIT_RD, NULL); + } + add_bg_result(q->w, q, buf, UB_NOERROR, why_bogus); +} + + +/** handle new query command for bg worker */ +static void +handle_newq(struct libworker* w, uint8_t* buf, uint32_t len) +{ + uint16_t qflags, qid; + struct query_info qinfo; + struct edns_data edns; + struct ctx_query* q; + if(w->is_bg_thread) { + lock_basic_lock(&w->ctx->cfglock); + q = context_lookup_new_query(w->ctx, buf, len); + lock_basic_unlock(&w->ctx->cfglock); + } else { + q = context_deserialize_new_query(w->ctx, buf, len); + } + free(buf); + if(!q) { + log_err("failed to deserialize newq"); + return; + } + if(!setup_qinfo_edns(w, q, &qinfo, &edns)) { + add_bg_result(w, q, NULL, UB_SYNTAX, NULL); + return; + } + qid = 0; + qflags = BIT_RD; + /* see if there is a fixed answer */ + ldns_buffer_write_u16_at(w->back->udp_buff, 0, qid); + ldns_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)) { + regional_free_all(w->env->scratch); + q->msg_security = sec_status_insecure; + add_bg_result(w, q, w->back->udp_buff, UB_NOERROR, NULL); + free(qinfo.qname); + return; + } + q->w = w; + /* process new query */ + if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns, + w->back->udp_buff, qid, libworker_bg_done_cb, q)) { + add_bg_result(w, q, NULL, UB_NOMEM, NULL); + } + free(qinfo.qname); +} + +void libworker_alloc_cleanup(void* arg) +{ + struct libworker* w = (struct libworker*)arg; + slabhash_clear(&w->env->rrset_cache->table); + slabhash_clear(w->env->msg_cache); +} + +/** compare outbound entry qstates */ +static int +outbound_entry_compare(void* a, void* b) +{ + struct outbound_entry* e1 = (struct outbound_entry*)a; + struct outbound_entry* e2 = (struct outbound_entry*)b; + if(e1->qstate == e2->qstate) + return 1; + return 0; +} + +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, 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( + q->region, sizeof(*e)); + if(!e) + return NULL; + e->qstate = q; + e->qsent = outnet_serviced_query(w->back, qname, + qnamelen, qtype, qclass, flags, dnssec, want_dnssec, + q->env->cfg->tcp_upstream, q->env->cfg->ssl_upstream, addr, + addrlen, zone, zonelen, libworker_handle_service_reply, e, + w->back->udp_buff, &outbound_entry_compare); + if(!e->qsent) { + return NULL; + } + return e; +} + +int +libworker_handle_reply(struct comm_point* c, void* arg, int error, + struct comm_reply* reply_info) +{ + struct module_qstate* q = (struct module_qstate*)arg; + struct libworker* lw = (struct libworker*)q->env->worker; + struct outbound_entry e; + e.qstate = q; + e.qsent = NULL; + + if(error != 0) { + mesh_report_reply(lw->env->mesh, &e, reply_info, error); + return 0; + } + /* sanity check. */ + if(!LDNS_QR_WIRE(ldns_buffer_begin(c->buffer)) + || LDNS_OPCODE_WIRE(ldns_buffer_begin(c->buffer)) != + LDNS_PACKET_QUERY + || LDNS_QDCOUNT(ldns_buffer_begin(c->buffer)) > 1) { + /* error becomes timeout for the module as if this reply + * never arrived. */ + mesh_report_reply(lw->env->mesh, &e, reply_info, + NETEVENT_TIMEOUT); + return 0; + } + mesh_report_reply(lw->env->mesh, &e, reply_info, NETEVENT_NOERROR); + return 0; +} + +int +libworker_handle_service_reply(struct comm_point* c, void* arg, int error, + struct comm_reply* reply_info) +{ + struct outbound_entry* e = (struct outbound_entry*)arg; + struct libworker* lw = (struct libworker*)e->qstate->env->worker; + + if(error != 0) { + mesh_report_reply(lw->env->mesh, e, reply_info, error); + return 0; + } + /* sanity check. */ + if(!LDNS_QR_WIRE(ldns_buffer_begin(c->buffer)) + || LDNS_OPCODE_WIRE(ldns_buffer_begin(c->buffer)) != + LDNS_PACKET_QUERY + || LDNS_QDCOUNT(ldns_buffer_begin(c->buffer)) > 1) { + /* error becomes timeout for the module as if this reply + * never arrived. */ + mesh_report_reply(lw->env->mesh, e, reply_info, + NETEVENT_TIMEOUT); + return 0; + } + mesh_report_reply(lw->env->mesh, e, reply_info, NETEVENT_NOERROR); + return 0; +} + +/* --- fake callbacks for fptr_wlist to work --- */ +void worker_handle_control_cmd(struct tube* ATTR_UNUSED(tube), + uint8_t* ATTR_UNUSED(buffer), size_t ATTR_UNUSED(len), + int ATTR_UNUSED(error), void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + +int worker_handle_request(struct comm_point* ATTR_UNUSED(c), + void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), + struct comm_reply* ATTR_UNUSED(repinfo)) +{ + log_assert(0); + return 0; +} + +int worker_handle_reply(struct comm_point* ATTR_UNUSED(c), + void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), + struct comm_reply* ATTR_UNUSED(reply_info)) +{ + log_assert(0); + return 0; +} + +int worker_handle_service_reply(struct comm_point* ATTR_UNUSED(c), + void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), + struct comm_reply* ATTR_UNUSED(reply_info)) +{ + log_assert(0); + return 0; +} + +int remote_accept_callback(struct comm_point* ATTR_UNUSED(c), + void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), + struct comm_reply* ATTR_UNUSED(repinfo)) +{ + log_assert(0); + return 0; +} + +int remote_control_callback(struct comm_point* ATTR_UNUSED(c), + void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), + struct comm_reply* ATTR_UNUSED(repinfo)) +{ + log_assert(0); + return 0; +} + +void worker_sighandler(int ATTR_UNUSED(sig), void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + +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), + struct sockaddr_storage* ATTR_UNUSED(addr), + socklen_t ATTR_UNUSED(addrlen), struct module_qstate* ATTR_UNUSED(q)) +{ + log_assert(0); + return 0; +} + +void +worker_alloc_cleanup(void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + +void worker_stat_timer_cb(void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + +void worker_probe_timer_cb(void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + +void worker_start_accept(void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + +void worker_stop_accept(void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + +int order_lock_cmp(const void* ATTR_UNUSED(e1), const void* ATTR_UNUSED(e2)) +{ + log_assert(0); + return 0; +} + +int +codeline_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b)) +{ + log_assert(0); + return 0; +} + +int replay_var_compare(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b)) +{ + log_assert(0); + return 0; +} + +void remote_get_opt_ssl(char* ATTR_UNUSED(str), void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + +#ifdef UB_ON_WINDOWS +void +worker_win_stop_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev), void* + ATTR_UNUSED(arg)) { + log_assert(0); +} + +void +wsvc_cron_cb(void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} +#endif /* UB_ON_WINDOWS */ diff --git a/libunbound/libworker.h b/libunbound/libworker.h new file mode 100644 index 00000000000..c3896fc5a82 --- /dev/null +++ b/libunbound/libworker.h @@ -0,0 +1,170 @@ +/* + * libunbound/worker.h - worker thread or process that resolves + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains the worker process or thread that performs + * the DNS resolving and validation. The worker is called by a procedure + * and if in the background continues until exit, if in the foreground + * returns from the procedure when done. + */ +#ifndef LIBUNBOUND_WORKER_H +#define LIBUNBOUND_WORKER_H +#include "util/data/packed_rrset.h" +struct ub_ctx; +struct ub_result; +struct module_env; +struct comm_base; +struct outside_network; +struct ub_randstate; +struct ctx_query; +struct outbound_entry; +struct module_qstate; +struct comm_point; +struct comm_reply; +struct regional; +struct tube; + +/** + * The library-worker status structure + * Internal to the worker. + */ +struct libworker { + /** every worker has a unique thread_num. (first in struct) */ + int thread_num; + /** context we are operating under */ + struct ub_ctx* ctx; + + /** is this the bg worker? */ + int is_bg; + /** is this a bg worker that is threaded (not forked)? */ + int is_bg_thread; + + /** copy of the module environment with worker local entries. */ + struct module_env* env; + /** the event base this worker works with */ + struct comm_base* base; + /** the backside outside network interface to the auth servers */ + struct outside_network* back; + /** random() table for this worker. */ + struct ub_randstate* rndstate; + /** sslcontext for SSL wrapped DNS over TCP queries */ + void* sslctx; +}; + +/** + * Create a background worker + * @param ctx: is updated with pid/tid of the background worker. + * a new allocation cache is obtained from ctx. It contains the + * threadnumber and unique id for further (shared) cache insertions. + * @return 0 if OK, else error. + * Further communication is done via the pipes in ctx. + */ +int libworker_bg(struct ub_ctx* ctx); + +/** + * Create a foreground worker. + * This worker will join the threadpool of resolver threads. + * It exits when the query answer has been obtained (or error). + * This routine blocks until the worker is finished. + * @param ctx: new allocation cache obtained and returned to it. + * @param q: query (result is stored in here). + * @return 0 if finished OK, else error. + */ +int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q); + +/** cleanup the cache to remove all rrset IDs from it, arg is libworker */ +void libworker_alloc_cleanup(void* arg); + +/** + * Worker service routine to send serviced queries to authoritative servers. + * @param qname: query name. (host order) + * @param qnamelen: length in bytes of qname, including trailing 0. + * @param qtype: query type. (host order) + * @param qclass: query class. (host order) + * @param flags: host order flags word, with opcode and CD bit. + * @param dnssec: if set, EDNS record will have DO bit set. + * @param want_dnssec: signatures needed. + * @param addr: where to. + * @param addrlen: length of addr. + * @param zone: delegation point name. + * @param zonelen: length of zone name wireformat dname. + * @param q: wich query state to reactivate upon return. + * @return: false on failure (memory or socket related). no query was + * sent. + */ +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, 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, + struct comm_reply* reply_info); + +/** process incoming serviced query replies from the network */ +int libworker_handle_service_reply(struct comm_point* c, void* arg, int error, + struct comm_reply* reply_info); + +/** handle control command coming into server */ +void libworker_handle_control_cmd(struct tube* tube, uint8_t* msg, size_t len, + int err, void* arg); + +/** handle opportunity to write result back */ +void libworker_handle_result_write(struct tube* tube, uint8_t* msg, size_t len, + int err, void* arg); + +/** mesh callback with fg results */ +void libworker_fg_done_cb(void* arg, int rcode, ldns_buffer* buf, + enum sec_status s, char* why_bogus); + +/** mesh callback with bg results */ +void libworker_bg_done_cb(void* arg, int rcode, ldns_buffer* buf, + enum sec_status s, char* why_bogus); + +/** + * fill result from parsed message, on error fills servfail + * @param res: is clear at start, filled in at end. + * @param buf: contains DNS message. + * @param temp: temporary buffer for parse. + * @param msg_security: security status of the DNS message. + * On error, the res may contain a different status + * (out of memory is not secure, not bogus). + */ +void libworker_enter_result(struct ub_result* res, ldns_buffer* buf, + struct regional* temp, enum sec_status msg_security); + +#endif /* LIBUNBOUND_WORKER_H */ diff --git a/libunbound/python/LICENSE b/libunbound/python/LICENSE new file mode 100644 index 00000000000..7b769d09120 --- /dev/null +++ b/libunbound/python/LICENSE @@ -0,0 +1,28 @@ +Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz) + Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) + +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 the organization 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. diff --git a/libunbound/python/Makefile b/libunbound/python/Makefile new file mode 100644 index 00000000000..86ba1774707 --- /dev/null +++ b/libunbound/python/Makefile @@ -0,0 +1,75 @@ +# +# Makefile: compilation of pyUnbound and documentation, testing +# +# Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz) +# Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) +# +# 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 organization 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 REGENTS OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +help: + @echo "Please use \`make ' where is one of" + @echo " testenv to make test environment and run bash " + @echo " usefull in case you don't want to install unbound but want to test examples" + @echo " doc to make documentation" + @echo " clean clean all" + +.PHONY: testenv clean doc swig + +#_unbound.so: ../../Makefile + #$(MAKE) -C ../.. + +#../../.libs/libunbound.so.0: ../../Makefile + #$(MAKE) -C ../.. + +#../../ldns-src/lib/libldns.so: ../../ldns-src/Makefile + #$(MAKE) -C ../../ldns-src + +clean: + rm -rdf examples/unbound + rm -f _unbound.so libunbound_wrap.o + $(MAKE) -C ../.. clean + +testenv: ../../.libs/libunbound.so.2 ../../ldns-src/lib/libldns.so ../../.libs/_unbound.so + rm -rdf examples/unbound + cd examples && mkdir unbound && ln -s ../../unbound.py unbound/__init__.py && ln -s ../../_unbound.so unbound/_unbound.so && ln -s ../../../../.libs/libunbound.so.2 unbound/libunbound.so.2 && ln -s ../../../../ldns-src/lib/libldns.so.1 unbound/libldns.so.1 && ls -la + cd examples && if test -f ../../../.libs/_unbound.so; then cp ../../../.libs/_unbound.so . ; fi + @echo "Run a script by typing ./script_name.py" + cd examples && LD_LIBRARY_PATH=unbound bash + rm -rdf examples/unbound examples/_unbound.so + +doc: ../../.libs/libunbound.so.0 _unbound.so + $(MAKE) -C docs html + +#for development only +swig: libunbound.i + swig -python -o libunbound_wrap.c -I../.. libunbound.i + gcc -c libunbound_wrap.c -O9 -fPIC -I../.. -I/usr/include/python2.5 -I. -o libunbound_wrap.o + gcc -shared libunbound_wrap.o -L../../.libs -lunbound -o _unbound.so + diff --git a/libunbound/python/doc/_static/readme b/libunbound/python/doc/_static/readme new file mode 100644 index 00000000000..db676aebbde --- /dev/null +++ b/libunbound/python/doc/_static/readme @@ -0,0 +1 @@ +this directory exists to pacify sphinx-build. diff --git a/libunbound/python/doc/conf.py b/libunbound/python/doc/conf.py new file mode 100644 index 00000000000..97fca2125f8 --- /dev/null +++ b/libunbound/python/doc/conf.py @@ -0,0 +1,181 @@ +# -*- coding: utf-8 -*- +# +# Unbound documentation build configuration file +# +# This file is execfile()d with the current directory set to its containing dir. +# +# The contents of this file are pickled, so don't put values in the namespace +# that aren't pickleable (module imports are okay, they're removed automatically). +# +# All configuration values have a default value; values that are commented out +# serve to show the default value. + +import sys, os + +# If your extensions are in another directory, add it here. If the directory +# is relative to the documentation root, use os.path.abspath to make it +# absolute, like shown here. +sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__),'../'))) +sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__),'../../../'))) +sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__),'../../../.libs/'))) +#print sys.path + +# General configuration +# --------------------- + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# General substitutions. +project = 'pyUnbound' +copyright = '2009, Zdenek Vasicek, Marek Vavrusa' + +# The default replacements for |version| and |release|, also used in various +# other places throughout the built documents. +# +# The short X.Y version. +version = '1.0' +# The full version, including alpha/beta/rc tags. +release = '1.0.0' + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +today_fmt = '%B %d, %Y' + +# List of documents that shouldn't be included in the build. +#unused_docs = [] + +# List of directories, relative to source directories, that shouldn't be searched +# for source files. +#exclude_dirs = [] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + + +# Options for HTML output +# ----------------------- + +# The style sheet to use for HTML and HTML Help pages. A file of that name +# must exist either in Sphinx' static/ path, or in one of the custom paths +# given in html_static_path. +html_style = 'default.css' + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (within the static path) to place at the top of +# the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +html_use_modindex = False + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, the reST sources are included in the HTML build as _sources/. +html_copy_source = False + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = '' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'Unbounddoc' + + +# Options for LaTeX output +# ------------------------ + +# The paper size ('letter' or 'a4'). +#latex_paper_size = 'letter' + +# The font size ('10pt', '11pt' or '12pt'). +#latex_font_size = '10pt' + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, document class [howto/manual]). +latex_documents = [ + ('index', 'Unbound.tex', 'Unbound Documentation', + 'Zdenek Vasicek, Marek Vavrusa', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# Additional stuff for the LaTeX preamble. +#latex_preamble = '' + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_use_modindex = True diff --git a/libunbound/python/doc/examples/example1a.rst b/libunbound/python/doc/examples/example1a.rst new file mode 100644 index 00000000000..3c81547f294 --- /dev/null +++ b/libunbound/python/doc/examples/example1a.rst @@ -0,0 +1,26 @@ +.. _example_resolve_name: + +============================== +Resolve a name +============================== + +This basic example shows how to create a context and resolve a host address (DNS record of A type). + +:: + + #!/usr/bin/python + import unbound + + ctx = unbound.ub_ctx() + ctx.resolvconf("/etc/resolv.conf") + + status, result = ctx.resolve("www.google.com") + if status == 0 and result.havedata: + print "Result.data:", result.data.address_list + elif status != 0: + print "Resolve error:", unbound.ub_strerror(status) + +In contrast with C API, the source code is more compact while the performance of C implementation is preserved. +The main advantage is that you need not take care about the deallocation and allocation of context and result structures; pyUnbound module do it automatically for you. + +If only domain name is given, the :meth:`unbound.ub_ctx.resolve` looks for A records in IN class. diff --git a/libunbound/python/doc/examples/example1b.rst b/libunbound/python/doc/examples/example1b.rst new file mode 100644 index 00000000000..ea1e6f57de6 --- /dev/null +++ b/libunbound/python/doc/examples/example1b.rst @@ -0,0 +1,33 @@ +.. _example_reverse_lookup: + +============================== +Reverse DNS lookup +============================== + +Reverse DNS lookup involves determining the hostname associated with a given IP address. +This example shows how reverse lookup can be done using unbound module. + +For the reverse DNS records, the special domain in-addr.arpa is reserved. +For example, a host name for the IP address 74.125.43.147 can be obtained by issuing a DNS query for the PTR record for address 147.43.125.74.in-addr.arpa. + +:: + + #!/usr/bin/python + import unbound + + ctx = unbound.ub_ctx() + ctx.resolvconf("/etc/resolv.conf") + + status, result = ctx.resolve(unbound.reverse("74.125.43.147") + ".in-addr.arpa.", unbound.RR_TYPE_PTR, unbound.RR_CLASS_IN) + if status == 0 and result.havedata: + print "Result.data:", result.data.domain_list + elif status != 0: + print "Resolve error:", unbound.ub_strerror(status) + +In order to simplify the python code, unbound module contains function which reverses the hostname components. +This function is defined as follows:: + + def reverse(domain): + return '.'.join([a for a in domain.split(".")][::-1]) + + diff --git a/libunbound/python/doc/examples/example2.rst b/libunbound/python/doc/examples/example2.rst new file mode 100644 index 00000000000..c009ec1f5ae --- /dev/null +++ b/libunbound/python/doc/examples/example2.rst @@ -0,0 +1,41 @@ +.. _example_setup_ctx: + +============================== +Lookup from threads +============================== + +This example shows how to use unbound module from a threaded program. +In this example, three lookup threads are created which work in background. +Each thread resolves different DNS record. + +:: + + #!/usr/bin/python + from unbound import ub_ctx, RR_TYPE_A, RR_CLASS_IN + from threading import Thread + + ctx = ub_ctx() + ctx.resolvconf("/etc/resolv.conf") + + class LookupThread(Thread): + def __init__(self,ctx, name): + Thread.__init__(self) + self.ctx = ctx + self.name = name + + def run(self): + print "Thread lookup started:",self.name + status, result = self.ctx.resolve(self.name, RR_TYPE_A, RR_CLASS_IN) + if status == 0 and result.havedata: + print " Result:",self.name,":", result.data.address_list + + threads = [] + for name in ["www.fit.vutbr.cz","www.vutbr.cz","www.google.com"]: + thread = LookupThread(ctx, name) + thread.start() + threads.append(thread) + + for thread in threads: + thread.join() + + diff --git a/libunbound/python/doc/examples/example3.rst b/libunbound/python/doc/examples/example3.rst new file mode 100644 index 00000000000..91360335c63 --- /dev/null +++ b/libunbound/python/doc/examples/example3.rst @@ -0,0 +1,36 @@ +.. _example_asynch: + +============================== +Asynchronous lookup +============================== + +This example performs the name lookup in the background. +The main program keeps running while the name is resolved. + +:: + + #!/usr/bin/python + import time + import unbound + + ctx = unbound.ub_ctx() + ctx.resolvconf("/etc/resolv.conf") + + def call_back(my_data,status,result): + print "Call_back:", my_data + if status == 0 and result.havedata: + print "Result:", result.data.address_list + my_data['done_flag'] = True + + + my_data = {'done_flag':False,'arbitrary':"object"} + status, async_id = ctx.resolve_async("www.seznam.cz", my_data, call_back, unbound.RR_TYPE_A, unbound.RR_CLASS_IN) + + while (status == 0) and (not my_data['done_flag']): + status = ctx.process() + time.sleep(0.1) + + if (status != 0): + print "Resolve error:", unbound.ub_strerror(status) + +The :meth:`unbound.ub_ctx.resolve_async` method is able to pass on any Python object. In this example, we used a dictionary object `my_data`. diff --git a/libunbound/python/doc/examples/example4.rst b/libunbound/python/doc/examples/example4.rst new file mode 100644 index 00000000000..996ef4ede92 --- /dev/null +++ b/libunbound/python/doc/examples/example4.rst @@ -0,0 +1,34 @@ +.. _example_examine: + +============================== +DNSSEC validator +============================== + +This example program performs DNSSEC validation of a DNS lookup. + +:: + + #!/usr/bin/python + import os + from unbound import ub_ctx,RR_TYPE_A,RR_CLASS_IN + + ctx = ub_ctx() + ctx.resolvconf("/etc/resolv.conf") + if (os.path.isfile("keys")): + ctx.add_ta_file("keys") #read public keys for DNSSEC verification + + status, result = ctx.resolve("www.nic.cz", RR_TYPE_A, RR_CLASS_IN) + if status == 0 and result.havedata: + + print "Result:", result.data.address_list + + if result.secure: + print "Result is secure" + elif result.bogus: + print "Result is bogus" + else: + print "Result is insecure" + +More detailed informations can be seen in libUnbound DNSSEC tutorial `here`_. + +.. _here: http://www.unbound.net/documentation/libunbound-tutorial-6.html diff --git a/libunbound/python/doc/examples/example5.rst b/libunbound/python/doc/examples/example5.rst new file mode 100644 index 00000000000..0a31d9a57e7 --- /dev/null +++ b/libunbound/python/doc/examples/example5.rst @@ -0,0 +1,29 @@ +.. _example_resolver_only: + +============================== +Resolver only +============================== + +This example program shows how to perform DNS resolution only. +Unbound contains two basic modules: resolver and validator. +In case, the validator is not necessary, the validator module can be turned off using "module-config" option. +This option contains a list of module names separated by the space char. This list determined which modules should be employed and in what order. + +:: + + #!/usr/bin/python + import os + from unbound import ub_ctx,RR_TYPE_A,RR_CLASS_IN + + ctx = ub_ctx() + ctx.set_option("module-config:","iterator") + ctx.resolvconf("/etc/resolv.conf") + + status, result = ctx.resolve("www.google.com", RR_TYPE_A, RR_CLASS_IN) + if status == 0 and result.havedata: + + print "Result:", result.data.address_list + +.. note:: + The :meth:`unbound.ub_ctx.set_option` method must be used before the first resolution (i.e. before :meth:`unbound.ub_ctx.resolve` or :meth:`unbound.ub_ctx.resolve_async` call). + diff --git a/libunbound/python/doc/examples/example6-1.py b/libunbound/python/doc/examples/example6-1.py new file mode 100644 index 00000000000..0f405448c51 --- /dev/null +++ b/libunbound/python/doc/examples/example6-1.py @@ -0,0 +1,27 @@ +#!/usr/bin/python +from unbound import ub_ctx,ub_strerror,RR_TYPE_A,RR_CLASS_IN + +ctx = ub_ctx() +ctx.resolvconf("/etc/resolv.conf") + +status, result = ctx.resolve("test.record.xxx", RR_TYPE_A, RR_CLASS_IN) +if status == 0 and result.havedata: + print "Result:", result.data.address_list +else: + print "No record found" + +#define new local zone +status = ctx.zone_add("xxx.","static") +if (status != 0): print "Error zone_add:",status, ub_strerror(status) + +#add RR to the zone +status = ctx.data_add("test.record.xxx. IN A 1.2.3.4") +if (status != 0): print "Error data_add:",status, ub_strerror(status) + +#lookup for an A record +status, result = ctx.resolve("test.record.xxx", RR_TYPE_A, RR_CLASS_IN) +if status == 0 and result.havedata: + print "Result:", result.data.as_address_list() +else: + print "No record found" + diff --git a/libunbound/python/doc/examples/example6.rst b/libunbound/python/doc/examples/example6.rst new file mode 100644 index 00000000000..478e1390927 --- /dev/null +++ b/libunbound/python/doc/examples/example6.rst @@ -0,0 +1,11 @@ +.. _example_localzone: + +============================== +Local zone manipulation +============================== + +This example program shows how to define local zone containing custom DNS records. + +.. literalinclude:: example6-1.py + :language: python + diff --git a/libunbound/python/doc/examples/example7-1.py b/libunbound/python/doc/examples/example7-1.py new file mode 100644 index 00000000000..802bd1c35ba --- /dev/null +++ b/libunbound/python/doc/examples/example7-1.py @@ -0,0 +1,17 @@ +#!/usr/bin/python +# vim:fileencoding=utf-8 +# +# IDN (Internationalized Domain Name) lookup support +# +import unbound + +ctx = unbound.ub_ctx() +ctx.resolvconf("/etc/resolv.conf") + +status, result = ctx.resolve(u"www.háčkyčárky.cz", unbound.RR_TYPE_A, unbound.RR_CLASS_IN) +if status == 0 and result.havedata: + print "Result:" + print " raw data:", result.data + for k in result.data.address_list: + print " address:%s" % k + diff --git a/libunbound/python/doc/examples/example7-2.py b/libunbound/python/doc/examples/example7-2.py new file mode 100644 index 00000000000..5a41f8dc933 --- /dev/null +++ b/libunbound/python/doc/examples/example7-2.py @@ -0,0 +1,16 @@ +#!/usr/bin/python +# vim:fileencoding=utf-8 +# +# IDN (Internationalized Domain Name) lookup support (lookup for MX) +# +import unbound + +ctx = unbound.ub_ctx() +ctx.resolvconf("/etc/resolv.conf") + +status, result = ctx.resolve(u"háčkyčárky.cz", unbound.RR_TYPE_MX, unbound.RR_CLASS_IN) +if status == 0 and result.havedata: + print "Result:" + print " raw data:", result.data + for k in result.data.mx_list_idn: + print " priority:%d address:%s" % k diff --git a/libunbound/python/doc/examples/example7.rst b/libunbound/python/doc/examples/example7.rst new file mode 100644 index 00000000000..d4050215e43 --- /dev/null +++ b/libunbound/python/doc/examples/example7.rst @@ -0,0 +1,18 @@ +.. _example_idna: + +================================================= +Internationalized domain name support +================================================= + +Unlike the libUnbound, pyUnbound is able to handle IDN queries. + +.. literalinclude:: example7-1.py + :language: python + +If we use unicode string in :meth:`unbound.ub_ctx.resolve` method, the IDN DNAME conversion (if it is necessary) is performed on background. + +.. literalinclude:: example7-2.py + :language: python + +The :class:`unbound.ub_data` class contains attributes suffix which converts the dname to UTF string. These attributes have the '_idn' suffix. +Apart from this aproach, two conversion functions exist (:func:`unbound.idn2dname` and :func:`unbound.dname2idn`). diff --git a/libunbound/python/doc/examples/example8-1.py b/libunbound/python/doc/examples/example8-1.py new file mode 100644 index 00000000000..79060167d83 --- /dev/null +++ b/libunbound/python/doc/examples/example8-1.py @@ -0,0 +1,31 @@ +#!/usr/bin/python +# vim:fileencoding=utf-8 +# +# Lookup for MX and NS records +# +import unbound + +ctx = unbound.ub_ctx() +ctx.resolvconf("/etc/resolv.conf") + +status, result = ctx.resolve("nic.cz", unbound.RR_TYPE_MX, unbound.RR_CLASS_IN) +if status == 0 and result.havedata: + print "Result:" + print " raw data:", result.data + for k in result.data.mx_list: + print " priority:%d address:%s" % k + +status, result = ctx.resolve("nic.cz", unbound.RR_TYPE_A, unbound.RR_CLASS_IN) +if status == 0 and result.havedata: + print "Result:" + print " raw data:", result.data + for k in result.data.address_list: + print " address:%s" % k + +status, result = ctx.resolve("nic.cz", unbound.RR_TYPE_NS, unbound.RR_CLASS_IN) +if status == 0 and result.havedata: + print "Result:" + print " raw data:", result.data + for k in result.data.domain_list: + print " host: %s" % k + diff --git a/libunbound/python/doc/examples/example8.rst b/libunbound/python/doc/examples/example8.rst new file mode 100644 index 00000000000..8cdfcdc0a90 --- /dev/null +++ b/libunbound/python/doc/examples/example8.rst @@ -0,0 +1,28 @@ +.. _example_mxlookup: + +================================================= +Lookup for MX and NS records +================================================= + +The pyUnbound extension provides functions which are able to encode RAW RDATA produces by unbound resolver (see :class:`unbound.ub_data`). + +.. literalinclude:: example8-1.py + :language: python + +Previous example produces following output:: + + Result: + raw data: 00 0F 05 6D 61 69 6C 34 03 6E 69 63 02 63 7A 00;00 14 02 6D 78 05 63 7A 6E 69 63 03 6F 72 67 00;00 0A 04 6D 61 69 6C 03 6E 69 63 02 63 7A 00 + priority:15 address: mail4.nic.cz. + priority:20 address: mx.cznic.org. + priority:10 address: mail.nic.cz. + + Result: + raw data: D9 1F CD 32 + address: 217.31.205.50 + + Result: + raw data: 01 61 02 6E 73 03 6E 69 63 02 63 7A 00;01 65 02 6E 73 03 6E 69 63 02 63 7A 00;01 63 02 6E 73 03 6E 69 63 02 63 7A 00 + host: a.ns.nic.cz. + host: e.ns.nic.cz. + host: c.ns.nic.cz. diff --git a/libunbound/python/doc/examples/index.rst b/libunbound/python/doc/examples/index.rst new file mode 100644 index 00000000000..c2c9cf45711 --- /dev/null +++ b/libunbound/python/doc/examples/index.rst @@ -0,0 +1,14 @@ +Examples +============================== + +Here you can find several examples which utilizes the unbound library in Python environment. +Unbound is a caching validator and resolver and can be linked into an application, as a library where can answer DNS queries for the application. +This set of examples shows how to use the functions from Python environment. + +`Tutorials` + +.. toctree:: + :maxdepth: 1 + :glob: + + example* diff --git a/libunbound/python/doc/index.rst b/libunbound/python/doc/index.rst new file mode 100644 index 00000000000..b42e0526223 --- /dev/null +++ b/libunbound/python/doc/index.rst @@ -0,0 +1,27 @@ +PyUnbound documentation +======================================= + +This project contains an Unbound wrapper providing the thinnest layer over the library possible. +Everything you can do from the libUnbound C API, you can do from Python, even more. + +Contents +---------- +.. toctree:: + :maxdepth: 2 + + intro.rst + install.rst + examples/index.rst + modules/unbound + +Module Documentation +----------------------- + +* Module :mod:`unbound` + +Indices and tables +------------------- + +* :ref:`genindex` +* :ref:`search` + diff --git a/libunbound/python/doc/install.rst b/libunbound/python/doc/install.rst new file mode 100644 index 00000000000..f638ed18e70 --- /dev/null +++ b/libunbound/python/doc/install.rst @@ -0,0 +1,31 @@ +Installation +=================================== + +**Prerequisites** + +Python 2.4 or higher, SWIG 1.3 or higher, GNU make + +**Compiling** + +After downloading, you can compile the pyUnbound library by doing:: + + > tar -xzf unbound-x.x.x-py.tar.gz + > cd unbound-x.x.x + > ./configure --with-pyunbound + > make + +You may want to --with-pythonmodule as well if you want to use python as +a module in the resolver. + +You need GNU make to compile sources; SWIG and Python devel libraries to compile extension module. + + +**Testing** + +If the compilation is successfull, you can test the python LDNS extension module by:: + + > cd contrib/python + > make testenv + > ./dns-lookup.py + +You may want to make install in the main directory since make testenv is for debugging. In contrib/examples you can find simple applications written in Python using the Unbound extension. diff --git a/libunbound/python/doc/intro.rst b/libunbound/python/doc/intro.rst new file mode 100644 index 00000000000..f751f54c07b --- /dev/null +++ b/libunbound/python/doc/intro.rst @@ -0,0 +1,39 @@ +Introduction +=================================== + +**Unbound** + + `Unbound`_ is an implementation of a DNS resolver, that performs caching and DNSSEC validation. + Together with unbound, the libunbound library is provided. + This library can be used to convert hostnames to ip addresses, and back, as well as obtain other information. + Since the resolver allows to specify the class and type of a query (A record, NS, MX, ...), this library offers powerful resolving tool. + The library also performs public-key validation of results with DNSSEC. + + .. _Unbound: http://www.unbound.net/documentation + +**pyUnbound** + + The pyUnbound is an extension module for Python which provides an object-oriented interface to libunbound. + It is the first Python module which offers thread-safe caching resolver. + + The interface was designed with the emphasis on the simplicity of use. + There are two main classes :class:`unbound.ub_ctx` (a validation and resolution context) and :class:`unbound.ub_result` which contains the validation and resolution results. + The objects are thread-safe, and a context can be used in non-threaded as well as threaded environment. + Resolution can be performed blocking and non-blocking (i.e. asynchronous). + The asynchronous method returns from the call immediately, so that processing can go on, while the results become available later. + +**Features** + * customizable caching validation resolver for synchronous and asynchronous lookups + * easy to use object interface + * easy to integrate extension module + * designed for thread environment (i.e. thread-safe) + * allows define and customize of local zone and its RR's during the operation (i.e. without restart) + * includes encoding functions to simplify the results retrieval + * Internationalized domain name (`IDN`_) support + + .. _IDN: http://en.wikipedia.org/wiki/Internationalized_domain_name + +**Application area** + * DNS-based applications performing DNS lookups; the caching resolver can reduce overhead + * Applications where the validation of DNS records is required + * Great solution for customizable and dynamic DNS-based white/blacklists (spam rejection, connection rejection, ...) using the dynamic local zone manipulation diff --git a/libunbound/python/doc/modules/unbound.rst b/libunbound/python/doc/modules/unbound.rst new file mode 100644 index 00000000000..21f4a12d844 --- /dev/null +++ b/libunbound/python/doc/modules/unbound.rst @@ -0,0 +1,167 @@ +Unbound module documentation +================================ + +.. automodule:: unbound + +Class ub_ctx +-------------- +.. autoclass:: ub_ctx + :members: + :undoc-members: + + .. automethod:: __init__ + +Class ub_result +---------------------- +.. autoclass:: ub_result + :members: + + .. attribute:: qname + + The original question, name text string. + + .. attribute:: qtype + + The class asked for. + + .. attribute:: canonname + + Canonical name for the result (the final cname). May be empty if no canonical name exists. + + .. attribute:: answer_packet + + The DNS answer packet. Network formatted. Can contain DNSSEC types. + + .. attribute:: havedata + + If there is any data, this property is true. If false, there was no data (nxdomain may be true, rcode can be set). + + .. attribute:: secure + + True, if the result is validated securely. + False, if validation failed or domain queried has no security info. + + It is possible to get a result with no data (havedata is false), + and secure is true. This means that the non-existance of the data + was cryptographically proven (with signatures). + + .. attribute:: bogus + + If the result was not secure (secure==0), and this result is due to a security failure, bogus is true. + This means the data has been actively tampered with, signatures + failed, expected signatures were not present, timestamps on + signatures were out of date and so on. + + If secure==0 and bogus==0, this can happen if the data is not secure + because security is disabled for that domain name. + This means the data is from a domain where data is not signed. + + .. attribute:: nxdomain + + If there was no data, and the domain did not exist, this is true. + If it is false, and there was no data, then the domain name is purported to exist, but the requested data type is not available. + + .. attribute:: rcode + + DNS RCODE for the result. May contain additional error code if there was no data due to an error. + 0 (RCODE_NOERROR) if okay. See predefined `RCODE_` constants. + + RCODE can be represented in display representation form (string) using :attr:`rcode_str` attribute. + +Class ub_data +---------------------- +.. autoclass:: ub_data + :members: + +Functions +---------------------- +.. autofunction:: reverse +.. autofunction:: idn2dname +.. autofunction:: dname2idn + +Predefined constants +----------------------- + +**RCODE** + * RCODE_FORMERR = 1 + * RCODE_NOERROR = 0 + * RCODE_NOTAUTH = 9 + * RCODE_NOTIMPL = 4 + * RCODE_NOTZONE = 10 + * RCODE_NXDOMAIN = 3 + * RCODE_NXRRSET = 8 + * RCODE_REFUSED = 5 + * RCODE_SERVFAIL = 2 + * RCODE_YXDOMAIN = 6 + * RCODE_YXRRSET = 7 + +**RR_CLASS** + * RR_CLASS_ANY = 255 + * RR_CLASS_CH = 3 + * RR_CLASS_HS = 4 + * RR_CLASS_IN = 1 + * RR_CLASS_NONE = 254 + +**RR_TYPE** + * RR_TYPE_A = 1 + * RR_TYPE_A6 = 38 + * RR_TYPE_AAAA = 28 + * RR_TYPE_AFSDB = 18 + * RR_TYPE_ANY = 255 + * RR_TYPE_APL = 42 + * RR_TYPE_ATMA = 34 + * RR_TYPE_AXFR = 252 + * RR_TYPE_CERT = 37 + * RR_TYPE_CNAME = 5 + * RR_TYPE_DHCID = 49 + * RR_TYPE_DLV = 32769 + * RR_TYPE_DNAME = 39 + * RR_TYPE_DNSKEY = 48 + * RR_TYPE_DS = 43 + * RR_TYPE_EID = 31 + * RR_TYPE_GID = 102 + * RR_TYPE_GPOS = 27 + * RR_TYPE_HINFO = 13 + * RR_TYPE_IPSECKEY = 45 + * RR_TYPE_ISDN = 20 + * RR_TYPE_IXFR = 251 + * RR_TYPE_KEY = 25 + * RR_TYPE_KX = 36 + * RR_TYPE_LOC = 29 + * RR_TYPE_MAILA = 254 + * RR_TYPE_MAILB = 253 + * RR_TYPE_MB = 7 + * RR_TYPE_MD = 3 + * RR_TYPE_MF = 4 + * RR_TYPE_MG = 8 + * RR_TYPE_MINFO = 14 + * RR_TYPE_MR = 9 + * RR_TYPE_MX = 15 + * RR_TYPE_NAPTR = 35 + * RR_TYPE_NIMLOC = 32 + * RR_TYPE_NS = 2 + * RR_TYPE_NSAP = 22 + * RR_TYPE_NSAP_PTR = 23 + * RR_TYPE_NSEC = 47 + * RR_TYPE_NSEC3 = 50 + * RR_TYPE_NSEC3PARAMS = 51 + * RR_TYPE_NULL = 10 + * RR_TYPE_NXT = 30 + * RR_TYPE_OPT = 41 + * RR_TYPE_PTR = 12 + * RR_TYPE_PX = 26 + * RR_TYPE_RP = 17 + * RR_TYPE_RRSIG = 46 + * RR_TYPE_RT = 21 + * RR_TYPE_SIG = 24 + * RR_TYPE_SINK = 40 + * RR_TYPE_SOA = 6 + * RR_TYPE_SRV = 33 + * RR_TYPE_SSHFP = 44 + * RR_TYPE_TSIG = 250 + * RR_TYPE_TXT = 16 + * RR_TYPE_UID = 101 + * RR_TYPE_UINFO = 100 + * RR_TYPE_UNSPEC = 103 + * RR_TYPE_WKS = 11 + * RR_TYPE_X25 = 19 diff --git a/libunbound/python/examples/async-lookup.py b/libunbound/python/examples/async-lookup.py new file mode 100644 index 00000000000..52a2d3c75c5 --- /dev/null +++ b/libunbound/python/examples/async-lookup.py @@ -0,0 +1,56 @@ +#!/usr/bin/python +''' + async-lookup.py : This example shows how to use asynchronous lookups + + Authors: Zdenek Vasicek (vasicek AT fit.vutbr.cz) + Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) + + Copyright (c) 2008. 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. + + 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 REGENTS OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +''' +import unbound +import time + +ctx = unbound.ub_ctx() +ctx.resolvconf("/etc/resolv.conf") + +def call_back(my_data,status,result): + print "Call_back:", my_data + if status == 0 and result.havedata: + print "Result:", result.data.address_list + my_data['done_flag'] = True + + +my_data = {'done_flag':False,'arbitrary':"object"} +status, async_id = ctx.resolve_async("www.nic.cz", my_data, call_back, unbound.RR_TYPE_A, unbound.RR_CLASS_IN) + +while (status == 0) and (not my_data['done_flag']): + status = ctx.process() + time.sleep(0.1) + +if (status != 0): + print "Resolve error:", unbound.ub_strerror(status) diff --git a/libunbound/python/examples/dns-lookup.py b/libunbound/python/examples/dns-lookup.py new file mode 100644 index 00000000000..2821ed3ba36 --- /dev/null +++ b/libunbound/python/examples/dns-lookup.py @@ -0,0 +1,44 @@ +#!/usr/bin/python +''' + dns-lookup.py : This example shows how to resolve IP address + + Authors: Zdenek Vasicek (vasicek AT fit.vutbr.cz) + Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) + + Copyright (c) 2008. 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. + + 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 REGENTS OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +''' +import unbound + +ctx = unbound.ub_ctx() +ctx.resolvconf("/etc/resolv.conf") + +status, result = ctx.resolve("www.nic.cz", unbound.RR_TYPE_A, unbound.RR_CLASS_IN) +if status == 0 and result.havedata: + print "Result:", result.data.address_list +elif status != 0: + print "Error:", unbound.ub_strerror(status) diff --git a/libunbound/python/examples/dnssec-valid.py b/libunbound/python/examples/dnssec-valid.py new file mode 100644 index 00000000000..3e05ddd7a28 --- /dev/null +++ b/libunbound/python/examples/dnssec-valid.py @@ -0,0 +1,59 @@ +#!/usr/bin/python +''' + dnssec-valid.py: DNSSEC validation + + Authors: Zdenek Vasicek (vasicek AT fit.vutbr.cz) + Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) + + Copyright (c) 2008. 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. + + 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 REGENTS OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +''' +import os +from unbound import ub_ctx,RR_TYPE_A,RR_CLASS_IN + +ctx = ub_ctx() +ctx.resolvconf("/etc/resolv.conf") + +fw = open("dnssec-valid.txt","wb") +ctx.debugout(fw) +ctx.debuglevel(2) + +if os.path.isfile("keys"): + ctx.add_ta_file("keys") #read public keys for DNSSEC verificatio + +status, result = ctx.resolve("www.nic.cz", RR_TYPE_A, RR_CLASS_IN) +if status == 0 and result.havedata: + + print "Result:", result.data.address_list + + if result.secure: + print "Result is secure" + elif result.bogus: + print "Result is bogus" + else: + print "Result is insecure" + diff --git a/libunbound/python/examples/dnssec_test.py b/libunbound/python/examples/dnssec_test.py new file mode 100644 index 00000000000..138e19b51a1 --- /dev/null +++ b/libunbound/python/examples/dnssec_test.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python +from unbound import ub_ctx, RR_TYPE_A, RR_TYPE_RRSIG, RR_TYPE_NSEC, RR_TYPE_NSEC3 +import ldns + +def dnssecParse(domain, rrType=RR_TYPE_A): + print "Resolving domain", domain + s, r = resolver.resolve(domain) + print "status: %s, secure: %s, rcode: %s, havedata: %s, answer_len; %s" % (s, r.secure, r.rcode_str, r.havedata, r.answer_len) + + s, pkt = ldns.ldns_wire2pkt(r.packet) + if s != 0: + raise RuntimeError("Error parsing DNS packet") + + rrsigs = pkt.rr_list_by_type(RR_TYPE_RRSIG, ldns.LDNS_SECTION_ANSWER) + print "RRSIGs from answer:", rrsigs + + rrsigs = pkt.rr_list_by_type(RR_TYPE_RRSIG, ldns.LDNS_SECTION_AUTHORITY) + print "RRSIGs from authority:", rrsigs + + nsecs = pkt.rr_list_by_type(RR_TYPE_NSEC, ldns.LDNS_SECTION_AUTHORITY) + print "NSECs:", nsecs + + nsec3s = pkt.rr_list_by_type(RR_TYPE_NSEC3, ldns.LDNS_SECTION_AUTHORITY) + print "NSEC3s:", nsec3s + + print "---" + + +resolver = ub_ctx() +resolver.add_ta(". IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5") + +dnssecParse("nic.cz") +dnssecParse("nonexistent-domain-blablabla.cz") +dnssecParse("nonexistent-domain-blablabla.root.cz") + diff --git a/libunbound/python/examples/example8-1.py b/libunbound/python/examples/example8-1.py new file mode 100644 index 00000000000..6816da0c2df --- /dev/null +++ b/libunbound/python/examples/example8-1.py @@ -0,0 +1,61 @@ +#!/usr/bin/python +# vim:fileencoding=utf-8 +''' + example8-1.py: Example shows how to lookup for MX and NS records + + Authors: Zdenek Vasicek (vasicek AT fit.vutbr.cz) + Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) + + Copyright (c) 2008. 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. + + 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 REGENTS OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +''' +import unbound + +ctx = unbound.ub_ctx() +ctx.resolvconf("/etc/resolv.conf") + +status, result = ctx.resolve("nic.cz", unbound.RR_TYPE_MX, unbound.RR_CLASS_IN) +if status == 0 and result.havedata: + print "Result:" + print " raw data:", result.data + for k in result.data.mx_list: + print " priority:%d address:%s" % k + +status, result = ctx.resolve("nic.cz", unbound.RR_TYPE_A, unbound.RR_CLASS_IN) +if status == 0 and result.havedata: + print "Result:" + print " raw data:", result.data + for k in result.data.address_list: + print " address:%s" % k + +status, result = ctx.resolve("nic.cz", unbound.RR_TYPE_NS, unbound.RR_CLASS_IN) +if status == 0 and result.havedata: + print "Result:" + print " raw data:", result.data + for k in result.data.domain_list: + print " host: %s" % k + diff --git a/libunbound/python/examples/idn-lookup.py b/libunbound/python/examples/idn-lookup.py new file mode 100644 index 00000000000..7cfdc9e9479 --- /dev/null +++ b/libunbound/python/examples/idn-lookup.py @@ -0,0 +1,62 @@ +#!/usr/bin/python +# vim:fileencoding=utf-8 +''' + idn-lookup.py: IDN (Internationalized Domain Name) lookup support + + Authors: Zdenek Vasicek (vasicek AT fit.vutbr.cz) + Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) + + Copyright (c) 2008. 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. + + 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 REGENTS OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +''' +import unbound +import locale + +ctx = unbound.ub_ctx() +ctx.set_option("module-config:","iterator") #We don't need validation +ctx.resolvconf("/etc/resolv.conf") + +#The unicode IDN string is automatically converted (if necessary) +status, result = ctx.resolve(u"www.háčkyčárky.cz", unbound.RR_TYPE_A, unbound.RR_CLASS_IN) +if status == 0 and result.havedata: + print "Result:" + print " raw data:", result.data + for k in result.data.address_list: + print " address:%s" % k + +status, result = ctx.resolve(u"háčkyčárky.cz", unbound.RR_TYPE_MX, unbound.RR_CLASS_IN) +if status == 0 and result.havedata: + print "Result:" + print " raw data:", result.data + for k in result.data.mx_list_idn: + print " priority:%d address:%s" % k + +status, result = ctx.resolve(unbound.reverse('217.31.204.66')+'.in-addr.arpa', unbound.RR_TYPE_PTR, unbound.RR_CLASS_IN) +if status == 0 and result.havedata: + print "Result.data:", result.data + for k in result.data.domain_list_idn: + print " dname:%s" % k diff --git a/libunbound/python/examples/mx-lookup.py b/libunbound/python/examples/mx-lookup.py new file mode 100644 index 00000000000..cdcd1b166b4 --- /dev/null +++ b/libunbound/python/examples/mx-lookup.py @@ -0,0 +1,53 @@ +#!/usr/bin/python +# vim:fileencoding=utf-8 +''' + mx-lookup.py: Lookup for MX records + + Authors: Zdenek Vasicek (vasicek AT fit.vutbr.cz) + Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) + + Copyright (c) 2008. 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. + + 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 REGENTS OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +''' +import unbound + +ctx = unbound.ub_ctx() +ctx.resolvconf("/etc/resolv.conf") + +status, result = ctx.resolve("nic.cz", unbound.RR_TYPE_MX, unbound.RR_CLASS_IN) +if status == 0 and result.havedata: + print "Result:" + print " raw data:", result.data + for k in result.data.mx_list: + print " priority:%d address:%s" % k + +status, result = ctx.resolve("nic.cz", unbound.RR_TYPE_A, unbound.RR_CLASS_IN) +if status == 0 and result.havedata: + print "Result:" + print " raw data:", result.data + for k in result.data.address_list: + print " address:%s" % k diff --git a/libunbound/python/examples/ns-lookup.py b/libunbound/python/examples/ns-lookup.py new file mode 100644 index 00000000000..f9eafb28aa3 --- /dev/null +++ b/libunbound/python/examples/ns-lookup.py @@ -0,0 +1,47 @@ +#!/usr/bin/python +# vim:fileencoding=utf-8 +''' + ns-lookup.py: Example shows how to lookup for NS records + + Authors: Zdenek Vasicek (vasicek AT fit.vutbr.cz) + Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) + + Copyright (c) 2008. 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. + + 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 REGENTS OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +''' +import unbound + +ctx = unbound.ub_ctx() +ctx.resolvconf("/etc/resolv.conf") + +status, result = ctx.resolve("vutbr.cz", unbound.RR_TYPE_NS, unbound.RR_CLASS_IN) +if status == 0 and result.havedata: + print "Result:" + print " raw data:", result.data + for k in result.data.domain_list: + print " host: %s" % k + diff --git a/libunbound/python/examples/reverse-lookup.py b/libunbound/python/examples/reverse-lookup.py new file mode 100644 index 00000000000..4d3e0bb36df --- /dev/null +++ b/libunbound/python/examples/reverse-lookup.py @@ -0,0 +1,43 @@ +#!/usr/bin/python +''' + reverse-lookup.py: Example shows how to resolve reverse record + + Authors: Zdenek Vasicek (vasicek AT fit.vutbr.cz) + Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) + + Copyright (c) 2008. 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. + + 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 REGENTS OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +''' +import unbound + +ctx = unbound.ub_ctx() +ctx.resolvconf("/etc/resolv.conf") + +status, result = ctx.resolve(unbound.reverse("74.125.43.147") + ".in-addr.arpa.", unbound.RR_TYPE_PTR, unbound.RR_CLASS_IN) +if status == 0 and result.havedata: + print "Result.data:", result.data, result.data.domain_list + diff --git a/libunbound/python/libunbound.i b/libunbound/python/libunbound.i new file mode 100644 index 00000000000..4f9279957fa --- /dev/null +++ b/libunbound/python/libunbound.i @@ -0,0 +1,941 @@ +/* + * libounbound.i: pyUnbound module (libunbound wrapper for Python) + * + * Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz) + * Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) + * + * 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 organization 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +%module unbound +%{ + #include + #include + #include + #include + #include "libunbound/unbound.h" +%} + +%pythoncode %{ + import encodings.idna +%} + +//%include "doc.i" +%include "file.i" + +%feature("docstring") strerror "Convert error value to a human readable string." + +// ================================================================================ +// ub_resolve - perform resolution and validation +// ================================================================================ +%typemap(in,numinputs=0,noblock=1) (struct ub_result** result) +{ + struct ub_result* newubr; + $1 = &newubr; +} + +/* result generation */ +%typemap(argout,noblock=1) (struct ub_result** result) +{ + if(1) { /* new code block for variable on stack */ + PyObject* tuple; + tuple = PyTuple_New(2); + PyTuple_SetItem(tuple, 0, $result); + if (result == 0) { + PyTuple_SetItem(tuple, 1, SWIG_NewPointerObj(SWIG_as_voidptr(newubr), SWIGTYPE_p_ub_result, SWIG_POINTER_OWN | 0 )); + } else { + PyTuple_SetItem(tuple, 1, Py_None); + } + $result = tuple; + } +} + + +// ================================================================================ +// ub_ctx - validation context +// ================================================================================ +%nodefaultctor ub_ctx; //no default constructor & destructor +%nodefaultdtor ub_ctx; + +%newobject ub_ctx_create; +%delobject ub_ctx_delete; +%rename(_ub_ctx_delete) ub_ctx_delete; + +%newobject ub_resolve; + +%inline %{ + void ub_ctx_free_dbg (struct ub_ctx* c) { + printf("******** UB_CTX free 0x%lX ************\n", (long unsigned int)c); + ub_ctx_delete(c); + } + + //RR types + enum enum_rr_type + { + /** a host address */ + RR_TYPE_A = 1, + /** an authoritative name server */ + RR_TYPE_NS = 2, + /** a mail destination (Obsolete - use MX) */ + RR_TYPE_MD = 3, + /** a mail forwarder (Obsolete - use MX) */ + RR_TYPE_MF = 4, + /** the canonical name for an alias */ + RR_TYPE_CNAME = 5, + /** marks the start of a zone of authority */ + RR_TYPE_SOA = 6, + /** a mailbox domain name (EXPERIMENTAL) */ + RR_TYPE_MB = 7, + /** a mail group member (EXPERIMENTAL) */ + RR_TYPE_MG = 8, + /** a mail rename domain name (EXPERIMENTAL) */ + RR_TYPE_MR = 9, + /** a null RR (EXPERIMENTAL) */ + RR_TYPE_NULL = 10, + /** a well known service description */ + RR_TYPE_WKS = 11, + /** a domain name pointer */ + RR_TYPE_PTR = 12, + /** host information */ + RR_TYPE_HINFO = 13, + /** mailbox or mail list information */ + RR_TYPE_MINFO = 14, + /** mail exchange */ + RR_TYPE_MX = 15, + /** text strings */ + RR_TYPE_TXT = 16, + /** RFC1183 */ + RR_TYPE_RP = 17, + /** RFC1183 */ + RR_TYPE_AFSDB = 18, + /** RFC1183 */ + RR_TYPE_X25 = 19, + /** RFC1183 */ + RR_TYPE_ISDN = 20, + /** RFC1183 */ + RR_TYPE_RT = 21, + /** RFC1706 */ + RR_TYPE_NSAP = 22, + /** RFC1348 */ + RR_TYPE_NSAP_PTR = 23, + /** 2535typecode */ + RR_TYPE_SIG = 24, + /** 2535typecode */ + RR_TYPE_KEY = 25, + /** RFC2163 */ + RR_TYPE_PX = 26, + /** RFC1712 */ + RR_TYPE_GPOS = 27, + /** ipv6 address */ + RR_TYPE_AAAA = 28, + /** LOC record RFC1876 */ + RR_TYPE_LOC = 29, + /** 2535typecode */ + RR_TYPE_NXT = 30, + /** draft-ietf-nimrod-dns-01.txt */ + RR_TYPE_EID = 31, + /** draft-ietf-nimrod-dns-01.txt */ + RR_TYPE_NIMLOC = 32, + /** SRV record RFC2782 */ + RR_TYPE_SRV = 33, + /** http://www.jhsoft.com/rfc/af-saa-0069.000.rtf */ + RR_TYPE_ATMA = 34, + /** RFC2915 */ + RR_TYPE_NAPTR = 35, + /** RFC2230 */ + RR_TYPE_KX = 36, + /** RFC2538 */ + RR_TYPE_CERT = 37, + /** RFC2874 */ + RR_TYPE_A6 = 38, + /** RFC2672 */ + RR_TYPE_DNAME = 39, + /** dnsind-kitchen-sink-02.txt */ + RR_TYPE_SINK = 40, + /** Pseudo OPT record... */ + RR_TYPE_OPT = 41, + /** RFC3123 */ + RR_TYPE_APL = 42, + /** draft-ietf-dnsext-delegation */ + RR_TYPE_DS = 43, + /** SSH Key Fingerprint */ + RR_TYPE_SSHFP = 44, + /** draft-richardson-ipseckey-rr-11.txt */ + RR_TYPE_IPSECKEY = 45, + /** draft-ietf-dnsext-dnssec-25 */ + RR_TYPE_RRSIG = 46, + RR_TYPE_NSEC = 47, + RR_TYPE_DNSKEY = 48, + RR_TYPE_DHCID = 49, + + RR_TYPE_NSEC3 = 50, + RR_TYPE_NSEC3PARAMS = 51, + + RR_TYPE_UINFO = 100, + RR_TYPE_UID = 101, + RR_TYPE_GID = 102, + RR_TYPE_UNSPEC = 103, + + RR_TYPE_TSIG = 250, + RR_TYPE_IXFR = 251, + RR_TYPE_AXFR = 252, + /** A request for mailbox-related records (MB, MG or MR) */ + RR_TYPE_MAILB = 253, + /** A request for mail agent RRs (Obsolete - see MX) */ + RR_TYPE_MAILA = 254, + /** any type (wildcard) */ + RR_TYPE_ANY = 255, + + /* RFC 4431, 5074, DNSSEC Lookaside Validation */ + RR_TYPE_DLV = 32769, + }; + + // RR classes + enum enum_rr_class + { + /** the Internet */ + RR_CLASS_IN = 1, + /** Chaos class */ + RR_CLASS_CH = 3, + /** Hesiod (Dyer 87) */ + RR_CLASS_HS = 4, + /** None class, dynamic update */ + RR_CLASS_NONE = 254, + /** Any class */ + RR_CLASS_ANY = 255, + }; +%} + +%feature("docstring") ub_ctx "Unbound resolving and validation context. + +The validation context is created to hold the resolver status, validation keys and a small cache (containing messages, rrsets, roundtrip times, trusted keys, lameness information). + +**Usage** + +>>> import unbound +>>> ctx = unbound.ub_ctx() +>>> ctx.resolvconf(\"/etc/resolv.conf\") +>>> status, result = ctx.resolve(\"www.google.com\", unbound.RR_TYPE_A, unbound.RR_CLASS_IN) +>>> if status==0 and result.havedata: +>>> print \"Result:\",result.data.address_list +Result: ['74.125.43.147', '74.125.43.99', '74.125.43.103', '74.125.43.104'] +" + +%extend ub_ctx +{ + %pythoncode %{ + def __init__(self): + """Creates a resolving and validation context. + + An exception is invoked if the process of creation an ub_ctx instance fails. + """ + self.this = _unbound.ub_ctx_create() + if not self.this: + raise Exception("Fatal error: unbound context initialization failed") + + #__swig_destroy__ = _unbound.ub_ctx_free_dbg + __swig_destroy__ = _unbound._ub_ctx_delete + + #UB_CTX_METHODS_# + def add_ta(self,ta): + """Add a trust anchor to the given context. + + The trust anchor is a string, on one line, that holds a valid DNSKEY or DS RR. + + :param ta: + string, with zone-format RR on one line. [domainname] [TTL optional] [type] [class optional] [rdata contents] + :returns: (int) 0 if OK, else error. + """ + return _unbound.ub_ctx_add_ta(self,ta) + #parameters: struct ub_ctx *,char *, + #retvals: int + + def add_ta_file(self,fname): + """Add trust anchors to the given context. + + Pass name of a file with DS and DNSKEY records (like from dig or drill). + + :param fname: + filename of file with keyfile with trust anchors. + :returns: (int) 0 if OK, else error. + """ + return _unbound.ub_ctx_add_ta_file(self,fname) + #parameters: struct ub_ctx *,char *, + #retvals: int + + def config(self,fname): + """setup configuration for the given context. + + :param fname: + unbound config file (not all settings applicable). This is a power-users interface that lets you specify all sorts of options. For some specific options, such as adding trust anchors, special routines exist. + :returns: (int) 0 if OK, else error. + """ + return _unbound.ub_ctx_config(self,fname) + #parameters: struct ub_ctx *,char *, + #retvals: int + + def debuglevel(self,d): + """Set debug verbosity for the context Output is directed to stderr. + + :param d: + debug level, 0 is off, 1 is very minimal, 2 is detailed, and 3 is lots. + :returns: (int) 0 if OK, else error. + """ + return _unbound.ub_ctx_debuglevel(self,d) + #parameters: struct ub_ctx *,int, + #retvals: int + + def debugout(self,out): + """Set debug output (and error output) to the specified stream. + + Pass None to disable. Default is stderr. + + :param out: + File stream to log to. + :returns: (int) 0 if OK, else error. + + **Usage:** + + In order to log into file, use + + :: + + ctx = unbound.ub_ctx() + fw = fopen("debug.log") + ctx.debuglevel(3) + ctx.debugout(fw) + + Another option is to print the debug informations to stderr output + + :: + + ctx = unbound.ub_ctx() + ctx.debuglevel(10) + ctx.debugout(sys.stderr) + """ + return _unbound.ub_ctx_debugout(self,out) + #parameters: struct ub_ctx *,void *, + #retvals: int + + def hosts(self,fname="/etc/hosts"): + """Read list of hosts from the filename given. + + Usually "/etc/hosts". These addresses are not flagged as DNSSEC secure when queried for. + + :param fname: + file name string. If None "/etc/hosts" is used. + :returns: (int) 0 if OK, else error. + """ + return _unbound.ub_ctx_hosts(self,fname) + #parameters: struct ub_ctx *,char *, + #retvals: int + + def print_local_zones(self): + """Print the local zones and their content (RR data) to the debug output. + + :returns: (int) 0 if OK, else error. + """ + return _unbound.ub_ctx_print_local_zones(self) + #parameters: struct ub_ctx *, + #retvals: int + + def resolvconf(self,fname="/etc/resolv.conf"): + """Read list of nameservers to use from the filename given. + + Usually "/etc/resolv.conf". Uses those nameservers as caching proxies. If they do not support DNSSEC, validation may fail. + + Only nameservers are picked up, the searchdomain, ndots and other settings from resolv.conf(5) are ignored. + + :param fname: + file name string. If None "/etc/resolv.conf" is used. + :returns: (int) 0 if OK, else error. + """ + return _unbound.ub_ctx_resolvconf(self,fname) + #parameters: struct ub_ctx *,char *, + #retvals: int + + def set_async(self,dothread): + """Set a context behaviour for asynchronous action. + + :param dothread: + if True, enables threading and a call to :meth:`resolve_async` creates a thread to handle work in the background. + If False, a process is forked to handle work in the background. + Changes to this setting after :meth:`async` calls have been made have no effect (delete and re-create the context to change). + :returns: (int) 0 if OK, else error. + """ + return _unbound.ub_ctx_async(self,dothread) + #parameters: struct ub_ctx *,int, + #retvals: int + + def set_fwd(self,addr): + """Set machine to forward DNS queries to, the caching resolver to use. + + IP4 or IP6 address. Forwards all DNS requests to that machine, which is expected to run a recursive resolver. If the is not DNSSEC-capable, validation may fail. Can be called several times, in that case the addresses are used as backup servers. + + To read the list of nameservers from /etc/resolv.conf (from DHCP or so), use the call :meth:`resolvconf`. + + :param addr: + address, IP4 or IP6 in string format. If the addr is None, forwarding is disabled. + :returns: (int) 0 if OK, else error. + """ + return _unbound.ub_ctx_set_fwd(self,addr) + #parameters: struct ub_ctx *,char *, + #retvals: int + + def set_option(self,opt,val): + """Set an option for the context. + + Changes to the options after :meth:`resolve`, :meth:`resolve_async`, :meth:`zone_add`, :meth:`zone_remove`, :meth:`data_add` or :meth:`data_remove` have no effect (you have to delete and re-create the context). + + :param opt: + option name from the unbound.conf config file format. (not all settings applicable). The name includes the trailing ':' for example set_option("logfile:", "mylog.txt"); This is a power-users interface that lets you specify all sorts of options. For some specific options, such as adding trust anchors, special routines exist. + :param val: + value of the option. + :returns: (int) 0 if OK, else error. + """ + return _unbound.ub_ctx_set_option(self,opt,val) + #parameters: struct ub_ctx *,char *,char *, + #retvals: int + + def trustedkeys(self,fname): + """Add trust anchors to the given context. + + Pass the name of a bind-style config file with trusted-keys{}. + + :param fname: + filename of file with bind-style config entries with trust anchors. + :returns: (int) 0 if OK, else error. + """ + return _unbound.ub_ctx_trustedkeys(self,fname) + #parameters: struct ub_ctx *,char *, + #retvals: int + #_UB_CTX_METHODS# + + def zone_print(self): + """Print local zones using debougout""" + _unbound.ub_ctx_print_local_zones(self) + + def zone_add(self,zonename,zonetype): + """Add new local zone + + :param zonename: zone domain name (e.g. myzone.) + :param zonetype: type of the zone ("static",...) + :returns: (int) 0 if OK, else error. + """ + return _unbound.ub_ctx_zone_add(self,zonename, zonetype) + #parameters: struct ub_ctx *,char*, char* + #retvals: int + + def zone_remove(self,zonename): + """Remove local zone + + If exists, removes local zone with all the RRs. + + :param zonename: zone domain name + :returns: (int) 0 if OK, else error. + """ + return _unbound.ub_ctx_zone_remove(self,zonename) + #parameters: struct ub_ctx *,char* + #retvals: int + + def data_add(self,rrdata): + """Add new local RR data + + :param rrdata: string, in zone-format on one line. [domainname] [TTL optional] [type] [class optional] [rdata contents] + :returns: (int) 0 if OK, else error. + + **Usage** + The local data ... + + :: + + >>> ctx = unbound.ub_ctx() + >>> ctx.zone_add("mydomain.net.","static") + 0 + >>> status = ctx.data_add("test.mydomain.net. IN A 192.168.1.1") + 0 + >>> status, result = ctx.resolve("test.mydomain.net") + >>> if status==0 and result.havedata: + >>> print \"Result:\",result.data.address_list + Result: ['192.168.1.1'] + + """ + return _unbound.ub_ctx_data_add(self,rrdata) + #parameters: struct ub_ctx *,char* + #retvals: int + + def data_remove(self,rrdata): + """Remove local RR data + + If exists, remove resource record from local zone + + :param rrdata: string, in zone-format on one line. [domainname] [TTL optional] [type] [class optional] [rdata contents] + :returns: (int) 0 if OK, else error. + """ + return _unbound.ub_ctx_data_remove(self,rrdata) + #parameters: struct ub_ctx *,char* + #retvals: int + + #UB_METHODS_# + def cancel(self,async_id): + """Cancel an async query in progress. + + Its callback will not be called. + + :param async_id: + which query to cancel. + :returns: (int) 0 if OK, else error. + """ + return _unbound.ub_cancel(self,async_id) + #parameters: struct ub_ctx *,int, + #retvals: int + + def get_fd(self): + """Get file descriptor. + + Wait for it to become readable, at this point answers are returned from the asynchronous validating resolver. Then call the ub_process to continue processing. This routine works immediately after context creation, the fd does not change. + + :returns: (int) -1 on error, or file descriptor to use select(2) with. + """ + return _unbound.ub_fd(self) + #parameters: struct ub_ctx *, + #retvals: int + + def poll(self): + """Poll a context to see if it has any new results Do not poll in a loop, instead extract the fd below to poll for readiness, and then check, or wait using the wait routine. + + :returns: (int) 0 if nothing to read, or nonzero if a result is available. If nonzero, call ctx_process() to do callbacks. + """ + return _unbound.ub_poll(self) + #parameters: struct ub_ctx *, + #retvals: int + + def process(self): + """Call this routine to continue processing results from the validating resolver (when the fd becomes readable). + + Will perform necessary callbacks. + + :returns: (int) 0 if OK, else error. + """ + return _unbound.ub_process(self) + #parameters: struct ub_ctx *, + #retvals: int + + def resolve(self,name,rrtype=RR_TYPE_A,rrclass=RR_CLASS_IN): + """Perform resolution and validation of the target name. + + :param name: + domain name in text format (a string or unicode string). IDN domain name have to be passed as a unicode string. + :param rrtype: + type of RR in host order (optional argument). Default value is RR_TYPE_A (A class). + :param rrclass: + class of RR in host order (optional argument). Default value is RR_CLASS_IN (for internet). + :returns: * (int) 0 if OK, else error. + * (:class:`ub_result`) the result data is returned in a newly allocated result structure. May be None on return, return value is set to an error in that case (out of memory). + """ + if isinstance(name, unicode): #probably IDN + return _unbound.ub_resolve(self,idn2dname(name),rrtype,rrclass) + else: + return _unbound.ub_resolve(self,name,rrtype,rrclass) + #parameters: struct ub_ctx *,char *,int,int, + #retvals: int,struct ub_result ** + + def resolve_async(self,name,mydata,callback,rrtype=RR_TYPE_A,rrclass=RR_CLASS_IN): + """Perform resolution and validation of the target name. + + Asynchronous, after a while, the callback will be called with your data and the result. + If an error happens during processing, your callback will be called with error set to a nonzero value (and result==None). + + :param name: + domain name in text format (a string or unicode string). IDN domain name have to be passed as a unicode string. + :param mydata: + this data is your own data (you can pass arbitrary python object or None) which are passed on to the callback function. + :param callback: + call-back function which is called on completion of the resolution. + :param rrtype: + type of RR in host order (optional argument). Default value is RR_TYPE_A (A class). + :param rrclass: + class of RR in host order (optional argument). Default value is RR_CLASS_IN (for internet). + :returns: * (int) 0 if OK, else error. + * (int) async_id, an identifier number is returned for the query as it is in progress. It can be used to cancel the query. + + **Call-back function:** + The call-back function looks as the follows:: + + def call_back(mydata, status, result): + pass + + **Parameters:** + * `mydata` - mydata object + * `status` - 0 when a result has been found + * `result` - the result structure. The result may be None, in that case err is set. + + """ + if isinstance(name, unicode): #probably IDN + return _unbound._ub_resolve_async(self,idn2dname(name),rrtype,rrclass,mydata,callback) + else: + return _unbound._ub_resolve_async(self,name,rrtype,rrclass,mydata,callback) + #parameters: struct ub_ctx *,char *,int,int,void *,ub_callback_t, + #retvals: int, int + + def wait(self): + """Wait for a context to finish with results. + + Calls after the wait for you. After the wait, there are no more outstanding asynchronous queries. + + :returns: (int) 0 if OK, else error. + """ + return _unbound.ub_wait(self) + #parameters: struct ub_ctx *, + #retvals: int + + #_UB_METHODS# + %} +} + + +// ================================================================================ +// ub_result - validation and resolution results +// ================================================================================ +%nodefaultctor ub_result; //no default constructor & destructor +%nodefaultdtor ub_result; + +%delobject ub_resolve_free; +%rename(_ub_resolve_free) ub_resolve_free; + +%inline %{ + void ub_resolve_free_dbg (struct ub_result* r) { + printf("******** UB_RESOLVE free 0x%lX ************\n", (long unsigned int)r); + ub_resolve_free(r); + } +%} + +%feature("docstring") ub_result "The validation and resolution results." + +//ub_result.rcode +%inline %{ + enum result_enum_rcode { + RCODE_NOERROR = 0, + RCODE_FORMERR = 1, + RCODE_SERVFAIL = 2, + RCODE_NXDOMAIN = 3, + RCODE_NOTIMPL = 4, + RCODE_REFUSED = 5, + RCODE_YXDOMAIN = 6, + RCODE_YXRRSET = 7, + RCODE_NXRRSET = 8, + RCODE_NOTAUTH = 9, + RCODE_NOTZONE = 10 + }; +%} + +%pythoncode %{ + class ub_data: + """Class which makes the resolution results accessible""" + def __init__(self, data): + """Creates ub_data class + :param data: a list of the result data in RAW format + """ + if data == None: + raise Exception("ub_data init: No data") + self.data = data + + def __str__(self): + """Represents data as string""" + return ';'.join([' '.join(map(lambda x:"%02X" % ord(x),a)) for a in self.data]) + + @staticmethod + def dname2str(s, ofs=0, maxlen=0): + """Parses DNAME and produces a list of labels + + :param ofs: where the conversion should start to parse data + :param maxlen: maximum length (0 means parse to the end) + :returns: list of labels (string) + """ + if not s: + return [] + + res = [] + slen = len(s) + if maxlen > 0: + slen = min(slen, maxlen) + + idx = ofs + while (idx < slen): + complen = ord(s[idx]) + res.append(s[idx+1:idx+1+complen]) + idx += complen + 1 + + return res + + def as_raw_data(self): + """Returns a list of RAW strings""" + return self.data + + raw = property(as_raw_data, doc="Returns RAW data (a list of binary encoded strings). See :meth:`as_raw_data`") + + def as_mx_list(self): + """Represents data as a list of MX records (query for RR_TYPE_MX) + + :returns: list of tuples (priority, dname) + """ + return [(256*ord(rdf[0])+ord(rdf[1]),'.'.join([a for a in self.dname2str(rdf,2)])) for rdf in self.data] + + mx_list = property(as_mx_list, doc="Returns a list of tuples containing priority and domain names. See :meth:`as_mx_list`") + + def as_idn_mx_list(self): + """Represents data as a list of MX records (query for RR_TYPE_MX) + + :returns: list of tuples (priority, unicode dname) + """ + return [(256*ord(rdf[0])+ord(rdf[1]),'.'.join([encodings.idna.ToUnicode(a) for a in self.dname2str(rdf,2)])) for rdf in self.data] + + mx_list_idn = property(as_idn_mx_list, doc="Returns a list of tuples containing priority and IDN domain names. See :meth:`as_idn_mx_list`") + + def as_address_list(self): + """Represents data as a list of IP addresses (query for RR_TYPE_PTR) + + :returns: list of strings + """ + return ['.'.join(map(lambda x:str(ord(x)),a)) for a in self.data] + + address_list = property(as_address_list, doc="Returns a list of IP addresses. See :meth:`as_address_list`") + + def as_domain_list(self): + """Represents data as a list of domain names (query for RR_TYPE_A) + + :returns: list of strings + """ + return map(lambda x:'.'.join(self.dname2str(x)), self.data) + + domain_list = property(as_domain_list, doc="Returns a list of domain names. See :meth:`as_domain_list`") + + def as_idn_domain_list(self): + """Represents data as a list of unicode domain names (query for RR_TYPE_A) + + :returns: list of strings + """ + return map(lambda x: '.'.join([encodings.idna.ToUnicode(a) for a in self.dname2str(x)]), self.data) + + domain_list_idn = property(as_idn_domain_list, doc="Returns a list of IDN domain names. See :meth:`as_idn_domain_list`") +%} + +%extend ub_result +{ + + %rename(_data) data; + + PyObject* _ub_result_data(struct ub_result* result) { + PyObject *list; + int i,cnt; + (void)self; + if ((result == 0) || (!result->havedata) || (result->data == 0)) + return Py_None; + + for (cnt=0,i=0;;i++,cnt++) + if (result->data[i] == 0) + break; + + list = PyList_New(cnt); + for (i=0;idata[i],result->len[i])); + + return list; + } + + PyObject* _packet() { + return PyString_FromStringAndSize($self->answer_packet, $self->answer_len); + } + + %pythoncode %{ + def __init__(self): + raise Exception("This class can't be created directly.") + + #__swig_destroy__ = _unbound.ub_resolve_free_dbg + __swig_destroy__ = _unbound._ub_resolve_free + + #havedata = property(_unbound.ub_result_havedata_get, _unbound.ub_result_havedata_set, "Havedata property") + + rcode2str = {RCODE_NOERROR:'no error', RCODE_FORMERR:'form error', RCODE_SERVFAIL:'serv fail', RCODE_NXDOMAIN:'nx domain', RCODE_NOTIMPL:'not implemented', RCODE_REFUSED:'refused', RCODE_YXDOMAIN:'yxdomain', RCODE_YXRRSET:'yxrrset', RCODE_NXRRSET:'nxrrset', RCODE_NOTAUTH:'not auth', RCODE_NOTZONE:'not zone'} + + def _get_rcode_str(self): + """Returns rcode in display representation form + + :returns: string + """ + return self.rcode2str[self.rcode] + + __swig_getmethods__["rcode_str"] = _get_rcode_str + if _newclass:rcode_str = _swig_property(_get_rcode_str) + + def _get_raw_data(self): + """Result data, a list of network order DNS rdata items. + + Data are represented as a list of strings. To decode RAW data to the list of IP addresses use :attr:`data` attribute which returns an :class:`ub_data` instance containing conversion function. + """ + return self._ub_result_data(self) + + __swig_getmethods__["rawdata"] = _get_raw_data + rawdata = property(_get_raw_data, doc="Returns raw data, a list of rdata items. To decode RAW data use the :attr:`data` attribute which returns an instance of :class:`ub_data` containing the conversion functions.") + + def _get_data(self): + if not self.havedata: return None + return ub_data(self._ub_result_data(self)) + + __swig_getmethods__["data"] = _get_data + __swig_getmethods__["packet"] = _packet + data = property(_get_data, doc="Returns :class:`ub_data` instance containing various decoding functions or None") + +%} + +} + +%exception ub_resolve +%{ + //printf("resolve_start(%lX)\n",(long unsigned int)arg1); + Py_BEGIN_ALLOW_THREADS + $function + Py_END_ALLOW_THREADS + //printf("resolve_stop()\n"); +%} + +%include "libunbound/unbound.h" + +%inline %{ + //SWIG will see the ub_ctx as a class + struct ub_ctx { + }; +%} + +//ub_ctx_debugout void* parameter correction +int ub_ctx_debugout(struct ub_ctx* ctx, FILE* out); + +// ================================================================================ +// ub_resolve_async - perform asynchronous resolution and validation +// ================================================================================ + +%typemap(in,numinputs=0,noblock=1) (int* async_id) +{ + int asyncid = -1; + $1 = &asyncid; +} + +%apply PyObject* {void* mydata} + +/* result generation */ +%typemap(argout,noblock=1) (int* async_id) +{ + if(1) { /* new code block for variable on stack */ + PyObject* tuple; + tuple = PyTuple_New(2); + PyTuple_SetItem(tuple, 0, $result); + PyTuple_SetItem(tuple, 1, SWIG_From_int(asyncid)); + $result = tuple; + } +} + +// Grab a Python function object as a Python object. +%typemap(in) (PyObject *pyfunc) { + if (!PyCallable_Check($input)) + { + PyErr_SetString(PyExc_TypeError, "Need a callable object!"); + return NULL; + } + $1 = $input; +} + +// Python callback workaround +int _ub_resolve_async(struct ub_ctx* ctx, char* name, int rrtype, int rrclass, void* mydata, PyObject *pyfunc, int* async_id); + +%{ + struct cb_data { + PyObject* data; + PyObject* func; + }; + + static void PythonCallBack(void* iddata, int status, struct ub_result* result) + { + PyObject *arglist; + PyObject *fresult; + struct cb_data* id; + id = (struct cb_data*) iddata; + arglist = Py_BuildValue("(OiO)",id->data,status, SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_ub_result, 0 | 0 )); // Build argument list + fresult = PyEval_CallObject(id->func,arglist); // Call Python + Py_DECREF(id->func); + Py_DECREF(id->data); + free(id); + ub_resolve_free(result); //free ub_result + //ub_resolve_free_dbg(result); //free ub_result + Py_DECREF(arglist); // Trash arglist + Py_XDECREF(fresult); + } + + int _ub_resolve_async(struct ub_ctx* ctx, char* name, int rrtype, int rrclass, PyObject* mydata, PyObject *pyfunc, int* async_id) { + int r; + struct cb_data* id; + id = (struct cb_data*) malloc(sizeof(struct cb_data)); + id->data = mydata; + id->func = pyfunc; + + r = ub_resolve_async(ctx,name,rrtype,rrclass, (void *) id, PythonCallBack, async_id); + Py_INCREF(mydata); + Py_INCREF(pyfunc); + return r; + } + +%} + +%pythoncode %{ + ub_resolve_async = _unbound._ub_resolve_async + + def reverse(domain): + """Reverse domain name + + Usable for reverse lookups when the IP address should be reversed + """ + return '.'.join([a for a in domain.split(".")][::-1]) + + def idn2dname(idnname): + """Converts domain name in IDN format to canonic domain name + + :param idnname: (unicode string) IDN name + :returns: (string) domain name + """ + return '.'.join([encodings.idna.ToASCII(a) for a in idnname.split('.')]) + + def dname2idn(name): + """Converts canonic domain name in IDN format to unicode string + + :param name: (string) domain name + :returns: (unicode string) domain name + """ + return '.'.join([encodings.idna.ToUnicode(a) for a in name.split('.')]) + +%} + diff --git a/libunbound/ubsyms.def b/libunbound/ubsyms.def new file mode 100644 index 00000000000..7e3fdd1e25e --- /dev/null +++ b/libunbound/ubsyms.def @@ -0,0 +1,29 @@ +ub_ctx_create +ub_ctx_delete +ub_ctx_get_option +ub_ctx_set_option +ub_ctx_config +ub_ctx_set_fwd +ub_ctx_resolvconf +ub_ctx_hosts +ub_ctx_add_ta +ub_ctx_add_ta_file +ub_ctx_trustedkeys +ub_ctx_debugout +ub_ctx_debuglevel +ub_ctx_async +ub_poll +ub_wait +ub_fd +ub_process +ub_resolve +ub_resolve_async +ub_cancel +ub_resolve_free +ub_strerror +ub_ctx_print_local_zones +ub_ctx_zone_add +ub_ctx_zone_remove +ub_ctx_data_add +ub_ctx_data_remove +ub_version diff --git a/libunbound/unbound.h b/libunbound/unbound.h new file mode 100644 index 00000000000..085f9f53415 --- /dev/null +++ b/libunbound/unbound.h @@ -0,0 +1,556 @@ +/* + * unbound.h - unbound validating resolver public API + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions to resolve DNS queries and + * validate the answers. Synchonously and asynchronously. + * + * Several ways to use this interface from an application wishing + * to perform (validated) DNS lookups. + * + * All start with + * ctx = ub_ctx_create(); + * err = ub_ctx_add_ta(ctx, "..."); + * err = ub_ctx_add_ta(ctx, "..."); + * ... some lookups + * ... call ub_ctx_delete(ctx); when you want to stop. + * + * Application not threaded. Blocking. + * int err = ub_resolve(ctx, "www.example.com", ... + * if(err) fprintf(stderr, "lookup error: %s\n", ub_strerror(err)); + * ... use the answer + * + * Application not threaded. Non-blocking ('asynchronous'). + * err = ub_resolve_async(ctx, "www.example.com", ... my_callback); + * ... application resumes processing ... + * ... and when either ub_poll(ctx) is true + * ... or when the file descriptor ub_fd(ctx) is readable, + * ... or whenever, the app calls ... + * ub_process(ctx); + * ... if no result is ready, the app resumes processing above, + * ... or process() calls my_callback() with results. + * + * ... if the application has nothing more to do, wait for answer + * ub_wait(ctx); + * + * Application threaded. Blocking. + * Blocking, same as above. The current thread does the work. + * Multiple threads can use the *same context*, each does work and uses + * shared cache data from the context. + * + * Application threaded. Non-blocking ('asynchronous'). + * ... setup threaded-asynchronous config option + * err = ub_ctx_async(ctx, 1); + * ... same as async for non-threaded + * ... the callbacks are called in the thread that calls process(ctx) + * + * If no threading is compiled in, the above async example uses fork(2) to + * create a process to perform the work. The forked process exits when the + * calling process exits, or ctx_delete() is called. + * Otherwise, for asynchronous with threading, a worker thread is created. + * + * The blocking calls use shared ctx-cache when threaded. Thus + * ub_resolve() and ub_resolve_async() && ub_wait() are + * not the same. The first makes the current thread do the work, setting + * up buffers, etc, to perform the work (but using shared cache data). + * The second calls another worker thread (or process) to perform the work. + * And no buffers need to be set up, but a context-switch happens. + */ +#ifndef _UB_UNBOUND_H +#define _UB_UNBOUND_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * The validation context is created to hold the resolver status, + * validation keys and a small cache (containing messages, rrsets, + * roundtrip times, trusted keys, lameness information). + * + * Its contents are internally defined. + */ +struct ub_ctx; + +/** + * The validation and resolution results. + * Allocated by the resolver, and need to be freed by the application + * with ub_resolve_free(). + */ +struct ub_result { + /** The original question, name text string. */ + char* qname; + /** the type asked for */ + int qtype; + /** the class asked for */ + int qclass; + + /** + * a list of network order DNS rdata items, terminated with a + * NULL pointer, so that data[0] is the first result entry, + * data[1] the second, and the last entry is NULL. + * If there was no data, data[0] is NULL. + */ + char** data; + + /** the length in bytes of the data items, len[i] for data[i] */ + int* len; + + /** + * canonical name for the result (the final cname). + * zero terminated string. + * May be NULL if no canonical name exists. + */ + char* canonname; + + /** + * DNS RCODE for the result. May contain additional error code if + * there was no data due to an error. 0 (NOERROR) if okay. + */ + int rcode; + + /** + * The DNS answer packet. Network formatted. Can contain DNSSEC types. + */ + void* answer_packet; + /** length of the answer packet in octets. */ + int answer_len; + + /** + * If there is any data, this is true. + * If false, there was no data (nxdomain may be true, rcode can be set). + */ + int havedata; + + /** + * If there was no data, and the domain did not exist, this is true. + * If it is false, and there was no data, then the domain name + * is purported to exist, but the requested data type is not available. + */ + int nxdomain; + + /** + * True, if the result is validated securely. + * False, if validation failed or domain queried has no security info. + * + * It is possible to get a result with no data (havedata is false), + * and secure is true. This means that the non-existance of the data + * was cryptographically proven (with signatures). + */ + int secure; + + /** + * If the result was not secure (secure==0), and this result is due + * to a security failure, bogus is true. + * This means the data has been actively tampered with, signatures + * failed, expected signatures were not present, timestamps on + * signatures were out of date and so on. + * + * If !secure and !bogus, this can happen if the data is not secure + * because security is disabled for that domain name. + * This means the data is from a domain where data is not signed. + */ + int bogus; + + /** + * If the result is bogus this contains a string (zero terminated) + * that describes the failure. There may be other errors as well + * as the one described, the description may not be perfectly accurate. + * Is NULL if the result is not bogus. + */ + char* why_bogus; +}; + +/** + * Callback for results of async queries. + * The readable function definition looks like: + * void my_callback(void* my_arg, int err, struct ub_result* result); + * It is called with + * void* my_arg: your pointer to a (struct of) data of your choice, + * or NULL. + * int err: if 0 all is OK, otherwise an error occured and no results + * are forthcoming. + * struct result: pointer to more detailed result structure. + * This structure is allocated on the heap and needs to be + * freed with ub_resolve_free(result); + */ +typedef void (*ub_callback_t)(void*, int, struct ub_result*); + +/** + * 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. + * @return a new context. default initialisation. + * returns NULL on error. + */ +struct ub_ctx* ub_ctx_create(void); + +/** + * Destroy a validation context and free all its resources. + * Outstanding async queries are killed and callbacks are not called for them. + * @param ctx: context to delete. + */ +void ub_ctx_delete(struct ub_ctx* ctx); + +/** + * Set an option for the context. + * @param ctx: context. + * @param opt: option name from the unbound.conf config file format. + * (not all settings applicable). The name includes the trailing ':' + * for example ub_ctx_set_option(ctx, "logfile:", "mylog.txt"); + * This is a power-users interface that lets you specify all sorts + * of options. + * For some specific options, such as adding trust anchors, special + * routines exist. + * @param val: value of the option. + * @return: 0 if OK, else error. + */ +int ub_ctx_set_option(struct ub_ctx* ctx, char* opt, char* val); + +/** + * Get an option from the context. + * @param ctx: context. + * @param opt: option name from the unbound.conf config file format. + * (not all settings applicable). The name excludes the trailing ':' + * for example ub_ctx_get_option(ctx, "logfile", &result); + * This is a power-users interface that lets you specify all sorts + * of options. + * @param str: the string is malloced and returned here. NULL on error. + * The caller must free() the string. In cases with multiple + * entries (auto-trust-anchor-file), a newline delimited list is + * returned in the string. + * @return 0 if OK else an error code (malloc failure, syntax error). + */ +int ub_ctx_get_option(struct ub_ctx* ctx, char* opt, char** str); + +/** + * setup configuration for the given context. + * @param ctx: context. + * @param fname: unbound config file (not all settings applicable). + * This is a power-users interface that lets you specify all sorts + * of options. + * For some specific options, such as adding trust anchors, special + * routines exist. + * @return: 0 if OK, else error. + */ +int ub_ctx_config(struct ub_ctx* ctx, char* fname); + +/** + * Set machine to forward DNS queries to, the caching resolver to use. + * IP4 or IP6 address. Forwards all DNS requests to that machine, which + * is expected to run a recursive resolver. If the proxy is not + * DNSSEC-capable, validation may fail. Can be called several times, in + * that case the addresses are used as backup servers. + * + * To read the list of nameservers from /etc/resolv.conf (from DHCP or so), + * use the call ub_ctx_resolvconf. + * + * @param ctx: context. + * At this time it is only possible to set configuration before the + * first resolve is done. + * @param addr: address, IP4 or IP6 in string format. + * If the addr is NULL, forwarding is disabled. + * @return 0 if OK, else error. + */ +int ub_ctx_set_fwd(struct ub_ctx* ctx, char* addr); + +/** + * Read list of nameservers to use from the filename given. + * Usually "/etc/resolv.conf". Uses those nameservers as caching proxies. + * If they do not support DNSSEC, validation may fail. + * + * Only nameservers are picked up, the searchdomain, ndots and other + * settings from resolv.conf(5) are ignored. + * + * @param ctx: context. + * At this time it is only possible to set configuration before the + * first resolve is done. + * @param fname: file name string. If NULL "/etc/resolv.conf" is used. + * @return 0 if OK, else error. + */ +int ub_ctx_resolvconf(struct ub_ctx* ctx, char* fname); + +/** + * Read list of hosts from the filename given. + * Usually "/etc/hosts". + * These addresses are not flagged as DNSSEC secure when queried for. + * + * @param ctx: context. + * At this time it is only possible to set configuration before the + * first resolve is done. + * @param fname: file name string. If NULL "/etc/hosts" is used. + * @return 0 if OK, else error. + */ +int ub_ctx_hosts(struct ub_ctx* ctx, char* fname); + +/** + * Add a trust anchor to the given context. + * The trust anchor is a string, on one line, that holds a valid DNSKEY or + * DS RR. + * @param ctx: context. + * At this time it is only possible to add trusted keys before the + * first resolve is done. + * @param ta: string, with zone-format RR on one line. + * [domainname] [TTL optional] [type] [class optional] [rdata contents] + * @return 0 if OK, else error. + */ +int ub_ctx_add_ta(struct ub_ctx* ctx, char* ta); + +/** + * Add trust anchors to the given context. + * Pass name of a file with DS and DNSKEY records (like from dig or drill). + * @param ctx: context. + * At this time it is only possible to add trusted keys before the + * first resolve is done. + * @param fname: filename of file with keyfile with trust anchors. + * @return 0 if OK, else error. + */ +int ub_ctx_add_ta_file(struct ub_ctx* ctx, char* fname); + +/** + * Add trust anchors to the given context. + * Pass the name of a bind-style config file with trusted-keys{}. + * @param ctx: context. + * At this time it is only possible to add trusted keys before the + * first resolve is done. + * @param fname: filename of file with bind-style config entries with trust + * anchors. + * @return 0 if OK, else error. + */ +int ub_ctx_trustedkeys(struct ub_ctx* ctx, char* fname); + +/** + * Set debug output (and error output) to the specified stream. + * Pass NULL to disable. Default is stderr. + * @param ctx: context. + * @param out: FILE* out file stream to log to. + * Type void* to avoid stdio dependency of this header file. + * @return 0 if OK, else error. + */ +int ub_ctx_debugout(struct ub_ctx* ctx, void* out); + +/** + * Set debug verbosity for the context + * Output is directed to stderr. + * @param ctx: context. + * @param d: debug level, 0 is off, 1 is very minimal, 2 is detailed, + * and 3 is lots. + * @return 0 if OK, else error. + */ +int ub_ctx_debuglevel(struct ub_ctx* ctx, int d); + +/** + * Set a context behaviour for asynchronous action. + * @param ctx: context. + * @param dothread: if true, enables threading and a call to resolve_async() + * creates a thread to handle work in the background. + * If false, a process is forked to handle work in the background. + * Changes to this setting after async() calls have been made have + * no effect (delete and re-create the context to change). + * @return 0 if OK, else error. + */ +int ub_ctx_async(struct ub_ctx* ctx, int dothread); + +/** + * Poll a context to see if it has any new results + * Do not poll in a loop, instead extract the fd below to poll for readiness, + * and then check, or wait using the wait routine. + * @param ctx: context. + * @return: 0 if nothing to read, or nonzero if a result is available. + * If nonzero, call ctx_process() to do callbacks. + */ +int ub_poll(struct ub_ctx* ctx); + +/** + * Wait for a context to finish with results. Calls ub_process() after + * the wait for you. After the wait, there are no more outstanding + * asynchronous queries. + * @param ctx: context. + * @return: 0 if OK, else error. + */ +int ub_wait(struct ub_ctx* ctx); + +/** + * Get file descriptor. Wait for it to become readable, at this point + * answers are returned from the asynchronous validating resolver. + * Then call the ub_process to continue processing. + * This routine works immediately after context creation, the fd + * does not change. + * @param ctx: context. + * @return: -1 on error, or file descriptor to use select(2) with. + */ +int ub_fd(struct ub_ctx* ctx); + +/** + * Call this routine to continue processing results from the validating + * resolver (when the fd becomes readable). + * Will perform necessary callbacks. + * @param ctx: context + * @return: 0 if OK, else error. + */ +int ub_process(struct ub_ctx* ctx); + +/** + * Perform resolution and validation of the target name. + * @param ctx: context. + * The context is finalized, and can no longer accept config changes. + * @param name: domain name in text format (a zero terminated text string). + * @param rrtype: type of RR in host order, 1 is A (address). + * @param rrclass: class of RR in host order, 1 is IN (for internet). + * @param result: the result data is returned in a newly allocated result + * structure. May be NULL on return, return value is set to an error + * in that case (out of memory). + * @return 0 if OK, else error. + */ +int ub_resolve(struct ub_ctx* ctx, char* name, int rrtype, + int rrclass, struct ub_result** result); + +/** + * Perform resolution and validation of the target name. + * Asynchronous, after a while, the callback will be called with your + * data and the result. + * @param ctx: context. + * If no thread or process has been created yet to perform the + * work in the background, it is created now. + * The context is finalized, and can no longer accept config changes. + * @param name: domain name in text format (a string). + * @param rrtype: type of RR in host order, 1 is A. + * @param rrclass: class of RR in host order, 1 is IN (for internet). + * @param mydata: this data is your own data (you can pass NULL), + * and is passed on to the callback function. + * @param callback: this is called on completion of the resolution. + * It is called as: + * void callback(void* mydata, int err, struct ub_result* result) + * with mydata: the same as passed here, you may pass NULL, + * with err: is 0 when a result has been found. + * with result: a newly allocated result structure. + * The result may be NULL, in that case err is set. + * + * If an error happens during processing, your callback will be called + * with error set to a nonzero value (and result==NULL). + * @param async_id: if you pass a non-NULL value, an identifier number is + * returned for the query as it is in progress. It can be used to + * cancel the query. + * @return 0 if OK, else error. + */ +int ub_resolve_async(struct ub_ctx* ctx, char* name, int rrtype, + int rrclass, void* mydata, ub_callback_t callback, int* async_id); + +/** + * Cancel an async query in progress. + * Its callback will not be called. + * + * @param ctx: context. + * @param async_id: which query to cancel. + * @return 0 if OK, else error. + * This routine can return an error if the async_id passed does not exist + * or has already been delivered. If another thread is processing results + * at the same time, the result may be delivered at the same time and the + * cancel fails with an error. Also the cancel can fail due to a system + * error, no memory or socket failures. + */ +int ub_cancel(struct ub_ctx* ctx, int async_id); + +/** + * Free storage associated with a result structure. + * @param result: to free + */ +void ub_resolve_free(struct ub_result* result); + +/** + * Convert error value to a human readable string. + * @param err: error code from one of the ub_val* functions. + * @return pointer to constant text string, zero terminated. + */ +const char* ub_strerror(int err); + +/** + * Debug routine. Print the local zone information to debug output. + * @param ctx: context. Is finalized by the routine. + * @return 0 if OK, else error. + */ +int ub_ctx_print_local_zones(struct ub_ctx* ctx); + +/** + * Add a new zone with the zonetype to the local authority info of the + * library. + * @param ctx: context. Is finalized by the routine. + * @param zone_name: name of the zone in text, "example.com" + * If it already exists, the type is updated. + * @param zone_type: type of the zone (like for unbound.conf) in text. + * @return 0 if OK, else error. + */ +int ub_ctx_zone_add(struct ub_ctx* ctx, char *zone_name, char *zone_type); + +/** + * Remove zone from local authority info of the library. + * @param ctx: context. Is finalized by the routine. + * @param zone_name: name of the zone in text, "example.com" + * If it does not exist, nothing happens. + * @return 0 if OK, else error. + */ +int ub_ctx_zone_remove(struct ub_ctx* ctx, char *zone_name); + +/** + * Add localdata to the library local authority info. + * Similar to local-data config statement. + * @param ctx: context. Is finalized by the routine. + * @param data: the resource record in text format, for example + * "www.example.com IN A 127.0.0.1" + * @return 0 if OK, else error. + */ +int ub_ctx_data_add(struct ub_ctx* ctx, char *data); + +/** + * Remove localdata from the library local authority info. + * @param ctx: context. Is finalized by the routine. + * @param data: the name to delete all data from, like "www.example.com". + * @return 0 if OK, else error. + */ +int ub_ctx_data_remove(struct ub_ctx* ctx, char *data); + +/** + * Get a version string from the libunbound implementation. + * @return a static constant string with the version number. + */ +const char* ub_version(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _UB_UNBOUND_H */ diff --git a/ltmain.sh b/ltmain.sh new file mode 100755 index 00000000000..aa5624c8161 --- /dev/null +++ b/ltmain.sh @@ -0,0 +1,9636 @@ + +# libtool (GNU libtool) 2.4 +# Written by Gordon Matzigkeit , 1996 + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, +# 2007, 2008, 2009, 2010 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, +# or obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +# Usage: $progname [OPTION]... [MODE-ARG]... +# +# Provide generalized library-building support services. +# +# --config show all configuration variables +# --debug enable verbose shell tracing +# -n, --dry-run display commands without modifying any files +# --features display basic configuration information and exit +# --mode=MODE use operation mode MODE +# --preserve-dup-deps don't remove duplicate dependency libraries +# --quiet, --silent don't print informational messages +# --no-quiet, --no-silent +# print informational messages (default) +# --tag=TAG use configuration variables from tag TAG +# -v, --verbose print more informational messages than default +# --no-verbose don't print the extra informational messages +# --version print version information +# -h, --help, --help-all print short, long, or detailed help message +# +# MODE must be one of the following: +# +# clean remove files from the build directory +# compile compile a source file into a libtool object +# execute automatically set library path, then run a program +# finish complete the installation of libtool libraries +# install install libraries or executables +# link create a library or an executable +# uninstall remove libraries from an installed directory +# +# MODE-ARGS vary depending on the MODE. When passed as first option, +# `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that. +# Try `$progname --help --mode=MODE' for a more detailed description of MODE. +# +# When reporting a bug, please describe a test case to reproduce it and +# include the following information: +# +# host-triplet: $host +# shell: $SHELL +# compiler: $LTCC +# compiler flags: $LTCFLAGS +# linker: $LD (gnu? $with_gnu_ld) +# $progname: (GNU libtool) 2.4 +# automake: $automake_version +# autoconf: $autoconf_version +# +# Report bugs to . +# GNU libtool home page: . +# General help using GNU software: . + +PROGRAM=libtool +PACKAGE=libtool +VERSION=2.4 +TIMESTAMP="" +package_revision=1.3293 + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + +# NLS nuisances: We save the old values to restore during execute mode. +lt_user_locale= +lt_safe_locale= +for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +do + eval "if test \"\${$lt_var+set}\" = set; then + save_$lt_var=\$$lt_var + $lt_var=C + export $lt_var + lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" + lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" + fi" +done +LC_ALL=C +LANGUAGE=C +export LANGUAGE LC_ALL + +$lt_unset CDPATH + + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath="$0" + + + +: ${CP="cp -f"} +test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'} +: ${EGREP="/bin/grep -E"} +: ${FGREP="/bin/grep -F"} +: ${GREP="/bin/grep"} +: ${LN_S="ln -s"} +: ${MAKE="make"} +: ${MKDIR="mkdir"} +: ${MV="mv -f"} +: ${RM="rm -f"} +: ${SED="/bin/sed"} +: ${SHELL="${CONFIG_SHELL-/bin/sh}"} +: ${Xsed="$SED -e 1s/^X//"} + +# Global variables: +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. + +exit_status=$EXIT_SUCCESS + +# Make sure IFS has a sensible default +lt_nl=' +' +IFS=" $lt_nl" + +dirname="s,/[^/]*$,," +basename="s,^.*/,," + +# func_dirname file append nondir_replacement +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +func_dirname () +{ + func_dirname_result=`$ECHO "${1}" | $SED "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi +} # func_dirname may be replaced by extended shell implementation + + +# func_basename file +func_basename () +{ + func_basename_result=`$ECHO "${1}" | $SED "$basename"` +} # func_basename may be replaced by extended shell implementation + + +# func_dirname_and_basename file append nondir_replacement +# perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# Implementation must be kept synchronized with func_dirname +# and func_basename. For efficiency, we do not delegate to +# those functions but instead duplicate the functionality here. +func_dirname_and_basename () +{ + # Extract subdirectory from the argument. + func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi + func_basename_result=`$ECHO "${1}" | $SED -e "$basename"` +} # func_dirname_and_basename may be replaced by extended shell implementation + + +# func_stripname prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# func_strip_suffix prefix name +func_stripname () +{ + case ${2} in + .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; + esac +} # func_stripname may be replaced by extended shell implementation + + +# These SED scripts presuppose an absolute path with a trailing slash. +pathcar='s,^/\([^/]*\).*$,\1,' +pathcdr='s,^/[^/]*,,' +removedotparts=':dotsl + s@/\./@/@g + t dotsl + s,/\.$,/,' +collapseslashes='s@/\{1,\}@/@g' +finalslash='s,/*$,/,' + +# func_normal_abspath PATH +# Remove doubled-up and trailing slashes, "." path components, +# and cancel out any ".." path components in PATH after making +# it an absolute path. +# value returned in "$func_normal_abspath_result" +func_normal_abspath () +{ + # Start from root dir and reassemble the path. + func_normal_abspath_result= + func_normal_abspath_tpath=$1 + func_normal_abspath_altnamespace= + case $func_normal_abspath_tpath in + "") + # Empty path, that just means $cwd. + func_stripname '' '/' "`pwd`" + func_normal_abspath_result=$func_stripname_result + return + ;; + # The next three entries are used to spot a run of precisely + # two leading slashes without using negated character classes; + # we take advantage of case's first-match behaviour. + ///*) + # Unusual form of absolute path, do nothing. + ;; + //*) + # Not necessarily an ordinary path; POSIX reserves leading '//' + # and for example Cygwin uses it to access remote file shares + # over CIFS/SMB, so we conserve a leading double slash if found. + func_normal_abspath_altnamespace=/ + ;; + /*) + # Absolute path, do nothing. + ;; + *) + # Relative path, prepend $cwd. + func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath + ;; + esac + # Cancel out all the simple stuff to save iterations. We also want + # the path to end with a slash for ease of parsing, so make sure + # there is one (and only one) here. + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"` + while :; do + # Processed it all yet? + if test "$func_normal_abspath_tpath" = / ; then + # If we ascended to the root using ".." the result may be empty now. + if test -z "$func_normal_abspath_result" ; then + func_normal_abspath_result=/ + fi + break + fi + func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$pathcar"` + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$pathcdr"` + # Figure out what to do with it + case $func_normal_abspath_tcomponent in + "") + # Trailing empty path component, ignore it. + ;; + ..) + # Parent dir; strip last assembled component from result. + func_dirname "$func_normal_abspath_result" + func_normal_abspath_result=$func_dirname_result + ;; + *) + # Actual path component, append it. + func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent + ;; + esac + done + # Restore leading double-slash if one was found on entry. + func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result +} + +# func_relative_path SRCDIR DSTDIR +# generates a relative path from SRCDIR to DSTDIR, with a trailing +# slash if non-empty, suitable for immediately appending a filename +# without needing to append a separator. +# value returned in "$func_relative_path_result" +func_relative_path () +{ + func_relative_path_result= + func_normal_abspath "$1" + func_relative_path_tlibdir=$func_normal_abspath_result + func_normal_abspath "$2" + func_relative_path_tbindir=$func_normal_abspath_result + + # Ascend the tree starting from libdir + while :; do + # check if we have found a prefix of bindir + case $func_relative_path_tbindir in + $func_relative_path_tlibdir) + # found an exact match + func_relative_path_tcancelled= + break + ;; + $func_relative_path_tlibdir*) + # found a matching prefix + func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" + func_relative_path_tcancelled=$func_stripname_result + if test -z "$func_relative_path_result"; then + func_relative_path_result=. + fi + break + ;; + *) + func_dirname $func_relative_path_tlibdir + func_relative_path_tlibdir=${func_dirname_result} + if test "x$func_relative_path_tlibdir" = x ; then + # Have to descend all the way to the root! + func_relative_path_result=../$func_relative_path_result + func_relative_path_tcancelled=$func_relative_path_tbindir + break + fi + func_relative_path_result=../$func_relative_path_result + ;; + esac + done + + # Now calculate path; take care to avoid doubling-up slashes. + func_stripname '' '/' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + func_stripname '/' '/' "$func_relative_path_tcancelled" + if test "x$func_stripname_result" != x ; then + func_relative_path_result=${func_relative_path_result}/${func_stripname_result} + fi + + # Normalisation. If bindir is libdir, return empty string, + # else relative path ending with a slash; either way, target + # file name can be directly appended. + if test ! -z "$func_relative_path_result"; then + func_stripname './' '' "$func_relative_path_result/" + func_relative_path_result=$func_stripname_result + fi +} + +# The name of this program: +func_dirname_and_basename "$progpath" +progname=$func_basename_result + +# Make sure we have an absolute path for reexecution: +case $progpath in + [\\/]*|[A-Za-z]:\\*) ;; + *[\\/]*) + progdir=$func_dirname_result + progdir=`cd "$progdir" && pwd` + progpath="$progdir/$progname" + ;; + *) + save_IFS="$IFS" + IFS=: + for progdir in $PATH; do + IFS="$save_IFS" + test -x "$progdir/$progname" && break + done + IFS="$save_IFS" + test -n "$progdir" || progdir=`pwd` + progpath="$progdir/$progname" + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed="${SED}"' -e 1s/^X//' +sed_quote_subst='s/\([`"$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution that turns a string into a regex matching for the +# string literally. +sed_make_literal_regex='s,[].[^$\\*\/],\\&,g' + +# Sed substitution that converts a w32 file name or path +# which contains forward slashes, into one that contains +# (escaped) backslashes. A very naive implementation. +lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + +# Re-`\' parameter expansions in output of double_quote_subst that were +# `\'-ed in input to the same. If an odd number of `\' preceded a '$' +# in input to double_quote_subst, that '$' was protected from expansion. +# Since each input `\' is now two `\'s, look for any number of runs of +# four `\'s followed by two `\'s and then a '$'. `\' that '$'. +bs='\\' +bs2='\\\\' +bs4='\\\\\\\\' +dollar='\$' +sed_double_backslash="\ + s/$bs4/&\\ +/g + s/^$bs2$dollar/$bs&/ + s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g + s/\n//g" + +# Standard options: +opt_dry_run=false +opt_help=false +opt_quiet=false +opt_verbose=false +opt_warning=: + +# func_echo arg... +# Echo program name prefixed message, along with the current mode +# name if it has been set yet. +func_echo () +{ + $ECHO "$progname: ${opt_mode+$opt_mode: }$*" +} + +# func_verbose arg... +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $opt_verbose && func_echo ${1+"$@"} + + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + +# func_error arg... +# Echo program name prefixed message to standard error. +func_error () +{ + $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 +} + +# func_warning arg... +# Echo program name prefixed warning message to standard error. +func_warning () +{ + $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 + + # bash bug again: + : +} + +# func_fatal_error arg... +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + func_error ${1+"$@"} + exit $EXIT_FAILURE +} + +# func_fatal_help arg... +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () +{ + func_error ${1+"$@"} + func_fatal_error "$help" +} +help="Try \`$progname --help' for more information." ## default + + +# func_grep expression filename +# Check whether EXPRESSION matches any line of FILENAME, without output. +func_grep () +{ + $GREP "$1" "$2" >/dev/null 2>&1 +} + + +# func_mkdir_p directory-path +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ + my_directory_path="$1" + my_dir_list= + + if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then + + # Protect directory names starting with `-' + case $my_directory_path in + -*) my_directory_path="./$my_directory_path" ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$my_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + my_dir_list="$my_directory_path:$my_dir_list" + + # If the last portion added has no slash in it, the list is done + case $my_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"` + done + my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'` + + save_mkdir_p_IFS="$IFS"; IFS=':' + for my_dir in $my_dir_list; do + IFS="$save_mkdir_p_IFS" + # mkdir can fail with a `File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$my_dir" 2>/dev/null || : + done + IFS="$save_mkdir_p_IFS" + + # Bail out if we (or some other process) failed to create a directory. + test -d "$my_directory_path" || \ + func_fatal_error "Failed to create \`$1'" + fi +} + + +# func_mktempdir [string] +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, STRING is the basename for that directory. +func_mktempdir () +{ + my_template="${TMPDIR-/tmp}/${1-$progname}" + + if test "$opt_dry_run" = ":"; then + # Return a directory name, but don't create it in dry-run mode + my_tmpdir="${my_template}-$$" + else + + # If mktemp works, use that first and foremost + my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` + + if test ! -d "$my_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + my_tmpdir="${my_template}-${RANDOM-0}$$" + + save_mktempdir_umask=`umask` + umask 0077 + $MKDIR "$my_tmpdir" + umask $save_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$my_tmpdir" || \ + func_fatal_error "cannot create temporary directory \`$my_tmpdir'" + fi + + $ECHO "$my_tmpdir" +} + + +# func_quote_for_eval arg +# Aesthetically quote ARG to be evaled later. +# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT +# is double-quoted, suitable for a subsequent eval, whereas +# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters +# which are still active within double quotes backslashified. +func_quote_for_eval () +{ + case $1 in + *[\\\`\"\$]*) + func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;; + *) + func_quote_for_eval_unquoted_result="$1" ;; + esac + + case $func_quote_for_eval_unquoted_result in + # Double-quote args containing shell metacharacters to delay + # word splitting, command substitution and and variable + # expansion for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" + ;; + *) + func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" + esac +} + + +# func_quote_for_expand arg +# Aesthetically quote ARG to be evaled later; same as above, +# but do not quote variable references. +func_quote_for_expand () +{ + case $1 in + *[\\\`\"]*) + my_arg=`$ECHO "$1" | $SED \ + -e "$double_quote_subst" -e "$sed_double_backslash"` ;; + *) + my_arg="$1" ;; + esac + + case $my_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting and command substitution for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + my_arg="\"$my_arg\"" + ;; + esac + + func_quote_for_expand_result="$my_arg" +} + + +# func_show_eval cmd [fail_exp] +# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + my_cmd="$1" + my_fail_exp="${2-:}" + + ${opt_silent-false} || { + func_quote_for_expand "$my_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + if ${opt_dry_run-false}; then :; else + eval "$my_cmd" + my_status=$? + if test "$my_status" -eq 0; then :; else + eval "(exit $my_status); $my_fail_exp" + fi + fi +} + + +# func_show_eval_locale cmd [fail_exp] +# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () +{ + my_cmd="$1" + my_fail_exp="${2-:}" + + ${opt_silent-false} || { + func_quote_for_expand "$my_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + if ${opt_dry_run-false}; then :; else + eval "$lt_user_locale + $my_cmd" + my_status=$? + eval "$lt_safe_locale" + if test "$my_status" -eq 0; then :; else + eval "(exit $my_status); $my_fail_exp" + fi + fi +} + +# func_tr_sh +# Turn $1 into a string suitable for a shell variable name. +# Result is stored in $func_tr_sh_result. All characters +# not in the set a-zA-Z0-9_ are replaced with '_'. Further, +# if $1 begins with a digit, a '_' is prepended as well. +func_tr_sh () +{ + case $1 in + [0-9]* | *[!a-zA-Z0-9_]*) + func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'` + ;; + * ) + func_tr_sh_result=$1 + ;; + esac +} + + +# func_version +# Echo version message to standard output and exit. +func_version () +{ + $opt_debug + + $SED -n '/(C)/!b go + :more + /\./!{ + N + s/\n# / / + b more + } + :go + /^# '$PROGRAM' (GNU /,/# warranty; / { + s/^# // + s/^# *$// + s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ + p + }' < "$progpath" + exit $? +} + +# func_usage +# Echo short help message to standard output and exit. +func_usage () +{ + $opt_debug + + $SED -n '/^# Usage:/,/^# *.*--help/ { + s/^# // + s/^# *$// + s/\$progname/'$progname'/ + p + }' < "$progpath" + echo + $ECHO "run \`$progname --help | more' for full usage" + exit $? +} + +# func_help [NOEXIT] +# Echo long help message to standard output and exit, +# unless 'noexit' is passed as argument. +func_help () +{ + $opt_debug + + $SED -n '/^# Usage:/,/# Report bugs to/ { + :print + s/^# // + s/^# *$// + s*\$progname*'$progname'* + s*\$host*'"$host"'* + s*\$SHELL*'"$SHELL"'* + s*\$LTCC*'"$LTCC"'* + s*\$LTCFLAGS*'"$LTCFLAGS"'* + s*\$LD*'"$LD"'* + s/\$with_gnu_ld/'"$with_gnu_ld"'/ + s/\$automake_version/'"`(automake --version) 2>/dev/null |$SED 1q`"'/ + s/\$autoconf_version/'"`(autoconf --version) 2>/dev/null |$SED 1q`"'/ + p + d + } + /^# .* home page:/b print + /^# General help using/b print + ' < "$progpath" + ret=$? + if test -z "$1"; then + exit $ret + fi +} + +# func_missing_arg argname +# Echo program name prefixed message to standard error and set global +# exit_cmd. +func_missing_arg () +{ + $opt_debug + + func_error "missing argument for $1." + exit_cmd=exit +} + + +# func_split_short_opt shortopt +# Set func_split_short_opt_name and func_split_short_opt_arg shell +# variables after splitting SHORTOPT after the 2nd character. +func_split_short_opt () +{ + my_sed_short_opt='1s/^\(..\).*$/\1/;q' + my_sed_short_rest='1s/^..\(.*\)$/\1/;q' + + func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"` + func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"` +} # func_split_short_opt may be replaced by extended shell implementation + + +# func_split_long_opt longopt +# Set func_split_long_opt_name and func_split_long_opt_arg shell +# variables after splitting LONGOPT at the `=' sign. +func_split_long_opt () +{ + my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q' + my_sed_long_arg='1s/^--[^=]*=//' + + func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"` + func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"` +} # func_split_long_opt may be replaced by extended shell implementation + +exit_cmd=: + + + + + +magic="%%%MAGIC variable%%%" +magic_exe="%%%MAGIC EXE variable%%%" + +# Global variables. +nonopt= +preserve_args= +lo2o="s/\\.lo\$/.${objext}/" +o2lo="s/\\.${objext}\$/.lo/" +extracted_archives= +extracted_serial=0 + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + +# func_append var value +# Append VALUE to the end of shell variable VAR. +func_append () +{ + eval "${1}=\$${1}\${2}" +} # func_append may be replaced by extended shell implementation + +# func_append_quoted var value +# Quote VALUE and append to the end of shell variable VAR, separated +# by a space. +func_append_quoted () +{ + func_quote_for_eval "${2}" + eval "${1}=\$${1}\\ \$func_quote_for_eval_result" +} # func_append_quoted may be replaced by extended shell implementation + + +# func_arith arithmetic-term... +func_arith () +{ + func_arith_result=`expr "${@}"` +} # func_arith may be replaced by extended shell implementation + + +# func_len string +# STRING may not start with a hyphen. +func_len () +{ + func_len_result=`expr "${1}" : ".*" 2>/dev/null || echo $max_cmd_len` +} # func_len may be replaced by extended shell implementation + + +# func_lo2o object +func_lo2o () +{ + func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"` +} # func_lo2o may be replaced by extended shell implementation + + +# func_xform libobj-or-source +func_xform () +{ + func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'` +} # func_xform may be replaced by extended shell implementation + + +# func_fatal_configuration arg... +# Echo program name prefixed message to standard error, followed by +# a configuration failure hint, and exit. +func_fatal_configuration () +{ + func_error ${1+"$@"} + func_error "See the $PACKAGE documentation for more information." + func_fatal_error "Fatal configuration error." +} + + +# func_config +# Display the configuration for all the tags in this script. +func_config () +{ + re_begincf='^# ### BEGIN LIBTOOL' + re_endcf='^# ### END LIBTOOL' + + # Default configuration. + $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" + + # Now print the configurations for the tags. + for tagname in $taglist; do + $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" + done + + exit $? +} + +# func_features +# Display the features supported by this script. +func_features () +{ + echo "host: $host" + if test "$build_libtool_libs" = yes; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test "$build_old_libs" = yes; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + + exit $? +} + +# func_enable_tag tagname +# Verify that TAGNAME is valid, and either flag an error and exit, or +# enable the TAGNAME tag. We also add TAGNAME to the global $taglist +# variable here. +func_enable_tag () +{ + # Global variable: + tagname="$1" + + re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" + re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" + sed_extractcf="/$re_begincf/,/$re_endcf/p" + + # Validate tagname. + case $tagname in + *[!-_A-Za-z0-9,/]*) + func_fatal_error "invalid tag name: $tagname" + ;; + esac + + # Don't test for the "default" C tag, as we know it's + # there but not specially marked. + case $tagname in + CC) ;; + *) + if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then + taglist="$taglist $tagname" + + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac +} + +# func_check_version_match +# Ensure that we are using m4 macros, and libtool script from the same +# release of libtool. +func_check_version_match () +{ + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from an older release. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + fi + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, +$progname: but the definition of this LT_INIT comes from revision $macro_revision. +$progname: You should recreate aclocal.m4 with macros from revision $package_revision +$progname: of $PACKAGE $VERSION and run autoconf again. +_LT_EOF + fi + + exit $EXIT_MISMATCH + fi +} + + +# Shorthand for --mode=foo, only valid as the first argument +case $1 in +clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; +compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; +execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; +finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; +install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; +link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; +uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; +esac + + + +# Option defaults: +opt_debug=: +opt_dry_run=false +opt_config=false +opt_preserve_dup_deps=false +opt_features=false +opt_finish=false +opt_help=false +opt_help_all=false +opt_silent=: +opt_verbose=: +opt_silent=false +opt_verbose=false + + +# Parse options once, thoroughly. This comes as soon as possible in the +# script to make things like `--version' happen as quickly as we can. +{ + # this just eases exit handling + while test $# -gt 0; do + opt="$1" + shift + case $opt in + --debug|-x) opt_debug='set -x' + func_echo "enabling shell trace mode" + $opt_debug + ;; + --dry-run|--dryrun|-n) + opt_dry_run=: + ;; + --config) + opt_config=: +func_config + ;; + --dlopen|-dlopen) + optarg="$1" + opt_dlopen="${opt_dlopen+$opt_dlopen +}$optarg" + shift + ;; + --preserve-dup-deps) + opt_preserve_dup_deps=: + ;; + --features) + opt_features=: +func_features + ;; + --finish) + opt_finish=: +set dummy --mode finish ${1+"$@"}; shift + ;; + --help) + opt_help=: + ;; + --help-all) + opt_help_all=: +opt_help=': help-all' + ;; + --mode) + test $# = 0 && func_missing_arg $opt && break + optarg="$1" + opt_mode="$optarg" +case $optarg in + # Valid mode arguments: + clean|compile|execute|finish|install|link|relink|uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $opt" + exit_cmd=exit + break + ;; +esac + shift + ;; + --no-silent|--no-quiet) + opt_silent=false +func_append preserve_args " $opt" + ;; + --no-verbose) + opt_verbose=false +func_append preserve_args " $opt" + ;; + --silent|--quiet) + opt_silent=: +func_append preserve_args " $opt" + opt_verbose=false + ;; + --verbose|-v) + opt_verbose=: +func_append preserve_args " $opt" +opt_silent=false + ;; + --tag) + test $# = 0 && func_missing_arg $opt && break + optarg="$1" + opt_tag="$optarg" +func_append preserve_args " $opt $optarg" +func_enable_tag "$optarg" + shift + ;; + + -\?|-h) func_usage ;; + --help) func_help ;; + --version) func_version ;; + + # Separate optargs to long options: + --*=*) + func_split_long_opt "$opt" + set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"} + shift + ;; + + # Separate non-argument short options: + -\?*|-h*|-n*|-v*) + func_split_short_opt "$opt" + set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + --) break ;; + -*) func_fatal_help "unrecognized option \`$opt'" ;; + *) set dummy "$opt" ${1+"$@"}; shift; break ;; + esac + done + + # Validate options: + + # save first non-option argument + if test "$#" -gt 0; then + nonopt="$opt" + shift + fi + + # preserve --debug + test "$opt_debug" = : || func_append preserve_args " --debug" + + case $host in + *cygwin* | *mingw* | *pw32* | *cegcc*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps + ;; + esac + + $opt_help || { + # Sanity checks first: + func_check_version_match + + if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then + func_fatal_configuration "not configured to build any kind of library" + fi + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$opt_dlopen" && test "$opt_mode" != execute; then + func_error "unrecognized option \`-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$progname --help --mode=$opt_mode' for more information." + } + + + # Bail if the options were screwed + $exit_cmd $EXIT_FAILURE +} + + + + +## ----------- ## +## Main. ## +## ----------- ## + +# func_lalib_p file +# True iff FILE is a libtool `.la' library or `.lo' object file. +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_lalib_p () +{ + test -f "$1" && + $SED -e 4q "$1" 2>/dev/null \ + | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + +# func_lalib_unsafe_p file +# True iff FILE is a libtool `.la' library or `.lo' object file. +# This function implements the same check as func_lalib_p without +# resorting to external programs. To this end, it redirects stdin and +# closes it afterwards, without saving the original file descriptor. +# As a safety measure, use it only where a negative result would be +# fatal anyway. Works if `file' does not exist. +func_lalib_unsafe_p () +{ + lalib_p=no + if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then + for lalib_p_l in 1 2 3 4 + do + read lalib_p_line + case "$lalib_p_line" in + \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; + esac + done + exec 0<&5 5<&- + fi + test "$lalib_p" = yes +} + +# func_ltwrapper_script_p file +# True iff FILE is a libtool wrapper script +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_script_p () +{ + func_lalib_p "$1" +} + +# func_ltwrapper_executable_p file +# True iff FILE is a libtool wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_executable_p () +{ + func_ltwrapper_exec_suffix= + case $1 in + *.exe) ;; + *) func_ltwrapper_exec_suffix=.exe ;; + esac + $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 +} + +# func_ltwrapper_scriptname file +# Assumes file is an ltwrapper_executable +# uses $file to determine the appropriate filename for a +# temporary ltwrapper_script. +func_ltwrapper_scriptname () +{ + func_dirname_and_basename "$1" "" "." + func_stripname '' '.exe' "$func_basename_result" + func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" +} + +# func_ltwrapper_p file +# True iff FILE is a libtool wrapper script or wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_p () +{ + func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" +} + + +# func_execute_cmds commands fail_cmd +# Execute tilde-delimited COMMANDS. +# If FAIL_CMD is given, eval that upon failure. +# FAIL_CMD may read-access the current command in variable CMD! +func_execute_cmds () +{ + $opt_debug + save_ifs=$IFS; IFS='~' + for cmd in $1; do + IFS=$save_ifs + eval cmd=\"$cmd\" + func_show_eval "$cmd" "${2-:}" + done + IFS=$save_ifs +} + + +# func_source file +# Source FILE, adding directory component if necessary. +# Note that it is not necessary on cygwin/mingw to append a dot to +# FILE even if both FILE and FILE.exe exist: automatic-append-.exe +# behavior happens only for exec(3), not for open(2)! Also, sourcing +# `FILE.' does not work on cygwin managed mounts. +func_source () +{ + $opt_debug + case $1 in + */* | *\\*) . "$1" ;; + *) . "./$1" ;; + esac +} + + +# func_resolve_sysroot PATH +# Replace a leading = in PATH with a sysroot. Store the result into +# func_resolve_sysroot_result +func_resolve_sysroot () +{ + func_resolve_sysroot_result=$1 + case $func_resolve_sysroot_result in + =*) + func_stripname '=' '' "$func_resolve_sysroot_result" + func_resolve_sysroot_result=$lt_sysroot$func_stripname_result + ;; + esac +} + +# func_replace_sysroot PATH +# If PATH begins with the sysroot, replace it with = and +# store the result into func_replace_sysroot_result. +func_replace_sysroot () +{ + case "$lt_sysroot:$1" in + ?*:"$lt_sysroot"*) + func_stripname "$lt_sysroot" '' "$1" + func_replace_sysroot_result="=$func_stripname_result" + ;; + *) + # Including no sysroot. + func_replace_sysroot_result=$1 + ;; + esac +} + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + $opt_debug + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case "$@ " in + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + func_echo "unable to infer tagged configuration" + func_fatal_error "specify a tag with \`--tag'" +# else +# func_verbose "using $tagname tagged configuration" + fi + ;; + esac + fi +} + + + +# func_write_libtool_object output_name pic_name nonpic_name +# Create a libtool object file (analogous to a ".la" file), +# but don't create it if we're doing a dry run. +func_write_libtool_object () +{ + write_libobj=${1} + if test "$build_libtool_libs" = yes; then + write_lobj=\'${2}\' + else + write_lobj=none + fi + + if test "$build_old_libs" = yes; then + write_oldobj=\'${3}\' + else + write_oldobj=none + fi + + $opt_dry_run || { + cat >${write_libobj}T </dev/null` + if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then + func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | + $SED -e "$lt_sed_naive_backslashify"` + else + func_convert_core_file_wine_to_w32_result= + fi + fi +} +# end: func_convert_core_file_wine_to_w32 + + +# func_convert_core_path_wine_to_w32 ARG +# Helper function used by path conversion functions when $build is *nix, and +# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly +# configured wine environment available, with the winepath program in $build's +# $PATH. Assumes ARG has no leading or trailing path separator characters. +# +# ARG is path to be converted from $build format to win32. +# Result is available in $func_convert_core_path_wine_to_w32_result. +# Unconvertible file (directory) names in ARG are skipped; if no directory names +# are convertible, then the result may be empty. +func_convert_core_path_wine_to_w32 () +{ + $opt_debug + # unfortunately, winepath doesn't convert paths, only file names + func_convert_core_path_wine_to_w32_result="" + if test -n "$1"; then + oldIFS=$IFS + IFS=: + for func_convert_core_path_wine_to_w32_f in $1; do + IFS=$oldIFS + func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" + if test -n "$func_convert_core_file_wine_to_w32_result" ; then + if test -z "$func_convert_core_path_wine_to_w32_result"; then + func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result" + else + func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" + fi + fi + done + IFS=$oldIFS + fi +} +# end: func_convert_core_path_wine_to_w32 + + +# func_cygpath ARGS... +# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when +# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) +# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or +# (2), returns the Cygwin file name or path in func_cygpath_result (input +# file name or path is assumed to be in w32 format, as previously converted +# from $build's *nix or MSYS format). In case (3), returns the w32 file name +# or path in func_cygpath_result (input file name or path is assumed to be in +# Cygwin format). Returns an empty string on error. +# +# ARGS are passed to cygpath, with the last one being the file name or path to +# be converted. +# +# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH +# environment variable; do not put it in $PATH. +func_cygpath () +{ + $opt_debug + if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then + func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` + if test "$?" -ne 0; then + # on failure, ensure result is empty + func_cygpath_result= + fi + else + func_cygpath_result= + func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'" + fi +} +#end: func_cygpath + + +# func_convert_core_msys_to_w32 ARG +# Convert file name or path ARG from MSYS format to w32 format. Return +# result in func_convert_core_msys_to_w32_result. +func_convert_core_msys_to_w32 () +{ + $opt_debug + # awkward: cmd appends spaces to result + func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | + $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"` +} +#end: func_convert_core_msys_to_w32 + + +# func_convert_file_check ARG1 ARG2 +# Verify that ARG1 (a file name in $build format) was converted to $host +# format in ARG2. Otherwise, emit an error message, but continue (resetting +# func_to_host_file_result to ARG1). +func_convert_file_check () +{ + $opt_debug + if test -z "$2" && test -n "$1" ; then + func_error "Could not determine host file name corresponding to" + func_error " \`$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback: + func_to_host_file_result="$1" + fi +} +# end func_convert_file_check + + +# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH +# Verify that FROM_PATH (a path in $build format) was converted to $host +# format in TO_PATH. Otherwise, emit an error message, but continue, resetting +# func_to_host_file_result to a simplistic fallback value (see below). +func_convert_path_check () +{ + $opt_debug + if test -z "$4" && test -n "$3"; then + func_error "Could not determine the host path corresponding to" + func_error " \`$3'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback. This is a deliberately simplistic "conversion" and + # should not be "improved". See libtool.info. + if test "x$1" != "x$2"; then + lt_replace_pathsep_chars="s|$1|$2|g" + func_to_host_path_result=`echo "$3" | + $SED -e "$lt_replace_pathsep_chars"` + else + func_to_host_path_result="$3" + fi + fi +} +# end func_convert_path_check + + +# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG +# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT +# and appending REPL if ORIG matches BACKPAT. +func_convert_path_front_back_pathsep () +{ + $opt_debug + case $4 in + $1 ) func_to_host_path_result="$3$func_to_host_path_result" + ;; + esac + case $4 in + $2 ) func_append func_to_host_path_result "$3" + ;; + esac +} +# end func_convert_path_front_back_pathsep + + +################################################## +# $build to $host FILE NAME CONVERSION FUNCTIONS # +################################################## +# invoked via `$to_host_file_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# Result will be available in $func_to_host_file_result. + + +# func_to_host_file ARG +# Converts the file name ARG from $build format to $host format. Return result +# in func_to_host_file_result. +func_to_host_file () +{ + $opt_debug + $to_host_file_cmd "$1" +} +# end func_to_host_file + + +# func_to_tool_file ARG LAZY +# converts the file name ARG from $build format to toolchain format. Return +# result in func_to_tool_file_result. If the conversion in use is listed +# in (the comma separated) LAZY, no conversion takes place. +func_to_tool_file () +{ + $opt_debug + case ,$2, in + *,"$to_tool_file_cmd",*) + func_to_tool_file_result=$1 + ;; + *) + $to_tool_file_cmd "$1" + func_to_tool_file_result=$func_to_host_file_result + ;; + esac +} +# end func_to_tool_file + + +# func_convert_file_noop ARG +# Copy ARG to func_to_host_file_result. +func_convert_file_noop () +{ + func_to_host_file_result="$1" +} +# end func_convert_file_noop + + +# func_convert_file_msys_to_w32 ARG +# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_file_result. +func_convert_file_msys_to_w32 () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_to_host_file_result="$func_convert_core_msys_to_w32_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_w32 + + +# func_convert_file_cygwin_to_w32 ARG +# Convert file name ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_file_cygwin_to_w32 () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + # because $build is cygwin, we call "the" cygpath in $PATH; no need to use + # LT_CYGPATH in this case. + func_to_host_file_result=`cygpath -m "$1"` + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_cygwin_to_w32 + + +# func_convert_file_nix_to_w32 ARG +# Convert file name ARG from *nix to w32 format. Requires a wine environment +# and a working winepath. Returns result in func_to_host_file_result. +func_convert_file_nix_to_w32 () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + func_convert_core_file_wine_to_w32 "$1" + func_to_host_file_result="$func_convert_core_file_wine_to_w32_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_w32 + + +# func_convert_file_msys_to_cygwin ARG +# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_file_msys_to_cygwin () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_cygpath -u "$func_convert_core_msys_to_w32_result" + func_to_host_file_result="$func_cygpath_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_cygwin + + +# func_convert_file_nix_to_cygwin ARG +# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed +# in a wine environment, working winepath, and LT_CYGPATH set. Returns result +# in func_to_host_file_result. +func_convert_file_nix_to_cygwin () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. + func_convert_core_file_wine_to_w32 "$1" + func_cygpath -u "$func_convert_core_file_wine_to_w32_result" + func_to_host_file_result="$func_cygpath_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_cygwin + + +############################################# +# $build to $host PATH CONVERSION FUNCTIONS # +############################################# +# invoked via `$to_host_path_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# The result will be available in $func_to_host_path_result. +# +# Path separators are also converted from $build format to $host format. If +# ARG begins or ends with a path separator character, it is preserved (but +# converted to $host format) on output. +# +# All path conversion functions are named using the following convention: +# file name conversion function : func_convert_file_X_to_Y () +# path conversion function : func_convert_path_X_to_Y () +# where, for any given $build/$host combination the 'X_to_Y' value is the +# same. If conversion functions are added for new $build/$host combinations, +# the two new functions must follow this pattern, or func_init_to_host_path_cmd +# will break. + + +# func_init_to_host_path_cmd +# Ensures that function "pointer" variable $to_host_path_cmd is set to the +# appropriate value, based on the value of $to_host_file_cmd. +to_host_path_cmd= +func_init_to_host_path_cmd () +{ + $opt_debug + if test -z "$to_host_path_cmd"; then + func_stripname 'func_convert_file_' '' "$to_host_file_cmd" + to_host_path_cmd="func_convert_path_${func_stripname_result}" + fi +} + + +# func_to_host_path ARG +# Converts the path ARG from $build format to $host format. Return result +# in func_to_host_path_result. +func_to_host_path () +{ + $opt_debug + func_init_to_host_path_cmd + $to_host_path_cmd "$1" +} +# end func_to_host_path + + +# func_convert_path_noop ARG +# Copy ARG to func_to_host_path_result. +func_convert_path_noop () +{ + func_to_host_path_result="$1" +} +# end func_convert_path_noop + + +# func_convert_path_msys_to_w32 ARG +# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_path_result. +func_convert_path_msys_to_w32 () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # Remove leading and trailing path separator characters from ARG. MSYS + # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; + # and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result="$func_convert_core_msys_to_w32_result" + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_msys_to_w32 + + +# func_convert_path_cygwin_to_w32 ARG +# Convert path ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_path_cygwin_to_w32 () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_cygwin_to_w32 + + +# func_convert_path_nix_to_w32 ARG +# Convert path ARG from *nix to w32 format. Requires a wine environment and +# a working winepath. Returns result in func_to_host_file_result. +func_convert_path_nix_to_w32 () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result="$func_convert_core_path_wine_to_w32_result" + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_nix_to_w32 + + +# func_convert_path_msys_to_cygwin ARG +# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_path_msys_to_cygwin () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_msys_to_w32_result" + func_to_host_path_result="$func_cygpath_result" + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_msys_to_cygwin + + +# func_convert_path_nix_to_cygwin ARG +# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a +# a wine environment, working winepath, and LT_CYGPATH set. Returns result in +# func_to_host_file_result. +func_convert_path_nix_to_cygwin () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # Remove leading and trailing path separator characters from + # ARG. msys behavior is inconsistent here, cygpath turns them + # into '.;' and ';.', and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" + func_to_host_path_result="$func_cygpath_result" + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_nix_to_cygwin + + +# func_mode_compile arg... +func_mode_compile () +{ + $opt_debug + # Get the compilation command and the source file. + base_compile= + srcfile="$nonopt" # always keep a non-empty value in "srcfile" + suppress_opt=yes + suppress_output= + arg_mode=normal + libobj= + later= + pie_flag= + + for arg + do + case $arg_mode in + arg ) + # do not "continue". Instead, add this to base_compile + lastarg="$arg" + arg_mode=normal + ;; + + target ) + libobj="$arg" + arg_mode=normal + continue + ;; + + normal ) + # Accept any command-line options. + case $arg in + -o) + test -n "$libobj" && \ + func_fatal_error "you cannot specify \`-o' more than once" + arg_mode=target + continue + ;; + + -pie | -fpie | -fPIE) + func_append pie_flag " $arg" + continue + ;; + + -shared | -static | -prefer-pic | -prefer-non-pic) + func_append later " $arg" + continue + ;; + + -no-suppress) + suppress_opt=no + continue + ;; + + -Xcompiler) + arg_mode=arg # the next one goes into the "base_compile" arg list + continue # The current "srcfile" will either be retained or + ;; # replaced later. I would guess that would be a bug. + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + lastarg= + save_ifs="$IFS"; IFS=',' + for arg in $args; do + IFS="$save_ifs" + func_append_quoted lastarg "$arg" + done + IFS="$save_ifs" + func_stripname ' ' '' "$lastarg" + lastarg=$func_stripname_result + + # Add the arguments to base_compile. + func_append base_compile " $lastarg" + continue + ;; + + *) + # Accept the current argument as the source file. + # The previous "srcfile" becomes the current argument. + # + lastarg="$srcfile" + srcfile="$arg" + ;; + esac # case $arg + ;; + esac # case $arg_mode + + # Aesthetically quote the previous argument. + func_append_quoted base_compile "$lastarg" + done # for arg + + case $arg_mode in + arg) + func_fatal_error "you must specify an argument for -Xcompile" + ;; + target) + func_fatal_error "you must specify a target with \`-o'" + ;; + *) + # Get the name of the library object. + test -z "$libobj" && { + func_basename "$srcfile" + libobj="$func_basename_result" + } + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + case $libobj in + *.[cCFSifmso] | \ + *.ada | *.adb | *.ads | *.asm | \ + *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ + *.[fF][09]? | *.for | *.java | *.obj | *.sx | *.cu | *.cup) + func_xform "$libobj" + libobj=$func_xform_result + ;; + esac + + case $libobj in + *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; + *) + func_fatal_error "cannot determine name of library object from \`$libobj'" + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -shared) + test "$build_libtool_libs" != yes && \ + func_fatal_configuration "can not build a shared library" + build_old_libs=no + continue + ;; + + -static) + build_libtool_libs=no + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + func_quote_for_eval "$libobj" + test "X$libobj" != "X$func_quote_for_eval_result" \ + && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && func_warning "libobj name \`$libobj' may not contain shell special characters." + func_dirname_and_basename "$obj" "/" "" + objname="$func_basename_result" + xdir="$func_dirname_result" + lobj=${xdir}$objdir/$objname + + test -z "$base_compile" && \ + func_fatal_help "you must specify a compilation command" + + # Delete any leftover library objects. + if test "$build_old_libs" = yes; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2* | cegcc*) + pic_mode=default + ;; + esac + if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test "$compiler_c_o" = no; then + output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext} + lockfile="$output_obj.lock" + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test "$need_locks" = yes; then + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + elif test "$need_locks" = warn; then + if test -f "$lockfile"; then + $ECHO "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + func_append removelist " $output_obj" + $ECHO "$srcfile" > "$lockfile" + fi + + $opt_dry_run || $RM $removelist + func_append removelist " $lockfile" + trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 + + func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 + srcfile=$func_to_tool_file_result + func_quote_for_eval "$srcfile" + qsrcfile=$func_quote_for_eval_result + + # Only build a PIC object if we are building libtool libraries. + if test "$build_libtool_libs" = yes; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test "$pic_mode" != no; then + command="$base_compile $qsrcfile $pic_flag" + else + # Don't build PIC code + command="$base_compile $qsrcfile" + fi + + func_mkdir_p "$xdir$objdir" + + if test -z "$output_obj"; then + # Place PIC objects in $objdir + func_append command " -o $lobj" + fi + + func_show_eval_locale "$command" \ + 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' + + if test "$need_locks" = warn && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + func_show_eval '$MV "$output_obj" "$lobj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + + # Allow error messages only from the first compilation. + if test "$suppress_opt" = yes; then + suppress_output=' >/dev/null 2>&1' + fi + fi + + # Only build a position-dependent object if we build old libraries. + if test "$build_old_libs" = yes; then + if test "$pic_mode" != yes; then + # Don't build PIC code + command="$base_compile $qsrcfile$pie_flag" + else + command="$base_compile $qsrcfile $pic_flag" + fi + if test "$compiler_c_o" = yes; then + func_append command " -o $obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + func_append command "$suppress_output" + func_show_eval_locale "$command" \ + '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' + + if test "$need_locks" = warn && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + func_show_eval '$MV "$output_obj" "$obj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + fi + + $opt_dry_run || { + func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" + + # Unlock the critical section if it was locked + if test "$need_locks" != no; then + removelist=$lockfile + $RM "$lockfile" + fi + } + + exit $EXIT_SUCCESS +} + +$opt_help || { + test "$opt_mode" = compile && func_mode_compile ${1+"$@"} +} + +func_mode_help () +{ + # We need to display help for each of the modes. + case $opt_mode in + "") + # Generic help is extracted from the usage comments + # at the start of this file. + func_help + ;; + + clean) + $ECHO \ +"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + + compile) + $ECHO \ +"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -no-suppress do not suppress compiler output for multiple passes + -prefer-pic try to build PIC objects only + -prefer-non-pic try to build non-PIC objects only + -shared do not build a \`.o' file suitable for static linking + -static only build a \`.o' file suitable for static linking + -Wc,FLAG pass FLAG directly to the compiler + +COMPILE-COMMAND is a command to be used in creating a \`standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix \`.c' with the +library object suffix, \`.lo'." + ;; + + execute) + $ECHO \ +"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to \`-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + + finish) + $ECHO \ +"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the \`--dry-run' option if you just want to see what would be executed." + ;; + + install) + $ECHO \ +"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the \`install' or \`cp' program. + +The following components of INSTALL-COMMAND are treated specially: + + -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + + link) + $ECHO \ +"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -bindir BINDIR specify path to binaries directory (for systems where + libraries must be found in the PATH setting at runtime) + -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE Use a list of object files found in FILE to specify objects + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -shared only do dynamic linking of libtool libraries + -shrext SUFFIX override the standard shared library file extension + -static do not do any dynamic linking of uninstalled libtool libraries + -static-libtool-libs + do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + -weak LIBNAME declare that the target provides the LIBNAME interface + -Wc,FLAG + -Xcompiler FLAG pass linker-specific FLAG directly to the compiler + -Wl,FLAG + -Xlinker FLAG pass linker-specific FLAG directly to the linker + -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) + +All other options (arguments beginning with \`-') are ignored. + +Every other argument is treated as a filename. Files ending in \`.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in \`.la', then a libtool library is created, +only library objects (\`.lo' files) may be specified, and \`-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created +using \`ar' and \`ranlib', or on Windows using \`lib'. + +If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file +is created, otherwise an executable program is created." + ;; + + uninstall) + $ECHO \ +"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + + *) + func_fatal_help "invalid operation mode \`$opt_mode'" + ;; + esac + + echo + $ECHO "Try \`$progname --help' for more information about other modes." +} + +# Now that we've collected a possible --mode arg, show help if necessary +if $opt_help; then + if test "$opt_help" = :; then + func_mode_help + else + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + func_mode_help + done + } | sed -n '1p; 2,$s/^Usage:/ or: /p' + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + echo + func_mode_help + done + } | + sed '1d + /^When reporting/,/^Report/{ + H + d + } + $x + /information about other modes/d + /more detailed .*MODE/d + s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' + fi + exit $? +fi + + +# func_mode_execute arg... +func_mode_execute () +{ + $opt_debug + # The first argument is the command name. + cmd="$nonopt" + test -z "$cmd" && \ + func_fatal_help "you must specify a COMMAND" + + # Handle -dlopen flags immediately. + for file in $opt_dlopen; do + test -f "$file" \ + || func_fatal_help "\`$file' is not a file" + + dir= + case $file in + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "\`$lib' is not a valid libtool archive" + + # Read the libtool library. + dlname= + library_names= + func_source "$file" + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && \ + func_warning "\`$file' was not linked with \`-export-dynamic'" + continue + fi + + func_dirname "$file" "" "." + dir="$func_dirname_result" + + if test -f "$dir/$objdir/$dlname"; then + func_append dir "/$objdir" + else + if test ! -f "$dir/$dlname"; then + func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" + fi + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + func_dirname "$file" "" "." + dir="$func_dirname_result" + ;; + + *) + func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir="$absdir" + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic="$magic" + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -* | *.la | *.lo ) ;; + *) + # Do a test to see if this is really a libtool program. + if func_ltwrapper_script_p "$file"; then + func_source "$file" + # Transform arg to wrapped name. + file="$progdir/$program" + elif func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + func_source "$func_ltwrapper_scriptname_result" + # Transform arg to wrapped name. + file="$progdir/$program" + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + func_append_quoted args "$file" + done + + if test "X$opt_dry_run" = Xfalse; then + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + do + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + else + $lt_unset $lt_var + fi" + done + + # Now prepare to actually exec the command. + exec_cmd="\$cmd$args" + else + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + echo "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS + fi +} + +test "$opt_mode" = execute && func_mode_execute ${1+"$@"} + + +# func_mode_finish arg... +func_mode_finish () +{ + $opt_debug + libs= + libdirs= + admincmds= + + for opt in "$nonopt" ${1+"$@"} + do + if test -d "$opt"; then + func_append libdirs " $opt" + + elif test -f "$opt"; then + if func_lalib_unsafe_p "$opt"; then + func_append libs " $opt" + else + func_warning "\`$opt' is not a valid libtool archive" + fi + + else + func_fatal_error "invalid argument \`$opt'" + fi + done + + if test -n "$libs"; then + if test -n "$lt_sysroot"; then + sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` + sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" + else + sysroot_cmd= + fi + + # Remove sysroot references + if $opt_dry_run; then + for lib in $libs; do + echo "removing references to $lt_sysroot and \`=' prefixes from $lib" + done + else + tmpdir=`func_mktempdir` + for lib in $libs; do + sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ + > $tmpdir/tmp-la + mv -f $tmpdir/tmp-la $lib + done + ${RM}r "$tmpdir" + fi + fi + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + func_execute_cmds "$finish_cmds" 'admincmds="$admincmds +'"$cmd"'"' + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $opt_dry_run || eval "$cmds" || func_append admincmds " + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + $opt_silent && exit $EXIT_SUCCESS + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + echo "----------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + $ECHO " $libdir" + done + echo + echo "If you ever happen to want to link against installed libraries" + echo "in a given directory, LIBDIR, you must either use libtool, and" + echo "specify the full pathname of the library, or use the \`-LLIBDIR'" + echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the \`$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the \`$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $ECHO " - use the \`$flag' linker flag" + fi + if test -n "$admincmds"; then + $ECHO " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + fi + echo + + echo "See any operating system documentation about shared libraries for" + case $host in + solaris2.[6789]|solaris2.1[0-9]) + echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" + echo "pages." + ;; + *) + echo "more information, such as the ld(1) and ld.so(8) manual pages." + ;; + esac + echo "----------------------------------------------------------------------" + fi + exit $EXIT_SUCCESS +} + +test "$opt_mode" = finish && func_mode_finish ${1+"$@"} + + +# func_mode_install arg... +func_mode_install () +{ + $opt_debug + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || + # Allow the use of GNU shtool's install command. + case $nonopt in *shtool*) :;; *) false;; esac; then + # Aesthetically quote it. + func_quote_for_eval "$nonopt" + install_prog="$func_quote_for_eval_result " + arg=$1 + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + func_quote_for_eval "$arg" + func_append install_prog "$func_quote_for_eval_result" + install_shared_prog=$install_prog + case " $install_prog " in + *[\\\ /]cp\ *) install_cp=: ;; + *) install_cp=false ;; + esac + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=no + stripme= + no_mode=: + for arg + do + arg2= + if test -n "$dest"; then + func_append files " $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=yes ;; + -f) + if $install_cp; then :; else + prev=$arg + fi + ;; + -g | -m | -o) + prev=$arg + ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + if test "x$prev" = x-m && test -n "$install_override_mode"; then + arg2=$install_override_mode + no_mode=false + fi + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + func_quote_for_eval "$arg" + func_append install_prog " $func_quote_for_eval_result" + if test -n "$arg2"; then + func_quote_for_eval "$arg2" + fi + func_append install_shared_prog " $func_quote_for_eval_result" + done + + test -z "$install_prog" && \ + func_fatal_help "you must specify an install program" + + test -n "$prev" && \ + func_fatal_help "the \`$prev' option requires an argument" + + if test -n "$install_override_mode" && $no_mode; then + if $install_cp; then :; else + func_quote_for_eval "$install_override_mode" + func_append install_shared_prog " -m $func_quote_for_eval_result" + fi + fi + + if test -z "$files"; then + if test -z "$dest"; then + func_fatal_help "no file or destination specified" + else + func_fatal_help "you must specify a destination" + fi + fi + + # Strip any trailing slash from the destination. + func_stripname '' '/' "$dest" + dest=$func_stripname_result + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=yes + if test "$isdir" = yes; then + destdir="$dest" + destname= + else + func_dirname_and_basename "$dest" "" "." + destdir="$func_dirname_result" + destname="$func_basename_result" + + # Not a directory, so check to see that there is only one file specified. + set dummy $files; shift + test "$#" -gt 1 && \ + func_fatal_help "\`$dest' is not a directory" + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + func_fatal_help "\`$destdir' must be an absolute directory name" + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + func_append staticlibs " $file" + ;; + + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "\`$file' is not a valid libtool archive" + + library_names= + old_library= + relink_command= + func_source "$file" + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) func_append current_libdirs " $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) func_append future_libdirs " $libdir" ;; + esac + fi + + func_dirname "$file" "/" "" + dir="$func_dirname_result" + func_append dir "$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + test "$inst_prefix_dir" = "$destdir" && \ + func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` + fi + + func_warning "relinking \`$file'" + func_show_eval "$relink_command" \ + 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' + fi + + # See the names of the shared library. + set dummy $library_names; shift + if test -n "$1"; then + realname="$1" + shift + + srcname="$realname" + test -n "$relink_command" && srcname="$realname"T + + # Install the shared library and build the symlinks. + func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ + 'exit $?' + tstripme="$stripme" + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + case $realname in + *.dll.a) + tstripme="" + ;; + esac + ;; + esac + if test -n "$tstripme" && test -n "$striplib"; then + func_show_eval "$striplib $destdir/$realname" 'exit $?' + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try `ln -sf' first, because the `ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + test "$linkname" != "$realname" \ + && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" + done + fi + + # Do each command in the postinstall commands. + lib="$destdir/$realname" + func_execute_cmds "$postinstall_cmds" 'exit $?' + fi + + # Install the pseudo-library for information purposes. + func_basename "$file" + name="$func_basename_result" + instname="$dir/$name"i + func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' + + # Maybe install the static library, too. + test -n "$old_library" && func_append staticlibs " $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + func_basename "$file" + destfile="$func_basename_result" + destfile="$destdir/$destfile" + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + func_lo2o "$destfile" + staticdest=$func_lo2o_result + ;; + *.$objext) + staticdest="$destfile" + destfile= + ;; + *) + func_fatal_help "cannot copy a libtool object to \`$destfile'" + ;; + esac + + # Install the libtool object if requested. + test -n "$destfile" && \ + func_show_eval "$install_prog $file $destfile" 'exit $?' + + # Install the old object if enabled. + if test "$build_old_libs" = yes; then + # Deduce the name of the old-style object file. + func_lo2o "$file" + staticobj=$func_lo2o_result + func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + func_basename "$file" + destfile="$func_basename_result" + destfile="$destdir/$destfile" + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext="" + case $file in + *.exe) + if test ! -f "$file"; then + func_stripname '' '.exe' "$file" + file=$func_stripname_result + stripped_ext=".exe" + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin* | *mingw*) + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + wrapper=$func_ltwrapper_scriptname_result + else + func_stripname '' '.exe' "$file" + wrapper=$func_stripname_result + fi + ;; + *) + wrapper=$file + ;; + esac + if func_ltwrapper_script_p "$wrapper"; then + notinst_deplibs= + relink_command= + + func_source "$wrapper" + + # Check the variables that should have been set. + test -z "$generated_by_libtool_version" && \ + func_fatal_error "invalid libtool wrapper script \`$wrapper'" + + finalize=yes + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + func_source "$lib" + fi + libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test + if test -n "$libdir" && test ! -f "$libfile"; then + func_warning "\`$lib' has not been installed in \`$libdir'" + finalize=no + fi + done + + relink_command= + func_source "$wrapper" + + outputname= + if test "$fast_install" = no && test -n "$relink_command"; then + $opt_dry_run || { + if test "$finalize" = yes; then + tmpdir=`func_mktempdir` + func_basename "$file$stripped_ext" + file="$func_basename_result" + outputname="$tmpdir/$file" + # Replace the output file specification. + relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` + + $opt_silent || { + func_quote_for_expand "$relink_command" + eval "func_echo $func_quote_for_expand_result" + } + if eval "$relink_command"; then : + else + func_error "error: relink \`$file' with the above command before installing it" + $opt_dry_run || ${RM}r "$tmpdir" + continue + fi + file="$outputname" + else + func_warning "cannot relink \`$file'" + fi + } + else + # Install the binary that we compiled earlier. + file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + func_stripname '' '.exe' "$destfile" + destfile=$func_stripname_result + ;; + esac + ;; + esac + func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' + $opt_dry_run || if test -n "$outputname"; then + ${RM}r "$tmpdir" + fi + ;; + esac + done + + for file in $staticlibs; do + func_basename "$file" + name="$func_basename_result" + + # Set up the ranlib parameters. + oldlib="$destdir/$name" + + func_show_eval "$install_prog \$file \$oldlib" 'exit $?' + + if test -n "$stripme" && test -n "$old_striplib"; then + func_show_eval "$old_striplib $oldlib" 'exit $?' + fi + + # Do each command in the postinstall commands. + func_execute_cmds "$old_postinstall_cmds" 'exit $?' + done + + test -n "$future_libdirs" && \ + func_warning "remember to run \`$progname --finish$future_libdirs'" + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + $opt_dry_run && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi +} + +test "$opt_mode" = install && func_mode_install ${1+"$@"} + + +# func_generate_dlsyms outputname originator pic_p +# Extract symbols from dlprefiles and create ${outputname}S.o with +# a dlpreopen symbol table. +func_generate_dlsyms () +{ + $opt_debug + my_outputname="$1" + my_originator="$2" + my_pic_p="${3-no}" + my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` + my_dlsyms= + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + my_dlsyms="${my_outputname}S.c" + else + func_error "not configured to extract global symbols from dlpreopened files" + fi + fi + + if test -n "$my_dlsyms"; then + case $my_dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist="$output_objdir/${my_outputname}.nm" + + func_show_eval "$RM $nlist ${nlist}S ${nlist}T" + + # Parse the name list into a source file. + func_verbose "creating $output_objdir/$my_dlsyms" + + $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ +/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +#if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) +#pragma GCC diagnostic ignored \"-Wstrict-prototypes\" +#endif + +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +/* DATA imports from DLLs on WIN32 con't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined(__osf__) +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +/* External symbol declarations for the compiler. */\ +" + + if test "$dlself" = yes; then + func_verbose "generating symbol list for \`$output'" + + $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` + for progfile in $progfiles; do + func_to_tool_file "$progfile" func_convert_file_msys_to_w32 + func_verbose "extracting global C symbols from \`$func_to_tool_file_result'" + $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $opt_dry_run || { + eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + if test -n "$export_symbols_regex"; then + $opt_dry_run || { + eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols="$output_objdir/$outputname.exp" + $opt_dry_run || { + $RM $export_symbols + eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + } + else + $opt_dry_run || { + eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + } + fi + fi + + for dlprefile in $dlprefiles; do + func_verbose "extracting global C symbols from \`$dlprefile'" + func_basename "$dlprefile" + name="$func_basename_result" + case $host in + *cygwin* | *mingw* | *cegcc* ) + # if an import library, we need to obtain dlname + if func_win32_import_lib_p "$dlprefile"; then + func_tr_sh "$dlprefile" + eval "curr_lafile=\$libfile_$func_tr_sh_result" + dlprefile_dlbasename="" + if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then + # Use subshell, to avoid clobbering current variable values + dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` + if test -n "$dlprefile_dlname" ; then + func_basename "$dlprefile_dlname" + dlprefile_dlbasename="$func_basename_result" + else + # no lafile. user explicitly requested -dlpreopen . + $sharedlib_from_linklib_cmd "$dlprefile" + dlprefile_dlbasename=$sharedlib_from_linklib_result + fi + fi + $opt_dry_run || { + if test -n "$dlprefile_dlbasename" ; then + eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' + else + func_warning "Could not compute DLL name from $name" + eval '$ECHO ": $name " >> "$nlist"' + fi + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | + $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" + } + else # not an import lib + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + fi + ;; + *) + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + ;; + esac + done + + $opt_dry_run || { + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $MV "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if $GREP -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + $GREP -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' + else + echo '/* NONE */' >> "$output_objdir/$my_dlsyms" + fi + + echo >> "$output_objdir/$my_dlsyms" "\ + +/* The mapping between symbol names and symbols. */ +typedef struct { + const char *name; + void *address; +} lt_dlsymlist; +extern LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[]; +LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[] = +{\ + { \"$my_originator\", (void *) 0 }," + + case $need_lib_prefix in + no) + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + *) + eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + esac + echo >> "$output_objdir/$my_dlsyms" "\ + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_${my_prefix}_LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + } # !$opt_dry_run + + pic_flag_for_symtable= + case "$compile_command " in + *" -static "*) ;; + *) + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; + *-*-hpux*) + pic_flag_for_symtable=" $pic_flag" ;; + *) + if test "X$my_pic_p" != Xno; then + pic_flag_for_symtable=" $pic_flag" + fi + ;; + esac + ;; + esac + symtab_cflags= + for arg in $LTCFLAGS; do + case $arg in + -pie | -fpie | -fPIE) ;; + *) func_append symtab_cflags " $arg" ;; + esac + done + + # Now compile the dynamic symbol file. + func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' + + # Clean up the generated files. + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' + + # Transform the symbol file into the correct name. + symfileobj="$output_objdir/${my_outputname}S.$objext" + case $host in + *cygwin* | *mingw* | *cegcc* ) + if test -f "$output_objdir/$my_outputname.def"; then + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + else + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + fi + ;; + *) + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + ;; + esac + ;; + *) + func_fatal_error "unknown suffix for \`$my_dlsyms'" + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` + fi +} + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +# Despite the name, also deal with 64 bit binaries. +func_win32_libid () +{ + $opt_debug + win32_libid_type="unknown" + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | + $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then + func_to_tool_file "$1" func_convert_file_msys_to_w32 + win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | + $SED -n -e ' + 1,100{ + / I /{ + s,.*,import, + p + q + } + }'` + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $ECHO "$win32_libid_type" +} + +# func_cygming_dll_for_implib ARG +# +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib () +{ + $opt_debug + sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` +} + +# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs +# +# The is the core of a fallback implementation of a +# platform-specific function to extract the name of the +# DLL associated with the specified import library LIBNAME. +# +# SECTION_NAME is either .idata$6 or .idata$7, depending +# on the platform and compiler that created the implib. +# +# Echos the name of the DLL associated with the +# specified import library. +func_cygming_dll_for_implib_fallback_core () +{ + $opt_debug + match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` + $OBJDUMP -s --section "$1" "$2" 2>/dev/null | + $SED '/^Contents of section '"$match_literal"':/{ + # Place marker at beginning of archive member dllname section + s/.*/====MARK====/ + p + d + } + # These lines can sometimes be longer than 43 characters, but + # are always uninteresting + /:[ ]*file format pe[i]\{,1\}-/d + /^In archive [^:]*:/d + # Ensure marker is printed + /^====MARK====/p + # Remove all lines with less than 43 characters + /^.\{43\}/!d + # From remaining lines, remove first 43 characters + s/^.\{43\}//' | + $SED -n ' + # Join marker and all lines until next marker into a single line + /^====MARK====/ b para + H + $ b para + b + :para + x + s/\n//g + # Remove the marker + s/^====MARK====// + # Remove trailing dots and whitespace + s/[\. \t]*$// + # Print + /./p' | + # we now have a list, one entry per line, of the stringified + # contents of the appropriate section of all members of the + # archive which possess that section. Heuristic: eliminate + # all those which have a first or second character that is + # a '.' (that is, objdump's representation of an unprintable + # character.) This should work for all archives with less than + # 0x302f exports -- but will fail for DLLs whose name actually + # begins with a literal '.' or a single character followed by + # a '.'. + # + # Of those that remain, print the first one. + $SED -e '/^\./d;/^.\./d;q' +} + +# func_cygming_gnu_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is a GNU/binutils-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_gnu_implib_p () +{ + $opt_debug + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` + test -n "$func_cygming_gnu_implib_tmp" +} + +# func_cygming_ms_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is an MS-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_ms_implib_p () +{ + $opt_debug + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` + test -n "$func_cygming_ms_implib_tmp" +} + +# func_cygming_dll_for_implib_fallback ARG +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# +# This fallback implementation is for use when $DLLTOOL +# does not support the --identify-strict option. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib_fallback () +{ + $opt_debug + if func_cygming_gnu_implib_p "$1" ; then + # binutils import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` + elif func_cygming_ms_implib_p "$1" ; then + # ms-generated import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` + else + # unknown + sharedlib_from_linklib_result="" + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + $opt_debug + f_ex_an_ar_dir="$1"; shift + f_ex_an_ar_oldlib="$1" + if test "$lock_old_archive_extraction" = yes; then + lockfile=$f_ex_an_ar_oldlib.lock + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + fi + func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ + 'stat=$?; rm -f "$lockfile"; exit $stat' + if test "$lock_old_archive_extraction" = yes; then + $opt_dry_run || rm -f "$lockfile" + fi + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" + fi +} + + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + $opt_debug + my_gentop="$1"; shift + my_oldlibs=${1+"$@"} + my_oldobjs="" + my_xlib="" + my_xabs="" + my_xdir="" + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + func_basename "$my_xlib" + my_xlib="$func_basename_result" + my_xlib_u=$my_xlib + while :; do + case " $extracted_archives " in + *" $my_xlib_u "*) + func_arith $extracted_serial + 1 + extracted_serial=$func_arith_result + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac + done + extracted_archives="$extracted_archives $my_xlib_u" + my_xdir="$my_gentop/$my_xlib_u" + + func_mkdir_p "$my_xdir" + + case $host in + *-darwin*) + func_verbose "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + $opt_dry_run || { + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + darwin_base_archive=`basename "$darwin_archive"` + darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` + if test -n "$darwin_arches"; then + darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches ; do + func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" + $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" + cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" + func_extract_an_archive "`pwd`" "${darwin_base_archive}" + cd "$darwin_curdir" + $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" + done # $darwin_arches + ## Okay now we've a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` + $LIPO -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + $RM -rf unfat-$$ + cd "$darwin_orig_dir" + else + cd $darwin_orig_dir + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + } # !$opt_dry_run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` + done + + func_extract_archives_result="$my_oldobjs" +} + + +# func_emit_wrapper [arg=no] +# +# Emit a libtool wrapper script on stdout. +# Don't directly open a file because we may want to +# incorporate the script contents within a cygwin/mingw +# wrapper executable. Must ONLY be called from within +# func_mode_link because it depends on a number of variables +# set therein. +# +# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR +# variable will take. If 'yes', then the emitted script +# will assume that the directory in which it is stored is +# the $objdir directory. This is a cygwin/mingw-specific +# behavior. +func_emit_wrapper () +{ + func_emit_wrapper_arg1=${1-no} + + $ECHO "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='$sed_quote_subst' + +# Be Bourne compatible +if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + generated_by_libtool_version='$macro_version' + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$ECHO are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + file=\"\$0\"" + + qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` + $ECHO "\ + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + ECHO=\"$qECHO\" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ which is used only on +# windows platforms, and (c) all begin with the string "--lt-" +# (application programs are unlikely to have options which match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's $0 value, followed by "$@". +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=\$0 + shift + for lt_opt + do + case \"\$lt_opt\" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` + test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. + lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` + cat \"\$lt_dump_D/\$lt_dump_F\" + exit 0 + ;; + --lt-*) + \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n \"\$lt_option_debug\"; then + echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\" + lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2* | *-cegcc*) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $ECHO "\ + \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from \$@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + for lt_wr_arg + do + case \$lt_wr_arg in + --lt-*) ;; + *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; + esac + shift + done + func_exec_program_core \${1+\"\$@\"} +} + + # Parse options + func_parse_lt_options \"\$0\" \${1+\"\$@\"} + + # Find the directory that this script lives in. + thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 + if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then + # special case for '.' + if test \"\$thisdir\" = \".\"; then + thisdir=\`pwd\` + fi + # remove .libs from thisdir + case \"\$thisdir\" in + *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; + $objdir ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test "$fast_install" = yes; then + $ECHO "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $MKDIR \"\$progdir\" + else + $RM \"\$progdir/\$file\" + fi" + + $ECHO "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + $ECHO \"\$relink_command_output\" >&2 + $RM \"\$progdir/\$file\" + exit 1 + fi + fi + + $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $RM \"\$progdir/\$program\"; + $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $RM \"\$progdir/\$file\" + fi" + else + $ECHO "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $ECHO "\ + + if test -f \"\$progdir/\$program\"; then" + + # fixup the dll searchpath if we need to. + # + # Fix the DLL searchpath if we need to. Do this before prepending + # to shlibpath, because on Windows, both are PATH and uninstalled + # libraries must come first. + if test -n "$dllsearchpath"; then + $ECHO "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + # Export our shlibpath_var if we have one. + if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $ECHO "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` + + export $shlibpath_var +" + fi + + $ECHO "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. + func_exec_program \${1+\"\$@\"} + fi + else + # The program doesn't exist. + \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 + \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" +} + + +# func_emit_cwrapperexe_src +# emit the source code for a wrapper executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_cwrapperexe_src () +{ + cat < +#include +#ifdef _MSC_VER +# include +# include +# include +#else +# include +# include +# ifdef __CYGWIN__ +# include +# endif +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +/* declarations of non-ANSI functions */ +#if defined(__MINGW32__) +# ifdef __STRICT_ANSI__ +int _putenv (const char *); +# endif +#elif defined(__CYGWIN__) +# ifdef __STRICT_ANSI__ +char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); +# endif +/* #elif defined (other platforms) ... */ +#endif + +/* portability defines, excluding path handling macros */ +#if defined(_MSC_VER) +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +# define S_IXUSR _S_IEXEC +# ifndef _INTPTR_T_DEFINED +# define _INTPTR_T_DEFINED +# define intptr_t int +# endif +#elif defined(__MINGW32__) +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +#elif defined(__CYGWIN__) +# define HAVE_SETENV +# define FOPEN_WB "wb" +/* #elif defined (other platforms) ... */ +#endif + +#if defined(PATH_MAX) +# define LT_PATHMAX PATH_MAX +#elif defined(MAXPATHLEN) +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef S_IXOTH +# define S_IXOTH 0 +#endif +#ifndef S_IXGRP +# define S_IXGRP 0 +#endif + +/* path handling portability macros */ +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ + defined (__OS2__) +# define HAVE_DOS_BASED_FILE_SYSTEM +# define FOPEN_WB "wb" +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#ifndef FOPEN_WB +# define FOPEN_WB "w" +#endif +#ifndef _O_BINARY +# define _O_BINARY 0 +#endif + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free ((void *) stale); stale = 0; } \ +} while (0) + +#if defined(LT_DEBUGWRAPPER) +static int lt_debug = 1; +#else +static int lt_debug = 0; +#endif + +const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ + +void *xmalloc (size_t num); +char *xstrdup (const char *string); +const char *base_name (const char *name); +char *find_executable (const char *wrapper); +char *chase_symlinks (const char *pathspec); +int make_executable (const char *path); +int check_executable (const char *path); +char *strendzap (char *str, const char *pat); +void lt_debugprintf (const char *file, int line, const char *fmt, ...); +void lt_fatal (const char *file, int line, const char *message, ...); +static const char *nonnull (const char *s); +static const char *nonempty (const char *s); +void lt_setenv (const char *name, const char *value); +char *lt_extend_str (const char *orig_value, const char *add, int to_end); +void lt_update_exe_path (const char *name, const char *value); +void lt_update_lib_path (const char *name, const char *value); +char **prepare_spawn (char **argv); +void lt_dump_script (FILE *f); +EOF + + cat <= 0) + && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) + return 1; + else + return 0; +} + +int +make_executable (const char *path) +{ + int rval = 0; + struct stat st; + + lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", + nonempty (path)); + if ((!path) || (!*path)) + return 0; + + if (stat (path, &st) >= 0) + { + rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); + } + return rval; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise + Does not chase symlinks, even on platforms that support them. +*/ +char * +find_executable (const char *wrapper) +{ + int has_slash = 0; + const char *p; + const char *p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + int tmp_len; + char *concat_name; + + lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", + nonempty (wrapper)); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char *path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char *q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR (*q)) + break; + p_len = q - p; + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = + XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = + XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + return NULL; +} + +char * +chase_symlinks (const char *pathspec) +{ +#ifndef S_ISLNK + return xstrdup (pathspec); +#else + char buf[LT_PATHMAX]; + struct stat s; + char *tmp_pathspec = xstrdup (pathspec); + char *p; + int has_symlinks = 0; + while (strlen (tmp_pathspec) && !has_symlinks) + { + lt_debugprintf (__FILE__, __LINE__, + "checking path component for symlinks: %s\n", + tmp_pathspec); + if (lstat (tmp_pathspec, &s) == 0) + { + if (S_ISLNK (s.st_mode) != 0) + { + has_symlinks = 1; + break; + } + + /* search backwards for last DIR_SEPARATOR */ + p = tmp_pathspec + strlen (tmp_pathspec) - 1; + while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + p--; + if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + { + /* no more DIR_SEPARATORS left */ + break; + } + *p = '\0'; + } + else + { + lt_fatal (__FILE__, __LINE__, + "error accessing file \"%s\": %s", + tmp_pathspec, nonnull (strerror (errno))); + } + } + XFREE (tmp_pathspec); + + if (!has_symlinks) + { + return xstrdup (pathspec); + } + + tmp_pathspec = realpath (pathspec, buf); + if (tmp_pathspec == 0) + { + lt_fatal (__FILE__, __LINE__, + "could not follow symlinks for %s", pathspec); + } + return xstrdup (tmp_pathspec); +#endif +} + +char * +strendzap (char *str, const char *pat) +{ + size_t len, patlen; + + assert (str != NULL); + assert (pat != NULL); + + len = strlen (str); + patlen = strlen (pat); + + if (patlen <= len) + { + str += len - patlen; + if (strcmp (str, pat) == 0) + *str = '\0'; + } + return str; +} + +void +lt_debugprintf (const char *file, int line, const char *fmt, ...) +{ + va_list args; + if (lt_debug) + { + (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); + va_start (args, fmt); + (void) vfprintf (stderr, fmt, args); + va_end (args); + } +} + +static void +lt_error_core (int exit_status, const char *file, + int line, const char *mode, + const char *message, va_list ap) +{ + fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *file, int line, const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); + va_end (ap); +} + +static const char * +nonnull (const char *s) +{ + return s ? s : "(null)"; +} + +static const char * +nonempty (const char *s) +{ + return (s && !*s) ? "(empty)" : nonnull (s); +} + +void +lt_setenv (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_setenv) setting '%s' to '%s'\n", + nonnull (name), nonnull (value)); + { +#ifdef HAVE_SETENV + /* always make a copy, for consistency with !HAVE_SETENV */ + char *str = xstrdup (value); + setenv (name, str, 1); +#else + int len = strlen (name) + 1 + strlen (value) + 1; + char *str = XMALLOC (char, len); + sprintf (str, "%s=%s", name, value); + if (putenv (str) != EXIT_SUCCESS) + { + XFREE (str); + } +#endif + } +} + +char * +lt_extend_str (const char *orig_value, const char *add, int to_end) +{ + char *new_value; + if (orig_value && *orig_value) + { + int orig_value_len = strlen (orig_value); + int add_len = strlen (add); + new_value = XMALLOC (char, add_len + orig_value_len + 1); + if (to_end) + { + strcpy (new_value, orig_value); + strcpy (new_value + orig_value_len, add); + } + else + { + strcpy (new_value, add); + strcpy (new_value + add_len, orig_value); + } + } + else + { + new_value = xstrdup (add); + } + return new_value; +} + +void +lt_update_exe_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + /* some systems can't cope with a ':'-terminated path #' */ + int len = strlen (new_value); + while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) + { + new_value[len-1] = '\0'; + } + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +void +lt_update_lib_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +EOF + case $host_os in + mingw*) + cat <<"EOF" + +/* Prepares an argument vector before calling spawn(). + Note that spawn() does not by itself call the command interpreter + (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : + ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&v); + v.dwPlatformId == VER_PLATFORM_WIN32_NT; + }) ? "cmd.exe" : "command.com"). + Instead it simply concatenates the arguments, separated by ' ', and calls + CreateProcess(). We must quote the arguments since Win32 CreateProcess() + interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a + special way: + - Space and tab are interpreted as delimiters. They are not treated as + delimiters if they are surrounded by double quotes: "...". + - Unescaped double quotes are removed from the input. Their only effect is + that within double quotes, space and tab are treated like normal + characters. + - Backslashes not followed by double quotes are not special. + - But 2*n+1 backslashes followed by a double quote become + n backslashes followed by a double quote (n >= 0): + \" -> " + \\\" -> \" + \\\\\" -> \\" + */ +#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +char ** +prepare_spawn (char **argv) +{ + size_t argc; + char **new_argv; + size_t i; + + /* Count number of arguments. */ + for (argc = 0; argv[argc] != NULL; argc++) + ; + + /* Allocate new argument vector. */ + new_argv = XMALLOC (char *, argc + 1); + + /* Put quoted arguments into the new argument vector. */ + for (i = 0; i < argc; i++) + { + const char *string = argv[i]; + + if (string[0] == '\0') + new_argv[i] = xstrdup ("\"\""); + else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) + { + int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); + size_t length; + unsigned int backslashes; + const char *s; + char *quoted_string; + char *p; + + length = 0; + backslashes = 0; + if (quote_around) + length++; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + length += backslashes + 1; + length++; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + length += backslashes + 1; + + quoted_string = XMALLOC (char, length + 1); + + p = quoted_string; + backslashes = 0; + if (quote_around) + *p++ = '"'; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + { + unsigned int j; + for (j = backslashes + 1; j > 0; j--) + *p++ = '\\'; + } + *p++ = c; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + { + unsigned int j; + for (j = backslashes; j > 0; j--) + *p++ = '\\'; + *p++ = '"'; + } + *p = '\0'; + + new_argv[i] = quoted_string; + } + else + new_argv[i] = (char *) string; + } + new_argv[argc] = NULL; + + return new_argv; +} +EOF + ;; + esac + + cat <<"EOF" +void lt_dump_script (FILE* f) +{ +EOF + func_emit_wrapper yes | + $SED -e 's/\([\\"]\)/\\\1/g' \ + -e 's/^/ fputs ("/' -e 's/$/\\n", f);/' + + cat <<"EOF" +} +EOF +} +# end: func_emit_cwrapperexe_src + +# func_win32_import_lib_p ARG +# True if ARG is an import lib, as indicated by $file_magic_cmd +func_win32_import_lib_p () +{ + $opt_debug + case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in + *import*) : ;; + *) false ;; + esac +} + +# func_mode_link arg... +func_mode_link () +{ + $opt_debug + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # which system we are compiling for in order to pass an extra + # flag for every libtool invocation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll which has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args=$nonopt + base_compile="$nonopt $@" + compile_command=$nonopt + finalize_command=$nonopt + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + new_inherited_linker_flags= + + avoid_version=no + bindir= + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + non_pic_objects= + precious_files_regex= + prefer_static_libs=no + preload=no + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + vinfo_number=no + weak_libs= + single_module="${wl}-single_module" + func_infer_tag $base_compile + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -shared) + test "$build_libtool_libs" != yes && \ + func_fatal_configuration "can not build a shared library" + build_old_libs=no + break + ;; + -all-static | -static | -static-libtool-libs) + case $arg in + -all-static) + if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then + func_warning "complete static linking is impossible in this configuration" + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + -static) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + ;; + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg="$1" + shift + func_quote_for_eval "$arg" + qarg=$func_quote_for_eval_unquoted_result + func_append libtool_args " $func_quote_for_eval_result" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + func_append compile_command " @OUTPUT@" + func_append finalize_command " @OUTPUT@" + ;; + esac + + case $prev in + bindir) + bindir="$arg" + prev= + continue + ;; + dlfiles|dlprefiles) + if test "$preload" = no; then + # Add the symbol object into the linking commands. + func_append compile_command " @SYMFILE@" + func_append finalize_command " @SYMFILE@" + preload=yes + fi + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test "$dlself" = no; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test "$prev" = dlprefiles; then + dlself=yes + elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test "$prev" = dlfiles; then + func_append dlfiles " $arg" + else + func_append dlprefiles " $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols="$arg" + test -f "$arg" \ + || func_fatal_error "symbol file \`$arg' does not exist" + prev= + continue + ;; + expsyms_regex) + export_symbols_regex="$arg" + prev= + continue + ;; + framework) + case $host in + *-*-darwin*) + case "$deplibs " in + *" $qarg.ltframework "*) ;; + *) func_append deplibs " $qarg.ltframework" # this is fixed later + ;; + esac + ;; + esac + prev= + continue + ;; + inst_prefix) + inst_prefix_dir="$arg" + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat "$save_arg"` + do +# func_append moreargs " $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test "$pic_object" = none && + test "$non_pic_object" = none; then + func_fatal_error "cannot find name of object for \`$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "\`$arg' is not a valid libtool object" + fi + fi + done + else + func_fatal_error "link input file \`$arg' does not exist" + fi + arg=$save_arg + prev= + continue + ;; + precious_regex) + precious_files_regex="$arg" + prev= + continue + ;; + release) + release="-$arg" + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + if test "$prev" = rpath; then + case "$rpath " in + *" $arg "*) ;; + *) func_append rpath " $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) func_append xrpath " $arg" ;; + esac + fi + prev= + continue + ;; + shrext) + shrext_cmds="$arg" + prev= + continue + ;; + weak) + func_append weak_libs " $arg" + prev= + continue + ;; + xcclinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xcompiler) + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xlinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $wl$qarg" + prev= + func_append compile_command " $wl$qarg" + func_append finalize_command " $wl$qarg" + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg="$arg" + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + # See comment for -static flag below, for more details. + func_append compile_command " $link_static_flag" + func_append finalize_command " $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + func_fatal_error "\`-allow-undefined' must not be used because it is the default" + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -bindir) + prev=bindir + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + func_fatal_error "more than one -exported-symbols argument is not allowed" + fi + if test "X$arg" = "X-export-symbols"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework) + prev=framework + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + func_append compile_command " $arg" + func_append finalize_command " $arg" + ;; + esac + continue + ;; + + -L*) + func_stripname "-L" '' "$arg" + if test -z "$func_stripname_result"; then + if test "$#" -gt 0; then + func_fatal_error "require no space between \`-L' and \`$1'" + else + func_fatal_error "need path for \`-L' option" + fi + fi + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + test -z "$absdir" && \ + func_fatal_error "cannot determine absolute directory name of \`$dir'" + dir="$absdir" + ;; + esac + case "$deplibs " in + *" -L$dir "* | *" $arg "*) + # Will only happen for absolute or sysroot arguments + ;; + *) + # Preserve sysroot, but never include relative directories + case $dir in + [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; + *) func_append deplibs " -L$dir" ;; + esac + func_append lib_search_path " $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + ::) dllsearchpath=$dir;; + *) func_append dllsearchpath ":$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test "X$arg" = "X-lc" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + test "X$arg" = "X-lc" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + func_append deplibs " System.ltframework" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test "X$arg" = "X-lc" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test "X$arg" = "X-lc" && continue + ;; + esac + elif test "X$arg" = "X-lc_r"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + func_append deplibs " $arg" + continue + ;; + + -module) + module=yes + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + # Darwin uses the -arch flag to determine output architecture. + -model|-arch|-isysroot|--sysroot) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case "$new_inherited_linker_flags " in + *" $arg "*) ;; + * ) func_append new_inherited_linker_flags " $arg" ;; + esac + continue + ;; + + -multi_module) + single_module="${wl}-multi_module" + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) + # The PATH hackery in wrapper scripts is required on Windows + # and Darwin in order for the loader to find any dlls it needs. + func_warning "\`-no-install' is ignored for $host" + func_warning "assuming \`-no-fast-install' instead" + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + func_stripname '-R' '' "$arg" + dir=$func_stripname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + =*) + func_stripname '=' '' "$dir" + dir=$lt_sysroot$func_stripname_result + ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + continue + ;; + + -shared) + # The effects of -shared are defined in a previous loop. + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -static | -static-libtool-libs) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -weak) + prev=weak + continue + ;; + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + func_quote_for_eval "$flag" + func_append arg " $func_quote_for_eval_result" + func_append compiler_flags " $func_quote_for_eval_result" + done + IFS="$save_ifs" + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Wl,*) + func_stripname '-Wl,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + func_quote_for_eval "$flag" + func_append arg " $wl$func_quote_for_eval_result" + func_append compiler_flags " $wl$func_quote_for_eval_result" + func_append linker_flags " $func_quote_for_eval_result" + done + IFS="$save_ifs" + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # -msg_* for osf cc + -msg_*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + + # Flags to be passed through unchanged, with rationale: + # -64, -mips[0-9] enable 64-bit mode for the SGI compiler + # -r[0-9][0-9]* specify processor for the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler + # +DA*, +DD* enable 64-bit mode for the HP compiler + # -q* compiler args for the IBM compiler + # -m*, -t[45]*, -txscale* architecture-specific flags for GCC + # -F/path path to uninstalled frameworks, gcc on darwin + # -p, -pg, --coverage, -fprofile-* profiling flags for GCC + # @file GCC response files + # -tp=* Portland pgcc target processor selection + # --sysroot=* for sysroot support + # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ + -O*|-flto*|-fwhopr*|-fuse-linker-plugin) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + func_append compile_command " $arg" + func_append finalize_command " $arg" + func_append compiler_flags " $arg" + continue + ;; + + # Some other compiler flag. + -* | +*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + + *.$objext) + # A standard object. + func_append objs " $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test "$pic_object" = none && + test "$non_pic_object" = none; then + func_fatal_error "cannot find name of object for \`$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "\`$arg' is not a valid libtool object" + fi + fi + ;; + + *.$libext) + # An archive. + func_append deplibs " $arg" + func_append old_deplibs " $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + func_resolve_sysroot "$arg" + if test "$prev" = dlfiles; then + # This library was specified with -dlopen. + func_append dlfiles " $func_resolve_sysroot_result" + prev= + elif test "$prev" = dlprefiles; then + # The library was specified with -dlpreopen. + func_append dlprefiles " $func_resolve_sysroot_result" + prev= + else + func_append deplibs " $func_resolve_sysroot_result" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + done # argument parsing loop + + test -n "$prev" && \ + func_fatal_help "the \`$prevarg' option requires an argument" + + if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + func_basename "$output" + outputname="$func_basename_result" + libobjs_save="$libobjs" + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + func_dirname "$output" "/" "" + output_objdir="$func_dirname_result$objdir" + func_to_tool_file "$output_objdir/" + tool_output_objdir=$func_to_tool_file_result + # Create the object directory. + func_mkdir_p "$output_objdir" + + # Determine the type of output + case $output in + "") + func_fatal_help "you must specify an output file" + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if $opt_preserve_dup_deps ; then + case "$libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append libs " $deplib" + done + + if test "$linkmode" = lib; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if $opt_duplicate_compiler_generated_deps; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; + esac + func_append pre_post_deps " $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + + case $linkmode in + lib) + passes="conv dlpreopen link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=no + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + + for pass in $passes; do + # The preopen pass in lib mode reverses $deplibs; put it back here + # so that -L comes before libs that need it for instance... + if test "$linkmode,$pass" = "lib,link"; then + ## FIXME: Find the place where the list is rebuilt in the wrong + ## order, and fix it there properly + tmp_deplibs= + for deplib in $deplibs; do + tmp_deplibs="$deplib $tmp_deplibs" + done + deplibs="$tmp_deplibs" + fi + + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan"; then + libs="$deplibs" + deplibs= + fi + if test "$linkmode" = prog; then + case $pass in + dlopen) libs="$dlfiles" ;; + dlpreopen) libs="$dlprefiles" ;; + link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; + esac + fi + if test "$linkmode,$pass" = "lib,dlpreopen"; then + # Collect and forward deplibs of preopened libtool libs + for lib in $dlprefiles; do + # Ignore non-libtool-libs + dependency_libs= + func_resolve_sysroot "$lib" + case $lib in + *.la) func_source "$func_resolve_sysroot_result" ;; + esac + + # Collect preopened libtool deplibs, except any this library + # has declared as weak libs + for deplib in $dependency_libs; do + func_basename "$deplib" + deplib_base=$func_basename_result + case " $weak_libs " in + *" $deplib_base "*) ;; + *) func_append deplibs " $deplib" ;; + esac + done + done + libs="$dlprefiles" + fi + if test "$pass" = dlopen; then + # Collect dlpreopened libraries + save_deplibs="$deplibs" + deplibs= + fi + + for deplib in $libs; do + lib= + found=no + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append compiler_flags " $deplib" + if test "$linkmode" = lib ; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -l*) + if test "$linkmode" != lib && test "$linkmode" != prog; then + func_warning "\`-l' is ignored for archives/objects" + continue + fi + func_stripname '-l' '' "$deplib" + name=$func_stripname_result + if test "$linkmode" = lib; then + searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" + else + searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" + fi + for searchdir in $searchdirs; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib="$searchdir/lib${name}${search_ext}" + if test -f "$lib"; then + if test "$search_ext" = ".la"; then + found=yes + else + found=no + fi + break 2 + fi + done + done + if test "$found" != yes; then + # deplib doesn't seem to be a libtool library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + else # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $deplib "*) + if func_lalib_p "$lib"; then + library_names= + old_library= + func_source "$lib" + for l in $old_library $library_names; do + ll="$l" + done + if test "X$ll" = "X$old_library" ; then # only static version available + found=no + func_dirname "$lib" "" "." + ladir="$func_dirname_result" + lib=$ladir/$old_library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + fi + ;; # -l + *.ltframework) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + if test "$linkmode" = lib ; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test "$pass" = conv && continue + newdependency_libs="$deplib $newdependency_libs" + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + prog) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + if test "$pass" = scan; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + *) + func_warning "\`-L' is ignored for archives/objects" + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test "$pass" = link; then + func_stripname '-R' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) + func_resolve_sysroot "$deplib" + lib=$func_resolve_sysroot_result + ;; + *.$libext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + # Linking convenience modules into shared libraries is allowed, + # but linking other static libraries is non-portable. + case " $dlpreconveniencelibs " in + *" $deplib "*) ;; + *) + valid_a_lib=no + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=yes + fi + ;; + pass_all) + valid_a_lib=yes + ;; + esac + if test "$valid_a_lib" != yes; then + echo + $ECHO "*** Warning: Trying to link with static lib archive $deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because the file extensions .$libext of this argument makes me believe" + echo "*** that it is just a static archive that I should not use here." + else + echo + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + fi + ;; + esac + continue + ;; + prog) + if test "$pass" != link; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + elif test "$linkmode" = prog; then + if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + func_append newdlprefiles " $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append newdlfiles " $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=yes + continue + ;; + esac # case $deplib + + if test "$found" = yes || test -f "$lib"; then : + else + func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" + fi + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$lib" \ + || func_fatal_error "\`$lib' is not a valid libtool archive" + + func_dirname "$lib" "" "." + ladir="$func_dirname_result" + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + inherited_linker_flags= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + func_source "$lib" + + # Convert "-framework foo" to "foo.ltframework" + if test -n "$inherited_linker_flags"; then + tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` + for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do + case " $new_inherited_linker_flags " in + *" $tmp_inherited_linker_flag "*) ;; + *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; + esac + done + fi + dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan" || + { test "$linkmode" != prog && test "$linkmode" != lib; }; then + test -n "$dlopen" && func_append dlfiles " $dlopen" + test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" + fi + + if test "$pass" = conv; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + func_fatal_error "cannot find name of link library for \`$lib'" + fi + # It is a libtool convenience library, so add in its objects. + func_append convenience " $ladir/$objdir/$old_library" + func_append old_convenience " $ladir/$objdir/$old_library" + elif test "$linkmode" != prog && test "$linkmode" != lib; then + func_fatal_error "\`$lib' is not a convenience library" + fi + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_preserve_dup_deps ; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + if test -n "$old_library" && + { test "$prefer_static_libs" = yes || + test "$prefer_static_libs,$installed" = "built,no"; }; then + linklib=$old_library + else + for l in $old_library $library_names; do + linklib="$l" + done + fi + if test -z "$linklib"; then + func_fatal_error "cannot find name of link library for \`$lib'" + fi + + # This library was specified with -dlopen. + if test "$pass" = dlopen; then + if test -z "$libdir"; then + func_fatal_error "cannot -dlopen a convenience library: \`$lib'" + fi + if test -z "$dlname" || + test "$dlopen_support" != yes || + test "$build_libtool_libs" = no; then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + func_append dlprefiles " $lib $dependency_libs" + else + func_append newdlfiles " $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + func_warning "cannot determine absolute directory name of \`$ladir'" + func_warning "passing it literally to the linker, although it might fail" + abs_ladir="$ladir" + fi + ;; + esac + func_basename "$lib" + laname="$func_basename_result" + + # Find the relevant object directory and library name. + if test "X$installed" = Xyes; then + if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + func_warning "library \`$lib' was moved." + dir="$ladir" + absdir="$abs_ladir" + libdir="$abs_ladir" + else + dir="$lt_sysroot$libdir" + absdir="$lt_sysroot$libdir" + fi + test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir="$ladir" + absdir="$abs_ladir" + # Remove this search path later + func_append notinst_path " $abs_ladir" + else + dir="$ladir/$objdir" + absdir="$abs_ladir/$objdir" + # Remove this search path later + func_append notinst_path " $abs_ladir" + fi + fi # $installed = yes + func_stripname 'lib' '.la' "$laname" + name=$func_stripname_result + + # This library was specified with -dlpreopen. + if test "$pass" = dlpreopen; then + if test -z "$libdir" && test "$linkmode" = prog; then + func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" + fi + case "$host" in + # special handling for platforms with PE-DLLs. + *cygwin* | *mingw* | *cegcc* ) + # Linker will automatically link against shared library if both + # static and shared are present. Therefore, ensure we extract + # symbols from the import library if a shared library is present + # (otherwise, the dlopen module name will be incorrect). We do + # this by putting the import library name into $newdlprefiles. + # We recover the dlopen module name by 'saving' the la file + # name in a special purpose variable, and (later) extracting the + # dlname from the la file. + if test -n "$dlname"; then + func_tr_sh "$dir/$linklib" + eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" + func_append newdlprefiles " $dir/$linklib" + else + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + fi + ;; + * ) + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + func_append newdlprefiles " $dir/$dlname" + else + func_append newdlprefiles " $dir/$linklib" + fi + ;; + esac + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test "$linkmode" = lib; then + deplibs="$dir/$old_library $deplibs" + elif test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test "$linkmode" = prog && test "$pass" != link; then + func_append newlib_search_path " $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=no + if test "$link_all_deplibs" != no || test -z "$library_names" || + test "$build_libtool_libs" = no; then + linkalldeplibs=yes + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + esac + # Need to link against all dependency_libs? + if test "$linkalldeplibs" = yes; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if $opt_preserve_dup_deps ; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test "$linkmode,$pass" = "prog,link"; then + if test -n "$library_names" && + { { test "$prefer_static_libs" = no || + test "$prefer_static_libs,$installed" = "built,yes"; } || + test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then + # Make sure the rpath contains only unique directories. + case "$temp_rpath:" in + *"$absdir:"*) ;; + *) func_append temp_rpath "$absdir:" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if test "$alldeplibs" = yes && + { test "$deplibs_check_method" = pass_all || + { test "$build_libtool_libs" = yes && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test "$use_static_libs" = built && test "$installed" = yes; then + use_static_libs=no + fi + if test -n "$library_names" && + { test "$use_static_libs" = no || test -z "$old_library"; }; then + case $host in + *cygwin* | *mingw* | *cegcc*) + # No point in relinking DLLs because paths are not encoded + func_append notinst_deplibs " $lib" + need_relink=no + ;; + *) + if test "$installed" = no; then + func_append notinst_deplibs " $lib" + need_relink=yes + fi + ;; + esac + # This is a shared library + + # Warn about portability, can't link against -module's on some + # systems (darwin). Don't bleat about dlopened modules though! + dlopenmodule="" + for dlpremoduletest in $dlprefiles; do + if test "X$dlpremoduletest" = "X$lib"; then + dlopenmodule="$dlpremoduletest" + break + fi + done + if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then + echo + if test "$linkmode" = prog; then + $ECHO "*** Warning: Linking the executable $output against the loadable module" + else + $ECHO "*** Warning: Linking the shared library $output against the loadable module" + fi + $ECHO "*** $linklib is not portable!" + fi + if test "$linkmode" = lib && + test "$hardcode_into_libs" = yes; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + shift + realname="$1" + shift + libname=`eval "\\$ECHO \"$libname_spec\""` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname="$dlname" + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw* | *cegcc*) + func_arith $current - $age + major=$func_arith_result + versuffix="-$major" + ;; + esac + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot="$soname" + func_basename "$soroot" + soname="$func_basename_result" + func_stripname 'lib' '.dll' "$soname" + newlib=libimp-$func_stripname_result.a + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + func_verbose "extracting exported symbol list from \`$soname'" + func_execute_cmds "$extract_expsyms_cmds" 'exit $?' + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + func_verbose "generating import library for \`$soname'" + func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test "$linkmode" = prog || test "$opt_mode" != relink; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test "$hardcode_direct" = no; then + add="$dir/$linklib" + case $host in + *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; + *-*-sysv4*uw2*) add_dir="-L$dir" ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir="-L$dir" ;; + *-*-darwin* ) + # if the lib is a (non-dlopened) module then we can not + # link against it, someone is ignoring the earlier warnings + if /usr/bin/file -L $add 2> /dev/null | + $GREP ": [^:]* bundle" >/dev/null ; then + if test "X$dlopenmodule" != "X$lib"; then + $ECHO "*** Warning: lib $linklib is a module, not a shared library" + if test -z "$old_library" ; then + echo + echo "*** And there doesn't seem to be a static archive available" + echo "*** The link will probably fail, sorry" + else + add="$dir/$old_library" + fi + elif test -n "$old_library"; then + add="$dir/$old_library" + fi + fi + esac + elif test "$hardcode_minus_L" = no; then + case $host in + *-*-sunos*) add_shlibpath="$dir" ;; + esac + add_dir="-L$dir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = no; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + relink) + if test "$hardcode_direct" = yes && + test "$hardcode_direct_absolute" = no; then + add="$dir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$dir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test "$lib_linked" != yes; then + func_fatal_configuration "unsupported hardcode properties" + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) func_append compile_shlibpath "$add_shlibpath:" ;; + esac + fi + if test "$linkmode" = prog; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test "$hardcode_direct" != yes && + test "$hardcode_minus_L" != yes && + test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + fi + fi + fi + + if test "$linkmode" = prog || test "$opt_mode" = relink; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test "$hardcode_direct" = yes && + test "$hardcode_direct_absolute" = no; then + add="$libdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$libdir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + add="-l$name" + elif test "$hardcode_automatic" = yes; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib" ; then + add="$inst_prefix_dir$libdir/$linklib" + else + add="$libdir/$linklib" + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir="-L$libdir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + fi + + if test "$linkmode" = prog; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test "$linkmode" = prog; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test "$hardcode_direct" != unsupported; then + test -n "$old_library" && linklib="$old_library" + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test "$build_libtool_libs" = yes; then + # Not a shared library + if test "$deplibs_check_method" != pass_all; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + echo + $ECHO "*** Warning: This system can not link to static lib archive $lib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + if test "$module" = yes; then + echo "*** But as you try to build a module library, libtool will still create " + echo "*** a static module, that should work as long as the dlopening application" + echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test "$linkmode" = lib; then + if test -n "$dependency_libs" && + { test "$hardcode_into_libs" != yes || + test "$build_old_libs" = yes || + test "$link_static" = yes; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) func_stripname '-R' '' "$libdir" + temp_xrpath=$func_stripname_result + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) func_append xrpath " $temp_xrpath";; + esac;; + *) func_append temp_deplibs " $libdir";; + esac + done + dependency_libs="$temp_deplibs" + fi + + func_append newlib_search_path " $absdir" + # Link against this library + test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result";; + *) func_resolve_sysroot "$deplib" ;; + esac + if $opt_preserve_dup_deps ; then + case "$tmp_libs " in + *" $func_resolve_sysroot_result "*) + func_append specialdeplibs " $func_resolve_sysroot_result" ;; + esac + fi + func_append tmp_libs " $func_resolve_sysroot_result" + done + + if test "$link_all_deplibs" != no; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + path= + case $deplib in + -L*) path="$deplib" ;; + *.la) + func_resolve_sysroot "$deplib" + deplib=$func_resolve_sysroot_result + func_dirname "$deplib" "" "." + dir=$func_dirname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + func_warning "cannot determine absolute directory name of \`$dir'" + absdir="$dir" + fi + ;; + esac + if $GREP "^installed=no" $deplib > /dev/null; then + case $host in + *-*-darwin*) + depdepl= + eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names" ; then + for tmp in $deplibrary_names ; do + depdepl=$tmp + done + if test -f "$absdir/$objdir/$depdepl" ; then + depdepl="$absdir/$objdir/$depdepl" + darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -z "$darwin_install_name"; then + darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + fi + func_append compiler_flags " ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" + func_append linker_flags " -dylib_file ${darwin_install_name}:${depdepl}" + path= + fi + fi + ;; + *) + path="-L$absdir/$objdir" + ;; + esac + else + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "\`$deplib' is not a valid libtool archive" + test "$absdir" != "$libdir" && \ + func_warning "\`$deplib' seems to be moved" + + path="-L$absdir" + fi + ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test "$pass" = link; then + if test "$linkmode" = "prog"; then + compile_deplibs="$new_inherited_linker_flags $compile_deplibs" + finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" + else + compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + fi + fi + dependency_libs="$newdependency_libs" + if test "$pass" = dlpreopen; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test "$pass" != dlopen; then + if test "$pass" != conv; then + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) func_append lib_search_path " $dir" ;; + esac + done + newlib_search_path= + fi + + if test "$linkmode,$pass" != "prog,link"; then + vars="deplibs" + else + vars="compile_deplibs finalize_deplibs" + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) func_append tmp_libs " $deplib" ;; + esac + ;; + *) func_append tmp_libs " $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs ; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i="" + ;; + esac + if test -n "$i" ; then + func_append tmp_libs " $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test "$linkmode" = prog; then + dlfiles="$newdlfiles" + fi + if test "$linkmode" = prog || test "$linkmode" = lib; then + dlprefiles="$newdlprefiles" + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + func_warning "\`-dlopen' is ignored for archives" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "\`-l' and \`-L' are ignored for archives" ;; + esac + + test -n "$rpath" && \ + func_warning "\`-rpath' is ignored for archives" + + test -n "$xrpath" && \ + func_warning "\`-R' is ignored for archives" + + test -n "$vinfo" && \ + func_warning "\`-version-info/-version-number' is ignored for archives" + + test -n "$release" && \ + func_warning "\`-release' is ignored for archives" + + test -n "$export_symbols$export_symbols_regex" && \ + func_warning "\`-export-symbols' is ignored for archives" + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs="$output" + func_append objs "$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form `libNAME.la'. + case $outputname in + lib*) + func_stripname 'lib' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + test "$module" = no && \ + func_fatal_help "libtool library \`$output' must begin with \`lib'" + + if test "$need_lib_prefix" != no; then + # Add the "lib" prefix for modules if required + func_stripname '' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + func_stripname '' '.la' "$outputname" + libname=$func_stripname_result + fi + ;; + esac + + if test -n "$objs"; then + if test "$deplibs_check_method" != pass_all; then + func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" + else + echo + $ECHO "*** Warning: Linking the shared library $output against the non-libtool" + $ECHO "*** objects $objs is not portable!" + func_append libobjs " $objs" + fi + fi + + test "$dlself" != no && \ + func_warning "\`-dlopen self' is ignored for libtool libraries" + + set dummy $rpath + shift + test "$#" -gt 1 && \ + func_warning "ignoring multiple \`-rpath's for a libtool library" + + install_libdir="$1" + + oldlibs= + if test -z "$rpath"; then + if test "$build_libtool_libs" = yes; then + # Building a libtool convenience library. + # Some compilers have problems with a `.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + test -n "$vinfo" && \ + func_warning "\`-version-info/-version-number' is ignored for convenience libraries" + + test -n "$release" && \ + func_warning "\`-release' is ignored for convenience libraries" + else + + # Parse the version information argument. + save_ifs="$IFS"; IFS=':' + set dummy $vinfo 0 0 0 + shift + IFS="$save_ifs" + + test -n "$7" && \ + func_fatal_help "too many parameters to \`-version-info'" + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major="$1" + number_minor="$2" + number_revision="$3" + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # which has an extra 1 added just for fun + # + case $version_type in + darwin|linux|osf|windows|none) + func_arith $number_major + $number_minor + current=$func_arith_result + age="$number_minor" + revision="$number_revision" + ;; + freebsd-aout|freebsd-elf|qnx|sunos) + current="$number_major" + revision="$number_minor" + age="0" + ;; + irix|nonstopux) + func_arith $number_major + $number_minor + current=$func_arith_result + age="$number_minor" + revision="$number_minor" + lt_irix_increment=no + ;; + esac + ;; + no) + current="$1" + revision="$2" + age="$3" + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "CURRENT \`$current' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "REVISION \`$revision' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "AGE \`$age' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + if test "$age" -gt "$current"; then + func_error "AGE \`$age' is greater than the current interface number \`$current'" + func_fatal_error "\`$vinfo' is not valid version information" + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + func_arith $current - $age + major=.$func_arith_result + versuffix="$major.$age.$revision" + # Darwin ld doesn't like 0 for these options... + func_arith $current + 1 + minor_current=$func_arith_result + xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + + freebsd-aout) + major=".$current" + versuffix=".$current.$revision"; + ;; + + freebsd-elf) + major=".$current" + versuffix=".$current" + ;; + + irix | nonstopux) + if test "X$lt_irix_increment" = "Xno"; then + func_arith $current - $age + else + func_arith $current - $age + 1 + fi + major=$func_arith_result + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring="$verstring_prefix$major.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test "$loop" -ne 0; do + func_arith $revision - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring="$verstring_prefix$major.$iface:$verstring" + done + + # Before this point, $major must not contain `.'. + major=.$major + versuffix="$major.$revision" + ;; + + linux) + func_arith $current - $age + major=.$func_arith_result + versuffix="$major.$age.$revision" + ;; + + osf) + func_arith $current - $age + major=.$func_arith_result + versuffix=".$current.$age.$revision" + verstring="$current.$age.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$age + while test "$loop" -ne 0; do + func_arith $current - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring="$verstring:${iface}.0" + done + + # Make executables depend on our current version. + func_append verstring ":${current}.0" + ;; + + qnx) + major=".$current" + versuffix=".$current" + ;; + + sunos) + major=".$current" + versuffix=".$current.$revision" + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 filesystems. + func_arith $current - $age + major=$func_arith_result + versuffix="-$major" + ;; + + *) + func_fatal_configuration "unknown library version type \`$version_type'" + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring="0.0" + ;; + esac + if test "$need_version" = no; then + versuffix= + else + versuffix=".0.0" + fi + fi + + # Remove version info from name if versioning should be avoided + if test "$avoid_version" = yes && test "$need_version" = no; then + major= + versuffix= + verstring="" + fi + + # Check to see if the archive will have undefined symbols. + if test "$allow_undefined" = yes; then + if test "$allow_undefined_flag" = unsupported; then + func_warning "undefined symbols not allowed in $host shared libraries" + build_libtool_libs=no + build_old_libs=yes + fi + else + # Don't allow undefined symbols. + allow_undefined_flag="$no_undefined_flag" + fi + + fi + + func_generate_dlsyms "$libname" "$libname" "yes" + func_append libobjs " $symfileobj" + test "X$libobjs" = "X " && libobjs= + + if test "$opt_mode" != relink; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$ECHO "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext | *.gcno) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) + if test "X$precious_files_regex" != "X"; then + if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + func_append removelist " $p" + ;; + *) ;; + esac + done + test -n "$removelist" && \ + func_show_eval "${RM}r \$removelist" + fi + + # Now set the variables for building old libraries. + if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then + func_append oldlibs " $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + #for path in $notinst_path; do + # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` + # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` + # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` + #done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + func_replace_sysroot "$libdir" + func_append temp_xrpath " -R$func_replace_sysroot_result" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles="$dlfiles" + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) func_append dlfiles " $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles="$dlprefiles" + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) func_append dlprefiles " $lib" ;; + esac + done + + if test "$build_libtool_libs" = yes; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + func_append deplibs " System.ltframework" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test "$build_libtool_need_lc" = "yes"; then + func_append deplibs " -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release="" + versuffix="" + major="" + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $opt_dry_run || $RM conftest.c + cat > conftest.c </dev/null` + $nocaseglob + else + potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` + fi + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null | + $GREP " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib="$potent_lib" + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; + *) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | + $SED -e 10q | + $EGREP "$file_magic_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $ECHO "*** with $libname but no candidates were found. (...for file magic test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a file magic. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $a_deplib "*) + func_append newdeplibs " $a_deplib" + a_deplib="" + ;; + esac + fi + if test -n "$a_deplib" ; then + libname=`eval "\\$ECHO \"$libname_spec\""` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib="$potent_lib" # see symlink-check above in file_magic test + if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ + $EGREP "$match_pattern_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a regex pattern. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs="" + tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + for i in $predeps $postdeps ; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"` + done + fi + case $tmp_deplibs in + *[!\ \ ]*) + echo + if test "X$deplibs_check_method" = "Xnone"; then + echo "*** Warning: inter-library dependencies are not supported in this platform." + else + echo "*** Warning: inter-library dependencies are not known to be supported." + fi + echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + ;; + esac + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library with the System framework + newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + if test "$droppeddeps" = yes; then + if test "$module" = yes; then + echo + echo "*** Warning: libtool could not satisfy all declared inter-library" + $ECHO "*** dependencies of module $libname. Therefore, libtool will create" + echo "*** a static module, that should work as long as the dlopening" + echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + echo "*** The inter-library dependencies that have been dropped here will be" + echo "*** automatically added whenever a program is linked with this library" + echo "*** or is declared to -dlopen it." + + if test "$allow_undefined" = no; then + echo + echo "*** Since this library must not contain undefined symbols," + echo "*** because either the platform does not support them or" + echo "*** it was explicitly requested with -no-undefined," + echo "*** libtool will only create a static version of it." + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + case $host in + *-*-darwin*) + newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + deplibs="$new_libs" + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test "$build_libtool_libs" = yes; then + if test "$hardcode_into_libs" = yes; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath="$finalize_rpath" + test "$opt_mode" != relink && rpath="$compile_rpath$rpath" + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + func_replace_sysroot "$libdir" + libdir=$func_replace_sysroot_result + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append dep_rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_apped perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + if test -n "$hardcode_libdir_flag_spec_ld"; then + eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" + else + eval dep_rpath=\"$hardcode_libdir_flag_spec\" + fi + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath="$finalize_shlibpath" + test "$opt_mode" != relink && shlibpath="$compile_shlibpath$shlibpath" + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + shift + realname="$1" + shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib="$output_objdir/$realname" + linknames= + for link + do + func_append linknames " $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` + test "X$libobjs" = "X " && libobjs= + + delfiles= + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" + export_symbols="$output_objdir/$libname.uexp" + func_append delfiles " $export_symbols" + fi + + orig_export_symbols= + case $host_os in + cygwin* | mingw* | cegcc*) + if test -n "$export_symbols" && test -z "$export_symbols_regex"; then + # exporting using user supplied symfile + if test "x`$SED 1q $export_symbols`" != xEXPORTS; then + # and it's NOT already a .def file. Must figure out + # which of the given symbols are data symbols and tag + # them as such. So, trigger use of export_symbols_cmds. + # export_symbols gets reassigned inside the "prepare + # the list of exported symbols" if statement, so the + # include_expsyms logic still works. + orig_export_symbols="$export_symbols" + export_symbols= + always_export_symbols=yes + fi + fi + ;; + esac + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $opt_dry_run || $RM $export_symbols + cmds=$export_symbols_cmds + save_ifs="$IFS"; IFS='~' + for cmd1 in $cmds; do + IFS="$save_ifs" + # Take the normal branch if the nm_file_list_spec branch + # doesn't work or if tool conversion is not needed. + case $nm_file_list_spec~$to_tool_file_cmd in + *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) + try_normal_branch=yes + eval cmd=\"$cmd1\" + func_len " $cmd" + len=$func_len_result + ;; + *) + try_normal_branch=no + ;; + esac + if test "$try_normal_branch" = yes \ + && { test "$len" -lt "$max_cmd_len" \ + || test "$max_cmd_len" -le -1; } + then + func_show_eval "$cmd" 'exit $?' + skipped_export=false + elif test -n "$nm_file_list_spec"; then + func_basename "$output" + output_la=$func_basename_result + save_libobjs=$libobjs + save_output=$output + output=${output_objdir}/${output_la}.nm + func_to_tool_file "$output" + libobjs=$nm_file_list_spec$func_to_tool_file_result + func_append delfiles " $output" + func_verbose "creating $NM input file list: $output" + for obj in $save_libobjs; do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > "$output" + eval cmd=\"$cmd1\" + func_show_eval "$cmd" 'exit $?' + output=$save_output + libobjs=$save_libobjs + skipped_export=false + else + # The command line is too long to execute in one step. + func_verbose "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS="$save_ifs" + if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols="$export_symbols" + test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + func_append tmp_deplibs " $test_deplib" + ;; + esac + done + deplibs="$tmp_deplibs" + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec" && + test "$compiler_needs_object" = yes && + test -z "$libobjs"; then + # extract the archives, so we have objects to list. + # TODO: could optimize this to just extract one archive. + whole_archive_flag_spec= + fi + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + else + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + fi + + if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + func_append linker_flags " $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test "$opt_mode" = relink; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test "X$skipped_export" != "X:" && + func_len " $test_cmds" && + len=$func_len_result && + test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise + # or, if using GNU ld and skipped_export is not :, use a linker + # script. + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + func_basename "$output" + output_la=$func_basename_result + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + last_robj= + k=1 + + if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then + output=${output_objdir}/${output_la}.lnkscript + func_verbose "creating GNU ld script: $output" + echo 'INPUT (' > $output + for obj in $save_libobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + echo ')' >> $output + func_append delfiles " $output" + func_to_tool_file "$output" + output=$func_to_tool_file_result + elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then + output=${output_objdir}/${output_la}.lnk + func_verbose "creating linker input file list: $output" + : > $output + set x $save_libobjs + shift + firstobj= + if test "$compiler_needs_object" = yes; then + firstobj="$1 " + shift + fi + for obj + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + func_append delfiles " $output" + func_to_tool_file "$output" + output=$firstobj\"$file_list_spec$func_to_tool_file_result\" + else + if test -n "$save_libobjs"; then + func_verbose "creating reloadable object files..." + output=$output_objdir/$output_la-${k}.$objext + eval test_cmds=\"$reload_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + if test "X$objlist" = X || + test "$len" -lt "$max_cmd_len"; then + func_append objlist " $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test "$k" -eq 1 ; then + # The first file doesn't have a previous command to add. + reload_objs=$objlist + eval concat_cmds=\"$reload_cmds\" + else + # All subsequent reloadable object files will link in + # the last one created. + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" + fi + last_robj=$output_objdir/$output_la-${k}.$objext + func_arith $k + 1 + k=$func_arith_result + output=$output_objdir/$output_la-${k}.$objext + objlist=" $obj" + func_len " $last_robj" + func_arith $len0 + $func_len_result + len=$func_arith_result + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\${concat_cmds}$reload_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" + fi + func_append delfiles " $output" + + else + output= + fi + + if ${skipped_export-false}; then + func_verbose "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $opt_dry_run || $RM $export_symbols + libobjs=$output + # Append the command to create the export file. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + fi + + test -n "$save_libobjs" && + func_verbose "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs="$IFS"; IFS='~' + for cmd in $concat_cmds; do + IFS="$save_ifs" + $opt_silent || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$opt_mode" = relink; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + if test -n "$export_symbols_regex" && ${skipped_export-false}; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + + if ${skipped_export-false}; then + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols="$export_symbols" + test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + fi + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + fi + + if test -n "$delfiles"; then + # Append the command to remove temporary files to $cmds. + eval cmds=\"\$cmds~\$RM $delfiles\" + fi + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $opt_silent || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$opt_mode" = relink; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + # Restore the uninstalled library and exit + if test "$opt_mode" = relink; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + func_show_eval '${RM}r "$gentop"' + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test "$module" = yes || test "$export_dynamic" = yes; then + # On all known operating systems, these are identical. + dlname="$soname" + fi + fi + ;; + + obj) + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + func_warning "\`-dlopen' is ignored for objects" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "\`-l' and \`-L' are ignored for objects" ;; + esac + + test -n "$rpath" && \ + func_warning "\`-rpath' is ignored for objects" + + test -n "$xrpath" && \ + func_warning "\`-R' is ignored for objects" + + test -n "$vinfo" && \ + func_warning "\`-version-info' is ignored for objects" + + test -n "$release" && \ + func_warning "\`-release' is ignored for objects" + + case $output in + *.lo) + test -n "$objs$old_deplibs" && \ + func_fatal_error "cannot build library object \`$output' from non-libtool objects" + + libobj=$output + func_lo2o "$libobj" + obj=$func_lo2o_result + ;; + *) + libobj= + obj="$output" + ;; + esac + + # Delete the old objects. + $opt_dry_run || $RM $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # reload_cmds runs $LD directly, so let us get rid of + # -Wl from whole_archive_flag_spec and hope we can get by with + # turning comma into space.. + wl= + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" + reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` + else + gentop="$output_objdir/${obj}x" + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # If we're not building shared, we need to use non_pic_objs + test "$build_libtool_libs" != yes && libobjs="$non_pic_objects" + + # Create the old-style object. + reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test + + output="$obj" + func_execute_cmds "$reload_cmds" 'exit $?' + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + fi + + if test "$build_libtool_libs" != yes; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + fi + + if test -n "$pic_flag" || test "$pic_mode" != default; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output="$libobj" + func_execute_cmds "$reload_cmds" 'exit $?' + fi + + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) func_stripname '' '.exe' "$output" + output=$func_stripname_result.exe;; + esac + test -n "$vinfo" && \ + func_warning "\`-version-info' is ignored for programs" + + test -n "$release" && \ + func_warning "\`-release' is ignored for programs" + + test "$preload" = yes \ + && test "$dlopen_support" = unknown \ + && test "$dlopen_self" = unknown \ + && test "$dlopen_self_static" = unknown && \ + func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + case $host in + *-*-darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + # But is supposedly fixed on 10.4 or later (yay!). + if test "$tagname" = CXX ; then + case ${MACOSX_DEPLOYMENT_TARGET-10.0} in + 10.[0123]) + func_append compile_command " ${wl}-bind_at_load" + func_append finalize_command " ${wl}-bind_at_load" + ;; + esac + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + compile_deplibs="$new_libs" + + + func_append compile_command " $compile_deplibs" + func_append finalize_command " $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + ::) dllsearchpath=$libdir;; + *) func_append dllsearchpath ":$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath="$rpath" + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) func_append finalize_perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath="$rpath" + + if test -n "$libobjs" && test "$build_old_libs" = yes; then + # Transform all the library objects into standard objects. + compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + fi + + func_generate_dlsyms "$outputname" "@PROGRAM@" "no" + + # template prelinking step + if test -n "$prelink_cmds"; then + func_execute_cmds "$prelink_cmds" 'exit $?' + fi + + wrappers_required=yes + case $host in + *cegcc* | *mingw32ce*) + # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. + wrappers_required=no + ;; + *cygwin* | *mingw* ) + if test "$build_libtool_libs" != yes; then + wrappers_required=no + fi + ;; + *) + if test "$need_relink" = no || test "$build_libtool_libs" != yes; then + wrappers_required=no + fi + ;; + esac + if test "$wrappers_required" = no; then + # Replace the output file specification. + compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + link_command="$compile_command$compile_rpath" + + # We have no uninstalled library dependencies, so finalize right now. + exit_status=0 + func_show_eval "$link_command" 'exit_status=$?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Delete the generated files. + if test -f "$output_objdir/${outputname}S.${objext}"; then + func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' + fi + + exit $exit_status + fi + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + func_append rpath "$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test "$no_install" = yes; then + # We don't need to create a wrapper script. + link_command="$compile_var$compile_command$compile_rpath" + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $opt_dry_run || $RM $output + # Link the executable and exit + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + exit $EXIT_SUCCESS + fi + + if test "$hardcode_action" = relink; then + # Fast installation is not supported + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + + func_warning "this platform does not like uninstalled shared libraries" + func_warning "\`$output' will be relinked during installation" + else + if test "$fast_install" != no; then + link_command="$finalize_var$compile_command$finalize_rpath" + if test "$fast_install" = yes; then + relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` + else + # fast_install is set to needless + relink_command= + fi + else + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + fi + fi + + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname + + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output_objdir/$outputname" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Now create the wrapper script. + func_verbose "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + fi + + # Only actually do things if not in dry run mode. + $opt_dry_run || { + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) func_stripname '' '.exe' "$output" + output=$func_stripname_result ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + func_stripname '' '.exe' "$outputname" + outputname=$func_stripname_result ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + func_dirname_and_basename "$output" "" "." + output_name=$func_basename_result + output_path=$func_dirname_result + cwrappersource="$output_path/$objdir/lt-$output_name.c" + cwrapper="$output_path/$output_name.exe" + $RM $cwrappersource $cwrapper + trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + func_emit_cwrapperexe_src > $cwrappersource + + # The wrapper executable is built using the $host compiler, + # because it contains $host paths and files. If cross- + # compiling, it, like the target executable, must be + # executed on the $host or under an emulation environment. + $opt_dry_run || { + $LTCC $LTCFLAGS -o $cwrapper $cwrappersource + $STRIP $cwrapper + } + + # Now, create the wrapper script for func_source use: + func_ltwrapper_scriptname $cwrapper + $RM $func_ltwrapper_scriptname_result + trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 + $opt_dry_run || { + # note: this script will not be executed, so do not chmod. + if test "x$build" = "x$host" ; then + $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result + else + func_emit_wrapper no > $func_ltwrapper_scriptname_result + fi + } + ;; + * ) + $RM $output + trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 + + func_emit_wrapper no > $output + chmod +x $output + ;; + esac + } + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + if test "$build_libtool_libs" = convenience; then + oldobjs="$libobjs_save $symfileobj" + addlibs="$convenience" + build_libtool_libs=no + else + if test "$build_libtool_libs" = module; then + oldobjs="$libobjs_save" + build_libtool_libs=no + else + oldobjs="$old_deplibs $non_pic_objects" + if test "$preload" = yes && test -f "$symfileobj"; then + func_append oldobjs " $symfileobj" + fi + fi + addlibs="$old_convenience" + fi + + if test -n "$addlibs"; then + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $addlibs + func_append oldobjs " $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then + cmds=$old_archive_from_new_cmds + else + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append oldobjs " $func_extract_archives_result" + fi + + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + func_basename "$obj" + $ECHO "$func_basename_result" + done | sort | sort -uc >/dev/null 2>&1); then + : + else + echo "copying selected object files to avoid basename conflicts..." + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + func_mkdir_p "$gentop" + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + func_basename "$obj" + objbase="$func_basename_result" + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + func_arith $counter + 1 + counter=$func_arith_result + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + func_append oldobjs " $gentop/$newobj" + ;; + *) func_append oldobjs " $obj" ;; + esac + done + fi + eval cmds=\"$old_archive_cmds\" + + func_len " $cmds" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + elif test -n "$archiver_list_spec"; then + func_verbose "using command file archive linking..." + for obj in $oldobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > $output_objdir/$libname.libcmd + func_to_tool_file "$output_objdir/$libname.libcmd" + oldobjs=" $archiver_list_spec$func_to_tool_file_result" + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + func_verbose "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + oldobjs= + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + eval test_cmds=\"$old_archive_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + for obj in $save_oldobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + func_append objlist " $obj" + if test "$len" -lt "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj" ; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" + objlist= + len=$len0 + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test "X$oldobjs" = "X" ; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + func_execute_cmds "$cmds" 'exit $?' + done + + test -n "$generated" && \ + func_show_eval "${RM}r$generated" + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test "$build_old_libs" = yes && old_library="$libname.$libext" + func_verbose "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + if test "$hardcode_automatic" = yes ; then + relink_command= + fi + + # Only create the output if not a dry run. + $opt_dry_run || { + for installed in no yes; do + if test "$installed" = yes; then + if test -z "$install_libdir"; then + break + fi + output="$output_objdir/$outputname"i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + func_basename "$deplib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "\`$deplib' is not a valid libtool archive" + func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" + ;; + -L*) + func_stripname -L '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -L$func_replace_sysroot_result" + ;; + -R*) + func_stripname -R '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -R$func_replace_sysroot_result" + ;; + *) func_append newdependency_libs " $deplib" ;; + esac + done + dependency_libs="$newdependency_libs" + newdlfiles= + + for lib in $dlfiles; do + case $lib in + *.la) + func_basename "$lib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "\`$lib' is not a valid libtool archive" + func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" + ;; + *) func_append newdlfiles " $lib" ;; + esac + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + *.la) + # Only pass preopened files to the pseudo-archive (for + # eventual linking with the app. that links it) if we + # didn't already link the preopened objects directly into + # the library: + func_basename "$lib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "\`$lib' is not a valid libtool archive" + func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" + ;; + esac + done + dlprefiles="$newdlprefiles" + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlfiles " $abs" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlprefiles " $abs" + done + dlprefiles="$newdlprefiles" + fi + $RM $output + # place dlname in correct position for cygwin + # In fact, it would be nice if we could use this code for all target + # systems that can't hard-code library paths into their executables + # and that have no shared library path variable independent of PATH, + # but it turns out we can't easily determine that from inspecting + # libtool variables, so we have to hard-code the OSs to which it + # applies here; at the moment, that means platforms that use the PE + # object format with DLL files. See the long comment at the top of + # tests/bindir.at for full details. + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) + # If a -bindir argument was supplied, place the dll there. + if test "x$bindir" != x ; + then + func_relative_path "$install_libdir" "$bindir" + tdlname=$func_relative_path_result$dlname + else + # Otherwise fall back on heuristic. + tdlname=../bin/$dlname + fi + ;; + esac + $ECHO > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Linker flags that can not go in dependency_libs. +inherited_linker_flags='$new_inherited_linker_flags' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Names of additional weak libraries provided by this library +weak_library_names='$weak_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test "$installed" = no && test "$need_relink" = yes; then + $ECHO >> $output "\ +relink_command=\"$relink_command\"" + fi + done + } + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' + ;; + esac + exit $EXIT_SUCCESS +} + +{ test "$opt_mode" = link || test "$opt_mode" = relink; } && + func_mode_link ${1+"$@"} + + +# func_mode_uninstall arg... +func_mode_uninstall () +{ + $opt_debug + RM="$nonopt" + files= + rmforce= + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + for arg + do + case $arg in + -f) func_append RM " $arg"; rmforce=yes ;; + -*) func_append RM " $arg" ;; + *) func_append files " $arg" ;; + esac + done + + test -z "$RM" && \ + func_fatal_help "you must specify an RM program" + + rmdirs= + + for file in $files; do + func_dirname "$file" "" "." + dir="$func_dirname_result" + if test "X$dir" = X.; then + odir="$objdir" + else + odir="$dir/$objdir" + fi + func_basename "$file" + name="$func_basename_result" + test "$opt_mode" = uninstall && odir="$dir" + + # Remember odir for removal later, being careful to avoid duplicates + if test "$opt_mode" = clean; then + case " $rmdirs " in + *" $odir "*) ;; + *) func_append rmdirs " $odir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if { test -L "$file"; } >/dev/null 2>&1 || + { test -h "$file"; } >/dev/null 2>&1 || + test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif test "$rmforce" = yes; then + continue + fi + + rmfiles="$file" + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if func_lalib_p "$file"; then + func_source $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + func_append rmfiles " $odir/$n" + done + test -n "$old_library" && func_append rmfiles " $odir/$old_library" + + case "$opt_mode" in + clean) + case " $library_names " in + *" $dlname "*) ;; + *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; + esac + test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if func_lalib_p "$file"; then + + # Read the .lo file + func_source $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" && + test "$pic_object" != none; then + func_append rmfiles " $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" && + test "$non_pic_object" != none; then + func_append rmfiles " $dir/$non_pic_object" + fi + fi + ;; + + *) + if test "$opt_mode" = clean ; then + noexename=$name + case $file in + *.exe) + func_stripname '' '.exe' "$file" + file=$func_stripname_result + func_stripname '' '.exe' "$name" + noexename=$func_stripname_result + # $file with .exe has already been added to rmfiles, + # add $file without .exe + func_append rmfiles " $file" + ;; + esac + # Do a test to see if this is a libtool program. + if func_ltwrapper_p "$file"; then + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + relink_command= + func_source $func_ltwrapper_scriptname_result + func_append rmfiles " $func_ltwrapper_scriptname_result" + else + relink_command= + func_source $dir/$noexename + fi + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + func_append rmfiles " $odir/$name $odir/${name}S.${objext}" + if test "$fast_install" = yes && test -n "$relink_command"; then + func_append rmfiles " $odir/lt-$name" + fi + if test "X$noexename" != "X$name" ; then + func_append rmfiles " $odir/lt-${noexename}.c" + fi + fi + fi + ;; + esac + func_show_eval "$RM $rmfiles" 'exit_status=1' + done + + # Try to remove the ${objdir}s in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + func_show_eval "rmdir $dir >/dev/null 2>&1" + fi + done + + exit $exit_status +} + +{ test "$opt_mode" = uninstall || test "$opt_mode" = clean; } && + func_mode_uninstall ${1+"$@"} + +test -z "$opt_mode" && { + help="$generic_help" + func_fatal_help "you must specify a MODE" +} + +test -z "$exec_cmd" && \ + func_fatal_help "invalid operation mode \`$opt_mode'" + +if test -n "$exec_cmd"; then + eval exec "$exec_cmd" + exit $EXIT_FAILURE +fi + +exit $exit_status + + +# The TAGs below are defined such that we never get into a situation +# in which we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +build_libtool_libs=no +build_old_libs=yes +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: +# vi:sw=2 + diff --git a/pythonmod/LICENSE b/pythonmod/LICENSE new file mode 100644 index 00000000000..7b769d09120 --- /dev/null +++ b/pythonmod/LICENSE @@ -0,0 +1,28 @@ +Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz) + Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) + +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 the organization 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. diff --git a/pythonmod/Makefile b/pythonmod/Makefile new file mode 100644 index 00000000000..2a00152418a --- /dev/null +++ b/pythonmod/Makefile @@ -0,0 +1,58 @@ +# Makefile: tests unbound python module (please edit SCRIPT variable) +# +# Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz) +# Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) +# +# 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 organization 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 REGENTS OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +SUEXEC = sudo +UNBOUND = ../unbound +SCRIPT = ./test-resip.conf + +UNBOUND_OPTS = -dv -c $(SCRIPT) + +.PHONY: test sudo suexec doc + +all: test + +$(UNBOUND): + make -C .. + +test: $(UNBOUND) + $(UNBOUND) $(UNBOUND_OPTS) + +sudo: $(UNBOUND) + sudo $(UNBOUND) $(UNBOUND_OPTS) + +suexec: $(UNBOUND) + su -c "$(UNBOUND) $(UNBOUND_OPTS)" + +doc: + $(MAKE) -C doc html diff --git a/pythonmod/doc/_static/readme b/pythonmod/doc/_static/readme new file mode 100644 index 00000000000..db676aebbde --- /dev/null +++ b/pythonmod/doc/_static/readme @@ -0,0 +1 @@ +this directory exists to pacify sphinx-build. diff --git a/pythonmod/doc/conf.py b/pythonmod/doc/conf.py new file mode 100644 index 00000000000..bc7a5aba68d --- /dev/null +++ b/pythonmod/doc/conf.py @@ -0,0 +1,179 @@ +# -*- coding: utf-8 -*- +# +# Unbound scripting interface documentation build configuration file +# +# This file is execfile()d with the current directory set to its containing dir. +# +# The contents of this file are pickled, so don't put values in the namespace +# that aren't pickleable (module imports are okay, they're removed automatically). +# +# All configuration values have a default value; values that are commented out +# serve to show the default value. + +import sys, os + +# If your extensions are in another directory, add it here. If the directory +# is relative to the documentation root, use os.path.abspath to make it +# absolute, like shown here. +sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__),'../..'))) +#print sys.path + +# General configuration +# --------------------- + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# General substitutions. +project = 'Unbound scriptable interface' +copyright = '2009, Zdenek Vasicek, Marek Vavrusa' + +# The default replacements for |version| and |release|, also used in various +# other places throughout the built documents. +# +# The short X.Y version. +version = '1.0' +# The full version, including alpha/beta/rc tags. +release = '1.0.0' + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +today_fmt = '%B %d, %Y' + +# List of documents that shouldn't be included in the build. +#unused_docs = [] + +# List of directories, relative to source directories, that shouldn't be searched +# for source files. +#exclude_dirs = [] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + + +# Options for HTML output +# ----------------------- + +# The style sheet to use for HTML and HTML Help pages. A file of that name +# must exist either in Sphinx' static/ path, or in one of the custom paths +# given in html_static_path. +html_style = 'default.css' + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (within the static path) to place at the top of +# the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +html_use_modindex = False + +# If false, no index is generated. +html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, the reST sources are included in the HTML build as _sources/. +html_copy_source = False + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = '' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'unbound_interface' + + +# Options for LaTeX output +# ------------------------ + +# The paper size ('letter' or 'a4'). +#latex_paper_size = 'letter' + +# The font size ('10pt', '11pt' or '12pt'). +#latex_font_size = '10pt' + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, document class [howto/manual]). +latex_documents = [ + ('index', 'Unbound_interface.tex', 'Unbound scriptable interface', + 'Zdenek Vasicek, Marek Vavrusa', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# Additional stuff for the LaTeX preamble. +#latex_preamble = '' + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_use_modindex = True diff --git a/pythonmod/doc/examples/example0-1.py b/pythonmod/doc/examples/example0-1.py new file mode 100644 index 00000000000..98a9acccdea --- /dev/null +++ b/pythonmod/doc/examples/example0-1.py @@ -0,0 +1,37 @@ + +print mod_env.fname # Print module script name +mod_env.data = "test" # Store global module data + +def init(id, cfg): + log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, cfg.port, cfg.python_script)) + return True + +def deinit(id): + log_info("pythonmod: deinit called, module id is %d" % id) + return True + +def inform_super(id, qstate, superqstate, qdata): + return True + +def operate(id, event, qstate, qdata): + log_info("pythonmod: operate called, id: %d, event:%s" % (id, strmodulevent(event))) + + if event == MODULE_EVENT_NEW: + qstate.ext_state[id] = MODULE_WAIT_MODULE + return True + + if event == MODULE_EVENT_MODDONE: + log_info("pythonmod: module we are waiting for is done") + qstate.ext_state[id] = MODULE_FINISHED + return True + + if event == MODULE_EVENT_PASS: + log_info("pythonmod: event_pass") + qstate.ext_state[id] = MODULE_ERROR + return True + + log_err("pythonmod: BAD event") + qstate.ext_state[id] = MODULE_ERROR + return True + +log_info("pythonmod: script loaded.") diff --git a/pythonmod/doc/examples/example0.rst b/pythonmod/doc/examples/example0.rst new file mode 100644 index 00000000000..80eca5ea6eb --- /dev/null +++ b/pythonmod/doc/examples/example0.rst @@ -0,0 +1,129 @@ +.. _example_handler: + +Fundamentals +================ + +This basic example shows how to create simple python module which will pass on the requests to the iterator. + +How to enable python module +---------------------------- +If you look into unbound configuration file, you can find the option `module-config` which specifies the names and the order of modules to be used. +Example configuration:: + + module-config: "validator python iterator" + +As soon as the DNS query arrives, Unbound calls modules starting from leftmost - the validator *(it is the first module on the list)*. +The validator does not know the answer *(it can only validate)*, thus it will pass on the event to the next module. +Next module is python which can + + a) generate answer *(response)* + When python module generates the response unbound calls validator. Validator grabs the answer and determines the security flag. + + b) pass on the event to the iterator. + When iterator resolves the query, Unbound informs python module (event :data:`module_event_moddone`). In the end, when the python module is done, validator is called. + +Note that the python module is called with :data:`module_event_pass` event, because new DNS event was already handled by validator. + +Another situation occurs when we use the following configuration:: + + module-config: "python validator iterator" + +Python module is the first module here, so it's invoked with :data:`module_event_new` event *(new query)*. + +On Python module initialization, module loads script from `python-script` option:: + + python-script: "/unbound/test/ubmodule.py" + +Simple python module step by step +--------------------------------- + +Script file must contain four compulsory functions: + +.. function:: init(id, cfg) + + Initialize module internals, like database etc. + Called just once on module load. + + :param id: module identifier (integer) + :param cfg: :class:`config_file` configuration structure + +:: + + def init(id, cfg): + log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, cfg.port, cfg.python_script)) + return True + + +.. function:: deinit(id) + + Deinitialize module internals. + Called just once on module unload. + + :param id: module identifier (integer) + +:: + + def deinit(id): + log_info("pythonmod: deinit called, module id is %d" % id) + return True + + +.. function:: inform_super(id, qstate, superqstate, qdata) + + Inform super querystate about the results from this subquerystate. + Is called when the querystate is finished. + + :param id: module identifier (integer) + :param qstate: :class:`module_qstate` Query state + :param superqstate: :class:`pythonmod_qstate` Mesh state + :param qdata: :class:`query_info` Query data + +:: + + def inform_super(id, qstate, superqstate, qdata): + return True + + + +.. function:: operate(id, event, qstate, qdata) + + Perform action on pending query. Accepts a new query, or work on pending query. + + You have to set qstate.ext_state on exit. + The state informs unbound about result and controls the following states. + + :param id: module identifier (integer) + :param qstate: :class:`module_qstate` query state structure + :param qdata: :class:`query_info` per query data, here you can store your own data + +:: + + def operate(id, event, qstate, qdata): + log_info("pythonmod: operate called, id: %d, event:%s" % (id, strmodulevent(event))) + if event == MODULE_EVENT_NEW: + qstate.ext_state[id] = MODULE_WAIT_MODULE + return True + + if event == MODULE_EVENT_MODDONE: + qstate.ext_state[id] = MODULE_FINISHED + return True + + if event == MODULE_EVENT_PASS: + qstate.ext_state[id] = MODULE_ERROR + return True + + log_err("pythonmod: BAD event") + qstate.ext_state[id] = MODULE_ERROR + return True + + +Complete source code +-------------------- + +.. literalinclude:: example0-1.py + :language: python + +As you can see, the source code is much more flexible in contrast to C modules. +Moreover, compulsory functions called on appropriate module events allows to handle almost +anything from web control to query analysis. + diff --git a/pythonmod/doc/examples/example1.rst b/pythonmod/doc/examples/example1.rst new file mode 100644 index 00000000000..b49e6440925 --- /dev/null +++ b/pythonmod/doc/examples/example1.rst @@ -0,0 +1,42 @@ +.. _log_handler: + +Packet logger +========================= + +This example shows how to log and print details about query and response. +As soon as the ``iterator`` has finished (event is :data:`module_event_moddone`), ``qstate.return_msg`` contains response packet or ``None``. +This packet will be send to a client that asked for it. + +Complete source code +-------------------- + +.. literalinclude:: ../../examples/log.py + :language: python + +Testing +------------------ +Run the unbound server: + +``root@localhost>unbound -dv -c ./test-log.conf`` + +In case you use own configuration file, don't forget to enable python module: ``module-config: "validator python iterator"`` and use valid script path: ``python-script: "./examples/log.py"``. + +Example of output:: + + [1231790168] unbound[7941:0] info: response for + [1231790168] unbound[7941:0] info: reply from 192.5.6.31#53 + [1231790168] unbound[7941:0] info: query response was ANSWER + [1231790168] unbound[7941:0] info: pythonmod: operate called, id: 1, event:module_event_moddone + ---------------------------------------------------------------------------------------------------- + Query: f.gtld-servers.NET., type: AAAA (28), class: IN (1) + ---------------------------------------------------------------------------------------------------- + Return reply :: flags: 8080, QDcount: 1, Security:0, TTL=86400 + qinfo :: qname: ['f', 'gtld-servers', 'NET', ''] f.gtld-servers.NET., qtype: AAAA, qclass: IN + Reply: + 0 : ['gtld-servers', 'NET', ''] gtld-servers.NET. flags: 0000 type: SOA (6) class: IN (1) + 0 : TTL= 86400 + 0x00 | 00 3A 02 41 32 05 4E 53 54 4C 44 03 43 4F 4D 00 05 | . : . A 2 . N S T L D . C O M . . + 0x10 | 05 6E 73 74 6C 64 0C 76 65 72 69 73 69 67 6E 2D 67 | . n s t l d . v e r i s i g n - g + 0x20 | 67 72 73 03 43 4F 4D 00 77 74 2D 64 00 00 0E 10 00 | g r s . C O M . w t - d . . . . . + 0x30 | 00 00 03 84 00 12 75 00 00 01 51 80 | . . . . . . u . . . Q . + diff --git a/pythonmod/doc/examples/example2.rst b/pythonmod/doc/examples/example2.rst new file mode 100644 index 00000000000..f00fcc23960 --- /dev/null +++ b/pythonmod/doc/examples/example2.rst @@ -0,0 +1,46 @@ +Response generation +===================== + +This example shows how to handle queries and generate response packet. + +.. note:: + If the python module is the first module and validator module is enabled (``module-config: "python validator iterator"``), + a return_msg security flag has to be set at least to 2. Leaving security flag untouched causes that the + response will be refused by unbound worker as unbound will consider it as non-valid response. + +Complete source code +-------------------- + +.. literalinclude:: ../../examples/resgen.py + :language: python + +Testing +------- + +Run the unbound server: + +``root@localhost>unbound -dv -c ./test-resgen.conf`` + +Query for a A record ending with .localdomain + +``dig A test.xxx.localdomain @127.0.0.1`` + +Dig produces the following output:: + + ;; global options: printcmd + ;; Got answer: + ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48426 + ;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 + + ;; QUESTION SECTION: + ;test.xxx.localdomain. IN A + + ;; ANSWER SECTION: + test.xxx.localdomain. 10 IN A 127.0.0.1 + + ;; Query time: 2 msec + ;; SERVER: 127.0.0.1#53(127.0.0.1) + ;; WHEN: Mon Jan 01 12:46:02 2009 + ;; MSG SIZE rcvd: 54 + +As we handle (override) in python module only queries ending with "localdomain.", the unboud can still resolve host names. diff --git a/pythonmod/doc/examples/example3.rst b/pythonmod/doc/examples/example3.rst new file mode 100644 index 00000000000..6213dc188f1 --- /dev/null +++ b/pythonmod/doc/examples/example3.rst @@ -0,0 +1,63 @@ +Response modification +===================== + +This example shows how to modify the response produced by the ``iterator`` module. + +As soon as the iterator module returns the response, we : + +1. invalidate the data in cache +2. modify the response *TTL* +3. rewrite the data in cache +4. return modified packet + +Note that the steps 1 and 3 are neccessary only in case, the python module is the first module in the processing chain. +In other cases, the validator module guarantees updating data which are produced by iterator module. + +Complete source code +-------------------- + +.. literalinclude:: ../../examples/resmod.py + :language: python + +Testing +------- + +Run Unbound server: + +``root@localhost>unbound -dv -c ./test-resmod.conf`` + +Issue a query for name ending with "nic.cz." + +``>>>dig A @127.0.0.1 www.nic.cz`` + +:: + + ;; global options: printcmd + ;; Got answer: + ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48831 + ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 3, ADDITIONAL: 5 + + ;; QUESTION SECTION: + ;www.nic.cz. IN A + + ;; ANSWER SECTION: + www.nic.cz. 10 IN A 217.31.205.50 + + ;; AUTHORITY SECTION: + nic.cz. 10 IN NS e.ns.nic.cz. + nic.cz. 10 IN NS a.ns.nic.cz. + nic.cz. 10 IN NS c.ns.nic.cz. + + ;; ADDITIONAL SECTION: + a.ns.nic.cz. 10 IN A 217.31.205.180 + a.ns.nic.cz. 10 IN AAAA 2001:1488:dada:176::180 + c.ns.nic.cz. 10 IN A 195.66.241.202 + c.ns.nic.cz. 10 IN AAAA 2a01:40:1000::2 + e.ns.nic.cz. 10 IN A 194.146.105.38 + + ;; Query time: 166 msec + ;; SERVER: 127.0.0.1#53(127.0.0.1) + ;; WHEN: Mon Jan 02 13:39:43 2009 + ;; MSG SIZE rcvd: 199 + +As you can see, TTL of all the records is set to 10. diff --git a/pythonmod/doc/examples/example4.rst b/pythonmod/doc/examples/example4.rst new file mode 100644 index 00000000000..6cc48479782 --- /dev/null +++ b/pythonmod/doc/examples/example4.rst @@ -0,0 +1,164 @@ +DNS-based language dictionary +=============================== + +This example shows how to create a simple language dictionary based on **DNS** +service within 15 minutes. The translation will be performed using TXT resource records. + +Key parts +----------- + +Initialization +~~~~~~~~~~~~~~~~~~~~~~~ +On **init()** module loads dictionary from a text file containing records in ``word [tab] translation`` format. +:: + + def init(id, cfg): + log_info("pythonmod: dict init") + f = open("examples/dict_data.txt", "r") + ... + +The suitable file can be found at http://slovnik.zcu.cz + +DNS query and word lookup +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Let's define the following format od DNS queries: ``word1[.]word2[.] ... wordN[.]{en,cs}[._dict_.cz.]``. +Word lookup is done by simple ``dict`` lookup from broken DNS request. +Query name is divided into a list of labels. This list is accesible as qname_list attribute. +:: + + aword = ' '.join(qstate.qinfo.qname_list[0:-4]) #skip last four labels + adict = qstate.qinfo.qname_list[-4] #get 4th label from the end + + words = [] #list of words + if (adict == "en") and (aword in en_dict): + words = en_dict[aword] + + if (adict == "cs") and (aword in cz_dict): + words = cz_dict[aword] # CS -> EN + +In the first step, we get a string in the form: ``word1[space]word2[space]...word[space]``. +In the second assignment, fourth label from the end is obtained. This label should contains *"cs"* or *"en"*. +This label determines the direction of translation. + + +Forming of a DNS reply +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +DNS reply is formed only on valid match and added as TXT answer. +:: + + msg = DNSMessage(qstate.qinfo.qname_str, RR_TYPE_TXT, RR_CLASS_IN, PKT_AA) + + for w in words: + msg.answer.append("%s 300 IN TXT \"%s\"" % (qstate.qinfo.qname_str, w.replace("\"", "\\\""))) + + if not msg.set_return_msg(qstate): + qstate.ext_state[id] = MODULE_ERROR + return True + + qstate.return_rcode = RCODE_NOERROR + qstate.ext_state[id] = MODULE_FINISHED + return True + +In the first step, a :class:`DNSMessage` instance is created for a given query *(type TXT)*. +The fourth argument specifies the flags *(authoritative answer)*. +In the second step, we append TXT records containing the translation *(on the right side of RR)*. +Then, the response is finished and ``qstate.return_msg`` contains new response. +If no error, the module sets :attr:`module_qstate.return_rcode` and :attr:`module_qstate.ext_state`. + +**Steps:** + +1. create :class:`DNSMessage` instance +2. append TXT records containing the translation +3. set response to ``qstate.return_msg`` + +Testing +------- + +Run the Unbound server: + +``root@localhost>unbound -dv -c ./test-dict.conf`` + +In case you use own configuration file, don't forget to enable Python module:: + + module-config: "validator python iterator" + +and use valid script path:: + + python-script: "./examples/dict.py" + +The translation from english word *"a bar fly"* to Czech can be done by doing: + +``>>>dig TXT @127.0.0.1 a.bar.fly.en._dict_.cz`` + +:: + + ; (1 server found) + ;; global options: printcmd + ;; Got answer: + ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48691 + ;; flags: aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 + + ;; QUESTION SECTION: + ;a.bar.fly.en._dict_.cz. IN TXT + + ;; ANSWER SECTION: + a.bar.fly.en._dict_.cz. 300 IN TXT "barov\253 povale\232" + + ;; Query time: 5 msec + ;; SERVER: 127.0.0.1#53(127.0.0.1) + ;; WHEN: Mon Jan 01 17:44:18 2009 + ;; MSG SIZE rcvd: 67 + +``>>>dig TXT @127.0.0.1 nic.cs._dict_.cz`` +:: + + ; <<>> DiG 9.5.0-P2 <<>> TXT @127.0.0.1 nic.cs._dict_.cz + ; (1 server found) + ;; global options: printcmd + ;; Got answer: + ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 58710 + ;; flags: aa rd ra; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 0 + + ;; QUESTION SECTION: + ;nic.cs._dict_.cz. IN TXT + + ;; ANSWER SECTION: + nic.cs._dict_.cz. 300 IN TXT "aught" + nic.cs._dict_.cz. 300 IN TXT "naught" + nic.cs._dict_.cz. 300 IN TXT "nihil" + nic.cs._dict_.cz. 300 IN TXT "nix" + nic.cs._dict_.cz. 300 IN TXT "nothing" + nic.cs._dict_.cz. 300 IN TXT "zilch" + + ;; Query time: 0 msec + ;; SERVER: 127.0.0.1#53(127.0.0.1) + ;; WHEN: Mon Jan 01 17:45:39 2009 + ;; MSG SIZE rcvd: 143 + +Proof that the unbound still works as resolver. + +``>>>dig A @127.0.0.1 www.nic.cz`` +:: + + ; (1 server found) + ;; global options: printcmd + ;; Got answer: + ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 19996 + ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 3, ADDITIONAL: 5 + + ;; QUESTION SECTION: + ;www.nic.cz. IN A + + ;; ANSWER SECTION: + www.nic.cz. 1662 IN A 217.31.205.50 + + ;; AUTHORITY SECTION: + ... + +Complete source code +-------------------- + +.. literalinclude:: ../../examples/dict.py + :language: python diff --git a/pythonmod/doc/examples/index.rst b/pythonmod/doc/examples/index.rst new file mode 100644 index 00000000000..6c50225810e --- /dev/null +++ b/pythonmod/doc/examples/index.rst @@ -0,0 +1,15 @@ +.. _Tutorials: + +============================== +Tutorials +============================== + +Here you can find several tutorials which clarify the usage and capabilities of Unbound scriptable interface. + +`Tutorials` + +.. toctree:: + :maxdepth: 2 + :glob: + + example* diff --git a/pythonmod/doc/index.rst b/pythonmod/doc/index.rst new file mode 100644 index 00000000000..fe9bcf42b96 --- /dev/null +++ b/pythonmod/doc/index.rst @@ -0,0 +1,34 @@ +Unbound scriptable interface +======================================= + +Python module for **Unbound** provides easy-to-use flexible solution, +for scripting query events and much more! + +Along with extensible **SWIG** interface, it turns **Unbound** into dynamic *DNS* service +designed for rapid development of *DNS* based applications, like detailed *(per query/domain)* statistics, +monitoring with anything Python can offer *(database backend, http server)*. + +**Key features** + * Rapid dynamic DNS-based application development in **Python** + * Extensible interface with **SWIG** + * Easy to use debugging and analysis tool + * Capable to produce authoritative answers + * Support for logging or doing detailed statistics + * Allows to manipulate with content of cache memory + +Contents +-------- +.. toctree:: + :maxdepth: 2 + + install + examples/index + usecase + modules/index + +Indices and tables +------------------- + +* :ref:`genindex` +* :ref:`search` + diff --git a/pythonmod/doc/install.rst b/pythonmod/doc/install.rst new file mode 100644 index 00000000000..991e2b4becf --- /dev/null +++ b/pythonmod/doc/install.rst @@ -0,0 +1,59 @@ +Installation +=================================== + +**Prerequisites** + +Python 2.4 or higher, SWIG 1.3 or higher, GNU make + +**Download** + +You can download the source codes `here`_. +The latest release is 1.1.1, Jan 15, 2009. + +.. _here: unbound-1.1.1-py.tar.gz + +**Compiling** + +After downloading, you can compile the Unbound library by doing:: + + > tar -xzf unbound-1.1.1-py.tar.gz + > cd unbound-1.1.1 + > ./configure --with-pythonmodule + > make + +You need GNU make to compile sources. +SWIG and Python devel libraries to compile extension module. + +**Testing** + +If the compilation is successful, you can test the extension module by:: + + > cd pythonmod + > make sudo # or "make test" or "make suexec" + +This will start unbound server with language dictionary service (see :ref:`Tutorials`). +In order to test this service, type:: + + > dig TXT @127.0.0.1 aught.en._dict_.cz + +Dig should print this message (czech equivalent of aught):: + + ; <<>> DiG 9.5.0-P2 <<>> TXT @127.0.0.1 aught.en._dict_.cz + ; (1 server found) + ;; global options: printcmd + ;; Got answer: + ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 30085 + ;; flags: aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 + + ;; QUESTION SECTION: + ;aught.en._dict_.cz. IN TXT + + ;; ANSWER SECTION: + aught.en._dict_.cz. 300 IN TXT "nic" + + ;; Query time: 11 msec + ;; SERVER: 127.0.0.1#53(127.0.0.1) + ;; WHEN: Thu Jan 10 16:45:58 2009 + ;; MSG SIZE rcvd: 52 + +The ``pythonmod/examples`` directory contains simple applications written in Python. diff --git a/pythonmod/doc/modules/config.rst b/pythonmod/doc/modules/config.rst new file mode 100644 index 00000000000..1277bceddf9 --- /dev/null +++ b/pythonmod/doc/modules/config.rst @@ -0,0 +1,350 @@ +Configuration interface +======================= + +Currently passed to Python module in init(module_id, cfg). + +config_file +-------------------- + +.. class:: config_file + + This class provides these data attributes: + + .. attribute:: verbosity + + Verbosity level as specified in the config file. + + .. attribute:: stat_interval + + Statistics interval (in seconds). + + .. attribute:: stat_cumulative + + If false, statistics values are reset after printing them. + + .. attribute:: stat_extended + + If true, the statistics are kept in greater detail. + + .. attribute:: num_threads + + Number of threads to create. + + .. attribute:: port + + Port on which queries are answered. + + .. attribute:: do_ip4 + + Do ip4 query support. + + .. attribute:: do_ip6 + + Do ip6 query support. + + .. attribute:: do_udp + + Do udp query support. + + .. attribute:: do_tcp + + Do tcp query support. + + .. attribute:: outgoing_num_ports + + Outgoing port range number of ports (per thread). + + .. attribute:: outgoing_num_tcp + + Number of outgoing tcp buffers per (per thread). + + .. attribute:: incoming_num_tcp + + Number of incoming tcp buffers per (per thread). + + .. attribute:: outgoing_avail_ports + + Allowed udp port numbers, array with 0 if not allowed. + + .. attribute:: msg_buffer_size + + Number of bytes buffer size for DNS messages. + + .. attribute:: msg_cache_size + + Size of the message cache. + + .. attribute:: msg_cache_slabs + + Slabs in the message cache. + + .. attribute:: num_queries_per_thread + + Number of queries every thread can service. + + .. attribute:: jostle_time + + Number of msec to wait before items can be jostled out. + + .. attribute:: rrset_cache_size + + Size of the rrset cache. + + .. attribute:: rrset_cache_slabs + + Slabs in the rrset cache. + + .. attribute:: host_ttl + + Host cache ttl in seconds. + + .. attribute:: lame_ttl + + Host is lame for a zone ttl, in seconds. + + .. attribute:: infra_cache_slabs + + Number of slabs in the infra host cache. + + .. attribute:: infra_cache_numhosts + + Max number of hosts in the infra cache. + + .. attribute:: infra_cache_lame_size + + Max size of lame zones per host in the infra cache. + + .. attribute:: target_fetch_policy + + The target fetch policy for the iterator. + + .. attribute:: if_automatic + + Automatic interface for incoming messages. Uses ipv6 remapping, + and recvmsg/sendmsg ancillary data to detect interfaces, boolean. + + .. attribute:: num_ifs + + Number of interfaces to open. If 0 default all interfaces. + + .. attribute:: ifs + + Interface description strings (IP addresses). + + .. attribute:: num_out_ifs + + Number of outgoing interfaces to open. + If 0 default all interfaces. + + .. attribute:: out_ifs + + Outgoing interface description strings (IP addresses). + + .. attribute:: root_hints + + The root hints. + + .. attribute:: stubs + + The stub definitions, linked list. + + .. attribute:: forwards + + The forward zone definitions, linked list. + + .. attribute:: donotqueryaddrs + + List of donotquery addresses, linked list. + + .. attribute:: acls + + List of access control entries, linked list. + + .. attribute:: donotquery_localhost + + Use default localhost donotqueryaddr entries. + + .. attribute:: harden_short_bufsize + + Harden against very small edns buffer sizes. + + .. attribute:: harden_large_queries + + Harden against very large query sizes. + + .. attribute:: harden_glue + + Harden against spoofed glue (out of zone data). + + .. attribute:: harden_dnssec_stripped + + Harden against receiving no DNSSEC data for trust anchor. + + .. attribute:: harden_referral_path + + Harden the referral path, query for NS,A,AAAA and validate. + + .. attribute:: use_caps_bits_for_id + + Use 0x20 bits in query as random ID bits. + + .. attribute:: private_address + + Strip away these private addrs from answers, no DNS Rebinding. + + .. attribute:: private_domain + + Allow domain (and subdomains) to use private address space. + + .. attribute:: unwanted_threshold + + What threshold for unwanted action. + + .. attribute:: chrootdir + + Chrootdir, if not "" or chroot will be done. + + .. attribute:: username + + Username to change to, if not "". + + .. attribute:: directory + + Working directory. + + .. attribute:: logfile + + Filename to log to. + + .. attribute:: pidfile + + Pidfile to write pid to. + + .. attribute:: use_syslog + + Should log messages be sent to syslogd. + + .. attribute:: hide_identity + + Do not report identity (id.server, hostname.bind). + + .. attribute:: hide_version + + Do not report version (version.server, version.bind). + + .. attribute:: identity + + Identity, hostname is returned if "". + + .. attribute:: version + + Version, package version returned if "". + + .. attribute:: module_conf + + The module configuration string. + + .. attribute:: trust_anchor_file_list + + Files with trusted DS and DNSKEYs in zonefile format, list. + + .. attribute:: trust_anchor_list + + List of trustanchor keys, linked list. + + .. attribute:: trusted_keys_file_list + + Files with trusted DNSKEYs in named.conf format, list. + + .. attribute:: dlv_anchor_file + + DLV anchor file. + + .. attribute:: dlv_anchor_list + + DLV anchor inline. + + .. attribute:: max_ttl + + The number of seconds maximal TTL used for RRsets and messages. + + .. attribute:: val_date_override + + If not 0, this value is the validation date for RRSIGs. + + .. attribute:: bogus_ttl + + This value sets the number of seconds before revalidating bogus. + + .. attribute:: val_clean_additional + + Should validator clean additional section for secure msgs. + + .. attribute:: val_permissive_mode + + Should validator allow bogus messages to go through. + + .. attribute:: val_nsec3_key_iterations + + Nsec3 maximum iterations per key size, string. + + .. attribute:: key_cache_size + + Size of the key cache. + + .. attribute:: key_cache_slabs + + Slabs in the key cache. + + .. attribute:: neg_cache_size + + Size of the neg cache. + + + .. attribute:: local_zones + + Local zones config. + + .. attribute:: local_zones_nodefault + + Local zones nodefault list. + + .. attribute:: local_data + + Local data RRs configged. + + .. attribute:: remote_control_enable + + Remote control section. enable toggle. + + .. attribute:: control_ifs + + The interfaces the remote control should listen on. + + .. attribute:: control_port + + Port number for the control port. + + .. attribute:: server_key_file + + Private key file for server. + + .. attribute:: server_cert_file + + Certificate file for server. + + .. attribute:: control_key_file + + Private key file for unbound-control. + + .. attribute:: control_cert_file + + Certificate file for unbound-control. + + .. attribute:: do_daemonize + + Daemonize, i.e. fork into the background. + + .. attribute:: python_script + + Python script file. diff --git a/pythonmod/doc/modules/env.rst b/pythonmod/doc/modules/env.rst new file mode 100644 index 00000000000..42dbbd1cfa3 --- /dev/null +++ b/pythonmod/doc/modules/env.rst @@ -0,0 +1,412 @@ +Global environment +================== + +Global variables +---------------- + +.. envvar:: mod_env + + Module environment, contains data pointer for module-specific data. + See :class:`pythonmod_env`. + + +Predefined constants +----------------------- + +Module extended state +~~~~~~~~~~~~~~~~~~~~~~~ + +.. data:: module_state_initial + + Initial state - new DNS query. + +.. data:: module_wait_reply + + Waiting for reply to outgoing network query. + +.. data:: module_wait_module + + Module is waiting for another module. + +.. data:: module_wait_subquery + + Module is waiting for sub-query. + +.. data:: module_error + + Module could not finish the query. + +.. data:: module_finished + + Module is finished with query. + +Module event +~~~~~~~~~~~~~ +.. data:: module_event_new + + New DNS query. + +.. data:: module_event_pass + + Query passed by other module. + +.. data:: module_event_reply + + Reply inbound from server. + +.. data:: module_event_noreply + + No reply, timeout or other error. + +.. data:: module_event_capsfail + + Reply is there, but capitalisation check failed. + +.. data:: module_event_moddone + + Next module is done, and its reply is awaiting you. + +.. data:: module_event_error + + Error occured. + +Security status +~~~~~~~~~~~~~~~~ + +.. data:: sec_status_unchecked + + Means that object has yet to be validated. + +.. data:: sec_status_bogus + + Means that the object *(RRset or message)* failed to validate + *(according to local policy)*, but should have validated. + +.. data:: sec_status_indeterminate + + Means that the object is insecure, but not + authoritatively so. Generally this means that the RRset is not + below a configured trust anchor. + +.. data:: sec_status_insecure + + Means that the object is authoritatively known to be + insecure. Generally this means that this RRset is below a trust + anchor, but also below a verified, insecure delegation. + +.. data:: sec_status_secure + + Means that the object (RRset or message) validated according to local policy. + +Resource records (RR sets) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The different RR classes. + + .. data:: RR_CLASS_IN + + Internet. + + .. data:: RR_CLASS_CH + + Chaos. + + .. data:: RR_CLASS_HS + + Hesiod (Dyer 87) + + .. data:: RR_CLASS_NONE + + None class, dynamic update. + + .. data:: RR_CLASS_ANY + + Any class. + + +The different RR types. + + + .. data:: RR_TYPE_A + + A host address. + + .. data:: RR_TYPE_NS + + An authoritative name server. + + .. data:: RR_TYPE_MD + + A mail destination (Obsolete - use MX). + + .. data:: RR_TYPE_MF + + A mail forwarder (Obsolete - use MX). + + .. data:: RR_TYPE_CNAME + + The canonical name for an alias. + + .. data:: RR_TYPE_SOA + + Marks the start of a zone of authority. + + .. data:: RR_TYPE_MB + + A mailbox domain name (EXPERIMENTAL). + + .. data:: RR_TYPE_MG + + A mail group member (EXPERIMENTAL). + + .. data:: RR_TYPE_MR + + A mail rename domain name (EXPERIMENTAL). + + .. data:: RR_TYPE_NULL + + A null RR (EXPERIMENTAL). + + .. data:: RR_TYPE_WKS + + A well known service description. + + .. data:: RR_TYPE_PTR + + A domain name pointer. + + .. data:: RR_TYPE_HINFO + + Host information. + + .. data:: RR_TYPE_MINFO + + Mailbox or mail list information. + + .. data:: RR_TYPE_MX + + Mail exchange. + + .. data:: RR_TYPE_TXT + + Text strings. + + .. data:: RR_TYPE_RP + + RFC1183. + + .. data:: RR_TYPE_AFSDB + + RFC1183. + + .. data:: RR_TYPE_X25 + + RFC1183. + + .. data:: RR_TYPE_ISDN + + RFC1183. + + .. data:: RR_TYPE_RT + + RFC1183. + + .. data:: RR_TYPE_NSAP + + RFC1706. + + .. data:: RR_TYPE_NSAP_PTR + + RFC1348. + + .. data:: RR_TYPE_SIG + + 2535typecode. + + .. data:: RR_TYPE_KEY + + 2535typecode. + + .. data:: RR_TYPE_PX + + RFC2163. + + .. data:: RR_TYPE_GPOS + + RFC1712. + + .. data:: RR_TYPE_AAAA + + IPv6 address. + + .. data:: RR_TYPE_LOC + + LOC record RFC1876. + + .. data:: RR_TYPE_NXT + + 2535typecode. + + .. data:: RR_TYPE_EID + + draft-ietf-nimrod-dns-01.txt. + + .. data:: RR_TYPE_NIMLOC + + draft-ietf-nimrod-dns-01.txt. + + .. data:: RR_TYPE_SRV + + SRV record RFC2782. + + .. data:: RR_TYPE_ATMA + + http://www.jhsoft.com/rfc/af-saa-0069.000.rtf. + + .. data:: RR_TYPE_NAPTR + + RFC2915. + + .. data:: RR_TYPE_KX + + RFC2230. + + .. data:: RR_TYPE_CERT + + RFC2538. + + .. data:: RR_TYPE_A6 + + RFC2874. + + .. data:: RR_TYPE_DNAME + + RFC2672. + + .. data:: RR_TYPE_SINK + + dnsind-kitchen-sink-02.txt. + + .. data:: RR_TYPE_OPT + + Pseudo OPT record. + + .. data:: RR_TYPE_APL + + RFC3123. + + .. data:: RR_TYPE_DS + + draft-ietf-dnsext-delegation. + + .. data:: RR_TYPE_SSHFP + + SSH Key Fingerprint. + + .. data:: RR_TYPE_IPSECKEY + + draft-richardson-ipseckey-rr-11.txt. + + .. data:: RR_TYPE_RRSIG + + draft-ietf-dnsext-dnssec-25. + + .. data:: RR_TYPE_NSEC + .. data:: RR_TYPE_DNSKEY + .. data:: RR_TYPE_DHCID + .. data:: RR_TYPE_NSEC3 + .. data:: RR_TYPE_NSEC3PARAMS + .. data:: RR_TYPE_UINFO + .. data:: RR_TYPE_UID + .. data:: RR_TYPE_GID + .. data:: RR_TYPE_UNSPEC + .. data:: RR_TYPE_TSIG + .. data:: RR_TYPE_IXFR + .. data:: RR_TYPE_AXFR + .. data:: RR_TYPE_MAILB + + A request for mailbox-related records (MB, MG or MR). + + .. data:: RR_TYPE_MAILA + + A request for mail agent RRs (Obsolete - see MX). + + .. data:: RR_TYPE_ANY + + Any type *(wildcard)*. + + .. data:: RR_TYPE_DLV + + RFC 4431, 5074, DNSSEC Lookaside Validation. + +Return codes +~~~~~~~~~~~~ + +Return codes for packets. + +.. data:: RCODE_NOERROR +.. data:: RCODE_FORMERR +.. data:: RCODE_SERVFAIL +.. data:: RCODE_NXDOMAIN +.. data:: RCODE_NOTIMPL +.. data:: RCODE_REFUSED +.. data:: RCODE_YXDOMAIN +.. data:: RCODE_YXRRSET +.. data:: RCODE_NXRRSET +.. data:: RCODE_NOTAUTH +.. data:: RCODE_NOTZONE + +Packet data +~~~~~~~~~~~~ + +.. data:: PKT_QR + + Query - query flag. + +.. data:: PKT_AA + + Authoritative Answer - server flag. + +.. data:: PKT_TC + + Truncated - server flag. + +.. data:: PKT_RD + + Recursion desired - query flag. + +.. data:: PKT_CD + + Checking disabled - query flag. + +.. data:: PKT_RA + + Recursion available - server flag. + +.. data:: PKT_AD + + Authenticated data - server flag. + + +Verbosity value +~~~~~~~~~~~~~~~~ + +.. data:: NO_VERBOSE + + No verbose messages. + +.. data:: VERB_OPS + + Operational information. + +.. data:: VERB_DETAIL + + Detailed information. + +.. data:: VERB_QUERY + + Query level information. + +.. data:: VERB_ALGO + + Algorithm level information. diff --git a/pythonmod/doc/modules/functions.rst b/pythonmod/doc/modules/functions.rst new file mode 100644 index 00000000000..45a469fec04 --- /dev/null +++ b/pythonmod/doc/modules/functions.rst @@ -0,0 +1,120 @@ +Scriptable functions +==================== + +Network +------- + +.. function:: ntohs(netshort) + + This subroutine converts values between the host and network byte order. + Specifically, **ntohs()** converts 16-bit quantities from network byte order to host byte order. + + :param netshort: 16-bit short addr + :rtype: converted addr + + +Cache +----- + +.. function:: storeQueryInCache(qstate, qinfo, msgrep, is_referral) + + Store pending query in local cache. + + :param qstate: :class:`module_qstate` + :param qinfo: :class:`query_info` + :param msgrep: :class:`reply_info` + :param is_referal: integer + :rtype: boolean + +.. function:: invalidateQueryInCache(qstate, qinfo) + + Invalidate record in local cache. + + :param qstate: :class:`module_qstate` + :param qinfo: :class:`query_info` + + +Logging +------- + +.. function:: verbose(level, msg) + + Log a verbose message, pass the level for this message. + No trailing newline is needed. + + :param level: verbosity level for this message, compared to global verbosity setting. + :param msg: string message + +.. function:: log_info(msg) + + Log informational message. No trailing newline is needed. + + :param msg: string message + +.. function:: log_err(msg) + + Log error message. No trailing newline is needed. + + :param msg: string message + +.. function:: log_warn(msg) + + Log warning message. No trailing newline is needed. + + :param msg: string message + +.. function:: log_hex(msg, data, length) + + Log a hex-string to the log. Can be any length. + performs mallocs to do so, slow. But debug useful. + + :param msg: string desc to accompany the hexdump. + :param data: data to dump in hex format. + :param length: length of data. + +.. function:: log_dns_msg(str, qinfo, reply) + + Log DNS message. + + :param str: string message + :param qinfo: :class:`query_info` + :param reply: :class:`reply_info` + +.. function:: log_query_info(verbosity_value, str, qinf) + + Log query information. + + :param verbosity_value: see constants + :param str: string message + :param qinf: :class:`query_info` + +.. function:: regional_log_stats(r) + + Log regional statistics. + + :param r: :class:`regional` + +Debugging +--------- + +.. function:: strextstate(module_ext_state) + + Debug utility, module external qstate to string. + + :param module_ext_state: the state value. + :rtype: descriptive string. + +.. function:: strmodulevent(module_event) + + Debug utility, module event to string. + + :param module_event: the module event value. + :rtype: descriptive string. + +.. function:: ldns_rr_type2str(atype) + + Convert RR type to string. + +.. function:: ldns_rr_class2str(aclass) + + Convert RR class to string. diff --git a/pythonmod/doc/modules/index.rst b/pythonmod/doc/modules/index.rst new file mode 100644 index 00000000000..ff0b956956e --- /dev/null +++ b/pythonmod/doc/modules/index.rst @@ -0,0 +1,11 @@ +Unbound module documentation +======================================= + +.. toctree:: + :maxdepth: 2 + + env + struct + functions + config + diff --git a/pythonmod/doc/modules/struct.rst b/pythonmod/doc/modules/struct.rst new file mode 100644 index 00000000000..c41e10b73df --- /dev/null +++ b/pythonmod/doc/modules/struct.rst @@ -0,0 +1,427 @@ +Scriptable structures +===================== + +module_qstate +----------------------- + +.. class:: module_qstate + + Module state, per query. + + This class provides these data attributes: + + .. attribute:: qinfo + + (:class:`query_info`) Informations about query being answered. Name, RR type, RR class. + + .. attribute:: query_flags + + (uint16) Flags for query. See QF_BIT\_ predefined constants. + + .. attribute:: is_priming + + If this is a (stub or root) priming query (with hints). + + .. attribute:: reply + + comm_reply contains server replies. + + .. attribute:: return_msg + + (:class:`dns_msg`) The reply message, with message for client and calling module (read-only attribute). + Note that if you want to create of modify return_msg you should use :class:`DNSMessage`. + + .. attribute:: return_rcode + + The rcode, in case of error, instead of a reply message. Determines whether the return_msg contains reply. + + .. attribute:: region + + Region for this query. Cleared when query process finishes. + + .. attribute:: curmod + + Which module is executing. + + .. attribute:: ext_state[] + + Module states. + + .. attribute:: env + + Environment for this query. + + .. attribute:: mesh_info + + Mesh related information for this query. + + +query_info +---------------- + +.. class:: query_info + + This class provides these data attributes: + + .. attribute:: qname + + The original question in the wireformat format (e.g. \\x03www\\x03nic\\x02cz\\x00 for www.nic.cz) + + .. attribute:: qname_len + + Lenght of question name (number of bytes). + + .. attribute:: qname_list[] + + The question ``qname`` converted into list of labels (e.g. ['www','nic','cz',''] for www.nic.cz) + + .. attribute:: qname_str + + The question ``qname`` converted into string (e.g. www.nic.cz. for www.nic.cz) + + .. attribute:: qtype + + The class type asked for. See RR_TYPE\_ predefined constants. + + .. attribute:: qtype_str + + The ``qtype`` in display presentation format (string) (e.g 'A' for RR_TYPE_A) + + .. attribute:: qclass + + The question class. See RR_CLASS\_ predefined constants. + + .. attribute:: qclass_str + + The ``qclass`` in display presentation format (string). + +reply_info +-------------------- + +.. class:: reply_info + + This class provides these data attributes: + + .. attribute:: flags + + The flags for the answer, host byte order. + + .. attribute:: qdcount + + Number of RRs in the query section. + If qdcount is not 0, then it is 1, and the data that appears + in the reply is the same as the query_info. + Host byte order. + + .. attribute:: ttl + + TTL of the entire reply (for negative caching). + only for use when there are 0 RRsets in this message. + if there are RRsets, check those instead. + + .. attribute:: security + + The security status from DNSSEC validation of this message. See sec_status\_ predefined constants. + + .. attribute:: an_numrrsets + + Number of RRsets in each section. + The answer section. Add up the RRs in every RRset to calculate + the number of RRs, and the count for the dns packet. + The number of RRs in RRsets can change due to RRset updates. + + .. attribute:: ns_numrrsets + + Count of authority section RRsets + + .. attribute:: ar_numrrsets + + Count of additional section RRsets + + .. attribute:: rrset_count + + Number of RRsets: an_numrrsets + ns_numrrsets + ar_numrrsets + + .. attribute:: rrsets[] + + (:class:`ub_packed_rrset_key`) List of RR sets in the order in which they appear in the reply message. + Number of elements is ancount + nscount + arcount RRsets. + + .. attribute:: ref[] + + (:class:`rrset_ref`) Packed array of ids (see counts) and pointers to packed_rrset_key. + The number equals ancount + nscount + arcount RRsets. + These are sorted in ascending pointer, the locking order. So + this list can be locked (and id, ttl checked), to see if + all the data is available and recent enough. + + +dns_msg +-------------- + +.. class:: dns_msg + + Region allocated message reply + + This class provides these data attributes: + + .. attribute:: qinfo + + (:class:`query_info`) Informations about query. + + .. attribute:: rep + + (:class:`reply_info`) This attribute points to the packed reply structure. + + +packed_rrset_key +---------------------- + +.. class:: packed_rrset_key + + The identifying information for an RRset. + + This class provides these data attributes: + + .. attribute:: dname + + The domain name. If not empty (for ``id = None``) it is allocated, and + contains the wireformat domain name. This dname is not canonicalized. + E.g., the dname contains \\x03www\\x03nic\\x02cz\\x00 for www.nic.cz. + + .. attribute:: dname_len + + Length of the domain name, including last 0 root octet. + + .. attribute:: dname_list[] + + The domain name ``dname`` converted into list of labels (see :attr:`query_info.qname_list`). + + .. attribute:: dname_str + + The domain name ``dname`` converted into string (see :attr:`query_info.qname_str`). + + .. attribute:: flags + + Flags. + + .. attribute:: type + + The rrset type in network format. + + .. attribute:: type_str + + The rrset type in display presentation format. + + .. attribute:: rrset_class + + The rrset class in network format. + + .. attribute:: rrset_class_str + + The rrset class in display presentation format. + +ub_packed_rrset_key +------------------------- + +.. class:: ub_packed_rrset_key + + This structure contains an RRset. A set of resource records that + share the same domain name, type and class. + Due to memory management and threading, the key structure cannot be + deleted, although the data can be. The id can be set to 0 to store and the + structure can be recycled with a new id. + + The :class:`ub_packed_rrset_key` provides these data attributes: + + .. attribute:: entry + + (:class:`lruhash_entry`) Entry into hashtable. Note the lock is never destroyed, + even when this key is retired to the cache. + the data pointer (if not None) points to a :class:`packed_rrset`. + + .. attribute:: id + + The ID of this rrset. unique, based on threadid + sequenceno. + ids are not reused, except after flushing the cache. + zero is an unused entry, and never a valid id. + Check this value after getting entry.lock. + The other values in this struct may only be altered after changing + the id (which needs a writelock on entry.lock). + + .. attribute:: rk + + (:class:`packed_rrset_key`) RR set data. + + +lruhash_entry +------------------------- + +.. class:: lruhash_entry + + The :class:`ub_packed_rrset_key` provides these data attributes: + + .. attribute:: lock + + rwlock for access to the contents of the entry. Note that you cannot change hash and key, if so, you have to delete it to change hash or key. + + .. attribute:: data + + (:class:`packed_rrset_data`) entry data stored in wireformat (RRs and RRsigs). + +packed_rrset_data +----------------------- + +.. class:: packed_rrset_data + + Rdata is stored in wireformat. The dname is stored in wireformat. + + TTLs are stored as absolute values (and could be expired). + + RRSIGs are stored in the arrays after the regular rrs. + + You need the packed_rrset_key to know dname, type, class of the + resource records in this RRset. (if signed the rrsig gives the type too). + + The :class:`packed_rrset_data` provides these data attributes: + + .. attribute:: ttl + + TTL (in seconds like time()) of the RRset. + Same for all RRs see rfc2181(5.2). + + .. attribute:: count + + Number of RRs. + + .. attribute:: rrsig_count + + Number of rrsigs, if 0 no rrsigs. + + .. attribute:: trust + + The trustworthiness of the RRset data. + + .. attribute:: security + + Security status of the RRset data. See sec_status\_ predefined constants. + + .. attribute:: rr_len[] + + Length of every RR's rdata, rr_len[i] is size of rr_data[i]. + + .. attribute:: rr_ttl[] + + TTL of every rr. rr_ttl[i] ttl of rr i. + + .. attribute:: rr_data[] + + Array of RR's rdata (list of strings). The rdata is stored in uncompressed wireformat. + The first 16B of rr_data[i] is rdlength in network format. + + +DNSMessage +---------------- + +.. class:: DNSMessage + + Abstract representation of DNS message. + + **Usage** + + This example shows how to create an authoritative answer response + + :: + + msg = DNSMessage(qstate.qinfo.qname_str, RR_TYPE_A, RR_CLASS_IN, PKT_AA) + + #append RR + if (qstate.qinfo.qtype == RR_TYPE_A) or (qstate.qinfo.qtype == RR_TYPE_ANY): + msg.answer.append("%s 10 IN A 127.0.0.1" % qstate.qinfo.qname_str) + + #set qstate.return_msg + if not msg.set_return_msg(qstate): + raise Exception("Can't create response") + + The :class:`DNSMessage` provides these methods and data attributes: + + .. method:: __init__(self, rr_name, rr_type, rr_class = RR_CLASS_IN, query_flags = 0, default_ttl = 0) + + Prepares an answer (DNS packet) from qiven information. Query flags are combination of PKT_xx contants. + + .. method:: set_return_msg(self, qstate) + + This method fills qstate return message according to the given informations. + It takes lists of RRs in each section of answer, created necessray RRsets in wire format and store the result in :attr:`qstate.return_msg`. + Returns 1 if OK. + + .. attribute:: rr_name + + RR name of question. + + .. attribute:: rr_type + + RR type of question. + + .. attribute:: rr_class + + RR class of question. + + .. attribute:: default_ttl + + Default time-to-live. + + .. attribute:: query_flags + + Query flags. See PKT\_ predefined constants. + + .. attribute:: question[] + + List of resource records that should appear (in the same order) in question section of answer. + + .. attribute:: answer[] + + List of resource records that should appear (in the same order) in answer section of answer. + + .. attribute:: authority[] + + List of resource records that should appear (in the same order) in authority section of answer. + + .. attribute:: additional[] + + List of resource records that should appear (in the same order) in additional section of answer. + +pythonmod_env +----------------------- + +.. class:: pythonmod_env + + Global state for the module. + + This class provides these data attributes: + + .. attribute:: data + + Here you can keep your own data shared across each thread. + + .. attribute:: fname + + Python script filename. + + .. attribute:: qstate + + Module query state. + +pythonmod_qstate +----------------------- + +.. class:: pythonmod_qstate + + Per query state for the iterator module. + + This class provides these data attributes: + + .. attribute:: data + + Here you can keep your own private data (each thread has own data object). + diff --git a/pythonmod/doc/usecase.rst b/pythonmod/doc/usecase.rst new file mode 100644 index 00000000000..7a77349f1e4 --- /dev/null +++ b/pythonmod/doc/usecase.rst @@ -0,0 +1,38 @@ +Use cases (examples) +==================== + +Dynamic DNS Service discovery (DNS-SD_) +------------------------------------------- +Synchronized with database engine, for example *MySQL*. + +.. _DNS-SD: http://www.dns-sd.org/ + +Firewall control +---------------- +Control firewall (e.g. enable incomming SSH connection) with DNS query signed with private key. +So firewall can blocks every service during normal operation. + +Scriptable DNS-based blacklist (DNS-BL_) +------------------------------------------- +Scripted in Python with already provided features, takes advantage of DNS reply, because +almost every mail server supports DNS based blacklisting. + +.. _DNS-BL: http://www.dnsbl.org + +DNS based Wake-On-Lan +--------------------- +Controled by secured queries secured with private key. + +Dynamic translation service +--------------------------- +DNS request can be translated to virtualy any answer, that's easy to implement in client side +because of many DNS libraries available. + +Examples : + * **Dictionary** - using *IDN* for non-ascii strings transfer, ``dig TXT slovo.en._dict_.nic.cz`` returns translation of "slovo" to EN. + * **Translation** - Extends *DNS-SD*, for example DNS to Jabber to find out people logged in. + * **Exchange rate calculator** - ``dig TXT 1000.99.czk.eur._rates_.nic.cz`` returns the given sum (1000.99 CZK) in EURs. + +Dynamic ENUM service +-------------------- +Support for redirection, synchronization, etc. diff --git a/pythonmod/examples/calc.py b/pythonmod/examples/calc.py new file mode 100644 index 00000000000..3230e37e3ee --- /dev/null +++ b/pythonmod/examples/calc.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +''' + calc.py: DNS-based calculator + + Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz) + Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) + + 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 organization 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 REGENTS OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +''' + +#Try: dig @localhost 1*25._calc_.cz. + +def init(id, cfg): return True +def deinit(id): return True +def inform_super(id, qstate, superqstate, qdata): return True + +def operate(id, event, qstate, qdata): + + if (event == MODULE_EVENT_NEW) or (event == MODULE_EVENT_PASS): + + if qstate.qinfo.qname_str.endswith("._calc_.cz."): + try: + res = eval(''.join(qstate.qinfo.qname_list[0:-3])) + except: + res = "exception" + + msg = DNSMessage(qstate.qinfo.qname_str, RR_TYPE_TXT, RR_CLASS_IN, PKT_QR | PKT_RA | PKT_AA) #, 300) + msg.answer.append("%s 300 IN TXT \"%s\"" % (qstate.qinfo.qname_str,res)) + if not msg.set_return_msg(qstate): + qstate.ext_state[id] = MODULE_ERROR + return True + + qstate.return_rcode = RCODE_NOERROR + qstate.ext_state[id] = MODULE_FINISHED + return True + + else: + #Pass on the unknown query to the iterator + qstate.ext_state[id] = MODULE_WAIT_MODULE + return True + + elif event == MODULE_EVENT_MODDONE: + #the iterator has finished + qstate.ext_state[id] = MODULE_FINISHED + return True + + log_err("pythonmod: Unknown event") + qstate.ext_state[id] = MODULE_ERROR + return True + diff --git a/pythonmod/examples/dict.py b/pythonmod/examples/dict.py new file mode 100644 index 00000000000..c8088a89c2f --- /dev/null +++ b/pythonmod/examples/dict.py @@ -0,0 +1,121 @@ +# -*- coding: utf-8 -*- +''' + calc.py: DNS-based czech-english dictionary + + Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz) + Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) + + 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 organization 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 REGENTS OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +''' +import os +cz_dict = {} +en_dict = {} + +def init(id, cfg): + log_info("pythonmod: dict init") + f = open("examples/dict_data.txt", "r") + try: + for line in f: + if line.startswith('#'): + continue + itm = line.split("\t", 3) + if len(itm) < 2: + continue + en,cs = itm[0:2] + + if not (cs in cz_dict): + cz_dict[cs] = [en] # [cs] = en + else: + cz_dict[cs].append(en) # [cs] = en + + if not (en in en_dict): + en_dict[en] = [cs] # [en] = cs + else: + en_dict[en].append(cs) # [en] = cs + + finally: + f.close() + return True + +def deinit(id): + log_info("pythonmod: dict deinit") + return True + +def operate(id, event, qstate, qdata): + if (event == MODULE_EVENT_NEW) or (event == MODULE_EVENT_PASS): + + if qstate.qinfo.qname_str.endswith("._dict_.cz."): + + aword = ' '.join(qstate.qinfo.qname_list[0:-4]) + adict = qstate.qinfo.qname_list[-4] + + log_info("pythonmod: dictionary look up; word:%s dict:%s" % (aword,adict)) + + words = [] + if (adict == "en") and (aword in en_dict): + words = en_dict[aword] # EN -> CS + if (adict == "cs") and (aword in cz_dict): + words = cz_dict[aword] # CS -> EN + + if len(words) and ((qstate.qinfo.qtype == RR_TYPE_TXT) or (qstate.qinfo.qtype == RR_TYPE_ANY)): + + msg = DNSMessage(qstate.qinfo.qname_str, RR_TYPE_TXT, RR_CLASS_IN, PKT_RD | PKT_RA | PKT_AA) + for w in words: + msg.answer.append("%s 300 IN TXT \"%s\"" % (qstate.qinfo.qname_str,w.replace("\"","\\\""))) + + if not msg.set_return_msg(qstate): + qstate.ext_state[id] = MODULE_ERROR + return True + + qstate.return_rcode = RCODE_NOERROR + qstate.ext_state[id] = MODULE_FINISHED + return True + + else: + qstate.return_rcode = RCODE_SERVFAIL + qstate.ext_state[id] = MODULE_FINISHED + return True + + else: #Pass on the unknown query to the iterator + qstate.ext_state[id] = MODULE_WAIT_MODULE + return True + + elif event == MODULE_EVENT_MODDONE: #the iterator has finished + #we don't need modify result + qstate.ext_state[id] = MODULE_FINISHED + return True + + log_err("pythonmod: Unknown event") + qstate.ext_state[id] = MODULE_ERROR + return True + +def inform_super(id, qstate, superqstate, qdata): + return True + diff --git a/pythonmod/examples/dict_data.txt b/pythonmod/examples/dict_data.txt new file mode 100644 index 00000000000..04cd3badffa --- /dev/null +++ b/pythonmod/examples/dict_data.txt @@ -0,0 +1,6 @@ +* * web +computer potaov adj: Zdenk Bro +computer pota n: +domain domna n: Zdenk Bro +query otaznk n: Zdenk Bro +network s n: [it.] potaov diff --git a/pythonmod/examples/log.py b/pythonmod/examples/log.py new file mode 100644 index 00000000000..c17106b0f26 --- /dev/null +++ b/pythonmod/examples/log.py @@ -0,0 +1,119 @@ +import os +''' + calc.py: Response packet logger + + Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz) + Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) + + 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 organization 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 REGENTS OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +''' + +def dataHex(data, prefix=""): + """Converts binary string data to display representation form""" + res = "" + for i in range(0, (len(data)+15)/16): + res += "%s0x%02X | " % (prefix, i*16) + d = map(lambda x:ord(x), data[i*16:i*16+17]) + for ch in d: + res += "%02X " % ch + for i in range(0,17-len(d)): + res += " " + res += "| " + for ch in d: + if (ch < 32) or (ch > 127): + res += ". " + else: + res += "%c " % ch + res += "\n" + return res + +def logDnsMsg(qstate): + """Logs response""" + + r = qstate.return_msg.rep + q = qstate.return_msg.qinfo + + print "-"*100 + print("Query: %s, type: %s (%d), class: %s (%d) " % ( + qstate.qinfo.qname_str, qstate.qinfo.qtype_str, qstate.qinfo.qtype, + qstate.qinfo.qclass_str, qstate.qinfo.qclass)) + print "-"*100 + print "Return reply :: flags: %04X, QDcount: %d, Security:%d, TTL=%d" % (r.flags, r.qdcount, r.security, r.ttl) + print " qinfo :: qname: %s %s, qtype: %s, qclass: %s" % (str(q.qname_list), q.qname_str, q.qtype_str, q.qclass_str) + + if (r): + print "Reply:" + for i in range(0, r.rrset_count): + rr = r.rrsets[i] + + rk = rr.rk + print i,":",rk.dname_list, rk.dname_str, "flags: %04X" % rk.flags, + print "type:",rk.type_str,"(%d)" % ntohs(rk.type), "class:",rk.rrset_class_str,"(%d)" % ntohs(rk.rrset_class) + + d = rr.entry.data + for j in range(0,d.count+d.rrsig_count): + print " ",j,":","TTL=",d.rr_ttl[j], + if (j >= d.count): print "rrsig", + print + print dataHex(d.rr_data[j]," ") + + print "-"*100 + +def init(id, cfg): + log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, cfg.port, cfg.python_script)) + return True + +def deinit(id): + log_info("pythonmod: deinit called, module id is %d" % id) + return True + +def inform_super(id, qstate, superqstate, qdata): + return True + +def operate(id, event, qstate, qdata): + log_info("pythonmod: operate called, id: %d, event:%s" % (id, strmodulevent(event))) + + if (event == MODULE_EVENT_NEW) or (event == MODULE_EVENT_PASS): + #Pass on the new event to the iterator + qstate.ext_state[id] = MODULE_WAIT_MODULE + return True + + if event == MODULE_EVENT_MODDONE: + #Iterator finished, show response (if any) + + if (qstate.return_msg): + logDnsMsg(qstate) + + qstate.ext_state[id] = MODULE_FINISHED + return True + + qstate.ext_state[id] = MODULE_ERROR + return True + diff --git a/pythonmod/examples/resgen.py b/pythonmod/examples/resgen.py new file mode 100644 index 00000000000..804c0bd1d35 --- /dev/null +++ b/pythonmod/examples/resgen.py @@ -0,0 +1,73 @@ +''' + resgen.py: This example shows how to generate authoritative response + + Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz) + Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) + + 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 organization 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 REGENTS OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +''' +def init(id, cfg): return True + +def deinit(id): return True + +def inform_super(id, qstate, superqstate, qdata): return True + +def operate(id, event, qstate, qdata): + if (event == MODULE_EVENT_NEW) or (event == MODULE_EVENT_PASS): + if (qstate.qinfo.qname_str.endswith(".localdomain.")): #query name ends with localdomain + #create instance of DNS message (packet) with given parameters + msg = DNSMessage(qstate.qinfo.qname_str, RR_TYPE_A, RR_CLASS_IN, PKT_QR | PKT_RA | PKT_AA) + #append RR + if (qstate.qinfo.qtype == RR_TYPE_A) or (qstate.qinfo.qtype == RR_TYPE_ANY): + msg.answer.append("%s 10 IN A 127.0.0.1" % qstate.qinfo.qname_str) + #set qstate.return_msg + if not msg.set_return_msg(qstate): + qstate.ext_state[id] = MODULE_ERROR + return True + + #we don't need validation, result is valid + qstate.return_msg.rep.security = 2 + + qstate.return_rcode = RCODE_NOERROR + qstate.ext_state[id] = MODULE_FINISHED + return True + else: + #pass the query to validator + qstate.ext_state[id] = MODULE_WAIT_MODULE + return True + + if event == MODULE_EVENT_MODDONE: + log_info("pythonmod: iterator module done") + qstate.ext_state[id] = MODULE_FINISHED + return True + + log_err("pythonmod: bad event") + qstate.ext_state[id] = MODULE_ERROR + return True diff --git a/pythonmod/examples/resip.py b/pythonmod/examples/resip.py new file mode 100644 index 00000000000..6bcac7252cd --- /dev/null +++ b/pythonmod/examples/resip.py @@ -0,0 +1,96 @@ +''' + resip.py: This example shows how to generate authoritative response + and how to find out the IP address of a client + + Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz) + Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) + + 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 organization 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 REGENTS OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + + Usage: + + dig @127.0.0.1 -t TXT what.is.my.ip. +''' + +def init(id, cfg): return True + +def deinit(id): return True + +def inform_super(id, qstate, superqstate, qdata): return True + +def operate(id, event, qstate, qdata): + print "Operate", event,"state:",qstate + + # Please note that if this module blocks, by moving to the validator + # to validate or iterator to lookup or spawn a subquery to look up, + # then, other incoming queries are queued up onto this module and + # all of them receive the same reply. + # You can inspect the cache. + + if (event == MODULE_EVENT_NEW) or (event == MODULE_EVENT_PASS): + if (qstate.qinfo.qname_str.endswith("what.is.my.ip.")): #query name ends with localdomain + #create instance of DNS message (packet) with given parameters + msg = DNSMessage(qstate.qinfo.qname_str, RR_TYPE_TXT, RR_CLASS_IN, PKT_QR | PKT_RA | PKT_AA) + #append RR + if (qstate.qinfo.qtype == RR_TYPE_TXT) or (qstate.qinfo.qtype == RR_TYPE_ANY): + rl = qstate.mesh_info.reply_list + while (rl): + if rl.query_reply: + q = rl.query_reply + # The TTL of 0 is mandatory, otherwise it ends up in + # the cache, and is returned to other IP addresses. + msg.answer.append("%s 0 IN TXT \"%s %d (%s)\"" % (qstate.qinfo.qname_str, q.addr,q.port,q.family)) + rl = rl.next + + #set qstate.return_msg + if not msg.set_return_msg(qstate): + qstate.ext_state[id] = MODULE_ERROR + return True + + #we don't need validation, result is valid + qstate.return_msg.rep.security = 2 + + qstate.return_rcode = RCODE_NOERROR + qstate.ext_state[id] = MODULE_FINISHED + return True + else: + #pass the query to validator + qstate.ext_state[id] = MODULE_WAIT_MODULE + return True + + if event == MODULE_EVENT_MODDONE: + log_info("pythonmod: iterator module done") + qstate.ext_state[id] = MODULE_FINISHED + return True + + log_err("pythonmod: bad event") + qstate.ext_state[id] = MODULE_ERROR + return True diff --git a/pythonmod/examples/resmod.py b/pythonmod/examples/resmod.py new file mode 100644 index 00000000000..cf392e4da27 --- /dev/null +++ b/pythonmod/examples/resmod.py @@ -0,0 +1,88 @@ +''' + resmod.py: This example shows how to modify the response from iterator + + Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz) + Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) + + 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 organization 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 REGENTS OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +''' + +def init(id, cfg): return True + +def deinit(id): return True + +def inform_super(id, qstate, superqstate, qdata): return True + +def setTTL(qstate, ttl): + """Updates return_msg TTL and the TTL of all the RRs""" + if qstate.return_msg: + qstate.return_msg.rep.ttl = ttl + if (qstate.return_msg.rep): + for i in range(0,qstate.return_msg.rep.rrset_count): + d = qstate.return_msg.rep.rrsets[i].entry.data + for j in range(0,d.count+d.rrsig_count): + d.rr_ttl[j] = ttl + +def operate(id, event, qstate, qdata): + if (event == MODULE_EVENT_NEW) or (event == MODULE_EVENT_PASS): + #pass the query to validator + qstate.ext_state[id] = MODULE_WAIT_MODULE + return True + + if event == MODULE_EVENT_MODDONE: + log_info("pythonmod: iterator module done") + + if not qstate.return_msg: + qstate.ext_state[id] = MODULE_FINISHED + return True + + #modify the response + + qdn = qstate.qinfo.qname_str + if qdn.endswith(".nic.cz."): + #invalidate response in cache added by iterator + #invalidateQueryInCache(qstate, qstate.return_msg.qinfo) + + #modify TTL to 10 secs and store response in cache + #setTTL(qstate, 5) + #if not storeQueryInCache(qstate, qstate.return_msg.qinfo, qstate.return_msg.rep, 0): + # qstate.ext_state[id] = MODULE_ERROR + # return False + + #modify TTL of response, which will be send to a) validator and then b) client + setTTL(qstate, 10) + qstate.return_rcode = RCODE_NOERROR + + qstate.ext_state[id] = MODULE_FINISHED + return True + + log_err("pythonmod: bad event") + qstate.ext_state[id] = MODULE_ERROR + return True diff --git a/pythonmod/interface.i b/pythonmod/interface.i new file mode 100644 index 00000000000..903563658b0 --- /dev/null +++ b/pythonmod/interface.i @@ -0,0 +1,889 @@ +/* + * interface.i: unbound python module + */ + +%module unboundmodule +%{ +/** + * \file + * This is the interface between the unbound server and a python module + * called to perform operations on queries. + */ + #include + #include + #include + #include + #include + #include "config.h" + #include "util/log.h" + #include "util/module.h" + #include "util/netevent.h" + #include "util/regional.h" + #include "util/config_file.h" + #include "util/data/msgreply.h" + #include "util/data/packed_rrset.h" + #include "util/data/dname.h" + #include "util/storage/lruhash.h" + #include "services/cache/dns.h" + #include "services/mesh.h" +%} + +%include "stdint.i" // uint_16_t can be known type now + +%inline %{ + //converts [len][data][len][data][0] string to a List of labels (PyStrings) + PyObject* GetNameAsLabelList(const char* name, int len) { + PyObject* list; + int cnt=0, i; + + i = 0; + while (i < len) { + i += name[i] + 1; + cnt++; + } + + list = PyList_New(cnt); + i = 0; cnt = 0; + while (i < len) { + PyList_SetItem(list, cnt, PyString_FromStringAndSize(name + i + 1, name[i])); + i += name[i] + 1; + cnt++; + } + return list; + } +%} + +/* ************************************************************************************ * + Structure query_info + * ************************************************************************************ */ +/* Query info */ +%ignore query_info::qname; +%ignore query_info::qname_len; + + +struct query_info { + %immutable; + char* qname; + size_t qname_len; + uint16_t qtype; + uint16_t qclass; + %mutable; +}; + +%inline %{ + enum enum_rr_class { + RR_CLASS_IN = 1, + RR_CLASS_CH = 3, + RR_CLASS_HS = 4, + RR_CLASS_NONE = 254, + RR_CLASS_ANY = 255, + }; + + enum enum_rr_type { + RR_TYPE_A = 1, + RR_TYPE_NS = 2, + RR_TYPE_MD = 3, + RR_TYPE_MF = 4, + RR_TYPE_CNAME = 5, + RR_TYPE_SOA = 6, + RR_TYPE_MB = 7, + RR_TYPE_MG = 8, + RR_TYPE_MR = 9, + RR_TYPE_NULL = 10, + RR_TYPE_WKS = 11, + RR_TYPE_PTR = 12, + RR_TYPE_HINFO = 13, + RR_TYPE_MINFO = 14, + RR_TYPE_MX = 15, + RR_TYPE_TXT = 16, + RR_TYPE_RP = 17, + RR_TYPE_AFSDB = 18, + RR_TYPE_X25 = 19, + RR_TYPE_ISDN = 20, + RR_TYPE_RT = 21, + RR_TYPE_NSAP = 22, + RR_TYPE_NSAP_PTR = 23, + RR_TYPE_SIG = 24, + RR_TYPE_KEY = 25, + RR_TYPE_PX = 26, + RR_TYPE_GPOS = 27, + RR_TYPE_AAAA = 28, + RR_TYPE_LOC = 29, + RR_TYPE_NXT = 30, + RR_TYPE_EID = 31, + RR_TYPE_NIMLOC = 32, + RR_TYPE_SRV = 33, + RR_TYPE_ATMA = 34, + RR_TYPE_NAPTR = 35, + RR_TYPE_KX = 36, + RR_TYPE_CERT = 37, + RR_TYPE_A6 = 38, + RR_TYPE_DNAME = 39, + RR_TYPE_SINK = 40, + RR_TYPE_OPT = 41, + RR_TYPE_APL = 42, + RR_TYPE_DS = 43, + RR_TYPE_SSHFP = 44, + RR_TYPE_IPSECKEY = 45, + RR_TYPE_RRSIG = 46, + RR_TYPE_NSEC = 47, + RR_TYPE_DNSKEY = 48, + RR_TYPE_DHCID = 49, + RR_TYPE_NSEC3 = 50, + RR_TYPE_NSEC3PARAMS = 51, + RR_TYPE_UINFO = 100, + RR_TYPE_UID = 101, + RR_TYPE_GID = 102, + RR_TYPE_UNSPEC = 103, + RR_TYPE_TSIG = 250, + RR_TYPE_IXFR = 251, + RR_TYPE_AXFR = 252, + RR_TYPE_MAILB = 253, + RR_TYPE_MAILA = 254, + RR_TYPE_ANY = 255, + RR_TYPE_DLV = 32769, + }; + + PyObject* _get_qname(struct query_info* q) { + return PyString_FromStringAndSize((char*)q->qname, q->qname_len); + } + + PyObject* _get_qname_components(struct query_info* q) { + return GetNameAsLabelList((const char*)q->qname, q->qname_len); + } +%} + +%inline %{ + PyObject* dnameAsStr(const char* dname) { + char buf[LDNS_MAX_DOMAINLEN+1]; + buf[0] = '\0'; + dname_str((uint8_t*)dname, buf); + return PyString_FromString(buf); + } +%} + +%extend query_info { + %pythoncode %{ + def _get_qtype_str(self): return ldns_rr_type2str(self.qtype) + __swig_getmethods__["qtype_str"] = _get_qtype_str + if _newclass:qtype_str = _swig_property(_get_qtype_str) + + def _get_qclass_str(self): return ldns_rr_class2str(self.qclass) + __swig_getmethods__["qclass_str"] = _get_qclass_str + if _newclass:qclass_str = _swig_property(_get_qclass_str) + + __swig_getmethods__["qname"] = _unboundmodule._get_qname + if _newclass:qname = _swig_property(_unboundmodule._get_qname) + + __swig_getmethods__["qname_list"] = _unboundmodule._get_qname_components + if _newclass:qname_list = _swig_property(_unboundmodule._get_qname_components) + + def _get_qname_str(self): return dnameAsStr(self.qname) + __swig_getmethods__["qname_str"] = _get_qname_str + if _newclass:qname_str = _swig_property(_get_qname_str) + %} +} + +/* ************************************************************************************ * + Structure packed_rrset_key + * ************************************************************************************ */ +%ignore packed_rrset_key::dname; +%ignore packed_rrset_key::dname_len; + +/* RRsets */ +struct packed_rrset_key { + %immutable; + char* dname; + size_t dname_len; + uint32_t flags; + uint16_t type; //rrset type in network format + uint16_t rrset_class; //rrset class in network format + %mutable; +}; + +//This subroutine converts values between the host and network byte order. +//Specifically, ntohs() converts 16-bit quantities from network byte order to host byte order. +uint16_t ntohs(uint16_t netshort); + +%inline %{ + PyObject* _get_dname(struct packed_rrset_key* k) { + return PyString_FromStringAndSize((char*)k->dname, k->dname_len); + } + PyObject* _get_dname_components(struct packed_rrset_key* k) { + return GetNameAsLabelList((char*)k->dname, k->dname_len); + } +%} + +%extend packed_rrset_key { + %pythoncode %{ + def _get_type_str(self): return ldns_rr_type2str(_unboundmodule.ntohs(self.type)) + __swig_getmethods__["type_str"] = _get_type_str + if _newclass:type_str = _swig_property(_get_type_str) + + def _get_class_str(self): return ldns_rr_class2str(_unboundmodule.ntohs(self.rrset_class)) + __swig_getmethods__["rrset_class_str"] = _get_class_str + if _newclass:rrset_class_str = _swig_property(_get_class_str) + + __swig_getmethods__["dname"] = _unboundmodule._get_dname + if _newclass:dname = _swig_property(_unboundmodule._get_dname) + + __swig_getmethods__["dname_list"] = _unboundmodule._get_dname_components + if _newclass:dname_list = _swig_property(_unboundmodule._get_dname_components) + + def _get_dname_str(self): return dnameAsStr(self.dname) + __swig_getmethods__["dname_str"] = _get_dname_str + if _newclass:dname_str = _swig_property(_get_dname_str) + %} +} + +#if defined(SWIGWORDSIZE64) +typedef long int rrset_id_t; +#else +typedef long long int rrset_id_t; +#endif + +struct ub_packed_rrset_key { + struct lruhash_entry entry; + rrset_id_t id; + struct packed_rrset_key rk; +}; + +struct lruhash_entry { + lock_rw_t lock; + struct lruhash_entry* overflow_next; + struct lruhash_entry* lru_next; + struct lruhash_entry* lru_prev; + hashvalue_t hash; + void* key; + struct packed_rrset_data* data; +}; + +%ignore packed_rrset_data::rr_len; +%ignore packed_rrset_data::rr_ttl; +%ignore packed_rrset_data::rr_data; + +struct packed_rrset_data { + uint32_t ttl; //TTL (in seconds like time()) + + size_t count; //number of rrs + size_t rrsig_count; //number of rrsigs + + enum rrset_trust trust; + enum sec_status security; + + size_t* rr_len; //length of every rr's rdata + uint32_t *rr_ttl; //ttl of every rr + uint8_t** rr_data; //array of pointers to every rr's rdata; The rr_data[i] rdata is stored in uncompressed wireformat. +}; + +%pythoncode %{ + class RRSetData_RRLen: + def __init__(self, obj): self.obj = obj + def __getitem__(self, index): return _unboundmodule._get_data_rr_len(self.obj, index) + def __len__(self): return obj.count + obj.rrsig_count + class RRSetData_RRTTL: + def __init__(self, obj): self.obj = obj + def __getitem__(self, index): return _unboundmodule._get_data_rr_ttl(self.obj, index) + def __setitem__(self, index, value): _unboundmodule._set_data_rr_ttl(self.obj, index, value) + def __len__(self): return obj.count + obj.rrsig_count + class RRSetData_RRData: + def __init__(self, obj): self.obj = obj + def __getitem__(self, index): return _unboundmodule._get_data_rr_data(self.obj, index) + def __len__(self): return obj.count + obj.rrsig_count +%} + +%inline %{ + PyObject* _get_data_rr_len(struct packed_rrset_data* d, int idx) { + if ((d != NULL) && (idx >= 0) && + ((size_t)idx < (d->count+d->rrsig_count))) + return PyInt_FromLong(d->rr_len[idx]); + return Py_None; + } + void _set_data_rr_ttl(struct packed_rrset_data* d, int idx, uint32_t ttl) + { + if ((d != NULL) && (idx >= 0) && + ((size_t)idx < (d->count+d->rrsig_count))) + d->rr_ttl[idx] = ttl; + } + PyObject* _get_data_rr_ttl(struct packed_rrset_data* d, int idx) { + if ((d != NULL) && (idx >= 0) && + ((size_t)idx < (d->count+d->rrsig_count))) + return PyInt_FromLong(d->rr_ttl[idx]); + return Py_None; + } + PyObject* _get_data_rr_data(struct packed_rrset_data* d, int idx) { + if ((d != NULL) && (idx >= 0) && + ((size_t)idx < (d->count+d->rrsig_count))) + return PyString_FromStringAndSize((char*)d->rr_data[idx], + d->rr_len[idx]); + return Py_None; + } +%} + +%extend packed_rrset_data { + %pythoncode %{ + def _get_data_rr_len(self): return RRSetData_RRLen(self) + __swig_getmethods__["rr_len"] = _get_data_rr_len + if _newclass:rr_len = _swig_property(_get_data_rr_len) + def _get_data_rr_ttl(self): return RRSetData_RRTTL(self) + __swig_getmethods__["rr_ttl"] =_get_data_rr_ttl + if _newclass:rr_len = _swig_property(_get_data_rr_ttl) + def _get_data_rr_data(self): return RRSetData_RRData(self) + __swig_getmethods__["rr_data"] = _get_data_rr_data + if _newclass:rr_len = _swig_property(_get_data_rr_data) + %} +} + +/* ************************************************************************************ * + Structure reply_info + * ************************************************************************************ */ +/* Messages */ +%ignore reply_info::rrsets; +%ignore reply_info::ref; + +struct reply_info { + uint16_t flags; + uint16_t qdcount; + uint32_t ttl; + uint32_t prefetch_ttl; + + uint16_t authoritative; + enum sec_status security; + + size_t an_numrrsets; + size_t ns_numrrsets; + size_t ar_numrrsets; + size_t rrset_count; // an_numrrsets + ns_numrrsets + ar_numrrsets + + struct ub_packed_rrset_key** rrsets; + struct rrset_ref ref[1]; //? +}; + +struct rrset_ref { + struct ub_packed_rrset_key* key; + rrset_id_t id; +}; + +struct dns_msg { + struct query_info qinfo; + struct reply_info *rep; +}; + +%pythoncode %{ + class ReplyInfo_RRSet: + def __init__(self, obj): self.obj = obj + def __getitem__(self, index): return _unboundmodule._rrset_rrsets_get(self.obj, index) + def __len__(self): return obj.rrset_count + + class ReplyInfo_Ref: + def __init__(self, obj): self.obj = obj + def __getitem__(self, index): return _unboundmodule._rrset_ref_get(self.obj, index) + def __len__(self): return obj.rrset_count +%} + +%inline %{ + struct ub_packed_rrset_key* _rrset_rrsets_get(struct reply_info* r, int idx) { + if ((r != NULL) && (idx >= 0) && ((size_t)idx < r->rrset_count)) + return r->rrsets[idx]; + return NULL; + } + + struct rrset_ref* _rrset_ref_get(struct reply_info* r, int idx) { + if ((r != NULL) && (idx >= 0) && ((size_t)idx < r->rrset_count)) { +//printf("_rrset_ref_get: %lX key:%lX\n", r->ref + idx, r->ref[idx].key); + return &(r->ref[idx]); +// return &(r->ref[idx]); + } +//printf("_rrset_ref_get: NULL\n"); + return NULL; + } +%} + +%extend reply_info { + %pythoncode %{ + def _rrset_ref_get(self): return ReplyInfo_Ref(self) + __swig_getmethods__["ref"] = _rrset_ref_get + if _newclass:ref = _swig_property(_rrset_ref_get) + + def _rrset_rrsets_get(self): return ReplyInfo_RRSet(self) + __swig_getmethods__["rrsets"] = _rrset_rrsets_get + if _newclass:rrsets = _swig_property(_rrset_rrsets_get) + %} +} + +/* ************************************************************************************ * + Structure mesh_state + * ************************************************************************************ */ +struct mesh_state { + struct mesh_reply* reply_list; +}; + +struct mesh_reply { + struct mesh_reply* next; + struct comm_reply query_reply; +}; + +struct comm_reply { + +}; + +%inline %{ + + PyObject* _comm_reply_addr_get(struct comm_reply* reply) { + char dest[64]; + reply_addr2str(reply, dest, 64); + if (dest[0] == 0) + return Py_None; + return PyString_FromString(dest); + } + + PyObject* _comm_reply_family_get(struct comm_reply* reply) { + + int af = (int)((struct sockaddr_in*) &(reply->addr))->sin_family; + + switch(af) { + case AF_INET: return PyString_FromString("ip4"); + case AF_INET6: return PyString_FromString("ip6"); + case AF_UNIX: return PyString_FromString("unix"); + } + + return Py_None; + } + + PyObject* _comm_reply_port_get(struct comm_reply* reply) { + uint16_t port; + port = ntohs(((struct sockaddr_in*)&(reply->addr))->sin_port); + return PyInt_FromLong(port); + } + +%} + +%extend comm_reply { + %pythoncode %{ + def _addr_get(self): return _comm_reply_addr_get(self) + __swig_getmethods__["addr"] = _addr_get + if _newclass:addr = _swig_property(_addr_get) + + def _port_get(self): return _comm_reply_port_get(self) + __swig_getmethods__["port"] = _port_get + if _newclass:port = _swig_property(_port_get) + + def _family_get(self): return _comm_reply_family_get(self) + __swig_getmethods__["family"] = _family_get + if _newclass:family = _swig_property(_family_get) + %} +} +/* ************************************************************************************ * + Structure module_qstate + * ************************************************************************************ */ +%ignore module_qstate::ext_state; +%ignore module_qstate::minfo; + +/* Query state */ +struct module_qstate { + struct query_info qinfo; + uint16_t query_flags; //See QF_BIT_xx constants + int is_priming; + + struct comm_reply* reply; + struct dns_msg* return_msg; + int return_rcode; + struct regional* region; /* unwrapped */ + + int curmod; + + enum module_ext_state ext_state[MAX_MODULE]; + void* minfo[MAX_MODULE]; + + struct module_env* env; /* unwrapped */ + struct mesh_state* mesh_info; +}; + +%constant int MODULE_COUNT = MAX_MODULE; + +%constant int QF_BIT_CD = 0x0010; +%constant int QF_BIT_AD = 0x0020; +%constant int QF_BIT_Z = 0x0040; +%constant int QF_BIT_RA = 0x0080; +%constant int QF_BIT_RD = 0x0100; +%constant int QF_BIT_TC = 0x0200; +%constant int QF_BIT_AA = 0x0400; +%constant int QF_BIT_QR = 0x8000; + +%inline %{ + enum enum_return_rcode { + RCODE_NOERROR = 0, + RCODE_FORMERR = 1, + RCODE_SERVFAIL = 2, + RCODE_NXDOMAIN = 3, + RCODE_NOTIMPL = 4, + RCODE_REFUSED = 5, + RCODE_YXDOMAIN = 6, + RCODE_YXRRSET = 7, + RCODE_NXRRSET = 8, + RCODE_NOTAUTH = 9, + RCODE_NOTZONE = 10 + }; +%} + +%pythoncode %{ + class ExtState: + def __init__(self, obj): self.obj = obj + def __str__(self): + return ", ".join([_unboundmodule.strextstate(_unboundmodule._ext_state_get(self.obj,a)) for a in range(0, _unboundmodule.MODULE_COUNT)]) + def __getitem__(self, index): return _unboundmodule._ext_state_get(self.obj, index) + def __setitem__(self, index, value): _unboundmodule._ext_state_set(self.obj, index, value) + def __len__(self): return _unboundmodule.MODULE_COUNT +%} + +%inline %{ + enum module_ext_state _ext_state_get(struct module_qstate* q, int idx) { + if ((q != NULL) && (idx >= 0) && (idx < MAX_MODULE)) { + return q->ext_state[idx]; + } + return 0; + } + + void _ext_state_set(struct module_qstate* q, int idx, enum module_ext_state state) { + if ((q != NULL) && (idx >= 0) && (idx < MAX_MODULE)) { + q->ext_state[idx] = state; + } + } +%} + +%extend module_qstate { + %pythoncode %{ + def set_ext_state(self, id, state): + """Sets the ext state""" + _unboundmodule._ext_state_set(self, id, state) + + def __ext_state_get(self): return ExtState(self) + __swig_getmethods__["ext_state"] = __ext_state_get + if _newclass:ext_state = _swig_property(__ext_state_get)#, __ext_state_set) + %} +} + +/* ************************************************************************************ * + Structure config_strlist + * ************************************************************************************ */ +struct config_strlist { + struct config_strlist* next; + char* str; +}; + +/* ************************************************************************************ * + Structure config_str2list + * ************************************************************************************ */ +struct config_str2list { + struct config_str2list* next; + char* str; + char* str2; +}; + +/* ************************************************************************************ * + Structure config_file + * ************************************************************************************ */ +struct config_file { + int verbosity; + int stat_interval; + int stat_cumulative; + int stat_extended; + int num_threads; + int port; + int do_ip4; + int do_ip6; + int do_udp; + int do_tcp; + int outgoing_num_ports; + size_t outgoing_num_tcp; + size_t incoming_num_tcp; + int* outgoing_avail_ports; + size_t msg_buffer_size; + size_t msg_cache_size; + size_t msg_cache_slabs; + size_t num_queries_per_thread; + size_t jostle_time; + size_t rrset_cache_size; + size_t rrset_cache_slabs; + int host_ttl; + size_t infra_cache_slabs; + size_t infra_cache_numhosts; + char* target_fetch_policy; + int if_automatic; + int num_ifs; + char **ifs; + int num_out_ifs; + char **out_ifs; + struct config_strlist* root_hints; + struct config_stub* stubs; + struct config_stub* forwards; + struct config_strlist* donotqueryaddrs; + struct config_str2list* acls; + int donotquery_localhost; + int harden_short_bufsize; + int harden_large_queries; + int harden_glue; + int harden_dnssec_stripped; + int harden_referral_path; + int use_caps_bits_for_id; + struct config_strlist* private_address; + struct config_strlist* private_domain; + size_t unwanted_threshold; + char* chrootdir; + char* username; + char* directory; + char* logfile; + char* pidfile; + int use_syslog; + int hide_identity; + int hide_version; + char* identity; + char* version; + char* module_conf; + struct config_strlist* trust_anchor_file_list; + struct config_strlist* trust_anchor_list; + struct config_strlist* trusted_keys_file_list; + char* dlv_anchor_file; + struct config_strlist* dlv_anchor_list; + int max_ttl; + int32_t val_date_override; + int bogus_ttl; + int val_clean_additional; + int val_permissive_mode; + char* val_nsec3_key_iterations; + size_t key_cache_size; + size_t key_cache_slabs; + size_t neg_cache_size; + struct config_str2list* local_zones; + struct config_strlist* local_zones_nodefault; + struct config_strlist* local_data; + int remote_control_enable; + struct config_strlist* control_ifs; + int control_port; + char* server_key_file; + char* server_cert_file; + char* control_key_file; + char* control_cert_file; + int do_daemonize; + char* python_script; +}; + +/* ************************************************************************************ * + Enums + * ************************************************************************************ */ +%rename ("MODULE_STATE_INITIAL") "module_state_initial"; +%rename ("MODULE_WAIT_REPLY") "module_wait_reply"; +%rename ("MODULE_WAIT_MODULE") "module_wait_module"; +%rename ("MODULE_WAIT_SUBQUERY") "module_wait_subquery"; +%rename ("MODULE_ERROR") "module_error"; +%rename ("MODULE_FINISHED") "module_finished"; + +enum module_ext_state { + module_state_initial = 0, + module_wait_reply, + module_wait_module, + module_wait_subquery, + module_error, + module_finished +}; + +%rename ("MODULE_EVENT_NEW") "module_event_new"; +%rename ("MODULE_EVENT_PASS") "module_event_pass"; +%rename ("MODULE_EVENT_REPLY") "module_event_reply"; +%rename ("MODULE_EVENT_NOREPLY") "module_event_noreply"; +%rename ("MODULE_EVENT_CAPSFAIL") "module_event_capsfail"; +%rename ("MODULE_EVENT_MODDONE") "module_event_moddone"; +%rename ("MODULE_EVENT_ERROR") "module_event_error"; + +enum module_ev { + module_event_new = 0, + module_event_pass, + module_event_reply, + module_event_noreply, + module_event_capsfail, + module_event_moddone, + module_event_error +}; + +enum sec_status { + sec_status_unchecked = 0, + sec_status_bogus, + sec_status_indeterminate, + sec_status_insecure, + sec_status_secure +}; + +enum verbosity_value { + NO_VERBOSE = 0, + VERB_OPS, + VERB_DETAIL, + VERB_QUERY, + VERB_ALGO +}; + +%{ +int checkList(PyObject *l) +{ + PyObject* item; + int i; + + if (l == Py_None) + return 1; + + if (PyList_Check(l)) + { + for (i=0; i < PyList_Size(l); i++) + { + item = PyList_GetItem(l, i); + if (!PyString_Check(item)) + return 0; + } + return 1; + } + + return 0; +} + +ldns_rr_list* createRRList(PyObject *l, uint32_t default_ttl) +{ + PyObject* item; + ldns_status status; + ldns_rr_list* rr_list; + ldns_rr* rr; + int i; + + if (PyList_Size(l) == 0) + return NULL; + + rr_list = ldns_rr_list_new(); + + for (i=0; i < PyList_Size(l); i++) + { + item = PyList_GetItem(l, i); + + status = ldns_rr_new_frm_str(&rr, PyString_AsString(item), default_ttl, 0, 0); + if (status != LDNS_STATUS_OK) + continue; + + if (!ldns_rr_list_push_rr(rr_list, rr)) + continue; + + } + return rr_list; +} + +int set_return_msg(struct module_qstate* qstate, + const char* rr_name, ldns_rr_type rr_type, ldns_rr_class rr_class , uint16_t flags, uint32_t default_ttl, + PyObject* question, PyObject* answer, PyObject* authority, PyObject* additional) +{ + ldns_pkt* pkt = 0; + ldns_status status; + ldns_rr_list* rr_list = 0; + ldns_buffer *qb = 0; + int res = 1; + + if ((!checkList(question)) || (!checkList(answer)) || (!checkList(authority)) || (!checkList(additional))) + return 0; + + status = ldns_pkt_query_new_frm_str(&pkt, rr_name, rr_type, rr_class, flags); + if ((status != LDNS_STATUS_OK) || (pkt == 0)) + return 0; + + rr_list = createRRList(question, default_ttl); + if ((rr_list) && (res)) res = ldns_pkt_push_rr_list(pkt, LDNS_SECTION_QUESTION, rr_list); + ldns_rr_list_free(rr_list); + rr_list = createRRList(answer, default_ttl); + if ((rr_list) && (res)) res = ldns_pkt_push_rr_list(pkt, LDNS_SECTION_ANSWER, rr_list); + ldns_rr_list_free(rr_list); + rr_list = createRRList(authority, default_ttl); + if ((rr_list) && (res)) res = ldns_pkt_push_rr_list(pkt, LDNS_SECTION_AUTHORITY, rr_list); + ldns_rr_list_free(rr_list); + rr_list = createRRList(additional, default_ttl); + if ((rr_list) && (res)) res = ldns_pkt_push_rr_list(pkt, LDNS_SECTION_ADDITIONAL, rr_list); + ldns_rr_list_free(rr_list); + + if ((res) && ((qb = ldns_buffer_new(LDNS_MIN_BUFLEN)) == 0)) res = 0; + if ((res) && (ldns_pkt2buffer_wire(qb, pkt) != LDNS_STATUS_OK)) res = 0; + + if (res) res = createResponse(qstate, qb); + + if (qb) ldns_buffer_free(qb); + + ldns_pkt_free(pkt); //this function dealocates pkt as well as rrs + return res; +} +%} + +%constant uint16_t PKT_QR = 1; /* QueRy - query flag */ +%constant uint16_t PKT_AA = 2; /* Authoritative Answer - server flag */ +%constant uint16_t PKT_TC = 4; /* TrunCated - server flag */ +%constant uint16_t PKT_RD = 8; /* Recursion Desired - query flag */ +%constant uint16_t PKT_CD = 16; /* Checking Disabled - query flag */ +%constant uint16_t PKT_RA = 32; /* Recursion Available - server flag */ +%constant uint16_t PKT_AD = 64; /* Authenticated Data - server flag */ + +int set_return_msg(struct module_qstate* qstate, + const char* rr_name, int rr_type, int rr_class , uint16_t flags, uint32_t default_ttl, + PyObject* question, PyObject* answer, PyObject* authority, PyObject* additional); + +%pythoncode %{ + class DNSMessage: + def __init__(self, rr_name, rr_type, rr_class = RR_CLASS_IN, query_flags = 0, default_ttl = 0): + """Query flags is a combination of PKT_xx contants""" + self.rr_name = rr_name + self.rr_type = rr_type + self.rr_class = rr_class + self.default_ttl = default_ttl + self.query_flags = query_flags + self.question = [] + self.answer = [] + self.authority = [] + self.additional = [] + + def set_return_msg(self, qstate): + """Returns 1 if OK""" + status = _unboundmodule.set_return_msg(qstate, self.rr_name, self.rr_type, self.rr_class, + self.query_flags, self.default_ttl, + self.question, self.answer, self.authority, self.additional) + + if (status) and (PKT_AA & self.query_flags): + qstate.return_msg.rep.authoritative = 1 + + return status + +%} +/* ************************************************************************************ * + Functions + * ************************************************************************************ */ + +// Various debuging functions +void verbose(enum verbosity_value level, const char* format, ...); +void log_info(const char* format, ...); +void log_err(const char* format, ...); +void log_warn(const char* format, ...); +void log_hex(const char* msg, void* data, size_t length); +void log_dns_msg(const char* str, struct query_info* qinfo, struct reply_info* rep); +void log_query_info(enum verbosity_value v, const char* str, struct query_info* qinf); +void regional_log_stats(struct regional *r); + +// Free allocated memory from marked sources returning corresponding types +%typemap(newfree, noblock = 1) char * { + free($1); +} + +// Mark as source returning newly allocated memory +%newobject ldns_rr_type2str; +%newobject ldns_rr_class2str; + +// LDNS functions +char *ldns_rr_type2str(const uint16_t atype); +char *ldns_rr_class2str(const uint16_t aclass); + +// Functions from pythonmod_utils +int storeQueryInCache(struct module_qstate* qstate, struct query_info* qinfo, struct reply_info* msgrep, int is_referral); +void invalidateQueryInCache(struct module_qstate* qstate, struct query_info* qinfo); + +// Module conversion functions +const char* strextstate(enum module_ext_state s); +const char* strmodulevent(enum module_ev e); + diff --git a/pythonmod/pythonmod.c b/pythonmod/pythonmod.c new file mode 100644 index 00000000000..9860d001d0e --- /dev/null +++ b/pythonmod/pythonmod.c @@ -0,0 +1,383 @@ +/* + * pythonmod.c: unbound module C wrapper + * + * Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz) + * Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) + * + * 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 organization 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \file + * Python module for unbound. Calls python script. + */ + +/* ignore the varargs unused warning from SWIGs internal vararg support */ +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +#include "config.h" +#include + +#undef _POSIX_C_SOURCE +#undef _XOPEN_SOURCE +#include + +#include "pythonmod/pythonmod.h" +#include "util/module.h" +#include "util/config_file.h" +#include "pythonmod_utils.h" + +#ifdef S_SPLINT_S +typedef struct PyObject PyObject; +typedef struct PyThreadState PyThreadState; +typedef void* PyGILState_STATE; +#endif + +/** + * Global state for the module. + */ +struct pythonmod_env { + + /** Python script filename. */ + const char* fname; + + /** Python main thread */ + PyThreadState* mainthr; + /** Python module. */ + PyObject* module; + + /** Module init function */ + PyObject* func_init; + /** Module deinit function */ + PyObject* func_deinit; + /** Module operate function */ + PyObject* func_operate; + /** Module super_inform function */ + PyObject* func_inform; + + /** Python dictionary. */ + PyObject* dict; + + /** Module data. */ + PyObject* data; + + /** Module qstate. */ + struct module_qstate* qstate; +}; + +/** + * Per query state for the iterator module. + */ +struct pythonmod_qstate { + + /** Module per query data. */ + PyObject* data; +}; + +/* Generated */ +#ifndef S_SPLINT_S +#include "pythonmod/interface.h" +#endif + +int pythonmod_init(struct module_env* env, int id) +{ + /* Initialize module */ + FILE* script_py = NULL; + PyObject* py_cfg, *res; + PyGILState_STATE gil; + struct pythonmod_env* pe = (struct pythonmod_env*)calloc(1, sizeof(struct pythonmod_env)); + if (!pe) + { + log_err("pythonmod: malloc failure"); + return 0; + } + + env->modinfo[id] = (void*) pe; + + /* Initialize module */ + pe->fname = env->cfg->python_script; + if(pe->fname==NULL || pe->fname[0]==0) { + log_err("pythonmod: no script given."); + return 0; + } + + /* Initialize Python libraries */ + if (!Py_IsInitialized()) + { + Py_SetProgramName("unbound"); + Py_NoSiteFlag = 1; + Py_Initialize(); + PyEval_InitThreads(); + SWIG_init(); + pe->mainthr = PyEval_SaveThread(); + } + + gil = PyGILState_Ensure(); + + /* Initialize Python */ + PyRun_SimpleString("import sys \n"); + PyRun_SimpleString("sys.path.append('.') \n"); + if(env->cfg->directory && env->cfg->directory[0]) { + char wdir[1524]; + snprintf(wdir, sizeof(wdir), "sys.path.append('%s') \n", + env->cfg->directory); + PyRun_SimpleString(wdir); + } + PyRun_SimpleString("sys.path.append('"RUN_DIR"') \n"); + PyRun_SimpleString("sys.path.append('"SHARE_DIR"') \n"); + PyRun_SimpleString("import distutils.sysconfig \n"); + PyRun_SimpleString("sys.path.append(distutils.sysconfig.get_python_lib(1,0)) \n"); + if (PyRun_SimpleString("from unboundmodule import *\n") < 0) + { + log_err("pythonmod: cannot initialize core module: unboundmodule.py"); + PyGILState_Release(gil); + return 0; + } + + /* Check Python file load */ + if ((script_py = fopen(pe->fname, "r")) == NULL) + { + log_err("pythonmod: can't open file %s for reading", pe->fname); + PyGILState_Release(gil); + return 0; + } + + /* Load file */ + pe->module = PyImport_AddModule("__main__"); + pe->dict = PyModule_GetDict(pe->module); + pe->data = Py_None; + Py_INCREF(pe->data); + PyModule_AddObject(pe->module, "mod_env", pe->data); + + /* TODO: deallocation of pe->... if an error occurs */ + + if (PyRun_SimpleFile(script_py, pe->fname) < 0) + { + log_err("pythonmod: can't parse Python script %s", pe->fname); + PyGILState_Release(gil); + return 0; + } + + fclose(script_py); + + if ((pe->func_init = PyDict_GetItemString(pe->dict, "init")) == NULL) + { + log_err("pythonmod: function init is missing in %s", pe->fname); + PyGILState_Release(gil); + return 0; + } + if ((pe->func_deinit = PyDict_GetItemString(pe->dict, "deinit")) == NULL) + { + log_err("pythonmod: function deinit is missing in %s", pe->fname); + PyGILState_Release(gil); + return 0; + } + if ((pe->func_operate = PyDict_GetItemString(pe->dict, "operate")) == NULL) + { + log_err("pythonmod: function operate is missing in %s", pe->fname); + PyGILState_Release(gil); + return 0; + } + if ((pe->func_inform = PyDict_GetItemString(pe->dict, "inform_super")) == NULL) + { + log_err("pythonmod: function inform_super is missing in %s", pe->fname); + PyGILState_Release(gil); + return 0; + } + + py_cfg = SWIG_NewPointerObj((void*) env->cfg, SWIGTYPE_p_config_file, 0); + res = PyObject_CallFunction(pe->func_init, "iO", id, py_cfg); + if (PyErr_Occurred()) + { + log_err("pythonmod: Exception occurred in function init"); + PyErr_Print(); + } + + Py_XDECREF(res); + Py_XDECREF(py_cfg); + PyGILState_Release(gil); + + return 1; +} + +void pythonmod_deinit(struct module_env* env, int id) +{ + struct pythonmod_env* pe = env->modinfo[id]; + if(pe == NULL) + return; + + /* Free Python resources */ + if(pe->module != NULL) + { + PyObject* res; + PyGILState_STATE gil = PyGILState_Ensure(); + + /* Deinit module */ + res = PyObject_CallFunction(pe->func_deinit, "i", id); + if (PyErr_Occurred()) { + log_err("pythonmod: Exception occurred in function deinit"); + PyErr_Print(); + } + /* Free result if any */ + Py_XDECREF(res); + /* Free shared data if any */ + Py_XDECREF(pe->data); + PyGILState_Release(gil); + + PyEval_RestoreThread(pe->mainthr); + Py_Finalize(); + pe->mainthr = NULL; + } + pe->fname = NULL; + free(pe); + + /* Module is deallocated in Python */ + env->modinfo[id] = NULL; +} + +void pythonmod_inform_super(struct module_qstate* qstate, int id, struct module_qstate* super) +{ + struct pythonmod_env* pe = (struct pythonmod_env*)qstate->env->modinfo[id]; + struct pythonmod_qstate* pq = (struct pythonmod_qstate*)qstate->minfo[id]; + PyObject* py_qstate, *py_sqstate, *res; + PyGILState_STATE gil = PyGILState_Ensure(); + + log_query_info(VERB_ALGO, "pythonmod: inform_super, sub is", &qstate->qinfo); + log_query_info(VERB_ALGO, "super is", &super->qinfo); + + py_qstate = SWIG_NewPointerObj((void*) qstate, SWIGTYPE_p_module_qstate, 0); + py_sqstate = SWIG_NewPointerObj((void*) super, SWIGTYPE_p_module_qstate, 0); + + res = PyObject_CallFunction(pe->func_inform, "iOOO", id, py_qstate, + py_sqstate, pq->data); + + if (PyErr_Occurred()) + { + log_err("pythonmod: Exception occurred in function inform_super"); + PyErr_Print(); + qstate->ext_state[id] = module_error; + } + else if ((res == NULL) || (!PyObject_IsTrue(res))) + { + log_err("pythonmod: python returned bad code in inform_super"); + qstate->ext_state[id] = module_error; + } + + Py_XDECREF(res); + Py_XDECREF(py_sqstate); + Py_XDECREF(py_qstate); + + PyGILState_Release(gil); +} + +void pythonmod_operate(struct module_qstate* qstate, enum module_ev event, + int id, struct outbound_entry* ATTR_UNUSED(outbound)) +{ + struct pythonmod_env* pe = (struct pythonmod_env*)qstate->env->modinfo[id]; + struct pythonmod_qstate* pq = (struct pythonmod_qstate*)qstate->minfo[id]; + PyObject* py_qstate, *res; + PyGILState_STATE gil = PyGILState_Ensure(); + + if ( pq == NULL) + { + /* create qstate */ + pq = qstate->minfo[id] = malloc(sizeof(struct pythonmod_qstate)); + + /* Initialize per query data */ + pq->data = Py_None; + Py_INCREF(pq->data); + } + + /* Call operate */ + py_qstate = SWIG_NewPointerObj((void*) qstate, SWIGTYPE_p_module_qstate, 0); + res = PyObject_CallFunction(pe->func_operate, "iiOO", id, (int) event, + py_qstate, pq->data); + if (PyErr_Occurred()) + { + log_err("pythonmod: Exception occurred in function operate, event: %s", strmodulevent(event)); + PyErr_Print(); + qstate->ext_state[id] = module_error; + } + else if ((res == NULL) || (!PyObject_IsTrue(res))) + { + log_err("pythonmod: python returned bad code, event: %s", strmodulevent(event)); + qstate->ext_state[id] = module_error; + } + Py_XDECREF(res); + Py_XDECREF(py_qstate); + + PyGILState_Release(gil); +} + +void pythonmod_clear(struct module_qstate* qstate, int id) +{ + struct pythonmod_qstate* pq; + if (qstate == NULL) + return; + + pq = (struct pythonmod_qstate*)qstate->minfo[id]; + verbose(VERB_ALGO, "pythonmod: clear, id: %d, pq:%lX", id, + (unsigned long int)pq); + if(pq != NULL) + { + PyGILState_STATE gil = PyGILState_Ensure(); + Py_DECREF(pq->data); + PyGILState_Release(gil); + /* Free qstate */ + free(pq); + } + + qstate->minfo[id] = NULL; +} + +size_t pythonmod_get_mem(struct module_env* env, int id) +{ + struct pythonmod_env* pe = (struct pythonmod_env*)env->modinfo[id]; + verbose(VERB_ALGO, "pythonmod: get_mem, id: %d, pe:%lX", id, + (unsigned long int)pe); + if(!pe) + return 0; + return sizeof(*pe); +} + +/** + * The module function block + */ +static struct module_func_block pythonmod_block = { + "python", + &pythonmod_init, &pythonmod_deinit, &pythonmod_operate, &pythonmod_inform_super, + &pythonmod_clear, &pythonmod_get_mem +}; + +struct module_func_block* pythonmod_get_funcblock(void) +{ + return &pythonmod_block; +} diff --git a/pythonmod/pythonmod.h b/pythonmod/pythonmod.h new file mode 100644 index 00000000000..b108cf9234c --- /dev/null +++ b/pythonmod/pythonmod.h @@ -0,0 +1,68 @@ +/* + * pythonmod.h: module header file + * + * Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz) + * Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) + * + * 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 organization 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \file + * Python module for unbound. Calls python script. + */ +#ifndef PYTHONMOD_H +#define PYTHONMOD_H +#include "util/module.h" +#include "services/outbound_list.h" + +/** + * Get the module function block. + * @return: function block with function pointers to module methods. + */ +struct module_func_block* pythonmod_get_funcblock(void); + +/** python module init */ +int pythonmod_init(struct module_env* env, int id); + +/** python module deinit */ +void pythonmod_deinit(struct module_env* env, int id); + +/** python module operate on a query */ +void pythonmod_operate(struct module_qstate* qstate, enum module_ev event, int id, struct outbound_entry* outbound); + +/** python module */ +void pythonmod_inform_super(struct module_qstate* qstate, int id, struct module_qstate* super); + +/** python module cleanup query state */ +void pythonmod_clear(struct module_qstate* qstate, int id); + +/** python module alloc size routine */ +size_t pythonmod_get_mem(struct module_env* env, int id); +#endif /* PYTHONMOD_H */ diff --git a/pythonmod/pythonmod_utils.c b/pythonmod/pythonmod_utils.c new file mode 100644 index 00000000000..b25acd3a890 --- /dev/null +++ b/pythonmod/pythonmod_utils.c @@ -0,0 +1,177 @@ +/* + * pythonmod_utils.c: utilities used by wrapper + * + * Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz) + * Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) + * + * 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 organization 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \file + * Utility functions for the python module that perform stores and loads and + * conversions. + */ +#include "config.h" +#include "util/module.h" +#include "util/netevent.h" +#include "util/net_help.h" +#include "services/cache/dns.h" +#include "services/cache/rrset.h" +#include "util/data/msgparse.h" +#include "util/data/msgreply.h" +#include "util/storage/slabhash.h" +#include "util/regional.h" + +#undef _POSIX_C_SOURCE +#undef _XOPEN_SOURCE +#include + +/* Store the reply_info and query_info pair in message cache (qstate->msg_cache) */ +int storeQueryInCache(struct module_qstate* qstate, struct query_info* qinfo, struct reply_info* msgrep, int is_referral) +{ + if (!msgrep) + return 0; + + if (msgrep->authoritative) /*authoritative answer can't be stored in cache*/ + { + PyErr_SetString(PyExc_ValueError, "Authoritative answer can't be stored"); + return 0; + } + + return dns_cache_store(qstate->env, qinfo, msgrep, is_referral, + qstate->prefetch_leeway, 0, NULL); +} + +/* Invalidate the message associated with query_info stored in message cache */ +void invalidateQueryInCache(struct module_qstate* qstate, struct query_info* qinfo) +{ + hashvalue_t h; + struct lruhash_entry* e; + struct reply_info *r; + size_t i, j; + + h = query_info_hash(qinfo); + if ((e=slabhash_lookup(qstate->env->msg_cache, h, qinfo, 0))) + { + r = (struct reply_info*)(e->data); + if (r) + { + r->ttl = 0; + if(rrset_array_lock(r->ref, r->rrset_count, *qstate->env->now)) { + for(i=0; i< r->rrset_count; i++) + { + struct packed_rrset_data* data = + (struct packed_rrset_data*) r->ref[i].key->entry.data; + if(i>0 && r->ref[i].key == r->ref[i-1].key) + continue; + + data->ttl = r->ttl; + for(j=0; jcount + data->rrsig_count; j++) + data->rr_ttl[j] = r->ttl; + } + rrset_array_unlock(r->ref, r->rrset_count); + } + } + lock_rw_unlock(&e->lock); + } else { + log_info("invalidateQueryInCache: qinfo is not in cache"); + } +} + +/* Create response according to the ldns packet content */ +int createResponse(struct module_qstate* qstate, ldns_buffer* pkt) +{ + struct msg_parse* prs; + struct edns_data edns; + + /* parse message */ + prs = (struct msg_parse*) regional_alloc(qstate->env->scratch, sizeof(struct msg_parse)); + if (!prs) { + log_err("storeResponse: out of memory on incoming message"); + return 0; + } + + memset(prs, 0, sizeof(*prs)); + memset(&edns, 0, sizeof(edns)); + + ldns_buffer_set_position(pkt, 0); + if (parse_packet(pkt, prs, qstate->env->scratch) != LDNS_RCODE_NOERROR) { + verbose(VERB_ALGO, "storeResponse: parse error on reply packet"); + return 0; + } + /* edns is not examined, but removed from message to help cache */ + if(parse_extract_edns(prs, &edns) != LDNS_RCODE_NOERROR) + return 0; + + /* remove CD-bit, we asked for in case we handle validation ourself */ + prs->flags &= ~BIT_CD; + + /* allocate response dns_msg in region */ + qstate->return_msg = (struct dns_msg*)regional_alloc(qstate->region, sizeof(struct dns_msg)); + if (!qstate->return_msg) + return 0; + + memset(qstate->return_msg, 0, sizeof(*qstate->return_msg)); + if(!parse_create_msg(pkt, prs, NULL, &(qstate->return_msg)->qinfo, &(qstate->return_msg)->rep, qstate->region)) { + log_err("storeResponse: malloc failure: allocating incoming dns_msg"); + return 0; + } + + /* Make sure that the RA flag is set (since the presence of + * this module means that recursion is available) */ + /* qstate->return_msg->rep->flags |= BIT_RA; */ + + /* Clear the AA flag */ + /* FIXME: does this action go here or in some other module? */ + /*qstate->return_msg->rep->flags &= ~BIT_AA; */ + + /* make sure QR flag is on */ + /*qstate->return_msg->rep->flags |= BIT_QR; */ + + if(verbosity >= VERB_ALGO) + log_dns_msg("storeResponse: packet:", &qstate->return_msg->qinfo, qstate->return_msg->rep); + + return 1; +} + + +/* Convert reply->addr to string */ +void reply_addr2str(struct comm_reply* reply, char* dest, int maxlen) +{ + int af = (int)((struct sockaddr_in*) &(reply->addr))->sin_family; + void* sinaddr = &((struct sockaddr_in*) &(reply->addr))->sin_addr; + + if(af == AF_INET6) + sinaddr = &((struct sockaddr_in6*)&(reply->addr))->sin6_addr; + dest[0] = 0; + if (inet_ntop(af, sinaddr, dest, (socklen_t)maxlen) == 0) + return; + dest[maxlen-1] = 0; +} diff --git a/pythonmod/pythonmod_utils.h b/pythonmod/pythonmod_utils.h new file mode 100644 index 00000000000..a1641d30858 --- /dev/null +++ b/pythonmod/pythonmod_utils.h @@ -0,0 +1,89 @@ +/* + * pythonmod_utils.h: utils header file + * + * Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz) + * Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) + * + * 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 organization 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \file + * Utility functions for the python module that perform stores and loads and + * conversions. + */ +#ifndef PYTHONMOD_UTILS_H +#define PYTHONMOD_UTILS_H + +#include "util/module.h" + +/** + * Store the reply_info and query_info pair in message cache (qstate->msg_cache) + * + * @param qstate: module environment + * @param qinfo: query info, the query for which answer is stored. + * @param msgrep: reply in dns_msg + * @param is_referral: If true, then the given message to be stored is a + * referral. The cache implementation may use this as a hint. + * It will store only the RRsets, not the message. + * @return 0 on alloc error (out of memory). + */ +int storeQueryInCache(struct module_qstate* qstate, struct query_info* qinfo, struct reply_info* msgrep, int is_referral); + + +/** + * Invalidate the message associated with query_info stored in message cache. + * + * This function invalidates the record in message cache associated with the given query only if such a record exists. + * + * @param qstate: module environment + * @param qinfo: query info, the query for which answer is stored. + */ +void invalidateQueryInCache(struct module_qstate* qstate, struct query_info* qinfo); + +/** + * Create response according to the ldns packet content + * + * This function fills qstate.return_msg up with data of a given packet + * + * @param qstate: module environment + * @param pkt: a ldns_buffer which contains ldns_packet data + * @return 0 on failure, out of memory or parse error. + */ +int createResponse(struct module_qstate* qstate, ldns_buffer* pkt); + +/** + * Convert reply->addr to string + * @param reply: comm reply with address in it. + * @param dest: destination string. + * @param maxlen: length of string buffer. + */ +void reply_addr2str(struct comm_reply* reply, char* dest, int maxlen); + +#endif /* PYTHONMOD_UTILS_H */ diff --git a/pythonmod/test-calc.conf b/pythonmod/test-calc.conf new file mode 100644 index 00000000000..ef854ce1bf6 --- /dev/null +++ b/pythonmod/test-calc.conf @@ -0,0 +1,18 @@ +# Example configuration file for calc.py +server: + verbosity: 1 + interface: 0.0.0.0 + do-daemonize: no + access-control: 0.0.0.0/0 allow + chroot: "" + username: "" + directory: "" + logfile: "" + pidfile: "unbound.pid" + module-config: "validator python iterator" + +# Python config section +python: + # Script file to load + python-script: "./examples/calc.py" + diff --git a/pythonmod/test-dict.conf b/pythonmod/test-dict.conf new file mode 100644 index 00000000000..daab7250e5d --- /dev/null +++ b/pythonmod/test-dict.conf @@ -0,0 +1,18 @@ +# Example configuration file for dict.py +server: + verbosity: 1 + interface: 0.0.0.0 + do-daemonize: no + access-control: 0.0.0.0/0 allow + chroot: "" + username: "" + directory: "" + logfile: "" + pidfile: "unbound.pid" + module-config: "validator python iterator" + +# Python config section +python: + # Script file to load + python-script: "./examples/dict.py" + diff --git a/pythonmod/test-log.conf b/pythonmod/test-log.conf new file mode 100644 index 00000000000..02214ba1d63 --- /dev/null +++ b/pythonmod/test-log.conf @@ -0,0 +1,17 @@ +# Example configuration file for log.py +server: + verbosity: 1 + interface: 0.0.0.0 + do-daemonize: no + access-control: 0.0.0.0/0 allow + chroot: "" + username: "" + directory: "" + logfile: "" + pidfile: "unbound.pid" + module-config: "validator python iterator" + +# Python config section +python: + # Script file to load + python-script: "./examples/log.py" diff --git a/pythonmod/test-resgen.conf b/pythonmod/test-resgen.conf new file mode 100644 index 00000000000..a0a79e42dfe --- /dev/null +++ b/pythonmod/test-resgen.conf @@ -0,0 +1,18 @@ +# Example configuration file for resgen.py +server: + verbosity: 1 + interface: 0.0.0.0 + do-daemonize: no + access-control: 0.0.0.0/0 allow + chroot: "" + username: "" + directory: "" + logfile: "" + pidfile: "unbound.pid" + module-config: "validator python iterator" + +# Python config section +python: + # Script file to load + python-script: "./examples/resgen.py" + diff --git a/pythonmod/test-resip.conf b/pythonmod/test-resip.conf new file mode 100644 index 00000000000..7620f736fe3 --- /dev/null +++ b/pythonmod/test-resip.conf @@ -0,0 +1,18 @@ +# Example configuration file for resip.py +server: + verbosity: 1 + #interface: 0.0.0.0 + do-daemonize: no + #access-control: 0.0.0.0/0 allow + chroot: "" + username: "" + directory: "" + logfile: "" + pidfile: "unbound.pid" + module-config: "validator python iterator" + +# Python config section +python: + # Script file to load + python-script: "./examples/resip.py" + diff --git a/pythonmod/test-resmod.conf b/pythonmod/test-resmod.conf new file mode 100644 index 00000000000..8de5fd257fa --- /dev/null +++ b/pythonmod/test-resmod.conf @@ -0,0 +1,19 @@ +# Example configuration file for resmod.py +server: + verbosity: 1 + interface: 0.0.0.0 + do-daemonize: no + access-control: 0.0.0.0/0 allow + chroot: "" + username: "" + directory: "" + logfile: "" + pidfile: "unbound.pid" + #module-config: "python iterator" + module-config: "validator python iterator" + +# Python config section +python: + # Script file to load + python-script: "./examples/resmod.py" + diff --git a/pythonmod/ubmodule-msg.py b/pythonmod/ubmodule-msg.py new file mode 100644 index 00000000000..648368080c0 --- /dev/null +++ b/pythonmod/ubmodule-msg.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +''' + ubmodule-msg.py: simple response packet logger + + Authors: Zdenek Vasicek (vasicek AT fit.vutbr.cz) + Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) + + Copyright (c) 2008. 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. + + 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 REGENTS OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +''' +import os + +def init(id, cfg): + log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, cfg.port, cfg.python_script)) + return True + +def deinit(id): + log_info("pythonmod: deinit called, module id is %d" % id) + return True + +def inform_super(id, qstate, superqstate, qdata): + return True + +def setTTL(qstate, ttl): + """Sets return_msg TTL and all the RRs TTL""" + if qstate.return_msg: + qstate.return_msg.rep.ttl = ttl + if (qstate.return_msg.rep): + for i in range(0,qstate.return_msg.rep.rrset_count): + d = qstate.return_msg.rep.rrsets[i].entry.data + for j in range(0,d.count+d.rrsig_count): + d.rr_ttl[j] = ttl + +def dataHex(data, prefix=""): + res = "" + for i in range(0, (len(data)+15)/16): + res += "%s0x%02X | " % (prefix, i*16) + d = map(lambda x:ord(x), data[i*16:i*16+17]) + for ch in d: + res += "%02X " % ch + for i in range(0,17-len(d)): + res += " " + res += "| " + for ch in d: + if (ch < 32) or (ch > 127): + res += ". " + else: + res += "%c " % ch + res += "\n" + return res + +def printReturnMsg(qstate): + print "Return MSG rep :: flags: %04X, QDcount: %d, Security:%d, TTL=%d" % (qstate.return_msg.rep.flags, qstate.return_msg.rep.qdcount,qstate.return_msg.rep.security, qstate.return_msg.rep.ttl) + print " qinfo :: qname:",qstate.return_msg.qinfo.qname_list, qstate.return_msg.qinfo.qname_str, "type:",qstate.return_msg.qinfo.qtype_str, "class:",qstate.return_msg.qinfo.qclass_str + if (qstate.return_msg.rep): + print "RRSets:",qstate.return_msg.rep.rrset_count + prevkey = None + for i in range(0,qstate.return_msg.rep.rrset_count): + r = qstate.return_msg.rep.rrsets[i] + rk = r.rk + print i,":",rk.dname_list, rk.dname_str, "flags: %04X" % rk.flags, + print "type:",rk.type_str,"(%d)" % ntohs(rk.type), "class:",rk.rrset_class_str,"(%d)" % ntohs(rk.rrset_class) + + d = r.entry.data + print " RRDatas:",d.count+d.rrsig_count + for j in range(0,d.count+d.rrsig_count): + print " ",j,":","TTL=",d.rr_ttl[j],"RR data:" + print dataHex(d.rr_data[j]," ") + + +def operate(id, event, qstate, qdata): + log_info("pythonmod: operate called, id: %d, event:%s" % (id, strmodulevent(event))) + #print "pythonmod: per query data", qdata + + print "Query:", ''.join(map(lambda x:chr(max(32,ord(x))),qstate.qinfo.qname)), qstate.qinfo.qname_list, qstate.qinfo.qname_str, + print "Type:",qstate.qinfo.qtype_str,"(%d)" % qstate.qinfo.qtype, + print "Class:",qstate.qinfo.qclass_str,"(%d)" % qstate.qinfo.qclass + print + + #if event == MODULE_EVENT_PASS: #pokud mame "validator python iterator" + if (event == MODULE_EVENT_NEW) and (qstate.qinfo.qname_str.endswith(".seznam.cz.")): #pokud mame "python validator iterator" + print qstate.qinfo.qname_str + + qstate.ext_state[id] = MODULE_FINISHED + + msg = DNSMessage(qstate.qinfo.qname_str, RR_TYPE_A, RR_CLASS_IN, PKT_QR | PKT_RA | PKT_AA) #, 300) + #msg.authority.append("xxx.seznam.cz. 10 IN A 192.168.1.1") + #msg.additional.append("yyy.seznam.cz. 10 IN A 1.1.1.2.") + + if qstate.qinfo.qtype == RR_TYPE_A: + msg.answer.append("%s 10 IN A 192.168.1.1" % qstate.qinfo.qname_str) + if (qstate.qinfo.qtype == RR_TYPE_SRV) or (qstate.qinfo.qtype == RR_TYPE_ANY): + msg.answer.append("%s 10 IN SRV 0 0 80 neinfo.example.com." % qstate.qinfo.qname_str) + if (qstate.qinfo.qtype == RR_TYPE_TXT) or (qstate.qinfo.qtype == RR_TYPE_ANY): + msg.answer.append("%s 10 IN TXT path=/" % qstate.qinfo.qname_str) + + if not msg.set_return_msg(qstate): + qstate.ext_state[id] = MODULE_ERROR + return True + + #qstate.return_msg.rep.security = 2 #pokud nebude nasledovat validator, je zapotrebi nastavit security, aby nebyl paket zahozen v mesh_send_reply + printReturnMsg(qstate) + + #Authoritative result can't be stored in cache + #if (not storeQueryInCache(qstate, qstate.return_msg.qinfo, qstate.return_msg.rep, 0)): + # print "Can't store in cache" + # qstate.ext_state[id] = MODULE_ERROR + # return False + #print "Store OK" + + qstate.return_rcode = RCODE_NOERROR + return True + + if event == MODULE_EVENT_NEW: + qstate.ext_state[id] = MODULE_WAIT_MODULE + return True + + if event == MODULE_EVENT_MODDONE: + log_info("pythonmod: previous module done") + qstate.ext_state[id] = MODULE_FINISHED + return True + + if event == MODULE_EVENT_PASS: + log_info("pythonmod: event_pass") + qstate.ext_state[id] = MODULE_WAIT_MODULE + return True + + log_err("pythonmod: BAD event") + qstate.ext_state[id] = MODULE_ERROR + return True + +log_info("pythonmod: script loaded.") diff --git a/pythonmod/ubmodule-tst.py b/pythonmod/ubmodule-tst.py new file mode 100644 index 00000000000..0b9b5a9d2cf --- /dev/null +++ b/pythonmod/ubmodule-tst.py @@ -0,0 +1,149 @@ +# -*- coding: utf-8 -*- +''' + ubmodule-tst.py: + + Authors: Zdenek Vasicek (vasicek AT fit.vutbr.cz) + Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) + + Copyright (c) 2008. 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. + + 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 REGENTS OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +''' +def init(id, cfg): + log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, cfg.port, cfg.python_script)) + return True + +def deinit(id): + log_info("pythonmod: deinit called, module id is %d" % id) + return True + +def inform_super(id, qstate, superqstate, qdata): + return True + +def setTTL(qstate, ttl): + """Sets return_msg TTL and all the RRs TTL""" + if qstate.return_msg: + qstate.return_msg.rep.ttl = ttl + if (qstate.return_msg.rep): + for i in range(0,qstate.return_msg.rep.rrset_count): + d = qstate.return_msg.rep.rrsets[i].entry.data + for j in range(0,d.count+d.rrsig_count): + d.rr_ttl[j] = ttl + +def dataHex(data, prefix=""): + res = "" + for i in range(0, (len(data)+15)/16): + res += "%s0x%02X | " % (prefix, i*16) + d = map(lambda x:ord(x), data[i*16:i*16+17]) + for ch in d: + res += "%02X " % ch + for i in range(0,17-len(d)): + res += " " + res += "| " + for ch in d: + if (ch < 32) or (ch > 127): + res += ". " + else: + res += "%c " % ch + res += "\n" + return res + +def printReturnMsg(qstate): + print "Return MSG rep :: flags: %04X, QDcount: %d, Security:%d, TTL=%d" % (qstate.return_msg.rep.flags, qstate.return_msg.rep.qdcount,qstate.return_msg.rep.security, qstate.return_msg.rep.ttl) + print " qinfo :: qname:",qstate.return_msg.qinfo.qname_list, qstate.return_msg.qinfo.qname_str, "type:",qstate.return_msg.qinfo.qtype_str, "class:",qstate.return_msg.qinfo.qclass_str + if (qstate.return_msg.rep): + print "RRSets:",qstate.return_msg.rep.rrset_count + prevkey = None + for i in range(0,qstate.return_msg.rep.rrset_count): + r = qstate.return_msg.rep.rrsets[i] + rk = r.rk + print i,":",rk.dname_list, rk.dname_str, "flags: %04X" % rk.flags, + print "type:",rk.type_str,"(%d)" % ntohs(rk.type), "class:",rk.rrset_class_str,"(%d)" % ntohs(rk.rrset_class) + + d = r.entry.data + print " RRDatas:",d.count+d.rrsig_count + for j in range(0,d.count+d.rrsig_count): + print " ",j,":","TTL=",d.rr_ttl[j],"RR data:" + print dataHex(d.rr_data[j]," ") + +def operate(id, event, qstate, qdata): + log_info("pythonmod: operate called, id: %d, event:%s" % (id, strmodulevent(event))) + #print "pythonmod: per query data", qdata + + print "Query:", ''.join(map(lambda x:chr(max(32,ord(x))),qstate.qinfo.qname)), qstate.qinfo.qname_list, + print "Type:",qstate.qinfo.qtype_str,"(%d)" % qstate.qinfo.qtype, + print "Class:",qstate.qinfo.qclass_str,"(%d)" % qstate.qinfo.qclass + print + + # TEST: + # > dig @127.0.0.1 www.seznam.cz A + # > dig @127.0.0.1 3.76.75.77.in-addr.arpa. PTR + # prvni dva dotazy vrati TTL 100 + # > dig @127.0.0.1 www.seznam.cz A + # > dig @127.0.0.1 3.76.75.77.in-addr.arpa. PTR + # dalsi dva dotazy vrati TTL 10, ktere se bude s dalsimi dotazy snizovat, nez vyprsi a znovu se zaktivuje mesh + + if qstate.return_msg: + printReturnMsg(qstate) + + #qdn = '.'.join(qstate.qinfo.qname_list) + qdn = qstate.qinfo.qname_str + + #Pokud dotaz konci na nasledujici, pozmenime TTL zpravy, ktera se posle klientovi (return_msg) i zpravy v CACHE + if qdn.endswith(".seznam.cz.") or qdn.endswith('.in-addr.arpa.'): + #pokud je v cache odpoved z iteratoru, pak ji zneplatnime, jinak se moduly nazavolaji do te doby, nez vyprsi TTL + invalidateQueryInCache(qstate, qstate.return_msg.qinfo) + + if (qstate.return_msg.rep.authoritative): + print "X"*300 + + setTTL(qstate, 10) #do cache nastavime TTL na 10 + if not storeQueryInCache(qstate, qstate.return_msg.qinfo, qstate.return_msg.rep, 0): + qstate.ext_state[id] = MODULE_ERROR + return False + + setTTL(qstate, 100) #odpoved klientovi prijde s TTL 100 + qstate.return_rcode = RCODE_NOERROR + + if event == MODULE_EVENT_NEW: + qstate.ext_state[id] = MODULE_WAIT_MODULE + return True + + if event == MODULE_EVENT_MODDONE: + log_info("pythonmod: previous module done") + qstate.ext_state[id] = MODULE_FINISHED + return True + + if event == MODULE_EVENT_PASS: + log_info("pythonmod: event_pass") + qstate.ext_state[id] = MODULE_WAIT_MODULE + return True + + log_err("pythonmod: BAD event") + qstate.ext_state[id] = MODULE_ERROR + return True + +log_info("pythonmod: script loaded.") diff --git a/services/cache/dns.c b/services/cache/dns.c new file mode 100644 index 00000000000..6e99b7fa4a8 --- /dev/null +++ b/services/cache/dns.c @@ -0,0 +1,796 @@ +/* + * services/cache/dns.c - Cache services for DNS using msg and rrset caches. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains the DNS cache. + */ +#include "config.h" +#include "iterator/iter_delegpt.h" +#include "validator/val_nsec.h" +#include "services/cache/dns.h" +#include "services/cache/rrset.h" +#include "util/data/msgreply.h" +#include "util/data/packed_rrset.h" +#include "util/data/dname.h" +#include "util/module.h" +#include "util/net_help.h" +#include "util/regional.h" +#include "util/config_file.h" + +/** store rrsets in the rrset cache. + * @param env: module environment with caches. + * @param rep: contains list of rrsets to store. + * @param now: current time. + * @param leeway: during prefetch how much leeway to update TTLs. + * This makes rrsets (other than type NS) timeout sooner so they get + * updated with a new full TTL. + * Type NS does not get this, because it must not be refreshed from the + * child domain, but keep counting down properly. + * @param pside: if from parentside discovered NS, so that its NS is okay + * in a prefetch situation to be updated (without becoming sticky). + * @param qrep: update rrsets here if cache is better + * @param region: for qrep allocs. + */ +static void +store_rrsets(struct module_env* env, struct reply_info* rep, uint32_t now, + uint32_t leeway, int pside, struct reply_info* qrep, + struct regional* region) +{ + size_t i; + /* see if rrset already exists in cache, if not insert it. */ + for(i=0; irrset_count; i++) { + rep->ref[i].key = rep->rrsets[i]; + rep->ref[i].id = rep->rrsets[i]->id; + /* update ref if it was in the cache */ + switch(rrset_cache_update(env->rrset_cache, &rep->ref[i], + env->alloc, now + ((ntohs(rep->ref[i].key->rk.type)== + LDNS_RR_TYPE_NS && !pside)?0:leeway))) { + case 0: /* ref unchanged, item inserted */ + break; + case 2: /* ref updated, cache is superior */ + if(region) { + struct ub_packed_rrset_key* ck; + lock_rw_rdlock(&rep->ref[i].key->entry.lock); + /* if deleted rrset, do not copy it */ + if(rep->ref[i].key->id == 0) + ck = NULL; + else ck = packed_rrset_copy_region( + rep->ref[i].key, region, now); + lock_rw_unlock(&rep->ref[i].key->entry.lock); + if(ck) { + /* use cached copy if memory allows */ + qrep->rrsets[i] = ck; + } + } + /* no break: also copy key item */ + case 1: /* ref updated, item inserted */ + rep->rrsets[i] = rep->ref[i].key; + } + } +} + +void +dns_cache_store_msg(struct module_env* env, struct query_info* qinfo, + hashvalue_t hash, struct reply_info* rep, uint32_t leeway, int pside, + struct reply_info* qrep, struct regional* region) +{ + struct msgreply_entry* e; + uint32_t ttl = rep->ttl; + size_t i; + + /* store RRsets */ + for(i=0; irrset_count; i++) { + rep->ref[i].key = rep->rrsets[i]; + rep->ref[i].id = rep->rrsets[i]->id; + } + + /* there was a reply_info_sortref(rep) here but it seems to be + * unnecessary, because the cache gets locked per rrset. */ + reply_info_set_ttls(rep, *env->now); + store_rrsets(env, rep, *env->now, leeway, pside, qrep, region); + if(ttl == 0) { + /* we do not store the message, but we did store the RRs, + * which could be useful for delegation information */ + verbose(VERB_ALGO, "TTL 0: dropped msg from cache"); + free(rep); + return; + } + + /* store msg in the cache */ + reply_info_sortref(rep); + if(!(e = query_info_entrysetup(qinfo, rep, hash))) { + log_err("store_msg: malloc failed"); + return; + } + slabhash_insert(env->msg_cache, hash, &e->entry, rep, env->alloc); +} + +/** find closest NS or DNAME and returns the rrset (locked) */ +static struct ub_packed_rrset_key* +find_closest_of_type(struct module_env* env, uint8_t* qname, size_t qnamelen, + uint16_t qclass, uint32_t now, uint16_t searchtype, int stripfront) +{ + struct ub_packed_rrset_key *rrset; + uint8_t lablen; + + if(stripfront) { + /* strip off so that DNAMEs have strict subdomain match */ + lablen = *qname; + qname += lablen + 1; + qnamelen -= lablen + 1; + } + + /* snip off front part of qname until the type is found */ + while(qnamelen > 0) { + if((rrset = rrset_cache_lookup(env->rrset_cache, qname, + qnamelen, searchtype, qclass, 0, now, 0))) + return rrset; + + /* snip off front label */ + lablen = *qname; + qname += lablen + 1; + qnamelen -= lablen + 1; + } + return NULL; +} + +/** add addr to additional section */ +static void +addr_to_additional(struct ub_packed_rrset_key* rrset, struct regional* region, + struct dns_msg* msg, uint32_t now) +{ + if((msg->rep->rrsets[msg->rep->rrset_count] = + packed_rrset_copy_region(rrset, region, now))) { + msg->rep->ar_numrrsets++; + msg->rep->rrset_count++; + } +} + +/** lookup message in message cache */ +static struct msgreply_entry* +msg_cache_lookup(struct module_env* env, uint8_t* qname, size_t qnamelen, + uint16_t qtype, uint16_t qclass, uint32_t now, int wr) +{ + struct lruhash_entry* e; + struct query_info k; + hashvalue_t h; + + k.qname = qname; + k.qname_len = qnamelen; + k.qtype = qtype; + k.qclass = qclass; + h = query_info_hash(&k); + e = slabhash_lookup(env->msg_cache, h, &k, wr); + + if(!e) return NULL; + if( now > ((struct reply_info*)e->data)->ttl ) { + lock_rw_unlock(&e->lock); + return NULL; + } + return (struct msgreply_entry*)e->key; +} + +/** find and add A and AAAA records for nameservers in delegpt */ +static int +find_add_addrs(struct module_env* env, uint16_t qclass, + struct regional* region, struct delegpt* dp, uint32_t now, + struct dns_msg** msg) +{ + struct delegpt_ns* ns; + struct msgreply_entry* neg; + struct ub_packed_rrset_key* akey; + for(ns = dp->nslist; ns; ns = ns->next) { + akey = rrset_cache_lookup(env->rrset_cache, ns->name, + ns->namelen, LDNS_RR_TYPE_A, qclass, 0, now, 0); + if(akey) { + if(!delegpt_add_rrset_A(dp, region, akey, 0)) { + lock_rw_unlock(&akey->entry.lock); + return 0; + } + if(msg) + addr_to_additional(akey, region, *msg, now); + lock_rw_unlock(&akey->entry.lock); + } else { + neg = msg_cache_lookup(env, ns->name, ns->namelen, + LDNS_RR_TYPE_A, qclass, now, 0); + if(neg) { + delegpt_add_neg_msg(dp, neg); + lock_rw_unlock(&neg->entry.lock); + } + } + akey = rrset_cache_lookup(env->rrset_cache, ns->name, + ns->namelen, LDNS_RR_TYPE_AAAA, qclass, 0, now, 0); + if(akey) { + if(!delegpt_add_rrset_AAAA(dp, region, akey, 0)) { + lock_rw_unlock(&akey->entry.lock); + return 0; + } + if(msg) + addr_to_additional(akey, region, *msg, now); + lock_rw_unlock(&akey->entry.lock); + } else { + neg = msg_cache_lookup(env, ns->name, ns->namelen, + LDNS_RR_TYPE_AAAA, qclass, now, 0); + if(neg) { + delegpt_add_neg_msg(dp, neg); + lock_rw_unlock(&neg->entry.lock); + } + } + } + return 1; +} + +/** find and add A and AAAA records for missing nameservers in delegpt */ +int +cache_fill_missing(struct module_env* env, uint16_t qclass, + struct regional* region, struct delegpt* dp) +{ + struct delegpt_ns* ns; + struct msgreply_entry* neg; + struct ub_packed_rrset_key* akey; + uint32_t now = *env->now; + for(ns = dp->nslist; ns; ns = ns->next) { + akey = rrset_cache_lookup(env->rrset_cache, ns->name, + ns->namelen, LDNS_RR_TYPE_A, qclass, 0, now, 0); + if(akey) { + if(!delegpt_add_rrset_A(dp, region, akey, (int)ns->lame)) { + lock_rw_unlock(&akey->entry.lock); + return 0; + } + log_nametypeclass(VERB_ALGO, "found in cache", + ns->name, LDNS_RR_TYPE_A, qclass); + lock_rw_unlock(&akey->entry.lock); + } else { + neg = msg_cache_lookup(env, ns->name, ns->namelen, + LDNS_RR_TYPE_A, qclass, now, 0); + if(neg) { + delegpt_add_neg_msg(dp, neg); + lock_rw_unlock(&neg->entry.lock); + } + } + akey = rrset_cache_lookup(env->rrset_cache, ns->name, + ns->namelen, LDNS_RR_TYPE_AAAA, qclass, 0, now, 0); + if(akey) { + if(!delegpt_add_rrset_AAAA(dp, region, akey, (int)ns->lame)) { + lock_rw_unlock(&akey->entry.lock); + return 0; + } + log_nametypeclass(VERB_ALGO, "found in cache", + ns->name, LDNS_RR_TYPE_AAAA, qclass); + lock_rw_unlock(&akey->entry.lock); + } else { + neg = msg_cache_lookup(env, ns->name, ns->namelen, + LDNS_RR_TYPE_AAAA, qclass, now, 0); + if(neg) { + delegpt_add_neg_msg(dp, neg); + lock_rw_unlock(&neg->entry.lock); + } + } + } + return 1; +} + +/** find and add DS or NSEC to delegation msg */ +static void +find_add_ds(struct module_env* env, struct regional* region, + struct dns_msg* msg, struct delegpt* dp, uint32_t now) +{ + /* Lookup the DS or NSEC at the delegation point. */ + struct ub_packed_rrset_key* rrset = rrset_cache_lookup( + env->rrset_cache, dp->name, dp->namelen, LDNS_RR_TYPE_DS, + msg->qinfo.qclass, 0, now, 0); + if(!rrset) { + /* NOTE: this won't work for alternate NSEC schemes + * (opt-in, NSEC3) */ + rrset = rrset_cache_lookup(env->rrset_cache, dp->name, + dp->namelen, LDNS_RR_TYPE_NSEC, msg->qinfo.qclass, + 0, now, 0); + /* Note: the PACKED_RRSET_NSEC_AT_APEX flag is not used. + * since this is a referral, we need the NSEC at the parent + * side of the zone cut, not the NSEC at apex side. */ + if(rrset && nsec_has_type(rrset, LDNS_RR_TYPE_DS)) { + lock_rw_unlock(&rrset->entry.lock); + rrset = NULL; /* discard wrong NSEC */ + } + } + if(rrset) { + /* add it to auth section. This is the second rrset. */ + if((msg->rep->rrsets[msg->rep->rrset_count] = + packed_rrset_copy_region(rrset, region, now))) { + msg->rep->ns_numrrsets++; + msg->rep->rrset_count++; + } + lock_rw_unlock(&rrset->entry.lock); + } +} + +struct dns_msg* +dns_msg_create(uint8_t* qname, size_t qnamelen, uint16_t qtype, + uint16_t qclass, struct regional* region, size_t capacity) +{ + struct dns_msg* msg = (struct dns_msg*)regional_alloc(region, + sizeof(struct dns_msg)); + if(!msg) + return NULL; + msg->qinfo.qname = regional_alloc_init(region, qname, qnamelen); + if(!msg->qinfo.qname) + return NULL; + msg->qinfo.qname_len = qnamelen; + msg->qinfo.qtype = qtype; + msg->qinfo.qclass = qclass; + /* non-packed reply_info, because it needs to grow the array */ + msg->rep = (struct reply_info*)regional_alloc_zero(region, + sizeof(struct reply_info)-sizeof(struct rrset_ref)); + if(!msg->rep) + return NULL; + msg->rep->flags = BIT_QR; /* with QR, no AA */ + msg->rep->qdcount = 1; + msg->rep->rrsets = (struct ub_packed_rrset_key**) + regional_alloc(region, + capacity*sizeof(struct ub_packed_rrset_key*)); + if(!msg->rep->rrsets) + return NULL; + return msg; +} + +int +dns_msg_authadd(struct dns_msg* msg, struct regional* region, + struct ub_packed_rrset_key* rrset, uint32_t now) +{ + if(!(msg->rep->rrsets[msg->rep->rrset_count++] = + packed_rrset_copy_region(rrset, region, now))) + return 0; + msg->rep->ns_numrrsets++; + return 1; +} + +struct delegpt* +dns_cache_find_delegation(struct module_env* env, uint8_t* qname, + size_t qnamelen, uint16_t qtype, uint16_t qclass, + struct regional* region, struct dns_msg** msg, uint32_t now) +{ + /* try to find closest NS rrset */ + struct ub_packed_rrset_key* nskey; + struct packed_rrset_data* nsdata; + struct delegpt* dp; + + nskey = find_closest_of_type(env, qname, qnamelen, qclass, now, + LDNS_RR_TYPE_NS, 0); + if(!nskey) /* hope the caller has hints to prime or something */ + return NULL; + nsdata = (struct packed_rrset_data*)nskey->entry.data; + /* got the NS key, create delegation point */ + dp = delegpt_create(region); + if(!dp || !delegpt_set_name(dp, region, nskey->rk.dname)) { + lock_rw_unlock(&nskey->entry.lock); + log_err("find_delegation: out of memory"); + return NULL; + } + /* create referral message */ + if(msg) { + /* allocate the array to as much as we could need: + * NS rrset + DS/NSEC rrset + + * A rrset for every NS RR + * AAAA rrset for every NS RR + */ + *msg = dns_msg_create(qname, qnamelen, qtype, qclass, region, + 2 + nsdata->count*2); + if(!*msg || !dns_msg_authadd(*msg, region, nskey, now)) { + lock_rw_unlock(&nskey->entry.lock); + log_err("find_delegation: out of memory"); + return NULL; + } + } + if(!delegpt_rrset_add_ns(dp, region, nskey, 0)) + log_err("find_delegation: addns out of memory"); + lock_rw_unlock(&nskey->entry.lock); /* first unlock before next lookup*/ + /* find and add DS/NSEC (if any) */ + if(msg) + find_add_ds(env, region, *msg, dp, now); + /* find and add A entries */ + if(!find_add_addrs(env, qclass, region, dp, now, msg)) + log_err("find_delegation: addrs out of memory"); + return dp; +} + +/** allocate dns_msg from query_info and reply_info */ +static struct dns_msg* +gen_dns_msg(struct regional* region, struct query_info* q, size_t num) +{ + struct dns_msg* msg = (struct dns_msg*)regional_alloc(region, + sizeof(struct dns_msg)); + if(!msg) + return NULL; + memcpy(&msg->qinfo, q, sizeof(struct query_info)); + msg->qinfo.qname = regional_alloc_init(region, q->qname, q->qname_len); + if(!msg->qinfo.qname) + return NULL; + /* allocate replyinfo struct and rrset key array separately */ + msg->rep = (struct reply_info*)regional_alloc(region, + sizeof(struct reply_info) - sizeof(struct rrset_ref)); + if(!msg->rep) + return NULL; + msg->rep->rrsets = (struct ub_packed_rrset_key**) + regional_alloc(region, + num * sizeof(struct ub_packed_rrset_key*)); + if(!msg->rep->rrsets) + return NULL; + return msg; +} + +/** generate dns_msg from cached message */ +static struct dns_msg* +tomsg(struct module_env* env, struct query_info* q, struct reply_info* r, + struct regional* region, uint32_t now, struct regional* scratch) +{ + struct dns_msg* msg; + size_t i; + if(now > r->ttl) + return NULL; + msg = gen_dns_msg(region, q, r->rrset_count); + if(!msg) + return NULL; + msg->rep->flags = r->flags; + msg->rep->qdcount = r->qdcount; + msg->rep->ttl = r->ttl - now; + if(r->prefetch_ttl > now) + msg->rep->prefetch_ttl = r->prefetch_ttl - now; + else msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl); + msg->rep->security = r->security; + msg->rep->an_numrrsets = r->an_numrrsets; + msg->rep->ns_numrrsets = r->ns_numrrsets; + msg->rep->ar_numrrsets = r->ar_numrrsets; + msg->rep->rrset_count = r->rrset_count; + msg->rep->authoritative = r->authoritative; + if(!rrset_array_lock(r->ref, r->rrset_count, now)) + return NULL; + if(r->an_numrrsets > 0 && (r->rrsets[0]->rk.type == htons( + LDNS_RR_TYPE_CNAME) || r->rrsets[0]->rk.type == htons( + LDNS_RR_TYPE_DNAME)) && !reply_check_cname_chain(r)) { + /* cname chain is now invalid, reconstruct msg */ + rrset_array_unlock(r->ref, r->rrset_count); + return NULL; + } + if(r->security == sec_status_secure && !reply_all_rrsets_secure(r)) { + /* message rrsets have changed status, revalidate */ + rrset_array_unlock(r->ref, r->rrset_count); + return NULL; + } + for(i=0; irep->rrset_count; i++) { + msg->rep->rrsets[i] = packed_rrset_copy_region(r->rrsets[i], + region, now); + if(!msg->rep->rrsets[i]) { + rrset_array_unlock(r->ref, r->rrset_count); + return NULL; + } + } + rrset_array_unlock_touch(env->rrset_cache, scratch, r->ref, + r->rrset_count); + return msg; +} + +/** synthesize RRset-only response from cached RRset item */ +static struct dns_msg* +rrset_msg(struct ub_packed_rrset_key* rrset, struct regional* region, + uint32_t now, struct query_info* q) +{ + struct dns_msg* msg; + struct packed_rrset_data* d = (struct packed_rrset_data*) + rrset->entry.data; + if(now > d->ttl) + return NULL; + msg = gen_dns_msg(region, q, 1); /* only the CNAME (or other) RRset */ + if(!msg) + return NULL; + msg->rep->flags = BIT_QR; /* reply, no AA, no error */ + msg->rep->authoritative = 0; /* reply stored in cache can't be authoritative */ + msg->rep->qdcount = 1; + msg->rep->ttl = d->ttl - now; + msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl); + msg->rep->security = sec_status_unchecked; + msg->rep->an_numrrsets = 1; + msg->rep->ns_numrrsets = 0; + msg->rep->ar_numrrsets = 0; + msg->rep->rrset_count = 1; + msg->rep->rrsets[0] = packed_rrset_copy_region(rrset, region, now); + if(!msg->rep->rrsets[0]) /* copy CNAME */ + return NULL; + return msg; +} + +/** synthesize DNAME+CNAME response from cached DNAME item */ +static struct dns_msg* +synth_dname_msg(struct ub_packed_rrset_key* rrset, struct regional* region, + uint32_t now, struct query_info* q) +{ + struct dns_msg* msg; + struct ub_packed_rrset_key* ck; + struct packed_rrset_data* newd, *d = (struct packed_rrset_data*) + rrset->entry.data; + uint8_t* newname, *dtarg = NULL; + size_t newlen, dtarglen; + if(now > d->ttl) + return NULL; + /* only allow validated (with DNSSEC) DNAMEs used from cache + * for insecure DNAMEs, query again. */ + if(d->security != sec_status_secure) + return NULL; + msg = gen_dns_msg(region, q, 2); /* DNAME + CNAME RRset */ + if(!msg) + return NULL; + msg->rep->flags = BIT_QR; /* reply, no AA, no error */ + msg->rep->authoritative = 0; /* reply stored in cache can't be authoritative */ + msg->rep->qdcount = 1; + msg->rep->ttl = d->ttl - now; + msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl); + msg->rep->security = sec_status_unchecked; + msg->rep->an_numrrsets = 1; + msg->rep->ns_numrrsets = 0; + msg->rep->ar_numrrsets = 0; + msg->rep->rrset_count = 1; + msg->rep->rrsets[0] = packed_rrset_copy_region(rrset, region, now); + if(!msg->rep->rrsets[0]) /* copy DNAME */ + return NULL; + /* synth CNAME rrset */ + get_cname_target(rrset, &dtarg, &dtarglen); + if(!dtarg) + return NULL; + newlen = q->qname_len + dtarglen - rrset->rk.dname_len; + if(newlen > LDNS_MAX_DOMAINLEN) { + msg->rep->flags |= LDNS_RCODE_YXDOMAIN; + return msg; + } + newname = (uint8_t*)regional_alloc(region, newlen); + if(!newname) + return NULL; + /* new name is concatenation of qname front (without DNAME owner) + * and DNAME target name */ + memcpy(newname, q->qname, q->qname_len-rrset->rk.dname_len); + memmove(newname+(q->qname_len-rrset->rk.dname_len), dtarg, dtarglen); + /* create rest of CNAME rrset */ + ck = (struct ub_packed_rrset_key*)regional_alloc(region, + sizeof(struct ub_packed_rrset_key)); + if(!ck) + return NULL; + memset(&ck->entry, 0, sizeof(ck->entry)); + msg->rep->rrsets[1] = ck; + ck->entry.key = ck; + ck->rk.type = htons(LDNS_RR_TYPE_CNAME); + ck->rk.rrset_class = rrset->rk.rrset_class; + ck->rk.flags = 0; + ck->rk.dname = regional_alloc_init(region, q->qname, q->qname_len); + if(!ck->rk.dname) + return NULL; + ck->rk.dname_len = q->qname_len; + ck->entry.hash = rrset_key_hash(&ck->rk); + newd = (struct packed_rrset_data*)regional_alloc_zero(region, + sizeof(struct packed_rrset_data) + sizeof(size_t) + + sizeof(uint8_t*) + sizeof(uint32_t) + sizeof(uint16_t) + + newlen); + if(!newd) + return NULL; + ck->entry.data = newd; + newd->ttl = 0; /* 0 for synthesized CNAME TTL */ + newd->count = 1; + newd->rrsig_count = 0; + newd->trust = rrset_trust_ans_noAA; + newd->rr_len = (size_t*)((uint8_t*)newd + + sizeof(struct packed_rrset_data)); + newd->rr_len[0] = newlen + sizeof(uint16_t); + packed_rrset_ptr_fixup(newd); + newd->rr_ttl[0] = newd->ttl; + msg->rep->ttl = newd->ttl; + msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(newd->ttl); + ldns_write_uint16(newd->rr_data[0], newlen); + memmove(newd->rr_data[0] + sizeof(uint16_t), newname, newlen); + msg->rep->an_numrrsets ++; + msg->rep->rrset_count ++; + return msg; +} + +struct dns_msg* +dns_cache_lookup(struct module_env* env, + uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass, + struct regional* region, struct regional* scratch) +{ + struct lruhash_entry* e; + struct query_info k; + hashvalue_t h; + uint32_t now = *env->now; + struct ub_packed_rrset_key* rrset; + + /* lookup first, this has both NXdomains and ANSWER responses */ + k.qname = qname; + k.qname_len = qnamelen; + k.qtype = qtype; + k.qclass = qclass; + h = query_info_hash(&k); + e = slabhash_lookup(env->msg_cache, h, &k, 0); + if(e) { + struct msgreply_entry* key = (struct msgreply_entry*)e->key; + struct reply_info* data = (struct reply_info*)e->data; + struct dns_msg* msg = tomsg(env, &key->key, data, region, now, + scratch); + if(msg) { + lock_rw_unlock(&e->lock); + return msg; + } + /* could be msg==NULL; due to TTL or not all rrsets available */ + lock_rw_unlock(&e->lock); + } + + /* see if a DNAME exists. Checked for first, to enforce that DNAMEs + * are more important, the CNAME is resynthesized and thus + * consistent with the DNAME */ + if( (rrset=find_closest_of_type(env, qname, qnamelen, qclass, now, + LDNS_RR_TYPE_DNAME, 1))) { + /* synthesize a DNAME+CNAME message based on this */ + struct dns_msg* msg = synth_dname_msg(rrset, region, now, &k); + if(msg) { + lock_rw_unlock(&rrset->entry.lock); + return msg; + } + lock_rw_unlock(&rrset->entry.lock); + } + + /* see if we have CNAME for this domain, + * but not for DS records (which are part of the parent) */ + if( qtype != LDNS_RR_TYPE_DS && + (rrset=rrset_cache_lookup(env->rrset_cache, qname, qnamelen, + LDNS_RR_TYPE_CNAME, qclass, 0, now, 0))) { + struct dns_msg* msg = rrset_msg(rrset, region, now, &k); + if(msg) { + lock_rw_unlock(&rrset->entry.lock); + return msg; + } + lock_rw_unlock(&rrset->entry.lock); + } + + /* construct DS, DNSKEY, DLV messages from rrset cache. */ + if((qtype == LDNS_RR_TYPE_DS || qtype == LDNS_RR_TYPE_DNSKEY || + qtype == LDNS_RR_TYPE_DLV) && + (rrset=rrset_cache_lookup(env->rrset_cache, qname, qnamelen, + qtype, qclass, 0, now, 0))) { + /* if the rrset is from the additional section, and the + * signatures have fallen off, then do not synthesize a msg + * instead, allow a full query for signed results to happen. + * Forego all rrset data from additional section, because + * some signatures may not be present and cause validation + * failure. + */ + struct packed_rrset_data *d = (struct packed_rrset_data*) + rrset->entry.data; + if(d->trust != rrset_trust_add_noAA && + d->trust != rrset_trust_add_AA && + (qtype == LDNS_RR_TYPE_DS || + (d->trust != rrset_trust_auth_noAA + && d->trust != rrset_trust_auth_AA) )) { + struct dns_msg* msg = rrset_msg(rrset, region, now, &k); + if(msg) { + lock_rw_unlock(&rrset->entry.lock); + return msg; + } + } + lock_rw_unlock(&rrset->entry.lock); + } + + /* stop downwards cache search on NXDOMAIN. + * Empty nonterminals are NOERROR, so an NXDOMAIN for foo + * means bla.foo also does not exist. The DNSSEC proofs are + * the same. We search upwards for NXDOMAINs. */ + if(env->cfg->harden_below_nxdomain) + while(!dname_is_root(k.qname)) { + dname_remove_label(&k.qname, &k.qname_len); + h = query_info_hash(&k); + e = slabhash_lookup(env->msg_cache, h, &k, 0); + if(e) { + struct reply_info* data = (struct reply_info*)e->data; + struct dns_msg* msg; + if(FLAGS_GET_RCODE(data->flags) == LDNS_RCODE_NXDOMAIN + && data->security == sec_status_secure + && (msg=tomsg(env, &k, data, region, now, scratch))){ + lock_rw_unlock(&e->lock); + msg->qinfo.qname=qname; + msg->qinfo.qname_len=qnamelen; + /* check that DNSSEC really works out */ + msg->rep->security = sec_status_unchecked; + return msg; + } + lock_rw_unlock(&e->lock); + } + } + + return NULL; +} + +int +dns_cache_store(struct module_env* env, struct query_info* msgqinf, + struct reply_info* msgrep, int is_referral, uint32_t leeway, int pside, + struct regional* region) +{ + struct reply_info* rep = NULL; + /* alloc, malloc properly (not in region, like msg is) */ + rep = reply_info_copy(msgrep, env->alloc, NULL); + if(!rep) + return 0; + /* ttl must be relative ;i.e. 0..86400 not time(0)+86400. + * the env->now is added to message and RRsets in this routine. */ + /* the leeway is used to invalidate other rrsets earlier */ + + if(is_referral) { + /* store rrsets */ + struct rrset_ref ref; + size_t i; + for(i=0; irrset_count; i++) { + packed_rrset_ttl_add((struct packed_rrset_data*) + rep->rrsets[i]->entry.data, *env->now); + ref.key = rep->rrsets[i]; + ref.id = rep->rrsets[i]->id; + /*ignore ret: it was in the cache, ref updated */ + /* no leeway for typeNS */ + (void)rrset_cache_update(env->rrset_cache, &ref, + env->alloc, *env->now + + ((ntohs(ref.key->rk.type)==LDNS_RR_TYPE_NS + && !pside) ? 0:leeway)); + } + free(rep); + return 1; + } else { + /* store msg, and rrsets */ + struct query_info qinf; + hashvalue_t h; + + qinf = *msgqinf; + qinf.qname = memdup(msgqinf->qname, msgqinf->qname_len); + if(!qinf.qname) { + reply_info_parsedelete(rep, env->alloc); + return 0; + } + /* fixup flags to be sensible for a reply based on the cache */ + /* this module means that RA is available. It is an answer QR. + * Not AA from cache. Not CD in cache (depends on client bit). */ + rep->flags |= (BIT_RA | BIT_QR); + rep->flags &= ~(BIT_AA | BIT_CD); + h = query_info_hash(&qinf); + dns_cache_store_msg(env, &qinf, h, rep, leeway, pside, msgrep, + region); + /* qname is used inside query_info_entrysetup, and set to + * NULL. If it has not been used, free it. free(0) is safe. */ + free(qinf.qname); + } + return 1; +} diff --git a/services/cache/dns.h b/services/cache/dns.h new file mode 100644 index 00000000000..bc9f57c9c0d --- /dev/null +++ b/services/cache/dns.h @@ -0,0 +1,182 @@ +/* + * services/cache/dns.h - Cache services for DNS using msg and rrset caches. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains the DNS cache. + */ + +#ifndef SERVICES_CACHE_DNS_H +#define SERVICES_CACHE_DNS_H +#include "util/storage/lruhash.h" +#include "util/data/msgreply.h" +struct module_env; +struct query_info; +struct reply_info; +struct regional; +struct delegpt; + +/** + * Region allocated message reply + */ +struct dns_msg { + /** query info */ + struct query_info qinfo; + /** reply info - ptr to packed repinfo structure */ + struct reply_info *rep; +}; + +/** + * Allocate a dns_msg with malloc/alloc structure and store in dns cache. + * + * @param env: environment, with alloc structure and dns cache. + * @param qinf: query info, the query for which answer is stored. + * this is allocated in a region, and will be copied to malloc area + * before insertion. + * @param rep: reply in dns_msg from dns_alloc_msg for example. + * this is allocated in a region, and will be copied to malloc area + * before insertion. + * @param is_referral: If true, then the given message to be stored is a + * referral. The cache implementation may use this as a hint. + * It will store only the RRsets, not the message. + * @param leeway: TTL value, if not 0, other rrsets are considered expired + * that many seconds before actual TTL expiry. + * @param pside: if true, information came from a server which was fetched + * from the parentside of the zonecut. This means that the type NS + * can be updated to full TTL even in prefetch situations. + * @param region: region to allocate better entries from cache into. + * (used when is_referral is false). + * @return 0 on alloc error (out of memory). + */ +int dns_cache_store(struct module_env* env, struct query_info* qinf, + struct reply_info* rep, int is_referral, uint32_t leeway, int pside, + struct regional* region); + +/** + * Store message in the cache. Stores in message cache and rrset cache. + * Both qinfo and rep should be malloced and are put in the cache. + * They should not be used after this call, as they are then in shared cache. + * Does not return errors, they are logged and only lead to less cache. + * + * @param env: module environment with the DNS cache. + * @param qinfo: query info + * @param hash: hash over qinfo. + * @param rep: reply info, together with qinfo makes up the message. + * Adjusts the reply info TTLs to absolute time. + * @param leeway: TTL value, if not 0, other rrsets are considered expired + * that many seconds before actual TTL expiry. + * @param pside: if true, information came from a server which was fetched + * from the parentside of the zonecut. This means that the type NS + * can be updated to full TTL even in prefetch situations. + * @param qrep: message that can be altered with better rrs from cache. + * @param region: to allocate into for qmsg. + */ +void dns_cache_store_msg(struct module_env* env, struct query_info* qinfo, + hashvalue_t hash, struct reply_info* rep, uint32_t leeway, int pside, + struct reply_info* qrep, struct regional* region); + +/** + * Find a delegation from the cache. + * @param env: module environment with the DNS cache. + * @param qname: query name. + * @param qnamelen: length of qname. + * @param qtype: query type. + * @param qclass: query class. + * @param region: where to allocate result delegation. + * @param msg: if not NULL, delegation message is returned here, synthesized + * from the cache. + * @param timenow: the time now, for checking if TTL on cache entries is OK. + * @return new delegation or NULL on error or if not found in cache. + */ +struct delegpt* dns_cache_find_delegation(struct module_env* env, + uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass, + struct regional* region, struct dns_msg** msg, uint32_t timenow); + +/** + * Find cached message + * @param env: module environment with the DNS cache. + * @param qname: query name. + * @param qnamelen: length of qname. + * @param qtype: query type. + * @param qclass: query class. + * @param region: where to allocate result. + * @param scratch: where to allocate temporary data. + * @return new response message (alloced in region, rrsets do not have IDs). + * or NULL on error or if not found in cache. + * TTLs are made relative to the current time. + */ +struct dns_msg* dns_cache_lookup(struct module_env* env, + uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass, + struct regional* region, struct regional* scratch); + +/** + * find and add A and AAAA records for missing nameservers in delegpt + * @param env: module environment with rrset cache + * @param qclass: which class to look in. + * @param region: where to store new dp info. + * @param dp: delegation point to fill missing entries. + * @return false on alloc failure. + */ +int cache_fill_missing(struct module_env* env, uint16_t qclass, + struct regional* region, struct delegpt* dp); + +/** + * Utility, create new, unpacked data structure for cache response. + * QR bit set, no AA. Query set as indicated. Space for number of rrsets. + * @param qname: query section name + * @param qnamelen: len of qname + * @param qtype: query section type + * @param qclass: query section class + * @param region: where to alloc. + * @param capacity: number of rrsets space to create in the array. + * @return new dns_msg struct or NULL on mem fail. + */ +struct dns_msg* dns_msg_create(uint8_t* qname, size_t qnamelen, uint16_t qtype, + uint16_t qclass, struct regional* region, size_t capacity); + +/** + * Add rrset to authority section in unpacked dns_msg message. Must have enough + * space left, does not grow the array. + * @param msg: msg to put it in. + * @param region: region to alloc in + * @param rrset: to add in authority section + * @param now: now. + * @return true if worked, false on fail + */ +int dns_msg_authadd(struct dns_msg* msg, struct regional* region, + struct ub_packed_rrset_key* rrset, uint32_t now); + +#endif /* SERVICES_CACHE_DNS_H */ diff --git a/services/cache/infra.c b/services/cache/infra.c new file mode 100644 index 00000000000..dbbd50326e5 --- /dev/null +++ b/services/cache/infra.c @@ -0,0 +1,564 @@ +/* + * services/cache/infra.c - infrastructure cache, server rtt and capabilities + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains the infrastructure cache. + */ +#include "config.h" +#include +#include "services/cache/infra.h" +#include "util/storage/slabhash.h" +#include "util/storage/lookup3.h" +#include "util/data/dname.h" +#include "util/log.h" +#include "util/net_help.h" +#include "util/config_file.h" +#include "iterator/iterator.h" + +/** Timeout when only a single probe query per IP is allowed. */ +#define PROBE_MAXRTO 12000 /* in msec */ + +/** number of timeouts for a type when the domain can be blocked ; + * even if another type has completely rtt maxed it, the different type + * can do this number of packets (until those all timeout too) */ +#define TIMEOUT_COUNT_MAX 3 + +size_t +infra_sizefunc(void* k, void* ATTR_UNUSED(d)) +{ + struct infra_key* key = (struct infra_key*)k; + return sizeof(*key) + sizeof(struct infra_data) + key->namelen + + lock_get_mem(&key->entry.lock); +} + +int +infra_compfunc(void* key1, void* key2) +{ + struct infra_key* k1 = (struct infra_key*)key1; + struct infra_key* k2 = (struct infra_key*)key2; + int r = sockaddr_cmp(&k1->addr, k1->addrlen, &k2->addr, k2->addrlen); + if(r != 0) + return r; + if(k1->namelen != k2->namelen) { + if(k1->namelen < k2->namelen) + return -1; + return 1; + } + return query_dname_compare(k1->zonename, k2->zonename); +} + +void +infra_delkeyfunc(void* k, void* ATTR_UNUSED(arg)) +{ + struct infra_key* key = (struct infra_key*)k; + if(!key) + return; + lock_rw_destroy(&key->entry.lock); + free(key->zonename); + free(key); +} + +void +infra_deldatafunc(void* d, void* ATTR_UNUSED(arg)) +{ + struct infra_data* data = (struct infra_data*)d; + free(data); +} + +struct infra_cache* +infra_create(struct config_file* cfg) +{ + struct infra_cache* infra = (struct infra_cache*)calloc(1, + sizeof(struct infra_cache)); + size_t maxmem = cfg->infra_cache_numhosts * (sizeof(struct infra_key)+ + sizeof(struct infra_data)+INFRA_BYTES_NAME); + infra->hosts = slabhash_create(cfg->infra_cache_slabs, + INFRA_HOST_STARTSIZE, maxmem, &infra_sizefunc, &infra_compfunc, + &infra_delkeyfunc, &infra_deldatafunc, NULL); + if(!infra->hosts) { + free(infra); + return NULL; + } + infra->host_ttl = cfg->host_ttl; + return infra; +} + +void +infra_delete(struct infra_cache* infra) +{ + if(!infra) + return; + slabhash_delete(infra->hosts); + free(infra); +} + +struct infra_cache* +infra_adjust(struct infra_cache* infra, struct config_file* cfg) +{ + size_t maxmem; + if(!infra) + return infra_create(cfg); + infra->host_ttl = cfg->host_ttl; + maxmem = cfg->infra_cache_numhosts * (sizeof(struct infra_key)+ + sizeof(struct infra_data)+INFRA_BYTES_NAME); + if(maxmem != slabhash_get_size(infra->hosts) || + cfg->infra_cache_slabs != infra->hosts->size) { + infra_delete(infra); + infra = infra_create(cfg); + } + return infra; +} + +/** calculate the hash value for a host key */ +static hashvalue_t +hash_addr(struct sockaddr_storage* addr, socklen_t addrlen) +{ + hashvalue_t h = 0xab; + /* select the pieces to hash, some OS have changing data inside */ + if(addr_is_ip6(addr, addrlen)) { + struct sockaddr_in6* in6 = (struct sockaddr_in6*)addr; + h = hashlittle(&in6->sin6_family, sizeof(in6->sin6_family), h); + h = hashlittle(&in6->sin6_port, sizeof(in6->sin6_port), h); + h = hashlittle(&in6->sin6_addr, INET6_SIZE, h); + } else { + struct sockaddr_in* in = (struct sockaddr_in*)addr; + h = hashlittle(&in->sin_family, sizeof(in->sin_family), h); + h = hashlittle(&in->sin_port, sizeof(in->sin_port), h); + h = hashlittle(&in->sin_addr, INET_SIZE, h); + } + return h; +} + +/** calculate infra hash for a key */ +static hashvalue_t +hash_infra(struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* name) +{ + return dname_query_hash(name, hash_addr(addr, addrlen)); +} + +/** lookup version that does not check host ttl (you check it) */ +struct lruhash_entry* +infra_lookup_nottl(struct infra_cache* infra, struct sockaddr_storage* addr, + socklen_t addrlen, uint8_t* name, size_t namelen, int wr) +{ + struct infra_key k; + k.addrlen = addrlen; + memcpy(&k.addr, addr, addrlen); + k.namelen = namelen; + k.zonename = name; + k.entry.hash = hash_infra(addr, addrlen, name); + k.entry.key = (void*)&k; + k.entry.data = NULL; + return slabhash_lookup(infra->hosts, k.entry.hash, &k, wr); +} + +/** init the data elements */ +static void +data_entry_init(struct infra_cache* infra, struct lruhash_entry* e, + uint32_t timenow) +{ + struct infra_data* data = (struct infra_data*)e->data; + data->ttl = timenow + infra->host_ttl; + rtt_init(&data->rtt); + data->edns_version = 0; + data->edns_lame_known = 0; + data->probedelay = 0; + data->isdnsseclame = 0; + data->rec_lame = 0; + data->lame_type_A = 0; + data->lame_other = 0; + data->timeout_A = 0; + data->timeout_AAAA = 0; + data->timeout_other = 0; +} + +/** + * Create and init a new entry for a host + * @param infra: infra structure with config parameters. + * @param addr: host address. + * @param addrlen: length of addr. + * @param name: name of zone + * @param namelen: length of name. + * @param tm: time now. + * @return: the new entry or NULL on malloc failure. + */ +static struct lruhash_entry* +new_entry(struct infra_cache* infra, struct sockaddr_storage* addr, + socklen_t addrlen, uint8_t* name, size_t namelen, uint32_t tm) +{ + struct infra_data* data; + struct infra_key* key = (struct infra_key*)malloc(sizeof(*key)); + if(!key) + return NULL; + data = (struct infra_data*)malloc(sizeof(struct infra_data)); + if(!data) { + free(key); + return NULL; + } + key->zonename = memdup(name, namelen); + if(!key->zonename) { + free(key); + free(data); + return NULL; + } + key->namelen = namelen; + lock_rw_init(&key->entry.lock); + key->entry.hash = hash_infra(addr, addrlen, name); + key->entry.key = (void*)key; + key->entry.data = (void*)data; + key->addrlen = addrlen; + memcpy(&key->addr, addr, addrlen); + data_entry_init(infra, &key->entry, tm); + return &key->entry; +} + +int +infra_host(struct infra_cache* infra, struct sockaddr_storage* addr, + socklen_t addrlen, uint8_t* nm, size_t nmlen, uint32_t timenow, + int* edns_vs, uint8_t* edns_lame_known, int* to) +{ + struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen, + nm, nmlen, 0); + struct infra_data* data; + int wr = 0; + if(e && ((struct infra_data*)e->data)->ttl < timenow) { + /* it expired, try to reuse existing entry */ + int old = ((struct infra_data*)e->data)->rtt.rto; + uint8_t tA = ((struct infra_data*)e->data)->timeout_A; + uint8_t tAAAA = ((struct infra_data*)e->data)->timeout_AAAA; + uint8_t tother = ((struct infra_data*)e->data)->timeout_other; + lock_rw_unlock(&e->lock); + e = infra_lookup_nottl(infra, addr, addrlen, nm, nmlen, 1); + if(e) { + /* if its still there we have a writelock, init */ + /* re-initialise */ + /* do not touch lameness, it may be valid still */ + data_entry_init(infra, e, timenow); + wr = 1; + /* TOP_TIMEOUT remains on reuse */ + if(old >= USEFUL_SERVER_TOP_TIMEOUT) { + ((struct infra_data*)e->data)->rtt.rto + = USEFUL_SERVER_TOP_TIMEOUT; + ((struct infra_data*)e->data)->timeout_A = tA; + ((struct infra_data*)e->data)->timeout_AAAA = tAAAA; + ((struct infra_data*)e->data)->timeout_other = tother; + } + } + } + if(!e) { + /* insert new entry */ + if(!(e = new_entry(infra, addr, addrlen, nm, nmlen, timenow))) + return 0; + data = (struct infra_data*)e->data; + *edns_vs = data->edns_version; + *edns_lame_known = data->edns_lame_known; + *to = rtt_timeout(&data->rtt); + slabhash_insert(infra->hosts, e->hash, e, data, NULL); + return 1; + } + /* use existing entry */ + data = (struct infra_data*)e->data; + *edns_vs = data->edns_version; + *edns_lame_known = data->edns_lame_known; + *to = rtt_timeout(&data->rtt); + if(*to >= PROBE_MAXRTO && rtt_notimeout(&data->rtt)*4 <= *to) { + /* delay other queries, this is the probe query */ + if(!wr) { + lock_rw_unlock(&e->lock); + e = infra_lookup_nottl(infra, addr,addrlen,nm,nmlen, 1); + if(!e) { /* flushed from cache real fast, no use to + allocate just for the probedelay */ + return 1; + } + data = (struct infra_data*)e->data; + } + /* add 999 to round up the timeout value from msec to sec, + * then add a whole second so it is certain that this probe + * has timed out before the next is allowed */ + data->probedelay = timenow + ((*to)+1999)/1000; + } + lock_rw_unlock(&e->lock); + return 1; +} + +int +infra_set_lame(struct infra_cache* infra, struct sockaddr_storage* addr, + socklen_t addrlen, uint8_t* nm, size_t nmlen, uint32_t timenow, + int dnsseclame, int reclame, uint16_t qtype) +{ + struct infra_data* data; + struct lruhash_entry* e; + int needtoinsert = 0; + e = infra_lookup_nottl(infra, addr, addrlen, nm, nmlen, 1); + if(!e) { + /* insert it */ + if(!(e = new_entry(infra, addr, addrlen, nm, nmlen, timenow))) { + log_err("set_lame: malloc failure"); + return 0; + } + needtoinsert = 1; + } else if( ((struct infra_data*)e->data)->ttl < timenow) { + /* expired, reuse existing entry */ + data_entry_init(infra, e, timenow); + } + /* got an entry, now set the zone lame */ + data = (struct infra_data*)e->data; + /* merge data (if any) */ + if(dnsseclame) + data->isdnsseclame = 1; + if(reclame) + data->rec_lame = 1; + if(!dnsseclame && !reclame && qtype == LDNS_RR_TYPE_A) + data->lame_type_A = 1; + if(!dnsseclame && !reclame && qtype != LDNS_RR_TYPE_A) + data->lame_other = 1; + /* done */ + if(needtoinsert) + slabhash_insert(infra->hosts, e->hash, e, e->data, NULL); + else { lock_rw_unlock(&e->lock); } + return 1; +} + +void +infra_update_tcp_works(struct infra_cache* infra, + struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* nm, + size_t nmlen) +{ + struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen, + nm, nmlen, 1); + struct infra_data* data; + if(!e) + return; /* doesn't exist */ + data = (struct infra_data*)e->data; + if(data->rtt.rto >= RTT_MAX_TIMEOUT) + /* do not disqualify this server altogether, it is better + * than nothing */ + data->rtt.rto = RTT_MAX_TIMEOUT-1000; + lock_rw_unlock(&e->lock); +} + +int +infra_rtt_update(struct infra_cache* infra, struct sockaddr_storage* addr, + socklen_t addrlen, uint8_t* nm, size_t nmlen, int qtype, + int roundtrip, int orig_rtt, uint32_t timenow) +{ + struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen, + nm, nmlen, 1); + struct infra_data* data; + int needtoinsert = 0; + int rto = 1; + if(!e) { + if(!(e = new_entry(infra, addr, addrlen, nm, nmlen, timenow))) + return 0; + needtoinsert = 1; + } else if(((struct infra_data*)e->data)->ttl < timenow) { + data_entry_init(infra, e, timenow); + } + /* have an entry, update the rtt */ + data = (struct infra_data*)e->data; + if(roundtrip == -1) { + rtt_lost(&data->rtt, orig_rtt); + if(qtype == LDNS_RR_TYPE_A) { + if(data->timeout_A < TIMEOUT_COUNT_MAX) + data->timeout_A++; + } else if(qtype == LDNS_RR_TYPE_AAAA) { + if(data->timeout_AAAA < TIMEOUT_COUNT_MAX) + data->timeout_AAAA++; + } else { + if(data->timeout_other < TIMEOUT_COUNT_MAX) + data->timeout_other++; + } + } else { + rtt_update(&data->rtt, roundtrip); + data->probedelay = 0; + if(qtype == LDNS_RR_TYPE_A) + data->timeout_A = 0; + else if(qtype == LDNS_RR_TYPE_AAAA) + data->timeout_AAAA = 0; + else data->timeout_other = 0; + } + if(data->rtt.rto > 0) + rto = data->rtt.rto; + + if(needtoinsert) + slabhash_insert(infra->hosts, e->hash, e, e->data, NULL); + else { lock_rw_unlock(&e->lock); } + return rto; +} + +int infra_get_host_rto(struct infra_cache* infra, + struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* nm, + size_t nmlen, struct rtt_info* rtt, int* delay, uint32_t timenow, + int* tA, int* tAAAA, int* tother) +{ + struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen, + nm, nmlen, 0); + struct infra_data* data; + int ttl = -2; + if(!e) return -1; + data = (struct infra_data*)e->data; + if(data->ttl >= timenow) { + ttl = (int)(data->ttl - timenow); + memmove(rtt, &data->rtt, sizeof(*rtt)); + if(timenow < data->probedelay) + *delay = (int)(data->probedelay - timenow); + else *delay = 0; + } + *tA = (int)data->timeout_A; + *tAAAA = (int)data->timeout_AAAA; + *tother = (int)data->timeout_other; + lock_rw_unlock(&e->lock); + return ttl; +} + +int +infra_edns_update(struct infra_cache* infra, struct sockaddr_storage* addr, + socklen_t addrlen, uint8_t* nm, size_t nmlen, int edns_version, + uint32_t timenow) +{ + struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen, + nm, nmlen, 1); + struct infra_data* data; + int needtoinsert = 0; + if(!e) { + if(!(e = new_entry(infra, addr, addrlen, nm, nmlen, timenow))) + return 0; + needtoinsert = 1; + } else if(((struct infra_data*)e->data)->ttl < timenow) { + data_entry_init(infra, e, timenow); + } + /* have an entry, update the rtt, and the ttl */ + data = (struct infra_data*)e->data; + /* do not update if noEDNS and stored is yesEDNS */ + if(!(edns_version == -1 && (data->edns_version != -1 && + data->edns_lame_known))) { + data->edns_version = edns_version; + data->edns_lame_known = 1; + } + + if(needtoinsert) + slabhash_insert(infra->hosts, e->hash, e, e->data, NULL); + else { lock_rw_unlock(&e->lock); } + return 1; +} + +int +infra_get_lame_rtt(struct infra_cache* infra, + struct sockaddr_storage* addr, socklen_t addrlen, + uint8_t* name, size_t namelen, uint16_t qtype, + int* lame, int* dnsseclame, int* reclame, int* rtt, uint32_t timenow) +{ + struct infra_data* host; + struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen, + name, namelen, 0); + if(!e) + return 0; + host = (struct infra_data*)e->data; + *rtt = rtt_unclamped(&host->rtt); + if(host->rtt.rto >= PROBE_MAXRTO && timenow < host->probedelay + && rtt_notimeout(&host->rtt)*4 <= host->rtt.rto) { + /* single probe for this domain, and we are not probing */ + /* unless the query type allows a probe to happen */ + if(qtype == LDNS_RR_TYPE_A) { + if(host->timeout_A >= TIMEOUT_COUNT_MAX) + *rtt = USEFUL_SERVER_TOP_TIMEOUT; + else *rtt = USEFUL_SERVER_TOP_TIMEOUT-1000; + } else if(qtype == LDNS_RR_TYPE_AAAA) { + if(host->timeout_AAAA >= TIMEOUT_COUNT_MAX) + *rtt = USEFUL_SERVER_TOP_TIMEOUT; + else *rtt = USEFUL_SERVER_TOP_TIMEOUT-1000; + } else { + if(host->timeout_other >= TIMEOUT_COUNT_MAX) + *rtt = USEFUL_SERVER_TOP_TIMEOUT; + else *rtt = USEFUL_SERVER_TOP_TIMEOUT-1000; + } + } + if(timenow > host->ttl) { + /* expired entry */ + /* see if this can be a re-probe of an unresponsive server */ + /* minus 1000 because that is outside of the RTTBAND, so + * blacklisted servers stay blacklisted if this is chosen */ + if(host->rtt.rto >= USEFUL_SERVER_TOP_TIMEOUT) { + lock_rw_unlock(&e->lock); + *rtt = USEFUL_SERVER_TOP_TIMEOUT-1000; + *lame = 0; + *dnsseclame = 0; + *reclame = 0; + return 1; + } + lock_rw_unlock(&e->lock); + return 0; + } + /* check lameness first */ + if(host->lame_type_A && qtype == LDNS_RR_TYPE_A) { + lock_rw_unlock(&e->lock); + *lame = 1; + *dnsseclame = 0; + *reclame = 0; + return 1; + } else if(host->lame_other && qtype != LDNS_RR_TYPE_A) { + lock_rw_unlock(&e->lock); + *lame = 1; + *dnsseclame = 0; + *reclame = 0; + return 1; + } else if(host->isdnsseclame) { + lock_rw_unlock(&e->lock); + *lame = 0; + *dnsseclame = 1; + *reclame = 0; + return 1; + } else if(host->rec_lame) { + lock_rw_unlock(&e->lock); + *lame = 0; + *dnsseclame = 0; + *reclame = 1; + return 1; + } + /* no lameness for this type of query */ + lock_rw_unlock(&e->lock); + *lame = 0; + *dnsseclame = 0; + *reclame = 0; + return 1; +} + +size_t +infra_get_mem(struct infra_cache* infra) +{ + return sizeof(*infra) + slabhash_get_mem(infra->hosts); +} diff --git a/services/cache/infra.h b/services/cache/infra.h new file mode 100644 index 00000000000..161f5ab4319 --- /dev/null +++ b/services/cache/infra.h @@ -0,0 +1,309 @@ +/* + * services/cache/infra.h - infrastructure cache, server rtt and capabilities + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains the infrastructure cache. + */ + +#ifndef SERVICES_CACHE_INFRA_H +#define SERVICES_CACHE_INFRA_H +#include "util/storage/lruhash.h" +#include "util/rtt.h" +struct slabhash; +struct config_file; + +/** + * Host information kept for every server, per zone. + */ +struct infra_key { + /** the host address. */ + struct sockaddr_storage addr; + /** length of addr. */ + socklen_t addrlen; + /** zone name in wireformat */ + uint8_t* zonename; + /** length of zonename */ + size_t namelen; + /** hash table entry, data of type infra_data. */ + struct lruhash_entry entry; +}; + +/** + * Host information encompasses host capabilities and retransmission timeouts. + * And lameness information (notAuthoritative, noEDNS, Recursive) + */ +struct infra_data { + /** TTL value for this entry. absolute time. */ + uint32_t ttl; + + /** time in seconds (absolute) when probing re-commences, 0 disabled */ + uint32_t probedelay; + /** round trip times for timeout calculation */ + struct rtt_info rtt; + + /** edns version that the host supports, -1 means no EDNS */ + int edns_version; + /** if the EDNS lameness is already known or not. + * EDNS lame is when EDNS queries or replies are dropped, + * and cause a timeout */ + uint8_t edns_lame_known; + + /** is the host lame (does not serve the zone authoritatively), + * or is the host dnssec lame (does not serve DNSSEC data) */ + uint8_t isdnsseclame; + /** is the host recursion lame (not AA, but RA) */ + uint8_t rec_lame; + /** the host is lame (not authoritative) for A records */ + uint8_t lame_type_A; + /** the host is lame (not authoritative) for other query types */ + uint8_t lame_other; + + /** timeouts counter for type A */ + uint8_t timeout_A; + /** timeouts counter for type AAAA */ + uint8_t timeout_AAAA; + /** timeouts counter for others */ + uint8_t timeout_other; +}; + +/** + * Infra cache + */ +struct infra_cache { + /** The hash table with hosts */ + struct slabhash* hosts; + /** TTL value for host information, in seconds */ + int host_ttl; +}; + +/** infra host cache default hash lookup size */ +#define INFRA_HOST_STARTSIZE 32 +/** bytes per zonename reserved in the hostcache, dnamelen(zonename.com.) */ +#define INFRA_BYTES_NAME 14 + +/** + * Create infra cache. + * @param cfg: config parameters or NULL for defaults. + * @return: new infra cache, or NULL. + */ +struct infra_cache* infra_create(struct config_file* cfg); + +/** + * Delete infra cache. + * @param infra: infrastructure cache to delete. + */ +void infra_delete(struct infra_cache* infra); + +/** + * Adjust infra cache to use updated configuration settings. + * This may clean the cache. Operates a bit like realloc. + * There may be no threading or use by other threads. + * @param infra: existing cache. If NULL a new infra cache is returned. + * @param cfg: config options. + * @return the new infra cache pointer or NULL on error. + */ +struct infra_cache* infra_adjust(struct infra_cache* infra, + struct config_file* cfg); + +/** + * Plain find infra data function (used by the the other functions) + * @param infra: infrastructure cache. + * @param addr: host address. + * @param addrlen: length of addr. + * @param name: domain name of zone. + * @param namelen: length of domain name. + * @param wr: if true, writelock, else readlock. + * @return the entry, could be expired (this is not checked) or NULL. + */ +struct lruhash_entry* infra_lookup_nottl(struct infra_cache* infra, + struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* name, + size_t namelen, int wr); + +/** + * Find host information to send a packet. Creates new entry if not found. + * Lameness is empty. EDNS is 0 (try with first), and rtt is returned for + * the first message to it. + * Use this to send a packet only, because it also locks out others when + * probing is restricted. + * @param infra: infrastructure cache. + * @param addr: host address. + * @param addrlen: length of addr. + * @param name: domain name of zone. + * @param namelen: length of domain name. + * @param timenow: what time it is now. + * @param edns_vs: edns version it supports, is returned. + * @param edns_lame_known: if EDNS lame (EDNS is dropped in transit) has + * already been probed, is returned. + * @param to: timeout to use, is returned. + * @return: 0 on error. + */ +int infra_host(struct infra_cache* infra, struct sockaddr_storage* addr, + socklen_t addrlen, uint8_t* name, size_t namelen, + uint32_t timenow, int* edns_vs, uint8_t* edns_lame_known, int* to); + +/** + * Set a host to be lame for the given zone. + * @param infra: infrastructure cache. + * @param addr: host address. + * @param addrlen: length of addr. + * @param name: domain name of zone apex. + * @param namelen: length of domain name. + * @param timenow: what time it is now. + * @param dnsseclame: if true the host is set dnssec lame. + * if false, the host is marked lame (not serving the zone). + * @param reclame: if true host is a recursor not AA server. + * if false, dnsseclame or marked lame. + * @param qtype: the query type for which it is lame. + * @return: 0 on error. + */ +int infra_set_lame(struct infra_cache* infra, + struct sockaddr_storage* addr, socklen_t addrlen, + uint8_t* name, size_t namelen, uint32_t timenow, int dnsseclame, + int reclame, uint16_t qtype); + +/** + * Update rtt information for the host. + * @param infra: infrastructure cache. + * @param addr: host address. + * @param addrlen: length of addr. + * @param name: zone name + * @param namelen: zone name length + * @param qtype: query type. + * @param roundtrip: estimate of roundtrip time in milliseconds or -1 for + * timeout. + * @param orig_rtt: original rtt for the query that timed out (roundtrip==-1). + * ignored if roundtrip != -1. + * @param timenow: what time it is now. + * @return: 0 on error. new rto otherwise. + */ +int infra_rtt_update(struct infra_cache* infra, struct sockaddr_storage* addr, + socklen_t addrlen, uint8_t* name, size_t namelen, int qtype, + int roundtrip, int orig_rtt, uint32_t timenow); + +/** + * Update information for the host, store that a TCP transaction works. + * @param infra: infrastructure cache. + * @param addr: host address. + * @param addrlen: length of addr. + * @param name: name of zone + * @param namelen: length of name + */ +void infra_update_tcp_works(struct infra_cache* infra, + struct sockaddr_storage* addr, socklen_t addrlen, + uint8_t* name, size_t namelen); + +/** + * Update edns information for the host. + * @param infra: infrastructure cache. + * @param addr: host address. + * @param addrlen: length of addr. + * @param name: name of zone + * @param namelen: length of name + * @param edns_version: the version that it publishes. + * If it is known to support EDNS then no-EDNS is not stored over it. + * @param timenow: what time it is now. + * @return: 0 on error. + */ +int infra_edns_update(struct infra_cache* infra, + struct sockaddr_storage* addr, socklen_t addrlen, + uint8_t* name, size_t namelen, int edns_version, uint32_t timenow); + +/** + * Get Lameness information and average RTT if host is in the cache. + * This information is to be used for server selection. + * @param infra: infrastructure cache. + * @param addr: host address. + * @param addrlen: length of addr. + * @param name: zone name. + * @param namelen: zone name length. + * @param qtype: the query to be made. + * @param lame: if function returns true, this returns lameness of the zone. + * @param dnsseclame: if function returns true, this returns if the zone + * is dnssec-lame. + * @param reclame: if function returns true, this is if it is recursion lame. + * @param rtt: if function returns true, this returns avg rtt of the server. + * The rtt value is unclamped and reflects recent timeouts. + * @param timenow: what time it is now. + * @return if found in cache, or false if not (or TTL bad). + */ +int infra_get_lame_rtt(struct infra_cache* infra, + struct sockaddr_storage* addr, socklen_t addrlen, + uint8_t* name, size_t namelen, uint16_t qtype, + int* lame, int* dnsseclame, int* reclame, int* rtt, uint32_t timenow); + +/** + * Get additional (debug) info on timing. + * @param infra: infra cache. + * @param addr: host address. + * @param addrlen: length of addr. + * @param name: zone name + * @param namelen: zone name length + * @param rtt: the rtt_info is copied into here (caller alloced return struct). + * @param delay: probe delay (if any). + * @param timenow: what time it is now. + * @param tA: timeout counter on type A. + * @param tAAAA: timeout counter on type AAAA. + * @param tother: timeout counter on type other. + * @return TTL the infra host element is valid for. If -1: not found in cache. + * TTL -2: found but expired. + */ +int infra_get_host_rto(struct infra_cache* infra, + struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* name, + size_t namelen, struct rtt_info* rtt, int* delay, uint32_t timenow, + int* tA, int* tAAAA, int* tother); + +/** + * Get memory used by the infra cache. + * @param infra: infrastructure cache. + * @return memory in use in bytes. + */ +size_t infra_get_mem(struct infra_cache* infra); + +/** calculate size for the hashtable, does not count size of lameness, + * so the hashtable is a fixed number of items */ +size_t infra_sizefunc(void* k, void* d); + +/** compare two addresses, returns -1, 0, or +1 */ +int infra_compfunc(void* key1, void* key2); + +/** delete key, and destroy the lock */ +void infra_delkeyfunc(void* k, void* arg); + +/** delete data and destroy the lameness hashtable */ +void infra_deldatafunc(void* d, void* arg); + +#endif /* SERVICES_CACHE_INFRA_H */ diff --git a/services/cache/rrset.c b/services/cache/rrset.c new file mode 100644 index 00000000000..b9d20db0e5d --- /dev/null +++ b/services/cache/rrset.c @@ -0,0 +1,416 @@ +/* + * services/cache/rrset.c - Resource record set cache. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains the rrset cache. + */ +#include "config.h" +#include "services/cache/rrset.h" +#include "util/storage/slabhash.h" +#include "util/config_file.h" +#include "util/data/packed_rrset.h" +#include "util/data/msgreply.h" +#include "util/regional.h" +#include "util/alloc.h" + +void +rrset_markdel(void* key) +{ + struct ub_packed_rrset_key* r = (struct ub_packed_rrset_key*)key; + r->id = 0; +} + +struct rrset_cache* rrset_cache_create(struct config_file* cfg, + struct alloc_cache* alloc) +{ + size_t slabs = (cfg?cfg->rrset_cache_slabs:HASH_DEFAULT_SLABS); + size_t startarray = HASH_DEFAULT_STARTARRAY; + size_t maxmem = (cfg?cfg->rrset_cache_size:HASH_DEFAULT_MAXMEM); + + struct rrset_cache *r = (struct rrset_cache*)slabhash_create(slabs, + startarray, maxmem, ub_rrset_sizefunc, ub_rrset_compare, + ub_rrset_key_delete, rrset_data_delete, alloc); + slabhash_setmarkdel(&r->table, &rrset_markdel); + return r; +} + +void rrset_cache_delete(struct rrset_cache* r) +{ + if(!r) + return; + slabhash_delete(&r->table); + /* slabhash delete also does free(r), since table is first in struct*/ +} + +struct rrset_cache* rrset_cache_adjust(struct rrset_cache *r, + struct config_file* cfg, struct alloc_cache* alloc) +{ + if(!r || !cfg || cfg->rrset_cache_slabs != r->table.size || + cfg->rrset_cache_size != slabhash_get_size(&r->table)) + { + rrset_cache_delete(r); + r = rrset_cache_create(cfg, alloc); + } + return r; +} + +void +rrset_cache_touch(struct rrset_cache* r, struct ub_packed_rrset_key* key, + hashvalue_t hash, rrset_id_t id) +{ + struct lruhash* table = slabhash_gettable(&r->table, hash); + /* + * This leads to locking problems, deadlocks, if the caller is + * holding any other rrset lock. + * Because a lookup through the hashtable does: + * tablelock -> entrylock (for that entry caller holds) + * And this would do + * entrylock(already held) -> tablelock + * And if two threads do this, it results in deadlock. + * So, the caller must not hold entrylock. + */ + lock_quick_lock(&table->lock); + /* we have locked the hash table, the item can still be deleted. + * because it could already have been reclaimed, but not yet set id=0. + * This is because some lruhash routines have lazy deletion. + * so, we must acquire a lock on the item to verify the id != 0. + * also, with hash not changed, we are using the right slab. + */ + lock_rw_rdlock(&key->entry.lock); + if(key->id == id && key->entry.hash == hash) { + lru_touch(table, &key->entry); + } + lock_rw_unlock(&key->entry.lock); + lock_quick_unlock(&table->lock); +} + +/** see if rrset needs to be updated in the cache */ +static int +need_to_update_rrset(void* nd, void* cd, uint32_t timenow, int equal, int ns) +{ + struct packed_rrset_data* newd = (struct packed_rrset_data*)nd; + struct packed_rrset_data* cached = (struct packed_rrset_data*)cd; + /* o store if rrset has been validated + * everything better than bogus data + * secure is preferred */ + if( newd->security == sec_status_secure && + cached->security != sec_status_secure) + return 1; + if( cached->security == sec_status_bogus && + newd->security != sec_status_bogus && !equal) + return 1; + /* o if current RRset is more trustworthy - insert it */ + if( newd->trust > cached->trust ) { + /* if the cached rrset is bogus, and this one equal, + * do not update the TTL - let it expire. */ + if(equal && cached->ttl >= timenow && + cached->security == sec_status_bogus) + return 0; + return 1; + } + /* o item in cache has expired */ + if( cached->ttl < timenow ) + return 1; + /* o same trust, but different in data - insert it */ + if( newd->trust == cached->trust && !equal ) { + /* if this is type NS, do not 'stick' to owner that changes + * the NS RRset, but use the old TTL for the new data, and + * update to fetch the latest data. ttl is not expired, because + * that check was before this one. */ + if(ns) { + size_t i; + newd->ttl = cached->ttl; + for(i=0; i<(newd->count+newd->rrsig_count); i++) + if(newd->rr_ttl[i] > newd->ttl) + newd->rr_ttl[i] = newd->ttl; + } + return 1; + } + return 0; +} + +/** Update RRSet special key ID */ +static void +rrset_update_id(struct rrset_ref* ref, struct alloc_cache* alloc) +{ + /* this may clear the cache and invalidate lock below */ + uint64_t newid = alloc_get_id(alloc); + /* obtain writelock */ + lock_rw_wrlock(&ref->key->entry.lock); + /* check if it was deleted in the meantime, if so, skip update */ + if(ref->key->id == ref->id) { + ref->key->id = newid; + ref->id = newid; + } + lock_rw_unlock(&ref->key->entry.lock); +} + +int +rrset_cache_update(struct rrset_cache* r, struct rrset_ref* ref, + struct alloc_cache* alloc, uint32_t timenow) +{ + struct lruhash_entry* e; + struct ub_packed_rrset_key* k = ref->key; + hashvalue_t h = k->entry.hash; + uint16_t rrset_type = ntohs(k->rk.type); + int equal = 0; + log_assert(ref->id != 0 && k->id != 0); + /* looks up item with a readlock - no editing! */ + if((e=slabhash_lookup(&r->table, h, k, 0)) != 0) { + /* return id and key as they will be used in the cache + * since the lruhash_insert, if item already exists, deallocs + * the passed key in favor of the already stored key. + * because of the small gap (see below) this key ptr and id + * may prove later to be already deleted, which is no problem + * as it only makes a cache miss. + */ + ref->key = (struct ub_packed_rrset_key*)e->key; + ref->id = ref->key->id; + equal = rrsetdata_equal((struct packed_rrset_data*)k->entry. + data, (struct packed_rrset_data*)e->data); + if(!need_to_update_rrset(k->entry.data, e->data, timenow, + equal, (rrset_type==LDNS_RR_TYPE_NS))) { + /* cache is superior, return that value */ + lock_rw_unlock(&e->lock); + ub_packed_rrset_parsedelete(k, alloc); + if(equal) return 2; + return 1; + } + lock_rw_unlock(&e->lock); + /* Go on and insert the passed item. + * small gap here, where entry is not locked. + * possibly entry is updated with something else. + * we then overwrite that with our data. + * this is just too bad, its cache anyway. */ + /* use insert to update entry to manage lruhash + * cache size values nicely. */ + } + log_assert(ref->key->id != 0); + slabhash_insert(&r->table, h, &k->entry, k->entry.data, alloc); + if(e) { + /* For NSEC, NSEC3, DNAME, when rdata is updated, update + * the ID number so that proofs in message cache are + * invalidated */ + if((rrset_type == LDNS_RR_TYPE_NSEC + || rrset_type == LDNS_RR_TYPE_NSEC3 + || rrset_type == LDNS_RR_TYPE_DNAME) && !equal) { + rrset_update_id(ref, alloc); + } + return 1; + } + return 0; +} + +struct ub_packed_rrset_key* +rrset_cache_lookup(struct rrset_cache* r, uint8_t* qname, size_t qnamelen, + uint16_t qtype, uint16_t qclass, uint32_t flags, uint32_t timenow, + int wr) +{ + struct lruhash_entry* e; + struct ub_packed_rrset_key key; + + key.entry.key = &key; + key.entry.data = NULL; + key.rk.dname = qname; + key.rk.dname_len = qnamelen; + key.rk.type = htons(qtype); + key.rk.rrset_class = htons(qclass); + key.rk.flags = flags; + + key.entry.hash = rrset_key_hash(&key.rk); + + if((e = slabhash_lookup(&r->table, key.entry.hash, &key, wr))) { + /* check TTL */ + struct packed_rrset_data* data = + (struct packed_rrset_data*)e->data; + if(timenow > data->ttl) { + lock_rw_unlock(&e->lock); + return NULL; + } + /* we're done */ + return (struct ub_packed_rrset_key*)e->key; + } + return NULL; +} + +int +rrset_array_lock(struct rrset_ref* ref, size_t count, uint32_t timenow) +{ + size_t i; + for(i=0; i0 && ref[i].key == ref[i-1].key) + continue; /* only lock items once */ + lock_rw_rdlock(&ref[i].key->entry.lock); + if(ref[i].id != ref[i].key->id || timenow > + ((struct packed_rrset_data*)(ref[i].key->entry.data)) + ->ttl) { + /* failure! rollback our readlocks */ + rrset_array_unlock(ref, i+1); + return 0; + } + } + return 1; +} + +void +rrset_array_unlock(struct rrset_ref* ref, size_t count) +{ + size_t i; + for(i=0; i0 && ref[i].key == ref[i-1].key) + continue; /* only unlock items once */ + lock_rw_unlock(&ref[i].key->entry.lock); + } +} + +void +rrset_array_unlock_touch(struct rrset_cache* r, struct regional* scratch, + struct rrset_ref* ref, size_t count) +{ + hashvalue_t* h; + size_t i; + if(!(h = (hashvalue_t*)regional_alloc(scratch, + sizeof(hashvalue_t)*count))) + log_warn("rrset LRU: memory allocation failed"); + else /* store hash values */ + for(i=0; ientry.hash; + /* unlock */ + for(i=0; i0 && ref[i].key == ref[i-1].key) + continue; /* only unlock items once */ + lock_rw_unlock(&ref[i].key->entry.lock); + } + if(h) { + /* LRU touch, with no rrset locks held */ + for(i=0; i0 && ref[i].key == ref[i-1].key) + continue; /* only touch items once */ + rrset_cache_touch(r, ref[i].key, h[i], ref[i].id); + } + } +} + +void +rrset_update_sec_status(struct rrset_cache* r, + struct ub_packed_rrset_key* rrset, uint32_t now) +{ + struct packed_rrset_data* updata = + (struct packed_rrset_data*)rrset->entry.data; + struct lruhash_entry* e; + struct packed_rrset_data* cachedata; + + /* hash it again to make sure it has a hash */ + rrset->entry.hash = rrset_key_hash(&rrset->rk); + + e = slabhash_lookup(&r->table, rrset->entry.hash, rrset, 1); + if(!e) + return; /* not in the cache anymore */ + cachedata = (struct packed_rrset_data*)e->data; + if(!rrsetdata_equal(updata, cachedata)) { + lock_rw_unlock(&e->lock); + return; /* rrset has changed in the meantime */ + } + /* update the cached rrset */ + if(updata->security > cachedata->security) { + size_t i; + if(updata->trust > cachedata->trust) + cachedata->trust = updata->trust; + cachedata->security = updata->security; + /* for NS records only shorter TTLs, other types: update it */ + if(ntohs(rrset->rk.type) != LDNS_RR_TYPE_NS || + updata->ttl+now < cachedata->ttl || + cachedata->ttl < now || + updata->security == sec_status_bogus) { + cachedata->ttl = updata->ttl + now; + for(i=0; icount+cachedata->rrsig_count; i++) + cachedata->rr_ttl[i] = updata->rr_ttl[i]+now; + } + } + lock_rw_unlock(&e->lock); +} + +void +rrset_check_sec_status(struct rrset_cache* r, + struct ub_packed_rrset_key* rrset, uint32_t now) +{ + struct packed_rrset_data* updata = + (struct packed_rrset_data*)rrset->entry.data; + struct lruhash_entry* e; + struct packed_rrset_data* cachedata; + + /* hash it again to make sure it has a hash */ + rrset->entry.hash = rrset_key_hash(&rrset->rk); + + e = slabhash_lookup(&r->table, rrset->entry.hash, rrset, 0); + if(!e) + return; /* not in the cache anymore */ + cachedata = (struct packed_rrset_data*)e->data; + if(now > cachedata->ttl || !rrsetdata_equal(updata, cachedata)) { + lock_rw_unlock(&e->lock); + return; /* expired, or rrset has changed in the meantime */ + } + if(cachedata->security > updata->security) { + updata->security = cachedata->security; + if(cachedata->security == sec_status_bogus) { + size_t i; + updata->ttl = cachedata->ttl - now; + for(i=0; icount+cachedata->rrsig_count; i++) + if(cachedata->rr_ttl[i] < now) + updata->rr_ttl[i] = 0; + else updata->rr_ttl[i] = + cachedata->rr_ttl[i]-now; + } + if(cachedata->trust > updata->trust) + updata->trust = cachedata->trust; + } + lock_rw_unlock(&e->lock); +} + +void rrset_cache_remove(struct rrset_cache* r, uint8_t* nm, size_t nmlen, + uint16_t type, uint16_t dclass, uint32_t flags) +{ + struct ub_packed_rrset_key key; + key.entry.key = &key; + key.rk.dname = nm; + key.rk.dname_len = nmlen; + key.rk.rrset_class = htons(dclass); + key.rk.type = htons(type); + key.rk.flags = flags; + key.entry.hash = rrset_key_hash(&key.rk); + slabhash_remove(&r->table, key.entry.hash, &key); +} diff --git a/services/cache/rrset.h b/services/cache/rrset.h new file mode 100644 index 00000000000..22d36719eaf --- /dev/null +++ b/services/cache/rrset.h @@ -0,0 +1,231 @@ +/* + * services/cache/rrset.h - Resource record set cache. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains the rrset cache. + */ + +#ifndef SERVICES_CACHE_RRSET_H +#define SERVICES_CACHE_RRSET_H +#include "util/storage/lruhash.h" +#include "util/storage/slabhash.h" +#include "util/data/packed_rrset.h" +struct config_file; +struct alloc_cache; +struct rrset_ref; +struct regional; + +/** + * The rrset cache + * Thin wrapper around hashtable, like a typedef. + */ +struct rrset_cache { + /** uses partitioned hash table */ + struct slabhash table; +}; + +/** + * Create rrset cache + * @param cfg: config settings or NULL for defaults. + * @param alloc: initial default rrset key allocation. + * @return: NULL on error. + */ +struct rrset_cache* rrset_cache_create(struct config_file* cfg, + struct alloc_cache* alloc); + +/** + * Delete rrset cache + * @param r: rrset cache to delete. + */ +void rrset_cache_delete(struct rrset_cache* r); + +/** + * Adjust settings of the cache to settings from the config file. + * May purge the cache. May recreate the cache. + * There may be no threading or use by other threads. + * @param r: rrset cache to adjust (like realloc). + * @param cfg: config settings or NULL for defaults. + * @param alloc: initial default rrset key allocation. + * @return 0 on error, or new rrset cache pointer on success. + */ +struct rrset_cache* rrset_cache_adjust(struct rrset_cache* r, + struct config_file* cfg, struct alloc_cache* alloc); + +/** + * Touch rrset, with given pointer and id. + * Caller may not hold a lock on ANY rrset, this could give deadlock. + * + * This routine is faster than a hashtable lookup: + * o no bin_lock is acquired. + * o no walk through the bin-overflow-list. + * o no comparison of the entry key to find it. + * + * @param r: rrset cache. + * @param key: rrset key. Marked recently used (if it was not deleted + * before the lock is acquired, in that case nothing happens). + * @param hash: hash value of the item. Please read it from the key when + * you have it locked. Used to find slab from slabhash. + * @param id: used to check that the item is unchanged and not deleted. + */ +void rrset_cache_touch(struct rrset_cache* r, struct ub_packed_rrset_key* key, + hashvalue_t hash, rrset_id_t id); + +/** + * Update an rrset in the rrset cache. Stores the information for later use. + * Will lookup if the rrset is in the cache and perform an update if necessary. + * If the item was present, and superior, references are returned to that. + * The passed item is then deallocated with rrset_parsedelete. + * + * A superior rrset is: + * o rrset with better trust value. + * o same trust value, different rdata, newly passed rrset is inserted. + * If rdata is the same, TTL in the cache is updated. + * + * @param r: the rrset cache. + * @param ref: reference (ptr and id) to the rrset. Pass reference setup for + * the new rrset. The reference may be changed if the cached rrset is + * superior. + * Before calling the rrset is presumed newly allocated and changeable. + * Afer calling you do not hold a lock, and the rrset is inserted in + * the hashtable so you need a lock to change it. + * @param alloc: how to allocate (and deallocate) the special rrset key. + * @param timenow: current time (to see if ttl in cache is expired). + * @return: true if the passed reference is updated, false if it is unchanged. + * 0: reference unchanged, inserted in cache. + * 1: reference updated, item is inserted in cache. + * 2: reference updated, item in cache is considered superior. + * also the rdata is equal (but other parameters in cache are superior). + */ +int rrset_cache_update(struct rrset_cache* r, struct rrset_ref* ref, + struct alloc_cache* alloc, uint32_t timenow); + +/** + * Lookup rrset. You obtain read/write lock. You must unlock before lookup + * anything of else. + * @param r: the rrset cache. + * @param qname: name of rrset to lookup. + * @param qnamelen: length of name of rrset to lookup. + * @param qtype: type of rrset to lookup (host order). + * @param qclass: class of rrset to lookup (host order). + * @param flags: rrset flags, or 0. + * @param timenow: used to compare with TTL. + * @param wr: set true to get writelock. + * @return packed rrset key pointer. Remember to unlock the key.entry.lock. + * or NULL if could not be found or it was timed out. + */ +struct ub_packed_rrset_key* rrset_cache_lookup(struct rrset_cache* r, + uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass, + uint32_t flags, uint32_t timenow, int wr); + +/** + * Obtain readlock on a (sorted) list of rrset references. + * Checks TTLs and IDs of the rrsets and rollbacks locking if not Ok. + * @param ref: array of rrset references (key pointer and ID value). + * duplicate references are allowed and handled. + * @param count: size of array. + * @param timenow: used to compare with TTL. + * @return true on success, false on a failure, which can be that some + * RRsets have timed out, or that they do not exist any more, the + * RRsets have been purged from the cache. + * If true, you hold readlocks on all the ref items. + */ +int rrset_array_lock(struct rrset_ref* ref, size_t count, uint32_t timenow); + +/** + * Unlock array (sorted) of rrset references. + * @param ref: array of rrset references (key pointer and ID value). + * duplicate references are allowed and handled. + * @param count: size of array. + */ +void rrset_array_unlock(struct rrset_ref* ref, size_t count); + +/** + * Unlock array (sorted) of rrset references and at the same time + * touch LRU on the rrsets. It needs the scratch region for temporary + * storage as it uses the initial locks to obtain hash values. + * @param r: the rrset cache. In this cache LRU is updated. + * @param scratch: region for temporary storage of hash values. + * if memory allocation fails, the lru touch fails silently, + * but locks are released. memory errors are logged. + * @param ref: array of rrset references (key pointer and ID value). + * duplicate references are allowed and handled. + * @param count: size of array. + */ +void rrset_array_unlock_touch(struct rrset_cache* r, struct regional* scratch, + struct rrset_ref* ref, size_t count); + +/** + * Update security status of an rrset. Looks up the rrset. + * If found, checks if rdata is equal. + * If so, it will update the security, trust and rrset-ttl values. + * The values are only updated if security is increased (towards secure). + * @param r: the rrset cache. + * @param rrset: which rrset to attempt to update. This rrset is left + * untouched. The rrset in the cache is updated in-place. + * @param now: current time. + */ +void rrset_update_sec_status(struct rrset_cache* r, + struct ub_packed_rrset_key* rrset, uint32_t now); + +/** + * Looks up security status of an rrset. Looks up the rrset. + * If found, checks if rdata is equal, and entry did not expire. + * If so, it will update the security, trust and rrset-ttl values. + * @param r: the rrset cache. + * @param rrset: This rrset may change security status due to the cache. + * But its status will only improve, towards secure. + * @param now: current time. + */ +void rrset_check_sec_status(struct rrset_cache* r, + struct ub_packed_rrset_key* rrset, uint32_t now); + +/** + * Remove an rrset from the cache, by name and type and flags + * @param r: rrset cache + * @param nm: name of rrset + * @param nmlen: length of name + * @param type: type of rrset + * @param dclass: class of rrset, host order + * @param flags: flags of rrset, host order + */ +void rrset_cache_remove(struct rrset_cache* r, uint8_t* nm, size_t nmlen, + uint16_t type, uint16_t dclass, uint32_t flags); + +/** mark rrset to be deleted, set id=0 */ +void rrset_markdel(void* key); + +#endif /* SERVICES_CACHE_RRSET_H */ diff --git a/services/listen_dnsport.c b/services/listen_dnsport.c new file mode 100644 index 00000000000..59ca1991eb1 --- /dev/null +++ b/services/listen_dnsport.c @@ -0,0 +1,944 @@ +/* + * services/listen_dnsport.c - listen on port 53 for incoming DNS queries. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file has functions to get queries from clients. + */ +#include "config.h" +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#include +#include "services/listen_dnsport.h" +#include "services/outside_network.h" +#include "util/netevent.h" +#include "util/log.h" +#include "util/config_file.h" +#include "util/net_help.h" + +#ifdef HAVE_NETDB_H +#include +#endif +#include + +/** number of queued TCP connections for listen() */ +#define TCP_BACKLOG 5 + +/** + * Debug print of the getaddrinfo returned address. + * @param addr: the address returned. + */ +static void +verbose_print_addr(struct addrinfo *addr) +{ + if(verbosity >= VERB_ALGO) { + char buf[100]; + void* sinaddr = &((struct sockaddr_in*)addr->ai_addr)->sin_addr; +#ifdef INET6 + if(addr->ai_family == AF_INET6) + sinaddr = &((struct sockaddr_in6*)addr->ai_addr)-> + sin6_addr; +#endif /* INET6 */ + if(inet_ntop(addr->ai_family, sinaddr, buf, + (socklen_t)sizeof(buf)) == 0) { + strncpy(buf, "(null)", sizeof(buf)); + } + buf[sizeof(buf)-1] = 0; + verbose(VERB_ALGO, "creating %s%s socket %s %d", + addr->ai_socktype==SOCK_DGRAM?"udp": + addr->ai_socktype==SOCK_STREAM?"tcp":"otherproto", + addr->ai_family==AF_INET?"4": + addr->ai_family==AF_INET6?"6": + "_otherfam", buf, + ntohs(((struct sockaddr_in*)addr->ai_addr)->sin_port)); + } +} + +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 s; +#if defined(IPV6_USE_MIN_MTU) + int on=1; +#endif +#ifdef IPV6_MTU + int mtu = IPV6_MIN_MTU; +#endif +#if !defined(SO_RCVBUFFORCE) && !defined(SO_RCVBUF) + (void)rcv; +#endif +#if !defined(SO_SNDBUFFORCE) && !defined(SO_SNDBUF) + (void)snd; +#endif +#ifndef IPV6_V6ONLY + (void)v6only; +#endif + if((s = socket(family, socktype, 0)) == -1) { + *inuse = 0; +#ifndef USE_WINSOCK + if(errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) { + *noproto = 1; + return -1; + } + log_err("can't create socket: %s", strerror(errno)); +#else + if(WSAGetLastError() == WSAEAFNOSUPPORT || + WSAGetLastError() == WSAEPROTONOSUPPORT) { + *noproto = 1; + return -1; + } + log_err("can't create socket: %s", + wsa_strerror(WSAGetLastError())); +#endif + *noproto = 0; + return -1; + } + if(rcv) { +#ifdef SO_RCVBUF + int got; + socklen_t slen = (socklen_t)sizeof(got); +# ifdef SO_RCVBUFFORCE + /* Linux specific: try to use root permission to override + * system limits on rcvbuf. The limit is stored in + * /proc/sys/net/core/rmem_max or sysctl net.core.rmem_max */ + if(setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, (void*)&rcv, + (socklen_t)sizeof(rcv)) < 0) { + if(errno != EPERM) { +# ifndef USE_WINSOCK + log_err("setsockopt(..., SO_RCVBUFFORCE, " + "...) failed: %s", strerror(errno)); + close(s); +# else + log_err("setsockopt(..., SO_RCVBUFFORCE, " + "...) failed: %s", + wsa_strerror(WSAGetLastError())); + closesocket(s); +# endif + *noproto = 0; + *inuse = 0; + return -1; + } +# endif /* SO_RCVBUFFORCE */ + if(setsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&rcv, + (socklen_t)sizeof(rcv)) < 0) { +# ifndef USE_WINSOCK + log_err("setsockopt(..., SO_RCVBUF, " + "...) failed: %s", strerror(errno)); + close(s); +# else + log_err("setsockopt(..., SO_RCVBUF, " + "...) failed: %s", + wsa_strerror(WSAGetLastError())); + closesocket(s); +# endif + *noproto = 0; + *inuse = 0; + return -1; + } + /* check if we got the right thing or if system + * reduced to some system max. Warn if so */ + if(getsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&got, + &slen) >= 0 && got < rcv/2) { + log_warn("so-rcvbuf %u was not granted. " + "Got %u. To fix: start with " + "root permissions(linux) or sysctl " + "bigger net.core.rmem_max(linux) or " + "kern.ipc.maxsockbuf(bsd) values.", + (unsigned)rcv, (unsigned)got); + } +# ifdef SO_RCVBUFFORCE + } +# endif +#endif /* SO_RCVBUF */ + } + /* first do RCVBUF as the receive buffer is more important */ + if(snd) { +#ifdef SO_SNDBUF + int got; + socklen_t slen = (socklen_t)sizeof(got); +# ifdef SO_SNDBUFFORCE + /* Linux specific: try to use root permission to override + * system limits on sndbuf. The limit is stored in + * /proc/sys/net/core/wmem_max or sysctl net.core.wmem_max */ + if(setsockopt(s, SOL_SOCKET, SO_SNDBUFFORCE, (void*)&snd, + (socklen_t)sizeof(snd)) < 0) { + if(errno != EPERM) { +# ifndef USE_WINSOCK + log_err("setsockopt(..., SO_SNDBUFFORCE, " + "...) failed: %s", strerror(errno)); + close(s); +# else + log_err("setsockopt(..., SO_SNDBUFFORCE, " + "...) failed: %s", + wsa_strerror(WSAGetLastError())); + closesocket(s); +# endif + *noproto = 0; + *inuse = 0; + return -1; + } +# endif /* SO_SNDBUFFORCE */ + if(setsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&snd, + (socklen_t)sizeof(snd)) < 0) { +# ifndef USE_WINSOCK + log_err("setsockopt(..., SO_SNDBUF, " + "...) failed: %s", strerror(errno)); + close(s); +# else + log_err("setsockopt(..., SO_SNDBUF, " + "...) failed: %s", + wsa_strerror(WSAGetLastError())); + closesocket(s); +# endif + *noproto = 0; + *inuse = 0; + return -1; + } + /* check if we got the right thing or if system + * reduced to some system max. Warn if so */ + if(getsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&got, + &slen) >= 0 && got < snd/2) { + log_warn("so-sndbuf %u was not granted. " + "Got %u. To fix: start with " + "root permissions(linux) or sysctl " + "bigger net.core.wmem_max(linux) or " + "kern.ipc.maxsockbuf(bsd) values.", + (unsigned)snd, (unsigned)got); + } +# ifdef SO_SNDBUFFORCE + } +# endif +#endif /* SO_SNDBUF */ + } + if(family == AF_INET6) { +# if defined(IPV6_V6ONLY) + if(v6only) { + int val=(v6only==2)?0:1; + if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, + (void*)&val, (socklen_t)sizeof(val)) < 0) { +#ifndef USE_WINSOCK + log_err("setsockopt(..., IPV6_V6ONLY" + ", ...) failed: %s", strerror(errno)); + close(s); +#else + log_err("setsockopt(..., IPV6_V6ONLY" + ", ...) failed: %s", + wsa_strerror(WSAGetLastError())); + closesocket(s); +#endif + *noproto = 0; + *inuse = 0; + return -1; + } + } +# endif +# if defined(IPV6_USE_MIN_MTU) + /* + * There is no fragmentation of IPv6 datagrams + * during forwarding in the network. Therefore + * we do not send UDP datagrams larger than + * the minimum IPv6 MTU of 1280 octets. The + * EDNS0 message length can be larger if the + * network stack supports IPV6_USE_MIN_MTU. + */ + if (setsockopt(s, IPPROTO_IPV6, IPV6_USE_MIN_MTU, + (void*)&on, (socklen_t)sizeof(on)) < 0) { +# ifndef USE_WINSOCK + log_err("setsockopt(..., IPV6_USE_MIN_MTU, " + "...) failed: %s", strerror(errno)); + close(s); +# else + log_err("setsockopt(..., IPV6_USE_MIN_MTU, " + "...) failed: %s", + wsa_strerror(WSAGetLastError())); + closesocket(s); +# endif + *noproto = 0; + *inuse = 0; + return -1; + } +# elif defined(IPV6_MTU) + /* + * On Linux, to send no larger than 1280, the PMTUD is + * disabled by default for datagrams anyway, so we set + * the MTU to use. + */ + if (setsockopt(s, IPPROTO_IPV6, IPV6_MTU, + (void*)&mtu, (socklen_t)sizeof(mtu)) < 0) { +# ifndef USE_WINSOCK + log_err("setsockopt(..., IPV6_MTU, ...) failed: %s", + strerror(errno)); + close(s); +# else + log_err("setsockopt(..., IPV6_MTU, ...) failed: %s", + wsa_strerror(WSAGetLastError())); + closesocket(s); +# endif + *noproto = 0; + *inuse = 0; + return -1; + } +# endif /* IPv6 MTU */ + } else if(family == AF_INET) { +# if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) + int action = IP_PMTUDISC_DONT; + if (setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, + &action, (socklen_t)sizeof(action)) < 0) { + log_err("setsockopt(..., IP_MTU_DISCOVER, " + "IP_PMTUDISC_DONT...) failed: %s", + strerror(errno)); + return -1; + } +# elif defined(IP_DONTFRAG) + int off = 0; + if (setsockopt(s, IPPROTO_IP, IP_DONTFRAG, + &off, (socklen_t)sizeof(off)) < 0) { + log_err("setsockopt(..., IP_DONTFRAG, ...) failed: %s", + strerror(errno)); + return -1; + } +# endif /* IPv4 MTU */ + } + if(bind(s, (struct sockaddr*)addr, addrlen) != 0) { + *noproto = 0; +#ifndef USE_WINSOCK +#ifdef EADDRINUSE + *inuse = (errno == EADDRINUSE); + /* detect freebsd jail with no ipv6 permission */ + if(family==AF_INET6 && errno==EINVAL) + *noproto = 1; + else if(errno != EADDRINUSE) { + log_err("can't bind socket: %s", strerror(errno)); + log_addr(0, "failed address", + (struct sockaddr_storage*)addr, addrlen); + } +#endif /* EADDRINUSE */ + close(s); +#else /* USE_WINSOCK */ + if(WSAGetLastError() != WSAEADDRINUSE && + WSAGetLastError() != WSAEADDRNOTAVAIL) { + log_err("can't bind socket: %s", + wsa_strerror(WSAGetLastError())); + log_addr(0, "failed address", + (struct sockaddr_storage*)addr, addrlen); + } + closesocket(s); +#endif + return -1; + } + if(!fd_set_nonblock(s)) { + *noproto = 0; + *inuse = 0; +#ifndef USE_WINSOCK + close(s); +#else + closesocket(s); +#endif + return -1; + } + return s; +} + +int +create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto) +{ + int s; +#if defined(SO_REUSEADDR) || defined(IPV6_V6ONLY) + int on = 1; +#endif /* SO_REUSEADDR || IPV6_V6ONLY */ + verbose_print_addr(addr); + *noproto = 0; + if((s = socket(addr->ai_family, addr->ai_socktype, 0)) == -1) { +#ifndef USE_WINSOCK + if(errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) { + *noproto = 1; + return -1; + } + log_err("can't create socket: %s", strerror(errno)); +#else + if(WSAGetLastError() == WSAEAFNOSUPPORT || + WSAGetLastError() == WSAEPROTONOSUPPORT) { + *noproto = 1; + return -1; + } + log_err("can't create socket: %s", + wsa_strerror(WSAGetLastError())); +#endif + return -1; + } +#ifdef SO_REUSEADDR + if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on, + (socklen_t)sizeof(on)) < 0) { +#ifndef USE_WINSOCK + log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s", + strerror(errno)); +#else + log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s", + wsa_strerror(WSAGetLastError())); +#endif + return -1; + } +#endif /* SO_REUSEADDR */ +#if defined(IPV6_V6ONLY) + if(addr->ai_family == AF_INET6 && v6only) { + if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, + (void*)&on, (socklen_t)sizeof(on)) < 0) { +#ifndef USE_WINSOCK + log_err("setsockopt(..., IPV6_V6ONLY, ...) failed: %s", + strerror(errno)); +#else + log_err("setsockopt(..., IPV6_V6ONLY, ...) failed: %s", + wsa_strerror(WSAGetLastError())); +#endif + return -1; + } + } +#else + (void)v6only; +#endif /* IPV6_V6ONLY */ + if(bind(s, addr->ai_addr, addr->ai_addrlen) != 0) { +#ifndef USE_WINSOCK + /* detect freebsd jail with no ipv6 permission */ + if(addr->ai_family==AF_INET6 && errno==EINVAL) + *noproto = 1; + else { + log_err("can't bind socket: %s", strerror(errno)); + log_addr(0, "failed address", + (struct sockaddr_storage*)addr->ai_addr, + addr->ai_addrlen); + } +#else + log_err("can't bind socket: %s", + wsa_strerror(WSAGetLastError())); + log_addr(0, "failed address", + (struct sockaddr_storage*)addr->ai_addr, + addr->ai_addrlen); +#endif + return -1; + } + if(!fd_set_nonblock(s)) { + return -1; + } + if(listen(s, TCP_BACKLOG) == -1) { +#ifndef USE_WINSOCK + log_err("can't listen: %s", strerror(errno)); +#else + log_err("can't listen: %s", wsa_strerror(WSAGetLastError())); +#endif + return -1; + } + return s; +} + +/** + * Create socket from getaddrinfo results + */ +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) +{ + struct addrinfo *res = NULL; + int r, s, inuse, noproto; + hints->ai_socktype = stype; + *noip6 = 0; + if((r=getaddrinfo(ifname, port, hints, &res)) != 0 || !res) { +#ifdef USE_WINSOCK + if(r == EAI_NONAME && hints->ai_family == AF_INET6){ + *noip6 = 1; /* 'Host not found' for IP6 on winXP */ + return -1; + } +#endif + log_err("node %s:%s getaddrinfo: %s %s", + ifname?ifname:"default", port, gai_strerror(r), +#ifdef EAI_SYSTEM + r==EAI_SYSTEM?(char*)strerror(errno):"" +#else + "" +#endif + ); + return -1; + } + if(stype == SOCK_DGRAM) { + verbose_print_addr(res); + 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); + if(s == -1 && inuse) { + log_err("bind: address already in use"); + } else if(s == -1 && noproto && hints->ai_family == AF_INET6){ + *noip6 = 1; + } + } else { + s = create_tcp_accept_sock(res, v6only, &noproto); + if(s == -1 && noproto && hints->ai_family == AF_INET6){ + *noip6 = 1; + } + } + freeaddrinfo(res); + return s; +} + +/** make socket and first see if ifname contains port override info */ +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) +{ + char* s = strchr(ifname, '@'); + if(s) { + /* override port with ifspec@port */ + char p[16]; + char newif[128]; + if((size_t)(s-ifname) >= sizeof(newif)) { + log_err("ifname too long: %s", ifname); + *noip6 = 0; + return -1; + } + if(strlen(s+1) >= sizeof(p)) { + log_err("portnumber too long: %s", ifname); + *noip6 = 0; + return -1; + } + strncpy(newif, ifname, sizeof(newif)); + newif[s-ifname] = 0; + strncpy(p, s+1, sizeof(p)); + p[strlen(s+1)]=0; + return make_sock(stype, newif, p, hints, v6only, noip6, + rcv, snd); + } + return make_sock(stype, ifname, port, hints, v6only, noip6, rcv, snd); +} + +/** + * Add port to open ports list. + * @param list: list head. changed. + * @param s: fd. + * @param ftype: if fd is UDP. + * @return false on failure. list in unchanged then. + */ +static int +port_insert(struct listen_port** list, int s, enum listen_type ftype) +{ + struct listen_port* item = (struct listen_port*)malloc( + sizeof(struct listen_port)); + if(!item) + return 0; + item->next = *list; + item->fd = s; + item->ftype = ftype; + *list = item; + return 1; +} + +/** set fd to receive source address packet info */ +static int +set_recvpktinfo(int s, int family) +{ +#if defined(IPV6_RECVPKTINFO) || defined(IPV6_PKTINFO) || (defined(IP_RECVDSTADDR) && defined(IP_SENDSRCADDR)) || defined(IP_PKTINFO) + int on = 1; +#else + (void)s; +#endif + if(family == AF_INET6) { +# ifdef IPV6_RECVPKTINFO + if(setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, + (void*)&on, (socklen_t)sizeof(on)) < 0) { + log_err("setsockopt(..., IPV6_RECVPKTINFO, ...) failed: %s", + strerror(errno)); + return 0; + } +# elif defined(IPV6_PKTINFO) + if(setsockopt(s, IPPROTO_IPV6, IPV6_PKTINFO, + (void*)&on, (socklen_t)sizeof(on)) < 0) { + log_err("setsockopt(..., IPV6_PKTINFO, ...) failed: %s", + strerror(errno)); + return 0; + } +# else + log_err("no IPV6_RECVPKTINFO and no IPV6_PKTINFO option, please " + "disable interface-automatic in config"); + return 0; +# endif /* defined IPV6_RECVPKTINFO */ + + } else if(family == AF_INET) { +# ifdef IP_PKTINFO + if(setsockopt(s, IPPROTO_IP, IP_PKTINFO, + (void*)&on, (socklen_t)sizeof(on)) < 0) { + log_err("setsockopt(..., IP_PKTINFO, ...) failed: %s", + strerror(errno)); + return 0; + } +# elif defined(IP_RECVDSTADDR) && defined(IP_SENDSRCADDR) + if(setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR, + (void*)&on, (socklen_t)sizeof(on)) < 0) { + log_err("setsockopt(..., IP_RECVDSTADDR, ...) failed: %s", + strerror(errno)); + return 0; + } +# else + log_err("no IP_SENDSRCADDR or IP_PKTINFO option, please disable " + "interface-automatic in config"); + return 0; +# endif /* IP_PKTINFO */ + + } + return 1; +} + +/** + * Helper for ports_open. Creates one interface (or NULL for default). + * @param ifname: The interface ip address. + * @param do_auto: use automatic interface detection. + * If enabled, then ifname must be the wildcard name. + * @param do_udp: if udp should be used. + * @param do_tcp: if udp should be used. + * @param hints: for getaddrinfo. family and flags have to be set by caller. + * @param port: Port number to use (as string). + * @param list: list of open ports, appended to, changed to point to list head. + * @param rcv: receive buffer size for UDP + * @param snd: send buffer size for UDP + * @param ssl_port: ssl service port number + * @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 s, noip6=0; + if(!do_udp && !do_tcp) + return 0; + if(do_auto) { + if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1, + &noip6, rcv, snd)) == -1) { + if(noip6) { + log_warn("IPv6 protocol not available"); + return 1; + } + return 0; + } + /* getting source addr packet info is highly non-portable */ + if(!set_recvpktinfo(s, hints->ai_family)) + return 0; + if(!port_insert(list, s, listen_type_udpancil)) { +#ifndef USE_WINSOCK + close(s); +#else + closesocket(s); +#endif + return 0; + } + } else if(do_udp) { + /* regular udp socket */ + if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1, + &noip6, rcv, snd)) == -1) { + if(noip6) { + log_warn("IPv6 protocol not available"); + return 1; + } + return 0; + } + if(!port_insert(list, s, listen_type_udp)) { +#ifndef USE_WINSOCK + close(s); +#else + closesocket(s); +#endif + return 0; + } + } + if(do_tcp) { + int is_ssl = ((strchr(ifname, '@') && + 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)) == -1) { + if(noip6) { + /*log_warn("IPv6 protocol not available");*/ + return 1; + } + return 0; + } + if(is_ssl) + verbose(VERB_ALGO, "setup TCP for SSL service"); + if(!port_insert(list, s, is_ssl?listen_type_ssl: + listen_type_tcp)) { +#ifndef USE_WINSOCK + close(s); +#else + closesocket(s); +#endif + return 0; + } + } + return 1; +} + +/** + * Add items to commpoint list in front. + * @param c: commpoint to add. + * @param front: listen struct. + * @return: false on failure. + */ +static int +listen_cp_insert(struct comm_point* c, struct listen_dnsport* front) +{ + struct listen_list* item = (struct listen_list*)malloc( + sizeof(struct listen_list)); + if(!item) + return 0; + item->com = c; + item->next = front->cps; + front->cps = item; + return 1; +} + +struct listen_dnsport* +listen_create(struct comm_base* base, struct listen_port* ports, + size_t bufsize, int tcp_accept_count, void* sslctx, + comm_point_callback_t* cb, void *cb_arg) +{ + struct listen_dnsport* front = (struct listen_dnsport*) + malloc(sizeof(struct listen_dnsport)); + if(!front) + return NULL; + front->cps = NULL; + front->udp_buff = ldns_buffer_new(bufsize); + if(!front->udp_buff) { + free(front); + return NULL; + } + + /* create comm points as needed */ + while(ports) { + struct comm_point* cp = NULL; + if(ports->ftype == listen_type_udp) + cp = comm_point_create_udp(base, ports->fd, + front->udp_buff, cb, cb_arg); + else if(ports->ftype == listen_type_tcp) + cp = comm_point_create_tcp(base, ports->fd, + tcp_accept_count, bufsize, cb, cb_arg); + else if(ports->ftype == listen_type_ssl) { + cp = comm_point_create_tcp(base, ports->fd, + tcp_accept_count, bufsize, cb, cb_arg); + cp->ssl = sslctx; + } else if(ports->ftype == listen_type_udpancil) + cp = comm_point_create_udp_ancil(base, ports->fd, + front->udp_buff, cb, cb_arg); + if(!cp) { + log_err("can't create commpoint"); + listen_delete(front); + return NULL; + } + cp->do_not_close = 1; + if(!listen_cp_insert(cp, front)) { + log_err("malloc failed"); + comm_point_delete(cp); + listen_delete(front); + return NULL; + } + ports = ports->next; + } + if(!front->cps) { + log_err("Could not open sockets to accept queries."); + listen_delete(front); + return NULL; + } + + return front; +} + +void +listen_list_delete(struct listen_list* list) +{ + struct listen_list *p = list, *pn; + while(p) { + pn = p->next; + comm_point_delete(p->com); + free(p); + p = pn; + } +} + +void +listen_delete(struct listen_dnsport* front) +{ + if(!front) + return; + listen_list_delete(front->cps); + ldns_buffer_free(front->udp_buff); + free(front); +} + +struct listen_port* +listening_ports_open(struct config_file* cfg) +{ + struct listen_port* list = NULL; + struct addrinfo hints; + int i, do_ip4, do_ip6; + int do_tcp, do_auto; + char portbuf[32]; + snprintf(portbuf, sizeof(portbuf), "%d", cfg->port); + do_ip4 = cfg->do_ip4; + do_ip6 = cfg->do_ip6; + do_tcp = cfg->do_tcp; + do_auto = cfg->if_automatic && cfg->do_udp; + if(cfg->incoming_num_tcp == 0) + do_tcp = 0; + + /* getaddrinfo */ + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_PASSIVE; + /* no name lookups on our listening ports */ + if(cfg->num_ifs > 0) + hints.ai_flags |= AI_NUMERICHOST; + hints.ai_family = AF_UNSPEC; +#ifndef INET6 + do_ip6 = 0; +#endif + if(!do_ip4 && !do_ip6) { + return NULL; + } + /* create ip4 and ip6 ports so that return addresses are nice. */ + if(do_auto || cfg->num_ifs == 0) { + if(do_ip6) { + hints.ai_family = AF_INET6; + if(!ports_create_if(do_auto?"::0":"::1", + do_auto, cfg->do_udp, do_tcp, + &hints, portbuf, &list, + cfg->so_rcvbuf, cfg->so_sndbuf, + cfg->ssl_port)) { + listening_ports_free(list); + return NULL; + } + } + if(do_ip4) { + hints.ai_family = AF_INET; + if(!ports_create_if(do_auto?"0.0.0.0":"127.0.0.1", + do_auto, cfg->do_udp, do_tcp, + &hints, portbuf, &list, + cfg->so_rcvbuf, cfg->so_sndbuf, + cfg->ssl_port)) { + listening_ports_free(list); + return NULL; + } + } + } else for(i = 0; inum_ifs; i++) { + if(str_is_ip6(cfg->ifs[i])) { + if(!do_ip6) + continue; + hints.ai_family = AF_INET6; + if(!ports_create_if(cfg->ifs[i], 0, cfg->do_udp, + do_tcp, &hints, portbuf, &list, + cfg->so_rcvbuf, cfg->so_sndbuf, + cfg->ssl_port)) { + listening_ports_free(list); + return NULL; + } + } else { + if(!do_ip4) + continue; + hints.ai_family = AF_INET; + if(!ports_create_if(cfg->ifs[i], 0, cfg->do_udp, + do_tcp, &hints, portbuf, &list, + cfg->so_rcvbuf, cfg->so_sndbuf, + cfg->ssl_port)) { + listening_ports_free(list); + return NULL; + } + } + } + return list; +} + +void listening_ports_free(struct listen_port* list) +{ + struct listen_port* nx; + while(list) { + nx = list->next; + if(list->fd != -1) { +#ifndef USE_WINSOCK + close(list->fd); +#else + closesocket(list->fd); +#endif + } + free(list); + list = nx; + } +} + +size_t listen_get_mem(struct listen_dnsport* listen) +{ + size_t s = sizeof(*listen) + sizeof(*listen->base) + + sizeof(*listen->udp_buff) + + ldns_buffer_capacity(listen->udp_buff); + struct listen_list* p; + for(p = listen->cps; p; p = p->next) { + s += sizeof(*p); + s += comm_point_get_mem(p->com); + } + return s; +} + +void listen_stop_accept(struct listen_dnsport* listen) +{ + /* do not stop the ones that have no tcp_free list + * (they have already stopped listening) */ + struct listen_list* p; + for(p=listen->cps; p; p=p->next) { + if(p->com->type == comm_tcp_accept && + p->com->tcp_free != NULL) { + comm_point_stop_listening(p->com); + } + } +} + +void listen_start_accept(struct listen_dnsport* listen) +{ + /* do not start the ones that have no tcp_free list, it is no + * use to listen to them because they have no free tcp handlers */ + struct listen_list* p; + for(p=listen->cps; p; p=p->next) { + if(p->com->type == comm_tcp_accept && + p->com->tcp_free != NULL) { + comm_point_start_listening(p->com, -1, -1); + } + } +} + diff --git a/services/listen_dnsport.h b/services/listen_dnsport.h new file mode 100644 index 00000000000..4d37aca5eee --- /dev/null +++ b/services/listen_dnsport.h @@ -0,0 +1,196 @@ +/* + * services/listen_dnsport.h - listen on port 53 for incoming DNS queries. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file has functions to get queries from clients. + */ + +#ifndef LISTEN_DNSPORT_H +#define LISTEN_DNSPORT_H + +#include "util/netevent.h" +struct listen_list; +struct config_file; +struct addrinfo; + +/** + * Listening for queries structure. + * Contains list of query-listen sockets. + */ +struct listen_dnsport { + /** Base for select calls */ + struct comm_base* base; + + /** buffer shared by UDP connections, since there is only one + datagram at any time. */ + ldns_buffer* udp_buff; + + /** list of comm points used to get incoming events */ + struct listen_list* cps; +}; + +/** + * Single linked list to store event points. + */ +struct listen_list { + /** next in list */ + struct listen_list* next; + /** event info */ + struct comm_point* com; +}; + +/** + * type of ports + */ +enum listen_type { + /** udp type */ + listen_type_udp, + /** tcp type */ + listen_type_tcp, + /** udp ipv6 (v4mapped) for use with ancillary data */ + listen_type_udpancil, + /** ssl over tcp type */ + listen_type_ssl +}; + +/** + * Single linked list to store shared ports that have been + * opened for use by all threads. + */ +struct listen_port { + /** next in list */ + struct listen_port* next; + /** file descriptor, open and ready for use */ + int fd; + /** type of file descriptor, udp or tcp */ + enum listen_type ftype; +}; + +/** + * Create shared listening ports + * Getaddrinfo, create socket, bind and listen to zero or more + * interfaces for IP4 and/or IP6, for UDP and/or TCP. + * On the given port number. It creates the sockets. + * @param cfg: settings on what ports to open. + * @return: linked list of ports or NULL on error. + */ +struct listen_port* listening_ports_open(struct config_file* cfg); + +/** + * Close and delete the (list of) listening ports. + */ +void listening_ports_free(struct listen_port* list); + +/** + * Create commpoints with for this thread for the shared ports. + * @param base: the comm_base that provides event functionality. + * for default all ifs. + * @param ports: the list of shared ports. + * @param bufsize: size of datagram buffer. + * @param tcp_accept_count: max number of simultaneous TCP connections + * from clients. + * @param sslctx: nonNULL if ssl context. + * @param cb: callback function when a request arrives. It is passed + * the packet and user argument. Return true to send a reply. + * @param cb_arg: user data argument for callback function. + * @return: the malloced listening structure, ready for use. NULL on error. + */ +struct listen_dnsport* listen_create(struct comm_base* base, + struct listen_port* ports, size_t bufsize, int tcp_accept_count, + void* sslctx, comm_point_callback_t* cb, void* cb_arg); + +/** + * delete the listening structure + * @param listen: listening structure. + */ +void listen_delete(struct listen_dnsport* listen); + +/** + * delete listen_list of commpoints. Calls commpointdelete() on items. + * This may close the fds or not depending on flags. + * @param list: to delete. + */ +void listen_list_delete(struct listen_list* list); + +/** + * get memory size used by the listening structs + * @param listen: listening structure. + * @return: size in bytes. + */ +size_t listen_get_mem(struct listen_dnsport* listen); + +/** + * stop accept handlers for TCP (until enabled again) + * @param listen: listening structure. + */ +void listen_stop_accept(struct listen_dnsport* listen); + +/** + * start accept handlers for TCP (was stopped before) + * @param listen: listening structure. + */ +void listen_start_accept(struct listen_dnsport* listen); + +/** + * Create and bind nonblocking UDP socket + * @param family: for socket call. + * @param socktype: for socket call. + * @param addr: for bind call. + * @param addrlen: for bind call. + * @param v6only: if enabled, IP6 sockets get IP6ONLY option set. + * if enabled with value 2 IP6ONLY option is disabled. + * @param inuse: on error, this is set true if the port was in use. + * @param noproto: on error, this is set true if cause is that the + IPv6 proto (family) is not available. + * @param rcv: set size on rcvbuf with socket option, if 0 it is not set. + * @param snd: set size on sndbuf with socket option, if 0 it is not set. + * @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); + +/** + * Create and bind TCP listening socket + * @param addr: address info ready to make socket. + * @param v6only: enable ip6 only flag on ip6 sockets. + * @param noproto: if error caused by lack of protocol support. + * @return: the socket. -1 on error. + */ +int create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto); + +#endif /* LISTEN_DNSPORT_H */ diff --git a/services/localzone.c b/services/localzone.c new file mode 100644 index 00000000000..98d69433e30 --- /dev/null +++ b/services/localzone.c @@ -0,0 +1,1353 @@ +/* + * services/localzone.c - local zones authority service. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions to enable local zone authority service. + */ +#include "config.h" +#include +#include +#include "services/localzone.h" +#include "util/regional.h" +#include "util/config_file.h" +#include "util/data/dname.h" +#include "util/data/packed_rrset.h" +#include "util/data/msgencode.h" +#include "util/net_help.h" +#include "util/data/msgreply.h" +#include "util/data/msgparse.h" + +struct local_zones* +local_zones_create(void) +{ + struct local_zones* zones = (struct local_zones*)calloc(1, + sizeof(*zones)); + if(!zones) + return NULL; + rbtree_init(&zones->ztree, &local_zone_cmp); + lock_quick_init(&zones->lock); + lock_protect(&zones->lock, &zones->ztree, sizeof(zones->ztree)); + /* also lock protects the rbnode's in struct local_zone */ + return zones; +} + +/** helper traverse to delete zones */ +static void +lzdel(rbnode_t* n, void* ATTR_UNUSED(arg)) +{ + struct local_zone* z = (struct local_zone*)n->key; + local_zone_delete(z); +} + +void +local_zones_delete(struct local_zones* zones) +{ + if(!zones) + return; + lock_quick_destroy(&zones->lock); + /* walk through zones and delete them all */ + traverse_postorder(&zones->ztree, lzdel, NULL); + free(zones); +} + +void +local_zone_delete(struct local_zone* z) +{ + if(!z) + return; + lock_rw_destroy(&z->lock); + regional_destroy(z->region); + free(z->name); + free(z); +} + +int +local_zone_cmp(const void* z1, const void* z2) +{ + /* first sort on class, so that hierarchy can be maintained within + * a class */ + struct local_zone* a = (struct local_zone*)z1; + struct local_zone* b = (struct local_zone*)z2; + int m; + if(a->dclass != b->dclass) { + if(a->dclass < b->dclass) + return -1; + return 1; + } + return dname_lab_cmp(a->name, a->namelabs, b->name, b->namelabs, &m); +} + +int +local_data_cmp(const void* d1, const void* d2) +{ + struct local_data* a = (struct local_data*)d1; + struct local_data* b = (struct local_data*)d2; + int m; + return dname_canon_lab_cmp(a->name, a->namelabs, b->name, + b->namelabs, &m); +} + +/* form wireformat from text format domain name */ +int +parse_dname(const char* str, uint8_t** res, size_t* len, int* labs) +{ + ldns_rdf* rdf; + *res = NULL; + *len = 0; + *labs = 0; + rdf = ldns_dname_new_frm_str(str); + if(!rdf) { + log_err("cannot parse name %s", str); + return 0; + } + *res = memdup(ldns_rdf_data(rdf), ldns_rdf_size(rdf)); + ldns_rdf_deep_free(rdf); + if(!*res) { + log_err("out of memory"); + return 0; + } + *labs = dname_count_size_labels(*res, len); + return 1; +} + +/** create a new localzone */ +static struct local_zone* +local_zone_create(uint8_t* nm, size_t len, int labs, + enum localzone_type t, uint16_t dclass) +{ + struct local_zone* z = (struct local_zone*)calloc(1, sizeof(*z)); + if(!z) { + return NULL; + } + z->node.key = z; + z->dclass = dclass; + z->type = t; + z->name = nm; + z->namelen = len; + z->namelabs = labs; + lock_rw_init(&z->lock); + z->region = regional_create(); + if(!z->region) { + free(z); + return NULL; + } + rbtree_init(&z->data, &local_data_cmp); + lock_protect(&z->lock, &z->parent, sizeof(*z)-sizeof(rbnode_t)); + /* also the zones->lock protects node, parent, name*, class */ + return z; +} + +/** enter a new zone with allocated dname returns with WRlock */ +static struct local_zone* +lz_enter_zone_dname(struct local_zones* zones, uint8_t* nm, size_t len, + int labs, enum localzone_type t, uint16_t c) +{ + struct local_zone* z = local_zone_create(nm, len, labs, t, c); + if(!z) { + log_err("out of memory"); + return NULL; + } + + /* add to rbtree */ + lock_quick_lock(&zones->lock); + lock_rw_wrlock(&z->lock); + if(!rbtree_insert(&zones->ztree, &z->node)) { + log_warn("duplicate local-zone"); + lock_rw_unlock(&z->lock); + local_zone_delete(z); + lock_quick_unlock(&zones->lock); + return NULL; + } + lock_quick_unlock(&zones->lock); + return z; +} + +/** enter a new zone */ +static struct local_zone* +lz_enter_zone(struct local_zones* zones, const char* name, const char* type, + uint16_t dclass) +{ + struct local_zone* z; + enum localzone_type t; + uint8_t* nm; + size_t len; + int labs; + if(!parse_dname(name, &nm, &len, &labs)) { + log_err("bad zone name %s %s", name, type); + return NULL; + } + if(!local_zone_str2type(type, &t)) { + log_err("bad lz_enter_zone type %s %s", name, type); + free(nm); + return NULL; + } + if(!(z=lz_enter_zone_dname(zones, nm, len, labs, t, dclass))) { + log_err("could not enter zone %s %s", name, type); + return NULL; + } + return z; +} + +/** return name and class and rdata of rr; parses string */ +static int +get_rr_content(const char* str, uint8_t** nm, uint16_t* type, + uint16_t* dclass, uint32_t* ttl, ldns_buffer* rdata) +{ + ldns_rr* rr = NULL; + ldns_status status = ldns_rr_new_frm_str(&rr, str, 3600, NULL, NULL); + if(status != LDNS_STATUS_OK) { + log_err("error parsing local-data '%s': %s", + str, ldns_get_errorstr_by_id(status)); + ldns_rr_free(rr); + return 0; + } + *nm = memdup(ldns_rdf_data(ldns_rr_owner(rr)), + ldns_rdf_size(ldns_rr_owner(rr))); + if(!*nm) { + log_err("out of memory"); + ldns_rr_free(rr); + return 0; + } + *dclass = ldns_rr_get_class(rr); + *type = ldns_rr_get_type(rr); + *ttl = (uint32_t)ldns_rr_ttl(rr); + ldns_buffer_clear(rdata); + ldns_buffer_skip(rdata, 2); + status = ldns_rr_rdata2buffer_wire(rdata, rr); + ldns_rr_free(rr); + if(status != LDNS_STATUS_OK) { + log_err("error converting RR '%s' to wireformat: %s", + str, ldns_get_errorstr_by_id(status)); + free(*nm); + *nm = NULL; + return 0; + } + ldns_buffer_flip(rdata); + ldns_buffer_write_u16_at(rdata, 0, ldns_buffer_limit(rdata) - 2); + return 1; +} + +/** return name and class of rr; parses string */ +static int +get_rr_nameclass(const char* str, uint8_t** nm, uint16_t* dclass) +{ + ldns_rr* rr = NULL; + ldns_status status = ldns_rr_new_frm_str(&rr, str, 3600, NULL, NULL); + if(status != LDNS_STATUS_OK) { + log_err("error parsing local-data '%s': %s", + str, ldns_get_errorstr_by_id(status)); + ldns_rr_free(rr); + return 0; + } + *nm = memdup(ldns_rdf_data(ldns_rr_owner(rr)), + ldns_rdf_size(ldns_rr_owner(rr))); + *dclass = ldns_rr_get_class(rr); + ldns_rr_free(rr); + if(!*nm) { + log_err("out of memory"); + return 0; + } + return 1; +} + +/** + * Find an rrset in local data structure. + * @param data: local data domain name structure. + * @param type: type to look for (host order). + * @return rrset pointer or NULL if not found. + */ +static struct local_rrset* +local_data_find_type(struct local_data* data, uint16_t type) +{ + struct local_rrset* p; + type = htons(type); + for(p = data->rrsets; p; p = p->next) { + if(p->rrset->rk.type == type) + return p; + } + return NULL; +} + +/** check for RR duplicates */ +static int +rr_is_duplicate(struct packed_rrset_data* pd, ldns_buffer* buf) +{ + size_t i; + for(i=0; icount; i++) { + if(ldns_buffer_limit(buf) == pd->rr_len[i] && + memcmp(ldns_buffer_begin(buf), pd->rr_data[i], + ldns_buffer_limit(buf)) == 0) + return 1; + } + return 0; +} + +/** new local_rrset */ +static struct local_rrset* +new_local_rrset(struct regional* region, struct local_data* node, + uint16_t rrtype, uint16_t rrclass) +{ + struct packed_rrset_data* pd; + struct local_rrset* rrset = (struct local_rrset*) + regional_alloc_zero(region, sizeof(*rrset)); + if(!rrset) { + log_err("out of memory"); + return NULL; + } + rrset->next = node->rrsets; + node->rrsets = rrset; + rrset->rrset = (struct ub_packed_rrset_key*) + regional_alloc_zero(region, sizeof(*rrset->rrset)); + if(!rrset->rrset) { + log_err("out of memory"); + return NULL; + } + rrset->rrset->entry.key = rrset->rrset; + pd = (struct packed_rrset_data*)regional_alloc_zero(region, + sizeof(*pd)); + if(!pd) { + log_err("out of memory"); + return NULL; + } + pd->trust = rrset_trust_prim_noglue; + pd->security = sec_status_insecure; + rrset->rrset->entry.data = pd; + rrset->rrset->rk.dname = node->name; + rrset->rrset->rk.dname_len = node->namelen; + rrset->rrset->rk.type = htons(rrtype); + rrset->rrset->rk.rrset_class = htons(rrclass); + return rrset; +} + +/** insert RR into RRset data structure; Wastes a couple of bytes */ +static int +insert_rr(struct regional* region, struct packed_rrset_data* pd, + ldns_buffer* buf, uint32_t ttl) +{ + size_t* oldlen = pd->rr_len; + uint32_t* oldttl = pd->rr_ttl; + uint8_t** olddata = pd->rr_data; + + /* add RR to rrset */ + pd->count++; + pd->rr_len = regional_alloc(region, sizeof(*pd->rr_len)*pd->count); + pd->rr_ttl = regional_alloc(region, sizeof(*pd->rr_ttl)*pd->count); + pd->rr_data = regional_alloc(region, sizeof(*pd->rr_data)*pd->count); + if(!pd->rr_len || !pd->rr_ttl || !pd->rr_data) { + log_err("out of memory"); + return 0; + } + if(pd->count > 1) { + memcpy(pd->rr_len+1, oldlen, + sizeof(*pd->rr_len)*(pd->count-1)); + memcpy(pd->rr_ttl+1, oldttl, + sizeof(*pd->rr_ttl)*(pd->count-1)); + memcpy(pd->rr_data+1, olddata, + sizeof(*pd->rr_data)*(pd->count-1)); + } + pd->rr_len[0] = ldns_buffer_limit(buf); + pd->rr_ttl[0] = ttl; + pd->rr_data[0] = regional_alloc_init(region, + ldns_buffer_begin(buf), ldns_buffer_limit(buf)); + if(!pd->rr_data[0]) { + log_err("out of memory"); + return 0; + } + return 1; +} + +/** find a data node by exact name */ +static struct local_data* +lz_find_node(struct local_zone* z, uint8_t* nm, size_t nmlen, int nmlabs) +{ + struct local_data key; + key.node.key = &key; + key.name = nm; + key.namelen = nmlen; + key.namelabs = nmlabs; + return (struct local_data*)rbtree_search(&z->data, &key.node); +} + +/** find a node, create it if not and all its empty nonterminal parents */ +static int +lz_find_create_node(struct local_zone* z, uint8_t* nm, size_t nmlen, + int nmlabs, struct local_data** res) +{ + struct local_data* ld = lz_find_node(z, nm, nmlen, nmlabs); + if(!ld) { + /* create a domain name to store rr. */ + ld = (struct local_data*)regional_alloc_zero(z->region, + sizeof(*ld)); + if(!ld) { + log_err("out of memory adding local data"); + return 0; + } + ld->node.key = ld; + ld->name = regional_alloc_init(z->region, nm, nmlen); + if(!ld->name) { + log_err("out of memory"); + return 0; + } + ld->namelen = nmlen; + ld->namelabs = nmlabs; + if(!rbtree_insert(&z->data, &ld->node)) { + log_assert(0); /* duplicate name */ + } + /* see if empty nonterminals need to be created */ + if(nmlabs > z->namelabs) { + dname_remove_label(&nm, &nmlen); + if(!lz_find_create_node(z, nm, nmlen, nmlabs-1, res)) + return 0; + } + } + *res = ld; + return 1; +} + +/** enter data RR into auth zone */ +static int +lz_enter_rr_into_zone(struct local_zone* z, ldns_buffer* buf, + const char* rrstr) +{ + uint8_t* nm; + size_t nmlen; + int nmlabs; + struct local_data* node; + struct local_rrset* rrset; + struct packed_rrset_data* pd; + uint16_t rrtype, rrclass; + uint32_t ttl; + if(!get_rr_content(rrstr, &nm, &rrtype, &rrclass, &ttl, buf)) { + log_err("bad local-data: %s", rrstr); + return 0; + } + log_assert(z->dclass == rrclass); + if(z->type == local_zone_redirect && + query_dname_compare(z->name, nm) != 0) { + log_err("local-data in redirect zone must reside at top of zone" + ", not at %s", rrstr); + free(nm); + return 0; + } + nmlabs = dname_count_size_labels(nm, &nmlen); + if(!lz_find_create_node(z, nm, nmlen, nmlabs, &node)) { + free(nm); + return 0; + } + log_assert(node); + free(nm); + + rrset = local_data_find_type(node, rrtype); + if(!rrset) { + rrset = new_local_rrset(z->region, node, rrtype, rrclass); + if(!rrset) + return 0; + if(query_dname_compare(node->name, z->name) == 0) { + if(rrtype == LDNS_RR_TYPE_NSEC) + rrset->rrset->rk.flags = PACKED_RRSET_NSEC_AT_APEX; + if(rrtype == LDNS_RR_TYPE_SOA) + z->soa = rrset->rrset; + } + } + pd = (struct packed_rrset_data*)rrset->rrset->entry.data; + log_assert(rrset && pd); + + /* check for duplicate RR */ + if(rr_is_duplicate(pd, buf)) { + verbose(VERB_ALGO, "ignoring duplicate RR: %s", rrstr); + return 1; + } + return insert_rr(z->region, pd, buf, ttl); +} + +/** enter a data RR into auth data; a zone for it must exist */ +static int +lz_enter_rr_str(struct local_zones* zones, const char* rr, ldns_buffer* buf) +{ + uint8_t* rr_name; + uint16_t rr_class; + size_t len; + int labs; + struct local_zone* z; + int r; + if(!get_rr_nameclass(rr, &rr_name, &rr_class)) { + log_err("bad rr %s", rr); + return 0; + } + labs = dname_count_size_labels(rr_name, &len); + lock_quick_lock(&zones->lock); + z = local_zones_lookup(zones, rr_name, len, labs, rr_class); + if(!z) { + lock_quick_unlock(&zones->lock); + fatal_exit("internal error: no zone for rr %s", rr); + } + lock_rw_wrlock(&z->lock); + lock_quick_unlock(&zones->lock); + free(rr_name); + r = lz_enter_rr_into_zone(z, buf, rr); + lock_rw_unlock(&z->lock); + return r; +} + +/** parse local-zone: statements */ +static int +lz_enter_zones(struct local_zones* zones, struct config_file* cfg) +{ + struct config_str2list* p; + struct local_zone* z; + for(p = cfg->local_zones; p; p = p->next) { + if(!(z=lz_enter_zone(zones, p->str, p->str2, + LDNS_RR_CLASS_IN))) + return 0; + lock_rw_unlock(&z->lock); + } + return 1; +} + +/** lookup a zone in rbtree; exact match only; SLOW due to parse */ +static int +lz_exists(struct local_zones* zones, const char* name) +{ + struct local_zone z; + z.node.key = &z; + z.dclass = LDNS_RR_CLASS_IN; + if(!parse_dname(name, &z.name, &z.namelen, &z.namelabs)) { + log_err("bad name %s", name); + return 0; + } + lock_quick_lock(&zones->lock); + if(rbtree_search(&zones->ztree, &z.node)) { + lock_quick_unlock(&zones->lock); + free(z.name); + return 1; + } + lock_quick_unlock(&zones->lock); + free(z.name); + return 0; +} + +/** lookup a zone in cfg->nodefault list */ +static int +lz_nodefault(struct config_file* cfg, const char* name) +{ + struct config_strlist* p; + size_t len = strlen(name); + if(len == 0) return 0; + if(name[len-1] == '.') len--; + + for(p = cfg->local_zones_nodefault; p; p = p->next) { + /* compare zone name, lowercase, compare without ending . */ + if(strncasecmp(p->str, name, len) == 0 && + (strlen(p->str) == len || (strlen(p->str)==len+1 && + p->str[len] == '.'))) + return 1; + } + return 0; +} + +/** enter AS112 default zone */ +static int +add_as112_default(struct local_zones* zones, struct config_file* cfg, + ldns_buffer* buf, const char* name) +{ + struct local_zone* z; + char str[1024]; /* known long enough */ + if(lz_exists(zones, name) || lz_nodefault(cfg, name)) + return 1; /* do not enter default content */ + if(!(z=lz_enter_zone(zones, name, "static", LDNS_RR_CLASS_IN))) + return 0; + snprintf(str, sizeof(str), "%s 10800 IN SOA localhost. " + "nobody.invalid. 1 3600 1200 604800 10800", name); + if(!lz_enter_rr_into_zone(z, buf, str)) { + lock_rw_unlock(&z->lock); + return 0; + } + snprintf(str, sizeof(str), "%s 10800 IN NS localhost. ", name); + if(!lz_enter_rr_into_zone(z, buf, str)) { + lock_rw_unlock(&z->lock); + return 0; + } + lock_rw_unlock(&z->lock); + return 1; +} + +/** enter default zones */ +static int +lz_enter_defaults(struct local_zones* zones, struct config_file* cfg, + ldns_buffer* buf) +{ + struct local_zone* z; + + /* this list of zones is from RFC 6303 */ + + /* localhost. zone */ + if(!lz_exists(zones, "localhost.") && + !lz_nodefault(cfg, "localhost.")) { + if(!(z=lz_enter_zone(zones, "localhost.", "static", + LDNS_RR_CLASS_IN)) || + !lz_enter_rr_into_zone(z, buf, + "localhost. 10800 IN NS localhost.") || + !lz_enter_rr_into_zone(z, buf, + "localhost. 10800 IN SOA localhost. nobody.invalid. " + "1 3600 1200 604800 10800") || + !lz_enter_rr_into_zone(z, buf, + "localhost. 10800 IN A 127.0.0.1") || + !lz_enter_rr_into_zone(z, buf, + "localhost. 10800 IN AAAA ::1")) { + log_err("out of memory adding default zone"); + if(z) { lock_rw_unlock(&z->lock); } + return 0; + } + lock_rw_unlock(&z->lock); + } + /* reverse ip4 zone */ + if(!lz_exists(zones, "127.in-addr.arpa.") && + !lz_nodefault(cfg, "127.in-addr.arpa.")) { + if(!(z=lz_enter_zone(zones, "127.in-addr.arpa.", "static", + LDNS_RR_CLASS_IN)) || + !lz_enter_rr_into_zone(z, buf, + "127.in-addr.arpa. 10800 IN NS localhost.") || + !lz_enter_rr_into_zone(z, buf, + "127.in-addr.arpa. 10800 IN SOA localhost. " + "nobody.invalid. 1 3600 1200 604800 10800") || + !lz_enter_rr_into_zone(z, buf, + "1.0.0.127.in-addr.arpa. 10800 IN PTR localhost.")) { + log_err("out of memory adding default zone"); + if(z) { lock_rw_unlock(&z->lock); } + return 0; + } + lock_rw_unlock(&z->lock); + } + /* reverse ip6 zone */ + if(!lz_exists(zones, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.") && + !lz_nodefault(cfg, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.")) { + if(!(z=lz_enter_zone(zones, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.", "static", + LDNS_RR_CLASS_IN)) || + !lz_enter_rr_into_zone(z, buf, + "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN NS localhost.") || + !lz_enter_rr_into_zone(z, buf, + "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN SOA localhost. " + "nobody.invalid. 1 3600 1200 604800 10800") || + !lz_enter_rr_into_zone(z, buf, + "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN PTR localhost.")) { + log_err("out of memory adding default zone"); + if(z) { lock_rw_unlock(&z->lock); } + return 0; + } + lock_rw_unlock(&z->lock); + } + if ( !add_as112_default(zones, cfg, buf, "10.in-addr.arpa.") || + !add_as112_default(zones, cfg, buf, "16.172.in-addr.arpa.") || + !add_as112_default(zones, cfg, buf, "17.172.in-addr.arpa.") || + !add_as112_default(zones, cfg, buf, "18.172.in-addr.arpa.") || + !add_as112_default(zones, cfg, buf, "19.172.in-addr.arpa.") || + !add_as112_default(zones, cfg, buf, "20.172.in-addr.arpa.") || + !add_as112_default(zones, cfg, buf, "21.172.in-addr.arpa.") || + !add_as112_default(zones, cfg, buf, "22.172.in-addr.arpa.") || + !add_as112_default(zones, cfg, buf, "23.172.in-addr.arpa.") || + !add_as112_default(zones, cfg, buf, "24.172.in-addr.arpa.") || + !add_as112_default(zones, cfg, buf, "25.172.in-addr.arpa.") || + !add_as112_default(zones, cfg, buf, "26.172.in-addr.arpa.") || + !add_as112_default(zones, cfg, buf, "27.172.in-addr.arpa.") || + !add_as112_default(zones, cfg, buf, "28.172.in-addr.arpa.") || + !add_as112_default(zones, cfg, buf, "29.172.in-addr.arpa.") || + !add_as112_default(zones, cfg, buf, "30.172.in-addr.arpa.") || + !add_as112_default(zones, cfg, buf, "31.172.in-addr.arpa.") || + !add_as112_default(zones, cfg, buf, "168.192.in-addr.arpa.") || + !add_as112_default(zones, cfg, buf, "0.in-addr.arpa.") || + !add_as112_default(zones, cfg, buf, "254.169.in-addr.arpa.") || + !add_as112_default(zones, cfg, buf, "2.0.192.in-addr.arpa.") || + !add_as112_default(zones, cfg, buf, "100.51.198.in-addr.arpa.") || + !add_as112_default(zones, cfg, buf, "113.0.203.in-addr.arpa.") || + !add_as112_default(zones, cfg, buf, "255.255.255.255.in-addr.arpa.") || + !add_as112_default(zones, cfg, buf, "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.") || + !add_as112_default(zones, cfg, buf, "d.f.ip6.arpa.") || + !add_as112_default(zones, cfg, buf, "8.e.f.ip6.arpa.") || + !add_as112_default(zones, cfg, buf, "9.e.f.ip6.arpa.") || + !add_as112_default(zones, cfg, buf, "a.e.f.ip6.arpa.") || + !add_as112_default(zones, cfg, buf, "b.e.f.ip6.arpa.") || + !add_as112_default(zones, cfg, buf, "8.b.d.0.1.0.0.2.ip6.arpa.")) { + log_err("out of memory adding default zone"); + 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) +{ + struct local_zone* node, *prev = NULL, *p; + int m; + lock_quick_lock(&zones->lock); + RBTREE_FOR(node, struct local_zone*, &zones->ztree) { + lock_rw_wrlock(&node->lock); + node->parent = NULL; + if(!prev || prev->dclass != node->dclass) { + prev = node; + lock_rw_unlock(&node->lock); + continue; + } + (void)dname_lab_cmp(prev->name, prev->namelabs, node->name, + node->namelabs, &m); /* we know prev is smaller */ + /* sort order like: . com. bla.com. zwb.com. net. */ + /* find the previous, or parent-parent-parent */ + for(p = prev; p; p = p->parent) + /* looking for name with few labels, a parent */ + if(p->namelabs <= m) { + /* ==: since prev matched m, this is closest*/ + /* <: prev matches more, but is not a parent, + * this one is a (grand)parent */ + node->parent = p; + break; + } + prev = node; + lock_rw_unlock(&node->lock); + } + lock_quick_unlock(&zones->lock); +} + +/** enter implicit transparent zone for local-data: without local-zone: */ +static int +lz_setup_implicit(struct local_zones* zones, struct config_file* cfg) +{ + /* walk over all items that have no parent zone and find + * the name that covers them all (could be the root) and + * add that as a transparent zone */ + struct config_strlist* p; + int have_name = 0; + int have_other_classes = 0; + uint16_t dclass = 0; + uint8_t* nm = 0; + size_t nmlen = 0; + int nmlabs = 0; + int match = 0; /* number of labels match count */ + + init_parents(zones); /* to enable local_zones_lookup() */ + for(p = cfg->local_data; p; p = p->next) { + uint8_t* rr_name; + uint16_t rr_class; + size_t len; + int labs; + if(!get_rr_nameclass(p->str, &rr_name, &rr_class)) { + log_err("Bad local-data RR %s", p->str); + return 0; + } + labs = dname_count_size_labels(rr_name, &len); + lock_quick_lock(&zones->lock); + if(!local_zones_lookup(zones, rr_name, len, labs, rr_class)) { + if(!have_name) { + dclass = rr_class; + nm = rr_name; + nmlen = len; + nmlabs = labs; + match = labs; + have_name = 1; + } else { + int m; + if(rr_class != dclass) { + /* process other classes later */ + free(rr_name); + have_other_classes = 1; + lock_quick_unlock(&zones->lock); + continue; + } + /* find smallest shared topdomain */ + (void)dname_lab_cmp(nm, nmlabs, + rr_name, labs, &m); + free(rr_name); + if(m < match) + match = m; + } + } else free(rr_name); + lock_quick_unlock(&zones->lock); + } + if(have_name) { + uint8_t* n2; + struct local_zone* z; + /* allocate zone of smallest shared topdomain to contain em */ + n2 = nm; + dname_remove_labels(&n2, &nmlen, nmlabs - match); + n2 = memdup(n2, nmlen); + free(nm); + if(!n2) { + log_err("out of memory"); + return 0; + } + log_nametypeclass(VERB_ALGO, "implicit transparent local-zone", + n2, 0, dclass); + if(!(z=lz_enter_zone_dname(zones, n2, nmlen, match, + local_zone_transparent, dclass))) { + return 0; + } + lock_rw_unlock(&z->lock); + } + if(have_other_classes) { + /* restart to setup other class */ + return lz_setup_implicit(zones, cfg); + } + return 1; +} + +/** enter auth data */ +static int +lz_enter_data(struct local_zones* zones, struct config_file* cfg, + ldns_buffer* buf) +{ + struct config_strlist* p; + for(p = cfg->local_data; p; p = p->next) { + if(!lz_enter_rr_str(zones, p->str, buf)) + return 0; + } + return 1; +} + +/** free memory from config */ +static void +lz_freeup_cfg(struct config_file* cfg) +{ + config_deldblstrlist(cfg->local_zones); + cfg->local_zones = NULL; + config_delstrlist(cfg->local_zones_nodefault); + cfg->local_zones_nodefault = NULL; + config_delstrlist(cfg->local_data); + cfg->local_data = NULL; +} + +int +local_zones_apply_cfg(struct local_zones* zones, struct config_file* cfg) +{ + ldns_buffer* buf = ldns_buffer_new(65535); + if(!buf) fatal_exit("cannot create temporary buffer"); + + /* create zones from zone statements. */ + if(!lz_enter_zones(zones, cfg)) { + ldns_buffer_free(buf); + return 0; + } + /* apply default zones+content (unless disabled, or overridden) */ + if(!lz_enter_defaults(zones, cfg, buf)) { + ldns_buffer_free(buf); + return 0; + } + /* create implicit transparent zone from data. */ + if(!lz_setup_implicit(zones, cfg)) { + ldns_buffer_free(buf); + return 0; + } + + /* setup parent ptrs for lookup during data entry */ + init_parents(zones); + /* insert local data */ + if(!lz_enter_data(zones, cfg, buf)) { + ldns_buffer_free(buf); + return 0; + } + /* freeup memory from cfg struct. */ + lz_freeup_cfg(cfg); + ldns_buffer_free(buf); + return 1; +} + +struct local_zone* +local_zones_lookup(struct local_zones* zones, + uint8_t* name, size_t len, int labs, uint16_t dclass) +{ + rbnode_t* res = NULL; + struct local_zone *result; + struct local_zone key; + 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; + } +} + +struct local_zone* +local_zones_find(struct local_zones* zones, + uint8_t* name, size_t len, int labs, uint16_t dclass) +{ + struct local_zone key; + key.node.key = &key; + key.dclass = dclass; + key.name = name; + key.namelen = len; + key.namelabs = labs; + /* exact */ + return (struct local_zone*)rbtree_search(&zones->ztree, &key); +} + +/** print all RRsets in local zone */ +static void +local_zone_out(struct local_zone* z) +{ + struct local_data* d; + struct local_rrset* p; + RBTREE_FOR(d, struct local_data*, &z->data) { + for(p = d->rrsets; p; p = p->next) { + log_nametypeclass(0, "rrset", d->name, + ntohs(p->rrset->rk.type), + ntohs(p->rrset->rk.rrset_class)); + } + } +} + +void local_zones_print(struct local_zones* zones) +{ + struct local_zone* z; + lock_quick_lock(&zones->lock); + log_info("number of auth zones %u", (unsigned)zones->ztree.count); + RBTREE_FOR(z, struct local_zone*, &zones->ztree) { + lock_rw_rdlock(&z->lock); + switch(z->type) { + case local_zone_deny: + log_nametypeclass(0, "deny zone", + z->name, 0, z->dclass); + break; + case local_zone_refuse: + log_nametypeclass(0, "refuse zone", + z->name, 0, z->dclass); + break; + case local_zone_redirect: + log_nametypeclass(0, "redirect zone", + z->name, 0, z->dclass); + break; + case local_zone_transparent: + log_nametypeclass(0, "transparent zone", + z->name, 0, z->dclass); + break; + case local_zone_typetransparent: + log_nametypeclass(0, "typetransparent zone", + z->name, 0, z->dclass); + break; + case local_zone_static: + log_nametypeclass(0, "static zone", + z->name, 0, z->dclass); + break; + default: + log_nametypeclass(0, "badtyped zone", + z->name, 0, z->dclass); + break; + } + local_zone_out(z); + lock_rw_unlock(&z->lock); + } + lock_quick_unlock(&zones->lock); +} + +/** encode answer consisting of 1 rrset */ +static int +local_encode(struct query_info* qinfo, struct edns_data* edns, + ldns_buffer* buf, struct regional* temp, + struct ub_packed_rrset_key* rrset, int ansec, int rcode) +{ + struct reply_info rep; + uint16_t udpsize; + /* make answer with time=0 for fixed TTL values */ + memset(&rep, 0, sizeof(rep)); + rep.flags = (uint16_t)((BIT_QR | BIT_AA | BIT_RA) | rcode); + rep.qdcount = 1; + if(ansec) + rep.an_numrrsets = 1; + else rep.ns_numrrsets = 1; + rep.rrset_count = 1; + rep.rrsets = &rrset; + udpsize = edns->udp_size; + edns->edns_version = EDNS_ADVERTISED_VERSION; + edns->udp_size = EDNS_ADVERTISED_SIZE; + edns->ext_rcode = 0; + edns->bits &= EDNS_DO; + if(!reply_info_answer_encode(qinfo, &rep, + *(uint16_t*)ldns_buffer_begin(buf), + ldns_buffer_read_u16_at(buf, 2), + buf, 0, 0, temp, udpsize, edns, + (int)(edns->bits&EDNS_DO), 0)) + error_encode(buf, (LDNS_RCODE_SERVFAIL|BIT_AA), qinfo, + *(uint16_t*)ldns_buffer_begin(buf), + ldns_buffer_read_u16_at(buf, 2), edns); + return 1; +} + +/** answer local data match */ +static int +local_data_answer(struct local_zone* z, struct query_info* qinfo, + struct edns_data* edns, ldns_buffer* buf, struct regional* temp, + int labs, struct local_data** ldp) +{ + struct local_data key; + struct local_data* ld; + struct local_rrset* lr; + key.node.key = &key; + key.name = qinfo->qname; + key.namelen = qinfo->qname_len; + key.namelabs = labs; + if(z->type == local_zone_redirect) { + key.name = z->name; + key.namelen = z->namelen; + key.namelabs = z->namelabs; + } + ld = (struct local_data*)rbtree_search(&z->data, &key.node); + *ldp = ld; + if(!ld) { + return 0; + } + lr = local_data_find_type(ld, qinfo->qtype); + if(!lr) + return 0; + if(z->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; + r.rk.dname_len = qinfo->qname_len; + return local_encode(qinfo, edns, buf, temp, &r, 1, + LDNS_RCODE_NOERROR); + } + return local_encode(qinfo, edns, buf, temp, lr->rrset, 1, + LDNS_RCODE_NOERROR); +} + +/** + * answer in case where no exact match is found + * @param z: zone for query + * @param qinfo: query + * @param edns: edns from query + * @param buf: buffer for answer. + * @param temp: temp region for encoding + * @param ld: local data, if NULL, no such name exists in localdata. + * @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, ldns_buffer* buf, struct regional* temp, + struct local_data* ld) +{ + if(z->type == local_zone_deny) { + /** no reply at all, signal caller by clearing buffer. */ + ldns_buffer_clear(buf); + ldns_buffer_flip(buf); + return 1; + } else if(z->type == local_zone_refuse) { + error_encode(buf, (LDNS_RCODE_REFUSED|BIT_AA), qinfo, + *(uint16_t*)ldns_buffer_begin(buf), + ldns_buffer_read_u16_at(buf, 2), edns); + return 1; + } else if(z->type == local_zone_static || + z->type == local_zone_redirect) { + /* for static, reply nodata or nxdomain + * for redirect, reply nodata */ + /* no additional section processing, + * cname, dname or wildcard processing, + * or using closest match for NSEC. + * or using closest match for returning delegation downwards + */ + int rcode = ld?LDNS_RCODE_NOERROR:LDNS_RCODE_NXDOMAIN; + if(z->soa) + return local_encode(qinfo, edns, buf, temp, + z->soa, 0, rcode); + error_encode(buf, (rcode|BIT_AA), qinfo, + *(uint16_t*)ldns_buffer_begin(buf), + ldns_buffer_read_u16_at(buf, 2), edns); + return 1; + } else if(z->type == local_zone_typetransparent) { + /* no NODATA or NXDOMAINS for this zone type */ + return 0; + } + /* else z->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 */ + if(ld && ld->rrsets) { + int rcode = LDNS_RCODE_NOERROR; + if(z->soa) + return local_encode(qinfo, edns, buf, temp, + z->soa, 0, rcode); + error_encode(buf, (rcode|BIT_AA), qinfo, + *(uint16_t*)ldns_buffer_begin(buf), + ldns_buffer_read_u16_at(buf, 2), edns); + return 1; + } + + /* stop here, and resolve further on */ + return 0; +} + +int +local_zones_answer(struct local_zones* zones, struct query_info* qinfo, + struct edns_data* edns, ldns_buffer* buf, struct regional* temp) +{ + /* 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_zone* z; + int r; + lock_quick_lock(&zones->lock); + z = local_zones_lookup(zones, qinfo->qname, + qinfo->qname_len, labs, qinfo->qclass); + if(!z) { + lock_quick_unlock(&zones->lock); + return 0; + } + lock_rw_rdlock(&z->lock); + lock_quick_unlock(&zones->lock); + + if(local_data_answer(z, qinfo, edns, buf, temp, labs, &ld)) { + lock_rw_unlock(&z->lock); + return 1; + } + r = lz_zone_answer(z, qinfo, edns, buf, temp, ld); + lock_rw_unlock(&z->lock); + return r; +} + +const char* local_zone_type2str(enum localzone_type t) +{ + switch(t) { + case local_zone_deny: return "deny"; + case local_zone_refuse: return "refuse"; + case local_zone_redirect: return "redirect"; + case local_zone_transparent: return "transparent"; + case local_zone_typetransparent: return "typetransparent"; + case local_zone_static: return "static"; + case local_zone_nodefault: return "nodefault"; + } + return "badtyped"; +} + +int local_zone_str2type(const char* type, enum localzone_type* t) +{ + if(strcmp(type, "deny") == 0) + *t = local_zone_deny; + else if(strcmp(type, "refuse") == 0) + *t = local_zone_refuse; + else if(strcmp(type, "static") == 0) + *t = local_zone_static; + else if(strcmp(type, "transparent") == 0) + *t = local_zone_transparent; + else if(strcmp(type, "typetransparent") == 0) + *t = local_zone_typetransparent; + else if(strcmp(type, "redirect") == 0) + *t = local_zone_redirect; + else return 0; + return 1; +} + +/** iterate over the kiddies of the given name and set their parent ptr */ +static void +set_kiddo_parents(struct local_zone* z, struct local_zone* match, + struct local_zone* newp) +{ + /* both zones and z are locked already */ + /* in the sorted rbtree, the kiddies of z are located after z */ + /* z must be present in the tree */ + struct local_zone* p = z; + p = (struct local_zone*)rbtree_next(&p->node); + while(p!=(struct local_zone*)RBTREE_NULL && + p->dclass == z->dclass && dname_strict_subdomain(p->name, + p->namelabs, z->name, z->namelabs)) { + /* update parent ptr */ + /* only when matches with existing parent pointer, so that + * deeper child structures are not touched, i.e. + * update of x, and a.x, b.x, f.b.x, g.b.x, c.x, y + * gets to update a.x, b.x and c.x */ + lock_rw_wrlock(&p->lock); + if(p->parent == match) + p->parent = newp; + lock_rw_unlock(&p->lock); + p = (struct local_zone*)rbtree_next(&p->node); + } +} + +struct local_zone* local_zones_add_zone(struct local_zones* zones, + uint8_t* name, size_t len, int labs, uint16_t dclass, + enum localzone_type tp) +{ + /* create */ + struct local_zone* z = local_zone_create(name, len, labs, tp, dclass); + if(!z) return NULL; + lock_rw_wrlock(&z->lock); + + /* find the closest parent */ + z->parent = local_zones_find(zones, name, len, labs, dclass); + + /* insert into the tree */ + if(!rbtree_insert(&zones->ztree, &z->node)) { + /* duplicate entry! */ + lock_rw_unlock(&z->lock); + local_zone_delete(z); + log_err("internal: duplicate entry in local_zones_add_zone"); + return NULL; + } + + /* set parent pointers right */ + set_kiddo_parents(z, z->parent, z); + + lock_rw_unlock(&z->lock); + return z; +} + +void local_zones_del_zone(struct local_zones* zones, struct local_zone* z) +{ + /* fix up parents in tree */ + lock_rw_wrlock(&z->lock); + set_kiddo_parents(z, z, z->parent); + + /* remove from tree */ + (void)rbtree_delete(&zones->ztree, z); + + /* delete the zone */ + lock_rw_unlock(&z->lock); + local_zone_delete(z); +} + +int +local_zones_add_RR(struct local_zones* zones, const char* rr, ldns_buffer* buf) +{ + uint8_t* rr_name; + uint16_t rr_class; + size_t len; + int labs; + struct local_zone* z; + int r; + if(!get_rr_nameclass(rr, &rr_name, &rr_class)) { + return 0; + } + labs = dname_count_size_labels(rr_name, &len); + lock_quick_lock(&zones->lock); + z = local_zones_lookup(zones, rr_name, len, labs, rr_class); + if(!z) { + z = local_zones_add_zone(zones, rr_name, len, labs, rr_class, + local_zone_transparent); + if(!z) { + lock_quick_unlock(&zones->lock); + return 0; + } + } else { + free(rr_name); + } + lock_rw_wrlock(&z->lock); + lock_quick_unlock(&zones->lock); + r = lz_enter_rr_into_zone(z, buf, rr); + lock_rw_unlock(&z->lock); + return r; +} + +/** returns true if the node is terminal so no deeper domain names exist */ +static int +is_terminal(struct local_data* d) +{ + /* for empty nonterminals, the deeper domain names are sorted + * right after them, so simply check the next name in the tree + */ + struct local_data* n = (struct local_data*)rbtree_next(&d->node); + if(n == (struct local_data*)RBTREE_NULL) + return 1; /* last in tree, no deeper node */ + if(dname_strict_subdomain(n->name, n->namelabs, d->name, d->namelabs)) + return 0; /* there is a deeper node */ + return 1; +} + +/** delete empty terminals from tree when final data is deleted */ +static void +del_empty_term(struct local_zone* z, struct local_data* d, + uint8_t* name, size_t len, int labs) +{ + while(d && d->rrsets == NULL && is_terminal(d)) { + /* is this empty nonterminal? delete */ + /* note, no memory recycling in zone region */ + (void)rbtree_delete(&z->data, d); + + /* go up and to the next label */ + if(dname_is_root(name)) + return; + dname_remove_label(&name, &len); + labs--; + d = lz_find_node(z, name, len, labs); + } +} + +void local_zones_del_data(struct local_zones* zones, + uint8_t* name, size_t len, int labs, uint16_t dclass) +{ + /* find zone */ + struct local_zone* z; + struct local_data* d; + lock_quick_lock(&zones->lock); + z = local_zones_lookup(zones, name, len, labs, dclass); + if(!z) { + /* no such zone, we're done */ + lock_quick_unlock(&zones->lock); + return; + } + lock_rw_wrlock(&z->lock); + lock_quick_unlock(&zones->lock); + + /* find the domain */ + d = lz_find_node(z, name, len, labs); + if(d) { + /* no memory recycling for zone deletions ... */ + d->rrsets = NULL; + /* did we delete the soa record ? */ + if(query_dname_compare(d->name, z->name) == 0) + z->soa = NULL; + + /* cleanup the empty nonterminals for this name */ + del_empty_term(z, d, name, len, labs); + } + + lock_rw_unlock(&z->lock); +} diff --git a/services/localzone.h b/services/localzone.h new file mode 100644 index 00000000000..794988e66bb --- /dev/null +++ b/services/localzone.h @@ -0,0 +1,318 @@ +/* + * services/localzone.h - local zones authority service. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions to enable local zone authority service. + */ + +#ifndef SERVICES_LOCALZONE_H +#define SERVICES_LOCALZONE_H +#include "util/rbtree.h" +#include "util/locks.h" +struct ub_packed_rrset_key; +struct regional; +struct config_file; +struct edns_data; +struct query_info; + +/** + * Local zone type + * This type determines processing for queries that did not match + * local-data directly. + */ +enum localzone_type { + /** drop query */ + local_zone_deny = 0, + /** answer with error */ + local_zone_refuse, + /** answer nxdomain or nodata */ + local_zone_static, + /** resolve normally */ + local_zone_transparent, + /** do not block types at localdata names */ + local_zone_typetransparent, + /** answer with data at zone apex */ + local_zone_redirect, + /** remove default AS112 blocking contents for zone + * nodefault is used in config not during service. */ + local_zone_nodefault +}; + +/** + * Authoritative local zones storage, shared. + */ +struct local_zones { + /** lock on the localzone tree */ + lock_quick_t lock; + /** rbtree of struct local_zone */ + rbtree_t ztree; +}; + +/** + * Local zone. A locally served authoritative zone. + */ +struct local_zone { + /** rbtree node, key is name and class */ + rbnode_t node; + /** parent zone, if any. */ + struct local_zone* parent; + + /** zone name, in uncompressed wireformat */ + uint8_t* name; + /** length of zone name */ + size_t namelen; + /** number of labels in zone name */ + int namelabs; + /** the class of this zone. + * uses 'dclass' to not conflict with c++ keyword class. */ + uint16_t dclass; + + /** lock on the data in the structure + * For the node, parent, name, namelen, namelabs, dclass, you + * need to also hold the zones_tree lock to change them (or to + * delete this zone) */ + lock_rw_t lock; + + /** how to process zone */ + enum localzone_type type; + + /** in this region the zone's data is allocated. + * the struct local_zone itself is malloced. */ + struct regional* region; + /** local data for this zone + * rbtree of struct local_data */ + rbtree_t data; + /** if data contains zone apex SOA data, this is a ptr to it. */ + struct ub_packed_rrset_key* soa; +}; + +/** + * Local data. One domain name, and the RRs to go with it. + */ +struct local_data { + /** rbtree node, key is name only */ + rbnode_t node; + /** domain name */ + uint8_t* name; + /** length of name */ + size_t namelen; + /** number of labels in name */ + int namelabs; + /** the data rrsets, with different types, linked list. + * If this list is NULL, the node is an empty non-terminal. */ + struct local_rrset* rrsets; +}; + +/** + * A local data RRset + */ +struct local_rrset { + /** next in list */ + struct local_rrset* next; + /** RRset data item */ + struct ub_packed_rrset_key* rrset; +}; + +/** + * Create local zones storage + * @return new struct or NULL on error. + */ +struct local_zones* local_zones_create(void); + +/** + * Delete local zones storage + * @param zones: to delete. + */ +void local_zones_delete(struct local_zones* zones); + +/** + * Apply config settings; setup the local authoritative data. + * Takes care of locking. + * @param zones: is set up. + * @param cfg: config data. + * @return false on error. + */ +int local_zones_apply_cfg(struct local_zones* zones, struct config_file* cfg); + +/** + * Compare two local_zone entries in rbtree. Sort hierarchical but not + * canonical + * @param z1: zone 1 + * @param z2: zone 2 + * @return: -1, 0, +1 comparison value. + */ +int local_zone_cmp(const void* z1, const void* z2); + +/** + * Compare two local_data entries in rbtree. Sort canonical. + * @param d1: data 1 + * @param d2: data 2 + * @return: -1, 0, +1 comparison value. + */ +int local_data_cmp(const void* d1, const void* d2); + +/** + * Delete one zone + * @param z: to delete. + */ +void local_zone_delete(struct local_zone* z); + +/** + * Lookup zone that contains the given name, class. + * 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. + * @return closest local_zone or NULL if no covering zone is found. + */ +struct local_zone* local_zones_lookup(struct local_zones* zones, + uint8_t* name, size_t len, int labs, uint16_t dclass); + +/** + * Debug helper. Print all zones + * Takes care of locking. + * @param zones: the zones tree + */ +void local_zones_print(struct local_zones* zones); + +/** + * Answer authoritatively for local zones. + * Takes care of locking. + * @param zones: the stored zones (shared, read only). + * @param qinfo: query info (parsed). + * @param edns: edns info (parsed). + * @param buf: buffer with query ID and flags, also for reply. + * @param temp: temporary storage region. + * @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, ldns_buffer* buf, struct regional* temp); + +/** + * Parse the string into localzone type. + * + * @param str: string to parse + * @param t: local zone type returned here. + * @return 0 on parse error. + */ +int local_zone_str2type(const char* str, enum localzone_type* t); + +/** + * Print localzone type to a string. Pointer to a constant string. + * + * @param t: local zone type. + * @return constant string that describes type. + */ +const char* local_zone_type2str(enum localzone_type t); + +/** + * Find zone that with exactly given name, class. + * 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. + * @return the exact local_zone or NULL. + */ +struct local_zone* local_zones_find(struct local_zones* zones, + uint8_t* name, size_t len, int labs, uint16_t dclass); + +/** + * Add a new zone. Caller must hold the zones lock. + * Adjusts the other zones as well (parent pointers) after insertion. + * The zone must NOT exist (returns NULL and logs error). + * @param zones: the zones tree + * @param name: dname to add + * @param len: length of name. + * @param labs: labelcount of name. + * @param dclass: class to add. + * @param tp: type. + * @return local_zone or NULL on error, caller must printout memory error. + */ +struct local_zone* local_zones_add_zone(struct local_zones* zones, + uint8_t* name, size_t len, int labs, uint16_t dclass, + enum localzone_type tp); + +/** + * Delete a zone. Caller must hold the zones lock. + * Adjusts the other zones as well (parent pointers) after insertion. + * @param zones: the zones tree + * @param zone: the zone to delete from tree. Also deletes zone from memory. + */ +void local_zones_del_zone(struct local_zones* zones, struct local_zone* zone); + +/** + * Add RR data into the localzone data. + * Looks up the zone, if no covering zone, a transparent zone with the + * name of the RR is created. + * @param zones: the zones tree. Not locked by caller. + * @param rr: string with on RR. + * @param buf: buffer for scratch. + * @return false on failure. + */ +int local_zones_add_RR(struct local_zones* zones, const char* rr, + ldns_buffer* buf); + +/** + * Remove data from domain name in the tree. + * All types are removed. No effect if zone or name does not exist. + * @param zones: zones tree. + * @param name: dname to remove + * @param len: length of name. + * @param labs: labelcount of name. + * @param dclass: class to remove. + */ +void local_zones_del_data(struct local_zones* zones, + uint8_t* name, size_t len, int labs, uint16_t dclass); + + +/** + * Form wireformat from text format domain name. + * @param str: the domain name in text "www.example.com" + * @param res: resulting wireformat is stored here with malloc. + * @param len: length of resulting wireformat. + * @param labs: number of labels in resulting wireformat. + * @return false on error, syntax or memory. Also logged. + */ +int parse_dname(const char* str, uint8_t** res, size_t* len, int* labs); + +#endif /* SERVICES_LOCALZONE_H */ diff --git a/services/mesh.c b/services/mesh.c new file mode 100644 index 00000000000..f6fd288adf8 --- /dev/null +++ b/services/mesh.c @@ -0,0 +1,1186 @@ +/* + * services/mesh.c - deal with mesh of query states and handle events for that. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions to assist in dealing with a mesh of + * query states. This mesh is supposed to be thread-specific. + * It consists of query states (per qname, qtype, qclass) and connections + * between query states and the super and subquery states, and replies to + * send back to clients. + */ +#include "config.h" +#include +#include "services/mesh.h" +#include "services/outbound_list.h" +#include "services/cache/dns.h" +#include "util/log.h" +#include "util/net_help.h" +#include "util/module.h" +#include "util/regional.h" +#include "util/data/msgencode.h" +#include "util/timehist.h" +#include "util/fptr_wlist.h" +#include "util/alloc.h" +#include "util/config_file.h" + +/** subtract timers and the values do not overflow or become negative */ +static void +timeval_subtract(struct timeval* d, const struct timeval* end, const struct timeval* start) +{ +#ifndef S_SPLINT_S + time_t end_usec = end->tv_usec; + d->tv_sec = end->tv_sec - start->tv_sec; + if(end_usec < start->tv_usec) { + end_usec += 1000000; + d->tv_sec--; + } + d->tv_usec = end_usec - start->tv_usec; +#endif +} + +/** add timers and the values do not overflow or become negative */ +static void +timeval_add(struct timeval* d, const struct timeval* add) +{ +#ifndef S_SPLINT_S + d->tv_sec += add->tv_sec; + d->tv_usec += add->tv_usec; + if(d->tv_usec > 1000000 ) { + d->tv_usec -= 1000000; + d->tv_sec++; + } +#endif +} + +/** divide sum of timers to get average */ +static void +timeval_divide(struct timeval* avg, const struct timeval* sum, size_t d) +{ +#ifndef S_SPLINT_S + size_t leftover; + if(d == 0) { + avg->tv_sec = 0; + avg->tv_usec = 0; + return; + } + avg->tv_sec = sum->tv_sec / d; + avg->tv_usec = sum->tv_usec / d; + /* handle fraction from seconds divide */ + leftover = sum->tv_sec - avg->tv_sec*d; + avg->tv_usec += (leftover*1000000)/d; +#endif +} + +/** histogram compare of time values */ +static int +timeval_smaller(const struct timeval* x, const struct timeval* y) +{ +#ifndef S_SPLINT_S + if(x->tv_sec < y->tv_sec) + return 1; + else if(x->tv_sec == y->tv_sec) { + if(x->tv_usec <= y->tv_usec) + return 1; + else return 0; + } + else return 0; +#endif +} + +int +mesh_state_compare(const void* ap, const void* bp) +{ + struct mesh_state* a = (struct mesh_state*)ap; + struct mesh_state* b = (struct mesh_state*)bp; + + if(a->s.is_priming && !b->s.is_priming) + return -1; + if(!a->s.is_priming && b->s.is_priming) + return 1; + + if((a->s.query_flags&BIT_RD) && !(b->s.query_flags&BIT_RD)) + return -1; + if(!(a->s.query_flags&BIT_RD) && (b->s.query_flags&BIT_RD)) + return 1; + + if((a->s.query_flags&BIT_CD) && !(b->s.query_flags&BIT_CD)) + return -1; + if(!(a->s.query_flags&BIT_CD) && (b->s.query_flags&BIT_CD)) + return 1; + + return query_info_compare(&a->s.qinfo, &b->s.qinfo); +} + +int +mesh_state_ref_compare(const void* ap, const void* bp) +{ + struct mesh_state_ref* a = (struct mesh_state_ref*)ap; + struct mesh_state_ref* b = (struct mesh_state_ref*)bp; + return mesh_state_compare(a->s, b->s); +} + +struct mesh_area* +mesh_create(struct module_stack* stack, struct module_env* env) +{ + struct mesh_area* mesh = calloc(1, sizeof(struct mesh_area)); + if(!mesh) { + log_err("mesh area alloc: out of memory"); + return NULL; + } + mesh->histogram = timehist_setup(); + mesh->qbuf_bak = ldns_buffer_new(env->cfg->msg_buffer_size); + if(!mesh->histogram || !mesh->qbuf_bak) { + free(mesh); + log_err("mesh area alloc: out of memory"); + return NULL; + } + mesh->mods = *stack; + mesh->env = env; + rbtree_init(&mesh->run, &mesh_state_compare); + rbtree_init(&mesh->all, &mesh_state_compare); + mesh->num_reply_addrs = 0; + mesh->num_reply_states = 0; + mesh->num_detached_states = 0; + mesh->num_forever_states = 0; + mesh->stats_jostled = 0; + mesh->stats_dropped = 0; + mesh->max_reply_states = env->cfg->num_queries_per_thread; + mesh->max_forever_states = (mesh->max_reply_states+1)/2; +#ifndef S_SPLINT_S + mesh->jostle_max.tv_sec = (time_t)(env->cfg->jostle_time / 1000); + mesh->jostle_max.tv_usec = (time_t)((env->cfg->jostle_time % 1000) + *1000); +#endif + return mesh; +} + +/** help mesh delete delete mesh states */ +static void +mesh_delete_helper(rbnode_t* n) +{ + struct mesh_state* mstate = (struct mesh_state*)n->key; + /* perform a full delete, not only 'cleanup' routine, + * because other callbacks expect a clean state in the mesh. + * For 're-entrant' calls */ + mesh_state_delete(&mstate->s); + /* but because these delete the items from the tree, postorder + * traversal and rbtree rebalancing do not work together */ +} + +void +mesh_delete(struct mesh_area* mesh) +{ + if(!mesh) + return; + /* free all query states */ + while(mesh->all.count) + mesh_delete_helper(mesh->all.root); + timehist_delete(mesh->histogram); + ldns_buffer_free(mesh->qbuf_bak); + free(mesh); +} + +void +mesh_delete_all(struct mesh_area* mesh) +{ + /* free all query states */ + while(mesh->all.count) + mesh_delete_helper(mesh->all.root); + mesh->stats_dropped += mesh->num_reply_addrs; + /* clear mesh area references */ + rbtree_init(&mesh->run, &mesh_state_compare); + rbtree_init(&mesh->all, &mesh_state_compare); + mesh->num_reply_addrs = 0; + mesh->num_reply_states = 0; + mesh->num_detached_states = 0; + mesh->num_forever_states = 0; + mesh->forever_first = NULL; + mesh->forever_last = NULL; + mesh->jostle_first = NULL; + mesh->jostle_last = NULL; +} + +int mesh_make_new_space(struct mesh_area* mesh, ldns_buffer* qbuf) +{ + struct mesh_state* m = mesh->jostle_first; + /* free space is available */ + if(mesh->num_reply_states < mesh->max_reply_states) + return 1; + /* try to kick out a jostle-list item */ + if(m && m->reply_list && m->list_select == mesh_jostle_list) { + /* how old is it? */ + struct timeval age; + timeval_subtract(&age, mesh->env->now_tv, + &m->reply_list->start_time); + if(timeval_smaller(&mesh->jostle_max, &age)) { + /* its a goner */ + log_nametypeclass(VERB_ALGO, "query jostled out to " + "make space for a new one", + m->s.qinfo.qname, m->s.qinfo.qtype, + m->s.qinfo.qclass); + /* backup the query */ + if(qbuf) ldns_buffer_copy(mesh->qbuf_bak, qbuf); + /* notify supers */ + if(m->super_set.count > 0) { + verbose(VERB_ALGO, "notify supers of failure"); + m->s.return_msg = NULL; + m->s.return_rcode = LDNS_RCODE_SERVFAIL; + mesh_walk_supers(mesh, m); + } + mesh->stats_jostled ++; + mesh_state_delete(&m->s); + /* restore the query - note that the qinfo ptr to + * the querybuffer is then correct again. */ + if(qbuf) ldns_buffer_copy(qbuf, mesh->qbuf_bak); + return 1; + } + } + /* no space for new item */ + return 0; +} + +void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo, + uint16_t qflags, struct edns_data* edns, struct comm_reply* rep, + uint16_t qid) +{ + /* do not use CD flag from user for mesh state, we want the CD-query + * to receive validation anyway, to protect out cache contents and + * avoid bad-data in this cache that a downstream validator cannot + * remove from this cache */ + struct mesh_state* s = mesh_area_find(mesh, qinfo, qflags&BIT_RD, 0); + int was_detached = 0; + int was_noreply = 0; + int added = 0; + /* does this create a new reply state? */ + if(!s || s->list_select == mesh_no_list) { + if(!mesh_make_new_space(mesh, rep->c->buffer)) { + verbose(VERB_ALGO, "Too many queries. dropping " + "incoming query."); + comm_point_drop_reply(rep); + mesh->stats_dropped ++; + return; + } + /* for this new reply state, the reply address is free, + * so the limit of reply addresses does not stop reply states*/ + } else { + /* protect our memory usage from storing reply addresses */ + if(mesh->num_reply_addrs > mesh->max_reply_states*16) { + verbose(VERB_ALGO, "Too many requests queued. " + "dropping incoming query."); + mesh->stats_dropped++; + comm_point_drop_reply(rep); + return; + } + } + /* see if it already exists, if not, create one */ + if(!s) { +#ifdef UNBOUND_DEBUG + struct rbnode_t* n; +#endif + s = mesh_state_create(mesh->env, qinfo, qflags&BIT_RD, 0); + if(!s) { + log_err("mesh_state_create: out of memory; SERVFAIL"); + error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL, + qinfo, qid, qflags, edns); + comm_point_send_reply(rep); + return; + } +#ifdef UNBOUND_DEBUG + n = +#endif + rbtree_insert(&mesh->all, &s->node); + log_assert(n != NULL); + /* set detached (it is now) */ + mesh->num_detached_states++; + added = 1; + } + if(!s->reply_list && !s->cb_list && s->super_set.count == 0) + was_detached = 1; + if(!s->reply_list && !s->cb_list) + was_noreply = 1; + /* 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"); + error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL, + qinfo, qid, qflags, edns); + comm_point_send_reply(rep); + if(added) + mesh_state_delete(&s->s); + return; + } + /* update statistics */ + if(was_detached) { + log_assert(mesh->num_detached_states > 0); + mesh->num_detached_states--; + } + if(was_noreply) { + mesh->num_reply_states ++; + } + mesh->num_reply_addrs++; + if(s->list_select == mesh_no_list) { + /* move to either the forever or the jostle_list */ + if(mesh->num_forever_states < mesh->max_forever_states) { + mesh->num_forever_states ++; + mesh_list_insert(s, &mesh->forever_first, + &mesh->forever_last); + s->list_select = mesh_forever_list; + } else { + mesh_list_insert(s, &mesh->jostle_first, + &mesh->jostle_last); + s->list_select = mesh_jostle_list; + } + } + if(added) + mesh_run(mesh, s, module_event_new, NULL); +} + +int +mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo, + uint16_t qflags, struct edns_data* edns, ldns_buffer* buf, + uint16_t qid, mesh_cb_func_t cb, void* cb_arg) +{ + struct mesh_state* s = mesh_area_find(mesh, qinfo, qflags&BIT_RD, 0); + int was_detached = 0; + int was_noreply = 0; + int added = 0; + /* there are no limits on the number of callbacks */ + + /* see if it already exists, if not, create one */ + if(!s) { +#ifdef UNBOUND_DEBUG + struct rbnode_t* n; +#endif + s = mesh_state_create(mesh->env, qinfo, qflags&BIT_RD, 0); + if(!s) { + return 0; + } +#ifdef UNBOUND_DEBUG + n = +#endif + rbtree_insert(&mesh->all, &s->node); + log_assert(n != NULL); + /* set detached (it is now) */ + mesh->num_detached_states++; + added = 1; + } + if(!s->reply_list && !s->cb_list && s->super_set.count == 0) + was_detached = 1; + if(!s->reply_list && !s->cb_list) + was_noreply = 1; + /* add reply to s */ + if(!mesh_state_add_cb(s, edns, buf, cb, cb_arg, qid, qflags)) { + if(added) + mesh_state_delete(&s->s); + return 0; + } + /* update statistics */ + if(was_detached) { + log_assert(mesh->num_detached_states > 0); + mesh->num_detached_states--; + } + if(was_noreply) { + mesh->num_reply_states ++; + } + mesh->num_reply_addrs++; + if(added) + mesh_run(mesh, s, module_event_new, NULL); + return 1; +} + +void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo, + uint16_t qflags, uint32_t leeway) +{ + struct mesh_state* s = mesh_area_find(mesh, qinfo, qflags&BIT_RD, 0); +#ifdef UNBOUND_DEBUG + struct rbnode_t* n; +#endif + /* already exists, and for a different purpose perhaps. + * if mesh_no_list, keep it that way. */ + if(s) { + /* make it ignore the cache from now on */ + if(!s->s.blacklist) + sock_list_insert(&s->s.blacklist, NULL, 0, s->s.region); + if(s->s.prefetch_leeway < leeway) + s->s.prefetch_leeway = leeway; + return; + } + if(!mesh_make_new_space(mesh, NULL)) { + verbose(VERB_ALGO, "Too many queries. dropped prefetch."); + mesh->stats_dropped ++; + return; + } + s = mesh_state_create(mesh->env, qinfo, qflags&BIT_RD, 0); + if(!s) { + log_err("prefetch mesh_state_create: out of memory"); + return; + } +#ifdef UNBOUND_DEBUG + n = +#endif + rbtree_insert(&mesh->all, &s->node); + log_assert(n != NULL); + /* set detached (it is now) */ + mesh->num_detached_states++; + /* make it ignore the cache */ + sock_list_insert(&s->s.blacklist, NULL, 0, s->s.region); + s->s.prefetch_leeway = leeway; + + if(s->list_select == mesh_no_list) { + /* move to either the forever or the jostle_list */ + if(mesh->num_forever_states < mesh->max_forever_states) { + mesh->num_forever_states ++; + mesh_list_insert(s, &mesh->forever_first, + &mesh->forever_last); + s->list_select = mesh_forever_list; + } else { + mesh_list_insert(s, &mesh->jostle_first, + &mesh->jostle_last); + s->list_select = mesh_jostle_list; + } + } + mesh_run(mesh, s, module_event_new, NULL); +} + +void mesh_report_reply(struct mesh_area* mesh, struct outbound_entry* e, + struct comm_reply* reply, int what) +{ + enum module_ev event = module_event_reply; + e->qstate->reply = reply; + if(what != NETEVENT_NOERROR) { + event = module_event_noreply; + if(what == NETEVENT_CAPSFAIL) + event = module_event_capsfail; + } + mesh_run(mesh, e->qstate->mesh_info, event, e); +} + +struct mesh_state* +mesh_state_create(struct module_env* env, struct query_info* qinfo, + uint16_t qflags, int prime) +{ + struct regional* region = alloc_reg_obtain(env->alloc); + struct mesh_state* mstate; + int i; + if(!region) + return NULL; + mstate = (struct mesh_state*)regional_alloc(region, + sizeof(struct mesh_state)); + if(!mstate) { + alloc_reg_release(env->alloc, region); + return NULL; + } + memset(mstate, 0, sizeof(*mstate)); + mstate->node = *RBTREE_NULL; + mstate->run_node = *RBTREE_NULL; + mstate->node.key = mstate; + mstate->run_node.key = mstate; + mstate->reply_list = NULL; + mstate->list_select = mesh_no_list; + mstate->replies_sent = 0; + rbtree_init(&mstate->super_set, &mesh_state_ref_compare); + rbtree_init(&mstate->sub_set, &mesh_state_ref_compare); + mstate->num_activated = 0; + /* init module qstate */ + mstate->s.qinfo.qtype = qinfo->qtype; + mstate->s.qinfo.qclass = qinfo->qclass; + mstate->s.qinfo.qname_len = qinfo->qname_len; + mstate->s.qinfo.qname = regional_alloc_init(region, qinfo->qname, + qinfo->qname_len); + if(!mstate->s.qinfo.qname) { + alloc_reg_release(env->alloc, region); + return NULL; + } + /* remove all weird bits from qflags */ + mstate->s.query_flags = (qflags & (BIT_RD|BIT_CD)); + mstate->s.is_priming = prime; + mstate->s.reply = NULL; + mstate->s.region = region; + mstate->s.curmod = 0; + mstate->s.return_msg = 0; + mstate->s.return_rcode = LDNS_RCODE_NOERROR; + mstate->s.env = env; + mstate->s.mesh_info = mstate; + mstate->s.prefetch_leeway = 0; + /* init modules */ + for(i=0; imesh->mods.num; i++) { + mstate->s.minfo[i] = NULL; + mstate->s.ext_state[i] = module_state_initial; + } + return mstate; +} + +void +mesh_state_cleanup(struct mesh_state* mstate) +{ + struct mesh_area* mesh; + int i; + if(!mstate) + return; + mesh = mstate->s.env->mesh; + /* drop unsent replies */ + if(!mstate->replies_sent) { + struct mesh_reply* rep; + struct mesh_cb* cb; + for(rep=mstate->reply_list; rep; rep=rep->next) { + comm_point_drop_reply(&rep->query_reply); + mesh->num_reply_addrs--; + } + for(cb=mstate->cb_list; cb; cb=cb->next) { + fptr_ok(fptr_whitelist_mesh_cb(cb->cb)); + (*cb->cb)(cb->cb_arg, LDNS_RCODE_SERVFAIL, NULL, + sec_status_unchecked, NULL); + mesh->num_reply_addrs--; + } + } + + /* de-init modules */ + for(i=0; imods.num; i++) { + fptr_ok(fptr_whitelist_mod_clear(mesh->mods.mod[i]->clear)); + (*mesh->mods.mod[i]->clear)(&mstate->s, i); + mstate->s.minfo[i] = NULL; + mstate->s.ext_state[i] = module_finished; + } + alloc_reg_release(mstate->s.env->alloc, mstate->s.region); +} + +void +mesh_state_delete(struct module_qstate* qstate) +{ + struct mesh_area* mesh; + struct mesh_state_ref* super, ref; + struct mesh_state* mstate; + if(!qstate) + return; + mstate = qstate->mesh_info; + mesh = mstate->s.env->mesh; + mesh_detach_subs(&mstate->s); + if(mstate->list_select == mesh_forever_list) { + mesh->num_forever_states --; + mesh_list_remove(mstate, &mesh->forever_first, + &mesh->forever_last); + } else if(mstate->list_select == mesh_jostle_list) { + mesh_list_remove(mstate, &mesh->jostle_first, + &mesh->jostle_last); + } + if(!mstate->reply_list && !mstate->cb_list + && mstate->super_set.count == 0) { + log_assert(mesh->num_detached_states > 0); + mesh->num_detached_states--; + } + if(mstate->reply_list || mstate->cb_list) { + log_assert(mesh->num_reply_states > 0); + mesh->num_reply_states--; + } + ref.node.key = &ref; + ref.s = mstate; + RBTREE_FOR(super, struct mesh_state_ref*, &mstate->super_set) { + (void)rbtree_delete(&super->s->sub_set, &ref); + } + (void)rbtree_delete(&mesh->run, mstate); + (void)rbtree_delete(&mesh->all, mstate); + mesh_state_cleanup(mstate); +} + +/** helper recursive rbtree find routine */ +static int +find_in_subsub(struct mesh_state* m, struct mesh_state* tofind, size_t *c) +{ + struct mesh_state_ref* r; + if((*c)++ > MESH_MAX_SUBSUB) + return 1; + RBTREE_FOR(r, struct mesh_state_ref*, &m->sub_set) { + if(r->s == tofind || find_in_subsub(r->s, tofind, c)) + return 1; + } + return 0; +} + +/** find cycle for already looked up mesh_state */ +static int +mesh_detect_cycle_found(struct module_qstate* qstate, struct mesh_state* dep_m) +{ + struct mesh_state* cyc_m = qstate->mesh_info; + size_t counter = 0; + if(!dep_m) + return 0; + if(dep_m == cyc_m || find_in_subsub(dep_m, cyc_m, &counter)) { + if(counter > MESH_MAX_SUBSUB) + return 2; + return 1; + } + return 0; +} + +void mesh_detach_subs(struct module_qstate* qstate) +{ + struct mesh_area* mesh = qstate->env->mesh; + struct mesh_state_ref* ref, lookup; +#ifdef UNBOUND_DEBUG + struct rbnode_t* n; +#endif + lookup.node.key = &lookup; + lookup.s = qstate->mesh_info; + RBTREE_FOR(ref, struct mesh_state_ref*, &qstate->mesh_info->sub_set) { +#ifdef UNBOUND_DEBUG + n = +#endif + rbtree_delete(&ref->s->super_set, &lookup); + log_assert(n != NULL); /* must have been present */ + if(!ref->s->reply_list && !ref->s->cb_list + && ref->s->super_set.count == 0) { + mesh->num_detached_states++; + log_assert(mesh->num_detached_states + + mesh->num_reply_states <= mesh->all.count); + } + } + rbtree_init(&qstate->mesh_info->sub_set, &mesh_state_ref_compare); +} + +int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo, + uint16_t qflags, int prime, struct module_qstate** newq) +{ + /* find it, if not, create it */ + struct mesh_area* mesh = qstate->env->mesh; + struct mesh_state* sub = mesh_area_find(mesh, qinfo, qflags, prime); + if(mesh_detect_cycle_found(qstate, sub)) { + verbose(VERB_ALGO, "attach failed, cycle detected"); + return 0; + } + if(!sub) { +#ifdef UNBOUND_DEBUG + struct rbnode_t* n; +#endif + /* create a new one */ + sub = mesh_state_create(qstate->env, qinfo, qflags, prime); + if(!sub) { + log_err("mesh_attach_sub: out of memory"); + return 0; + } +#ifdef UNBOUND_DEBUG + n = +#endif + rbtree_insert(&mesh->all, &sub->node); + log_assert(n != NULL); + /* set detached (it is now) */ + mesh->num_detached_states++; + /* set new query state to run */ +#ifdef UNBOUND_DEBUG + n = +#endif + rbtree_insert(&mesh->run, &sub->run_node); + log_assert(n != NULL); + *newq = &sub->s; + } else + *newq = NULL; + if(!mesh_state_attachment(qstate->mesh_info, sub)) + return 0; + if(!sub->reply_list && !sub->cb_list && sub->super_set.count == 1) { + /* it used to be detached, before this one got added */ + log_assert(mesh->num_detached_states > 0); + mesh->num_detached_states--; + } + /* *newq will be run when inited after the current module stops */ + return 1; +} + +int mesh_state_attachment(struct mesh_state* super, struct mesh_state* sub) +{ +#ifdef UNBOUND_DEBUG + struct rbnode_t* n; +#endif + struct mesh_state_ref* subref; /* points to sub, inserted in super */ + struct mesh_state_ref* superref; /* points to super, inserted in sub */ + if( !(subref = regional_alloc(super->s.region, + sizeof(struct mesh_state_ref))) || + !(superref = regional_alloc(sub->s.region, + sizeof(struct mesh_state_ref))) ) { + log_err("mesh_state_attachment: out of memory"); + return 0; + } + superref->node.key = superref; + superref->s = super; + subref->node.key = subref; + subref->s = sub; +#ifdef UNBOUND_DEBUG + n = +#endif + rbtree_insert(&sub->super_set, &superref->node); + log_assert(n != NULL); +#ifdef UNBOUND_DEBUG + n = +#endif + rbtree_insert(&super->sub_set, &subref->node); + log_assert(n != NULL); + return 1; +} + +/** + * callback results to mesh cb entry + * @param m: mesh state to send it for. + * @param rcode: if not 0, error code. + * @param rep: reply to send (or NULL if rcode is set). + * @param r: callback entry + */ +static void +mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep, + struct mesh_cb* r) +{ + int secure; + char* reason = NULL; + /* bogus messages are not made into servfail, sec_status passed + * to the callback function */ + if(rep && rep->security == sec_status_secure) + secure = 1; + else secure = 0; + if(!rep && rcode == LDNS_RCODE_NOERROR) + rcode = LDNS_RCODE_SERVFAIL; + if(!rcode && rep->security == sec_status_bogus) { + if(!(reason = errinf_to_str(&m->s))) + rcode = LDNS_RCODE_SERVFAIL; + } + /* send the reply */ + if(rcode) { + fptr_ok(fptr_whitelist_mesh_cb(r->cb)); + (*r->cb)(r->cb_arg, rcode, r->buf, sec_status_unchecked, NULL); + } else { + size_t udp_size = r->edns.udp_size; + ldns_buffer_clear(r->buf); + r->edns.edns_version = EDNS_ADVERTISED_VERSION; + 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, + r->qflags, r->buf, 0, 1, + m->s.env->scratch, udp_size, &r->edns, + (int)(r->edns.bits & EDNS_DO), secure)) + { + fptr_ok(fptr_whitelist_mesh_cb(r->cb)); + (*r->cb)(r->cb_arg, LDNS_RCODE_SERVFAIL, r->buf, + sec_status_unchecked, NULL); + } else { + fptr_ok(fptr_whitelist_mesh_cb(r->cb)); + (*r->cb)(r->cb_arg, LDNS_RCODE_NOERROR, r->buf, + rep->security, reason); + } + } + free(reason); + m->s.env->mesh->num_reply_addrs--; +} + +/** + * Send reply to mesh reply entry + * @param m: mesh state to send it for. + * @param rcode: if not 0, error code. + * @param rep: reply to send (or NULL if rcode is set). + * @param r: reply entry + * @param prev: previous reply, already has its answer encoded in buffer. + */ +static void +mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep, + struct mesh_reply* r, struct mesh_reply* prev) +{ + struct timeval end_time; + struct timeval duration; + int secure; + /* examine security status */ + if(m->s.env->need_to_validate && (!(r->qflags&BIT_CD) || + m->s.env->cfg->ignore_cd) && rep && + rep->security <= sec_status_bogus) { + rcode = LDNS_RCODE_SERVFAIL; + if(m->s.env->cfg->stat_extended) + m->s.env->mesh->ans_bogus++; + } + if(rep && rep->security == sec_status_secure) + secure = 1; + else secure = 0; + if(!rep && rcode == LDNS_RCODE_NOERROR) + rcode = LDNS_RCODE_SERVFAIL; + /* send the reply */ + 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) { + /* if the previous reply is identical to this one, fix ID */ + if(prev->query_reply.c->buffer != r->query_reply.c->buffer) + ldns_buffer_copy(r->query_reply.c->buffer, + prev->query_reply.c->buffer); + ldns_buffer_write_at(r->query_reply.c->buffer, 0, + &r->qid, sizeof(uint16_t)); + ldns_buffer_write_at(r->query_reply.c->buffer, 12, + r->qname, m->s.qinfo.qname_len); + comm_point_send_reply(&r->query_reply); + } else if(rcode) { + m->s.qinfo.qname = r->qname; + error_encode(r->query_reply.c->buffer, rcode, &m->s.qinfo, + r->qid, r->qflags, &r->edns); + comm_point_send_reply(&r->query_reply); + } else { + size_t udp_size = r->edns.udp_size; + r->edns.edns_version = EDNS_ADVERTISED_VERSION; + r->edns.udp_size = EDNS_ADVERTISED_SIZE; + 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, + r->qflags, r->query_reply.c->buffer, 0, 1, + m->s.env->scratch, udp_size, &r->edns, + (int)(r->edns.bits & EDNS_DO), secure)) + { + error_encode(r->query_reply.c->buffer, + LDNS_RCODE_SERVFAIL, &m->s.qinfo, r->qid, + r->qflags, &r->edns); + } + comm_point_send_reply(&r->query_reply); + } + /* account */ + m->s.env->mesh->num_reply_addrs--; + end_time = *m->s.env->now_tv; + timeval_subtract(&duration, &end_time, &r->start_time); + verbose(VERB_ALGO, "query took %d.%6.6d sec", + (int)duration.tv_sec, (int)duration.tv_usec); + m->s.env->mesh->replies_sent++; + timeval_add(&m->s.env->mesh->replies_sum_wait, &duration); + timehist_insert(m->s.env->mesh->histogram, &duration); + if(m->s.env->cfg->stat_extended) { + uint16_t rc = FLAGS_GET_RCODE(ldns_buffer_read_u16_at(r-> + query_reply.c->buffer, 2)); + if(secure) m->s.env->mesh->ans_secure++; + m->s.env->mesh->ans_rcode[ rc ] ++; + if(rc == 0 && LDNS_ANCOUNT(ldns_buffer_begin(r-> + query_reply.c->buffer)) == 0) + m->s.env->mesh->ans_nodata++; + } +} + +void mesh_query_done(struct mesh_state* mstate) +{ + struct mesh_reply* r; + struct mesh_reply* prev = NULL; + struct mesh_cb* c; + struct reply_info* rep = (mstate->s.return_msg? + mstate->s.return_msg->rep:NULL); + for(r = mstate->reply_list; r; r = r->next) { + mesh_send_reply(mstate, mstate->s.return_rcode, rep, r, prev); + prev = r; + } + mstate->replies_sent = 1; + for(c = mstate->cb_list; c; c = c->next) { + mesh_do_callback(mstate, mstate->s.return_rcode, rep, c); + } +} + +void mesh_walk_supers(struct mesh_area* mesh, struct mesh_state* mstate) +{ + struct mesh_state_ref* ref; + RBTREE_FOR(ref, struct mesh_state_ref*, &mstate->super_set) + { + /* make super runnable */ + (void)rbtree_insert(&mesh->run, &ref->s->run_node); + /* callback the function to inform super of result */ + fptr_ok(fptr_whitelist_mod_inform_super( + mesh->mods.mod[ref->s->s.curmod]->inform_super)); + (*mesh->mods.mod[ref->s->s.curmod]->inform_super)(&mstate->s, + ref->s->s.curmod, &ref->s->s); + } +} + +struct mesh_state* mesh_area_find(struct mesh_area* mesh, + struct query_info* qinfo, uint16_t qflags, int prime) +{ + struct mesh_state key; + struct mesh_state* result; + + key.node.key = &key; + key.s.is_priming = prime; + key.s.qinfo = *qinfo; + key.s.query_flags = qflags; + + result = (struct mesh_state*)rbtree_search(&mesh->all, &key); + return result; +} + +int mesh_state_add_cb(struct mesh_state* s, struct edns_data* edns, + ldns_buffer* buf, mesh_cb_func_t cb, void* cb_arg, + uint16_t qid, uint16_t qflags) +{ + struct mesh_cb* r = regional_alloc(s->s.region, + sizeof(struct mesh_cb)); + if(!r) + return 0; + r->buf = buf; + log_assert(fptr_whitelist_mesh_cb(cb)); /* early failure ifmissing*/ + r->cb = cb; + r->cb_arg = cb_arg; + r->edns = *edns; + r->qid = qid; + r->qflags = qflags; + r->next = s->cb_list; + s->cb_list = r; + return 1; + +} + +int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns, + struct comm_reply* rep, uint16_t qid, uint16_t qflags, uint8_t* qname) +{ + struct mesh_reply* r = regional_alloc(s->s.region, + sizeof(struct mesh_reply)); + if(!r) + return 0; + r->query_reply = *rep; + r->edns = *edns; + r->qid = qid; + r->qflags = qflags; + r->start_time = *s->s.env->now_tv; + r->next = s->reply_list; + r->qname = regional_alloc_init(s->s.region, qname, + s->s.qinfo.qname_len); + if(!r->qname) + return 0; + s->reply_list = r; + return 1; + +} + +/** + * Continue processing the mesh state at another module. + * Handles module to modules tranfer of control. + * Handles module finished. + * @param mesh: the mesh area. + * @param mstate: currently active mesh state. + * Deleted if finished, calls _done and _supers to + * send replies to clients and inform other mesh states. + * This in turn may create additional runnable mesh states. + * @param s: state at which the current module exited. + * @param ev: the event sent to the module. + * returned is the event to send to the next module. + * @return true if continue processing at the new module. + * false if not continued processing is needed. + */ +static int +mesh_continue(struct mesh_area* mesh, struct mesh_state* mstate, + enum module_ext_state s, enum module_ev* ev) +{ + mstate->num_activated++; + if(mstate->num_activated > MESH_MAX_ACTIVATION) { + /* module is looping. Stop it. */ + log_err("internal error: looping module stopped"); + log_query_info(VERB_QUERY, "pass error for qstate", + &mstate->s.qinfo); + s = module_error; + } + if(s == module_wait_module || s == module_restart_next) { + /* start next module */ + mstate->s.curmod++; + if(mesh->mods.num == mstate->s.curmod) { + log_err("Cannot pass to next module; at last module"); + log_query_info(VERB_QUERY, "pass error for qstate", + &mstate->s.qinfo); + mstate->s.curmod--; + return mesh_continue(mesh, mstate, module_error, ev); + } + if(s == module_restart_next) { + fptr_ok(fptr_whitelist_mod_clear( + mesh->mods.mod[mstate->s.curmod]->clear)); + (*mesh->mods.mod[mstate->s.curmod]->clear) + (&mstate->s, mstate->s.curmod); + mstate->s.minfo[mstate->s.curmod] = NULL; + } + *ev = module_event_pass; + return 1; + } + 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; + } + if(s == module_error || s == module_finished) { + if(mstate->s.curmod == 0) { + mesh_query_done(mstate); + mesh_walk_supers(mesh, mstate); + mesh_state_delete(&mstate->s); + return 0; + } + /* pass along the locus of control */ + mstate->s.curmod --; + *ev = module_event_moddone; + return 1; + } + return 0; +} + +void mesh_run(struct mesh_area* mesh, struct mesh_state* mstate, + enum module_ev ev, struct outbound_entry* e) +{ + enum module_ext_state s; + verbose(VERB_ALGO, "mesh_run: start"); + while(mstate) { + /* run the module */ + fptr_ok(fptr_whitelist_mod_operate( + mesh->mods.mod[mstate->s.curmod]->operate)); + (*mesh->mods.mod[mstate->s.curmod]->operate) + (&mstate->s, ev, mstate->s.curmod, e); + + /* examine results */ + mstate->s.reply = NULL; + regional_free_all(mstate->s.env->scratch); + s = mstate->s.ext_state[mstate->s.curmod]; + verbose(VERB_ALGO, "mesh_run: %s module exit state is %s", + mesh->mods.mod[mstate->s.curmod]->name, strextstate(s)); + e = NULL; + if(mesh_continue(mesh, mstate, s, &ev)) + continue; + + /* run more modules */ + ev = module_event_pass; + if(mesh->run.count > 0) { + /* pop random element off the runnable tree */ + mstate = (struct mesh_state*)mesh->run.root->key; + (void)rbtree_delete(&mesh->run, mstate); + } else mstate = NULL; + } + if(verbosity >= VERB_ALGO) { + mesh_stats(mesh, "mesh_run: end"); + mesh_log_list(mesh); + } +} + +void +mesh_log_list(struct mesh_area* mesh) +{ + char buf[30]; + struct mesh_state* m; + int num = 0; + RBTREE_FOR(m, struct mesh_state*, &mesh->all) { + snprintf(buf, sizeof(buf), "%d%s%s%s%s%s mod%d %s%s", + num++, (m->s.is_priming)?"p":"", /* prime */ + (m->s.query_flags&BIT_RD)?"RD":"", + (m->s.query_flags&BIT_CD)?"CD":"", + (m->super_set.count==0)?"d":"", /* detached */ + (m->sub_set.count!=0)?"c":"", /* children */ + m->s.curmod, (m->reply_list)?"rep":"", /*hasreply*/ + (m->cb_list)?"cb":"" /* callbacks */ + ); + log_query_info(VERB_ALGO, buf, &m->s.qinfo); + } +} + +void +mesh_stats(struct mesh_area* mesh, const char* str) +{ + verbose(VERB_DETAIL, "%s %u recursion states (%u with reply, " + "%u detached), %u waiting replies, %u recursion replies " + "sent, %d replies dropped, %d states jostled out", + str, (unsigned)mesh->all.count, + (unsigned)mesh->num_reply_states, + (unsigned)mesh->num_detached_states, + (unsigned)mesh->num_reply_addrs, + (unsigned)mesh->replies_sent, + (unsigned)mesh->stats_dropped, + (unsigned)mesh->stats_jostled); + if(mesh->replies_sent > 0) { + struct timeval avg; + timeval_divide(&avg, &mesh->replies_sum_wait, + mesh->replies_sent); + log_info("average recursion processing time " + "%d.%6.6d sec", (int)avg.tv_sec, (int)avg.tv_usec); + log_info("histogram of recursion processing times"); + timehist_log(mesh->histogram, "recursions"); + } +} + +void +mesh_stats_clear(struct mesh_area* mesh) +{ + if(!mesh) + return; + mesh->replies_sent = 0; + mesh->replies_sum_wait.tv_sec = 0; + mesh->replies_sum_wait.tv_usec = 0; + mesh->stats_jostled = 0; + mesh->stats_dropped = 0; + timehist_clear(mesh->histogram); + mesh->ans_secure = 0; + mesh->ans_bogus = 0; + memset(&mesh->ans_rcode[0], 0, sizeof(size_t)*16); + mesh->ans_nodata = 0; +} + +size_t +mesh_get_mem(struct mesh_area* mesh) +{ + struct mesh_state* m; + size_t s = sizeof(*mesh) + sizeof(struct timehist) + + sizeof(struct th_buck)*mesh->histogram->num + + sizeof(ldns_buffer) + ldns_buffer_capacity(mesh->qbuf_bak); + RBTREE_FOR(m, struct mesh_state*, &mesh->all) { + /* all, including m itself allocated in qstate region */ + s += regional_get_mem(m->s.region); + } + return s; +} + +int +mesh_detect_cycle(struct module_qstate* qstate, struct query_info* qinfo, + uint16_t flags, int prime) +{ + struct mesh_area* mesh = qstate->env->mesh; + struct mesh_state* dep_m = mesh_area_find(mesh, qinfo, flags, prime); + return mesh_detect_cycle_found(qstate, dep_m); +} + +void mesh_list_insert(struct mesh_state* m, struct mesh_state** fp, + struct mesh_state** lp) +{ + /* insert as last element */ + m->prev = *lp; + m->next = NULL; + if(*lp) + (*lp)->next = m; + else *fp = m; + *lp = m; +} + +void mesh_list_remove(struct mesh_state* m, struct mesh_state** fp, + struct mesh_state** lp) +{ + if(m->next) + m->next->prev = m->prev; + else *lp = m->prev; + if(m->prev) + m->prev->next = m->next; + else *fp = m->next; +} diff --git a/services/mesh.h b/services/mesh.h new file mode 100644 index 00000000000..5f109779a4d --- /dev/null +++ b/services/mesh.h @@ -0,0 +1,571 @@ +/* + * services/mesh.h - deal with mesh of query states and handle events for that. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions to assist in dealing with a mesh of + * query states. This mesh is supposed to be thread-specific. + * It consists of query states (per qname, qtype, qclass) and connections + * between query states and the super and subquery states, and replies to + * send back to clients. + */ + +#ifndef SERVICES_MESH_H +#define SERVICES_MESH_H + +#include "util/rbtree.h" +#include "util/netevent.h" +#include "util/data/msgparse.h" +#include "util/module.h" +#include "services/modstack.h" +struct mesh_state; +struct mesh_reply; +struct mesh_cb; +struct query_info; +struct reply_info; +struct outbound_entry; +struct timehist; + +/** + * Maximum number of mesh state activations. Any more is likely an + * infinite loop in the module. It is then terminated. + */ +#define MESH_MAX_ACTIVATION 3000 + +/** + * Max number of references-to-references-to-references.. search size. + * Any more is treated like 'too large', and the creation of a new + * dependency is failed (so that no loops can be created). + */ +#define MESH_MAX_SUBSUB 1024 + +/** + * Mesh of query states + */ +struct mesh_area { + /** active module stack */ + struct module_stack mods; + /** environment for new states */ + struct module_env* env; + + /** set of runnable queries (mesh_state.run_node) */ + rbtree_t run; + /** rbtree of all current queries (mesh_state.node)*/ + rbtree_t all; + + /** count of the total number of mesh_reply entries */ + size_t num_reply_addrs; + /** count of the number of mesh_states that have mesh_replies + * Because a state can send results to multiple reply addresses, + * this number must be equal or lower than num_reply_addrs. */ + size_t num_reply_states; + /** number of mesh_states that have no mesh_replies, and also + * an empty set of super-states, thus are 'toplevel' or detached + * internal opportunistic queries */ + size_t num_detached_states; + /** number of reply states in the forever list */ + size_t num_forever_states; + + /** max total number of reply states to have */ + size_t max_reply_states; + /** max forever number of reply states to have */ + size_t max_forever_states; + + /** stats, cumulative number of reply states jostled out */ + size_t stats_jostled; + /** stats, cumulative number of incoming client msgs dropped */ + size_t stats_dropped; + /** number of replies sent */ + size_t replies_sent; + /** sum of waiting times for the replies */ + struct timeval replies_sum_wait; + /** histogram of time values */ + struct timehist* histogram; + /** (extended stats) secure replies */ + size_t ans_secure; + /** (extended stats) bogus replies */ + size_t ans_bogus; + /** (extended stats) rcodes in replies */ + size_t ans_rcode[16]; + /** (extended stats) rcode nodata in replies */ + size_t ans_nodata; + + /** backup of query if other operations recurse and need the + * network buffers */ + ldns_buffer* qbuf_bak; + + /** double linked list of the run-to-completion query states. + * These are query states with a reply */ + struct mesh_state* forever_first; + /** last entry in run forever list */ + struct mesh_state* forever_last; + + /** double linked list of the query states that can be jostled out + * by new queries if too old. These are query states with a reply */ + struct mesh_state* jostle_first; + /** last entry in jostle list - this is the entry that is newest */ + struct mesh_state* jostle_last; + /** timeout for jostling. if age is lower, it does not get jostled. */ + struct timeval jostle_max; +}; + +/** + * A mesh query state + * Unique per qname, qtype, qclass (from the qstate). + * And RD / CD flag; in case a client turns it off. + * And priming queries are different from ordinary queries (because of hints). + * + * The entire structure is allocated in a region, this region is the qstate + * region. All parts (rbtree nodes etc) are also allocated in the region. + */ +struct mesh_state { + /** node in mesh_area all tree, key is this struct. Must be first. */ + rbnode_t node; + /** node in mesh_area runnable tree, key is this struct */ + rbnode_t run_node; + /** the query state. Note that the qinfo and query_flags + * may not change. */ + struct module_qstate s; + /** the list of replies to clients for the results */ + struct mesh_reply* reply_list; + /** the list of callbacks for the results */ + struct mesh_cb* cb_list; + /** set of superstates (that want this state's result) + * contains struct mesh_state_ref* */ + rbtree_t super_set; + /** set of substates (that this state needs to continue) + * contains struct mesh_state_ref* */ + rbtree_t sub_set; + /** number of activations for the mesh state */ + size_t num_activated; + + /** previous in linked list for reply states */ + struct mesh_state* prev; + /** next in linked list for reply states */ + struct mesh_state* next; + /** if this state is in the forever list, jostle list, or neither */ + enum mesh_list_select { mesh_no_list, mesh_forever_list, + mesh_jostle_list } list_select; + + /** true if replies have been sent out (at end for alignment) */ + uint8_t replies_sent; +}; + +/** + * Rbtree reference to a mesh_state. + * Used in super_set and sub_set. + */ +struct mesh_state_ref { + /** node in rbtree for set, key is this structure */ + rbnode_t node; + /** the mesh state */ + struct mesh_state* s; +}; + +/** + * Reply to a client + */ +struct mesh_reply { + /** next in reply list */ + struct mesh_reply* next; + /** the query reply destination, packet buffer and where to send. */ + struct comm_reply query_reply; + /** edns data from query */ + struct edns_data edns; + /** the time when request was entered */ + struct timeval start_time; + /** id of query, in network byteorder. */ + uint16_t qid; + /** flags of query, for reply flags */ + uint16_t qflags; + /** qname from this query. len same as mesh qinfo. */ + uint8_t* qname; +}; + +/** + * Mesh result callback func. + * called as func(cb_arg, rcode, buffer_with_reply, security, why_bogus); + */ +typedef void (*mesh_cb_func_t)(void*, int, ldns_buffer*, enum sec_status, + char*); + +/** + * Callback to result routine + */ +struct mesh_cb { + /** next in list */ + struct mesh_cb* next; + /** edns data from query */ + struct edns_data edns; + /** id of query, in network byteorder. */ + uint16_t qid; + /** flags of query, for reply flags */ + uint16_t qflags; + /** buffer for reply */ + ldns_buffer* buf; + + /** callback routine for results. if rcode != 0 buf has message. + * called as cb(cb_arg, rcode, buf, sec_state); + */ + mesh_cb_func_t cb; + /** user arg for callback */ + void* cb_arg; +}; + +/* ------------------- Functions for worker -------------------- */ + +/** + * Allocate mesh, to empty. + * @param stack: module stack to activate, copied (as readonly reference). + * @param env: environment for new queries. + * @return mesh: the new mesh or NULL on error. + */ +struct mesh_area* mesh_create(struct module_stack* stack, + struct module_env* env); + +/** + * Delete mesh, and all query states and replies in it. + * @param mesh: the mesh to delete. + */ +void mesh_delete(struct mesh_area* mesh); + +/** + * New query incoming from clients. Create new query state if needed, and + * add mesh_reply to it. Returns error to client on malloc failures. + * Will run the mesh area queries to process if a new query state is created. + * + * @param mesh: the mesh. + * @param qinfo: query from client. + * @param qflags: flags from client query. + * @param edns: edns data from client query. + * @param rep: where to reply to. + * @param qid: query id to reply with. + */ +void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo, + uint16_t qflags, struct edns_data* edns, struct comm_reply* rep, + uint16_t qid); + +/** + * New query with callback. Create new query state if needed, and + * add mesh_cb to it. + * Will run the mesh area queries to process if a new query state is created. + * + * @param mesh: the mesh. + * @param qinfo: query from client. + * @param qflags: flags from client query. + * @param edns: edns data from client query. + * @param buf: buffer for reply contents. + * @param qid: query id to reply with. + * @param cb: callback function. + * @param cb_arg: callback user arg. + * @return 0 on error. + */ +int mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo, + uint16_t qflags, struct edns_data* edns, ldns_buffer* buf, + uint16_t qid, mesh_cb_func_t cb, void* cb_arg); + +/** + * New prefetch message. Create new query state if needed. + * Will run the mesh area queries to process if a new query state is created. + * + * @param mesh: the mesh. + * @param qinfo: query from client. + * @param qflags: flags from client query. + * @param leeway: TTL leeway what to expire earlier for this update. + */ +void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo, + uint16_t qflags, uint32_t leeway); + +/** + * Handle new event from the wire. A serviced query has returned. + * The query state will be made runnable, and the mesh_area will process + * query states until processing is complete. + * + * @param mesh: the query mesh. + * @param e: outbound entry, with query state to run and reply pointer. + * @param reply: the comm point reply info. + * @param what: NETEVENT_* error code (if not 0, what is wrong, TIMEOUT). + */ +void mesh_report_reply(struct mesh_area* mesh, struct outbound_entry* e, + struct comm_reply* reply, int what); + +/* ------------------- Functions for module environment --------------- */ + +/** + * Detach-subqueries. + * Remove all sub-query references from this query state. + * Keeps super-references of those sub-queries correct. + * Updates stat items in mesh_area structure. + * @param qstate: used to find mesh state. + */ +void mesh_detach_subs(struct module_qstate* qstate); + +/** + * Attach subquery. + * Creates it if it does not exist already. + * Keeps sub and super references correct. + * Performs a cycle detection - for double check - and fails if there is one. + * Also fails if the sub-sub-references become too large. + * Updates stat items in mesh_area structure. + * Pass if it is priming query or not. + * return: + * o if error (malloc) happened. + * o need to initialise the new state (module init; it is a new state). + * so that the next run of the query with this module is successful. + * o no init needed, attachment successful. + * + * @param qstate: the state to find mesh state, and that wants to receive + * the results from the new subquery. + * @param qinfo: what to query for (copied). + * @param qflags: what flags to use (RD / CD flag or not). + * @param prime: if it is a (stub) priming query. + * @param newq: If the new subquery needs initialisation, it is returned, + * otherwise NULL is returned. + * @return: false on error, true if success (and init may be needed). + */ +int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo, + uint16_t qflags, int prime, struct module_qstate** newq); + +/** + * Query state is done, send messages to reply entries. + * Encode messages using reply entry values and the querystate (with original + * qinfo), using given reply_info. + * Pass errcode != 0 if an error reply is needed. + * If no reply entries, nothing is done. + * Must be called before a module can module_finished or return module_error. + * The module must handle the super query states itself as well. + * + * @param mstate: mesh state that is done. return_rcode and return_msg + * are used for replies. + * return_rcode: if not 0 (NOERROR) an error is sent back (and + * return_msg is ignored). + * return_msg: reply to encode and send back to clients. + */ +void mesh_query_done(struct mesh_state* mstate); + +/** + * Call inform_super for the super query states that are interested in the + * results from this query state. These can then be changed for error + * or results. + * Called when a module is module_finished or returns module_error. + * The super query states become runnable with event module_event_pass, + * it calls the current module for the super with the inform_super event. + * + * @param mesh: mesh area to add newly runnable modules to. + * @param mstate: the state that has results, used to find mesh state. + */ +void mesh_walk_supers(struct mesh_area* mesh, struct mesh_state* mstate); + +/** + * Delete mesh state, cleanup and also rbtrees and so on. + * Will detach from all super/subnodes. + * @param qstate: to remove. + */ +void mesh_state_delete(struct module_qstate* qstate); + +/* ------------------- Functions for mesh -------------------- */ + +/** + * Create and initialize a new mesh state and its query state + * Does not put the mesh state into rbtrees and so on. + * @param env: module environment to set. + * @param qinfo: query info that the mesh is for. + * @param qflags: flags for query (RD / CD flag). + * @param prime: if true, it is a priming query, set is_priming on mesh state. + * @return: new mesh state or NULL on allocation error. + */ +struct mesh_state* mesh_state_create(struct module_env* env, + struct query_info* qinfo, uint16_t qflags, int prime); + +/** + * Cleanup a mesh state and its query state. Does not do rbtree or + * reference cleanup. + * @param mstate: mesh state to cleanup. Its pointer may no longer be used + * afterwards. Cleanup rbtrees before calling this function. + */ +void mesh_state_cleanup(struct mesh_state* mstate); + +/** + * Delete all mesh states from the mesh. + * @param mesh: the mesh area to clear + */ +void mesh_delete_all(struct mesh_area* mesh); + +/** + * Find a mesh state in the mesh area. Pass relevant flags. + * + * @param mesh: the mesh area to look in. + * @param qinfo: what query + * @param qflags: if RD / CD bit is set or not. + * @param prime: if it is a priming query. + * @return: mesh state or NULL if not found. + */ +struct mesh_state* mesh_area_find(struct mesh_area* mesh, + struct query_info* qinfo, uint16_t qflags, int prime); + +/** + * Setup attachment super/sub relation between super and sub mesh state. + * The relation must not be present when calling the function. + * Does not update stat items in mesh_area. + * @param super: super state. + * @param sub: sub state. + * @return: 0 on alloc error. + */ +int mesh_state_attachment(struct mesh_state* super, struct mesh_state* sub); + +/** + * Create new reply structure and attach it to a mesh state. + * Does not update stat items in mesh area. + * @param s: the mesh state. + * @param edns: edns data for reply (bufsize). + * @param rep: comm point reply info. + * @param qid: ID of reply. + * @param qflags: original query flags. + * @param qname: original query name. + * @return: 0 on alloc error. + */ +int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns, + struct comm_reply* rep, uint16_t qid, uint16_t qflags, uint8_t* qname); + +/** + * Create new callback structure and attach it to a mesh state. + * Does not update stat items in mesh area. + * @param s: the mesh state. + * @param edns: edns data for reply (bufsize). + * @param buf: buffer for reply + * @param cb: callback to call with results. + * @param cb_arg: callback user arg. + * @param qid: ID of reply. + * @param qflags: original query flags. + * @return: 0 on alloc error. + */ +int mesh_state_add_cb(struct mesh_state* s, struct edns_data* edns, + ldns_buffer* buf, mesh_cb_func_t cb, void* cb_arg, uint16_t qid, + uint16_t qflags); + +/** + * Run the mesh. Run all runnable mesh states. Which can create new + * runnable mesh states. Until completion. Automatically called by + * mesh_report_reply and mesh_new_client as needed. + * @param mesh: mesh area. + * @param mstate: first mesh state to run. + * @param ev: event the mstate. Others get event_pass. + * @param e: if a reply, its outbound entry. + */ +void mesh_run(struct mesh_area* mesh, struct mesh_state* mstate, + enum module_ev ev, struct outbound_entry* e); + +/** + * Print some stats about the mesh to the log. + * @param mesh: the mesh to print it for. + * @param str: descriptive string to go with it. + */ +void mesh_stats(struct mesh_area* mesh, const char* str); + +/** + * Clear the stats that the mesh keeps (number of queries serviced) + * @param mesh: the mesh + */ +void mesh_stats_clear(struct mesh_area* mesh); + +/** + * Print all the states in the mesh to the log. + * @param mesh: the mesh to print all states of. + */ +void mesh_log_list(struct mesh_area* mesh); + +/** + * Calculate memory size in use by mesh and all queries inside it. + * @param mesh: the mesh to examine. + * @return size in bytes. + */ +size_t mesh_get_mem(struct mesh_area* mesh); + +/** + * Find cycle; see if the given mesh is in the targets sub, or sub-sub, ... + * trees. + * If the sub-sub structure is too large, it returns 'a cycle'=2. + * @param qstate: given mesh querystate. + * @param qinfo: query info for dependency. + * @param flags: query flags of dependency. + * @param prime: if dependency is a priming query or not. + * @return true if the name,type,class exists and the given qstate mesh exists + * as a dependency of that name. Thus if qstate becomes dependent on + * name,type,class then a cycle is created, this is return value 1. + * Too large to search is value 2 (also true). + */ +int mesh_detect_cycle(struct module_qstate* qstate, struct query_info* qinfo, + uint16_t flags, int prime); + +/** compare two mesh_states */ +int mesh_state_compare(const void* ap, const void* bp); + +/** compare two mesh references */ +int mesh_state_ref_compare(const void* ap, const void* bp); + +/** + * Make space for another recursion state for a reply in the mesh + * @param mesh: mesh area + * @param qbuf: query buffer to save if recursion is invoked to make space. + * This buffer is necessary, because the following sequence in calls + * can result in an overwrite of the incoming query: + * delete_other_mesh_query - iter_clean - serviced_delete - waiting + * udp query is sent - on error callback - callback sends SERVFAIL reply + * over the same network channel, and shared UDP buffer is overwritten. + * You can pass NULL if there is no buffer that must be backed up. + * @return false if no space is available. + */ +int mesh_make_new_space(struct mesh_area* mesh, ldns_buffer* qbuf); + +/** + * Insert mesh state into a double linked list. Inserted at end. + * @param m: mesh state. + * @param fp: pointer to the first-elem-pointer of the list. + * @param lp: pointer to the last-elem-pointer of the list. + */ +void mesh_list_insert(struct mesh_state* m, struct mesh_state** fp, + struct mesh_state** lp); + +/** + * Remove mesh state from a double linked list. Remove from any position. + * @param m: mesh state. + * @param fp: pointer to the first-elem-pointer of the list. + * @param lp: pointer to the last-elem-pointer of the list. + */ +void mesh_list_remove(struct mesh_state* m, struct mesh_state** fp, + struct mesh_state** lp); + +#endif /* SERVICES_MESH_H */ diff --git a/services/modstack.c b/services/modstack.c new file mode 100644 index 00000000000..7395598c31c --- /dev/null +++ b/services/modstack.c @@ -0,0 +1,212 @@ +/* + * services/modstack.c - stack of modules + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions to help maintain a stack of modules. + */ +#include "config.h" +#include +#include "services/modstack.h" +#include "util/module.h" +#include "util/fptr_wlist.h" +#include "iterator/iterator.h" +#include "validator/validator.h" + +#ifdef WITH_PYTHONMODULE +#include "pythonmod/pythonmod.h" +#endif + +/** count number of modules (words) in the string */ +static int +count_modules(const char* s) +{ + int num = 0; + if(!s) + return 0; + while(*s) { + /* skip whitespace */ + while(*s && isspace((int)*s)) + s++; + if(*s && !isspace((int)*s)) { + /* skip identifier */ + num++; + while(*s && !isspace((int)*s)) + s++; + } + } + return num; +} + +void +modstack_init(struct module_stack* stack) +{ + stack->num = 0; + stack->mod = NULL; +} + +int +modstack_config(struct module_stack* stack, const char* module_conf) +{ + int i; + verbose(VERB_QUERY, "module config: \"%s\"", module_conf); + stack->num = count_modules(module_conf); + if(stack->num == 0) { + log_err("error: no modules specified"); + return 0; + } + if(stack->num > MAX_MODULE) { + log_err("error: too many modules (%d max %d)", + stack->num, MAX_MODULE); + return 0; + } + stack->mod = (struct module_func_block**)calloc((size_t) + stack->num, sizeof(struct module_func_block*)); + if(!stack->mod) { + log_err("out of memory"); + return 0; + } + for(i=0; inum; i++) { + stack->mod[i] = module_factory(&module_conf); + if(!stack->mod[i]) { + log_err("Unknown value for next module: '%s'", + module_conf); + return 0; + } + } + return 1; +} + +/** The list of module names */ +const char** +module_list_avail(void) +{ + /* these are the modules available */ + static const char* names[] = { +#ifdef WITH_PYTHONMODULE + "python", +#endif + "validator", + "iterator", + NULL}; + return names; +} + +/** func block get function type */ +typedef struct module_func_block* (*fbgetfunctype)(void); + +/** The list of module func blocks */ +static fbgetfunctype* +module_funcs_avail(void) +{ + static struct module_func_block* (*fb[])(void) = { +#ifdef WITH_PYTHONMODULE + &pythonmod_get_funcblock, +#endif + &val_get_funcblock, + &iter_get_funcblock, + NULL}; + return fb; +} + +struct +module_func_block* module_factory(const char** str) +{ + int i = 0; + const char* s = *str; + const char** names = module_list_avail(); + fbgetfunctype* fb = module_funcs_avail(); + while(*s && isspace((int)*s)) + s++; + while(names[i]) { + if(strncmp(names[i], s, strlen(names[i])) == 0) { + s += strlen(names[i]); + *str = s; + return (*fb[i])(); + } + i++; + } + return NULL; +} + +int +modstack_setup(struct module_stack* stack, const char* module_conf, + struct module_env* env) +{ + int i; + if(stack->num != 0) + modstack_desetup(stack, env); + /* fixed setup of the modules */ + if(!modstack_config(stack, module_conf)) { + return 0; + } + env->need_to_validate = 0; /* set by module init below */ + for(i=0; inum; i++) { + verbose(VERB_OPS, "init module %d: %s", + i, stack->mod[i]->name); + fptr_ok(fptr_whitelist_mod_init(stack->mod[i]->init)); + if(!(*stack->mod[i]->init)(env, i)) { + log_err("module init for module %s failed", + stack->mod[i]->name); + return 0; + } + } + return 1; +} + +void +modstack_desetup(struct module_stack* stack, struct module_env* env) +{ + int i; + for(i=0; inum; i++) { + fptr_ok(fptr_whitelist_mod_deinit(stack->mod[i]->deinit)); + (*stack->mod[i]->deinit)(env, i); + } + stack->num = 0; + free(stack->mod); + stack->mod = NULL; +} + +int +modstack_find(struct module_stack* stack, const char* name) +{ + int i; + for(i=0; inum; i++) { + if(strcmp(stack->mod[i]->name, name) == 0) + return i; + } + return -1; +} diff --git a/services/modstack.h b/services/modstack.h new file mode 100644 index 00000000000..869b593ad26 --- /dev/null +++ b/services/modstack.h @@ -0,0 +1,113 @@ +/* + * services/modstack.h - stack of modules + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions to help maintain a stack of modules. + */ + +#ifndef SERVICES_MODSTACK_H +#define SERVICES_MODSTACK_H +struct module_func_block; +struct module_env; + +/** + * Stack of modules. + */ +struct module_stack { + /** the number of modules */ + int num; + /** the module callbacks, array of num_modules length (ref only) */ + struct module_func_block** mod; +}; + +/** + * Init a stack of modules + * @param stack: initialised as empty. + */ +void modstack_init(struct module_stack* stack); + +/** + * Read config file module settings and set up the modfunc block + * @param stack: the stack of modules (empty before call). + * @param module_conf: string what modules to insert. + * @return false on error + */ +int modstack_config(struct module_stack* stack, const char* module_conf); + +/** + * Get funcblock for module name + * @param str: string with module name. Advanced to next value on success. + * The string is assumed whitespace separated list of module names. + * @return funcblock or NULL on error. + */ +struct module_func_block* module_factory(const char** str); + +/** + * Get list of modules available. + * @return list of modules available. Static strings, ends with NULL. + */ +const char** module_list_avail(void); + +/** + * Setup modules. Assigns ids and calls module_init. + * @param stack: if not empty beforehand, it will be desetup()ed. + * It is then modstack_configged(). + * @param module_conf: string what modules to insert. + * @param env: module environment which is inited by the modules. + * environment should have a superalloc, cfg, + * env.need_to_validate is set by the modules. + * @return on false a module init failed. + */ +int modstack_setup(struct module_stack* stack, const char* module_conf, + struct module_env* env); + +/** + * Desetup the modules, deinit, delete. + * @param stack: made empty. + * @param env: module env for module deinit() calls. + */ +void modstack_desetup(struct module_stack* stack, struct module_env* env); + +/** + * Find index of module by name. + * @param stack: to look in + * @param name: the name to look for + * @return -1 on failure, otherwise index number. + */ +int modstack_find(struct module_stack* stack, const char* name); + +#endif /* SERVICES_MODSTACK_H */ diff --git a/services/outbound_list.c b/services/outbound_list.c new file mode 100644 index 00000000000..be491490411 --- /dev/null +++ b/services/outbound_list.c @@ -0,0 +1,89 @@ +/* + * services/outbound_list.c - keep list of outbound serviced queries. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions to help a module keep track of the + * queries it has outstanding to authoritative servers. + */ +#include "config.h" +#include +#include "services/outbound_list.h" +#include "services/outside_network.h" + +void +outbound_list_init(struct outbound_list* list) +{ + list->first = NULL; +} + +void +outbound_list_clear(struct outbound_list* list) +{ + struct outbound_entry *p, *np; + p = list->first; + while(p) { + np = p->next; + outnet_serviced_query_stop(p->qsent, p); + /* in region, no free needed */ + p = np; + } + outbound_list_init(list); +} + +void +outbound_list_insert(struct outbound_list* list, struct outbound_entry* e) +{ + if(list->first) + list->first->prev = e; + e->next = list->first; + e->prev = NULL; + list->first = e; +} + +void +outbound_list_remove(struct outbound_list* list, struct outbound_entry* e) +{ + if(!e) + return; + outnet_serviced_query_stop(e->qsent, e); + if(e->next) + e->next->prev = e->prev; + if(e->prev) + e->prev->next = e->next; + else list->first = e->next; + /* in region, no free needed */ +} diff --git a/services/outbound_list.h b/services/outbound_list.h new file mode 100644 index 00000000000..5631910f6f8 --- /dev/null +++ b/services/outbound_list.h @@ -0,0 +1,105 @@ +/* + * services/outbound_list.h - keep list of outbound serviced queries. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions to help a module keep track of the + * queries it has outstanding to authoritative servers. + */ +#ifndef SERVICES_OUTBOUND_LIST_H +#define SERVICES_OUTBOUND_LIST_H +struct outbound_entry; +struct serviced_query; +struct module_qstate; + +/** + * The outbound list. This structure is part of the module specific query + * state. + */ +struct outbound_list { + /** The linked list of outbound query entries. */ + struct outbound_entry* first; +}; + +/** + * Outbound list entry. A serviced query sent by a module processing the + * query from the qstate. Double linked list to aid removal. + */ +struct outbound_entry { + /** next in list */ + struct outbound_entry* next; + /** prev in list */ + struct outbound_entry* prev; + /** The query that was sent out */ + struct serviced_query* qsent; + /** the module query state that sent it */ + struct module_qstate* qstate; +}; + +/** + * Init the user allocated outbound list structure + * @param list: the list structure. + */ +void outbound_list_init(struct outbound_list* list); + +/** + * Clear the user owner outbound list structure. + * Deletes serviced queries. + * @param list: the list structure. It is cleared, but the list struct itself + * is callers responsability to delete. + */ +void outbound_list_clear(struct outbound_list* list); + +/** + * Insert new entry into the list. Caller must allocate the entry with malloc. + * qstate and qsent are set by caller. + * @param list: the list to add to. + * @param e: entry to add, it is only half initialised at call start, fully + * initialised at call end. + */ +void outbound_list_insert(struct outbound_list* list, + struct outbound_entry* e); + +/** + * Remove an entry from the list, and deletes it. + * Deletes serviced query in the entry. + * @param list: the list to remove from. + * @param e: the entry to remove. + */ +void outbound_list_remove(struct outbound_list* list, + struct outbound_entry* e); + +#endif /* SERVICES_OUTBOUND_LIST_H */ diff --git a/services/outside_network.c b/services/outside_network.c new file mode 100644 index 00000000000..24d65db3993 --- /dev/null +++ b/services/outside_network.c @@ -0,0 +1,1994 @@ +/* + * services/outside_network.c - implement sending of queries and wait answer. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file has functions to send queries to authoritative servers and + * wait for the pending answer events. + */ +#include "config.h" +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#include +#include +#include "services/outside_network.h" +#include "services/listen_dnsport.h" +#include "services/cache/infra.h" +#include "util/data/msgparse.h" +#include "util/data/msgreply.h" +#include "util/data/msgencode.h" +#include "util/data/dname.h" +#include "util/netevent.h" +#include "util/log.h" +#include "util/net_help.h" +#include "util/random.h" +#include "util/fptr_wlist.h" +#include + +#ifdef HAVE_NETDB_H +#include +#endif +#include + +/** number of times to retry making a random ID that is unique. */ +#define MAX_ID_RETRY 1000 +/** number of times to retry finding interface, port that can be opened. */ +#define MAX_PORT_RETRY 10000 +/** number of retries on outgoing UDP queries */ +#define OUTBOUND_UDP_RETRY 1 + +/** initiate TCP transaction for serviced query */ +static void serviced_tcp_initiate(struct outside_network* outnet, + struct serviced_query* sq, ldns_buffer* buff); +/** with a fd available, randomize and send UDP */ +static int randomize_and_send_udp(struct outside_network* outnet, + struct pending* pend, ldns_buffer* packet, int timeout); + +int +pending_cmp(const void* key1, const void* key2) +{ + struct pending *p1 = (struct pending*)key1; + struct pending *p2 = (struct pending*)key2; + if(p1->id < p2->id) + return -1; + if(p1->id > p2->id) + return 1; + log_assert(p1->id == p2->id); + return sockaddr_cmp(&p1->addr, p1->addrlen, &p2->addr, p2->addrlen); +} + +int +serviced_cmp(const void* key1, const void* key2) +{ + struct serviced_query* q1 = (struct serviced_query*)key1; + struct serviced_query* q2 = (struct serviced_query*)key2; + int r; + if(q1->qbuflen < q2->qbuflen) + return -1; + if(q1->qbuflen > q2->qbuflen) + return 1; + log_assert(q1->qbuflen == q2->qbuflen); + log_assert(q1->qbuflen >= 15 /* 10 header, root, type, class */); + /* alternate casing of qname is still the same query */ + if((r = memcmp(q1->qbuf, q2->qbuf, 10)) != 0) + return r; + if((r = memcmp(q1->qbuf+q1->qbuflen-4, q2->qbuf+q2->qbuflen-4, 4)) != 0) + return r; + if(q1->dnssec != q2->dnssec) { + if(q1->dnssec < q2->dnssec) + return -1; + return 1; + } + if((r = query_dname_compare(q1->qbuf+10, q2->qbuf+10)) != 0) + return r; + return sockaddr_cmp(&q1->addr, q1->addrlen, &q2->addr, q2->addrlen); +} + +/** delete waiting_tcp entry. Does not unlink from waiting list. + * @param w: to delete. + */ +static void +waiting_tcp_delete(struct waiting_tcp* w) +{ + if(!w) return; + if(w->timer) + comm_timer_delete(w->timer); + free(w); +} + +/** + * Pick random outgoing-interface of that family, and bind it. + * port set to 0 so OS picks a port number for us. + * if it is the ANY address, do not bind. + * @param w: tcp structure with destination address. + * @param s: socket fd. + * @return false on error, socket closed. + */ +static int +pick_outgoing_tcp(struct waiting_tcp* w, int s) +{ + struct port_if* pi = NULL; + int num; +#ifdef INET6 + if(addr_is_ip6(&w->addr, w->addrlen)) + num = w->outnet->num_ip6; + else +#endif + num = w->outnet->num_ip4; + if(num == 0) { + log_err("no TCP outgoing interfaces of family"); + log_addr(VERB_OPS, "for addr", &w->addr, w->addrlen); +#ifndef USE_WINSOCK + close(s); +#else + closesocket(s); +#endif + return 0; + } +#ifdef INET6 + if(addr_is_ip6(&w->addr, w->addrlen)) + pi = &w->outnet->ip6_ifs[ub_random_max(w->outnet->rnd, num)]; + else +#endif + pi = &w->outnet->ip4_ifs[ub_random_max(w->outnet->rnd, num)]; + log_assert(pi); + if(addr_is_any(&pi->addr, pi->addrlen)) { + /* binding to the ANY interface is for listening sockets */ + return 1; + } + /* set port to 0 */ + if(addr_is_ip6(&pi->addr, pi->addrlen)) + ((struct sockaddr_in6*)&pi->addr)->sin6_port = 0; + else ((struct sockaddr_in*)&pi->addr)->sin_port = 0; + if(bind(s, (struct sockaddr*)&pi->addr, pi->addrlen) != 0) { +#ifndef USE_WINSOCK + log_err("outgoing tcp: bind: %s", strerror(errno)); + close(s); +#else + log_err("outgoing tcp: bind: %s", + wsa_strerror(WSAGetLastError())); + closesocket(s); +#endif + return 0; + } + log_addr(VERB_ALGO, "tcp bound to src", &pi->addr, pi->addrlen); + return 1; +} + +/** use next free buffer to service a tcp query */ +static int +outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len) +{ + struct pending_tcp* pend = w->outnet->tcp_free; + int s; + log_assert(pend); + log_assert(pkt); + log_assert(w->addrlen > 0); + /* open socket */ +#ifdef INET6 + if(addr_is_ip6(&w->addr, w->addrlen)) + s = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP); + else +#endif + s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if(s == -1) { +#ifndef USE_WINSOCK + log_err("outgoing tcp: socket: %s", strerror(errno)); +#else + log_err("outgoing tcp: socket: %s", + wsa_strerror(WSAGetLastError())); +#endif + log_addr(0, "failed address", &w->addr, w->addrlen); + return 0; + } + if(!pick_outgoing_tcp(w, s)) + return 0; + + fd_set_nonblock(s); + if(connect(s, (struct sockaddr*)&w->addr, w->addrlen) == -1) { +#ifndef USE_WINSOCK +#ifdef EINPROGRESS + if(errno != EINPROGRESS) { +#else + if(1) { +#endif + if(tcp_connect_errno_needs_log( + (struct sockaddr*)&w->addr, w->addrlen)) + log_err("outgoing tcp: connect: %s", + strerror(errno)); + close(s); +#else /* USE_WINSOCK */ + if(WSAGetLastError() != WSAEINPROGRESS && + WSAGetLastError() != WSAEWOULDBLOCK) { + closesocket(s); +#endif + log_addr(0, "failed address", &w->addr, w->addrlen); + return 0; + } + } + if(w->outnet->sslctx && w->ssl_upstream) { + pend->c->ssl = outgoing_ssl_fd(w->outnet->sslctx, s); + if(!pend->c->ssl) { + pend->c->fd = s; + comm_point_close(pend->c); + return 0; + } +#ifdef USE_WINSOCK + comm_point_tcp_win_bio_cb(pend->c, pend->c->ssl); +#endif + pend->c->ssl_shake_state = comm_ssl_shake_write; + } + w->pkt = NULL; + w->next_waiting = (void*)pend; + pend->id = LDNS_ID_WIRE(pkt); + w->outnet->tcp_free = pend->next_free; + pend->next_free = NULL; + pend->query = w; + pend->c->repinfo.addrlen = w->addrlen; + memcpy(&pend->c->repinfo.addr, &w->addr, w->addrlen); + ldns_buffer_clear(pend->c->buffer); + ldns_buffer_write(pend->c->buffer, pkt, pkt_len); + ldns_buffer_flip(pend->c->buffer); + pend->c->tcp_is_reading = 0; + pend->c->tcp_byte_count = 0; + comm_point_start_listening(pend->c, s, -1); + return 1; +} + +/** see if buffers can be used to service TCP queries */ +static void +use_free_buffer(struct outside_network* outnet) +{ + struct waiting_tcp* w; + while(outnet->tcp_free && outnet->tcp_wait_first + && !outnet->want_to_quit) { + w = outnet->tcp_wait_first; + outnet->tcp_wait_first = w->next_waiting; + if(outnet->tcp_wait_last == w) + outnet->tcp_wait_last = NULL; + if(!outnet_tcp_take_into_use(w, w->pkt, w->pkt_len)) { + comm_point_callback_t* cb = w->cb; + void* cb_arg = w->cb_arg; + waiting_tcp_delete(w); + fptr_ok(fptr_whitelist_pending_tcp(cb)); + (void)(*cb)(NULL, cb_arg, NETEVENT_CLOSED, NULL); + } + } +} + +/** decomission a tcp buffer, closes commpoint and frees waiting_tcp entry */ +static void +decomission_pending_tcp(struct outside_network* outnet, + struct pending_tcp* pend) +{ + if(pend->c->ssl) { + SSL_shutdown(pend->c->ssl); + SSL_free(pend->c->ssl); + pend->c->ssl = NULL; + } + comm_point_close(pend->c); + pend->next_free = outnet->tcp_free; + outnet->tcp_free = pend; + waiting_tcp_delete(pend->query); + pend->query = NULL; + use_free_buffer(outnet); +} + +int +outnet_tcp_cb(struct comm_point* c, void* arg, int error, + struct comm_reply *reply_info) +{ + struct pending_tcp* pend = (struct pending_tcp*)arg; + struct outside_network* outnet = pend->query->outnet; + verbose(VERB_ALGO, "outnettcp cb"); + if(error != NETEVENT_NOERROR) { + verbose(VERB_QUERY, "outnettcp got tcp error %d", error); + /* pass error below and exit */ + } else { + /* check ID */ + if(ldns_buffer_limit(c->buffer) < sizeof(uint16_t) || + LDNS_ID_WIRE(ldns_buffer_begin(c->buffer))!=pend->id) { + log_addr(VERB_QUERY, + "outnettcp: bad ID in reply, from:", + &pend->query->addr, pend->query->addrlen); + error = NETEVENT_CLOSED; + } + } + fptr_ok(fptr_whitelist_pending_tcp(pend->query->cb)); + (void)(*pend->query->cb)(c, pend->query->cb_arg, error, reply_info); + decomission_pending_tcp(outnet, pend); + return 0; +} + +/** lower use count on pc, see if it can be closed */ +static void +portcomm_loweruse(struct outside_network* outnet, struct port_comm* pc) +{ + struct port_if* pif; + pc->num_outstanding--; + if(pc->num_outstanding > 0) { + return; + } + /* close it and replace in unused list */ + verbose(VERB_ALGO, "close of port %d", pc->number); + comm_point_close(pc->cp); + pif = pc->pif; + log_assert(pif->inuse > 0); + pif->avail_ports[pif->avail_total - pif->inuse] = pc->number; + pif->inuse--; + pif->out[pc->index] = pif->out[pif->inuse]; + pif->out[pc->index]->index = pc->index; + pc->next = outnet->unused_fds; + outnet->unused_fds = pc; +} + +/** try to send waiting UDP queries */ +static void +outnet_send_wait_udp(struct outside_network* outnet) +{ + struct pending* pend; + /* process waiting queries */ + while(outnet->udp_wait_first && outnet->unused_fds + && !outnet->want_to_quit) { + pend = outnet->udp_wait_first; + outnet->udp_wait_first = pend->next_waiting; + if(!pend->next_waiting) outnet->udp_wait_last = NULL; + ldns_buffer_clear(outnet->udp_buff); + ldns_buffer_write(outnet->udp_buff, pend->pkt, pend->pkt_len); + ldns_buffer_flip(outnet->udp_buff); + free(pend->pkt); /* freeing now makes get_mem correct */ + pend->pkt = NULL; + pend->pkt_len = 0; + if(!randomize_and_send_udp(outnet, pend, outnet->udp_buff, + pend->timeout)) { + /* callback error on pending */ + fptr_ok(fptr_whitelist_pending_udp(pend->cb)); + (void)(*pend->cb)(outnet->unused_fds->cp, pend->cb_arg, + NETEVENT_CLOSED, NULL); + pending_delete(outnet, pend); + } + } +} + +int +outnet_udp_cb(struct comm_point* c, void* arg, int error, + struct comm_reply *reply_info) +{ + struct outside_network* outnet = (struct outside_network*)arg; + struct pending key; + struct pending* p; + verbose(VERB_ALGO, "answer cb"); + + if(error != NETEVENT_NOERROR) { + verbose(VERB_QUERY, "outnetudp got udp error %d", error); + return 0; + } + if(ldns_buffer_limit(c->buffer) < LDNS_HEADER_SIZE) { + verbose(VERB_QUERY, "outnetudp udp too short"); + return 0; + } + log_assert(reply_info); + + /* setup lookup key */ + key.id = (unsigned)LDNS_ID_WIRE(ldns_buffer_begin(c->buffer)); + memcpy(&key.addr, &reply_info->addr, reply_info->addrlen); + key.addrlen = reply_info->addrlen; + verbose(VERB_ALGO, "Incoming reply id = %4.4x", key.id); + log_addr(VERB_ALGO, "Incoming reply addr =", + &reply_info->addr, reply_info->addrlen); + + /* find it, see if this thing is a valid query response */ + verbose(VERB_ALGO, "lookup size is %d entries", (int)outnet->pending->count); + p = (struct pending*)rbtree_search(outnet->pending, &key); + if(!p) { + verbose(VERB_QUERY, "received unwanted or unsolicited udp reply dropped."); + log_buf(VERB_ALGO, "dropped message", c->buffer); + outnet->unwanted_replies++; + if(outnet->unwanted_threshold && ++outnet->unwanted_total + >= outnet->unwanted_threshold) { + log_warn("unwanted reply total reached threshold (%u)" + " you may be under attack." + " defensive action: clearing the cache", + (unsigned)outnet->unwanted_threshold); + fptr_ok(fptr_whitelist_alloc_cleanup( + outnet->unwanted_action)); + (*outnet->unwanted_action)(outnet->unwanted_param); + outnet->unwanted_total = 0; + } + return 0; + } + + verbose(VERB_ALGO, "received udp reply."); + log_buf(VERB_ALGO, "udp message", c->buffer); + if(p->pc->cp != c) { + verbose(VERB_QUERY, "received reply id,addr on wrong port. " + "dropped."); + outnet->unwanted_replies++; + if(outnet->unwanted_threshold && ++outnet->unwanted_total + >= outnet->unwanted_threshold) { + log_warn("unwanted reply total reached threshold (%u)" + " you may be under attack." + " defensive action: clearing the cache", + (unsigned)outnet->unwanted_threshold); + fptr_ok(fptr_whitelist_alloc_cleanup( + outnet->unwanted_action)); + (*outnet->unwanted_action)(outnet->unwanted_param); + outnet->unwanted_total = 0; + } + return 0; + } + comm_timer_disable(p->timer); + verbose(VERB_ALGO, "outnet handle udp reply"); + /* delete from tree first in case callback creates a retry */ + (void)rbtree_delete(outnet->pending, p->node.key); + fptr_ok(fptr_whitelist_pending_udp(p->cb)); + (void)(*p->cb)(p->pc->cp, p->cb_arg, NETEVENT_NOERROR, reply_info); + portcomm_loweruse(outnet, p->pc); + pending_delete(NULL, p); + outnet_send_wait_udp(outnet); + return 0; +} + +/** calculate number of ip4 and ip6 interfaces*/ +static void +calc_num46(char** ifs, int num_ifs, int do_ip4, int do_ip6, + int* num_ip4, int* num_ip6) +{ + int i; + *num_ip4 = 0; + *num_ip6 = 0; + if(num_ifs <= 0) { + if(do_ip4) + *num_ip4 = 1; + if(do_ip6) + *num_ip6 = 1; + return; + } + for(i=0; ioutnet; + /* it timed out */ + verbose(VERB_ALGO, "timeout udp"); + fptr_ok(fptr_whitelist_pending_udp(p->cb)); + (void)(*p->cb)(p->pc->cp, p->cb_arg, NETEVENT_TIMEOUT, NULL); + portcomm_loweruse(outnet, p->pc); + pending_delete(outnet, p); + outnet_send_wait_udp(outnet); +} + +/** create pending_tcp buffers */ +static int +create_pending_tcp(struct outside_network* outnet, size_t bufsize) +{ + size_t i; + if(outnet->num_tcp == 0) + return 1; /* no tcp needed, nothing to do */ + if(!(outnet->tcp_conns = (struct pending_tcp **)calloc( + outnet->num_tcp, sizeof(struct pending_tcp*)))) + return 0; + for(i=0; inum_tcp; i++) { + if(!(outnet->tcp_conns[i] = (struct pending_tcp*)calloc(1, + sizeof(struct pending_tcp)))) + return 0; + outnet->tcp_conns[i]->next_free = outnet->tcp_free; + outnet->tcp_free = outnet->tcp_conns[i]; + outnet->tcp_conns[i]->c = comm_point_create_tcp_out( + outnet->base, bufsize, outnet_tcp_cb, + outnet->tcp_conns[i]); + if(!outnet->tcp_conns[i]->c) + return 0; + } + return 1; +} + +/** setup an outgoing interface, ready address */ +static int setup_if(struct port_if* pif, const char* addrstr, + int* avail, int numavail, size_t numfd) +{ + pif->avail_total = numavail; + 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)) + return 0; + pif->maxout = (int)numfd; + pif->inuse = 0; + pif->out = (struct port_comm**)calloc(numfd, + sizeof(struct port_comm*)); + if(!pif->out) + return 0; + return 1; +} + +struct outside_network* +outside_network_create(struct comm_base *base, size_t bufsize, + size_t num_ports, char** ifs, int num_ifs, int do_ip4, + int do_ip6, size_t num_tcp, struct infra_cache* infra, + struct ub_randstate* rnd, int use_caps_for_id, int* availports, + int numavailports, size_t unwanted_threshold, + void (*unwanted_action)(void*), void* unwanted_param, int do_udp, + void* sslctx) +{ + struct outside_network* outnet = (struct outside_network*) + calloc(1, sizeof(struct outside_network)); + size_t k; + if(!outnet) { + log_err("malloc failed"); + return NULL; + } + comm_base_timept(base, &outnet->now_secs, &outnet->now_tv); + outnet->base = base; + outnet->num_tcp = num_tcp; + outnet->infra = infra; + outnet->rnd = rnd; + outnet->sslctx = sslctx; + outnet->svcd_overhead = 0; + outnet->want_to_quit = 0; + outnet->unwanted_threshold = unwanted_threshold; + outnet->unwanted_action = unwanted_action; + outnet->unwanted_param = unwanted_param; + outnet->use_caps_for_id = use_caps_for_id; + outnet->do_udp = do_udp; + if(numavailports == 0) { + log_err("no outgoing ports available"); + outside_network_delete(outnet); + return NULL; + } +#ifndef INET6 + do_ip6 = 0; +#endif + calc_num46(ifs, num_ifs, do_ip4, do_ip6, + &outnet->num_ip4, &outnet->num_ip6); + if(outnet->num_ip4 != 0) { + if(!(outnet->ip4_ifs = (struct port_if*)calloc( + (size_t)outnet->num_ip4, sizeof(struct port_if)))) { + log_err("malloc failed"); + outside_network_delete(outnet); + return NULL; + } + } + if(outnet->num_ip6 != 0) { + if(!(outnet->ip6_ifs = (struct port_if*)calloc( + (size_t)outnet->num_ip6, sizeof(struct port_if)))) { + log_err("malloc failed"); + outside_network_delete(outnet); + return NULL; + } + } + if( !(outnet->udp_buff = ldns_buffer_new(bufsize)) || + !(outnet->pending = rbtree_create(pending_cmp)) || + !(outnet->serviced = rbtree_create(serviced_cmp)) || + !create_pending_tcp(outnet, bufsize)) { + log_err("malloc failed"); + outside_network_delete(outnet); + return NULL; + } + + /* allocate commpoints */ + for(k=0; kcp = comm_point_create_udp(outnet->base, -1, + outnet->udp_buff, outnet_udp_cb, outnet); + if(!pc->cp) { + log_err("malloc failed"); + free(pc); + outside_network_delete(outnet); + return NULL; + } + pc->next = outnet->unused_fds; + outnet->unused_fds = pc; + } + + /* allocate interfaces */ + if(num_ifs == 0) { + if(do_ip4 && !setup_if(&outnet->ip4_ifs[0], "0.0.0.0", + availports, numavailports, num_ports)) { + log_err("malloc failed"); + outside_network_delete(outnet); + return NULL; + } + if(do_ip6 && !setup_if(&outnet->ip6_ifs[0], "::", + availports, numavailports, num_ports)) { + log_err("malloc failed"); + outside_network_delete(outnet); + return NULL; + } + } else { + size_t done_4 = 0, done_6 = 0; + int i; + for(i=0; iip6_ifs[done_6], ifs[i], + availports, numavailports, num_ports)){ + log_err("malloc failed"); + outside_network_delete(outnet); + return NULL; + } + done_6++; + } + if(!str_is_ip6(ifs[i]) && do_ip4) { + if(!setup_if(&outnet->ip4_ifs[done_4], ifs[i], + availports, numavailports, num_ports)){ + log_err("malloc failed"); + outside_network_delete(outnet); + return NULL; + } + done_4++; + } + } + } + return outnet; +} + +/** helper pending delete */ +static void +pending_node_del(rbnode_t* node, void* arg) +{ + struct pending* pend = (struct pending*)node; + struct outside_network* outnet = (struct outside_network*)arg; + pending_delete(outnet, pend); +} + +/** helper serviced delete */ +static void +serviced_node_del(rbnode_t* node, void* ATTR_UNUSED(arg)) +{ + struct serviced_query* sq = (struct serviced_query*)node; + struct service_callback* p = sq->cblist, *np; + free(sq->qbuf); + free(sq->zone); + while(p) { + np = p->next; + free(p); + p = np; + } + free(sq); +} + +void +outside_network_quit_prepare(struct outside_network* outnet) +{ + if(!outnet) + return; + /* prevent queued items from being sent */ + outnet->want_to_quit = 1; +} + +void +outside_network_delete(struct outside_network* outnet) +{ + if(!outnet) + return; + outnet->want_to_quit = 1; + /* check every element, since we can be called on malloc error */ + if(outnet->pending) { + /* free pending elements, but do no unlink from tree. */ + traverse_postorder(outnet->pending, pending_node_del, NULL); + free(outnet->pending); + } + if(outnet->serviced) { + traverse_postorder(outnet->serviced, serviced_node_del, NULL); + free(outnet->serviced); + } + if(outnet->udp_buff) + ldns_buffer_free(outnet->udp_buff); + if(outnet->unused_fds) { + struct port_comm* p = outnet->unused_fds, *np; + while(p) { + np = p->next; + comm_point_delete(p->cp); + free(p); + p = np; + } + outnet->unused_fds = NULL; + } + if(outnet->ip4_ifs) { + int i, k; + for(i=0; inum_ip4; i++) { + for(k=0; kip4_ifs[i].inuse; k++) { + struct port_comm* pc = outnet->ip4_ifs[i]. + out[k]; + comm_point_delete(pc->cp); + free(pc); + } + free(outnet->ip4_ifs[i].avail_ports); + free(outnet->ip4_ifs[i].out); + } + free(outnet->ip4_ifs); + } + if(outnet->ip6_ifs) { + int i, k; + for(i=0; inum_ip6; i++) { + for(k=0; kip6_ifs[i].inuse; k++) { + struct port_comm* pc = outnet->ip6_ifs[i]. + out[k]; + comm_point_delete(pc->cp); + free(pc); + } + free(outnet->ip6_ifs[i].avail_ports); + free(outnet->ip6_ifs[i].out); + } + free(outnet->ip6_ifs); + } + if(outnet->tcp_conns) { + size_t i; + for(i=0; inum_tcp; i++) + if(outnet->tcp_conns[i]) { + comm_point_delete(outnet->tcp_conns[i]->c); + waiting_tcp_delete(outnet->tcp_conns[i]->query); + free(outnet->tcp_conns[i]); + } + free(outnet->tcp_conns); + } + if(outnet->tcp_wait_first) { + struct waiting_tcp* p = outnet->tcp_wait_first, *np; + while(p) { + np = p->next_waiting; + waiting_tcp_delete(p); + p = np; + } + } + if(outnet->udp_wait_first) { + struct pending* p = outnet->udp_wait_first, *np; + while(p) { + np = p->next_waiting; + pending_delete(NULL, p); + p = np; + } + } + free(outnet); +} + +void +pending_delete(struct outside_network* outnet, struct pending* p) +{ + if(!p) + return; + if(outnet && outnet->udp_wait_first && + (p->next_waiting || p == outnet->udp_wait_last) ) { + /* delete from waiting list, if it is in the waiting list */ + struct pending* prev = NULL, *x = outnet->udp_wait_first; + while(x && x != p) { + prev = x; + x = x->next_waiting; + } + if(x) { + log_assert(x == p); + if(prev) + prev->next_waiting = p->next_waiting; + else outnet->udp_wait_first = p->next_waiting; + if(outnet->udp_wait_last == p) + outnet->udp_wait_last = prev; + } + } + if(outnet) { + (void)rbtree_delete(outnet->pending, p->node.key); + } + if(p->timer) + comm_timer_delete(p->timer); + free(p->pkt); + free(p); +} + +/** + * Try to open a UDP socket for outgoing communication. + * Sets sockets options as needed. + * @param addr: socket address. + * @param addrlen: length of address. + * @param port: port override for addr. + * @param inuse: if -1 is returned, this bool means the port was in use. + * @return fd or -1 + */ +static int +udp_sockport(struct sockaddr_storage* addr, socklen_t addrlen, int port, + int* inuse) +{ + 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); + fd = create_udp_sock(AF_INET6, SOCK_DGRAM, + (struct sockaddr*)addr, addrlen, 1, inuse, &noproto, + 0, 0); + } 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); + } + return fd; +} + +/** Select random ID */ +static int +select_id(struct outside_network* outnet, struct pending* pend, + ldns_buffer* packet) +{ + int id_tries = 0; + pend->id = ((unsigned)ub_random(outnet->rnd)>>8) & 0xffff; + LDNS_ID_SET(ldns_buffer_begin(packet), pend->id); + + /* insert in tree */ + pend->node.key = pend; + while(!rbtree_insert(outnet->pending, &pend->node)) { + /* change ID to avoid collision */ + pend->id = ((unsigned)ub_random(outnet->rnd)>>8) & 0xffff; + LDNS_ID_SET(ldns_buffer_begin(packet), pend->id); + id_tries++; + if(id_tries == MAX_ID_RETRY) { + pend->id=99999; /* non existant ID */ + log_err("failed to generate unique ID, drop msg"); + return 0; + } + } + verbose(VERB_ALGO, "inserted new pending reply id=%4.4x", pend->id); + return 1; +} + +/** Select random interface and port */ +static int +select_ifport(struct outside_network* outnet, struct pending* pend, + int num_if, struct port_if* ifs) +{ + int my_if, my_port, fd, portno, inuse, tries=0; + struct port_if* pif; + /* randomly select interface and port */ + if(num_if == 0) { + verbose(VERB_QUERY, "Need to send query but have no " + "outgoing interfaces of that family"); + return 0; + } + log_assert(outnet->unused_fds); + tries = 0; + while(1) { + my_if = ub_random_max(outnet->rnd, num_if); + pif = &ifs[my_if]; + my_port = ub_random_max(outnet->rnd, pif->avail_total); + if(my_port < pif->inuse) { + /* port already open */ + pend->pc = pif->out[my_port]; + verbose(VERB_ALGO, "using UDP if=%d port=%d", + my_if, pend->pc->number); + break; + } + /* 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); + if(fd == -1 && !inuse) { + /* nonrecoverable error making socket */ + return 0; + } + if(fd != -1) { + verbose(VERB_ALGO, "opened UDP if=%d port=%d", + my_if, portno); + /* grab fd */ + pend->pc = outnet->unused_fds; + outnet->unused_fds = pend->pc->next; + + /* setup portcomm */ + pend->pc->next = NULL; + pend->pc->number = portno; + pend->pc->pif = pif; + pend->pc->index = pif->inuse; + pend->pc->num_outstanding = 0; + comm_point_start_listening(pend->pc->cp, fd, -1); + + /* grab port in interface */ + pif->out[pif->inuse] = pend->pc; + pif->avail_ports[my_port - pif->inuse] = + pif->avail_ports[pif->avail_total-pif->inuse-1]; + pif->inuse++; + break; + } + /* failed, already in use */ + verbose(VERB_QUERY, "port %d in use, trying another", portno); + tries++; + if(tries == MAX_PORT_RETRY) { + log_err("failed to find an open port, drop msg"); + return 0; + } + } + log_assert(pend->pc); + pend->pc->num_outstanding++; + + return 1; +} + +static int +randomize_and_send_udp(struct outside_network* outnet, struct pending* pend, + ldns_buffer* packet, int timeout) +{ + struct timeval tv; + + /* select id */ + if(!select_id(outnet, pend, packet)) { + return 0; + } + + /* select src_if, port */ + if(addr_is_ip6(&pend->addr, pend->addrlen)) { + if(!select_ifport(outnet, pend, + outnet->num_ip6, outnet->ip6_ifs)) + return 0; + } else { + if(!select_ifport(outnet, pend, + outnet->num_ip4, outnet->ip4_ifs)) + return 0; + } + log_assert(pend->pc && pend->pc->cp); + + /* send it over the commlink */ + if(!comm_point_send_udp_msg(pend->pc->cp, packet, + (struct sockaddr*)&pend->addr, pend->addrlen)) { + portcomm_loweruse(outnet, pend->pc); + return 0; + } + + /* system calls to set timeout after sending UDP to make roundtrip + smaller. */ +#ifndef S_SPLINT_S + tv.tv_sec = timeout/1000; + tv.tv_usec = (timeout%1000)*1000; +#endif + comm_timer_set(pend->timer, &tv); + return 1; +} + +struct pending* +pending_udp_query(struct outside_network* outnet, ldns_buffer* packet, + struct sockaddr_storage* addr, socklen_t addrlen, int timeout, + comm_point_callback_t* cb, void* cb_arg) +{ + struct pending* pend = (struct pending*)calloc(1, sizeof(*pend)); + if(!pend) return NULL; + pend->outnet = outnet; + pend->addrlen = addrlen; + memmove(&pend->addr, addr, addrlen); + pend->cb = cb; + pend->cb_arg = cb_arg; + pend->node.key = pend; + pend->timer = comm_timer_create(outnet->base, pending_udp_timer_cb, + pend); + if(!pend->timer) { + free(pend); + return NULL; + } + + if(outnet->unused_fds == NULL) { + /* no unused fd, cannot create a new port (randomly) */ + verbose(VERB_ALGO, "no fds available, udp query waiting"); + pend->timeout = timeout; + pend->pkt_len = ldns_buffer_limit(packet); + pend->pkt = (uint8_t*)memdup(ldns_buffer_begin(packet), + pend->pkt_len); + if(!pend->pkt) { + comm_timer_delete(pend->timer); + free(pend); + return NULL; + } + /* put at end of waiting list */ + if(outnet->udp_wait_last) + outnet->udp_wait_last->next_waiting = pend; + else + outnet->udp_wait_first = pend; + outnet->udp_wait_last = pend; + return pend; + } + if(!randomize_and_send_udp(outnet, pend, packet, timeout)) { + pending_delete(outnet, pend); + return NULL; + } + return pend; +} + +void +outnet_tcptimer(void* arg) +{ + struct waiting_tcp* w = (struct waiting_tcp*)arg; + struct outside_network* outnet = w->outnet; + comm_point_callback_t* cb; + void* cb_arg; + if(w->pkt) { + /* it is on the waiting list */ + struct waiting_tcp* p=outnet->tcp_wait_first, *prev=NULL; + while(p) { + if(p == w) { + if(prev) prev->next_waiting = w->next_waiting; + else outnet->tcp_wait_first=w->next_waiting; + outnet->tcp_wait_last = prev; + break; + } + prev = p; + p=p->next_waiting; + } + } else { + /* it was in use */ + struct pending_tcp* pend=(struct pending_tcp*)w->next_waiting; + comm_point_close(pend->c); + pend->query = NULL; + pend->next_free = outnet->tcp_free; + outnet->tcp_free = pend; + } + cb = w->cb; + cb_arg = w->cb_arg; + waiting_tcp_delete(w); + fptr_ok(fptr_whitelist_pending_tcp(cb)); + (void)(*cb)(NULL, cb_arg, NETEVENT_TIMEOUT, NULL); + use_free_buffer(outnet); +} + +struct waiting_tcp* +pending_tcp_query(struct outside_network* outnet, ldns_buffer* packet, + struct sockaddr_storage* addr, socklen_t addrlen, int timeout, + comm_point_callback_t* callback, void* callback_arg, int ssl_upstream) +{ + struct pending_tcp* pend = outnet->tcp_free; + struct waiting_tcp* w; + struct timeval tv; + uint16_t id; + /* if no buffer is free allocate space to store query */ + w = (struct waiting_tcp*)malloc(sizeof(struct waiting_tcp) + + (pend?0:ldns_buffer_limit(packet))); + if(!w) { + return NULL; + } + if(!(w->timer = comm_timer_create(outnet->base, outnet_tcptimer, w))) { + free(w); + return NULL; + } + w->pkt = NULL; + w->pkt_len = 0; + id = ((unsigned)ub_random(outnet->rnd)>>8) & 0xffff; + LDNS_ID_SET(ldns_buffer_begin(packet), id); + memcpy(&w->addr, addr, addrlen); + w->addrlen = addrlen; + w->outnet = outnet; + w->cb = callback; + w->cb_arg = callback_arg; + w->ssl_upstream = ssl_upstream; +#ifndef S_SPLINT_S + tv.tv_sec = timeout; + tv.tv_usec = 0; +#endif + comm_timer_set(w->timer, &tv); + if(pend) { + /* we have a buffer available right now */ + if(!outnet_tcp_take_into_use(w, ldns_buffer_begin(packet), + ldns_buffer_limit(packet))) { + waiting_tcp_delete(w); + return NULL; + } + } else { + /* queue up */ + w->pkt = (uint8_t*)w + sizeof(struct waiting_tcp); + w->pkt_len = ldns_buffer_limit(packet); + memmove(w->pkt, ldns_buffer_begin(packet), w->pkt_len); + w->next_waiting = NULL; + if(outnet->tcp_wait_last) + outnet->tcp_wait_last->next_waiting = w; + else outnet->tcp_wait_first = w; + outnet->tcp_wait_last = w; + } + return w; +} + +/** create query for serviced queries */ +static void +serviced_gen_query(ldns_buffer* buff, uint8_t* qname, size_t qnamelen, + uint16_t qtype, uint16_t qclass, uint16_t flags) +{ + ldns_buffer_clear(buff); + /* skip id */ + ldns_buffer_write_u16(buff, flags); + ldns_buffer_write_u16(buff, 1); /* qdcount */ + ldns_buffer_write_u16(buff, 0); /* ancount */ + ldns_buffer_write_u16(buff, 0); /* nscount */ + ldns_buffer_write_u16(buff, 0); /* arcount */ + ldns_buffer_write(buff, qname, qnamelen); + ldns_buffer_write_u16(buff, qtype); + ldns_buffer_write_u16(buff, qclass); + ldns_buffer_flip(buff); +} + +/** lookup serviced query in serviced query rbtree */ +static struct serviced_query* +lookup_serviced(struct outside_network* outnet, ldns_buffer* buff, int dnssec, + struct sockaddr_storage* addr, socklen_t addrlen) +{ + struct serviced_query key; + key.node.key = &key; + key.qbuf = ldns_buffer_begin(buff); + key.qbuflen = ldns_buffer_limit(buff); + key.dnssec = dnssec; + memcpy(&key.addr, addr, addrlen); + key.addrlen = addrlen; + key.outnet = outnet; + return (struct serviced_query*)rbtree_search(outnet->serviced, &key); +} + +/** Create new serviced entry */ +static struct serviced_query* +serviced_create(struct outside_network* outnet, ldns_buffer* buff, int dnssec, + int want_dnssec, int tcp_upstream, int ssl_upstream, + struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, + size_t zonelen, int qtype) +{ + struct serviced_query* sq = (struct serviced_query*)malloc(sizeof(*sq)); +#ifdef UNBOUND_DEBUG + rbnode_t* ins; +#endif + if(!sq) + return NULL; + sq->node.key = sq; + sq->qbuf = memdup(ldns_buffer_begin(buff), ldns_buffer_limit(buff)); + if(!sq->qbuf) { + free(sq); + return NULL; + } + sq->qbuflen = ldns_buffer_limit(buff); + sq->zone = memdup(zone, zonelen); + if(!sq->zone) { + free(sq->qbuf); + free(sq); + return NULL; + } + sq->zonelen = zonelen; + sq->qtype = qtype; + sq->dnssec = dnssec; + sq->want_dnssec = want_dnssec; + sq->tcp_upstream = tcp_upstream; + sq->ssl_upstream = ssl_upstream; + memcpy(&sq->addr, addr, addrlen); + sq->addrlen = addrlen; + sq->outnet = outnet; + sq->cblist = NULL; + sq->pending = NULL; + sq->status = serviced_initial; + sq->retry = 0; + sq->to_be_deleted = 0; +#ifdef UNBOUND_DEBUG + ins = +#endif + rbtree_insert(outnet->serviced, &sq->node); + log_assert(ins != NULL); /* must not be already present */ + return sq; +} + +/** remove waiting tcp from the outnet waiting list */ +static void +waiting_list_remove(struct outside_network* outnet, struct waiting_tcp* w) +{ + struct waiting_tcp* p = outnet->tcp_wait_first, *prev = NULL; + while(p) { + if(p == w) { + /* remove w */ + if(prev) + prev->next_waiting = w->next_waiting; + else outnet->tcp_wait_first = w->next_waiting; + if(outnet->tcp_wait_last == w) + outnet->tcp_wait_last = prev; + return; + } + prev = p; + p = p->next_waiting; + } +} + +/** cleanup serviced query entry */ +static void +serviced_delete(struct serviced_query* sq) +{ + if(sq->pending) { + /* clear up the pending query */ + if(sq->status == serviced_query_UDP_EDNS || + sq->status == serviced_query_UDP || + sq->status == serviced_query_PROBE_EDNS || + sq->status == serviced_query_UDP_EDNS_FRAG || + sq->status == serviced_query_UDP_EDNS_fallback) { + struct pending* p = (struct pending*)sq->pending; + if(p->pc) + portcomm_loweruse(sq->outnet, p->pc); + pending_delete(sq->outnet, p); + /* this call can cause reentrant calls back into the + * mesh */ + outnet_send_wait_udp(sq->outnet); + } else { + struct waiting_tcp* p = (struct waiting_tcp*) + sq->pending; + if(p->pkt == NULL) { + decomission_pending_tcp(sq->outnet, + (struct pending_tcp*)p->next_waiting); + } else { + waiting_list_remove(sq->outnet, p); + waiting_tcp_delete(p); + } + } + } + /* does not delete from tree, caller has to do that */ + serviced_node_del(&sq->node, NULL); +} + +/** perturb a dname capitalization randomly */ +static void +serviced_perturb_qname(struct ub_randstate* rnd, uint8_t* qbuf, size_t len) +{ + uint8_t lablen; + uint8_t* d = qbuf + 10; + long int random = 0; + int bits = 0; + log_assert(len >= 10 + 5 /* offset qname, root, qtype, qclass */); + lablen = *d++; + while(lablen) { + while(lablen--) { + /* only perturb A-Z, a-z */ + if(isalpha((int)*d)) { + /* get a random bit */ + if(bits == 0) { + random = ub_random(rnd); + bits = 30; + } + if(random & 0x1) { + *d = (uint8_t)toupper((int)*d); + } else { + *d = (uint8_t)tolower((int)*d); + } + random >>= 1; + bits--; + } + d++; + } + lablen = *d++; + } + if(verbosity >= VERB_ALGO) { + char buf[LDNS_MAX_DOMAINLEN+1]; + dname_str(qbuf+10, buf); + verbose(VERB_ALGO, "qname perturbed to %s", buf); + } +} + +/** put serviced query into a buffer */ +static void +serviced_encode(struct serviced_query* sq, ldns_buffer* buff, int with_edns) +{ + /* if we are using 0x20 bits for ID randomness, perturb them */ + if(sq->outnet->use_caps_for_id) { + serviced_perturb_qname(sq->outnet->rnd, sq->qbuf, sq->qbuflen); + } + /* generate query */ + ldns_buffer_clear(buff); + ldns_buffer_write_u16(buff, 0); /* id placeholder */ + ldns_buffer_write(buff, sq->qbuf, sq->qbuflen); + ldns_buffer_flip(buff); + if(with_edns) { + /* add edns section */ + struct edns_data edns; + edns.edns_present = 1; + edns.ext_rcode = 0; + edns.edns_version = EDNS_ADVERTISED_VERSION; + if(sq->status == serviced_query_UDP_EDNS_FRAG) { + if(addr_is_ip6(&sq->addr, sq->addrlen)) { + if(EDNS_FRAG_SIZE_IP6 < EDNS_ADVERTISED_SIZE) + edns.udp_size = EDNS_FRAG_SIZE_IP6; + else edns.udp_size = EDNS_ADVERTISED_SIZE; + } else { + if(EDNS_FRAG_SIZE_IP4 < EDNS_ADVERTISED_SIZE) + edns.udp_size = EDNS_FRAG_SIZE_IP4; + else edns.udp_size = EDNS_ADVERTISED_SIZE; + } + } else { + edns.udp_size = EDNS_ADVERTISED_SIZE; + } + edns.bits = 0; + if(sq->dnssec & EDNS_DO) + edns.bits = EDNS_DO; + if(sq->dnssec & BIT_CD) + LDNS_CD_SET(ldns_buffer_begin(buff)); + attach_edns_record(buff, &edns); + } +} + +/** + * Perform serviced query UDP sending operation. + * Sends UDP with EDNS, unless infra host marked non EDNS. + * @param sq: query to send. + * @param buff: buffer scratch space. + * @return 0 on error. + */ +static int +serviced_udp_send(struct serviced_query* sq, ldns_buffer* buff) +{ + int rtt, vs; + uint8_t edns_lame_known; + uint32_t now = *sq->outnet->now_secs; + + if(!infra_host(sq->outnet->infra, &sq->addr, sq->addrlen, sq->zone, + sq->zonelen, now, &vs, &edns_lame_known, &rtt)) + return 0; + sq->last_rtt = rtt; + verbose(VERB_ALGO, "EDNS lookup known=%d vs=%d", edns_lame_known, vs); + if(sq->status == serviced_initial) { + if(edns_lame_known == 0 && rtt > 5000 && rtt < 10001) { + /* perform EDNS lame probe - check if server is + * EDNS lame (EDNS queries to it are dropped) */ + verbose(VERB_ALGO, "serviced query: send probe to see " + " if use of EDNS causes timeouts"); + /* even 700 msec may be too small */ + rtt = 1000; + sq->status = serviced_query_PROBE_EDNS; + } else if(vs != -1) { + sq->status = serviced_query_UDP_EDNS; + } else { + sq->status = serviced_query_UDP; + } + } + serviced_encode(sq, buff, (sq->status == serviced_query_UDP_EDNS) || + (sq->status == serviced_query_UDP_EDNS_FRAG)); + sq->last_sent_time = *sq->outnet->now_tv; + sq->edns_lame_known = (int)edns_lame_known; + verbose(VERB_ALGO, "serviced query UDP timeout=%d msec", rtt); + sq->pending = pending_udp_query(sq->outnet, buff, &sq->addr, + sq->addrlen, rtt, serviced_udp_callback, sq); + if(!sq->pending) + return 0; + return 1; +} + +/** check that perturbed qname is identical */ +static int +serviced_check_qname(ldns_buffer* pkt, uint8_t* qbuf, size_t qbuflen) +{ + uint8_t* d1 = ldns_buffer_at(pkt, 12); + uint8_t* d2 = qbuf+10; + uint8_t len1, len2; + int count = 0; + log_assert(qbuflen >= 15 /* 10 header, root, type, class */); + len1 = *d1++; + len2 = *d2++; + if(ldns_buffer_limit(pkt) < 12+1+4) /* packet too small for qname */ + return 0; + while(len1 != 0 || len2 != 0) { + if(LABEL_IS_PTR(len1)) { + d1 = ldns_buffer_at(pkt, PTR_OFFSET(len1, *d1)); + if(d1 >= ldns_buffer_at(pkt, ldns_buffer_limit(pkt))) + return 0; + len1 = *d1++; + if(count++ > MAX_COMPRESS_PTRS) + return 0; + continue; + } + if(d2 > qbuf+qbuflen) + return 0; + if(len1 != len2) + return 0; + if(len1 > LDNS_MAX_LABELLEN) + return 0; + log_assert(len1 <= LDNS_MAX_LABELLEN); + log_assert(len2 <= LDNS_MAX_LABELLEN); + log_assert(len1 == len2 && len1 != 0); + /* compare the labels - bitwise identical */ + if(memcmp(d1, d2, len1) != 0) + return 0; + d1 += len1; + d2 += len2; + len1 = *d1++; + len2 = *d2++; + } + return 1; +} + +/** call the callbacks for a serviced query */ +static void +serviced_callbacks(struct serviced_query* sq, int error, struct comm_point* c, + struct comm_reply* rep) +{ + struct service_callback* p = sq->cblist, *n; + int dobackup = (sq->cblist && sq->cblist->next); /* >1 cb*/ + uint8_t *backup_p = NULL; + size_t backlen = 0; +#ifdef UNBOUND_DEBUG + rbnode_t* rem = +#endif + /* remove from tree, and schedule for deletion, so that callbacks + * can safely deregister themselves and even create new serviced + * queries that are identical to this one. */ + rbtree_delete(sq->outnet->serviced, sq); + log_assert(rem); /* should have been present */ + sq->to_be_deleted = 1; + verbose(VERB_ALGO, "svcd callbacks start"); + if(sq->outnet->use_caps_for_id && error == NETEVENT_NOERROR && c) { + /* noerror and nxdomain must have a qname in reply */ + if(ldns_buffer_read_u16_at(c->buffer, 4) == 0 && + (LDNS_RCODE_WIRE(ldns_buffer_begin(c->buffer)) + == LDNS_RCODE_NOERROR || + LDNS_RCODE_WIRE(ldns_buffer_begin(c->buffer)) + == LDNS_RCODE_NXDOMAIN)) { + verbose(VERB_DETAIL, "no qname in reply to check 0x20ID"); + log_addr(VERB_DETAIL, "from server", + &sq->addr, sq->addrlen); + log_buf(VERB_DETAIL, "for packet", c->buffer); + error = NETEVENT_CLOSED; + c = NULL; + } else if(ldns_buffer_read_u16_at(c->buffer, 4) > 0 && + !serviced_check_qname(c->buffer, sq->qbuf, + sq->qbuflen)) { + verbose(VERB_DETAIL, "wrong 0x20-ID in reply qname"); + log_addr(VERB_DETAIL, "from server", + &sq->addr, sq->addrlen); + log_buf(VERB_DETAIL, "for packet", c->buffer); + error = NETEVENT_CAPSFAIL; + /* and cleanup too */ + pkt_dname_tolower(c->buffer, + ldns_buffer_at(c->buffer, 12)); + } else { + verbose(VERB_ALGO, "good 0x20-ID in reply qname"); + /* cleanup caps, prettier cache contents. */ + pkt_dname_tolower(c->buffer, + ldns_buffer_at(c->buffer, 12)); + } + } + if(dobackup && c) { + /* make a backup of the query, since the querystate processing + * may send outgoing queries that overwrite the buffer. + * use secondary buffer to store the query. + * This is a data copy, but faster than packet to server */ + backlen = ldns_buffer_limit(c->buffer); + backup_p = memdup(ldns_buffer_begin(c->buffer), backlen); + if(!backup_p) { + log_err("malloc failure in serviced query callbacks"); + error = NETEVENT_CLOSED; + c = NULL; + } + sq->outnet->svcd_overhead = backlen; + } + while(p) { + n = p->next; + if(dobackup && c) { + ldns_buffer_clear(c->buffer); + ldns_buffer_write(c->buffer, backup_p, backlen); + ldns_buffer_flip(c->buffer); + } + fptr_ok(fptr_whitelist_serviced_query(p->cb)); + (void)(*p->cb)(c, p->cb_arg, error, rep); + p = n; + } + if(backup_p) { + free(backup_p); + sq->outnet->svcd_overhead = 0; + } + verbose(VERB_ALGO, "svcd callbacks end"); + log_assert(sq->cblist == NULL); + serviced_delete(sq); +} + +int +serviced_tcp_callback(struct comm_point* c, void* arg, int error, + struct comm_reply* rep) +{ + struct serviced_query* sq = (struct serviced_query*)arg; + struct comm_reply r2; + sq->pending = NULL; /* removed after this callback */ + if(error != NETEVENT_NOERROR) + log_addr(VERB_QUERY, "tcp error for address", + &sq->addr, sq->addrlen); + if(error==NETEVENT_NOERROR) + infra_update_tcp_works(sq->outnet->infra, &sq->addr, + sq->addrlen, sq->zone, sq->zonelen); + if(error==NETEVENT_NOERROR && sq->status == serviced_query_TCP_EDNS && + (LDNS_RCODE_WIRE(ldns_buffer_begin(c->buffer)) == + LDNS_RCODE_FORMERR || LDNS_RCODE_WIRE(ldns_buffer_begin( + c->buffer)) == LDNS_RCODE_NOTIMPL) ) { + /* attempt to fallback to nonEDNS */ + sq->status = serviced_query_TCP_EDNS_fallback; + serviced_tcp_initiate(sq->outnet, sq, c->buffer); + return 0; + } else if(error==NETEVENT_NOERROR && + sq->status == serviced_query_TCP_EDNS_fallback && + (LDNS_RCODE_WIRE(ldns_buffer_begin(c->buffer)) == + LDNS_RCODE_NOERROR || LDNS_RCODE_WIRE( + ldns_buffer_begin(c->buffer)) == LDNS_RCODE_NXDOMAIN + || LDNS_RCODE_WIRE(ldns_buffer_begin(c->buffer)) + == LDNS_RCODE_YXDOMAIN)) { + /* the fallback produced a result that looks promising, note + * that this server should be approached without EDNS */ + /* only store noEDNS in cache if domain is noDNSSEC */ + if(!sq->want_dnssec) + if(!infra_edns_update(sq->outnet->infra, &sq->addr, + sq->addrlen, sq->zone, sq->zonelen, -1, + *sq->outnet->now_secs)) + log_err("Out of memory caching no edns for host"); + sq->status = serviced_query_TCP; + } + if(sq->tcp_upstream || sq->ssl_upstream) { + struct timeval now = *sq->outnet->now_tv; + if(now.tv_sec > sq->last_sent_time.tv_sec || + (now.tv_sec == sq->last_sent_time.tv_sec && + now.tv_usec > sq->last_sent_time.tv_usec)) { + /* convert from microseconds to milliseconds */ + int roundtime = ((int)now.tv_sec - (int)sq->last_sent_time.tv_sec)*1000 + + ((int)now.tv_usec - (int)sq->last_sent_time.tv_usec)/1000; + verbose(VERB_ALGO, "measured TCP-time at %d msec", roundtime); + log_assert(roundtime >= 0); + /* only store if less then AUTH_TIMEOUT seconds, it could be + * huge due to system-hibernated and we woke up */ + if(roundtime < TCP_AUTH_QUERY_TIMEOUT*1000) { + if(!infra_rtt_update(sq->outnet->infra, &sq->addr, + sq->addrlen, sq->zone, sq->zonelen, sq->qtype, + roundtime, sq->last_rtt, (uint32_t)now.tv_sec)) + log_err("out of memory noting rtt."); + } + } + } + /* insert address into reply info */ + if(!rep) { + /* create one if there isn't (on errors) */ + rep = &r2; + r2.c = c; + } + memcpy(&rep->addr, &sq->addr, sq->addrlen); + rep->addrlen = sq->addrlen; + serviced_callbacks(sq, error, c, rep); + return 0; +} + +static void +serviced_tcp_initiate(struct outside_network* outnet, + struct serviced_query* sq, ldns_buffer* buff) +{ + verbose(VERB_ALGO, "initiate TCP query %s", + sq->status==serviced_query_TCP_EDNS?"EDNS":""); + serviced_encode(sq, buff, sq->status == serviced_query_TCP_EDNS); + sq->last_sent_time = *sq->outnet->now_tv; + sq->pending = pending_tcp_query(outnet, buff, &sq->addr, + sq->addrlen, TCP_AUTH_QUERY_TIMEOUT, serviced_tcp_callback, + sq, sq->ssl_upstream); + if(!sq->pending) { + /* delete from tree so that a retry by above layer does not + * clash with this entry */ + log_err("serviced_tcp_initiate: failed to send tcp query"); + serviced_callbacks(sq, NETEVENT_CLOSED, NULL, NULL); + } +} + +/** Send serviced query over TCP return false on initial failure */ +static int +serviced_tcp_send(struct serviced_query* sq, ldns_buffer* buff) +{ + int vs, rtt; + uint8_t edns_lame_known; + if(!infra_host(sq->outnet->infra, &sq->addr, sq->addrlen, sq->zone, + sq->zonelen, *sq->outnet->now_secs, &vs, &edns_lame_known, + &rtt)) + return 0; + if(vs != -1) + sq->status = serviced_query_TCP_EDNS; + else sq->status = serviced_query_TCP; + serviced_encode(sq, buff, sq->status == serviced_query_TCP_EDNS); + sq->last_sent_time = *sq->outnet->now_tv; + sq->pending = pending_tcp_query(sq->outnet, buff, &sq->addr, + sq->addrlen, TCP_AUTH_QUERY_TIMEOUT, serviced_tcp_callback, + sq, sq->ssl_upstream); + return sq->pending != NULL; +} + +int +serviced_udp_callback(struct comm_point* c, void* arg, int error, + struct comm_reply* rep) +{ + struct serviced_query* sq = (struct serviced_query*)arg; + struct outside_network* outnet = sq->outnet; + struct timeval now = *sq->outnet->now_tv; + int fallback_tcp = 0; + + sq->pending = NULL; /* removed after callback */ + if(error == NETEVENT_TIMEOUT) { + int rto = 0; + if(sq->status == serviced_query_PROBE_EDNS) { + /* non-EDNS probe failed; we do not know its status, + * keep trying with EDNS, timeout may not be caused + * by EDNS. */ + sq->status = serviced_query_UDP_EDNS; + } + if(sq->status == serviced_query_UDP_EDNS && sq->last_rtt < 5000) { + /* fallback to 1480/1280 */ + sq->status = serviced_query_UDP_EDNS_FRAG; + log_name_addr(VERB_ALGO, "try edns1xx0", sq->qbuf+10, + &sq->addr, sq->addrlen); + if(!serviced_udp_send(sq, c->buffer)) { + serviced_callbacks(sq, NETEVENT_CLOSED, c, rep); + } + return 0; + } + if(sq->status == serviced_query_UDP_EDNS_FRAG) { + /* fragmentation size did not fix it */ + sq->status = serviced_query_UDP_EDNS; + } + sq->retry++; + if(!(rto=infra_rtt_update(outnet->infra, &sq->addr, sq->addrlen, + sq->zone, sq->zonelen, sq->qtype, -1, sq->last_rtt, + (uint32_t)now.tv_sec))) + log_err("out of memory in UDP exponential backoff"); + if(sq->retry < OUTBOUND_UDP_RETRY) { + log_name_addr(VERB_ALGO, "retry query", sq->qbuf+10, + &sq->addr, sq->addrlen); + if(!serviced_udp_send(sq, c->buffer)) { + serviced_callbacks(sq, NETEVENT_CLOSED, c, rep); + } + return 0; + } + if(rto >= RTT_MAX_TIMEOUT) { + fallback_tcp = 1; + /* UDP does not work, fallback to TCP below */ + } else { + serviced_callbacks(sq, NETEVENT_TIMEOUT, c, rep); + return 0; + } + } else if(error != NETEVENT_NOERROR) { + /* udp returns error (due to no ID or interface available) */ + serviced_callbacks(sq, error, c, rep); + return 0; + } + if(!fallback_tcp) { + if( (sq->status == serviced_query_UDP_EDNS + ||sq->status == serviced_query_UDP_EDNS_FRAG) + && (LDNS_RCODE_WIRE(ldns_buffer_begin(c->buffer)) + == LDNS_RCODE_FORMERR || LDNS_RCODE_WIRE( + ldns_buffer_begin(c->buffer)) == LDNS_RCODE_NOTIMPL)) { + /* 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; + sq->retry = 0; + if(!serviced_udp_send(sq, c->buffer)) { + serviced_callbacks(sq, NETEVENT_CLOSED, c, rep); + } + return 0; + } else if(sq->status == serviced_query_PROBE_EDNS) { + /* probe without EDNS succeeds, so we conclude that this + * host likely has EDNS packets dropped */ + log_addr(VERB_DETAIL, "timeouts, concluded that connection to " + "host drops EDNS packets", &sq->addr, sq->addrlen); + /* only store noEDNS in cache if domain is noDNSSEC */ + if(!sq->want_dnssec) + if(!infra_edns_update(outnet->infra, &sq->addr, sq->addrlen, + sq->zone, sq->zonelen, -1, (uint32_t)now.tv_sec)) { + log_err("Out of memory caching no edns for host"); + } + sq->status = serviced_query_UDP; + } else if(sq->status == serviced_query_UDP_EDNS && + !sq->edns_lame_known) { + /* now we know that edns queries received answers store that */ + log_addr(VERB_ALGO, "serviced query: EDNS works for", + &sq->addr, sq->addrlen); + if(!infra_edns_update(outnet->infra, &sq->addr, sq->addrlen, + sq->zone, sq->zonelen, 0, (uint32_t)now.tv_sec)) { + log_err("Out of memory caching edns works"); + } + sq->edns_lame_known = 1; + } else if(sq->status == serviced_query_UDP_EDNS_fallback && + !sq->edns_lame_known && (LDNS_RCODE_WIRE( + ldns_buffer_begin(c->buffer)) == LDNS_RCODE_NOERROR || + LDNS_RCODE_WIRE(ldns_buffer_begin(c->buffer)) == + LDNS_RCODE_NXDOMAIN || LDNS_RCODE_WIRE(ldns_buffer_begin( + c->buffer)) == LDNS_RCODE_YXDOMAIN)) { + /* the fallback produced a result that looks promising, note + * that this server should be approached without EDNS */ + /* only store noEDNS in cache if domain is noDNSSEC */ + if(!sq->want_dnssec) { + log_addr(VERB_ALGO, "serviced query: EDNS fails for", + &sq->addr, sq->addrlen); + if(!infra_edns_update(outnet->infra, &sq->addr, sq->addrlen, + sq->zone, sq->zonelen, -1, (uint32_t)now.tv_sec)) { + log_err("Out of memory caching no edns for host"); + } + } else { + log_addr(VERB_ALGO, "serviced query: EDNS fails, but " + "not stored because need DNSSEC for", &sq->addr, + sq->addrlen); + } + sq->status = serviced_query_UDP; + } + if(now.tv_sec > sq->last_sent_time.tv_sec || + (now.tv_sec == sq->last_sent_time.tv_sec && + now.tv_usec > sq->last_sent_time.tv_usec)) { + /* convert from microseconds to milliseconds */ + int roundtime = ((int)now.tv_sec - (int)sq->last_sent_time.tv_sec)*1000 + + ((int)now.tv_usec - (int)sq->last_sent_time.tv_usec)/1000; + verbose(VERB_ALGO, "measured roundtrip at %d msec", roundtime); + log_assert(roundtime >= 0); + /* in case the system hibernated, do not enter a huge value, + * above this value gives trouble with server selection */ + if(roundtime < 60000) { + if(!infra_rtt_update(outnet->infra, &sq->addr, sq->addrlen, + sq->zone, sq->zonelen, sq->qtype, roundtime, + sq->last_rtt, (uint32_t)now.tv_sec)) + log_err("out of memory noting rtt."); + } + } + } /* end of if_!fallback_tcp */ + /* perform TC flag check and TCP fallback after updating our + * cache entries for EDNS status and RTT times */ + if(LDNS_TC_WIRE(ldns_buffer_begin(c->buffer)) || fallback_tcp) { + /* fallback to TCP */ + /* this discards partial UDP contents */ + if(sq->status == serviced_query_UDP_EDNS || + sq->status == serviced_query_UDP_EDNS_FRAG || + sq->status == serviced_query_UDP_EDNS_fallback) + /* if we have unfinished EDNS_fallback, start again */ + sq->status = serviced_query_TCP_EDNS; + else sq->status = serviced_query_TCP; + serviced_tcp_initiate(outnet, sq, c->buffer); + return 0; + } + /* yay! an answer */ + serviced_callbacks(sq, error, c, rep); + return 0; +} + +/** find callback in list */ +static struct service_callback* +callback_list_find(struct serviced_query* sq, void* cb_arg, + int (*arg_compare)(void*,void*)) +{ + struct service_callback* p; + for(p = sq->cblist; p; p = p->next) { + if(arg_compare(p->cb_arg, cb_arg)) + return p; + } + return NULL; +} + +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 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, ldns_buffer* buff, int (*arg_compare)(void*,void*)) +{ + 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); + if(sq) { + /* see if it is a duplicate notification request for cb_arg */ + if(callback_list_find(sq, callback_arg, arg_compare)) { + return sq; + } + } + if(!(cb = (struct service_callback*)malloc(sizeof(*cb)))) + return NULL; + if(!sq) { + /* make new serviced query entry */ + sq = serviced_create(outnet, buff, dnssec, want_dnssec, + tcp_upstream, ssl_upstream, addr, addrlen, zone, + zonelen, (int)qtype); + if(!sq) { + free(cb); + return NULL; + } + /* perform first network action */ + if(outnet->do_udp && !(tcp_upstream || ssl_upstream)) { + if(!serviced_udp_send(sq, buff)) { + (void)rbtree_delete(outnet->serviced, sq); + free(sq->qbuf); + free(sq->zone); + free(sq); + free(cb); + return NULL; + } + } else { + if(!serviced_tcp_send(sq, buff)) { + (void)rbtree_delete(outnet->serviced, sq); + free(sq->qbuf); + free(sq->zone); + free(sq); + free(cb); + return NULL; + } + } + } + /* add callback to list of callbacks */ + cb->cb = callback; + cb->cb_arg = callback_arg; + cb->next = sq->cblist; + sq->cblist = cb; + return sq; +} + +/** remove callback from list */ +static void +callback_list_remove(struct serviced_query* sq, void* cb_arg) +{ + struct service_callback** pp = &sq->cblist; + while(*pp) { + if((*pp)->cb_arg == cb_arg) { + struct service_callback* del = *pp; + *pp = del->next; + free(del); + return; + } + pp = &(*pp)->next; + } +} + +void outnet_serviced_query_stop(struct serviced_query* sq, void* cb_arg) +{ + if(!sq) + return; + 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 = +#endif + rbtree_delete(sq->outnet->serviced, sq); + log_assert(rem); /* should be present */ + serviced_delete(sq); + } +} + +/** get memory used by waiting tcp entry (in use or not) */ +static size_t +waiting_tcp_get_mem(struct waiting_tcp* w) +{ + size_t s; + if(!w) return 0; + s = sizeof(*w) + w->pkt_len; + if(w->timer) + s += comm_timer_get_mem(w->timer); + return s; +} + +/** get memory used by port if */ +static size_t +if_get_mem(struct port_if* pif) +{ + size_t s; + int i; + s = sizeof(*pif) + sizeof(int)*pif->avail_total + + sizeof(struct port_comm*)*pif->maxout; + for(i=0; iinuse; i++) + s += sizeof(*pif->out[i]) + + comm_point_get_mem(pif->out[i]->cp); + return s; +} + +/** get memory used by waiting udp */ +static size_t +waiting_udp_get_mem(struct pending* w) +{ + size_t s; + s = sizeof(*w) + comm_timer_get_mem(w->timer) + w->pkt_len; + return s; +} + +size_t outnet_get_mem(struct outside_network* outnet) +{ + size_t i; + int k; + struct waiting_tcp* w; + struct pending* u; + struct serviced_query* sq; + struct service_callback* sb; + struct port_comm* pc; + size_t s = sizeof(*outnet) + sizeof(*outnet->base) + + sizeof(*outnet->udp_buff) + + ldns_buffer_capacity(outnet->udp_buff); + /* second buffer is not ours */ + for(pc = outnet->unused_fds; pc; pc = pc->next) { + s += sizeof(*pc) + comm_point_get_mem(pc->cp); + } + for(k=0; knum_ip4; k++) + s += if_get_mem(&outnet->ip4_ifs[k]); + for(k=0; knum_ip6; k++) + s += if_get_mem(&outnet->ip6_ifs[k]); + for(u=outnet->udp_wait_first; u; u=u->next_waiting) + s += waiting_udp_get_mem(u); + + s += sizeof(struct pending_tcp*)*outnet->num_tcp; + for(i=0; inum_tcp; i++) { + s += sizeof(struct pending_tcp); + s += comm_point_get_mem(outnet->tcp_conns[i]->c); + if(outnet->tcp_conns[i]->query) + s += waiting_tcp_get_mem(outnet->tcp_conns[i]->query); + } + for(w=outnet->tcp_wait_first; w; w = w->next_waiting) + s += waiting_tcp_get_mem(w); + s += sizeof(*outnet->pending); + s += (sizeof(struct pending) + comm_timer_get_mem(NULL)) * + outnet->pending->count; + s += sizeof(*outnet->serviced); + s += outnet->svcd_overhead; + RBTREE_FOR(sq, struct serviced_query*, outnet->serviced) { + s += sizeof(*sq) + sq->qbuflen; + for(sb = sq->cblist; sb; sb = sb->next) + s += sizeof(*sb); + } + return s; +} + +size_t +serviced_get_mem(struct serviced_query* sq) +{ + struct service_callback* sb; + size_t s; + s = sizeof(*sq) + sq->qbuflen; + for(sb = sq->cblist; sb; sb = sb->next) + s += sizeof(*sb); + if(sq->status == serviced_query_UDP_EDNS || + sq->status == serviced_query_UDP || + sq->status == serviced_query_PROBE_EDNS || + sq->status == serviced_query_UDP_EDNS_FRAG || + sq->status == serviced_query_UDP_EDNS_fallback) { + s += sizeof(struct pending); + s += comm_timer_get_mem(NULL); + } else { + /* does not have size of the pkt pointer */ + /* always has a timer except on malloc failures */ + + /* these sizes are part of the main outside network mem */ + /* + s += sizeof(struct waiting_tcp); + s += comm_timer_get_mem(NULL); + */ + } + return s; +} + diff --git a/services/outside_network.h b/services/outside_network.h new file mode 100644 index 00000000000..ab18d2406e6 --- /dev/null +++ b/services/outside_network.h @@ -0,0 +1,538 @@ +/* + * services/outside_network.h - listen to answers from the network + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file has functions to send queries to authoritative servers, + * and wait for the pending answer, with timeouts. + */ + +#ifndef OUTSIDE_NETWORK_H +#define OUTSIDE_NETWORK_H + +#include "util/rbtree.h" +#include "util/netevent.h" +struct pending; +struct pending_timeout; +struct ub_randstate; +struct pending_tcp; +struct waiting_tcp; +struct waiting_udp; +struct infra_cache; +struct port_comm; +struct port_if; + +/** + * Send queries to outside servers and wait for answers from servers. + * Contains answer-listen sockets. + */ +struct outside_network { + /** Base for select calls */ + struct comm_base* base; + /** pointer to time in seconds */ + uint32_t* now_secs; + /** pointer to time in microseconds */ + struct timeval* now_tv; + + /** buffer shared by UDP connections, since there is only one + datagram at any time. */ + ldns_buffer* udp_buff; + /** serviced_callbacks malloc overhead when processing multiple + * identical serviced queries to the same server. */ + size_t svcd_overhead; + /** use x20 bits to encode additional ID random bits */ + int use_caps_for_id; + /** outside network wants to quit. Stop queued msgs from sent. */ + int want_to_quit; + + /** number of unwanted replies received (for statistics) */ + size_t unwanted_replies; + /** cumulative total of unwanted replies (for defense) */ + size_t unwanted_total; + /** threshold when to take defensive action. If 0 then never. */ + size_t unwanted_threshold; + /** what action to take, called when defensive action is needed */ + void (*unwanted_action)(void*); + /** user param for action */ + void* unwanted_param; + + /** linked list of available commpoints, unused file descriptors, + * for use as outgoing UDP ports. cp.fd=-1 in them. */ + struct port_comm* unused_fds; + /** if udp is done */ + int do_udp; + + /** array of outgoing IP4 interfaces */ + struct port_if* ip4_ifs; + /** number of outgoing IP4 interfaces */ + int num_ip4; + + /** array of outgoing IP6 interfaces */ + struct port_if* ip6_ifs; + /** number of outgoing IP6 interfaces */ + int num_ip6; + + /** pending udp queries waiting to be sent out, waiting for fd */ + struct pending* udp_wait_first; + /** last pending udp query in list */ + struct pending* udp_wait_last; + + /** pending udp answers. sorted by id, addr */ + rbtree_t* pending; + /** serviced queries, sorted by qbuf, addr, dnssec */ + rbtree_t* serviced; + /** host cache, pointer but not owned by outnet. */ + struct infra_cache* infra; + /** where to get random numbers */ + struct ub_randstate* rnd; + /** ssl context to create ssl wrapped TCP with DNS connections */ + void* sslctx; + + /** + * Array of tcp pending used for outgoing TCP connections. + * Each can be used to establish a TCP connection with a server. + * The file descriptors are -1 if they are free, and need to be + * opened for the tcp connection. Can be used for ip4 and ip6. + */ + struct pending_tcp **tcp_conns; + /** number of tcp communication points. */ + size_t num_tcp; + /** list of tcp comm points that are free for use */ + struct pending_tcp* tcp_free; + /** list of tcp queries waiting for a buffer */ + struct waiting_tcp* tcp_wait_first; + /** last of waiting query list */ + struct waiting_tcp* tcp_wait_last; +}; + +/** + * Outgoing interface. Ports available and currently used are tracked + * per interface + */ +struct port_if { + /** address ready to allocate new socket (except port no). */ + struct sockaddr_storage addr; + /** length of addr field */ + socklen_t addrlen; + + /** the available ports array. These are unused. + * Only the first total-inuse part is filled. */ + int* avail_ports; + /** the total number of available ports (size of the array) */ + int avail_total; + + /** array of the commpoints currently in use. + * allocated for max number of fds, first part in use. */ + struct port_comm** out; + /** max number of fds, size of out array */ + int maxout; + /** number of commpoints (and thus also ports) in use */ + int inuse; +}; + +/** + * Outgoing commpoint for UDP port. + */ +struct port_comm { + /** next in free list */ + struct port_comm* next; + /** which port number (when in use) */ + int number; + /** interface it is used in */ + struct port_if* pif; + /** index in the out array of the interface */ + int index; + /** number of outstanding queries on this port */ + int num_outstanding; + /** UDP commpoint, fd=-1 if not in use */ + struct comm_point* cp; +}; + +/** + * A query that has an answer pending for it. + */ +struct pending { + /** redblacktree entry, key is the pending struct(id, addr). */ + rbnode_t node; + /** the ID for the query. int so that a value out of range can + * be used to signify a pending that is for certain not present in + * the rbtree. (and for which deletion is safe). */ + unsigned int id; + /** remote address. */ + struct sockaddr_storage addr; + /** length of addr field in use. */ + socklen_t addrlen; + /** comm point it was sent on (and reply must come back on). */ + struct port_comm* pc; + /** timeout event */ + struct comm_timer* timer; + /** callback for the timeout, error or reply to the message */ + comm_point_callback_t* cb; + /** callback user argument */ + void* cb_arg; + /** the outside network it is part of */ + struct outside_network* outnet; + + /*---- filled if udp pending is waiting -----*/ + /** next in waiting list. */ + struct pending* next_waiting; + /** timeout in msec */ + int timeout; + /** The query itself, the query packet to send. */ + uint8_t* pkt; + /** length of query packet. */ + size_t pkt_len; +}; + +/** + * Pending TCP query to server. + */ +struct pending_tcp { + /** next in list of free tcp comm points, or NULL. */ + struct pending_tcp* next_free; + /** the ID for the query; checked in reply */ + uint16_t id; + /** tcp comm point it was sent on (and reply must come back on). */ + struct comm_point* c; + /** the query being serviced, NULL if the pending_tcp is unused. */ + struct waiting_tcp* query; +}; + +/** + * Query waiting for TCP buffer. + */ +struct waiting_tcp { + /** + * next in waiting list. + * if pkt==0, this points to the pending_tcp structure. + */ + struct waiting_tcp* next_waiting; + /** timeout event; timer keeps running whether the query is + * waiting for a buffer or the tcp reply is pending */ + struct comm_timer* timer; + /** the outside network it is part of */ + struct outside_network* outnet; + /** remote address. */ + struct sockaddr_storage addr; + /** length of addr field in use. */ + socklen_t addrlen; + /** + * The query itself, the query packet to send. + * allocated after the waiting_tcp structure. + * set to NULL when the query is serviced and it part of pending_tcp. + * if this is NULL, the next_waiting points to the pending_tcp. + */ + uint8_t* pkt; + /** length of query packet. */ + size_t pkt_len; + /** callback for the timeout, error or reply to the message */ + comm_point_callback_t* cb; + /** callback user argument */ + void* cb_arg; + /** if it uses ssl upstream */ + int ssl_upstream; +}; + +/** + * Callback to party interested in serviced query results. + */ +struct service_callback { + /** next in callback list */ + struct service_callback* next; + /** callback function */ + comm_point_callback_t* cb; + /** user argument for callback function */ + void* cb_arg; +}; + +/** fallback size for fragmentation for EDNS in IPv4 */ +#define EDNS_FRAG_SIZE_IP4 1480 +/** fallback size for EDNS in IPv6, fits one fragment with ip6-tunnel-ids */ +#define EDNS_FRAG_SIZE_IP6 1260 + +/** + * Query service record. + * Contains query and destination. UDP, TCP, EDNS are all tried. + * complete with retries and timeouts. A number of interested parties can + * receive a callback. + */ +struct serviced_query { + /** The rbtree node, key is this record */ + rbnode_t node; + /** The query that needs to be answered. Starts with flags u16, + * then qdcount, ..., including qname, qtype, qclass. Does not include + * EDNS record. */ + uint8_t* qbuf; + /** length of qbuf. */ + size_t qbuflen; + /** If an EDNS section is included, the DO/CD bit will be turned on. */ + int dnssec; + /** We want signatures, or else the answer is likely useless */ + int want_dnssec; + /** tcp upstream used, use tcp, or ssl_upstream for SSL */ + int tcp_upstream, ssl_upstream; + /** where to send it */ + struct sockaddr_storage addr; + /** length of addr field in use. */ + socklen_t addrlen; + /** zone name, uncompressed domain name in wireformat */ + uint8_t* zone; + /** length of zone name */ + size_t zonelen; + /** qtype */ + int qtype; + /** current status */ + enum serviced_query_status { + /** initial status */ + serviced_initial, + /** UDP with EDNS sent */ + serviced_query_UDP_EDNS, + /** UDP without EDNS sent */ + serviced_query_UDP, + /** TCP with EDNS sent */ + serviced_query_TCP_EDNS, + /** TCP without EDNS sent */ + serviced_query_TCP, + /** probe to test EDNS lameness (EDNS is dropped) */ + serviced_query_PROBE_EDNS, + /** probe to test noEDNS0 (EDNS gives FORMERRorNOTIMP) */ + serviced_query_UDP_EDNS_fallback, + /** probe to test TCP noEDNS0 (EDNS gives FORMERRorNOTIMP) */ + serviced_query_TCP_EDNS_fallback, + /** send UDP query with EDNS1480 (or 1280) */ + serviced_query_UDP_EDNS_FRAG + } + /** variable with current status */ + status; + /** true if serviced_query is scheduled for deletion already */ + int to_be_deleted; + /** number of UDP retries */ + int retry; + /** time last UDP was sent */ + struct timeval last_sent_time; + /** rtt of last (UDP) message */ + int last_rtt; + /** do we know edns probe status already, for UDP_EDNS queries */ + int edns_lame_known; + /** outside network this is part of */ + struct outside_network* outnet; + /** list of interested parties that need callback on results. */ + struct service_callback* cblist; + /** the UDP or TCP query that is pending, see status which */ + void* pending; +}; + +/** + * Create outside_network structure with N udp ports. + * @param base: the communication base to use for event handling. + * @param bufsize: size for network buffers. + * @param num_ports: number of udp ports to open per interface. + * @param ifs: interface names (or NULL for default interface). + * These interfaces must be able to access all authoritative servers. + * @param num_ifs: number of names in array ifs. + * @param do_ip4: service IP4. + * @param do_ip6: service IP6. + * @param num_tcp: number of outgoing tcp buffers to preallocate. + * @param infra: pointer to infra cached used for serviced queries. + * @param rnd: stored to create random numbers for serviced queries. + * @param use_caps_for_id: enable to use 0x20 bits to encode id randomness. + * @param availports: array of available ports. + * @param numavailports: number of available ports in array. + * @param unwanted_threshold: when to take defensive action. + * @param unwanted_action: the action to take. + * @param unwanted_param: user parameter to action. + * @param do_udp: if udp is done. + * @param sslctx: context to create outgoing connections with (if enabled). + * @return: the new structure (with no pending answers) or NULL on error. + */ +struct outside_network* outside_network_create(struct comm_base* base, + size_t bufsize, size_t num_ports, char** ifs, int num_ifs, + int do_ip4, int do_ip6, size_t num_tcp, struct infra_cache* infra, + struct ub_randstate* rnd, int use_caps_for_id, int* availports, + int numavailports, size_t unwanted_threshold, + void (*unwanted_action)(void*), void* unwanted_param, int do_udp, + void* sslctx); + +/** + * Delete outside_network structure. + * @param outnet: object to delete. + */ +void outside_network_delete(struct outside_network* outnet); + +/** + * Prepare for quit. Sends no more queries, even if queued up. + * @param outnet: object to prepare for removal + */ +void outside_network_quit_prepare(struct outside_network* outnet); + +/** + * Send UDP query, create pending answer. + * Changes the ID for the query to be random and unique for that destination. + * @param outnet: provides the event handling + * @param packet: wireformat query to send to destination. + * @param addr: address to send to. + * @param addrlen: length of addr. + * @param timeout: in milliseconds from now. + * @param callback: function to call on error, timeout or reply. + * @param callback_arg: user argument for callback function. + * @return: NULL on error for malloc or socket. Else the pending query object. + */ +struct pending* pending_udp_query(struct outside_network* outnet, + ldns_buffer* packet, struct sockaddr_storage* addr, + socklen_t addrlen, int timeout, comm_point_callback_t* callback, + void* callback_arg); + +/** + * Send TCP query. May wait for TCP buffer. Selects ID to be random, and + * checks id. + * @param outnet: provides the event handling. + * @param packet: wireformat query to send to destination. copied from. + * @param addr: address to send to. + * @param addrlen: length of addr. + * @param timeout: in seconds from now. + * Timer starts running now. Timer may expire if all buffers are used, + * without any query been sent to the server yet. + * @param callback: function to call on error, timeout or reply. + * @param callback_arg: user argument for callback function. + * @param ssl_upstream: if the tcp connection must use SSL. + * @return: false on error for malloc or socket. Else the pending TCP object. + */ +struct waiting_tcp* pending_tcp_query(struct outside_network* outnet, + ldns_buffer* packet, struct sockaddr_storage* addr, + socklen_t addrlen, int timeout, comm_point_callback_t* callback, + void* callback_arg, int ssl_upstream); + +/** + * Delete pending answer. + * @param outnet: outside network the pending query is part of. + * Internal feature: if outnet is NULL, p is not unlinked from rbtree. + * @param p: deleted + */ +void pending_delete(struct outside_network* outnet, struct pending* p); + +/** + * Perform a serviced query to the authoritative servers. + * Duplicate efforts are detected, and EDNS, TCP and UDP retry is performed. + * @param outnet: outside network, with rbtree of serviced queries. + * @param qname: what qname to query. + * @param qnamelen: length of qname in octets including 0 root label. + * @param qtype: rrset type to query (host format) + * @param qclass: query class. (host format) + * @param flags: flags u16 (host format), includes opcode, CD bit. + * @param dnssec: if set, DO bit is set in EDNS queries. + * If the value includes BIT_CD, CD bit is set when in EDNS queries. + * If the value includes BIT_DO, DO bit is set when in EDNS queries. + * @param want_dnssec: signatures are needed, without EDNS the answer is + * likely to be useless. + * @param tcp_upstream: use TCP for upstream queries. + * @param ssl_upstream: use SSL for upstream queries. + * @param callback: callback function. + * @param callback_arg: user argument to callback function. + * @param addr: to which server to send the query. + * @param addrlen: length of addr. + * @param zone: name of the zone of the delegation point. wireformat dname. + This is the delegation point name for which the server is deemed + authoritative. + * @param zonelen: length of zone. + * @param buff: scratch buffer to create query contents in. Empty on exit. + * @param arg_compare: function to compare callback args, return true if + * identical. It is given the callback_arg and args that are listed. + * @return 0 on error, or pointer to serviced query that is used to answer + * this serviced query may be shared with other callbacks as well. + */ +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 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, ldns_buffer* buff, + int (*arg_compare)(void*,void*)); + +/** + * Remove service query callback. + * If that leads to zero callbacks, the query is completely cancelled. + * @param sq: serviced query to adjust. + * @param cb_arg: callback argument of callback that needs removal. + * same as the callback_arg to outnet_serviced_query(). + */ +void outnet_serviced_query_stop(struct serviced_query* sq, void* cb_arg); + +/** + * Get memory size in use by outside network. + * Counts buffers and outstanding query (serviced queries) malloced data. + * @param outnet: outside network structure. + * @return size in bytes. + */ +size_t outnet_get_mem(struct outside_network* outnet); + +/** + * Get memory size in use by serviced query while it is servicing callbacks. + * This takes into account the pre-deleted status of it; it will be deleted + * when the callbacks are done. + * @param sq: serviced query. + * @return size in bytes. + */ +size_t serviced_get_mem(struct serviced_query* sq); + +/** callback for incoming udp answers from the network */ +int outnet_udp_cb(struct comm_point* c, void* arg, int error, + struct comm_reply *reply_info); + +/** callback for pending tcp connections */ +int outnet_tcp_cb(struct comm_point* c, void* arg, int error, + struct comm_reply *reply_info); + +/** callback for udp timeout */ +void pending_udp_timer_cb(void *arg); + +/** callback for outgoing TCP timer event */ +void outnet_tcptimer(void* arg); + +/** callback for serviced query UDP answers */ +int serviced_udp_callback(struct comm_point* c, void* arg, int error, + struct comm_reply* rep); + +/** TCP reply or error callback for serviced queries */ +int serviced_tcp_callback(struct comm_point* c, void* arg, int error, + struct comm_reply* rep); + +/** compare function of pending rbtree */ +int pending_cmp(const void* key1, const void* key2); + +/** compare function of serviced query rbtree */ +int serviced_cmp(const void* key1, const void* key2); + +#endif /* OUTSIDE_NETWORK_H */ diff --git a/smallapp/unbound-anchor.c b/smallapp/unbound-anchor.c new file mode 100644 index 00000000000..e14ca733fd7 --- /dev/null +++ b/smallapp/unbound-anchor.c @@ -0,0 +1,2165 @@ +/* + * unbound-anchor.c - update the root anchor if necessary. + * + * Copyright (c) 2010, 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \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. + * + * This is a concept solution for distribution of the DNSSEC root + * trust anchor. It is a small tool, called "unbound-anchor", that + * runs before the main validator starts. I.e. in the init script: + * unbound-anchor; unbound. Thus it is meant to run at system boot time. + * + * 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. + * Special considerations: + * * 30-days RFC5011 timer saves a lot of https traffic. + * * DNSKEY probe must be NOERROR, saves a lot of https traffic. + * * fail if clock before sign date of the root, if cert expired. + * * if the root goes back to unsigned, deals with it. + * + * It has hardcoded the root DS anchors and the ICANN CA root certificate. + * It allows with options to override those. It also takes root-hints (it + * has to do a DNS resolve), and also has hardcoded defaults for those. + * + * Once it starts, just before the validator starts, it quickly checks if + * the root anchor file needs to be updated. First it tries to use + * RFC5011-tracking of the root key. If that fails (and for 30-days since + * last successful probe), then it attempts to update using the + * certificate. So most of the time, the RFC5011 tracking will work fine, + * and within a couple milliseconds, the main daemon can start. It will + * have only probed the . DNSKEY, not done expensive https transfers on the + * root infrastructure. + * + * If there is no root key in the root.key file, it bootstraps the + * RFC5011-tracking with its builtin DS anchors; if that fails it + * bootstraps the RFC5011-tracking using the certificate. (again to avoid + * https, and it is also faster). + * + * It uses the XML file by converting it to DS records and writing that to the + * key file. Unbound can detect that the 'special comments' are gone, and + * 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 + * 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 + * without DNSSEC. It tries a random IP until the transfer succeeds. It + * then checks the p7s signature. + * + * On any failure, it leaves the root key file untouched. The main + * validator has to cope with it, it cannot fix things (So a failure does + * not go 'without DNSSEC', no downgrade). If it used its builtin stuff or + * did the https, it exits with an exit code, so that this can trigger the + * init script to log the event and potentially alert the operator that can + * do a manual check. + * + * The date is also checked. Before 2010-07-15 is a failure (root not + * signed yet; avoids attacks on system clock). The + * last-successful-RFC5011-probe (if available) has to be more than 30 days + * in the past (otherwise, RFC5011 should have worked). This keeps + * unneccesary https traffic down. If the main certificate is expired, it + * fails. + * + * The dates on the keys in the xml are checked (uses the libexpat xml + * parser), only the valid ones are used to re-enstate RFC5011 tracking. + * If 0 keys are valid, the zone has gone to insecure (a special marker is + * written in the keyfile that tells the main validator daemon the zone is + * insecure). + * + * Only the root ICANN CA is shipped, not the intermediate ones. The + * intermediate CAs are included in the p7s file that was downloaded. (the + * root cert is valid to 2028 and the intermediate to 2014, today). + * + * Obviously, the tool also has options so the operator can provide a new + * keyfile, a new certificate and new URLs, and fresh root hints. By + * default it logs nothing on failure and success; it 'just works'. + * + */ + +#include "config.h" +#include "libunbound/unbound.h" +#include +#include +#ifndef HAVE_EXPAT_H +#error "need libexpat to parse root-anchors.xml file." +#endif +#ifdef HAVE_GETOPT_H +#include +#endif +#ifdef HAVE_OPENSSL_SSL_H +#include +#endif +#ifdef HAVE_OPENSSL_ERR_H +#include +#endif +#ifdef HAVE_OPENSSL_RAND_H +#include +#endif +#include +#include + +/** name of server in URL to fetch HTTPS from */ +#define URLNAME "data.iana.org" +/** path on HTTPS server to xml file */ +#define XMLNAME "root-anchors/root-anchors.xml" +/** path on HTTPS server to p7s file */ +#define P7SNAME "root-anchors/root-anchors.p7s" +/** port number for https access */ +#define HTTPS_PORT 443 + +#ifdef USE_WINSOCK +/* sneakily reuse the the wsa_strerror function, on windows */ +char* wsa_strerror(int err); +#endif + +/** verbosity for this application */ +static int verb = 0; + +/** list of IP addresses */ +struct ip_list { + /** next in list */ + struct ip_list* next; + /** length of addr */ + socklen_t len; + /** address ready to connect to */ + struct sockaddr_storage addr; + /** has the address been used */ + int used; +}; + +/** Give unbound-anchor usage, and exit (1). */ +static void +usage() +{ + printf("Usage: unbound-anchor [opts]\n"); + printf(" Setup or update root anchor. " + "Most options have defaults.\n"); + printf(" Run this program before you start the validator.\n"); + printf("\n"); + printf(" The anchor and cert have default builtin content\n"); + printf(" if the file does not exist or is empty.\n"); + printf("\n"); + printf("-a file root key file, default %s\n", ROOT_ANCHOR_FILE); + printf(" The key is input and output for this tool.\n"); + printf("-c file cert file, default %s\n", ROOT_CERT_FILE); + printf("-l list builtin key and cert on stdout\n"); + printf("-u name server in https url, default %s\n", URLNAME); + printf("-x path pathname to xml in url, default %s\n", XMLNAME); + printf("-s path pathname to p7s in url, default %s\n", P7SNAME); + printf("-4 work using IPv4 only\n"); + printf("-6 work using IPv6 only\n"); + printf("-f resolv.conf use given resolv.conf to resolve -u name\n"); + printf("-r root.hints use given root.hints to resolve -u name\n" + " builtin root hints are used by default\n"); + printf("-v more verbose\n"); + printf("-C conf debug, read config\n"); + printf("-P port use port for https connect, default 443\n"); + printf("-F debug, force update with cert\n"); + printf("-h show this usage help\n"); + 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); +} + +/** return the built in root update certificate */ +static const char* +get_builtin_cert(void) +{ + return +/* The ICANN CA fetched at 24 Sep 2010. Valid to 2028 */ +"-----BEGIN CERTIFICATE-----\n" +"MIIDdzCCAl+gAwIBAgIBATANBgkqhkiG9w0BAQsFADBdMQ4wDAYDVQQKEwVJQ0FO\n" +"TjEmMCQGA1UECxMdSUNBTk4gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxFjAUBgNV\n" +"BAMTDUlDQU5OIFJvb3QgQ0ExCzAJBgNVBAYTAlVTMB4XDTA5MTIyMzA0MTkxMloX\n" +"DTI5MTIxODA0MTkxMlowXTEOMAwGA1UEChMFSUNBTk4xJjAkBgNVBAsTHUlDQU5O\n" +"IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRYwFAYDVQQDEw1JQ0FOTiBSb290IENB\n" +"MQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKDb\n" +"cLhPNNqc1NB+u+oVvOnJESofYS9qub0/PXagmgr37pNublVThIzyLPGCJ8gPms9S\n" +"G1TaKNIsMI7d+5IgMy3WyPEOECGIcfqEIktdR1YWfJufXcMReZwU4v/AdKzdOdfg\n" +"ONiwc6r70duEr1IiqPbVm5T05l1e6D+HkAvHGnf1LtOPGs4CHQdpIUcy2kauAEy2\n" +"paKcOcHASvbTHK7TbbvHGPB+7faAztABLoneErruEcumetcNfPMIjXKdv1V1E3C7\n" +"MSJKy+jAqqQJqjZoQGB0necZgUMiUv7JK1IPQRM2CXJllcyJrm9WFxY0c1KjBO29\n" +"iIKK69fcglKcBuFShUECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B\n" +"Af8EBAMCAf4wHQYDVR0OBBYEFLpS6UmDJIZSL8eZzfyNa2kITcBQMA0GCSqGSIb3\n" +"DQEBCwUAA4IBAQAP8emCogqHny2UYFqywEuhLys7R9UKmYY4suzGO4nkbgfPFMfH\n" +"6M+Zj6owwxlwueZt1j/IaCayoKU3QsrYYoDRolpILh+FPwx7wseUEV8ZKpWsoDoD\n" +"2JFbLg2cfB8u/OlE4RYmcxxFSmXBg0yQ8/IoQt/bxOcEEhhiQ168H2yE5rxJMt9h\n" +"15nu5JBSewrCkYqYYmaxyOC3WrVGfHZxVI7MpIFcGdvSb2a1uyuua8l0BKgk3ujF\n" +"0/wsHNeP22qNyVO+XVBzrM8fk8BSUFuiT/6tZTYXRtEt5aKQZgXbKU5dUF3jT9qg\n" +"j/Br5BZw3X/zd325TvnswzMC1+ljLzHnQGGk\n" +"-----END CERTIFICATE-----\n" + ; +} + +/** return the built in root DS trust anchor */ +static const char* +get_builtin_ds(void) +{ + return +". IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5\n"; +} + +/** print hex data */ +static void +print_data(char* msg, char* data, int len) +{ + int i; + printf("%s: ", msg); + for(i=0; iaddr)->sin_addr; + if(ip->len != (socklen_t)sizeof(struct sockaddr_in)) + a = &((struct sockaddr_in6*)&ip->addr)->sin6_addr; + + if(inet_ntop((int)((struct sockaddr_in*)&ip->addr)->sin_family, + a, out, (socklen_t)sizeof(out))==0) + printf("%s (inet_ntop error)\n", msg); + else printf("%s %s\n", msg, out); + } +} + +/** free ip_list */ +static void +ip_list_free(struct ip_list* p) +{ + struct ip_list* np; + while(p) { + np = p->next; + free(p); + p = np; + } +} + +/** create ip_list entry for a RR record */ +static struct ip_list* +RR_to_ip(int tp, char* data, int len, int port) +{ + struct ip_list* ip = (struct ip_list*)calloc(1, sizeof(*ip)); + uint16_t p = (uint16_t)port; + if(tp == LDNS_RR_TYPE_A) { + struct sockaddr_in* sa = (struct sockaddr_in*)&ip->addr; + ip->len = (socklen_t)sizeof(*sa); + sa->sin_family = AF_INET; + sa->sin_port = (in_port_t)htons(p); + if(len != (int)sizeof(sa->sin_addr)) { + if(verb) printf("skipped badly formatted A\n"); + free(ip); + return NULL; + } + memmove(&sa->sin_addr, data, sizeof(sa->sin_addr)); + + } else if(tp == LDNS_RR_TYPE_AAAA) { + struct sockaddr_in6* sa = (struct sockaddr_in6*)&ip->addr; + ip->len = (socklen_t)sizeof(*sa); + sa->sin6_family = AF_INET6; + sa->sin6_port = (in_port_t)htons(p); + if(len != (int)sizeof(sa->sin6_addr)) { + if(verb) printf("skipped badly formatted AAAA\n"); + free(ip); + return NULL; + } + memmove(&sa->sin6_addr, data, sizeof(sa->sin6_addr)); + } else { + if(verb) printf("internal error: bad type in RRtoip\n"); + free(ip); + return NULL; + } + verb_addr("resolved server address", ip); + return ip; +} + +/** Resolve name, type, class and add addresses to iplist */ +static void +resolve_host_ip(struct ub_ctx* ctx, char* host, int port, int tp, int cl, + struct ip_list** head) +{ + struct ub_result* res = NULL; + int r; + int i; + + r = ub_resolve(ctx, host, tp, cl, &res); + if(r) { + if(verb) printf("error: resolve %s %s: %s\n", host, + (tp==LDNS_RR_TYPE_A)?"A":"AAAA", ub_strerror(r)); + return; + } + if(!res) { + if(verb) printf("out of memory\n"); + ub_ctx_delete(ctx); + exit(0); + } + for(i = 0; res->data[i]; i++) { + struct ip_list* ip = RR_to_ip(tp, res->data[i], res->len[i], + port); + if(!ip) continue; + ip->next = *head; + *head = ip; + } + ub_resolve_free(res); +} + +/** parse a text IP address into a sockaddr */ +static struct ip_list* +parse_ip_addr(char* str, int port) +{ + socklen_t len = 0; + struct sockaddr_storage* addr = NULL; + struct sockaddr_in6 a6; + struct sockaddr_in a; + struct ip_list* ip; + uint16_t p = (uint16_t)port; + memset(&a6, 0, sizeof(a6)); + memset(&a, 0, sizeof(a)); + + if(inet_pton(AF_INET6, str, &a6.sin6_addr) > 0) { + /* it is an IPv6 */ + a6.sin6_family = AF_INET6; + a6.sin6_port = (in_port_t)htons(p); + addr = (struct sockaddr_storage*)&a6; + len = (socklen_t)sizeof(struct sockaddr_in6); + } + if(inet_pton(AF_INET, str, &a.sin_addr) > 0) { + /* it is an IPv4 */ + a.sin_family = AF_INET; + a.sin_port = (in_port_t)htons(p); + addr = (struct sockaddr_storage*)&a; + len = (socklen_t)sizeof(struct sockaddr_in); + } + if(!len) return NULL; + ip = (struct ip_list*)calloc(1, sizeof(*ip)); + if(!ip) { + if(verb) printf("out of memory\n"); + exit(0); + } + ip->len = len; + memmove(&ip->addr, addr, len); + if(verb) printf("server address is %s\n", str); + return ip; +} + +/** + * Resolve a domain name (even though the resolver is down and there is + * no trust anchor). Without DNSSEC validation. + * @param host: the name to resolve. + * If this name is an IP4 or IP6 address this address is returned. + * @param port: the port number used for the returned IP structs. + * @param res_conf: resolv.conf (if any). + * @param root_hints: root hints (if any). + * @param debugconf: unbound.conf for debugging options. + * @param ip4only: use only ip4 for resolve and only lookup A + * @param ip6only: use only ip6 for resolve and only lookup AAAA + * default is to lookup A and AAAA using ip4 and ip6. + * @return list of IP addresses. + */ +static struct ip_list* +resolve_name(char* host, int port, char* res_conf, char* root_hints, + char* debugconf, int ip4only, int ip6only) +{ + struct ub_ctx* ctx; + struct ip_list* list = NULL; + /* first see if name is an IP address itself */ + if( (list=parse_ip_addr(host, port)) ) { + return list; + } + + /* create resolver context */ + ctx = create_unbound_context(res_conf, root_hints, debugconf, + ip4only, ip6only); + + /* try resolution of A */ + if(!ip6only) { + resolve_host_ip(ctx, host, port, LDNS_RR_TYPE_A, + LDNS_RR_CLASS_IN, &list); + } + + /* try resolution of AAAA */ + if(!ip4only) { + resolve_host_ip(ctx, host, port, LDNS_RR_TYPE_AAAA, + LDNS_RR_CLASS_IN, &list); + } + + ub_ctx_delete(ctx); + if(!list) { + if(verb) printf("%s has no IP addresses I can use\n", host); + exit(0); + } + return list; +} + +/** clear used flags */ +static void +wipe_ip_usage(struct ip_list* p) +{ + while(p) { + p->used = 0; + p = p->next; + } +} + +/** cound unused IPs */ +static int +count_unused(struct ip_list* p) +{ + int num = 0; + while(p) { + if(!p->used) num++; + p = p->next; + } + return num; +} + +/** pick random unused element from IP list */ +static struct ip_list* +pick_random_ip(struct ip_list* list) +{ + struct ip_list* p = list; + int num = count_unused(list); + int sel; + if(num == 0) return NULL; + /* not perfect, but random enough */ + sel = (int)ldns_get_random() % num; + /* skip over unused elements that we did not select */ + while(sel > 0 && p) { + if(!p->used) sel--; + p = p->next; + } + /* find the next unused element */ + while(p && p->used) + p = p->next; + if(!p) return NULL; /* robustness */ + return p; +} + +/** close the fd */ +static void +fd_close(int fd) +{ +#ifndef USE_WINSOCK + close(fd); +#else + closesocket(fd); +#endif +} + +/** printout socket errno */ +static void +print_sock_err(const char* msg) +{ +#ifndef USE_WINSOCK + if(verb) printf("%s: %s\n", msg, strerror(errno)); +#else + if(verb) printf("%s: %s\n", msg, wsa_strerror(WSAGetLastError())); +#endif +} + +/** connect to IP address */ +static int +connect_to_ip(struct ip_list* ip) +{ + int fd; + verb_addr("connect to", ip); + fd = socket(ip->len==(socklen_t)sizeof(struct sockaddr_in)? + AF_INET:AF_INET6, SOCK_STREAM, 0); + if(fd == -1) { + print_sock_err("socket"); + return -1; + } + if(connect(fd, (struct sockaddr*)&ip->addr, ip->len) < 0) { + print_sock_err("connect"); + fd_close(fd); + return -1; + } + return fd; +} + +/** create SSL context */ +static SSL_CTX* +setup_sslctx(void) +{ + SSL_CTX* sslctx = SSL_CTX_new(SSLv23_client_method()); + if(!sslctx) { + if(verb) printf("SSL_CTX_new error\n"); + return NULL; + } + return sslctx; +} + +/** initiate TLS on a connection */ +static SSL* +TLS_initiate(SSL_CTX* sslctx, int fd) +{ + X509* x; + int r; + SSL* ssl = SSL_new(sslctx); + if(!ssl) { + if(verb) printf("SSL_new error\n"); + return NULL; + } + SSL_set_connect_state(ssl); + (void)SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); + if(!SSL_set_fd(ssl, fd)) { + if(verb) printf("SSL_set_fd error\n"); + SSL_free(ssl); + return NULL; + } + while(1) { + ERR_clear_error(); + if( (r=SSL_do_handshake(ssl)) == 1) + break; + r = SSL_get_error(ssl, r); + if(r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE) { + if(verb) printf("SSL handshake failed\n"); + SSL_free(ssl); + return NULL; + } + /* wants to be called again */ + } + x = SSL_get_peer_certificate(ssl); + if(!x) { + if(verb) printf("Server presented no peer certificate\n"); + SSL_free(ssl); + return NULL; + } + verb_cert("server SSL certificate", x); + X509_free(x); + return ssl; +} + +/** perform neat TLS shutdown */ +static void +TLS_shutdown(int fd, SSL* ssl, SSL_CTX* sslctx) +{ + /* shutdown the SSL connection nicely */ + if(SSL_shutdown(ssl) == 0) { + SSL_shutdown(ssl); + } + SSL_free(ssl); + SSL_CTX_free(sslctx); + fd_close(fd); +} + +/** write a line over SSL */ +static int +write_ssl_line(SSL* ssl, char* str, char* sec) +{ + char buf[1024]; + size_t l; + if(sec) { + snprintf(buf, sizeof(buf), str, sec); + } else { + snprintf(buf, sizeof(buf), "%s", str); + } + l = strlen(buf); + if(l+2 >= sizeof(buf)) { + if(verb) printf("line too long\n"); + return 0; + } + if(verb >= 2) printf("SSL_write: %s\n", buf); + buf[l] = '\r'; + buf[l+1] = '\n'; + buf[l+2] = 0; + /* add \r\n */ + if(SSL_write(ssl, buf, (int)strlen(buf)) <= 0) { + if(verb) printf("could not SSL_write %s", str); + return 0; + } + return 1; +} + +/** process header line, check rcode and keeping track of size */ +static int +process_one_header(char* buf, size_t* clen, int* chunked) +{ + if(verb>=2) printf("header: '%s'\n", buf); + if(strncasecmp(buf, "HTTP/1.1 ", 9) == 0) { + /* check returncode */ + if(buf[9] != '2') { + if(verb) printf("bad status %s\n", buf+9); + return 0; + } + } else if(strncasecmp(buf, "Content-Length: ", 16) == 0) { + if(!*chunked) + *clen = (size_t)atoi(buf+16); + } else if(strncasecmp(buf, "Transfer-Encoding: chunked", 19+7) == 0) { + *clen = 0; + *chunked = 1; + } + return 1; +} + +/** + * Read one line from SSL + * zero terminates. + * skips "\r\n" (but not copied to buf). + * @param ssl: the SSL connection to read from (blocking). + * @param buf: buffer to return line in. + * @param len: size of the buffer. + * @return 0 on error, 1 on success. + */ +static int +read_ssl_line(SSL* ssl, char* buf, size_t len) +{ + size_t n = 0; + int r; + int endnl = 0; + while(1) { + if(n >= len) { + if(verb) printf("line too long\n"); + return 0; + } + if((r = SSL_read(ssl, buf+n, 1)) <= 0) { + if(SSL_get_error(ssl, r) == SSL_ERROR_ZERO_RETURN) { + /* EOF */ + break; + } + if(verb) printf("could not SSL_read\n"); + return 0; + } + if(endnl && buf[n] == '\n') { + break; + } else if(endnl) { + /* bad data */ + if(verb) printf("error: stray linefeeds\n"); + return 0; + } else if(buf[n] == '\r') { + /* skip \r, and also \n on the wire */ + endnl = 1; + continue; + } else if(buf[n] == '\n') { + /* skip the \n, we are done */ + break; + } else n++; + } + buf[n] = 0; + return 1; +} + +/** read http headers and process them */ +static size_t +read_http_headers(SSL* ssl, size_t* clen) +{ + char buf[1024]; + int chunked = 0; + *clen = 0; + while(read_ssl_line(ssl, buf, sizeof(buf))) { + if(buf[0] == 0) + return 1; + if(!process_one_header(buf, clen, &chunked)) + return 0; + } + return 0; +} + +/** read a data chunk */ +static char* +read_data_chunk(SSL* ssl, size_t len) +{ + size_t got = 0; + int r; + char* data = malloc(len+1); + if(!data) { + if(verb) printf("out of memory\n"); + return NULL; + } + while(got < len) { + if((r = SSL_read(ssl, data+got, (int)(len-got))) <= 0) { + if(SSL_get_error(ssl, r) == SSL_ERROR_ZERO_RETURN) { + /* EOF */ + if(verb) printf("could not SSL_read: unexpected EOF\n"); + free(data); + return NULL; + } + if(verb) printf("could not SSL_read\n"); + free(data); + return NULL; + } + if(verb >= 2) printf("at %d/%d\n", (int)got, (int)len); + got += r; + } + if(verb>=2) printf("read %d data\n", (int)len); + data[len] = 0; + return data; +} + +/** parse chunk header */ +static int +parse_chunk_header(char* buf, size_t* result) +{ + char* e = NULL; + size_t v = (size_t)strtol(buf, &e, 16); + if(e == buf) + return 0; + *result = v; + return 1; +} + +/** read chunked data from connection */ +static BIO* +do_chunked_read(SSL* ssl) +{ + char buf[1024]; + size_t len; + char* body; + BIO* mem = BIO_new(BIO_s_mem()); + if(verb>=3) printf("do_chunked_read\n"); + if(!mem) { + if(verb) printf("out of memory\n"); + return NULL; + } + while(read_ssl_line(ssl, buf, sizeof(buf))) { + /* read the chunked start line */ + if(verb>=2) printf("chunk header: %s\n", buf); + if(!parse_chunk_header(buf, &len)) { + BIO_free(mem); + if(verb>=3) printf("could not parse chunk header\n"); + return NULL; + } + if(verb>=2) printf("chunk len: %d\n", (int)len); + /* are we done? */ + if(len == 0) { + char z = 0; + /* skip end-of-chunk-trailer lines, + * until the empty line after that */ + do { + if(!read_ssl_line(ssl, buf, sizeof(buf))) { + BIO_free(mem); + return NULL; + } + } while (strlen(buf) > 0); + /* end of chunks, zero terminate it */ + if(BIO_write(mem, &z, 1) <= 0) { + if(verb) printf("out of memory\n"); + BIO_free(mem); + return NULL; + } + return mem; + } + /* read the chunked body */ + body = read_data_chunk(ssl, len); + if(!body) { + BIO_free(mem); + return NULL; + } + if(BIO_write(mem, body, (int)len) <= 0) { + if(verb) printf("out of memory\n"); + free(body); + BIO_free(mem); + return NULL; + } + free(body); + /* skip empty line after data chunk */ + if(!read_ssl_line(ssl, buf, sizeof(buf))) { + BIO_free(mem); + return NULL; + } + } + BIO_free(mem); + return NULL; +} + +/** start HTTP1.1 transaction on SSL */ +static int +write_http_get(SSL* ssl, char* pathname, char* urlname) +{ + if(write_ssl_line(ssl, "GET /%s HTTP/1.1", pathname) && + write_ssl_line(ssl, "Host: %s", urlname) && + write_ssl_line(ssl, "User-Agent: unbound-anchor/%s", + PACKAGE_VERSION) && + /* We do not really do multiple queries per connection, + * but this header setting is also not needed. + * write_ssl_line(ssl, "Connection: close", NULL) &&*/ + write_ssl_line(ssl, "", NULL)) { + return 1; + } + return 0; +} + +/** read chunked data and zero terminate; len is without zero */ +static char* +read_chunked_zero_terminate(SSL* ssl, size_t* len) +{ + /* do the chunked version */ + BIO* tmp = do_chunked_read(ssl); + char* data, *d = NULL; + size_t l; + if(!tmp) { + if(verb) printf("could not read from https\n"); + return NULL; + } + l = (size_t)BIO_get_mem_data(tmp, &d); + if(verb>=2) printf("chunked data is %d\n", (int)l); + if(l == 0 || d == NULL) { + if(verb) printf("out of memory\n"); + return NULL; + } + *len = l-1; + data = (char*)malloc(l); + if(data == NULL) { + if(verb) printf("out of memory\n"); + return NULL; + } + memcpy(data, d, l); + BIO_free(tmp); + return data; +} + +/** read HTTP result from SSL */ +static BIO* +read_http_result(SSL* ssl) +{ + size_t len = 0; + char* data; + BIO* m; + if(!read_http_headers(ssl, &len)) { + return NULL; + } + if(len == 0) { + data = read_chunked_zero_terminate(ssl, &len); + } else { + data = read_data_chunk(ssl, len); + } + if(!data) return NULL; + if(verb >= 4) print_data("read data", data, (int)len); + m = BIO_new_mem_buf(data, (int)len); + if(!m) { + if(verb) printf("out of memory\n"); + exit(0); + } + return m; +} + +/** https to an IP addr, return BIO with pathname or NULL */ +static BIO* +https_to_ip(struct ip_list* ip, char* pathname, char* urlname) +{ + int fd; + SSL* ssl; + BIO* bio; + SSL_CTX* sslctx = setup_sslctx(); + if(!sslctx) { + return NULL; + } + fd = connect_to_ip(ip); + if(fd == -1) { + SSL_CTX_free(sslctx); + return NULL; + } + ssl = TLS_initiate(sslctx, fd); + if(!ssl) { + SSL_CTX_free(sslctx); + fd_close(fd); + return NULL; + } + if(!write_http_get(ssl, pathname, urlname)) { + if(verb) printf("could not write to server\n"); + SSL_free(ssl); + SSL_CTX_free(sslctx); + fd_close(fd); + return NULL; + } + bio = read_http_result(ssl); + TLS_shutdown(fd, ssl, sslctx); + return bio; +} + +/** + * Do a HTTPS, HTTP1.1 over TLS, to fetch a file + * @param ip_list: list of IP addresses to use to fetch from. + * @param pathname: pathname of file on server to GET. + * @param urlname: name to pass as the virtual host for this request. + * @return a memory BIO with the file in it. + */ +static BIO* +https(struct ip_list* ip_list, char* pathname, char* urlname) +{ + struct ip_list* ip; + BIO* bio = NULL; + /* try random address first, and work through the list */ + wipe_ip_usage(ip_list); + while( (ip = pick_random_ip(ip_list)) ) { + ip->used = 1; + bio = https_to_ip(ip, pathname, urlname); + if(bio) break; + } + if(!bio) { + if(verb) printf("could not fetch %s\n", pathname); + exit(0); + } else { + if(verb) printf("fetched %s (%d bytes)\n", + pathname, (int)BIO_ctrl_pending(bio)); + } + return bio; +} + +/** free up a downloaded file BIO */ +static void +free_file_bio(BIO* bio) +{ + char* pp = NULL; + (void)BIO_reset(bio); + (void)BIO_get_mem_data(bio, &pp); + free(pp); + BIO_free(bio); +} + +/** XML parse private data during the parse */ +struct xml_data { + /** the parser, reference */ + XML_Parser parser; + /** the current tag; malloced; or NULL outside of tags */ + char* tag; + /** current date to use during the parse */ + time_t date; + /** number of keys usefully read in */ + int num_keys; + /** the compiled anchors as DS records */ + BIO* ds; + + /** do we want to use this anchor? */ + int use_key; + /** the current anchor: Zone */ + BIO* czone; + /** the current anchor: KeyTag */ + BIO* ctag; + /** the current anchor: Algorithm */ + BIO* calgo; + /** the current anchor: DigestType */ + BIO* cdigtype; + /** the current anchor: Digest*/ + BIO* cdigest; +}; + +/** The BIO for the tag */ +static BIO* +xml_selectbio(struct xml_data* data, const char* tag) +{ + BIO* b = NULL; + if(strcasecmp(tag, "KeyTag") == 0) + b = data->ctag; + else if(strcasecmp(tag, "Algorithm") == 0) + b = data->calgo; + else if(strcasecmp(tag, "DigestType") == 0) + b = data->cdigtype; + else if(strcasecmp(tag, "Digest") == 0) + b = data->cdigest; + return b; +} + +/** + * XML handle character data, the data inside an element. + * @param userData: xml_data structure + * @param s: the character data. May not all be in one callback. + * NOT zero terminated. + * @param len: length of this part of the data. + */ +void +xml_charhandle(void *userData, const XML_Char *s, int len) +{ + struct xml_data* data = (struct xml_data*)userData; + BIO* b = NULL; + /* skip characters outside of elements */ + if(!data->tag) + return; + if(verb>=4) { + int i; + printf("%s%s charhandle: '", + data->use_key?"use ":"", + data->tag?data->tag:"none"); + for(i=0; itag, "Zone") == 0) { + if(BIO_write(data->czone, s, len) <= 0) { + if(verb) printf("out of memory in BIO_write\n"); + exit(0); + } + return; + } + /* only store if key is used */ + if(!data->use_key) + return; + b = xml_selectbio(data, data->tag); + if(b) { + if(BIO_write(b, s, len) <= 0) { + if(verb) printf("out of memory in BIO_write\n"); + exit(0); + } + } +} + +/** + * XML fetch value of particular attribute(by name) or NULL if not present. + * @param atts: attribute array (from xml_startelem). + * @param name: name of attribute to look for. + * @return the value or NULL. (ptr into atts). + */ +static const XML_Char* +find_att(const XML_Char **atts, XML_Char* name) +{ + int i; + for(i=0; atts[i]; i+=2) { + if(strcasecmp(atts[i], name) == 0) + return atts[i+1]; + } + return NULL; +} + +/** + * XML convert DateTime element to time_t. + * [-]CCYY-MM-DDThh:mm:ss[Z|(+|-)hh:mm] + * (with optional .ssssss fractional seconds) + * @param str: the string + * @return a time_t representation or 0 on failure. + */ +static time_t +xml_convertdate(const char* str) +{ + time_t t = 0; + struct tm tm; + const char* s; + /* for this application, ignore minus in front; + * only positive dates are expected */ + s = str; + if(s[0] == '-') s++; + memset(&tm, 0, sizeof(tm)); + /* parse initial content of the string (lots of whitespace allowed) */ + s = strptime(s, "%t%Y%t-%t%m%t-%t%d%tT%t%H%t:%t%M%t:%t%S%t", &tm); + if(!s) { + if(verb) printf("xml_convertdate parse failure %s\n", str); + return 0; + } + /* parse remainder of date string */ + if(*s == '.') { + /* optional '.' and fractional seconds */ + int frac = 0, n = 0; + if(sscanf(s+1, "%d%n", &frac, &n) < 1) { + if(verb) printf("xml_convertdate f failure %s\n", str); + return 0; + } + /* fraction is not used, time_t has second accuracy */ + s++; + s+=n; + } + if(*s == 'Z' || *s == 'z') { + /* nothing to do for this */ + s++; + } else if(*s == '+' || *s == '-') { + /* optional timezone spec: Z or +hh:mm or -hh:mm */ + int hr = 0, mn = 0, n = 0; + if(sscanf(s+1, "%d:%d%n", &hr, &mn, &n) < 2) { + if(verb) printf("xml_convertdate tz failure %s\n", str); + return 0; + } + if(*s == '+') { + tm.tm_hour += hr; + tm.tm_min += mn; + } else { + tm.tm_hour -= hr; + tm.tm_min -= mn; + } + s++; + s += n; + } + if(*s != 0) { + /* not ended properly */ + /* but ignore, (lenient) */ + } + + t = mktime(&tm); + if(t == (time_t)-1) { + if(verb) printf("xml_convertdate mktime failure\n"); + return 0; + } + return t; +} + +/** + * XML handle the KeyDigest start tag, check validity periods. + */ +static void +handle_keydigest(struct xml_data* data, const XML_Char **atts) +{ + data->use_key = 0; + if(find_att(atts, "validFrom")) { + time_t from = xml_convertdate(find_att(atts, "validFrom")); + if(from == 0) { + if(verb) printf("error: xml cannot be parsed\n"); + exit(0); + } + if(data->date < from) + return; + } + if(find_att(atts, "validUntil")) { + time_t until = xml_convertdate(find_att(atts, "validUntil")); + if(until == 0) { + if(verb) printf("error: xml cannot be parsed\n"); + exit(0); + } + if(data->date > until) + return; + } + /* yes we want to use this key */ + data->use_key = 1; + (void)BIO_reset(data->ctag); + (void)BIO_reset(data->calgo); + (void)BIO_reset(data->cdigtype); + (void)BIO_reset(data->cdigest); +} + +/** See if XML element equals the zone name */ +static int +xml_is_zone_name(BIO* zone, char* name) +{ + char buf[1024]; + char* z = NULL; + long zlen; + (void)BIO_seek(zone, 0); + zlen = BIO_get_mem_data(zone, &z); + if(!zlen || !z) return 0; + /* zero terminate */ + if(zlen >= (long)sizeof(buf)) return 0; + memmove(buf, z, (size_t)zlen); + buf[zlen] = 0; + /* compare */ + return (strncasecmp(buf, name, strlen(name)) == 0); +} + +/** + * XML start of element. This callback is called whenever an XML tag starts. + * XML_Char is UTF8. + * @param userData: the xml_data structure. + * @param name: the tag that starts. + * @param atts: array of strings, pairs of attr = value, ends with NULL. + * i.e. att[0]="att[1]" att[2]="att[3]" att[4]isNull + */ +static void +xml_startelem(void *userData, const XML_Char *name, const XML_Char **atts) +{ + struct xml_data* data = (struct xml_data*)userData; + BIO* b; + if(verb>=4) printf("xml tag start '%s'\n", name); + free(data->tag); + data->tag = strdup(name); + if(!data->tag) { + if(verb) printf("out of memory\n"); + exit(0); + } + if(verb>=4) { + int i; + for(i=0; atts[i]; i+=2) { + printf(" %s='%s'\n", atts[i], atts[i+1]); + } + } + /* handle attributes to particular types */ + if(strcasecmp(name, "KeyDigest") == 0) { + handle_keydigest(data, atts); + return; + } else if(strcasecmp(name, "Zone") == 0) { + (void)BIO_reset(data->czone); + return; + } + + /* for other types we prepare to pick up the data */ + if(!data->use_key) + return; + b = xml_selectbio(data, data->tag); + if(b) { + /* empty it */ + (void)BIO_reset(b); + } +} + +/** Append str to bio */ +static void +xml_append_str(BIO* b, const char* s) +{ + if(BIO_write(b, s, (int)strlen(s)) <= 0) { + if(verb) printf("out of memory in BIO_write\n"); + exit(0); + } +} + +/** Append bio to bio */ +static void +xml_append_bio(BIO* b, BIO* a) +{ + char* z = NULL; + long i, len; + (void)BIO_seek(a, 0); + len = BIO_get_mem_data(a, &z); + if(!len || !z) { + if(verb) printf("out of memory in BIO_write\n"); + exit(0); + } + /* remove newlines in the data here */ + for(i=0; ids, ". IN DS "); + xml_append_bio(data->ds, data->ctag); + xml_append_str(data->ds, " "); + xml_append_bio(data->ds, data->calgo); + xml_append_str(data->ds, " "); + xml_append_bio(data->ds, data->cdigtype); + xml_append_str(data->ds, " "); + xml_append_bio(data->ds, data->cdigest); + xml_append_str(data->ds, "\n"); + data->num_keys++; +} + +/** + * XML end of element. This callback is called whenever an XML tag ends. + * XML_Char is UTF8. + * @param userData: the xml_data structure + * @param name: the tag that ends. + */ +static void +xml_endelem(void *userData, const XML_Char *name) +{ + struct xml_data* data = (struct xml_data*)userData; + if(verb>=4) printf("xml tag end '%s'\n", name); + free(data->tag); + data->tag = NULL; + if(strcasecmp(name, "KeyDigest") == 0) { + if(data->use_key) + xml_append_ds(data); + data->use_key = 0; + } else if(strcasecmp(name, "Zone") == 0) { + if(!xml_is_zone_name(data->czone, ".")) { + if(verb) printf("xml not for the right zone\n"); + exit(0); + } + } +} + +/** + * XML parser setup of the callbacks for the tags + */ +static void +xml_parse_setup(XML_Parser parser, struct xml_data* data, time_t now) +{ + char buf[1024]; + memset(data, 0, sizeof(*data)); + XML_SetUserData(parser, data); + data->parser = parser; + data->date = now; + data->ds = BIO_new(BIO_s_mem()); + data->ctag = BIO_new(BIO_s_mem()); + data->czone = BIO_new(BIO_s_mem()); + data->calgo = BIO_new(BIO_s_mem()); + data->cdigtype = BIO_new(BIO_s_mem()); + data->cdigest = BIO_new(BIO_s_mem()); + if(!data->ds || !data->ctag || !data->calgo || !data->czone || + !data->cdigtype || !data->cdigest) { + if(verb) printf("out of memory\n"); + exit(0); + } + snprintf(buf, sizeof(buf), "; created by unbound-anchor on %s", + ctime(&now)); + if(BIO_write(data->ds, buf, (int)strlen(buf)) <= 0) { + if(verb) printf("out of memory\n"); + exit(0); + } + XML_SetElementHandler(parser, xml_startelem, xml_endelem); + XML_SetCharacterDataHandler(parser, xml_charhandle); +} + +/** + * Perform XML parsing of the root-anchors file + * Its format description can be read here + * https://data.iana.org/root-anchors/draft-icann-dnssec-trust-anchor.txt + * It uses libexpat. + * @param xml: BIO with xml data. + * @param now: the current time for checking DS validity periods. + * @return memoryBIO with the DS data in zone format. + * or NULL if the zone is insecure. + * (It exit()s on error) + */ +static BIO* +xml_parse(BIO* xml, time_t now) +{ + char* pp; + int len; + XML_Parser parser; + struct xml_data data; + + parser = XML_ParserCreate(NULL); + if(!parser) { + if(verb) printf("could not XML_ParserCreate\n"); + exit(0); + } + + /* setup callbacks */ + xml_parse_setup(parser, &data, now); + + /* parse it */ + (void)BIO_reset(xml); + len = (int)BIO_get_mem_data(xml, &pp); + if(!len || !pp) { + if(verb) printf("out of memory\n"); + exit(0); + } + if(!XML_Parse(parser, pp, len, 1 /*isfinal*/ )) { + const char *e = XML_ErrorString(XML_GetErrorCode(parser)); + if(verb) printf("XML_Parse failure %s\n", e?e:""); + exit(0); + } + + /* parsed */ + if(verb) printf("XML was parsed successfully, %d keys\n", + data.num_keys); + free(data.tag); + XML_ParserFree(parser); + + if(verb >= 4) { + char* pp = NULL; + int len; + (void)BIO_seek(data.ds, 0); + len = BIO_get_mem_data(data.ds, &pp); + printf("got DS bio %d: '", len); + if(!fwrite(pp, (size_t)len, 1, stdout)) + /* compilers do not allow us to ignore fwrite .. */ + fprintf(stderr, "error writing to stdout\n"); + printf("'\n"); + } + BIO_free(data.czone); + BIO_free(data.ctag); + BIO_free(data.calgo); + BIO_free(data.cdigtype); + BIO_free(data.cdigest); + + if(data.num_keys == 0) { + /* the root zone seems to have gone insecure */ + BIO_free(data.ds); + return NULL; + } else { + return data.ds; + } +} + +/** verify a PKCS7 signature, false on failure */ +static int +verify_p7sig(BIO* data, BIO* p7s, STACK_OF(X509)* trust) +{ + PKCS7* p7; + X509_STORE *store = X509_STORE_new(); + int secure = 0; + int i; +#ifdef X509_V_FLAG_CHECK_SS_SIGNATURE + X509_VERIFY_PARAM* param = X509_VERIFY_PARAM_new(); + if(!param) { + if(verb) printf("out of memory\n"); + X509_STORE_free(store); + return 0; + } + /* do the selfcheck on the root certificate; it checks that the + * input is valid */ + X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CHECK_SS_SIGNATURE); + if(store) X509_STORE_set1_param(store, param); +#endif + if(!store) { + if(verb) printf("out of memory\n"); +#ifdef X509_V_FLAG_CHECK_SS_SIGNATURE + X509_VERIFY_PARAM_free(param); +#endif + return 0; + } + + (void)BIO_reset(p7s); + (void)BIO_reset(data); + + /* convert p7s to p7 (the signature) */ + p7 = d2i_PKCS7_bio(p7s, NULL); + if(!p7) { + if(verb) printf("could not parse p7s signature file\n"); + X509_STORE_free(store); + return 0; + } + if(verb >= 2) printf("parsed the PKCS7 signature\n"); + + /* convert trust to trusted certificate store */ + for(i=0; i= 2) printf("setup the X509_STORE\n"); + + if(PKCS7_verify(p7, NULL, store, data, NULL, 0) == 1) { + secure = 1; + if(verb) printf("the PKCS7 signature verified\n"); + } else { + if(verb) { + ERR_print_errors_fp(stdout); + } + } + + X509_STORE_free(store); + PKCS7_free(p7); + return secure; +} + +/** write unsigned root anchor file, a 5011 revoked tp */ +static void +write_unsigned_root(char* root_anchor_file) +{ + FILE* out; + time_t now = time(NULL); + out = fopen(root_anchor_file, "w"); + if(!out) { + if(verb) printf("%s: %s\n", root_anchor_file, strerror(errno)); + return; + } + if(fprintf(out, "; autotrust trust anchor file\n" + ";;REVOKED\n" + ";;id: . 1\n" + "; This file was written by unbound-anchor on %s" + "; It indicates that the root does not use DNSSEC\n" + "; to restart DNSSEC overwrite this file with a\n" + "; valid trustanchor or (empty-it and run unbound-anchor)\n" + , ctime(&now)) < 0) { + if(verb) printf("failed to write 'unsigned' to %s\n", + root_anchor_file); + if(verb && errno != 0) printf("%s\n", strerror(errno)); + } + fclose(out); +} + +/** write root anchor file */ +static void +write_root_anchor(char* root_anchor_file, BIO* ds) +{ + char* pp = NULL; + int len; + FILE* out; + (void)BIO_seek(ds, 0); + len = BIO_get_mem_data(ds, &pp); + if(!len || !pp) { + if(verb) printf("out of memory\n"); + return; + } + out = fopen(root_anchor_file, "w"); + if(!out) { + if(verb) printf("%s: %s\n", root_anchor_file, strerror(errno)); + return; + } + if(fwrite(pp, (size_t)len, 1, out) != 1) { + if(verb) printf("failed to write all data to %s\n", + root_anchor_file); + if(verb && errno != 0) printf("%s\n", strerror(errno)); + } + fclose(out); +} + +/** Perform the verification and update of the trustanchor file */ +static void +verify_and_update_anchor(char* root_anchor_file, BIO* xml, BIO* p7s, + STACK_OF(X509)* cert) +{ + BIO* ds; + + /* verify xml file */ + if(!verify_p7sig(xml, p7s, cert)) { + printf("the PKCS7 signature failed\n"); + exit(0); + } + + /* parse the xml file into DS records */ + ds = xml_parse(xml, time(NULL)); + if(!ds) { + /* the root zone is unsigned now */ + write_unsigned_root(root_anchor_file); + } else { + /* reinstate 5011 tracking */ + write_root_anchor(root_anchor_file, ds); + } + BIO_free(ds); +} + +#ifdef USE_WINSOCK +static void do_wsa_cleanup(void) { WSACleanup(); } +#endif + +/** perform actual certupdate work */ +static int +do_certupdate(char* root_anchor_file, char* root_cert_file, + char* urlname, char* xmlname, char* p7sname, + char* res_conf, char* root_hints, char* debugconf, + int ip4only, int ip6only, int port, struct ub_result* dnskey) +{ + STACK_OF(X509)* cert; + BIO *xml, *p7s; + struct ip_list* ip_list = NULL; + + /* read pem file or provide builtin */ + cert = read_cert_or_builtin(root_cert_file); + + /* lookup A, AAAA for the urlname (or parse urlname if IP address) */ + ip_list = resolve_name(urlname, port, res_conf, root_hints, debugconf, + ip4only, ip6only); + +#ifdef USE_WINSOCK + if(1) { /* libunbound finished, startup WSA for the https connection */ + WSADATA wsa_data; + int r; + if((r = WSAStartup(MAKEWORD(2,2), &wsa_data)) != 0) { + if(verb) printf("WSAStartup failed: %s\n", + wsa_strerror(r)); + exit(0); + } + atexit(&do_wsa_cleanup); + } +#endif + + /* fetch the necessary files over HTTPS */ + xml = https(ip_list, xmlname, urlname); + p7s = https(ip_list, p7sname, urlname); + + /* verify and update the root anchor */ + verify_and_update_anchor(root_anchor_file, xml, p7s, cert); + if(verb) printf("success: the anchor has been updated " + "using the cert\n"); + + free_file_bio(xml); + free_file_bio(p7s); +#ifndef S_SPLINT_S + sk_X509_pop_free(cert, X509_free); +#endif + ub_resolve_free(dnskey); + ip_list_free(ip_list); + return 1; +} + +/** + * Try to read the root RFC5011 autotrust anchor file, + * @param file: filename. + * @return: + * 0 if does not exist or empty + * 1 if trust-point-revoked-5011 + * 2 if it is OK. + */ +static int +try_read_anchor(char* file) +{ + int empty = 1; + char line[10240]; + char* p; + FILE* in = fopen(file, "r"); + if(!in) { + /* only if the file does not exist, can we fix it */ + if(errno != ENOENT) { + if(verb) printf("%s: %s\n", file, strerror(errno)); + if(verb) printf("error: cannot access the file\n"); + exit(0); + } + if(verb) printf("%s does not exist\n", file); + return 0; + } + while(fgets(line, (int)sizeof(line), in)) { + line[sizeof(line)-1] = 0; + if(strncmp(line, ";;REVOKED", 9) == 0) { + fclose(in); + if(verb) printf("%s : the trust point is revoked\n" + "and the zone is considered unsigned.\n" + "if you wish to re-enable, delete the file\n", + file); + return 1; + } + p=line; + while(*p == ' ' || *p == '\t') + p++; + if(p[0]==0 || p[0]=='\n' || p[0]==';') continue; + /* this line is a line of content */ + empty = 0; + } + fclose(in); + if(empty) { + if(verb) printf("%s is empty\n", file); + return 0; + } + if(verb) printf("%s has content\n", file); + return 2; +} + +/** Write the builtin root anchor to a file */ +static void +write_builtin_anchor(char* file) +{ + const char* builtin_root_anchor = get_builtin_ds(); + FILE* out = fopen(file, "w"); + if(!out) { + if(verb) printf("%s: %s\n", file, strerror(errno)); + if(verb) printf(" could not write builtin anchor\n"); + return; + } + if(!fwrite(builtin_root_anchor, strlen(builtin_root_anchor), 1, out)) { + if(verb) printf("%s: %s\n", file, strerror(errno)); + if(verb) printf(" could not complete write builtin anchor\n"); + } + fclose(out); +} + +/** + * Check the root anchor file. + * If does not exist, provide builtin and write file. + * If empty, provide builtin and write file. + * If trust-point-revoked-5011 file: make the program exit. + * @param root_anchor_file: filename of the root anchor. + * @param used_builtin: set to 1 if the builtin is written. + * @return 0 if trustpoint is insecure, 1 on success. Exit on failure. + */ +static int +provide_builtin(char* root_anchor_file, int* used_builtin) +{ + /* try to read it */ + switch(try_read_anchor(root_anchor_file)) + { + case 0: /* no exist or empty */ + write_builtin_anchor(root_anchor_file); + *used_builtin = 1; + break; + case 1: /* revoked tp */ + return 0; + case 2: /* it is fine */ + default: + break; + } + return 1; +} + +/** + * add an autotrust anchor for the root to the context + */ +static void +add_5011_probe_root(struct ub_ctx* ctx, char* root_anchor_file) +{ + int r; + r = ub_ctx_set_option(ctx, "auto-trust-anchor-file:", root_anchor_file); + if(r) { + if(verb) printf("add 5011 probe to ctx: %s\n", ub_strerror(r)); + ub_ctx_delete(ctx); + exit(0); + } +} + +/** + * Prime the root key and return the result. Exit on error. + * @param ctx: the unbound context to perform the priming with. + * @return: the result of the prime, on error it exit()s. + */ +static struct ub_result* +prime_root_key(struct ub_ctx* ctx) +{ + struct ub_result* res = NULL; + int r; + r = ub_resolve(ctx, ".", LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN, &res); + if(r) { + if(verb) printf("resolve DNSKEY: %s\n", ub_strerror(r)); + ub_ctx_delete(ctx); + exit(0); + } + if(!res) { + if(verb) printf("out of memory\n"); + ub_ctx_delete(ctx); + exit(0); + } + return res; +} + +/** see if ADDPEND keys exist in autotrust file (if possible) */ +static int +read_if_pending_keys(char* file) +{ + FILE* in = fopen(file, "r"); + char line[8192]; + if(!in) { + if(verb>=2) printf("%s: %s\n", file, strerror(errno)); + return 0; + } + while(fgets(line, (int)sizeof(line), in)) { + if(line[0]==';') continue; + if(strstr(line, "[ ADDPEND ]")) { + fclose(in); + if(verb) printf("RFC5011-state has ADDPEND keys\n"); + return 1; + } + } + fclose(in); + return 0; +} + +/** read last successful probe time from autotrust file (if possible) */ +static int32_t +read_last_success_time(char* file) +{ + FILE* in = fopen(file, "r"); + char line[1024]; + if(!in) { + if(verb) printf("%s: %s\n", file, strerror(errno)); + return 0; + } + while(fgets(line, (int)sizeof(line), in)) { + if(strncmp(line, ";;last_success: ", 16) == 0) { + char* e; + time_t x = (unsigned int)strtol(line+16, &e, 10); + fclose(in); + if(line+16 == e) { + if(verb) printf("failed to parse " + "last_success probe time\n"); + return 0; + } + if(verb) printf("last successful probe: %s", ctime(&x)); + return (int32_t)x; + } + } + fclose(in); + if(verb) printf("no last_success probe time in anchor file\n"); + return 0; +} + +/** + * Read autotrust 5011 probe file and see if the date + * compared to the current date allows a certupdate. + * If the last successful probe was recent then 5011 cannot be behind, + * and the failure cannot be solved with a certupdate. + * The debugconf is to validation-override the date for testing. + * @param root_anchor_file: filename of root key + * @return true if certupdate is ok. + */ +static int +probe_date_allows_certupdate(char* root_anchor_file) +{ + int has_pending_keys = read_if_pending_keys(root_anchor_file); + int32_t last_success = read_last_success_time(root_anchor_file); + int32_t now = (int32_t)time(NULL); + int32_t leeway = 30 * 24 * 3600; /* 30 days leeway */ + /* if the date is before 2010-07-15:00.00.00 then the root has not + * been signed yet, and thus we refuse to take action. */ + if(time(NULL) < xml_convertdate("2010-07-15T00:00:00")) { + if(verb) printf("the date is before the root was first signed," + " please correct the clock\n"); + return 0; + } + if(last_success == 0) + return 1; /* no probe time */ + if(has_pending_keys) + return 1; /* key in ADDPEND state, a previous probe has + inserted that, and it was present in all recent probes, + but it has not become active. The 30 day timer may not have + expired, but we know(for sure) there is a rollover going on. + If we only managed to pickup the new key on its last day + of announcement (for example) this can happen. */ + if(now - last_success < 0) { + if(verb) printf("the last successful probe is in the future," + " clock was modified\n"); + return 0; + } + if(now - last_success >= leeway) { + if(verb) printf("the last successful probe was more than 30 " + "days ago\n"); + return 1; + } + if(verb) printf("the last successful probe is recent\n"); + return 0; +} + +/** perform the unbound-anchor work */ +static int +do_root_update_work(char* root_anchor_file, char* root_cert_file, + char* urlname, char* xmlname, char* p7sname, + char* res_conf, char* root_hints, char* debugconf, + int ip4only, int ip6only, int force, int port) +{ + struct ub_ctx* ctx; + struct ub_result* dnskey; + int used_builtin = 0; + + /* see if builtin rootanchor needs to be provided, or if + * rootanchor is 'revoked-trust-point' */ + if(!provide_builtin(root_anchor_file, &used_builtin)) + return 0; + + /* make unbound context with 5011-probe for root anchor, + * and probe . DNSKEY */ + ctx = create_unbound_context(res_conf, root_hints, debugconf, + ip4only, ip6only); + add_5011_probe_root(ctx, root_anchor_file); + dnskey = prime_root_key(ctx); + ub_ctx_delete(ctx); + + /* if secure: exit */ + if(dnskey->secure && !force) { + if(verb) printf("success: the anchor is ok\n"); + ub_resolve_free(dnskey); + return used_builtin; + } + if(force && verb) printf("debug cert update forced\n"); + + /* if not (and NOERROR): check date and do certupdate */ + if((dnskey->rcode == 0 && + probe_date_allows_certupdate(root_anchor_file)) || force) { + if(do_certupdate(root_anchor_file, root_cert_file, urlname, + xmlname, p7sname, res_conf, root_hints, debugconf, + ip4only, ip6only, port, dnskey)) + return 1; + return used_builtin; + } + if(verb) printf("fail: the anchor is NOT ok and could not be fixed\n"); + ub_resolve_free(dnskey); + return used_builtin; +} + +/** getopt global, in case header files fail to declare it. */ +extern int optind; +/** getopt global, in case header files fail to declare it. */ +extern char* optarg; + +/** Main routine for unbound-anchor */ +int main(int argc, char* argv[]) +{ + int c; + char* root_anchor_file = ROOT_ANCHOR_FILE; + char* root_cert_file = ROOT_CERT_FILE; + char* urlname = URLNAME; + char* xmlname = XMLNAME; + char* p7sname = P7SNAME; + char* res_conf = NULL; + char* root_hints = NULL; + char* debugconf = NULL; + int dolist=0, ip4only=0, ip6only=0, force=0, port = HTTPS_PORT; + /* parse the options */ + while( (c=getopt(argc, argv, "46C:FP:a:c:f:hlr:s:u:vx:")) != -1) { + switch(c) { + case 'l': + dolist = 1; + break; + case '4': + ip4only = 1; + break; + case '6': + ip6only = 1; + break; + case 'a': + root_anchor_file = optarg; + break; + case 'c': + root_cert_file = optarg; + break; + case 'u': + urlname = optarg; + break; + case 'x': + xmlname = optarg; + break; + case 's': + p7sname = optarg; + break; + case 'f': + res_conf = optarg; + break; + case 'r': + root_hints = optarg; + break; + case 'C': + debugconf = optarg; + break; + case 'F': + force = 1; + break; + case 'P': + port = atoi(optarg); + break; + case 'v': + verb++; + break; + case '?': + case 'h': + default: + usage(); + } + } + argc -= optind; + argv += optind; + if(argc != 0) + usage(); + + ERR_load_crypto_strings(); + ERR_load_SSL_strings(); + OpenSSL_add_all_algorithms(); + (void)SSL_library_init(); + + if(dolist) do_list_builtin(); + + return do_root_update_work(root_anchor_file, root_cert_file, urlname, + xmlname, p7sname, res_conf, root_hints, debugconf, ip4only, + ip6only, force, port); +} diff --git a/smallapp/unbound-checkconf.c b/smallapp/unbound-checkconf.c new file mode 100644 index 00000000000..c73d8bdc7c9 --- /dev/null +++ b/smallapp/unbound-checkconf.c @@ -0,0 +1,517 @@ +/* + * checkconf/unbound-checkconf.c - config file checker for unbound.conf file. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * The config checker checks for syntax and other errors in the unbound.conf + * file, and can be used to check for errors before the server is started + * or sigHUPped. + * Exit status 1 means an error. + */ + +#include "config.h" +#include "util/log.h" +#include "util/config_file.h" +#include "util/module.h" +#include "util/net_help.h" +#include "util/regional.h" +#include "iterator/iterator.h" +#include "iterator/iter_fwd.h" +#include "iterator/iter_hints.h" +#include "validator/validator.h" +#include "services/localzone.h" +#ifdef HAVE_GETOPT_H +#include +#endif +#ifdef HAVE_PWD_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_GLOB_H +#include +#endif +#ifdef WITH_PYTHONMODULE +#include "pythonmod/pythonmod.h" +#endif + +/** Give checkconf usage, and exit (1). */ +static void +usage() +{ + printf("Usage: unbound-checkconf [file]\n"); + printf(" Checks unbound configuration file for errors.\n"); + printf("file if omitted %s is used.\n", CONFIGFILE); + printf("-o option print value of option to stdout.\n"); + printf("-h show this usage help.\n"); + 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); +} + +/** + * Print given option to stdout + * @param cfg: config + * @param opt: option name without trailing :. + * This is different from config_set_option. + */ +static void +print_option(struct config_file* cfg, const char* opt) +{ + if(!config_get_option(cfg, opt, config_print_func, stdout)) + fatal_exit("cannot print option '%s'", opt); +} + +/** check if module works with config */ +static void +check_mod(struct config_file* cfg, struct module_func_block* fb) +{ + struct module_env env; + memset(&env, 0, sizeof(env)); + env.cfg = cfg; + env.scratch = regional_create(); + env.scratch_buffer = ldns_buffer_new(BUFSIZ); + if(!env.scratch || !env.scratch_buffer) + fatal_exit("out of memory"); + if(!(*fb->init)(&env, 0)) { + fatal_exit("bad config for %s module", fb->name); + } + (*fb->deinit)(&env, 0); + ldns_buffer_free(env.scratch_buffer); + regional_destroy(env.scratch); +} + +/** check localzones */ +static void +localzonechecks(struct config_file* cfg) +{ + struct local_zones* zs; + if(!(zs = local_zones_create())) + fatal_exit("out of memory"); + if(!local_zones_apply_cfg(zs, cfg)) + fatal_exit("failed local-zone, local-data configuration"); + local_zones_delete(zs); +} + +/** emit warnings for IP in hosts */ +static void +warn_hosts(const char* typ, struct config_stub* list) +{ + struct sockaddr_storage a; + socklen_t alen; + struct config_stub* s; + struct config_strlist* h; + for(s=list; s; s=s->next) { + for(h=s->hosts; h; h=h->next) { + if(extstrtoaddr(h->str, &a, &alen)) { + fprintf(stderr, "unbound-checkconf: warning:" + " %s %s: \"%s\" is an IP%s address, " + "and when looked up as a host name " + "during use may not resolve.\n", + s->name, typ, h->str, + addr_is_ip6(&a, alen)?"6":"4"); + } + } + } +} + +/** check interface strings */ +static void +interfacechecks(struct config_file* cfg) +{ + struct sockaddr_storage a; + socklen_t alen; + int i, j; + for(i=0; inum_ifs; i++) { + if(!extstrtoaddr(cfg->ifs[i], &a, &alen)) { + fatal_exit("cannot parse interface specified as '%s'", + cfg->ifs[i]); + } + for(j=0; jnum_ifs; j++) { + if(i!=j && strcmp(cfg->ifs[i], cfg->ifs[j])==0) + fatal_exit("interface: %s present twice, " + "cannot bind same ports twice.", + cfg->ifs[i]); + } + } + for(i=0; inum_out_ifs; i++) { + if(!ipstrtoaddr(cfg->out_ifs[i], UNBOUND_DNS_PORT, + &a, &alen)) { + fatal_exit("cannot parse outgoing-interface " + "specified as '%s'", cfg->out_ifs[i]); + } + for(j=0; jnum_out_ifs; j++) { + if(i!=j && strcmp(cfg->out_ifs[i], cfg->out_ifs[j])==0) + fatal_exit("outgoing-interface: %s present " + "twice, cannot bind same ports twice.", + cfg->out_ifs[i]); + } + } +} + +/** check acl ips */ +static void +aclchecks(struct config_file* cfg) +{ + int d; + struct sockaddr_storage a; + socklen_t alen; + struct config_str2list* acl; + for(acl=cfg->acls; acl; acl = acl->next) { + if(!netblockstrtoaddr(acl->str, UNBOUND_DNS_PORT, &a, &alen, + &d)) { + fatal_exit("cannot parse access control address %s %s", + acl->str, acl->str2); + } + } +} + +/** true if fname is a file */ +static int +is_file(const char* fname) +{ + struct stat buf; + if(stat(fname, &buf) < 0) { + if(errno==EACCES) { + printf("warning: no search permission for one of the directories in path: %s\n", fname); + return 1; + } + perror(fname); + return 0; + } + if(S_ISDIR(buf.st_mode)) { + printf("%s is not a file\n", fname); + return 0; + } + return 1; +} + +/** true if fname is a directory */ +static int +is_dir(const char* fname) +{ + struct stat buf; + if(stat(fname, &buf) < 0) { + if(errno==EACCES) { + printf("warning: no search permission for one of the directories in path: %s\n", fname); + return 1; + } + perror(fname); + return 0; + } + if(!(S_ISDIR(buf.st_mode))) { + printf("%s is not a directory\n", fname); + return 0; + } + return 1; +} + +/** get base dir of a fname */ +static char* +basedir(char* fname) +{ + char* rev; + if(!fname) fatal_exit("out of memory"); + rev = strrchr(fname, '/'); + if(!rev) return NULL; + if(fname == rev) return NULL; + rev[0] = 0; + return fname; +} + +/** check chroot for a file string */ +static void +check_chroot_string(const char* desc, char** ss, + const char* chrootdir, struct config_file* cfg) +{ + char* str = *ss; + if(str && str[0]) { + *ss = fname_after_chroot(str, cfg, 1); + if(!*ss) fatal_exit("out of memory"); + if(!is_file(*ss)) { + if(chrootdir && chrootdir[0]) + fatal_exit("%s: \"%s\" does not exist in " + "chrootdir %s", desc, str, chrootdir); + else + fatal_exit("%s: \"%s\" does not exist", + desc, str); + } + /* put in a new full path for continued checking */ + free(str); + } +} + +/** check file list, every file must be inside the chroot location */ +static void +check_chroot_filelist(const char* desc, struct config_strlist* list, + const char* chrootdir, struct config_file* cfg) +{ + struct config_strlist* p; + for(p=list; p; p=p->next) { + check_chroot_string(desc, &p->str, chrootdir, cfg); + } +} + +/** check file list, with wildcard processing */ +static void +check_chroot_filelist_wild(const char* desc, struct config_strlist* list, + const char* chrootdir, struct config_file* cfg) +{ + struct config_strlist* p; + for(p=list; p; p=p->next) { +#ifdef HAVE_GLOB + if(strchr(p->str, '*') || strchr(p->str, '[') || + strchr(p->str, '?') || strchr(p->str, '{') || + strchr(p->str, '~')) { + char* s = p->str; + /* adjust whole pattern for chroot and check later */ + p->str = fname_after_chroot(p->str, cfg, 1); + free(s); + } else +#endif /* HAVE_GLOB */ + check_chroot_string(desc, &p->str, chrootdir, cfg); + } +} + +/** check configuration for errors */ +static void +morechecks(struct config_file* cfg, const char* fname) +{ + warn_hosts("stub-host", cfg->stubs); + warn_hosts("forward-host", cfg->forwards); + interfacechecks(cfg); + aclchecks(cfg); + + if(cfg->verbosity < 0) + fatal_exit("verbosity value < 0"); + if(cfg->num_threads <= 0 || cfg->num_threads > 10000) + 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_udp && !cfg->do_tcp) + fatal_exit("udp and tcp are both disabled, pointless"); + if(cfg->edns_buffer_size > cfg->msg_buffer_size) + fatal_exit("edns-buffer-size larger than msg-buffer-size, " + "answers will not fit in processing buffer"); + + if(cfg->chrootdir && cfg->chrootdir[0] && + cfg->chrootdir[strlen(cfg->chrootdir)-1] == '/') + fatal_exit("chootdir %s has trailing slash '/' please remove.", + cfg->chrootdir); + if(cfg->chrootdir && cfg->chrootdir[0] && + !is_dir(cfg->chrootdir)) { + fatal_exit("bad chroot directory"); + } + if(cfg->chrootdir && cfg->chrootdir[0]) { + char buf[10240]; + buf[0] = 0; + if(fname[0] != '/') { + if(getcwd(buf, sizeof(buf)) == NULL) + fatal_exit("getcwd: %s", strerror(errno)); + strncat(buf, "/", sizeof(buf)-strlen(buf)-1); + } + strncat(buf, fname, sizeof(buf)-strlen(buf)-1); + if(strncmp(buf, cfg->chrootdir, strlen(cfg->chrootdir)) != 0) + fatal_exit("config file %s is not inside chroot %s", + buf, cfg->chrootdir); + } + if(cfg->directory && cfg->directory[0]) { + char* ad = fname_after_chroot(cfg->directory, cfg, 0); + if(!ad) fatal_exit("out of memory"); + if(!is_dir(ad)) fatal_exit("bad chdir directory"); + free(ad); + } + if( (cfg->chrootdir && cfg->chrootdir[0]) || + (cfg->directory && cfg->directory[0])) { + if(cfg->pidfile && cfg->pidfile[0]) { + char* ad = (cfg->pidfile[0]=='/')?strdup(cfg->pidfile): + fname_after_chroot(cfg->pidfile, cfg, 1); + char* bd = basedir(ad); + if(bd && !is_dir(bd)) + fatal_exit("pidfile directory does not exist"); + free(ad); + } + if(cfg->logfile && cfg->logfile[0]) { + char* ad = fname_after_chroot(cfg->logfile, cfg, 1); + char* bd = basedir(ad); + if(bd && !is_dir(bd)) + fatal_exit("logfile directory does not exist"); + free(ad); + } + } + + check_chroot_filelist("file with root-hints", + cfg->root_hints, cfg->chrootdir, cfg); + check_chroot_filelist("trust-anchor-file", + cfg->trust_anchor_file_list, cfg->chrootdir, cfg); + check_chroot_filelist("auto-trust-anchor-file", + cfg->auto_trust_anchor_file_list, cfg->chrootdir, cfg); + check_chroot_filelist_wild("trusted-keys-file", + cfg->trusted_keys_file_list, cfg->chrootdir, cfg); + check_chroot_string("dlv-anchor-file", &cfg->dlv_anchor_file, + cfg->chrootdir, cfg); + /* remove chroot setting so that modules are not stripping pathnames*/ + free(cfg->chrootdir); + cfg->chrootdir = NULL; + + if(strcmp(cfg->module_conf, "iterator") != 0 + && strcmp(cfg->module_conf, "validator iterator") != 0 +#ifdef WITH_PYTHONMODULE + && strcmp(cfg->module_conf, "python iterator") != 0 + && strcmp(cfg->module_conf, "python validator iterator") != 0 + && strcmp(cfg->module_conf, "validator python iterator") != 0 +#endif + ) { + fatal_exit("module conf '%s' is not known to work", + cfg->module_conf); + } + +#ifdef HAVE_GETPWNAM + if(cfg->username && cfg->username[0]) { + if(getpwnam(cfg->username) == NULL) + fatal_exit("user '%s' does not exist.", cfg->username); + endpwent(); + } +#endif + if(cfg->remote_control_enable) { + check_chroot_string("server-key-file", &cfg->server_key_file, + cfg->chrootdir, cfg); + check_chroot_string("server-cert-file", &cfg->server_cert_file, + cfg->chrootdir, cfg); + if(!is_file(cfg->control_key_file)) + fatal_exit("control-key-file: \"%s\" does not exist", + cfg->control_key_file); + if(!is_file(cfg->control_cert_file)) + fatal_exit("control-cert-file: \"%s\" does not exist", + cfg->control_cert_file); + } + + localzonechecks(cfg); +} + +/** check forwards */ +static void +check_fwd(struct config_file* cfg) +{ + struct iter_forwards* fwd = forwards_create(); + if(!fwd || !forwards_apply_cfg(fwd, cfg)) { + fatal_exit("Could not set forward zones"); + } + forwards_delete(fwd); +} + +/** check hints */ +static void +check_hints(struct config_file* cfg) +{ + struct iter_hints* hints = hints_create(); + if(!hints || !hints_apply_cfg(hints, cfg)) { + fatal_exit("Could not set root or stub hints"); + } + hints_delete(hints); +} + +/** check config file */ +static void +checkconf(const char* cfgfile, const char* opt) +{ + struct config_file* cfg = config_create(); + if(!cfg) + fatal_exit("out of memory"); + if(!config_read(cfg, cfgfile, NULL)) { + /* config_read prints messages to stderr */ + config_delete(cfg); + exit(1); + } + morechecks(cfg, cfgfile); + check_mod(cfg, iter_get_funcblock()); + check_mod(cfg, val_get_funcblock()); +#ifdef WITH_PYTHONMODULE + if(strstr(cfg->module_conf, "python")) + check_mod(cfg, pythonmod_get_funcblock()); +#endif + check_fwd(cfg); + check_hints(cfg); + if(opt) print_option(cfg, opt); + else printf("unbound-checkconf: no errors in %s\n", cfgfile); + config_delete(cfg); +} + +/** getopt global, in case header files fail to declare it. */ +extern int optind; +/** getopt global, in case header files fail to declare it. */ +extern char* optarg; + +/** Main routine for checkconf */ +int main(int argc, char* argv[]) +{ + int c; + const char* f; + const char* opt = NULL; + const char* cfgfile = CONFIGFILE; + log_ident_set("unbound-checkconf"); + log_init(NULL, 0, NULL); + checklock_start(); +#ifdef USE_WINSOCK + /* use registry config file in preference to compiletime location */ + if(!(cfgfile=w_lookup_reg_str("Software\\Unbound", "ConfigFile"))) + cfgfile = CONFIGFILE; +#endif /* USE_WINSOCK */ + /* parse the options */ + while( (c=getopt(argc, argv, "ho:")) != -1) { + switch(c) { + case 'o': + opt = optarg; + break; + case '?': + case 'h': + default: + usage(); + } + } + argc -= optind; + argv += optind; + if(argc != 0 && argc != 1) + usage(); + if(argc == 1) + f = argv[0]; + else f = cfgfile; + checkconf(f, opt); + checklock_stop(); + return 0; +} diff --git a/smallapp/unbound-control-setup.sh b/smallapp/unbound-control-setup.sh new file mode 100755 index 00000000000..aca62ac8cdf --- /dev/null +++ b/smallapp/unbound-control-setup.sh @@ -0,0 +1,162 @@ +#!/bin/sh +# +# unbound-control-setup.sh - set up SSL certificates for unbound-control +# +# Copyright (c) 2008, 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 REGENTS OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +# settings: + +# directory for files +DESTDIR=/usr/local/etc/unbound + +# issuer and subject name for certificates +SERVERNAME=unbound +CLIENTNAME=unbound-control + +# validity period for certificates +DAYS=7200 + +# size of keys in bits +BITS=1536 + +# hash algorithm +HASH=sha256 + +# base name for unbound server keys +SVR_BASE=unbound_server + +# base name for unbound-control keys +CTL_BASE=unbound_control + +# we want -rw-r--- access (say you run this as root: grp=yes (server), all=no). +umask 0026 + +# end of options + +# functions: +error ( ) { + echo "$0 fatal error: $1" + exit 1 +} + +# check arguments: +while test $# -ne 0; do + case $1 in + -d) + if test $# -eq 1; then error "need argument for -d"; fi + DESTDIR="$2" + shift + ;; + *) + echo "unbound-control-setup.sh - setup SSL keys for unbound-control" + echo " -d dir use directory to store keys and certificates." + echo " default: $DESTDIR" + echo "please run this command using the same user id that the " + echo "unbound daemon uses, it needs read privileges." + exit 1 + ;; + esac + shift +done + +# go!: +echo "setup in directory $DESTDIR" +cd "$DESTDIR" || error "could not cd to $DESTDIR" + +# create certificate keys; do not recreate if they already exist. +if test -f $SVR_BASE.key; then + echo "$SVR_BASE.key exists" +else + echo "generating $SVR_BASE.key" + openssl genrsa -out $SVR_BASE.key $BITS || error "could not genrsa" +fi +if test -f $CTL_BASE.key; then + echo "$CTL_BASE.key exists" +else + echo "generating $CTL_BASE.key" + openssl genrsa -out $CTL_BASE.key $BITS || error "could not genrsa" +fi + +# create self-signed cert for server +cat >request.cfg <request.cfg < +#endif +#ifdef HAVE_OPENSSL_SSL_H +#include +#endif +#ifdef HAVE_OPENSSL_ERR_H +#include +#endif +#ifdef HAVE_OPENSSL_RAND_H +#include +#endif +#include "util/log.h" +#include "util/config_file.h" +#include "util/locks.h" +#include "util/net_help.h" + +/** Give unbound-control usage, and exit (1). */ +static void +usage() +{ + printf("Usage: unbound-control [options] command\n"); + printf(" Remote control utility for unbound server.\n"); + printf("Options:\n"); + printf(" -c file config file, default is %s\n", CONFIGFILE); + printf(" -s ip[@port] server address, if omitted config is used.\n"); + printf(" -h show this usage help.\n"); + printf("Commands:\n"); + printf(" start start server; runs unbound(8)\n"); + printf(" stop stops the server\n"); + printf(" reload reloads the server\n"); + printf(" (this flushes data, stats, requestlist)\n"); + printf(" stats print statistics\n"); + printf(" stats_noreset peek at statistics\n"); + printf(" status display status of server\n"); + printf(" verbosity change logging detail\n"); + printf(" log_reopen close and open the logfile\n"); + printf(" local_zone add new local zone\n"); + printf(" local_zone_remove remove local zone and its contents\n"); + printf(" local_data add local data, for example\n"); + printf(" local_data www.example.com A 192.0.2.1\n"); + printf(" local_data_remove remove local RR data from name\n"); + printf(" dump_cache print cache to stdout\n"); + printf(" load_cache load cache from stdin\n"); + printf(" lookup print nameservers for name\n"); + printf(" flush flushes common types for name from cache\n"); + printf(" types: A, AAAA, MX, PTR, NS,\n"); + printf(" SOA, CNAME, DNAME, SRV, NAPTR\n"); + printf(" flush_type flush name, type from cache\n"); + printf(" flush_zone flush everything at or under name\n"); + printf(" from rr and dnssec caches\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(" 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"); + printf(" get_option opt get option value\n"); + printf(" list_stubs list stub-zones and root hints in use\n"); + printf(" list_forwards list forward-zones in use\n"); + printf(" list_local_zones list local-zones in use\n"); + printf(" list_local_data list local-data RRs in use\n"); + printf(" forward_add [+i] zone addr.. add forward-zone with servers\n"); + printf(" forward_remove [+i] zone remove forward zone\n"); + printf(" stub_add [+ip] zone addr.. add stub-zone with servers\n"); + printf(" stub_remove [+i] zone remove stub zone\n"); + printf(" +i also do dnssec insecure point\n"); + printf(" +p set stub to use priming\n"); + printf(" forward [off | addr ...] without arg show forward setup\n"); + printf(" or off to turn off root forwarding\n"); + printf(" or give list of ip addresses\n"); + 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 with ssl error */ +static void ssl_err(const char* s) +{ + fprintf(stderr, "error: %s\n", s); + ERR_print_errors_fp(stderr); + exit(1); +} + +/** setup SSL context */ +static SSL_CTX* +setup_ctx(struct config_file* cfg) +{ + char* s_cert, *c_key, *c_cert; + SSL_CTX* ctx; + + s_cert = fname_after_chroot(cfg->server_cert_file, cfg, 1); + c_key = fname_after_chroot(cfg->control_key_file, cfg, 1); + c_cert = fname_after_chroot(cfg->control_cert_file, cfg, 1); + if(!s_cert || !c_key || !c_cert) + fatal_exit("out of memory"); + ctx = SSL_CTX_new(SSLv23_client_method()); + if(!ctx) + ssl_err("could not allocate SSL_CTX pointer"); + if(!(SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)) + ssl_err("could not set SSL_OP_NO_SSLv2"); + if(!SSL_CTX_use_certificate_file(ctx,c_cert,SSL_FILETYPE_PEM) || + !SSL_CTX_use_PrivateKey_file(ctx,c_key,SSL_FILETYPE_PEM) + || !SSL_CTX_check_private_key(ctx)) + ssl_err("Error setting up SSL_CTX client key and cert"); + if (SSL_CTX_load_verify_locations(ctx, s_cert, NULL) != 1) + ssl_err("Error setting up SSL_CTX verify, server cert"); + SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); + + free(s_cert); + free(c_key); + free(c_cert); + return ctx; +} + +/** contact the server with TCP connect */ +static int +contact_server(const char* svr, struct config_file* cfg, int statuscmd) +{ + struct sockaddr_storage addr; + socklen_t addrlen; + int fd; + /* use svr or the first config entry */ + if(!svr) { + if(cfg->control_ifs) + svr = cfg->control_ifs->str; + else svr = "127.0.0.1"; + /* config 0 addr (everything), means ask localhost */ + if(strcmp(svr, "0.0.0.0") == 0) + svr = "127.0.0.1"; + else if(strcmp(svr, "::0") == 0 || + strcmp(svr, "0::0") == 0 || + strcmp(svr, "0::") == 0 || + strcmp(svr, "::") == 0) + svr = "::1"; + } + if(strchr(svr, '@')) { + if(!extstrtoaddr(svr, &addr, &addrlen)) + fatal_exit("could not parse IP@port: %s", svr); + } else { + if(!ipstrtoaddr(svr, cfg->control_port, &addr, &addrlen)) + fatal_exit("could not parse IP: %s", svr); + } + fd = socket(addr_is_ip6(&addr, addrlen)?AF_INET6:AF_INET, + SOCK_STREAM, 0); + if(fd == -1) { +#ifndef USE_WINSOCK + fatal_exit("socket: %s", strerror(errno)); +#else + fatal_exit("socket: %s", wsa_strerror(WSAGetLastError())); +#endif + } + if(connect(fd, (struct sockaddr*)&addr, addrlen) < 0) { + log_addr(0, "address", &addr, addrlen); +#ifndef USE_WINSOCK + log_err("connect: %s", strerror(errno)); + if(errno == ECONNREFUSED && statuscmd) { + printf("unbound is stopped\n"); + exit(3); + } +#else + log_err("connect: %s", wsa_strerror(WSAGetLastError())); + if(WSAGetLastError() == WSAECONNREFUSED && statuscmd) { + printf("unbound is stopped\n"); + exit(3); + } +#endif + exit(1); + } + return fd; +} + +/** setup SSL on the connection */ +static SSL* +setup_ssl(SSL_CTX* ctx, int fd) +{ + SSL* ssl; + X509* x; + int r; + + ssl = SSL_new(ctx); + if(!ssl) + ssl_err("could not SSL_new"); + SSL_set_connect_state(ssl); + (void)SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); + if(!SSL_set_fd(ssl, fd)) + ssl_err("could not SSL_set_fd"); + while(1) { + ERR_clear_error(); + if( (r=SSL_do_handshake(ssl)) == 1) + break; + r = SSL_get_error(ssl, r); + if(r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE) + ssl_err("SSL handshake failed"); + /* wants to be called again */ + } + + /* check authenticity of server */ + if(SSL_get_verify_result(ssl) != X509_V_OK) + ssl_err("SSL verification failed"); + x = SSL_get_peer_certificate(ssl); + if(!x) + ssl_err("Server presented no peer certificate"); + X509_free(x); + return ssl; +} + +/** send stdin to server */ +static void +send_file(SSL* ssl, FILE* in, char* buf, size_t sz) +{ + while(fgets(buf, (int)sz, in)) { + if(SSL_write(ssl, buf, (int)strlen(buf)) <= 0) + ssl_err("could not SSL_write contents"); + } +} + +/** send command and display result */ +static int +go_cmd(SSL* ssl, int argc, char* argv[]) +{ + char pre[10]; + const char* space=" "; + const char* newline="\n"; + int was_error = 0, first_line = 1; + int r, i; + char buf[1024]; + snprintf(pre, sizeof(pre), "UBCT%d ", UNBOUND_CONTROL_VERSION); + if(SSL_write(ssl, pre, (int)strlen(pre)) <= 0) + ssl_err("could not SSL_write"); + for(i=0; iremote_control_enable) + log_warn("control-enable is 'no' in the config file."); + ctx = setup_ctx(cfg); + + /* contact server */ + fd = contact_server(svr, cfg, argc>0&&strcmp(argv[0],"status")==0); + ssl = setup_ssl(ctx, fd); + + /* send command */ + ret = go_cmd(ssl, argc, argv); + + SSL_free(ssl); +#ifndef USE_WINSOCK + close(fd); +#else + closesocket(fd); +#endif + SSL_CTX_free(ctx); + config_delete(cfg); + return ret; +} + +/** getopt global, in case header files fail to declare it. */ +extern int optind; +/** getopt global, in case header files fail to declare it. */ +extern char* optarg; + +/** Main routine for unbound-control */ +int main(int argc, char* argv[]) +{ + int c, ret; + const char* cfgfile = CONFIGFILE; + char* svr = NULL; +#ifdef USE_WINSOCK + int r; + WSADATA wsa_data; +#endif +#ifdef USE_THREAD_DEBUG + /* stop the file output from unbound-control, overwites the servers */ + extern int check_locking_order; + check_locking_order = 0; +#endif /* USE_THREAD_DEBUG */ + log_ident_set("unbound-control"); + log_init(NULL, 0, NULL); + checklock_start(); +#ifdef USE_WINSOCK + if((r = WSAStartup(MAKEWORD(2,2), &wsa_data)) != 0) + fatal_exit("WSAStartup failed: %s", wsa_strerror(r)); + /* use registry config file in preference to compiletime location */ + if(!(cfgfile=w_lookup_reg_str("Software\\Unbound", "ConfigFile"))) + cfgfile = CONFIGFILE; +#endif + + ERR_load_crypto_strings(); + ERR_load_SSL_strings(); + OpenSSL_add_all_algorithms(); + (void)SSL_library_init(); + + if(!RAND_status()) { + /* try to seed it */ + unsigned char buf[256]; + unsigned int v, seed=(unsigned)time(NULL) ^ (unsigned)getpid(); + size_t i; + for(i=0; i<256/sizeof(v); i++) { + memmove(buf+i*sizeof(v), &v, sizeof(v)); + v = v*seed + (unsigned int)i; + } + RAND_seed(buf, 256); + log_warn("no entropy, seeding openssl PRNG with time\n"); + } + + /* parse the options */ + while( (c=getopt(argc, argv, "c:s:h")) != -1) { + switch(c) { + case 'c': + cfgfile = optarg; + break; + case 's': + svr = optarg; + break; + case '?': + case 'h': + default: + usage(); + } + } + argc -= optind; + argv += optind; + if(argc == 0) + usage(); + if(argc >= 1 && strcmp(argv[0], "start")==0) { + if(execlp("unbound", "unbound", "-c", cfgfile, + (char*)NULL) < 0) { + fatal_exit("could not exec unbound: %s", + strerror(errno)); + } + } + + ret = go(cfgfile, svr, argc, argv); + +#ifdef USE_WINSOCK + WSACleanup(); +#endif + checklock_stop(); + return ret; +} diff --git a/smallapp/unbound-host.c b/smallapp/unbound-host.c new file mode 100644 index 00000000000..095396749ff --- /dev/null +++ b/smallapp/unbound-host.c @@ -0,0 +1,514 @@ +/* + * checkconf/unbound-host.c - replacement for host that supports validation. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file performs functionality like 'host', and also supports validation. + * It uses the libunbound library. + */ + +#include "config.h" +#ifdef HAVE_GETOPT_H +#include +#endif +/* remove alloc checks, not in this part of the code */ +#ifdef UNBOUND_ALLOC_STATS +#undef malloc +#undef calloc +#undef free +#undef realloc +#endif +#ifdef UNBOUND_ALLOC_LITE +#undef malloc +#undef calloc +#undef free +#undef realloc +#undef strdup +#define unbound_lite_wrapstr(s) s +#endif +#include "libunbound/unbound.h" +#include + +/** verbosity for unbound-host app */ +static int verb = 0; + +/** Give unbound-host usage, and exit (1). */ +static void +usage() +{ + printf("Usage: unbound-host [-vdhr46] [-c class] [-t type] hostname\n"); + printf(" [-y key] [-f keyfile] [-F namedkeyfile]\n"); + printf(" [-C configfile]\n"); + printf(" Queries the DNS for information.\n"); + printf(" The hostname is looked up for IP4, IP6 and mail.\n"); + printf(" If an ip-address is given a reverse lookup is done.\n"); + printf(" Use the -v option to see DNSSEC security information.\n"); + printf(" -t type what type to look for.\n"); + printf(" -c class what class to look for, if not class IN.\n"); + printf(" -y 'keystring' specify trust anchor, DS or DNSKEY, like\n"); + printf(" -y 'example.com DS 31560 5 1 1CFED8478...'\n"); + printf(" -f keyfile read trust anchors from file, with lines as -y.\n"); + 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(" -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"); + printf(" -6 use ipv6 network, avoid ipv4.\n"); + printf(" -h show this usage help.\n"); + 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); +} + +/** determine if str is ip4 and put into reverse lookup format */ +static int +isip4(const char* nm, char** res) +{ + struct in_addr addr; + /* ddd.ddd.ddd.ddd.in-addr.arpa. is less than 32 */ + char buf[32]; + if(inet_pton(AF_INET, nm, &addr) <= 0) { + return 0; + } + snprintf(buf, sizeof(buf), "%u.%u.%u.%u.in-addr.arpa", + (unsigned)((uint8_t*)&addr)[3], (unsigned)((uint8_t*)&addr)[2], + (unsigned)((uint8_t*)&addr)[1], (unsigned)((uint8_t*)&addr)[0]); + *res = strdup(buf); + return 1; +} + +/** determine if str is ip6 and put into reverse lookup format */ +static int +isip6(const char* nm, char** res) +{ + struct in6_addr addr; + /* [nibble.]{32}.ip6.arpa. is less than 128 */ + const char* hex = "0123456789abcdef"; + char buf[128]; + char *p; + int i; + if(inet_pton(AF_INET6, nm, &addr) <= 0) { + return 0; + } + p = buf; + for(i=15; i>=0; i--) { + uint8_t b = ((uint8_t*)&addr)[i]; + *p++ = hex[ (b&0x0f) ]; + *p++ = '.'; + *p++ = hex[ (b&0xf0) >> 4 ]; + *p++ = '.'; + } + snprintf(buf+16*4, sizeof(buf)-16*4, "ip6.arpa"); + *res = strdup(buf); + if(!*res) { + fprintf(stderr, "error: out of memory\n"); + exit(1); + } + return 1; +} + +/** massage input name */ +static char* +massage_qname(const char* nm, int* reverse) +{ + /* recognise IP4 and IP6, create reverse addresses if needed */ + char* res; + if(isip4(nm, &res)) { + *reverse = 1; + } else if(isip6(nm, &res)) { + *reverse = 1; + } else { + res = strdup(nm); + } + if(!res) { + fprintf(stderr, "error: out of memory\n"); + exit(1); + } + return res; +} + +/** massage input type */ +static int +massage_type(const char* t, int reverse, int* multi) +{ + if(t) { + int r = ldns_get_rr_type_by_name(t); + if(r == 0 && strcasecmp(t, "TYPE0") != 0 && + strcmp(t, "") != 0) { + fprintf(stderr, "error unknown type %s\n", t); + exit(1); + } + return r; + } + if(!t && reverse) + return LDNS_RR_TYPE_PTR; + *multi = 1; + return LDNS_RR_TYPE_A; +} + +/** massage input class */ +static int +massage_class(const char* c) +{ + if(c) { + int r = ldns_get_rr_class_by_name(c); + if(r == 0 && strcasecmp(c, "CLASS0") != 0 && + strcmp(c, "") != 0) { + fprintf(stderr, "error unknown class %s\n", c); + exit(1); + } + return r; + } + return LDNS_RR_CLASS_IN; +} + +/** nice security status string */ +static const char* +secure_str(struct ub_result* result) +{ + if(result->secure) return "(secure)"; + if(result->bogus) return "(BOGUS (security failure))"; + return "(insecure)"; +} + +/** nice string for type */ +static void +pretty_type(char* s, size_t len, int t) +{ + char* d = ldns_rr_type2str(t); + snprintf(s, len, "%s", d); + free(d); +} + +/** nice string for class */ +static void +pretty_class(char* s, size_t len, int c) +{ + char* d = ldns_rr_class2str(c); + snprintf(s, len, "%s", d); + free(d); +} + +/** nice string for rcode */ +static void +pretty_rcode(char* s, size_t len, int r) +{ + ldns_lookup_table *rcode = ldns_lookup_by_id(ldns_rcodes, r); + if(rcode) { + snprintf(s, len, "%s", rcode->name); + } else { + snprintf(s, len, "RCODE%d", r); + } +} + +/** convert and print rdata */ +static void +print_rd(int t, char* data, size_t len) +{ + size_t i, pos = 0; + uint8_t* rd = (uint8_t*)malloc(len+2); + ldns_rr* rr = ldns_rr_new(); + ldns_status status; + if(!rd || !rr) { + fprintf(stderr, "out of memory"); + exit(1); + } + ldns_rr_set_type(rr, t); + ldns_write_uint16(rd, len); + memmove(rd+2, data, len); + ldns_rr_set_owner(rr, NULL); + status = ldns_wire2rdf(rr, rd, len+2, &pos); + if(status != LDNS_STATUS_OK) { + free(rd); + ldns_rr_free(rr); + printf("error_printing_data"); + return; + } + for(i=0; i 0) + printf(" %s", sec); + printf("\n"); +} + +/** pretty line of output for results */ +static void +pretty_output(char* q, int t, int c, struct ub_result* result, int docname) +{ + int i; + const char *secstatus = secure_str(result); + char tstr[16]; + char cstr[16]; + char rcodestr[16]; + pretty_type(tstr, 16, t); + pretty_class(cstr, 16, c); + pretty_rcode(rcodestr, 16, result->rcode); + + if(!result->havedata && result->rcode) { + printf("Host %s not found: %d(%s).", + q, result->rcode, rcodestr); + if(verb > 0) + printf(" %s", secstatus); + printf("\n"); + if(result->bogus && result->why_bogus) + printf("%s\n", result->why_bogus); + return; + } + if(docname && result->canonname && + result->canonname != result->qname) { + printf("%s is an alias for %s", result->qname, + result->canonname); + if(verb > 0) + printf(" %s", secstatus); + printf("\n"); + } + /* remove trailing . from long canonnames for nicer output */ + if(result->canonname && strlen(result->canonname) > 1 && + result->canonname[strlen(result->canonname)-1] == '.') + result->canonname[strlen(result->canonname)-1] = 0; + if(!result->havedata) { + if(verb > 0) { + printf("%s", result->canonname?result->canonname:q); + if(strcmp(cstr, "IN") != 0) + printf(" in class %s", cstr); + if(t == LDNS_RR_TYPE_A) + printf(" has no address"); + else if(t == LDNS_RR_TYPE_AAAA) + printf(" has no IPv6 address"); + else if(t == LDNS_RR_TYPE_PTR) + printf(" has no domain name ptr"); + else if(t == LDNS_RR_TYPE_MX) + printf(" has no mail handler record"); + else if(t == LDNS_RR_TYPE_ANY) { + ldns_pkt* p = NULL; + if(ldns_wire2pkt(&p, result->answer_packet, + (size_t)result->answer_len)==LDNS_STATUS_OK){ + if(ldns_rr_list_rr_count( + ldns_pkt_answer(p)) == 0) + printf(" has no records\n"); + else { + printf(" ANY:\n"); + ldns_rr_list_print(stdout, + ldns_pkt_answer(p)); + } + } else { + fprintf(stderr, "could not parse " + "reply packet to ANY query\n"); + exit(1); + } + ldns_pkt_free(p); + + } else printf(" has no %s record", tstr); + printf(" %s\n", secstatus); + } + /* else: emptiness to indicate no data */ + if(result->bogus && result->why_bogus) + printf("%s\n", result->why_bogus); + return; + } + i=0; + while(result->data[i]) + { + pretty_rdata( + result->canonname?result->canonname:q, + cstr, tstr, t, secstatus, result->data[i], + (size_t)result->len[i]); + i++; + } + if(result->bogus && result->why_bogus) + printf("%s\n", result->why_bogus); +} + +/** perform a lookup and printout return if domain existed */ +static int +dnslook(struct ub_ctx* ctx, char* q, int t, int c, int docname) +{ + int ret; + struct ub_result* result; + + ret = ub_resolve(ctx, q, t, c, &result); + if(ret != 0) { + fprintf(stderr, "resolve error: %s\n", ub_strerror(ret)); + exit(1); + } + pretty_output(q, t, c, result, docname); + ret = result->nxdomain; + ub_resolve_free(result); + return ret; +} + +/** perform host lookup */ +static void +lookup(struct ub_ctx* ctx, const char* nm, const char* qt, const char* qc) +{ + /* massage input into a query name, type and class */ + int multi = 0; /* no type, so do A, AAAA, MX */ + int reverse = 0; /* we are doing a reverse lookup */ + char* realq = massage_qname(nm, &reverse); + int t = massage_type(qt, reverse, &multi); + int c = massage_class(qc); + + /* perform the query */ + if(multi) { + if(!dnslook(ctx, realq, LDNS_RR_TYPE_A, c, 1)) { + /* domain exists, lookup more */ + (void)dnslook(ctx, realq, LDNS_RR_TYPE_AAAA, c, 0); + (void)dnslook(ctx, realq, LDNS_RR_TYPE_MX, c, 0); + } + } else { + (void)dnslook(ctx, realq, t, c, 1); + } + ub_ctx_delete(ctx); + free(realq); +} + +/** print error if any */ +static void +check_ub_res(int r) +{ + if(r != 0) { + fprintf(stderr, "error: %s\n", ub_strerror(r)); + exit(1); + } +} + +/** getopt global, in case header files fail to declare it. */ +extern int optind; +/** getopt global, in case header files fail to declare it. */ +extern char* optarg; + +/** Main routine for checkconf */ +int main(int argc, char* argv[]) +{ + int c; + char* qclass = NULL; + char* qtype = NULL; + struct ub_ctx* ctx = NULL; + int debuglevel = 0; + + ctx = ub_ctx_create(); + if(!ctx) { + fprintf(stderr, "error: out of memory\n"); + exit(1); + } + + /* parse the options */ + while( (c=getopt(argc, argv, "46F:c:df:hrt:vy:C:")) != -1) { + switch(c) { + case '4': + check_ub_res(ub_ctx_set_option(ctx, "do-ip6:", "no")); + break; + case '6': + check_ub_res(ub_ctx_set_option(ctx, "do-ip4:", "no")); + break; + case 'c': + qclass = optarg; + break; + case 'C': + check_ub_res(ub_ctx_config(ctx, optarg)); + break; + case 'd': + debuglevel++; + if(debuglevel < 2) + debuglevel = 2; /* at least VERB_DETAIL */ + break; + case 'r': + check_ub_res(ub_ctx_resolvconf(ctx, "/etc/resolv.conf")); + break; + case 't': + qtype = optarg; + break; + case 'v': + verb++; + break; + case 'y': + check_ub_res(ub_ctx_add_ta(ctx, optarg)); + break; + case 'f': + check_ub_res(ub_ctx_add_ta_file(ctx, optarg)); + break; + case 'F': + check_ub_res(ub_ctx_trustedkeys(ctx, optarg)); + break; + case '?': + case 'h': + default: + usage(); + } + } + if(debuglevel != 0) /* set after possible -C options */ + check_ub_res(ub_ctx_debuglevel(ctx, debuglevel)); + if(ub_ctx_get_option(ctx, "use-syslog", &optarg) == 0) { + if(strcmp(optarg, "yes") == 0) /* disable use-syslog */ + check_ub_res(ub_ctx_set_option(ctx, + "use-syslog:", "no")); + free(optarg); + } + argc -= optind; + argv += optind; + if(argc != 1) + usage(); + + lookup(ctx, argv[0], qtype, qclass); + return 0; +} diff --git a/smallapp/worker_cb.c b/smallapp/worker_cb.c new file mode 100644 index 00000000000..bc37e3307ae --- /dev/null +++ b/smallapp/worker_cb.c @@ -0,0 +1,242 @@ +/* + * checkconf/worker_cb.c - fake callback routines to make fptr_wlist work + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains fake callback functions, so that the symbols exist + * and the fptr_wlist continues to work even if the daemon/worker is not + * linked into the resulting program. + */ +#include "config.h" +#include "util/log.h" +#include "services/mesh.h" +struct comm_reply; +struct comm_point; +struct module_qstate; +struct tube; + +void worker_handle_control_cmd(struct tube* ATTR_UNUSED(tube), + uint8_t* ATTR_UNUSED(buffer), size_t ATTR_UNUSED(len), + int ATTR_UNUSED(error), void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + +int worker_handle_request(struct comm_point* ATTR_UNUSED(c), + void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), + struct comm_reply* ATTR_UNUSED(repinfo)) +{ + log_assert(0); + return 0; +} + +int worker_handle_reply(struct comm_point* ATTR_UNUSED(c), + void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), + struct comm_reply* ATTR_UNUSED(reply_info)) +{ + log_assert(0); + return 0; +} + +int worker_handle_service_reply(struct comm_point* ATTR_UNUSED(c), + void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), + struct comm_reply* ATTR_UNUSED(reply_info)) +{ + log_assert(0); + return 0; +} + +int remote_accept_callback(struct comm_point* ATTR_UNUSED(c), + void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), + struct comm_reply* ATTR_UNUSED(repinfo)) +{ + log_assert(0); + return 0; +} + +int remote_control_callback(struct comm_point* ATTR_UNUSED(c), + void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), + struct comm_reply* ATTR_UNUSED(repinfo)) +{ + log_assert(0); + return 0; +} + +void worker_sighandler(int ATTR_UNUSED(sig), void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + +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), + struct sockaddr_storage* ATTR_UNUSED(addr), + socklen_t ATTR_UNUSED(addrlen), struct module_qstate* ATTR_UNUSED(q)) +{ + log_assert(0); + return 0; +} + +#ifdef UB_ON_WINDOWS +void +worker_win_stop_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev), void* + ATTR_UNUSED(arg)) { + log_assert(0); +} + +void +wsvc_cron_cb(void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} +#endif /* UB_ON_WINDOWS */ + +void +worker_alloc_cleanup(void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + +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), + struct sockaddr_storage* ATTR_UNUSED(addr), + socklen_t ATTR_UNUSED(addrlen), struct module_qstate* ATTR_UNUSED(q)) +{ + log_assert(0); + return 0; +} + +int libworker_handle_reply(struct comm_point* ATTR_UNUSED(c), + void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), + struct comm_reply* ATTR_UNUSED(reply_info)) +{ + log_assert(0); + return 0; +} + +int libworker_handle_service_reply(struct comm_point* ATTR_UNUSED(c), + void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), + struct comm_reply* ATTR_UNUSED(reply_info)) +{ + log_assert(0); + return 0; +} + +void libworker_handle_control_cmd(struct tube* ATTR_UNUSED(tube), + uint8_t* ATTR_UNUSED(buffer), size_t ATTR_UNUSED(len), + int ATTR_UNUSED(error), void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + +void libworker_fg_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode), + ldns_buffer* ATTR_UNUSED(buf), enum sec_status ATTR_UNUSED(s), + char* ATTR_UNUSED(why_bogus)) +{ + log_assert(0); +} + +void libworker_bg_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode), + ldns_buffer* ATTR_UNUSED(buf), enum sec_status ATTR_UNUSED(s), + char* ATTR_UNUSED(why_bogus)) +{ + log_assert(0); +} + +int context_query_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b)) +{ + log_assert(0); + return 0; +} + +void worker_stat_timer_cb(void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + +void worker_probe_timer_cb(void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + +void worker_start_accept(void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + +void worker_stop_accept(void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + +/** keep track of lock id in lock-verify application */ +struct order_id { + /** the thread id that created it */ + int thr; + /** the instance number of creation */ + int instance; +}; + +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; + if(o1->thr < o2->thr) return -1; + if(o1->thr > o2->thr) return 1; + if(o1->instance < o2->instance) return -1; + if(o1->instance > o2->instance) return 1; + return 0; +} + +int +codeline_cmp(const void* a, const void* b) +{ + return strcmp((const char*)a, (const char*)b); +} + +int replay_var_compare(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b)) +{ + log_assert(0); + return 0; +} + +void remote_get_opt_ssl(char* ATTR_UNUSED(str), void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} diff --git a/testcode/asynclook.c b/testcode/asynclook.c new file mode 100644 index 00000000000..7ec013c0cb9 --- /dev/null +++ b/testcode/asynclook.c @@ -0,0 +1,517 @@ +/* + * testcode/asynclook.c - debug program perform async libunbound queries. + * + * Copyright (c) 2008, 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This program shows the results from several background lookups, + * while printing time in the foreground. + */ + +#include "config.h" +#ifdef HAVE_GETOPT_H +#include +#endif +#include "libunbound/unbound.h" +#include "libunbound/context.h" +#include "util/locks.h" +#include "util/log.h" +#ifdef UNBOUND_ALLOC_LITE +#undef malloc +#undef calloc +#undef realloc +#undef free +#undef strdup +#endif + +/** keeping track of the async ids */ +struct track_id { + /** the id to pass to libunbound to cancel */ + int id; + /** true if cancelled */ + int cancel; + /** a lock on this structure for thread safety */ + lock_basic_t lock; +}; + +/** + * result list for the lookups + */ +struct lookinfo { + /** name to look up */ + char* name; + /** tracking number that can be used to cancel the query */ + int async_id; + /** error code from libunbound */ + int err; + /** result from lookup */ + struct ub_result* result; +}; + +/** global variable to see how many queries we have left */ +static int num_wait = 0; + +/** usage information for asynclook */ +static void usage(char* argv[]) +{ + printf("usage: %s [options] name ...\n", argv[0]); + printf("names are looked up at the same time, asynchronously.\n"); + printf(" -b : use blocking requests\n"); + printf(" -c : cancel the requests\n"); + printf(" -d : enable debug output\n"); + printf(" -f addr : use addr, forward to that server\n"); + printf(" -h : this help message\n"); + printf(" -H fname : read hosts from fname\n"); + printf(" -r fname : read resolv.conf from fname\n"); + printf(" -t : use a resolver thread instead of forking a process\n"); + printf(" -x : perform extended threaded test\n"); + exit(1); +} + +/** print result from lookup nicely */ +static void +print_result(struct lookinfo* info) +{ + char buf[100]; + if(info->err) /* error (from libunbound) */ + printf("%s: error %s\n", info->name, + ub_strerror(info->err)); + else if(!info->result) + printf("%s: cancelled\n", info->name); + else if(info->result->havedata) + printf("%s: %s\n", info->name, + inet_ntop(AF_INET, info->result->data[0], + buf, (socklen_t)sizeof(buf))); + else { + /* there is no data, why that? */ + if(info->result->rcode == 0 /*noerror*/ || + info->result->nxdomain) + printf("%s: no data %s\n", info->name, + info->result->nxdomain?"(no such host)": + "(no IP4 address)"); + else /* some error (from the server) */ + printf("%s: DNS error %d\n", info->name, + info->result->rcode); + } +} + +/** this is a function of type ub_callback_t */ +static void +lookup_is_done(void* mydata, int err, struct ub_result* result) +{ + /* cast mydata back to the correct type */ + struct lookinfo* info = (struct lookinfo*)mydata; + fprintf(stderr, "name %s resolved\n", info->name); + info->err = err; + info->result = result; + /* one less to wait for */ + num_wait--; +} + +/** check error, if bad, exit with error message */ +static void +checkerr(const char* desc, int err) +{ + if(err != 0) { + printf("%s error: %s\n", desc, ub_strerror(err)); + exit(1); + } +} + +#ifdef THREADS_DISABLED +/** only one process can communicate with async worker */ +#define NUMTHR 1 +#else /* have threads */ +/** number of threads to make in extended test */ +#define NUMTHR 10 +#endif + +/** struct for extended thread info */ +struct ext_thr_info { + /** thread num for debug */ + int thread_num; + /** thread id */ + ub_thread_t tid; + /** context */ + struct ub_ctx* ctx; + /** size of array to query */ + int argc; + /** array of names to query */ + char** argv; + /** number of queries to do */ + int numq; +}; + +/** if true, we are testing against 'localhost' and extra checking is done */ +static int q_is_localhost = 0; + +/** check result structure for the 'correct' answer */ +static void +ext_check_result(const char* desc, int err, struct ub_result* result) +{ + checkerr(desc, err); + if(result == NULL) { + printf("%s: error result is NULL.\n", desc); + exit(1); + } + if(q_is_localhost) { + if(strcmp(result->qname, "localhost") != 0) { + printf("%s: error result has wrong qname.\n", desc); + exit(1); + } + if(result->qtype != LDNS_RR_TYPE_A) { + printf("%s: error result has wrong qtype.\n", desc); + exit(1); + } + if(result->qclass != LDNS_RR_CLASS_IN) { + printf("%s: error result has wrong qclass.\n", desc); + exit(1); + } + if(result->data == NULL) { + printf("%s: error result->data is NULL.\n", desc); + exit(1); + } + if(result->len == NULL) { + printf("%s: error result->len is NULL.\n", desc); + exit(1); + } + if(result->rcode != 0) { + printf("%s: error result->rcode is set.\n", desc); + exit(1); + } + if(result->havedata == 0) { + printf("%s: error result->havedata is unset.\n", desc); + exit(1); + } + if(result->nxdomain != 0) { + printf("%s: error result->nxdomain is set.\n", desc); + exit(1); + } + if(result->secure || result->bogus) { + printf("%s: error result->secure or bogus is set.\n", + desc); + exit(1); + } + if(result->data[0] == NULL) { + printf("%s: error result->data[0] is NULL.\n", desc); + exit(1); + } + if(result->len[0] != 4) { + printf("%s: error result->len[0] is wrong.\n", desc); + exit(1); + } + if(result->len[1] != 0 || result->data[1] != NULL) { + printf("%s: error result->data[1] or len[1] is " + "wrong.\n", desc); + exit(1); + } + if(result->answer_packet == NULL) { + printf("%s: error result->answer_packet is NULL.\n", + desc); + exit(1); + } + if(result->answer_len != 54) { + printf("%s: error result->answer_len is wrong.\n", + desc); + exit(1); + } + } +} + +/** extended bg result callback, this function is ub_callback_t */ +static void +ext_callback(void* mydata, int err, struct ub_result* result) +{ + struct track_id* my_id = (struct track_id*)mydata; + int doprint = 0; + if(my_id) { + /* I have an id, make sure we are not cancelled */ + lock_basic_lock(&my_id->lock); + if(doprint) + printf("cb %d: ", my_id->id); + if(my_id->cancel) { + printf("error: query id=%d returned, but was cancelled\n", + my_id->id); + abort(); + exit(1); + } + lock_basic_unlock(&my_id->lock); + } + ext_check_result("ext_callback", err, result); + log_assert(result); + if(doprint) { + struct lookinfo pi; + pi.name = result?result->qname:"noname"; + pi.result = result; + pi.err = 0; + print_result(&pi); + } + ub_resolve_free(result); +} + +/** extended thread worker */ +static void* +ext_thread(void* arg) +{ + struct ext_thr_info* inf = (struct ext_thr_info*)arg; + int i, r; + struct ub_result* result; + struct track_id* async_ids = NULL; + log_thread_set(&inf->thread_num); + if(inf->thread_num > NUMTHR*2/3) { + async_ids = (struct track_id*)calloc((size_t)inf->numq, sizeof(struct track_id)); + if(!async_ids) { + printf("out of memory\n"); + exit(1); + } + for(i=0; inumq; i++) { + lock_basic_init(&async_ids[i].lock); + } + } + for(i=0; inumq; i++) { + if(async_ids) { + r = ub_resolve_async(inf->ctx, + inf->argv[i%inf->argc], LDNS_RR_TYPE_A, + LDNS_RR_CLASS_IN, &async_ids[i], ext_callback, + &async_ids[i].id); + checkerr("ub_resolve_async", r); + if(i > 100) { + lock_basic_lock(&async_ids[i-100].lock); + r = ub_cancel(inf->ctx, async_ids[i-100].id); + if(r != UB_NOID) + async_ids[i-100].cancel=1; + lock_basic_unlock(&async_ids[i-100].lock); + if(r != UB_NOID) + checkerr("ub_cancel", r); + } + } else if(inf->thread_num > NUMTHR/2) { + /* async */ + r = ub_resolve_async(inf->ctx, + inf->argv[i%inf->argc], LDNS_RR_TYPE_A, + LDNS_RR_CLASS_IN, NULL, ext_callback, NULL); + checkerr("ub_resolve_async", r); + } else { + /* blocking */ + r = ub_resolve(inf->ctx, inf->argv[i%inf->argc], + LDNS_RR_TYPE_A, LDNS_RR_CLASS_IN, &result); + ext_check_result("ub_resolve", r, result); + ub_resolve_free(result); + } + } + if(inf->thread_num > NUMTHR/2) { + r = ub_wait(inf->ctx); + checkerr("ub_ctx_wait", r); + } + free(async_ids); + + return NULL; +} + +/** perform extended threaded test */ +static int +ext_test(struct ub_ctx* ctx, int argc, char** argv) +{ + struct ext_thr_info inf[NUMTHR]; + int i; + if(argc == 1 && strcmp(argv[0], "localhost") == 0) + q_is_localhost = 1; + printf("extended test start (%d threads)\n", NUMTHR); + for(i=0; i 0) + for(i=0; i<1000; i++) { + usleep(100000); + fprintf(stderr, "%g seconds passed\n", 0.1*(double)i); + r = ub_process(ctx); + checkerr("ub_process", r); + if(num_wait == 0) + break; + } + if(i>=999) { + printf("timed out\n"); + return 0; + } + printf("lookup complete\n"); + + /* print lookup results */ + for(i=0; i +#include "util/locks.h" /* include before checklocks.h */ +#include "testcode/checklocks.h" + +/** + * \file + * Locks that are checked. + * + * Ugly hack: uses the fact that workers start with an int thread_num, and + * are passed to thread_create to make the thread numbers here the same as + * those used for logging which is nice. + * + * Todo: + * - debug status print, of thread lock stacks, and current waiting. + */ +#ifdef USE_THREAD_DEBUG + +/** How long to wait before lock attempt is a failure. */ +#define CHECK_LOCK_TIMEOUT 120 /* seconds */ +/** How long to wait before join attempt is a failure. */ +#define CHECK_JOIN_TIMEOUT 120 /* seconds */ + +/** if key has been created */ +static int key_created = 0; +/** we hide the thread debug info with this key. */ +static ub_thread_key_t thr_debug_key; +/** the list of threads, so all threads can be examined. NULL if unused. */ +static struct thr_check* thread_infos[THRDEBUG_MAX_THREADS]; +/** do we check locking order */ +int check_locking_order = 1; +/** the pid of this runset, reasonably unique. */ +static pid_t check_lock_pid; + +/** print all possible debug info on the state of the system */ +static void total_debug_info(void); + +/** print pretty lock error and exit */ +static void lock_error(struct checked_lock* lock, + const char* func, const char* file, int line, const char* err) +{ + log_err("lock error (description follows)"); + log_err("Created at %s %s:%d", lock->create_func, + lock->create_file, lock->create_line); + if(lock->holder_func && lock->holder_file) + log_err("Previously %s %s:%d", lock->holder_func, + lock->holder_file, lock->holder_line); + log_err("At %s %s:%d", func, file, line); + log_err("Error for %s lock: %s", + (lock->type==check_lock_mutex)?"mutex": ( + (lock->type==check_lock_spinlock)?"spinlock": ( + (lock->type==check_lock_rwlock)?"rwlock": "badtype")), err); + log_err("complete status display:"); + total_debug_info(); + fatal_exit("bailing out"); +} + +/** + * Obtain lock on debug lock structure. This could be a deadlock by the caller. + * The debug code itself does not deadlock. Anyway, check with timeouts. + * @param lock: on what to acquire lock. + * @param func: user level caller identification. + * @param file: user level caller identification. + * @param line: user level caller identification. + */ +static void +acquire_locklock(struct checked_lock* lock, + const char* func, const char* file, int line) +{ + struct timespec to; + int err; + int contend = 0; + /* first try; inc contention counter if not immediately */ + if((err = pthread_mutex_trylock(&lock->lock))) { + if(err==EBUSY) + contend++; + else fatal_exit("error in mutex_trylock: %s", strerror(err)); + } + if(!err) + return; /* immediate success */ + to.tv_sec = time(NULL) + CHECK_LOCK_TIMEOUT; + to.tv_nsec = 0; + err = pthread_mutex_timedlock(&lock->lock, &to); + if(err) { + log_err("in acquiring locklock: %s", strerror(err)); + lock_error(lock, func, file, line, "acquire locklock"); + } + /* since we hold the lock, we can edit the contention_count */ + lock->contention_count += contend; +} + +/** add protected region */ +void +lock_protect(void *p, void* area, size_t size) +{ + struct checked_lock* lock = *(struct checked_lock**)p; + struct protected_area* e = (struct protected_area*)malloc( + sizeof(struct protected_area)); + if(!e) + fatal_exit("lock_protect: out of memory"); + e->region = area; + e->size = size; + e->hold = malloc(size); + if(!e->hold) + fatal_exit("lock_protect: out of memory"); + memcpy(e->hold, e->region, e->size); + + acquire_locklock(lock, __func__, __FILE__, __LINE__); + e->next = lock->prot; + lock->prot = e; + LOCKRET(pthread_mutex_unlock(&lock->lock)); +} + +/** remove protected region */ +void +lock_unprotect(void* mangled, void* area) +{ + struct checked_lock* lock = *(struct checked_lock**)mangled; + struct protected_area* p, **prevp; + if(!lock) + return; + acquire_locklock(lock, __func__, __FILE__, __LINE__); + p = lock->prot; + prevp = &lock->prot; + while(p) { + if(p->region == area) { + *prevp = p->next; + free(p->hold); + free(p); + LOCKRET(pthread_mutex_unlock(&lock->lock)); + return; + } + prevp = &p->next; + p = p->next; + } + LOCKRET(pthread_mutex_unlock(&lock->lock)); +} + +/** + * Check protected memory region. Memory compare. Exit on error. + * @param lock: which lock to check. + * @param func: location we are now (when failure is detected). + * @param file: location we are now (when failure is detected). + * @param line: location we are now (when failure is detected). + */ +static void +prot_check(struct checked_lock* lock, + const char* func, const char* file, int line) +{ + struct protected_area* p = lock->prot; + while(p) { + if(memcmp(p->hold, p->region, p->size) != 0) { + log_hex("memory prev", p->hold, p->size); + log_hex("memory here", p->region, p->size); + lock_error(lock, func, file, line, + "protected area modified"); + } + p = p->next; + } +} + +/** Copy protected memory region */ +static void +prot_store(struct checked_lock* lock) +{ + struct protected_area* p = lock->prot; + while(p) { + memcpy(p->hold, p->region, p->size); + p = p->next; + } +} + +/** get memory held by lock */ +size_t +lock_get_mem(void* pp) +{ + size_t s; + struct checked_lock* lock = *(struct checked_lock**)pp; + struct protected_area* p; + s = sizeof(struct checked_lock); + acquire_locklock(lock, __func__, __FILE__, __LINE__); + for(p = lock->prot; p; p = p->next) { + s += sizeof(struct protected_area); + s += p->size; + } + LOCKRET(pthread_mutex_unlock(&lock->lock)); + return s; +} + +/** write lock trace info to file, while you hold those locks */ +static void +ordercheck_locklock(struct thr_check* thr, struct checked_lock* lock) +{ + int info[4]; + if(!check_locking_order) return; + if(!thr->holding_first) return; /* no older lock, no info */ + /* write: */ + info[0] = thr->holding_first->create_thread; + info[1] = thr->holding_first->create_instance; + info[2] = lock->create_thread; + info[3] = lock->create_instance; + if(fwrite(info, 4*sizeof(int), 1, thr->order_info) != 1 || + fwrite(lock->holder_file, strlen(lock->holder_file)+1, 1, + thr->order_info) != 1 || + fwrite(&lock->holder_line, sizeof(int), 1, + thr->order_info) != 1) + log_err("fwrite: %s", strerror(errno)); +} + +/** write ordercheck lock creation details to file */ +static void +ordercheck_lockcreate(struct thr_check* thr, struct checked_lock* lock) +{ + /* write: */ + int cmd = -1; + if(!check_locking_order) return; + + if( fwrite(&cmd, sizeof(int), 1, thr->order_info) != 1 || + fwrite(&lock->create_thread, sizeof(int), 1, + thr->order_info) != 1 || + fwrite(&lock->create_instance, sizeof(int), 1, + thr->order_info) != 1 || + fwrite(lock->create_file, strlen(lock->create_file)+1, 1, + thr->order_info) != 1 || + fwrite(&lock->create_line, sizeof(int), 1, + thr->order_info) != 1) + log_err("fwrite: %s", strerror(errno)); +} + +/** alloc struct, init lock empty */ +void +checklock_init(enum check_lock_type type, struct checked_lock** lock, + const char* func, const char* file, int line) +{ + struct checked_lock* e = (struct checked_lock*)calloc(1, + sizeof(struct checked_lock)); + struct thr_check *thr = (struct thr_check*)pthread_getspecific( + thr_debug_key); + if(!e) + fatal_exit("%s %s %d: out of memory", func, file, line); + if(!thr) + fatal_exit("%s %s %d: lock_init no thread info", func, file, + line); + *lock = e; + e->type = type; + e->create_func = func; + e->create_file = file; + e->create_line = line; + e->create_thread = thr->num; + e->create_instance = thr->locks_created++; + ordercheck_lockcreate(thr, e); + LOCKRET(pthread_mutex_init(&e->lock, NULL)); + switch(e->type) { + case check_lock_mutex: + LOCKRET(pthread_mutex_init(&e->u.mutex, NULL)); + break; + case check_lock_spinlock: + LOCKRET(pthread_spin_init(&e->u.spinlock, PTHREAD_PROCESS_PRIVATE)); + break; + case check_lock_rwlock: + LOCKRET(pthread_rwlock_init(&e->u.rwlock, NULL)); + break; + default: + log_assert(0); + } +} + +/** delete prot items */ +static void +prot_clear(struct checked_lock* lock) +{ + struct protected_area* p=lock->prot, *np; + while(p) { + np = p->next; + free(p->hold); + free(p); + p = np; + } +} + +/** check if type is OK for the lock given */ +static void +checktype(enum check_lock_type type, struct checked_lock* lock, + const char* func, const char* file, int line) +{ + if(!lock) + fatal_exit("use of null/deleted lock at %s %s:%d", + func, file, line); + if(type != lock->type) { + lock_error(lock, func, file, line, "wrong lock type"); + } +} + +/** check if OK, free struct */ +void +checklock_destroy(enum check_lock_type type, struct checked_lock** lock, + const char* func, const char* file, int line) +{ + const size_t contention_interest = 1; /* promille contented locks */ + struct checked_lock* e; + if(!lock) + return; + e = *lock; + if(!e) + return; + checktype(type, e, func, file, line); + + /* check if delete is OK */ + acquire_locklock(e, func, file, line); + if(e->hold_count != 0) + lock_error(e, func, file, line, "delete while locked."); + if(e->wait_count != 0) + lock_error(e, func, file, line, "delete while waited on."); + prot_check(e, func, file, line); + *lock = NULL; /* use after free will fail */ + LOCKRET(pthread_mutex_unlock(&e->lock)); + + /* contention, look at fraction in trouble. */ + if(e->history_count > 1 && + 1000*e->contention_count/e->history_count > contention_interest) { + log_info("lock created %s %s %d has contention %u of %u (%d%%)", + e->create_func, e->create_file, e->create_line, + (unsigned int)e->contention_count, + (unsigned int)e->history_count, + (int)(100*e->contention_count/e->history_count)); + } + + /* delete it */ + LOCKRET(pthread_mutex_destroy(&e->lock)); + prot_clear(e); + /* since nobody holds the lock - see check above, no need to unlink + * from the thread-held locks list. */ + switch(e->type) { + case check_lock_mutex: + LOCKRET(pthread_mutex_destroy(&e->u.mutex)); + break; + case check_lock_spinlock: + LOCKRET(pthread_spin_destroy(&e->u.spinlock)); + break; + case check_lock_rwlock: + LOCKRET(pthread_rwlock_destroy(&e->u.rwlock)); + break; + default: + log_assert(0); + } + memset(e, 0, sizeof(struct checked_lock)); + free(e); +} + +/** finish acquiring lock, shared between _(rd|wr||)lock() routines */ +static void +finish_acquire_lock(struct thr_check* thr, struct checked_lock* lock, + const char* func, const char* file, int line) +{ + thr->waiting = NULL; + lock->wait_count --; + lock->holder = thr; + lock->hold_count ++; + lock->holder_func = func; + lock->holder_file = file; + lock->holder_line = line; + ordercheck_locklock(thr, lock); + + /* insert in thread lock list, as first */ + lock->prev_held_lock[thr->num] = NULL; + lock->next_held_lock[thr->num] = thr->holding_first; + if(thr->holding_first) + /* no need to lock it, since this thread already holds the + * lock (since it is on this list) and we only edit thr->num + * member in array. So it is safe. */ + thr->holding_first->prev_held_lock[thr->num] = lock; + else thr->holding_last = lock; + thr->holding_first = lock; +} + +/** + * Locking routine. + * @param type: as passed by user. + * @param lock: as passed by user. + * @param func: caller location. + * @param file: caller location. + * @param line: caller location. + * @param tryfunc: the pthread_mutex_trylock or similar function. + * @param timedfunc: the pthread_mutex_timedlock or similar function. + * Uses absolute timeout value. + * @param arg: what to pass to tryfunc and timedlock. + * @param exclusive: if lock must be exlusive (only one allowed). + * @param getwr: if attempts to get writelock (or readlock) for rwlocks. + */ +static void +checklock_lockit(enum check_lock_type type, struct checked_lock* lock, + const char* func, const char* file, int line, + int (*tryfunc)(void*), int (*timedfunc)(void*, struct timespec*), + void* arg, int exclusive, int getwr) +{ + int err; + int contend = 0; + struct thr_check *thr = (struct thr_check*)pthread_getspecific( + thr_debug_key); + checktype(type, lock, func, file, line); + if(!thr) lock_error(lock, func, file, line, "no thread info"); + + acquire_locklock(lock, func, file, line); + lock->wait_count ++; + thr->waiting = lock; + if(exclusive && lock->hold_count > 0 && lock->holder == thr) + lock_error(lock, func, file, line, "thread already owns lock"); + if(type==check_lock_rwlock && getwr && lock->writeholder == thr) + lock_error(lock, func, file, line, "thread already has wrlock"); + LOCKRET(pthread_mutex_unlock(&lock->lock)); + + /* first try; if busy increase contention counter */ + if((err=tryfunc(arg))) { + struct timespec to; + if(err != EBUSY) log_err("trylock: %s", strerror(err)); + to.tv_sec = time(NULL) + CHECK_LOCK_TIMEOUT; + to.tv_nsec = 0; + if((err=timedfunc(arg, &to))) { + if(err == ETIMEDOUT) + lock_error(lock, func, file, line, + "timeout possible deadlock"); + log_err("timedlock: %s", strerror(err)); + } + contend ++; + } + /* got the lock */ + + acquire_locklock(lock, func, file, line); + lock->contention_count += contend; + lock->history_count++; + if(exclusive && lock->hold_count > 0) + lock_error(lock, func, file, line, "got nonexclusive lock"); + if(type==check_lock_rwlock && getwr && lock->writeholder) + lock_error(lock, func, file, line, "got nonexclusive wrlock"); + if(type==check_lock_rwlock && getwr) + lock->writeholder = thr; + /* check the memory areas for unauthorized changes, + * between last unlock time and current lock time. + * we check while holding the lock (threadsafe). + */ + if(getwr || exclusive) + prot_check(lock, func, file, line); + finish_acquire_lock(thr, lock, func, file, line); + LOCKRET(pthread_mutex_unlock(&lock->lock)); +} + +/** helper for rdlock: try */ +static int try_rd(void* arg) +{ return pthread_rwlock_tryrdlock((pthread_rwlock_t*)arg); } +/** helper for rdlock: timed */ +static int timed_rd(void* arg, struct timespec* to) +{ return pthread_rwlock_timedrdlock((pthread_rwlock_t*)arg, to); } + +/** check if OK, lock */ +void +checklock_rdlock(enum check_lock_type type, struct checked_lock* lock, + const char* func, const char* file, int line) +{ + + log_assert(type == check_lock_rwlock); + checklock_lockit(type, lock, func, file, line, + try_rd, timed_rd, &lock->u.rwlock, 0, 0); +} + +/** helper for wrlock: try */ +static int try_wr(void* arg) +{ return pthread_rwlock_trywrlock((pthread_rwlock_t*)arg); } +/** helper for wrlock: timed */ +static int timed_wr(void* arg, struct timespec* to) +{ return pthread_rwlock_timedwrlock((pthread_rwlock_t*)arg, to); } + +/** check if OK, lock */ +void +checklock_wrlock(enum check_lock_type type, struct checked_lock* lock, + const char* func, const char* file, int line) +{ + log_assert(type == check_lock_rwlock); + checklock_lockit(type, lock, func, file, line, + try_wr, timed_wr, &lock->u.rwlock, 0, 1); +} + +/** helper for lock mutex: try */ +static int try_mutex(void* arg) +{ return pthread_mutex_trylock((pthread_mutex_t*)arg); } +/** helper for lock mutex: timed */ +static int timed_mutex(void* arg, struct timespec* to) +{ return pthread_mutex_timedlock((pthread_mutex_t*)arg, to); } + +/** helper for lock spinlock: try */ +static int try_spinlock(void* arg) +{ return pthread_spin_trylock((pthread_spinlock_t*)arg); } +/** helper for lock spinlock: timed */ +static int timed_spinlock(void* arg, struct timespec* to) +{ + int err; + /* spin for 5 seconds. (ouch for the CPU, but it beats forever) */ + while( (err=try_spinlock(arg)) == EBUSY) { +#ifndef S_SPLINT_S + if(time(NULL) >= to->tv_sec) + return ETIMEDOUT; + usleep(1000); /* in 1/1000000s of a second */ +#endif + } + return err; +} + +/** check if OK, lock */ +void +checklock_lock(enum check_lock_type type, struct checked_lock* lock, + const char* func, const char* file, int line) +{ + log_assert(type != check_lock_rwlock); + switch(type) { + case check_lock_mutex: + checklock_lockit(type, lock, func, file, line, + try_mutex, timed_mutex, &lock->u.mutex, 1, 0); + break; + case check_lock_spinlock: + /* void* cast needed because 'volatile' on some OS */ + checklock_lockit(type, lock, func, file, line, + try_spinlock, timed_spinlock, + (void*)&lock->u.spinlock, 1, 0); + break; + default: + log_assert(0); + } +} + +/** check if OK, unlock */ +void +checklock_unlock(enum check_lock_type type, struct checked_lock* lock, + const char* func, const char* file, int line) +{ + struct thr_check *thr = (struct thr_check*)pthread_getspecific( + thr_debug_key); + checktype(type, lock, func, file, line); + if(!thr) lock_error(lock, func, file, line, "no thread info"); + + acquire_locklock(lock, func, file, line); + /* was this thread even holding this lock? */ + if(thr->holding_first != lock && + lock->prev_held_lock[thr->num] == NULL) { + lock_error(lock, func, file, line, "unlock nonlocked lock"); + } + if(lock->hold_count <= 0) + lock_error(lock, func, file, line, "too many unlocks"); + + /* store this point as last touched by */ + lock->holder = thr; + lock->hold_count --; + lock->holder_func = func; + lock->holder_file = file; + lock->holder_line = line; + + /* delete from thread holder list */ + /* no need to lock other lockstructs, because they are all on the + * held-locks list, and this thread holds their locks. + * we only touch the thr->num members, so it is safe. */ + if(thr->holding_first == lock) + thr->holding_first = lock->next_held_lock[thr->num]; + if(thr->holding_last == lock) + thr->holding_last = lock->prev_held_lock[thr->num]; + if(lock->next_held_lock[thr->num]) + lock->next_held_lock[thr->num]->prev_held_lock[thr->num] = + lock->prev_held_lock[thr->num]; + if(lock->prev_held_lock[thr->num]) + lock->prev_held_lock[thr->num]->next_held_lock[thr->num] = + lock->next_held_lock[thr->num]; + lock->next_held_lock[thr->num] = NULL; + lock->prev_held_lock[thr->num] = NULL; + + if(type==check_lock_rwlock && lock->writeholder == thr) { + lock->writeholder = NULL; + prot_store(lock); + } else if(type != check_lock_rwlock) { + /* store memory areas that are protected, for later checks */ + prot_store(lock); + } + LOCKRET(pthread_mutex_unlock(&lock->lock)); + + /* unlock it */ + switch(type) { + case check_lock_mutex: + LOCKRET(pthread_mutex_unlock(&lock->u.mutex)); + break; + case check_lock_spinlock: + LOCKRET(pthread_spin_unlock(&lock->u.spinlock)); + break; + case check_lock_rwlock: + LOCKRET(pthread_rwlock_unlock(&lock->u.rwlock)); + break; + default: + log_assert(0); + } +} + +/** open order info debug file, thr->num must be valid */ +static void +open_lockorder(struct thr_check* thr) +{ + char buf[24]; + time_t t; + snprintf(buf, sizeof(buf), "ublocktrace.%d", thr->num); + thr->order_info = fopen(buf, "w"); + if(!thr->order_info) + fatal_exit("could not open %s: %s", buf, strerror(errno)); + thr->locks_created = 0; + t = time(NULL); + /* write: */ + if(fwrite(&t, sizeof(t), 1, thr->order_info) != 1 || + fwrite(&thr->num, sizeof(thr->num), 1, thr->order_info) != 1 || + fwrite(&check_lock_pid, sizeof(check_lock_pid), 1, + thr->order_info) != 1) + log_err("fwrite: %s", strerror(errno)); +} + +/** checklock thread main, Inits thread structure */ +static void* checklock_main(void* arg) +{ + struct thr_check* thr = (struct thr_check*)arg; + void* ret; + thr->id = pthread_self(); + /* Hack to get same numbers as in log file */ + thr->num = *(int*)(thr->arg); + log_assert(thr->num < THRDEBUG_MAX_THREADS); + /* as an aside, due to this, won't work for libunbound bg thread */ + if(thread_infos[thr->num] != NULL) + log_warn("thread warning, thr->num %d not NULL", thr->num); + thread_infos[thr->num] = thr; + LOCKRET(pthread_setspecific(thr_debug_key, thr)); + if(check_locking_order) + open_lockorder(thr); + ret = thr->func(thr->arg); + thread_infos[thr->num] = NULL; + if(check_locking_order) + fclose(thr->order_info); + free(thr); + return ret; +} + +/** init the main thread */ +void checklock_start(void) +{ + if(!key_created) { + struct thr_check* thisthr = (struct thr_check*)calloc(1, + sizeof(struct thr_check)); + if(!thisthr) + fatal_exit("thrcreate: out of memory"); + key_created = 1; + check_lock_pid = getpid(); + LOCKRET(pthread_key_create(&thr_debug_key, NULL)); + LOCKRET(pthread_setspecific(thr_debug_key, thisthr)); + thread_infos[0] = thisthr; + if(check_locking_order) + open_lockorder(thisthr); + } +} + +/** stop checklocks */ +void checklock_stop(void) +{ + if(key_created) { + int i; + if(check_locking_order) + fclose(thread_infos[0]->order_info); + free(thread_infos[0]); + thread_infos[0] = NULL; + for(i = 0; i < THRDEBUG_MAX_THREADS; i++) + log_assert(thread_infos[i] == NULL); + /* should have been cleaned up. */ + LOCKRET(pthread_key_delete(thr_debug_key)); + key_created = 0; + } +} + +/** allocate debug info and create thread */ +void +checklock_thrcreate(pthread_t* id, void* (*func)(void*), void* arg) +{ + struct thr_check* thr = (struct thr_check*)calloc(1, + sizeof(struct thr_check)); + if(!thr) + fatal_exit("thrcreate: out of memory"); + if(!key_created) { + checklock_start(); + } + thr->func = func; + thr->arg = arg; + LOCKRET(pthread_create(id, NULL, checklock_main, thr)); +} + +/** count number of thread infos */ +static int +count_thread_infos(void) +{ + int cnt = 0; + int i; + for(i=0; icreate_thread, lock->create_instance, + lock->create_func, lock->create_file, lock->create_line); + log_info("lock type: %s", + (lock->type==check_lock_mutex)?"mutex": ( + (lock->type==check_lock_spinlock)?"spinlock": ( + (lock->type==check_lock_rwlock)?"rwlock": "badtype"))); + log_info("lock contention %u, history:%u, hold:%d, wait:%d", + (unsigned)lock->contention_count, (unsigned)lock->history_count, + lock->hold_count, lock->wait_count); + log_info("last touch %s %s %d", lock->holder_func, lock->holder_file, + lock->holder_line); + log_info("holder thread %d, writeholder thread %d", + lock->holder?lock->holder->num:-1, + lock->writeholder?lock->writeholder->num:-1); +} + +/** print debug locks held by a thread */ +static void +held_debug_info(struct thr_check* thr, struct checked_lock* lock) +{ + if(!lock) return; + lock_debug_info(lock); + held_debug_info(thr, lock->next_held_lock[thr->num]); +} + +/** print debug info for a thread */ +static void +thread_debug_info(struct thr_check* thr) +{ + struct checked_lock* w = NULL; + struct checked_lock* f = NULL; + struct checked_lock* l = NULL; + if(!thr) return; + log_info("pthread id is %x", (int)thr->id); + log_info("thread func is %x", (int)thr->func); + log_info("thread arg is %x (%d)", (int)thr->arg, + (thr->arg?*(int*)thr->arg:0)); + log_info("thread num is %d", thr->num); + log_info("locks created %d", thr->locks_created); + log_info("open file for lockinfo: %s", + thr->order_info?"yes, flushing":"no"); + fflush(thr->order_info); + w = thr->waiting; + f = thr->holding_first; + l = thr->holding_last; + log_info("thread waiting for a lock: %s %x", w?"yes":"no", (int)w); + lock_debug_info(w); + log_info("thread holding first: %s, last: %s", f?"yes":"no", + l?"yes":"no"); + held_debug_info(thr, f); +} + +static void +total_debug_info(void) +{ + int i; + log_info("checklocks: supervising %d threads.", + count_thread_infos()); + if(!key_created) { + log_info("No thread debug key created yet"); + } + for(i=0; i + +/** How many threads to allocate for */ +#define THRDEBUG_MAX_THREADS 32 /* threads */ +/** do we check locking order */ +extern int check_locking_order; + +/** + * Protection memory area. + * It is copied to a holding buffer to compare against later. + * Note that it may encompass the lock structure. + */ +struct protected_area { + /** where the memory region starts */ + void* region; + /** size of the region */ + size_t size; + /** backbuffer that holds a copy, of same size. */ + void* hold; + /** next protected area in list */ + struct protected_area* next; +}; + +/** + * Per thread information for locking debug wrappers. + */ +struct thr_check { + /** thread id */ + pthread_t id; + /** real thread func */ + void* (*func)(void*); + /** func user arg */ + void* arg; + /** number of thread in list structure */ + int num; + /** instance number - how many locks have been created by thread */ + int locks_created; + /** file to write locking order information to */ + FILE* order_info; + /** + * List of locks that this thread is holding, double + * linked list. The first element is the most recent lock acquired. + * So it represents the stack of locks acquired. (of all types). + */ + struct checked_lock *holding_first, *holding_last; + /** if the thread is currently waiting for a lock, which one */ + struct checked_lock* waiting; +}; + +/** + * One structure for all types of locks. + */ +struct checked_lock { + /** mutex for exclusive access to this structure */ + pthread_mutex_t lock; + /** list of memory regions protected by this checked lock */ + struct protected_area* prot; + /** where was this lock created */ + const char* create_func, *create_file; + /** where was this lock created */ + int create_line; + /** unique instance identifier */ + int create_thread, create_instance; + /** contention count */ + size_t contention_count; + /** number of times locked, ever */ + size_t history_count; + /** hold count (how many threads are holding this lock) */ + int hold_count; + /** how many threads are waiting for this lock */ + int wait_count; + /** who touched it last */ + const char* holder_func, *holder_file; + /** who touched it last */ + int holder_line; + /** who owns the lock now */ + struct thr_check* holder; + /** for rwlocks, the writelock holder */ + struct thr_check* writeholder; + + /** next lock a thread is holding (less recent) */ + struct checked_lock* next_held_lock[THRDEBUG_MAX_THREADS]; + /** prev lock a thread is holding (more recent) */ + struct checked_lock* prev_held_lock[THRDEBUG_MAX_THREADS]; + + /** type of lock */ + enum check_lock_type { + /** basic mutex */ + check_lock_mutex, + /** fast spinlock */ + check_lock_spinlock, + /** rwlock */ + check_lock_rwlock + } type; + /** the lock itself, see type to disambiguate the union */ + union { + /** mutex */ + pthread_mutex_t mutex; + /** spinlock */ + pthread_spinlock_t spinlock; + /** rwlock */ + pthread_rwlock_t rwlock; + } u; +}; + +/** + * Additional call for the user to specify what areas are protected + * @param lock: the lock that protects the area. It can be inside the area. + * The lock must be inited. Call with user lock. (any type). + * It demangles the lock itself (struct checked_lock**). + * @param area: ptr to mem. + * @param size: length of area. + * You can call it multiple times with the same lock to give several areas. + * Call it when you are done initialising the area, since it will be copied + * at this time and protected right away against unauthorised changes until + * the next lock() call is done. + */ +void lock_protect(void* lock, void* area, size_t size); + +/** + * Remove protected area from lock. + * No need to call this when deleting the lock. + * @param lock: the lock, any type, (struct checked_lock**). + * @param area: pointer to memory. + */ +void lock_unprotect(void* lock, void* area); + +/** + * Get memory associated with a checked lock + * @param lock: the checked lock, any type. (struct checked_lock**). + * @return: in bytes, including protected areas. + */ +size_t lock_get_mem(void* lock); + +/** + * Initialise checklock. Sets up internal debug structures. + */ +void checklock_start(void); + +/** + * Cleanup internal debug state. + */ +void checklock_stop(void); + +/** + * Init locks. + * @param type: what type of lock this is. + * @param lock: ptr to user alloced ptr structure. This is inited. + * So an alloc is done and the ptr is stored as result. + * @param func: caller function name. + * @param file: caller file name. + * @param line: caller line number. + */ +void checklock_init(enum check_lock_type type, struct checked_lock** lock, + const char* func, const char* file, int line); + +/** + * Destroy locks. Free the structure. + * @param type: what type of lock this is. + * @param lock: ptr to user alloced structure. This is destroyed. + * @param func: caller function name. + * @param file: caller file name. + * @param line: caller line number. + */ +void checklock_destroy(enum check_lock_type type, struct checked_lock** lock, + const char* func, const char* file, int line); + +/** + * Acquire readlock. + * @param type: what type of lock this is. Had better be a rwlock. + * @param lock: ptr to lock. + * @param func: caller function name. + * @param file: caller file name. + * @param line: caller line number. + */ +void checklock_rdlock(enum check_lock_type type, struct checked_lock* lock, + const char* func, const char* file, int line); + +/** + * Acquire writelock. + * @param type: what type of lock this is. Had better be a rwlock. + * @param lock: ptr to lock. + * @param func: caller function name. + * @param file: caller file name. + * @param line: caller line number. + */ +void checklock_wrlock(enum check_lock_type type, struct checked_lock* lock, + const char* func, const char* file, int line); + +/** + * Locks. + * @param type: what type of lock this is. Had better be mutex or spinlock. + * @param lock: the lock. + * @param func: caller function name. + * @param file: caller file name. + * @param line: caller line number. + */ +void checklock_lock(enum check_lock_type type, struct checked_lock* lock, + const char* func, const char* file, int line); + +/** + * Unlocks. + * @param type: what type of lock this is. + * @param lock: the lock. + * @param func: caller function name. + * @param file: caller file name. + * @param line: caller line number. + */ +void checklock_unlock(enum check_lock_type type, struct checked_lock* lock, + const char* func, const char* file, int line); + +/** + * Create thread. + * @param thr: Thread id, where to store result. + * @param func: thread start function. + * @param arg: user argument. + */ +void checklock_thrcreate(pthread_t* thr, void* (*func)(void*), void* arg); + +/** + * Wait for thread to exit. Returns thread return value. + * @param thread: thread to wait for. + */ +void checklock_thrjoin(pthread_t thread); + +/** structures to enable compiler type checking on the locks. + * Also the pointer makes it so that the lock can be part of the protected + * region without any possible problem (since the ptr will stay the same.) + * i.e. there can be contention and readlocks stored in checked_lock, while + * the protected area stays the same, even though it contains (ptr to) lock. + */ +struct checked_lock_rw { struct checked_lock* c_rw; }; +/** structures to enable compiler type checking on the locks. */ +struct checked_lock_mutex { struct checked_lock* c_m; }; +/** structures to enable compiler type checking on the locks. */ +struct checked_lock_spl { struct checked_lock* c_spl; }; + +/** debugging rwlock */ +typedef struct checked_lock_rw lock_rw_t; +#define lock_rw_init(lock) checklock_init(check_lock_rwlock, &((lock)->c_rw), __func__, __FILE__, __LINE__) +#define lock_rw_destroy(lock) checklock_destroy(check_lock_rwlock, &((lock)->c_rw), __func__, __FILE__, __LINE__) +#define lock_rw_rdlock(lock) checklock_rdlock(check_lock_rwlock, (lock)->c_rw, __func__, __FILE__, __LINE__) +#define lock_rw_wrlock(lock) checklock_wrlock(check_lock_rwlock, (lock)->c_rw, __func__, __FILE__, __LINE__) +#define lock_rw_unlock(lock) checklock_unlock(check_lock_rwlock, (lock)->c_rw, __func__, __FILE__, __LINE__) + +/** debugging mutex */ +typedef struct checked_lock_mutex lock_basic_t; +#define lock_basic_init(lock) checklock_init(check_lock_mutex, &((lock)->c_m), __func__, __FILE__, __LINE__) +#define lock_basic_destroy(lock) checklock_destroy(check_lock_mutex, &((lock)->c_m), __func__, __FILE__, __LINE__) +#define lock_basic_lock(lock) checklock_lock(check_lock_mutex, (lock)->c_m, __func__, __FILE__, __LINE__) +#define lock_basic_unlock(lock) checklock_unlock(check_lock_mutex, (lock)->c_m, __func__, __FILE__, __LINE__) + +/** debugging spinlock */ +typedef struct checked_lock_spl lock_quick_t; +#define lock_quick_init(lock) checklock_init(check_lock_spinlock, &((lock)->c_spl), __func__, __FILE__, __LINE__) +#define lock_quick_destroy(lock) checklock_destroy(check_lock_spinlock, &((lock)->c_spl), __func__, __FILE__, __LINE__) +#define lock_quick_lock(lock) checklock_lock(check_lock_spinlock, (lock)->c_spl, __func__, __FILE__, __LINE__) +#define lock_quick_unlock(lock) checklock_unlock(check_lock_spinlock, (lock)->c_spl, __func__, __FILE__, __LINE__) + +/** we use the pthread id, our thr_check structure is kept behind the scenes */ +typedef pthread_t ub_thread_t; +#define ub_thread_create(thr, func, arg) checklock_thrcreate(thr, func, arg) +#define ub_thread_self() pthread_self() +#define ub_thread_join(thread) checklock_thrjoin(thread) + +typedef pthread_key_t ub_thread_key_t; +#define ub_thread_key_create(key, f) LOCKRET(pthread_key_create(key, f)) +#define ub_thread_key_set(key, v) LOCKRET(pthread_setspecific(key, v)) +#define ub_thread_key_get(key) pthread_getspecific(key) + +#endif /* USE_THREAD_DEBUG */ +#endif /* TESTCODE_CHECK_LOCKS_H */ diff --git a/testcode/delayer.c b/testcode/delayer.c new file mode 100644 index 00000000000..b42a3b1aa7c --- /dev/null +++ b/testcode/delayer.c @@ -0,0 +1,1185 @@ +/* + * testcode/delayer.c - debug program that delays queries to a server. + * + * Copyright (c) 2008, 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This program delays queries made. It performs as a proxy to another + * server and delays queries to it. + */ + +#include "config.h" +#ifdef HAVE_GETOPT_H +#include +#endif +#ifdef HAVE_TIME_H +#include +#endif +#include +#include "util/net_help.h" +#include "util/config_file.h" +#include + +/** number of reads per select for delayer */ +#define TRIES_PER_SELECT 100 + +/** + * The ring buffer + */ +struct ringbuf { + /** base of buffer */ + uint8_t* buf; + /** size of buffer */ + size_t size; + /** low mark, items start here */ + size_t low; + /** high mark, items end here */ + size_t high; +}; + +/** + * List of proxy fds that return replies from the server to our clients. + */ +struct proxy { + /** the fd to listen for replies from server */ + int s; + /** last time this was used */ + struct timeval lastuse; + /** remote address */ + struct sockaddr_storage addr; + /** length of addr */ + socklen_t addr_len; + /** number of queries waiting (in total) */ + size_t numwait; + /** number of queries sent to server (in total) */ + size_t numsent; + /** numberof answers returned to client (in total) */ + size_t numreturn; + /** how many times repurposed */ + size_t numreuse; + /** next in proxylist */ + struct proxy* next; +}; + +/** + * An item that has to be TCP relayed + */ +struct tcp_send_list { + /** the data item */ + uint8_t* item; + /** size of item */ + size_t len; + /** time when the item can be transmitted on */ + struct timeval wait; + /** how much of the item has already been transmitted */ + size_t done; + /** next in list */ + struct tcp_send_list* next; +}; + +/** + * List of TCP proxy fd pairs to TCP connect client to server + */ +struct tcp_proxy { + /** the fd to listen for client query */ + int client_s; + /** the fd to listen for server answer */ + int server_s; + + /** remote client address */ + struct sockaddr_storage addr; + /** length of address */ + socklen_t addr_len; + /** timeout on this entry */ + struct timeval timeout; + + /** list of query items to send to server */ + struct tcp_send_list* querylist; + /** last in query list */ + struct tcp_send_list* querylast; + /** list of answer items to send to client */ + struct tcp_send_list* answerlist; + /** last in answerlist */ + struct tcp_send_list* answerlast; + + /** next in list */ + struct tcp_proxy* next; +}; + +/** usage information for delayer */ +static void usage(char* argv[]) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" -f addr : use addr, forward to that server, @port.\n"); + printf(" -b addr : bind to this address to listen.\n"); + printf(" -p port : bind to this port (use 0 for random).\n"); + printf(" -m mem : use this much memory for waiting queries.\n"); + printf(" -d delay: UDP queries are delayed n milliseconds.\n"); + printf(" TCP is delayed twice (on send, on recv).\n"); + printf(" -h : this help message\n"); + exit(1); +} + +/** timeval compare, t1 < t2 */ +static int +dl_tv_smaller(struct timeval* t1, const struct timeval* t2) +{ +#ifndef S_SPLINT_S + if(t1->tv_sec < t2->tv_sec) + return 1; + if(t1->tv_sec == t2->tv_sec && + t1->tv_usec < t2->tv_usec) + return 1; +#endif + return 0; +} + +/** timeval add, t1 += t2 */ +static void +dl_tv_add(struct timeval* t1, const struct timeval* t2) +{ +#ifndef S_SPLINT_S + t1->tv_sec += t2->tv_sec; + t1->tv_usec += t2->tv_usec; + while(t1->tv_usec > 1000000) { + t1->tv_usec -= 1000000; + t1->tv_sec++; + } +#endif +} + +/** timeval subtract, t1 -= t2 */ +static void +dl_tv_subtract(struct timeval* t1, const struct timeval* t2) +{ +#ifndef S_SPLINT_S + t1->tv_sec -= t2->tv_sec; + if(t1->tv_usec >= t2->tv_usec) { + t1->tv_usec -= t2->tv_usec; + } else { + t1->tv_sec--; + t1->tv_usec = 1000000-(t2->tv_usec-t1->tv_usec); + } +#endif +} + + +/** create new ring buffer */ +static struct ringbuf* +ring_create(size_t sz) +{ + struct ringbuf* r = (struct ringbuf*)calloc(1, sizeof(*r)); + if(!r) fatal_exit("out of memory"); + r->buf = (uint8_t*)malloc(sz); + if(!r->buf) fatal_exit("out of memory"); + r->size = sz; + r->low = 0; + r->high = 0; + return r; +} + +/** delete ring buffer */ +static void +ring_delete(struct ringbuf* r) +{ + if(!r) return; + free(r->buf); + free(r); +} + +/** add entry to ringbuffer */ +static void +ring_add(struct ringbuf* r, ldns_buffer* pkt, struct timeval* now, + struct timeval* delay, struct proxy* p) +{ + /* time -- proxy* -- 16bitlen -- message */ + uint16_t len = (uint16_t)ldns_buffer_limit(pkt); + struct timeval when; + size_t needed; + uint8_t* where = NULL; + log_assert(ldns_buffer_limit(pkt) <= 65535); + needed = sizeof(when) + sizeof(p) + sizeof(len) + len; + /* put item into ringbuffer */ + if(r->low < r->high) { + /* used part is in the middle */ + if(r->size - r->high >= needed) { + where = r->buf + r->high; + r->high += needed; + } else if(r->low > needed) { + /* wrap around ringbuffer */ + /* make sure r->low == r->high means empty */ + /* so r->low == r->high cannot be used to signify + * a completely full ringbuf */ + if(r->size - r->high > sizeof(when)+sizeof(p)) { + /* zero entry at end of buffer */ + memset(r->buf+r->high, 0, + sizeof(when)+sizeof(p)); + } + where = r->buf; + r->high = needed; + } else { + /* drop message */ + log_warn("warning: mem full, dropped message"); + return; + } + } else { + /* empty */ + if(r->high == r->low) { + where = r->buf; + r->low = 0; + r->high = needed; + /* unused part is in the middle */ + /* so ringbuffer has wrapped around */ + } else if(r->low - r->high > needed) { + where = r->buf + r->high; + r->high += needed; + } else { + log_warn("warning: mem full, dropped message"); + return; + } + } + when = *now; + dl_tv_add(&when, delay); + /* copy it at where part */ + log_assert(where != NULL); + memmove(where, &when, sizeof(when)); + memmove(where+sizeof(when), &p, sizeof(p)); + memmove(where+sizeof(when)+sizeof(p), &len, sizeof(len)); + memmove(where+sizeof(when)+sizeof(p)+sizeof(len), + ldns_buffer_begin(pkt), len); +} + +/** see if the ringbuffer is empty */ +static int +ring_empty(struct ringbuf* r) +{ + return (r->low == r->high); +} + +/** peek at timevalue for next item in ring */ +static struct timeval* +ring_peek_time(struct ringbuf* r) +{ + if(ring_empty(r)) + return NULL; + return (struct timeval*)&r->buf[r->low]; +} + +/** get entry from ringbuffer */ +static int +ring_pop(struct ringbuf* r, ldns_buffer* pkt, struct timeval* tv, + struct proxy** p) +{ + /* time -- proxy* -- 16bitlen -- message */ + uint16_t len; + uint8_t* where = NULL; + size_t done; + if(r->low == r->high) + return 0; + where = r->buf + r->low; + memmove(tv, where, sizeof(*tv)); + memmove(p, where+sizeof(*tv), sizeof(*p)); + memmove(&len, where+sizeof(*tv)+sizeof(*p), sizeof(len)); + memmove(ldns_buffer_begin(pkt), + where+sizeof(*tv)+sizeof(*p)+sizeof(len), len); + ldns_buffer_set_limit(pkt, (size_t)len); + done = sizeof(*tv)+sizeof(*p)+sizeof(len)+len; + /* move lowmark */ + if(r->low < r->high) { + /* used part in middle */ + log_assert(r->high - r->low >= done); + r->low += done; + } else { + /* unused part in middle */ + log_assert(r->size - r->low >= done); + r->low += done; + if(r->size - r->low > sizeof(*tv)+sizeof(*p)) { + /* see if it is zeroed; means end of buffer */ + struct proxy* pz; + memmove(&pz, r->buf+r->low+sizeof(*tv), sizeof(pz)); + if(pz == NULL) + r->low = 0; + } else r->low = 0; + } + if(r->low == r->high) { + r->low = 0; /* reset if empty */ + r->high = 0; + } + return 1; +} + +/** signal handler global info */ +static volatile int do_quit = 0; + +/** signal handler for user quit */ +static RETSIGTYPE delayer_sigh(int sig) +{ + printf("exit on signal %d\n", sig); + do_quit = 1; +} + +/** send out waiting packets */ +static void +service_send(struct ringbuf* ring, struct timeval* now, ldns_buffer* pkt, + struct sockaddr_storage* srv_addr, socklen_t srv_len) +{ + struct proxy* p; + struct timeval tv; + ssize_t sent; + while(!ring_empty(ring) && + dl_tv_smaller(ring_peek_time(ring), now)) { + /* this items needs to be sent out */ + if(!ring_pop(ring, pkt, &tv, &p)) + fatal_exit("ringbuf error: pop failed"); + verbose(1, "send out query %d.%6.6d", + (unsigned)tv.tv_sec, (unsigned)tv.tv_usec); + log_addr(1, "from client", &p->addr, p->addr_len); + /* send it */ + sent = sendto(p->s, (void*)ldns_buffer_begin(pkt), + ldns_buffer_limit(pkt), 0, + (struct sockaddr*)srv_addr, srv_len); + if(sent == -1) { +#ifndef USE_WINSOCK + log_err("sendto: %s", strerror(errno)); +#else + log_err("sendto: %s", wsa_strerror(WSAGetLastError())); +#endif + } else if(sent != (ssize_t)ldns_buffer_limit(pkt)) { + log_err("sendto: partial send"); + } + p->lastuse = *now; + p->numsent++; + } +} + +/** do proxy for one readable client */ +static void +do_proxy(struct proxy* p, int retsock, ldns_buffer* pkt) +{ + int i; + ssize_t r; + for(i=0; is, (void*)ldns_buffer_begin(pkt), + ldns_buffer_capacity(pkt), 0); + if(r == -1) { +#ifndef USE_WINSOCK + if(errno == EAGAIN || errno == EINTR) + return; + log_err("recv: %s", strerror(errno)); +#else + if(WSAGetLastError() == WSAEINPROGRESS || + WSAGetLastError() == WSAEWOULDBLOCK) + return; + log_err("recv: %s", wsa_strerror(WSAGetLastError())); +#endif + return; + } + ldns_buffer_set_limit(pkt, (size_t)r); + log_addr(1, "return reply to client", &p->addr, p->addr_len); + /* send reply back to the real client */ + p->numreturn++; + r = sendto(retsock, (void*)ldns_buffer_begin(pkt), (size_t)r, + 0, (struct sockaddr*)&p->addr, p->addr_len); + if(r == -1) { +#ifndef USE_WINSOCK + log_err("sendto: %s", strerror(errno)); +#else + log_err("sendto: %s", wsa_strerror(WSAGetLastError())); +#endif + } + } +} + +/** proxy return replies to clients */ +static void +service_proxy(fd_set* rset, int retsock, struct proxy* proxies, + ldns_buffer* pkt, struct timeval* now) +{ + struct proxy* p; + for(p = proxies; p; p = p->next) { + if(FD_ISSET(p->s, rset)) { + p->lastuse = *now; + do_proxy(p, retsock, pkt); + } + } +} + +/** find or else create proxy for this remote client */ +static struct proxy* +find_create_proxy(struct sockaddr_storage* from, socklen_t from_len, + fd_set* rorig, int* max, struct proxy** proxies, int serv_ip6, + struct timeval* now, struct timeval* reuse_timeout) +{ + struct proxy* p; + struct timeval t; + for(p = *proxies; p; p = p->next) { + if(sockaddr_cmp(from, from_len, &p->addr, p->addr_len)==0) + return p; + } + /* possibly: reuse lapsed entries */ + for(p = *proxies; p; p = p->next) { + if(p->numwait > p->numsent || p->numsent > p->numreturn) + continue; + t = *now; + dl_tv_subtract(&t, &p->lastuse); + if(dl_tv_smaller(&t, reuse_timeout)) + continue; + /* yes! */ + verbose(1, "reuse existing entry"); + memmove(&p->addr, from, from_len); + p->addr_len = from_len; + p->numreuse++; + return p; + } + /* create new */ + p = (struct proxy*)calloc(1, sizeof(*p)); + if(!p) fatal_exit("out of memory"); + p->s = socket(serv_ip6?AF_INET6:AF_INET, SOCK_DGRAM, 0); + if(p->s == -1) { +#ifndef USE_WINSOCK + fatal_exit("socket: %s", strerror(errno)); +#else + fatal_exit("socket: %s", wsa_strerror(WSAGetLastError())); +#endif + } + fd_set_nonblock(p->s); + memmove(&p->addr, from, from_len); + p->addr_len = from_len; + p->next = *proxies; + *proxies = p; + FD_SET(FD_SET_T p->s, rorig); + if(p->s+1 > *max) + *max = p->s+1; + return p; +} + +/** recv new waiting packets */ +static void +service_recv(int s, struct ringbuf* ring, ldns_buffer* pkt, + fd_set* rorig, int* max, struct proxy** proxies, + struct sockaddr_storage* srv_addr, socklen_t srv_len, + struct timeval* now, struct timeval* delay, struct timeval* reuse) +{ + int i; + struct sockaddr_storage from; + socklen_t from_len; + ssize_t len; + struct proxy* p; + for(i=0; ilastuse = *now; + ring_add(ring, pkt, now, delay, p); + p->numwait++; + log_addr(1, "recv from client", &p->addr, p->addr_len); + } +} + +/** delete tcp proxy */ +static void +tcp_proxy_delete(struct tcp_proxy* p) +{ + struct tcp_send_list* s, *sn; + if(!p) + return; + log_addr(1, "delete tcp proxy", &p->addr, p->addr_len); + s = p->querylist; + while(s) { + sn = s->next; + free(s->item); + free(s); + s = sn; + } + s = p->answerlist; + while(s) { + sn = s->next; + free(s->item); + free(s); + s = sn; + } +#ifndef USE_WINSOCK + close(p->client_s); + if(p->server_s != -1) + close(p->server_s); +#else + closesocket(p->client_s); + if(p->server_s != -1) + closesocket(p->server_s); +#endif + free(p); +} + +/** accept new TCP connections, and set them up */ +static void +service_tcp_listen(int s, fd_set* rorig, int* max, struct tcp_proxy** proxies, + struct sockaddr_storage* srv_addr, socklen_t srv_len, + struct timeval* now, struct timeval* tcp_timeout) +{ + int newfd; + struct sockaddr_storage addr; + struct tcp_proxy* p; + socklen_t addr_len; + newfd = accept(s, (struct sockaddr*)&addr, &addr_len); + if(newfd == -1) { +#ifndef USE_WINSOCK + if(errno == EAGAIN || errno == EINTR) + return; + fatal_exit("accept: %s", strerror(errno)); +#else + if(WSAGetLastError() == WSAEWOULDBLOCK || + WSAGetLastError() == WSAEINPROGRESS || + WSAGetLastError() == WSAECONNRESET) + return; + fatal_exit("accept: %s", wsa_strerror(WSAGetLastError())); +#endif + } + p = (struct tcp_proxy*)calloc(1, sizeof(*p)); + if(!p) fatal_exit("out of memory"); + memmove(&p->addr, &addr, addr_len); + p->addr_len = addr_len; + log_addr(1, "new tcp proxy", &p->addr, p->addr_len); + p->client_s = newfd; + p->server_s = socket(addr_is_ip6(srv_addr, srv_len)?AF_INET6:AF_INET, + SOCK_STREAM, 0); + if(p->server_s == -1) { +#ifndef USE_WINSOCK + fatal_exit("tcp socket: %s", strerror(errno)); +#else + fatal_exit("tcp socket: %s", wsa_strerror(WSAGetLastError())); +#endif + } + fd_set_nonblock(p->client_s); + fd_set_nonblock(p->server_s); + if(connect(p->server_s, (struct sockaddr*)srv_addr, srv_len) == -1) { +#ifndef USE_WINSOCK + if(errno != EINPROGRESS) { + log_err("tcp connect: %s", strerror(errno)); + close(p->server_s); + close(p->client_s); +#else + if(WSAGetLastError() != WSAEWOULDBLOCK && + WSAGetLastError() != WSAEINPROGRESS) { + log_err("tcp connect: %s", + wsa_strerror(WSAGetLastError())); + closesocket(p->server_s); + closesocket(p->client_s); +#endif + free(p); + return; + } + } + p->timeout = *now; + dl_tv_add(&p->timeout, tcp_timeout); + + /* listen to client and server */ + FD_SET(FD_SET_T p->client_s, rorig); + FD_SET(FD_SET_T p->server_s, rorig); + if(p->client_s+1 > *max) + *max = p->client_s+1; + if(p->server_s+1 > *max) + *max = p->server_s+1; + + /* add into proxy list */ + p->next = *proxies; + *proxies = p; +} + +/** relay TCP, read a part */ +static int +tcp_relay_read(int s, struct tcp_send_list** first, + struct tcp_send_list** last, struct timeval* now, + struct timeval* delay, ldns_buffer* pkt) +{ + struct tcp_send_list* item; + ssize_t r = recv(s, (void*)ldns_buffer_begin(pkt), + ldns_buffer_capacity(pkt), 0); + if(r == -1) { +#ifndef USE_WINSOCK + if(errno == EINTR || errno == EAGAIN) + return 1; + log_err("tcp read: %s", strerror(errno)); +#else + if(WSAGetLastError() == WSAEINPROGRESS || + WSAGetLastError() == WSAEWOULDBLOCK) + return 1; + log_err("tcp read: %s", wsa_strerror(WSAGetLastError())); +#endif + return 0; + } else if(r == 0) { + /* connection closed */ + return 0; + } + item = (struct tcp_send_list*)malloc(sizeof(*item)); + if(!item) { + log_err("out of memory"); + return 0; + } + verbose(1, "read item len %d", (int)r); + item->len = (size_t)r; + item->item = memdup(ldns_buffer_begin(pkt), item->len); + if(!item->item) { + free(item); + log_err("out of memory"); + return 0; + } + item->done = 0; + item->wait = *now; + dl_tv_add(&item->wait, delay); + item->next = NULL; + + /* link in */ + if(*first) { + (*last)->next = item; + } else { + *first = item; + } + *last = item; + return 1; +} + +/** relay TCP, write a part */ +static int +tcp_relay_write(int s, struct tcp_send_list** first, + struct tcp_send_list** last, struct timeval* now) +{ + ssize_t r; + struct tcp_send_list* p; + while(*first) { + p = *first; + /* is the item ready? */ + if(!dl_tv_smaller(&p->wait, now)) + return 1; + /* write it */ + r = send(s, (void*)(p->item + p->done), p->len - p->done, 0); + if(r == -1) { +#ifndef USE_WINSOCK + if(errno == EAGAIN || errno == EINTR) + return 1; + log_err("tcp write: %s", strerror(errno)); +#else + if(WSAGetLastError() == WSAEWOULDBLOCK || + WSAGetLastError() == WSAEINPROGRESS) + return 1; + log_err("tcp write: %s", + wsa_strerror(WSAGetLastError())); +#endif + return 0; + } else if(r == 0) { + /* closed */ + return 0; + } + /* account it */ + p->done += (size_t)r; + verbose(1, "write item %d of %d", (int)p->done, (int)p->len); + if(p->done >= p->len) { + free(p->item); + *first = p->next; + if(!*first) + *last = NULL; + free(p); + } else { + /* partial write */ + return 1; + } + } + return 1; +} + +/** perform TCP relaying */ +static void +service_tcp_relay(struct tcp_proxy** tcp_proxies, struct timeval* now, + struct timeval* delay, struct timeval* tcp_timeout, ldns_buffer* pkt, + fd_set* rset, fd_set* rorig, fd_set* worig) +{ + struct tcp_proxy* p, **prev; + struct timeval tout; + int delete_it; + p = *tcp_proxies; + prev = tcp_proxies; + tout = *now; + dl_tv_add(&tout, tcp_timeout); + + while(p) { + delete_it = 0; + /* can we receive further queries? */ + if(!delete_it && FD_ISSET(p->client_s, rset)) { + p->timeout = tout; + log_addr(1, "read tcp query", &p->addr, p->addr_len); + if(!tcp_relay_read(p->client_s, &p->querylist, + &p->querylast, now, delay, pkt)) + delete_it = 1; + } + /* can we receive further answers? */ + if(!delete_it && p->server_s != -1 && + FD_ISSET(p->server_s, rset)) { + p->timeout = tout; + log_addr(1, "read tcp answer", &p->addr, p->addr_len); + if(!tcp_relay_read(p->server_s, &p->answerlist, + &p->answerlast, now, delay, pkt)) { +#ifndef USE_WINSOCK + close(p->server_s); +#else + closesocket(p->server_s); +#endif + FD_CLR(FD_SET_T p->server_s, worig); + FD_CLR(FD_SET_T p->server_s, rorig); + p->server_s = -1; + } + } + /* can we send on further queries */ + if(!delete_it && p->querylist && p->server_s != -1) { + p->timeout = tout; + if(dl_tv_smaller(&p->querylist->wait, now)) + log_addr(1, "write tcp query", + &p->addr, p->addr_len); + if(!tcp_relay_write(p->server_s, &p->querylist, + &p->querylast, now)) + delete_it = 1; + if(p->querylist && p->server_s != -1 && + dl_tv_smaller(&p->querylist->wait, now)) + FD_SET(FD_SET_T p->server_s, worig); + else FD_CLR(FD_SET_T p->server_s, worig); + } + + /* can we send on further answers */ + if(!delete_it && p->answerlist) { + p->timeout = tout; + if(dl_tv_smaller(&p->answerlist->wait, now)) + log_addr(1, "write tcp answer", + &p->addr, p->addr_len); + if(!tcp_relay_write(p->client_s, &p->answerlist, + &p->answerlast, now)) + delete_it = 1; + if(p->answerlist && dl_tv_smaller(&p->answerlist->wait, + now)) + FD_SET(FD_SET_T p->client_s, worig); + else FD_CLR(FD_SET_T p->client_s, worig); + if(!p->answerlist && p->server_s == -1) + delete_it = 1; + } + + /* does this entry timeout? (unused too long) */ + if(dl_tv_smaller(&p->timeout, now)) { + delete_it = 1; + } + if(delete_it) { + struct tcp_proxy* np = p->next; + *prev = np; + FD_CLR(FD_SET_T p->client_s, rorig); + FD_CLR(FD_SET_T p->client_s, worig); + if(p->server_s != -1) { + FD_CLR(FD_SET_T p->server_s, rorig); + FD_CLR(FD_SET_T p->server_s, worig); + } + tcp_proxy_delete(p); + p = np; + continue; + } + + prev = &p->next; + p = p->next; + } +} + +/** find waiting time */ +static int +service_findwait(struct timeval* now, struct timeval* wait, + struct ringbuf* ring, struct tcp_proxy* tcplist) +{ + /* first item is the time to wait */ + struct timeval* peek = ring_peek_time(ring); + struct timeval tcv; + int have_tcpval = 0; + struct tcp_proxy* p; + + /* also for TCP list the first in sendlists is the time to wait */ + for(p=tcplist; p; p=p->next) { + if(!have_tcpval) + tcv = p->timeout; + have_tcpval = 1; + if(dl_tv_smaller(&p->timeout, &tcv)) + tcv = p->timeout; + if(p->querylist && dl_tv_smaller(&p->querylist->wait, &tcv)) + tcv = p->querylist->wait; + if(p->answerlist && dl_tv_smaller(&p->answerlist->wait, &tcv)) + tcv = p->answerlist->wait; + } + if(peek) { + /* peek can be unaligned */ + /* use wait as a temp variable */ + memmove(wait, peek, sizeof(*wait)); + if(!have_tcpval) + tcv = *wait; + else if(dl_tv_smaller(wait, &tcv)) + tcv = *wait; + have_tcpval = 1; + } + if(have_tcpval) { + *wait = tcv; + dl_tv_subtract(wait, now); + return 1; + } + /* nothing, block */ + return 0; +} + +/** clear proxy list */ +static void +proxy_list_clear(struct proxy* p) +{ + char from[109]; + struct proxy* np; + int i=0, port; + while(p) { + np = p->next; + port = (int)ntohs(((struct sockaddr_in*)&p->addr)->sin_port); + if(addr_is_ip6(&p->addr, p->addr_len)) { + if(inet_ntop(AF_INET6, + &((struct sockaddr_in6*)&p->addr)->sin6_addr, + from, (socklen_t)sizeof(from)) == 0) + strncpy(from, "err", sizeof(from)); + } else { + if(inet_ntop(AF_INET, + &((struct sockaddr_in*)&p->addr)->sin_addr, + from, (socklen_t)sizeof(from)) == 0) + strncpy(from, "err", sizeof(from)); + } + printf("client[%d]: last %s@%d of %d : %u in, %u out, " + "%u returned\n", i++, from, port, (int)p->numreuse+1, + (unsigned)p->numwait, (unsigned)p->numsent, + (unsigned)p->numreturn); +#ifndef USE_WINSOCK + close(p->s); +#else + closesocket(p->s); +#endif + free(p); + p = np; + } +} + +/** clear TCP proxy list */ +static void +tcp_proxy_list_clear(struct tcp_proxy* p) +{ + struct tcp_proxy* np; + while(p) { + np = p->next; + tcp_proxy_delete(p); + p = np; + } +} + +/** delayer service loop */ +static void +service_loop(int udp_s, int listen_s, struct ringbuf* ring, + struct timeval* delay, struct timeval* reuse, + struct sockaddr_storage* srv_addr, socklen_t srv_len, + ldns_buffer* pkt) +{ + fd_set rset, rorig; + fd_set wset, worig; + struct timeval now, wait; + int max, have_wait = 0; + struct proxy* proxies = NULL; + struct tcp_proxy* tcp_proxies = NULL; + struct timeval tcp_timeout; + tcp_timeout.tv_sec = 120; + tcp_timeout.tv_usec = 0; +#ifndef S_SPLINT_S + FD_ZERO(&rorig); + FD_ZERO(&worig); + FD_SET(FD_SET_T udp_s, &rorig); + FD_SET(FD_SET_T listen_s, &rorig); +#endif + max = udp_s + 1; + if(listen_s + 1 > max) max = listen_s + 1; + while(!do_quit) { + /* wait for events */ + rset = rorig; + wset = worig; + if(have_wait) + verbose(1, "wait for %d.%6.6d", + (unsigned)wait.tv_sec, (unsigned)wait.tv_usec); + else verbose(1, "wait"); + if(select(max, &rset, &wset, NULL, have_wait?&wait:NULL) < 0) { + if(errno == EAGAIN || errno == EINTR) + continue; + fatal_exit("select: %s", strerror(errno)); + } + /* get current time */ + if(gettimeofday(&now, NULL) < 0) { + if(errno == EAGAIN || errno == EINTR) + continue; + fatal_exit("gettimeofday: %s", strerror(errno)); + } + verbose(1, "process at %u.%6.6u\n", + (unsigned)now.tv_sec, (unsigned)now.tv_usec); + /* sendout delayed queries to master server (frees up buffer)*/ + service_send(ring, &now, pkt, srv_addr, srv_len); + /* proxy return replies */ + service_proxy(&rset, udp_s, proxies, pkt, &now); + /* see what can be received to start waiting */ + service_recv(udp_s, ring, pkt, &rorig, &max, &proxies, + srv_addr, srv_len, &now, delay, reuse); + /* see if there are new tcp connections */ + service_tcp_listen(listen_s, &rorig, &max, &tcp_proxies, + srv_addr, srv_len, &now, &tcp_timeout); + /* service tcp connections */ + service_tcp_relay(&tcp_proxies, &now, delay, &tcp_timeout, + pkt, &rset, &rorig, &worig); + /* see what next timeout is (if any) */ + have_wait = service_findwait(&now, &wait, ring, tcp_proxies); + } + proxy_list_clear(proxies); + tcp_proxy_list_clear(tcp_proxies); +} + +/** delayer main service routine */ +static void +service(const char* bind_str, int bindport, const char* serv_str, + size_t memsize, int delay_msec) +{ + struct sockaddr_storage bind_addr, srv_addr; + socklen_t bind_len, srv_len; + struct ringbuf* ring = ring_create(memsize); + struct timeval delay, reuse; + ldns_buffer* pkt; + int i, s, listen_s; +#ifndef S_SPLINT_S + delay.tv_sec = delay_msec / 1000; + delay.tv_usec = (delay_msec % 1000)*1000; +#endif + reuse = delay; /* reuse is max(4*delay, 1 second) */ + dl_tv_add(&reuse, &delay); + dl_tv_add(&reuse, &delay); + dl_tv_add(&reuse, &delay); + if(reuse.tv_sec == 0) + reuse.tv_sec = 1; + if(!extstrtoaddr(serv_str, &srv_addr, &srv_len)) { + printf("cannot parse forward address: %s\n", serv_str); + exit(1); + } + pkt = ldns_buffer_new(65535); + if(!pkt) + fatal_exit("out of memory"); + if( signal(SIGINT, delayer_sigh) == SIG_ERR || +#ifdef SIGHUP + signal(SIGHUP, delayer_sigh) == SIG_ERR || +#endif +#ifdef SIGQUIT + signal(SIGQUIT, delayer_sigh) == SIG_ERR || +#endif +#ifdef SIGBREAK + signal(SIGBREAK, delayer_sigh) == SIG_ERR || +#endif +#ifdef SIGALRM + signal(SIGALRM, delayer_sigh) == SIG_ERR || +#endif + signal(SIGTERM, delayer_sigh) == SIG_ERR) + fatal_exit("could not bind to signal"); + /* bind UDP port */ + if((s = socket(str_is_ip6(bind_str)?AF_INET6:AF_INET, + SOCK_DGRAM, 0)) == -1) { +#ifndef USE_WINSOCK + fatal_exit("socket: %s", strerror(errno)); +#else + fatal_exit("socket: %s", wsa_strerror(WSAGetLastError())); +#endif + } + i=0; + if(bindport == 0) { + bindport = 1024 + random()%64000; + i = 100; + } + while(1) { + if(!ipstrtoaddr(bind_str, bindport, &bind_addr, &bind_len)) { + printf("cannot parse listen address: %s\n", bind_str); + exit(1); + } + if(bind(s, (struct sockaddr*)&bind_addr, bind_len) == -1) { +#ifndef USE_WINSOCK + log_err("bind: %s", strerror(errno)); +#else + log_err("bind: %s", wsa_strerror(WSAGetLastError())); +#endif + if(i--==0) + fatal_exit("cannot bind any port"); + bindport = 1024 + random()%64000; + } else break; + } + fd_set_nonblock(s); + /* and TCP port */ + if((listen_s = socket(str_is_ip6(bind_str)?AF_INET6:AF_INET, + SOCK_STREAM, 0)) == -1) { +#ifndef USE_WINSOCK + fatal_exit("tcp socket: %s", strerror(errno)); +#else + fatal_exit("tcp socket: %s", wsa_strerror(WSAGetLastError())); +#endif + } +#ifdef SO_REUSEADDR + if(1) { + int on = 1; + if(setsockopt(listen_s, SOL_SOCKET, SO_REUSEADDR, (void*)&on, + (socklen_t)sizeof(on)) < 0) +#ifndef USE_WINSOCK + fatal_exit("setsockopt(.. SO_REUSEADDR ..) failed: %s", + strerror(errno)); +#else + fatal_exit("setsockopt(.. SO_REUSEADDR ..) failed: %s", + wsa_strerror(WSAGetLastError())); +#endif + } +#endif + if(bind(listen_s, (struct sockaddr*)&bind_addr, bind_len) == -1) { +#ifndef USE_WINSOCK + fatal_exit("tcp bind: %s", strerror(errno)); +#else + fatal_exit("tcp bind: %s", wsa_strerror(WSAGetLastError())); +#endif + } + if(listen(listen_s, 5) == -1) { +#ifndef USE_WINSOCK + fatal_exit("tcp listen: %s", strerror(errno)); +#else + fatal_exit("tcp listen: %s", wsa_strerror(WSAGetLastError())); +#endif + } + fd_set_nonblock(listen_s); + printf("listening on port: %d\n", bindport); + + /* process loop */ + do_quit = 0; + service_loop(s, listen_s, ring, &delay, &reuse, &srv_addr, srv_len, + pkt); + + /* cleanup */ + verbose(1, "cleanup"); +#ifndef USE_WINSOCK + close(s); + close(listen_s); +#else + closesocket(s); + closesocket(listen_s); +#endif + ldns_buffer_free(pkt); + ring_delete(ring); +} + +/** getopt global, in case header files fail to declare it. */ +extern int optind; +/** getopt global, in case header files fail to declare it. */ +extern char* optarg; + +/** main program for delayer */ +int main(int argc, char** argv) +{ + int c; /* defaults */ + const char* server = "127.0.0.1@53"; + const char* bindto = "0.0.0.0"; + int bindport = 0; + size_t memsize = 10*1024*1024; + int delay = 100; + + verbosity = 0; + log_init(0, 0, 0); + log_ident_set("delayer"); + srandom(time(NULL) ^ getpid()); + if(argc == 1) usage(argv); + while( (c=getopt(argc, argv, "b:d:f:hm:p:")) != -1) { + switch(c) { + case 'b': + bindto = optarg; + break; + case 'd': + if(atoi(optarg)==0 && strcmp(optarg,"0")!=0) { + printf("bad delay: %s\n", optarg); + return 1; + } + delay = atoi(optarg); + break; + case 'f': + server = optarg; + break; + case 'm': + if(!cfg_parse_memsize(optarg, &memsize)) { + printf("bad memsize: %s\n", optarg); + return 1; + } + break; + case 'p': + if(atoi(optarg)==0 && strcmp(optarg,"0")!=0) { + printf("bad port nr: %s\n", optarg); + return 1; + } + bindport = atoi(optarg); + break; + case 'h': + case '?': + default: + usage(argv); + } + } + argc -= optind; + argv += optind; + if(argc != 0) + usage(argv); + + printf("bind to %s @ %d and forward to %s after %d msec\n", + bindto, bindport, server, delay); + service(bindto, bindport, server, memsize, delay); + return 0; +} diff --git a/testcode/do-tests.sh b/testcode/do-tests.sh new file mode 100755 index 00000000000..84d2ef566fd --- /dev/null +++ b/testcode/do-tests.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash +. testdata/common.sh + +NEED_SPLINT='00-lint.tpkg' +NEED_DOXYGEN='01-doc.tpkg' +NEED_XXD='fwd_compress_c00c.tpkg fwd_zero.tpkg' +NEED_NC='fwd_compress_c00c.tpkg fwd_zero.tpkg' +NEED_CURL='06-ianaports.tpkg root_anchor.tpkg' +NEED_WHOAMI='07-confroot.tpkg' +NEED_IPV6='fwd_ancil.tpkg fwd_tcp_tc6.tpkg stub_udp6.tpkg edns_cache.tpkg' +NEED_NOMINGW='tcp_sigpipe.tpkg 07-confroot.tpkg 08-host-lib.tpkg fwd_ancil.tpkg' + +# test if dig and ldns-testns are available. +test_tool_avail "dig" +test_tool_avail "ldns-testns" + +# test for ipv6, uses streamptcp peculiarity. +if ./streamtcp -f ::1 2>&1 | grep "not supported" >/dev/null 2>&1; then + HAVE_IPV6=no +else + HAVE_IPV6=yes +fi + +# test mingw. no signals and so on. +if uname | grep MINGW >/dev/null; then + HAVE_MINGW=yes +else + HAVE_MINGW=no +fi + +cd testdata; +sh ../testcode/mini_tpkg.sh clean +rm -f .perfstats.txt +for test in `ls *.tpkg`; do + SKIP=0 + skip_if_in_list $test "$NEED_SPLINT" "splint" + skip_if_in_list $test "$NEED_DOXYGEN" "doxygen" + skip_if_in_list $test "$NEED_CURL" "curl" + skip_if_in_list $test "$NEED_XXD" "xxd" + skip_if_in_list $test "$NEED_NC" "nc" + skip_if_in_list $test "$NEED_WHOAMI" "whoami" + + if echo $NEED_IPV6 | grep $test >/dev/null; then + if test "$HAVE_IPV6" = no; then + SKIP=1; + fi + fi + if echo $NEED_NOMINGW | grep $test >/dev/null; then + if test "$HAVE_MINGW" = yes; then + SKIP=1; + fi + fi + if test $SKIP -eq 0; then + echo $test + sh ../testcode/mini_tpkg.sh -a ../.. exe $test + else + echo "skip $test" + fi +done +sh ../testcode/mini_tpkg.sh report +cat .perfstats.txt diff --git a/testcode/fake_event.c b/testcode/fake_event.c new file mode 100644 index 00000000000..26dfaa8b068 --- /dev/null +++ b/testcode/fake_event.c @@ -0,0 +1,1413 @@ +/* + * testcode/fake_event.c - fake event handling that replays existing scenario. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * Event service that replays a scenario. + * This implements the same exported symbols as the files: + * util/netevent.c + * services/listen_dnsport.c + * services/outside_network.c + * But these do not actually access the network or events, instead + * the scenario is played. + */ + +#include "config.h" +#include "testcode/fake_event.h" +#include "util/netevent.h" +#include "util/net_help.h" +#include "util/data/msgparse.h" +#include "util/data/msgreply.h" +#include "util/data/msgencode.h" +#include "util/data/dname.h" +#include "util/config_file.h" +#include "services/listen_dnsport.h" +#include "services/outside_network.h" +#include "services/cache/infra.h" +#include "testcode/replay.h" +#include "testcode/ldns-testpkts.h" +#include "util/log.h" +#include "util/fptr_wlist.h" +#include +struct worker; +struct daemon_remote; + +/** Global variable: the scenario. Saved here for when event_init is done. */ +static struct replay_scenario* saved_scenario = NULL; + +/** add timers and the values do not overflow or become negative */ +static void +timeval_add(struct timeval* d, const struct timeval* add) +{ +#ifndef S_SPLINT_S + d->tv_sec += add->tv_sec; + d->tv_usec += add->tv_usec; + if(d->tv_usec > 1000000) { + d->tv_usec -= 1000000; + d->tv_sec++; + } +#endif +} + +void +fake_temp_file(const char* adj, const char* id, char* buf, size_t len) +{ +#ifdef USE_WINSOCK + snprintf(buf, len, "testbound_%u%s%s.tmp", + (unsigned)getpid(), adj, id); +#else + snprintf(buf, len, "/tmp/testbound_%u%s%s.tmp", + (unsigned)getpid(), adj, id); +#endif +} + +void +fake_event_init(struct replay_scenario* scen) +{ + saved_scenario = scen; +} + +void +fake_event_cleanup(void) +{ + replay_scenario_delete(saved_scenario); + saved_scenario = NULL; +} + +/** helper function that logs a ldns_pkt packet to logfile */ +static void +log_pkt(const char* desc, ldns_pkt* pkt) +{ + char* str = ldns_pkt2str(pkt); + if(!str) + log_info("%s: (failed)", desc); + else { + log_info("%s%s", desc, str); + free(str); + } +} + +/** + * Returns a string describing the event type. + */ +static const char* +repevt_string(enum replay_event_type t) +{ + switch(t) { + case repevt_nothing: return "NOTHING"; + case repevt_front_query: return "QUERY"; + case repevt_front_reply: return "CHECK_ANSWER"; + case repevt_timeout: return "TIMEOUT"; + case repevt_time_passes: return "TIME_PASSES"; + case repevt_back_reply: return "REPLY"; + case repevt_back_query: return "CHECK_OUT_QUERY"; + case repevt_autotrust_check: return "CHECK_AUTOTRUST"; + case repevt_error: return "ERROR"; + case repevt_assign: return "ASSIGN"; + case repevt_traffic: return "TRAFFIC"; + case repevt_infra_rtt: return "INFRA_RTT"; + default: return "UNKNOWN"; + } +} + +/** delete a fake pending */ +static void +delete_fake_pending(struct fake_pending* pend) +{ + if(!pend) + return; + free(pend->zone); + ldns_buffer_free(pend->buffer); + ldns_pkt_free(pend->pkt); + free(pend); +} + +/** delete a replay answer */ +static void +delete_replay_answer(struct replay_answer* a) +{ + if(!a) + return; + if(a->repinfo.c) { + ldns_buffer_free(a->repinfo.c->buffer); + free(a->repinfo.c); + } + ldns_pkt_free(a->pkt); + free(a); +} + +/** + * return: true if pending query matches the now event. + */ +static int +pending_matches_current(struct replay_runtime* runtime, + struct entry** entry, struct fake_pending **pend) +{ + struct fake_pending* p; + struct entry* e; + if(!runtime->now || runtime->now->evt_type != repevt_back_query + || !runtime->pending_list) + return 0; + /* see if any of the pending queries matches */ + for(p = runtime->pending_list; p; p = p->next) { + if(runtime->now->addrlen != 0 && + sockaddr_cmp(&p->addr, p->addrlen, &runtime->now->addr, + runtime->now->addrlen) != 0) + continue; + if((e=find_match(runtime->now->match, p->pkt, p->transport))) { + *entry = e; + *pend = p; + return 1; + } + } + return 0; +} + +/** + * Find the range that matches this pending message. + * @param runtime: runtime with current moment, and range list. + * @param entry: returns the pointer to entry that matches. + * @param pend: the pending that the entry must match. + * @return: true if a match is found. + */ +static int +pending_find_match(struct replay_runtime* runtime, struct entry** entry, + struct fake_pending* pend) +{ + int timenow = runtime->now->time_step; + struct replay_range* p = runtime->scenario->range_list; + while(p) { + if(p->start_step <= timenow && timenow <= p->end_step && + (p->addrlen == 0 || sockaddr_cmp(&p->addr, p->addrlen, + &pend->addr, pend->addrlen) == 0) && + (*entry = find_match(p->match, pend->pkt, pend->transport))) { + log_info("matched query time %d in range [%d, %d] " + "with entry line %d", timenow, + p->start_step, p->end_step, (*entry)->lineno); + if(p->addrlen != 0) + log_addr(0, "matched ip", &p->addr, p->addrlen); + log_pkt("matched pkt: ", (*entry)->reply_list->reply); + return 1; + } + p = p->next_range; + } + return 0; +} + +/** + * See if outgoing pending query matches an entry. + * @param runtime: runtime. + * @param entry: if true, the entry that matches is returned. + * @param pend: if true, the outgoing message that matches is returned. + * @return: true if pending query matches the now event. + */ +static int +pending_matches_range(struct replay_runtime* runtime, + struct entry** entry, struct fake_pending** pend) +{ + struct fake_pending* p = runtime->pending_list; + /* slow, O(N*N), but it works as advertised with weird matching */ + while(p) { + log_info("check of pending"); + if(pending_find_match(runtime, entry, p)) { + *pend = p; + return 1; + } + p = p->next; + } + return 0; +} + +/** + * Remove the item from the pending list. + */ +static void +pending_list_delete(struct replay_runtime* runtime, struct fake_pending* pend) +{ + struct fake_pending** prev = &runtime->pending_list; + struct fake_pending* p = runtime->pending_list; + + while(p) { + if(p == pend) { + *prev = p->next; + delete_fake_pending(pend); + return; + } + + prev = &p->next; + p = p->next; + } +} + +/** + * Fill buffer with reply from the entry. + */ +static void +fill_buffer_with_reply(ldns_buffer* buffer, struct entry* entry, ldns_pkt* q) +{ + ldns_status status; + ldns_pkt* answer_pkt = NULL; + log_assert(entry && entry->reply_list); + ldns_buffer_clear(buffer); + if(entry->reply_list->reply_from_hex) { + status = ldns_buffer2pkt_wire(&answer_pkt, + entry->reply_list->reply_from_hex); + if(status != LDNS_STATUS_OK) { + log_err("testbound: hex packet unparsable, used asis."); + ldns_buffer_write(buffer, + ldns_buffer_begin(entry->reply_list->reply_from_hex), + ldns_buffer_limit(entry->reply_list->reply_from_hex)); + } + } else { + answer_pkt = ldns_pkt_clone(entry->reply_list->reply); + } + if(answer_pkt) { + if(q) adjust_packet(entry, answer_pkt, q); + status = ldns_pkt2buffer_wire(buffer, answer_pkt); + if(status != LDNS_STATUS_OK) + fatal_exit("ldns: cannot pkt2buffer_wire parsed pkt"); + } + ldns_pkt_free(answer_pkt); + ldns_buffer_flip(buffer); +} + +/** + * Perform range entry on pending message. + * @param runtime: runtime buffer size preference. + * @param entry: entry that codes for the reply to do. + * @param pend: pending query that is answered, callback called. + */ +static void +answer_callback_from_entry(struct replay_runtime* runtime, + struct entry* entry, struct fake_pending* pend) +{ + struct comm_point c; + struct comm_reply repinfo; + void* cb_arg = pend->cb_arg; + comm_point_callback_t* cb = pend->callback; + + memset(&c, 0, sizeof(c)); + c.fd = -1; + c.buffer = ldns_buffer_new(runtime->bufsize); + c.type = comm_udp; + if(pend->transport == transport_tcp) + c.type = comm_tcp; + fill_buffer_with_reply(c.buffer, entry, pend->pkt); + repinfo.c = &c; + repinfo.addrlen = pend->addrlen; + memcpy(&repinfo.addr, &pend->addr, pend->addrlen); + if(!pend->serviced) + pending_list_delete(runtime, pend); + if((*cb)(&c, cb_arg, NETEVENT_NOERROR, &repinfo)) { + fatal_exit("testbound: unexpected: callback returned 1"); + } + ldns_buffer_free(c.buffer); +} + +/** Check the now moment answer check event */ +static void +answer_check_it(struct replay_runtime* runtime) +{ + struct replay_answer* ans = runtime->answer_list, + *prev = NULL; + log_assert(runtime && runtime->now && + runtime->now->evt_type == repevt_front_reply); + while(ans) { + enum transport_type tr = transport_tcp; + if(ans->repinfo.c->type == comm_udp) + tr = transport_udp; + if((runtime->now->addrlen == 0 || sockaddr_cmp( + &runtime->now->addr, runtime->now->addrlen, + &ans->repinfo.addr, ans->repinfo.addrlen) == 0) && + find_match(runtime->now->match, ans->pkt, tr)) { + log_info("testbound matched event entry from line %d", + runtime->now->match->lineno); + log_info("testbound: do STEP %d %s", + runtime->now->time_step, + repevt_string(runtime->now->evt_type)); + if(prev) + prev->next = ans->next; + else runtime->answer_list = ans->next; + if(!ans->next) + runtime->answer_last = prev; + delete_replay_answer(ans); + return; + } else { + prev = ans; + ans = ans->next; + } + } + log_info("testbound: do STEP %d %s", runtime->now->time_step, + repevt_string(runtime->now->evt_type)); + fatal_exit("testbound: not matched"); +} + +/** + * Create commpoint (as return address) for a fake incoming query. + */ +static void +fake_front_query(struct replay_runtime* runtime, struct replay_moment *todo) +{ + struct comm_reply repinfo; + memset(&repinfo, 0, sizeof(repinfo)); + repinfo.c = (struct comm_point*)calloc(1, sizeof(struct comm_point)); + repinfo.addrlen = (socklen_t)sizeof(struct sockaddr_in); + if(todo->addrlen != 0) { + repinfo.addrlen = todo->addrlen; + memcpy(&repinfo.addr, &todo->addr, todo->addrlen); + } + repinfo.c->fd = -1; + repinfo.c->ev = (struct internal_event*)runtime; + repinfo.c->buffer = ldns_buffer_new(runtime->bufsize); + if(todo->match->match_transport == transport_tcp) + repinfo.c->type = comm_tcp; + else repinfo.c->type = comm_udp; + fill_buffer_with_reply(repinfo.c->buffer, todo->match, NULL); + log_info("testbound: incoming QUERY"); + log_pkt("query pkt", todo->match->reply_list->reply); + /* call the callback for incoming queries */ + if((*runtime->callback_query)(repinfo.c, runtime->cb_arg, + NETEVENT_NOERROR, &repinfo)) { + /* send immediate reply */ + comm_point_send_reply(&repinfo); + } + /* clear it again, in case copy not done properly */ + memset(&repinfo, 0, sizeof(repinfo)); +} + +/** + * Perform callback for fake pending message. + */ +static void +fake_pending_callback(struct replay_runtime* runtime, + struct replay_moment* todo, int error) +{ + struct fake_pending* p = runtime->pending_list; + struct comm_reply repinfo; + struct comm_point c; + void* cb_arg; + comm_point_callback_t* cb; + + memset(&c, 0, sizeof(c)); + if(!p) fatal_exit("No pending queries."); + cb_arg = p->cb_arg; + cb = p->callback; + log_assert(todo->qname == NULL); /* or find that one */ + c.buffer = ldns_buffer_new(runtime->bufsize); + c.type = comm_udp; + if(p->transport == transport_tcp) + c.type = comm_tcp; + if(todo->evt_type == repevt_back_reply && todo->match) { + fill_buffer_with_reply(c.buffer, todo->match, p->pkt); + } + repinfo.c = &c; + repinfo.addrlen = p->addrlen; + memcpy(&repinfo.addr, &p->addr, p->addrlen); + if(!p->serviced) + pending_list_delete(runtime, p); + if((*cb)(&c, cb_arg, error, &repinfo)) { + fatal_exit("unexpected: pending callback returned 1"); + } + /* delete the pending item. */ + ldns_buffer_free(c.buffer); +} + +/** pass time */ +static void +moment_assign(struct replay_runtime* runtime, struct replay_moment* mom) +{ + char* value = macro_process(runtime->vars, runtime, mom->string); + if(!value) + fatal_exit("could not process macro step %d", mom->time_step); + log_info("assign %s = %s", mom->variable, value); + if(!macro_assign(runtime->vars, mom->variable, value)) + fatal_exit("out of memory storing macro"); + free(value); + if(verbosity >= VERB_ALGO) + macro_print_debug(runtime->vars); +} + +/** pass time */ +static void +time_passes(struct replay_runtime* runtime, struct replay_moment* mom) +{ + struct fake_timer *t; + struct timeval tv = mom->elapse; + if(mom->string) { + char* xp = macro_process(runtime->vars, runtime, mom->string); + double sec; + if(!xp) fatal_exit("could not macro expand %s", mom->string); + verbose(VERB_ALGO, "EVAL %s", mom->string); + sec = atof(xp); + free(xp); +#ifndef S_SPLINT_S + tv.tv_sec = sec; + tv.tv_usec = (int)((sec - (double)tv.tv_sec) *1000000. + 0.5); +#endif + } + timeval_add(&runtime->now_tv, &tv); + runtime->now_secs = (uint32_t)runtime->now_tv.tv_sec; +#ifndef S_SPLINT_S + log_info("elapsed %d.%6.6d now %d.%6.6d", + (int)tv.tv_sec, (int)tv.tv_usec, + (int)runtime->now_tv.tv_sec, (int)runtime->now_tv.tv_usec); +#endif + /* see if any timers have fired; and run them */ + while( (t=replay_get_oldest_timer(runtime)) ) { + t->enabled = 0; + log_info("fake_timer callback"); + fptr_ok(fptr_whitelist_comm_timer(t->cb)); + (*t->cb)(t->cb_arg); + } +} + +/** check autotrust file contents */ +static void +autotrust_check(struct replay_runtime* runtime, struct replay_moment* mom) +{ + char name[1024], line[1024]; + FILE *in; + int lineno = 0, oke=1; + char* expanded; + struct config_strlist* p; + line[sizeof(line)-1] = 0; + log_assert(mom->autotrust_id); + fake_temp_file("_auto_", mom->autotrust_id, name, sizeof(name)); + in = fopen(name, "r"); + if(!in) fatal_exit("could not open %s: %s", name, strerror(errno)); + for(p=mom->file_content; p; p=p->next) { + lineno++; + if(!fgets(line, (int)sizeof(line)-1, in)) { + log_err("autotrust check failed, could not read line"); + log_err("file %s, line %d", name, lineno); + log_err("should be: %s", p->str); + fatal_exit("autotrust_check failed"); + } + if(line[0]) line[strlen(line)-1] = 0; /* remove newline */ + expanded = macro_process(runtime->vars, runtime, p->str); + if(!expanded) + fatal_exit("could not expand macro line %d", lineno); + if(verbosity >= 7 && strcmp(p->str, expanded) != 0) + log_info("expanded '%s' to '%s'", p->str, expanded); + if(strcmp(expanded, line) != 0) { + log_err("mismatch in file %s, line %d", name, lineno); + log_err("file has : %s", line); + log_err("should be: %s", expanded); + free(expanded); + oke = 0; + continue; + } + free(expanded); + fprintf(stderr, "%s:%2d ok : %s\n", name, lineno, line); + } + if(fgets(line, (int)sizeof(line)-1, in)) { + log_err("autotrust check failed, extra lines in %s after %d", + name, lineno); + do { + fprintf(stderr, "file has: %s", line); + } while(fgets(line, (int)sizeof(line)-1, in)); + oke = 0; + } + fclose(in); + if(!oke) + fatal_exit("autotrust_check STEP %d failed", mom->time_step); + log_info("autotrust %s is OK", mom->autotrust_id); +} + +/** Store RTT in infra cache */ +static void +do_infra_rtt(struct replay_runtime* runtime) +{ + struct replay_moment* now = runtime->now; + int rto; + ldns_rdf* dp = ldns_dname_new_frm_str(now->variable); + if(!dp) fatal_exit("cannot parse %s", now->variable); + rto = infra_rtt_update(runtime->infra, &now->addr, + now->addrlen, ldns_rdf_data(dp), ldns_rdf_size(dp), + LDNS_RR_TYPE_A, atoi(now->string), -1, runtime->now_secs); + log_addr(0, "INFRA_RTT for", &now->addr, now->addrlen); + log_info("INFRA_RTT(%s roundtrip %d): rto of %d", now->variable, + atoi(now->string), rto); + if(rto == 0) fatal_exit("infra_rtt_update failed"); + ldns_rdf_deep_free(dp); +} + +/** perform exponential backoff on the timout */ +static void +expon_timeout_backoff(struct replay_runtime* runtime) +{ + struct fake_pending* p = runtime->pending_list; + int rtt, vs; + uint8_t edns_lame_known; + int last_rtt, rto; + if(!p) return; /* no pending packet to backoff */ + if(!infra_host(runtime->infra, &p->addr, p->addrlen, p->zone, + p->zonelen, runtime->now_secs, &vs, &edns_lame_known, &rtt)) + return; + last_rtt = rtt; + rto = infra_rtt_update(runtime->infra, &p->addr, p->addrlen, p->zone, + p->zonelen, p->qtype, -1, last_rtt, runtime->now_secs); + log_info("infra_rtt_update returned rto %d", rto); +} + +/** + * Advance to the next moment. + */ +static void +advance_moment(struct replay_runtime* runtime) +{ + if(!runtime->now) + runtime->now = runtime->scenario->mom_first; + else runtime->now = runtime->now->mom_next; +} + +/** + * Perform actions or checks determined by the moment. + * Also advances the time by one step. + * @param runtime: scenario runtime information. + */ +static void +do_moment_and_advance(struct replay_runtime* runtime) +{ + struct replay_moment* mom; + if(!runtime->now) { + advance_moment(runtime); + return; + } + log_info("testbound: do STEP %d %s", runtime->now->time_step, + repevt_string(runtime->now->evt_type)); + switch(runtime->now->evt_type) { + case repevt_nothing: + advance_moment(runtime); + break; + case repevt_front_query: + /* advance moment before doing the step, so that the next + moment which may check some result of the mom step + can catch those results. */ + mom = runtime->now; + advance_moment(runtime); + fake_front_query(runtime, mom); + break; + case repevt_front_reply: + if(runtime->answer_list) + log_err("testbound: There are unmatched answers."); + fatal_exit("testbound: query answer not matched"); + break; + case repevt_timeout: + mom = runtime->now; + advance_moment(runtime); + expon_timeout_backoff(runtime); + fake_pending_callback(runtime, mom, NETEVENT_TIMEOUT); + break; + case repevt_back_reply: + mom = runtime->now; + advance_moment(runtime); + fake_pending_callback(runtime, mom, NETEVENT_NOERROR); + break; + case repevt_back_query: + /* Back queries are matched when they are sent out. */ + log_err("No query matching the current moment was sent."); + fatal_exit("testbound: back query not matched"); + break; + case repevt_error: + mom = runtime->now; + advance_moment(runtime); + fake_pending_callback(runtime, mom, NETEVENT_CLOSED); + break; + case repevt_time_passes: + time_passes(runtime, runtime->now); + advance_moment(runtime); + break; + case repevt_autotrust_check: + autotrust_check(runtime, runtime->now); + advance_moment(runtime); + break; + case repevt_assign: + moment_assign(runtime, runtime->now); + advance_moment(runtime); + break; + case repevt_traffic: + advance_moment(runtime); + break; + case repevt_infra_rtt: + do_infra_rtt(runtime); + advance_moment(runtime); + break; + default: + fatal_exit("testbound: unknown event type %d", + runtime->now->evt_type); + } +} + +/** run the scenario in event callbacks */ +static void +run_scenario(struct replay_runtime* runtime) +{ + struct entry* entry = NULL; + struct fake_pending* pending = NULL; + int max_rounds = 5000; + int rounds = 0; + runtime->now = runtime->scenario->mom_first; + log_info("testbound: entering fake runloop"); + do { + /* if moment matches pending query do it. */ + /* else if moment matches given answer, do it */ + /* else if precoded_range matches pending, do it */ + /* else do the current moment */ + if(pending_matches_current(runtime, &entry, &pending)) { + log_info("testbound: do STEP %d CHECK_OUT_QUERY", + runtime->now->time_step); + advance_moment(runtime); + if(entry->copy_id) + answer_callback_from_entry(runtime, entry, + pending); + } else if(runtime->answer_list && runtime->now && + runtime->now->evt_type == repevt_front_reply) { + answer_check_it(runtime); + advance_moment(runtime); + } else if(pending_matches_range(runtime, &entry, &pending)) { + answer_callback_from_entry(runtime, entry, pending); + } else { + do_moment_and_advance(runtime); + } + log_info("testbound: end of event stage"); + rounds++; + if(rounds > max_rounds) + fatal_exit("testbound: too many rounds, it loops."); + } while(runtime->now); + + if(runtime->pending_list) { + struct fake_pending* p; + log_err("testbound: there are still messages pending."); + for(p = runtime->pending_list; p; p=p->next) { + log_pkt("pending msg", p->pkt); + log_addr(0, "pending to", &p->addr, p->addrlen); + } + fatal_exit("testbound: there are still messages pending."); + } + if(runtime->answer_list) { + fatal_exit("testbound: there are unmatched answers."); + } + log_info("testbound: exiting fake runloop."); + runtime->exit_cleanly = 1; +} + +/*********** Dummy routines ***********/ + +struct listen_dnsport* +listen_create(struct comm_base* base, struct listen_port* ATTR_UNUSED(ports), + size_t bufsize, int ATTR_UNUSED(tcp_accept_count), + void* ATTR_UNUSED(sslctx), comm_point_callback_t* cb, void* cb_arg) +{ + struct replay_runtime* runtime = (struct replay_runtime*)base; + struct listen_dnsport* l= calloc(1, sizeof(struct listen_dnsport)); + if(!l) + return NULL; + l->base = base; + l->udp_buff = ldns_buffer_new(bufsize); + if(!l->udp_buff) { + free(l); + return NULL; + } + runtime->callback_query = cb; + runtime->cb_arg = cb_arg; + runtime->bufsize = bufsize; + return l; +} + +void +listen_delete(struct listen_dnsport* listen) +{ + if(!listen) + return; + ldns_buffer_free(listen->udp_buff); + free(listen); +} + +struct comm_base* +comm_base_create(int ATTR_UNUSED(sigs)) +{ + /* we return the runtime structure instead. */ + struct replay_runtime* runtime = (struct replay_runtime*) + calloc(1, sizeof(struct replay_runtime)); + runtime->scenario = saved_scenario; + runtime->vars = macro_store_create(); + if(!runtime->vars) fatal_exit("out of memory"); + return (struct comm_base*)runtime; +} + +void +comm_base_delete(struct comm_base* b) +{ + struct replay_runtime* runtime = (struct replay_runtime*)b; + struct fake_pending* p, *np; + struct replay_answer* a, *na; + struct fake_timer* t, *nt; + if(!runtime) + return; + runtime->scenario= NULL; + p = runtime->pending_list; + while(p) { + np = p->next; + delete_fake_pending(p); + p = np; + } + a = runtime->answer_list; + while(a) { + na = a->next; + delete_replay_answer(a); + a = na; + } + t = runtime->timer_list; + while(t) { + nt = t->next; + free(t); + t = nt; + } + macro_store_delete(runtime->vars); + free(runtime); +} + +void +comm_base_timept(struct comm_base* b, uint32_t** tt, struct timeval** tv) +{ + struct replay_runtime* runtime = (struct replay_runtime*)b; + *tt = &runtime->now_secs; + *tv = &runtime->now_tv; +} + +void +comm_base_dispatch(struct comm_base* b) +{ + struct replay_runtime* runtime = (struct replay_runtime*)b; + run_scenario(runtime); + if(runtime->sig_cb) + (*runtime->sig_cb)(SIGTERM, runtime->sig_cb_arg); + else exit(0); /* OK exit when LIBEVENT_SIGNAL_PROBLEM exists */ +} + +void +comm_base_exit(struct comm_base* b) +{ + struct replay_runtime* runtime = (struct replay_runtime*)b; + if(!runtime->exit_cleanly) { + /* some sort of failure */ + fatal_exit("testbound: comm_base_exit was called."); + } +} + +struct comm_signal* +comm_signal_create(struct comm_base* base, + void (*callback)(int, void*), void* cb_arg) +{ + struct replay_runtime* runtime = (struct replay_runtime*)base; + runtime->sig_cb = callback; + runtime->sig_cb_arg = cb_arg; + return calloc(1, sizeof(struct comm_signal)); +} + +int +comm_signal_bind(struct comm_signal* ATTR_UNUSED(comsig), int + ATTR_UNUSED(sig)) +{ + return 1; +} + +void +comm_signal_delete(struct comm_signal* comsig) +{ + free(comsig); +} + +void +comm_point_send_reply(struct comm_reply* repinfo) +{ + struct replay_answer* ans = (struct replay_answer*)calloc(1, + sizeof(struct replay_answer)); + ldns_status status; + struct replay_runtime* runtime = (struct replay_runtime*)repinfo->c->ev; + log_info("testbound: comm_point_send_reply fake"); + /* dump it into the todo list */ + log_assert(ans); + memcpy(&ans->repinfo, repinfo, sizeof(struct comm_reply)); + ans->next = NULL; + if(runtime->answer_last) + runtime->answer_last->next = ans; + else runtime->answer_list = ans; + runtime->answer_last = ans; + + /* try to parse packet */ + status = ldns_buffer2pkt_wire(&ans->pkt, ans->repinfo.c->buffer); + if(status != LDNS_STATUS_OK) { + log_err("ldns error parsing packet: %s", + ldns_get_errorstr_by_id(status)); + fatal_exit("Sending unparseable DNS replies to clients!"); + } + log_pkt("reply pkt: ", ans->pkt); +} + +void +comm_point_drop_reply(struct comm_reply* repinfo) +{ + log_info("comm_point_drop_reply fake"); + if(repinfo->c) { + ldns_buffer_free(repinfo->c->buffer); + free(repinfo->c); + } +} + +struct outside_network* +outside_network_create(struct comm_base* base, size_t bufsize, + size_t ATTR_UNUSED(num_ports), char** ATTR_UNUSED(ifs), + int ATTR_UNUSED(num_ifs), int ATTR_UNUSED(do_ip4), + int ATTR_UNUSED(do_ip6), size_t ATTR_UNUSED(num_tcp), + struct infra_cache* infra, + struct ub_randstate* ATTR_UNUSED(rnd), + int ATTR_UNUSED(use_caps_for_id), int* ATTR_UNUSED(availports), + int ATTR_UNUSED(numavailports), size_t ATTR_UNUSED(unwanted_threshold), + void (*unwanted_action)(void*), void* ATTR_UNUSED(unwanted_param), + int ATTR_UNUSED(do_udp), void* ATTR_UNUSED(sslctx)) +{ + struct replay_runtime* runtime = (struct replay_runtime*)base; + struct outside_network* outnet = calloc(1, + sizeof(struct outside_network)); + (void)unwanted_action; + if(!outnet) + return NULL; + runtime->infra = infra; + outnet->base = base; + outnet->udp_buff = ldns_buffer_new(bufsize); + if(!outnet->udp_buff) + return NULL; + return outnet; +} + +void +outside_network_delete(struct outside_network* outnet) +{ + if(!outnet) + return; + ldns_buffer_free(outnet->udp_buff); + free(outnet); +} + +void +outside_network_quit_prepare(struct outside_network* ATTR_UNUSED(outnet)) +{ +} + +struct pending* +pending_udp_query(struct outside_network* outnet, ldns_buffer* packet, + struct sockaddr_storage* addr, socklen_t addrlen, int timeout, + comm_point_callback_t* callback, void* callback_arg) +{ + struct replay_runtime* runtime = (struct replay_runtime*)outnet->base; + struct fake_pending* pend = (struct fake_pending*)calloc(1, + sizeof(struct fake_pending)); + ldns_status status; + log_assert(pend); + pend->buffer = ldns_buffer_new(ldns_buffer_capacity(packet)); + log_assert(pend->buffer); + ldns_buffer_write(pend->buffer, ldns_buffer_begin(packet), + ldns_buffer_limit(packet)); + ldns_buffer_flip(pend->buffer); + memcpy(&pend->addr, addr, addrlen); + pend->addrlen = addrlen; + pend->callback = callback; + pend->cb_arg = callback_arg; + pend->timeout = timeout/1000; + pend->transport = transport_udp; + pend->pkt = NULL; + pend->zone = NULL; + pend->serviced = 0; + pend->runtime = runtime; + status = ldns_buffer2pkt_wire(&pend->pkt, packet); + if(status != LDNS_STATUS_OK) { + log_err("ldns error parsing udp output packet: %s", + ldns_get_errorstr_by_id(status)); + fatal_exit("Sending unparseable DNS packets to servers!"); + } + log_pkt("pending udp pkt: ", pend->pkt); + + /* see if it matches the current moment */ + if(runtime->now && runtime->now->evt_type == repevt_back_query && + (runtime->now->addrlen == 0 || sockaddr_cmp( + &runtime->now->addr, runtime->now->addrlen, + &pend->addr, pend->addrlen) == 0) && + find_match(runtime->now->match, pend->pkt, pend->transport)) { + log_info("testbound: matched pending to event. " + "advance time between events."); + log_info("testbound: do STEP %d %s", runtime->now->time_step, + repevt_string(runtime->now->evt_type)); + advance_moment(runtime); + /* still create the pending, because we need it to callback */ + } + log_info("testbound: created fake pending"); + /* add to list */ + pend->next = runtime->pending_list; + runtime->pending_list = pend; + return (struct pending*)pend; +} + +struct waiting_tcp* +pending_tcp_query(struct outside_network* outnet, ldns_buffer* packet, + struct sockaddr_storage* addr, socklen_t addrlen, int timeout, + comm_point_callback_t* callback, void* callback_arg, + int ATTR_UNUSED(ssl_upstream)) +{ + struct replay_runtime* runtime = (struct replay_runtime*)outnet->base; + struct fake_pending* pend = (struct fake_pending*)calloc(1, + sizeof(struct fake_pending)); + ldns_status status; + log_assert(pend); + pend->buffer = ldns_buffer_new(ldns_buffer_capacity(packet)); + log_assert(pend->buffer); + ldns_buffer_write(pend->buffer, ldns_buffer_begin(packet), + ldns_buffer_limit(packet)); + ldns_buffer_flip(pend->buffer); + memcpy(&pend->addr, addr, addrlen); + pend->addrlen = addrlen; + pend->callback = callback; + pend->cb_arg = callback_arg; + pend->timeout = timeout; + pend->transport = transport_tcp; + pend->pkt = NULL; + pend->zone = NULL; + pend->runtime = runtime; + pend->serviced = 0; + status = ldns_buffer2pkt_wire(&pend->pkt, packet); + if(status != LDNS_STATUS_OK) { + log_err("ldns error parsing tcp output packet: %s", + ldns_get_errorstr_by_id(status)); + fatal_exit("Sending unparseable DNS packets to servers!"); + } + log_pkt("pending tcp pkt: ", pend->pkt); + + /* see if it matches the current moment */ + if(runtime->now && runtime->now->evt_type == repevt_back_query && + (runtime->now->addrlen == 0 || sockaddr_cmp( + &runtime->now->addr, runtime->now->addrlen, + &pend->addr, pend->addrlen) == 0) && + find_match(runtime->now->match, pend->pkt, pend->transport)) { + log_info("testbound: matched pending to event. " + "advance time between events."); + log_info("testbound: do STEP %d %s", runtime->now->time_step, + repevt_string(runtime->now->evt_type)); + advance_moment(runtime); + /* still create the pending, because we need it to callback */ + } + log_info("testbound: created fake pending"); + /* add to list */ + pend->next = runtime->pending_list; + runtime->pending_list = pend; + return (struct waiting_tcp*)pend; +} + +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 ATTR_UNUSED(want_dnssec), + int ATTR_UNUSED(tcp_upstream), int ATTR_UNUSED(ssl_upstream), + struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, + size_t zonelen, comm_point_callback_t* callback, void* callback_arg, + ldns_buffer* ATTR_UNUSED(buff), int (*arg_compare)(void*,void*)) +{ + struct replay_runtime* runtime = (struct replay_runtime*)outnet->base; + struct fake_pending* pend = (struct fake_pending*)calloc(1, + sizeof(struct fake_pending)); + char z[256]; + ldns_status status; + (void)arg_compare; + log_assert(pend); + log_nametypeclass(VERB_OPS, "pending serviced query", + qname, qtype, qclass); + dname_str(zone, z); + verbose(VERB_OPS, "pending serviced query zone %s flags%s%s%s%s", + z, (flags&BIT_RD)?" RD":"", (flags&BIT_CD)?" CD":"", + (flags&~(BIT_RD|BIT_CD))?" MORE":"", (dnssec)?" DO":""); + + /* create packet with EDNS */ + pend->buffer = ldns_buffer_new(512); + log_assert(pend->buffer); + ldns_buffer_write_u16(pend->buffer, 0); /* id */ + ldns_buffer_write_u16(pend->buffer, flags); + ldns_buffer_write_u16(pend->buffer, 1); /* qdcount */ + ldns_buffer_write_u16(pend->buffer, 0); /* ancount */ + ldns_buffer_write_u16(pend->buffer, 0); /* nscount */ + ldns_buffer_write_u16(pend->buffer, 0); /* arcount */ + ldns_buffer_write(pend->buffer, qname, qnamelen); + ldns_buffer_write_u16(pend->buffer, qtype); + ldns_buffer_write_u16(pend->buffer, qclass); + ldns_buffer_flip(pend->buffer); + if(1) { + /* add edns */ + struct edns_data edns; + edns.edns_present = 1; + edns.ext_rcode = 0; + edns.edns_version = EDNS_ADVERTISED_VERSION; + edns.udp_size = EDNS_ADVERTISED_SIZE; + edns.bits = 0; + if(dnssec) + edns.bits = EDNS_DO; + attach_edns_record(pend->buffer, &edns); + } + memcpy(&pend->addr, addr, addrlen); + pend->addrlen = addrlen; + pend->zone = memdup(zone, zonelen); + pend->zonelen = zonelen; + pend->qtype = (int)qtype; + log_assert(pend->zone); + pend->callback = callback; + pend->cb_arg = callback_arg; + pend->timeout = UDP_AUTH_QUERY_TIMEOUT; + pend->transport = transport_udp; /* pretend UDP */ + pend->pkt = NULL; + pend->runtime = runtime; + pend->serviced = 1; + status = ldns_buffer2pkt_wire(&pend->pkt, pend->buffer); + if(status != LDNS_STATUS_OK) { + log_err("ldns error parsing serviced output packet: %s", + ldns_get_errorstr_by_id(status)); + fatal_exit("internal error"); + } + /*log_pkt("pending serviced query: ", pend->pkt);*/ + + /* see if it matches the current moment */ + if(runtime->now && runtime->now->evt_type == repevt_back_query && + (runtime->now->addrlen == 0 || sockaddr_cmp( + &runtime->now->addr, runtime->now->addrlen, + &pend->addr, pend->addrlen) == 0) && + find_match(runtime->now->match, pend->pkt, pend->transport)) { + log_info("testbound: matched pending to event. " + "advance time between events."); + log_info("testbound: do STEP %d %s", runtime->now->time_step, + repevt_string(runtime->now->evt_type)); + advance_moment(runtime); + /* still create the pending, because we need it to callback */ + } + log_info("testbound: created fake pending"); + /* add to list */ + pend->next = runtime->pending_list; + runtime->pending_list = pend; + return (struct serviced_query*)pend; +} + +void outnet_serviced_query_stop(struct serviced_query* sq, void* cb_arg) +{ + struct fake_pending* pend = (struct fake_pending*)sq; + struct replay_runtime* runtime = pend->runtime; + /* delete from the list */ + struct fake_pending* p = runtime->pending_list, *prev=NULL; + while(p) { + if(p == pend) { + log_assert(p->cb_arg == cb_arg); + log_info("serviced pending delete"); + if(prev) + prev->next = p->next; + else runtime->pending_list = p->next; + ldns_buffer_free(p->buffer); + ldns_pkt_free(p->pkt); + free(p->zone); + free(p); + return; + } + prev = p; + p = p->next; + } + log_info("double delete of pending serviced query"); +} + +struct listen_port* listening_ports_open(struct config_file* ATTR_UNUSED(cfg)) +{ + return calloc(1, 1); +} + +void listening_ports_free(struct listen_port* list) +{ + free(list); +} + +struct comm_point* comm_point_create_local(struct comm_base* ATTR_UNUSED(base), + int ATTR_UNUSED(fd), size_t ATTR_UNUSED(bufsize), + comm_point_callback_t* ATTR_UNUSED(callback), + void* ATTR_UNUSED(callback_arg)) +{ + return calloc(1, 1); +} + +struct comm_point* comm_point_create_raw(struct comm_base* ATTR_UNUSED(base), + int ATTR_UNUSED(fd), int ATTR_UNUSED(writing), + comm_point_callback_t* ATTR_UNUSED(callback), + void* ATTR_UNUSED(callback_arg)) +{ + /* no pipe comm possible */ + return calloc(1, 1); +} + +void comm_point_start_listening(struct comm_point* ATTR_UNUSED(c), + int ATTR_UNUSED(newfd), int ATTR_UNUSED(sec)) +{ + /* no bg write pipe comm possible */ +} + +void comm_point_stop_listening(struct comm_point* ATTR_UNUSED(c)) +{ + /* no bg write pipe comm possible */ +} + +/* only cmd com _local gets deleted */ +void comm_point_delete(struct comm_point* c) +{ + free(c); +} + +size_t listen_get_mem(struct listen_dnsport* ATTR_UNUSED(listen)) +{ + return 0; +} + +size_t outnet_get_mem(struct outside_network* ATTR_UNUSED(outnet)) +{ + return 0; +} + +size_t comm_point_get_mem(struct comm_point* ATTR_UNUSED(c)) +{ + return 0; +} + +size_t serviced_get_mem(struct serviced_query* ATTR_UNUSED(c)) +{ + return 0; +} + +/* fake for fptr wlist */ +int outnet_udp_cb(struct comm_point* ATTR_UNUSED(c), + void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), + struct comm_reply *ATTR_UNUSED(reply_info)) +{ + log_assert(0); + return 0; +} + +int outnet_tcp_cb(struct comm_point* ATTR_UNUSED(c), + void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), + struct comm_reply *ATTR_UNUSED(reply_info)) +{ + log_assert(0); + return 0; +} + +void pending_udp_timer_cb(void *ATTR_UNUSED(arg)) +{ + log_assert(0); +} + +void outnet_tcptimer(void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + +void comm_point_udp_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(event), + void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + +void comm_point_udp_ancil_callback(int ATTR_UNUSED(fd), + short ATTR_UNUSED(event), void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + +void comm_point_tcp_accept_callback(int ATTR_UNUSED(fd), + short ATTR_UNUSED(event), void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + +void comm_point_tcp_handle_callback(int ATTR_UNUSED(fd), + short ATTR_UNUSED(event), void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + +void comm_timer_callback(int ATTR_UNUSED(fd), + short ATTR_UNUSED(event), void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + +void comm_signal_callback(int ATTR_UNUSED(fd), + short ATTR_UNUSED(event), void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + +void comm_point_local_handle_callback(int ATTR_UNUSED(fd), + short ATTR_UNUSED(event), void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + +void comm_point_raw_handle_callback(int ATTR_UNUSED(fd), + short ATTR_UNUSED(event), void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + +void comm_base_handle_slow_accept(int ATTR_UNUSED(fd), + short ATTR_UNUSED(event), void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + +int serviced_udp_callback(struct comm_point* ATTR_UNUSED(c), + void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), + struct comm_reply* ATTR_UNUSED(reply_info)) +{ + log_assert(0); + return 0; +} + +int serviced_tcp_callback(struct comm_point* ATTR_UNUSED(c), + void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), + struct comm_reply* ATTR_UNUSED(reply_info)) +{ + log_assert(0); + return 0; +} + +int pending_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b)) +{ + log_assert(0); + return 0; +} + +int serviced_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b)) +{ + log_assert(0); + return 0; +} + +/* timers in testbound for autotrust. statistics tested in tpkg. */ +struct comm_timer* comm_timer_create(struct comm_base* base, + void (*cb)(void*), void* cb_arg) +{ + struct replay_runtime* runtime = (struct replay_runtime*)base; + struct fake_timer* t = (struct fake_timer*)calloc(1, sizeof(*t)); + t->cb = cb; + t->cb_arg = cb_arg; + fptr_ok(fptr_whitelist_comm_timer(t->cb)); /* check in advance */ + t->runtime = runtime; + t->next = runtime->timer_list; + runtime->timer_list = t; + return (struct comm_timer*)t; +} + +void comm_timer_disable(struct comm_timer* timer) +{ + struct fake_timer* t = (struct fake_timer*)timer; + log_info("fake timer disabled"); + t->enabled = 0; +} + +void comm_timer_set(struct comm_timer* timer, struct timeval* tv) +{ + struct fake_timer* t = (struct fake_timer*)timer; + t->enabled = 1; + t->tv = *tv; + log_info("fake timer set %d.%6.6d", + (int)t->tv.tv_sec, (int)t->tv.tv_usec); + timeval_add(&t->tv, &t->runtime->now_tv); +} + +void comm_timer_delete(struct comm_timer* timer) +{ + struct fake_timer* t = (struct fake_timer*)timer; + struct fake_timer** pp, *p; + if(!t) return; + + /* remove from linked list */ + pp = &t->runtime->timer_list; + p = t->runtime->timer_list; + while(p) { + if(p == t) { + /* snip from list */ + *pp = p->next; + break; + } + pp = &p->next; + p = p->next; + } + + free(timer); +} + +void comm_base_set_slow_accept_handlers(struct comm_base* ATTR_UNUSED(b), + void (*stop_acc)(void*), void (*start_acc)(void*), + void* ATTR_UNUSED(arg)) +{ + /* ignore this */ + (void)stop_acc; + (void)start_acc; +} + +struct event_base* comm_base_internal(struct comm_base* ATTR_UNUSED(b)) +{ + /* no pipe comm possible in testbound */ + return NULL; +} + +void daemon_remote_exec(struct worker* ATTR_UNUSED(worker)) +{ +} + +void listen_start_accept(struct listen_dnsport* ATTR_UNUSED(listen)) +{ +} + +void listen_stop_accept(struct listen_dnsport* ATTR_UNUSED(listen)) +{ +} + +void daemon_remote_start_accept(struct daemon_remote* ATTR_UNUSED(rc)) +{ +} + +void daemon_remote_stop_accept(struct daemon_remote* ATTR_UNUSED(rc)) +{ +} + +/*********** End of Dummy routines ***********/ diff --git a/testcode/fake_event.h b/testcode/fake_event.h new file mode 100644 index 00000000000..1a73de824c1 --- /dev/null +++ b/testcode/fake_event.h @@ -0,0 +1,75 @@ +/* + * testcode/fake_event.h - fake event handling that replays existing scenario. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * Event service that replays a scenario. + * This implements the same exported symbols as the files: + * util/netevent.c + * services/listen_dnsport.c + * services/outside_network.c + * But these do not actually access the network or events, instead + * the scenario is played. + */ + +#ifndef TESTCODE_FAKE_EVENT_H +#define TESTCODE_FAKE_EVENT_H +struct replay_scenario; + +/** + * Initialise fake event services. + * + * The fake event services will automatically start when the main program + * calls netevent.h functions, such as comm_base_dispatch(). + * + * @param scen: Set the scenario to use for upcoming event handling. + */ +void fake_event_init(struct replay_scenario* scen); + +/** + * Deinit fake event services. + */ +void fake_event_cleanup(void); + +/** + * Get filename to store temporary config stuff. The pid is added. in /tmp. + * @param adj: adjective, like "_cfg_", "_auto_" + * @param id: identifier, like "example.com". + * @param buf: where to store. + * @param len: length of buf. + */ +void fake_temp_file(const char* adj, const char* id, char* buf, size_t len); + +#endif /* TESTCODE_FAKE_EVENT_H */ diff --git a/testcode/harvest.c b/testcode/harvest.c new file mode 100644 index 00000000000..1952dc2a221 --- /dev/null +++ b/testcode/harvest.c @@ -0,0 +1,857 @@ +/* + * testcode/harvest.c - debug program to get relevant data to a set of queries. + * + * Copyright (c) 2008, 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This program downloads relevant DNS data to a set of queries. + * This means that the queries are asked to root, TLD, SLD servers and + * the results stored per zone. + * The following data is pertinent: + * + * At each label: + * SOA + * NS + * DNSKEY + * DS + * For the whole query: + * the result. + * For NS-records: + * their label data + * and the A and AAAA records for it. + * (as if the name, with A and AAAA query type is in the list, + * referred to as recursion depth+1) + * Any NSEC, NSEC3, SOA records or additional data found in answers. + * + * All of this is data that would be encountered during an iterative lookup + * for the queries in the list. It is saved to enable a replay of iterative + * lookups for performance testing. + * + * A number of assumptions are made. + * 1) configuration is correct. + * The parent has the same NS records as the child. + * All nameservers carry the same data. + * 2) EDNS/nonEDNS responses and other behaviour is ignored. + * Only the data is saved. + * This creates a snapshot that represents the data as this resolver saw it. + */ + +#include "config.h" +#ifdef HAVE_GETOPT_H +#include +#endif +#include +#include +#include "libunbound/unbound.h" +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef UNBOUND_ALLOC_LITE +#undef malloc +#undef calloc +#undef realloc +#undef free +#undef strdup +#define unbound_lite_wrapstr(s) s +#endif +struct todo_item; +struct labdata; + +/** this represents the data that has been collected + * as well as a todo list and some settings */ +struct harvest_data { + /** the unbound context */ + struct ub_ctx* ctx; + + /** a tree per label; thus this first one is one root entry, + * that has a tree of TLD labels. Those have trees of SLD labels. */ + struct labdata* root; + /** the original query list */ + struct todo_item* orig_list; + /** the query list todo */ + struct todo_item* todo_list; + /** last item in todo list */ + struct todo_item* todo_last; + /** number of todo items */ + int numtodo; + + /** where to store the results */ + char* resultdir; + /** maximum recursion depth */ + int maxdepth; + /** current recursion depth */ + int curdepth; + + /** max depth of labels */ + int maxlabels; + /** number of RRs stored */ + int num_rrs; + /** number of zones written */ + int num_zones; +}; + +/** + * Todo item + */ +struct todo_item { + /** the next item */ + struct todo_item* next; + + /** query as rdf */ + ldns_rdf* qname; + /** the query type */ + int qtype; + /** query class */ + int qclass; + + /** recursion depth of todo item (orig list is 0) */ + int depth; + /** the label associated with the query */ + struct labdata* lab; +}; + +/** + * Every label has a sest of sublabels, that have sets of sublabels ... + * Per label is stored also a set of data items, and todo information + */ +struct labdata { + /** node in ldns rbtree */ + ldns_rbnode_t node; + /** the name of this label */ + ldns_rdf* label; + /** full name of point in domain tree */ + ldns_rdf* name; + + /** parent in label tree (NULL for root) */ + struct labdata* parent; + /** tree of sublabels (if any) */ + ldns_rbtree_t* sublabels; + + /** list of RRs for this label */ + ldns_rr_list* rrlist; + /** have queries for this label been queued */ + int done; +}; + +/** usage information for harvest */ +static void usage(char* nm) +{ + printf("usage: %s [options]\n", nm); + printf("-f fnm query list to read from file\n"); + printf(" every line has format: qname qclass qtype\n"); + printf("-v verbose (-v -v even more)\n"); + printf("-C cfg config file with resolver options\n"); + exit(1); +} + +/** verbosity for harvest */ +static int hverb = 0; + +/** exit with error */ +static void error_exit(const char* str) +{ + printf("error: %s\n", str); + exit(1); +} + +/** read a query file */ +static void +qlist_read_file(struct harvest_data* data, char* fname) +{ + char buf[1024]; + char nm[1024], cl[1024], tp[1024]; + int r; + int num = 0; + FILE* in = fopen(fname, "r"); + struct todo_item* t; + if(!in) { + perror(fname); + error_exit("could not open file"); + } + while(fgets(buf, (int)sizeof(buf), in)) { + if(buf[0] == 0) continue; + if(buf[0] == '\n') continue; + /* allow some comments */ + if(buf[0] == ';') continue; + if(buf[0] == '#') continue; + nm[0] = 0; cl[0] = 0; tp[0] = 0; + r = sscanf(buf, " %1023s %1023s %1023s", nm, cl, tp); + if(r == 0) continue; + t = (struct todo_item*)calloc(1, sizeof(*t)); + if(!t) error_exit("out of memory"); + t->qname = ldns_dname_new_frm_str(nm); + if(!t->qname) { + printf("parse error: %s\n", nm); + error_exit("bad qname"); + } + t->depth = 0; + t->qtype = LDNS_RR_TYPE_A; + t->qclass = LDNS_RR_CLASS_IN; + if(r >= 2) { + if(strcmp(cl, "IN") == 0 || strcmp(cl, "CH") == 0) + t->qclass = ldns_get_rr_class_by_name(cl); + else t->qtype = ldns_get_rr_type_by_name(cl); + } + if(r >= 3) { + if(strcmp(tp, "IN") == 0 || strcmp(tp, "CH") == 0) + t->qclass = ldns_get_rr_class_by_name(tp); + else t->qtype = ldns_get_rr_type_by_name(tp); + } + num++; + + t->next = data->orig_list; + data->orig_list = t; + } + printf("read %s: %d queries\n", fname, num); + fclose(in); +} + +/** compare two labels */ +static int +lab_cmp(const void *x, const void *y) +{ + return ldns_dname_compare((const ldns_rdf*)x, (const ldns_rdf*)y); +} + +/** create label entry */ +static struct labdata* +lab_create(const char* name) +{ + struct labdata* lab = (struct labdata*)calloc(1, sizeof(*lab)); + if(!lab) error_exit("out of memory"); + lab->label = ldns_dname_new_frm_str(name); + if(!lab->label) error_exit("out of memory"); + lab->name = ldns_dname_new_frm_str(name); + if(!lab->name) error_exit("out of memory"); + lab->node.key = lab->label; + lab->node.data = lab; + lab->sublabels = ldns_rbtree_create(lab_cmp); + if(!lab->sublabels) error_exit("out of memory"); + lab->rrlist = ldns_rr_list_new(); + if(!lab->rrlist) error_exit("out of memory"); + + return lab; +} + +/** for this name, lookup the label, create if does not exist */ +static struct labdata* +find_create_lab(struct harvest_data* data, ldns_rdf* name) +{ + struct labdata* lab = data->root; + struct labdata* nextlab; + ldns_rdf* next; + uint8_t numlab = ldns_dname_label_count(name); + if((int)numlab > data->maxlabels) + data->maxlabels = (int)numlab; + while(numlab--) { + next = ldns_dname_label(name, numlab); + if(!next) error_exit("ldns_dname_label"); + + nextlab = (struct labdata*) + ldns_rbtree_search(lab->sublabels, next); + if(!nextlab) { + /* create it */ + nextlab = (struct labdata*)calloc(1, sizeof(*lab)); + if(!nextlab) error_exit("out of memory"); + nextlab->label = ldns_rdf_clone(next); + if(!nextlab->label) error_exit("out of memory"); + nextlab->node.key = nextlab->label; + nextlab->node.data = nextlab; + nextlab->sublabels = ldns_rbtree_create(lab_cmp); + if(!nextlab->sublabels) error_exit("out of memory"); + nextlab->parent = lab; + nextlab->name = ldns_rdf_clone(next); + if(!nextlab->name) error_exit("out of memory"); + if(ldns_dname_cat(nextlab->name, lab->name) + != LDNS_STATUS_OK) error_exit("outofmem"); + nextlab->rrlist = ldns_rr_list_new(); + if(!nextlab->rrlist) error_exit("out of memory"); + (void)ldns_rbtree_insert(lab->sublabels, + &nextlab->node); + if(hverb) { + printf("new label: "); + ldns_rdf_print(stdout, nextlab->name); + printf("\n"); + } + } + lab = nextlab; + ldns_rdf_deep_free(next); + } + return lab; +} + +/** for given query, create todo items, and labels if needed */ +static void +new_todo_item(struct harvest_data* data, ldns_rdf* qname, int qtype, + int qclass, int depth) +{ + struct labdata* lab = find_create_lab(data, qname); + struct todo_item* it; + if(!lab) error_exit("out of memory creating new label"); + it = (struct todo_item*)calloc(1, sizeof(*it)); + it->qname = ldns_rdf_clone(qname); + it->qtype = qtype; + it->qclass = qclass; + it->depth = depth; + it->lab = lab; + it->next = NULL; + if(data->todo_last) + data->todo_last->next = it; + else data->todo_list = it; + data->todo_last = it; + data->numtodo ++; + if(hverb >= 2) { + printf("new todo: "); + ldns_rdf_print(stdout, it->qname); + if(ldns_rr_descript((uint16_t)it->qtype) && + ldns_rr_descript((uint16_t)it->qtype)->_name) + printf(" %s", ldns_rr_descript((uint16_t) + it->qtype)->_name); + if(ldns_lookup_by_id(ldns_rr_classes, it->qclass) && + ldns_lookup_by_id(ldns_rr_classes, it->qclass)->name) + printf(" %s", ldns_lookup_by_id(ldns_rr_classes, + it->qclass)->name); + printf("\n"); + } +} + +/** add infra todo items for this query */ +static void +new_todo_infra(struct harvest_data* data, struct labdata* startlab, int depth) +{ + struct labdata* lab; + for(lab = startlab; lab; lab = lab->parent) { + if(lab->done) + return; + new_todo_item(data, lab->name, LDNS_RR_TYPE_NS, + LDNS_RR_CLASS_IN, depth); + new_todo_item(data, lab->name, LDNS_RR_TYPE_SOA, + LDNS_RR_CLASS_IN, depth); + new_todo_item(data, lab->name, LDNS_RR_TYPE_DNSKEY, + LDNS_RR_CLASS_IN, depth); + new_todo_item(data, lab->name, LDNS_RR_TYPE_DS, + LDNS_RR_CLASS_IN, depth); + new_todo_item(data, lab->name, LDNS_RR_TYPE_A, + LDNS_RR_CLASS_IN, depth); + new_todo_item(data, lab->name, LDNS_RR_TYPE_AAAA, + LDNS_RR_CLASS_IN, depth); + lab->done = 1; + } +} + +/** make todo items for initial data */ +static void +make_todo(struct harvest_data* data) +{ + struct todo_item* it; + for(it=data->orig_list; it; it = it->next) { + /* create todo item for this query itself */ + new_todo_item(data, it->qname, it->qtype, it->qclass, 0); + /* create todo items for infra queries to support it */ + new_todo_infra(data, data->todo_list->lab, + data->todo_list->depth); + } +} + +/** store RR and make new work items for it if needed */ +static void +process_rr(struct harvest_data* data, ldns_rr* rr, int depth) +{ + /* must free or store rr */ + struct labdata* lab = find_create_lab(data, ldns_rr_owner(rr)); + if(!lab) error_exit("cannot find/create label"); + /* generate extra queries */ + if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_NS) { + new_todo_infra(data, find_create_lab(data, + ldns_rr_ns_nsdname(rr)), depth+1); + } else if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_MX) { + new_todo_infra(data, find_create_lab(data, + ldns_rr_mx_exchange(rr)), depth+1); + } else if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) { + new_todo_infra(data, find_create_lab(data, + ldns_rr_rdf(rr, 0)), depth+1); + } else if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_CNAME) { + int t = ldns_rr_get_type(rr); + if(t!=LDNS_RR_TYPE_A && t!=LDNS_RR_TYPE_AAAA && + t!=LDNS_RR_TYPE_SOA && t!=LDNS_RR_TYPE_NS && + t!=LDNS_RR_TYPE_DS && t!=LDNS_RR_TYPE_DNSKEY) + new_todo_item(data, ldns_rr_rdf(rr, 0), t, + ldns_rr_get_class(rr), depth+1); + /* can get caught in CNAME loop, but depth will + * catch that; unbound cache helps too(servfails on + * a cname loop) */ + new_todo_infra(data, find_create_lab(data, + ldns_rr_rdf(rr, 0)), depth+1); + } + /* store it */ + if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC) { + /* find correct zone to store NSEC in (for delegation zones) */ + if(ldns_dname_compare(ldns_rr_rdf(rr, 0), ldns_rr_owner(rr)) + == 0) { + /* store at the single name = apex */ + } else if(!ldns_dname_is_subdomain(ldns_rr_rdf(rr, 0), + ldns_rr_owner(rr)) && lab->parent) { + /* if owner NSEC subdomain-of-owner then + * store at owner (owner is apex or empty nonterminal). + * Otherwise at owner parent. */ + lab = lab->parent; + } + } else if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_DS) { + /* store DSes in parent zone */ + if(lab->parent) + lab = lab->parent; + } else if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3) { + /* store NSEC3s one label up at zone apex */ + if(lab->parent) + lab = lab->parent; + } + /* we assume NS set is equal across parent-child border. */ + + if(!ldns_rr_list_contains_rr(lab->rrlist, rr)) { + if(hverb >= 2) { + printf("store RR "); + ldns_rr_print(stdout, rr); + printf("\n"); + } + if(!ldns_rr_list_push_rr(lab->rrlist, rr)) + error_exit("outofmem ldns_rr_list_push_rr"); + data->num_rrs++; + } else { + if(hverb >= 2) { + printf("duplicate RR "); + ldns_rr_print(stdout, rr); + printf("\n"); + } + ldns_rr_free(rr); + } +} + +/** store RRs and make new work items if needed */ +static void +process_pkt(struct harvest_data* data, ldns_pkt* pkt, int depth) +{ + size_t i; + ldns_rr_list* list; + list = ldns_pkt_get_section_clone(pkt, LDNS_SECTION_ANY_NOQUESTION); + if(!list) error_exit("outofmemory"); + for(i=0; iqname); + if(ldns_rr_descript((uint16_t)it->qtype) && + ldns_rr_descript((uint16_t)it->qtype)->_name) + printf(" %s", ldns_rr_descript((uint16_t) + it->qtype)->_name); + if(ldns_lookup_by_id(ldns_rr_classes, it->qclass) && + ldns_lookup_by_id(ldns_rr_classes, it->qclass)->name) + printf(" %s", ldns_lookup_by_id(ldns_rr_classes, + it->qclass)->name); + printf("\n"); + } + /* do lookup */ + nm = ldns_rdf2str(it->qname); + if(!nm) error_exit("ldns_rdf2str"); + r = ub_resolve(data->ctx, nm, it->qtype, it->qclass, &result); + if(r != 0) { + printf("ub_resolve(%s, %d, %d): %s\n", nm, it->qtype, + it->qclass, ub_strerror(r)); + free(nm); + return; + } + if(result->rcode == LDNS_RCODE_SERVFAIL) { + free(nm); + return; + } + /* even if result is a negative, try to store resulting SOA/NSEC */ + + /* create ldns pkt */ + s = ldns_wire2pkt(&pkt, result->answer_packet, + (size_t)result->answer_len); + if(s != LDNS_STATUS_OK) { + printf("ldns_wire2pkt failed! %s %d %d %s %d\n", nm, + it->qtype, it->qclass, ldns_get_errorstr_by_id(s), + result->answer_len); + free(nm); + return; + } + if(hverb >= 2) { + printf("answer: "); + ldns_pkt_print(stdout, pkt); + printf("\n"); + } + /* process results */ + process_pkt(data, pkt, it->depth); + + ldns_pkt_free(pkt); + free(nm); + ub_resolve_free(result); +} + +/** perform main harvesting */ +static void +harvest_main(struct harvest_data* data) +{ + struct todo_item* it; + int numdone = 0; + /* register todo queries for all original queries */ + make_todo(data); + printf("depth 0: done %d todo %d\n", 0, data->numtodo); + /* pick up a todo item and process it */ + while(data->todo_list) { + numdone++; + it = data->todo_list; + data->todo_list = it->next; + if(!data->todo_list) data->todo_last = NULL; + if(numdone%1000==0 || it->depth > data->curdepth) { + data->curdepth = it->depth; + printf("depth %d: done %d todo %d, %d rrs\n", + it->depth, numdone, data->numtodo, + data->num_rrs); + } + if(it->depth >= data->maxdepth) { + printf("obtained %d rrs to a max of %d labels.\n", + data->num_rrs, data->maxlabels); + return; + } + data->numtodo--; + process(data, it); + usleep(1000000/100); + } +} + +/** create directory if it does not exist */ +static void +hv_mkdir(char* dir) +{ +#ifdef MKDIR_HAS_ONE_ARG + if(mkdir(dir) == -1) { +#else + if(mkdir(dir, 0755) == -1) { +#endif + if(errno == EEXIST) + return; + perror(dir); + error_exit("mkdir failed"); + } +} + + +/** see if rrlist contains a SOA record */ +static ldns_rr* +has_SOA(ldns_rr_list* list) +{ + size_t i; + for(i=0; isublabels) { + if(has_SOA(lab->rrlist)) { + /* copy only NS glue */ + for(i=0; irrlist); i++) { + ns = ldns_rr_list_rr(lab->rrlist, i); + if(ldns_rr_get_type(ns) == LDNS_RR_TYPE_NS) { + ldns_rr_print(f, ns); + if(ldns_dname_is_subdomain( + ldns_rr_ns_nsdname(ns), + lab->name)) { + ldns_rr_push_rdf(nslist, + ldns_rdf_clone( + ldns_rr_ns_nsdname(ns))); + } + } + } + } else { + /* copy all, recurse */ + for(i=0; irrlist); i++) { + ldns_rr_print(f, + ldns_rr_list_rr(lab->rrlist, i)); + } + write_moredata(data, zone, f, lab, nslist); + } + } +} + +/** find and write glue into zone file */ +static void +write_glue(struct harvest_data* data, struct labdata* thislab, FILE* f, + ldns_rdf* name, int dep) +{ + size_t i; + struct labdata* lab; + ldns_rr* rr; + if(ldns_dname_compare(name, thislab->name) == 0) { + /* this is it! Did we go outside the zone? */ + if(dep == 0) + return; + /* find A and AAAA */ + for(i=0; irrlist); i++) { + rr = ldns_rr_list_rr(thislab->rrlist, i); + if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_A || + ldns_rr_get_type(rr) == LDNS_RR_TYPE_AAAA) { + ldns_rr_print(f, rr); + } + } + return; + } + /* recurse deeper */ + LDNS_RBTREE_FOR(lab, struct labdata*, thislab->sublabels) { + if(has_SOA(lab->rrlist)) { + write_glue(data, lab, f, name, dep+1); + } else { + write_glue(data, lab, f, name, dep); + } + } +} + +/** write zonefile for zone at this apex */ +static void +write_zonefile(struct harvest_data* data, int dep, FILE* zlist, + struct labdata* apex, ldns_rr* soa) +{ + FILE *f; + char fname[1024]; + char* zname = ldns_rdf2str(apex->name); + time_t tm = time(NULL); + size_t i; + ldns_rr* nslist; + if(!zname) error_exit("out of mem ldns_rdf2str"); + if(strcmp(zname, ".") == 0) + snprintf(fname, sizeof(fname), "l%d/root.zone", dep); + else snprintf(fname, sizeof(fname), "l%d/%szone", dep, zname); + + fprintf(zlist, "zone: name: \"%s\" %s%szonefile: \"%s\"\n", + zname, + strlen(zname)/8<1?"\t":"", + strlen(zname)/8<2?"\t":"", + fname); + + if(hverb) printf("writing %s\n", fname); + f = fopen(fname, "w"); + if(!f) { + perror(fname); + error_exit("cannot open zone file"); + } + fprintf(f, "; %s - generated by harvest program.\n", fname); + fprintf(f, "; zone name %s - this is a partial snapshot of " + "data relevant to the query list.\n", zname); + fprintf(f, "; created %u - date %s\n", (unsigned)tm, ctime(&tm)); + ldns_rr_print(f, soa); + fprintf(f, "\n"); + for(i=0; irrlist); i++) { + if(ldns_rr_get_type(ldns_rr_list_rr(apex->rrlist, i)) + == LDNS_RR_TYPE_SOA) continue; + ldns_rr_print(f, ldns_rr_list_rr(apex->rrlist, i)); + } + /* search for more data - subdomains inside the zone, NS glue */ + nslist = ldns_rr_new(); + if(!nslist) error_exit("out of memory"); + fprintf(f, "; end of apex, more data follows\n"); + write_moredata(data, apex, f, apex, nslist); + + /* add NS from apex that need glue too */ + for(i=0; irrlist); i++) { + if(ldns_rr_get_type(ldns_rr_list_rr(apex->rrlist, i)) != + LDNS_RR_TYPE_NS) + continue; + /* these are only added again if in a subzone */ + if(ldns_dname_is_subdomain(ldns_rr_ns_nsdname( + ldns_rr_list_rr(apex->rrlist, i)), apex->name)) { + ldns_rr_push_rdf(nslist, ldns_rdf_clone( + ldns_rr_ns_nsdname(ldns_rr_list_rr( + apex->rrlist, i)))); + } + } + + fprintf(f, "; glue data follows\n"); + /* lookup and add glue (if not already in zone) */ + for(i=0; irrlist))) { + write_zonefile(data, dep, zlist, labnow, soa); + data->num_zones++; + } + return; + } + /* recurse */ + LDNS_RBTREE_FOR(s, struct labdata*, labnow->sublabels) { + create_zones(data, dep, zlist, s, depnow+1); + } +} + +/** sort rrlists */ +static void +harvest_sort(struct labdata* lab) +{ + struct labdata* s; + /* prettier output if sorted here */ + ldns_rr_list_sort(lab->rrlist); + /* and recurse */ + LDNS_RBTREE_FOR(s, struct labdata*, lab->sublabels) { + harvest_sort(s); + } +} + +/** output harvested results */ +static void +harvest_output(struct harvest_data* data) +{ + int d; + char buf[20]; + FILE* zlist; + int lastzones; + hv_mkdir(data->resultdir); + if(chdir(data->resultdir) == -1) { + perror(data->resultdir); + error_exit("cannot chdir"); + } + harvest_sort(data->root); + /* create zones */ + for(d = 0; dmaxlabels; d++) { + lastzones = data->num_zones; + printf("creating zones %d\n", d); + snprintf(buf, sizeof(buf), "l%d", d); + hv_mkdir(buf); + snprintf(buf, sizeof(buf), "l%d.zones", d); + zlist = fopen(buf, "w"); + if(!zlist) { + perror(buf); + error_exit("cannot write zonelist file"); + } + fprintf(zlist, "# partial zones at depth %d\n", d); + create_zones(data, d, zlist, data->root, 0); + fclose(zlist); + printf("creating zones %d - %d zones written\n", d, + data->num_zones - lastzones); + } +} + +/** getopt global, in case header files fail to declare it. */ +extern int optind; +/** getopt global, in case header files fail to declare it. */ +extern char* optarg; + +/** main program for harvest */ +int main(int argc, char* argv[]) +{ + struct harvest_data data; + char* nm = argv[0]; + int c; + + /* defaults */ + memset(&data, 0, sizeof(data)); + data.ctx = ub_ctx_create(); + data.resultdir = strdup("harvested_zones"); + if(!data.resultdir) error_exit("out of memory"); + data.maxdepth = 2; + + /* parse the options */ + while( (c=getopt(argc, argv, "hf:vC:")) != -1) { + switch(c) { + case 'C': + if(ub_ctx_config(data.ctx, optarg) != 0) + error_exit("config read failed"); + break; + case 'f': + qlist_read_file(&data, optarg); + break; + case 'v': + hverb++; + break; + case '?': + case 'h': + default: + usage(nm); + } + } + argc -= optind; + argv += optind; + if(argc != 0) + usage(nm); + if(data.orig_list == NULL) + error_exit("No queries to make, use -f (help with -h)."); + data.root = lab_create("."); + if(!data.root) error_exit("out of memory"); + + /* harvest the data */ + harvest_main(&data); + harvest_output(&data); + + /* no cleanup except the context (to close open sockets) */ + ub_ctx_delete(data.ctx); + return 0; +} diff --git a/testcode/ldns-testpkts.c b/testcode/ldns-testpkts.c new file mode 100644 index 00000000000..d8139511ab5 --- /dev/null +++ b/testcode/ldns-testpkts.c @@ -0,0 +1,881 @@ +/* + * ldns-testpkts. Data file parse for test packets, and query matching. + * + * Data storage for specially crafted replies for testing purposes. + * + * (c) NLnet Labs, 2005, 2006, 2007, 2008 + * See the file LICENSE for the license + */ + +/** + * \file + * This is a debugging aid. It is not efficient, especially + * with a long config file, but it can give any reply to any query. + * This can help the developer pre-script replies for queries. + * + * You can specify a packet RR by RR with header flags to return. + * + * Missing features: + * - matching content different from reply content. + * - find way to adjust mangled packets? + */ + +#include "config.h" +struct sockaddr_storage; +#include +#include +#include "ldns-testpkts.h" + +/** max line length */ +#define MAX_LINE 10240 +/** string to show in warnings and errors */ +static const char* prog_name = "ldns-testpkts"; + +#ifndef UTIL_LOG_H +/** verbosity definition for compat */ +enum verbosity_value { NO_VERBOSE=0 }; +#endif +/** logging routine, provided by caller */ +void verbose(enum verbosity_value lvl, const char* msg, ...) ATTR_FORMAT(printf, 2, 3); + +/** print error and exit */ +static void error(const char* msg, ...) +{ + va_list args; + va_start(args, msg); + fprintf(stderr, "%s error: ", prog_name); + vfprintf(stderr, msg, args); + fprintf(stderr, "\n"); + fflush(stderr); + va_end(args); + exit(EXIT_FAILURE); +} + +/** return if string is empty or comment */ +static bool isendline(char c) +{ + if(c == ';' || c == '#' + || c == '\n' || c == 0) + return true; + return false; +} + +/** true if the string starts with the keyword given. Moves the str ahead. + * @param str: before keyword, afterwards after keyword and spaces. + * @param keyword: the keyword to match + * @return: true if keyword present. False otherwise, and str unchanged. +*/ +static bool str_keyword(char** str, const char* keyword) +{ + size_t len = strlen(keyword); + assert(str && keyword); + if(strncmp(*str, keyword, len) != 0) + return false; + *str += len; + while(isspace((int)**str)) + (*str)++; + return true; +} + +/** Add reply packet to entry */ +static struct reply_packet* +entry_add_reply(struct entry* entry) +{ + struct reply_packet* pkt = (struct reply_packet*)malloc( + sizeof(struct reply_packet)); + struct reply_packet ** p = &entry->reply_list; + pkt->next = NULL; + pkt->packet_sleep = 0; + pkt->reply = ldns_pkt_new(); + pkt->reply_from_hex = NULL; + /* link at end */ + while(*p) + p = &((*p)->next); + *p = pkt; + return pkt; +} + +/** parse MATCH line */ +static void matchline(char* line, struct entry* e) +{ + char* parse = line; + while(*parse) { + if(isendline(*parse)) + return; + if(str_keyword(&parse, "opcode")) { + e->match_opcode = true; + } else if(str_keyword(&parse, "qtype")) { + e->match_qtype = true; + } else if(str_keyword(&parse, "qname")) { + e->match_qname = true; + } else if(str_keyword(&parse, "subdomain")) { + e->match_subdomain = true; + } else if(str_keyword(&parse, "all")) { + e->match_all = true; + } else if(str_keyword(&parse, "ttl")) { + e->match_ttl = true; + } else if(str_keyword(&parse, "DO")) { + e->match_do = true; + } else if(str_keyword(&parse, "noedns")) { + e->match_noedns = true; + } else if(str_keyword(&parse, "UDP")) { + e->match_transport = transport_udp; + } else if(str_keyword(&parse, "TCP")) { + e->match_transport = transport_tcp; + } else if(str_keyword(&parse, "serial")) { + e->match_serial = true; + if(*parse != '=' && *parse != ':') + error("expected = or : in MATCH: %s", line); + parse++; + e->ixfr_soa_serial = (uint32_t)strtol(parse, (char**)&parse, 10); + while(isspace((int)*parse)) + parse++; + } else { + error("could not parse MATCH: '%s'", parse); + } + } +} + +/** parse REPLY line */ +static void replyline(char* line, ldns_pkt *reply) +{ + char* parse = line; + while(*parse) { + if(isendline(*parse)) + return; + /* opcodes */ + if(str_keyword(&parse, "QUERY")) { + ldns_pkt_set_opcode(reply, LDNS_PACKET_QUERY); + } else if(str_keyword(&parse, "IQUERY")) { + ldns_pkt_set_opcode(reply, LDNS_PACKET_IQUERY); + } else if(str_keyword(&parse, "STATUS")) { + ldns_pkt_set_opcode(reply, LDNS_PACKET_STATUS); + } else if(str_keyword(&parse, "NOTIFY")) { + ldns_pkt_set_opcode(reply, LDNS_PACKET_NOTIFY); + } else if(str_keyword(&parse, "UPDATE")) { + ldns_pkt_set_opcode(reply, LDNS_PACKET_UPDATE); + /* rcodes */ + } else if(str_keyword(&parse, "NOERROR")) { + ldns_pkt_set_rcode(reply, LDNS_RCODE_NOERROR); + } else if(str_keyword(&parse, "FORMERR")) { + ldns_pkt_set_rcode(reply, LDNS_RCODE_FORMERR); + } else if(str_keyword(&parse, "SERVFAIL")) { + ldns_pkt_set_rcode(reply, LDNS_RCODE_SERVFAIL); + } else if(str_keyword(&parse, "NXDOMAIN")) { + ldns_pkt_set_rcode(reply, LDNS_RCODE_NXDOMAIN); + } else if(str_keyword(&parse, "NOTIMPL")) { + ldns_pkt_set_rcode(reply, LDNS_RCODE_NOTIMPL); + } else if(str_keyword(&parse, "REFUSED")) { + ldns_pkt_set_rcode(reply, LDNS_RCODE_REFUSED); + } else if(str_keyword(&parse, "YXDOMAIN")) { + ldns_pkt_set_rcode(reply, LDNS_RCODE_YXDOMAIN); + } else if(str_keyword(&parse, "YXRRSET")) { + ldns_pkt_set_rcode(reply, LDNS_RCODE_YXRRSET); + } else if(str_keyword(&parse, "NXRRSET")) { + ldns_pkt_set_rcode(reply, LDNS_RCODE_NXRRSET); + } else if(str_keyword(&parse, "NOTAUTH")) { + ldns_pkt_set_rcode(reply, LDNS_RCODE_NOTAUTH); + } else if(str_keyword(&parse, "NOTZONE")) { + ldns_pkt_set_rcode(reply, LDNS_RCODE_NOTZONE); + /* flags */ + } else if(str_keyword(&parse, "QR")) { + ldns_pkt_set_qr(reply, true); + } else if(str_keyword(&parse, "AA")) { + ldns_pkt_set_aa(reply, true); + } else if(str_keyword(&parse, "TC")) { + ldns_pkt_set_tc(reply, true); + } else if(str_keyword(&parse, "RD")) { + ldns_pkt_set_rd(reply, true); + } else if(str_keyword(&parse, "CD")) { + ldns_pkt_set_cd(reply, true); + } else if(str_keyword(&parse, "RA")) { + ldns_pkt_set_ra(reply, true); + } else if(str_keyword(&parse, "AD")) { + ldns_pkt_set_ad(reply, true); + } else if(str_keyword(&parse, "DO")) { + ldns_pkt_set_edns_udp_size(reply, 4096); + ldns_pkt_set_edns_do(reply, true); + } else { + error("could not parse REPLY: '%s'", parse); + } + } +} + +/** parse ADJUST line */ +static void adjustline(char* line, struct entry* e, + struct reply_packet* pkt) +{ + char* parse = line; + while(*parse) { + if(isendline(*parse)) + return; + if(str_keyword(&parse, "copy_id")) { + e->copy_id = true; + } else if(str_keyword(&parse, "copy_query")) { + e->copy_query = true; + } else if(str_keyword(&parse, "sleep=")) { + e->sleeptime = (unsigned int) strtol(parse, (char**)&parse, 10); + while(isspace((int)*parse)) + parse++; + } else if(str_keyword(&parse, "packet_sleep=")) { + pkt->packet_sleep = (unsigned int) strtol(parse, (char**)&parse, 10); + while(isspace((int)*parse)) + parse++; + } else { + error("could not parse ADJUST: '%s'", parse); + } + } +} + +/** create new entry */ +static struct entry* new_entry() +{ + struct entry* e = LDNS_MALLOC(struct entry); + memset(e, 0, sizeof(*e)); + e->match_opcode = false; + e->match_qtype = false; + e->match_qname = false; + e->match_subdomain = false; + e->match_all = false; + e->match_ttl = false; + e->match_do = false; + e->match_noedns = false; + e->match_serial = false; + e->ixfr_soa_serial = 0; + e->match_transport = transport_any; + e->reply_list = NULL; + e->copy_id = false; + e->copy_query = false; + e->sleeptime = 0; + e->next = NULL; + return e; +} + +/** + * Converts a hex string to binary data + * @param hexstr: string of hex. + * @param len: is the length of the string + * @param buf: is the buffer to store the result in + * @param offset: is the starting position in the result buffer + * @param buf_len: is the length of buf. + * @return This function returns the length of the result + */ +static size_t +hexstr2bin(char *hexstr, int len, uint8_t *buf, size_t offset, size_t buf_len) +{ + char c; + int i; + uint8_t int8 = 0; + int sec = 0; + size_t bufpos = 0; + + if (len % 2 != 0) { + return 0; + } + + for (i=0; i= '0' && c <= '9') { + int8 += c & 0x0f; + } else if (c >= 'a' && c <= 'z') { + int8 += (c & 0x0f) + 9; + } else if (c >= 'A' && c <= 'Z') { + int8 += (c & 0x0f) + 9; + } else { + return 0; + } + + if (sec == 0) { + int8 = int8 << 4; + sec = 1; + } else { + if (bufpos + offset + 1 <= buf_len) { + buf[bufpos+offset] = int8; + int8 = 0; + sec = 0; + bufpos++; + } else { + fprintf(stderr, "Buffer too small in hexstr2bin"); + } + } + } + } + return bufpos; +} + +/** convert hex buffer to binary buffer */ +static ldns_buffer * +data_buffer2wire(ldns_buffer *data_buffer) +{ + ldns_buffer *wire_buffer = NULL; + int c; + + /* stat hack + * 0 = normal + * 1 = comment (skip to end of line) + * 2 = unprintable character found, read binary data directly + */ + size_t data_buf_pos = 0; + int state = 0; + uint8_t *hexbuf; + int hexbufpos = 0; + size_t wirelen; + uint8_t *data_wire = (uint8_t *) ldns_buffer_export(data_buffer); + uint8_t *wire = LDNS_XMALLOC(uint8_t, LDNS_MAX_PACKETLEN); + + hexbuf = LDNS_XMALLOC(uint8_t, LDNS_MAX_PACKETLEN); + for (data_buf_pos = 0; data_buf_pos < ldns_buffer_position(data_buffer); data_buf_pos++) { + c = (int) data_wire[data_buf_pos]; + + if (state < 2 && !isascii(c)) { + /*verbose("non ascii character found in file: (%d) switching to raw mode\n", c);*/ + state = 2; + } + switch (state) { + case 0: + if ( (c >= '0' && c <= '9') || + (c >= 'a' && c <= 'f') || + (c >= 'A' && c <= 'F') ) + { + hexbuf[hexbufpos] = (uint8_t) c; + hexbufpos++; + } else if (c == ';') { + state = 1; + } else if (c == ' ' || c == '\t' || c == '\n') { + /* skip whitespace */ + } + break; + case 1: + if (c == '\n' || c == EOF) { + state = 0; + } + break; + case 2: + hexbuf[hexbufpos] = (uint8_t) c; + hexbufpos++; + break; + default: + error("unknown state while reading"); + LDNS_FREE(hexbuf); + return 0; + break; + } + } + + if (hexbufpos >= LDNS_MAX_PACKETLEN) { + /*verbose("packet size reached\n");*/ + } + + /* lenient mode: length must be multiple of 2 */ + if (hexbufpos % 2 != 0) { + hexbuf[hexbufpos] = (uint8_t) '0'; + hexbufpos++; + } + + if (state < 2) { + wirelen = hexstr2bin((char *) hexbuf, hexbufpos, wire, 0, LDNS_MAX_PACKETLEN); + wire_buffer = ldns_buffer_new(wirelen); + ldns_buffer_new_frm_data(wire_buffer, wire, wirelen); + } else { + error("Incomplete hex data, not at byte boundary\n"); + } + LDNS_FREE(wire); + LDNS_FREE(hexbuf); + return wire_buffer; +} + +/** parse ORIGIN */ +static void +get_origin(const char* name, int lineno, ldns_rdf** origin, char* parse) +{ + /* snip off rest of the text so as to make the parse work in ldns */ + char* end; + char store; + ldns_status status; + + ldns_rdf_free(*origin); + *origin = NULL; + + end=parse; + while(!isspace((int)*end) && !isendline(*end)) + end++; + store = *end; + *end = 0; + verbose(3, "parsing '%s'\n", parse); + status = ldns_str2rdf_dname(origin, parse); + *end = store; + if (status != LDNS_STATUS_OK) + error("%s line %d:\n\t%s: %s", name, lineno, + ldns_get_errorstr_by_id(status), parse); +} + +/* Reads one entry from file. Returns entry or NULL on error. */ +struct entry* +read_entry(FILE* in, const char* name, int *lineno, uint32_t* default_ttl, + ldns_rdf** origin, ldns_rdf** prev_rr) +{ + struct entry* current = NULL; + char line[MAX_LINE]; + char* parse; + ldns_pkt_section add_section = LDNS_SECTION_QUESTION; + struct reply_packet *cur_reply = NULL; + bool reading_hex = false; + ldns_buffer* hex_data_buffer = NULL; + + while(fgets(line, (int)sizeof(line), in) != NULL) { + line[MAX_LINE-1] = 0; + parse = line; + (*lineno) ++; + + while(isspace((int)*parse)) + parse++; + /* test for keywords */ + if(isendline(*parse)) + continue; /* skip comment and empty lines */ + if(str_keyword(&parse, "ENTRY_BEGIN")) { + if(current) { + error("%s line %d: previous entry does not ENTRY_END", + name, *lineno); + } + current = new_entry(); + current->lineno = *lineno; + cur_reply = entry_add_reply(current); + continue; + } else if(str_keyword(&parse, "$ORIGIN")) { + get_origin(name, *lineno, origin, parse); + continue; + } else if(str_keyword(&parse, "$TTL")) { + *default_ttl = (uint32_t)atoi(parse); + continue; + } + + /* working inside an entry */ + if(!current) { + error("%s line %d: expected ENTRY_BEGIN but got %s", + name, *lineno, line); + } + if(str_keyword(&parse, "MATCH")) { + matchline(parse, current); + } else if(str_keyword(&parse, "REPLY")) { + replyline(parse, cur_reply->reply); + } else if(str_keyword(&parse, "ADJUST")) { + adjustline(parse, current, cur_reply); + } else if(str_keyword(&parse, "EXTRA_PACKET")) { + cur_reply = entry_add_reply(current); + } else if(str_keyword(&parse, "SECTION")) { + if(str_keyword(&parse, "QUESTION")) + add_section = LDNS_SECTION_QUESTION; + else if(str_keyword(&parse, "ANSWER")) + add_section = LDNS_SECTION_ANSWER; + else if(str_keyword(&parse, "AUTHORITY")) + add_section = LDNS_SECTION_AUTHORITY; + else if(str_keyword(&parse, "ADDITIONAL")) + add_section = LDNS_SECTION_ADDITIONAL; + else error("%s line %d: bad section %s", name, *lineno, parse); + } else if(str_keyword(&parse, "HEX_ANSWER_BEGIN")) { + hex_data_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN); + reading_hex = true; + } else if(str_keyword(&parse, "HEX_ANSWER_END")) { + if (!reading_hex) { + error("%s line %d: HEX_ANSWER_END read but no HEX_ANSWER_BEGIN keyword seen", name, *lineno); + } + reading_hex = false; + cur_reply->reply_from_hex = data_buffer2wire(hex_data_buffer); + ldns_buffer_free(hex_data_buffer); + } else if(str_keyword(&parse, "ENTRY_END")) { + return current; + } else if(reading_hex) { + ldns_buffer_printf(hex_data_buffer, line); + } else { + /* it must be a RR, parse and add to packet. */ + ldns_rr* n = NULL; + ldns_status status; + if(add_section == LDNS_SECTION_QUESTION) + status = ldns_rr_new_question_frm_str( + &n, parse, *origin, prev_rr); + else status = ldns_rr_new_frm_str(&n, parse, + *default_ttl, *origin, prev_rr); + if(status != LDNS_STATUS_OK) + error("%s line %d:\n\t%s: %s", name, *lineno, + ldns_get_errorstr_by_id(status), parse); + ldns_pkt_push_rr(cur_reply->reply, add_section, n); + } + + } + if (reading_hex) { + error("%s: End of file reached while still reading hex, " + "missing HEX_ANSWER_END\n", name); + } + if(current) { + error("%s: End of file reached while reading entry. " + "missing ENTRY_END\n", name); + } + return 0; +} + +/* reads the canned reply file and returns a list of structs */ +struct entry* +read_datafile(const char* name) +{ + struct entry* list = NULL; + struct entry* last = NULL; + struct entry* current = NULL; + FILE *in; + int lineno = 0; + uint32_t default_ttl = 0; + ldns_rdf* origin = NULL; + ldns_rdf* prev_rr = NULL; + int entry_num = 0; + + if((in=fopen(name, "r")) == NULL) { + error("could not open file %s: %s", name, strerror(errno)); + } + + while((current = read_entry(in, name, &lineno, &default_ttl, + &origin, &prev_rr))) + { + if(last) + last->next = current; + else list = current; + last = current; + entry_num ++; + } + verbose(1, "%s: Read %d entries\n", prog_name, entry_num); + + fclose(in); + ldns_rdf_deep_free(origin); + ldns_rdf_deep_free(prev_rr); + return list; +} + +/** get qtype from rr */ +static ldns_rr_type get_qtype(ldns_pkt* p) +{ + if(!ldns_rr_list_rr(ldns_pkt_question(p), 0)) + return 0; + return ldns_rr_get_type(ldns_rr_list_rr(ldns_pkt_question(p), 0)); +} + +/** returns owner from rr */ +static ldns_rdf* get_owner(ldns_pkt* p) +{ + if(!ldns_rr_list_rr(ldns_pkt_question(p), 0)) + return NULL; + return ldns_rr_owner(ldns_rr_list_rr(ldns_pkt_question(p), 0)); +} + +/** get authority section SOA serial value */ +static uint32_t get_serial(ldns_pkt* p) +{ + ldns_rr *rr = ldns_rr_list_rr(ldns_pkt_authority(p), 0); + ldns_rdf *rdf; + uint32_t val; + if(!rr) return 0; + rdf = ldns_rr_rdf(rr, 2); + if(!rdf) return 0; + val = ldns_rdf2native_int32(rdf); + verbose(3, "found serial %u in msg. ", (int)val); + return val; +} + +/** match two rr lists */ +static int +match_list(ldns_rr_list* q, ldns_rr_list *p, bool mttl) +{ + size_t i; + if(ldns_rr_list_rr_count(q) != ldns_rr_list_rr_count(p)) + return 0; + for(i=0; inext) { + verbose(3, "comparepkt: "); + reply = p->reply_list->reply; + if(p->match_opcode && ldns_pkt_get_opcode(query_pkt) != + ldns_pkt_get_opcode(reply)) { + verbose(3, "bad opcode\n"); + continue; + } + if(p->match_qtype && get_qtype(query_pkt) != get_qtype(reply)) { + verbose(3, "bad qtype\n"); + continue; + } + if(p->match_qname) { + if(!get_owner(query_pkt) || !get_owner(reply) || + ldns_dname_compare( + get_owner(query_pkt), get_owner(reply)) != 0) { + verbose(3, "bad qname\n"); + continue; + } + } + if(p->match_subdomain) { + if(!get_owner(query_pkt) || !get_owner(reply) || + (ldns_dname_compare(get_owner(query_pkt), + get_owner(reply)) != 0 && + !ldns_dname_is_subdomain( + get_owner(query_pkt), get_owner(reply)))) + { + verbose(3, "bad subdomain\n"); + continue; + } + } + if(p->match_serial && get_serial(query_pkt) != p->ixfr_soa_serial) { + verbose(3, "bad serial\n"); + continue; + } + if(p->match_do && !ldns_pkt_edns_do(query_pkt)) { + verbose(3, "no DO bit set\n"); + continue; + } + if(p->match_noedns && ldns_pkt_edns(query_pkt)) { + verbose(3, "bad; EDNS OPT present\n"); + continue; + } + if(p->match_transport != transport_any && p->match_transport != transport) { + verbose(3, "bad transport\n"); + continue; + } + if(p->match_all && !match_all(query_pkt, reply, p->match_ttl)) { + verbose(3, "bad allmatch\n"); + continue; + } + verbose(3, "match!\n"); + return p; + } + return NULL; +} + +void +adjust_packet(struct entry* match, ldns_pkt* answer_pkt, ldns_pkt* query_pkt) +{ + /* copy & adjust packet */ + if(match->copy_id) + ldns_pkt_set_id(answer_pkt, ldns_pkt_id(query_pkt)); + if(match->copy_query) { + ldns_rr_list* list = ldns_pkt_get_section_clone(query_pkt, + LDNS_SECTION_QUESTION); + ldns_rr_list_deep_free(ldns_pkt_question(answer_pkt)); + ldns_pkt_set_question(answer_pkt, list); + } + if(match->sleeptime > 0) { + verbose(3, "sleeping for %d seconds\n", match->sleeptime); +#ifdef HAVE_SLEEP + sleep(match->sleeptime); +#else + Sleep(match->sleeptime * 1000); +#endif + } +} + +/* + * Parses data buffer to a query, finds the correct answer + * and calls the given function for every packet to send. + */ +void +handle_query(uint8_t* inbuf, ssize_t inlen, struct entry* entries, int* count, + enum transport_type transport, void (*sendfunc)(uint8_t*, size_t, void*), + void* userdata, FILE* verbose_out) +{ + ldns_status status; + ldns_pkt *query_pkt = NULL; + ldns_pkt *answer_pkt = NULL; + struct reply_packet *p; + ldns_rr *query_rr = NULL; + uint8_t *outbuf = NULL; + size_t answer_size = 0; + struct entry* entry = NULL; + ldns_rdf *stop_command = ldns_dname_new_frm_str("server.stop."); + + status = ldns_wire2pkt(&query_pkt, inbuf, (size_t)inlen); + if (status != LDNS_STATUS_OK) { + verbose(1, "Got bad packet: %s\n", ldns_get_errorstr_by_id(status)); + ldns_rdf_free(stop_command); + return; + } + + query_rr = ldns_rr_list_rr(ldns_pkt_question(query_pkt), 0); + verbose(1, "query %d: id %d: %s %d bytes: ", ++(*count), (int)ldns_pkt_id(query_pkt), + (transport==transport_tcp)?"TCP":"UDP", (int)inlen); + if(verbose_out) ldns_rr_print(verbose_out, query_rr); + if(verbose_out) ldns_pkt_print(verbose_out, query_pkt); + + if (ldns_rr_get_type(query_rr) == LDNS_RR_TYPE_TXT && + ldns_rr_get_class(query_rr) == LDNS_RR_CLASS_CH && + ldns_dname_compare(ldns_rr_owner(query_rr), stop_command) == 0) { + exit(0); + } + + /* fill up answer packet */ + entry = find_match(entries, query_pkt, transport); + if(!entry || !entry->reply_list) { + verbose(1, "no answer packet for this query, no reply.\n"); + ldns_pkt_free(query_pkt); + ldns_rdf_free(stop_command); + return; + } + for(p = entry->reply_list; p; p = p->next) + { + verbose(3, "Answer pkt:\n"); + if (p->reply_from_hex) { + /* try to parse the hex packet, if it can be + * parsed, we can use adjust rules. if not, + * send packet literally */ + status = ldns_buffer2pkt_wire(&answer_pkt, p->reply_from_hex); + if (status == LDNS_STATUS_OK) { + adjust_packet(entry, answer_pkt, query_pkt); + if(verbose_out) ldns_pkt_print(verbose_out, answer_pkt); + status = ldns_pkt2wire(&outbuf, answer_pkt, &answer_size); + verbose(2, "Answer packet size: %u bytes.\n", (unsigned int)answer_size); + if (status != LDNS_STATUS_OK) { + verbose(1, "Error creating answer: %s\n", ldns_get_errorstr_by_id(status)); + ldns_pkt_free(query_pkt); + ldns_rdf_free(stop_command); + return; + } + ldns_pkt_free(answer_pkt); + answer_pkt = NULL; + } else { + verbose(3, "Could not parse hex data (%s), sending hex data directly.\n", ldns_get_errorstr_by_id(status)); + /* still try to adjust ID */ + answer_size = ldns_buffer_capacity(p->reply_from_hex); + outbuf = LDNS_XMALLOC(uint8_t, answer_size); + memcpy(outbuf, ldns_buffer_export(p->reply_from_hex), answer_size); + if(entry->copy_id) { + ldns_write_uint16(outbuf, + ldns_pkt_id(query_pkt)); + } + } + } else { + answer_pkt = ldns_pkt_clone(p->reply); + adjust_packet(entry, answer_pkt, query_pkt); + if(verbose_out) ldns_pkt_print(verbose_out, answer_pkt); + status = ldns_pkt2wire(&outbuf, answer_pkt, &answer_size); + verbose(1, "Answer packet size: %u bytes.\n", (unsigned int)answer_size); + if (status != LDNS_STATUS_OK) { + verbose(1, "Error creating answer: %s\n", ldns_get_errorstr_by_id(status)); + ldns_pkt_free(query_pkt); + ldns_rdf_free(stop_command); + return; + } + ldns_pkt_free(answer_pkt); + answer_pkt = NULL; + } + if(p->packet_sleep) { + verbose(3, "sleeping for next packet %d secs\n", + p->packet_sleep); +#ifdef HAVE_SLEEP + sleep(p->packet_sleep); +#else + Sleep(p->packet_sleep * 1000); +#endif + verbose(3, "wakeup for next packet " + "(slept %d secs)\n", p->packet_sleep); + } + sendfunc(outbuf, answer_size, userdata); + LDNS_FREE(outbuf); + outbuf = NULL; + answer_size = 0; + } + ldns_pkt_free(query_pkt); + ldns_rdf_free(stop_command); +} + +/** delete the list of reply packets */ +void delete_replylist(struct reply_packet* replist) +{ + struct reply_packet *p=replist, *np; + while(p) { + np = p->next; + ldns_pkt_free(p->reply); + ldns_buffer_free(p->reply_from_hex); + free(p); + p=np; + } +} + +void delete_entry(struct entry* list) +{ + struct entry *p=list, *np; + while(p) { + np = p->next; + delete_replylist(p->reply_list); + free(p); + p = np; + } +} diff --git a/testcode/ldns-testpkts.h b/testcode/ldns-testpkts.h new file mode 100644 index 00000000000..59e42895275 --- /dev/null +++ b/testcode/ldns-testpkts.h @@ -0,0 +1,255 @@ +/* + * ldns-testpkts. Data file parse for test packets, and query matching. + * + * Data storage for specially crafted replies for testing purposes. + * + * (c) NLnet Labs, 2005, 2006, 2007 + * See the file LICENSE for the license + */ + +#ifndef LDNS_TESTPKTS_H +#define LDNS_TESTPKTS_H + +/** + * \file + * + * This is a debugging aid. It is not efficient, especially + * with a long config file, but it can give any reply to any query. + * This can help the developer pre-script replies for queries. + * + * You can specify a packet RR by RR with header flags to return. + * + * Missing features: + * - matching content different from reply content. + * - find way to adjust mangled packets? + * + */ + + /* + The data file format is as follows: + + ; comment. + ; a number of entries, these are processed first to last. + ; a line based format. + + $ORIGIN origin + $TTL default_ttl + + ENTRY_BEGIN + ; first give MATCH lines, that say what queries are matched + ; by this entry. + ; 'opcode' makes the query match the opcode from the reply + ; if you leave it out, any opcode matches this entry. + ; 'qtype' makes the query match the qtype from the reply + ; 'qname' makes the query match the qname from the reply + ; 'subdomain' makes the query match subdomains of qname from the reply + ; 'serial=1023' makes the query match if ixfr serial is 1023. + ; 'all' has to match header byte for byte and all rrs in packet. + ; 'ttl' used with all, rrs in packet must also have matching TTLs. + ; 'DO' will match only queries with DO bit set. + ; 'noedns' matches queries without EDNS OPT records. + MATCH [opcode] [qtype] [qname] [serial=] [all] [ttl] + MATCH [UDP|TCP] DO + MATCH ... + ; Then the REPLY header is specified. + REPLY opcode, rcode or flags. + (opcode) QUERY IQUERY STATUS NOTIFY UPDATE + (rcode) NOERROR FORMERR SERVFAIL NXDOMAIN NOTIMPL YXDOMAIN + YXRRSET NXRRSET NOTAUTH NOTZONE + (flags) QR AA TC RD CD RA AD DO + REPLY ... + ; any additional actions to do. + ; 'copy_id' copies the ID from the query to the answer. + ADJUST copy_id + ; 'copy_query' copies the query name, type and class to the answer. + ADJUST copy_query + ; 'sleep=10' sleeps for 10 seconds before giving the answer (TCP is open) + ADJUST [sleep=] ; sleep before giving any reply + ADJUST [packet_sleep=] ; sleep before this packet in sequence + SECTION QUESTION + ; the RRcount is determined automatically. + SECTION ANSWER + + SECTION AUTHORITY + + SECTION ADDITIONAL + + EXTRA_PACKET ; follow with SECTION, REPLY for more packets. + HEX_ANSWER_BEGIN ; follow with hex data + ; this replaces any answer packet constructed + ; with the SECTION keywords (only SECTION QUERY + ; is used to match queries). If the data cannot + ; be parsed, ADJUST rules for the answer packet + ; are ignored. Only copy_id is done. + HEX_ANSWER_END + ENTRY_END + + + Example data file: +$ORIGIN nlnetlabs.nl +$TTL 3600 + +ENTRY_BEGIN +MATCH qname +REPLY NOERROR +ADJUST copy_id +SECTION QUESTION +www.nlnetlabs.nl. IN A +SECTION ANSWER +www.nlnetlabs.nl. IN A 195.169.215.155 +SECTION AUTHORITY +nlnetlabs.nl. IN NS www.nlnetlabs.nl. +ENTRY_END + +ENTRY_BEGIN +MATCH qname +REPLY NOERROR +ADJUST copy_id +SECTION QUESTION +www2.nlnetlabs.nl. IN A +HEX_ANSWER_BEGIN +; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 +;-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + 00 bf 81 80 00 01 00 01 00 02 00 02 03 77 77 77 0b 6b 61 6e ; 1- 20 + 61 72 69 65 70 69 65 74 03 63 6f 6d 00 00 01 00 01 03 77 77 ; 21- 40 + 77 0b 6b 61 6e 61 72 69 65 70 69 65 74 03 63 6f 6d 00 00 01 ; 41- 60 + 00 01 00 01 50 8b 00 04 52 5e ed 32 0b 6b 61 6e 61 72 69 65 ; 61- 80 + 70 69 65 74 03 63 6f 6d 00 00 02 00 01 00 01 50 8b 00 11 03 ; 81- 100 + 6e 73 31 08 68 65 78 6f 6e 2d 69 73 02 6e 6c 00 0b 6b 61 6e ; 101- 120 + 61 72 69 65 70 69 65 74 03 63 6f 6d 00 00 02 00 01 00 01 50 ; 121- 140 + 8b 00 11 03 6e 73 32 08 68 65 78 6f 6e 2d 69 73 02 6e 6c 00 ; 141- 160 + 03 6e 73 31 08 68 65 78 6f 6e 2d 69 73 02 6e 6c 00 00 01 00 ; 161- 180 + 01 00 00 46 53 00 04 52 5e ed 02 03 6e 73 32 08 68 65 78 6f ; 181- 200 + 6e 2d 69 73 02 6e 6c 00 00 01 00 01 00 00 46 53 00 04 d4 cc ; 201- 220 + db 5b +HEX_ANSWER_END +ENTRY_END + + + + note that this file will link with your + void verbose(int level, char* format, ...); output function. +*/ + +#include + +/** Type of transport, since some entries match based on UDP or TCP of query */ +enum transport_type {transport_any = 0, transport_udp, transport_tcp }; + +/** struct to keep a linked list of reply packets for a query */ +struct reply_packet { + /** next in list of reply packets, for TCP multiple pkts on wire */ + struct reply_packet* next; + /** the reply pkt */ + ldns_pkt* reply; + /** or reply pkt in hex if not parsable */ + ldns_buffer* reply_from_hex; + /** seconds to sleep before giving packet */ + unsigned int packet_sleep; +}; + +/** data structure to keep the canned queries in. + format is the 'matching query' and the 'canned answer' */ +struct entry { + /* match */ + /* How to match an incoming query with this canned reply */ + /** match query opcode with answer opcode */ + bool match_opcode; + /** match qtype with answer qtype */ + bool match_qtype; + /** match qname with answer qname */ + bool match_qname; + /** match qname as subdomain of answer qname */ + bool match_subdomain; + /** match SOA serial number, from auth section */ + bool match_serial; + /** match all of the packet */ + bool match_all; + /** match ttls in the packet */ + bool match_ttl; + /** match DO bit */ + bool match_do; + /** match absence of EDNS OPT record in query */ + bool match_noedns; + /** match query serial with this value. */ + uint32_t ixfr_soa_serial; + /** match on UDP/TCP */ + enum transport_type match_transport; + + /** pre canned reply */ + struct reply_packet *reply_list; + + /** how to adjust the reply packet */ + /** copy over the ID from the query into the answer */ + bool copy_id; + /** copy the query nametypeclass from query into the answer */ + bool copy_query; + /** in seconds */ + unsigned int sleeptime; + + /** some number that names this entry, line number in file or so */ + int lineno; + + /** next in list */ + struct entry* next; +}; + +/** + * reads the canned reply file and returns a list of structs + * does an exit on error. + */ +struct entry* read_datafile(const char* name); + +/** + * Delete linked list of entries. + */ +void delete_entry(struct entry* list); + +/** + * Read one entry from the data file. + * @param in: file to read from. Filepos must be at the start of a new line. + * @param name: name of the file for prettier errors. + * @param lineno: line number in file, incremented as lines are read. + * for prettier errors. + * @param default_ttl: on first call set to default TTL for entries, + * later it stores the $TTL value last seen. Try 3600 first call. + * @param origin: domain name for origin appending. Can be &NULL on first call. + * later it stores the $ORIGIN value last seen. Often &NULL or the zone + * name on first call. + * @param prev_rr: previous rr name for correcter parsing. &NULL on first call. + * @return: The entry read (malloced) or NULL if no entry could be read. + */ +struct entry* read_entry(FILE* in, const char* name, int *lineno, + uint32_t* default_ttl, ldns_rdf** origin, ldns_rdf** prev_rr); + +/** + * finds entry in list, or returns NULL. + */ +struct entry* find_match(struct entry* entries, ldns_pkt* query_pkt, + enum transport_type transport); + +/** + * copy & adjust packet + */ +void adjust_packet(struct entry* match, ldns_pkt* answer_pkt, + ldns_pkt* query_pkt); + +/** + * Parses data buffer to a query, finds the correct answer + * and calls the given function for every packet to send. + * if verbose_out filename is given, packets are dumped there. + * @param inbuf: the packet that came in + * @param inlen: length of packet. + * @param entries: entries read in from datafile. + * @param count: is increased to count number of queries answered. + * @param transport: set to UDP or TCP to match some types of entries. + * @param sendfunc: called to send answer (buffer, size, userarg). + * @param userdata: userarg to give to sendfunc. + * @param verbose_out: if not NULL, verbose messages are printed there. + */ +void handle_query(uint8_t* inbuf, ssize_t inlen, struct entry* entries, + int* count, enum transport_type transport, + void (*sendfunc)(uint8_t*, size_t, void*), void* userdata, + FILE* verbose_out); + +#endif /* LDNS_TESTPKTS_H */ diff --git a/testcode/lock_verify.c b/testcode/lock_verify.c new file mode 100644 index 00000000000..9f51c3385a6 --- /dev/null +++ b/testcode/lock_verify.c @@ -0,0 +1,418 @@ +/* + * testcode/lock_verify.c - verifier program for lock traces, checks order. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file checks the lock traces generated by checklock.c. + * Checks if locks are consistently locked in the same order. + * If not, this can lead to deadlock if threads execute the different + * ordering at the same time. + * + */ + +#include "config.h" +#include "util/log.h" +#include "util/rbtree.h" +#include "util/locks.h" +#include "util/fptr_wlist.h" + +/* --- data structures --- */ +struct lock_ref; + +/** keep track of lock id in lock-verify application + * Also defined in smallapp/worker_cb.c for fptr_wlist encapsulation + * breakage (the security tests break encapsulation for this test app) */ +struct order_id { + /** the thread id that created it */ + int thr; + /** the instance number of creation */ + int instance; +}; + +/** a lock */ +struct order_lock { + /** rbnode in all tree */ + rbnode_t node; + /** lock id */ + struct order_id id; + /** the creation file */ + char* create_file; + /** creation line */ + int create_line; + /** set of all locks that are smaller than this one (locked earlier) */ + rbtree_t* smaller; + /** during depthfirstsearch, this is a linked list of the stack + * of locks. points to the next lock bigger than this one. */ + struct lock_ref* dfs_next; + /** if lock has been visited (all smaller locks have been compared to + * this lock), only need to compare this with all unvisited(bigger) + * locks */ + int visited; +}; + +/** reference to a lock in a rbtree set */ +struct lock_ref { + /** rbnode, key is an order_id ptr */ + rbnode_t node; + /** the lock referenced */ + struct order_lock* lock; + /** why is this ref */ + char* file; + /** line number */ + int line; +}; + +/** count of errors detected */ +static int errors_detected = 0; +/** verbose? */ +static int verb = 0; + +/** print program usage help */ +static void +usage() +{ + printf("lock_verify \n"); +} + +/** read header entry. + * @param in: file to read header of. + * @return: False if it does not belong to the rest. */ +static int +read_header(FILE* in) +{ + time_t t; + pid_t p; + int thrno; + static int have_values = 0; + static time_t the_time; + static pid_t the_pid; + static int threads[256]; + + if(fread(&t, sizeof(t), 1, in) != 1 || + fread(&thrno, sizeof(thrno), 1, in) != 1 || + fread(&p, sizeof(p), 1, in) != 1) { + fatal_exit("fread failed"); + } + /* check these values are sorta OK */ + if(!have_values) { + the_time = t; + the_pid = p; + memset(threads, 0, 256*sizeof(int)); + if(thrno >= 256) { + fatal_exit("Thread number too big. %d", thrno); + } + threads[thrno] = 1; + have_values = 1; + printf(" trace %d from pid %u on %s", thrno, + (unsigned)p, ctime(&t)); + } else { + if(the_pid != p) { + printf(" has pid %u, not %u. Skipped.\n", + (unsigned)p, (unsigned)the_pid); + return 0; + } + if(threads[thrno]) + fatal_exit("same threadno in two files"); + threads[thrno] = 1; + if( abs((int)(the_time - t)) > 3600) + fatal_exit("input files from different times: %u %u", + (unsigned)the_time, (unsigned)t); + printf(" trace of thread %u:%d\n", (unsigned)p, thrno); + } + return 1; +} + +/** max length of strings: filenames and function names. */ +#define STRMAX 1024 +/** read a string from file, false on error */ +static int readup_str(char** str, FILE* in) +{ + char buf[STRMAX]; + int len = 0; + int c; + /* ends in zero */ + while( (c = fgetc(in)) != 0) { + if(c == EOF) + fatal_exit("eof in readstr, file too short"); + buf[len++] = c; + if(len == STRMAX) { + fatal_exit("string too long, bad file format"); + } + } + buf[len] = 0; + *str = strdup(buf); + return 1; +} + +/** read creation entry */ +static void read_create(rbtree_t* all, FILE* in) +{ + struct order_lock* o = calloc(1, sizeof(struct order_lock)); + if(!o) fatal_exit("malloc failure"); + if(fread(&o->id.thr, sizeof(int), 1, in) != 1 || + fread(&o->id.instance, sizeof(int), 1, in) != 1 || + !readup_str(&o->create_file, in) || + fread(&o->create_line, sizeof(int), 1, in) != 1) + fatal_exit("fread failed"); + o->smaller = rbtree_create(order_lock_cmp); + o->node.key = &o->id; + if(!rbtree_insert(all, &o->node)) { + /* already inserted */ + struct order_lock* a = (struct order_lock*)rbtree_search(all, + &o->id); + log_assert(a); + a->create_file = o->create_file; + a->create_line = o->create_line; + free(o->smaller); + free(o); + o = a; + } + if(verb) printf("read create %u %u %s %d\n", + (unsigned)o->id.thr, (unsigned)o->id.instance, + o->create_file, o->create_line); +} + +/** insert lock entry (empty) into list */ +static struct order_lock* +insert_lock(rbtree_t* all, struct order_id* id) +{ + struct order_lock* o = calloc(1, sizeof(struct order_lock)); + if(!o) fatal_exit("malloc failure"); + o->smaller = rbtree_create(order_lock_cmp); + o->id = *id; + o->node.key = &o->id; + if(!rbtree_insert(all, &o->node)) + fatal_exit("insert fail should not happen"); + return o; +} + +/** read lock entry */ +static void read_lock(rbtree_t* all, FILE* in, int val) +{ + struct order_id prev_id, now_id; + struct lock_ref* ref; + struct order_lock* prev, *now; + ref = (struct lock_ref*)calloc(1, sizeof(struct lock_ref)); + if(!ref) fatal_exit("malloc failure"); + prev_id.thr = val; + if(fread(&prev_id.instance, sizeof(int), 1, in) != 1 || + fread(&now_id.thr, sizeof(int), 1, in) != 1 || + fread(&now_id.instance, sizeof(int), 1, in) != 1 || + !readup_str(&ref->file, in) || + fread(&ref->line, sizeof(int), 1, in) != 1) + fatal_exit("fread failed"); + if(verb) printf("read lock %u %u %u %u %s %d\n", + (unsigned)prev_id.thr, (unsigned)prev_id.instance, + (unsigned)now_id.thr, (unsigned)now_id.instance, + ref->file, ref->line); + /* find the two locks involved */ + prev = (struct order_lock*)rbtree_search(all, &prev_id); + now = (struct order_lock*)rbtree_search(all, &now_id); + /* if not there - insert 'em */ + if(!prev) prev = insert_lock(all, &prev_id); + if(!now) now = insert_lock(all, &now_id); + ref->lock = prev; + ref->node.key = &prev->id; + if(!rbtree_insert(now->smaller, &ref->node)) { + free(ref->file); + free(ref); + } +} + +/** read input file */ +static void readinput(rbtree_t* all, char* file) +{ + FILE *in = fopen(file, "r"); + int fst; + if(!in) { + perror(file); + exit(1); + } + printf("file %s", file); + if(!read_header(in)) { + fclose(in); + return; + } + while(fread(&fst, sizeof(fst), 1, in) == 1) { + if(fst == -1) + read_create(all, in); + else read_lock(all, in, fst); + } + fclose(in); +} + +/** print cycle message */ +static void found_cycle(struct lock_ref* visit, int level) +{ + struct lock_ref* p; + int i = 0; + errors_detected++; + printf("Found inconsistent locking order of length %d\n", level); + printf("for lock %d %d created %s %d\n", + visit->lock->id.thr, visit->lock->id.instance, + visit->lock->create_file, visit->lock->create_line); + printf("sequence is:\n"); + p = visit; + while(p) { + struct order_lock* next = + p->lock->dfs_next?p->lock->dfs_next->lock:visit->lock; + printf("[%d] is locked at line %s %d before lock %d %d\n", + i, p->file, p->line, next->id.thr, next->id.instance); + printf("[%d] lock %d %d is created at %s %d\n", + i, next->id.thr, next->id.instance, + next->create_file, next->create_line); + i++; + p = p->lock->dfs_next; + if(p && p->lock == visit->lock) + break; + } +} + +/** Detect cycle by comparing visited now with all (unvisited) bigger nodes */ +static int detect_cycle(struct lock_ref* visit, struct lock_ref* from) +{ + struct lock_ref* p = from; + while(p) { + if(p->lock == visit->lock) + return 1; + p = p->lock->dfs_next; + } + return 0; +} + +/** recursive function to depth first search for cycles. + * @param visit: the lock visited at this step. + * its dfs_next pointer gives the visited lock up in recursion. + * same as lookfor at level 0. + * @param level: depth of recursion. 0 is start. + * @param from: search for matches from unvisited node upwards. + */ +static void search_cycle(struct lock_ref* visit, int level, + struct lock_ref* from) +{ + struct lock_ref* ref; + /* check for cycle */ + if(detect_cycle(visit, from) && level != 0) { + found_cycle(visit, level); + fatal_exit("found lock order cycle"); + } + /* recurse */ + if(!visit->lock->visited) + from = visit; + if(verb > 1) fprintf(stderr, "[%d] visit lock %u %u %s %d\n", level, + (unsigned)visit->lock->id.thr, + (unsigned)visit->lock->id.instance, + visit->lock->create_file, visit->lock->create_line); + RBTREE_FOR(ref, struct lock_ref*, visit->lock->smaller) { + ref->lock->dfs_next = visit; + search_cycle(ref, level+1, from); + } + visit->lock->visited = 1; +} + +/** Check ordering of one lock */ +static void check_order_lock(struct order_lock* lock) +{ + struct lock_ref start; + if(lock->visited) return; + + start.node.key = &lock->id; + start.lock = lock; + start.file = lock->create_file; + start.line = lock->create_line; + + if(!lock->create_file) + log_err("lock %u %u does not have create info", + (unsigned)lock->id.thr, (unsigned)lock->id.instance); + + /* depth first search to find cycle with this lock at head */ + lock->dfs_next = NULL; + search_cycle(&start, 0, &start); +} + +/** Check ordering of locks */ +static void check_order(rbtree_t* all_locks) +{ + /* check each lock */ + struct order_lock* lock; + int i=0; + RBTREE_FOR(lock, struct order_lock*, all_locks) { + if(verb) + printf("[%d/%d] Checking lock %d %d %s %d\n", + i, (int)all_locks->count, + lock->id.thr, lock->id.instance, + lock->create_file, lock->create_line); + else if (i % ((all_locks->count/75)<1?1:all_locks->count/75) + == 0) + fprintf(stderr, "."); + i++; + check_order_lock(lock); + } + fprintf(stderr, "\n"); +} + +/** main program to verify all traces passed */ +int +main(int argc, char* argv[]) +{ + rbtree_t* all_locks; + int i; + time_t starttime = time(NULL); + if(argc <= 1) { + usage(); + return 1; + } + log_init(NULL, 0, NULL); + log_ident_set("lock-verify"); + /* init */ + all_locks = rbtree_create(order_lock_cmp); + errors_detected = 0; + + /* read the input files */ + for(i=1; icount, (int)(time(NULL)-starttime), + errors_detected); + if(errors_detected) return 1; + return 0; +} diff --git a/testcode/memstats.c b/testcode/memstats.c new file mode 100644 index 00000000000..8cbd9f546e0 --- /dev/null +++ b/testcode/memstats.c @@ -0,0 +1,248 @@ +/* + * testcode/memstats.c - debug tool to show memory allocation statistics. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This program reads a log file and prints the memory allocation summed + * up. + */ +#include "config.h" +#include "util/log.h" +#include "util/rbtree.h" +#include "util/locks.h" +#include "util/fptr_wlist.h" +#include + +/** + * The allocation statistics block + */ +struct codeline { + /** rbtree node */ + rbnode_t node; + /** the name of the file:linenumber */ + char* codeline; + /** the name of the function */ + char* func; + /** number of bytes allocated */ + uint64_t alloc; + /** number of bytes freed */ + uint64_t free; + /** number allocations and frees */ + uint64_t calls; +}; + +/** print usage and exit */ +static void +usage() +{ + printf("usage: memstats \n"); + printf("statistics are printed on stdout.\n"); + exit(1); +} + +/** match logfile line to see if it needs accounting processing */ +static int +match(char* line) +{ + /* f.e.: + * [1187340064] unbound[24604:0] info: ul/rb.c:81 r_create malloc(12) + * 0123456789 123456789 123456789 123456789 + * But now also: + * Sep 16 15:18:20 unbound[1:0] info: ul/nh.c:143 memdup malloc(11) + */ + if(strlen(line) < 32) /* up to 'info: ' */ + return 0; + if(!strstr(line, " info: ")) + return 0; + if(strstr(line, "info: stat ")) + return 0; /* skip the hex dumps */ + if(strstr(line+30, "malloc(")) + return 1; + else if(strstr(line+30, "calloc(")) + return 1; + /* skip reallocs */ + return 0; +} + +/** find or alloc codeline in tree */ +static struct codeline* +get_codeline(rbtree_t* tree, char* key, char* func) +{ + struct codeline* cl = (struct codeline*)rbtree_search(tree, key); + if(!cl) { + cl = calloc(1, sizeof(*cl)); + if(!cl) return 0; + cl->codeline = strdup(key); + if(!cl->codeline) return 0; + cl->func = strdup(func); + if(!cl->func) return 0; + cl->alloc = 0; + cl->node.key = cl->codeline; + (void)rbtree_insert(tree, &cl->node); + } + return cl; +} + +/** read up the malloc stats */ +static void +read_malloc_stat(char* line, rbtree_t* tree) +{ + char codeline[10240]; + char name[10240]; + int skip = 0; + long num = 0; + struct codeline* cl = 0; + line = strstr(line, "info: ")+6; + if(sscanf(line, "%s %s %n", codeline, name, &skip) != 2) { + printf("%s\n", line); + fatal_exit("unhandled malloc"); + } + if(sscanf(line+skip+7, "%ld", &num) != 1) { + printf("%s\n%s\n", line, line+skip+7); + fatal_exit("unhandled malloc"); + } + cl = get_codeline(tree, codeline, name); + if(!cl) + fatal_exit("alloc failure"); + cl->alloc += num; + cl->calls ++; +} + +/** read up the calloc stats */ +static void +read_calloc_stat(char* line, rbtree_t* tree) +{ + char codeline[10240]; + char name[10240]; + int skip = 0; + long num = 0, sz = 0; + struct codeline* cl = 0; + line = strstr(line, "info: ")+6; + if(sscanf(line, "%s %s %n", codeline, name, &skip) != 2) { + printf("%s\n", line); + fatal_exit("unhandled calloc"); + } + if(sscanf(line+skip+7, "%ld, %ld", &num, &sz) != 2) { + printf("%s\n%s\n", line, line+skip+7); + fatal_exit("unhandled calloc"); + } + + cl = get_codeline(tree, codeline, name); + if(!cl) + fatal_exit("alloc failure"); + cl->alloc += num*sz; + cl->calls ++; +} + +/** get size of file */ +static off_t +get_file_size(const char* fname) +{ + struct stat s; + if(stat(fname, &s) < 0) { + fatal_exit("could not stat %s: %s", fname, strerror(errno)); + } + return s.st_size; +} + +/** read the logfile */ +static void +readfile(rbtree_t* tree, const char* fname) +{ + off_t total = get_file_size(fname); + off_t done = (off_t)0; + int report = 0; + FILE* in = fopen(fname, "r"); + char buf[102400]; + if(!in) + fatal_exit("could not open %s: %s", fname, strerror(errno)); + printf("Reading %s of size %lld\n", fname, (long long)total); + while(fgets(buf, 102400, in)) { + buf[102400-1] = 0; + done += (off_t)strlen(buf); + /* progress count */ + if((int)(((double)done / (double)total)*100.) > report) { + report = (int)(((double)done / (double)total)*100.); + fprintf(stderr, " %d%%", report); + } + + if(!match(buf)) + continue; + else if(strstr(buf+30, "malloc(")) + read_malloc_stat(buf, tree); + else if(strstr(buf+30, "calloc(")) + read_calloc_stat(buf, tree); + else { + printf("%s\n", buf); + fatal_exit("unhandled input"); + } + } + fprintf(stderr, " done\n"); + fclose(in); +} + +/** print memory stats */ +static void +printstats(rbtree_t* tree) +{ + struct codeline* cl; + uint64_t total = 0, tcalls = 0; + RBTREE_FOR(cl, struct codeline*, tree) { + printf("%12lld / %8lld in %s %s\n", (long long)cl->alloc, + (long long)cl->calls, cl->codeline, cl->func); + total += cl->alloc; + tcalls += cl->calls; + } + printf("------------\n"); + printf("%12lld / %8lld total in %ld code lines\n", (long long)total, + (long long)tcalls, (long)tree->count); + printf("\n"); +} + +/** main program */ +int main(int argc, const char* argv[]) +{ + rbtree_t* tree = 0; + if(argc != 2) { + usage(); + } + tree = rbtree_create(codeline_cmp); + if(!tree) + fatal_exit("alloc failure"); + readfile(tree, argv[1]); + printstats(tree); + return 0; +} diff --git a/testcode/mini_tpkg.sh b/testcode/mini_tpkg.sh new file mode 100755 index 00000000000..ebf27a7d48a --- /dev/null +++ b/testcode/mini_tpkg.sh @@ -0,0 +1,128 @@ +# tpkg that only exes the files. +args="../.." +if test "$1" = "-a"; then + args=$2 + shift + shift +fi + +if test "$1" = "clean"; then + echo "rm -f result.* .done* .tpkg.var.master .tpkg.var.test" + rm -f result.* .done* .tpkg.var.master .tpkg.var.test + exit 0 +fi +if test "$1" = "fake"; then + echo "minitpkg fake $2" + echo "fake" > .done-`basename $2 .tpkg` + exit 0 +fi +if test "$1" = "report" || test "$2" = "report"; then + echo "Minitpkg Report" + for result in *.tpkg; do + name=`basename $result .tpkg` + if test -f ".done-$name"; then + if test "$1" != "-q"; then + echo "** PASSED ** : $name" + fi + else + if test -f "result.$name"; then + echo "!! FAILED !! : $name" + else + echo ">> SKIPPED<< : $name" + fi + fi + done + exit 0 +fi + +if test "$1" != 'exe'; then + # usage + echo "mini tpkg. Reduced functionality for old shells." + echo " tpkg exe " + echo " tpkg fake " + echo " tpkg clean" + echo " tpkg [-q] report" + exit 1 +fi +shift + +# do not execute if the disk is too full +#DISKLIMIT=100000 +# This check is not portable (to Solaris 10). +#avail=`df . | tail -1 | awk '{print $4}'` +#if test "$avail" -lt "$DISKLIMIT"; then + #echo "minitpkg: The disk is too full! Only $avail." + #exit 1 +#fi + +name=`basename $1 .tpkg` +dir=$name.$$ +result=result.$name +done=.done-$name +success="no" +if test -x "`which bash`"; then + shell="bash" +else + shell="sh" +fi + +# check already done +if test -f .done-$name; then + echo "minitpkg .done-$name exists. skip test." + exit 0 +fi + +# Extract +echo "minitpkg extract $1 to $dir" +mkdir $dir +gzip -cd $name.tpkg | (cd $dir; tar xf -) +cd $dir +mv $name.dir/* . + +# EXE +echo "minitpkg exe $name" > $result +grep "Description:" $name.dsc >> $result 2>&1 +echo "DateRunStart: "`date "+%s" 2>/dev/null` >> $result +if test -f $name.pre; then + echo "minitpkg exe $name.pre" + echo "minitpkg exe $name.pre" >> $result + $shell $name.pre $args >> $result + if test $? -ne 0; then + echo "Warning: $name.pre did not exit successfully" + fi +fi +if test -f $name.test; then + echo "minitpkg exe $name.test" + echo "minitpkg exe $name.test" >> $result + $shell $name.test $args >>$result 2>&1 + if test $? -ne 0; then + echo "$name: FAILED" >> $result + echo "$name: FAILED" + success="no" + else + echo "$name: PASSED" >> $result + echo "$name: PASSED" > ../.done-$name + echo "$name: PASSED" + success="yes" + fi +fi +if test -f $name.post; then + echo "minitpkg exe $name.post" + echo "minitpkg exe $name.post" >> $result + $shell $name.post $args >> $result + if test $? -ne 0; then + echo "Warning: $name.post did not exit successfully" + fi +fi +echo "DateRunEnd: "`date "+%s" 2>/dev/null` >> $result + +mv $result .. +cd .. +rm -rf $dir +# compat for windows where deletion may not succeed initially (files locked +# by processes that still have to exit). +if test $? -eq 1; then + echo "minitpkg waiting for processes to terminate" + sleep 2 # some time to exit, and try again + rm -rf $dir +fi diff --git a/testcode/perf.c b/testcode/perf.c new file mode 100644 index 00000000000..cc892efa99f --- /dev/null +++ b/testcode/perf.c @@ -0,0 +1,654 @@ +/* + * testcode/perf.c - debug program to estimate name server performance. + * + * Copyright (c) 2008, 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This program estimates DNS name server performance. + */ + +#include "config.h" +#ifdef HAVE_GETOPT_H +#include +#endif +#include +#include +#include "util/log.h" +#include "util/locks.h" +#include "util/net_help.h" +#include "util/data/msgencode.h" +#include "util/data/msgreply.h" +#include "util/data/msgparse.h" + +/** usage information for perf */ +static void usage(char* nm) +{ + printf("usage: %s [options] server\n", nm); + printf("server: ip address of server, IP4 or IP6.\n"); + printf(" If not on port %d add @port.\n", UNBOUND_DNS_PORT); + printf("-d sec duration of test in whole seconds (0: wait for ^C)\n"); + printf("-a str query to ask, interpreted as a line from qfile\n"); + printf("-f fnm query list to read from file\n"); + printf(" every line has format: qname qclass qtype [+-]{E}\n"); + printf(" where + means RD set, E means EDNS enabled\n"); + printf("-q quiet mode, print only final qps\n"); + exit(1); +} + +struct perfinfo; +struct perfio; + +/** Global info for perf */ +struct perfinfo { + /** need to exit */ + volatile int exit; + /** all purpose buffer (for UDP send and receive) */ + ldns_buffer* buf; + + /** destination */ + struct sockaddr_storage dest; + /** length of dest socket addr */ + socklen_t destlen; + + /** when did this time slice start */ + struct timeval since; + /** number of queries received in that time */ + size_t numrecv; + /** number of queries sent out in that time */ + size_t numsent; + + /** duration of test in seconds */ + int duration; + /** quiet mode? */ + int quiet; + + /** when did the total test start */ + struct timeval start; + /** total number recvd */ + size_t total_recv; + /** total number sent */ + size_t total_sent; + /** numbers by rcode */ + size_t by_rcode[32]; + + /** number of I/O ports */ + size_t io_num; + /** I/O ports array */ + struct perfio* io; + /** max fd value in io ports */ + int maxfd; + /** readset */ + fd_set rset; + + /** size of querylist */ + size_t qlist_size; + /** allocated size of qlist array */ + size_t qlist_capacity; + /** list of query packets (data) */ + uint8_t** qlist_data; + /** list of query packets (length of a packet) */ + size_t* qlist_len; + /** index into querylist, for walking the list */ + size_t qlist_idx; +}; + +/** I/O port for perf */ +struct perfio { + /** id number */ + size_t id; + /** file descriptor of socket */ + int fd; + /** timeout value */ + struct timeval timeout; + /** ptr back to perfinfo */ + struct perfinfo* info; +}; + +/** number of msec between starting io ports */ +#define START_IO_INTERVAL 10 +/** number of msec timeout on io ports */ +#define IO_TIMEOUT 10 + +/** signal handler global info */ +static struct perfinfo* sig_info; + +/** signal handler for user quit */ +static RETSIGTYPE perf_sigh(int sig) +{ + log_assert(sig_info); + if(!sig_info->quiet) + printf("exit on signal %d\n", sig); + sig_info->exit = 1; +} + +/** timeval compare, t1 < t2 */ +static int +perf_tv_smaller(struct timeval* t1, struct timeval* t2) +{ +#ifndef S_SPLINT_S + if(t1->tv_sec < t2->tv_sec) + return 1; + if(t1->tv_sec == t2->tv_sec && + t1->tv_usec < t2->tv_usec) + return 1; +#endif + return 0; +} + +/** timeval add, t1 += t2 */ +static void +perf_tv_add(struct timeval* t1, struct timeval* t2) +{ +#ifndef S_SPLINT_S + t1->tv_sec += t2->tv_sec; + t1->tv_usec += t2->tv_usec; + while(t1->tv_usec > 1000000) { + t1->tv_usec -= 1000000; + t1->tv_sec++; + } +#endif +} + +/** timeval subtract, t1 -= t2 */ +static void +perf_tv_subtract(struct timeval* t1, struct timeval* t2) +{ +#ifndef S_SPLINT_S + t1->tv_sec -= t2->tv_sec; + if(t1->tv_usec >= t2->tv_usec) { + t1->tv_usec -= t2->tv_usec; + } else { + t1->tv_sec--; + t1->tv_usec = 1000000-(t2->tv_usec-t1->tv_usec); + } +#endif +} + + +/** setup perf test environment */ +static void +perfsetup(struct perfinfo* info) +{ + size_t i; + if(gettimeofday(&info->start, NULL) < 0) + fatal_exit("gettimeofday: %s", strerror(errno)); + sig_info = info; + if( signal(SIGINT, perf_sigh) == SIG_ERR || +#ifdef SIGQUIT + signal(SIGQUIT, perf_sigh) == SIG_ERR || +#endif +#ifdef SIGHUP + signal(SIGHUP, perf_sigh) == SIG_ERR || +#endif +#ifdef SIGBREAK + signal(SIGBREAK, perf_sigh) == SIG_ERR || +#endif + signal(SIGTERM, perf_sigh) == SIG_ERR) + fatal_exit("could not bind to signal"); + info->io = (struct perfio*)calloc(sizeof(struct perfio), info->io_num); + if(!info->io) fatal_exit("out of memory"); +#ifndef S_SPLINT_S + FD_ZERO(&info->rset); +#endif + info->since = info->start; + for(i=0; iio_num; i++) { + info->io[i].id = i; + info->io[i].info = info; + info->io[i].fd = socket( + addr_is_ip6(&info->dest, info->destlen)? + AF_INET6:AF_INET, SOCK_DGRAM, 0); + if(info->io[i].fd == -1) { +#ifndef USE_WINSOCK + fatal_exit("socket: %s", strerror(errno)); +#else + fatal_exit("socket: %s", + wsa_strerror(WSAGetLastError())); +#endif + } + if(info->io[i].fd > info->maxfd) + info->maxfd = info->io[i].fd; +#ifndef S_SPLINT_S + FD_SET(FD_SET_T info->io[i].fd, &info->rset); + info->io[i].timeout.tv_usec = ((START_IO_INTERVAL*i)%1000) + *1000; + info->io[i].timeout.tv_sec = (START_IO_INTERVAL*i)/1000; + perf_tv_add(&info->io[i].timeout, &info->since); +#endif + } +} + +/** cleanup perf test environment */ +static void +perffree(struct perfinfo* info) +{ + size_t i; + if(!info) return; + if(info->io) { + for(i=0; iio_num; i++) { +#ifndef USE_WINSOCK + close(info->io[i].fd); +#else + closesocket(info->io[i].fd); +#endif + } + free(info->io); + } + for(i=0; iqlist_size; i++) + free(info->qlist_data[i]); + free(info->qlist_data); + free(info->qlist_len); +} + +/** send new query for io */ +static void +perfsend(struct perfinfo* info, size_t n, struct timeval* now) +{ + ssize_t r; + r = sendto(info->io[n].fd, (void*)info->qlist_data[info->qlist_idx], + info->qlist_len[info->qlist_idx], 0, + (struct sockaddr*)&info->dest, info->destlen); + /*log_hex("send", info->qlist_data[info->qlist_idx], + info->qlist_len[info->qlist_idx]);*/ + if(r == -1) { +#ifndef USE_WINSOCK + log_err("sendto: %s", strerror(errno)); +#else + log_err("sendto: %s", wsa_strerror(WSAGetLastError())); +#endif + } else if(r != (ssize_t)info->qlist_len[info->qlist_idx]) { + log_err("partial sendto"); + } + info->qlist_idx = (info->qlist_idx+1) % info->qlist_size; + info->numsent++; + + info->io[n].timeout.tv_sec = IO_TIMEOUT/1000; + info->io[n].timeout.tv_usec = (IO_TIMEOUT%1000)*1000; + perf_tv_add(&info->io[n].timeout, now); +} + +/** got reply for io */ +static void +perfreply(struct perfinfo* info, size_t n, struct timeval* now) +{ + ssize_t r; + r = recv(info->io[n].fd, (void*)ldns_buffer_begin(info->buf), + ldns_buffer_capacity(info->buf), 0); + if(r == -1) { +#ifndef USE_WINSOCK + log_err("recv: %s", strerror(errno)); +#else + log_err("recv: %s", wsa_strerror(WSAGetLastError())); +#endif + } else { + info->by_rcode[LDNS_RCODE_WIRE(ldns_buffer_begin( + info->buf))]++; + info->numrecv++; + } + /*ldns_buffer_set_limit(info->buf, r); + log_buf(0, "reply", info->buf);*/ + perfsend(info, n, now); +} + +/** got timeout for io */ +static void +perftimeout(struct perfinfo* info, size_t n, struct timeval* now) +{ + /* may not be a dropped packet, this is also used to start + * up the sending IOs */ + perfsend(info, n, now); +} + +/** print nice stats about qps */ +static void +stat_printout(struct perfinfo* info, struct timeval* now, + struct timeval* elapsed) +{ + /* calculate qps */ + double dt, qps = 0; +#ifndef S_SPLINT_S + dt = (double)(elapsed->tv_sec*1000000 + elapsed->tv_usec) / 1000000; +#endif + if(dt > 0.001) + qps = (double)(info->numrecv) / dt; + if(!info->quiet) + printf("qps: %g\n", qps); + /* setup next slice */ + info->since = *now; + info->total_sent += info->numsent; + info->total_recv += info->numrecv; + info->numrecv = 0; + info->numsent = 0; +} + +/** wait for new events for performance test */ +static void +perfselect(struct perfinfo* info) +{ + fd_set rset = info->rset; + struct timeval timeout, now; + int num; + size_t i; + if(gettimeofday(&now, NULL) < 0) + fatal_exit("gettimeofday: %s", strerror(errno)); + /* time to exit? */ + if(info->duration > 0) { + timeout = now; + perf_tv_subtract(&timeout, &info->start); + if((int)timeout.tv_sec >= info->duration) { + info->exit = 1; + return; + } + } + /* time for stats printout? */ + timeout = now; + perf_tv_subtract(&timeout, &info->since); + if(timeout.tv_sec > 0) { + stat_printout(info, &now, &timeout); + } + /* see what is closest port to timeout; or if there is a timeout */ + timeout = info->io[0].timeout; + for(i=0; iio_num; i++) { + if(perf_tv_smaller(&info->io[i].timeout, &now)) { + perftimeout(info, i, &now); + return; + } + if(perf_tv_smaller(&info->io[i].timeout, &timeout)) { + timeout = info->io[i].timeout; + } + } + perf_tv_subtract(&timeout, &now); + + num = select(info->maxfd+1, &rset, NULL, NULL, &timeout); + if(num == -1) { + if(errno == EAGAIN || errno == EINTR) + return; + log_err("select: %s", strerror(errno)); + } + + /* handle new events */ + for(i=0; num && iio_num; i++) { + if(FD_ISSET(info->io[i].fd, &rset)) { + perfreply(info, i, &now); + num--; + } + } +} + +/** show end stats */ +static void +perfendstats(struct perfinfo* info) +{ + double dt, qps; + struct timeval timeout, now; + int i, lost; + if(gettimeofday(&now, NULL) < 0) + fatal_exit("gettimeofday: %s", strerror(errno)); + timeout = now; + perf_tv_subtract(&timeout, &info->since); + stat_printout(info, &now, &timeout); + + timeout = now; + perf_tv_subtract(&timeout, &info->start); + dt = (double)(timeout.tv_sec*1000000 + timeout.tv_usec) / 1000000.0; + qps = (double)(info->total_recv) / dt; + lost = (int)(info->total_sent - info->total_recv) - (int)info->io_num; + if(!info->quiet) { + printf("overall time: %g sec\n", + (double)timeout.tv_sec + + (double)timeout.tv_usec/1000000.); + if(lost > 0) + printf("Packets lost: %d\n", (int)lost); + + for(i=0; i<(int)(sizeof(info->by_rcode)/sizeof(size_t)); i++) + { + if(info->by_rcode[i] > 0) { + printf("%d(%5s): %u replies\n", + i, ldns_lookup_by_id(ldns_rcodes, i)? + ldns_lookup_by_id(ldns_rcodes, + i)->name:"??", + (unsigned)info->by_rcode[i]); + } + } + } + printf("average qps: %g\n", qps); +} + +/** perform the performance test */ +static void +perfmain(struct perfinfo* info) +{ + perfsetup(info); + while(!info->exit) { + perfselect(info); + } + perfendstats(info); + perffree(info); +} + +/** parse a query line to a packet into buffer */ +static int +qlist_parse_line(ldns_buffer* buf, char* p) +{ + char nm[1024], cl[1024], tp[1024], fl[1024]; + int r; + int rec = 1, edns = 0; + struct query_info qinfo; + ldns_rdf* rdf; + nm[0] = 0; cl[0] = 0; tp[0] = 0; fl[0] = 0; + r = sscanf(p, " %1023s %1023s %1023s %1023s", nm, cl, tp, fl); + if(r != 3 && r != 4) + return 0; + /*printf("nm='%s', cl='%s', tp='%s', fl='%s'\n", nm, cl, tp, fl);*/ + if(strcmp(tp, "IN") == 0 || strcmp(tp, "CH") == 0) { + qinfo.qtype = ldns_get_rr_type_by_name(cl); + qinfo.qclass = ldns_get_rr_class_by_name(tp); + } else { + qinfo.qtype = ldns_get_rr_type_by_name(tp); + qinfo.qclass = ldns_get_rr_class_by_name(cl); + } + if(fl[0] == '+') rec = 1; + else if(fl[0] == '-') rec = 0; + else if(fl[0] == 'E') edns = 1; + if((fl[0] == '+' || fl[0] == '-') && fl[1] == 'E') + edns = 1; + rdf = ldns_dname_new_frm_str(nm); + if(!rdf) + return 0; + qinfo.qname = ldns_rdf_data(rdf); + qinfo.qname_len = ldns_rdf_size(rdf); + qinfo_query_encode(buf, &qinfo); + ldns_buffer_write_u16_at(buf, 0, 0); /* zero ID */ + if(rec) LDNS_RD_SET(ldns_buffer_begin(buf)); + if(edns) { + struct edns_data ed; + memset(&ed, 0, sizeof(ed)); + ed.edns_present = 1; + ed.udp_size = EDNS_ADVERTISED_SIZE; + /* Set DO bit in all EDNS datagrams ... */ + ed.bits = EDNS_DO; + attach_edns_record(buf, &ed); + } + ldns_rdf_deep_free(rdf); + return 1; +} + +/** grow query list capacity */ +static void +qlist_grow_capacity(struct perfinfo* info) +{ + size_t newcap = (size_t)((info->qlist_capacity==0)?16: + info->qlist_capacity*2); + uint8_t** d = (uint8_t**)calloc(sizeof(uint8_t*), newcap); + size_t* l = (size_t*)calloc(sizeof(size_t), newcap); + if(!d || !l) fatal_exit("out of memory"); + memcpy(d, info->qlist_data, sizeof(uint8_t*)* + info->qlist_capacity); + memcpy(l, info->qlist_len, sizeof(size_t)* + info->qlist_capacity); + free(info->qlist_data); + free(info->qlist_len); + info->qlist_data = d; + info->qlist_len = l; + info->qlist_capacity = newcap; +} + +/** setup query list in info */ +static void +qlist_add_line(struct perfinfo* info, char* line, int no) +{ + if(!qlist_parse_line(info->buf, line)) { + printf("error parsing query %d: %s\n", no, line); + exit(1); + } + ldns_buffer_write_u16_at(info->buf, 0, (uint16_t)info->qlist_size); + if(info->qlist_size + 1 > info->qlist_capacity) { + qlist_grow_capacity(info); + } + info->qlist_len[info->qlist_size] = ldns_buffer_limit(info->buf); + info->qlist_data[info->qlist_size] = memdup( + ldns_buffer_begin(info->buf), ldns_buffer_limit(info->buf)); + if(!info->qlist_data[info->qlist_size]) + fatal_exit("out of memory"); + info->qlist_size ++; +} + +/** setup query list in info */ +static void +qlist_read_file(struct perfinfo* info, char* fname) +{ + char buf[1024]; + char *p; + FILE* in = fopen(fname, "r"); + int lineno = 0; + if(!in) { + perror(fname); + exit(1); + } + while(fgets(buf, (int)sizeof(buf), in)) { + lineno++; + buf[sizeof(buf)-1] = 0; + p = buf; + while(*p == ' ' || *p == '\t') + p++; + if(p[0] == 0 || p[0] == '\n' || p[0] == ';' || p[0] == '#') + continue; + qlist_add_line(info, p, lineno); + } + printf("Read %s, got %u queries\n", fname, (unsigned)info->qlist_size); + fclose(in); +} + +/** getopt global, in case header files fail to declare it. */ +extern int optind; +/** getopt global, in case header files fail to declare it. */ +extern char* optarg; + +/** main program for perf */ +int main(int argc, char* argv[]) +{ + char* nm = argv[0]; + int c; + struct perfinfo info; +#ifdef USE_WINSOCK + int r; + WSADATA wsa_data; +#endif + + /* defaults */ + memset(&info, 0, sizeof(info)); + info.io_num = 16; + + log_init(NULL, 0, NULL); + log_ident_set("perf"); + checklock_start(); +#ifdef USE_WINSOCK + if((r = WSAStartup(MAKEWORD(2,2), &wsa_data)) != 0) + fatal_exit("WSAStartup failed: %s", wsa_strerror(r)); +#endif + + info.buf = ldns_buffer_new(65553); + if(!info.buf) fatal_exit("out of memory"); + + /* parse the options */ + while( (c=getopt(argc, argv, "d:ha:f:q")) != -1) { + switch(c) { + case 'q': + info.quiet = 1; + break; + case 'd': + if(atoi(optarg)==0 && strcmp(optarg, "0")!=0) { + printf("-d not a number %s", optarg); + return 1; + } + info.duration = atoi(optarg); + break; + case 'a': + qlist_add_line(&info, optarg, 0); + break; + case 'f': + qlist_read_file(&info, optarg); + break; + case '?': + case 'h': + default: + usage(nm); + } + } + argc -= optind; + argv += optind; + + if(argc != 1) { + printf("error: pass server IP address on commandline.\n"); + usage(nm); + } + if(!extstrtoaddr(argv[0], &info.dest, &info.destlen)) { + printf("Could not parse ip: %s\n", argv[0]); + return 1; + } + if(info.qlist_size == 0) { + printf("No queries to make, use -f or -a.\n"); + return 1; + } + + /* do the performance test */ + perfmain(&info); + + ldns_buffer_free(info.buf); +#ifdef USE_WINSOCK + WSACleanup(); +#endif + checklock_stop(); + return 0; +} diff --git a/testcode/petal.c b/testcode/petal.c new file mode 100644 index 00000000000..14a187e3ff2 --- /dev/null +++ b/testcode/petal.c @@ -0,0 +1,618 @@ +/* + * petal.c - https daemon that is small and beautiful. + * + * Copyright (c) 2010, 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * HTTP1.1/SSL server. + */ + +#include "config.h" +#ifdef HAVE_GETOPT_H +#include +#endif +#ifdef HAVE_OPENSSL_SSL_H +#include +#endif +#ifdef HAVE_OPENSSL_ERR_H +#include +#endif +#ifdef HAVE_OPENSSL_RAND_H +#include +#endif +#include +#include +#include +#include +#if defined(UNBOUND_ALLOC_LITE) || defined(UNBOUND_ALLOC_STATS) +#ifdef malloc +#undef malloc +#endif +#ifdef free +#undef free +#endif +#endif /* alloc lite or alloc stats */ + +/** verbosity for this application */ +static int verb = 0; + +/** Give petal usage, and exit (1). */ +static void +usage() +{ + printf("Usage: petal [opts]\n"); + printf(" https daemon serves files from ./'host'/filename\n"); + printf(" (no hostname: from the 'default' directory)\n"); + printf("-a addr bind to this address, 127.0.0.1\n"); + printf("-p port port number, default 443\n"); + printf("-k keyfile SSL private key file (PEM), petal.key\n"); + printf("-c certfile SSL certificate file (PEM), petal.pem\n"); + printf("-v more verbose\n"); + printf("-h show this usage help\n"); + 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); +} + +/** fatal exit */ +static void print_exit(const char* str) {printf("error %s\n", str); exit(1);} +/** print errno */ +static void log_errno(const char* str) +{printf("error %s: %s\n", str, strerror(errno));} + +/** parse a text IP address into a sockaddr */ +static int +parse_ip_addr(char* str, int port, struct sockaddr_storage* ret, socklen_t* l) +{ + socklen_t len = 0; + struct sockaddr_storage* addr = NULL; + struct sockaddr_in6 a6; + struct sockaddr_in a; + uint16_t p = (uint16_t)port; + int fam = 0; + memset(&a6, 0, sizeof(a6)); + memset(&a, 0, sizeof(a)); + + if(inet_pton(AF_INET6, str, &a6.sin6_addr) > 0) { + /* it is an IPv6 */ + fam = AF_INET6; + a6.sin6_family = AF_INET6; + a6.sin6_port = (in_port_t)htons(p); + addr = (struct sockaddr_storage*)&a6; + len = (socklen_t)sizeof(struct sockaddr_in6); + } + if(inet_pton(AF_INET, str, &a.sin_addr) > 0) { + /* it is an IPv4 */ + fam = AF_INET; + a.sin_family = AF_INET; + a.sin_port = (in_port_t)htons(p); + addr = (struct sockaddr_storage*)&a; + len = (socklen_t)sizeof(struct sockaddr_in); + } + if(!len) print_exit("cannot parse addr"); + *l = len; + memmove(ret, addr, len); + return fam; +} + +/** close the fd */ +static void +fd_close(int fd) +{ +#ifndef USE_WINSOCK + close(fd); +#else + closesocket(fd); +#endif +} + +/** + * Read one line from SSL + * zero terminates. + * skips "\r\n" (but not copied to buf). + * @param ssl: the SSL connection to read from (blocking). + * @param buf: buffer to return line in. + * @param len: size of the buffer. + * @return 0 on error, 1 on success. + */ +static int +read_ssl_line(SSL* ssl, char* buf, size_t len) +{ + size_t n = 0; + int r; + int endnl = 0; + while(1) { + if(n >= len) { + if(verb) printf("line too long\n"); + return 0; + } + if((r = SSL_read(ssl, buf+n, 1)) <= 0) { + if(SSL_get_error(ssl, r) == SSL_ERROR_ZERO_RETURN) { + /* EOF */ + break; + } + if(verb) printf("could not SSL_read\n"); + return 0; + } + if(endnl && buf[n] == '\n') { + break; + } else if(endnl) { + /* bad data */ + if(verb) printf("error: stray linefeeds\n"); + return 0; + } else if(buf[n] == '\r') { + /* skip \r, and also \n on the wire */ + endnl = 1; + continue; + } else if(buf[n] == '\n') { + /* skip the \n, we are done */ + break; + } else n++; + } + buf[n] = 0; + return 1; +} + +/** process one http header */ +static int +process_one_header(char* buf, char* file, size_t flen, char* host, size_t hlen, + int* vs) +{ + if(strncasecmp(buf, "GET ", 4) == 0) { + char* e = strstr(buf, " HTTP/1.1"); + if(!e) e = strstr(buf, " http/1.1"); + if(!e) { + e = strstr(buf, " HTTP/1.0"); + if(!e) e = strstr(buf, " http/1.0"); + if(!e) e = strrchr(buf, ' '); + if(!e) e = strrchr(buf, '\t'); + if(e) *vs = 10; + } + if(e) *e = 0; + if(strlen(buf) < 4) return 0; + (void)strlcpy(file, buf+4, flen); + } else if(strncasecmp(buf, "Host: ", 6) == 0) { + (void)strlcpy(host, buf+6, hlen); + } + return 1; +} + +/** read http headers and process them */ +static int +read_http_headers(SSL* ssl, char* file, size_t flen, char* host, size_t hlen, + int* vs) +{ + char buf[1024]; + file[0] = 0; + host[0] = 0; + while(read_ssl_line(ssl, buf, sizeof(buf))) { + if(verb>=2) printf("read: %s\n", buf); + if(buf[0] == 0) + return 1; + if(!process_one_header(buf, file, flen, host, hlen, vs)) + return 0; + } + return 0; +} + +/** setup SSL context */ +static SSL_CTX* +setup_ctx(char* key, char* cert) +{ + SSL_CTX* ctx = SSL_CTX_new(SSLv23_server_method()); + if(!ctx) print_exit("out of memory"); + (void)SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2); + if(!SSL_CTX_use_certificate_file(ctx, cert, SSL_FILETYPE_PEM)) + print_exit("cannot read cert"); + if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) + print_exit("cannot read key"); + if(!SSL_CTX_check_private_key(ctx)) + print_exit("private key is not correct"); + if(!SSL_CTX_load_verify_locations(ctx, cert, NULL)) + print_exit("cannot load cert verify locations"); + return ctx; +} + +/** setup listening TCP */ +static int +setup_fd(char* addr, int port) +{ + struct sockaddr_storage ad; + socklen_t len; + int fd; + int c = 1; + int fam = parse_ip_addr(addr, port, &ad, &len); + fd = socket(fam, SOCK_STREAM, 0); + if(fd == -1) { + log_errno("socket"); + return -1; + } + if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, + (void*)&c, (socklen_t) sizeof(int)) < 0) { + log_errno("setsockopt(SOL_SOCKET, SO_REUSEADDR)"); + } + if(bind(fd, (struct sockaddr*)&ad, len) == -1) { + log_errno("bind"); + fd_close(fd); + return -1; + } + if(listen(fd, 5) == -1) { + log_errno("listen"); + fd_close(fd); + return -1; + } + return fd; +} + +/** setup SSL connection to the client */ +static SSL* +setup_ssl(int s, SSL_CTX* ctx) +{ + SSL* ssl = SSL_new(ctx); + if(!ssl) return NULL; + SSL_set_accept_state(ssl); + (void)SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); + if(!SSL_set_fd(ssl, s)) { + SSL_free(ssl); + return NULL; + } + return ssl; +} + +/** check a file name for safety */ +static int +file_name_is_safe(char* s) +{ + size_t l = strlen(s); + if(s[0] != '/') + return 0; /* must start with / */ + if(strstr(s, "/../")) + return 0; /* no updirs in URL */ + if(l>=3 && s[l-1]=='.' && s[l-2]=='.' && s[l-3]=='/') + return 0; /* ends with /.. */ + return 1; +} + +/** adjust host and filename */ +static void +adjust_host_file(char* host, char* file) +{ + size_t i, len; + /* remove a port number if present */ + if(strrchr(host, ':')) + *strrchr(host, ':') = 0; + /* lowercase */ + len = strlen(host); + for(i=0; i= 3) + {printf("chunk len %x\n", (unsigned)red); fflush(stdout);} + at += r; + avail -= r; + if(red != 0) { + if(red > avail) break; /* robust */ + memmove(at, tmpbuf, red); + at += red; + avail -= red; + r = snprintf(at, avail, "\r\n"); + at += r; + avail -= r; + } + if(in && feof(in) && red != 0) { + r = snprintf(at, avail, "0\r\n"); + at += r; + avail -= r; + } + if(!in || feof(in)) { + r = snprintf(at, avail, "\r\n"); + at += r; + avail -= r; + } + /* send chunk */ + if(SSL_write(ssl, buf, at-buf) <= 0) { + /* SSL error */ + break; + } + + /* setup for next chunk */ + at = buf; + avail = sizeof(buf); + } while(in && !feof(in) && !ferror(in)); + + if(in) fclose(in); +} + +/** provide service to the ssl descriptor */ +static void +service_ssl(SSL* ssl, struct sockaddr_storage* from, socklen_t falen) +{ + char file[1024]; + char host[1024]; + char combined[2048]; + int vs = 11; + if(!read_http_headers(ssl, file, sizeof(file), host, sizeof(host), + &vs)) + return; + adjust_host_file(host, file); + if(host[0] == 0 || !host_name_is_safe(host)) + (void)strlcpy(host, "default", sizeof(host)); + if(!file_name_is_safe(file)) { + return; + } + snprintf(combined, sizeof(combined), "%s%s", host, file); + if(verb) { + char out[100]; + void* a = &((struct sockaddr_in*)from)->sin_addr; + if(falen != (socklen_t)sizeof(struct sockaddr_in)) + a = &((struct sockaddr_in6*)from)->sin6_addr; + out[0]=0; + (void)inet_ntop((int)((struct sockaddr_in*)from)->sin_family, + a, out, (socklen_t)sizeof(out)); + printf("%s requests %s\n", out, combined); + fflush(stdout); + } + if(vs == 10) + provide_file_10(ssl, combined); + else provide_file_chunked(ssl, combined); +} + +/** provide ssl service */ +static void +do_service(char* addr, int port, char* key, char* cert) +{ + SSL_CTX* sslctx = setup_ctx(key, cert); + int fd = setup_fd(addr, port); + int go = 1; + if(fd == -1) print_exit("could not setup sockets"); + if(verb) {printf("petal start\n"); fflush(stdout);} + while(go) { + struct sockaddr_storage from; + socklen_t flen = (socklen_t)sizeof(from); + int s = accept(fd, (struct sockaddr*)&from, &flen); + if(verb) fflush(stdout); + if(s != -1) { + SSL* ssl = setup_ssl(s, sslctx); + if(verb) fflush(stdout); + if(ssl) { + service_ssl(ssl, &from, flen); + if(verb) fflush(stdout); + SSL_shutdown(ssl); + SSL_free(ssl); + } + fd_close(s); + } else if (verb >=2) log_errno("accept"); + if(verb) fflush(stdout); + } + /* if we get a kill signal, the process dies and the OS reaps us */ + if(verb) printf("petal end\n"); + fd_close(fd); + SSL_CTX_free(sslctx); +} + +/** getopt global, in case header files fail to declare it. */ +extern int optind; +/** getopt global, in case header files fail to declare it. */ +extern char* optarg; + +/** Main routine for petal */ +int main(int argc, char* argv[]) +{ + int c; + int port = 443; + char* addr = "127.0.0.1", *key = "petal.key", *cert = "petal.pem"; +#ifdef USE_WINSOCK + WSADATA wsa_data; + if((c=WSAStartup(MAKEWORD(2,2), &wsa_data)) != 0) + { printf("WSAStartup failed\n"); exit(1); } + atexit((void (*)(void))WSACleanup); +#endif + + /* parse the options */ + while( (c=getopt(argc, argv, "a:c:k:hp:v")) != -1) { + switch(c) { + case 'a': + addr = optarg; + break; + case 'c': + cert = optarg; + break; + case 'k': + key = optarg; + break; + case 'p': + port = atoi(optarg); + break; + case 'v': + verb++; + break; + case '?': + case 'h': + default: + usage(); + } + } + argc -= optind; + argv += optind; + if(argc != 0) + usage(); + +#ifdef SIGPIPE + (void)signal(SIGPIPE, SIG_IGN); +#endif + ERR_load_crypto_strings(); + ERR_load_SSL_strings(); + OpenSSL_add_all_algorithms(); + (void)SSL_library_init(); + + do_service(addr, port, key, cert); + + CRYPTO_cleanup_all_ex_data(); + ERR_remove_state(0); + ERR_free_strings(); + RAND_cleanup(); + return 0; +} diff --git a/testcode/pktview.c b/testcode/pktview.c new file mode 100644 index 00000000000..3cbdfc39581 --- /dev/null +++ b/testcode/pktview.c @@ -0,0 +1,201 @@ +/* + * testcode/pktview.c - debug program to disassemble a DNS packet. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This program shows a dns packet wire format. + */ + +#include "config.h" +#include +#include "util/log.h" +#include "util/data/dname.h" +#include "util/data/msgparse.h" +#include "testcode/unitmain.h" +#include "testcode/readhex.h" + +/** usage information for pktview */ +static void usage(char* argv[]) +{ + printf("usage: %s\n", argv[0]); + printf("present hex packet on stdin.\n"); + exit(1); +} + +/** read hex input */ +static void read_input(ldns_buffer* pkt, FILE* in) +{ + char buf[102400]; + char* np = buf; + while(fgets(np, (int)sizeof(buf) - (np-buf), in)) { + if(buf[0] == ';') /* comment */ + continue; + np = &np[strlen(np)]; + } + hex_to_buf(pkt, buf); +} + +/** analyze domain name in packet, possibly compressed */ +static void analyze_dname(ldns_buffer* pkt) +{ + size_t oldpos = ldns_buffer_position(pkt); + size_t len; + printf("[pos %d] dname: ", (int)oldpos); + dname_print(stdout, pkt, ldns_buffer_current(pkt)); + len = pkt_dname_len(pkt); + printf(" len=%d", (int)len); + if(ldns_buffer_position(pkt)-oldpos != len) + printf(" comprlen=%d\n", + (int)(ldns_buffer_position(pkt)-oldpos)); + else printf("\n"); +} + +/** analyze rdata in packet */ +static void analyze_rdata(ldns_buffer*pkt, const ldns_rr_descriptor* desc, + uint16_t rdlen) +{ + int rdf = 0; + int count = (int)desc->_dname_count; + size_t len, oldpos; + while(rdlen > 0 && count) { + switch(desc->_wireformat[rdf]) { + case LDNS_RDF_TYPE_DNAME: + oldpos = ldns_buffer_position(pkt); + analyze_dname(pkt); + rdlen -= ldns_buffer_position(pkt)-oldpos; + count --; + len = 0; + break; + case LDNS_RDF_TYPE_STR: + len = ldns_buffer_current(pkt)[0] + 1; + break; + default: + len = get_rdf_size(desc->_wireformat[rdf]); + } + if(len) { + printf(" wf[%d]", (int)len); + ldns_buffer_skip(pkt, (ssize_t)len); + rdlen -= len; + } + rdf++; + } + if(rdlen) { + size_t i; + printf(" remain[%d]\n", (int)rdlen); + for(i=0; i_name: "??" , (int)type); + printf(" class %s(%d) ", ldns_lookup_by_id(ldns_rr_classes, + (int)dclass)?ldns_lookup_by_id( ldns_rr_classes, + (int)dclass)->name:"??", (int)dclass); + if(q) { + printf("\n"); + } else { + ttl = ldns_buffer_read_u32(pkt); + printf(" ttl %d (0x%x)", (int)ttl, (unsigned)ttl); + len = ldns_buffer_read_u16(pkt); + printf(" rdata len %d:\n", (int)len); + if(ldns_rr_descript(type)) + analyze_rdata(pkt, ldns_rr_descript(type), len); + else ldns_buffer_skip(pkt, (ssize_t)len); + } +} + +/** analyse pkt */ +static void analyze(ldns_buffer* pkt) +{ + uint16_t i, f, qd, an, ns, ar; + int rrnum = 0; + printf("packet length %d\n", (int)ldns_buffer_limit(pkt)); + if(ldns_buffer_limit(pkt) < 12) return; + + i = ldns_buffer_read_u16(pkt); + printf("id (hostorder): %d (0x%x)\n", (int)i, (unsigned)i); + f = ldns_buffer_read_u16(pkt); + printf("flags: 0x%x\n", (unsigned)f); + qd = ldns_buffer_read_u16(pkt); + printf("qdcount: %d\n", (int)qd); + an = ldns_buffer_read_u16(pkt); + printf("ancount: %d\n", (int)an); + ns = ldns_buffer_read_u16(pkt); + printf("nscount: %d\n", (int)ns); + ar = ldns_buffer_read_u16(pkt); + printf("arcount: %d\n", (int)ar); + + printf(";-- query section\n"); + while(ldns_buffer_remaining(pkt) > 0) { + if(rrnum == (int)qd) + printf(";-- answer section\n"); + if(rrnum == (int)qd+(int)an) + printf(";-- authority section\n"); + if(rrnum == (int)qd+(int)an+(int)ns) + printf(";-- additional section\n"); + printf("rr %d ", rrnum); + analyze_rr(pkt, rrnum < (int)qd); + rrnum++; + } +} + +/** main program for pktview */ +int main(int argc, char* argv[]) +{ + ldns_buffer* pkt = ldns_buffer_new(65553); + if(argc != 1) { + usage(argv); + } + if(!pkt) fatal_exit("out of memory"); + + read_input(pkt, stdin); + analyze(pkt); + + ldns_buffer_free(pkt); + return 0; +} diff --git a/testcode/readhex.c b/testcode/readhex.c new file mode 100644 index 00000000000..f212ddd747c --- /dev/null +++ b/testcode/readhex.c @@ -0,0 +1,83 @@ +/* + * testcode/readhex.c - read hex data. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +/** + * \file + * Declarations useful for the unit tests. + */ +#include "config.h" +#include +#include "testcode/readhex.h" +#include "util/log.h" + +/** skip whitespace */ +static void +skip_whites(const char** p) +{ + while(1) { + while(isspace((int)**p)) + (*p)++; + if(**p == ';') { + /* comment, skip until newline */ + while(**p && **p != '\n') + (*p)++; + if(**p == '\n') + (*p)++; + } else return; + } +} + +/* takes a hex string and puts into buffer */ +void hex_to_buf(ldns_buffer* pkt, const char* hex) +{ + const char* p = hex; + int val; + ldns_buffer_clear(pkt); + while(*p) { + skip_whites(&p); + if(ldns_buffer_position(pkt) == ldns_buffer_limit(pkt)) + fatal_exit("hex_to_buf: buffer too small"); + if(!isalnum((int)*p)) + break; + val = ldns_hexdigit_to_int(*p++) << 4; + skip_whites(&p); + log_assert(*p && isalnum((int)*p)); + val |= ldns_hexdigit_to_int(*p++); + ldns_buffer_write_u8(pkt, (uint8_t)val); + skip_whites(&p); + } + ldns_buffer_flip(pkt); +} + diff --git a/testcode/readhex.h b/testcode/readhex.h new file mode 100644 index 00000000000..5ae3f4dbd51 --- /dev/null +++ b/testcode/readhex.h @@ -0,0 +1,52 @@ +/* + * testcode/readhex.h - read hex data. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +/** + * \file + * Declarations useful for the unit tests. + */ + +#ifndef TESTCODE_READHEX_H +#define TESTCODE_READHEX_H +#include + +/** + * Helper to convert hex string to packet buffer. + * @param pkt: buffer to put result in. + * @param hex: string of hex data. Spaces and ';...' comments are skipped. + */ +void hex_to_buf(ldns_buffer* pkt, const char* hex); + +#endif /* TESTCODE_READHEX_H */ diff --git a/testcode/replay.c b/testcode/replay.c new file mode 100644 index 00000000000..3d3aa01a08d --- /dev/null +++ b/testcode/replay.c @@ -0,0 +1,1026 @@ +/* + * testcode/replay.c - store and use a replay of events for the DNS resolver. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * Store and use a replay of events for the DNS resolver. + * Used to test known scenarios to get known outcomes. + */ + +#include "config.h" +/* for strtod prototype */ +#include +#include "util/log.h" +#include "util/net_help.h" +#include "util/config_file.h" +#include "testcode/replay.h" +#include "testcode/ldns-testpkts.h" +#include "testcode/fake_event.h" + +/** max length of lines in file */ +#define MAX_LINE_LEN 10240 + +/** + * Expand a macro + * @param store: value storage + * @param runtime: replay runtime for other stuff. + * @param text: the macro text, after the ${, Updated to after the } when + * done (successfully). + * @return expanded text, malloced. NULL on failure. + */ +static char* macro_expand(rbtree_t* store, + struct replay_runtime* runtime, char** text); + +/** compare of time values */ +static int +timeval_smaller(const struct timeval* x, const struct timeval* y) +{ +#ifndef S_SPLINT_S + if(x->tv_sec < y->tv_sec) + return 1; + else if(x->tv_sec == y->tv_sec) { + if(x->tv_usec <= y->tv_usec) + return 1; + else return 0; + } + else return 0; +#endif +} + +/** parse keyword in string. + * @param line: if found, the line is advanced to after the keyword. + * @param keyword: string. + * @return: true if found, false if not. + */ +static int +parse_keyword(char** line, const char* keyword) +{ + size_t len = (size_t)strlen(keyword); + if(strncmp(*line, keyword, len) == 0) { + *line += len; + return 1; + } + return 0; +} + +/** delete moment */ +static void +replay_moment_delete(struct replay_moment* mom) +{ + if(!mom) + return; + if(mom->match) { + delete_entry(mom->match); + } + free(mom->autotrust_id); + free(mom->string); + free(mom->variable); + config_delstrlist(mom->file_content); + free(mom); +} + +/** delete range */ +static void +replay_range_delete(struct replay_range* rng) +{ + if(!rng) + return; + delete_entry(rng->match); + free(rng); +} + +/** strip whitespace from end of string */ +static void +strip_end_white(char* p) +{ + size_t i; + for(i = strlen(p); i > 0; i--) { + if(isspace((int)p[i-1])) + p[i-1] = 0; + else return; + } +} + +/** + * Read a range from file. + * @param remain: Rest of line (after RANGE keyword). + * @param in: file to read from. + * @param name: name to print in errors. + * @param lineno: incremented as lines are read. + * @param line: line buffer. + * @param ttl: for readentry + * @param or: for readentry + * @param prev: for readentry + * @return: range object to add to list, or NULL on error. + */ +static struct replay_range* +replay_range_read(char* remain, FILE* in, const char* name, int* lineno, + char* line, uint32_t* ttl, ldns_rdf** or, ldns_rdf** prev) +{ + struct replay_range* rng = (struct replay_range*)malloc( + sizeof(struct replay_range)); + off_t pos; + char *parse; + struct entry* entry, *last = NULL; + if(!rng) + return NULL; + memset(rng, 0, sizeof(*rng)); + /* read time range */ + if(sscanf(remain, " %d %d", &rng->start_step, &rng->end_step)!=2) { + log_err("Could not read time range: %s", line); + free(rng); + return NULL; + } + /* read entries */ + pos = ftello(in); + while(fgets(line, MAX_LINE_LEN-1, in)) { + (*lineno)++; + parse = line; + while(isspace((int)*parse)) + parse++; + if(!*parse || *parse == ';') { + pos = ftello(in); + continue; + } + if(parse_keyword(&parse, "ADDRESS")) { + while(isspace((int)*parse)) + parse++; + strip_end_white(parse); + if(!extstrtoaddr(parse, &rng->addr, &rng->addrlen)) { + log_err("Line %d: could not read ADDRESS: %s", + *lineno, parse); + free(rng); + return NULL; + } + pos = ftello(in); + continue; + } + if(parse_keyword(&parse, "RANGE_END")) { + return rng; + } + /* set position before line; read entry */ + (*lineno)--; + fseeko(in, pos, SEEK_SET); + entry = read_entry(in, name, lineno, ttl, or, prev); + if(!entry) + fatal_exit("%d: bad entry", *lineno); + entry->next = NULL; + if(last) + last->next = entry; + else rng->match = entry; + last = entry; + + pos = ftello(in); + } + replay_range_delete(rng); + return NULL; +} + +/** Read FILE match content */ +static void +read_file_content(FILE* in, int* lineno, struct replay_moment* mom) +{ + char line[MAX_LINE_LEN]; + char* remain = line; + struct config_strlist** last = &mom->file_content; + line[MAX_LINE_LEN-1]=0; + if(!fgets(line, MAX_LINE_LEN-1, in)) + fatal_exit("FILE_BEGIN expected at line %d", *lineno); + if(!parse_keyword(&remain, "FILE_BEGIN")) + fatal_exit("FILE_BEGIN expected at line %d", *lineno); + while(fgets(line, MAX_LINE_LEN-1, in)) { + (*lineno)++; + if(strncmp(line, "FILE_END", 8) == 0) { + return; + } + if(line[0]) line[strlen(line)-1] = 0; /* remove newline */ + if(!cfg_strlist_insert(last, strdup(line))) + fatal_exit("malloc failure"); + last = &( (*last)->next ); + } + fatal_exit("no FILE_END in input file"); +} + +/** read assign step info */ +static void +read_assign_step(char* remain, struct replay_moment* mom) +{ + char buf[1024]; + char eq; + int skip; + buf[sizeof(buf)-1]=0; + if(sscanf(remain, " %1023s %c %n", buf, &eq, &skip) != 2) + fatal_exit("cannot parse assign: %s", remain); + mom->variable = strdup(buf); + if(eq != '=') + fatal_exit("no '=' in assign: %s", remain); + remain += skip; + if(remain[0]) remain[strlen(remain)-1]=0; /* remove newline */ + mom->string = strdup(remain); + if(!mom->variable || !mom->string) + fatal_exit("out of memory"); +} + +/** + * Read a replay moment 'STEP' from file. + * @param remain: Rest of line (after STEP keyword). + * @param in: file to read from. + * @param name: name to print in errors. + * @param lineno: incremented as lines are read. + * @param ttl: for readentry + * @param or: for readentry + * @param prev: for readentry + * @return: range object to add to list, or NULL on error. + */ +static struct replay_moment* +replay_moment_read(char* remain, FILE* in, const char* name, int* lineno, + uint32_t* ttl, ldns_rdf** or, ldns_rdf** prev) +{ + struct replay_moment* mom = (struct replay_moment*)malloc( + sizeof(struct replay_moment)); + int skip = 0; + int readentry = 0; + if(!mom) + return NULL; + memset(mom, 0, sizeof(*mom)); + if(sscanf(remain, " %d%n", &mom->time_step, &skip) != 1) { + log_err("%d: cannot read number: %s", *lineno, remain); + free(mom); + return NULL; + } + remain += skip; + while(isspace((int)*remain)) + remain++; + if(parse_keyword(&remain, "NOTHING")) { + mom->evt_type = repevt_nothing; + } else if(parse_keyword(&remain, "QUERY")) { + mom->evt_type = repevt_front_query; + readentry = 1; + if(!extstrtoaddr("127.0.0.1", &mom->addr, &mom->addrlen)) + fatal_exit("internal error"); + } else if(parse_keyword(&remain, "CHECK_ANSWER")) { + mom->evt_type = repevt_front_reply; + readentry = 1; + } else if(parse_keyword(&remain, "CHECK_OUT_QUERY")) { + mom->evt_type = repevt_back_query; + readentry = 1; + } else if(parse_keyword(&remain, "REPLY")) { + mom->evt_type = repevt_back_reply; + readentry = 1; + } else if(parse_keyword(&remain, "TIMEOUT")) { + mom->evt_type = repevt_timeout; + } else if(parse_keyword(&remain, "TIME_PASSES")) { + mom->evt_type = repevt_time_passes; + while(isspace((int)*remain)) + remain++; + if(parse_keyword(&remain, "EVAL")) { + while(isspace((int)*remain)) + remain++; + mom->string = strdup(remain); + if(!mom->string) fatal_exit("out of memory"); + if(strlen(mom->string)>0) + mom->string[strlen(mom->string)-1]=0; + remain += strlen(mom->string); + } + } else if(parse_keyword(&remain, "CHECK_AUTOTRUST")) { + mom->evt_type = repevt_autotrust_check; + while(isspace((int)*remain)) + remain++; + if(strlen(remain)>0 && remain[strlen(remain)-1]=='\n') + remain[strlen(remain)-1] = 0; + mom->autotrust_id = strdup(remain); + if(!mom->autotrust_id) fatal_exit("out of memory"); + read_file_content(in, lineno, mom); + } else if(parse_keyword(&remain, "ERROR")) { + mom->evt_type = repevt_error; + } else if(parse_keyword(&remain, "TRAFFIC")) { + mom->evt_type = repevt_traffic; + } else if(parse_keyword(&remain, "ASSIGN")) { + mom->evt_type = repevt_assign; + read_assign_step(remain, mom); + } else if(parse_keyword(&remain, "INFRA_RTT")) { + char *s, *m; + mom->evt_type = repevt_infra_rtt; + while(isspace((int)*remain)) + remain++; + s = remain; + remain = strchr(s, ' '); + if(!remain) fatal_exit("expected three args for INFRA_RTT"); + remain[0] = 0; + remain++; + while(isspace((int)*remain)) + remain++; + m = strchr(remain, ' '); + if(!m) fatal_exit("expected three args for INFRA_RTT"); + m[0] = 0; + m++; + while(isspace((int)*m)) + m++; + if(!extstrtoaddr(s, &mom->addr, &mom->addrlen)) + fatal_exit("bad infra_rtt address %s", s); + if(strlen(m)>0 && m[strlen(m)-1]=='\n') + m[strlen(m)-1] = 0; + mom->variable = strdup(remain); + mom->string = strdup(m); + if(!mom->string) fatal_exit("out of memory"); + if(!mom->variable) fatal_exit("out of memory"); + } else { + log_err("%d: unknown event type %s", *lineno, remain); + free(mom); + return NULL; + } + while(isspace((int)*remain)) + remain++; + if(parse_keyword(&remain, "ADDRESS")) { + while(isspace((int)*remain)) + remain++; + if(strlen(remain) > 0) /* remove \n */ + remain[strlen(remain)-1] = 0; + if(!extstrtoaddr(remain, &mom->addr, &mom->addrlen)) { + log_err("line %d: could not parse ADDRESS: %s", + *lineno, remain); + free(mom); + return NULL; + } + } + if(parse_keyword(&remain, "ELAPSE")) { + double sec; + errno = 0; + sec = strtod(remain, &remain); + if(sec == 0. && errno != 0) { + log_err("line %d: could not parse ELAPSE: %s (%s)", + *lineno, remain, strerror(errno)); + free(mom); + return NULL; + } +#ifndef S_SPLINT_S + mom->elapse.tv_sec = (int)sec; + mom->elapse.tv_usec = (int)((sec - (double)mom->elapse.tv_sec) + *1000000. + 0.5); +#endif + } + + if(readentry) { + mom->match = read_entry(in, name, lineno, ttl, or, prev); + if(!mom->match) { + free(mom); + return NULL; + } + } + + return mom; +} + +/** makes scenario with title on rest of line */ +static struct replay_scenario* +make_scenario(char* line) +{ + struct replay_scenario* scen; + while(isspace((int)*line)) + line++; + if(!*line) { + log_err("scenario: no title given"); + return NULL; + } + scen = (struct replay_scenario*)malloc(sizeof(struct replay_scenario)); + if(!scen) + return NULL; + memset(scen, 0, sizeof(*scen)); + scen->title = strdup(line); + if(!scen->title) { + free(scen); + return NULL; + } + return scen; +} + +struct replay_scenario* +replay_scenario_read(FILE* in, const char* name, int* lineno) +{ + char line[MAX_LINE_LEN]; + char *parse; + struct replay_scenario* scen = NULL; + uint32_t ttl = 3600; + ldns_rdf* or = NULL; + ldns_rdf* prev = NULL; + line[MAX_LINE_LEN-1]=0; + + while(fgets(line, MAX_LINE_LEN-1, in)) { + parse=line; + (*lineno)++; + while(isspace((int)*parse)) + parse++; + if(!*parse) + continue; /* empty line */ + if(parse_keyword(&parse, ";")) + continue; /* comment */ + if(parse_keyword(&parse, "SCENARIO_BEGIN")) { + scen = make_scenario(parse); + if(!scen) + fatal_exit("%d: could not make scen", *lineno); + continue; + } + if(!scen) + fatal_exit("%d: expected SCENARIO", *lineno); + if(parse_keyword(&parse, "RANGE_BEGIN")) { + struct replay_range* newr = replay_range_read(parse, + in, name, lineno, line, &ttl, &or, &prev); + if(!newr) + fatal_exit("%d: bad range", *lineno); + newr->next_range = scen->range_list; + scen->range_list = newr; + } else if(parse_keyword(&parse, "STEP")) { + struct replay_moment* mom = replay_moment_read(parse, + in, name, lineno, &ttl, &or, &prev); + if(!mom) + fatal_exit("%d: bad moment", *lineno); + if(scen->mom_last && + scen->mom_last->time_step >= mom->time_step) + fatal_exit("%d: time goes backwards", *lineno); + if(scen->mom_last) + scen->mom_last->mom_next = mom; + else scen->mom_first = mom; + scen->mom_last = mom; + } else if(parse_keyword(&parse, "SCENARIO_END")) { + struct replay_moment *p = scen->mom_first; + int num = 0; + while(p) { + num++; + p = p->mom_next; + } + log_info("Scenario has %d steps", num); + ldns_rdf_deep_free(or); + ldns_rdf_deep_free(prev); + return scen; + } + } + ldns_rdf_deep_free(or); + ldns_rdf_deep_free(prev); + replay_scenario_delete(scen); + return NULL; +} + +void +replay_scenario_delete(struct replay_scenario* scen) +{ + struct replay_moment* mom, *momn; + struct replay_range* rng, *rngn; + if(!scen) + return; + if(scen->title) + free(scen->title); + mom = scen->mom_first; + while(mom) { + momn = mom->mom_next; + replay_moment_delete(mom); + mom = momn; + } + rng = scen->range_list; + while(rng) { + rngn = rng->next_range; + replay_range_delete(rng); + rng = rngn; + } + free(scen); +} + +/** fetch oldest timer in list that is enabled */ +static struct fake_timer* +first_timer(struct replay_runtime* runtime) +{ + struct fake_timer* p, *res = NULL; + for(p=runtime->timer_list; p; p=p->next) { + if(!p->enabled) + continue; + if(!res) + res = p; + else if(timeval_smaller(&p->tv, &res->tv)) + res = p; + } + return res; +} + +struct fake_timer* +replay_get_oldest_timer(struct replay_runtime* runtime) +{ + struct fake_timer* t = first_timer(runtime); + if(t && timeval_smaller(&t->tv, &runtime->now_tv)) + return t; + return NULL; +} + +int +replay_var_compare(const void* a, const void* b) +{ + struct replay_var* x = (struct replay_var*)a; + struct replay_var* y = (struct replay_var*)b; + return strcmp(x->name, y->name); +} + +rbtree_t* +macro_store_create(void) +{ + return rbtree_create(&replay_var_compare); +} + +/** helper function to delete macro values */ +static void +del_macro(rbnode_t* x, void* ATTR_UNUSED(arg)) +{ + struct replay_var* v = (struct replay_var*)x; + free(v->name); + free(v->value); + free(v); +} + +void +macro_store_delete(rbtree_t* store) +{ + if(!store) + return; + traverse_postorder(store, del_macro, NULL); + free(store); +} + +/** return length of macro */ +static size_t +macro_length(char* text) +{ + /* we are after ${, looking for } */ + int depth = 0; + size_t len = 0; + while(*text) { + len++; + if(*text == '}') { + if(depth == 0) + break; + depth--; + } else if(text[0] == '$' && text[1] == '{') { + depth++; + } + text++; + } + return len; +} + +/** insert new stuff at start of buffer */ +static int +do_buf_insert(char* buf, size_t remain, char* after, char* inserted) +{ + char* save = strdup(after); + size_t len; + if(!save) return 0; + if(strlen(inserted) > remain) { + free(save); + return 0; + } + len = strlcpy(buf, inserted, remain); + buf += len; + remain -= len; + (void)strlcpy(buf, save, remain); + free(save); + return 1; +} + +/** do macro recursion */ +static char* +do_macro_recursion(rbtree_t* store, struct replay_runtime* runtime, + char* at, size_t remain) +{ + char* after = at+2; + char* expand = macro_expand(store, runtime, &after); + if(!expand) + return NULL; /* expansion failed */ + if(!do_buf_insert(at, remain, after, expand)) { + free(expand); + return NULL; + } + free(expand); + return at; /* and parse over the expanded text to see if again */ +} + +/** get var from store */ +static struct replay_var* +macro_getvar(rbtree_t* store, char* name) +{ + struct replay_var k; + k.node.key = &k; + k.name = name; + return (struct replay_var*)rbtree_search(store, &k); +} + +/** do macro variable */ +static char* +do_macro_variable(rbtree_t* store, char* buf, size_t remain) +{ + struct replay_var* v; + char* at = buf+1; + char* name = at; + char sv; + if(at[0]==0) + return NULL; /* no variable name after $ */ + while(*at && (isalnum((int)*at) || *at=='_')) { + at++; + } + /* terminator, we are working in macro_expand() buffer */ + sv = *at; + *at = 0; + v = macro_getvar(store, name); + *at = sv; + + if(!v) { + log_err("variable is not defined: $%s", name); + return NULL; /* variable undefined is error for now */ + } + + /* insert the variable contents */ + if(!do_buf_insert(buf, remain, at, v->value)) + return NULL; + return buf; /* and expand the variable contents */ +} + +/** do ctime macro on argument */ +static char* +do_macro_ctime(char* arg) +{ + char buf[32]; + time_t tt = (time_t)atoi(arg); + if(tt == 0 && strcmp(arg, "0") != 0) { + log_err("macro ctime: expected number, not: %s", arg); + return NULL; + } + ctime_r(&tt, buf); + if(buf[0]) buf[strlen(buf)-1]=0; /* remove trailing newline */ + return strdup(buf); +} + +/** perform arithmetic operator */ +static double +perform_arith(double x, char op, double y, double* res) +{ + switch(op) { + case '+': + *res = x+y; + break; + case '-': + *res = x-y; + break; + case '/': + *res = x/y; + break; + case '*': + *res = x*y; + break; + default: + return 0; + } + + return 1; +} + +/** do macro arithmetic on two numbers and operand */ +static char* +do_macro_arith(char* orig, size_t remain, char** arithstart) +{ + double x, y, result; + char operator; + int skip; + char buf[32]; + char* at; + /* not yet done? we want number operand number expanded first. */ + if(!*arithstart) { + /* remember start pos of expr, skip the first number */ + at = orig; + *arithstart = at; + while(*at && (isdigit((int)*at) || *at == '.')) + at++; + return at; + } + /* move back to start */ + remain += (size_t)(orig - *arithstart); + at = *arithstart; + + /* parse operands */ + if(sscanf(at, " %lf %c %lf%n", &x, &operator, &y, &skip) != 3) { + *arithstart = NULL; + return do_macro_arith(orig, remain, arithstart); + } + if(isdigit((int)operator)) { + *arithstart = orig; + return at+skip; /* do nothing, but setup for later number */ + } + + /* calculate result */ + if(!perform_arith(x, operator, y, &result)) { + log_err("unknown operator: %s", at); + return NULL; + } + + /* put result back in buffer */ + snprintf(buf, sizeof(buf), "%.12g", result); + if(!do_buf_insert(at, remain, at+skip, buf)) + return NULL; + + /* the result can be part of another expression, restart that */ + *arithstart = NULL; + return at; +} + +/** Do range macro on expanded buffer */ +static char* +do_macro_range(char* buf) +{ + double x, y, z; + if(sscanf(buf, " %lf %lf %lf", &x, &y, &z) != 3) { + log_err("range func requires 3 args: %s", buf); + return NULL; + } + if(x <= y && y <= z) { + char res[1024]; + snprintf(res, sizeof(res), "%.24g", y); + return strdup(res); + } + fatal_exit("value %.24g not in range [%.24g, %.24g]", y, x, z); + return NULL; +} + +static char* +macro_expand(rbtree_t* store, struct replay_runtime* runtime, char** text) +{ + char buf[10240]; + char* at = *text; + size_t len = macro_length(at); + int dofunc = 0; + char* arithstart = NULL; + if(len >= sizeof(buf)) + return NULL; /* too long */ + buf[0] = 0; + (void)strlcpy(buf, at, len+1-1); /* do not copy last '}' character */ + at = buf; + + /* check for functions */ + if(strcmp(buf, "time") == 0) { + snprintf(buf, sizeof(buf), "%u", (unsigned)runtime->now_secs); + *text += len; + return strdup(buf); + } else if(strcmp(buf, "timeout") == 0) { + uint32_t res = 0; + struct fake_timer* t = first_timer(runtime); + if(t && (uint32_t)t->tv.tv_sec >= runtime->now_secs) + res = (uint32_t)t->tv.tv_sec - runtime->now_secs; + snprintf(buf, sizeof(buf), "%u", (unsigned)res); + *text += len; + return strdup(buf); + } else if(strncmp(buf, "ctime ", 6) == 0 || + strncmp(buf, "ctime\t", 6) == 0) { + at += 6; + dofunc = 1; + } else if(strncmp(buf, "range ", 6) == 0 || + strncmp(buf, "range\t", 6) == 0) { + at += 6; + dofunc = 1; + } + + /* actual macro text expansion */ + while(*at) { + size_t remain = sizeof(buf)-strlen(buf); + if(strncmp(at, "${", 2) == 0) { + at = do_macro_recursion(store, runtime, at, remain); + } else if(*at == '$') { + at = do_macro_variable(store, at, remain); + } else if(isdigit((int)*at)) { + at = do_macro_arith(at, remain, &arithstart); + } else { + /* copy until whitespace or operator */ + if(*at && (isalnum((int)*at) || *at=='_')) { + at++; + while(*at && (isalnum((int)*at) || *at=='_')) + at++; + } else at++; + } + if(!at) return NULL; /* failure */ + } + *text += len; + if(dofunc) { + /* post process functions, buf has the argument(s) */ + if(strncmp(buf, "ctime", 5) == 0) { + return do_macro_ctime(buf+6); + } else if(strncmp(buf, "range", 5) == 0) { + return do_macro_range(buf+6); + } + } + return strdup(buf); +} + +char* +macro_process(rbtree_t* store, struct replay_runtime* runtime, char* text) +{ + char buf[10240]; + char* next, *expand; + char* at = text; + if(!strstr(text, "${")) + return strdup(text); /* no macros */ + buf[0] = 0; + buf[sizeof(buf)-1]=0; + while( (next=strstr(at, "${")) ) { + /* copy text before next macro */ + if((size_t)(next-at) >= sizeof(buf)-strlen(buf)) + return NULL; /* string too long */ + (void)strlcpy(buf+strlen(buf), at, (size_t)(next-at+1)); + /* process the macro itself */ + next += 2; + expand = macro_expand(store, runtime, &next); + if(!expand) return NULL; /* expansion failed */ + (void)strlcpy(buf+strlen(buf), expand, sizeof(buf)-strlen(buf)); + free(expand); + at = next; + } + /* copy remainder fixed text */ + (void)strlcpy(buf+strlen(buf), at, sizeof(buf)-strlen(buf)); + return strdup(buf); +} + +char* +macro_lookup(rbtree_t* store, char* name) +{ + struct replay_var* x = macro_getvar(store, name); + if(!x) return strdup(""); + return strdup(x->value); +} + +void macro_print_debug(rbtree_t* store) +{ + struct replay_var* x; + RBTREE_FOR(x, struct replay_var*, store) { + log_info("%s = %s", x->name, x->value); + } +} + +int +macro_assign(rbtree_t* store, char* name, char* value) +{ + struct replay_var* x = macro_getvar(store, name); + if(x) { + free(x->value); + } else { + x = (struct replay_var*)malloc(sizeof(*x)); + if(!x) return 0; + x->node.key = x; + x->name = strdup(name); + if(!x->name) { + free(x); + return 0; + } + (void)rbtree_insert(store, &x->node); + } + x->value = strdup(value); + return x->value != NULL; +} + +void testbound_selftest(void) +{ + /* test the macro store */ + rbtree_t* store = macro_store_create(); + char* v; + int r; + log_assert(store); + + v = macro_lookup(store, "bla"); + log_assert(strcmp(v, "") == 0); + free(v); + + v = macro_lookup(store, "vlerk"); + log_assert(strcmp(v, "") == 0); + free(v); + + r = macro_assign(store, "bla", "waarde1"); + log_assert(r); + + v = macro_lookup(store, "vlerk"); + log_assert(strcmp(v, "") == 0); + free(v); + + v = macro_lookup(store, "bla"); + log_assert(strcmp(v, "waarde1") == 0); + free(v); + + r = macro_assign(store, "vlerk", "kanteel"); + log_assert(r); + + v = macro_lookup(store, "bla"); + log_assert(strcmp(v, "waarde1") == 0); + free(v); + + v = macro_lookup(store, "vlerk"); + log_assert(strcmp(v, "kanteel") == 0); + free(v); + + r = macro_assign(store, "bla", "ww"); + log_assert(r); + + v = macro_lookup(store, "bla"); + log_assert(strcmp(v, "ww") == 0); + free(v); + + log_assert( macro_length("}") == 1); + log_assert( macro_length("blabla}") == 7); + log_assert( macro_length("bla${zoink}bla}") == 7+8); + log_assert( macro_length("bla${zoink}${bla}bla}") == 7+8+6); + + v = macro_process(store, NULL, ""); + log_assert( v && strcmp(v, "") == 0); + free(v); + + v = macro_process(store, NULL, "${}"); + log_assert( v && strcmp(v, "") == 0); + free(v); + + v = macro_process(store, NULL, "blabla ${} dinges"); + log_assert( v && strcmp(v, "blabla dinges") == 0); + free(v); + + v = macro_process(store, NULL, "1${$bla}2${$bla}3"); + log_assert( v && strcmp(v, "1ww2ww3") == 0); + free(v); + + v = macro_process(store, NULL, "it is ${ctime 123456}"); + log_assert( v && strcmp(v, "it is Fri Jan 2 10:17:36 1970") == 0); + free(v); + + r = macro_assign(store, "t1", "123456"); + log_assert(r); + v = macro_process(store, NULL, "it is ${ctime ${$t1}}"); + log_assert( v && strcmp(v, "it is Fri Jan 2 10:17:36 1970") == 0); + free(v); + + v = macro_process(store, NULL, "it is ${ctime $t1}"); + log_assert( v && strcmp(v, "it is Fri Jan 2 10:17:36 1970") == 0); + free(v); + + r = macro_assign(store, "x", "1"); + log_assert(r); + r = macro_assign(store, "y", "2"); + log_assert(r); + v = macro_process(store, NULL, "${$x + $x}"); + log_assert( v && strcmp(v, "2") == 0); + free(v); + v = macro_process(store, NULL, "${$x - $x}"); + log_assert( v && strcmp(v, "0") == 0); + free(v); + v = macro_process(store, NULL, "${$y * $y}"); + log_assert( v && strcmp(v, "4") == 0); + free(v); + v = macro_process(store, NULL, "${32 / $y + $x + $y}"); + log_assert( v && strcmp(v, "19") == 0); + free(v); + + v = macro_process(store, NULL, "${32 / ${$y+$y} + ${${100*3}/3}}"); + log_assert( v && strcmp(v, "108") == 0); + free(v); + + v = macro_process(store, NULL, "${1 2 33 2 1}"); + log_assert( v && strcmp(v, "1 2 33 2 1") == 0); + free(v); + + v = macro_process(store, NULL, "${123 3 + 5}"); + log_assert( v && strcmp(v, "123 8") == 0); + free(v); + + v = macro_process(store, NULL, "${123 glug 3 + 5}"); + log_assert( v && strcmp(v, "123 glug 8") == 0); + free(v); + + macro_store_delete(store); +} diff --git a/testcode/replay.h b/testcode/replay.h new file mode 100644 index 00000000000..049db4e800b --- /dev/null +++ b/testcode/replay.h @@ -0,0 +1,461 @@ +/* + * testcode/replay.h - store and use a replay of events for the DNS resolver. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * Store and use a replay of events for the DNS resolver. + * Used to test known scenarios to get known outcomes. + * + *

    + * File format for replay files.
    + *
    + * ; unbound.conf options.
    + * ; ...
    + * ; additional commandline options to pass to unbound
    + * COMMANDLINE cmdline_option
    + * ; autotrust key file contents, also adds auto-trust-anchor-file: "x" to cfg
    + * AUTOTRUST_FILE id
    + * ; contents of that file
    + * AUTOTRUST_END
    + * CONFIG_END
    + * ; comment line.
    + * SCENARIO_BEGIN name_of_scenario
    + * RANGE_BEGIN start_time end_time
    + *    ; give ip of the virtual server, it matches any ip if not present.
    + *    ADDRESS ip_address 
    + *    match_entries
    + * RANGE_END
    + * ; more RANGE items.
    + * ; go to the next moment
    + * STEP time_step event_type [ADDRESS ip_address]
    + * ; event_type can be:
    + *	o NOTHING - nothing
    + *	o QUERY - followed by entry
    + *	o CHECK_ANSWER - followed by entry
    + *	o CHECK_OUT_QUERY - followed by entry (if copy-id it is also reply).
    + *	o REPLY - followed by entry
    + *      o TIMEOUT
    + *      o TIME_PASSES ELAPSE [seconds] - increase 'now' time counter, can be 
    + *      			a floating point number.
    + *        TIME_PASSES EVAL [macro] - expanded for seconds to move time.
    + *      o TRAFFIC - like CHECK_ANSWER, causes traffic to flow.
    + *		actually the traffic flows before this step is taken.
    + *		the step waits for traffic to stop.
    + *      o CHECK_AUTOTRUST [id] - followed by FILE_BEGIN [to match] FILE_END.
    + *      	The file contents is macro expanded before match.
    + *      o INFRA_RTT [ip] [dp] [rtt] - update infra cache entry with rtt.
    + *      o ERROR
    + * ; following entry starts on the next line, ENTRY_BEGIN.
    + * ; more STEP items
    + * SCENARIO_END
    + *
    + * Calculations, a macro-like system: ${$myvar + 3600}
    + * STEP 10 ASSIGN myvar = 3600
    + * 	; ASSIGN event. '=' is syntactic sugar here. 3600 is some expression.
    + * ${..} is macro expanded from its expression.  Text substitution.
    + * 	o $var replaced with its value.  var is identifier [azAZ09_]*
    + * 	o number is that number.
    + * 	o ${variables and arithmetic }
    + * 	o +, -, / and *.  Note, evaluated left-to-right. Use ${} for brackets.
    + * 	  So again, no precedence rules, so 2+3*4 == ${2+3}*4 = 20.
    + * 	  Do 2+${3*4} to get 24.
    + * 	o ${function params}
    + *		o ${time} is the current time for the simulated unbound.
    + *		o ${ctime value} is the text ctime(value), Fri 3 Aug 2009, ...
    + *		o ${timeout} is the time until next timeout in comm_timer list.
    + *		o ${range lower value upper} checks if lower<=value<=upper
    + *			returns value if check succeeds.
    + *
    + * ; Example file
    + * SCENARIO_BEGIN Example scenario
    + * RANGE_BEGIN 0 100
    + *   ENTRY_BEGIN
    + *   ; precoded answers to queries.
    + *   ENTRY_END
    + * END_RANGE
    + * STEP 0 QUERY
    + *   ENTRY_BEGIN
    + *   ; query
    + *   ENTRY_END
    + * ; a query is sent out to the network by resolver.
    + * ; precoded answer from range is returned.
    + * ; algorithm will do precoded answers from RANGE immediately, except if
    + * ; the next step specifically checks for that OUT_QUERY.
    + * ; or if none of the precoded answers match.
    + * STEP 1 CHECK_ANSWER
    + *   ENTRY_BEGIN
    + *   ; what the reply should look like
    + *   ENTRY_END
    + * ; successful termination. (if the answer was OK).
    + * ; also, all answers must have been checked with CHECK_ANSWER.
    + * ; and, no more pending out_queries (that have not been checked).
    + * SCENARIO_END
    + * 
    + * 
    + */ + +#ifndef TESTCODE_REPLAY_H +#define TESTCODE_REPLAY_H +#include "util/netevent.h" +#include "testcode/ldns-testpkts.h" +#include "util/rbtree.h" +struct replay_answer; +struct replay_moment; +struct replay_range; +struct fake_pending; +struct fake_timer; +struct replay_var; +struct infra_cache; + +/** + * A replay scenario. + */ +struct replay_scenario { + /** name of replay scenario. malloced string. */ + char* title; + + /** The list of replay moments. Linked list. Time increases in list. */ + struct replay_moment* mom_first; + /** The last element in list of replay moments. */ + struct replay_moment* mom_last; + + /** + * List of matching answers. This is to ease replay scenario + * creation. It lists queries (to the network) and what answer + * should be returned. The matching answers are valid for a range + * of time steps. + * So: timestep, parts of query, destination --> answer. + */ + struct replay_range* range_list; +}; + +/** + * A replay moment. + * Basically, it consists of events to a fake select() call. + * This is a recording of an event that happens. + * And if output is presented, what is done with that. + */ +struct replay_moment { + /** + * The replay time step number. Starts at 0, time is incremented + * every time the fake select() is run. + */ + int time_step; + /** Next replay moment in list of replay moments. */ + struct replay_moment* mom_next; + + /** what happens this moment? */ + enum replay_event_type { + /** nothing happens, as if this event is not there. */ + repevt_nothing, + /** incoming query */ + repevt_front_query, + /** test fails if reply to query does not match */ + repevt_front_reply, + /** timeout */ + repevt_timeout, + /** time passes */ + repevt_time_passes, + /** reply arrives from the network */ + repevt_back_reply, + /** test fails if query to the network does not match */ + repevt_back_query, + /** check autotrust key file */ + repevt_autotrust_check, + /** an error happens to outbound query */ + repevt_error, + /** assignment to a variable */ + repevt_assign, + /** store infra rtt cache entry: addr and string (int) */ + repevt_infra_rtt, + /** cause traffic to flow */ + repevt_traffic + } + /** variable with what is to happen this moment */ + evt_type; + + /** The sent packet must match this. Incoming events, the data. */ + struct entry* match; + + /** the amount of time that passes */ + struct timeval elapse; + + /** address that must be matched, or packet remote host address. */ + struct sockaddr_storage addr; + /** length of addr, if 0, then any address will do */ + socklen_t addrlen; + + /** what pending query should timeout or is answered. or + * NULL for last sent query. + * Unused at this time. + */ + ldns_rr* qname; + + /** macro name, for assign. */ + char* variable; + /** string argument, for assign. */ + char* string; + + /** the autotrust file id to check */ + char* autotrust_id; + /** file contents to match, one string per line */ + struct config_strlist* file_content; +}; + +/** + * Range of timesteps, and canned replies to matching queries. + */ +struct replay_range { + /** time range when this is valid. Including start and end step. */ + int start_step; + /** end step of time range. */ + int end_step; + /** address of where this range is served. */ + struct sockaddr_storage addr; + /** length of addr, if 0, then any address will do */ + socklen_t addrlen; + + /** Matching list */ + struct entry* match; + + /** next in list of time ranges. */ + struct replay_range* next_range; +}; + +/** + * Replay storage of runtime information. + */ +struct replay_runtime { + /** + * The scenario + */ + struct replay_scenario* scenario; + /** + * Current moment. + */ + struct replay_moment* now; + + /** + * List of pending queries in order they were sent out. First + * one has been sent out most recently. Last one in list is oldest. + */ + struct fake_pending* pending_list; + + /** + * List of answers to queries from clients. These need to be checked. + */ + struct replay_answer* answer_list; + + /** last element in answer list. */ + struct replay_answer* answer_last; + + /** list of fake timer callbacks that are pending */ + struct fake_timer* timer_list; + + /** callback to call for incoming queries */ + comm_point_callback_t* callback_query; + /** user argument for incoming query callback */ + void *cb_arg; + + /** ref the infra cache (was passed to outside_network_create) */ + struct infra_cache* infra; + + /** the current time in seconds */ + uint32_t now_secs; + /** the current time in microseconds */ + struct timeval now_tv; + + /** signal handler callback */ + void (*sig_cb)(int, void*); + /** signal handler user arg */ + void *sig_cb_arg; + /** time to exit cleanly */ + int exit_cleanly; + + /** size of buffers */ + size_t bufsize; + + /** + * Tree of macro values. Of type replay_var + */ + rbtree_t* vars; +}; + +/** + * Pending queries to network, fake replay version. + */ +struct fake_pending { + /** what is important only that we remember the query, copied here. */ + ldns_buffer* buffer; + /** and to what address this is sent to. */ + struct sockaddr_storage addr; + /** len of addr */ + socklen_t addrlen; + /** zone name, uncompressed wire format (as used when sent) */ + uint8_t* zone; + /** length of zone name */ + size_t zonelen; + /** qtype */ + int qtype; + /** The callback function to call when answer arrives (or timeout) */ + comm_point_callback_t* callback; + /** callback user argument */ + void* cb_arg; + /** original timeout in seconds from 'then' */ + int timeout; + + /** next in pending list */ + struct fake_pending* next; + /** the buffer parsed into a ldns_pkt */ + ldns_pkt* pkt; + /** by what transport was the query sent out */ + enum transport_type transport; + /** if this is a serviced query */ + int serviced; + /** the runtime structure this is part of */ + struct replay_runtime* runtime; +}; + +/** + * An answer that is pending to happen. + */ +struct replay_answer { + /** Next in list */ + struct replay_answer* next; + /** reply information */ + struct comm_reply repinfo; + /** the answer preparsed as ldns pkt */ + ldns_pkt* pkt; +}; + +/** + * Timers with callbacks, fake replay version. + */ +struct fake_timer { + /** next in list */ + struct fake_timer* next; + /** the runtime structure this is part of */ + struct replay_runtime* runtime; + /** the callback to call */ + void (*cb)(void*); + /** the callback user argument */ + void* cb_arg; + /** if timer is enabled */ + int enabled; + /** when the timer expires */ + struct timeval tv; +}; + +/** + * Replay macro variable. And its value. + */ +struct replay_var { + /** rbtree node. Key is this structure. Sorted by name. */ + rbnode_t node; + /** the variable name */ + char* name; + /** the variable value */ + char* value; +}; + +/** + * Read a replay scenario from the file. + * @param in: file to read from. + * @param name: name to print in errors. + * @param lineno: incremented for every line read. + * @return: Scenario. NULL if no scenario read. + */ +struct replay_scenario* replay_scenario_read(FILE* in, const char* name, + int* lineno); + +/** + * Delete scenario. + * @param scen: to delete. + */ +void replay_scenario_delete(struct replay_scenario* scen); + +/** compare two replay_vars */ +int replay_var_compare(const void* a, const void* b); + +/** get oldest enabled fake timer */ +struct fake_timer* replay_get_oldest_timer(struct replay_runtime* runtime); + +/** + * Create variable storage + * @return new or NULL on failure. + */ +rbtree_t* macro_store_create(void); + +/** + * Delete variable storage + * @param store: the macro storage to free up. + */ +void macro_store_delete(rbtree_t* store); + +/** + * Apply macro substitution to string. + * @param store: variable store. + * @param runtime: the runtime to look up values as needed. + * @param text: string to work on. + * @return newly malloced string with result. + */ +char* macro_process(rbtree_t* store, struct replay_runtime* runtime, + char* text); + +/** + * Look up a macro value. Like calling ${$name}. + * @param store: variable store + * @param name: macro name + * @return newly malloced string with result or strdup("") if not found. + * or NULL on malloc failure. + */ +char* macro_lookup(rbtree_t* store, char* name); + +/** + * Set macro value. + * @param store: variable store + * @param name: macro name + * @param value: text to set it to. Not expanded. + * @return false on failure. + */ +int macro_assign(rbtree_t* store, char* name, char* value); + +/** Print macro variables stored as debug info */ +void macro_print_debug(rbtree_t* store); + +/** testbounds self test */ +void testbound_selftest(void); + +#endif /* TESTCODE_REPLAY_H */ diff --git a/testcode/signit.c b/testcode/signit.c new file mode 100644 index 00000000000..49256e707d3 --- /dev/null +++ b/testcode/signit.c @@ -0,0 +1,250 @@ +/* + * testcode/signit.c - debug tool to sign rrsets with given keys. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This program signs rrsets with the given keys. It can be used to + * construct input to test the validator with. + */ +#include "config.h" +#include +#include "util/log.h" +#include "util/config_file.h" +#include "util/net_help.h" + +/** + * Key settings + */ +struct keysets { + /** signature inception */ + uint32_t incep; + /** signature expiration */ + uint32_t expi; + /** owner name */ + char* owner; + /** keytag */ + uint16_t keytag; + /** DNSKEY flags */ + uint16_t flags; +}; + +/** print usage and exit */ +static void +usage() +{ + printf("usage: signit expi ince keytag owner keyfile\n"); + printf("present rrset data on stdin.\n"); + printf("signed data is printed to stdout.\n"); + printf("\n"); + printf("Or use: signit NSEC3PARAM hash flags iter salt\n"); + printf("present names on stdin, hashed names are printed to stdout.\n"); + exit(1); +} + +/** read expi ince keytag owner from cmdline */ +static void +parse_cmdline(char *argv[], struct keysets* s) +{ + s->expi = cfg_convert_timeval(argv[1]); + s->incep = cfg_convert_timeval(argv[2]); + s->keytag = (uint16_t)atoi(argv[3]); + s->owner = argv[4]; + s->flags = DNSKEY_BIT_ZSK; /* to enforce signing */ +} + +/** read all key files, exit on error */ +static ldns_key_list* +read_keys(int num, char* names[], struct keysets* set) +{ + int i; + ldns_key_list* keys = ldns_key_list_new(); + ldns_key* k; + ldns_rdf* rdf; + ldns_status s; + int b; + FILE* in; + + if(!keys) fatal_exit("alloc failure"); + for(i=0; iexpi); + ldns_key_set_inception(k, set->incep); + s = ldns_str2rdf_dname(&rdf, set->owner); + if(s != LDNS_STATUS_OK) + fatal_exit("bad owner name %s: %s", set->owner, + ldns_get_errorstr_by_id(s)); + ldns_key_set_pubkey_owner(k, rdf); + ldns_key_set_flags(k, set->flags); + ldns_key_set_keytag(k, set->keytag); + b = ldns_key_list_push_key(keys, k); + log_assert(b); + } + return keys; +} + +/** read list of rrs from the file */ +static ldns_rr_list* +read_rrs(FILE* in) +{ + uint32_t my_ttl = 3600; + ldns_rdf *my_origin = NULL; + ldns_rdf *my_prev = NULL; + ldns_status s; + int line_nr = 1; + int b; + + ldns_rr_list* list; + ldns_rr *rr; + + list = ldns_rr_list_new(); + if(!list) fatal_exit("alloc error"); + + while(!feof(in)) { + s = ldns_rr_new_frm_fp_l(&rr, in, &my_ttl, &my_origin, + &my_prev, &line_nr); + if(s == LDNS_STATUS_SYNTAX_TTL || + s == LDNS_STATUS_SYNTAX_ORIGIN || + s == LDNS_STATUS_SYNTAX_EMPTY) + continue; + else if(s != LDNS_STATUS_OK) + fatal_exit("parse error in line %d: %s", line_nr, + ldns_get_errorstr_by_id(s)); + b = ldns_rr_list_push_rr(list, rr); + log_assert(b); + } + printf("read %d lines\n", line_nr); + + return list; +} + +/** sign the rrs with the keys */ +static void +signit(ldns_rr_list* rrs, ldns_key_list* keys) +{ + ldns_rr_list* rrset; + ldns_rr_list* sigs; + + while(ldns_rr_list_rr_count(rrs) > 0) { + rrset = ldns_rr_list_pop_rrset(rrs); + if(!rrset) fatal_exit("copy alloc failure"); + sigs = ldns_sign_public(rrset, keys); + if(!sigs) fatal_exit("failed to sign"); + ldns_rr_list_print(stdout, rrset); + ldns_rr_list_print(stdout, sigs); + printf("\n"); + ldns_rr_list_free(rrset); + ldns_rr_list_free(sigs); + } +} + +/** process keys and signit */ +static void +process_keys(int argc, char* argv[]) +{ + ldns_rr_list* rrs; + ldns_key_list* keys; + struct keysets settings; + log_assert(argc == 6); + + parse_cmdline(argv, &settings); + keys = read_keys(1, argv+5, &settings); + rrs = read_rrs(stdin); + signit(rrs, keys); + + ldns_rr_list_deep_free(rrs); + ldns_key_list_free(keys); +} + +/** process nsec3 params and perform hashing */ +static void +process_nsec3(int argc, char* argv[]) +{ + char line[10240]; + ldns_rdf* salt; + ldns_rdf* in, *out; + ldns_status status; + status = ldns_str2rdf_nsec3_salt(&salt, argv[5]); + if(status != LDNS_STATUS_OK) + fatal_exit("Could not parse salt %s: %s", argv[5], + ldns_get_errorstr_by_id(status)); + log_assert(argc == 6); + while(fgets(line, (int)sizeof(line), stdin)) { + if(strlen(line) > 0) + line[strlen(line)-1] = 0; /* remove trailing newline */ + if(line[0]==0) + continue; + status = ldns_str2rdf_dname(&in, line); + if(status != LDNS_STATUS_OK) + fatal_exit("Could not parse name %s: %s", line, + ldns_get_errorstr_by_id(status)); + ldns_rdf_print(stdout, in); + printf(" -> "); + /* arg 3 is flags, unused */ + out = ldns_nsec3_hash_name(in, (uint8_t)atoi(argv[2]), + (uint16_t)atoi(argv[4]), + ldns_rdf_data(salt)[0], ldns_rdf_data(salt)+1); + if(!out) + fatal_exit("Could not hash %s", line); + ldns_rdf_print(stdout, out); + printf("\n"); + ldns_rdf_deep_free(in); + ldns_rdf_deep_free(out); + } + ldns_rdf_deep_free(salt); +} + +/** main program */ +int main(int argc, char* argv[]) +{ + log_init(NULL, 0, NULL); + if(argc != 6) { + usage(); + } + if(strcmp(argv[1], "NSEC3PARAM") == 0) { + process_nsec3(argc, argv); + return 0; + } + process_keys(argc, argv); + return 0; +} diff --git a/testcode/streamtcp.c b/testcode/streamtcp.c new file mode 100644 index 00000000000..dbdf1408c1d --- /dev/null +++ b/testcode/streamtcp.c @@ -0,0 +1,417 @@ +/* + * testcode/streamtcp.c - debug program perform multiple DNS queries on tcp. + * + * Copyright (c) 2008, 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This program performs multiple DNS queries on a TCP stream. + */ + +#include "config.h" +#ifdef HAVE_GETOPT_H +#include +#endif +#include +#include +#include "util/locks.h" +#include "util/log.h" +#include "util/net_help.h" +#include "util/data/msgencode.h" +#include "util/data/msgparse.h" +#include "util/data/msgreply.h" +#include "util/data/dname.h" +#include + +#ifndef PF_INET6 +/** define in case streamtcp is compiled on legacy systems */ +#define PF_INET6 10 +#endif + +/** usage information for streamtcp */ +static void usage(char* argv[]) +{ + printf("usage: %s [options] name type class ...\n", argv[0]); + printf(" sends the name-type-class queries over TCP.\n"); + printf("-f server what ipaddr@portnr to send the queries to\n"); + printf("-u use UDP. No retries are attempted.\n"); + printf("-n do not wait for an answer.\n"); + printf("-s use ssl\n"); + printf("-h this help text\n"); + exit(1); +} + +/** open TCP socket to svr */ +static int +open_svr(const char* svr, int udp) +{ + struct sockaddr_storage addr; + socklen_t addrlen; + int fd = -1; + /* svr can be ip@port */ + memset(&addr, 0, sizeof(addr)); + if(!extstrtoaddr(svr, &addr, &addrlen)) { + printf("fatal: bad server specs '%s'\n", svr); + exit(1); + } + fd = socket(addr_is_ip6(&addr, addrlen)?PF_INET6:PF_INET, + udp?SOCK_DGRAM:SOCK_STREAM, 0); + if(fd == -1) { +#ifndef USE_WINSOCK + perror("socket() error"); +#else + printf("socket: %s\n", wsa_strerror(WSAGetLastError())); +#endif + exit(1); + } + if(connect(fd, (struct sockaddr*)&addr, addrlen) < 0) { +#ifndef USE_WINSOCK + perror("connect() error"); +#else + printf("connect: %s\n", wsa_strerror(WSAGetLastError())); +#endif + exit(1); + } + return fd; +} + +/** write a query over the TCP fd */ +static void +write_q(int fd, int udp, SSL* ssl, ldns_buffer* buf, uint16_t id, + const char* strname, const char* strtype, const char* strclass) +{ + struct query_info qinfo; + ldns_rdf* rdf; + uint16_t len; + /* qname */ + rdf = ldns_dname_new_frm_str(strname); + if(!rdf) { + printf("cannot parse query name: '%s'\n", strname); + exit(1); + } + qinfo.qname = memdup(ldns_rdf_data(rdf), ldns_rdf_size(rdf)); + (void)dname_count_size_labels(qinfo.qname, &qinfo.qname_len); + ldns_rdf_deep_free(rdf); + if(!qinfo.qname) fatal_exit("out of memory"); + + /* qtype and qclass */ + qinfo.qtype = ldns_get_rr_type_by_name(strtype); + qinfo.qclass = ldns_get_rr_class_by_name(strclass); + + /* make query */ + qinfo_query_encode(buf, &qinfo); + ldns_buffer_write_u16_at(buf, 0, id); + ldns_buffer_write_u16_at(buf, 2, BIT_RD); + + if(1) { + /* add EDNS DO */ + struct edns_data edns; + memset(&edns, 0, sizeof(edns)); + edns.edns_present = 1; + edns.bits = EDNS_DO; + edns.udp_size = 4096; + attach_edns_record(buf, &edns); + } + + /* send it */ + if(!udp) { + len = (uint16_t)ldns_buffer_limit(buf); + len = htons(len); + if(ssl) { + if(SSL_write(ssl, (void*)&len, (int)sizeof(len)) <= 0) { + log_crypto_err("cannot SSL_write"); + exit(1); + } + } else { + if(send(fd, (void*)&len, sizeof(len), 0) < + (ssize_t)sizeof(len)){ +#ifndef USE_WINSOCK + perror("send() len failed"); +#else + printf("send len: %s\n", + wsa_strerror(WSAGetLastError())); +#endif + exit(1); + } + } + } + if(ssl) { + if(SSL_write(ssl, (void*)ldns_buffer_begin(buf), + (int)ldns_buffer_limit(buf)) <= 0) { + log_crypto_err("cannot SSL_write"); + exit(1); + } + } else { + if(send(fd, (void*)ldns_buffer_begin(buf), + ldns_buffer_limit(buf), 0) < + (ssize_t)ldns_buffer_limit(buf)) { +#ifndef USE_WINSOCK + perror("send() data failed"); +#else + printf("send data: %s\n", wsa_strerror(WSAGetLastError())); +#endif + exit(1); + } + } + + free(qinfo.qname); +} + +/** receive DNS datagram over TCP and print it */ +static void +recv_one(int fd, int udp, SSL* ssl, ldns_buffer* buf) +{ + uint16_t len; + ldns_pkt* pkt; + ldns_status status; + if(!udp) { + if(ssl) { + if(SSL_read(ssl, (void*)&len, (int)sizeof(len)) <= 0) { + log_crypto_err("could not SSL_read"); + exit(1); + } + } else { + if(recv(fd, (void*)&len, sizeof(len), 0) < + (ssize_t)sizeof(len)) { +#ifndef USE_WINSOCK + perror("read() len failed"); +#else + printf("read len: %s\n", + wsa_strerror(WSAGetLastError())); +#endif + exit(1); + } + } + len = ntohs(len); + ldns_buffer_clear(buf); + ldns_buffer_set_limit(buf, len); + if(ssl) { + int r = SSL_read(ssl, (void*)ldns_buffer_begin(buf), + (int)len); + if(r <= 0) { + log_crypto_err("could not SSL_read"); + exit(1); + } + if(r != (int)len) + fatal_exit("ssl_read %d of %d", r, len); + } else { + if(recv(fd, (void*)ldns_buffer_begin(buf), len, 0) < + (ssize_t)len) { +#ifndef USE_WINSOCK + perror("read() data failed"); +#else + printf("read data: %s\n", + wsa_strerror(WSAGetLastError())); +#endif + exit(1); + } + } + } else { + ssize_t l; + ldns_buffer_clear(buf); + if((l=recv(fd, (void*)ldns_buffer_begin(buf), + ldns_buffer_capacity(buf), 0)) < 0) { +#ifndef USE_WINSOCK + perror("read() data failed"); +#else + printf("read data: %s\n", + wsa_strerror(WSAGetLastError())); +#endif + exit(1); + } + ldns_buffer_set_limit(buf, (size_t)l); + len = (size_t)l; + } + printf("\nnext received packet\n"); + log_buf(0, "data", buf); + + status = ldns_wire2pkt(&pkt, ldns_buffer_begin(buf), len); + if(status != LDNS_STATUS_OK) { + printf("could not parse incoming packet: %s\n", + ldns_get_errorstr_by_id(status)); + log_buf(0, "data was", buf); + exit(1); + } + ldns_pkt_print(stdout, pkt); + ldns_pkt_free(pkt); +} + +/** send the TCP queries and print answers */ +static void +send_em(const char* svr, int udp, int usessl, int noanswer, int num, char** qs) +{ + ldns_buffer* buf = ldns_buffer_new(65553); + int fd = open_svr(svr, udp); + int i; + SSL_CTX* ctx = NULL; + SSL* ssl = NULL; + if(!buf) fatal_exit("out of memory"); + if(usessl) { + ctx = connect_sslctx_create(NULL, NULL, NULL); + if(!ctx) fatal_exit("cannot create ssl ctx"); + ssl = outgoing_ssl_fd(ctx, fd); + if(!ssl) fatal_exit("cannot create ssl"); + while(1) { + int r; + ERR_clear_error(); + if( (r=SSL_do_handshake(ssl)) == 1) + break; + r = SSL_get_error(ssl, r); + if(r != SSL_ERROR_WANT_READ && + r != SSL_ERROR_WANT_WRITE) { + log_crypto_err("could not ssl_handshake"); + exit(1); + } + } + if(1) { + X509* x = SSL_get_peer_certificate(ssl); + if(!x) printf("SSL: no peer certificate\n"); + else { + X509_print_fp(stdout, x); + X509_free(x); + } + } + } + for(i=0; i ssh $*" + ssh $* +} + +# Compile and run NSD on platforms +function dotest() +# parameters: +# host is name of ssh host +# dir is directory of nsd trunk on host +{ + echo "$1 begin on "`date` | tee -a $REPORT_FILE + + DISABLE="" + if test $IP6 = no; then + DISABLE="--disable-ipv6" + fi + if test x$LDNS != x; then + DISABLE="--with-ldns=$LDNS $DISABLE" + fi + if test x$LIBEVENT != x; then + DISABLE="--with-libevent=$LIBEVENT $DISABLE" + fi + + cat >makeconf.mak.$$ << EOF +#configure: configure.ac +# $AC_CMD +# touch configure +Makefile: Makefile.in #configure + ./configure $CONFIGURE_FLAGS $DISABLE + touch Makefile +EOF + scp makeconf.mak.$$ $1:$2 + # determine make to use + tempx=`ssh $1 "cd $2; which gmake"` + MAKE_CMD=`ssh $1 "cd $2; if test -f '$tempx'; then echo $tempx; else echo $MAKE_CMD; fi"` + + if test $SVN = yes; then + echossh $1 "cd $2; svn up" + echossh $1 "cd $2; $MAKE_CMD -f makeconf.mak.$$ configure" + else + # svn and autoconf locally + echo "fake svn via svnexport, tar, autoconf, bison, flex." + svn export svn+ssh://open.nlnetlabs.nl/svn/nsd/trunk unbound_ttt + (cd unbound_ttt; $AC_CMD; rm -r autom4te* .c-mode-rc.el .cvsignore) + if test $FIXCONFIGURE = yes; then + echo fixing up configure length test. + (cd unbound_ttt; mv configure oldconf; sed -e 's?while (test "X"?lt_cv_sys_max_cmd_len=65500; echo skip || while (test "X"?' configure; chmod +x ./configure) + fi + du unbound_ttt + rsync -vrcpz --rsync-path=/home/wouter/bin/rsync unbound_ttt $1:unbound_ttt + # tar czf unbound_ttt.tgz unbound_ttt + rm -rf unbound_ttt + # ls -al unbound_ttt.tgz + # scp unbound_ttt.tgz $1:unbound_ttt.tar.gz + # rm unbound_ttt.tgz + # echossh $1 "gtar xzf unbound_ttt.tar.gz && rm unbound_ttt.tar.gz" + fi + echossh $1 "cd $2; $MAKE_CMD -f makeconf.mak.$$ Makefile" + echossh $1 "cd $2; $MAKE_CMD all tests" + echossh $1 "cd $2; $MAKE_CMD doc" + if test $RUN_TEST = yes; then + echossh $1 "cd $2; bash testcode/do-tests.sh" + echossh $1 "cd $2/testdata; sh ../testcode/mini_tpkg.sh -q report" | tee -a $REPORT_FILE + fi + echossh $1 "cd $2; rm -f makeconf.mak.$$" + rm -f makeconf.mak.$$ + echo "$1 end on "`date` | tee -a $REPORT_FILE +} + +echo "on "`date`" by $USER." > $REPORT_FILE +echo "on "`date`" by $USER." > $LOG_FILE + +# read host names +declare -a hostname desc dir vars +IFS=' ' +i=0 +while read a b c d; do + if echo $a | grep "^#" >/dev/null; then + continue # skip it + fi + # append after arrays + hostname[$i]=$a + desc[$i]=$b + dir[$i]=$c + vars[$i]=$d + i=$(($i+1)) +done <$HOST_FILE +echo "testing on $i hosts" + +# do the test +for((i=0; i<${#hostname[*]}; i=$i+1)); do + if echo ${hostname[$i]} | grep "^#" >/dev/null; then + continue # skip it + fi + # echo "hostname=[${hostname[$i]}]" + # echo "desc=[${desc[$i]}]" + # echo "dir=[${dir[$i]}]" + # echo "vars=[${vars[$i]}]" + AC_CMD="libtoolize -c --force; autoconf && autoheader" + MAKE_CMD="make" + SVN=yes + IP6=yes + FIXCONFIGURE=no + RUN_TEST=yes + LDNS= + LIBEVENT= + eval ${vars[$i]} + echo "*** ${hostname[$i]} ${desc[$i]} ***" | tee -a $LOG_FILE | tee -a $REPORT_FILE + dotest ${hostname[$i]} ${dir[$i]} 2>&1 | tee -a $LOG_FILE +done + +echo "done" diff --git a/testcode/testbed.txt b/testcode/testbed.txt new file mode 100644 index 00000000000..b0175049eec --- /dev/null +++ b/testcode/testbed.txt @@ -0,0 +1,38 @@ +Testbed.sh help page. + +Testbed helps in running the test packages (using tpkg(1)) on several systems. +The script is specially written for unbound (edit it to change to different +software). It is licensed BSD. + +The hosts to run on are listed in host_file.. You need to have +public-key authorized ssh access to these systems (or type your password lots +and lots of times). The host_file describes the directories and environment +of each host. You need only user-level access to the host. + +The host_file is very restrictive in formatting. Comments are lines starting +with the # mark. The entries must be separated by tabs. Please list the +hostnamedescriptioncheckoutdirvariables + +hostname: network hostname to ssh to. +desc: pretty text to describe the machine architecture. +checkoutdir: directory on the remote host where a svn checkout is present. +variables: zero or more variables separated by spaces. BLA=value BAR=val. + +Only important variable for unbound is the LDNS= variable that if present +forces --with-ldns= to be passed to ./configure. In case LDNS is not +installed on the system itself, but present somewhere else. + +You can also set LIBEVENT= for the libevent directory, if it is +installed in a nonstandard location. + +*** Running the testbed + +Run by executing the script. It will take all the hosts from the file in +turn and update the svn directory there, possible autoreconf if necessary, +possibly ./configure if necessary, make the executables. +Then it will run the testcode/do-tests script. This script should execute +the tests that this host is capable of running. + +in testdata/testbed.log has a line-by-line log. See your make errors here. +in testdata/testbed.report has only the tpkg reports. Summary. + diff --git a/testcode/testbound.c b/testcode/testbound.c new file mode 100644 index 00000000000..05982849cc2 --- /dev/null +++ b/testcode/testbound.c @@ -0,0 +1,445 @@ +/* + * testcode/testbound.c - test program for unbound. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +/** + * \file + * Exits with code 1 on a failure. 0 if all unit tests are successfull. + */ + +#include "config.h" +#include "testcode/ldns-testpkts.h" +#include "testcode/replay.h" +#include "testcode/fake_event.h" +#include "daemon/remote.h" +#include "util/config_file.h" + +/** signal that this is a testbound compile */ +#define unbound_testbound 1 +/** + * include the main program from the unbound daemon. + * rename main to daemon_main to call it + */ +#define main daemon_main +#include "daemon/unbound.c" +#undef main + +/** maximum line length for lines in the replay file. */ +#define MAX_LINE_LEN 1024 +/** config files (removed at exit) */ +static struct config_strlist* cfgfiles = NULL; + +/** give commandline usage for testbound. */ +static void +testbound_usage() +{ + printf("usage: testbound [options]\n"); + printf("\ttest the unbound daemon.\n"); + printf("-h this help\n"); + printf("-p file playback text file\n"); + printf("-2 detect SHA256 support (exit code 0 or 1)\n"); + printf("-g detect GOST support (exit code 0 or 1)\n"); + printf("-e detect ECDSA support (exit code 0 or 1)\n"); + printf("-s testbound self-test - unit test of testbound parts.\n"); + printf("-o str unbound commandline options separated by spaces.\n"); + printf("Version %s\n", PACKAGE_VERSION); + printf("BSD licensed, see LICENSE file in source package.\n"); + printf("Report bugs to %s.\n", PACKAGE_BUGREPORT); +} + +/** Max number of arguments to pass to unbound. */ +#define MAXARG 100 + +/** + * Add options from string to passed argc. splits on whitespace. + * @param args: the option argument, "-v -p 12345" or so. + * @param pass_argc: ptr to the argc for unbound. Modified. + * @param pass_argv: the argv to pass to unbound. Modified. + */ +static void +add_opts(const char* args, int* pass_argc, char* pass_argv[]) +{ + const char *p = args, *np; + size_t len; + while(p && isspace((int)*p)) + p++; + while(p && *p) { + /* find location of next string and length of this one */ + if((np = strchr(p, ' '))) + len = (size_t)(np-p); + else len = strlen(p); + /* allocate and copy option */ + if(*pass_argc >= MAXARG-1) + fatal_exit("too many arguments: '%s'", p); + pass_argv[*pass_argc] = (char*)malloc(len+1); + if(!pass_argv[*pass_argc]) + fatal_exit("add_opts: out of memory"); + memcpy(pass_argv[*pass_argc], p, len); + pass_argv[*pass_argc][len] = 0; + (*pass_argc)++; + /* go to next option */ + p = np; + while(p && isspace((int)*p)) + p++; + } +} + +/** pretty print commandline for unbound in this test */ +static void +echo_cmdline(int argc, char* argv[]) +{ + int i; + fprintf(stderr, "testbound is starting:"); + for(i=0; ititle); + return scen; +} + +/** remove config file at exit */ +void remove_configfile(void) +{ + struct config_strlist* p; + for(p=cfgfiles; p; p=p->next) + unlink(p->str); + config_delstrlist(cfgfiles); + cfgfiles = NULL; +} + +/** + * Main fake event test program. Setup, teardown and report errors. + * @param argc: arg count. + * @param argv: array of commandline arguments. + * @return program failure if test fails. + */ +int +main(int argc, char* argv[]) +{ + int c, res; + int pass_argc = 0; + char* pass_argv[MAXARG]; + char* playback_file = NULL; + int init_optind = optind; + char* init_optarg = optarg; + struct replay_scenario* scen = NULL; + + /* we do not want the test to depend on the timezone */ + (void)putenv("TZ=UTC"); + + log_init(NULL, 0, NULL); + /* determine commandline options for the daemon */ + pass_argc = 1; + pass_argv[0] = "unbound"; + add_opts("-d", &pass_argc, pass_argv); + while( (c=getopt(argc, argv, "2egho:p:s")) != -1) { + switch(c) { + case 's': + free(pass_argv[1]); + testbound_selftest(); + printf("selftest successful\n"); + exit(0); + case '2': +#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2) + printf("SHA256 supported\n"); + exit(0); +#else + printf("SHA256 not supported\n"); + exit(1); +#endif + break; + case 'e': +#if defined(USE_ECDSA) + printf("ECDSA supported\n"); + exit(0); +#else + printf("ECDSA not supported\n"); + exit(1); +#endif + break; + case 'g': +#ifdef USE_GOST + if(ldns_key_EVP_load_gost_id()) { + printf("GOST supported\n"); + exit(0); + } else { + printf("GOST not supported\n"); + exit(1); + } +#else + printf("GOST not supported\n"); + exit(1); +#endif + break; + case 'p': + playback_file = optarg; + break; + case 'o': + add_opts(optarg, &pass_argc, pass_argv); + break; + case '?': + case 'h': + default: + testbound_usage(); + return 1; + } + } + argc -= optind; + argv += optind; + if(argc != 0) { + testbound_usage(); + return 1; + } + log_info("Start of %s testbound program.", PACKAGE_STRING); + if(atexit(&remove_configfile) != 0) + fatal_exit("atexit() failed: %s", strerror(errno)); + + /* setup test environment */ + scen = setup_playback(playback_file, &pass_argc, pass_argv); + /* init fake event backend */ + fake_event_init(scen); + + pass_argv[pass_argc] = NULL; + echo_cmdline(pass_argc, pass_argv); + + /* reset getopt processing */ + optind = init_optind; + optarg = init_optarg; + + /* run the normal daemon */ + res = daemon_main(pass_argc, pass_argv); + + fake_event_cleanup(); + for(c=1; c +#include "util/log.h" +#include "util/data/dname.h" +#include "testcode/unitmain.h" +#include "validator/val_anchor.h" + +/** test empty set */ +static void +test_anchor_empty(struct val_anchors* a) +{ + uint16_t c = LDNS_RR_CLASS_IN; + unit_assert(anchors_lookup(a, (uint8_t*)"\000", 1, c) == NULL); + unit_assert(anchors_lookup(a, (uint8_t*)"\003com\000", 5, c) == NULL); + unit_assert(anchors_lookup(a, + (uint8_t*)"\007example\003com\000", 11, c) == NULL); + unit_assert(anchors_lookup(a, (uint8_t*)"\002nl\000", 4, c) == NULL); + unit_assert(anchors_lookup(a, + (uint8_t*)"\004labs\002nl\000", 9, c) == NULL); + unit_assert(anchors_lookup(a, + (uint8_t*)"\004fabs\002nl\000", 9, c) == NULL); +} + +/** test set of one anchor */ +static void +test_anchor_one(ldns_buffer* buff, struct val_anchors* a) +{ + struct trust_anchor* ta; + uint16_t c = LDNS_RR_CLASS_IN; + unit_assert(anchor_store_str(a, buff, + "nl. DS 42860 5 1 14D739EB566D2B1A5E216A0BA4D17FA9B038BE4A")); + unit_assert(anchors_lookup(a, (uint8_t*)"\000", 1, c) == NULL); + unit_assert(anchors_lookup(a, (uint8_t*)"\003com\000", 5, c) == NULL); + unit_assert(anchors_lookup(a, + (uint8_t*)"\007example\003com\000", 11, c) == NULL); + + unit_assert((ta=anchors_lookup(a, + (uint8_t*)"\002nl\000", 4, c)) != NULL); + lock_basic_unlock(&ta->lock); + + unit_assert((ta=anchors_lookup(a, + (uint8_t*)"\004labs\002nl\000", 9, c)) != NULL); + lock_basic_unlock(&ta->lock); + + unit_assert((ta=anchors_lookup(a, + (uint8_t*)"\004fabs\002nl\000", 9, c)) != NULL); + lock_basic_unlock(&ta->lock); + + unit_assert(anchors_lookup(a, (uint8_t*)"\002oo\000", 4, c) == NULL); +} + +/** test with several anchors */ +static void +test_anchors(ldns_buffer* buff, struct val_anchors* a) +{ + struct trust_anchor* ta; + uint16_t c = LDNS_RR_CLASS_IN; + unit_assert(anchor_store_str(a, buff, + "labs.nl. DS 42860 5 1 14D739EB566D2B1A5E216A0BA4D17FA9B038BE4A")); + unit_assert(anchors_lookup(a, (uint8_t*)"\000", 1, c) == NULL); + unit_assert(anchors_lookup(a, (uint8_t*)"\003com\000", 5, c) == NULL); + unit_assert(anchors_lookup(a, + (uint8_t*)"\007example\003com\000", 11, c) == NULL); + + unit_assert(ta = anchors_lookup(a, (uint8_t*)"\002nl\000", 4, c)); + unit_assert(query_dname_compare(ta->name, (uint8_t*)"\002nl\000")==0); + lock_basic_unlock(&ta->lock); + + unit_assert(ta = anchors_lookup(a, + (uint8_t*)"\004labs\002nl\000", 9, c)); + unit_assert(query_dname_compare(ta->name, + (uint8_t*)"\004labs\002nl\000") == 0); + lock_basic_unlock(&ta->lock); + + unit_assert(ta = anchors_lookup(a, + (uint8_t*)"\004fabs\002nl\000", 9, c)); + unit_assert(query_dname_compare(ta->name, + (uint8_t*)"\002nl\000") == 0); + lock_basic_unlock(&ta->lock); + + unit_assert(anchors_lookup(a, (uint8_t*)"\002oo\000", 4, c) == NULL); +} + +void anchors_test(void) +{ + ldns_buffer* buff = ldns_buffer_new(65800); + struct val_anchors* a; + unit_show_feature("trust anchor store"); + unit_assert(a = anchors_create()); + ldns_buffer_flip(buff); + test_anchor_empty(a); + test_anchor_one(buff, a); + test_anchors(buff, a); + anchors_delete(a); + ldns_buffer_free(buff); +} diff --git a/testcode/unitdname.c b/testcode/unitdname.c new file mode 100644 index 00000000000..3dcd8e43c20 --- /dev/null +++ b/testcode/unitdname.c @@ -0,0 +1,862 @@ +/* + * testcode/unitdname.c - unit test for dname routines. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +/** + * \file + * Calls dname unit tests. Exits with code 1 on a failure. + */ + +#include "config.h" +#include +#include +#include "util/log.h" +#include "testcode/unitmain.h" +#include "util/data/dname.h" + +/** put dname into buffer */ +static ldns_buffer* +dname_to_buf(ldns_buffer* b, const char* str) +{ + ldns_rdf* rdf; + ldns_status status; + ldns_buffer_clear(b); + rdf = ldns_dname_new_frm_str(str); + status = ldns_dname2buffer_wire(b, rdf); + if(status != LDNS_STATUS_OK) + fatal_exit("%s ldns: %s", __func__, + ldns_get_errorstr_by_id(status)); + ldns_rdf_deep_free(rdf); + ldns_buffer_flip(b); + return b; +} + +/** test query_dname_len function */ +static void +dname_test_qdl(ldns_buffer* buff) +{ + unit_show_func("util/data/dname.c", "query_dname_len"); + unit_assert( query_dname_len(buff) == 0); + unit_assert( query_dname_len(dname_to_buf(buff, ".")) == 1 ); + unit_assert( query_dname_len(dname_to_buf(buff, "bla.foo.")) == 9 ); + unit_assert( query_dname_len(dname_to_buf(buff, "x.y.z.example.com." + )) == 19 ); +} + +/** test query_dname_tolower */ +static void +dname_test_qdtl(ldns_buffer* buff) +{ + unit_show_func("util/data/dname.c", "query_dname_tolower"); + ldns_buffer_write_at(buff, 0, "\012abCDeaBCde\003cOm\000", 16); + query_dname_tolower(ldns_buffer_begin(buff)); + unit_assert( memcmp(ldns_buffer_begin(buff), + "\012abcdeabcde\003com\000", 16) == 0); + + ldns_buffer_write_at(buff, 0, "\001+\012abC{e-ZYXe\003NET\000", 18); + query_dname_tolower(ldns_buffer_begin(buff)); + unit_assert( memcmp(ldns_buffer_begin(buff), + "\001+\012abc{e-zyxe\003net\000", 18) == 0); + + ldns_buffer_write_at(buff, 0, "\000", 1); + query_dname_tolower(ldns_buffer_begin(buff)); + unit_assert( memcmp(ldns_buffer_begin(buff), "\000", 1) == 0); + + ldns_buffer_write_at(buff, 0, "\002NL\000", 4); + query_dname_tolower(ldns_buffer_begin(buff)); + unit_assert( memcmp(ldns_buffer_begin(buff), "\002nl\000", 4) == 0); +} + +/** test query_dname_compare */ +static void +dname_test_query_dname_compare(void) +{ + unit_show_func("util/data/dname.c", "query_dname_compare"); + unit_assert(query_dname_compare((uint8_t*)"", (uint8_t*)"") == 0); + unit_assert(query_dname_compare((uint8_t*)"\001a", + (uint8_t*)"\001a") == 0); + unit_assert(query_dname_compare((uint8_t*)"\003abc\001a", + (uint8_t*)"\003abc\001a") == 0); + unit_assert(query_dname_compare((uint8_t*)"\003aBc\001a", + (uint8_t*)"\003AbC\001A") == 0); + unit_assert(query_dname_compare((uint8_t*)"\003abc", + (uint8_t*)"\003abc\001a") == -1); + unit_assert(query_dname_compare((uint8_t*)"\003abc\001a", + (uint8_t*)"\003abc") == +1); + unit_assert(query_dname_compare((uint8_t*)"\003abc\001a", + (uint8_t*)"") == +1); + unit_assert(query_dname_compare((uint8_t*)"", + (uint8_t*)"\003abc\001a") == -1); + unit_assert(query_dname_compare((uint8_t*)"\003abc\001a", + (uint8_t*)"\003xxx\001a") == -1); + unit_assert(query_dname_compare((uint8_t*)"\003axx\001a", + (uint8_t*)"\003abc\001a") == 1); + unit_assert(query_dname_compare((uint8_t*)"\003abc\001a", + (uint8_t*)"\003abc\001Z") == -1); + unit_assert(query_dname_compare((uint8_t*)"\003abc\001Z", + (uint8_t*)"\003abc\001a") == 1); +} + +/** test dname_count_labels */ +static void +dname_test_count_labels(void) +{ + unit_show_func("util/data/dname.c", "dname_count_labels"); + unit_assert(dname_count_labels((uint8_t*)"") == 1); + unit_assert(dname_count_labels((uint8_t*)"\003com") == 2); + unit_assert(dname_count_labels((uint8_t*)"\003org") == 2); + unit_assert(dname_count_labels((uint8_t*)"\007example\003com") == 3); + unit_assert(dname_count_labels((uint8_t*)"\003bla\007example\003com") + == 4); +} + +/** test dname_count_size_labels */ +static void +dname_test_count_size_labels(void) +{ + size_t sz = 0; + unit_show_func("util/data/dname.c", "dname_count_size_labels"); + unit_assert(dname_count_size_labels((uint8_t*)"", &sz) == 1); + unit_assert(sz == 1); + unit_assert(dname_count_size_labels((uint8_t*)"\003com", &sz) == 2); + unit_assert(sz == 5); + unit_assert(dname_count_size_labels((uint8_t*)"\003org", &sz) == 2); + unit_assert(sz == 5); + unit_assert(dname_count_size_labels((uint8_t*)"\007example\003com", + &sz) == 3); + unit_assert(sz == 13); + unit_assert(dname_count_size_labels((uint8_t*)"\003bla\007example" + "\003com", &sz) == 4); + unit_assert(sz == 17); +} + + +/** test pkt_dname_len */ +static void +dname_test_pkt_dname_len(ldns_buffer* buff) +{ + unit_show_func("util/data/dname.c", "pkt_dname_len"); + ldns_buffer_clear(buff); + ldns_buffer_write(buff, "\000", 1); + ldns_buffer_flip(buff); + unit_assert( pkt_dname_len(buff) == 1 ); + unit_assert( ldns_buffer_position(buff) == 1); + + ldns_buffer_clear(buff); + ldns_buffer_write(buff, "\003org\000", 5); + ldns_buffer_flip(buff); + unit_assert( pkt_dname_len(buff) == 5 ); + unit_assert( ldns_buffer_position(buff) == 5); + + ldns_buffer_clear(buff); + ldns_buffer_write(buff, "\002os\007example\003org\000", 16); + ldns_buffer_flip(buff); + unit_assert( pkt_dname_len(buff) == 16 ); + unit_assert( ldns_buffer_position(buff) == 16); + + /* invalid compression pointer: to self */ + ldns_buffer_clear(buff); + ldns_buffer_write(buff, "\300\000os\007example\003org\000", 17); + ldns_buffer_flip(buff); + unit_assert( pkt_dname_len(buff) == 0 ); + + /* valid compression pointer */ + ldns_buffer_clear(buff); + ldns_buffer_write(buff, "\003com\000\040\300\000", 8); + ldns_buffer_flip(buff); + ldns_buffer_set_position(buff, 6); + unit_assert( pkt_dname_len(buff) == 5 ); + unit_assert( ldns_buffer_position(buff) == 8); + + /* unknown label type */ + ldns_buffer_clear(buff); + ldns_buffer_write(buff, "\002os\107example\003org\000", 16); + ldns_buffer_flip(buff); + unit_assert( pkt_dname_len(buff) == 0 ); + + /* label too long */ + ldns_buffer_clear(buff); + ldns_buffer_write(buff, "\002os\047example\003org\000", 16); + ldns_buffer_flip(buff); + unit_assert( pkt_dname_len(buff) == 0 ); + + /* label exceeds packet */ + ldns_buffer_clear(buff); + ldns_buffer_write(buff, "\002os\007example\007org\004", 16); + ldns_buffer_flip(buff); + unit_assert( pkt_dname_len(buff) == 0 ); + + /* name very long */ + ldns_buffer_clear(buff); + ldns_buffer_write(buff, + "\020a1cdef5555544444" + "\020a2cdef5555544444" + "\020a3cdef5555544444" + "\020a4cdef5555544444" + "\020a5cdef5555544444" + "\020a6cdef5555544444" + "\020a7cdef5555544444" + "\020a8cdef5555544444" + "\020a9cdef5555544444" + "\020aAcdef5555544444" + "\020aBcdef5555544444" + "\020aCcdef5555544444" + "\020aDcdef5555544444" + "\020aEcdef5555544444" /* 238 up to here */ + "\007aabbccd" /* 246 up to here */ + "\007example\000" /* 255 to here */ + , 255); + ldns_buffer_flip(buff); + unit_assert( pkt_dname_len(buff) == 255 ); + unit_assert( ldns_buffer_position(buff) == 255); + + /* name too long */ + ldns_buffer_clear(buff); + ldns_buffer_write(buff, + "\020a1cdef5555544444" + "\020a2cdef5555544444" + "\020a3cdef5555544444" + "\020a4cdef5555544444" + "\020a5cdef5555544444" + "\020a6cdef5555544444" + "\020a7cdef5555544444" + "\020a8cdef5555544444" + "\020a9cdef5555544444" + "\020aAcdef5555544444" + "\020aBcdef5555544444" + "\020aCcdef5555544444" + "\020aXcdef5555544444" + "\020aXcdef5555544444" + "\020aXcdef5555544444" + "\020aDcdef5555544444" + "\020aEcdef5555544444" /* 238 up to here */ + "\007aabbccd" /* 246 up to here */ + "\007example\000" /* 255 to here */ + , 255); + ldns_buffer_flip(buff); + unit_assert( pkt_dname_len(buff) == 0 ); +} + +/** test dname_lab_cmp */ +static void +dname_test_dname_lab_cmp(void) +{ + int ml = 0; /* number of labels that matched exactly */ + unit_show_func("util/data/dname.c", "dname_lab_cmp"); + + /* test for equality succeeds */ + unit_assert(dname_lab_cmp((uint8_t*)"", 1, (uint8_t*)"", 1, &ml) == 0); + unit_assert(ml == 1); + unit_assert(dname_lab_cmp( + (uint8_t*)"\003net", 2, + (uint8_t*)"\003net", 2, + &ml) == 0); + unit_assert(ml == 2); + unit_assert(dname_lab_cmp( + (uint8_t*)"\007example\003net", 3, + (uint8_t*)"\007example\003net", 3, + &ml) == 0); + unit_assert(ml == 3); + unit_assert(dname_lab_cmp( + (uint8_t*)"\004test\007example\003net", 4, + (uint8_t*)"\004test\007example\003net", 4, + &ml) == 0); + unit_assert(ml == 4); + + /* root is smaller than anything else */ + unit_assert(dname_lab_cmp( + (uint8_t*)"", 1, + (uint8_t*)"\003net", 2, + &ml) == -1); + unit_assert(ml == 1); + unit_assert(dname_lab_cmp( + (uint8_t*)"\003net", 2, + (uint8_t*)"", 1, + &ml) == 1); + unit_assert(ml == 1); + unit_assert(dname_lab_cmp( + (uint8_t*)"", 1, + (uint8_t*)"\007example\003net", 3, + &ml) == -1); + unit_assert(ml == 1); + unit_assert(dname_lab_cmp( + (uint8_t*)"\007example\003net", 3, + (uint8_t*)"", 1, + &ml) == 1); + unit_assert(ml == 1); + + /* label length makes a difference */ + unit_assert(dname_lab_cmp( + (uint8_t*)"\004neta", 2, + (uint8_t*)"\003net", 2, + &ml) != 0); + unit_assert(ml == 1); + unit_assert(dname_lab_cmp( + (uint8_t*)"\002ne", 2, + (uint8_t*)"\004neta", 2, + &ml) != 0); + unit_assert(ml == 1); + + /* contents follow the zone apex */ + unit_assert(dname_lab_cmp( + (uint8_t*)"\003bla\007example\003net", 4, + (uint8_t*)"\007example\003net", 3, + &ml) == 1); + unit_assert(ml == 3); + unit_assert(dname_lab_cmp( + (uint8_t*)"\007example\003net", 3, + (uint8_t*)"\003bla\007example\003net", 4, + &ml) == -1); + unit_assert(ml == 3); + + /* label content makes a difference */ + unit_assert(dname_lab_cmp( + (uint8_t*)"\003aag\007example\003net", 4, + (uint8_t*)"\003bla\007example\003net", 4, + &ml) == -1); + unit_assert(ml == 3); + unit_assert(dname_lab_cmp( + (uint8_t*)"\003aag\007example\003net", 4, + (uint8_t*)"\003bla\007example\003net", 4, + &ml) == -1); + unit_assert(ml == 3); + unit_assert(dname_lab_cmp( + (uint8_t*)"\003bla\003aag\007example\003net", 5, + (uint8_t*)"\003aag\003bla\007example\003net", 5, + &ml) == -1); + unit_assert(ml == 3); + unit_assert(dname_lab_cmp( + (uint8_t*)"\02sn\003opt\003aag\007example\003net", 6, + (uint8_t*)"\02sn\003opt\003bla\007example\003net", 6, + &ml) == -1); + unit_assert(ml == 3); + + /* but lowercase/uppercase does not make a difference. */ + unit_assert(dname_lab_cmp( + (uint8_t*)"\003bLa\007examPLe\003net", 4, + (uint8_t*)"\003bla\007eXAmple\003nET", 4, + &ml) == 0); + unit_assert(ml == 4); +} + +/** test dname_subdomain_c */ +static void +dname_test_subdomain(void) +{ + unit_show_func("util/data/dname.c", "dname_subdomain"); + unit_assert(dname_subdomain_c( + (uint8_t*)"", + (uint8_t*)"")); + unit_assert(dname_subdomain_c( + (uint8_t*)"\003com", + (uint8_t*)"")); + unit_assert(!dname_subdomain_c( + (uint8_t*)"", + (uint8_t*)"\003com")); + unit_assert(dname_subdomain_c( + (uint8_t*)"\007example\003com", + (uint8_t*)"\003com")); + unit_assert(!dname_subdomain_c( + (uint8_t*)"\003com", + (uint8_t*)"\007example\003com")); + unit_assert(dname_subdomain_c( + (uint8_t*)"\007example\003com", + (uint8_t*)"")); + unit_assert(!dname_subdomain_c( + (uint8_t*)"\003net", + (uint8_t*)"\003com")); + unit_assert(!dname_subdomain_c( + (uint8_t*)"\003net", + (uint8_t*)"\003org")); + unit_assert(!dname_subdomain_c( + (uint8_t*)"\007example\003net", + (uint8_t*)"\003org")); + unit_assert(!dname_subdomain_c( + (uint8_t*)"\003net", + (uint8_t*)"\007example\003org")); +} + +/** test dname_strict_subdomain */ +static void +dname_test_strict_subdomain(void) +{ + unit_show_func("util/data/dname.c", "dname_strict_subdomain"); + unit_assert(!dname_strict_subdomain( + (uint8_t*)"", 1, + (uint8_t*)"", 1)); + unit_assert(dname_strict_subdomain( + (uint8_t*)"\003com", 2, + (uint8_t*)"", 1)); + unit_assert(!dname_strict_subdomain( + (uint8_t*)"", 1, + (uint8_t*)"\003com", 2)); + unit_assert(dname_strict_subdomain( + (uint8_t*)"\007example\003com", 3, + (uint8_t*)"\003com", 2)); + unit_assert(!dname_strict_subdomain( + (uint8_t*)"\003com", 2, + (uint8_t*)"\007example\003com", 3)); + unit_assert(dname_strict_subdomain( + (uint8_t*)"\007example\003com", 3, + (uint8_t*)"", 1)); + unit_assert(!dname_strict_subdomain( + (uint8_t*)"\003net", 2, + (uint8_t*)"\003com", 2)); + unit_assert(!dname_strict_subdomain( + (uint8_t*)"\003net", 2, + (uint8_t*)"\003org", 2)); + unit_assert(!dname_strict_subdomain( + (uint8_t*)"\007example\003net", 3, + (uint8_t*)"\003org", 2)); + unit_assert(!dname_strict_subdomain( + (uint8_t*)"\003net", 2, + (uint8_t*)"\007example\003org", 3)); +} + +/** test dname_is_root */ +static void +dname_test_isroot(void) +{ + unit_show_func("util/data/dname.c", "dname_isroot"); + unit_assert(dname_is_root((uint8_t*)"\000")); + unit_assert(!dname_is_root((uint8_t*)"\001a\000")); + unit_assert(!dname_is_root((uint8_t*)"\005abvcd\003com\000")); + /* malformed dname in this test, but should work */ + unit_assert(!dname_is_root((uint8_t*)"\077a\000")); + unit_assert(dname_is_root((uint8_t*)"\000")); +} + +/** test dname_remove_label */ +static void +dname_test_removelabel(void) +{ + uint8_t* orig = (uint8_t*)"\007example\003com\000"; + uint8_t* n = orig; + size_t l = 13; + unit_show_func("util/data/dname.c", "dname_remove_label"); + dname_remove_label(&n, &l); + unit_assert( n == orig+8 ); + unit_assert( l == 5 ); + dname_remove_label(&n, &l); + unit_assert( n == orig+12 ); + unit_assert( l == 1 ); + dname_remove_label(&n, &l); + unit_assert( n == orig+12 ); + unit_assert( l == 1 ); +} + +/** test dname_signame_label_count */ +static void +dname_test_sigcount(void) +{ + unit_show_func("util/data/dname.c", "dname_signame_label_count"); + unit_assert(dname_signame_label_count((uint8_t*)"\000") == 0); + unit_assert(dname_signame_label_count((uint8_t*)"\001*\000") == 0); + unit_assert(dname_signame_label_count((uint8_t*)"\003xom\000") == 1); + unit_assert(dname_signame_label_count( + (uint8_t*)"\001*\003xom\000") == 1); + unit_assert(dname_signame_label_count( + (uint8_t*)"\007example\003xom\000") == 2); + unit_assert(dname_signame_label_count( + (uint8_t*)"\001*\007example\003xom\000") == 2); + unit_assert(dname_signame_label_count( + (uint8_t*)"\003www\007example\003xom\000") == 3); + unit_assert(dname_signame_label_count( + (uint8_t*)"\001*\003www\007example\003xom\000") == 3); +} + +/** test dname_is_wild routine */ +static void +dname_test_iswild(void) +{ + unit_show_func("util/data/dname.c", "dname_iswild"); + unit_assert( !dname_is_wild((uint8_t*)"\000") ); + unit_assert( dname_is_wild((uint8_t*)"\001*\000") ); + unit_assert( !dname_is_wild((uint8_t*)"\003net\000") ); + unit_assert( dname_is_wild((uint8_t*)"\001*\003net\000") ); +} + +/** test dname_canonical_compare */ +static void +dname_test_canoncmp(void) +{ + unit_show_func("util/data/dname.c", "dname_canonical_compare"); + /* equality */ + unit_assert( dname_canonical_compare( + (uint8_t*)"\000", + (uint8_t*)"\000" + ) == 0); + unit_assert( dname_canonical_compare( + (uint8_t*)"\003net\000", + (uint8_t*)"\003net\000" + ) == 0); + unit_assert( dname_canonical_compare( + (uint8_t*)"\007example\003net\000", + (uint8_t*)"\007example\003net\000" + ) == 0); + unit_assert( dname_canonical_compare( + (uint8_t*)"\004test\007example\003net\000", + (uint8_t*)"\004test\007example\003net\000" + ) == 0); + + /* subdomains */ + unit_assert( dname_canonical_compare( + (uint8_t*)"\003com", + (uint8_t*)"\000" + ) == 1); + unit_assert( dname_canonical_compare( + (uint8_t*)"\000", + (uint8_t*)"\003com" + ) == -1); + unit_assert( dname_canonical_compare( + (uint8_t*)"\007example\003com", + (uint8_t*)"\003com" + ) == 1); + unit_assert( dname_canonical_compare( + (uint8_t*)"\003com", + (uint8_t*)"\007example\003com" + ) == -1); + unit_assert( dname_canonical_compare( + (uint8_t*)"\007example\003com", + (uint8_t*)"\000" + ) == 1); + unit_assert( dname_canonical_compare( + (uint8_t*)"\000", + (uint8_t*)"\007example\003com" + ) == -1); + + /* compare rightmost label */ + unit_assert( dname_canonical_compare( + (uint8_t*)"\003com", + (uint8_t*)"\003net" + ) == -1); + unit_assert( dname_canonical_compare( + (uint8_t*)"\003net", + (uint8_t*)"\003com" + ) == 1); + unit_assert( dname_canonical_compare( + (uint8_t*)"\003net", + (uint8_t*)"\003org" + ) == -1); + unit_assert( dname_canonical_compare( + (uint8_t*)"\007example\003net", + (uint8_t*)"\003org" + ) == -1); + unit_assert( dname_canonical_compare( + (uint8_t*)"\003org", + (uint8_t*)"\007example\003net" + ) == 1); + + /* label length makes a difference; but only if rest is equal */ + unit_assert( dname_canonical_compare( + (uint8_t*)"\004neta", + (uint8_t*)"\003net" + ) == 1); + unit_assert( dname_canonical_compare( + (uint8_t*)"\002ne", + (uint8_t*)"\004neta" + ) == -1); + + /* label content */ + unit_assert( dname_canonical_compare( + (uint8_t*)"\003aag\007example\003net", + (uint8_t*)"\003bla\007example\003net" + ) == -1); + unit_assert( dname_canonical_compare( + (uint8_t*)"\003bla\007example\003net", + (uint8_t*)"\003aag\007example\003net" + ) == 1); + unit_assert( dname_canonical_compare( + (uint8_t*)"\003bla\003aag\007example\003net", + (uint8_t*)"\003aag\003bla\007example\003net" + ) == -1); + unit_assert( dname_canonical_compare( + (uint8_t*)"\02sn\003opt\003aag\007example\003net", + (uint8_t*)"\02sn\003opt\003bla\007example\003net" + ) == -1); + + /* lowercase during compare */ + unit_assert( dname_canonical_compare( + (uint8_t*)"\003bLa\007examPLe\003net", + (uint8_t*)"\003bla\007eXAmple\003nET" + ) == 0); + + /* example from 4034 */ + /* example a.example yljkjljk.a.example Z.a.example zABC.a.EXAMPLE + z.example \001.z.example *.z.example \200.z.example */ + unit_assert( dname_canonical_compare( + (uint8_t*)"", + (uint8_t*)"\007example" + ) == -1); + unit_assert( dname_canonical_compare( + (uint8_t*)"\007example", + (uint8_t*)"\001a\007example" + ) == -1); + unit_assert( dname_canonical_compare( + (uint8_t*)"\001a\007example", + (uint8_t*)"\010yljkjljk\001a\007example" + ) == -1); + unit_assert( dname_canonical_compare( + (uint8_t*)"\010yljkjljk\001a\007example", + (uint8_t*)"\001Z\001a\007example" + ) == -1); + unit_assert( dname_canonical_compare( + (uint8_t*)"\001Z\001a\007example", + (uint8_t*)"\004zABC\001a\007EXAMPLE" + ) == -1); + unit_assert( dname_canonical_compare( + (uint8_t*)"\004zABC\001a\007EXAMPLE", + (uint8_t*)"\001z\007example" + ) == -1); + unit_assert( dname_canonical_compare( + (uint8_t*)"\001z\007example", + (uint8_t*)"\001\001\001z\007example" + ) == -1); + unit_assert( dname_canonical_compare( + (uint8_t*)"\001\001\001z\007example", + (uint8_t*)"\001*\001z\007example" + ) == -1); + unit_assert( dname_canonical_compare( + (uint8_t*)"\001*\001z\007example", + (uint8_t*)"\001\200\001z\007example" + ) == -1); + /* same example in reverse */ + unit_assert( dname_canonical_compare( + (uint8_t*)"\007example", + (uint8_t*)"" + ) == 1); + unit_assert( dname_canonical_compare( + (uint8_t*)"\001a\007example", + (uint8_t*)"\007example" + ) == 1); + unit_assert( dname_canonical_compare( + (uint8_t*)"\010yljkjljk\001a\007example", + (uint8_t*)"\001a\007example" + ) == 1); + unit_assert( dname_canonical_compare( + (uint8_t*)"\001Z\001a\007example", + (uint8_t*)"\010yljkjljk\001a\007example" + ) == 1); + unit_assert( dname_canonical_compare( + (uint8_t*)"\004zABC\001a\007EXAMPLE", + (uint8_t*)"\001Z\001a\007example" + ) == 1); + unit_assert( dname_canonical_compare( + (uint8_t*)"\001z\007example", + (uint8_t*)"\004zABC\001a\007EXAMPLE" + ) == 1); + unit_assert( dname_canonical_compare( + (uint8_t*)"\001\001\001z\007example", + (uint8_t*)"\001z\007example" + ) == 1); + unit_assert( dname_canonical_compare( + (uint8_t*)"\001*\001z\007example", + (uint8_t*)"\001\001\001z\007example" + ) == 1); + unit_assert( dname_canonical_compare( + (uint8_t*)"\001\200\001z\007example", + (uint8_t*)"\001*\001z\007example" + ) == 1); + /* same example for equality */ + unit_assert( dname_canonical_compare( + (uint8_t*)"\007example", + (uint8_t*)"\007example" + ) == 0); + unit_assert( dname_canonical_compare( + (uint8_t*)"\001a\007example", + (uint8_t*)"\001a\007example" + ) == 0); + unit_assert( dname_canonical_compare( + (uint8_t*)"\010yljkjljk\001a\007example", + (uint8_t*)"\010yljkjljk\001a\007example" + ) == 0); + unit_assert( dname_canonical_compare( + (uint8_t*)"\001Z\001a\007example", + (uint8_t*)"\001Z\001a\007example" + ) == 0); + unit_assert( dname_canonical_compare( + (uint8_t*)"\004zABC\001a\007EXAMPLE", + (uint8_t*)"\004zABC\001a\007EXAMPLE" + ) == 0); + unit_assert( dname_canonical_compare( + (uint8_t*)"\001z\007example", + (uint8_t*)"\001z\007example" + ) == 0); + unit_assert( dname_canonical_compare( + (uint8_t*)"\001\001\001z\007example", + (uint8_t*)"\001\001\001z\007example" + ) == 0); + unit_assert( dname_canonical_compare( + (uint8_t*)"\001*\001z\007example", + (uint8_t*)"\001*\001z\007example" + ) == 0); + unit_assert( dname_canonical_compare( + (uint8_t*)"\001\200\001z\007example", + (uint8_t*)"\001\200\001z\007example" + ) == 0); +} + +/** Test dname_get_shared_topdomain */ +static void +dname_test_topdomain(void) +{ + unit_show_func("util/data/dname.c", "dname_get_shared_topdomain"); + unit_assert( query_dname_compare( + dname_get_shared_topdomain( + (uint8_t*)"", + (uint8_t*)""), + (uint8_t*)"") == 0); + unit_assert( query_dname_compare( + dname_get_shared_topdomain( + (uint8_t*)"\003www\007example\003com", + (uint8_t*)"\003www\007example\003com"), + (uint8_t*)"\003www\007example\003com") == 0); + unit_assert( query_dname_compare( + dname_get_shared_topdomain( + (uint8_t*)"\003www\007example\003com", + (uint8_t*)"\003bla\007example\003com"), + (uint8_t*)"\007example\003com") == 0); +} + +/** Test dname_valid */ +static void +dname_test_valid(void) +{ + unit_show_func("util/data/dname.c", "dname_valid"); + unit_assert( dname_valid( + (uint8_t*)"\003www\007example\003com", 255) == 17); + unit_assert( dname_valid((uint8_t*)"", 255) == 1); + unit_assert( dname_valid( (uint8_t*) + "\020a1cdef5555544444" + "\020a2cdef5555544444" + "\020a3cdef5555544444" + "\020a4cdef5555544444" + "\020a5cdef5555544444" + "\020a6cdef5555544444" + "\020a7cdef5555544444" + "\020a8cdef5555544444" + "\020a9cdef5555544444" + "\020aAcdef5555544444" + "\020aBcdef5555544444" + "\020aCcdef5555544444" + "\020aDcdef5555544444" + "\020aEcdef5555544444" /* 238 up to here */ + "\007aabbccd" /* 246 up to here */ + "\007example\000" /* 255 to here */ + , 255) == 255); + unit_assert( dname_valid( (uint8_t*) + "\020a1cdef5555544444" + "\020a2cdef5555544444" + "\020a3cdef5555544444" + "\020a4cdef5555544444" + "\020a5cdef5555544444" + "\020a6cdef5555544444" + "\020a7cdef5555544444" + "\020a8cdef5555544444" + "\020a9cdef5555544444" + "\020aAcdef5555544444" + "\020aBcdef5555544444" + "\020aCcdef5555544444" + "\020aDcdef5555544444" + "\020aEcdef5555544444" /* 238 up to here */ + "\007aabbccd" /* 246 up to here */ + "\010exampleX\000" /* 256 to here */ + , 4096) == 0); +} + +/** test pkt_dname_tolower */ +static void +dname_test_pdtl(ldns_buffer* loopbuf, ldns_buffer* boundbuf) +{ + unit_show_func("util/data/dname.c", "pkt_dname_tolower"); + pkt_dname_tolower(loopbuf, ldns_buffer_at(loopbuf, 12)); + pkt_dname_tolower(boundbuf, ldns_buffer_at(boundbuf, 12)); +} + +/** setup looped dname and out-of-bounds dname ptr */ +static void +dname_setup_bufs(ldns_buffer* loopbuf, ldns_buffer* boundbuf) +{ + ldns_buffer_write_u16(loopbuf, 0xd54d); /* id */ + ldns_buffer_write_u16(loopbuf, 0x12); /* flags */ + ldns_buffer_write_u16(loopbuf, 1); /* qdcount */ + ldns_buffer_write_u16(loopbuf, 0); /* ancount */ + ldns_buffer_write_u16(loopbuf, 0); /* nscount */ + ldns_buffer_write_u16(loopbuf, 0); /* arcount */ + ldns_buffer_write_u8(loopbuf, 0xc0); /* PTR back at itself */ + ldns_buffer_write_u8(loopbuf, 0x0c); + ldns_buffer_flip(loopbuf); + + ldns_buffer_write_u16(boundbuf, 0xd54d); /* id */ + ldns_buffer_write_u16(boundbuf, 0x12); /* flags */ + ldns_buffer_write_u16(boundbuf, 1); /* qdcount */ + ldns_buffer_write_u16(boundbuf, 0); /* ancount */ + ldns_buffer_write_u16(boundbuf, 0); /* nscount */ + ldns_buffer_write_u16(boundbuf, 0); /* arcount */ + ldns_buffer_write_u8(boundbuf, 0x01); /* len=1 */ + ldns_buffer_write_u8(boundbuf, (uint8_t)'A'); /* A. label */ + ldns_buffer_write_u8(boundbuf, 0xc0); /* PTR out of bounds */ + ldns_buffer_write_u8(boundbuf, 0xcc); + ldns_buffer_flip(boundbuf); +} + +void dname_test(void) +{ + ldns_buffer* loopbuf = ldns_buffer_new(14); + ldns_buffer* boundbuf = ldns_buffer_new(16); + ldns_buffer* buff = ldns_buffer_new(65800); + unit_assert(loopbuf && boundbuf && buff); + ldns_buffer_flip(buff); + dname_setup_bufs(loopbuf, boundbuf); + dname_test_qdl(buff); + dname_test_qdtl(buff); + dname_test_pdtl(loopbuf, boundbuf); + dname_test_query_dname_compare(); + dname_test_count_labels(); + dname_test_count_size_labels(); + dname_test_dname_lab_cmp(); + dname_test_pkt_dname_len(buff); + dname_test_strict_subdomain(); + dname_test_subdomain(); + dname_test_isroot(); + dname_test_removelabel(); + dname_test_sigcount(); + dname_test_iswild(); + dname_test_canoncmp(); + dname_test_topdomain(); + dname_test_valid(); + ldns_buffer_free(buff); + ldns_buffer_free(loopbuf); + ldns_buffer_free(boundbuf); +} diff --git a/testcode/unitlruhash.c b/testcode/unitlruhash.c new file mode 100644 index 00000000000..3bb7c26267d --- /dev/null +++ b/testcode/unitlruhash.c @@ -0,0 +1,499 @@ +/* + * testcode/unitlruhash.c - unit test for lruhash table. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +/** + * \file + * Tests the locking LRU keeping hash table implementation. + */ + +#include "config.h" +#include "testcode/unitmain.h" +#include "util/log.h" +#include "util/storage/lruhash.h" +#include "util/storage/slabhash.h" /* for the test structures */ + +/** use this type for the lruhash test key */ +typedef struct slabhash_testkey testkey_t; +/** use this type for the lruhash test data */ +typedef struct slabhash_testdata testdata_t; + +/** delete key */ +static void delkey(struct slabhash_testkey* k) { + lock_rw_destroy(&k->entry.lock); free(k);} +/** delete data */ +static void deldata(struct slabhash_testdata* d) {free(d);} + +/** hash func, very bad to improve collisions */ +static hashvalue_t myhash(int id) {return (hashvalue_t)id & 0x0f;} +/** allocate new key, fill in hash */ +static testkey_t* newkey(int id) { + testkey_t* k = (testkey_t*)calloc(1, sizeof(testkey_t)); + if(!k) fatal_exit("out of memory"); + k->id = id; + k->entry.hash = myhash(id); + k->entry.key = k; + lock_rw_init(&k->entry.lock); + return k; +} +/** new data el */ +static testdata_t* newdata(int val) { + testdata_t* d = (testdata_t*)calloc(1, + sizeof(testdata_t)); + if(!d) fatal_exit("out of memory"); + d->data = val; + return d; +} + +/** test bin_find_entry function and bin_overflow_remove */ +static void +test_bin_find_entry(struct lruhash* table) +{ + testkey_t* k = newkey(12); + testdata_t* d = newdata(128); + testkey_t* k2 = newkey(12 + 1024); + testkey_t* k3 = newkey(14); + testkey_t* k4 = newkey(12 + 1024*2); + hashvalue_t h = myhash(12); + struct lruhash_bin bin; + memset(&bin, 0, sizeof(bin)); + bin_init(&bin, 1); + + /* remove from empty list */ + bin_overflow_remove(&bin, &k->entry); + + /* find in empty list */ + unit_assert( bin_find_entry(table, &bin, h, k) == NULL ); + + /* insert */ + lock_quick_lock(&bin.lock); + bin.overflow_list = &k->entry; + lock_quick_unlock(&bin.lock); + + /* find, hash not OK. */ + unit_assert( bin_find_entry(table, &bin, myhash(13), k) == NULL ); + + /* find, hash OK, but cmp not */ + unit_assert( k->entry.hash == k2->entry.hash ); + unit_assert( bin_find_entry(table, &bin, h, k2) == NULL ); + + /* find, hash OK, and cmp too */ + unit_assert( bin_find_entry(table, &bin, h, k) == &k->entry ); + + /* remove the element */ + lock_quick_lock(&bin.lock); + bin_overflow_remove(&bin, &k->entry); + lock_quick_unlock(&bin.lock); + unit_assert( bin_find_entry(table, &bin, h, k) == NULL ); + + /* prepend two different elements; so the list is long */ + /* one has the same hash, but different cmp */ + lock_quick_lock(&bin.lock); + unit_assert( k->entry.hash == k4->entry.hash ); + k4->entry.overflow_next = &k->entry; + k3->entry.overflow_next = &k4->entry; + bin.overflow_list = &k3->entry; + lock_quick_unlock(&bin.lock); + + /* find, hash not OK. */ + unit_assert( bin_find_entry(table, &bin, myhash(13), k) == NULL ); + + /* find, hash OK, but cmp not */ + unit_assert( k->entry.hash == k2->entry.hash ); + unit_assert( bin_find_entry(table, &bin, h, k2) == NULL ); + + /* find, hash OK, and cmp too */ + unit_assert( bin_find_entry(table, &bin, h, k) == &k->entry ); + + /* remove middle element */ + unit_assert( bin_find_entry(table, &bin, k4->entry.hash, k4) + == &k4->entry ); + lock_quick_lock(&bin.lock); + bin_overflow_remove(&bin, &k4->entry); + lock_quick_unlock(&bin.lock); + unit_assert( bin_find_entry(table, &bin, k4->entry.hash, k4) == NULL); + + /* remove last element */ + lock_quick_lock(&bin.lock); + bin_overflow_remove(&bin, &k->entry); + lock_quick_unlock(&bin.lock); + unit_assert( bin_find_entry(table, &bin, h, k) == NULL ); + + lock_quick_destroy(&bin.lock); + delkey(k); + delkey(k2); + delkey(k3); + delkey(k4); + deldata(d); +} + +/** test lru_front lru_remove */ +static void test_lru(struct lruhash* table) +{ + testkey_t* k = newkey(12); + testkey_t* k2 = newkey(14); + lock_quick_lock(&table->lock); + + unit_assert( table->lru_start == NULL && table->lru_end == NULL); + lru_remove(table, &k->entry); + unit_assert( table->lru_start == NULL && table->lru_end == NULL); + + /* add one */ + lru_front(table, &k->entry); + unit_assert( table->lru_start == &k->entry && + table->lru_end == &k->entry); + /* remove it */ + lru_remove(table, &k->entry); + unit_assert( table->lru_start == NULL && table->lru_end == NULL); + + /* add two */ + lru_front(table, &k->entry); + unit_assert( table->lru_start == &k->entry && + table->lru_end == &k->entry); + lru_front(table, &k2->entry); + unit_assert( table->lru_start == &k2->entry && + table->lru_end == &k->entry); + /* remove first in list */ + lru_remove(table, &k2->entry); + unit_assert( table->lru_start == &k->entry && + table->lru_end == &k->entry); + lru_front(table, &k2->entry); + unit_assert( table->lru_start == &k2->entry && + table->lru_end == &k->entry); + /* remove last in list */ + lru_remove(table, &k->entry); + unit_assert( table->lru_start == &k2->entry && + table->lru_end == &k2->entry); + + /* empty the list */ + lru_remove(table, &k2->entry); + unit_assert( table->lru_start == NULL && table->lru_end == NULL); + lock_quick_unlock(&table->lock); + delkey(k); + delkey(k2); +} + +/** test hashtable using short sequence */ +static void +test_short_table(struct lruhash* table) +{ + testkey_t* k = newkey(12); + testkey_t* k2 = newkey(14); + testdata_t* d = newdata(128); + testdata_t* d2 = newdata(129); + + k->entry.data = d; + k2->entry.data = d2; + + lruhash_insert(table, myhash(12), &k->entry, d, NULL); + lruhash_insert(table, myhash(14), &k2->entry, d2, NULL); + + unit_assert( lruhash_lookup(table, myhash(12), k, 0) == &k->entry); + lock_rw_unlock( &k->entry.lock ); + unit_assert( lruhash_lookup(table, myhash(14), k2, 0) == &k2->entry); + lock_rw_unlock( &k2->entry.lock ); + lruhash_remove(table, myhash(12), k); + lruhash_remove(table, myhash(14), k2); +} + +/** number of hash test max */ +#define HASHTESTMAX 25 + +/** test adding a random element */ +static void +testadd(struct lruhash* table, testdata_t* ref[]) +{ + int numtoadd = random() % HASHTESTMAX; + testdata_t* data = newdata(numtoadd); + testkey_t* key = newkey(numtoadd); + key->entry.data = data; + lruhash_insert(table, myhash(numtoadd), &key->entry, data, NULL); + ref[numtoadd] = data; +} + +/** test adding a random element */ +static void +testremove(struct lruhash* table, testdata_t* ref[]) +{ + int num = random() % HASHTESTMAX; + testkey_t* key = newkey(num); + lruhash_remove(table, myhash(num), key); + ref[num] = NULL; + delkey(key); +} + +/** test adding a random element */ +static void +testlookup(struct lruhash* table, testdata_t* ref[]) +{ + int num = random() % HASHTESTMAX; + testkey_t* key = newkey(num); + struct lruhash_entry* en = lruhash_lookup(table, myhash(num), key, 0); + testdata_t* data = en? (testdata_t*)en->data : NULL; + if(en) { + unit_assert(en->key); + unit_assert(en->data); + } + if(0) log_info("lookup %d got %d, expect %d", num, en? data->data :-1, + ref[num]? ref[num]->data : -1); + unit_assert( data == ref[num] ); + if(en) { lock_rw_unlock(&en->lock); } + delkey(key); +} + +/** check integrity of hash table */ +static void +check_table(struct lruhash* table) +{ + struct lruhash_entry* p; + size_t c = 0; + lock_quick_lock(&table->lock); + unit_assert( table->num <= table->size); + unit_assert( table->size_mask == (int)table->size-1 ); + unit_assert( (table->lru_start && table->lru_end) || + (!table->lru_start && !table->lru_end) ); + unit_assert( table->space_used <= table->space_max ); + /* check lru list integrity */ + if(table->lru_start) + unit_assert(table->lru_start->lru_prev == NULL); + if(table->lru_end) + unit_assert(table->lru_end->lru_next == NULL); + p = table->lru_start; + while(p) { + if(p->lru_prev) { + unit_assert(p->lru_prev->lru_next == p); + } + if(p->lru_next) { + unit_assert(p->lru_next->lru_prev == p); + } + c++; + p = p->lru_next; + } + unit_assert(c == table->num); + + /* this assertion is specific to the unit test */ + unit_assert( table->space_used == + table->num * test_slabhash_sizefunc(NULL, NULL) ); + lock_quick_unlock(&table->lock); +} + +/** test adding a random element (unlimited range) */ +static void +testadd_unlim(struct lruhash* table, testdata_t** ref) +{ + int numtoadd = random() % (HASHTESTMAX * 10); + testdata_t* data = newdata(numtoadd); + testkey_t* key = newkey(numtoadd); + key->entry.data = data; + lruhash_insert(table, myhash(numtoadd), &key->entry, data, NULL); + if(ref) + ref[numtoadd] = data; +} + +/** test adding a random element (unlimited range) */ +static void +testremove_unlim(struct lruhash* table, testdata_t** ref) +{ + int num = random() % (HASHTESTMAX*10); + testkey_t* key = newkey(num); + lruhash_remove(table, myhash(num), key); + if(ref) + ref[num] = NULL; + delkey(key); +} + +/** test adding a random element (unlimited range) */ +static void +testlookup_unlim(struct lruhash* table, testdata_t** ref) +{ + int num = random() % (HASHTESTMAX*10); + testkey_t* key = newkey(num); + struct lruhash_entry* en = lruhash_lookup(table, myhash(num), key, 0); + testdata_t* data = en? (testdata_t*)en->data : NULL; + if(en) { + unit_assert(en->key); + unit_assert(en->data); + } + if(0 && ref) log_info("lookup unlim %d got %d, expect %d", num, en ? + data->data :-1, ref[num] ? ref[num]->data : -1); + if(data && ref) { + /* its okay for !data, it fell off the lru */ + unit_assert( data == ref[num] ); + } + if(en) { lock_rw_unlock(&en->lock); } + delkey(key); +} + +/** test with long sequence of adds, removes and updates, and lookups */ +static void +test_long_table(struct lruhash* table) +{ + /* assuming it all fits in the hastable, this check will work */ + testdata_t* ref[HASHTESTMAX * 100]; + size_t i; + memset(ref, 0, sizeof(ref)); + /* test assumption */ + if(0) log_info(" size %d x %d < %d", (int)test_slabhash_sizefunc(NULL, NULL), + (int)HASHTESTMAX, (int)table->space_max); + unit_assert( test_slabhash_sizefunc(NULL, NULL)*HASHTESTMAX < table->space_max); + if(0) lruhash_status(table, "unit test", 1); + srandom(48); + for(i=0; i<1000; i++) { + /* what to do? */ + if(i == 500) { + lruhash_clear(table); + memset(ref, 0, sizeof(ref)); + continue; + } + switch(random() % 4) { + case 0: + case 3: + testadd(table, ref); + break; + case 1: + testremove(table, ref); + break; + case 2: + testlookup(table, ref); + break; + default: + unit_assert(0); + } + if(0) lruhash_status(table, "unit test", 1); + check_table(table); + unit_assert( table->num <= HASHTESTMAX ); + } + + /* test more, but 'ref' assumption does not hold anymore */ + for(i=0; i<1000; i++) { + /* what to do? */ + switch(random() % 4) { + case 0: + case 3: + testadd_unlim(table, ref); + break; + case 1: + testremove_unlim(table, ref); + break; + case 2: + testlookup_unlim(table, ref); + break; + default: + unit_assert(0); + } + if(0) lruhash_status(table, "unlim", 1); + check_table(table); + } +} + +/** structure to threaded test the lru hash table */ +struct test_thr { + /** thread num, first entry. */ + int num; + /** id */ + ub_thread_t id; + /** hash table */ + struct lruhash* table; +}; + +/** main routine for threaded hash table test */ +static void* +test_thr_main(void* arg) +{ + struct test_thr* t = (struct test_thr*)arg; + int i; + log_thread_set(&t->num); + for(i=0; i<1000; i++) { + switch(random() % 4) { + case 0: + case 3: + testadd_unlim(t->table, NULL); + break; + case 1: + testremove_unlim(t->table, NULL); + break; + case 2: + testlookup_unlim(t->table, NULL); + break; + default: + unit_assert(0); + } + if(0) lruhash_status(t->table, "hashtest", 1); + if(i % 100 == 0) /* because of locking, not all the time */ + check_table(t->table); + } + check_table(t->table); + return NULL; +} + +/** test hash table access by multiple threads */ +static void +test_threaded_table(struct lruhash* table) +{ + int numth = 10; + struct test_thr t[100]; + int i; + + for(i=1; i +#endif + +#ifdef HAVE_OPENSSL_RAND_H +#include +#endif + +#ifdef HAVE_OPENSSL_CONF_H +#include +#endif + +#ifdef HAVE_OPENSSL_ENGINE_H +#include +#endif +#include +#include "util/log.h" +#include "testcode/unitmain.h" + +/** number of tests done */ +int testcount = 0; + +#include "util/alloc.h" +/** test alloc code */ +static void +alloc_test(void) { + alloc_special_t *t1, *t2; + struct alloc_cache major, minor1, minor2; + int i; + + unit_show_feature("alloc_special_obtain"); + alloc_init(&major, NULL, 0); + alloc_init(&minor1, &major, 0); + alloc_init(&minor2, &major, 1); + + t1 = alloc_special_obtain(&minor1); + alloc_clear(&minor1); + + alloc_special_release(&minor2, t1); + t2 = alloc_special_obtain(&minor2); + unit_assert( t1 == t2 ); /* reused */ + alloc_special_release(&minor2, t1); + + for(i=0; i<100; i++) { + t1 = alloc_special_obtain(&minor1); + alloc_special_release(&minor2, t1); + } + if(0) { + alloc_stats(&minor1); + alloc_stats(&minor2); + alloc_stats(&major); + } + /* reuse happened */ + unit_assert(minor1.num_quar + minor2.num_quar + major.num_quar == 11); + + alloc_clear(&minor1); + alloc_clear(&minor2); + unit_assert(major.num_quar == 11); + alloc_clear(&major); +} + +#include "util/net_help.h" +/** test net code */ +static void +net_test(void) +{ + const char* t4[] = {"\000\000\000\000", + "\200\000\000\000", + "\300\000\000\000", + "\340\000\000\000", + "\360\000\000\000", + "\370\000\000\000", + "\374\000\000\000", + "\376\000\000\000", + "\377\000\000\000", + "\377\200\000\000", + "\377\300\000\000", + "\377\340\000\000", + "\377\360\000\000", + "\377\370\000\000", + "\377\374\000\000", + "\377\376\000\000", + "\377\377\000\000", + "\377\377\200\000", + "\377\377\300\000", + "\377\377\340\000", + "\377\377\360\000", + "\377\377\370\000", + "\377\377\374\000", + "\377\377\376\000", + "\377\377\377\000", + "\377\377\377\200", + "\377\377\377\300", + "\377\377\377\340", + "\377\377\377\360", + "\377\377\377\370", + "\377\377\377\374", + "\377\377\377\376", + "\377\377\377\377", + "\377\377\377\377", + "\377\377\377\377", + }; + unit_show_func("util/net_help.c", "str_is_ip6"); + unit_assert( str_is_ip6("::") ); + unit_assert( str_is_ip6("::1") ); + unit_assert( str_is_ip6("2001:7b8:206:1:240:f4ff:fe37:8810") ); + unit_assert( str_is_ip6("fe80::240:f4ff:fe37:8810") ); + unit_assert( !str_is_ip6("0.0.0.0") ); + unit_assert( !str_is_ip6("213.154.224.12") ); + unit_assert( !str_is_ip6("213.154.224.255") ); + unit_assert( !str_is_ip6("255.255.255.0") ); + unit_show_func("util/net_help.c", "is_pow2"); + unit_assert( is_pow2(0) ); + unit_assert( is_pow2(1) ); + unit_assert( is_pow2(2) ); + unit_assert( is_pow2(4) ); + unit_assert( is_pow2(8) ); + unit_assert( is_pow2(16) ); + unit_assert( is_pow2(1024) ); + unit_assert( is_pow2(1024*1024) ); + unit_assert( is_pow2(1024*1024*1024) ); + unit_assert( !is_pow2(3) ); + unit_assert( !is_pow2(5) ); + unit_assert( !is_pow2(6) ); + unit_assert( !is_pow2(7) ); + unit_assert( !is_pow2(9) ); + unit_assert( !is_pow2(10) ); + unit_assert( !is_pow2(11) ); + unit_assert( !is_pow2(17) ); + unit_assert( !is_pow2(23) ); + unit_assert( !is_pow2(257) ); + unit_assert( !is_pow2(259) ); + + /* test addr_mask */ + unit_show_func("util/net_help.c", "addr_mask"); + if(1) { + struct sockaddr_in a4; + struct sockaddr_in6 a6; + socklen_t l4 = (socklen_t)sizeof(a4); + socklen_t l6 = (socklen_t)sizeof(a6); + int i; + a4.sin_family = AF_INET; + a6.sin6_family = AF_INET6; + for(i=0; i<35; i++) { + /* address 255.255.255.255 */ + memcpy(&a4.sin_addr, "\377\377\377\377", 4); + addr_mask((struct sockaddr_storage*)&a4, l4, i); + unit_assert(memcmp(&a4.sin_addr, t4[i], 4) == 0); + } + memcpy(&a6.sin6_addr, "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377", 16); + addr_mask((struct sockaddr_storage*)&a6, l6, 128); + unit_assert(memcmp(&a6.sin6_addr, "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377", 16) == 0); + addr_mask((struct sockaddr_storage*)&a6, l6, 122); + unit_assert(memcmp(&a6.sin6_addr, "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\300", 16) == 0); + addr_mask((struct sockaddr_storage*)&a6, l6, 120); + unit_assert(memcmp(&a6.sin6_addr, "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\000", 16) == 0); + addr_mask((struct sockaddr_storage*)&a6, l6, 64); + unit_assert(memcmp(&a6.sin6_addr, "\377\377\377\377\377\377\377\377\000\000\000\000\000\000\000\000", 16) == 0); + addr_mask((struct sockaddr_storage*)&a6, l6, 0); + unit_assert(memcmp(&a6.sin6_addr, "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000", 16) == 0); + } + + /* test addr_in_common */ + unit_show_func("util/net_help.c", "addr_in_common"); + if(1) { + struct sockaddr_in a4, b4; + struct sockaddr_in6 a6, b6; + socklen_t l4 = (socklen_t)sizeof(a4); + socklen_t l6 = (socklen_t)sizeof(a6); + int i; + a4.sin_family = AF_INET; + b4.sin_family = AF_INET; + a6.sin6_family = AF_INET6; + b6.sin6_family = AF_INET6; + memcpy(&a4.sin_addr, "abcd", 4); + memcpy(&b4.sin_addr, "abcd", 4); + unit_assert(addr_in_common((struct sockaddr_storage*)&a4, 32, + (struct sockaddr_storage*)&b4, 32, l4) == 32); + unit_assert(addr_in_common((struct sockaddr_storage*)&a4, 34, + (struct sockaddr_storage*)&b4, 32, l4) == 32); + for(i=0; i<=32; i++) { + unit_assert(addr_in_common( + (struct sockaddr_storage*)&a4, 32, + (struct sockaddr_storage*)&b4, i, l4) == i); + unit_assert(addr_in_common( + (struct sockaddr_storage*)&a4, i, + (struct sockaddr_storage*)&b4, 32, l4) == i); + unit_assert(addr_in_common( + (struct sockaddr_storage*)&a4, i, + (struct sockaddr_storage*)&b4, i, l4) == i); + } + for(i=0; i<=32; i++) { + memcpy(&a4.sin_addr, "\377\377\377\377", 4); + memcpy(&b4.sin_addr, t4[i], 4); + unit_assert(addr_in_common( + (struct sockaddr_storage*)&a4, 32, + (struct sockaddr_storage*)&b4, 32, l4) == i); + unit_assert(addr_in_common( + (struct sockaddr_storage*)&b4, 32, + (struct sockaddr_storage*)&a4, 32, l4) == i); + } + memcpy(&a6.sin6_addr, "abcdefghabcdefgh", 16); + memcpy(&b6.sin6_addr, "abcdefghabcdefgh", 16); + unit_assert(addr_in_common((struct sockaddr_storage*)&a6, 128, + (struct sockaddr_storage*)&b6, 128, l6) == 128); + unit_assert(addr_in_common((struct sockaddr_storage*)&a6, 129, + (struct sockaddr_storage*)&b6, 128, l6) == 128); + for(i=0; i<=128; i++) { + unit_assert(addr_in_common( + (struct sockaddr_storage*)&a6, 128, + (struct sockaddr_storage*)&b6, i, l6) == i); + unit_assert(addr_in_common( + (struct sockaddr_storage*)&a6, i, + (struct sockaddr_storage*)&b6, 128, l6) == i); + unit_assert(addr_in_common( + (struct sockaddr_storage*)&a6, i, + (struct sockaddr_storage*)&b6, i, l6) == i); + } + } + /* test sockaddr_cmp_addr */ + unit_show_func("util/net_help.c", "sockaddr_cmp_addr"); + if(1) { + struct sockaddr_storage a, b; + socklen_t alen = (socklen_t)sizeof(a); + socklen_t blen = (socklen_t)sizeof(b); + unit_assert(ipstrtoaddr("127.0.0.0", 53, &a, &alen)); + unit_assert(ipstrtoaddr("127.255.255.255", 53, &b, &blen)); + unit_assert(sockaddr_cmp_addr(&a, alen, &b, blen) < 0); + unit_assert(sockaddr_cmp_addr(&b, blen, &a, alen) > 0); + unit_assert(sockaddr_cmp_addr(&a, alen, &a, alen) == 0); + unit_assert(sockaddr_cmp_addr(&b, blen, &b, blen) == 0); + unit_assert(ipstrtoaddr("192.168.121.5", 53, &a, &alen)); + unit_assert(sockaddr_cmp_addr(&a, alen, &b, blen) > 0); + unit_assert(sockaddr_cmp_addr(&b, blen, &a, alen) < 0); + unit_assert(sockaddr_cmp_addr(&a, alen, &a, alen) == 0); + unit_assert(ipstrtoaddr("2001:3578:ffeb::99", 53, &b, &blen)); + unit_assert(sockaddr_cmp_addr(&b, blen, &b, blen) == 0); + unit_assert(sockaddr_cmp_addr(&a, alen, &b, blen) < 0); + unit_assert(sockaddr_cmp_addr(&b, blen, &a, alen) > 0); + } + /* test addr_is_ip4mapped */ + unit_show_func("util/net_help.c", "addr_is_ip4mapped"); + if(1) { + struct sockaddr_storage a; + socklen_t l = (socklen_t)sizeof(a); + unit_assert(ipstrtoaddr("12.13.14.15", 53, &a, &l)); + unit_assert(!addr_is_ip4mapped(&a, l)); + unit_assert(ipstrtoaddr("fe80::217:31ff:fe91:df", 53, &a, &l)); + unit_assert(!addr_is_ip4mapped(&a, l)); + unit_assert(ipstrtoaddr("ffff::217:31ff:fe91:df", 53, &a, &l)); + unit_assert(!addr_is_ip4mapped(&a, l)); + unit_assert(ipstrtoaddr("::ffff:31ff:fe91:df", 53, &a, &l)); + unit_assert(!addr_is_ip4mapped(&a, l)); + unit_assert(ipstrtoaddr("::fffe:fe91:df", 53, &a, &l)); + unit_assert(!addr_is_ip4mapped(&a, l)); + unit_assert(ipstrtoaddr("::ffff:127.0.0.1", 53, &a, &l)); + unit_assert(addr_is_ip4mapped(&a, l)); + unit_assert(ipstrtoaddr("::ffff:127.0.0.2", 53, &a, &l)); + unit_assert(addr_is_ip4mapped(&a, l)); + unit_assert(ipstrtoaddr("::ffff:192.168.0.2", 53, &a, &l)); + unit_assert(addr_is_ip4mapped(&a, l)); + unit_assert(ipstrtoaddr("2::ffff:192.168.0.2", 53, &a, &l)); + unit_assert(!addr_is_ip4mapped(&a, l)); + } + /* test addr_is_any */ + unit_show_func("util/net_help.c", "addr_is_any"); + if(1) { + struct sockaddr_storage a; + socklen_t l = (socklen_t)sizeof(a); + unit_assert(ipstrtoaddr("0.0.0.0", 53, &a, &l)); + unit_assert(addr_is_any(&a, l)); + unit_assert(ipstrtoaddr("0.0.0.0", 10053, &a, &l)); + unit_assert(addr_is_any(&a, l)); + unit_assert(ipstrtoaddr("0.0.0.0", 0, &a, &l)); + unit_assert(addr_is_any(&a, l)); + unit_assert(ipstrtoaddr("::0", 0, &a, &l)); + unit_assert(addr_is_any(&a, l)); + unit_assert(ipstrtoaddr("::0", 53, &a, &l)); + unit_assert(addr_is_any(&a, l)); + unit_assert(ipstrtoaddr("::1", 53, &a, &l)); + unit_assert(!addr_is_any(&a, l)); + unit_assert(ipstrtoaddr("2001:1667::1", 0, &a, &l)); + unit_assert(!addr_is_any(&a, l)); + unit_assert(ipstrtoaddr("2001::0", 0, &a, &l)); + unit_assert(!addr_is_any(&a, l)); + unit_assert(ipstrtoaddr("10.0.0.0", 0, &a, &l)); + unit_assert(!addr_is_any(&a, l)); + unit_assert(ipstrtoaddr("0.0.0.10", 0, &a, &l)); + unit_assert(!addr_is_any(&a, l)); + unit_assert(ipstrtoaddr("192.0.2.1", 0, &a, &l)); + unit_assert(!addr_is_any(&a, l)); + } +} + +#include "util/config_file.h" +/** test config_file: cfg_parse_memsize */ +static void +config_memsize_test(void) +{ + size_t v = 0; + unit_show_func("util/config_file.c", "cfg_parse_memsize"); + if(0) { + /* these emit errors */ + unit_assert( cfg_parse_memsize("", &v) == 0); + unit_assert( cfg_parse_memsize("bla", &v) == 0); + unit_assert( cfg_parse_memsize("nop", &v) == 0); + unit_assert( cfg_parse_memsize("n0b", &v) == 0); + unit_assert( cfg_parse_memsize("gb", &v) == 0); + unit_assert( cfg_parse_memsize("b", &v) == 0); + unit_assert( cfg_parse_memsize("kb", &v) == 0); + unit_assert( cfg_parse_memsize("kk kb", &v) == 0); + } + unit_assert( cfg_parse_memsize("0", &v) && v==0); + unit_assert( cfg_parse_memsize("1", &v) && v==1); + unit_assert( cfg_parse_memsize("10", &v) && v==10); + unit_assert( cfg_parse_memsize("10b", &v) && v==10); + unit_assert( cfg_parse_memsize("5b", &v) && v==5); + unit_assert( cfg_parse_memsize("1024", &v) && v==1024); + unit_assert( cfg_parse_memsize("1k", &v) && v==1024); + unit_assert( cfg_parse_memsize("1K", &v) && v==1024); + unit_assert( cfg_parse_memsize("1Kb", &v) && v==1024); + unit_assert( cfg_parse_memsize("1kb", &v) && v==1024); + unit_assert( cfg_parse_memsize("1 kb", &v) && v==1024); + unit_assert( cfg_parse_memsize("10 kb", &v) && v==10240); + unit_assert( cfg_parse_memsize("2k", &v) && v==2048); + unit_assert( cfg_parse_memsize("2m", &v) && v==2048*1024); + unit_assert( cfg_parse_memsize("3M", &v) && v==3072*1024); + unit_assert( cfg_parse_memsize("40m", &v) && v==40960*1024); + unit_assert( cfg_parse_memsize("1G", &v) && v==1024*1024*1024); + unit_assert( cfg_parse_memsize("1 Gb", &v) && v==1024*1024*1024); + unit_assert( cfg_parse_memsize("0 Gb", &v) && v==0*1024*1024); +} + +#include "util/rtt.h" +/** test RTT code */ +static void +rtt_test(void) +{ + int init = 376; + int i; + struct rtt_info r; + unit_show_func("util/rtt.c", "rtt_timeout"); + rtt_init(&r); + /* initial value sensible */ + unit_assert( rtt_timeout(&r) == init ); + rtt_lost(&r, init); + unit_assert( rtt_timeout(&r) == init*2 ); + rtt_lost(&r, init*2); + unit_assert( rtt_timeout(&r) == init*4 ); + rtt_update(&r, 4000); + unit_assert( rtt_timeout(&r) >= 2000 ); + rtt_lost(&r, rtt_timeout(&r) ); + for(i=0; i<100; i++) { + rtt_lost(&r, rtt_timeout(&r) ); + unit_assert( rtt_timeout(&r) > RTT_MIN_TIMEOUT-1); + unit_assert( rtt_timeout(&r) < RTT_MAX_TIMEOUT+1); + } +} + +#include "services/cache/infra.h" +#include "util/config_file.h" + +/* lookup and get key and data structs easily */ +static struct infra_data* infra_lookup_host(struct infra_cache* infra, + struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, + size_t zonelen, int wr, uint32_t now, struct infra_key** k) +{ + struct infra_data* d; + struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen, + zone, zonelen, wr); + if(!e) return NULL; + d = (struct infra_data*)e->data; + if(d->ttl < now) { + lock_rw_unlock(&e->lock); + return NULL; + } + *k = (struct infra_key*)e->key; + return d; +} + +/** test host cache */ +static void +infra_test(void) +{ + struct sockaddr_storage one; + socklen_t onelen; + uint8_t* zone = (uint8_t*)"\007example\003com\000"; + size_t zonelen = 13; + struct infra_cache* slab; + struct config_file* cfg = config_create(); + uint32_t now = 0; + uint8_t edns_lame; + int vs, to; + struct infra_key* k; + struct infra_data* d; + int init = 376; + + unit_show_feature("infra cache"); + unit_assert(ipstrtoaddr("127.0.0.1", 53, &one, &onelen)); + + slab = infra_create(cfg); + unit_assert( infra_host(slab, &one, onelen, zone, zonelen, now, + &vs, &edns_lame, &to) ); + unit_assert( vs == 0 && to == init && edns_lame == 0 ); + + unit_assert( infra_rtt_update(slab, &one, onelen, zone, zonelen, LDNS_RR_TYPE_A, -1, init, now) ); + unit_assert( infra_host(slab, &one, onelen, zone, zonelen, + now, &vs, &edns_lame, &to) ); + unit_assert( vs == 0 && to == init*2 && edns_lame == 0 ); + + unit_assert( infra_edns_update(slab, &one, onelen, zone, zonelen, -1, now) ); + unit_assert( infra_host(slab, &one, onelen, zone, zonelen, + now, &vs, &edns_lame, &to) ); + unit_assert( vs == -1 && to == init*2 && edns_lame == 1); + + now += cfg->host_ttl + 10; + unit_assert( infra_host(slab, &one, onelen, zone, zonelen, + now, &vs, &edns_lame, &to) ); + unit_assert( vs == 0 && to == init && edns_lame == 0 ); + + unit_assert( infra_set_lame(slab, &one, onelen, + zone, zonelen, now, 0, 0, LDNS_RR_TYPE_A) ); + unit_assert( (d=infra_lookup_host(slab, &one, onelen, zone, zonelen, 0, now, &k)) ); + unit_assert( d->ttl == now+cfg->host_ttl ); + unit_assert( d->edns_version == 0 ); + unit_assert(!d->isdnsseclame && !d->rec_lame && d->lame_type_A && + !d->lame_other); + lock_rw_unlock(&k->entry.lock); + + /* test merge of data */ + unit_assert( infra_set_lame(slab, &one, onelen, + zone, zonelen, now, 0, 0, LDNS_RR_TYPE_AAAA) ); + unit_assert( (d=infra_lookup_host(slab, &one, onelen, zone, zonelen, 0, now, &k)) ); + unit_assert(!d->isdnsseclame && !d->rec_lame && d->lame_type_A && + d->lame_other); + lock_rw_unlock(&k->entry.lock); + + /* test that noEDNS cannot overwrite known-yesEDNS */ + now += cfg->host_ttl + 10; + unit_assert( infra_host(slab, &one, onelen, zone, zonelen, + now, &vs, &edns_lame, &to) ); + unit_assert( vs == 0 && to == init && edns_lame == 0 ); + + unit_assert( infra_edns_update(slab, &one, onelen, zone, zonelen, 0, now) ); + unit_assert( infra_host(slab, &one, onelen, zone, zonelen, + now, &vs, &edns_lame, &to) ); + unit_assert( vs == 0 && to == init && edns_lame == 1 ); + + unit_assert( infra_edns_update(slab, &one, onelen, zone, zonelen, -1, now) ); + unit_assert( infra_host(slab, &one, onelen, zone, zonelen, + now, &vs, &edns_lame, &to) ); + unit_assert( vs == 0 && to == init && edns_lame == 1 ); + + infra_delete(slab); + config_delete(cfg); +} + +#include "util/random.h" +/** test randomness */ +static void +rnd_test(void) +{ + struct ub_randstate* r; + int num = 1000, i; + long int a[1000]; + unsigned int seed = (unsigned)time(NULL); + unit_show_feature("ub_random"); + printf("ub_random seed is %u\n", seed); + unit_assert( (r = ub_initstate(seed, NULL)) ); + for(i=0; i= 0); + unit_assert((size_t)a[i] <= (size_t)0x7fffffff); + if(i > 5) + unit_assert(a[i] != a[i-1] || a[i] != a[i-2] || + a[i] != a[i-3] || a[i] != a[i-4] || + a[i] != a[i-5] || a[i] != a[i-6]); + } + a[0] = ub_random_max(r, 1); + unit_assert(a[0] >= 0 && a[0] < 1); + a[0] = ub_random_max(r, 10000); + unit_assert(a[0] >= 0 && a[0] < 10000); + for(i=0; i= 0 && a[i] < 10); + } + ub_randfree(r); +} + +void unit_show_func(const char* file, const char* func) +{ + printf("test %s:%s\n", file, func); +} + +void unit_show_feature(const char* feature) +{ + printf("test %s functions\n", feature); +} + +/** + * Main unit test program. Setup, teardown and report errors. + * @param argc: arg count. + * @param argv: array of commandline arguments. + * @return program failure if test fails. + */ +int +main(int argc, char* argv[]) +{ + log_init(NULL, 0, NULL); + if(argc != 1) { + printf("usage: %s\n", argv[0]); + printf("\tperforms unit tests.\n"); + return 1; + } + printf("Start of %s unit test.\n", PACKAGE_STRING); + ERR_load_crypto_strings(); +#ifdef HAVE_OPENSSL_CONFIG + OPENSSL_config("unbound"); +#endif +#ifdef USE_GOST + (void)ldns_key_EVP_load_gost_id(); +#endif + checklock_start(); + neg_test(); + rnd_test(); + verify_test(); + net_test(); + config_memsize_test(); + dname_test(); + rtt_test(); + anchors_test(); + alloc_test(); + regional_test(); + lruhash_test(); + slabhash_test(); + infra_test(); + msgparse_test(); + checklock_stop(); + printf("%d checks ok.\n", testcount); +#if defined(USE_GOST) && defined(HAVE_LDNS_KEY_EVP_UNLOAD_GOST) + ldns_key_EVP_unload_gost(); +#endif +#ifdef HAVE_OPENSSL_CONFIG + EVP_cleanup(); + ENGINE_cleanup(); + CONF_modules_free(); +#endif + CRYPTO_cleanup_all_ex_data(); + ERR_remove_state(0); + ERR_free_strings(); + RAND_cleanup(); +#ifdef HAVE_PTHREAD + /* dlopen frees its thread specific state */ + pthread_exit(NULL); +#endif + return 0; +} diff --git a/testcode/unitmain.h b/testcode/unitmain.h new file mode 100644 index 00000000000..6cfad3eb545 --- /dev/null +++ b/testcode/unitmain.h @@ -0,0 +1,76 @@ +/* + * testcode/unitmain.h - unit test main program for unbound. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +/** + * \file + * Declarations useful for the unit tests. + */ + +#ifndef TESTCODE_UNITMAIN_H +#define TESTCODE_UNITMAIN_H +#include "util/log.h" + +/** number of tests done */ +extern int testcount; +/** test bool x, exits on failure, increases testcount. */ +#ifdef DEBUG_UNBOUND +#define unit_assert(x) do {testcount++; log_assert(x);} while(0) +#else +#define unit_assert(x) do {testcount++; if(!(x)) { fprintf(stderr, "assertion failure %s:%d\n", __FILE__, __LINE__); exit(1);}} while(0) +#endif + +/** we are now testing this function */ +void unit_show_func(const char* file, const char* func); +/** we are testing this functionality */ +void unit_show_feature(const char* feature); + +/** unit test lruhashtable implementation */ +void lruhash_test(void); +/** unit test slabhashtable implementation */ +void slabhash_test(void); +/** unit test for msgreply and msgparse */ +void msgparse_test(void); +/** unit test dname handling functions */ +void dname_test(void); +/** unit test trust anchor storage functions */ +void anchors_test(void); +/** unit test for verification functions */ +void verify_test(void); +/** unit test for negative cache functions */ +void neg_test(void); +/** unit test for regional allocator functions */ +void regional_test(void); + +#endif /* TESTCODE_UNITMAIN_H */ diff --git a/testcode/unitmsgparse.c b/testcode/unitmsgparse.c new file mode 100644 index 00000000000..434239507b4 --- /dev/null +++ b/testcode/unitmsgparse.c @@ -0,0 +1,624 @@ +/* + * testcode/unitmsgparse.c - unit test for msg parse routines. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +/** + * \file + * Calls msg parse unit tests. Exits with code 1 on a failure. + */ + +#include "config.h" +#include +#include "util/log.h" +#include "testcode/unitmain.h" +#include "util/data/msgparse.h" +#include "util/data/msgreply.h" +#include "util/data/msgencode.h" +#include "util/data/dname.h" +#include "util/alloc.h" +#include "util/regional.h" +#include "util/net_help.h" +#include "testcode/readhex.h" + +/** verbose message parse unit test */ +static int vbmp = 0; +/** do not accept formerr */ +static int check_formerr_gone = 0; +/** if matching within a section should disregard the order of RRs. */ +static int matches_nolocation = 0; +/** see if RRSIGs are properly matched to RRsets. */ +static int check_rrsigs = 0; +/** do not check buffer sameness */ +static int check_nosameness = 0; + +/** match two rr lists */ +static int +match_list(ldns_rr_list* q, ldns_rr_list *p) +{ + size_t i; + if(ldns_rr_list_rr_count(q) != ldns_rr_list_rr_count(p)) { + verbose(3, "rrlistcount different %d %d", + (int)ldns_rr_list_rr_count(q), + (int)ldns_rr_list_rr_count(p)); + return 0; + } + for(i=0; ibits & EDNS_DO) ); + unit_assert(ret != 0); /* udp packets should fit */ + attach_edns_record(out, edns); + regional_free_all(r2); + } + if(gettimeofday(&end, NULL) < 0) + fatal_exit("gettimeofday: %s", strerror(errno)); + /* time in millisec */ + dt = (double)(end.tv_sec - start.tv_sec)*1000. + + ((double)end.tv_usec - (double)start.tv_usec)/1000.; + printf("[%d] did %u in %g msec for %f encode/sec size %d\n", num++, + (unsigned)max, dt, (double)max / (dt/1000.), + (int)ldns_buffer_limit(out)); + regional_destroy(r2); +} + +/** perf test a packet */ +static void +perftestpkt(ldns_buffer* pkt, struct alloc_cache* alloc, ldns_buffer* out, + const char* hex) +{ + struct query_info qi; + struct reply_info* rep = 0; + int ret; + uint16_t id; + uint16_t flags; + uint32_t timenow = 0; + struct regional* region = regional_create(); + struct edns_data edns; + + hex_to_buf(pkt, hex); + memmove(&id, ldns_buffer_begin(pkt), sizeof(id)); + if(ldns_buffer_limit(pkt) < 2) + flags = 0; + else memmove(&flags, ldns_buffer_at(pkt, 2), sizeof(flags)); + flags = ntohs(flags); + ret = reply_info_parse(pkt, alloc, &qi, &rep, region, &edns); + if(ret != 0) { + if(vbmp) printf("parse code %d: %s\n", ret, + ldns_lookup_by_id(ldns_rcodes, ret)->name); + if(ret == LDNS_RCODE_FORMERR) + checkformerr(pkt); + unit_assert(ret != LDNS_RCODE_SERVFAIL); + } else { + perf_encode(&qi, rep, id, flags, out, timenow, &edns); + } + + query_info_clear(&qi); + reply_info_parsedelete(rep, alloc); + regional_destroy(region); +} + +/** debug print a packet that failed */ +static void +print_packet_rrsets(struct query_info* qinfo, struct reply_info* rep) +{ + size_t i; + ldns_rr_list* l; + ldns_buffer* buf = ldns_buffer_new(65536); + log_query_info(0, "failed query", qinfo); + printf(";; ANSWER SECTION (%d rrsets)\n", (int)rep->an_numrrsets); + for(i=0; ian_numrrsets; i++) { + l = packed_rrset_to_rr_list(rep->rrsets[i], buf); + printf("; rrset %d\n", (int)i); + ldns_rr_list_print(stdout, l); + ldns_rr_list_deep_free(l); + } + printf(";; AUTHORITY SECTION (%d rrsets)\n", (int)rep->ns_numrrsets); + for(i=rep->an_numrrsets; ian_numrrsets+rep->ns_numrrsets; i++) { + l = packed_rrset_to_rr_list(rep->rrsets[i], buf); + printf("; rrset %d\n", (int)i); + ldns_rr_list_print(stdout, l); + ldns_rr_list_deep_free(l); + } + printf(";; ADDITIONAL SECTION (%d rrsets)\n", (int)rep->ar_numrrsets); + for(i=rep->an_numrrsets+rep->ns_numrrsets; irrset_count; i++) { + l = packed_rrset_to_rr_list(rep->rrsets[i], buf); + printf("; rrset %d\n", (int)i); + ldns_rr_list_print(stdout, l); + ldns_rr_list_deep_free(l); + } + printf(";; packet end\n"); + ldns_buffer_free(buf); +} + +/** check that there is no data element that matches the RRSIG */ +static int +no_data_for_rrsig(struct reply_info* rep, struct ub_packed_rrset_key* rrsig) +{ + size_t i; + for(i=0; irrset_count; i++) { + if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_RRSIG) + continue; + if(query_dname_compare(rep->rrsets[i]->rk.dname, + rrsig->rk.dname) == 0) + /* only name is compared right now */ + return 0; + } + return 1; +} + +/** check RRSIGs in packet */ +static void +check_the_rrsigs(struct query_info* qinfo, struct reply_info* rep) +{ + /* every RRSIG must be matched to an RRset */ + size_t i; + for(i=0; irrset_count; i++) { + struct ub_packed_rrset_key* s = rep->rrsets[i]; + if(ntohs(s->rk.type) == LDNS_RR_TYPE_RRSIG) { + /* see if really a problem, i.e. is there a data + * element. */ + if(no_data_for_rrsig(rep, rep->rrsets[i])) + continue; + log_dns_msg("rrsig failed for packet", qinfo, rep); + print_packet_rrsets(qinfo, rep); + printf("failed rrset is nr %d\n", (int)i); + unit_assert(0); + } + } +} + +/** test a packet */ +static void +testpkt(ldns_buffer* pkt, struct alloc_cache* alloc, ldns_buffer* out, + const char* hex) +{ + struct query_info qi; + struct reply_info* rep = 0; + int ret; + uint16_t id; + uint16_t flags; + uint32_t timenow = 0; + struct regional* region = regional_create(); + struct edns_data edns; + + hex_to_buf(pkt, hex); + memmove(&id, ldns_buffer_begin(pkt), sizeof(id)); + if(ldns_buffer_limit(pkt) < 2) + flags = 0; + else memmove(&flags, ldns_buffer_at(pkt, 2), sizeof(flags)); + flags = ntohs(flags); + ret = reply_info_parse(pkt, alloc, &qi, &rep, region, &edns); + if(ret != 0) { + if(vbmp) printf("parse code %d: %s\n", ret, + ldns_lookup_by_id(ldns_rcodes, ret)->name); + if(ret == LDNS_RCODE_FORMERR) { + unit_assert(!check_formerr_gone); + checkformerr(pkt); + } + unit_assert(ret != LDNS_RCODE_SERVFAIL); + } else if(!check_formerr_gone) { + const size_t lim = 512; + ret = reply_info_encode(&qi, rep, id, flags, out, timenow, + region, 65535, (int)(edns.bits & EDNS_DO) ); + unit_assert(ret != 0); /* udp packets should fit */ + attach_edns_record(out, &edns); + if(vbmp) printf("inlen %u outlen %u\n", + (unsigned)ldns_buffer_limit(pkt), + (unsigned)ldns_buffer_limit(out)); + if(!check_nosameness) + test_buffers(pkt, out); + if(check_rrsigs) + check_the_rrsigs(&qi, rep); + + if(ldns_buffer_limit(out) > lim) { + ret = reply_info_encode(&qi, rep, id, flags, out, + timenow, region, + lim - calc_edns_field_size(&edns), + (int)(edns.bits & EDNS_DO)); + unit_assert(ret != 0); /* should fit, but with TC */ + attach_edns_record(out, &edns); + if( LDNS_QDCOUNT(ldns_buffer_begin(out)) != + LDNS_QDCOUNT(ldns_buffer_begin(pkt)) || + LDNS_ANCOUNT(ldns_buffer_begin(out)) != + LDNS_ANCOUNT(ldns_buffer_begin(pkt)) || + LDNS_NSCOUNT(ldns_buffer_begin(out)) != + LDNS_NSCOUNT(ldns_buffer_begin(pkt))) + unit_assert( + LDNS_TC_WIRE(ldns_buffer_begin(out))); + /* must set TC bit if shortened */ + unit_assert(ldns_buffer_limit(out) <= lim); + } + } + + query_info_clear(&qi); + reply_info_parsedelete(rep, alloc); + regional_destroy(region); +} + +/** simple test of parsing */ +static void +simpletest(ldns_buffer* pkt, struct alloc_cache* alloc, ldns_buffer* out) +{ + /* a root query drill -q - */ + testpkt(pkt, alloc, out, + " c5 40 01 00 00 01 00 00 00 00 00 00 00 00 02 00 01 "); + + /* very small packet */ + testpkt(pkt, alloc, out, +"; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19\n" +";-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --\n" +"74 0c 85 83 00 01 00 00 00 01 00 00 03 62 6c 61 09 6e 6c 6e ; 1- 20\n" +"65 74 6c 61 62 73 02 6e 6c 00 00 0f 00 01 09 6e 6c 6e 65 74 ; 21- 40\n" +"6c 61 62 73 02 6e 6c 00 00 06 00 01 00 00 46 50 00 40 04 6f ; 41- 60\n" +"70 65 6e 09 6e 6c 6e 65 74 6c 61 62 73 02 6e 6c 00 0a 68 6f ; 61- 80\n" +"73 74 6d 61 73 74 65 72 09 6e 6c 6e 65 74 6c 61 62 73 02 6e ; 81- 100\n" +"6c 00 77 a1 02 58 00 00 70 80 00 00 1c 20 00 09 3a 80 00 00 ; 101- 120\n" +"46 50\n"); + + /* a root reply drill -w - */ + testpkt(pkt, alloc, out, + " ; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19\n" + " ;-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --\n" + " 97 3f 81 80 00 01 00 0d 00 00 00 02 00 00 02 00 01 00 00 02 ; 1- 20\n" + " 00 01 00 06 6d 38 00 14 01 49 0c 52 4f 4f 54 2d 53 45 52 56 ; 21- 40\n" + " 45 52 53 03 4e 45 54 00 00 00 02 00 01 00 06 6d 38 00 14 01 ; 41- 60\n" + " 4a 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 00 ; 61- 80\n" + " 00 02 00 01 00 06 6d 38 00 14 01 4b 0c 52 4f 4f 54 2d 53 45 ; 81- 100\n" + " 52 56 45 52 53 03 4e 45 54 00 00 00 02 00 01 00 06 6d 38 00 ; 101- 120\n" + " 14 01 4c 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54 ; 121- 140\n" + " 00 00 00 02 00 01 00 06 6d 38 00 14 01 4d 0c 52 4f 4f 54 2d ; 141- 160\n" + " 53 45 52 56 45 52 53 03 4e 45 54 00 00 00 02 00 01 00 06 6d ; 161- 180\n" + " 38 00 14 01 41 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e ; 181- 200\n" + " 45 54 00 00 00 02 00 01 00 06 6d 38 00 14 01 42 0c 52 4f 4f ; 201- 220\n" + " 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 00 00 02 00 01 00 ; 221- 240\n" + " 06 6d 38 00 14 01 43 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 ; 241- 260\n" + " 03 4e 45 54 00 00 00 02 00 01 00 06 6d 38 00 14 01 44 0c 52 ; 261- 280\n" + " 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 00 00 02 00 ; 281- 300\n" + " 01 00 06 6d 38 00 14 01 45 0c 52 4f 4f 54 2d 53 45 52 56 45 ; 301- 320\n" + " 52 53 03 4e 45 54 00 00 00 02 00 01 00 06 6d 38 00 14 01 46 ; 321- 340\n" + " 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 00 00 ; 341- 360\n" + " 02 00 01 00 06 6d 38 00 14 01 47 0c 52 4f 4f 54 2d 53 45 52 ; 361- 380\n" + " 56 45 52 53 03 4e 45 54 00 00 00 02 00 01 00 06 6d 38 00 14 ; 381- 400\n" + " 01 48 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 ; 401- 420\n" + " 01 41 0c 52 4f 4f 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 ; 421- 440\n" + " 00 01 00 01 00 02 64 b9 00 04 c6 29 00 04 01 4a 0c 52 4f 4f ; 441- 460\n" + " 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 00 01 00 01 00 02 ; 461- 480\n" + " 64 b9 00 04 c0 3a 80 1e "); + + /* root delegation from unbound trace with new AAAA glue */ + perftestpkt(pkt, alloc, out, + "55BC84000001000D00000014000002000100000200010007E900001401610C726F6F742D73657276657273036E65740000000200010007E90000040162C01E00000200010007E90000040163C01E00000200010007E90000040164C01E00000200010007E90000040165C01E00000200010007E90000040166C01E00000200010007E90000040167C01E00000200010007E90000040168C01E00000200010007E90000040169C01E00000200010007E9000004016AC01E00000200010007E9000004016BC01E00000200010007E9000004016CC01E00000200010007E9000004016DC01EC01C000100010007E9000004C6290004C03B000100010007E9000004C0E44FC9C04A000100010007E9000004C021040CC059000100010007E900000480080A5AC068000100010007E9000004C0CBE60AC077000100010007E9000004C00505F1C086000100010007E9000004C0702404C095000100010007E9000004803F0235C0A4000100010007E9000004C0249411C0B3000100010007E9000004C03A801EC0C2000100010007E9000004C1000E81C0D1000100010007E9000004C707532AC0E0000100010007E9000004CA0C1B21C01C001C00010007E900001020010503BA3E00000000000000020030C077001C00010007E900001020010500002F0000000000000000000FC095001C00010007E90000102001050000010000" + "00000000803F0235C0B3001C00010007E9000010200105030C2700000000000000020030C0C2001C00010007E9000010200107FD000000000000000000000001C0E0001C00010007E900001020010DC30000000000000000000000350000291000000000000000" + ); +} + +/** simple test of parsing, pcat file */ +static void +testfromfile(ldns_buffer* pkt, struct alloc_cache* alloc, ldns_buffer* out, + const char* fname) +{ + FILE* in = fopen(fname, "r"); + char buf[102400]; + int no=0; + if(!in) { + perror("fname"); + return; + } + while(fgets(buf, (int)sizeof(buf), in)) { + if(buf[0] == ';') /* comment */ + continue; + if(strlen(buf) < 10) /* skip pcat line numbers. */ + continue; + if(vbmp) { + printf("test no %d: %s", no, buf); + fflush(stdout); + } + testpkt(pkt, alloc, out, buf); + no++; + } + fclose(in); +} + +/** simple test of parsing, drill file */ +static void +testfromdrillfile(ldns_buffer* pkt, struct alloc_cache* alloc, + ldns_buffer* out, const char* fname) +{ + /* ;-- is used to indicate a new message */ + FILE* in = fopen(fname, "r"); + char buf[102400]; + char* np = buf; + buf[0]=0; + if(!in) { + perror("fname"); + return; + } + while(fgets(np, (int)sizeof(buf) - (np-buf), in)) { + if(strncmp(np, ";--", 3) == 0) { + /* new entry */ + /* test previous */ + if(np != buf) + testpkt(pkt, alloc, out, buf); + /* set for new entry */ + np = buf; + buf[0]=0; + continue; + } + if(np[0] == ';') /* comment */ + continue; + np = &np[strlen(np)]; + } + testpkt(pkt, alloc, out, buf); + fclose(in); +} + +void msgparse_test(void) +{ + ldns_buffer* pkt = ldns_buffer_new(65553); + ldns_buffer* out = ldns_buffer_new(65553); + struct alloc_cache super_a, alloc; + /* init */ + alloc_init(&super_a, NULL, 0); + alloc_init(&alloc, &super_a, 2); + + unit_show_feature("message parse"); + simpletest(pkt, &alloc, out); + /* plain hex dumps, like pcat */ + testfromfile(pkt, &alloc, out, "testdata/test_packets.1"); + testfromfile(pkt, &alloc, out, "testdata/test_packets.2"); + testfromfile(pkt, &alloc, out, "testdata/test_packets.3"); + /* like from drill -w - */ + testfromdrillfile(pkt, &alloc, out, "testdata/test_packets.4"); + testfromdrillfile(pkt, &alloc, out, "testdata/test_packets.5"); + + matches_nolocation = 1; /* RR order not important for the next test */ + testfromdrillfile(pkt, &alloc, out, "testdata/test_packets.6"); + check_rrsigs = 1; + testfromdrillfile(pkt, &alloc, out, "testdata/test_packets.7"); + check_rrsigs = 0; + matches_nolocation = 0; + + check_formerr_gone = 1; + testfromdrillfile(pkt, &alloc, out, "testdata/test_packets.8"); + check_formerr_gone = 0; + + check_rrsigs = 1; + check_nosameness = 1; + testfromdrillfile(pkt, &alloc, out, "testdata/test_packets.9"); + check_nosameness = 0; + check_rrsigs = 0; + + /* cleanup */ + alloc_clear(&alloc); + alloc_clear(&super_a); + ldns_buffer_free(pkt); + ldns_buffer_free(out); +} diff --git a/testcode/unitneg.c b/testcode/unitneg.c new file mode 100644 index 00000000000..e18aefc34b6 --- /dev/null +++ b/testcode/unitneg.c @@ -0,0 +1,542 @@ +/* + * testcode/unitneg.c - unit test for negative cache routines. + * + * Copyright (c) 2008, 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +/** + * \file + * Calls negative cache unit tests. Exits with code 1 on a failure. + */ + +#include "config.h" +#include "util/log.h" +#include "util/net_help.h" +#include "util/data/packed_rrset.h" +#include "util/data/dname.h" +#include "testcode/unitmain.h" +#include "validator/val_neg.h" + +/** verbose unit test for negative cache */ +static int negverbose = 0; + +/** debug printout of neg cache */ +static void print_neg_cache(struct val_neg_cache* neg) +{ + char buf[1024]; + struct val_neg_zone* z; + struct val_neg_data* d; + printf("neg_cache print\n"); + printf("memuse %d of %d\n", (int)neg->use, (int)neg->max); + printf("maxiter %d\n", (int)neg->nsec3_max_iter); + printf("%d zones\n", (int)neg->tree.count); + RBTREE_FOR(z, struct val_neg_zone*, &neg->tree) { + dname_str(z->name, buf); + printf("%24s", buf); + printf(" len=%2.2d labs=%d inuse=%d count=%d tree.count=%d\n", + (int)z->len, z->labs, (int)z->in_use, z->count, + (int)z->tree.count); + } + RBTREE_FOR(z, struct val_neg_zone*, &neg->tree) { + printf("\n"); + dname_print(stdout, NULL, z->name); + printf(" zone details\n"); + printf("len=%2.2d labs=%d inuse=%d count=%d tree.count=%d\n", + (int)z->len, z->labs, (int)z->in_use, z->count, + (int)z->tree.count); + if(z->parent) { + printf("parent="); + dname_print(stdout, NULL, z->parent->name); + printf("\n"); + } else { + printf("parent=NULL\n"); + } + + RBTREE_FOR(d, struct val_neg_data*, &z->tree) { + dname_str(d->name, buf); + printf("%24s", buf); + printf(" len=%2.2d labs=%d inuse=%d count=%d\n", + (int)d->len, d->labs, (int)d->in_use, d->count); + } + } +} + +/** get static pointer to random zone name */ +static char* get_random_zone(void) +{ + static char zname[256]; + int labels = random() % 3; + int i; + char* p = zname; + int labnum; + + for(i=0; ilock); + if(negverbose) + log_nametypeclass(0, "add to zone", (uint8_t*)zname, 0, 0); + z = neg_find_zone(neg, (uint8_t*)zname, strlen(zname)+1, + LDNS_RR_CLASS_IN); + if(!z) { + z = neg_create_zone(neg, (uint8_t*)zname, strlen(zname)+1, + LDNS_RR_CLASS_IN); + } + unit_assert(z); + val_neg_zone_take_inuse(z); + + /* construct random NSEC item */ + get_random_data(&from, &to, zname); + + /* create nsec and insert it */ + memset(&rd, 0, sizeof(rd)); + memset(&nsec, 0, sizeof(nsec)); + nsec.rk.dname = (uint8_t*)from; + nsec.rk.dname_len = strlen(from)+1; + nsec.rk.type = htons(LDNS_RR_TYPE_NSEC); + nsec.rk.rrset_class = htons(LDNS_RR_CLASS_IN); + nsec.entry.data = &rd; + rd.security = sec_status_secure; + rd.count = 1; + rd.rr_len = &rr_len; + rr_len = 19; + rd.rr_ttl = &rr_ttl; + rr_ttl = 0; + rd.rr_data = &rr_data; + rr_data = (uint8_t*)to; + + neg_insert_data(neg, z, &nsec); + lock_basic_unlock(&neg->lock); +} + +/** remove a random item */ +static void remove_item(struct val_neg_cache* neg) +{ + int n, i; + struct val_neg_data* d; + rbnode_t* walk; + struct val_neg_zone* z; + + lock_basic_lock(&neg->lock); + if(neg->tree.count == 0) { + lock_basic_unlock(&neg->lock); + return; /* nothing to delete */ + } + + /* pick a random zone */ + walk = rbtree_first(&neg->tree); /* first highest parent, big count */ + z = (struct val_neg_zone*)walk; + n = random() % (int)(z->count); + if(negverbose) + printf("neg stress delete zone %d\n", n); + i=0; + walk = rbtree_first(&neg->tree); + z = (struct val_neg_zone*)walk; + while(i!=n+1 && walk && walk != RBTREE_NULL && !z->in_use) { + walk = rbtree_next(walk); + z = (struct val_neg_zone*)walk; + if(z->in_use) + i++; + } + if(!walk || walk == RBTREE_NULL) { + lock_basic_unlock(&neg->lock); + return; + } + if(!z->in_use) { + lock_basic_unlock(&neg->lock); + return; + } + if(negverbose) + log_nametypeclass(0, "delete zone", z->name, 0, 0); + + /* pick a random nsec item. - that is in use */ + walk = rbtree_first(&z->tree); /* first is highest parent */ + d = (struct val_neg_data*)walk; + n = random() % (int)(d->count); + if(negverbose) + printf("neg stress delete item %d\n", n); + i=0; + walk = rbtree_first(&z->tree); + d = (struct val_neg_data*)walk; + while(i!=n+1 && walk && walk != RBTREE_NULL && !d->in_use) { + walk = rbtree_next(walk); + d = (struct val_neg_data*)walk; + if(d->in_use) + i++; + } + if(!walk || walk == RBTREE_NULL) { + lock_basic_unlock(&neg->lock); + return; + } + if(d->in_use) { + if(negverbose) + log_nametypeclass(0, "neg delete item:", d->name, 0, 0); + neg_delete_data(neg, d); + } + lock_basic_unlock(&neg->lock); +} + +/** sum up the zone trees */ +static size_t sumtrees_all(struct val_neg_cache* neg) +{ + size_t res = 0; + struct val_neg_zone* z; + RBTREE_FOR(z, struct val_neg_zone*, &neg->tree) { + res += z->tree.count; + } + return res; +} + +/** sum up the zone trees, in_use only */ +static size_t sumtrees_inuse(struct val_neg_cache* neg) +{ + size_t res = 0; + struct val_neg_zone* z; + struct val_neg_data* d; + RBTREE_FOR(z, struct val_neg_zone*, &neg->tree) { + /* get count of highest parent for num in use */ + d = (struct val_neg_data*)rbtree_first(&z->tree); + if(d && (rbnode_t*)d!=RBTREE_NULL) + res += d->count; + } + return res; +} + +/** check if lru is still valid */ +static void check_lru(struct val_neg_cache* neg) +{ + struct val_neg_data* p, *np; + size_t num = 0; + size_t inuse; + p = neg->first; + while(p) { + if(!p->prev) { + unit_assert(neg->first == p); + } + np = p->next; + if(np) { + unit_assert(np->prev == p); + } else { + unit_assert(neg->last == p); + } + num++; + p = np; + } + inuse = sumtrees_inuse(neg); + if(negverbose) + printf("num lru %d, inuse %d, all %d\n", + (int)num, (int)sumtrees_inuse(neg), + (int)sumtrees_all(neg)); + unit_assert( num == inuse); + unit_assert( inuse <= sumtrees_all(neg)); +} + +/** sum up number of items inuse in subtree */ +static int sum_subtree_inuse(struct val_neg_zone* zone, + struct val_neg_data* data) +{ + struct val_neg_data* d; + int num = 0; + RBTREE_FOR(d, struct val_neg_data*, &zone->tree) { + if(dname_subdomain_c(d->name, data->name)) { + if(d->in_use) + num++; + } + } + return num; +} + +/** sum up number of items inuse in subtree */ +static int sum_zone_subtree_inuse(struct val_neg_cache* neg, + struct val_neg_zone* zone) +{ + struct val_neg_zone* z; + int num = 0; + RBTREE_FOR(z, struct val_neg_zone*, &neg->tree) { + if(dname_subdomain_c(z->name, zone->name)) { + if(z->in_use) + num++; + } + } + return num; +} + +/** check point in data tree */ +static void check_data(struct val_neg_zone* zone, struct val_neg_data* data) +{ + unit_assert(data->count > 0); + if(data->parent) { + unit_assert(data->parent->count >= data->count); + if(data->parent->in_use) { + unit_assert(data->parent->count > data->count); + } + unit_assert(data->parent->labs == data->labs-1); + /* and parent must be one label shorter */ + unit_assert(data->name[0] == (data->len-data->parent->len-1)); + unit_assert(query_dname_compare(data->name + data->name[0]+1, + data->parent->name) == 0); + } else { + /* must be apex */ + unit_assert(dname_is_root(data->name)); + } + /* tree property: */ + unit_assert(data->count == sum_subtree_inuse(zone, data)); +} + +/** check if tree of data in zone is valid */ +static void checkzonetree(struct val_neg_zone* zone) +{ + struct val_neg_data* d; + + /* check all data in tree */ + RBTREE_FOR(d, struct val_neg_data*, &zone->tree) { + check_data(zone, d); + } +} + +/** check if negative cache is still valid */ +static void check_zone_invariants(struct val_neg_cache* neg, + struct val_neg_zone* zone) +{ + unit_assert(zone->nsec3_hash == 0); + unit_assert(zone->tree.cmp == &val_neg_data_compare); + unit_assert(zone->count != 0); + + if(zone->tree.count == 0) + unit_assert(!zone->in_use); + else { + if(!zone->in_use) { + /* details on error */ + log_nametypeclass(0, "zone", zone->name, 0, 0); + log_err("inuse %d count=%d tree.count=%d", + zone->in_use, zone->count, + (int)zone->tree.count); + if(negverbose) + print_neg_cache(neg); + } + unit_assert(zone->in_use); + } + + if(zone->parent) { + unit_assert(zone->parent->count >= zone->count); + if(zone->parent->in_use) { + unit_assert(zone->parent->count > zone->count); + } + unit_assert(zone->parent->labs == zone->labs-1); + /* and parent must be one label shorter */ + unit_assert(zone->name[0] == (zone->len-zone->parent->len-1)); + unit_assert(query_dname_compare(zone->name + zone->name[0]+1, + zone->parent->name) == 0); + } else { + /* must be apex */ + unit_assert(dname_is_root(zone->name)); + } + /* tree property: */ + unit_assert(zone->count == sum_zone_subtree_inuse(neg, zone)); + + /* check structure of zone data tree */ + checkzonetree(zone); +} + +/** check if negative cache is still valid */ +static void check_neg_invariants(struct val_neg_cache* neg) +{ + struct val_neg_zone* z; + /* check structure of LRU list */ + lock_basic_lock(&neg->lock); + check_lru(neg); + unit_assert(neg->max == 1024*1024); + unit_assert(neg->nsec3_max_iter == 1500); + unit_assert(neg->tree.cmp == &val_neg_zone_compare); + + if(neg->tree.count == 0) { + /* empty */ + unit_assert(neg->tree.count == 0); + unit_assert(neg->first == NULL); + unit_assert(neg->last == NULL); + unit_assert(neg->use == 0); + lock_basic_unlock(&neg->lock); + return; + } + + unit_assert(neg->first != NULL); + unit_assert(neg->last != NULL); + + RBTREE_FOR(z, struct val_neg_zone*, &neg->tree) { + check_zone_invariants(neg, z); + } + lock_basic_unlock(&neg->lock); +} + +/** perform stress test on insert and delete in neg cache */ +static void stress_test(struct val_neg_cache* neg) +{ + int i; + if(negverbose) + printf("negcache test\n"); + for(i=0; i<100; i++) { + if(random() % 10 < 8) + add_item(neg); + else remove_item(neg); + check_neg_invariants(neg); + } + /* empty it */ + if(negverbose) + printf("neg stress empty\n"); + while(neg->first) { + remove_item(neg); + check_neg_invariants(neg); + } + if(negverbose) + printf("neg stress emptied\n"); + unit_assert(neg->first == NULL); + /* insert again */ + for(i=0; i<100; i++) { + if(random() % 10 < 8) + add_item(neg); + else remove_item(neg); + check_neg_invariants(neg); + } +} + +void neg_test(void) +{ + struct val_neg_cache* neg; + srandom(48); + unit_show_feature("negative cache"); + + /* create with defaults */ + neg = val_neg_create(NULL, 1500); + unit_assert(neg); + + stress_test(neg); + + neg_cache_delete(neg); +} diff --git a/testcode/unitregional.c b/testcode/unitregional.c new file mode 100644 index 00000000000..93249deb4ee --- /dev/null +++ b/testcode/unitregional.c @@ -0,0 +1,244 @@ +/* + * testcode/unitregional.c - unit test for regional allocator. + * + * Copyright (c) 2010, 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +/** + * \file + * Tests the regional special purpose allocator. + */ + +#include "config.h" +#include "testcode/unitmain.h" +#include "util/log.h" +#include "util/regional.h" + +/** test regional corner cases, zero, one, end of structure */ +static void +corner_cases(struct regional* r) +{ + size_t s; /* shadow count of allocated memory */ + void* a; + size_t minsize = sizeof(uint64_t); + size_t mysize; + char* str; + unit_assert(r); + /* alloc cases: + * 0, 1, 2. + * smaller than LARGE_OBJECT_SIZE. + * smaller but does not fit in remainder in regional. + * smaller but exactly fits in remainder of regional. + * size is remainder of regional - 8. + * size is remainder of regional + 8. + * larger than LARGE_OBJECT_SIZE. + */ + s = sizeof(struct regional); + unit_assert((s % minsize) == 0); + unit_assert(r->available == r->first_size - s); + unit_assert(r->large_list == NULL); + unit_assert(r->next == NULL); + + /* Note an alloc of 0 gets a pointer to current last + * position (where you should then use 0 bytes) */ + a = regional_alloc(r, 0); + unit_assert(a); + s+=0; + unit_assert(r->available == r->first_size - s); + + a = regional_alloc(r, 1); + unit_assert(a); + memset(a, 0x42, 1); + s+=minsize; + unit_assert(r->available == r->first_size - s); + + a = regional_alloc(r, 2); + unit_assert(a); + memset(a, 0x42, 2); + s+=minsize; + unit_assert(r->available == r->first_size - s); + + a = regional_alloc(r, 128); + unit_assert(a); + memset(a, 0x42, 128); + s+=128; + unit_assert(r->available == r->first_size - s); + + unit_assert(r->large_list == NULL); + a = regional_alloc(r, 10240); + unit_assert(a); + unit_assert(r->large_list != NULL); + memset(a, 0x42, 10240); + /* s does not change */ + unit_assert(r->available == r->first_size - s); + unit_assert(r->total_large == 10240+minsize); + + /* go towards the end of the current chunk */ + while(r->available > 1024) { + a = regional_alloc(r, 1024); + unit_assert(a); + memset(a, 0x42, 1024); + s += 1024; + unit_assert(r->available == r->first_size - s); + } + + unit_assert(r->next == NULL); + mysize = 1280; /* does not fit in current chunk */ + a = regional_alloc(r, mysize); + memset(a, 0x42, mysize); + unit_assert(r->next != NULL); + unit_assert(a); + + /* go towards the end of the current chunk */ + while(r->available > 864) { + a = regional_alloc(r, 864); + unit_assert(a); + memset(a, 0x42, 864); + s += 864; + } + + mysize = r->available; /* exactly fits */ + a = regional_alloc(r, mysize); + memset(a, 0x42, mysize); + unit_assert(a); + unit_assert(r->available == 0); /* implementation does not go ahead*/ + + a = regional_alloc(r, 8192); /* another large allocation */ + unit_assert(a); + memset(a, 0x42, 8192); + unit_assert(r->available == 0); + unit_assert(r->total_large == 10240 + 8192 + 2*minsize); + + a = regional_alloc(r, 32); /* make new chunk */ + unit_assert(a); + memset(a, 0x42, 32); + unit_assert(r->available > 0); + unit_assert(r->total_large == 10240 + 8192 + 2*minsize); + + /* go towards the end of the current chunk */ + while(r->available > 1320) { + a = regional_alloc(r, 1320); + unit_assert(a); + memset(a, 0x42, 1320); + s += 1320; + } + + mysize = r->available + 8; /* exact + 8 ; does not fit */ + a = regional_alloc(r, mysize); + memset(a, 0x42, mysize); + unit_assert(a); + unit_assert(r->available > 0); /* new chunk */ + + /* go towards the end of the current chunk */ + while(r->available > 1480) { + a = regional_alloc(r, 1480); + unit_assert(a); + memset(a, 0x42, 1480); + s += 1480; + } + + mysize = r->available - 8; /* exact - 8 ; fits. */ + a = regional_alloc(r, mysize); + memset(a, 0x42, mysize); + unit_assert(a); + unit_assert(r->available == 8); + + /* test if really copied over */ + str = "test12345"; + a = regional_alloc_init(r, str, 8); + unit_assert(a); + unit_assert(memcmp(a, str, 8) == 0); + + /* test if really zeroed */ + a = regional_alloc_zero(r, 32); + str="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; + unit_assert(a); + unit_assert(memcmp(a, str, 32) == 0); + + /* test if copied over (and null byte) */ + str = "an interesting string"; + a = regional_strdup(r, str); + unit_assert(a); + unit_assert(memcmp(a, str, strlen(str)+1) == 0); + + regional_free_all(r); +} + +/** test specific cases */ +static void +specific_cases(void) +{ + struct regional* r = regional_create(); + corner_cases(r); + regional_destroy(r); + r = regional_create_custom(2048); /* a small regional */ + unit_assert(r->first_size == 2048); + unit_assert(regional_get_mem(r) == 2048); + corner_cases(r); + unit_assert(regional_get_mem(r) == 2048); + regional_destroy(r); +} + +/** put random stuff in a region and free it */ +static void +burden_test(size_t max) +{ + size_t get; + void* a; + int i; + struct regional* r = regional_create_custom(2048); + for(i=0; i<1000; i++) { + get = random() % max; + a = regional_alloc(r, get); + unit_assert(a); + memset(a, 0x54, get); + } + regional_free_all(r); + regional_destroy(r); +} + +/** randomly allocate stuff */ +static void +random_burden(void) +{ + size_t max_alloc = 2048 + 128; /* small chance of LARGE */ + int i; + for(i=0; i<100; i++) + burden_test(max_alloc); +} + +void regional_test(void) +{ + unit_show_feature("regional"); + specific_cases(); + random_burden(); +} diff --git a/testcode/unitslabhash.c b/testcode/unitslabhash.c new file mode 100644 index 00000000000..70f1c58b0ec --- /dev/null +++ b/testcode/unitslabhash.c @@ -0,0 +1,376 @@ +/* + * testcode/unitslabhash.c - unit test for slabhash table. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +/** + * \file + * Tests the locking LRU keeping hash table implementation. + */ + +#include "config.h" +#include "testcode/unitmain.h" +#include "util/log.h" +#include "util/storage/slabhash.h" + +/** use this type for the slabhash test key */ +typedef struct slabhash_testkey testkey_t; +/** use this type for the slabhash test data */ +typedef struct slabhash_testdata testdata_t; + +/** delete key */ +static void delkey(struct slabhash_testkey* k) { + lock_rw_destroy(&k->entry.lock); free(k);} + +/** hash func, very bad to improve collisions, both high and low bits */ +static hashvalue_t myhash(int id) { + hashvalue_t h = (hashvalue_t)id & 0x0f; + h |= (h << 28); + return h; +} + +/** allocate new key, fill in hash */ +static testkey_t* newkey(int id) { + testkey_t* k = (testkey_t*)calloc(1, sizeof(testkey_t)); + if(!k) fatal_exit("out of memory"); + k->id = id; + k->entry.hash = myhash(id); + k->entry.key = k; + lock_rw_init(&k->entry.lock); + return k; +} +/** new data el */ +static testdata_t* newdata(int val) { + testdata_t* d = (testdata_t*)calloc(1, + sizeof(testdata_t)); + if(!d) fatal_exit("out of memory"); + d->data = val; + return d; +} + +/** test hashtable using short sequence */ +static void +test_short_table(struct slabhash* table) +{ + testkey_t* k = newkey(12); + testkey_t* k2 = newkey(14); + testdata_t* d = newdata(128); + testdata_t* d2 = newdata(129); + + k->entry.data = d; + k2->entry.data = d2; + + slabhash_insert(table, myhash(12), &k->entry, d, NULL); + slabhash_insert(table, myhash(14), &k2->entry, d2, NULL); + + unit_assert( slabhash_lookup(table, myhash(12), k, 0) == &k->entry); + lock_rw_unlock( &k->entry.lock ); + unit_assert( slabhash_lookup(table, myhash(14), k2, 0) == &k2->entry); + lock_rw_unlock( &k2->entry.lock ); + slabhash_remove(table, myhash(12), k); + slabhash_remove(table, myhash(14), k2); +} + +/** number of hash test max */ +#define HASHTESTMAX 32 + +/** test adding a random element */ +static void +testadd(struct slabhash* table, testdata_t* ref[]) +{ + int numtoadd = random() % HASHTESTMAX; + testdata_t* data = newdata(numtoadd); + testkey_t* key = newkey(numtoadd); + key->entry.data = data; + slabhash_insert(table, myhash(numtoadd), &key->entry, data, NULL); + ref[numtoadd] = data; +} + +/** test adding a random element */ +static void +testremove(struct slabhash* table, testdata_t* ref[]) +{ + int num = random() % HASHTESTMAX; + testkey_t* key = newkey(num); + slabhash_remove(table, myhash(num), key); + ref[num] = NULL; + delkey(key); +} + +/** test adding a random element */ +static void +testlookup(struct slabhash* table, testdata_t* ref[]) +{ + int num = random() % HASHTESTMAX; + testkey_t* key = newkey(num); + struct lruhash_entry* en = slabhash_lookup(table, myhash(num), key, 0); + testdata_t* data = en? (testdata_t*)en->data : NULL; + if(en) { + unit_assert(en->key); + unit_assert(en->data); + } + if(0) log_info("lookup %d got %d, expect %d", num, en? data->data :-1, + ref[num]? ref[num]->data : -1); + unit_assert( data == ref[num] ); + if(en) { lock_rw_unlock(&en->lock); } + delkey(key); +} + +/** check integrity of hash table */ +static void +check_lru_table(struct lruhash* table) +{ + struct lruhash_entry* p; + size_t c = 0; + lock_quick_lock(&table->lock); + unit_assert( table->num <= table->size); + unit_assert( table->size_mask == (int)table->size-1 ); + unit_assert( (table->lru_start && table->lru_end) || + (!table->lru_start && !table->lru_end) ); + unit_assert( table->space_used <= table->space_max ); + /* check lru list integrity */ + if(table->lru_start) + unit_assert(table->lru_start->lru_prev == NULL); + if(table->lru_end) + unit_assert(table->lru_end->lru_next == NULL); + p = table->lru_start; + while(p) { + if(p->lru_prev) { + unit_assert(p->lru_prev->lru_next == p); + } + if(p->lru_next) { + unit_assert(p->lru_next->lru_prev == p); + } + c++; + p = p->lru_next; + } + unit_assert(c == table->num); + + /* this assertion is specific to the unit test */ + unit_assert( table->space_used == + table->num * test_slabhash_sizefunc(NULL, NULL) ); + lock_quick_unlock(&table->lock); +} + +/** check integrity of hash table */ +static void +check_table(struct slabhash* table) +{ + size_t i; + for(i=0; isize; i++) + check_lru_table(table->array[i]); +} + +/** test adding a random element (unlimited range) */ +static void +testadd_unlim(struct slabhash* table, testdata_t** ref) +{ + int numtoadd = random() % (HASHTESTMAX * 10); + testdata_t* data = newdata(numtoadd); + testkey_t* key = newkey(numtoadd); + key->entry.data = data; + slabhash_insert(table, myhash(numtoadd), &key->entry, data, NULL); + if(ref) + ref[numtoadd] = data; +} + +/** test adding a random element (unlimited range) */ +static void +testremove_unlim(struct slabhash* table, testdata_t** ref) +{ + int num = random() % (HASHTESTMAX*10); + testkey_t* key = newkey(num); + slabhash_remove(table, myhash(num), key); + if(ref) + ref[num] = NULL; + delkey(key); +} + +/** test adding a random element (unlimited range) */ +static void +testlookup_unlim(struct slabhash* table, testdata_t** ref) +{ + int num = random() % (HASHTESTMAX*10); + testkey_t* key = newkey(num); + struct lruhash_entry* en = slabhash_lookup(table, myhash(num), key, 0); + testdata_t* data = en? (testdata_t*)en->data : NULL; + if(en) { + unit_assert(en->key); + unit_assert(en->data); + } + if(0 && ref) log_info("lookup unlim %d got %d, expect %d", num, en ? + data->data :-1, ref[num] ? ref[num]->data : -1); + if(data && ref) { + /* its okay for !data, it fell off the lru */ + unit_assert( data == ref[num] ); + } + if(en) { lock_rw_unlock(&en->lock); } + delkey(key); +} + +/** test with long sequence of adds, removes and updates, and lookups */ +static void +test_long_table(struct slabhash* table) +{ + /* assuming it all fits in the hastable, this check will work */ + testdata_t* ref[HASHTESTMAX * 100]; + size_t i; + memset(ref, 0, sizeof(ref)); + /* test assumption */ + if(0) slabhash_status(table, "unit test", 1); + srandom(48); + for(i=0; i<1000; i++) { + /* what to do? */ + if(i == 500) { + slabhash_clear(table); + memset(ref, 0, sizeof(ref)); + continue; + } + switch(random() % 4) { + case 0: + case 3: + testadd(table, ref); + break; + case 1: + testremove(table, ref); + break; + case 2: + testlookup(table, ref); + break; + default: + unit_assert(0); + } + if(0) slabhash_status(table, "unit test", 1); + check_table(table); + } + + /* test more, but 'ref' assumption does not hold anymore */ + for(i=0; i<1000; i++) { + /* what to do? */ + switch(random() % 4) { + case 0: + case 3: + testadd_unlim(table, ref); + break; + case 1: + testremove_unlim(table, ref); + break; + case 2: + testlookup_unlim(table, ref); + break; + default: + unit_assert(0); + } + if(0) slabhash_status(table, "unlim", 1); + check_table(table); + } +} + +/** structure to threaded test the lru hash table */ +struct slab_test_thr { + /** thread num, first entry. */ + int num; + /** id */ + ub_thread_t id; + /** hash table */ + struct slabhash* table; +}; + +/** main routine for threaded hash table test */ +static void* +test_thr_main(void* arg) +{ + struct slab_test_thr* t = (struct slab_test_thr*)arg; + int i; + log_thread_set(&t->num); + for(i=0; i<1000; i++) { + switch(random() % 4) { + case 0: + case 3: + testadd_unlim(t->table, NULL); + break; + case 1: + testremove_unlim(t->table, NULL); + break; + case 2: + testlookup_unlim(t->table, NULL); + break; + default: + unit_assert(0); + } + if(0) slabhash_status(t->table, "hashtest", 1); + if(i % 100 == 0) /* because of locking, not all the time */ + check_table(t->table); + } + check_table(t->table); + return NULL; +} + +/** test hash table access by multiple threads */ +static void +test_threaded_table(struct slabhash* table) +{ + int numth = 10; + struct slab_test_thr t[100]; + int i; + + for(i=1; ireply_list); + if(e->reply_list->reply_from_hex) { + ldns_buffer_copy(pkt, e->reply_list->reply_from_hex); + } else { + ldns_status status; + size_t answer_size; + uint8_t* ans = NULL; + status = ldns_pkt2wire(&ans, e->reply_list->reply, + &answer_size); + if(status != LDNS_STATUS_OK) { + log_err("could not create reply: %s", + ldns_get_errorstr_by_id(status)); + fatal_exit("error in test"); + } + ldns_buffer_clear(pkt); + ldns_buffer_write(pkt, ans, answer_size); + ldns_buffer_flip(pkt); + free(ans); + } +} + +/** entry to reply info conversion */ +static void +entry_to_repinfo(struct entry* e, struct alloc_cache* alloc, + struct regional* region, ldns_buffer* pkt, struct query_info* qi, + struct reply_info** rep) +{ + int ret; + struct edns_data edns; + entry_to_buf(e, pkt); + /* lock alloc lock to please lock checking software. + * alloc_special_obtain assumes it is talking to a ub-alloc, + * and does not need to perform locking. Here the alloc is + * the only one, so we lock it here */ + lock_quick_lock(&alloc->lock); + ret = reply_info_parse(pkt, alloc, qi, rep, region, &edns); + lock_quick_unlock(&alloc->lock); + if(ret != 0) { + printf("parse code %d: %s\n", ret, + ldns_lookup_by_id(ldns_rcodes, ret)->name); + unit_assert(ret != 0); + } +} + +/** extract DNSKEY rrset from answer and convert it */ +static struct ub_packed_rrset_key* +extract_keys(struct entry* e, struct alloc_cache* alloc, + struct regional* region, ldns_buffer* pkt) +{ + struct ub_packed_rrset_key* dnskey = NULL; + struct query_info qinfo; + struct reply_info* rep = NULL; + size_t i; + + entry_to_repinfo(e, alloc, region, pkt, &qinfo, &rep); + for(i=0; ian_numrrsets; i++) { + if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_DNSKEY) { + dnskey = rep->rrsets[i]; + rep->rrsets[i] = NULL; + break; + } + } + unit_assert(dnskey); + + reply_info_parsedelete(rep, alloc); + query_info_clear(&qinfo); + return dnskey; +} + +/** return true if answer should be bogus */ +static int +should_be_bogus(struct ub_packed_rrset_key* rrset, struct query_info* qinfo) +{ + struct packed_rrset_data* d = (struct packed_rrset_data*)rrset-> + entry.data; + if(d->rrsig_count == 0) + return 1; + /* name 'bogus' as first label signals bogus */ + if(rrset->rk.dname_len > 6 && memcmp(rrset->rk.dname+1, "bogus", 5)==0) + return 1; + if(qinfo->qname_len > 6 && memcmp(qinfo->qname+1, "bogus", 5)==0) + return 1; + return 0; +} + +/** return number of rrs in an rrset */ +static size_t +rrset_get_count(struct ub_packed_rrset_key* rrset) +{ + struct packed_rrset_data* d = (struct packed_rrset_data*) + rrset->entry.data; + if(!d) return 0; + return d->count; +} + +/** setup sig alg list from dnskey */ +static void +setup_sigalg(struct ub_packed_rrset_key* dnskey, uint8_t* sigalg) +{ + uint8_t a[ALGO_NEEDS_MAX]; + size_t i, n = 0; + memset(a, 0, sizeof(a)); + for(i=0; irk.dname, ntohs(rrset->rk.type), + ntohs(rrset->rk.rrset_class)); + } + setup_sigalg(dnskey, sigalg); /* check all algorithms in the dnskey */ + sec = dnskeyset_verify_rrset(env, ve, rrset, dnskey, sigalg, &reason); + if(vsig) { + printf("verify outcome is: %s %s\n", sec_status_to_string(sec), + reason?reason:""); + } + if(should_be_bogus(rrset, qinfo)) { + unit_assert(sec == sec_status_bogus); + } else { + unit_assert(sec == sec_status_secure); + } +} + +/** verify and test an entry - every rr in the message */ +static void +verifytest_entry(struct entry* e, struct alloc_cache* alloc, + struct regional* region, ldns_buffer* pkt, + struct ub_packed_rrset_key* dnskey, struct module_env* env, + struct val_env* ve) +{ + struct query_info qinfo; + struct reply_info* rep = NULL; + size_t i; + + regional_free_all(region); + if(vsig) { + printf("verifying pkt:\n"); + ldns_pkt_print(stdout, e->reply_list->reply); + printf("\n"); + } + entry_to_repinfo(e, alloc, region, pkt, &qinfo, &rep); + + for(i=0; irrset_count; i++) { + verifytest_rrset(env, ve, rep->rrsets[i], dnskey, &qinfo); + } + + reply_info_parsedelete(rep, alloc); + query_info_clear(&qinfo); +} + +/** find RRset in reply by type */ +static struct ub_packed_rrset_key* +find_rrset_type(struct reply_info* rep, uint16_t type) +{ + size_t i; + for(i=0; irrset_count; i++) { + if(ntohs(rep->rrsets[i]->rk.type) == type) + return rep->rrsets[i]; + } + return NULL; +} + +/** DS sig test an entry - get DNSKEY and DS in entry and verify */ +static void +dstest_entry(struct entry* e, struct alloc_cache* alloc, + struct regional* region, ldns_buffer* pkt, struct module_env* env) +{ + struct query_info qinfo; + struct reply_info* rep = NULL; + struct ub_packed_rrset_key* ds, *dnskey; + int ret; + + regional_free_all(region); + if(vsig) { + printf("verifying DS-DNSKEY match:\n"); + ldns_pkt_print(stdout, e->reply_list->reply); + printf("\n"); + } + entry_to_repinfo(e, alloc, region, pkt, &qinfo, &rep); + ds = find_rrset_type(rep, LDNS_RR_TYPE_DS); + dnskey = find_rrset_type(rep, LDNS_RR_TYPE_DNSKEY); + /* check test is OK */ + unit_assert(ds && dnskey); + + ret = ds_digest_match_dnskey(env, dnskey, 0, ds, 0); + if(strncmp((char*)qinfo.qname, "\003yes", 4) == 0) { + if(vsig) { + printf("result(yes)= %s\n", ret?"yes":"no"); + } + unit_assert(ret); + } else if (strncmp((char*)qinfo.qname, "\002no", 3) == 0) { + if(vsig) { + printf("result(no)= %s\n", ret?"yes":"no"); + } + unit_assert(!ret); + verbose(VERB_QUERY, "DS fail: OK; matched unit test"); + } else { + fatal_exit("Bad qname in DS unit test, yes or no"); + } + + reply_info_parsedelete(rep, alloc); + query_info_clear(&qinfo); +} + +/** verify from a file */ +static void +verifytest_file(const char* fname, const char* at_date) +{ + /* + * The file contains a list of ldns-testpkts entries. + * The first entry must be a query for DNSKEY. + * The answer rrset is the keyset that will be used for verification + */ + struct ub_packed_rrset_key* dnskey; + struct regional* region = regional_create(); + struct alloc_cache alloc; + ldns_buffer* buf = ldns_buffer_new(65535); + struct entry* e; + struct entry* list = read_datafile(fname); + struct module_env env; + struct val_env ve; + uint32_t now = time(NULL); + + if(!list) + fatal_exit("could not read %s: %s", fname, strerror(errno)); + alloc_init(&alloc, NULL, 1); + memset(&env, 0, sizeof(env)); + memset(&ve, 0, sizeof(ve)); + env.scratch = region; + env.scratch_buffer = buf; + env.now = &now; + ve.date_override = cfg_convert_timeval(at_date); + unit_assert(region && buf); + dnskey = extract_keys(list, &alloc, region, buf); + if(vsig) log_nametypeclass(VERB_QUERY, "test dnskey", + dnskey->rk.dname, ntohs(dnskey->rk.type), + ntohs(dnskey->rk.rrset_class)); + /* ready to go! */ + for(e = list->next; e; e = e->next) { + verifytest_entry(e, &alloc, region, buf, dnskey, &env, &ve); + } + + ub_packed_rrset_parsedelete(dnskey, &alloc); + delete_entry(list); + regional_destroy(region); + alloc_clear(&alloc); + ldns_buffer_free(buf); +} + +/** verify DS matches DNSKEY from a file */ +static void +dstest_file(const char* fname) +{ + /* + * The file contains a list of ldns-testpkts entries. + * The first entry must be a query for DNSKEY. + * The answer rrset is the keyset that will be used for verification + */ + struct regional* region = regional_create(); + struct alloc_cache alloc; + ldns_buffer* buf = ldns_buffer_new(65535); + struct entry* e; + struct entry* list = read_datafile(fname); + struct module_env env; + + if(!list) + fatal_exit("could not read %s: %s", fname, strerror(errno)); + alloc_init(&alloc, NULL, 1); + memset(&env, 0, sizeof(env)); + env.scratch = region; + env.scratch_buffer = buf; + unit_assert(region && buf); + + /* ready to go! */ + for(e = list; e; e = e->next) { + dstest_entry(e, &alloc, region, buf, &env); + } + + delete_entry(list); + regional_destroy(region); + alloc_clear(&alloc); + ldns_buffer_free(buf); +} + +/** helper for unittest of NSEC routines */ +static int +unitest_nsec_has_type_rdata(char* bitmap, size_t len, uint16_t type) +{ + return nsecbitmap_has_type_rdata((uint8_t*)bitmap, len, type); +} + +/** Test NSEC type bitmap routine */ +static void +nsectest(void) +{ + /* bitmap starts at type bitmap rdata field */ + /* from rfc 4034 example */ + char* bitmap = "\000\006\100\001\000\000\000\003" + "\004\033\000\000\000\000\000\000" + "\000\000\000\000\000\000\000\000" + "\000\000\000\000\000\000\000\000" + "\000\000\000\000\040"; + size_t len = 37; + + unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 0)); + unit_assert(unitest_nsec_has_type_rdata(bitmap, len, LDNS_RR_TYPE_A)); + unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 2)); + unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 3)); + unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 4)); + unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 5)); + unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 6)); + unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 7)); + unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 8)); + unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 9)); + unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 10)); + unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 11)); + unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 12)); + unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 13)); + unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 14)); + unit_assert(unitest_nsec_has_type_rdata(bitmap, len, LDNS_RR_TYPE_MX)); + unit_assert(unitest_nsec_has_type_rdata(bitmap, len, LDNS_RR_TYPE_RRSIG)); + unit_assert(unitest_nsec_has_type_rdata(bitmap, len, LDNS_RR_TYPE_NSEC)); + unit_assert(unitest_nsec_has_type_rdata(bitmap, len, 1234)); + unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1233)); + unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1235)); + unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1236)); + unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1237)); + unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1238)); + unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1239)); + unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 1240)); + unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 2230)); +} + +/** Test hash algo - NSEC3 hash it and compare result */ +static void +nsec3_hash_test_entry(struct entry* e, rbtree_t* ct, + struct alloc_cache* alloc, struct regional* region, + ldns_buffer* buf) +{ + struct query_info qinfo; + struct reply_info* rep = NULL; + struct ub_packed_rrset_key* answer, *nsec3; + struct nsec3_cached_hash* hash; + int ret; + uint8_t* qname; + + if(vsig) { + printf("verifying NSEC3 hash:\n"); + ldns_pkt_print(stdout, e->reply_list->reply); + printf("\n"); + } + entry_to_repinfo(e, alloc, region, buf, &qinfo, &rep); + nsec3 = find_rrset_type(rep, LDNS_RR_TYPE_NSEC3); + answer = find_rrset_type(rep, LDNS_RR_TYPE_AAAA); + qname = regional_alloc_init(region, qinfo.qname, qinfo.qname_len); + /* check test is OK */ + unit_assert(nsec3 && answer && qname); + + ret = nsec3_hash_name(ct, region, buf, nsec3, 0, qname, + qinfo.qname_len, &hash); + if(ret != 1) { + printf("Bad nsec3_hash_name retcode %d\n", ret); + unit_assert(ret == 1); + } + unit_assert(hash->dname && hash->hash && hash->hash_len && + hash->b32 && hash->b32_len); + unit_assert(hash->b32_len == (size_t)answer->rk.dname[0]); + /* does not do lowercasing. */ + unit_assert(memcmp(hash->b32, answer->rk.dname+1, hash->b32_len) + == 0); + + reply_info_parsedelete(rep, alloc); + query_info_clear(&qinfo); +} + + +/** Read file to test NSEC3 hash algo */ +static void +nsec3_hash_test(const char* fname) +{ + /* + * The list contains a list of ldns-testpkts entries. + * Every entry is a test. + * The qname is hashed. + * The answer section AAAA RR name is the required result. + * The auth section NSEC3 is used to get hash parameters. + * The hash cache is maintained per file. + * + * The test does not perform canonicalization during the compare. + */ + rbtree_t ct; + struct regional* region = regional_create(); + struct alloc_cache alloc; + ldns_buffer* buf = ldns_buffer_new(65535); + struct entry* e; + struct entry* list = read_datafile(fname); + + if(!list) + fatal_exit("could not read %s: %s", fname, strerror(errno)); + rbtree_init(&ct, &nsec3_hash_cmp); + alloc_init(&alloc, NULL, 1); + unit_assert(region && buf); + + /* ready to go! */ + for(e = list; e; e = e->next) { + nsec3_hash_test_entry(e, &ct, &alloc, region, buf); + } + + delete_entry(list); + regional_destroy(region); + alloc_clear(&alloc); + ldns_buffer_free(buf); +} + +void +verify_test(void) +{ + unit_show_feature("signature verify"); + verifytest_file("testdata/test_signatures.1", "20070818005004"); + verifytest_file("testdata/test_signatures.2", "20080414005004"); + verifytest_file("testdata/test_signatures.3", "20080416005004"); + verifytest_file("testdata/test_signatures.4", "20080416005004"); + verifytest_file("testdata/test_signatures.5", "20080416005004"); + verifytest_file("testdata/test_signatures.6", "20080416005004"); + verifytest_file("testdata/test_signatures.7", "20070829144150"); + verifytest_file("testdata/test_signatures.8", "20070829144150"); +#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2) + verifytest_file("testdata/test_sigs.rsasha256", "20070829144150"); + verifytest_file("testdata/test_sigs.sha1_and_256", "20070829144150"); + verifytest_file("testdata/test_sigs.rsasha256_draft", "20090101000000"); +#endif +#if defined(HAVE_EVP_SHA512) && defined(USE_SHA2) + verifytest_file("testdata/test_sigs.rsasha512_draft", "20070829144150"); +#endif + verifytest_file("testdata/test_sigs.hinfo", "20090107100022"); + verifytest_file("testdata/test_sigs.revoked", "20080414005004"); +#ifdef USE_GOST + if(ldns_key_EVP_load_gost_id()) + verifytest_file("testdata/test_sigs.gost", "20090807060504"); + else printf("Warning: skipped GOST, openssl does not provide gost.\n"); +#endif +#ifdef USE_ECDSA + verifytest_file("testdata/test_sigs.ecdsa_p256", "20100908100439"); + verifytest_file("testdata/test_sigs.ecdsa_p384", "20100908100439"); + dstest_file("testdata/test_ds.sha384"); +#endif + dstest_file("testdata/test_ds.sha1"); + nsectest(); + nsec3_hash_test("testdata/test_nsec3_hash.1"); +} diff --git a/testdata/00-lint.tpkg b/testdata/00-lint.tpkg new file mode 100644 index 0000000000000000000000000000000000000000..89e44966d8b6cb4dfb066725bba8ae06133104dc GIT binary patch literal 530 zcmV+t0`2`DiwFQY_*6{*1MQUEZ__Xk!1L_C;gXrv$>O4)`FDgL^%&%Vo@5dNyD9M21L>OBzxN#eNcWfF^iE~BXL z*LYIKK`fI<3{ftFU>JH3Kh=dE(psksfOlKBPMgQ{w6TY{&|wh|;{S7OXM46G#PCPF zcg89$=(7*_&Z4eTkX*2_wlh;S zu3wn84s6|;nFds>q5oM}X0+<$W99IaE1knzRRM$`qf`c|2q2qWLVzWJoh#gdpEfDv zhQk%l_z1h=Yqe0y?+@5uljv@#p;Q)K12^cWIpz}FE_DTkduBVS(d;AmbKv}xyXJbqQH`&6 ze1emc%|SclXa&6r_shNcd2O(~KtIOCLVZD#4d!l9E!L*CH*8ti5;5MHoz-PoSKKby z^!?=3QFjr3#1`6pF4eVW?D;H*V-&$lI6fb}oAh<<1*7sn5ClOG1VIo4K@bE%5ClOG U1VIo4LHs-10Y%}2l>jIJ0Oq#{IsgCw literal 0 HcmV?d00001 diff --git a/testdata/01-doc.tpkg b/testdata/01-doc.tpkg new file mode 100644 index 0000000000000000000000000000000000000000..af82a3e4181d85c621d0c507405b15b598cc6423 GIT binary patch literal 902 zcmV;119|)(iwFP-`BY5+1MOCAYa=%h_E+my4C|1-fcM4r+OXyVsgt9$TnXi9K9rKk zyJN5FU1^ballb3vwCg1HHN7JtmlmoAW6h4{MViqg6h^~LrG6%K(EC~l39~r1V>FAy z_B)zP+Hr?o6vd-BnoTAohtVjUMm>nX+KTqjn3`*V-mPkC)St6MZQf!*Z;SA;|M#Lv zUpoh3+V%U%{*PzW|1h3RXX7}U(m9F7aXjfk_{!^e694o5|G*9Y!b?n`Yd`yqwkecM zAo4?Yh9=dbs$0b($8-Z^)08M{Zk24Iu@%mEO(8BZgP*tr7()~%^a~?coPUH7@t=L* zg1m%8oj|62xbzqPDGlOJx#nDFhAk+_TIp>9Y@y0ZNlKHjMVXypg)%dwf0Ta2qDt6> zM*35R>^>s>?{?wW^ubP>yZ53%Ykk3u!7O3#xhNXz^KaMvzk-KviuhAIO$RHhZt32t+gAnI?7oz=*G zhv5o*Kk(~nv-Zi%-+BB2$H(`9o|vaBR8)9Wx9L|(gOJe5q!fHfDJ!C{kn3HlLx+Pb z2UEe%wT<$sk`kOy{{?4;&^F6kv*^+ONeVb-*L^CjlqYtM) zpW8d{J2-)ITc|aRPL3nSmOOhGGO>cS#tMcA-X+(P*66h#xBDOGS}Wa&*oj@FlOV&J zKsH6u2Awmir)2$<*PQ|D+bj{o!XWDpz}u}I)W+L4TM72C<~j99X5hn6(yb2O_kK>9 zD@}JVZ6PlNmF1sp(>>dr@xV6Sc9Zx4sgf(P_H(xCwtdrX>R#(X>q3(DdKY;2a_8+HnxWBY z@H{WEY~)fkG7GA0ohunUYOZcIub#PzE=Z}efX)i)6;JWYrTF9|mBheL&ym%Ad1rJ( zk}QjfZp|z-Zky1KFY7X_Ou7Y;vlcfBCxj@wT{F+3eKTpUq68X z5sdXa*7Y&X)dRT`3I{niAl2bRh^~+Rj;(#7V@7WmhIgWdBT~A@hJ%BHgM)*EgM)*E cgM)*EgM)*EgM)*EgTq_lFBx;$yZ|Tw04*rl2><{9 literal 0 HcmV?d00001 diff --git a/testdata/02-unittest.tpkg b/testdata/02-unittest.tpkg new file mode 100644 index 0000000000000000000000000000000000000000..4618ae30e6a168d4c2d8ad934891a8d4c92f1da0 GIT binary patch literal 640 zcmV-`0)PDo>l19qJ#ppI6(9nbiTp)zJ z#A!{Nq_UlT{CiHahPB-oH~T>1JZj_m_&D!tyT^Xu)unb$S;sSNhP_9?N8%`IS`kNn z+ZSQjwo7_KL_s9tFpMxRb^|}^LG&1AHmR+X2B3FQ)lQlF@|3YpVd!b`H_m^pZ_|g- zKt|W+edqb_#z9Z`Q5Xjz_M88Sh~jwE1OGwP|H6NM{%@sKA7!BuSUGw21=p&pG6BJT zcA#u(^uo1)&zJ&Dj^%7@lx(60(&7BmX$|jX2@rx9CA&cq1~5K6g#e469ZOw0{3??` zW;lH1W4@1#{#j0>G?`^%e95FTR|&9jRV=Dfl`di9B0EqERc03BH^1Jg`66K_M&YBf zn0Jbf)|SBAb?n!dM|!TBDJRlel_l&*>UrHveD0n9H@L6Aq!HeVl4~NigN7tWM>C8JJOm z8VkMq5?1qH|2DRiUQJv#*uQr8r@R}doz*^i#ZTMw=~5*Kf*=TjAP9mW a2!bF8f*=TjAP9nZE`9-~mqfseutENPtpQS(}&doY|G?a4rhi#(eE@hDt#^s5qoixw{{*LKH;F( zGrz$>&$s`BZrA=+*a?DOyB8dEdtH(XI-SnJ4)lHkmn{@Z^BiF3N){UP`{XcJk3r~h z;cw=DZNNM|fDb~y%=c~i@A-arBmezwzrO?ikGuXh{^$8`K%?1&t)xS<*?1v1}>GJP9nU}r}s(}lM)cOm7hQo2D!L*s-s=wnig>DVS6_6w2d(w-czu6yof zcf}42z$H_2Cx*%XV$PCZ7=WgN7kZY_#wyuAohvyQO(iX#C|CyoAKn4D%)yi*xix(} zeEa*+p=%~66A&=73}+F=Aw_43JcIL8Mi&aMs2pLOBNBrq2ni{28s;>bNva?!C6Dq~ z61zRZjuQejAR` zl1dG4Zq*o7Q(2@jT*>?bq#)@VP&c&QXRvQ%&31n3v2vGZlm-gfA`UUvy!FhQ*&H*3 zpF=E}LkW*DADr2Ue;ysZAAWlK;mfO|*Kgm$ZfWyhQxz1@fS!~o281W7wISPTJvn2J zO|;b-oY^2QOjL@ldb!T!u45ZF);B@J8wv}>M#*heudLlN0;WG=>{))vAXz%JOWU$`zp*i=SBA>ia{!ufzTKzgR^N;p6`MpWkiwcLKlH?{<25h$_mHOxuA^g;?GZ054H!pyMLt^oAFqpu3t>9vkJzjr<|kWcsu~ zIL31bIuP{3PCpEOgVE6`w0-}8o$y3x`d}VHoO|%6H}Zz`ll&tloaeD(BQi3f6DtHZ zl5_|O@)@$xEIz~xMXYFi`Sb?UEMy;Zq%V3;3E3%;4YzN&Y*<_$Q^PbmAL(L=ambFT sgBC{fS7)V0jT$v-)TmLTMvWRZYSgGvqehJyHGUlb0kMN-`2Z*Y0I^zdxBvhE literal 0 HcmV?d00001 diff --git a/testdata/04-checkconf.tpkg b/testdata/04-checkconf.tpkg new file mode 100644 index 0000000000000000000000000000000000000000..f2ffe3535ff78f945ae5a39150321bfdaf320363 GIT binary patch literal 5127 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 literal 0 HcmV?d00001 diff --git a/testdata/05-asynclook.tpkg b/testdata/05-asynclook.tpkg new file mode 100644 index 0000000000000000000000000000000000000000..8143b43f4425bcf9428b90db1ae772f304e190f3 GIT binary patch literal 1950 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 D{y9+e literal 0 HcmV?d00001 diff --git a/testdata/08-host-lib.tpkg b/testdata/08-host-lib.tpkg new file mode 100644 index 0000000000000000000000000000000000000000..3c7be0e6c17d26227d8cec6e3319c466d690891f GIT binary patch literal 1908 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 DTMXBW literal 0 HcmV?d00001 diff --git a/testdata/10-unbound-anchor.tpkg b/testdata/10-unbound-anchor.tpkg new file mode 100644 index 0000000000000000000000000000000000000000..85f63e842b1ce6ee87549c9a9843827afc23dcf1 GIT binary patch literal 12318 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 literal 0 HcmV?d00001 diff --git a/testdata/Kexample.com.+003+02854.ds b/testdata/Kexample.com.+003+02854.ds new file mode 100644 index 00000000000..05f331b188b --- /dev/null +++ b/testdata/Kexample.com.+003+02854.ds @@ -0,0 +1 @@ +example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b diff --git a/testdata/Kexample.com.+003+02854.key b/testdata/Kexample.com.+003+02854.key new file mode 100644 index 00000000000..72f2b29b3e7 --- /dev/null +++ b/testdata/Kexample.com.+003+02854.key @@ -0,0 +1 @@ +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJIIs70j+sDS/UT2QRp61SE7S3EEXopNXoFE73JLRmvpi/UrOO/Vz4Se6wXv/CYCKjGw06U4WRgRYXcpEhJROyNapmdIKSxhOzfLVE1gqA0PweZR8dtY3aNQSRn3sPpwJr6Mi/PqQKAMMrZ9ckJpf1+bQMOOvxgzz2U1GS18b3yZKcgTMEaJzd/GZYzi/BN2DzQ0MsrSwYXfsNLFOBbs8PJMW4LYIxeeOe6rUgkWOF7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} diff --git a/testdata/Kexample.com.+003+02854.private b/testdata/Kexample.com.+003+02854.private new file mode 100644 index 00000000000..71d81d9f12c --- /dev/null +++ b/testdata/Kexample.com.+003+02854.private @@ -0,0 +1,7 @@ +Private-key-format: v1.2 +Algorithm: 3 (DSA) +Prime(p): +sDS/UT2QRp61SE7S3EEXopNXoFE73JLRmvpi/UrOO/Vz4Se6wXv/CYCKjGw06U4WRgRYXcpEhJROyNapmdIKQ== +Subprime(q): tctSxapStjclgRHdPhMEkgizvSM= +Base(g): LGE7N8tUTWCoDQ/B5lHx21jdo1BJGfew+nAmvoyL8+pAoAwytn1yQml/X5tAw46/GDPPZTUZLXxvfJkpyBMwRg== +Private_value(x): XMs4XYi1oNckzTPvGMkgG5IiuzY= +Public_value(y): ic3fxmWM4vwTdg80NDLK0sGF37DSxTgW7PDyTFuC2CMXnjnuq1IJFjhewgvQ4f3XbkNUK7CYZmQBBX3egcmFfg== diff --git a/testdata/Kexample.com.+005+16486.ds b/testdata/Kexample.com.+005+16486.ds new file mode 100644 index 00000000000..a4eb57d041d --- /dev/null +++ b/testdata/Kexample.com.+005+16486.ds @@ -0,0 +1 @@ +example.com. 3600 IN DS 16486 5 1 9adff86d0a468b5989a686df8076269b3a31ba54 ; xokit-zevek-tydyg-kydoh-nydap-kicet-zybil-konon-ruvef-covuh-gyxex diff --git a/testdata/Kexample.com.+005+16486.key b/testdata/Kexample.com.+005+16486.key new file mode 100644 index 00000000000..b5b2395e9b0 --- /dev/null +++ b/testdata/Kexample.com.+005+16486.key @@ -0,0 +1 @@ +example.com. 3600 IN DNSKEY 257 3 5 AwEAAas/cAhCFXvBUgTSNZCvQp0pLx1dY+7rXR0hH4/3EUgWmsmbYUpI1qD0xhwKD/oYGEwAm291fyWJ9c0oVxXDEK8= ;{id = 16486 (ksk), size = 512b} diff --git a/testdata/Kexample.com.+005+16486.private b/testdata/Kexample.com.+005+16486.private new file mode 100644 index 00000000000..c7ea159d294 --- /dev/null +++ b/testdata/Kexample.com.+005+16486.private @@ -0,0 +1,10 @@ +Private-key-format: v1.2 +Algorithm: 5 (RSASHA1) +Modulus: qz9wCEIVe8FSBNI1kK9CnSkvHV1j7utdHSEfj/cRSBaayZthSkjWoPTGHAoP+hgYTACbb3V/JYn1zShXFcMQrw== +PublicExponent: AQAB +PrivateExponent: lT++xpPB4ZAFicojgSweZJbmRzODy1E6YA7kUTbFywrrClEi6vjb88AshqZsPuDnI4iOZ2Cy56qN9SZTD2WokQ== +Prime1: 29ChQQp9Dd7jH8L+QxEowJGOxwo2WD8rLOjvdz7FBos= +Prime2: x3AbQo22FBaEbB1Z6rM31WsLNhNNgHvD2G1gpXD2Ru0= +Exponent1: Sj0eGQ9nyOV8I+ABa7lB4DfI1uRWElvTQymwpr9mX50= +Exponent2: ZnWUu6NcKIPM8lI98JK0G4OL1fMivOBYpCbFIRmgnJ0= +Coefficient: N2jmFfQh8jhGIlrUvOlJFdDnAFNxEy/C5gXRJpNHHBM= diff --git a/testdata/Kexample.com.+005+30899.ds b/testdata/Kexample.com.+005+30899.ds new file mode 100644 index 00000000000..423347c3b39 --- /dev/null +++ b/testdata/Kexample.com.+005+30899.ds @@ -0,0 +1 @@ +example.com. 3600 IN DS 30899 5 1 d4bf9d2e10f6d76840d42ef5913022abcd0bf512 diff --git a/testdata/Kexample.com.+005+30899.key b/testdata/Kexample.com.+005+30899.key new file mode 100644 index 00000000000..17b36c94d6f --- /dev/null +++ b/testdata/Kexample.com.+005+30899.key @@ -0,0 +1 @@ +example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} diff --git a/testdata/Kexample.com.+005+30899.private b/testdata/Kexample.com.+005+30899.private new file mode 100644 index 00000000000..be0a6bb5af8 --- /dev/null +++ b/testdata/Kexample.com.+005+30899.private @@ -0,0 +1,10 @@ +Private-key-format: v1.2 +Algorithm: 5 (RSASHA1) +Modulus: 0ONXIUfQxB7f2iMyBQKmp2w5UX5SaEbOcs9YxbKESE+3Vn9K/j3g7nsHcZLMzR+sJ1OEC/KXyhUYeTyGFQSytw== +PublicExponent: Aw== +PrivateExponent: i0I6Fi/ggr8/5sIhWKxvGkgmNlQ28C80TIo7LncC2t6ar2Q5rpyiDxEHvFLfphRh108ZOqf2tQdHx7tXTx5Gqw== +Prime1: 9WS85Q92ilTAuGiVi+KesKzrFqF98l2Gpu4003hfmbc= +Prime2: 2eqsD2jcY4Mgw26A8XFiaLdxx5J4s10Dhd9ur6X3rwE= +Exponent1: o5h97gpPBuMrJZsOXUG/IHNHZGupTD5ZxJ7N4lA/u88= +Exponent2: kUcdX5s9l6zAgkmrS6DsRc+hL7b7Ij4CWT+fH8P6dKs= +Coefficient: PVZrElFmz9tWa4kwu9jArjcocycYu0eBycgguQ03J7w= diff --git a/testdata/Kexample.com.+005+55582.ds b/testdata/Kexample.com.+005+55582.ds new file mode 100644 index 00000000000..d8381ad27ee --- /dev/null +++ b/testdata/Kexample.com.+005+55582.ds @@ -0,0 +1 @@ +example.com. 3600 IN DS 55582 5 1 66e829ebd8145e6f030b840ae63b77273c9575e1 ; xiniv-mopov-rakoc-galuk-zibeb-ricob-penuf-rutad-lyzan-hetuv-caxox diff --git a/testdata/Kexample.com.+005+55582.key b/testdata/Kexample.com.+005+55582.key new file mode 100644 index 00000000000..592ff1c06d6 --- /dev/null +++ b/testdata/Kexample.com.+005+55582.key @@ -0,0 +1 @@ +example.com. 3600 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} diff --git a/testdata/Kexample.com.+005+55582.private b/testdata/Kexample.com.+005+55582.private new file mode 100644 index 00000000000..9abbae2fdaf --- /dev/null +++ b/testdata/Kexample.com.+005+55582.private @@ -0,0 +1,10 @@ +Private-key-format: v1.2 +Algorithm: 5 (RSASHA1) +Modulus: zdnkNAMmkfig9020LgFRAeTnRcwP50evivymweaK8hrzeHFHkJGAK132wQ0Jb0B7w4g7X3HD239E9oQCpBr44Q== +PublicExponent: AQAB +PrivateExponent: DE8+TTnvAYWboo47+xBLFtDoX40fWlY4EhifpDK0FlwYtslxlSkCZkynCwYtZ+DKVpqRHfKqiJ58YLHSfh3NLQ== +Prime1: 9Gn4mzILOWnw5w1x2qeDj5yTny3un0J1PnPhPsPlpHs= +Prime2: 15vzQpJ7l5rh1grtqEbom/mxaUX49CzMS6zi9xfHX1M= +Exponent1: qknPEWobkePzGTgv1DUUH5Hq9GPPNpzaDSo1jEJ2lFM= +Exponent2: FTrI0BRGUR4yAHZhAkHBI6KJYnk+UySaFRV336aavfs= +Coefficient: iaMsVK9xzKl9+2tiaoNQNcVQSTkP5oI2upGqfOsQXbg= diff --git a/testdata/Kexample.com.+005+60946.ds b/testdata/Kexample.com.+005+60946.ds new file mode 100644 index 00000000000..154703f8b59 --- /dev/null +++ b/testdata/Kexample.com.+005+60946.ds @@ -0,0 +1 @@ +example.com. 3600 IN DS 60946 5 1 f48a5c8c1eceb7df2d68d1ad29151a77d5650505 ; xutam-pulim-seles-votit-zorek-mygep-tipyc-hakol-luhik-hecib-hoxax diff --git a/testdata/Kexample.com.+005+60946.key b/testdata/Kexample.com.+005+60946.key new file mode 100644 index 00000000000..3fe8ae6749d --- /dev/null +++ b/testdata/Kexample.com.+005+60946.key @@ -0,0 +1 @@ +example.com. 3600 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} diff --git a/testdata/Kexample.com.+005+60946.private b/testdata/Kexample.com.+005+60946.private new file mode 100644 index 00000000000..79e0aff8cae --- /dev/null +++ b/testdata/Kexample.com.+005+60946.private @@ -0,0 +1,10 @@ +Private-key-format: v1.2 +Algorithm: 5 (RSASHA1) +Modulus: 6JpSJQilYx9jPkvSx8lNlae430jIFfh6b1WOyipBOw4PUcNCk1vhu68mjuk3ZoELE1Lt7Q4vx7aZUHoItn7x6Q== +PublicExponent: AQAB +PrivateExponent: Y21D28y8VYifNYvXx8rGvUf6gIdt7+ZM/7ZE2SoCxCjHkHQqWh9k1l5xEjCDZ7YOyFyQAbowMhEsr6C+11UvOQ== +Prime1: /4r1mlWLh3x1afMpWPxIfeNFsRHeyujk7GBuCZ0MlkM= +Prime2: 6QTa08YMv3JQrdEe8n+zZvMDkOhS/1wltFBn+mt9cmM= +Exponent1: 4AWFDBiEanEsSYaXL+By+JF+Lh3Zb4696Y8byCe6uhs= +Exponent2: p7bo0bgggMMEsrZrcdrcA2Mx0+CDrGxkbu3YiPNI7UU= +Coefficient: ahJU2OH7E2Q1yhzja925x7g4r289nD/GGIHz47e0ysk= diff --git a/testdata/Kexample.com.+007+57024.ds b/testdata/Kexample.com.+007+57024.ds new file mode 100644 index 00000000000..559cf4989fd --- /dev/null +++ b/testdata/Kexample.com.+007+57024.ds @@ -0,0 +1 @@ +example.com. 3600 IN DS 57024 7 1 46d134be319b2cc910b9938f1cb25dc41abb27bf ; xicit-citor-vasin-rarus-nygir-nagam-zulor-dylos-gokar-ranor-zixyx diff --git a/testdata/Kexample.com.+007+57024.key b/testdata/Kexample.com.+007+57024.key new file mode 100644 index 00000000000..b8843766ca4 --- /dev/null +++ b/testdata/Kexample.com.+007+57024.key @@ -0,0 +1 @@ +example.com. 3600 IN DNSKEY 257 3 7 AwEAAbvre/wK/WVeoj0SiwVkTD+NefvHPru9YIqLWY0m+0E5NYOpJZdc+PGQQYRzFNOlugVZtFirmv5Lmz7GNiASXtG/IFi//SlE30DxEKQOjt2F6qSZTZ1nZ5XOIMGTwWyp4OoI0egk5JavC5mQbyXqcj82ywt6F5Z3CmnThVl6MtOv ;{id = 57024 (ksk), size = 1024b} diff --git a/testdata/Kexample.com.+007+57024.private b/testdata/Kexample.com.+007+57024.private new file mode 100644 index 00000000000..4030ca130b7 --- /dev/null +++ b/testdata/Kexample.com.+007+57024.private @@ -0,0 +1,10 @@ +Private-key-format: v1.2 +Algorithm: 7 (RSASHA1_NSEC3) +Modulus: u+t7/Ar9ZV6iPRKLBWRMP415+8c+u71giotZjSb7QTk1g6kll1z48ZBBhHMU06W6BVm0WKua/kubPsY2IBJe0b8gWL/9KUTfQPEQpA6O3YXqpJlNnWdnlc4gwZPBbKng6gjR6CTklq8LmZBvJepyPzbLC3oXlncKadOFWXoy068= +PublicExponent: AQAB +PrivateExponent: WsmD1trAXS8BFpxUycARDksdecRizHTLpWN5WjZRAMvQzND1NlFWe+4DmSe4EiBo5JjYBlaxxNVmJUfBcnEtmTfED52KiOfvMQFS8ii+14UqZqLj6iyqh9MeWsxAzC3J0A+nBu7lAgqvwCCqrqSOmF/8EJSZWEGla8qWylKMgyE= +Prime1: 4hE5iju9vDvbPCmy4+K6nwELakuyrcaxdvPxEUicSkbTpBRnIDuerGJySnuNbiLScq7WUyJsjLsq0wOFNCtlVw== +Prime2: 1M0299YZUU0NxAGMFeKEQAvuO0r3zXbgURwLyXLoerhs1K6S1szT+/vgbPLwL55IR7A/LDa6u6SqMrqdGqb1aQ== +Exponent1: csYd+YGVNdEJ4ISnLy24Y+vK2N+vyqxbAzKcjJLZzpgg8WfuZ539VDXzIr+RsX36bIE5jSGoDNclydY6tZ7mpw== +Exponent2: yF2NMyAA6J8fpf069GQ6178kCeoVlv0mStiYdI5gPSSnPD4/fkaQFsPbVVoNMxjav71AThYeDo4Fvwwc3rpzeQ== +Coefficient: gIrzPgL4XhCn/yP0qRCqBTmnqRLeEvRsYNz2T8gsyVGc9gyt/9ouhKOGGHmD2DJf7yWfJiQEEuhw+lBBTNNKtQ== diff --git a/testdata/Kexample.com.+008+01443.ds b/testdata/Kexample.com.+008+01443.ds new file mode 100644 index 00000000000..3e031f9b3bc --- /dev/null +++ b/testdata/Kexample.com.+008+01443.ds @@ -0,0 +1 @@ +example.com. 3600 IN DS 1443 8 1 54f8ccd08089fd8b7c1b51d487eadf1c527dece4 ; xihaz-mufit-bybem-nezam-ryzuc-rugyt-gucyv-pulec-sygyl-tiriv-goxox diff --git a/testdata/Kexample.com.+008+01443.key b/testdata/Kexample.com.+008+01443.key new file mode 100644 index 00000000000..61b39f45eac --- /dev/null +++ b/testdata/Kexample.com.+008+01443.key @@ -0,0 +1 @@ +example.com. 3600 IN DNSKEY 256 3 8 AwEAAbd9WqjzE2Pynz21OG5doSf9hFzMr5dhzz2waZ3vTa+0o5r7AjTAqmA1yH/B3+aAMihUm5ucZSfVqo7+kOaRE8yFj9aivOmA1n1+JLevJq/oyvQyjxQN2Qb89LyaNUT5oKZIiL+uyyhNW3KDR3SSbQ/GBwQNDHVcZi+JDR3RC0r7 ;{id = 1443 (zsk), size = 1024b} diff --git a/testdata/Kexample.com.+008+01443.private b/testdata/Kexample.com.+008+01443.private new file mode 100644 index 00000000000..4d70dd39cee --- /dev/null +++ b/testdata/Kexample.com.+008+01443.private @@ -0,0 +1,10 @@ +Private-key-format: v1.2 +Algorithm: 8 (RSASHA256) +Modulus: t31aqPMTY/KfPbU4bl2hJ/2EXMyvl2HPPbBpne9Nr7SjmvsCNMCqYDXIf8Hf5oAyKFSbm5xlJ9Wqjv6Q5pETzIWP1qK86YDWfX4kt68mr+jK9DKPFA3ZBvz0vJo1RPmgpkiIv67LKE1bcoNHdJJtD8YHBA0MdVxmL4kNHdELSvs= +PublicExponent: AQAB +PrivateExponent: azCanqnpgPDCX90Wyzp9I4xxH3kfdrLXyzTcbjvWyTcggC/0WPbYUP36U8/hSZlIM9FBWgVh/oROb9x8r4S+6DT5k3tdhI303AL6bC8x1PBCzHjXBmYa9JvPKx/7a1hpSVOw9iJJh0Y4IclrfA8Ssdqxkj5QdNvR1CqDYTvIH/E= +Prime1: 4yIEKoY9ew1mX7+MUA8T1sGp64VzTiFpnn/8eomwdYVEsX6Sg563qLEn6IuORxrqCz8Ae3qfgVkT0J96ArURsw== +Prime2: zs9dU2j2jlToxIXtKu+YeO7QCKd1gVP6beI9IxjMYm21opsVvJ/xMlHu9aocGuCgvfmFyu/ShhsF/IPlFkvtmQ== +Exponent1: EAy8TKD1wTc+L6/iY1ndZgSDVFA2yKOVygxzM9l87aEALKasBb72bWYvUsBhymZ9eVP3XcJZeRNpUgmi3oQa/w== +Exponent2: nukr9wmyWo/YBBo8sT9F07b9V4kFe4jB52luPOezNPbEGNw+CaCEv3vBuDcsPWLZYOC488Tv6WgeY3gdsdJKEQ== +Coefficient: Fr7ARq2yRTv8+1ZAAwv2gbDa92RZxdZzj9hpC+/64kjCxq5//2haIhU/wtgDbBlr99Uk90cXf6F8AeaqCYgjLQ== diff --git a/testdata/Kexample.com.+009+48886.ds b/testdata/Kexample.com.+009+48886.ds new file mode 100644 index 00000000000..d04c37bd21b --- /dev/null +++ b/testdata/Kexample.com.+009+48886.ds @@ -0,0 +1 @@ +example.com. 3600 IN DS 48886 9 1 eb70a0d5001a3da004b428f01bf15cb5aad22f73 ; xupol-bamyt-hobuc-pyzop-bacur-gupaz-bakoz-cylyr-hepyt-dorol-foxux diff --git a/testdata/Kexample.com.+009+48886.key b/testdata/Kexample.com.+009+48886.key new file mode 100644 index 00000000000..11dd86acd42 --- /dev/null +++ b/testdata/Kexample.com.+009+48886.key @@ -0,0 +1 @@ +example.com. 3600 IN DNSKEY 256 3 9 AwEAAazmeO3BNv+xPYuFbQp8JN4XX+iKNuvJgD2QG5jRXI0IP5by+JGSob20OEmbPLqKcXWMRPICTyPBDaBh0tXA66DVlHV8rCtAT5Yqdrz2qw05SNYCGWJulscR6GM0e4gkO1FrBINr385IiMH3sJegBzm2HUbyb2I+xuFIfl7SgMuZ5fahHnhjDwsdgw+19OQlbYDRmNhMvtJemomIiGzPwrxEtKBlcUevcFPX7cPU7lpbcZwVP16xhLbtSNwMHvoCoRpJrAtdDGiSyAzTQef+jWuaUlFCPle6Qkghi51zmpBrPunqRCoYg7LIyJ9zS/KzPKX2zN2ASu9KJD3tDW9OSZM= ;{id = 48886 (zsk), size = 2048b} diff --git a/testdata/Kexample.com.+009+48886.private b/testdata/Kexample.com.+009+48886.private new file mode 100644 index 00000000000..7604de8dd0b --- /dev/null +++ b/testdata/Kexample.com.+009+48886.private @@ -0,0 +1,10 @@ +Private-key-format: v1.2 +Algorithm: 9 (RSASHA512) +Modulus: rOZ47cE2/7E9i4VtCnwk3hdf6Io268mAPZAbmNFcjQg/lvL4kZKhvbQ4SZs8uopxdYxE8gJPI8ENoGHS1cDroNWUdXysK0BPlip2vParDTlI1gIZYm6WxxHoYzR7iCQ7UWsEg2vfzkiIwfewl6AHObYdRvJvYj7G4Uh+XtKAy5nl9qEeeGMPCx2DD7X05CVtgNGY2Ey+0l6aiYiIbM/CvES0oGVxR69wU9ftw9TuWltxnBU/XrGEtu1I3Awe+gKhGkmsC10MaJLIDNNB5/6Na5pSUUI+V7pCSCGLnXOakGs+6epEKhiDssjIn3NL8rM8pfbM3YBK70okPe0Nb05Jkw== +PublicExponent: AQAB +PrivateExponent: FeWqcxIBUSi1TrI7ORS35pi3QNAgXIRMhX92v0fknMfqpcdny6fybAAjEM9kRYu7CtQU90FrnG+atjEtbnzcWqYyAx8i/udKLQ57szraNvaGTvQ9GsY+uj9+WvIOoxNTn+AZ1jsXQRzWlRo1dz6BK8Hwu0eA68Rfk7CGsKOgRCioONwz8m9/GTTxMsZ+VcLkenK/IyYOCnh47vrNkUGb5+3g9Bunkbymcjyhw79DLdMvRRYoqzvhAiGS8r+EpOtAA443iZ+RwfEae7U0VUJEPEEytLb3EZx2qjvWuXtN84tCvXpdum0M7y9dfDojH+I7ZvhiOIMmnWd20ldgjqqOQQ== +Prime1: 0xom8n5L5YrcHIHTAZtQK039Ozqay5vOz6QvqqEiXevAdYdDUQVuX3VSAWCScF9OxfPXHZhX8z4hNpjc8zDirVUDlWRf77Shp1kjdhBZvwwxOp28uuXvg6g3VtTirEp0iwCCt6Wy4HErAKRFFZ0sEq5nzp/fn2y71AAWezLk4Gs= +Prime2: 0axZNMdHG2ornNjoOJzQAgDDibmqBHgebkJg/f6IWI2X1ew044Qg+67t7VzvnkVe7UiVjLJYsnlVmXhIPA618hSIvPb2WH4QFNVBAW8Q9WeCSvczuTeyjg5BxZVNta4tSWrpm+oYLcwn0MDWJMCynQmT5C5pDjEQtlbQrutCZXk= +Exponent1: pQ8+wr6jw3BG2PddsFTrY2DQjv4syOUj2NFNAAKL55oNWxgPN4uimHsYSsFi3wB2jGszmQ1kP2ol+BWgNXrU0qi1a5sXNEstVrdo9cilE6+J0oZBanWdSHlAA+Hi9sokxAb7LnMeIUX7VL4c0mCZdGXv/uycooAXgRUsftn1gc8= +Exponent2: Zc1Ukree4sSt4D3AopwgsphEWH54+iqIO+imxyvqb3RwIEHLfBwPF6RbiT/yZ9ouuO7hDasaPa2DzjwEdoR9+sfVjEosWdL7Y+IW6edPSJe1P0i/KFLOswJhFNnlHS0wd9EdE8KZcsMJIeY/EyEsl+qqj8Oo5mcUQjPspsE7P6E= +Coefficient: SkqMe/RECHeiSYo+DBGMOdBiCKrxDc02W1lVCM9k9tD7lN6OA2KdhxTWGtfNI147kQkRnR8Q6Qv/ushy9S+dYScDXjqB3n1vpKaklvPdWOXGokJds6zgiviUKxtYuFiDoluPNEdHblk9sThkTBb2qpb17R9xUNIX4zRidkQweHQ= diff --git a/testdata/Kexample.com.+012+60385.ds b/testdata/Kexample.com.+012+60385.ds new file mode 100644 index 00000000000..335e8f200b9 --- /dev/null +++ b/testdata/Kexample.com.+012+60385.ds @@ -0,0 +1 @@ +example.com. 3600 IN DS 60385 12 3 c93b6fd6893d42ae60acd15088c2aeea0e0f013e535961855f17299507f70e0d ; xudef-ririt-kidaf-tebyp-vemep-segih-bydes-dyriv-pofab-zibaf-vigyh-numom-halac-lypin-hycaz-lofub-taxex diff --git a/testdata/Kexample.com.+012+60385.key b/testdata/Kexample.com.+012+60385.key new file mode 100644 index 00000000000..022315c2bbe --- /dev/null +++ b/testdata/Kexample.com.+012+60385.key @@ -0,0 +1 @@ +example.com. 3600 IN DNSKEY 256 3 12 9SZY+xB3wKtrLoRHzkBs9L3fjcvazjnk5HF3gMaD1PVp4pthrwgHIm0TUaLrd3YCa2VCl5wj+MzbhZi8NEJ/Cg== ;{id = 60385 (zsk), size = 512b} diff --git a/testdata/Kexample.com.+012+60385.private b/testdata/Kexample.com.+012+60385.private new file mode 100644 index 00000000000..f1c62914811 --- /dev/null +++ b/testdata/Kexample.com.+012+60385.private @@ -0,0 +1,3 @@ +Private-key-format: v1.2 +Algorithm: 12 (ECC-GOST) +GostAsn1: MEUCAQAwHAYGKoUDAgITMBIGByqFAwICIwEGByqFAwICHgEEIgIge0NaZG76WD9K6vNRD1yDuVPtKlEtFQbHIjoB106B6Hc= diff --git a/testdata/acl.rpl b/testdata/acl.rpl new file mode 100644 index 00000000000..3df7f81c82f --- /dev/null +++ b/testdata/acl.rpl @@ -0,0 +1,52 @@ +; config options +server: + hide-identity: no + hide-version: no + identity: "test-identity" + version: "test-version" + access-control: 20.0.0.0/8 allow + access-control: 20.40.0.0/16 refuse + access-control: 20.40.80.0/24 deny + +CONFIG_END +SCENARIO_BEGIN Test access control list + +; version.bind. +; allow +STEP 1 QUERY ADDRESS 20.1.2.3 +ENTRY_BEGIN +SECTION QUESTION +version.bind. CH TXT +ENTRY_END +STEP 2 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RA +SECTION QUESTION +version.bind. CH TXT +SECTION ANSWER +version.bind. 0 CH TXT "test-version" +ENTRY_END + +; refuse +STEP 3 QUERY ADDRESS 20.40.2.3 +ENTRY_BEGIN +SECTION QUESTION +version.bind. CH TXT +ENTRY_END +STEP 4 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR REFUSED +ENTRY_END + +; deny (drop) +STEP 5 QUERY ADDRESS 20.40.80.3 +ENTRY_BEGIN +SECTION QUESTION +version.bind. CH TXT +ENTRY_END + +; no answer must be pending + +SCENARIO_END diff --git a/testdata/autotrust_10key.rpl b/testdata/autotrust_10key.rpl new file mode 100644 index 00000000000..89f2102a341 --- /dev/null +++ b/testdata/autotrust_10key.rpl @@ -0,0 +1,144 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + log-time-ascii: yes +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +AUTOTRUST_FILE example.com +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: 1258962400 ;;Mon Nov 23 07:46:40 2009 +;;last_success: 1258962400 ;;Mon Nov 23 07:46:40 2009 +;;next_probe_time: 1258967360 ;;Mon Nov 23 09:09:20 2009 +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAas/cAhCFXvBUgTSNZCvQp0pLx1dY+7rXR0hH4/3EUgWmsmbYUpI1qD0xhwKD/oYGEwAm291fyWJ9c0oVxXDEK8= ;{id = 16486 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1258962400 ;;Mon Nov 23 07:46:40 2009 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1258962400 ;;Mon Nov 23 07:46:40 2009 +AUTOTRUST_END +CONFIG_END + +SCENARIO_BEGIN Test autotrust with 10 keys +; spec says you must be able to handle at least 5 keys per trust point + +; K-ROOT +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR AA +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS k.root-servers.net. +SECTION ADDITIONAL +k.root-servers.net IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER + +example.com. 10800 IN DNSKEY 257 3 5 AwEAAas/cAhCFXvBUgTSNZCvQp0pLx1dY+7rXR0hH4/3EUgWmsmbYUpI1qD0xhwKD/oYGEwAm291fyWJ9c0oVxXDEK8= ;{id = 16486 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1258962400 ;;Mon Nov 23 07:46:40 2009 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1258962400 ;;Mon Nov 23 07:46:40 2009 +example.com. 3600 IN DNSKEY 257 3 5 AwEAAaxpsO70/oPdKhulQXVbkLX5V6lyzF7G0gtz0nReLlBmfEk6zQ3WSW8VZ8kdZUCOLQwJl+5nWNfRvFxnqUGwjT8= ;{id = 11146 (ksk), size = 512b} +example.com. 3600 IN DNSKEY 257 3 5 AwEAAbXPzz66rviAvNKgPV5JNdkOZv9olQwNDFWnxy7p/RtObOL35ahwpamQGL5A5uPOvn1OghQyqiytTFFP8ZM/5Rc= ;{id = 11446 (ksk), size = 512b} +example.com. 3600 IN DNSKEY 257 3 5 AwEAAdSj6e3XGnFwRNgw6Aifi4Q7SyRIdQ25XVsiWP/N9m7evkN+y6rlnaMP1ELRkhpiwK0bbNTP3DsGXtSMbR/4uzU= ;{id = 20314 (ksk), size = 512b} +example.com. 3600 IN DNSKEY 257 3 5 AwEAAa8er29rQIzO6+o3D4S8HsTTICTHHzDTeVbY/2kLdR0wwRy2PL8qvgxTX1YZXxEjrGHBhY5jD+aF9y9G3Ztfns8= ;{id = 22402 (ksk), size = 512b} +example.com. 3600 IN DNSKEY 257 3 5 AwEAAZ25ylUZoX11EeM7aPqJOprcnGFiXgI7P407NMiBVd8Wz5J1aaUuPabfu4f15oLp4/6czzn3iuJp4UJU4ZTjFrc= ;{id = 27586 (ksk), size = 512b} +example.com. 3600 IN DNSKEY 257 3 5 AwEAAbZxgKqPMoc8E7BqdrT84U7ux57LHMXQJnAogNcobTvC9+e3aeL5YdFSqgf6Em7ICISMzS+Sd0wJqgRoL0ZDhzk= ;{id = 29146 (ksk), size = 512b} +example.com. 3600 IN DNSKEY 257 3 5 AwEAAbpIKlHvo1Ev4La/eEPoqThtFA8+vLxcjUQaowkkR/Xvvt6fd6iM3vSH6RsyvNgbj5C+HBjkciSeW4KthUuIDUk= ;{id = 51673 (ksk), size = 512b} +example.com. 3600 IN DNSKEY 257 3 5 AwEAAdzRZ1JnXuspXF03PH6p97f6Xq8JkbZiOZYTCcfBiSFuyq6046Yqhbo3UNpPxMlB0JY52Ffj3gohTZAuClVoIZ8= ;{id = 55999 (ksk), size = 512b} +example.com. 3600 IN DNSKEY 257 3 5 AwEAAeu99txoU5i2Z4BVatCVi9PTj93oOPft8ZB9ovcjfzRZLpfc/woges07k5Ru+H44qSRxjtDKDqtf4QSo3RkkGLk= ;{id = 56782 (ksk), size = 512b} +example.com. 3600 IN DNSKEY 257 3 5 AwEAAd9vx7tR9cd9MMDh0gL/qHNTG4ykehjT3UzIIEtAi3Z4DI3/FFw9U/GjpYcqVC6hx2Yo1lbc4tVIa/uA0mbU7uE= ;{id = 58687 (ksk), size = 512b} +example.com. 3600 IN DNSKEY 257 3 5 AwEAAdz+Xe5qS3BRnw1hBy2wL2wi0o3Nh94lDxtDtfOsmyJ0WD/25Ova9Pb27Yzh5XW/baENkI+xGJTFsljbi9bdSd0= ;{id = 63067 (ksk), size = 512b} + +example.com. 3600 IN RRSIG DNSKEY 5 2 3600 20091124111500 20091018111500 55582 example.com. baTsvlgA0tIVAts9myEBGKP/A7PvPshZfESq/dueRhPGVRwNYEoQACjkqYsIquzOs4sBec9xVH15CXIH+okXYA== ;{id = 55582} + +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ENTRY_END +RANGE_END + +RANGE_END + +; set date/time to Mon Nov 23 09:46:40 2009 +STEP 5 TIME_PASSES EVAL ${1258962400 + 7200} +STEP 6 TRAFFIC ; do the probe +STEP 7 ASSIGN t0 = ${time} +STEP 8 ASSIGN probe0 = ${range 3200 ${timeout} 5400} +STEP 9 ASSIGN tp = ${1258962400} + +; the auto probing should have been done now. +STEP 11 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t0} ;;${ctime $t0} +;;last_success: ${$t0} ;;${ctime $t0} +;;next_probe_time: ${$t0 + $probe0} ;;${ctime $t0 + $probe0} +;;query_failed: 0 +;;query_interval: 3600 +;;retry_time: 3600 +example.com. 3600 IN DNSKEY 257 3 5 AwEAAdz+Xe5qS3BRnw1hBy2wL2wi0o3Nh94lDxtDtfOsmyJ0WD/25Ova9Pb27Yzh5XW/baENkI+xGJTFsljbi9bdSd0= ;{id = 63067 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=1 ;;lastchange=${$t0} ;;${ctime $t0} +example.com. 3600 IN DNSKEY 257 3 5 AwEAAd9vx7tR9cd9MMDh0gL/qHNTG4ykehjT3UzIIEtAi3Z4DI3/FFw9U/GjpYcqVC6hx2Yo1lbc4tVIa/uA0mbU7uE= ;{id = 58687 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=1 ;;lastchange=${$t0} ;;${ctime $t0} +example.com. 3600 IN DNSKEY 257 3 5 AwEAAeu99txoU5i2Z4BVatCVi9PTj93oOPft8ZB9ovcjfzRZLpfc/woges07k5Ru+H44qSRxjtDKDqtf4QSo3RkkGLk= ;{id = 56782 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=1 ;;lastchange=${$t0} ;;${ctime $t0} +example.com. 3600 IN DNSKEY 257 3 5 AwEAAdzRZ1JnXuspXF03PH6p97f6Xq8JkbZiOZYTCcfBiSFuyq6046Yqhbo3UNpPxMlB0JY52Ffj3gohTZAuClVoIZ8= ;{id = 55999 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=1 ;;lastchange=${$t0} ;;${ctime $t0} +example.com. 3600 IN DNSKEY 257 3 5 AwEAAbpIKlHvo1Ev4La/eEPoqThtFA8+vLxcjUQaowkkR/Xvvt6fd6iM3vSH6RsyvNgbj5C+HBjkciSeW4KthUuIDUk= ;{id = 51673 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=1 ;;lastchange=${$t0} ;;${ctime $t0} +example.com. 3600 IN DNSKEY 257 3 5 AwEAAbZxgKqPMoc8E7BqdrT84U7ux57LHMXQJnAogNcobTvC9+e3aeL5YdFSqgf6Em7ICISMzS+Sd0wJqgRoL0ZDhzk= ;{id = 29146 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=1 ;;lastchange=${$t0} ;;${ctime $t0} +example.com. 3600 IN DNSKEY 257 3 5 AwEAAZ25ylUZoX11EeM7aPqJOprcnGFiXgI7P407NMiBVd8Wz5J1aaUuPabfu4f15oLp4/6czzn3iuJp4UJU4ZTjFrc= ;{id = 27586 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=1 ;;lastchange=${$t0} ;;${ctime $t0} +example.com. 3600 IN DNSKEY 257 3 5 AwEAAa8er29rQIzO6+o3D4S8HsTTICTHHzDTeVbY/2kLdR0wwRy2PL8qvgxTX1YZXxEjrGHBhY5jD+aF9y9G3Ztfns8= ;{id = 22402 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=1 ;;lastchange=${$t0} ;;${ctime $t0} +example.com. 3600 IN DNSKEY 257 3 5 AwEAAdSj6e3XGnFwRNgw6Aifi4Q7SyRIdQ25XVsiWP/N9m7evkN+y6rlnaMP1ELRkhpiwK0bbNTP3DsGXtSMbR/4uzU= ;{id = 20314 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=1 ;;lastchange=${$t0} ;;${ctime $t0} +example.com. 3600 IN DNSKEY 257 3 5 AwEAAbXPzz66rviAvNKgPV5JNdkOZv9olQwNDFWnxy7p/RtObOL35ahwpamQGL5A5uPOvn1OghQyqiytTFFP8ZM/5Rc= ;{id = 11446 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=1 ;;lastchange=${$t0} ;;${ctime $t0} +example.com. 3600 IN DNSKEY 257 3 5 AwEAAaxpsO70/oPdKhulQXVbkLX5V6lyzF7G0gtz0nReLlBmfEk6zQ3WSW8VZ8kdZUCOLQwJl+5nWNfRvFxnqUGwjT8= ;{id = 11146 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=1 ;;lastchange=${$t0} ;;${ctime $t0} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1258962400 ;;Mon Nov 23 07:46:40 2009 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAas/cAhCFXvBUgTSNZCvQp0pLx1dY+7rXR0hH4/3EUgWmsmbYUpI1qD0xhwKD/oYGEwAm291fyWJ9c0oVxXDEK8= ;{id = 16486 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1258962400 ;;Mon Nov 23 07:46:40 2009 +FILE_END + +SCENARIO_END diff --git a/testdata/autotrust_addpend_2exceed.rpl b/testdata/autotrust_addpend_2exceed.rpl new file mode 100644 index 00000000000..5a15f8a1321 --- /dev/null +++ b/testdata/autotrust_addpend_2exceed.rpl @@ -0,0 +1,304 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + log-time-ascii: yes +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +; initial content (say from dig example.com DNSKEY > example.com.key) +AUTOTRUST_FILE example.com +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +AUTOTRUST_END +CONFIG_END + +SCENARIO_BEGIN Test autotrust with ADDPEND twice and exceeded time +; should work even though not signed with old key at latest time. + +; K-ROOT +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR AA +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS k.root-servers.net. +SECTION ADDITIONAL +k.root-servers.net IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 +RANGE_BEGIN 0 10 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. pYGxVLsWUvOp1wSf0iwPap+JnECfC5GAm1lRqy3YEqecNGld7U7x/5Imo3CerbdZrVptUQs2oH0lcjwYJXMnsw== ;{id = 30899} +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 5 2 3600 20090924111500 20090821111500 30899 example.com. J5wxRq0jgwQL6yy530kvo9cHqNAUHV8IF4dvaYZL0bNraO2Oe6dVXqlJl4+cxNHI2TMsstwFPr2Zz8tv6Az2mQ== ;{id = 30899} +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. JsXbS18oyc0zkVaOWGSFdIQuOsZKflT0GraT9afDPoWLCgH4ApF7jNgfJV7Pqy1sTBRajME5IUAhpANwGBuW4A== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 30899 example.com. b/HK231jIQLX8IhlZfup3r0yhpXaasbPE6LzxoEVVvWaTZWcLmeV8jDIcn0qO7Yvs7bIJN20lwVAV0GcHH3hWQ== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 55582 example.com. PCHme1QLoULxqjhg5tMlpR0qJlBfstEUVq18TtNoKQe9le1YhJ9caheXcTWoK+boLhXxg9u6Yyvq8FboQh0OjA== ;{id = 55582} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 and 60946 +RANGE_BEGIN 11 40 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 30899 example.com. rkaCUpTFPWVu4Om5oMTR+39Mct6ZMs56xrE0rbxMMOokfvIQheIxsAEc5BFJeA/2y5WTewl6diCD6yQXCybrDg== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 55582 example.com. CoMon+lWPAsUvgfpCTDPx8Zn8dQpky3lu2O6T+oJ2Mat9a/u1YwGhSQHGPn7ZNG/4vKM97tx84sSlUGz3geD1w== ;{id = 55582} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 60946 example.com. o+Cbs7DcYPYlSLd4hi3vkSVQpXGnKgKSi9MpHGfu1Uahv5190U2DUOxP1du/HOYbf+IHYL8zLbMZjVEG5wgnTg== ;{id = 60946} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 60946 +RANGE_BEGIN 41 50 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 30899 example.com. YHX8pWL0LsJ4HGuEgu/9cFbC+pQnN3QWA50p+Q6ukY+fTALxiBFlaLUXzNqMqxl7CoYU3Ty2LVd8acEoGLwy/g== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 60946 example.com. CZUdTyi3yebXMoyhMsna153k+WIiOk3jDPv8ixgwnw4u+ys/EB2UeQF0Laf1nDVziPhsQgu7/DYZQwfpvvpmmQ== ;{id = 60946} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582-REVOKED and 60946 +RANGE_BEGIN 51 60 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 385 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55710 (ksk), size = 512b} +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091224111500 20091118111500 30899 example.com. qLKZUJEi3ajSJ4/b7xl0BwhzW6JtjsojpZ+2nUx1PvaeQVoTmyWxjxc2tAmJGcBPqMqzeY470xvyMDvGTOiQCQ== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091224111500 20091118111500 55710 example.com. EW2YB+2yNX9LTNDPVwkcGnRTTx38pOiwBaixdwxmDgqWKXLDLM6Kd2Xv9tveS39RnSZ5H1inRXE55q+rL6Re3g== ;{id = 55710} +; wrong keytag: +;example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091224111500 20091118111500 55582 example.com. nH/6HauVJI4GGz78UoK/38cOOrEqsYZP0jFzfCC3OyIlclVTjAFvjVPlVMGK7sA5Nw1v20YtFTQkXZgbrRuInQ== ;{id = 55582} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091224111500 20091118111500 60946 example.com. xKSBZr4vOsEUKlVoNb6SOV69DM7xFOJI4gPFKq5Tv4APIMJ/9G3odoDmNcLCVyYGzhoDik5hciJnZio6UHgzAA== ;{id = 60946} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 60946 +RANGE_BEGIN 61 70 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20101224111500 20101118111500 30899 example.com. TfFGz1kDtkn3ixbKMJvQDZ0uGw/eW+inIiPqQVPQtO2WiocKrnYnzwv/AqwnFvEar70dF15/zffNIF+ipOS5/g== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20101224111500 20101118111500 60946 example.com. X0Ci//w0czN/J5RvypHGqp56n1tLdapi92ODAqjM7QpZXbSHaJ7wfPG1PZzvdxHUZUVyf8uy2stjg/XoLGHMWA== ;{id = 60946} +ENTRY_END +RANGE_END + +; set date/time to Aug 24 07:46:40 (2009). +STEP 5 TIME_PASSES ELAPSE 1251100000 +STEP 6 TRAFFIC ; the initial probe +STEP 7 ASSIGN t0 = ${time} +STEP 8 ASSIGN probe0 = ${range 4800 ${timeout} 5400} + +; the auto probing should have been done now. +STEP 10 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t0} ;;${ctime $t0} +;;last_success: ${$t0} ;;${ctime $t0} +;;next_probe_time: ${$t0 + $probe0} ;;${ctime $t0 + $probe0} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; key prepublished. First poll. 30 days later +STEP 11 TIME_PASSES EVAL ${30*24*3600} +STEP 12 TRAFFIC +STEP 13 ASSIGN t1 = ${time} +STEP 14 ASSIGN probe1 = ${range 4800 ${timeout} 5400} +STEP 15 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t1} ;;${ctime $t1} +;;last_success: ${$t1} ;;${ctime $t1} +;;next_probe_time: ${$t1 + $probe1} ;;${ctime $t1 + $probe1} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=1 ;;lastchange=${$t1} ;;${ctime $t1} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; Second poll. 10 days later +STEP 21 TIME_PASSES EVAL ${10*24*3600} +STEP 22 TRAFFIC +STEP 23 ASSIGN t2 = ${time} +STEP 24 ASSIGN probe2 = ${range 4800 ${timeout} 5400} +STEP 25 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t2} ;;${ctime $t2} +;;last_success: ${$t2} ;;${ctime $t2} +;;next_probe_time: ${$t2 + $probe2} ;;${ctime $t2 + $probe2} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=2 ;;lastchange=${$t1} ;;${ctime $t1} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; t3 is removed third poll time. + +; 21 days later, hold down has lapsed. +STEP 41 TIME_PASSES EVAL ${21*24*3600} +STEP 42 TRAFFIC +STEP 43 ASSIGN t4 = ${time} +STEP 44 ASSIGN probe4 = ${range 4800 ${timeout} 5400} +STEP 45 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t4} ;;${ctime $t4} +;;last_success: ${$t4} ;;${ctime $t4} +;;next_probe_time: ${$t4 + $probe4} ;;${ctime $t4 + $probe4} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t4} ;;${ctime $t4} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=3 [ MISSING ] ;;count=0 ;;lastchange=${$t4} ;;${ctime $t4} +FILE_END + +; 30 days later, the old key is revoked +STEP 51 TIME_PASSES EVAL ${30*24*3600} +STEP 52 TRAFFIC +STEP 53 ASSIGN t5 = ${time} +STEP 54 ASSIGN probe5 = ${range 4800 ${timeout} 5400} +STEP 55 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t5} ;;${ctime $t5} +;;last_success: ${$t5} ;;${ctime $t5} +;;next_probe_time: ${$t5 + $probe5} ;;${ctime $t5 + $probe5} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t4} ;;${ctime $t4} +example.com. 10800 IN DNSKEY 385 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55710 (ksk), size = 512b} ;;state=4 [ REVOKED ] ;;count=0 ;;lastchange=${$t5} ;;${ctime $t5} +FILE_END + +; 370 days later, the old key is removed from storage +STEP 61 TIME_PASSES EVAL ${370*24*3600} +STEP 62 TRAFFIC +STEP 63 ASSIGN t6 = ${time} +STEP 64 ASSIGN probe6 = ${range 4800 ${timeout} 5400} +STEP 65 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t6} ;;${ctime $t6} +;;last_success: ${$t6} ;;${ctime $t6} +;;next_probe_time: ${$t6 + $probe6} ;;${ctime $t6 + $probe6} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t4} ;;${ctime $t4} +FILE_END + + +SCENARIO_END diff --git a/testdata/autotrust_addpend_early.rpl b/testdata/autotrust_addpend_early.rpl new file mode 100644 index 00000000000..8ff3299e7ff --- /dev/null +++ b/testdata/autotrust_addpend_early.rpl @@ -0,0 +1,240 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + log-time-ascii: yes +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +; initial content (say from dig example.com DNSKEY > example.com.key) +AUTOTRUST_FILE example.com +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +AUTOTRUST_END +CONFIG_END + +SCENARIO_BEGIN Test autotrust with ADDPEND used too early +; this should not work, as the holdown has not expired yet. + +; K-ROOT +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR AA +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS k.root-servers.net. +SECTION ADDITIONAL +k.root-servers.net IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 +RANGE_BEGIN 0 10 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. pYGxVLsWUvOp1wSf0iwPap+JnECfC5GAm1lRqy3YEqecNGld7U7x/5Imo3CerbdZrVptUQs2oH0lcjwYJXMnsw== ;{id = 30899} +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 5 2 3600 20090924111500 20090821111500 30899 example.com. J5wxRq0jgwQL6yy530kvo9cHqNAUHV8IF4dvaYZL0bNraO2Oe6dVXqlJl4+cxNHI2TMsstwFPr2Zz8tv6Az2mQ== ;{id = 30899} +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. JsXbS18oyc0zkVaOWGSFdIQuOsZKflT0GraT9afDPoWLCgH4ApF7jNgfJV7Pqy1sTBRajME5IUAhpANwGBuW4A== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 30899 example.com. b/HK231jIQLX8IhlZfup3r0yhpXaasbPE6LzxoEVVvWaTZWcLmeV8jDIcn0qO7Yvs7bIJN20lwVAV0GcHH3hWQ== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 55582 example.com. PCHme1QLoULxqjhg5tMlpR0qJlBfstEUVq18TtNoKQe9le1YhJ9caheXcTWoK+boLhXxg9u6Yyvq8FboQh0OjA== ;{id = 55582} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 and 60946 +RANGE_BEGIN 11 40 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 30899 example.com. rkaCUpTFPWVu4Om5oMTR+39Mct6ZMs56xrE0rbxMMOokfvIQheIxsAEc5BFJeA/2y5WTewl6diCD6yQXCybrDg== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 55582 example.com. CoMon+lWPAsUvgfpCTDPx8Zn8dQpky3lu2O6T+oJ2Mat9a/u1YwGhSQHGPn7ZNG/4vKM97tx84sSlUGz3geD1w== ;{id = 55582} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 60946 example.com. o+Cbs7DcYPYlSLd4hi3vkSVQpXGnKgKSi9MpHGfu1Uahv5190U2DUOxP1du/HOYbf+IHYL8zLbMZjVEG5wgnTg== ;{id = 60946} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 60946 +RANGE_BEGIN 41 50 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 30899 example.com. nDlOZCE24pNtuoYkmmy9cVvtCn7ykdmlhJX9hYcI9b3DzqJjOrGz3GD5RQvti3uxD74gFcFho0g76NwOKFx/qQ== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 60946 example.com. qBHDZu0XQmr6kpt51r1DxT5tuyfwSHcoL8qLpwwhyyNFF13OPlvxgmCVl+1v27A9+h8tcuqaNls5f+tcFBwtRg== ;{id = 60946} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN A +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN AAAA +ENTRY_END +RANGE_END + + +; set date/time to Aug 24 07:46:40 (2009). +STEP 5 TIME_PASSES ELAPSE 1251100000 +STEP 6 TRAFFIC ; the initial probe +STEP 7 ASSIGN t0 = ${time} +STEP 8 ASSIGN probe0 = ${range 4800 ${timeout} 5400} + +; the auto probing should have been done now. +STEP 10 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t0} ;;${ctime $t0} +;;last_success: ${$t0} ;;${ctime $t0} +;;next_probe_time: ${$t0 + $probe0} ;;${ctime $t0 + $probe0} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; key prepublished. First poll. 30 days later +STEP 11 TIME_PASSES EVAL ${30*24*3600} +STEP 12 TRAFFIC +STEP 13 ASSIGN t1 = ${time} +STEP 14 ASSIGN probe1 = ${range 4800 ${timeout} 5400} +STEP 15 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t1} ;;${ctime $t1} +;;last_success: ${$t1} ;;${ctime $t1} +;;next_probe_time: ${$t1 + $probe1} ;;${ctime $t1 + $probe1} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=1 ;;lastchange=${$t1} ;;${ctime $t1} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; Second poll. 10 days later +STEP 21 TIME_PASSES EVAL ${10*24*3600} +STEP 22 TRAFFIC +STEP 23 ASSIGN t2 = ${time} +STEP 24 ASSIGN probe2 = ${range 4800 ${timeout} 5400} +STEP 25 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t2} ;;${ctime $t2} +;;last_success: ${$t2} ;;${ctime $t2} +;;next_probe_time: ${$t2 + $probe2} ;;${ctime $t2 + $probe2} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=2 ;;lastchange=${$t1} ;;${ctime $t1} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; t3 is removed third poll time. + +; only 10 days later: hold down has not lapsed! (need 21 days). +STEP 41 TIME_PASSES EVAL ${10*24*3600} +STEP 42 TRAFFIC +STEP 43 ASSIGN t4 = ${time} +; must fail! +STEP 44 ASSIGN probe4 = ${range 3200 ${timeout} 3600} +STEP 45 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t4} ;;${ctime $t4} +;;last_success: ${$t2} ;;${ctime $t2} +;;next_probe_time: ${$t4 + $probe4} ;;${ctime $t4 + $probe4} +;;query_failed: 6 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=2 ;;lastchange=${$t1} ;;${ctime $t1} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + + +SCENARIO_END diff --git a/testdata/autotrust_addpend_nosign.rpl b/testdata/autotrust_addpend_nosign.rpl new file mode 100644 index 00000000000..68906330961 --- /dev/null +++ b/testdata/autotrust_addpend_nosign.rpl @@ -0,0 +1,222 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + log-time-ascii: yes +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +; initial content (say from dig example.com DNSKEY > example.com.key) +AUTOTRUST_FILE example.com +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +AUTOTRUST_END +CONFIG_END + +SCENARIO_BEGIN Test autotrust ADDPEND state cannot sign + +; K-ROOT +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR AA +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS k.root-servers.net. +SECTION ADDITIONAL +k.root-servers.net IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 +RANGE_BEGIN 0 10 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. pYGxVLsWUvOp1wSf0iwPap+JnECfC5GAm1lRqy3YEqecNGld7U7x/5Imo3CerbdZrVptUQs2oH0lcjwYJXMnsw== ;{id = 30899} +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 5 2 3600 20090924111500 20090821111500 30899 example.com. J5wxRq0jgwQL6yy530kvo9cHqNAUHV8IF4dvaYZL0bNraO2Oe6dVXqlJl4+cxNHI2TMsstwFPr2Zz8tv6Az2mQ== ;{id = 30899} +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. JsXbS18oyc0zkVaOWGSFdIQuOsZKflT0GraT9afDPoWLCgH4ApF7jNgfJV7Pqy1sTBRajME5IUAhpANwGBuW4A== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 30899 example.com. b/HK231jIQLX8IhlZfup3r0yhpXaasbPE6LzxoEVVvWaTZWcLmeV8jDIcn0qO7Yvs7bIJN20lwVAV0GcHH3hWQ== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 55582 example.com. PCHme1QLoULxqjhg5tMlpR0qJlBfstEUVq18TtNoKQe9le1YhJ9caheXcTWoK+boLhXxg9u6Yyvq8FboQh0OjA== ;{id = 55582} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 and 60946 +RANGE_BEGIN 11 20 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 30899 example.com. rkaCUpTFPWVu4Om5oMTR+39Mct6ZMs56xrE0rbxMMOokfvIQheIxsAEc5BFJeA/2y5WTewl6diCD6yQXCybrDg== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 55582 example.com. CoMon+lWPAsUvgfpCTDPx8Zn8dQpky3lu2O6T+oJ2Mat9a/u1YwGhSQHGPn7ZNG/4vKM97tx84sSlUGz3geD1w== ;{id = 55582} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 60946 example.com. o+Cbs7DcYPYlSLd4hi3vkSVQpXGnKgKSi9MpHGfu1Uahv5190U2DUOxP1du/HOYbf+IHYL8zLbMZjVEG5wgnTg== ;{id = 60946} +ENTRY_END + +RANGE_END + +; ns.example.com. KSK 55582 and 60946 (signatures updated) +RANGE_BEGIN 21 50 + ADDRESS 1.2.3.4 +; badly signed DNSKEY probe only signed with ADDPEND key +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 30899 example.com. rkaCUpTFPWVu4Om5oMTR+39Mct6ZMs56xrE0rbxMMOokfvIQheIxsAEc5BFJeA/2y5WTewl6diCD6yQXCybrDg== ;{id = 30899} +;example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 55582 example.com. CoMon+lWPAsUvgfpCTDPx8Zn8dQpky3lu2O6T+oJ2Mat9a/u1YwGhSQHGPn7ZNG/4vKM97tx84sSlUGz3geD1w== ;{id = 55582} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 60946 example.com. o+Cbs7DcYPYlSLd4hi3vkSVQpXGnKgKSi9MpHGfu1Uahv5190U2DUOxP1du/HOYbf+IHYL8zLbMZjVEG5wgnTg== ;{id = 60946} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN A +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN AAAA +ENTRY_END +RANGE_END + +; set date/time to Aug 24 07:46:40 (2009). +STEP 5 TIME_PASSES ELAPSE 1251100000 +STEP 6 TRAFFIC ; the initial probe +STEP 7 ASSIGN t0 = ${time} +STEP 8 ASSIGN probe0 = ${range 4800 ${timeout} 5400} + +; the auto probing should have been done now. +STEP 10 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t0} ;;${ctime $t0} +;;last_success: ${$t0} ;;${ctime $t0} +;;next_probe_time: ${$t0 + $probe0} ;;${ctime $t0 + $probe0} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; key prepublished. First poll. 30 days later +STEP 11 TIME_PASSES EVAL ${30*24*3600} +STEP 12 TRAFFIC +STEP 13 ASSIGN t1 = ${time} +STEP 14 ASSIGN probe1 = ${range 4800 ${timeout} 5400} +STEP 15 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t1} ;;${ctime $t1} +;;last_success: ${$t1} ;;${ctime $t1} +;;next_probe_time: ${$t1 + $probe1} ;;${ctime $t1 + $probe1} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=1 ;;lastchange=${$t1} ;;${ctime $t1} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; Second poll. 10 days later +STEP 21 TIME_PASSES EVAL ${10*24*3600} +STEP 22 TRAFFIC +STEP 23 ASSIGN t2 = ${time} + +; probe must be a failed probe! no larger than 3600 +STEP 24 ASSIGN probe2 = ${range 3200 ${timeout} 3600} +STEP 25 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t2} ;;${ctime $t2} +;;last_success: ${$t1} ;;${ctime $t1} +;;next_probe_time: ${$t2 + $probe2} ;;${ctime $t2 + $probe2} +;;query_failed: 6 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=1 ;;lastchange=${$t1} ;;${ctime $t1} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +SCENARIO_END diff --git a/testdata/autotrust_addpend_nosignnew.rpl b/testdata/autotrust_addpend_nosignnew.rpl new file mode 100644 index 00000000000..d3b46d86bed --- /dev/null +++ b/testdata/autotrust_addpend_nosignnew.rpl @@ -0,0 +1,223 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + log-time-ascii: yes +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +; initial content (say from dig example.com DNSKEY > example.com.key) +AUTOTRUST_FILE example.com +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +AUTOTRUST_END +CONFIG_END + +SCENARIO_BEGIN Test autotrust ADDPEND state cannot add new key + +; K-ROOT +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR AA +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS k.root-servers.net. +SECTION ADDITIONAL +k.root-servers.net IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 +RANGE_BEGIN 0 10 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. pYGxVLsWUvOp1wSf0iwPap+JnECfC5GAm1lRqy3YEqecNGld7U7x/5Imo3CerbdZrVptUQs2oH0lcjwYJXMnsw== ;{id = 30899} +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 5 2 3600 20090924111500 20090821111500 30899 example.com. J5wxRq0jgwQL6yy530kvo9cHqNAUHV8IF4dvaYZL0bNraO2Oe6dVXqlJl4+cxNHI2TMsstwFPr2Zz8tv6Az2mQ== ;{id = 30899} +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. JsXbS18oyc0zkVaOWGSFdIQuOsZKflT0GraT9afDPoWLCgH4ApF7jNgfJV7Pqy1sTBRajME5IUAhpANwGBuW4A== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 30899 example.com. b/HK231jIQLX8IhlZfup3r0yhpXaasbPE6LzxoEVVvWaTZWcLmeV8jDIcn0qO7Yvs7bIJN20lwVAV0GcHH3hWQ== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 55582 example.com. PCHme1QLoULxqjhg5tMlpR0qJlBfstEUVq18TtNoKQe9le1YhJ9caheXcTWoK+boLhXxg9u6Yyvq8FboQh0OjA== ;{id = 55582} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 and 60946 +RANGE_BEGIN 11 20 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 30899 example.com. rkaCUpTFPWVu4Om5oMTR+39Mct6ZMs56xrE0rbxMMOokfvIQheIxsAEc5BFJeA/2y5WTewl6diCD6yQXCybrDg== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 55582 example.com. CoMon+lWPAsUvgfpCTDPx8Zn8dQpky3lu2O6T+oJ2Mat9a/u1YwGhSQHGPn7ZNG/4vKM97tx84sSlUGz3geD1w== ;{id = 55582} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 60946 example.com. o+Cbs7DcYPYlSLd4hi3vkSVQpXGnKgKSi9MpHGfu1Uahv5190U2DUOxP1du/HOYbf+IHYL8zLbMZjVEG5wgnTg== ;{id = 60946} +ENTRY_END + +RANGE_END + +; ns.example.com. KSK 55582 and 60946 (signatures updated) +RANGE_BEGIN 21 50 + ADDRESS 1.2.3.4 +; badly signed DNSKEY probe only signed with ADDPEND key +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; new KSK +example.com. 10800 IN DNSKEY 257 3 5 AwEAAas/cAhCFXvBUgTSNZCvQp0pLx1dY+7rXR0hH4/3EUgWmsmbYUpI1qD0xhwKD/oYGEwAm291fyWJ9c0oVxXDEK8= ;{id = 16486 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 30899 example.com. JDeT7Z5zP9iw3RDFT4Yo+UMHo7qDNr3KjwIopAr+T3OyVGvoOWkDV+nqHIj3UNNzrjzWvoLpZaUrZuhaqily7w== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 60946 example.com. rOxbAROwiW21OR8HjINk3IBs9bsxJKjipQ5EU4wWutiF/jr6KNT6LgtZv0TaFSiBHN/Jqz1wB2ODD2HXwLQ4DQ== ;{id = 60946} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN A +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN AAAA +ENTRY_END +RANGE_END + +; set date/time to Aug 24 07:46:40 (2009). +STEP 5 TIME_PASSES ELAPSE 1251100000 +STEP 6 TRAFFIC ; the initial probe +STEP 7 ASSIGN t0 = ${time} +STEP 8 ASSIGN probe0 = ${range 4800 ${timeout} 5400} + +; the auto probing should have been done now. +STEP 10 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t0} ;;${ctime $t0} +;;last_success: ${$t0} ;;${ctime $t0} +;;next_probe_time: ${$t0 + $probe0} ;;${ctime $t0 + $probe0} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; key prepublished. First poll. 30 days later +STEP 11 TIME_PASSES EVAL ${30*24*3600} +STEP 12 TRAFFIC +STEP 13 ASSIGN t1 = ${time} +STEP 14 ASSIGN probe1 = ${range 4800 ${timeout} 5400} +STEP 15 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t1} ;;${ctime $t1} +;;last_success: ${$t1} ;;${ctime $t1} +;;next_probe_time: ${$t1 + $probe1} ;;${ctime $t1 + $probe1} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=1 ;;lastchange=${$t1} ;;${ctime $t1} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; Second poll. 10 days later +STEP 21 TIME_PASSES EVAL ${10*24*3600} +STEP 22 TRAFFIC +STEP 23 ASSIGN t2 = ${time} + +; probe must be a failed probe! no larger than 3600 +STEP 24 ASSIGN probe2 = ${range 3200 ${timeout} 3600} +STEP 25 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t2} ;;${ctime $t2} +;;last_success: ${$t1} ;;${ctime $t1} +;;next_probe_time: ${$t2 + $probe2} ;;${ctime $t2 + $probe2} +;;query_failed: 6 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=1 ;;lastchange=${$t1} ;;${ctime $t1} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +SCENARIO_END diff --git a/testdata/autotrust_addpend_once.rpl b/testdata/autotrust_addpend_once.rpl new file mode 100644 index 00000000000..3c7b46804b1 --- /dev/null +++ b/testdata/autotrust_addpend_once.rpl @@ -0,0 +1,276 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + log-time-ascii: yes +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +; initial content (say from dig example.com DNSKEY > example.com.key) +AUTOTRUST_FILE example.com +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +AUTOTRUST_END +CONFIG_END + +SCENARIO_BEGIN Test autotrust with ADDPEND seen once +; this should fail. + +; K-ROOT +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR AA +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS k.root-servers.net. +SECTION ADDITIONAL +k.root-servers.net IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 +RANGE_BEGIN 0 10 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. pYGxVLsWUvOp1wSf0iwPap+JnECfC5GAm1lRqy3YEqecNGld7U7x/5Imo3CerbdZrVptUQs2oH0lcjwYJXMnsw== ;{id = 30899} +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 5 2 3600 20090924111500 20090821111500 30899 example.com. J5wxRq0jgwQL6yy530kvo9cHqNAUHV8IF4dvaYZL0bNraO2Oe6dVXqlJl4+cxNHI2TMsstwFPr2Zz8tv6Az2mQ== ;{id = 30899} +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. JsXbS18oyc0zkVaOWGSFdIQuOsZKflT0GraT9afDPoWLCgH4ApF7jNgfJV7Pqy1sTBRajME5IUAhpANwGBuW4A== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 30899 example.com. b/HK231jIQLX8IhlZfup3r0yhpXaasbPE6LzxoEVVvWaTZWcLmeV8jDIcn0qO7Yvs7bIJN20lwVAV0GcHH3hWQ== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 55582 example.com. PCHme1QLoULxqjhg5tMlpR0qJlBfstEUVq18TtNoKQe9le1YhJ9caheXcTWoK+boLhXxg9u6Yyvq8FboQh0OjA== ;{id = 55582} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 and 60946 +RANGE_BEGIN 11 40 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 30899 example.com. rkaCUpTFPWVu4Om5oMTR+39Mct6ZMs56xrE0rbxMMOokfvIQheIxsAEc5BFJeA/2y5WTewl6diCD6yQXCybrDg== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 55582 example.com. CoMon+lWPAsUvgfpCTDPx8Zn8dQpky3lu2O6T+oJ2Mat9a/u1YwGhSQHGPn7ZNG/4vKM97tx84sSlUGz3geD1w== ;{id = 55582} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 60946 example.com. o+Cbs7DcYPYlSLd4hi3vkSVQpXGnKgKSi9MpHGfu1Uahv5190U2DUOxP1du/HOYbf+IHYL8zLbMZjVEG5wgnTg== ;{id = 60946} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 and 60946 (signatures updated) +RANGE_BEGIN 41 50 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 30899 example.com. rkaCUpTFPWVu4Om5oMTR+39Mct6ZMs56xrE0rbxMMOokfvIQheIxsAEc5BFJeA/2y5WTewl6diCD6yQXCybrDg== ;{id = 30899} +;example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 55582 example.com. v/HJbdpeVMpbhwYXrT1EDGpAFMvEgdKQII1cAbP6o8KHYNKDh8TIJ25/pXe3daEXfej6/Z5kpqJ79okPKUoi1Q== ;{id = 55582} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 60946 example.com. HgXol1hdvbomOM1CFRW8qsHd3D0qOnN72EeMHTcpxIBBiuNLKZn4n1M14Voxj3vo0eAMNuG/y7EjQkxKvSsaDA== ;{id = 60946} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN A +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN AAAA +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582-REVOKED and 60946 +RANGE_BEGIN 51 60 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 385 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55710 (ksk), size = 512b} +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091224111500 20091118111500 30899 example.com. qLKZUJEi3ajSJ4/b7xl0BwhzW6JtjsojpZ+2nUx1PvaeQVoTmyWxjxc2tAmJGcBPqMqzeY470xvyMDvGTOiQCQ== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091224111500 20091118111500 55710 example.com. EW2YB+2yNX9LTNDPVwkcGnRTTx38pOiwBaixdwxmDgqWKXLDLM6Kd2Xv9tveS39RnSZ5H1inRXE55q+rL6Re3g== ;{id = 55710} +; wrong keytag: +;example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091224111500 20091118111500 55582 example.com. nH/6HauVJI4GGz78UoK/38cOOrEqsYZP0jFzfCC3OyIlclVTjAFvjVPlVMGK7sA5Nw1v20YtFTQkXZgbrRuInQ== ;{id = 55582} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091224111500 20091118111500 60946 example.com. xKSBZr4vOsEUKlVoNb6SOV69DM7xFOJI4gPFKq5Tv4APIMJ/9G3odoDmNcLCVyYGzhoDik5hciJnZio6UHgzAA== ;{id = 60946} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN AAAA +ENTRY_END +RANGE_END + +; ns.example.com. KSK 60946 +RANGE_BEGIN 61 70 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20101224111500 20101118111500 30899 example.com. TfFGz1kDtkn3ixbKMJvQDZ0uGw/eW+inIiPqQVPQtO2WiocKrnYnzwv/AqwnFvEar70dF15/zffNIF+ipOS5/g== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20101224111500 20101118111500 60946 example.com. X0Ci//w0czN/J5RvypHGqp56n1tLdapi92ODAqjM7QpZXbSHaJ7wfPG1PZzvdxHUZUVyf8uy2stjg/XoLGHMWA== ;{id = 60946} +ENTRY_END +RANGE_END + +; set date/time to Aug 24 07:46:40 (2009). +STEP 5 TIME_PASSES ELAPSE 1251100000 +STEP 6 TRAFFIC ; the initial probe +STEP 7 ASSIGN t0 = ${time} +STEP 8 ASSIGN probe0 = ${range 4800 ${timeout} 5400} + +; the auto probing should have been done now. +STEP 10 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t0} ;;${ctime $t0} +;;last_success: ${$t0} ;;${ctime $t0} +;;next_probe_time: ${$t0 + $probe0} ;;${ctime $t0 + $probe0} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; key prepublished. First poll. 30 days later +STEP 11 TIME_PASSES EVAL ${30*24*3600} +STEP 12 TRAFFIC +STEP 13 ASSIGN t1 = ${time} +STEP 14 ASSIGN probe1 = ${range 4800 ${timeout} 5400} +STEP 15 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t1} ;;${ctime $t1} +;;last_success: ${$t1} ;;${ctime $t1} +;;next_probe_time: ${$t1 + $probe1} ;;${ctime $t1 + $probe1} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=1 ;;lastchange=${$t1} ;;${ctime $t1} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; t2 is removed second poll time. +; t3 is removed third poll time. + +; 31 days later, hold down has lapsed. +STEP 41 TIME_PASSES EVAL ${31*24*3600} +STEP 42 TRAFFIC +STEP 43 ASSIGN t4 = ${time} +; it fails! ADDPEND not valid for signing this answer. +STEP 44 ASSIGN probe4 = ${range 3200 ${timeout} 3600} +STEP 45 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t4} ;;${ctime $t4} +;;last_success: ${$t1} ;;${ctime $t1} +;;next_probe_time: ${$t4 + $probe4} ;;${ctime $t4 + $probe4} +;;query_failed: 6 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=1 ;;lastchange=${$t1} ;;${ctime $t1} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +SCENARIO_END diff --git a/testdata/autotrust_addpend_twice.rpl b/testdata/autotrust_addpend_twice.rpl new file mode 100644 index 00000000000..9bb788093fb --- /dev/null +++ b/testdata/autotrust_addpend_twice.rpl @@ -0,0 +1,307 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + log-time-ascii: yes +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +; initial content (say from dig example.com DNSKEY > example.com.key) +AUTOTRUST_FILE example.com +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +AUTOTRUST_END +CONFIG_END + +SCENARIO_BEGIN Test autotrust with ADDPEND seen twice +; this should work. + +; K-ROOT +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR AA +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS k.root-servers.net. +SECTION ADDITIONAL +k.root-servers.net IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 +RANGE_BEGIN 0 10 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. pYGxVLsWUvOp1wSf0iwPap+JnECfC5GAm1lRqy3YEqecNGld7U7x/5Imo3CerbdZrVptUQs2oH0lcjwYJXMnsw== ;{id = 30899} +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 5 2 3600 20090924111500 20090821111500 30899 example.com. J5wxRq0jgwQL6yy530kvo9cHqNAUHV8IF4dvaYZL0bNraO2Oe6dVXqlJl4+cxNHI2TMsstwFPr2Zz8tv6Az2mQ== ;{id = 30899} +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. JsXbS18oyc0zkVaOWGSFdIQuOsZKflT0GraT9afDPoWLCgH4ApF7jNgfJV7Pqy1sTBRajME5IUAhpANwGBuW4A== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 30899 example.com. b/HK231jIQLX8IhlZfup3r0yhpXaasbPE6LzxoEVVvWaTZWcLmeV8jDIcn0qO7Yvs7bIJN20lwVAV0GcHH3hWQ== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 55582 example.com. PCHme1QLoULxqjhg5tMlpR0qJlBfstEUVq18TtNoKQe9le1YhJ9caheXcTWoK+boLhXxg9u6Yyvq8FboQh0OjA== ;{id = 55582} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 and 60946 +RANGE_BEGIN 11 40 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 30899 example.com. rkaCUpTFPWVu4Om5oMTR+39Mct6ZMs56xrE0rbxMMOokfvIQheIxsAEc5BFJeA/2y5WTewl6diCD6yQXCybrDg== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 55582 example.com. CoMon+lWPAsUvgfpCTDPx8Zn8dQpky3lu2O6T+oJ2Mat9a/u1YwGhSQHGPn7ZNG/4vKM97tx84sSlUGz3geD1w== ;{id = 55582} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 60946 example.com. o+Cbs7DcYPYlSLd4hi3vkSVQpXGnKgKSi9MpHGfu1Uahv5190U2DUOxP1du/HOYbf+IHYL8zLbMZjVEG5wgnTg== ;{id = 60946} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 and 60946 (signatures updated) +RANGE_BEGIN 41 50 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 30899 example.com. rkaCUpTFPWVu4Om5oMTR+39Mct6ZMs56xrE0rbxMMOokfvIQheIxsAEc5BFJeA/2y5WTewl6diCD6yQXCybrDg== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 55582 example.com. v/HJbdpeVMpbhwYXrT1EDGpAFMvEgdKQII1cAbP6o8KHYNKDh8TIJ25/pXe3daEXfej6/Z5kpqJ79okPKUoi1Q== ;{id = 55582} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 60946 example.com. HgXol1hdvbomOM1CFRW8qsHd3D0qOnN72EeMHTcpxIBBiuNLKZn4n1M14Voxj3vo0eAMNuG/y7EjQkxKvSsaDA== ;{id = 60946} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582-REVOKED and 60946 +RANGE_BEGIN 51 60 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 385 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55710 (ksk), size = 512b} +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091224111500 20091118111500 30899 example.com. qLKZUJEi3ajSJ4/b7xl0BwhzW6JtjsojpZ+2nUx1PvaeQVoTmyWxjxc2tAmJGcBPqMqzeY470xvyMDvGTOiQCQ== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091224111500 20091118111500 55710 example.com. EW2YB+2yNX9LTNDPVwkcGnRTTx38pOiwBaixdwxmDgqWKXLDLM6Kd2Xv9tveS39RnSZ5H1inRXE55q+rL6Re3g== ;{id = 55710} +; wrong keytag: +;example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091224111500 20091118111500 55582 example.com. nH/6HauVJI4GGz78UoK/38cOOrEqsYZP0jFzfCC3OyIlclVTjAFvjVPlVMGK7sA5Nw1v20YtFTQkXZgbrRuInQ== ;{id = 55582} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091224111500 20091118111500 60946 example.com. xKSBZr4vOsEUKlVoNb6SOV69DM7xFOJI4gPFKq5Tv4APIMJ/9G3odoDmNcLCVyYGzhoDik5hciJnZio6UHgzAA== ;{id = 60946} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 60946 +RANGE_BEGIN 61 70 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20101224111500 20101118111500 30899 example.com. TfFGz1kDtkn3ixbKMJvQDZ0uGw/eW+inIiPqQVPQtO2WiocKrnYnzwv/AqwnFvEar70dF15/zffNIF+ipOS5/g== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20101224111500 20101118111500 60946 example.com. X0Ci//w0czN/J5RvypHGqp56n1tLdapi92ODAqjM7QpZXbSHaJ7wfPG1PZzvdxHUZUVyf8uy2stjg/XoLGHMWA== ;{id = 60946} +ENTRY_END +RANGE_END + +; set date/time to Aug 24 07:46:40 (2009). +STEP 5 TIME_PASSES ELAPSE 1251100000 +STEP 6 TRAFFIC ; the initial probe +STEP 7 ASSIGN t0 = ${time} +STEP 8 ASSIGN probe0 = ${range 4800 ${timeout} 5400} + +; the auto probing should have been done now. +STEP 10 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t0} ;;${ctime $t0} +;;last_success: ${$t0} ;;${ctime $t0} +;;next_probe_time: ${$t0 + $probe0} ;;${ctime $t0 + $probe0} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; key prepublished. First poll. 30 days later +STEP 11 TIME_PASSES EVAL ${30*24*3600} +STEP 12 TRAFFIC +STEP 13 ASSIGN t1 = ${time} +STEP 14 ASSIGN probe1 = ${range 4800 ${timeout} 5400} +STEP 15 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t1} ;;${ctime $t1} +;;last_success: ${$t1} ;;${ctime $t1} +;;next_probe_time: ${$t1 + $probe1} ;;${ctime $t1 + $probe1} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=1 ;;lastchange=${$t1} ;;${ctime $t1} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; Second poll. 10 days later +STEP 21 TIME_PASSES EVAL ${10*24*3600} +STEP 22 TRAFFIC +STEP 23 ASSIGN t2 = ${time} +STEP 24 ASSIGN probe2 = ${range 4800 ${timeout} 5400} +STEP 25 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t2} ;;${ctime $t2} +;;last_success: ${$t2} ;;${ctime $t2} +;;next_probe_time: ${$t2 + $probe2} ;;${ctime $t2 + $probe2} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=2 ;;lastchange=${$t1} ;;${ctime $t1} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; t3 is removed third poll time. + +; 21 days later, hold down has lapsed. +STEP 41 TIME_PASSES EVAL ${21*24*3600} +STEP 42 TRAFFIC +STEP 43 ASSIGN t4 = ${time} +STEP 44 ASSIGN probe4 = ${range 4800 ${timeout} 5400} +STEP 45 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t4} ;;${ctime $t4} +;;last_success: ${$t4} ;;${ctime $t4} +;;next_probe_time: ${$t4 + $probe4} ;;${ctime $t4 + $probe4} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t4} ;;${ctime $t4} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; 30 days later, the old key is revoked +STEP 51 TIME_PASSES EVAL ${30*24*3600} +STEP 52 TRAFFIC +STEP 53 ASSIGN t5 = ${time} +STEP 54 ASSIGN probe5 = ${range 4800 ${timeout} 5400} +STEP 55 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t5} ;;${ctime $t5} +;;last_success: ${$t5} ;;${ctime $t5} +;;next_probe_time: ${$t5 + $probe5} ;;${ctime $t5 + $probe5} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t4} ;;${ctime $t4} +example.com. 10800 IN DNSKEY 385 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55710 (ksk), size = 512b} ;;state=4 [ REVOKED ] ;;count=0 ;;lastchange=${$t5} ;;${ctime $t5} +FILE_END + +; 370 days later, the old key is removed from storage +STEP 61 TIME_PASSES EVAL ${370*24*3600} +STEP 62 TRAFFIC +STEP 63 ASSIGN t6 = ${time} +STEP 64 ASSIGN probe6 = ${range 4800 ${timeout} 5400} +STEP 65 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t6} ;;${ctime $t6} +;;last_success: ${$t6} ;;${ctime $t6} +;;next_probe_time: ${$t6 + $probe6} ;;${ctime $t6 + $probe6} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t4} ;;${ctime $t4} +FILE_END + + +SCENARIO_END diff --git a/testdata/autotrust_init.rpl b/testdata/autotrust_init.rpl new file mode 100644 index 00000000000..53698a1077f --- /dev/null +++ b/testdata/autotrust_init.rpl @@ -0,0 +1,181 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + log-time-ascii: yes +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +; initial content (say from dig example.com DNSKEY > example.com.key) +AUTOTRUST_FILE example.com +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +AUTOTRUST_END +CONFIG_END + +SCENARIO_BEGIN Test autotrust with initial trust anchor + +; K-ROOT +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR AA +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS k.root-servers.net. +SECTION ADDITIONAL +k.root-servers.net IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. pYGxVLsWUvOp1wSf0iwPap+JnECfC5GAm1lRqy3YEqecNGld7U7x/5Imo3CerbdZrVptUQs2oH0lcjwYJXMnsw== ;{id = 30899} +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 5 2 3600 20090924111500 20090821111500 30899 example.com. J5wxRq0jgwQL6yy530kvo9cHqNAUHV8IF4dvaYZL0bNraO2Oe6dVXqlJl4+cxNHI2TMsstwFPr2Zz8tv6Az2mQ== ;{id = 30899} +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. JsXbS18oyc0zkVaOWGSFdIQuOsZKflT0GraT9afDPoWLCgH4ApF7jNgfJV7Pqy1sTBRajME5IUAhpANwGBuW4A== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (ksk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 30899 example.com. b/HK231jIQLX8IhlZfup3r0yhpXaasbPE6LzxoEVVvWaTZWcLmeV8jDIcn0qO7Yvs7bIJN20lwVAV0GcHH3hWQ== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 55582 example.com. PCHme1QLoULxqjhg5tMlpR0qJlBfstEUVq18TtNoKQe9le1YhJ9caheXcTWoK+boLhXxg9u6Yyvq8FboQh0OjA== ;{id = 55582} + +ENTRY_END +RANGE_END + +; set date/time to Aug 24 07:46:40 (2009). +STEP 5 TIME_PASSES ELAPSE 1251100000 +STEP 6 ASSIGN t0 = ${time} +; get probe time and check it. 4800 is about 10% less than 5400. And more than +; the 3600 that a failure timeout would have. +STEP 7 ASSIGN probe = ${range 4800 ${timeout} 5400} + + +; the auto probing should have been done now. +STEP 8 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: 1251100000 ;;Mon Aug 24 07:46:40 2009 +;;last_success: 1251100000 ;;Mon Aug 24 07:46:40 2009 +;;next_probe_time: ${$t0 + $probe} ;;${ctime $t0 + $probe} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1251100000 ;;Mon Aug 24 07:46:40 2009 +FILE_END + + +STEP 10 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 20 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. pYGxVLsWUvOp1wSf0iwPap+JnECfC5GAm1lRqy3YEqecNGld7U7x/5Imo3CerbdZrVptUQs2oH0lcjwYJXMnsw== ;{id = 30899} +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 5 2 3600 20090924111500 20090821111500 30899 example.com. J5wxRq0jgwQL6yy530kvo9cHqNAUHV8IF4dvaYZL0bNraO2Oe6dVXqlJl4+cxNHI2TMsstwFPr2Zz8tv6Az2mQ== ;{id = 30899} +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. JsXbS18oyc0zkVaOWGSFdIQuOsZKflT0GraT9afDPoWLCgH4ApF7jNgfJV7Pqy1sTBRajME5IUAhpANwGBuW4A== ;{id = 30899} +ENTRY_END + +; The autotrust anchor was probed due to the query. + +STEP 30 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: 1251100000 ;;Mon Aug 24 07:46:40 2009 +;;last_success: 1251100000 ;;Mon Aug 24 07:46:40 2009 +;;next_probe_time: ${$t0 + $probe} ;;${ctime $t0 + $probe} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1251100000 ;;Mon Aug 24 07:46:40 2009 +FILE_END + +; wait and see if autotrust probes (the unchanged) domain again. +STEP 40 TIME_PASSES EVAL ${$probe} + +STEP 50 TRAFFIC + +STEP 65 ASSIGN probe2 = ${range 4800 ${timeout} 5400} + +STEP 70 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${time} ;;${ctime ${time}} +;;last_success: ${time} ;;${ctime ${time}} +;;next_probe_time: ${$t0 + $probe + $probe2} ;;${ctime $t0 + $probe + $probe2} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1251100000 ;;Mon Aug 24 07:46:40 2009 +FILE_END + +SCENARIO_END diff --git a/testdata/autotrust_init_ds.rpl b/testdata/autotrust_init_ds.rpl new file mode 100644 index 00000000000..b6c620c730f --- /dev/null +++ b/testdata/autotrust_init_ds.rpl @@ -0,0 +1,180 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + log-time-ascii: yes +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +; initial content (say from dig example.com DS > example.com.key) +AUTOTRUST_FILE example.com +example.com. 10800 IN DS 55582 5 1 66e829ebd8145e6f030b840ae63b77273c9575e1 ; xiniv-mopov-rakoc-galuk-zibeb-ricob-penuf-rutad-lyzan-hetuv-caxox +AUTOTRUST_END +CONFIG_END + +SCENARIO_BEGIN Test autotrust with initial trust anchor from DS + +; K-ROOT +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR AA +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS k.root-servers.net. +SECTION ADDITIONAL +k.root-servers.net IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. pYGxVLsWUvOp1wSf0iwPap+JnECfC5GAm1lRqy3YEqecNGld7U7x/5Imo3CerbdZrVptUQs2oH0lcjwYJXMnsw== ;{id = 30899} +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 5 2 3600 20090924111500 20090821111500 30899 example.com. J5wxRq0jgwQL6yy530kvo9cHqNAUHV8IF4dvaYZL0bNraO2Oe6dVXqlJl4+cxNHI2TMsstwFPr2Zz8tv6Az2mQ== ;{id = 30899} +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. JsXbS18oyc0zkVaOWGSFdIQuOsZKflT0GraT9afDPoWLCgH4ApF7jNgfJV7Pqy1sTBRajME5IUAhpANwGBuW4A== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (ksk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 30899 example.com. b/HK231jIQLX8IhlZfup3r0yhpXaasbPE6LzxoEVVvWaTZWcLmeV8jDIcn0qO7Yvs7bIJN20lwVAV0GcHH3hWQ== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 55582 example.com. PCHme1QLoULxqjhg5tMlpR0qJlBfstEUVq18TtNoKQe9le1YhJ9caheXcTWoK+boLhXxg9u6Yyvq8FboQh0OjA== ;{id = 55582} + +ENTRY_END +RANGE_END + +; set date/time to Aug 24 07:46:40 (2009). +STEP 5 TIME_PASSES ELAPSE 1251100000 +STEP 6 ASSIGN t0 = ${time} +; get probe time and check it. 4800 is about 10% less than 5400. And more than +; the 3600 that a failure timeout would have. +STEP 7 ASSIGN probe = ${range 4800 ${timeout} 5400} + + +; the auto probing should have been done now. +STEP 8 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: 1251100000 ;;Mon Aug 24 07:46:40 2009 +;;last_success: 1251100000 ;;Mon Aug 24 07:46:40 2009 +;;next_probe_time: ${$t0 + $probe} ;;${ctime $t0 + $probe} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1251100000 ;;Mon Aug 24 07:46:40 2009 +FILE_END + + +STEP 10 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 20 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. pYGxVLsWUvOp1wSf0iwPap+JnECfC5GAm1lRqy3YEqecNGld7U7x/5Imo3CerbdZrVptUQs2oH0lcjwYJXMnsw== ;{id = 30899} +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 5 2 3600 20090924111500 20090821111500 30899 example.com. J5wxRq0jgwQL6yy530kvo9cHqNAUHV8IF4dvaYZL0bNraO2Oe6dVXqlJl4+cxNHI2TMsstwFPr2Zz8tv6Az2mQ== ;{id = 30899} +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. JsXbS18oyc0zkVaOWGSFdIQuOsZKflT0GraT9afDPoWLCgH4ApF7jNgfJV7Pqy1sTBRajME5IUAhpANwGBuW4A== ;{id = 30899} +ENTRY_END + +; The autotrust anchor was probed due to the query. + +STEP 30 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: 1251100000 ;;Mon Aug 24 07:46:40 2009 +;;last_success: 1251100000 ;;Mon Aug 24 07:46:40 2009 +;;next_probe_time: ${$t0 + $probe} ;;${ctime $t0 + $probe} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1251100000 ;;Mon Aug 24 07:46:40 2009 +FILE_END + +; wait and see if autotrust probes (the unchanged) domain again. +STEP 40 TIME_PASSES EVAL ${$probe} + +STEP 50 TRAFFIC + +STEP 65 ASSIGN probe2 = ${range 4800 ${timeout} 5400} + +STEP 70 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${time} ;;${ctime ${time}} +;;last_success: ${time} ;;${ctime ${time}} +;;next_probe_time: ${$t0 + $probe + $probe2} ;;${ctime $t0 + $probe + $probe2} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1251100000 ;;Mon Aug 24 07:46:40 2009 +FILE_END + +SCENARIO_END diff --git a/testdata/autotrust_init_fail.rpl b/testdata/autotrust_init_fail.rpl new file mode 100644 index 00000000000..f62e28539bf --- /dev/null +++ b/testdata/autotrust_init_fail.rpl @@ -0,0 +1,179 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + log-time-ascii: yes +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +; initial content (say from dig example.com DNSKEY > example.com.key) +AUTOTRUST_FILE example.com +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +AUTOTRUST_END +CONFIG_END + +SCENARIO_BEGIN Test autotrust with failed initial trust anchor + +; K-ROOT +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR AA +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS k.root-servers.net. +SECTION ADDITIONAL +k.root-servers.net IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +ns.example.com. IN NSEC nugget.example.com. A NSEC RRSIG +ns.example.com. 3600 IN RRSIG NSEC 5 3 3600 20090924111500 20090821111500 30899 example.com. WRUQ5d5aBO5AXbvnfCd0AWfKGvQIuAjT2qydGkUIaLZaiP4nj+JdquEy1nGvBwYQ9gWyP7b6C6UGrUnVcNBpcw== ;{id = 30899} +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 5 2 3600 20090924111500 20090821111500 30899 example.com. J5wxRq0jgwQL6yy530kvo9cHqNAUHV8IF4dvaYZL0bNraO2Oe6dVXqlJl4+cxNHI2TMsstwFPr2Zz8tv6Az2mQ== ;{id = 30899} +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. 3600 IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. JsXbS18oyc0zkVaOWGSFdIQuOsZKflT0GraT9afDPoWLCgH4ApF7jNgfJV7Pqy1sTBRajME5IUAhpANwGBuW4A== ;{id = 30899} +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 5 2 3600 20090924111500 20090821111500 30899 example.com. J5wxRq0jgwQL6yy530kvo9cHqNAUHV8IF4dvaYZL0bNraO2Oe6dVXqlJl4+cxNHI2TMsstwFPr2Zz8tv6Az2mQ== ;{id = 30899} +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. pYGxVLsWUvOp1wSf0iwPap+JnECfC5GAm1lRqy3YEqecNGld7U7x/5Imo3CerbdZrVptUQs2oH0lcjwYJXMnsw== ;{id = 30899} +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 5 2 3600 20090924111500 20090821111500 30899 example.com. J5wxRq0jgwQL6yy530kvo9cHqNAUHV8IF4dvaYZL0bNraO2Oe6dVXqlJl4+cxNHI2TMsstwFPr2Zz8tv6Az2mQ== ;{id = 30899} +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. JsXbS18oyc0zkVaOWGSFdIQuOsZKflT0GraT9afDPoWLCgH4ApF7jNgfJV7Pqy1sTBRajME5IUAhpANwGBuW4A== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA SERVFAIL +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (ksk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 30899 example.com. b/HK231jIQLX8IhlZfup3r0yhpXaasbPE6LzxoEVVvWaTZWcLmeV8jDIcn0qO7Yvs7bIJN20lwVAV0GcHH3hWQ== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 55582 example.com. PCHme1QLoULxqjhg5tMlpR0qJlBfstEUVq18TtNoKQe9le1YhJ9caheXcTWoK+boLhXxg9u6Yyvq8FboQh0OjA== ;{id = 55582} + +ENTRY_END +RANGE_END + +; set date/time to Aug 24 07:46:40 (2009). +STEP 5 TIME_PASSES ELAPSE 1251100000 +STEP 6 ASSIGN t0 = ${time} +STEP 7 ASSIGN probe = ${range 3200 ${timeout} 3600} + +; the auto probing should have been done now. +STEP 8 CHECK_AUTOTRUST example.com +FILE_BEGIN +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +FILE_END + + +STEP 10 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 20 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +ENTRY_END + +; The autotrust anchor was probed due to the query. + +STEP 30 CHECK_AUTOTRUST example.com +FILE_BEGIN +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +FILE_END + +; wait and see if autotrust probes (the unchanged) domain again. +STEP 40 TIME_PASSES EVAL ${$probe} + +STEP 50 TRAFFIC + +STEP 65 ASSIGN probe2 = ${range 3200 ${timeout} 3600} + +STEP 70 CHECK_AUTOTRUST example.com +FILE_BEGIN +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +FILE_END + +SCENARIO_END diff --git a/testdata/autotrust_init_failsig.rpl b/testdata/autotrust_init_failsig.rpl new file mode 100644 index 00000000000..ad46bae8ca6 --- /dev/null +++ b/testdata/autotrust_init_failsig.rpl @@ -0,0 +1,166 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + log-time-ascii: yes +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +; initial content (say from dig example.com DNSKEY > example.com.key) +AUTOTRUST_FILE example.com +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +AUTOTRUST_END +CONFIG_END + +SCENARIO_BEGIN Test autotrust with failed signature initial trust anchor + +; K-ROOT +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR AA +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS k.root-servers.net. +SECTION ADDITIONAL +k.root-servers.net IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +ns.example.com. IN NSEC nugget.example.com. A NSEC RRSIG +ns.example.com. 3600 IN RRSIG NSEC 5 3 3600 20090924111500 20090821111500 30899 example.com. WRUQ5d5aBO5AXbvnfCd0AWfKGvQIuAjT2qydGkUIaLZaiP4nj+JdquEy1nGvBwYQ9gWyP7b6C6UGrUnVcNBpcw== ;{id = 30899} +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 5 2 3600 20090924111500 20090821111500 30899 example.com. J5wxRq0jgwQL6yy530kvo9cHqNAUHV8IF4dvaYZL0bNraO2Oe6dVXqlJl4+cxNHI2TMsstwFPr2Zz8tv6Az2mQ== ;{id = 30899} +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. pYGxVLsWUvOp1wSf0iwPap+JnECfC5GAm1lRqy3YEqecNGld7U7x/5Imo3CerbdZrVptUQs2oH0lcjwYJXMnsw== ;{id = 30899} +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 5 2 3600 20090924111500 20090821111500 30899 example.com. J5wxRq0jgwQL6yy530kvo9cHqNAUHV8IF4dvaYZL0bNraO2Oe6dVXqlJl4+cxNHI2TMsstwFPr2Zz8tv6Az2mQ== ;{id = 30899} +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. JsXbS18oyc0zkVaOWGSFdIQuOsZKflT0GraT9afDPoWLCgH4ApF7jNgfJV7Pqy1sTBRajME5IUAhpANwGBuW4A== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (ksk), size = 512b} +; signatures +; changed the date in signatures from 20090924111500 20090821111500 +; to make them fail. +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090101010000 20090101010000 30899 example.com. b/HK231jIQLX8IhlZfup3r0yhpXaasbPE6LzxoEVVvWaTZWcLmeV8jDIcn0qO7Yvs7bIJN20lwVAV0GcHH3hWQ== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090101010000 20090101010000 55582 example.com. PCHme1QLoULxqjhg5tMlpR0qJlBfstEUVq18TtNoKQe9le1YhJ9caheXcTWoK+boLhXxg9u6Yyvq8FboQh0OjA== ;{id = 55582} + +ENTRY_END +RANGE_END + +; set date/time to Aug 24 07:46:40 (2009). +STEP 5 TIME_PASSES ELAPSE 1251100000 +STEP 6 ASSIGN t0 = ${time} +STEP 7 ASSIGN probe = ${range 3200 ${timeout} 3600} + +; the auto probing should have been done now. +STEP 8 CHECK_AUTOTRUST example.com +FILE_BEGIN +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +FILE_END + + +STEP 10 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 20 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +ENTRY_END + +; The autotrust anchor was probed due to the query. + +STEP 30 CHECK_AUTOTRUST example.com +FILE_BEGIN +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +FILE_END + +; wait and see if autotrust probes (the unchanged) domain again. +STEP 40 TIME_PASSES EVAL ${$probe} + +STEP 50 TRAFFIC + +STEP 65 ASSIGN probe2 = ${range 3200 ${timeout} 3600} + +STEP 70 CHECK_AUTOTRUST example.com +FILE_BEGIN +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +FILE_END + +SCENARIO_END diff --git a/testdata/autotrust_init_legacy.rpl b/testdata/autotrust_init_legacy.rpl new file mode 100644 index 00000000000..f188d0aed78 --- /dev/null +++ b/testdata/autotrust_init_legacy.rpl @@ -0,0 +1,84 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + log-time-ascii: yes +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +AUTOTRUST_FILE example.com +bg. 3600 IN DNSKEY 257 3 5 AwEAAdSkAKz985k77l1wsGJJb0ITOjJnYNW7viMGMu6gxn+k94g+JBnVK3ic6vgtpgApKZXLPF/1IYtBxc6Xd+EtrJ9QMhCOhDK5enHYwmWoo/P4zSu1RIDDsi2xge7HQt3rzGiZB6L3CWm1gmLIYoYUKmpq2QttVtTcziEmP+MbO/WVvJsQYDMFb/eszILyPRB76kSmSz56k+lHl6BWwv4LUchKWNf8s0pJsI357FVqdXaqjES6PqbNeymPW6rvMRSRFFp7KGLrizPJjsMfBIvyXkya5Gx4Y81wPqoRbW74efgD5bXsPCwitI/WayJ5h99VL8VtH4Ed0/b7F/H0CqFUohAipZkwLyimagxcWPem0WvGRXy/o/XHr/n1aG9D4SVUrGFQZsUk+PztJdYhLw2zNTgmIW+/RGUzowyhkmqD4CC+cn7BgXJTAig3REQ6GSfmEbQk8mDwhmIKw/GOLNiUL9EIGmZintg/zdzU4fb8Wn+4oBtOBFmzrw1uWEgDtsmLpVZcJPnvrIOE+lVnist1b4mTz7OSFApcOquwpTaMxsaSu9cufbN0jpBzslhSwaUyWXNruxAypuIlOXWt6yPAJ+u6pZ7db7APj5XY5Pff16/zWTfC2xI5OpFsn2vuEsi816lknDwfi6vYihx10VBwlcfUus0cuZ+SxUGj9fHq3+TX ;{id = 64693 (ksk), size = 4096b} ;;state=2 ;;count=0 ;;lastchange=1253688984 ;;Wed Sep 23 06:56:24 2009 +AUTOTRUST_END +CONFIG_END + +SCENARIO_BEGIN Test autotrust in unbound with legacy autotrust file + +; K-ROOT +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR AA +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS k.root-servers.net. +SECTION ADDITIONAL +k.root-servers.net IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +bg. IN NS +SECTION AUTHORITY +bg. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR AA +SECTION QUESTION +bg. IN DNSKEY +SECTION ANSWER +bg. 3600 IN DNSKEY 257 3 5 AwEAAdSkAKz985k77l1wsGJJb0ITOjJnYNW7viMGMu6gxn+k94g+JBnV K3ic6vgtpgApKZXLPF/1IYtBxc6Xd+EtrJ9QMhCOhDK5enHYwmWoo/P4 zSu1RIDDsi2xge7HQt3rzGiZB6L3CWm1gmLIYoYUKmpq2QttVtTcziEm P+MbO/WVvJsQYDMFb/eszILyPRB76kSmSz56k+lHl6BWwv4LUchKWNf8 s0pJsI357FVqdXaqjES6PqbNeymPW6rvMRSRFFp7KGLrizPJjsMfBIvy Xkya5Gx4Y81wPqoRbW74efgD5bXsPCwitI/WayJ5h99VL8VtH4Ed0/b7 F/H0CqFUohAipZkwLyimagxcWPem0WvGRXy/o/XHr/n1aG9D4SVUrGFQ ZsUk+PztJdYhLw2zNTgmIW+/RGUzowyhkmqD4CC+cn7BgXJTAig3REQ6 GSfmEbQk8mDwhmIKw/GOLNiUL9EIGmZintg/zdzU4fb8Wn+4oBtOBFmz rw1uWEgDtsmLpVZcJPnvrIOE+lVnist1b4mTz7OSFApcOquwpTaMxsaS u9cufbN0jpBzslhSwaUyWXNruxAypuIlOXWt6yPAJ+u6pZ7db7APj5XY 5Pff16/zWTfC2xI5OpFsn2vuEsi816lknDwfi6vYihx10VBwlcfUus0c uZ+SxUGj9fHq3+TX +bg. 3600 IN DNSKEY 256 3 5 AwEAAcgZKgxv/GlzYF/7ExO7fd4M23oC4z5vZa9A5kjiHDhK3fWbX7Zb 6i3Do668AVo2OVPJkhLHgueRkvON6G1AuKnNPr/aqYkswHp5RK4+bDz4 MYIgNxTHxVnmR0xY3K63xDinP1MP4bXfo8qoJDgYM25zQg4yZ5etrH+k l/fPK0Tr +bg. 3600 IN DNSKEY 256 3 5 AwEAAduUF9stPDvXkFznyZ/lL1CPJWHhmHqFv7zZHKtpd0YdoRSxJlT/ KtlEX5TFXOwiaodc5VPTPsUmkoIJ8XW+v9ocjzIPbKErSvQ1HsRNxjFR mUgnRGUeD7rlqGqwheEMlXD57IYAm5Vfs4RPp+zyp1PYVwDtamGPmWny 1xdOwiXF +bg. 3600 IN DNSKEY 257 3 5 AwEAAblV90SQjp4rI9ZLQs3pwcvkmlEt0OogfuI5cm4l+b3fHGA3YtVU Tz8j6SzpMQR/psx5KzFzqIJc8YRdLJSFhiBaLxDYPltcjFSie71Ln2U0 +PPn5NHqUzCYTysLtRG0sl8FHmFGEY4OmkevpDZCX9sscDdt0MfiVwoN 23Ni3nHuSrGewgr0RI4nBrcrBWII7oAfhyZ9XKWmlZpRM8aNHA6hijix ZsSzTNYAfr9r+s/lpiDG2ybiju1H6sKhL/jY02UdMTFiLFdRZ6yuOzxw FXWQE/d7cSe5dSCYMU5EmD2Qy0nbGG0YSD9e0iehw01Fr70HfIV9uNXM zqHrrTyajMtlft/z9aUug5qIVxFSczNSRCyJedcJU+9OZUMj90yXQLeG 2soa6QOfAUyYZLs9OgOIKoE0c7hQRIicPM5bK0ycUM3NTcIYUzDV8zZZ Fo0xaM1QEIMdXz4kCfFS6V4lUleufTCDTI0CkTq9g14ia464HFXb4WKD 6eHl0hvnXAviPAqrma0K1iX9efjxiDumyAIJlm/plBL39CMuX/ENyER8 XXqv9aXAAcdlN2EYsbejGJ262SjvGIMzEVoUKd9UqrnSe44w/2+lzL6a WYqFz6njejH6rbzcof2MoEt1QC47G80gZzFk/tn1mMIKKMbQyvMy7+6K HaTKSHnJCXr27klR +bg. 3600 IN RRSIG DNSKEY 5 1 3600 20091023110015 20090923110015 12576 bg. n73VW50NVGhJYvXUjuobebUFYS3NiVkYoZ9oW+lKtbp4AUQHf7HfIxKk aOesl1EeXMI+IcAIyMkmJQDVPBEpf5WhWarGVthAxOXradSSYKI0Nvuf 4cXoig8tM1n2qScNWlEwQTdNxZl5bQND61ZSPWWTpA3bt4iu8lWqXxFB O2g= +bg. 3600 IN RRSIG DNSKEY 5 1 3600 20091023110015 20090923110015 46846 bg. O4eZhJMy+A8aJL63rK04fFeDrn/CLLkuXW+NePdcuyDEaHwX0UwvuNxy V8aGQNtp+YJCfVzc4Qw9lrTCg+qS4o8qDtj4/p27HHtQ4+owLM2gi1pS Ek9/Ct8FabsuBAR+f4/SCVtf75+QT7kfNzJqN1/o6GU8W9/CILGzD52f kHxqpW8k0pPUrZ4r5UkpUiZTFoLe8lkSN30Dlc84dFOH8myuoDbiwH5B GjdrR8xwe5e2+wnsAkzcwN0+7ND1mIGCjebrdnfyCV3eMDzrDu2ZH8Bt swPShC+8VbnGcEmNfGycaIvwFJO89zQ0YBPbfiX07n+2mDIcfvHpq0cD iL0As6rbvEq9tmePkHrggN1DuuxZWInhfmUCOZK62F33rxefJv/VmM5T C45fvAh5RzetMhuRHq6Upxcma1hqlY7hz3PfQTHl0cPNI3ZnJOrfg5pe 04Tlu7KfVdSuhsS71+I8dotokCMdocoft9kPyQxfSln4/eoSPTYa/oaL pUJJfjdTS2XkgVL5zm8aC33273hzz82eLuHNc78x0Gac+QLknNJMwylx OYXn27o53TufSb8fkh4M3IiU53qY6IhCTQqEFwqiANodvQaOV6nrs4+D jRKbdviwxM7Tt2SQ3Z3d64kuD6T23C9FdovSGpRG5SHALcTdd8O9pUyk /mPoNBWKOuw= +bg. 3600 IN RRSIG DNSKEY 5 1 3600 20091023110015 20090923110015 64693 bg. DVh3tlQ6LnQ4HC5G9DFPszU8OmKDKBPIbp4DIKt/TbKWRpbMLfwzBUwR EHr6qkrdwKyUgo59JoDeeb0cXCFooxtIhZMLv2ntlPTPTp+4jEoi/t9P KhqTS2r3Ptbj3wVypdRwi45wChro0XW+ZNmbh/BRSo8eKJVZcor9rj5b soPwfPVvKe+iQ18PWxTXE4FLDv3wQ1/5EpqaAbOjvvCnuOCMUYotjvZt GwDcAx98mPLY42zQfc+EoN9qnlEfsu9zZOVgQQDgvb+yTbyLaP9yRp13 PIf3jQ4IPMAtL9ONGokd1Jl6v0hXIVTlMoF0EGgtcDiE2KZ64hhtY+t9 Z8sraETJxxdTeX/E81+9I3cBL1VVAT9Fe9nzfXd1sP0FKjaVcIzJnsZ4 lBVZE0iDA2ZaMVeaH8z/38eMHIhn+J2ZiMwz/5b/ueHFfiAjFedbSQrR ALOSggmFd2v6uh8X4osM9Gxg8Q3fDhqGjSkEQIc/VdEMQbh2yU0o+X8q 5r13WkEmS0pKJhvPXocpRWdqfKb2QwnswU6pxbuBuwUd1i087YkTSl/R QREOZNgtfw2qpwv6Lm3q5DT5igF0G78OS3L58aSm0nHxQx9WsCE19/pe 66o1hH3Umx1Q/B7Zt4ZD0R9YE1w20qUcb9HmZumt0LJWtIgTrOuW+6SE WgGvpjXrHS8= +ENTRY_END +RANGE_END + +; set date/time to wed sep 23. +STEP 5 TIME_PASSES EVAL ${1253688984 + 7200 + 10800} +STEP 6 TRAFFIC ; do the probe +STEP 7 ASSIGN t0 = ${time} +STEP 8 ASSIGN probe0 = ${range 3200 ${timeout} 3600} + +; the auto probing should have been done now. +STEP 11 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: bg. 1 +;;last_queried: ${$t0} ;;${ctime $t0} +;;last_success: ${$t0} ;;${ctime $t0} +;;next_probe_time: ${$t0+$probe0} ;;${ctime $t0+$probe0} +;;query_failed: 0 +;;query_interval: 3600 +;;retry_time: 3600 +bg. 3600 IN DNSKEY 257 3 5 AwEAAblV90SQjp4rI9ZLQs3pwcvkmlEt0OogfuI5cm4l+b3fHGA3YtVUTz8j6SzpMQR/psx5KzFzqIJc8YRdLJSFhiBaLxDYPltcjFSie71Ln2U0+PPn5NHqUzCYTysLtRG0sl8FHmFGEY4OmkevpDZCX9sscDdt0MfiVwoN23Ni3nHuSrGewgr0RI4nBrcrBWII7oAfhyZ9XKWmlZpRM8aNHA6hijixZsSzTNYAfr9r+s/lpiDG2ybiju1H6sKhL/jY02UdMTFiLFdRZ6yuOzxwFXWQE/d7cSe5dSCYMU5EmD2Qy0nbGG0YSD9e0iehw01Fr70HfIV9uNXMzqHrrTyajMtlft/z9aUug5qIVxFSczNSRCyJedcJU+9OZUMj90yXQLeG2soa6QOfAUyYZLs9OgOIKoE0c7hQRIicPM5bK0ycUM3NTcIYUzDV8zZZFo0xaM1QEIMdXz4kCfFS6V4lUleufTCDTI0CkTq9g14ia464HFXb4WKD6eHl0hvnXAviPAqrma0K1iX9efjxiDumyAIJlm/plBL39CMuX/ENyER8XXqv9aXAAcdlN2EYsbejGJ262SjvGIMzEVoUKd9UqrnSe44w/2+lzL6aWYqFz6njejH6rbzcof2MoEt1QC47G80gZzFk/tn1mMIKKMbQyvMy7+6KHaTKSHnJCXr27klR ;{id = 46846 (ksk), size = 4096b} ;;state=1 [ ADDPEND ] ;;count=1 ;;lastchange=${$t0} ;;${ctime $t0} +bg. 3600 IN DNSKEY 257 3 5 AwEAAdSkAKz985k77l1wsGJJb0ITOjJnYNW7viMGMu6gxn+k94g+JBnVK3ic6vgtpgApKZXLPF/1IYtBxc6Xd+EtrJ9QMhCOhDK5enHYwmWoo/P4zSu1RIDDsi2xge7HQt3rzGiZB6L3CWm1gmLIYoYUKmpq2QttVtTcziEmP+MbO/WVvJsQYDMFb/eszILyPRB76kSmSz56k+lHl6BWwv4LUchKWNf8s0pJsI357FVqdXaqjES6PqbNeymPW6rvMRSRFFp7KGLrizPJjsMfBIvyXkya5Gx4Y81wPqoRbW74efgD5bXsPCwitI/WayJ5h99VL8VtH4Ed0/b7F/H0CqFUohAipZkwLyimagxcWPem0WvGRXy/o/XHr/n1aG9D4SVUrGFQZsUk+PztJdYhLw2zNTgmIW+/RGUzowyhkmqD4CC+cn7BgXJTAig3REQ6GSfmEbQk8mDwhmIKw/GOLNiUL9EIGmZintg/zdzU4fb8Wn+4oBtOBFmzrw1uWEgDtsmLpVZcJPnvrIOE+lVnist1b4mTz7OSFApcOquwpTaMxsaSu9cufbN0jpBzslhSwaUyWXNruxAypuIlOXWt6yPAJ+u6pZ7db7APj5XY5Pff16/zWTfC2xI5OpFsn2vuEsi816lknDwfi6vYihx10VBwlcfUus0cuZ+SxUGj9fHq3+TX ;{id = 64693 (ksk), size = 4096b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1253688984 ;;Wed Sep 23 06:56:24 2009 +FILE_END + +SCENARIO_END diff --git a/testdata/autotrust_init_sigs.rpl b/testdata/autotrust_init_sigs.rpl new file mode 100644 index 00000000000..ac8bde0e1da --- /dev/null +++ b/testdata/autotrust_init_sigs.rpl @@ -0,0 +1,183 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + log-time-ascii: yes +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +; initial content (say from dig example.com DNSKEY > example.com.key) +AUTOTRUST_FILE example.com +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20070926134150 20070829134150 55582 example.com. sT5Se0rwBm0oAOcrX37oidl3zxK9QwvgAyOH+08Jq3V8KS4iPehBjNqXi9OITLgos4dHU/up4Z1BwgwTNYJIgg== ;{id = 55582} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20070926134150 20070829134150 30899 example.com. DnrdGYsSAjAX1z93FQvPL8eX66uS9ip7A21gPTkvGBDwDoNB8JTNdRlEyWeXlipatbcQoZeG8mo87Wgp9eT/PA== ;{id = 30899} +AUTOTRUST_END +CONFIG_END + +SCENARIO_BEGIN Test autotrust with initial trust anchor with RRSIGs + +; K-ROOT +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR AA +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS k.root-servers.net. +SECTION ADDITIONAL +k.root-servers.net IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. pYGxVLsWUvOp1wSf0iwPap+JnECfC5GAm1lRqy3YEqecNGld7U7x/5Imo3CerbdZrVptUQs2oH0lcjwYJXMnsw== ;{id = 30899} +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 5 2 3600 20090924111500 20090821111500 30899 example.com. J5wxRq0jgwQL6yy530kvo9cHqNAUHV8IF4dvaYZL0bNraO2Oe6dVXqlJl4+cxNHI2TMsstwFPr2Zz8tv6Az2mQ== ;{id = 30899} +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. JsXbS18oyc0zkVaOWGSFdIQuOsZKflT0GraT9afDPoWLCgH4ApF7jNgfJV7Pqy1sTBRajME5IUAhpANwGBuW4A== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (ksk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 30899 example.com. b/HK231jIQLX8IhlZfup3r0yhpXaasbPE6LzxoEVVvWaTZWcLmeV8jDIcn0qO7Yvs7bIJN20lwVAV0GcHH3hWQ== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 55582 example.com. PCHme1QLoULxqjhg5tMlpR0qJlBfstEUVq18TtNoKQe9le1YhJ9caheXcTWoK+boLhXxg9u6Yyvq8FboQh0OjA== ;{id = 55582} + +ENTRY_END +RANGE_END + +; set date/time to Aug 24 07:46:40 (2009). +STEP 5 TIME_PASSES ELAPSE 1251100000 +STEP 6 ASSIGN t0 = ${time} +; get probe time and check it. 4800 is about 10% less than 5400. And more than +; the 3600 that a failure timeout would have. +STEP 7 ASSIGN probe = ${range 4800 ${timeout} 5400} + + +; the auto probing should have been done now. +STEP 8 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: 1251100000 ;;Mon Aug 24 07:46:40 2009 +;;last_success: 1251100000 ;;Mon Aug 24 07:46:40 2009 +;;next_probe_time: ${$t0 + $probe} ;;${ctime $t0 + $probe} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1251100000 ;;Mon Aug 24 07:46:40 2009 +FILE_END + + +STEP 10 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 20 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. pYGxVLsWUvOp1wSf0iwPap+JnECfC5GAm1lRqy3YEqecNGld7U7x/5Imo3CerbdZrVptUQs2oH0lcjwYJXMnsw== ;{id = 30899} +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 5 2 3600 20090924111500 20090821111500 30899 example.com. J5wxRq0jgwQL6yy530kvo9cHqNAUHV8IF4dvaYZL0bNraO2Oe6dVXqlJl4+cxNHI2TMsstwFPr2Zz8tv6Az2mQ== ;{id = 30899} +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. JsXbS18oyc0zkVaOWGSFdIQuOsZKflT0GraT9afDPoWLCgH4ApF7jNgfJV7Pqy1sTBRajME5IUAhpANwGBuW4A== ;{id = 30899} +ENTRY_END + +; The autotrust anchor was probed due to the query. + +STEP 30 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: 1251100000 ;;Mon Aug 24 07:46:40 2009 +;;last_success: 1251100000 ;;Mon Aug 24 07:46:40 2009 +;;next_probe_time: ${$t0 + $probe} ;;${ctime $t0 + $probe} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1251100000 ;;Mon Aug 24 07:46:40 2009 +FILE_END + +; wait and see if autotrust probes (the unchanged) domain again. +STEP 40 TIME_PASSES EVAL ${$probe} + +STEP 50 TRAFFIC + +STEP 65 ASSIGN probe2 = ${range 4800 ${timeout} 5400} + +STEP 70 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${time} ;;${ctime ${time}} +;;last_success: ${time} ;;${ctime ${time}} +;;next_probe_time: ${$t0 + $probe + $probe2} ;;${ctime $t0 + $probe + $probe2} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1251100000 ;;Mon Aug 24 07:46:40 2009 +FILE_END + +SCENARIO_END diff --git a/testdata/autotrust_init_zsk.rpl b/testdata/autotrust_init_zsk.rpl new file mode 100644 index 00000000000..16b0a0588ec --- /dev/null +++ b/testdata/autotrust_init_zsk.rpl @@ -0,0 +1,180 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + log-time-ascii: yes +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +; initial content (say from dig example.com DNSKEY > example.com.key) +AUTOTRUST_FILE example.com +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +AUTOTRUST_END +CONFIG_END + +SCENARIO_BEGIN Test autotrust with initial trust anchor ZSK + +; K-ROOT +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR AA +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS k.root-servers.net. +SECTION ADDITIONAL +k.root-servers.net IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. pYGxVLsWUvOp1wSf0iwPap+JnECfC5GAm1lRqy3YEqecNGld7U7x/5Imo3CerbdZrVptUQs2oH0lcjwYJXMnsw== ;{id = 30899} +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 5 2 3600 20090924111500 20090821111500 30899 example.com. J5wxRq0jgwQL6yy530kvo9cHqNAUHV8IF4dvaYZL0bNraO2Oe6dVXqlJl4+cxNHI2TMsstwFPr2Zz8tv6Az2mQ== ;{id = 30899} +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. JsXbS18oyc0zkVaOWGSFdIQuOsZKflT0GraT9afDPoWLCgH4ApF7jNgfJV7Pqy1sTBRajME5IUAhpANwGBuW4A== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (ksk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 30899 example.com. b/HK231jIQLX8IhlZfup3r0yhpXaasbPE6LzxoEVVvWaTZWcLmeV8jDIcn0qO7Yvs7bIJN20lwVAV0GcHH3hWQ== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 55582 example.com. PCHme1QLoULxqjhg5tMlpR0qJlBfstEUVq18TtNoKQe9le1YhJ9caheXcTWoK+boLhXxg9u6Yyvq8FboQh0OjA== ;{id = 55582} + +ENTRY_END +RANGE_END + +; set date/time to Aug 24 07:46:40 (2009). +STEP 5 TIME_PASSES ELAPSE 1251100000 +STEP 6 ASSIGN t0 = ${time} +; get probe time and check it. 4800 is about 10% less than 5400. And more than +; the 3600 that a failure timeout would have. +STEP 7 ASSIGN probe = ${range 4800 ${timeout} 5400} + + +; the auto probing should have been done now. +STEP 8 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: 1251100000 ;;Mon Aug 24 07:46:40 2009 +;;last_success: 1251100000 ;;Mon Aug 24 07:46:40 2009 +;;next_probe_time: ${$t0 + $probe} ;;${ctime $t0 + $probe} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1251100000 ;;Mon Aug 24 07:46:40 2009 +FILE_END + + +STEP 10 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 20 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. pYGxVLsWUvOp1wSf0iwPap+JnECfC5GAm1lRqy3YEqecNGld7U7x/5Imo3CerbdZrVptUQs2oH0lcjwYJXMnsw== ;{id = 30899} +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 5 2 3600 20090924111500 20090821111500 30899 example.com. J5wxRq0jgwQL6yy530kvo9cHqNAUHV8IF4dvaYZL0bNraO2Oe6dVXqlJl4+cxNHI2TMsstwFPr2Zz8tv6Az2mQ== ;{id = 30899} +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. JsXbS18oyc0zkVaOWGSFdIQuOsZKflT0GraT9afDPoWLCgH4ApF7jNgfJV7Pqy1sTBRajME5IUAhpANwGBuW4A== ;{id = 30899} +ENTRY_END + +; The autotrust anchor was probed due to the query. + +STEP 30 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: 1251100000 ;;Mon Aug 24 07:46:40 2009 +;;last_success: 1251100000 ;;Mon Aug 24 07:46:40 2009 +;;next_probe_time: ${$t0 + $probe} ;;${ctime $t0 + $probe} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1251100000 ;;Mon Aug 24 07:46:40 2009 +FILE_END + +; wait and see if autotrust probes (the unchanged) domain again. +STEP 40 TIME_PASSES EVAL ${$probe} + +STEP 50 TRAFFIC + +STEP 65 ASSIGN probe2 = ${range 4800 ${timeout} 5400} + +STEP 70 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${time} ;;${ctime ${time}} +;;last_success: ${time} ;;${ctime ${time}} +;;next_probe_time: ${$t0 + $probe + $probe2} ;;${ctime $t0 + $probe + $probe2} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1251100000 ;;Mon Aug 24 07:46:40 2009 +FILE_END + +SCENARIO_END diff --git a/testdata/autotrust_missing.rpl b/testdata/autotrust_missing.rpl new file mode 100644 index 00000000000..aab99911c7e --- /dev/null +++ b/testdata/autotrust_missing.rpl @@ -0,0 +1,318 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + log-time-ascii: yes +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +; initial content (say from dig example.com DNSKEY > example.com.key) +AUTOTRUST_FILE example.com +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +AUTOTRUST_END +CONFIG_END + +SCENARIO_BEGIN Test autotrust with missing key + +; K-ROOT +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR AA +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS k.root-servers.net. +SECTION ADDITIONAL +k.root-servers.net IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 +RANGE_BEGIN 0 10 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. pYGxVLsWUvOp1wSf0iwPap+JnECfC5GAm1lRqy3YEqecNGld7U7x/5Imo3CerbdZrVptUQs2oH0lcjwYJXMnsw== ;{id = 30899} +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 5 2 3600 20090924111500 20090821111500 30899 example.com. J5wxRq0jgwQL6yy530kvo9cHqNAUHV8IF4dvaYZL0bNraO2Oe6dVXqlJl4+cxNHI2TMsstwFPr2Zz8tv6Az2mQ== ;{id = 30899} +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. JsXbS18oyc0zkVaOWGSFdIQuOsZKflT0GraT9afDPoWLCgH4ApF7jNgfJV7Pqy1sTBRajME5IUAhpANwGBuW4A== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 30899 example.com. b/HK231jIQLX8IhlZfup3r0yhpXaasbPE6LzxoEVVvWaTZWcLmeV8jDIcn0qO7Yvs7bIJN20lwVAV0GcHH3hWQ== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 55582 example.com. PCHme1QLoULxqjhg5tMlpR0qJlBfstEUVq18TtNoKQe9le1YhJ9caheXcTWoK+boLhXxg9u6Yyvq8FboQh0OjA== ;{id = 55582} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 and 60946 +RANGE_BEGIN 11 40 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 30899 example.com. rkaCUpTFPWVu4Om5oMTR+39Mct6ZMs56xrE0rbxMMOokfvIQheIxsAEc5BFJeA/2y5WTewl6diCD6yQXCybrDg== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 55582 example.com. CoMon+lWPAsUvgfpCTDPx8Zn8dQpky3lu2O6T+oJ2Mat9a/u1YwGhSQHGPn7ZNG/4vKM97tx84sSlUGz3geD1w== ;{id = 55582} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 60946 example.com. o+Cbs7DcYPYlSLd4hi3vkSVQpXGnKgKSi9MpHGfu1Uahv5190U2DUOxP1du/HOYbf+IHYL8zLbMZjVEG5wgnTg== ;{id = 60946} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 and 60946 (signatures updated) +RANGE_BEGIN 41 50 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 30899 example.com. rkaCUpTFPWVu4Om5oMTR+39Mct6ZMs56xrE0rbxMMOokfvIQheIxsAEc5BFJeA/2y5WTewl6diCD6yQXCybrDg== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 55582 example.com. v/HJbdpeVMpbhwYXrT1EDGpAFMvEgdKQII1cAbP6o8KHYNKDh8TIJ25/pXe3daEXfej6/Z5kpqJ79okPKUoi1Q== ;{id = 55582} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 60946 example.com. HgXol1hdvbomOM1CFRW8qsHd3D0qOnN72EeMHTcpxIBBiuNLKZn4n1M14Voxj3vo0eAMNuG/y7EjQkxKvSsaDA== ;{id = 60946} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 60946 , 55582 is missing +RANGE_BEGIN 51 60 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091224111500 20091118111500 30899 example.com. ddH76HLQaMMN8O8BWuI9LxFzFOH0iVpdOJg2anl6xvNAnZH0Xtdi/KedsNolEx0EOHFrGrU7dH8w7Ag6sMDUpA== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091224111500 20091118111500 60946 example.com. fRitjw2TEF+5i17ksiKZNBOGbYiqKKCUXywafBwfcOLiEKr8dapSPQLJst09FjEooRqc3Ii1YbBaL7pbdqfqOw== ;{id = 60946} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 60946 +RANGE_BEGIN 61 70 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20101224111500 20101118111500 30899 example.com. TfFGz1kDtkn3ixbKMJvQDZ0uGw/eW+inIiPqQVPQtO2WiocKrnYnzwv/AqwnFvEar70dF15/zffNIF+ipOS5/g== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20101224111500 20101118111500 60946 example.com. X0Ci//w0czN/J5RvypHGqp56n1tLdapi92ODAqjM7QpZXbSHaJ7wfPG1PZzvdxHUZUVyf8uy2stjg/XoLGHMWA== ;{id = 60946} +ENTRY_END +RANGE_END + +; set date/time to Aug 24 07:46:40 (2009). +STEP 5 TIME_PASSES ELAPSE 1251100000 +STEP 6 TRAFFIC ; the initial probe +STEP 7 ASSIGN t0 = ${time} +STEP 8 ASSIGN probe0 = ${range 4800 ${timeout} 5400} + +; the auto probing should have been done now. +STEP 10 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t0} ;;${ctime $t0} +;;last_success: ${$t0} ;;${ctime $t0} +;;next_probe_time: ${$t0 + $probe0} ;;${ctime $t0 + $probe0} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; key prepublished. First poll. 30 days later +STEP 11 TIME_PASSES EVAL ${30*24*3600} +STEP 12 TRAFFIC +STEP 13 ASSIGN t1 = ${time} +STEP 14 ASSIGN probe1 = ${range 4800 ${timeout} 5400} +STEP 15 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t1} ;;${ctime $t1} +;;last_success: ${$t1} ;;${ctime $t1} +;;next_probe_time: ${$t1 + $probe1} ;;${ctime $t1 + $probe1} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=1 ;;lastchange=${$t1} ;;${ctime $t1} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; Second poll. 10 days later +STEP 21 TIME_PASSES EVAL ${10*24*3600} +STEP 22 TRAFFIC +STEP 23 ASSIGN t2 = ${time} +STEP 24 ASSIGN probe2 = ${range 4800 ${timeout} 5400} +STEP 25 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t2} ;;${ctime $t2} +;;last_success: ${$t2} ;;${ctime $t2} +;;next_probe_time: ${$t2 + $probe2} ;;${ctime $t2 + $probe2} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=2 ;;lastchange=${$t1} ;;${ctime $t1} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; Third poll. 10 days later +STEP 31 TIME_PASSES EVAL ${10*24*3600} +STEP 32 TRAFFIC +STEP 33 ASSIGN t3 = ${time} +STEP 34 ASSIGN probe3 = ${range 4800 ${timeout} 5400} +STEP 35 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t3} ;;${ctime $t3} +;;last_success: ${$t3} ;;${ctime $t3} +;;next_probe_time: ${$t3 + $probe3} ;;${ctime $t3 + $probe3} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=3 ;;lastchange=${$t1} ;;${ctime $t1} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; 11 days later, hold down has lapsed. +STEP 41 TIME_PASSES EVAL ${11*24*3600} +STEP 42 TRAFFIC +STEP 43 ASSIGN t4 = ${time} +STEP 44 ASSIGN probe4 = ${range 4800 ${timeout} 5400} +STEP 45 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t4} ;;${ctime $t4} +;;last_success: ${$t4} ;;${ctime $t4} +;;next_probe_time: ${$t4 + $probe4} ;;${ctime $t4 + $probe4} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t4} ;;${ctime $t4} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; 30 days later, the old key is revoked +STEP 51 TIME_PASSES EVAL ${30*24*3600} +STEP 52 TRAFFIC +STEP 53 ASSIGN t5 = ${time} +STEP 54 ASSIGN probe5 = ${range 4800 ${timeout} 5400} +STEP 55 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t5} ;;${ctime $t5} +;;last_success: ${$t5} ;;${ctime $t5} +;;next_probe_time: ${$t5 + $probe5} ;;${ctime $t5 + $probe5} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t4} ;;${ctime $t4} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=3 [ MISSING ] ;;count=0 ;;lastchange=${$t5} ;;${ctime $t5} +FILE_END + +; 370 days later, the old key is removed from storage +STEP 61 TIME_PASSES EVAL ${370*24*3600} +STEP 62 TRAFFIC +STEP 63 ASSIGN t6 = ${time} +STEP 64 ASSIGN probe6 = ${range 4800 ${timeout} 5400} +STEP 65 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t6} ;;${ctime $t6} +;;last_success: ${$t6} ;;${ctime $t6} +;;next_probe_time: ${$t6 + $probe6} ;;${ctime $t6 + $probe6} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t4} ;;${ctime $t4} +FILE_END + + +SCENARIO_END diff --git a/testdata/autotrust_missing_all.rpl b/testdata/autotrust_missing_all.rpl new file mode 100644 index 00000000000..0c78aa6b109 --- /dev/null +++ b/testdata/autotrust_missing_all.rpl @@ -0,0 +1,316 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + log-time-ascii: yes +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +; initial content (say from dig example.com DNSKEY > example.com.key) +AUTOTRUST_FILE example.com +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +AUTOTRUST_END +CONFIG_END + +SCENARIO_BEGIN Test autotrust with all keys missing + +; K-ROOT +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR AA +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS k.root-servers.net. +SECTION ADDITIONAL +k.root-servers.net IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 +RANGE_BEGIN 0 10 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. pYGxVLsWUvOp1wSf0iwPap+JnECfC5GAm1lRqy3YEqecNGld7U7x/5Imo3CerbdZrVptUQs2oH0lcjwYJXMnsw== ;{id = 30899} +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 5 2 3600 20090924111500 20090821111500 30899 example.com. J5wxRq0jgwQL6yy530kvo9cHqNAUHV8IF4dvaYZL0bNraO2Oe6dVXqlJl4+cxNHI2TMsstwFPr2Zz8tv6Az2mQ== ;{id = 30899} +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. JsXbS18oyc0zkVaOWGSFdIQuOsZKflT0GraT9afDPoWLCgH4ApF7jNgfJV7Pqy1sTBRajME5IUAhpANwGBuW4A== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 30899 example.com. b/HK231jIQLX8IhlZfup3r0yhpXaasbPE6LzxoEVVvWaTZWcLmeV8jDIcn0qO7Yvs7bIJN20lwVAV0GcHH3hWQ== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 55582 example.com. PCHme1QLoULxqjhg5tMlpR0qJlBfstEUVq18TtNoKQe9le1YhJ9caheXcTWoK+boLhXxg9u6Yyvq8FboQh0OjA== ;{id = 55582} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 and 60946 +RANGE_BEGIN 11 40 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 30899 example.com. rkaCUpTFPWVu4Om5oMTR+39Mct6ZMs56xrE0rbxMMOokfvIQheIxsAEc5BFJeA/2y5WTewl6diCD6yQXCybrDg== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 55582 example.com. CoMon+lWPAsUvgfpCTDPx8Zn8dQpky3lu2O6T+oJ2Mat9a/u1YwGhSQHGPn7ZNG/4vKM97tx84sSlUGz3geD1w== ;{id = 55582} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 60946 example.com. o+Cbs7DcYPYlSLd4hi3vkSVQpXGnKgKSi9MpHGfu1Uahv5190U2DUOxP1du/HOYbf+IHYL8zLbMZjVEG5wgnTg== ;{id = 60946} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 and 60946 (signatures updated) +RANGE_BEGIN 41 50 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 30899 example.com. rkaCUpTFPWVu4Om5oMTR+39Mct6ZMs56xrE0rbxMMOokfvIQheIxsAEc5BFJeA/2y5WTewl6diCD6yQXCybrDg== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 55582 example.com. v/HJbdpeVMpbhwYXrT1EDGpAFMvEgdKQII1cAbP6o8KHYNKDh8TIJ25/pXe3daEXfej6/Z5kpqJ79okPKUoi1Q== ;{id = 55582} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 60946 example.com. HgXol1hdvbomOM1CFRW8qsHd3D0qOnN72EeMHTcpxIBBiuNLKZn4n1M14Voxj3vo0eAMNuG/y7EjQkxKvSsaDA== ;{id = 60946} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 60946 missing , 55582 is missing +RANGE_BEGIN 51 60 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091224111500 20091118111500 30899 example.com. wzXQvn/XBgdkUn0HFl/mzaxZ30k8R9126hCio+gH5MgaFhWIdp8ob0TWRDA5yzrQCKzkyUqqcx+6fUWVOZOtXg== ;{id = 30899} +; includes a signature from 60946. +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091224111500 20091118111500 60946 example.com. rn/rE/xoqKRbTz1tGUjTESB5e4UrFT5liigwrUi5a6nxn9juhAa+o1VbMXi1zXCAnZwHRE+tGZc8v44zjeioIw== ;{id = 60946} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 60946 +RANGE_BEGIN 61 70 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20101224111500 20101118111500 30899 example.com. ukRqyDSzKwQ6tI59ThkPDOcO+F6JFwfHMcRKq4N+ZM5pGc/aVZaFyF9M8dyF/tfwst1kVwF+r7eQuJuZuFm0Fg== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20101224111500 20101118111500 60946 example.com. G8wabxIoGwpFPycOuOfBk6+l2/E/t3DhKlzUGBZjMY7gE+tOLCZnibZrhLd+2j07hoISlJ88fosjOdpD8Sqsqw== ;{id = 60946} +ENTRY_END +RANGE_END + +; set date/time to Aug 24 07:46:40 (2009). +STEP 5 TIME_PASSES ELAPSE 1251100000 +STEP 6 TRAFFIC ; the initial probe +STEP 7 ASSIGN t0 = ${time} +STEP 8 ASSIGN probe0 = ${range 4800 ${timeout} 5400} + +; the auto probing should have been done now. +STEP 10 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t0} ;;${ctime $t0} +;;last_success: ${$t0} ;;${ctime $t0} +;;next_probe_time: ${$t0 + $probe0} ;;${ctime $t0 + $probe0} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; key prepublished. First poll. 30 days later +STEP 11 TIME_PASSES EVAL ${30*24*3600} +STEP 12 TRAFFIC +STEP 13 ASSIGN t1 = ${time} +STEP 14 ASSIGN probe1 = ${range 4800 ${timeout} 5400} +STEP 15 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t1} ;;${ctime $t1} +;;last_success: ${$t1} ;;${ctime $t1} +;;next_probe_time: ${$t1 + $probe1} ;;${ctime $t1 + $probe1} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=1 ;;lastchange=${$t1} ;;${ctime $t1} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; Second poll. 10 days later +STEP 21 TIME_PASSES EVAL ${10*24*3600} +STEP 22 TRAFFIC +STEP 23 ASSIGN t2 = ${time} +STEP 24 ASSIGN probe2 = ${range 4800 ${timeout} 5400} +STEP 25 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t2} ;;${ctime $t2} +;;last_success: ${$t2} ;;${ctime $t2} +;;next_probe_time: ${$t2 + $probe2} ;;${ctime $t2 + $probe2} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=2 ;;lastchange=${$t1} ;;${ctime $t1} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; Third poll. 10 days later +STEP 31 TIME_PASSES EVAL ${10*24*3600} +STEP 32 TRAFFIC +STEP 33 ASSIGN t3 = ${time} +STEP 34 ASSIGN probe3 = ${range 4800 ${timeout} 5400} +STEP 35 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t3} ;;${ctime $t3} +;;last_success: ${$t3} ;;${ctime $t3} +;;next_probe_time: ${$t3 + $probe3} ;;${ctime $t3 + $probe3} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=3 ;;lastchange=${$t1} ;;${ctime $t1} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; 11 days later, hold down has lapsed. +STEP 41 TIME_PASSES EVAL ${11*24*3600} +STEP 42 TRAFFIC +STEP 43 ASSIGN t4 = ${time} +STEP 44 ASSIGN probe4 = ${range 4800 ${timeout} 5400} +STEP 45 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t4} ;;${ctime $t4} +;;last_success: ${$t4} ;;${ctime $t4} +;;next_probe_time: ${$t4 + $probe4} ;;${ctime $t4 + $probe4} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t4} ;;${ctime $t4} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; 30 days later, the old key is revoked +STEP 51 TIME_PASSES EVAL ${30*24*3600} +STEP 52 TRAFFIC +STEP 53 ASSIGN t5 = ${time} +STEP 54 ASSIGN probe5 = ${range 4800 ${timeout} 5400} +STEP 55 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t5} ;;${ctime $t5} +;;last_success: ${$t5} ;;${ctime $t5} +;;next_probe_time: ${$t5 + $probe5} ;;${ctime $t5 + $probe5} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=3 [ MISSING ] ;;count=0 ;;lastchange=${$t5} ;;${ctime $t5} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=3 [ MISSING ] ;;count=0 ;;lastchange=${$t5} ;;${ctime $t5} +FILE_END + +; 370 days later, no keys are removed because there are no valid keys +STEP 61 TIME_PASSES EVAL ${370*24*3600} +STEP 62 TRAFFIC +STEP 63 ASSIGN t6 = ${time} +STEP 64 ASSIGN probe6 = ${range 4800 ${timeout} 5400} +STEP 65 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t6} ;;${ctime $t6} +;;last_success: ${$t6} ;;${ctime $t6} +;;next_probe_time: ${$t6 + $probe6} ;;${ctime $t6 + $probe6} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=3 [ MISSING ] ;;count=0 ;;lastchange=${$t5} ;;${ctime $t5} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=3 [ MISSING ] ;;count=0 ;;lastchange=${$t5} ;;${ctime $t5} +FILE_END + + +SCENARIO_END diff --git a/testdata/autotrust_missing_returns.rpl b/testdata/autotrust_missing_returns.rpl new file mode 100644 index 00000000000..d44e0b04985 --- /dev/null +++ b/testdata/autotrust_missing_returns.rpl @@ -0,0 +1,317 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + log-time-ascii: yes +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +; initial content (say from dig example.com DNSKEY > example.com.key) +AUTOTRUST_FILE example.com +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +AUTOTRUST_END +CONFIG_END + +SCENARIO_BEGIN Test autotrust with missing key that returns + +; K-ROOT +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR AA +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS k.root-servers.net. +SECTION ADDITIONAL +k.root-servers.net IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 +RANGE_BEGIN 0 10 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. pYGxVLsWUvOp1wSf0iwPap+JnECfC5GAm1lRqy3YEqecNGld7U7x/5Imo3CerbdZrVptUQs2oH0lcjwYJXMnsw== ;{id = 30899} +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 5 2 3600 20090924111500 20090821111500 30899 example.com. J5wxRq0jgwQL6yy530kvo9cHqNAUHV8IF4dvaYZL0bNraO2Oe6dVXqlJl4+cxNHI2TMsstwFPr2Zz8tv6Az2mQ== ;{id = 30899} +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. JsXbS18oyc0zkVaOWGSFdIQuOsZKflT0GraT9afDPoWLCgH4ApF7jNgfJV7Pqy1sTBRajME5IUAhpANwGBuW4A== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 30899 example.com. b/HK231jIQLX8IhlZfup3r0yhpXaasbPE6LzxoEVVvWaTZWcLmeV8jDIcn0qO7Yvs7bIJN20lwVAV0GcHH3hWQ== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 55582 example.com. PCHme1QLoULxqjhg5tMlpR0qJlBfstEUVq18TtNoKQe9le1YhJ9caheXcTWoK+boLhXxg9u6Yyvq8FboQh0OjA== ;{id = 55582} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 and 60946 +RANGE_BEGIN 11 40 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 30899 example.com. rkaCUpTFPWVu4Om5oMTR+39Mct6ZMs56xrE0rbxMMOokfvIQheIxsAEc5BFJeA/2y5WTewl6diCD6yQXCybrDg== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 55582 example.com. CoMon+lWPAsUvgfpCTDPx8Zn8dQpky3lu2O6T+oJ2Mat9a/u1YwGhSQHGPn7ZNG/4vKM97tx84sSlUGz3geD1w== ;{id = 55582} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 60946 example.com. o+Cbs7DcYPYlSLd4hi3vkSVQpXGnKgKSi9MpHGfu1Uahv5190U2DUOxP1du/HOYbf+IHYL8zLbMZjVEG5wgnTg== ;{id = 60946} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 and 60946 (signatures updated) +RANGE_BEGIN 41 50 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 30899 example.com. rkaCUpTFPWVu4Om5oMTR+39Mct6ZMs56xrE0rbxMMOokfvIQheIxsAEc5BFJeA/2y5WTewl6diCD6yQXCybrDg== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 55582 example.com. v/HJbdpeVMpbhwYXrT1EDGpAFMvEgdKQII1cAbP6o8KHYNKDh8TIJ25/pXe3daEXfej6/Z5kpqJ79okPKUoi1Q== ;{id = 55582} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 60946 example.com. HgXol1hdvbomOM1CFRW8qsHd3D0qOnN72EeMHTcpxIBBiuNLKZn4n1M14Voxj3vo0eAMNuG/y7EjQkxKvSsaDA== ;{id = 60946} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 60946 missing , 55582 is missing +RANGE_BEGIN 51 60 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091224111500 20091118111500 30899 example.com. wzXQvn/XBgdkUn0HFl/mzaxZ30k8R9126hCio+gH5MgaFhWIdp8ob0TWRDA5yzrQCKzkyUqqcx+6fUWVOZOtXg== ;{id = 30899} +; includes a signature from 60946. +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091224111500 20091118111500 60946 example.com. rn/rE/xoqKRbTz1tGUjTESB5e4UrFT5liigwrUi5a6nxn9juhAa+o1VbMXi1zXCAnZwHRE+tGZc8v44zjeioIw== ;{id = 60946} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 60946 +RANGE_BEGIN 61 70 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20101224111500 20101118111500 30899 example.com. TfFGz1kDtkn3ixbKMJvQDZ0uGw/eW+inIiPqQVPQtO2WiocKrnYnzwv/AqwnFvEar70dF15/zffNIF+ipOS5/g== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20101224111500 20101118111500 60946 example.com. X0Ci//w0czN/J5RvypHGqp56n1tLdapi92ODAqjM7QpZXbSHaJ7wfPG1PZzvdxHUZUVyf8uy2stjg/XoLGHMWA== ;{id = 60946} +ENTRY_END +RANGE_END + +; set date/time to Aug 24 07:46:40 (2009). +STEP 5 TIME_PASSES ELAPSE 1251100000 +STEP 6 TRAFFIC ; the initial probe +STEP 7 ASSIGN t0 = ${time} +STEP 8 ASSIGN probe0 = ${range 4800 ${timeout} 5400} + +; the auto probing should have been done now. +STEP 10 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t0} ;;${ctime $t0} +;;last_success: ${$t0} ;;${ctime $t0} +;;next_probe_time: ${$t0 + $probe0} ;;${ctime $t0 + $probe0} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; key prepublished. First poll. 30 days later +STEP 11 TIME_PASSES EVAL ${30*24*3600} +STEP 12 TRAFFIC +STEP 13 ASSIGN t1 = ${time} +STEP 14 ASSIGN probe1 = ${range 4800 ${timeout} 5400} +STEP 15 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t1} ;;${ctime $t1} +;;last_success: ${$t1} ;;${ctime $t1} +;;next_probe_time: ${$t1 + $probe1} ;;${ctime $t1 + $probe1} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=1 ;;lastchange=${$t1} ;;${ctime $t1} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; Second poll. 10 days later +STEP 21 TIME_PASSES EVAL ${10*24*3600} +STEP 22 TRAFFIC +STEP 23 ASSIGN t2 = ${time} +STEP 24 ASSIGN probe2 = ${range 4800 ${timeout} 5400} +STEP 25 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t2} ;;${ctime $t2} +;;last_success: ${$t2} ;;${ctime $t2} +;;next_probe_time: ${$t2 + $probe2} ;;${ctime $t2 + $probe2} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=2 ;;lastchange=${$t1} ;;${ctime $t1} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; Third poll. 10 days later +STEP 31 TIME_PASSES EVAL ${10*24*3600} +STEP 32 TRAFFIC +STEP 33 ASSIGN t3 = ${time} +STEP 34 ASSIGN probe3 = ${range 4800 ${timeout} 5400} +STEP 35 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t3} ;;${ctime $t3} +;;last_success: ${$t3} ;;${ctime $t3} +;;next_probe_time: ${$t3 + $probe3} ;;${ctime $t3 + $probe3} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=3 ;;lastchange=${$t1} ;;${ctime $t1} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; 11 days later, hold down has lapsed. +STEP 41 TIME_PASSES EVAL ${11*24*3600} +STEP 42 TRAFFIC +STEP 43 ASSIGN t4 = ${time} +STEP 44 ASSIGN probe4 = ${range 4800 ${timeout} 5400} +STEP 45 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t4} ;;${ctime $t4} +;;last_success: ${$t4} ;;${ctime $t4} +;;next_probe_time: ${$t4 + $probe4} ;;${ctime $t4 + $probe4} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t4} ;;${ctime $t4} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; 30 days later, the old key is revoked +STEP 51 TIME_PASSES EVAL ${30*24*3600} +STEP 52 TRAFFIC +STEP 53 ASSIGN t5 = ${time} +STEP 54 ASSIGN probe5 = ${range 4800 ${timeout} 5400} +STEP 55 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t5} ;;${ctime $t5} +;;last_success: ${$t5} ;;${ctime $t5} +;;next_probe_time: ${$t5 + $probe5} ;;${ctime $t5 + $probe5} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=3 [ MISSING ] ;;count=0 ;;lastchange=${$t5} ;;${ctime $t5} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=3 [ MISSING ] ;;count=0 ;;lastchange=${$t5} ;;${ctime $t5} +FILE_END + +; 370 days later, the old key is removed from storage +STEP 61 TIME_PASSES EVAL ${370*24*3600} +STEP 62 TRAFFIC +STEP 63 ASSIGN t6 = ${time} +STEP 64 ASSIGN probe6 = ${range 4800 ${timeout} 5400} +STEP 65 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t6} ;;${ctime $t6} +;;last_success: ${$t6} ;;${ctime $t6} +;;next_probe_time: ${$t6 + $probe6} ;;${ctime $t6 + $probe6} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t6} ;;${ctime $t6} +FILE_END + + +SCENARIO_END diff --git a/testdata/autotrust_probefail.rpl b/testdata/autotrust_probefail.rpl new file mode 100644 index 00000000000..b63613a9654 --- /dev/null +++ b/testdata/autotrust_probefail.rpl @@ -0,0 +1,163 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + log-time-ascii: yes +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +AUTOTRUST_FILE example.com +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: 1258962400 ;;Mon Nov 23 08:46:40 2009 +;;last_success: 1258962400 ;;Mon Nov 23 08:46:40 2009 +;;next_probe_time: 1258967360 ;;Mon Nov 23 10:09:20 2009 +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAas/cAhCFXvBUgTSNZCvQp0pLx1dY+7rXR0hH4/3EUgWmsmbYUpI1qD0xhwKD/oYGEwAm291fyWJ9c0oVxXDEK8= ;{id = 16486 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1258962400 ;;Mon Nov 23 08:46:40 2009 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1258962400 ;;Mon Nov 23 08:46:40 2009 +AUTOTRUST_END +CONFIG_END + +SCENARIO_BEGIN Test autotrust with probe failure + +; K-ROOT +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR AA +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS k.root-servers.net. +SECTION ADDITIONAL +k.root-servers.net IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA SERVFAIL +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. 3600 IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. JsXbS18oyc0zkVaOWGSFdIQuOsZKflT0GraT9afDPoWLCgH4ApF7jNgfJV7Pqy1sTBRajME5IUAhpANwGBuW4A== ;{id = 30899} +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 5 2 3600 20090924111500 20090821111500 30899 example.com. J5wxRq0jgwQL6yy530kvo9cHqNAUHV8IF4dvaYZL0bNraO2Oe6dVXqlJl4+cxNHI2TMsstwFPr2Zz8tv6Az2mQ== ;{id = 30899} +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA SERVFAIL +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER + +; revoked keys +example.com. 10800 IN DNSKEY 385 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55710 (ksk), size = 512b} +example.com. 10800 IN DNSKEY 385 3 5 AwEAAas/cAhCFXvBUgTSNZCvQp0pLx1dY+7rXR0hH4/3EUgWmsmbYUpI1qD0xhwKD/oYGEwAm291fyWJ9c0oVxXDEK8= ;{id = 16614 (ksk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 55710 example.com. zOSlB1iwtlP2lum1RK0WoDQrMVj0JKwk2E5Mu1okzV38hAx3Xm9IGMK6WrNkVVLmx4OkhYmdPVA95jVsFpwLMw== ;{id = 55710} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 16614 example.com. qP49cCYP3lvNnLBYty/JxAwHqBIGjpup5zQ7qpjPnaZpBb/TlpOhY17LBZrqD86VvBbEVz5tkxC9UrCy85ePDQ== ;{id = 16614} + +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ENTRY_END +RANGE_END + +RANGE_END + +; set date/time to Mon Nov 23 09:46:40 2009 +STEP 5 TIME_PASSES EVAL ${1258962400 + 7200} +STEP 6 TRAFFIC ; do the probe +STEP 7 ASSIGN t0 = ${time} +STEP 8 ASSIGN probe0 = ${range 3200 ${timeout} 3600} +STEP 9 ASSIGN tp = ${1258962400} + +; the auto probing should have been done now. +STEP 11 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: 1258962400 ;;Mon Nov 23 08:46:40 2009 +;;last_success: 1258962400 ;;Mon Nov 23 08:46:40 2009 +;;next_probe_time: 1258967360 ;;Mon Nov 23 10:09:20 2009 +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAas/cAhCFXvBUgTSNZCvQp0pLx1dY+7rXR0hH4/3EUgWmsmbYUpI1qD0xhwKD/oYGEwAm291fyWJ9c0oVxXDEK8= ;{id = 16486 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1258962400 ;;Mon Nov 23 08:46:40 2009 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1258962400 ;;Mon Nov 23 08:46:40 2009 +FILE_END + +STEP 20 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 30 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +ENTRY_END + +SCENARIO_END diff --git a/testdata/autotrust_probefailsig.rpl b/testdata/autotrust_probefailsig.rpl new file mode 100644 index 00000000000..110f23dd20a --- /dev/null +++ b/testdata/autotrust_probefailsig.rpl @@ -0,0 +1,163 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + log-time-ascii: yes +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +AUTOTRUST_FILE example.com +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: 1258962400 ;;Mon Nov 23 07:46:40 2009 +;;last_success: 1258962400 ;;Mon Nov 23 07:46:40 2009 +;;next_probe_time: 1258967360 ;;Mon Nov 23 09:09:20 2009 +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAas/cAhCFXvBUgTSNZCvQp0pLx1dY+7rXR0hH4/3EUgWmsmbYUpI1qD0xhwKD/oYGEwAm291fyWJ9c0oVxXDEK8= ;{id = 16486 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1258962400 ;;Mon Nov 23 07:46:40 2009 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1258962400 ;;Mon Nov 23 07:46:40 2009 +AUTOTRUST_END +CONFIG_END + +SCENARIO_BEGIN Test autotrust with probe signature failure + +; K-ROOT +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR AA +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS k.root-servers.net. +SECTION ADDITIONAL +k.root-servers.net IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA SERVFAIL +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER + +; revoked keys +example.com. 10800 IN DNSKEY 385 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55710 (ksk), size = 512b} +example.com. 10800 IN DNSKEY 385 3 5 AwEAAas/cAhCFXvBUgTSNZCvQp0pLx1dY+7rXR0hH4/3EUgWmsmbYUpI1qD0xhwKD/oYGEwAm291fyWJ9c0oVxXDEK8= ;{id = 16614 (ksk), size = 512b} +; signatures +; were edited from 20091124111500 20091018111500 to make them fail. +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090101011500 20090101011500 55710 example.com. zOSlB1iwtlP2lum1RK0WoDQrMVj0JKwk2E5Mu1okzV38hAx3Xm9IGMK6WrNkVVLmx4OkhYmdPVA95jVsFpwLMw== ;{id = 55710} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090101011500 20090101011500 16614 example.com. qP49cCYP3lvNnLBYty/JxAwHqBIGjpup5zQ7qpjPnaZpBb/TlpOhY17LBZrqD86VvBbEVz5tkxC9UrCy85ePDQ== ;{id = 16614} + +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN A +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN AAAA +ENTRY_END +RANGE_END + +; set date/time to Mon Nov 23 09:46:40 2009 +STEP 5 TIME_PASSES EVAL ${1258962400 + 7200} +STEP 6 TRAFFIC ; do the probe +STEP 7 ASSIGN t0 = ${time} +STEP 8 ASSIGN probe0 = ${range 3200 ${timeout} 3600} +STEP 9 ASSIGN tp = ${1258962400} + +; the auto probing should have been done now. +STEP 11 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t0} ;;${ctime $t0} +;;last_success: 1258962400 ;;Mon Nov 23 07:46:40 2009 +;;next_probe_time: ${$t0+$probe0} ;;${ctime $t0+$probe0} +;;query_failed: 6 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1258962400 ;;Mon Nov 23 07:46:40 2009 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAas/cAhCFXvBUgTSNZCvQp0pLx1dY+7rXR0hH4/3EUgWmsmbYUpI1qD0xhwKD/oYGEwAm291fyWJ9c0oVxXDEK8= ;{id = 16486 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1258962400 ;;Mon Nov 23 07:46:40 2009 +FILE_END + +STEP 20 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 30 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +ENTRY_END + +SCENARIO_END diff --git a/testdata/autotrust_revoked_use.rpl b/testdata/autotrust_revoked_use.rpl new file mode 100644 index 00000000000..ae72c42f6ba --- /dev/null +++ b/testdata/autotrust_revoked_use.rpl @@ -0,0 +1,403 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + log-time-ascii: yes +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +; initial content (say from dig example.com DNSKEY > example.com.key) +AUTOTRUST_FILE example.com +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +AUTOTRUST_END +CONFIG_END + +SCENARIO_BEGIN Test autotrust with use of revoked key + +; K-ROOT +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR AA +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS k.root-servers.net. +SECTION ADDITIONAL +k.root-servers.net IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 +RANGE_BEGIN 0 10 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. pYGxVLsWUvOp1wSf0iwPap+JnECfC5GAm1lRqy3YEqecNGld7U7x/5Imo3CerbdZrVptUQs2oH0lcjwYJXMnsw== ;{id = 30899} +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 5 2 3600 20090924111500 20090821111500 30899 example.com. J5wxRq0jgwQL6yy530kvo9cHqNAUHV8IF4dvaYZL0bNraO2Oe6dVXqlJl4+cxNHI2TMsstwFPr2Zz8tv6Az2mQ== ;{id = 30899} +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. JsXbS18oyc0zkVaOWGSFdIQuOsZKflT0GraT9afDPoWLCgH4ApF7jNgfJV7Pqy1sTBRajME5IUAhpANwGBuW4A== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 30899 example.com. b/HK231jIQLX8IhlZfup3r0yhpXaasbPE6LzxoEVVvWaTZWcLmeV8jDIcn0qO7Yvs7bIJN20lwVAV0GcHH3hWQ== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 55582 example.com. PCHme1QLoULxqjhg5tMlpR0qJlBfstEUVq18TtNoKQe9le1YhJ9caheXcTWoK+boLhXxg9u6Yyvq8FboQh0OjA== ;{id = 55582} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 and 60946 +RANGE_BEGIN 11 40 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 30899 example.com. rkaCUpTFPWVu4Om5oMTR+39Mct6ZMs56xrE0rbxMMOokfvIQheIxsAEc5BFJeA/2y5WTewl6diCD6yQXCybrDg== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 55582 example.com. CoMon+lWPAsUvgfpCTDPx8Zn8dQpky3lu2O6T+oJ2Mat9a/u1YwGhSQHGPn7ZNG/4vKM97tx84sSlUGz3geD1w== ;{id = 55582} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 60946 example.com. o+Cbs7DcYPYlSLd4hi3vkSVQpXGnKgKSi9MpHGfu1Uahv5190U2DUOxP1du/HOYbf+IHYL8zLbMZjVEG5wgnTg== ;{id = 60946} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 and 60946 (signatures updated) +RANGE_BEGIN 41 50 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 30899 example.com. rkaCUpTFPWVu4Om5oMTR+39Mct6ZMs56xrE0rbxMMOokfvIQheIxsAEc5BFJeA/2y5WTewl6diCD6yQXCybrDg== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 55582 example.com. v/HJbdpeVMpbhwYXrT1EDGpAFMvEgdKQII1cAbP6o8KHYNKDh8TIJ25/pXe3daEXfej6/Z5kpqJ79okPKUoi1Q== ;{id = 55582} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 60946 example.com. HgXol1hdvbomOM1CFRW8qsHd3D0qOnN72EeMHTcpxIBBiuNLKZn4n1M14Voxj3vo0eAMNuG/y7EjQkxKvSsaDA== ;{id = 60946} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582-REVOKED and 60946 +RANGE_BEGIN 51 60 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 385 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55710 (ksk), size = 512b} +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091224111500 20091118111500 30899 example.com. qLKZUJEi3ajSJ4/b7xl0BwhzW6JtjsojpZ+2nUx1PvaeQVoTmyWxjxc2tAmJGcBPqMqzeY470xvyMDvGTOiQCQ== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091224111500 20091118111500 55710 example.com. EW2YB+2yNX9LTNDPVwkcGnRTTx38pOiwBaixdwxmDgqWKXLDLM6Kd2Xv9tveS39RnSZ5H1inRXE55q+rL6Re3g== ;{id = 55710} +; wrong keytag: +;example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091224111500 20091118111500 55582 example.com. nH/6HauVJI4GGz78UoK/38cOOrEqsYZP0jFzfCC3OyIlclVTjAFvjVPlVMGK7sA5Nw1v20YtFTQkXZgbrRuInQ== ;{id = 55582} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091224111500 20091118111500 60946 example.com. xKSBZr4vOsEUKlVoNb6SOV69DM7xFOJI4gPFKq5Tv4APIMJ/9G3odoDmNcLCVyYGzhoDik5hciJnZio6UHgzAA== ;{id = 60946} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 60946 and also KSK 55582 resurrected +RANGE_BEGIN 61 70 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091224111500 20091118111500 30899 example.com. jTB+ID5gp3U+cxedEPpRvM3tegrBFuVjGR7y9IL+olrtbs5Yr3qeANJwbfO1WVAWiG+EtG876uHny9epo/tlhQ== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091224111500 20091118111500 60946 example.com. p6lOsJpkmZUbj1KCSwzxip0NbK0SnjV1LKLayqkWTDiVNkTYHHLHHJfOU8Grb63SDTsZ5lyDocIwJSUBiKuhig== ;{id = 60946} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091224111500 20091118111500 55582 example.com. NsC5s2quifzA7yQBnbroWHJ9rHfSrBo0V7+c+kZoii2cViOm8636uqcWlaNTqNtD5UI6vzQ5zXF4P8JGoac6ZQ== ;{id = 55582} + +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN A +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN AAAA +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 used on its own +; so no signature from a real key, only signatures by REVOKED keys +RANGE_BEGIN 71 80 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091224111500 20091118111500 30899 example.com. jTB+ID5gp3U+cxedEPpRvM3tegrBFuVjGR7y9IL+olrtbs5Yr3qeANJwbfO1WVAWiG+EtG876uHny9epo/tlhQ== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091224111500 20091118111500 55582 example.com. NsC5s2quifzA7yQBnbroWHJ9rHfSrBo0V7+c+kZoii2cViOm8636uqcWlaNTqNtD5UI6vzQ5zXF4P8JGoac6ZQ== ;{id = 55582} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN A +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN AAAA +ENTRY_END +RANGE_END + +; set date/time to Aug 24 07:46:40 (2009). +STEP 5 TIME_PASSES ELAPSE 1251100000 +STEP 6 TRAFFIC ; the initial probe +STEP 7 ASSIGN t0 = ${time} +STEP 8 ASSIGN probe0 = ${range 4800 ${timeout} 5400} + +; the auto probing should have been done now. +STEP 10 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t0} ;;${ctime $t0} +;;last_success: ${$t0} ;;${ctime $t0} +;;next_probe_time: ${$t0 + $probe0} ;;${ctime $t0 + $probe0} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; key prepublished. First poll. 30 days later +STEP 11 TIME_PASSES EVAL ${30*24*3600} +STEP 12 TRAFFIC +STEP 13 ASSIGN t1 = ${time} +STEP 14 ASSIGN probe1 = ${range 4800 ${timeout} 5400} +STEP 15 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t1} ;;${ctime $t1} +;;last_success: ${$t1} ;;${ctime $t1} +;;next_probe_time: ${$t1 + $probe1} ;;${ctime $t1 + $probe1} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=1 ;;lastchange=${$t1} ;;${ctime $t1} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; Second poll. 10 days later +STEP 21 TIME_PASSES EVAL ${10*24*3600} +STEP 22 TRAFFIC +STEP 23 ASSIGN t2 = ${time} +STEP 24 ASSIGN probe2 = ${range 4800 ${timeout} 5400} +STEP 25 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t2} ;;${ctime $t2} +;;last_success: ${$t2} ;;${ctime $t2} +;;next_probe_time: ${$t2 + $probe2} ;;${ctime $t2 + $probe2} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=2 ;;lastchange=${$t1} ;;${ctime $t1} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; Third poll. 10 days later +STEP 31 TIME_PASSES EVAL ${10*24*3600} +STEP 32 TRAFFIC +STEP 33 ASSIGN t3 = ${time} +STEP 34 ASSIGN probe3 = ${range 4800 ${timeout} 5400} +STEP 35 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t3} ;;${ctime $t3} +;;last_success: ${$t3} ;;${ctime $t3} +;;next_probe_time: ${$t3 + $probe3} ;;${ctime $t3 + $probe3} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=3 ;;lastchange=${$t1} ;;${ctime $t1} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; 11 days later, hold down has lapsed. +STEP 41 TIME_PASSES EVAL ${11*24*3600} +STEP 42 TRAFFIC +STEP 43 ASSIGN t4 = ${time} +STEP 44 ASSIGN probe4 = ${range 4800 ${timeout} 5400} +STEP 45 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t4} ;;${ctime $t4} +;;last_success: ${$t4} ;;${ctime $t4} +;;next_probe_time: ${$t4 + $probe4} ;;${ctime $t4 + $probe4} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t4} ;;${ctime $t4} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; 30 days later, the old key is revoked +STEP 51 TIME_PASSES EVAL ${30*24*3600} +STEP 52 TRAFFIC +STEP 53 ASSIGN t5 = ${time} +STEP 54 ASSIGN probe5 = ${range 4800 ${timeout} 5400} +STEP 55 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t5} ;;${ctime $t5} +;;last_success: ${$t5} ;;${ctime $t5} +;;next_probe_time: ${$t5 + $probe5} ;;${ctime $t5 + $probe5} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t4} ;;${ctime $t4} +example.com. 10800 IN DNSKEY 385 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55710 (ksk), size = 512b} ;;state=4 [ REVOKED ] ;;count=0 ;;lastchange=${$t5} ;;${ctime $t5} +FILE_END + +; couple days later: someone is trying to use the revoked key again! +; like an outofdate authority server. +STEP 61 TIME_PASSES EVAL ${10*24*3600} +STEP 62 TRAFFIC +STEP 63 ASSIGN t6 = ${time} +STEP 64 ASSIGN probe6 = ${range 4800 ${timeout} 5400} +STEP 65 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t6} ;;${ctime $t6} +;;last_success: ${$t6} ;;${ctime $t6} +;;next_probe_time: ${$t6 + $probe6} ;;${ctime $t6 + $probe6} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t4} ;;${ctime $t4} +example.com. 10800 IN DNSKEY 385 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55710 (ksk), size = 512b} ;;state=4 [ REVOKED ] ;;count=0 ;;lastchange=${$t6} ;;${ctime $t6} +FILE_END + +; couple days later: someone is abusing the revoked key! +; like key material used after revocation +STEP 71 TIME_PASSES EVAL ${2*24*3600} +STEP 72 TRAFFIC +STEP 73 ASSIGN t7 = ${time} +STEP 74 ASSIGN probe7 = ${range 3200 ${timeout} 3600} +STEP 75 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t7} ;;${ctime $t7} +;;last_success: ${$t6} ;;${ctime $t6} +;;next_probe_time: ${$t7 + $probe7} ;;${ctime $t7 + $probe7} +;;query_failed: 6 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t4} ;;${ctime $t4} +example.com. 10800 IN DNSKEY 385 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55710 (ksk), size = 512b} ;;state=4 [ REVOKED ] ;;count=0 ;;lastchange=${$t6} ;;${ctime $t6} +FILE_END + +SCENARIO_END diff --git a/testdata/autotrust_revoked_with_invalid.rpl b/testdata/autotrust_revoked_with_invalid.rpl new file mode 100644 index 00000000000..144bf4918b4 --- /dev/null +++ b/testdata/autotrust_revoked_with_invalid.rpl @@ -0,0 +1,128 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + log-time-ascii: yes +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +AUTOTRUST_FILE example.com +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: 1258962400 ;;Mon Nov 23 07:46:40 2009 +;;last_success: 1258962400 ;;Mon Nov 23 07:46:40 2009 +;;next_probe_time: 1258967360 ;;Mon Nov 23 09:09:20 2009 +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1256370400 ;;Sat Oct 24 09:46:40 2009 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1258962400 ;;Mon Nov 23 07:46:40 2009 +AUTOTRUST_END +CONFIG_END + +SCENARIO_BEGIN Test autotrust with revoked key amidst invalid keys + +; K-ROOT +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR AA +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS k.root-servers.net. +SECTION ADDITIONAL +k.root-servers.net IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER + +; revoked key and an unknown key + +example.com. 10800 IN DNSKEY 385 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55710 (ksk), size = 512b} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAas/cAhCFXvBUgTSNZCvQp0pLx1dY+7rXR0hH4/3EUgWmsmbYUpI1qD0xhwKD/oYGEwAm291fyWJ9c0oVxXDEK8= ;{id = 16486 (ksk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 55710 example.com. nu+W3T0afsJc2MrrsnBZ3adysi39TLUJ0o8GYaR/PFYsYSOigSCnr3xo05aKoNZ2oeQXhmwQVAxfwU1M/jXngQ== ;{id = 55710} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 16486 example.com. LDW5an/v6YzgUhpTm8VJnBCko56WDvzzoqCmjXBwpoGjWXThO2hUyO6w00K90swQvKwgIWsC4y00zFlOgLayJw== ;{id = 16486} + +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN A +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN AAAA +ENTRY_END +RANGE_END + +; set date/time to Mon Nov 23 09:46:40 2009 +STEP 5 TIME_PASSES EVAL ${1258962400 + 7200} +STEP 6 TRAFFIC ; do the probe +STEP 7 ASSIGN t0 = ${time} +STEP 8 ASSIGN probe0 = ${range 3200 ${timeout} 3600} +STEP 9 ASSIGN tp = ${1258962400} + +; the auto probing should have been done now. +STEP 11 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t0} ;;${ctime $t0} +;;last_success: ${$tp} ;;${ctime $tp} +;;next_probe_time: ${$t0 + $probe0} ;;${ctime $t0 + $probe0} +;;query_failed: 6 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 385 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55710 (ksk), size = 512b} ;;state=4 [ REVOKED ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1256370400 ;;Sat Oct 24 07:46:40 2009 +FILE_END + +SCENARIO_END diff --git a/testdata/autotrust_revtp.rpl b/testdata/autotrust_revtp.rpl new file mode 100644 index 00000000000..26a4f309303 --- /dev/null +++ b/testdata/autotrust_revtp.rpl @@ -0,0 +1,148 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + log-time-ascii: yes +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +AUTOTRUST_FILE example.com +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: 1258962400 ;;Mon Nov 23 08:46:40 2009 +;;last_success: 1258962400 ;;Mon Nov 23 08:46:40 2009 +;;next_probe_time: 1258967360 ;;Mon Nov 23 10:09:20 2009 +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAas/cAhCFXvBUgTSNZCvQp0pLx1dY+7rXR0hH4/3EUgWmsmbYUpI1qD0xhwKD/oYGEwAm291fyWJ9c0oVxXDEK8= ;{id = 16486 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1258962400 ;;Mon Nov 23 08:46:40 2009 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1258962400 ;;Mon Nov 23 08:46:40 2009 +AUTOTRUST_END +CONFIG_END + +SCENARIO_BEGIN Test autotrust with trust point revocation + +; K-ROOT +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR AA +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS k.root-servers.net. +SECTION ADDITIONAL +k.root-servers.net IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER + +; revoked keys + +example.com. 10800 IN DNSKEY 385 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55710 (ksk), size = 512b} +example.com. 10800 IN DNSKEY 385 3 5 AwEAAas/cAhCFXvBUgTSNZCvQp0pLx1dY+7rXR0hH4/3EUgWmsmbYUpI1qD0xhwKD/oYGEwAm291fyWJ9c0oVxXDEK8= ;{id = 16614 (ksk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 55710 example.com. zOSlB1iwtlP2lum1RK0WoDQrMVj0JKwk2E5Mu1okzV38hAx3Xm9IGMK6WrNkVVLmx4OkhYmdPVA95jVsFpwLMw== ;{id = 55710} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 16614 example.com. qP49cCYP3lvNnLBYty/JxAwHqBIGjpup5zQ7qpjPnaZpBb/TlpOhY17LBZrqD86VvBbEVz5tkxC9UrCy85ePDQ== ;{id = 16614} + +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ENTRY_END +RANGE_END + +RANGE_END + +; set date/time to Mon Nov 23 09:46:40 2009 +STEP 5 TIME_PASSES EVAL ${1258962400 + 7200} +STEP 6 TRAFFIC ; do the probe +STEP 7 ASSIGN t0 = ${time} +STEP 8 ASSIGN probe0 = ${range 0 ${timeout} 0} +STEP 9 ASSIGN tp = ${1258962400} + +; the auto probing should have been done now. +STEP 11 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;REVOKED +; The zone has all keys revoked, and is +; considered as if it has no trust anchors. +; the remainder of the file is the last probe. +; to restart the trust anchor, overwrite this file. +; with one containing valid DNSKEYs or DSes. +;;id: example.com. 1 +;;last_queried: ${$t0} ;;${ctime $t0} +;;last_success: ${$t0} ;;${ctime $t0} +;;next_probe_time: ${0} ;;${ctime 0} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 385 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55710 (ksk), size = 512b} ;;state=4 [ REVOKED ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +example.com. 10800 IN DNSKEY 385 3 5 AwEAAas/cAhCFXvBUgTSNZCvQp0pLx1dY+7rXR0hH4/3EUgWmsmbYUpI1qD0xhwKD/oYGEwAm291fyWJ9c0oVxXDEK8= ;{id = 16614 (ksk), size = 512b} ;;state=4 [ REVOKED ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +STEP 20 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; correct unsigned response works after trust point revocation. +STEP 30 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ENTRY_END + +SCENARIO_END diff --git a/testdata/autotrust_revtp_read.rpl b/testdata/autotrust_revtp_read.rpl new file mode 100644 index 00000000000..b7ea63a8ea4 --- /dev/null +++ b/testdata/autotrust_revtp_read.rpl @@ -0,0 +1,109 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + log-time-ascii: yes + val-override-date: '20091018111500' +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +AUTOTRUST_FILE example.com +; autotrust trust anchor file +;;REVOKED +; The zone has all keys revoked, and is +; considered as if it has no trust anchors. +; the remainder of the file is the last probe. +; to restart the trust anchor, overwrite this file. +; with one containing valid DNSKEYs or DSes. +;;id: example.com. 1 +;;last_queried: 1258962400 ;;Mon Nov 23 08:46:40 2009 +;;last_success: 1258962400 ;;Mon Nov 23 08:46:40 2009 +;;next_probe_time: ${0} ;;${ctime 0} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 385 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55710 (ksk), size = 512b} ;;state=4 [ REVOKED ] ;;count=0 ;;lastchange=1258962400 ;;Mon Nov 23 08:46:40 2009 +example.com. 10800 IN DNSKEY 385 3 5 AwEAAas/cAhCFXvBUgTSNZCvQp0pLx1dY+7rXR0hH4/3EUgWmsmbYUpI1qD0xhwKD/oYGEwAm291fyWJ9c0oVxXDEK8= ;{id = 16614 (ksk), size = 512b} ;;state=4 [ REVOKED ] ;;count=0 ;;lastchange=1258962400 ;;Mon Nov 23 08:46:40 2009 +AUTOTRUST_END +CONFIG_END + +SCENARIO_BEGIN Test autotrust with revoked trust point read back from config + +; K-ROOT +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR AA +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS k.root-servers.net. +SECTION ADDITIONAL +k.root-servers.net IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ENTRY_END +RANGE_END + +RANGE_END + +STEP 20 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; correct unsigned response works after trust point revocation. +STEP 30 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ENTRY_END + +SCENARIO_END diff --git a/testdata/autotrust_revtp_use.rpl b/testdata/autotrust_revtp_use.rpl new file mode 100644 index 00000000000..a96bf181976 --- /dev/null +++ b/testdata/autotrust_revtp_use.rpl @@ -0,0 +1,143 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + log-time-ascii: yes + val-override-date: '20091018111500' +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +AUTOTRUST_FILE example.com +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: 1258962400 ;;Mon Nov 23 08:46:40 2009 +;;last_success: 1258962400 ;;Mon Nov 23 08:46:40 2009 +;;next_probe_time: 1258967360 ;;Mon Nov 23 10:09:20 2009 +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAas/cAhCFXvBUgTSNZCvQp0pLx1dY+7rXR0hH4/3EUgWmsmbYUpI1qD0xhwKD/oYGEwAm291fyWJ9c0oVxXDEK8= ;{id = 16486 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1258962400 ;;Mon Nov 23 08:46:40 2009 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=1258962400 ;;Mon Nov 23 08:46:40 2009 +AUTOTRUST_END +CONFIG_END + +SCENARIO_BEGIN Test autotrust with trust point revocation and instant use +; so not a probe that discovers it but a user query. + +; K-ROOT +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR AA +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS k.root-servers.net. +SECTION ADDITIONAL +k.root-servers.net IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER + +; revoked keys + +example.com. 10800 IN DNSKEY 385 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55710 (ksk), size = 512b} +example.com. 10800 IN DNSKEY 385 3 5 AwEAAas/cAhCFXvBUgTSNZCvQp0pLx1dY+7rXR0hH4/3EUgWmsmbYUpI1qD0xhwKD/oYGEwAm291fyWJ9c0oVxXDEK8= ;{id = 16614 (ksk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 55710 example.com. zOSlB1iwtlP2lum1RK0WoDQrMVj0JKwk2E5Mu1okzV38hAx3Xm9IGMK6WrNkVVLmx4OkhYmdPVA95jVsFpwLMw== ;{id = 55710} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 16614 example.com. qP49cCYP3lvNnLBYty/JxAwHqBIGjpup5zQ7qpjPnaZpBb/TlpOhY17LBZrqD86VvBbEVz5tkxC9UrCy85ePDQ== ;{id = 16614} + +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ENTRY_END +RANGE_END + +RANGE_END + +STEP 20 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; correct unsigned response works after trust point revocation. +STEP 30 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ENTRY_END + +STEP 37 ASSIGN t0 = ${time} +STEP 41 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;REVOKED +; The zone has all keys revoked, and is +; considered as if it has no trust anchors. +; the remainder of the file is the last probe. +; to restart the trust anchor, overwrite this file. +; with one containing valid DNSKEYs or DSes. +;;id: example.com. 1 +;;last_queried: ${$t0} ;;${ctime $t0} +;;last_success: ${$t0} ;;${ctime $t0} +;;next_probe_time: ${0} ;;${ctime 0} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 385 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55710 (ksk), size = 512b} ;;state=4 [ REVOKED ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +example.com. 10800 IN DNSKEY 385 3 5 AwEAAas/cAhCFXvBUgTSNZCvQp0pLx1dY+7rXR0hH4/3EUgWmsmbYUpI1qD0xhwKD/oYGEwAm291fyWJ9c0oVxXDEK8= ;{id = 16614 (ksk), size = 512b} ;;state=4 [ REVOKED ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +SCENARIO_END diff --git a/testdata/autotrust_rollalgo.rpl b/testdata/autotrust_rollalgo.rpl new file mode 100644 index 00000000000..4deec32a834 --- /dev/null +++ b/testdata/autotrust_rollalgo.rpl @@ -0,0 +1,314 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + log-time-ascii: yes +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +; initial content (say from dig example.com DNSKEY > example.com.key) +AUTOTRUST_FILE example.com +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +AUTOTRUST_END +CONFIG_END + +SCENARIO_BEGIN Test autotrust with algorithm rollover +; from RSASHA1(5) to DSASHA1(3) +; Note, when both algorithms are present, the zone must be double-signed. +; with a ZSK for RSASHA1(5) and a ZSK for DSASHA1(3). + +; K-ROOT +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR AA +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS k.root-servers.net. +SECTION ADDITIONAL +k.root-servers.net IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 +RANGE_BEGIN 0 10 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. pYGxVLsWUvOp1wSf0iwPap+JnECfC5GAm1lRqy3YEqecNGld7U7x/5Imo3CerbdZrVptUQs2oH0lcjwYJXMnsw== ;{id = 30899} +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 5 2 3600 20090924111500 20090821111500 30899 example.com. J5wxRq0jgwQL6yy530kvo9cHqNAUHV8IF4dvaYZL0bNraO2Oe6dVXqlJl4+cxNHI2TMsstwFPr2Zz8tv6Az2mQ== ;{id = 30899} +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. JsXbS18oyc0zkVaOWGSFdIQuOsZKflT0GraT9afDPoWLCgH4ApF7jNgfJV7Pqy1sTBRajME5IUAhpANwGBuW4A== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 30899 example.com. b/HK231jIQLX8IhlZfup3r0yhpXaasbPE6LzxoEVVvWaTZWcLmeV8jDIcn0qO7Yvs7bIJN20lwVAV0GcHH3hWQ== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 55582 example.com. PCHme1QLoULxqjhg5tMlpR0qJlBfstEUVq18TtNoKQe9le1YhJ9caheXcTWoK+boLhXxg9u6Yyvq8FboQh0OjA== ;{id = 55582} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 and DSAkey 02855 +RANGE_BEGIN 11 40 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 3 ALXLUsWqUrY3JYER3T4TBJIIs70j+sDS/UT2QRp61SE7S3EEXopNXoFE73JLRmvpi/UrOO/Vz4Se6wXv/CYCKjGw06U4WRgRYXcpEhJROyNapmdIKSxhOzfLVE1gqA0PweZR8dtY3aNQSRn3sPpwJr6Mi/PqQKAMMrZ9ckJpf1+bQMOOvxgzz2U1GS18b3yZKcgTMEaJzd/GZYzi/BN2DzQ0MsrSwYXfsNLFOBbs8PJMW4LYIxeeOe6rUgkWOF7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2855 (ksk), size = 1688b} +; and two ZSKs (omitted) for both algorithms. +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 55582 example.com. aCZVA+PLXxm15p46499FCPHvhR/MSpMSRTZT6PoUy2e+wdk7bszLdsEmfWym81UN2Xx1JOj5104c43c3QnvjNQ== ;{id = 55582} +example.com. 10800 IN RRSIG DNSKEY 3 2 10800 20091024111500 20090921111500 2855 example.com. AKdhmjqEbe0STsFNq/UxOidElaWHWCy2hSPQ7oN0Tsq56w6Hsk72PpM= ;{id = 2855} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 and 02855 (signatures updated) +RANGE_BEGIN 41 50 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 3 ALXLUsWqUrY3JYER3T4TBJIIs70j+sDS/UT2QRp61SE7S3EEXopNXoFE73JLRmvpi/UrOO/Vz4Se6wXv/CYCKjGw06U4WRgRYXcpEhJROyNapmdIKSxhOzfLVE1gqA0PweZR8dtY3aNQSRn3sPpwJr6Mi/PqQKAMMrZ9ckJpf1+bQMOOvxgzz2U1GS18b3yZKcgTMEaJzd/GZYzi/BN2DzQ0MsrSwYXfsNLFOBbs8PJMW4LYIxeeOe6rUgkWOF7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2855 (ksk), size = 1688b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 55582 example.com. vpLMiMW+2uxqE1+OpMWipQdyGJ/pOQ63tIhup50WFejPysvlZRZ27XOoB4GVRyCwK9Bv46PrsQf3IsjHZf6jvw== ;{id = 55582} +example.com. 10800 IN RRSIG DNSKEY 3 2 10800 20091124111500 20091018111500 2855 example.com. ABJyZ97htJyBFk5wsKml3YAz81FpXkQKdJeC++fB5ysvl3i+zKJFzTo= ;{id = 2855} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582-REVOKED and 02855 +RANGE_BEGIN 51 60 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 385 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55710 (ksk), size = 512b} +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 3 ALXLUsWqUrY3JYER3T4TBJIIs70j+sDS/UT2QRp61SE7S3EEXopNXoFE73JLRmvpi/UrOO/Vz4Se6wXv/CYCKjGw06U4WRgRYXcpEhJROyNapmdIKSxhOzfLVE1gqA0PweZR8dtY3aNQSRn3sPpwJr6Mi/PqQKAMMrZ9ckJpf1+bQMOOvxgzz2U1GS18b3yZKcgTMEaJzd/GZYzi/BN2DzQ0MsrSwYXfsNLFOBbs8PJMW4LYIxeeOe6rUgkWOF7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2855 (ksk), size = 1688b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 3 2 10800 20091224111500 20091118111500 2855 example.com. AFAbqLJsTDBfwAipE84ETdFTfzKHs7pzdyzjTKHR2VXygGvHY4QsBaA= ;{id = 2855} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091224111500 20091118111500 55710 example.com. DqR6BRE9G+kEb+ZorUr3yKKUsCF2TN+vrsNBaLfpHR+Vgv0RgeRCkXki+/FY9b4NEhXkg719dlLSASg4DmyV7g== ;{id = 55710} +; wrong keytag: 55582 +ENTRY_END +RANGE_END + +; ns.example.com. KSK 02855 +RANGE_BEGIN 61 70 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 3 ALXLUsWqUrY3JYER3T4TBJIIs70j+sDS/UT2QRp61SE7S3EEXopNXoFE73JLRmvpi/UrOO/Vz4Se6wXv/CYCKjGw06U4WRgRYXcpEhJROyNapmdIKSxhOzfLVE1gqA0PweZR8dtY3aNQSRn3sPpwJr6Mi/PqQKAMMrZ9ckJpf1+bQMOOvxgzz2U1GS18b3yZKcgTMEaJzd/GZYzi/BN2DzQ0MsrSwYXfsNLFOBbs8PJMW4LYIxeeOe6rUgkWOF7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2855 (ksk), size = 1688b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 3 2 10800 20101224111500 20101118111500 2855 example.com. AJv9ujre3iUykHlhJpLYPqsXq12lmQp+AHUPSPpE5zuUhXAPjbnbewk= ;{id = 2855} +ENTRY_END +RANGE_END + +; set date/time to Aug 24 07:46:40 (2009). +STEP 5 TIME_PASSES ELAPSE 1251100000 +STEP 6 TRAFFIC ; the initial probe +STEP 7 ASSIGN t0 = ${time} +STEP 8 ASSIGN probe0 = ${range 4800 ${timeout} 5400} + +; the auto probing should have been done now. +STEP 10 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t0} ;;${ctime $t0} +;;last_success: ${$t0} ;;${ctime $t0} +;;next_probe_time: ${$t0 + $probe0} ;;${ctime $t0 + $probe0} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; key prepublished. First poll. 30 days later +STEP 11 TIME_PASSES EVAL ${30*24*3600} +STEP 12 TRAFFIC +STEP 13 ASSIGN t1 = ${time} +STEP 14 ASSIGN probe1 = ${range 4800 ${timeout} 5400} +STEP 15 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t1} ;;${ctime $t1} +;;last_success: ${$t1} ;;${ctime $t1} +;;next_probe_time: ${$t1 + $probe1} ;;${ctime $t1 + $probe1} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 3 ALXLUsWqUrY3JYER3T4TBJIIs70j+sDS/UT2QRp61SE7S3EEXopNXoFE73JLRmvpi/UrOO/Vz4Se6wXv/CYCKjGw06U4WRgRYXcpEhJROyNapmdIKSxhOzfLVE1gqA0PweZR8dtY3aNQSRn3sPpwJr6Mi/PqQKAMMrZ9ckJpf1+bQMOOvxgzz2U1GS18b3yZKcgTMEaJzd/GZYzi/BN2DzQ0MsrSwYXfsNLFOBbs8PJMW4LYIxeeOe6rUgkWOF7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2855 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=1 ;;lastchange=${$t1} ;;${ctime $t1} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; Second poll. 10 days later +STEP 21 TIME_PASSES EVAL ${10*24*3600} +STEP 22 TRAFFIC +STEP 23 ASSIGN t2 = ${time} +STEP 24 ASSIGN probe2 = ${range 4800 ${timeout} 5400} +STEP 25 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t2} ;;${ctime $t2} +;;last_success: ${$t2} ;;${ctime $t2} +;;next_probe_time: ${$t2 + $probe2} ;;${ctime $t2 + $probe2} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 3 ALXLUsWqUrY3JYER3T4TBJIIs70j+sDS/UT2QRp61SE7S3EEXopNXoFE73JLRmvpi/UrOO/Vz4Se6wXv/CYCKjGw06U4WRgRYXcpEhJROyNapmdIKSxhOzfLVE1gqA0PweZR8dtY3aNQSRn3sPpwJr6Mi/PqQKAMMrZ9ckJpf1+bQMOOvxgzz2U1GS18b3yZKcgTMEaJzd/GZYzi/BN2DzQ0MsrSwYXfsNLFOBbs8PJMW4LYIxeeOe6rUgkWOF7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2855 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=2 ;;lastchange=${$t1} ;;${ctime $t1} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; Third poll. 10 days later +STEP 31 TIME_PASSES EVAL ${10*24*3600} +STEP 32 TRAFFIC +STEP 33 ASSIGN t3 = ${time} +STEP 34 ASSIGN probe3 = ${range 4800 ${timeout} 5400} +STEP 35 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t3} ;;${ctime $t3} +;;last_success: ${$t3} ;;${ctime $t3} +;;next_probe_time: ${$t3 + $probe3} ;;${ctime $t3 + $probe3} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 3 ALXLUsWqUrY3JYER3T4TBJIIs70j+sDS/UT2QRp61SE7S3EEXopNXoFE73JLRmvpi/UrOO/Vz4Se6wXv/CYCKjGw06U4WRgRYXcpEhJROyNapmdIKSxhOzfLVE1gqA0PweZR8dtY3aNQSRn3sPpwJr6Mi/PqQKAMMrZ9ckJpf1+bQMOOvxgzz2U1GS18b3yZKcgTMEaJzd/GZYzi/BN2DzQ0MsrSwYXfsNLFOBbs8PJMW4LYIxeeOe6rUgkWOF7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2855 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=3 ;;lastchange=${$t1} ;;${ctime $t1} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; 11 days later, hold down has lapsed. +STEP 41 TIME_PASSES EVAL ${11*24*3600} +STEP 42 TRAFFIC +STEP 43 ASSIGN t4 = ${time} +STEP 44 ASSIGN probe4 = ${range 4800 ${timeout} 5400} +STEP 45 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t4} ;;${ctime $t4} +;;last_success: ${$t4} ;;${ctime $t4} +;;next_probe_time: ${$t4 + $probe4} ;;${ctime $t4 + $probe4} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 3 ALXLUsWqUrY3JYER3T4TBJIIs70j+sDS/UT2QRp61SE7S3EEXopNXoFE73JLRmvpi/UrOO/Vz4Se6wXv/CYCKjGw06U4WRgRYXcpEhJROyNapmdIKSxhOzfLVE1gqA0PweZR8dtY3aNQSRn3sPpwJr6Mi/PqQKAMMrZ9ckJpf1+bQMOOvxgzz2U1GS18b3yZKcgTMEaJzd/GZYzi/BN2DzQ0MsrSwYXfsNLFOBbs8PJMW4LYIxeeOe6rUgkWOF7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2855 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t4} ;;${ctime $t4} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; 30 days later, the old key is revoked +STEP 51 TIME_PASSES EVAL ${30*24*3600} +STEP 52 TRAFFIC +STEP 53 ASSIGN t5 = ${time} +STEP 54 ASSIGN probe5 = ${range 4800 ${timeout} 5400} +STEP 55 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t5} ;;${ctime $t5} +;;last_success: ${$t5} ;;${ctime $t5} +;;next_probe_time: ${$t5 + $probe5} ;;${ctime $t5 + $probe5} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 3 ALXLUsWqUrY3JYER3T4TBJIIs70j+sDS/UT2QRp61SE7S3EEXopNXoFE73JLRmvpi/UrOO/Vz4Se6wXv/CYCKjGw06U4WRgRYXcpEhJROyNapmdIKSxhOzfLVE1gqA0PweZR8dtY3aNQSRn3sPpwJr6Mi/PqQKAMMrZ9ckJpf1+bQMOOvxgzz2U1GS18b3yZKcgTMEaJzd/GZYzi/BN2DzQ0MsrSwYXfsNLFOBbs8PJMW4LYIxeeOe6rUgkWOF7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2855 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t4} ;;${ctime $t4} +example.com. 10800 IN DNSKEY 385 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55710 (ksk), size = 512b} ;;state=4 [ REVOKED ] ;;count=0 ;;lastchange=${$t5} ;;${ctime $t5} +FILE_END + +; 370 days later, the old key is removed from storage +STEP 61 TIME_PASSES EVAL ${370*24*3600} +STEP 62 TRAFFIC +STEP 63 ASSIGN t6 = ${time} +STEP 64 ASSIGN probe6 = ${range 4800 ${timeout} 5400} +STEP 65 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t6} ;;${ctime $t6} +;;last_success: ${$t6} ;;${ctime $t6} +;;next_probe_time: ${$t6 + $probe6} ;;${ctime $t6 + $probe6} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 3 ALXLUsWqUrY3JYER3T4TBJIIs70j+sDS/UT2QRp61SE7S3EEXopNXoFE73JLRmvpi/UrOO/Vz4Se6wXv/CYCKjGw06U4WRgRYXcpEhJROyNapmdIKSxhOzfLVE1gqA0PweZR8dtY3aNQSRn3sPpwJr6Mi/PqQKAMMrZ9ckJpf1+bQMOOvxgzz2U1GS18b3yZKcgTMEaJzd/GZYzi/BN2DzQ0MsrSwYXfsNLFOBbs8PJMW4LYIxeeOe6rUgkWOF7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2855 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t4} ;;${ctime $t4} +FILE_END + + +SCENARIO_END diff --git a/testdata/autotrust_rollalgo_unknown.rpl b/testdata/autotrust_rollalgo_unknown.rpl new file mode 100644 index 00000000000..621e5d13cc6 --- /dev/null +++ b/testdata/autotrust_rollalgo_unknown.rpl @@ -0,0 +1,323 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + log-time-ascii: yes +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +; initial content (say from dig example.com DNSKEY > example.com.key) +AUTOTRUST_FILE example.com +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +AUTOTRUST_END +CONFIG_END + +SCENARIO_BEGIN Test autotrust with algorithm rollover to unknown algo +; from RSASHA1(5) to 'unknown' (157) +; 157 is really the algocode for HMACMD5, which is not used for DNSSEC. +; the signatures are made with a DSA key (02855) but the algorithm is +; edited (afterwards) to be 157. So the RRSIGs do not verify. + +; K-ROOT +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR AA +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS k.root-servers.net. +SECTION ADDITIONAL +k.root-servers.net IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 +RANGE_BEGIN 0 10 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. pYGxVLsWUvOp1wSf0iwPap+JnECfC5GAm1lRqy3YEqecNGld7U7x/5Imo3CerbdZrVptUQs2oH0lcjwYJXMnsw== ;{id = 30899} +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 5 2 3600 20090924111500 20090821111500 30899 example.com. J5wxRq0jgwQL6yy530kvo9cHqNAUHV8IF4dvaYZL0bNraO2Oe6dVXqlJl4+cxNHI2TMsstwFPr2Zz8tv6Az2mQ== ;{id = 30899} +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. JsXbS18oyc0zkVaOWGSFdIQuOsZKflT0GraT9afDPoWLCgH4ApF7jNgfJV7Pqy1sTBRajME5IUAhpANwGBuW4A== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 30899 example.com. b/HK231jIQLX8IhlZfup3r0yhpXaasbPE6LzxoEVVvWaTZWcLmeV8jDIcn0qO7Yvs7bIJN20lwVAV0GcHH3hWQ== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 55582 example.com. PCHme1QLoULxqjhg5tMlpR0qJlBfstEUVq18TtNoKQe9le1YhJ9caheXcTWoK+boLhXxg9u6Yyvq8FboQh0OjA== ;{id = 55582} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 and 02855 +RANGE_BEGIN 11 40 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 157 ALXLUsWqUrY3JYER3T4TBJIIs70j+sDS/UT2QRp61SE7S3EEXopNXoFE73JLRmvpi/UrOO/Vz4Se6wXv/CYCKjGw06U4WRgRYXcpEhJROyNapmdIKSxhOzfLVE1gqA0PweZR8dtY3aNQSRn3sPpwJr6Mi/PqQKAMMrZ9ckJpf1+bQMOOvxgzz2U1GS18b3yZKcgTMEaJzd/GZYzi/BN2DzQ0MsrSwYXfsNLFOBbs8PJMW4LYIxeeOe6rUgkWOF7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2855 (ksk), size = 1688b} +; and two ZSKs (omitted) for both algorithms. +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 55582 example.com. Wp40P+Odx5gh1Zpjwa1YBwwKnqhobPSkv55sEb21vvKpLE2NNt7B6vZqRLg+bBiW0T/vRdo4w+7whKANVuPrtA== ;{id = 55582} +example.com. 10800 IN RRSIG DNSKEY 157 2 10800 20091024111500 20090921111500 2855 example.com. AKdhmjqEbe0STsFNq/UxOidElaWHWCy2hSPQ7oN0Tsq56w6Hsk72PpM= ;{id = 2855} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 and 02855 (signatures updated) +RANGE_BEGIN 41 50 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 157 ALXLUsWqUrY3JYER3T4TBJIIs70j+sDS/UT2QRp61SE7S3EEXopNXoFE73JLRmvpi/UrOO/Vz4Se6wXv/CYCKjGw06U4WRgRYXcpEhJROyNapmdIKSxhOzfLVE1gqA0PweZR8dtY3aNQSRn3sPpwJr6Mi/PqQKAMMrZ9ckJpf1+bQMOOvxgzz2U1GS18b3yZKcgTMEaJzd/GZYzi/BN2DzQ0MsrSwYXfsNLFOBbs8PJMW4LYIxeeOe6rUgkWOF7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2855 (ksk), size = 1688b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 55582 example.com. FXY4N99Udr/2Q+9oU4Dil9B8XQCBcaU0NlqJ9HnwZoLqzKiPhtxNlldU2Ab5TmuXfnkTT1bTYvsq5Dz6P3ezbw== ;{id = 55582} +example.com. 10800 IN RRSIG DNSKEY 157 2 10800 20091124111500 20091018111500 2855 example.com. ABJyZ97htJyBFk5wsKml3YAz81FpXkQKdJeC++fB5ysvl3i+zKJFzTo= ;{id = 2855} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582-REVOKED and 02855 +RANGE_BEGIN 51 60 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 385 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55710 (ksk), size = 512b} +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 157 ALXLUsWqUrY3JYER3T4TBJIIs70j+sDS/UT2QRp61SE7S3EEXopNXoFE73JLRmvpi/UrOO/Vz4Se6wXv/CYCKjGw06U4WRgRYXcpEhJROyNapmdIKSxhOzfLVE1gqA0PweZR8dtY3aNQSRn3sPpwJr6Mi/PqQKAMMrZ9ckJpf1+bQMOOvxgzz2U1GS18b3yZKcgTMEaJzd/GZYzi/BN2DzQ0MsrSwYXfsNLFOBbs8PJMW4LYIxeeOe6rUgkWOF7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2855 (ksk), size = 1688b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091224111500 20091118111500 55710 example.com. w5hXwGyeLHWTzdStx4yjB7LNzt86u9A+Qpl3rtQlTKN/qkWIT+Hxa3M32P6jhFTpf+Iq1K9T06mKM21L3TQAOg== ;{id = 55710} +example.com. 10800 IN RRSIG DNSKEY 157 2 10800 20091224111500 20091118111500 2855 example.com. AFAbqLJsTDBfwAipE84ETdFTfzKHs7pzdyzjTKHR2VXygGvHY4QsBaA= ;{id = 2855} +; wrong keytag: 55582 +ENTRY_END +RANGE_END + +; ns.example.com. KSK 02855 +RANGE_BEGIN 61 70 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 157 ALXLUsWqUrY3JYER3T4TBJIIs70j+sDS/UT2QRp61SE7S3EEXopNXoFE73JLRmvpi/UrOO/Vz4Se6wXv/CYCKjGw06U4WRgRYXcpEhJROyNapmdIKSxhOzfLVE1gqA0PweZR8dtY3aNQSRn3sPpwJr6Mi/PqQKAMMrZ9ckJpf1+bQMOOvxgzz2U1GS18b3yZKcgTMEaJzd/GZYzi/BN2DzQ0MsrSwYXfsNLFOBbs8PJMW4LYIxeeOe6rUgkWOF7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2855 (ksk), size = 1688b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 157 2 10800 20101224111500 20101118111500 2855 example.com. AJv9ujre3iUykHlhJpLYPqsXq12lmQp+AHUPSPpE5zuUhXAPjbnbewk= ;{id = 2855} +ENTRY_END +RANGE_END + +; set date/time to Aug 24 07:46:40 (2009). +STEP 5 TIME_PASSES ELAPSE 1251100000 +STEP 6 TRAFFIC ; the initial probe +STEP 7 ASSIGN t0 = ${time} +STEP 8 ASSIGN probe0 = ${range 4800 ${timeout} 5400} + +; the auto probing should have been done now. +STEP 10 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t0} ;;${ctime $t0} +;;last_success: ${$t0} ;;${ctime $t0} +;;next_probe_time: ${$t0 + $probe0} ;;${ctime $t0 + $probe0} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; key prepublished. First poll. 30 days later +STEP 11 TIME_PASSES EVAL ${30*24*3600} +STEP 12 TRAFFIC +STEP 13 ASSIGN t1 = ${time} +STEP 14 ASSIGN probe1 = ${range 4800 ${timeout} 5400} +STEP 15 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t1} ;;${ctime $t1} +;;last_success: ${$t1} ;;${ctime $t1} +;;next_probe_time: ${$t1 + $probe1} ;;${ctime $t1 + $probe1} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; Second poll. 10 days later +STEP 21 TIME_PASSES EVAL ${10*24*3600} +STEP 22 TRAFFIC +STEP 23 ASSIGN t2 = ${time} +STEP 24 ASSIGN probe2 = ${range 4800 ${timeout} 5400} +STEP 25 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t2} ;;${ctime $t2} +;;last_success: ${$t2} ;;${ctime $t2} +;;next_probe_time: ${$t2 + $probe2} ;;${ctime $t2 + $probe2} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; Third poll. 10 days later +STEP 31 TIME_PASSES EVAL ${10*24*3600} +STEP 32 TRAFFIC +STEP 33 ASSIGN t3 = ${time} +STEP 34 ASSIGN probe3 = ${range 4800 ${timeout} 5400} +STEP 35 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t3} ;;${ctime $t3} +;;last_success: ${$t3} ;;${ctime $t3} +;;next_probe_time: ${$t3 + $probe3} ;;${ctime $t3 + $probe3} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; 11 days later, hold down has lapsed. +STEP 41 TIME_PASSES EVAL ${11*24*3600} +STEP 42 TRAFFIC +STEP 43 ASSIGN t4 = ${time} +STEP 44 ASSIGN probe4 = ${range 4800 ${timeout} 5400} +STEP 45 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t4} ;;${ctime $t4} +;;last_success: ${$t4} ;;${ctime $t4} +;;next_probe_time: ${$t4 + $probe4} ;;${ctime $t4 + $probe4} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; 30 days later, the old key is revoked +STEP 51 TIME_PASSES EVAL ${30*24*3600} +STEP 52 TRAFFIC +STEP 53 ASSIGN t5 = ${time} +; no more timeout +STEP 54 ASSIGN probe5 = ${range 0 ${timeout} 0} +STEP 55 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;REVOKED +; The zone has all keys revoked, and is +; considered as if it has no trust anchors. +; the remainder of the file is the last probe. +; to restart the trust anchor, overwrite this file. +; with one containing valid DNSKEYs or DSes. +;;id: example.com. 1 +;;last_queried: ${$t5} ;;${ctime $t5} +;;last_success: ${$t5} ;;${ctime $t5} +;;next_probe_time: 0 ;;${ctime 0} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 385 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55710 (ksk), size = 512b} ;;state=4 [ REVOKED ] ;;count=0 ;;lastchange=${$t5} ;;${ctime $t5} +FILE_END + +; 370 days later, the old key is removed from storage +STEP 61 TIME_PASSES EVAL ${370*24*3600} +STEP 62 TRAFFIC +STEP 63 ASSIGN t6 = ${time} +STEP 64 ASSIGN probe6 = ${range 0 ${timeout} 0} +STEP 65 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;REVOKED +; The zone has all keys revoked, and is +; considered as if it has no trust anchors. +; the remainder of the file is the last probe. +; to restart the trust anchor, overwrite this file. +; with one containing valid DNSKEYs or DSes. +;;id: example.com. 1 +;;last_queried: ${$t5} ;;${ctime $t5} +;;last_success: ${$t5} ;;${ctime $t5} +;;next_probe_time: 0 ;;${ctime 0} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 385 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55710 (ksk), size = 512b} ;;state=4 [ REVOKED ] ;;count=0 ;;lastchange=${$t5} ;;${ctime $t5} +FILE_END + + +SCENARIO_END diff --git a/testdata/autotrust_rollover.rpl b/testdata/autotrust_rollover.rpl new file mode 100644 index 00000000000..0b94418fe30 --- /dev/null +++ b/testdata/autotrust_rollover.rpl @@ -0,0 +1,323 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + log-time-ascii: yes +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +; initial content (say from dig example.com DNSKEY > example.com.key) +AUTOTRUST_FILE example.com +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +AUTOTRUST_END +CONFIG_END + +SCENARIO_BEGIN Test autotrust with prepublish rollover + +; K-ROOT +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR AA +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS k.root-servers.net. +SECTION ADDITIONAL +k.root-servers.net IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 +RANGE_BEGIN 0 10 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. pYGxVLsWUvOp1wSf0iwPap+JnECfC5GAm1lRqy3YEqecNGld7U7x/5Imo3CerbdZrVptUQs2oH0lcjwYJXMnsw== ;{id = 30899} +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 5 2 3600 20090924111500 20090821111500 30899 example.com. J5wxRq0jgwQL6yy530kvo9cHqNAUHV8IF4dvaYZL0bNraO2Oe6dVXqlJl4+cxNHI2TMsstwFPr2Zz8tv6Az2mQ== ;{id = 30899} +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. JsXbS18oyc0zkVaOWGSFdIQuOsZKflT0GraT9afDPoWLCgH4ApF7jNgfJV7Pqy1sTBRajME5IUAhpANwGBuW4A== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 30899 example.com. b/HK231jIQLX8IhlZfup3r0yhpXaasbPE6LzxoEVVvWaTZWcLmeV8jDIcn0qO7Yvs7bIJN20lwVAV0GcHH3hWQ== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 55582 example.com. PCHme1QLoULxqjhg5tMlpR0qJlBfstEUVq18TtNoKQe9le1YhJ9caheXcTWoK+boLhXxg9u6Yyvq8FboQh0OjA== ;{id = 55582} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 and 60946 +RANGE_BEGIN 11 40 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 30899 example.com. rkaCUpTFPWVu4Om5oMTR+39Mct6ZMs56xrE0rbxMMOokfvIQheIxsAEc5BFJeA/2y5WTewl6diCD6yQXCybrDg== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 55582 example.com. CoMon+lWPAsUvgfpCTDPx8Zn8dQpky3lu2O6T+oJ2Mat9a/u1YwGhSQHGPn7ZNG/4vKM97tx84sSlUGz3geD1w== ;{id = 55582} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 60946 example.com. o+Cbs7DcYPYlSLd4hi3vkSVQpXGnKgKSi9MpHGfu1Uahv5190U2DUOxP1du/HOYbf+IHYL8zLbMZjVEG5wgnTg== ;{id = 60946} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 and 60946 (signatures updated) +RANGE_BEGIN 41 50 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 30899 example.com. rkaCUpTFPWVu4Om5oMTR+39Mct6ZMs56xrE0rbxMMOokfvIQheIxsAEc5BFJeA/2y5WTewl6diCD6yQXCybrDg== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 55582 example.com. v/HJbdpeVMpbhwYXrT1EDGpAFMvEgdKQII1cAbP6o8KHYNKDh8TIJ25/pXe3daEXfej6/Z5kpqJ79okPKUoi1Q== ;{id = 55582} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 60946 example.com. HgXol1hdvbomOM1CFRW8qsHd3D0qOnN72EeMHTcpxIBBiuNLKZn4n1M14Voxj3vo0eAMNuG/y7EjQkxKvSsaDA== ;{id = 60946} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582-REVOKED and 60946 +RANGE_BEGIN 51 60 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 385 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55710 (ksk), size = 512b} +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091224111500 20091118111500 30899 example.com. qLKZUJEi3ajSJ4/b7xl0BwhzW6JtjsojpZ+2nUx1PvaeQVoTmyWxjxc2tAmJGcBPqMqzeY470xvyMDvGTOiQCQ== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091224111500 20091118111500 55710 example.com. EW2YB+2yNX9LTNDPVwkcGnRTTx38pOiwBaixdwxmDgqWKXLDLM6Kd2Xv9tveS39RnSZ5H1inRXE55q+rL6Re3g== ;{id = 55710} +; wrong keytag: +;example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091224111500 20091118111500 55582 example.com. nH/6HauVJI4GGz78UoK/38cOOrEqsYZP0jFzfCC3OyIlclVTjAFvjVPlVMGK7sA5Nw1v20YtFTQkXZgbrRuInQ== ;{id = 55582} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091224111500 20091118111500 60946 example.com. xKSBZr4vOsEUKlVoNb6SOV69DM7xFOJI4gPFKq5Tv4APIMJ/9G3odoDmNcLCVyYGzhoDik5hciJnZio6UHgzAA== ;{id = 60946} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 60946 +RANGE_BEGIN 61 70 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20101224111500 20101118111500 30899 example.com. TfFGz1kDtkn3ixbKMJvQDZ0uGw/eW+inIiPqQVPQtO2WiocKrnYnzwv/AqwnFvEar70dF15/zffNIF+ipOS5/g== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20101224111500 20101118111500 60946 example.com. X0Ci//w0czN/J5RvypHGqp56n1tLdapi92ODAqjM7QpZXbSHaJ7wfPG1PZzvdxHUZUVyf8uy2stjg/XoLGHMWA== ;{id = 60946} +ENTRY_END +RANGE_END + +; set date/time to Aug 24 07:46:40 (2009). +STEP 5 TIME_PASSES ELAPSE 1251100000 +STEP 6 TRAFFIC ; the initial probe +STEP 7 ASSIGN t0 = ${time} +STEP 8 ASSIGN probe0 = ${range 4800 ${timeout} 5400} + +; the auto probing should have been done now. +STEP 10 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t0} ;;${ctime $t0} +;;last_success: ${$t0} ;;${ctime $t0} +;;next_probe_time: ${$t0 + $probe0} ;;${ctime $t0 + $probe0} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; key prepublished. First poll. 30 days later +STEP 11 TIME_PASSES EVAL ${30*24*3600} +STEP 12 TRAFFIC +STEP 13 ASSIGN t1 = ${time} +STEP 14 ASSIGN probe1 = ${range 4800 ${timeout} 5400} +STEP 15 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t1} ;;${ctime $t1} +;;last_success: ${$t1} ;;${ctime $t1} +;;next_probe_time: ${$t1 + $probe1} ;;${ctime $t1 + $probe1} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=1 ;;lastchange=${$t1} ;;${ctime $t1} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; Second poll. 10 days later +STEP 21 TIME_PASSES EVAL ${10*24*3600} +STEP 22 TRAFFIC +STEP 23 ASSIGN t2 = ${time} +STEP 24 ASSIGN probe2 = ${range 4800 ${timeout} 5400} +STEP 25 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t2} ;;${ctime $t2} +;;last_success: ${$t2} ;;${ctime $t2} +;;next_probe_time: ${$t2 + $probe2} ;;${ctime $t2 + $probe2} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=2 ;;lastchange=${$t1} ;;${ctime $t1} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; Third poll. 10 days later +STEP 31 TIME_PASSES EVAL ${10*24*3600} +STEP 32 TRAFFIC +STEP 33 ASSIGN t3 = ${time} +STEP 34 ASSIGN probe3 = ${range 4800 ${timeout} 5400} +STEP 35 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t3} ;;${ctime $t3} +;;last_success: ${$t3} ;;${ctime $t3} +;;next_probe_time: ${$t3 + $probe3} ;;${ctime $t3 + $probe3} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=3 ;;lastchange=${$t1} ;;${ctime $t1} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; 11 days later, hold down has lapsed. +STEP 41 TIME_PASSES EVAL ${11*24*3600} +STEP 42 TRAFFIC +STEP 43 ASSIGN t4 = ${time} +STEP 44 ASSIGN probe4 = ${range 4800 ${timeout} 5400} +STEP 45 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t4} ;;${ctime $t4} +;;last_success: ${$t4} ;;${ctime $t4} +;;next_probe_time: ${$t4 + $probe4} ;;${ctime $t4 + $probe4} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t4} ;;${ctime $t4} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; 30 days later, the old key is revoked +STEP 51 TIME_PASSES EVAL ${30*24*3600} +STEP 52 TRAFFIC +STEP 53 ASSIGN t5 = ${time} +STEP 54 ASSIGN probe5 = ${range 4800 ${timeout} 5400} +STEP 55 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t5} ;;${ctime $t5} +;;last_success: ${$t5} ;;${ctime $t5} +;;next_probe_time: ${$t5 + $probe5} ;;${ctime $t5 + $probe5} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t4} ;;${ctime $t4} +example.com. 10800 IN DNSKEY 385 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55710 (ksk), size = 512b} ;;state=4 [ REVOKED ] ;;count=0 ;;lastchange=${$t5} ;;${ctime $t5} +FILE_END + +; 370 days later, the old key is removed from storage +STEP 61 TIME_PASSES EVAL ${370*24*3600} +STEP 62 TRAFFIC +STEP 63 ASSIGN t6 = ${time} +STEP 64 ASSIGN probe6 = ${range 4800 ${timeout} 5400} +STEP 65 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t6} ;;${ctime $t6} +;;last_success: ${$t6} ;;${ctime $t6} +;;next_probe_time: ${$t6 + $probe6} ;;${ctime $t6 + $probe6} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t4} ;;${ctime $t4} +FILE_END + + +SCENARIO_END diff --git a/testdata/autotrust_valid_use.rpl b/testdata/autotrust_valid_use.rpl new file mode 100644 index 00000000000..a6330b143fb --- /dev/null +++ b/testdata/autotrust_valid_use.rpl @@ -0,0 +1,310 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + log-time-ascii: yes +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +; initial content (say from dig example.com DNSKEY > example.com.key) +AUTOTRUST_FILE example.com +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +AUTOTRUST_END +CONFIG_END + +SCENARIO_BEGIN Test autotrust with using a valid key for validation + +; K-ROOT +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR AA +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS k.root-servers.net. +SECTION ADDITIONAL +k.root-servers.net IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 +RANGE_BEGIN 0 10 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. pYGxVLsWUvOp1wSf0iwPap+JnECfC5GAm1lRqy3YEqecNGld7U7x/5Imo3CerbdZrVptUQs2oH0lcjwYJXMnsw== ;{id = 30899} +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 5 2 3600 20090924111500 20090821111500 30899 example.com. J5wxRq0jgwQL6yy530kvo9cHqNAUHV8IF4dvaYZL0bNraO2Oe6dVXqlJl4+cxNHI2TMsstwFPr2Zz8tv6Az2mQ== ;{id = 30899} +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. JsXbS18oyc0zkVaOWGSFdIQuOsZKflT0GraT9afDPoWLCgH4ApF7jNgfJV7Pqy1sTBRajME5IUAhpANwGBuW4A== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 30899 example.com. b/HK231jIQLX8IhlZfup3r0yhpXaasbPE6LzxoEVVvWaTZWcLmeV8jDIcn0qO7Yvs7bIJN20lwVAV0GcHH3hWQ== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20090924111500 20090821111500 55582 example.com. PCHme1QLoULxqjhg5tMlpR0qJlBfstEUVq18TtNoKQe9le1YhJ9caheXcTWoK+boLhXxg9u6Yyvq8FboQh0OjA== ;{id = 55582} +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 and 60946 +RANGE_BEGIN 11 30 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 30899 example.com. rkaCUpTFPWVu4Om5oMTR+39Mct6ZMs56xrE0rbxMMOokfvIQheIxsAEc5BFJeA/2y5WTewl6diCD6yQXCybrDg== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 55582 example.com. CoMon+lWPAsUvgfpCTDPx8Zn8dQpky3lu2O6T+oJ2Mat9a/u1YwGhSQHGPn7ZNG/4vKM97tx84sSlUGz3geD1w== ;{id = 55582} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091024111500 20090921111500 60946 example.com. o+Cbs7DcYPYlSLd4hi3vkSVQpXGnKgKSi9MpHGfu1Uahv5190U2DUOxP1du/HOYbf+IHYL8zLbMZjVEG5wgnTg== ;{id = 60946} +ENTRY_END +RANGE_END + +; probe failures +RANGE_BEGIN 31 40 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA SERVFAIL +SECTION QUESTION +example.com. IN DNSKEY +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA SERVFAIL +SECTION QUESTION +ns.example.com. IN AAAA +ENTRY_END +RANGE_END + +; ns.example.com. KSK 55582 and 60946 (signatures updated) +RANGE_BEGIN 41 50 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. 3600 IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. JsXbS18oyc0zkVaOWGSFdIQuOsZKflT0GraT9afDPoWLCgH4ApF7jNgfJV7Pqy1sTBRajME5IUAhpANwGBuW4A== ;{id = 30899} +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 5 2 3600 20090924111500 20090821111500 30899 example.com. J5wxRq0jgwQL6yy530kvo9cHqNAUHV8IF4dvaYZL0bNraO2Oe6dVXqlJl4+cxNHI2TMsstwFPr2Zz8tv6Az2mQ== ;{id = 30899} +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 5 2 3600 20090924111500 20090821111500 30899 example.com. J5wxRq0jgwQL6yy530kvo9cHqNAUHV8IF4dvaYZL0bNraO2Oe6dVXqlJl4+cxNHI2TMsstwFPr2Zz8tv6Az2mQ== ;{id = 30899} +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 5 3 3600 20090924111500 20090821111500 30899 example.com. JsXbS18oyc0zkVaOWGSFdIQuOsZKflT0GraT9afDPoWLCgH4ApF7jNgfJV7Pqy1sTBRajME5IUAhpANwGBuW4A== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +; KSK 1 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +; KSK 2 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +; ZSK 1 +example.com. 10800 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; signatures +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 30899 example.com. rkaCUpTFPWVu4Om5oMTR+39Mct6ZMs56xrE0rbxMMOokfvIQheIxsAEc5BFJeA/2y5WTewl6diCD6yQXCybrDg== ;{id = 30899} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 55582 example.com. v/HJbdpeVMpbhwYXrT1EDGpAFMvEgdKQII1cAbP6o8KHYNKDh8TIJ25/pXe3daEXfej6/Z5kpqJ79okPKUoi1Q== ;{id = 55582} +example.com. 10800 IN RRSIG DNSKEY 5 2 10800 20091124111500 20091018111500 60946 example.com. HgXol1hdvbomOM1CFRW8qsHd3D0qOnN72EeMHTcpxIBBiuNLKZn4n1M14Voxj3vo0eAMNuG/y7EjQkxKvSsaDA== ;{id = 60946} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 5 3 3600 20091124111500 20091018111500 60946 example.com. pI3iwElQXjhje3SnAfwAG/VwdRskQcLdiApbKdUbR7MIsDUpqVjxIUtSIRu/aXNt8EVA8SwZQXNmTYA2SrrBhA== ;{id = 60946} +ENTRY_END + +RANGE_END + +; set date/time to Aug 24 07:46:40 (2009). +STEP 5 TIME_PASSES ELAPSE 1251100000 +STEP 6 TRAFFIC ; the initial probe +STEP 7 ASSIGN t0 = ${time} +STEP 8 ASSIGN probe0 = ${range 4800 ${timeout} 5400} + +; the auto probing should have been done now. +STEP 10 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t0} ;;${ctime $t0} +;;last_success: ${$t0} ;;${ctime $t0} +;;next_probe_time: ${$t0 + $probe0} ;;${ctime $t0 + $probe0} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; key prepublished. First poll. 30 days later +STEP 11 TIME_PASSES EVAL ${30*24*3600} +STEP 12 TRAFFIC +STEP 13 ASSIGN t1 = ${time} +STEP 14 ASSIGN probe1 = ${range 4800 ${timeout} 5400} +STEP 15 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t1} ;;${ctime $t1} +;;last_success: ${$t1} ;;${ctime $t1} +;;next_probe_time: ${$t1 + $probe1} ;;${ctime $t1 + $probe1} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=1 ;;lastchange=${$t1} ;;${ctime $t1} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; Second poll. 10 days later +STEP 21 TIME_PASSES EVAL ${10*24*3600} +STEP 22 TRAFFIC +STEP 23 ASSIGN t2 = ${time} +STEP 24 ASSIGN probe2 = ${range 4800 ${timeout} 5400} +STEP 25 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t2} ;;${ctime $t2} +;;last_success: ${$t2} ;;${ctime $t2} +;;next_probe_time: ${$t2 + $probe2} ;;${ctime $t2 + $probe2} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=2 ;;lastchange=${$t1} ;;${ctime $t1} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; put this almost one hour before expiration so that the next query arrives +; before the next poll timer. +; Make this probe fail to keep DNSKEY out of the cache +; Third poll. 10 days later +STEP 31 TIME_PASSES EVAL ${ ${20*24*3600} - 3000 } +STEP 32 TRAFFIC +STEP 33 ASSIGN t3 = ${time} +STEP 34 ASSIGN probe3 = ${range 3200 ${timeout} 3600} +STEP 35 CHECK_AUTOTRUST example.com +FILE_BEGIN +; autotrust trust anchor file +;;id: example.com. 1 +;;last_queried: ${$t2} ;;${ctime $t2} +;;last_success: ${$t2} ;;${ctime $t2} +;;next_probe_time: ${$t2 + $probe2} ;;${ctime $t2 + $probe2} +;;query_failed: 0 +;;query_interval: 5400 +;;retry_time: 3600 +example.com. 10800 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} ;;state=1 [ ADDPEND ] ;;count=2 ;;lastchange=${$t1} ;;${ctime $t1} +example.com. 10800 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [ VALID ] ;;count=0 ;;lastchange=${$t0} ;;${ctime $t0} +FILE_END + +; 3010 seconds later, hold down has lapsed. +; but the probe timer does not expire yet! +; key 60946 becomes valid. Use it. +; check this with a data query. +STEP 41 TIME_PASSES EVAL ${3010} +STEP 42 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; Note the data is signed with the newly valid KSK to make sure it can be used. +STEP 43 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 5 3 3600 20091124111500 20091018111500 60946 example.com. pI3iwElQXjhje3SnAfwAG/VwdRskQcLdiApbKdUbR7MIsDUpqVjxIUtSIRu/aXNt8EVA8SwZQXNmTYA2SrrBhA== ;{id = 60946} +ENTRY_END + +SCENARIO_END diff --git a/testdata/black_data.rpl b/testdata/black_data.rpl new file mode 100644 index 00000000000..2ca75793973 --- /dev/null +++ b/testdata/black_data.rpl @@ -0,0 +1,303 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with blacklist for data response + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.blabla.com. IN A +SECTION ANSWER +ns.blabla.com. IN A 1.2.3.5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.blabla.com. IN AAAA +SECTION AUTHORITY +com. IN SOA com. com. 2009100100 28800 7200 604800 3600 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +; no ns.blabla.com, try that later +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20030926134150 20030829134150 2854 example.com. AKJ3xUBdSrCiOFkYajsy93d+h06rewpbmBHItTkL8R/26rw57b1gCIg= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AHNj99mBmP4np19V01nSq990ZIFlIiLWoeHijm/HcOG/o8+DuIp4fL8= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AHNj99mBmP4np19V01nSq990ZIFlIiLWoeHijm/HcOG/o8+DuIp4fL8= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +SECTION ADDITIONAL +ns.example.com. IN NSEC oof.example.com. NSEC RRSIG A +ns.example.com. 3600 IN RRSIG NSEC 3 3 3600 20030926134150 20030829134150 2854 example.com. ACFVLLBtuSX/1z3461tbOwDz9zTHe5S9DbVtwnSO1f2x06fYbMpzSDE= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +; make priming query succeed +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +;example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20030926134150 20030829134150 2854 example.com. AG21xE8CFQzTq6XtHErg28b9EAmqPsoYCUcFPEAoAjFybM6AY4/bMOo= ;{id = 2854} +SECTION AUTHORITY +;example.com. IN NS ns.example.com. +;example.com. IN NS ns.blabla.com. +;example.com. 3600 IN RRSIG NS 3 2 3600 20030926134150 20030829134150 2854 example.com. ACiWu7zjBHqgEX3iUoOF7rfpOmIAHj1npKQ+XDIaNlmdkfJxoCwFl04= ;{id = 2854} +SECTION ADDITIONAL +;ns.example.com. IN A 1.2.3.4 +;ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. ACmAsKTf7hqDaYK8CQ7FL1cGYPW+blTCnzZGkExFtEUAGrHeze87o+A= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AGj9kE8oW3OhOLhkmJ3HBaNIOpvGf3S8zSd5gWmhpxAMc5hh6cxZfpQ= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20030926134150 20030829134150 2854 example.com. ACHETweBNPgbmRoNRdKvxuw4X9qNUUTEpSuwV+HhuiBE83gbB98asAc= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AGvu9A/nGsbatxJCmnObioIhKg2Tm0Apr0eo+DO1kIDrAHco/bt/EdY= ;{id = 2854} +ENTRY_END +RANGE_END + +; ns.blabla.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. AAJHNhPYVG6+550zQga9ZgV8McQZHLboOWjfbdiq2ZC+gUcQeQDDlFs= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +SECTION ADDITIONAL +ns.example.com. IN NSEC oof.example.com. NSEC RRSIG A +ns.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. ABhDNtJramb2a4R1SK5gb/CTYJybQts6mZ++z3kLiwsrUSZInA4ikeQ= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. AAJHNhPYVG6+550zQga9ZgV8McQZHLboOWjfbdiq2ZC+gUcQeQDDlFs= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. AAJHNhPYVG6+550zQga9ZgV8McQZHLboOWjfbdiq2ZC+gUcQeQDDlFs= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. AAJHNhPYVG6+550zQga9ZgV8McQZHLboOWjfbdiq2ZC+gUcQeQDDlFs= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +ENTRY_END + +; remove pending ns.blabla.com AAAA msg +STEP 30 QUERY +ENTRY_BEGIN +REPLY RD DO CD +SECTION QUESTION +ns.blabla.com. IN AAAA +ENTRY_END + +; recursion happens here. +STEP 40 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD CD RA NOERROR +SECTION QUESTION +ns.blabla.com. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +com. IN SOA com. com. 2009100100 28800 7200 604800 3600 +ENTRY_END + +SCENARIO_END diff --git a/testdata/black_dnskey.rpl b/testdata/black_dnskey.rpl new file mode 100644 index 00000000000..b75e46a7cc1 --- /dev/null +++ b/testdata/black_dnskey.rpl @@ -0,0 +1,506 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with blacklist for DNSKEY response +; DNSKEY not for prime but further down the chain of trust +; data response also needs a blacklist action. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.blabla.com. IN A +SECTION ANSWER +ns.blabla.com. IN A 1.2.3.5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.blabla.com. IN AAAA +SECTION AUTHORITY +com. IN SOA com. com. 2009100100 28800 7200 604800 3600 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.foo.com. IN A +SECTION ANSWER +ns.foo.com. IN A 1.2.4.7 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.foo.com. IN AAAA +SECTION AUTHORITY +com. IN SOA com. com. 2009100100 28800 7200 604800 3600 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +; no ns.blabla.com, try that later +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20030926134150 20030829134150 2854 example.com. AKJ3xUBdSrCiOFkYajsy93d+h06rewpbmBHItTkL8R/26rw57b1gCIg= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AHNj99mBmP4np19V01nSq990ZIFlIiLWoeHijm/HcOG/o8+DuIp4fL8= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AHNj99mBmP4np19V01nSq990ZIFlIiLWoeHijm/HcOG/o8+DuIp4fL8= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +SECTION ADDITIONAL +ns.example.com. IN NSEC oof.example.com. NSEC RRSIG A +ns.example.com. 3600 IN RRSIG NSEC 3 3 3600 20030926134150 20030829134150 2854 example.com. ACFVLLBtuSX/1z3461tbOwDz9zTHe5S9DbVtwnSO1f2x06fYbMpzSDE= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +; make priming query succeed +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +;example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20030926134150 20030829134150 2854 example.com. AG21xE8CFQzTq6XtHErg28b9EAmqPsoYCUcFPEAoAjFybM6AY4/bMOo= ;{id = 2854} +SECTION AUTHORITY +;example.com. IN NS ns.example.com. +;example.com. IN NS ns.blabla.com. +;example.com. 3600 IN RRSIG NS 3 2 3600 20030926134150 20030829134150 2854 example.com. ACiWu7zjBHqgEX3iUoOF7rfpOmIAHj1npKQ+XDIaNlmdkfJxoCwFl04= ;{id = 2854} +SECTION ADDITIONAL +;ns.example.com. IN A 1.2.3.4 +;ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. ACmAsKTf7hqDaYK8CQ7FL1cGYPW+blTCnzZGkExFtEUAGrHeze87o+A= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AGj9kE8oW3OhOLhkmJ3HBaNIOpvGf3S8zSd5gWmhpxAMc5hh6cxZfpQ= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20030926134150 20030829134150 2854 example.com. ACHETweBNPgbmRoNRdKvxuw4X9qNUUTEpSuwV+HhuiBE83gbB98asAc= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AGvu9A/nGsbatxJCmnObioIhKg2Tm0Apr0eo+DO1kIDrAHco/bt/EdY= ;{id = 2854} +ENTRY_END + +; DS request +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION ANSWER +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. AKslZ9oXcoyeOkPfGkTB3/hxnpdgU5ahzElLyK6B0n6+BdIXeirIEtE= ;{id = 2854} +;sub.example.com. 3600 IN RRSIG DS 3 3 3600 20030926134150 20030829134150 2854 example.com. AAT/7XwtMjHiT1GFHfV6Wvv4n+oOkqxllNdf9bLnpTHw/8h586yBgwg= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. IN NS ns.foo.com. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. AKslZ9oXcoyeOkPfGkTB3/hxnpdgU5ahzElLyK6B0n6+BdIXeirIEtE= ;{id = 2854} +;sub.example.com. 3600 IN RRSIG DS 3 3 3600 20030926134150 20030829134150 2854 example.com. AAT/7XwtMjHiT1GFHfV6Wvv4n+oOkqxllNdf9bLnpTHw/8h586yBgwg= ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.4.6 +ENTRY_END + +RANGE_END + +; ns.blabla.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. AAJHNhPYVG6+550zQga9ZgV8McQZHLboOWjfbdiq2ZC+gUcQeQDDlFs= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +SECTION ADDITIONAL +ns.example.com. IN NSEC oof.example.com. NSEC RRSIG A +ns.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. ABhDNtJramb2a4R1SK5gb/CTYJybQts6mZ++z3kLiwsrUSZInA4ikeQ= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. AAJHNhPYVG6+550zQga9ZgV8McQZHLboOWjfbdiq2ZC+gUcQeQDDlFs= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. AAJHNhPYVG6+550zQga9ZgV8McQZHLboOWjfbdiq2ZC+gUcQeQDDlFs= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +ENTRY_END + +; DS request +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION ANSWER +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. AKslZ9oXcoyeOkPfGkTB3/hxnpdgU5ahzElLyK6B0n6+BdIXeirIEtE= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. IN NS ns.foo.com. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. AKslZ9oXcoyeOkPfGkTB3/hxnpdgU5ahzElLyK6B0n6+BdIXeirIEtE= ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.4.6 +ENTRY_END + +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.4.6 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20030926134150 20030829134150 30899 sub.example.com. g+YoDwrCF75YCFyqYoxlF+/mNfcscnuZ6LfmfBgPLohlvCCC7jYj/wkc2fxAl3MEK0CriWkHp1hw0QQYkmbbKw== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. IN NS ns.foo.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20030926134150 20030829134150 30899 sub.example.com. VCDq+gfZHuziE81Uypxm2va4eXCtoD8F8YKkwNo8laMNUcXh/hvGdbHKXMMghwuJXgxLh89Diu5kywBVwb/AIg== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.4.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20030926134150 20030829134150 30899 sub.example.com. l3wjlbDU2y7ECix6t1pp5Rtz+qFlADRMohcRsCrnD9b99IoOL0/cTpvvf2V1VTJveIibFGhbcHTuCqAQ4G4FKA== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.sub.example.com. IN A +SECTION ANSWER +ns.sub.example.com. IN A 1.2.4.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20030926134150 20030829134150 30899 sub.example.com. l3wjlbDU2y7ECix6t1pp5Rtz+qFlADRMohcRsCrnD9b99IoOL0/cTpvvf2V1VTJveIibFGhbcHTuCqAQ4G4FKA== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.sub.example.com. IN AAAA +SECTION AUTHORITY +ns.sub.example.com. IN NSEC nt.sub.example.com. NSEC RRSIG A +ns.sub.example.com. 3600 IN RRSIG NSEC 5 4 3600 20030926134150 20030829134150 30899 sub.example.com. eVe3iQS2/a1Y57AA2QSlMU/z31xaJ2mwUU36PZh8vlv6shPpQywAT70JdX6+ZsuliRpsbY6crkVXTXJ2qpKTiQ== ;{id = 30899} +sub.example.com. IN SOA sub.example.com. hostmaster.sub.example.com. 1 2 3 4 5 +sub.example.com. 3600 IN RRSIG SOA 5 3 3600 20030926134150 20030829134150 30899 sub.example.com. vEX2n1CksMr5jPq9d2BQJMIDwxaXdWlY5mYg+PBmOFI4xngFMKTsXa/+SfJy2SiqAgHTDI6joIo30AdQJsjdHA== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 10.20.30.40 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20030926134150 20030829134150 30899 sub.example.com. dBK6JOkKlp2G+f7mhInKnQM6DUBnEziTS+KpXzQ/5HT8/h9XkryOt4vAJKGCz0Ew3qRqjLgylsbGrcuxmIO9jA== ;{id = 30899} +ENTRY_END + +RANGE_END + +; ns.foo.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.4.7 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. IN NS ns.foo.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. hJ3nkrfyBwPcfpwc9wEwzhF5+ZKUddKBHQuZuHPZBjBwb1BsT7B7ryadttbGE3keQJiwNmK9AqvE0Zb+WkDceg== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.4.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. fMRshSYDWgvGAwc24Lzg6746jnoG5shlK+o9CgzU7CQbkeNWmj3oO/0TJGP/zxp52JiDBpzRuTmBlrcJYV/gBA== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.sub.example.com. IN A +SECTION ANSWER +ns.sub.example.com. IN A 1.2.4.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. fMRshSYDWgvGAwc24Lzg6746jnoG5shlK+o9CgzU7CQbkeNWmj3oO/0TJGP/zxp52JiDBpzRuTmBlrcJYV/gBA== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.sub.example.com. IN AAAA +SECTION AUTHORITY +ns.sub.example.com. IN NSEC nt.sub.example.com. NSEC RRSIG A +ns.sub.example.com. 3600 IN RRSIG NSEC 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. qwUibvlPTFnxgiyCNtEJCYqJIgA8WFDqypmsO6TSYje2Rqhq4AaWEVxQwU4bdjmipCGVqtlP8mMyMQHaYNMGKA== ;{id = 30899} +sub.example.com. IN SOA sub.example.com. hostmaster.sub.example.com. 1 2 3 4 5 +sub.example.com. 3600 IN RRSIG SOA 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. sZQEMd0ys2mxPRajzBuvy4XdLNVvXMmJSnmfTHUL41d9IxbGN/ifpiIWs2MXOFPnbab05aYadrzZpT/cpDTxmQ== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 10.20.30.40 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. deNzEy9Hq+6gDZhafC0M7UDuRBm51AA1/FAIauAitNuQlYUzOvWLVHFQ95bn308rCVPqrb4rFDV+gNzxkzm1rw== ;{id = 30899} +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 10.20.30.40 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. deNzEy9Hq+6gDZhafC0M7UDuRBm51AA1/FAIauAitNuQlYUzOvWLVHFQ95bn308rCVPqrb4rFDV+gNzxkzm1rw== ;{id = 30899} +ENTRY_END + +; remove pending ns.blabla.com AAAA msg +STEP 30 QUERY +ENTRY_BEGIN +REPLY RD DO CD +SECTION QUESTION +ns.blabla.com. IN AAAA +ENTRY_END + +; recursion happens here. +STEP 40 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD CD RA NOERROR +SECTION QUESTION +ns.blabla.com. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +com. IN SOA com. com. 2009100100 28800 7200 604800 3600 +ENTRY_END + +SCENARIO_END diff --git a/testdata/black_ds.rpl b/testdata/black_ds.rpl new file mode 100644 index 00000000000..fd02a8806cd --- /dev/null +++ b/testdata/black_ds.rpl @@ -0,0 +1,416 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with blacklist for DS response + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.blabla.com. IN A +SECTION ANSWER +ns.blabla.com. IN A 1.2.3.5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.blabla.com. IN AAAA +SECTION AUTHORITY +com. IN SOA com. com. 2009100100 28800 7200 604800 3600 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +; no ns.blabla.com, try that later +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20030926134150 20030829134150 2854 example.com. AKJ3xUBdSrCiOFkYajsy93d+h06rewpbmBHItTkL8R/26rw57b1gCIg= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AHNj99mBmP4np19V01nSq990ZIFlIiLWoeHijm/HcOG/o8+DuIp4fL8= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AHNj99mBmP4np19V01nSq990ZIFlIiLWoeHijm/HcOG/o8+DuIp4fL8= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +SECTION ADDITIONAL +ns.example.com. IN NSEC oof.example.com. NSEC RRSIG A +ns.example.com. 3600 IN RRSIG NSEC 3 3 3600 20030926134150 20030829134150 2854 example.com. ACFVLLBtuSX/1z3461tbOwDz9zTHe5S9DbVtwnSO1f2x06fYbMpzSDE= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +; make priming query succeed +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +;example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20030926134150 20030829134150 2854 example.com. AG21xE8CFQzTq6XtHErg28b9EAmqPsoYCUcFPEAoAjFybM6AY4/bMOo= ;{id = 2854} +SECTION AUTHORITY +;example.com. IN NS ns.example.com. +;example.com. IN NS ns.blabla.com. +;example.com. 3600 IN RRSIG NS 3 2 3600 20030926134150 20030829134150 2854 example.com. ACiWu7zjBHqgEX3iUoOF7rfpOmIAHj1npKQ+XDIaNlmdkfJxoCwFl04= ;{id = 2854} +SECTION ADDITIONAL +;ns.example.com. IN A 1.2.3.4 +;ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. ACmAsKTf7hqDaYK8CQ7FL1cGYPW+blTCnzZGkExFtEUAGrHeze87o+A= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AGj9kE8oW3OhOLhkmJ3HBaNIOpvGf3S8zSd5gWmhpxAMc5hh6cxZfpQ= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20030926134150 20030829134150 2854 example.com. ACHETweBNPgbmRoNRdKvxuw4X9qNUUTEpSuwV+HhuiBE83gbB98asAc= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AGvu9A/nGsbatxJCmnObioIhKg2Tm0Apr0eo+DO1kIDrAHco/bt/EdY= ;{id = 2854} +ENTRY_END + +; DS request +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION ANSWER +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20030926134150 20030829134150 2854 example.com. AAT/7XwtMjHiT1GFHfV6Wvv4n+oOkqxllNdf9bLnpTHw/8h586yBgwg= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. IN NS ns.foo.com. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20030926134150 20030829134150 2854 example.com. AAT/7XwtMjHiT1GFHfV6Wvv4n+oOkqxllNdf9bLnpTHw/8h586yBgwg= ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.4.6 +ENTRY_END + +RANGE_END + +; ns.blabla.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. AAJHNhPYVG6+550zQga9ZgV8McQZHLboOWjfbdiq2ZC+gUcQeQDDlFs= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +SECTION ADDITIONAL +ns.example.com. IN NSEC oof.example.com. NSEC RRSIG A +ns.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. ABhDNtJramb2a4R1SK5gb/CTYJybQts6mZ++z3kLiwsrUSZInA4ikeQ= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. AAJHNhPYVG6+550zQga9ZgV8McQZHLboOWjfbdiq2ZC+gUcQeQDDlFs= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. AAJHNhPYVG6+550zQga9ZgV8McQZHLboOWjfbdiq2ZC+gUcQeQDDlFs= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +ENTRY_END + +; DS request +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION ANSWER +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. AKslZ9oXcoyeOkPfGkTB3/hxnpdgU5ahzElLyK6B0n6+BdIXeirIEtE= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. IN NS ns.foo.com. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. AKslZ9oXcoyeOkPfGkTB3/hxnpdgU5ahzElLyK6B0n6+BdIXeirIEtE= ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.4.6 +ENTRY_END + +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.4.6 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. IN NS ns.foo.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. hJ3nkrfyBwPcfpwc9wEwzhF5+ZKUddKBHQuZuHPZBjBwb1BsT7B7ryadttbGE3keQJiwNmK9AqvE0Zb+WkDceg== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.4.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. fMRshSYDWgvGAwc24Lzg6746jnoG5shlK+o9CgzU7CQbkeNWmj3oO/0TJGP/zxp52JiDBpzRuTmBlrcJYV/gBA== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.sub.example.com. IN A +SECTION ANSWER +ns.sub.example.com. IN A 1.2.4.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. fMRshSYDWgvGAwc24Lzg6746jnoG5shlK+o9CgzU7CQbkeNWmj3oO/0TJGP/zxp52JiDBpzRuTmBlrcJYV/gBA== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.sub.example.com. IN AAAA +SECTION AUTHORITY +ns.sub.example.com. IN NSEC nt.sub.example.com. NSEC RRSIG A +ns.sub.example.com. 3600 IN RRSIG NSEC 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. qwUibvlPTFnxgiyCNtEJCYqJIgA8WFDqypmsO6TSYje2Rqhq4AaWEVxQwU4bdjmipCGVqtlP8mMyMQHaYNMGKA== ;{id = 30899} +sub.example.com. IN SOA sub.example.com. hostmaster.sub.example.com. 1 2 3 4 5 +sub.example.com. 3600 IN RRSIG SOA 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. sZQEMd0ys2mxPRajzBuvy4XdLNVvXMmJSnmfTHUL41d9IxbGN/ifpiIWs2MXOFPnbab05aYadrzZpT/cpDTxmQ== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 10.20.30.40 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. deNzEy9Hq+6gDZhafC0M7UDuRBm51AA1/FAIauAitNuQlYUzOvWLVHFQ95bn308rCVPqrb4rFDV+gNzxkzm1rw== ;{id = 30899} +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 10.20.30.40 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. deNzEy9Hq+6gDZhafC0M7UDuRBm51AA1/FAIauAitNuQlYUzOvWLVHFQ95bn308rCVPqrb4rFDV+gNzxkzm1rw== ;{id = 30899} +ENTRY_END + +; remove pending ns.blabla.com AAAA msg +STEP 30 QUERY +ENTRY_BEGIN +REPLY RD DO CD +SECTION QUESTION +ns.blabla.com. IN AAAA +ENTRY_END + +; recursion happens here. +STEP 40 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD CD RA NOERROR +SECTION QUESTION +ns.blabla.com. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +com. IN SOA com. com. 2009100100 28800 7200 604800 3600 +ENTRY_END + +SCENARIO_END diff --git a/testdata/black_ds_entry.rpl b/testdata/black_ds_entry.rpl new file mode 100644 index 00000000000..b0e2cd6b96d --- /dev/null +++ b/testdata/black_ds_entry.rpl @@ -0,0 +1,626 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with blacked key entry for DS and further queries +; a DS record fails. +; the blacklist action does not help. +; the further queries should not generate traffic to the authority any more. +; until the key entry expires. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.blabla.com. IN A +SECTION ANSWER +ns.blabla.com. IN A 1.2.3.5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.blabla.com. IN AAAA +SECTION AUTHORITY +com. IN SOA com. com. 2009100100 28800 7200 604800 3600 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.foo.com. IN A +SECTION ANSWER +ns.foo.com. IN A 1.2.4.7 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.foo.com. IN AAAA +SECTION AUTHORITY +com. IN SOA com. com. 2009100100 28800 7200 604800 3600 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +;example.com. IN NS ns.blabla.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +;example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20030926134150 20030829134150 2854 example.com. AKJ3xUBdSrCiOFkYajsy93d+h06rewpbmBHItTkL8R/26rw57b1gCIg= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AHNj99mBmP4np19V01nSq990ZIFlIiLWoeHijm/HcOG/o8+DuIp4fL8= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AHNj99mBmP4np19V01nSq990ZIFlIiLWoeHijm/HcOG/o8+DuIp4fL8= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +SECTION ADDITIONAL +ns.example.com. IN NSEC oof.example.com. NSEC RRSIG A +ns.example.com. 3600 IN RRSIG NSEC 3 3 3600 20030926134150 20030829134150 2854 example.com. ACFVLLBtuSX/1z3461tbOwDz9zTHe5S9DbVtwnSO1f2x06fYbMpzSDE= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +; make priming query succeed +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +;example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20030926134150 20030829134150 2854 example.com. AG21xE8CFQzTq6XtHErg28b9EAmqPsoYCUcFPEAoAjFybM6AY4/bMOo= ;{id = 2854} +SECTION AUTHORITY +;example.com. IN NS ns.example.com. +;example.com. IN NS ns.blabla.com. +;example.com. 3600 IN RRSIG NS 3 2 3600 20030926134150 20030829134150 2854 example.com. ACiWu7zjBHqgEX3iUoOF7rfpOmIAHj1npKQ+XDIaNlmdkfJxoCwFl04= ;{id = 2854} +SECTION ADDITIONAL +;ns.example.com. IN A 1.2.3.4 +;ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. ACmAsKTf7hqDaYK8CQ7FL1cGYPW+blTCnzZGkExFtEUAGrHeze87o+A= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AGj9kE8oW3OhOLhkmJ3HBaNIOpvGf3S8zSd5gWmhpxAMc5hh6cxZfpQ= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +;example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20030926134150 20030829134150 2854 example.com. ACHETweBNPgbmRoNRdKvxuw4X9qNUUTEpSuwV+HhuiBE83gbB98asAc= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AGvu9A/nGsbatxJCmnObioIhKg2Tm0Apr0eo+DO1kIDrAHco/bt/EdY= ;{id = 2854} +ENTRY_END + +; DS request +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION ANSWER +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +;sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. AKslZ9oXcoyeOkPfGkTB3/hxnpdgU5ahzElLyK6B0n6+BdIXeirIEtE= ;{id = 2854} +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20030926134150 20030829134150 2854 example.com. AAT/7XwtMjHiT1GFHfV6Wvv4n+oOkqxllNdf9bLnpTHw/8h586yBgwg= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +;sub.example.com. IN NS ns.foo.com. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +;sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. AKslZ9oXcoyeOkPfGkTB3/hxnpdgU5ahzElLyK6B0n6+BdIXeirIEtE= ;{id = 2854} +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20030926134150 20030829134150 2854 example.com. AAT/7XwtMjHiT1GFHfV6Wvv4n+oOkqxllNdf9bLnpTHw/8h586yBgwg= ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.4.6 +ENTRY_END + +RANGE_END + +; ns.blabla.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. AAJHNhPYVG6+550zQga9ZgV8McQZHLboOWjfbdiq2ZC+gUcQeQDDlFs= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +SECTION ADDITIONAL +ns.example.com. IN NSEC oof.example.com. NSEC RRSIG A +ns.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. ABhDNtJramb2a4R1SK5gb/CTYJybQts6mZ++z3kLiwsrUSZInA4ikeQ= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. AAJHNhPYVG6+550zQga9ZgV8McQZHLboOWjfbdiq2ZC+gUcQeQDDlFs= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. AAJHNhPYVG6+550zQga9ZgV8McQZHLboOWjfbdiq2ZC+gUcQeQDDlFs= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +ENTRY_END + +; DS request +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION ANSWER +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. AKslZ9oXcoyeOkPfGkTB3/hxnpdgU5ahzElLyK6B0n6+BdIXeirIEtE= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +;sub.example.com. IN NS ns.foo.com. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. AKslZ9oXcoyeOkPfGkTB3/hxnpdgU5ahzElLyK6B0n6+BdIXeirIEtE= ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.4.6 +ENTRY_END + +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.4.6 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20030926134150 20030829134150 30899 sub.example.com. g+YoDwrCF75YCFyqYoxlF+/mNfcscnuZ6LfmfBgPLohlvCCC7jYj/wkc2fxAl3MEK0CriWkHp1hw0QQYkmbbKw== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +;sub.example.com. IN NS ns.foo.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20030926134150 20030829134150 30899 sub.example.com. VCDq+gfZHuziE81Uypxm2va4eXCtoD8F8YKkwNo8laMNUcXh/hvGdbHKXMMghwuJXgxLh89Diu5kywBVwb/AIg== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.4.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20030926134150 20030829134150 30899 sub.example.com. l3wjlbDU2y7ECix6t1pp5Rtz+qFlADRMohcRsCrnD9b99IoOL0/cTpvvf2V1VTJveIibFGhbcHTuCqAQ4G4FKA== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.sub.example.com. IN A +SECTION ANSWER +ns.sub.example.com. IN A 1.2.4.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20030926134150 20030829134150 30899 sub.example.com. l3wjlbDU2y7ECix6t1pp5Rtz+qFlADRMohcRsCrnD9b99IoOL0/cTpvvf2V1VTJveIibFGhbcHTuCqAQ4G4FKA== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.sub.example.com. IN AAAA +SECTION AUTHORITY +ns.sub.example.com. IN NSEC nt.sub.example.com. NSEC RRSIG A +ns.sub.example.com. 3600 IN RRSIG NSEC 5 4 3600 20030926134150 20030829134150 30899 sub.example.com. eVe3iQS2/a1Y57AA2QSlMU/z31xaJ2mwUU36PZh8vlv6shPpQywAT70JdX6+ZsuliRpsbY6crkVXTXJ2qpKTiQ== ;{id = 30899} +sub.example.com. IN SOA sub.example.com. hostmaster.sub.example.com. 1 2 3 4 5 +sub.example.com. 3600 IN RRSIG SOA 5 3 3600 20030926134150 20030829134150 30899 sub.example.com. vEX2n1CksMr5jPq9d2BQJMIDwxaXdWlY5mYg+PBmOFI4xngFMKTsXa/+SfJy2SiqAgHTDI6joIo30AdQJsjdHA== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 10.20.30.40 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20030926134150 20030829134150 30899 sub.example.com. dBK6JOkKlp2G+f7mhInKnQM6DUBnEziTS+KpXzQ/5HT8/h9XkryOt4vAJKGCz0Ew3qRqjLgylsbGrcuxmIO9jA== ;{id = 30899} +ENTRY_END + +RANGE_END + +; ns.foo.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.4.7 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +;sub.example.com. IN NS ns.foo.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. hJ3nkrfyBwPcfpwc9wEwzhF5+ZKUddKBHQuZuHPZBjBwb1BsT7B7ryadttbGE3keQJiwNmK9AqvE0Zb+WkDceg== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.4.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. fMRshSYDWgvGAwc24Lzg6746jnoG5shlK+o9CgzU7CQbkeNWmj3oO/0TJGP/zxp52JiDBpzRuTmBlrcJYV/gBA== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.sub.example.com. IN A +SECTION ANSWER +ns.sub.example.com. IN A 1.2.4.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. fMRshSYDWgvGAwc24Lzg6746jnoG5shlK+o9CgzU7CQbkeNWmj3oO/0TJGP/zxp52JiDBpzRuTmBlrcJYV/gBA== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.sub.example.com. IN AAAA +SECTION AUTHORITY +ns.sub.example.com. IN NSEC nt.sub.example.com. NSEC RRSIG A +ns.sub.example.com. 3600 IN RRSIG NSEC 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. qwUibvlPTFnxgiyCNtEJCYqJIgA8WFDqypmsO6TSYje2Rqhq4AaWEVxQwU4bdjmipCGVqtlP8mMyMQHaYNMGKA== ;{id = 30899} +sub.example.com. IN SOA sub.example.com. hostmaster.sub.example.com. 1 2 3 4 5 +sub.example.com. 3600 IN RRSIG SOA 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. sZQEMd0ys2mxPRajzBuvy4XdLNVvXMmJSnmfTHUL41d9IxbGN/ifpiIWs2MXOFPnbab05aYadrzZpT/cpDTxmQ== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 10.20.30.40 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. deNzEy9Hq+6gDZhafC0M7UDuRBm51AA1/FAIauAitNuQlYUzOvWLVHFQ95bn308rCVPqrb4rFDV+gNzxkzm1rw== ;{id = 30899} +ENTRY_END +RANGE_END + +; ns.sub.example.com. +; This is for after, so only new queries, no requeries allowed. +RANGE_BEGIN 100 200 + ADDRESS 1.2.4.6 + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ftp.sub.example.com. IN A +SECTION ANSWER +ftp.sub.example.com. IN A 10.20.30.46 +ftp.sub.example.com. 3600 IN RRSIG A 5 4 3600 20030926134150 20030829134150 30899 sub.example.com. nbxk6SiooKsUeVm/ZGskrxKwhOSWdJt9ly9X6Hqji4DKpBskM6bqulmTt/xZ/3G4ZOguYBeiTp8qwlWjl7VoSQ== ;{id = 30899} +ENTRY_END + +RANGE_END + +; ns.example.com. +; fixed version +RANGE_BEGIN 200 300 + ADDRESS 1.2.3.4 +; DS request +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION ANSWER +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. AKslZ9oXcoyeOkPfGkTB3/hxnpdgU5ahzElLyK6B0n6+BdIXeirIEtE= ;{id = 2854} +ENTRY_END + +RANGE_END + +; ns.sub.example.com. +; fixed version +RANGE_BEGIN 200 300 + ADDRESS 1.2.4.6 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +;sub.example.com. IN NS ns.foo.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. hJ3nkrfyBwPcfpwc9wEwzhF5+ZKUddKBHQuZuHPZBjBwb1BsT7B7ryadttbGE3keQJiwNmK9AqvE0Zb+WkDceg== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.4.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. fMRshSYDWgvGAwc24Lzg6746jnoG5shlK+o9CgzU7CQbkeNWmj3oO/0TJGP/zxp52JiDBpzRuTmBlrcJYV/gBA== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.sub.example.com. IN A +SECTION ANSWER +ns.sub.example.com. IN A 1.2.4.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. fMRshSYDWgvGAwc24Lzg6746jnoG5shlK+o9CgzU7CQbkeNWmj3oO/0TJGP/zxp52JiDBpzRuTmBlrcJYV/gBA== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.sub.example.com. IN AAAA +SECTION AUTHORITY +ns.sub.example.com. IN NSEC nt.sub.example.com. NSEC RRSIG A +ns.sub.example.com. 3600 IN RRSIG NSEC 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. qwUibvlPTFnxgiyCNtEJCYqJIgA8WFDqypmsO6TSYje2Rqhq4AaWEVxQwU4bdjmipCGVqtlP8mMyMQHaYNMGKA== ;{id = 30899} +sub.example.com. IN SOA sub.example.com. hostmaster.sub.example.com. 1 2 3 4 5 +sub.example.com. 3600 IN RRSIG SOA 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. sZQEMd0ys2mxPRajzBuvy4XdLNVvXMmJSnmfTHUL41d9IxbGN/ifpiIWs2MXOFPnbab05aYadrzZpT/cpDTxmQ== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 10.20.30.40 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. deNzEy9Hq+6gDZhafC0M7UDuRBm51AA1/FAIauAitNuQlYUzOvWLVHFQ95bn308rCVPqrb4rFDV+gNzxkzm1rw== ;{id = 30899} +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +ENTRY_END + +; no more outgoing traffic possible. +STEP 110 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +ftp.sub.example.com. IN A +ENTRY_END + +STEP 120 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +ftp.sub.example.com. IN A +SECTION ANSWER +ENTRY_END + +; wait for timeout seconds. +STEP 130 TIME_PASSES ELAPSE 901 + +STEP 210 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 220 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 10.20.30.40 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. deNzEy9Hq+6gDZhafC0M7UDuRBm51AA1/FAIauAitNuQlYUzOvWLVHFQ95bn308rCVPqrb4rFDV+gNzxkzm1rw== ;{id = 30899} +ENTRY_END + + +SCENARIO_END diff --git a/testdata/black_ent.rpl b/testdata/black_ent.rpl new file mode 100644 index 00000000000..8a6d3c12e84 --- /dev/null +++ b/testdata/black_ent.rpl @@ -0,0 +1,449 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with blacklist for ENT response +; 'ENT' Empty Non Terminal +; which needs a valid NSEC(3) proof. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.blabla.com. IN A +SECTION ANSWER +ns.blabla.com. IN A 1.2.3.5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.blabla.com. IN AAAA +SECTION AUTHORITY +com. IN SOA com. com. 2009100100 28800 7200 604800 3600 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +; no ns.blabla.com, try that later +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20030926134150 20030829134150 2854 example.com. AKJ3xUBdSrCiOFkYajsy93d+h06rewpbmBHItTkL8R/26rw57b1gCIg= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AHNj99mBmP4np19V01nSq990ZIFlIiLWoeHijm/HcOG/o8+DuIp4fL8= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AHNj99mBmP4np19V01nSq990ZIFlIiLWoeHijm/HcOG/o8+DuIp4fL8= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +SECTION ADDITIONAL +ns.example.com. IN NSEC oof.example.com. NSEC RRSIG A +ns.example.com. 3600 IN RRSIG NSEC 3 3 3600 20030926134150 20030829134150 2854 example.com. ACFVLLBtuSX/1z3461tbOwDz9zTHe5S9DbVtwnSO1f2x06fYbMpzSDE= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +; make priming query succeed +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +;example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20030926134150 20030829134150 2854 example.com. AG21xE8CFQzTq6XtHErg28b9EAmqPsoYCUcFPEAoAjFybM6AY4/bMOo= ;{id = 2854} +SECTION AUTHORITY +;example.com. IN NS ns.example.com. +;example.com. IN NS ns.blabla.com. +;example.com. 3600 IN RRSIG NS 3 2 3600 20030926134150 20030829134150 2854 example.com. ACiWu7zjBHqgEX3iUoOF7rfpOmIAHj1npKQ+XDIaNlmdkfJxoCwFl04= ;{id = 2854} +SECTION ADDITIONAL +;ns.example.com. IN A 1.2.3.4 +;ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. ACmAsKTf7hqDaYK8CQ7FL1cGYPW+blTCnzZGkExFtEUAGrHeze87o+A= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AGj9kE8oW3OhOLhkmJ3HBaNIOpvGf3S8zSd5gWmhpxAMc5hh6cxZfpQ= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20030926134150 20030829134150 2854 example.com. ACHETweBNPgbmRoNRdKvxuw4X9qNUUTEpSuwV+HhuiBE83gbB98asAc= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AGvu9A/nGsbatxJCmnObioIhKg2Tm0Apr0eo+DO1kIDrAHco/bt/EdY= ;{id = 2854} +ENTRY_END + +; ENT request +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION AUTHORITY +rub.example.com. IN NSEC sub.sub.example.com. RRSIG NSEC A +rub.example.com. 3600 IN RRSIG NSEC 3 3 3600 20030926134150 20030829134150 2854 example.com. AAUOa/L9F/ZrGfXSov4WRhTTbd8+CsdTJeM4Nk973wcLZ27A4YiIlTs= ;{id = 2854} +; extraneous DS +sub.sub.example.com. IN NSEC tub.example.com. RRSIG NSEC DS +sub.sub.example.com. 3600 IN RRSIG NSEC 3 4 3600 20030926134150 20030829134150 2854 example.com. AJVJEBTIlbnAHF0HR0skEfTVS28hMrbUHzBx5CMfY/NhxZohQtGVcwo= ;{id = 2854} +ENTRY_END + +; DS request +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.sub.example.com. IN DS +SECTION ANSWER +sub.sub.example.com. 3600 IN DS 30899 5 1 dea269e4bccaa019a4ba0cf5b198292f28faeee1 +sub.sub.example.com. 3600 IN RRSIG DS 3 4 3600 20030926134150 20030829134150 2854 example.com. AGQoKQd4UT+e4AMdYdDznxWo9cybYZyRAgC7exEgJ1asYRmmgvJG7Zw= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR AA NOERROR +SECTION QUESTION +sub.sub.example.com. IN NS +SECTION AUTHORITY +sub.sub.example.com. IN NS ns.sub.sub.example.com. +sub.sub.example.com. IN NS ns.foo.com. +sub.sub.example.com. 3600 IN DS 30899 5 1 dea269e4bccaa019a4ba0cf5b198292f28faeee1 +sub.sub.example.com. 3600 IN RRSIG DS 3 4 3600 20030926134150 20030829134150 2854 example.com. AGQoKQd4UT+e4AMdYdDznxWo9cybYZyRAgC7exEgJ1asYRmmgvJG7Zw= ;{id = 2854} +SECTION ADDITIONAL +ns.sub.sub.example.com. IN A 1.2.4.6 +ENTRY_END + +RANGE_END + +; ns.blabla.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. AAJHNhPYVG6+550zQga9ZgV8McQZHLboOWjfbdiq2ZC+gUcQeQDDlFs= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +SECTION ADDITIONAL +ns.example.com. IN NSEC oof.example.com. NSEC RRSIG A +ns.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. ABhDNtJramb2a4R1SK5gb/CTYJybQts6mZ++z3kLiwsrUSZInA4ikeQ= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. AAJHNhPYVG6+550zQga9ZgV8McQZHLboOWjfbdiq2ZC+gUcQeQDDlFs= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. AAJHNhPYVG6+550zQga9ZgV8McQZHLboOWjfbdiq2ZC+gUcQeQDDlFs= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +ENTRY_END + +; ENT request +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION AUTHORITY +rub.example.com. IN NSEC sub.sub.example.com. RRSIG NSEC A +rub.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. AKxt275OlwQmfqO36rTYkPXBqdoyaD3lId4q+UA4+Gs50qfn/RkuIOs= ;{id = 2854} +; extraneous DS +sub.sub.example.com. IN NSEC tub.example.com. RRSIG NSEC DS +sub.sub.example.com. 3600 IN RRSIG NSEC 3 4 3600 20070926134150 20070829134150 2854 example.com. AJlIjBQvBluNTu1883DMH9ZtBVfKTXVEH2LvLV785UcwGELnwRYfZbA= ;{id = 2854} +ENTRY_END + +; DS request +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.sub.example.com. IN DS +SECTION ANSWER +sub.sub.example.com. 3600 IN DS 30899 5 1 dea269e4bccaa019a4ba0cf5b198292f28faeee1 +sub.sub.example.com. 3600 IN RRSIG DS 3 4 3600 20070926134150 20070829134150 2854 example.com. AAPYiFzyEyehaff0hYTyOBFHF6qiCE7I7Zoa7Atn2F+HN2N/g/RloN8= ;{id = 2854} + +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR AA NOERROR +SECTION QUESTION +sub.sub.example.com. IN NS +SECTION AUTHORITY +sub.sub.example.com. IN NS ns.sub.sub.example.com. +sub.sub.example.com. IN NS ns.foo.com. +sub.sub.example.com. 3600 IN DS 30899 5 1 dea269e4bccaa019a4ba0cf5b198292f28faeee1 +sub.sub.example.com. 3600 IN RRSIG DS 3 4 3600 20070926134150 20070829134150 2854 example.com. AAPYiFzyEyehaff0hYTyOBFHF6qiCE7I7Zoa7Atn2F+HN2N/g/RloN8= ;{id = 2854} +SECTION ADDITIONAL +ns.sub.sub.example.com. IN A 1.2.4.6 +ENTRY_END + +RANGE_END + +; ns.sub.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.4.6 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.sub.example.com. IN DNSKEY +SECTION ANSWER +sub.sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.sub.example.com. 3600 IN RRSIG DNSKEY 5 4 3600 20070926134150 20070829134150 30899 sub.sub.example.com. RO6LECPRS3aL6kRp++qbSIdNiJvhvYTJr0fupJMF5lPuTwI5HhAL5mAHjrmc3r0LeFE9iRpjFmdp/p1i0qVWzQ== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.sub.example.com. IN NS +SECTION ANSWER +sub.sub.example.com. IN NS ns.sub.sub.example.com. +sub.sub.example.com. IN NS ns.foo.com. +sub.sub.example.com. 3600 IN RRSIG NS 5 4 3600 20070926134150 20070829134150 30899 sub.sub.example.com. blhq9ELWjE5YhhLn1UN3K/QTh52w/ZkGv+hI8HbL1a9Av6W67H2jsb1B5iaPbOagKzAIPId9qtcskjCo3DSaHg== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.sub.example.com. IN A 1.2.4.6 +ns.sub.sub.example.com. 3600 IN RRSIG A 5 5 3600 20070926134150 20070829134150 30899 sub.sub.example.com. JU2A7WvVR3AB7Ni9Qjfv7sxetc0jIfRgeERj8x+UUWdPiEBEkhUvD+ba6eLu5irMRWCj7CXIM81Mgl58QXCqfg== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.sub.sub.example.com. IN A +SECTION ANSWER +ns.sub.sub.example.com. IN A 1.2.4.6 +ns.sub.sub.example.com. 3600 IN RRSIG A 5 5 3600 20070926134150 20070829134150 30899 sub.sub.example.com. JU2A7WvVR3AB7Ni9Qjfv7sxetc0jIfRgeERj8x+UUWdPiEBEkhUvD+ba6eLu5irMRWCj7CXIM81Mgl58QXCqfg== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.sub.sub.example.com. IN AAAA +SECTION AUTHORITY +ns.sub.sub.example.com. IN NSEC nt.sub.sub.example.com. NSEC RRSIG A +ns.sub.sub.example.com. 3600 IN RRSIG NSEC 5 5 3600 20070926134150 20070829134150 30899 sub.sub.example.com. zoir16lVMbPOFS81l20ZXyqWlXYvQg99zzfOiH5tzpbqPYHxrnQvsfJgTMR7rZvYG55Qh64Y4J1MSw+U2QAgmw== ;{id = 30899} +sub.sub.example.com. IN SOA sub.sub.example.com. hostmaster.sub.sub.example.com. 1 2 3 4 5 +sub.sub.example.com. 3600 IN RRSIG SOA 5 4 3600 20070926134150 20070829134150 30899 sub.sub.example.com. aAKz5eF2EdRP5HVojabqDkvINeXczBAZyBesjC0+DtMmb7WvaUQzKQfYtBdWhE7CdrnPYuHPg4WlNbn0f7DsCw== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.sub.sub.example.com. IN A +SECTION ANSWER +www.sub.sub.example.com. IN A 10.20.30.40 +www.sub.sub.example.com. 3600 IN RRSIG A 5 5 3600 20070926134150 20070829134150 30899 sub.sub.example.com. ZXZoHA8pavJZELucMJpXLWQXNaIYXO4ryXpkp2BVZbW9sdcYCobWPyyzN5nmBatm+CaWLd6fjhwXh+OVVIH1Gg== ;{id = 30899} +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.sub.sub.example.com. IN A +SECTION ANSWER +www.sub.sub.example.com. IN A 10.20.30.40 +www.sub.sub.example.com. 3600 IN RRSIG A 5 5 3600 20070926134150 20070829134150 30899 sub.sub.example.com. ZXZoHA8pavJZELucMJpXLWQXNaIYXO4ryXpkp2BVZbW9sdcYCobWPyyzN5nmBatm+CaWLd6fjhwXh+OVVIH1Gg== ;{id = 30899} +ENTRY_END + +; remove pending ns.blabla.com AAAA msg +STEP 30 QUERY +ENTRY_BEGIN +REPLY RD DO CD +SECTION QUESTION +ns.blabla.com. IN AAAA +ENTRY_END + +; recursion happens here. +STEP 40 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD CD RA NOERROR +SECTION QUESTION +ns.blabla.com. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +com. IN SOA com. com. 2009100100 28800 7200 604800 3600 +ENTRY_END + +SCENARIO_END diff --git a/testdata/black_key_entry.rpl b/testdata/black_key_entry.rpl new file mode 100644 index 00000000000..1bc41859a33 --- /dev/null +++ b/testdata/black_key_entry.rpl @@ -0,0 +1,608 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with blacked key entry and further queries +; DNSKEY not for prime but further down the chain of trust +; the blacklist action does not help. +; the further queries should not generate traffic to the authority any more. +; until the key entry expires. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.blabla.com. IN A +SECTION ANSWER +ns.blabla.com. IN A 1.2.3.5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.blabla.com. IN AAAA +SECTION AUTHORITY +com. IN SOA com. com. 2009100100 28800 7200 604800 3600 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.foo.com. IN A +SECTION ANSWER +ns.foo.com. IN A 1.2.4.7 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.foo.com. IN AAAA +SECTION AUTHORITY +com. IN SOA com. com. 2009100100 28800 7200 604800 3600 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20030926134150 20030829134150 2854 example.com. AKJ3xUBdSrCiOFkYajsy93d+h06rewpbmBHItTkL8R/26rw57b1gCIg= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AHNj99mBmP4np19V01nSq990ZIFlIiLWoeHijm/HcOG/o8+DuIp4fL8= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AHNj99mBmP4np19V01nSq990ZIFlIiLWoeHijm/HcOG/o8+DuIp4fL8= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +SECTION ADDITIONAL +ns.example.com. IN NSEC oof.example.com. NSEC RRSIG A +ns.example.com. 3600 IN RRSIG NSEC 3 3 3600 20030926134150 20030829134150 2854 example.com. ACFVLLBtuSX/1z3461tbOwDz9zTHe5S9DbVtwnSO1f2x06fYbMpzSDE= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +; make priming query succeed +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +;example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20030926134150 20030829134150 2854 example.com. AG21xE8CFQzTq6XtHErg28b9EAmqPsoYCUcFPEAoAjFybM6AY4/bMOo= ;{id = 2854} +SECTION AUTHORITY +;example.com. IN NS ns.example.com. +;example.com. IN NS ns.blabla.com. +;example.com. 3600 IN RRSIG NS 3 2 3600 20030926134150 20030829134150 2854 example.com. ACiWu7zjBHqgEX3iUoOF7rfpOmIAHj1npKQ+XDIaNlmdkfJxoCwFl04= ;{id = 2854} +SECTION ADDITIONAL +;ns.example.com. IN A 1.2.3.4 +;ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. ACmAsKTf7hqDaYK8CQ7FL1cGYPW+blTCnzZGkExFtEUAGrHeze87o+A= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AGj9kE8oW3OhOLhkmJ3HBaNIOpvGf3S8zSd5gWmhpxAMc5hh6cxZfpQ= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20030926134150 20030829134150 2854 example.com. ACHETweBNPgbmRoNRdKvxuw4X9qNUUTEpSuwV+HhuiBE83gbB98asAc= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AGvu9A/nGsbatxJCmnObioIhKg2Tm0Apr0eo+DO1kIDrAHco/bt/EdY= ;{id = 2854} +ENTRY_END + +; DS request +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION ANSWER +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. AKslZ9oXcoyeOkPfGkTB3/hxnpdgU5ahzElLyK6B0n6+BdIXeirIEtE= ;{id = 2854} +;sub.example.com. 3600 IN RRSIG DS 3 3 3600 20030926134150 20030829134150 2854 example.com. AAT/7XwtMjHiT1GFHfV6Wvv4n+oOkqxllNdf9bLnpTHw/8h586yBgwg= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +;sub.example.com. IN NS ns.foo.com. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. AKslZ9oXcoyeOkPfGkTB3/hxnpdgU5ahzElLyK6B0n6+BdIXeirIEtE= ;{id = 2854} +;sub.example.com. 3600 IN RRSIG DS 3 3 3600 20030926134150 20030829134150 2854 example.com. AAT/7XwtMjHiT1GFHfV6Wvv4n+oOkqxllNdf9bLnpTHw/8h586yBgwg= ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.4.6 +ENTRY_END + +RANGE_END + +; ns.blabla.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. AAJHNhPYVG6+550zQga9ZgV8McQZHLboOWjfbdiq2ZC+gUcQeQDDlFs= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +SECTION ADDITIONAL +ns.example.com. IN NSEC oof.example.com. NSEC RRSIG A +ns.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. ABhDNtJramb2a4R1SK5gb/CTYJybQts6mZ++z3kLiwsrUSZInA4ikeQ= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. AAJHNhPYVG6+550zQga9ZgV8McQZHLboOWjfbdiq2ZC+gUcQeQDDlFs= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. AAJHNhPYVG6+550zQga9ZgV8McQZHLboOWjfbdiq2ZC+gUcQeQDDlFs= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +ENTRY_END + +; DS request +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION ANSWER +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. AKslZ9oXcoyeOkPfGkTB3/hxnpdgU5ahzElLyK6B0n6+BdIXeirIEtE= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +;sub.example.com. IN NS ns.foo.com. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. AKslZ9oXcoyeOkPfGkTB3/hxnpdgU5ahzElLyK6B0n6+BdIXeirIEtE= ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.4.6 +ENTRY_END + +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.4.6 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20030926134150 20030829134150 30899 sub.example.com. g+YoDwrCF75YCFyqYoxlF+/mNfcscnuZ6LfmfBgPLohlvCCC7jYj/wkc2fxAl3MEK0CriWkHp1hw0QQYkmbbKw== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +;sub.example.com. IN NS ns.foo.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20030926134150 20030829134150 30899 sub.example.com. VCDq+gfZHuziE81Uypxm2va4eXCtoD8F8YKkwNo8laMNUcXh/hvGdbHKXMMghwuJXgxLh89Diu5kywBVwb/AIg== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.4.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20030926134150 20030829134150 30899 sub.example.com. l3wjlbDU2y7ECix6t1pp5Rtz+qFlADRMohcRsCrnD9b99IoOL0/cTpvvf2V1VTJveIibFGhbcHTuCqAQ4G4FKA== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.sub.example.com. IN A +SECTION ANSWER +ns.sub.example.com. IN A 1.2.4.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20030926134150 20030829134150 30899 sub.example.com. l3wjlbDU2y7ECix6t1pp5Rtz+qFlADRMohcRsCrnD9b99IoOL0/cTpvvf2V1VTJveIibFGhbcHTuCqAQ4G4FKA== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.sub.example.com. IN AAAA +SECTION AUTHORITY +ns.sub.example.com. IN NSEC nt.sub.example.com. NSEC RRSIG A +ns.sub.example.com. 3600 IN RRSIG NSEC 5 4 3600 20030926134150 20030829134150 30899 sub.example.com. eVe3iQS2/a1Y57AA2QSlMU/z31xaJ2mwUU36PZh8vlv6shPpQywAT70JdX6+ZsuliRpsbY6crkVXTXJ2qpKTiQ== ;{id = 30899} +sub.example.com. IN SOA sub.example.com. hostmaster.sub.example.com. 1 2 3 4 5 +sub.example.com. 3600 IN RRSIG SOA 5 3 3600 20030926134150 20030829134150 30899 sub.example.com. vEX2n1CksMr5jPq9d2BQJMIDwxaXdWlY5mYg+PBmOFI4xngFMKTsXa/+SfJy2SiqAgHTDI6joIo30AdQJsjdHA== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 10.20.30.40 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20030926134150 20030829134150 30899 sub.example.com. dBK6JOkKlp2G+f7mhInKnQM6DUBnEziTS+KpXzQ/5HT8/h9XkryOt4vAJKGCz0Ew3qRqjLgylsbGrcuxmIO9jA== ;{id = 30899} +ENTRY_END + +RANGE_END + +; ns.foo.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.4.7 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +;sub.example.com. IN NS ns.foo.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. hJ3nkrfyBwPcfpwc9wEwzhF5+ZKUddKBHQuZuHPZBjBwb1BsT7B7ryadttbGE3keQJiwNmK9AqvE0Zb+WkDceg== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.4.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. fMRshSYDWgvGAwc24Lzg6746jnoG5shlK+o9CgzU7CQbkeNWmj3oO/0TJGP/zxp52JiDBpzRuTmBlrcJYV/gBA== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.sub.example.com. IN A +SECTION ANSWER +ns.sub.example.com. IN A 1.2.4.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. fMRshSYDWgvGAwc24Lzg6746jnoG5shlK+o9CgzU7CQbkeNWmj3oO/0TJGP/zxp52JiDBpzRuTmBlrcJYV/gBA== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.sub.example.com. IN AAAA +SECTION AUTHORITY +ns.sub.example.com. IN NSEC nt.sub.example.com. NSEC RRSIG A +ns.sub.example.com. 3600 IN RRSIG NSEC 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. qwUibvlPTFnxgiyCNtEJCYqJIgA8WFDqypmsO6TSYje2Rqhq4AaWEVxQwU4bdjmipCGVqtlP8mMyMQHaYNMGKA== ;{id = 30899} +sub.example.com. IN SOA sub.example.com. hostmaster.sub.example.com. 1 2 3 4 5 +sub.example.com. 3600 IN RRSIG SOA 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. sZQEMd0ys2mxPRajzBuvy4XdLNVvXMmJSnmfTHUL41d9IxbGN/ifpiIWs2MXOFPnbab05aYadrzZpT/cpDTxmQ== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 10.20.30.40 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. deNzEy9Hq+6gDZhafC0M7UDuRBm51AA1/FAIauAitNuQlYUzOvWLVHFQ95bn308rCVPqrb4rFDV+gNzxkzm1rw== ;{id = 30899} +ENTRY_END +RANGE_END + +; ns.sub.example.com. +; This is for after, so only new queries, no requeries allowed. +RANGE_BEGIN 100 200 + ADDRESS 1.2.4.6 + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ftp.sub.example.com. IN A +SECTION ANSWER +ftp.sub.example.com. IN A 10.20.30.46 +ftp.sub.example.com. 3600 IN RRSIG A 5 4 3600 20030926134150 20030829134150 30899 sub.example.com. nbxk6SiooKsUeVm/ZGskrxKwhOSWdJt9ly9X6Hqji4DKpBskM6bqulmTt/xZ/3G4ZOguYBeiTp8qwlWjl7VoSQ== ;{id = 30899} +ENTRY_END + +RANGE_END + +; ns.sub.example.com. +; fixed version +RANGE_BEGIN 200 300 + ADDRESS 1.2.4.6 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +;sub.example.com. IN NS ns.foo.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. hJ3nkrfyBwPcfpwc9wEwzhF5+ZKUddKBHQuZuHPZBjBwb1BsT7B7ryadttbGE3keQJiwNmK9AqvE0Zb+WkDceg== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.4.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. fMRshSYDWgvGAwc24Lzg6746jnoG5shlK+o9CgzU7CQbkeNWmj3oO/0TJGP/zxp52JiDBpzRuTmBlrcJYV/gBA== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.sub.example.com. IN A +SECTION ANSWER +ns.sub.example.com. IN A 1.2.4.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. fMRshSYDWgvGAwc24Lzg6746jnoG5shlK+o9CgzU7CQbkeNWmj3oO/0TJGP/zxp52JiDBpzRuTmBlrcJYV/gBA== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.sub.example.com. IN AAAA +SECTION AUTHORITY +ns.sub.example.com. IN NSEC nt.sub.example.com. NSEC RRSIG A +ns.sub.example.com. 3600 IN RRSIG NSEC 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. qwUibvlPTFnxgiyCNtEJCYqJIgA8WFDqypmsO6TSYje2Rqhq4AaWEVxQwU4bdjmipCGVqtlP8mMyMQHaYNMGKA== ;{id = 30899} +sub.example.com. IN SOA sub.example.com. hostmaster.sub.example.com. 1 2 3 4 5 +sub.example.com. 3600 IN RRSIG SOA 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. sZQEMd0ys2mxPRajzBuvy4XdLNVvXMmJSnmfTHUL41d9IxbGN/ifpiIWs2MXOFPnbab05aYadrzZpT/cpDTxmQ== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 10.20.30.40 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. deNzEy9Hq+6gDZhafC0M7UDuRBm51AA1/FAIauAitNuQlYUzOvWLVHFQ95bn308rCVPqrb4rFDV+gNzxkzm1rw== ;{id = 30899} +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +ENTRY_END + +; no more outgoing traffic possible. +STEP 110 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +ftp.sub.example.com. IN A +ENTRY_END + +STEP 120 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +ftp.sub.example.com. IN A +SECTION ANSWER +ENTRY_END + +; wait for timeout seconds. +STEP 130 TIME_PASSES ELAPSE 901 + +STEP 210 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 220 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 10.20.30.40 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. deNzEy9Hq+6gDZhafC0M7UDuRBm51AA1/FAIauAitNuQlYUzOvWLVHFQ95bn308rCVPqrb4rFDV+gNzxkzm1rw== ;{id = 30899} +ENTRY_END + + +SCENARIO_END diff --git a/testdata/black_prime.rpl b/testdata/black_prime.rpl new file mode 100644 index 00000000000..cdd0a8707c2 --- /dev/null +++ b/testdata/black_prime.rpl @@ -0,0 +1,303 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with blacklist for prime response +; the data response needs a blacklist action as well, since it also +; comes from an 'expired signatures' name server. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.blabla.com. IN A +SECTION ANSWER +ns.blabla.com. IN A 1.2.3.5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.blabla.com. IN AAAA +SECTION AUTHORITY +com. IN SOA com. com. 2009100100 28800 7200 604800 3600 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +; no ns.blabla.com, try that later +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20030926134150 20030829134150 2854 example.com. AKJ3xUBdSrCiOFkYajsy93d+h06rewpbmBHItTkL8R/26rw57b1gCIg= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AHNj99mBmP4np19V01nSq990ZIFlIiLWoeHijm/HcOG/o8+DuIp4fL8= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AHNj99mBmP4np19V01nSq990ZIFlIiLWoeHijm/HcOG/o8+DuIp4fL8= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +SECTION ADDITIONAL +ns.example.com. IN NSEC oof.example.com. NSEC RRSIG A +ns.example.com. 3600 IN RRSIG NSEC 3 3 3600 20030926134150 20030829134150 2854 example.com. ACFVLLBtuSX/1z3461tbOwDz9zTHe5S9DbVtwnSO1f2x06fYbMpzSDE= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20030926134150 20030829134150 2854 example.com. AG21xE8CFQzTq6XtHErg28b9EAmqPsoYCUcFPEAoAjFybM6AY4/bMOo= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20030926134150 20030829134150 2854 example.com. ACiWu7zjBHqgEX3iUoOF7rfpOmIAHj1npKQ+XDIaNlmdkfJxoCwFl04= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. ACmAsKTf7hqDaYK8CQ7FL1cGYPW+blTCnzZGkExFtEUAGrHeze87o+A= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AGj9kE8oW3OhOLhkmJ3HBaNIOpvGf3S8zSd5gWmhpxAMc5hh6cxZfpQ= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20030926134150 20030829134150 2854 example.com. ACHETweBNPgbmRoNRdKvxuw4X9qNUUTEpSuwV+HhuiBE83gbB98asAc= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AGvu9A/nGsbatxJCmnObioIhKg2Tm0Apr0eo+DO1kIDrAHco/bt/EdY= ;{id = 2854} +ENTRY_END +RANGE_END + +; ns.blabla.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. AAJHNhPYVG6+550zQga9ZgV8McQZHLboOWjfbdiq2ZC+gUcQeQDDlFs= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +SECTION ADDITIONAL +ns.example.com. IN NSEC oof.example.com. NSEC RRSIG A +ns.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. ABhDNtJramb2a4R1SK5gb/CTYJybQts6mZ++z3kLiwsrUSZInA4ikeQ= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. AAJHNhPYVG6+550zQga9ZgV8McQZHLboOWjfbdiq2ZC+gUcQeQDDlFs= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. AAJHNhPYVG6+550zQga9ZgV8McQZHLboOWjfbdiq2ZC+gUcQeQDDlFs= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. AAJHNhPYVG6+550zQga9ZgV8McQZHLboOWjfbdiq2ZC+gUcQeQDDlFs= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +ENTRY_END + +; remove pending ns.blabla.com AAAA msg +STEP 30 QUERY +ENTRY_BEGIN +REPLY RD DO CD +SECTION QUESTION +ns.blabla.com. IN AAAA +ENTRY_END + +; recursion happens here. +STEP 40 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD CD RA NOERROR +SECTION QUESTION +ns.blabla.com. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +com. IN SOA com. com. 2009100100 28800 7200 604800 3600 +ENTRY_END + +SCENARIO_END diff --git a/testdata/black_prime_entry.rpl b/testdata/black_prime_entry.rpl new file mode 100644 index 00000000000..8ccbb90a7be --- /dev/null +++ b/testdata/black_prime_entry.rpl @@ -0,0 +1,311 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with blacklist prime gives bad key entry +; the data response needs a blacklist action as well, since it also +; comes from an 'expired signatures' name server. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.blabla.com. IN A +SECTION ANSWER +ns.blabla.com. IN A 1.2.3.5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.blabla.com. IN AAAA +SECTION AUTHORITY +com. IN SOA com. com. 2009100100 28800 7200 604800 3600 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +;example.com. IN NS ns.blabla.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +; no ns.blabla.com, try that later +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20030926134150 20030829134150 2854 example.com. AKJ3xUBdSrCiOFkYajsy93d+h06rewpbmBHItTkL8R/26rw57b1gCIg= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AHNj99mBmP4np19V01nSq990ZIFlIiLWoeHijm/HcOG/o8+DuIp4fL8= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AHNj99mBmP4np19V01nSq990ZIFlIiLWoeHijm/HcOG/o8+DuIp4fL8= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +SECTION ADDITIONAL +ns.example.com. IN NSEC oof.example.com. NSEC RRSIG A +ns.example.com. 3600 IN RRSIG NSEC 3 3 3600 20030926134150 20030829134150 2854 example.com. ACFVLLBtuSX/1z3461tbOwDz9zTHe5S9DbVtwnSO1f2x06fYbMpzSDE= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20030926134150 20030829134150 2854 example.com. AG21xE8CFQzTq6XtHErg28b9EAmqPsoYCUcFPEAoAjFybM6AY4/bMOo= ;{id = 2854} +SECTION AUTHORITY +;example.com. IN NS ns.example.com. +;example.com. IN NS ns.blabla.com. +;example.com. 3600 IN RRSIG NS 3 2 3600 20030926134150 20030829134150 2854 example.com. ACiWu7zjBHqgEX3iUoOF7rfpOmIAHj1npKQ+XDIaNlmdkfJxoCwFl04= ;{id = 2854} +SECTION ADDITIONAL +;ns.example.com. IN A 1.2.3.4 +;ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. ACmAsKTf7hqDaYK8CQ7FL1cGYPW+blTCnzZGkExFtEUAGrHeze87o+A= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AGj9kE8oW3OhOLhkmJ3HBaNIOpvGf3S8zSd5gWmhpxAMc5hh6cxZfpQ= ;{id = 2854} +SECTION AUTHORITY +;example.com. IN NS ns.example.com. +;example.com. IN NS ns.blabla.com. +;example.com. 3600 IN RRSIG NS 3 2 3600 20030926134150 20030829134150 2854 example.com. ACHETweBNPgbmRoNRdKvxuw4X9qNUUTEpSuwV+HhuiBE83gbB98asAc= ;{id = 2854} +SECTION ADDITIONAL +;ns.example.com. IN A 1.2.3.4 +;ns.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AGvu9A/nGsbatxJCmnObioIhKg2Tm0Apr0eo+DO1kIDrAHco/bt/EdY= ;{id = 2854} +ENTRY_END +RANGE_END + +; ns.blabla.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. AAJHNhPYVG6+550zQga9ZgV8McQZHLboOWjfbdiq2ZC+gUcQeQDDlFs= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +SECTION ADDITIONAL +ns.example.com. IN NSEC oof.example.com. NSEC RRSIG A +ns.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. ABhDNtJramb2a4R1SK5gb/CTYJybQts6mZ++z3kLiwsrUSZInA4ikeQ= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. AAJHNhPYVG6+550zQga9ZgV8McQZHLboOWjfbdiq2ZC+gUcQeQDDlFs= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.blabla.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. AAJHNhPYVG6+550zQga9ZgV8McQZHLboOWjfbdiq2ZC+gUcQeQDDlFs= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +ENTRY_END +RANGE_END + +; ns.example.com. +; later on, making sure DNSKEY primes give testbound failure. +RANGE_BEGIN 100 200 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ftp.example.com. IN A +SECTION ANSWER +ftp.example.com. IN A 10.20.33.33 +; very bad signature +ftp.example.com. 3600 IN RRSIG A 3 3 3600 20030926134150 20030829134150 2854 example.com. AHNj99mBmP4np19V01nSq990ZIFlIiLWoeHijm/HcOG/o8+DuIp4fL8= ;{id = 2854} +ENTRY_END +RANGE_END + + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 100 TIME_PASSES ELAPSE 10 + +; second query should not result in going to the network. +STEP 110 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +ftp.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 120 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +ftp.example.com. IN A +ENTRY_END + + +SCENARIO_END diff --git a/testdata/common.sh b/testdata/common.sh new file mode 100755 index 00000000000..8e3b2293ec6 --- /dev/null +++ b/testdata/common.sh @@ -0,0 +1,256 @@ +# common.sh - an include file for commonly used functions for test code. +# BSD licensed (see LICENSE file). +# +# Version 3 +# 2011-02-23: get_pcat for PCAT, PCAT_DIFF and PCAT_PRINT defines. +# 2011-02-18: ports check on BSD,Solaris. wait_nsd_up. +# 2011-02-11: first version. +# +# include this file from a tpkg script with +# . ../common.sh +# +# overview of functions available: +# error x : print error and exit +# info x : print info +# test_tool_avail x : see if program in path and complain, exit if not. +# get_ldns_testns : set LDNS_TESTNS to executable ldns-testns +# get_make : set MAKE to gmake or make tool. +# get_gcc : set cc or gcc in CC +# get_pcat : set PCAT, PCAT_DIFF and PCAT_PRINT executables. +# set_doxygen_path : set doxygen path +# skip_if_in_list : set SKIP=1 if name in list and tool not available. +# get_random_port x : get RND_PORT a sequence of free random port numbers. +# wait_server_up : wait on logfile to see when server comes up. +# wait_ldns_testns_up : wait for ldns-testns to come up. +# wait_unbound_up : wait for unbound to come up. +# wait_petal_up : wait for petal to come up. +# wait_nsd_up : wait for nsd to come up. +# wait_server_up_or_fail: wait for server to come up or print a failure string +# kill_pid : kill a server, make sure and wait for it to go down. + + +# print error and exit +# $0: name of program +# $1: error to printout. +error () { + echo "$0: error: $1" >&2 + exit 1 +} + +# print info +# $0: name of program +# $1: to printout. +info () { + echo "$0: info: $1" +} + +# test if 'tool' is available in path and complain otherwise. +# $1: tool +test_tool_avail () { + if test ! -x "`which $1 2>&1`"; then + echo No "$1" in path + exit 1 + fi +} + +# get ldns-testns tool in LDNS_TESTNS variable. +get_ldns_testns () { + if test -x "`which ldns-testns 2>&1`"; then + LDNS_TESTNS=ldns-testns + else + LDNS_TESTNS=/home/wouter/bin/ldns-testns + fi +} + +# get make tool in MAKE variable, gmake is used if present. +get_make () { + if test -x "`which gmake 2>&1`"; then + MAKE=gmake + else + MAKE=make + fi +} + +# get cc tool in CC variable, gcc is used if present. +get_gcc () { + if test -x "`which gcc 2>&1`"; then + CC=gcc + else + CC=cc + fi +} + +# get pcat, pcat-print and pcat-diff +get_pcat () { + PCAT=`which pcat` + PCAT_PRINT=`which pcat-print` + PCAT_DIFF=`which pcat-diff` +} + +# set SKIP=1 if the name is in list and tool is not available. +# $1: name of package to check. +# $2: list of packages that need the tool. +# #3: name of the tool required. +skip_if_in_list () { + if echo $2 | grep $1 >/dev/null; then + if test ! -x "`which $3 2>&1`"; then + SKIP=1; + fi + fi +} + +# function to get a number of random port numbers. +# $1: number of random ports. +# RND_PORT is returned as the starting port number +get_random_port () { + local plist + local cont + local collisions + local i + local MAXCOLLISION=1000 + cont=1 + collisions=0 + while test "$cont" = 1; do + #netstat -n -A ip -A ip6 -a | sed -e "s/^.*:\([0-9]*\) .*$/\1/" + RND_PORT=$(( $RANDOM + 5354 )) + # depending on uname try to check for collisions in port numbers + case "`uname`" in + linux|Linux) + plist=`netstat -n -A ip -A ip6 -a | sed -e 's/^.*:\([0-9]*\) .*$/\1/'` + ;; + FreeBSD|freebsd|NetBSD|netbsd|OpenBSD|openbsd) + plist=`netstat -n -a | grep "^[ut][dc]p[46] " | sed -e 's/^.*\.\([0-9]*\) .*$/\1/'` + ;; + Solaris|SunOS) + plist=`netstat -n -a | sed -e 's/^.*\.\([0-9]*\) .*$/\1/' | grep '^[0-9]*$'` + ;; + *) + plist="" + ;; + esac + cont=0 + for (( i=0 ; i < $1 ; i++ )); do + if echo "$plist" | grep '^'`expr $i + $RND_PORT`'$' >/dev/null 2>&1; then + cont=1; + collisions=`expr $collisions + 1` + fi + done + if test $collisions = $MAXCOLLISION; then + error "too many collisions getting random port number" + fi + done +} + +# wait for server to go up, pass +# $1 : logfilename +# $2 : string to watch for. +# exits with failure if it does not come up +wait_server_up () { + local MAX_UP_TRY=120 + local WAIT_THRES=30 + local try + for (( try=0 ; try <= $MAX_UP_TRY ; try++ )) ; do + if test -f $1 && fgrep "$2" $1 >/dev/null; then + #echo "done on try $try" + break; + fi + if test $try -eq $MAX_UP_TRY; then + echo "Server in $1 did not go up!" + cat $1 + exit 1; + fi + if test $try -ge $WAIT_THRES; then + sleep 1 + fi + done +} + +# wait for ldns-testns to come up +# $1 : logfilename that is watched. +wait_ldns_testns_up () { + wait_server_up "$1" "Listening on port" +} + +# wait for unbound to come up +# string 'Start of service' in log. +# $1 : logfilename that is watched. +wait_unbound_up () { + wait_server_up "$1" "start of service" +} + +# wait for petal to come up +# string 'petal start' in log. +# $1 : logfilename that is watched. +wait_petal_up () { + wait_server_up "$1" "petal start" +} + +# wait for nsd to come up +# string nsd start in log. +# $1 : logfilename that is watched. +wait_nsd_up () { + wait_server_up "$1" " started (NSD " +} + +# wait for server to go up, pass +# $1 : logfile +# $2 : success string +# $3 : failure string +wait_server_up_or_fail () { + local MAX_UP_TRY=120 + local WAIT_THRES=30 + local try + for (( try=0 ; try <= $MAX_UP_TRY ; try++ )) ; do + if test -f $1 && fgrep "$2" $1 >/dev/null; then + echo "done on try $try" + break; + fi + if test -f $1 && fgrep "$3" $1 >/dev/null; then + echo "failed on try $try" + break; + fi + if test $try -eq $MAX_UP_TRY; then + echo "Server in $1 did not go up!" + cat $1 + exit 1; + fi + if test $try -ge $WAIT_THRES; then + sleep 1 + fi + done +} + +# kill a pid, make sure and wait for it to go down. +# $1 : pid to kill +kill_pid () { + local MAX_DOWN_TRY=120 + local WAIT_THRES=30 + local try + kill $1 + for (( try=0 ; try <= $MAX_DOWN_TRY ; try++ )) ; do + if kill -0 $1 >/dev/null 2>&1; then + : + else + #echo "done on try $try" + break; + fi + if test $try -eq $MAX_DOWN_TRY; then + echo "Server in $1 did not go down! Send SIGKILL" + kill -9 $1 >/dev/null 2>&1 + fi + if test $try -ge $WAIT_THRES; then + sleep 1 + fi + # re-send the signal + kill $1 >/dev/null 2>&1 + done + return 0 +} + +# set doxygen path, so that make doc can find doxygen +set_doxygen_path () { + if test -x '/home/wouter/bin/doxygen'; then + export PATH="/home/wouter/bin:$PATH" + fi +} + diff --git a/testdata/dlv_anchor.rpl b/testdata/dlv_anchor.rpl new file mode 100644 index 00000000000..e01b6863abb --- /dev/null +++ b/testdata/dlv_anchor.rpl @@ -0,0 +1,275 @@ +; config options +; The island of trust is at example.com (the DLV repository) +server: + dlv-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with DLV anchor +; positive response for DLV. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; DLV query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net.example.com. IN DLV +SECTION ANSWER +example.net.example.com. 3600 IN DLV 30899 5 1 14188c885f20623ad1d3bec42798f3f951793e4c ; xehac-mofum-malyd-bomaf-pegit-fuzes-ganin-misiz-nigel-nozog-soxix +example.net.example.com. 3600 IN RRSIG DLV 3 4 3600 20070926134150 20070829134150 2854 example.com. ACK48Q/oKwh/SM9yRiKjZYuc+AtEZ2yCPNJ15kKCN8nsVcv7xigmNTY= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net.example.com. IN DLV +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AKPJnPBqfJKxE4P2iVYkSRJno9HmiXJZtjdqE8oBeq9Lk9FytcMdcig= ;{id = 2854} +example.com IN NSEC example.net.example.com. SOA NS RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. AIoUkJ04/7/kJFDLocoqksqt9UL2RHHwlRfXAMxGdBHcNO+GSpG47Uk= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +com.example.com. IN DLV +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AKPJnPBqfJKxE4P2iVYkSRJno9HmiXJZtjdqE8oBeq9Lk9FytcMdcig= ;{id = 2854} +example.com IN NSEC example.net.example.com. SOA NS RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. AIoUkJ04/7/kJFDLocoqksqt9UL2RHHwlRfXAMxGdBHcNO+GSpG47Uk= ;{id = 2854} +ENTRY_END + +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +; DS RR is +; example.net. 3600 IN DS 30899 5 1 14188c885f20623ad1d3bec42798f3f951793e4c ; xehac-mofum-malyd-bomaf-pegit-fuzes-ganin-misiz-nigel-nozog-soxix +; DNSKEY prime query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN DNSKEY +SECTION ANSWER +example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.net. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; NS query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; www.example.net query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +www.example.net. 3600 IN A 10.20.30.40 +www.example.net. 3600 IN RRSIG A 5 3 3600 20070926135752 20070829135752 30899 example.net. ACvv4RQVC7TbI57ewqFImRaVoymktJ5Cxn/FaCodIENt82LVM92nivbP2WtwWCsQHWp7FkrMxTlQTJwyAeXFyg== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.net. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +www.example.net. 3600 IN A 10.20.30.40 +www.example.net. 3600 IN RRSIG A 5 3 3600 20070926135752 20070829135752 30899 example.net. ACvv4RQVC7TbI57ewqFImRaVoymktJ5Cxn/FaCodIENt82LVM92nivbP2WtwWCsQHWp7FkrMxTlQTJwyAeXFyg== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +SCENARIO_END diff --git a/testdata/dlv_ask_higher.rpl b/testdata/dlv_ask_higher.rpl new file mode 100644 index 00000000000..11e3cdaf607 --- /dev/null +++ b/testdata/dlv_ask_higher.rpl @@ -0,0 +1,350 @@ +; config options +; The island of trust is at example.com (the DLV repository) +server: + dlv-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with DLV where it needs to ask higher up in dlv. +; at first negative DLV response, it needs to ask higher. +; the SOA record in that negative reponse has a big span (if interpreted as NSEC) +; then a positive response for DLV. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; failed DLV query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NXDOMAIN +SECTION QUESTION +sub.example.net.example.com. IN DLV +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AKPJnPBqfJKxE4P2iVYkSRJno9HmiXJZtjdqE8oBeq9Lk9FytcMdcig= ;{id = 2854} +example.net.example.com IN NSEC not.example.com. RRSIG NSEC DLV +example.net.example.com. 3600 IN RRSIG NSEC 3 4 3600 20070926134150 20070829134150 2854 example.com. AKz/e6KOw8gCx6wnpIatBwKb0WOPBTWmNNMg91XR/wlJQ9Z2+qICPmA= ;{id = 2854} +example.com IN NSEC example.net.example.com. SOA NS RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. AIoUkJ04/7/kJFDLocoqksqt9UL2RHHwlRfXAMxGdBHcNO+GSpG47Uk= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +; DLV query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net.example.com. IN DLV +SECTION ANSWER +example.net.example.com. 3600 IN DLV 30899 5 1 14188c885f20623ad1d3bec42798f3f951793e4c ; xehac-mofum-malyd-bomaf-pegit-fuzes-ganin-misiz-nigel-nozog-soxix +example.net.example.com. 3600 IN RRSIG DLV 3 4 3600 20070926134150 20070829134150 2854 example.com. ACK48Q/oKwh/SM9yRiKjZYuc+AtEZ2yCPNJ15kKCN8nsVcv7xigmNTY= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net.example.com. IN DLV +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AKPJnPBqfJKxE4P2iVYkSRJno9HmiXJZtjdqE8oBeq9Lk9FytcMdcig= ;{id = 2854} +example.com IN NSEC example.net.example.com. SOA NS RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. AIoUkJ04/7/kJFDLocoqksqt9UL2RHHwlRfXAMxGdBHcNO+GSpG47Uk= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +com.example.com. IN DLV +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AKPJnPBqfJKxE4P2iVYkSRJno9HmiXJZtjdqE8oBeq9Lk9FytcMdcig= ;{id = 2854} +example.com IN NSEC example.net.example.com. SOA NS RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. AIoUkJ04/7/kJFDLocoqksqt9UL2RHHwlRfXAMxGdBHcNO+GSpG47Uk= ;{id = 2854} +ENTRY_END + +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +; DS RR is +; example.net. 3600 IN DS 30899 5 1 14188c885f20623ad1d3bec42798f3f951793e4c ; xehac-mofum-malyd-bomaf-pegit-fuzes-ganin-misiz-nigel-nozog-soxix +; DNSKEY prime query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN DNSKEY +SECTION ANSWER +example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.net. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; NS query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; www.sub.example.net query +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +sub.example.net. IN A +SECTION ANSWER +SECTION AUTHORITY +sub.example.net. IN NS ns.sub.example.net. +sub.example.net. 3600 IN DS 30899 5 1 36b39460f94a807cbbbf3b31cc9db955081b2b36 ; xetir-fahok-bovug-pebyl-sovur-zyvaf-cufan-tivih-hadec-rypof-kixox +sub.example.net. 3600 IN RRSIG DS 5 3 3600 20070926134150 20070829134150 30899 example.net. nM5HAlRsrLurc5mUNKwCye5X6LSH53pLgSeyni4wb6Jd2J48ZRWwrVvy7IpyvI75+Wlu3aGOjv/kEyVaizChRQ== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.net. IN A 1.2.3.6 +ENTRY_END + +RANGE_END + +; ns.sub.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 +; DS +; sub.example.net. 3600 IN DS 30899 5 1 36b39460f94a807cbbbf3b31cc9db955081b2b36 ; xetir-fahok-bovug-pebyl-sovur-zyvaf-cufan-tivih-hadec-rypof-kixox +; DNSKEY prime query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.net. IN DNSKEY +SECTION ANSWER +sub.example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.net. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.net. PATh0K1jz9QeN02C79noX9gwK+Nr5VznWPQwygm/pYDsOb0z3EsaiOrzyoreegDKgoNn3kN0CywS+usCWM6hrw== ;{id = 30899} +SECTION AUTHORITY +sub.example.net. IN NS ns.sub.example.net. +sub.example.net. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.net. JZUK303aE7R428S5XXLaowpM79YSc2g7wy2rDOH+6Ts2UefZInv6X5cjJU4+qBrS8i9XhdllqG7SEnPKZ0GtAw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.net. IN A 1.2.3.6 +ns.sub.example.net. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.net. AluXPa4XdlCysQMVrt0YairoOug4GMvy8rNUeKLCfQ5xVqRMqkTisbzJXBQPgYEVA0DJR74eEpgLrcz5ztb1aA== ;{id = 30899} +ENTRY_END + +; NS query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.net. IN NS +SECTION ANSWER +sub.example.net. IN NS ns.sub.example.net. +sub.example.net. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.net. JZUK303aE7R428S5XXLaowpM79YSc2g7wy2rDOH+6Ts2UefZInv6X5cjJU4+qBrS8i9XhdllqG7SEnPKZ0GtAw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.net. IN A 1.2.3.6 +ns.sub.example.net. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.net. AluXPa4XdlCysQMVrt0YairoOug4GMvy8rNUeKLCfQ5xVqRMqkTisbzJXBQPgYEVA0DJR74eEpgLrcz5ztb1aA== ;{id = 30899} +ENTRY_END + +; www.sub.example.net query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.net. IN A +SECTION ANSWER +www.sub.example.net. 3600 IN A 10.20.30.40 +www.sub.example.net. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.net. Q+88AIM3K8q6S0bHeFVT742EepZFxOxgtaL1V68DEkP4NePKzL4zttWQD3uI/5ALw/fIrC7G43Eo+epWn2ZGCA== ;{id = 30899} +SECTION AUTHORITY +sub.example.net. IN NS ns.sub.example.net. +sub.example.net. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.net. JZUK303aE7R428S5XXLaowpM79YSc2g7wy2rDOH+6Ts2UefZInv6X5cjJU4+qBrS8i9XhdllqG7SEnPKZ0GtAw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.net. IN A 1.2.3.6 +ns.sub.example.net. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.net. AluXPa4XdlCysQMVrt0YairoOug4GMvy8rNUeKLCfQ5xVqRMqkTisbzJXBQPgYEVA0DJR74eEpgLrcz5ztb1aA== ;{id = 30899} +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.net. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.sub.example.net. IN A +SECTION ANSWER +www.sub.example.net. 3600 IN A 10.20.30.40 +www.sub.example.net. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.net. Q+88AIM3K8q6S0bHeFVT742EepZFxOxgtaL1V68DEkP4NePKzL4zttWQD3uI/5ALw/fIrC7G43Eo+epWn2ZGCA== ;{id = 30899} +SECTION AUTHORITY +sub.example.net. IN NS ns.sub.example.net. +sub.example.net. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.net. JZUK303aE7R428S5XXLaowpM79YSc2g7wy2rDOH+6Ts2UefZInv6X5cjJU4+qBrS8i9XhdllqG7SEnPKZ0GtAw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.net. IN A 1.2.3.6 +ns.sub.example.net. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.net. AluXPa4XdlCysQMVrt0YairoOug4GMvy8rNUeKLCfQ5xVqRMqkTisbzJXBQPgYEVA0DJR74eEpgLrcz5ztb1aA== ;{id = 30899} +ENTRY_END + +SCENARIO_END diff --git a/testdata/dlv_below_ta.rpl b/testdata/dlv_below_ta.rpl new file mode 100644 index 00000000000..374294637aa --- /dev/null +++ b/testdata/dlv_below_ta.rpl @@ -0,0 +1,351 @@ +; config options +; The island of trust is at example.com (the DLV repository) +server: + dlv-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + trust-anchor: "example.net. 3600 IN DS 30899 5 1 14188c885f20623ad1d3bec42798f3f951793e4c ; xehac-mofum-malyd-bomaf-pegit-fuzes-ganin-misiz-nigel-nozog-soxix" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator, use DLV for nonDSed zone below trustanchor. +; DLV example.com. +; trust anchor at example.net but no secure delegation to +; sub.example.net signed with DLV but not by parent. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; DLV query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.net.example.com. IN DLV +SECTION ANSWER +sub.example.net.example.com. 3600 IN DLV 30899 5 1 36b39460f94a807cbbbf3b31cc9db955081b2b36 ; xetir-fahok-bovug-pebyl-sovur-zyvaf-cufan-tivih-hadec-rypof-kixox +sub.example.net.example.com. 3600 IN RRSIG DLV 3 5 3600 20070926135752 20070829135752 2854 example.com. AAdhy87nuDEaxmc+k9pJHYnhKiEYL++OLPxzOdwEQOtsHi7jeD3lRDU= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net.example.com. IN DLV +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AKPJnPBqfJKxE4P2iVYkSRJno9HmiXJZtjdqE8oBeq9Lk9FytcMdcig= ;{id = 2854} +example.com IN NSEC sub.example.net.example.com. SOA NS RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926135752 20070829135752 2854 example.com. ALITtZY03PDWnuAeEL/5VwMIXY3iC2y7Qkeq5DgAHmPbNyWiOmJNEKg= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +com.example.com. IN DLV +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AKPJnPBqfJKxE4P2iVYkSRJno9HmiXJZtjdqE8oBeq9Lk9FytcMdcig= ;{id = 2854} +example.com IN NSEC sub.example.net.example.com. SOA NS RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926135752 20070829135752 2854 example.com. ALITtZY03PDWnuAeEL/5VwMIXY3iC2y7Qkeq5DgAHmPbNyWiOmJNEKg= ;{id = 2854} +ENTRY_END + +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +; DS RR is +; example.net. 3600 IN DS 30899 5 1 14188c885f20623ad1d3bec42798f3f951793e4c ; xehac-mofum-malyd-bomaf-pegit-fuzes-ganin-misiz-nigel-nozog-soxix +; DNSKEY prime query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN DNSKEY +SECTION ANSWER +example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.net. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; NS query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; no DS to sub.example.net, securely insecure. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.net. IN DS +SECTION ANSWER +SECTION AUTHORITY +example.net. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600 +example.net. 3600 IN RRSIG SOA 5 2 3600 20070926134150 20070829134150 30899 example.net. ELVULZHTRc0Qk06rSBRnB/T6sm1+AbAtdEJHN6PCsz2Z3s3E5A8NH7Krz0VzRaYIEUStnbAtuE3oP8XHWHBnyQ== ;{id = 30899} +sub.example.net. IN NSEC tut.example.net. NS NSEC +sub.example.net. 3600 IN RRSIG NSEC 5 3 3600 20070926134150 20070829134150 30899 example.net. eNJ2OPjMhGKvg70aYT9l9Uo1lJsqmDqVRMlHibv6t+CNjljytI9Vwbao17oV0cjIksmESAewReb73x9fmVIgEQ== ;{id = 30899} +SECTION ADDITIONAL +ENTRY_END + +; delegation to sub.example.net, securely insecure. +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +sub.example.net. IN NS +SECTION ANSWER +SECTION AUTHORITY +sub.example.net. IN NS ns.sub.example.net. +sub.example.net. IN NSEC tut.example.net. NS NSEC +sub.example.net. 3600 IN RRSIG NSEC 5 3 3600 20070926134150 20070829134150 30899 example.net. eNJ2OPjMhGKvg70aYT9l9Uo1lJsqmDqVRMlHibv6t+CNjljytI9Vwbao17oV0cjIksmESAewReb73x9fmVIgEQ== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.net. IN A 1.2.3.6 +ENTRY_END + + +RANGE_END + +; ns.sub.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 +; DS is +; sub.example.net. 3600 IN DS 30899 5 1 36b39460f94a807cbbbf3b31cc9db955081b2b36 ; xetir-fahok-bovug-pebyl-sovur-zyvaf-cufan-tivih-hadec-rypof-kixox +; DNSKEY query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.net. IN DNSKEY +SECTION ANSWER +sub.example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.net. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.net. PATh0K1jz9QeN02C79noX9gwK+Nr5VznWPQwygm/pYDsOb0z3EsaiOrzyoreegDKgoNn3kN0CywS+usCWM6hrw== ;{id = 30899} +SECTION AUTHORITY +sub.example.net. IN NS ns.sub.example.net. +sub.example.net. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.net. JZUK303aE7R428S5XXLaowpM79YSc2g7wy2rDOH+6Ts2UefZInv6X5cjJU4+qBrS8i9XhdllqG7SEnPKZ0GtAw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.net. IN A 1.2.3.6 +ns.sub.example.net. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.net. AluXPa4XdlCysQMVrt0YairoOug4GMvy8rNUeKLCfQ5xVqRMqkTisbzJXBQPgYEVA0DJR74eEpgLrcz5ztb1aA== ;{id = 30899} +ENTRY_END + +; NS query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.net. IN NS +SECTION ANSWER +sub.example.net. IN NS ns.sub.example.net. +sub.example.net. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.net. JZUK303aE7R428S5XXLaowpM79YSc2g7wy2rDOH+6Ts2UefZInv6X5cjJU4+qBrS8i9XhdllqG7SEnPKZ0GtAw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.net. IN A 1.2.3.6 +ns.sub.example.net. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.net. AluXPa4XdlCysQMVrt0YairoOug4GMvy8rNUeKLCfQ5xVqRMqkTisbzJXBQPgYEVA0DJR74eEpgLrcz5ztb1aA== ;{id = 30899} +ENTRY_END + +; www.sub.example.net query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.sub.example.net. IN A +SECTION ANSWER +www.sub.example.net. IN A 10.20.30.40 +www.sub.example.net. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.net. Q+88AIM3K8q6S0bHeFVT742EepZFxOxgtaL1V68DEkP4NePKzL4zttWQD3uI/5ALw/fIrC7G43Eo+epWn2ZGCA== ;{id = 30899} +SECTION AUTHORITY +sub.example.net. IN NS ns.sub.example.net. +sub.example.net. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.net. JZUK303aE7R428S5XXLaowpM79YSc2g7wy2rDOH+6Ts2UefZInv6X5cjJU4+qBrS8i9XhdllqG7SEnPKZ0GtAw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.net. IN A 1.2.3.6 +ns.sub.example.net. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.net. AluXPa4XdlCysQMVrt0YairoOug4GMvy8rNUeKLCfQ5xVqRMqkTisbzJXBQPgYEVA0DJR74eEpgLrcz5ztb1aA== ;{id = 30899} +ENTRY_END + + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.net. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.sub.example.net. IN A +SECTION ANSWER +www.sub.example.net. IN A 10.20.30.40 +www.sub.example.net. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.net. Q+88AIM3K8q6S0bHeFVT742EepZFxOxgtaL1V68DEkP4NePKzL4zttWQD3uI/5ALw/fIrC7G43Eo+epWn2ZGCA== ;{id = 30899} +SECTION AUTHORITY +sub.example.net. IN NS ns.sub.example.net. +sub.example.net. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.net. JZUK303aE7R428S5XXLaowpM79YSc2g7wy2rDOH+6Ts2UefZInv6X5cjJU4+qBrS8i9XhdllqG7SEnPKZ0GtAw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.net. IN A 1.2.3.6 +ns.sub.example.net. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.net. AluXPa4XdlCysQMVrt0YairoOug4GMvy8rNUeKLCfQ5xVqRMqkTisbzJXBQPgYEVA0DJR74eEpgLrcz5ztb1aA== ;{id = 30899} +ENTRY_END + +SCENARIO_END diff --git a/testdata/dlv_delegation.rpl b/testdata/dlv_delegation.rpl new file mode 100644 index 00000000000..3643f8cebf9 --- /dev/null +++ b/testdata/dlv_delegation.rpl @@ -0,0 +1,331 @@ +; config options +; The island of trust is at example.com (the DLV repository) +server: + dlv-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with delegation in DLV repository +; positive response for DLV. +; but the DLV repository has a (secure) delegation inside it. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; referral to the net.example.com DLV server +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net.example.com. IN DLV +SECTION ANSWER +SECTION AUTHORITY +net.example.com. NS ns.net.example.com. +net.example.com. 3600 IN DS 2854 3 1 24d80cd822bc4083cf491b7f055890345a77dd9b ; xenat-myfat-memir-sabym-fefig-nakol-zucyh-megef-gakel-lolyn-ruxox +net.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. AA0APyTN12wzj1XmDEZe+wrPE1hkLAINKT8cT9zGup7zX3O8R4Ki2N8= ;{id = 2854} +SECTION ADDITIONAL +ns.net.example.com. A 1.2.3.6 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +com.example.com. IN DLV +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AKPJnPBqfJKxE4P2iVYkSRJno9HmiXJZtjdqE8oBeq9Lk9FytcMdcig= ;{id = 2854} +example.com IN NSEC net.example.com. SOA NS RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. AJEvfI+tX6Y1OF0h1CNHERJjXaaTsmLWTMLgXk4UYJl8JjAikCpsf9Q= ;{id = 2854} +ENTRY_END + +RANGE_END + +; ns.net.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 +; NS query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net.example.com. IN NS +SECTION ANSWER +net.example.com. NS ns.net.example.com. +net.example.com. 3600 IN RRSIG NS 3 3 3600 20070926134150 20070829134150 2854 net.example.com. AHjTvB20SzZVV9P3LXJ6lVzFWCoDk7T71VHllOwmom3a/EutlUpsgNM= ;{id = 2854} +SECTION ADDITIONAL +ns.net.example.com. A 1.2.3.6 +ns.net.example.com. 3600 IN RRSIG A 3 4 3600 20070926134150 20070829134150 2854 net.example.com. AE2wjNCJayCBi6e8QAGwgujdMC2LbVWQVbQCuQx+grjoQJXQxxpFB5I= ;{id = 2854} +ENTRY_END + +; DNSKEY query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net.example.com. IN DNSKEY +SECTION ANSWER +net.example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJIIs70j+sDS/UT2QRp61SE7S3EEXopNXoFE73JLRmvpi/UrOO/Vz4Se6wXv/CYCKjGw06U4WRgRYXcpEhJROyNapmdIKSxhOzfLVE1gqA0PweZR8dtY3aNQSRn3sPpwJr6Mi/PqQKAMMrZ9ckJpf1+bQMOOvxgzz2U1GS18b3yZKcgTMEaJzd/GZYzi/BN2DzQ0MsrSwYXfsNLFOBbs8PJMW4LYIxeeOe6rUgkWOF7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +net.example.com. 3600 IN RRSIG DNSKEY 3 3 3600 20070926134150 20070829134150 2854 net.example.com. ADgKDV1Yi2iFOXFUN1XkvBU7KW/rdtGcOEdc9VMIxfIKDo5h24E5fqs= ;{id = 2854} +SECTION AUTHORITY +net.example.com. NS ns.net.example.com. +net.example.com. 3600 IN RRSIG NS 3 3 3600 20070926134150 20070829134150 2854 net.example.com. AHjTvB20SzZVV9P3LXJ6lVzFWCoDk7T71VHllOwmom3a/EutlUpsgNM= ;{id = 2854} +SECTION ADDITIONAL +ns.net.example.com. A 1.2.3.6 +ns.net.example.com. 3600 IN RRSIG A 3 4 3600 20070926134150 20070829134150 2854 net.example.com. AE2wjNCJayCBi6e8QAGwgujdMC2LbVWQVbQCuQx+grjoQJXQxxpFB5I= ;{id = 2854} +ENTRY_END + +; DLV apex +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net.example.com. IN DLV +SECTION ANSWER +SECTION AUTHORITY +net.example.com. SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600 +net.example.com. 3600 IN RRSIG SOA 3 3 3600 20070926134150 20070829134150 2854 net.example.com. AKAjedAeGWRHaqhDhNhbTvVUQMgCspiD4GNC7dMVbEZSd87AFcqwg1Y= ;{id = 2854} +net.example.com. NSEC example.net.example.com. SOA NS DNSKEY RRSIG NSEC +net.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 net.example.com. AAHqj3xDqng7ZuNFn89sTjTo2qfuXTv0yR6v8mZ1+L5mCsOwjpGXrJw= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +; DLV of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net.example.com. IN DLV +SECTION ANSWER +example.net.example.com. 3600 IN DLV 30899 5 1 14188c885f20623ad1d3bec42798f3f951793e4c ; xehac-mofum-malyd-bomaf-pegit-fuzes-ganin-misiz-nigel-nozog-soxix +example.net.example.com. 3600 IN RRSIG DLV 3 4 3600 20070926134150 20070829134150 2854 net.example.com. AIZmoTbAlXYwLknm84i7sbglbHr1Iq7t0yyTENO/MsPj7K/mvEQAI/g= ;{id = 2854} +SECTION AUTHORITY +net.example.com. NS ns.net.example.com. +net.example.com. 3600 IN RRSIG NS 3 3 3600 20070926134150 20070829134150 2854 net.example.com. AHjTvB20SzZVV9P3LXJ6lVzFWCoDk7T71VHllOwmom3a/EutlUpsgNM= ;{id = 2854} +SECTION ADDITIONAL +ns.net.example.com. A 1.2.3.6 +ns.net.example.com. 3600 IN RRSIG A 3 4 3600 20070926134150 20070829134150 2854 net.example.com. AE2wjNCJayCBi6e8QAGwgujdMC2LbVWQVbQCuQx+grjoQJXQxxpFB5I= ;{id = 2854} +ENTRY_END + +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +; DS RR is +; example.net. 3600 IN DS 30899 5 1 14188c885f20623ad1d3bec42798f3f951793e4c ; xehac-mofum-malyd-bomaf-pegit-fuzes-ganin-misiz-nigel-nozog-soxix +; DNSKEY prime query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN DNSKEY +SECTION ANSWER +example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.net. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; NS query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; www.example.net query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +www.example.net. 3600 IN A 10.20.30.40 +www.example.net. 3600 IN RRSIG A 5 3 3600 20070926135752 20070829135752 30899 example.net. ACvv4RQVC7TbI57ewqFImRaVoymktJ5Cxn/FaCodIENt82LVM92nivbP2WtwWCsQHWp7FkrMxTlQTJwyAeXFyg== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.net. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +www.example.net. 3600 IN A 10.20.30.40 +www.example.net. 3600 IN RRSIG A 5 3 3600 20070926135752 20070829135752 30899 example.net. ACvv4RQVC7TbI57ewqFImRaVoymktJ5Cxn/FaCodIENt82LVM92nivbP2WtwWCsQHWp7FkrMxTlQTJwyAeXFyg== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +SCENARIO_END diff --git a/testdata/dlv_ds_lookup.rpl b/testdata/dlv_ds_lookup.rpl new file mode 100644 index 00000000000..50e0fc2ec6c --- /dev/null +++ b/testdata/dlv_ds_lookup.rpl @@ -0,0 +1,278 @@ +; config options +; The island of trust is at example.com (the DLV repository) +server: + dlv-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with DLV anchor for a DS lookup. +; positive response for DLV. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN DS +SECTION AUTHORITY +net. 900 IN SOA a.gtld-servers.net. nstld.verisign-grs.com. 1251367385 1800 900 604800 86400 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; DLV query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net.example.com. IN DLV +SECTION ANSWER +example.net.example.com. 3600 IN DLV 30899 5 1 14188c885f20623ad1d3bec42798f3f951793e4c ; xehac-mofum-malyd-bomaf-pegit-fuzes-ganin-misiz-nigel-nozog-soxix +example.net.example.com. 3600 IN RRSIG DLV 3 4 3600 20070926134150 20070829134150 2854 example.com. ACK48Q/oKwh/SM9yRiKjZYuc+AtEZ2yCPNJ15kKCN8nsVcv7xigmNTY= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net.example.com. IN DLV +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AKPJnPBqfJKxE4P2iVYkSRJno9HmiXJZtjdqE8oBeq9Lk9FytcMdcig= ;{id = 2854} +example.com IN NSEC example.net.example.com. SOA NS RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. AIoUkJ04/7/kJFDLocoqksqt9UL2RHHwlRfXAMxGdBHcNO+GSpG47Uk= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +com.example.com. IN DLV +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AKPJnPBqfJKxE4P2iVYkSRJno9HmiXJZtjdqE8oBeq9Lk9FytcMdcig= ;{id = 2854} +example.com IN NSEC example.net.example.com. SOA NS RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. AIoUkJ04/7/kJFDLocoqksqt9UL2RHHwlRfXAMxGdBHcNO+GSpG47Uk= ;{id = 2854} +ENTRY_END + +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +; DS RR is +; example.net. 3600 IN DS 30899 5 1 14188c885f20623ad1d3bec42798f3f951793e4c ; xehac-mofum-malyd-bomaf-pegit-fuzes-ganin-misiz-nigel-nozog-soxix +; DNSKEY prime query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN DNSKEY +SECTION ANSWER +example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.net. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; NS query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; www.example.net query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +www.example.net. 3600 IN A 10.20.30.40 +www.example.net. 3600 IN RRSIG A 5 3 3600 20070926135752 20070829135752 30899 example.net. ACvv4RQVC7TbI57ewqFImRaVoymktJ5Cxn/FaCodIENt82LVM92nivbP2WtwWCsQHWp7FkrMxTlQTJwyAeXFyg== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +example.net. IN DS +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +example.net. IN DS +SECTION AUTHORITY +net. 900 IN SOA a.gtld-servers.net. nstld.verisign-grs.com. 1251367385 1800 900 604800 86400 +ENTRY_END + +SCENARIO_END diff --git a/testdata/dlv_insecure.rpl b/testdata/dlv_insecure.rpl new file mode 100644 index 00000000000..f466b9131c9 --- /dev/null +++ b/testdata/dlv_insecure.rpl @@ -0,0 +1,250 @@ +; config options +; The island of trust is at example.com (the DLV repository) +server: + dlv-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + harden-referral-path: no + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with insecure zone with no DLV + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; DLV query +; could be picked out of the negative cache due to NS queries in between. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +www.example.net.example.com. IN DLV +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AKPJnPBqfJKxE4P2iVYkSRJno9HmiXJZtjdqE8oBeq9Lk9FytcMdcig= ;{id = 2854} +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +example.com IN NSEC zazz.example.com. SOA NS RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926135752 20070829135752 2854 example.com. AAi21jQpno6gXnrPrtK0NvNgX9B8E9U5RvTd47QiCWLF7KdtKxB7Xz0= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +net.example.com. IN DLV +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AKPJnPBqfJKxE4P2iVYkSRJno9HmiXJZtjdqE8oBeq9Lk9FytcMdcig= ;{id = 2854} +example.com IN NSEC zazz.example.com. SOA NS RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926135752 20070829135752 2854 example.com. AAi21jQpno6gXnrPrtK0NvNgX9B8E9U5RvTd47QiCWLF7KdtKxB7Xz0= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +com.example.com. IN DLV +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AKPJnPBqfJKxE4P2iVYkSRJno9HmiXJZtjdqE8oBeq9Lk9FytcMdcig= ;{id = 2854} +example.com IN NSEC zazz.example.com. SOA NS RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926135752 20070829135752 2854 example.com. AAi21jQpno6gXnrPrtK0NvNgX9B8E9U5RvTd47QiCWLF7KdtKxB7Xz0= ;{id = 2854} +ENTRY_END + +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +; NS query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END + +; www.example.net query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +www.example.net. 3600 IN A 10.20.30.40 +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END + + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.net. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +www.example.net. 3600 IN A 10.20.30.40 +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END + +SCENARIO_END diff --git a/testdata/dlv_insecure_negcache.rpl b/testdata/dlv_insecure_negcache.rpl new file mode 100644 index 00000000000..55aa9278cb4 --- /dev/null +++ b/testdata/dlv_insecure_negcache.rpl @@ -0,0 +1,307 @@ +; config options +; The island of trust is at example.com (the DLV repository) +server: + dlv-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + harden-referral-path: no + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with insecure zone, no DLV from negative cache + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 300 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; DLV query +; could be picked out of the negative cache due to NS queries in between. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +www.example.net.example.com. IN DLV +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AKPJnPBqfJKxE4P2iVYkSRJno9HmiXJZtjdqE8oBeq9Lk9FytcMdcig= ;{id = 2854} +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +zoink.name.example.com IN NSEC zazz.net.example.com. RRSIG NSEC DLV +zoink.name.example.com. 3600 IN RRSIG NSEC 3 4 3600 20070926134150 20070829134150 2854 example.com. AHipxvshRHglCEN4nZCT4m/4RIj8TrCOE2AsqEoH9e+6OYSo+yuNzzo= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net.example.com. IN DLV +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AKPJnPBqfJKxE4P2iVYkSRJno9HmiXJZtjdqE8oBeq9Lk9FytcMdcig= ;{id = 2854} +zoink.name.example.com IN NSEC zazz.net.example.com. RRSIG NSEC DLV +zoink.name.example.com. 3600 IN RRSIG NSEC 3 4 3600 20070926134150 20070829134150 2854 example.com. AHipxvshRHglCEN4nZCT4m/4RIj8TrCOE2AsqEoH9e+6OYSo+yuNzzo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DLV +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AKPJnPBqfJKxE4P2iVYkSRJno9HmiXJZtjdqE8oBeq9Lk9FytcMdcig= ;{id = 2854} +example.com IN NSEC frump.aqua.example.com. SOA NS RRSIG NSEC DNSKEY +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. AAscY9DfNm3Uy8f8Q4WX6AzR0flHYNSr3fKfgQ0Xc20fzj1lGP9ebfk= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +com.example.com. IN DLV +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AKPJnPBqfJKxE4P2iVYkSRJno9HmiXJZtjdqE8oBeq9Lk9FytcMdcig= ;{id = 2854} +example.com IN NSEC zazz.example.com. SOA NS RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926135752 20070829135752 2854 example.com. AAi21jQpno6gXnrPrtK0NvNgX9B8E9U5RvTd47QiCWLF7KdtKxB7Xz0= ;{id = 2854} +ENTRY_END + +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 300 + ADDRESS 1.2.3.5 +; NS query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END + +; www.example.net query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +www.example.net. 10 IN A 10.20.30.40 +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END + + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.net. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +www.example.net. 10 IN A 10.20.30.40 +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END + +STEP 150 TIME_PASSES ELAPSE 30 + +; no more DLV authority reachable +STEP 200 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.net. IN A +ENTRY_END + +STEP 210 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +www.example.net. 10 IN A 10.20.30.40 +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END + +STEP 220 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +net. IN NS +ENTRY_END + +STEP 230 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +SCENARIO_END diff --git a/testdata/dlv_keyretry.rpl b/testdata/dlv_keyretry.rpl new file mode 100644 index 00000000000..fc472da1924 --- /dev/null +++ b/testdata/dlv_keyretry.rpl @@ -0,0 +1,284 @@ +; config options +; The island of trust is at example.com (the DLV repository) +server: + dlv-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with DLV anchor and subsequently key retries +; positive response for DLV. But the DNSKEY for the target fails validation. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; DLV query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net.example.com. IN DLV +SECTION ANSWER +example.net.example.com. 3600 IN DLV 30899 5 1 14188c885f20623ad1d3bec42798f3f951793e4c ; xehac-mofum-malyd-bomaf-pegit-fuzes-ganin-misiz-nigel-nozog-soxix +example.net.example.com. 3600 IN RRSIG DLV 3 4 3600 20070926134150 20070829134150 2854 example.com. ACK48Q/oKwh/SM9yRiKjZYuc+AtEZ2yCPNJ15kKCN8nsVcv7xigmNTY= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net.example.com. IN DLV +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AKPJnPBqfJKxE4P2iVYkSRJno9HmiXJZtjdqE8oBeq9Lk9FytcMdcig= ;{id = 2854} +example.com IN NSEC example.net.example.com. SOA NS RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. AIoUkJ04/7/kJFDLocoqksqt9UL2RHHwlRfXAMxGdBHcNO+GSpG47Uk= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +com.example.com. IN DLV +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AKPJnPBqfJKxE4P2iVYkSRJno9HmiXJZtjdqE8oBeq9Lk9FytcMdcig= ;{id = 2854} +example.com IN NSEC example.net.example.com. SOA NS RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. AIoUkJ04/7/kJFDLocoqksqt9UL2RHHwlRfXAMxGdBHcNO+GSpG47Uk= ;{id = 2854} +ENTRY_END + +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +; DS RR is +; example.net. 3600 IN DS 30899 5 1 14188c885f20623ad1d3bec42798f3f951793e4c ; xehac-mofum-malyd-bomaf-pegit-fuzes-ganin-misiz-nigel-nozog-soxix +; DNSKEY prime query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN DNSKEY +SECTION ANSWER +example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +; expired signature +example.net. 3600 IN RRSIG DNSKEY 5 2 3600 20050926134150 20050829134150 30899 example.net. ydM0/eWMqFn4RxMTbscdSLU7bJNoPuzjCa0eI7HSV/r/54slSGvkl0fmwqrROl1tpc0YMV6kAzgB1T5lJbvdsA== ;{id = 30899} +; good signature: +;example.net. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; NS query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; AAAA for nameserver (for dnssec retry) query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION AUTHORITY +example.net. IN SOA . . 2007091300 28800 7200 604800 3600 +example.net. 3600 IN RRSIG SOA 5 2 3600 20070926134150 20070829134150 30899 example.net. MrpP4svNpbN/YKhuYRlNbvNg0yVxn4ywW1tyEFA9v6F7BR6k1pP8iPfN5XV+XWPAmbss9h3fwKq8zNs4F/SPkg== ;{id = 30899} +ns.example.net. IN NSEC ppp.example.net. A RRSIG NSEC +ns.example.net. 3600 IN RRSIG NSEC 5 3 3600 20070926134150 20070829134150 30899 example.net. freWP6rXWsU5iyRE2gIM9rICuBxCYlQSW01GkLPez5czqtEL0hHN8vtjTlfoNxjJjiZj3vAavZDIQGgOOOMIsA== ;{id = 30899} +ENTRY_END + +; www.example.net query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +www.example.net. 3600 IN A 10.20.30.40 +www.example.net. 3600 IN RRSIG A 5 3 3600 20070926135752 20070829135752 30899 example.net. ACvv4RQVC7TbI57ewqFImRaVoymktJ5Cxn/FaCodIENt82LVM92nivbP2WtwWCsQHWp7FkrMxTlQTJwyAeXFyg== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.net. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +ENTRY_END + +SCENARIO_END diff --git a/testdata/dlv_negnx.rpl b/testdata/dlv_negnx.rpl new file mode 100644 index 00000000000..866746ad680 --- /dev/null +++ b/testdata/dlv_negnx.rpl @@ -0,0 +1,402 @@ +; config options +; The island of trust is at example.com (the DLV repository) +server: + dlv-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with DLV anchor for negcache nxdomain proof +; put a DLV in the negcache. +; then test ask-higher with that in the cache. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; DLV query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net.example.com. IN DLV +SECTION ANSWER +example.net.example.com. 3600 IN DLV 30899 5 1 14188c885f20623ad1d3bec42798f3f951793e4c ; xehac-mofum-malyd-bomaf-pegit-fuzes-ganin-misiz-nigel-nozog-soxix +example.net.example.com. 3600 IN RRSIG DLV 3 4 3600 20070926134150 20070829134150 2854 example.com. ACK48Q/oKwh/SM9yRiKjZYuc+AtEZ2yCPNJ15kKCN8nsVcv7xigmNTY= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; under example.net in DLV +ENTRY_BEGIN +MATCH opcode qtype subdomain +ADJUST copy_id copy_query +REPLY QR NXDOMAIN +SECTION QUESTION +example.net.example.com. IN DLV +SECTION ANSWER +SECTION AUTHORITY +example.net.example.com. 3600 IN NSEC fru.net.example.com. RRSIG NSEC DLV +example.net.example.com. 3600 IN RRSIG NSEC 3 4 3600 20070926134150 20070829134150 2854 example.com. AI6NNKt4dGcAdCrW73GYwyoqelsdj1dd8mBNPpHRQIL0yp7yYFZ7kXU= ;{id = 2854} +example.com. IN SOA . . 1 2 3 4 5 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AIkRPbv+kZaiG61pH/wQy8fX2UqQS5YRwHaxe4yjEUXk59fgO71Db3s= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net.example.com. IN DLV +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AKPJnPBqfJKxE4P2iVYkSRJno9HmiXJZtjdqE8oBeq9Lk9FytcMdcig= ;{id = 2854} +example.com IN NSEC example.net.example.com. SOA NS RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. AIoUkJ04/7/kJFDLocoqksqt9UL2RHHwlRfXAMxGdBHcNO+GSpG47Uk= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +com.example.com. IN DLV +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AKPJnPBqfJKxE4P2iVYkSRJno9HmiXJZtjdqE8oBeq9Lk9FytcMdcig= ;{id = 2854} +example.com IN NSEC example.net.example.com. SOA NS RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. AIoUkJ04/7/kJFDLocoqksqt9UL2RHHwlRfXAMxGdBHcNO+GSpG47Uk= ;{id = 2854} +ENTRY_END + +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +; DS RR is +; example.net. 3600 IN DS 30899 5 1 14188c885f20623ad1d3bec42798f3f951793e4c ; xehac-mofum-malyd-bomaf-pegit-fuzes-ganin-misiz-nigel-nozog-soxix +; DNSKEY prime query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN DNSKEY +SECTION ANSWER +; have it flushed out of the cache quickly. +example.net. 0 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.net. 0 IN RRSIG DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; NS query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; www.example.net query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +www.example.net. 3600 IN A 10.20.30.40 +www.example.net. 3600 IN RRSIG A 5 3 3600 20070926135752 20070829135752 30899 example.net. ACvv4RQVC7TbI57ewqFImRaVoymktJ5Cxn/FaCodIENt82LVM92nivbP2WtwWCsQHWp7FkrMxTlQTJwyAeXFyg== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; subzone +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +sub1.example.net. IN A +SECTION ANSWER +SECTION AUTHORITY +sub1.example.net. 3600 IN DS 30899 5 1 8916603e54c6f7edcfd885602e3b7b8dc475ba5c ; xodec-komif-vehis-kotav-tefot-mecyk-biryf-rivym-ticol-huvyh-saxox +sub1.example.net. 3600 IN RRSIG DS 5 3 3600 20070926134150 20070829134150 30899 example.net. A3vVrEY3+oIUqdbAa3tkKaU3o47eBD01hVXfAEAue1M+Uci2PA5YyiulLzStyiP75XUXkvubLQ2+ltKMTtfdag== ;{id = 30899} +sub1.example.net. IN NS ns.sub1.example.net. +SECTION ADDITIONAL +ns.sub1.example.net. IN A 1.2.3.10 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +sub2.example.net. IN A +SECTION ANSWER +SECTION AUTHORITY +sub2.example.net. 3600 IN DS 30899 5 1 627f7a51f1545133fec3ecbd19b85b92b15679c9 ; ximil-zovah-casuh-gygef-fyzas-farir-tikir-mukon-disih-kavus-nyxex +sub2.example.net. 3600 IN RRSIG DS 5 3 3600 20070926134150 20070829134150 30899 example.net. azMXKt4VPHj2hk5MDU6h8E/HOtNnHnIVS6Le3BV43wtJcHG5wlCxOksOZBOpXMkpbWLvbCJOOMPOnh31nlbjgg== ;{id = 30899} +sub2.example.net. IN NS ns.sub2.example.net. +SECTION ADDITIONAL +ns.sub2.example.net. IN A 1.2.3.12 +ENTRY_END +RANGE_END + +; sub1.example.net. +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.10 +; DNSKEY query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub1.example.net. IN DNSKEY +SECTION ANSWER +sub1.example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub1.example.net. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub1.example.net. E200eTdRnkL7/fk54i1nXEE9a/rC2GxZfVkWMU044tpwV6d4XRxVhlFBzY4FytbRFFBUDhz7L3B0qC6BXJM8rg== ;{id = 30899} +ENTRY_END + +; www query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub1.example.net. IN A +SECTION ANSWER +www.sub1.example.net. IN A 192.168.1.1 +www.sub1.example.net. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub1.example.net. JKxcjPjc/TsQmUmCYHLQa3cBk1c+SbDPtVml69nDWC167NNWG8OLjLrLtUBVCfbTzCmqOWXq2qhrGPxjO65GCQ== ;{id = 30899} +ENTRY_END + +RANGE_END + +; sub2.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.12 +; DNSKEY query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub2.example.net. IN DNSKEY +SECTION ANSWER +sub2.example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub2.example.net. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub2.example.net. VcNaPuz9Mmjj5ofZqOa4FsixBomFJTjd/9wxhZOVdxf1LsNR5L++8k09gQvnjtCvqSPfNer/uv0xl+9sRr8Wmw== ;{id = 30899} +ENTRY_END + +; www query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub2.example.net. IN A +SECTION ANSWER +www.sub2.example.net. IN A 192.168.1.12 +www.sub2.example.net. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub2.example.net. PsWY6+5/0+hsTOhNak/jdSeG44hvHgX5az1Q5XY/YkIchsflH9rmvP1EruFhflNhRR+22M7POiljYOoD5ylQXQ== ;{id = 30899} +ENTRY_END + +RANGE_END + + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub1.example.net. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.sub1.example.net. IN A +SECTION ANSWER +www.sub1.example.net. IN A 192.168.1.1 +www.sub1.example.net. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub1.example.net. JKxcjPjc/TsQmUmCYHLQa3cBk1c+SbDPtVml69nDWC167NNWG8OLjLrLtUBVCfbTzCmqOWXq2qhrGPxjO65GCQ== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +; have example.net DNSKEY time out +STEP 14 TIME_PASSES ELAPSE 1.0 + +STEP 20 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub2.example.net. IN A +ENTRY_END + +STEP 30 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.sub2.example.net. IN A +SECTION ANSWER +www.sub2.example.net. IN A 192.168.1.12 +www.sub2.example.net. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub2.example.net. PsWY6+5/0+hsTOhNak/jdSeG44hvHgX5az1Q5XY/YkIchsflH9rmvP1EruFhflNhRR+22M7POiljYOoD5ylQXQ== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + + +SCENARIO_END diff --git a/testdata/dlv_optout.rpl b/testdata/dlv_optout.rpl new file mode 100644 index 00000000000..1b9d7b2ba2f --- /dev/null +++ b/testdata/dlv_optout.rpl @@ -0,0 +1,437 @@ +; config options +; The island of trust is at example.com (the DLV repository) +server: + dlv-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + trust-anchor: "example.net. 3600 IN DS 30899 5 1 14188c885f20623ad1d3bec42798f3f951793e4c ; xehac-mofum-malyd-bomaf-pegit-fuzes-ganin-misiz-nigel-nozog-soxix" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator, DLV to zone below optout, check negative cache. +; DLV example.com. +; trust anchor at example.net but no secure delegation to +; sub.example.net signed with DLV but not by parent. +; parent uses optout NSEC3. +; then a signed delegation to down.sub.example.net. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; DLV query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.net.example.com. IN DLV +SECTION ANSWER +sub.example.net.example.com. 3600 IN DLV 30899 5 1 36b39460f94a807cbbbf3b31cc9db955081b2b36 ; xetir-fahok-bovug-pebyl-sovur-zyvaf-cufan-tivih-hadec-rypof-kixox +sub.example.net.example.com. 3600 IN RRSIG DLV 3 5 3600 20070926135752 20070829135752 2854 example.com. AAdhy87nuDEaxmc+k9pJHYnhKiEYL++OLPxzOdwEQOtsHi7jeD3lRDU= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +down.sub.example.net.example.com. IN DLV +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AKPJnPBqfJKxE4P2iVYkSRJno9HmiXJZtjdqE8oBeq9Lk9FytcMdcig= ;{id = 2854} +sub.example.net.example.com. IN NSEC zzz.example.net.example.com. RRSIG NSEC DLV +sub.example.net.example.com. 3600 IN RRSIG NSEC 3 5 3600 20070926134150 20070829134150 2854 example.com. AG/M+H/lex1CMTIuO+JpdmTjCzt7XBsLtRLPDfYTykhxnnECzZwkMnQ= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net.example.com. IN DLV +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AKPJnPBqfJKxE4P2iVYkSRJno9HmiXJZtjdqE8oBeq9Lk9FytcMdcig= ;{id = 2854} +example.com IN NSEC sub.example.net.example.com. SOA NS RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926135752 20070829135752 2854 example.com. ALITtZY03PDWnuAeEL/5VwMIXY3iC2y7Qkeq5DgAHmPbNyWiOmJNEKg= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +com.example.com. IN DLV +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AKPJnPBqfJKxE4P2iVYkSRJno9HmiXJZtjdqE8oBeq9Lk9FytcMdcig= ;{id = 2854} +example.com IN NSEC sub.example.net.example.com. SOA NS RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926135752 20070829135752 2854 example.com. ALITtZY03PDWnuAeEL/5VwMIXY3iC2y7Qkeq5DgAHmPbNyWiOmJNEKg= ;{id = 2854} +ENTRY_END + +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +; DS RR is +; example.net. 3600 IN DS 30899 5 1 14188c885f20623ad1d3bec42798f3f951793e4c ; xehac-mofum-malyd-bomaf-pegit-fuzes-ganin-misiz-nigel-nozog-soxix +; DNSKEY prime query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN DNSKEY +SECTION ANSWER +example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.net. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; NS query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; no DS to sub.example.net, optout NSEC3. +; NSEC3PARAM 1 1 31 DE15C001 +; example.net. -> hk4jq0lg6q3bt992urc88dqten1k2be8. +; sub.example.net. -> ecs17hqd0kf7dk9g1cjvevj25pginrf2. +; *.example.net. -> 1tgbedpeeuubbsejh2dqvso62f8n4dk1. +; down.sub.example.net. -> 9j1r8re9b1238vd907tilclgat1i0fre. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.net. IN DS +SECTION ANSWER +SECTION AUTHORITY +example.net. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600 +example.net. 3600 IN RRSIG SOA 5 2 3600 20070926134150 20070829134150 30899 example.net. ELVULZHTRc0Qk06rSBRnB/T6sm1+AbAtdEJHN6PCsz2Z3s3E5A8NH7Krz0VzRaYIEUStnbAtuE3oP8XHWHBnyQ== ;{id = 30899} +; CE is example.net +hk4jq0lg6q3bt992urc88dqten1k2be8.example.net. IN NSEC3 1 1 31 DE15C001 hl4jq0lg6q3bt992urc88dqten1k2be8 NS SOA NAPTR RRSIG DNSKEY NSEC3PARAM +hk4jq0lg6q3bt992urc88dqten1k2be8.example.net. 3600 IN RRSIG NSEC3 5 3 3600 20070926134150 20070829134150 30899 example.net. n1dQKbRoB+X4K003RAhdUp6ZUP5dCiwQi+apGfLII8wmCUmw/cKiz7/Ijhs/+88hZwq/7yhlZM0D/yqAUKUiAA== ;{id = 30899} +; NC covers sub.example.net +ebs17hqd0kf7dk9g1cjvevj25pginrf2.example.net. IN NSEC3 1 1 31 de15c001 efs17hqd0kf7dk9g1cjvevj25pginrf2 A RRSIG +ebs17hqd0kf7dk9g1cjvevj25pginrf2.example.net. 3600 IN RRSIG NSEC3 5 3 3600 20070926134150 20070829134150 30899 example.net. oSVB7Dyp7/yaOlT8AFwBJZdqwRRSQ8XFzCpu1AP51JPIuhCg5byepdvY6UC3xXc7YVO6h74tpxFCGqLpRXwDoQ== ;{id = 30899} +SECTION ADDITIONAL +ENTRY_END + +; delegation to sub.example.net, optout NSEC3. +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +sub.example.net. IN NS +SECTION ANSWER +SECTION AUTHORITY +sub.example.net. IN NS ns.sub.example.net. +hk4jq0lg6q3bt992urc88dqten1k2be8.example.net. IN NSEC3 1 1 31 DE15C001 hl4jq0lg6q3bt992urc88dqten1k2be8 NS SOA NAPTR RRSIG DNSKEY NSEC3PARAM +hk4jq0lg6q3bt992urc88dqten1k2be8.example.net. 3600 IN RRSIG NSEC3 5 3 3600 20070926134150 20070829134150 30899 example.net. n1dQKbRoB+X4K003RAhdUp6ZUP5dCiwQi+apGfLII8wmCUmw/cKiz7/Ijhs/+88hZwq/7yhlZM0D/yqAUKUiAA== ;{id = 30899} +ebs17hqd0kf7dk9g1cjvevj25pginrf2.example.net. IN NSEC3 1 1 31 de15c001 efs17hqd0kf7dk9g1cjvevj25pginrf2 A RRSIG +ebs17hqd0kf7dk9g1cjvevj25pginrf2.example.net. 3600 IN RRSIG NSEC3 5 3 3600 20070926134150 20070829134150 30899 example.net. oSVB7Dyp7/yaOlT8AFwBJZdqwRRSQ8XFzCpu1AP51JPIuhCg5byepdvY6UC3xXc7YVO6h74tpxFCGqLpRXwDoQ== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.net. IN A 1.2.3.6 +ENTRY_END + + +RANGE_END + +; ns.sub.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 +; DS is +; sub.example.net. 3600 IN DS 30899 5 1 36b39460f94a807cbbbf3b31cc9db955081b2b36 ; xetir-fahok-bovug-pebyl-sovur-zyvaf-cufan-tivih-hadec-rypof-kixox +; DNSKEY query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.net. IN DNSKEY +SECTION ANSWER +sub.example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.net. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.net. PATh0K1jz9QeN02C79noX9gwK+Nr5VznWPQwygm/pYDsOb0z3EsaiOrzyoreegDKgoNn3kN0CywS+usCWM6hrw== ;{id = 30899} +SECTION AUTHORITY +sub.example.net. IN NS ns.sub.example.net. +sub.example.net. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.net. JZUK303aE7R428S5XXLaowpM79YSc2g7wy2rDOH+6Ts2UefZInv6X5cjJU4+qBrS8i9XhdllqG7SEnPKZ0GtAw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.net. IN A 1.2.3.6 +ns.sub.example.net. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.net. AluXPa4XdlCysQMVrt0YairoOug4GMvy8rNUeKLCfQ5xVqRMqkTisbzJXBQPgYEVA0DJR74eEpgLrcz5ztb1aA== ;{id = 30899} +ENTRY_END + +; NS query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.net. IN NS +SECTION ANSWER +sub.example.net. IN NS ns.sub.example.net. +sub.example.net. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.net. JZUK303aE7R428S5XXLaowpM79YSc2g7wy2rDOH+6Ts2UefZInv6X5cjJU4+qBrS8i9XhdllqG7SEnPKZ0GtAw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.net. IN A 1.2.3.6 +ns.sub.example.net. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.net. AluXPa4XdlCysQMVrt0YairoOug4GMvy8rNUeKLCfQ5xVqRMqkTisbzJXBQPgYEVA0DJR74eEpgLrcz5ztb1aA== ;{id = 30899} +ENTRY_END + +; www.sub.example.net query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.sub.example.net. IN A +SECTION ANSWER +www.sub.example.net. IN A 10.20.30.40 +www.sub.example.net. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.net. Q+88AIM3K8q6S0bHeFVT742EepZFxOxgtaL1V68DEkP4NePKzL4zttWQD3uI/5ALw/fIrC7G43Eo+epWn2ZGCA== ;{id = 30899} +SECTION AUTHORITY +sub.example.net. IN NS ns.sub.example.net. +sub.example.net. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.net. JZUK303aE7R428S5XXLaowpM79YSc2g7wy2rDOH+6Ts2UefZInv6X5cjJU4+qBrS8i9XhdllqG7SEnPKZ0GtAw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.net. IN A 1.2.3.6 +ns.sub.example.net. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.net. AluXPa4XdlCysQMVrt0YairoOug4GMvy8rNUeKLCfQ5xVqRMqkTisbzJXBQPgYEVA0DJR74eEpgLrcz5ztb1aA== ;{id = 30899} +ENTRY_END + +; DS for down.sub.example.net +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +down.sub.example.net. IN DS +SECTION ANSWER +down.sub.example.net. 3600 IN DS 60946 5 1 c636304ab7cdb6272215aceac95a8d312ac7a4f6 +down.sub.example.net. 3600 IN RRSIG DS 5 4 3600 20070926134150 20070829134150 30899 sub.example.net. AMc8J534UF2+0PtPSNBw6RzN4Q5gXfnBXiUfpuT/MR1YtOE/5AP/0dTgvqvKRiFZx3NjOPeZmRnaabxkw0Qzrw== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +; delegation to down.sub.example.net +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +down.sub.example.net. IN NS +SECTION ANSWER +SECTION AUTHORITY +down.sub.example.net. IN NS ns.down.sub.example.net. +; the DS record is not given (like it was parent and child hosted on the same +; server) +;down.sub.example.net. 3600 IN DS 60946 5 1 c636304ab7cdb6272215aceac95a8d312ac7a4f6 +;down.sub.example.net. 3600 IN RRSIG DS 5 4 3600 20070926134150 20070829134150 30899 sub.example.net. AMc8J534UF2+0PtPSNBw6RzN4Q5gXfnBXiUfpuT/MR1YtOE/5AP/0dTgvqvKRiFZx3NjOPeZmRnaabxkw0Qzrw== ;{id = 30899} +SECTION ADDITIONAL +ns.down.sub.example.net. IN A 1.2.3.7 +ENTRY_END + +RANGE_END + +; ns.down.sub.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.7 +; DNSKEY query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +down.sub.example.net. IN DNSKEY +SECTION ANSWER +down.sub.example.net. 3600 IN DNSKEY 257 3 5 AwEAAeiaUiUIpWMfYz5L0sfJTZWnuN9IyBX4em9VjsoqQTsOD1HDQpNb4buvJo7pN2aBCxNS7e0OL8e2mVB6CLZ+8ek= ;{id = 60946 (ksk), size = 512b} +down.sub.example.net. 3600 IN RRSIG DNSKEY 5 4 3600 20070926134150 20070829134150 60946 down.sub.example.net. lK5HNva/IPw0CS9BfBd16fqm5y9bgCSwGsBLBAA1d5SCcKep6AVrv6NFuXl12d1G3MdQ4ruHi6eDDO5dhtkfrw== ;{id = 60946} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +; www.down.sub.example.net. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.down.sub.example.net. IN A +SECTION ANSWER +www.down.sub.example.net. IN A 10.20.30.44 +www.down.sub.example.net. 3600 IN RRSIG A 5 5 3600 20070926134150 20070829134150 60946 down.sub.example.net. Hg5WF/xW8PRth2rl1mZcYK8/pgGpM73e/fD+mH/XElEKgL9zq0ou8psA0I6OvMLGBN6RQeknQHRAy3D2/5k/Wg== ;{id = 60946} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.down.sub.example.net. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.down.sub.example.net. IN A +SECTION ANSWER +www.down.sub.example.net. IN A 10.20.30.44 +www.down.sub.example.net. 3600 IN RRSIG A 5 5 3600 20070926134150 20070829134150 60946 down.sub.example.net. Hg5WF/xW8PRth2rl1mZcYK8/pgGpM73e/fD+mH/XElEKgL9zq0ou8psA0I6OvMLGBN6RQeknQHRAy3D2/5k/Wg== ;{id = 60946} +ENTRY_END + +SCENARIO_END diff --git a/testdata/dlv_unused.rpl b/testdata/dlv_unused.rpl new file mode 100644 index 00000000000..3e4850bc38c --- /dev/null +++ b/testdata/dlv_unused.rpl @@ -0,0 +1,274 @@ +; config options +; The island of trust is at example.com (the DLV repository) +server: + dlv-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + trust-anchor: "example.net. 3600 IN DS 30899 5 1 14188c885f20623ad1d3bec42798f3f951793e4c ; xehac-mofum-malyd-bomaf-pegit-fuzes-ganin-misiz-nigel-nozog-soxix" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator, DLV anchor unused because trustanchor works. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; DLV query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +example.net.example.com. IN DLV +SECTION ANSWER +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +example.com IN NSEC zazz.example.com. SOA NS RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926135752 20070829135752 2854 example.com. AAi21jQpno6gXnrPrtK0NvNgX9B8E9U5RvTd47QiCWLF7KdtKxB7Xz0= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +net.example.com. IN DLV +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AKPJnPBqfJKxE4P2iVYkSRJno9HmiXJZtjdqE8oBeq9Lk9FytcMdcig= ;{id = 2854} +example.com IN NSEC zazz.example.com. SOA NS RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926135752 20070829135752 2854 example.com. AAi21jQpno6gXnrPrtK0NvNgX9B8E9U5RvTd47QiCWLF7KdtKxB7Xz0= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +com.example.com. IN DLV +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AKPJnPBqfJKxE4P2iVYkSRJno9HmiXJZtjdqE8oBeq9Lk9FytcMdcig= ;{id = 2854} +example.com IN NSEC zazz.example.com. SOA NS RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926135752 20070829135752 2854 example.com. AAi21jQpno6gXnrPrtK0NvNgX9B8E9U5RvTd47QiCWLF7KdtKxB7Xz0= ;{id = 2854} +ENTRY_END + +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +; DS RR is +; example.net. 3600 IN DS 30899 5 1 14188c885f20623ad1d3bec42798f3f951793e4c ; xehac-mofum-malyd-bomaf-pegit-fuzes-ganin-misiz-nigel-nozog-soxix +; DNSKEY prime query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN DNSKEY +SECTION ANSWER +example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.net. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; NS query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; www.example.net query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +www.example.net. 3600 IN A 10.20.30.40 +www.example.net. 3600 IN RRSIG A 5 3 3600 20070926135752 20070829135752 30899 example.net. ACvv4RQVC7TbI57ewqFImRaVoymktJ5Cxn/FaCodIENt82LVM92nivbP2WtwWCsQHWp7FkrMxTlQTJwyAeXFyg== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.net. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +www.example.net. 3600 IN A 10.20.30.40 +www.example.net. 3600 IN RRSIG A 5 3 3600 20070926135752 20070829135752 30899 example.net. ACvv4RQVC7TbI57ewqFImRaVoymktJ5Cxn/FaCodIENt82LVM92nivbP2WtwWCsQHWp7FkrMxTlQTJwyAeXFyg== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +SCENARIO_END diff --git a/testdata/domain_insec_dlv.rpl b/testdata/domain_insec_dlv.rpl new file mode 100644 index 00000000000..f3789e68c81 --- /dev/null +++ b/testdata/domain_insec_dlv.rpl @@ -0,0 +1,276 @@ +; config options +; The island of trust is at example.com (the DLV repository) +server: + dlv-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + domain-insecure: "example.net" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with domain-insecure below a DLV +; positive response for DLV. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; DLV query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net.example.com. IN DLV +SECTION ANSWER +example.net.example.com. 3600 IN DLV 30899 5 1 14188c885f20623ad1d3bec42798f3f951793e4c ; xehac-mofum-malyd-bomaf-pegit-fuzes-ganin-misiz-nigel-nozog-soxix +example.net.example.com. 3600 IN RRSIG DLV 3 4 3600 20070926134150 20070829134150 2854 example.com. ACK48Q/oKwh/SM9yRiKjZYuc+AtEZ2yCPNJ15kKCN8nsVcv7xigmNTY= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net.example.com. IN DLV +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AKPJnPBqfJKxE4P2iVYkSRJno9HmiXJZtjdqE8oBeq9Lk9FytcMdcig= ;{id = 2854} +example.com IN NSEC example.net.example.com. SOA NS RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. AIoUkJ04/7/kJFDLocoqksqt9UL2RHHwlRfXAMxGdBHcNO+GSpG47Uk= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +com.example.com. IN DLV +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AKPJnPBqfJKxE4P2iVYkSRJno9HmiXJZtjdqE8oBeq9Lk9FytcMdcig= ;{id = 2854} +example.com IN NSEC example.net.example.com. SOA NS RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. AIoUkJ04/7/kJFDLocoqksqt9UL2RHHwlRfXAMxGdBHcNO+GSpG47Uk= ;{id = 2854} +ENTRY_END + +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +; DS RR is +; example.net. 3600 IN DS 30899 5 1 14188c885f20623ad1d3bec42798f3f951793e4c ; xehac-mofum-malyd-bomaf-pegit-fuzes-ganin-misiz-nigel-nozog-soxix +; DNSKEY prime query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN DNSKEY +SECTION ANSWER +example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.net. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; NS query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; www.example.net query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +www.example.net. 3600 IN A 10.20.30.40 +www.example.net. 3600 IN RRSIG A 5 3 3600 20070926135752 20070829135752 30899 example.net. ACvv4RQVC7TbI57ewqFImRaVoymktJ5Cxn/FaCodIENt82LVM92nivbP2WtwWCsQHWp7FkrMxTlQTJwyAeXFyg== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.net. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +www.example.net. 3600 IN A 10.20.30.40 +www.example.net. 3600 IN RRSIG A 5 3 3600 20070926135752 20070829135752 30899 example.net. ACvv4RQVC7TbI57ewqFImRaVoymktJ5Cxn/FaCodIENt82LVM92nivbP2WtwWCsQHWp7FkrMxTlQTJwyAeXFyg== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +SCENARIO_END diff --git a/testdata/domain_insec_ds.rpl b/testdata/domain_insec_ds.rpl new file mode 100644 index 00000000000..703acbb9cf4 --- /dev/null +++ b/testdata/domain_insec_ds.rpl @@ -0,0 +1,212 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + domain-insecure: "sub.example.com" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with domain-insecure below a DS + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response to DNSKEY priming query +; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899} +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. 3600 IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/edns_cache.tpkg b/testdata/edns_cache.tpkg new file mode 100644 index 0000000000000000000000000000000000000000..63756410856cbb925fbb77896c8f9afbdefe9556 GIT binary patch literal 1830 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 UqC|-jB}x?VAD=*L{QxKc0E4*33IG5A literal 0 HcmV?d00001 diff --git a/testdata/fetch_glue.rpl b/testdata/fetch_glue.rpl new file mode 100644 index 00000000000..9a25d52e2b0 --- /dev/null +++ b/testdata/fetch_glue.rpl @@ -0,0 +1,209 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Fetch glue when missing or timed out. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +; is missing the glue! +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +; is missing the glue! +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION AUTHORITY +example.com. IN NS ns.example.com. +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +; due to ordering of answer packets, this is still outstanding, remove it +STEP 21 CHECK_OUT_QUERY +ENTRY_BEGIN +ADJUST copy_id +MATCH qname qtype +REPLY QR +SECTION QUESTION +ns.example.com IN AAAA +ENTRY_END + +; some more recursion needed. +; to finish the NS query +STEP 40 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +. IN NS +ENTRY_END + +STEP 41 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION AUTHORITY +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +SCENARIO_END diff --git a/testdata/fetch_glue_cname.rpl b/testdata/fetch_glue_cname.rpl new file mode 100644 index 00000000000..46e17fe798e --- /dev/null +++ b/testdata/fetch_glue_cname.rpl @@ -0,0 +1,221 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Fetch cnamed glue when missing or timed out. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +; is missing the glue! +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +; is missing the glue! +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN CNAME ns2.example.com. +SECTION AUTHORITY +example.com. IN NS ns.example.com. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ns2.example.com. IN A +SECTION ANSWER +ns2.example.com. IN A 1.2.3.4 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION AUTHORITY +example.com. IN NS ns.example.com. +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +; due to ordering of answer packets, this is still outstanding, remove it +STEP 21 CHECK_OUT_QUERY +ENTRY_BEGIN +ADJUST copy_id +MATCH qname qtype +REPLY QR +SECTION QUESTION +ns.example.com IN AAAA +ENTRY_END + +; some more recursion needed. +; to finish the NS query +STEP 40 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +. IN NS +ENTRY_END + +STEP 41 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION AUTHORITY +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +SCENARIO_END diff --git a/testdata/fwd.rpl b/testdata/fwd.rpl new file mode 100644 index 00000000000..53b6f9ad1ec --- /dev/null +++ b/testdata/fwd.rpl @@ -0,0 +1,42 @@ +; This is a comment. +; config options go here. +forward-zone: name: "." forward-addr: 216.0.0.1 +CONFIG_END + +SCENARIO_BEGIN Sample of a valid query +RANGE_BEGIN 0 100 + ENTRY_BEGIN + MATCH opcode qtype qname + ADJUST copy_id + REPLY QR RD RA NOERROR + SECTION QUESTION +www.example.com. IN A + SECTION ANSWER +www.example.com. IN A 10.20.30.40 + SECTION AUTHORITY +www.example.com. IN NS ns.example.com. + SECTION ADDITIONAL +ns.example.com. IN A 10.20.30.50 + ENTRY_END +RANGE_END +RANGE_BEGIN 200 300 +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; unneccesary nothing steps. +STEP 2 NOTHING +STEP 3 NOTHING +STEP 4 CHECK_ANSWER +ENTRY_BEGIN +MATCH opcode qname qtype +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ENTRY_END +SCENARIO_END diff --git a/testdata/fwd_ancil.tpkg b/testdata/fwd_ancil.tpkg new file mode 100644 index 0000000000000000000000000000000000000000..09ecfb98e313bca0a7a3abd5238b8cbaaae34c95 GIT binary patch literal 1689 zcmV;K24?vmiwFQB|5Qx?1MOM+bJ|7__OIMuvB8X;Oh>ZBv!gT~6CjQA00Ov~Oxs~( z=>XM2r<|k^I{o9jcOYKI_BgRgYv1Pwx`+1mcJ=M1Lu(U)n4s2u+U*H zh0pOc#Q#Dl=``B!KEa0$RIAWzH9DPEhg9ot&bmEtSUBx_F6lOEz0+0`KAbhW;(|;j zlgw!|Q(cTyo86C%&Z0kK8hYN)3x-}a=2|qGbwYl$9sjSmivMop+}Rp8@xNHEEcjo_ zW4~D{mQ2O}UErl1(I%4Bf`#wNZ@5#B1s0gPLFzPexEIEvoJQ^b!hh>;TLXn1)rXScMAI8a>Dx#?R!v?FBLZ zQEq|Db@-^)^eTRMe+5I^=59o4C}ha^)B;jtv`Cw; zZcGn3C2bbPYkk-zVqdGBA`p^l^7R$QLLsefM-g=`^2+x71Z6&)aB~&^9Tp7kYKrNti>bbub>n5gp4CaPTH+b z?}TK~8d@}sd^WToU?hVN4|QTm&TJMZd#)%Wu#p7kED2m4d$8XbamM1=9AVHvMjp{} znHI2E`Dgx2AJ!jqcZ7;?YbC^vSz*_<(elay_PgU_Q4b!SMgtj z#k*SLCjKMa7w5l1xghvoF;xEF3HD)M(>Br}Xxcv6hlnNIp%9NKjO_@G17FZmg4Zw^ z(Ez;oFcPDfRDTC;0J?sp$Kl0L$7%Zfjz8hxAQiM_e0>#p{J3F_g#bBuP5jyr5j$`h zOmPqeBb(VI04Ycpn&5$E%mO_ckqfM1`WT)d_v&N4-#)DqEN})xPD9ALUSyx6E?Xi{ z7Shm$LGZcIF(4WG)r-L(0}mutWS=!(w$7R}`9Ip{tGJT?oZi_QH}F4i=2!S{o0Ph`4y3&Kz2QSy6Aw#^mB$7fPnLX;tB zD51CS22p?ZT8`x2)tlXZuhH!_yP$=zkO!M@@ZcDGM2Ld?@qq~kWFF*R3;T&-`D~|p#th9lrjUekw;UgDIPA(@vjK>@+;ixm*f~nj zXX0noI!f*{-XGv$bTtV*8KWFWRxmYjl_#4Y^H_JthKWAa*-HXZ$X3eBnEF7 zFitOf6BS5JKxRkE^r*VcMc?3@dveRnDJ$QWWz&1ExBT~*a;*$lHQZK9S=KFVgp(hW zb&^{eD0!?lx;5SIFA)AG?X@m?P4cGTdCdFK6^Vj^f`WpAf`WpAf`WpAf`WpAf`WpA jf`WpAf`WpAf`WpAf`WpAf`WpA!d3VevjCm}08jt`Ce2Zo literal 0 HcmV?d00001 diff --git a/testdata/fwd_bogus.tpkg b/testdata/fwd_bogus.tpkg new file mode 100644 index 0000000000000000000000000000000000000000..e060f5f9cebcdd355c6c3c5cb5422dc93ae25bfc GIT binary patch literal 4096 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 Jfk^-;004$^tD^t_ literal 0 HcmV?d00001 diff --git a/testdata/fwd_capsid_fallback.tpkg b/testdata/fwd_capsid_fallback.tpkg new file mode 100644 index 0000000000000000000000000000000000000000..c6fd4cdf83cc0560c02bf8f95c235e59e86a2294 GIT binary patch literal 1461 zcmV;m1xorKiwFQP098!@1ML~@a@t1Ff4QgFV2_e9 z-g`k%5GtjT_*N?=CGM-mV*I^;Jyk7fB@J5wua*>5+k?_e3b74lJTwD5j6x&8NH zUy@*pwIykv>;q@Bz@iXNC`?U`N`kMbv616ah$hqnCp_X}G@#^nkVYWO$8zZ3jAfiA zFIM~shleSl4dciK^$U0Ckn#{lEC9!YxQ$5193o5KX-9b<9_KYq_J}l{N zv}v*kPH{|j*%-9bLlq8_JvJL}4_>W`ClHIq7U8Dm4F!vNBWE0+2g0ch5``mvd?sZ0 zpp+ATXre(ck99 zL6h_306WL&R0)5rln|UQ(5uQ=%DbwNHRMWXqhc&GypM}aXU%SdnGXviBx4If1b#&( z^4uib9BP^g6!{&UKtau4=vddtkoBYzkk(xsRWMDCy|! z%irKr2WmAiT6(9`>X2IF!*#cZLBpR99Gi6Ydav0s;L|lmFl>+$=pq#yOop=Hz2c;bA%ai<>hzXUv-eT{DC-*8aYZ);cWOI@zB zD;aW4BUf88s~O$C-XT#xs-4#x`o+8V%?}?huZ)LC#1wL>B5R6VP~@VrP=RhV$oKcs z?*~uue-SdD!{agkFO(}w{}*k{|H_({`Ts5;@%$>u;pdQXC!ANINOJq&&8AW~38-oF zDySqUvZN}+*ZLXBp*AEw=Xga`(KAU7j|{a!7U1f99w$4t2qV}@FEhj--kJoAg~=SD zP!T4Qp3Nlma4Gg~$z_)5P8bgp;)0ntixQ?ml4Dn4PB~emMAA3rQ51hc39tKHI%3*( zfGAa~$O`_bXN#QUEdQVO*q4PT)qiM_=kR#U|BL0~UHy-_fbf4D&isD|@Id{C)`neH zfGb?mlJ6lN|G4xMJFpqdaS#b(WMGj8F`;`k;f>?E0}NDF3La0*|DVI- zvG*UPaF_p=mH7RqT*%&kb^_b|KX$7h=>=%@O(2d4X{1@y_@`hyV~C$E}2m42277f zG{_TY1ml4EnC;wEDEXAliP)(}a>>%x$2_4fr)l57!b;$B^wtS6(;GR2#7*Ug3UnE4 zgr~%Rn_JJ~@#y=HT3*KgqE?LG{|j0Ew-Y!wIW^+iX@kYduefK2c~}6-3TaSo1&$xa zh>N7i!T@B8P^#Q&3M>x_sbk$J<~7U^DPJ)UT2=^92DMx*C{?utb-mjI%=dpLSEl2I z_=i;}*ntdvxh~i6%lYh$O=Q7I9jT1t+LF}S)W?F)3#+6)wHwr@o~TdBUF$t{{VHh( zn|CDst3ldvWw|ZqB|W-rIKC`uv)c<1r;%41Zz5_}$%W~-Gvt^B%nUNfAcG7t$RL9Z P{^jsD?ajO|04M+etJl?k literal 0 HcmV?d00001 diff --git a/testdata/fwd_compress_c00c.tpkg b/testdata/fwd_compress_c00c.tpkg new file mode 100644 index 0000000000000000000000000000000000000000..6b06a8608db065c21ffaa99c54b92f7ae6f9c7ea GIT binary patch literal 1786 zcmVPQy_*z z$to0DE%lb}|7~u>lJv1M_y*hAelOjB)7IzvuVKHgT8_N|>Qfqe7yZxoe-k!k8J6!i z$nqxHgoKS_k3u@2Fme-IB>03Y)(eIdCIcEmknSYBH>Tuwkb9sgyGj~e^c5VYOlSNF z+uJ$NlK!HUl%ni=WXu4>-~xQ1i*O5k2G`h$z;5ibNeBW+;hLb;BNi&jfLsK_VJ8ZF z*g86|bxw|J3!JmY>*iS_Dzh+xD`oC$Lmg(@okN$7##@hc^ zL3jDTaI01NKd$dhukNuJf^ZfN0=J7IBR5Hcu>Y-L03~<>>Rq79Zi-{#6j%>JntJ#; zp)hbiQ4%1>19<>?Wm|(U(2r>Z(j_F+OQcua#*makk45ReBwvC7@&t5=&|yO7e8K7k zgq*bM`w}-+k+K++$2LN}0RyQ5mtz`V1N($a7lb~I71RgCq7GXE4N@<{_p2)(A+kv- zItT6IS5nJ-M_nY>?m4z?IXZgOOPkszZ>t8jEXSOU*Q5*+?%`5}vldhD{$~PvPoH7R8p#Mxl##MkO@x54vV0(8UG=I&uw3IWtt`AA@nf?eN zOM!PUKyz$A==GNPP@ge>xriE{kjp7B@x0@VXq*;>h^G1ve0v@m|2-D=9xLO%{Le5k z|5qKyu^mHqOp*WD&N}|Dg3u}qKV?$FXO|^GdR+#clr|w8kK}X^Q`b+*cnC`ohRiY? z@NjTIO1K(wa-E=4m(eLm2@ehRQWoQE1;++HKl5dfa_>hD9%ye6GlnRVBoN}z9ntK~ zXEOShECQlDWS%=5U;-+z@hdRFv`zlZLW+7$=U_lA}h){@GY7>4E{hK<`)3U zP^l_&Vq}_Fl!50Sz>^Q)*$43S19<)cJOKfofnUh{0cd z)JF&aB}|l$>;erzZ7RVq1zeGi0@L1eT5;VG4G3waN| z|B30}I%8k0|BU(lk6{|z|4r3g`~NEF&ikL3eoxikjk}&cO*^q0`fSwUc@1Vfi{;M# zR%_ZK;wnh6ozTT70KqzQS;Wav3&9IY>JiOc@8cV*L&!P zNrw*z6SDQT);R67>!_?QcC>RE{&IjXP8uxfdA1 zuqp`p;xv$iVns<|C)pKA;vWaQJB8)g+1<(ev-C`i$Q9xpIhkC!7Z#!@i5M6LN?seNl3fLzIr? zVVIW5;mEJih=#muCG*xBI*iKXBwl7H|JaceQEx8)j}X$P%R7aKSI1XJ{PGK>oZ#n) z`ekzD2E#GR`tO&Y-*W#SKJxtE=l`~2=Kil~2G9R^Hn{fxRnRNpn%ON-mTQTR`Bt-a z{PS_+#@)0+w%YBtVA!fkNWIZ+edxTd<1q5B+CF>(Eb^F7;WE9B@X2vWtA6tK1H5lR zwF-@9z13>ANVWFM8G50`ynjTMo0kbE!LI5ZL0Mb*3CjbBd literal 0 HcmV?d00001 diff --git a/testdata/fwd_droptoomany.rpl b/testdata/fwd_droptoomany.rpl new file mode 100644 index 00000000000..26af5f3cab4 --- /dev/null +++ b/testdata/fwd_droptoomany.rpl @@ -0,0 +1,90 @@ +; config options go here. +server: + num-queries-per-thread: 1 +forward-zone: + name: "." + forward-addr: 216.0.0.1 +CONFIG_END +SCENARIO_BEGIN Test too many queries asked, last is dropped. + +; query responses from authority servers. +RANGE_BEGIN 0 100 +ENTRY_BEGIN + MATCH opcode qtype qname + ADJUST copy_id + REPLY QR RD RA NOERROR + SECTION QUESTION +www.example.net. IN A + SECTION ANSWER +www.example.net. IN A 10.20.30.40 + SECTION AUTHORITY +www.example.net. IN NS ns.example.net. + SECTION ADDITIONAL +ns.example.net. IN A 10.20.30.50 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 2 CHECK_OUT_QUERY +ENTRY_BEGIN +MATCH qname qtype opcode +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; NO REPLY (this step is not needed) +STEP 3 NOTHING + +; another query +STEP 4 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.net. IN A +ENTRY_END + +; reply from first query returns +STEP 5 REPLY +ENTRY_BEGIN + MATCH opcode qtype qname + ADJUST copy_id + REPLY QR RD RA NOERROR + SECTION QUESTION +www.example.com. IN A + SECTION ANSWER +www.example.com. IN A 10.20.30.40 + SECTION AUTHORITY +www.example.com. IN NS ns.example.com. + SECTION ADDITIONAL +ns.example.com. IN A 10.20.30.50 +ENTRY_END + +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH opcode qname qtype +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ENTRY_END + +; This answer does not arrive, the query was dropped +;STEP 11 CHECK_ANSWER +;ENTRY_BEGIN +;MATCH opcode qname qtype +;SECTION QUESTION +;www.example.net. IN A +;SECTION ANSWER +;www.example.net. IN A 10.20.30.40 +;ENTRY_END +SCENARIO_END + +; testbound checks before exit: +; * no more pending queries outstanding. +; * and no answers that have not been checked. diff --git a/testdata/fwd_edns_bksec.tpkg b/testdata/fwd_edns_bksec.tpkg new file mode 100644 index 0000000000000000000000000000000000000000..5869ffa9ec3401ceaa6e7721f2c3e75c97dc652d GIT binary patch literal 2278 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 YETfDv$|$3ZGWwS3AG5n4pa3WU0L^{`o&W#< literal 0 HcmV?d00001 diff --git a/testdata/fwd_error.rpl b/testdata/fwd_error.rpl new file mode 100644 index 00000000000..238b1f58d03 --- /dev/null +++ b/testdata/fwd_error.rpl @@ -0,0 +1,27 @@ +; config options go here. +forward-zone: name: "." forward-addr: 216.0.0.1 +CONFIG_END +SCENARIO_BEGIN Forwarder and an error happens on server query. +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; But the pending query fails due to error (say TCP failure or malloc or ...) +; This is iterator/iterator.h OUTBOUND_MSG_RETRY number of errors. +STEP 2 ERROR +STEP 3 ERROR +STEP 4 ERROR +STEP 5 ERROR +STEP 6 ERROR +; returns servfail +STEP 14 CHECK_ANSWER +ENTRY_BEGIN +MATCH opcode qname qtype +SECTION QUESTION +REPLY SERVFAIL QR RD RA +MATCH all +www.example.com. IN A +ENTRY_END +SCENARIO_END diff --git a/testdata/fwd_jostle.rpl b/testdata/fwd_jostle.rpl new file mode 100644 index 00000000000..14e5e863501 --- /dev/null +++ b/testdata/fwd_jostle.rpl @@ -0,0 +1,110 @@ +; config options go here. +; This is one forever, one jostle. +server: + num-queries-per-thread: 2 +forward-zone: + name: "." + forward-addr: 216.0.0.1 +CONFIG_END +SCENARIO_BEGIN Test too many queries asked, last is too recent to be jostled + +; fill the forever slot. +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 2 CHECK_OUT_QUERY +ENTRY_BEGIN +MATCH qname qtype opcode +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; NO REPLY (this step is not needed) +STEP 3 NOTHING + +;something enters the jostle slot. +STEP 4 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.net. IN A +ENTRY_END + +STEP 5 CHECK_OUT_QUERY +ENTRY_BEGIN +MATCH qname qtype opcode +SECTION QUESTION +www.example.net. IN A +ENTRY_END + +; something else tries to replace the entry in the jostle slot. +; but the entry in the jostle slot is too recent. +STEP 6 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.org. IN A +ENTRY_END + +; reply from latest query returns +STEP 7 REPLY +ENTRY_BEGIN + MATCH opcode qtype qname + ADJUST copy_id + REPLY QR RD RA NOERROR + SECTION QUESTION +www.example.net. IN A + SECTION ANSWER +www.example.net. IN A 10.20.30.42 + SECTION AUTHORITY +www.example.net. IN NS ns.example.net. + SECTION ADDITIONAL +ns.example.net. IN A 10.20.30.50 +ENTRY_END + +; answer to last query +STEP 8 CHECK_ANSWER +ENTRY_BEGIN +MATCH opcode qname qtype +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +www.example.net. IN A 10.20.30.42 +ENTRY_END + + +; reply from first query returns +STEP 10 REPLY +ENTRY_BEGIN + MATCH opcode qtype qname + ADJUST copy_id + REPLY QR RD RA NOERROR + SECTION QUESTION +www.example.com. IN A + SECTION ANSWER +www.example.com. IN A 10.20.30.40 + SECTION AUTHORITY +www.example.com. IN NS ns.example.com. + SECTION ADDITIONAL +ns.example.com. IN A 10.20.30.50 +ENTRY_END + +; answer to first query +STEP 11 CHECK_ANSWER +ENTRY_BEGIN +MATCH opcode qname qtype +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ENTRY_END + +SCENARIO_END + +; testbound checks before exit: +; * no more pending queries outstanding. +; * and no answers that have not been checked. diff --git a/testdata/fwd_jostle_out.rpl b/testdata/fwd_jostle_out.rpl new file mode 100644 index 00000000000..7e01d9e434c --- /dev/null +++ b/testdata/fwd_jostle_out.rpl @@ -0,0 +1,113 @@ +; config options go here. +; This is one forever, one jostle. +server: + num-queries-per-thread: 2 +forward-zone: + name: "." + forward-addr: 216.0.0.1 +CONFIG_END +SCENARIO_BEGIN Test too many queries asked, last one jostled out to make space + +; fill the forever slot. +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 2 CHECK_OUT_QUERY +ENTRY_BEGIN +MATCH qname qtype opcode +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; NO REPLY (this step is not needed) +STEP 3 NOTHING + +;something enters the jostle slot. +STEP 4 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.net. IN A +ENTRY_END + +STEP 5 CHECK_OUT_QUERY +ENTRY_BEGIN +MATCH qname qtype opcode +SECTION QUESTION +www.example.net. IN A +ENTRY_END + +; 300 msec passes +STEP 6 TIME_PASSES ELAPSE 0.300 + +; something else tries to replace the entry in the jostle slot. +; and it works because the entry is now too old. +STEP 8 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.org. IN A +ENTRY_END + +; reply from latest query returns +STEP 9 REPLY +ENTRY_BEGIN + MATCH opcode qtype qname + ADJUST copy_id + REPLY QR RD RA NOERROR + SECTION QUESTION +www.example.org. IN A + SECTION ANSWER +www.example.org. IN A 10.20.30.42 + SECTION AUTHORITY +www.example.org. IN NS ns.example.org. + SECTION ADDITIONAL +ns.example.org. IN A 10.20.30.50 +ENTRY_END + +; answer to last query +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH opcode qname qtype +SECTION QUESTION +www.example.org. IN A +SECTION ANSWER +www.example.org. IN A 10.20.30.42 +ENTRY_END + + +; reply from first query returns +STEP 11 REPLY +ENTRY_BEGIN + MATCH opcode qtype qname + ADJUST copy_id + REPLY QR RD RA NOERROR + SECTION QUESTION +www.example.com. IN A + SECTION ANSWER +www.example.com. IN A 10.20.30.40 + SECTION AUTHORITY +www.example.com. IN NS ns.example.com. + SECTION ADDITIONAL +ns.example.com. IN A 10.20.30.50 +ENTRY_END + +; answer to first query +STEP 12 CHECK_ANSWER +ENTRY_BEGIN +MATCH opcode qname qtype +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ENTRY_END + +SCENARIO_END + +; testbound checks before exit: +; * no more pending queries outstanding. +; * and no answers that have not been checked. diff --git a/testdata/fwd_lrudrop.rpl b/testdata/fwd_lrudrop.rpl new file mode 100644 index 00000000000..31b26748ff4 --- /dev/null +++ b/testdata/fwd_lrudrop.rpl @@ -0,0 +1,122 @@ +; This is a comment. +; config options go here. +; extremely small cache to force dropping old records. +server: + msg-cache-size: 1 # one whole byte! + msg-cache-slabs: 1 +forward-zone: name: "." forward-addr: 216.0.0.1 +CONFIG_END + +SCENARIO_BEGIN Old answer is dropped from the cache + +STEP 1 QUERY +ENTRY_BEGIN + REPLY RD + SECTION QUESTION + www.example.com. IN A +ENTRY_END +; the query is sent to the forwarder - no cache yet. +STEP 2 CHECK_OUT_QUERY +ENTRY_BEGIN + MATCH qname qtype opcode + SECTION QUESTION + www.example.com. IN A +ENTRY_END +STEP 3 REPLY +ENTRY_BEGIN + MATCH opcode qtype qname + ADJUST copy_id + REPLY QR RD RA NOERROR + SECTION QUESTION + www.example.com. IN A + SECTION ANSWER + www.example.com. IN A 10.20.30.40 + SECTION AUTHORITY + www.example.com. IN NS ns.example.com. + SECTION ADDITIONAL + ns.example.com. IN A 10.20.30.50 +ENTRY_END +STEP 4 CHECK_ANSWER +ENTRY_BEGIN + MATCH opcode qname qtype + SECTION QUESTION + www.example.com. IN A + SECTION ANSWER + www.example.com. IN A 10.20.30.40 +ENTRY_END + +; another query to force the cache to drop the example.com entry. +STEP 11 QUERY +ENTRY_BEGIN + REPLY RD + SECTION QUESTION + www.example.net. IN A +ENTRY_END +; the query is sent to the forwarder - no cache yet. +STEP 12 CHECK_OUT_QUERY +ENTRY_BEGIN + MATCH qname qtype opcode + SECTION QUESTION + www.example.net. IN A +ENTRY_END +STEP 13 REPLY +ENTRY_BEGIN + MATCH opcode qtype qname + ADJUST copy_id + REPLY QR RD RA NOERROR + SECTION QUESTION + www.example.net. IN A + SECTION ANSWER + www.example.net. IN A 10.20.30.40 + SECTION AUTHORITY + www.example.net. IN NS ns.example.net. + SECTION ADDITIONAL + ns.example.net. IN A 10.20.30.50 +ENTRY_END +STEP 14 CHECK_ANSWER +ENTRY_BEGIN + MATCH opcode qname qtype + SECTION QUESTION + www.example.net. IN A + SECTION ANSWER + www.example.net. IN A 10.20.30.40 +ENTRY_END + + +; query, same as first, but it fell out of the cache. +STEP 21 QUERY +ENTRY_BEGIN + REPLY RD + SECTION QUESTION + www.example.com. IN A +ENTRY_END +STEP 22 CHECK_OUT_QUERY +ENTRY_BEGIN + MATCH qname qtype opcode + SECTION QUESTION + www.example.com. IN A +ENTRY_END +STEP 23 REPLY +ENTRY_BEGIN + MATCH opcode qtype qname + ADJUST copy_id + REPLY QR RD RA NOERROR + SECTION QUESTION + www.example.com. IN A + SECTION ANSWER + www.example.com. IN A 10.20.30.40 + SECTION AUTHORITY + www.example.com. IN NS ns.example.com. + SECTION ADDITIONAL + ns.example.com. IN A 10.20.30.50 +ENTRY_END +STEP 24 CHECK_ANSWER +ENTRY_BEGIN + MATCH opcode qname qtype + SECTION QUESTION + www.example.com. IN A + SECTION ANSWER + www.example.com. IN A 10.20.30.40 +ENTRY_END + +SCENARIO_END diff --git a/testdata/fwd_no_edns.tpkg b/testdata/fwd_no_edns.tpkg new file mode 100644 index 0000000000000000000000000000000000000000..1629cba0144cb266a13e625f6792124177815135 GIT binary patch literal 1370 zcmV-g1*Q5QiwFRO0#!`_1MOJULJ=quxVM*^s>8bhZ`fblhq*`;|DJ0ZZyg3n_bKGu(h(J>4< zE{%59KVNq_8y!N2SYR_<@4f4<>$MYAu`J89uxR1>n?}tz0p$?NpQ8Wy`s1uV(XdWR z_Ib~9ECn4u3q+CuUgv^=IwB~V%@mTser{PkXa@UzocoZkH zM?73Op(p*x8AUT!V`LnZwK$#^B1_dQS;0T`)u1b^ER%2T+y4SRhJP<|52E8K{MQT} z@o#E1!?ctn{+qf{;QuIe;Y8F$H}r!zVO*x5gOJAI5*B_u zL6AbHZQqa<1`E-t?ZhZGQ^s~55S~IUr1Ik2DBAe1{It}Wi7j92O4nj(LNg&zc zB8Lpz9W-)A^^4FAF-htTm9{w+(*@NXJe7U#dE z7x+I0RiGkC4{!jIR3R0J_&jte#1jfLCqnnYC-jv#+hH-G4E*>k60Hcc-$5FIET7A9 za6gu@o4gwF2b`W}g7&nd7W6D^*ok^P+QDa#l#%H>cc?NzK>BRFQnfu`OUqUhA-#U* zWm%}kq@e;HPv(;}QFp?j+yKuX!(y?J>1SsaOerS5Gwdt4uhz*3NC8xD?ThZM-5!ek z;=u^`3#C%PeIz`z7VbJRV4@^=QJIJudRs;gB$X^hLdIsugu3_OuxLTUGVw<+4rzcH zjv{M{tSfR&D`#q6h}kewN{4oTEfYG8XjZp*41!mppZyrKxRFmtQdF{N_7wiv0rvb; z_%~H^g?~%YHGzLiMOK0TBhU*F8FhLKNb#0z-fFjh_4Abt`Tb3*gTWinO+_K3V-Nc8 zhZh~}L#~^H)@$H_%RLGo<7I%~LMYs}d(iHZey8{5J-qEhvk8~o{&lC{C(ZURx0nmK zJXj8WkKA-xgR8C$Z*MU}zyd*Rm9FekbKTOkZ{BtKYkp~i1!ZMS$8LYQU0X)kT{NkC zV59ah)qPAYZ~pPu|1tby`g9N-PvBoQ6@BymlivSz!z%E940?F}F2^EhWEqFnI91^^ zo!eFWW%Y-=S%R@D{DV<5=bnOi6~xRaIVSLe1QLa_=sbBCIzQWT!`b=Ssx^I)!RE|L z(exASJ~l!F=66YH?SWN#lAKMnT cP(cM1R8T<$6;x0`1^qkv8$M*&B>*S@0O10q)&Kwi literal 0 HcmV?d00001 diff --git a/testdata/fwd_notcached.rpl b/testdata/fwd_notcached.rpl new file mode 100644 index 00000000000..d937bb2df52 --- /dev/null +++ b/testdata/fwd_notcached.rpl @@ -0,0 +1,87 @@ +; This is a comment. + +; can set commandline options using something like this: +; COMMANDLINE -v +; here config file options: +server: + msg-cache-size: 1024 +forward-zone: + name: "." + forward-addr: 216.0.0.1 +CONFIG_END + +SCENARIO_BEGIN Query receives answer not from the cache + +STEP 1 QUERY +ENTRY_BEGIN + REPLY RD + SECTION QUESTION + www.example.com. IN A +ENTRY_END +; the query is sent to the forwarder - no cache yet. +STEP 2 CHECK_OUT_QUERY +ENTRY_BEGIN + MATCH qname qtype opcode + SECTION QUESTION + www.example.com. IN A +ENTRY_END +STEP 3 REPLY +ENTRY_BEGIN + MATCH opcode qtype qname + ADJUST copy_id + REPLY QR RD RA NOERROR + SECTION QUESTION + www.example.com. IN A + SECTION ANSWER + www.example.com. IN A 10.20.30.40 + SECTION AUTHORITY + www.example.com. IN NS ns.example.com. + SECTION ADDITIONAL + ns.example.com. IN A 10.20.30.50 +ENTRY_END +STEP 4 CHECK_ANSWER +ENTRY_BEGIN + MATCH opcode qname qtype + SECTION QUESTION + www.example.com. IN A + SECTION ANSWER + www.example.com. IN A 10.20.30.40 +ENTRY_END + +; another query, different, so not from cache. +STEP 5 QUERY +ENTRY_BEGIN + REPLY RD + SECTION QUESTION + www.example.net. IN A +ENTRY_END +STEP 6 CHECK_OUT_QUERY +ENTRY_BEGIN + MATCH qname qtype opcode + SECTION QUESTION + www.example.net. IN A +ENTRY_END +STEP 7 REPLY +ENTRY_BEGIN + MATCH opcode qtype qname + ADJUST copy_id + REPLY QR RD RA NOERROR + SECTION QUESTION + www.example.net. IN A + SECTION ANSWER + www.example.net. IN A 10.20.30.60 + SECTION AUTHORITY + www.example.net. IN NS ns.example.net. + SECTION ADDITIONAL + ns.example.net. IN A 10.20.30.50 +ENTRY_END +STEP 8 CHECK_ANSWER +ENTRY_BEGIN + MATCH opcode qname qtype + SECTION QUESTION + www.example.net. IN A + SECTION ANSWER + www.example.net. IN A 10.20.30.60 +ENTRY_END + +SCENARIO_END diff --git a/testdata/fwd_oneport.tpkg b/testdata/fwd_oneport.tpkg new file mode 100644 index 0000000000000000000000000000000000000000..d752f852ce76845e4d488e14ad3a65e9574bf4e6 GIT binary patch literal 2017 zcmV<72OjtziwFP-1654`1MOLDbKAxd)>q!I*isxTnHCVi;PWtu64`O1{heO` z3ZieC^sV+yB`vFlk$&gcQB_kjHAU6?)((CeT7L)3Um}<$mT_W706VK-negZ_KOV)~ z2xz;QHRiusPI#R7&v4B&!B#fkZS$}8brt8IoODB1ah<4rO;vV4`R}`a8o%-Re+9n1 z;COAHc?2}!FmpZ5dY7Y%KV1xgf3X*#$K`3TkXdg$eha##D2$yC$DRnUok8**MHSe@!(ff^wx#`Zv(IGm=AH44xlpg>@Rq&Zr~3RMhnG>_qh}-0TW+zDeF7V+bj6gL&RR;ROK^SDmfW5I@Z;8yC?ydg? zJhuOF(4M7_r}95bHOu^8vy^oITO$A43U*;vlA2pZl6KiH#KAI}a!77DEbJHu2R`FS zQF;igTkeCK?8Q`zTkEeN%|Mp-Uthi-o=vVU zN8`iZDF4OYd?-xcd{bKC_n?0JE#uSM0J`;t)lwIZj+%jFZPu*CuQp#Ad|Z|3NRZm% zKvCSD9Mvyq{#rww;z~7Gd_iCfDx4&1^k1tD)B3`QfV=Z3d zh9g+sq`%6sSo$}?(s$C8flKnnp5DzPvaqYs`C*qii z`+o}|^nV*@(SMwE*yagP>7|hT$NJb<`soUs0Pe98iBU#_l@BRV<4m}7J#P}?ZCIgv zBy%$t1;q9|;9ru+CMCW@oy)Zp4-lYM6xc#$*w%C7k%i2`38KK#eskHVgkI69pQ9sBJ^y=-HTJ~*Hw?9W z{%5LvHQoP)*#BF>*ZV)+R{u{KU^P8R6`@d?G|#$o!_+|3*vY3QkM6Ttx_+#}^W9E& zdc?D8m&btV7$ok3091G`OAud)NmLQrJL7$Ywg3*E^|)jVU}>XuLMP|V^L22EpL9R#Ft zXOIb6F3u+KU<+vT6J0rz5FT82RaWX19qHvyIH&RoXIAqk4X?6RLf3`cno zl*3_bR6v#Tw+)E2b|S4L(l#X0+llm&NZ*jiXeTmCB4a}$vz^E+iOda&tac)+B(jJo zeP{_*dIo`X0KI%7ng*?D(3=LMX)v1xYrSx2H5aqrWz`b2`DisCt<^`b`RHvfM$N@& zb1`c!W}AyubFoDks{l+^iYhH2@BqRw@QQe zSFRH?f4PX!=kO!-f(DeA)f6P}BU>Bn)gA2pGen6?p!f3Mul6XDp<8EZnXza@v-I6h zC5^V`K?z9(x|jQa^iqS7rEf+QH{A*%!O{~?4wKigHV`6Jf ztk;S4He!8a;{KZ0s1qA)#Ky+NFW1Coo!D$6Ha8|dSQA@yVylhVdVrYai|E%*#C|0_ zmjBaJljrE;sr!FZ)zY3gRPHssO5MLJEf`dEp}j!%>H z1y2{ZCZ6`Rr?F6+S7<@|^fn5DB=e!k@YAdL@v7@PmVbqPPu8H&4RU8KODTR0l{^#e9ySkygK}z`liiKXZ zXh4OO%HYQ{Iht^4yI}(~QVJN48gSI_4Xh(lLT$+5BAl{u1AInGczvi7F^;Phoa?zG zZ%P{=#r_qGeOEz@L`u$tGloLqeYT|Ft@z3j5yz9NQr^6O&q=KKU8<=`kOTUQtPhh7R|FC_$X0_69as?LGvyb4??# zeHS>5V(#N7m@X93MyDYbbnFPpT9X(~=oP?w&?*hxXjI=ryK6xOa{}_o_WTI{&;xU@BY|ERv~F4k#XWzNSn<9^Z|aDysQ-3B?ay=jcpUa=e5WdA}P{uAEyN8`U%TiJhA ztBUwv)6~NLw*enO1k^MO0CDgjA~)IX4NiYJHG$sRvtUXwC7dZ_*Rsx_T31y?>HKL8ZB;!Ctzr)6U`UcX^QnV%c~=pqYJ5 zLA(lh<1{>Ab_6no{qP_u2!A~~*k4n^{=t4Wo|aa>?kH_*q!_e;PKSNL6f9l2i&sJdF|0f>xHAR5D zuPB4dlKtd-auZziX_#0l`AkzUJQ!Wv21Y<0%LCU4QQpVC)a$5~0(OW_^=I zAaEsm>qVfEkw-|7>{tf&E L6fAEg04M+ecJ7uW literal 0 HcmV?d00001 diff --git a/testdata/fwd_tcp_tc.tpkg b/testdata/fwd_tcp_tc.tpkg new file mode 100644 index 0000000000000000000000000000000000000000..a51258eb42023eb0efc4b0b834fc4ad48ffc4a1a GIT binary patch literal 1368 zcmV-e1*iHSiwFSs1654`1MOICbK*7-&R6s+whoirO~;OH-sXHgCIm?IR86!65M?{1`zfP7a`)k1E@TUH(N4`6Hfpf%=s*#;<0vA#QSh)zcSpM z|4cFBak85+%UVInub>aXFiwmlx*ZwV%vkmK9gdDtL-*8g zj*?Iu`-w5u22|q>^BYw}zCplYft6_369JzyP=*ZYiO;7~&Ww0WZo|oB5QPC0&#zm9 z?nNu3xpL1sSME|v{_DAV4tW^=GKg#^EB-0`SFP%SWmav|uGzQ^Nc>l7R*wID$ZKHU zl;XR6recXdi9J&6^e%q9aDjgDrqP5Nh!%qs`~7!Ns+uMtZMWb1I5=x#8}h!|9!}r7gHBO;bb@f`2}A!0Y;jFda_N+OVHRg4dA`E0C)xFE61{&k_}CS5!iSXAn(19 zCHSGjfj}5=Z8VJr{)B(9k%#7E(nKpGE*1`uCZ9%}QIk{M^4-H<-r(ki~tn0-0Ntxp>4dT~qxhn#!iWQJzH$;`i$$MgSg#&`<< zwVJuczin3(|1a4&{`VnY@qfhu_R0S-u-mMD$c5Zn(&Iqr-QbWBf-+>Ie|rod-Cp~R zCWkh(<%u9YX%OmQTba0nwoBhWIOK}&~uE#HQb z!m?}UXN}NFOw+Q<6Og(B{Sqc%kzq)PdNkKN+QazwIUDX~jXj0`QrSZM*J`zDtyHdB z3jcT{$nn1iSu%fz6!80o$6Fgna#Z^^5A8dYNACXw-O(6N;2+t3 zMBsFUc6Xq z;d`)NzFg($&5qfU2KD;3Bg;N_R@0~Z+REVLqEwNP`x^#I`aKC)JXqe!k>b0SdpYRi ziORiH)FidHP32e&^^|bf^&<<8$m*8!P4T;|S5mQhc)+KrcS}LC0whL?;@}wxbPC7u ziAoE)yp-LzyYu8xKj|wsdnZ+?b`oEK14VvTo&w)Mt5Lo}+Tf aC6`=s$t9Oua>*r^eaPP{>V>KRC;$K&L$wzG literal 0 HcmV?d00001 diff --git a/testdata/fwd_tcp_tc6.tpkg b/testdata/fwd_tcp_tc6.tpkg new file mode 100644 index 0000000000000000000000000000000000000000..44348201894b461efc97b92d999ad7b4abf2a60d GIT binary patch literal 1415 zcmV;21$g=&iwFRq1654`1MOICbJ|7__E+v#Y-PqyrXyM6MRb&gF#+7Ti3P#9nM~VZ zWa$9aNT=M15IX(w-4h54LQSTF$&8~NKzDn0yL)@Lk9HZ(yg}?n_%$`p=VwQcKsr*b zT9r?uR@IZfQK=-)B^?+2Gd7JWe`p@%;t&QM zmWCVWpY2DS?nQ?@U~_Ta+s@xGjq>XJtCcdIzgaR$N1*RT`wsff&;J;XRTVZ)T~&|C zF$gy0E`@kZA#emb2R@;vhW>=YY)nJ&<5M9=IVHb?Is{ES)8goEq~SDex#CYaIY|X= z8AmPXSGZ@#RKzf39Q+WHHZpzZ7F9-$5PmpXs#;&Lre$r25KZcJSrD*L6Js)>@qjy_ z$AUq`cnl?SW54R$*sVdg)9b%1_LePj@jhied$!`jk6=81PN+L(psX*<_7tesHw{^= zxtE%@w#}8!$6J|rV&-rU9VP9ac%c}`385gxw=Mg6&~IP&?Q2jYSjhv`TszLie5fN& zo3Ig->L&)AEVg&qdRhD-Ynfy$8~N{)LJ?E^P0UEyo3vJ*n1;7(8hXjSzzccnxOXEiIi%Zbzf|Pi(iBp} z&RIHD#gCf`g8Gu3b;8QdtRvQ#na);+xK6yun>qg4Q4OXMESiJ*;l!ks^v3?koy6#Fuq3;=wi2z^|7DE_4v_n~7~{-@V!8~MLkG4wqC4?$nX ze-c(tDFe(V2wSp2nbDAEF2*`ed;!I)#+x=K9h^D=y5u=oph${N%Os(GKLcj7nMOZ5 zK{TP5Y6NK-az8SUsUS%TyVB}qHdgf8i1 z6N%N5F?H|23B`@T+*kT z>?Ff$Og~@9Gz(>RG3BJ5MJ^nFGDXQx4?1?$f8ieP{I2*nG3FQXZ`6`;!>l1Bcq%?G|muG`K2WygkhH;4|{ zAXpj|F6}~NHPW!J-?w`!e&N1~(U-=w?bcV?g^;yo*P|G)Vi1PC4b2 VQ%*VMl+#nEe*t_|`ZoY5007BgvMT@p literal 0 HcmV?d00001 diff --git a/testdata/fwd_three.tpkg b/testdata/fwd_three.tpkg new file mode 100644 index 0000000000000000000000000000000000000000..afb05167f07c859aebfa80f9fa154b0470ba20fc GIT binary patch literal 1653 zcmV-*28#I~iwFST1XWD{1MOLDbJ{o%&R6s+_JB#+>Dl-N<0-u`AwaIVYau1%I-R>4 z>ezz#0+!D3O0lBH0oq&5=K@4a4=<)hz1YI(IDJ~Lc66w zX8jj6n|Xt6jlmbV60i5#^)DOhfvT9MSuu6PM80a6s(t{R3RvZvv94kK&9Icp3527Rzx0 zWT~1dEBK?Hob)Qu>@<&GwZ`8~ygP5#equ&ps3@qf)w%9#IQil|gnRoC|C{|>1D1xZ@j`yfdL zQh<<60-K^cQy5zz8V5e1rTEDW(;Mo68y$tb72WE0kOm;jB{}kMhcb%ENsm9_@Gu2h z(~hH{U17l%!{ccTt_PxwOxL=`A$@d0j4sJg*$$aeGEIbBbX&)HJ~W>51#p;{k7%Oy z4TF3Q9CrxQ=~R{Joi+AHJog==FlV3469|xeC|8@i5a_Uk$CVht}uNI)@HN6zy)1TX!@9=_M4C z8Lcw3RfbM7`ysVSydUNkS|_7rWVE$1dPYXy*47Kf-doud4{km+yZcmdLs;E{g6ZAg zhxdVv1+bO{*46=QUkqGX0P9&`eI2mA0hoxQ@}Euz9yg~(-t?r^Bw-k61JzDMN)2gIxQb}7;$=I1n`X-h16_qL(l~&h( zlmFvoX={7z5&u^!iaCG()eKYI|M42I_x~NxYW|Pw{yk;?G9MR%*O+;7cteIX>IatR zuyLQiWP(PPGsELzHz|>`_bKbyvpE-DfcpG-k}738F4yutnaf=fE2UIa!e2WDg4$B1o0?#*<+2$v%%#d&bMO>; zg*Ua_%tG}iewuQ}ZHXeBznp!4yA*O`{AW9R|KW+>;`={EkKcdHef-}A-HZQh$L~K& zqog7Kp)tNV^cUjSo*6bGFosb!^*{iv9ts5zmvyuOD#VL@ys$$W33=EXxEN9_l%aP~ zVDY$oi*YZBt$3Wo0H`J=$=G+~hSBlIL44^hdb(?_Oz!x?P*VY+AjSI|2`v804M+egjO~% literal 0 HcmV?d00001 diff --git a/testdata/fwd_three_service.tpkg b/testdata/fwd_three_service.tpkg new file mode 100644 index 0000000000000000000000000000000000000000..8660e1de9d694346745dd2ab2cbfc168bd9469ba GIT binary patch literal 1646 zcmV-!29fz6iwFRX1XWD{1ML}MciJ{EU(v6)5nj^1&Bm57taRap0$H=QkP@=IzHN^= zwg4|+yOt@*-hTW}!UjxCljh~o*Oeo|(&=<}I_b`LVlZ?1(I{lB&sq45_W$my7cr*nV)^cOBqk#)2bC&RdP% zX{QbEE?VcJL1wd=o;z*l>WiUz`~0%iT@K`QO{JP@XlhA|^=Y-6+fj{fQjM;uW^P?I zW0Pvenrh{gYG3*s?%>P7L*u{gdxOWyxF`N=CB1_0e?g>G%7!80zfS2c{%-^3k-tiE z_GqCE4ox-mU2mv_mN#T_0-hRXM}COY z^LeCq9q}H)&eXf|r=FuC2J!YN^!;c~BP=Q+-n=Iyeweb*Wn2kZ7)wXt8ZAj$h2QeA zKdgf1qc~sj{76o?RmQ$;jYmF@&TVmzr8T{Q2!6mypNS}pZ`}(eUbm`6;1kodFTIIfqmFl6v*ChP?UYL58R)IHiKxy zU}AAJ5`0993HOHCh@h2P{B#bh~(^6y_dXJ0+ z14*1>pBf@!1&$B5IEakV{r#B-l94Jj!Nhjrdnz9hq`P*mT~Ub<@GlX_AOP2cLd@$WE`;Qkngztc7`IS7j$Z;aLNsOqG9o0AhA?~NL%s%%I|NZ(s;fnBo(S~uBEQtH*m?)4#GBg79dW?9%F)9tc4B-Vm3x2{iyKW zLm1I)Ms&f5K9G@-&B$0VG6W-8N`onbCMYkU5No@Rpz8>Oq;@u0?|f$$tIwjLDH@td zW29(|r#eJjo}#tg{p2yy)8|MBm&5vDl1T6FiMq?!Tr#F<#x#pDeK6zllChCyY-BMu zHZUf#seMCbz(e2v4!0jIly?oJ;ZFh- z_M41)TcKmA`+vNGfYdE zQza*sJD#GfuO);$xc(2>qh;Lp`%l@ZEbIT0F8#l3?)-lnu(AFR+5ai~U#szQEgDMbJ$5|apWiu9|}Lzxr`mlWo0JlD`S<>3Z2H8=6rnB400x?ofXIsjSn4M^*^1H)WHEhM($3L%xd% z?Un{>`@hPGD36|MLu_y*-tSHOkGrk!=~~6mirO*Kp6FFB?t%6k3*1Kk^Znn4eMN!w zJqJbEC;PzJB(y0+BMM`Sql4fhdTZc%6s9BUgBu-kAq^?{8I%F2>X8}+_d^xCsmX|6 z;ou-uv_Xzm(6_K)OY;L3g6o5PMy6}sp~=AF-1Ucvsnr21R#rrWbh@pRyfCfi(VD~L zdZdWjBL?{zIPMUp)2T`yta0E`)n;StE4Zf~vn_ALgi8V_+?Z$W8?)K(w7b2v5%33U zrGRge@X%bjJ)-tKSU#W9Fi+e83_}_~Ue{DZQ;V8f((>t;H)3i&$;Ct4KjsPbI8ECo zi$L&l^udilCj%FkGqv2il!0LGJDVs6IikV-A6mY{#(j~~FxxFxHBJiM_I@aQm=$5~nS zNGB_#-@!WOfErBhK3eHM>uYirCw5x*ucB%+!OLd^s4NK^5 z;ffXJQe&e_M1koMPn6`A_o_b$(t=bhOC}=tE48WJ$N#qc?{NFcHn!ovvbL!ISIQ-s z|BHH-|93%W7N@2}R4e;Ve!|td%tz>_YNScI9lAjz8A(Qhn`Q?vje;l&#e;Ynnzm(+ zC}|*g6hoR;gz9fGOW;DjpNstvV{Kkje- z&_ZjRG*HV>0!-3i;{dUsA5}?X>@;aWeF0L*;^{5*f-32RkC!EmHqw#6a{bCndURbN yCh&okrZn@qB^=J4pql_}jD5H!r$|$2RiT(rvqzSD6C;$LF=f5-n literal 0 HcmV?d00001 diff --git a/testdata/fwd_two.rpl b/testdata/fwd_two.rpl new file mode 100644 index 00000000000..ca4d0658e02 --- /dev/null +++ b/testdata/fwd_two.rpl @@ -0,0 +1,89 @@ +; config options go here. +server: + num-queries-per-thread: 2 +forward-zone: + name: "." + forward-addr: 216.0.0.1 +CONFIG_END +SCENARIO_BEGIN Sample of a valid query + +; query responses from authority servers. +RANGE_BEGIN 0 100 +ENTRY_BEGIN + MATCH opcode qtype qname + ADJUST copy_id + REPLY QR RD RA NOERROR + SECTION QUESTION +www.example.net. IN A + SECTION ANSWER +www.example.net. IN A 10.20.30.40 + SECTION AUTHORITY +www.example.net. IN NS ns.example.net. + SECTION ADDITIONAL +ns.example.net. IN A 10.20.30.50 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 2 CHECK_OUT_QUERY +ENTRY_BEGIN +MATCH qname qtype opcode +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; NO REPLY (this step is not needed) +STEP 3 NOTHING + +; another query +STEP 4 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.net. IN A +ENTRY_END + +; reply from first query returns +STEP 5 REPLY +ENTRY_BEGIN + MATCH opcode qtype qname + ADJUST copy_id + REPLY QR RD RA NOERROR + SECTION QUESTION +www.example.com. IN A + SECTION ANSWER +www.example.com. IN A 10.20.30.40 + SECTION AUTHORITY +www.example.com. IN NS ns.example.com. + SECTION ADDITIONAL +ns.example.com. IN A 10.20.30.50 +ENTRY_END + +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH opcode qname qtype +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ENTRY_END + +STEP 11 CHECK_ANSWER +ENTRY_BEGIN +MATCH opcode qname qtype +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +www.example.net. IN A 10.20.30.40 +ENTRY_END +SCENARIO_END + +; testbound checks before exit: +; * no more pending queries outstanding. +; * and no answers that have not been checked. diff --git a/testdata/fwd_udp.tpkg b/testdata/fwd_udp.tpkg new file mode 100644 index 0000000000000000000000000000000000000000..b515d8317326e12b52bdb4080338491a1bf0385f GIT binary patch literal 1357 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 QJNh>0Z?ObD82~5%0CE9TX#fBK literal 0 HcmV?d00001 diff --git a/testdata/fwd_zero.tpkg b/testdata/fwd_zero.tpkg new file mode 100644 index 0000000000000000000000000000000000000000..151d695635f297aa1c65b4e3efc617dd93ec8766 GIT binary patch literal 1479 zcmV;&1vvU2iwFQ^231V}1ML`VbJ|AGU%6kg#f+UyD_IW^327J;AdS-m2*%B1+72V6 z0~CupS&v{c`SINo5|#+ACo>L7Q>`Dm+uOU{+q-?;bZL)2QlHDV< z^_mj*)oL~VCUBstHLa#8x~l63imKIB^#E#LNuC@;L1_8_2TLA>)c-d+>IeG}XumMc zp8uv}aW=g_9^!zF^?C0+f4!>W`K!8OXu7W9xLVWec>c=$iEumo&(9xs^?~{gQo{ce z9ysBu0U9YC0*e+>IQOY(2Mth3$>V<5fYU*LI65UI)P@wS0+-Jkz&I)4?V(o4eVkn` zBe7#o9hYJ!ViO)QTSg4xt+~&6xTX;bW#)pedp4IC52dS!`YXxhmg&xU5XOs7xxX}h zTl&ZuMM0A}GEPcIOxyMmg>FMu@JBs89ra^D%Y=Mu1%KzT+x|V&{r&N{%l@l1b<6+P zs(QV!|9!wA97+=84jv@wkQ_q5Bj2JB&M7R+0CfW&P*K9HVL7J^obWghqdp~nf;0tL zK9NK3awa30oXq$ej*ilWc8uq_gcNz-!DF*POq^RjH$=n^Yz`|N#D&pG@FjzIAz4Ub z@x_8OIhd16$92c(ouKmkZD%|<>trw&y=VQ4-WvO@59%wyZu_?b>mGUBZU6O6{I9B- zuzyV}?0+xt%nWERj;QJ3lRt2y4rdtkWrcKTVEK+0#)y$HIt;oX=wPx6DO_|0;8V|C zff=BN1RYFG$0cn{9Yn8VhPe1BqVUpW00yW^Lx0@R9znZ10!>jKlh>xhLj1!#1Z-c1 zw{lx<;m3K;W+s|$K-##-EY2=Sn=d>}1X$Q0?SyCtC~@d z<3ExW_P+<%ivMv~-DmtqwQfgs;b0uLNe3Krf-F6>M2F43Gz}nwVfSfSu*P~pYzln@ z#6<=yop26UqMCq76k?$f!d1BPDEtCfmW%A*!NPP=m<3IyJS5bbb0{}~S+HC#WqNHc zJeOj*ypS{056cPRq^dts)b%A-vVb>UfKoSV^+$$k*mcFQjGCewx-m6uMJdB4xW2YQ z@u&0}XOh}XG`k5Z`0;G#u$Q!FgfeXq+^zhEfh=I71mWhbCnKGx=C73K& zQol@`Dal-AU`qND?_unEy#M#&8lf@7p+h}UddP!;&lrZ zCFFK(7K{Y}3rOWvr*}Rcb*WJE3!s^LS*>}b!VyVo+^3bFvN8!o(zr#U zg?ULqyb5D9i2XXI#UN2Q4o>1H!M{#Vj&oW#J~>Xu*Kct#MJlHl{S|W0&CrBs61O%A zNP$7wYgb_cKC!J8qpTF~ov zhr|Amv^p;@&PV7_C$Y!FN*OJ}`OYcta7oxkl4H~3N}{Y#|i h_B!8zAr(+S0R description directory variables +linux.example.com Linux Fedora Core i386 src/unbound/trunk +solaris.example.com Solaris 10 sparc64 nsd_trunk LDNS=/var/local/ldns diff --git a/testdata/hostsfileosx.tpkg b/testdata/hostsfileosx.tpkg new file mode 100644 index 0000000000000000000000000000000000000000..05ab7c233985dc1c838ce2bd6a7c268cc6475851 GIT binary patch literal 1642 zcmV-w29^0AiwFP!2USe~1ML}UbJ|AKU)f*rf~k*oP$Y3Bc&rzm&I&J77M7eQV(>-~U}W!##!?jcJ!g zjO>zKXb*S<$^{@Ah{SWj5kX9O0P%nUbzRA#h($mH7pTXny6*`Io^YrK+GP-v#>goe zP|5IN!p{I`vCyLqgMEKwxWY%S`_N^c7{ZXp11(`Z98jNu=)p)N5;^(Q8SsD^s9?El z!Cj!`EAjI?VVM8u`QI*zQQaXUO)zFrFH5c-=P;&6rU9 z0(*N?Mt96FONklEUL#}1KqD`)Uz*aj%oVzVAY&?BF$_R6GL$Bc@O=>&(STfY&+CNT zh0N*uTIce-_VuL1`{Q3NWAI?FUl;$S(!BpO^Enm&MLWNZ|4qOVs0IUV`^4lp`qbW& zOtW?V!+8VP4fR88+%Q%Ql4-YJL#}9=gdFLPFO=NpK_5OQOpZvs(QbX{ysRS~xu~?O zXCOjHxC}nVqY!^}C)285zWxAjT2QG#qgijYnk`bP{rL8(ja_Cq>Ts7_)vN9EW&_^5 ztzW4d@*;KKNHwlz6P3o*`+93SoSJoZ6AkK(8u@(642MG{x3a3ubUd}tcx_4{`>!;z zS5>kXRZ{!Erv6Lz2tKy<{Ab(q`fn9g{3HH0{x<=4)qlx0S^aTgS8KY;E$X;AX$Cm$ zqR5a&5hj~|+61iD`aX+05|6IJ?}S3eU=v;Qo2~Y7=HMXHYK$M?JFpH933CPl(sPXI zT^deKZb`xwLtoPB53$=o>y$9h4WiDtkdn;nTH~tI#>j14K{kXLKe(gp!bxxF;t{P6 z_Q{?Fdt}m_9A};^>ZJxIH+O2~(0FxhNcoapog{>bEb{fVK3mxNJN@6oWvt2ncG1eu z^M4_~J^yVG?#TZ-qyC>Nz-6m`oK~WZ^lCLg>6)DPR02e8c?3x~Nv|j1@;r)aXLMBk0fwe56&v@>YdYO>s5NJ zxFdod?;C@u98Hyt(`vP*-adXukK664)7t^2edfdr7ku&(9B2{`F#dXC(gE$Ctn3h{%OlqL&d3Pf`-zewkGfBknO=MiMAd;e1~3-j-Prlrq+d2?I;Hvunc#2VCR<)vsN z@6cFGk{B0;Nop)|BoAXf&}RBmnYhL?L!!ztc)XhgU4iLn{0$H3CmBWuKvk6$B&}g_ zDZ{Dca6w046~W4t?dRp(bEx8Z2yD}QMlLAVUmBS#gDVYqZ&Zy6Uihy;pW=}!B30zl z7jjevQWbtE0v5z&QuW;$3t8YsI6l8SV_sM$mvY5Ab;2c=IIudbKG!Mx%C{RLQb}%3 oRp=tyOYB3KTPCNJdkHe%9+|eVg)MAh3;#9v6NoI1a{wp+0FbgXZ2$lO literal 0 HcmV?d00001 diff --git a/testdata/iter_class_any.rpl b/testdata/iter_class_any.rpl new file mode 100644 index 00000000000..1256dfb5e42 --- /dev/null +++ b/testdata/iter_class_any.rpl @@ -0,0 +1,150 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test lookup of class any response + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. ANY A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. ANY A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_cname_cache.rpl b/testdata/iter_cname_cache.rpl new file mode 100644 index 00000000000..a8068d247d2 --- /dev/null +++ b/testdata/iter_cname_cache.rpl @@ -0,0 +1,298 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test iterative resolve with cached cname for nameserver +; example.com NS ns.example.com en ns2.example.com +; ns.example.com CNAME ns.bla.nl +; ns.bla.nl A .... +; dan timeout van A record uit cache - refetch. +; ns2.example.com timeed niet uit ; maar geeft altijd servfail. + + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +a.gtld-servers.net. IN AAAA +SECTION ANSWER +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +nl. IN A +SECTION AUTHORITY +nl. IN NS ns2.nic.nl. +SECTION ADDITIONAL +ns2.nic.nl. IN A 192.1.1.2 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. ".com" +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns2.example.com. +SECTION ADDITIONAL +;;; but really a CNAME in child server +ns.example.com. 1 IN A 1.2.3.4 +ns2.example.com. IN A 1.2.3.5 +ns2.example.com. IN AAAA 2002::5 +ENTRY_END + +; lame answers back to root for .nl (.com server not authoritative for .nl) +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +nl. IN A +SECTION AUTHORITY +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +RANGE_END + +; ns2.nic.nl ".nl" +RANGE_BEGIN 0 100 + ADDRESS 192.1.1.2 + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +bla.nl. IN A +SECTION AUTHORITY +bla.nl. IN NS ns.bla.nl. +SECTION ADDITIONAL +ns.bla.nl. IN A 1.2.3.6 +ENTRY_END + +RANGE_END + +; ns.bla.nl "bla..nl" +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +ns.bla.nl. IN A +SECTION ANSWER +ns.bla.nl. IN A 1.2.3.6 +SECTION AUTHORITY +bla.nl. IN NS ns.bla.nl. +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +ns.bla.nl. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +bla.nl. IN SOA bla.nl. bla.nl. 1 2 3 4 5 +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +ns.bla.nl. IN MX +SECTION ANSWER +ns.bla.nl. IN MX 10 bla.nl. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ENTRY_END +RANGE_END + +; ns.example.com "example.com" +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN MX +SECTION ANSWER +ns.example.com IN CNAME ns.bla.nl. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ENTRY_END +RANGE_END + +; ns2.example.com "example.com" +; bad failing server +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode +ADJUST copy_id copy_query +REPLY QR SERVFAIL +SECTION QUESTION +ns.example.com. IN MX +SECTION ANSWER +ENTRY_END +RANGE_END + +; ns2.example.com "example.com" +; bad failing server +RANGE_BEGIN 0 100 + ADDRESS 2002::5 +ENTRY_BEGIN +MATCH opcode +ADJUST copy_id copy_query +REPLY QR SERVFAIL +SECTION QUESTION +ns.example.com. IN MX +SECTION ANSWER +ENTRY_END +RANGE_END + +; get cname in cache. use MX query +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +ns.example.com. IN MX +ENTRY_END + +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +ns.example.com. IN MX +SECTION ANSWER +ns.example.com. IN CNAME ns.bla.nl +ns.bla.nl. IN MX 10 bla.nl. +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +; get seconds to pass to timeout the A record +STEP 15 TIME_PASSES ELAPSE 5 + +; get into trouble getting cname for nameserver. +STEP 20 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 30 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +; there may still be pending ns.bla.nl AAAA queries ; get rid of them like this +STEP 40 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +ns.bla.nl. IN AAAA +ENTRY_END + +STEP 50 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +ns.bla.nl. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +bla.nl. IN SOA bla.nl. bla.nl. 1 2 3 4 5 +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_cname_double.rpl b/testdata/iter_cname_double.rpl new file mode 100644 index 00000000000..2e640fd114f --- /dev/null +++ b/testdata/iter_cname_double.rpl @@ -0,0 +1,163 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test double cname in reply. +; this is in response to an error report from Robert Edmonds, +; about resolution of images-na.ssl-images-amazon.com. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.next.com. IN A +SECTION AUTHORITY +next.com. IN NS ns.next.com. +SECTION ADDITIONAL +ns.next.com. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +; two CNAMEs for one name? +www.example.com. IN CNAME www.next.com. +www.example.com. IN CNAME www.next.com. +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.next.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA +SECTION QUESTION +www.next.com. IN A +SECTION ANSWER +www.next.com. IN A 10.20.30.40 +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +next.com. IN NS +SECTION ANSWER +next.com. IN NS ns.next.com. +SECTION ADDITIONAL +ns.next.com. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME www.next.com. +www.next.com. IN A 10.20.30.40 +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_cname_nx.rpl b/testdata/iter_cname_nx.rpl new file mode 100644 index 00000000000..cb80aa5fc7a --- /dev/null +++ b/testdata/iter_cname_nx.rpl @@ -0,0 +1,157 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test cname followed by nxdomain reply rcode. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.next.com. IN A +SECTION AUTHORITY +next.com. IN NS ns.next.com. +SECTION ADDITIONAL +ns.next.com. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME www.next.com. +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.next.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NXDOMAIN +SECTION QUESTION +www.next.com. IN A +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +next.com. IN NS +SECTION ANSWER +next.com. IN NS ns.next.com. +SECTION ADDITIONAL +ns.next.com. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NXDOMAIN +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME www.next.com. +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_cname_qnamecopy.rpl b/testdata/iter_cname_qnamecopy.rpl new file mode 100644 index 00000000000..12019816ac1 --- /dev/null +++ b/testdata/iter_cname_qnamecopy.rpl @@ -0,0 +1,198 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test cname to nodata and if qname is set to orig after prepend + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.next.com. IN A +SECTION AUTHORITY +next.com. IN NS ns.next.com. +SECTION ADDITIONAL +ns.next.com. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME www.next.com. +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +; ns.next.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.next.com. IN A +SECTION ANSWER +SECTION AUTHORITY +next.com. IN SOA next.com. next.com. 2007090400 28800 7200 604800 18000 +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +next.com. IN NS +SECTION ANSWER +next.com. IN NS ns.next.com. +SECTION ADDITIONAL +ns.next.com. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD CD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 3 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD CD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME www.next.com. +SECTION AUTHORITY +next.com. IN SOA next.com. next.com. 2007090400 28800 7200 604800 18000 +SECTION ADDITIONAL +ENTRY_END + +; query it from cache again +STEP 5 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 7 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME www.next.com. +SECTION AUTHORITY +next.com. IN SOA next.com. next.com. 2007090400 28800 7200 604800 18000 +SECTION ADDITIONAL +ENTRY_END + +; query answer to cname from cache again, test if stored under wrong qname. +STEP 9 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.next.com. IN A +ENTRY_END + +STEP 11 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.next.com. IN A +SECTION ANSWER +SECTION AUTHORITY +next.com. IN SOA next.com. next.com. 2007090400 28800 7200 604800 18000 +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_cycle.rpl b/testdata/iter_cycle.rpl new file mode 100644 index 00000000000..fd1cf238a17 --- /dev/null +++ b/testdata/iter_cycle.rpl @@ -0,0 +1,178 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test resolution with dependency cycle +; query for ns.example.com, needs ns.example.net, needs ns.example.com. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION AUTHORITY +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION AUTHORITY +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +; note this will be scrubbed off +ns.example.net. IN A 1.2.3.1 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION AUTHORITY +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +; note this will be scrubbed off +ns.example.net. IN A 1.2.3.1 +ENTRY_END +RANGE_END + +; e.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.12.94.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.com. +SECTION ADDITIONAL +; note this will be scrubbed off +ns.example.com. IN A 1.2.3.2 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION AUTHORITY +example.net. IN NS ns.example.com. +SECTION ADDITIONAL +; note this will be scrubbed off +ns.example.com. IN A 1.2.3.2 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +ns.example.com. IN A +ENTRY_END + +; recursion happens here. +; cycle detected and it fails. +STEP 20 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +ns.example.com. IN A +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_cycle_noh.rpl b/testdata/iter_cycle_noh.rpl new file mode 100644 index 00000000000..ce5a8672247 --- /dev/null +++ b/testdata/iter_cycle_noh.rpl @@ -0,0 +1,225 @@ +; config options +server: + harden-glue: "no" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test resolution where disabled scrubber avoids cycle +; query for ns.example.com, needs ns.example.net, needs ns.example.com. +; scrubber disabled, so extra glue is trusted. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION AUTHORITY +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION AUTHORITY +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.1 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION AUTHORITY +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.1 +ENTRY_END +RANGE_END + +; e.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.12.94.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.2 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION AUTHORITY +example.net. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.2 +ENTRY_END +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.1 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.2 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.1 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.2 +SECTION AUTHORITY +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.1 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +ns.example.com. IN A +ENTRY_END + +; recursion happens here. +; cycle detected and it fails. +STEP 20 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.2 +SECTION AUTHORITY +example.com. IN NS ns.example.net. +; scrubbed off +; SECTION ADDITIONAL +; ns.example.net. IN A 1.2.3.1 +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_dnsseclame_bug.rpl b/testdata/iter_dnsseclame_bug.rpl new file mode 100644 index 00000000000..a22dc96bc55 --- /dev/null +++ b/testdata/iter_dnsseclame_bug.rpl @@ -0,0 +1,465 @@ +; config options +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. + +CONFIG_END + +SCENARIO_BEGIN Bug test dnssec-lame detection at ds point with target queries. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN A +SECTION AUTHORITY +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION AUTHORITY +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END +RANGE_END + +; e.gtld-servers.net. +; Note this timing is so it will provide answers at the beginning. +RANGE_BEGIN 0 30 + ADDRESS 192.12.94.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +e.gtld-servers.net. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +a.gtld-servers.net. IN AAAA +SECTION ANSWER +ENTRY_END + +; no example.net delegation answers yet. + +RANGE_END + +; e.gtld-servers.net. +; Note this timing is so it will not provide answers at the beginning, +; but only later on. +RANGE_BEGIN 30 100 + ADDRESS 192.12.94.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +e.gtld-servers.net. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +a.gtld-servers.net. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END +RANGE_END + +; ns.example.net. +; Note this timing is so it will not provide answers at the beginning, +; but only later on. +RANGE_BEGIN 30 100 + ADDRESS 1.2.3.44 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION ANSWER +ns.example.net. IN A 1.2.3.44 +SECTION AUTHORITY +example.net. IN NS ns.example.net. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END + +; response to DNSKEY priming query +; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899} +SECTION AUTHORITY +; no NS set. not needed for this test. +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. IN NS ns.example.net. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. C/0b+sqlsdSTkhd+aDXb6ELyuQreosIGBzLCtWxYGD+Q9QGB5rN8uB+4+48yhw36pd3MfeAn06AgAnJ6eu8tJg== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.sub.example.com. IN AAAA +SECTION ANSWER +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.55 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.55 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +ENTRY_END + +; fine DNSKEY response. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +ENTRY_END + + +; correct delegation with DS +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. IN NS ns.example.net. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. IN NS ns.example.net. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END +RANGE_END + +; This server is DNSSEC LAME! +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + + +; response to DNSKEY priming query +; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.sub.example.com. IN AAAA +SECTION ANSWER +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 11.11.11.11 +SECTION AUTHORITY +; dnssec-lameness detection depends on this information +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END +RANGE_END + + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +STEP 10 NOTHING +; recursion at time 10. +; first recursion with answers in 0-30 time +; with bug it now resolves to the bad version +; fixed, it stops waiting for more target queries. + +STEP 40 NOTHING +; next recursion with more answers at time 40. + +; recursion happens here. +STEP 50 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD DO NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +ENTRY_END +SCENARIO_END diff --git a/testdata/iter_dnsseclame_ds.rpl b/testdata/iter_dnsseclame_ds.rpl new file mode 100644 index 00000000000..0e8405db94e --- /dev/null +++ b/testdata/iter_dnsseclame_ds.rpl @@ -0,0 +1,414 @@ +; config options +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. + +CONFIG_END + +SCENARIO_BEGIN Test dnssec-lame detection at ds point. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN A +SECTION AUTHORITY +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION AUTHORITY +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END +RANGE_END + +; e.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.12.94.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +e.gtld-servers.net. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +a.gtld-servers.net. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.44 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION ANSWER +ns.example.net. IN A 1.2.3.44 +SECTION AUTHORITY +example.net. IN NS ns.example.net. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END + +; response to DNSKEY priming query +; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899} +SECTION AUTHORITY +; no NS set. not needed for this test. +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. IN NS ns.example.net. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. C/0b+sqlsdSTkhd+aDXb6ELyuQreosIGBzLCtWxYGD+Q9QGB5rN8uB+4+48yhw36pd3MfeAn06AgAnJ6eu8tJg== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.sub.example.com. IN AAAA +SECTION ANSWER +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.55 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.55 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +ENTRY_END + +; fine DNSKEY response. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +ENTRY_END + + +; correct delegation with DS +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. IN NS ns.example.net. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. IN NS ns.example.net. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END +RANGE_END + +; This server is DNSSEC LAME! +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + + +; response to DNSKEY priming query +; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.sub.example.com. IN AAAA +SECTION ANSWER +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 11.11.11.11 +SECTION AUTHORITY +; dnssec-lameness detection depends on this information +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END +RANGE_END + + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 20 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD DO NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +ENTRY_END +SCENARIO_END diff --git a/testdata/iter_dnsseclame_ds_ok.rpl b/testdata/iter_dnsseclame_ds_ok.rpl new file mode 100644 index 00000000000..0ff322cd42b --- /dev/null +++ b/testdata/iter_dnsseclame_ds_ok.rpl @@ -0,0 +1,367 @@ +; config options +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. + +CONFIG_END + +SCENARIO_BEGIN Test dnssec-lame detection at ds point, which is ok. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION AUTHORITY +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION AUTHORITY +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END + +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END +RANGE_END + +; e.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.12.94.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.44 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION ANSWER +ns.example.net. IN A 1.2.3.44 +SECTION AUTHORITY +example.net. IN NS ns.example.net. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END + +; response to DNSKEY priming query +; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899} +SECTION AUTHORITY +; no NS set. not needed for this test. +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.55 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.55 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +ENTRY_END + +; fine DNSKEY response. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +ENTRY_END + +; correct delegation with DS +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. IN NS ns.example.net. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. IN NS ns.example.net. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END +RANGE_END + +; server is not DNSSEC lame. +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. IN NS ns.example.net. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. C/0b+sqlsdSTkhd+aDXb6ELyuQreosIGBzLCtWxYGD+Q9QGB5rN8uB+4+48yhw36pd3MfeAn06AgAnJ6eu8tJg== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response to DNSKEY priming query +; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.sub.example.com. IN AAAA +SECTION ANSWER +ENTRY_END +RANGE_END + + + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 20 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD DO NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_dnsseclame_ta.rpl b/testdata/iter_dnsseclame_ta.rpl new file mode 100644 index 00000000000..9472dcc1a1e --- /dev/null +++ b/testdata/iter_dnsseclame_ta.rpl @@ -0,0 +1,327 @@ +; config options +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. + +CONFIG_END + +SCENARIO_BEGIN Test dnssec-lame detection at anchor point. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN A +SECTION AUTHORITY +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION AUTHORITY +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +; this entry; glue will make unbound take this reference first. +; it is however, the lame server. +ns.example.com. IN A 1.2.3.55 +ENTRY_END +RANGE_END + +; e.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.12.94.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +a.gtld-servers.net. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +e.gtld-servers.net. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.44 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION ANSWER +ns.example.net. IN A 1.2.3.44 +SECTION AUTHORITY +example.net. IN NS ns.example.net. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134802 20070829134802 2854 example.com. AJwwYIUGH7HgjehzPVkrVUFmFkSGGksGjUX+/zqpCOG9a/cgGC+n40I= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134802 20070829134802 2854 example.com. ABUu7ITHLl6vfuWzedIp03igXknUR1gYPBl8X6uIDrvraN1bjQJPXME= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.55 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.55 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +ENTRY_END + +; lame DNSKEY response. +; here without sigs (assuming server does unknown-RR type handling) +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +ENTRY_END + +; lame NS response +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END + +; the lame response. No RRSIGS. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +; the wrong answer. +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +; dnssec-lameness detection depends on this information +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 20 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD DO NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_dnsseclame_ta_ok.rpl b/testdata/iter_dnsseclame_ta_ok.rpl new file mode 100644 index 00000000000..e794b54fdaa --- /dev/null +++ b/testdata/iter_dnsseclame_ta_ok.rpl @@ -0,0 +1,303 @@ +; config options +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. + +CONFIG_END + +SCENARIO_BEGIN Test dnssec-lame detection with anchor point that is ok. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION AUTHORITY +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION AUTHORITY +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END +RANGE_END + +; e.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.12.94.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.44 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION ANSWER +ns.example.net. IN A 1.2.3.44 +SECTION AUTHORITY +example.net. IN NS ns.example.net. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134802 20070829134802 2854 example.com. AJwwYIUGH7HgjehzPVkrVUFmFkSGGksGjUX+/zqpCOG9a/cgGC+n40I= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134802 20070829134802 2854 example.com. ABUu7ITHLl6vfuWzedIp03igXknUR1gYPBl8X6uIDrvraN1bjQJPXME= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.55 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.55 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +ENTRY_END + +; the response is not lame at all. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134802 20070829134802 2854 example.com. AJwwYIUGH7HgjehzPVkrVUFmFkSGGksGjUX+/zqpCOG9a/cgGC+n40I= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134802 20070829134802 2854 example.com. ABUu7ITHLl6vfuWzedIp03igXknUR1gYPBl8X6uIDrvraN1bjQJPXME= ;{id = 2854} +ENTRY_END + +; response is not lame. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 20 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD DO NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_domain_sale.rpl b/testdata/iter_domain_sale.rpl new file mode 100644 index 00000000000..724b51dadb1 --- /dev/null +++ b/testdata/iter_domain_sale.rpl @@ -0,0 +1,272 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test resolver with a domain sale +; and the old operator is nasty, keeps running his server with the old data. +; and lots of lookups keep going towards the domain. +; eventually, the NS record has to timeout. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. (before sale of domain) +RANGE_BEGIN 0 20 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. (after sale of domain) +RANGE_BEGIN 30 200 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 8.8.8.8 +ENTRY_END +RANGE_END + +; ns.example.com. first owner +RANGE_BEGIN 0 200 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ENTRY_END + +; nxdomains for any name,type +; last in RANGE so that it matches everything left over. +; it includes the NS record. +ENTRY_BEGIN +MATCH opcode +ADJUST copy_id copy_query +REPLY QR AA NXDOMAIN +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. 3600 IN SOA a. b. 1 2 3 4 5 +example.com. 3600 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. new owner +RANGE_BEGIN 0 200 + ADDRESS 8.8.8.8 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 8.8.8.8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 88.88.88.88 +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 3600 IN A 8.8.8.8 +ENTRY_END +RANGE_END + +; Fetch the old record from the old owner. +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 5 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ENTRY_END + +; the domain is sold (right at this time). +; but the information stays in the cache. + +; after 1800 secs still the cached answer +STEP 20 TIME_PASSES ELAPSE 1800 + +STEP 30 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 40 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 1800 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. 1800 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 1800 IN A 1.2.3.4 +ENTRY_END + +; and ask another query +STEP 50 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +nx1.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 60 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NXDOMAIN +SECTION QUESTION +nx1.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. 3600 IN SOA a. b. 1 2 3 4 5 +example.com. 1800 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 1800 IN A 1.2.3.4 +ENTRY_END + +; after another 1900 seconds the domain must have timed out. +STEP 70 TIME_PASSES ELAPSE 1900 + +; the NS record should have timed out. +STEP 80 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 90 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 88.88.88.88 +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 3600 IN A 8.8.8.8 +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_domain_sale_nschange.rpl b/testdata/iter_domain_sale_nschange.rpl new file mode 100644 index 00000000000..a7d9f11b88b --- /dev/null +++ b/testdata/iter_domain_sale_nschange.rpl @@ -0,0 +1,340 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test resolver with a domain sale and NS changes +; and the old operator is nasty, keeps running his server with the old data. +; and lots of lookups keep going towards the domain. +; and the old server is changing the NS record of the old domain. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. (before sale of domain) +RANGE_BEGIN 0 20 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. (after sale of domain) +RANGE_BEGIN 30 200 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 8.8.8.8 +ENTRY_END +RANGE_END + +; ns.example.com. first owner +RANGE_BEGIN 0 30 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ENTRY_END + +; nxdomains for any name,type +; last in RANGE so that it matches everything left over. +; it includes the NS record. +ENTRY_BEGIN +MATCH opcode +ADJUST copy_id copy_query +REPLY QR AA NXDOMAIN +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. 3600 IN SOA a. b. 1 2 3 4 5 +example.com. 3600 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. first owner, NS changed +RANGE_BEGIN 40 200 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS nsb.example.com. +SECTION ADDITIONAL +nsb.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. 3600 IN NS nsb.example.com. +SECTION ADDITIONAL +nsb.example.com. 3600 IN A 1.2.3.4 +ENTRY_END + +; nxdomains for any name,type +; last in RANGE so that it matches everything left over. +; it includes the NS record. +ENTRY_BEGIN +MATCH opcode +ADJUST copy_id copy_query +REPLY QR AA NXDOMAIN +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. 3600 IN SOA a. b. 1 2 3 4 5 +example.com. 3600 IN NS nsb.example.com. +SECTION ADDITIONAL +nsb.example.com. 3600 IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. new owner +RANGE_BEGIN 0 200 + ADDRESS 8.8.8.8 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 8.8.8.8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 88.88.88.88 +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 3600 IN A 8.8.8.8 +ENTRY_END +RANGE_END + +; Fetch the old record from the old owner. +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 5 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ENTRY_END + +; the domain is sold (right at this time). +; but the information stays in the cache. + +; after 1800 secs still the cached answer +STEP 20 TIME_PASSES ELAPSE 1800 + +STEP 30 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 40 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 1800 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. 1800 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 1800 IN A 1.2.3.4 +ENTRY_END + +; and ask another query +STEP 50 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +nx1.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 60 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NXDOMAIN +SECTION QUESTION +nx1.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. 3600 IN SOA a. b. 1 2 3 4 5 +example.com. 3600 IN NS nsb.example.com. +SECTION ADDITIONAL +nsb.example.com. 3600 IN A 1.2.3.4 +ENTRY_END + +STEP 62 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +nx1.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 63 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NXDOMAIN +SECTION QUESTION +nx1.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. 3600 IN SOA a. b. 1 2 3 4 5 +example.com. 1800 IN NS nsb.example.com. +SECTION ADDITIONAL +nsb.example.com. 3600 IN A 1.2.3.4 +ENTRY_END + +; after another 1900 seconds the domain must have timed out. +STEP 70 TIME_PASSES ELAPSE 1900 + +; the NS record should have timed out. +STEP 80 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 90 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 88.88.88.88 +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 3600 IN A 8.8.8.8 +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_donotq127.rpl b/testdata/iter_donotq127.rpl new file mode 100644 index 00000000000..15f9fff6086 --- /dev/null +++ b/testdata/iter_donotq127.rpl @@ -0,0 +1,134 @@ +; config options +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test iterator donotquery of 127/8. +; The scenario presents an iteration chain that has 127.0.0.2 and +; 127.255.255.255 as nameserver IPs, like a spam-blocklist. +; these are 127/8 localhost and should be blocked, causing servfail. +; if not blocked, they cause a lookup, but this file does not specify +; 127.* responses, so testbound will fail the test. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +a.gtld-servers.net. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns2.example.com. +SECTION ADDITIONAL +;ns.example.com. IN A 1.2.3.4 +ns.example.com. IN A 127.255.255.255 +ns2.example.com. IN A 127.0.0.2 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS ns2.example.com. +SECTION ADDITIONAL +;ns.example.com. IN A 1.2.3.4 +ns.example.com. IN A 127.255.255.255 +ns2.example.com. IN A 127.0.0.2 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_dp_turnsuseless.rpl b/testdata/iter_dp_turnsuseless.rpl new file mode 100644 index 00000000000..9d0c35518b8 --- /dev/null +++ b/testdata/iter_dp_turnsuseless.rpl @@ -0,0 +1,166 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test parent-child dichotomy where dp turns useless + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +; data for ns-crap does not exist. +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NXDOMAIN +SECTION QUESTION +ns-crap. IN NS +SECTION AUTHORITY +; very short TTL so it'll expire. +. 2 SOA . . 1 2 3 4 5 +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +; very short TTL so it can time out quickly. +example.com. 2 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns-crap. +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 2 IN A 10.20.30.40 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +example.com. IN NS +ENTRY_END + +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns-crap. +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +STEP 20 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 30 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 2 IN A 10.20.30.40 +ENTRY_END + +; parent side stuff times out +STEP 40 TIME_PASSES ELAPSE 5.0 + +; actual retry logic must fire +STEP 50 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 60 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 2 IN A 10.20.30.40 +ENTRY_END + + + +SCENARIO_END diff --git a/testdata/iter_ds_locate_ns.rpl b/testdata/iter_ds_locate_ns.rpl new file mode 100644 index 00000000000..d3b613e89e6 --- /dev/null +++ b/testdata/iter_ds_locate_ns.rpl @@ -0,0 +1,145 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test locate of NS records for parent nameservers of DS + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +; content of root-servers.net +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +root-servers.net. IN NS +SECTION ANSWER +root-servers.net. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +k.root-servers.net. IN A +SECTION ANSWER +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +SECTION AUTHORITY +root-servers.net. IN NS K.ROOT-SERVERS.NET. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +k.root-servers.net. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +root-servers.net. IN SOA K.ROOT-SERVERS.NET. hostmaster. 1 2 3 4 5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +root-servers.net. IN DS +SECTION ANSWER +SECTION AUTHORITY +root-servers.net. IN SOA K.ROOT-SERVERS.NET. hostmaster. 1 2 3 4 5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +root-servers.net. IN DS +SECTION AUTHORITY +net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +root-servers.net. IN A +SECTION AUTHORITY +root-servers.net. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +root-servers.net. IN DS +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +root-servers.net. IN DS +SECTION ANSWER +SECTION AUTHORITY +net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6 +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_ds_locate_ns_cname.rpl b/testdata/iter_ds_locate_ns_cname.rpl new file mode 100644 index 00000000000..d99d301ce76 --- /dev/null +++ b/testdata/iter_ds_locate_ns_cname.rpl @@ -0,0 +1,155 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test locate of NS records for DS with CNAME + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +; content of root-servers.net +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +root-servers.net. IN NS +SECTION ANSWER +root-servers.net. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +k.root-servers.net. IN A +SECTION ANSWER +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +SECTION AUTHORITY +root-servers.net. IN NS K.ROOT-SERVERS.NET. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +k.root-servers.net. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +root-servers.net. IN SOA K.ROOT-SERVERS.NET. hostmaster. 1 2 3 4 5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +root-servers.net. IN DS +SECTION ANSWER +root-servers.net. IN CNAME blabla.com. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NXDOMAIN +SECTION QUESTION +blabla.com. IN DS +SECTION ANSWER +SECTION AUTHORITY +. IN SOA K.ROOT-SERVERS.NET. hostmaster. 1 2 3 4 5 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +root-servers.net. IN DS +SECTION AUTHORITY +net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +root-servers.net. IN A +SECTION AUTHORITY +root-servers.net. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +root-servers.net. IN DS +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +root-servers.net. IN DS +SECTION ANSWER +SECTION AUTHORITY +net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6 +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_ds_locate_ns_nosoa.rpl b/testdata/iter_ds_locate_ns_nosoa.rpl new file mode 100644 index 00000000000..9c14cea4419 --- /dev/null +++ b/testdata/iter_ds_locate_ns_nosoa.rpl @@ -0,0 +1,145 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test locate of NS records for DS without a SOA record + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +; content of root-servers.net +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +root-servers.net. IN NS +SECTION ANSWER +root-servers.net. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +k.root-servers.net. IN A +SECTION ANSWER +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +SECTION AUTHORITY +root-servers.net. IN NS K.ROOT-SERVERS.NET. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +k.root-servers.net. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +root-servers.net. IN SOA K.ROOT-SERVERS.NET. hostmaster. 1 2 3 4 5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +root-servers.net. IN DS +SECTION ANSWER +SECTION AUTHORITY +;root-servers.net. IN SOA K.ROOT-SERVERS.NET. hostmaster. 1 2 3 4 5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +root-servers.net. IN DS +SECTION AUTHORITY +net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +root-servers.net. IN A +SECTION AUTHORITY +root-servers.net. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +root-servers.net. IN DS +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +root-servers.net. IN DS +SECTION ANSWER +SECTION AUTHORITY +net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6 +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_emptydp.rpl b/testdata/iter_emptydp.rpl new file mode 100644 index 00000000000..857a64e49d9 --- /dev/null +++ b/testdata/iter_emptydp.rpl @@ -0,0 +1,263 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "3 2 1 0 0" # make sure it fetches for test + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test iterator with empty delegation from cache. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. + +; sneak in some data into the cache to simulate partial data after timeouts +; gets scrubbed anyway. +example.net. NS ns.example.net. + +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +; com zone +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ENTRY_END + +; net zone +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +a.gtld-servers.net. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION AUTHORITY +example.net. NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +; example.net. zone +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION ANSWER +ns.example.net. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION ANSWER +ENTRY_END + +; example.com. zone +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +; bogus +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +ENTRY_END + +; make sure glue fetch is done. +STEP 11 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +ns.example.net. IN AAAA +ENTRY_END + +STEP 12 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_emptydp_for_glue.rpl b/testdata/iter_emptydp_for_glue.rpl new file mode 100644 index 00000000000..5e5e27a346d --- /dev/null +++ b/testdata/iter_emptydp_for_glue.rpl @@ -0,0 +1,493 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "3 2 1 0 0" # make sure it fetches for test + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test iterator with empty delegation for glue address +; setup: +; query for www.example.com. +; needs example.com served by ns.example.net and ns.example.org +; needs example.net served by ns.example.net and ns.example.org +; needs example.org served by ns.example.net and ns.example.org +; but the cache has all these NS rrsets, but not the addresses. +; observed in the wild this was from the in-addr zone towards two +; domains with such a setup. and high TTL NS, lower for A. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. + +; sneak in some data into the cache to simulate partial data after timeouts +; gets scrubbed away now .... +example.com. NS ns.example.net. +example.com. NS ns.example.org. +example.net. NS ns.example.net. +example.net. NS ns.example.org. +example.org. NS ns.example.net. +example.org. NS ns.example.org. + +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +org. IN A +SECTION AUTHORITY +org. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +; com zone +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. NS ns.example.net. +example.com. NS ns.example.org. +SECTION ADDITIONAL +; no glue! +ENTRY_END + +; net zone +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN A +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +a.gtld-servers.net. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION AUTHORITY +example.net. NS ns.example.net. +example.net. NS ns.example.org. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.4 +ENTRY_END + +; org zone +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +org. IN A +SECTION ANSWER +org. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +ns.example.org. IN A +SECTION AUTHORITY +example.org. NS ns.example.net. +example.org. NS ns.example.org. +SECTION ADDITIONAL +ns.example.org. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +; example.org. zone +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.org. IN NS +SECTION ANSWER +example.org. NS ns.example.net. +example.org. NS ns.example.org. +SECTION ADDITIONAL +ns.example.org. IN A 1.2.3.5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.org. IN A +SECTION ANSWER +ns.example.org. IN A 1.2.3.5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.org. IN AAAA +SECTION ANSWER +ENTRY_END + +; example.net. zone +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. NS ns.example.net. +example.net. NS ns.example.org. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION ANSWER +ns.example.net. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION ANSWER +ENTRY_END + +; example.com. zone +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +; bogus message. +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +ENTRY_END +RANGE_END + +; ns.example.org. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 + +; example.org. zone +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.org. IN NS +SECTION ANSWER +example.org. NS ns.example.net. +example.org. NS ns.example.org. +SECTION ADDITIONAL +ns.example.org. IN A 1.2.3.5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.org. IN A +SECTION ANSWER +ns.example.org. IN A 1.2.3.5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.org. IN AAAA +SECTION ANSWER +ENTRY_END + +; example.net. zone +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. NS ns.example.net. +example.net. NS ns.example.org. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION ANSWER +ns.example.net. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION ANSWER +ENTRY_END + +; example.com. zone +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +ENTRY_END + +; make sure glue fetch is done. +STEP 11 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +ns.example.net. IN AAAA +ENTRY_END + +STEP 12 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +; make sure NS fetch is done. +STEP 14 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +example.org. IN NS +ENTRY_END + +STEP 15 CHECK_ANSWER +ENTRY_BEGIN +MATCH ; none +REPLY QR RD RA NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + + +SCENARIO_END diff --git a/testdata/iter_fwdfirst.rpl b/testdata/iter_fwdfirst.rpl new file mode 100644 index 00000000000..5154babb348 --- /dev/null +++ b/testdata/iter_fwdfirst.rpl @@ -0,0 +1,157 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. + +forward-zone: + name: "example.com" + forward-addr: 1.2.3.6 # failing resolver + forward-first: yes + +CONFIG_END + +SCENARIO_BEGIN Test forward-first directive + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; local resolver (that fails a lot) +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR RA SERVFAIL +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +;example.com. IN NS ns.example.com. +SECTION ADDITIONAL +;ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR RA SERVFAIL +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +;www.example.com. IN A 10.20.30.50 +SECTION AUTHORITY +;example.com. IN NS ns.example.com. +SECTION ADDITIONAL +;ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_fwdstub.rpl b/testdata/iter_fwdstub.rpl new file mode 100644 index 00000000000..06a8789b721 --- /dev/null +++ b/testdata/iter_fwdstub.rpl @@ -0,0 +1,218 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +forward-zone: + name: "example.com" + forward-addr: 10.0.0.1 +stub-zone: + name: "sub.example.com" + stub-addr: 10.0.0.2 +CONFIG_END + +SCENARIO_BEGIN Test iterative resolve with a stub under a forward zone + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; forwarder for example.com. +RANGE_BEGIN 0 100 + ADDRESS 10.0.0.1 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.0.0.4 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +; fail all other queries +ENTRY_BEGIN +MATCH opcode +ADJUST copy_id copy_query +REPLY QR SERVFAIL +SECTION QUESTION +example.com. IN A +ENTRY_END +RANGE_END + +; stub for sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 10.0.0.2 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 10.0.0.5 +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.44 +ENTRY_END +RANGE_END + + +; check if forwarder is honored +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.0.0.4 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +; try to resolve from stub zone +STEP 20 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +STEP 30 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 10.0.0.5 +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.44 +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_fwdstubroot.rpl b/testdata/iter_fwdstubroot.rpl new file mode 100644 index 00000000000..e43584cbef1 --- /dev/null +++ b/testdata/iter_fwdstubroot.rpl @@ -0,0 +1,175 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +forward-zone: + name: "." + forward-addr: 10.0.0.1 +stub-zone: + name: "sub.example.com" + stub-addr: 10.0.0.2 +CONFIG_END + +SCENARIO_BEGIN Test iterative resolve with a stub under a forward root zone + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 + +; No answers from the actual root, blocked. + +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; forwarder for example.com. +RANGE_BEGIN 0 100 + ADDRESS 10.0.0.1 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.0.0.4 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +; fail all other queries +ENTRY_BEGIN +MATCH opcode +ADJUST copy_id copy_query +REPLY QR SERVFAIL +SECTION QUESTION +example.com. IN A +ENTRY_END +RANGE_END + +; stub for sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 10.0.0.2 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 10.0.0.5 +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.44 +ENTRY_END +RANGE_END + +; try to resolve from stub zone +STEP 20 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +STEP 30 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 10.0.0.5 +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.44 +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_got6only.rpl b/testdata/iter_got6only.rpl new file mode 100644 index 00000000000..d7b4fdebaf0 --- /dev/null +++ b/testdata/iter_got6only.rpl @@ -0,0 +1,135 @@ +; config options +server: + do-ip6: no + target-fetch-policy: "0 0 0 0 0 " +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test iterator when only ip6 in dp but doip6 is no + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.bla.com. +SECTION ADDITIONAL +; not included +;ns.bla.com. IN A 1.2.3.4 + +; and this one is useless because do-ip6 is "no" +ns.bla.com. IN AAAA ::53 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.bla.com. IN A +SECTION ANSWER +ns.bla.com. IN A 1.2.3.4 +ENTRY_END + +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_hint_lame.rpl b/testdata/iter_hint_lame.rpl new file mode 100644 index 00000000000..8cbede12213 --- /dev/null +++ b/testdata/iter_hint_lame.rpl @@ -0,0 +1,120 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test iterative resolve with lame hints. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR RA NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_lame_aaaa.rpl b/testdata/iter_lame_aaaa.rpl new file mode 100644 index 00000000000..8afef770ff6 --- /dev/null +++ b/testdata/iter_lame_aaaa.rpl @@ -0,0 +1,181 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test iterator lameness detection of AAAA-only lameness + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN AAAA +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN AAAA +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + + +; response to AAAA query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.com. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +. 3600000 IN NS a.root-servers.net. +. 3600000 IN NS b.root-servers.net. +. 3600000 IN NS c.root-servers.net. +. 3600000 IN NS d.root-servers.net. +. 3600000 IN NS e.root-servers.net. +. 3600000 IN NS f.root-servers.net. +. 3600000 IN NS g.root-servers.net. +. 3600000 IN NS h.root-servers.net. +. 3600000 IN NS i.root-servers.net. +. 3600000 IN NS j.root-servers.net. +. 3600000 IN NS k.root-servers.net. +. 3600000 IN NS l.root-servers.net. +. 3600000 IN NS m.root-servers.net. +SECTION ADDITIONAL +a.root-servers.net. 3600000 IN A 198.41.0.4 +b.root-servers.net. 3600000 IN A 128.9.0.107 +c.root-servers.net. 3600000 IN A 192.33.4.12 +ENTRY_END + +; response to A query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.com. IN A +SECTION ANSWER +example.com. 120 IN A 204.14.213.188 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +MATCH TCP +REPLY RD +SECTION QUESTION +example.com. IN AAAA +ENTRY_END + +; this fails; it is LAME +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +example.com. IN AAAA +SECTION ANSWER +ENTRY_END + +; Now try the A type, which works, and is not LAME. +STEP 20 QUERY +ENTRY_BEGIN +MATCH TCP +REPLY RD +SECTION QUESTION +example.com. IN A +ENTRY_END + +; this fails; it is LAME +STEP 30 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +example.com. IN A +SECTION ANSWER +example.com. 120 IN A 204.14.213.188 +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_lame_noaa.rpl b/testdata/iter_lame_noaa.rpl new file mode 100644 index 00000000000..116d7a2d426 --- /dev/null +++ b/testdata/iter_lame_noaa.rpl @@ -0,0 +1,201 @@ +; config options +server: + harden-referral-path: no + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test lame detection if AA bit is omitted +; the query is answered with a reply that has +; no AA bit +; no SOA record +; noanswer/noerror +; NS record in there which is not a down delegation (==). +; the query is not sent to a forward zone + +STEP 10 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; root prime is sent +STEP 20 CHECK_OUT_QUERY +ENTRY_BEGIN +MATCH qname qtype opcode +SECTION QUESTION +. IN NS +ENTRY_END +STEP 30 REPLY +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +; query sent to root server +STEP 40 CHECK_OUT_QUERY +ENTRY_BEGIN +MATCH qname qtype opcode +SECTION QUESTION +www.example.com. IN A +ENTRY_END +STEP 50 REPLY +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +; query sent to .com server +STEP 60 CHECK_OUT_QUERY +ENTRY_BEGIN +MATCH qname qtype opcode +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; answer the NS queries that have been generated +; STEP 62 CHECK_OUT_QUERY +; ENTRY_BEGIN +; MATCH qname qtype opcode +; SECTION QUESTION +; com. IN NS +; ENTRY_END +; +; STEP 63 REPLY +; ; ENTRY_BEGIN +; MATCH opcode qtype qname +; ADJUST copy_id +; REPLY QR AA NOERROR +; SECTION QUESTION +; com. IN NS +; SECTION ANSWER +; com. IN NS a.gtld-servers.net. +; SECTION ADDITIONAL +; a.gtld-servers.net. IN A 192.5.6.30 +; ENTRY_END + +STEP 70 REPLY +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns1.example.com. +example.com. IN NS ns2.example.com. +SECTION ADDITIONAL +ns1.example.com. IN A 168.192.2.2 +ns2.example.com. IN A 168.192.3.3 +ENTRY_END + +; no matter which one the iterator tries first, we present it as 'lame' +; query to ns1.example.com or ns2.example.com. +STEP 80 CHECK_OUT_QUERY +ENTRY_BEGIN +MATCH qname qtype opcode +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; STEP 82 CHECK_OUT_QUERY +; ENTRY_BEGIN +; MATCH qname qtype opcode +; SECTION QUESTION +; example.com. IN NS +; ENTRY_END +; +; STEP 83 REPLY +; ENTRY_BEGIN +; MATCH opcode qtype qname +; ADJUST copy_id +; REPLY QR AA NOERROR +; SECTION QUESTION +; example.com. IN NS +; SECTION ANSWER +; example.com. IN NS ns1.example.com. +; example.com. IN NS ns2.example.com. +; SECTION ADDITIONAL +; ns1.example.com. IN A 168.192.2.2 +; ns2.example.com. IN A 168.192.3.3 +; ENTRY_END +; +STEP 90 REPLY +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +; This is the BROKEN ANSWER here. +; it is lame. A delegation to example.com. itself. +example.com. IN NS ns1.example.com. +example.com. IN NS ns2.example.com. +SECTION ADDITIONAL +ns1.example.com. IN A 168.192.2.2 +ns2.example.com. IN A 168.192.3.3 +ENTRY_END + +; iterator should try again and ask the other nameserver. +STEP 100 CHECK_OUT_QUERY +ENTRY_BEGIN +MATCH qname qtype opcode +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 110 REPLY +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns1.example.com. +example.com. IN NS ns2.example.com. +SECTION ADDITIONAL +ns1.example.com. IN A 168.192.2.2 +ns2.example.com. IN A 168.192.3.3 +ENTRY_END + + +; is the final answer correct? +STEP 200 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns1.example.com. +example.com. IN NS ns2.example.com. +SECTION ADDITIONAL +ns1.example.com. IN A 168.192.2.2 +ns2.example.com. IN A 168.192.3.3 +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_lame_nosoa.rpl b/testdata/iter_lame_nosoa.rpl new file mode 100644 index 00000000000..903bb29bc99 --- /dev/null +++ b/testdata/iter_lame_nosoa.rpl @@ -0,0 +1,290 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test resolution with lame reply looks like nodata with noSOA + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION AUTHORITY +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END + +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.net. +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END +RANGE_END + +; e.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.12.94.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END +RANGE_END + +; ns.example.net. +; advertises +RA so it is REC_LAME. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.44 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR RA NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR RA NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION ANSWER +ns.example.net. IN A 1.2.3.44 +SECTION AUTHORITY +example.net. IN NS ns.example.net. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR RA NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +www.example.net. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR RA NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.net. +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR RA NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +example.com. IN NS ns.example.net. +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR RA NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.55 +SECTION AUTHORITY +example.com. IN NS ns.example.net. +example.com. IN NS ns.example.com. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.net. +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ns.example.net IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR RA NOERROR +SECTION QUESTION +mail.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. IN NS ns.example.net. +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +; ns.example.com. +; is like a BIND server that is LAME, authoritative for other domains, +; but not this one, and somehow got this NS record in its cache. +; trying to give 'lame referral' but to the same name, not up. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.55 +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +; store bad timing for one server to influence server selection +; 1.2.3.44 (ns.example.net) gets 900 msec. +; so the 376 ns.example.com is preferred. +STEP 1 INFRA_RTT 1.2.3.44 example.net. 900 + +STEP 10 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 20 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.net. +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +; scrubbed off +;ns.example.net IN A 1.2.3.44 +ENTRY_END + +; query to recursion-lame server +STEP 30 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +mail.example.com. IN A +ENTRY_END + +STEP 40 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +mail.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. IN NS ns.example.net. +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ENTRY_END + + +SCENARIO_END diff --git a/testdata/iter_lamescrub.rpl b/testdata/iter_lamescrub.rpl new file mode 100644 index 00000000000..5fe6b8af3d1 --- /dev/null +++ b/testdata/iter_lamescrub.rpl @@ -0,0 +1,149 @@ +; config options +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test lameness detection after scrubber. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +a.gtld-servers.net. IN AAAA +SECTION ANSWER +ENTRY_END +ENTRY_BEGIN + +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +a.gtld-servers.net. IN A +SECTION ANSWER +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +; This server is Lame! +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode +ADJUST copy_id copy_query +REPLY QR RD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +com. 155182 IN NS a.gtld-servers.net. +com. 155182 IN NS b.gtld-servers.net. +com. 155182 IN NS c.gtld-servers.net. +com. 155182 IN NS d.gtld-servers.net. +com. 155182 IN NS e.gtld-servers.net. +com. 155182 IN NS f.gtld-servers.net. +com. 155182 IN NS g.gtld-servers.net. +com. 155182 IN NS h.gtld-servers.net. +com. 155182 IN NS i.gtld-servers.net. +com. 155182 IN NS j.gtld-servers.net. +com. 155182 IN NS k.gtld-servers.net. +com. 155182 IN NS l.gtld-servers.net. +com. 155182 IN NS m.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. 155182 IN A 192.5.6.30 +b.gtld-servers.net. 155182 IN A 192.33.14.30 +c.gtld-servers.net. 155182 IN A 192.26.92.30 +d.gtld-servers.net. 155182 IN A 192.31.80.30 +e.gtld-servers.net. 155182 IN A 192.12.94.30 +f.gtld-servers.net. 155182 IN A 192.35.51.30 +g.gtld-servers.net. 155182 IN A 192.42.93.30 +h.gtld-servers.net. 155182 IN A 192.54.112.30 +i.gtld-servers.net. 155182 IN A 192.43.172.30 +j.gtld-servers.net. 155182 IN A 192.48.79.30 +k.gtld-servers.net. 155182 IN A 192.52.178.30 +l.gtld-servers.net. 155182 IN A 192.41.162.30 +m.gtld-servers.net. 155182 IN A 192.55.83.30 +a.gtld-servers.net. 155182 IN AAAA 2001:503:a83e::2:30 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursin happens here + +; check that the answer is a failure (lame server) +; and not a nodata-noerror message (false answer classification). +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_mod.rpl b/testdata/iter_mod.rpl new file mode 100644 index 00000000000..f7dd43e561d --- /dev/null +++ b/testdata/iter_mod.rpl @@ -0,0 +1,121 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + module-config: "iterator" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test basic iterative resolve without validator module + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_ns_badip.rpl b/testdata/iter_ns_badip.rpl new file mode 100644 index 00000000000..49abdd6887f --- /dev/null +++ b/testdata/iter_ns_badip.rpl @@ -0,0 +1,237 @@ +; config options +server: + target-fetch-policy: "3 2 1 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test iterator with delagation with bad IP address + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +a.gtld-servers.net. IN A +SECTION ANSWER +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +a.gtld-servers.net. IN AAAA +SECTION AUTHORITY +. SOA bla bla 1 2 3 4 5 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns2.example.com. +SECTION ADDITIONAL +ns.example.com. 10 IN A 1.2.3.4 +ns2.example.com. 3600 IN A 1.2.3.5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +foo.com. IN A +SECTION AUTHORITY +foo.com. IN NS ns.example.com. +foo.com. IN NS ns2.example.com. +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 10 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN NS ns2.example.com. +SECTION ADDITIONAL +ns.example.com. 10 IN A 1.2.3.4 +ns2.example.com. 3600 IN A 1.2.3.5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. 10 IN A 1.2.3.4 +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN NS ns2.example.com. +SECTION ADDITIONAL +ns2.example.com. 3600 IN A 1.2.3.5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns2.example.com. IN A +SECTION ANSWER +ns2.example.com. 3600 IN A 1.2.3.5 +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN NS ns2.example.com. +SECTION ADDITIONAL +ns.example.com. 10 IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +example.com. 3600 IN SOA bla. bla. 1 2 3 4 5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns2.example.com. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +example.com. 3600 IN SOA bla. bla. 1 2 3 4 5 +ENTRY_END + +; foo.com contents. +ENTRY_BEGIN +MATCH opcode qtype qname +REPLY QR NOERROR +SECTION QUESTION +www.foo.com. IN A +SECTION ANSWER +www.foo.com. 10 IN A 10.20.30.40 +SECTION AUTHORITY +foo.com. 3600 IN NS ns.example.com. +foo.com. 3600 IN NS ns2.example.com. +ENTRY_END + +RANGE_END + +; ns2.example.com. (lame) +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode +ADJUST copy_id copy_query +REPLY QR SERVFAIL +SECTION QUESTION +www.example.com. IN A +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.foo.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.foo.com. IN A +SECTION ANSWER +www.foo.com. 10 IN A 10.20.30.40 +SECTION AUTHORITY +foo.com. 3600 IN NS ns.example.com. +foo.com. 3600 IN NS ns2.example.com. +ENTRY_END + +STEP 15 TRAFFIC + +; Now move the time so good server times out and bad remains. +STEP 20 TIME_PASSES ELAPSE 20 + +; Try query again. +STEP 30 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.foo.com. IN A +ENTRY_END + +STEP 35 TRAFFIC + +; recursion happens here. +STEP 40 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.foo.com. IN A +SECTION ANSWER +www.foo.com. 10 IN A 10.20.30.40 +SECTION AUTHORITY +foo.com. 3600 IN NS ns.example.com. +foo.com. 3600 IN NS ns2.example.com. +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_ns_spoof.rpl b/testdata/iter_ns_spoof.rpl new file mode 100644 index 00000000000..8b7a4d57050 --- /dev/null +++ b/testdata/iter_ns_spoof.rpl @@ -0,0 +1,278 @@ +; config options +server: + harden-referral-path: yes + target-fetch-policy: "0 0 0 0 0" +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test NS record spoof protection. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +; for simplicity the root server is authoritative for root-servers.net +; and also for gtld-servers.net +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +K.ROOT-SERVERS.NET. IN A +SECTION ANSWER +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +a.gtld-servers.net. IN A +SECTION ANSWER +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +mail.example.com. IN A +SECTION ANSWER +mail.example.com. IN A 10.20.30.50 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +ENTRY_END + +;; answer to the spoofed query ; spoofed reply answer. +; here we put it in the nameserver for ease. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +bad123.example.com. IN A +SECTION ANSWER +bad123.example.com. IN A 6.6.6.6 +SECTION AUTHORITY +; evil NS set. +example.com. IN NS bad123.example.com. +ENTRY_END + +RANGE_END + +; evil server +RANGE_BEGIN 0 100 + ADDRESS 6.6.6.6 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 6.6.6.6 +SECTION AUTHORITY +example.com. IN NS bad123.example.com. +SECTION ADDITIONAL +bad123.example.com. IN A 6.6.6.6 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +mail.example.com. IN A +SECTION ANSWER +mail.example.com. IN A 6.6.6.6 +SECTION AUTHORITY +example.com. IN NS bad123.example.com. +SECTION ADDITIONAL +bad123.example.com. IN A 6.6.6.6 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +bad123.example.com. IN A +SECTION ANSWER +bad123.example.com. IN A 6.6.6.6 +SECTION AUTHORITY +; evil NS set. +example.com. IN NS bad123.example.com. +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +; spoofed query +STEP 20 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +bad123.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 30 CHECK_ANSWER +ENTRY_BEGIN +; no matching here, just accept the answer to the spoofed query. +; it is wrong, but only one query ... +; this test is to check further on, that we still have the right nameserver. +;MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +bad123.example.com. IN A +SECTION ANSWER +bad123.example.com. IN A 6.6.6.6 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +; a new query +STEP 40 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +mail.example.com. IN A +ENTRY_END + +STEP 50 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +mail.example.com. IN A +SECTION ANSWER +mail.example.com. IN A 10.20.30.50 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_pc_a.rpl b/testdata/iter_pc_a.rpl new file mode 100644 index 00000000000..985345c1536 --- /dev/null +++ b/testdata/iter_pc_a.rpl @@ -0,0 +1,233 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test resolution with parent child differ for type A. +; the parent has the correct A record. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.44 +ENTRY_END +RANGE_END + +; the working version. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.44 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.55 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +mail.example.com. IN A +SECTION ANSWER +mail.example.com. IN A 10.20.30.20 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ftp.example.com. IN A +SECTION ANSWER +ftp.example.com. IN A 10.20.30.10 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END +RANGE_END + +; Broken. Does not respond to anything (servfail instead +; of timeouts since this is easier to encode in .rpl file format). +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.55 +ENTRY_BEGIN +MATCH opcode +ADJUST copy_id copy_query +REPLY QR SERVFAIL +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 20 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END + +; now that the bad child NS record is in cache, ask something else. +STEP 30 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +mail.example.com. IN A +ENTRY_END + +STEP 40 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +mail.example.com. IN A +SECTION ANSWER +mail.example.com. IN A 10.20.30.20 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END + +; test cache of parent data +STEP 50 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +ftp.example.com. IN A +ENTRY_END + +STEP 60 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +ftp.example.com. IN A +SECTION ANSWER +ftp.example.com. IN A 10.20.30.10 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_pc_aaaa.rpl b/testdata/iter_pc_aaaa.rpl new file mode 100644 index 00000000000..20e1a787f40 --- /dev/null +++ b/testdata/iter_pc_aaaa.rpl @@ -0,0 +1,233 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test resolution with parent child differ for type AAAA. +; the parent has the correct A record. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN AAAA 2002:b44d::44 +ENTRY_END +RANGE_END + +; the working version. +RANGE_BEGIN 0 100 + ADDRESS 2002:b44d::44 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +ns.example.com. IN AAAA 2002:b44d::55 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN AAAA 2002:b44d::55 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN AAAA 2002:b44d::55 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN AAAA 2002:b44d::55 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +mail.example.com. IN A +SECTION ANSWER +mail.example.com. IN A 10.20.30.20 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN AAAA 2002:b44d::55 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ftp.example.com. IN A +SECTION ANSWER +ftp.example.com. IN A 10.20.30.10 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN AAAA 2002:b44d::55 +ENTRY_END +RANGE_END + +; Broken. Does not respond to anything (servfail instead +; of timeouts since this is easier to encode in .rpl file format). +RANGE_BEGIN 0 100 + ADDRESS 2002:b44d::55 +ENTRY_BEGIN +MATCH opcode +ADJUST copy_id copy_query +REPLY QR SERVFAIL +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 20 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN AAAA 2002:b44d::55 +ENTRY_END + +; now that the bad child NS record is in cache, ask something else. +STEP 30 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +mail.example.com. IN A +ENTRY_END + +STEP 40 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +mail.example.com. IN A +SECTION ANSWER +mail.example.com. IN A 10.20.30.20 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN AAAA 2002:b44d::55 +ENTRY_END + +; test cache of parent data +STEP 50 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +ftp.example.com. IN A +ENTRY_END + +STEP 60 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +ftp.example.com. IN A +SECTION ANSWER +ftp.example.com. IN A 10.20.30.10 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN AAAA 2002:b44d::55 +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_pcdiff.rpl b/testdata/iter_pcdiff.rpl new file mode 100644 index 00000000000..18b984c1679 --- /dev/null +++ b/testdata/iter_pcdiff.rpl @@ -0,0 +1,213 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test resolution with recursion and parent child differ. +; and the child gives bad information. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION AUTHORITY +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END + +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.net. +ENTRY_END +RANGE_END + +; e.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.12.94.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END + +RANGE_END + +; ns.example.net. +; The parent-IP version +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.44 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.55 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION ANSWER +ns.example.net. IN A 1.2.3.55 +SECTION AUTHORITY +example.net. IN NS ns.example.net. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.55 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.net. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net IN A 1.2.3.55 +ENTRY_END +RANGE_END + +; ns.example.net +; The child IP version. Does not respond to anything (servfail instead +; of timeouts since this is easier to encode in .rpl file format). +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.55 +ENTRY_BEGIN +MATCH opcode +ADJUST copy_id copy_query +REPLY QR SERVFAIL +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 20 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.net. +; scrubbed off +;SECTION ADDITIONAL +;ns.example.net IN A 1.2.3.44 +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_pcdirect.rpl b/testdata/iter_pcdirect.rpl new file mode 100644 index 00000000000..45765bee249 --- /dev/null +++ b/testdata/iter_pcdirect.rpl @@ -0,0 +1,246 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test resolver with parent-child diff for direct impact +; the trouble is resolving this right away. +; otherwise it gets picked out of the cache. +; i.e. on a failed lookup, pickup lame stuff from the cache. +; the nameserver lookup may have failed but produced some (lame) addresses. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +org. IN A +SECTION AUTHORITY +org. IN NS a0.org.afilias-nst.org. +SECTION ADDITIONAL +a0.org.afilias-nst.org. IN A 199.19.56.1 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.org. +ENTRY_END +RANGE_END + +; a0.org.afilias-nst.org. +RANGE_BEGIN 0 100 + ADDRESS 199.19.56.1 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +org. IN NS +SECTION ANSWER +org. IN NS a0.org.afilias-nst.org. +SECTION ADDITIONAL +a0.org.afilias-nst.org. IN A 199.19.56.1 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.org. IN A +SECTION AUTHORITY +example.org. IN NS ns.example.org. +SECTION ADDITIONAL +; parent-side working address. +ns.example.org. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.org. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.org. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.org. IN NS +SECTION ANSWER +example.org. IN NS ns.example.org. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.org. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA RA NOERROR +SECTION QUESTION +mail.example.com. IN A +SECTION ANSWER +mail.example.com. IN A 10.20.30.50 +SECTION AUTHORITY +example.com. IN NS ns.example.org. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR RA NOERROR +SECTION QUESTION +ns.example.org. IN A +SECTION ANSWER +; correct answer: ns.example.org. IN A 1.2.3.4 +SECTION AUTHORITY +ns.example.org. IN NS 1.2.3.4.example.org. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR RA NOERROR +SECTION QUESTION +ns.example.org. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +ns.example.org. IN NS 1.2.3.4.example.org. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA RA NXDOMAIN +SECTION QUESTION +1.2.3.4.example.org. IN A +SECTION ANSWER +SECTION AUTHORITY +example.org. IN SOA ns.example.org. root.example.org. 2009111400 14400 3600 1209600 86400 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA RA NXDOMAIN +SECTION QUESTION +1.2.3.4.example.org. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +example.org. IN SOA ns.example.org. root.example.org. 2009111400 14400 3600 1209600 86400 +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.org. +ENTRY_END + +; perhaps some messages are still pending - allow those to resolve. +STEP 20 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +mail.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 30 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +mail.example.com. IN A +SECTION ANSWER +mail.example.com. IN A 10.20.30.50 +SECTION AUTHORITY +example.com. IN NS ns.example.org. +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_pclame.rpl b/testdata/iter_pclame.rpl new file mode 100644 index 00000000000..21273e396df --- /dev/null +++ b/testdata/iter_pclame.rpl @@ -0,0 +1,191 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test resolution with recursion, parent child differ, lame domain +; make sure it stops probing once is has cached all the badness. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION AUTHORITY +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END + +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.net. +ENTRY_END +RANGE_END + +; e.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.12.94.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END + +RANGE_END + +RANGE_BEGIN 0 200 + ADDRESS 1.2.3.44 +ENTRY_BEGIN +MATCH opcode +ADJUST copy_id copy_query +REPLY QR SERVFAIL +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +ENTRY_END + +RANGE_END + +; Does not respond to anything (servfail instead +; of timeouts since this is easier to encode in .rpl file format). +RANGE_BEGIN 0 200 + ADDRESS 1.2.3.55 +ENTRY_BEGIN +MATCH opcode +ADJUST copy_id copy_query +REPLY QR SERVFAIL +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 20 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +ENTRY_END + +STEP 30 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +ftp.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 40 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +ftp.example.com. IN A +SECTION ANSWER +ENTRY_END + + +; no more outgoing queries to .com or .net, all should be cached. + +STEP 101 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +mail.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 120 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +mail.example.com. IN A +SECTION ANSWER +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_pcname.rpl b/testdata/iter_pcname.rpl new file mode 100644 index 00000000000..037b6426f4d --- /dev/null +++ b/testdata/iter_pcname.rpl @@ -0,0 +1,277 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test resolution with parent child differ in names. +; the parent has an extra name that is the only working one. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION AUTHORITY +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END + +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END +RANGE_END + +; e.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.12.94.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END + +RANGE_END + +; ns.example.net. +; the working version. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.44 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION ANSWER +ns.example.net. IN A 1.2.3.44 +SECTION AUTHORITY +example.net. IN NS ns.example.net. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.55 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +mail.example.com. IN A +SECTION ANSWER +mail.example.com. IN A 10.20.30.20 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END +RANGE_END + +; ns.example.net +; Broken. Does not respond to anything (servfail instead +; of timeouts since this is easier to encode in .rpl file format). +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.55 +ENTRY_BEGIN +MATCH opcode +ADJUST copy_id copy_query +REPLY QR SERVFAIL +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 20 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END + +; now that the bad child NS record is in cache, ask something else. +STEP 30 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +mail.example.com. IN A +ENTRY_END + +STEP 40 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +mail.example.com. IN A +SECTION ANSWER +mail.example.com. IN A 10.20.30.20 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_pcnamech.rpl b/testdata/iter_pcnamech.rpl new file mode 100644 index 00000000000..a979101d954 --- /dev/null +++ b/testdata/iter_pcnamech.rpl @@ -0,0 +1,424 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test resolution with parent child differ with extra child name. +; child has extra name and it has to be used once the other one stops working. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION AUTHORITY +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END + +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.44 +ENTRY_END +RANGE_END + +; e.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.12.94.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.55 +ENTRY_END + +RANGE_END + +; the working version, until time 50. +RANGE_BEGIN 0 50 + ADDRESS 1.2.3.44 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.55 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION ANSWER +ns.example.net. IN A 1.2.3.55 +SECTION AUTHORITY +example.net. IN NS ns.example.net. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.55 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.44 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +mail.example.com. IN A +SECTION ANSWER +mail.example.com. IN A 10.20.30.20 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.44 +ENTRY_END +RANGE_END + +; Broken. Does not respond to anything (servfail instead +; of timeouts since this is easier to encode in .rpl file format). +RANGE_BEGIN 0 50 + ADDRESS 1.2.3.55 +ENTRY_BEGIN +MATCH opcode +ADJUST copy_id copy_query +REPLY QR SERVFAIL +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +ENTRY_END +RANGE_END + +RANGE_BEGIN 50 100 + ADDRESS 1.2.3.44 +ENTRY_BEGIN +MATCH opcode +ADJUST copy_id copy_query +REPLY QR SERVFAIL +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +ENTRY_END +RANGE_END + +RANGE_BEGIN 50 100 + ADDRESS 1.2.3.55 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.55 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION ANSWER +ns.example.net. IN A 1.2.3.55 +SECTION AUTHORITY +example.net. IN NS ns.example.net. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.55 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.44 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +mail.example.com. IN A +SECTION ANSWER +mail.example.com. IN A 10.20.30.20 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.44 +ENTRY_END +RANGE_END + + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 20 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.44 +ENTRY_END + +; server stops working. + +STEP 50 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +mail.example.com. IN A +ENTRY_END + +STEP 60 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +mail.example.com. IN A +SECTION ANSWER +mail.example.com. IN A 10.20.30.20 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.44 +ENTRY_END + +; still pending query needs removal. +STEP 70 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +ns.example.net. IN AAAA +ENTRY_END + +STEP 71 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.55 +ENTRY_END + + +SCENARIO_END diff --git a/testdata/iter_pcnamechrec.rpl b/testdata/iter_pcnamechrec.rpl new file mode 100644 index 00000000000..f4c0197ba90 --- /dev/null +++ b/testdata/iter_pcnamechrec.rpl @@ -0,0 +1,403 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test resolution with parent child differ with pc child name. +; child has extra name and it has to be used once the other one stops working. +; the extra child name has parent-child trouble and needs its parent version. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION AUTHORITY +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END + +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.44 +ENTRY_END +RANGE_END + +; e.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.12.94.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.55 +ENTRY_END + +RANGE_END + +; the working version, until time 50. +RANGE_BEGIN 0 50 + ADDRESS 1.2.3.44 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION ANSWER +ns.example.net. IN A 1.2.3.44 +SECTION AUTHORITY +example.net. IN NS ns.example.net. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.44 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +mail.example.com. IN A +SECTION ANSWER +mail.example.com. IN A 10.20.30.20 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.44 +ENTRY_END +RANGE_END + +; Broken. Does not respond to anything (servfail instead +; of timeouts since this is easier to encode in .rpl file format). +RANGE_BEGIN 0 50 + ADDRESS 1.2.3.55 +ENTRY_BEGIN +MATCH opcode +ADJUST copy_id copy_query +REPLY QR SERVFAIL +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +ENTRY_END +RANGE_END + +RANGE_BEGIN 50 100 + ADDRESS 1.2.3.44 +ENTRY_BEGIN +MATCH opcode +ADJUST copy_id copy_query +REPLY QR SERVFAIL +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +ENTRY_END +RANGE_END + +RANGE_BEGIN 50 100 + ADDRESS 1.2.3.55 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION ANSWER +ns.example.net. IN A 1.2.3.44 +SECTION AUTHORITY +example.net. IN NS ns.example.net. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.44 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +mail.example.com. IN A +SECTION ANSWER +mail.example.com. IN A 10.20.30.20 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.44 +ENTRY_END +RANGE_END + + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 20 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.44 +ENTRY_END + +; server stops working. + +STEP 50 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +mail.example.com. IN A +ENTRY_END + +STEP 60 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +mail.example.com. IN A +SECTION ANSWER +mail.example.com. IN A 10.20.30.20 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.44 +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_pcnamerec.rpl b/testdata/iter_pcnamerec.rpl new file mode 100644 index 00000000000..ecc03d35350 --- /dev/null +++ b/testdata/iter_pcnamerec.rpl @@ -0,0 +1,278 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test resolution with parent child differ names recursive. +; the parent has an extra name that is the only working one. +; and that name needs its parent-side glue to work. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION AUTHORITY +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END + +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END +RANGE_END + +; e.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.12.94.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END + +RANGE_END + +; ns.example.net. +; the working version. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.44 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.55 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION ANSWER +ns.example.net. IN A 1.2.3.55 +SECTION AUTHORITY +example.net. IN NS ns.example.net. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.55 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.55 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +mail.example.com. IN A +SECTION ANSWER +mail.example.com. IN A 10.20.30.20 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END +RANGE_END + +; ns.example.net +; Broken. Does not respond to anything (servfail instead +; of timeouts since this is easier to encode in .rpl file format). +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.55 +ENTRY_BEGIN +MATCH opcode +ADJUST copy_id copy_query +REPLY QR SERVFAIL +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 20 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END + +; now that the bad child NS record is in cache, ask something else. +STEP 30 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +mail.example.com. IN A +ENTRY_END + +STEP 40 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +mail.example.com. IN A +SECTION ANSWER +mail.example.com. IN A 10.20.30.20 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_pcttl.rpl b/testdata/iter_pcttl.rpl new file mode 100644 index 00000000000..41d94bc4234 --- /dev/null +++ b/testdata/iter_pcttl.rpl @@ -0,0 +1,245 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + do-ip6: no + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test cache ttls where parent child differ in ttl +; and the lameness for parent suddenly becomes the only information point. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION AUTHORITY +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END + +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.foo.com. +SECTION ADDITIONAL +;ns.foo.com. 200 IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +foo.com. IN NS +SECTION AUTHORITY +foo.com. 200 IN NS ns.foo.com. +SECTION ADDITIONAL +ns.foo.com. 200 IN A 1.2.3.44 +ENTRY_END + +RANGE_END + +; e.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.12.94.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END + +RANGE_END + +; ns.foo.com. +; The parent-IP version +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.44 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +foo.com. IN NS +SECTION ANSWER +foo.com. 200 IN NS ns.foo.com. +SECTION ADDITIONAL +ns.foo.com. 100 IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ns.foo.com. IN A +SECTION ANSWER +ns.foo.com. 100 IN A 1.2.3.44 +SECTION AUTHORITY +foo.com. 200 IN NS ns.foo.com. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +ns.foo.com. IN AAAA +SECTION AUTHORITY +foo.com. 100 IN SOA . . 1 2 3 4 5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. 200 IN NS ns.foo.com. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 100 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. 200 IN NS ns.foo.com. +SECTION ADDITIONAL +ns.foo.com 100 IN A 1.2.3.44 +ENTRY_END +RANGE_END + +; NOT USED. The parent side equals child side but not in the cache. +; and they have different TTLs only. +; ns.foo.com +; The child IP version. Does not respond to anything (servfail instead +; of timeouts since this is easier to encode in .rpl file format). +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.55 +ENTRY_BEGIN +MATCH opcode +ADJUST copy_id copy_query +REPLY QR SERVFAIL +SECTION QUESTION +foo.com. IN NS +SECTION ANSWER +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 20 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 100 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. 100 IN NS ns.foo.com. +; scrubbed off +;SECTION ADDITIONAL +;ns.foo.com IN A 1.2.3.44 +ENTRY_END + +; Now we wait 101 seconds, and the child data is gone, +; but the parent-side was cached for 200 and it still there. + +STEP 30 TIME_PASSES ELAPSE 101 + +STEP 40 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 50 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 100 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. 100 IN NS ns.foo.com. +; scrubbed off +;SECTION ADDITIONAL +;ns.foo.com IN A 1.2.3.44 +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_prefetch.rpl b/testdata/iter_prefetch.rpl new file mode 100644 index 00000000000..678bdd79d3e --- /dev/null +++ b/testdata/iter_prefetch.rpl @@ -0,0 +1,226 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + prefetch: "yes" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test resolver prefetch of almost expired data + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 40 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 50 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ENTRY_END + +; after 1800 secs still the cached answer +STEP 20 TIME_PASSES ELAPSE 1800 + +STEP 30 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 40 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 1800 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. 1800 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 1800 IN A 1.2.3.4 +ENTRY_END + +; after 1440 we are 360 seconds before the expiry +; (the authority changes behind the scenes to detect new lookup) +STEP 50 TIME_PASSES ELAPSE 1440 + +STEP 60 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 70 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 360 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. 360 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 360 IN A 1.2.3.4 +ENTRY_END +STEP 80 TRAFFIC +; let traffic flow for prefetch to happen + +; above a cache reply with 10% of the original TTL +; but the actual cache is changed, try to get that +STEP 120 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 130 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +SECTION AUTHORITY +; NS rrset picked up from parent-NS (the child-NS timed out at now+prefetch) +example.com. 3600 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_prefetch_change.rpl b/testdata/iter_prefetch_change.rpl new file mode 100644 index 00000000000..2ed70cdadf8 --- /dev/null +++ b/testdata/iter_prefetch_change.rpl @@ -0,0 +1,364 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + prefetch: "yes" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test resolver prefetch and a moved domain +; for bug #425. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 500 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. (before sale of domain) +RANGE_BEGIN 0 30 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. 86400 IN NS old-ns.example.com. +SECTION ADDITIONAL +old-ns.example.com. 86400 IN A 192.168.0.1 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. (after sale of domain) +RANGE_BEGIN 40 500 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. 86400 IN NS new-ns.example.com. +SECTION ADDITIONAL +new-ns.example.com. 86400 IN A 172.16.0.1 +ENTRY_END +RANGE_END + +; ns.example.com. first owner +RANGE_BEGIN 0 500 + ADDRESS 192.168.0.1 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. 86400 IN NS old-ns.example.com. +SECTION ADDITIONAL +old-ns.example.com. 86400 IN A 192.168.0.1 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.1.1.1 +SECTION AUTHORITY +example.com. 86400 IN NS old-ns.example.com. +SECTION ADDITIONAL +old-ns.example.com. 86400 IN A 192.168.0.1 +ENTRY_END +RANGE_END + +; ns.example.com. new owner +RANGE_BEGIN 0 500 + ADDRESS 172.16.0.1 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. 86400 IN NS new-ns.example.com. +SECTION ADDITIONAL +new-ns.example.com. 86400 IN A 172.16.0.1 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +old-ns.example.com. IN A +SECTION ANSWER +old-ns.example.com. 86400 IN A 172.16.0.1 +SECTION AUTHORITY +example.com. 86400 IN NS new-ns.example.com. +SECTION ADDITIONAL +new-ns.example.com. 86400 IN A 172.16.0.1 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.2.2.2 +SECTION AUTHORITY +example.com. 86400 IN NS new-ns.example.com. +SECTION ADDITIONAL +new-ns.example.com. 86400 IN A 172.16.0.1 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.1.1.1 +SECTION AUTHORITY +example.com. 86400 IN NS old-ns.example.com. +SECTION ADDITIONAL +old-ns.example.com. 86400 IN A 192.168.0.1 +ENTRY_END + +; after 1800 secs still the cached answer +STEP 20 TIME_PASSES ELAPSE 1800 + +STEP 30 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 40 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 1800 IN A 10.1.1.1 +SECTION AUTHORITY +example.com. 84600 IN NS old-ns.example.com. +SECTION ADDITIONAL +old-ns.example.com. 84600 IN A 192.168.0.1 +ENTRY_END + +; after 1440 we are 360 seconds before the expiry +; but it still contacts the old-ns +STEP 50 TIME_PASSES ELAPSE 1440 + +STEP 60 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 70 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 360 IN A 10.1.1.1 +SECTION AUTHORITY +example.com. 83160 IN NS old-ns.example.com. +SECTION ADDITIONAL +old-ns.example.com. 83160 IN A 192.168.0.1 +ENTRY_END + +STEP 80 TRAFFIC +; let traffic flow for prefetch to happen + +; we updated from the old-ns. +STEP 90 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 100 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.1.1.1 +SECTION AUTHORITY +example.com. 83160 IN NS old-ns.example.com. +SECTION ADDITIONAL +old-ns.example.com. 83160 IN A 192.168.0.1 +ENTRY_END + +; the NS record is now 10% from expiry (8640 TTL left). +; and the A record has expired completely, retry. +STEP 110 TIME_PASSES ELAPSE 74520 + +; the NS record should have timed out. +; but you see the full TTL here, this is only for *this query* +; in the cache itself its 8640, not 86400. +STEP 120 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 130 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.1.1.1 +SECTION AUTHORITY +example.com. 8640 IN NS old-ns.example.com. +SECTION ADDITIONAL +old-ns.example.com. 8640 IN A 192.168.0.1 +ENTRY_END + +; get it from cache +STEP 140 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 150 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.1.1.1 +SECTION AUTHORITY +example.com. 8640 IN NS old-ns.example.com. +SECTION ADDITIONAL +old-ns.example.com. 8640 IN A 192.168.0.1 +ENTRY_END + +; the NS record times out after 8640 seconds. +STEP 160 TIME_PASSES ELAPSE 8641 + +; fetch it +STEP 170 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 180 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.2.2.2 +SECTION AUTHORITY +example.com. 86400 IN NS new-ns.example.com. +SECTION ADDITIONAL +new-ns.example.com. 86400 IN A 172.16.0.1 +ENTRY_END + +; a reply from cache +STEP 190 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 200 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.2.2.2 +SECTION AUTHORITY +example.com. 86400 IN NS new-ns.example.com. +SECTION ADDITIONAL +new-ns.example.com. 86400 IN A 172.16.0.1 +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_prefetch_change2.rpl b/testdata/iter_prefetch_change2.rpl new file mode 100644 index 00000000000..93196d555f7 --- /dev/null +++ b/testdata/iter_prefetch_change2.rpl @@ -0,0 +1,313 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + prefetch: "yes" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test resolver prefetch and a moved domain 2. +; for slightly different query pattern. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 500 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. (before sale of domain) +RANGE_BEGIN 0 30 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. 86400 IN NS old-ns.example.com. +SECTION ADDITIONAL +old-ns.example.com. 86400 IN A 192.168.0.1 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. (after sale of domain) +RANGE_BEGIN 40 500 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. 86400 IN NS new-ns.example.com. +SECTION ADDITIONAL +new-ns.example.com. 86400 IN A 172.16.0.1 +ENTRY_END +RANGE_END + +; ns.example.com. first owner +RANGE_BEGIN 0 500 + ADDRESS 192.168.0.1 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. 300 IN NS old-ns.example.com. +SECTION ADDITIONAL +old-ns.example.com. 300 IN A 192.168.0.1 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 300 IN A 10.1.1.1 +SECTION AUTHORITY +example.com. 300 IN NS old-ns.example.com. +SECTION ADDITIONAL +old-ns.example.com. 300 IN A 192.168.0.1 +ENTRY_END +RANGE_END + +; ns.example.com. new owner +RANGE_BEGIN 0 500 + ADDRESS 172.16.0.1 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. 86400 IN NS new-ns.example.com. +SECTION ADDITIONAL +new-ns.example.com. 86400 IN A 172.16.0.1 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +old-ns.example.com. IN A +SECTION ANSWER +old-ns.example.com. 86400 IN A 172.16.0.1 +SECTION AUTHORITY +example.com. 86400 IN NS new-ns.example.com. +SECTION ADDITIONAL +new-ns.example.com. 86400 IN A 172.16.0.1 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 86400 IN A 10.2.2.2 +SECTION AUTHORITY +example.com. 86400 IN NS new-ns.example.com. +SECTION ADDITIONAL +new-ns.example.com. 86400 IN A 172.16.0.1 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 300 IN A 10.1.1.1 +SECTION AUTHORITY +example.com. 300 IN NS old-ns.example.com. +SECTION ADDITIONAL +old-ns.example.com. 300 IN A 192.168.0.1 +ENTRY_END + +; after 40 secs still the cached answer +STEP 20 TIME_PASSES ELAPSE 40 + +STEP 30 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 40 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 260 IN A 10.1.1.1 +SECTION AUTHORITY +example.com. 260 IN NS old-ns.example.com. +SECTION ADDITIONAL +old-ns.example.com. 260 IN A 192.168.0.1 +ENTRY_END + +; after 230 we are 30 seconds before expiry, prefetch happens. +STEP 50 TIME_PASSES ELAPSE 230 + +STEP 60 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 70 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 30 IN A 10.1.1.1 +SECTION AUTHORITY +example.com. 30 IN NS old-ns.example.com. +SECTION ADDITIONAL +old-ns.example.com. 30 IN A 192.168.0.1 +ENTRY_END + +STEP 80 TRAFFIC +; let traffic flow for prefetch to happen + +; we updated from the old-ns. +STEP 90 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 100 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 86400 IN A 10.2.2.2 +SECTION AUTHORITY +example.com. 86400 IN NS new-ns.example.com. +SECTION ADDITIONAL +new-ns.example.com. 86400 IN A 172.16.0.1 +ENTRY_END + +; the NS record times out after 31 seconds. +STEP 160 TIME_PASSES ELAPSE 31 + +; fetch it +STEP 170 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 180 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 86369 IN A 10.2.2.2 +SECTION AUTHORITY +example.com. 86369 IN NS new-ns.example.com. +SECTION ADDITIONAL +new-ns.example.com. 86369 IN A 172.16.0.1 +ENTRY_END + +; a reply from cache +STEP 190 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 200 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 86369 IN A 10.2.2.2 +SECTION AUTHORITY +example.com. 86369 IN NS new-ns.example.com. +SECTION ADDITIONAL +new-ns.example.com. 86369 IN A 172.16.0.1 +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_prefetch_childns.rpl b/testdata/iter_prefetch_childns.rpl new file mode 100644 index 00000000000..c2b72d62a0d --- /dev/null +++ b/testdata/iter_prefetch_childns.rpl @@ -0,0 +1,227 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + prefetch: "yes" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test resolver prefetch from child nameserver +; child NS record has longer TTL than A record and is thus valid for prefetch. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 40 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 1800 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 50 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 1800 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 1800 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ENTRY_END + +; after 900 secs still the cached answer +STEP 20 TIME_PASSES ELAPSE 900 + +STEP 30 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 40 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 900 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. 2700 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 2700 IN A 1.2.3.4 +ENTRY_END + +; after 720 we are 180 seconds before the expiry +; (the authority changes behind the scenes to detect new lookup) +STEP 50 TIME_PASSES ELAPSE 720 + +STEP 60 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 70 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 180 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. 1980 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 1980 IN A 1.2.3.4 +ENTRY_END +STEP 80 TRAFFIC +; let traffic flow for prefetch to happen + +; above a cache reply with 10% of the original TTL +; but the actual cache is changed, try to get that +STEP 120 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 130 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 1800 IN A 10.20.30.40 +SECTION AUTHORITY +; The NS rrset (from the child-side NS) is not updated but keeps counting down +example.com. 1980 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 1980 IN A 1.2.3.4 +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_prefetch_ns.rpl b/testdata/iter_prefetch_ns.rpl new file mode 100644 index 00000000000..3dcda608c09 --- /dev/null +++ b/testdata/iter_prefetch_ns.rpl @@ -0,0 +1,314 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + prefetch: "yes" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test resolver prefetch of NS record for moved domain + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 200 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. (before sale of domain) +RANGE_BEGIN 0 20 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. (after sale of domain) +RANGE_BEGIN 30 200 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 8.8.8.8 +ENTRY_END +RANGE_END + +; ns.example.com. first owner +RANGE_BEGIN 0 200 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. new owner +RANGE_BEGIN 0 200 + ADDRESS 8.8.8.8 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 8.8.8.8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 88.88.88.88 +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 3600 IN A 8.8.8.8 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 5 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ENTRY_END + +STEP 10 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +example.com. IN NS +ENTRY_END +; recursion happens here. +STEP 15 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. 3600 IN NS ns.example.com. +SECTION AUTHORITY +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ENTRY_END + +; after 1800 secs still the cached answer +STEP 20 TIME_PASSES ELAPSE 1800 + +STEP 30 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 40 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 1800 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. 1800 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 1800 IN A 1.2.3.4 +ENTRY_END + +STEP 44 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +example.com. IN NS +ENTRY_END +; recursion happens here. +STEP 45 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. 1800 IN NS ns.example.com. +SECTION AUTHORITY +SECTION ADDITIONAL +ns.example.com. 1800 IN A 1.2.3.4 +ENTRY_END + +; after 1440 we are 360 seconds before the expiry +STEP 50 TIME_PASSES ELAPSE 1440 + +STEP 60 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +example.com. IN NS +ENTRY_END +; recursion happens here. +STEP 70 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. 360 IN NS ns.example.com. +SECTION AUTHORITY +SECTION ADDITIONAL +ns.example.com. 360 IN A 1.2.3.4 +ENTRY_END + +STEP 80 TRAFFIC +; let traffic flow for prefetch to happen + +; check result of that prefetch +STEP 90 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +example.com. IN NS +ENTRY_END +; recursion happens here. + +; because the prefetch+current makes old-NS expired, new delegation is picked up +STEP 91 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. 3600 IN NS ns.example.com. +SECTION AUTHORITY +SECTION ADDITIONAL +ns.example.com. 3600 IN A 8.8.8.8 +ENTRY_END + +STEP 100 TIME_PASSES ELAPSE 2360 + +STEP 120 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; recursion happens here. +STEP 130 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 88.88.88.88 +SECTION AUTHORITY +example.com. 1240 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 1240 IN A 8.8.8.8 +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_primenoglue.rpl b/testdata/iter_primenoglue.rpl new file mode 100644 index 00000000000..24de1e367f2 --- /dev/null +++ b/testdata/iter_primenoglue.rpl @@ -0,0 +1,383 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "3 2 1 0 0" # make sure it fetches for test + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test iterator with root prime answer without glue. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +; glue ommitted! +;K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. + +; sneak in some data into the cache to simulate partial data after timeouts +; scrubbed away... +example.net. NS ns.example.net. + +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +; com zone +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ENTRY_END + +; net zone +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +A.ROOT-SERVERS.NET. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +a.gtld-servers.net. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +K.ROOT-SERVERS.NET. IN A +SECTION AUTHORITY +ROOT-SERVERS.NET. IN NS A.ROOT-SERVERS.NET. +SECTION ADDITIONAL +A.ROOT-SERVERS.NET. IN A 198.41.0.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +K.ROOT-SERVERS.NET. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION AUTHORITY +example.net. NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; A.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 198.41.0.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +ROOT-SERVERS.NET. IN NS +SECTION ANSWER +ROOT-SERVERS.NET. IN NS A.ROOT-SERVERS.NET. +SECTION ADDITIONAL +A.ROOT-SERVERS.NET. IN A 198.41.0.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +A.ROOT-SERVERS.NET. IN A +SECTION ANSWER +A.ROOT-SERVERS.NET. IN A 198.41.0.4 +SECTION AUTHORITY +ROOT-SERVERS.NET. IN NS A.ROOT-SERVERS.NET. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +A.ROOT-SERVERS.NET. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +ROOT-SERVERS.NET. IN NS A.ROOT-SERVERS.NET. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +K.ROOT-SERVERS.NET. IN A +SECTION ANSWER +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +K.ROOT-SERVERS.NET. IN AAAA +SECTION ANSWER +; no ip6 address: we want to use only one address for K. to avoid having +; to duplicate the entries in this file for both addresses. +ENTRY_END +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +; example.net. zone +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION ANSWER +ns.example.net. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION ANSWER +ENTRY_END + +; example.com. zone +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +ENTRY_END + + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +ENTRY_END + +; make sure glue fetch is done. +STEP 11 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +ns.example.net. IN AAAA +ENTRY_END + +STEP 12 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +STEP 13 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +K.ROOT-SERVERS.NET. IN AAAA +ENTRY_END + +STEP 14 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +K.ROOT-SERVERS.NET. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_privaddr.rpl b/testdata/iter_privaddr.rpl new file mode 100644 index 00000000000..63fa5331bb2 --- /dev/null +++ b/testdata/iter_privaddr.rpl @@ -0,0 +1,246 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + + private-address: 10.0.0.0/8 + private-address: 172.16.0.0/12 + private-address: 192.168.0.0/16 + private-address: 169.254.0.0/16 + private-address: fd00::/8 + private-address: fe80::/10 + + private-domain: "example.net" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. + +CONFIG_END + +SCENARIO_BEGIN Test iterator scrubber with private addresses. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +; root server authoritative for example.net too. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +mail.example.net. IN A +SECTION ANSWER +mail.example.net. IN A 10.20.30.40 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 192.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +mail.example.com. IN AAAA +SECTION ANSWER +mail.example.com. IN AAAA fe80::15 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +foo.example.com. IN A +SECTION ANSWER +foo.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; public address is not scrubbed +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 2 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 192.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +; IPv4 address is scrubbed +STEP 3 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +foo.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +foo.example.com. IN A +SECTION ANSWER +; scrubbed away +;foo.example.com. IN A 10.20.30.40 +ENTRY_END + +; IPv6 address is scrubbed +STEP 20 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +mail.example.com. IN AAAA +ENTRY_END + +STEP 30 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +mail.example.com. IN AAAA +SECTION ANSWER +ENTRY_END + +; allowed domain is not scrubbed. +STEP 40 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +mail.example.net. IN A +ENTRY_END + +STEP 50 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +mail.example.net. IN A +SECTION ANSWER +mail.example.net. IN A 10.20.30.40 +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_ranoaa_lame.rpl b/testdata/iter_ranoaa_lame.rpl new file mode 100644 index 00000000000..d2db84a8e09 --- /dev/null +++ b/testdata/iter_ranoaa_lame.rpl @@ -0,0 +1,293 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test detection of RA but no AA lameness +; in this scenario mistakenly, a recursive server is deployed, instead +; of an authoritative server. It gives answers from cache. +; However, unbound is doing recursion on behalf of its client, and does +; not trust the server to do so. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN A +SECTION AUTHORITY +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +; this entry; glue will make unbound take this reference first. +; it is however, the lame server. +ns.example.com. IN A 1.2.3.55 +ENTRY_END +RANGE_END + +; e.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.12.94.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.44 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION ANSWER +ns.example.net. IN A 1.2.3.44 +SECTION AUTHORITY +example.net. IN NS ns.example.net. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +www.example.net. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +ENTRY_END + +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.55 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.55 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +ENTRY_END + +; the lame response. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +; the wrong answer. +www.example.com. IN A 10.20.30.50 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.55 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 20 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +; scrubbed off +;SECTION ADDITIONAL +;ns.example.net IN A 1.2.3.44 +ENTRY_END + +; query still pending +STEP 30 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +ns.example.net. IN AAAA +ENTRY_END + +; query still pending +STEP 40 CHECK_ANSWER +ENTRY_BEGIN +REPLY RD RA +SECTION QUESTION +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_reclame_one.rpl b/testdata/iter_reclame_one.rpl new file mode 100644 index 00000000000..e2e6b4502aa --- /dev/null +++ b/testdata/iter_reclame_one.rpl @@ -0,0 +1,165 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test iterative resolve with a recursion lame server. +; The scenario has a domain with two servers, one is lame the other doesn't +; so depending on the randomly chosen server that goes first, it may +; select the nonlame or the lame server first. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS lame.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +lame.example.com. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS lame.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +lame.example.com. IN A 1.2.3.5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS lame.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +lame.example.com. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; lame.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR RA NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS lame.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +lame.example.com. IN A 1.2.3.5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS lame.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +lame.example.com. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS lame.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +lame.example.com. IN A 1.2.3.5 +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_reclame_two.rpl b/testdata/iter_reclame_two.rpl new file mode 100644 index 00000000000..3b7dfd65cbe --- /dev/null +++ b/testdata/iter_reclame_two.rpl @@ -0,0 +1,182 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test iterative resolve with two recursion lame servers. +; both servers are recursion lame. The iterator tries both servers, +; but they are both lame. Then it concludes that it only has reclame. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS lame.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +lame.example.com. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR RA NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS lame.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +lame.example.com. IN A 1.2.3.5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR RA NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR RA NOERROR +SECTION QUESTION +lame.example.com. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS lame.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +lame.example.com. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; lame.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR RA NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS lame.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +lame.example.com. IN A 1.2.3.5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode +ADJUST copy_id copy_query +REPLY QR RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS lame.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +lame.example.com. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS lame.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +lame.example.com. IN A 1.2.3.5 +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_recurse.rpl b/testdata/iter_recurse.rpl new file mode 100644 index 00000000000..c787ac32a2e --- /dev/null +++ b/testdata/iter_recurse.rpl @@ -0,0 +1,227 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test resolution with recursion for NS target. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION AUTHORITY +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION AUTHORITY +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.net. +ENTRY_END +RANGE_END + +; e.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.12.94.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS e.gtld-servers.net. +SECTION ADDITIONAL +e.gtld-servers.net. IN A 192.12.94.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.44 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION ANSWER +ns.example.net. IN A 1.2.3.44 +SECTION AUTHORITY +example.net. IN NS ns.example.net. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +www.example.net. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.net. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net IN A 1.2.3.44 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 20 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.net. +; scrubbed off +;SECTION ADDITIONAL +;ns.example.net IN A 1.2.3.44 +ENTRY_END + +; due to ordering of answer packets, this is still outstanding, remove it +STEP 21 CHECK_OUT_QUERY +ENTRY_BEGIN +ADJUST copy_id +MATCH qname qtype +REPLY QR +SECTION QUESTION +ns.example.net IN AAAA +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_req_qname.rpl b/testdata/iter_req_qname.rpl new file mode 100644 index 00000000000..2dc2c8f2de2 --- /dev/null +++ b/testdata/iter_req_qname.rpl @@ -0,0 +1,118 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test a query name in the reply is required by resolver + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +; always the same reply since we cannot match anything from the qsection. +ENTRY_BEGIN +MATCH opcode +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +; no query section! +; www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. + +; the query name is echoed properly to *our* client +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_resolve.rpl b/testdata/iter_resolve.rpl new file mode 100644 index 00000000000..293c3fecea7 --- /dev/null +++ b/testdata/iter_resolve.rpl @@ -0,0 +1,120 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test basic iterative resolve of www.example.com. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_scrub_cname_an.rpl b/testdata/iter_scrub_cname_an.rpl new file mode 100644 index 00000000000..8f184d4015e --- /dev/null +++ b/testdata/iter_scrub_cname_an.rpl @@ -0,0 +1,181 @@ +; config options +server: + harden-referral-path: no + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test scrub of CNAME in answer section + +STEP 10 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; root prime is sent +STEP 20 CHECK_OUT_QUERY +ENTRY_BEGIN +MATCH qname qtype opcode +SECTION QUESTION +. IN NS +ENTRY_END +STEP 30 REPLY +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +; query sent to root server +STEP 40 CHECK_OUT_QUERY +ENTRY_BEGIN +MATCH qname qtype opcode +SECTION QUESTION +www.example.com. IN A +ENTRY_END +STEP 50 REPLY +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +; query sent to .com server +STEP 60 CHECK_OUT_QUERY +ENTRY_BEGIN +MATCH qname qtype opcode +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; STEP 62 CHECK_OUT_QUERY +; ENTRY_BEGIN +; MATCH qname qtype opcode +; SECTION QUESTION +; com. IN NS +; ENTRY_END +; STEP 63 REPLY +; ENTRY_BEGIN +; MATCH opcode qtype qname +; ADJUST copy_id +; REPLY QR NOERROR +; SECTION QUESTION +; com. IN NS +; SECTION ANSWER +; com. IN NS a.gtld-servers.net. +; SECTION ADDITIONAL +; a.gtld-servers.net. IN A 192.5.6.30 +; ENTRY_END + +STEP 70 REPLY +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns1.example.com. +SECTION ADDITIONAL +ns1.example.com. IN A 168.192.2.2 +ENTRY_END + +; this query reply has to be scrubbed +STEP 80 CHECK_OUT_QUERY +ENTRY_BEGIN +MATCH qname qtype opcode +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; STEP 82 CHECK_OUT_QUERY +; ENTRY_BEGIN +; MATCH qname qtype opcode +; SECTION QUESTION +; example.com. IN NS +; ENTRY_END +; STEP 83 REPLY +; ENTRY_BEGIN +; MATCH opcode qtype qname +; ADJUST copy_id +; REPLY QR NOERROR +; SECTION QUESTION +; example.com. IN NS +; SECTION ANSWER +; example.com. IN NS ns1.example.com. +; SECTION ADDITIONAL +; ns1.example.com. IN A 168.192.2.2 +; ENTRY_END + +STEP 90 REPLY +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME next.example.com. +next.example.com. IN A 10.20.30.0 +SECTION AUTHORITY +example.com. IN NS ns1.example.com. +SECTION ADDITIONAL +ns1.example.com. IN A 168.192.2.2 +ENTRY_END + +; iterator should try again and ask the other nameserver. +STEP 100 CHECK_OUT_QUERY +ENTRY_BEGIN +MATCH qname qtype opcode +SECTION QUESTION +next.example.com. IN A +ENTRY_END +STEP 110 REPLY +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +next.example.com. IN A +SECTION ANSWER +next.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns1.example.com. +SECTION ADDITIONAL +ns1.example.com. IN A 168.192.2.2 +ENTRY_END + +; is the final answer correct? +STEP 200 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME next.example.com. +next.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns1.example.com. +SECTION ADDITIONAL +ns1.example.com. IN A 168.192.2.2 +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_scrub_dname_insec.rpl b/testdata/iter_scrub_dname_insec.rpl new file mode 100644 index 00000000000..f205b0e31e4 --- /dev/null +++ b/testdata/iter_scrub_dname_insec.rpl @@ -0,0 +1,250 @@ +; config options +server: + harden-referral-path: no + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test scrub of insecure DNAME in answer section + +STEP 10 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +x.y.example.com. IN A +ENTRY_END + +; root prime is sent +STEP 20 CHECK_OUT_QUERY +ENTRY_BEGIN +MATCH qname qtype opcode +SECTION QUESTION +. IN NS +ENTRY_END +STEP 30 REPLY +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +; query sent to root server +STEP 40 CHECK_OUT_QUERY +ENTRY_BEGIN +MATCH qname qtype opcode +SECTION QUESTION +x.y.example.com. IN A +ENTRY_END +STEP 50 REPLY +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +x.y.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +; query sent to .com server +STEP 60 CHECK_OUT_QUERY +ENTRY_BEGIN +MATCH qname qtype opcode +SECTION QUESTION +x.y.example.com. IN A +ENTRY_END + +; STEP 62 CHECK_OUT_QUERY +; ENTRY_BEGIN +; MATCH qname qtype opcode +; SECTION QUESTION +; com. IN NS +; ENTRY_END +; STEP 63 REPLY +; ENTRY_BEGIN +; MATCH opcode qtype qname +; ADJUST copy_id +; REPLY QR NOERROR +; SECTION QUESTION +; com. IN NS +; SECTION ANSWER +; com. IN NS a.gtld-servers.net. +; SECTION ADDITIONAL +; a.gtld-servers.net. IN A 192.5.6.30 +; ENTRY_END + +STEP 70 REPLY +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +x.y.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns1.example.com. +SECTION ADDITIONAL +ns1.example.com. IN A 168.192.2.2 +ENTRY_END + +STEP 80 CHECK_OUT_QUERY +ENTRY_BEGIN +MATCH qname qtype opcode +SECTION QUESTION +x.y.example.com. IN A +ENTRY_END + +; STEP 82 CHECK_OUT_QUERY +; ENTRY_BEGIN +; MATCH qname qtype opcode +; SECTION QUESTION +; example.com. IN NS +; ENTRY_END +; STEP 83 REPLY +; ENTRY_BEGIN +; MATCH opcode qtype qname +; ADJUST copy_id +; REPLY QR NOERROR +; SECTION QUESTION +; example.com. IN NS +; SECTION ANSWER +; example.com. IN NS ns1.example.com. +; SECTION ADDITIONAL +; ns1.example.com. IN A 168.192.2.2 +; ENTRY_END + +STEP 90 REPLY +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +x.y.example.com. IN A +SECTION ANSWER +y.example.com. DNAME z.example.com. +x.y.example.com. IN CNAME x.z.example.com. +x.z.example.com. IN A 10.20.30.0 +SECTION AUTHORITY +example.com. IN NS ns1.example.com. +SECTION ADDITIONAL +ns1.example.com. IN A 168.192.2.2 +ENTRY_END + +STEP 100 CHECK_OUT_QUERY +ENTRY_BEGIN +MATCH qname qtype opcode +SECTION QUESTION +x.z.example.com. IN A +ENTRY_END +STEP 110 REPLY +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +x.z.example.com. IN A +SECTION ANSWER +x.z.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns1.example.com. +SECTION ADDITIONAL +ns1.example.com. IN A 168.192.2.2 +ENTRY_END + +; answer to first query (simply puts DNAME in cache) +STEP 120 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA +SECTION QUESTION +x.y.example.com. IN A +SECTION ANSWER +y.example.com. DNAME z.example.com. +x.y.example.com. IN CNAME x.z.example.com. +x.z.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns1.example.com. +SECTION ADDITIONAL +ns1.example.com. IN A 168.192.2.2 +ENTRY_END + +; now, DNAME insecure from cache should not be used. +; new query +STEP 200 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +other.y.example.com. IN A +ENTRY_END + +STEP 210 CHECK_OUT_QUERY +ENTRY_BEGIN +MATCH qname qtype opcode +SECTION QUESTION +other.y.example.com. IN A +ENTRY_END +STEP 220 REPLY +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +other.y.example.com. IN A +SECTION ANSWER +y.example.com. DNAME z.example.com. +other.y.example.com. IN CNAME other.z.example.com. +other.z.example.com. IN A 50.60.70.0 +SECTION AUTHORITY +example.com. IN NS ns1.example.com. +SECTION ADDITIONAL +ns1.example.com. IN A 168.192.2.2 +ENTRY_END + +STEP 230 CHECK_OUT_QUERY +ENTRY_BEGIN +MATCH qname qtype opcode +SECTION QUESTION +other.z.example.com. IN A +ENTRY_END +STEP 240 REPLY +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +other.z.example.com. IN A +SECTION ANSWER +other.z.example.com. IN A 50.60.70.80 +SECTION AUTHORITY +example.com. IN NS ns1.example.com. +SECTION ADDITIONAL +ns1.example.com. IN A 168.192.2.2 +ENTRY_END + +STEP 250 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA +SECTION QUESTION +other.y.example.com. IN A +SECTION ANSWER +y.example.com. DNAME z.example.com. +other.y.example.com. IN CNAME other.z.example.com. +other.z.example.com. IN A 50.60.70.80 +SECTION AUTHORITY +example.com. IN NS ns1.example.com. +SECTION ADDITIONAL +ns1.example.com. IN A 168.192.2.2 +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_scrub_dname_sec.rpl b/testdata/iter_scrub_dname_sec.rpl new file mode 100644 index 00000000000..1ce74ca1778 --- /dev/null +++ b/testdata/iter_scrub_dname_sec.rpl @@ -0,0 +1,212 @@ +; config options +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + trust-anchor: "example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test scrub of secure DNAME in answer section + +RANGE_BEGIN 0 100 +; all adresses +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +; ENTRY_BEGIN +; MATCH opcode qtype qname +; ADJUST copy_id +; REPLY QR NOERROR +; SECTION QUESTION +; x.y.example.com. IN A +; SECTION AUTHORITY +; com. IN NS a.gtld-servers.net. +; SECTION ADDITIONAL +; a.gtld-servers.net. IN A 192.5.6.30 +; ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +; ENTRY_BEGIN +; MATCH opcode qtype qname +; ADJUST copy_id +; REPLY QR NOERROR +; SECTION QUESTION +; x.y.example.com. IN A +; SECTION AUTHORITY +; example.com. IN NS ns1.example.com. +; SECTION ADDITIONAL +; ns1.example.com. IN A 168.192.2.2 +; ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +x.y.example.com. IN A +SECTION ANSWER +y.example.com. DNAME z.example.com. +y.example.com. 3600 IN RRSIG DNAME 3 3 3600 20070926134150 20070829134150 2854 example.com. ALCQdkXflwgQVKCFeYgCAx3ipuoPsGJVZjNeUriXE4nd94h50zJWDJ4= ;{id = 2854} +x.y.example.com. IN CNAME x.z.example.com. +x.z.example.com. IN A 10.20.30.0 +SECTION AUTHORITY +example.com. IN NS ns1.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. AA3IkI13XbKFU5NSqBVA9oM1WiyEKCy4DYFOAdihDf6uHps9lce3kEc= ;{id = 2854} +SECTION ADDITIONAL +ns1.example.com. IN A 168.192.2.2 +ns1.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. AKcUlwrSz2xYKnQ7b7oMblRa0rKjfUNT900bIkGjLKLWDUGc8mKZE2M= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +x.z.example.com. IN A +SECTION ANSWER +x.z.example.com. IN A 10.20.30.40 +x.z.example.com. 3600 IN RRSIG A 3 4 3600 20070926134150 20070829134150 2854 example.com. ADZ12PiZGEjVUyLLYkct/SBE2WT4D5IkMOKdcl0dzQ0XRAC5y/0bS7A= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns1.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. ADesKDqTIOswg5QC6eTIQvGu3DHsPMz1htpHLcDJwE8IpURTnMuD0Mw= ;{id = 2854} +SECTION ADDITIONAL +ns1.example.com. IN A 168.192.2.2 +ns1.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. ACYkeSRNcLVXeL+R9AM9e1GbxTwXNXpy1M5hcyuVkhkY2d5jGrkye7I= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns1.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. ACHcJehLt4Hz+rAdxMPE96o7HJAEFohFXbxrKYlG+0WLfYAvH2nxU8k= ;{id = 2854} +SECTION ADDITIONAL +ns1.example.com. IN A 168.192.2.2 +ns1.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. AInP69g8uR1n/aRg4gmGu8UoM+zZYgjOqbNN2IvOxw3bk/q+g05jKg0= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + + +RANGE_END + +STEP 10 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +x.y.example.com. IN A +ENTRY_END + +; answer to first query (simply puts DNAME in cache) +STEP 90 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD DO +SECTION QUESTION +x.y.example.com. IN A +SECTION ANSWER +y.example.com. DNAME z.example.com. +y.example.com. 3600 IN RRSIG DNAME 3 3 3600 20070926134150 20070829134150 2854 example.com. ALCQdkXflwgQVKCFeYgCAx3ipuoPsGJVZjNeUriXE4nd94h50zJWDJ4= ;{id = 2854} +x.y.example.com. IN CNAME x.z.example.com. +x.z.example.com. IN A 10.20.30.40 +x.z.example.com. 3600 IN RRSIG A 3 4 3600 20070926134150 20070829134150 2854 example.com. ADZ12PiZGEjVUyLLYkct/SBE2WT4D5IkMOKdcl0dzQ0XRAC5y/0bS7A= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns1.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. ADesKDqTIOswg5QC6eTIQvGu3DHsPMz1htpHLcDJwE8IpURTnMuD0Mw= ;{id = 2854} +SECTION ADDITIONAL +ns1.example.com. IN A 168.192.2.2 +ns1.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. ACYkeSRNcLVXeL+R9AM9e1GbxTwXNXpy1M5hcyuVkhkY2d5jGrkye7I= ;{id = 2854} +ENTRY_END + +; now, DNAME is secure and can be used from cache. +; new query +STEP 200 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +other.y.example.com. IN A +ENTRY_END + +STEP 230 CHECK_OUT_QUERY +ENTRY_BEGIN +MATCH qname qtype opcode +SECTION QUESTION +other.z.example.com. IN A +ENTRY_END +STEP 240 REPLY +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +other.z.example.com. IN A +SECTION ANSWER +other.z.example.com. IN A 50.60.70.80 +other.z.example.com. 3600 IN RRSIG A 3 4 3600 20070926134150 20070829134150 2854 example.com. AAp6G89oAvkyAaeF2d35AJNlzMhedGo0Bcppl0IOyF3HRzoc51vjJoU= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns1.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. ADesKDqTIOswg5QC6eTIQvGu3DHsPMz1htpHLcDJwE8IpURTnMuD0Mw= ;{id = 2854} +SECTION ADDITIONAL +ns1.example.com. IN A 168.192.2.2 +ns1.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. ACYkeSRNcLVXeL+R9AM9e1GbxTwXNXpy1M5hcyuVkhkY2d5jGrkye7I= ;{id = 2854} +ENTRY_END + +STEP 250 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD DO +SECTION QUESTION +other.y.example.com. IN A +SECTION ANSWER +y.example.com. DNAME z.example.com. +y.example.com. 3600 IN RRSIG DNAME 3 3 3600 20070926134150 20070829134150 2854 example.com. ALCQdkXflwgQVKCFeYgCAx3ipuoPsGJVZjNeUriXE4nd94h50zJWDJ4= ;{id = 2854} +other.y.example.com. IN CNAME other.z.example.com. +other.z.example.com. IN A 50.60.70.80 +other.z.example.com. 3600 IN RRSIG A 3 4 3600 20070926134150 20070829134150 2854 example.com. AAp6G89oAvkyAaeF2d35AJNlzMhedGo0Bcppl0IOyF3HRzoc51vjJoU= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns1.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. ADesKDqTIOswg5QC6eTIQvGu3DHsPMz1htpHLcDJwE8IpURTnMuD0Mw= ;{id = 2854} +SECTION ADDITIONAL +ns1.example.com. IN A 168.192.2.2 +ns1.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. ACYkeSRNcLVXeL+R9AM9e1GbxTwXNXpy1M5hcyuVkhkY2d5jGrkye7I= ;{id = 2854} +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_scrub_ns.rpl b/testdata/iter_scrub_ns.rpl new file mode 100644 index 00000000000..365f0b54ec3 --- /dev/null +++ b/testdata/iter_scrub_ns.rpl @@ -0,0 +1,103 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. + +stub-zone: + name: "example.com" + stub-addr: 1.2.3.4 +CONFIG_END + +SCENARIO_BEGIN Test scrubber to scrub NS record for lamelike reply from stub + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +; must be scrubbed +www.burritolovers.com. IN A 10.20.30.40 +SECTION AUTHORITY +example1234.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +mail.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +; LAME +com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +STEP 20 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +mail.example.com. IN A +ENTRY_END + +STEP 30 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +mail.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_scrub_ns_fwd.rpl b/testdata/iter_scrub_ns_fwd.rpl new file mode 100644 index 00000000000..239dc37f975 --- /dev/null +++ b/testdata/iter_scrub_ns_fwd.rpl @@ -0,0 +1,103 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. + +forward-zone: + name: "example.com" + forward-addr: 1.2.3.4 +CONFIG_END + +SCENARIO_BEGIN Test scrubber to scrub NS record for lamelike reply from fwd + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY RD RA QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +; must be scrubbed +www.burritolovers.com. IN A 10.20.30.40 +SECTION AUTHORITY +example1234.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY RD RA QR NOERROR +SECTION QUESTION +mail.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +; LAME +com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +STEP 20 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +mail.example.com. IN A +ENTRY_END + +STEP 30 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +mail.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_scrub_ns_side.rpl b/testdata/iter_scrub_ns_side.rpl new file mode 100644 index 00000000000..98d00fd9250 --- /dev/null +++ b/testdata/iter_scrub_ns_side.rpl @@ -0,0 +1,103 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. + +stub-zone: + name: "example.com" + stub-addr: 1.2.3.4 +CONFIG_END + +SCENARIO_BEGIN Test scrubber to scrub NS record to the side of the query + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +; must be scrubbed +www.burritolovers.com. IN A 10.20.30.40 +SECTION AUTHORITY +example1234.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +mail.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +; not pertinent to the query +www.example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +STEP 20 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +mail.example.com. IN A +ENTRY_END + +STEP 30 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +mail.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_soamin.rpl b/testdata/iter_soamin.rpl new file mode 100644 index 00000000000..42eb80827d6 --- /dev/null +++ b/testdata/iter_soamin.rpl @@ -0,0 +1,208 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test cache of SOA with minimum ttl and normal ttl. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.com. IN SOA +SECTION ANSWER +example.com. 86400 IN SOA dns1.icann.org. hostmaster.icann.org. 2010074630 7200 3600 1209600 3600 +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NXDOMAIN +SECTION QUESTION +nx.example.com. IN A +SECTION AUTHORITY +example.com. 3600 IN SOA dns1.icann.org. hostmaster.icann.org. 2010074630 7200 3600 1209600 3600 +ENTRY_END + +RANGE_END + +; put both queries with SOA records into the cache and then query them from +; the cache. +; first the nxdomain, so that the positive SOA answer later overrides the +; SOA from the authority section from that nxdomain. + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +nx.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NXDOMAIN +SECTION QUESTION +nx.example.com. IN A +SECTION AUTHORITY +example.com. 3600 IN SOA dns1.icann.org. hostmaster.icann.org. 2010074630 7200 3600 1209600 3600 +ENTRY_END + +STEP 20 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +example.com. IN SOA +ENTRY_END + +; recursion happens here. +STEP 30 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +example.com. IN SOA +SECTION ANSWER +example.com. 86400 IN SOA dns1.icann.org. hostmaster.icann.org. 2010074630 7200 3600 1209600 3600 +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ENTRY_END + +; now check them from the cache (no seconds elapsed). + +STEP 110 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +nx.example.com. IN A +ENTRY_END + +STEP 120 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NXDOMAIN +SECTION QUESTION +nx.example.com. IN A +SECTION AUTHORITY +example.com. 3600 IN SOA dns1.icann.org. hostmaster.icann.org. 2010074630 7200 3600 1209600 3600 +ENTRY_END + +STEP 130 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +example.com. IN SOA +ENTRY_END + +STEP 140 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +example.com. IN SOA +SECTION ANSWER +example.com. 86400 IN SOA dns1.icann.org. hostmaster.icann.org. 2010074630 7200 3600 1209600 3600 +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 3600 IN A 1.2.3.4 +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_stub_noroot.rpl b/testdata/iter_stub_noroot.rpl new file mode 100644 index 00000000000..0bc1ff5d203 --- /dev/null +++ b/testdata/iter_stub_noroot.rpl @@ -0,0 +1,64 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 81.187.81.187 +stub-zone: + name: "lp0.eu" + stub-addr: 81.2.80.65 + stub-prime: no +CONFIG_END + +SCENARIO_BEGIN Test resolve of stub zone without root prime. + +; this server does not respond. (for the root) +RANGE_BEGIN 0 100 + ADDRESS 81.187.81.187 +ENTRY_BEGIN +MATCH +ADJUST copy_id copy_query +REPLY QR SERVFAIL +SECTION QUESTION +. IN NS +ENTRY_END +RANGE_END + +; lp0.eu server +RANGE_BEGIN 0 100 + ADDRESS 81.2.80.65 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +proxima.lp0.eu. IN A +SECTION ANSWER +proxima.lp0.eu. IN A 81.2.80.65 +SECTION AUTHORITY +lp0.eu. IN NS proxima.lp0.eu. +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +proxima.lp0.eu. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +proxima.lp0.eu. IN A +SECTION ANSWER +proxima.lp0.eu. IN A 81.2.80.65 +SECTION AUTHORITY +lp0.eu. IN NS proxima.lp0.eu. +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_stubfirst.rpl b/testdata/iter_stubfirst.rpl new file mode 100644 index 00000000000..6245a4f09a1 --- /dev/null +++ b/testdata/iter_stubfirst.rpl @@ -0,0 +1,157 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. + +stub-zone: + name: "example.com" + stub-addr: 1.2.3.6 # failing server + stub-first: yes + +CONFIG_END + +SCENARIO_BEGIN Test stub-first directive + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; local authority (that fails a lot) +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA SERVFAIL +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +;example.com. IN NS ns.example.com. +SECTION ADDITIONAL +;ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA SERVFAIL +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +;www.example.com. IN A 10.20.30.50 +SECTION AUTHORITY +;example.com. IN NS ns.example.com. +SECTION ADDITIONAL +;ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +SCENARIO_END diff --git a/testdata/iter_timeout_ra_aaaa.rpl b/testdata/iter_timeout_ra_aaaa.rpl new file mode 100644 index 00000000000..2815d4c5a23 --- /dev/null +++ b/testdata/iter_timeout_ra_aaaa.rpl @@ -0,0 +1,244 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test iterator with timeouts on reclame AAAA dropping server + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION ANSWER +ns.example.net. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +. IN SOA a. b. 1 2 3 4 5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +a.gtld-servers.net. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +. IN SOA a. b. 1 2 3 4 5 +ENTRY_END + +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. 280 IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +; This server is REC_LAME +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR RA NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. 280 IN NS ns.example.net. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 10 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. 280 IN NS ns.example.net. +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.net. +ENTRY_END + +; query for (dropped) AAAA record. +STEP 20 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN AAAA +ENTRY_END + +; the AAAA query times out. +STEP 21 TIMEOUT +STEP 22 TIMEOUT +STEP 23 TIMEOUT +STEP 24 TIMEOUT +STEP 25 TIMEOUT + +; we get servfail, but the AAA arrives again (after the servfail times +; out of the cache) +STEP 30 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN AAAA +ENTRY_END +STEP 31 TIME_PASSES ELAPSE 6 +STEP 40 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN AAAA +ENTRY_END + +; timeouts for AAAA keep happening. +STEP 41 TIMEOUT +STEP 42 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN AAAA +ENTRY_END +STEP 43 TIME_PASSES ELAPSE 12 + +STEP 50 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN AAAA +ENTRY_END +; fallback queries +STEP 51 TRAFFIC +; and it fails, no parentside entries and so on. +STEP 52 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN AAAA +ENTRY_END +STEP 53 TIME_PASSES ELAPSE 12 + +STEP 60 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN AAAA +ENTRY_END +STEP 61 TIMEOUT +STEP 62 TRAFFIC +STEP 63 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN AAAA +ENTRY_END + +STEP 70 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +STEP 72 TRAFFIC +STEP 73 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.net. +ENTRY_END + +SCENARIO_END diff --git a/testdata/local_nodefault.rpl b/testdata/local_nodefault.rpl new file mode 100644 index 00000000000..208b68327ed --- /dev/null +++ b/testdata/local_nodefault.rpl @@ -0,0 +1,60 @@ +; config options +; The island of trust is at example.com +server: + local-zone: "10.in-addr.arpa" nodefault + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test local data with nodefault for as112 zone. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NXDOMAIN +SECTION QUESTION +40.30.20.10.in-addr-arpa. IN PTR +SECTION ANSWER +SECTION AUTHORITY +. IN SOA invalid. invalid. 1 2 3 4 5 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +40.30.20.10.in-addr-arpa. IN PTR +ENTRY_END +; not blocked! + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NXDOMAIN +SECTION QUESTION +40.30.20.10.in-addr-arpa. IN PTR +SECTION ANSWER +SECTION AUTHORITY +. IN SOA invalid. invalid. 1 2 3 4 5 +ENTRY_END + +SCENARIO_END diff --git a/testdata/local_nodefault.tpkg b/testdata/local_nodefault.tpkg new file mode 100644 index 0000000000000000000000000000000000000000..f23f50dd158935f2f617cc37008f282569b86edd GIT binary patch literal 1569 zcmV++2HyD}iwFQu2USe~1MOJULJqb)8F-_K_^t$ja!Pb-B7d`1cedK_<6UpMwjbpJ` zhePY7AY=Wn@**zeU2LcYu1wcEbNx#dd%pgqecUJbwCpXg?rV~tqX)kJ+pujIkhS7q z7~5nU1W#g@fgCXyQ-L9ZbBx!(4;WmGSO~t{6{*@|Rn`vx0x1$yw3`lT+SX5ev{U?(c3vBxh$(27juiOa`h9-3lA&io+gMZO1x z7w;Rr>kc`@*5A5BJ72tOSD*CKE=*N05@Vj6mU+>3ZD!6EYuZ+E)S3Z2;- z(WOAM9zB|K;YY9^KPJo_amX(VF1GS;aB$U;sm!I;^etk9f=DpTo@?jci@Gh zrv`+A6y7viC%ta-q}w_HBZ9fUYwI}`fP=w>X9j!-&cTiiJ7iYso)vyrbWJg4FDo1y z(=!Gx4+s8G?*$^52L^*(v3IEK|8cmtyA+Jwz1_6G+n$d|-BrCmU-Mb%hXY9Z`fVPL zB<%Af^z`PyUD>DZ*)Ucda@=V?%c~7$=1Bn?d+AUE|J+m&9L(5@fmo>Um%&(KE;KTO z;!=5)cR~H7_39-N%obqUH*-Ys7kpap5p$dR?+N!#Hg3XyWv7Vs-*RlH=vY(yXO%bj zZ!Pqk3f7`yR=t{kzLJj4TnL(HOpx{5v1 zFx9C0i55ZO1`1Z8n=p8lgaAdbOI7Ph)v}-gnw{$3~=LV5S1EJPy%s);)%Ql z7Ab7gjYX(17a1}43}`4WSez&R0ESqNA)n4DpW1k;Rw^X9sa*TD4l;#4I)8=`u0NUA zZdJAOgav}7qgz};`*j|hpL_{68TeU|9Qx;KMlq<1wnrres<($e9wyfVYJG7)GbF!y zKyAx(wCR%d`IydA>1zdY8+WP1Fb)Qod7%Uuv=YB)4U#;)!)V@Eu&H1nP&|PfY^!>*wIqCUd+~2S0^S@Z!od4?}oYgr3ZIZ*^ zJ{P`3Q05_wtzyEF9Bv!tN)5^Lm|l_Z zsr2 z1n7zI)#4eIY*CubzP(I`libW*ER(3$56@}fd!Qtl5b6rl$Lft&0K`NvK#Ky+r5e;I z6t$gwETEQIKAe3BIn1vxk}au2fD|HXGFg_5v?foyjL+!ii`%lF#U*7*p z`uk*nnvu=vc4W~=daJ<3GBE8Sc*ddYWZ(f4n?88)<` T4Q*&c4~G5)f?^Nl04M+ec99$z literal 0 HcmV?d00001 diff --git a/testdata/local_norec.tpkg b/testdata/local_norec.tpkg new file mode 100644 index 0000000000000000000000000000000000000000..c2ceb22ea24e894545dbb31343e15cb237877f6c GIT binary patch literal 1501 zcmV<31tR(%iwFRf2USe~1ML}MciJ{EU(v6)k-VgReKxki(C4naP@rqJ6jC7T>)ZBt zjxE58v0TfPvbP_D z;#xfxSfHyKX;AJ&UKmTnrJzz=JGQ|NT(BL7at;m);)wZR`#ziYdB9i*G3BvJ>JhcY z%!VDKjMprHE)4;6&`Xw4wlodu&2A42O?ygS+g=dkFO4j4BNg7Nb+v|H-k-tHwj-C5 zI&vAZXl4PavvJ4*8pIZ4qq#x_Uezz4L{03!jWBN~7gpK&pY@$?%g15nk18i%(-70J|O z#vgEcnlid$9HpRLVTl&;1_Ks>7sv!6M0)lOiVQLGykMA!TAi>WWo3vERmgSNc+3Ko zkI0b5{RlG`8}~yN#bA)@){FLatI@w|cY4oHI!TMXe4C;kJz8Ml3Fwa>6Y7i@?obkfBkp264 z;cUeaXN9wLyw_e(q^gS1A6N7hyrBw{8`)ZzVG`W137$4$Q{ZmAv7OstBrxQv(|n#6 z8%xcT6YLaHQU!mUlo3=Dbk+z9J+p>bL1sF48pN^Vb==hUR{YeTgpe42K9(pV@EM)R zS35`U&Hs2N?n1`4`mbb`mi50@5&7RVjYIz52i%eW(d)3!6CficP5Jl9`0Ug#R^T$2 z;UF@`G|Hv{NJeXC!ma1~{m^qEO@A3oCI@`;wccHDU;GOz?n1_v_&3b*^8QyYCh>o$ z|Mmi#@h`*bd#V7lHG<3tX{M1GVmh6w^rJlveTuch7(5R42fW=$k?{!2jNu5-E)#hp zR&mCFvF$VbH zylbm=hu|Qt)&q)rgq3{{U$gv<`B!^pvIu$R;Ymnt z{vxd;FVYrhs{9nR?Bnz%nQl}P!l(BWTGm!xmZfha7$8`w%vEZVJo+eqv4Emu5*uOh zl1oQy*NqUhn17zUuAJw;_#t6i{U7XL&u{(zPce;uvr;LE`oE$Z#Y6n>1D=7{U-K+5 zueaq1deZJ({B+TRY@CskUhfi$WlbZb+3I!P^aT!>4s$8Ik7ptN6--H| zd3E^?-gKZ=gI2rQ>9jkf*7*6l+XIJ%v%cq&ZnNIIXt&_ab+aoP1S`7SMJrcZjMQ4) zx6RH1pUYHWi5AUP;{g@IY;&hVDSoMtxuVe5cI*KTaDW3G-~b0Wz$f4zK+CG&04M+e DcSP*i literal 0 HcmV?d00001 diff --git a/testdata/local_nosnoop.tpkg b/testdata/local_nosnoop.tpkg new file mode 100644 index 0000000000000000000000000000000000000000..3bb16c265578a7c905adec6139cb5d65378872e8 GIT binary patch literal 1605 zcmV-L2Dis4 z4p1y~icW;k>5uQ;3GudZY6mwdYa4XCcejtbUG1(tW?Np@XWVBjP#rhS9XvQ_2xY?% z-+I~5~ z4YhTdZ-TCBq(-?Nx5{zXnkKETl~ME88iRa^-@XrzmYHQ{eKs5 z2#1QY;iiM49FjxeY!uoQq5*}W#nC|U39Z#b7l84A`rt-cE~w~Czk|{PRn4hUaNSpN znmS$aCmbCm8*QK?7ql(R(UN_Sh2Z)!eh8MXb%iVgbUD}WPgyN5SmLroBIKe~f0-7n z)iiQ*nAAs-gpT9!Sf!t>Vc=2KW8_9VXlP54ly5Knz%jahxkrN z>zbO^)PklKwRFPfg|LfHQt{H}uW3R(PLpv1H5a%P{p?1dlb%bqC@#&nru)>Yk8grj z{q(Y3uidCVgf?^NCL<)2MN@o%Wmhe^$Uxv%ExY0dcf3+-tG@b`QsvJBU8i-WzwA1F zi|UIxfW; zgCtNP2JtrLMl6cw2!r~v@)RS7DVV}2A4fEtD6=RUZ%$J4TncBeMbHW)F^-T_T#qW# zdej6>l|MNxE=|`b==t(=%JZA1nC30(O;f*_)I%^64#_-%ncEmkS>-RRUD5PYD`0Y( zN+_1&VEvn(tvosDG^OcL#RonAyVQUFJ@5V2{!c-l_kW7UftJVl#@_#T0WUz@zBmfR z)s{>{GR@Z6&u0x-^fQv_bk3nr(lkQqjZW)*_f;L|kT;c1^);|SRQfai` z)mt-sY9WoCN>OjrzM?=FZ8i#&;O7DvO9DOi!QK(J`M+p~-IvEU|1TP)dH=tdkNZFS z_y0~{Q~xJmJMRB1a7h|IxAC}hPGjeU?CsX`JAYD4C$d_b;U&+B4} z0-4iySf`!U7BI8w4Y7}XS`QCf{XeAl=CQ^9^^!jK|591z|Aj(+@Bh1ijs73f@2UH{ z;_H1HbwkT{*sv>V8mx8}`!g>yt?3hyp+KUZJegtP8R$=+PJ1rP3l~ReI6ht#BwjP$ zHF?@JR~R4frL=@72+&YMZqM;~H%`e(=DgNucRQG-G}^Mwlmo9}ZtPWngr<0Bo8 z$TZNs%>1w@m_SS)ZV+o|T~qPjzMklXiByqO2NVifo|DDlA1Ar&k}0yeY(kG~7&#*m zR#1O}^_~M9!{|yr%}g;ZCFRAy8+m2f*Zojnmiqe{9OROz3jW&3MsU2)HA~E}5Z&jd zSVArgHkw4V<5qBE%UwFF?kGswcQI`$h`=v)^1j3O%O3Wyhdu1!zX|^UU^{PV04M+e DWl$s- literal 0 HcmV?d00001 diff --git a/testdata/local_transparent_sametype.rpl b/testdata/local_transparent_sametype.rpl new file mode 100644 index 00000000000..6f0880b5d55 --- /dev/null +++ b/testdata/local_transparent_sametype.rpl @@ -0,0 +1,78 @@ +; config options +; The island of trust is at example.com +server: + local-zone: "example.com." transparent + local-data: "mail.example.com. IN A 10.20.30.40" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test local data with transparent zone queried for types + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NXDOMAIN +SECTION QUESTION +mail.example.com. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +. IN SOA invalid. invalid. 1 2 3 4 5 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +mail.example.com. IN A +ENTRY_END +; get straight answer from localdata + +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR AA RD RA NOERROR +SECTION QUESTION +mail.example.com. IN A +SECTION ANSWER +mail.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +ENTRY_END + +STEP 20 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +mail.example.com. IN AAAA +ENTRY_END +; must be NOERROR/NODATA because of A record, not NXDOMAIN from internet. + +STEP 30 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR AA RD RA NOERROR +SECTION QUESTION +mail.example.com. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +ENTRY_END + +SCENARIO_END diff --git a/testdata/local_typetransparent.rpl b/testdata/local_typetransparent.rpl new file mode 100644 index 00000000000..c1c1931aa1f --- /dev/null +++ b/testdata/local_typetransparent.rpl @@ -0,0 +1,109 @@ +; config options +; The island of trust is at example.com +server: + local-zone: "example.com." typetransparent + local-data: "mail.example.com. IN A 10.20.30.40" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test local data with typetransparent zone + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +mail.example.com. IN MX +SECTION ANSWER +mail.example.com. IN MX 100 mail.example.com. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN AAAA +SECTION ANSWER +www.example.com. IN AAAA 2001::1 +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +mail.example.com. IN A +ENTRY_END +; get straight answer from localdata + +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR AA RD RA NOERROR +SECTION QUESTION +mail.example.com. IN A +SECTION ANSWER +mail.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +ENTRY_END + +STEP 20 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +mail.example.com. IN MX +ENTRY_END + +; get internet answer for other type. + +STEP 30 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +mail.example.com. IN MX +SECTION ANSWER +mail.example.com. IN MX 100 mail.example.com. +ENTRY_END + +STEP 40 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN AAAA +ENTRY_END + +; get internet answer for other name. + +STEP 50 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN AAAA +SECTION ANSWER +www.example.com. IN AAAA 2001::1 +ENTRY_END + + +SCENARIO_END diff --git a/testdata/localdata.rpl b/testdata/localdata.rpl new file mode 100644 index 00000000000..08aec6d7dd1 --- /dev/null +++ b/testdata/localdata.rpl @@ -0,0 +1,357 @@ +; config options +server: + hide-identity: no + hide-version: no + identity: "test-identity" + version: "test-version" + + ; implicit transparent zone should not block id.server + local-data: "mydata.server. CH A 10.11.12.13" + local-data: "myd2.server. CH A 10.11.12.14" + local-data: 'myd3.server. CH TXT "a text record"' + ; together implicit CH top domain .server is created transparent. + + ; static zone + local-zone: "local" static + local-data: "local SOA nobody nobody 1 2 3 4 5" + local-data: "serv.local. A 20.30.40.50" + ; multiple RRs in this RRset. + local-data: "bla.bla.local. A 20.30.40.51" + local-data: "bla.bla.local. A 20.30.40.52" + local-data: "bla.bla.local. A 20.30.40.53" + + ; static zone (no soa) + local-zone: "noso.local" static + local-data: "bla.bla.noso.local AAAA 2001::2" + + ; deny zone (no answer) + local-zone: "deny.top." deny + + ; refuse zone (error) + local-zone: "refuse.top." refuse + + ; redirect zone + local-zone: "redirect.top." redirect + local-data: "redirect.top. A 20.30.40.54" + + ; create implicit data in the IN domain as well + local-data: "a.a.implicit. A 20.30.41.50" + local-data: "b.a.implicit. A 20.30.42.50" + local-data: "b.b.implicit. A 20.30.43.50" + local-data: "b.c.implicit. A 20.30.45.50" + local-data: "c.c.implicit. A 20.30.44.50" + +CONFIG_END +SCENARIO_BEGIN Test local data queries + +; id.server. +STEP 1 QUERY +ENTRY_BEGIN +SECTION QUESTION +id.server. CH TXT +ENTRY_END +STEP 2 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RA +SECTION QUESTION +id.server. CH TXT +SECTION ANSWER +id.server. 0 CH TXT "test-identity" +ENTRY_END + +; mydata.server. +STEP 3 QUERY +ENTRY_BEGIN +SECTION QUESTION +mydata.server. CH A +ENTRY_END +STEP 4 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RA AA +SECTION QUESTION +mydata.server. CH A +SECTION ANSWER +mydata.server. 3600 CH A 10.11.12.13 +ENTRY_END + +; nodata with SOA +STEP 5 QUERY +ENTRY_BEGIN +SECTION QUESTION +local. IN A +ENTRY_END +STEP 6 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RA AA +SECTION QUESTION +local. IN A +SECTION AUTHORITY +local. 3600 IN SOA nobody nobody 1 2 3 4 5 +ENTRY_END + +; positive SOA +STEP 7 QUERY +ENTRY_BEGIN +SECTION QUESTION +local. IN SOA +ENTRY_END +STEP 8 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RA AA +SECTION QUESTION +local. IN SOA +SECTION ANSWER +local. 3600 IN SOA nobody nobody 1 2 3 4 5 +ENTRY_END + +; positive subdomain +STEP 9 QUERY +ENTRY_BEGIN +SECTION QUESTION +serv.local. IN A +ENTRY_END +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RA AA +SECTION QUESTION +serv.local. IN A +SECTION ANSWER +serv.local. IN A 20.30.40.50 +ENTRY_END + +; no such type +STEP 11 QUERY +ENTRY_BEGIN +SECTION QUESTION +serv.local. IN MX +ENTRY_END +STEP 12 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RA AA +SECTION QUESTION +serv.local. IN MX +SECTION AUTHORITY +local. 3600 IN SOA nobody nobody 1 2 3 4 5 +ENTRY_END + +; no such type, empty nonterminal +STEP 13 QUERY +ENTRY_BEGIN +SECTION QUESTION +bla.local. IN MX +ENTRY_END +STEP 14 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RA AA +SECTION QUESTION +bla.local. IN MX +SECTION AUTHORITY +local. 3600 IN SOA nobody nobody 1 2 3 4 5 +ENTRY_END + +; nxdomain with SOA +STEP 15 QUERY +ENTRY_BEGIN +SECTION QUESTION +doing.local. IN MX +ENTRY_END +STEP 16 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RA AA NXDOMAIN +SECTION QUESTION +doing.local. IN MX +SECTION AUTHORITY +local. 3600 IN SOA nobody nobody 1 2 3 4 5 +ENTRY_END + +; nxdomain without SOA +STEP 17 QUERY +ENTRY_BEGIN +SECTION QUESTION +doing.noso.local. IN MX +ENTRY_END +STEP 18 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RA AA NXDOMAIN +SECTION QUESTION +doing.noso.local. IN MX +ENTRY_END + +; positive multiple RR +STEP 19 QUERY +ENTRY_BEGIN +SECTION QUESTION +bla.bla.local. IN A +ENTRY_END +STEP 20 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RA AA +SECTION QUESTION +bla.bla.local. IN A +SECTION ANSWER +bla.bla.local. IN A 20.30.40.51 +bla.bla.local. IN A 20.30.40.52 +bla.bla.local. IN A 20.30.40.53 +ENTRY_END + +; second implicit transparent zone. +STEP 21 QUERY +ENTRY_BEGIN +SECTION QUESTION +b.b.implicit. IN A +ENTRY_END +STEP 22 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RA AA +SECTION QUESTION +b.b.implicit. IN A +SECTION ANSWER +b.b.implicit. 3600 IN A 20.30.43.50 +ENTRY_END + +; localhost A default +STEP 30 QUERY +ENTRY_BEGIN +SECTION QUESTION +localhost. IN A +ENTRY_END +STEP 31 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RA AA +SECTION QUESTION +localhost. IN A +SECTION ANSWER +localhost. 10800 IN A 127.0.0.1 +ENTRY_END + +; localhost AAAA default +STEP 32 QUERY +ENTRY_BEGIN +SECTION QUESTION +localhost. IN AAAA +ENTRY_END +STEP 33 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RA AA +SECTION QUESTION +localhost. IN AAAA +SECTION ANSWER +localhost. 10800 IN AAAA ::1 +ENTRY_END + +; localhost A reverse default +STEP 34 QUERY +ENTRY_BEGIN +SECTION QUESTION +1.0.0.127.in-addr.arpa. IN PTR +ENTRY_END +STEP 35 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RA AA +SECTION QUESTION +1.0.0.127.in-addr.arpa. IN PTR +SECTION ANSWER +1.0.0.127.in-addr.arpa. 10800 IN PTR localhost. +ENTRY_END + +; localhost AAAA reverse default +STEP 36 QUERY +ENTRY_BEGIN +SECTION QUESTION +1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. IN PTR +ENTRY_END +STEP 37 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RA AA +SECTION QUESTION +1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. IN PTR +SECTION ANSWER +1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN PTR localhost. +ENTRY_END + +; blocked AS112 reverse default +STEP 38 QUERY +ENTRY_BEGIN +SECTION QUESTION +1.0.0.10.in-addr.arpa. IN PTR +ENTRY_END +STEP 39 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RA AA NXDOMAIN +SECTION QUESTION +1.0.0.10.in-addr.arpa. IN PTR +SECTION AUTHORITY +10.in-addr.arpa. 10800 IN SOA localhost. nobody.invalid. 1 3600 1200 604800 10800 +ENTRY_END + +; refuse zone +STEP 40 QUERY +ENTRY_BEGIN +SECTION QUESTION +www.refuse.top. IN A +ENTRY_END +STEP 41 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RA AA REFUSED +SECTION QUESTION +www.refuse.top. IN A +ENTRY_END + +; deny zone +STEP 42 QUERY +ENTRY_BEGIN +SECTION QUESTION +www.deny.top. IN A +ENTRY_END +; no answer is checked at exit of testbound. + +; redirect zone apex +STEP 50 QUERY +ENTRY_BEGIN +SECTION QUESTION +redirect.top. IN A +ENTRY_END +STEP 51 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RA AA NOERROR +SECTION QUESTION +redirect.top. IN A +SECTION ANSWER +redirect.top. IN A 20.30.40.54 +ENTRY_END + +; redirect zone +STEP 52 QUERY +ENTRY_BEGIN +SECTION QUESTION +www.redirect.top. IN A +ENTRY_END +STEP 53 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RA AA NOERROR +SECTION QUESTION +www.redirect.top. IN A +SECTION ANSWER +www.redirect.top. IN A 20.30.40.54 +ENTRY_END + +SCENARIO_END diff --git a/testdata/net_signed_servfail.rpl b/testdata/net_signed_servfail.rpl new file mode 100644 index 00000000000..5dfe9b9a9d0 --- /dev/null +++ b/testdata/net_signed_servfail.rpl @@ -0,0 +1,1374 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: ". IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk)}" + val-override-date: "20110207110823" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with DS introduction for .net +; the report for a bug in BIND is on +; http://www.verisignlabs.com/documents/BIND-DS-Servfail.pdf. +; they saw a pattern of servfail/nonservfail every 1 minute (1 day really) +; after introduction of a .NET DS in the root for a running validator. + +; K.ROOT-SERVERS.NET. (before .net DS introduction) +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. 360 IN NS K.ROOT-SERVERS.NET. +. 360 IN RRSIG NS 5 0 360 20110214110823 20110205110823 55582 . vk0d/Bpr1NJFXh4eIG+JrTcBmeo7fxB5cHSBzfQLsuahzMd2x0VuBTvWjl1ziGrNEL/jEl64E41+s3nInUoXmg== ;{id = 55582} +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. 360 IN A 193.0.14.129 +k.root-servers.net. 360 IN RRSIG A 5 3 360 20110214110823 20110205110823 55582 . L/ldGIu3qvN9LxHWkT4nkgu/7wM4zCmQDvCeGvR5lnOAyesKQsO44XhrVFTZ7eZHHffCoXF0bNA47wkTLiio2w== ;{id = 55582} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +. IN DNSKEY +SECTION ANSWER +. 60 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +. 60 IN RRSIG DNSKEY 5 0 60 20110214110823 20110205110823 55582 . WbDYJXdisfjhZ1gZ2U/VO2Hn9P2bPcQ6OEAhip6e5vtbtVFVYV6WhHuwcqE89VZGlrcTyQDHGVj+Yx17bmvX5g== ;{id = 55582} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION AUTHORITY +net. 120 IN NS a.gtld-servers.net. +net. 60 IN NSEC nl. NS RRSIG NSEC +net. 60 IN RRSIG NSEC 5 1 60 20110214110823 20110205110823 55582 . OAo8N6bM0SqXZiUT7q/j4LlT2UDpn8ia2NcKwm1KCpve+FUFNWHY670aJ5tx8PCYXk+FFfunPVMtQBRJMAUgtg== ;{id = 55582} +SECTION ADDITIONAL +a.gtld-servers.net. 120 IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; K.ROOT-SERVERS.NET. (after .net DS introduction) +RANGE_BEGIN 100 1000 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. 360 IN NS K.ROOT-SERVERS.NET. +. 360 IN RRSIG NS 5 0 360 20110214110823 20110205110823 55582 . vk0d/Bpr1NJFXh4eIG+JrTcBmeo7fxB5cHSBzfQLsuahzMd2x0VuBTvWjl1ziGrNEL/jEl64E41+s3nInUoXmg== ;{id = 55582} +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. 360 IN A 193.0.14.129 +k.root-servers.net. 360 IN RRSIG A 5 3 360 20110214110823 20110205110823 55582 . L/ldGIu3qvN9LxHWkT4nkgu/7wM4zCmQDvCeGvR5lnOAyesKQsO44XhrVFTZ7eZHHffCoXF0bNA47wkTLiio2w== ;{id = 55582} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +. IN DNSKEY +SECTION ANSWER +. 60 IN DNSKEY 257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} +. 60 IN RRSIG DNSKEY 5 0 60 20110214110823 20110205110823 55582 . WbDYJXdisfjhZ1gZ2U/VO2Hn9P2bPcQ6OEAhip6e5vtbtVFVYV6WhHuwcqE89VZGlrcTyQDHGVj+Yx17bmvX5g== ;{id = 55582} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +net. IN DS +SECTION ANSWER +net. 60 IN DS 30899 5 1 cd056cca0e95e76acb7c0934d63082570078c5e8 +net. 60 IN RRSIG DS 5 1 60 20110214110823 20110205110823 55582 . LFpCyJVQZFIqVEsI8CxV1GAhyvb1KTwanKEYTfw8ySsUuPL1M/YOuYehCw6JR7PFubLUem8OwO0Wu64/o3mP4Q== ;{id = 55582} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION AUTHORITY +net. 120 IN NS a.gtld-servers.net. +net. 60 IN DS 30899 5 1 cd056cca0e95e76acb7c0934d63082570078c5e8 +net. 60 IN RRSIG DS 5 1 60 20110214110823 20110205110823 55582 . LFpCyJVQZFIqVEsI8CxV1GAhyvb1KTwanKEYTfw8ySsUuPL1M/YOuYehCw6JR7PFubLUem8OwO0Wu64/o3mP4Q== ;{id = 55582} +SECTION ADDITIONAL +a.gtld-servers.net. 120 IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 1000 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. 120 IN NS a.gtld-servers.net. +net. 120 IN RRSIG NS 5 1 120 20110214110823 20110205110823 30899 net. YnBGgfp1HPjgqxooKBYSR8cVL0MCPwT1w0z1ABXlq3mv40BR3gG041HnSQ35vj5Jrx3m8OmmX+bZYIalZsjPzw== ;{id = 30899} +SECTION ADDITIONAL +a.gtld-servers.net. 120 IN A 192.5.6.30 +a.gtld-servers.net. 120 IN RRSIG A 5 3 120 20110214110823 20110205110823 30899 net. QVDWcK9A1vBOwUmN1juqFWW/BTbY56npDnjf3FtLHsUzpwWfxd2GsbYda2pMXvOLI+C0/SRjkcmcjNIXXMFFFQ== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +net. IN DNSKEY +SECTION ANSWER +net. 60 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +net. 60 IN RRSIG DNSKEY 5 1 60 20110214110823 20110205110823 30899 net. RlK9lmXX69AkYLsGtNwraiaLboon6gZsSQADf3Z2r8MeBXo+zg24xWdBxXZRGNe8tkmvUOMxsAxFETJRmY1icQ== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +signed.net. IN DS +SECTION ANSWER +signed.net. 60 IN DS 16486 5 1 d98b27d62ec1be02346ca0c513a6562a03373fc3 +signed.net. 60 IN RRSIG DS 5 2 60 20110214110823 20110205110823 30899 net. JECbUqFSmPNXwG7q0wgBTXgk0u0q/5SuJh53gSthu027kpaYIL9gCAro0k9ZTzkpL2gc/T75iqQakMoWzWrvqQ== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +signed.net. IN NS +SECTION AUTHORITY +signed.net. 120 IN NS ns.signed.net. +signed.net. 60 IN DS 16486 5 1 d98b27d62ec1be02346ca0c513a6562a03373fc3 +signed.net. 60 IN RRSIG DS 5 2 60 20110214110823 20110205110823 30899 net. JECbUqFSmPNXwG7q0wgBTXgk0u0q/5SuJh53gSthu027kpaYIL9gCAro0k9ZTzkpL2gc/T75iqQakMoWzWrvqQ== ;{id = 30899} +SECTION ADDITIONAL +ns.signed.net. 120 IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +unsigned.net. IN DS +SECTION AUTHORITY +unsigned.net. 60 IN NSEC net. NS RRSIG NSEC +unsigned.net. 60 IN RRSIG NSEC 5 2 60 20110214110823 20110205110823 30899 net. BQVqD7KBhS6+mthhFmLajE899bt4aI5FqXIR0eJqhf8MYqXYYpF+R841QjpNjRQcDKeenu4TCeA3OtlGp3FoXA== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +unsigned.net. IN NS +SECTION AUTHORITY +unsigned.net. 120 IN NS ns.unsigned.net. +unsigned.net. 60 IN NSEC net. NS RRSIG NSEC +unsigned.net. 60 IN RRSIG NSEC 5 2 60 20110214110823 20110205110823 30899 net. BQVqD7KBhS6+mthhFmLajE899bt4aI5FqXIR0eJqhf8MYqXYYpF+R841QjpNjRQcDKeenu4TCeA3OtlGp3FoXA== ;{id = 30899} +SECTION ADDITIONAL +ns.unsigned.net. 120 IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.unsigned.net. +RANGE_BEGIN 0 1000 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.unsigned.net. IN A +SECTION ANSWER +www.unsigned.net. 60 IN A 10.20.30.44 +ENTRY_END +RANGE_END + +; ns.signed.net. +RANGE_BEGIN 0 1000 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +signed.net. IN DNSKEY +SECTION ANSWER +signed.net. 60 IN DNSKEY 257 3 5 AwEAAas/cAhCFXvBUgTSNZCvQp0pLx1dY+7rXR0hH4/3EUgWmsmbYUpI1qD0xhwKD/oYGEwAm291fyWJ9c0oVxXDEK8= ;{id = 16486 (ksk), size = 512b} +signed.net. 60 IN RRSIG DNSKEY 5 2 60 20110214110823 20110205110823 16486 signed.net. MSTL72Tx6duOuvU7t1WgqeidjJzPw+hR1khHiCgA07wYyjOzIMhUvSIUJElbk7znTH9I1cW+e14Gn4OeV2S/Lg== ;{id = 16486} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.signed.net. IN A +SECTION ANSWER +www.signed.net. 60 IN A 10.20.30.40 +www.signed.net. 60 IN RRSIG A 5 3 60 20110214110823 20110205110823 16486 signed.net. Q7leQsS7zlMGD1he8yfa8TfgSNc0boERx/qprOB691cgzD6Cnx2InP57hYgoR09iNXU8Zrng4hpF6CJLGZKhvw== ;{id = 16486} +ENTRY_END +RANGE_END + +; a series of queries. The first starts by priming the cache with +; the contents (that includes the signed and unsigned subdomain). +; then we probe every 10 seconds, and they must all succeed for 3 minutes, +; because in the graphs in the report there is an alternating 1 minute OK +; 1 minute servfail in the results (for BIND; this test is to make sure we +; do not suffer the same fate). + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.signed.net. IN A +ENTRY_END + +STEP 2 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.unsigned.net. IN A +ENTRY_END + +STEP 3 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.signed.net. IN A +SECTION ANSWER +www.signed.net. 60 IN A 10.20.30.40 +www.signed.net. 60 IN RRSIG A 5 3 60 20110214110823 20110205110823 16486 signed.net. Q7leQsS7zlMGD1he8yfa8TfgSNc0boERx/qprOB691cgzD6Cnx2InP57hYgoR09iNXU8Zrng4hpF6CJLGZKhvw== ;{id = 16486} +ENTRY_END + +STEP 4 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.unsigned.net. IN A +SECTION ANSWER +www.unsigned.net. 60 IN A 10.20.30.44 +ENTRY_END + +; after 10 seconds +STEP 10 TIME_PASSES ELAPSE 10 +STEP 11 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.signed.net. IN A +ENTRY_END +STEP 12 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.unsigned.net. IN A +ENTRY_END +STEP 13 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.signed.net. IN A +SECTION ANSWER +www.signed.net. 50 IN A 10.20.30.40 +www.signed.net. 50 IN RRSIG A 5 3 60 20110214110823 20110205110823 16486 signed.net. Q7leQsS7zlMGD1he8yfa8TfgSNc0boERx/qprOB691cgzD6Cnx2InP57hYgoR09iNXU8Zrng4hpF6CJLGZKhvw== ;{id = 16486} +ENTRY_END +STEP 14 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.unsigned.net. IN A +SECTION ANSWER +www.unsigned.net. 50 IN A 10.20.30.44 +ENTRY_END + +; at 50 seconds +STEP 50 TIME_PASSES ELAPSE 40 +STEP 51 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.signed.net. IN A +ENTRY_END +STEP 52 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.unsigned.net. IN A +ENTRY_END +STEP 53 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.signed.net. IN A +SECTION ANSWER +www.signed.net. 10 IN A 10.20.30.40 +www.signed.net. 10 IN RRSIG A 5 3 60 20110214110823 20110205110823 16486 signed.net. Q7leQsS7zlMGD1he8yfa8TfgSNc0boERx/qprOB691cgzD6Cnx2InP57hYgoR09iNXU8Zrng4hpF6CJLGZKhvw== ;{id = 16486} +ENTRY_END +STEP 54 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.unsigned.net. IN A +SECTION ANSWER +www.unsigned.net. 10 IN A 10.20.30.44 +ENTRY_END + +; introduce .net DS record, time at 70 s. +STEP 100 TIME_PASSES ELAPSE 20 +STEP 101 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.signed.net. IN A +ENTRY_END +STEP 102 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.unsigned.net. IN A +ENTRY_END +STEP 103 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.signed.net. IN A +SECTION ANSWER +www.signed.net. 60 IN A 10.20.30.40 +www.signed.net. 60 IN RRSIG A 5 3 60 20110214110823 20110205110823 16486 signed.net. Q7leQsS7zlMGD1he8yfa8TfgSNc0boERx/qprOB691cgzD6Cnx2InP57hYgoR09iNXU8Zrng4hpF6CJLGZKhvw== ;{id = 16486} +ENTRY_END +STEP 104 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.unsigned.net. IN A +SECTION ANSWER +www.unsigned.net. 60 IN A 10.20.30.44 +ENTRY_END + + +; a very long list of tests that try every 10 seconds +; no strict ttl matches so it can be copy and pasted. + +STEP 200 TIME_PASSES ELAPSE 10 +STEP 201 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.signed.net. IN A +ENTRY_END +STEP 202 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.unsigned.net. IN A +ENTRY_END +STEP 203 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.signed.net. IN A +SECTION ANSWER +www.signed.net. 60 IN A 10.20.30.40 +www.signed.net. 60 IN RRSIG A 5 3 60 20110214110823 20110205110823 16486 signed.net. Q7leQsS7zlMGD1he8yfa8TfgSNc0boERx/qprOB691cgzD6Cnx2InP57hYgoR09iNXU8Zrng4hpF6CJLGZKhvw== ;{id = 16486} +ENTRY_END +STEP 204 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.unsigned.net. IN A +SECTION ANSWER +www.unsigned.net. 60 IN A 10.20.30.44 +ENTRY_END + +STEP 210 TIME_PASSES ELAPSE 10 +STEP 211 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.signed.net. IN A +ENTRY_END +STEP 212 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.unsigned.net. IN A +ENTRY_END +STEP 213 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.signed.net. IN A +SECTION ANSWER +www.signed.net. 60 IN A 10.20.30.40 +www.signed.net. 60 IN RRSIG A 5 3 60 20110214110823 20110205110823 16486 signed.net. Q7leQsS7zlMGD1he8yfa8TfgSNc0boERx/qprOB691cgzD6Cnx2InP57hYgoR09iNXU8Zrng4hpF6CJLGZKhvw== ;{id = 16486} +ENTRY_END +STEP 214 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.unsigned.net. IN A +SECTION ANSWER +www.unsigned.net. 60 IN A 10.20.30.44 +ENTRY_END + +STEP 220 TIME_PASSES ELAPSE 10 +STEP 221 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.signed.net. IN A +ENTRY_END +STEP 222 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.unsigned.net. IN A +ENTRY_END +STEP 223 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.signed.net. IN A +SECTION ANSWER +www.signed.net. 60 IN A 10.20.30.40 +www.signed.net. 60 IN RRSIG A 5 3 60 20110214110823 20110205110823 16486 signed.net. Q7leQsS7zlMGD1he8yfa8TfgSNc0boERx/qprOB691cgzD6Cnx2InP57hYgoR09iNXU8Zrng4hpF6CJLGZKhvw== ;{id = 16486} +ENTRY_END +STEP 224 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.unsigned.net. IN A +SECTION ANSWER +www.unsigned.net. 60 IN A 10.20.30.44 +ENTRY_END + +STEP 230 TIME_PASSES ELAPSE 10 +STEP 231 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.signed.net. IN A +ENTRY_END +STEP 232 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.unsigned.net. IN A +ENTRY_END +STEP 233 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.signed.net. IN A +SECTION ANSWER +www.signed.net. 60 IN A 10.20.30.40 +www.signed.net. 60 IN RRSIG A 5 3 60 20110214110823 20110205110823 16486 signed.net. Q7leQsS7zlMGD1he8yfa8TfgSNc0boERx/qprOB691cgzD6Cnx2InP57hYgoR09iNXU8Zrng4hpF6CJLGZKhvw== ;{id = 16486} +ENTRY_END +STEP 234 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.unsigned.net. IN A +SECTION ANSWER +www.unsigned.net. 60 IN A 10.20.30.44 +ENTRY_END + +STEP 240 TIME_PASSES ELAPSE 10 +STEP 241 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.signed.net. IN A +ENTRY_END +STEP 242 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.unsigned.net. IN A +ENTRY_END +STEP 243 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.signed.net. IN A +SECTION ANSWER +www.signed.net. 60 IN A 10.20.30.40 +www.signed.net. 60 IN RRSIG A 5 3 60 20110214110823 20110205110823 16486 signed.net. Q7leQsS7zlMGD1he8yfa8TfgSNc0boERx/qprOB691cgzD6Cnx2InP57hYgoR09iNXU8Zrng4hpF6CJLGZKhvw== ;{id = 16486} +ENTRY_END +STEP 244 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.unsigned.net. IN A +SECTION ANSWER +www.unsigned.net. 60 IN A 10.20.30.44 +ENTRY_END + +STEP 250 TIME_PASSES ELAPSE 10 +STEP 251 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.signed.net. IN A +ENTRY_END +STEP 252 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.unsigned.net. IN A +ENTRY_END +STEP 253 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.signed.net. IN A +SECTION ANSWER +www.signed.net. 60 IN A 10.20.30.40 +www.signed.net. 60 IN RRSIG A 5 3 60 20110214110823 20110205110823 16486 signed.net. Q7leQsS7zlMGD1he8yfa8TfgSNc0boERx/qprOB691cgzD6Cnx2InP57hYgoR09iNXU8Zrng4hpF6CJLGZKhvw== ;{id = 16486} +ENTRY_END +STEP 254 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.unsigned.net. IN A +SECTION ANSWER +www.unsigned.net. 60 IN A 10.20.30.44 +ENTRY_END + +STEP 260 TIME_PASSES ELAPSE 10 +STEP 261 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.signed.net. IN A +ENTRY_END +STEP 262 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.unsigned.net. IN A +ENTRY_END +STEP 263 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.signed.net. IN A +SECTION ANSWER +www.signed.net. 60 IN A 10.20.30.40 +www.signed.net. 60 IN RRSIG A 5 3 60 20110214110823 20110205110823 16486 signed.net. Q7leQsS7zlMGD1he8yfa8TfgSNc0boERx/qprOB691cgzD6Cnx2InP57hYgoR09iNXU8Zrng4hpF6CJLGZKhvw== ;{id = 16486} +ENTRY_END +STEP 264 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.unsigned.net. IN A +SECTION ANSWER +www.unsigned.net. 60 IN A 10.20.30.44 +ENTRY_END + +STEP 270 TIME_PASSES ELAPSE 10 +STEP 271 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.signed.net. IN A +ENTRY_END +STEP 272 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.unsigned.net. IN A +ENTRY_END +STEP 273 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.signed.net. IN A +SECTION ANSWER +www.signed.net. 60 IN A 10.20.30.40 +www.signed.net. 60 IN RRSIG A 5 3 60 20110214110823 20110205110823 16486 signed.net. Q7leQsS7zlMGD1he8yfa8TfgSNc0boERx/qprOB691cgzD6Cnx2InP57hYgoR09iNXU8Zrng4hpF6CJLGZKhvw== ;{id = 16486} +ENTRY_END +STEP 274 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.unsigned.net. IN A +SECTION ANSWER +www.unsigned.net. 60 IN A 10.20.30.44 +ENTRY_END + +STEP 280 TIME_PASSES ELAPSE 10 +STEP 281 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.signed.net. IN A +ENTRY_END +STEP 282 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.unsigned.net. IN A +ENTRY_END +STEP 283 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.signed.net. IN A +SECTION ANSWER +www.signed.net. 60 IN A 10.20.30.40 +www.signed.net. 60 IN RRSIG A 5 3 60 20110214110823 20110205110823 16486 signed.net. Q7leQsS7zlMGD1he8yfa8TfgSNc0boERx/qprOB691cgzD6Cnx2InP57hYgoR09iNXU8Zrng4hpF6CJLGZKhvw== ;{id = 16486} +ENTRY_END +STEP 284 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.unsigned.net. IN A +SECTION ANSWER +www.unsigned.net. 60 IN A 10.20.30.44 +ENTRY_END + +STEP 290 TIME_PASSES ELAPSE 10 +STEP 291 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.signed.net. IN A +ENTRY_END +STEP 292 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.unsigned.net. IN A +ENTRY_END +STEP 293 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.signed.net. IN A +SECTION ANSWER +www.signed.net. 60 IN A 10.20.30.40 +www.signed.net. 60 IN RRSIG A 5 3 60 20110214110823 20110205110823 16486 signed.net. Q7leQsS7zlMGD1he8yfa8TfgSNc0boERx/qprOB691cgzD6Cnx2InP57hYgoR09iNXU8Zrng4hpF6CJLGZKhvw== ;{id = 16486} +ENTRY_END +STEP 294 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.unsigned.net. IN A +SECTION ANSWER +www.unsigned.net. 60 IN A 10.20.30.44 +ENTRY_END + +STEP 300 TIME_PASSES ELAPSE 10 +STEP 301 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.signed.net. IN A +ENTRY_END +STEP 302 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.unsigned.net. IN A +ENTRY_END +STEP 303 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.signed.net. IN A +SECTION ANSWER +www.signed.net. 60 IN A 10.20.30.40 +www.signed.net. 60 IN RRSIG A 5 3 60 20110214110823 20110205110823 16486 signed.net. Q7leQsS7zlMGD1he8yfa8TfgSNc0boERx/qprOB691cgzD6Cnx2InP57hYgoR09iNXU8Zrng4hpF6CJLGZKhvw== ;{id = 16486} +ENTRY_END +STEP 304 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.unsigned.net. IN A +SECTION ANSWER +www.unsigned.net. 60 IN A 10.20.30.44 +ENTRY_END + +STEP 310 TIME_PASSES ELAPSE 10 +STEP 311 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.signed.net. IN A +ENTRY_END +STEP 312 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.unsigned.net. IN A +ENTRY_END +STEP 313 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.signed.net. IN A +SECTION ANSWER +www.signed.net. 60 IN A 10.20.30.40 +www.signed.net. 60 IN RRSIG A 5 3 60 20110214110823 20110205110823 16486 signed.net. Q7leQsS7zlMGD1he8yfa8TfgSNc0boERx/qprOB691cgzD6Cnx2InP57hYgoR09iNXU8Zrng4hpF6CJLGZKhvw== ;{id = 16486} +ENTRY_END +STEP 314 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.unsigned.net. IN A +SECTION ANSWER +www.unsigned.net. 60 IN A 10.20.30.44 +ENTRY_END + +STEP 320 TIME_PASSES ELAPSE 10 +STEP 321 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.signed.net. IN A +ENTRY_END +STEP 322 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.unsigned.net. IN A +ENTRY_END +STEP 323 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.signed.net. IN A +SECTION ANSWER +www.signed.net. 60 IN A 10.20.30.40 +www.signed.net. 60 IN RRSIG A 5 3 60 20110214110823 20110205110823 16486 signed.net. Q7leQsS7zlMGD1he8yfa8TfgSNc0boERx/qprOB691cgzD6Cnx2InP57hYgoR09iNXU8Zrng4hpF6CJLGZKhvw== ;{id = 16486} +ENTRY_END +STEP 324 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.unsigned.net. IN A +SECTION ANSWER +www.unsigned.net. 60 IN A 10.20.30.44 +ENTRY_END + +STEP 330 TIME_PASSES ELAPSE 10 +STEP 331 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.signed.net. IN A +ENTRY_END +STEP 332 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.unsigned.net. IN A +ENTRY_END +STEP 333 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.signed.net. IN A +SECTION ANSWER +www.signed.net. 60 IN A 10.20.30.40 +www.signed.net. 60 IN RRSIG A 5 3 60 20110214110823 20110205110823 16486 signed.net. Q7leQsS7zlMGD1he8yfa8TfgSNc0boERx/qprOB691cgzD6Cnx2InP57hYgoR09iNXU8Zrng4hpF6CJLGZKhvw== ;{id = 16486} +ENTRY_END +STEP 334 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.unsigned.net. IN A +SECTION ANSWER +www.unsigned.net. 60 IN A 10.20.30.44 +ENTRY_END + +STEP 340 TIME_PASSES ELAPSE 10 +STEP 341 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.signed.net. IN A +ENTRY_END +STEP 342 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.unsigned.net. IN A +ENTRY_END +STEP 343 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.signed.net. IN A +SECTION ANSWER +www.signed.net. 60 IN A 10.20.30.40 +www.signed.net. 60 IN RRSIG A 5 3 60 20110214110823 20110205110823 16486 signed.net. Q7leQsS7zlMGD1he8yfa8TfgSNc0boERx/qprOB691cgzD6Cnx2InP57hYgoR09iNXU8Zrng4hpF6CJLGZKhvw== ;{id = 16486} +ENTRY_END +STEP 344 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.unsigned.net. IN A +SECTION ANSWER +www.unsigned.net. 60 IN A 10.20.30.44 +ENTRY_END + +STEP 350 TIME_PASSES ELAPSE 10 +STEP 351 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.signed.net. IN A +ENTRY_END +STEP 352 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.unsigned.net. IN A +ENTRY_END +STEP 353 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.signed.net. IN A +SECTION ANSWER +www.signed.net. 60 IN A 10.20.30.40 +www.signed.net. 60 IN RRSIG A 5 3 60 20110214110823 20110205110823 16486 signed.net. Q7leQsS7zlMGD1he8yfa8TfgSNc0boERx/qprOB691cgzD6Cnx2InP57hYgoR09iNXU8Zrng4hpF6CJLGZKhvw== ;{id = 16486} +ENTRY_END +STEP 354 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.unsigned.net. IN A +SECTION ANSWER +www.unsigned.net. 60 IN A 10.20.30.44 +ENTRY_END + +STEP 360 TIME_PASSES ELAPSE 10 +STEP 361 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.signed.net. IN A +ENTRY_END +STEP 362 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.unsigned.net. IN A +ENTRY_END +STEP 363 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.signed.net. IN A +SECTION ANSWER +www.signed.net. 60 IN A 10.20.30.40 +www.signed.net. 60 IN RRSIG A 5 3 60 20110214110823 20110205110823 16486 signed.net. Q7leQsS7zlMGD1he8yfa8TfgSNc0boERx/qprOB691cgzD6Cnx2InP57hYgoR09iNXU8Zrng4hpF6CJLGZKhvw== ;{id = 16486} +ENTRY_END +STEP 364 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.unsigned.net. IN A +SECTION ANSWER +www.unsigned.net. 60 IN A 10.20.30.44 +ENTRY_END + +STEP 370 TIME_PASSES ELAPSE 10 +STEP 371 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.signed.net. IN A +ENTRY_END +STEP 372 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.unsigned.net. IN A +ENTRY_END +STEP 373 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.signed.net. IN A +SECTION ANSWER +www.signed.net. 60 IN A 10.20.30.40 +www.signed.net. 60 IN RRSIG A 5 3 60 20110214110823 20110205110823 16486 signed.net. Q7leQsS7zlMGD1he8yfa8TfgSNc0boERx/qprOB691cgzD6Cnx2InP57hYgoR09iNXU8Zrng4hpF6CJLGZKhvw== ;{id = 16486} +ENTRY_END +STEP 374 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.unsigned.net. IN A +SECTION ANSWER +www.unsigned.net. 60 IN A 10.20.30.44 +ENTRY_END + +STEP 380 TIME_PASSES ELAPSE 10 +STEP 381 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.signed.net. IN A +ENTRY_END +STEP 382 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.unsigned.net. IN A +ENTRY_END +STEP 383 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.signed.net. IN A +SECTION ANSWER +www.signed.net. 60 IN A 10.20.30.40 +www.signed.net. 60 IN RRSIG A 5 3 60 20110214110823 20110205110823 16486 signed.net. Q7leQsS7zlMGD1he8yfa8TfgSNc0boERx/qprOB691cgzD6Cnx2InP57hYgoR09iNXU8Zrng4hpF6CJLGZKhvw== ;{id = 16486} +ENTRY_END +STEP 384 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.unsigned.net. IN A +SECTION ANSWER +www.unsigned.net. 60 IN A 10.20.30.44 +ENTRY_END + +STEP 390 TIME_PASSES ELAPSE 10 +STEP 391 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.signed.net. IN A +ENTRY_END +STEP 392 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.unsigned.net. IN A +ENTRY_END +STEP 393 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.signed.net. IN A +SECTION ANSWER +www.signed.net. 60 IN A 10.20.30.40 +www.signed.net. 60 IN RRSIG A 5 3 60 20110214110823 20110205110823 16486 signed.net. Q7leQsS7zlMGD1he8yfa8TfgSNc0boERx/qprOB691cgzD6Cnx2InP57hYgoR09iNXU8Zrng4hpF6CJLGZKhvw== ;{id = 16486} +ENTRY_END +STEP 394 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.unsigned.net. IN A +SECTION ANSWER +www.unsigned.net. 60 IN A 10.20.30.44 +ENTRY_END + +STEP 400 TIME_PASSES ELAPSE 10 +STEP 401 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.signed.net. IN A +ENTRY_END +STEP 402 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.unsigned.net. IN A +ENTRY_END +STEP 403 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.signed.net. IN A +SECTION ANSWER +www.signed.net. 60 IN A 10.20.30.40 +www.signed.net. 60 IN RRSIG A 5 3 60 20110214110823 20110205110823 16486 signed.net. Q7leQsS7zlMGD1he8yfa8TfgSNc0boERx/qprOB691cgzD6Cnx2InP57hYgoR09iNXU8Zrng4hpF6CJLGZKhvw== ;{id = 16486} +ENTRY_END +STEP 404 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.unsigned.net. IN A +SECTION ANSWER +www.unsigned.net. 60 IN A 10.20.30.44 +ENTRY_END + +STEP 410 TIME_PASSES ELAPSE 10 +STEP 411 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.signed.net. IN A +ENTRY_END +STEP 412 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.unsigned.net. IN A +ENTRY_END +STEP 413 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.signed.net. IN A +SECTION ANSWER +www.signed.net. 60 IN A 10.20.30.40 +www.signed.net. 60 IN RRSIG A 5 3 60 20110214110823 20110205110823 16486 signed.net. Q7leQsS7zlMGD1he8yfa8TfgSNc0boERx/qprOB691cgzD6Cnx2InP57hYgoR09iNXU8Zrng4hpF6CJLGZKhvw== ;{id = 16486} +ENTRY_END +STEP 414 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.unsigned.net. IN A +SECTION ANSWER +www.unsigned.net. 60 IN A 10.20.30.44 +ENTRY_END + +STEP 420 TIME_PASSES ELAPSE 10 +STEP 421 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.signed.net. IN A +ENTRY_END +STEP 422 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.unsigned.net. IN A +ENTRY_END +STEP 423 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.signed.net. IN A +SECTION ANSWER +www.signed.net. 60 IN A 10.20.30.40 +www.signed.net. 60 IN RRSIG A 5 3 60 20110214110823 20110205110823 16486 signed.net. Q7leQsS7zlMGD1he8yfa8TfgSNc0boERx/qprOB691cgzD6Cnx2InP57hYgoR09iNXU8Zrng4hpF6CJLGZKhvw== ;{id = 16486} +ENTRY_END +STEP 424 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.unsigned.net. IN A +SECTION ANSWER +www.unsigned.net. 60 IN A 10.20.30.44 +ENTRY_END + +STEP 430 TIME_PASSES ELAPSE 10 +STEP 431 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.signed.net. IN A +ENTRY_END +STEP 432 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.unsigned.net. IN A +ENTRY_END +STEP 433 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.signed.net. IN A +SECTION ANSWER +www.signed.net. 60 IN A 10.20.30.40 +www.signed.net. 60 IN RRSIG A 5 3 60 20110214110823 20110205110823 16486 signed.net. Q7leQsS7zlMGD1he8yfa8TfgSNc0boERx/qprOB691cgzD6Cnx2InP57hYgoR09iNXU8Zrng4hpF6CJLGZKhvw== ;{id = 16486} +ENTRY_END +STEP 434 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.unsigned.net. IN A +SECTION ANSWER +www.unsigned.net. 60 IN A 10.20.30.44 +ENTRY_END + +STEP 440 TIME_PASSES ELAPSE 10 +STEP 441 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.signed.net. IN A +ENTRY_END +STEP 442 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.unsigned.net. IN A +ENTRY_END +STEP 443 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.signed.net. IN A +SECTION ANSWER +www.signed.net. 60 IN A 10.20.30.40 +www.signed.net. 60 IN RRSIG A 5 3 60 20110214110823 20110205110823 16486 signed.net. Q7leQsS7zlMGD1he8yfa8TfgSNc0boERx/qprOB691cgzD6Cnx2InP57hYgoR09iNXU8Zrng4hpF6CJLGZKhvw== ;{id = 16486} +ENTRY_END +STEP 444 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.unsigned.net. IN A +SECTION ANSWER +www.unsigned.net. 60 IN A 10.20.30.44 +ENTRY_END + +STEP 450 TIME_PASSES ELAPSE 10 +STEP 451 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.signed.net. IN A +ENTRY_END +STEP 452 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.unsigned.net. IN A +ENTRY_END +STEP 453 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.signed.net. IN A +SECTION ANSWER +www.signed.net. 60 IN A 10.20.30.40 +www.signed.net. 60 IN RRSIG A 5 3 60 20110214110823 20110205110823 16486 signed.net. Q7leQsS7zlMGD1he8yfa8TfgSNc0boERx/qprOB691cgzD6Cnx2InP57hYgoR09iNXU8Zrng4hpF6CJLGZKhvw== ;{id = 16486} +ENTRY_END +STEP 454 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.unsigned.net. IN A +SECTION ANSWER +www.unsigned.net. 60 IN A 10.20.30.44 +ENTRY_END + +STEP 460 TIME_PASSES ELAPSE 10 +STEP 461 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.signed.net. IN A +ENTRY_END +STEP 462 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.unsigned.net. IN A +ENTRY_END +STEP 463 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.signed.net. IN A +SECTION ANSWER +www.signed.net. 60 IN A 10.20.30.40 +www.signed.net. 60 IN RRSIG A 5 3 60 20110214110823 20110205110823 16486 signed.net. Q7leQsS7zlMGD1he8yfa8TfgSNc0boERx/qprOB691cgzD6Cnx2InP57hYgoR09iNXU8Zrng4hpF6CJLGZKhvw== ;{id = 16486} +ENTRY_END +STEP 464 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.unsigned.net. IN A +SECTION ANSWER +www.unsigned.net. 60 IN A 10.20.30.44 +ENTRY_END + +STEP 470 TIME_PASSES ELAPSE 10 +STEP 471 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.signed.net. IN A +ENTRY_END +STEP 472 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.unsigned.net. IN A +ENTRY_END +STEP 473 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.signed.net. IN A +SECTION ANSWER +www.signed.net. 60 IN A 10.20.30.40 +www.signed.net. 60 IN RRSIG A 5 3 60 20110214110823 20110205110823 16486 signed.net. Q7leQsS7zlMGD1he8yfa8TfgSNc0boERx/qprOB691cgzD6Cnx2InP57hYgoR09iNXU8Zrng4hpF6CJLGZKhvw== ;{id = 16486} +ENTRY_END +STEP 474 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.unsigned.net. IN A +SECTION ANSWER +www.unsigned.net. 60 IN A 10.20.30.44 +ENTRY_END + +STEP 480 TIME_PASSES ELAPSE 10 +STEP 481 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.signed.net. IN A +ENTRY_END +STEP 482 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.unsigned.net. IN A +ENTRY_END +STEP 483 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.signed.net. IN A +SECTION ANSWER +www.signed.net. 60 IN A 10.20.30.40 +www.signed.net. 60 IN RRSIG A 5 3 60 20110214110823 20110205110823 16486 signed.net. Q7leQsS7zlMGD1he8yfa8TfgSNc0boERx/qprOB691cgzD6Cnx2InP57hYgoR09iNXU8Zrng4hpF6CJLGZKhvw== ;{id = 16486} +ENTRY_END +STEP 484 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.unsigned.net. IN A +SECTION ANSWER +www.unsigned.net. 60 IN A 10.20.30.44 +ENTRY_END + +STEP 490 TIME_PASSES ELAPSE 10 +STEP 491 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.signed.net. IN A +ENTRY_END +STEP 492 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.unsigned.net. IN A +ENTRY_END +STEP 493 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.signed.net. IN A +SECTION ANSWER +www.signed.net. 60 IN A 10.20.30.40 +www.signed.net. 60 IN RRSIG A 5 3 60 20110214110823 20110205110823 16486 signed.net. Q7leQsS7zlMGD1he8yfa8TfgSNc0boERx/qprOB691cgzD6Cnx2InP57hYgoR09iNXU8Zrng4hpF6CJLGZKhvw== ;{id = 16486} +ENTRY_END +STEP 494 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.unsigned.net. IN A +SECTION ANSWER +www.unsigned.net. 60 IN A 10.20.30.44 +ENTRY_END + + +SCENARIO_END diff --git a/testdata/nomem_cnametopos.rpl b/testdata/nomem_cnametopos.rpl new file mode 100644 index 00000000000..8600209462c --- /dev/null +++ b/testdata/nomem_cnametopos.rpl @@ -0,0 +1,296 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + trust-anchor: "example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}" + val-override-date: "20070916134226" + msg-cache-size: 8 + rrset-cache-size: 8 + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test cname to positive without cache + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +a.gtld-servers.net. IN A +SECTION ANSWER +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +a.gtld-servers.net. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME www.example.net. +www.example.com. 3600 IN RRSIG CNAME DSA 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFGcJxnNxpWCBzXejiSdl4p1BKRMnAhUApoJrugVBRwFgAoYAhhqlZFac7fE= ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN DNSKEY +SECTION ANSWER +example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.net. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +www.example.net. IN A 11.12.13.14 +www.example.net. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.net. CPxF5hK9Kg5eT7W6LgZwr0ePYEm9HMcSY4vvqCS6gDWB4X9jvXLCfBkCLhsNybPBpGWlsLi5wM6MTdJXuPpsRA== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 5 TRAFFIC + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME www.example.net. +www.example.com. 3600 IN RRSIG CNAME DSA 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFGcJxnNxpWCBzXejiSdl4p1BKRMnAhUApoJrugVBRwFgAoYAhhqlZFac7fE= ;{id = 2854} +www.example.net. IN A 11.12.13.14 +www.example.net. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.net. CPxF5hK9Kg5eT7W6LgZwr0ePYEm9HMcSY4vvqCS6gDWB4X9jvXLCfBkCLhsNybPBpGWlsLi5wM6MTdJXuPpsRA== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/pylib.tpkg b/testdata/pylib.tpkg new file mode 100644 index 0000000000000000000000000000000000000000..6507f781dfd1dd69b2b521d49d5889becda536a8 GIT binary patch literal 4209 zcmV-%5RUI3iwFQR3RO)21MM6AciK3zzeaz>tkZ5_3yy(&?9oeK9dH`o5umoyG}qh5 zI#>iZU{l*9p>O~An~`lWUrBc_mwS7M_H8OlqnXi2^CgMVWZ+)OjvMU0_>UC@%i;b$ z{aZTRSHyQ|Z%_Q2lozGaetEyF>?`}_7fPvIE>&K@{(p|8Ss90s9RR$z^T!bn9)jaR z_#6y9Zy8P3KdudY|7JXrN0TR{@!0wwmiKY}%ZGdWl|$^o_1`a-4_<)sggmS*|L5z! z{lo4!40f+vZqhr*lzz(Ns}45g@(d*%jYI6gPr2)RJ@+~%jju#i$}_hI3B(Uapj6q`C~&<9 zq=4HF#Ng1g-2rz%DkPw6i{HCZu9RmifldIsI4a_f#1g6n2zWRiL4h?9kx7C;gtXxt1%XY~PpbGy zAss)6^?il@m-Y^oGU|Wn;GnX5rkFvhr>O710U@W z4aE)QZj*{?LC=lk+i`Ri$lY&w2Geq82V%r+Fb-{i-2E+86@|ux(b$pa2QsMnqeQjlk)({#2mjn z9&#@df@L&h7sc*lR{%pa@_}m)!kL7{x`=TZ=EZ!hQ{4o!bz)tph6Y$~8?BFeU8}?K zC3b31Yqc*8{r#y0r>#a^GfYsMb!=@~hJJi*wG5Miq?$NX5V)-mEpw>w5Ej0T2T;TNX6*Gu_ha$WN;v$S#kA)(Mq*(Y!FOmX9vd`L-y3;h8B~+`PFqpt64OWS*?abL&h2fFxy&9r;7GT!&#`tWdV^g z!fI+C&JhZGp{|~(?{QYS_0kZ+!1bt|8`>E$+d5%jo*$c*Zk<~iyl=JYf?rcJKI%2i zd;^V^DFk(HY6T==sYIG^pp>v1>&NG&PV!>Nv!xlvdE3%k%{;E|1xf_xuHx9bkZh|d zW{bjU8JC2W#2^G;fQwTN+i`uHEEbnaVlYu`H7g5;6j6#+W}48{-ZylVbxot*7NNP& zO%3gyYUn0G=rQ376{()nw8a7;UvV|FV+&##K|cYt{!u5!V_;l-l!Tsa6KpfjYp03K z$@rZKyM&q%2Xijk9}4ZRCU7Bq9$dIzyldMI9JFf9hKB~dVP9b#P3m9f0z5xt%;7y$ zOpG&JrvTmFb-pTWIJ$t2>-GGc6o-ǒbTy7mAAnF7SF1YC#g?<+Kkh_OnQup77| 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 H08jt`ZUQ0M literal 0 HcmV?d00001 diff --git a/testdata/pymod.tpkg b/testdata/pymod.tpkg new file mode 100644 index 0000000000000000000000000000000000000000..164a82a00424b3d7887fb41d809b19f4b7ac47f2 GIT binary patch literal 4072 zcmV$$zBra=ZijP1SD{`-ezw14UFptOG^AC%Dk`{ljT3y`0hk!9`w-2N!l z4GSv52L8PALMNJ3pe$@`f;%1+qd~wdJFGxS*zmm|s=(`3Q#W4=8>o$9I0=VdzXGl& zY~TW7-N*}YwkRU7WA~gP!d&Qf)MwhJn=&@>;{fc6yxRX zPY|Z(1-DjU7r%HeL&$^)3Aso|EZYvSt5iOcWc*ip{n~7D$#M3#w%F6Q`~DxXFnVel zU-AF)zPv~Nf3%NT;s|pA`TybC|DUC8!e+4uGuuP4xG8Kx=#7IegJ{5DWQC|0xIrzE zPs8nik;m&Eq`^-lpet;!?!W_aVBN4Z-oyb(6xc9i>A36NAKhSgP6V>ha|EK!xfOpK zQ@DZhtM5v`iEs>J%?fTES4@aO(uTGhqEjCK#(7TPxEiJ1bL*OMQ~VAgv!TdfC)`b8 zc6WDvo1)>Yu{(<0P`j+xI(6+tSMrwh6`Wix_`x%&!$dPb&UEJ;Kh;j(~ACDZNKwA6G^NLWg`D0v7t7 z8&YEKUNi30eN5;AC}Yfk0d5%nV>6ds!#gW#Xdexd+X&z}TNe-J^gn}@P2{~&=f90KnPiAmbq*b;)8 z11H2Hp%-Cwj|nFP&&MJrt{Nl(1kjo7gi+vJjUxwBxaHcsIB`-S-gD)+RxqIwWfT_R z)`C1+IZ=c;+7G-N$Hs?ffRT=}P0t$+JJy7obXvz6 zhBFOwyYP7#=D9rPnPz~|JT)&AT?Kq@>CJaqO|8MnB@U`kZMH6T?ai49XU%#|)eTS@ zHSBGex^~hwo4O%@s2Dg^bRoit% z7ogSFTTMd+lB}i~)w-gct2GJfBTZ1>sSOj1Go@bV6m|6tc5tS%(!q%;AbZLQR>PbG z%2(5LwQ7H!z-XyejULqZDoTNMUjdN{gw;^rwh;T|Fmeo2LR8?GwY)%(kh*n`X1d`88DiomN$ipP=3}xT4yIT0jz}LZk@?Y6*w& z`J`=Vq%Q$^HdS43w@j_s$fI>HP$MY2f^%zJv&{yV7M0V~F9|EDfh)cM7iTK=qkS7f ztS*JrV4&KnW)==9np6+X#Ds?Wrmmr`t168)3C)FOs2KMYT{8$miwR#SNVQF3a|0n? z@ndGi7PuKfI|ZfoP9w%+U^G5zLQ9qj_8IN!S)y|ae&;+cp=Z$EYV2ao!?z+=6S&|x z4=$WfZr`#38>3pI?qWc%TUYpuA@xUzX95iSRP%eGAmH{19n*<&j$MFmub;2*7>+5R z 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 X9v&VZ9v&VZpMgICh3yX@;a^r6$1 zvvh`wg^szCAkFlT@7_sZuw}ascG{V+1NzwA+uwfN?nz0R{W%e7roC9G#?DI+r2*|6 z9N?Y$op#II&0~4DwBsYSsNZS@M(zg(L1*XSMZCE~xz3nE$c4-^t{&Et+2k>?4W{YS zGN{h8`}snoHtWCss-tJZpgyJTAb7C;f#1RU(@v+|3|cM2_d5aBpFR`*qx6l}{|(dp z1Do;?Zc9%-a;1e#L-0LHdR#|J%reV}COoD0KUmLugX^136=80RLQt5GxOU^}60M-o&SL%$SNb>7tdfRDXp) zx^g;`DNnPIbf(f2&D@wfSH4f4kM(_WxI)8q{1DXxkMmWizSD!h`G9 zNDZ{iRm1^9hbhyTADA-**VsL#+UrPld1^bLl!LAT;hTSUCaS64#U;|}CM9AQxf9M!!&mjmGi!uBNKM}mo z4@c(BokR0z&xgNZ5rLbG2o5-FwQh94O*#0lO`Iv&<wnEfm7OR2uw4}WbsgTcLYZe<;nn* zUUYM%aJpK|&><1aRtiLMohR9$Lsto8NrHZ;Ii3{2()jjZ(0G^-Q$7@+ugBg!@8C@Z zuUoP!24&Y`JHxQ4ksw zpUOFpU%@FJ;b^2hyI5zsOpg%Px|zsi}hSASCItM)_zj1%(TvG@A^-M1y0)~XEp6$4K>q;f)E6-T G6aWAo85HyY literal 0 HcmV?d00001 diff --git a/testdata/rrset_rettl.rpl b/testdata/rrset_rettl.rpl new file mode 100644 index 00000000000..2ae64e9476b --- /dev/null +++ b/testdata/rrset_rettl.rpl @@ -0,0 +1,118 @@ +; This is a comment. +; config options go here. +forward-zone: name: "." forward-addr: 216.0.0.1 +CONFIG_END + +SCENARIO_BEGIN RRset TTL is not greedily updated from message. + +STEP 1 QUERY +ENTRY_BEGIN + REPLY RD + SECTION QUESTION + www.example.com. IN A +ENTRY_END +; the query is sent to the forwarder - no cache yet. +STEP 2 CHECK_OUT_QUERY +ENTRY_BEGIN + MATCH qname qtype opcode + SECTION QUESTION + www.example.com. IN A +ENTRY_END +STEP 3 REPLY +ENTRY_BEGIN + MATCH opcode qtype qname + ADJUST copy_id + ; authoritative answer + REPLY QR AA RD RA NOERROR + SECTION QUESTION + www.example.com. IN A + SECTION ANSWER + www.example.com. IN A 10.20.30.40 + SECTION AUTHORITY + example.com. 100 IN NS ns.example.com. + SECTION ADDITIONAL + ns.example.com. IN A 10.20.30.50 +ENTRY_END +STEP 4 CHECK_ANSWER +ENTRY_BEGIN + MATCH all ttl + REPLY QR RD RA + SECTION QUESTION + www.example.com. IN A + SECTION ANSWER + www.example.com. IN A 10.20.30.40 + SECTION AUTHORITY + example.com. 100 IN NS ns.example.com. + SECTION ADDITIONAL + ns.example.com. IN A 10.20.30.50 +ENTRY_END + +; another query passes along +STEP 6 QUERY +ENTRY_BEGIN + REPLY RD + SECTION QUESTION + bla.example.com. IN A +ENTRY_END +STEP 7 CHECK_OUT_QUERY +ENTRY_BEGIN + MATCH qname qtype opcode + SECTION QUESTION + bla.example.com. IN A +ENTRY_END +STEP 8 REPLY +; This answer has a fresh TTL +ENTRY_BEGIN + MATCH opcode qtype qname + ADJUST copy_id + ; authoritative answer + REPLY QR AA RD RA NOERROR + SECTION QUESTION + bla.example.com. IN A + SECTION ANSWER + bla.example.com. IN A 10.20.30.140 + SECTION AUTHORITY + example.com. 200 IN NS ns.example.com. + SECTION ADDITIONAL + ns.example.com. IN A 10.20.30.50 +ENTRY_END +STEP 9 CHECK_ANSWER +ENTRY_BEGIN + MATCH all ttl + REPLY QR RD RA + SECTION QUESTION + bla.example.com. IN A + SECTION ANSWER + bla.example.com. IN A 10.20.30.140 + SECTION AUTHORITY + example.com. 100 IN NS ns.example.com. + SECTION ADDITIONAL + ns.example.com. IN A 10.20.30.50 +ENTRY_END + +; original www.example.com query +STEP 10 QUERY +ENTRY_BEGIN + REPLY RD + SECTION QUESTION + www.example.com. IN A +ENTRY_END + +; immediate answer without an OUT_QUERY happening (checked on exit) +; also, the answer does not have AA set +; NS rrset has not been updated. No greedy TTL has happened. +STEP 11 CHECK_ANSWER +ENTRY_BEGIN + MATCH all ttl + REPLY QR RD RA + SECTION QUESTION + www.example.com. IN A + SECTION ANSWER + www.example.com. IN A 10.20.30.40 + SECTION AUTHORITY + example.com. 100 IN NS ns.example.com. + SECTION ADDITIONAL + ns.example.com. IN A 10.20.30.50 +ENTRY_END + +SCENARIO_END diff --git a/testdata/rrset_untrusted.rpl b/testdata/rrset_untrusted.rpl new file mode 100644 index 00000000000..232554872b4 --- /dev/null +++ b/testdata/rrset_untrusted.rpl @@ -0,0 +1,119 @@ +; This is a comment. +; config options go here. +forward-zone: name: "." forward-addr: 216.0.0.1 +CONFIG_END + +SCENARIO_BEGIN Untrusted rrset not used for update + +STEP 1 QUERY +ENTRY_BEGIN + REPLY RD + SECTION QUESTION + www.example.com. IN A +ENTRY_END +; the query is sent to the forwarder - no cache yet. +STEP 2 CHECK_OUT_QUERY +ENTRY_BEGIN + MATCH qname qtype opcode + SECTION QUESTION + www.example.com. IN A +ENTRY_END +STEP 3 REPLY +ENTRY_BEGIN + MATCH opcode qtype qname + ADJUST copy_id + ; authoritative answer + REPLY QR AA RD RA NOERROR + SECTION QUESTION + www.example.com. IN A + SECTION ANSWER + www.example.com. IN A 10.20.30.40 + SECTION AUTHORITY + example.com. IN NS ns.example.com. + SECTION ADDITIONAL + ns.example.com. IN A 10.20.30.50 +ENTRY_END +STEP 4 CHECK_ANSWER +ENTRY_BEGIN + MATCH all + REPLY QR RD RA + SECTION QUESTION + www.example.com. IN A + SECTION ANSWER + www.example.com. IN A 10.20.30.40 + SECTION AUTHORITY + example.com. IN NS ns.example.com. + SECTION ADDITIONAL + ns.example.com. IN A 10.20.30.50 +ENTRY_END + +; another query passes along +STEP 6 QUERY +ENTRY_BEGIN + REPLY RD + SECTION QUESTION + bla.example.com. IN A +ENTRY_END +STEP 7 CHECK_OUT_QUERY +ENTRY_BEGIN + MATCH qname qtype opcode + SECTION QUESTION + bla.example.com. IN A +ENTRY_END +STEP 8 REPLY +; This answer has updated information on ns2.example.com. +; But it is nerfed into the additional. Must be ignored per rfc2181. +ENTRY_BEGIN + MATCH opcode qtype qname + ADJUST copy_id + ; authoritative answer + REPLY QR AA RD RA NOERROR + SECTION QUESTION + bla.example.com. IN A + SECTION ANSWER + bla.example.com. IN A 10.20.30.140 + SECTION AUTHORITY + SECTION ADDITIONAL + example.com. IN NS ns.eeeek.com. + example.com. IN NS ns2.eeeek.com. + ns.eeeek.com. IN A 55.44.33.22 + ns2.eeeek.com. IN A 55.44.33.24 +ENTRY_END +STEP 9 CHECK_ANSWER +ENTRY_BEGIN + MATCH all + REPLY QR RD RA + SECTION QUESTION + bla.example.com. IN A + SECTION ANSWER + bla.example.com. IN A 10.20.30.140 + SECTION AUTHORITY + SECTION ADDITIONAL +ENTRY_END + + +; original www.example.com query +STEP 10 QUERY +ENTRY_BEGIN + REPLY RD + SECTION QUESTION + www.example.com. IN A +ENTRY_END +; immediate answer without an OUT_QUERY happening (checked on exit) +; also, the answer does not have AA set +; NS rrset has not been updated from the additional seen before. +STEP 11 CHECK_ANSWER +ENTRY_BEGIN + MATCH all + REPLY QR RD RA + SECTION QUESTION + www.example.com. IN A + SECTION ANSWER + www.example.com. IN A 10.20.30.40 + SECTION AUTHORITY + example.com. IN NS ns.example.com. + SECTION ADDITIONAL + ns.example.com. IN A 10.20.30.50 +ENTRY_END + +SCENARIO_END diff --git a/testdata/rrset_updated.rpl b/testdata/rrset_updated.rpl new file mode 100644 index 00000000000..4e877df1147 --- /dev/null +++ b/testdata/rrset_updated.rpl @@ -0,0 +1,123 @@ +; This is a comment. +; config options go here. +forward-zone: name: "." forward-addr: 216.0.0.1 +CONFIG_END + +SCENARIO_BEGIN RRset is updated from other message that passes by. + +STEP 1 QUERY +ENTRY_BEGIN + REPLY RD + SECTION QUESTION + www.example.com. IN A +ENTRY_END +; the query is sent to the forwarder - no cache yet. +STEP 2 CHECK_OUT_QUERY +ENTRY_BEGIN + MATCH qname qtype opcode + SECTION QUESTION + www.example.com. IN A +ENTRY_END +STEP 3 REPLY +ENTRY_BEGIN + MATCH opcode qtype qname + ADJUST copy_id + ; authoritative answer + REPLY QR AA RD RA NOERROR + SECTION QUESTION + www.example.com. IN A + SECTION ANSWER + www.example.com. IN A 10.20.30.40 + SECTION AUTHORITY + example.com. IN NS ns.example.com. + SECTION ADDITIONAL + ns.example.com. IN A 10.20.30.50 +ENTRY_END +STEP 4 CHECK_ANSWER +ENTRY_BEGIN + MATCH all + REPLY QR RD RA + SECTION QUESTION + www.example.com. IN A + SECTION ANSWER + www.example.com. IN A 10.20.30.40 + SECTION AUTHORITY + example.com. IN NS ns.example.com. + SECTION ADDITIONAL + ns.example.com. IN A 10.20.30.50 +ENTRY_END + +; another query passes along +STEP 6 QUERY +ENTRY_BEGIN + REPLY RD + SECTION QUESTION + bla.example.com. IN A +ENTRY_END +STEP 7 CHECK_OUT_QUERY +ENTRY_BEGIN + MATCH qname qtype opcode + SECTION QUESTION + bla.example.com. IN A +ENTRY_END +STEP 8 REPLY +; This answer has updated information on ns2.example.com. +ENTRY_BEGIN + MATCH opcode qtype qname + ADJUST copy_id + ; authoritative answer + REPLY QR AA RD RA NOERROR + SECTION QUESTION + bla.example.com. IN A + SECTION ANSWER + bla.example.com. IN A 10.20.30.140 + SECTION AUTHORITY + example.com. IN NS ns.example.com. + example.com. IN NS ns2.example.com. + SECTION ADDITIONAL + ns.example.com. IN A 10.20.30.50 + ns2.example.com. IN A 10.20.30.53 +ENTRY_END +STEP 9 CHECK_ANSWER +ENTRY_BEGIN + MATCH all + REPLY QR RD RA + SECTION QUESTION + bla.example.com. IN A + SECTION ANSWER + bla.example.com. IN A 10.20.30.140 + SECTION AUTHORITY + example.com. IN NS ns.example.com. + example.com. IN NS ns2.example.com. + SECTION ADDITIONAL + ns.example.com. IN A 10.20.30.50 + ns2.example.com. IN A 10.20.30.53 +ENTRY_END + + +; original www.example.com query +STEP 10 QUERY +ENTRY_BEGIN + REPLY RD + SECTION QUESTION + www.example.com. IN A +ENTRY_END +; immediate answer without an OUT_QUERY happening (checked on exit) +; also, the answer does not have AA set +; NS rrset has been updated. +STEP 11 CHECK_ANSWER +ENTRY_BEGIN + MATCH all + REPLY QR RD RA + SECTION QUESTION + www.example.com. IN A + SECTION ANSWER + www.example.com. IN A 10.20.30.40 + SECTION AUTHORITY + example.com. IN NS ns.example.com. + example.com. IN NS ns2.example.com. + SECTION ADDITIONAL + ns.example.com. IN A 10.20.30.50 +ENTRY_END + +SCENARIO_END diff --git a/testdata/speed_cache.tpkg b/testdata/speed_cache.tpkg new file mode 100644 index 0000000000000000000000000000000000000000..cdba5e3f93ed5cd79323b15d3d10708b726c96c5 GIT binary patch literal 2153 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 literal 0 HcmV?d00001 diff --git a/testdata/speed_local.tpkg b/testdata/speed_local.tpkg new file mode 100644 index 0000000000000000000000000000000000000000..e7d7c5d5e2dbd95c2491b5c95176a8f0bf97662f GIT binary patch literal 1351 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 OAN~d<-YHxFC;$Li)8+C2 literal 0 HcmV?d00001 diff --git a/testdata/stop_nxdomain.rpl b/testdata/stop_nxdomain.rpl new file mode 100644 index 00000000000..9c57ec71bd4 --- /dev/null +++ b/testdata/stop_nxdomain.rpl @@ -0,0 +1,93 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + harden-below-nxdomain: yes + trust-anchor: ". IN DNSKEY 257 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3" + val-override-date: "20070916134226" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test stop cache search on nxdomain + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN DNSKEY +SECTION ANSWER +. 3600 IN DNSKEY 257 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30900 (ksk), size = 512b} +. 3600 IN RRSIG DNSKEY 5 0 3600 20070926134150 20070829134150 30900 . BlVcSh8xSgm7ne+XVCJwNHQKjk5kTJgG4Fa3sOSfp3YUjb2YclmVWyIw7XEHl0/C6CN5gdy18idnM6vT6Hy42A== ;{id = 30900} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NXDOMAIN +SECTION QUESTION +example.local. IN A +SECTION AUTHORITY +. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2010111601 1800 900 604800 86400 +. 86400 IN RRSIG SOA 5 0 86400 20070926134150 20070829134150 30900 . bOYbFZZp7vWWC2oxV+kph+YXjoQj2f6QJktlgmzRI7oReFX9jy/LibTPQi/sW0SGHpLaj3G5p4IfIlBibne4DA== ;{id = 30900} +. 86400 IN NSEC ac. NS SOA RRSIG NSEC DNSKEY +. 86400 IN RRSIG NSEC 5 0 86400 20070926134150 20070829134150 30900 . U+/m5+FmczzkosEx1aTP7MK/F3PpcKWct8CzM1jhjwNe2RlnW7qFe0IH8SLzD/elvxDTQMpJSMlKOhUUdapB8g== ;{id = 30900} +lk. 86400 IN NSEC lr. NS DS RRSIG NSEC +lk. 86400 IN RRSIG NSEC 5 1 86400 20070926134150 20070829134150 30900 . j6Pw5Eu9vGHDJcckTSWa8YD1b7FV7c/Z8aVkLfJCH+iPcaa40/LSp784+t2PnAAXL8fgriNL6jF/ve1rti3ANQ== ;{id = 30900} +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +example.local. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NXDOMAIN +SECTION QUESTION +example.local. IN A +SECTION AUTHORITY +. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2010111601 1800 900 604800 86400 +ENTRY_END + +STEP 20 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +foo.example.local. IN A +ENTRY_END + +; this query does not get sent to K-ROOT. +STEP 30 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NXDOMAIN +SECTION QUESTION +foo.example.local. IN A +SECTION AUTHORITY +. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2010111601 1800 900 604800 86400 +ENTRY_END + +SCENARIO_END diff --git a/testdata/stream_ssl.tpkg b/testdata/stream_ssl.tpkg new file mode 100644 index 0000000000000000000000000000000000000000..724e4af6c824c6f43f1dcf5ded0a212a2410d2a4 GIT binary patch literal 3732 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 literal 0 HcmV?d00001 diff --git a/testdata/stream_tcp.tpkg b/testdata/stream_tcp.tpkg new file mode 100644 index 0000000000000000000000000000000000000000..37cb249b159836668754b16f19a19b0a0361213f GIT binary patch literal 1520 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 TBOKuf-x2%^_)Pmr04M+eQef{* literal 0 HcmV?d00001 diff --git a/testdata/stub_udp6.tpkg b/testdata/stub_udp6.tpkg new file mode 100644 index 0000000000000000000000000000000000000000..c5e7ffe9dcf4aedd3dc2f3448744f425b2adaa35 GIT binary patch literal 1529 zcmV5ooQ`6Nm+Z)-QM2b?%wTcSI6VoTom-T%(Qc(KC5kD$GLNvJz!P}rQ9?-ih0y(!3Y z&YEl1+D0pkk7qKm#N3HIG?b8g;styl2m($H&l+}b&~Ntob`N9|!NB?p0U>VZt*n4g@AmH#+BIo`0u z@yT&E-fyocGC{@YPdRA?XQ;yLGHI=>Fbgi(Ebx*ufrs(Zaj!;^z>rS2`MMy^l~N#w z*g45aW&C$DMo>-Bc@wOp%$s2Ynd@vdhwH>QadXGt*rvfOgw*uQu~ZO&&&fo{Gy4Bs z@!#X_qpk5k{8!7Sc>n8VqoS#%t|sxnr0(PYF5r#BsqIXuwRS}E8*1vazyeKCNrQ4X z^20bm^pFP75Z4&o(YIp9jWGmV`wpBpI=}?F)wwnmQje%3rZk)wSzjR0d$h8qf~H%# zZmA~Jn|&x@nn&I{J~HwH8d=~)3S204rG^jxQ!sKc{Bcr8CLm8kh7U@KJjl^4xbQq5}aM&k(x`|BuxHkLp7Q>t1*1`7<^(^w%@h3Cn z`JAr$BygAi3qw5C8V}`v_Wr*MxS9VY8P)fc0p^p0B6uv(Czq2| z!NYWBKA$V}i!%);6qAN2(hBUUWob!nl}~DJ(Zb)zj{=^bBq_?+iUa}Q?gGaPNxG1w zVM!;S0Ia5rse1)Zz~?k75Pt}xh=x$mRHdXUx~i1bLbl8+p+`WZ<<$1C1wtpBW__E* zAaD}>;>Vzop-)5tx8(292^}TTnZqz*QyMR{^VD^`$bj#=~-1D&A zZT;M`A@9NDu-`ue-BeXVns&eYaqy;zG~|7)Uw;QIbeTutbG!)gS1={rX6Ni9eCR^0 z26nsI?Y6t5*7)VT*T>{BTnv1V^qTd4t8K%FbF5{tK`^*VEnBLsMrwBNqS;;HrCcyv z)13F;p}_r*}f|cL7T;vWSGgmyG){R@o&Y6(N{S<#>!`yr`-*B4LqE zqoLzsU5yDJk-8d=c3z&I@z9-%{ z*vT?I#30@s3m;$72+Ie_CkoN?m>jTJ{yd}6LY^?!nT(Ud9+`{NEC0m;EYqcQLM}k! z+=RgKya-27*3VAO%^_9KVM fT>^ZY?!AXS>|qak*ux(7a0~tcdM6VH04M+eHaHV_ literal 0 HcmV?d00001 diff --git a/testdata/tcp_sigpipe.tpkg b/testdata/tcp_sigpipe.tpkg new file mode 100644 index 0000000000000000000000000000000000000000..2f6e3e7a60edbf0b20296b919f76a7180571576e GIT binary patch literal 1576 zcmV+@2G{u?iwFR`4OLA51MOLRbJ|7__rKhy*vgEZOh-Zw9vxCs6Ce&v3fgIXQ4wOo=}+D5xNIHpsz-rPhmcx47~U>61^cMzk)gfO)F?|a5vU)n6`Z5cQ`po z1a0VF*Ai3Iy+y}LfE>Igeyxj$8Mqwou@eQ`q08qCq##XL;_&H|GcB5sJJ0urf#*X0 z#Z7bAYd2Gz>(2A;b!Wl-+H3VC=&|@0USvDi^IPH{L%)LYuj`goDjJrB@n6AgaESkX z&@*86l;Yez&~OocBJ@bU+izdAJ3v3$)4-=128%}WgTZUC%DPTSt25}o9X@a27;;%3 zG+x4Wvj;qIxJ%)Ed>`O{A(-@Az1MHyO&{uY=yY5Cezy;U2B|lHzP=iO!-M-Fh8ekP zH3sc&2i{z_uEYbG&*!;zCs$u;YIT~MlnxqyS7}ybYAl%Mg4K({*_@H4KhDxk(o8g+?Pq#=S;G)CRu5dzV>!MP=+4M{|;xPUFg_`|E!|E z%Kv($Ebw2cR6gYYeb6HFS4j^4-}1-God zB!}Kmqx;C`<0>#ta=3M<6Y~(?)^M!nic_Qt%8cFe8FMw{C?w}hLe5c&qDTp$NI;90 z%T>l>_5F;7_o~kw+n*o|m9oi*hjT=4>K~j@G<5lrhHoW3w(Ew-GR%smz=^Lu5XvHPE?{%1d(jxpT@CwT(Mk>xme7(k_%uKi$l@w#Ox-38FcTv@ zB@a(8sUK8HFI=CH7T^)plZY~V)ky|4%a+GRefIH%NE0ZthX)UJtK^04`7@OKErH5M z@Bc%(6CGRepOO0hM=#0vH?2eb?}Ikn|A+KjLVp{OSZE`Tn+`=qi?wbV7@g(&%O@hg z3XrTPPgY#`9*n0?mv~_P#dJ%7S}kkH;++Sn$!uhx>r6)vzi;fa@`!0)yi%WTu zf8Fd{4F{M;J6E6vu#)#lCSwuQ5@fRkcFV6h&hp=-%@T~|!)J^V5LO`LkvCpk6JuHg zmBMLMkQW2Lofl5m9C2DWP5KuVxg3$0Dtdo}?2QxDV0J5?R&H2gF}W#lH{ROL-8dAS zHOwvHZ!%QHUnda+wG^65oRC7a4~|%4rWzX^B4A>MC!le9orbd@ft8ECr6Gc!Mws8y ak#e8|9q2#@I?#ds> DiG 9.4.1-P1 <<>> @open.nlnetlabs.nl. nlnetlabs.nl. AXFR +; (3 servers found) +;; global options: printcmd +nlnetlabs.nl. 86400 IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2007081501 28800 7200 604800 18000 +nlnetlabs.nl. 18000 IN NSEC _sip._udp.nlnetlabs.nl. A NS SOA MX TXT AAAA NAPTR RRSIG NSEC DNSKEY +nlnetlabs.nl. 18000 IN RRSIG NSEC 5 2 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. RMppeajhOKtJXWq2HRFHN7fbbBVrqQwyr8uuiaSft48JpCA4QfM8/sxD ahqGOt2P5BvMqVeHz6oWPYrxpnoe9NGJBYCnQ50aipTEFohct9HTFUFu cnk2NoEizMHPWWbQOhVxXaL+sQHZhLR69DIu6KwH9SNu8Dks9V2n6Yi5 slg= +nlnetlabs.nl. 86400 IN A 213.154.224.1 +nlnetlabs.nl. 86400 IN RRSIG A 5 2 86400 20070912141341 20070815141341 18182 nlnetlabs.nl. mpbqSRHxv3TUo+MgzQndhWdZp0CqlOyaIPKFp2trycJ7onH63hCZ7Ixd d4sk/DhIfgzoo8HHootbsYvFCHr5oue8qgkAk9bjco7wWFt9KskturwS RS29p8+jTf4uQ0oXOad0IJo07iccpPyqVapIOHjOFwsFKG1ma7TZQRcW Sz0= +nlnetlabs.nl. 86400 IN NS ns7.domain-registry.nl. +nlnetlabs.nl. 86400 IN NS open.nlnetlabs.nl. +nlnetlabs.nl. 86400 IN NS omval.tednet.nl. +nlnetlabs.nl. 86400 IN RRSIG NS 5 2 86400 20070912141341 20070815141341 18182 nlnetlabs.nl. mXE8tSPoCvD7f6SjQ4skJi8tvbiloN5dlXNHcwufK1rREEVl8oCJ34VV cldL6tv4APj8w0PXmYOiB3xM3TIFpi33n6eqRjudKiq5906PKaj/zLEE cl+dU64+hg9VL0rsT+Fx7TWs/i+gh6oiQm6MsbG415UWUgqtZLflwmMB SC4= +nlnetlabs.nl. 86400 IN RRSIG SOA 5 2 86400 20070912141341 20070815141341 18182 nlnetlabs.nl. C54bDHKC2sRbVUrDOeM2kXCHpJIFu0LlZWAFVFLf4l1Grfj+B4WcXqel kSVhi/Gpt70VW+zDEOHrS0kcE5XaBnrQE1AUZ9QjGyfjXlRzGWYbyVLD evIFrs7FdIeGKKWWp1YDLUHHF+txDT9NFu6KyEqPbZEVgIVok3skO5Vu jpA= +nlnetlabs.nl. 86400 IN MX 50 open.nlnetlabs.nl. +nlnetlabs.nl. 86400 IN MX 100 omval.tednet.nl. +nlnetlabs.nl. 86400 IN RRSIG MX 5 2 86400 20070912141341 20070815141341 18182 nlnetlabs.nl. o9l0WEH53WBdFd+3PE5UHN8kAJVFDb60DcES9oWlBOVwsBMqeTU7eDQr o+wlq1AlUYC+PlFb/W1vLdWN6eCJ//4iPxFJhKoElUEFR+ICPYIIZcD9 VLJM3i4FVsqUwcfgHdOcafciMpMeCgYutxbQDoOwDPe5o+jbynu3gq9a PQ4= +nlnetlabs.nl. 86400 IN TXT "Stichting NLnet Labs zone" +nlnetlabs.nl. 86400 IN RRSIG TXT 5 2 86400 20070912141341 20070815141341 18182 nlnetlabs.nl. lSeFN/S4BATNoC5DG2fYtdSGkC5yxIwOxMH3rChYurB/bD3M4435ySKS Z+vHjLbXQqPtlXw1Jt5ZcVZujRhBM6kEmYZ2XwvC0rPZF0wMtz9nFhxK oc+seBSuP0R9GkbJZReho+JwAYh4F7EC/RQVbHylE1lPAQUHtxCGjmlV EAg= +nlnetlabs.nl. 86400 IN AAAA 2001:7b8:206:1::1 +nlnetlabs.nl. 86400 IN RRSIG AAAA 5 2 86400 20070912141341 20070815141341 18182 nlnetlabs.nl. KGGDcoOAmCby+/xrK7f1b/t/evXfwWgm39VVzE/xButUtPzXv+0htDgO jtUMmouO3GWicIU3fGCffDBCdOmdIrMffjvrR0lKmQAC5JwWPt2FNF/F K7dKh+KrRMp2ruqucpajfvwShWnfesEWaTYWNox1/saLjsw1NXiQ6h+0 2bc= +nlnetlabs.nl. 600 IN NAPTR 20 0 "s" "SIP+D2U" "" _sip._udp.nlnetlabs.nl. +nlnetlabs.nl. 600 IN RRSIG NAPTR 5 2 600 20070912141341 20070815141341 18182 nlnetlabs.nl. cxgMuZWTVJEagjnERLGjnPNZ7JKuyfe3o1gkkjoS1sg+AQb/8nUEKO/A tIoAwqPHWyALjlbOf25mWEIWviYVVt9TDn6d8k4saWNgTdnnCS+Kc5sM fV/Wz0Np/eQRZElBN0fP4QSBv0rk1VjqK1FHnFpSYz/zRV7FqDSQE1nQ 64w= +nlnetlabs.nl. 3600 IN DNSKEY 256 3 5 AQOpbYrUNahQAV5/wTCJ9/wbSM/eV+N+jYZAMmIKn6QF3Z57B6upgcjV HEOyFkA3YcIt5Fz+WqodCrABn4qShd6qJYR8iP3S6fjN6PVpljMjrhsp /6yVc30C6c7P2b/mgWZi5iYC56lkegDs0VGfAW5HmosKjQVoYMjOtNo3 F+MGQw== +nlnetlabs.nl. 3600 IN DNSKEY 257 3 5 AQO6TtiOq7uZa8wHrQNUGT3ZXudaGjnbduUnyLw9WwiDEd8Vy1Ao4FVK 7xqEAFo4F5gOkdGr6Y7Xz0F+Z5e1AaQlvhBhjujvIhPZ5EIuNGkGUbRT YLhVX5OJUHMYdrXpGPdyG+V1TBTmxJ/+OmUdkWiT2J6w5XUpSYRB+p0k YwGf7uxPO/cDNp67fILtx1+dduS30B7QygOK+f7PeAZDcdBo2qsy5rnB sPsLhbEpdpWFs2WPTVo0IGYAER3nG6WZptiq8OYAb1K22K8i+j8+hDwv NRDMjWeVMebBZXbNQGkwsGgJsIsaoGfVOT3WdeJxDu9GqODM//mwZxTv O7StbOht +nlnetlabs.nl. 3600 IN DNSKEY 257 3 5 AQPzzTWMz8qSWIQlfRnPckx2BiVmkVN6LPupO3mbz7FhLSnm26n6iG9N Lby97Ji453aWZY3M5/xJBSOS2vWtco2t8C0+xeO1bc/d6ZTy32DHchpW 6rDH1vp86Ll+ha0tmwyy9QP7y2bVw5zSbFCrefk8qCUBgfHm9bHzMG1U BYtEIQ== +nlnetlabs.nl. 3600 IN RRSIG DNSKEY 5 2 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. foMQGGiev3Lys1fGMfYiHCHnqE9IIzpOFsXECGmT2kPHCRvXWDRcAGMu DWWfCQBPcAlDLZBKCvpUhp/H/VSLS+EA6wonPWN2dS20cDuPWKm3QsHo 6+wQmw7y5t/ejsd+i370dUTjgT40T5bR6nvXZkOLN0DJvaLk7USDRvRg BNU= +nlnetlabs.nl. 3600 IN RRSIG DNSKEY 5 2 3600 20070912141341 20070815141341 36867 nlnetlabs.nl. hw0alVZsoFJqe+u4Meg2VMJ9acbLa85V65RvEAB6RDOqXvaYBhok3kNJ HGR4zq+FYC7i4EKczT7HVKdLtxL9QGt0rzVPq++tcE85861kAgHcLpB9 Iml8QkR7dRER/FpQ1t15gTxoGg6ctlNLfDM6j0x5+S144Rg7gAm1YODB VfL5gSML385EVo2nX7Jiv/Rz1Y6shJ5SzmXnkARqhrJDhQE/Tuf2N+HY sCNatrAv3aNwN0P7a+c99qd5esIb/WVt8eR7cx9Z46nO9GV8HOvfeYxh nMnhlQ/Oy+yG2s2FnJMpD9B4m4WS/m/lBR4pyxHvZR2PQ+/drlJ+oRUS Jt4yhw== +nlnetlabs.nl. 3600 IN RRSIG DNSKEY 5 2 3600 20070912141341 20070815141341 43791 nlnetlabs.nl. uykSWt5yfpz/IN2jKEO+XPtCj9KBFuNWz7vIk+HvEDd+KhXp7vpjISvC tI/xK6yRCeTBIbX6uxR8VRsWEtoKuWwXWHhNmpPBWTGdDuguHOLiuGBn NBUSiTPhideDW8qx/cir6I1MtqypHjEr2w9dn21xdYZbieNXpdZWDLQl ufw= +_sip._udp.nlnetlabs.nl. 18000 IN NSEC alpha.nlnetlabs.nl. SRV +_sip._udp.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 4 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. R0Mg9z4VQHtZXK3xcv3SOZLlibfhJ4nCXURBzvDSn2C3eI1UHvOdbeZ/ B7L7/1aVlho2kHFwjkPI0wGdTSyPqlc3tSHh9Kr+EuMw2wiqtjKqzROF 9hofI/V/PKYCQGBS31e6Dq2Mi5pfeHfxAaBQ8HoFVyLBvj7Xc33aRXGE DaI= +_sip._udp.nlnetlabs.nl. 600 IN SRV 0 0 5060 johnny.nlnetlabs.nl. +_sip._udp.nlnetlabs.nl. 600 IN RRSIG SRV 5 4 600 20070912141341 20070815141341 18182 nlnetlabs.nl. ON/hEJ3zq5J7QUKEMT7mDY8Jj++cYCpTJoFfR/XjWC+JxQuQ5kA5HHoI kI6kABBVK+/6Npz1wof3ELQxvz3IU1jxVn2gwwofC2BNcf+MKRw6aSwc BKcDWRsrQwtMRABwZ63ixobXIUOr/NWBoRODrKQ+61ntPFmwHHCFmfwR YJ0= +alpha.nlnetlabs.nl. 18000 IN NSEC asus-ap.nlnetlabs.nl. A MX AAAA RRSIG NSEC +alpha.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. ntDts9XbX6LamoCEkr7nsEBtqC8PMjsbrXmoZUDggDRKIjAjaqRt3tfy 2QdTdVYcPtG1Tj53RqAXGFfIn3+BfpSvkLELO9qIcIFvmaX+wZr458PV okltp9fX8rm2rirspNlHPNCuZBYVWb9gIRJkg64wnDFC31ERqqF+GS8/ iyo= +alpha.nlnetlabs.nl. 600 IN A 213.154.224.59 +alpha.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. Hu76XqcNZI3IjJT6DwIisVWXhGFP3MCYUTH2XHGwpGF9mQOHX+Jbk7NO k88mwZ9CM3ZNLrDWGu1Z8qhd1ZfgvpxAXshqGBvKhne7Rvf/CopP4XWx QEKcA3Zy5EYUo8J+UBJVm/l5cURlDyj3skqBb+inFpL+FysLKRcQx2E5 Mg0= +alpha.nlnetlabs.nl. 600 IN MX 50 open.nlnetlabs.nl. +alpha.nlnetlabs.nl. 600 IN MX 100 omval.tednet.nl. +alpha.nlnetlabs.nl. 600 IN RRSIG MX 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. YK+H+ugme14+K8H8zdXcB96wI8gNXloKW1IJVBgjzzAwGooqxRM6LEXt jfD9F+ZA8wn0HnB58a/CZ9S/24+grfdTRjUdeTEl8Cbk0ZR5tqVUFLJt MZSXAKczyXWGXZnCn6htGy6diHm+SL0S2Agr/JhsGBBxSX22tTKcoI+i CxA= +alpha.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1:202:44ff:fe41:b898 +alpha.nlnetlabs.nl. 600 IN RRSIG AAAA 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. DtljNKbGwkLs+LtvDeRQEXBUTg/TGFjRdrkxp7HEfx/N6n7fWiRgvzo7 va1py1cc+EMxBO6zC2hegCVS5c1lRjwYuIoA1lSfclkZLQFwwJTfyFVe M/Iq2mE0bbPoJhQ6RAhivD+5Yb9JCqRcKM4B2zlAV2LGKlhwMD/Cq8u3 IB8= +asus-ap.nlnetlabs.nl. 18000 IN NSEC bartok.nlnetlabs.nl. A RRSIG NSEC +asus-ap.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. bCWeNq/W0loWFRQpKPO2bJT6XsEmjfwdP7X8Iz2aIXmHXmfMyNTpFEJH 26vcJJ8D/hMC8zDAKutHWRdcFPwJp+bCg3HJqemLdvzpdSlcGcC/hmr4 zCVLVNWYK/Q/Vq7/cbVWoJTYwVEarwwwATK+Hu3YZFMPOmxoWoHVPaoN bys= +asus-ap.nlnetlabs.nl. 600 IN A 213.154.224.63 +asus-ap.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. PQFBpiGWor6itylbCSIiowF0iTTGbmS1JyH4Yh2tUsexqlWNSJVvIiL5 EYqdttTSRGGDHkYFas8MN6CWXCvTUAAzAyDHOomHr3qt76n5bPpWXNlQ atz+Q2j+n9sqSrqiFYQ2ubAIyclsMetdRNtZxZvo+0Dqcyn42O6cx+0c L6o= +bartok.nlnetlabs.nl. 18000 IN NSEC dhcp-01.nlnetlabs.nl. A MX AAAA RRSIG NSEC +bartok.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. Q7VfSibMW/aRxye7XKj1mxq9tT3b76H7PNuqNWmvQplA05Ad4mlBGrnN +THcTIv1ymE0pWzDR94LQkmQZabCzFpP5cwRqoVb5TwLgJBwWIxQeVMp zzFQ43+jYhlpiPnmzrtBMmG+js0gDPDa4446mMDFp9BapJEG1TYg2Mzl 7oQ= +bartok.nlnetlabs.nl. 600 IN A 213.154.224.50 +bartok.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. J26AYtIbdOrZdLxKSp65MOdbIcMmx+Cty8l9Z0HlsiamAYovhhWWh39+ HqO6H2sJiGXT8dPBrQvvRNbtbLWi2c02WRAtGZt1GFolLIvkgVPGjd0y 0eLJXikN9L7W4j5nspTRBe6GOWIatCg1NwHM7VWNFEsUSZJVNVxBmIVi Dao= +bartok.nlnetlabs.nl. 600 IN MX 50 bartok.nlnetlabs.nl. +bartok.nlnetlabs.nl. 600 IN MX 100 omval.tednet.nl. +bartok.nlnetlabs.nl. 600 IN RRSIG MX 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. kPtROxDJsZMq0XF/sM6tF3MQyaWBPAKGmEdWJ1DAcKwR5GJgBCCPbL4Z poV7NtJwfs0tN+vE5IqdxRu707Px3Omoc9HUJqF7mwu+dr8R4ltMkUGH 4XJpfSty7/4Q4B7Y/BrcJbYduudi4YmwqmO0ffFDJjTjDgJGCGC/DFtE HAo= +bartok.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1:216:76ff:feb8:3c02 +bartok.nlnetlabs.nl. 600 IN RRSIG AAAA 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. HKozneYfqXBLk/3VIcSTDGY3jb3fqQfjvl2yKN3rTkYUrewI5EwSMo4p kXfkCZOvhu24UTuPNjJClCa2eDmuCOJ6uRfHprnF5zVEDOXYdibYSF6Q VAHEi7hzKdJVzk+Fg3BYdxkjzx2kq8jCSF7LAMQ7z1I7eJbpRZ/ORafC aHE= +dhcp-01.nlnetlabs.nl. 18000 IN NSEC dhcp-02.nlnetlabs.nl. A RRSIG NSEC +dhcp-01.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. BhWsjNlZlugg3KMFyaCTK+jX3JXiRsGA7KdKWvP/lvFkBS1nSI4dwwej omkDGiNWa90NGZiBx8A41eqykM9SJNi/+57K6jEKI8X/A1CngK1HxyyS JZyU2sbdSqV7MVERfnd5i7ZbThS5M90G/C2Dr5tJ0pMUJ9mwr1PN7mbj jlw= +dhcp-01.nlnetlabs.nl. 3600 IN A 213.154.224.64 +dhcp-01.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. Q/uN5lccCVcHi/BW3QL7HbQFSjw+9y3kFy00WCxo52ydjo91bPLME3e3 e988ajyZDWDp9BGmIe6lYjXaVpbzB5semGmlpX6ZKw9Ngq8BVVvCIfcN QLEsqzFsnQCa0wrRXqTeBsGa/msU3y09UJOpMBvVndUxjpX7liAMz5Up Iug= +dhcp-02.nlnetlabs.nl. 18000 IN NSEC dhcp-03.nlnetlabs.nl. A RRSIG NSEC +dhcp-02.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. h0JZ2yT+qAnoZc8C5x/7F063grW9x9nIyY1yHVhLHknwcJ0i7CA662jA FxdsEpj7r9oUrJKZEBC/txzeAb//mOM6Dt7xaQWL2JaqmGjRaIVhUX7g zmGTXqGxNr8+SSLwe8+D6h+FJHXirO495bk6fpa2AQNxlraCROV7IdFW Sik= +dhcp-02.nlnetlabs.nl. 3600 IN A 213.154.224.65 +dhcp-02.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. B08kP1Sw3I2JGN9gZ2WOvmo5Kg0dE/9Hu3zyoiJei2Ed8iNnl7G1snYI bBlWqvsbdqxlcwuV5wcwbkgmXsHQbvuSLjShKTyoJglqdMI3etKsseDT 2kBZsxvarrk4fXVlvTI0ICm35tKEgBKT+Nw87z+ZSd/a4zpIToLVIQv4 rio= +dhcp-03.nlnetlabs.nl. 18000 IN NSEC dhcp-04.nlnetlabs.nl. A RRSIG NSEC +dhcp-03.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. c4G82wM8U9YX0ESAPFfjosrPTivw/6Mbqq+DtqP76tLG2Ukm5xxth81w HgUDiOVegTQpJbaHXdwJL2gjzTsN3WTdn+5/ivGUSdH7SUiIkcge2MGZ Oz0Q/iCvDs/1ftDYW9SWaizuNay5Uyg15LCasf4UrVam5JcQtidGiBif l3g= +dhcp-03.nlnetlabs.nl. 3600 IN A 213.154.224.66 +dhcp-03.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. bTv4qvtUqco993fs4Oak+BmAU8CyQhk5XUBXoKzXYN4T8Fto5bFUkYi4 tzlzKzNxQpMpKww5uNPBOjxpyi1fBZDt+qZqrGzFiQ6+sq4G1x8qJ7fm h6/wW2QGYNR7A9j9VGmDmlGL9dOwXkNBGuKVPfD8n6GFF1FJ6HNJLqr5 n1U= +dhcp-04.nlnetlabs.nl. 18000 IN NSEC dhcp-05.nlnetlabs.nl. A RRSIG NSEC +dhcp-04.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. ZquGGtHlQKK+D3CUAsWPPK/pyjtR7QBrrs4OTtEFhzJpkvm6kpYi6Gtf TtMy4M8LFFyslQaMsJM63ByzEf2LjNx3vUjgi80vbl4/dZhBDcegaBcB QBUZ3BUdDihfmjoZk/GvT4ddKoU5l8xGhbeG3qKsfNrA5VWVe51UgwiY dpo= +dhcp-04.nlnetlabs.nl. 3600 IN A 213.154.224.67 +dhcp-04.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. p34f8rWzYb5wQUsk20o+vWv3FfdJ/mbjVoK5zP6WZTIKUMxTAiXihLwB yhgQlOvJKJFT6Q/AZPC55lleZ5h0hE43P6S/9Q9rWRZVUJtrCAqy9xo2 QvRcsM/8VHR8ziehErSGHCSFdsiT6ANNMuO3FC5hBSRLrE8KHO5Aujum 0mg= +dhcp-05.nlnetlabs.nl. 18000 IN NSEC dhcp-06.nlnetlabs.nl. A RRSIG NSEC +dhcp-05.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. fx9KvvNQgkNrk0cbOJGqUAXIKSKLaS/u3zmdaKKEVJH+Xy2UpX1vGHgF WSgg6Cx8vuYu02yRMBv/PJwI5gg5flAXVfP1+GsT6Zd4c+fapUV6BPFc 7YNANu3eRv1kdjwEVZlKVmmZU9TL6oef+RSXZXiF3Zn8n+Cv+fwRIbGg +0I= +dhcp-05.nlnetlabs.nl. 3600 IN A 213.154.224.68 +dhcp-05.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. GHUlG1mfvwOPXrgY8pUBAtDj+InxjGRUnilnnhdeYnpB9ioNgNAmYMtG peRjGl8I6TgC2pYySkIP4kXHBG+KU/BrwcNyHNTjwCtfkWRD5em3nUMX SAlbh10ArTwtDBPuNLL/JVXQlVnXFqWdzONRH7coi0CQmE9Pd0HIdDe8 L1c= +dhcp-06.nlnetlabs.nl. 18000 IN NSEC dhcp-07.nlnetlabs.nl. A RRSIG NSEC +dhcp-06.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. DQcSwxeQL1yAZyxeA0JlRRVgy7NPTvwg8Jblv4eSCj/+hC7MWCNnS7uw syCqo06hxK9cDTppyeiBWFig1+Dd+dSJQF4P8NxEgmLLh2TWXEvPPgFy cd/D4C+Dvra0nuu1QWoEJP/oQrHoxGMiRz5b591XB+MOyfNOXTYw7YEg Qus= +dhcp-06.nlnetlabs.nl. 3600 IN A 213.154.224.69 +dhcp-06.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. N7ETvKemqDEOlcFfL21Un+IXT+cYrANIGOwnw9EZC2V/qyRVU0m2WlGB T6VgCOZyBAL5D7tEEqBHlWwTqdzstL4R05xlrgwcXuIehMlKhk5NJd+H t8lFw5jWSPhAeL5/8AM7fKV2gubV2W219ogzuvirIMfOtzf4hyXOsxTb 03Y= +dhcp-07.nlnetlabs.nl. 18000 IN NSEC dhcp-08.nlnetlabs.nl. A RRSIG NSEC +dhcp-07.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. KNII0C76+CbI1nrRS+TcRYpKfr2jNZ4K1dv9KhGPSV74p4X/HlPD3gn4 B2Gyj7kHGP1t8AkIbhpW1PpT1r3AslXkNoI843/P5XcOIQch4xtgXup5 xMp3gm/WQNOK00zrE8DgL/qnl+zVZBjKYPivuCOse9f5uP+2BAc/F09r fEQ= +dhcp-07.nlnetlabs.nl. 3600 IN A 213.154.224.70 +dhcp-07.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. E4Y9q8xhxzaMHYz9z/2zJm/9GA0mMBIpJENQPOEYTuHA6z17/MZumBym NpuQKmPm89qNIKcSUT3E2Yn/iayPZ7g3B4O6He8FJbv5ZlPXhb+/nZiT POd3gmUGtrGxmmF47u7c+KcMgM8eNS7zLAwHfGYihjbgsW0riTxjzlko 08k= +dhcp-08.nlnetlabs.nl. 18000 IN NSEC dhcp-09.nlnetlabs.nl. A RRSIG NSEC +dhcp-08.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. DWcPcqjgKVIXnko5DR2uwWDHX2nkp66TY1pcZDKVRCxt1dYO/b28CSHB 7Fnr8J5/fwtV5XKriw4VShk5azAphWke+XA3SCWNUmJ7cK0Rc6XcszwJ 02bHFSHMrfT6uxM6qUSOXJBqoHkhw2clVaeIXJSpmYpFsAF5kgLajOz0 yxM= +dhcp-08.nlnetlabs.nl. 3600 IN A 213.154.224.71 +dhcp-08.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. UTP/kGB7yZyh8aRFgomdLQHVGoRU6rn9HuoH1Tbcvu8++MmicoeYyXrs ei6W6lVHsZLjVAnWqistb8NAsHeS1MMy0cYHDqFe+NQl1osk6c+lmXu5 VxRG79J8CLXHR3Nr23HPWFLjZ0RRyrRykQsjdpgBlcydnfRgZ3JrXyXw GoI= +dhcp-09.nlnetlabs.nl. 18000 IN NSEC dhcp-10.nlnetlabs.nl. A RRSIG NSEC +dhcp-09.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. luSV2RpmFyjniakKkCo9sY4ZqgAOIo2k3fWmsZeIKEt7C2XD8bKyVO6v iL/55qSbd8p+xs/W6fvWtoDmlgrVk+e1E47UIu7uthbV/nLCyskwM2y4 ZX9VW/yC5WEgG/bzCKH1AY/ucLdYH4b/hD5IDyhM62ZXAqk/umj5zR27 bQA= +dhcp-09.nlnetlabs.nl. 3600 IN A 213.154.224.72 +dhcp-09.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. pjayjQAL8C2DUDJSSLxT2WaVbcRAObAGU7MCEQO+KK6jnbKpXM1lzVuC NFy6z0MqyjjcRv6bsBqLW22XJicJ8uEJxqGKD/w3RUF1mXaGVKj07z/G DpAH/ZuPeVWrlXrszLEuqXKeFd+UMvWc+0Wmfyu+SbAySmEeBhT0UqUM 2L4= +dhcp-10.nlnetlabs.nl. 3600 IN A 213.154.224.73 +dhcp-10.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. A6M/86z7t0FHkSboB/cXkzI4LduR7WYWhMHk/gPOVlWJkVtz6tl/MOaW PIC1Ls7e6qMdNLZpoKxsUUSnjYplurZXOPsi5rR96gWCuR4IRy2Lq+Fu IuVATPhXeKwexSwxDe2A0Ah1RdcTGQRxA763d2tsxenSbmRgSWZRwO/b SnY= +dhcp-10.nlnetlabs.nl. 18000 IN NSEC dhcp-11.nlnetlabs.nl. A RRSIG NSEC +dhcp-10.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. jKRrUspeXbc+oMTAZxt8C5TLK1PogrPcgIa02XykMJ5r1t/laYI5oXry tWj2S1l41zfNopBmSBGwysDZk67k41lj5Z4Hn9ytLsYzKCaOuOeL8LF0 +R0IlpJKZCZ6EglkyNBnTeXF8XbndoRh8FM6H0OEmftr906k7XQCzIlA WsI= +dhcp-11.nlnetlabs.nl. 18000 IN NSEC dhcp-12.nlnetlabs.nl. A RRSIG NSEC +dhcp-11.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. BbTDena3H6eEte8SjPGF+B8wQxd2Z024yUVPRs2zWfvLeXShVhJ5PbXJ Z8J4O/8iVxidFPWCr34YdJobtNcDZbMNPdfiLiyWT4LChBEAqWNaBJ7d uVDNxoKiS02aKfrKoOhTWgjf4An0FGmDh30Qxj0Mdq2ck7cNAaVAgCE/ Z5k= +dhcp-11.nlnetlabs.nl. 3600 IN A 213.154.224.74 +dhcp-11.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. ClbgLhqTC1EbKUoYJRJpIaQQKvBEWcxoOChOntxYTFw6vvPSx4C1M8Fr uDX40OEO0NO/l3IwHpBCBKrtKcP0mpdnkwcB3Zu12dlUuZSv8Syx3bjE ehXFcRktbh45M9JfiIuhI6kiN0SjWdK59LJzJ1PMGAOwiKjk7ZxBtngg qUI= +dhcp-12.nlnetlabs.nl. 18000 IN NSEC dhcp-13.nlnetlabs.nl. A RRSIG NSEC +dhcp-12.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. FAaeKtLXHurb5H8utLHKy7Y75dgQaE+qzcM8NYRjxrVD2qlHRQb+Wj2E 06He2jnOu/XAMC32Auuj0mllc2ixodg1hTCX2z/HyjM1RHR4dj2ZPCOx arKTpiTVd2J2UUabb5aUQjArlzbq1grIvy5fnkRfP5hBprq9Z8S1acVh 7Hs= +dhcp-12.nlnetlabs.nl. 3600 IN A 213.154.224.75 +dhcp-12.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. hejfyrYuoJJ4kJEep/dD/zjIAYa1ouw27xRj0G1CyTZuiyEmZrqgwPzc SbWcVI23ZoqooE5EYPfr/l8QJj0JHpc0QNlxVa/lC9BGFHIVVlOZkvmf qYkxBw0AZPzaW6oa7xA0aYHyksLOwAnaVD1G/P9k3TcNceTbRTJTqvIK 0QI= +dhcp-13.nlnetlabs.nl. 18000 IN NSEC dhcp-14.nlnetlabs.nl. A RRSIG NSEC +dhcp-13.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. NpHGV/R2Nou9bOLma3xNhFYFTs0iFC4ys/pWuyizz8YmWB32/oJCQ2wK kruitBPuEna3AuYtT5sG07AO5e4ueUYXYG2vLSUn+j6JrneL+k25zH2Z rLE68W+J646iIZZ5ruKraJ2Y28J8GZzArshwFwR9oRi+0iM94jdspIV1 qpI= +dhcp-13.nlnetlabs.nl. 3600 IN A 213.154.224.76 +dhcp-13.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. ZKDNqZ1I/d7KnVUnzakaPHKCj2A1Z8W17c5diDVvrWKeudgeHBM+JD+9 0bfAHH4gbgosKANNTGXA2cpUHlDlJoADhUX5sfd9+l5amxZAqLtC+QnX hea8LuHDIlMQQG66hsX7qvvzVpD1MuK5newEpJfKVUeKHbp+tFRSLGCr u3c= +dhcp-14.nlnetlabs.nl. 18000 IN NSEC dhcp-15.nlnetlabs.nl. A RRSIG NSEC +dhcp-14.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. c9mU38QvqETEs/v1y0RSeNhP3XELt2dhm4m0cRrYHkqxEERwt9NSDx9n gL9w7xVhVcnfzCXDzIfumqL+ZCjEjavMZ14X6a89CD6lGM+b/dqQoMzw ijeOSTJ6hq0p3lZYS13NXjUaQi8jwCeFNb2q2+TDhF8QPzJrW650Z8IB 5v8= +dhcp-14.nlnetlabs.nl. 3600 IN A 213.154.224.77 +dhcp-14.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. qUR/vpPkDIEQAa9L+a3QilfzvjYWti3btPUdal0gQD1+hmkMlFOI5wGO aaKyDU6GSU8F/i9VmRs3nuggKWVLoG9PJwkfZoDiJNlE81aZ+sKsGE1b AL2Hw2ZYqnUT7LDtzWt/TslpJcpxS0usfMfQtJN8E8iC7kcFEsCcLtyw z0k= +dhcp-15.nlnetlabs.nl. 18000 IN NSEC dhcp-16.nlnetlabs.nl. A RRSIG NSEC +dhcp-15.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. lAzCYeVTtrmNilOU9SuymQSyziT/qysJLtf92jY1/u9ZfG0wHMP7HE1n c2k1r2yCPKvjnJbNYEgYZJnjUhk8HH797TWkWQXY1dGJ2Vw4fPeXiB8b qH685V5i4fSjWkW6bk32WqdkpkWkLs1P6lzfWq5aQg3csQRWdOfw3HZ3 6NU= +dhcp-15.nlnetlabs.nl. 3600 IN A 213.154.224.78 +dhcp-15.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. k9ji4tuqlojJjFKGL/jlpXZDfEn2OUJYQdu5VJOI9vlGVcdKlL/QMERa vLweoleRNTdu0/Tt27caz7TrG0KtLhM71qRS0rd9X8fmGkO2PpxbvuJW yFjY/ckv22Y/K0sKn1zCf6/o1XxR2Wro6D6+V/u7KLYnRm7aVa//D5ef zfk= +dhcp-16.nlnetlabs.nl. 18000 IN NSEC dhcp-80.nlnetlabs.nl. A RRSIG NSEC +dhcp-16.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. e1rPfAwWPq9LBn2AXGgw43W8eO7K/VUtKvnGJ/ennRKlfJu5vsqDnhje zbQh2PY33jy2LUuLdGv9H3Ba2Hf4i8skK7YjcXI0yBMmWLiBHGoiF9i1 oD55Fpk+77RLJp6XU6wNDodsNGa83zsAfxdySrwy3USNAkIn3AXee5l7 4OQ= +dhcp-16.nlnetlabs.nl. 3600 IN A 213.154.224.79 +dhcp-16.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. g2qWzNzrbjlZVTGwj0ujmOGZzMmRZ0CNMZbMZVbBrf77aP9Lz1VgDvGL h9MPpBvdk3JanO/xZL+PY2Elkj0iTFGP3uRNteywdcUP2/Xx3nATzJzr eP5mIDZYDKiAmkoqXOLhouWXQ9j1xAJ2uinslw0ZefxaOF6MGpXihdos EYc= +dhcp-80.nlnetlabs.nl. 18000 IN NSEC dhcp-81.nlnetlabs.nl. A RRSIG NSEC +dhcp-80.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. Q52UtKoSAbaBFrJmT6SH7fHzg2W1HK3ybH/s/sqJSyaqZbf9pZQRopL3 ryiXMX7L4eGXWr4tOuOdVf8j5EboGEJfKDMRBZeQXEgEYw7VlCC0t5dP VALFQP2NKtYa7yZ9rXe7Ua/3duo7ydGpv4/acT0wwNNcW/Risx9pozH0 3OI= +dhcp-80.nlnetlabs.nl. 3600 IN A 213.154.224.80 +dhcp-80.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. HWdpL/uE9hV1FUjMSotBWtTlEJwT3RR36LcTyUa7/VHeL1H5Grq5QkxM 6Mf1Wv4zT9tjqTouDU7vkGlDvh9JN8eW+MIcV42Sugt27F+Oe/MAP4EW heYUF7Ez/7oZ6RWcq2I3n30x+qK3ehfwBNBfMchyPYEIqRIzWwyPVNjF 6c0= +dhcp-81.nlnetlabs.nl. 18000 IN NSEC dhcp-82.nlnetlabs.nl. A RRSIG NSEC +dhcp-81.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. R04Tz8a9qYlqNg6JPzNlAl+xGn5CGL3qEHJ6AM1C5uwZ9NU6vYdStNbp /gU7LJlMzcsN5wcS9V3dBsAap+P9awL9TUiPphlJA2O/37VL6pr2GmFF ZAKmJW28YN+dbqfeeiKE2mz6J+ZYcumlO5vPr46g6QtRf0pLFVkVlo12 TEE= +dhcp-81.nlnetlabs.nl. 3600 IN A 213.154.224.81 +dhcp-81.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. N6lkHwdgk53nhMoHDT/7cWhuybmHPMDZWPFEdNjnoStic3o8zlAOuXZ+ zucX9S6Pefw2fwTXlfxoAAs5TGU4WCY0I2DQszSDcj8polwDY5SJrJDJ Veu1lXXyd4iBzhZRww/VLoBmf44HLbB0kZ7ZbH+xlmwnbkRZ0xR+gvLb XoI= +dhcp-82.nlnetlabs.nl. 18000 IN NSEC dhcp-83.nlnetlabs.nl. A RRSIG NSEC +dhcp-82.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. HLiIvzxeEKcJF3NHZgrY1EhnZ+91fdLmvqePzKi7RDJZLxiTsCCdET17 FdQWRX4zT9wMg9WhI0Q2jvacomj1FGaW7jOJl9iEhPNPmy+O9HogWmE5 BxICgAkOJzX1SATH1tQnUTgXMarmmZd1YU/hc2mxM+Xtf5g6xs6VXotK VKE= +dhcp-82.nlnetlabs.nl. 3600 IN A 213.154.224.82 +dhcp-82.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. DhGvag9N4qTDfV2PpZmmDDwSkDx7QTrRAfH4SWU/fM5QYAMSk0P8g/4I dWDRL3BxAvvVNzfm5ATOEe+Kq+xNLDKAMxxRYSbaoeLQtEiRai+QUvrl YU7rgUpszenfwi5c5aVYeI0YvqC8DgLDjqIxcJEqvsi4mbWFYu2u4oJQ B90= +dhcp-83.nlnetlabs.nl. 18000 IN NSEC dhcp-84.nlnetlabs.nl. A RRSIG NSEC +dhcp-83.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. E2z6O6f4AHqXjlFaOMMyG8Xy9tCD89jgAmpioIqgOB4J/HgZHSzH0xi1 8XjNILyvYDnfjTDEcxUmfPHKBP8u7ngS6dKbKXT4+O4Q3ZeAvYUs3m5v h+U+2oOm5qM21k4CEIQmSSUFVqU44ASry4TbiT+Di9z2iqLDW17ajyr3 3NM= +dhcp-83.nlnetlabs.nl. 3600 IN A 213.154.224.83 +dhcp-83.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. XNPiy0sSgZgQjrq4fcTpxkRiHI8V6N+twVL1Q4A+3oFbAv4CLrvWZBnX 0N2cagdqFhLLtWNYxIw5P7wrZF/UowcxPa2KCr5DyDpo0JfNWR9En38G +XvV/f96DyR8LDnlfoGb7/PeopHnNP0W3sl5jXQPUBfZe6A1gh8Ph0F2 yzg= +dhcp-84.nlnetlabs.nl. 18000 IN NSEC dhcp-85.nlnetlabs.nl. A RRSIG NSEC +dhcp-84.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. MfJPB+IQxZs2N2x6qjCT3aJ27it8asZedsMrRii/6ZEvGJ0QQU5+x2xl bh3+mxRxbkTguk4Rf6ZPbbCwI3qa3ReP+V0GQTVFIctNmAV7OCreE5y2 svobwBThQp5Ue7U0l4w2u6r2kGXVISipYgll3rp8JdvhD1bs0HC82qL2 WGY= +dhcp-84.nlnetlabs.nl. 3600 IN A 213.154.224.84 +dhcp-84.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. KSgsF31Edr0e7wUJEaUGE1OzRU862UXlSISgmqyjLyqrR6HqyvtVAN7E WWz22LNwZdEKUxqkQ3EFNISGxcl0EgnIuM+1mnKNiWGLZY4gcxv9gyxr dHjtJC/03rCfeN5QDFqxwrZwRcChiyXt8sHDM5t43fWjb0bumjkMt0qb tBM= +dhcp-85.nlnetlabs.nl. 18000 IN NSEC dhcp-86.nlnetlabs.nl. A RRSIG NSEC +dhcp-85.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. HMipwg278ezTwQ7XW2SLz4rF+QVZRMPwVrxQ3elO/io0juBJLGDiI6UX GNZ8HeoBVLKR+EbXR0uzHj8Bu/nD/+5463CXWFDRVH26cBG8ppkD573v H8kkAsf1NBMSPvmxsnk100vfgInjsdVjbjPViVmq0MF+SUrfCDK3UwGi Vz8= +dhcp-85.nlnetlabs.nl. 3600 IN A 213.154.224.85 +dhcp-85.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. fdbeSnzQ3oDiuT6+h654Z9Q4Ap2G0SNVGzv7fICz5cTW6ofkHHgRGpsl XmZnvHergU4+mesbBsGOq6mQDL5lFVuQpZkoU9U+ZsDTVa4IOHjuxv1Z 7Gq6ipR5Tv/FnJwkxs7IR7G6iikN+cRfWau1b5qfJbjxcxI5IaxxVOjn zGY= +dhcp-86.nlnetlabs.nl. 18000 IN NSEC dhcp-87.nlnetlabs.nl. A RRSIG NSEC +dhcp-86.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. ZiLXpVFO2a/xUFHr+lCLD/1WxSDBTzyfu+m5KCT63eQMyjetTqhic1xo o4Evww2ePf1/WMoUopJ2ho0gnrsNv6fCRQY1apXwPE/5NW36PZn3h4MV ldlSYx1ut/j1THjNf7QxL/Rd+mcixrYcRAByvn2edfrhU5wuCfybI3MO 3/A= +dhcp-86.nlnetlabs.nl. 3600 IN A 213.154.224.86 +dhcp-86.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. f7O7tH/gA1WhQ/EOEAAsyXpEUH3+XEAC1Kmy1F5zMF6TFB4ynIrqiCbJ Xvdl1AN+WoEClK/bJ+Y9gLjRHzD/fYGSuO1wnPjJRD6WGynVtaYEfSal ly8UHRuywvHlKV4vL6YQ+z/FFegMb47WCvmEd1Gu3QvohyOJrz/aS773 gBo= +dhcp-87.nlnetlabs.nl. 18000 IN NSEC dhcp-88.nlnetlabs.nl. A RRSIG NSEC +dhcp-87.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. n5zIChy2yTS4ulHqNe2/obbF+JXcKWMs1DnLPRsDm6BaXRjosn32zrj9 P0hoQJNOQxhG8f2xKO+3jYoDXMLKh6qOJrjXjUHeaBBiuj5kxU/EUJRz YspUKC4oEFE3KcA5UNL+siRfdMsnAD+fUVpWs0msrr+aT+rAIeZ44r+B HD0= +dhcp-87.nlnetlabs.nl. 3600 IN A 213.154.224.87 +dhcp-87.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. c2oRlyKG9hDQ+WUdBshyeKrgBNmeZQi/WTMaWMN/F3iICYGOd3NF0JLd ba9LqpY2BHFvA16y1LfVFY/3aRlmFqp/r8GZcdODyC0UMEf1nSY/gILg sLWTdi3H2Fk7+64FfpUu0o5WaDNWQKHz2lAyDU9h403cOQbaDKh5IIMH y0M= +dhcp-88.nlnetlabs.nl. 18000 IN NSEC dhcp-89.nlnetlabs.nl. A RRSIG NSEC +dhcp-88.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. EeWOJ4JcjbHxB4qu8du2YOa3Xbww9v6kIia88YCJLfRviaUlSqXxkrdl UOj7HoNWMMVyTAAT+Zc5zGS0IZi5JdxyAZyfdC3mwto3asSDNhsT1HZA qpHiOQIXoT/+yPLgYLtpBxafgiPzLP+V4yW+Q1ZmrBj9jZa0+WILjmHz qv8= +dhcp-88.nlnetlabs.nl. 3600 IN A 213.154.224.88 +dhcp-88.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. SSdcAQ+8Dpuc+XfIK9R9vhWTjkOabSrolGYzCvrjSnSyTQQbzNGgLOr3 SEt1XOCEKQ9p/uK+MPvytuJhZEIJThhE7umCJ278+q2EfYHvtc22gMuc /S9b1QpX4iwUNmsJRbSFhfhW7huL92kEhwh2ABUwjD5j/wC8DDLKGJdn bvk= +dhcp-89.nlnetlabs.nl. 18000 IN NSEC dhcp-90.nlnetlabs.nl. A RRSIG NSEC +dhcp-89.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. nEMoh/PDePEoGN8sqX8+cwzViqGADytqVQgsUjD/dR/rpetLAo+r2NKg mAtRpC0lzF5AMFgqheKvqGTyKFhiiHUCwL2JO6xturvGQ88BiQLku0Dl IsNHRqrqPbRdCsMnnh3dFgnlt2RgY0tFAlb0QvtUFS4JFLeZ4zrE0CAX QYQ= +dhcp-89.nlnetlabs.nl. 3600 IN A 213.154.224.89 +dhcp-89.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. S1QrqU8nF0wHHwkyJDTNz85WGwEZAqK0S3S6U8X5o8j6t6YA5shoqRUg HNNG9i2T2QLAuFDJ6RFKTuC2NjaTtuMlKOJN6eOUBDG7r9JEkTDj79jV EDMjjXOBVhG4DVeughfwSdGX20o/CEcVsD7w/cuG/h86tloLCdAxXf+3 xXQ= +ENTRY_END + +ENTRY_BEGIN +SECTION QUESTION +nlnetlabs.nl. IN AXFR +SECTION ANSWER +dhcp-90.nlnetlabs.nl. 18000 IN NSEC dhcp-91.nlnetlabs.nl. A RRSIG NSEC +dhcp-90.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. cPEmnWaQJQflV/fR1LTiDn+EfCm9PO7DoIhjvr35dfp9Gx39OJPf5Fnc 4NC2Ay0gnfiJ8RmtWsd5A/rg0HYDAOqI50oHjmgBPjBaCDyclkZdCUdH r4wycksRf8yUWyrOc9EZtF7PekY8Pcd0HtaXG2eWH6h36qPZcuDDZExV ONk= +dhcp-90.nlnetlabs.nl. 3600 IN A 213.154.224.90 +dhcp-90.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. ZLV7Q/fuq/lxC7NuoSL3a8kkXnbvno7cujDLdqjNZWqMBWFe06GKYyFa lDQ6UDhKOOvavGJaY0dA6k+PoSzoL+bch3Ro+56/8+hNOGL33LDSiycZ 5X4bF7ghW+ggvrGCPoomICfoNVOKefHRBzKGBm6C8zJKjggb4FbDFeh9 DVM= +dhcp-91.nlnetlabs.nl. 18000 IN NSEC dhcp-92.nlnetlabs.nl. A RRSIG NSEC +dhcp-91.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. cJoIQjSfnuf/OIJXr+IQqHC+fl8bXlHrFEQf5PvdUgmYO5lx6HZ9FB9h dLuqDzLdVzPjf7ncBxiQrt1ng7gySAzeBqjezrTm9XqFoTXyK6W5SASC vSmAx/c8yHCcqsNSIWQWyo56VCF+ampF/xqVRO8xmmJP4EWJ49VOMOgt Smw= +dhcp-91.nlnetlabs.nl. 3600 IN A 213.154.224.91 +dhcp-91.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. DlSRwEHWgHWe+epmbdI+bo2fI3K+jJcm6plDXxy4b86Uc0wU25QMMbnV 6ksrJ2SAAXUzcdruJLlpdtdnZk6gX29w9KH9OTyIDDi8+Pkff16F1YQ/ 2WBrCDT/ogQFD7hLpmu5i5MuBSxblCigaQy1DWL8ZQLN1uIg+PIOG5mh j20= +dhcp-92.nlnetlabs.nl. 18000 IN NSEC dhcp-93.nlnetlabs.nl. A RRSIG NSEC +dhcp-92.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. YqjXuYbOomBjOwFVVCv7tg0ofoHrrvZRGmt2QNTHzuyFyvm1tVlYauF7 xHpTnFsdsKJMkWVNX1U05O1+gXI7mv7CiJmwk4ixap/oGNc/qT5ziOMm mEaW+HbD6Q3bMrb3/n3M3dQdU6aSHjKi6PAeqdu8k7101jb6qwJyKih7 cyg= +dhcp-92.nlnetlabs.nl. 3600 IN A 213.154.224.92 +dhcp-92.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. JGRsNgN+pLLGKqTkPRgGpP7wthjinjxS5aEI/SzyqYJ49jn58gLvUk02 j2rrC4zi14X74qaVg6Rqk5iYEaCnDD8WFF3rrTM2svyrxHtL9WooXVKD meuZUHo/S9em6avaMaJ4ATbrLRnyesDwX9ObKvFPqIB6ngDL7BEbdMcw FXE= +dhcp-93.nlnetlabs.nl. 18000 IN NSEC dhcp-94.nlnetlabs.nl. A RRSIG NSEC +dhcp-93.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. ghKndVKwVwB3GCCbB05AQ+QHErd5hDH/eThxntJzD+t4XwfE/ba7w+15 R3n/rCMP8GZyOXIu4t9qRDuaqyx0Z2vnSDXVie20qilq+liFuSJc08oI OhD+TTUTfc3JeDFSq8966nE2iDOlga/0PlQv1J2ZWlHy6GW7uG9+erCD OQw= +dhcp-93.nlnetlabs.nl. 3600 IN A 213.154.224.93 +dhcp-93.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. OxOLXxd9IyHhfSZDgH6e3Q4kmu39n/STAFvveQ7lzrzABIiauIHqy2oR mteIYUzy3fV+C+GogeiowA6c9JROKzsU4DQHERP/WGM2TyYGVHrH+vuo FlkNEVUc85hbVySwXgjJDLo3megI0HYatldTNYt5I90mZOgUg7pSpLhG Wo4= +dhcp-94.nlnetlabs.nl. 18000 IN NSEC dhcp-95.nlnetlabs.nl. A RRSIG NSEC +dhcp-94.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. GiTajmO7Q7P5D9RSjFthAjKb3VFaU3IsEi1WIa9SdDCCgkweHh+a+42V TmbsSUxCEtHtHcutgARIoL1fghxAQUE0d0WPaOHlqsKXcIlOqFGe/uHF phydsYuyba0k5KwP5KQ9vpj55dUHmvE45EGpclooon6/j+dhYjlV15Kh MfI= +dhcp-94.nlnetlabs.nl. 3600 IN A 213.154.224.94 +dhcp-94.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. gMEfCCsC2RBehO29NobegN3YbUmPE6aml7dSEhVS2vzRXkceZ/kCDn4n yXkbBJA6WhZCR3XjIN9/YvGdCWS7TkbzebQC/btbEp1n0t/yDhjzyt8y 2waiIWM4ooehjyKRtr0B6GXv0UolSzK77JzHVtkaNOkNn0WJyLfY/Xyc 494= +dhcp-95.nlnetlabs.nl. 18000 IN NSEC dicht.nlnetlabs.nl. A RRSIG NSEC +dhcp-95.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. Fv/xwiUB8s25tD6FRSiaSHpO34hpxPZCGSQrkqExl8vqKP3B3dHtIcCX SiA0u22LlkehvpkoHUWzIhjRK2I5MslqHSzN+ZOmf2FNZd/NJruPPwVz lAjRn3pKQkOV1iqQBj0DlxAsTpI5r6a0dkPRcQ+qKs96xUXY6g9fhU/C pjg= +dhcp-95.nlnetlabs.nl. 3600 IN A 213.154.224.95 +dhcp-95.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. g9TfAoDLV1A+FXaLFU1pKxXYIk3Jy9nco8uvX6eR1lnuQkLg0ZD5Kmbk Yen8BuqlUDe7Tn7HFQ9/dq4y6eFXyoVi0ysvRw6E4P0yAwKHmvkqK0Sp surB64dt2MWKMekaXas8MTgCiwe6FkSutEO3/q64yGgFZcfcLTOy+8w6 unY= +dicht.nlnetlabs.nl. 18000 IN NSEC fable.nlnetlabs.nl. A RRSIG NSEC +dicht.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. V+b6TXHkfPt1DpfJdeQLIqlfyaev6ifluTkgA8rYA1ncehDH4OJtWg/a ChZBy8Y9LMzkQMFgqTBGjPlkrE6uzOlBEfZNAP+YA920KUZ84KdFutfL 0FYYracWonskOMdQvdbZNo0pFz/3OZr/9123okc/dCVEA7tavWiBfsBZ o9Q= +dicht.nlnetlabs.nl. 3600 IN A 213.154.224.250 +dicht.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. enxkeWL8VC9lsXjBnqCZt6BrONS/W6WzNhXJrhDFf/LBZTRdb37MgnGH fCBRqgKn/HozKPKAFtZiqsXrlsQ86P3mzlNm4IUpaj1v+y9syrFOjkyx 4/osLK1CZZdSEMUqROgoE9DQ+UdSJmKto2oUNxjidg8Ewlb7SDPXM/G+ ct0= +fable.nlnetlabs.nl. 18000 IN NSEC ferret.nlnetlabs.nl. A AAAA RRSIG NSEC +fable.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. p7JVmo3vVvAmgXLqEAljzKxhacRC6/T5r8SwF+t80zoEDTSTnS7wTmcq K/nXkkxUcQv/9fJAC5pZaj4karJURQ2q38EExwyoJGMgUvw7I8wzGZ/k /NMahGyGJLZf8hbcb0jLyvpnnq38V4DsQfbb9CcifcwmJkvS6cgHU6AE aOg= +fable.nlnetlabs.nl. 600 IN A 213.154.224.45 +fable.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. WWnxLKqS8bZ3WnJfmman1E9Xx+JwXM2/UVF78YjCVqCV8RMT6W2fzPCt ylgCAweIa6aG28hEGzPHCiWlSvQUs+cd2wUWbdDiVwle9FC+Vji9Iszs 19JQy3HEwiuZ4m3eapgYia+DRzJnXg1ZWaFgvhb6IW17DfHPVmcYYHku eQk= +fable.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1:250:bfff:fe58:4d93 +fable.nlnetlabs.nl. 600 IN RRSIG AAAA 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. oOKls8T7L9tx2AqgyClKIcFquXD6aT3NYJb5ZA3gXGp+cPMbvnfixilu pD7XZF2i08AzmlOxHpd1zNw0jp3IMKebQ5eZcIV4kIyyuY6rFovJCmxW ECcLumjIKlyxb8h3Qj7KSZcPH7Pt0yw/czluGD//5LWA+/7gg+itwk20 2dw= +ferret.nlnetlabs.nl. 600 IN RRSIG AAAA 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. CaP8AdmTbja9YXpxnJfYsLWENSChjjG899PVPoluvQYXbfrLcb465uXe mp8MI03nySvo8786wGe++Icj9bXOzeP7zfUSEPW2UFREd3LsjvZB/wdu dfOApQcWBLrQEvD/++EGgJB7idf4cgrkovtW4elRWFpWHY3GQLCvbjGH UYM= +ferret.nlnetlabs.nl. 18000 IN NSEC ferret-e.nlnetlabs.nl. A AAAA RRSIG NSEC +ferret.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. FF69Elwu+M4nDJWr+f1UwyaL0UzAoorPOhZ8AZr90uuAeDdhNRZ9fdPj qLb4qqVj+5bDNFS4oxYyf1RZyMsHJPPMwi9j8STFh3uTa56JLSsK8zby CSc90Ik8ipnB/5fe0DThnEHzqGzujuPpX33pTgYd3+OHJCiCsTTJH/ml Tqc= +ferret.nlnetlabs.nl. 600 IN A 213.154.224.60 +ferret.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. QEZ72Z7l0zhUNTn5IqkoasFWSuV/cRasyTw3eFC/B2AT5l+0SQT1AlRd w1WHKJ+EcCeVdtujX4TbWgSfNB9Cwc90tLvWPTm6bq6WXI+LpfHEPw1m Vxi6dZAjncKN6S5GKYmovpiiipQgpA32vjc/52Ptzep1VZuFIXvHYesC 6kc= +ferret.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1:20d:93ff:fe86:918d +ferret-e.nlnetlabs.nl. 18000 IN NSEC floep.nlnetlabs.nl. A AAAA RRSIG NSEC +ferret-e.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. EUhsopQYSHZgNW64CNKUOIgJ3o8NU+EhCXoG0GGyvBQSkUOUAdqzMHJ4 wWXvigqPxpEa24mrMZQKKnHyAq1B/cB8Bt05TCNblOCcUxrDATaUYtOt K16NFIGCmI7gRTt5CTKKjMDrVpH12uDwISk7h2MGCvYVnsA/NN4Y+4BV k8c= +ferret-e.nlnetlabs.nl. 600 IN A 213.154.224.61 +ferret-e.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. GDL06fR5q0+YsaoRcBHzNZHgZ9GRpIGFQyTdwUQLWGIl3XeyZgiMVU3g w1MNDk1TM/UtTOLgUDu+lG2QJEgRFadU43F2ubcSVrL1PahAoN7Gou7N JlagBdgXE99gi2UfPeePBwcL/COv3U8aTSIiEJ7WVODSVtR9l0PCZ1m9 bfU= +ferret-e.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1:20d:93ff:fe27:ff66 +ferret-e.nlnetlabs.nl. 600 IN RRSIG AAAA 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. Vt9a8m/XSjOcDurL+0H8vDFRXNsSlTgUVlsxmxQoNnw+2O9iA05i7UUl f2iubmnvgUmBpYa8ILp0FHGD6cyqD/O/wKKNpc4W7RoLBelWAwDVrhx/ yx8j5XXr56ER6XjoPPtCpNVNRvXPZ980VQr7HoPzbJWjOCAUovQ4YONT Ny8= +floep.nlnetlabs.nl. 18000 IN NSEC gary.nlnetlabs.nl. A MX AAAA RRSIG NSEC +floep.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. K5r3od2Qo7nQwgnggvuTpQcB+NX5nlXfFFVH9TRzlx3kSupiEROO3YUd GXtTBl4fw9vDimo2o/VajENF50d0yU6aqfgCHhnjL7rg+pWPbyY6w02M c01/F5RklmwPCiynHebJ/RGXWSKFUi5/hNKr0LCIFae4YydPNUCHyivI 04Y= +floep.nlnetlabs.nl. 600 IN A 213.154.224.37 +floep.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. pmC5tXXZPnc4Sjfmcn4ADpuUbTdKAx9wIm5hflE6xCYnNGNCCY2LZDBh eggJtjMTsY30a7/ziDCwMiG9LzPoUo3cHURV5vVwSfiqMFDSyMrNxYQU aSa9tl+TdP3pxuGG0MG0MykM0CwnkjZOG2kTtd09pNYgg//iuD7UnAp9 6pw= +floep.nlnetlabs.nl. 600 IN MX 100 floep.nlnetlabs.nl. +floep.nlnetlabs.nl. 600 IN RRSIG MX 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. Ix/ol/iR+Tp70/bxUifh4FRu2lK8WDpj6aGyNFyzUrpSQH0cs5ZL+Xns S5fnhmGjkCm+6WCSr6oT1ncKqNmztwKBXFfAjkLQK9iynxDRC+j/ERuv OfxIh+nlvZ5pZXDIOJx4qzHSGZYi3D4bDL0otSjJjXG4316nzeeGIbFG c6g= +floep.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1:240:f4ff:fe37:7af9 +floep.nlnetlabs.nl. 600 IN RRSIG AAAA 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. SekN1WZszjlLSrVN2FFkRGSB0MVcTfsX0GEMn9cknFsA5hItnty+0rlf A++miOFdb6NbxNaoCSBLA95eldnEBkTOy3hp5rMHdQpjUxuzv31z3Kc/ tsMFBajyv79SFWibeUxzwS6kdgabO+yA8EN3S3be2f7/+n3dRBYpxxle cm8= +gary.nlnetlabs.nl. 18000 IN NSEC hpr.nlnetlabs.nl. A AAAA RRSIG NSEC +gary.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. k1ylHPSUOzCI+8eOhyJi1RVtc0g6SB+EqDEi0e45fsBh3Hsa5yr7/bua aK3NUI7OHRVjEg0Bs27UmNTrfzmNpFfties+eh5QTbtJ32DqQzzKCPPu CMfGOYVOqUrSVqAuYDLq2hVQwTLtvV6u7Dc5pCDE2RslGoqhL6BExdn5 0wQ= +gary.nlnetlabs.nl. 600 IN A 213.154.224.58 +gary.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. FElqOEtxgXvbJJbXE4e/0i7w/tCCCT03SC3Q4AJZ5wzhjyUBRMUQ5fZ7 Xa2YFUYtWvtZnuP74mIHc1mV4lUpGwT3TbXOVqCX45UaIA9GdEoFDeay S2vJbYRrdJewLGJHb8uIqFi+8MvGQWIm0TcCFd4s3CEMpoPASe+KzO3p ET4= +gary.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1:216:76ff:feb8:1853 +gary.nlnetlabs.nl. 600 IN RRSIG AAAA 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. JiqXQWJj/xzn9NopyM+M0p3EVdg/QuQZbZ+o4bQZ5JWHFvwzXSkjjR6u SDmObQTJCWVmgFvNQav6Y6Xh28Vgw3wO7ut5i3VOs2T7GAF5Ezr2tH2E rPP6NjgmvWgYwNSDCDuyzFIunNocVnUHt1VMk1FpfTxD3IIOY12UBWhL wuA= +hpr.nlnetlabs.nl. 18000 IN NSEC iii.nlnetlabs.nl. A TXT RRSIG NSEC +hpr.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. aS/em0n3uWpObWr73TyAppJfzVBBqsm3ItqrejZQwvPneUbf/VFTcRCn Rrkr1MkRpGHc1EKe4UOikhc/BLh3/WSlKeAHphVb4FxOHsik1gA9mkWN GgczZiB+iJhoSvXCrB548DcCC3kWRM7llz1GsbVfdJMlMu76G+K8j5DU 4vc= +hpr.nlnetlabs.nl. 600 IN A 213.154.224.35 +hpr.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. MtNG5jmsGvikF2+8VeM6YmtjtdwyaVtlYp2TOnhf9f/DnwGbHF6IyNp7 e3UCGaVSCe25nO3LXC8Bd/B/vXDrKhlvwdeLHnQttVC/1FukNySWLoIl 2TQMo+awluLnvndbSqinZat3IJwy7V3PHTTJByVagg6qf6SahBwPaxjG 7L4= +hpr.nlnetlabs.nl. 600 IN TXT "HP LaserJet 2420" +hpr.nlnetlabs.nl. 600 IN RRSIG TXT 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. emQOMgaasP6+meaCM7LWQA1euf7K0cKe84pKOJj5wh9ZcX+gIpORsTlt o7wvqbEq6khMRNkjtyqxaJW06LBw/diXtPqpwNbl+DfEXHmtU/QRoJzm tpEBaqZbmBcWXjBZeZJ3EJ4ZLxl1L52JAwOtW6FFtxDzt46pp5mB2DSZ P2E= +iii.nlnetlabs.nl. 18000 IN NSEC ipdns.nlnetlabs.nl. A AAAA RRSIG NSEC +iii.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. ASgNY0oaCiUS8DJVzRrPlF33EHjAnYhyTfFjXIUqxXraoNhMba1qqgIS AsBUAbaGfBsxl32lbLMvb1utYrCUtfo+ZMxjpr1EK+KhD0QQoudVI7Yk o60VHl6mrsZXFlJ2DBm/FLYbkMbhJFzI7DLLsRN2vQsCeOTjPHcSw9wi 4Yk= +iii.nlnetlabs.nl. 600 IN A 213.154.224.1 +iii.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. UjvIGM54znUgTcuEJmR/e8u3jnmG1LM/+3JLZmzDdvNMVnW3n+K8qkEz ERWJwW3V+alkN2Rl+udErP8I7H5lB5YmtQDeGnZwiu4k6f/J3gdmNrkx MRpSnEtVYeNkajjPb0xX++7emchkeSydAA/Jt35cEEaMZwvWXkzaUyI2 MYM= +iii.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1::1 +iii.nlnetlabs.nl. 600 IN RRSIG AAAA 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. LzM3IiVN+rCNYAHM0/9Hd2b8q9gO1NeTxdIp4YVnrQqJMYIR+cwmJ7ie 6s7L4tlbbPsuN/rwXTog85dPyRhr7p0p5qFiHePXuzZm9sFwBH+hCrp9 F5/Op0YfjRGDbaQ2Aa2Ujc75Xp92kWVViJWP3efH6/FyGXARXR0OVPNS DM4= +ipdns.nlnetlabs.nl. 18000 IN NSEC jelte.nlnetlabs.nl. NS RRSIG NSEC +ipdns.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. jFgGPCL0aBhyG+xXjKy0wKlFosRlUtnURPnzSLAgjqU328xZUZK2k4Fe mc5ZxIgUDQdqsXm8B+1zKu8X7fnjeeX/4la8VIP5vRhIETKuDURyrU2S ZO/XYgMyzgXGo91zVxsOEp5otw+w8PuVJX0ErdE60v90KsGuzuy9z1NP aQU= +ipdns.nlnetlabs.nl. 3600 IN NS fable.nlnetlabs.nl. +jelte.nlnetlabs.nl. 18000 IN NSEC johnny.nlnetlabs.nl. NS DS RRSIG NSEC +jelte.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. kKd6XS6j7oXpvhquML+09ef+RdD26UJ/UF7byOsGUGnadu1d+22K6/9a mfvDwwDtLb+ozZb4mHkhsRWgUDkPaLUjwj4GIwUbo0fb/29XsixNt7XZ djqVS0RgoOC6v7MsOluENBN5CB1rL1DPyQYqEGg7coT9onlREL3fy6cA dA8= +jelte.nlnetlabs.nl. 600 IN NS talon.fluim.net. +jelte.nlnetlabs.nl. 3600 IN DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546CD +jelte.nlnetlabs.nl. 3600 IN RRSIG DS 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. MNtlv53uN3bLOFWlpqwZb6gWMJCkrCuUs1qrHiTPpzSyG/2Yn/pvqpRN pvS0OKZgZEv+xPodqFnYbFLc90//FFaMEiiXRh5M2M1wZbxdhf4CF2pQ Ip2E3TecPAZO1OAzxGJwXvYP/INFZsGSedP81+NmGOgXkDQ73hF8Pz7j Dpo= +johnny.nlnetlabs.nl. 18000 IN NSEC lappie.nlnetlabs.nl. A MX RRSIG NSEC +johnny.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. j3hxzzPIGSGWaaMCmsv5rO0exCMGKG7axgFN+zQ7S72MVBRsssddDa7J 0oFUZvKX3ZxH1oaxwuaBJURo0+2Z4ip4FJaqykY2CAHq19/ki55DDxiK 4hgBUj73gbeMeTWu01grVzdp5SdDCOP87DRmY0fhZ0W82it8bWYV5Nos pFs= +johnny.nlnetlabs.nl. 600 IN A 213.154.224.44 +johnny.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. EJAy5kI3QxNNABLIw/asxL2LjCMshjnWMNyUeu1pRd7KM3QQUDygnw+c 50MpE1y4X8LkBXDizazoUXPsqEGhq+fzGeFEhdB0DqrxVXtyQ3ikHa+d oVp2jdGiI5zl3yWBlxr4GtLr59jIB0ZU1sL5F0voBIAGv2i6PqArRswr HBI= +johnny.nlnetlabs.nl. 600 IN MX 50 open.nlnetlabs.nl. +johnny.nlnetlabs.nl. 600 IN MX 100 omval.tednet.nl. +johnny.nlnetlabs.nl. 600 IN RRSIG MX 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. I0qgNxmzI+Y83gLAMRkbqXqaTAwXksmtS0bxyw9ZeZuP6p68ScV5siS1 MsOmqmdcoqLX9BRU0ekL2JZBIiaOCBrZg9Gt4+NMRQdaZGv3cR79X6QB W2cEdQO5dKVuzFWH/oFJEBoThetFNKaEPNH7jlZSUMqSpBEdo6uHGOPP EvQ= +lappie.nlnetlabs.nl. 18000 IN NSEC localhost.nlnetlabs.nl. A MX RRSIG NSEC +lappie.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. EC+9kJ73MmOyyXzmo9Gf+CoNDEItyKdQB6YderLcv7or9CcWPnZ6hsW1 aZbU4SPYjO8Qtyp5O+vcTY3gFyex0eVmCSI05dNEY9VNCACfb5rUPtGw 6Q+Fc2oll0CAJhFRaRWHHfEoDuDh5MCNjnGM6bDax9JIKzJBi3cNmS1W VEc= +lappie.nlnetlabs.nl. 600 IN A 213.154.224.55 +lappie.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. TXeBHEwmv5bQDnkofdL2No8B7uf2/kQlDMRZh/yeGE86vIppxXZ1I42V SBzM3qEZ+dPWxJZU2yWdFcX45+NVIxQp/ktgaTNHcgPRHalX5B7gbd3N Ga4niMxUSXKQM3aZYqXrxDLvWjYaj9qH23AO65rF/sANAkPiZp4+/GqJ zPc= +lappie.nlnetlabs.nl. 600 IN MX 50 open.nlnetlabs.nl. +lappie.nlnetlabs.nl. 600 IN MX 100 omval.tednet.nl. +lappie.nlnetlabs.nl. 600 IN RRSIG MX 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. pD5bMt84XFoNJDcCbkq/+xBLg/yb1nPmfuYOeE4YaSV6lFFmth6HrQiS p86ErhD80R9omATBTEEaHnuYw/HxHUM219NA1kKO9smocB7oNhsb/Has WrdgzlzMm1oGyIJknuVCXFQQo/Z9kUJyLMLPntaOAORsRwuRgOn60JMb szo= +localhost.nlnetlabs.nl. 18000 IN NSEC loghost.nlnetlabs.nl. A RRSIG NSEC +localhost.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. h7Y5+OptNNj5UMWuDnRARnMbf0IKBYkii20PAHEQ1+tBtfA5bv1aavrk n3i/amzJLk5GV1xAoc459mV0+RcTzOrlrZZ7MwsvYFmdiB+0xmplRTgn 9bF0W43LZ5mMH5pFyBnygc3myoDMxmrgcdhjiW52JRCX19Ui0Dn33lZ3 dYU= +localhost.nlnetlabs.nl. 3600 IN A 127.0.0.1 +localhost.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. T1giRKds7G/HjqKOgDnGXwsRDm/kt6c4cWs10Xd0vaVKmeEFyi52+YoK j6AIRlHMd3aDJO2F0yNTy2MufDZTHVJ6usyGw0+GEi6Vf0AT1lAMtg5i /C4i38KAwJXLCNWQxPTfbAubpnPOtt/078Oq2I/MLNGytcWyRXApyftW J/Q= +loghost.nlnetlabs.nl. 18000 IN NSEC lustra.nlnetlabs.nl. A MX AAAA RRSIG NSEC +loghost.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. VcO1o9JRiqFCkOCgizKfCWslCQObdt7QrvlSDgd7kkcT0UDuDcDMcD42 jDy3hhrJkmU+ICqx1g7CaaMIbsOPZWOsZi/qcNki6oEuLG8gRD55F3X9 TGApgPAd0feU1S2GuEBZSc/4oeizx4xuYrC+RSCQlgl5OUwJf1Iql1v0 Iwc= +loghost.nlnetlabs.nl. 600 IN A 213.154.224.1 +loghost.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. Qa7seOsz+RF6J2NIk2Z2WQio+qoxgKHNLdYapzooJxvkghOQCqF2Ogto ykmmTvZTj7fUoZ+gyipkosNi6BIIxIUpI/BaEtEEp/sZK7vQZsGXHoqS Etoduv4dEUX1ZjVtBnuzW8BIg4NzPRXtrHTGox2SNcvEHpB2QrXD33XN BxY= +loghost.nlnetlabs.nl. 600 IN MX 50 open.nlnetlabs.nl. +loghost.nlnetlabs.nl. 600 IN MX 100 omval.tednet.nl. +loghost.nlnetlabs.nl. 600 IN RRSIG MX 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. VO0p+Ygk0L1HIwrCRsy/6GAF/HSaWZjDkM19iKhtlA1rmry1DQ4u0Zoz GV4gWLmuqxxC0ablYo3TPP1krRTuVowfEsxOPcInP1NbFXtfaJxNh73a KfyFOHCMbLboBU7pQCdnKjXZOqrOOaipEVAkPviAEhY9Rz3bHeDQKmTX R5M= +loghost.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1::1 +loghost.nlnetlabs.nl. 600 IN RRSIG AAAA 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. G0G/zsG2irSSY/Ym5Sk7e4qyfXU17S3gueNN/3it6AvoT6twshV604GZ 6aFRvpmx5tUhaosSV6uASzeZ65aR+5/kZa+IJtmzDoVliYv3Z1T4Bu85 MFX3ep0OSjXkF8umDzopfgiv89UHU/1lM/R+8WcgIyNBxpkcr0BDk5tL CZY= +lustra.nlnetlabs.nl. 18000 IN NSEC markbook.nlnetlabs.nl. A RRSIG NSEC +lustra.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. eI6c1Zvg7B4W33c3Hp682BUQFLldh/cuZU9Ynk0Ymga20lyjGRS27SYA 1PNiEge9h6dg+nLPJztgz7lexDfdp2p3ZLq4guNiGkN2YaQDMxoGzeOd zG3hHEyzTYKCBbdAlFmuy+94eIp4GWptlhu2vgAuWjvCQxvqAoTKIfiU 0q4= +lustra.nlnetlabs.nl. 600 IN A 213.154.224.52 +lustra.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. l5CL80Ow8dk/Cv/Yq6U1Fq2RuvkdrU1zvdh8SMIEim1JljsqV1YsyWZC AwBTH6ms35sG8MbiF5X0luwAV/V30jL8CUrB4EhQCA4TDwM+xSYZrEi4 wfb2KpNsX3GNDDa1CV5YEqbJEp69EmMhX92Wg+L2cd+0xXop1Z8PmKKw W5Y= +markbook.nlnetlabs.nl. 18000 IN NSEC markbook-wifi.nlnetlabs.nl. A RRSIG NSEC +markbook.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. BWuNDPuQ/yQoF6cI26tayhNArrClF9stzilmBnQpewBPuthWEllswZpQ yGKQ1cuBw189DD4rDN+22152lttO7Evwgf3rQTrCCIwpZm4/xERdLVbH 0/vwHVooJHgA4hjX6JeNkT8UrMnyTHt/0j/uZi76YI4jkttGKBQTw1IH V34= +markbook.nlnetlabs.nl. 600 IN A 213.154.224.15 +markbook.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. HDLwWv+UtqQvGPpr1Pb3NHqwt5bUqWOdJRx3a4UN9TAdjH2p54jjd+0Q TkobfBra18VfwThK9J7PP6br0ceEKBLXfI1bpOu93PMTmJJSjReocakw YSkwbjepZH9rWAMnVsUHEenjt6BfyIB36vKe+BXN+nsTT89JVewyd/Up nEk= +markbook-wifi.nlnetlabs.nl. 18000 IN NSEC mirre.nlnetlabs.nl. A RRSIG NSEC +markbook-wifi.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. Z9ay1VDAu6CFmZwnTBj/zBe/orvWl/KpfqcLe3M+YW0+Xmqr0egZKGtn b6DZjDBUAe0gsu+T5pGa0KL5QxX4SBTs6eIBqNaUmvwQEDFuaxjWiCTJ CtHItcmiWtCYSHMhqXJNehMFUWmW+MCtqQnBzHP/+ETvgwS8PXPrCi2H Exc= +markbook-wifi.nlnetlabs.nl. 600 IN A 213.154.224.14 +markbook-wifi.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. SxAdBN/lM9g4cAVnQbY7T2RyDxtis1DUjQ26N3Vwz9DpjvO6gF1mVZBm E31BIoV0oqx/qPAUZ5acIvelMvnabqeD33eZ8PPSBjLZ1ozGli0hNzD0 2zAL+zSfV6A/Ndl1f0FXH3L8yQnCYk1xamgvrWSwOqB/ikpkK+F0fy4A 0fE= +mirre.nlnetlabs.nl. 18000 IN NSEC motel.nlnetlabs.nl. A AAAA RRSIG NSEC +mirre.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. DXlYJ5kmPFQavM16V9QkoHZqHhmyTdFE/iF/k/RL/1NzZ/3G8gL+sXfI r1I1Ziq1/NrrYdAGkZTQqw3TIXMkqsRUFqpGxzPu8mKB2e+IGprzhtyg HanlZQLzQAecIo5iiVpoqK3suYgE43nBDnjbILCUU/uuiKCsqnqwIac4 7Q8= +mirre.nlnetlabs.nl. 600 IN A 213.154.224.9 +mirre.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. IZx+IOx6mC3IZWWjdhAfgp8GGpYpEWGkx+IuIYT15ScE71xcP8Erd1Di s5e6Omtt0roZLOWMAFzC9gxd1n1E6nx9hyP8fYzSDaNsp8mfJhTPl5Of 8NEeGyZ/lBlWbxlBcaV0dSnllP44sjDbmLZqQBWhWWtG+Z5Of0Sqiahs DRU= +mirre.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1:219:d1ff:fe0b:89f4 +mirre.nlnetlabs.nl. 600 IN RRSIG AAAA 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. XEgipNwqEvfrpL2EEwBdGz4gtNMwJb9NQPrro1H85li59ts2yEH7GIGz CrSkI+nwXkNKhwf1NW7EE32DsGmYyWB6Ysg0+ISoeyx2gtlYh4NGVPav MrgWXYfg6p23w94fjfLGze2ADdcDpNmPSuz0q5zdLgEh5kSq09LAn//J txM= +motel.nlnetlabs.nl. 18000 IN NSEC nlnetlabs-bit-gw.nlnetlabs.nl. A AAAA RRSIG NSEC +motel.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. n16G/quCXHjHTfhdMdZUf836jZSHkhDbDJZwB0L2UT7OppTMBRwWL2+E /Gfiza5HRYCdOUhx7QBKD/eqXMwbASDuD2wfxoNXHna4aYeuHn47pI+2 cijH4EFslnwzyNvcY0m3L/fws75pmE9iKw4+e92sz2h3Pp4YG7IM+wTg +2A= +motel.nlnetlabs.nl. 600 IN A 213.154.224.7 +motel.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. cIVhYnVXBJoUll4z4y+PisMtJi9HAKQFVLN8yYK/dqkkK0FbMptChIJj Bqnoc3EghwIuGIi1sbAbn/dFb3Bsdio3E6mKsdBJ+Cit4TgqPTcQT05M wWMRKBNVkSVFLxisyAZCl78pNAji2DmpABtDVhHjI2HuhvFEqtUOUH4s GNA= +motel.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1::7 +motel.nlnetlabs.nl. 600 IN RRSIG AAAA 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. Ekv3MGcrn16kes3koWHMfw6RwXIot/4kJYQOJus1dICT7Zuhrpbhps2k msSNHQ+/ziuJ0dvmkP4TBZU2rFHsYmJlzEv5qtBF6MMzQFH6M6ZgkDh1 Ovv3Xp5XBGfSm+hJMLtzoWmS8p/22RLogOsiv8RGiKCD+T3UF8TnRleU XXQ= +nlnetlabs-bit-gw.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. OxxcW1xKbolFyiydndIfBIYdsb0jLL98VFEUsSaj2qstoLlRAL6YKORV wn/ssblwQsXqfdimVwyoNUvIdIO5rInbcqfBcimXDlvO8ihZENZZv4iw iHPxQ/Bc1pPTYFdHem+xfn/ih5i4oLLn6nd/v/0U1/immMWX16La86s7 Og8= +nlnetlabs-bit-gw.nlnetlabs.nl. 3600 IN A 213.136.31.102 +nlnetlabs-bit-gw.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. aTs3q0dm27hE9RSCUXMxyqVXCH/bo18YzV1N31ywu+0uGAqEkhnwtZpm PNX1C/PJNbmeVpRlOR1oIJ6KV73Q8r9zA2/gWODlr2G7uEwed3Uife0j FRA4D1DRMIituvD3Tjb6UIyqV/qikPe2fn1s9Kcl0IpMJ8uc/HgIARnz DGE= +nlnetlabs-bit-gw.nlnetlabs.nl. 3600 IN AAAA 2001:7b8:40:1::3 +nlnetlabs-bit-gw.nlnetlabs.nl. 3600 IN RRSIG AAAA 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. a4kVuaQbmEs7Ju1slFsv+6aLqkVP1r330aCF1h1c/P+qayNYIpWibQHS ZojJtgVbB2eid0xaYXCFd1TK5BBTu58SSNc9G7vR8U2WTkhmk0bvBeyc bVgMSfiPJsALtj5ID3OAkxtvO1ZusiVbKPXHeSFIXKFHJcRePZ8dox/n /jQ= +nlnetlabs-bit-gw.nlnetlabs.nl. 18000 IN NSEC ns-ext.nlnetlabs.nl. A AAAA RRSIG NSEC +ns-ext.nlnetlabs.nl. 18000 IN NSEC ns1.nlnetlabs.nl. A AAAA RRSIG NSEC +ns-ext.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. OY+bcQreb7oTtgveymg0FWRG35NcEu9iBP8SHokm7NH2WtL5jOH7FZMR Jyaaq222Iv9TMcOEn2KEYqui7VaHkoQRS8YKchPHVS85YTDsjk7uULdm bZw6BqskiNKSo90bQDPBobvER41B3DGwvVUP3RDptNrEiMxhuIidGjOl yTU= +ns-ext.nlnetlabs.nl. 600 IN A 213.154.224.4 +ns-ext.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. lj0ArLI85OQ59mhEj9FPnx2UYfTOehnql3nAG8uNmnGbeepyIKDi5QRf ZKp0/eyyBFiMmKHVxvvrm1z0TtOULb7nS5325w9KfS2JQR4/nHAQZrff HGDnqZ8wFWVdnebhAqKzYt8paqlRc4I7tsyYuFxmKGZt4vi+1DQfK0z6 jbw= +ns-ext.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1::4:53 +ns-ext.nlnetlabs.nl. 600 IN RRSIG AAAA 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. gKo21eKXSxeR+8MpSUnGVBt46BLOm39e0Jxolz4dc880hOiWlfNRl+3y vZTILWgTn9iLJ2wz5ZPZwuk9ae/EHqlIvJUx+RLZ+i7tCsMr7Y5P2ris 27Ar0I4aipnN0DIdXio8VQF0GCvQHj+lcFlqBcV0d0saM3ZsMNoZc4jW zo0= +ns1.nlnetlabs.nl. 18000 IN NSEC nsd-xfr.nlnetlabs.nl. A AAAA RRSIG NSEC +ns1.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. mRQhMDYQM8/0Dkn9dplPnHqV0+d7wv/rGItfEYNOOu5HwGLmcp0D/fC5 caFMYtlfu6Py7/zNWrs7Ulwg0H0hfJhaQhHmxXRmf4ereFdrEiHEpgyN A1Uw8HsDOjOPEJTSbov2FxYvjihG+qJoiQWF+35qJC5/D0s5M6vXib0f 81A= +ns1.nlnetlabs.nl. 600 IN A 213.154.224.1 +ns1.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. AJpm2iiICAWSAWfcyWSZtlywNWlLgMk3qH2v0OcLawL5GPd9gCOw38iM J0fwYKu34UF08Z7f+ytNA7zPGUFGND4Xhe4lQeYworPXh2SeMfggmWtB y9tjGGsxQJe3+ldRajSIP71fSuWsvcp/YhNA4Q8/pQ51pgrxeOuJDgOj aGw= +ns1.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1::1 +ns1.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1::53 +ns1.nlnetlabs.nl. 600 IN RRSIG AAAA 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. mL6AM8KRQFBtCSy8V10Rjmn0j6PfWB8j8Af79og8DirJkUuIJQq7Oiy/ EaNGHHpThAwEvS/JwCZbFOezx9gLgEW6s/So7E+U1v4iMnjm/HrEQlpk aXcLm6sI3oNP46mlBuBKpbaze6m41wJZHp80xPCqEmbiBxDEdQzjUVcf VBE= +nsd-xfr.nlnetlabs.nl. 18000 IN NSEC omega.nlnetlabs.nl. A RRSIG NSEC +nsd-xfr.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. p4YKePcT1qhweFhgILxcioJgEgsQprIIpYXSSb1KGcWAizPsTB4VrWAc qBrHWL7ok1XMIUBZEJ1ukwjmWKdG2bIr10PLIRKpFQl/+UtzxRXqldJh 8W9rBrxvZnaQCSFCm/fBMk+TcH82F90EvLIG08Pbr0f8R7Fad1NEwsmG eKg= +nsd-xfr.nlnetlabs.nl. 600 IN A 213.154.224.49 +nsd-xfr.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. HK3CIL/brGoxxuBGd7lvhUUZPt4Xjjs9bxoiiksCxkj7aGz8Kchi98tO sulv4HKGFV9CqzCtwgL09cLJOq4O9qg+WF/ZqbtJhFCLMgOq1hVE42j1 ZQQ78ueVtaBrxztyPHZWha2lgJKj0KKU8B9SJwdY+E6nXqd1lDWIEBtM 5V0= +omega.nlnetlabs.nl. 18000 IN NSEC open.nlnetlabs.nl. A MX RRSIG NSEC +omega.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. fcIj3rZIOYBdooN8hE/QzUMFm8J1uuwKPTqJpMU0QJWvvGNVZRI0oNVi Lc0rKg35xkW13GC51MPx7fiBOdYJHGVi0azSAtGAn358Q1BkekDXd7CG jMxlZ4z5DxMbdxcUpIIcWu1JGLI8EZ6Oog95CSA1987ya6H2c33Qn1Dr uZw= +omega.nlnetlabs.nl. 600 IN A 213.154.224.54 +omega.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. PPGDFlV4KMJKObKpSIj5EamMQL0xN4jJ1ilmeaZiLyrf5o51sG2YyzZc InUOznjoI74m4I53uvyUuf/DaEDivan+5xHb5ZlUkQu+/JnK2zRXF20b iARFnKdPW8kNe3aWLrolc7XSpKqOXGcsDoa2SS8zSU3oG875IkQOUzwR 76M= +omega.nlnetlabs.nl. 600 IN MX 50 open.nlnetlabs.nl. +omega.nlnetlabs.nl. 600 IN MX 100 omval.tednet.nl. +omega.nlnetlabs.nl. 600 IN RRSIG MX 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. UtSt0IyUVg+SiHBNkaz8S7otj2rpqZJQuKJSLb3bQvfXPJ9vnPvJsaCo pVB+CxXqx1GqjKj00Sfq8BZHbDS5OyO1baLRVXTNBZuXcjSDBksWEoel cdxuMG6If2R1rRfZnck3cu4DH2s2eQvk0SKUyfewOjp9QBuuGN/SEJcU X9M= +open.nlnetlabs.nl. 18000 IN NSEC pan.nlnetlabs.nl. A MX AAAA RRSIG NSEC +open.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. mxHCyGC0YrwXJ1EUFB4fEzxV9ZERmCJLkdiCYt3zrub0zzoUAmlRZkrq J+7/HHpozI5mI8NuSNYNHtbD1Nu7Z2a+JaHOgbmKpEXx+BiQjKmUf/fM 63mkv1gtWjluk9wLc2tk01H0JEEX7CrwHfLKX346i6/qDPh4Xa+Mf5p8 2z0= +open.nlnetlabs.nl. 600 IN A 213.154.224.1 +open.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. ViuIpiw1c6a0roF+XCOSFMQ3BCH/qmy+lRcU0Y8jEeoN7vLu5rJlWUuF yuuU3kAx6RFB/XDPjxNzm2OER/JJSUUeagzXSqnJVL8Orj03RGpS2PAW 5p66uf5uMv34VEednxoGoigVHKIBfpIwYIbcaXAkDaRMMpw+ylRWwWee q84= +open.nlnetlabs.nl. 600 IN MX 50 open.nlnetlabs.nl. +open.nlnetlabs.nl. 600 IN MX 100 omval.tednet.nl. +open.nlnetlabs.nl. 600 IN RRSIG MX 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. bXZIS3/aa5cdXU2k2vYCbfVj/1FnU8sI/4zAP5HNNVEl5PtNj3Zc97yi 0hj0grLoBqRYpwKB1ZzIVMWbJ0F/Ly39kx7yVWfQ047t27cXUZzGRWKu 3gUITW8qsLVTSr4tj1faWofrWTUZHRjn+5eT7stFTMKFQnXNRnE9aLb8 OhU= +open.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1::1 +open.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1::53 +open.nlnetlabs.nl. 600 IN RRSIG AAAA 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. bcDWQYXDf6XEyNFeYeDJZTcdUCD4hbfzEIMCL1Fap4Lm6FNSvACQ8c+F F48UfJVdvSZeczDKgsHSm7nte81qYu4+lBQm5TuJcMkjgJakHumKGV0Y 17wIJAsMPiacw+NNICweKO4x4RKwNzWgcn1ymktYsiaPIJpOxQCQVJcU tlg= +pan.nlnetlabs.nl. 18000 IN NSEC pontdugard.nlnetlabs.nl. A AAAA RRSIG NSEC +pan.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. g126geXJj4BHuWcsmaG+gXMLh6qGya58U2gZ5KGIsLdqjyEdRUrwkwiP vOoXPFhPXYi3PnWO+qmCZF3+VZUYa4WDqGCHfkNtgV0VPmw0sTJvXN8q Y3I4ODvvYXwDSR0lzQvvZh5nXELGs6cMzEhxu9fU9ujBj0nA+3JL6V/t 23o= +pan.nlnetlabs.nl. 600 IN A 213.154.224.38 +pan.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. KJ+uPefKJD2HIqt8EYCsIT24kVRszJ74XwBlvkxuLZZlBu9ld4MBqfaj JJWssWPFGGHVFaK67afa/t8fn+NL7b9uF3OCo6iWSOrFlVzXcT+huQRI yokYnncKdbk4GHWJn7vjfFjfgiNZT5cbdq+e3zp/NjBuvETcyXGgQbDP 7Jw= +pan.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1:240:f4ff:fe37:8810 +pan.nlnetlabs.nl. 600 IN RRSIG AAAA 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. Et98q71wUk53WPF3SURj1QmAQLLVXolNVIihwSnZcosB1v4VtrwXIDGp JocHKH3gl5ixOrGFnXLSi0x5icJ/MEFRAEUd5J+CcXhAjMmcwim2mZax d9SWjl0bLjrcXrQNHKqUZJn3QouEkrAiP+FM7eeD4xJ8cWxD3OVj6Foh YYQ= +pontdugard.nlnetlabs.nl. 18000 IN NSEC qubit.nlnetlabs.nl. A RRSIG NSEC +pontdugard.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. H3nguVxothKIXYwrCGnsklJMK0eDOM9PLY14YZBucyT77GcXbrG8yUKy C6KztNFDWWMDWGF5yZloQVPqaBAvmTKFxPC2q5e/JrCiwmZfStcOgFhg S7IpIZOYwa9QBWmQShfsnb/2GJbE9H1XsvAtGw25BCg4j1CFeBDm+n7s mCg= +pontdugard.nlnetlabs.nl. 600 IN A 213.154.224.8 +pontdugard.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. WfJXmfIWFVRmJxloj73JK/FMwNyBtXiAvDI2eX2BLBu6DCc4VqdE2sjn ObSE7wOx/28Nt5TL3ZktJkW+pOvxDHO0WE9F4GtEskSZdFSV0mV11xC2 dbn3F23+S2MpgNN0ZDEvYeZIcxvpYoDAbwEbKyd22efzcIv+A9dlH11n kPU= +qubit.nlnetlabs.nl. 18000 IN NSEC roto.nlnetlabs.nl. A MX AAAA RRSIG NSEC +qubit.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. JhEWtMOZPbTlq3P7H0VZuGdLXVSxsTbpWe4Ers1zAUEKSZSpQ0UYKX+c IypwIOTgrRJLdPqKYeKWeU+/JVq0ZB2u0oc8fuxVnEfiR9yVILtbLwVv P4pgkzC/lUHU1GPljiqrLo2HngamQuIaznZ72FVrMIgFg3hZElHtturM /G8= +qubit.nlnetlabs.nl. 600 IN A 213.154.224.46 +qubit.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. frtAaueWLxb2/wzKkY4ltLS6yf7NAAMLxj4d6e/VAH7WrhFpak1sqQxn lGXOAJGTlwE36q1EtIOlbxB7ugvd9m8QkMiPkUE8OsdiafGcGR/o7UYH /fTBuqhnU6pkBztENZb1e1+elBZo9+dvkB1NeVkoildpZAUkdy1eYz0Y IaE= +qubit.nlnetlabs.nl. 600 IN MX 50 open.nlnetlabs.nl. +qubit.nlnetlabs.nl. 600 IN MX 100 omval.tednet.nl. +qubit.nlnetlabs.nl. 600 IN RRSIG MX 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. HYpo/8yh+GsNZsy2jPGzr5ya/pBYNwXbcpIOboCQt3yRwbieodwn4uDm yftGeL5DSVsaU0GalM7OR98sGG5weXV7WlCccqAZq+SGLALyqJ42hXfi tdNSiq3/snDtx5e+RPKqe97z3jcbthm26SrRLxMdLtt5v0S0ppNGfh4v nX4= +qubit.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1:202:8aff:fef2:f598 +qubit.nlnetlabs.nl. 600 IN RRSIG AAAA 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. Pqlh2e0tXkamkSPQuvEQNqbqVWsq0RSqdgYSB1N08M/Jbe+BiqWoml7X EO90ir4ug1gTF/Re0vtEV8cr3lRofhmpHXHMe3dcVoZ538Yq3Eu7MyGV /NsjYGgNj2ek4sZiTt75/auvU6grx04egDJn6gvvsiVt5xnEwipNnP0S WIs= +roto.nlnetlabs.nl. 18000 IN NSEC sane.nlnetlabs.nl. A AAAA RRSIG NSEC +roto.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. GYigpeoLV9ax25m4mmF2HKWCbDT/flBZaBo8b8GBJ6RURaBr6ShcMe3J t645fVr6VOIAcNGDddSqqFOWvCIGEZhXSR7e7sjDJBKXVa8j72ANKN5Q zvfx5JDNxclWbsqiADgn6oYC9rp7KxvpqEUL/f/Yp2j7c4OP+xerduvf LWQ= +roto.nlnetlabs.nl. 3600 IN A 213.154.224.153 +roto.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. kBGp41jRARMoXDaLWWUD4i/jrj8n52a75EoFJMOgsy1/8QtWl9UpzGcK P8J32u4rAj8jQTprC9eyLYTXwPp7ACfqmCCSOeec1G3RLDzxm1bs6xzp ez4sZfbcbBlqI/MQccD6O6dTxI3Szxzt9WEM067QwdgU5KcLI7+noaxk 5DY= +roto.nlnetlabs.nl. 3600 IN AAAA 2001:7b8:206:1::153 +roto.nlnetlabs.nl. 3600 IN RRSIG AAAA 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. psSEF/+UXwZpCYqhQbHU89q/DFkA4odxlEcLZZkZmJG1+TFnOuDDh+FV MYFhjlZfHiWoN7tIhTqGtHHh04xrlcx5NVbnphZMqlZd4PBl05iCCrZb FT9AhsHftolVgH8fq29LVO3tQso8pbYw6MpG9flGT45rZzTU/eI8F3Aw luI= +sane.nlnetlabs.nl. 18000 IN NSEC sanne.nlnetlabs.nl. A RRSIG NSEC +sane.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. ZHA2sgpDy7DLxLZBn+4TWnfYIfFJTZbvr/qqSGKYaMswNUgsq5D0g3sg LS0721YI37qDtZNKA/6wLVO2epnKm0vzLDJSn40YUOMdTyCt/xXpV8p2 oUopbsQhflxP3AWNQ8VnsijhJQLgQhTdr7NEz8EHgHpFjgSjB1h4pDkM nV0= +sane.nlnetlabs.nl. 600 IN A 213.154.224.6 +sane.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. NYHvgCZCpgAVe5roAttvnxc4I3ltRa/P/VHUofQgTRRFIGJY2FzcinYH 8CHRN0BEdgoCzNUGirHvYnbHin8PIqVgfllMWJ7Dtexz+Vl0RRyGqeUo ArVZf3j7C+z/kKpL8CYMk8WvSAVlXlPFqolUiiJJwwNzlsjrKqLs7fwE BzY= +sanne.nlnetlabs.nl. 18000 IN NSEC se-dns-probe.nlnetlabs.nl. A MX AAAA RRSIG NSEC +sanne.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. ewVO7sU70vbby8VL52SZ+M74yy7ClyIH/R9oFbLI3O4OQ2iqN8YXR0Fs uf30tSI6XKYYzIjps1MLlK0zSL23PKwcZIOkK55icSrgV7TnasWkrvFD LigM1smmErxyMeqfrrwu8yGFdhpzHDvYAjqiiVRiXJNRaoLC0GkOYEfQ eQs= +sanne.nlnetlabs.nl. 600 IN A 213.154.224.39 +sanne.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. J0HE1rZbC4cPBVt2gmiFBoyE2s7PyH52BkIalz5J1gBD8xTo6Kq5iPO2 zqk7aijDlbWAvgaftzyKwab5WZHdBJEfZ1wMvlMukPd2tRyiBfW/Hqbi kJf2SzAvUOipAUHHomESV2cO1U5OAbYvFMR5syu9WD/+5xjsnGabSLjK aFw= +sanne.nlnetlabs.nl. 600 IN MX 50 sanne.nlnetlabs.nl. +sanne.nlnetlabs.nl. 600 IN MX 75 open.nlnetlabs.nl. +sanne.nlnetlabs.nl. 600 IN RRSIG MX 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. i3YmK7bxxz37q5NNfU5f0bPoO8xHVOC8xbzngXsieqfKsJEty5PPTDRZ f7opc7Xe/yMfU3IH/ZX2C0NJHxI1GwWGe0mRs5uic/gHJIFMqv/XUvjB MPZKVnIeSSa8fbfOBgHOpjXCXeEGVhHEmRjfrcePTIz5/eNUmPpaQZ15 NvU= +sanne.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1:200:39ff:fe59:b187 +sanne.nlnetlabs.nl. 600 IN RRSIG AAAA 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. mHVDCixUCNsdQoWtenWumJ6jYi5KOYk4WSZBZtm2QOBBVzyY9R6nqIZM HChCivztLR5lLdc7sO4aGekLxko5MVm6nZ+AG2yz2kIRNhxqyYYbWmD2 Ta3QGXz2RKiiwgyE6d5xk55sG9lEHhngwfItBgwYLOvrLVGIdjh8UmGF PLg= +se-dns-probe.nlnetlabs.nl. 18000 IN NSEC sixgate.nlnetlabs.nl. A AAAA RRSIG NSEC +se-dns-probe.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. E13fsWV+gXja+Ynt5/fc3ry47LyHBlCuUC74XjWXHGSiCY4KaaWbmv1Y LpjCvVQz7SKXyhL20el1qQVQZkDqfDUvtJKThgJpVdIlPGVpfhg00BMb XaD5UNIzGvsEUPo7cNqPswRvGU/9lc9Tn7z/Fwvikmj+8bL3SbDQPQlk mS8= +se-dns-probe.nlnetlabs.nl. 600 IN A 213.154.224.5 +se-dns-probe.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. jKPpQ5cpUdFh8Dd/VHwN6geBBiPRi4tihr1/FMZO4enHbzmwHhtuh5ql qaZXn1hySLnNOJ70+0e4Ma4DZOsvuapGY44lpuQ49qGbu5AgpxPH2bUZ CjrsVnHfoifhR9c68GhocgjOQ9PS59/Ec2Ej/DF2rMFXFD0aF6bq555f ldE= +se-dns-probe.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1::5 +se-dns-probe.nlnetlabs.nl. 600 IN RRSIG AAAA 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. nh/86UHPGKcVw6nmQT8fYUplqtl5SzzKLYxXk5SsDl1rpGg6iHMvl3nz X/UnDXn7gMa4OQPEg4oVz7ZBjmBSuVjIjM3LoBSF41zZscBfjSue8HUE YIkOhhkJYvzR/xAhjnA+aAjmldtZ7HQYo1XfgOjwx/rh6asIwDtS4TxY 7NM= +sixgate.nlnetlabs.nl. 18000 IN NSEC snom0.nlnetlabs.nl. A MX AAAA RRSIG NSEC +sixgate.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. p9SYrNRZKAcvnrFhk/oJVuVAJMRmlWuyijhz1ueoMrU0zslFqqKOCG1e HcuWVDLjjn8SV8nAak6uEZRWigjttjXLwl1uNenKUtt+pp5vo16a1Eff bGhoN0R4N+Q9yzoI6zfET2y7R+HrYBHOlVkrvUwGFo2Sliupi5b7kumr gdU= +sixgate.nlnetlabs.nl. 600 IN A 213.154.224.41 +sixgate.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. eBLYxx2wU5FyrLCIJqfWpEyUh1omWfqb6d++s3tQJWtbL8jV1E84Erde y7kphOsn8w9ar/ytcVg/k99+664FNTnMEiU8blJnLXUzBB97sy2irmS6 P/2TznKYEIce6kOyD99COJ6D2+u6SHCHEKKBv2G1RIGLyQt13aPiQkjk uXA= +sixgate.nlnetlabs.nl. 600 IN MX 50 open.nlnetlabs.nl. +sixgate.nlnetlabs.nl. 600 IN MX 100 omval.tednet.nl. +sixgate.nlnetlabs.nl. 600 IN RRSIG MX 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. KL+o5qDn8O69KadGbacCGLNYRkcVdrY1EqEGCib0AjVcemRyl382cqhP qUQI7Vzlr+dzRz5YON16OK0GOh+j9yBBUeabF2kZoZk/lzS6fojNZrFl Q3aE/sqEygYcKtuVft21Bg0W2v66x+mpYd35jbZbxpgg6K7RW/ceH0u7 rEc= +sixgate.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1:250:bfff:fe5e:33e0 +sixgate.nlnetlabs.nl. 600 IN RRSIG AAAA 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. aG4F9+Vx3wX43Si/iX+J2036Tz8ja0DkJg4+/G+0suCM/OHDFZcfR1Ne zxbwgdhXY74FODdYaz7JuJDUpYoQNy8HA0eHLaXMTPEjzU/C/YuePVrD DJjHEb2TpNapjD4BKCqXDY+OaQclPLdPIoOHkAv7I4DRvn/8qwUHK/Gf 3Fo= +snom0.nlnetlabs.nl. 18000 IN NSEC snom1.nlnetlabs.nl. A RRSIG NSEC +snom0.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. puhC3IReZ0U31hWvtWLlSrMww4BUf9+ExNAmQY9+rAOh8N61E25qmsSl wOveKfVIW/EK3d7Ld/DDcYEVsoOKcOXrSZ53SVUPFpmdx6FNPvkWkbjT LzwUspdwB/L1Ox7T7yFMvFAaubq0TzbEcZVnZlPxPKwGqw1ABgAT/FzP oo8= +snom0.nlnetlabs.nl. 3600 IN A 213.154.224.200 +snom0.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. kPE4amI57Hk6j+HLuKUzwYgj665mCP7klFnt2Ty1rjbBACXJDrzbgm5k Wq9Ee8OfpTrALro6qFhry5TSFkxA/46KADTRNtYzOHZvHtXJx//ZIJZU 3oBjnMbNFEGKQ7NUa1TmTg0XtKmZkFk45hiVsXEUTkHJ1br55Sk9ZN7P R6E= +snom1.nlnetlabs.nl. 18000 IN NSEC snom2.nlnetlabs.nl. A RRSIG NSEC +snom1.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. lsp1olju7Z38jPpBQ+TRPttAHLE/QU6tm1iRe8F5DAZVKduUCFtz4qsN jbCD9B5iWuhEBwPZ4+LLQi2Ga27OEioe9k9kFeWuF2GBSxYjSCOeczIr s6gGi7fARK1b4x5HoI5JrbwW8zrQ+y9lu/dwrXhFyPOX5SgQSwqLNUo8 qBM= +snom1.nlnetlabs.nl. 3600 IN A 213.154.224.201 +snom1.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. COot+bPSyihBf9iTeChxvIfMYm9a2LH9eR/kC2bmp64DIo2OhO4W58WJ CcDh/KzW6mtQt2PMU7JW8FwWHrRfgvScWxfcQGl90nlnWrb8I0VaZuyP M65WPwxB+xqCs3tmnN87m2jHCL9eWFXg7yCPPDTRJPDr0OZWbeQZXb2e 9F0= +snom2.nlnetlabs.nl. 18000 IN NSEC snom3.nlnetlabs.nl. A RRSIG NSEC +snom2.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. SjUDNgnAwaETHAovXMHWVFxcNTFn5+JKqcnk0SYEzIXZiTcfbDGfFE5b hGMVEwKl08KvsHCF9v9ckb+RfL9aQOkRoUEjxnsqU9L0J6WWXYv0CWld 46GFG9Rm0IbiE80IY4KMfXW9/sAbv8anDqhWLm3yHn5Muj2Al+h0OjSB kvE= +snom2.nlnetlabs.nl. 3600 IN A 213.154.224.202 +snom2.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. DQ9hFcmw8bXdW+TX4sTS3y1qPMUOzfzgDRIqCDu8oIiARH102rNpuB8E +JJT2ziaGgKjyfsVxJQldiBMIIvGagLIR0ArsJXThxtlaiFDbQeqZSZL +b8xqQcTDOhaU7xAC0V5cRYfdCYbd5sMtVx7XYQggX/Mot5Zt6oEOg3i msg= +snom3.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. PJyBfD+TVk4JjyzUreels+5tWLmOOZg9Of3uklVcX+GK+Q2hCtU7yyUj k2mkeMJ731V7zLQXZGz+1vC91WtIVXP6tlY3rr63nMtj3jb1R8WWqY3/ 4O2hP6d6S2OEyuESuGnIhVXyZlPunzAWgLN53Dnzb+xn8KULe+iy9Sjp uH4= +snom3.nlnetlabs.nl. 18000 IN NSEC sol.nlnetlabs.nl. A RRSIG NSEC +snom3.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. j/KJY9y9PZIoSnAOzRkUbfq5PoUeSPW/Dy3d7K7HfVlysfJ+I2DloTPs 8CssOp/oCdki5EUnpnn2ym1csJTKZdEl6MSfDGMT4BP1W7FK6RDpLO6z ehQj7yKs+Pbr1nBq0tZWlr/HUTmJY1VJmnj5G81dmazesufO/9wDKer+ TCo= +snom3.nlnetlabs.nl. 3600 IN A 213.154.224.203 +sol.nlnetlabs.nl. 18000 IN NSEC sparc5.nlnetlabs.nl. A MX AAAA RRSIG NSEC +sol.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. jUXNRrMfRHbf7p4KgbdVI8WsDMC8k/1FOsO3BoIjSyX22Hr5v1RuKHG2 v8ZDlFXMbKcP92xdj3mAJbEmcM2JKvaHiY47VrweO+FbwY3JDgUkTQmH jf3SMOHXrxtKjixQOAJKOWOLDigEBBLkuUjdfG6PybDDG7sBgx8WHFIE Ulc= +sol.nlnetlabs.nl. 600 IN A 213.154.224.43 +sol.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. XEkjh4r+7asDkk98LEV5mlaIFD/nUvfP1eUBKVTfh4a8ba4W5sLo6HgY Y6sJcnaBuK0a4IDv2q2q/BPIokAcg72+P420oRD2vQXUhM+fgxVESJt5 AqWrqRetmctCOIhWuNhOYw1PlCT+lZ9eT5INhXAscepQyyjuAKQ+nQFK qW4= +sol.nlnetlabs.nl. 600 IN MX 100 sol.nlnetlabs.nl. +sol.nlnetlabs.nl. 600 IN RRSIG MX 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. gEqhZntMOkonkQ6ONN1fwqOPf/kp7XGQMsORg7MPEt8UUxfkx4FlIZSc uQU11EfLr14BE6zkPZj4i8927KmfWK6M2I5F9WWynq41xDPO5giI7nPQ xX1d2ga2Oq/kCHH5Q3DyWmXTrdc9JpbwKIQLdtPEmAN2t2VslSH77M2a IVE= +sol.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1:7200:ff:fe00:28e3 +sol.nlnetlabs.nl. 600 IN RRSIG AAAA 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. ExX2ABe4l4kOkFMeexofV/KE9u+XWvQKpdXtydtawymAz++crBdrYCUj 0tjDH8f9lUJEYPc/M0XUBj0FXrEK/OGrHREcj+U4dA4PfbKdCshp0+Ha jDqNigaFhwtXlRxwaaVX2F4B8y8WTOMpLeLA8GjH14gnC29TY/Fu5EAy rzM= +sparc5.nlnetlabs.nl. 18000 IN NSEC stun1.nlnetlabs.nl. A MX AAAA RRSIG NSEC +sparc5.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. ZGKUwlLbPYCQqGZQzUwaZUU7C89Qnq+7Uyo1VaPmDNMYLLxmi8RaRJKG SzNBDmr+om2MiEV68S4zkwj5aZ+IYB8cvvjdq8ZA4walYg1O8cf0OMFS A03lAnSfWiu9Ok7SryjltHfWZbEmS1bfhJQ7QVznKuIrzUbrx0giGxUl G7A= +sparc5.nlnetlabs.nl. 600 IN A 213.154.224.47 +sparc5.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. PqrRrkXcrTRXWSbrT1JZ9Rvt80SplTqpVgOlmLhe8qIxz+DiYdlBdIv9 bmb6orj1cLYG62/hWuGaW5UHpmslp1rn3LgrZCVbWS7JpULLEYs1l+B7 XYnRRGR4LlQ6cE1fZLbT55k4hMCnv+jYcto+gYDcp58ssZy3MUUyno+P C50= +sparc5.nlnetlabs.nl. 600 IN MX 50 open.nlnetlabs.nl. +sparc5.nlnetlabs.nl. 600 IN MX 100 omval.tednet.nl. +sparc5.nlnetlabs.nl. 600 IN RRSIG MX 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. G8cIIEKxLSh+Ql+OxYSCDdaeJ+iLreSS6DWLcgaMSXY+O0qXiy/avUYG IunyJyp95PuIle9OS6s3CpRTH7ZKcC7v80uAeBjGkwliIMaZc3L35x/t epNGGkw2FM2G0ZZCOoH55nw8CT9RHoKtvtXsr2A7er4gj2gLsk6sNSpo jqE= +sparc5.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1:a00:20ff:fea7:8f78 +sparc5.nlnetlabs.nl. 600 IN RRSIG AAAA 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. b9woyIw2bKMA3eJCTurjgBi1/3Er6Edgk6nT0iUBfzhv/qUK0K4ROor+ 9UkenclArkh2lbDHm/ziqn0z35gNn6FZUjo4L2x3jZQggxOuLz9ZhmpP es3eEArPU+c290i6NGGytrOmF5mh7S9h5nVapjDIPqgSBq7TtKBJ89wv ayc= +stun1.nlnetlabs.nl. 18000 IN NSEC stun2.nlnetlabs.nl. CNAME RRSIG NSEC +stun1.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. HFbzEeDw66ot0Qdm4S8z2YWJT3tD1HlRPhSwV/yN7GnJSQqmD4s6tUkz ZCyZtgcUNUwzm7ntIUMzD/njEiMCPWAR7SMoSHEnfLYlCx43GyiTDf8E J77Do1l8m116gA7sGnj6aPEsKrq/E0ml0yZn8sxRLhWEgxvCiGrQo652 e94= +stun1.nlnetlabs.nl. 600 IN CNAME johnny.nlnetlabs.nl. +stun1.nlnetlabs.nl. 600 IN RRSIG CNAME 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. Vfy6Magu59sn5mCUs1qf/6FghANc01hJ8kpFzmt9Sxhowf+xpuJnyG9a lsYjYHhzvjpCv1ys82aDlN4s28ILOt7sbgeBTfG30VX6F3WZ3A7EtWS4 4ZTEwwDvV+c5x/mm+HAQQCnz9LGuNLF/9rQOprHmEivomWqnp4sXRAHs TyI= +stun2.nlnetlabs.nl. 18000 IN NSEC tednet-gw.nlnetlabs.nl. A RRSIG NSEC +stun2.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. YQJd0U7xpSZanBGsDMR5o3Sim0aU91L52cDVkdG/mgfkOjJcvXskQbyb 39LQozpAas5PeBvQ6xK07KR0nza4fmg1882Nv5TI38CktrdoBO0m1oDa Zj3rM5MwxAd5jClVIKuQ3Nw0DsTLR5Tlm7IVPZMPrWUJjO5QILfjWXMH Ny0= +stun2.nlnetlabs.nl. 600 IN A 213.154.224.154 +stun2.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. ZxQ4qsRBDOj/BK800jqNncEQoyCWCqkZoT8VUmZOUdnUXv/pOQg3Fe51 a1/zeeUq9D7CPs5O8DV7OcYZSFpJHEA/GIBE+QGMT6wIdtlDl+lyvfOc lQnV+sf5t4jCexh/Mv/fSVgceO6aSqyiWc1jzQ/7kluQ/+Jk3RKJq7PA WUM= +tednet-gw.nlnetlabs.nl. 18000 IN NSEC ds10.testlab.nlnetlabs.nl. A RRSIG NSEC +tednet-gw.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. KKnPYYlzIMH7atLRWHIQMUim3GnfSQrpkRE49/2NeHcPuEgcSJebOf1l Ew/NEBiDCQtHEK0aiN+sE+nZ3tqdj951Ub9N332nKg98cNIqM5FVTcPS 8C5SrTH83O/xyhLbOYSJd+eOsuGlrmF0dnV6uFwC11DwGEp5fAtHXQ3/ SAQ= +tednet-gw.nlnetlabs.nl. 3600 IN A 213.154.224.33 +tednet-gw.nlnetlabs.nl. 3600 IN RRSIG A 5 3 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. jSPQxVwJ9Mks7+EAAYBrFkEmT8Pxmv1Op6AFldVRzsgNUh8AZYpsTqiO AH49+sbG8ZjHLSSKGdd54PGxPgTvF+h+B7NpSzpnachWIgczbiAejgsD X8EDS3D7JArouSl4/FPns2JKOJXyuA2vipB9Q0hota06O3s3T3VkOJLV Z+8= +ds10.testlab.nlnetlabs.nl. 18000 IN NSEC listener.testlab.nlnetlabs.nl. A AAAA RRSIG NSEC +ds10.testlab.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 4 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. CASiMvLsgqAkq6WIOqPIAtjAmi/fcd9mNCxJLgeOuyDrd6r/gbUTHky2 +sU2wYwpM19ThHyb+SLYTqlU/hI1dCpxMGVm5xf8PN3dINSZJFsKaaCx 01fg1j9LaZidOTLu8AtJqGH4TU+E7H7wvv4lvBYwwGejFHpM2r43CxIL DA4= +ds10.testlab.nlnetlabs.nl. 3600 IN A 213.154.224.100 +ds10.testlab.nlnetlabs.nl. 3600 IN RRSIG A 5 4 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. e9iqEEVgfnanV/2O/aNch3vIYbaAG4hvub+/UbbelsXDyADWfcVnunWU kF3WIsxFSqaZIQxAlHyIcK63z/jr+oDaGvPFmZcFE9cIU0rUlRC1GkVA pqNHcXRMcsPVdkX+kF82hbdy/CVqVGfEQfigcQq7E1bvLhs7ir+ckcRR 3gA= +ds10.testlab.nlnetlabs.nl. 3600 IN AAAA 2001:7b8:206:1:a00:2bff:fe86:cdb3 +ds10.testlab.nlnetlabs.nl. 3600 IN RRSIG AAAA 5 4 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. bWxVt+4GHXW2RIv5vxVeGRaDpI5O3wKoUoj71Nm+5Dx8ffzM/ZtcQNKs Xch2H+MowJ4EMqfct8YLufxFp7kv3aTYP7q/bhCk9PoxADSUVnZjs+Zh gSTTpX5InphKFEeT+JIg9RqAyYxMOSfjXU3KRI/xfWtzJ3VgYExVh4i5 UUw= +listener.testlab.nlnetlabs.nl. 18000 IN NSEC player.testlab.nlnetlabs.nl. A AAAA RRSIG NSEC +listener.testlab.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 4 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. dDJhcIcG9y/kF2WE/EbDG/5NKtY3cCv6VghKzv3gVnThDg24YwHq1x7s 3cGRzI6l1PpNAEBgim7Z90W5lIlfQfcwknDwh5fSZ7gD74KyG8/2I6SY EMTfW9P+cyM34Ujk8TwSlq0MLQYtElzfEkps0IC5nVRYvyRJYSzPOR51 y7w= +listener.testlab.nlnetlabs.nl. 3600 IN A 213.154.224.98 +listener.testlab.nlnetlabs.nl. 3600 IN RRSIG A 5 4 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. Sj5nJWIyGIuURQTGhIVfxNG8DqKDcTcwSRxWAihplSZ3gXdyL6M0qePn y23qlmj9H3DugndOol/vmmtDOUrAqOUTK3uKXeNuhJ8bxS5AN5f7PaJE CMGDMfvl9XTw6nlKF30ufpbXXlfZ26TFhfXjFmNz/r5H285kF/mNU8bF rX0= +listener.testlab.nlnetlabs.nl. 3600 IN AAAA 2001:7b8:206:1:42e0:4cff:fe39:6302 +listener.testlab.nlnetlabs.nl. 3600 IN RRSIG AAAA 5 4 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. PNZSXJS0xGP65+wQJtG4N8mBxeorUEVv8pRs4FtFqXv4wDvcnTpgCT4d 449V7gjlPk2ngQK5qpy68CvDVs47qrtfpgGQKOfNxeGpQbGsUE9I1114 B+38q4NUQldGGzzBQIxWBIlJnUVABPjAAyNVeSLVREVUp0m8wzsR1HQt syo= +player.testlab.nlnetlabs.nl. 18000 IN NSEC rotten.testlab.nlnetlabs.nl. A AAAA RRSIG NSEC +player.testlab.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 4 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. ICq3/OV9Pb9yt+dMASSV6EGiXZulQqsCYoWpUs3a+ZKHVqS1Qepi0vK1 4s/mtv0xn3z/qLDzUjB3UDH4ezo7WZJILQR1W0nVdRj+baCqnR/QfA+4 Y4F37cs8qfrT0neIpSyCzDEdlMaLext+OhyhYP2eQ/17NM/OFJiMavjw OXg= +player.testlab.nlnetlabs.nl. 3600 IN A 213.154.224.99 +player.testlab.nlnetlabs.nl. 3600 IN RRSIG A 5 4 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. F7/bPM5B1Ye9q1urMwT2DVH5u9K3eyDau20o/Zx272aXLkJP3s3fbjhB cUtQz9DFs6MLVthN3s3BN/2+JS5XsxqGeY2ypjhlpWxb4j759gEe79pz 188jzliidXkoTxHotaTfE4z1SR35cS/nfBbMEBLILgkC7TmQpXdh9WdD NQU= +player.testlab.nlnetlabs.nl. 3600 IN AAAA 2001:7b8:206:1:22e0:4cff:fe39:5e05 +player.testlab.nlnetlabs.nl. 3600 IN RRSIG AAAA 5 4 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. DuuL+20G6fAgD5VFMvDHTAm8hKxgvksDvsQRUJ8yT7RpBh/VZQKzpPR/ 0l9FeZZ00dy1x/QSdPTo56t84SUGdvPh219zvs6ksmg4kXfyZquv6m0f 19IoGFX3myQ//aKnE6XDI0jvZekKmY01NXEdC0ujZe06VUyHxUpR3bnQ pek= +rotten.testlab.nlnetlabs.nl. 18000 IN NSEC server.testlab.nlnetlabs.nl. A AAAA RRSIG NSEC +rotten.testlab.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 4 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. ZQqczzsqR6ob3f2ldPcxxUFwMoJHygObZkL7XqdkpuHV4WzfA9rw9wUZ FYi5dE3D+2sFPDY8LGjPyd0DqQswDdi80eecv/ZIROiL2ka0buFsFo9L 93RoeaB/f52ilAuvTaJUie8L38p9G9w0g9HljscUEbBhGUSzvB32fAbw SE4= +rotten.testlab.nlnetlabs.nl. 3600 IN A 213.154.224.101 +rotten.testlab.nlnetlabs.nl. 3600 IN RRSIG A 5 4 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. bDraapmxqrCuAcoLuAKxYN646POaFATJa+YJ/ZKSgCJC7efwjVzWAqvL ga3gR+uGu9iRUzQh68OE2IYOgxYtGvG/lkMYBfTcreO6NbgOnFCQ4+J5 BpxucrvgQxz9tVqyl84kG+eZiB+ksVF0FQRYhJxxZUqWTPcMtU2p1RTU dOw= +rotten.testlab.nlnetlabs.nl. 3600 IN AAAA 2001:7b8:206:1:206:5bff:fef2:ae8b +rotten.testlab.nlnetlabs.nl. 3600 IN RRSIG AAAA 5 4 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. EqVqCWsRTraX6Ykw2L8WOSnV3GG2Ox8T5fh/nHfBX+Nxp8fJJg/CE9+q eVU7GUyqzmobFSDrwc5O9cgtR6hJ/ZP4g2TEWob9TMIguCXByjzq6zqr 8SPn0WXmJV/hja4GnnEM2oe4AZxu1hjWW2YVCJ/LdslPyPqLDPosFcmz 8Fk= +server.testlab.nlnetlabs.nl. 18000 IN NSEC tinkerbell.nlnetlabs.nl. A AAAA RRSIG NSEC +server.testlab.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 4 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. TKWHK663II7q0IcML1dy+PsMLYNnrOg9SeXCpgsP8xYsiFHWHPrYViRY NC+tJj3G4ORrhp8qgSi5Zb/loXDNahL2hHsqfs3vmWyONMu5zysBtfC7 BO41fRBkDtDzxQchfpaII0DDNdXzMN6rF0/tA10zOzbetTOrAzdgO0aM h44= +server.testlab.nlnetlabs.nl. 3600 IN A 213.154.224.97 +server.testlab.nlnetlabs.nl. 3600 IN RRSIG A 5 4 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. jYUS4vthWsYDgB1Ks8vOx9qI7mcvLN4YdMb1UnUUMua/jWuZ3j0flmTJ n0oTXWuje5Fnyu+ZgpNAbR2/TgrP9GGwFbnvLcye5lcz0tSK8RQpja7I nVmzs+BSN6YgAmmNpl7hA49ofDPmxb4Uo+ykfh6DR7lPkgec1KuXC47M sFw= +server.testlab.nlnetlabs.nl. 3600 IN AAAA 2001:7b8:206:1:22e0:4cff:fe39:5e02 +server.testlab.nlnetlabs.nl. 3600 IN RRSIG AAAA 5 4 3600 20070912141341 20070815141341 18182 nlnetlabs.nl. a7mvvRN5wAwqObak5JMtWLrMyLCwDhB9eVZCON+nIE478i2WcuPFxWSx XYiOZGiZq7OwIBU7aO7BwaBMKXqNokbJqbwE8KGvLMXgnWQgqlUCHRBy 2YKD9tsFT5xCtaDcSynBlMri/z9Wk+KXxlf58Adj5yCIqTEGueT4n1LG QhQ= +tinkerbell.nlnetlabs.nl. 18000 IN NSEC ufo.nlnetlabs.nl. A RRSIG NSEC +tinkerbell.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. FX1z7mozbIq/4PufluGQ6ZVirevfKu8nZUHb9Ol4DNAD1nIu0v+teldL Ahx7fHpmzcYrMTA1n9Kktsim8cTd0LizMTd/wwWb+syExqNINZ1L20p1 nvIKzl/Razv27HKsY/kpiBUK7X+TCd/xJnFIO7D2JzoGjyiYpRGiaqef XxY= +tinkerbell.nlnetlabs.nl. 600 IN A 213.154.224.13 +tinkerbell.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. Ws7cRR7C2t+njlV/zBhVLfYPJN2l9fWOn97DjcU0sB6hT7r09cYIVV5u 8RTrH5UgwaboSqkImD+0LlbNte9nwcJS9wP3sItg/eO6eZyJ5NGKm/Nk 4KrKV6J1Vx1Ms+EtgzFhxYAiX4ThWBwZxaSNEDVh3ZCA+dAucURt315h xF0= +ufo.nlnetlabs.nl. 18000 IN NSEC unbound.nlnetlabs.nl. A MX RRSIG NSEC +ufo.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. IgEV6H97KEnxkNdhytWMjmtbXYerO61AqhAhDeD6J8iakPf83SqXOE9R ExwFmiSeqBRe+y/YZ+wVxLeWOU6okBrP4L6FAg57X+WVNNa123KD4r4j CMNR2hxXtFMjvvfRRPdi3i6JtTl2ygHJpvMzvbqJc2BrN7zdaGEG8bDU vQ8= +ufo.nlnetlabs.nl. 600 IN A 213.154.224.56 +ufo.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. mEc9varsLkWC5CCcQJqlSK1Tsk29Qfo6K2WzGQCLHaX+hhy83NbkHSss tYqXgpXNFUcxHRTmPoVofzlHFEkD+/5U8PxFEnSOI5FEfBbcYlHPSr7v l+8AJBPKXlC2ftVr7my7w+UhzvAODEbXxhveeqe/zJfeRImr+lJlANpk /pA= +ufo.nlnetlabs.nl. 600 IN MX 50 open.nlnetlabs.nl. +ufo.nlnetlabs.nl. 600 IN MX 100 omval.tednet.nl. +ufo.nlnetlabs.nl. 600 IN RRSIG MX 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. K2RffkDkyKmII1DVIgom/MeplVYzo6HLYgm4bbwbGP9y1T41XDwvgnvE EBI7OO+Dcz4m+adtIAD6/adkKYEQnqymok/BK1N1WArMtXXPyotRFOK7 UlrbYIFiIDE7GaVJsvJH0jyCDp8/pAJt7m3WLmhc579avWNvIPNqRAB7 uM0= +unbound.nlnetlabs.nl. 18000 IN NSEC viertje.nlnetlabs.nl. A MX AAAA RRSIG NSEC +unbound.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. T7VzMgdNSmXjZgw5VI8khY6k71BfeOH59r6vfHQhdlalMpALaDWYN6RD Oloslx7lLucA3ZrQ4X/RPwr84ZrRc0K0sH61MyQtuzyeiIWu8ifK7KHG yuxLYlngZx0jWsf2DgJuUaPaU6tzLLccfRJ0xZbbbv6TKL3sTD+EGSdI Wkc= +unbound.nlnetlabs.nl. 600 IN A 213.154.224.1 +unbound.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. euqJ/pC1YAuQB04coh1qWAptIkgfJDcJcGcKHH+bCGy5NK/IhEH8SKQE D0WlSD1pD+ibmeGQAi2be8eF3v2bHLog/Gm9wPjpxRj7lLkqtVxrXmyO pO6w7S9xfncsqJLkyyDhOgdg4/5LKghb6WAzkPKcMOd9GWLmVPdYhZ7u Pa4= +unbound.nlnetlabs.nl. 600 IN MX 10 open.nlnetlabs.nl. +unbound.nlnetlabs.nl. 600 IN RRSIG MX 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. YxVXw9KyfAmxJqhIKh6L2X2cs6eUnQNlo3xkenBPZW1UjEne6I4H0nbB hXWc4hWFaADJjLEJlXu0NoYTIsSVafynu4knJfmNiUykmWc2nqUy96R8 1qmQ+TknQ93qW8s/2LA5Maf8UjHqFhbZbX/EpGxlVFEc5WN1nNwIiSH+ hwM= +unbound.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1::1 +unbound.nlnetlabs.nl. 600 IN RRSIG AAAA 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. BwPZseI4zk7Kh4JFKGmeevVKIG4FtLVdajwGWluOk9vhC7Hv7jbEbO+R k/pfkJuibHy+cx0Rv72sRM6vK86G7WD9PsLseHJvCupXOcHB/gfrftfq kSRyt8bNs+XZ2oFVLLj9MkksbuJt7ZrJVhYneBUGvDyzDOitIhg6aIDt oPc= +viertje.nlnetlabs.nl. 18000 IN NSEC vrij-2.nlnetlabs.nl. A AAAA RRSIG NSEC +viertje.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. KDdYp63+Wl7DRcwjA90xwSOqZUGQsZnqweopqsaVhZ3eKz4seGnihRwh oXrNVJlAZpsujIrTZwfh9VbzbATtaUciVCfE4AjGdXxsLKhEQIGjExau XyFgCmaT4/kKc6d9Bdxhw2Lan2cClWQWCtlUEIDyoAybtwkmO5zU0Pil EvE= +viertje.nlnetlabs.nl. 600 IN A 213.154.224.62 +viertje.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. fldcX8mF5FC4YxcoPgOmLhGmW/TTw5MVLOwK35aItqemNfXwFglbuJtv KiW3Qdtcr5g5iE5xkDl9aCJRYlfAyugYgJX+AJ1WkO0nfpSUUbulOnRN MEZImO2EHsyA3JQCEHTZ+J8xfYQJ87rfAD/pRXbmh5TW+wiXckNflf4J rPM= +viertje.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1:203:93ff:feea:3086 +viertje.nlnetlabs.nl. 600 IN RRSIG AAAA 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. hFGUoyGTYcfURTEKx0qFYaJRBqzGeuctzC/rVQqLGTx0DhzVxNUIJN9V Rqj79FQXQ3S/XxOANmk14Y78HZmykUcARxCDDZGjgGrMTuuoQpYiDCdD FRhWWXr0/uS9yl0exj9Xo7fTIiGHe+d57CIuy8daJuxaBNXvc5+OIiyD U3U= +vrij-2.nlnetlabs.nl. 18000 IN NSEC www.nlnetlabs.nl. A MX RRSIG NSEC +vrij-2.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. avyjH0dMBtuhwewLd0ZIy/m4dFJCqdD2sWhq7X7s/wHIf4A3sSAZecFf 5Eu0gtyKkX4cIhFjrPzj6NTJPIUZmkaEAXIsmJ6sVw58+Wc6dP0E84d/ WQ8vBkpYzoAWVH5p9FDyax/3jNmn5U5KAqraOy3UaihnbafpmyR801kz 0uQ= +vrij-2.nlnetlabs.nl. 600 IN A 213.154.224.53 +vrij-2.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. ieo0tj2nMObHvje9Zb8KuhHzEE7hAo/d61NovqrGEe3MKFZ1Q/m15bC7 QTXZpuqundT1cIDPQmc9nA7vC7dX3JZameQ1j5QE3GSiNuU5xpFmnpvc KTBQbSDer+dncn/A3F+qY2HjylgkzMrmxRRSxOjexVIYCjFbtUvYsiAd KRk= +vrij-2.nlnetlabs.nl. 600 IN MX 50 open.nlnetlabs.nl. +vrij-2.nlnetlabs.nl. 600 IN MX 100 sanne.nlnetlabs.nl. +vrij-2.nlnetlabs.nl. 600 IN RRSIG MX 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. hwamqP2ZCEhBO5Wn12GsZoKwxkmhn7J0NTbsuYKF2Vk23aPlV9qc7yfR SnK2G4y33dq/omt6LxN+29Sd+9lcu/Krx3rlYd5Y/dmu2ZX/SXX+XVUY Iqla+LwyYe6UWhG1zdvtD5UHuBBYocGcGud9amqFXHo8Q7YVded4AkoC 1BQ= +www.nlnetlabs.nl. 18000 IN NSEC nlnetlabs.nl. A AAAA RRSIG NSEC +www.nlnetlabs.nl. 18000 IN RRSIG NSEC 5 3 18000 20070912141341 20070815141341 18182 nlnetlabs.nl. L2RzZigsb3UEJTef8PTiDghDDWsRdwEFRUNZTSm79MO6poZOkq/0yzBr mfRMo3ST2wHfcyV+/Ws11imgrZ4EVXZ8bynQ7HFVnsI1xH/SrMHSUnzQ g1OPsiXJbukgfVaM0q4URq6cmBSuX6Ti/6waq39j4Cj3UJXAClG3lloB z+o= +www.nlnetlabs.nl. 600 IN A 213.154.224.1 +www.nlnetlabs.nl. 600 IN RRSIG A 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. Luav3fjE1VGhran3tnxR93cgoEyH3Kh//240KDCT8k0U4Tfw6xSBMVjj rf3oH13SXCZfYdJYZbZEahBvysMRm40Izl4+rpfUKzwjHXn1una1o4Gt A48v0fwffCXtUPz1TDFq9IKlVe95uLwjheMF8auDXHLwLItj2lF827Dd VI0= +www.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1::1 +www.nlnetlabs.nl. 600 IN RRSIG AAAA 5 3 600 20070912141341 20070815141341 18182 nlnetlabs.nl. kNBkVXmMFOsKXv6IdhydkSbopCxiW1gHOVHv3G9co1SzRuaubyZ+Z7PL 5xVVMwx9Z7AwvwZ1t4b3IqVnXOXtdbABMSlUyLLRxMGt6pPt6jrcFery 7aNlmtIEStJ4FBLL5T8wdsNWUP4/iV9iTrppB/Emxp0dTz77MF2rpI+V DL0= +nlnetlabs.nl. 86400 IN RRSIG SOA 5 2 86400 20070912141341 20070815141341 18182 nlnetlabs.nl. C54bDHKC2sRbVUrDOeM2kXCHpJIFu0LlZWAFVFLf4l1Grfj+B4WcXqel kSVhi/Gpt70VW+zDEOHrS0kcE5XaBnrQE1AUZ9QjGyfjXlRzGWYbyVLD evIFrs7FdIeGKKWWp1YDLUHHF+txDT9NFu6KyEqPbZEVgIVok3skO5Vu jpA= +nlnetlabs.nl. 86400 IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2007081501 28800 7200 604800 18000 +;; Query time: 20 msec +;; SERVER: 2001:7b8:206:1::53#53(2001:7b8:206:1::53) +;; WHEN: Thu Aug 16 11:36:35 2007 +;; XFR size: 493 records (messages 1, bytes 50727) +ENTRY_END diff --git a/testdata/test_signatures.2 b/testdata/test_signatures.2 new file mode 100644 index 00000000000..03378538e95 --- /dev/null +++ b/testdata/test_signatures.2 @@ -0,0 +1,23 @@ +; Signature test file + +; first entry is a DNSKEY answer, with the DNSKEY rrset used for verification. +; later entries are verified with it. + + +; DNSKEY used for testing, from april 2008 +ENTRY_BEGIN +SECTION QUESTION +cesar.sec3.br. IN DNSKEY +SECTION ANSWER +cesar.sec3.br. 43200 IN DNSKEY 257 3 3 AMAdw+X4IcinbsSOXamwV4BrJVbRjSJ63DYRV0NLR4W5cDMEQGmB3Lci ybjLvaEogs9RDmjhxQrQJRfaIVMG11LtOwlTPBr4yzyeK9zzeZPAQz2F 9yCCPqgUdts51v4XeK5evtn+b4AB7t/j+v7Vb+26k8No6hmJiRJAy59N Fpzrt5FoY5qFZ8QbPl59nzEcXTbOiXBNSu9mQbe/jFH5p9NP4KB0iNL/ oAthNIVVsDG8hQFh1hE5YlDNLxYY3U+TODjWx//DZvkn5Tyyvp7I6b33 oJiq +ENTRY_END + +; entry to test +ENTRY_BEGIN +SECTION QUESTION +cesar.sec3.br. IN SOA +SECTION ANSWER +cesar.sec3.br. 43200 IN SOA home.kuroiwa.eng.br. hostmaster.cesar.sec3.br. 2008040903 86400 86400 8640000 600 +cesar.sec3.br. 43200 IN RRSIG SOA 3 3 43200 20081010000000 20080410122550 14996 cesar.sec3.br. AJOGbuGOMggPspEBhIc58I8BXUHqR+DKiZqGZRwu9jMTgAX6JCPunSI= ;{id = 14996} +ENTRY_END + diff --git a/testdata/test_signatures.3 b/testdata/test_signatures.3 new file mode 100644 index 00000000000..fddc462c2b6 --- /dev/null +++ b/testdata/test_signatures.3 @@ -0,0 +1,48 @@ +; Signature test file + +; first entry is a DNSKEY answer, with the DNSKEY rrset used for verification. +; later entries are verified with it. + +; created test keys with bind tools: +; dnssec-keygen 9.4.2: /usr/sbin/dnssec-keygen -a DSA -b 512 -n ZONE nlnetlabs.nl +; Knlnetlabs.nl.+003+03510 + +; private key file: +; Private-key-format: v1.2 +; Algorithm: 3 (DSA) +; Prime(p): 4nziv5P4tsXwaf71EoyKFoLzFq0/wN5fb6yb8IY5uwmVh5hvO0M4lR8LAjwimCIo3SYEdCnUPkl8WbJYHkRm9w== +; Subprime(q): 3ueDKL3Jc2Ue1G/ZCfhwMEyR4v0= +; Base(g): Ji9iYukmprX5qXO7V0MALKCTsfvz3kef2TsZdpM/VdetDK53OwKE1NRTMU6PSPGyumedOrkSD2BLa7CT1dJRJQ== +; Private_value(x): wlEfaVwW10q6Re/ZOBL9PLJJb20= +; Public_value(y): cHuTGyrkbj5QVkgmFm3KEpLnb5c7jH6tapeU5ugEIJiacbroPhfz/9vPw8tkZedBGImuYPSohRPfHIQPMxfxAg== + + +; DSA key from bind tool 9.4.2 +ENTRY_BEGIN +SECTION QUESTION +nlnetlabs.nl. IN DNSKEY +SECTION ANSWER +nlnetlabs.nl. IN DNSKEY 256 3 3 AN7ngyi9yXNlHtRv2Qn4cDBMkeL94nziv5P4tsXwaf71EoyKFoLzFq0/ wN5fb6yb8IY5uwmVh5hvO0M4lR8LAjwimCIo3SYEdCnUPkl8WbJYHkRm 9yYvYmLpJqa1+alzu1dDACygk7H7895Hn9k7GXaTP1XXrQyudzsChNTU UzFOj0jxsrpnnTq5Eg9gS2uwk9XSUSVwe5MbKuRuPlBWSCYWbcoSkudv lzuMfq1ql5Tm6AQgmJpxuug+F/P/28/Dy2Rl50EYia5g9KiFE98chA8z F/EC +ENTRY_END + +; entry to test +; from +; /usr/sbin/dnssec-signzone nlnetlabs.nl +ENTRY_BEGIN +SECTION QUESTION +nlnetlabs.nl. IN SOA +SECTION ANSWER +nlnetlabs.nl. 10200 IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. ( 2008040100 28800 7200 604800 3600 ) +nlnetlabs.nl. 10200 RRSIG SOA 3 2 10200 20080515132632 ( 20080415132632 3510 nlnetlabs.nl. ACYwIl9GQofKJ2xdgx1YelKbtmLrWRl8f+eC ToRnfyQ+gvdUIX3mTTw= ) +ENTRY_END + +ENTRY_BEGIN +SECTION QUESTION +nlnetlabs.nl. IN NS +SECTION ANSWER +nlnetlabs.nl. 10200 NS omval.tednet.nl. +nlnetlabs.nl. 10200 NS ns7.domain-registry.nl. +nlnetlabs.nl. 10200 NS open.nlnetlabs.nl. +nlnetlabs.nl. 10200 RRSIG NS 3 2 10200 20080515132632 ( 20080415132632 3510 nlnetlabs.nl. AEYy9ZN3KEDHybhZbL3PoR71jMQuufKM1lej +obA6uL6CjYQAPrL9tk= ) +ENTRY_END + diff --git a/testdata/test_signatures.4 b/testdata/test_signatures.4 new file mode 100644 index 00000000000..fbda8f9e6ae --- /dev/null +++ b/testdata/test_signatures.4 @@ -0,0 +1,47 @@ +; Signature test file + +; first entry is a DNSKEY answer, with the DNSKEY rrset used for verification. +; later entries are verified with it. + +; dnssec-keygen 9.4.2: /usr/sbin/dnssec-keygen -a DSA -b 768 -n ZONE nlnetlabs.nl +; Knlnetlabs.nl.+003+03793 + +; private key file +; Private-key-format: v1.2 +; Algorithm: 3 (DSA) +; Prime(p): lHKDKRMhV1yBk/gXk3IL29jkPwWwOqEskebo/hC0ieobdQkeuf9B3AgzCdn2hQOWVGoIMWyxChhqHVLwnQzUGY/uAhTZgSXBG47eHZC+Pj1hgX9tkB+9kzoK5jKhstR9 +; Subprime(q): 6u+5FI/H5WmwyTPWB5K0LjegVb0= +; Base(g): hWj33Fnu7b9vhIriw6nXnJKpeus9pffjSaKzVJBNnlWTMXbo3+w3rObnJlbkVLfRsY4F8boWn1EbUUHCaRIW3bsqziE739S8HBJDDwxYx85n0xRqkg0djWoCG2e4uv4o +; Private_value(x): xSLjPW1PE6twDgObqfkUk6EXO+g= +; Public_value(y): ORFJhDQMHGQNdWXlh05vAJJ8Fqm6u+72qsIY2pnSgWL7vQIL6sKKJL14oIVJbsZW9FIjQCFpqe19leUdzUDQa9AxB8WSRAzmh4S6tWkmbAGpUjoAUJSLtqV1NgvH8ESg + + +; DSA key from bind tool 9.4.2 +ENTRY_BEGIN +SECTION QUESTION +nlnetlabs.nl. IN DNSKEY +SECTION ANSWER +nlnetlabs.nl. IN DNSKEY 256 3 3 BOrvuRSPx+VpsMkz1geStC43oFW9lHKDKRMhV1yBk/gXk3IL29jkPwWw OqEskebo/hC0ieobdQkeuf9B3AgzCdn2hQOWVGoIMWyxChhqHVLwnQzU GY/uAhTZgSXBG47eHZC+Pj1hgX9tkB+9kzoK5jKhstR9hWj33Fnu7b9v hIriw6nXnJKpeus9pffjSaKzVJBNnlWTMXbo3+w3rObnJlbkVLfRsY4F 8boWn1EbUUHCaRIW3bsqziE739S8HBJDDwxYx85n0xRqkg0djWoCG2e4 uv4oORFJhDQMHGQNdWXlh05vAJJ8Fqm6u+72qsIY2pnSgWL7vQIL6sKK JL14oIVJbsZW9FIjQCFpqe19leUdzUDQa9AxB8WSRAzmh4S6tWkmbAGp UjoAUJSLtqV1NgvH8ESg +ENTRY_END + +; entry to test +; from +; /usr/sbin/dnssec-signzone nlnetlabs.nl +ENTRY_BEGIN +SECTION QUESTION +nlnetlabs.nl. IN SOA +SECTION ANSWER +nlnetlabs.nl. 10200 IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. ( 2008040100 28800 7200 604800 3600 ) +nlnetlabs.nl. 10200 RRSIG SOA 3 2 10200 20080515133546 ( 20080415133546 3793 nlnetlabs.nl. BHMt1eWN8HzfFOqrqL1PrsED43JVCrybDYL1 GJXymKlkWRAjar0wT6o= ) +ENTRY_END + +ENTRY_BEGIN +SECTION QUESTION +nlnetlabs.nl. IN NS +SECTION ANSWER +nlnetlabs.nl. 10200 NS omval.tednet.nl. +nlnetlabs.nl. 10200 NS ns7.domain-registry.nl. +nlnetlabs.nl. 10200 NS open.nlnetlabs.nl. +nlnetlabs.nl. 10200 RRSIG NS 3 2 10200 20080515133546 ( 20080415133546 3793 nlnetlabs.nl. BJZaThgkBaF3k6t2q+tr0ngKcF2EntSOn9gX Ut9Xipj3CdioZl8b0cY= ) +ENTRY_END + diff --git a/testdata/test_signatures.5 b/testdata/test_signatures.5 new file mode 100644 index 00000000000..2e9c55c1dd8 --- /dev/null +++ b/testdata/test_signatures.5 @@ -0,0 +1,48 @@ +; Signature test file + +; first entry is a DNSKEY answer, with the DNSKEY rrset used for verification. +; later entries are verified with it. + +; ldns-keygen (svn trunk 1.3.0, 15 april 2008) +; ./ldns-keygen -a DSAMD5 -b 512 nlnetlabs.nl +; Knlnetlabs.nl.+003+08866 + +; nlnetlabs.nl. 3600 IN DS 8866 3 1 1300e7258af98cef40a47e6ac1e34ea79cb4b27f +; Private-key-format: v1.2 +; Algorithm: 3 (DSA) +; Prime(p): qp/0xtfW76CbSH29kZmI0iUEhJ9cIs/52WsgqogqBwrY/HpT+D6G2jd66WLi88DF0z/We3/YIjZYkR5PH03IRQ== +; Subprime(q): iTRl4piaQvy9yxIsz/c5pAaVIeM= +; Base(g): RJhjYU22ooiTKltbGmIR6OfXZjKDBfSODrT3e3/IrwiT8oQZriDFZkExYKrKqoqZFn7y0esTf9Bwvx2IhGabQw== +; Private_value(x): gYjuQexf8JiiVBvCcxpXO+QaD88= +; Public_value(y): aPtEU9ui/w2+9aFnCrWUB/fGvMEyAyLyGCCaT/N+l8bPYDPCv+wDxEKHoM3HT/ZOf3RuCE/CYKVK7CDX6+AZrA== + +; DSA key from ldns tool +ENTRY_BEGIN +SECTION QUESTION +nlnetlabs.nl. IN DNSKEY +SECTION ANSWER +nlnetlabs.nl. 3600 IN DNSKEY 256 3 3 AIk0ZeKYmkL8vcsSLM/3OaQGlSHjqp/0xtfW76CbSH29kZmI0iUEhJ9cIs/52WsgqogqBwrY/HpT+D6G2jd66WLi88DF0z/We3/YIjZYkR5PH03IRUSYY2FNtqKIkypbWxpiEejn12YygwX0jg6093t/yK8Ik/KEGa4gxWZBMWCqyqqKmRZ+8tHrE3/QcL8diIRmm0No+0RT26L/Db71oWcKtZQH98a8wTIDIvIYIJpP836Xxs9gM8K/7APEQoegzcdP9k5/dG4IT8JgpUrsINfr4Bms ;{id = 8866 (zsk), size = 512b} +ENTRY_END + +; entry to test +; from +; ldns-signzone nlnetlabs.nl Knlnetlabs.nl.+003+08866 +ENTRY_BEGIN +SECTION QUESTION +nlnetlabs.nl. IN SOA +SECTION ANSWER +nlnetlabs.nl. 10200 IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. ( 2008040100 28800 7200 604800 3600 ) +nlnetlabs.nl. 10200 IN RRSIG SOA 3 2 10200 20080513173901 20080415173901 8866 nlnetlabs.nl. MC0CFFI7JB0x4xaO0qhe9iQGk0eot8zGAhUAg/SFtf5MrR7DEkmd6vm2xf+SN9M= ;{id = 8866} +ENTRY_END + +ENTRY_BEGIN +SECTION QUESTION +nlnetlabs.nl. IN NS +SECTION ANSWER +nlnetlabs.nl. 10200 NS omval.tednet.nl. +nlnetlabs.nl. 10200 NS ns7.domain-registry.nl. +nlnetlabs.nl. 10200 NS open.nlnetlabs.nl. +nlnetlabs.nl. 10200 IN RRSIG NS 3 2 10200 20080513173901 20080415173901 8866 nlnetlabs.nl. MCwCFFHwxz9Kx7Un60vLMMoOrZizagNrAhR6OskQNF/KVL5/xanbOmK3ZUj0vw== ;{id = 8866} + +ENTRY_END + diff --git a/testdata/test_signatures.6 b/testdata/test_signatures.6 new file mode 100644 index 00000000000..be6f09092f2 --- /dev/null +++ b/testdata/test_signatures.6 @@ -0,0 +1,48 @@ +; Signature test file + +; first entry is a DNSKEY answer, with the DNSKEY rrset used for verification. +; later entries are verified with it. + +; ldns-keygen (svn trunk 1.3.0, 15 april 2008) +; ./ldns-keygen -a DSAMD5 -b 768 nlnetlabs.nl +; Knlnetlabs.nl.+003+51124 + +; nlnetlabs.nl. 3600 IN DS 51124 3 1 6f7e3ea1d525f3428ce342596f7375b1c3a71c51 +; Private-key-format: v1.2 +; Algorithm: 3 (DSA) +; Prime(p): 1kpY0hU98SJrpDCTKHv9TQyN6EGcY9FJ8bw0QiQdcm3nx3fkS298V9Y7ZRzjCQmkxVwNrwdhtNpz4MvrByHKy+YE/hSJamNhwKHAtiIAHNggqfutGQwUkfqHmybFO8Kx +; Subprime(q): 3GwgwvHRyOeXNgZqR/5XpaNs6Pc= +; Base(g): Rw1YckcZ/Es07FYrNV6soRTbcQ5NEDj7ITSUdGSLKRPQT0k4ofR3L8aslTeOJESR2s2sIay/ZHoYmdQuwLZ93HLEq5MooPO19c/GnVkOWZm1Ab9H7zttNcoKgzQ64dhT +; Private_value(x): OoN8CQisHVjCIET7B3WdAwERRro= +; Public_value(y): 08zY8i9l5qn1xC829beHq2Hhb8MUIvGHyW+eBchQa4S5XIRwf1rVpnw1iengslp/Y1Kx28/a9GEQbIESQORfxllPV23Uv2OJ3aNV0jP7kI2a7VLVSDSJrCh2wBCFj8tY + +; DSA key from ldns tool +ENTRY_BEGIN +SECTION QUESTION +nlnetlabs.nl. IN DNSKEY +SECTION ANSWER +nlnetlabs.nl. 3600 IN DNSKEY 256 3 3 BNxsIMLx0cjnlzYGakf+V6WjbOj31kpY0hU98SJrpDCTKHv9TQyN6EGcY9FJ8bw0QiQdcm3nx3fkS298V9Y7ZRzjCQmkxVwNrwdhtNpz4MvrByHKy+YE/hSJamNhwKHAtiIAHNggqfutGQwUkfqHmybFO8KxRw1YckcZ/Es07FYrNV6soRTbcQ5NEDj7ITSUdGSLKRPQT0k4ofR3L8aslTeOJESR2s2sIay/ZHoYmdQuwLZ93HLEq5MooPO19c/GnVkOWZm1Ab9H7zttNcoKgzQ64dhT08zY8i9l5qn1xC829beHq2Hhb8MUIvGHyW+eBchQa4S5XIRwf1rVpnw1iengslp/Y1Kx28/a9GEQbIESQORfxllPV23Uv2OJ3aNV0jP7kI2a7VLVSDSJrCh2wBCFj8tY ;{id = 51124 (zsk), size = 768b} +ENTRY_END + +; entry to test +; from +; ldns-signzone nlnetlabs.nl Knlnetlabs.nl.+003+51124 +ENTRY_BEGIN +SECTION QUESTION +nlnetlabs.nl. IN SOA +SECTION ANSWER +nlnetlabs.nl. 10200 IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. ( 2008040100 28800 7200 604800 3600 ) +nlnetlabs.nl. 10200 IN RRSIG SOA 3 2 10200 20080513174626 20080415174626 51124 nlnetlabs.nl. MC0CFB3cRDHQROzkGp4NtLNc4jDA1lhWAhUAgsbb8VMxGqifShEzuCNgczxDHHg= ;{id = 51124} +ENTRY_END + +ENTRY_BEGIN +SECTION QUESTION +nlnetlabs.nl. IN NS +SECTION ANSWER +nlnetlabs.nl. 10200 NS omval.tednet.nl. +nlnetlabs.nl. 10200 NS ns7.domain-registry.nl. +nlnetlabs.nl. 10200 NS open.nlnetlabs.nl. +nlnetlabs.nl. 10200 IN RRSIG NS 3 2 10200 20080513174626 20080415174626 51124 nlnetlabs.nl. MCwCFEzgEjT0n/ooV/xZkRMzKNqeF4pkAhQxEPFtMt5LbIlsi9mSi0HS4+RZuA== ;{id = 51124} + +ENTRY_END + diff --git a/testdata/test_signatures.7 b/testdata/test_signatures.7 new file mode 100644 index 00000000000..8c629980d50 --- /dev/null +++ b/testdata/test_signatures.7 @@ -0,0 +1,32 @@ +; Signature test file + +; first entry is a DNSKEY answer, with the DNSKEY rrset used for verification. +; later entries are verified with it. + +; DSA Key from ldns tool, key used in the testbound tests. + +; DSA key from ldns tool +ENTRY_BEGIN +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJIIs70j+sDS/UT2QRp61SE7S3EEXopNXoFE73JLRmvpi/UrOO/Vz4Se6wXv/CYCKjGw06U4WRgRYXcpEhJROyNapmdIKSxhOzfLVE1gqA0PweZR8dtY3aNQSRn3sPpwJr6Mi/PqQKAMMrZ9ckJpf1+bQMOOvxgzz2U1GS18b3yZKcgTMEaJzd/GZYzi/BN2DzQ0MsrSwYXfsNLFOBbs8PJMW4LYIxeeOe6rUgkWOF7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +ENTRY_END + +; entry to test +ENTRY_BEGIN +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + diff --git a/testdata/test_signatures.8 b/testdata/test_signatures.8 new file mode 100644 index 00000000000..7e607a4f778 --- /dev/null +++ b/testdata/test_signatures.8 @@ -0,0 +1,83 @@ +; Signature test file + +; first entry is a DNSKEY answer, with the DNSKEY rrset used for verification. +; later entries are verified with it. + +; RSA Key from ldns tool, key used in the testbound tests. + +; RSA key from ldns tool +ENTRY_BEGIN +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +ENTRY_END + +; entry to test -- capitals in signer name. +ENTRY_BEGIN +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. 3600 IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sUb.eXamPle.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +ENTRY_END + +; entry to test +ENTRY_BEGIN +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. 3600 IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +ENTRY_END + +; another entry. Signed with ldns. +ENTRY_BEGIN +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. 3600 IN A 11.11.11.11 +www.sub.example.com. 3600 IN A 22.22.22.22 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. A1rCcVWeTZ5u0Fr1IewSOhpZvpSd8jMBsy4zk12LzZbjFK2yINSpClGYoyRvJMySfbNHjFKfufR/YpdsrsjC8A== ;{id = 30899} +ENTRY_END + +; another entry. Signed with ldns. 10800 ttl +ENTRY_BEGIN +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. 10800 IN A 11.11.11.11 +www.sub.example.com. 10800 IN A 22.22.22.22 +www.sub.example.com. 10800 IN RRSIG A 5 4 10800 20070926134150 20070829134150 30899 sub.example.com. gRrsfYr57vipJHXE21RmXp0Y4cwp9rHyTYeqf1ncBgeipYSPFMILRw21wvAKNKEQ418/0toZOw6Nfmc1gXWS/w== ;{id = 30899} +ENTRY_END + +; another entry. Signed with ldns. 10800 ttl original, now modified TTLs +ENTRY_BEGIN +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. 3600 IN A 11.11.11.11 +www.sub.example.com. 10800 IN A 22.22.22.22 +www.sub.example.com. 10800 IN RRSIG A 5 4 10800 20070926134150 20070829134150 30899 sub.example.com. gRrsfYr57vipJHXE21RmXp0Y4cwp9rHyTYeqf1ncBgeipYSPFMILRw21wvAKNKEQ418/0toZOw6Nfmc1gXWS/w== ;{id = 30899} +ENTRY_END + +; another entry. Signed with ldns. 10800 ttl original, now modified TTLs +ENTRY_BEGIN +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. 10800 IN A 11.11.11.11 +www.sub.example.com. 3600 IN A 22.22.22.22 +www.sub.example.com. 10800 IN RRSIG A 5 4 10800 20070926134150 20070829134150 30899 sub.example.com. gRrsfYr57vipJHXE21RmXp0Y4cwp9rHyTYeqf1ncBgeipYSPFMILRw21wvAKNKEQ418/0toZOw6Nfmc1gXWS/w== ;{id = 30899} +ENTRY_END + +; another entry. Signed with ldns. 10800 ttl original, now modified TTLs +ENTRY_BEGIN +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. 1234 IN A 11.11.11.11 +www.sub.example.com. 3600 IN A 22.22.22.22 +www.sub.example.com. 10800 IN RRSIG A 5 4 10800 20070926134150 20070829134150 30899 sub.example.com. gRrsfYr57vipJHXE21RmXp0Y4cwp9rHyTYeqf1ncBgeipYSPFMILRw21wvAKNKEQ418/0toZOw6Nfmc1gXWS/w== ;{id = 30899} +ENTRY_END + diff --git a/testdata/test_sigs.ecdsa_p256 b/testdata/test_sigs.ecdsa_p256 new file mode 100644 index 00000000000..28d08a7e948 --- /dev/null +++ b/testdata/test_sigs.ecdsa_p256 @@ -0,0 +1,23 @@ +; Signature test file + +; first entry is a DNSKEY answer, with the DNSKEY rrset used for verification. +; later entries are verified with it. + +; Test ECDSA P256 signatures from draft-ietf-dnsext-ecdsa-04 + +ENTRY_BEGIN +SECTION QUESTION +example.net. IN DNSKEY +SECTION ANSWER +example.net. 3600 IN DNSKEY 257 3 13 ( GojIhhXUN/u4v54ZQqGSnyhWJwaubCvTmeexv7bR6edb krSqQpF64cYbcB7wNcP+e+MAnLr+Wi9xMWyQLc8NAA== ) +ENTRY_END + +; entry to test +ENTRY_BEGIN +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +www.example.net. 3600 IN A 192.0.2.1 +www.example.net. 3600 IN RRSIG A 13 3 3600 ( 20100909100439 20100812100439 55648 example.net. qx6wLYqmh+l9oCKTN6qIc+bw6ya+KJ8oMz0YP107epXA yGmt+3SNruPFKG7tZoLBLlUzGGus7ZwmwWep666VCw== ) +ENTRY_END + diff --git a/testdata/test_sigs.ecdsa_p384 b/testdata/test_sigs.ecdsa_p384 new file mode 100644 index 00000000000..fc5d12e1b63 --- /dev/null +++ b/testdata/test_sigs.ecdsa_p384 @@ -0,0 +1,23 @@ +; Signature test file + +; first entry is a DNSKEY answer, with the DNSKEY rrset used for verification. +; later entries are verified with it. + +; Test ECDSA P384 signatures from draft-ietf-dnsext-ecdsa-04 + +ENTRY_BEGIN +SECTION QUESTION +example.net. IN DNSKEY +SECTION ANSWER +example.net. 3600 IN DNSKEY 257 3 14 ( xKYaNhWdGOfJ+nPrL8/arkwf2EY3MDJ+SErKivBVSum1 w/egsXvSADtNJhyem5RCOpgQ6K8X1DRSEkrbYQ+OB+v8 /uX45NBwY8rp65F6Glur8I/mlVNgF6W/qTI37m40 ) +ENTRY_END + +; entry to test +ENTRY_BEGIN +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +www.example.net. 3600 IN A 192.0.2.1 +www.example.net. 3600 IN RRSIG A 14 3 3600 ( 20100909102025 20100812102025 10771 example.net. /L5hDKIvGDyI1fcARX3z65qrmPsVz73QD1Mr5CEqOiLP 95hxQouuroGCeZOvzFaxsT8Glr74hbavRKayJNuydCuz WTSSPdz7wnqXL5bdcJzusdnI0RSMROxxwGipWcJm ) +ENTRY_END + diff --git a/testdata/test_sigs.gost b/testdata/test_sigs.gost new file mode 100644 index 00000000000..ebc85aabb9f --- /dev/null +++ b/testdata/test_sigs.gost @@ -0,0 +1,40 @@ +; Signature test file + +; first entry is a DNSKEY answer, with the DNSKEY rrset used for verification. +; later entries are verified with it. + +; Test GOST signatures using algo number 12. + +ENTRY_BEGIN +SECTION QUESTION +nlnetlabs.nl. IN DNSKEY +SECTION ANSWER +nlnetlabs.nl. 3600 IN DNSKEY 256 3 12 9SZY+xB3wKtrLoRHzkBs9L3fjcvazjnk5HF3gMaD1PVp4pthrwgHIm0TUaLrd3YCa2VCl5wj+MzbhZi8NEJ/Cg== ;{id = 60385 (zsk), size = 512b} +ENTRY_END + +; entry to test +ENTRY_BEGIN +SECTION QUESTION +open.nlnetlabs.nl. IN A +SECTION ANSWER +open.nlnetlabs.nl. 600 IN A 213.154.224.1 +open.nlnetlabs.nl. 600 IN RRSIG A 12 3 600 20090903100515 20090806100515 60385 nlnetlabs.nl. XVxDmt7/gRk13Yv+U+RPuEZ86iCGSVPmTcpMZYJs14Yn6Y/On8X+vgLV6IzxQTxAwGb+D35/dUfT55p6pFo8YQ== ;{id = 60385} +ENTRY_END + +ENTRY_BEGIN +SECTION QUESTION +open.nlnetlabs.nl. IN AAAA +SECTION ANSWER +open.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1::1 +open.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1::53 +open.nlnetlabs.nl. 600 IN RRSIG AAAA 12 3 600 20090903100515 20090806100515 60385 nlnetlabs.nl. +tdW+Uhkl2dBsD3zjGFGg1UtkBgfEhM6aXzERl0gWElgoJ4pCpXTV7VhZQ4yjibpMYjcXsBhQLcN7AuG20Ps9Q== ;{id = 60385} +ENTRY_END + +ENTRY_BEGIN +SECTION QUESTION +open.nlnetlabs.nl. IN NSEC +SECTION ANSWER +open.nlnetlabs.nl. 3600 IN NSEC nlnetlabs.nl. A AAAA RRSIG NSEC +open.nlnetlabs.nl. 3600 IN RRSIG NSEC 12 3 3600 20090903100515 20090806100515 60385 nlnetlabs.nl. vOzQQh9ITdgD74ohIE37L8mAZcgDt7V+HrrPjCdalsFYw9dvGwuEvc0MfSDmzrFQ7OhL0elwI/A1AfK57M7emQ== ;{id = 60385} +ENTRY_END + diff --git a/testdata/test_sigs.hinfo b/testdata/test_sigs.hinfo new file mode 100644 index 00000000000..eb4d594abc3 --- /dev/null +++ b/testdata/test_sigs.hinfo @@ -0,0 +1,55 @@ +; Signature test file + +; first entry is a DNSKEY answer, with the DNSKEY rrset used for verification. +; later entries are verified with it. + +; Test HINFO canonicalisation + +; RSA key from ldns tool +ENTRY_BEGIN +SECTION QUESTION +jelte.nlnetlabs.nl. IN DNSKEY +SECTION ANSWER +jelte.nlnetlabs.nl. 3600 IN DNSKEY 256 3 5 AwEAAawmHBgxeOiaYE4JpNU+CBqEj7xGB1o6ThEsUmtjsbmTnsJ89uWv 2PudzhQKCR1hJtuxVxG0Aw4mwHlAy+SoWHp8NXW1JYVA5qbvYhUUUM3l +ZFImaMhShhlviJJDLla5nmB5pyNYbC4wxqkCs51mzJY1abbCmZepmQL IlprTjUL +ENTRY_END + +; check that signatures work +ENTRY_BEGIN +SECTION QUESTION +jelte.nlnetlabs.nl. IN NS +SECTION ANSWER +jelte.nlnetlabs.nl. 3600 IN NS ns1.jelte.nlnetlabs.nl. +jelte.nlnetlabs.nl. 3600 IN NS ns2.jelte.nlnetlabs.nl. +jelte.nlnetlabs.nl. 3600 IN RRSIG NS 5 3 3600 20090203100022 20090106100022 48885 jelte.nlnetlabs.nl. E3G8ZsCvUw56EKxYA4JzjYaB3ojLpdmQdUHOPSxlWK43haSuxpFERGRc P7AhiMjcYcoJcR+LWQr0uOFVnW8VcFFdy8u7Gs9MNAIWs5+jOaI3WDRC reee7K/NEBiubQCdm7UPA894VNM5oiLCa1waMoMD+LfEeijuN4N09HqY 6eo= +ENTRY_END + +; currently this fails due to the design of canonicalisation in unbound. +; HINFO record signed with ldns, HINFO in uppercase, signature uppercase +ENTRY_BEGIN +SECTION QUESTION +jelte.nlnetlabs.nl. IN HINFO +SECTION ANSWER +jelte.nlnetlabs.nl. 3600 IN HINFO "Jelte" "Machine van" +jelte.nlnetlabs.nl. 3600 IN RRSIG HINFO 5 3 3600 20090203100022 20090106100022 48885 jelte.nlnetlabs.nl. eRig3NjIIgBTmQiN7AREmplgiY6OOtVwCNZgF5UAoYFAE1K1tl5WLqe9 FmTcVtaNUzFdgYv+TD93NNYdV0uxJkr+rS2sSykGf9OIlxevFm+rW2ya 4/Y+5GIN77eN9q9/6ULQRdsX3p8w1fhloiDXk+tgCaw+cJJElMEE1Avw 2dY= +ENTRY_END + + +; HINFO record signed with ldns, HINFO in lowercase, signature lowercase +ENTRY_BEGIN +SECTION QUESTION +jelte.nlnetlabs.nl. IN HINFO +SECTION ANSWER +jelte.nlnetlabs.nl. 3600 IN HINFO "jelte" "machine van" +jelte.nlnetlabs.nl. 3600 IN RRSIG HINFO 5 3 3600 20090203105558 20090106105558 48885 jelte.nlnetlabs.nl. UwFKSqH9oau3nCdJ4i6iYamo2izgMCKy1K8ec0IkhniUONKaIGiRNz8/ QrLAeBHhMnLQYNV/GBprNjvnPyYLG/6bWYUBxvP6pCG4oDEmNY7QF9di I6So5Ycv0ZWaYoT/NYStUj1fLNZ4xCdNXVLA7Oi5PRMeOvPQIvMG3hHK Ja0= +ENTRY_END + +; HINFO record signed with ldns, HINFO in uppercase, signature lowercase +; (signer canonicalised) +ENTRY_BEGIN +SECTION QUESTION +bogus.jelte.nlnetlabs.nl. IN HINFO +SECTION ANSWER +jelte.nlnetlabs.nl. 3600 IN HINFO "Jelte" "Machine van" +jelte.nlnetlabs.nl. 3600 IN RRSIG HINFO 5 3 3600 20090203105558 20090106105558 48885 jelte.nlnetlabs.nl. UwFKSqH9oau3nCdJ4i6iYamo2izgMCKy1K8ec0IkhniUONKaIGiRNz8/ QrLAeBHhMnLQYNV/GBprNjvnPyYLG/6bWYUBxvP6pCG4oDEmNY7QF9di I6So5Ycv0ZWaYoT/NYStUj1fLNZ4xCdNXVLA7Oi5PRMeOvPQIvMG3hHK Ja0= +ENTRY_END + diff --git a/testdata/test_sigs.revoked b/testdata/test_sigs.revoked new file mode 100644 index 00000000000..bcf6e159ca8 --- /dev/null +++ b/testdata/test_sigs.revoked @@ -0,0 +1,24 @@ +; Signature test file + +; first entry is a DNSKEY answer, with the DNSKEY rrset used for verification. +; later entries are verified with it. + + +; DNSKEY is revoked. +ENTRY_BEGIN +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 384 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 31027 (zsk), size = 512b} +ENTRY_END + +; entry to test +ENTRY_BEGIN +SECTION QUESTION +secure.example.com. IN SOA +SECTION ANSWER +example.com. 43200 IN SOA home.kuroiwa.eng.br. hostmaster.cesar.sec3.br. 2008040903 86400 86400 8640000 600 +example.com. 43200 IN RRSIG SOA 5 2 43200 20081010000000 20080410122550 31027 example.com. af7nqRak6cEeQLytqLHMIUKPsOECA4Cu/Zpm7vdnKSh2q2+/8ZwIxwHLyCEGdiu/mTYffZEHTZytJyzxnB0oxA== ;{id = 31027} +ENTRY_END + + diff --git a/testdata/test_sigs.rsasha256 b/testdata/test_sigs.rsasha256 new file mode 100644 index 00000000000..0c44ffaf9c6 --- /dev/null +++ b/testdata/test_sigs.rsasha256 @@ -0,0 +1,23 @@ +; Signature test file + +; first entry is a DNSKEY answer, with the DNSKEY rrset used for verification. +; later entries are verified with it. + +; Test RSASHA256 signatures. + +; RSA key from ldns tool +ENTRY_BEGIN +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 8 AwEAAbd9WqjzE2Pynz21OG5doSf9hFzMr5dhzz2waZ3vTa+0o5r7AjTAqmA1yH/B3+aAMihUm5ucZSfVqo7+kOaRE8yFj9aivOmA1n1+JLevJq/oyvQyjxQN2Qb89LyaNUT5oKZIiL+uyyhNW3KDR3SSbQ/GBwQNDHVcZi+JDR3RC0r7 ;{id = 1443 (zsk), size = 1024b} +ENTRY_END + +; entry to test +ENTRY_BEGIN +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 192.0.2.66 +www.example.com. 3600 IN RRSIG A 8 3 3600 20070926134150 20070829134150 1443 example.com. sX+BZ6Qdq0Td/THR1HgOnWh9URNP03KMEgjpnRGbS74NqlmlqLU3HcimOT/lUD7xsZTeOIWw5kAcQePxU3UrjS5gsIttIXAfrHFmOtTsyb0O4w0/RpR0QYxRl1hk4zQRPzHeEkgxNTe+y9V9gYe7iv9OddXsfwEnmqQiXk+tdsU= ;{id = 1443} +ENTRY_END diff --git a/testdata/test_sigs.rsasha256_draft b/testdata/test_sigs.rsasha256_draft new file mode 100644 index 00000000000..94122e91581 --- /dev/null +++ b/testdata/test_sigs.rsasha256_draft @@ -0,0 +1,23 @@ +; Signature test file + +; first entry is a DNSKEY answer, with the DNSKEY rrset used for verification. +; later entries are verified with it. + +; Test RSASHA256 signatures from draft-ietf-dnsext-dnssec-rsasha256-14 + +ENTRY_BEGIN +SECTION QUESTION +example.net. IN DNSKEY +SECTION ANSWER +example.net. 3600 IN DNSKEY (256 3 8 AwEAAcFcGsaxxdgiuuGmCkVI my4h99CqT7jwY3pexPGcnUFtR2Fh36BponcwtkZ4cAgtvd4Qs8P kxUdp6p/DlUmObdk= );{id = 9033 (zsk), size = 512b} +ENTRY_END + +; entry to test +ENTRY_BEGIN +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +www.example.net. 3600 IN A 192.0.2.91 +www.example.net. 3600 IN RRSIG (A 8 3 3600 20300101000000 20000101000000 9033 example.net. kRCOH6u7l0QGy9qpC9 l1sLncJcOKFLJ7GhiUOibu4teYp5VE9RncriShZNz85mwlMgNEa cFYK/lPtPiVYP4bwg== ;{id = 9033} +ENTRY_END + diff --git a/testdata/test_sigs.rsasha512_draft b/testdata/test_sigs.rsasha512_draft new file mode 100644 index 00000000000..08d5bcb2673 --- /dev/null +++ b/testdata/test_sigs.rsasha512_draft @@ -0,0 +1,23 @@ +; Signature test file + +; first entry is a DNSKEY answer, with the DNSKEY rrset used for verification. +; later entries are verified with it. + +; Test RSASHA512 signatures from draft-ietf-dnsext-dnssec-rsasha256-14 + +ENTRY_BEGIN +SECTION QUESTION +example.net. IN DNSKEY +SECTION ANSWER +example.net. 3600 IN DNSKEY (256 3 10 AwEAAdHoNTOW+et86KuJOWRD p1pndvwb6Y83nSVXXyLA3DLroROUkN6X0O6pnWnjJQujX/AyhqFD xj13tOnD9u/1kTg7cV6rklMrZDtJCQ5PCl/D7QNPsgVsMu1J2Q8g pMpztNFLpPBz1bWXjDtaR7ZQBlZ3PFY12ZTSncorffcGmhOL);{id = 3740 (zsk), size = 1024b} +ENTRY_END + +; entry to test +ENTRY_BEGIN +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +www.example.net. 3600 IN A 192.0.2.91 +www.example.net. 3600 IN RRSIG (A 10 3 3600 20300101000000 20000101000000 3740 example.net. tsb4wnjRUDnB1BUi+t 6TMTXThjVnG+eCkWqjvvjhzQL1d0YRoOe0CbxrVDYd0xDtsuJRa eUw1ep94PzEWzr0iGYgZBWm/zpq+9fOuagYJRfDqfReKBzMweOL DiNa8iP5g9vMhpuv6OPlvpXwm9Sa9ZXIbNl1MBGk0fthPgxdDLw =);{id = 3740} +ENTRY_END + diff --git a/testdata/test_sigs.sha1_and_256 b/testdata/test_sigs.sha1_and_256 new file mode 100644 index 00000000000..92fb05a3a95 --- /dev/null +++ b/testdata/test_sigs.sha1_and_256 @@ -0,0 +1,56 @@ +; Signature test file + +; first entry is a DNSKEY answer, with the DNSKEY rrset used for verification. +; later entries are verified with it. + +; Test multiple signature algos: RSASHA1 + RSASHA256 signatures. + +; RSA key from ldns tool +ENTRY_BEGIN +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 8 AwEAAbd9WqjzE2Pynz21OG5doSf9hFzMr5dhzz2waZ3vTa+0o5r7AjTAqmA1yH/B3+aAMihUm5ucZSfVqo7+kOaRE8yFj9aivOmA1n1+JLevJq/oyvQyjxQN2Qb89LyaNUT5oKZIiL+uyyhNW3KDR3SSbQ/GBwQNDHVcZi+JDR3RC0r7 ;{id = 1443 (zsk), size = 1024b} +example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +ENTRY_END + +; both signatures valid +ENTRY_BEGIN +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN A 192.0.2.66 +www.example.com. 3600 IN RRSIG A 8 3 3600 20070926134150 20070829134150 1443 example.com. sX+BZ6Qdq0Td/THR1HgOnWh9URNP03KMEgjpnRGbS74NqlmlqLU3HcimOT/lUD7xsZTeOIWw5kAcQePxU3UrjS5gsIttIXAfrHFmOtTsyb0O4w0/RpR0QYxRl1hk4zQRPzHeEkgxNTe+y9V9gYe7iv9OddXsfwEnmqQiXk+tdsU= ;{id = 1443} +www.example.com. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.com. Ip2xOAgSq3HdeGEMyQ0jafKNOOJO7Ca+huBgBPSj7B3txTlP9hBzlV0rb0XULymEiQLSpIPm4EY7xzom7z6aKA== ;{id = 30899} +ENTRY_END + +; the SHA1 invalid +ENTRY_BEGIN +SECTION QUESTION +bogus.example.com. IN A +SECTION ANSWER +bogus.example.com. 3600 IN A 192.0.2.66 +bogus.example.com. 3600 IN RRSIG A 8 3 3600 20070926134150 20070829134150 1443 example.com. qaYKAK9+t5HggYjHduA5d3A3i41HoU0ct0yqNzsYQqElFkH0d1aTjRDExD0PGeVbMTocMBru+ID9cLot3kwgn8aZL6UI3AwV6MR+0lianuA8DyhuqpD8OwkZ+LJxNsfq3t5ospXlBhyaI95S7lC3N6dsHDj4qtOwyE42fnQkedE= ;{id = 1443} +bogus.example.com. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.com. Ip2xOAgSq3HdeGEMyQ0jafKNOOJO7Ca+huBgBPSj7B3txTlP9hBzlV0rb0XULymEiQLSpIPm4EY7xzom7z6aKA== ;{id = 30899} +ENTRY_END + +; the SHA256 invalid +ENTRY_BEGIN +SECTION QUESTION +bogus.example.com. IN A +SECTION ANSWER +bogus.example.com. 3600 IN A 192.0.2.66 +bogus.example.com. 3600 IN RRSIG A 8 3 3600 20070926134150 20070829134150 1443 example.com. sX+BZ6Qdq0Td/THR1HgOnWh9URNP03KMEgjpnRGbS74NqlmlqLU3HcimOT/lUD7xsZTeOIWw5kAcQePxU3UrjS5gsIttIXAfrHFmOtTsyb0O4w0/RpR0QYxRl1hk4zQRPzHeEkgxNTe+y9V9gYe7iv9OddXsfwEnmqQiXk+tdsU= ;{id = 1443} +bogus.example.com. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.com. EetlYQbmdt8deu6LIOYTxwHsMnivWBaxClTlLTPooUjgE+upQfCbG25mdY/wx+lM8fthKry+z65YACR8opA0Sw== ;{id = 30899} +ENTRY_END + +; SHA1 and SHA256 not valid +ENTRY_BEGIN +SECTION QUESTION +bogus.example.com. IN A +SECTION ANSWER +bogus.example.com. 3600 IN A 192.0.2.66 +bogus.example.com. 3600 IN RRSIG A 8 3 3600 20070926134150 20070829134150 1443 example.com. sX+BZ6Qdq0Td/THR1HgOnWh9URNP03KMEgjpnRGbS74NqlmlqLU3HcimOT/lUD7xsZTeOIWw5kAcQePxU3UrjS5gsIttIXAfrHFmOtTsyb0O4w0/RpR0QYxRl1hk4zQRPzHeEkgxNTe+y9V9gYe7iv9OddXsfwEnmqQiXk+tdsU= ;{id = 1443} +bogus.example.com. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.com. Ip2xOAgSq3HdeGEMyQ0jafKNOOJO7Ca+huBgBPSj7B3txTlP9hBzlV0rb0XULymEiQLSpIPm4EY7xzom7z6aKA== ;{id = 30899} +ENTRY_END + diff --git a/testdata/trust_cname_chain.rpl b/testdata/trust_cname_chain.rpl new file mode 100644 index 00000000000..e4d2d2a99b7 --- /dev/null +++ b/testdata/trust_cname_chain.rpl @@ -0,0 +1,153 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test trust in cname chain answer + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME xxx.example.com. +xxx.example.com. IN CNAME yyy.example.com. +yyy.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +xxx.example.com. IN A +SECTION ANSWER +xxx.example.com. IN CNAME yyy.example.com. +yyy.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +yyy.example.com. IN A +SECTION ANSWER +yyy.example.com. IN A 10.20.30.42 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + + +; This stores it into cache. +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME xxx.example.com. +xxx.example.com. IN CNAME yyy.example.com. +;;; did not trust the remainder of the CNAME chain! +yyy.example.com. IN A 10.20.30.42 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +SCENARIO_END diff --git a/testdata/ttl_max.rpl b/testdata/ttl_max.rpl new file mode 100644 index 00000000000..6443da71b1a --- /dev/null +++ b/testdata/ttl_max.rpl @@ -0,0 +1,212 @@ +; config options +server: + access-control: 127.0.0.1 allow_snoop + cache-max-ttl: 10 + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test TTL max option for messages in the cache + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +a.gtld-servers.net. IN A +SECTION ANSWER +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +K.ROOT-SERVERS.NET. IN A +SECTION ANSWER +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +a.gtld-servers.net. IN AAAA +SECTION AUTHORITY +. 86400 IN SOA . . 20070304 28800 7200 604800 86400 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +K.ROOT-SERVERS.NET. IN AAAA +SECTION AUTHORITY +. 86400 IN SOA . . 20070304 28800 7200 604800 86400 +ENTRY_END + +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 248 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION AUTHORITY +example.com. 10 IN SOA . . 15 28800 7200 604800 10 +ENTRY_END + +RANGE_END + +; start by passing time ; so we are not at 0 +STEP 1 TIME_PASSES ELAPSE 10 + +; query for the record +STEP 8 QUERY +ENTRY_BEGIN +REPLY RD CD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA CD +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 248 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +; wait +STEP 20 TIME_PASSES ELAPSE 17 + +; do a lookup to check TTLs. +STEP 25 QUERY +ENTRY_BEGIN +REPLY +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 26 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RA +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +. 3600 IN NS K.ROOT-SERVERS.NET. +SECTION AUTHORITY +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. 3600 IN A 193.0.14.129 +ENTRY_END + +SCENARIO_END diff --git a/testdata/ttl_min.rpl b/testdata/ttl_min.rpl new file mode 100644 index 00000000000..1fa7ef1c966 --- /dev/null +++ b/testdata/ttl_min.rpl @@ -0,0 +1,213 @@ +; config options +server: + access-control: 127.0.0.1 allow_snoop + cache-min-ttl: 10 + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test TTL min option for messages in the cache + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +a.gtld-servers.net. IN A +SECTION ANSWER +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +K.ROOT-SERVERS.NET. IN A +SECTION ANSWER +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +a.gtld-servers.net. IN AAAA +SECTION AUTHORITY +. 86400 IN SOA . . 20070304 28800 7200 604800 86400 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +K.ROOT-SERVERS.NET. IN AAAA +SECTION AUTHORITY +. 86400 IN SOA . . 20070304 28800 7200 604800 86400 +ENTRY_END + +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 5 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION AUTHORITY +example.com. 10 IN SOA . . 15 28800 7200 604800 10 +ENTRY_END + +RANGE_END + +; start by passing time ; so we are not at 0 +STEP 1 TIME_PASSES ELAPSE 10 + +; query for the record +STEP 8 QUERY +ENTRY_BEGIN +REPLY RD CD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA CD +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 10 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +; wait for 7 seconds +STEP 20 TIME_PASSES ELAPSE 7 + +; do a lookup to check TTLs. +STEP 25 QUERY +ENTRY_BEGIN +REPLY +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 26 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RA +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. 3593 IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. 3593 IN A 1.2.3.4 +ENTRY_END + +SCENARIO_END diff --git a/testdata/ttl_msg.rpl b/testdata/ttl_msg.rpl new file mode 100644 index 00000000000..627f0614244 --- /dev/null +++ b/testdata/ttl_msg.rpl @@ -0,0 +1,491 @@ +; config options +; fetch all extra targets - we want to trigger a lookup in cache +server: + target-fetch-policy: "-1 -1 -1 -1 -1" + access-control: 127.0.0.1 allow_snoop + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test TTL countdown on messages in the cache + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +a.gtld-servers.net. IN A +SECTION ANSWER +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +K.ROOT-SERVERS.NET. IN A +SECTION ANSWER +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +a.gtld-servers.net. IN AAAA +SECTION AUTHORITY +. 86400 IN SOA . . 20070304 28800 7200 604800 86400 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +K.ROOT-SERVERS.NET. IN AAAA +SECTION AUTHORITY +. 86400 IN SOA . . 20070304 28800 7200 604800 86400 +ENTRY_END + +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +foo.com. IN A +SECTION AUTHORITY +foo.com. IN NS ns.foo.com. +;foo.com. IN NS nx1.example.com. +SECTION ADDITIONAL +ns.foo.com. IN A 1.2.5.6 +ENTRY_END +RANGE_END + +; ns.foo.com +RANGE_BEGIN 0 100 + ADDRESS 1.2.5.6 + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +foo.com. IN NS +SECTION ANSWER +foo.com. IN NS ns.foo.com. +;foo.com. IN NS nx1.example.com. +SECTION ADDITIONAL +ns.foo.com. IN A 1.2.5.6 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.foo.com. IN A +SECTION ANSWER +;www.foo.com. IN A 1.2.5.6 +www.foo.com. IN CNAME nx1.example.com. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.foo.com. IN A +SECTION ANSWER +ns.foo.com. IN A 1.2.5.6 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.foo.com. IN AAAA +SECTION AUTHORITY +foo.com. IN SOA . . 1 2 3 4 3600 +ENTRY_END +RANGE_END + +; ns.example.com. --- serial=15 +RANGE_BEGIN 0 20 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION AUTHORITY +example.com. 10 IN SOA . . 15 28800 7200 604800 10 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NXDOMAIN +SECTION QUESTION +nx1.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. 10 IN SOA . . 15 28800 7200 604800 10 +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NXDOMAIN +SECTION QUESTION +nx2.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. 10 IN SOA . . 15 28800 7200 604800 10 +SECTION ADDITIONAL +ENTRY_END + +RANGE_END + +; ns.example.com. --- serial=17 +RANGE_BEGIN 20 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION AUTHORITY +example.com. 10 IN SOA . . 17 28800 7200 604800 10 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NXDOMAIN +SECTION QUESTION +nx1.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. 10 IN SOA . . 17 28800 7200 604800 10 +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NXDOMAIN +SECTION QUESTION +nx2.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. 10 IN SOA . . 17 28800 7200 604800 10 +SECTION ADDITIONAL +ENTRY_END + +RANGE_END + +; start by passing time ; so we are not at 0 +STEP 1 TIME_PASSES ELAPSE 10 + +; query for NXDOMAIN +STEP 8 QUERY +ENTRY_BEGIN +REPLY RD CD +SECTION QUESTION +nx1.example.com. IN A +ENTRY_END + +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NXDOMAIN CD +SECTION QUESTION +nx1.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. 10 IN SOA . . 15 28800 7200 604800 10 +SECTION ADDITIONAL +ENTRY_END + +; wait for 5 seconds +STEP 20 TIME_PASSES ELAPSE 5 + +; do a lookup for nx1.example.com just to check TTLs... +STEP 25 QUERY +ENTRY_BEGIN +REPLY RD CD +SECTION QUESTION +nx1.example.com. IN A +ENTRY_END +STEP 26 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NXDOMAIN CD +SECTION QUESTION +nx1.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. 5 IN SOA . . 15 28800 7200 604800 10 +SECTION ADDITIONAL +ENTRY_END + +; cause a lookup that refreshes the TTL on the SOA record +STEP 30 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +nx2.example.com. IN A +ENTRY_END +STEP 31 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NXDOMAIN +SECTION QUESTION +nx2.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. 10 IN SOA . . 17 28800 7200 604800 10 +SECTION ADDITIONAL +ENTRY_END + +; do a lookup for nx1.example.com to check TTLs updated +STEP 35 QUERY +ENTRY_BEGIN +REPLY RD CD +SECTION QUESTION +nx1.example.com. IN A +ENTRY_END +STEP 36 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NXDOMAIN CD +SECTION QUESTION +nx1.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. 10 IN SOA . . 17 28800 7200 604800 10 +SECTION ADDITIONAL +ENTRY_END + +; cause a lookup for nx1.example.com bypassing the cache. +; with bug; this causes msg ttl for nx1 to be time(NOW)+ttl. +; so 15+5 = 20 +; visiable in debug log as "msg ttl is %d" +STEP 40 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.foo.com. IN A +ENTRY_END +STEP 41 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NXDOMAIN +SECTION QUESTION +www.foo.com. IN A +SECTION ANSWER +;www.foo.com IN A 1.2.5.6 +www.foo.com IN CNAME nx1.example.com. +SECTION AUTHORITY +example.com. 10 IN SOA . . 17 28800 7200 604800 10 +ENTRY_END + +; now cause lookup from cache by not passing CD flag +; (validator has a look, and stores after iterator cache lookup). +STEP 45 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +nx1.example.com. IN A +ENTRY_END +STEP 46 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NXDOMAIN +SECTION QUESTION +nx1.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. 10 IN SOA . . 17 28800 7200 604800 10 +SECTION ADDITIONAL +ENTRY_END + +; the message should timeout in 5 seconds, wait 7 +STEP 50 TIME_PASSES ELAPSE 7 + +; it is still there? (nonRD query) +STEP 55 QUERY +ENTRY_BEGIN +REPLY +SECTION QUESTION +nx1.example.com. IN A +ENTRY_END + +; this answer is the bug - NXDOMAIN too long in the cache. +;STEP 56 CHECK_ANSWER +;ENTRY_BEGIN +;MATCH all ttl +;REPLY QR RA NXDOMAIN +;SECTION QUESTION +;nx1.example.com. IN A +;SECTION ANSWER +;SECTION AUTHORITY +;example.com. 3 IN SOA . . 17 28800 7200 604800 10 +;SECTION ADDITIONAL +;ENTRY_END + +; Now the correct answer: no such cached query. +STEP 56 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RA NOERROR +SECTION QUESTION +nx1.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_adbit.rpl b/testdata/val_adbit.rpl new file mode 100644 index 00000000000..bffc9b71370 --- /dev/null +++ b/testdata/val_adbit.rpl @@ -0,0 +1,170 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator AD bit signaling + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD AD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +; ask from cache too +STEP 21 QUERY +ENTRY_BEGIN +REPLY RD AD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 23 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + + +SCENARIO_END diff --git a/testdata/val_adcopy.rpl b/testdata/val_adcopy.rpl new file mode 100644 index 00000000000..6cd9ad6ecdf --- /dev/null +++ b/testdata/val_adcopy.rpl @@ -0,0 +1,170 @@ +; config options +; The island of trust is at example.com +server: + #trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator AD bit sent by untrusted upstream + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA RA AD NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA RA AD NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD AD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +; ask from cache too +STEP 21 QUERY +ENTRY_BEGIN +REPLY RD AD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 23 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + + +SCENARIO_END diff --git a/testdata/val_anchor_nx.rpl b/testdata/val_anchor_nx.rpl new file mode 100644 index 00000000000..66a08c524e1 --- /dev/null +++ b/testdata/val_anchor_nx.rpl @@ -0,0 +1,217 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + trust-anchor: "sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with secure proof of trust anchor nxdomain + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response for sub.example.com. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +example.com. SOA ns.example.com. h.example.com. 2007090504 1800 1800 2419200 7200 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFC5uwIHSehZtetK2CMNXttSFUB0XAhROFDAgy/FaxR8zFXJzyPdpQG93Sw== ;{id = 2854} +blub.example.com. NSEC znub.example.com. A MX RRSIG NSEC +blub.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCic/WwyMtdDE/84g8l0S0M8AOtnAhR88hQEp5cD5XQ3EmQ79RUuNTCgdg== ;{id = 2854} +example.com. NSEC blub.example.com. SOA NS MX DNSKEY RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFFYX7iNIlT79gNFFlvnn44Ittm6HAhUAg7u0hZ4to87qyfkonZu2jVLW3xw= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +www.sub.example.com. IN DS +SECTION AUTHORITY +example.com. SOA ns.example.com. h.example.com. 2007090504 1800 1800 2419200 7200 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFC5uwIHSehZtetK2CMNXttSFUB0XAhROFDAgy/FaxR8zFXJzyPdpQG93Sw== ;{id = 2854} +blub.example.com. NSEC znub.example.com. A MX RRSIG NSEC +blub.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCic/WwyMtdDE/84g8l0S0M8AOtnAhR88hQEp5cD5XQ3EmQ79RUuNTCgdg== ;{id = 2854} +example.com. NSEC blub.example.com. SOA NS MX DNSKEY RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFFYX7iNIlT79gNFFlvnn44Ittm6HAhUAg7u0hZ4to87qyfkonZu2jVLW3xw= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION AUTHORITY +example.com. SOA ns.example.com. h.example.com. 2007090504 1800 1800 2419200 7200 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFC5uwIHSehZtetK2CMNXttSFUB0XAhROFDAgy/FaxR8zFXJzyPdpQG93Sw== ;{id = 2854} +blub.example.com. NSEC znub.example.com. A MX RRSIG NSEC +blub.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCic/WwyMtdDE/84g8l0S0M8AOtnAhR88hQEp5cD5XQ3EmQ79RUuNTCgdg== ;{id = 2854} +example.com. NSEC blub.example.com. SOA NS MX DNSKEY RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFFYX7iNIlT79gNFFlvnn44Ittm6HAhUAg7u0hZ4to87qyfkonZu2jVLW3xw= ;{id = 2854} +ENTRY_END +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 + +; response to DNSKEY priming query +; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899} +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NXDOMAIN +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. SOA ns.example.com. h.example.com. 2007090504 1800 1800 2419200 7200 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFC5uwIHSehZtetK2CMNXttSFUB0XAhROFDAgy/FaxR8zFXJzyPdpQG93Sw== ;{id = 2854} +blub.example.com. NSEC znub.example.com. A MX RRSIG NSEC +blub.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCic/WwyMtdDE/84g8l0S0M8AOtnAhR88hQEp5cD5XQ3EmQ79RUuNTCgdg== ;{id = 2854} +example.com. NSEC blub.example.com. SOA NS MX DNSKEY RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFFYX7iNIlT79gNFFlvnn44Ittm6HAhUAg7u0hZ4to87qyfkonZu2jVLW3xw= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_anchor_nx_nosig.rpl b/testdata/val_anchor_nx_nosig.rpl new file mode 100644 index 00000000000..d69db39d962 --- /dev/null +++ b/testdata/val_anchor_nx_nosig.rpl @@ -0,0 +1,216 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with unsigned denial of trust anchor + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response for sub.example.com. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +example.com. SOA ns.example.com. h.example.com. 2007090504 1800 1800 2419200 7200 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFC5uwIHSehZtetK2CMNXttSFUB0XAhROFDAgy/FaxR8zFXJzyPdpQG93Sw== ;{id = 2854} +blub.example.com. NSEC znub.example.com. A MX RRSIG NSEC +blub.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCic/WwyMtdDE/84g8l0S0M8AOtnAhR88hQEp5cD5XQ3EmQ79RUuNTCgdg== ;{id = 2854} +example.com. NSEC blub.example.com. SOA NS MX DNSKEY RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFFYX7iNIlT79gNFFlvnn44Ittm6HAhUAg7u0hZ4to87qyfkonZu2jVLW3xw= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +www.sub.example.com. IN DS +SECTION AUTHORITY +example.com. SOA ns.example.com. h.example.com. 2007090504 1800 1800 2419200 7200 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFC5uwIHSehZtetK2CMNXttSFUB0XAhROFDAgy/FaxR8zFXJzyPdpQG93Sw== ;{id = 2854} +blub.example.com. NSEC znub.example.com. A MX RRSIG NSEC +blub.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCic/WwyMtdDE/84g8l0S0M8AOtnAhR88hQEp5cD5XQ3EmQ79RUuNTCgdg== ;{id = 2854} +example.com. NSEC blub.example.com. SOA NS MX DNSKEY RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFFYX7iNIlT79gNFFlvnn44Ittm6HAhUAg7u0hZ4to87qyfkonZu2jVLW3xw= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION AUTHORITY +example.com. SOA ns.example.com. h.example.com. 2007090504 1800 1800 2419200 7200 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFC5uwIHSehZtetK2CMNXttSFUB0XAhROFDAgy/FaxR8zFXJzyPdpQG93Sw== ;{id = 2854} +blub.example.com. NSEC znub.example.com. A MX RRSIG NSEC +blub.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCic/WwyMtdDE/84g8l0S0M8AOtnAhR88hQEp5cD5XQ3EmQ79RUuNTCgdg== ;{id = 2854} +example.com. NSEC blub.example.com. SOA NS MX DNSKEY RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFFYX7iNIlT79gNFFlvnn44Ittm6HAhUAg7u0hZ4to87qyfkonZu2jVLW3xw= ;{id = 2854} +ENTRY_END +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 + +; response to DNSKEY priming query +; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899} +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NXDOMAIN +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. SOA ns.example.com. h.example.com. 2007090504 1800 1800 2419200 7200 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFC5uwIHSehZtetK2CMNXttSFUB0XAhROFDAgy/FaxR8zFXJzyPdpQG93Sw== ;{id = 2854} +blub.example.com. NSEC znub.example.com. A MX RRSIG NSEC +blub.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCic/WwyMtdDE/84g8l0S0M8AOtnAhR88hQEp5cD5XQ3EmQ79RUuNTCgdg== ;{id = 2854} +example.com. NSEC blub.example.com. SOA NS MX DNSKEY RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFFYX7iNIlT79gNFFlvnn44Ittm6HAhUAg7u0hZ4to87qyfkonZu2jVLW3xw= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_ans_dsent.rpl b/testdata/val_ans_dsent.rpl new file mode 100644 index 00000000000..150504037cb --- /dev/null +++ b/testdata/val_ans_dsent.rpl @@ -0,0 +1,244 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with empty nonterminals on the trust chain. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +328.0.0.194.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +328.0.0.194.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; responses to DS empty nonterminal queries. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +194.example.com. IN DS +SECTION AUTHORITY +example.com. 3600 IN SOA ns.example.com. host.example.com. 2007091980 3600 7200 1209600 7200 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926135752 20070829135752 2854 example.com. MC0CFCOn5qKBIV7bwFMBA+Qqiblx0cylAhUAoFiGtFm2wHhJpq9MooTYdeVw45s= ;{id = 2854} + +; This NSEC proves the NOERROR/NODATA case. +194.example.com. IN NSEC 0.0.194.example.com. A RRSIG NSEC +194.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFDcoKl74U9FjsuYF3Vc0E8GQ2GgzAhUAhlyhO2MMcAWQMxIhEZ4MguokN5g= ;{id = 2854} + +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +; this should be NOERROR. +REPLY QR AA NOERROR +SECTION QUESTION +0.194.example.com. IN DS +SECTION AUTHORITY +example.com. 3600 IN SOA ns.example.com. host.example.com. 2007091980 3600 7200 1209600 7200 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926135752 20070829135752 2854 example.com. MC0CFCOn5qKBIV7bwFMBA+Qqiblx0cylAhUAoFiGtFm2wHhJpq9MooTYdeVw45s= ;{id = 2854} + +; This NSEC proves the NOERROR/NODATA case. +194.example.com. IN NSEC 0.0.194.example.com. A RRSIG NSEC +194.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFDcoKl74U9FjsuYF3Vc0E8GQ2GgzAhUAhlyhO2MMcAWQMxIhEZ4MguokN5g= ;{id = 2854} + +ENTRY_END + +; response for delegation to sub zone. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +328.0.0.194.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +0.0.194.example.com. IN NS ns.sub.example.com. +0.0.194.example.com. 3600 IN DS 30899 RSASHA1 1 aa46f0717075d9750ac3596c659a2e326b33c28c +0.0.194.example.com. 3600 IN RRSIG DS 3 5 3600 20070926135752 20070829135752 2854 example.com. MCwCFC9GIqtp/103hktw6bPpD83gr+0iAhQ8yev2yUaR9l64rYBUYTJqOoTKdw== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +; response for delegation to sub zone +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +0.0.194.example.com. IN DNSKEY +SECTION ANSWER +SECTION AUTHORITY +0.0.194.example.com. IN NS ns.sub.example.com. +0.0.194.example.com. 3600 IN DS 30899 RSASHA1 1 aa46f0717075d9750ac3596c659a2e326b33c28c +0.0.194.example.com. 3600 IN RRSIG DS 3 5 3600 20070926135752 20070829135752 2854 example.com. MCwCFC9GIqtp/103hktw6bPpD83gr+0iAhQ8yev2yUaR9l64rYBUYTJqOoTKdw== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END +RANGE_END + +; ns.sub.example.com. for zone 0.0.194.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +0.0.194.example.com. IN NS +SECTION ANSWER +0.0.194.example.com. IN NS ns.sub.example.com. +0.0.194.example.com. 3600 IN RRSIG NS 5 5 3600 20070926135752 20070829135752 30899 0.0.194.example.com. KXDA+/PJAE+dXhv6O6Z0ZovDwabSRJcIt+GT5AL6ewlj46hzo/SDKUtEhYCeT1IVQvYtXrESwFZjpp7N0rXXBg== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + + +; response to DNSKEY priming query +; 0.0.194.example.com. 3600 IN DS 30899 RSASHA1 1 aa46f0717075d9750ac3596c659a2e326b33c28c +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +0.0.194.example.com. IN DNSKEY +SECTION ANSWER +0.0.194.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +0.0.194.example.com. 3600 IN RRSIG DNSKEY 5 5 3600 20070926135752 20070829135752 30899 0.0.194.example.com. fSmc7ef6NwbDXC0o4wPc/aa8LakW5ZJwEZ4xPYl3tTZKmPNM7hPXskl1tFlvst9Va4u37F62v+16trprHb+SCQ== ;{id = 30899} +SECTION AUTHORITY +0.0.194.example.com. IN NS ns.sub.example.com. +0.0.194.example.com. 3600 IN RRSIG NS 5 5 3600 20070926135752 20070829135752 30899 0.0.194.example.com. KXDA+/PJAE+dXhv6O6Z0ZovDwabSRJcIt+GT5AL6ewlj46hzo/SDKUtEhYCeT1IVQvYtXrESwFZjpp7N0rXXBg== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +328.0.0.194.example.com. IN A +SECTION ANSWER +328.0.0.194.example.com. IN A 11.11.11.11 +328.0.0.194.example.com. 3600 IN RRSIG A 5 6 3600 20070926135752 20070829135752 30899 0.0.194.example.com. chZW77mqywhw/4ch6BxXQ4EbFgb9zgh2xF75FLlKq/7ey6CfHSJRpJRjRqtMTn+1i18UL2B4nPS/WnK5DZeqlA== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +328.0.0.194.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +328.0.0.194.example.com. IN A +SECTION ANSWER +328.0.0.194.example.com. 3600 IN A 11.11.11.11 +328.0.0.194.example.com. 3600 IN RRSIG A 5 6 3600 20070926135752 20070829135752 30899 0.0.194.example.com. chZW77mqywhw/4ch6BxXQ4EbFgb9zgh2xF75FLlKq/7ey6CfHSJRpJRjRqtMTn+1i18UL2B4nPS/WnK5DZeqlA== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_ans_nx.rpl b/testdata/val_ans_nx.rpl new file mode 100644 index 00000000000..8eceaa96280 --- /dev/null +++ b/testdata/val_ans_nx.rpl @@ -0,0 +1,246 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with DS nodata as nxdomain on trust chain +; This is a bug in ANS 2.8.1.0 where it gives an NXDOMAIN instead of +; NOERROR for an empty nonterminal DS query. The proof for this NXDOMAIN +; is the NSEC that proves emptynonterminal. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +328.0.0.194.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +328.0.0.194.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; responses to DS empty nonterminal queries. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +194.example.com. IN DS +SECTION AUTHORITY +example.com. 3600 IN SOA ns.example.com. host.example.com. 2007091980 3600 7200 1209600 7200 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926135752 20070829135752 2854 example.com. MC0CFCOn5qKBIV7bwFMBA+Qqiblx0cylAhUAoFiGtFm2wHhJpq9MooTYdeVw45s= ;{id = 2854} + +; This NSEC proves the NOERROR/NODATA case. +194.example.com. IN NSEC 0.0.194.example.com. A RRSIG NSEC +194.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFDcoKl74U9FjsuYF3Vc0E8GQ2GgzAhUAhlyhO2MMcAWQMxIhEZ4MguokN5g= ;{id = 2854} + +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +; Bad NXDOMAIN response, this should be NOERROR. +REPLY QR AA NXDOMAIN +SECTION QUESTION +0.194.example.com. IN DS +SECTION AUTHORITY +example.com. 3600 IN SOA ns.example.com. host.example.com. 2007091980 3600 7200 1209600 7200 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926135752 20070829135752 2854 example.com. MC0CFCOn5qKBIV7bwFMBA+Qqiblx0cylAhUAoFiGtFm2wHhJpq9MooTYdeVw45s= ;{id = 2854} + +; This NSEC proves the NOERROR/NODATA case. +194.example.com. IN NSEC 0.0.194.example.com. A RRSIG NSEC +194.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFDcoKl74U9FjsuYF3Vc0E8GQ2GgzAhUAhlyhO2MMcAWQMxIhEZ4MguokN5g= ;{id = 2854} + +ENTRY_END + +; response for delegation to sub zone. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +328.0.0.194.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +0.0.194.example.com. IN NS ns.sub.example.com. +0.0.194.example.com. 3600 IN DS 30899 RSASHA1 1 aa46f0717075d9750ac3596c659a2e326b33c28c +0.0.194.example.com. 3600 IN RRSIG DS 3 5 3600 20070926135752 20070829135752 2854 example.com. MCwCFC9GIqtp/103hktw6bPpD83gr+0iAhQ8yev2yUaR9l64rYBUYTJqOoTKdw== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +; response for delegation to sub zone +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +0.0.194.example.com. IN DNSKEY +SECTION ANSWER +SECTION AUTHORITY +0.0.194.example.com. IN NS ns.sub.example.com. +0.0.194.example.com. 3600 IN DS 30899 RSASHA1 1 aa46f0717075d9750ac3596c659a2e326b33c28c +0.0.194.example.com. 3600 IN RRSIG DS 3 5 3600 20070926135752 20070829135752 2854 example.com. MCwCFC9GIqtp/103hktw6bPpD83gr+0iAhQ8yev2yUaR9l64rYBUYTJqOoTKdw== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END +RANGE_END + +; ns.sub.example.com. for zone 0.0.194.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +0.0.194.example.com. IN NS +SECTION ANSWER +0.0.194.example.com. IN NS ns.sub.example.com. +0.0.194.example.com. 3600 IN RRSIG NS 5 5 3600 20070926135752 20070829135752 30899 0.0.194.example.com. KXDA+/PJAE+dXhv6O6Z0ZovDwabSRJcIt+GT5AL6ewlj46hzo/SDKUtEhYCeT1IVQvYtXrESwFZjpp7N0rXXBg== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +; response to DNSKEY priming query +; 0.0.194.example.com. 3600 IN DS 30899 RSASHA1 1 aa46f0717075d9750ac3596c659a2e326b33c28c +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +0.0.194.example.com. IN DNSKEY +SECTION ANSWER +0.0.194.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +0.0.194.example.com. 3600 IN RRSIG DNSKEY 5 5 3600 20070926135752 20070829135752 30899 0.0.194.example.com. fSmc7ef6NwbDXC0o4wPc/aa8LakW5ZJwEZ4xPYl3tTZKmPNM7hPXskl1tFlvst9Va4u37F62v+16trprHb+SCQ== ;{id = 30899} +SECTION AUTHORITY +0.0.194.example.com. IN NS ns.sub.example.com. +0.0.194.example.com. 3600 IN RRSIG NS 5 5 3600 20070926135752 20070829135752 30899 0.0.194.example.com. KXDA+/PJAE+dXhv6O6Z0ZovDwabSRJcIt+GT5AL6ewlj46hzo/SDKUtEhYCeT1IVQvYtXrESwFZjpp7N0rXXBg== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +328.0.0.194.example.com. IN A +SECTION ANSWER +328.0.0.194.example.com. IN A 11.11.11.11 +328.0.0.194.example.com. 3600 IN RRSIG A 5 6 3600 20070926135752 20070829135752 30899 0.0.194.example.com. chZW77mqywhw/4ch6BxXQ4EbFgb9zgh2xF75FLlKq/7ey6CfHSJRpJRjRqtMTn+1i18UL2B4nPS/WnK5DZeqlA== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +328.0.0.194.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +328.0.0.194.example.com. IN A +SECTION ANSWER +328.0.0.194.example.com. 3600 IN A 11.11.11.11 +328.0.0.194.example.com. 3600 IN RRSIG A 5 6 3600 20070926135752 20070829135752 30899 0.0.194.example.com. chZW77mqywhw/4ch6BxXQ4EbFgb9zgh2xF75FLlKq/7ey6CfHSJRpJRjRqtMTn+1i18UL2B4nPS/WnK5DZeqlA== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_any.rpl b/testdata/val_any.rpl new file mode 100644 index 00000000000..e0f7b1f62d5 --- /dev/null +++ b/testdata/val_any.rpl @@ -0,0 +1,200 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with response to qtype ANY + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN ANY +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN ANY +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN ANY +SECTION ANSWER +example.com. 86400 IN SOA open.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000 +example.com. 86400 IN RRSIG SOA 3 2 86400 20070926134150 20070829134150 2854 example.com. MC0CFQCSs8KJepwaIp5vu++/0hk04lkXvgIUdphJSAE/MYob30WcRei9/nL49tE= ;{id = 2854} +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJIIs70j+sDS/UT2QRp61SE7S3EEXopNXoFE73JLRmvpi/UrOO/Vz4Se6wXv/CYCKjGw06U4WRgRYXcpEhJROyNapmdIKSxhOzfLVE1gqA0PweZR8dtY3aNQSRn3sPpwJr6Mi/PqQKAMMrZ9ckJpf1+bQMOOvxgzz2U1GS18b3yZKcgTMEaJzd/GZYzi/BN2DzQ0MsrSwYXfsNLFOBbs8PJMW4LYIxeeOe6rUgkWOF7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFHq7BNVAeLW+Uw/rkjVS08lrMDk/AhR+bvChHfiE4jLb6uoyE54/irCuqA== ;{id = 2854} +example.com. 600 IN NAPTR 20 0 "s" "SIP+D2U" "" _sip._udp.example.com. +example.com. 600 IN RRSIG NAPTR 3 2 600 20070926134150 20070829134150 2854 example.com. MC0CFE8qs66bzuOyKmTIacamrmqabMRzAhUAn0MujX1LB0UpTHuLMgdgMgJJlq4= ;{id = 2854} +example.com. 86400 IN AAAA 2001:7b8:206:1::1 +example.com. 86400 IN RRSIG AAAA 3 2 86400 20070926134150 20070829134150 2854 example.com. MC0CFEqS4WHyqhUkv7t42TsBZJk/Q9paAhUAtTZ8GaXGpot0PmsM0oGzQU+2iw4= ;{id = 2854} +example.com. 86400 IN TXT "Stichting NLnet Labs" +example.com. 86400 IN RRSIG TXT 3 2 86400 20070926134150 20070829134150 2854 example.com. MCwCFH3otn2u8zXczBS8L0VKpyAYZGSkAhQLGaQclkzMAzlB5j73opFjdkh8TA== ;{id = 2854} +example.com. 86400 IN MX 100 v.net.example. +example.com. 86400 IN MX 50 open.example.com. +example.com. 86400 IN RRSIG MX 3 2 86400 20070926134150 20070829134150 2854 example.com. MCwCFEKh3jeqh69zcOqWWv3GNKlMECPyAhR9HJkcPLqlyVWUccWDFJfGGcQfdg== ;{id = 2854} +example.com. 86400 IN NS v.net.example. +example.com. 86400 IN NS open.example.com. +example.com. 86400 IN NS ns7.domain-registry.example. +example.com. 86400 IN RRSIG NS 3 2 86400 20070926134150 20070829134150 2854 example.com. MC0CFQCaRn30X4neKW7KYoTa2kcsoOLgfgIURvKEyDczLypWlx99KpxzMxRYhEc= ;{id = 2854} +example.com. 86400 IN A 213.154.224.1 +example.com. 86400 IN RRSIG A 3 2 86400 20070926134150 20070829134150 2854 example.com. MCwCFH8kSLxmRTwzlGDxvF1e4y/gM+5dAhQkzyQ2a6Gf+CMaHzVScaUvTt9HhQ== ;{id = 2854} +example.com. 18000 IN NSEC _sip._udp.example.com. A NS SOA MX TXT AAAA NAPTR RRSIG NSEC DNSKEY +example.com. 18000 IN RRSIG NSEC 3 2 18000 20070926134150 20070829134150 2854 example.com. MCwCFBzOGtpgq4uJ2jeuLPYl2HowIRzDAhQVXNz1haQ1mI7z9lt5gcvWW+lFhA== ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +ns7.domain-registry.example. 80173 IN A 62.4.86.230 +open.example.com. 600 IN A 213.154.224.1 +open.example.com. 600 IN AAAA 2001:7b8:206:1::53 +open.example.com. 600 IN AAAA 2001:7b8:206:1::1 +v.net.example. 28800 IN A 213.154.224.17 +v.net.example. 28800 IN AAAA 2001:7b8:206:1:200:39ff:fe59:b187 +johnny.example.com. 600 IN A 213.154.224.44 +open.example.com. 600 IN RRSIG A 3 3 600 20070926134150 20070829134150 2854 example.com. MC0CFQCh8bja923UJmg1+sYXMK8WIE4dpgIUQe9sZa0GOcUYSgb2rXoogF8af+Y= ;{id = 2854} +open.example.com. 600 IN RRSIG AAAA 3 3 600 20070926134150 20070829134150 2854 example.com. MC0CFQCRGJgIS6kEVG7aJfovuG/q3cgOWwIUYEIFCnfRQlMIYWF7BKMQoMbdkE0= ;{id = 2854} +johnny.example.com. 600 IN RRSIG A 3 3 600 20070926134150 20070829134150 2854 example.com. MCwCFAh0/zSpCd/9eMNz7AyfnuGQFD1ZAhQEpNFNw4XByNEcbi/vsVeii9kp7g== ;{id = 2854} +_sip._udp.example.com. 600 IN RRSIG SRV 3 4 600 20070926134150 20070829134150 2854 example.com. MCwCFFSRVgOcq1ihVuO6MhCuzWs6SxpVAhRPHHCKy0JxymVkYeFOxTkbVSWMMw== ;{id = 2854} +_sip._udp.example.com. 600 IN SRV 0 0 5060 johnny.example.com. +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +MATCH TCP +REPLY RD DO +SECTION QUESTION +example.com. IN ANY +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +example.com. IN ANY +SECTION ANSWER +example.com. 86400 IN SOA open.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000 +example.com. 86400 IN RRSIG SOA 3 2 86400 20070926134150 20070829134150 2854 example.com. MC0CFQCSs8KJepwaIp5vu++/0hk04lkXvgIUdphJSAE/MYob30WcRei9/nL49tE= ;{id = 2854} +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJIIs70j+sDS/UT2QRp61SE7S3EEXopNXoFE73JLRmvpi/UrOO/Vz4Se6wXv/CYCKjGw06U4WRgRYXcpEhJROyNapmdIKSxhOzfLVE1gqA0PweZR8dtY3aNQSRn3sPpwJr6Mi/PqQKAMMrZ9ckJpf1+bQMOOvxgzz2U1GS18b3yZKcgTMEaJzd/GZYzi/BN2DzQ0MsrSwYXfsNLFOBbs8PJMW4LYIxeeOe6rUgkWOF7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFHq7BNVAeLW+Uw/rkjVS08lrMDk/AhR+bvChHfiE4jLb6uoyE54/irCuqA== ;{id = 2854} +example.com. 600 IN NAPTR 20 0 "s" "SIP+D2U" "" _sip._udp.example.com. +example.com. 600 IN RRSIG NAPTR 3 2 600 20070926134150 20070829134150 2854 example.com. MC0CFE8qs66bzuOyKmTIacamrmqabMRzAhUAn0MujX1LB0UpTHuLMgdgMgJJlq4= ;{id = 2854} +example.com. 86400 IN AAAA 2001:7b8:206:1::1 +example.com. 86400 IN RRSIG AAAA 3 2 86400 20070926134150 20070829134150 2854 example.com. MC0CFEqS4WHyqhUkv7t42TsBZJk/Q9paAhUAtTZ8GaXGpot0PmsM0oGzQU+2iw4= ;{id = 2854} +example.com. 86400 IN TXT "Stichting NLnet Labs" +example.com. 86400 IN RRSIG TXT 3 2 86400 20070926134150 20070829134150 2854 example.com. MCwCFH3otn2u8zXczBS8L0VKpyAYZGSkAhQLGaQclkzMAzlB5j73opFjdkh8TA== ;{id = 2854} +example.com. 86400 IN MX 100 v.net.example. +example.com. 86400 IN MX 50 open.example.com. +example.com. 86400 IN RRSIG MX 3 2 86400 20070926134150 20070829134150 2854 example.com. MCwCFEKh3jeqh69zcOqWWv3GNKlMECPyAhR9HJkcPLqlyVWUccWDFJfGGcQfdg== ;{id = 2854} +example.com. 86400 IN NS v.net.example. +example.com. 86400 IN NS open.example.com. +example.com. 86400 IN NS ns7.domain-registry.example. +example.com. 86400 IN RRSIG NS 3 2 86400 20070926134150 20070829134150 2854 example.com. MC0CFQCaRn30X4neKW7KYoTa2kcsoOLgfgIURvKEyDczLypWlx99KpxzMxRYhEc= ;{id = 2854} +example.com. 86400 IN A 213.154.224.1 +example.com. 86400 IN RRSIG A 3 2 86400 20070926134150 20070829134150 2854 example.com. MCwCFH8kSLxmRTwzlGDxvF1e4y/gM+5dAhQkzyQ2a6Gf+CMaHzVScaUvTt9HhQ== ;{id = 2854} +example.com. 18000 IN NSEC _sip._udp.example.com. A NS SOA MX TXT AAAA NAPTR RRSIG NSEC DNSKEY +example.com. 18000 IN RRSIG NSEC 3 2 18000 20070926134150 20070829134150 2854 example.com. MCwCFBzOGtpgq4uJ2jeuLPYl2HowIRzDAhQVXNz1haQ1mI7z9lt5gcvWW+lFhA== ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +open.example.com. 600 IN A 213.154.224.1 +open.example.com. 600 IN AAAA 2001:7b8:206:1::53 +open.example.com. 600 IN AAAA 2001:7b8:206:1::1 +_sip._udp.example.com. 600 IN SRV 0 0 5060 johnny.example.com. +open.example.com. 600 IN RRSIG A 3 3 600 20070926134150 20070829134150 2854 example.com. MC0CFQCh8bja923UJmg1+sYXMK8WIE4dpgIUQe9sZa0GOcUYSgb2rXoogF8af+Y= ;{id = 2854} +open.example.com. 600 IN RRSIG AAAA 3 3 600 20070926134150 20070829134150 2854 example.com. MC0CFQCRGJgIS6kEVG7aJfovuG/q3cgOWwIUYEIFCnfRQlMIYWF7BKMQoMbdkE0= ;{id = 2854} +_sip._udp.example.com. 600 IN RRSIG SRV 3 4 600 20070926134150 20070829134150 2854 example.com. MCwCFFSRVgOcq1ihVuO6MhCuzWs6SxpVAhRPHHCKy0JxymVkYeFOxTkbVSWMMw== ;{id = 2854} +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_any_cname.rpl b/testdata/val_any_cname.rpl new file mode 100644 index 00000000000..925bc924000 --- /dev/null +++ b/testdata/val_any_cname.rpl @@ -0,0 +1,161 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with response to qtype ANY that includes CNAME + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN ANY +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN ANY +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN ANY +SECTION ANSWER +www.example.com. 3600 IN CNAME serf.example.com. +www.example.com. 3600 IN RRSIG CNAME 3 3 3600 20070926134150 20070829134150 2854 example.com. AH/qSA7et6tXS08u4UUsWmXbIedGFpBKhiCqqVAgV8Z95dgn/vrB5ag= ;{id = 2854} +www.example.com. 18000 IN NSEC example.com. CNAME RRSIG NSEC +www.example.com. 18000 IN RRSIG NSEC 3 3 18000 20070926134150 20070829134150 2854 example.com. ACqeCl/aLq90zkeSfneQY+HnvJTUAeyTF03HWdXr3WhnYzupKAdnuQ4= ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +serf.example.com. IN ANY +SECTION ANSWER +serf.example.com. 3600 IN A 192.0.2.1 +serf.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. AGLOiUcDNkSCplT07hT8szlUfMHNfPh6/104ydBt4bJ6UcfXUiM3pV8= ;{id = 2854} +serf.example.com. 18000 IN NSEC www.example.com. A RRSIG NSEC +serf.example.com. 18000 IN RRSIG NSEC 3 3 18000 20070926134150 20070829134150 2854 example.com. AEBNiqg7Uz+NfNvoyA4KjkqJPb7hrjyS7oPE2MGNgVwUgQrcRIxd7DA= ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +MATCH TCP +REPLY RD DO +SECTION QUESTION +www.example.com. IN ANY +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN ANY +SECTION ANSWER +www.example.com. 3600 IN CNAME serf.example.com. +www.example.com. 3600 IN RRSIG CNAME 3 3 3600 20070926134150 20070829134150 2854 example.com. AH/qSA7et6tXS08u4UUsWmXbIedGFpBKhiCqqVAgV8Z95dgn/vrB5ag= ;{id = 2854} +www.example.com. 18000 IN NSEC example.com. CNAME RRSIG NSEC +www.example.com. 18000 IN RRSIG NSEC 3 3 18000 20070926134150 20070829134150 2854 example.com. ACqeCl/aLq90zkeSfneQY+HnvJTUAeyTF03HWdXr3WhnYzupKAdnuQ4= ;{id = 2854} +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_any_dname.rpl b/testdata/val_any_dname.rpl new file mode 100644 index 00000000000..459b11bd371 --- /dev/null +++ b/testdata/val_any_dname.rpl @@ -0,0 +1,204 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with response to qtype ANY that includes DNAME + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN ANY +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN ANY +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN ANY +SECTION ANSWER +example.com. 86400 IN SOA open.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000 +example.com. 86400 IN RRSIG SOA 3 2 86400 20070926134150 20070829134150 2854 example.com. MC0CFQCSs8KJepwaIp5vu++/0hk04lkXvgIUdphJSAE/MYob30WcRei9/nL49tE= ;{id = 2854} +example.com. 3600 IN DNAME example.net. +example.com. 3600 IN RRSIG DNAME 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCdje5lZfq9kENX9a8lOOKn79BRlQIUbVCx/fXo0kfvAgC5kB8Dvd5LodQ= ;{id = 2854} +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJIIs70j+sDS/UT2QRp61SE7S3EEXopNXoFE73JLRmvpi/UrOO/Vz4Se6wXv/CYCKjGw06U4WRgRYXcpEhJROyNapmdIKSxhOzfLVE1gqA0PweZR8dtY3aNQSRn3sPpwJr6Mi/PqQKAMMrZ9ckJpf1+bQMOOvxgzz2U1GS18b3yZKcgTMEaJzd/GZYzi/BN2DzQ0MsrSwYXfsNLFOBbs8PJMW4LYIxeeOe6rUgkWOF7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFHq7BNVAeLW+Uw/rkjVS08lrMDk/AhR+bvChHfiE4jLb6uoyE54/irCuqA== ;{id = 2854} +example.com. 600 IN NAPTR 20 0 "s" "SIP+D2U" "" _sip._udp.example.com. +example.com. 600 IN RRSIG NAPTR 3 2 600 20070926134150 20070829134150 2854 example.com. MC0CFE8qs66bzuOyKmTIacamrmqabMRzAhUAn0MujX1LB0UpTHuLMgdgMgJJlq4= ;{id = 2854} +example.com. 86400 IN AAAA 2001:7b8:206:1::1 +example.com. 86400 IN RRSIG AAAA 3 2 86400 20070926134150 20070829134150 2854 example.com. MC0CFEqS4WHyqhUkv7t42TsBZJk/Q9paAhUAtTZ8GaXGpot0PmsM0oGzQU+2iw4= ;{id = 2854} +example.com. 86400 IN TXT "Stichting NLnet Labs" +example.com. 86400 IN RRSIG TXT 3 2 86400 20070926134150 20070829134150 2854 example.com. MCwCFH3otn2u8zXczBS8L0VKpyAYZGSkAhQLGaQclkzMAzlB5j73opFjdkh8TA== ;{id = 2854} +example.com. 86400 IN MX 100 v.net.example. +example.com. 86400 IN MX 50 open.example.com. +example.com. 86400 IN RRSIG MX 3 2 86400 20070926134150 20070829134150 2854 example.com. MCwCFEKh3jeqh69zcOqWWv3GNKlMECPyAhR9HJkcPLqlyVWUccWDFJfGGcQfdg== ;{id = 2854} +example.com. 86400 IN NS v.net.example. +example.com. 86400 IN NS open.example.com. +example.com. 86400 IN NS ns7.domain-registry.example. +example.com. 86400 IN RRSIG NS 3 2 86400 20070926134150 20070829134150 2854 example.com. MC0CFQCaRn30X4neKW7KYoTa2kcsoOLgfgIURvKEyDczLypWlx99KpxzMxRYhEc= ;{id = 2854} +example.com. 86400 IN A 213.154.224.1 +example.com. 86400 IN RRSIG A 3 2 86400 20070926134150 20070829134150 2854 example.com. MCwCFH8kSLxmRTwzlGDxvF1e4y/gM+5dAhQkzyQ2a6Gf+CMaHzVScaUvTt9HhQ== ;{id = 2854} +example.com. 18000 IN NSEC _sip._udp.example.com. A NS SOA MX TXT AAAA NAPTR RRSIG NSEC DNSKEY +example.com. 18000 IN RRSIG NSEC 3 2 18000 20070926134150 20070829134150 2854 example.com. MCwCFBzOGtpgq4uJ2jeuLPYl2HowIRzDAhQVXNz1haQ1mI7z9lt5gcvWW+lFhA== ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +ns7.domain-registry.example. 80173 IN A 62.4.86.230 +open.example.com. 600 IN A 213.154.224.1 +open.example.com. 600 IN AAAA 2001:7b8:206:1::53 +open.example.com. 600 IN AAAA 2001:7b8:206:1::1 +v.net.example. 28800 IN A 213.154.224.17 +v.net.example. 28800 IN AAAA 2001:7b8:206:1:200:39ff:fe59:b187 +johnny.example.com. 600 IN A 213.154.224.44 +open.example.com. 600 IN RRSIG A 3 3 600 20070926134150 20070829134150 2854 example.com. MC0CFQCh8bja923UJmg1+sYXMK8WIE4dpgIUQe9sZa0GOcUYSgb2rXoogF8af+Y= ;{id = 2854} +open.example.com. 600 IN RRSIG AAAA 3 3 600 20070926134150 20070829134150 2854 example.com. MC0CFQCRGJgIS6kEVG7aJfovuG/q3cgOWwIUYEIFCnfRQlMIYWF7BKMQoMbdkE0= ;{id = 2854} +johnny.example.com. 600 IN RRSIG A 3 3 600 20070926134150 20070829134150 2854 example.com. MCwCFAh0/zSpCd/9eMNz7AyfnuGQFD1ZAhQEpNFNw4XByNEcbi/vsVeii9kp7g== ;{id = 2854} +_sip._udp.example.com. 600 IN RRSIG SRV 3 4 600 20070926134150 20070829134150 2854 example.com. MCwCFFSRVgOcq1ihVuO6MhCuzWs6SxpVAhRPHHCKy0JxymVkYeFOxTkbVSWMMw== ;{id = 2854} +_sip._udp.example.com. 600 IN SRV 0 0 5060 johnny.example.com. +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +MATCH TCP +REPLY RD DO +SECTION QUESTION +example.com. IN ANY +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +example.com. IN ANY +SECTION ANSWER +example.com. 86400 IN SOA open.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000 +example.com. 86400 IN RRSIG SOA 3 2 86400 20070926134150 20070829134150 2854 example.com. MC0CFQCSs8KJepwaIp5vu++/0hk04lkXvgIUdphJSAE/MYob30WcRei9/nL49tE= ;{id = 2854} +example.com. 3600 IN DNAME example.net. +example.com. 3600 IN RRSIG DNAME 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCdje5lZfq9kENX9a8lOOKn79BRlQIUbVCx/fXo0kfvAgC5kB8Dvd5LodQ= ;{id = 2854} +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJIIs70j+sDS/UT2QRp61SE7S3EEXopNXoFE73JLRmvpi/UrOO/Vz4Se6wXv/CYCKjGw06U4WRgRYXcpEhJROyNapmdIKSxhOzfLVE1gqA0PweZR8dtY3aNQSRn3sPpwJr6Mi/PqQKAMMrZ9ckJpf1+bQMOOvxgzz2U1GS18b3yZKcgTMEaJzd/GZYzi/BN2DzQ0MsrSwYXfsNLFOBbs8PJMW4LYIxeeOe6rUgkWOF7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFHq7BNVAeLW+Uw/rkjVS08lrMDk/AhR+bvChHfiE4jLb6uoyE54/irCuqA== ;{id = 2854} +example.com. 600 IN NAPTR 20 0 "s" "SIP+D2U" "" _sip._udp.example.com. +example.com. 600 IN RRSIG NAPTR 3 2 600 20070926134150 20070829134150 2854 example.com. MC0CFE8qs66bzuOyKmTIacamrmqabMRzAhUAn0MujX1LB0UpTHuLMgdgMgJJlq4= ;{id = 2854} +example.com. 86400 IN AAAA 2001:7b8:206:1::1 +example.com. 86400 IN RRSIG AAAA 3 2 86400 20070926134150 20070829134150 2854 example.com. MC0CFEqS4WHyqhUkv7t42TsBZJk/Q9paAhUAtTZ8GaXGpot0PmsM0oGzQU+2iw4= ;{id = 2854} +example.com. 86400 IN TXT "Stichting NLnet Labs" +example.com. 86400 IN RRSIG TXT 3 2 86400 20070926134150 20070829134150 2854 example.com. MCwCFH3otn2u8zXczBS8L0VKpyAYZGSkAhQLGaQclkzMAzlB5j73opFjdkh8TA== ;{id = 2854} +example.com. 86400 IN MX 100 v.net.example. +example.com. 86400 IN MX 50 open.example.com. +example.com. 86400 IN RRSIG MX 3 2 86400 20070926134150 20070829134150 2854 example.com. MCwCFEKh3jeqh69zcOqWWv3GNKlMECPyAhR9HJkcPLqlyVWUccWDFJfGGcQfdg== ;{id = 2854} +example.com. 86400 IN NS v.net.example. +example.com. 86400 IN NS open.example.com. +example.com. 86400 IN NS ns7.domain-registry.example. +example.com. 86400 IN RRSIG NS 3 2 86400 20070926134150 20070829134150 2854 example.com. MC0CFQCaRn30X4neKW7KYoTa2kcsoOLgfgIURvKEyDczLypWlx99KpxzMxRYhEc= ;{id = 2854} +example.com. 86400 IN A 213.154.224.1 +example.com. 86400 IN RRSIG A 3 2 86400 20070926134150 20070829134150 2854 example.com. MCwCFH8kSLxmRTwzlGDxvF1e4y/gM+5dAhQkzyQ2a6Gf+CMaHzVScaUvTt9HhQ== ;{id = 2854} +example.com. 18000 IN NSEC _sip._udp.example.com. A NS SOA MX TXT AAAA NAPTR RRSIG NSEC DNSKEY +example.com. 18000 IN RRSIG NSEC 3 2 18000 20070926134150 20070829134150 2854 example.com. MCwCFBzOGtpgq4uJ2jeuLPYl2HowIRzDAhQVXNz1haQ1mI7z9lt5gcvWW+lFhA== ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +open.example.com. 600 IN A 213.154.224.1 +open.example.com. 600 IN AAAA 2001:7b8:206:1::53 +open.example.com. 600 IN AAAA 2001:7b8:206:1::1 +_sip._udp.example.com. 600 IN SRV 0 0 5060 johnny.example.com. +open.example.com. 600 IN RRSIG A 3 3 600 20070926134150 20070829134150 2854 example.com. MC0CFQCh8bja923UJmg1+sYXMK8WIE4dpgIUQe9sZa0GOcUYSgb2rXoogF8af+Y= ;{id = 2854} +open.example.com. 600 IN RRSIG AAAA 3 3 600 20070926134150 20070829134150 2854 example.com. MC0CFQCRGJgIS6kEVG7aJfovuG/q3cgOWwIUYEIFCnfRQlMIYWF7BKMQoMbdkE0= ;{id = 2854} +_sip._udp.example.com. 600 IN RRSIG SRV 3 4 600 20070926134150 20070829134150 2854 example.com. MCwCFFSRVgOcq1ihVuO6MhCuzWs6SxpVAhRPHHCKy0JxymVkYeFOxTkbVSWMMw== ;{id = 2854} +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_cname_loop1.rpl b/testdata/val_cname_loop1.rpl new file mode 100644 index 00000000000..5fd4acc75b1 --- /dev/null +++ b/testdata/val_cname_loop1.rpl @@ -0,0 +1,144 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with cname loop + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME www.example.com. +www.example.com. 3600 IN RRSIG CNAME DSA 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFH0SwLHe7u56TshoVciFRHEl1KqbAhQ3zBOZMlL8bt1DqoDoM5ni8U/1UA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_cname_loop2.rpl b/testdata/val_cname_loop2.rpl new file mode 100644 index 00000000000..e8cd24bccb4 --- /dev/null +++ b/testdata/val_cname_loop2.rpl @@ -0,0 +1,153 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with cname 2 step loop + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME foo.example.com. +www.example.com. 3600 IN RRSIG CNAME DSA 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFH0SwLHe7u56TshoVciFRHEl1KqbAhQ3zBOZMlL8bt1DqoDoM5ni8U/1UA== ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +foo.example.com. IN A +SECTION ANSWER +foo.example.com. IN CNAME www.example.com. +foo.example.com. 3600 IN RRSIG CNAME DSA 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC7kcWPsMnGbjvzj5UNnxQzM0YvnAhUAgxIKgs1huJHvcAP2Xt3p8Adpy/c= ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_cname_loop3.rpl b/testdata/val_cname_loop3.rpl new file mode 100644 index 00000000000..e34b0108db2 --- /dev/null +++ b/testdata/val_cname_loop3.rpl @@ -0,0 +1,166 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with cname 3 step loop + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME foo.example.com. +www.example.com. 3600 IN RRSIG CNAME DSA 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFH0SwLHe7u56TshoVciFRHEl1KqbAhQ3zBOZMlL8bt1DqoDoM5ni8U/1UA== ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +foo.example.com. IN A +SECTION ANSWER +foo.example.com. IN CNAME bar.example.com. +foo.example.com. 3600 IN RRSIG CNAME DSA 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFFMlXuWrNL/8aYOl9U9WYjgif8gAAhUAqsC/xOXakHP1SYxMSLANziOik94= ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +bar.example.com. IN A +SECTION ANSWER +bar.example.com. IN CNAME www.example.com. +bar.example.com. 3600 IN RRSIG CNAME DSA 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFAsalUJJSV86uPlfiGS3kKDc0JB7AhQ+qmHqagY/r36Re/J3Q1OfvcA1dA== ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_cnameinsectopos.rpl b/testdata/val_cnameinsectopos.rpl new file mode 100644 index 00000000000..aa521c30fd5 --- /dev/null +++ b/testdata/val_cnameinsectopos.rpl @@ -0,0 +1,289 @@ +; config options +; The island of trust is at example.com +server: + ;trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + trust-anchor: "example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with an insecure cname to positive cached + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME www.example.net. +www.example.com. 3600 IN RRSIG CNAME DSA 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFGcJxnNxpWCBzXejiSdl4p1BKRMnAhUApoJrugVBRwFgAoYAhhqlZFac7fE= ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +insecure.example.com. IN A +SECTION ANSWER +insecure.example.com. IN CNAME www.example.net. +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN DNSKEY +SECTION ANSWER +example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.net. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +www.example.net. IN A 11.12.13.14 +www.example.net. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.net. CPxF5hK9Kg5eT7W6LgZwr0ePYEm9HMcSY4vvqCS6gDWB4X9jvXLCfBkCLhsNybPBpGWlsLi5wM6MTdJXuPpsRA== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME www.example.net. +www.example.com. 3600 IN RRSIG CNAME DSA 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFGcJxnNxpWCBzXejiSdl4p1BKRMnAhUApoJrugVBRwFgAoYAhhqlZFac7fE= ;{id = 2854} +www.example.net. IN A 11.12.13.14 +www.example.net. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.net. CPxF5hK9Kg5eT7W6LgZwr0ePYEm9HMcSY4vvqCS6gDWB4X9jvXLCfBkCLhsNybPBpGWlsLi5wM6MTdJXuPpsRA== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + + +; Get www.example.net validated in the cache. +STEP 30 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.net. IN A +ENTRY_END + +; recursion happens here. +STEP 40 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +www.example.net. IN A 11.12.13.14 +www.example.net. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.net. CPxF5hK9Kg5eT7W6LgZwr0ePYEm9HMcSY4vvqCS6gDWB4X9jvXLCfBkCLhsNybPBpGWlsLi5wM6MTdJXuPpsRA== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + + +; reference the cache object +STEP 50 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +insecure.example.com. IN A +ENTRY_END + +STEP 60 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +insecure.example.com. IN A +SECTION ANSWER +insecure.example.com. IN CNAME www.example.net. +www.example.net. IN A 11.12.13.14 +www.example.net. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.net. CPxF5hK9Kg5eT7W6LgZwr0ePYEm9HMcSY4vvqCS6gDWB4X9jvXLCfBkCLhsNybPBpGWlsLi5wM6MTdJXuPpsRA== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + + +SCENARIO_END diff --git a/testdata/val_cnamenx_dblnsec.rpl b/testdata/val_cnamenx_dblnsec.rpl new file mode 100644 index 00000000000..0064ab58047 --- /dev/null +++ b/testdata/val_cnamenx_dblnsec.rpl @@ -0,0 +1,176 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with cname-nxdomain for duplicate NSEC detection + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +cname.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +cname.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NXDOMAIN +SECTION QUESTION +cname.example.com. IN A +SECTION ANSWER +cname.example.com. 3600 IN CNAME www.example.com. +cname.example.com. 3600 IN RRSIG CNAME 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFBhJC8qi+g+EOYqzT2q6RxE8Im09AhUAotz8NFnpY+cpEDNBKjM940a74/E= ;{id = 2854} +SECTION AUTHORITY +; already includes the necessary NSECs +example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFCNGZ+/OfElYQMCZ77O9Lw9rhk7PAhUAmDcvTAst6Bq83qPq3r6c/Dm1nFc= ;{id = 2854} +; wildcard denial +example.com. IN NSEC abc.example.com. SOA NS DNSKEY NSEC RRSIG +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFHV2IBWyTmDJvZ+sT+WsGrJX0op/AhQkAijjnjPAtx/tNub2FAGqcexJSg== ;{id = 2854} +; qname denial +wab.example.com. IN NSEC wzz.example.com. A NSEC RRSIG +wab.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFG5DZSEIZC088rjcB1e6sQx8nQz4AhUAtQ09tP1YYLJkhL/Wg1KV2pW4Ivk= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NXDOMAIN +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFCNGZ+/OfElYQMCZ77O9Lw9rhk7PAhUAmDcvTAst6Bq83qPq3r6c/Dm1nFc= ;{id = 2854} +; wildcard denial +example.com. IN NSEC abc.example.com. SOA NS DNSKEY NSEC RRSIG +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFHV2IBWyTmDJvZ+sT+WsGrJX0op/AhQkAijjnjPAtx/tNub2FAGqcexJSg== ;{id = 2854} +; qname denial +wab.example.com. IN NSEC wzz.example.com. A NSEC RRSIG +wab.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFG5DZSEIZC088rjcB1e6sQx8nQz4AhUAtQ09tP1YYLJkhL/Wg1KV2pW4Ivk= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +cname.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NXDOMAIN +SECTION QUESTION +cname.example.com. IN A +SECTION ANSWER +cname.example.com. 3600 IN CNAME www.example.com. +cname.example.com. 3600 IN RRSIG CNAME 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFBhJC8qi+g+EOYqzT2q6RxE8Im09AhUAotz8NFnpY+cpEDNBKjM940a74/E= ;{id = 2854} +SECTION AUTHORITY +example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFCNGZ+/OfElYQMCZ77O9Lw9rhk7PAhUAmDcvTAst6Bq83qPq3r6c/Dm1nFc= ;{id = 2854} +example.com. IN NSEC abc.example.com. SOA NS DNSKEY NSEC RRSIG +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFHV2IBWyTmDJvZ+sT+WsGrJX0op/AhQkAijjnjPAtx/tNub2FAGqcexJSg== ;{id = 2854} +wab.example.com. IN NSEC wzz.example.com. A NSEC RRSIG +wab.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFG5DZSEIZC088rjcB1e6sQx8nQz4AhUAtQ09tP1YYLJkhL/Wg1KV2pW4Ivk= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_cnamenx_rcodenx.rpl b/testdata/val_cnamenx_rcodenx.rpl new file mode 100644 index 00000000000..6676b340f81 --- /dev/null +++ b/testdata/val_cnamenx_rcodenx.rpl @@ -0,0 +1,234 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + trust-anchor: "example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with cname-nxdomain with rcode nxdomain + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN CNAME www.example.net. +www.example.com. 3600 IN RRSIG CNAME 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFGtYzScyRnHV8U/jOIPYwrlI9t3oAhRF0PIf+IthUR7uCWIvskWp5CfReQ== ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN DNSKEY +SECTION ANSWER +example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.net. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +SECTION AUTHORITY +example.net. IN NSEC abc.example.net. SOA NS DNSKEY NSEC RRSIG +example.net. 3600 IN RRSIG NSEC 5 2 3600 20070926134150 20070829134150 30899 example.net. SEHthmjHyqGlzaOp3Dx6Jn5Fnvvtknw/IF6YSFY8NZLe+YSh1oRJbdEkQ8G92IT08n1jSN6jvKRsFBOUoFOQAw== ;{id = 30899} +wab.example.net. IN NSEC wzz.example.net. A NSEC RRSIG +wab.example.net. 3600 IN RRSIG NSEC 5 3 3600 20070926134150 20070829134150 30899 example.net. gl8vkI3xfSWx4Pyv5OdOthiewE6u/13kclY7UG9ptuFBddamdJO3RQqyxM6Xcmq+ToO4kMCCyaKijp01gTDoGg== ;{id = 30899} +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NXDOMAIN +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME www.example.net. +www.example.com. 3600 IN RRSIG CNAME 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFGtYzScyRnHV8U/jOIPYwrlI9t3oAhRF0PIf+IthUR7uCWIvskWp5CfReQ== ;{id = 2854} +SECTION AUTHORITY +example.net. IN NSEC abc.example.net. SOA NS DNSKEY NSEC RRSIG +example.net. 3600 IN RRSIG NSEC 5 2 3600 20070926134150 20070829134150 30899 example.net. SEHthmjHyqGlzaOp3Dx6Jn5Fnvvtknw/IF6YSFY8NZLe+YSh1oRJbdEkQ8G92IT08n1jSN6jvKRsFBOUoFOQAw== ;{id = 30899} +wab.example.net. IN NSEC wzz.example.net. A NSEC RRSIG +wab.example.net. 3600 IN RRSIG NSEC 5 3 3600 20070926134150 20070829134150 30899 example.net. gl8vkI3xfSWx4Pyv5OdOthiewE6u/13kclY7UG9ptuFBddamdJO3RQqyxM6Xcmq+ToO4kMCCyaKijp01gTDoGg== ;{id = 30899} +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_cnameqtype.rpl b/testdata/val_cnameqtype.rpl new file mode 100644 index 00000000000..cd9b8fa22c3 --- /dev/null +++ b/testdata/val_cnameqtype.rpl @@ -0,0 +1,228 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + trust-anchor: "example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with a query for type cname + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN CNAME +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN CNAME +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN CNAME +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN CNAME +SECTION ANSWER +www.example.com. IN CNAME www.example.net. +www.example.com. 3600 IN RRSIG CNAME DSA 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFGcJxnNxpWCBzXejiSdl4p1BKRMnAhUApoJrugVBRwFgAoYAhhqlZFac7fE= ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN DNSKEY +SECTION ANSWER +example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.net. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +www.example.net. IN A 11.12.13.14 +www.example.net. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.net. CPxF5hK9Kg5eT7W6LgZwr0ePYEm9HMcSY4vvqCS6gDWB4X9jvXLCfBkCLhsNybPBpGWlsLi5wM6MTdJXuPpsRA== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN CNAME +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN CNAME +SECTION ANSWER +www.example.com. IN CNAME www.example.net. +www.example.com. 3600 IN RRSIG CNAME DSA 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFGcJxnNxpWCBzXejiSdl4p1BKRMnAhUApoJrugVBRwFgAoYAhhqlZFac7fE= ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_cnametocloser.rpl b/testdata/val_cnametocloser.rpl new file mode 100644 index 00000000000..e9c05baed3d --- /dev/null +++ b/testdata/val_cnametocloser.rpl @@ -0,0 +1,103 @@ +; config options +server: + trust-anchor: "example.com. 3600 IN DS 30899 5 1 d4bf9d2e10f6d76840d42ef5913022abcd0bf512" + trust-anchor: "a.b.example.com. 3600 IN DNSKEY 257 3 5 AwEAAas/cAhCFXvBUgTSNZCvQp0pLx1dY+7rXR0hH4/3EUgWmsmbYUpI1qD0xhwKD/oYGEwAm291fyWJ9c0oVxXDEK8=" + val-override-date: "20091113091234" + +forward-zone: + name: "." + forward-addr: 192.0.2.1 +CONFIG_END + +SCENARIO_BEGIN Test validator with CNAME to closer anchor under optout. + +RANGE_BEGIN 0 100 + ADDRESS 192.0.2.1 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN AAAA +SECTION ANSWER +www.example.com. IN CNAME www.a.b.example.com. +www.example.com. 3600 IN RRSIG CNAME 5 3 3600 20091213091234 20091111091234 30899 example.com. mfQXJgOsRe8wiqNDZT4+ygSgRqzNowJ20o5+b681Mssp0xc007dq1ZaUYwUCdZjTn/GhF+f74t0UI1oqsFw2XA== ;{id = 30899} + +SECTION AUTHORITY +;; nsec3param 1 1 1 d399eaab +; example.com. -> l0c0e5lac37ai0lpij31sj699hkktdmb. +; b.example.com. -> 1lq6sb4omkd2vgj0l8lro2cbie223hco. +;; closest encloser: example.com. +l0c0e5lac37ai0lpij31sj699hkktdmb.example.com. IN NSEC3 1 1 1 d399eaab l0c0e5lac37ai0lpij31sj699hkktdmc SOA NS DNSKEY NSEC3PARAM RRSIG +l0c0e5lac37ai0lpij31sj699hkktdmb.example.com. 3600 IN RRSIG NSEC3 5 3 3600 20091213091234 20091111091234 30899 example.com. qjV0zsbDWLuoOQQ3tgCE2zo1z31bK9nv/Wh6xqKhmhyFI87nw2HM0lZGfRQrpWvWfBDczLRxHH9WNZkeIzv28w== ;{id = 30899} + +;; nextcloser is: b.example.com. ; under optout range. +; disproof of DS using the optout range. +1lq4sb4omkd2vgj0l8lro2cbie223hco.example.com. IN NSEC3 1 1 1 d399eaab 1lq8sb4omkd2vgj0l8lro2cbie223hco NS RRSIG +1lq4sb4omkd2vgj0l8lro2cbie223hco.example.com. 3600 IN RRSIG NSEC3 5 3 3600 20091213091234 20091111091234 30899 example.com. ZOJhHYt+YkGHBxHynuXlyZ8PEGg4YyqD/roWiEtBoP2PiGoPNCNqtWd0WjRgsUT0YFp/VqjqAU/RH8D45B8S8A== ;{id = 30899} + +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.a.b.example.com. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +; NSEC that proves there is no AAAA record +www.a.b.example.com. IN NSEC zzz.a.b.example.com. A NSEC RRSIG MX +www.a.b.example.com. 3600 IN RRSIG NSEC 5 5 3600 20091213091234 20091111091234 16486 a.b.example.com. pOj+aOIolZ8VXlLpaLD1NsYVbl8FW4wmsJbiVTYAMcyDOlgxOsbhTtlB4jQ7uV9pRVAzkvdm1V5wc/1PcncTuw== ;{id = 16486} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.com. 3600 IN RRSIG DNSKEY 5 2 3600 20091213091234 20091111091234 30899 example.com. hc+1QLqhy6lcfgH95k6eabsXrYsdH2oTLqDu6BjHYrmLi0kX4ZDiOI+syhIcGw9+hRqW1j8t+lsHvzvi7BgcXg== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +a.b.example.com. IN DNSKEY +SECTION ANSWER +a.b.example.com. 3600 IN DNSKEY 257 3 5 AwEAAas/cAhCFXvBUgTSNZCvQp0pLx1dY+7rXR0hH4/3EUgWmsmbYUpI1qD0xhwKD/oYGEwAm291fyWJ9c0oVxXDEK8= ;{id = 16486 (ksk), size = 512b} +a.b.example.com. 3600 IN RRSIG DNSKEY 5 4 3600 20091213091234 20091111091234 16486 a.b.example.com. kPftbF2Rut5h2Sc2k/gp27XS+4I9WQ/EYa5NJOnqfJZqpw/es7GuLyWAAZyvNhBDIUEenXtZ8k1H8F8poKdNXw== ;{id = 16486} +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN AAAA +ENTRY_END +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN AAAA +SECTION ANSWER +www.example.com. IN CNAME www.a.b.example.com. +www.example.com. 3600 IN RRSIG CNAME 5 3 3600 20091213091234 20091111091234 30899 example.com. mfQXJgOsRe8wiqNDZT4+ygSgRqzNowJ20o5+b681Mssp0xc007dq1ZaUYwUCdZjTn/GhF+f74t0UI1oqsFw2XA== ;{id = 30899} +SECTION AUTHORITY +l0c0e5lac37ai0lpij31sj699hkktdmb.example.com. 3600 IN NSEC3 1 1 1 d399eaab l0c0e5lac37ai0lpij31sj699hkktdmc NS SOA RRSIG DNSKEY NSEC3PARAM ; flags: optout +l0c0e5lac37ai0lpij31sj699hkktdmb.example.com. 3600 IN RRSIG NSEC3 5 3 3600 20091213091234 20091111091234 30899 example.com. qjV0zsbDWLuoOQQ3tgCE2zo1z31bK9nv/Wh6xqKhmhyFI87nw2HM0lZGfRQrpWvWfBDczLRxHH9WNZkeIzv28w== ;{id = 30899} +1lq4sb4omkd2vgj0l8lro2cbie223hco.example.com. 3600 IN NSEC3 1 1 1 d399eaab 1lq8sb4omkd2vgj0l8lro2cbie223hco NS RRSIG ; flags: optout +1lq4sb4omkd2vgj0l8lro2cbie223hco.example.com. 3600 IN RRSIG NSEC3 5 3 3600 20091213091234 20091111091234 30899 example.com. ZOJhHYt+YkGHBxHynuXlyZ8PEGg4YyqD/roWiEtBoP2PiGoPNCNqtWd0WjRgsUT0YFp/VqjqAU/RH8D45B8S8A== ;{id = 30899} +www.a.b.example.com. 3600 IN NSEC zzz.a.b.example.com. A MX RRSIG NSEC +www.a.b.example.com. 3600 IN RRSIG NSEC 5 5 3600 20091213091234 20091111091234 16486 a.b.example.com. pOj+aOIolZ8VXlLpaLD1NsYVbl8FW4wmsJbiVTYAMcyDOlgxOsbhTtlB4jQ7uV9pRVAzkvdm1V5wc/1PcncTuw== ;{id = 16486} +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_cnametocloser_nosig.rpl b/testdata/val_cnametocloser_nosig.rpl new file mode 100644 index 00000000000..c56faede711 --- /dev/null +++ b/testdata/val_cnametocloser_nosig.rpl @@ -0,0 +1,96 @@ +; config options +server: + trust-anchor: "example.com. 3600 IN DS 30899 5 1 d4bf9d2e10f6d76840d42ef5913022abcd0bf512" + trust-anchor: "a.b.example.com. 3600 IN DNSKEY 257 3 5 AwEAAas/cAhCFXvBUgTSNZCvQp0pLx1dY+7rXR0hH4/3EUgWmsmbYUpI1qD0xhwKD/oYGEwAm291fyWJ9c0oVxXDEK8=" + val-override-date: "20091113091234" + +forward-zone: + name: "." + forward-addr: 192.0.2.1 +CONFIG_END + +SCENARIO_BEGIN Test validator with CNAME to closer anchor optout missing sigs. + +RANGE_BEGIN 0 100 + ADDRESS 192.0.2.1 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN AAAA +SECTION ANSWER +www.example.com. IN CNAME www.a.b.example.com. +www.example.com. 3600 IN RRSIG CNAME 5 3 3600 20091213091234 20091111091234 30899 example.com. mfQXJgOsRe8wiqNDZT4+ygSgRqzNowJ20o5+b681Mssp0xc007dq1ZaUYwUCdZjTn/GhF+f74t0UI1oqsFw2XA== ;{id = 30899} + +SECTION AUTHORITY +;; nsec3param 1 1 1 d399eaab +; example.com. -> l0c0e5lac37ai0lpij31sj699hkktdmb. +; b.example.com. -> 1lq6sb4omkd2vgj0l8lro2cbie223hco. +;; closest encloser: example.com. +l0c0e5lac37ai0lpij31sj699hkktdmb.example.com. IN NSEC3 1 1 1 d399eaab l0c0e5lac37ai0lpij31sj699hkktdmc SOA NS DNSKEY NSEC3PARAM RRSIG +l0c0e5lac37ai0lpij31sj699hkktdmb.example.com. 3600 IN RRSIG NSEC3 5 3 3600 20091213091234 20091111091234 30899 example.com. qjV0zsbDWLuoOQQ3tgCE2zo1z31bK9nv/Wh6xqKhmhyFI87nw2HM0lZGfRQrpWvWfBDczLRxHH9WNZkeIzv28w== ;{id = 30899} + +;; nextcloser is: b.example.com. ; under optout range. +; disproof of DS using the optout range. +1lq4sb4omkd2vgj0l8lro2cbie223hco.example.com. IN NSEC3 1 1 1 d399eaab 1lq8sb4omkd2vgj0l8lro2cbie223hco NS RRSIG +1lq4sb4omkd2vgj0l8lro2cbie223hco.example.com. 3600 IN RRSIG NSEC3 5 3 3600 20091213091234 20091111091234 30899 example.com. ZOJhHYt+YkGHBxHynuXlyZ8PEGg4YyqD/roWiEtBoP2PiGoPNCNqtWd0WjRgsUT0YFp/VqjqAU/RH8D45B8S8A== ;{id = 30899} + +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.a.b.example.com. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +; NSEC that proves there is no AAAA record +www.a.b.example.com. IN NSEC zzz.a.b.example.com. A NSEC RRSIG MX +; signature missing! +;www.a.b.example.com. 3600 IN RRSIG NSEC 5 5 3600 20091213091234 20091111091234 16486 a.b.example.com. pOj+aOIolZ8VXlLpaLD1NsYVbl8FW4wmsJbiVTYAMcyDOlgxOsbhTtlB4jQ7uV9pRVAzkvdm1V5wc/1PcncTuw== ;{id = 16486} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.com. 3600 IN RRSIG DNSKEY 5 2 3600 20091213091234 20091111091234 30899 example.com. hc+1QLqhy6lcfgH95k6eabsXrYsdH2oTLqDu6BjHYrmLi0kX4ZDiOI+syhIcGw9+hRqW1j8t+lsHvzvi7BgcXg== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +a.b.example.com. IN DNSKEY +SECTION ANSWER +a.b.example.com. 3600 IN DNSKEY 257 3 5 AwEAAas/cAhCFXvBUgTSNZCvQp0pLx1dY+7rXR0hH4/3EUgWmsmbYUpI1qD0xhwKD/oYGEwAm291fyWJ9c0oVxXDEK8= ;{id = 16486 (ksk), size = 512b} +; signature missing! +;a.b.example.com. 3600 IN RRSIG DNSKEY 5 4 3600 20091213091234 20091111091234 16486 a.b.example.com. kPftbF2Rut5h2Sc2k/gp27XS+4I9WQ/EYa5NJOnqfJZqpw/es7GuLyWAAZyvNhBDIUEenXtZ8k1H8F8poKdNXw== ;{id = 16486} +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN AAAA +ENTRY_END +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN AAAA +SECTION ANSWER +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_cnametodname.rpl b/testdata/val_cnametodname.rpl new file mode 100644 index 00000000000..d9b05c6383e --- /dev/null +++ b/testdata/val_cnametodname.rpl @@ -0,0 +1,230 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + trust-anchor: "example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with a cname to a dname + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN DNAME +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN DNAME +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN DNAME +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN DNAME +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN DNAME +SECTION ANSWER +www.example.com. IN CNAME www.example.net. +www.example.com. 3600 IN RRSIG CNAME DSA 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFGcJxnNxpWCBzXejiSdl4p1BKRMnAhUApoJrugVBRwFgAoYAhhqlZFac7fE= ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN DNSKEY +SECTION ANSWER +example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.net. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN DNAME +SECTION ANSWER +www.example.net. IN DNAME blarg.com. +www.example.net. 3600 IN RRSIG DNAME RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. ByevtOI1ChCDb8CD8Qvu2pNcooUWN4LkNXQj0vzSLp62rCltiWWTg8iU6DiojeOx2inVqx+PZXyiX1nX80kCgg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN DNAME +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN DNAME +SECTION ANSWER +www.example.com. IN CNAME www.example.net. +www.example.com. 3600 IN RRSIG CNAME DSA 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFGcJxnNxpWCBzXejiSdl4p1BKRMnAhUApoJrugVBRwFgAoYAhhqlZFac7fE= ;{id = 2854} +www.example.net. IN DNAME blarg.com. +www.example.net. 3600 IN RRSIG DNAME RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. ByevtOI1ChCDb8CD8Qvu2pNcooUWN4LkNXQj0vzSLp62rCltiWWTg8iU6DiojeOx2inVqx+PZXyiX1nX80kCgg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_cnametodnametocnametopos.rpl b/testdata/val_cnametodnametocnametopos.rpl new file mode 100644 index 00000000000..887c1afc481 --- /dev/null +++ b/testdata/val_cnametodnametocnametopos.rpl @@ -0,0 +1,418 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + trust-anchor: "example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}" + trust-anchor: "example.org. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJIIs70j+sDS/UT2QRp61SE7S3EEXopNXoFE73JLRmvpi/UrOO/Vz4Se6wXv/CYCKjGw06U4WRgRYXcpEhJROyNapmdIKSxhOzfLVE1gqA0PweZR8dtY3aNQSRn3sPpwJr6Mi/PqQKAMMrZ9ckJpf1+bQMOOvxgzz2U1GS18b3yZKcgTMEaJzd/GZYzi/BN2DzQ0MsrSwYXfsNLFOBbs8PJMW4LYIxeeOe6rUgkWOF7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with cname, dname, cname, positive answer + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.org. IN A +SECTION AUTHORITY +org. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +org. IN NS +SECTION ANSWER +org. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.org. IN A +SECTION AUTHORITY +example.org. IN NS ns.example.org. +SECTION ADDITIONAL +ns.example.org. IN A 1.2.3.7 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME www.sub.example.net. +www.example.com. 3600 IN RRSIG CNAME 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFEv1gOb7KEskzkJNtFKKVBxY+Hb2AhUAqKJDIZJvNl+AdzqAt+JgdvnYAF0= ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN DNSKEY +SECTION ANSWER +example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.net. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.net. IN DS +SECTION ANSWER +SECTION AUTHORITY +sub.example.net. IN NSEC www.example.net. DNAME RRSIG NSEC +sub.example.net. 3600 IN RRSIG NSEC 5 3 3600 20070926134150 20070829134150 30899 example.net. PsKlcOSNElUi3u7Cn6c5+Sv8CRLTqmooMbvloTwUCkM53SuAirXcCA+9Pz5y0unO9+5IxwdkwssnoCOX5FqnCQ== ;{id = 30899} +SECTION ADDITIONAL +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.net. IN A +SECTION ANSWER +sub.example.net. IN DNAME sub.example.com. +sub.example.net. 3600 IN RRSIG DNAME 5 3 3600 20070926134150 20070829134150 30899 example.net. G/UmcL1VmCF2mjB1O9IeNM2DnvayxEy6vOrvA+Ic/Gqcsgnq/f4VTCV9soQQIAWEir2v5Vt8hqPDP8rCRbMnyA== ;{id = 30899} +www.sub.example.net. IN CNAME www.sub.example.com. +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response to DNSKEY priming query +; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899} +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN CNAME www.example.org. +www.sub.example.com. 3600 IN RRSIG CNAME 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. ZE6A4pkyeUpNCscu2oeBv/3JbbirdwUaAMgmQ/ighzacUJCC6Lh8vAL5aYDEyTk7oktb8uS7gmYan171aM9/tg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +; ns.example.org. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.7 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.org. IN NS +SECTION ANSWER +example.org. IN NS ns.example.org. +example.org. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.org. MCwCFAE1sQemdwqUPt4Qo+mr59a66DlFAhRV1mftIFs2YnkmIWsGtikIOJvh5A== ;{id = 2854} +SECTION ADDITIONAL +ns.example.org. IN A 1.2.3.7 +ns.example.org. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.org. MC0CFQC0yXaA8ywsZF+7dHukVIBFD820wQIUONbyI+UX9SDSDFmFnr+ApuTEooY= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.org. IN DNSKEY +SECTION ANSWER +example.org. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.org. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134150 20070829134150 2854 example.org. MC0CFBCSESiUl5XEht/LRecGFuX2Xad7AhUAoURP4DsIEbwMjlB955vziIB798E= ;{id = 2854} +SECTION AUTHORITY +example.org. IN NS ns.example.org. +example.org. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.org. MCwCFAE1sQemdwqUPt4Qo+mr59a66DlFAhRV1mftIFs2YnkmIWsGtikIOJvh5A== ;{id = 2854} +SECTION ADDITIONAL +ns.example.org. IN A 1.2.3.7 +ns.example.org. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.org. MC0CFQC0yXaA8ywsZF+7dHukVIBFD820wQIUONbyI+UX9SDSDFmFnr+ApuTEooY= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.org. IN A +SECTION ANSWER +www.example.org. IN A 11.11.11.11 +www.example.org. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.org. MC0CFB/erEAxSMqW0I51r6VQMq861B+yAhUAqJ7DPU7xHFpWJGILOQ0WW3aDGi0= ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN CNAME www.sub.example.net. +www.example.com. 3600 IN RRSIG CNAME 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFEv1gOb7KEskzkJNtFKKVBxY+Hb2AhUAqKJDIZJvNl+AdzqAt+JgdvnYAF0= ;{id = 2854} +sub.example.net. 3600 IN DNAME sub.example.com. +sub.example.net. 3600 IN RRSIG DNAME 5 3 3600 20070926134150 20070829134150 30899 example.net. G/UmcL1VmCF2mjB1O9IeNM2DnvayxEy6vOrvA+Ic/Gqcsgnq/f4VTCV9soQQIAWEir2v5Vt8hqPDP8rCRbMnyA== ;{id = 30899} +www.sub.example.net. 0 IN CNAME www.sub.example.com. +www.sub.example.com. 3600 IN CNAME www.example.org. +www.sub.example.com. 3600 IN RRSIG CNAME 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. ZE6A4pkyeUpNCscu2oeBv/3JbbirdwUaAMgmQ/ighzacUJCC6Lh8vAL5aYDEyTk7oktb8uS7gmYan171aM9/tg== ;{id = 30899} +www.example.org. 3600 IN A 11.11.11.11 +www.example.org. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.org. MC0CFB/erEAxSMqW0I51r6VQMq861B+yAhUAqJ7DPU7xHFpWJGILOQ0WW3aDGi0= ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_cnametoinsecure.rpl b/testdata/val_cnametoinsecure.rpl new file mode 100644 index 00000000000..aece72a7b65 --- /dev/null +++ b/testdata/val_cnametoinsecure.rpl @@ -0,0 +1,137 @@ +; config options +server: + trust-anchor: "example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}" + trust-anchor: "example.org. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}" + val-override-date: "20091011000000" + +forward-zone: + name: "." + forward-addr: 192.0.2.1 +CONFIG_END + +SCENARIO_BEGIN Test validator with CNAME to insecure NSEC or NSEC3. + +RANGE_BEGIN 0 100 + ADDRESS 192.0.2.1 + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.com. 3600 IN RRSIG DNSKEY 5 2 3600 20091012000000 20091010000000 30899 example.com. BeCk6+D0ysmO1+X0CjvXH55AO78C7Vxrq58C3YgO0wt2eTG/deZCiWI3bz+3OC64cICbJr5fvCfqUuJDABU/fw== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN AAAA +SECTION ANSWER +www.example.com. 3600 IN CNAME unsafe.example.com. +www.example.com. 3600 IN RRSIG CNAME 5 3 3600 20091012000000 20091010000000 30899 example.com. FJN0bZitZfxNQNTD1V2vcDBQ9cb4y4YGa35Ilr+VnrBiisAB9ZyrO8umvdtwzV1VPIlfFDQTJrKh5aZparLHPw== ;{id = 30899} +SECTION AUTHORITY +; really an insecure delegation, but co-hosted on the server. +unsafe.example.com. 3600 IN NSEC v.example.com. NS RRSIG NSEC +unsafe.example.com. 3600 IN RRSIG NSEC 5 3 3600 20091012000000 20091010000000 30899 example.com. Le9EsRd2MxkOGRCvGtQkXRDAob5ZJOFQlZbDvcWAh5OXVpmcwZmCHctxw/Zyi4LkNYoYCSCc8PiVRrJM3IsGrQ== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +unsafe.example.com. IN AAAA +SECTION ANSWER +; empty response +ENTRY_END + + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.org. IN DNSKEY +SECTION ANSWER +example.org. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.org. 3600 IN RRSIG DNSKEY 5 2 3600 20091012000000 20091010000000 30899 example.org. rd9aoXbeaE0zyT96Z0sjN3Mz5Nz/wuRsIH1lwcjwUFmAAT7F+SjwVWeo8nGaTBd8JDSUdiL+VwotEE0I22RrnA== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.org. IN AAAA +SECTION ANSWER +www.example.org. 3600 IN CNAME unsafe.example.org. +www.example.org. 3600 IN RRSIG CNAME 5 3 3600 20091012000000 20091010000000 30899 example.org. ZgRbMnunAqa1K46GINIihekkI73/1PkGFSAJRn7bSTxBpLM+qiHJDU1+QgS2SjaSKHqNqbXy/eeG3qX9r9y87g== ;{id = 30899} +SECTION AUTHORITY +; really an insecure delegation, but co-hosted on the server. +; h(unsafe.example.org.) = ltchu0548v0cof8f25u2pj4mjf4shcms. +ltchu0548v0cof8f25u2pj4mjf4shcms.example.org. IN NSEC3 1 0 1 - ltchu0548v0cof8f25u2pj4mjf4shcmt NS +ltchu0548v0cof8f25u2pj4mjf4shcms.example.org. 3600 IN RRSIG NSEC3 5 3 3600 20091012000000 20091010000000 30899 example.org. yxuYgfkg8QTdB5yBMN9Up9GyKu7xjKDScqq95/tsy3lx22tLsdLD9Fojdrq7eB+K7Tr72AejmVJs44v6TmWkZw== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +unsafe.example.org. IN AAAA +SECTION ANSWER +; empty response +ENTRY_END + +RANGE_END + +; NSEC +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN AAAA +ENTRY_END +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN AAAA +SECTION ANSWER +www.example.com. 3600 IN CNAME unsafe.example.com. +www.example.com. 3600 IN RRSIG CNAME 5 3 3600 20091012000000 20091010000000 30899 example.com. FJN0bZitZfxNQNTD1V2vcDBQ9cb4y4YGa35Ilr+VnrBiisAB9ZyrO8umvdtwzV1VPIlfFDQTJrKh5aZparLHPw== ;{id = 30899} +SECTION AUTHORITY +unsafe.example.com. 3600 IN NSEC v.example.com. NS RRSIG NSEC +unsafe.example.com. 3600 IN RRSIG NSEC 5 3 3600 20091012000000 20091010000000 30899 example.com. Le9EsRd2MxkOGRCvGtQkXRDAob5ZJOFQlZbDvcWAh5OXVpmcwZmCHctxw/Zyi4LkNYoYCSCc8PiVRrJM3IsGrQ== ;{id = 30899} +ENTRY_END + +; NSEC3 +STEP 20 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.org. IN AAAA +ENTRY_END +; recursion happens here. +STEP 30 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.org. IN AAAA +SECTION ANSWER +www.example.org. 3600 IN CNAME unsafe.example.org. +www.example.org. 3600 IN RRSIG CNAME 5 3 3600 20091012000000 20091010000000 30899 example.org. ZgRbMnunAqa1K46GINIihekkI73/1PkGFSAJRn7bSTxBpLM+qiHJDU1+QgS2SjaSKHqNqbXy/eeG3qX9r9y87g== ;{id = 30899} +SECTION AUTHORITY +ltchu0548v0cof8f25u2pj4mjf4shcms.example.org. 3600 IN NSEC3 1 0 1 - ltchu0548v0cof8f25u2pj4mjf4shcmt NS +ltchu0548v0cof8f25u2pj4mjf4shcms.example.org. 3600 IN RRSIG NSEC3 5 3 3600 20091012000000 20091010000000 30899 example.org. yxuYgfkg8QTdB5yBMN9Up9GyKu7xjKDScqq95/tsy3lx22tLsdLD9Fojdrq7eB+K7Tr72AejmVJs44v6TmWkZw== ;{id = 30899} +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_cnametonodata.rpl b/testdata/val_cnametonodata.rpl new file mode 100644 index 00000000000..e4716180670 --- /dev/null +++ b/testdata/val_cnametonodata.rpl @@ -0,0 +1,230 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + trust-anchor: "example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with cname to nodata + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN CNAME www.example.net. +www.example.com. 3600 IN RRSIG CNAME 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFGtYzScyRnHV8U/jOIPYwrlI9t3oAhRF0PIf+IthUR7uCWIvskWp5CfReQ== ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN DNSKEY +SECTION ANSWER +example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.net. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +SECTION AUTHORITY +www.example.net. IN NSEC example.net. MX NSEC RRSIG +www.example.net. 3600 IN RRSIG NSEC 5 3 3600 20070926134150 20070829134150 30899 example.net. Z+3/WKJEqhWoMOQLC7Yb1dTVGaqzmU0bZ2cH9jSfNQZiT0O37yzCNNUmMsW4gsJOh3o61iZ+hxpze3aO3aedqQ== ;{id = 30899} +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME www.example.net. +www.example.com. 3600 IN RRSIG CNAME 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFGtYzScyRnHV8U/jOIPYwrlI9t3oAhRF0PIf+IthUR7uCWIvskWp5CfReQ== ;{id = 2854} +SECTION AUTHORITY +www.example.net. IN NSEC example.net. MX NSEC RRSIG +www.example.net. 3600 IN RRSIG NSEC 5 3 3600 20070926134150 20070829134150 30899 example.net. Z+3/WKJEqhWoMOQLC7Yb1dTVGaqzmU0bZ2cH9jSfNQZiT0O37yzCNNUmMsW4gsJOh3o61iZ+hxpze3aO3aedqQ== ;{id = 30899} +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_cnametonsec.rpl b/testdata/val_cnametonsec.rpl new file mode 100644 index 00000000000..9e54909389b --- /dev/null +++ b/testdata/val_cnametonsec.rpl @@ -0,0 +1,158 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with CNAME to insecure NSEC delegation + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME www.sub.example.com. +www.example.com. 3600 IN RRSIG CNAME 3 3 3600 20070926134802 20070829134802 2854 example.com. AKvv+5rFiCFiNRbdpna4rQtyARsLltUL9lXRWgpBVB5voJNJ9g/n/f4= ;{id = 2854} +SECTION AUTHORITY +sub.example.com. IN NSEC zzz.example.com. NS +sub.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134802 20070829134802 2854 example.com. AJPvjSrqGbe3ZBOxV9J3XyFeOqrcPfIYPIWnlmj6G+PebJdAkvwIu9o= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +; this server also serves the zone sub.example.com. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +sub.example.com. IN SOA a. b. 1 2 3 4 5 +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME www.sub.example.com. +www.example.com. 3600 IN RRSIG CNAME 3 3 3600 20070926134802 20070829134802 2854 example.com. AKvv+5rFiCFiNRbdpna4rQtyARsLltUL9lXRWgpBVB5voJNJ9g/n/f4= ;{id = 2854} +SECTION AUTHORITY +sub.example.com. IN NSEC zzz.example.com. NS +sub.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134802 20070829134802 2854 example.com. AJPvjSrqGbe3ZBOxV9J3XyFeOqrcPfIYPIWnlmj6G+PebJdAkvwIu9o= ;{id = 2854} +sub.example.com. IN SOA a. b. 1 2 3 4 5 +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_cnametonx.rpl b/testdata/val_cnametonx.rpl new file mode 100644 index 00000000000..6b041bbc71b --- /dev/null +++ b/testdata/val_cnametonx.rpl @@ -0,0 +1,234 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + trust-anchor: "example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with cname to nxdomain + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN CNAME www.example.net. +www.example.com. 3600 IN RRSIG CNAME 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFGtYzScyRnHV8U/jOIPYwrlI9t3oAhRF0PIf+IthUR7uCWIvskWp5CfReQ== ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN DNSKEY +SECTION ANSWER +example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.net. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +SECTION AUTHORITY +example.net. IN NSEC abc.example.net. SOA NS DNSKEY NSEC RRSIG +example.net. 3600 IN RRSIG NSEC 5 2 3600 20070926134150 20070829134150 30899 example.net. SEHthmjHyqGlzaOp3Dx6Jn5Fnvvtknw/IF6YSFY8NZLe+YSh1oRJbdEkQ8G92IT08n1jSN6jvKRsFBOUoFOQAw== ;{id = 30899} +wab.example.net. IN NSEC wzz.example.net. A NSEC RRSIG +wab.example.net. 3600 IN RRSIG NSEC 5 3 3600 20070926134150 20070829134150 30899 example.net. gl8vkI3xfSWx4Pyv5OdOthiewE6u/13kclY7UG9ptuFBddamdJO3RQqyxM6Xcmq+ToO4kMCCyaKijp01gTDoGg== ;{id = 30899} +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NXDOMAIN +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME www.example.net. +www.example.com. 3600 IN RRSIG CNAME 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFGtYzScyRnHV8U/jOIPYwrlI9t3oAhRF0PIf+IthUR7uCWIvskWp5CfReQ== ;{id = 2854} +SECTION AUTHORITY +example.net. IN NSEC abc.example.net. SOA NS DNSKEY NSEC RRSIG +example.net. 3600 IN RRSIG NSEC 5 2 3600 20070926134150 20070829134150 30899 example.net. SEHthmjHyqGlzaOp3Dx6Jn5Fnvvtknw/IF6YSFY8NZLe+YSh1oRJbdEkQ8G92IT08n1jSN6jvKRsFBOUoFOQAw== ;{id = 30899} +wab.example.net. IN NSEC wzz.example.net. A NSEC RRSIG +wab.example.net. 3600 IN RRSIG NSEC 5 3 3600 20070926134150 20070829134150 30899 example.net. gl8vkI3xfSWx4Pyv5OdOthiewE6u/13kclY7UG9ptuFBddamdJO3RQqyxM6Xcmq+ToO4kMCCyaKijp01gTDoGg== ;{id = 30899} +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_cnametooptin.rpl b/testdata/val_cnametooptin.rpl new file mode 100644 index 00000000000..657dcd11e54 --- /dev/null +++ b/testdata/val_cnametooptin.rpl @@ -0,0 +1,162 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with CNAME to insecure optin NSEC3 + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME www.sub.example.com. +www.example.com. 3600 IN RRSIG CNAME 3 3 3600 20070926134802 20070829134802 2854 example.com. AKvv+5rFiCFiNRbdpna4rQtyARsLltUL9lXRWgpBVB5voJNJ9g/n/f4= ;{id = 2854} +SECTION AUTHORITY +; NSEC3PARAM 1 0 1 - +; example.com. -> 9vq38lj9qs6s1aruer131mbtsfnvek2p. +; sub.example.com. -> 7t1ect6t5vp0s7se8si9d07roqupr3gc. +; www.example.com. -> 0lverorlcjoa2lji5rik0otij3lgoj3l. +7t1ect6t5vp0s7se8si9d07roqupr3gc.example.com. IN NSEC3 1 0 1 - 7t1ect6t5vp0s7se8si9d07roqupr3gd NS +7t1ect6t5vp0s7se8si9d07roqupr3gc.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926134802 20070829134802 2854 example.com. AIiTSxI4hTDiDzo+bMaOKSvjIyoChgjY19y2NQG/Mtt80sNbDBY126I= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +; this server also serves the zone sub.example.com. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +sub.example.com. IN SOA a. b. 1 2 3 4 5 +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME www.sub.example.com. +www.example.com. 3600 IN RRSIG CNAME 3 3 3600 20070926134802 20070829134802 2854 example.com. AKvv+5rFiCFiNRbdpna4rQtyARsLltUL9lXRWgpBVB5voJNJ9g/n/f4= ;{id = 2854} +SECTION AUTHORITY +7t1ect6t5vp0s7se8si9d07roqupr3gc.example.com. IN NSEC3 1 0 1 - 7t1ect6t5vp0s7se8si9d07roqupr3gd NS +7t1ect6t5vp0s7se8si9d07roqupr3gc.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926134802 20070829134802 2854 example.com. AIiTSxI4hTDiDzo+bMaOKSvjIyoChgjY19y2NQG/Mtt80sNbDBY126I= ;{id = 2854} +sub.example.com. IN SOA a. b. 1 2 3 4 5 +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_cnametooptout.rpl b/testdata/val_cnametooptout.rpl new file mode 100644 index 00000000000..d4638d07f76 --- /dev/null +++ b/testdata/val_cnametooptout.rpl @@ -0,0 +1,110 @@ +; config options +server: + trust-anchor: "GOV. DS 26079 7 2 4ED5FFBC8A40262B56E1232135B929192804ACC006930D087AAB38A611C89041" + val-override-date: "20091113091234" + +forward-zone: + name: "." + forward-addr: 192.0.2.1 +CONFIG_END + +SCENARIO_BEGIN Test validator with CNAME to optout NSEC3 span NODATA + +RANGE_BEGIN 0 100 + ADDRESS 192.0.2.1 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.hud.gov. IN AAAA +SECTION ANSWER +www.hud.gov. 86400 IN CNAME www.content.hud.gov. +www.hud.gov. 86400 IN RRSIG CNAME 7 3 86400 20091204150200 20091104150200 64775 hud.gov. taZtumaTp8eSlcj0vEGnY0Up05RtlC2NhHrtHDUdq1TskAPQH8Eu9AoVe6gKrFEyCC1ixprOhT8Ni661d/ZykdzgceZ8KgFIlSQ84Whm59yB2gcbXLen9rApF0+NuyRgdAph6yjMYMtfoRQWAASG7SqS/v52dkHNf/a9PXaDvHBvjoiTK+dXPKFulkmEl0KyhXBdsikl6/Xd68FF41FdDNzWS8ZzYCdd4CWaXXkwTtPSFsKyXGZeXOTxqGQJnD+hNBkn2sAca1oLiAsfaiCHec66I+rHGXT+mPB7HXez32jbbeInkgB7M2TUoRXehifuloR8sur8Xck9FPRv24Si8A== ;{id = 64775} +SECTION AUTHORITY +content.hud.gov. 86400 IN NS drfswitch.hud.gov. +content.hud.gov. 86400 IN NS lanswitch.hud.gov. +3RUD2HK5O5KA0IC6BF22C1T4R1BJGJ3R.hud.gov. 86400 IN NSEC3 1 1 5 abcd 42bsks495i3mb2s3f6nhusc6rfm54g4g A NS SOA MX RRSIG DNSKEY NSEC3PARAM ; flags: optout +3RUD2HK5O5KA0IC6BF22C1T4R1BJGJ3R.hud.gov. 86400 IN RRSIG NSEC3 7 3 86400 20091204150200 20091104150200 64775 hud.gov. APf75Nx4eY9eHov3T9hduDLuG4TJfVfEUEhSgm7HIZRvSPFgajHz2q+Wy6888G3C0T1Zft1qL2PdHMonK6H1OEE+NiOxroDsZaH+aWZjAsbIO86qQ2xcC+/Z9DsddQtONk0zAqpuYxHSn879rAk/BIKeDukNoBChHCSTy8olUFiYt7XEmjz5AOoc8R5VQhMQi/vmbmC0BoFOemDxxowG2MX27Hj2MbVBEJiT8xioFEk41jsdDI0WQtpnory2NT/UM4kWZdmDdxbpwu2F8oixe3oi4AOI9j3EukoOZT9f0Sx+tCg/I9zLNZJi+VuI5oUlpZkSH5EoUyRgK33eO+KJhQ== ;{id = 64775} +GO8CPDSLPULIOURE31GBK5JJKA0BKIVN.hud.gov. 86400 IN NSEC3 1 1 5 abcd gvfjd9enpjtet8a14uhb8hlrfeon2b72 A RRSIG ; flags: optout +GO8CPDSLPULIOURE31GBK5JJKA0BKIVN.hud.gov. 86400 IN RRSIG NSEC3 7 3 86400 20091204150200 20091104150200 64775 hud.gov. eQFg/RvJ640k+Fa5yIUZwkx8FvsYSivykYFjc6dOiGt7r3VprfxwGWeYpyjYr/+mzu0ugE5ePDjZWtr5naK3dvqmt7qKk4/nEvVDoUmrg7joIUmeTzami9RB9lzCq2O/ddempQ6jpwfjiIDuEKUxHMpBFpw8QQZnZSZHKKQCDB4pOj8U8J/wNJXCS+SP7plU1hEVroC+QXCOYS8NHY2wFyeuW7A+xvg9tyYp9PH6c5MoNMkRQt36Kdvfk1nk3osktwalJNLmMhDr/vtErFieGGD6E9Ud9Pg70bPF2G5nqwwLDRevy7hIFjaMDHfYrcWc4B5hrUSpGtLJkYog9vsd2w== ;{id = 64775} +SECTION ADDITIONAL +drfswitch.hud.gov. 86400 IN A 170.97.167.1 +lanswitch.hud.gov. 86400 IN A 170.97.67.78 +drfswitch.hud.gov. 86400 IN RRSIG A 7 3 86400 20091204150200 20091104150200 64775 hud.gov. ub6Anb7XgDMRsTYxqKDRUOYnntLetcJMXM9SVbG7Cb2n+ccp4OO38u6KnGO1i8U5rhTQ6WPlG6iKA+8U0mQuWp3fkzBaE+a5R3eEfzLlRE/MbjUqHjTb0MVYQnMWaA7YXmj/1BNFjBuAam+J3QnU4JR3RqN9WDmHXYx8IUEY9BYSWvTMhOnzebRu6z9MUBQWFfm69pFxf0Z1SkpInznU/mxGdGlslzxL8ScKAUMSBiQG1tyL90OEXW3Yp7kbOtpTxGrXucpMiMB9lXI/z9UiRJenZrJ7swyyyJ5Do0TjCiS3oS8RBhX8ou09sNftUmF9crKz/BdNq90wVYoHXYz9vg== ;{id = 64775} +lanswitch.hud.gov. 86400 IN RRSIG A 7 3 86400 20091204150200 20091104150200 64775 hud.gov. QO+quzaZXrIBZy0JXhx85/8auhBj8dCqeidaUCs6rzCd/lgUDt7B/mH8IanU33o+PyKsBN+B5r9bavFFCNc4sPDUVwNcnZfKCyFQvvUnI3rztCJb/ESYnJ/xu/5g966cRLOajzAvvLAWZ6vT4p3b9+CpaONOJ19D08RpwsWnTkqiEP/UiXaWBpVwyt4JHN0oiNmMGshk5zjbHir1gUInd7QbJk3SpyiIgHT5Z4nhTUGkd1sIve++aIxjsQ8MVrE+INw4v56dJaoYD6bqQewmg2yAr9nYemYUHYi8+USy7/anEaUsOvk9zZfncevTfY/sOORFWoD15bHF2BWUo2YwaQ== ;{id = 64775} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.content.hud.gov. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +GOV. IN DNSKEY +SECTION ANSWER +GOV. 86400 IN DNSKEY 256 3 7 AwEAAaQ6vDoHd2QDRBLwB+n63RxnmJExvIcOz7uv9gM+l8QSMAJTTCDpqJ8R+8UfYs97cn6LM3cT3kcl9V0GnjljNzNMk39W11Ej7htNcbf4u1n5z2e4WsnpjQJJmKoWv2FORIfJmLKbxzGILSK13mrDUETj9onhdtOsjkhcK/7S+h1d ;{id = 51998 (zsk), size = 1024b} +GOV. 86400 IN DNSKEY 257 3 7 AwEAAZ1OCt7zZxeaROvzXNCNlqQWIi++p5ABXSoxqJ65WQko6xrI9RImK7IBT5roFhXjBDGJ8ld9CYIEN94kK83K/QwUGCJ+v3vIQFi09IqsPeRdHTQyghWWbhzAZpnlZ16imXB4yFZjdbV2iM66KcgsESQMPEcIayDQJh6JEi1wmslrYvRRJ6YPOWrlLD0RmdtCaRuzlUE0RiWSem/i8vDFdmsSwChRMcORklKqjqt1+RBIiEFJGKIz7lGc9DXRwkBfb+halii+jrELiZAPzfO7rf08l3QlgHEuxclTTdEaxctPd2O2U/Hl9tRgkxRL/Zv1i0sEx2mOJGcUCeVm4Hf2aM8= ;{id = 26079 (ksk), size = 2048b} +GOV. 86400 IN RRSIG DNSKEY 7 1 86400 20091117211705 20091112211705 26079 gov. OR2ltuGs0IxWqikvqWIoXLy7gPpWafolM+fyQ9uyuzPdxILo8QboVzfRr3Q8X/hOa6MRwR0KHGci2NH/29p9cekafdMbOer0kvh0hndnf+yGLuDcd9HLj5hpoZ5uecZ2r02OWtRHCKetAPF95SYrIQBzoqUNOswdDlSTW1R8v/BQ6UpztuUQcciZJxARbXlovzSkMbnoyjtehgKjXPP/Zy79vSwhjpTJ4XAsc2E3Tw1qAE7ZZUzYpN8uGmAQYVtZraQIjazE/A+xVo+XB0dZdhlM00xUs6GNuZytckUOqecBKZ2IKlxBe+kBEkj2nz1PBRAzmZUoS3ZZPkKaA6ygTA== ;{id = 26079} +GOV. 86400 IN RRSIG DNSKEY 7 1 86400 20091117211705 20091112211705 51998 gov. VDizeuAywZB0tQm4kmbOSGhrK1eJYC9VSSND/wG7oTj/oWDAKMEke1XrQXGEoIFyBKZk5dHpUB6tmEA9RPLMwI51ue66pM9RRT1aNLba08r6TDzr6ZxKjtqBDj4Xy16h6PWZ2jC9JASGeNGINg6zCeVmU75yqXh6+X+KeypO64E= ;{id = 51998} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +hud.gov. IN DS +SECTION ANSWER +hud.gov. 86399 IN DS 52146 7 2 54af554fc3ffc532bb898b9ab39f1276fd17b59d3e44772c3142ea62680d71c7 ; xihap-zehog-zybyz-zecaf-dyvym-nydun-pusan-zagil-kezyc-lutyn-tazog-gyted-sosig-depyk-dypeb-tasas-lexix +hud.gov. 86399 IN RRSIG DS 7 2 86400 20091117211705 20091112211705 51998 gov. FHDstL7xVBBedCaG83M884pnxCV8PY9GjUulwH7BSTVIaFBJe/kxlKGTsD0j5x4QfezjBWKenjpvw5SiMGeQOnIJeA/z6Ze9QBCGVrbx0ZgoKEoSRyfD0vIjvM7J4T2PLgslI8fsMpWFs4KzmujKJNRVq4aFzFk9k8bFCJnEPJk= ;{id = 51998} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +hud.gov. IN DNSKEY +SECTION ANSWER +hud.gov. 86400 IN DNSKEY 256 3 7 AwEAAcAOoW+zclZqs8kCGmm290DImA1DDfKqbifB1oGNjOcmz6xz6PigLa8ORaAG0zpabZwLMXyhMaKbseR+beGnOf2wh5N0oxN8grCNTJm+YAMeyvCn2dz3J8YEoclyST4bhU38MGFsEVVZukXsIniFfvnKfpVxArpO7ocbDXI+EN3RA8EHFTIHOCfEbCS7zyO0mtrdM88Y/tIX9fjsYUig6lfVUNISJUL4TyUMpmi8/hu2dLdTuXXIAEMx/vyQHVFq2ZZM0nnDJ9vJCZEgwFAjUE5/BjlrDgofonxdY8SLDbQvn11z/SPugKiA16bdO6i/ND4FjEhG2HUJHeeQCrZ61rE= ;{id = 64775 (zsk), size = 2048b} +hud.gov. 86400 IN DNSKEY 256 3 7 AwEAAfFubFVJ6m7jO8HvInmFEXivfnqZZpS7SnsucTlfGg5yhIayzS3tC0UMAt1QU+pEIyVH+qa2fG2+/45gAp+iG3zwyepyZuup8eo/SlXefWXZ9CIjBNaaptd2sSDsuF8mPtdQmtm3AbPqGEe7p7edIHHJBxPy90AzJQeKppyRcRcrGO3QNC9Glso177NbHZVZuY46V63RdaY3Qf5t7/03xy/Z68KWFEJKUCBxkHjAVIH0KaT9M37dPzs9L7F/+NyOLfMUzk87ctv4ivW9dcJRf79aulzoIV4LlGu0ZsrvxRZ5t+ind+GDeTvaKseH0NWF5Am2dG/QrHtewQL9qGztjN8= ;{id = 41402 (zsk), size = 2048b} +hud.gov. 86400 IN DNSKEY 257 3 7 AwEAAZ50d20TkOzWzJD+anUMSIMfGaI8m4If6DMax4NQnZ34yta6UOb907SRqBs2vJ+MpcJkyRuLx/Z9vGlfZQ7V9eBgI62EZwmfiitanwSFPZgCzM8nVswpDS+/CmaHhXUoLdgNgUYh4WSl/7fXroluC/18xyMl3ZGQRRjJftpQSMXubP/n9nCHZXE5YiDw1cRklqA4lLyNeXBgadWa8klekr89WNij454KApevbg0GSudEJw7IWzbOb09npvQ1hnLz8pmDsaahfIsGBvcHSUEJrjSkk3J1oHDj0B7Gxm+tZH4Er21RTucEWeroyIJSQmsYN+Cm0FyfgJ75bNEsRe5M4Vc= ;{id = 52146 (ksk), size = 2048b} +hud.gov. 86400 IN RRSIG DNSKEY 7 2 86400 20091204150200 20091104150200 52146 hud.gov. KWIA6wH6BqwuF7d6dyTbfqbcLgbUG2ZKJA4vVfhWqOC76Xnt7gXPLeB2GQwwyhSR0s3IHIzAB0Uj+RAGGcz2NH5JanfxNC9rAvubYESXSlLr/FC33exLeOxGisJZzRnPpk5NynXwyT8TXul1ew48/Mpyi7j6+tlqakqHw2HlId7oblxO2cjN6JV0JLZ44l7tCw6ALYhamA48PQ1WeJbGcfH7buCEG7S1ceZSZlG6kml+u7pb65QL9AZjCnDIecXk7B3HMCdIT8zyrO8QK0GiLMMak9RogF/5gBiH/WDCq7146vcVneW/Hn/+hLnY104iOKuadJcbmStlMF5k0iBzng== ;{id = 52146} +hud.gov. 86400 IN RRSIG DNSKEY 7 2 86400 20091204150200 20091104150200 64775 hud.gov. V0JSAtTmQn76T408nyntg1ydX5sVvq8RSCN/Bf+cqTPXMFlPpmOs4VQv791bY85n28qOehV7Ws2CrhfxbyFbyYRXPBtWkg6jH3JXicYPn7Abm7E5N2Y6Mkm1Z9xt/APCw+aSkt0swMJzYBO5P5aeDesIB+Pz5I+SLuOPin3GFjGYL+YB5j5rTY/Nqnp2eQytF0SoFdqCIPCP7l9ZtYdaxBDQNX3Hklm4dRYP5U9wL8sqaeUwgKjJTGcbXiXdPXF9+3AojshKMpk14lcplHcy+cQ4p5ehSngtDwdWtG8gcWKCg829I/1iOFcnPgJ1YK1DdPVEGTgUFgGGwTx+HYMsPA== ;{id = 64775} +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.hud.gov. IN AAAA +ENTRY_END +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.hud.gov. IN AAAA +SECTION ANSWER +www.hud.gov. 86400 IN CNAME www.content.hud.gov. +www.hud.gov. 86400 IN RRSIG CNAME 7 3 86400 20091204150200 20091104150200 64775 hud.gov. taZtumaTp8eSlcj0vEGnY0Up05RtlC2NhHrtHDUdq1TskAPQH8Eu9AoVe6gKrFEyCC1ixprOhT8Ni661d/ZykdzgceZ8KgFIlSQ84Whm59yB2gcbXLen9rApF0+NuyRgdAph6yjMYMtfoRQWAASG7SqS/v52dkHNf/a9PXaDvHBvjoiTK+dXPKFulkmEl0KyhXBdsikl6/Xd68FF41FdDNzWS8ZzYCdd4CWaXXkwTtPSFsKyXGZeXOTxqGQJnD+hNBkn2sAca1oLiAsfaiCHec66I+rHGXT+mPB7HXez32jbbeInkgB7M2TUoRXehifuloR8sur8Xck9FPRv24Si8A== ;{id = 64775} +SECTION AUTHORITY +3RUD2HK5O5KA0IC6BF22C1T4R1BJGJ3R.hud.gov. 86400 IN NSEC3 1 1 5 abcd 42bsks495i3mb2s3f6nhusc6rfm54g4g A NS SOA MX RRSIG DNSKEY NSEC3PARAM ; flags: optout +3RUD2HK5O5KA0IC6BF22C1T4R1BJGJ3R.hud.gov. 86400 IN RRSIG NSEC3 7 3 86400 20091204150200 20091104150200 64775 hud.gov. APf75Nx4eY9eHov3T9hduDLuG4TJfVfEUEhSgm7HIZRvSPFgajHz2q+Wy6888G3C0T1Zft1qL2PdHMonK6H1OEE+NiOxroDsZaH+aWZjAsbIO86qQ2xcC+/Z9DsddQtONk0zAqpuYxHSn879rAk/BIKeDukNoBChHCSTy8olUFiYt7XEmjz5AOoc8R5VQhMQi/vmbmC0BoFOemDxxowG2MX27Hj2MbVBEJiT8xioFEk41jsdDI0WQtpnory2NT/UM4kWZdmDdxbpwu2F8oixe3oi4AOI9j3EukoOZT9f0Sx+tCg/I9zLNZJi+VuI5oUlpZkSH5EoUyRgK33eO+KJhQ== ;{id = 64775} +GO8CPDSLPULIOURE31GBK5JJKA0BKIVN.hud.gov. 86400 IN NSEC3 1 1 5 abcd gvfjd9enpjtet8a14uhb8hlrfeon2b72 A RRSIG ; flags: optout +GO8CPDSLPULIOURE31GBK5JJKA0BKIVN.hud.gov. 86400 IN RRSIG NSEC3 7 3 86400 20091204150200 20091104150200 64775 hud.gov. eQFg/RvJ640k+Fa5yIUZwkx8FvsYSivykYFjc6dOiGt7r3VprfxwGWeYpyjYr/+mzu0ugE5ePDjZWtr5naK3dvqmt7qKk4/nEvVDoUmrg7joIUmeTzami9RB9lzCq2O/ddempQ6jpwfjiIDuEKUxHMpBFpw8QQZnZSZHKKQCDB4pOj8U8J/wNJXCS+SP7plU1hEVroC+QXCOYS8NHY2wFyeuW7A+xvg9tyYp9PH6c5MoNMkRQt36Kdvfk1nk3osktwalJNLmMhDr/vtErFieGGD6E9Ud9Pg70bPF2G5nqwwLDRevy7hIFjaMDHfYrcWc4B5hrUSpGtLJkYog9vsd2w== ;{id = 64775} +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_cnametopos.rpl b/testdata/val_cnametopos.rpl new file mode 100644 index 00000000000..d5136d5c5c6 --- /dev/null +++ b/testdata/val_cnametopos.rpl @@ -0,0 +1,230 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + trust-anchor: "example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with a cname to positive + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME www.example.net. +www.example.com. 3600 IN RRSIG CNAME DSA 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFGcJxnNxpWCBzXejiSdl4p1BKRMnAhUApoJrugVBRwFgAoYAhhqlZFac7fE= ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN DNSKEY +SECTION ANSWER +example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.net. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +www.example.net. IN A 11.12.13.14 +www.example.net. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.net. CPxF5hK9Kg5eT7W6LgZwr0ePYEm9HMcSY4vvqCS6gDWB4X9jvXLCfBkCLhsNybPBpGWlsLi5wM6MTdJXuPpsRA== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME www.example.net. +www.example.com. 3600 IN RRSIG CNAME DSA 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFGcJxnNxpWCBzXejiSdl4p1BKRMnAhUApoJrugVBRwFgAoYAhhqlZFac7fE= ;{id = 2854} +www.example.net. IN A 11.12.13.14 +www.example.net. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.net. CPxF5hK9Kg5eT7W6LgZwr0ePYEm9HMcSY4vvqCS6gDWB4X9jvXLCfBkCLhsNybPBpGWlsLi5wM6MTdJXuPpsRA== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_cnametoposnowc.rpl b/testdata/val_cnametoposnowc.rpl new file mode 100644 index 00000000000..bc1a6945667 --- /dev/null +++ b/testdata/val_cnametoposnowc.rpl @@ -0,0 +1,262 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + trust-anchor: "example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with a cname to positive wildcard without proof + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME www.example.net. +www.example.com. 3600 IN RRSIG CNAME DSA 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFGcJxnNxpWCBzXejiSdl4p1BKRMnAhUApoJrugVBRwFgAoYAhhqlZFac7fE= ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN AAAA +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN A +ENTRY_END +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN DNSKEY +SECTION ANSWER +example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.net. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +; from *.example.net. +www.example.net. IN A 11.12.13.14 +www.example.net. 3600 IN RRSIG A 5 2 3600 20070926134150 20070829134150 30899 example.net. quSyDbSeHRvyMmanqq5rW+APC9MKOswbRLB5QP/G+C2iyokQFLuRTlX9Wmo/jo1Oo1MGBefJUmP9NdRd2EqABA== ;{id = 30899} +SECTION AUTHORITY +; missing proof +;wab.example.net IN NSEC wzz.example.net. A NSEC RRSIG +;wab.example.net. 3600 IN RRSIG NSEC 5 3 3600 20070926134150 20070829134150 30899 example.net. gl8vkI3xfSWx4Pyv5OdOthiewE6u/13kclY7UG9ptuFBddamdJO3RQqyxM6Xcmq+ToO4kMCCyaKijp01gTDoGg== ;{id = 30899} +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.net. IN A +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.net. IN AAAA +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_cnametoposwc.rpl b/testdata/val_cnametoposwc.rpl new file mode 100644 index 00000000000..feb178b087d --- /dev/null +++ b/testdata/val_cnametoposwc.rpl @@ -0,0 +1,236 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + trust-anchor: "example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with a cname to positive wildcard + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME www.example.net. +www.example.com. 3600 IN RRSIG CNAME DSA 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFGcJxnNxpWCBzXejiSdl4p1BKRMnAhUApoJrugVBRwFgAoYAhhqlZFac7fE= ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN DNSKEY +SECTION ANSWER +example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.net. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +; from *.example.net. +www.example.net. IN A 11.12.13.14 +www.example.net. 3600 IN RRSIG A 5 2 3600 20070926134150 20070829134150 30899 example.net. quSyDbSeHRvyMmanqq5rW+APC9MKOswbRLB5QP/G+C2iyokQFLuRTlX9Wmo/jo1Oo1MGBefJUmP9NdRd2EqABA== ;{id = 30899} +SECTION AUTHORITY +wab.example.net IN NSEC wzz.example.net. A NSEC RRSIG +wab.example.net. 3600 IN RRSIG NSEC 5 3 3600 20070926134150 20070829134150 30899 example.net. gl8vkI3xfSWx4Pyv5OdOthiewE6u/13kclY7UG9ptuFBddamdJO3RQqyxM6Xcmq+ToO4kMCCyaKijp01gTDoGg== ;{id = 30899} +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME www.example.net. +www.example.com. 3600 IN RRSIG CNAME DSA 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFGcJxnNxpWCBzXejiSdl4p1BKRMnAhUApoJrugVBRwFgAoYAhhqlZFac7fE= ;{id = 2854} +www.example.net. IN A 11.12.13.14 +www.example.net. 3600 IN RRSIG A 5 2 3600 20070926134150 20070829134150 30899 example.net. quSyDbSeHRvyMmanqq5rW+APC9MKOswbRLB5QP/G+C2iyokQFLuRTlX9Wmo/jo1Oo1MGBefJUmP9NdRd2EqABA== ;{id = 30899} +SECTION AUTHORITY +wab.example.net IN NSEC wzz.example.net. A NSEC RRSIG +wab.example.net. 3600 IN RRSIG NSEC 5 3 3600 20070926134150 20070829134150 30899 example.net. gl8vkI3xfSWx4Pyv5OdOthiewE6u/13kclY7UG9ptuFBddamdJO3RQqyxM6Xcmq+ToO4kMCCyaKijp01gTDoGg== ;{id = 30899} +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_cnamewctonodata.rpl b/testdata/val_cnamewctonodata.rpl new file mode 100644 index 00000000000..97722566bc5 --- /dev/null +++ b/testdata/val_cnamewctonodata.rpl @@ -0,0 +1,234 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + trust-anchor: "example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with wilcard cname to nodata + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN CNAME www.example.net. +www.example.com. 3600 IN RRSIG CNAME 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFDwBErFx90ixZDOdIsKz1QaXA1WzAhUAprOUlV1d5fmUiOp7DZ0TWWcM81Q= ;{id = 2854} +SECTION AUTHORITY +u.example.com. IN NSEC z.example.com. NSEC RRSIG +u.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCdc/AWOi3BbYLOClSaw7uVkEf0/AhRJLUUXhuvEsdxEXESjotO3tJZyog== ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN DNSKEY +SECTION ANSWER +example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.net. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +SECTION AUTHORITY +www.example.net. IN NSEC example.net. MX NSEC RRSIG +www.example.net. 3600 IN RRSIG NSEC 5 3 3600 20070926134150 20070829134150 30899 example.net. Z+3/WKJEqhWoMOQLC7Yb1dTVGaqzmU0bZ2cH9jSfNQZiT0O37yzCNNUmMsW4gsJOh3o61iZ+hxpze3aO3aedqQ== ;{id = 30899} +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME www.example.net. +www.example.com. 3600 IN RRSIG CNAME 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFDwBErFx90ixZDOdIsKz1QaXA1WzAhUAprOUlV1d5fmUiOp7DZ0TWWcM81Q= ;{id = 2854} +SECTION AUTHORITY +u.example.com. IN NSEC z.example.com. NSEC RRSIG +u.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCdc/AWOi3BbYLOClSaw7uVkEf0/AhRJLUUXhuvEsdxEXESjotO3tJZyog== ;{id = 2854} +www.example.net. IN NSEC example.net. MX NSEC RRSIG +www.example.net. 3600 IN RRSIG NSEC 5 3 3600 20070926134150 20070829134150 30899 example.net. Z+3/WKJEqhWoMOQLC7Yb1dTVGaqzmU0bZ2cH9jSfNQZiT0O37yzCNNUmMsW4gsJOh3o61iZ+hxpze3aO3aedqQ== ;{id = 30899} +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_cnamewctonx.rpl b/testdata/val_cnamewctonx.rpl new file mode 100644 index 00000000000..5675c42a575 --- /dev/null +++ b/testdata/val_cnamewctonx.rpl @@ -0,0 +1,238 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + trust-anchor: "example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with wildcard cname to nxdomain + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 3600 IN CNAME www.example.net. +www.example.com. 3600 IN RRSIG CNAME 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFDwBErFx90ixZDOdIsKz1QaXA1WzAhUAprOUlV1d5fmUiOp7DZ0TWWcM81Q= ;{id = 2854} +SECTION AUTHORITY +u.example.com. IN NSEC z.example.com. NSEC RRSIG +u.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCdc/AWOi3BbYLOClSaw7uVkEf0/AhRJLUUXhuvEsdxEXESjotO3tJZyog== ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN DNSKEY +SECTION ANSWER +example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.net. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +SECTION AUTHORITY +example.net. IN NSEC abc.example.net. SOA NS DNSKEY NSEC RRSIG +example.net. 3600 IN RRSIG NSEC 5 2 3600 20070926134150 20070829134150 30899 example.net. SEHthmjHyqGlzaOp3Dx6Jn5Fnvvtknw/IF6YSFY8NZLe+YSh1oRJbdEkQ8G92IT08n1jSN6jvKRsFBOUoFOQAw== ;{id = 30899} +wab.example.net. IN NSEC wzz.example.net. A NSEC RRSIG +wab.example.net. 3600 IN RRSIG NSEC 5 3 3600 20070926134150 20070829134150 30899 example.net. gl8vkI3xfSWx4Pyv5OdOthiewE6u/13kclY7UG9ptuFBddamdJO3RQqyxM6Xcmq+ToO4kMCCyaKijp01gTDoGg== ;{id = 30899} +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NXDOMAIN +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME www.example.net. +www.example.com. 3600 IN RRSIG CNAME 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFDwBErFx90ixZDOdIsKz1QaXA1WzAhUAprOUlV1d5fmUiOp7DZ0TWWcM81Q= ;{id = 2854} +SECTION AUTHORITY +u.example.com. IN NSEC z.example.com. NSEC RRSIG +u.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCdc/AWOi3BbYLOClSaw7uVkEf0/AhRJLUUXhuvEsdxEXESjotO3tJZyog== ;{id = 2854} +example.net. IN NSEC abc.example.net. SOA NS DNSKEY NSEC RRSIG +example.net. 3600 IN RRSIG NSEC 5 2 3600 20070926134150 20070829134150 30899 example.net. SEHthmjHyqGlzaOp3Dx6Jn5Fnvvtknw/IF6YSFY8NZLe+YSh1oRJbdEkQ8G92IT08n1jSN6jvKRsFBOUoFOQAw== ;{id = 30899} +wab.example.net. IN NSEC wzz.example.net. A NSEC RRSIG +wab.example.net. 3600 IN RRSIG NSEC 5 3 3600 20070926134150 20070829134150 30899 example.net. gl8vkI3xfSWx4Pyv5OdOthiewE6u/13kclY7UG9ptuFBddamdJO3RQqyxM6Xcmq+ToO4kMCCyaKijp01gTDoGg== ;{id = 30899} +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_cnamewctoposwc.rpl b/testdata/val_cnamewctoposwc.rpl new file mode 100644 index 00000000000..057cd03119f --- /dev/null +++ b/testdata/val_cnamewctoposwc.rpl @@ -0,0 +1,242 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + trust-anchor: "example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with wildcard cname to positive wildcard + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +; *.example.com. IN CNAME www.example.net. +www.example.com. 3600 IN CNAME www.example.net. +www.example.com. 3600 IN RRSIG CNAME 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFCA2HhM4cInPoUZ58o6t9CVlqv+kAhRjxWXvnFecgDxnDphpEVEoc0Ps6Q== ;{id = 2854} +SECTION AUTHORITY +; weird NSEC that denies everything. But validly signed, so valid. +; extreme version of 'white lies' :-) +example.com. IN NSEC example.com. SOA NS A NSEC RRSIG DNSKEY +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCSPaRH721mYjuTGb6fZ+nR3pnVxAIUAxEctE1hzMQSw0CWJSMLHS/A+Xk= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN DNSKEY +SECTION ANSWER +example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.net. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +; from *.example.net. +www.example.net. IN A 11.12.13.14 +www.example.net. 3600 IN RRSIG A 5 2 3600 20070926134150 20070829134150 30899 example.net. quSyDbSeHRvyMmanqq5rW+APC9MKOswbRLB5QP/G+C2iyokQFLuRTlX9Wmo/jo1Oo1MGBefJUmP9NdRd2EqABA== ;{id = 30899} +SECTION AUTHORITY +wab.example.net IN NSEC wzz.example.net. A NSEC RRSIG +wab.example.net. 3600 IN RRSIG NSEC 5 3 3600 20070926134150 20070829134150 30899 example.net. gl8vkI3xfSWx4Pyv5OdOthiewE6u/13kclY7UG9ptuFBddamdJO3RQqyxM6Xcmq+ToO4kMCCyaKijp01gTDoGg== ;{id = 30899} +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME www.example.net. +www.example.com. 3600 IN RRSIG CNAME 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFCA2HhM4cInPoUZ58o6t9CVlqv+kAhRjxWXvnFecgDxnDphpEVEoc0Ps6Q== ;{id = 2854} +www.example.net. IN A 11.12.13.14 +www.example.net. 3600 IN RRSIG A 5 2 3600 20070926134150 20070829134150 30899 example.net. quSyDbSeHRvyMmanqq5rW+APC9MKOswbRLB5QP/G+C2iyokQFLuRTlX9Wmo/jo1Oo1MGBefJUmP9NdRd2EqABA== ;{id = 30899} +SECTION AUTHORITY +example.com. IN NSEC example.com. SOA NS A NSEC RRSIG DNSKEY +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCSPaRH721mYjuTGb6fZ+nR3pnVxAIUAxEctE1hzMQSw0CWJSMLHS/A+Xk= ;{id = 2854} +wab.example.net IN NSEC wzz.example.net. A NSEC RRSIG +wab.example.net. 3600 IN RRSIG NSEC 5 3 3600 20070926134150 20070829134150 30899 example.net. gl8vkI3xfSWx4Pyv5OdOthiewE6u/13kclY7UG9ptuFBddamdJO3RQqyxM6Xcmq+ToO4kMCCyaKijp01gTDoGg== ;{id = 30899} +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_dnametoolong.rpl b/testdata/val_dnametoolong.rpl new file mode 100644 index 00000000000..43b27f1868e --- /dev/null +++ b/testdata/val_dnametoolong.rpl @@ -0,0 +1,255 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + trust-anchor: "example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with a dname too long response + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR YXDOMAIN +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +; length +; www. = 4 +; long1234567890abcdef. = 21 +; long1234567890abcdef.long1234567890abcdef.long1234567890abcdef.long1234567890abcdef.long1234567890abcdef.long1234567890abcdef.long1234567890abcdef.long1234567890abcdef.long1234567890abcdef.long1234567890abcdef.long1234567890abcdef.long1234567890abcdef. = 12 * 21 = 252 +example.com. IN DNAME long1234567890abcdef.long1234567890abcdef.long1234567890abcdef.long1234567890abcdef.long1234567890abcdef.long1234567890abcdef.long1234567890abcdef.long1234567890abcdef.long1234567890abcdef.long1234567890abcdef.long1234567890abcdef.long1234567890abcdef. +example.com. 3600 IN RRSIG DNAME 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFBdWQE6lzktCN4vdAx9HY1zZe6dYAhUAghsHM4lSJAykdvp5p0wppml03K0= ;{id = 2854} +; unsigned CNAME synthesis is too long +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN DNSKEY +SECTION ANSWER +example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.net. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +; from *.example.net. +www.example.net. IN A 11.12.13.14 +www.example.net. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.net. CPxF5hK9Kg5eT7W6LgZwr0ePYEm9HMcSY4vvqCS6gDWB4X9jvXLCfBkCLhsNybPBpGWlsLi5wM6MTdJXuPpsRA== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_dnametopos.rpl b/testdata/val_dnametopos.rpl new file mode 100644 index 00000000000..f564f879d6b --- /dev/null +++ b/testdata/val_dnametopos.rpl @@ -0,0 +1,234 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + trust-anchor: "example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with a dname to positive + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +example.com. IN DNAME example.net. +example.com. 3600 IN RRSIG DNAME 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFH1xw24Hswia3g10AVL1yFUHUPdFAhQDrA+qZJwqXRPg2C1oiNPk9fosGg== ;{id = 2854} +; unsigned CNAME +www.example.com. IN CNAME www.example.net. +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN DNSKEY +SECTION ANSWER +example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.net. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +; from *.example.net. +www.example.net. IN A 11.12.13.14 +www.example.net. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.net. CPxF5hK9Kg5eT7W6LgZwr0ePYEm9HMcSY4vvqCS6gDWB4X9jvXLCfBkCLhsNybPBpGWlsLi5wM6MTdJXuPpsRA== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +example.com. 3600 IN DNAME example.net. +example.com. 3600 IN RRSIG DNAME 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFH1xw24Hswia3g10AVL1yFUHUPdFAhQDrA+qZJwqXRPg2C1oiNPk9fosGg== ;{id = 2854} +www.example.com. 0 IN CNAME www.example.net. +www.example.net. 3600 IN A 11.12.13.14 +www.example.net. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.net. CPxF5hK9Kg5eT7W6LgZwr0ePYEm9HMcSY4vvqCS6gDWB4X9jvXLCfBkCLhsNybPBpGWlsLi5wM6MTdJXuPpsRA== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_dnametoposwc.rpl b/testdata/val_dnametoposwc.rpl new file mode 100644 index 00000000000..6ece5344006 --- /dev/null +++ b/testdata/val_dnametoposwc.rpl @@ -0,0 +1,238 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + trust-anchor: "example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with a dname to positive wildcard + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +example.com. IN DNAME example.net. +example.com. 3600 IN RRSIG DNAME 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFH1xw24Hswia3g10AVL1yFUHUPdFAhQDrA+qZJwqXRPg2C1oiNPk9fosGg== ;{id = 2854} +; unsigned CNAME +www.example.com. IN CNAME www.example.net. +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN DNSKEY +SECTION ANSWER +example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.net. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +; from *.example.net. +www.example.net. IN A 11.12.13.14 +www.example.net. 3600 IN RRSIG A 5 2 3600 20070926134150 20070829134150 30899 example.net. quSyDbSeHRvyMmanqq5rW+APC9MKOswbRLB5QP/G+C2iyokQFLuRTlX9Wmo/jo1Oo1MGBefJUmP9NdRd2EqABA== ;{id = 30899} +SECTION AUTHORITY +wab.example.net IN NSEC wzz.example.net. A NSEC RRSIG +wab.example.net. 3600 IN RRSIG NSEC 5 3 3600 20070926134150 20070829134150 30899 example.net. gl8vkI3xfSWx4Pyv5OdOthiewE6u/13kclY7UG9ptuFBddamdJO3RQqyxM6Xcmq+ToO4kMCCyaKijp01gTDoGg== ;{id = 30899} +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +example.com. 3600 IN DNAME example.net. +example.com. 3600 IN RRSIG DNAME 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFH1xw24Hswia3g10AVL1yFUHUPdFAhQDrA+qZJwqXRPg2C1oiNPk9fosGg== ;{id = 2854} +www.example.com. 0 IN CNAME www.example.net. +www.example.net. 3600 IN A 11.12.13.14 +www.example.net. 3600 IN RRSIG A 5 2 3600 20070926134150 20070829134150 30899 example.net. quSyDbSeHRvyMmanqq5rW+APC9MKOswbRLB5QP/G+C2iyokQFLuRTlX9Wmo/jo1Oo1MGBefJUmP9NdRd2EqABA== ;{id = 30899} +SECTION AUTHORITY +wab.example.net IN NSEC wzz.example.net. A NSEC RRSIG +wab.example.net. 3600 IN RRSIG NSEC 5 3 3600 20070926134150 20070829134150 30899 example.net. gl8vkI3xfSWx4Pyv5OdOthiewE6u/13kclY7UG9ptuFBddamdJO3RQqyxM6Xcmq+ToO4kMCCyaKijp01gTDoGg== ;{id = 30899} +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_dnamewc.rpl b/testdata/val_dnamewc.rpl new file mode 100644 index 00000000000..3c02768a0d1 --- /dev/null +++ b/testdata/val_dnamewc.rpl @@ -0,0 +1,265 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + trust-anchor: "example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with a wildcarded dname + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN AAAA +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN A +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +; *.example.com. IN DNAME example.net. +sub.example.com. IN DNAME example.net. +sub.example.com. 3600 IN RRSIG DNAME 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFEyO+NY3QgAf/cF0mmZhsj3TqgoGAhRqJhHoCd+aA1FbBp16WGfk1HmeIg== ;{id = 2854} +; unsigned CNAME; one interpretation of the wildcarded DNAME expansion +www.sub.example.com. IN CNAME www.example.net. +SECTION AUTHORITY +; prove original does not exist +ns.example.com. IN NSEC www.example.com. A RRSIG NSEC +ns.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCCqvDUT+jMCvfm7OHL2IDY75JDmQIUfOtDiiyeSiwjuq3i3OuLnVRyoJ8= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.net. IN AAAA +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.net. IN A +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN DNSKEY +SECTION ANSWER +example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.net. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +; from *.example.net. +www.example.net. IN A 11.12.13.14 +www.example.net. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.net. CPxF5hK9Kg5eT7W6LgZwr0ePYEm9HMcSY4vvqCS6gDWB4X9jvXLCfBkCLhsNybPBpGWlsLi5wM6MTdJXuPpsRA== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_ds_afterprime.rpl b/testdata/val_ds_afterprime.rpl new file mode 100644 index 00000000000..258f1c936c8 --- /dev/null +++ b/testdata/val_ds_afterprime.rpl @@ -0,0 +1,177 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test DS lookup after key prime is done. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DS +SECTION AUTHORITY +com. 900 IN SOA a.gtld-servers.net. nstld.verisign-grs.com. 1251367385 1800 900 604800 86400 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +ENTRY_END + +STEP 20 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +example.com. IN DS +ENTRY_END + +STEP 30 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +example.com. IN DS +SECTION AUTHORITY +com. 900 IN SOA a.gtld-servers.net. nstld.verisign-grs.com. 1251367385 1800 900 604800 86400 +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_ds_cname.rpl b/testdata/val_ds_cname.rpl new file mode 100644 index 00000000000..1c9fb775136 --- /dev/null +++ b/testdata/val_ds_cname.rpl @@ -0,0 +1,202 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with CNAME response to DS + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +; not legal NOERROR/NODATA response, but leniently accepted (not validated) +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +; nothing here, not even NSECs +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +; DS query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN DS +SECTION ANSWER +www.example.com. IN CNAME zzz.example.com. +www.example.com. 3600 IN RRSIG CNAME 3 2 3600 20070926134150 20070829134150 2854 example.com. AERsv3PiBObAEhZ/dKyamie0sjvYLn7YaEKgv9ExB14KKLgWvzCaOWo= ;{id = 2854} +;*.example.com. IN CNAME zzz.example.com. +;*.example.com. 3600 IN RRSIG CNAME 3 2 3600 20070926134150 20070829134150 2854 example.com. AERsv3PiBObAEhZ/dKyamie0sjvYLn7YaEKgv9ExB14KKLgWvzCaOWo= ;{id = 2854} + +SECTION AUTHORITY +*.example.com. IN NSEC zzz.example.com. CNAME RRSIG NSEC +*.example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. AJxl2TXciyhbKqSakVNtjlt8Bbkco02zpl5RlY88iqVmSa6ts+/guU4= ;{id = 2854} +zzz.example.com. IN NSEC *.zzz.example.com. A RRSIG NSEC +zzz.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. ACtgx/h0YfGEK79zg4G16jB/0oRWH0nxrMzUc/4hCY3oprsP8DrdjqU= ;{id = 2854} +example.com. IN SOA alfa.ns.example.com.cz. hostmaster.example.com. 2010030800 10800 86400 604800 86400 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. ADsxLOHjxFzwFmwIiGOubqD9nKWAp4RccRIXQ0+EAUGfSDZMCB0ZiFA= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +zzz.example.com. IN DS +SECTION ANSWER +SECTION AUTHORITY +zzz.example.com. IN NSEC *.zzz.example.com. A RRSIG NSEC +zzz.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. ACtgx/h0YfGEK79zg4G16jB/0oRWH0nxrMzUc/4hCY3oprsP8DrdjqU= ;{id = 2854} +example.com. IN SOA alfa.ns.example.com.cz. hostmaster.example.com. 2010030800 10800 86400 604800 86400 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. ADsxLOHjxFzwFmwIiGOubqD9nKWAp4RccRIXQ0+EAUGfSDZMCB0ZiFA= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_ds_gost.crpl b/testdata/val_ds_gost.crpl new file mode 100644 index 00000000000..11601e1f2e6 --- /dev/null +++ b/testdata/val_ds_gost.crpl @@ -0,0 +1,206 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with GOST DS digest + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. + +; GOST DS for sub.example.com. +sub.example.com. 3600 IN DS 60385 12 3 2be04f63b3d069fd65f81a3b810b661a00d39be3ff00d1c7481a150b93b0d027 ; xepov-bofek-fuset-bipiz-tunoz-mukyf-rybyb-ranic-pobet-fakov-fozob-bagus-ludac-pyheb-rygor-bygyd-lyxyx + +; SHA DS for sub.example.com. +;sub.example.com. 3600 IN DS 60385 12 1 0a66f7923318bb1e208bfd975ffa2e30cfcdf962 ; xedik-katin-dasec-myvic-vumum-rizan-luluz-paraf-befas-tovek-dyxax +;sub.example.com. 3600 IN DS 60385 12 2 cd3290b84b457d02ca29846a005a5eba61640256ced8deca0ef8345d2cd34a58 ; xufef-dugir-modog-hyzyb-dadod-nicuk-pubyh-polor-pomuk-gobuh-kufet-mulus-pofyz-metoh-tarit-fudih-moxex + +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926135752 20070829135752 2854 example.com. ADwjiGkzrz8RPRJ6LAB37cNEQxTXSaR6Stu/GwGvcQ7KVGH/Qw76ktI= ;{id = 2854} + +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 12 3 3600 20070926134150 20070829134150 60385 sub.example.com. LAgerMKnwGgapo7tDs2jV8kjA+RminByvkR6qHineRDv4SYbRdDlCtYcFR4CoYo9aigLPej1WBmaZjFV+/7AVA== ;{id = 60385} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 12 4 3600 20070926134150 20070829134150 60385 sub.example.com. qYVQEwiVNWwRRoDJxK3c3LaXtfvOm/YzOEzXbN2MxPHZXHaa2nCzWLsILNstot/wTAbrk4wNcT16gKxF5JguNw== ;{id = 60385} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 12 9SZY+xB3wKtrLoRHzkBs9L3fjcvazjnk5HF3gMaD1PVp4pthrwgHIm0TUaLrd3YCa2VCl5wj+MzbhZi8NEJ/Cg== ;{id = 60385 (zsk), size = 512b} +sub.example.com. 3600 IN RRSIG DNSKEY 12 3 3600 20070926134150 20070829134150 60385 sub.example.com. zyZCppfMjlMS9xs3pJfbWkdA6EgV5MqI11AdVRV8pBsyI7diYLWm8RAHlhEI5MT59A6IT6Di9YjOCvWJjzZ9tA== ;{id = 60385} +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 12 3 3600 20070926134150 20070829134150 60385 sub.example.com. 3y6qmOn5GIytQQtXmdhkyL0+8Um7uNzOA0m0CkWFtzN81T98jHdGcCGNC3CIGMyhKaWKqPlOoSwIfm55fa4qRA== ;{id = 60385} + +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 12 4 3600 20070926134150 20070829134150 60385 sub.example.com. VS97UxG9Kn7DIYFCnBDJQ3n7sQ+aYF42/cU6s8jF1Y4nHSorKPFa0KHn0WVmaW33hA+Vs4BWTvJ1/JOpbiJskA== ;{id = 60385} + +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 12 4 3600 20070926134150 20070829134150 60385 sub.example.com. KVDpNBH83UM8l1e9yAdXA1fV+wFJSJF4NtOnDLTtbpfyVbndNW3tvPc2YfLBxTEZeUCns2QrqcmIMdZ086frOQ== ;{id = 60385} + +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. 3600 IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 12 4 3600 20070926134150 20070829134150 60385 sub.example.com. KVDpNBH83UM8l1e9yAdXA1fV+wFJSJF4NtOnDLTtbpfyVbndNW3tvPc2YfLBxTEZeUCns2QrqcmIMdZ086frOQ== ;{id = 60385} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_ds_gost_downgrade.crpl b/testdata/val_ds_gost_downgrade.crpl new file mode 100644 index 00000000000..00e6e4e3b50 --- /dev/null +++ b/testdata/val_ds_gost_downgrade.crpl @@ -0,0 +1,244 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with GOST DS digest downgrade attack + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN AAAA +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. + +; downgrade: false GOST, correct SHA + + +sub.example.com. 3600 IN DS 60385 12 3 2be04f63b3d069fd65f81a3b810b661a00d39be3ff00d1c7481a150b93b0d028 + +; correct GOST DS for sub.example.com. +; sub.example.com. 3600 IN DS 60385 12 3 2be04f63b3d069fd65f81a3b810b661a00d39be3ff00d1c7481a150b93b0d027 ; xepov-bofek-fuset-bipiz-tunoz-mukyf-rybyb-ranic-pobet-fakov-fozob-bagus-ludac-pyheb-rygor-bygyd-lyxyx + +; SHA1 DS for sub.example.com. +sub.example.com. 3600 IN DS 60385 12 1 0a66f7923318bb1e208bfd975ffa2e30cfcdf962 ; xedik-katin-dasec-myvic-vumum-rizan-luluz-paraf-befas-tovek-dyxax +; SHA256 DS for sub.example.com. +sub.example.com. 3600 IN DS 60385 12 2 cd3290b84b457d02ca29846a005a5eba61640256ced8deca0ef8345d2cd34a58 ; xufef-dugir-modog-hyzyb-dadod-nicuk-pubyh-polor-pomuk-gobuh-kufet-mulus-pofyz-metoh-tarit-fudih-moxex + +; signs SHA1, SHA2 and GOST DSes +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926135752 20070829135752 2854 example.com. ADB1PPtGoPKRrhNtRtkqeqpgnZdbPOdJMgjdZVxPfgGCoMTu3JFQVbo= ;{id = 2854} + +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 12 3 3600 20070926134150 20070829134150 60385 sub.example.com. 6mNrX32/DC2RU1A+yWCccn5H6wnsbNYTlf8e/LyF1fsuNfw6tH12sKGBCtk1mp4HpDIgH02HDHplJskSFOvzTw== ;{id = 60385} + +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 12 4 3600 20070926134150 20070829134150 60385 sub.example.com. kJEyinL7BkpiPW2HxmFHRLAi68EdrLXToJiK83a5cedDe5ABL7c/k+nFHd3WjATUtVoueY3pSnCDVCJaFmd+/A== ;{id = 60385} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.sub.example.com. IN A +SECTION ANSWER +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 12 4 3600 20070926134150 20070829134150 60385 sub.example.com. kJEyinL7BkpiPW2HxmFHRLAi68EdrLXToJiK83a5cedDe5ABL7c/k+nFHd3WjATUtVoueY3pSnCDVCJaFmd+/A== ;{id = 60385} +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 12 3 3600 20070926134150 20070829134150 60385 sub.example.com. 6mNrX32/DC2RU1A+yWCccn5H6wnsbNYTlf8e/LyF1fsuNfw6tH12sKGBCtk1mp4HpDIgH02HDHplJskSFOvzTw== ;{id = 60385} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 12 9SZY+xB3wKtrLoRHzkBs9L3fjcvazjnk5HF3gMaD1PVp4pthrwgHIm0TUaLrd3YCa2VCl5wj+MzbhZi8NEJ/Cg== ;{id = 60385 (zsk), size = 512b} +sub.example.com. 3600 IN RRSIG DNSKEY 12 3 3600 20070926134150 20070829134150 60385 sub.example.com. zyZCppfMjlMS9xs3pJfbWkdA6EgV5MqI11AdVRV8pBsyI7diYLWm8RAHlhEI5MT59A6IT6Di9YjOCvWJjzZ9tA== ;{id = 60385} +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 12 3 3600 20070926134150 20070829134150 60385 sub.example.com. 6mNrX32/DC2RU1A+yWCccn5H6wnsbNYTlf8e/LyF1fsuNfw6tH12sKGBCtk1mp4HpDIgH02HDHplJskSFOvzTw== ;{id = 60385} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 12 4 3600 20070926134150 20070829134150 60385 sub.example.com. kJEyinL7BkpiPW2HxmFHRLAi68EdrLXToJiK83a5cedDe5ABL7c/k+nFHd3WjATUtVoueY3pSnCDVCJaFmd+/A== ;{id = 60385} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 12 4 3600 20070926134150 20070829134150 60385 sub.example.com. KVDpNBH83UM8l1e9yAdXA1fV+wFJSJF4NtOnDLTtbpfyVbndNW3tvPc2YfLBxTEZeUCns2QrqcmIMdZ086frOQ== ;{id = 60385} + +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.sub.example.com. IN AAAA +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +; must servfail bogus +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +;www.sub.example.com. 3600 IN A 11.11.11.11 +;www.sub.example.com. 3600 IN RRSIG A 12 4 3600 20070926134150 20070829134150 60385 sub.example.com. KVDpNBH83UM8l1e9yAdXA1fV+wFJSJF4NtOnDLTtbpfyVbndNW3tvPc2YfLBxTEZeUCns2QrqcmIMdZ086frOQ== ;{id = 60385} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_ds_sha2.crpl b/testdata/val_ds_sha2.crpl new file mode 100644 index 00000000000..111382d22c4 --- /dev/null +++ b/testdata/val_ds_sha2.crpl @@ -0,0 +1,201 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with SHA256 DS digest + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. + +; SHA256 DS for sub.example.com. +sub.example.com. 3600 IN DS 30899 5 2 51be8e847cc663f2775d0f2b6d15e41553c97ecb99b8dd667f18244e2f652033 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926135752 20070829135752 2854 example.com. AJ6FL7yKjrpEEO8WMKlG7TVZoGjgFblJeu0rkJCmJxfdeh6ysUlWQWs= ;{id = 2854} + +; SHA1 DS for sub.example.com. +;sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response to DNSKEY priming query +; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899} +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. 3600 IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_ds_sha2_downgrade.crpl b/testdata/val_ds_sha2_downgrade.crpl new file mode 100644 index 00000000000..2418c87fd6a --- /dev/null +++ b/testdata/val_ds_sha2_downgrade.crpl @@ -0,0 +1,224 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with SHA256 DS downgrade to SHA1 + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. + +; Downgrade attack: false SHA2, correct SHA1 + +; SHA256 DS for sub.example.com. +;sub.example.com. 3600 IN DS 30899 5 2 51be8e847cc663f2775d0f2b6d15e41553c97ecb99b8dd667f18244e2f652033 +; BAD SHA256 DS +sub.example.com. 3600 IN DS 30899 5 2 51be8e847cc663f2775d0f2b6d15e41553c97ecb99b8dd667f18244e2f652000 + +; SHA1 DS for sub.example.com. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926135752 20070829135752 2854 example.com. ACqqpk1ow07XJvN1orEpiWOeqMLdDKQtTgWB8Mp6CF/9VTfHuWWmsu8= ;{id = 2854} + +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response to DNSKEY priming query +; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899} +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.sub.example.com. IN A +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.sub.example.com. IN AAAA +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +; must servfail, BOGUS +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +;www.sub.example.com. 3600 IN A 11.11.11.11 +;www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_dsnsec.rpl b/testdata/val_dsnsec.rpl new file mode 100644 index 00000000000..32702034fdf --- /dev/null +++ b/testdata/val_dsnsec.rpl @@ -0,0 +1,285 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test pickup of DS NSEC from the cache. +; make sure unbound does not pick up the wrong nsec. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; barely valid nodata for AAAA +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response for tub.example.com +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NXDOMAIN +SECTION QUESTION +tub.example.com. IN DNSKEY +SECTION ANSWER +SECTION AUTHORITY +; SOA record +example.com IN SOA ns.iana.org. NSTLD.iana.org. 2009061200 1800 900 604800 86400 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AAvpEruGS0UJzMoO6ou/+y8ZyHjjrFC6HKDWU8a61Ru9qtl4R66fC1c= ;{id = 2854} +; qname denial +sub.example.com. IN NSEC wub.example.com. NS DS RRSIG NSEC +sub.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. AA4+SSCI8kQZ2/iGj+9rxpNZyaIJNNRZ4eM0fEw2D5fVR/+WLUZ9GdE= ;{id = 2854} +; wildcard denial +example.com. IN NSEC blub.example.com. NS SOA RRSIG NSEC DNSKEY +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. AARheDFiRjrnKHzsPloUJ0FC+8aAM6H49Lnm2AJrgxE9RlBlH2E4sRo= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +; DS query for sub.example.com +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION ANSWER +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +;sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +;sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response to DNSKEY priming query +; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899} +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +; query for a domain next to it, so the wrong NSEC gets in the cache. +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.tub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NXDOMAIN +SECTION QUESTION +www.tub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. 3600 IN SOA ns.iana.org. NSTLD.iana.org. 2009061200 1800 900 604800 86400 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AAvpEruGS0UJzMoO6ou/+y8ZyHjjrFC6HKDWU8a61Ru9qtl4R66fC1c= ;{id = 2854} +sub.example.com. 3600 IN NSEC wub.example.com. NS DS RRSIG NSEC +sub.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. AA4+SSCI8kQZ2/iGj+9rxpNZyaIJNNRZ4eM0fEw2D5fVR/+WLUZ9GdE= ;{id = 2854} +example.com. 3600 IN NSEC blub.example.com. NS SOA RRSIG NSEC DNSKEY +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. AARheDFiRjrnKHzsPloUJ0FC+8aAM6H49Lnm2AJrgxE9RlBlH2E4sRo= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +; query of interest. +STEP 30 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +STEP 40 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. 3600 IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + + +SCENARIO_END diff --git a/testdata/val_entds.rpl b/testdata/val_entds.rpl new file mode 100644 index 00000000000..6235baadcd5 --- /dev/null +++ b/testdata/val_entds.rpl @@ -0,0 +1,275 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with lots of ENTs in the chain of trust +; query is for a.1.2.b.3.4.c.5.6.example.com. +; labels 1-6 are empty nonterminals. +; there are DNSKEYs at labels b, c, example.com. +; and DSes at b and c. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response for ENT DS queries. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +6.example.com. IN DS +SECTION AUTHORITY +example.com. NSEC c.5.6.example.com. SOA DNSKEY NS RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCoocKDsR+Hius4e+5zJPlXeeWNowIUO+pa14FBcWH/dCNK5R0vRrlWY5s= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +5.6.example.com. IN DS +SECTION AUTHORITY +example.com. NSEC c.5.6.example.com. SOA DNSKEY NS RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCoocKDsR+Hius4e+5zJPlXeeWNowIUO+pa14FBcWH/dCNK5R0vRrlWY5s= ;{id = 2854} +ENTRY_END + +; response for query in question - delegation +; and all other queries, receive a delegation to c.5.6.example.com. +ENTRY_BEGIN +MATCH opcode +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +a.1.2.b.3.4.c.5.6.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +c.5.6.example.com. IN NS ns.c.5.6.example.com. +c.5.6.example.com. 3600 IN DS 2854 3 1 4449f16fa7d712283aa43cc8dcc8e07c05856e08 +c.5.6.example.com. 3600 IN RRSIG DS 3 5 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCgiF7eFL89mSqjUPEpQuL5QEa1OgIUWdfUmMkwVBwOgmxlxZIKfGs5od0= ;{id = 2854} +SECTION ADDITIONAL +ns.c.5.6.example.com. IN A 1.2.3.6 +ENTRY_END +RANGE_END + +; ns.c.5.6.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +c.5.6.example.com. IN NS +SECTION ANSWER +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +c.5.6.example.com. IN DNSKEY +SECTION ANSWER +c.5.6.example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +c.5.6.example.com. 3600 IN RRSIG DNSKEY 3 5 3600 20070926134150 20070829134150 2854 c.5.6.example.com. MC0CFHsYd4tGO5BotXFzG9d8fzHkX576AhUAoZ2d1FNUBsrwxl6XSz/hoxme/4Q= ;{id = 2854} +ENTRY_END + +; response to DS queries. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +4.c.5.6.example.com. IN DS +SECTION AUTHORITY +3.c.5.6.example.com. IN NSEC b.3.4.c.5.6.example.com. NS DS RRSIG NSEC +3.c.5.6.example.com. 3600 IN RRSIG NSEC 3 6 3600 20070926134150 20070829134150 2854 c.5.6.example.com. MCwCFFFF5WwGibkPunDt0BW2W9lncACcAhQuFh7FbfCE1ulJqBFf1YxjvT/WHQ== ;{id = 2854} + +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY AA QR NOERROR +SECTION QUESTION +3.4.c.5.6.example.com. IN DS +SECTION AUTHORITY +3.c.5.6.example.com. IN NSEC b.3.4.c.5.6.example.com. NS DS RRSIG NSEC +3.c.5.6.example.com. 3600 IN RRSIG NSEC 3 6 3600 20070926134150 20070829134150 2854 c.5.6.example.com. MCwCFFFF5WwGibkPunDt0BW2W9lncACcAhQuFh7FbfCE1ulJqBFf1YxjvT/WHQ== ;{id = 2854} +ENTRY_END + +; any other query gets a referral +ENTRY_BEGIN +MATCH opcode +ADJUST copy_id copy_query +REPLY AA QR NOERROR +SECTION QUESTION +4.c.5.6.example.com. IN DS +SECTION AUTHORITY +b.3.4.c.5.6.example.com. IN NS ns.b.3.4.c.5.6.example.com. +b.3.4.c.5.6.example.com. 3600 IN DS 30899 5 1 849ebbdefa338db3e6c3ddffd58851523ba701de +b.3.4.c.5.6.example.com. 3600 IN RRSIG DS 3 8 3600 20070926134150 20070829134150 2854 c.5.6.example.com. MC0CFEuXbvClpAOx7E1SXeH0d+Q4jpySAhUAtbEbQ8qtRF5chUOWNtg31ESAjWg= ;{id = 2854} +SECTION ADDITIONAL +ns.b.3.4.c.5.6.example.com. IN A 1.2.3.7 +ENTRY_END +RANGE_END + +; ns.b.3.4.c.5.6.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.7 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +b.3.4.c.5.6.example.com. IN NS +SECTION ANSWER +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +b.3.4.c.5.6.example.com. IN DNSKEY +SECTION ANSWER +b.3.4.c.5.6.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +b.3.4.c.5.6.example.com. 3600 IN RRSIG DNSKEY 5 8 3600 20070926134150 20070829134150 30899 b.3.4.c.5.6.example.com. KNftlGVkrfvo3l3Wliq+i695MqJI9B8QnTVhCHKhFPZfEq0HCxV8gO3ZlaTUle1YEnr7+yXUritXlzjFOlf1hw== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +a.1.2.b.3.4.c.5.6.example.com. IN A +SECTION ANSWER +a.1.2.b.3.4.c.5.6.example.com. IN A 11.11.11.11 +a.1.2.b.3.4.c.5.6.example.com. 3600 IN RRSIG A 5 11 3600 20070926134150 20070829134150 30899 b.3.4.c.5.6.example.com. GUZcUHhxAvc6FYwAzVJcTqsjz5L36bGA45dyeSupEGEhhUJj0wm/FaYCAlO8J+H2zcFEqbgK0KzHdrFmNHkgUQ== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +a.1.2.b.3.4.c.5.6.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +a.1.2.b.3.4.c.5.6.example.com. IN A +SECTION ANSWER +a.1.2.b.3.4.c.5.6.example.com. 3600 IN A 11.11.11.11 +a.1.2.b.3.4.c.5.6.example.com. 3600 IN RRSIG A 5 11 3600 20070926134150 20070829134150 30899 b.3.4.c.5.6.example.com. GUZcUHhxAvc6FYwAzVJcTqsjz5L36bGA45dyeSupEGEhhUJj0wm/FaYCAlO8J+H2zcFEqbgK0KzHdrFmNHkgUQ== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_faildnskey.rpl b/testdata/val_faildnskey.rpl new file mode 100644 index 00000000000..1d154591fe0 --- /dev/null +++ b/testdata/val_faildnskey.rpl @@ -0,0 +1,168 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + # test that default value of harden-dnssec-stripped is still yes. + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with failed DNSKEY request + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +;REPLY QR AA NOERROR +REPLY QR AA SERVFAIL +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +;example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +;example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +;SECTION AUTHORITY +;example.com. IN NS ns.example.com. +;example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +;SECTION ADDITIONAL +;ns.example.com. IN A 1.2.3.4 +;ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_faildnskey_ok.rpl b/testdata/val_faildnskey_ok.rpl new file mode 100644 index 00000000000..5bd6db261d7 --- /dev/null +++ b/testdata/val_faildnskey_ok.rpl @@ -0,0 +1,177 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + harden-dnssec-stripped: no + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with failed DNSKEY request, but not hardened. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +ENTRY_END + + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +;REPLY QR AA NOERROR +REPLY QR AA SERVFAIL +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +;example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +;example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +;SECTION AUTHORITY +;example.com. IN NS ns.example.com. +;example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +;SECTION ADDITIONAL +;ns.example.com. IN A 1.2.3.4 +;ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_fwdds.rpl b/testdata/val_fwdds.rpl new file mode 100644 index 00000000000..3fdd333463d --- /dev/null +++ b/testdata/val_fwdds.rpl @@ -0,0 +1,457 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +forward-zone: + name: "sub.example.com" + forward-addr: 1.2.3.6 +CONFIG_END + +SCENARIO_BEGIN Test forward-zone with DS query +; The fwd zone is linked validly with a DS to the public internet zone. +; unbound just has to be able to ask the DS from the right server (not +; from the fwd). +; Here the fwd is not even recursive, just the plain server for sub.example.com + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response for DS of sub.example.com. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION ANSWER +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response to DNSKEY priming query +; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899} +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response for qtype DS. This is not available here. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR SERVFAIL +SECTION QUESTION +sub.example.com. IN DS +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. 3600 IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +stub-zone: + name: "sub.example.com" + stub-addr: 1.2.3.6 +CONFIG_END + +SCENARIO_BEGIN Test stub with DS query +; The stub zone is linked validly with a DS to the public internet zone. +; unbound just has to be able to ask the DS from the right server (not +; from the stub). + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response for DS of sub.example.com. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION ANSWER +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response to DNSKEY priming query +; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899} +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response for qtype DS. This is not available here. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR SERVFAIL +SECTION QUESTION +sub.example.com. IN DS +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. 3600 IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_keyprefetch.rpl b/testdata/val_keyprefetch.rpl new file mode 100644 index 00000000000..9e9b13f38f3 --- /dev/null +++ b/testdata/val_keyprefetch.rpl @@ -0,0 +1,212 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + prefetch-key: yes + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with key prefetch + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response to DNSKEY priming query +; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899} +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. 3600 IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_keyprefetch_verify.rpl b/testdata/val_keyprefetch_verify.rpl new file mode 100644 index 00000000000..567b6395d7a --- /dev/null +++ b/testdata/val_keyprefetch_verify.rpl @@ -0,0 +1,245 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + prefetch-key: yes + prefetch: yes + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with key prefetch and verify with the anchor + + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response to DNSKEY priming query +; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899} +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. 3600 IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +STEP 20 TIME_PASSES ELAPSE 3400 + +; now the key gets prefetched and has to be verified with the anchor, +; not with the key itself. +; this answer is from cache enyway. +STEP 30 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +sub.example.com. IN DNSKEY +ENTRY_END + +STEP 40 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899} +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +STEP 50 TRAFFIC + +SCENARIO_END diff --git a/testdata/val_mal_wc.rpl b/testdata/val_mal_wc.rpl new file mode 100644 index 00000000000..ba0c6c951d5 --- /dev/null +++ b/testdata/val_mal_wc.rpl @@ -0,0 +1,149 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with nodata, wildcards and ENT + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +b.example.com. IN DS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +b.example.com. IN DS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +b.example.com. IN DS +SECTION ANSWER +SECTION AUTHORITY +example.com. 86394 IN SOA NS.IANA.ORG. NSTLD.IANA.ORG. 2007092000 1800 900 604800 86400 +example.com. 86394 IN RRSIG SOA 3 2 86394 20070926135752 20070829135752 2854 example.com. MCwCFFHjDbVjiPywHcXm669wMUJ7dlcoAhRfuauTUoExMSx96lTVYbBHOXtQEw== ;{id = 2854} + +; note that b.example.com. is an empty nonterminal +*.example.com. 3600 IN NSEC *.b.example.com. A MX RRSIG NSEC +*.example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926135752 20070829135752 2854 example.com. MCwCFE9CopvxP6w/1HqnqxNluh1Qbgk0AhRgKrdjk/YoEm4tcYflNX6McDMCgQ== ;{id = 2854} + +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +b.example.com. IN DS +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +b.example.com. IN DS +SECTION ANSWER +SECTION AUTHORITY +example.com. 86394 IN SOA NS.IANA.ORG. NSTLD.IANA.ORG. 2007092000 1800 900 604800 86400 +example.com. 86394 IN RRSIG SOA 3 2 86394 20070926135752 20070829135752 2854 example.com. MCwCFFHjDbVjiPywHcXm669wMUJ7dlcoAhRfuauTUoExMSx96lTVYbBHOXtQEw== ;{id = 2854} +*.example.com. 3600 IN NSEC *.b.example.com. A MX RRSIG NSEC +*.example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926135752 20070829135752 2854 example.com. MCwCFE9CopvxP6w/1HqnqxNluh1Qbgk0AhRgKrdjk/YoEm4tcYflNX6McDMCgQ== ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_negcache_ds.rpl b/testdata/val_negcache_ds.rpl new file mode 100644 index 00000000000..a589eefbc29 --- /dev/null +++ b/testdata/val_negcache_ds.rpl @@ -0,0 +1,213 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with negative cache DS response + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. IN NSEC www.example.com. NS RRSIG NSEC +sub.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFDCaiDM6G+glwNW276HWdH+McmjgAhRSwF5OfimNQCqkWgnYotLOwUghKQ== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +; query for missing DS record. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA ns.example.com. h.example.com. 2007090504 1800 1800 2419200 7200 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFC5uwIHSehZtetK2CMNXttSFUB0XAhROFDAgy/FaxR8zFXJzyPdpQG93Sw== ;{id = 2854} +sub.example.com. IN NSEC www.example.com. NS RRSIG NSEC +sub.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFDCaiDM6G+glwNW276HWdH+McmjgAhRSwF5OfimNQCqkWgnYotLOwUghKQ== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + + +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 11.11.11.11 +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. 3600 IN A 11.11.11.11 +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +; the downstream validator wants the DS record. +STEP 20 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +sub.example.com. IN DS +ENTRY_END + +STEP 30 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA ns.example.com. h.example.com. 2007090504 1800 1800 2419200 7200 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFC5uwIHSehZtetK2CMNXttSFUB0XAhROFDAgy/FaxR8zFXJzyPdpQG93Sw== ;{id = 2854} +sub.example.com. IN NSEC www.example.com. NS RRSIG NSEC +sub.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFDCaiDM6G+glwNW276HWdH+McmjgAhRSwF5OfimNQCqkWgnYotLOwUghKQ== ;{id = 2854} +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_negcache_dssoa.rpl b/testdata/val_negcache_dssoa.rpl new file mode 100644 index 00000000000..7040af8302a --- /dev/null +++ b/testdata/val_negcache_dssoa.rpl @@ -0,0 +1,253 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with negative cache DS response with cached SOA + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. IN NSEC www.example.com. NS RRSIG NSEC +sub.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFDCaiDM6G+glwNW276HWdH+McmjgAhRSwF5OfimNQCqkWgnYotLOwUghKQ== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +; query for missing DS record. +; commented out, this query should not happen as negative cache works. +;ENTRY_BEGIN +;MATCH opcode qtype qname +;ADJUST copy_id +;REPLY QR NOERROR +;SECTION QUESTION +;sub.example.com. IN DS +;SECTION ANSWER +;SECTION AUTHORITY +;example.com. IN SOA ns.example.com. h.example.com. 2007090504 1800 1800 2419200 7200 +;example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFC5uwIHSehZtetK2CMNXttSFUB0XAhROFDAgy/FaxR8zFXJzyPdpQG93Sw== ;{id = 2854} +;sub.example.com. IN NSEC www.example.com. NS RRSIG NSEC +;sub.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFDCaiDM6G+glwNW276HWdH+McmjgAhRSwF5OfimNQCqkWgnYotLOwUghKQ== ;{id = 2854} +;SECTION ADDITIONAL +;ns.sub.example.com. IN A 1.2.3.6 +;ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NXDOMAIN +SECTION QUESTION +nx.example.com. IN A +SECTION AUTHORITY +example.com. 7200 IN SOA ns.example.com. h.example.com. 2007090504 1800 1800 2419200 7200 +example.com. 7200 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFC5uwIHSehZtetK2CMNXttSFUB0XAhROFDAgy/FaxR8zFXJzyPdpQG93Sw== ;{id = 2854} +nw.example.com. 7200 IN NSEC ny.example.com. A RRSIG +nw.example.com. 7200 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. AHMp+sqWyR3JL6P0LhJ10fufMFSkW9+DM3QghOokyqgbRu54Q1XrHoE= ;{id = 2854} +!.example.com. 7200 IN NSEC +.example.com. A RRSIG +!.example.com. 7200 IN RRSIG NSEC 3 3 7200 20070926134150 20070829134150 2854 example.com. AJsNy2VkFTJEMShfEcvIkBe+UViVYDJbNNuGnwf/QecOrhONaVpIXy4= ;{id = 2854} +ENTRY_END + +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 11.11.11.11 +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. 3600 IN A 11.11.11.11 +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +; put the SOA into the cache +STEP 14 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +nx.example.com. IN A +ENTRY_END + +STEP 15 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NXDOMAIN +SECTION QUESTION +nx.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. 7200 IN SOA ns.example.com. h.example.com. 2007090504 1800 1800 2419200 7200 +example.com. 7200 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFC5uwIHSehZtetK2CMNXttSFUB0XAhROFDAgy/FaxR8zFXJzyPdpQG93Sw== ;{id = 2854} +nw.example.com. 7200 IN NSEC ny.example.com. A RRSIG +nw.example.com. 7200 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. AHMp+sqWyR3JL6P0LhJ10fufMFSkW9+DM3QghOokyqgbRu54Q1XrHoE= ;{id = 2854} +!.example.com. 7200 IN NSEC +.example.com. A RRSIG +!.example.com. 7200 IN RRSIG NSEC 3 3 7200 20070926134150 20070829134150 2854 example.com. AJsNy2VkFTJEMShfEcvIkBe+UViVYDJbNNuGnwf/QecOrhONaVpIXy4= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +; the downstream validator wants the DS record. +STEP 20 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +sub.example.com. IN DS +ENTRY_END + +STEP 30 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NSEC www.example.com. NS RRSIG NSEC +sub.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFDCaiDM6G+glwNW276HWdH+McmjgAhRSwF5OfimNQCqkWgnYotLOwUghKQ== ;{id = 2854} +example.com. 7200 IN SOA ns.example.com. h.example.com. 2007090504 1800 1800 2419200 7200 +example.com. 7200 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFC5uwIHSehZtetK2CMNXttSFUB0XAhROFDAgy/FaxR8zFXJzyPdpQG93Sw== ;{id = 2854} +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_noadwhennodo.rpl b/testdata/val_noadwhennodo.rpl new file mode 100644 index 00000000000..13015dbdbd6 --- /dev/null +++ b/testdata/val_noadwhennodo.rpl @@ -0,0 +1,149 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test if AD bit is returned on non-DO query. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +; it is validated, but no AD bit, because no AD was requested. +; (this is a copy of val_positive.rpl). +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nodata.rpl b/testdata/val_nodata.rpl new file mode 100644 index 00000000000..8fc8d51eed0 --- /dev/null +++ b/testdata/val_nodata.rpl @@ -0,0 +1,147 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with nodata response + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +; SOA record is missing in reply. +; Denies A, note this is the end of the NSEC chain. +www.example.com. IN NSEC example.com. RRSIG NSEC +www.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCreYgWjFPE/E47n+KUp6vAPIfS4gIUaof1QcUQeIcsxVi1/M73CuHVwEc= ;{id = 2854} +; Denies wildcard +;example.com. IN NSEC ns.example.com. NS SOA RRSIG NSEC DNSKEY +;example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926135752 20070829135752 2854 example.com. MCwCFGlz/gvGdVxEo3Kpr+MijEGCZgwaAhRU7qbF13vmCVgR8dFw7LQFKopV6w== ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +www.example.com. IN NSEC example.com. RRSIG NSEC +www.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCreYgWjFPE/E47n+KUp6vAPIfS4gIUaof1QcUQeIcsxVi1/M73CuHVwEc= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nodata_ent.rpl b/testdata/val_nodata_ent.rpl new file mode 100644 index 00000000000..4eaace1d805 --- /dev/null +++ b/testdata/val_nodata_ent.rpl @@ -0,0 +1,153 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with nodata on empty nonterminal response + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA ns.example.com. h.example.com. 2007090504 1800 1800 2419200 7200 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFC5uwIHSehZtetK2CMNXttSFUB0XAhROFDAgy/FaxR8zFXJzyPdpQG93Sw== ;{id = 2854} +; Denies A, note this is the end of the NSEC chain. +u.example.com. IN NSEC y.www.example.com. RRSIG NSEC +u.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCvUG2P/8Q8b02C6agrgtJX4YfBbwIUaF/fIuS4OFmGVNkFzgiLAkpze3M= ;{id = 2854} + +; Denies wildcard +example.com. IN NSEC ns.example.com. NS SOA RRSIG NSEC DNSKEY +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926135752 20070829135752 2854 example.com. MCwCFGlz/gvGdVxEo3Kpr+MijEGCZgwaAhRU7qbF13vmCVgR8dFw7LQFKopV6w== ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA ns.example.com. h.example.com. 2007090504 1800 1800 2419200 7200 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFC5uwIHSehZtetK2CMNXttSFUB0XAhROFDAgy/FaxR8zFXJzyPdpQG93Sw== ;{id = 2854} +u.example.com. IN NSEC y.www.example.com. RRSIG NSEC +u.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCvUG2P/8Q8b02C6agrgtJX4YfBbwIUaF/fIuS4OFmGVNkFzgiLAkpze3M= ;{id = 2854} +example.com. IN NSEC ns.example.com. NS SOA RRSIG NSEC DNSKEY +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926135752 20070829135752 2854 example.com. MCwCFGlz/gvGdVxEo3Kpr+MijEGCZgwaAhRU7qbF13vmCVgR8dFw7LQFKopV6w== ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nodata_entwc.rpl b/testdata/val_nodata_entwc.rpl new file mode 100644 index 00000000000..0bbc2a9e8ed --- /dev/null +++ b/testdata/val_nodata_entwc.rpl @@ -0,0 +1,153 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with wildcard nodata on empty nonterminal response + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA ns.example.com. h.example.com. 2007090504 1800 1800 2419200 7200 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFC5uwIHSehZtetK2CMNXttSFUB0XAhROFDAgy/FaxR8zFXJzyPdpQG93Sw== ;{id = 2854} +; Denies A, note this is the end of the NSEC chain. +*.u.example.com. IN NSEC y.www.example.com. RRSIG NSEC +*.u.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFEiVqFPbtbpIh8NrE/YjNCDPFYZgAhR9/9SDX2lwxckJZR299JcRRsjnqw== ;{id = 2854} + +; Denies wildcard +example.com. IN NSEC ns.example.com. NS SOA RRSIG NSEC DNSKEY +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926135752 20070829135752 2854 example.com. MCwCFGlz/gvGdVxEo3Kpr+MijEGCZgwaAhRU7qbF13vmCVgR8dFw7LQFKopV6w== ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA ns.example.com. h.example.com. 2007090504 1800 1800 2419200 7200 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFC5uwIHSehZtetK2CMNXttSFUB0XAhROFDAgy/FaxR8zFXJzyPdpQG93Sw== ;{id = 2854} +*.u.example.com. IN NSEC y.www.example.com. RRSIG NSEC +*.u.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFEiVqFPbtbpIh8NrE/YjNCDPFYZgAhR9/9SDX2lwxckJZR299JcRRsjnqw== ;{id = 2854} +example.com. IN NSEC ns.example.com. NS SOA RRSIG NSEC DNSKEY +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926135752 20070829135752 2854 example.com. MCwCFGlz/gvGdVxEo3Kpr+MijEGCZgwaAhRU7qbF13vmCVgR8dFw7LQFKopV6w== ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nodata_failsig.rpl b/testdata/val_nodata_failsig.rpl new file mode 100644 index 00000000000..9cd8289c727 --- /dev/null +++ b/testdata/val_nodata_failsig.rpl @@ -0,0 +1,161 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with nodata response with bogus RRSIG + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN A +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN AAAA +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +; SOA record is missing in reply. +; Denies A, note this is the end of the NSEC chain. +www.example.com. IN NSEC example.com. RRSIG NSEC +www.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFDA8yqBITvLruoQjn/eqjYjwCwySAhUAk5/f3H1HKMsvM+spmmswwFtndyY= ;{id = 2854} +; Denies wildcard +example.com. IN NSEC ns.example.com. NS SOA RRSIG NSEC DNSKEY +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926135752 20070829135752 2854 example.com. MCwCFGlz/gvGdVxEo3Kpr+MijEGCZgwaAhRU7qbF13vmCVgR8dFw7LQFKopV6w== ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nodata_hasdata.rpl b/testdata/val_nodata_hasdata.rpl new file mode 100644 index 00000000000..f5321182a5e --- /dev/null +++ b/testdata/val_nodata_hasdata.rpl @@ -0,0 +1,161 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with nodata response, that proves the data. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN A +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN AAAA +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +; SOA record is missing in reply. +; Denies A, note this is the end of the NSEC chain. +www.example.com. IN NSEC example.com. A RRSIG NSEC +www.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFDA8yqBITvLruoQjn/eqjYjwCwySAhUAk5/f3H1HKMsvM+spmmswwFtndyY= ;{id = 2854} +; Denies wildcard +example.com. IN NSEC ns.example.com. NS SOA RRSIG NSEC DNSKEY +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926135752 20070829135752 2854 example.com. MCwCFGlz/gvGdVxEo3Kpr+MijEGCZgwaAhRU7qbF13vmCVgR8dFw7LQFKopV6w== ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nodata_zonecut.rpl b/testdata/val_nodata_zonecut.rpl new file mode 100644 index 00000000000..e9e50a7ce60 --- /dev/null +++ b/testdata/val_nodata_zonecut.rpl @@ -0,0 +1,159 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with nodata response from wrong side of zonecut + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN A +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN AAAA +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +; SOA record is missing in reply. +; Denies A, note this is the end of the NSEC chain. +; from wrong side of zone-cut +www.example.com. 3600 IN NSEC example.com. NS DS RRSIG NSEC +www.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926135752 20070829135752 2854 example.com. AA+3mzAYPyQ8G9EKxeyNM+UZY+RtCiS5BOkS8h4wSxMT3lfVdadGpn8= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nodatawc.rpl b/testdata/val_nodatawc.rpl new file mode 100644 index 00000000000..dc4971f6fc7 --- /dev/null +++ b/testdata/val_nodatawc.rpl @@ -0,0 +1,149 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with wildcard nodata response + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +; SOA record is missing in reply. +; wildcard, Denies A, note this is the end of the NSEC chain. +*.example.com. IN NSEC example.com. RRSIG NSEC +*.example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926135752 20070829135752 2854 example.com. MC0CFEwIBOyCychIo8y/JnBLLrhQdejHAhUAtKBLVPEvhF2haaX/RNUGLji1Xw0= ;{id = 2854} +; this NSEC denies original query name +ns.example.com. IN NSEC zork.example.com. A RRSIG NSEC +ns.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCfm3mQakqw9pd8SluduiMXYYc+/wIULqIBxw1bK8QEwCrd8E6T50P4BEw= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +*.example.com. IN NSEC example.com. RRSIG NSEC +*.example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926135752 20070829135752 2854 example.com. MC0CFEwIBOyCychIo8y/JnBLLrhQdejHAhUAtKBLVPEvhF2haaX/RNUGLji1Xw0= ;{id = 2854} +ns.example.com. IN NSEC zork.example.com. A RRSIG NSEC +ns.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCfm3mQakqw9pd8SluduiMXYYc+/wIULqIBxw1bK8QEwCrd8E6T50P4BEw= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nodatawc_badce.rpl b/testdata/val_nodatawc_badce.rpl new file mode 100644 index 00000000000..dcf8697db0c --- /dev/null +++ b/testdata/val_nodatawc_badce.rpl @@ -0,0 +1,161 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with wildcard nodata, bad closest encloser + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN A +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN AAAA +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +; SOA record is missing in reply. +; wildcard is *.com, +*.com. IN NSEC com. RRSIG NSEC +*.com. 3600 IN RRSIG NSEC 3 1 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCdZKVAPYKe6WhoeuK4+J2hd3F2DgIUXv9Dif1uZsSjboLYVx7Wp0DEg78= ;{id = 2854} +; this NSEC denies original query name from a different zone +ns.example.com. IN NSEC zork.example.com. A RRSIG NSEC +ns.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCfm3mQakqw9pd8SluduiMXYYc+/wIULqIBxw1bK8QEwCrd8E6T50P4BEw= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nodatawc_nodeny.rpl b/testdata/val_nodatawc_nodeny.rpl new file mode 100644 index 00000000000..52dcb0f7842 --- /dev/null +++ b/testdata/val_nodatawc_nodeny.rpl @@ -0,0 +1,161 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with wildcard nodata response without qdenial + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN A +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN AAAA +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +; SOA record is missing in reply. +; wildcard, Denies A, note this is the end of the NSEC chain. +*.example.com. IN NSEC ns.example.com. RRSIG NSEC +*.example.com. IN RRSIG NSEC 3 2 3600 20070926135752 20070829135752 2854 example.com. MCwCFG0+PaReanKYupgDsJMHBBl7qaAOAhRApLLtiHNSl326iqVz/icLUJ6+Kg== ;{id = 2854} +; this NSEC denies original query name +;ns.example.com. IN NSEC zork.example.com. A RRSIG NSEC +;ns.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCfm3mQakqw9pd8SluduiMXYYc+/wIULqIBxw1bK8QEwCrd8E6T50P4BEw= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nodatawc_one.rpl b/testdata/val_nodatawc_one.rpl new file mode 100644 index 00000000000..375be171b30 --- /dev/null +++ b/testdata/val_nodatawc_one.rpl @@ -0,0 +1,144 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with wildcard nodata response with one NSEC + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +; SOA record is missing in reply. +; wildcard, Denies A, note this is the end of the NSEC chain. +*.example.com. IN NSEC example.com. RRSIG NSEC +*.example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926135752 20070829135752 2854 example.com. MC0CFEwIBOyCychIo8y/JnBLLrhQdejHAhUAtKBLVPEvhF2haaX/RNUGLji1Xw0= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +*.example.com. IN NSEC example.com. RRSIG NSEC +*.example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926135752 20070829135752 2854 example.com. MC0CFEwIBOyCychIo8y/JnBLLrhQdejHAhUAtKBLVPEvhF2haaX/RNUGLji1Xw0= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nokeyprime.rpl b/testdata/val_nokeyprime.rpl new file mode 100644 index 00000000000..c30396af938 --- /dev/null +++ b/testdata/val_nokeyprime.rpl @@ -0,0 +1,161 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with failed key prime, no keys. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +ENTRY_END + +; barely valid nodata for AAAA +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +ENTRY_END + + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA ns.example.com. hostmaster.example.com. 2007101500 28800 7200 604800 18000 +SECTION ADDITIONAL +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nsec3_b1_nameerror.rpl b/testdata/val_nsec3_b1_nameerror.rpl new file mode 100644 index 00000000000..b7c300cca0e --- /dev/null +++ b/testdata/val_nsec3_b1_nameerror.rpl @@ -0,0 +1,131 @@ +; config options +server: + trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )" + val-override-date: "20120420235959" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator NSEC3 B.1 name error. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +. IN A +SECTION AUTHORITY +example. IN NS ns1.example. +; leave out to make unbound take ns1 +;example. IN NS ns2.example. +SECTION ADDITIONAL +ns1.example. IN A 192.0.2.1 +; leave out to make unbound take ns1 +;ns2.example. IN A 192.0.2.2 +ENTRY_END +RANGE_END + +; ns1.example. +RANGE_BEGIN 0 100 + ADDRESS 192.0.2.1 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +example. IN NS +SECTION ANSWER +ENTRY_END + +; response to DNSKEY priming query + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example. IN DNSKEY +SECTION ANSWER +example. DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU ( sAD0QPWU+wzt89epO6tHzkMBVDkC7qphQO2h TY4hHn9npWFRw5BYubE= ) +example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= ) +example. RRSIG DNSKEY 7 1 3600 20150420235959 ( 20051021000000 12708 example. AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31 uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm MGQZf3bH+QsCtg== ) +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA DO NXDOMAIN +SECTION QUESTION +a.c.x.w.example. IN A +SECTION AUTHORITY +example. SOA ns1.example. bugs.x.w.example. 1 3600 300 ( 3600000 3600 ) +example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 ( 40430 example. Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd VI2LmKusbZsT0Q== ) + +;; NSEC3 RR that covers the "next closer" name (c.x.w.example) +;; H(c.x.w.example) = 0va5bpr2ou0vk0lbqeeljri88laipsfh + +0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd ( 2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG ) +0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. OSgWSm26B+cS+dDL8b5QrWr/dEWhtCsKlwKL IBHYH6blRxK9rC0bMJPwQ4mLIuw85H2EY762 BOCXJZMnpuwhpA== ) + +;; NSEC3 RR that matches the closest encloser (x.w.example) +;; H(x.w.example) = b4um86eghhds6nea196smvmlo4ors995 + +b4um86eghhds6nea196smvmlo4ors995.example. NSEC3 1 1 12 aabbccdd ( gjeqe526plbf1g8mklp59enfd789njgi MX RRSIG ) +b4um86eghhds6nea196smvmlo4ors995.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. ZkPG3M32lmoHM6pa3D6gZFGB/rhL//Bs3Omh 5u4m/CUiwtblEVOaAKKZd7S959OeiX43aLX3 pOv0TSTyiTxIZg== ) + +;; NSEC3 RR that covers wildcard at the closest encloser (*.x.w.example) +;; H(*.x.w.example) = 92pqneegtaue7pjatc3l3qnk738c6v5m + +35mthgpgcu1qg68fab165klnsnk3dpvl.example. NSEC3 1 1 12 aabbccdd ( b4um86eghhds6nea196smvmlo4ors995 NS DS RRSIG ) +35mthgpgcu1qg68fab165klnsnk3dpvl.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. g6jPUUpduAJKRljUsN8gB4UagAX0NxY9shwQ Aynzo8EUWH+z6hEIBlUTPGj15eZll6VhQqgZ XtAIR3chwgW+SA== ) +SECTION ADDITIONAL +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +a.c.x.w.example. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NXDOMAIN +SECTION QUESTION +a.c.x.w.example. IN A +SECTION ANSWER +SECTION AUTHORITY +example. SOA ns1.example. bugs.x.w.example. 1 3600 300 ( 3600000 3600 ) +example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 ( 40430 example. Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd VI2LmKusbZsT0Q== ) +0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd ( 2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG ) +0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. OSgWSm26B+cS+dDL8b5QrWr/dEWhtCsKlwKL IBHYH6blRxK9rC0bMJPwQ4mLIuw85H2EY762 BOCXJZMnpuwhpA== ) +b4um86eghhds6nea196smvmlo4ors995.example. NSEC3 1 1 12 aabbccdd ( gjeqe526plbf1g8mklp59enfd789njgi MX RRSIG ) +b4um86eghhds6nea196smvmlo4ors995.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. ZkPG3M32lmoHM6pa3D6gZFGB/rhL//Bs3Omh 5u4m/CUiwtblEVOaAKKZd7S959OeiX43aLX3 pOv0TSTyiTxIZg== ) +35mthgpgcu1qg68fab165klnsnk3dpvl.example. NSEC3 1 1 12 aabbccdd ( b4um86eghhds6nea196smvmlo4ors995 NS DS RRSIG ) +35mthgpgcu1qg68fab165klnsnk3dpvl.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. g6jPUUpduAJKRljUsN8gB4UagAX0NxY9shwQ Aynzo8EUWH+z6hEIBlUTPGj15eZll6VhQqgZ XtAIR3chwgW+SA== ) +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nsec3_b1_nameerror_noce.rpl b/testdata/val_nsec3_b1_nameerror_noce.rpl new file mode 100644 index 00000000000..6dca24cc50e --- /dev/null +++ b/testdata/val_nsec3_b1_nameerror_noce.rpl @@ -0,0 +1,141 @@ +; config options +server: + trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )" + val-override-date: "20120420235959" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator NSEC3 B.1 name error without ce NSEC3. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example. IN A +SECTION AUTHORITY +example. IN NS ns1.example. +; leave out to make unbound take ns1 +;example. IN NS ns2.example. +SECTION ADDITIONAL +ns1.example. IN A 192.0.2.1 +; leave out to make unbound take ns1 +;ns2.example. IN A 192.0.2.2 +ENTRY_END +RANGE_END + +; ns1.example. +RANGE_BEGIN 0 100 + ADDRESS 192.0.2.1 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +ns1.example. IN A +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +ns1.example. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +example. IN NS +SECTION ANSWER +ENTRY_END + +; response to DNSKEY priming query + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example. IN DNSKEY +SECTION ANSWER +example. DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU ( sAD0QPWU+wzt89epO6tHzkMBVDkC7qphQO2h TY4hHn9npWFRw5BYubE= ) +example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= ) +example. RRSIG DNSKEY 7 1 3600 20150420235959 ( 20051021000000 12708 example. AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31 uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm MGQZf3bH+QsCtg== ) +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA DO NXDOMAIN +SECTION QUESTION +a.c.x.w.example. IN A +SECTION AUTHORITY +example. SOA ns1.example. bugs.x.w.example. 1 3600 300 ( 3600000 3600 ) +example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 ( 40430 example. Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd VI2LmKusbZsT0Q== ) + +;; NSEC3 RR that covers the "next closer" name (c.x.w.example) +;; H(c.x.w.example) = 0va5bpr2ou0vk0lbqeeljri88laipsfh + +0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd ( 2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG ) +0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. OSgWSm26B+cS+dDL8b5QrWr/dEWhtCsKlwKL IBHYH6blRxK9rC0bMJPwQ4mLIuw85H2EY762 BOCXJZMnpuwhpA== ) + +;; NSEC3 RR that matches the closest encloser (x.w.example) +;; H(x.w.example) = b4um86eghhds6nea196smvmlo4ors995 + +; b4um86eghhds6nea196smvmlo4ors995.example. NSEC3 1 1 12 aabbccdd ( gjeqe526plbf1g8mklp59enfd789njgi MX RRSIG ) +; b4um86eghhds6nea196smvmlo4ors995.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. ZkPG3M32lmoHM6pa3D6gZFGB/rhL//Bs3Omh 5u4m/CUiwtblEVOaAKKZd7S959OeiX43aLX3 pOv0TSTyiTxIZg== ) + +;; NSEC3 RR that covers wildcard at the closest encloser (*.x.w.example) +;; H(*.x.w.example) = 92pqneegtaue7pjatc3l3qnk738c6v5m + +35mthgpgcu1qg68fab165klnsnk3dpvl.example. NSEC3 1 1 12 aabbccdd ( b4um86eghhds6nea196smvmlo4ors995 NS DS RRSIG ) +35mthgpgcu1qg68fab165klnsnk3dpvl.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. g6jPUUpduAJKRljUsN8gB4UagAX0NxY9shwQ Aynzo8EUWH+z6hEIBlUTPGj15eZll6VhQqgZ XtAIR3chwgW+SA== ) +SECTION ADDITIONAL +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +a.c.x.w.example. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +a.c.x.w.example. IN A +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nsec3_b1_nameerror_nonc.rpl b/testdata/val_nsec3_b1_nameerror_nonc.rpl new file mode 100644 index 00000000000..b9d32d32e0d --- /dev/null +++ b/testdata/val_nsec3_b1_nameerror_nonc.rpl @@ -0,0 +1,143 @@ +; config options +server: + trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm 3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )" + val-override-date: "20120420235959" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator NSEC3 B.1 name error without nc NSEC3. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example. IN A +SECTION AUTHORITY +example. IN NS ns1.example. +; leave out to make unbound take ns1 +;example. IN NS ns2.example. +SECTION ADDITIONAL +ns1.example. IN A 192.0.2.1 +; leave out to make unbound take ns1 +;ns2.example. IN A 192.0.2.2 +ENTRY_END +RANGE_END + +; ns1.example. +RANGE_BEGIN 0 100 + ADDRESS 192.0.2.1 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +ns1.example. IN A +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +ns1.example. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +example. IN NS +SECTION ANSWER +ENTRY_END + +; response to DNSKEY priming query + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example. IN DNSKEY +SECTION ANSWER +example. DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU ( sAD0QPWU+wzt89ep O6tHzkMBVDkC7qphQO2h TY4hHn9npWFRw5BYubE= ) +example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8 Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= ) +example. RRSIG DNSKEY 7 1 3600 20150420235959 ( 20051021000000 12708 example. AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31 uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm MGQZf 3bH+QsCtg== ) + +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA DO NXDOMAIN +SECTION QUESTION +a.c.x.w.example. IN A +SECTION AUTHORITY +example. SOA ns1.example. bugs.x.w.example. 1 3600 300 ( 3600000 3600 ) +example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 ( 40430 example. Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd V I2LmKusbZsT0Q== ) + +;; NSEC3 RR that covers the "next closer" name (c.x.w.example) +;; H(c.x.w.example) = 0va5bpr2ou0vk0lbqeeljri88laipsfh + +;0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd ( 2t7b4g4vsa5smi 47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG ) +;0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. OSgWSm26B+cS+dDL8b5QrWr/dEWhtCsKlwKL IBHYH6blRx K9rC0bMJPwQ4mLIuw85H2EY762 BOCXJZMnpuwhpA== ) + +;; NSEC3 RR that matches the closest encloser (x.w.example) +;; H(x.w.example) = b4um86eghhds6nea196smvmlo4ors995 + +b4um86eghhds6nea196smvmlo4ors995.example. NSEC3 1 1 12 aabbccdd ( gjeqe526plbf1g8mklp59enfd789njgi MX RRSIG ) +b4um86eghhds6nea196smvmlo4ors995.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. ZkPG3M32lmoHM6pa3D6gZFGB/rhL//Bs3Omh 5u4m/CUi wtblEVOaAKKZd7S959OeiX43aLX3 pOv0TSTyiTxIZg== ) + +;; NSEC3 RR that covers wildcard at the closest encloser (*.x.w.example) +;; H(*.x.w.example) = 92pqneegtaue7pjatc3l3qnk738c6v5m + +35mthgpgcu1qg68fab165klnsnk3dpvl.example. NSEC3 1 1 12 aabbccdd ( b4um86eghhds6nea196smvmlo4ors995 NS DS RRSIG ) +35mthgpgcu1qg68fab165klnsnk3dpvl.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. g6jPUUpduAJKRljUsN8gB4UagAX0NxY9shwQ Aynzo8EUWH +z6hEIBlUTPGj15eZll6VhQqgZ XtAIR3chwgW+SA== ) + +SECTION ADDITIONAL +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +a.c.x.w.example. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +a.c.x.w.example. IN A +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nsec3_b1_nameerror_nowc.rpl b/testdata/val_nsec3_b1_nameerror_nowc.rpl new file mode 100644 index 00000000000..bf4d223216a --- /dev/null +++ b/testdata/val_nsec3_b1_nameerror_nowc.rpl @@ -0,0 +1,148 @@ +; config options +server: + trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )" + val-override-date: "20120420235959" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator NSEC3 B.1 name error without wc NSEC3. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example. IN A +SECTION AUTHORITY +example. IN NS ns1.example. +; leave out to make unbound take ns1 +;example. IN NS ns2.example. +SECTION ADDITIONAL +ns1.example. IN A 192.0.2.1 +; leave out to make unbound take ns1 +;ns2.example. IN A 192.0.2.2 +ENTRY_END +RANGE_END + +; ns1.example. +RANGE_BEGIN 0 100 + ADDRESS 192.0.2.1 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +ns1.example. IN A +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +ns1.example. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +example. IN NS +SECTION ANSWER +ENTRY_END + +; response to DNSKEY priming query + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example. IN DNSKEY +SECTION ANSWER +example. DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU ( sAD0QPWU+wzt89epO6tHzkMBVDkC7qphQO2h TY4hHn9npWFRw5BYubE= ) +example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= ) +example. RRSIG DNSKEY 7 1 3600 20150420235959 ( 20051021000000 12708 example. AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31 uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm MGQZf3bH+QsCtg== ) +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA DO NXDOMAIN +SECTION QUESTION +a.c.x.w.example. IN A +SECTION AUTHORITY +example. SOA ns1.example. bugs.x.w.example. 1 3600 300 ( 3600000 3600 ) +example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 ( 40430 example. Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd VI2LmKusbZsT0Q== ) + +;; NSEC3 RR that covers the "next closer" name (c.x.w.example) +;; H(c.x.w.example) = 0va5bpr2ou0vk0lbqeeljri88laipsfh + +0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd ( 2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG ) +0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. OSgWSm26B+cS+dDL8b5QrWr/dEWhtCsKlwKL IBHYH6blRxK9rC0bMJPwQ4mLIuw85H2EY762 BOCXJZMnpuwhpA== ) + +;; NSEC3 RR that matches the closest encloser (x.w.example) +;; H(x.w.example) = b4um86eghhds6nea196smvmlo4ors995 + +b4um86eghhds6nea196smvmlo4ors995.example. NSEC3 1 1 12 aabbccdd ( gjeqe526plbf1g8mklp59enfd789njgi MX RRSIG ) +b4um86eghhds6nea196smvmlo4ors995.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. ZkPG3M32lmoHM6pa3D6gZFGB/rhL//Bs3Omh 5u4m/CUiwtblEVOaAKKZd7S959OeiX43aLX3 pOv0TSTyiTxIZg== ) + +;; NSEC3 RR that covers wildcard at the closest encloser (*.x.w.example) +;; H(*.x.w.example) = 92pqneegtaue7pjatc3l3qnk738c6v5m + + +;35mthgpgcu1qg68fab165klnsnk3dpvl.example. NSEC3 1 1 12 aabbccdd ( b4um86eghhds6nea196smvmlo4ors995 NS DS RRSIG ) +;35mthgpgcu1qg68fab165klnsnk3dpvl.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. g6jPUUpduAJKRljUsN8gB4UagAX0NxY9shwQ Aynzo8EUWH+z6hEIBlUTPGj15eZll6VhQqgZ XtAIR3chwgW+SA== ) +SECTION ADDITIONAL +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +a.c.x.w.example. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +a.c.x.w.example. IN A +SECTION ANSWER +SECTION AUTHORITY +; example. SOA ns1.example. bugs.x.w.example. 1 3600 300 ( 3600000 3600 ) +; example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 ( 40430 example. Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd VI2LmKusbZsT0Q== ) +; 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd ( 2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG ) +; 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. OSgWSm26B+cS+dDL8b5QrWr/dEWhtCsKlwKL IBHYH6blRxK9rC0bMJPwQ4mLIuw85H2EY762 BOCXJZMnpuwhpA== ) +; b4um86eghhds6nea196smvmlo4ors995.example. NSEC3 1 1 12 aabbccdd ( gjeqe526plbf1g8mklp59enfd789njgi MX RRSIG ) +; b4um86eghhds6nea196smvmlo4ors995.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. ZkPG3M32lmoHM6pa3D6gZFGB/rhL//Bs3Omh 5u4m/CUiwtblEVOaAKKZd7S959OeiX43aLX3 pOv0TSTyiTxIZg== ) +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nsec3_b21_nodataent.rpl b/testdata/val_nsec3_b21_nodataent.rpl new file mode 100644 index 00000000000..f384792b2c0 --- /dev/null +++ b/testdata/val_nsec3_b21_nodataent.rpl @@ -0,0 +1,114 @@ +; config options +server: + trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )" + val-override-date: "20120420235959" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator NSEC3 B.2.1 no data empty nonterminal. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +. IN A +SECTION AUTHORITY +example. IN NS ns1.example. +; leave out to make unbound take ns1 +;example. IN NS ns2.example. +SECTION ADDITIONAL +ns1.example. IN A 192.0.2.1 +; leave out to make unbound take ns1 +;ns2.example. IN A 192.0.2.2 +ENTRY_END +RANGE_END + +; ns1.example. +RANGE_BEGIN 0 100 + ADDRESS 192.0.2.1 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +example. IN NS +SECTION ANSWER +ENTRY_END + +; response to DNSKEY priming query + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example. IN DNSKEY +SECTION ANSWER +example. DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU ( sAD0QPWU+wzt89epO6tHzkMBVDkC7qphQO2h TY4hHn9npWFRw5BYubE= ) +example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= ) +example. RRSIG DNSKEY 7 1 3600 20150420235959 ( 20051021000000 12708 example. AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31 uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm MGQZf3bH+QsCtg== ) +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA DO NOERROR +SECTION QUESTION +y.w.example. IN A +SECTION AUTHORITY +example. SOA ns1.example. bugs.x.w.example. 1 3600 300 ( 3600000 3600 ) +example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 ( 40430 example. Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd VI2LmKusbZsT0Q== ) + +;; NSEC3 RR matches the QNAME and shows that the A type bit is not set. +ji6neoaepv8b5o6k4ev33abha8ht9fgc.example. NSEC3 1 1 12 aabbccdd ( k8udemvp1j2f7eg6jebps17vp3n8i58h ) +ji6neoaepv8b5o6k4ev33abha8ht9fgc.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. gPkFp1s2QDQ6wQzcg1uSebZ61W33rUBDcTj7 2F3kQ490fEdp7k1BUIfbcZtPbX3YCpE+sIt0 MpzVSKfTwx4uYA== ) + +SECTION ADDITIONAL +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +y.w.example. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +y.w.example. IN A +SECTION ANSWER +SECTION AUTHORITY +example. SOA ns1.example. bugs.x.w.example. 1 3600 300 ( 3600000 3600 ) +example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 ( 40430 example. Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd VI2LmKusbZsT0Q== ) +ji6neoaepv8b5o6k4ev33abha8ht9fgc.example. NSEC3 1 1 12 aabbccdd ( k8udemvp1j2f7eg6jebps17vp3n8i58h ) +ji6neoaepv8b5o6k4ev33abha8ht9fgc.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. gPkFp1s2QDQ6wQzcg1uSebZ61W33rUBDcTj7 2F3kQ490fEdp7k1BUIfbcZtPbX3YCpE+sIt0 MpzVSKfTwx4uYA== ) +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nsec3_b21_nodataent_wr.rpl b/testdata/val_nsec3_b21_nodataent_wr.rpl new file mode 100644 index 00000000000..6c2f44ef574 --- /dev/null +++ b/testdata/val_nsec3_b21_nodataent_wr.rpl @@ -0,0 +1,132 @@ +; config options +server: + trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )" + val-override-date: "20120420235959" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator NSEC3 B.2.1 no data empty nonterminal, wrong rr. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example. IN A +SECTION AUTHORITY +example. IN NS ns1.example. +; leave out to make unbound take ns1 +;example. IN NS ns2.example. +SECTION ADDITIONAL +ns1.example. IN A 192.0.2.1 +; leave out to make unbound take ns1 +;ns2.example. IN A 192.0.2.2 +ENTRY_END +RANGE_END + +; ns1.example. +RANGE_BEGIN 0 100 + ADDRESS 192.0.2.1 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +ns1.example. IN A +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +ns1.example. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +example. IN NS +SECTION ANSWER +ENTRY_END + +; response to DNSKEY priming query + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example. IN DNSKEY +SECTION ANSWER +example. DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU ( sAD0QPWU+wzt89epO6tHzkMBVDkC7qphQO2h TY4hHn9npWFRw5BYubE= ) +example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= ) +example. RRSIG DNSKEY 7 1 3600 20150420235959 ( 20051021000000 12708 example. AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31 uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm MGQZf3bH+QsCtg== ) +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA DO NOERROR +SECTION QUESTION +y.w.example. IN A +SECTION AUTHORITY +example. SOA ns1.example. bugs.x.w.example. 1 3600 300 ( 3600000 3600 ) +example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 ( 40430 example. Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd VI2LmKusbZsT0Q== ) + +;; NSEC3 RR matches the QNAME and shows that the A type bit is not set. +;ji6neoaepv8b5o6k4ev33abha8ht9fgc.example. NSEC3 1 1 12 aabbccdd ( k8udemvp1j2f7eg6jebps17vp3n8i58h ) +;ji6neoaepv8b5o6k4ev33abha8ht9fgc.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. gPkFp1s2QDQ6wQzcg1uSebZ61W33rUBDcTj7 2F3kQ490fEdp7k1BUIfbcZtPbX3YCpE+sIt0 MpzVSKfTwx4uYA== ) + +; instead the wrong NSEC3 rr is included +35mthgpgcu1qg68fab165klnsnk3dpvl.example. NSEC3 1 1 12 aabbccdd ( b4um86eghhds6nea196smvmlo4ors995 NS DS RRSIG ) +35mthgpgcu1qg68fab165klnsnk3dpvl.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. g6jPUUpduAJKRljUsN8gB4UagAX0NxY9shwQ Aynzo8EUWH+z6hEIBlUTPGj15eZll6VhQqgZ XtAIR3chwgW+SA== ) + +SECTION ADDITIONAL +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +y.w.example. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +y.w.example. IN A +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nsec3_b2_nodata.rpl b/testdata/val_nsec3_b2_nodata.rpl new file mode 100644 index 00000000000..0700ab67aea --- /dev/null +++ b/testdata/val_nsec3_b2_nodata.rpl @@ -0,0 +1,114 @@ +; config options +server: + trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )" + val-override-date: "20120420235959" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator NSEC3 B.2 no data. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +. IN A +SECTION AUTHORITY +example. IN NS ns1.example. +; leave out to make unbound take ns1 +;example. IN NS ns2.example. +SECTION ADDITIONAL +ns1.example. IN A 192.0.2.1 +; leave out to make unbound take ns1 +;ns2.example. IN A 192.0.2.2 +ENTRY_END +RANGE_END + +; ns1.example. +RANGE_BEGIN 0 100 + ADDRESS 192.0.2.1 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +example. IN NS +SECTION ANSWER +ENTRY_END + +; response to DNSKEY priming query + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example. IN DNSKEY +SECTION ANSWER +example. DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU ( sAD0QPWU+wzt89epO6tHzkMBVDkC7qphQO2h TY4hHn9npWFRw5BYubE= ) +example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= ) +example. RRSIG DNSKEY 7 1 3600 20150420235959 ( 20051021000000 12708 example. AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31 uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm MGQZf3bH+QsCtg== ) +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA DO NOERROR +SECTION QUESTION +ns1.example. IN MX +SECTION AUTHORITY +example. SOA ns1.example. bugs.x.w.example. 1 3600 300 ( 3600000 3600 ) +example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 ( 40430 example. Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd VI2LmKusbZsT0Q== ) + +;; NSEC3 RR matches the QNAME and shows that the MX type bit is not set. +2t7b4g4vsa5smi47k61mv5bv1a22bojr.example. NSEC3 1 1 12 aabbccdd ( 2vptu5timamqttgl4luu9kg21e0aor3s A RRSIG ) +2t7b4g4vsa5smi47k61mv5bv1a22bojr.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. OmBvJ1Vgg1hCKMXHFiNeIYHK9XVW0iLDLwJN 4TFoNxZuP03gAXEI634YwOc4YBNITrj413iq NI6mRk/r1dOSUw== ) + +SECTION ADDITIONAL +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +ns1.example. IN MX +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +ns1.example. IN MX +SECTION ANSWER +SECTION AUTHORITY +example. SOA ns1.example. bugs.x.w.example. 1 3600 300 ( 3600000 3600 ) +example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 ( 40430 example. Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd VI2LmKusbZsT0Q== ) +2t7b4g4vsa5smi47k61mv5bv1a22bojr.example. NSEC3 1 1 12 aabbccdd ( 2vptu5timamqttgl4luu9kg21e0aor3s A RRSIG ) +2t7b4g4vsa5smi47k61mv5bv1a22bojr.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. OmBvJ1Vgg1hCKMXHFiNeIYHK9XVW0iLDLwJN 4TFoNxZuP03gAXEI634YwOc4YBNITrj413iq NI6mRk/r1dOSUw== ) +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nsec3_b2_nodata_nons.rpl b/testdata/val_nsec3_b2_nodata_nons.rpl new file mode 100644 index 00000000000..11f1579259e --- /dev/null +++ b/testdata/val_nsec3_b2_nodata_nons.rpl @@ -0,0 +1,137 @@ +; config options +server: + trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )" + val-override-date: "20120420235959" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator NSEC3 B.2 no data, without NSEC3. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example. IN A +SECTION AUTHORITY +example. IN NS ns1.example. +; leave out to make unbound take ns1 +;example. IN NS ns2.example. +SECTION ADDITIONAL +ns1.example. IN A 192.0.2.1 +; leave out to make unbound take ns1 +;ns2.example. IN A 192.0.2.2 +ENTRY_END +RANGE_END + +; ns1.example. +RANGE_BEGIN 0 100 + ADDRESS 192.0.2.1 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +ns1.example. IN A +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +ns1.example. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +example. IN NS +SECTION ANSWER +ENTRY_END + +; response to DNSKEY priming query + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example. IN DNSKEY +SECTION ANSWER +example. DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU ( sAD0QPWU+wzt89epO6tHzkMBVDkC7qphQO2h TY4hHn9npWFRw5BYubE= ) +example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= ) +example. RRSIG DNSKEY 7 1 3600 20150420235959 ( 20051021000000 12708 example. AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31 uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm MGQZf3bH+QsCtg== ) +ENTRY_END + +; response to DS query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA DO NOERROR +SECTION QUESTION +ns1.example. IN DS +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA DO NOERROR +SECTION QUESTION +ns1.example. IN MX +SECTION AUTHORITY +example. SOA ns1.example. bugs.x.w.example. 1 3600 300 ( 3600000 3600 ) +example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 ( 40430 example. Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd VI2LmKusbZsT0Q== ) + +;; NSEC3 RR matches the QNAME and shows that the MX type bit is not set. +;2t7b4g4vsa5smi47k61mv5bv1a22bojr.example. NSEC3 1 1 12 aabbccdd ( 2vptu5timamqttgl4luu9kg21e0aor3s A RRSIG ) +;2t7b4g4vsa5smi47k61mv5bv1a22bojr.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. OmBvJ1Vgg1hCKMXHFiNeIYHK9XVW0iLDLwJN 4TFoNxZuP03gAXEI634YwOc4YBNITrj413iq NI6mRk/r1dOSUw== ) + +SECTION ADDITIONAL +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +ns1.example. IN MX +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +ns1.example. IN MX +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nsec3_b3_optout.rpl b/testdata/val_nsec3_b3_optout.rpl new file mode 100644 index 00000000000..a3a938a692f --- /dev/null +++ b/testdata/val_nsec3_b3_optout.rpl @@ -0,0 +1,211 @@ +; config options +server: + trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )" + val-override-date: "20120420235959" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator NSEC3 B.3 referral to optout unsigned zone. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +. IN A +SECTION AUTHORITY +example. IN NS ns1.example. +; leave out to make unbound take ns1 +;example. IN NS ns2.example. +SECTION ADDITIONAL +ns1.example. IN A 192.0.2.1 +; leave out to make unbound take ns1 +;ns2.example. IN A 192.0.2.2 +ENTRY_END +RANGE_END + +; ns1.example. +RANGE_BEGIN 0 100 + ADDRESS 192.0.2.1 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +example. IN NS +SECTION ANSWER +ENTRY_END + +; response to DNSKEY priming query + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example. IN DNSKEY +SECTION ANSWER +example. DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU ( sAD0QPWU+wzt89epO6tHzkMBVDkC7qphQO2h TY4hHn9npWFRw5BYubE= ) +example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= ) +example. RRSIG DNSKEY 7 1 3600 20150420235959 ( 20051021000000 12708 example. AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31 uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm MGQZf3bH+QsCtg== ) +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA DO NOERROR +SECTION QUESTION +mc.c.example. IN MX +SECTION AUTHORITY +c.example. NS ns1.c.example. +c.example. NS ns2.c.example. + +;; NSEC3 RR that covers the "next closer" name (c.example) +;; H(c.example) = 4g6p9u5gvfshp30pqecj98b3maqbn1ck +35mthgpgcu1qg68fab165klnsnk3dpvl.example. NSEC3 1 1 12 aabbccdd ( b4um86eghhds6nea196smvmlo4ors995 NS DS RRSIG ) +35mthgpgcu1qg68fab165klnsnk3dpvl.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. g6jPUUpduAJKRljUsN8gB4UagAX0NxY9shwQ Aynzo8EUWH+z6hEIBlUTPGj15eZll6VhQqgZ XtAIR3chwgW+SA== ) + +;; NSEC3 RR that matches the closest encloser (example) +;; H(example) = 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom +0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd ( 2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG ) +0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. OSgWSm26B+cS+dDL8b5QrWr/dEWhtCsKlwKL IBHYH6blRxK9rC0bMJPwQ4mLIuw85H2EY762 BOCXJZMnpuwhpA== ) + +SECTION ADDITIONAL +ns1.c.example. A 192.0.2.7 +ns2.c.example. A 192.0.2.8 + +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA DO NOERROR +SECTION QUESTION +c.example. IN DS +SECTION AUTHORITY +;; NSEC3 RR that covers the "next closer" name (c.example) +;; H(c.example) = 4g6p9u5gvfshp30pqecj98b3maqbn1ck +35mthgpgcu1qg68fab165klnsnk3dpvl.example. NSEC3 1 1 12 aabbccdd ( b4um86eghhds6nea196smvmlo4ors995 NS DS RRSIG ) +35mthgpgcu1qg68fab165klnsnk3dpvl.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. g6jPUUpduAJKRljUsN8gB4UagAX0NxY9shwQ Aynzo8EUWH+z6hEIBlUTPGj15eZll6VhQqgZ XtAIR3chwgW+SA== ) + +;; NSEC3 RR that matches the closest encloser (example) +;; H(example) = 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom +0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd ( 2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG ) +0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. OSgWSm26B+cS+dDL8b5QrWr/dEWhtCsKlwKL IBHYH6blRxK9rC0bMJPwQ4mLIuw85H2EY762 BOCXJZMnpuwhpA== ) +ENTRY_END + +RANGE_END + +; ns1.c.example. +RANGE_BEGIN 0 100 + ADDRESS 192.0.2.7 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +c.example. IN NS +SECTION ANSWER +c.example. NS ns1.c.example. +c.example. NS ns2.c.example. +SECTION ADDITIONAL +ns1.c.example. A 192.0.2.7 +ns2.c.example. A 192.0.2.8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +mc.c.example. IN MX +SECTION ANSWER +mc.c.example. IN MX 50 mx.c.example. +SECTION AUTHORITY +c.example. NS ns1.c.example. +c.example. NS ns2.c.example. +SECTION ADDITIONAL +ns1.c.example. A 192.0.2.7 +ns2.c.example. A 192.0.2.8 +ENTRY_END +RANGE_END + +; ns2.c.example. +RANGE_BEGIN 0 100 + ADDRESS 192.0.2.8 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +c.example. IN NS +SECTION ANSWER +c.example. NS ns1.c.example. +c.example. NS ns2.c.example. +SECTION ADDITIONAL +ns1.c.example. A 192.0.2.7 +ns2.c.example. A 192.0.2.8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +mc.c.example. IN MX +SECTION ANSWER +mc.c.example. IN MX 50 mx.c.example. +SECTION AUTHORITY +c.example. NS ns1.c.example. +c.example. NS ns2.c.example. +SECTION ADDITIONAL +ns1.c.example. A 192.0.2.7 +ns2.c.example. A 192.0.2.8 +ENTRY_END +RANGE_END + + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +mc.c.example. IN MX +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +mc.c.example. IN MX +SECTION ANSWER +mc.c.example. IN MX 50 mx.c.example. +SECTION AUTHORITY +c.example. NS ns1.c.example. +c.example. NS ns2.c.example. +SECTION ADDITIONAL +ns1.c.example. A 192.0.2.7 +ns2.c.example. A 192.0.2.8 +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nsec3_b3_optout_negcache.rpl b/testdata/val_nsec3_b3_optout_negcache.rpl new file mode 100644 index 00000000000..b52b3925d67 --- /dev/null +++ b/testdata/val_nsec3_b3_optout_negcache.rpl @@ -0,0 +1,213 @@ +; config options +server: + trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )" + val-override-date: "20120420235959" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator NSEC3 B.3 referral optout with negative cache. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +. IN A +SECTION AUTHORITY +example. IN NS ns1.example. +; leave out to make unbound take ns1 +;example. IN NS ns2.example. +SECTION ADDITIONAL +ns1.example. IN A 192.0.2.1 +; leave out to make unbound take ns1 +;ns2.example. IN A 192.0.2.2 +ENTRY_END +RANGE_END + +; ns1.example. +RANGE_BEGIN 0 100 + ADDRESS 192.0.2.1 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +example. IN NS +SECTION ANSWER +ENTRY_END + +; response to DNSKEY priming query + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example. IN DNSKEY +SECTION ANSWER +example. DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU ( sAD0QPWU+wzt89epO6tHzkMBVDkC7qphQO2h TY4hHn9npWFRw5BYubE= ) +example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= ) +example. RRSIG DNSKEY 7 1 3600 20150420235959 ( 20051021000000 12708 example. AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31 uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm MGQZf3bH+QsCtg== ) +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA DO NOERROR +SECTION QUESTION +mc.c.example. IN MX +SECTION AUTHORITY +c.example. NS ns1.c.example. +c.example. NS ns2.c.example. + +;; NSEC3 RR that covers the "next closer" name (c.example) +;; H(c.example) = 4g6p9u5gvfshp30pqecj98b3maqbn1ck +35mthgpgcu1qg68fab165klnsnk3dpvl.example. NSEC3 1 1 12 aabbccdd ( b4um86eghhds6nea196smvmlo4ors995 NS DS RRSIG ) +35mthgpgcu1qg68fab165klnsnk3dpvl.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. g6jPUUpduAJKRljUsN8gB4UagAX0NxY9shwQ Aynzo8EUWH+z6hEIBlUTPGj15eZll6VhQqgZ XtAIR3chwgW+SA== ) + +;; NSEC3 RR that matches the closest encloser (example) +;; H(example) = 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom +0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd ( 2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG ) +0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. OSgWSm26B+cS+dDL8b5QrWr/dEWhtCsKlwKL IBHYH6blRxK9rC0bMJPwQ4mLIuw85H2EY762 BOCXJZMnpuwhpA== ) + +SECTION ADDITIONAL +ns1.c.example. A 192.0.2.7 +ns2.c.example. A 192.0.2.8 + +ENTRY_END + + +; DS must be gotten from neg cache +; ENTRY_BEGIN +; MATCH opcode qtype qname +; ADJUST copy_id +; REPLY QR AA DO NOERROR +; SECTION QUESTION +; c.example. IN DS +; SECTION AUTHORITY +; ;; NSEC3 RR that covers the "next closer" name (c.example) +; ;; H(c.example) = 4g6p9u5gvfshp30pqecj98b3maqbn1ck +; 35mthgpgcu1qg68fab165klnsnk3dpvl.example. NSEC3 1 1 12 aabbccdd ( b4um86eghhds6nea196smvmlo4ors995 NS DS RRSIG ) +; 35mthgpgcu1qg68fab165klnsnk3dpvl.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. g6jPUUpduAJKRljUsN8gB4UagAX0NxY9shwQ Aynzo8EUWH+z6hEIBlUTPGj15eZll6VhQqgZ XtAIR3chwgW+SA== ) +; +; ;; NSEC3 RR that matches the closest encloser (example) +; ;; H(example) = 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom +; 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd ( 2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG ) +; 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. OSgWSm26B+cS+dDL8b5QrWr/dEWhtCsKlwKL IBHYH6blRxK9rC0bMJPwQ4mLIuw85H2EY762 BOCXJZMnpuwhpA== ) +; ENTRY_END + +RANGE_END + +; ns1.c.example. +RANGE_BEGIN 0 100 + ADDRESS 192.0.2.7 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +c.example. IN NS +SECTION ANSWER +c.example. NS ns1.c.example. +c.example. NS ns2.c.example. +SECTION ADDITIONAL +ns1.c.example. A 192.0.2.7 +ns2.c.example. A 192.0.2.8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +mc.c.example. IN MX +SECTION ANSWER +mc.c.example. IN MX 50 mx.c.example. +SECTION AUTHORITY +c.example. NS ns1.c.example. +c.example. NS ns2.c.example. +SECTION ADDITIONAL +ns1.c.example. A 192.0.2.7 +ns2.c.example. A 192.0.2.8 +ENTRY_END +RANGE_END + +; ns2.c.example. +RANGE_BEGIN 0 100 + ADDRESS 192.0.2.8 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +c.example. IN NS +SECTION ANSWER +c.example. NS ns1.c.example. +c.example. NS ns2.c.example. +SECTION ADDITIONAL +ns1.c.example. A 192.0.2.7 +ns2.c.example. A 192.0.2.8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +mc.c.example. IN MX +SECTION ANSWER +mc.c.example. IN MX 50 mx.c.example. +SECTION AUTHORITY +c.example. NS ns1.c.example. +c.example. NS ns2.c.example. +SECTION ADDITIONAL +ns1.c.example. A 192.0.2.7 +ns2.c.example. A 192.0.2.8 +ENTRY_END +RANGE_END + + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +mc.c.example. IN MX +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +mc.c.example. IN MX +SECTION ANSWER +mc.c.example. IN MX 50 mx.c.example. +SECTION AUTHORITY +c.example. NS ns1.c.example. +c.example. NS ns2.c.example. +SECTION ADDITIONAL +ns1.c.example. A 192.0.2.7 +ns2.c.example. A 192.0.2.8 +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nsec3_b3_optout_noce.rpl b/testdata/val_nsec3_b3_optout_noce.rpl new file mode 100644 index 00000000000..e61aba83e24 --- /dev/null +++ b/testdata/val_nsec3_b3_optout_noce.rpl @@ -0,0 +1,252 @@ +; config options +server: + trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )" + val-override-date: "20120420235959" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator NSEC3 B.3 optout unsigned, without ce. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example. IN A +SECTION AUTHORITY +example. IN NS ns1.example. +; leave out to make unbound take ns1 +;example. IN NS ns2.example. +SECTION ADDITIONAL +ns1.example. IN A 192.0.2.1 +; leave out to make unbound take ns1 +;ns2.example. IN A 192.0.2.2 +ENTRY_END +RANGE_END + +; ns1.example. +RANGE_BEGIN 0 100 + ADDRESS 192.0.2.1 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +ns1.example. IN A +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +ns1.example. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +example. IN NS +SECTION ANSWER +ENTRY_END + +; response to DNSKEY priming query + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example. IN DNSKEY +SECTION ANSWER +example. DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU ( sAD0QPWU+wzt89epO6tHzkMBVDkC7qphQO2h TY4hHn9npWFRw5BYubE= ) +example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= ) +example. RRSIG DNSKEY 7 1 3600 20150420235959 ( 20051021000000 12708 example. AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31 uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm MGQZf3bH+QsCtg== ) +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA DO NOERROR +SECTION QUESTION +c.example. IN DS +SECTION AUTHORITY +;; NSEC3 RR that covers the "next closer" name (c.example) +;; H(c.example) = 4g6p9u5gvfshp30pqecj98b3maqbn1ck +35mthgpgcu1qg68fab165klnsnk3dpvl.example. NSEC3 1 1 12 aabbccdd ( b4um86eghhds6nea196smvmlo4ors995 NS DS RRSIG ) +35mthgpgcu1qg68fab165klnsnk3dpvl.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. g6jPUUpduAJKRljUsN8gB4UagAX0NxY9shwQ Aynzo8EUWH+z6hEIBlUTPGj15eZll6VhQqgZ XtAIR3chwgW+SA== ) + +;; NSEC3 RR that matches the closest encloser (example) +;; H(example) = 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom +;0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd ( 2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG ) +;0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. OSgWSm26B+cS+dDL8b5QrWr/dEWhtCsKlwKL IBHYH6blRxK9rC0bMJPwQ4mLIuw85H2EY762 BOCXJZMnpuwhpA== ) +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR AA DO NOERROR +SECTION QUESTION +c.example. IN MX +SECTION AUTHORITY +c.example. NS ns1.c.example. +c.example. NS ns2.c.example. + +;; NSEC3 RR that covers the "next closer" name (c.example) +;; H(c.example) = 4g6p9u5gvfshp30pqecj98b3maqbn1ck +35mthgpgcu1qg68fab165klnsnk3dpvl.example. NSEC3 1 1 12 aabbccdd ( b4um86eghhds6nea196smvmlo4ors995 NS DS RRSIG ) +35mthgpgcu1qg68fab165klnsnk3dpvl.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. g6jPUUpduAJKRljUsN8gB4UagAX0NxY9shwQ Aynzo8EUWH+z6hEIBlUTPGj15eZll6VhQqgZ XtAIR3chwgW+SA== ) + +;; NSEC3 RR that matches the closest encloser (example) +;; H(example) = 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom +; 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd ( 2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG ) +; 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. OSgWSm26B+cS+dDL8b5QrWr/dEWhtCsKlwKL IBHYH6blRxK9rC0bMJPwQ4mLIuw85H2EY762 BOCXJZMnpuwhpA== ) + +SECTION ADDITIONAL +ns1.c.example. A 192.0.2.7 +ns2.c.example. A 192.0.2.8 + +ENTRY_END +RANGE_END + +; ns1.c.example. +RANGE_BEGIN 0 100 + ADDRESS 192.0.2.7 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns1.c.example. IN AAAA +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns2.c.example. IN AAAA +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +c.example. IN NS +SECTION ANSWER +c.example. NS ns1.c.example. +c.example. NS ns2.c.example. +SECTION ADDITIONAL +ns1.c.example. A 192.0.2.7 +ns2.c.example. A 192.0.2.8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +mc.c.example. IN MX +SECTION ANSWER +mc.c.example. IN MX 50 mx.c.example. +SECTION AUTHORITY +c.example. NS ns1.c.example. +c.example. NS ns2.c.example. +SECTION ADDITIONAL +ns1.c.example. A 192.0.2.7 +ns2.c.example. A 192.0.2.8 +ENTRY_END +RANGE_END + +; ns2.c.example. +RANGE_BEGIN 0 100 + ADDRESS 192.0.2.8 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns1.c.example. IN AAAA +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns2.c.example. IN AAAA +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +c.example. IN NS +SECTION ANSWER +c.example. NS ns1.c.example. +c.example. NS ns2.c.example. +SECTION ADDITIONAL +ns1.c.example. A 192.0.2.7 +ns2.c.example. A 192.0.2.8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +mc.c.example. IN MX +SECTION ANSWER +mc.c.example. IN MX 50 mx.c.example. +SECTION AUTHORITY +c.example. NS ns1.c.example. +c.example. NS ns2.c.example. +SECTION ADDITIONAL +ns1.c.example. A 192.0.2.7 +ns2.c.example. A 192.0.2.8 +ENTRY_END +RANGE_END + + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +mc.c.example. IN MX +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +mc.c.example. IN MX +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nsec3_b3_optout_nonc.rpl b/testdata/val_nsec3_b3_optout_nonc.rpl new file mode 100644 index 00000000000..7c8f19fd5b9 --- /dev/null +++ b/testdata/val_nsec3_b3_optout_nonc.rpl @@ -0,0 +1,253 @@ +; config options +server: + trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )" + val-override-date: "20120420235959" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator NSEC3 B.3 optout unsigned, without nc. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example. IN A +SECTION AUTHORITY +example. IN NS ns1.example. +; leave out to make unbound take ns1 +;example. IN NS ns2.example. +SECTION ADDITIONAL +ns1.example. IN A 192.0.2.1 +; leave out to make unbound take ns1 +;ns2.example. IN A 192.0.2.2 +ENTRY_END +RANGE_END + +; ns1.example. +RANGE_BEGIN 0 100 + ADDRESS 192.0.2.1 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +ns1.example. IN A +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +ns1.example. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +example. IN NS +SECTION ANSWER +ENTRY_END + +; response to DNSKEY priming query + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example. IN DNSKEY +SECTION ANSWER +example. DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU ( sAD0QPWU+wzt89epO6tHzkMBVDkC7qphQO2h TY4hHn9npWFRw5BYubE= ) +example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= ) +example. RRSIG DNSKEY 7 1 3600 20150420235959 ( 20051021000000 12708 example. AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31 uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm MGQZf3bH+QsCtg== ) +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA DO NOERROR +SECTION QUESTION +c.example. IN DS +SECTION AUTHORITY +;; NSEC3 RR that covers the "next closer" name (c.example) +;; H(c.example) = 4g6p9u5gvfshp30pqecj98b3maqbn1ck +;35mthgpgcu1qg68fab165klnsnk3dpvl.example. NSEC3 1 1 12 aabbccdd ( b4um86eghhds6nea196smvmlo4ors995 NS DS RRSIG ) +;35mthgpgcu1qg68fab165klnsnk3dpvl.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. g6jPUUpduAJKRljUsN8gB4UagAX0NxY9shwQ Aynzo8EUWH+z6hEIBlUTPGj15eZll6VhQqgZ XtAIR3chwgW+SA== ) + +;; NSEC3 RR that matches the closest encloser (example) +;; H(example) = 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom +0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd ( 2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG ) +0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. OSgWSm26B+cS+dDL8b5QrWr/dEWhtCsKlwKL IBHYH6blRxK9rC0bMJPwQ4mLIuw85H2EY762 BOCXJZMnpuwhpA== ) +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR AA DO NOERROR +SECTION QUESTION +c.example. IN MX +SECTION AUTHORITY +c.example. NS ns1.c.example. +c.example. NS ns2.c.example. + +;; NSEC3 RR that covers the "next closer" name (c.example) +;; H(c.example) = 4g6p9u5gvfshp30pqecj98b3maqbn1ck +; 35mthgpgcu1qg68fab165klnsnk3dpvl.example. NSEC3 1 1 12 aabbccdd ( b4um86eghhds6nea196smvmlo4ors995 NS DS RRSIG ) +; 35mthgpgcu1qg68fab165klnsnk3dpvl.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. g6jPUUpduAJKRljUsN8gB4UagAX0NxY9shwQ Aynzo8EUWH+z6hEIBlUTPGj15eZll6VhQqgZ XtAIR3chwgW+SA== ) + +;; NSEC3 RR that matches the closest encloser (example) +;; H(example) = 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom +0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd ( 2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG ) +0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. OSgWSm26B+cS+dDL8b5QrWr/dEWhtCsKlwKL IBHYH6blRxK9rC0bMJPwQ4mLIuw85H2EY762 BOCXJZMnpuwhpA== ) + +SECTION ADDITIONAL +ns1.c.example. A 192.0.2.7 +ns2.c.example. A 192.0.2.8 + +ENTRY_END + +RANGE_END + +; ns1.c.example. +RANGE_BEGIN 0 100 + ADDRESS 192.0.2.7 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns1.c.example. IN AAAA +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns2.c.example. IN AAAA +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +c.example. IN NS +SECTION ANSWER +c.example. NS ns1.c.example. +c.example. NS ns2.c.example. +SECTION ADDITIONAL +ns1.c.example. A 192.0.2.7 +ns2.c.example. A 192.0.2.8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +mc.c.example. IN MX +SECTION ANSWER +mc.c.example. IN MX 50 mx.c.example. +SECTION AUTHORITY +c.example. NS ns1.c.example. +c.example. NS ns2.c.example. +SECTION ADDITIONAL +ns1.c.example. A 192.0.2.7 +ns2.c.example. A 192.0.2.8 +ENTRY_END +RANGE_END + +; ns2.c.example. +RANGE_BEGIN 0 100 + ADDRESS 192.0.2.8 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns1.c.example. IN AAAA +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns2.c.example. IN AAAA +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +c.example. IN NS +SECTION ANSWER +c.example. NS ns1.c.example. +c.example. NS ns2.c.example. +SECTION ADDITIONAL +ns1.c.example. A 192.0.2.7 +ns2.c.example. A 192.0.2.8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +mc.c.example. IN MX +SECTION ANSWER +mc.c.example. IN MX 50 mx.c.example. +SECTION AUTHORITY +c.example. NS ns1.c.example. +c.example. NS ns2.c.example. +SECTION ADDITIONAL +ns1.c.example. A 192.0.2.7 +ns2.c.example. A 192.0.2.8 +ENTRY_END +RANGE_END + + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +mc.c.example. IN MX +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +mc.c.example. IN MX +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nsec3_b4_wild.rpl b/testdata/val_nsec3_b4_wild.rpl new file mode 100644 index 00000000000..4da066c4e0e --- /dev/null +++ b/testdata/val_nsec3_b4_wild.rpl @@ -0,0 +1,152 @@ +; config options +server: + trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )" + val-override-date: "20120420235959" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator NSEC3 B.4 wildcard expansion. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +. IN A +SECTION AUTHORITY +example. IN NS ns1.example. +; leave out to make unbound take ns1 +;example. IN NS ns2.example. +SECTION ADDITIONAL +ns1.example. IN A 192.0.2.1 +; leave out to make unbound take ns1 +;ns2.example. IN A 192.0.2.2 +ENTRY_END +RANGE_END + +; ns1.example. +RANGE_BEGIN 0 100 + ADDRESS 192.0.2.1 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +example. IN NS +SECTION ANSWER +ENTRY_END + +; response to DNSKEY priming query + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example. IN DNSKEY +SECTION ANSWER +example. DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU ( sAD0QPWU+wzt89epO6tHzkMBVDkC7qphQO2h TY4hHn9npWFRw5BYubE= ) +example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= ) +example. RRSIG DNSKEY 7 1 3600 20150420235959 ( 20051021000000 12708 example. AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31 uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm MGQZf3bH+QsCtg== ) +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA DO NOERROR +SECTION QUESTION +a.z.w.example. IN MX +SECTION ANSWER +a.z.w.example. MX 1 ai.example. +a.z.w.example. RRSIG MX 7 2 3600 20150420235959 20051021000000 ( 40430 example. CikebjQwGQPwijVcxgcZcSJKtfynugtlBiKb 9FcBTrmOoyQ4InoWVudhCWsh/URX3lc4WRUM ivEBP6+4KS3ldA== ) +SECTION AUTHORITY +example. NS ns1.example. +example. NS ns2.example. +example. RRSIG NS 7 1 3600 20150420235959 20051021000000 ( 40430 example. PVOgtMK1HHeSTau+HwDWC8Ts+6C8qtqd4pQJ qOtdEVgg+MA+ai4fWDEhu3qHJyLcQ9tbD2vv CnMXjtz6SyObxA== ) + +;; NSEC3 RR that covers the "next closer" name (z.w.example) +;; H(z.w.example) = qlu7gtfaeh0ek0c05ksfhdpbcgglbe03 +q04jkcevqvmu85r014c7dkba38o0ji5r.example. NSEC3 1 1 12 aabbccdd ( r53bq7cc2uvmubfu5ocmm6pers9tk9en A RRSIG ) +q04jkcevqvmu85r014c7dkba38o0ji5r.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. hV5I89b+4FHJDATp09g4bbN0R1F845CaXpL3 ZxlMKimoPAyqletMlEWwLfFia7sdpSzn+ZlN NlkxWcLsIlMmUg== ) + +SECTION ADDITIONAL +ai.example. A 192.0.2.9 +ai.example. RRSIG A 7 2 3600 20150420235959 20051021000000 ( 40430 example. hVe+wKYMlObTRPhX0NL67GxeZfdxqr/QeR6F tfdAj5+FgYxyzPEjIzvKWy00hWIl6wD3Vws+ rznEn8sQ64UdqA== ) +ai.example. AAAA 2001:db8:0:0:0:0:f00:baa9 +ai.example. RRSIG AAAA 7 2 3600 20150420235959 20051021000000 ( 40430 example. LcdxKaCB5bGZwPDg+3JJ4O02zoMBrjxqlf6W uaHQZZfTUpb9Nf2nxFGe2XRPfR5tpJT6GdRG cHueLuXkMjBArQ== ) +ENTRY_END + +; catch glue queries +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA DO NOERROR +SECTION QUESTION +ns2.example. IN A +SECTION ANSWER +; nothing to make sure the ns1 server is used for queries. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA DO NOERROR +SECTION QUESTION +ns2.example. IN AAAA +SECTION ANSWER +; nothing to make sure the ns1 server is used for queries. +ENTRY_END + + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +a.z.w.example. IN MX +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +a.z.w.example. IN MX +SECTION ANSWER +a.z.w.example. MX 1 ai.example. +a.z.w.example. RRSIG MX 7 2 3600 20150420235959 20051021000000 ( 40430 example. CikebjQwGQPwijVcxgcZcSJKtfynugtlBiKb 9FcBTrmOoyQ4InoWVudhCWsh/URX3lc4WRUM ivEBP6+4KS3ldA== ) +SECTION AUTHORITY +example. NS ns1.example. +example. NS ns2.example. +example. RRSIG NS 7 1 3600 20150420235959 20051021000000 ( 40430 example. PVOgtMK1HHeSTau+HwDWC8Ts+6C8qtqd4pQJ qOtdEVgg+MA+ai4fWDEhu3qHJyLcQ9tbD2vv CnMXjtz6SyObxA== ) +q04jkcevqvmu85r014c7dkba38o0ji5r.example. NSEC3 1 1 12 aabbccdd ( r53bq7cc2uvmubfu5ocmm6pers9tk9en A RRSIG ) +q04jkcevqvmu85r014c7dkba38o0ji5r.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. hV5I89b+4FHJDATp09g4bbN0R1F845CaXpL3 ZxlMKimoPAyqletMlEWwLfFia7sdpSzn+ZlN NlkxWcLsIlMmUg== ) + +SECTION ADDITIONAL +ai.example. A 192.0.2.9 +ai.example. AAAA 2001:db8:0:0:0:0:f00:baa9 +ai.example. RRSIG A 7 2 3600 20150420235959 20051021000000 ( 40430 example. hVe+wKYMlObTRPhX0NL67GxeZfdxqr/QeR6F tfdAj5+FgYxyzPEjIzvKWy00hWIl6wD3Vws+ rznEn8sQ64UdqA== ) +ai.example. RRSIG AAAA 7 2 3600 20150420235959 20051021000000 ( 40430 example. LcdxKaCB5bGZwPDg+3JJ4O02zoMBrjxqlf6W uaHQZZfTUpb9Nf2nxFGe2XRPfR5tpJT6GdRG cHueLuXkMjBArQ== ) +ENTRY_END +SCENARIO_END diff --git a/testdata/val_nsec3_b4_wild_wr.rpl b/testdata/val_nsec3_b4_wild_wr.rpl new file mode 100644 index 00000000000..bff6b445753 --- /dev/null +++ b/testdata/val_nsec3_b4_wild_wr.rpl @@ -0,0 +1,163 @@ +; config options +server: + trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )" + val-override-date: "20120420235959" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator NSEC3 B.4 wildcard expansion, wrong NSEC3. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example. IN A +SECTION AUTHORITY +example. IN NS ns1.example. +; leave out to make unbound take ns1 +;example. IN NS ns2.example. +SECTION ADDITIONAL +ns1.example. IN A 192.0.2.1 +; leave out to make unbound take ns1 +;ns2.example. IN A 192.0.2.2 +ENTRY_END +RANGE_END + +; ns1.example. +RANGE_BEGIN 0 100 + ADDRESS 192.0.2.1 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +ns1.example. IN A +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +ns1.example. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +example. IN NS +SECTION ANSWER +ENTRY_END + +; response to DNSKEY priming query + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example. IN DNSKEY +SECTION ANSWER +example. DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU ( sAD0QPWU+wzt89epO6tHzkMBVDkC7qphQO2h TY4hHn9npWFRw5BYubE= ) +example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= ) +example. RRSIG DNSKEY 7 1 3600 20150420235959 ( 20051021000000 12708 example. AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31 uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm MGQZf3bH+QsCtg== ) +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA DO NOERROR +SECTION QUESTION +a.z.w.example. IN MX +SECTION ANSWER +a.z.w.example. MX 1 ai.example. +a.z.w.example. RRSIG MX 7 2 3600 20150420235959 20051021000000 ( 40430 example. CikebjQwGQPwijVcxgcZcSJKtfynugtlBiKb 9FcBTrmOoyQ4InoWVudhCWsh/URX3lc4WRUM ivEBP6+4KS3ldA== ) +SECTION AUTHORITY +example. NS ns1.example. +example. NS ns2.example. +example. RRSIG NS 7 1 3600 20150420235959 20051021000000 ( 40430 example. PVOgtMK1HHeSTau+HwDWC8Ts+6C8qtqd4pQJ qOtdEVgg+MA+ai4fWDEhu3qHJyLcQ9tbD2vv CnMXjtz6SyObxA== ) + +;; NSEC3 RR that covers the "next closer" name (z.w.example) +;; H(z.w.example) = qlu7gtfaeh0ek0c05ksfhdpbcgglbe03 +;q04jkcevqvmu85r014c7dkba38o0ji5r.example. NSEC3 1 1 12 aabbccdd ( r53bq7cc2uvmubfu5ocmm6pers9tk9en A RRSIG ) +;q04jkcevqvmu85r014c7dkba38o0ji5r.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. hV5I89b+4FHJDATp09g4bbN0R1F845CaXpL3 ZxlMKimoPAyqletMlEWwLfFia7sdpSzn+ZlN NlkxWcLsIlMmUg== ) + +; The wrong NSEC3 here +k8udemvp1j2f7eg6jebps17vp3n8i58h.example. NSEC3 1 1 12 aabbccdd ( kohar7mbb8dc2ce8a9qvl8hon4k53uhi ) +k8udemvp1j2f7eg6jebps17vp3n8i58h.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. FtXGbvF0+wf8iWkyo73enAuVx03klN+pILBK S6qCcftVtfH4yVzsEZquJ27NHR7ruxJWDNMt Otx7w9WfcIg62A== ) + +SECTION ADDITIONAL +ai.example. A 192.0.2.9 +ai.example. RRSIG A 7 2 3600 20150420235959 20051021000000 ( 40430 example. hVe+wKYMlObTRPhX0NL67GxeZfdxqr/QeR6F tfdAj5+FgYxyzPEjIzvKWy00hWIl6wD3Vws+ rznEn8sQ64UdqA== ) +ai.example. AAAA 2001:db8:0:0:0:0:f00:baa9 +ai.example. RRSIG AAAA 7 2 3600 20150420235959 20051021000000 ( 40430 example. LcdxKaCB5bGZwPDg+3JJ4O02zoMBrjxqlf6W uaHQZZfTUpb9Nf2nxFGe2XRPfR5tpJT6GdRG cHueLuXkMjBArQ== ) +ENTRY_END + +; catch glue queries +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA DO NOERROR +SECTION QUESTION +ns2.example. IN A +SECTION ANSWER +; nothing to make sure the ns1 server is used for queries. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA DO NOERROR +SECTION QUESTION +ns2.example. IN AAAA +SECTION ANSWER +; nothing to make sure the ns1 server is used for queries. +ENTRY_END + + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +a.z.w.example. IN MX +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +a.z.w.example. IN MX +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nsec3_b5_wcnodata.rpl b/testdata/val_nsec3_b5_wcnodata.rpl new file mode 100644 index 00000000000..d12bb8c3910 --- /dev/null +++ b/testdata/val_nsec3_b5_wcnodata.rpl @@ -0,0 +1,153 @@ +; config options +server: + trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )" + val-override-date: "20120420235959" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator NSEC3 B.5 wildcard nodata. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +. IN A +SECTION AUTHORITY +example. IN NS ns1.example. +; leave out to make unbound take ns1 +;example. IN NS ns2.example. +SECTION ADDITIONAL +ns1.example. IN A 192.0.2.1 +; leave out to make unbound take ns1 +;ns2.example. IN A 192.0.2.2 +ENTRY_END +RANGE_END + +; ns1.example. +RANGE_BEGIN 0 100 + ADDRESS 192.0.2.1 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +example. IN NS +SECTION ANSWER +ENTRY_END + +; response to DNSKEY priming query + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example. IN DNSKEY +SECTION ANSWER +example. DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU ( sAD0QPWU+wzt89epO6tHzkMBVDkC7qphQO2h TY4hHn9npWFRw5BYubE= ) +example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= ) +example. RRSIG DNSKEY 7 1 3600 20150420235959 ( 20051021000000 12708 example. AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31 uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm MGQZf3bH+QsCtg== ) +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA DO NOERROR +SECTION QUESTION +a.z.w.example. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +example. SOA ns1.example. bugs.x.w.example. 1 3600 300 ( 3600000 3600 ) +example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 ( 40430 example. Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd VI2LmKusbZsT0Q== ) + +;; NSEC3 RR that matches the closest encloser (w.example) +;; H(w.example) = k8udemvp1j2f7eg6jebps17vp3n8i58h +k8udemvp1j2f7eg6jebps17vp3n8i58h.example. NSEC3 1 1 12 aabbccdd ( kohar7mbb8dc2ce8a9qvl8hon4k53uhi ) +k8udemvp1j2f7eg6jebps17vp3n8i58h.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. FtXGbvF0+wf8iWkyo73enAuVx03klN+pILBK S6qCcftVtfH4yVzsEZquJ27NHR7ruxJWDNMt Otx7w9WfcIg62A== ) + +;; NSEC3 RR that covers the "next closer" name (z.w.example) +;; H(z.w.example) = qlu7gtfaeh0ek0c05ksfhdpbcgglbe03 +q04jkcevqvmu85r014c7dkba38o0ji5r.example. NSEC3 1 1 12 aabbccdd ( r53bq7cc2uvmubfu5ocmm6pers9tk9en A RRSIG ) +q04jkcevqvmu85r014c7dkba38o0ji5r.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. hV5I89b+4FHJDATp09g4bbN0R1F845CaXpL3 ZxlMKimoPAyqletMlEWwLfFia7sdpSzn+ZlN NlkxWcLsIlMmUg== ) + +;; NSEC3 RR that matches a wildcard at the closest encloser. +;; H(*.w.example) = r53bq7cc2uvmubfu5ocmm6pers9tk9en +r53bq7cc2uvmubfu5ocmm6pers9tk9en.example. NSEC3 1 1 12 aabbccdd ( t644ebqk9bibcna874givr6joj62mlhv MX RRSIG ) +r53bq7cc2uvmubfu5ocmm6pers9tk9en.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. aupviViruXs4bDg9rCbezzBMf9h1ZlDvbW/C ZFKulIGXXLj8B/fsDJarXVDA9bnUoRhEbKp+ HF1FWKW7RIJdtQ== ) + +SECTION ADDITIONAL +ENTRY_END + +; catch glue queries +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA DO NOERROR +SECTION QUESTION +ns2.example. IN A +SECTION ANSWER +; nothing to make sure the ns1 server is used for queries. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA DO NOERROR +SECTION QUESTION +ns2.example. IN AAAA +SECTION ANSWER +; nothing to make sure the ns1 server is used for queries. +ENTRY_END + + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +a.z.w.example. IN AAAA +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +a.z.w.example. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +example. SOA ns1.example. bugs.x.w.example. 1 3600 300 ( 3600000 3600 ) +example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 ( 40430 example. Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd VI2LmKusbZsT0Q== ) +k8udemvp1j2f7eg6jebps17vp3n8i58h.example. NSEC3 1 1 12 aabbccdd ( kohar7mbb8dc2ce8a9qvl8hon4k53uhi ) +k8udemvp1j2f7eg6jebps17vp3n8i58h.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. FtXGbvF0+wf8iWkyo73enAuVx03klN+pILBK S6qCcftVtfH4yVzsEZquJ27NHR7ruxJWDNMt Otx7w9WfcIg62A== ) +q04jkcevqvmu85r014c7dkba38o0ji5r.example. NSEC3 1 1 12 aabbccdd ( r53bq7cc2uvmubfu5ocmm6pers9tk9en A RRSIG ) +q04jkcevqvmu85r014c7dkba38o0ji5r.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. hV5I89b+4FHJDATp09g4bbN0R1F845CaXpL3 ZxlMKimoPAyqletMlEWwLfFia7sdpSzn+ZlN NlkxWcLsIlMmUg== ) +r53bq7cc2uvmubfu5ocmm6pers9tk9en.example. NSEC3 1 1 12 aabbccdd ( t644ebqk9bibcna874givr6joj62mlhv MX RRSIG ) +r53bq7cc2uvmubfu5ocmm6pers9tk9en.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. aupviViruXs4bDg9rCbezzBMf9h1ZlDvbW/C ZFKulIGXXLj8B/fsDJarXVDA9bnUoRhEbKp+ HF1FWKW7RIJdtQ== ) + +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nsec3_b5_wcnodata_noce.rpl b/testdata/val_nsec3_b5_wcnodata_noce.rpl new file mode 100644 index 00000000000..a933b50c94f --- /dev/null +++ b/testdata/val_nsec3_b5_wcnodata_noce.rpl @@ -0,0 +1,162 @@ +; config options +server: + trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )" + val-override-date: "20120420235959" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator NSEC3 B.5 wildcard nodata, without ce. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example. IN A +SECTION AUTHORITY +example. IN NS ns1.example. +; leave out to make unbound take ns1 +;example. IN NS ns2.example. +SECTION ADDITIONAL +ns1.example. IN A 192.0.2.1 +; leave out to make unbound take ns1 +;ns2.example. IN A 192.0.2.2 +ENTRY_END +RANGE_END + +; ns1.example. +RANGE_BEGIN 0 100 + ADDRESS 192.0.2.1 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +ns1.example. IN A +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +ns1.example. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +example. IN NS +SECTION ANSWER +ENTRY_END + +; response to DNSKEY priming query + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example. IN DNSKEY +SECTION ANSWER +example. DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU ( sAD0QPWU+wzt89epO6tHzkMBVDkC7qphQO2h TY4hHn9npWFRw5BYubE= ) +example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= ) +example. RRSIG DNSKEY 7 1 3600 20150420235959 ( 20051021000000 12708 example. AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31 uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm MGQZf3bH+QsCtg== ) +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA DO NOERROR +SECTION QUESTION +a.z.w.example. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +example. SOA ns1.example. bugs.x.w.example. 1 3600 300 ( 3600000 3600 ) +example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 ( 40430 example. Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd VI2LmKusbZsT0Q== ) + +;; NSEC3 RR that matches the closest encloser (w.example) +;; H(w.example) = k8udemvp1j2f7eg6jebps17vp3n8i58h +;k8udemvp1j2f7eg6jebps17vp3n8i58h.example. NSEC3 1 1 12 aabbccdd ( kohar7mbb8dc2ce8a9qvl8hon4k53uhi ) +;k8udemvp1j2f7eg6jebps17vp3n8i58h.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. FtXGbvF0+wf8iWkyo73enAuVx03klN+pILBK S6qCcftVtfH4yVzsEZquJ27NHR7ruxJWDNMt Otx7w9WfcIg62A== ) + +;; NSEC3 RR that covers the "next closer" name (z.w.example) +;; H(z.w.example) = qlu7gtfaeh0ek0c05ksfhdpbcgglbe03 +q04jkcevqvmu85r014c7dkba38o0ji5r.example. NSEC3 1 1 12 aabbccdd ( r53bq7cc2uvmubfu5ocmm6pers9tk9en A RRSIG ) +q04jkcevqvmu85r014c7dkba38o0ji5r.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. hV5I89b+4FHJDATp09g4bbN0R1F845CaXpL3 ZxlMKimoPAyqletMlEWwLfFia7sdpSzn+ZlN NlkxWcLsIlMmUg== ) + +;; NSEC3 RR that matches a wildcard at the closest encloser. +;; H(*.w.example) = r53bq7cc2uvmubfu5ocmm6pers9tk9en +r53bq7cc2uvmubfu5ocmm6pers9tk9en.example. NSEC3 1 1 12 aabbccdd ( t644ebqk9bibcna874givr6joj62mlhv MX RRSIG ) +r53bq7cc2uvmubfu5ocmm6pers9tk9en.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. aupviViruXs4bDg9rCbezzBMf9h1ZlDvbW/C ZFKulIGXXLj8B/fsDJarXVDA9bnUoRhEbKp+ HF1FWKW7RIJdtQ== ) + +SECTION ADDITIONAL +ENTRY_END + +; catch glue queries +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA DO NOERROR +SECTION QUESTION +ns2.example. IN A +SECTION ANSWER +; nothing to make sure the ns1 server is used for queries. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA DO NOERROR +SECTION QUESTION +ns2.example. IN AAAA +SECTION ANSWER +; nothing to make sure the ns1 server is used for queries. +ENTRY_END + + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +a.z.w.example. IN AAAA +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +a.z.w.example. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nsec3_b5_wcnodata_nonc.rpl b/testdata/val_nsec3_b5_wcnodata_nonc.rpl new file mode 100644 index 00000000000..8ff0e76bc86 --- /dev/null +++ b/testdata/val_nsec3_b5_wcnodata_nonc.rpl @@ -0,0 +1,162 @@ +; config options +server: + trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )" + val-override-date: "20120420235959" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator NSEC3 B.5 wildcard nodata, without nc. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example. IN A +SECTION AUTHORITY +example. IN NS ns1.example. +; leave out to make unbound take ns1 +;example. IN NS ns2.example. +SECTION ADDITIONAL +ns1.example. IN A 192.0.2.1 +; leave out to make unbound take ns1 +;ns2.example. IN A 192.0.2.2 +ENTRY_END +RANGE_END + +; ns1.example. +RANGE_BEGIN 0 100 + ADDRESS 192.0.2.1 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +ns1.example. IN A +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +ns1.example. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +example. IN NS +SECTION ANSWER +ENTRY_END + +; response to DNSKEY priming query + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example. IN DNSKEY +SECTION ANSWER +example. DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU ( sAD0QPWU+wzt89epO6tHzkMBVDkC7qphQO2h TY4hHn9npWFRw5BYubE= ) +example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= ) +example. RRSIG DNSKEY 7 1 3600 20150420235959 ( 20051021000000 12708 example. AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31 uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm MGQZf3bH+QsCtg== ) +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA DO NOERROR +SECTION QUESTION +a.z.w.example. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +example. SOA ns1.example. bugs.x.w.example. 1 3600 300 ( 3600000 3600 ) +example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 ( 40430 example. Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd VI2LmKusbZsT0Q== ) + +;; NSEC3 RR that matches the closest encloser (w.example) +;; H(w.example) = k8udemvp1j2f7eg6jebps17vp3n8i58h +k8udemvp1j2f7eg6jebps17vp3n8i58h.example. NSEC3 1 1 12 aabbccdd ( kohar7mbb8dc2ce8a9qvl8hon4k53uhi ) +k8udemvp1j2f7eg6jebps17vp3n8i58h.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. FtXGbvF0+wf8iWkyo73enAuVx03klN+pILBK S6qCcftVtfH4yVzsEZquJ27NHR7ruxJWDNMt Otx7w9WfcIg62A== ) + +;; NSEC3 RR that covers the "next closer" name (z.w.example) +;; H(z.w.example) = qlu7gtfaeh0ek0c05ksfhdpbcgglbe03 +;q04jkcevqvmu85r014c7dkba38o0ji5r.example. NSEC3 1 1 12 aabbccdd ( r53bq7cc2uvmubfu5ocmm6pers9tk9en A RRSIG ) +;q04jkcevqvmu85r014c7dkba38o0ji5r.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. hV5I89b+4FHJDATp09g4bbN0R1F845CaXpL3 ZxlMKimoPAyqletMlEWwLfFia7sdpSzn+ZlN NlkxWcLsIlMmUg== ) + +;; NSEC3 RR that matches a wildcard at the closest encloser. +;; H(*.w.example) = r53bq7cc2uvmubfu5ocmm6pers9tk9en +r53bq7cc2uvmubfu5ocmm6pers9tk9en.example. NSEC3 1 1 12 aabbccdd ( t644ebqk9bibcna874givr6joj62mlhv MX RRSIG ) +r53bq7cc2uvmubfu5ocmm6pers9tk9en.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. aupviViruXs4bDg9rCbezzBMf9h1ZlDvbW/C ZFKulIGXXLj8B/fsDJarXVDA9bnUoRhEbKp+ HF1FWKW7RIJdtQ== ) + +SECTION ADDITIONAL +ENTRY_END + +; catch glue queries +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA DO NOERROR +SECTION QUESTION +ns2.example. IN A +SECTION ANSWER +; nothing to make sure the ns1 server is used for queries. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA DO NOERROR +SECTION QUESTION +ns2.example. IN AAAA +SECTION ANSWER +; nothing to make sure the ns1 server is used for queries. +ENTRY_END + + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +a.z.w.example. IN AAAA +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +a.z.w.example. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nsec3_b5_wcnodata_nowc.rpl b/testdata/val_nsec3_b5_wcnodata_nowc.rpl new file mode 100644 index 00000000000..4460e5faee2 --- /dev/null +++ b/testdata/val_nsec3_b5_wcnodata_nowc.rpl @@ -0,0 +1,164 @@ +; config options +server: + trust-anchor: "example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= )" + val-override-date: "20120420235959" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator NSEC3 B.5 wildcard nodata, without wc. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example. IN A +SECTION AUTHORITY +example. IN NS ns1.example. +; leave out to make unbound take ns1 +;example. IN NS ns2.example. +SECTION ADDITIONAL +ns1.example. IN A 192.0.2.1 +; leave out to make unbound take ns1 +;ns2.example. IN A 192.0.2.2 +ENTRY_END +RANGE_END + +; ns1.example. +RANGE_BEGIN 0 100 + ADDRESS 192.0.2.1 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +ns1.example. IN A +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +ns1.example. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR REFUSED +SECTION QUESTION +example. IN NS +SECTION ANSWER +ENTRY_END + +; response to DNSKEY priming query + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example. IN DNSKEY +SECTION ANSWER +example. DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU ( sAD0QPWU+wzt89epO6tHzkMBVDkC7qphQO2h TY4hHn9npWFRw5BYubE= ) +example. DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ ( j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9 AbsUdblMFin8CVF3n4s= ) +example. RRSIG DNSKEY 7 1 3600 20150420235959 ( 20051021000000 12708 example. AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31 uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm MGQZf3bH+QsCtg== ) +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA DO NOERROR +SECTION QUESTION +a.z.w.example. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +example. SOA ns1.example. bugs.x.w.example. 1 3600 300 ( 3600000 3600 ) +example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 ( 40430 example. Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd VI2LmKusbZsT0Q== ) + +;; NSEC3 RR that matches the closest encloser (w.example) +;; H(w.example) = k8udemvp1j2f7eg6jebps17vp3n8i58h +k8udemvp1j2f7eg6jebps17vp3n8i58h.example. NSEC3 1 1 12 aabbccdd ( kohar7mbb8dc2ce8a9qvl8hon4k53uhi ) +k8udemvp1j2f7eg6jebps17vp3n8i58h.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. FtXGbvF0+wf8iWkyo73enAuVx03klN+pILBK S6qCcftVtfH4yVzsEZquJ27NHR7ruxJWDNMt Otx7w9WfcIg62A== ) + +;; NSEC3 RR that covers the "next closer" name (z.w.example) +;; H(z.w.example) = qlu7gtfaeh0ek0c05ksfhdpbcgglbe03 +q04jkcevqvmu85r014c7dkba38o0ji5r.example. NSEC3 1 1 12 aabbccdd ( r53bq7cc2uvmubfu5ocmm6pers9tk9en A RRSIG ) +q04jkcevqvmu85r014c7dkba38o0ji5r.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. hV5I89b+4FHJDATp09g4bbN0R1F845CaXpL3 ZxlMKimoPAyqletMlEWwLfFia7sdpSzn+ZlN NlkxWcLsIlMmUg== ) + +;; NSEC3 RR that matches a wildcard at the closest encloser. +;; H(*.w.example) = r53bq7cc2uvmubfu5ocmm6pers9tk9en +;r53bq7cc2uvmubfu5ocmm6pers9tk9en.example. NSEC3 1 1 12 aabbccdd ( t644ebqk9bibcna874givr6joj62mlhv MX RRSIG ) +;r53bq7cc2uvmubfu5ocmm6pers9tk9en.example. RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 ( 40430 example. aupviViruXs4bDg9rCbezzBMf9h1ZlDvbW/C ZFKulIGXXLj8B/fsDJarXVDA9bnUoRhEbKp+ HF1FWKW7RIJdtQ== ) + +SECTION ADDITIONAL +ENTRY_END + +; catch glue queries +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA DO NOERROR +SECTION QUESTION +ns2.example. IN A +SECTION ANSWER +; nothing to make sure the ns1 server is used for queries. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA DO NOERROR +SECTION QUESTION +ns2.example. IN AAAA +SECTION ANSWER +; nothing to make sure the ns1 server is used for queries. +ENTRY_END + + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +a.z.w.example. IN AAAA +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +; insecure! not bogus! (due to optout) +REPLY QR RD RA NOERROR +SECTION QUESTION +a.z.w.example. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +example. 3600 IN SOA ns1.example. bugs.x.w.example. 1 3600 300 3600000 3600 +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nsec3_cname_ds.rpl b/testdata/val_nsec3_cname_ds.rpl new file mode 100644 index 00000000000..34c1678560f --- /dev/null +++ b/testdata/val_nsec3_cname_ds.rpl @@ -0,0 +1,211 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with NSEC3 CNAME for qtype DS. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN DS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN DS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCM6lsu9byZIQ1yYjJmyYfFWM2RWAIUcR5t84r2La824oWCkLjmHXRQlco= ;{id = 2854} + +; NODATA response. H(www.example.com.) = s1unhcti19bkdr98fegs0v46mbu3t4m3 +s1unhcti19bkdr98fegs0v46mbu3t4m3.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd s1unhcti19bkdr98fegs0v46mbu3t4m4 MX RRSIG +s1unhcti19bkdr98fegs0v46mbu3t4m3.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MCwCFE/a24nsY2luhQmZjY/ObAIgNSMkAhQWd4MUOUVK55bD6AbMHWrDA0yvEA== ;{id = 2854} + +ENTRY_END + +; refer to server one down +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN DS +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN DS 2854 DSA 1 be4d46cd7489cce25a31af0dff2968ce0425dd31 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQC1WMTfb25sTgeUEXCFR4+YiJqecwIUc2R/jrO4amyQxovSnld2reg8eyo= ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.10 +ENTRY_END +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.10 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.10 +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +sub.example.com. 3600 IN RRSIG DNSKEY 3 3 3600 20070926135752 20070829135752 2854 sub.example.com. MCwCFBznBTYM/SrdUnjQdBnLtRO79KAaAhQReG5nRuL7Xsdf6D0KKwPa1GpWyQ== ;{id = 2854} + +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN DS +SECTION ANSWER +; from *.sub.example.com. IN CNAME sub.example.com. +www.sub.example.com. IN CNAME sub.example.com. +www.sub.example.com. 3600 IN RRSIG CNAME 3 3 3600 20070926135752 20070829135752 2854 sub.example.com. MCwCFFyXwAzONbrkZD3oQ50zRYXOr1vvAhQAmzDTm7YYloe6F96eBS1L+KE9hg== ;{id = 2854} +SECTION AUTHORITY +; cover qname next closer name, for the wildcard. +; H(www.sub.example.com.) = ecllopkacmb753v6jlld4d371l1u8gme +ecllopkacmb753v6jlld4d371l1u7gme.sub.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd ecllopkacmb753v6jlld4d371l1u9gme A RRSIG +ecllopkacmb753v6jlld4d371l1u7gme.sub.example.com. 3600 IN RRSIG NSEC3 3 4 3600 20070926135752 20070829135752 2854 sub.example.com. MCwCFD4bIeWulXj9lhAGsqCfsKg6jQheAhQ9kkYqd9AVdomcl2YzWOupJnV5wQ== ;{id = 2854} + +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN DS +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.sub.example.com. IN DS +SECTION ANSWER +www.sub.example.com. IN CNAME sub.example.com. +www.sub.example.com. 3600 IN RRSIG CNAME 3 3 3600 20070926135752 20070829135752 2854 sub.example.com. MCwCFFyXwAzONbrkZD3oQ50zRYXOr1vvAhQAmzDTm7YYloe6F96eBS1L+KE9hg== ;{id = 2854} +sub.example.com. 3600 IN DS 2854 DSA 1 be4d46cd7489cce25a31af0dff2968ce0425dd31 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQC1WMTfb25sTgeUEXCFR4+YiJqecwIUc2R/jrO4amyQxovSnld2reg8eyo= ;{id = 2854} +SECTION AUTHORITY +ecllopkacmb753v6jlld4d371l1u7gme.sub.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd ecllopkacmb753v6jlld4d371l1u9gme A RRSIG +ecllopkacmb753v6jlld4d371l1u7gme.sub.example.com. 3600 IN RRSIG NSEC3 3 4 3600 20070926135752 20070829135752 2854 sub.example.com. MCwCFD4bIeWulXj9lhAGsqCfsKg6jQheAhQ9kkYqd9AVdomcl2YzWOupJnV5wQ== ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nsec3_cname_par.rpl b/testdata/val_nsec3_cname_par.rpl new file mode 100644 index 00000000000..7bd0a1a2b17 --- /dev/null +++ b/testdata/val_nsec3_cname_par.rpl @@ -0,0 +1,215 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with NSEC3 wildcard CNAME to parent. +; to test the zone determination routines in nsec3. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCM6lsu9byZIQ1yYjJmyYfFWM2RWAIUcR5t84r2La824oWCkLjmHXRQlco= ;{id = 2854} + +; NODATA response. H(www.example.com.) = s1unhcti19bkdr98fegs0v46mbu3t4m3 +s1unhcti19bkdr98fegs0v46mbu3t4m3.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd s1unhcti19bkdr98fegs0v46mbu3t4m4 MX RRSIG +s1unhcti19bkdr98fegs0v46mbu3t4m3.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MCwCFE/a24nsY2luhQmZjY/ObAIgNSMkAhQWd4MUOUVK55bD6AbMHWrDA0yvEA== ;{id = 2854} + +ENTRY_END + +; refer to server one down +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN DS 2854 DSA 1 be4d46cd7489cce25a31af0dff2968ce0425dd31 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQC1WMTfb25sTgeUEXCFR4+YiJqecwIUc2R/jrO4amyQxovSnld2reg8eyo= ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.10 +ENTRY_END +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.10 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.10 +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +sub.example.com. 3600 IN RRSIG DNSKEY 3 3 3600 20070926135752 20070829135752 2854 sub.example.com. MCwCFBznBTYM/SrdUnjQdBnLtRO79KAaAhQReG5nRuL7Xsdf6D0KKwPa1GpWyQ== ;{id = 2854} + +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +; from *.sub.example.com. IN CNAME www.example.com. +www.sub.example.com. IN CNAME www.example.com. +www.sub.example.com. 3600 IN RRSIG CNAME 3 3 3600 20070926135752 20070829135752 2854 sub.example.com. MCwCFFKPEuHCx2R69zF2Nd4c7Vu/4RUxAhRB9zHHPCihRU4HT5HhpPJxJykeFg== ;{id = 2854} +SECTION AUTHORITY +; cover qname next closer name, for the wildcard. +; H(www.sub.example.com.) = ecllopkacmb753v6jlld4d371l1u8gme +ecllopkacmb753v6jlld4d371l1u7gme.sub.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd ecllopkacmb753v6jlld4d371l1u9gme A RRSIG +ecllopkacmb753v6jlld4d371l1u7gme.sub.example.com. 3600 IN RRSIG NSEC3 3 4 3600 20070926135752 20070829135752 2854 sub.example.com. MCwCFD4bIeWulXj9lhAGsqCfsKg6jQheAhQ9kkYqd9AVdomcl2YzWOupJnV5wQ== ;{id = 2854} + +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN CNAME www.example.com. +www.sub.example.com. 3600 IN RRSIG CNAME 3 3 3600 20070926135752 20070829135752 2854 sub.example.com. MCwCFFKPEuHCx2R69zF2Nd4c7Vu/4RUxAhRB9zHHPCihRU4HT5HhpPJxJykeFg== ;{id = 2854} +SECTION AUTHORITY +ecllopkacmb753v6jlld4d371l1u7gme.sub.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd ecllopkacmb753v6jlld4d371l1u9gme A RRSIG +ecllopkacmb753v6jlld4d371l1u7gme.sub.example.com. 3600 IN RRSIG NSEC3 3 4 3600 20070926135752 20070829135752 2854 sub.example.com. MCwCFD4bIeWulXj9lhAGsqCfsKg6jQheAhQ9kkYqd9AVdomcl2YzWOupJnV5wQ== ;{id = 2854} +example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCM6lsu9byZIQ1yYjJmyYfFWM2RWAIUcR5t84r2La824oWCkLjmHXRQlco= ;{id = 2854} +s1unhcti19bkdr98fegs0v46mbu3t4m3.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd s1unhcti19bkdr98fegs0v46mbu3t4m4 MX RRSIG +s1unhcti19bkdr98fegs0v46mbu3t4m3.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MCwCFE/a24nsY2luhQmZjY/ObAIgNSMkAhQWd4MUOUVK55bD6AbMHWrDA0yvEA== ;{id = 2854} + +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nsec3_cname_sub.rpl b/testdata/val_nsec3_cname_sub.rpl new file mode 100644 index 00000000000..8babfad3767 --- /dev/null +++ b/testdata/val_nsec3_cname_sub.rpl @@ -0,0 +1,225 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with NSEC3 wildcard CNAME to subzone. +; to test the zone determination routines in nsec3. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +;from *.example.com. IN CNAME www.sub.example.com. +www.example.com. IN CNAME www.sub.example.com. +www.example.com. 3600 IN RRSIG CNAME 3 2 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCjVxqOi0bcgHgxVkwzJqIi6iNJswIUZxbmItvoyEczTclgVtHsr9Jmf+w= ;{id = 2854} +SECTION AUTHORITY +; cover qname next closer name. +; H(www.example.com.) = s1unhcti19bkdr98fegs0v46mbu3t4m3. +s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 123 aabb00123456bbccdd s1unhcti19bkdr98fegs0v46mbu3t4m4 A MX RRSIG +s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFFSH4klZKke48dYyddYDj17gjTS0AhUAltWicpFLWqW98/Af9Qlx70MH8o4= ;{id = 2854} +ENTRY_END + +; refer to server one down +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN DS 2854 DSA 1 be4d46cd7489cce25a31af0dff2968ce0425dd31 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQC1WMTfb25sTgeUEXCFR4+YiJqecwIUc2R/jrO4amyQxovSnld2reg8eyo= ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.10 +ENTRY_END +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.10 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.10 +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +sub.example.com. 3600 IN RRSIG DNSKEY 3 3 3600 20070926135752 20070829135752 2854 sub.example.com. MCwCFBznBTYM/SrdUnjQdBnLtRO79KAaAhQReG5nRuL7Xsdf6D0KKwPa1GpWyQ== ;{id = 2854} + +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +sub.example.com. IN SOA ns.sub.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000 +sub.example.com. 3600 IN RRSIG SOA 3 3 3600 20070926135752 20070829135752 2854 sub.example.com. MCwCFBLls0z0ncWxTXzDt4uLAuJsr932AhQvVeUJevgwAL6mfmLL6fAf2IZ7mg== ;{id = 2854} + +; closest encloser, H(sub.example.com). = 8r1f0ieoutlnjc03meng9e3bn2n0o9pd +8r1f0ieoutlnjc03meng9e3bn2n0o9pd.sub.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd 8r1f0ieoutlnjc03meng9e3bn3n0o9pd SOA NS MX RRSIG +8r1f0ieoutlnjc03meng9e3bn2n0o9pd.sub.example.com. 3600 IN RRSIG NSEC3 3 4 3600 20070926135752 20070829135752 2854 sub.example.com. MCwCFBX1qVlth+YE+y57p5C7X00bLthDAhRIF2xoHF0exs29obE7JjVthwXfHA== ;{id = 2854} + +; wildcard denial, H(*.sub.example.com.) = hq432j8q183b54mejh50200pqo8rvlog +hq432j8q183b54mejh50200pqo7rvlog.sub.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd hq432j8q183b54mejh50200pqo9rvlog A RRSIG +hq432j8q183b54mejh50200pqo7rvlog.sub.example.com. 3600 IN RRSIG NSEC3 3 4 3600 20070926135752 20070829135752 2854 sub.example.com. MCwCFAOXoeUk1d0cxT9p1gUvBrybAQCSAhQ5eLWaK932TxxY4U6NAxgst4O4uA== ;{id = 2854} + +; next closer denial H(www.sub.example.com.) = ecllopkacmb753v6jlld4d371l1u8gme +ecllopkacmb753v6jlld4d371l1u7gme.sub.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd ecllopkacmb753v6jlld4d371l1u9gme A RRSIG +ecllopkacmb753v6jlld4d371l1u7gme.sub.example.com. 3600 IN RRSIG NSEC3 3 4 3600 20070926135752 20070829135752 2854 sub.example.com. MCwCFAuD3qb/+CWyqjBRt/RDjZvsSyCGAhQivfP3zr1+2Uknw9RhXUcUO0g6Lg== ;{id = 2854} +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NXDOMAIN +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN CNAME www.sub.example.com. +www.example.com. 3600 IN RRSIG CNAME 3 2 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCjVxqOi0bcgHgxVkwzJqIi6iNJswIUZxbmItvoyEczTclgVtHsr9Jmf+w= ;{id = 2854} +SECTION AUTHORITY +SECTION AUTHORITY +s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 123 aabb00123456bbccdd s1unhcti19bkdr98fegs0v46mbu3t4m4 A MX RRSIG +s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFFSH4klZKke48dYyddYDj17gjTS0AhUAltWicpFLWqW98/Af9Qlx70MH8o4= ;{id = 2854} +sub.example.com. IN SOA ns.sub.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000 +sub.example.com. 3600 IN RRSIG SOA 3 3 3600 20070926135752 20070829135752 2854 sub.example.com. MCwCFBLls0z0ncWxTXzDt4uLAuJsr932AhQvVeUJevgwAL6mfmLL6fAf2IZ7mg== ;{id = 2854} +8r1f0ieoutlnjc03meng9e3bn2n0o9pd.sub.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd 8r1f0ieoutlnjc03meng9e3bn3n0o9pd SOA NS MX RRSIG +8r1f0ieoutlnjc03meng9e3bn2n0o9pd.sub.example.com. 3600 IN RRSIG NSEC3 3 4 3600 20070926135752 20070829135752 2854 sub.example.com. MCwCFBX1qVlth+YE+y57p5C7X00bLthDAhRIF2xoHF0exs29obE7JjVthwXfHA== ;{id = 2854} +hq432j8q183b54mejh50200pqo7rvlog.sub.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd hq432j8q183b54mejh50200pqo9rvlog A RRSIG +hq432j8q183b54mejh50200pqo7rvlog.sub.example.com. 3600 IN RRSIG NSEC3 3 4 3600 20070926135752 20070829135752 2854 sub.example.com. MCwCFAOXoeUk1d0cxT9p1gUvBrybAQCSAhQ5eLWaK932TxxY4U6NAxgst4O4uA== ;{id = 2854} +ecllopkacmb753v6jlld4d371l1u7gme.sub.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd ecllopkacmb753v6jlld4d371l1u9gme A RRSIG +ecllopkacmb753v6jlld4d371l1u7gme.sub.example.com. 3600 IN RRSIG NSEC3 3 4 3600 20070926135752 20070829135752 2854 sub.example.com. MCwCFAuD3qb/+CWyqjBRt/RDjZvsSyCGAhQivfP3zr1+2Uknw9RhXUcUO0g6Lg== ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nsec3_iter_high.rpl b/testdata/val_nsec3_iter_high.rpl new file mode 100644 index 00000000000..9ae0fcae3b7 --- /dev/null +++ b/testdata/val_nsec3_iter_high.rpl @@ -0,0 +1,162 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + val-nsec3-keysize-iterations: "1024 100 2048 200 4096 500" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with nxdomain NSEC3 with too high iterations + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFCNGZ+/OfElYQMCZ77O9Lw9rhk7PAhUAmDcvTAst6Bq83qPq3r6c/Dm1nFc= ;{id = 2854} + +; closest encloser, H(example.com). +6md8numosa4q9ugkffdo1bmm82t5j39s.example.com. NSEC3 1 1 8 - 6md8numosa4q9ugkffdo1bmm82t5j49s SOA NS MX DNSKEY RRSIG +6md8numosa4q9ugkffdo1bmm82t5j39s.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCz/LkFOFcaQzVnyySW9ZoVUnxh7gIUdxyS9vqVDzo8pGhFU+3YogN2ZRk= ;{id = 2854} + +; wildcard denial, H(*.example.com.) = 4f3cnt8cu22tngec382jj4gde4rb47ub +4f3cnt8cu22tngec382jj4gde4rb46ub.example.com. NSEC3 1 1 0 - 4f3cnt8cu22tngec382jj4gde4rb48ub A MX RRSIG +4f3cnt8cu22tngec382jj4gde4rb46ub.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MCwCFHS+i/OB/V/gYmS1eQTXieXIXGjsAhQQ0Ql7TW/hsUklrb0DfoyhVPG95Q== ;{id = 2854} + +; next closer name, H(www.example.com.) = s1unhcti19bkdr98fegs0v46mbu3t4m3. +s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 123 aabb00123456bbccdd s1unhcti19bkdr98fegs0v46mbu3t4m4 A MX RRSIG +s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFFSH4klZKke48dYyddYDj17gjTS0AhUAltWicpFLWqW98/Af9Qlx70MH8o4= ;{id = 2854} + +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NXDOMAIN +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFCNGZ+/OfElYQMCZ77O9Lw9rhk7PAhUAmDcvTAst6Bq83qPq3r6c/Dm1nFc= ;{id = 2854} +6md8numosa4q9ugkffdo1bmm82t5j39s.example.com. NSEC3 1 1 8 - 6md8numosa4q9ugkffdo1bmm82t5j49s SOA NS MX DNSKEY RRSIG +6md8numosa4q9ugkffdo1bmm82t5j39s.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCz/LkFOFcaQzVnyySW9ZoVUnxh7gIUdxyS9vqVDzo8pGhFU+3YogN2ZRk= ;{id = 2854} +4f3cnt8cu22tngec382jj4gde4rb46ub.example.com. NSEC3 1 1 0 - 4f3cnt8cu22tngec382jj4gde4rb48ub A MX RRSIG +4f3cnt8cu22tngec382jj4gde4rb46ub.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MCwCFHS+i/OB/V/gYmS1eQTXieXIXGjsAhQQ0Ql7TW/hsUklrb0DfoyhVPG95Q== ;{id = 2854} +s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 123 aabb00123456bbccdd s1unhcti19bkdr98fegs0v46mbu3t4m4 A MX RRSIG +s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFFSH4klZKke48dYyddYDj17gjTS0AhUAltWicpFLWqW98/Af9Qlx70MH8o4= ;{id = 2854} + +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nsec3_nodatawccname.rpl b/testdata/val_nsec3_nodatawccname.rpl new file mode 100644 index 00000000000..4f01cdf8a41 --- /dev/null +++ b/testdata/val_nsec3_nodatawccname.rpl @@ -0,0 +1,167 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with nodata NSEC3 abused wildcarded CNAME. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN A +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN AAAA +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFCNGZ+/OfElYQMCZ77O9Lw9rhk7PAhUAmDcvTAst6Bq83qPq3r6c/Dm1nFc= ;{id = 2854} +; closest encloser +6md8numosa4q9ugkffdo1bmm82t5j39s.example.com. NSEC3 1 1 8 - 6md8numosa4q9ugkffdo1bmm82t5j49s SOA NS MX DNSKEY RRSIG +6md8numosa4q9ugkffdo1bmm82t5j39s.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCz/LkFOFcaQzVnyySW9ZoVUnxh7gIUdxyS9vqVDzo8pGhFU+3YogN2ZRk= ;{id = 2854} + +; wildcard H(*.example.com.) = 4f3cnt8cu22tngec382jj4gde4rb47ub +4f3cnt8cu22tngec382jj4gde4rb47ub.example.com. NSEC3 1 1 0 - 4f3cnt8cu22tngec382jj4gde4rb48ub CNAME RRSIG +4f3cnt8cu22tngec382jj4gde4rb47ub.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFHo9PHBS+MkNWl2DVXH1h1Z8p0yFAhUAjBVKA5s0q5Bt8YOGdY1+9J6GmDU= ;{id = 2854} + +; next closer name, H(www.example.com.) = s1unhcti19bkdr98fegs0v46mbu3t4m3. +s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 123 aabb00123456bbccdd s1unhcti19bkdr98fegs0v46mbu3t4m4 A MX RRSIG +s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFFSH4klZKke48dYyddYDj17gjTS0AhUAltWicpFLWqW98/Af9Qlx70MH8o4= ;{id = 2854} + +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nsec3_nods.rpl b/testdata/val_nsec3_nods.rpl new file mode 100644 index 00000000000..d9dfdfabdab --- /dev/null +++ b/testdata/val_nsec3_nods.rpl @@ -0,0 +1,218 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with NSEC3 with no DS referral. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCM6lsu9byZIQ1yYjJmyYfFWM2RWAIUcR5t84r2La824oWCkLjmHXRQlco= ;{id = 2854} + +; NODATA response. H(www.example.com.) = s1unhcti19bkdr98fegs0v46mbu3t4m3 +s1unhcti19bkdr98fegs0v46mbu3t4m3.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd s1unhcti19bkdr98fegs0v46mbu3t4m4 MX RRSIG +s1unhcti19bkdr98fegs0v46mbu3t4m3.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MCwCFE/a24nsY2luhQmZjY/ObAIgNSMkAhQWd4MUOUVK55bD6AbMHWrDA0yvEA== ;{id = 2854} + +ENTRY_END + +; refer to server one down +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +; proof that there is no DS here. +;sub.example.com. 3600 IN DS 2854 DSA 1 be4d46cd7489cce25a31af0dff2968ce0425dd31 +;sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQC1WMTfb25sTgeUEXCFR4+YiJqecwIUc2R/jrO4amyQxovSnld2reg8eyo= ;{id = 2854} +; sub.example.com. -> 8r1f0ieoutlnjc03meng9e3bn2n0o9pd. +8r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd 8r1f0ieoutlnjc03meng9e3bn3n0o9pd NS RRSIG +8r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFEC78oZJjqlV6kVyQb4X0o6tsUpUAhUAk+bgth7eeN+aO8ts2+yLSyzSX9g= ;{id = 2854} + +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.10 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION AUTHORITY +; proof that there is no DS here. +;sub.example.com. 3600 IN DS 2854 DSA 1 be4d46cd7489cce25a31af0dff2968ce0425dd31 +;sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQC1WMTfb25sTgeUEXCFR4+YiJqecwIUc2R/jrO4amyQxovSnld2reg8eyo= ;{id = 2854} +; sub.example.com. -> 8r1f0ieoutlnjc03meng9e3bn2n0o9pd. +8r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd 8r1f0ieoutlnjc03meng9e3bn3n0o9pd NS RRSIG +8r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFEC78oZJjqlV6kVyQb4X0o6tsUpUAhUAk+bgth7eeN+aO8ts2+yLSyzSX9g= ;{id = 2854} +ENTRY_END +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.10 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR REFUSED +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +ENTRY_END + + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +sub.example.com. 3600 IN RRSIG DNSKEY 3 3 3600 20070926135752 20070829135752 2854 sub.example.com. MCwCFBznBTYM/SrdUnjQdBnLtRO79KAaAhQReG5nRuL7Xsdf6D0KKwPa1GpWyQ== ;{id = 2854} + +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 1.2.3.123 +www.sub.example.com. 3600 IN RRSIG A 3 4 3600 20070926135752 20070829135752 2854 sub.example.com. MC0CFEExteiCsLkRi/md6o5K8BhRJAKFAhUAgg2tkvwaDn8Xbm9q+5xnjvgIB8k= ;{id = 2854} +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 1.2.3.123 +www.sub.example.com. 3600 IN RRSIG A 3 4 3600 20070926135752 20070829135752 2854 sub.example.com. MC0CFEExteiCsLkRi/md6o5K8BhRJAKFAhUAgg2tkvwaDn8Xbm9q+5xnjvgIB8k= ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nsec3_nods_badopt.rpl b/testdata/val_nsec3_nods_badopt.rpl new file mode 100644 index 00000000000..c2f71ca76ac --- /dev/null +++ b/testdata/val_nsec3_nods_badopt.rpl @@ -0,0 +1,246 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with NSEC3 with no DS with wrong optout bit. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN A +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN AAAA +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCM6lsu9byZIQ1yYjJmyYfFWM2RWAIUcR5t84r2La824oWCkLjmHXRQlco= ;{id = 2854} + +; NODATA response. H(www.example.com.) = s1unhcti19bkdr98fegs0v46mbu3t4m3 +s1unhcti19bkdr98fegs0v46mbu3t4m3.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd s1unhcti19bkdr98fegs0v46mbu3t4m4 MX RRSIG +s1unhcti19bkdr98fegs0v46mbu3t4m3.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MCwCFE/a24nsY2luhQmZjY/ObAIgNSMkAhQWd4MUOUVK55bD6AbMHWrDA0yvEA== ;{id = 2854} + +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION AUTHORITY +; proof that there is no DS here. +;sub.example.com. 3600 IN DS 2854 DSA 1 be4d46cd7489cce25a31af0dff2968ce0425dd31 +;sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQC1WMTfb25sTgeUEXCFR4+YiJqecwIUc2R/jrO4amyQxovSnld2reg8eyo= ;{id = 2854} +; example.com. -> b6fuorg741ufili49mg9j4328ig53sqg. +b6fuorg741ufili49mg9j4328ig53sqg.example.com. IN NSEC3 1 0 123 aabb00123456bbccdd b6fuorg741ufili49mg9j4328ig54sqg NS SOA DNSKEY RRSIG +b6fuorg741ufili49mg9j4328ig53sqg.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFEtLEiFNr2V6qJOHUxIRQ4ittparAhUAm+WN3aqAHEgiQQEeX9z4S0Ub/dM= ;{id = 2854} +; sub.example.com. -> 8r1f0ieoutlnjc03meng9e3bn2n0o9pd. +8r1f0ieoutlnjc03meng9e3bn1n0o9pd.example.com. IN NSEC3 1 0 123 aabb00123456bbccdd 8r1f0ieoutlnjc03meng9e3bn3n0o9pd NS RRSIG +8r1f0ieoutlnjc03meng9e3bn1n0o9pd.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCategdxsiQTpOMHED1ehjPT7PO2gIUDJ9f/zGCEUHy/UVp97aOh0RRoks= ;{id = 2854} +ENTRY_END + +; refer to server one down +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN A +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +; proof that there is no DS here. +;sub.example.com. 3600 IN DS 2854 DSA 1 be4d46cd7489cce25a31af0dff2968ce0425dd31 +;sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQC1WMTfb25sTgeUEXCFR4+YiJqecwIUc2R/jrO4amyQxovSnld2reg8eyo= ;{id = 2854} +; example.com. -> b6fuorg741ufili49mg9j4328ig53sqg. +b6fuorg741ufili49mg9j4328ig53sqg.example.com. IN NSEC3 1 0 123 aabb00123456bbccdd b6fuorg741ufili49mg9j4328ig54sqg NS SOA DNSKEY RRSIG +b6fuorg741ufili49mg9j4328ig53sqg.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFEtLEiFNr2V6qJOHUxIRQ4ittparAhUAm+WN3aqAHEgiQQEeX9z4S0Ub/dM= ;{id = 2854} +; sub.example.com. -> 8r1f0ieoutlnjc03meng9e3bn2n0o9pd. +8r1f0ieoutlnjc03meng9e3bn1n0o9pd.example.com. IN NSEC3 1 0 123 aabb00123456bbccdd 8r1f0ieoutlnjc03meng9e3bn3n0o9pd NS RRSIG +8r1f0ieoutlnjc03meng9e3bn1n0o9pd.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCategdxsiQTpOMHED1ehjPT7PO2gIUDJ9f/zGCEUHy/UVp97aOh0RRoks= ;{id = 2854} + +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.10 +ENTRY_END + +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.10 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.sub.example.com. IN AAAA +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR REFUSED +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +sub.example.com. 3600 IN RRSIG DNSKEY 3 3 3600 20070926135752 20070829135752 2854 sub.example.com. MCwCFBznBTYM/SrdUnjQdBnLtRO79KAaAhQReG5nRuL7Xsdf6D0KKwPa1GpWyQ== ;{id = 2854} + +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 1.2.3.123 +www.sub.example.com. 3600 IN RRSIG A 3 4 3600 20070926135752 20070829135752 2854 sub.example.com. MC0CFEExteiCsLkRi/md6o5K8BhRJAKFAhUAgg2tkvwaDn8Xbm9q+5xnjvgIB8k= ;{id = 2854} +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nsec3_nods_badsig.rpl b/testdata/val_nsec3_nods_badsig.rpl new file mode 100644 index 00000000000..8e5a0cf451a --- /dev/null +++ b/testdata/val_nsec3_nods_badsig.rpl @@ -0,0 +1,235 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with NSEC3 with no DS referral with bad signature. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN A +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN AAAA +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCM6lsu9byZIQ1yYjJmyYfFWM2RWAIUcR5t84r2La824oWCkLjmHXRQlco= ;{id = 2854} + +; NODATA response. H(www.example.com.) = s1unhcti19bkdr98fegs0v46mbu3t4m3 +s1unhcti19bkdr98fegs0v46mbu3t4m3.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd s1unhcti19bkdr98fegs0v46mbu3t4m4 MX RRSIG +s1unhcti19bkdr98fegs0v46mbu3t4m3.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MCwCFE/a24nsY2luhQmZjY/ObAIgNSMkAhQWd4MUOUVK55bD6AbMHWrDA0yvEA== ;{id = 2854} + +ENTRY_END + +; refer to server one down +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +; proof that there is no DS here. +;sub.example.com. 3600 IN DS 2854 DSA 1 be4d46cd7489cce25a31af0dff2968ce0425dd31 +;sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQC1WMTfb25sTgeUEXCFR4+YiJqecwIUc2R/jrO4amyQxovSnld2reg8eyo= ;{id = 2854} +; sub.example.com. -> 8r1f0ieoutlnjc03meng9e3bn2n0o9pd. +8r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd 8r1f0ieoutlnjc03meng9e3bn3n0o9pd NS RRSIG +; bad signature: +8r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20010926135752 20010829135752 2854 example.com. MC0CFEC78oZJjqlV6kVyQb4X0o6tsUpUAhUAk+bgth7eeN+aO8ts2+yLSyzSX9g= ;{id = 2854} +;8r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFEC78oZJjqlV6kVyQb4X0o6tsUpUAhUAk+bgth7eeN+aO8ts2+yLSyzSX9g= ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.10 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION AUTHORITY +; proof that there is no DS here. +;sub.example.com. 3600 IN DS 2854 DSA 1 be4d46cd7489cce25a31af0dff2968ce0425dd31 +;sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQC1WMTfb25sTgeUEXCFR4+YiJqecwIUc2R/jrO4amyQxovSnld2reg8eyo= ;{id = 2854} +; sub.example.com. -> 8r1f0ieoutlnjc03meng9e3bn2n0o9pd. +8r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd 8r1f0ieoutlnjc03meng9e3bn3n0o9pd NS RRSIG +; bad signature +8r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20010926135752 20010829135752 2854 example.com. MC0CFEC78oZJjqlV6kVyQb4X0o6tsUpUAhUAk+bgth7eeN+aO8ts2+yLSyzSX9g= ;{id = 2854} +;8r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFEC78oZJjqlV6kVyQb4X0o6tsUpUAhUAk+bgth7eeN+aO8ts2+yLSyzSX9g= ;{id = 2854} +ENTRY_END +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.10 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR REFUSED +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +ENTRY_END + + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +sub.example.com. 3600 IN RRSIG DNSKEY 3 3 3600 20070926135752 20070829135752 2854 sub.example.com. MCwCFBznBTYM/SrdUnjQdBnLtRO79KAaAhQReG5nRuL7Xsdf6D0KKwPa1GpWyQ== ;{id = 2854} + +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 1.2.3.123 +www.sub.example.com. 3600 IN RRSIG A 3 4 3600 20070926135752 20070829135752 2854 sub.example.com. MC0CFEExteiCsLkRi/md6o5K8BhRJAKFAhUAgg2tkvwaDn8Xbm9q+5xnjvgIB8k= ;{id = 2854} +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nsec3_nods_negcache.rpl b/testdata/val_nsec3_nods_negcache.rpl new file mode 100644 index 00000000000..75dcbed75f3 --- /dev/null +++ b/testdata/val_nsec3_nods_negcache.rpl @@ -0,0 +1,219 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with NSEC3 with no DS referral from neg cache. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCM6lsu9byZIQ1yYjJmyYfFWM2RWAIUcR5t84r2La824oWCkLjmHXRQlco= ;{id = 2854} + +; NODATA response. H(www.example.com.) = s1unhcti19bkdr98fegs0v46mbu3t4m3 +s1unhcti19bkdr98fegs0v46mbu3t4m3.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd s1unhcti19bkdr98fegs0v46mbu3t4m4 MX RRSIG +s1unhcti19bkdr98fegs0v46mbu3t4m3.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MCwCFE/a24nsY2luhQmZjY/ObAIgNSMkAhQWd4MUOUVK55bD6AbMHWrDA0yvEA== ;{id = 2854} + +ENTRY_END + +; refer to server one down +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +; proof that there is no DS here. +;sub.example.com. 3600 IN DS 2854 DSA 1 be4d46cd7489cce25a31af0dff2968ce0425dd31 +;sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQC1WMTfb25sTgeUEXCFR4+YiJqecwIUc2R/jrO4amyQxovSnld2reg8eyo= ;{id = 2854} +; sub.example.com. -> 8r1f0ieoutlnjc03meng9e3bn2n0o9pd. +8r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd 8r1f0ieoutlnjc03meng9e3bn3n0o9pd NS RRSIG +8r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFEC78oZJjqlV6kVyQb4X0o6tsUpUAhUAk+bgth7eeN+aO8ts2+yLSyzSX9g= ;{id = 2854} + +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.10 +ENTRY_END + +; get DS proof from neg cache +; ENTRY_BEGIN +; MATCH opcode qtype qname +; ADJUST copy_id +; REPLY QR NOERROR +; SECTION QUESTION +; sub.example.com. IN DS +; SECTION AUTHORITY +; ; proof that there is no DS here. +; ;sub.example.com. 3600 IN DS 2854 DSA 1 be4d46cd7489cce25a31af0dff2968ce0425dd31 +; ;sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQC1WMTfb25sTgeUEXCFR4+YiJqecwIUc2R/jrO4amyQxovSnld2reg8eyo= ;{id = 2854} +; ; sub.example.com. -> 8r1f0ieoutlnjc03meng9e3bn2n0o9pd. +; 8r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd 8r1f0ieoutlnjc03meng9e3bn3n0o9pd NS RRSIG +; 8r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFEC78oZJjqlV6kVyQb4X0o6tsUpUAhUAk+bgth7eeN+aO8ts2+yLSyzSX9g= ;{id = 2854} +; ENTRY_END +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.10 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR REFUSED +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +ENTRY_END + + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +sub.example.com. 3600 IN RRSIG DNSKEY 3 3 3600 20070926135752 20070829135752 2854 sub.example.com. MCwCFBznBTYM/SrdUnjQdBnLtRO79KAaAhQReG5nRuL7Xsdf6D0KKwPa1GpWyQ== ;{id = 2854} + +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 1.2.3.123 +www.sub.example.com. 3600 IN RRSIG A 3 4 3600 20070926135752 20070829135752 2854 sub.example.com. MC0CFEExteiCsLkRi/md6o5K8BhRJAKFAhUAgg2tkvwaDn8Xbm9q+5xnjvgIB8k= ;{id = 2854} +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 1.2.3.123 +www.sub.example.com. 3600 IN RRSIG A 3 4 3600 20070926135752 20070829135752 2854 sub.example.com. MC0CFEExteiCsLkRi/md6o5K8BhRJAKFAhUAgg2tkvwaDn8Xbm9q+5xnjvgIB8k= ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nsec3_nods_soa.rpl b/testdata/val_nsec3_nods_soa.rpl new file mode 100644 index 00000000000..a967c5037e3 --- /dev/null +++ b/testdata/val_nsec3_nods_soa.rpl @@ -0,0 +1,251 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with NSEC3 with no DS referral abuse of apex. +; abusing subzone apex NSEC3. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA SERVFAIL +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA SERVFAIL +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCM6lsu9byZIQ1yYjJmyYfFWM2RWAIUcR5t84r2La824oWCkLjmHXRQlco= ;{id = 2854} + +; NODATA response. H(www.example.com.) = s1unhcti19bkdr98fegs0v46mbu3t4m3 +s1unhcti19bkdr98fegs0v46mbu3t4m3.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd s1unhcti19bkdr98fegs0v46mbu3t4m4 MX RRSIG +s1unhcti19bkdr98fegs0v46mbu3t4m3.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MCwCFE/a24nsY2luhQmZjY/ObAIgNSMkAhQWd4MUOUVK55bD6AbMHWrDA0yvEA== ;{id = 2854} + +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION AUTHORITY +; proof that there is no DS here. +;sub.example.com. 3600 IN DS 2854 DSA 1 be4d46cd7489cce25a31af0dff2968ce0425dd31 +;sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQC1WMTfb25sTgeUEXCFR4+YiJqecwIUc2R/jrO4amyQxovSnld2reg8eyo= ;{id = 2854} +; sub.example.com. -> 8r1f0ieoutlnjc03meng9e3bn2n0o9pd. +8r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd 8r1f0ieoutlnjc03meng9e3bn3n0o9pd NS SOA DNSKEY RRSIG +8r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC4CFQCeKcyw76yvOvfa2+qtxv8bKcEyJwIVAJBeIGST4Y8Tk8YkQI0suee3Bxb1 ;{id = 2854} +ENTRY_END + +; refer to server one down +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN A +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +; proof that there is no DS here. +;sub.example.com. 3600 IN DS 2854 DSA 1 be4d46cd7489cce25a31af0dff2968ce0425dd31 +;sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQC1WMTfb25sTgeUEXCFR4+YiJqecwIUc2R/jrO4amyQxovSnld2reg8eyo= ;{id = 2854} +; sub.example.com. -> 8r1f0ieoutlnjc03meng9e3bn2n0o9pd. +8r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd 8r1f0ieoutlnjc03meng9e3bn3n0o9pd NS SOA DNSKEY RRSIG +8r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC4CFQCeKcyw76yvOvfa2+qtxv8bKcEyJwIVAJBeIGST4Y8Tk8YkQI0suee3Bxb1 ;{id = 2854} + +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.10 +ENTRY_END +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.10 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.sub.example.com. IN A +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.sub.example.com. IN AAAA +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR REFUSED +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +sub.example.com. 3600 IN RRSIG DNSKEY 3 3 3600 20070926135752 20070829135752 2854 sub.example.com. MCwCFBznBTYM/SrdUnjQdBnLtRO79KAaAhQReG5nRuL7Xsdf6D0KKwPa1GpWyQ== ;{id = 2854} + +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 1.2.3.123 +www.sub.example.com. 3600 IN RRSIG A 3 4 3600 20070926135752 20070829135752 2854 sub.example.com. MC0CFEExteiCsLkRi/md6o5K8BhRJAKFAhUAgg2tkvwaDn8Xbm9q+5xnjvgIB8k= ;{id = 2854} +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nsec3_optout_ad.rpl b/testdata/val_nsec3_optout_ad.rpl new file mode 100644 index 00000000000..2001640c227 --- /dev/null +++ b/testdata/val_nsec3_optout_ad.rpl @@ -0,0 +1,359 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. DS 57024 7 1 46d134be319b2cc910b9938f1cb25dc41abb27bf" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with optout NSEC3 response that gets no AD. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 7 2 3600 20070926134150 20070829134150 57024 example.com. fIE3H2v3wAm3GPajsdgJn+A8R4Cp7dMXf1PSUQ8BfklzMBMJjpc0oM/S7u/HVLYQs1jx8CMdw2TZEpIPfo6Rl0TekDqNtVk6IBw1H+zxDFwf3v7UdOjm8s6FfoEJcZ5yEFV/Lps82NzHCR9uqprhv6ddQdAeVNA5QHis1c5Y1P0= ;{id = 57024} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 7 3 3600 20070926134150 20070829134150 57024 example.com. b0iX5vuTqngB5F0ORFrFLx8sAeTHGJVcPpD34iNFY71ZoFnHrHfAMWC3RAWz+nQ1NmH1oDdA8NTYN/aQQNzwEz4VmVYA2PANBSiwSY3q3gp9PWZU6CfRNf2dU/210H0y35FroQpADszmwC+Hlbcvll+bQj3fSyT2W/69kRVssj4= ;{id = 57024} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 257 3 7 AwEAAbvre/wK/WVeoj0SiwVkTD+NefvHPru9YIqLWY0m+0E5NYOpJZdc+PGQQYRzFNOlugVZtFirmv5Lmz7GNiASXtG/IFi//SlE30DxEKQOjt2F6qSZTZ1nZ5XOIMGTwWyp4OoI0egk5JavC5mQbyXqcj82ywt6F5Z3CmnThVl6MtOv ;{id = 57024 (ksk), size = 1024b} +example.com. 3600 IN RRSIG DNSKEY 7 2 3600 20070926134150 20070829134150 57024 example.com. lqOo8W7UffLZIKBoIJg8OAPkmCWptnstiLIg1bAtzuEZDZFr2KNZGv+5k6hbRJKYnZRLReY4v8G9Eg0GCC/44gLm8BZlnh/4jLOjMH9MKusFV/jNqz/HABITYn1pBwvVak7lzqN+bmL0KMyWf1MzPWilx4fM9YWinsQFILVLPL0= ;{id = 57024} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 7 2 3600 20070926134150 20070829134150 57024 example.com. fIE3H2v3wAm3GPajsdgJn+A8R4Cp7dMXf1PSUQ8BfklzMBMJjpc0oM/S7u/HVLYQs1jx8CMdw2TZEpIPfo6Rl0TekDqNtVk6IBw1H+zxDFwf3v7UdOjm8s6FfoEJcZ5yEFV/Lps82NzHCR9uqprhv6ddQdAeVNA5QHis1c5Y1P0= ;{id = 57024} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 7 3 3600 20070926134150 20070829134150 57024 example.com. b0iX5vuTqngB5F0ORFrFLx8sAeTHGJVcPpD34iNFY71ZoFnHrHfAMWC3RAWz+nQ1NmH1oDdA8NTYN/aQQNzwEz4VmVYA2PANBSiwSY3q3gp9PWZU6CfRNf2dU/210H0y35FroQpADszmwC+Hlbcvll+bQj3fSyT2W/69kRVssj4= ;{id = 57024} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA ns.example.com. noc.example.com. 2009310622 1800 900 604800 86400 +example.com. 3600 IN RRSIG SOA 7 2 3600 20070926134150 20070829134150 57024 example.com. HlyER7bYPiSJ9jdjjRBucQexYr932Oor1TvxSLPWw5fuWvr/fFitKVnLqC+lqBIeOby44KiDr0rIk+ZqYjWWKNjaLm5wMfhQzbsAgGTQxmO07jnYOGQG9SI6DSbR9GJdZ7imu5sx5oo5dze73MxgLMZIethGaFMkktYN53+AzG0= ;{id = 57024} + +; optout +; example.com. -> onib9mgub9h0rml3cdf5bgrj59dkjhvk. +; sub.example.com. -> kg19n32806c832kijdnglq8p9m2r5mdj. +; *.example.com. -> 4f3cnt8cu22tngec382jj4gde4rb47ub. +onib9mgub9h0rml3cdf5bgrj59dkjhvk.example.com. NSEC3 1 1 0 - pnib9mgub9h0rml3cdf5bgrj59dkjhvk NS SOA RRSIG DNSKEY NSEC3PARAM +jg19n32806c832kijdnglq8p9m2r5mdj.example.com. NSEC3 1 1 0 - lg19n32806c832kijdnglq8p9m2r5mdj NS DS RRSIG + +onib9mgub9h0rml3cdf5bgrj59dkjhvk.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. jHrF+lnyRL1LE/Bwz6C+jZg3E/2qQkVSboGxya6iX71v0zA3eUsob9m9l3gHNlhwhyahbamHUKx+OMvtYuzRa+RMv4ObuLRIt8StdixeXaUU+rx7C2qCKOFsa5q4HzK4bLYPfyb5T9w67HbzHPLEllXPA7tghzyzCM9qBtbvwK4= ;{id = 57024} +jg19n32806c832kijdnglq8p9m2r5mdj.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. f7ZSCahAuKOLXquM0jpdU6I9AX31CgGicRiB3aU4jvqQp/EygbCNn5kfpyXY0FvZvzggpl8naXSStOPN9dy3bb0NwGQkJcYD94NEw307T8uEunOvx1ug5TuakBAwqjY8xKM3xab3LnWYRtx4zdln/3ZDHvBUwfzkxUZrzeKjpiI= ;{id = 57024} +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN MX +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA ns.example.com. noc.example.com. 2009310622 1800 900 604800 86400 +example.com. 3600 IN RRSIG SOA 7 2 3600 20070926134150 20070829134150 57024 example.com. HlyER7bYPiSJ9jdjjRBucQexYr932Oor1TvxSLPWw5fuWvr/fFitKVnLqC+lqBIeOby44KiDr0rIk+ZqYjWWKNjaLm5wMfhQzbsAgGTQxmO07jnYOGQG9SI6DSbR9GJdZ7imu5sx5oo5dze73MxgLMZIethGaFMkktYN53+AzG0= ;{id = 57024} + +; optout +; example.com. -> onib9mgub9h0rml3cdf5bgrj59dkjhvk. +; sub.example.com. -> kg19n32806c832kijdnglq8p9m2r5mdj. +; *.example.com. -> 4f3cnt8cu22tngec382jj4gde4rb47ub. +onib9mgub9h0rml3cdf5bgrj59dkjhvk.example.com. NSEC3 1 1 0 - pnib9mgub9h0rml3cdf5bgrj59dkjhvk NS SOA RRSIG DNSKEY NSEC3PARAM +jg19n32806c832kijdnglq8p9m2r5mdj.example.com. NSEC3 1 1 0 - lg19n32806c832kijdnglq8p9m2r5mdj NS DS RRSIG + +onib9mgub9h0rml3cdf5bgrj59dkjhvk.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. jHrF+lnyRL1LE/Bwz6C+jZg3E/2qQkVSboGxya6iX71v0zA3eUsob9m9l3gHNlhwhyahbamHUKx+OMvtYuzRa+RMv4ObuLRIt8StdixeXaUU+rx7C2qCKOFsa5q4HzK4bLYPfyb5T9w67HbzHPLEllXPA7tghzyzCM9qBtbvwK4= ;{id = 57024} +jg19n32806c832kijdnglq8p9m2r5mdj.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. f7ZSCahAuKOLXquM0jpdU6I9AX31CgGicRiB3aU4jvqQp/EygbCNn5kfpyXY0FvZvzggpl8naXSStOPN9dy3bb0NwGQkJcYD94NEw307T8uEunOvx1ug5TuakBAwqjY8xKM3xab3LnWYRtx4zdln/3ZDHvBUwfzkxUZrzeKjpiI= ;{id = 57024} +SECTION ADDITIONAL +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NXDOMAIN +SECTION QUESTION +rub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA ns.example.com. noc.example.com. 2009310622 1800 900 604800 86400 +example.com. 3600 IN RRSIG SOA 7 2 3600 20070926134150 20070829134150 57024 example.com. HlyER7bYPiSJ9jdjjRBucQexYr932Oor1TvxSLPWw5fuWvr/fFitKVnLqC+lqBIeOby44KiDr0rIk+ZqYjWWKNjaLm5wMfhQzbsAgGTQxmO07jnYOGQG9SI6DSbR9GJdZ7imu5sx5oo5dze73MxgLMZIethGaFMkktYN53+AzG0= ;{id = 57024} + +; optout +; example.com. -> onib9mgub9h0rml3cdf5bgrj59dkjhvk. +; rub.example.com. -> c2bqk3tb4foaenfbp1v0pdk6mor3r7vo. +; *.example.com. -> 4f3cnt8cu22tngec382jj4gde4rb47ub. +onib9mgub9h0rml3cdf5bgrj59dkjhvk.example.com. NSEC3 1 1 0 - pnib9mgub9h0rml3cdf5bgrj59dkjhvk NS SOA RRSIG DNSKEY NSEC3PARAM +22bqk3tb4foaenfbp1v0pdk6mor3r7vo.example.com. NSEC3 1 1 0 - f2bqk3tb4foaenfbp1v0pdk6mor3r7vo NS RRSIG + +onib9mgub9h0rml3cdf5bgrj59dkjhvk.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. jHrF+lnyRL1LE/Bwz6C+jZg3E/2qQkVSboGxya6iX71v0zA3eUsob9m9l3gHNlhwhyahbamHUKx+OMvtYuzRa+RMv4ObuLRIt8StdixeXaUU+rx7C2qCKOFsa5q4HzK4bLYPfyb5T9w67HbzHPLEllXPA7tghzyzCM9qBtbvwK4= ;{id = 57024} +22bqk3tb4foaenfbp1v0pdk6mor3r7vo.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. jk6EYU9qTrmNeeKuQRG7iKyfNJnBt45MToPVpAQ+LoGDC3muy4bkWeKspj68cN9E5wNijfmm1eFK3khSSEnM50mfJbpiwlbKgL0VZz33Zn+Wu8b7sTtdDwDH7MUBLRwHeb7W+NtQIEXPLs4Z3BXHzAXy5ZpSjQ3PJZn6zBx4/dw= ;{id = 57024} +SECTION ADDITIONAL +ENTRY_END + +; wildcard expansion +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +a.wild.example.com. IN A +SECTION ANSWER +; *.wild.example.com. IN A 77.88.99.0 +a.wild.example.com. IN A 77.88.99.0 +a.wild.example.com. 3600 IN RRSIG A 7 3 3600 20070926134150 20070829134150 57024 example.com. GWV6cQprrpAsaYla5z7N9tppdb+X0ZjOsiWBuBueSACHU8CzsYPMbwKUZlTNbQ4mSVRRDa0rM1niYoZF9oqyAfbn5HBLi62TRjrBLHfvatDgSiZCa4mauUfzUS+U7FfUXikNIigG0aN0xdpJ//urmecjNSKg2aW4M0DYsm7keMI= ;{id = 57024} +SECTION AUTHORITY +; a.wild.example.com -> ad1535hlgg914unuuaei9jfh4ofr44uo. covered by optout +ac1535hlgg914unuuaei9jfh4ofr44uo.example.com. IN NSEC3 1 1 0 - ae1535hlgg914unuuaei9jfh4ofr44uo NS RRSIG +ac1535hlgg914unuuaei9jfh4ofr44uo.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. imoxsXE1c3FaXu6uSantJfMPGBgsauf1GhmNpS1lLuaNRjXOhf1PDXwt/GoD/dm2GXJAlWT8u6EK3RXkFwlDIsP7vYFuDfUNCQ/hvYq300sXl1nfW0O1bsoBJahQJuNM+xcbwbnQf0krCTxNthyi2cuiY7RYug6ZTZ3gz4DMkhU= ;{id = 57024} +; for wild.example.com the closest encloser +; wild.example.com -> 8aeigskl5tmraedgji7v1lqbmqs8qv7u. +8aeigskl5tmraedgji7v1lqbmqs8qv7u.example.com. IN NSEC3 1 1 0 - 9aeigskl5tmraedgji7v1lqbmqs8qv7u +8aeigskl5tmraedgji7v1lqbmqs8qv7u.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. afV7c9knpxmD5c6UKrqw5J/06eokPwSb3HZi3TI63tzFcswuMjj4d7NKJmdpA+uo0aweVZgcOp+O+v9urgNYNYbxOy02qqOetLph8YWH7MQTftaGBwKD7gZMbnUArryPCtrlJz0i0GzoWvVTZnsjrrlDtP/ogLDnCKyi7Q0si+k= ;{id = 57024} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +a.wild.example.com. IN MX +SECTION ANSWER +SECTION AUTHORITY +; wildcard no data +example.com. IN SOA ns.example.com. noc.example.com. 2009310622 1800 900 604800 86400 +example.com. 3600 IN RRSIG SOA 7 2 3600 20070926134150 20070829134150 57024 example.com. HlyER7bYPiSJ9jdjjRBucQexYr932Oor1TvxSLPWw5fuWvr/fFitKVnLqC+lqBIeOby44KiDr0rIk+ZqYjWWKNjaLm5wMfhQzbsAgGTQxmO07jnYOGQG9SI6DSbR9GJdZ7imu5sx5oo5dze73MxgLMZIethGaFMkktYN53+AzG0= ;{id = 57024} +; wild.example.com -> 8aeigskl5tmraedgji7v1lqbmqs8qv7u. +; *.wild.example.com. -> nvec78au1hpuma9eebeji5n06eq33gbk. +; the NSEC3 for the wildcard *.wild.example.com. , with optout, A RRSIG +nvec78au1hpuma9eebeji5n06eq33gbk.example.com. IN NSEC3 1 1 0 - ovec78au1hpuma9eebeji5n06eq33gbk A RRSIG +nvec78au1hpuma9eebeji5n06eq33gbk.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. jE+b5p+stQumm+tLZdaBT+KBpwYI7wRXijRHWcqiUp2SY1uV7HxBdW8aedVTqpFe8kYbMUgI3pCOAitmiI9R6SJg3q7022QOb9y+0/xSmIDqxATVPTJbkzVBInfWrulRtn7o3HmOyoIc9/w7NnNxFYpwtFL08jTBRr8XRTWDM7Q= ;{id = 57024} +; NSEC3 for the closest encloser, wild.example.com. (an empty nonterminal) +8aeigskl5tmraedgji7v1lqbmqs8qv7u.example.com. IN NSEC3 1 1 0 - 9aeigskl5tmraedgji7v1lqbmqs8qv7u +8aeigskl5tmraedgji7v1lqbmqs8qv7u.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. afV7c9knpxmD5c6UKrqw5J/06eokPwSb3HZi3TI63tzFcswuMjj4d7NKJmdpA+uo0aweVZgcOp+O+v9urgNYNYbxOy02qqOetLph8YWH7MQTftaGBwKD7gZMbnUArryPCtrlJz0i0GzoWvVTZnsjrrlDtP/ogLDnCKyi7Q0si+k= ;{id = 57024} +; a.wild.example.com -> ad1535hlgg914unuuaei9jfh4ofr44uo. covered by optout +ac1535hlgg914unuuaei9jfh4ofr44uo.example.com. IN NSEC3 1 1 0 - ae1535hlgg914unuuaei9jfh4ofr44uo NS RRSIG +ac1535hlgg914unuuaei9jfh4ofr44uo.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. imoxsXE1c3FaXu6uSantJfMPGBgsauf1GhmNpS1lLuaNRjXOhf1PDXwt/GoD/dm2GXJAlWT8u6EK3RXkFwlDIsP7vYFuDfUNCQ/hvYq300sXl1nfW0O1bsoBJahQJuNM+xcbwbnQf0krCTxNthyi2cuiY7RYug6ZTZ3gz4DMkhU= ;{id = 57024} +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +sub.example.com. IN MX +ENTRY_END + +; recursion happens here. +; no AD flag on this because an optout NSEC3 is used. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +sub.example.com. IN MX +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA ns.example.com. noc.example.com. 2009310622 1800 900 604800 86400 +example.com. 3600 IN RRSIG SOA 7 2 3600 20070926134150 20070829134150 57024 example.com. HlyER7bYPiSJ9jdjjRBucQexYr932Oor1TvxSLPWw5fuWvr/fFitKVnLqC+lqBIeOby44KiDr0rIk+ZqYjWWKNjaLm5wMfhQzbsAgGTQxmO07jnYOGQG9SI6DSbR9GJdZ7imu5sx5oo5dze73MxgLMZIethGaFMkktYN53+AzG0= ;{id = 57024} +onib9mgub9h0rml3cdf5bgrj59dkjhvk.example.com. NSEC3 1 1 0 - pnib9mgub9h0rml3cdf5bgrj59dkjhvk NS SOA RRSIG DNSKEY NSEC3PARAM +onib9mgub9h0rml3cdf5bgrj59dkjhvk.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. jHrF+lnyRL1LE/Bwz6C+jZg3E/2qQkVSboGxya6iX71v0zA3eUsob9m9l3gHNlhwhyahbamHUKx+OMvtYuzRa+RMv4ObuLRIt8StdixeXaUU+rx7C2qCKOFsa5q4HzK4bLYPfyb5T9w67HbzHPLEllXPA7tghzyzCM9qBtbvwK4= ;{id = 57024} +jg19n32806c832kijdnglq8p9m2r5mdj.example.com. NSEC3 1 1 0 - lg19n32806c832kijdnglq8p9m2r5mdj NS DS RRSIG +jg19n32806c832kijdnglq8p9m2r5mdj.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. f7ZSCahAuKOLXquM0jpdU6I9AX31CgGicRiB3aU4jvqQp/EygbCNn5kfpyXY0FvZvzggpl8naXSStOPN9dy3bb0NwGQkJcYD94NEw307T8uEunOvx1ug5TuakBAwqjY8xKM3xab3LnWYRtx4zdln/3ZDHvBUwfzkxUZrzeKjpiI= ;{id = 57024} +SECTION ADDITIONAL +ENTRY_END + +STEP 20 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +sub.example.com. IN DS +ENTRY_END + +; recursion happens here. +; no AD flag here because of RFC5155 9.2 section. +; even though we are sure there is no DS, this is what the RFC says. +STEP 30 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA ns.example.com. noc.example.com. 2009310622 1800 900 604800 86400 +example.com. 3600 IN RRSIG SOA 7 2 3600 20070926134150 20070829134150 57024 example.com. HlyER7bYPiSJ9jdjjRBucQexYr932Oor1TvxSLPWw5fuWvr/fFitKVnLqC+lqBIeOby44KiDr0rIk+ZqYjWWKNjaLm5wMfhQzbsAgGTQxmO07jnYOGQG9SI6DSbR9GJdZ7imu5sx5oo5dze73MxgLMZIethGaFMkktYN53+AzG0= ;{id = 57024} +onib9mgub9h0rml3cdf5bgrj59dkjhvk.example.com. NSEC3 1 1 0 - pnib9mgub9h0rml3cdf5bgrj59dkjhvk NS SOA RRSIG DNSKEY NSEC3PARAM +onib9mgub9h0rml3cdf5bgrj59dkjhvk.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. jHrF+lnyRL1LE/Bwz6C+jZg3E/2qQkVSboGxya6iX71v0zA3eUsob9m9l3gHNlhwhyahbamHUKx+OMvtYuzRa+RMv4ObuLRIt8StdixeXaUU+rx7C2qCKOFsa5q4HzK4bLYPfyb5T9w67HbzHPLEllXPA7tghzyzCM9qBtbvwK4= ;{id = 57024} +jg19n32806c832kijdnglq8p9m2r5mdj.example.com. NSEC3 1 1 0 - lg19n32806c832kijdnglq8p9m2r5mdj NS DS RRSIG +jg19n32806c832kijdnglq8p9m2r5mdj.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. f7ZSCahAuKOLXquM0jpdU6I9AX31CgGicRiB3aU4jvqQp/EygbCNn5kfpyXY0FvZvzggpl8naXSStOPN9dy3bb0NwGQkJcYD94NEw307T8uEunOvx1ug5TuakBAwqjY8xKM3xab3LnWYRtx4zdln/3ZDHvBUwfzkxUZrzeKjpiI= ;{id = 57024} +SECTION ADDITIONAL +ENTRY_END + +STEP 40 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +rub.example.com. IN A +ENTRY_END + +; recursion happens here. +; no AD flag here because of RFC5155 9.2 section. +; also for NXDOMAIN +STEP 50 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NXDOMAIN +SECTION QUESTION +rub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA ns.example.com. noc.example.com. 2009310622 1800 900 604800 86400 +example.com. 3600 IN RRSIG SOA 7 2 3600 20070926134150 20070829134150 57024 example.com. HlyER7bYPiSJ9jdjjRBucQexYr932Oor1TvxSLPWw5fuWvr/fFitKVnLqC+lqBIeOby44KiDr0rIk+ZqYjWWKNjaLm5wMfhQzbsAgGTQxmO07jnYOGQG9SI6DSbR9GJdZ7imu5sx5oo5dze73MxgLMZIethGaFMkktYN53+AzG0= ;{id = 57024} +onib9mgub9h0rml3cdf5bgrj59dkjhvk.example.com. NSEC3 1 1 0 - pnib9mgub9h0rml3cdf5bgrj59dkjhvk NS SOA RRSIG DNSKEY NSEC3PARAM +onib9mgub9h0rml3cdf5bgrj59dkjhvk.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. jHrF+lnyRL1LE/Bwz6C+jZg3E/2qQkVSboGxya6iX71v0zA3eUsob9m9l3gHNlhwhyahbamHUKx+OMvtYuzRa+RMv4ObuLRIt8StdixeXaUU+rx7C2qCKOFsa5q4HzK4bLYPfyb5T9w67HbzHPLEllXPA7tghzyzCM9qBtbvwK4= ;{id = 57024} +22bqk3tb4foaenfbp1v0pdk6mor3r7vo.example.com. NSEC3 1 1 0 - f2bqk3tb4foaenfbp1v0pdk6mor3r7vo NS RRSIG +22bqk3tb4foaenfbp1v0pdk6mor3r7vo.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. jk6EYU9qTrmNeeKuQRG7iKyfNJnBt45MToPVpAQ+LoGDC3muy4bkWeKspj68cN9E5wNijfmm1eFK3khSSEnM50mfJbpiwlbKgL0VZz33Zn+Wu8b7sTtdDwDH7MUBLRwHeb7W+NtQIEXPLs4Z3BXHzAXy5ZpSjQ3PJZn6zBx4/dw= ;{id = 57024} +SECTION ADDITIONAL +ENTRY_END + +STEP 60 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +a.wild.example.com. IN A +ENTRY_END + +; query is a wildcard expansion, covered by optout. +; hence it is without AD flag (even though we are sure this wildcard exists, +; we are not sure that there is no delegation covered by the optout span +; with the name a.wild.example.com). +STEP 70 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +a.wild.example.com. IN A +SECTION ANSWER +a.wild.example.com. IN A 77.88.99.0 +a.wild.example.com. 3600 IN RRSIG A 7 3 3600 20070926134150 20070829134150 57024 example.com. GWV6cQprrpAsaYla5z7N9tppdb+X0ZjOsiWBuBueSACHU8CzsYPMbwKUZlTNbQ4mSVRRDa0rM1niYoZF9oqyAfbn5HBLi62TRjrBLHfvatDgSiZCa4mauUfzUS+U7FfUXikNIigG0aN0xdpJ//urmecjNSKg2aW4M0DYsm7keMI= ;{id = 57024} +SECTION AUTHORITY +ac1535hlgg914unuuaei9jfh4ofr44uo.example.com. IN NSEC3 1 1 0 - ae1535hlgg914unuuaei9jfh4ofr44uo NS RRSIG +ac1535hlgg914unuuaei9jfh4ofr44uo.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. imoxsXE1c3FaXu6uSantJfMPGBgsauf1GhmNpS1lLuaNRjXOhf1PDXwt/GoD/dm2GXJAlWT8u6EK3RXkFwlDIsP7vYFuDfUNCQ/hvYq300sXl1nfW0O1bsoBJahQJuNM+xcbwbnQf0krCTxNthyi2cuiY7RYug6ZTZ3gz4DMkhU= ;{id = 57024} +8aeigskl5tmraedgji7v1lqbmqs8qv7u.example.com. IN NSEC3 1 1 0 - 9aeigskl5tmraedgji7v1lqbmqs8qv7u +8aeigskl5tmraedgji7v1lqbmqs8qv7u.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. afV7c9knpxmD5c6UKrqw5J/06eokPwSb3HZi3TI63tzFcswuMjj4d7NKJmdpA+uo0aweVZgcOp+O+v9urgNYNYbxOy02qqOetLph8YWH7MQTftaGBwKD7gZMbnUArryPCtrlJz0i0GzoWvVTZnsjrrlDtP/ogLDnCKyi7Q0si+k= ;{id = 57024} +ENTRY_END + +STEP 80 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +a.wild.example.com. IN MX +ENTRY_END + +; nodata wildcard expansion, we are sure that the wildcard does not have +; the data that is requested, but there an optout flag set on the wildcard +; expansion denial, thus we are not sure of a.wild.example.com delegation +; under the optout. +STEP 90 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +a.wild.example.com. IN MX +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA ns.example.com. noc.example.com. 2009310622 1800 900 604800 86400 +example.com. 3600 IN RRSIG SOA 7 2 3600 20070926134150 20070829134150 57024 example.com. HlyER7bYPiSJ9jdjjRBucQexYr932Oor1TvxSLPWw5fuWvr/fFitKVnLqC+lqBIeOby44KiDr0rIk+ZqYjWWKNjaLm5wMfhQzbsAgGTQxmO07jnYOGQG9SI6DSbR9GJdZ7imu5sx5oo5dze73MxgLMZIethGaFMkktYN53+AzG0= ;{id = 57024} +nvec78au1hpuma9eebeji5n06eq33gbk.example.com. IN NSEC3 1 1 0 - ovec78au1hpuma9eebeji5n06eq33gbk A RRSIG +nvec78au1hpuma9eebeji5n06eq33gbk.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. jE+b5p+stQumm+tLZdaBT+KBpwYI7wRXijRHWcqiUp2SY1uV7HxBdW8aedVTqpFe8kYbMUgI3pCOAitmiI9R6SJg3q7022QOb9y+0/xSmIDqxATVPTJbkzVBInfWrulRtn7o3HmOyoIc9/w7NnNxFYpwtFL08jTBRr8XRTWDM7Q= ;{id = 57024} +8aeigskl5tmraedgji7v1lqbmqs8qv7u.example.com. IN NSEC3 1 1 0 - 9aeigskl5tmraedgji7v1lqbmqs8qv7u +8aeigskl5tmraedgji7v1lqbmqs8qv7u.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. afV7c9knpxmD5c6UKrqw5J/06eokPwSb3HZi3TI63tzFcswuMjj4d7NKJmdpA+uo0aweVZgcOp+O+v9urgNYNYbxOy02qqOetLph8YWH7MQTftaGBwKD7gZMbnUArryPCtrlJz0i0GzoWvVTZnsjrrlDtP/ogLDnCKyi7Q0si+k= ;{id = 57024} +ac1535hlgg914unuuaei9jfh4ofr44uo.example.com. IN NSEC3 1 1 0 - ae1535hlgg914unuuaei9jfh4ofr44uo NS RRSIG +ac1535hlgg914unuuaei9jfh4ofr44uo.example.com. 3600 IN RRSIG NSEC3 7 3 3600 20070926134150 20070829134150 57024 example.com. imoxsXE1c3FaXu6uSantJfMPGBgsauf1GhmNpS1lLuaNRjXOhf1PDXwt/GoD/dm2GXJAlWT8u6EK3RXkFwlDIsP7vYFuDfUNCQ/hvYq300sXl1nfW0O1bsoBJahQJuNM+xcbwbnQf0krCTxNthyi2cuiY7RYug6ZTZ3gz4DMkhU= ;{id = 57024} +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nsec3_optout_cache.rpl b/testdata/val_nsec3_optout_cache.rpl new file mode 100644 index 00000000000..14462d48a19 --- /dev/null +++ b/testdata/val_nsec3_optout_cache.rpl @@ -0,0 +1,278 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with NSEC3 span change and cache effects. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +; blacklisted address to stop it from using it, the negative answer uses its +; nsec3-hash which is alittle inconvenient +; ns.example.com. -> 7l9dbddmge35f7vr9mec78dqr6l3236k. +ns.example.com. IN AAAA ::1 +ns.example.com. 3600 IN RRSIG AAAA 3 3 3600 20070926135752 20070829135752 2854 example.com. AExGBc6JU/xwwoSIeK/DtX8kr7AgOecx5Z2FnRiz/YSpnWGnFDt26ec= +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; DS query +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION AUTHORITY +example.com. IN SOA a. b. 1 2 3 4 5 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926135752 20070829135752 2854 example.com. AAkQt1yoMF7s4gCYlojFzi0ubw6Uo4uWPSJTz6Dp/2iWUVDbxDKpy+E= + +; sub.example.com. -> 8r1f0ieoutlnjc03meng9e3bn2n0o9pd. +; example.com. -> b6fuorg741ufili49mg9j4328ig53sqg. +; proof that there is no DS here. +; ce: +b6fuorg741ufili49mg9j4328ig53sqg.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd b6fuorg741ufili49mg9j4328ig53sqh NS SOA DNSKEY NSEC3PARAM RRSIG +b6fuorg741ufili49mg9j4328ig53sqg.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. AKHQ0gnNP5WDab1yqbd+Bt12CSSff88sqeDR40dvhiWOcYA8mmyjYNA= + +; span around sub.example.com., same span as foo.example.com, but it has +; just changed and it is now larger to accomodate sub.example.com. +6obgmo062d9935unjnnj2su5otaj9334.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd 9r1f0ieoutlnjc03meng9e3bn2n0o9pd NS DS RRSIG +6obgmo062d9935unjnnj2su5otaj9334.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. ABzruSKUUcJRNlYDqZ4UmQH/WnzeXt9Gozp3chS4cR0sqsEeGjL54eQ= + +; span around sub.example.com. from previous delegation in nsec3-chain +;7r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd 9r1f0ieoutlnjc03meng9e3bn2n0o9pd NS DS RRSIG +;7r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. AF2FOKiIfOV9KrDTuP4RwnDI6lZnmhRHE+HAh8UHEq87uakYUEHfGUY= +ENTRY_END + +; refer to server one down +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN A +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +; sub.example.com. -> 8r1f0ieoutlnjc03meng9e3bn2n0o9pd. +; example.com. -> b6fuorg741ufili49mg9j4328ig53sqg. +; proof that there is no DS here. +; ce: +b6fuorg741ufili49mg9j4328ig53sqg.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd b6fuorg741ufili49mg9j4328ig53sqh NS SOA DNSKEY NSEC3PARAM RRSIG +b6fuorg741ufili49mg9j4328ig53sqg.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. AKHQ0gnNP5WDab1yqbd+Bt12CSSff88sqeDR40dvhiWOcYA8mmyjYNA= + +; span around sub.example.com., same span as foo.example.com, but it has +; just changed and it is now larger to accomodate sub.example.com. +6obgmo062d9935unjnnj2su5otaj9334.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd 9r1f0ieoutlnjc03meng9e3bn2n0o9pd NS DS RRSIG +6obgmo062d9935unjnnj2su5otaj9334.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. ABzruSKUUcJRNlYDqZ4UmQH/WnzeXt9Gozp3chS4cR0sqsEeGjL54eQ= + +; span around sub.example.com. from previous delegation in nsec3-chain +;7r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd 9r1f0ieoutlnjc03meng9e3bn2n0o9pd NS DS RRSIG +;7r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. AF2FOKiIfOV9KrDTuP4RwnDI6lZnmhRHE+HAh8UHEq87uakYUEHfGUY= + +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.10 +ENTRY_END + +; refer to server one down +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +foo.example.com. IN A +SECTION AUTHORITY +foo.example.com. IN NS ns.sub.example.com. +; sub.example.com. -> 8r1f0ieoutlnjc03meng9e3bn2n0o9pd. +; foo.example.com. -> 7obgmo062d9935unjnnj2su5otaj9334. +; example.com. -> b6fuorg741ufili49mg9j4328ig53sqg. +; proof that there is no DS here. +; ce: +b6fuorg741ufili49mg9j4328ig53sqg.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd b6fuorg741ufili49mg9j4328ig53sqh NS SOA DNSKEY NSEC3PARAM RRSIG +b6fuorg741ufili49mg9j4328ig53sqg.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. AKHQ0gnNP5WDab1yqbd+Bt12CSSff88sqeDR40dvhiWOcYA8mmyjYNA= + +; span around sub.example.com. from previous delegation in nsec3-chain +; note it does not cover sub.example.com. +6obgmo062d9935unjnnj2su5otaj9334.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd 7r1f0ieoutlnjc03meng9e3bn2n0o9pd NS DS RRSIG +6obgmo062d9935unjnnj2su5otaj9334.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. ABQZ49PmeXGxUmMebbKcYI/Y3mhMdlHmshohKTbGhEsNF11OjPYmr9c= + +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.10 +ENTRY_END + +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.10 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR REFUSED +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 1.2.3.123 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.foo.example.com. IN A +SECTION ANSWER +www.foo.example.com. IN A 1.2.3.124 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.foo.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.foo.example.com. IN A +SECTION ANSWER +www.foo.example.com. IN A 1.2.3.124 +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +STEP 20 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 30 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 1.2.3.123 +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nsec3_wcany.rpl b/testdata/val_nsec3_wcany.rpl new file mode 100644 index 00000000000..ba8ce2c3cd3 --- /dev/null +++ b/testdata/val_nsec3_wcany.rpl @@ -0,0 +1,159 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with NSEC3 wilcard qtype ANY response. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN ANY +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN ANY +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN ANY +SECTION ANSWER +; *.example.com. IN A 1.2.3.123 +; *.example.com. IN AAAA ::5 +; *.example.com. IN MX 10 mail.example.com. +www.example.com. 3600 IN MX 10 mail.example.com. +www.example.com. 3600 IN RRSIG MX 3 2 3600 20070926135752 20070829135752 2854 example.com. MCwCFBncNdBkFSOTvqF7RtZ4bZuojWF8AhQlEv7Iw8BpQ7YkZQidRDJdx+BrGw== ;{id = 2854} +www.example.com. 3600 IN AAAA ::5 +www.example.com. 3600 IN RRSIG AAAA 3 2 3600 20070926135752 20070829135752 2854 example.com. MC0CFCWSH0WGURY1mQwpL08SN1XF9p39AhUAgwbFk0frQC62UxhNfn4pu7iq8q4= ;{id = 2854} +www.example.com. 3600 IN A 1.2.3.123 +www.example.com. 3600 IN RRSIG A 3 2 3600 20070926135752 20070829135752 2854 example.com. MCwCFCypz6dZfecwPbJ3BKrXEA7jw5kkAhRz1vprGL0idsKos8szoybKXe17Jw== ;{id = 2854} + +SECTION AUTHORITY +; next closer name, H(www.example.com.) = s1unhcti19bkdr98fegs0v46mbu3t4m3. +s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 123 aabb00123456bbccdd s1unhcti19bkdr98fegs0v46mbu3t4m4 A MX RRSIG +s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFFSH4klZKke48dYyddYDj17gjTS0AhUAltWicpFLWqW98/Af9Qlx70MH8o4= ;{id = 2854} + +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN ANY +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN ANY +SECTION ANSWER +www.example.com. 3600 IN MX 10 mail.example.com. +www.example.com. 3600 IN RRSIG MX 3 2 3600 20070926135752 20070829135752 2854 example.com. MCwCFBncNdBkFSOTvqF7RtZ4bZuojWF8AhQlEv7Iw8BpQ7YkZQidRDJdx+BrGw== ;{id = 2854} +www.example.com. 3600 IN AAAA ::5 +www.example.com. 3600 IN RRSIG AAAA 3 2 3600 20070926135752 20070829135752 2854 example.com. MC0CFCWSH0WGURY1mQwpL08SN1XF9p39AhUAgwbFk0frQC62UxhNfn4pu7iq8q4= ;{id = 2854} +www.example.com. 3600 IN A 1.2.3.123 +www.example.com. 3600 IN RRSIG A 3 2 3600 20070926135752 20070829135752 2854 example.com. MCwCFCypz6dZfecwPbJ3BKrXEA7jw5kkAhRz1vprGL0idsKos8szoybKXe17Jw== ;{id = 2854} +SECTION AUTHORITY +s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 123 aabb00123456bbccdd s1unhcti19bkdr98fegs0v46mbu3t4m4 A MX RRSIG +s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFFSH4klZKke48dYyddYDj17gjTS0AhUAltWicpFLWqW98/Af9Qlx70MH8o4= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nsec3_wcany_nodeny.rpl b/testdata/val_nsec3_wcany_nodeny.rpl new file mode 100644 index 00000000000..9215ccc04a4 --- /dev/null +++ b/testdata/val_nsec3_wcany_nodeny.rpl @@ -0,0 +1,168 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with NSEC3 wilcard qtype ANY without denial. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN ANY +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN ANY +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN A +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN AAAA +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN ANY +SECTION ANSWER +; *.example.com. IN A 1.2.3.123 +; *.example.com. IN AAAA ::5 +; *.example.com. IN MX 10 mail.example.com. +www.example.com. 3600 IN MX 10 mail.example.com. +www.example.com. 3600 IN RRSIG MX 3 2 3600 20070926135752 20070829135752 2854 example.com. MCwCFBncNdBkFSOTvqF7RtZ4bZuojWF8AhQlEv7Iw8BpQ7YkZQidRDJdx+BrGw== ;{id = 2854} +www.example.com. 3600 IN AAAA ::5 +www.example.com. 3600 IN RRSIG AAAA 3 2 3600 20070926135752 20070829135752 2854 example.com. MC0CFCWSH0WGURY1mQwpL08SN1XF9p39AhUAgwbFk0frQC62UxhNfn4pu7iq8q4= ;{id = 2854} +www.example.com. 3600 IN A 1.2.3.123 +www.example.com. 3600 IN RRSIG A 3 2 3600 20070926135752 20070829135752 2854 example.com. MCwCFCypz6dZfecwPbJ3BKrXEA7jw5kkAhRz1vprGL0idsKos8szoybKXe17Jw== ;{id = 2854} + +SECTION AUTHORITY +; no qname denial! +; next closer name, H(www.example.com.) = s1unhcti19bkdr98fegs0v46mbu3t4m3. +;s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 123 aabb00123456bbccdd s1unhcti19bkdr98fegs0v46mbu3t4m4 A MX RRSIG +;s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFFSH4klZKke48dYyddYDj17gjTS0AhUAltWicpFLWqW98/Af9Qlx70MH8o4= ;{id = 2854} + +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN ANY +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN ANY +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nx.rpl b/testdata/val_nx.rpl new file mode 100644 index 00000000000..885dc42a3fe --- /dev/null +++ b/testdata/val_nx.rpl @@ -0,0 +1,152 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with nxdomain response + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFCNGZ+/OfElYQMCZ77O9Lw9rhk7PAhUAmDcvTAst6Bq83qPq3r6c/Dm1nFc= ;{id = 2854} +; wildcard denial +example.com. IN NSEC abc.example.com. SOA NS DNSKEY NSEC RRSIG +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFHV2IBWyTmDJvZ+sT+WsGrJX0op/AhQkAijjnjPAtx/tNub2FAGqcexJSg== ;{id = 2854} +; qname denial +wab.example.com. IN NSEC wzz.example.com. A NSEC RRSIG +wab.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFG5DZSEIZC088rjcB1e6sQx8nQz4AhUAtQ09tP1YYLJkhL/Wg1KV2pW4Ivk= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NXDOMAIN +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFCNGZ+/OfElYQMCZ77O9Lw9rhk7PAhUAmDcvTAst6Bq83qPq3r6c/Dm1nFc= ;{id = 2854} +example.com. IN NSEC abc.example.com. SOA NS DNSKEY NSEC RRSIG +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFHV2IBWyTmDJvZ+sT+WsGrJX0op/AhQkAijjnjPAtx/tNub2FAGqcexJSg== ;{id = 2854} +wab.example.com. IN NSEC wzz.example.com. A NSEC RRSIG +wab.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFG5DZSEIZC088rjcB1e6sQx8nQz4AhUAtQ09tP1YYLJkhL/Wg1KV2pW4Ivk= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nx_nodeny.rpl b/testdata/val_nx_nodeny.rpl new file mode 100644 index 00000000000..9c1e0bb3d76 --- /dev/null +++ b/testdata/val_nx_nodeny.rpl @@ -0,0 +1,162 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with nxdomain response missing qname denial + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN A +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN AAAA +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFCNGZ+/OfElYQMCZ77O9Lw9rhk7PAhUAmDcvTAst6Bq83qPq3r6c/Dm1nFc= ;{id = 2854} +; wildcard denial +example.com. IN NSEC abc.example.com. SOA NS DNSKEY NSEC RRSIG +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFHV2IBWyTmDJvZ+sT+WsGrJX0op/AhQkAijjnjPAtx/tNub2FAGqcexJSg== ;{id = 2854} +; qname denial +;wab.example.com. IN NSEC wzz.example.com. A NSEC RRSIG +;wab.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFG5DZSEIZC088rjcB1e6sQx8nQz4AhUAtQ09tP1YYLJkhL/Wg1KV2pW4Ivk= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nx_nowc.rpl b/testdata/val_nx_nowc.rpl new file mode 100644 index 00000000000..9b8880d77b6 --- /dev/null +++ b/testdata/val_nx_nowc.rpl @@ -0,0 +1,162 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with nxdomain response missing wildcard denial + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN A +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN AAAA +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFCNGZ+/OfElYQMCZ77O9Lw9rhk7PAhUAmDcvTAst6Bq83qPq3r6c/Dm1nFc= ;{id = 2854} +; wildcard denial +;example.com. IN NSEC abc.example.com. SOA NS DNSKEY NSEC RRSIG +;example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFHV2IBWyTmDJvZ+sT+WsGrJX0op/AhQkAijjnjPAtx/tNub2FAGqcexJSg== ;{id = 2854} +; qname denial +wab.example.com. IN NSEC wzz.example.com. A NSEC RRSIG +wab.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFG5DZSEIZC088rjcB1e6sQx8nQz4AhUAtQ09tP1YYLJkhL/Wg1KV2pW4Ivk= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nx_nsec3_collision.rpl b/testdata/val_nx_nsec3_collision.rpl new file mode 100644 index 00000000000..60ddb1c64ef --- /dev/null +++ b/testdata/val_nx_nsec3_collision.rpl @@ -0,0 +1,185 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with nxdomain NSEC3 with a collision. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFCNGZ+/OfElYQMCZ77O9Lw9rhk7PAhUAmDcvTAst6Bq83qPq3r6c/Dm1nFc= ;{id = 2854} + +; some collisions added here. Say different chains are being signed +; and some colliding NSEC3 RRs are generated. + +; closest encloser, H(example.com) = 6md8numosa4q9ugkffdo1bmm82t5j39s +; for 1 1 8 - +6md8numosa4q9ugkffdo1bmm82t5j39s.example.com. NSEC3 1 1 123 aabb00123456bbccdd 6md8numosa4q9ugkffdo1bmm82t5j49s A RRSIG +6md8numosa4q9ugkffdo1bmm82t5j39s.example.com. NSEC3 1 1 8 - 6md8numosa4q9ugkffdo1bmm82t5j49s SOA NS MX DNSKEY RRSIG +6md8numosa4q9ugkffdo1bmm82t5j39s.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MCwCFHndWrEEbuzezs/4lxeiMgEuUsUbAhR72gJgd/Zmhf80yoxCauw9k5OkCw== ;{id = 2854} + +; wildcard denial, H(*.example.com.) = 4f3cnt8cu22tngec382jj4gde4rb47ub +; for 1 1 0 - +4f3cnt8cu22tngec382jj4gde4rb46ub.example.com. NSEC3 1 1 18 - 4f3cnt8cu22tngec382jj4gde4rb87ub A RRSIG +4f3cnt8cu22tngec382jj4gde4rb46ub.example.com. NSEC3 1 1 0 - 4f3cnt8cu22tngec382jj4gde4rb48ub A MX RRSIG +4f3cnt8cu22tngec382jj4gde4rb46ub.example.com. NSEC3 1 1 19 - 4f3cnt8cu22tngec382jj4gde4rb87ub A RRSIG +4f3cnt8cu22tngec382jj4gde4rb46ub.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MCwCFDRwji51WCXJg7W/3+Jx586af5qgAhQPxHegtzu1I/QbvCNrOOON05N1rw== ;{id = 2854} + +; next closer name, H(www.example.com.) = s1unhcti19bkdr98fegs0v46mbu3t4m3. +; for 1 1 123 aaabb... +s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 18 - s1unhcti19bkdr98fegs0v46mbu3t4m4 A RRSIG +s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 19 - s1unhcti19bkdr98fegs0v46mbu3t4m4 A RRSIG +s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 20 00 s1unhcti19bkdr98fegs0v46mbu3t4m4 A RRSIG +s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 123 aabb00123456bbccdd s1unhcti19bkdr98fegs0v46mbu3t4m4 A MX RRSIG +s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 20 01 s1unhcti19bkdr98fegs0v46mbu3t4m4 A RRSIG +s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 20 02 s1unhcti19bkdr98fegs0v46mbu3t4m4 A RRSIG +s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 20 03 s1unhcti19bkdr98fegs0v46mbu3t4m4 A RRSIG +s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MCwCFDLy4GbR8ZaKHATVJGnGxzpsuq60AhQ1/pRbXi1ZbcYohzHgWzNC50fC5A== ;{id = 2854} + +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NXDOMAIN +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFCNGZ+/OfElYQMCZ77O9Lw9rhk7PAhUAmDcvTAst6Bq83qPq3r6c/Dm1nFc= ;{id = 2854} +6md8numosa4q9ugkffdo1bmm82t5j39s.example.com. NSEC3 1 1 123 aabb00123456bbccdd 6md8numosa4q9ugkffdo1bmm82t5j49s A RRSIG +6md8numosa4q9ugkffdo1bmm82t5j39s.example.com. NSEC3 1 1 8 - 6md8numosa4q9ugkffdo1bmm82t5j49s SOA NS MX DNSKEY RRSIG +6md8numosa4q9ugkffdo1bmm82t5j39s.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MCwCFHndWrEEbuzezs/4lxeiMgEuUsUbAhR72gJgd/Zmhf80yoxCauw9k5OkCw== ;{id = 2854} +4f3cnt8cu22tngec382jj4gde4rb46ub.example.com. NSEC3 1 1 18 - 4f3cnt8cu22tngec382jj4gde4rb87ub A RRSIG +4f3cnt8cu22tngec382jj4gde4rb46ub.example.com. NSEC3 1 1 0 - 4f3cnt8cu22tngec382jj4gde4rb48ub A MX RRSIG +4f3cnt8cu22tngec382jj4gde4rb46ub.example.com. NSEC3 1 1 19 - 4f3cnt8cu22tngec382jj4gde4rb87ub A RRSIG +4f3cnt8cu22tngec382jj4gde4rb46ub.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MCwCFDRwji51WCXJg7W/3+Jx586af5qgAhQPxHegtzu1I/QbvCNrOOON05N1rw== ;{id = 2854} +s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 18 - s1unhcti19bkdr98fegs0v46mbu3t4m4 A RRSIG +s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 19 - s1unhcti19bkdr98fegs0v46mbu3t4m4 A RRSIG +s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 20 00 s1unhcti19bkdr98fegs0v46mbu3t4m4 A RRSIG +s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 123 aabb00123456bbccdd s1unhcti19bkdr98fegs0v46mbu3t4m4 A MX RRSIG +s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 20 01 s1unhcti19bkdr98fegs0v46mbu3t4m4 A RRSIG +s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 20 02 s1unhcti19bkdr98fegs0v46mbu3t4m4 A RRSIG +s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 20 03 s1unhcti19bkdr98fegs0v46mbu3t4m4 A RRSIG +s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MCwCFDLy4GbR8ZaKHATVJGnGxzpsuq60AhQ1/pRbXi1ZbcYohzHgWzNC50fC5A== ;{id = 2854} + +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nx_nsec3_params.rpl b/testdata/val_nx_nsec3_params.rpl new file mode 100644 index 00000000000..f25245a0b6c --- /dev/null +++ b/testdata/val_nx_nsec3_params.rpl @@ -0,0 +1,161 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with nxdomain NSEC3 several parameters. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFCNGZ+/OfElYQMCZ77O9Lw9rhk7PAhUAmDcvTAst6Bq83qPq3r6c/Dm1nFc= ;{id = 2854} + +; closest encloser, H(example.com). +6md8numosa4q9ugkffdo1bmm82t5j39s.example.com. NSEC3 1 1 8 - 6md8numosa4q9ugkffdo1bmm82t5j49s SOA NS MX DNSKEY RRSIG +6md8numosa4q9ugkffdo1bmm82t5j39s.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCz/LkFOFcaQzVnyySW9ZoVUnxh7gIUdxyS9vqVDzo8pGhFU+3YogN2ZRk= ;{id = 2854} + +; wildcard denial, H(*.example.com.) = 4f3cnt8cu22tngec382jj4gde4rb47ub +4f3cnt8cu22tngec382jj4gde4rb46ub.example.com. NSEC3 1 1 0 - 4f3cnt8cu22tngec382jj4gde4rb48ub A MX RRSIG +4f3cnt8cu22tngec382jj4gde4rb46ub.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MCwCFHS+i/OB/V/gYmS1eQTXieXIXGjsAhQQ0Ql7TW/hsUklrb0DfoyhVPG95Q== ;{id = 2854} + +; next closer name, H(www.example.com.) = s1unhcti19bkdr98fegs0v46mbu3t4m3. +s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 123 aabb00123456bbccdd s1unhcti19bkdr98fegs0v46mbu3t4m4 A MX RRSIG +s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFFSH4klZKke48dYyddYDj17gjTS0AhUAltWicpFLWqW98/Af9Qlx70MH8o4= ;{id = 2854} + +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NXDOMAIN +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFCNGZ+/OfElYQMCZ77O9Lw9rhk7PAhUAmDcvTAst6Bq83qPq3r6c/Dm1nFc= ;{id = 2854} +6md8numosa4q9ugkffdo1bmm82t5j39s.example.com. NSEC3 1 1 8 - 6md8numosa4q9ugkffdo1bmm82t5j49s SOA NS MX DNSKEY RRSIG +6md8numosa4q9ugkffdo1bmm82t5j39s.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCz/LkFOFcaQzVnyySW9ZoVUnxh7gIUdxyS9vqVDzo8pGhFU+3YogN2ZRk= ;{id = 2854} +4f3cnt8cu22tngec382jj4gde4rb46ub.example.com. NSEC3 1 1 0 - 4f3cnt8cu22tngec382jj4gde4rb48ub A MX RRSIG +4f3cnt8cu22tngec382jj4gde4rb46ub.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MCwCFHS+i/OB/V/gYmS1eQTXieXIXGjsAhQQ0Ql7TW/hsUklrb0DfoyhVPG95Q== ;{id = 2854} +s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 123 aabb00123456bbccdd s1unhcti19bkdr98fegs0v46mbu3t4m4 A MX RRSIG +s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFFSH4klZKke48dYyddYDj17gjTS0AhUAltWicpFLWqW98/Af9Qlx70MH8o4= ;{id = 2854} + +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_nx_overreach.rpl b/testdata/val_nx_overreach.rpl new file mode 100644 index 00000000000..0e958f51490 --- /dev/null +++ b/testdata/val_nx_overreach.rpl @@ -0,0 +1,163 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with overreaching NSEC record + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN A +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN AAAA +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFCNGZ+/OfElYQMCZ77O9Lw9rhk7PAhUAmDcvTAst6Bq83qPq3r6c/Dm1nFc= ;{id = 2854} +; wildcard denial +example.com. IN NSEC abc.example.com. SOA NS DNSKEY NSEC RRSIG +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFHV2IBWyTmDJvZ+sT+WsGrJX0op/AhQkAijjnjPAtx/tNub2FAGqcexJSg== ;{id = 2854} +; qname denial +; The overreaching NSEC record; it tries to deny other .com zones! +wab.example.com. IN NSEC wzz.foo.com. A NSEC RRSIG +wab.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. AEimIB2N5u7AQOb5IBMnckASZ4MlhBxziJy+zVUjLov/s7q85j8eWQc= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_pos_truncns.rpl b/testdata/val_pos_truncns.rpl new file mode 100644 index 00000000000..63b7fd0fdbf --- /dev/null +++ b/testdata/val_pos_truncns.rpl @@ -0,0 +1,148 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with badly truncated positive response + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. + +; Truncated, no signature for NS record. +;;;example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +;;;SECTION ADDITIONAL +;;;ns.example.com. IN A 1.2.3.4 +;;;ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_positive.rpl b/testdata/val_positive.rpl new file mode 100644 index 00000000000..3c45c10a134 --- /dev/null +++ b/testdata/val_positive.rpl @@ -0,0 +1,150 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with positive response + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_positive_nosigs.rpl b/testdata/val_positive_nosigs.rpl new file mode 100644 index 00000000000..4ab6e54f0d0 --- /dev/null +++ b/testdata/val_positive_nosigs.rpl @@ -0,0 +1,179 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with positive response, signatures removed. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN A +SECTION ANSWER +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +ENTRY_END + +; barely valid nodata for AAAA +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +ENTRY_END + + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DS query for subzone +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN DS +SECTION ANSWER +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_positive_wc.rpl b/testdata/val_positive_wc.rpl new file mode 100644 index 00000000000..355e31581a1 --- /dev/null +++ b/testdata/val_positive_wc.rpl @@ -0,0 +1,159 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with positive wildcard response + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +; from +; *.example.com. IN A 10.20.30.40 +www.example.com. IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 3 2 3600 20070926135752 20070829135752 2854 example.com. MCwCFFi0g6v/20JyUxoQq7XM0iQnaMMOAhRjhUCLZjMqR1tj2MGGOgfhb1BSyw== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +; denies www.example.com. +ns.example.com. IN NSEC zork.example.com. A RRSIG NSEC +ns.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFGbrr95DAxBIRKFmr4BUm5OxXWMUAhUAsduS0iF2Pa7FagrbAPrJxZ2KPNs= ;{id = 2854} + +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 3 2 3600 20070926135752 20070829135752 2854 example.com. MCwCFFi0g6v/20JyUxoQq7XM0iQnaMMOAhRjhUCLZjMqR1tj2MGGOgfhb1BSyw== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +ns.example.com. IN NSEC zork.example.com. A RRSIG NSEC +ns.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFGbrr95DAxBIRKFmr4BUm5OxXWMUAhUAsduS0iF2Pa7FagrbAPrJxZ2KPNs= ;{id = 2854} + +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_positive_wc_nodeny.rpl b/testdata/val_positive_wc_nodeny.rpl new file mode 100644 index 00000000000..b0c1a542850 --- /dev/null +++ b/testdata/val_positive_wc_nodeny.rpl @@ -0,0 +1,166 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with positive wildcard without qname denial + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN A +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN AAAA +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +; from +; *.example.com. IN A 10.20.30.40 +www.example.com. IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 3 2 3600 20070926135752 20070829135752 2854 example.com. MCwCFFi0g6v/20JyUxoQq7XM0iQnaMMOAhRjhUCLZjMqR1tj2MGGOgfhb1BSyw== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +; denies www.example.com. +; ns.example.com. IN NSEC zork.example.com. A RRSIG NSEC +; ns.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFGbrr95DAxBIRKFmr4BUm5OxXWMUAhUAsduS0iF2Pa7FagrbAPrJxZ2KPNs= ;{id = 2854} + +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_qds_badanc.rpl b/testdata/val_qds_badanc.rpl new file mode 100644 index 00000000000..8fc6195caac --- /dev/null +++ b/testdata/val_qds_badanc.rpl @@ -0,0 +1,221 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with DS query and a bad anchor +; The anchor is the wrong side of the zone cut; no parent anchor. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +; response to DS query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION ANSWER +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 + +; response to DNSKEY priming query +; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899} +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +sub.example.com. IN DS +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION ANSWER +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_qds_oneanc.rpl b/testdata/val_qds_oneanc.rpl new file mode 100644 index 00000000000..9a0904084bc --- /dev/null +++ b/testdata/val_qds_oneanc.rpl @@ -0,0 +1,220 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with DS query and one anchor + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +; response to DS query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION ANSWER +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 + +; response to DNSKEY priming query +; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899} +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +sub.example.com. IN DS +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION ANSWER +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_qds_twoanc.rpl b/testdata/val_qds_twoanc.rpl new file mode 100644 index 00000000000..0d782895618 --- /dev/null +++ b/testdata/val_qds_twoanc.rpl @@ -0,0 +1,221 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + trust-anchor: "sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with DS query and two anchors + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +; response to DS query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION ANSWER +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 + +; response to DNSKEY priming query +; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899} +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +sub.example.com. IN DS +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION ANSWER +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_refer_unsignadd.rpl b/testdata/val_refer_unsignadd.rpl new file mode 100644 index 00000000000..93e87f619e1 --- /dev/null +++ b/testdata/val_refer_unsignadd.rpl @@ -0,0 +1,350 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + trust-anchor: "example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}" + val-override-date: "20070916134226" + access-control: 127.0.0.1 allow_snoop + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with a referral with unsigned additional +; but the additional record is from a signed zone, +; and a proper proof for no DS or DSNKEY types is forthcoming. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +; Skip .com, to provide unsigned referral A record for ns.example.net +; and go straight to example.com. +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.net IN A 1.2.3.5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.net IN A 1.2.3.5 +ENTRY_END +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926135752 20070829135752 2854 example.com. MCwCFEsWNXjGDFwH/0NGClonWUQlBaiFAhR/dt0asVj8M0VKs7PdTEKN/Y9i5w== ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to example.com. DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926135752 20070829135752 2854 example.com. MCwCFEsWNXjGDFwH/0NGClonWUQlBaiFAhR/dt0asVj8M0VKs7PdTEKN/Y9i5w== ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 11.12.13.14 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFC6+BbFcL95vH6SOhMLGotcBospIAhUAhjfof+1VY5GsCp5b9UOD7UydBzI= ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926135752 20070829135752 2854 example.com. MCwCFEsWNXjGDFwH/0NGClonWUQlBaiFAhR/dt0asVj8M0VKs7PdTEKN/Y9i5w== ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; example.com zone in ns.example.net. +; response to example.com. DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926135752 20070829135752 2854 example.com. MCwCFEsWNXjGDFwH/0NGClonWUQlBaiFAhR/dt0asVj8M0VKs7PdTEKN/Y9i5w== ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 11.12.13.14 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFC6+BbFcL95vH6SOhMLGotcBospIAhUAhjfof+1VY5GsCp5b9UOD7UydBzI= ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +; example.net zone in ns.example.net. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN DNSKEY +SECTION ANSWER +example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.net. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; deny DS and DNSKEY types +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN DS +SECTION AUTHORITY +example.net. IN SOA ns-pri.ripe.net. ops.ripe.net. 2007092101 3600 7200 1209600 7200 +example.net. 3600 IN RRSIG SOA 5 2 3600 20070926134150 20070829134150 30899 example.net. E1T+LAsAk7rtA6mnKRlgca5Lk+NJYUNNkfco1CrUp5IZZ1+QL7u7CINQBcndJkvoBwKhdVI8rz2LLW19wIywTw== ;{id = 30899} +ns.example.net IN NSEC ns-new.example.net. A AAAA RRSIG NSEC +ns.example.net. 3600 IN RRSIG NSEC 5 3 3600 20070926134150 20070829134150 30899 example.net. HLkPBWA8Hstub8e/zdp/A8xyI6+fnnMsA9oiZ20VBuSTaBknX0SXmVulNhVGfdmz9fYmYFUr1zjqvPFG+ErO8A== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN DNSKEY +SECTION AUTHORITY +example.net. IN SOA ns-pri.ripe.net. ops.ripe.net. 2007092101 3600 7200 1209600 7200 +example.net. 3600 IN RRSIG SOA 5 2 3600 20070926134150 20070829134150 30899 example.net. E1T+LAsAk7rtA6mnKRlgca5Lk+NJYUNNkfco1CrUp5IZZ1+QL7u7CINQBcndJkvoBwKhdVI8rz2LLW19wIywTw== ;{id = 30899} +ns.example.net IN NSEC ns-new.example.net. A RRSIG NSEC +ns.example.net. 3600 IN RRSIG NSEC 5 3 3600 20070926134150 20070829134150 30899 example.net. fAbDxuMP6lMqi71Wa9nsByG7buoJpfxyQhjps6HXOPzOC24UCCjdvZfZltlRy7Yrfrs28MjHwYEmHFmCeFpfPw== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION ANSWER +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION AUTHORITY +example.net. IN SOA ns-pri.ripe.net. ops.ripe.net. 2007092101 3600 7200 1209600 7200 +example.net. 3600 IN RRSIG SOA 5 2 3600 20070926134150 20070829134150 30899 example.net. E1T+LAsAk7rtA6mnKRlgca5Lk+NJYUNNkfco1CrUp5IZZ1+QL7u7CINQBcndJkvoBwKhdVI8rz2LLW19wIywTw== ;{id = 30899} +ns.example.net IN NSEC ns-new.example.net. A RRSIG NSEC +ns.example.net. 3600 IN RRSIG NSEC 5 3 3600 20070926134150 20070829134150 30899 example.net. fAbDxuMP6lMqi71Wa9nsByG7buoJpfxyQhjps6HXOPzOC24UCCjdvZfZltlRy7Yrfrs28MjHwYEmHFmCeFpfPw== ;{id = 30899} +ENTRY_END + +RANGE_END + +; prime cache with example.com. NS rrset. +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 11.12.13.14 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFC6+BbFcL95vH6SOhMLGotcBospIAhUAhjfof+1VY5GsCp5b9UOD7UydBzI= ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +; test nonrec referral validation +STEP 11 QUERY +ENTRY_BEGIN +REPLY DO +SECTION QUESTION +bla.example.com. IN A +ENTRY_END + +STEP 12 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RA AD NOERROR +SECTION QUESTION +bla.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns.example.net. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926135752 20070829135752 2854 example.com. MCwCFEsWNXjGDFwH/0NGClonWUQlBaiFAhR/dt0asVj8M0VKs7PdTEKN/Y9i5w== ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_referd.rpl b/testdata/val_referd.rpl new file mode 100644 index 00000000000..fe8900c0b88 --- /dev/null +++ b/testdata/val_referd.rpl @@ -0,0 +1,172 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + harden-referral-path: no + access-control: 127.0.0.1 allow_snoop + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with cache referral + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. AD8qRJvXxOtmSuy8Ogyo0roA294qOtNT2E1m05kSU0jbxN4qLYn0OmU= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +ENTRY_END +RANGE_END + +; first ask for +CD and get the data in the cache. +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD CD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 3 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA CD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +; now the data is in the cache, validate a referral from cache +; note, no recursion desired +STEP 5 QUERY +ENTRY_BEGIN +REPLY DO +SECTION QUESTION +bla.example.com. IN A +ENTRY_END + +STEP 6 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RA AD NOERROR +SECTION QUESTION +bla.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_referglue.rpl b/testdata/val_referglue.rpl new file mode 100644 index 00000000000..fd7e7caa5e8 --- /dev/null +++ b/testdata/val_referglue.rpl @@ -0,0 +1,297 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + directory: "" + access-control: 127.0.0.1 allow_snoop + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with cache referral with unsigned glue + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS ns2.sub.example.com. +example.com. 3600 IN RRSIG NS DSA 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCiyp/3hxwKS5QZPnjk36t16s4QTwIUI0m+MBVOAPacANrXXFKieyZd39o= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +ns2.sub.example.com. IN A 100.200.30.40 +ENTRY_END + +; referral, for all types +ENTRY_BEGIN +MATCH opcode qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns2.sub.example.com. IN A +SECTION AUTHORITY +sub.example.com. IN NS ns2.sub.example.com. +sub.example.com. IN NSEC tlib.example.com. NS RRSIG NSEC +sub.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. ABdrfr+eKT1syk2qFlV01wLOqQdvNMpEtPmGAM6CrtyQAje/ddXSi9A= ;{id = 2854} +ns2.sub.example.com. IN A 100.200.30.40 +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns2.sub.example.com. +example.com. 3600 IN RRSIG NS DSA 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCiyp/3hxwKS5QZPnjk36t16s4QTwIUI0m+MBVOAPacANrXXFKieyZd39o= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +ns2.sub.example.com. IN A 100.200.30.40 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns2.sub.example.com. +example.com. 3600 IN RRSIG NS DSA 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCiyp/3hxwKS5QZPnjk36t16s4QTwIUI0m+MBVOAPacANrXXFKieyZd39o= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +; This is from an unsigned subzone +ns2.sub.example.com. IN A 100.200.30.40 +ENTRY_END +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NSEC www.example.com. NS RRSIG NSEC +sub.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFEG4WWIYBDknWlr2d8S42UZHRuByAhRgnDELUAccGZTCVzG+xl/locivpA== ;{id = 2854} +ENTRY_END +RANGE_END + +; ns2.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 100.200.30.40 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. IN NS ns2.sub.example.com. +example.com. 3600 IN RRSIG NS DSA 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCiyp/3hxwKS5QZPnjk36t16s4QTwIUI0m+MBVOAPacANrXXFKieyZd39o= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns2.sub.example.com. +example.com. 3600 IN RRSIG NS DSA 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCiyp/3hxwKS5QZPnjk36t16s4QTwIUI0m+MBVOAPacANrXXFKieyZd39o= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns2.sub.example.com. +example.com. 3600 IN RRSIG NS DSA 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCiyp/3hxwKS5QZPnjk36t16s4QTwIUI0m+MBVOAPacANrXXFKieyZd39o= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +; This is from an unsigned subzone +ns2.sub.example.com. IN A 100.200.30.40 +ENTRY_END +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NSEC www.example.com. NS RRSIG NSEC +sub.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFEG4WWIYBDknWlr2d8S42UZHRuByAhRgnDELUAccGZTCVzG+xl/locivpA== ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns2.sub.example.com. IN A +SECTION ANSWER +ns2.sub.example.com. IN A 100.200.30.40 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns2.sub.example.com. IN AAAA +SECTION ANSWER +ENTRY_END + +RANGE_END + +; first ask for +CD and get the data in the cache. +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD CD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 3 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA CD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. IN NS ns2.sub.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +; already validated and thus stripped from the answer. +;ns2.sub.example.com. IN A 100.200.30.40 +ENTRY_END + +; now the data is in the cache, validate a referral from cache +; note, no recursion desired +STEP 5 QUERY +ENTRY_BEGIN +REPLY DO +SECTION QUESTION +bla.example.com. IN A +ENTRY_END + +STEP 6 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RA AD NOERROR +SECTION QUESTION +bla.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN NS ns2.sub.example.com. +example.com. 3600 IN RRSIG NS DSA 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCiyp/3hxwKS5QZPnjk36t16s4QTwIUI0m+MBVOAPacANrXXFKieyZd39o= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_rrsig.rpl b/testdata/val_rrsig.rpl new file mode 100644 index 00000000000..202d07ded47 --- /dev/null +++ b/testdata/val_rrsig.rpl @@ -0,0 +1,167 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with qtype RRSIG response + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query for A +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +ENTRY_END + +; RRSIG query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN RRSIG +SECTION ANSWER +;www.example.com. IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN RRSIG +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN RRSIG +SECTION ANSWER +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_secds.rpl b/testdata/val_secds.rpl new file mode 100644 index 00000000000..28be6142807 --- /dev/null +++ b/testdata/val_secds.rpl @@ -0,0 +1,211 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with secure delegation + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response to DNSKEY priming query +; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899} +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. 3600 IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_secds_nosig.rpl b/testdata/val_secds_nosig.rpl new file mode 100644 index 00000000000..5aeb47f93a5 --- /dev/null +++ b/testdata/val_secds_nosig.rpl @@ -0,0 +1,230 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with no signatures after secure delegation + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; barely valid nodata for AAAA +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +;sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +;ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; barely valid nodata for AAAA +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.sub.example.com. IN AAAA +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +;sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +;ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.sub.example.com. IN A +SECTION ANSWER +ns.sub.example.com. IN A 1.2.3.6 +;ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response to DNSKEY priming query +; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +;sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899} +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +;sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +;ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 11.11.11.11 +;www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_stub_noroot.rpl b/testdata/val_stub_noroot.rpl new file mode 100644 index 00000000000..cfa133b80a7 --- /dev/null +++ b/testdata/val_stub_noroot.rpl @@ -0,0 +1,83 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + trust-anchor: "lp0.eu. IN DNSKEY 257 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3" + val-override-date: "20100913111500" + ; the dlv anchor is completely ignored, but here to test that. + dlv-anchor: "dlv.isc.org. IN DNSKEY 257 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3" + +stub-zone: + name: "." + stub-addr: 81.187.81.187 +stub-zone: + name: "lp0.eu" + stub-addr: 81.2.80.65 + stub-prime: no +CONFIG_END + +SCENARIO_BEGIN Test validation of stub zone without root prime. + +; this server does not respond. (for the root) +RANGE_BEGIN 0 100 + ADDRESS 81.187.81.187 +ENTRY_BEGIN +MATCH +ADJUST copy_id copy_query +REPLY QR SERVFAIL +SECTION QUESTION +. IN NS +ENTRY_END +RANGE_END + +; lp0.eu server +RANGE_BEGIN 0 100 + ADDRESS 81.2.80.65 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +lp0.eu. IN DNSKEY +SECTION ANSWER +lp0.eu. 3600 IN DNSKEY 257 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30900 (ksk), size = 512b} +lp0.eu. 3600 IN RRSIG DNSKEY 5 2 3600 20101013111500 20100909111500 30900 lp0.eu. zWYOT1zmB2k7hMl7mke7k1UNp4lDveUxi2EnF0tW++j2/qJopiAAcFHBo2GOo88jHcLWycurf0Qo+YGXfFbpEg== ;{id = 30900} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +proxima.lp0.eu. IN A +SECTION ANSWER +proxima.lp0.eu. IN A 81.2.80.65 +proxima.lp0.eu. 3600 IN RRSIG A 5 3 3600 20101013111500 20100909111500 30900 lp0.eu. xwS3PLSlxh500pDYh/t6fnLzxQAra6n3nhzk4fVqLzwmneBIfcx4F/vO44wRzXSprz1UbMkVUcruTbQYlLFBEg== ;{id = 30900} +SECTION AUTHORITY +lp0.eu. IN NS proxima.lp0.eu. +lp0.eu. 3600 IN RRSIG NS 5 2 3600 20101013111500 20100909111500 30900 lp0.eu. KM7Zfwc1b0Ay8Ezer0ZAERPbmgGzKIrTfZMxzXzSkVx5DWirTtdgPTNVG/y9fkN4tUARNhElN2eb0ufb04Hdgw== ;{id = 30900} +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +proxima.lp0.eu. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +proxima.lp0.eu. IN A +SECTION ANSWER +proxima.lp0.eu. IN A 81.2.80.65 +proxima.lp0.eu. 3600 IN RRSIG A 5 3 3600 20101013111500 20100909111500 30900 lp0.eu. xwS3PLSlxh500pDYh/t6fnLzxQAra6n3nhzk4fVqLzwmneBIfcx4F/vO44wRzXSprz1UbMkVUcruTbQYlLFBEg== ;{id = 30900} +SECTION AUTHORITY +lp0.eu. IN NS proxima.lp0.eu. +lp0.eu. 3600 IN RRSIG NS 5 2 3600 20101013111500 20100909111500 30900 lp0.eu. KM7Zfwc1b0Ay8Ezer0ZAERPbmgGzKIrTfZMxzXzSkVx5DWirTtdgPTNVG/y9fkN4tUARNhElN2eb0ufb04Hdgw== ;{id = 30900} +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_stubds.rpl b/testdata/val_stubds.rpl new file mode 100644 index 00000000000..a79c5b6d1ae --- /dev/null +++ b/testdata/val_stubds.rpl @@ -0,0 +1,456 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +stub-zone: + name: "sub.example.com" + stub-addr: 1.2.3.6 +CONFIG_END + +SCENARIO_BEGIN Test stub with DS query +; The stub zone is linked validly with a DS to the public internet zone. +; unbound just has to be able to ask the DS from the right server (not +; from the stub). + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response for DS of sub.example.com. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION ANSWER +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response to DNSKEY priming query +; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899} +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response for qtype DS. This is not available here. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR SERVFAIL +SECTION QUESTION +sub.example.com. IN DS +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. 3600 IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +stub-zone: + name: "sub.example.com" + stub-addr: 1.2.3.6 +CONFIG_END + +SCENARIO_BEGIN Test stub with DS query +; The stub zone is linked validly with a DS to the public internet zone. +; unbound just has to be able to ask the DS from the right server (not +; from the stub). + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response for DS of sub.example.com. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION ANSWER +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response to DNSKEY priming query +; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899} +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response for qtype DS. This is not available here. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR SERVFAIL +SECTION QUESTION +sub.example.com. IN DS +SECTION ANSWER +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. 3600 IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_ta_algo_dnskey.rpl b/testdata/val_ta_algo_dnskey.rpl new file mode 100644 index 00000000000..21cbdab7d78 --- /dev/null +++ b/testdata/val_ta_algo_dnskey.rpl @@ -0,0 +1,181 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJIIs70j+sDS/UT2QRp61SE7S3EEXopNXoFE73JLRmvpi/UrOO/Vz4Se6wXv/CYCKjGw06U4WRgRYXcpEhJROyNapmdIKSxhOzfLVE1gqA0PweZR8dtY3aNQSRn3sPpwJr6Mi/PqQKAMMrZ9ckJpf1+bQMOOvxgzz2U1GS18b3yZKcgTMEaJzd/GZYzi/BN2DzQ0MsrSwYXfsNLFOBbs8PJMW4LYIxeeOe6rUgkWOF7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}" + trust-anchor: "example.com. 3600 IN DS 30899 5 1 d4bf9d2e10f6d76840d42ef5913022abcd0bf512" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with multiple algorithm trust anchor + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +example.com. 3600 IN RRSIG NS 5 2 3600 20070926134150 20070829134150 30899 example.com. YTqtYba73HIOQuPr5oDyIX9pfmz1ybEBjwlD/jUgcPmFINUOZ9FeqG6ywgRKwn4AizkKTK00p1sxZYMKxl91wg== ;{id = 30899} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ns.example.com. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.com. Dn1ziMKrc3NdJkSv8g61Y9WNk3+BAuwCwnYzAZiHmkejkSCPViLJN7+f4Conp9l8LkTl50ZnLgoYrrUYNhMj6w== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +example.com. 3600 IN RRSIG NS 5 2 3600 20070926134150 20070829134150 30899 example.com. YTqtYba73HIOQuPr5oDyIX9pfmz1ybEBjwlD/jUgcPmFINUOZ9FeqG6ywgRKwn4AizkKTK00p1sxZYMKxl91wg== ;{id = 30899} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ns.example.com. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.com. Dn1ziMKrc3NdJkSv8g61Y9WNk3+BAuwCwnYzAZiHmkejkSCPViLJN7+f4Conp9l8LkTl50ZnLgoYrrUYNhMj6w== ;{id = 30899} +ENTRY_END + + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJIIs70j+sDS/UT2QRp61SE7S3EEXopNXoFE73JLRmvpi/UrOO/Vz4Se6wXv/CYCKjGw06U4WRgRYXcpEhJROyNapmdIKSxhOzfLVE1gqA0PweZR8dtY3aNQSRn3sPpwJr6Mi/PqQKAMMrZ9ckJpf1+bQMOOvxgzz2U1GS18b3yZKcgTMEaJzd/GZYzi/BN2DzQ0MsrSwYXfsNLFOBbs8PJMW4LYIxeeOe6rUgkWOF7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 512b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134150 20070829134150 2854 example.com. AKIIYDOGHogglFqJK94ZtOnF7EfGikgAyloMNRSMCrQgFaFkmcOyjrc= ;{id = 2854} +example.com. 3600 IN RRSIG DNSKEY 5 2 3600 20070926134150 20070829134150 30899 example.com. J55fsz1GGMnngc4r50xvXDUdaVMlfcLKLVsfMhwNLF+ERac5XV/lLRAc/aSER+qQdsSo0CrjYjy1wat7YQpDAA== ;{id = 30899} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +example.com. 3600 IN RRSIG NS 5 2 3600 20070926134150 20070829134150 30899 example.com. YTqtYba73HIOQuPr5oDyIX9pfmz1ybEBjwlD/jUgcPmFINUOZ9FeqG6ywgRKwn4AizkKTK00p1sxZYMKxl91wg== ;{id = 30899} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ns.example.com. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.com. Dn1ziMKrc3NdJkSv8g61Y9WNk3+BAuwCwnYzAZiHmkejkSCPViLJN7+f4Conp9l8LkTl50ZnLgoYrrUYNhMj6w== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +www.example.com. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.com. JNWECShNE+nCLQwOXJJ3xpUkh2G+FCh5nk8uYAHIVQRse/BIvCMSlvRrtVyw9RnXvk5RR2bEgN0pRdLWW7ug5Q== ;{id = 30899} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +example.com. 3600 IN RRSIG NS 5 2 3600 20070926134150 20070829134150 30899 example.com. YTqtYba73HIOQuPr5oDyIX9pfmz1ybEBjwlD/jUgcPmFINUOZ9FeqG6ywgRKwn4AizkKTK00p1sxZYMKxl91wg== ;{id = 30899} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +ns.example.com. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.com. Dn1ziMKrc3NdJkSv8g61Y9WNk3+BAuwCwnYzAZiHmkejkSCPViLJN7+f4Conp9l8LkTl50ZnLgoYrrUYNhMj6w== ;{id = 30899} +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.com. JNWECShNE+nCLQwOXJJ3xpUkh2G+FCh5nk8uYAHIVQRse/BIvCMSlvRrtVyw9RnXvk5RR2bEgN0pRdLWW7ug5Q== ;{id = 30899} +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +example.com. 3600 IN RRSIG NS 5 2 3600 20070926134150 20070829134150 30899 example.com. YTqtYba73HIOQuPr5oDyIX9pfmz1ybEBjwlD/jUgcPmFINUOZ9FeqG6ywgRKwn4AizkKTK00p1sxZYMKxl91wg== ;{id = 30899} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +ns.example.com. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.com. Dn1ziMKrc3NdJkSv8g61Y9WNk3+BAuwCwnYzAZiHmkejkSCPViLJN7+f4Conp9l8LkTl50ZnLgoYrrUYNhMj6w== ;{id = 30899} +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_ta_algo_missing.rpl b/testdata/val_ta_algo_missing.rpl new file mode 100644 index 00000000000..3baeabfd720 --- /dev/null +++ b/testdata/val_ta_algo_missing.rpl @@ -0,0 +1,171 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJIIs70j+sDS/UT2QRp61SE7S3EEXopNXoFE73JLRmvpi/UrOO/Vz4Se6wXv/CYCKjGw06U4WRgRYXcpEhJROyNapmdIKSxhOzfLVE1gqA0PweZR8dtY3aNQSRn3sPpwJr6Mi/PqQKAMMrZ9ckJpf1+bQMOOvxgzz2U1GS18b3yZKcgTMEaJzd/GZYzi/BN2DzQ0MsrSwYXfsNLFOBbs8PJMW4LYIxeeOe6rUgkWOF7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}" + trust-anchor: "example.com. 3600 IN DS 30899 5 1 d4bf9d2e10f6d76840d42ef5913022abcd0bf512" + trust-anchor: "example.com. 3600 IN DS 30899 7 1 d4bf9d2e10f6d76840d42ef5913022abcd0bf512" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with multiple algorithm missing one + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +example.com. 3600 IN RRSIG NS 5 2 3600 20070926134150 20070829134150 30899 example.com. YTqtYba73HIOQuPr5oDyIX9pfmz1ybEBjwlD/jUgcPmFINUOZ9FeqG6ywgRKwn4AizkKTK00p1sxZYMKxl91wg== ;{id = 30899} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ns.example.com. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.com. Dn1ziMKrc3NdJkSv8g61Y9WNk3+BAuwCwnYzAZiHmkejkSCPViLJN7+f4Conp9l8LkTl50ZnLgoYrrUYNhMj6w== ;{id = 30899} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +example.com. 3600 IN RRSIG NS 5 2 3600 20070926134150 20070829134150 30899 example.com. YTqtYba73HIOQuPr5oDyIX9pfmz1ybEBjwlD/jUgcPmFINUOZ9FeqG6ywgRKwn4AizkKTK00p1sxZYMKxl91wg== ;{id = 30899} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ns.example.com. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.com. Dn1ziMKrc3NdJkSv8g61Y9WNk3+BAuwCwnYzAZiHmkejkSCPViLJN7+f4Conp9l8LkTl50ZnLgoYrrUYNhMj6w== ;{id = 30899} +ENTRY_END + + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJIIs70j+sDS/UT2QRp61SE7S3EEXopNXoFE73JLRmvpi/UrOO/Vz4Se6wXv/CYCKjGw06U4WRgRYXcpEhJROyNapmdIKSxhOzfLVE1gqA0PweZR8dtY3aNQSRn3sPpwJr6Mi/PqQKAMMrZ9ckJpf1+bQMOOvxgzz2U1GS18b3yZKcgTMEaJzd/GZYzi/BN2DzQ0MsrSwYXfsNLFOBbs8PJMW4LYIxeeOe6rUgkWOF7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 512b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134150 20070829134150 2854 example.com. AKIIYDOGHogglFqJK94ZtOnF7EfGikgAyloMNRSMCrQgFaFkmcOyjrc= ;{id = 2854} +example.com. 3600 IN RRSIG DNSKEY 5 2 3600 20070926134150 20070829134150 30899 example.com. J55fsz1GGMnngc4r50xvXDUdaVMlfcLKLVsfMhwNLF+ERac5XV/lLRAc/aSER+qQdsSo0CrjYjy1wat7YQpDAA== ;{id = 30899} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +example.com. 3600 IN RRSIG NS 5 2 3600 20070926134150 20070829134150 30899 example.com. YTqtYba73HIOQuPr5oDyIX9pfmz1ybEBjwlD/jUgcPmFINUOZ9FeqG6ywgRKwn4AizkKTK00p1sxZYMKxl91wg== ;{id = 30899} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ns.example.com. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.com. Dn1ziMKrc3NdJkSv8g61Y9WNk3+BAuwCwnYzAZiHmkejkSCPViLJN7+f4Conp9l8LkTl50ZnLgoYrrUYNhMj6w== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +www.example.com. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.com. JNWECShNE+nCLQwOXJJ3xpUkh2G+FCh5nk8uYAHIVQRse/BIvCMSlvRrtVyw9RnXvk5RR2bEgN0pRdLWW7ug5Q== ;{id = 30899} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +example.com. 3600 IN RRSIG NS 5 2 3600 20070926134150 20070829134150 30899 example.com. YTqtYba73HIOQuPr5oDyIX9pfmz1ybEBjwlD/jUgcPmFINUOZ9FeqG6ywgRKwn4AizkKTK00p1sxZYMKxl91wg== ;{id = 30899} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +ns.example.com. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.com. Dn1ziMKrc3NdJkSv8g61Y9WNk3+BAuwCwnYzAZiHmkejkSCPViLJN7+f4Conp9l8LkTl50ZnLgoYrrUYNhMj6w== ;{id = 30899} +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_twocname.rpl b/testdata/val_twocname.rpl new file mode 100644 index 00000000000..4474d71f856 --- /dev/null +++ b/testdata/val_twocname.rpl @@ -0,0 +1,132 @@ +; config options +server: + trust-anchor: "ORG. DS 21366 7 1 E6C1716CFB6BDC84E84CE1AB5510DAC69173B5B2" + val-override-date: "20091116100204" + +forward-zone: + name: "." + forward-addr: 192.0.2.1 +CONFIG_END + +SCENARIO_BEGIN Test validator with unsigned CNAME to signed CNAME to data + +RANGE_BEGIN 0 100 + ADDRESS 192.0.2.1 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +k.root-servers.org. IN A +SECTION ANSWER +k.root-servers.org. 3600 IN CNAME www.ripe.net. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.ripe.net. IN A +SECTION ANSWER +www.ripe.net. 900 IN CNAME aquila-www.ripe.net. +www.ripe.net. 900 IN RRSIG CNAME 5 3 900 20091216060007 20091116060007 19386 ripe.net. NjCpVZC/LLnoV1pa91GSL9SP65n7eFKoe/OcuKzUPHumXIDrXnE23F1rNfbjYpVrQDEsG6iInI7Edh2MCS4NI4tLwrytEDgCX7ZnqIMIOV2/gJa5ZkLlmVT71Agnfi788q7ozEq14zlhY+brD5kyBiEcfOhH/qkX+zJuGdt1AcQwMxYn/GQ0Z32k5ulBnzrIFWObBksO ;{id = 19386} +SECTION AUTHORITY +ripe.net. 172800 IN NS ns3.nic.fr. +ripe.net. 172800 IN NS sunic.sunet.se. +ripe.net. 172800 IN NS ns-pri.ripe.net. +ripe.net. 172800 IN NS sns-pb.isc.org. +ripe.net. 172800 IN RRSIG NS 5 2 172800 20091216060007 20091116060007 19386 ripe.net. Km2zmkvPOjRddE+SlFBokj2QVroW/R8D2C6u6uCtFI5HVLZTV+oxrIw1ZYYWwe/Jf2CpVBzh3P6iHtWvojM8DHhfkO84wsO33ssqzIzq7e8nDOinqeeGB7yyl642xHCt0jObRewX1hU6Deubs42pFZmO6YKL8Tx6Jb5oe2yyoVebv4bX2qLoEPFw9plE0VavfD397Y4g ;{id = 19386} +SECTION ADDITIONAL +ns-pri.ripe.net. 172800 IN A 193.0.0.195 +ns-pri.ripe.net. 172800 IN AAAA 2001:610:240:0:53::3 +ns-pri.ripe.net. 172800 IN RRSIG A 5 3 172800 20091216060007 20091116060007 19386 ripe.net. BRxWwUNDivDxXnrPlj3/VPUBrf/bk8tKljRG0pQ/7XucTUMR9ae1huNVTC+FTrfZjggqU9/PZlyJ9TwI1lp7J1lEua1mByCHObzHlO7Cq/m7sjZ9cFvpIm6ke2c+xxjs3X8mHsiyftSsCCSvB43DLhgcJtib6QZlCpFxa4Y3sg1fx+1GENrbKlcuJGGqkdrAw0irvKEv ;{id = 19386} +ns-pri.ripe.net. 172800 IN RRSIG AAAA 5 3 172800 20091216060007 20091116060007 19386 ripe.net. Ngd/GLGHakPj1A4rna19OPFpMPVSgCj7CgBtsuwjGwurMFEje4F4miNleazkdQKqe2kRMpB+Kg2OBnnRZpjR2PR9ZjRv6rss6/DL5qMRkDH6Xghwl5ZZzIONTgRSZlHKaHQZ7BHR2azZTo9wupK7VuE7f7EWmjBc5SDNiNOfwuEujUg2DvO1JOv16P2JLeQ3Vst4ovxW ;{id = 19386} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +aquila-www.ripe.net. IN A +SECTION ANSWER +aquila-www.ripe.net. 600 IN A 193.0.19.25 +aquila-www.ripe.net. 600 IN RRSIG A 5 3 600 20091216060007 20091116060007 19386 ripe.net. RuPSSATpwiS5hY4WTt7x9Hzq1tQ+ttWgq0hpgJPSorqJHlLbvgucXd8LhrcIFmBm/K/3sj9UYP1viCjbqfvjGToUdv+g4z9KrNq3FoAal6WSyTBgxAgvnHjNi9gRTZBm4O+rUQCKUD8XwlG6r3SKo6iOeSM84CHeQkGjsp5GNxpGnIagWkr5BzjKhaaUc+i82vk1SrNa ;{id = 19386} +SECTION AUTHORITY +ripe.net. 172800 IN NS ns3.nic.fr. +ripe.net. 172800 IN NS sunic.sunet.se. +ripe.net. 172800 IN NS ns-pri.ripe.net. +ripe.net. 172800 IN NS sns-pb.isc.org. +ripe.net. 172800 IN RRSIG NS 5 2 172800 20091216060007 20091116060007 19386 ripe.net. Km2zmkvPOjRddE+SlFBokj2QVroW/R8D2C6u6uCtFI5HVLZTV+oxrIw1ZYYWwe/Jf2CpVBzh3P6iHtWvojM8DHhfkO84wsO33ssqzIzq7e8nDOinqeeGB7yyl642xHCt0jObRewX1hU6Deubs42pFZmO6YKL8Tx6Jb5oe2yyoVebv4bX2qLoEPFw9plE0VavfD397Y4g ;{id = 19386} +SECTION ADDITIONAL +ns-pri.ripe.net. 172800 IN A 193.0.0.195 +ns-pri.ripe.net. 172800 IN AAAA 2001:610:240:0:53::3 +ns-pri.ripe.net. 172800 IN RRSIG A 5 3 172800 20091216060007 20091116060007 19386 ripe.net. BRxWwUNDivDxXnrPlj3/VPUBrf/bk8tKljRG0pQ/7XucTUMR9ae1huNVTC+FTrfZjggqU9/PZlyJ9TwI1lp7J1lEua1mByCHObzHlO7Cq/m7sjZ9cFvpIm6ke2c+xxjs3X8mHsiyftSsCCSvB43DLhgcJtib6QZlCpFxa4Y3sg1fx+1GENrbKlcuJGGqkdrAw0irvKEv ;{id = 19386} +ns-pri.ripe.net. 172800 IN RRSIG AAAA 5 3 172800 20091216060007 20091116060007 19386 ripe.net. Ngd/GLGHakPj1A4rna19OPFpMPVSgCj7CgBtsuwjGwurMFEje4F4miNleazkdQKqe2kRMpB+Kg2OBnnRZpjR2PR9ZjRv6rss6/DL5qMRkDH6Xghwl5ZZzIONTgRSZlHKaHQZ7BHR2azZTo9wupK7VuE7f7EWmjBc5SDNiNOfwuEujUg2DvO1JOv16P2JLeQ3Vst4ovxW ;{id = 19386} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ORG. IN DNSKEY +SECTION ANSWER +ORG. 900 IN DNSKEY 256 3 7 AwEAAdV7bl0omw53nFPoUZSowSTSTDpQO4K8th19coBjlS0iMIWb0NF5YzGkoeditMS8ZLkgc9wS9txeH6XGHzwqJNc5eQcQEOasmC7vqaopoeN/GP/ZkUMbtNTcN1qzS9WzJ4gToxeNCHkAc7LZGh5XY/v1n599hk/ifotV/ZDGhN+H ;{id = 5273 (zsk), size = 1024b} +ORG. 900 IN DNSKEY 257 3 7 AwEAAYpYfj3aaRzzkxWQqMdl7YExY81NdYSv+qayuZDodnZ9IMh0bwMcYaVUdzNAbVeJ8gd6jq1sR3VvP/SR36mmGssbV4Udl5ORDtqiZP2TDNDHxEnKKTX+jWfytZeT7d3AbSzBKC0v7uZrM6M2eoJnl6id66rEUmQC2p9DrrDg9F6tXC9CD/zC7/y+BNNpiOdnM5DXk7HhZm7ra9E7ltL13h2mx7kEgU8e6npJlCoXjraIBgUDthYs48W/sdTDLu7N59rjCG+bpil+c8oZ9f7NR3qmSTpTP1m86RqUQnVErifrH8KjDqL+3wzUdF5ACkYwt1XhPVPU+wSIlzbaAQN49PU= ;{id = 21366 (ksk), size = 2048b} +ORG. 900 IN DNSKEY 257 3 7 AwEAAZTjbIO5kIpxWUtyXc8avsKyHIIZ+LjC2Dv8naO+Tz6X2fqzDC1bdq7HlZwtkaqTkMVVJ+8gE9FIreGJ4c8G1GdbjQgbP1OyYIG7OHTc4hv5T2NlyWr6k6QFz98Q4zwFIGTFVvwBhmrMDYsOTtXakK6QwHovA1+83BsUACxlidpwB0hQacbD6x+I2RCDzYuTzj64Jv0/9XsX6AYV3ebcgn4hL1jIR2eJYyXlrAoWxdzxcW//5yeL5RVWuhRxejmnSVnCuxkfS4AQ485KH2tpdbWcCopLJZs6tw8q3jWcpTGzdh/v3xdYfNpQNcPImFlxAun3BtORPA2r8ti6MNoJEHU= ;{id = 9795 (ksk), size = 2048b} +ORG. 900 IN DNSKEY 256 3 7 AwEAAaT7yoAEj5kX1rW40gMxUgPYGIc6hIPXihtK44jq6UQlZxTeFdsNX6aNaFpSq9pbI19y4JfQvCPPjw2248fwNzgwxfkdyRk7vzKagad2hs8wQ/C7vYuTUoTjrOBRwnsEHix+jYgKZH+lX1ZRKo/YXyMz05KWH+3j5y0VSrKBcdBZ ;{id = 53990 (zsk), size = 1024b} +ORG. 900 IN RRSIG DNSKEY 7 1 900 20091123154522 20091109144522 5273 org. zHcY20bnIBzsl1CXmZdtt8PWPy079Ic3dQ/pLH2z1yCoC+kWGzLIlU/EcWa0rrQzqc9oK+v63xzXFoib3LewcijiGmKYtFcyi3HGfVdJrDFIxmN52x4pZerVZq9NA/FLQ8ZrobkVgYiEAmjMU1OesPPZPwwlPRdSG421q3o3N4Q= ;{id = 5273} +ORG. 900 IN RRSIG DNSKEY 7 1 900 20091123154522 20091109144522 21366 org. Xlh0UQl+Ldig/jBS7Ty9rfeUztG5P7Brjr/Du+XlC7KjUkk/gNfpxgPmIKuA3ZLwgwTvEF6i7CD7b5gEKKC2P8Y5kQjKcjcDZl0+5W1IfpFF1Ka546erCy5cznXT23W5bzODNiraMs7KwvwMlD3LeOCiBeldPKeZ0yxWI/3YXmwAbkky4MApX9khSnilSaewcVSzQM/iOVuCR/+5esNvcKqjgWbT3M4vorzjc7YxVxF2BTgxybDOn4OkWvdeSlDiIVVS+VtxK0U7yIc59mpE7WxoRLtw/Qkd8bjh+KF5izQO2Q/7VxhkJ6pBxxumHwQahlgOQYxWMLqUc/EZnXSQpQ== ;{id = 21366} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +root-servers.org. IN DS +SECTION ANSWER +SECTION AUTHORITY +h9p7u7tr2u91d0v0ljs9l1gidnp90u3h.org. 86399 IN NSEC3 1 1 1 d399eaab h9rsfb7fpf2l8hg35cmpc765tdk23rp6 NS SOA RRSIG DNSKEY NSEC3PARAM ; flags: optout +h9p7u7tr2u91d0v0ljs9l1gidnp90u3h.org. 86399 IN RRSIG NSEC3 7 2 86400 20091130090148 20091116080148 5273 org. FL7e/4Lhihh9LKAPDKNmlvEHbjkPY/6GLhtVMWtbSfBS8rAaHuInCD/tbQxCmFmT6e3HXHXkUcjC7BSDFPnlhtB8P2iNjvkdZJ72jVTXDY1P6LuK/OJhRT8DjFlHlvjdNgS5/0HCuGYU5A1GPkWGx1waUmblryPApb8HNSAmdYA= ;{id = 5273} +i8i48ibuph5kgh999ld485qnt660qdag.org. 86399 IN NSEC3 1 1 1 d399eaab i94atlaqkvkoms2q45m5msds8r3414ft A RRSIG ; flags: optout +i8i48ibuph5kgh999ld485qnt660qdag.org. 86399 IN RRSIG NSEC3 7 2 86400 20091125010858 20091111000858 5273 org. WrWFYs2FuzPRYh+hgc8B3ZKL6jiMee2F1FsPNVEx9Ojv76BMELWomI0Zcd90NZbs7kvs5FP1G79s9o3oQHeWVfa6as8Wi6RLn97nX3FVqYI39r7GZnoKj8QGrCsRCatqK4Lsh426X0vzR5CwIA14/XL1w6UQ1KuTHlIu51RidA4= ;{id = 5273} +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +k.root-servers.org. IN A +ENTRY_END +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +k.root-servers.org. IN A +SECTION ANSWER +k.root-servers.org. IN CNAME www.ripe.net. +www.ripe.net. 900 IN CNAME aquila-www.ripe.net. +www.ripe.net. 900 IN RRSIG CNAME 5 3 900 20091216060007 20091116060007 19386 ripe.net. NjCpVZC/LLnoV1pa91GSL9SP65n7eFKoe/OcuKzUPHumXIDrXnE23F1rNfbjYpVrQDEsG6iInI7Edh2MCS4NI4tLwrytEDgCX7ZnqIMIOV2/gJa5ZkLlmVT71Agnfi788q7ozEq14zlhY+brD5kyBiEcfOhH/qkX+zJuGdt1AcQwMxYn/GQ0Z32k5ulBnzrIFWObBksO ;{id = 19386} +aquila-www.ripe.net. 600 IN A 193.0.19.25 +aquila-www.ripe.net. 600 IN RRSIG A 5 3 600 20091216060007 20091116060007 19386 ripe.net. RuPSSATpwiS5hY4WTt7x9Hzq1tQ+ttWgq0hpgJPSorqJHlLbvgucXd8LhrcIFmBm/K/3sj9UYP1viCjbqfvjGToUdv+g4z9KrNq3FoAal6WSyTBgxAgvnHjNi9gRTZBm4O+rUQCKUD8XwlG6r3SKo6iOeSM84CHeQkGjsp5GNxpGnIagWkr5BzjKhaaUc+i82vk1SrNa ;{id = 19386} +SECTION AUTHORITY +ripe.net. 172800 IN NS ns3.nic.fr. +ripe.net. 172800 IN NS sunic.sunet.se. +ripe.net. 172800 IN NS ns-pri.ripe.net. +ripe.net. 172800 IN NS sns-pb.isc.org. +ripe.net. 172800 IN RRSIG NS 5 2 172800 20091216060007 20091116060007 19386 ripe.net. Km2zmkvPOjRddE+SlFBokj2QVroW/R8D2C6u6uCtFI5HVLZTV+oxrIw1ZYYWwe/Jf2CpVBzh3P6iHtWvojM8DHhfkO84wsO33ssqzIzq7e8nDOinqeeGB7yyl642xHCt0jObRewX1hU6Deubs42pFZmO6YKL8Tx6Jb5oe2yyoVebv4bX2qLoEPFw9plE0VavfD397Y4g ;{id = 19386} +SECTION ADDITIONAL +ns-pri.ripe.net. 172800 IN A 193.0.0.195 +ns-pri.ripe.net. 172800 IN AAAA 2001:610:240:0:53::3 +ns-pri.ripe.net. 172800 IN RRSIG A 5 3 172800 20091216060007 20091116060007 19386 ripe.net. BRxWwUNDivDxXnrPlj3/VPUBrf/bk8tKljRG0pQ/7XucTUMR9ae1huNVTC+FTrfZjggqU9/PZlyJ9TwI1lp7J1lEua1mByCHObzHlO7Cq/m7sjZ9cFvpIm6ke2c+xxjs3X8mHsiyftSsCCSvB43DLhgcJtib6QZlCpFxa4Y3sg1fx+1GENrbKlcuJGGqkdrAw0irvKEv ;{id = 19386} +ns-pri.ripe.net. 172800 IN RRSIG AAAA 5 3 172800 20091216060007 20091116060007 19386 ripe.net. Ngd/GLGHakPj1A4rna19OPFpMPVSgCj7CgBtsuwjGwurMFEje4F4miNleazkdQKqe2kRMpB+Kg2OBnnRZpjR2PR9ZjRv6rss6/DL5qMRkDH6Xghwl5ZZzIONTgRSZlHKaHQZ7BHR2azZTo9wupK7VuE7f7EWmjBc5SDNiNOfwuEujUg2DvO1JOv16P2JLeQ3Vst4ovxW ;{id = 19386} +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_unalgo_anchor.rpl b/testdata/val_unalgo_anchor.rpl new file mode 100644 index 00000000000..e588b8a546e --- /dev/null +++ b/testdata/val_unalgo_anchor.rpl @@ -0,0 +1,150 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 208 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with unsupported algorithm trust anchor + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_unalgo_dlv.rpl b/testdata/val_unalgo_dlv.rpl new file mode 100644 index 00000000000..8157793a34c --- /dev/null +++ b/testdata/val_unalgo_dlv.rpl @@ -0,0 +1,280 @@ +; config options +; The island of trust is at example.com (the DLV repository) +server: + dlv-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with unknown algorithm DLV anchor +; positive response for DLV. +; but only has unknown algos +; have to treat zone as insecure + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +net. IN A +SECTION AUTHORITY +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net. IN NS +SECTION ANSWER +net. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.net. IN A +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; DLV query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net.example.com. IN DLV +SECTION ANSWER +; algo 208 is unknown +example.net.example.com. 3600 IN DLV 30899 208 1 14188c885f20623ad1d3bec42798f3f951793e4c ; xehac-mofum-malyd-bomaf-pegit-fuzes-ganin-misiz-nigel-nozog-soxix +example.net.example.com. 3600 IN RRSIG DLV 3 4 3600 20070926134150 20070829134150 2854 example.com. AFBU1dN/KstcLfQQzy7ZKvPq+2hQg7D6QynqgwI3f8envPQGj782/NA= ;{id = 2854} +;example.net.example.com. 3600 IN DLV 30899 5 1 14188c885f20623ad1d3bec42798f3f951793e4c ; xehac-mofum-malyd-bomaf-pegit-fuzes-ganin-misiz-nigel-nozog-soxix +;example.net.example.com. 3600 IN RRSIG DLV 3 4 3600 20070926134150 20070829134150 2854 example.com. ACK48Q/oKwh/SM9yRiKjZYuc+AtEZ2yCPNJ15kKCN8nsVcv7xigmNTY= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +net.example.com. IN DLV +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AKPJnPBqfJKxE4P2iVYkSRJno9HmiXJZtjdqE8oBeq9Lk9FytcMdcig= ;{id = 2854} +example.com IN NSEC example.net.example.com. SOA NS RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. AIoUkJ04/7/kJFDLocoqksqt9UL2RHHwlRfXAMxGdBHcNO+GSpG47Uk= ;{id = 2854} +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NXDOMAIN +SECTION QUESTION +com.example.com. IN DLV +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AKPJnPBqfJKxE4P2iVYkSRJno9HmiXJZtjdqE8oBeq9Lk9FytcMdcig= ;{id = 2854} +example.com IN NSEC example.net.example.com. SOA NS RRSIG NSEC +example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. AIoUkJ04/7/kJFDLocoqksqt9UL2RHHwlRfXAMxGdBHcNO+GSpG47Uk= ;{id = 2854} +ENTRY_END + +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.5 +; DS RR is +; example.net. 3600 IN DS 30899 5 1 14188c885f20623ad1d3bec42798f3f951793e4c ; xehac-mofum-malyd-bomaf-pegit-fuzes-ganin-misiz-nigel-nozog-soxix +; DNSKEY prime query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN DNSKEY +SECTION ANSWER +example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +example.net. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; NS query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +; www.example.net query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +www.example.net. 3600 IN A 10.20.30.40 +www.example.net. 3600 IN RRSIG A 5 3 3600 20070926135752 20070829135752 30899 example.net. ACvv4RQVC7TbI57ewqFImRaVoymktJ5Cxn/FaCodIENt82LVM92nivbP2WtwWCsQHWp7FkrMxTlQTJwyAeXFyg== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.net. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.net. IN A +SECTION ANSWER +www.example.net. 3600 IN A 10.20.30.40 +www.example.net. 3600 IN RRSIG A 5 3 3600 20070926135752 20070829135752 30899 example.net. ACvv4RQVC7TbI57ewqFImRaVoymktJ5Cxn/FaCodIENt82LVM92nivbP2WtwWCsQHWp7FkrMxTlQTJwyAeXFyg== ;{id = 30899} +SECTION AUTHORITY +example.net. IN NS ns.example.net. +example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899} +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.5 +ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899} +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_unalgo_ds.rpl b/testdata/val_unalgo_ds.rpl new file mode 100644 index 00000000000..72e39b812d6 --- /dev/null +++ b/testdata/val_unalgo_ds.rpl @@ -0,0 +1,200 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with unknown algorithm delegation +; DS has unknown algo only. +; so subzone has to be treated as unsigned. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode qtype subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +; algorithm 208 is unknown. +sub.example.com. 3600 IN DS 30899 208 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. AEMPMNVJAygL0TyRUU+MVgP4FA7jSIpVj6628IdLe7eY3OwWp3hUTnU= ;{id = 2854} +;sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +;sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response to DNSKEY priming query +; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899} +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. 3600 IN A 11.11.11.11 +www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899} +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_unsec_cname.rpl b/testdata/val_unsec_cname.rpl new file mode 100644 index 00000000000..a1871401bad --- /dev/null +++ b/testdata/val_unsec_cname.rpl @@ -0,0 +1,359 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with DS, unsec, cname sequence. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +a.b.sub.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +a.b.sub.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response for delegation to c.example.com. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +c.c.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +c.example.com. IN NS ns.c.example.com. +c.example.com. IN NSEC d.example.com. NS RRSIG NSEC +c.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFDQ1xBqQ8Yxy7d7MbfAOg9g+dInHAhUAgP2w61bvME+hLWFiNg42Ny02/vo= ;{id = 2854} +SECTION ADDITIONAL +ns.c.example.com. IN A 1.2.3.8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +c.example.com. IN DS +SECTION ANSWER +SECTION AUTHORITY +c.example.com. IN NSEC d.example.com. NS RRSIG NSEC +c.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFDQ1xBqQ8Yxy7d7MbfAOg9g+dInHAhUAgP2w61bvME+hLWFiNg42Ny02/vo= ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +a.b.sub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response to DNSKEY priming query +; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DNSKEY +SECTION ANSWER +sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b} +sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899} +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899} +ENTRY_END + +; response to query of interest +; another delegation, validated unsecure. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +a.b.sub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +b.sub.example.com. IN NS ns.b.sub.example.com. +b.sub.example.com. IN NSEC c.sub.example.com. NS NSEC RRSIG +b.sub.example.com. 3600 IN RRSIG NSEC 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. KPdURTUrbQvc6OXtDZaH3+14uO2qPUPIFO86aTNZ/Ujy3d2RMSB7fkSSulDO6QDSBEUhr9WgbQr0/YoljCBirA== ;{id = 30899} +SECTION ADDITIONAL +ns.b.sub.example.com. IN A 1.2.3.7 +ENTRY_END + +; b DS query. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +b.sub.example.com. IN DS +SECTION AUTHORITY +b.sub.example.com. IN NSEC c.sub.example.com. NS NSEC RRSIG +b.sub.example.com. 3600 IN RRSIG NSEC 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. KPdURTUrbQvc6OXtDZaH3+14uO2qPUPIFO86aTNZ/Ujy3d2RMSB7fkSSulDO6QDSBEUhr9WgbQr0/YoljCBirA== ;{id = 30899} +ENTRY_END +RANGE_END + +; server ns.b.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.7 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +b.sub.example.com. IN NS +SECTION ANSWER +b.sub.example.com. IN NS ns.b.sub.example.com. +SECTION ADDITIONAL +ns.b.sub.example.com. IN A 1.2.3.7 +ENTRY_END + +ENTRY_BEGIN +; query of interest, give a cname to another unsecure zone. +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +a.b.sub.example.com. IN A +SECTION ANSWER +a.b.sub.example.com. IN CNAME c.c.example.com. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +a.b.sub.example.com. IN DS +SECTION AUTHORITY +b.sub.example.com. IN SOA B-EXAMPLE. b-example. 1 2 3 7 7 +ENTRY_END +RANGE_END + +; server ns.c.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.8 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +c.sub.example.com. IN NS +SECTION ANSWER +c.sub.example.com. IN NS ns.c.sub.example.com. +SECTION ADDITIONAL +ns.c.sub.example.com. IN A 1.2.3.8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +c.example.com. IN NS +SECTION ANSWER +c.example.com. IN NS ns.c.example.com. +SECTION ADDITIONAL +ns.c.example.com. IN A 1.2.3.8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +c.c.example.com. IN A +SECTION ANSWER +c.c.example.com. IN A 11.11.11.11 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +c.c.example.com. IN DS +SECTION AUTHORITY +c.example.com. IN SOA C-EXAMPLE. c-example. 1 2 3 4 5 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +a.b.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +a.b.sub.example.com. IN A +SECTION ANSWER +a.b.sub.example.com. IN CNAME c.c.example.com. +c.c.example.com. 3600 IN A 11.11.11.11 +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +; test that a DS query does not get CNAME redirected, but instead +; asked to the right server that has to respond to it. +STEP 20 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +a.b.sub.example.com. IN DS +ENTRY_END + +STEP 30 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +a.b.sub.example.com. IN DS +SECTION AUTHORITY +b.sub.example.com. IN SOA B-EXAMPLE. b-example. 1 2 3 7 7 +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_unsecds.rpl b/testdata/val_unsecds.rpl new file mode 100644 index 00000000000..21cb8007655 --- /dev/null +++ b/testdata/val_unsecds.rpl @@ -0,0 +1,191 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with insecure delegation + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. IN NSEC www.example.com. NS RRSIG NSEC +sub.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFDCaiDM6G+glwNW276HWdH+McmjgAhRSwF5OfimNQCqkWgnYotLOwUghKQ== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +; query for missing DS record. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA ns.example.com. h.example.com. 2007090504 1800 1800 2419200 7200 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFC5uwIHSehZtetK2CMNXttSFUB0XAhROFDAgy/FaxR8zFXJzyPdpQG93Sw== ;{id = 2854} +sub.example.com. IN NSEC www.example.com. NS RRSIG NSEC +sub.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFDCaiDM6G+glwNW276HWdH+McmjgAhRSwF5OfimNQCqkWgnYotLOwUghKQ== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + + +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 11.11.11.11 +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. 3600 IN A 11.11.11.11 +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_unsecds_negcache.rpl b/testdata/val_unsecds_negcache.rpl new file mode 100644 index 00000000000..eae1dab7877 --- /dev/null +++ b/testdata/val_unsecds_negcache.rpl @@ -0,0 +1,192 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with insecure delegation and DS negative cache + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. IN NSEC www.example.com. NS RRSIG NSEC +sub.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFDCaiDM6G+glwNW276HWdH+McmjgAhRSwF5OfimNQCqkWgnYotLOwUghKQ== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +; query for missing DS record. +; get it from the negative cache instead! +;ENTRY_BEGIN +;MATCH opcode qtype qname +;ADJUST copy_id +;REPLY QR NOERROR +;SECTION QUESTION +;sub.example.com. IN DS +;SECTION ANSWER +;SECTION AUTHORITY +;example.com. IN SOA ns.example.com. h.example.com. 2007090504 1800 1800 2419200 7200 +;example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFC5uwIHSehZtetK2CMNXttSFUB0XAhROFDAgy/FaxR8zFXJzyPdpQG93Sw== ;{id = 2854} +;sub.example.com. IN NSEC www.example.com. NS RRSIG NSEC +;sub.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFDCaiDM6G+glwNW276HWdH+McmjgAhRSwF5OfimNQCqkWgnYotLOwUghKQ== ;{id = 2854} +;SECTION ADDITIONAL +;ns.sub.example.com. IN A 1.2.3.6 +;ENTRY_END + + +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 11.11.11.11 +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.sub.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. 3600 IN A 11.11.11.11 +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_unsecds_qtypeds.rpl b/testdata/val_unsecds_qtypeds.rpl new file mode 100644 index 00000000000..0448ea4c0f4 --- /dev/null +++ b/testdata/val_unsecds_qtypeds.rpl @@ -0,0 +1,207 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with insecure delegation and qtype DS. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; query for missing DS record. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA ns.example.com. h.example.com. 2007090504 1800 1800 2419200 7200 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFC5uwIHSehZtetK2CMNXttSFUB0XAhROFDAgy/FaxR8zFXJzyPdpQG93Sw== ;{id = 2854} +sub.example.com. IN NSEC www.example.com. NS RRSIG NSEC +sub.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFDCaiDM6G+glwNW276HWdH+McmjgAhRSwF5OfimNQCqkWgnYotLOwUghKQ== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +; response for delegation to sub.example.com. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN A +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN NS ns.sub.example.com. +sub.example.com. IN NSEC www.example.com. NS RRSIG NSEC +sub.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFDCaiDM6G+glwNW276HWdH+McmjgAhRSwF5OfimNQCqkWgnYotLOwUghKQ== ;{id = 2854} +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + + +RANGE_END + +; ns.sub.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.6 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +sub.example.com. IN NS +SECTION ANSWER +sub.example.com. IN NS ns.sub.example.com. +SECTION ADDITIONAL +ns.sub.example.com. IN A 1.2.3.6 +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.sub.example.com. IN A +SECTION ANSWER +www.sub.example.com. IN A 11.11.11.11 +SECTION AUTHORITY +SECTION ADDITIONAL +ENTRY_END + +; query for missing DS record. on wrong side of zone cut. +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION ANSWER +SECTION AUTHORITY +sub.example.com. IN SOA ns.sub.example.com. h.sub.example.com. 2007090504 1800 1800 2419200 7200 +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +sub.example.com. IN DS +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +sub.example.com. IN DS +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA ns.example.com. h.example.com. 2007090504 1800 1800 2419200 7200 +example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFC5uwIHSehZtetK2CMNXttSFUB0XAhROFDAgy/FaxR8zFXJzyPdpQG93Sw== ;{id = 2854} +sub.example.com. IN NSEC www.example.com. NS RRSIG NSEC +sub.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFDCaiDM6G+glwNW276HWdH+McmjgAhRSwF5OfimNQCqkWgnYotLOwUghKQ== ;{id = 2854} +SECTION ADDITIONAL +ENTRY_END + +SCENARIO_END diff --git a/testdata/val_wild_pos.rpl b/testdata/val_wild_pos.rpl new file mode 100644 index 00000000000..b5b56e9540f --- /dev/null +++ b/testdata/val_wild_pos.rpl @@ -0,0 +1,159 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + target-fetch-policy: "0 0 0 0 0" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with direct wildcard positive response + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +*.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +*.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.com. IN AAAA +SECTION ANSWER +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +*.example.com. IN A +SECTION ANSWER +*.example.com. IN A 10.20.30.40 +*.example.com. 3600 IN RRSIG A 3 2 3600 20070926134150 20070829134150 2854 example.com. AG3iIIzflgRHsIlOKiSHADHIn/NmfNgESAslc1wIjxys5r9w4CxNIGs= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +*.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +*.example.com. IN A +SECTION ANSWER +*.example.com. IN A 10.20.30.40 +*.example.com. 3600 IN RRSIG A 3 2 3600 20070926134150 20070829134150 2854 example.com. AG3iIIzflgRHsIlOKiSHADHIn/NmfNgESAslc1wIjxys5r9w4CxNIGs= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +ENTRY_END + +SCENARIO_END diff --git a/testdata/version_bind.rpl b/testdata/version_bind.rpl new file mode 100644 index 00000000000..1c5b914c188 --- /dev/null +++ b/testdata/version_bind.rpl @@ -0,0 +1,74 @@ +; config options +server: + hide-identity: no + hide-version: no + identity: "test-identity" + version: "test-version" +CONFIG_END +SCENARIO_BEGIN Test version.bind identity and version queries + +; version.bind. +STEP 1 QUERY +ENTRY_BEGIN +SECTION QUESTION +version.bind. CH TXT +ENTRY_END +STEP 2 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RA +SECTION QUESTION +version.bind. CH TXT +SECTION ANSWER +version.bind. 0 CH TXT "test-version" +ENTRY_END + +; version.server. +STEP 3 QUERY +ENTRY_BEGIN +SECTION QUESTION +version.server. CH TXT +ENTRY_END +STEP 4 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RA +SECTION QUESTION +version.server. CH TXT +SECTION ANSWER +version.server. 0 CH TXT "test-version" +ENTRY_END + +; hostname.bind. +STEP 5 QUERY +ENTRY_BEGIN +SECTION QUESTION +hostname.bind. CH TXT +ENTRY_END +STEP 6 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RA +SECTION QUESTION +hostname.bind. CH TXT +SECTION ANSWER +hostname.bind. 0 CH TXT "test-identity" +ENTRY_END + +; id.server. +STEP 7 QUERY +ENTRY_BEGIN +SECTION QUESTION +id.server. CH TXT +ENTRY_END +STEP 8 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RA +SECTION QUESTION +id.server. CH TXT +SECTION ANSWER +id.server. 0 CH TXT "test-identity" +ENTRY_END + +SCENARIO_END diff --git a/testdata/version_bind_hide.rpl b/testdata/version_bind_hide.rpl new file mode 100644 index 00000000000..02376461fa1 --- /dev/null +++ b/testdata/version_bind_hide.rpl @@ -0,0 +1,71 @@ +; config options +server: + hide-identity: yes + hide-version: yes + identity: "test-identity" + version: "test-version" +; we rely on the fact that there are no builtin stubs for class CH. +CONFIG_END +SCENARIO_BEGIN Test config hide options for identity and version queries + +; version.bind. +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +version.bind. CH TXT +ENTRY_END +STEP 2 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA REFUSED +SECTION QUESTION +version.bind. CH TXT +ENTRY_END + +; version.server. +STEP 3 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +version.server. CH TXT +ENTRY_END +STEP 4 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA REFUSED +SECTION QUESTION +version.server. CH TXT +ENTRY_END + +; hostname.bind. +STEP 5 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +hostname.bind. CH TXT +ENTRY_END +STEP 6 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA REFUSED +SECTION QUESTION +hostname.bind. CH TXT +ENTRY_END + +; id.server. +STEP 7 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +id.server. CH TXT +ENTRY_END +STEP 8 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA REFUSED +SECTION QUESTION +id.server. CH TXT +ENTRY_END + +SCENARIO_END diff --git a/util/alloc.c b/util/alloc.c new file mode 100644 index 00000000000..b5ccd96b429 --- /dev/null +++ b/util/alloc.c @@ -0,0 +1,642 @@ +/* + * util/alloc.c - memory allocation service. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains memory allocation functions. + */ + +#include "config.h" +#include "util/alloc.h" +#include "util/regional.h" +#include "util/data/packed_rrset.h" +#include "util/fptr_wlist.h" + +/** custom size of cached regional blocks */ +#define ALLOC_REG_SIZE 16384 +/** number of bits for ID part of uint64, rest for number of threads. */ +#define THRNUM_SHIFT 48 /* for 65k threads, 2^48 rrsets per thr. */ + +/** setup new special type */ +static void +alloc_setup_special(alloc_special_t* t) +{ + memset(t, 0, sizeof(*t)); + lock_rw_init(&t->entry.lock); + t->entry.key = t; +} + +/** prealloc some entries in the cache. To minimize contention. + * Result is 1 lock per alloc_max newly created entries. + * @param alloc: the structure to fill up. + */ +static void +prealloc(struct alloc_cache* alloc) +{ + alloc_special_t* p; + int i; + for(i=0; iquar); + alloc->quar = p; + alloc->num_quar++; + } +} + +/** prealloc region blocks */ +static void +prealloc_blocks(struct alloc_cache* alloc, size_t num) +{ + size_t i; + struct regional* r; + for(i=0; inext = (char*)alloc->reg_list; + alloc->reg_list = r; + alloc->num_reg_blocks ++; + } +} + +void +alloc_init(struct alloc_cache* alloc, struct alloc_cache* super, + int thread_num) +{ + memset(alloc, 0, sizeof(*alloc)); + alloc->super = super; + alloc->thread_num = thread_num; + alloc->next_id = (uint64_t)thread_num; /* in steps, so that type */ + alloc->next_id <<= THRNUM_SHIFT; /* of *_id is used. */ + alloc->last_id = 1; /* so no 64bit constants, */ + alloc->last_id <<= THRNUM_SHIFT; /* or implicit 'int' ops. */ + alloc->last_id -= 1; /* for compiler portability. */ + alloc->last_id |= alloc->next_id; + alloc->next_id += 1; /* because id=0 is special. */ + alloc->max_reg_blocks = 100; + alloc->num_reg_blocks = 0; + alloc->reg_list = NULL; + alloc->cleanup = NULL; + alloc->cleanup_arg = NULL; + if(alloc->super) + prealloc_blocks(alloc, alloc->max_reg_blocks); + if(!alloc->super) { + lock_quick_init(&alloc->lock); + lock_protect(&alloc->lock, alloc, sizeof(*alloc)); + } +} + +void +alloc_clear(struct alloc_cache* alloc) +{ + alloc_special_t* p, *np; + struct regional* r, *nr; + if(!alloc) + return; + if(!alloc->super) { + lock_quick_destroy(&alloc->lock); + } + if(alloc->super && alloc->quar) { + /* push entire list into super */ + p = alloc->quar; + while(alloc_special_next(p)) /* find last */ + p = alloc_special_next(p); + lock_quick_lock(&alloc->super->lock); + alloc_set_special_next(p, alloc->super->quar); + alloc->super->quar = alloc->quar; + alloc->super->num_quar += alloc->num_quar; + lock_quick_unlock(&alloc->super->lock); + } else { + /* free */ + p = alloc->quar; + while(p) { + np = alloc_special_next(p); + /* deinit special type */ + lock_rw_destroy(&p->entry.lock); + free(p); + p = np; + } + } + alloc->quar = 0; + alloc->num_quar = 0; + r = alloc->reg_list; + while(r) { + nr = (struct regional*)r->next; + free(r); + r = nr; + } + alloc->reg_list = NULL; + alloc->num_reg_blocks = 0; +} + +uint64_t +alloc_get_id(struct alloc_cache* alloc) +{ + uint64_t id = alloc->next_id++; + if(id == alloc->last_id) { + log_warn("rrset alloc: out of 64bit ids. Clearing cache."); + fptr_ok(fptr_whitelist_alloc_cleanup(alloc->cleanup)); + (*alloc->cleanup)(alloc->cleanup_arg); + + /* start back at first number */ /* like in alloc_init*/ + alloc->next_id = (uint64_t)alloc->thread_num; + alloc->next_id <<= THRNUM_SHIFT; /* in steps for comp. */ + alloc->next_id += 1; /* portability. */ + /* and generate new and safe id */ + id = alloc->next_id++; + } + return id; +} + +alloc_special_t* +alloc_special_obtain(struct alloc_cache* alloc) +{ + alloc_special_t* p; + log_assert(alloc); + /* see if in local cache */ + if(alloc->quar) { + p = alloc->quar; + alloc->quar = alloc_special_next(p); + alloc->num_quar--; + p->id = alloc_get_id(alloc); + return p; + } + /* see if in global cache */ + if(alloc->super) { + /* could maybe grab alloc_max/2 entries in one go, + * but really, isn't that just as fast as this code? */ + lock_quick_lock(&alloc->super->lock); + if((p = alloc->super->quar)) { + alloc->super->quar = alloc_special_next(p); + alloc->super->num_quar--; + } + lock_quick_unlock(&alloc->super->lock); + if(p) { + p->id = alloc_get_id(alloc); + return p; + } + } + /* allocate new */ + prealloc(alloc); + if(!(p = (alloc_special_t*)malloc(sizeof(alloc_special_t)))) { + log_err("alloc_special_obtain: out of memory"); + return NULL; + } + alloc_setup_special(p); + p->id = alloc_get_id(alloc); + return p; +} + +/** push mem and some more items to the super */ +static void +pushintosuper(struct alloc_cache* alloc, alloc_special_t* mem) +{ + int i; + alloc_special_t *p = alloc->quar; + log_assert(p); + log_assert(alloc && alloc->super && + alloc->num_quar >= ALLOC_SPECIAL_MAX); + /* push ALLOC_SPECIAL_MAX/2 after mem */ + alloc_set_special_next(mem, alloc->quar); + for(i=1; iquar = alloc_special_next(p); + alloc->num_quar -= ALLOC_SPECIAL_MAX/2; + + /* dump mem+list into the super quar list */ + lock_quick_lock(&alloc->super->lock); + alloc_set_special_next(p, alloc->super->quar); + alloc->super->quar = mem; + alloc->super->num_quar += ALLOC_SPECIAL_MAX/2 + 1; + lock_quick_unlock(&alloc->super->lock); + /* so 1 lock per mem+alloc/2 deletes */ +} + +void +alloc_special_release(struct alloc_cache* alloc, alloc_special_t* mem) +{ + log_assert(alloc); + if(!mem) + return; + if(!alloc->super) { + lock_quick_lock(&alloc->lock); /* superalloc needs locking */ + } + + alloc_special_clean(mem); + if(alloc->super && alloc->num_quar >= ALLOC_SPECIAL_MAX) { + /* push it to the super structure */ + pushintosuper(alloc, mem); + return; + } + + alloc_set_special_next(mem, alloc->quar); + alloc->quar = mem; + alloc->num_quar++; + if(!alloc->super) { + lock_quick_unlock(&alloc->lock); + } +} + +void +alloc_stats(struct alloc_cache* alloc) +{ + log_info("%salloc: %d in cache, %d blocks.", alloc->super?"":"sup", + (int)alloc->num_quar, (int)alloc->num_reg_blocks); +} + +size_t alloc_get_mem(struct alloc_cache* alloc) +{ + alloc_special_t* p; + size_t s = sizeof(*alloc); + if(!alloc->super) { + lock_quick_lock(&alloc->lock); /* superalloc needs locking */ + } + s += sizeof(alloc_special_t) * alloc->num_quar; + for(p = alloc->quar; p; p = alloc_special_next(p)) { + s += lock_get_mem(&p->entry.lock); + } + s += alloc->num_reg_blocks * ALLOC_REG_SIZE; + if(!alloc->super) { + lock_quick_unlock(&alloc->lock); + } + return s; +} + +struct regional* +alloc_reg_obtain(struct alloc_cache* alloc) +{ + if(alloc->num_reg_blocks > 0) { + struct regional* r = alloc->reg_list; + alloc->reg_list = (struct regional*)r->next; + r->next = NULL; + alloc->num_reg_blocks--; + return r; + } + return regional_create_custom(ALLOC_REG_SIZE); +} + +void +alloc_reg_release(struct alloc_cache* alloc, struct regional* r) +{ + if(alloc->num_reg_blocks >= alloc->max_reg_blocks) { + regional_destroy(r); + return; + } + if(!r) return; + regional_free_all(r); + log_assert(r->next == NULL); + r->next = (char*)alloc->reg_list; + alloc->reg_list = r; + alloc->num_reg_blocks++; +} + +void +alloc_set_id_cleanup(struct alloc_cache* alloc, void (*cleanup)(void*), + void* arg) +{ + alloc->cleanup = cleanup; + alloc->cleanup_arg = arg; +} + +/** global debug value to keep track of total memory mallocs */ +size_t unbound_mem_alloc = 0; +/** global debug value to keep track of total memory frees */ +size_t unbound_mem_freed = 0; +#ifdef UNBOUND_ALLOC_STATS +/** special value to know if the memory is being tracked */ +uint64_t mem_special = (uint64_t)0xfeed43327766abcdLL; +#ifdef malloc +#undef malloc +#endif +/** malloc with stats */ +void *unbound_stat_malloc(size_t size) +{ + void* res; + if(size == 0) size = 1; + res = malloc(size+16); + if(!res) return NULL; + unbound_mem_alloc += size; + log_info("stat %p=malloc(%u)", res+16, (unsigned)size); + memcpy(res, &size, sizeof(size)); + memcpy(res+8, &mem_special, sizeof(mem_special)); + return res+16; +} +#ifdef calloc +#undef calloc +#endif +/** calloc with stats */ +void *unbound_stat_calloc(size_t nmemb, size_t size) +{ + size_t s = (nmemb*size==0)?(size_t)1:nmemb*size; + void* res = calloc(1, s+16); + if(!res) return NULL; + log_info("stat %p=calloc(%u, %u)", res+16, (unsigned)nmemb, (unsigned)size); + unbound_mem_alloc += s; + memcpy(res, &s, sizeof(s)); + memcpy(res+8, &mem_special, sizeof(mem_special)); + return res+16; +} +#ifdef free +#undef free +#endif +/** free with stats */ +void unbound_stat_free(void *ptr) +{ + size_t s; + if(!ptr) return; + if(memcmp(ptr-8, &mem_special, sizeof(mem_special)) != 0) { + free(ptr); + return; + } + ptr-=16; + memcpy(&s, ptr, sizeof(s)); + log_info("stat free(%p) size %u", ptr+16, (unsigned)s); + memset(ptr+8, 0, 8); + unbound_mem_freed += s; + free(ptr); +} +#ifdef realloc +#undef realloc +#endif +/** realloc with stats */ +void *unbound_stat_realloc(void *ptr, size_t size) +{ + size_t cursz; + void* res; + if(!ptr) return unbound_stat_malloc(size); + if(memcmp(ptr-8, &mem_special, sizeof(mem_special)) != 0) { + return realloc(ptr, size); + } + if(size==0) { + unbound_stat_free(ptr); + return NULL; + } + ptr -= 16; + memcpy(&cursz, ptr, sizeof(cursz)); + if(cursz == size) { + /* nothing changes */ + return ptr; + } + res = malloc(size+16); + if(!res) return NULL; + unbound_mem_alloc += size; + unbound_mem_freed += cursz; + log_info("stat realloc(%p, %u) from %u", ptr+16, (unsigned)size, (unsigned)cursz); + if(cursz > size) { + memcpy(res+16, ptr+16, size); + } else if(size > cursz) { + memcpy(res+16, ptr+16, cursz); + } + memset(ptr+8, 0, 8); + free(ptr); + memcpy(res, &size, sizeof(size)); + memcpy(res+8, &mem_special, sizeof(mem_special)); + return res+16; +} + +/** log to file where alloc was done */ +void *unbound_stat_malloc_log(size_t size, const char* file, int line, + const char* func) +{ + log_info("%s:%d %s malloc(%u)", file, line, func, (unsigned)size); + return unbound_stat_malloc(size); +} + +/** log to file where alloc was done */ +void *unbound_stat_calloc_log(size_t nmemb, size_t size, const char* file, + int line, const char* func) +{ + log_info("%s:%d %s calloc(%u, %u)", file, line, func, + (unsigned) nmemb, (unsigned)size); + return unbound_stat_calloc(nmemb, size); +} + +/** log to file where free was done */ +void unbound_stat_free_log(void *ptr, const char* file, int line, + const char* func) +{ + if(ptr && memcmp(ptr-8, &mem_special, sizeof(mem_special)) == 0) { + size_t s; + memcpy(&s, ptr-16, sizeof(s)); + log_info("%s:%d %s free(%p) size %u", + file, line, func, ptr, (unsigned)s); + } else + log_info("%s:%d %s unmatched free(%p)", file, line, func, ptr); + unbound_stat_free(ptr); +} + +/** log to file where alloc was done */ +void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file, + int line, const char* func) +{ + log_info("%s:%d %s realloc(%p, %u)", file, line, func, + ptr, (unsigned)size); + return unbound_stat_realloc(ptr, size); +} + +#endif /* UNBOUND_ALLOC_STATS */ +#ifdef UNBOUND_ALLOC_LITE +#undef malloc +#undef calloc +#undef free +#undef realloc +/** length of prefix and suffix */ +static size_t lite_pad = 16; +/** prefix value to check */ +static char* lite_pre = "checkfront123456"; +/** suffix value to check */ +static char* lite_post= "checkafter123456"; + +void *unbound_stat_malloc_lite(size_t size, const char* file, int line, + const char* func) +{ + /* [prefix .. len .. actual data .. suffix] */ + void* res = malloc(size+lite_pad*2+sizeof(size_t)); + if(!res) return NULL; + memmove(res, lite_pre, lite_pad); + memmove(res+lite_pad, &size, sizeof(size_t)); + memset(res+lite_pad+sizeof(size_t), 0x1a, size); /* init the memory */ + memmove(res+lite_pad+size+sizeof(size_t), lite_post, lite_pad); + return res+lite_pad+sizeof(size_t); +} + +void *unbound_stat_calloc_lite(size_t nmemb, size_t size, const char* file, + int line, const char* func) +{ + size_t req = nmemb * size; + void* res = malloc(req+lite_pad*2+sizeof(size_t)); + if(!res) return NULL; + memmove(res, lite_pre, lite_pad); + memmove(res+lite_pad, &req, sizeof(size_t)); + memset(res+lite_pad+sizeof(size_t), 0, req); + memmove(res+lite_pad+req+sizeof(size_t), lite_post, lite_pad); + return res+lite_pad+sizeof(size_t); +} + +void unbound_stat_free_lite(void *ptr, const char* file, int line, + const char* func) +{ + void* real; + size_t orig = 0; + if(!ptr) return; + real = ptr-lite_pad-sizeof(size_t); + if(memcmp(real, lite_pre, lite_pad) != 0) { + log_err("free(): prefix failed %s:%d %s", file, line, func); + log_hex("prefix here", real, lite_pad); + log_hex(" should be", lite_pre, lite_pad); + fatal_exit("alloc assertion failed"); + } + memmove(&orig, real+lite_pad, sizeof(size_t)); + if(memcmp(real+lite_pad+orig+sizeof(size_t), lite_post, lite_pad)!=0){ + log_err("free(): suffix failed %s:%d %s", file, line, func); + log_err("alloc size is %d", (int)orig); + log_hex("suffix here", real+lite_pad+orig+sizeof(size_t), + lite_pad); + log_hex(" should be", lite_post, lite_pad); + fatal_exit("alloc assertion failed"); + } + memset(real, 0xdd, orig+lite_pad*2+sizeof(size_t)); /* mark it */ + free(real); +} + +void *unbound_stat_realloc_lite(void *ptr, size_t size, const char* file, + int line, const char* func) +{ + /* always free and realloc (no growing) */ + void* real, *newa; + size_t orig = 0; + if(!ptr) { + /* like malloc() */ + return unbound_stat_malloc_lite(size, file, line, func); + } + if(!size) { + /* like free() */ + unbound_stat_free_lite(ptr, file, line, func); + return NULL; + } + /* change allocation size and copy */ + real = ptr-lite_pad-sizeof(size_t); + if(memcmp(real, lite_pre, lite_pad) != 0) { + log_err("realloc(): prefix failed %s:%d %s", file, line, func); + log_hex("prefix here", real, lite_pad); + log_hex(" should be", lite_pre, lite_pad); + fatal_exit("alloc assertion failed"); + } + memmove(&orig, real+lite_pad, sizeof(size_t)); + if(memcmp(real+lite_pad+orig+sizeof(size_t), lite_post, lite_pad)!=0){ + log_err("realloc(): suffix failed %s:%d %s", file, line, func); + log_err("alloc size is %d", (int)orig); + log_hex("suffix here", real+lite_pad+orig+sizeof(size_t), + lite_pad); + log_hex(" should be", lite_post, lite_pad); + fatal_exit("alloc assertion failed"); + } + /* new alloc and copy over */ + newa = unbound_stat_malloc_lite(size, file, line, func); + if(!newa) + return NULL; + if(orig < size) + memmove(newa, ptr, orig); + else memmove(newa, ptr, size); + memset(real, 0xdd, orig+lite_pad*2+sizeof(size_t)); /* mark it */ + free(real); + return newa; +} + +char* unbound_strdup_lite(const char* s, const char* file, int line, + const char* func) +{ + /* this routine is made to make sure strdup() uses the malloc_lite */ + size_t l = strlen(s)+1; + char* n = (char*)unbound_stat_malloc_lite(l, file, line, func); + if(!n) return NULL; + memmove(n, s, l); + return n; +} + +char* unbound_lite_wrapstr(char* s) +{ + char* n = unbound_strdup_lite(s, __FILE__, __LINE__, __func__); + free(s); + return n; +} + +#undef ldns_pkt2wire +ldns_status unbound_lite_pkt2wire(uint8_t **dest, const ldns_pkt *p, + size_t *size) +{ + uint8_t* md = NULL; + size_t ms = 0; + ldns_status s = ldns_pkt2wire(&md, p, &ms); + if(md) { + *dest = unbound_stat_malloc_lite(ms, __FILE__, __LINE__, + __func__); + *size = ms; + if(!*dest) { free(md); return LDNS_STATUS_MEM_ERR; } + memcpy(*dest, md, ms); + free(md); + } else { + *dest = NULL; + *size = 0; + } + return s; +} + +#undef i2d_DSA_SIG +int unbound_lite_i2d_DSA_SIG(DSA_SIG* dsasig, unsigned char** sig) +{ + unsigned char* n = NULL; + int r= i2d_DSA_SIG(dsasig, &n); + if(n) { + *sig = unbound_stat_malloc_lite((size_t)r, __FILE__, __LINE__, + __func__); + if(!*sig) return -1; + memcpy(*sig, n, (size_t)r); + free(n); + return r; + } + *sig = NULL; + return r; +} + +#endif /* UNBOUND_ALLOC_LITE */ diff --git a/util/alloc.h b/util/alloc.h new file mode 100644 index 00000000000..4ed0053e2b4 --- /dev/null +++ b/util/alloc.h @@ -0,0 +1,214 @@ +/* + * util/alloc.h - memory allocation service. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains memory allocation functions. + * + * The reasons for this service are: + * o Avoid locking costs of getting global lock to call malloc(). + * o The packed rrset type needs to be kept on special freelists, + * so that they are reused for other packet rrset allocations. + * + */ + +#ifndef UTIL_ALLOC_H +#define UTIL_ALLOC_H + +#include "util/locks.h" +struct ub_packed_rrset_key; +struct regional; + +/** The special type, packed rrset. Not allowed to be used for other memory */ +typedef struct ub_packed_rrset_key alloc_special_t; +/** clean the special type. Pass pointer. */ +#define alloc_special_clean(x) (x)->id = 0; +/** access next pointer. (in available spot). Pass pointer. */ +#define alloc_special_next(x) ((alloc_special_t*)((x)->entry.overflow_next)) +/** set next pointer. (in available spot). Pass pointers. */ +#define alloc_set_special_next(x, y) \ + ((x)->entry.overflow_next) = (struct lruhash_entry*)(y); + +/** how many blocks to cache locally. */ +#define ALLOC_SPECIAL_MAX 10 + +/** + * Structure that provides allocation. Use one per thread. + * The one on top has a NULL super pointer. + */ +struct alloc_cache { + /** lock, only used for the super. */ + lock_quick_t lock; + /** global allocator above this one. NULL for none (malloc/free) */ + struct alloc_cache* super; + /** singly linked lists of special type. These are free for use. */ + alloc_special_t* quar; + /** number of items in quarantine. */ + size_t num_quar; + /** thread number for id creation */ + int thread_num; + /** next id number to pass out */ + uint64_t next_id; + /** last id number possible */ + uint64_t last_id; + /** what function to call to cleanup when last id is reached */ + void (*cleanup)(void*); + /** user arg for cleanup */ + void* cleanup_arg; + + /** how many regional blocks to keep back max */ + size_t max_reg_blocks; + /** how many regional blocks are kept now */ + size_t num_reg_blocks; + /** linked list of regional blocks, using regional->next */ + struct regional* reg_list; +}; + +/** + * Init alloc (zeroes the struct). + * @param alloc: this parameter is allocated by the caller. + * @param super: super to use (init that before with super_init). + * Pass this argument NULL to init the toplevel alloc structure. + * @param thread_num: thread number for id creation of special type. + */ +void alloc_init(struct alloc_cache* alloc, struct alloc_cache* super, + int thread_num); + +/** + * Free the alloc. Pushes all the cached items into the super structure. + * Or deletes them if alloc->super is NULL. + * Does not free the alloc struct itself (it was also allocated by caller). + * @param alloc: is almost zeroed on exit (except some stats). + */ +void alloc_clear(struct alloc_cache* alloc); + +/** + * Get a new special_t element. + * @param alloc: where to alloc it. + * @return: memory block. Will not return NULL (instead fatal_exit). + * The block is zeroed. + */ +alloc_special_t* alloc_special_obtain(struct alloc_cache* alloc); + +/** + * Return special_t back to pool. + * The block is cleaned up (zeroed) which also invalidates the ID inside. + * @param alloc: where to alloc it. + * @param mem: block to free. + */ +void alloc_special_release(struct alloc_cache* alloc, alloc_special_t* mem); + +/** + * Set ID number of special type to a fresh new ID number. + * In case of ID number overflow, the rrset cache has to be cleared. + * @param alloc: the alloc cache + * @return: fresh id is returned. + */ +uint64_t alloc_get_id(struct alloc_cache* alloc); + +/** + * Get memory size of alloc cache, alloc structure including special types. + * @param alloc: on what alloc. + * @return size in bytes. + */ +size_t alloc_get_mem(struct alloc_cache* alloc); + +/** + * Print debug information (statistics). + * @param alloc: on what alloc. + */ +void alloc_stats(struct alloc_cache* alloc); + +/** + * Get a new regional for query states + * @param alloc: where to alloc it. + * @return regional for use or NULL on alloc failure. + */ +struct regional* alloc_reg_obtain(struct alloc_cache* alloc); + +/** + * Put regional for query states back into alloc cache. + * @param alloc: where to alloc it. + * @param r: regional to put back. + */ +void alloc_reg_release(struct alloc_cache* alloc, struct regional* r); + +/** + * Set cleanup on ID overflow callback function. This should remove all + * RRset ID references from the program. Clear the caches. + * @param alloc: the alloc + * @param cleanup: the callback function, called as cleanup(arg). + * @param arg: user argument to callback function. + */ +void alloc_set_id_cleanup(struct alloc_cache* alloc, void (*cleanup)(void*), + void* arg); + +#ifdef UNBOUND_ALLOC_LITE +# include +# include +# define malloc(s) unbound_stat_malloc_lite(s, __FILE__, __LINE__, __func__) +# define calloc(n,s) unbound_stat_calloc_lite(n, s, __FILE__, __LINE__, __func__) +# define free(p) unbound_stat_free_lite(p, __FILE__, __LINE__, __func__) +# define realloc(p,s) unbound_stat_realloc_lite(p, s, __FILE__, __LINE__, __func__) +void *unbound_stat_malloc_lite(size_t size, const char* file, int line, + const char* func); +void *unbound_stat_calloc_lite(size_t nmemb, size_t size, const char* file, + int line, const char* func); +void unbound_stat_free_lite(void *ptr, const char* file, int line, + const char* func); +void *unbound_stat_realloc_lite(void *ptr, size_t size, const char* file, + int line, const char* func); +# ifdef strdup +# undef strdup +# endif +# define strdup(s) unbound_strdup_lite(s, __FILE__, __LINE__, __func__) +char* unbound_strdup_lite(const char* s, const char* file, int line, + const char* func); +char* unbound_lite_wrapstr(char* s); +# define ldns_rr2str(rr) unbound_lite_wrapstr(ldns_rr2str(rr)) +# define ldns_rdf2str(rdf) unbound_lite_wrapstr(ldns_rdf2str(rdf)) +# define ldns_rr_type2str(t) unbound_lite_wrapstr(ldns_rr_type2str(t)) +# define ldns_rr_class2str(c) unbound_lite_wrapstr(ldns_rr_class2str(c)) +# define ldns_rr_list2str(r) unbound_lite_wrapstr(ldns_rr_list2str(r)) +# define ldns_pkt2str(p) unbound_lite_wrapstr(ldns_pkt2str(p)) +# define ldns_pkt_rcode2str(r) unbound_lite_wrapstr(ldns_pkt_rcode2str(r)) +# define ldns_pkt2wire(a, r, s) unbound_lite_pkt2wire(a, r, s) +ldns_status unbound_lite_pkt2wire(uint8_t **dest, const ldns_pkt *p, size_t *size); +# define i2d_DSA_SIG(d, s) unbound_lite_i2d_DSA_SIG(d, s) +int unbound_lite_i2d_DSA_SIG(DSA_SIG* dsasig, unsigned char** sig); +#endif /* UNBOUND_ALLOC_LITE */ + +#endif /* UTIL_ALLOC_H */ diff --git a/util/config_file.c b/util/config_file.c new file mode 100644 index 00000000000..8ba79d2a29c --- /dev/null +++ b/util/config_file.c @@ -0,0 +1,1489 @@ +/* + * util/config_file.c - reads and stores the config file for unbound. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions for the config file. + */ + +#include "config.h" +#include +#include +#include "util/log.h" + +#include "util/configyyrename.h" +#include "util/config_file.h" +#include "util/configparser.h" +#include "util/net_help.h" +#include "util/data/msgparse.h" +#include "util/module.h" +#include "util/regional.h" +#include "util/fptr_wlist.h" +#include "util/data/dname.h" +/** global config during parsing */ +struct config_parser_state* cfg_parser = 0; +/** lex in file */ +extern FILE* ub_c_in; +/** lex out file */ +extern FILE* ub_c_out; +/** the yacc lex generated parse function */ +int ub_c_parse(void); +/** the lexer function */ +int ub_c_lex(void); +/** wrap function */ +int ub_c_wrap(void); + +/** init ports possible for use */ +static void init_outgoing_availports(int* array, int num); + +struct config_file* +config_create(void) +{ + struct config_file* cfg; + cfg = (struct config_file*)calloc(1, sizeof(struct config_file)); + if(!cfg) + return NULL; + /* the defaults if no config is present */ + cfg->verbosity = 1; + cfg->stat_interval = 0; + cfg->stat_cumulative = 0; + cfg->stat_extended = 0; + cfg->num_threads = 1; + cfg->port = UNBOUND_DNS_PORT; + cfg->do_ip4 = 1; + cfg->do_ip6 = 1; + cfg->do_udp = 1; + cfg->do_tcp = 1; + cfg->tcp_upstream = 0; + cfg->ssl_service_key = NULL; + cfg->ssl_service_pem = NULL; + cfg->ssl_port = 443; + cfg->ssl_upstream = 0; + cfg->use_syslog = 1; + cfg->log_time_ascii = 0; + cfg->log_queries = 0; +#ifndef USE_WINSOCK +# ifdef USE_MINI_EVENT + /* select max 1024 sockets */ + cfg->outgoing_num_ports = 960; + cfg->num_queries_per_thread = 512; +# else + /* libevent can use many sockets */ + cfg->outgoing_num_ports = 4096; + cfg->num_queries_per_thread = 1024; +# endif + cfg->outgoing_num_tcp = 10; + cfg->incoming_num_tcp = 10; +#else + cfg->outgoing_num_ports = 48; /* windows is limited in num fds */ + cfg->num_queries_per_thread = 24; + cfg->outgoing_num_tcp = 2; /* leaves 64-52=12 for: 4if,1stop,thread4 */ + cfg->incoming_num_tcp = 2; +#endif + cfg->edns_buffer_size = 4096; /* 4k from rfc recommendation */ + cfg->msg_buffer_size = 65552; /* 64 k + a small margin */ + cfg->msg_cache_size = 4 * 1024 * 1024; + cfg->msg_cache_slabs = 4; + cfg->jostle_time = 200; + cfg->rrset_cache_size = 4 * 1024 * 1024; + cfg->rrset_cache_slabs = 4; + cfg->host_ttl = 900; + cfg->bogus_ttl = 60; + cfg->min_ttl = 0; + cfg->max_ttl = 3600 * 24; + cfg->prefetch = 0; + cfg->prefetch_key = 0; + cfg->infra_cache_slabs = 4; + cfg->infra_cache_numhosts = 10000; + if(!(cfg->outgoing_avail_ports = (int*)calloc(65536, sizeof(int)))) + goto error_exit; + init_outgoing_availports(cfg->outgoing_avail_ports, 65536); + if(!(cfg->username = strdup(UB_USERNAME))) goto error_exit; +#ifdef HAVE_CHROOT + if(!(cfg->chrootdir = strdup(CHROOT_DIR))) goto error_exit; +#endif + if(!(cfg->directory = strdup(RUN_DIR))) goto error_exit; + if(!(cfg->logfile = strdup(""))) goto error_exit; + if(!(cfg->pidfile = strdup(PIDFILE))) goto error_exit; + if(!(cfg->target_fetch_policy = strdup("3 2 1 0 0"))) goto error_exit; + cfg->donotqueryaddrs = NULL; + cfg->donotquery_localhost = 1; + cfg->root_hints = NULL; + cfg->do_daemonize = 1; + cfg->if_automatic = 0; + cfg->so_rcvbuf = 0; + cfg->so_sndbuf = 0; + cfg->num_ifs = 0; + cfg->ifs = NULL; + cfg->num_out_ifs = 0; + cfg->out_ifs = NULL; + cfg->stubs = NULL; + cfg->forwards = NULL; + cfg->acls = NULL; + cfg->harden_short_bufsize = 0; + cfg->harden_large_queries = 0; + cfg->harden_glue = 1; + cfg->harden_dnssec_stripped = 1; + cfg->harden_below_nxdomain = 0; + cfg->harden_referral_path = 0; + cfg->use_caps_bits_for_id = 0; + cfg->private_address = NULL; + cfg->private_domain = NULL; + cfg->unwanted_threshold = 0; + cfg->hide_identity = 0; + cfg->hide_version = 0; + cfg->identity = NULL; + cfg->version = NULL; + cfg->auto_trust_anchor_file_list = NULL; + cfg->trust_anchor_file_list = NULL; + cfg->trust_anchor_list = NULL; + cfg->trusted_keys_file_list = NULL; + cfg->dlv_anchor_file = NULL; + cfg->dlv_anchor_list = NULL; + cfg->domain_insecure = NULL; + cfg->val_date_override = 0; + cfg->val_sig_skew_min = 3600; /* at least daylight savings trouble */ + cfg->val_sig_skew_max = 86400; /* at most timezone settings trouble */ + cfg->val_clean_additional = 1; + cfg->val_log_level = 0; + cfg->val_log_squelch = 0; + cfg->val_permissive_mode = 0; + cfg->ignore_cd = 0; + cfg->add_holddown = 30*24*3600; + cfg->del_holddown = 30*24*3600; + cfg->keep_missing = 366*24*3600; /* one year plus a little leeway */ + cfg->key_cache_size = 4 * 1024 * 1024; + cfg->key_cache_slabs = 4; + cfg->neg_cache_size = 1 * 1024 * 1024; + cfg->local_zones = NULL; + cfg->local_zones_nodefault = NULL; + cfg->local_data = NULL; + cfg->python_script = NULL; + cfg->remote_control_enable = 0; + cfg->control_ifs = NULL; + cfg->control_port = UNBOUND_CONTROL_PORT; + cfg->minimal_responses = 0; + cfg->rrset_roundrobin = 0; + if(!(cfg->server_key_file = strdup(RUN_DIR"/unbound_server.key"))) + goto error_exit; + if(!(cfg->server_cert_file = strdup(RUN_DIR"/unbound_server.pem"))) + goto error_exit; + if(!(cfg->control_key_file = strdup(RUN_DIR"/unbound_control.key"))) + goto error_exit; + if(!(cfg->control_cert_file = strdup(RUN_DIR"/unbound_control.pem"))) + goto error_exit; + + if(!(cfg->module_conf = strdup("validator iterator"))) goto error_exit; + if(!(cfg->val_nsec3_key_iterations = + strdup("1024 150 2048 500 4096 2500"))) goto error_exit; + return cfg; +error_exit: + config_delete(cfg); + return NULL; +} + +struct config_file* config_create_forlib(void) +{ + struct config_file* cfg = config_create(); + if(!cfg) return NULL; + /* modifications for library use, less verbose, less memory */ + free(cfg->chrootdir); + cfg->chrootdir = NULL; + cfg->verbosity = 0; + cfg->outgoing_num_ports = 16; /* in library use, this is 'reasonable' + and probably within the ulimit(maxfds) of the user */ + cfg->outgoing_num_tcp = 2; + cfg->msg_cache_size = 1024*1024; + cfg->msg_cache_slabs = 1; + cfg->rrset_cache_size = 1024*1024; + cfg->rrset_cache_slabs = 1; + cfg->infra_cache_slabs = 1; + cfg->use_syslog = 0; + cfg->key_cache_size = 1024*1024; + cfg->key_cache_slabs = 1; + cfg->neg_cache_size = 100 * 1024; + cfg->donotquery_localhost = 0; /* allow, so that you can ask a + forward nameserver running on localhost */ + cfg->val_log_level = 2; /* to fill why_bogus with */ + cfg->val_log_squelch = 1; + return cfg; +} + +/** check that the value passed is >= 0 */ +#define IS_NUMBER_OR_ZERO \ + if(atoi(val) == 0 && strcmp(val, "0") != 0) return 0 +/** check that the value passed is > 0 */ +#define IS_NONZERO_NUMBER \ + if(atoi(val) == 0) return 0 +/** check that the value passed is not 0 and a power of 2 */ +#define IS_POW2_NUMBER \ + if(atoi(val) == 0 || !is_pow2((size_t)atoi(val))) return 0 +/** check that the value passed is yes or no */ +#define IS_YES_OR_NO \ + if(strcmp(val, "yes") != 0 && strcmp(val, "no") != 0) return 0 +/** put integer_or_zero into variable */ +#define S_NUMBER_OR_ZERO(str, var) if(strcmp(opt, str) == 0) \ + { IS_NUMBER_OR_ZERO; cfg->var = atoi(val); } +/** put integer_nonzero into variable */ +#define S_NUMBER_NONZERO(str, var) if(strcmp(opt, str) == 0) \ + { IS_NONZERO_NUMBER; cfg->var = atoi(val); } +/** put integer_or_zero into unsigned */ +#define S_UNSIGNED_OR_ZERO(str, var) if(strcmp(opt, str) == 0) \ + { IS_NUMBER_OR_ZERO; cfg->var = (unsigned)atoi(val); } +/** put integer_or_zero into size_t */ +#define S_SIZET_OR_ZERO(str, var) if(strcmp(opt, str) == 0) \ + { IS_NUMBER_OR_ZERO; cfg->var = (size_t)atoi(val); } +/** put integer_nonzero into size_t */ +#define S_SIZET_NONZERO(str, var) if(strcmp(opt, str) == 0) \ + { IS_NONZERO_NUMBER; cfg->var = (size_t)atoi(val); } +/** put yesno into variable */ +#define S_YNO(str, var) if(strcmp(opt, str) == 0) \ + { IS_YES_OR_NO; cfg->var = (strcmp(val, "yes") == 0); } +/** put memsize into variable */ +#define S_MEMSIZE(str, var) if(strcmp(opt, str)==0) \ + { return cfg_parse_memsize(val, &cfg->var); } +/** put pow2 number into variable */ +#define S_POW2(str, var) if(strcmp(opt, str)==0) \ + { IS_POW2_NUMBER; cfg->var = (size_t)atoi(val); } +/** put string into variable */ +#define S_STR(str, var) if(strcmp(opt, str)==0) \ + { free(cfg->var); return (cfg->var = strdup(val)) != NULL; } +/** put string into strlist */ +#define S_STRLIST(str, var) if(strcmp(opt, str)==0) \ + { return cfg_strlist_insert(&cfg->var, strdup(val)); } + +int config_set_option(struct config_file* cfg, const char* opt, + const char* val) +{ + S_NUMBER_OR_ZERO("verbosity:", verbosity) + else if(strcmp(opt, "statistics-interval:") == 0) { + if(strcmp(val, "0") == 0 || strcmp(val, "") == 0) + cfg->stat_interval = 0; + else if(atoi(val) == 0) + return 0; + else cfg->stat_interval = atoi(val); + } else if(strcmp(opt, "num_threads:") == 0) { + /* not supported, library must have 1 thread in bgworker */ + return 0; + } else if(strcmp(opt, "outgoing-port-permit:") == 0) { + return cfg_mark_ports(val, 1, + cfg->outgoing_avail_ports, 65536); + } else if(strcmp(opt, "outgoing-port-avoid:") == 0) { + return cfg_mark_ports(val, 0, + cfg->outgoing_avail_ports, 65536); + } else if(strcmp(opt, "local-zone:") == 0) { + return cfg_parse_local_zone(cfg, val); + } else if(strcmp(opt, "val-override-date:") == 0) { + if(strcmp(val, "") == 0 || strcmp(val, "0") == 0) { + cfg->val_date_override = 0; + } else if(strlen(val) == 14) { + cfg->val_date_override = cfg_convert_timeval(val); + return cfg->val_date_override != 0; + } else { + if(atoi(val) == 0) return 0; + cfg->val_date_override = (uint32_t)atoi(val); + } + } else if(strcmp(opt, "local-data-ptr:") == 0) { + char* ptr = cfg_ptr_reverse((char*)opt); + return cfg_strlist_insert(&cfg->local_data, ptr); + } else if(strcmp(opt, "logfile:") == 0) { + cfg->use_syslog = 0; + free(cfg->logfile); + return (cfg->logfile = strdup(val)) != NULL; + } + else S_YNO("use-syslog:", use_syslog) + else S_YNO("extended-statistics:", stat_extended) + else S_YNO("statistics-cumulative:", stat_cumulative) + else S_YNO("do-ip4:", do_ip4) + else S_YNO("do-ip6:", do_ip6) + else S_YNO("do-udp:", do_udp) + else S_YNO("do-tcp:", do_tcp) + else S_YNO("tcp-upstream:", tcp_upstream) + else S_YNO("ssl-upstream:", ssl_upstream) + else S_STR("ssl-service-key:", ssl_service_key) + else S_STR("ssl-service-pem:", ssl_service_pem) + else S_NUMBER_NONZERO("ssl-port:", ssl_port) + else S_YNO("interface-automatic:", if_automatic) + else S_YNO("do-daemonize:", do_daemonize) + else S_NUMBER_NONZERO("port:", port) + else S_NUMBER_NONZERO("outgoing-range:", outgoing_num_ports) + else S_SIZET_OR_ZERO("outgoing-num-tcp:", outgoing_num_tcp) + else S_SIZET_OR_ZERO("incoming-num-tcp:", incoming_num_tcp) + else S_SIZET_NONZERO("edns-buffer-size:", edns_buffer_size) + else S_SIZET_NONZERO("msg-buffer-size:", msg_buffer_size) + else S_MEMSIZE("msg-cache-size:", msg_cache_size) + else S_POW2("msg-cache-slabs:", msg_cache_slabs) + else S_SIZET_NONZERO("num-queries-per-thread:",num_queries_per_thread) + else S_SIZET_OR_ZERO("jostle-timeout:", jostle_time) + else S_MEMSIZE("so-rcvbuf:", so_rcvbuf) + else S_MEMSIZE("so-sndbuf:", so_sndbuf) + else S_MEMSIZE("rrset-cache-size:", rrset_cache_size) + else S_POW2("rrset-cache-slabs:", rrset_cache_slabs) + else S_YNO("prefetch:", prefetch) + else S_YNO("prefetch-key:", prefetch_key) + else S_NUMBER_OR_ZERO("cache-max-ttl:", max_ttl) + else S_NUMBER_OR_ZERO("infra-host-ttl:", host_ttl) + else S_POW2("infra-cache-slabs:", infra_cache_slabs) + else S_SIZET_NONZERO("infra-cache-numhosts:", infra_cache_numhosts) + else S_STR("chroot:", chrootdir) + else S_STR("username:", username) + else S_STR("directory:", directory) + else S_STR("pidfile:", pidfile) + else S_YNO("hide-identity:", hide_identity) + else S_YNO("hide-version:", hide_version) + else S_STR("identity:", identity) + else S_STR("version:", version) + else S_STRLIST("root-hints:", root_hints) + else S_STR("target-fetch-policy:", target_fetch_policy) + else S_YNO("harden-glue:", harden_glue) + else S_YNO("harden-short-bufsize:", harden_short_bufsize) + else S_YNO("harden-large-queries:", harden_large_queries) + else S_YNO("harden-dnssec-stripped:", harden_dnssec_stripped) + else S_YNO("harden-below-nxdomain:", harden_below_nxdomain) + else S_YNO("harden-referral-path:", harden_referral_path) + else S_YNO("use-caps-for-id", use_caps_bits_for_id) + else S_SIZET_OR_ZERO("unwanted-reply-threshold:", unwanted_threshold) + else S_STRLIST("private-address:", private_address) + else S_STRLIST("private-domain:", private_domain) + else S_YNO("do-not-query-localhost:", donotquery_localhost) + else S_STRLIST("do-not-query-address:", donotqueryaddrs) + else S_STRLIST("auto-trust-anchor-file:", auto_trust_anchor_file_list) + else S_STRLIST("trust-anchor-file:", trust_anchor_file_list) + else S_STRLIST("trust-anchor:", trust_anchor_list) + else S_STRLIST("trusted-keys-file:", trusted_keys_file_list) + else S_STR("dlv-anchor-file:", dlv_anchor_file) + else S_STRLIST("dlv-anchor:", dlv_anchor_list) + else S_STRLIST("domain-insecure:", domain_insecure) + else S_NUMBER_OR_ZERO("val-bogus-ttl:", bogus_ttl) + else S_YNO("val-clean-additional:", val_clean_additional) + else S_NUMBER_OR_ZERO("val-log-level:", val_log_level) + else S_YNO("val-log-squelch:", val_log_squelch) + else S_YNO("log-queries:", log_queries) + else S_YNO("val-permissive-mode:", val_permissive_mode) + else S_YNO("ignore-cd-flag:", ignore_cd) + else S_STR("val-nsec3-keysize-iterations:", val_nsec3_key_iterations) + else S_UNSIGNED_OR_ZERO("add-holddown:", add_holddown) + else S_UNSIGNED_OR_ZERO("del-holddown:", del_holddown) + else S_UNSIGNED_OR_ZERO("keep-missing:", keep_missing) + else S_MEMSIZE("key-cache-size:", key_cache_size) + else S_POW2("key-cache-slabs:", key_cache_slabs) + else S_MEMSIZE("neg-cache-size:", neg_cache_size) + else S_YNO("minimal-responses:", minimal_responses) + else S_YNO("rrset-roundrobin:", rrset_roundrobin) + else S_STRLIST("local-data:", local_data) + else S_YNO("control-enable:", remote_control_enable) + else S_STRLIST("control-interface:", control_ifs) + else S_NUMBER_NONZERO("control-port:", control_port) + else S_STR("server-key-file:", server_key_file) + else S_STR("server-cert-file:", server_cert_file) + else S_STR("control-key-file:", control_key_file) + else S_STR("control-cert-file:", control_cert_file) + else S_STR("module-config:", module_conf) + else S_STR("python-script:", python_script) + else if (strcmp(opt, "outgoing-interface:") == 0) { + char* d = strdup(val); + char** oi = (char**)malloc((cfg->num_out_ifs+1)*sizeof(char*)); + if(!d || !oi) { free(d); free(oi); return -1; } + if(cfg->out_ifs && cfg->num_out_ifs) { + memmove(oi, cfg->out_ifs, cfg->num_out_ifs*sizeof(char*)); + free(cfg->out_ifs); + } + oi[cfg->num_out_ifs++] = d; + cfg->out_ifs = oi; + } else { + /* unknown or unsupported (from the set_option interface): + * interface, outgoing-interface, access-control, + * stub-zone, name, stub-addr, stub-host, stub-prime + * forward-first, stub-first, + * forward-zone, name, forward-addr, forward-host */ + return 0; + } + return 1; +} + +void config_print_func(char* line, void* arg) +{ + FILE* f = (FILE*)arg; + (void)fprintf(f, "%s\n", line); +} + +/** collate func arg */ +struct config_collate_arg { + /** list of result items */ + struct config_strlist_head list; + /** if a malloc error occurred, 0 is OK */ + int status; +}; + +void config_collate_func(char* line, void* arg) +{ + struct config_collate_arg* m = (struct config_collate_arg*)arg; + if(m->status) + return; + if(!cfg_strlist_append(&m->list, strdup(line))) + m->status = 1; +} + +int config_get_option_list(struct config_file* cfg, const char* opt, + struct config_strlist** list) +{ + struct config_collate_arg m; + memset(&m, 0, sizeof(m)); + *list = NULL; + if(!config_get_option(cfg, opt, config_collate_func, &m)) + return 1; + if(m.status) { + config_delstrlist(m.list.first); + return 2; + } + *list = m.list.first; + return 0; +} + +int +config_get_option_collate(struct config_file* cfg, const char* opt, char** str) +{ + struct config_strlist* list = NULL; + int r; + *str = NULL; + if((r = config_get_option_list(cfg, opt, &list)) != 0) + return r; + *str = config_collate_cat(list); + config_delstrlist(list); + if(!*str) return 2; + return 0; +} + +char* +config_collate_cat(struct config_strlist* list) +{ + size_t total = 0, left; + struct config_strlist* s; + char *r, *w; + if(!list) /* no elements */ + return strdup(""); + if(list->next == NULL) /* one element , no newline at end. */ + return strdup(list->str); + /* count total length */ + for(s=list; s; s=s->next) + total += strlen(s->str) + 1; /* len + newline */ + left = total+1; /* one extra for nul at end */ + r = malloc(left); + if(!r) + return NULL; + w = r; + for(s=list; s; s=s->next) { + size_t this = strlen(s->str); + if(this+2 > left) { /* sanity check */ + free(r); + return NULL; + } + snprintf(w, left, "%s\n", s->str); + w += this+1; + left -= this+1; + } + return r; +} + +/** compare and print decimal option */ +#define O_DEC(opt, str, var) if(strcmp(opt, str)==0) \ + {snprintf(buf, len, "%d", (int)cfg->var); \ + func(buf, arg);} +/** compare and print unsigned option */ +#define O_UNS(opt, str, var) if(strcmp(opt, str)==0) \ + {snprintf(buf, len, "%u", (unsigned)cfg->var); \ + func(buf, arg);} +/** compare and print yesno option */ +#define O_YNO(opt, str, var) if(strcmp(opt, str)==0) \ + {func(cfg->var?"yes":"no", arg);} +/** compare and print string option */ +#define O_STR(opt, str, var) if(strcmp(opt, str)==0) \ + {func(cfg->var?cfg->var:"", arg);} +/** compare and print array option */ +#define O_IFC(opt, str, num, arr) if(strcmp(opt, str)==0) \ + {int i; for(i=0; inum; i++) func(cfg->arr[i], arg);} +/** compare and print memorysize option */ +#define O_MEM(opt, str, var) if(strcmp(opt, str)==0) { \ + if(cfg->var > 1024*1024*1024) { \ + size_t f=cfg->var/(size_t)1000000, b=cfg->var%(size_t)1000000; \ + snprintf(buf, len, "%u%6.6u\n", (unsigned)f, (unsigned)b); \ + } else snprintf(buf, len, "%u\n", (unsigned)cfg->var); \ + func(buf, arg);} +/** compare and print list option */ +#define O_LST(opt, name, lst) if(strcmp(opt, name)==0) { \ + struct config_strlist* p = cfg->lst; \ + for(p = cfg->lst; p; p = p->next) \ + func(p->str, arg); \ + } +/** 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); \ + func(buf, arg); \ + } + +int +config_get_option(struct config_file* cfg, const char* opt, + void (*func)(char*,void*), void* arg) +{ + char buf[1024]; + size_t len = sizeof(buf); + fptr_ok(fptr_whitelist_print_func(func)); + O_DEC(opt, "verbosity", verbosity) + else O_DEC(opt, "statistics-interval", stat_interval) + else O_YNO(opt, "statistics-cumulative", stat_cumulative) + else O_YNO(opt, "extended-statistics", stat_extended) + else O_YNO(opt, "use-syslog", use_syslog) + else O_DEC(opt, "num-threads", num_threads) + else O_IFC(opt, "interface", num_ifs, ifs) + else O_IFC(opt, "outgoing-interface", num_out_ifs, out_ifs) + else O_YNO(opt, "interface-automatic", if_automatic) + else O_DEC(opt, "port", port) + else O_DEC(opt, "outgoing-range", outgoing_num_ports) + else O_DEC(opt, "outgoing-num-tcp", outgoing_num_tcp) + else O_DEC(opt, "incoming-num-tcp", incoming_num_tcp) + else O_DEC(opt, "edns-buffer-size", edns_buffer_size) + else O_DEC(opt, "msg-buffer-size", msg_buffer_size) + else O_MEM(opt, "msg-cache-size", msg_cache_size) + else O_DEC(opt, "msg-cache-slabs", msg_cache_slabs) + else O_DEC(opt, "num-queries-per-thread", num_queries_per_thread) + else O_UNS(opt, "jostle-timeout", jostle_time) + else O_MEM(opt, "so-rcvbuf", so_rcvbuf) + else O_MEM(opt, "so-sndbuf", so_sndbuf) + 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) + else O_YNO(opt, "prefetch", prefetch) + else O_DEC(opt, "cache-max-ttl", max_ttl) + else O_DEC(opt, "infra-host-ttl", host_ttl) + else O_DEC(opt, "infra-cache-slabs", infra_cache_slabs) + else O_MEM(opt, "infra-cache-numhosts", infra_cache_numhosts) + else O_YNO(opt, "do-ip4", do_ip4) + else O_YNO(opt, "do-ip6", do_ip6) + else O_YNO(opt, "do-udp", do_udp) + else O_YNO(opt, "do-tcp", do_tcp) + else O_YNO(opt, "tcp-upstream", tcp_upstream) + else O_YNO(opt, "ssl-upstream", ssl_upstream) + else O_STR(opt, "ssl-service-key", ssl_service_key) + else O_STR(opt, "ssl-service-pem", ssl_service_pem) + else O_DEC(opt, "ssl-port", ssl_port) + else O_YNO(opt, "do-daemonize", do_daemonize) + else O_STR(opt, "chroot", chrootdir) + else O_STR(opt, "username", username) + else O_STR(opt, "directory", directory) + else O_STR(opt, "logfile", logfile) + else O_YNO(opt, "log-queries", log_queries) + else O_STR(opt, "pidfile", pidfile) + else O_YNO(opt, "hide-identity", hide_identity) + else O_YNO(opt, "hide-version", hide_version) + else O_STR(opt, "identity", identity) + else O_STR(opt, "version", version) + else O_STR(opt, "target-fetch-policy", target_fetch_policy) + else O_YNO(opt, "harden-short-bufsize", harden_short_bufsize) + else O_YNO(opt, "harden-large-queries", harden_large_queries) + else O_YNO(opt, "harden-glue", harden_glue) + else O_YNO(opt, "harden-dnssec-stripped", harden_dnssec_stripped) + else O_YNO(opt, "harden-below-nxdomain", harden_below_nxdomain) + else O_YNO(opt, "harden-referral-path", harden_referral_path) + else O_YNO(opt, "use-caps-for-id", use_caps_bits_for_id) + else O_DEC(opt, "unwanted-reply-threshold", unwanted_threshold) + else O_YNO(opt, "do-not-query-localhost", donotquery_localhost) + else O_STR(opt, "module-config", module_conf) + else O_STR(opt, "dlv-anchor-file", dlv_anchor_file) + else O_DEC(opt, "val-bogus-ttl", bogus_ttl) + else O_YNO(opt, "val-clean-additional", val_clean_additional) + else O_DEC(opt, "val-log-level", val_log_level) + else O_YNO(opt, "val-permissive-mode", val_permissive_mode) + else O_YNO(opt, "ignore-cd-flag", ignore_cd) + else O_STR(opt, "val-nsec3-keysize-iterations",val_nsec3_key_iterations) + else O_UNS(opt, "add-holddown", add_holddown) + else O_UNS(opt, "del-holddown", del_holddown) + else O_UNS(opt, "keep-missing", keep_missing) + else O_MEM(opt, "key-cache-size", key_cache_size) + else O_DEC(opt, "key-cache-slabs", key_cache_slabs) + else O_MEM(opt, "neg-cache-size", neg_cache_size) + else O_YNO(opt, "control-enable", remote_control_enable) + else O_DEC(opt, "control-port", control_port) + else O_STR(opt, "server-key-file", server_key_file) + else O_STR(opt, "server-cert-file", server_cert_file) + else O_STR(opt, "control-key-file", control_key_file) + else O_STR(opt, "control-cert-file", control_cert_file) + else O_LST(opt, "root-hints", root_hints) + else O_LS2(opt, "access-control", acls) + else O_LST(opt, "do-not-query-address", donotqueryaddrs) + else O_LST(opt, "private-address", private_address) + else O_LST(opt, "private-domain", private_domain) + else O_LST(opt, "auto-trust-anchor-file", auto_trust_anchor_file_list) + else O_LST(opt, "trust-anchor-file", trust_anchor_file_list) + else O_LST(opt, "trust-anchor", trust_anchor_list) + else O_LST(opt, "trusted-keys-file", trusted_keys_file_list) + else O_LST(opt, "dlv-anchor", dlv_anchor_list) + else O_LST(opt, "control-interface", control_ifs) + else O_LST(opt, "domain-insecure", domain_insecure) + else O_UNS(opt, "val-override-date", val_date_override) + else O_YNO(opt, "minimal-responses", minimal_responses) + else O_YNO(opt, "rrset-roundrobin", rrset_roundrobin) + /* not here: + * outgoing-permit, outgoing-avoid - have list of ports + * local-zone - zones and nodefault variables + * local-data - see below + * local-data-ptr - converted to local-data entries + * stub-zone, name, stub-addr, stub-host, stub-prime + * forward-zone, name, forward-addr, forward-host + */ + else return 0; + return 1; +} + +/** initialize the global cfg_parser object */ +static void +create_cfg_parser(struct config_file* cfg, char* filename, const char* chroot) +{ + static struct config_parser_state st; + cfg_parser = &st; + cfg_parser->filename = filename; + cfg_parser->line = 1; + cfg_parser->errors = 0; + cfg_parser->cfg = cfg; + cfg_parser->chroot = chroot; +} + +int +config_read(struct config_file* cfg, const char* filename, const char* chroot) +{ + FILE *in; + char *fname = (char*)filename; + if(!fname) + return 1; + in = fopen(fname, "r"); + if(!in) { + log_err("Could not open %s: %s", fname, strerror(errno)); + return 0; + } + create_cfg_parser(cfg, fname, chroot); + ub_c_in = in; + ub_c_parse(); + fclose(in); + + if(cfg_parser->errors != 0) { + fprintf(stderr, "read %s failed: %d errors in configuration file\n", + cfg_parser->filename, cfg_parser->errors); + errno=EINVAL; + return 0; + } + return 1; +} + +void +config_delstrlist(struct config_strlist* p) +{ + struct config_strlist *np; + while(p) { + np = p->next; + free(p->str); + free(p); + p = np; + } +} + +void +config_deldblstrlist(struct config_str2list* p) +{ + struct config_str2list *np; + while(p) { + np = p->next; + free(p->str); + free(p->str2); + free(p); + p = np; + } +} + +void +config_delstubs(struct config_stub* p) +{ + struct config_stub* np; + while(p) { + np = p->next; + free(p->name); + config_delstrlist(p->hosts); + config_delstrlist(p->addrs); + free(p); + p = np; + } +} + +void +config_delete(struct config_file* cfg) +{ + if(!cfg) return; + free(cfg->username); + free(cfg->chrootdir); + free(cfg->directory); + free(cfg->logfile); + free(cfg->pidfile); + free(cfg->target_fetch_policy); + free(cfg->ssl_service_key); + free(cfg->ssl_service_pem); + if(cfg->ifs) { + int i; + for(i=0; inum_ifs; i++) + free(cfg->ifs[i]); + free(cfg->ifs); + } + if(cfg->out_ifs) { + int i; + for(i=0; inum_out_ifs; i++) + free(cfg->out_ifs[i]); + free(cfg->out_ifs); + } + config_delstubs(cfg->stubs); + config_delstubs(cfg->forwards); + config_delstrlist(cfg->donotqueryaddrs); + config_delstrlist(cfg->root_hints); + free(cfg->identity); + free(cfg->version); + free(cfg->module_conf); + free(cfg->outgoing_avail_ports); + config_delstrlist(cfg->private_address); + config_delstrlist(cfg->private_domain); + config_delstrlist(cfg->auto_trust_anchor_file_list); + config_delstrlist(cfg->trust_anchor_file_list); + config_delstrlist(cfg->trusted_keys_file_list); + config_delstrlist(cfg->trust_anchor_list); + config_delstrlist(cfg->domain_insecure); + free(cfg->dlv_anchor_file); + config_delstrlist(cfg->dlv_anchor_list); + config_deldblstrlist(cfg->acls); + free(cfg->val_nsec3_key_iterations); + config_deldblstrlist(cfg->local_zones); + config_delstrlist(cfg->local_zones_nodefault); + config_delstrlist(cfg->local_data); + config_delstrlist(cfg->control_ifs); + free(cfg->server_key_file); + free(cfg->server_cert_file); + free(cfg->control_key_file); + free(cfg->control_cert_file); + free(cfg); +} + +static void +init_outgoing_availports(int* a, int num) +{ + /* generated with make iana_update */ + const int iana_assigned[] = { +#include "util/iana_ports.inc" + -1 }; /* end marker to put behind trailing comma */ + + int i; + /* do not use <1024, that could be trouble with the system, privs */ + for(i=1024; i= (int)sizeof(buf) ) { + log_err("cannot parse port number '%s'", str); + return 0; + } + if(mid > str) + memcpy(buf, str, (size_t)(mid-str)); + buf[mid-str] = 0; + low = atoi(buf); + if(low == 0 && strcmp(buf, "0") != 0) { + log_err("cannot parse port number '%s'", buf); + return 0; + } + for(i=low; i<=high; i++) { + if(i < num) + avail[i] = (allow?i:0); + } + return 1; + } + return 1; +} + +int +cfg_scan_ports(int* avail, int num) +{ + int i; + int count = 0; + for(i=0; ioutgoing_avail_ports, 65536); + int i, at = 0; + *avail = NULL; + if(num == 0) + return 0; + *avail = (int*)malloc(sizeof(int)*num); + if(!*avail) + return 0; + for(i=0; i<65536; i++) { + if(cfg->outgoing_avail_ports[i]) + (*avail)[at++] = cfg->outgoing_avail_ports[i]; + } + log_assert(at == num); + return num; +} + +/** print error with file and line number */ +static void ub_c_error_va_list(const char *fmt, va_list args) +{ + cfg_parser->errors++; + fprintf(stderr, "%s:%d: error: ", cfg_parser->filename, + cfg_parser->line); + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); +} + +/** print error with file and line number */ +void ub_c_error_msg(const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + ub_c_error_va_list(fmt, args); + va_end(args); +} + +void ub_c_error(const char *str) +{ + cfg_parser->errors++; + fprintf(stderr, "%s:%d: error: %s\n", cfg_parser->filename, + cfg_parser->line, str); +} + +int ub_c_wrap(void) +{ + return 1; +} + +int cfg_strlist_append(struct config_strlist_head* list, char* item) +{ + struct config_strlist *s; + if(!item || !list) + return 0; + s = (struct config_strlist*)calloc(1, sizeof(struct config_strlist)); + if(!s) + return 0; + s->str = item; + s->next = NULL; + if(list->last) + list->last->next = s; + else + list->first = s; + list->last = s; + return 1; +} + +int +cfg_strlist_insert(struct config_strlist** head, char* item) +{ + struct config_strlist *s; + if(!item || !head) + return 0; + s = (struct config_strlist*)calloc(1, sizeof(struct config_strlist)); + if(!s) + return 0; + s->str = item; + s->next = *head; + *head = s; + return 1; +} + +int +cfg_str2list_insert(struct config_str2list** head, char* item, char* i2) +{ + struct config_str2list *s; + if(!item || !i2 || !head) + return 0; + s = (struct config_str2list*)calloc(1, sizeof(struct config_str2list)); + if(!s) + return 0; + s->str = item; + s->str2 = i2; + s->next = *head; + *head = s; + return 1; +} + +uint32_t +cfg_convert_timeval(const char* str) +{ + uint32_t t; + struct tm tm; + memset(&tm, 0, sizeof(tm)); + if(strlen(str) < 14) + return 0; + if(sscanf(str, "%4d%2d%2d%2d%2d%2d", &tm.tm_year, &tm.tm_mon, + &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) + return 0; + tm.tm_year -= 1900; + tm.tm_mon--; + /* Check values */ + if (tm.tm_year < 70) return 0; + if (tm.tm_mon < 0 || tm.tm_mon > 11) return 0; + if (tm.tm_mday < 1 || tm.tm_mday > 31) return 0; + if (tm.tm_hour < 0 || tm.tm_hour > 23) return 0; + if (tm.tm_min < 0 || tm.tm_min > 59) return 0; + if (tm.tm_sec < 0 || tm.tm_sec > 59) return 0; + /* call ldns conversion function */ + t = mktime_from_utc(&tm); + return t; +} + +int +cfg_count_numbers(const char* s) +{ + /* format ::= (sp num)+ sp */ + /* num ::= [-](0-9)+ */ + /* sp ::= (space|tab)* */ + int num = 0; + while(*s) { + while(*s && isspace((int)*s)) + s++; + if(!*s) /* end of string */ + break; + if(*s == '-') + s++; + if(!*s) /* only - not allowed */ + return 0; + if(!isdigit((int)*s)) /* bad character */ + return 0; + while(*s && isdigit((int)*s)) + s++; + num++; + } + return num; +} + +/** all digit number */ +static int isalldigit(const char* str, size_t l) +{ + size_t i; + for(i=0; i0 && str[len-1]==' ') + len--; + if(len > 1 && str[len-1] == 'b') + len--; + else if(len > 1 && str[len-1] == 'B') + len--; + + if(len > 1 && tolower(str[len-1]) == 'g') + mult = 1024*1024*1024; + else if(len > 1 && tolower(str[len-1]) == 'm') + mult = 1024*1024; + else if(len > 1 && tolower(str[len-1]) == 'k') + mult = 1024; + else if(len > 0 && isdigit(str[len-1])) + mult = 1; + else { + log_err("unknown size specifier: '%s'", str); + return 0; + } + while(len>1 && str[len-2]==' ') + len--; + + if(!isalldigit(str, len-1)) { + log_err("unknown size specifier: '%s'", str); + return 0; + } + *res = ((size_t)atol(str)) * mult; + return 1; +} + +void +config_apply(struct config_file* config) +{ + MAX_TTL = (uint32_t)config->max_ttl; + MIN_TTL = (uint32_t)config->min_ttl; + EDNS_ADVERTISED_SIZE = (uint16_t)config->edns_buffer_size; + MINIMAL_RESPONSES = config->minimal_responses; + RRSET_ROUNDROBIN = config->rrset_roundrobin; + log_set_time_asc(config->log_time_ascii); +} + +/** + * Calculate string length of full pathname in original filesys + * @param fname: the path name to convert. + * Must not be null or empty. + * @param cfg: config struct for chroot and chdir (if set). + * @param use_chdir: if false, only chroot is applied. + * @return length of string. + * remember to allocate one more for 0 at end in mallocs. + */ +static size_t +strlen_after_chroot(const char* fname, struct config_file* cfg, int use_chdir) +{ + size_t len = 0; + int slashit = 0; + if(cfg->chrootdir && cfg->chrootdir[0] && + strncmp(cfg->chrootdir, fname, strlen(cfg->chrootdir)) == 0) { + /* already full pathname, return it */ + return strlen(fname); + } + /* chroot */ + if(cfg->chrootdir && cfg->chrootdir[0]) { + /* start with chrootdir */ + len += strlen(cfg->chrootdir); + slashit = 1; + } + /* chdir */ +#ifdef UB_ON_WINDOWS + if(fname[0] != 0 && fname[1] == ':') { + /* full path, no chdir */ + } else +#endif + if(fname[0] == '/' || !use_chdir) { + /* full path, no chdir */ + } else if(cfg->directory && cfg->directory[0]) { + /* prepend chdir */ + if(slashit && cfg->directory[0] != '/') + len++; + if(cfg->chrootdir && cfg->chrootdir[0] && + strncmp(cfg->chrootdir, cfg->directory, + strlen(cfg->chrootdir)) == 0) + len += strlen(cfg->directory)-strlen(cfg->chrootdir); + else len += strlen(cfg->directory); + slashit = 1; + } + /* fname */ + if(slashit && fname[0] != '/') + len++; + len += strlen(fname); + return len; +} + +char* +fname_after_chroot(const char* fname, struct config_file* cfg, int use_chdir) +{ + size_t len = strlen_after_chroot(fname, cfg, use_chdir); + int slashit = 0; + char* buf = (char*)malloc(len+1); + if(!buf) + return NULL; + buf[0] = 0; + /* is fname already in chroot ? */ + if(cfg->chrootdir && cfg->chrootdir[0] && + strncmp(cfg->chrootdir, fname, strlen(cfg->chrootdir)) == 0) { + /* already full pathname, return it */ + strncpy(buf, fname, len); + buf[len] = 0; + return buf; + } + /* chroot */ + if(cfg->chrootdir && cfg->chrootdir[0]) { + /* start with chrootdir */ + strncpy(buf, cfg->chrootdir, len); + slashit = 1; + } +#ifdef UB_ON_WINDOWS + if(fname[0] != 0 && fname[1] == ':') { + /* full path, no chdir */ + } else +#endif + /* chdir */ + if(fname[0] == '/' || !use_chdir) { + /* full path, no chdir */ + } else if(cfg->directory && cfg->directory[0]) { + /* prepend chdir */ + if(slashit && cfg->directory[0] != '/') + strncat(buf, "/", len-strlen(buf)); + /* is the directory already in the chroot? */ + if(cfg->chrootdir && cfg->chrootdir[0] && + strncmp(cfg->chrootdir, cfg->directory, + strlen(cfg->chrootdir)) == 0) + strncat(buf, cfg->directory+strlen(cfg->chrootdir), + len-strlen(buf)); + else strncat(buf, cfg->directory, len-strlen(buf)); + slashit = 1; + } + /* fname */ + if(slashit && fname[0] != '/') + strncat(buf, "/", len-strlen(buf)); + strncat(buf, fname, len-strlen(buf)); + buf[len] = 0; + return buf; +} + +/** return next space character in string */ +static char* next_space_pos(const char* str) +{ + char* sp = strchr(str, ' '); + char* tab = strchr(str, '\t'); + if(!tab && !sp) + return NULL; + if(!sp) return tab; + if(!tab) return sp; + return (sptab)?sp:tab; +} + +int +cfg_parse_local_zone(struct config_file* cfg, const char* val) +{ + const char *type, *name_end, *name; + char buf[256]; + + /* parse it as: [zone_name] [between stuff] [zone_type] */ + name = val; + while(*name && isspace(*name)) + name++; + if(!*name) { + log_err("syntax error: too short: %s", val); + return 0; + } + name_end = next_space_pos(name); + if(!name_end || !*name_end) { + log_err("syntax error: expected zone type: %s", val); + return 0; + } + if (name_end - name > 255) { + log_err("syntax error: bad zone name: %s", val); + return 0; + } + strncpy(buf, name, (size_t)(name_end-name)); + buf[name_end-name] = '\0'; + + type = last_space_pos(name_end); + while(type && *type && isspace(*type)) + type++; + if(!type || !*type) { + log_err("syntax error: expected zone type: %s", val); + return 0; + } + + if(strcmp(type, "nodefault")==0) { + return cfg_strlist_insert(&cfg->local_zones_nodefault, + strdup(name)); + } else { + return cfg_str2list_insert(&cfg->local_zones, strdup(buf), + strdup(type)); + } +} + +char* cfg_ptr_reverse(char* str) +{ + char* ip, *ip_end; + char* name; + char* result; + char buf[1024]; + struct sockaddr_storage addr; + socklen_t addrlen; + + /* parse it as: [IP] [between stuff] [name] */ + ip = str; + while(*ip && isspace(*ip)) + ip++; + if(!*ip) { + log_err("syntax error: too short: %s", str); + return NULL; + } + ip_end = next_space_pos(ip); + if(!ip_end || !*ip_end) { + log_err("syntax error: expected name: %s", str); + return NULL; + } + + name = last_space_pos(ip_end); + if(!name || !*name) { + log_err("syntax error: expected name: %s", str); + return NULL; + } + + sscanf(ip, "%100s", buf); + buf[sizeof(buf)-1]=0; + + if(!ipstrtoaddr(buf, UNBOUND_DNS_PORT, &addr, &addrlen)) { + log_err("syntax error: cannot parse address: %s", str); + return NULL; + } + + /* reverse IPv4: + * ddd.ddd.ddd.ddd.in-addr-arpa. + * IPv6: (h.){32}.ip6.arpa. */ + + if(addr_is_ip6(&addr, addrlen)) { + uint8_t ad[16]; + const char* hex = "0123456789abcdef"; + char *p = buf; + int i; + memmove(ad, &((struct sockaddr_in6*)&addr)->sin6_addr, + sizeof(ad)); + for(i=15; i>=0; i--) { + uint8_t b = ad[i]; + *p++ = hex[ (b&0x0f) ]; + *p++ = '.'; + *p++ = hex[ (b&0xf0) >> 4 ]; + *p++ = '.'; + } + snprintf(buf+16*4, sizeof(buf)-16*4, "ip6.arpa. "); + } else { + uint8_t ad[4]; + memmove(ad, &((struct sockaddr_in*)&addr)->sin_addr, + sizeof(ad)); + snprintf(buf, sizeof(buf), "%u.%u.%u.%u.in-addr.arpa. ", + (unsigned)ad[3], (unsigned)ad[2], + (unsigned)ad[1], (unsigned)ad[0]); + } + + /* printed the reverse address, now the between goop and name on end */ + while(*ip_end && isspace(*ip_end)) + ip_end++; + if(name>ip_end) { + snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "%.*s", + (int)(name-ip_end), ip_end); + } + snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), " PTR %s", name); + + result = strdup(buf); + if(!result) { + log_err("out of memory parsing %s", str); + return NULL; + } + return result; +} + +#ifdef UB_ON_WINDOWS +char* +w_lookup_reg_str(const char* key, const char* name) +{ + HKEY hk = NULL; + DWORD type = 0; + BYTE buf[1024]; + DWORD len = (DWORD)sizeof(buf); + LONG ret; + char* result = NULL; + ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, key, 0, KEY_READ, &hk); + if(ret == ERROR_FILE_NOT_FOUND) + return NULL; /* key does not exist */ + else if(ret != ERROR_SUCCESS) { + log_err("RegOpenKeyEx failed"); + return NULL; + } + ret = RegQueryValueEx(hk, (LPCTSTR)name, 0, &type, buf, &len); + if(RegCloseKey(hk)) + log_err("RegCloseKey"); + if(ret == ERROR_FILE_NOT_FOUND) + return NULL; /* name does not exist */ + else if(ret != ERROR_SUCCESS) { + log_err("RegQueryValueEx failed"); + return NULL; + } + if(type == REG_SZ || type == REG_MULTI_SZ || type == REG_EXPAND_SZ) { + buf[sizeof(buf)-1] = 0; + buf[sizeof(buf)-2] = 0; /* for multi_sz */ + result = strdup((char*)buf); + if(!result) log_err("out of memory"); + } + return result; +} +#endif /* UB_ON_WINDOWS */ + +void errinf(struct module_qstate* qstate, const char* str) +{ + struct config_strlist* p; + if(qstate->env->cfg->val_log_level < 2 || !str) + return; + p = (struct config_strlist*)regional_alloc(qstate->region, sizeof(*p)); + if(!p) { + log_err("malloc failure in validator-error-info string"); + return; + } + p->next = NULL; + p->str = regional_strdup(qstate->region, str); + if(!p->str) { + log_err("malloc failure in validator-error-info string"); + return; + } + /* add at end */ + if(qstate->errinf) { + struct config_strlist* q = qstate->errinf; + while(q->next) + q = q->next; + q->next = p; + } else qstate->errinf = p; +} + +void errinf_origin(struct module_qstate* qstate, struct sock_list *origin) +{ + struct sock_list* p; + if(qstate->env->cfg->val_log_level < 2) + return; + for(p=origin; p; p=p->next) { + char buf[256]; + if(p == origin) + snprintf(buf, sizeof(buf), "from "); + else snprintf(buf, sizeof(buf), "and "); + if(p->len == 0) + snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), + "cache"); + else + addr_to_str(&p->addr, p->len, buf+strlen(buf), + sizeof(buf)-strlen(buf)); + errinf(qstate, buf); + } +} + +char* errinf_to_str(struct module_qstate* qstate) +{ + char buf[20480]; + char* p = buf; + size_t left = sizeof(buf); + struct config_strlist* s; + char dname[LDNS_MAX_DOMAINLEN+1]; + char* t = ldns_rr_type2str(qstate->qinfo.qtype); + char* c = ldns_rr_class2str(qstate->qinfo.qclass); + if(!t || !c) { + free(t); + free(c); + log_err("malloc failure in errinf_to_str"); + return NULL; + } + dname_str(qstate->qinfo.qname, dname); + snprintf(p, left, "validation failure <%s %s %s>:", dname, t, c); + free(t); + free(c); + left -= strlen(p); p += strlen(p); + if(!qstate->errinf) + snprintf(p, left, " misc failure"); + else for(s=qstate->errinf; s; s=s->next) { + snprintf(p, left, " %s", s->str); + left -= strlen(p); p += strlen(p); + } + p = strdup(buf); + if(!p) + log_err("malloc failure in errinf_to_str"); + return p; +} + +void errinf_rrset(struct module_qstate* qstate, struct ub_packed_rrset_key *rr) +{ + char buf[1024]; + char dname[LDNS_MAX_DOMAINLEN+1]; + char *t, *c; + if(qstate->env->cfg->val_log_level < 2 || !rr) + return; + t = ldns_rr_type2str(ntohs(rr->rk.type)); + c = ldns_rr_class2str(ntohs(rr->rk.rrset_class)); + if(!t || !c) { + free(t); + free(c); + log_err("malloc failure in errinf_rrset"); + return; + } + dname_str(rr->rk.dname, dname); + snprintf(buf, sizeof(buf), "for <%s %s %s>", dname, t, c); + free(t); + free(c); + errinf(qstate, buf); +} + +void errinf_dname(struct module_qstate* qstate, const char* str, uint8_t* dname) +{ + char b[1024]; + char buf[LDNS_MAX_DOMAINLEN+1]; + if(qstate->env->cfg->val_log_level < 2 || !str || !dname) + return; + dname_str(dname, buf); + snprintf(b, sizeof(b), "%s %s", str, buf); + errinf(qstate, b); +} diff --git a/util/config_file.h b/util/config_file.h new file mode 100644 index 00000000000..69595cb50f2 --- /dev/null +++ b/util/config_file.h @@ -0,0 +1,651 @@ +/* + * util/config_file.h - reads and stores the config file for unbound. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions for the config file. + */ + +#ifndef UTIL_CONFIG_FILE_H +#define UTIL_CONFIG_FILE_H +struct config_stub; +struct config_strlist; +struct config_str2list; +struct module_qstate; +struct sock_list; +struct ub_packed_rrset_key; + +/** + * The configuration options. + * Strings are malloced. + */ +struct config_file { + /** verbosity level as specified in the config file */ + int verbosity; + + /** statistics interval (in seconds) */ + int stat_interval; + /** if false, statistics values are reset after printing them */ + int stat_cumulative; + /** if true, the statistics are kept in greater detail */ + int stat_extended; + + /** number of threads to create */ + int num_threads; + + /** port on which queries are answered. */ + int port; + /** do ip4 query support. */ + int do_ip4; + /** do ip6 query support. */ + int do_ip6; + /** do udp query support. */ + int do_udp; + /** do tcp query support. */ + int do_tcp; + /** tcp upstream queries (no UDP upstream queries) */ + int tcp_upstream; + + /** private key file for dnstcp-ssl service (enabled if not NULL) */ + char* ssl_service_key; + /** public key file for dnstcp-ssl service */ + char* ssl_service_pem; + /** port on which to provide ssl service */ + int ssl_port; + /** if outgoing tcp connections use SSL */ + int ssl_upstream; + + /** outgoing port range number of ports (per thread) */ + int outgoing_num_ports; + /** number of outgoing tcp buffers per (per thread) */ + size_t outgoing_num_tcp; + /** number of incoming tcp buffers per (per thread) */ + size_t incoming_num_tcp; + /** allowed udp port numbers, array with 0 if not allowed */ + int* outgoing_avail_ports; + + /** EDNS buffer size to use */ + size_t edns_buffer_size; + /** number of bytes buffer size for DNS messages */ + size_t msg_buffer_size; + /** size of the message cache */ + size_t msg_cache_size; + /** slabs in the message cache. */ + size_t msg_cache_slabs; + /** number of queries every thread can service */ + size_t num_queries_per_thread; + /** number of msec to wait before items can be jostled out */ + size_t jostle_time; + /** size of the rrset cache */ + size_t rrset_cache_size; + /** slabs in the rrset cache */ + size_t rrset_cache_slabs; + /** host cache ttl in seconds */ + int host_ttl; + /** number of slabs in the infra host cache */ + size_t infra_cache_slabs; + /** max number of hosts in the infra cache */ + size_t infra_cache_numhosts; + + /** the target fetch policy for the iterator */ + char* target_fetch_policy; + + /** automatic interface for incoming messages. Uses ipv6 remapping, + * and recvmsg/sendmsg ancillary data to detect interfaces, boolean */ + int if_automatic; + /** SO_RCVBUF size to set on port 53 UDP socket */ + size_t so_rcvbuf; + /** SO_SNDBUF size to set on port 53 UDP socket */ + size_t so_sndbuf; + + /** number of interfaces to open. If 0 default all interfaces. */ + int num_ifs; + /** interface description strings (IP addresses) */ + char **ifs; + + /** number of outgoing interfaces to open. + * If 0 default all interfaces. */ + int num_out_ifs; + /** outgoing interface description strings (IP addresses) */ + char **out_ifs; + + /** the root hints */ + struct config_strlist* root_hints; + /** the stub definitions, linked list */ + struct config_stub* stubs; + /** the forward zone definitions, linked list */ + struct config_stub* forwards; + /** list of donotquery addresses, linked list */ + struct config_strlist* donotqueryaddrs; + /** list of access control entries, linked list */ + struct config_str2list* acls; + /** use default localhost donotqueryaddr entries */ + int donotquery_localhost; + + /** harden against very small edns buffer sizes */ + int harden_short_bufsize; + /** harden against very large query sizes */ + int harden_large_queries; + /** harden against spoofed glue (out of zone data) */ + int harden_glue; + /** harden against receiving no DNSSEC data for trust anchor */ + int harden_dnssec_stripped; + /** harden against queries that fall under known nxdomain names */ + int harden_below_nxdomain; + /** harden the referral path, query for NS,A,AAAA and validate */ + int harden_referral_path; + /** use 0x20 bits in query as random ID bits */ + int use_caps_bits_for_id; + /** strip away these private addrs from answers, no DNS Rebinding */ + struct config_strlist* private_address; + /** allow domain (and subdomains) to use private address space */ + struct config_strlist* private_domain; + /** what threshold for unwanted action. */ + size_t unwanted_threshold; + /** the number of seconds maximal TTL used for RRsets and messages */ + int max_ttl; + /** the number of seconds minimum TTL used for RRsets and messages */ + int min_ttl; + /** if prefetching of messages should be performed. */ + int prefetch; + /** if prefetching of DNSKEYs should be performed. */ + int prefetch_key; + + /** chrootdir, if not "" or chroot will be done */ + char* chrootdir; + /** username to change to, if not "". */ + char* username; + /** working directory */ + char* directory; + /** filename to log to. */ + char* logfile; + /** pidfile to write pid to. */ + char* pidfile; + + /** should log messages be sent to syslogd */ + int use_syslog; + /** log timestamp in ascii UTC */ + int log_time_ascii; + /** log queries with one line per query */ + int log_queries; + + /** do not report identity (id.server, hostname.bind) */ + int hide_identity; + /** do not report version (version.server, version.bind) */ + int hide_version; + /** identity, hostname is returned if "". */ + char* identity; + /** version, package version returned if "". */ + char* version; + + /** the module configuration string */ + char* module_conf; + + /** files with trusted DS and DNSKEYs in zonefile format, list */ + struct config_strlist* trust_anchor_file_list; + /** list of trustanchor keys, linked list */ + struct config_strlist* trust_anchor_list; + /** files with 5011 autotrust tracked keys */ + struct config_strlist* auto_trust_anchor_file_list; + /** files with trusted DNSKEYs in named.conf format, list */ + struct config_strlist* trusted_keys_file_list; + /** DLV anchor file */ + char* dlv_anchor_file; + /** DLV anchor inline */ + struct config_strlist* dlv_anchor_list; + /** insecure domain list */ + struct config_strlist* domain_insecure; + + /** if not 0, this value is the validation date for RRSIGs */ + int32_t val_date_override; + /** the minimum for signature clock skew */ + int32_t val_sig_skew_min; + /** the maximum for signature clock skew */ + int32_t val_sig_skew_max; + /** this value sets the number of seconds before revalidating bogus */ + int bogus_ttl; + /** should validator clean additional section for secure msgs */ + int val_clean_additional; + /** log bogus messages by the validator */ + int val_log_level; + /** squelch val_log_level to log - this is library goes to callback */ + int val_log_squelch; + /** should validator allow bogus messages to go through */ + int val_permissive_mode; + /** ignore the CD flag in incoming queries and refuse them bogus data */ + int ignore_cd; + /** nsec3 maximum iterations per key size, string */ + char* val_nsec3_key_iterations; + /** autotrust add holddown time, in seconds */ + unsigned int add_holddown; + /** autotrust del holddown time, in seconds */ + unsigned int del_holddown; + /** autotrust keep_missing time, in seconds. 0 is forever. */ + unsigned int keep_missing; + + /** size of the key cache */ + size_t key_cache_size; + /** slabs in the key cache. */ + size_t key_cache_slabs; + /** size of the neg cache */ + size_t neg_cache_size; + + /** local zones config */ + struct config_str2list* local_zones; + /** local zones nodefault list */ + struct config_strlist* local_zones_nodefault; + /** local data RRs configged */ + struct config_strlist* local_data; + + /** remote control section. enable toggle. */ + int remote_control_enable; + /** the interfaces the remote control should listen on */ + struct config_strlist* control_ifs; + /** port number for the control port */ + int control_port; + /** private key file for server */ + char* server_key_file; + /** certificate file for server */ + char* server_cert_file; + /** private key file for unbound-control */ + char* control_key_file; + /** certificate file for unbound-control */ + char* control_cert_file; + + /** Python script file */ + char* python_script; + + /** daemonize, i.e. fork into the background. */ + int do_daemonize; + + /* minimal response when positive answer */ + int minimal_responses; + + /* RRSet roundrobin */ + int rrset_roundrobin; +}; + +/** + * Stub config options + */ +struct config_stub { + /** next in list */ + struct config_stub* next; + /** domain name (in text) of the stub apex domain */ + char* name; + /** list of stub nameserver hosts (domain name) */ + struct config_strlist* hosts; + /** list of stub nameserver addresses (IP address) */ + struct config_strlist* addrs; + /** if stub-prime is set */ + int isprime; + /** if forward-first is set (failover to without if fails) */ + int isfirst; +}; + +/** + * List of strings for config options + */ +struct config_strlist { + /** next item in list */ + struct config_strlist* next; + /** config option string */ + char* str; +}; + +/** + * List of two strings for config options + */ +struct config_str2list { + /** next item in list */ + struct config_str2list* next; + /** first string */ + char* str; + /** second string */ + char* str2; +}; + +/** List head for strlist processing, used for append operation. */ +struct config_strlist_head { + /** first in list of text items */ + struct config_strlist* first; + /** last in list of text items */ + struct config_strlist* last; +}; + +/** + * Create config file structure. Filled with default values. + * @return: the new structure or NULL on memory error. + */ +struct config_file* config_create(void); + +/** + * Create config file structure for library use. Filled with default values. + * @return: the new structure or NULL on memory error. + */ +struct config_file* config_create_forlib(void); + +/** + * Read the config file from the specified filename. + * @param config: where options are stored into, must be freshly created. + * @param filename: name of configfile. If NULL nothing is done. + * @param chroot: if not NULL, the chroot dir currently in use (for include). + * @return: false on error. In that case errno is set, ENOENT means + * file not found. + */ +int config_read(struct config_file* config, const char* filename, + const char* chroot); + +/** + * Destroy the config file structure. + * @param config: to delete. + */ +void config_delete(struct config_file* config); + +/** + * Apply config to global constants; this routine is called in single thread. + * @param config: to apply. Side effect: global constants change. + */ +void config_apply(struct config_file* config); + +/** + * Set the given keyword to the given value. + * @param config: where to store config + * @param option: option name, including the ':' character. + * @param value: value, this string is copied if needed, or parsed. + * The caller owns the value string. + * @return 0 on error (malloc or syntax error). + */ +int config_set_option(struct config_file* config, const char* option, + const char* value); + +/** + * Call print routine for the given option. + * @param cfg: config. + * @param opt: option name without trailing :. + * This is different from config_set_option. + * @param func: print func, called as (str, arg) for every data element. + * @param arg: user argument for print func. + * @return false if the option name is not supported (syntax error). + */ +int config_get_option(struct config_file* cfg, const char* opt, + void (*func)(char*,void*), void* arg); + +/** + * Get an option and return strlist + * @param cfg: config file + * @param opt: option name. + * @param list: list is returned here. malloced, caller must free it. + * @return 0=OK, 1=syntax error, 2=malloc failed. + */ +int config_get_option_list(struct config_file* cfg, const char* opt, + struct config_strlist** list); + +/** + * Get an option and collate results into string + * @param cfg: config file + * @param opt: option name. + * @param str: string. malloced, caller must free it. + * @return 0=OK, 1=syntax error, 2=malloc failed. + */ +int config_get_option_collate(struct config_file* cfg, const char* opt, + char** str); + +/** + * function to print to a file, use as func with config_get_option. + * @param line: text to print. \n appended. + * @param arg: pass a FILE*, like stdout. + */ +void config_print_func(char* line, void* arg); + +/** + * function to collate the text strings into a strlist_head. + * @param line: text to append. + * @param arg: pass a strlist_head structure. zeroed on start. + */ +void config_collate_func(char* line, void* arg); + +/** + * take a strlist_head list and return a malloc string. separated with newline. + * @param list: strlist first to collate. zeroes return "". + * @return NULL on malloc failure. Or if malloc failure happened in strlist. + */ +char* config_collate_cat(struct config_strlist* list); + +/** + * Append text at end of list. + * @param list: list head. zeroed at start. + * @param item: new item. malloced by caller. if NULL the insertion fails. + * @return true on success. + */ +int cfg_strlist_append(struct config_strlist_head* list, char* item); + +/** + * Insert string into strlist. + * @param head: pointer to strlist head variable. + * @param item: new item. malloced by caller. If NULL the insertion fails. + * @return: true on success. + */ +int cfg_strlist_insert(struct config_strlist** head, char* item); + +/** + * Insert string into str2list. + * @param head: pointer to str2list 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. + * @return: true on success. + */ +int cfg_str2list_insert(struct config_str2list** head, char* item, char* i2); + +/** + * Delete items in config string list. + * @param list: list. + */ +void config_delstrlist(struct config_strlist* list); + +/** + * Delete items in config double string list. + * @param list: list. + */ +void config_deldblstrlist(struct config_str2list* list); + +/** + * Delete items in config stub list. + * @param list: list. + */ +void config_delstubs(struct config_stub* list); + +/** + * Convert 14digit to time value + * @param str: string of 14 digits + * @return time value or 0 for error. + */ +uint32_t cfg_convert_timeval(const char* str); + +/** + * Count number of values in the string. + * format ::= (sp num)+ sp + * num ::= [-](0-9)+ + * sp ::= (space|tab)* + * + * @param str: string + * @return: 0 on parse error, or empty string, else + * number of integer values in the string. + */ +int cfg_count_numbers(const char* str); + +/** + * Convert a 'nice' memory or file size into a bytecount + * From '100k' to 102400. and so on. Understands kKmMgG. + * k=1024, m=1024*1024, g=1024*1024*1024. + * @param str: string + * @param res: result is stored here, size in bytes. + * @return: true if parsed correctly, or 0 on a parse error (and an error + * is logged). + */ +int cfg_parse_memsize(const char* str, size_t* res); + +/** + * 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". + * @return: false on failure + */ +int cfg_parse_local_zone(struct config_file* cfg, const char* val); + +/** + * Mark "number" or "low-high" as available or not in ports array. + * @param str: string in input + * @param allow: give true if this range is permitted. + * @param avail: the array from cfg. + * @param num: size of the array (65536). + * @return: true if parsed correctly, or 0 on a parse error (and an error + * is logged). + */ +int cfg_mark_ports(const char* str, int allow, int* avail, int num); + +/** + * Get a condensed list of ports returned. allocated. + * @param cfg: config file. + * @param avail: the available ports array is returned here. + * @return: number of ports in array or 0 on error. + */ +int cfg_condense_ports(struct config_file* cfg, int** avail); + +/** + * Scan ports available + * @param avail: the array from cfg. + * @param num: size of the array (65536). + * @return the number of ports available for use. + */ +int cfg_scan_ports(int* avail, int num); + +/** + * Convert a filename to full pathname in original filesys + * @param fname: the path name to convert. + * Must not be null or empty. + * @param cfg: config struct for chroot and chdir (if set). + * @param use_chdir: if false, only chroot is applied. + * @return pointer to malloced buffer which is: [chroot][chdir]fname + * or NULL on malloc failure. + */ +char* fname_after_chroot(const char* fname, struct config_file* cfg, + int use_chdir); + +/** + * Convert a ptr shorthand into a full reverse-notation PTR record. + * @param str: input string, "IP name" + * @return: malloced string "reversed-ip-name PTR name" + */ +char* cfg_ptr_reverse(char* str); + +/** + * Append text to the error info for validation. + * @param qstate: query state. + * @param str: copied into query region and appended. + * Failures to allocate are logged. + */ +void errinf(struct module_qstate* qstate, const char* str); + +/** + * Append text to error info: from 1.2.3.4 + * @param qstate: query state. + * @param origin: sock list with origin of trouble. + * Every element added. + * If NULL: nothing is added. + * if 0len element: 'from cache' is added. + */ +void errinf_origin(struct module_qstate* qstate, struct sock_list *origin); + +/** + * Append text to error info: for RRset name type class + * @param qstate: query state. + * @param rr: rrset_key. + */ +void errinf_rrset(struct module_qstate* qstate, struct ub_packed_rrset_key *rr); + +/** + * Append text to error info: str dname + * @param qstate: query state. + * @param str: explanation string + * @param dname: the dname. + */ +void errinf_dname(struct module_qstate* qstate, const char* str, + uint8_t* dname); + +/** + * Create error info in string + * @param qstate: query state. + * @return string or NULL on malloc failure (already logged). + * This string is malloced and has to be freed by caller. + */ +char* errinf_to_str(struct module_qstate* qstate); + +/** + * Used during options parsing + */ +struct config_parser_state { + /** name of file being parser */ + char* filename; + /** line number in the file, starts at 1 */ + int line; + /** number of errors encountered */ + int errors; + /** the result of parsing is stored here. */ + struct config_file* cfg; + /** the current chroot dir (or NULL if none) */ + const char* chroot; +}; + +/** global config parser object used during config parsing */ +extern struct config_parser_state* cfg_parser; +/** parsing helpers: print error with file and line numbers */ +void ub_c_error(const char* msg); +/** parsing helpers: print error with file and line numbers */ +void ub_c_error_msg(const char* fmt, ...) ATTR_FORMAT(printf, 1, 2); + +#ifdef UB_ON_WINDOWS +/** + * Obtain registry string (if it exists). + * @param key: key string + * @param name: name of value to fetch. + * @return malloced string with the result or NULL if it did not + * exist on an error (logged with log_err) was encountered. + */ +char* w_lookup_reg_str(const char* key, const char* name); +#endif /* UB_ON_WINDOWS */ + +#endif /* UTIL_CONFIG_FILE_H */ diff --git a/util/configlexer.c b/util/configlexer.c new file mode 100644 index 00000000000..4e8ed337821 --- /dev/null +++ b/util/configlexer.c @@ -0,0 +1,3912 @@ +#include "config.h" +#include "util/configyyrename.h" + +#line 3 "" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 35 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; +#endif /* ! C99 */ + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) + +#define YY_USE_CONST + +#endif /* defined (__STDC__) */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN (yy_start) = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START (((yy_start) - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart(yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#define YY_BUF_SIZE 16384 +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +extern int yyleng; + +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = (yy_hold_char); \ + YY_RESTORE_YY_MORE_OFFSET \ + (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, (yytext_ptr) ) + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ + ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; +static int yy_n_chars; /* number of characters read into yy_ch_buf */ +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 0; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart (FILE *input_file ); +void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ); +void yy_delete_buffer (YY_BUFFER_STATE b ); +void yy_flush_buffer (YY_BUFFER_STATE b ); +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ); +void yypop_buffer_state (void ); + +static void yyensure_buffer_stack (void ); +static void yy_load_buffer_state (void ); +static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ); + +#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ) + +YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ); +YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ); +YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ); + +void *yyalloc (yy_size_t ); +void *yyrealloc (void *,yy_size_t ); +void yyfree (void * ); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +typedef unsigned char YY_CHAR; + +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; + +typedef int yy_state_type; + +extern int yylineno; + +int yylineno = 1; + +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state (void ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); +static int yy_get_next_buffer (void ); +static void yy_fatal_error (yyconst char msg[] ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + (yytext_ptr) = yy_bp; \ + (yytext_ptr) -= (yy_more_len); \ + yyleng = (size_t) (yy_cp - (yytext_ptr)); \ + (yy_hold_char) = *yy_cp; \ + *yy_cp = '\0'; \ + (yy_c_buf_p) = yy_cp; + +#define YY_NUM_RULES 142 +#define YY_END_OF_BUFFER 143 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[1343] = + { 0, + 1, 1, 124, 124, 128, 128, 132, 132, 136, 136, + 1, 1, 143, 140, 1, 122, 122, 141, 2, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 141, 124, + 125, 125, 126, 141, 128, 129, 129, 130, 141, 135, + 132, 133, 133, 134, 141, 136, 137, 137, 138, 141, + 139, 123, 2, 127, 139, 141, 140, 0, 1, 2, + 2, 2, 2, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 124, + 0, 128, 0, 135, 0, 132, 136, 0, 139, 0, + 2, 2, 139, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 139, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 139, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 62, 140, 140, + 140, 140, 140, 6, 140, 140, 140, 140, 140, 140, + + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 139, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + + 140, 140, 140, 140, 139, 140, 140, 140, 140, 27, + 140, 140, 140, 140, 140, 12, 13, 140, 15, 14, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 118, 140, 140, 140, 140, + 140, 3, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 139, 140, 140, 140, 140, 140, 140, 140, 140, 140, + + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 131, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 30, + 140, 140, 140, 140, 140, 140, 140, 140, 31, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 77, 131, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + + 140, 140, 140, 140, 140, 140, 140, 76, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 60, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 20, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 28, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 29, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + + 140, 140, 140, 22, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 25, 26, 140, 140, 140, 63, 140, 64, + 140, 61, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 5, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 79, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 104, 103, 140, + + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 32, 140, 140, + 140, 140, 140, 140, 140, 66, 65, 140, 140, 140, + 140, 140, 140, 100, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 51, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 102, 140, 140, 140, 140, 140, 140, 140, 140, + 4, 140, 140, 140, 140, 140, 140, 140, 140, 140, + + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 97, 140, 140, 140, 140, 140, 140, 140, + 112, 98, 140, 21, 140, 140, 140, 140, 68, 140, + 69, 67, 140, 140, 140, 140, 140, 140, 75, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 99, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 59, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 17, 140, 140, 140, 16, + 140, 84, 140, 140, 140, 140, 140, 140, 140, 140, + + 140, 140, 140, 140, 39, 40, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 70, 140, 140, 140, + 140, 140, 74, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 78, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 117, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 88, 140, 92, 140, 140, + 140, 140, 73, 140, 140, 110, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 91, + 140, 140, 140, 140, 41, 42, 140, 47, 93, 140, + + 105, 101, 140, 140, 35, 140, 95, 140, 140, 140, + 140, 140, 7, 140, 58, 109, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 80, 140, 140, 119, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 94, 140, 34, 36, + 140, 140, 140, 140, 140, 57, 140, 140, 140, 140, + 113, 18, 19, 140, 140, 140, 140, 140, 140, 55, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 115, + 140, 140, 33, 140, 140, 140, 140, 140, 140, 11, + + 140, 140, 140, 140, 140, 140, 140, 10, 140, 140, + 37, 140, 121, 114, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 140, 87, 86, 140, 116, 111, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 43, + 140, 120, 140, 140, 140, 140, 38, 140, 140, 140, + 81, 83, 140, 140, 140, 85, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 23, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 108, 140, 140, 140, 140, 140, 140, + 140, 24, 140, 9, 140, 140, 106, 48, 140, 140, + + 140, 90, 140, 71, 140, 140, 140, 50, 54, 49, + 140, 44, 140, 8, 140, 140, 89, 140, 140, 140, + 53, 140, 45, 140, 107, 140, 140, 82, 72, 52, + 46, 140, 140, 140, 140, 56, 140, 140, 140, 140, + 96, 0 + } ; + +static yyconst flex_int32_t yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 5, 6, 1, 1, 1, 7, 1, + 1, 1, 1, 1, 8, 1, 1, 1, 1, 1, + 9, 10, 1, 11, 1, 1, 1, 12, 1, 1, + 1, 1, 1, 1, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 1, 39, 1, 1, 1, 1, 40, 41, 42, 43, + + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst flex_int32_t yy_meta[66] = + { 0, + 1, 2, 3, 4, 5, 1, 6, 1, 1, 1, + 1, 7, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst flex_int16_t yy_base[1357] = + { 0, + 0, 0, 63, 66, 69, 71, 77, 83, 88, 91, + 129, 135, 483, 443, 95, 3880, 3880, 3880, 107, 110, + 142, 140, 108, 50, 159, 147, 121, 148, 158, 174, + 191, 176, 190, 216, 225, 235, 214, 246, 116, 436, + 3880, 3880, 3880, 94, 402, 3880, 3880, 3880, 96, 335, + 329, 3880, 3880, 3880, 214, 282, 3880, 3880, 3880, 102, + 250, 3880, 289, 3880, 184, 293, 239, 297, 111, 0, + 301, 0, 0, 219, 223, 248, 273, 280, 285, 290, + 286, 283, 310, 294, 291, 297, 309, 316, 232, 319, + 338, 303, 334, 345, 326, 347, 349, 342, 350, 360, + + 343, 376, 370, 384, 371, 368, 187, 375, 374, 137, + 387, 403, 378, 390, 401, 386, 405, 400, 407, 229, + 154, 186, 199, 163, 448, 176, 115, 277, 90, 452, + 463, 0, 432, 441, 318, 433, 442, 439, 437, 465, + 462, 469, 493, 471, 455, 473, 453, 479, 490, 477, + 494, 496, 498, 510, 492, 517, 530, 526, 549, 522, + 525, 532, 542, 534, 536, 541, 544, 545, 556, 529, + 558, 552, 560, 559, 568, 578, 574, 561, 582, 591, + 603, 583, 599, 610, 607, 612, 608, 594, 611, 616, + 617, 618, 624, 640, 629, 635, 649, 637, 639, 658, + + 664, 643, 669, 657, 672, 677, 676, 663, 660, 665, + 680, 688, 679, 690, 698, 705, 699, 701, 703, 706, + 710, 738, 674, 720, 734, 716, 733, 736, 739, 752, + 747, 737, 756, 750, 767, 773, 761, 766, 777, 763, + 790, 771, 781, 791, 804, 797, 849, 800, 812, 789, + 814, 820, 809, 830, 826, 828, 839, 847, 831, 866, + 884, 857, 853, 859, 873, 883, 893, 881, 889, 896, + 892, 902, 909, 906, 910, 911, 916, 912, 926, 935, + 920, 937, 938, 948, 951, 934, 957, 3880, 959, 942, + 962, 965, 954, 3880, 952, 968, 953, 986, 990, 975, + + 978, 981, 1000, 992, 1001, 993, 995, 1041, 1012, 994, + 1033, 1023, 1025, 1019, 1034, 1036, 1046, 1039, 1029, 1050, + 1059, 1070, 1061, 1068, 1078, 1028, 1075, 1071, 1077, 1092, + 1081, 1084, 1085, 1098, 1102, 1103, 1113, 1122, 1121, 1124, + 1126, 1110, 1127, 1129, 1130, 1134, 1136, 1119, 1140, 1142, + 1148, 1168, 1151, 1154, 1146, 1161, 1166, 1167, 1173, 1178, + 1175, 1181, 1179, 1193, 1198, 1199, 1191, 1197, 1210, 1213, + 1212, 1233, 1194, 1218, 1229, 1234, 1239, 1244, 1230, 1231, + 1236, 1242, 1260, 1243, 1238, 1254, 1263, 1271, 1258, 1282, + 1280, 1281, 1276, 1269, 1287, 1290, 1289, 1295, 1296, 1307, + + 1308, 1311, 1316, 1279, 1327, 1328, 1329, 1309, 1339, 3880, + 1341, 1338, 1343, 1336, 1335, 3880, 3880, 1347, 3880, 3880, + 1363, 1367, 1374, 1353, 1404, 1371, 1365, 1357, 1390, 1385, + 1380, 1401, 1398, 1414, 1394, 1399, 1417, 1410, 1426, 1424, + 1429, 1425, 1432, 1438, 1445, 1449, 1450, 1452, 1443, 1457, + 1464, 1467, 1465, 1468, 1459, 3880, 1466, 1476, 1479, 1482, + 1499, 3880, 1487, 1491, 1484, 1493, 1496, 1492, 1509, 1503, + 1506, 1518, 1520, 1526, 1524, 1535, 1472, 1537, 1519, 1543, + 1545, 1536, 1559, 1562, 1553, 1548, 1554, 1573, 1558, 1574, + 1579, 1575, 1584, 1572, 1568, 1582, 1621, 1594, 1583, 1589, + + 1593, 1601, 1600, 1606, 1617, 1639, 1631, 1615, 1634, 1642, + 1649, 1644, 1641, 1656, 1650, 1658, 3880, 1664, 1677, 1659, + 1671, 1682, 1679, 1674, 1685, 1676, 1681, 1691, 1698, 3880, + 1692, 1701, 1694, 1708, 1719, 1720, 1730, 1734, 3880, 1736, + 1737, 1739, 1718, 1728, 1746, 1723, 1747, 1754, 1756, 1761, + 1753, 1763, 1760, 1774, 1764, 1765, 1773, 1783, 1780, 1790, + 1779, 1799, 1787, 1743, 1807, 1800, 1808, 1794, 1804, 1816, + 337, 1812, 1810, 1814, 1811, 3880, 76, 1834, 1817, 1827, + 1853, 1854, 1846, 1838, 1842, 1857, 1843, 1849, 1866, 1850, + 1863, 1877, 1867, 1883, 1873, 1893, 1878, 1881, 1891, 1889, + + 1884, 1900, 1880, 1911, 1907, 1909, 1923, 3880, 1875, 1912, + 1927, 1920, 1936, 1946, 1918, 1928, 1916, 1950, 1947, 1955, + 1956, 1961, 1958, 1953, 1965, 1969, 1970, 1977, 1991, 1979, + 3880, 1985, 1986, 1976, 1996, 1992, 1987, 2006, 1997, 2004, + 2025, 2026, 3880, 2027, 2034, 2016, 2040, 2021, 2044, 2045, + 2046, 2031, 2054, 2047, 2058, 2042, 2043, 2057, 3880, 2069, + 2079, 2075, 2083, 2084, 2070, 2077, 2092, 2074, 2072, 2087, + 2078, 2097, 2082, 2102, 2106, 2107, 2110, 2085, 3880, 2140, + 2112, 2123, 2137, 2125, 2127, 2144, 2131, 2153, 2104, 2136, + 2154, 2152, 2155, 2156, 2159, 2176, 2175, 2160, 2170, 2187, + + 2198, 2199, 2195, 3880, 2200, 2193, 2182, 2210, 2208, 2194, + 2197, 2211, 2209, 2202, 2212, 2214, 2225, 2226, 2232, 2227, + 2234, 2250, 2242, 2252, 2253, 2254, 2235, 2264, 2260, 2280, + 2268, 2271, 3880, 3880, 2281, 2269, 2272, 3880, 2285, 3880, + 2289, 3880, 2291, 2299, 2287, 2276, 2304, 2290, 2306, 2303, + 2318, 2298, 2311, 2330, 2316, 2332, 3880, 2321, 2326, 2341, + 2324, 2336, 2338, 2350, 2349, 2314, 2353, 2360, 2364, 3880, + 2367, 2357, 2375, 2328, 2385, 2371, 2369, 2383, 2387, 2381, + 2390, 2393, 2401, 2400, 2405, 2409, 2397, 2414, 2394, 2427, + 2415, 2417, 2419, 2424, 2436, 2438, 2432, 3880, 3880, 2449, + + 2452, 2441, 2451, 2442, 2471, 2463, 2462, 2473, 2465, 2468, + 2475, 2477, 2469, 2479, 2500, 2487, 2495, 3880, 2490, 2498, + 2509, 2505, 2519, 2510, 2526, 3880, 3880, 2525, 2518, 2521, + 2515, 2528, 2536, 3880, 2537, 2543, 2546, 2560, 2562, 2532, + 2549, 2564, 2569, 2561, 2568, 2570, 2581, 2571, 2585, 2584, + 2586, 2593, 2591, 2601, 2589, 2594, 2595, 2599, 2604, 2605, + 2623, 2624, 2609, 2626, 3880, 2637, 2616, 2639, 2613, 2644, + 2646, 2641, 2643, 2640, 2649, 2652, 2627, 2658, 2651, 2679, + 2661, 3880, 2674, 2671, 2684, 2685, 2666, 2689, 2676, 2693, + 3880, 2695, 2699, 2703, 2698, 2697, 2710, 2719, 2711, 2718, + + 2716, 2724, 2734, 2732, 2736, 2744, 2727, 2742, 2738, 2749, + 2757, 2768, 2758, 2776, 2761, 2774, 2765, 2755, 2785, 2764, + 2791, 2781, 3880, 2787, 2789, 2794, 2792, 2797, 2800, 2801, + 3880, 3880, 2784, 3880, 2814, 2804, 2821, 2823, 3880, 2809, + 3880, 3880, 2820, 2839, 2827, 2837, 2841, 2840, 3880, 2845, + 2831, 2854, 2835, 2848, 2857, 2861, 2859, 2865, 3880, 2871, + 2875, 2862, 2881, 2879, 2891, 2868, 2892, 2903, 2904, 2906, + 2895, 2896, 2914, 2910, 3880, 2907, 2921, 2925, 2917, 2937, + 2943, 2930, 2938, 2942, 2953, 3880, 2941, 2940, 2955, 3880, + 2957, 3880, 2969, 2934, 2970, 2928, 2974, 2951, 2972, 2984, + + 2987, 2976, 2993, 2986, 3880, 3880, 2995, 3000, 3006, 2996, + 3012, 3001, 3009, 3020, 3003, 3018, 3880, 3014, 3021, 3022, + 3030, 3032, 3880, 3046, 3047, 3041, 3045, 3059, 3055, 3061, + 3049, 3063, 3066, 3052, 3075, 3078, 3064, 3880, 3079, 3092, + 3076, 3094, 3081, 3090, 3097, 3112, 3104, 3088, 3109, 3880, + 3114, 3103, 3115, 3111, 3106, 3127, 3110, 3131, 3125, 3143, + 3134, 3141, 3142, 2999, 3153, 3880, 3140, 3880, 3154, 3164, + 3168, 3173, 3880, 3170, 3167, 3880, 3169, 3161, 3183, 3194, + 3186, 3202, 3199, 3187, 3201, 3188, 3206, 3190, 3197, 3880, + 3220, 3213, 3214, 3217, 3880, 3880, 3226, 3880, 3880, 3223, + + 3880, 3880, 3232, 3239, 3880, 3242, 3880, 3224, 3247, 3240, + 3230, 3238, 3880, 3255, 3880, 3880, 3253, 3259, 3246, 3257, + 3268, 3271, 3272, 3264, 3263, 3265, 3266, 3282, 3280, 3296, + 3288, 3275, 3286, 3298, 3290, 3302, 3292, 3307, 3313, 3320, + 3880, 3304, 3325, 3880, 3330, 3323, 3321, 3317, 3324, 3338, + 3337, 3346, 3359, 3343, 3341, 3347, 3880, 3352, 3880, 3880, + 3355, 3363, 3361, 3357, 3362, 3880, 3376, 3373, 3377, 3378, + 3880, 3880, 3880, 3390, 3374, 3386, 3401, 3403, 3389, 3880, + 3394, 3405, 3407, 3399, 3411, 3415, 3424, 3425, 3427, 3880, + 3426, 3417, 3880, 3437, 3430, 3436, 3438, 3448, 3441, 3880, + + 3442, 3452, 3446, 3451, 3455, 3454, 3475, 3880, 3457, 3470, + 3880, 3459, 3880, 3880, 3465, 3489, 3488, 3494, 3495, 3478, + 3486, 3503, 3501, 3502, 3880, 3880, 3498, 3880, 3880, 3492, + 3512, 3505, 3507, 3510, 3509, 3522, 3517, 3531, 3525, 3880, + 3547, 3880, 3528, 3548, 3552, 3551, 3880, 3553, 3549, 3532, + 3880, 3880, 3558, 3564, 3559, 3880, 3566, 3572, 3575, 3582, + 3596, 3591, 3585, 3584, 3598, 3599, 3587, 3588, 3605, 3611, + 3880, 3610, 3602, 3614, 3617, 3619, 3620, 3623, 3625, 3642, + 3641, 3648, 3632, 3880, 3640, 3650, 3656, 3657, 3658, 3659, + 3660, 3880, 3669, 3880, 3661, 3666, 3880, 3880, 3665, 3674, + + 3684, 3880, 3685, 3880, 3675, 3676, 3700, 3880, 3880, 3880, + 3679, 3880, 3701, 3880, 3694, 3692, 3880, 3681, 3709, 3710, + 3880, 3713, 3880, 3714, 3880, 3703, 3717, 3880, 3880, 3880, + 3880, 3716, 3719, 3723, 3724, 3880, 3734, 3711, 3729, 3735, + 3880, 3880, 3788, 3795, 3802, 3809, 3816, 82, 3823, 3830, + 3837, 3844, 3851, 3858, 3865, 3872 + } ; + +static yyconst flex_int16_t yy_def[1357] = + { 0, + 1342, 1, 1343, 1343, 1344, 1344, 1345, 1345, 1346, 1346, + 1347, 1347, 1342, 1348, 1342, 1342, 1342, 1342, 1349, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1350, + 1342, 1342, 1342, 1350, 1351, 1342, 1342, 1342, 1351, 1352, + 1342, 1342, 1342, 1342, 1352, 1353, 1342, 1342, 1342, 1353, + 1354, 1342, 1355, 1342, 1354, 1354, 1348, 1348, 1342, 1356, + 1349, 1356, 1349, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1350, + 1350, 1351, 1351, 1352, 1352, 1342, 1353, 1353, 1354, 1354, + 1355, 1355, 1354, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1354, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1354, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1342, 1348, 1348, + 1348, 1348, 1348, 1342, 1348, 1348, 1348, 1348, 1348, 1348, + + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1354, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + + 1348, 1348, 1348, 1348, 1354, 1348, 1348, 1348, 1348, 1342, + 1348, 1348, 1348, 1348, 1348, 1342, 1342, 1348, 1342, 1342, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1342, 1348, 1348, 1348, 1348, + 1348, 1342, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1354, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1342, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1342, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1342, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1342, 1354, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1342, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1342, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1342, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1342, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1342, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + + 1348, 1348, 1348, 1342, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1342, 1342, 1348, 1348, 1348, 1342, 1348, 1342, + 1348, 1342, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1342, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1342, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1342, 1342, 1348, + + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1342, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1342, 1342, 1348, 1348, 1348, + 1348, 1348, 1348, 1342, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1342, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1342, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1342, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1342, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1342, 1342, 1348, 1342, 1348, 1348, 1348, 1348, 1342, 1348, + 1342, 1342, 1348, 1348, 1348, 1348, 1348, 1348, 1342, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1342, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1342, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1342, 1348, 1348, 1348, 1342, + 1348, 1342, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + + 1348, 1348, 1348, 1348, 1342, 1342, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1342, 1348, 1348, 1348, + 1348, 1348, 1342, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1342, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1342, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1342, 1348, 1342, 1348, 1348, + 1348, 1348, 1342, 1348, 1348, 1342, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1342, + 1348, 1348, 1348, 1348, 1342, 1342, 1348, 1342, 1342, 1348, + + 1342, 1342, 1348, 1348, 1342, 1348, 1342, 1348, 1348, 1348, + 1348, 1348, 1342, 1348, 1342, 1342, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1342, 1348, 1348, 1342, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1342, 1348, 1342, 1342, + 1348, 1348, 1348, 1348, 1348, 1342, 1348, 1348, 1348, 1348, + 1342, 1342, 1342, 1348, 1348, 1348, 1348, 1348, 1348, 1342, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1342, + 1348, 1348, 1342, 1348, 1348, 1348, 1348, 1348, 1348, 1342, + + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1342, 1348, 1348, + 1342, 1348, 1342, 1342, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1342, 1342, 1348, 1342, 1342, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1342, + 1348, 1342, 1348, 1348, 1348, 1348, 1342, 1348, 1348, 1348, + 1342, 1342, 1348, 1348, 1348, 1342, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1342, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1342, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1342, 1348, 1342, 1348, 1348, 1342, 1342, 1348, 1348, + + 1348, 1342, 1348, 1342, 1348, 1348, 1348, 1342, 1342, 1342, + 1348, 1342, 1348, 1342, 1348, 1348, 1342, 1348, 1348, 1348, + 1342, 1348, 1342, 1348, 1342, 1348, 1348, 1342, 1342, 1342, + 1342, 1348, 1348, 1348, 1348, 1342, 1348, 1348, 1348, 1348, + 1342, 0, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, + 1342, 1342, 1342, 1342, 1342, 1342 + } ; + +static yyconst flex_int16_t yy_nxt[3946] = + { 0, + 14, 15, 16, 17, 18, 19, 18, 14, 14, 14, + 14, 18, 20, 14, 21, 22, 23, 24, 14, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 14, 34, + 35, 36, 37, 38, 14, 14, 14, 14, 39, 20, + 14, 21, 22, 23, 24, 14, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 14, 34, 35, 36, 37, + 38, 14, 14, 14, 14, 41, 42, 43, 41, 42, + 43, 46, 47, 46, 47, 48, 86, 48, 51, 52, + 53, 54, 67, 18, 51, 52, 53, 54, 68, 18, + 57, 58, 59, 57, 58, 59, 69, 120, 120, 122, + + 70, 44, 122, 86, 44, 127, 127, 49, 72, 49, + 72, 72, 69, 72, 130, 55, 70, 67, 72, 67, + 67, 55, 67, 84, 74, 75, 60, 67, 130, 60, + 15, 16, 17, 62, 63, 64, 15, 16, 17, 62, + 63, 64, 76, 85, 176, 73, 68, 92, 68, 65, + 84, 74, 75, 128, 77, 65, 80, 120, 120, 68, + 81, 78, 89, 82, 93, 90, 83, 66, 79, 76, + 85, 87, 91, 66, 92, 68, 65, 126, 68, 88, + 68, 77, 65, 80, 94, 68, 68, 81, 78, 89, + 82, 93, 90, 83, 95, 79, 68, 68, 87, 91, + + 96, 125, 122, 98, 97, 122, 88, 99, 101, 133, + 102, 94, 68, 173, 68, 124, 103, 124, 124, 104, + 124, 95, 130, 100, 123, 68, 105, 96, 68, 68, + 98, 97, 106, 134, 99, 101, 133, 102, 135, 116, + 173, 109, 107, 103, 117, 108, 104, 113, 150, 114, + 100, 110, 68, 105, 68, 111, 112, 68, 118, 106, + 134, 68, 119, 68, 115, 135, 116, 121, 109, 107, + 68, 117, 108, 68, 113, 150, 114, 68, 110, 136, + 127, 127, 111, 112, 68, 118, 68, 137, 130, 119, + 72, 115, 72, 72, 129, 72, 129, 129, 67, 129, + + 67, 67, 72, 67, 72, 72, 136, 72, 67, 138, + 139, 68, 72, 140, 137, 141, 142, 143, 68, 145, + 128, 68, 146, 68, 68, 189, 147, 132, 68, 68, + 126, 149, 68, 155, 144, 68, 138, 139, 148, 73, + 140, 68, 141, 142, 151, 663, 145, 68, 68, 146, + 156, 160, 152, 147, 68, 153, 68, 68, 149, 158, + 155, 144, 161, 159, 68, 148, 163, 162, 164, 154, + 157, 151, 68, 125, 166, 68, 68, 156, 160, 152, + 68, 68, 153, 68, 165, 68, 158, 68, 68, 161, + 159, 167, 172, 163, 162, 164, 154, 157, 68, 168, + + 169, 166, 171, 175, 170, 174, 68, 180, 68, 68, + 177, 165, 68, 68, 68, 178, 68, 181, 167, 172, + 183, 184, 68, 185, 68, 68, 168, 169, 68, 171, + 175, 170, 174, 182, 180, 179, 186, 177, 68, 68, + 123, 68, 178, 68, 181, 68, 187, 183, 184, 124, + 185, 124, 124, 129, 124, 129, 129, 188, 129, 190, + 182, 191, 179, 186, 72, 192, 72, 72, 193, 72, + 130, 68, 194, 187, 121, 68, 196, 68, 195, 68, + 68, 68, 1342, 202, 188, 203, 190, 205, 191, 204, + 1342, 68, 192, 68, 206, 193, 1342, 1342, 1342, 1342, + + 68, 132, 208, 68, 1342, 195, 207, 68, 197, 68, + 202, 68, 203, 198, 205, 68, 204, 68, 199, 210, + 209, 206, 211, 214, 200, 201, 213, 212, 68, 208, + 68, 68, 68, 207, 68, 197, 68, 216, 217, 222, + 198, 224, 220, 225, 215, 199, 210, 209, 68, 211, + 214, 200, 201, 213, 212, 68, 218, 221, 223, 226, + 68, 227, 230, 68, 68, 217, 219, 68, 68, 220, + 68, 215, 68, 229, 68, 234, 228, 231, 232, 68, + 68, 238, 68, 68, 221, 223, 226, 68, 227, 230, + 68, 233, 239, 219, 68, 240, 68, 68, 68, 68, + + 229, 235, 234, 228, 231, 232, 68, 236, 237, 241, + 242, 244, 68, 243, 247, 1342, 68, 245, 233, 239, + 68, 68, 240, 253, 251, 248, 1342, 1342, 235, 68, + 252, 250, 68, 254, 236, 237, 241, 68, 244, 246, + 243, 68, 249, 258, 255, 68, 130, 259, 68, 68, + 68, 251, 248, 256, 68, 68, 68, 252, 250, 257, + 254, 260, 68, 265, 261, 262, 246, 68, 1342, 249, + 258, 255, 263, 68, 259, 68, 266, 68, 68, 264, + 256, 68, 267, 270, 268, 288, 257, 68, 260, 272, + 265, 261, 262, 269, 271, 68, 68, 273, 68, 263, + + 275, 68, 68, 68, 274, 278, 264, 68, 276, 267, + 68, 268, 68, 277, 68, 68, 272, 68, 68, 279, + 269, 271, 280, 283, 273, 1342, 68, 275, 68, 281, + 284, 274, 282, 285, 289, 276, 68, 68, 1342, 68, + 277, 68, 292, 68, 68, 1342, 279, 294, 68, 280, + 283, 286, 287, 293, 68, 295, 281, 284, 68, 282, + 285, 289, 290, 299, 296, 291, 1342, 1342, 298, 292, + 308, 68, 68, 297, 68, 68, 68, 68, 286, 287, + 293, 300, 295, 301, 1342, 68, 303, 302, 68, 290, + 68, 296, 291, 304, 68, 298, 305, 307, 306, 68, + + 297, 68, 1342, 310, 68, 68, 309, 1342, 300, 68, + 301, 68, 311, 303, 302, 68, 312, 1342, 313, 68, + 304, 325, 315, 305, 307, 306, 323, 130, 68, 68, + 310, 1342, 324, 309, 314, 68, 1342, 329, 68, 311, + 328, 1342, 68, 312, 326, 313, 327, 68, 325, 315, + 68, 1342, 68, 323, 331, 1342, 334, 330, 68, 324, + 1342, 314, 316, 317, 68, 332, 68, 328, 68, 68, + 1342, 326, 318, 327, 319, 320, 321, 68, 333, 322, + 339, 331, 335, 334, 330, 68, 340, 68, 338, 316, + 317, 68, 332, 336, 337, 68, 342, 68, 341, 318, + + 1342, 319, 320, 321, 68, 333, 322, 339, 343, 335, + 344, 68, 348, 340, 345, 338, 346, 352, 349, 68, + 1342, 68, 68, 342, 350, 341, 351, 68, 353, 347, + 68, 68, 354, 1342, 68, 343, 355, 344, 356, 348, + 68, 345, 357, 346, 68, 349, 1342, 68, 68, 68, + 68, 350, 358, 351, 68, 353, 347, 359, 68, 354, + 361, 360, 1342, 355, 68, 356, 363, 362, 1342, 364, + 1342, 365, 68, 68, 366, 68, 68, 369, 372, 358, + 68, 367, 375, 370, 359, 368, 68, 361, 360, 68, + 68, 68, 68, 363, 362, 68, 364, 68, 365, 371, + + 68, 366, 373, 68, 369, 372, 68, 376, 367, 374, + 370, 1342, 368, 68, 377, 378, 68, 380, 379, 68, + 381, 389, 1342, 1342, 68, 382, 371, 1342, 68, 373, + 68, 68, 68, 68, 376, 406, 374, 393, 68, 68, + 390, 377, 378, 388, 380, 379, 395, 381, 389, 391, + 68, 1342, 382, 383, 392, 394, 1342, 68, 384, 399, + 385, 68, 396, 68, 393, 398, 68, 68, 386, 397, + 388, 68, 68, 395, 68, 401, 391, 68, 387, 68, + 383, 392, 394, 400, 68, 384, 399, 385, 68, 396, + 402, 403, 398, 405, 404, 386, 397, 68, 407, 68, + + 408, 409, 401, 410, 411, 387, 68, 412, 68, 68, + 400, 413, 414, 68, 416, 68, 130, 402, 403, 68, + 405, 404, 68, 68, 417, 407, 415, 408, 409, 418, + 68, 411, 419, 421, 412, 420, 68, 425, 413, 414, + 68, 68, 422, 423, 424, 1342, 1342, 429, 68, 426, + 428, 68, 427, 415, 1342, 1342, 1342, 68, 430, 68, + 68, 436, 68, 435, 68, 68, 437, 68, 68, 422, + 423, 424, 68, 431, 68, 438, 426, 428, 68, 427, + 68, 439, 432, 441, 68, 430, 68, 433, 445, 68, + 435, 434, 68, 437, 443, 1342, 446, 442, 444, 68, + + 431, 457, 438, 440, 68, 68, 68, 447, 439, 432, + 441, 68, 448, 68, 433, 449, 68, 68, 434, 68, + 450, 443, 451, 446, 442, 444, 452, 453, 454, 68, + 440, 68, 68, 1342, 447, 68, 68, 68, 458, 448, + 455, 461, 449, 459, 456, 462, 1342, 450, 68, 451, + 68, 68, 463, 452, 453, 454, 68, 464, 460, 465, + 466, 1342, 1342, 470, 471, 458, 467, 68, 68, 68, + 459, 68, 68, 468, 68, 469, 68, 68, 474, 463, + 68, 68, 68, 472, 464, 460, 465, 466, 475, 473, + 470, 471, 68, 467, 476, 477, 68, 478, 68, 480, + + 468, 68, 469, 479, 490, 483, 1342, 68, 482, 68, + 472, 481, 485, 484, 68, 475, 473, 68, 68, 68, + 68, 476, 477, 486, 478, 68, 480, 68, 68, 488, + 479, 490, 483, 68, 68, 482, 489, 487, 481, 485, + 484, 494, 492, 491, 493, 68, 68, 68, 497, 68, + 486, 495, 1342, 498, 68, 500, 488, 1342, 1342, 496, + 506, 501, 1342, 489, 487, 130, 68, 68, 494, 492, + 491, 493, 499, 68, 68, 502, 68, 68, 495, 68, + 498, 68, 500, 503, 504, 68, 496, 513, 501, 505, + 1342, 68, 1342, 515, 514, 68, 517, 1342, 518, 499, + + 1342, 68, 502, 68, 516, 68, 1342, 1342, 522, 68, + 503, 504, 68, 519, 513, 1342, 505, 507, 68, 508, + 515, 514, 509, 68, 520, 518, 521, 510, 68, 525, + 523, 516, 68, 511, 512, 522, 68, 68, 526, 68, + 519, 529, 68, 530, 507, 531, 508, 524, 68, 509, + 527, 520, 68, 521, 510, 68, 525, 523, 528, 532, + 511, 512, 68, 68, 68, 526, 533, 68, 529, 534, + 68, 535, 536, 537, 524, 541, 68, 527, 539, 563, + 543, 68, 538, 68, 540, 528, 532, 68, 68, 542, + 68, 545, 1342, 533, 1342, 68, 534, 68, 535, 536, + + 537, 544, 68, 68, 68, 68, 68, 543, 546, 538, + 68, 540, 554, 547, 68, 551, 542, 68, 545, 549, + 68, 548, 68, 550, 555, 68, 552, 553, 544, 68, + 68, 68, 556, 1342, 68, 546, 557, 68, 558, 554, + 547, 68, 551, 560, 68, 559, 549, 68, 548, 565, + 550, 555, 564, 552, 553, 561, 68, 68, 68, 556, + 562, 567, 68, 557, 68, 558, 566, 571, 568, 570, + 560, 569, 559, 68, 68, 68, 565, 572, 573, 564, + 574, 68, 561, 68, 1342, 576, 68, 562, 567, 575, + 577, 68, 68, 566, 571, 568, 68, 68, 569, 579, + + 68, 578, 580, 581, 572, 573, 68, 582, 1342, 588, + 68, 68, 68, 68, 1342, 590, 575, 130, 591, 589, + 68, 68, 68, 594, 595, 593, 579, 68, 578, 580, + 581, 68, 68, 592, 582, 583, 588, 584, 68, 68, + 601, 585, 590, 586, 68, 591, 589, 600, 587, 1342, + 594, 596, 593, 68, 603, 68, 597, 602, 598, 68, + 592, 608, 583, 605, 584, 604, 606, 601, 585, 68, + 586, 610, 68, 609, 600, 587, 599, 68, 596, 68, + 68, 603, 68, 597, 602, 598, 607, 68, 68, 612, + 605, 611, 604, 606, 68, 613, 68, 68, 614, 615, + + 609, 617, 68, 599, 616, 621, 619, 618, 1342, 68, + 624, 620, 68, 607, 68, 68, 612, 68, 611, 68, + 68, 622, 613, 68, 625, 614, 615, 623, 617, 68, + 68, 616, 68, 619, 618, 626, 68, 624, 620, 68, + 627, 629, 628, 630, 635, 1342, 68, 631, 622, 632, + 656, 625, 633, 634, 623, 638, 68, 68, 68, 636, + 637, 68, 626, 639, 643, 1342, 68, 627, 68, 628, + 640, 635, 68, 641, 68, 68, 632, 68, 642, 633, + 634, 68, 638, 644, 68, 68, 636, 637, 646, 645, + 639, 68, 68, 647, 68, 648, 651, 640, 68, 68, + + 641, 68, 68, 68, 649, 642, 652, 650, 653, 655, + 644, 68, 68, 654, 657, 646, 645, 68, 68, 659, + 647, 68, 648, 651, 660, 68, 658, 1342, 68, 661, + 665, 649, 68, 652, 650, 653, 655, 68, 68, 662, + 654, 664, 68, 669, 666, 68, 68, 667, 68, 68, + 68, 660, 68, 658, 68, 68, 661, 665, 670, 668, + 671, 672, 673, 674, 1342, 68, 662, 675, 664, 677, + 669, 666, 68, 676, 667, 678, 68, 679, 1342, 680, + 68, 68, 698, 681, 68, 670, 668, 68, 68, 673, + 674, 68, 68, 682, 675, 68, 677, 683, 687, 684, + + 676, 68, 678, 685, 68, 68, 680, 688, 686, 693, + 681, 68, 690, 68, 691, 68, 68, 689, 68, 68, + 682, 68, 68, 707, 683, 687, 684, 68, 694, 68, + 685, 68, 692, 695, 688, 686, 693, 699, 68, 690, + 696, 691, 705, 697, 689, 68, 700, 68, 706, 68, + 68, 701, 702, 703, 68, 694, 68, 704, 68, 692, + 695, 68, 708, 709, 699, 68, 68, 696, 711, 705, + 697, 710, 715, 700, 68, 706, 716, 712, 701, 702, + 1342, 1342, 714, 713, 68, 68, 717, 1342, 68, 708, + 709, 68, 718, 68, 68, 711, 68, 1342, 710, 68, + + 724, 723, 1342, 68, 712, 726, 729, 68, 68, 714, + 713, 719, 725, 717, 68, 68, 720, 68, 721, 718, + 722, 727, 728, 68, 68, 68, 731, 724, 723, 68, + 68, 730, 726, 729, 68, 68, 733, 734, 719, 725, + 732, 735, 68, 720, 68, 721, 737, 722, 727, 728, + 736, 738, 739, 731, 68, 740, 1342, 742, 730, 68, + 748, 741, 743, 68, 68, 68, 745, 732, 735, 68, + 744, 747, 68, 737, 746, 749, 750, 736, 68, 739, + 68, 68, 68, 68, 68, 68, 751, 748, 741, 743, + 753, 752, 68, 745, 760, 68, 68, 744, 747, 756, + + 755, 746, 749, 757, 754, 758, 759, 68, 68, 761, + 68, 763, 68, 68, 764, 68, 68, 68, 752, 768, + 68, 68, 68, 68, 1342, 68, 756, 755, 762, 779, + 68, 754, 758, 759, 1342, 68, 761, 765, 763, 767, + 68, 764, 68, 766, 68, 68, 768, 769, 68, 771, + 68, 770, 772, 773, 774, 762, 779, 1342, 775, 776, + 777, 68, 780, 68, 765, 68, 767, 1342, 782, 68, + 766, 1342, 784, 783, 68, 68, 771, 788, 68, 772, + 773, 774, 68, 778, 781, 775, 776, 777, 785, 780, + 68, 68, 68, 68, 68, 782, 786, 68, 68, 784, + + 783, 787, 789, 790, 788, 791, 792, 793, 68, 804, + 778, 781, 796, 68, 68, 785, 794, 797, 795, 799, + 68, 798, 1342, 786, 800, 68, 803, 801, 787, 789, + 790, 68, 68, 68, 793, 68, 68, 68, 68, 796, + 68, 802, 805, 794, 806, 795, 68, 68, 68, 68, + 68, 800, 68, 803, 801, 807, 808, 809, 813, 810, + 811, 1342, 812, 68, 68, 68, 817, 814, 802, 805, + 68, 806, 68, 68, 816, 818, 819, 815, 822, 825, + 68, 824, 807, 808, 809, 813, 810, 811, 68, 812, + 68, 68, 68, 817, 814, 820, 826, 823, 68, 821, + + 827, 816, 68, 819, 815, 828, 68, 68, 824, 68, + 68, 829, 831, 830, 68, 1342, 833, 834, 68, 68, + 832, 850, 820, 68, 823, 68, 821, 68, 68, 68, + 836, 837, 828, 838, 835, 857, 68, 68, 829, 831, + 830, 68, 68, 833, 68, 839, 840, 832, 841, 68, + 842, 843, 68, 844, 68, 845, 68, 836, 837, 68, + 838, 835, 68, 848, 68, 849, 68, 846, 68, 847, + 68, 1342, 839, 840, 68, 841, 68, 842, 843, 68, + 844, 853, 845, 854, 851, 852, 1342, 68, 68, 856, + 848, 68, 849, 855, 846, 68, 847, 858, 68, 860, + + 859, 1342, 68, 862, 865, 68, 864, 68, 853, 68, + 854, 851, 852, 68, 861, 863, 856, 866, 872, 68, + 855, 68, 870, 68, 858, 68, 860, 859, 68, 867, + 862, 68, 68, 864, 873, 68, 868, 871, 68, 68, + 869, 861, 863, 68, 866, 872, 874, 68, 875, 870, + 877, 876, 68, 68, 878, 68, 867, 68, 879, 881, + 882, 880, 68, 868, 871, 68, 883, 869, 884, 890, + 68, 885, 886, 874, 68, 875, 68, 877, 876, 68, + 68, 878, 1342, 889, 891, 879, 881, 68, 880, 68, + 68, 887, 893, 883, 888, 884, 892, 901, 885, 886, + + 68, 68, 895, 68, 894, 896, 68, 68, 897, 68, + 889, 68, 898, 68, 899, 68, 903, 68, 887, 893, + 1342, 888, 904, 892, 900, 68, 905, 902, 68, 895, + 1342, 894, 896, 68, 906, 897, 68, 1342, 68, 898, + 907, 899, 910, 68, 909, 912, 908, 68, 68, 904, + 911, 900, 920, 68, 902, 913, 68, 68, 916, 68, + 1342, 906, 917, 68, 68, 914, 68, 907, 915, 910, + 68, 909, 912, 908, 68, 68, 918, 911, 919, 920, + 923, 68, 913, 921, 68, 916, 924, 68, 927, 917, + 922, 925, 914, 926, 928, 915, 935, 931, 68, 68, + + 68, 930, 68, 918, 932, 919, 68, 68, 68, 68, + 921, 933, 934, 924, 929, 939, 943, 922, 925, 68, + 926, 928, 68, 68, 68, 937, 936, 68, 930, 68, + 938, 68, 68, 68, 941, 942, 940, 68, 933, 68, + 944, 929, 68, 68, 945, 946, 947, 68, 951, 948, + 1342, 68, 937, 936, 68, 949, 1342, 938, 950, 958, + 1342, 68, 68, 940, 68, 68, 952, 944, 953, 959, + 1342, 955, 946, 954, 1342, 68, 948, 68, 68, 68, + 956, 68, 68, 957, 68, 950, 958, 68, 960, 68, + 68, 961, 962, 952, 963, 953, 68, 964, 955, 68, + + 954, 968, 965, 967, 68, 966, 972, 956, 975, 68, + 957, 971, 68, 969, 68, 960, 974, 68, 961, 962, + 970, 963, 68, 68, 964, 1342, 976, 68, 968, 965, + 967, 68, 966, 68, 973, 68, 68, 68, 971, 977, + 969, 68, 978, 974, 979, 989, 980, 970, 68, 68, + 981, 982, 983, 976, 68, 986, 68, 68, 984, 987, + 990, 973, 68, 985, 991, 68, 977, 988, 992, 978, + 68, 979, 68, 980, 68, 993, 68, 981, 982, 983, + 68, 994, 68, 995, 996, 984, 987, 68, 998, 997, + 985, 999, 1000, 68, 988, 68, 68, 1001, 1002, 68, + + 1005, 1004, 68, 68, 1003, 1006, 68, 1011, 994, 1007, + 1342, 996, 68, 1008, 68, 998, 997, 1009, 999, 68, + 1017, 1010, 68, 68, 1001, 68, 1012, 68, 1004, 68, + 68, 1003, 68, 1014, 1011, 68, 1007, 1013, 68, 68, + 1008, 1015, 68, 1016, 1009, 1018, 1019, 68, 1010, 1021, + 1342, 1023, 68, 1012, 1022, 1020, 1342, 1342, 68, 68, + 1014, 68, 1025, 1024, 1013, 68, 1026, 1027, 1015, 68, + 1016, 1028, 1018, 68, 1342, 68, 1021, 68, 68, 68, + 1029, 1022, 1020, 68, 1030, 1031, 68, 1033, 1034, 1025, + 1024, 1035, 68, 1026, 1027, 68, 1032, 68, 1028, 68, + + 68, 1036, 1038, 68, 1037, 1039, 68, 1029, 1040, 68, + 1342, 1030, 1031, 68, 1033, 1034, 1041, 68, 1035, 68, + 1042, 1046, 1043, 1032, 1044, 1342, 1047, 1045, 1036, 68, + 68, 1037, 1039, 68, 68, 1040, 1050, 1048, 1342, 1066, + 1051, 68, 68, 1041, 68, 68, 1049, 1042, 68, 1043, + 1055, 1044, 68, 1047, 1045, 68, 1054, 1052, 1057, 68, + 1053, 1056, 1068, 68, 1048, 1059, 68, 1051, 68, 1058, + 1064, 1060, 68, 1049, 1062, 68, 68, 1055, 68, 68, + 68, 68, 1061, 1054, 1052, 1057, 1063, 1053, 1056, 68, + 1065, 68, 1059, 68, 1067, 68, 1058, 1064, 1060, 1070, + + 1072, 1062, 1069, 1071, 1073, 1074, 1129, 68, 68, 1061, + 68, 1076, 68, 1063, 68, 1075, 1080, 1065, 1077, 1078, + 1342, 1067, 68, 1342, 68, 68, 1070, 1072, 1079, 1069, + 1071, 68, 1074, 68, 68, 1081, 1082, 68, 68, 68, + 1083, 68, 1075, 1080, 68, 1077, 1078, 68, 1084, 1085, + 68, 1086, 68, 1088, 1087, 1079, 68, 1090, 68, 68, + 68, 1091, 1081, 1082, 1089, 1092, 1095, 1083, 68, 1093, + 68, 1094, 1096, 1097, 1098, 1084, 1085, 1099, 1086, 68, + 1088, 1087, 1100, 68, 68, 68, 1101, 68, 1091, 1102, + 68, 1089, 1092, 68, 1103, 1104, 1093, 68, 1094, 68, + + 1097, 68, 68, 1105, 68, 1107, 1106, 1109, 1342, 1100, + 1108, 1110, 1342, 68, 68, 1113, 68, 68, 1114, 68, + 1115, 1103, 1104, 1342, 1111, 1116, 68, 1118, 68, 1120, + 68, 1119, 68, 1106, 1109, 68, 1342, 1108, 1110, 1112, + 1117, 68, 68, 1121, 68, 1114, 1122, 68, 68, 68, + 68, 1111, 68, 68, 1118, 1123, 1120, 1124, 1119, 1125, + 1126, 1127, 1128, 68, 1342, 68, 1112, 1117, 1130, 68, + 1121, 1131, 68, 1122, 1132, 1134, 1133, 1140, 68, 68, + 68, 68, 1123, 1139, 1124, 1135, 1125, 1126, 1127, 1128, + 1138, 68, 68, 1136, 1141, 1130, 1137, 1150, 1131, 68, + + 1143, 1132, 68, 1133, 1140, 68, 68, 68, 68, 1142, + 1139, 68, 1135, 1144, 1151, 1145, 1147, 1138, 1146, 1148, + 1136, 68, 1149, 1137, 68, 68, 68, 1143, 68, 1153, + 1155, 1161, 68, 1154, 1157, 68, 1142, 68, 1156, 68, + 68, 1151, 1145, 1147, 68, 1146, 1148, 1152, 1158, 1149, + 1159, 68, 68, 1160, 1165, 68, 1153, 1155, 68, 1162, + 1154, 68, 68, 1164, 68, 1156, 1166, 1163, 68, 1167, + 68, 1169, 1168, 1170, 1152, 1158, 68, 68, 68, 1171, + 68, 1165, 1172, 1173, 68, 68, 1162, 1174, 1176, 1177, + 1164, 68, 1175, 68, 1163, 68, 1167, 68, 1169, 1168, + + 1170, 68, 68, 68, 68, 1178, 68, 1180, 1181, 68, + 68, 1179, 1182, 68, 1174, 1176, 1177, 1183, 68, 1175, + 68, 1187, 1184, 1188, 68, 1185, 68, 1186, 68, 1189, + 68, 1190, 1178, 1191, 68, 1181, 68, 1192, 1179, 1182, + 68, 1193, 68, 1194, 1183, 68, 1196, 1195, 1187, 1184, + 1188, 68, 1185, 1197, 1186, 68, 1189, 1200, 68, 68, + 1191, 68, 68, 68, 1192, 1198, 1201, 1199, 68, 1202, + 1194, 1203, 1208, 1196, 1195, 68, 68, 1207, 1204, 68, + 1197, 68, 1205, 1209, 68, 68, 1206, 1211, 1213, 1214, + 68, 1210, 1198, 68, 1199, 68, 1202, 68, 1203, 68, + + 68, 68, 1215, 1212, 1207, 1204, 1217, 1216, 1220, 1205, + 1209, 68, 68, 1206, 68, 68, 68, 1218, 1210, 1219, + 1221, 1222, 1225, 1223, 68, 1224, 1226, 68, 68, 1215, + 1212, 1227, 68, 1217, 1216, 1220, 1228, 68, 1229, 68, + 1231, 68, 1230, 68, 1218, 68, 1219, 1221, 1222, 68, + 1223, 1232, 1224, 68, 1233, 68, 1234, 1240, 1235, 1342, + 1236, 1237, 68, 68, 68, 68, 1242, 1231, 68, 1230, + 1247, 1241, 1238, 1243, 68, 68, 68, 1245, 1232, 68, + 68, 1233, 1239, 1234, 68, 1235, 68, 1236, 1237, 68, + 68, 1244, 68, 68, 1246, 68, 1248, 68, 1241, 1238, + + 1243, 1249, 1250, 68, 1245, 1251, 1252, 1253, 68, 1239, + 1255, 1254, 1256, 68, 1342, 1258, 68, 1257, 1244, 1262, + 1342, 1246, 1259, 1248, 68, 1264, 68, 68, 1249, 1250, + 68, 1260, 68, 68, 1253, 1261, 68, 1263, 1254, 68, + 68, 68, 1258, 68, 1257, 68, 1262, 68, 68, 1259, + 68, 1267, 1264, 1265, 1266, 68, 1268, 1270, 1260, 1271, + 68, 1269, 1261, 68, 1263, 1342, 68, 1272, 1276, 68, + 68, 1273, 1275, 1274, 1277, 1342, 1278, 1342, 1267, 1279, + 1265, 1266, 1280, 1268, 1270, 68, 68, 68, 1269, 68, + 68, 68, 1281, 1342, 1272, 1276, 68, 68, 1273, 1275, + + 1274, 1277, 68, 1278, 68, 1282, 1279, 1284, 1283, 1280, + 68, 1285, 1286, 68, 1287, 1289, 1292, 1288, 1291, 1281, + 68, 1294, 68, 68, 1290, 68, 68, 1293, 1297, 68, + 1298, 1342, 1282, 1295, 68, 1283, 68, 68, 1285, 1286, + 68, 1287, 1289, 68, 1288, 1291, 1300, 1296, 68, 68, + 1299, 1290, 68, 1302, 1293, 68, 1301, 68, 68, 1304, + 1295, 68, 1305, 68, 1303, 1306, 1307, 1308, 1309, 1310, + 68, 1312, 1314, 1300, 1296, 1311, 1342, 1299, 68, 68, + 68, 1313, 1315, 1301, 1316, 1317, 68, 1321, 68, 1305, + 1323, 1303, 1306, 1307, 68, 68, 68, 68, 68, 68, + + 1318, 1319, 1311, 68, 68, 1325, 1320, 68, 1313, 1315, + 1327, 1316, 68, 68, 68, 1322, 1324, 68, 1326, 68, + 1328, 1329, 68, 68, 1330, 1331, 1332, 1318, 1319, 1333, + 68, 1334, 68, 1320, 1336, 1342, 1339, 1327, 68, 68, + 1342, 68, 1322, 1324, 1337, 1326, 1341, 68, 68, 68, + 1335, 68, 68, 1332, 68, 68, 1333, 68, 1334, 1340, + 1338, 68, 68, 1339, 1342, 1342, 1342, 68, 1342, 1342, + 1342, 1337, 68, 68, 1342, 1342, 1342, 1335, 1342, 1342, + 1342, 1342, 1342, 1342, 1342, 1342, 1340, 1338, 40, 40, + 40, 40, 40, 40, 40, 45, 45, 45, 45, 45, + + 45, 45, 50, 50, 50, 50, 50, 50, 50, 56, + 56, 56, 56, 56, 56, 56, 61, 61, 61, 61, + 61, 61, 61, 71, 71, 1342, 71, 71, 71, 71, + 120, 120, 1342, 1342, 1342, 120, 120, 122, 122, 1342, + 1342, 122, 1342, 122, 124, 1342, 1342, 1342, 1342, 1342, + 124, 127, 127, 1342, 1342, 1342, 127, 127, 129, 1342, + 1342, 1342, 1342, 1342, 129, 131, 131, 1342, 131, 131, + 131, 131, 72, 72, 1342, 72, 72, 72, 72, 13, + 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, + 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, + + 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, + 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, + 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, + 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, + 1342, 1342, 1342, 1342, 1342 + } ; + +static yyconst flex_int16_t yy_chk[3946] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 3, 3, 3, 4, 4, + 4, 5, 5, 6, 6, 5, 24, 6, 7, 7, + 7, 7, 1348, 7, 8, 8, 8, 8, 24, 8, + 9, 9, 9, 10, 10, 10, 15, 44, 44, 49, + + 15, 3, 49, 24, 4, 60, 60, 5, 19, 6, + 19, 19, 69, 19, 577, 7, 69, 39, 19, 39, + 39, 8, 39, 23, 20, 20, 9, 39, 129, 10, + 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, + 12, 12, 20, 23, 110, 19, 23, 27, 20, 11, + 23, 20, 20, 127, 21, 12, 22, 121, 121, 27, + 22, 21, 26, 22, 28, 26, 22, 11, 21, 20, + 23, 25, 26, 12, 27, 110, 11, 126, 22, 25, + 21, 21, 12, 22, 29, 26, 28, 22, 21, 26, + 22, 28, 26, 22, 30, 21, 29, 25, 25, 26, + + 30, 124, 123, 31, 30, 123, 25, 31, 32, 65, + 33, 29, 30, 107, 32, 55, 33, 55, 55, 33, + 55, 30, 65, 31, 122, 107, 33, 30, 33, 31, + 31, 30, 34, 74, 31, 32, 65, 33, 75, 37, + 107, 35, 34, 33, 37, 34, 33, 36, 89, 36, + 31, 35, 37, 33, 34, 35, 35, 74, 38, 34, + 74, 75, 38, 35, 36, 75, 37, 120, 35, 34, + 89, 37, 34, 36, 36, 89, 36, 67, 35, 76, + 128, 128, 35, 35, 38, 38, 76, 77, 61, 38, + 63, 36, 63, 63, 66, 63, 66, 66, 68, 66, + + 68, 68, 71, 68, 71, 71, 76, 71, 68, 78, + 79, 77, 71, 80, 77, 81, 82, 83, 78, 84, + 56, 82, 85, 79, 81, 135, 86, 63, 80, 85, + 51, 88, 84, 92, 83, 86, 78, 79, 87, 71, + 80, 92, 81, 82, 90, 571, 84, 87, 83, 85, + 93, 95, 91, 86, 88, 91, 135, 90, 88, 94, + 92, 83, 96, 94, 95, 87, 98, 97, 99, 91, + 93, 90, 93, 50, 101, 571, 91, 93, 95, 91, + 98, 101, 91, 94, 100, 96, 94, 97, 99, 96, + 94, 102, 106, 98, 97, 99, 91, 93, 100, 103, + + 104, 101, 105, 109, 104, 108, 106, 113, 103, 105, + 111, 100, 109, 108, 102, 112, 113, 114, 102, 106, + 116, 117, 104, 118, 116, 111, 103, 104, 114, 105, + 109, 104, 108, 115, 113, 112, 119, 111, 118, 115, + 45, 112, 112, 117, 114, 119, 133, 116, 117, 125, + 118, 125, 125, 130, 125, 130, 130, 134, 130, 136, + 115, 137, 112, 119, 131, 138, 131, 131, 139, 131, + 133, 136, 140, 133, 40, 139, 142, 138, 141, 134, + 137, 14, 13, 144, 134, 145, 136, 147, 137, 146, + 0, 147, 138, 145, 148, 139, 0, 0, 0, 0, + + 141, 131, 150, 140, 0, 141, 149, 142, 143, 144, + 144, 146, 145, 143, 147, 150, 146, 148, 143, 152, + 151, 148, 152, 155, 143, 143, 154, 153, 149, 150, + 155, 143, 151, 149, 152, 143, 153, 157, 158, 162, + 143, 164, 160, 165, 156, 143, 152, 151, 154, 152, + 155, 143, 143, 154, 153, 156, 159, 161, 163, 166, + 160, 167, 170, 161, 158, 158, 159, 170, 157, 160, + 162, 156, 164, 169, 165, 174, 168, 171, 172, 166, + 163, 177, 167, 168, 161, 163, 166, 159, 167, 170, + 172, 173, 178, 159, 169, 179, 171, 174, 173, 178, + + 169, 175, 174, 168, 171, 172, 175, 176, 176, 180, + 181, 183, 177, 182, 185, 0, 176, 184, 173, 178, + 179, 182, 179, 190, 188, 186, 0, 0, 175, 180, + 189, 187, 188, 191, 176, 176, 180, 183, 183, 184, + 182, 181, 186, 195, 192, 185, 187, 196, 184, 189, + 186, 188, 186, 193, 190, 191, 192, 189, 187, 194, + 191, 197, 193, 202, 198, 199, 184, 195, 0, 186, + 195, 192, 200, 196, 196, 198, 203, 199, 194, 201, + 193, 202, 204, 207, 205, 223, 194, 197, 197, 209, + 202, 198, 199, 206, 208, 204, 200, 210, 209, 200, + + 212, 208, 201, 210, 211, 215, 201, 203, 213, 204, + 205, 205, 223, 214, 207, 206, 209, 213, 211, 216, + 206, 208, 217, 219, 210, 0, 212, 212, 214, 218, + 220, 211, 218, 221, 224, 213, 215, 217, 0, 218, + 214, 219, 226, 216, 220, 0, 216, 228, 221, 217, + 219, 222, 222, 227, 226, 229, 218, 220, 224, 218, + 221, 224, 225, 233, 230, 225, 0, 0, 232, 226, + 240, 227, 225, 231, 228, 232, 222, 229, 222, 222, + 227, 234, 229, 235, 0, 231, 237, 236, 234, 225, + 230, 230, 225, 238, 233, 232, 238, 239, 238, 237, + + 231, 240, 0, 242, 238, 235, 241, 0, 234, 242, + 235, 236, 243, 237, 236, 239, 244, 0, 245, 243, + 238, 250, 246, 238, 239, 238, 248, 250, 241, 244, + 242, 0, 249, 241, 245, 246, 0, 254, 248, 243, + 253, 0, 245, 244, 251, 245, 252, 253, 250, 246, + 249, 0, 251, 248, 256, 0, 259, 255, 252, 249, + 0, 245, 247, 247, 255, 257, 256, 253, 254, 259, + 0, 251, 247, 252, 247, 247, 247, 257, 258, 247, + 263, 256, 260, 259, 255, 258, 264, 247, 262, 247, + 247, 263, 257, 261, 261, 262, 266, 264, 265, 247, + + 0, 247, 247, 247, 260, 258, 247, 263, 267, 260, + 268, 265, 271, 264, 269, 262, 270, 275, 272, 268, + 0, 266, 261, 266, 273, 265, 274, 269, 276, 270, + 271, 267, 277, 0, 270, 267, 278, 268, 279, 271, + 272, 269, 280, 270, 274, 272, 0, 273, 275, 276, + 278, 273, 281, 274, 277, 276, 270, 282, 281, 277, + 284, 283, 0, 278, 279, 279, 286, 285, 0, 287, + 0, 289, 286, 280, 290, 282, 283, 293, 297, 281, + 290, 291, 300, 295, 282, 292, 284, 284, 283, 285, + 295, 297, 293, 286, 285, 287, 287, 289, 289, 296, + + 291, 290, 298, 292, 293, 297, 296, 301, 291, 299, + 295, 0, 292, 300, 302, 303, 301, 305, 304, 302, + 306, 310, 0, 0, 298, 307, 296, 0, 299, 298, + 304, 306, 310, 307, 301, 326, 299, 313, 303, 305, + 311, 302, 303, 309, 305, 304, 315, 306, 310, 311, + 309, 0, 307, 308, 312, 314, 0, 314, 308, 319, + 308, 312, 316, 313, 313, 318, 326, 319, 308, 317, + 309, 311, 315, 315, 316, 321, 311, 318, 308, 308, + 308, 312, 314, 320, 317, 308, 319, 308, 320, 316, + 322, 323, 318, 325, 324, 308, 317, 321, 327, 323, + + 328, 329, 321, 330, 331, 308, 324, 332, 322, 328, + 320, 333, 334, 327, 336, 329, 325, 322, 323, 331, + 325, 324, 332, 333, 337, 327, 335, 328, 329, 338, + 330, 331, 339, 341, 332, 340, 334, 345, 333, 334, + 335, 336, 342, 343, 344, 0, 0, 349, 342, 346, + 348, 337, 347, 335, 0, 0, 0, 348, 350, 339, + 338, 354, 340, 353, 341, 343, 355, 344, 345, 342, + 343, 344, 346, 351, 347, 356, 346, 348, 349, 347, + 350, 357, 352, 358, 355, 350, 351, 352, 362, 353, + 353, 352, 354, 355, 360, 0, 363, 359, 361, 356, + + 351, 373, 356, 357, 357, 358, 352, 364, 357, 352, + 358, 359, 365, 361, 352, 366, 360, 363, 352, 362, + 367, 360, 368, 363, 359, 361, 369, 370, 371, 367, + 357, 364, 373, 0, 364, 368, 365, 366, 374, 365, + 372, 376, 366, 375, 372, 376, 0, 367, 369, 368, + 371, 370, 377, 369, 370, 371, 374, 378, 375, 379, + 380, 0, 0, 384, 385, 374, 381, 375, 379, 380, + 375, 372, 376, 382, 381, 383, 385, 377, 388, 377, + 382, 384, 378, 386, 378, 375, 379, 380, 389, 387, + 384, 385, 386, 381, 390, 391, 389, 392, 383, 394, + + 382, 387, 383, 393, 404, 397, 0, 394, 396, 388, + 386, 395, 399, 398, 393, 389, 387, 404, 391, 392, + 390, 390, 391, 400, 392, 395, 394, 397, 396, 402, + 393, 404, 397, 398, 399, 396, 403, 401, 395, 399, + 398, 408, 406, 405, 407, 400, 401, 408, 411, 402, + 400, 409, 0, 412, 403, 414, 402, 0, 0, 409, + 424, 415, 0, 403, 401, 405, 406, 407, 408, 406, + 405, 407, 413, 415, 414, 418, 412, 409, 409, 411, + 412, 413, 414, 421, 422, 418, 409, 426, 415, 423, + 0, 424, 0, 428, 427, 428, 430, 0, 431, 413, + + 0, 421, 418, 427, 429, 422, 0, 0, 435, 426, + 421, 422, 423, 432, 426, 0, 423, 425, 431, 425, + 428, 427, 425, 430, 433, 431, 434, 425, 429, 438, + 436, 429, 435, 425, 425, 435, 433, 436, 439, 432, + 432, 442, 425, 443, 425, 444, 425, 437, 438, 425, + 440, 433, 434, 434, 425, 437, 438, 436, 441, 445, + 425, 425, 440, 442, 439, 439, 446, 441, 442, 447, + 443, 448, 449, 450, 437, 454, 444, 440, 452, 477, + 457, 449, 451, 445, 453, 441, 445, 446, 447, 455, + 448, 459, 0, 446, 0, 450, 447, 455, 448, 449, + + 450, 458, 451, 453, 457, 452, 454, 457, 460, 451, + 477, 453, 468, 461, 458, 465, 455, 459, 459, 463, + 460, 461, 465, 464, 469, 463, 466, 467, 458, 464, + 468, 466, 470, 0, 467, 460, 471, 461, 472, 468, + 461, 470, 465, 474, 471, 473, 463, 469, 461, 479, + 464, 469, 478, 466, 467, 475, 472, 479, 473, 470, + 476, 481, 475, 471, 474, 472, 480, 485, 482, 484, + 474, 483, 473, 476, 482, 478, 479, 486, 487, 478, + 488, 480, 475, 481, 0, 490, 486, 476, 481, 489, + 491, 485, 487, 480, 485, 482, 489, 483, 483, 493, + + 484, 492, 494, 495, 486, 487, 495, 496, 0, 498, + 494, 488, 490, 492, 0, 500, 489, 491, 501, 499, + 496, 499, 493, 504, 505, 503, 493, 500, 492, 494, + 495, 501, 498, 502, 496, 497, 498, 497, 503, 502, + 508, 497, 500, 497, 504, 501, 499, 507, 497, 0, + 504, 506, 503, 508, 510, 505, 506, 509, 506, 497, + 502, 515, 497, 512, 497, 511, 513, 508, 497, 507, + 497, 518, 509, 516, 507, 497, 506, 506, 506, 513, + 510, 510, 512, 506, 509, 506, 514, 511, 515, 520, + 512, 519, 511, 513, 514, 521, 516, 520, 522, 523, + + 516, 525, 518, 506, 524, 529, 527, 526, 0, 521, + 533, 528, 524, 514, 526, 519, 520, 523, 519, 527, + 522, 531, 521, 525, 534, 522, 523, 532, 525, 528, + 531, 524, 533, 527, 526, 535, 529, 533, 528, 532, + 536, 538, 537, 540, 543, 0, 534, 540, 531, 541, + 564, 534, 541, 542, 532, 546, 543, 535, 536, 544, + 545, 546, 535, 547, 551, 0, 544, 536, 537, 537, + 548, 543, 538, 549, 540, 541, 541, 542, 550, 541, + 542, 564, 546, 552, 545, 547, 544, 545, 554, 553, + 547, 551, 548, 555, 549, 556, 559, 548, 553, 550, + + 549, 552, 555, 556, 557, 550, 560, 558, 561, 563, + 552, 557, 554, 562, 565, 554, 553, 561, 559, 567, + 555, 558, 556, 559, 568, 563, 566, 0, 560, 569, + 573, 557, 568, 560, 558, 561, 563, 562, 566, 570, + 562, 572, 569, 579, 574, 565, 567, 575, 573, 575, + 572, 568, 574, 566, 570, 579, 569, 573, 580, 578, + 581, 582, 583, 584, 0, 580, 570, 585, 572, 587, + 579, 574, 578, 586, 575, 588, 584, 589, 0, 590, + 585, 587, 609, 591, 583, 580, 578, 588, 590, 583, + 584, 581, 582, 592, 585, 586, 587, 593, 597, 594, + + 586, 591, 588, 595, 589, 593, 590, 598, 596, 603, + 591, 595, 600, 609, 601, 592, 597, 599, 603, 598, + 592, 594, 601, 617, 593, 597, 594, 600, 604, 599, + 595, 596, 602, 605, 598, 596, 603, 610, 602, 600, + 606, 601, 615, 607, 599, 605, 611, 606, 616, 604, + 610, 612, 613, 614, 617, 604, 615, 614, 612, 602, + 605, 607, 618, 619, 610, 611, 616, 606, 621, 615, + 607, 620, 625, 611, 613, 616, 626, 622, 612, 613, + 0, 0, 624, 623, 614, 619, 627, 0, 618, 618, + 619, 624, 628, 620, 621, 621, 623, 0, 620, 622, + + 632, 630, 0, 625, 622, 634, 637, 626, 627, 624, + 623, 629, 633, 627, 634, 628, 629, 630, 629, 628, + 629, 635, 636, 632, 633, 637, 639, 632, 630, 629, + 636, 638, 634, 637, 635, 639, 641, 642, 629, 633, + 640, 644, 640, 629, 638, 629, 646, 629, 635, 636, + 645, 647, 648, 639, 646, 649, 0, 651, 638, 648, + 657, 650, 652, 641, 642, 644, 654, 640, 644, 652, + 653, 656, 645, 646, 655, 658, 660, 645, 647, 648, + 656, 657, 649, 650, 651, 654, 661, 657, 650, 652, + 663, 662, 653, 654, 670, 658, 655, 653, 656, 666, + + 665, 655, 658, 667, 664, 668, 669, 660, 665, 671, + 669, 673, 668, 662, 674, 666, 671, 661, 662, 678, + 673, 663, 664, 678, 0, 670, 666, 665, 672, 689, + 667, 664, 668, 669, 0, 672, 671, 675, 673, 677, + 674, 674, 689, 676, 675, 676, 678, 680, 677, 681, + 681, 680, 682, 683, 684, 672, 689, 0, 685, 686, + 687, 682, 690, 684, 675, 685, 677, 0, 692, 687, + 676, 0, 694, 693, 690, 683, 681, 698, 680, 682, + 683, 684, 686, 688, 691, 685, 686, 687, 695, 690, + 692, 688, 691, 693, 694, 692, 696, 695, 698, 694, + + 693, 697, 699, 700, 698, 701, 702, 703, 699, 714, + 688, 691, 707, 697, 696, 695, 705, 708, 706, 709, + 707, 708, 0, 696, 710, 700, 713, 711, 697, 699, + 700, 706, 710, 703, 703, 711, 701, 702, 705, 707, + 714, 712, 715, 705, 716, 706, 709, 713, 708, 712, + 715, 710, 716, 713, 711, 717, 718, 719, 723, 720, + 721, 0, 722, 717, 718, 720, 727, 724, 712, 715, + 719, 716, 721, 727, 726, 728, 729, 725, 732, 737, + 723, 736, 717, 718, 719, 723, 720, 721, 722, 722, + 724, 725, 726, 727, 724, 730, 739, 735, 729, 731, + + 741, 726, 728, 729, 725, 743, 731, 736, 736, 732, + 737, 744, 746, 745, 746, 0, 748, 749, 730, 735, + 747, 766, 730, 739, 735, 745, 731, 741, 748, 743, + 751, 752, 743, 753, 750, 774, 752, 744, 744, 746, + 745, 750, 747, 748, 749, 754, 755, 747, 756, 753, + 758, 759, 766, 760, 755, 761, 751, 751, 752, 758, + 753, 750, 761, 764, 759, 765, 774, 762, 754, 763, + 756, 0, 754, 755, 762, 756, 763, 758, 759, 760, + 760, 769, 761, 771, 767, 768, 0, 765, 764, 773, + 764, 767, 765, 772, 762, 772, 763, 775, 768, 777, + + 776, 0, 769, 779, 782, 771, 781, 777, 769, 776, + 771, 767, 768, 773, 778, 780, 773, 783, 789, 780, + 772, 778, 787, 775, 775, 779, 777, 776, 781, 784, + 779, 782, 789, 781, 790, 787, 785, 788, 784, 783, + 786, 778, 780, 785, 783, 789, 791, 786, 792, 787, + 794, 793, 788, 791, 795, 792, 784, 793, 796, 797, + 800, 796, 794, 785, 788, 790, 801, 786, 802, 807, + 797, 803, 804, 791, 795, 792, 796, 794, 793, 802, + 804, 795, 0, 806, 808, 796, 797, 800, 796, 803, + 801, 805, 810, 801, 805, 802, 809, 819, 803, 804, + + 807, 806, 812, 809, 811, 813, 810, 813, 814, 805, + 806, 808, 815, 811, 816, 812, 821, 814, 805, 810, + 0, 805, 822, 809, 817, 816, 823, 820, 819, 812, + 0, 811, 813, 817, 824, 814, 820, 0, 815, 815, + 825, 816, 829, 822, 828, 831, 825, 821, 824, 822, + 830, 817, 840, 831, 820, 832, 829, 823, 836, 830, + 0, 824, 837, 828, 825, 833, 832, 825, 835, 829, + 840, 828, 831, 825, 833, 835, 838, 830, 839, 840, + 843, 836, 832, 841, 837, 836, 844, 841, 847, 837, + 842, 845, 833, 846, 848, 835, 855, 851, 838, 844, + + 839, 850, 842, 838, 852, 839, 845, 843, 846, 848, + 841, 853, 854, 844, 849, 859, 863, 842, 845, 847, + 846, 848, 850, 849, 851, 857, 856, 855, 850, 853, + 858, 852, 856, 857, 861, 862, 860, 858, 853, 854, + 864, 849, 859, 860, 866, 867, 868, 863, 872, 869, + 0, 869, 857, 856, 867, 870, 0, 858, 871, 877, + 0, 861, 862, 860, 864, 877, 873, 864, 873, 878, + 0, 874, 867, 873, 0, 866, 869, 868, 874, 872, + 875, 873, 870, 876, 871, 871, 877, 875, 879, 879, + 876, 880, 881, 873, 883, 873, 878, 884, 874, 881, + + 873, 888, 885, 887, 887, 886, 893, 875, 896, 884, + 876, 892, 883, 889, 889, 879, 895, 880, 880, 881, + 890, 883, 885, 886, 884, 0, 897, 888, 888, 885, + 887, 890, 886, 892, 894, 896, 895, 893, 892, 898, + 889, 894, 899, 895, 900, 909, 901, 890, 897, 899, + 902, 903, 904, 897, 901, 906, 900, 898, 905, 907, + 910, 894, 902, 905, 911, 907, 898, 908, 911, 899, + 904, 900, 903, 901, 905, 912, 909, 902, 903, 904, + 908, 913, 906, 914, 915, 905, 907, 910, 917, 916, + 905, 918, 919, 918, 908, 911, 913, 920, 921, 915, + + 925, 924, 920, 917, 922, 926, 912, 933, 913, 927, + 0, 915, 916, 928, 914, 917, 916, 929, 918, 922, + 940, 930, 933, 919, 920, 924, 935, 925, 924, 921, + 927, 922, 926, 936, 933, 928, 927, 935, 929, 930, + 928, 937, 936, 938, 929, 943, 944, 940, 930, 946, + 0, 948, 935, 935, 947, 945, 0, 0, 943, 937, + 936, 938, 951, 950, 935, 945, 952, 953, 937, 951, + 938, 954, 943, 953, 0, 946, 946, 944, 948, 947, + 955, 947, 945, 950, 956, 957, 954, 960, 961, 951, + 950, 962, 952, 952, 953, 955, 958, 957, 954, 956, + + 962, 963, 965, 958, 964, 966, 966, 955, 967, 960, + 0, 956, 957, 961, 960, 961, 968, 964, 962, 963, + 969, 973, 970, 958, 971, 0, 974, 972, 963, 965, + 967, 964, 966, 971, 972, 967, 978, 976, 0, 996, + 979, 968, 969, 968, 970, 976, 977, 969, 974, 970, + 982, 971, 973, 974, 972, 979, 981, 980, 984, 977, + 980, 983, 998, 978, 976, 987, 996, 979, 982, 985, + 994, 988, 994, 977, 991, 980, 983, 982, 988, 987, + 984, 981, 989, 981, 980, 984, 993, 980, 983, 998, + 995, 985, 987, 989, 997, 991, 985, 994, 988, 1000, + + 1002, 991, 999, 1001, 1003, 1004, 1064, 993, 995, 989, + 999, 1008, 997, 993, 1002, 1007, 1012, 995, 1009, 1010, + 0, 997, 1000, 0, 1004, 1001, 1000, 1002, 1011, 999, + 1001, 1003, 1004, 1007, 1010, 1013, 1014, 1064, 1008, 1012, + 1015, 1015, 1007, 1012, 1009, 1009, 1010, 1013, 1016, 1018, + 1011, 1019, 1018, 1021, 1020, 1011, 1016, 1024, 1014, 1019, + 1020, 1025, 1013, 1014, 1022, 1026, 1029, 1015, 1021, 1027, + 1022, 1028, 1030, 1031, 1032, 1016, 1018, 1033, 1019, 1026, + 1021, 1020, 1034, 1027, 1024, 1025, 1035, 1031, 1025, 1036, + 1034, 1022, 1026, 1029, 1037, 1039, 1027, 1028, 1028, 1030, + + 1031, 1032, 1037, 1040, 1033, 1042, 1041, 1044, 0, 1034, + 1043, 1045, 0, 1035, 1041, 1047, 1036, 1039, 1048, 1043, + 1049, 1037, 1039, 0, 1046, 1051, 1048, 1053, 1044, 1055, + 1040, 1054, 1042, 1041, 1044, 1045, 0, 1043, 1045, 1046, + 1052, 1052, 1047, 1056, 1055, 1048, 1057, 1049, 1057, 1054, + 1046, 1046, 1051, 1053, 1053, 1058, 1055, 1059, 1054, 1060, + 1061, 1062, 1063, 1059, 0, 1056, 1046, 1052, 1065, 1058, + 1056, 1067, 1061, 1057, 1069, 1071, 1070, 1078, 1067, 1062, + 1063, 1060, 1058, 1077, 1059, 1072, 1060, 1061, 1062, 1063, + 1075, 1065, 1069, 1072, 1079, 1065, 1074, 1088, 1067, 1078, + + 1081, 1069, 1070, 1070, 1078, 1075, 1071, 1077, 1074, 1080, + 1077, 1072, 1072, 1082, 1089, 1083, 1085, 1075, 1084, 1086, + 1072, 1079, 1087, 1074, 1081, 1084, 1086, 1081, 1088, 1092, + 1094, 1108, 1080, 1093, 1100, 1089, 1080, 1083, 1097, 1085, + 1082, 1089, 1083, 1085, 1087, 1084, 1086, 1091, 1103, 1087, + 1104, 1092, 1093, 1106, 1112, 1094, 1092, 1094, 1091, 1109, + 1093, 1100, 1108, 1111, 1097, 1097, 1114, 1110, 1111, 1117, + 1103, 1119, 1118, 1120, 1091, 1103, 1112, 1104, 1110, 1121, + 1106, 1112, 1122, 1123, 1119, 1109, 1109, 1124, 1126, 1127, + 1111, 1117, 1125, 1114, 1110, 1120, 1117, 1118, 1119, 1118, + + 1120, 1125, 1124, 1126, 1127, 1128, 1121, 1130, 1131, 1122, + 1123, 1129, 1132, 1132, 1124, 1126, 1127, 1133, 1129, 1125, + 1128, 1137, 1134, 1138, 1133, 1135, 1131, 1136, 1135, 1139, + 1137, 1140, 1128, 1142, 1130, 1131, 1134, 1143, 1129, 1132, + 1136, 1145, 1142, 1146, 1133, 1138, 1148, 1147, 1137, 1134, + 1138, 1139, 1135, 1149, 1136, 1148, 1139, 1152, 1140, 1147, + 1142, 1146, 1149, 1143, 1143, 1150, 1153, 1151, 1145, 1154, + 1146, 1155, 1163, 1148, 1147, 1151, 1150, 1162, 1156, 1155, + 1149, 1154, 1158, 1164, 1152, 1156, 1161, 1167, 1169, 1170, + 1158, 1165, 1150, 1161, 1151, 1164, 1154, 1153, 1155, 1163, + + 1165, 1162, 1174, 1168, 1162, 1156, 1176, 1175, 1179, 1158, + 1164, 1168, 1175, 1161, 1167, 1169, 1170, 1177, 1165, 1178, + 1181, 1182, 1185, 1183, 1176, 1184, 1186, 1179, 1174, 1174, + 1168, 1187, 1181, 1176, 1175, 1179, 1188, 1184, 1189, 1177, + 1192, 1178, 1191, 1182, 1177, 1183, 1178, 1181, 1182, 1185, + 1183, 1194, 1184, 1186, 1195, 1192, 1196, 1203, 1197, 0, + 1198, 1199, 1187, 1188, 1191, 1189, 1205, 1192, 1195, 1191, + 1212, 1204, 1201, 1206, 1196, 1194, 1197, 1209, 1194, 1199, + 1201, 1195, 1202, 1196, 1203, 1197, 1198, 1198, 1199, 1204, + 1202, 1207, 1206, 1205, 1210, 1209, 1215, 1212, 1204, 1201, + + 1206, 1216, 1217, 1215, 1209, 1218, 1219, 1220, 1210, 1202, + 1222, 1221, 1223, 1207, 0, 1227, 1220, 1224, 1207, 1233, + 0, 1210, 1230, 1215, 1221, 1235, 1217, 1216, 1216, 1217, + 1230, 1231, 1218, 1219, 1220, 1232, 1227, 1234, 1221, 1223, + 1224, 1222, 1227, 1232, 1224, 1233, 1233, 1235, 1234, 1230, + 1231, 1238, 1235, 1236, 1237, 1237, 1239, 1243, 1231, 1244, + 1236, 1241, 1232, 1239, 1234, 0, 1243, 1245, 1250, 1238, + 1250, 1246, 1249, 1248, 1253, 0, 1254, 0, 1238, 1255, + 1236, 1237, 1257, 1239, 1243, 1241, 1244, 1249, 1241, 1246, + 1245, 1248, 1258, 0, 1245, 1250, 1253, 1255, 1246, 1249, + + 1248, 1253, 1254, 1254, 1257, 1259, 1255, 1261, 1260, 1257, + 1258, 1262, 1263, 1259, 1264, 1266, 1269, 1265, 1268, 1258, + 1260, 1272, 1264, 1263, 1267, 1267, 1268, 1270, 1275, 1262, + 1276, 0, 1259, 1273, 1261, 1260, 1265, 1266, 1262, 1263, + 1273, 1264, 1266, 1269, 1265, 1268, 1278, 1274, 1272, 1270, + 1277, 1267, 1274, 1280, 1270, 1275, 1279, 1276, 1277, 1282, + 1273, 1278, 1283, 1279, 1281, 1285, 1286, 1287, 1288, 1289, + 1283, 1291, 1295, 1278, 1274, 1290, 0, 1277, 1285, 1281, + 1280, 1293, 1296, 1279, 1299, 1300, 1282, 1306, 1286, 1283, + 1311, 1281, 1285, 1286, 1287, 1288, 1289, 1290, 1291, 1295, + + 1301, 1303, 1290, 1299, 1296, 1315, 1305, 1293, 1293, 1296, + 1318, 1299, 1300, 1305, 1306, 1307, 1313, 1311, 1316, 1318, + 1319, 1320, 1301, 1303, 1322, 1324, 1326, 1301, 1303, 1327, + 1316, 1332, 1315, 1305, 1334, 0, 1338, 1318, 1307, 1313, + 0, 1326, 1307, 1313, 1335, 1316, 1340, 1319, 1320, 1338, + 1333, 1322, 1324, 1326, 1332, 1327, 1327, 1333, 1332, 1339, + 1337, 1334, 1335, 1338, 0, 0, 0, 1339, 0, 0, + 0, 1335, 1337, 1340, 0, 0, 0, 1333, 0, 0, + 0, 0, 0, 0, 0, 0, 1339, 1337, 1343, 1343, + 1343, 1343, 1343, 1343, 1343, 1344, 1344, 1344, 1344, 1344, + + 1344, 1344, 1345, 1345, 1345, 1345, 1345, 1345, 1345, 1346, + 1346, 1346, 1346, 1346, 1346, 1346, 1347, 1347, 1347, 1347, + 1347, 1347, 1347, 1349, 1349, 0, 1349, 1349, 1349, 1349, + 1350, 1350, 0, 0, 0, 1350, 1350, 1351, 1351, 0, + 0, 1351, 0, 1351, 1352, 0, 0, 0, 0, 0, + 1352, 1353, 1353, 0, 0, 0, 1353, 1353, 1354, 0, + 0, 0, 0, 0, 1354, 1355, 1355, 0, 1355, 1355, + 1355, 1355, 1356, 1356, 0, 1356, 1356, 1356, 1356, 1342, + 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, + 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, + + 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, + 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, + 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, + 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, 1342, + 1342, 1342, 1342, 1342, 1342 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +extern int yy_flex_debug; +int yy_flex_debug = 0; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +static int yy_more_flag = 0; +static int yy_more_len = 0; +#define yymore() ((yy_more_flag) = 1) +#define YY_MORE_ADJ (yy_more_len) +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "util/configlexer.lex" +#line 2 "util/configlexer.lex" +/* + * configlexer.lex - lexical analyzer for unbound config file + * + * Copyright (c) 2001-2006, NLnet Labs. All rights reserved + * + * See LICENSE for the license. + * + */ + +#include +#include +#include + +#include "util/config_file.h" +#include "util/configparser.h" +void ub_c_error(const char *message); + +#if 0 +#define LEXOUT(s) printf s /* used ONLY when debugging */ +#else +#define LEXOUT(s) +#endif + +/** avoid warning in about fwrite return value */ +#define ECHO ub_c_error_msg("syntax error at text: %s", yytext) + +/** A parser variable, this is a statement in the config file which is + * of the form variable: value1 value2 ... nargs is the number of values. */ +#define YDVAR(nargs, var) \ + num_args=(nargs); \ + LEXOUT(("v(%s%d) ", yytext, num_args)); \ + if(num_args > 0) { BEGIN(val); } \ + return (var); + +struct inc_state { + char* filename; + int line; +}; +static struct inc_state parse_stack[MAXINCLUDES]; +static YY_BUFFER_STATE include_stack[MAXINCLUDES]; +static int config_include_stack_ptr = 0; +static int inc_prev = 0; +static int num_args = 0; + +static void config_start_include(const char* filename) +{ + FILE *input; + if(strlen(filename) == 0) { + ub_c_error_msg("empty include file name"); + return; + } + if(config_include_stack_ptr >= MAXINCLUDES) { + ub_c_error_msg("includes nested too deeply, skipped (>%d)", MAXINCLUDES); + return; + } + if(cfg_parser->chroot && strncmp(filename, cfg_parser->chroot, + strlen(cfg_parser->chroot)) == 0) { + filename += strlen(cfg_parser->chroot); + } + input = fopen(filename, "r"); + if(!input) { + ub_c_error_msg("cannot open include file '%s': %s", + filename, strerror(errno)); + return; + } + LEXOUT(("switch_to_include_file(%s) ", filename)); + parse_stack[config_include_stack_ptr].filename = cfg_parser->filename; + parse_stack[config_include_stack_ptr].line = cfg_parser->line; + include_stack[config_include_stack_ptr] = YY_CURRENT_BUFFER; + cfg_parser->filename = strdup(filename); + cfg_parser->line = 1; + yy_switch_to_buffer(yy_create_buffer(input,YY_BUF_SIZE)); + ++config_include_stack_ptr; +} + +static void config_end_include(void) +{ + --config_include_stack_ptr; + free(cfg_parser->filename); + cfg_parser->filename = parse_stack[config_include_stack_ptr].filename; + cfg_parser->line = parse_stack[config_include_stack_ptr].line; + yy_delete_buffer(YY_CURRENT_BUFFER); + yy_switch_to_buffer(include_stack[config_include_stack_ptr]); +} + +#ifndef yy_set_bol /* compat definition, for flex 2.4.6 */ +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer(yyin,YY_BUF_SIZE ); \ + yy_current_buffer->yy_ch_buf[0] = ((at_bol)?'\n':' '); \ + } +#endif + +#define YY_NO_INPUT 1 +#line 100 "util/configlexer.lex" +#ifndef YY_NO_UNPUT +#define YY_NO_UNPUT 1 +#endif +#ifndef YY_NO_INPUT +#define YY_NO_INPUT 1 +#endif + +#line 1871 "" + +#define INITIAL 0 +#define quotedstring 1 +#define singlequotedstr 2 +#define include 3 +#define include_quoted 4 +#define val 5 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +static int yy_init_globals (void ); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int yylex_destroy (void ); + +int yyget_debug (void ); + +void yyset_debug (int debug_flag ); + +YY_EXTRA_TYPE yyget_extra (void ); + +void yyset_extra (YY_EXTRA_TYPE user_defined ); + +FILE *yyget_in (void ); + +void yyset_in (FILE * in_str ); + +FILE *yyget_out (void ); + +void yyset_out (FILE * out_str ); + +int yyget_leng (void ); + +char *yyget_text (void ); + +int yyget_lineno (void ); + +void yyset_lineno (int line_number ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap (void ); +#else +extern int yywrap (void ); +#endif +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ); +#endif + +#ifndef YY_NO_INPUT + +#ifdef __cplusplus +static int yyinput (void ); +#else +static int input (void ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + unsigned n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(yyin); \ + } \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int yylex (void); + +#define YY_DECL int yylex (void) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 120 "util/configlexer.lex" + +#line 2058 "" + + if ( !(yy_init) ) + { + (yy_init) = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! (yy_start) ) + (yy_start) = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer(yyin,YY_BUF_SIZE ); + } + + yy_load_buffer_state( ); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + (yy_more_len) = 0; + if ( (yy_more_flag) ) + { + (yy_more_len) = (yy_c_buf_p) - (yytext_ptr); + (yy_more_flag) = 0; + } + yy_cp = (yy_c_buf_p); + + /* Support of yytext. */ + *yy_cp = (yy_hold_char); + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = (yy_start); +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 1343 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 3880 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = (yy_hold_char); + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 121 "util/configlexer.lex" +{ + LEXOUT(("SP ")); /* ignore */ } + YY_BREAK +case 2: +YY_RULE_SETUP +#line 123 "util/configlexer.lex" +{ + /* note that flex makes the longest match and '.' is any but not nl */ + LEXOUT(("comment(%s) ", yytext)); /* ignore */ } + YY_BREAK +case 3: +YY_RULE_SETUP +#line 126 "util/configlexer.lex" +{ YDVAR(0, VAR_SERVER) } + YY_BREAK +case 4: +YY_RULE_SETUP +#line 127 "util/configlexer.lex" +{ YDVAR(1, VAR_NUM_THREADS) } + YY_BREAK +case 5: +YY_RULE_SETUP +#line 128 "util/configlexer.lex" +{ YDVAR(1, VAR_VERBOSITY) } + YY_BREAK +case 6: +YY_RULE_SETUP +#line 129 "util/configlexer.lex" +{ YDVAR(1, VAR_PORT) } + YY_BREAK +case 7: +YY_RULE_SETUP +#line 130 "util/configlexer.lex" +{ YDVAR(1, VAR_OUTGOING_RANGE) } + YY_BREAK +case 8: +YY_RULE_SETUP +#line 131 "util/configlexer.lex" +{ YDVAR(1, VAR_OUTGOING_PORT_PERMIT) } + YY_BREAK +case 9: +YY_RULE_SETUP +#line 132 "util/configlexer.lex" +{ YDVAR(1, VAR_OUTGOING_PORT_AVOID) } + YY_BREAK +case 10: +YY_RULE_SETUP +#line 133 "util/configlexer.lex" +{ YDVAR(1, VAR_OUTGOING_NUM_TCP) } + YY_BREAK +case 11: +YY_RULE_SETUP +#line 134 "util/configlexer.lex" +{ YDVAR(1, VAR_INCOMING_NUM_TCP) } + YY_BREAK +case 12: +YY_RULE_SETUP +#line 135 "util/configlexer.lex" +{ YDVAR(1, VAR_DO_IP4) } + YY_BREAK +case 13: +YY_RULE_SETUP +#line 136 "util/configlexer.lex" +{ YDVAR(1, VAR_DO_IP6) } + YY_BREAK +case 14: +YY_RULE_SETUP +#line 137 "util/configlexer.lex" +{ YDVAR(1, VAR_DO_UDP) } + YY_BREAK +case 15: +YY_RULE_SETUP +#line 138 "util/configlexer.lex" +{ YDVAR(1, VAR_DO_TCP) } + YY_BREAK +case 16: +YY_RULE_SETUP +#line 139 "util/configlexer.lex" +{ YDVAR(1, VAR_TCP_UPSTREAM) } + YY_BREAK +case 17: +YY_RULE_SETUP +#line 140 "util/configlexer.lex" +{ YDVAR(1, VAR_SSL_UPSTREAM) } + YY_BREAK +case 18: +YY_RULE_SETUP +#line 141 "util/configlexer.lex" +{ YDVAR(1, VAR_SSL_SERVICE_KEY) } + YY_BREAK +case 19: +YY_RULE_SETUP +#line 142 "util/configlexer.lex" +{ YDVAR(1, VAR_SSL_SERVICE_PEM) } + YY_BREAK +case 20: +YY_RULE_SETUP +#line 143 "util/configlexer.lex" +{ YDVAR(1, VAR_SSL_PORT) } + YY_BREAK +case 21: +YY_RULE_SETUP +#line 144 "util/configlexer.lex" +{ YDVAR(1, VAR_DO_DAEMONIZE) } + YY_BREAK +case 22: +YY_RULE_SETUP +#line 145 "util/configlexer.lex" +{ YDVAR(1, VAR_INTERFACE) } + YY_BREAK +case 23: +YY_RULE_SETUP +#line 146 "util/configlexer.lex" +{ YDVAR(1, VAR_OUTGOING_INTERFACE) } + YY_BREAK +case 24: +YY_RULE_SETUP +#line 147 "util/configlexer.lex" +{ YDVAR(1, VAR_INTERFACE_AUTOMATIC) } + YY_BREAK +case 25: +YY_RULE_SETUP +#line 148 "util/configlexer.lex" +{ YDVAR(1, VAR_SO_RCVBUF) } + YY_BREAK +case 26: +YY_RULE_SETUP +#line 149 "util/configlexer.lex" +{ YDVAR(1, VAR_SO_SNDBUF) } + YY_BREAK +case 27: +YY_RULE_SETUP +#line 150 "util/configlexer.lex" +{ YDVAR(1, VAR_CHROOT) } + YY_BREAK +case 28: +YY_RULE_SETUP +#line 151 "util/configlexer.lex" +{ YDVAR(1, VAR_USERNAME) } + YY_BREAK +case 29: +YY_RULE_SETUP +#line 152 "util/configlexer.lex" +{ YDVAR(1, VAR_DIRECTORY) } + YY_BREAK +case 30: +YY_RULE_SETUP +#line 153 "util/configlexer.lex" +{ YDVAR(1, VAR_LOGFILE) } + YY_BREAK +case 31: +YY_RULE_SETUP +#line 154 "util/configlexer.lex" +{ YDVAR(1, VAR_PIDFILE) } + YY_BREAK +case 32: +YY_RULE_SETUP +#line 155 "util/configlexer.lex" +{ YDVAR(1, VAR_ROOT_HINTS) } + YY_BREAK +case 33: +YY_RULE_SETUP +#line 156 "util/configlexer.lex" +{ YDVAR(1, VAR_EDNS_BUFFER_SIZE) } + YY_BREAK +case 34: +YY_RULE_SETUP +#line 157 "util/configlexer.lex" +{ YDVAR(1, VAR_MSG_BUFFER_SIZE) } + YY_BREAK +case 35: +YY_RULE_SETUP +#line 158 "util/configlexer.lex" +{ YDVAR(1, VAR_MSG_CACHE_SIZE) } + YY_BREAK +case 36: +YY_RULE_SETUP +#line 159 "util/configlexer.lex" +{ YDVAR(1, VAR_MSG_CACHE_SLABS) } + YY_BREAK +case 37: +YY_RULE_SETUP +#line 160 "util/configlexer.lex" +{ YDVAR(1, VAR_RRSET_CACHE_SIZE) } + YY_BREAK +case 38: +YY_RULE_SETUP +#line 161 "util/configlexer.lex" +{ YDVAR(1, VAR_RRSET_CACHE_SLABS) } + YY_BREAK +case 39: +YY_RULE_SETUP +#line 162 "util/configlexer.lex" +{ YDVAR(1, VAR_CACHE_MAX_TTL) } + YY_BREAK +case 40: +YY_RULE_SETUP +#line 163 "util/configlexer.lex" +{ YDVAR(1, VAR_CACHE_MIN_TTL) } + YY_BREAK +case 41: +YY_RULE_SETUP +#line 164 "util/configlexer.lex" +{ YDVAR(1, VAR_INFRA_HOST_TTL) } + YY_BREAK +case 42: +YY_RULE_SETUP +#line 165 "util/configlexer.lex" +{ YDVAR(1, VAR_INFRA_LAME_TTL) } + YY_BREAK +case 43: +YY_RULE_SETUP +#line 166 "util/configlexer.lex" +{ YDVAR(1, VAR_INFRA_CACHE_SLABS) } + YY_BREAK +case 44: +YY_RULE_SETUP +#line 167 "util/configlexer.lex" +{ YDVAR(1, VAR_INFRA_CACHE_NUMHOSTS) } + YY_BREAK +case 45: +YY_RULE_SETUP +#line 168 "util/configlexer.lex" +{ YDVAR(1, VAR_INFRA_CACHE_LAME_SIZE) } + YY_BREAK +case 46: +YY_RULE_SETUP +#line 169 "util/configlexer.lex" +{ YDVAR(1, VAR_NUM_QUERIES_PER_THREAD) } + YY_BREAK +case 47: +YY_RULE_SETUP +#line 170 "util/configlexer.lex" +{ YDVAR(1, VAR_JOSTLE_TIMEOUT) } + YY_BREAK +case 48: +YY_RULE_SETUP +#line 171 "util/configlexer.lex" +{ YDVAR(1, VAR_TARGET_FETCH_POLICY) } + YY_BREAK +case 49: +YY_RULE_SETUP +#line 172 "util/configlexer.lex" +{ YDVAR(1, VAR_HARDEN_SHORT_BUFSIZE) } + YY_BREAK +case 50: +YY_RULE_SETUP +#line 173 "util/configlexer.lex" +{ YDVAR(1, VAR_HARDEN_LARGE_QUERIES) } + YY_BREAK +case 51: +YY_RULE_SETUP +#line 174 "util/configlexer.lex" +{ YDVAR(1, VAR_HARDEN_GLUE) } + YY_BREAK +case 52: +YY_RULE_SETUP +#line 175 "util/configlexer.lex" +{ YDVAR(1, VAR_HARDEN_DNSSEC_STRIPPED) } + YY_BREAK +case 53: +YY_RULE_SETUP +#line 176 "util/configlexer.lex" +{ YDVAR(1, VAR_HARDEN_BELOW_NXDOMAIN) } + YY_BREAK +case 54: +YY_RULE_SETUP +#line 177 "util/configlexer.lex" +{ YDVAR(1, VAR_HARDEN_REFERRAL_PATH) } + YY_BREAK +case 55: +YY_RULE_SETUP +#line 178 "util/configlexer.lex" +{ YDVAR(1, VAR_USE_CAPS_FOR_ID) } + YY_BREAK +case 56: +YY_RULE_SETUP +#line 179 "util/configlexer.lex" +{ YDVAR(1, VAR_UNWANTED_REPLY_THRESHOLD) } + YY_BREAK +case 57: +YY_RULE_SETUP +#line 180 "util/configlexer.lex" +{ YDVAR(1, VAR_PRIVATE_ADDRESS) } + YY_BREAK +case 58: +YY_RULE_SETUP +#line 181 "util/configlexer.lex" +{ YDVAR(1, VAR_PRIVATE_DOMAIN) } + YY_BREAK +case 59: +YY_RULE_SETUP +#line 182 "util/configlexer.lex" +{ YDVAR(1, VAR_PREFETCH_KEY) } + YY_BREAK +case 60: +YY_RULE_SETUP +#line 183 "util/configlexer.lex" +{ YDVAR(1, VAR_PREFETCH) } + YY_BREAK +case 61: +YY_RULE_SETUP +#line 184 "util/configlexer.lex" +{ YDVAR(0, VAR_STUB_ZONE) } + YY_BREAK +case 62: +YY_RULE_SETUP +#line 185 "util/configlexer.lex" +{ YDVAR(1, VAR_NAME) } + YY_BREAK +case 63: +YY_RULE_SETUP +#line 186 "util/configlexer.lex" +{ YDVAR(1, VAR_STUB_ADDR) } + YY_BREAK +case 64: +YY_RULE_SETUP +#line 187 "util/configlexer.lex" +{ YDVAR(1, VAR_STUB_HOST) } + YY_BREAK +case 65: +YY_RULE_SETUP +#line 188 "util/configlexer.lex" +{ YDVAR(1, VAR_STUB_PRIME) } + YY_BREAK +case 66: +YY_RULE_SETUP +#line 189 "util/configlexer.lex" +{ YDVAR(1, VAR_STUB_FIRST) } + YY_BREAK +case 67: +YY_RULE_SETUP +#line 190 "util/configlexer.lex" +{ YDVAR(0, VAR_FORWARD_ZONE) } + YY_BREAK +case 68: +YY_RULE_SETUP +#line 191 "util/configlexer.lex" +{ YDVAR(1, VAR_FORWARD_ADDR) } + YY_BREAK +case 69: +YY_RULE_SETUP +#line 192 "util/configlexer.lex" +{ YDVAR(1, VAR_FORWARD_HOST) } + YY_BREAK +case 70: +YY_RULE_SETUP +#line 193 "util/configlexer.lex" +{ YDVAR(1, VAR_FORWARD_FIRST) } + YY_BREAK +case 71: +YY_RULE_SETUP +#line 194 "util/configlexer.lex" +{ YDVAR(1, VAR_DO_NOT_QUERY_ADDRESS) } + YY_BREAK +case 72: +YY_RULE_SETUP +#line 195 "util/configlexer.lex" +{ YDVAR(1, VAR_DO_NOT_QUERY_LOCALHOST) } + YY_BREAK +case 73: +YY_RULE_SETUP +#line 196 "util/configlexer.lex" +{ YDVAR(2, VAR_ACCESS_CONTROL) } + YY_BREAK +case 74: +YY_RULE_SETUP +#line 197 "util/configlexer.lex" +{ YDVAR(1, VAR_HIDE_IDENTITY) } + YY_BREAK +case 75: +YY_RULE_SETUP +#line 198 "util/configlexer.lex" +{ YDVAR(1, VAR_HIDE_VERSION) } + YY_BREAK +case 76: +YY_RULE_SETUP +#line 199 "util/configlexer.lex" +{ YDVAR(1, VAR_IDENTITY) } + YY_BREAK +case 77: +YY_RULE_SETUP +#line 200 "util/configlexer.lex" +{ YDVAR(1, VAR_VERSION) } + YY_BREAK +case 78: +YY_RULE_SETUP +#line 201 "util/configlexer.lex" +{ YDVAR(1, VAR_MODULE_CONF) } + YY_BREAK +case 79: +YY_RULE_SETUP +#line 202 "util/configlexer.lex" +{ YDVAR(1, VAR_DLV_ANCHOR) } + YY_BREAK +case 80: +YY_RULE_SETUP +#line 203 "util/configlexer.lex" +{ YDVAR(1, VAR_DLV_ANCHOR_FILE) } + YY_BREAK +case 81: +YY_RULE_SETUP +#line 204 "util/configlexer.lex" +{ YDVAR(1, VAR_TRUST_ANCHOR_FILE) } + YY_BREAK +case 82: +YY_RULE_SETUP +#line 205 "util/configlexer.lex" +{ YDVAR(1, VAR_AUTO_TRUST_ANCHOR_FILE) } + YY_BREAK +case 83: +YY_RULE_SETUP +#line 206 "util/configlexer.lex" +{ YDVAR(1, VAR_TRUSTED_KEYS_FILE) } + YY_BREAK +case 84: +YY_RULE_SETUP +#line 207 "util/configlexer.lex" +{ YDVAR(1, VAR_TRUST_ANCHOR) } + YY_BREAK +case 85: +YY_RULE_SETUP +#line 208 "util/configlexer.lex" +{ YDVAR(1, VAR_VAL_OVERRIDE_DATE) } + YY_BREAK +case 86: +YY_RULE_SETUP +#line 209 "util/configlexer.lex" +{ YDVAR(1, VAR_VAL_SIG_SKEW_MIN) } + YY_BREAK +case 87: +YY_RULE_SETUP +#line 210 "util/configlexer.lex" +{ YDVAR(1, VAR_VAL_SIG_SKEW_MAX) } + YY_BREAK +case 88: +YY_RULE_SETUP +#line 211 "util/configlexer.lex" +{ YDVAR(1, VAR_BOGUS_TTL) } + YY_BREAK +case 89: +YY_RULE_SETUP +#line 212 "util/configlexer.lex" +{ YDVAR(1, VAR_VAL_CLEAN_ADDITIONAL) } + YY_BREAK +case 90: +YY_RULE_SETUP +#line 213 "util/configlexer.lex" +{ YDVAR(1, VAR_VAL_PERMISSIVE_MODE) } + YY_BREAK +case 91: +YY_RULE_SETUP +#line 214 "util/configlexer.lex" +{ YDVAR(1, VAR_IGNORE_CD_FLAG) } + YY_BREAK +case 92: +YY_RULE_SETUP +#line 215 "util/configlexer.lex" +{ YDVAR(1, VAR_VAL_LOG_LEVEL) } + YY_BREAK +case 93: +YY_RULE_SETUP +#line 216 "util/configlexer.lex" +{ YDVAR(1, VAR_KEY_CACHE_SIZE) } + YY_BREAK +case 94: +YY_RULE_SETUP +#line 217 "util/configlexer.lex" +{ YDVAR(1, VAR_KEY_CACHE_SLABS) } + YY_BREAK +case 95: +YY_RULE_SETUP +#line 218 "util/configlexer.lex" +{ YDVAR(1, VAR_NEG_CACHE_SIZE) } + YY_BREAK +case 96: +YY_RULE_SETUP +#line 219 "util/configlexer.lex" +{ + YDVAR(1, VAR_VAL_NSEC3_KEYSIZE_ITERATIONS) } + YY_BREAK +case 97: +YY_RULE_SETUP +#line 221 "util/configlexer.lex" +{ YDVAR(1, VAR_ADD_HOLDDOWN) } + YY_BREAK +case 98: +YY_RULE_SETUP +#line 222 "util/configlexer.lex" +{ YDVAR(1, VAR_DEL_HOLDDOWN) } + YY_BREAK +case 99: +YY_RULE_SETUP +#line 223 "util/configlexer.lex" +{ YDVAR(1, VAR_KEEP_MISSING) } + YY_BREAK +case 100: +YY_RULE_SETUP +#line 224 "util/configlexer.lex" +{ YDVAR(1, VAR_USE_SYSLOG) } + YY_BREAK +case 101: +YY_RULE_SETUP +#line 225 "util/configlexer.lex" +{ YDVAR(1, VAR_LOG_TIME_ASCII) } + YY_BREAK +case 102: +YY_RULE_SETUP +#line 226 "util/configlexer.lex" +{ YDVAR(1, VAR_LOG_QUERIES) } + YY_BREAK +case 103: +YY_RULE_SETUP +#line 227 "util/configlexer.lex" +{ YDVAR(2, VAR_LOCAL_ZONE) } + YY_BREAK +case 104: +YY_RULE_SETUP +#line 228 "util/configlexer.lex" +{ YDVAR(1, VAR_LOCAL_DATA) } + YY_BREAK +case 105: +YY_RULE_SETUP +#line 229 "util/configlexer.lex" +{ YDVAR(1, VAR_LOCAL_DATA_PTR) } + YY_BREAK +case 106: +YY_RULE_SETUP +#line 230 "util/configlexer.lex" +{ YDVAR(1, VAR_STATISTICS_INTERVAL) } + YY_BREAK +case 107: +YY_RULE_SETUP +#line 231 "util/configlexer.lex" +{ YDVAR(1, VAR_STATISTICS_CUMULATIVE) } + YY_BREAK +case 108: +YY_RULE_SETUP +#line 232 "util/configlexer.lex" +{ YDVAR(1, VAR_EXTENDED_STATISTICS) } + YY_BREAK +case 109: +YY_RULE_SETUP +#line 233 "util/configlexer.lex" +{ YDVAR(0, VAR_REMOTE_CONTROL) } + YY_BREAK +case 110: +YY_RULE_SETUP +#line 234 "util/configlexer.lex" +{ YDVAR(1, VAR_CONTROL_ENABLE) } + YY_BREAK +case 111: +YY_RULE_SETUP +#line 235 "util/configlexer.lex" +{ YDVAR(1, VAR_CONTROL_INTERFACE) } + YY_BREAK +case 112: +YY_RULE_SETUP +#line 236 "util/configlexer.lex" +{ YDVAR(1, VAR_CONTROL_PORT) } + YY_BREAK +case 113: +YY_RULE_SETUP +#line 237 "util/configlexer.lex" +{ YDVAR(1, VAR_SERVER_KEY_FILE) } + YY_BREAK +case 114: +YY_RULE_SETUP +#line 238 "util/configlexer.lex" +{ YDVAR(1, VAR_SERVER_CERT_FILE) } + YY_BREAK +case 115: +YY_RULE_SETUP +#line 239 "util/configlexer.lex" +{ YDVAR(1, VAR_CONTROL_KEY_FILE) } + YY_BREAK +case 116: +YY_RULE_SETUP +#line 240 "util/configlexer.lex" +{ YDVAR(1, VAR_CONTROL_CERT_FILE) } + YY_BREAK +case 117: +YY_RULE_SETUP +#line 241 "util/configlexer.lex" +{ YDVAR(1, VAR_PYTHON_SCRIPT) } + YY_BREAK +case 118: +YY_RULE_SETUP +#line 242 "util/configlexer.lex" +{ YDVAR(0, VAR_PYTHON) } + YY_BREAK +case 119: +YY_RULE_SETUP +#line 243 "util/configlexer.lex" +{ YDVAR(1, VAR_DOMAIN_INSECURE) } + YY_BREAK +case 120: +YY_RULE_SETUP +#line 244 "util/configlexer.lex" +{ YDVAR(1, VAR_MINIMAL_RESPONSES) } + YY_BREAK +case 121: +YY_RULE_SETUP +#line 245 "util/configlexer.lex" +{ YDVAR(1, VAR_RRSET_ROUNDROBIN) } + YY_BREAK +case 122: +/* rule 122 can match eol */ +YY_RULE_SETUP +#line 246 "util/configlexer.lex" +{ LEXOUT(("NL\n")); cfg_parser->line++; } + YY_BREAK +/* Quoted strings. Strip leading and ending quotes */ +case 123: +YY_RULE_SETUP +#line 249 "util/configlexer.lex" +{ BEGIN(quotedstring); LEXOUT(("QS ")); } + YY_BREAK +case YY_STATE_EOF(quotedstring): +#line 250 "util/configlexer.lex" +{ + yyerror("EOF inside quoted string"); + if(--num_args == 0) { BEGIN(INITIAL); } + else { BEGIN(val); } +} + YY_BREAK +case 124: +YY_RULE_SETUP +#line 255 "util/configlexer.lex" +{ LEXOUT(("STR(%s) ", yytext)); yymore(); } + YY_BREAK +case 125: +/* rule 125 can match eol */ +YY_RULE_SETUP +#line 256 "util/configlexer.lex" +{ yyerror("newline inside quoted string, no end \""); + cfg_parser->line++; BEGIN(INITIAL); } + YY_BREAK +case 126: +YY_RULE_SETUP +#line 258 "util/configlexer.lex" +{ + LEXOUT(("QE ")); + if(--num_args == 0) { BEGIN(INITIAL); } + else { BEGIN(val); } + yytext[yyleng - 1] = '\0'; + yylval.str = strdup(yytext); + if(!yylval.str) + yyerror("out of memory"); + return STRING_ARG; +} + YY_BREAK +/* Single Quoted strings. Strip leading and ending quotes */ +case 127: +YY_RULE_SETUP +#line 270 "util/configlexer.lex" +{ BEGIN(singlequotedstr); LEXOUT(("SQS ")); } + YY_BREAK +case YY_STATE_EOF(singlequotedstr): +#line 271 "util/configlexer.lex" +{ + yyerror("EOF inside quoted string"); + if(--num_args == 0) { BEGIN(INITIAL); } + else { BEGIN(val); } +} + YY_BREAK +case 128: +YY_RULE_SETUP +#line 276 "util/configlexer.lex" +{ LEXOUT(("STR(%s) ", yytext)); yymore(); } + YY_BREAK +case 129: +/* rule 129 can match eol */ +YY_RULE_SETUP +#line 277 "util/configlexer.lex" +{ yyerror("newline inside quoted string, no end '"); + cfg_parser->line++; BEGIN(INITIAL); } + YY_BREAK +case 130: +YY_RULE_SETUP +#line 279 "util/configlexer.lex" +{ + LEXOUT(("SQE ")); + if(--num_args == 0) { BEGIN(INITIAL); } + else { BEGIN(val); } + yytext[yyleng - 1] = '\0'; + yylval.str = strdup(yytext); + if(!yylval.str) + yyerror("out of memory"); + return STRING_ARG; +} + YY_BREAK +/* include: directive */ +case 131: +YY_RULE_SETUP +#line 291 "util/configlexer.lex" +{ + LEXOUT(("v(%s) ", yytext)); inc_prev = YYSTATE; BEGIN(include); } + YY_BREAK +case YY_STATE_EOF(include): +#line 293 "util/configlexer.lex" +{ + yyerror("EOF inside include directive"); + BEGIN(inc_prev); +} + YY_BREAK +case 132: +YY_RULE_SETUP +#line 297 "util/configlexer.lex" +{ LEXOUT(("ISP ")); /* ignore */ } + YY_BREAK +case 133: +/* rule 133 can match eol */ +YY_RULE_SETUP +#line 298 "util/configlexer.lex" +{ LEXOUT(("NL\n")); cfg_parser->line++;} + YY_BREAK +case 134: +YY_RULE_SETUP +#line 299 "util/configlexer.lex" +{ LEXOUT(("IQS ")); BEGIN(include_quoted); } + YY_BREAK +case 135: +YY_RULE_SETUP +#line 300 "util/configlexer.lex" +{ + LEXOUT(("Iunquotedstr(%s) ", yytext)); + config_start_include(yytext); + BEGIN(inc_prev); +} + YY_BREAK +case YY_STATE_EOF(include_quoted): +#line 305 "util/configlexer.lex" +{ + yyerror("EOF inside quoted string"); + BEGIN(inc_prev); +} + YY_BREAK +case 136: +YY_RULE_SETUP +#line 309 "util/configlexer.lex" +{ LEXOUT(("ISTR(%s) ", yytext)); yymore(); } + YY_BREAK +case 137: +/* rule 137 can match eol */ +YY_RULE_SETUP +#line 310 "util/configlexer.lex" +{ yyerror("newline before \" in include name"); + cfg_parser->line++; BEGIN(inc_prev); } + YY_BREAK +case 138: +YY_RULE_SETUP +#line 312 "util/configlexer.lex" +{ + LEXOUT(("IQE ")); + yytext[yyleng - 1] = '\0'; + config_start_include(yytext); + BEGIN(inc_prev); +} + YY_BREAK +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(val): +#line 318 "util/configlexer.lex" +{ + yy_set_bol(1); /* Set beginning of line, so "^" rules match. */ + if (config_include_stack_ptr == 0) { + yyterminate(); + } else { + fclose(yyin); + config_end_include(); + } +} + YY_BREAK +case 139: +YY_RULE_SETUP +#line 328 "util/configlexer.lex" +{ LEXOUT(("unquotedstr(%s) ", yytext)); + if(--num_args == 0) { BEGIN(INITIAL); } + yylval.str = strdup(yytext); return STRING_ARG; } + YY_BREAK +case 140: +YY_RULE_SETUP +#line 332 "util/configlexer.lex" +{ + ub_c_error_msg("unknown keyword '%s'", yytext); + } + YY_BREAK +case 141: +YY_RULE_SETUP +#line 336 "util/configlexer.lex" +{ + ub_c_error_msg("stray '%s'", yytext); + } + YY_BREAK +case 142: +YY_RULE_SETUP +#line 340 "util/configlexer.lex" +ECHO; + YY_BREAK +#line 2949 "" + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = (yy_hold_char); + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++(yy_c_buf_p); + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = (yy_c_buf_p); + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_END_OF_FILE: + { + (yy_did_buffer_switch_on_eof) = 0; + + if ( yywrap( ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = + (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + (yy_c_buf_p) = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ +} /* end of yylex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (void) +{ + register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + register char *source = (yytext_ptr); + register int number_to_move, i; + int ret_val; + + if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; + + else + { + int num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER; + + int yy_c_buf_p_offset = + (int) ((yy_c_buf_p) - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + (yy_n_chars), (size_t) num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + if ( (yy_n_chars) == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart(yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + } + + (yy_n_chars) += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + + (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (void) +{ + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = (yy_start); + + for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 1343 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) +{ + register int yy_is_jam; + register char *yy_cp = (yy_c_buf_p); + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 1343 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 1342); + + return yy_is_jam ? 0 : yy_current_state; +} + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (void) +#else + static int input (void) +#endif + +{ + int c; + + *(yy_c_buf_p) = (yy_hold_char); + + if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + /* This was really a NUL. */ + *(yy_c_buf_p) = '\0'; + + else + { /* need more input */ + int offset = (yy_c_buf_p) - (yytext_ptr); + ++(yy_c_buf_p); + + switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart(yyin ); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap( ) ) + return EOF; + + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = (yytext_ptr) + offset; + break; + } + } + } + + c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ + *(yy_c_buf_p) = '\0'; /* preserve yytext */ + (yy_hold_char) = *++(yy_c_buf_p); + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * + * @note This function does not reset the start condition to @c INITIAL . + */ + void yyrestart (FILE * input_file ) +{ + + if ( ! YY_CURRENT_BUFFER ){ + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer(yyin,YY_BUF_SIZE ); + } + + yy_init_buffer(YY_CURRENT_BUFFER,input_file ); + yy_load_buffer_state( ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * + */ + void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) +{ + + /* TODO. We should be able to replace this entire function body + * with + * yypop_buffer_state(); + * yypush_buffer_state(new_buffer); + */ + yyensure_buffer_stack (); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + yy_load_buffer_state( ); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + (yy_did_buffer_switch_on_eof) = 1; +} + +static void yy_load_buffer_state (void) +{ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + (yy_hold_char) = *(yy_c_buf_p); +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * + * @return the allocated buffer state. + */ + YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer(b,file ); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with yy_create_buffer() + * + */ + void yy_delete_buffer (YY_BUFFER_STATE b ) +{ + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yyfree((void *) b->yy_ch_buf ); + + yyfree((void *) b ); +} + +#ifndef __cplusplus +extern int isatty (int ); +#endif /* __cplusplus */ + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a yyrestart() or at EOF. + */ + static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) + +{ + int oerrno = errno; + + yy_flush_buffer(b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then yy_init_buffer was _probably_ + * called from yyrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * + */ + void yy_flush_buffer (YY_BUFFER_STATE b ) +{ + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + yy_load_buffer_state( ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * + */ +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) +{ + if (new_buffer == NULL) + return; + + yyensure_buffer_stack(); + + /* This block is copied from yy_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + (yy_buffer_stack_top)++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from yy_switch_to_buffer. */ + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * + */ +void yypop_buffer_state (void) +{ + if (!YY_CURRENT_BUFFER) + return; + + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + if ((yy_buffer_stack_top) > 0) + --(yy_buffer_stack_top); + + if (YY_CURRENT_BUFFER) { + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void yyensure_buffer_stack (void) +{ + int num_to_alloc; + + if (!(yy_buffer_stack)) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; + (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + (yy_buffer_stack_max) = num_to_alloc; + (yy_buffer_stack_top) = 0; + return; + } + + if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + int grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = (yy_buffer_stack_max) + grow_size; + (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc + ((yy_buffer_stack), + num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); + (yy_buffer_stack_max) = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer(b ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to yylex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * yy_scan_bytes() instead. + */ +YY_BUFFER_STATE yy_scan_string (yyconst char * yystr ) +{ + + return yy_scan_bytes(yystr,strlen(yystr) ); +} + +/** Setup the input buffer state to scan the given bytes. The next call to yylex() will + * scan from a @e copy of @a bytes. + * @param bytes the byte buffer to scan + * @param len the number of bytes in the buffer pointed to by @a bytes. + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len ) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; + buf = (char *) yyalloc(n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer(buf,n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yy_fatal_error (yyconst char* msg ) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + yytext[yyleng] = (yy_hold_char); \ + (yy_c_buf_p) = yytext + yyless_macro_arg; \ + (yy_hold_char) = *(yy_c_buf_p); \ + *(yy_c_buf_p) = '\0'; \ + yyleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the current line number. + * + */ +int yyget_lineno (void) +{ + + return yylineno; +} + +/** Get the input stream. + * + */ +FILE *yyget_in (void) +{ + return yyin; +} + +/** Get the output stream. + * + */ +FILE *yyget_out (void) +{ + return yyout; +} + +/** Get the length of the current token. + * + */ +int yyget_leng (void) +{ + return yyleng; +} + +/** Get the current token. + * + */ + +char *yyget_text (void) +{ + return yytext; +} + +/** Set the current line number. + * @param line_number + * + */ +void yyset_lineno (int line_number ) +{ + + yylineno = line_number; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param in_str A readable stream. + * + * @see yy_switch_to_buffer + */ +void yyset_in (FILE * in_str ) +{ + yyin = in_str ; +} + +void yyset_out (FILE * out_str ) +{ + yyout = out_str ; +} + +int yyget_debug (void) +{ + return yy_flex_debug; +} + +void yyset_debug (int bdebug ) +{ + yy_flex_debug = bdebug ; +} + +static int yy_init_globals (void) +{ + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from yylex_destroy(), so don't allocate here. + */ + + (yy_buffer_stack) = 0; + (yy_buffer_stack_top) = 0; + (yy_buffer_stack_max) = 0; + (yy_c_buf_p) = (char *) 0; + (yy_init) = 0; + (yy_start) = 0; + +/* Defined in main.c */ +#ifdef YY_STDINIT + yyin = stdin; + yyout = stdout; +#else + yyin = (FILE *) 0; + yyout = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * yylex_init() + */ + return 0; +} + +/* yylex_destroy is for both reentrant and non-reentrant scanners. */ +int yylex_destroy (void) +{ + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + yypop_buffer_state(); + } + + /* Destroy the stack itself. */ + yyfree((yy_buffer_stack) ); + (yy_buffer_stack) = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * yylex() is called, initialization will occur. */ + yy_init_globals( ); + + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) +{ + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s ) +{ + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *yyalloc (yy_size_t size ) +{ + return (void *) malloc( size ); +} + +void *yyrealloc (void * ptr, yy_size_t size ) +{ + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); +} + +void yyfree (void * ptr ) +{ + free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +#line 340 "util/configlexer.lex" + + + diff --git a/util/configlexer.lex b/util/configlexer.lex new file mode 100644 index 00000000000..ed808aafc39 --- /dev/null +++ b/util/configlexer.lex @@ -0,0 +1,340 @@ +%{ +/* + * configlexer.lex - lexical analyzer for unbound config file + * + * Copyright (c) 2001-2006, NLnet Labs. All rights reserved + * + * See LICENSE for the license. + * + */ + +#include +#include +#include + +#include "util/config_file.h" +#include "util/configparser.h" +void ub_c_error(const char *message); + +#if 0 +#define LEXOUT(s) printf s /* used ONLY when debugging */ +#else +#define LEXOUT(s) +#endif + +/** avoid warning in about fwrite return value */ +#define ECHO ub_c_error_msg("syntax error at text: %s", yytext) + +/** A parser variable, this is a statement in the config file which is + * of the form variable: value1 value2 ... nargs is the number of values. */ +#define YDVAR(nargs, var) \ + num_args=(nargs); \ + LEXOUT(("v(%s%d) ", yytext, num_args)); \ + if(num_args > 0) { BEGIN(val); } \ + return (var); + +struct inc_state { + char* filename; + int line; +}; +static struct inc_state parse_stack[MAXINCLUDES]; +static YY_BUFFER_STATE include_stack[MAXINCLUDES]; +static int config_include_stack_ptr = 0; +static int inc_prev = 0; +static int num_args = 0; + +static void config_start_include(const char* filename) +{ + FILE *input; + if(strlen(filename) == 0) { + ub_c_error_msg("empty include file name"); + return; + } + if(config_include_stack_ptr >= MAXINCLUDES) { + ub_c_error_msg("includes nested too deeply, skipped (>%d)", MAXINCLUDES); + return; + } + if(cfg_parser->chroot && strncmp(filename, cfg_parser->chroot, + strlen(cfg_parser->chroot)) == 0) { + filename += strlen(cfg_parser->chroot); + } + input = fopen(filename, "r"); + if(!input) { + ub_c_error_msg("cannot open include file '%s': %s", + filename, strerror(errno)); + return; + } + LEXOUT(("switch_to_include_file(%s) ", filename)); + parse_stack[config_include_stack_ptr].filename = cfg_parser->filename; + parse_stack[config_include_stack_ptr].line = cfg_parser->line; + include_stack[config_include_stack_ptr] = YY_CURRENT_BUFFER; + cfg_parser->filename = strdup(filename); + cfg_parser->line = 1; + yy_switch_to_buffer(yy_create_buffer(input, YY_BUF_SIZE)); + ++config_include_stack_ptr; +} + +static void config_end_include(void) +{ + --config_include_stack_ptr; + free(cfg_parser->filename); + cfg_parser->filename = parse_stack[config_include_stack_ptr].filename; + cfg_parser->line = parse_stack[config_include_stack_ptr].line; + yy_delete_buffer(YY_CURRENT_BUFFER); + yy_switch_to_buffer(include_stack[config_include_stack_ptr]); +} + +#ifndef yy_set_bol /* compat definition, for flex 2.4.6 */ +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_ch_buf[0] = ((at_bol)?'\n':' '); \ + } +#endif + +%} +%option noinput +%option nounput +%{ +#ifndef YY_NO_UNPUT +#define YY_NO_UNPUT 1 +#endif +#ifndef YY_NO_INPUT +#define YY_NO_INPUT 1 +#endif +%} + +SPACE [ \t] +LETTER [a-zA-Z] +UNQUOTEDLETTER [^\'\"\n\r \t\\]|\\. +UNQUOTEDLETTER_NOCOLON [^\:\'\"\n\r \t\\]|\\. +NEWLINE [\r\n] +COMMENT \# +COLON \: +DQANY [^\"\n\r\\]|\\. +SQANY [^\'\n\r\\]|\\. + +%x quotedstring singlequotedstr include include_quoted val + +%% +{SPACE}* { + LEXOUT(("SP ")); /* ignore */ } +{SPACE}*{COMMENT}.* { + /* note that flex makes the longest match and '.' is any but not nl */ + LEXOUT(("comment(%s) ", yytext)); /* ignore */ } +server{COLON} { YDVAR(0, VAR_SERVER) } +num-threads{COLON} { YDVAR(1, VAR_NUM_THREADS) } +verbosity{COLON} { YDVAR(1, VAR_VERBOSITY) } +port{COLON} { YDVAR(1, VAR_PORT) } +outgoing-range{COLON} { YDVAR(1, VAR_OUTGOING_RANGE) } +outgoing-port-permit{COLON} { YDVAR(1, VAR_OUTGOING_PORT_PERMIT) } +outgoing-port-avoid{COLON} { YDVAR(1, VAR_OUTGOING_PORT_AVOID) } +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) } +do-udp{COLON} { YDVAR(1, VAR_DO_UDP) } +do-tcp{COLON} { YDVAR(1, VAR_DO_TCP) } +tcp-upstream{COLON} { YDVAR(1, VAR_TCP_UPSTREAM) } +ssl-upstream{COLON} { YDVAR(1, VAR_SSL_UPSTREAM) } +ssl-service-key{COLON} { YDVAR(1, VAR_SSL_SERVICE_KEY) } +ssl-service-pem{COLON} { YDVAR(1, VAR_SSL_SERVICE_PEM) } +ssl-port{COLON} { YDVAR(1, VAR_SSL_PORT) } +do-daemonize{COLON} { YDVAR(1, VAR_DO_DAEMONIZE) } +interface{COLON} { YDVAR(1, VAR_INTERFACE) } +outgoing-interface{COLON} { YDVAR(1, VAR_OUTGOING_INTERFACE) } +interface-automatic{COLON} { YDVAR(1, VAR_INTERFACE_AUTOMATIC) } +so-rcvbuf{COLON} { YDVAR(1, VAR_SO_RCVBUF) } +so-sndbuf{COLON} { YDVAR(1, VAR_SO_SNDBUF) } +chroot{COLON} { YDVAR(1, VAR_CHROOT) } +username{COLON} { YDVAR(1, VAR_USERNAME) } +directory{COLON} { YDVAR(1, VAR_DIRECTORY) } +logfile{COLON} { YDVAR(1, VAR_LOGFILE) } +pidfile{COLON} { YDVAR(1, VAR_PIDFILE) } +root-hints{COLON} { YDVAR(1, VAR_ROOT_HINTS) } +edns-buffer-size{COLON} { YDVAR(1, VAR_EDNS_BUFFER_SIZE) } +msg-buffer-size{COLON} { YDVAR(1, VAR_MSG_BUFFER_SIZE) } +msg-cache-size{COLON} { YDVAR(1, VAR_MSG_CACHE_SIZE) } +msg-cache-slabs{COLON} { YDVAR(1, VAR_MSG_CACHE_SLABS) } +rrset-cache-size{COLON} { YDVAR(1, VAR_RRSET_CACHE_SIZE) } +rrset-cache-slabs{COLON} { YDVAR(1, VAR_RRSET_CACHE_SLABS) } +cache-max-ttl{COLON} { YDVAR(1, VAR_CACHE_MAX_TTL) } +cache-min-ttl{COLON} { YDVAR(1, VAR_CACHE_MIN_TTL) } +infra-host-ttl{COLON} { YDVAR(1, VAR_INFRA_HOST_TTL) } +infra-lame-ttl{COLON} { YDVAR(1, VAR_INFRA_LAME_TTL) } +infra-cache-slabs{COLON} { YDVAR(1, VAR_INFRA_CACHE_SLABS) } +infra-cache-numhosts{COLON} { YDVAR(1, VAR_INFRA_CACHE_NUMHOSTS) } +infra-cache-lame-size{COLON} { YDVAR(1, VAR_INFRA_CACHE_LAME_SIZE) } +num-queries-per-thread{COLON} { YDVAR(1, VAR_NUM_QUERIES_PER_THREAD) } +jostle-timeout{COLON} { YDVAR(1, VAR_JOSTLE_TIMEOUT) } +target-fetch-policy{COLON} { YDVAR(1, VAR_TARGET_FETCH_POLICY) } +harden-short-bufsize{COLON} { YDVAR(1, VAR_HARDEN_SHORT_BUFSIZE) } +harden-large-queries{COLON} { YDVAR(1, VAR_HARDEN_LARGE_QUERIES) } +harden-glue{COLON} { YDVAR(1, VAR_HARDEN_GLUE) } +harden-dnssec-stripped{COLON} { YDVAR(1, VAR_HARDEN_DNSSEC_STRIPPED) } +harden-below-nxdomain{COLON} { YDVAR(1, VAR_HARDEN_BELOW_NXDOMAIN) } +harden-referral-path{COLON} { YDVAR(1, VAR_HARDEN_REFERRAL_PATH) } +use-caps-for-id{COLON} { YDVAR(1, VAR_USE_CAPS_FOR_ID) } +unwanted-reply-threshold{COLON} { YDVAR(1, VAR_UNWANTED_REPLY_THRESHOLD) } +private-address{COLON} { YDVAR(1, VAR_PRIVATE_ADDRESS) } +private-domain{COLON} { YDVAR(1, VAR_PRIVATE_DOMAIN) } +prefetch-key{COLON} { YDVAR(1, VAR_PREFETCH_KEY) } +prefetch{COLON} { YDVAR(1, VAR_PREFETCH) } +stub-zone{COLON} { YDVAR(0, VAR_STUB_ZONE) } +name{COLON} { YDVAR(1, VAR_NAME) } +stub-addr{COLON} { YDVAR(1, VAR_STUB_ADDR) } +stub-host{COLON} { YDVAR(1, VAR_STUB_HOST) } +stub-prime{COLON} { YDVAR(1, VAR_STUB_PRIME) } +stub-first{COLON} { YDVAR(1, VAR_STUB_FIRST) } +forward-zone{COLON} { YDVAR(0, VAR_FORWARD_ZONE) } +forward-addr{COLON} { YDVAR(1, VAR_FORWARD_ADDR) } +forward-host{COLON} { YDVAR(1, VAR_FORWARD_HOST) } +forward-first{COLON} { YDVAR(1, VAR_FORWARD_FIRST) } +do-not-query-address{COLON} { YDVAR(1, VAR_DO_NOT_QUERY_ADDRESS) } +do-not-query-localhost{COLON} { YDVAR(1, VAR_DO_NOT_QUERY_LOCALHOST) } +access-control{COLON} { YDVAR(2, VAR_ACCESS_CONTROL) } +hide-identity{COLON} { YDVAR(1, VAR_HIDE_IDENTITY) } +hide-version{COLON} { YDVAR(1, VAR_HIDE_VERSION) } +identity{COLON} { YDVAR(1, VAR_IDENTITY) } +version{COLON} { YDVAR(1, VAR_VERSION) } +module-config{COLON} { YDVAR(1, VAR_MODULE_CONF) } +dlv-anchor{COLON} { YDVAR(1, VAR_DLV_ANCHOR) } +dlv-anchor-file{COLON} { YDVAR(1, VAR_DLV_ANCHOR_FILE) } +trust-anchor-file{COLON} { YDVAR(1, VAR_TRUST_ANCHOR_FILE) } +auto-trust-anchor-file{COLON} { YDVAR(1, VAR_AUTO_TRUST_ANCHOR_FILE) } +trusted-keys-file{COLON} { YDVAR(1, VAR_TRUSTED_KEYS_FILE) } +trust-anchor{COLON} { YDVAR(1, VAR_TRUST_ANCHOR) } +val-override-date{COLON} { YDVAR(1, VAR_VAL_OVERRIDE_DATE) } +val-sig-skew-min{COLON} { YDVAR(1, VAR_VAL_SIG_SKEW_MIN) } +val-sig-skew-max{COLON} { YDVAR(1, VAR_VAL_SIG_SKEW_MAX) } +val-bogus-ttl{COLON} { YDVAR(1, VAR_BOGUS_TTL) } +val-clean-additional{COLON} { YDVAR(1, VAR_VAL_CLEAN_ADDITIONAL) } +val-permissive-mode{COLON} { YDVAR(1, VAR_VAL_PERMISSIVE_MODE) } +ignore-cd-flag{COLON} { YDVAR(1, VAR_IGNORE_CD_FLAG) } +val-log-level{COLON} { YDVAR(1, VAR_VAL_LOG_LEVEL) } +key-cache-size{COLON} { YDVAR(1, VAR_KEY_CACHE_SIZE) } +key-cache-slabs{COLON} { YDVAR(1, VAR_KEY_CACHE_SLABS) } +neg-cache-size{COLON} { YDVAR(1, VAR_NEG_CACHE_SIZE) } +val-nsec3-keysize-iterations{COLON} { + YDVAR(1, VAR_VAL_NSEC3_KEYSIZE_ITERATIONS) } +add-holddown{COLON} { YDVAR(1, VAR_ADD_HOLDDOWN) } +del-holddown{COLON} { YDVAR(1, VAR_DEL_HOLDDOWN) } +keep-missing{COLON} { YDVAR(1, VAR_KEEP_MISSING) } +use-syslog{COLON} { YDVAR(1, VAR_USE_SYSLOG) } +log-time-ascii{COLON} { YDVAR(1, VAR_LOG_TIME_ASCII) } +log-queries{COLON} { YDVAR(1, VAR_LOG_QUERIES) } +local-zone{COLON} { YDVAR(2, VAR_LOCAL_ZONE) } +local-data{COLON} { YDVAR(1, VAR_LOCAL_DATA) } +local-data-ptr{COLON} { YDVAR(1, VAR_LOCAL_DATA_PTR) } +statistics-interval{COLON} { YDVAR(1, VAR_STATISTICS_INTERVAL) } +statistics-cumulative{COLON} { YDVAR(1, VAR_STATISTICS_CUMULATIVE) } +extended-statistics{COLON} { YDVAR(1, VAR_EXTENDED_STATISTICS) } +remote-control{COLON} { YDVAR(0, VAR_REMOTE_CONTROL) } +control-enable{COLON} { YDVAR(1, VAR_CONTROL_ENABLE) } +control-interface{COLON} { YDVAR(1, VAR_CONTROL_INTERFACE) } +control-port{COLON} { YDVAR(1, VAR_CONTROL_PORT) } +server-key-file{COLON} { YDVAR(1, VAR_SERVER_KEY_FILE) } +server-cert-file{COLON} { YDVAR(1, VAR_SERVER_CERT_FILE) } +control-key-file{COLON} { YDVAR(1, VAR_CONTROL_KEY_FILE) } +control-cert-file{COLON} { YDVAR(1, VAR_CONTROL_CERT_FILE) } +python-script{COLON} { YDVAR(1, VAR_PYTHON_SCRIPT) } +python{COLON} { YDVAR(0, VAR_PYTHON) } +domain-insecure{COLON} { YDVAR(1, VAR_DOMAIN_INSECURE) } +minimal-responses{COLON} { YDVAR(1, VAR_MINIMAL_RESPONSES) } +rrset-roundrobin{COLON} { YDVAR(1, VAR_RRSET_ROUNDROBIN) } +{NEWLINE} { LEXOUT(("NL\n")); cfg_parser->line++; } + + /* Quoted strings. Strip leading and ending quotes */ +\" { BEGIN(quotedstring); LEXOUT(("QS ")); } +<> { + yyerror("EOF inside quoted string"); + if(--num_args == 0) { BEGIN(INITIAL); } + else { BEGIN(val); } +} +{DQANY}* { LEXOUT(("STR(%s) ", yytext)); yymore(); } +{NEWLINE} { yyerror("newline inside quoted string, no end \""); + cfg_parser->line++; BEGIN(INITIAL); } +\" { + LEXOUT(("QE ")); + if(--num_args == 0) { BEGIN(INITIAL); } + else { BEGIN(val); } + yytext[yyleng - 1] = '\0'; + yylval.str = strdup(yytext); + if(!yylval.str) + yyerror("out of memory"); + return STRING_ARG; +} + + /* Single Quoted strings. Strip leading and ending quotes */ +\' { BEGIN(singlequotedstr); LEXOUT(("SQS ")); } +<> { + yyerror("EOF inside quoted string"); + if(--num_args == 0) { BEGIN(INITIAL); } + else { BEGIN(val); } +} +{SQANY}* { LEXOUT(("STR(%s) ", yytext)); yymore(); } +{NEWLINE} { yyerror("newline inside quoted string, no end '"); + cfg_parser->line++; BEGIN(INITIAL); } +\' { + LEXOUT(("SQE ")); + if(--num_args == 0) { BEGIN(INITIAL); } + else { BEGIN(val); } + yytext[yyleng - 1] = '\0'; + yylval.str = strdup(yytext); + if(!yylval.str) + yyerror("out of memory"); + return STRING_ARG; +} + + /* include: directive */ +include{COLON} { + LEXOUT(("v(%s) ", yytext)); inc_prev = YYSTATE; BEGIN(include); } +<> { + yyerror("EOF inside include directive"); + BEGIN(inc_prev); +} +{SPACE}* { LEXOUT(("ISP ")); /* ignore */ } +{NEWLINE} { LEXOUT(("NL\n")); cfg_parser->line++;} +\" { LEXOUT(("IQS ")); BEGIN(include_quoted); } +{UNQUOTEDLETTER}* { + LEXOUT(("Iunquotedstr(%s) ", yytext)); + config_start_include(yytext); + BEGIN(inc_prev); +} +<> { + yyerror("EOF inside quoted string"); + BEGIN(inc_prev); +} +{DQANY}* { LEXOUT(("ISTR(%s) ", yytext)); yymore(); } +{NEWLINE} { yyerror("newline before \" in include name"); + cfg_parser->line++; BEGIN(inc_prev); } +\" { + LEXOUT(("IQE ")); + yytext[yyleng - 1] = '\0'; + config_start_include(yytext); + BEGIN(inc_prev); +} +<> { + yy_set_bol(1); /* Set beginning of line, so "^" rules match. */ + if (config_include_stack_ptr == 0) { + yyterminate(); + } else { + fclose(yyin); + config_end_include(); + } +} + +{UNQUOTEDLETTER}* { LEXOUT(("unquotedstr(%s) ", yytext)); + if(--num_args == 0) { BEGIN(INITIAL); } + yylval.str = strdup(yytext); return STRING_ARG; } + +{UNQUOTEDLETTER_NOCOLON}* { + ub_c_error_msg("unknown keyword '%s'", yytext); + } + +<*>. { + ub_c_error_msg("stray '%s'", yytext); + } + +%% diff --git a/util/configparser.c b/util/configparser.c new file mode 100644 index 00000000000..6ed60dfad68 --- /dev/null +++ b/util/configparser.c @@ -0,0 +1,3892 @@ +/* A Bison parser, made by GNU Bison 2.5. */ + +/* Bison implementation for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "2.5" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 0 + +/* Push parsers. */ +#define YYPUSH 0 + +/* Pull parsers. */ +#define YYPULL 1 + +/* Using locations. */ +#define YYLSP_NEEDED 0 + + + +/* Copy the first part of user declarations. */ + +/* Line 268 of yacc.c */ +#line 38 "util/configparser.y" + +#include "config.h" + +#include +#include +#include +#include +#include + +#include "util/configyyrename.h" +#include "util/config_file.h" +#include "util/net_help.h" + +int ub_c_lex(void); +void ub_c_error(const char *message); + +/* these need to be global, otherwise they cannot be used inside yacc */ +extern struct config_parser_state* cfg_parser; + +#if 0 +#define OUTYY(s) printf s /* used ONLY when debugging */ +#else +#define OUTYY(s) +#endif + + + +/* Line 268 of yacc.c */ +#line 99 "util/configparser.c" + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +/* Enabling the token table. */ +#ifndef YYTOKEN_TABLE +# define YYTOKEN_TABLE 0 +#endif + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + SPACE = 258, + LETTER = 259, + NEWLINE = 260, + COMMENT = 261, + COLON = 262, + ANY = 263, + ZONESTR = 264, + STRING_ARG = 265, + VAR_SERVER = 266, + VAR_VERBOSITY = 267, + VAR_NUM_THREADS = 268, + VAR_PORT = 269, + VAR_OUTGOING_RANGE = 270, + VAR_INTERFACE = 271, + VAR_DO_IP4 = 272, + VAR_DO_IP6 = 273, + VAR_DO_UDP = 274, + VAR_DO_TCP = 275, + VAR_CHROOT = 276, + VAR_USERNAME = 277, + VAR_DIRECTORY = 278, + VAR_LOGFILE = 279, + VAR_PIDFILE = 280, + VAR_MSG_CACHE_SIZE = 281, + VAR_MSG_CACHE_SLABS = 282, + VAR_NUM_QUERIES_PER_THREAD = 283, + VAR_RRSET_CACHE_SIZE = 284, + VAR_RRSET_CACHE_SLABS = 285, + VAR_OUTGOING_NUM_TCP = 286, + VAR_INFRA_HOST_TTL = 287, + VAR_INFRA_LAME_TTL = 288, + VAR_INFRA_CACHE_SLABS = 289, + VAR_INFRA_CACHE_NUMHOSTS = 290, + VAR_INFRA_CACHE_LAME_SIZE = 291, + VAR_NAME = 292, + VAR_STUB_ZONE = 293, + VAR_STUB_HOST = 294, + VAR_STUB_ADDR = 295, + VAR_TARGET_FETCH_POLICY = 296, + VAR_HARDEN_SHORT_BUFSIZE = 297, + VAR_HARDEN_LARGE_QUERIES = 298, + VAR_FORWARD_ZONE = 299, + VAR_FORWARD_HOST = 300, + VAR_FORWARD_ADDR = 301, + VAR_DO_NOT_QUERY_ADDRESS = 302, + VAR_HIDE_IDENTITY = 303, + VAR_HIDE_VERSION = 304, + VAR_IDENTITY = 305, + VAR_VERSION = 306, + VAR_HARDEN_GLUE = 307, + VAR_MODULE_CONF = 308, + VAR_TRUST_ANCHOR_FILE = 309, + VAR_TRUST_ANCHOR = 310, + VAR_VAL_OVERRIDE_DATE = 311, + VAR_BOGUS_TTL = 312, + VAR_VAL_CLEAN_ADDITIONAL = 313, + VAR_VAL_PERMISSIVE_MODE = 314, + VAR_INCOMING_NUM_TCP = 315, + VAR_MSG_BUFFER_SIZE = 316, + VAR_KEY_CACHE_SIZE = 317, + VAR_KEY_CACHE_SLABS = 318, + VAR_TRUSTED_KEYS_FILE = 319, + VAR_VAL_NSEC3_KEYSIZE_ITERATIONS = 320, + VAR_USE_SYSLOG = 321, + VAR_OUTGOING_INTERFACE = 322, + VAR_ROOT_HINTS = 323, + VAR_DO_NOT_QUERY_LOCALHOST = 324, + VAR_CACHE_MAX_TTL = 325, + VAR_HARDEN_DNSSEC_STRIPPED = 326, + VAR_ACCESS_CONTROL = 327, + VAR_LOCAL_ZONE = 328, + VAR_LOCAL_DATA = 329, + VAR_INTERFACE_AUTOMATIC = 330, + VAR_STATISTICS_INTERVAL = 331, + VAR_DO_DAEMONIZE = 332, + VAR_USE_CAPS_FOR_ID = 333, + VAR_STATISTICS_CUMULATIVE = 334, + VAR_OUTGOING_PORT_PERMIT = 335, + VAR_OUTGOING_PORT_AVOID = 336, + VAR_DLV_ANCHOR_FILE = 337, + VAR_DLV_ANCHOR = 338, + VAR_NEG_CACHE_SIZE = 339, + VAR_HARDEN_REFERRAL_PATH = 340, + VAR_PRIVATE_ADDRESS = 341, + VAR_PRIVATE_DOMAIN = 342, + VAR_REMOTE_CONTROL = 343, + VAR_CONTROL_ENABLE = 344, + VAR_CONTROL_INTERFACE = 345, + VAR_CONTROL_PORT = 346, + VAR_SERVER_KEY_FILE = 347, + VAR_SERVER_CERT_FILE = 348, + VAR_CONTROL_KEY_FILE = 349, + VAR_CONTROL_CERT_FILE = 350, + VAR_EXTENDED_STATISTICS = 351, + VAR_LOCAL_DATA_PTR = 352, + VAR_JOSTLE_TIMEOUT = 353, + VAR_STUB_PRIME = 354, + VAR_UNWANTED_REPLY_THRESHOLD = 355, + VAR_LOG_TIME_ASCII = 356, + VAR_DOMAIN_INSECURE = 357, + VAR_PYTHON = 358, + VAR_PYTHON_SCRIPT = 359, + VAR_VAL_SIG_SKEW_MIN = 360, + VAR_VAL_SIG_SKEW_MAX = 361, + VAR_CACHE_MIN_TTL = 362, + VAR_VAL_LOG_LEVEL = 363, + VAR_AUTO_TRUST_ANCHOR_FILE = 364, + VAR_KEEP_MISSING = 365, + VAR_ADD_HOLDDOWN = 366, + VAR_DEL_HOLDDOWN = 367, + VAR_SO_RCVBUF = 368, + VAR_EDNS_BUFFER_SIZE = 369, + VAR_PREFETCH = 370, + VAR_PREFETCH_KEY = 371, + VAR_SO_SNDBUF = 372, + VAR_HARDEN_BELOW_NXDOMAIN = 373, + VAR_IGNORE_CD_FLAG = 374, + VAR_LOG_QUERIES = 375, + VAR_TCP_UPSTREAM = 376, + VAR_SSL_UPSTREAM = 377, + VAR_SSL_SERVICE_KEY = 378, + VAR_SSL_SERVICE_PEM = 379, + VAR_SSL_PORT = 380, + VAR_FORWARD_FIRST = 381, + VAR_STUB_FIRST = 382, + VAR_MINIMAL_RESPONSES = 383, + VAR_RRSET_ROUNDROBIN = 384 + }; +#endif +/* Tokens. */ +#define SPACE 258 +#define LETTER 259 +#define NEWLINE 260 +#define COMMENT 261 +#define COLON 262 +#define ANY 263 +#define ZONESTR 264 +#define STRING_ARG 265 +#define VAR_SERVER 266 +#define VAR_VERBOSITY 267 +#define VAR_NUM_THREADS 268 +#define VAR_PORT 269 +#define VAR_OUTGOING_RANGE 270 +#define VAR_INTERFACE 271 +#define VAR_DO_IP4 272 +#define VAR_DO_IP6 273 +#define VAR_DO_UDP 274 +#define VAR_DO_TCP 275 +#define VAR_CHROOT 276 +#define VAR_USERNAME 277 +#define VAR_DIRECTORY 278 +#define VAR_LOGFILE 279 +#define VAR_PIDFILE 280 +#define VAR_MSG_CACHE_SIZE 281 +#define VAR_MSG_CACHE_SLABS 282 +#define VAR_NUM_QUERIES_PER_THREAD 283 +#define VAR_RRSET_CACHE_SIZE 284 +#define VAR_RRSET_CACHE_SLABS 285 +#define VAR_OUTGOING_NUM_TCP 286 +#define VAR_INFRA_HOST_TTL 287 +#define VAR_INFRA_LAME_TTL 288 +#define VAR_INFRA_CACHE_SLABS 289 +#define VAR_INFRA_CACHE_NUMHOSTS 290 +#define VAR_INFRA_CACHE_LAME_SIZE 291 +#define VAR_NAME 292 +#define VAR_STUB_ZONE 293 +#define VAR_STUB_HOST 294 +#define VAR_STUB_ADDR 295 +#define VAR_TARGET_FETCH_POLICY 296 +#define VAR_HARDEN_SHORT_BUFSIZE 297 +#define VAR_HARDEN_LARGE_QUERIES 298 +#define VAR_FORWARD_ZONE 299 +#define VAR_FORWARD_HOST 300 +#define VAR_FORWARD_ADDR 301 +#define VAR_DO_NOT_QUERY_ADDRESS 302 +#define VAR_HIDE_IDENTITY 303 +#define VAR_HIDE_VERSION 304 +#define VAR_IDENTITY 305 +#define VAR_VERSION 306 +#define VAR_HARDEN_GLUE 307 +#define VAR_MODULE_CONF 308 +#define VAR_TRUST_ANCHOR_FILE 309 +#define VAR_TRUST_ANCHOR 310 +#define VAR_VAL_OVERRIDE_DATE 311 +#define VAR_BOGUS_TTL 312 +#define VAR_VAL_CLEAN_ADDITIONAL 313 +#define VAR_VAL_PERMISSIVE_MODE 314 +#define VAR_INCOMING_NUM_TCP 315 +#define VAR_MSG_BUFFER_SIZE 316 +#define VAR_KEY_CACHE_SIZE 317 +#define VAR_KEY_CACHE_SLABS 318 +#define VAR_TRUSTED_KEYS_FILE 319 +#define VAR_VAL_NSEC3_KEYSIZE_ITERATIONS 320 +#define VAR_USE_SYSLOG 321 +#define VAR_OUTGOING_INTERFACE 322 +#define VAR_ROOT_HINTS 323 +#define VAR_DO_NOT_QUERY_LOCALHOST 324 +#define VAR_CACHE_MAX_TTL 325 +#define VAR_HARDEN_DNSSEC_STRIPPED 326 +#define VAR_ACCESS_CONTROL 327 +#define VAR_LOCAL_ZONE 328 +#define VAR_LOCAL_DATA 329 +#define VAR_INTERFACE_AUTOMATIC 330 +#define VAR_STATISTICS_INTERVAL 331 +#define VAR_DO_DAEMONIZE 332 +#define VAR_USE_CAPS_FOR_ID 333 +#define VAR_STATISTICS_CUMULATIVE 334 +#define VAR_OUTGOING_PORT_PERMIT 335 +#define VAR_OUTGOING_PORT_AVOID 336 +#define VAR_DLV_ANCHOR_FILE 337 +#define VAR_DLV_ANCHOR 338 +#define VAR_NEG_CACHE_SIZE 339 +#define VAR_HARDEN_REFERRAL_PATH 340 +#define VAR_PRIVATE_ADDRESS 341 +#define VAR_PRIVATE_DOMAIN 342 +#define VAR_REMOTE_CONTROL 343 +#define VAR_CONTROL_ENABLE 344 +#define VAR_CONTROL_INTERFACE 345 +#define VAR_CONTROL_PORT 346 +#define VAR_SERVER_KEY_FILE 347 +#define VAR_SERVER_CERT_FILE 348 +#define VAR_CONTROL_KEY_FILE 349 +#define VAR_CONTROL_CERT_FILE 350 +#define VAR_EXTENDED_STATISTICS 351 +#define VAR_LOCAL_DATA_PTR 352 +#define VAR_JOSTLE_TIMEOUT 353 +#define VAR_STUB_PRIME 354 +#define VAR_UNWANTED_REPLY_THRESHOLD 355 +#define VAR_LOG_TIME_ASCII 356 +#define VAR_DOMAIN_INSECURE 357 +#define VAR_PYTHON 358 +#define VAR_PYTHON_SCRIPT 359 +#define VAR_VAL_SIG_SKEW_MIN 360 +#define VAR_VAL_SIG_SKEW_MAX 361 +#define VAR_CACHE_MIN_TTL 362 +#define VAR_VAL_LOG_LEVEL 363 +#define VAR_AUTO_TRUST_ANCHOR_FILE 364 +#define VAR_KEEP_MISSING 365 +#define VAR_ADD_HOLDDOWN 366 +#define VAR_DEL_HOLDDOWN 367 +#define VAR_SO_RCVBUF 368 +#define VAR_EDNS_BUFFER_SIZE 369 +#define VAR_PREFETCH 370 +#define VAR_PREFETCH_KEY 371 +#define VAR_SO_SNDBUF 372 +#define VAR_HARDEN_BELOW_NXDOMAIN 373 +#define VAR_IGNORE_CD_FLAG 374 +#define VAR_LOG_QUERIES 375 +#define VAR_TCP_UPSTREAM 376 +#define VAR_SSL_UPSTREAM 377 +#define VAR_SSL_SERVICE_KEY 378 +#define VAR_SSL_SERVICE_PEM 379 +#define VAR_SSL_PORT 380 +#define VAR_FORWARD_FIRST 381 +#define VAR_STUB_FIRST 382 +#define VAR_MINIMAL_RESPONSES 383 +#define VAR_RRSET_ROUNDROBIN 384 + + + + +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE +{ + +/* Line 293 of yacc.c */ +#line 64 "util/configparser.y" + + char* str; + + + +/* Line 293 of yacc.c */ +#line 399 "util/configparser.c" +} YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +#endif + + +/* Copy the second part of user declarations. */ + + +/* Line 343 of yacc.c */ +#line 411 "util/configparser.c" + +#ifdef short +# undef short +#endif + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#elif (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +typedef signed char yytype_int8; +#else +typedef short int yytype_int8; +#endif + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif +#endif + +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + +#ifndef YY_ +# if defined YYENABLE_NLS && YYENABLE_NLS +# if ENABLE_NLS +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_(msgid) dgettext ("bison-runtime", msgid) +# endif +# endif +# ifndef YY_ +# define YY_(msgid) msgid +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(e) ((void) (e)) +#else +# define YYUSE(e) /* empty */ +#endif + +/* Identity function, used to suppress warnings about constant conditions. */ +#ifndef lint +# define YYID(n) (n) +#else +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static int +YYID (int yyi) +#else +static int +YYID (yyi) + int yyi; +#endif +{ + return yyi; +} +#endif + +#if ! defined yyoverflow || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined EXIT_SUCCESS \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ + + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yytype_int16 yyss_alloc; + YYSTYPE yyvs_alloc; +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +# define YYCOPY_NEEDED 1 + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (YYID (0)) + +#endif + +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif +#endif /* !YYCOPY_NEEDED */ + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 2 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 237 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 130 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 133 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 253 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 371 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 384 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const yytype_uint8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, + 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, + 125, 126, 127, 128, 129 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const yytype_uint16 yyprhs[] = +{ + 0, 0, 3, 4, 7, 10, 13, 16, 19, 22, + 24, 27, 28, 30, 32, 34, 36, 38, 40, 42, + 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, + 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, + 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, + 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, + 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, + 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, + 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, + 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, + 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, + 224, 226, 229, 230, 232, 234, 236, 238, 240, 242, + 245, 246, 248, 250, 252, 254, 257, 260, 263, 266, + 269, 272, 275, 278, 281, 284, 287, 290, 293, 296, + 299, 302, 305, 308, 311, 314, 317, 320, 323, 326, + 329, 332, 335, 338, 341, 344, 347, 350, 353, 356, + 359, 362, 365, 368, 371, 374, 377, 380, 383, 386, + 389, 392, 395, 398, 401, 404, 407, 410, 413, 416, + 419, 422, 425, 428, 431, 434, 437, 440, 443, 446, + 449, 452, 455, 458, 461, 464, 467, 470, 473, 476, + 480, 483, 486, 489, 492, 495, 498, 501, 504, 507, + 510, 513, 516, 519, 522, 525, 528, 531, 534, 538, + 541, 544, 547, 550, 553, 556, 559, 562, 565, 568, + 571, 574, 577, 579, 582, 583, 585, 587, 589, 591, + 593, 595, 597, 600, 603, 606, 609, 612, 615, 618, + 620, 623, 624, 626 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yytype_int16 yyrhs[] = +{ + 131, 0, -1, -1, 131, 132, -1, 133, 134, -1, + 136, 137, -1, 139, 140, -1, 259, 260, -1, 249, + 250, -1, 11, -1, 134, 135, -1, -1, 142, -1, + 143, -1, 147, -1, 150, -1, 156, -1, 157, -1, + 158, -1, 159, -1, 148, -1, 169, -1, 170, -1, + 171, -1, 172, -1, 173, -1, 190, -1, 191, -1, + 192, -1, 194, -1, 195, -1, 153, -1, 196, -1, + 197, -1, 200, -1, 198, -1, 199, -1, 201, -1, + 202, -1, 203, -1, 214, -1, 182, -1, 183, -1, + 184, -1, 185, -1, 204, -1, 217, -1, 178, -1, + 180, -1, 218, -1, 223, -1, 224, -1, 225, -1, + 154, -1, 189, -1, 232, -1, 233, -1, 179, -1, + 228, -1, 166, -1, 149, -1, 174, -1, 215, -1, + 221, -1, 205, -1, 216, -1, 235, -1, 236, -1, + 155, -1, 144, -1, 165, -1, 208, -1, 145, -1, + 151, -1, 152, -1, 175, -1, 176, -1, 234, -1, + 207, -1, 209, -1, 210, -1, 146, -1, 237, -1, + 193, -1, 213, -1, 167, -1, 181, -1, 219, -1, + 220, -1, 222, -1, 227, -1, 177, -1, 229, -1, + 230, -1, 231, -1, 186, -1, 188, -1, 211, -1, + 212, -1, 187, -1, 206, -1, 226, -1, 168, -1, + 160, -1, 161, -1, 162, -1, 163, -1, 164, -1, + 238, -1, 239, -1, 38, -1, 137, 138, -1, -1, + 240, -1, 241, -1, 242, -1, 244, -1, 243, -1, + 44, -1, 140, 141, -1, -1, 245, -1, 246, -1, + 247, -1, 248, -1, 13, 10, -1, 12, 10, -1, + 76, 10, -1, 79, 10, -1, 96, 10, -1, 14, + 10, -1, 16, 10, -1, 67, 10, -1, 15, 10, + -1, 80, 10, -1, 81, 10, -1, 31, 10, -1, + 60, 10, -1, 75, 10, -1, 17, 10, -1, 18, + 10, -1, 19, 10, -1, 20, 10, -1, 121, 10, + -1, 122, 10, -1, 123, 10, -1, 124, 10, -1, + 125, 10, -1, 77, 10, -1, 66, 10, -1, 101, + 10, -1, 120, 10, -1, 21, 10, -1, 22, 10, + -1, 23, 10, -1, 24, 10, -1, 25, 10, -1, + 68, 10, -1, 82, 10, -1, 83, 10, -1, 109, + 10, -1, 54, 10, -1, 64, 10, -1, 55, 10, + -1, 102, 10, -1, 48, 10, -1, 49, 10, -1, + 50, 10, -1, 51, 10, -1, 113, 10, -1, 117, + 10, -1, 114, 10, -1, 61, 10, -1, 26, 10, + -1, 27, 10, -1, 28, 10, -1, 98, 10, -1, + 29, 10, -1, 30, 10, -1, 32, 10, -1, 33, + 10, -1, 35, 10, -1, 36, 10, -1, 34, 10, + -1, 41, 10, -1, 42, 10, -1, 43, 10, -1, + 52, 10, -1, 71, 10, -1, 118, 10, -1, 85, + 10, -1, 78, 10, -1, 86, 10, -1, 87, 10, + -1, 115, 10, -1, 116, 10, -1, 100, 10, -1, + 47, 10, -1, 69, 10, -1, 72, 10, 10, -1, + 53, 10, -1, 56, 10, -1, 105, 10, -1, 106, + 10, -1, 70, 10, -1, 107, 10, -1, 57, 10, + -1, 58, 10, -1, 59, 10, -1, 119, 10, -1, + 108, 10, -1, 65, 10, -1, 111, 10, -1, 112, + 10, -1, 110, 10, -1, 62, 10, -1, 63, 10, + -1, 84, 10, -1, 73, 10, 10, -1, 74, 10, + -1, 97, 10, -1, 128, 10, -1, 129, 10, -1, + 37, 10, -1, 39, 10, -1, 40, 10, -1, 127, + 10, -1, 99, 10, -1, 37, 10, -1, 45, 10, + -1, 46, 10, -1, 126, 10, -1, 88, -1, 250, + 251, -1, -1, 252, -1, 254, -1, 253, -1, 255, + -1, 256, -1, 257, -1, 258, -1, 89, 10, -1, + 91, 10, -1, 90, 10, -1, 92, 10, -1, 93, + 10, -1, 94, 10, -1, 95, 10, -1, 103, -1, + 260, 261, -1, -1, 262, -1, 104, 10, -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const yytype_uint16 yyrline[] = +{ + 0, 110, 110, 110, 111, 111, 112, 112, 113, 117, + 122, 123, 124, 124, 124, 125, 125, 126, 126, 126, + 127, 127, 127, 128, 128, 128, 129, 129, 130, 130, + 131, 131, 132, 132, 133, 133, 134, 134, 135, 135, + 136, 136, 137, 137, 137, 138, 138, 138, 139, 139, + 139, 140, 140, 141, 141, 142, 142, 143, 143, 144, + 144, 144, 145, 145, 146, 146, 147, 147, 147, 148, + 148, 149, 149, 150, 150, 151, 151, 151, 152, 152, + 153, 153, 154, 154, 155, 155, 156, 156, 157, 157, + 157, 158, 158, 159, 159, 159, 160, 160, 160, 161, + 161, 161, 162, 162, 162, 163, 163, 163, 164, 164, + 166, 178, 179, 180, 180, 180, 180, 180, 182, 194, + 195, 196, 196, 196, 196, 198, 207, 216, 227, 236, + 245, 254, 267, 282, 291, 300, 309, 318, 327, 336, + 345, 354, 363, 372, 381, 390, 397, 404, 413, 422, + 436, 445, 454, 461, 468, 475, 483, 490, 497, 504, + 511, 519, 527, 535, 542, 549, 558, 567, 574, 581, + 589, 597, 610, 621, 629, 642, 651, 660, 668, 681, + 690, 698, 707, 715, 728, 735, 745, 755, 765, 775, + 785, 795, 805, 812, 819, 828, 837, 846, 853, 863, + 877, 884, 902, 915, 928, 937, 946, 955, 965, 975, + 984, 993, 1000, 1009, 1018, 1027, 1035, 1048, 1056, 1078, + 1085, 1100, 1110, 1120, 1130, 1137, 1144, 1153, 1163, 1173, + 1180, 1187, 1196, 1201, 1202, 1203, 1203, 1203, 1204, 1204, + 1204, 1205, 1207, 1217, 1226, 1233, 1240, 1247, 1254, 1261, + 1266, 1267, 1268, 1270 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "SPACE", "LETTER", "NEWLINE", "COMMENT", + "COLON", "ANY", "ZONESTR", "STRING_ARG", "VAR_SERVER", "VAR_VERBOSITY", + "VAR_NUM_THREADS", "VAR_PORT", "VAR_OUTGOING_RANGE", "VAR_INTERFACE", + "VAR_DO_IP4", "VAR_DO_IP6", "VAR_DO_UDP", "VAR_DO_TCP", "VAR_CHROOT", + "VAR_USERNAME", "VAR_DIRECTORY", "VAR_LOGFILE", "VAR_PIDFILE", + "VAR_MSG_CACHE_SIZE", "VAR_MSG_CACHE_SLABS", + "VAR_NUM_QUERIES_PER_THREAD", "VAR_RRSET_CACHE_SIZE", + "VAR_RRSET_CACHE_SLABS", "VAR_OUTGOING_NUM_TCP", "VAR_INFRA_HOST_TTL", + "VAR_INFRA_LAME_TTL", "VAR_INFRA_CACHE_SLABS", + "VAR_INFRA_CACHE_NUMHOSTS", "VAR_INFRA_CACHE_LAME_SIZE", "VAR_NAME", + "VAR_STUB_ZONE", "VAR_STUB_HOST", "VAR_STUB_ADDR", + "VAR_TARGET_FETCH_POLICY", "VAR_HARDEN_SHORT_BUFSIZE", + "VAR_HARDEN_LARGE_QUERIES", "VAR_FORWARD_ZONE", "VAR_FORWARD_HOST", + "VAR_FORWARD_ADDR", "VAR_DO_NOT_QUERY_ADDRESS", "VAR_HIDE_IDENTITY", + "VAR_HIDE_VERSION", "VAR_IDENTITY", "VAR_VERSION", "VAR_HARDEN_GLUE", + "VAR_MODULE_CONF", "VAR_TRUST_ANCHOR_FILE", "VAR_TRUST_ANCHOR", + "VAR_VAL_OVERRIDE_DATE", "VAR_BOGUS_TTL", "VAR_VAL_CLEAN_ADDITIONAL", + "VAR_VAL_PERMISSIVE_MODE", "VAR_INCOMING_NUM_TCP", "VAR_MSG_BUFFER_SIZE", + "VAR_KEY_CACHE_SIZE", "VAR_KEY_CACHE_SLABS", "VAR_TRUSTED_KEYS_FILE", + "VAR_VAL_NSEC3_KEYSIZE_ITERATIONS", "VAR_USE_SYSLOG", + "VAR_OUTGOING_INTERFACE", "VAR_ROOT_HINTS", "VAR_DO_NOT_QUERY_LOCALHOST", + "VAR_CACHE_MAX_TTL", "VAR_HARDEN_DNSSEC_STRIPPED", "VAR_ACCESS_CONTROL", + "VAR_LOCAL_ZONE", "VAR_LOCAL_DATA", "VAR_INTERFACE_AUTOMATIC", + "VAR_STATISTICS_INTERVAL", "VAR_DO_DAEMONIZE", "VAR_USE_CAPS_FOR_ID", + "VAR_STATISTICS_CUMULATIVE", "VAR_OUTGOING_PORT_PERMIT", + "VAR_OUTGOING_PORT_AVOID", "VAR_DLV_ANCHOR_FILE", "VAR_DLV_ANCHOR", + "VAR_NEG_CACHE_SIZE", "VAR_HARDEN_REFERRAL_PATH", "VAR_PRIVATE_ADDRESS", + "VAR_PRIVATE_DOMAIN", "VAR_REMOTE_CONTROL", "VAR_CONTROL_ENABLE", + "VAR_CONTROL_INTERFACE", "VAR_CONTROL_PORT", "VAR_SERVER_KEY_FILE", + "VAR_SERVER_CERT_FILE", "VAR_CONTROL_KEY_FILE", "VAR_CONTROL_CERT_FILE", + "VAR_EXTENDED_STATISTICS", "VAR_LOCAL_DATA_PTR", "VAR_JOSTLE_TIMEOUT", + "VAR_STUB_PRIME", "VAR_UNWANTED_REPLY_THRESHOLD", "VAR_LOG_TIME_ASCII", + "VAR_DOMAIN_INSECURE", "VAR_PYTHON", "VAR_PYTHON_SCRIPT", + "VAR_VAL_SIG_SKEW_MIN", "VAR_VAL_SIG_SKEW_MAX", "VAR_CACHE_MIN_TTL", + "VAR_VAL_LOG_LEVEL", "VAR_AUTO_TRUST_ANCHOR_FILE", "VAR_KEEP_MISSING", + "VAR_ADD_HOLDDOWN", "VAR_DEL_HOLDDOWN", "VAR_SO_RCVBUF", + "VAR_EDNS_BUFFER_SIZE", "VAR_PREFETCH", "VAR_PREFETCH_KEY", + "VAR_SO_SNDBUF", "VAR_HARDEN_BELOW_NXDOMAIN", "VAR_IGNORE_CD_FLAG", + "VAR_LOG_QUERIES", "VAR_TCP_UPSTREAM", "VAR_SSL_UPSTREAM", + "VAR_SSL_SERVICE_KEY", "VAR_SSL_SERVICE_PEM", "VAR_SSL_PORT", + "VAR_FORWARD_FIRST", "VAR_STUB_FIRST", "VAR_MINIMAL_RESPONSES", + "VAR_RRSET_ROUNDROBIN", "$accept", "toplevelvars", "toplevelvar", + "serverstart", "contents_server", "content_server", "stubstart", + "contents_stub", "content_stub", "forwardstart", "contents_forward", + "content_forward", "server_num_threads", "server_verbosity", + "server_statistics_interval", "server_statistics_cumulative", + "server_extended_statistics", "server_port", "server_interface", + "server_outgoing_interface", "server_outgoing_range", + "server_outgoing_port_permit", "server_outgoing_port_avoid", + "server_outgoing_num_tcp", "server_incoming_num_tcp", + "server_interface_automatic", "server_do_ip4", "server_do_ip6", + "server_do_udp", "server_do_tcp", "server_tcp_upstream", + "server_ssl_upstream", "server_ssl_service_key", + "server_ssl_service_pem", "server_ssl_port", "server_do_daemonize", + "server_use_syslog", "server_log_time_ascii", "server_log_queries", + "server_chroot", "server_username", "server_directory", "server_logfile", + "server_pidfile", "server_root_hints", "server_dlv_anchor_file", + "server_dlv_anchor", "server_auto_trust_anchor_file", + "server_trust_anchor_file", "server_trusted_keys_file", + "server_trust_anchor", "server_domain_insecure", "server_hide_identity", + "server_hide_version", "server_identity", "server_version", + "server_so_rcvbuf", "server_so_sndbuf", "server_edns_buffer_size", + "server_msg_buffer_size", "server_msg_cache_size", + "server_msg_cache_slabs", "server_num_queries_per_thread", + "server_jostle_timeout", "server_rrset_cache_size", + "server_rrset_cache_slabs", "server_infra_host_ttl", + "server_infra_lame_ttl", "server_infra_cache_numhosts", + "server_infra_cache_lame_size", "server_infra_cache_slabs", + "server_target_fetch_policy", "server_harden_short_bufsize", + "server_harden_large_queries", "server_harden_glue", + "server_harden_dnssec_stripped", "server_harden_below_nxdomain", + "server_harden_referral_path", "server_use_caps_for_id", + "server_private_address", "server_private_domain", "server_prefetch", + "server_prefetch_key", "server_unwanted_reply_threshold", + "server_do_not_query_address", "server_do_not_query_localhost", + "server_access_control", "server_module_conf", + "server_val_override_date", "server_val_sig_skew_min", + "server_val_sig_skew_max", "server_cache_max_ttl", + "server_cache_min_ttl", "server_bogus_ttl", + "server_val_clean_additional", "server_val_permissive_mode", + "server_ignore_cd_flag", "server_val_log_level", + "server_val_nsec3_keysize_iterations", "server_add_holddown", + "server_del_holddown", "server_keep_missing", "server_key_cache_size", + "server_key_cache_slabs", "server_neg_cache_size", "server_local_zone", + "server_local_data", "server_local_data_ptr", "server_minimal_responses", + "server_rrset_roundrobin", "stub_name", "stub_host", "stub_addr", + "stub_first", "stub_prime", "forward_name", "forward_host", + "forward_addr", "forward_first", "rcstart", "contents_rc", "content_rc", + "rc_control_enable", "rc_control_port", "rc_control_interface", + "rc_server_key_file", "rc_server_cert_file", "rc_control_key_file", + "rc_control_cert_file", "pythonstart", "contents_py", "content_py", + "py_script", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const yytype_uint16 yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, + 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, + 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, + 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, + 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, + 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, + 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, + 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, + 375, 376, 377, 378, 379, 380, 381, 382, 383, 384 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint16 yyr1[] = +{ + 0, 130, 131, 131, 132, 132, 132, 132, 132, 133, + 134, 134, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 136, 137, 137, 138, 138, 138, 138, 138, 139, 140, + 140, 141, 141, 141, 141, 142, 143, 144, 145, 146, + 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, + 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, + 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, + 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, + 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, + 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, + 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, + 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, + 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, + 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, + 247, 248, 249, 250, 250, 251, 251, 251, 251, 251, + 251, 251, 252, 253, 254, 255, 256, 257, 258, 259, + 260, 260, 261, 262 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 0, 2, 2, 2, 2, 2, 2, 1, + 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 0, 1, 1, 1, 1, 1, 1, 2, + 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 1, 2, 0, 1, 1, 1, 1, 1, + 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, + 2, 0, 1, 2 +}; + +/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const yytype_uint8 yydefact[] = +{ + 2, 0, 1, 9, 110, 118, 232, 249, 3, 11, + 112, 120, 234, 251, 4, 5, 6, 8, 7, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 10, 12, 13, + 69, 72, 81, 14, 20, 60, 15, 73, 74, 31, + 53, 68, 16, 17, 18, 19, 103, 104, 105, 106, + 107, 70, 59, 85, 102, 21, 22, 23, 24, 25, + 61, 75, 76, 91, 47, 57, 48, 86, 41, 42, + 43, 44, 95, 99, 96, 54, 26, 27, 28, 83, + 29, 30, 32, 33, 35, 36, 34, 37, 38, 39, + 45, 64, 100, 78, 71, 79, 80, 97, 98, 84, + 40, 62, 65, 46, 49, 87, 88, 63, 89, 50, + 51, 52, 101, 90, 58, 92, 93, 94, 55, 56, + 77, 66, 67, 82, 108, 109, 0, 0, 0, 0, + 0, 111, 113, 114, 115, 117, 116, 0, 0, 0, + 0, 119, 121, 122, 123, 124, 0, 0, 0, 0, + 0, 0, 0, 233, 235, 237, 236, 238, 239, 240, + 241, 0, 250, 252, 126, 125, 130, 133, 131, 139, + 140, 141, 142, 152, 153, 154, 155, 156, 173, 174, + 175, 177, 178, 136, 179, 180, 183, 181, 182, 184, + 185, 186, 197, 165, 166, 167, 168, 187, 200, 161, + 163, 201, 206, 207, 208, 137, 172, 215, 216, 162, + 211, 149, 132, 157, 198, 204, 188, 0, 0, 219, + 138, 127, 148, 191, 128, 134, 135, 158, 159, 217, + 190, 192, 193, 129, 220, 176, 196, 150, 164, 202, + 203, 205, 210, 160, 214, 212, 213, 169, 171, 194, + 195, 170, 189, 209, 151, 143, 144, 145, 146, 147, + 221, 222, 223, 224, 225, 227, 226, 228, 229, 230, + 231, 242, 244, 243, 245, 246, 247, 248, 253, 199, + 218 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int16 yydefgoto[] = +{ + -1, 1, 8, 9, 14, 117, 10, 15, 221, 11, + 16, 231, 118, 119, 120, 121, 122, 123, 124, 125, + 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, + 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, + 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, + 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, + 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, + 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, + 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, + 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, + 222, 223, 224, 225, 226, 232, 233, 234, 235, 12, + 17, 243, 244, 245, 246, 247, 248, 249, 250, 13, + 18, 252, 253 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -80 +static const yytype_int16 yypact[] = +{ + -80, 76, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -12, 40, 46, 32, -79, 16, + 17, 18, 22, 23, 24, 68, 71, 72, 105, 108, + 109, 118, 119, 120, 121, 122, 123, 124, 125, 126, + 127, 128, 130, 131, 132, 133, 134, 135, 136, 137, + 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, + 148, 149, 150, 151, 152, 153, 155, 156, 158, 159, + 160, 161, 163, 164, 165, 166, 167, 168, 170, 171, + 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, + 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, + 202, 203, 204, 205, 206, 207, 208, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, 209, 210, 211, 212, + 213, -80, -80, -80, -80, -80, -80, 214, 215, 216, + 217, -80, -80, -80, -80, -80, 218, 219, 220, 221, + 222, 223, 224, -80, -80, -80, -80, -80, -80, -80, + -80, 225, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, 226, 227, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yytype_int8 yypgoto[] = +{ + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -1 +static const yytype_uint16 yytable[] = +{ + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 251, 254, 255, 256, 44, + 45, 46, 257, 258, 259, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, 2, 216, 260, 217, + 218, 261, 262, 227, 88, 89, 90, 3, 91, 92, + 93, 228, 229, 94, 95, 96, 97, 98, 99, 100, + 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 4, 263, 115, 116, 264, 265, + 5, 236, 237, 238, 239, 240, 241, 242, 266, 267, + 268, 269, 270, 271, 272, 273, 274, 275, 276, 219, + 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, + 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, + 297, 298, 299, 300, 6, 301, 302, 220, 303, 304, + 305, 306, 230, 307, 308, 309, 310, 311, 312, 7, + 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, + 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, + 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, + 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, + 363, 364, 365, 366, 367, 368, 369, 370 +}; + +#define yypact_value_is_default(yystate) \ + ((yystate) == (-80)) + +#define yytable_value_is_error(yytable_value) \ + YYID (0) + +static const yytype_uint8 yycheck[] = +{ + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 104, 10, 10, 10, 41, + 42, 43, 10, 10, 10, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, 0, 37, 10, 39, + 40, 10, 10, 37, 96, 97, 98, 11, 100, 101, + 102, 45, 46, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, + 122, 123, 124, 125, 38, 10, 128, 129, 10, 10, + 44, 89, 90, 91, 92, 93, 94, 95, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 99, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 88, 10, 10, 127, 10, 10, + 10, 10, 126, 10, 10, 10, 10, 10, 10, 103, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint16 yystos[] = +{ + 0, 131, 0, 11, 38, 44, 88, 103, 132, 133, + 136, 139, 249, 259, 134, 137, 140, 250, 260, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 41, 42, 43, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 96, 97, + 98, 100, 101, 102, 105, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, + 121, 122, 123, 124, 125, 128, 129, 135, 142, 143, + 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, + 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, + 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, + 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, + 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, + 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, + 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, + 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, + 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, + 234, 235, 236, 237, 238, 239, 37, 39, 40, 99, + 127, 138, 240, 241, 242, 243, 244, 37, 45, 46, + 126, 141, 245, 246, 247, 248, 89, 90, 91, 92, + 93, 94, 95, 251, 252, 253, 254, 255, 256, 257, + 258, 104, 261, 262, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10 +}; + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. However, + YYFAIL appears to be in use. Nevertheless, it is formally deprecated + in Bison 2.4.2's NEWS entry, where a plan to phase it out is + discussed. */ + +#define YYFAIL goto yyerrlab +#if defined YYFAIL + /* This is here to suppress warnings from the GCC cpp's + -Wunused-macros. Normally we don't worry about that warning, but + some users do, and we want to make it easy for users to remove + YYFAIL uses, which will produce warnings from Bison 2.5. */ +#endif + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (1); \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (YYID (0)) + + +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (YYID (N)) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (YYID (0)) +#endif + + +/* This macro is provided for backward compatibility. */ + +#ifndef YY_LOCATION_PRINT +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +#endif + + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#ifdef YYLEX_PARAM +# define YYLEX yylex (YYLEX_PARAM) +#else +# define YYLEX yylex () +#endif + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (YYID (0)) + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (YYID (0)) + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +#else +static void +yy_symbol_value_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; +#endif +{ + if (!yyvaluep) + return; +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# else + YYUSE (yyoutput); +# endif + switch (yytype) + { + default: + break; + } +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +#else +static void +yy_symbol_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; +#endif +{ + if (yytype < YYNTOKENS) + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + yy_symbol_value_print (yyoutput, yytype, yyvaluep); + YYFPRINTF (yyoutput, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) +#else +static void +yy_stack_print (yybottom, yytop) + yytype_int16 *yybottom; + yytype_int16 *yytop; +#endif +{ + YYFPRINTF (stderr, "Stack now"); + for (; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF (stderr, " %d", yybot); + } + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (YYID (0)) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_reduce_print (YYSTYPE *yyvsp, int yyrule) +#else +static void +yy_reduce_print (yyvsp, yyrule) + YYSTYPE *yyvsp; + int yyrule; +#endif +{ + int yynrhs = yyr2[yyrule]; + int yyi; + unsigned long int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + YYFPRINTF (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], + &(yyvsp[(yyi + 1) - (yynrhs)]) + ); + YYFPRINTF (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyvsp, Rule); \ +} while (YYID (0)) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static YYSIZE_T +yystrlen (const char *yystr) +#else +static YYSIZE_T +yystrlen (yystr) + const char *yystr; +#endif +{ + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +# endif +# endif + +# ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static char * +yystpcpy (char *yydest, const char *yysrc) +#else +static char * +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +#endif +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message + about the unexpected token YYTOKEN for the state stack whose top is + YYSSP. + + Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is + not large enough to hold the message. In that case, also set + *YYMSG_ALLOC to the required number of bytes. Return 2 if the + required number of bytes is too large to store. */ +static int +yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, + yytype_int16 *yyssp, int yytoken) +{ + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + /* Internationalized format string. */ + const char *yyformat = 0; + /* Arguments of yyformat. */ + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + /* Number of reported tokens (one for the "unexpected", one per + "expected"). */ + int yycount = 0; + + /* There are many possibilities here to consider: + - Assume YYFAIL is not used. It's too flawed to consider. See + + for details. YYERROR is fine as it does not invoke this + function. + - If this state is a consistent state with a default action, then + the only way this function was invoked is if the default action + is an error action. In that case, don't check for expected + tokens because there are none. + - The only way there can be no lookahead present (in yychar) is if + this state is a consistent state with a default action. Thus, + detecting the absence of a lookahead is sufficient to determine + that there is no unexpected or expected token to report. In that + case, just report a simple "syntax error". + - Don't assume there isn't a lookahead just because this state is a + consistent state with a default action. There might have been a + previous inconsistent state, consistent state with a non-default + action, or user semantic action that manipulated yychar. + - Of course, the expected token list depends on states to have + correct lookahead information, and it depends on the parser not + to perform extra reductions after fetching a lookahead from the + scanner and before detecting a syntax error. Thus, state merging + (from LALR or IELR) and default reductions corrupt the expected + token list. However, the list is correct for canonical LR with + one exception: it will still contain any token that will not be + accepted due to an error action in a later state. + */ + if (yytoken != YYEMPTY) + { + int yyn = yypact[*yyssp]; + yyarg[yycount++] = yytname[yytoken]; + if (!yypact_value_is_default (yyn)) + { + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. In other words, skip the first -YYN actions for + this state because they are default actions. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yyx; + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR + && !yytable_value_is_error (yytable[yyx + yyn])) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + if (! (yysize <= yysize1 + && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + } + } + + switch (yycount) + { +# define YYCASE_(N, S) \ + case N: \ + yyformat = S; \ + break + YYCASE_(0, YY_("syntax error")); + YYCASE_(1, YY_("syntax error, unexpected %s")); + YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); + YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); + YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); + YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); +# undef YYCASE_ + } + + yysize1 = yysize + yystrlen (yyformat); + if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + + if (*yymsg_alloc < yysize) + { + *yymsg_alloc = 2 * yysize; + if (! (yysize <= *yymsg_alloc + && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) + *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; + return 1; + } + + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + { + char *yyp = *yymsg; + int yyi = 0; + while ((*yyp = *yyformat) != '\0') + if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyformat += 2; + } + else + { + yyp++; + yyformat++; + } + } + return 0; +} +#endif /* YYERROR_VERBOSE */ + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) +#else +static void +yydestruct (yymsg, yytype, yyvaluep) + const char *yymsg; + int yytype; + YYSTYPE *yyvaluep; +#endif +{ + YYUSE (yyvaluep); + + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + switch (yytype) + { + + default: + break; + } +} + + +/* Prevent warnings from -Wmissing-prototypes. */ +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse (void *YYPARSE_PARAM); +#else +int yyparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse (void); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + +/* The lookahead symbol. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; + +/* Number of syntax errors so far. */ +int yynerrs; + + +/*----------. +| yyparse. | +`----------*/ + +#ifdef YYPARSE_PARAM +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void *YYPARSE_PARAM) +#else +int +yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +#endif +#else /* ! YYPARSE_PARAM */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void) +#else +int +yyparse () + +#endif +#endif +{ + int yystate; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + + /* The stacks and their tools: + `yyss': related to states. + `yyvs': related to semantic values. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs; + YYSTYPE *yyvsp; + + YYSIZE_T yystacksize; + + int yyn; + int yyresult; + /* Lookahead token as an internal (translated) token number. */ + int yytoken; + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + yytoken = 0; + yyss = yyssa; + yyvs = yyvsa; + yystacksize = YYINITDEPTH; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + yyssp = yyss; + yyvsp = yyvs; + + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + if (yystate == YYFINAL) + YYACCEPT; + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + + /* Do appropriate processing given the current state. Read a + lookahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to lookahead token. */ + yyn = yypact[yystate]; + if (yypact_value_is_default (yyn)) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yytable_value_is_error (yyn)) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the lookahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token. */ + yychar = YYEMPTY; + + yystate = yyn; + *++yyvsp = yylval; + + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 9: + +/* Line 1806 of yacc.c */ +#line 118 "util/configparser.y" + { + OUTYY(("\nP(server:)\n")); + } + break; + + case 110: + +/* Line 1806 of yacc.c */ +#line 167 "util/configparser.y" + { + struct config_stub* s; + OUTYY(("\nP(stub_zone:)\n")); + s = (struct config_stub*)calloc(1, sizeof(struct config_stub)); + if(s) { + s->next = cfg_parser->cfg->stubs; + cfg_parser->cfg->stubs = s; + } else + yyerror("out of memory"); + } + break; + + case 118: + +/* Line 1806 of yacc.c */ +#line 183 "util/configparser.y" + { + struct config_stub* s; + OUTYY(("\nP(forward_zone:)\n")); + s = (struct config_stub*)calloc(1, sizeof(struct config_stub)); + if(s) { + s->next = cfg_parser->cfg->forwards; + cfg_parser->cfg->forwards = s; + } else + yyerror("out of memory"); + } + break; + + case 125: + +/* Line 1806 of yacc.c */ +#line 199 "util/configparser.y" + { + OUTYY(("P(server_num_threads:%s)\n", (yyvsp[(2) - (2)].str))); + if(atoi((yyvsp[(2) - (2)].str)) == 0 && strcmp((yyvsp[(2) - (2)].str), "0") != 0) + yyerror("number expected"); + else cfg_parser->cfg->num_threads = atoi((yyvsp[(2) - (2)].str)); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 126: + +/* Line 1806 of yacc.c */ +#line 208 "util/configparser.y" + { + OUTYY(("P(server_verbosity:%s)\n", (yyvsp[(2) - (2)].str))); + if(atoi((yyvsp[(2) - (2)].str)) == 0 && strcmp((yyvsp[(2) - (2)].str), "0") != 0) + yyerror("number expected"); + else cfg_parser->cfg->verbosity = atoi((yyvsp[(2) - (2)].str)); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 127: + +/* Line 1806 of yacc.c */ +#line 217 "util/configparser.y" + { + OUTYY(("P(server_statistics_interval:%s)\n", (yyvsp[(2) - (2)].str))); + if(strcmp((yyvsp[(2) - (2)].str), "") == 0 || strcmp((yyvsp[(2) - (2)].str), "0") == 0) + cfg_parser->cfg->stat_interval = 0; + else if(atoi((yyvsp[(2) - (2)].str)) == 0) + yyerror("number expected"); + else cfg_parser->cfg->stat_interval = atoi((yyvsp[(2) - (2)].str)); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 128: + +/* Line 1806 of yacc.c */ +#line 228 "util/configparser.y" + { + OUTYY(("P(server_statistics_cumulative:%s)\n", (yyvsp[(2) - (2)].str))); + if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->stat_cumulative = (strcmp((yyvsp[(2) - (2)].str), "yes")==0); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 129: + +/* Line 1806 of yacc.c */ +#line 237 "util/configparser.y" + { + OUTYY(("P(server_extended_statistics:%s)\n", (yyvsp[(2) - (2)].str))); + if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->stat_extended = (strcmp((yyvsp[(2) - (2)].str), "yes")==0); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 130: + +/* Line 1806 of yacc.c */ +#line 246 "util/configparser.y" + { + OUTYY(("P(server_port:%s)\n", (yyvsp[(2) - (2)].str))); + if(atoi((yyvsp[(2) - (2)].str)) == 0) + yyerror("port number expected"); + else cfg_parser->cfg->port = atoi((yyvsp[(2) - (2)].str)); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 131: + +/* Line 1806 of yacc.c */ +#line 255 "util/configparser.y" + { + OUTYY(("P(server_interface:%s)\n", (yyvsp[(2) - (2)].str))); + if(cfg_parser->cfg->num_ifs == 0) + cfg_parser->cfg->ifs = calloc(1, sizeof(char*)); + else cfg_parser->cfg->ifs = realloc(cfg_parser->cfg->ifs, + (cfg_parser->cfg->num_ifs+1)*sizeof(char*)); + if(!cfg_parser->cfg->ifs) + yyerror("out of memory"); + else + cfg_parser->cfg->ifs[cfg_parser->cfg->num_ifs++] = (yyvsp[(2) - (2)].str); + } + break; + + case 132: + +/* Line 1806 of yacc.c */ +#line 268 "util/configparser.y" + { + OUTYY(("P(server_outgoing_interface:%s)\n", (yyvsp[(2) - (2)].str))); + if(cfg_parser->cfg->num_out_ifs == 0) + cfg_parser->cfg->out_ifs = calloc(1, sizeof(char*)); + else cfg_parser->cfg->out_ifs = realloc( + cfg_parser->cfg->out_ifs, + (cfg_parser->cfg->num_out_ifs+1)*sizeof(char*)); + if(!cfg_parser->cfg->out_ifs) + yyerror("out of memory"); + else + cfg_parser->cfg->out_ifs[ + cfg_parser->cfg->num_out_ifs++] = (yyvsp[(2) - (2)].str); + } + break; + + case 133: + +/* Line 1806 of yacc.c */ +#line 283 "util/configparser.y" + { + OUTYY(("P(server_outgoing_range:%s)\n", (yyvsp[(2) - (2)].str))); + if(atoi((yyvsp[(2) - (2)].str)) == 0) + yyerror("number expected"); + else cfg_parser->cfg->outgoing_num_ports = atoi((yyvsp[(2) - (2)].str)); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 134: + +/* Line 1806 of yacc.c */ +#line 292 "util/configparser.y" + { + OUTYY(("P(server_outgoing_port_permit:%s)\n", (yyvsp[(2) - (2)].str))); + if(!cfg_mark_ports((yyvsp[(2) - (2)].str), 1, + cfg_parser->cfg->outgoing_avail_ports, 65536)) + yyerror("port number or range (\"low-high\") expected"); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 135: + +/* Line 1806 of yacc.c */ +#line 301 "util/configparser.y" + { + OUTYY(("P(server_outgoing_port_avoid:%s)\n", (yyvsp[(2) - (2)].str))); + if(!cfg_mark_ports((yyvsp[(2) - (2)].str), 0, + cfg_parser->cfg->outgoing_avail_ports, 65536)) + yyerror("port number or range (\"low-high\") expected"); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 136: + +/* Line 1806 of yacc.c */ +#line 310 "util/configparser.y" + { + OUTYY(("P(server_outgoing_num_tcp:%s)\n", (yyvsp[(2) - (2)].str))); + if(atoi((yyvsp[(2) - (2)].str)) == 0 && strcmp((yyvsp[(2) - (2)].str), "0") != 0) + yyerror("number expected"); + else cfg_parser->cfg->outgoing_num_tcp = atoi((yyvsp[(2) - (2)].str)); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 137: + +/* Line 1806 of yacc.c */ +#line 319 "util/configparser.y" + { + OUTYY(("P(server_incoming_num_tcp:%s)\n", (yyvsp[(2) - (2)].str))); + if(atoi((yyvsp[(2) - (2)].str)) == 0 && strcmp((yyvsp[(2) - (2)].str), "0") != 0) + yyerror("number expected"); + else cfg_parser->cfg->incoming_num_tcp = atoi((yyvsp[(2) - (2)].str)); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 138: + +/* Line 1806 of yacc.c */ +#line 328 "util/configparser.y" + { + OUTYY(("P(server_interface_automatic:%s)\n", (yyvsp[(2) - (2)].str))); + if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->if_automatic = (strcmp((yyvsp[(2) - (2)].str), "yes")==0); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 139: + +/* Line 1806 of yacc.c */ +#line 337 "util/configparser.y" + { + OUTYY(("P(server_do_ip4:%s)\n", (yyvsp[(2) - (2)].str))); + if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->do_ip4 = (strcmp((yyvsp[(2) - (2)].str), "yes")==0); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 140: + +/* Line 1806 of yacc.c */ +#line 346 "util/configparser.y" + { + OUTYY(("P(server_do_ip6:%s)\n", (yyvsp[(2) - (2)].str))); + if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->do_ip6 = (strcmp((yyvsp[(2) - (2)].str), "yes")==0); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 141: + +/* Line 1806 of yacc.c */ +#line 355 "util/configparser.y" + { + OUTYY(("P(server_do_udp:%s)\n", (yyvsp[(2) - (2)].str))); + if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->do_udp = (strcmp((yyvsp[(2) - (2)].str), "yes")==0); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 142: + +/* Line 1806 of yacc.c */ +#line 364 "util/configparser.y" + { + OUTYY(("P(server_do_tcp:%s)\n", (yyvsp[(2) - (2)].str))); + if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->do_tcp = (strcmp((yyvsp[(2) - (2)].str), "yes")==0); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 143: + +/* Line 1806 of yacc.c */ +#line 373 "util/configparser.y" + { + OUTYY(("P(server_tcp_upstream:%s)\n", (yyvsp[(2) - (2)].str))); + if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->tcp_upstream = (strcmp((yyvsp[(2) - (2)].str), "yes")==0); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 144: + +/* Line 1806 of yacc.c */ +#line 382 "util/configparser.y" + { + OUTYY(("P(server_ssl_upstream:%s)\n", (yyvsp[(2) - (2)].str))); + if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->ssl_upstream = (strcmp((yyvsp[(2) - (2)].str), "yes")==0); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 145: + +/* Line 1806 of yacc.c */ +#line 391 "util/configparser.y" + { + OUTYY(("P(server_ssl_service_key:%s)\n", (yyvsp[(2) - (2)].str))); + free(cfg_parser->cfg->ssl_service_key); + cfg_parser->cfg->ssl_service_key = (yyvsp[(2) - (2)].str); + } + break; + + case 146: + +/* Line 1806 of yacc.c */ +#line 398 "util/configparser.y" + { + OUTYY(("P(server_ssl_service_pem:%s)\n", (yyvsp[(2) - (2)].str))); + free(cfg_parser->cfg->ssl_service_pem); + cfg_parser->cfg->ssl_service_pem = (yyvsp[(2) - (2)].str); + } + break; + + case 147: + +/* Line 1806 of yacc.c */ +#line 405 "util/configparser.y" + { + OUTYY(("P(server_ssl_port:%s)\n", (yyvsp[(2) - (2)].str))); + if(atoi((yyvsp[(2) - (2)].str)) == 0) + yyerror("port number expected"); + else cfg_parser->cfg->ssl_port = atoi((yyvsp[(2) - (2)].str)); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 148: + +/* Line 1806 of yacc.c */ +#line 414 "util/configparser.y" + { + OUTYY(("P(server_do_daemonize:%s)\n", (yyvsp[(2) - (2)].str))); + if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->do_daemonize = (strcmp((yyvsp[(2) - (2)].str), "yes")==0); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 149: + +/* Line 1806 of yacc.c */ +#line 423 "util/configparser.y" + { + OUTYY(("P(server_use_syslog:%s)\n", (yyvsp[(2) - (2)].str))); + if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->use_syslog = (strcmp((yyvsp[(2) - (2)].str), "yes")==0); +#if !defined(HAVE_SYSLOG_H) && !defined(UB_ON_WINDOWS) + if(strcmp((yyvsp[(2) - (2)].str), "yes") == 0) + yyerror("no syslog services are available. " + "(reconfigure and compile to add)"); +#endif + free((yyvsp[(2) - (2)].str)); + } + break; + + case 150: + +/* Line 1806 of yacc.c */ +#line 437 "util/configparser.y" + { + OUTYY(("P(server_log_time_ascii:%s)\n", (yyvsp[(2) - (2)].str))); + if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->log_time_ascii = (strcmp((yyvsp[(2) - (2)].str), "yes")==0); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 151: + +/* Line 1806 of yacc.c */ +#line 446 "util/configparser.y" + { + OUTYY(("P(server_log_queries:%s)\n", (yyvsp[(2) - (2)].str))); + if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->log_queries = (strcmp((yyvsp[(2) - (2)].str), "yes")==0); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 152: + +/* Line 1806 of yacc.c */ +#line 455 "util/configparser.y" + { + OUTYY(("P(server_chroot:%s)\n", (yyvsp[(2) - (2)].str))); + free(cfg_parser->cfg->chrootdir); + cfg_parser->cfg->chrootdir = (yyvsp[(2) - (2)].str); + } + break; + + case 153: + +/* Line 1806 of yacc.c */ +#line 462 "util/configparser.y" + { + OUTYY(("P(server_username:%s)\n", (yyvsp[(2) - (2)].str))); + free(cfg_parser->cfg->username); + cfg_parser->cfg->username = (yyvsp[(2) - (2)].str); + } + break; + + case 154: + +/* Line 1806 of yacc.c */ +#line 469 "util/configparser.y" + { + OUTYY(("P(server_directory:%s)\n", (yyvsp[(2) - (2)].str))); + free(cfg_parser->cfg->directory); + cfg_parser->cfg->directory = (yyvsp[(2) - (2)].str); + } + break; + + case 155: + +/* Line 1806 of yacc.c */ +#line 476 "util/configparser.y" + { + OUTYY(("P(server_logfile:%s)\n", (yyvsp[(2) - (2)].str))); + free(cfg_parser->cfg->logfile); + cfg_parser->cfg->logfile = (yyvsp[(2) - (2)].str); + cfg_parser->cfg->use_syslog = 0; + } + break; + + case 156: + +/* Line 1806 of yacc.c */ +#line 484 "util/configparser.y" + { + OUTYY(("P(server_pidfile:%s)\n", (yyvsp[(2) - (2)].str))); + free(cfg_parser->cfg->pidfile); + cfg_parser->cfg->pidfile = (yyvsp[(2) - (2)].str); + } + break; + + case 157: + +/* Line 1806 of yacc.c */ +#line 491 "util/configparser.y" + { + OUTYY(("P(server_root_hints:%s)\n", (yyvsp[(2) - (2)].str))); + if(!cfg_strlist_insert(&cfg_parser->cfg->root_hints, (yyvsp[(2) - (2)].str))) + yyerror("out of memory"); + } + break; + + case 158: + +/* Line 1806 of yacc.c */ +#line 498 "util/configparser.y" + { + OUTYY(("P(server_dlv_anchor_file:%s)\n", (yyvsp[(2) - (2)].str))); + free(cfg_parser->cfg->dlv_anchor_file); + cfg_parser->cfg->dlv_anchor_file = (yyvsp[(2) - (2)].str); + } + break; + + case 159: + +/* Line 1806 of yacc.c */ +#line 505 "util/configparser.y" + { + OUTYY(("P(server_dlv_anchor:%s)\n", (yyvsp[(2) - (2)].str))); + if(!cfg_strlist_insert(&cfg_parser->cfg->dlv_anchor_list, (yyvsp[(2) - (2)].str))) + yyerror("out of memory"); + } + break; + + case 160: + +/* Line 1806 of yacc.c */ +#line 512 "util/configparser.y" + { + OUTYY(("P(server_auto_trust_anchor_file:%s)\n", (yyvsp[(2) - (2)].str))); + if(!cfg_strlist_insert(&cfg_parser->cfg-> + auto_trust_anchor_file_list, (yyvsp[(2) - (2)].str))) + yyerror("out of memory"); + } + break; + + case 161: + +/* Line 1806 of yacc.c */ +#line 520 "util/configparser.y" + { + OUTYY(("P(server_trust_anchor_file:%s)\n", (yyvsp[(2) - (2)].str))); + if(!cfg_strlist_insert(&cfg_parser->cfg-> + trust_anchor_file_list, (yyvsp[(2) - (2)].str))) + yyerror("out of memory"); + } + break; + + case 162: + +/* Line 1806 of yacc.c */ +#line 528 "util/configparser.y" + { + OUTYY(("P(server_trusted_keys_file:%s)\n", (yyvsp[(2) - (2)].str))); + if(!cfg_strlist_insert(&cfg_parser->cfg-> + trusted_keys_file_list, (yyvsp[(2) - (2)].str))) + yyerror("out of memory"); + } + break; + + case 163: + +/* Line 1806 of yacc.c */ +#line 536 "util/configparser.y" + { + OUTYY(("P(server_trust_anchor:%s)\n", (yyvsp[(2) - (2)].str))); + if(!cfg_strlist_insert(&cfg_parser->cfg->trust_anchor_list, (yyvsp[(2) - (2)].str))) + yyerror("out of memory"); + } + break; + + case 164: + +/* Line 1806 of yacc.c */ +#line 543 "util/configparser.y" + { + OUTYY(("P(server_domain_insecure:%s)\n", (yyvsp[(2) - (2)].str))); + if(!cfg_strlist_insert(&cfg_parser->cfg->domain_insecure, (yyvsp[(2) - (2)].str))) + yyerror("out of memory"); + } + break; + + case 165: + +/* Line 1806 of yacc.c */ +#line 550 "util/configparser.y" + { + OUTYY(("P(server_hide_identity:%s)\n", (yyvsp[(2) - (2)].str))); + if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->hide_identity = (strcmp((yyvsp[(2) - (2)].str), "yes")==0); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 166: + +/* Line 1806 of yacc.c */ +#line 559 "util/configparser.y" + { + OUTYY(("P(server_hide_version:%s)\n", (yyvsp[(2) - (2)].str))); + if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->hide_version = (strcmp((yyvsp[(2) - (2)].str), "yes")==0); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 167: + +/* Line 1806 of yacc.c */ +#line 568 "util/configparser.y" + { + OUTYY(("P(server_identity:%s)\n", (yyvsp[(2) - (2)].str))); + free(cfg_parser->cfg->identity); + cfg_parser->cfg->identity = (yyvsp[(2) - (2)].str); + } + break; + + case 168: + +/* Line 1806 of yacc.c */ +#line 575 "util/configparser.y" + { + OUTYY(("P(server_version:%s)\n", (yyvsp[(2) - (2)].str))); + free(cfg_parser->cfg->version); + cfg_parser->cfg->version = (yyvsp[(2) - (2)].str); + } + break; + + case 169: + +/* Line 1806 of yacc.c */ +#line 582 "util/configparser.y" + { + OUTYY(("P(server_so_rcvbuf:%s)\n", (yyvsp[(2) - (2)].str))); + if(!cfg_parse_memsize((yyvsp[(2) - (2)].str), &cfg_parser->cfg->so_rcvbuf)) + yyerror("buffer size expected"); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 170: + +/* Line 1806 of yacc.c */ +#line 590 "util/configparser.y" + { + OUTYY(("P(server_so_sndbuf:%s)\n", (yyvsp[(2) - (2)].str))); + if(!cfg_parse_memsize((yyvsp[(2) - (2)].str), &cfg_parser->cfg->so_sndbuf)) + yyerror("buffer size expected"); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 171: + +/* Line 1806 of yacc.c */ +#line 598 "util/configparser.y" + { + OUTYY(("P(server_edns_buffer_size:%s)\n", (yyvsp[(2) - (2)].str))); + if(atoi((yyvsp[(2) - (2)].str)) == 0) + yyerror("number expected"); + else if (atoi((yyvsp[(2) - (2)].str)) < 12) + yyerror("edns buffer size too small"); + else if (atoi((yyvsp[(2) - (2)].str)) > 65535) + cfg_parser->cfg->edns_buffer_size = 65535; + else cfg_parser->cfg->edns_buffer_size = atoi((yyvsp[(2) - (2)].str)); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 172: + +/* Line 1806 of yacc.c */ +#line 611 "util/configparser.y" + { + OUTYY(("P(server_msg_buffer_size:%s)\n", (yyvsp[(2) - (2)].str))); + if(atoi((yyvsp[(2) - (2)].str)) == 0) + yyerror("number expected"); + else if (atoi((yyvsp[(2) - (2)].str)) < 4096) + yyerror("message buffer size too small (use 4096)"); + else cfg_parser->cfg->msg_buffer_size = atoi((yyvsp[(2) - (2)].str)); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 173: + +/* Line 1806 of yacc.c */ +#line 622 "util/configparser.y" + { + OUTYY(("P(server_msg_cache_size:%s)\n", (yyvsp[(2) - (2)].str))); + if(!cfg_parse_memsize((yyvsp[(2) - (2)].str), &cfg_parser->cfg->msg_cache_size)) + yyerror("memory size expected"); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 174: + +/* Line 1806 of yacc.c */ +#line 630 "util/configparser.y" + { + OUTYY(("P(server_msg_cache_slabs:%s)\n", (yyvsp[(2) - (2)].str))); + if(atoi((yyvsp[(2) - (2)].str)) == 0) + yyerror("number expected"); + else { + cfg_parser->cfg->msg_cache_slabs = atoi((yyvsp[(2) - (2)].str)); + if(!is_pow2(cfg_parser->cfg->msg_cache_slabs)) + yyerror("must be a power of 2"); + } + free((yyvsp[(2) - (2)].str)); + } + break; + + case 175: + +/* Line 1806 of yacc.c */ +#line 643 "util/configparser.y" + { + OUTYY(("P(server_num_queries_per_thread:%s)\n", (yyvsp[(2) - (2)].str))); + if(atoi((yyvsp[(2) - (2)].str)) == 0) + yyerror("number expected"); + else cfg_parser->cfg->num_queries_per_thread = atoi((yyvsp[(2) - (2)].str)); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 176: + +/* Line 1806 of yacc.c */ +#line 652 "util/configparser.y" + { + OUTYY(("P(server_jostle_timeout:%s)\n", (yyvsp[(2) - (2)].str))); + if(atoi((yyvsp[(2) - (2)].str)) == 0 && strcmp((yyvsp[(2) - (2)].str), "0") != 0) + yyerror("number expected"); + else cfg_parser->cfg->jostle_time = atoi((yyvsp[(2) - (2)].str)); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 177: + +/* Line 1806 of yacc.c */ +#line 661 "util/configparser.y" + { + OUTYY(("P(server_rrset_cache_size:%s)\n", (yyvsp[(2) - (2)].str))); + if(!cfg_parse_memsize((yyvsp[(2) - (2)].str), &cfg_parser->cfg->rrset_cache_size)) + yyerror("memory size expected"); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 178: + +/* Line 1806 of yacc.c */ +#line 669 "util/configparser.y" + { + OUTYY(("P(server_rrset_cache_slabs:%s)\n", (yyvsp[(2) - (2)].str))); + if(atoi((yyvsp[(2) - (2)].str)) == 0) + yyerror("number expected"); + else { + cfg_parser->cfg->rrset_cache_slabs = atoi((yyvsp[(2) - (2)].str)); + if(!is_pow2(cfg_parser->cfg->rrset_cache_slabs)) + yyerror("must be a power of 2"); + } + free((yyvsp[(2) - (2)].str)); + } + break; + + case 179: + +/* Line 1806 of yacc.c */ +#line 682 "util/configparser.y" + { + OUTYY(("P(server_infra_host_ttl:%s)\n", (yyvsp[(2) - (2)].str))); + if(atoi((yyvsp[(2) - (2)].str)) == 0 && strcmp((yyvsp[(2) - (2)].str), "0") != 0) + yyerror("number expected"); + else cfg_parser->cfg->host_ttl = atoi((yyvsp[(2) - (2)].str)); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 180: + +/* Line 1806 of yacc.c */ +#line 691 "util/configparser.y" + { + OUTYY(("P(server_infra_lame_ttl:%s)\n", (yyvsp[(2) - (2)].str))); + verbose(VERB_DETAIL, "ignored infra-lame-ttl: %s (option " + "removed, use infra-host-ttl)", (yyvsp[(2) - (2)].str)); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 181: + +/* Line 1806 of yacc.c */ +#line 699 "util/configparser.y" + { + OUTYY(("P(server_infra_cache_numhosts:%s)\n", (yyvsp[(2) - (2)].str))); + if(atoi((yyvsp[(2) - (2)].str)) == 0) + yyerror("number expected"); + else cfg_parser->cfg->infra_cache_numhosts = atoi((yyvsp[(2) - (2)].str)); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 182: + +/* Line 1806 of yacc.c */ +#line 708 "util/configparser.y" + { + OUTYY(("P(server_infra_cache_lame_size:%s)\n", (yyvsp[(2) - (2)].str))); + verbose(VERB_DETAIL, "ignored infra-cache-lame-size: %s " + "(option removed, use infra-cache-numhosts)", (yyvsp[(2) - (2)].str)); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 183: + +/* Line 1806 of yacc.c */ +#line 716 "util/configparser.y" + { + OUTYY(("P(server_infra_cache_slabs:%s)\n", (yyvsp[(2) - (2)].str))); + if(atoi((yyvsp[(2) - (2)].str)) == 0) + yyerror("number expected"); + else { + cfg_parser->cfg->infra_cache_slabs = atoi((yyvsp[(2) - (2)].str)); + if(!is_pow2(cfg_parser->cfg->infra_cache_slabs)) + yyerror("must be a power of 2"); + } + free((yyvsp[(2) - (2)].str)); + } + break; + + case 184: + +/* Line 1806 of yacc.c */ +#line 729 "util/configparser.y" + { + OUTYY(("P(server_target_fetch_policy:%s)\n", (yyvsp[(2) - (2)].str))); + free(cfg_parser->cfg->target_fetch_policy); + cfg_parser->cfg->target_fetch_policy = (yyvsp[(2) - (2)].str); + } + break; + + case 185: + +/* Line 1806 of yacc.c */ +#line 736 "util/configparser.y" + { + OUTYY(("P(server_harden_short_bufsize:%s)\n", (yyvsp[(2) - (2)].str))); + if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->harden_short_bufsize = + (strcmp((yyvsp[(2) - (2)].str), "yes")==0); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 186: + +/* Line 1806 of yacc.c */ +#line 746 "util/configparser.y" + { + OUTYY(("P(server_harden_large_queries:%s)\n", (yyvsp[(2) - (2)].str))); + if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->harden_large_queries = + (strcmp((yyvsp[(2) - (2)].str), "yes")==0); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 187: + +/* Line 1806 of yacc.c */ +#line 756 "util/configparser.y" + { + OUTYY(("P(server_harden_glue:%s)\n", (yyvsp[(2) - (2)].str))); + if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->harden_glue = + (strcmp((yyvsp[(2) - (2)].str), "yes")==0); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 188: + +/* Line 1806 of yacc.c */ +#line 766 "util/configparser.y" + { + OUTYY(("P(server_harden_dnssec_stripped:%s)\n", (yyvsp[(2) - (2)].str))); + if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->harden_dnssec_stripped = + (strcmp((yyvsp[(2) - (2)].str), "yes")==0); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 189: + +/* Line 1806 of yacc.c */ +#line 776 "util/configparser.y" + { + OUTYY(("P(server_harden_below_nxdomain:%s)\n", (yyvsp[(2) - (2)].str))); + if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->harden_below_nxdomain = + (strcmp((yyvsp[(2) - (2)].str), "yes")==0); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 190: + +/* Line 1806 of yacc.c */ +#line 786 "util/configparser.y" + { + OUTYY(("P(server_harden_referral_path:%s)\n", (yyvsp[(2) - (2)].str))); + if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->harden_referral_path = + (strcmp((yyvsp[(2) - (2)].str), "yes")==0); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 191: + +/* Line 1806 of yacc.c */ +#line 796 "util/configparser.y" + { + OUTYY(("P(server_use_caps_for_id:%s)\n", (yyvsp[(2) - (2)].str))); + if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->use_caps_bits_for_id = + (strcmp((yyvsp[(2) - (2)].str), "yes")==0); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 192: + +/* Line 1806 of yacc.c */ +#line 806 "util/configparser.y" + { + OUTYY(("P(server_private_address:%s)\n", (yyvsp[(2) - (2)].str))); + if(!cfg_strlist_insert(&cfg_parser->cfg->private_address, (yyvsp[(2) - (2)].str))) + yyerror("out of memory"); + } + break; + + case 193: + +/* Line 1806 of yacc.c */ +#line 813 "util/configparser.y" + { + OUTYY(("P(server_private_domain:%s)\n", (yyvsp[(2) - (2)].str))); + if(!cfg_strlist_insert(&cfg_parser->cfg->private_domain, (yyvsp[(2) - (2)].str))) + yyerror("out of memory"); + } + break; + + case 194: + +/* Line 1806 of yacc.c */ +#line 820 "util/configparser.y" + { + OUTYY(("P(server_prefetch:%s)\n", (yyvsp[(2) - (2)].str))); + if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->prefetch = (strcmp((yyvsp[(2) - (2)].str), "yes")==0); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 195: + +/* Line 1806 of yacc.c */ +#line 829 "util/configparser.y" + { + OUTYY(("P(server_prefetch_key:%s)\n", (yyvsp[(2) - (2)].str))); + if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->prefetch_key = (strcmp((yyvsp[(2) - (2)].str), "yes")==0); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 196: + +/* Line 1806 of yacc.c */ +#line 838 "util/configparser.y" + { + OUTYY(("P(server_unwanted_reply_threshold:%s)\n", (yyvsp[(2) - (2)].str))); + if(atoi((yyvsp[(2) - (2)].str)) == 0 && strcmp((yyvsp[(2) - (2)].str), "0") != 0) + yyerror("number expected"); + else cfg_parser->cfg->unwanted_threshold = atoi((yyvsp[(2) - (2)].str)); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 197: + +/* Line 1806 of yacc.c */ +#line 847 "util/configparser.y" + { + OUTYY(("P(server_do_not_query_address:%s)\n", (yyvsp[(2) - (2)].str))); + if(!cfg_strlist_insert(&cfg_parser->cfg->donotqueryaddrs, (yyvsp[(2) - (2)].str))) + yyerror("out of memory"); + } + break; + + case 198: + +/* Line 1806 of yacc.c */ +#line 854 "util/configparser.y" + { + OUTYY(("P(server_do_not_query_localhost:%s)\n", (yyvsp[(2) - (2)].str))); + if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->donotquery_localhost = + (strcmp((yyvsp[(2) - (2)].str), "yes")==0); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 199: + +/* Line 1806 of yacc.c */ +#line 864 "util/configparser.y" + { + OUTYY(("P(server_access_control:%s %s)\n", (yyvsp[(2) - (3)].str), (yyvsp[(3) - (3)].str))); + if(strcmp((yyvsp[(3) - (3)].str), "deny")!=0 && strcmp((yyvsp[(3) - (3)].str), "refuse")!=0 && + strcmp((yyvsp[(3) - (3)].str), "allow")!=0 && + strcmp((yyvsp[(3) - (3)].str), "allow_snoop")!=0) { + yyerror("expected deny, refuse, allow or allow_snoop " + "in access control action"); + } else { + if(!cfg_str2list_insert(&cfg_parser->cfg->acls, (yyvsp[(2) - (3)].str), (yyvsp[(3) - (3)].str))) + fatal_exit("out of memory adding acl"); + } + } + break; + + case 200: + +/* Line 1806 of yacc.c */ +#line 878 "util/configparser.y" + { + OUTYY(("P(server_module_conf:%s)\n", (yyvsp[(2) - (2)].str))); + free(cfg_parser->cfg->module_conf); + cfg_parser->cfg->module_conf = (yyvsp[(2) - (2)].str); + } + break; + + case 201: + +/* Line 1806 of yacc.c */ +#line 885 "util/configparser.y" + { + OUTYY(("P(server_val_override_date:%s)\n", (yyvsp[(2) - (2)].str))); + if(strlen((yyvsp[(2) - (2)].str)) == 0 || strcmp((yyvsp[(2) - (2)].str), "0") == 0) { + cfg_parser->cfg->val_date_override = 0; + } else if(strlen((yyvsp[(2) - (2)].str)) == 14) { + cfg_parser->cfg->val_date_override = + cfg_convert_timeval((yyvsp[(2) - (2)].str)); + if(!cfg_parser->cfg->val_date_override) + yyerror("bad date/time specification"); + } else { + if(atoi((yyvsp[(2) - (2)].str)) == 0) + yyerror("number expected"); + cfg_parser->cfg->val_date_override = atoi((yyvsp[(2) - (2)].str)); + } + free((yyvsp[(2) - (2)].str)); + } + break; + + case 202: + +/* Line 1806 of yacc.c */ +#line 903 "util/configparser.y" + { + OUTYY(("P(server_val_sig_skew_min:%s)\n", (yyvsp[(2) - (2)].str))); + if(strlen((yyvsp[(2) - (2)].str)) == 0 || strcmp((yyvsp[(2) - (2)].str), "0") == 0) { + cfg_parser->cfg->val_sig_skew_min = 0; + } else { + cfg_parser->cfg->val_sig_skew_min = atoi((yyvsp[(2) - (2)].str)); + if(!cfg_parser->cfg->val_sig_skew_min) + yyerror("number expected"); + } + free((yyvsp[(2) - (2)].str)); + } + break; + + case 203: + +/* Line 1806 of yacc.c */ +#line 916 "util/configparser.y" + { + OUTYY(("P(server_val_sig_skew_max:%s)\n", (yyvsp[(2) - (2)].str))); + if(strlen((yyvsp[(2) - (2)].str)) == 0 || strcmp((yyvsp[(2) - (2)].str), "0") == 0) { + cfg_parser->cfg->val_sig_skew_max = 0; + } else { + cfg_parser->cfg->val_sig_skew_max = atoi((yyvsp[(2) - (2)].str)); + if(!cfg_parser->cfg->val_sig_skew_max) + yyerror("number expected"); + } + free((yyvsp[(2) - (2)].str)); + } + break; + + case 204: + +/* Line 1806 of yacc.c */ +#line 929 "util/configparser.y" + { + OUTYY(("P(server_cache_max_ttl:%s)\n", (yyvsp[(2) - (2)].str))); + if(atoi((yyvsp[(2) - (2)].str)) == 0 && strcmp((yyvsp[(2) - (2)].str), "0") != 0) + yyerror("number expected"); + else cfg_parser->cfg->max_ttl = atoi((yyvsp[(2) - (2)].str)); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 205: + +/* Line 1806 of yacc.c */ +#line 938 "util/configparser.y" + { + OUTYY(("P(server_cache_min_ttl:%s)\n", (yyvsp[(2) - (2)].str))); + if(atoi((yyvsp[(2) - (2)].str)) == 0 && strcmp((yyvsp[(2) - (2)].str), "0") != 0) + yyerror("number expected"); + else cfg_parser->cfg->min_ttl = atoi((yyvsp[(2) - (2)].str)); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 206: + +/* Line 1806 of yacc.c */ +#line 947 "util/configparser.y" + { + OUTYY(("P(server_bogus_ttl:%s)\n", (yyvsp[(2) - (2)].str))); + if(atoi((yyvsp[(2) - (2)].str)) == 0 && strcmp((yyvsp[(2) - (2)].str), "0") != 0) + yyerror("number expected"); + else cfg_parser->cfg->bogus_ttl = atoi((yyvsp[(2) - (2)].str)); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 207: + +/* Line 1806 of yacc.c */ +#line 956 "util/configparser.y" + { + OUTYY(("P(server_val_clean_additional:%s)\n", (yyvsp[(2) - (2)].str))); + if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->val_clean_additional = + (strcmp((yyvsp[(2) - (2)].str), "yes")==0); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 208: + +/* Line 1806 of yacc.c */ +#line 966 "util/configparser.y" + { + OUTYY(("P(server_val_permissive_mode:%s)\n", (yyvsp[(2) - (2)].str))); + if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->val_permissive_mode = + (strcmp((yyvsp[(2) - (2)].str), "yes")==0); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 209: + +/* Line 1806 of yacc.c */ +#line 976 "util/configparser.y" + { + OUTYY(("P(server_ignore_cd_flag:%s)\n", (yyvsp[(2) - (2)].str))); + if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->ignore_cd = (strcmp((yyvsp[(2) - (2)].str), "yes")==0); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 210: + +/* Line 1806 of yacc.c */ +#line 985 "util/configparser.y" + { + OUTYY(("P(server_val_log_level:%s)\n", (yyvsp[(2) - (2)].str))); + if(atoi((yyvsp[(2) - (2)].str)) == 0 && strcmp((yyvsp[(2) - (2)].str), "0") != 0) + yyerror("number expected"); + else cfg_parser->cfg->val_log_level = atoi((yyvsp[(2) - (2)].str)); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 211: + +/* Line 1806 of yacc.c */ +#line 994 "util/configparser.y" + { + OUTYY(("P(server_val_nsec3_keysize_iterations:%s)\n", (yyvsp[(2) - (2)].str))); + free(cfg_parser->cfg->val_nsec3_key_iterations); + cfg_parser->cfg->val_nsec3_key_iterations = (yyvsp[(2) - (2)].str); + } + break; + + case 212: + +/* Line 1806 of yacc.c */ +#line 1001 "util/configparser.y" + { + OUTYY(("P(server_add_holddown:%s)\n", (yyvsp[(2) - (2)].str))); + if(atoi((yyvsp[(2) - (2)].str)) == 0 && strcmp((yyvsp[(2) - (2)].str), "0") != 0) + yyerror("number expected"); + else cfg_parser->cfg->add_holddown = atoi((yyvsp[(2) - (2)].str)); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 213: + +/* Line 1806 of yacc.c */ +#line 1010 "util/configparser.y" + { + OUTYY(("P(server_del_holddown:%s)\n", (yyvsp[(2) - (2)].str))); + if(atoi((yyvsp[(2) - (2)].str)) == 0 && strcmp((yyvsp[(2) - (2)].str), "0") != 0) + yyerror("number expected"); + else cfg_parser->cfg->del_holddown = atoi((yyvsp[(2) - (2)].str)); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 214: + +/* Line 1806 of yacc.c */ +#line 1019 "util/configparser.y" + { + OUTYY(("P(server_keep_missing:%s)\n", (yyvsp[(2) - (2)].str))); + if(atoi((yyvsp[(2) - (2)].str)) == 0 && strcmp((yyvsp[(2) - (2)].str), "0") != 0) + yyerror("number expected"); + else cfg_parser->cfg->keep_missing = atoi((yyvsp[(2) - (2)].str)); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 215: + +/* Line 1806 of yacc.c */ +#line 1028 "util/configparser.y" + { + OUTYY(("P(server_key_cache_size:%s)\n", (yyvsp[(2) - (2)].str))); + if(!cfg_parse_memsize((yyvsp[(2) - (2)].str), &cfg_parser->cfg->key_cache_size)) + yyerror("memory size expected"); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 216: + +/* Line 1806 of yacc.c */ +#line 1036 "util/configparser.y" + { + OUTYY(("P(server_key_cache_slabs:%s)\n", (yyvsp[(2) - (2)].str))); + if(atoi((yyvsp[(2) - (2)].str)) == 0) + yyerror("number expected"); + else { + cfg_parser->cfg->key_cache_slabs = atoi((yyvsp[(2) - (2)].str)); + if(!is_pow2(cfg_parser->cfg->key_cache_slabs)) + yyerror("must be a power of 2"); + } + free((yyvsp[(2) - (2)].str)); + } + break; + + case 217: + +/* Line 1806 of yacc.c */ +#line 1049 "util/configparser.y" + { + OUTYY(("P(server_neg_cache_size:%s)\n", (yyvsp[(2) - (2)].str))); + if(!cfg_parse_memsize((yyvsp[(2) - (2)].str), &cfg_parser->cfg->neg_cache_size)) + yyerror("memory size expected"); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 218: + +/* Line 1806 of yacc.c */ +#line 1057 "util/configparser.y" + { + OUTYY(("P(server_local_zone:%s %s)\n", (yyvsp[(2) - (3)].str), (yyvsp[(3) - (3)].str))); + if(strcmp((yyvsp[(3) - (3)].str), "static")!=0 && strcmp((yyvsp[(3) - (3)].str), "deny")!=0 && + strcmp((yyvsp[(3) - (3)].str), "refuse")!=0 && strcmp((yyvsp[(3) - (3)].str), "redirect")!=0 && + strcmp((yyvsp[(3) - (3)].str), "transparent")!=0 && strcmp((yyvsp[(3) - (3)].str), "nodefault")!=0 + && strcmp((yyvsp[(3) - (3)].str), "typetransparent")!=0) + yyerror("local-zone type: expected static, deny, " + "refuse, redirect, transparent, " + "typetransparent or nodefault"); + else if(strcmp((yyvsp[(3) - (3)].str), "nodefault")==0) { + if(!cfg_strlist_insert(&cfg_parser->cfg-> + local_zones_nodefault, (yyvsp[(2) - (3)].str))) + fatal_exit("out of memory adding local-zone"); + free((yyvsp[(3) - (3)].str)); + } else { + if(!cfg_str2list_insert(&cfg_parser->cfg->local_zones, + (yyvsp[(2) - (3)].str), (yyvsp[(3) - (3)].str))) + fatal_exit("out of memory adding local-zone"); + } + } + break; + + case 219: + +/* Line 1806 of yacc.c */ +#line 1079 "util/configparser.y" + { + OUTYY(("P(server_local_data:%s)\n", (yyvsp[(2) - (2)].str))); + if(!cfg_strlist_insert(&cfg_parser->cfg->local_data, (yyvsp[(2) - (2)].str))) + fatal_exit("out of memory adding local-data"); + } + break; + + case 220: + +/* Line 1806 of yacc.c */ +#line 1086 "util/configparser.y" + { + char* ptr; + OUTYY(("P(server_local_data_ptr:%s)\n", (yyvsp[(2) - (2)].str))); + ptr = cfg_ptr_reverse((yyvsp[(2) - (2)].str)); + free((yyvsp[(2) - (2)].str)); + if(ptr) { + if(!cfg_strlist_insert(&cfg_parser->cfg-> + local_data, ptr)) + fatal_exit("out of memory adding local-data"); + } else { + yyerror("local-data-ptr could not be reversed"); + } + } + break; + + case 221: + +/* Line 1806 of yacc.c */ +#line 1101 "util/configparser.y" + { + OUTYY(("P(server_minimal_responses:%s)\n", (yyvsp[(2) - (2)].str))); + if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->minimal_responses = + (strcmp((yyvsp[(2) - (2)].str), "yes")==0); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 222: + +/* Line 1806 of yacc.c */ +#line 1111 "util/configparser.y" + { + OUTYY(("P(server_rrset_roundrobin:%s)\n", (yyvsp[(2) - (2)].str))); + if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->rrset_roundrobin = + (strcmp((yyvsp[(2) - (2)].str), "yes")==0); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 223: + +/* Line 1806 of yacc.c */ +#line 1121 "util/configparser.y" + { + OUTYY(("P(name:%s)\n", (yyvsp[(2) - (2)].str))); + if(cfg_parser->cfg->stubs->name) + yyerror("stub name override, there must be one name " + "for one stub-zone"); + free(cfg_parser->cfg->stubs->name); + cfg_parser->cfg->stubs->name = (yyvsp[(2) - (2)].str); + } + break; + + case 224: + +/* Line 1806 of yacc.c */ +#line 1131 "util/configparser.y" + { + OUTYY(("P(stub-host:%s)\n", (yyvsp[(2) - (2)].str))); + if(!cfg_strlist_insert(&cfg_parser->cfg->stubs->hosts, (yyvsp[(2) - (2)].str))) + yyerror("out of memory"); + } + break; + + case 225: + +/* Line 1806 of yacc.c */ +#line 1138 "util/configparser.y" + { + OUTYY(("P(stub-addr:%s)\n", (yyvsp[(2) - (2)].str))); + if(!cfg_strlist_insert(&cfg_parser->cfg->stubs->addrs, (yyvsp[(2) - (2)].str))) + yyerror("out of memory"); + } + break; + + case 226: + +/* Line 1806 of yacc.c */ +#line 1145 "util/configparser.y" + { + OUTYY(("P(stub-first:%s)\n", (yyvsp[(2) - (2)].str))); + if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->stubs->isfirst=(strcmp((yyvsp[(2) - (2)].str), "yes")==0); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 227: + +/* Line 1806 of yacc.c */ +#line 1154 "util/configparser.y" + { + OUTYY(("P(stub-prime:%s)\n", (yyvsp[(2) - (2)].str))); + if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->stubs->isprime = + (strcmp((yyvsp[(2) - (2)].str), "yes")==0); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 228: + +/* Line 1806 of yacc.c */ +#line 1164 "util/configparser.y" + { + OUTYY(("P(name:%s)\n", (yyvsp[(2) - (2)].str))); + if(cfg_parser->cfg->forwards->name) + yyerror("forward name override, there must be one " + "name for one forward-zone"); + free(cfg_parser->cfg->forwards->name); + cfg_parser->cfg->forwards->name = (yyvsp[(2) - (2)].str); + } + break; + + case 229: + +/* Line 1806 of yacc.c */ +#line 1174 "util/configparser.y" + { + OUTYY(("P(forward-host:%s)\n", (yyvsp[(2) - (2)].str))); + if(!cfg_strlist_insert(&cfg_parser->cfg->forwards->hosts, (yyvsp[(2) - (2)].str))) + yyerror("out of memory"); + } + break; + + case 230: + +/* Line 1806 of yacc.c */ +#line 1181 "util/configparser.y" + { + OUTYY(("P(forward-addr:%s)\n", (yyvsp[(2) - (2)].str))); + if(!cfg_strlist_insert(&cfg_parser->cfg->forwards->addrs, (yyvsp[(2) - (2)].str))) + yyerror("out of memory"); + } + break; + + case 231: + +/* Line 1806 of yacc.c */ +#line 1188 "util/configparser.y" + { + OUTYY(("P(forward-first:%s)\n", (yyvsp[(2) - (2)].str))); + if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->forwards->isfirst=(strcmp((yyvsp[(2) - (2)].str), "yes")==0); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 232: + +/* Line 1806 of yacc.c */ +#line 1197 "util/configparser.y" + { + OUTYY(("\nP(remote-control:)\n")); + } + break; + + case 242: + +/* Line 1806 of yacc.c */ +#line 1208 "util/configparser.y" + { + OUTYY(("P(control_enable:%s)\n", (yyvsp[(2) - (2)].str))); + if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->remote_control_enable = + (strcmp((yyvsp[(2) - (2)].str), "yes")==0); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 243: + +/* Line 1806 of yacc.c */ +#line 1218 "util/configparser.y" + { + OUTYY(("P(control_port:%s)\n", (yyvsp[(2) - (2)].str))); + if(atoi((yyvsp[(2) - (2)].str)) == 0) + yyerror("control port number expected"); + else cfg_parser->cfg->control_port = atoi((yyvsp[(2) - (2)].str)); + free((yyvsp[(2) - (2)].str)); + } + break; + + case 244: + +/* Line 1806 of yacc.c */ +#line 1227 "util/configparser.y" + { + OUTYY(("P(control_interface:%s)\n", (yyvsp[(2) - (2)].str))); + if(!cfg_strlist_insert(&cfg_parser->cfg->control_ifs, (yyvsp[(2) - (2)].str))) + yyerror("out of memory"); + } + break; + + case 245: + +/* Line 1806 of yacc.c */ +#line 1234 "util/configparser.y" + { + OUTYY(("P(rc_server_key_file:%s)\n", (yyvsp[(2) - (2)].str))); + free(cfg_parser->cfg->server_key_file); + cfg_parser->cfg->server_key_file = (yyvsp[(2) - (2)].str); + } + break; + + case 246: + +/* Line 1806 of yacc.c */ +#line 1241 "util/configparser.y" + { + OUTYY(("P(rc_server_cert_file:%s)\n", (yyvsp[(2) - (2)].str))); + free(cfg_parser->cfg->server_cert_file); + cfg_parser->cfg->server_cert_file = (yyvsp[(2) - (2)].str); + } + break; + + case 247: + +/* Line 1806 of yacc.c */ +#line 1248 "util/configparser.y" + { + OUTYY(("P(rc_control_key_file:%s)\n", (yyvsp[(2) - (2)].str))); + free(cfg_parser->cfg->control_key_file); + cfg_parser->cfg->control_key_file = (yyvsp[(2) - (2)].str); + } + break; + + case 248: + +/* Line 1806 of yacc.c */ +#line 1255 "util/configparser.y" + { + OUTYY(("P(rc_control_cert_file:%s)\n", (yyvsp[(2) - (2)].str))); + free(cfg_parser->cfg->control_cert_file); + cfg_parser->cfg->control_cert_file = (yyvsp[(2) - (2)].str); + } + break; + + case 249: + +/* Line 1806 of yacc.c */ +#line 1262 "util/configparser.y" + { + OUTYY(("\nP(python:)\n")); + } + break; + + case 253: + +/* Line 1806 of yacc.c */ +#line 1271 "util/configparser.y" + { + OUTYY(("P(python-script:%s)\n", (yyvsp[(2) - (2)].str))); + free(cfg_parser->cfg->python_script); + cfg_parser->cfg->python_script = (yyvsp[(2) - (2)].str); + } + break; + + + +/* Line 1806 of yacc.c */ +#line 3658 "util/configparser.c" + default: break; + } + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); + + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if ! YYERROR_VERBOSE + yyerror (YY_("syntax error")); +#else +# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ + yyssp, yytoken) + { + char const *yymsgp = YY_("syntax error"); + int yysyntax_error_status; + yysyntax_error_status = YYSYNTAX_ERROR; + if (yysyntax_error_status == 0) + yymsgp = yymsg; + else if (yysyntax_error_status == 1) + { + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); + if (!yymsg) + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + yysyntax_error_status = 2; + } + else + { + yysyntax_error_status = YYSYNTAX_ERROR; + yymsgp = yymsg; + } + } + yyerror (yymsgp); + if (yysyntax_error_status == 2) + goto yyexhaustedlab; + } +# undef YYSYNTAX_ERROR +#endif + } + + + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) + goto yyerrorlab; + + /* Do not reclaim the symbols of the rule which action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (!yypact_value_is_default (yyn)) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", + yystos[yystate], yyvsp); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + *++yyvsp = yylval; + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#if !defined(yyoverflow) || YYERROR_VERBOSE +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEMPTY) + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval); + } + /* Do not reclaim the symbols of the rule which action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif + /* Make sure YYID is used. */ + return YYID (yyresult); +} + + + +/* Line 2067 of yacc.c */ +#line 1276 "util/configparser.y" + + +/* parse helper routines could be here */ + diff --git a/util/configparser.h b/util/configparser.h new file mode 100644 index 00000000000..06dd5d9f307 --- /dev/null +++ b/util/configparser.h @@ -0,0 +1,322 @@ +/* A Bison parser, made by GNU Bison 2.5. */ + +/* Bison interface for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + SPACE = 258, + LETTER = 259, + NEWLINE = 260, + COMMENT = 261, + COLON = 262, + ANY = 263, + ZONESTR = 264, + STRING_ARG = 265, + VAR_SERVER = 266, + VAR_VERBOSITY = 267, + VAR_NUM_THREADS = 268, + VAR_PORT = 269, + VAR_OUTGOING_RANGE = 270, + VAR_INTERFACE = 271, + VAR_DO_IP4 = 272, + VAR_DO_IP6 = 273, + VAR_DO_UDP = 274, + VAR_DO_TCP = 275, + VAR_CHROOT = 276, + VAR_USERNAME = 277, + VAR_DIRECTORY = 278, + VAR_LOGFILE = 279, + VAR_PIDFILE = 280, + VAR_MSG_CACHE_SIZE = 281, + VAR_MSG_CACHE_SLABS = 282, + VAR_NUM_QUERIES_PER_THREAD = 283, + VAR_RRSET_CACHE_SIZE = 284, + VAR_RRSET_CACHE_SLABS = 285, + VAR_OUTGOING_NUM_TCP = 286, + VAR_INFRA_HOST_TTL = 287, + VAR_INFRA_LAME_TTL = 288, + VAR_INFRA_CACHE_SLABS = 289, + VAR_INFRA_CACHE_NUMHOSTS = 290, + VAR_INFRA_CACHE_LAME_SIZE = 291, + VAR_NAME = 292, + VAR_STUB_ZONE = 293, + VAR_STUB_HOST = 294, + VAR_STUB_ADDR = 295, + VAR_TARGET_FETCH_POLICY = 296, + VAR_HARDEN_SHORT_BUFSIZE = 297, + VAR_HARDEN_LARGE_QUERIES = 298, + VAR_FORWARD_ZONE = 299, + VAR_FORWARD_HOST = 300, + VAR_FORWARD_ADDR = 301, + VAR_DO_NOT_QUERY_ADDRESS = 302, + VAR_HIDE_IDENTITY = 303, + VAR_HIDE_VERSION = 304, + VAR_IDENTITY = 305, + VAR_VERSION = 306, + VAR_HARDEN_GLUE = 307, + VAR_MODULE_CONF = 308, + VAR_TRUST_ANCHOR_FILE = 309, + VAR_TRUST_ANCHOR = 310, + VAR_VAL_OVERRIDE_DATE = 311, + VAR_BOGUS_TTL = 312, + VAR_VAL_CLEAN_ADDITIONAL = 313, + VAR_VAL_PERMISSIVE_MODE = 314, + VAR_INCOMING_NUM_TCP = 315, + VAR_MSG_BUFFER_SIZE = 316, + VAR_KEY_CACHE_SIZE = 317, + VAR_KEY_CACHE_SLABS = 318, + VAR_TRUSTED_KEYS_FILE = 319, + VAR_VAL_NSEC3_KEYSIZE_ITERATIONS = 320, + VAR_USE_SYSLOG = 321, + VAR_OUTGOING_INTERFACE = 322, + VAR_ROOT_HINTS = 323, + VAR_DO_NOT_QUERY_LOCALHOST = 324, + VAR_CACHE_MAX_TTL = 325, + VAR_HARDEN_DNSSEC_STRIPPED = 326, + VAR_ACCESS_CONTROL = 327, + VAR_LOCAL_ZONE = 328, + VAR_LOCAL_DATA = 329, + VAR_INTERFACE_AUTOMATIC = 330, + VAR_STATISTICS_INTERVAL = 331, + VAR_DO_DAEMONIZE = 332, + VAR_USE_CAPS_FOR_ID = 333, + VAR_STATISTICS_CUMULATIVE = 334, + VAR_OUTGOING_PORT_PERMIT = 335, + VAR_OUTGOING_PORT_AVOID = 336, + VAR_DLV_ANCHOR_FILE = 337, + VAR_DLV_ANCHOR = 338, + VAR_NEG_CACHE_SIZE = 339, + VAR_HARDEN_REFERRAL_PATH = 340, + VAR_PRIVATE_ADDRESS = 341, + VAR_PRIVATE_DOMAIN = 342, + VAR_REMOTE_CONTROL = 343, + VAR_CONTROL_ENABLE = 344, + VAR_CONTROL_INTERFACE = 345, + VAR_CONTROL_PORT = 346, + VAR_SERVER_KEY_FILE = 347, + VAR_SERVER_CERT_FILE = 348, + VAR_CONTROL_KEY_FILE = 349, + VAR_CONTROL_CERT_FILE = 350, + VAR_EXTENDED_STATISTICS = 351, + VAR_LOCAL_DATA_PTR = 352, + VAR_JOSTLE_TIMEOUT = 353, + VAR_STUB_PRIME = 354, + VAR_UNWANTED_REPLY_THRESHOLD = 355, + VAR_LOG_TIME_ASCII = 356, + VAR_DOMAIN_INSECURE = 357, + VAR_PYTHON = 358, + VAR_PYTHON_SCRIPT = 359, + VAR_VAL_SIG_SKEW_MIN = 360, + VAR_VAL_SIG_SKEW_MAX = 361, + VAR_CACHE_MIN_TTL = 362, + VAR_VAL_LOG_LEVEL = 363, + VAR_AUTO_TRUST_ANCHOR_FILE = 364, + VAR_KEEP_MISSING = 365, + VAR_ADD_HOLDDOWN = 366, + VAR_DEL_HOLDDOWN = 367, + VAR_SO_RCVBUF = 368, + VAR_EDNS_BUFFER_SIZE = 369, + VAR_PREFETCH = 370, + VAR_PREFETCH_KEY = 371, + VAR_SO_SNDBUF = 372, + VAR_HARDEN_BELOW_NXDOMAIN = 373, + VAR_IGNORE_CD_FLAG = 374, + VAR_LOG_QUERIES = 375, + VAR_TCP_UPSTREAM = 376, + VAR_SSL_UPSTREAM = 377, + VAR_SSL_SERVICE_KEY = 378, + VAR_SSL_SERVICE_PEM = 379, + VAR_SSL_PORT = 380, + VAR_FORWARD_FIRST = 381, + VAR_STUB_FIRST = 382, + VAR_MINIMAL_RESPONSES = 383, + VAR_RRSET_ROUNDROBIN = 384 + }; +#endif +/* Tokens. */ +#define SPACE 258 +#define LETTER 259 +#define NEWLINE 260 +#define COMMENT 261 +#define COLON 262 +#define ANY 263 +#define ZONESTR 264 +#define STRING_ARG 265 +#define VAR_SERVER 266 +#define VAR_VERBOSITY 267 +#define VAR_NUM_THREADS 268 +#define VAR_PORT 269 +#define VAR_OUTGOING_RANGE 270 +#define VAR_INTERFACE 271 +#define VAR_DO_IP4 272 +#define VAR_DO_IP6 273 +#define VAR_DO_UDP 274 +#define VAR_DO_TCP 275 +#define VAR_CHROOT 276 +#define VAR_USERNAME 277 +#define VAR_DIRECTORY 278 +#define VAR_LOGFILE 279 +#define VAR_PIDFILE 280 +#define VAR_MSG_CACHE_SIZE 281 +#define VAR_MSG_CACHE_SLABS 282 +#define VAR_NUM_QUERIES_PER_THREAD 283 +#define VAR_RRSET_CACHE_SIZE 284 +#define VAR_RRSET_CACHE_SLABS 285 +#define VAR_OUTGOING_NUM_TCP 286 +#define VAR_INFRA_HOST_TTL 287 +#define VAR_INFRA_LAME_TTL 288 +#define VAR_INFRA_CACHE_SLABS 289 +#define VAR_INFRA_CACHE_NUMHOSTS 290 +#define VAR_INFRA_CACHE_LAME_SIZE 291 +#define VAR_NAME 292 +#define VAR_STUB_ZONE 293 +#define VAR_STUB_HOST 294 +#define VAR_STUB_ADDR 295 +#define VAR_TARGET_FETCH_POLICY 296 +#define VAR_HARDEN_SHORT_BUFSIZE 297 +#define VAR_HARDEN_LARGE_QUERIES 298 +#define VAR_FORWARD_ZONE 299 +#define VAR_FORWARD_HOST 300 +#define VAR_FORWARD_ADDR 301 +#define VAR_DO_NOT_QUERY_ADDRESS 302 +#define VAR_HIDE_IDENTITY 303 +#define VAR_HIDE_VERSION 304 +#define VAR_IDENTITY 305 +#define VAR_VERSION 306 +#define VAR_HARDEN_GLUE 307 +#define VAR_MODULE_CONF 308 +#define VAR_TRUST_ANCHOR_FILE 309 +#define VAR_TRUST_ANCHOR 310 +#define VAR_VAL_OVERRIDE_DATE 311 +#define VAR_BOGUS_TTL 312 +#define VAR_VAL_CLEAN_ADDITIONAL 313 +#define VAR_VAL_PERMISSIVE_MODE 314 +#define VAR_INCOMING_NUM_TCP 315 +#define VAR_MSG_BUFFER_SIZE 316 +#define VAR_KEY_CACHE_SIZE 317 +#define VAR_KEY_CACHE_SLABS 318 +#define VAR_TRUSTED_KEYS_FILE 319 +#define VAR_VAL_NSEC3_KEYSIZE_ITERATIONS 320 +#define VAR_USE_SYSLOG 321 +#define VAR_OUTGOING_INTERFACE 322 +#define VAR_ROOT_HINTS 323 +#define VAR_DO_NOT_QUERY_LOCALHOST 324 +#define VAR_CACHE_MAX_TTL 325 +#define VAR_HARDEN_DNSSEC_STRIPPED 326 +#define VAR_ACCESS_CONTROL 327 +#define VAR_LOCAL_ZONE 328 +#define VAR_LOCAL_DATA 329 +#define VAR_INTERFACE_AUTOMATIC 330 +#define VAR_STATISTICS_INTERVAL 331 +#define VAR_DO_DAEMONIZE 332 +#define VAR_USE_CAPS_FOR_ID 333 +#define VAR_STATISTICS_CUMULATIVE 334 +#define VAR_OUTGOING_PORT_PERMIT 335 +#define VAR_OUTGOING_PORT_AVOID 336 +#define VAR_DLV_ANCHOR_FILE 337 +#define VAR_DLV_ANCHOR 338 +#define VAR_NEG_CACHE_SIZE 339 +#define VAR_HARDEN_REFERRAL_PATH 340 +#define VAR_PRIVATE_ADDRESS 341 +#define VAR_PRIVATE_DOMAIN 342 +#define VAR_REMOTE_CONTROL 343 +#define VAR_CONTROL_ENABLE 344 +#define VAR_CONTROL_INTERFACE 345 +#define VAR_CONTROL_PORT 346 +#define VAR_SERVER_KEY_FILE 347 +#define VAR_SERVER_CERT_FILE 348 +#define VAR_CONTROL_KEY_FILE 349 +#define VAR_CONTROL_CERT_FILE 350 +#define VAR_EXTENDED_STATISTICS 351 +#define VAR_LOCAL_DATA_PTR 352 +#define VAR_JOSTLE_TIMEOUT 353 +#define VAR_STUB_PRIME 354 +#define VAR_UNWANTED_REPLY_THRESHOLD 355 +#define VAR_LOG_TIME_ASCII 356 +#define VAR_DOMAIN_INSECURE 357 +#define VAR_PYTHON 358 +#define VAR_PYTHON_SCRIPT 359 +#define VAR_VAL_SIG_SKEW_MIN 360 +#define VAR_VAL_SIG_SKEW_MAX 361 +#define VAR_CACHE_MIN_TTL 362 +#define VAR_VAL_LOG_LEVEL 363 +#define VAR_AUTO_TRUST_ANCHOR_FILE 364 +#define VAR_KEEP_MISSING 365 +#define VAR_ADD_HOLDDOWN 366 +#define VAR_DEL_HOLDDOWN 367 +#define VAR_SO_RCVBUF 368 +#define VAR_EDNS_BUFFER_SIZE 369 +#define VAR_PREFETCH 370 +#define VAR_PREFETCH_KEY 371 +#define VAR_SO_SNDBUF 372 +#define VAR_HARDEN_BELOW_NXDOMAIN 373 +#define VAR_IGNORE_CD_FLAG 374 +#define VAR_LOG_QUERIES 375 +#define VAR_TCP_UPSTREAM 376 +#define VAR_SSL_UPSTREAM 377 +#define VAR_SSL_SERVICE_KEY 378 +#define VAR_SSL_SERVICE_PEM 379 +#define VAR_SSL_PORT 380 +#define VAR_FORWARD_FIRST 381 +#define VAR_STUB_FIRST 382 +#define VAR_MINIMAL_RESPONSES 383 +#define VAR_RRSET_ROUNDROBIN 384 + + + + +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE +{ + +/* Line 2068 of yacc.c */ +#line 64 "util/configparser.y" + + char* str; + + + +/* Line 2068 of yacc.c */ +#line 314 "util/configparser.h" +} YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +#endif + +extern YYSTYPE yylval; + + diff --git a/util/configparser.y b/util/configparser.y new file mode 100644 index 00000000000..0dbee2b498c --- /dev/null +++ b/util/configparser.y @@ -0,0 +1,1278 @@ +/* + * configparser.y -- yacc grammar for unbound configuration files + * + * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +%{ +#include "config.h" + +#include +#include +#include +#include +#include + +#include "util/configyyrename.h" +#include "util/config_file.h" +#include "util/net_help.h" + +int ub_c_lex(void); +void ub_c_error(const char *message); + +/* these need to be global, otherwise they cannot be used inside yacc */ +extern struct config_parser_state* cfg_parser; + +#if 0 +#define OUTYY(s) printf s /* used ONLY when debugging */ +#else +#define OUTYY(s) +#endif + +%} +%union { + char* str; +}; + +%token SPACE LETTER NEWLINE COMMENT COLON ANY ZONESTR +%token 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_CHROOT VAR_USERNAME VAR_DIRECTORY VAR_LOGFILE VAR_PIDFILE +%token VAR_MSG_CACHE_SIZE VAR_MSG_CACHE_SLABS VAR_NUM_QUERIES_PER_THREAD +%token VAR_RRSET_CACHE_SIZE VAR_RRSET_CACHE_SLABS VAR_OUTGOING_NUM_TCP +%token VAR_INFRA_HOST_TTL VAR_INFRA_LAME_TTL VAR_INFRA_CACHE_SLABS +%token VAR_INFRA_CACHE_NUMHOSTS VAR_INFRA_CACHE_LAME_SIZE VAR_NAME +%token VAR_STUB_ZONE VAR_STUB_HOST VAR_STUB_ADDR VAR_TARGET_FETCH_POLICY +%token VAR_HARDEN_SHORT_BUFSIZE VAR_HARDEN_LARGE_QUERIES +%token VAR_FORWARD_ZONE VAR_FORWARD_HOST VAR_FORWARD_ADDR +%token VAR_DO_NOT_QUERY_ADDRESS VAR_HIDE_IDENTITY VAR_HIDE_VERSION +%token VAR_IDENTITY VAR_VERSION VAR_HARDEN_GLUE VAR_MODULE_CONF +%token VAR_TRUST_ANCHOR_FILE VAR_TRUST_ANCHOR VAR_VAL_OVERRIDE_DATE +%token VAR_BOGUS_TTL VAR_VAL_CLEAN_ADDITIONAL VAR_VAL_PERMISSIVE_MODE +%token VAR_INCOMING_NUM_TCP VAR_MSG_BUFFER_SIZE VAR_KEY_CACHE_SIZE +%token VAR_KEY_CACHE_SLABS VAR_TRUSTED_KEYS_FILE +%token VAR_VAL_NSEC3_KEYSIZE_ITERATIONS VAR_USE_SYSLOG +%token VAR_OUTGOING_INTERFACE VAR_ROOT_HINTS VAR_DO_NOT_QUERY_LOCALHOST +%token VAR_CACHE_MAX_TTL VAR_HARDEN_DNSSEC_STRIPPED VAR_ACCESS_CONTROL +%token VAR_LOCAL_ZONE VAR_LOCAL_DATA VAR_INTERFACE_AUTOMATIC +%token VAR_STATISTICS_INTERVAL VAR_DO_DAEMONIZE VAR_USE_CAPS_FOR_ID +%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_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 +%token VAR_EXTENDED_STATISTICS VAR_LOCAL_DATA_PTR VAR_JOSTLE_TIMEOUT +%token VAR_STUB_PRIME VAR_UNWANTED_REPLY_THRESHOLD VAR_LOG_TIME_ASCII +%token VAR_DOMAIN_INSECURE VAR_PYTHON VAR_PYTHON_SCRIPT VAR_VAL_SIG_SKEW_MIN +%token VAR_VAL_SIG_SKEW_MAX VAR_CACHE_MIN_TTL VAR_VAL_LOG_LEVEL +%token VAR_AUTO_TRUST_ANCHOR_FILE VAR_KEEP_MISSING VAR_ADD_HOLDDOWN +%token VAR_DEL_HOLDDOWN VAR_SO_RCVBUF VAR_EDNS_BUFFER_SIZE VAR_PREFETCH +%token VAR_PREFETCH_KEY VAR_SO_SNDBUF VAR_HARDEN_BELOW_NXDOMAIN +%token VAR_IGNORE_CD_FLAG VAR_LOG_QUERIES VAR_TCP_UPSTREAM VAR_SSL_UPSTREAM +%token VAR_SSL_SERVICE_KEY VAR_SSL_SERVICE_PEM VAR_SSL_PORT VAR_FORWARD_FIRST +%token VAR_STUB_FIRST VAR_MINIMAL_RESPONSES VAR_RRSET_ROUNDROBIN + +%% +toplevelvars: /* empty */ | toplevelvars toplevelvar ; +toplevelvar: serverstart contents_server | stubstart contents_stub | + forwardstart contents_forward | pythonstart contents_py | + rcstart contents_rc + ; + +/* server: declaration */ +serverstart: VAR_SERVER + { + OUTYY(("\nP(server:)\n")); + } + ; +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_interface | server_chroot | server_username | + server_directory | server_logfile | server_pidfile | + server_msg_cache_size | server_msg_cache_slabs | + server_num_queries_per_thread | server_rrset_cache_size | + server_rrset_cache_slabs | server_outgoing_num_tcp | + server_infra_host_ttl | server_infra_lame_ttl | + server_infra_cache_slabs | server_infra_cache_numhosts | + server_infra_cache_lame_size | server_target_fetch_policy | + server_harden_short_bufsize | server_harden_large_queries | + server_do_not_query_address | server_hide_identity | + server_hide_version | server_identity | server_version | + server_harden_glue | server_module_conf | server_trust_anchor_file | + server_trust_anchor | server_val_override_date | server_bogus_ttl | + server_val_clean_additional | server_val_permissive_mode | + server_incoming_num_tcp | server_msg_buffer_size | + server_key_cache_size | server_key_cache_slabs | + server_trusted_keys_file | server_val_nsec3_keysize_iterations | + server_use_syslog | server_outgoing_interface | server_root_hints | + server_do_not_query_localhost | server_cache_max_ttl | + server_harden_dnssec_stripped | server_access_control | + server_local_zone | server_local_data | server_interface_automatic | + server_statistics_interval | server_do_daemonize | + server_use_caps_for_id | server_statistics_cumulative | + server_outgoing_port_permit | server_outgoing_port_avoid | + 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_local_data_ptr | server_jostle_timeout | + server_unwanted_reply_threshold | server_log_time_ascii | + server_domain_insecure | server_val_sig_skew_min | + server_val_sig_skew_max | server_cache_min_ttl | server_val_log_level | + server_auto_trust_anchor_file | server_add_holddown | + server_del_holddown | server_keep_missing | server_so_rcvbuf | + server_edns_buffer_size | server_prefetch | server_prefetch_key | + server_so_sndbuf | server_harden_below_nxdomain | server_ignore_cd_flag | + server_log_queries | server_tcp_upstream | server_ssl_upstream | + server_ssl_service_key | server_ssl_service_pem | server_ssl_port | + server_minimal_responses | server_rrset_roundrobin + ; +stubstart: VAR_STUB_ZONE + { + struct config_stub* s; + OUTYY(("\nP(stub_zone:)\n")); + s = (struct config_stub*)calloc(1, sizeof(struct config_stub)); + if(s) { + s->next = cfg_parser->cfg->stubs; + cfg_parser->cfg->stubs = s; + } else + yyerror("out of memory"); + } + ; +contents_stub: contents_stub content_stub + | ; +content_stub: stub_name | stub_host | stub_addr | stub_prime | stub_first + ; +forwardstart: VAR_FORWARD_ZONE + { + struct config_stub* s; + OUTYY(("\nP(forward_zone:)\n")); + s = (struct config_stub*)calloc(1, sizeof(struct config_stub)); + if(s) { + s->next = cfg_parser->cfg->forwards; + cfg_parser->cfg->forwards = s; + } else + yyerror("out of memory"); + } + ; +contents_forward: contents_forward content_forward + | ; +content_forward: forward_name | forward_host | forward_addr | forward_first + ; +server_num_threads: VAR_NUM_THREADS STRING_ARG + { + OUTYY(("P(server_num_threads:%s)\n", $2)); + if(atoi($2) == 0 && strcmp($2, "0") != 0) + yyerror("number expected"); + else cfg_parser->cfg->num_threads = atoi($2); + free($2); + } + ; +server_verbosity: VAR_VERBOSITY STRING_ARG + { + OUTYY(("P(server_verbosity:%s)\n", $2)); + if(atoi($2) == 0 && strcmp($2, "0") != 0) + yyerror("number expected"); + else cfg_parser->cfg->verbosity = atoi($2); + free($2); + } + ; +server_statistics_interval: VAR_STATISTICS_INTERVAL STRING_ARG + { + OUTYY(("P(server_statistics_interval:%s)\n", $2)); + if(strcmp($2, "") == 0 || strcmp($2, "0") == 0) + cfg_parser->cfg->stat_interval = 0; + else if(atoi($2) == 0) + yyerror("number expected"); + else cfg_parser->cfg->stat_interval = atoi($2); + free($2); + } + ; +server_statistics_cumulative: VAR_STATISTICS_CUMULATIVE STRING_ARG + { + OUTYY(("P(server_statistics_cumulative:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->stat_cumulative = (strcmp($2, "yes")==0); + free($2); + } + ; +server_extended_statistics: VAR_EXTENDED_STATISTICS STRING_ARG + { + OUTYY(("P(server_extended_statistics:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->stat_extended = (strcmp($2, "yes")==0); + free($2); + } + ; +server_port: VAR_PORT STRING_ARG + { + OUTYY(("P(server_port:%s)\n", $2)); + if(atoi($2) == 0) + yyerror("port number expected"); + else cfg_parser->cfg->port = atoi($2); + free($2); + } + ; +server_interface: VAR_INTERFACE STRING_ARG + { + OUTYY(("P(server_interface:%s)\n", $2)); + if(cfg_parser->cfg->num_ifs == 0) + cfg_parser->cfg->ifs = calloc(1, sizeof(char*)); + else cfg_parser->cfg->ifs = realloc(cfg_parser->cfg->ifs, + (cfg_parser->cfg->num_ifs+1)*sizeof(char*)); + if(!cfg_parser->cfg->ifs) + yyerror("out of memory"); + else + cfg_parser->cfg->ifs[cfg_parser->cfg->num_ifs++] = $2; + } + ; +server_outgoing_interface: VAR_OUTGOING_INTERFACE STRING_ARG + { + OUTYY(("P(server_outgoing_interface:%s)\n", $2)); + if(cfg_parser->cfg->num_out_ifs == 0) + cfg_parser->cfg->out_ifs = calloc(1, sizeof(char*)); + else cfg_parser->cfg->out_ifs = realloc( + cfg_parser->cfg->out_ifs, + (cfg_parser->cfg->num_out_ifs+1)*sizeof(char*)); + if(!cfg_parser->cfg->out_ifs) + yyerror("out of memory"); + else + cfg_parser->cfg->out_ifs[ + cfg_parser->cfg->num_out_ifs++] = $2; + } + ; +server_outgoing_range: VAR_OUTGOING_RANGE STRING_ARG + { + OUTYY(("P(server_outgoing_range:%s)\n", $2)); + if(atoi($2) == 0) + yyerror("number expected"); + else cfg_parser->cfg->outgoing_num_ports = atoi($2); + free($2); + } + ; +server_outgoing_port_permit: VAR_OUTGOING_PORT_PERMIT STRING_ARG + { + OUTYY(("P(server_outgoing_port_permit:%s)\n", $2)); + if(!cfg_mark_ports($2, 1, + cfg_parser->cfg->outgoing_avail_ports, 65536)) + yyerror("port number or range (\"low-high\") expected"); + free($2); + } + ; +server_outgoing_port_avoid: VAR_OUTGOING_PORT_AVOID STRING_ARG + { + OUTYY(("P(server_outgoing_port_avoid:%s)\n", $2)); + if(!cfg_mark_ports($2, 0, + cfg_parser->cfg->outgoing_avail_ports, 65536)) + yyerror("port number or range (\"low-high\") expected"); + free($2); + } + ; +server_outgoing_num_tcp: VAR_OUTGOING_NUM_TCP STRING_ARG + { + OUTYY(("P(server_outgoing_num_tcp:%s)\n", $2)); + if(atoi($2) == 0 && strcmp($2, "0") != 0) + yyerror("number expected"); + else cfg_parser->cfg->outgoing_num_tcp = atoi($2); + free($2); + } + ; +server_incoming_num_tcp: VAR_INCOMING_NUM_TCP STRING_ARG + { + OUTYY(("P(server_incoming_num_tcp:%s)\n", $2)); + if(atoi($2) == 0 && strcmp($2, "0") != 0) + yyerror("number expected"); + else cfg_parser->cfg->incoming_num_tcp = atoi($2); + free($2); + } + ; +server_interface_automatic: VAR_INTERFACE_AUTOMATIC STRING_ARG + { + OUTYY(("P(server_interface_automatic:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->if_automatic = (strcmp($2, "yes")==0); + free($2); + } + ; +server_do_ip4: VAR_DO_IP4 STRING_ARG + { + OUTYY(("P(server_do_ip4:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->do_ip4 = (strcmp($2, "yes")==0); + free($2); + } + ; +server_do_ip6: VAR_DO_IP6 STRING_ARG + { + OUTYY(("P(server_do_ip6:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->do_ip6 = (strcmp($2, "yes")==0); + free($2); + } + ; +server_do_udp: VAR_DO_UDP STRING_ARG + { + OUTYY(("P(server_do_udp:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->do_udp = (strcmp($2, "yes")==0); + free($2); + } + ; +server_do_tcp: VAR_DO_TCP STRING_ARG + { + OUTYY(("P(server_do_tcp:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->do_tcp = (strcmp($2, "yes")==0); + free($2); + } + ; +server_tcp_upstream: VAR_TCP_UPSTREAM STRING_ARG + { + OUTYY(("P(server_tcp_upstream:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->tcp_upstream = (strcmp($2, "yes")==0); + free($2); + } + ; +server_ssl_upstream: VAR_SSL_UPSTREAM STRING_ARG + { + OUTYY(("P(server_ssl_upstream:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->ssl_upstream = (strcmp($2, "yes")==0); + free($2); + } + ; +server_ssl_service_key: VAR_SSL_SERVICE_KEY STRING_ARG + { + OUTYY(("P(server_ssl_service_key:%s)\n", $2)); + free(cfg_parser->cfg->ssl_service_key); + cfg_parser->cfg->ssl_service_key = $2; + } + ; +server_ssl_service_pem: VAR_SSL_SERVICE_PEM STRING_ARG + { + OUTYY(("P(server_ssl_service_pem:%s)\n", $2)); + free(cfg_parser->cfg->ssl_service_pem); + cfg_parser->cfg->ssl_service_pem = $2; + } + ; +server_ssl_port: VAR_SSL_PORT STRING_ARG + { + OUTYY(("P(server_ssl_port:%s)\n", $2)); + if(atoi($2) == 0) + yyerror("port number expected"); + else cfg_parser->cfg->ssl_port = atoi($2); + free($2); + } + ; +server_do_daemonize: VAR_DO_DAEMONIZE STRING_ARG + { + OUTYY(("P(server_do_daemonize:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->do_daemonize = (strcmp($2, "yes")==0); + free($2); + } + ; +server_use_syslog: VAR_USE_SYSLOG STRING_ARG + { + OUTYY(("P(server_use_syslog:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->use_syslog = (strcmp($2, "yes")==0); +#if !defined(HAVE_SYSLOG_H) && !defined(UB_ON_WINDOWS) + if(strcmp($2, "yes") == 0) + yyerror("no syslog services are available. " + "(reconfigure and compile to add)"); +#endif + free($2); + } + ; +server_log_time_ascii: VAR_LOG_TIME_ASCII STRING_ARG + { + OUTYY(("P(server_log_time_ascii:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->log_time_ascii = (strcmp($2, "yes")==0); + free($2); + } + ; +server_log_queries: VAR_LOG_QUERIES STRING_ARG + { + OUTYY(("P(server_log_queries:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->log_queries = (strcmp($2, "yes")==0); + free($2); + } + ; +server_chroot: VAR_CHROOT STRING_ARG + { + OUTYY(("P(server_chroot:%s)\n", $2)); + free(cfg_parser->cfg->chrootdir); + cfg_parser->cfg->chrootdir = $2; + } + ; +server_username: VAR_USERNAME STRING_ARG + { + OUTYY(("P(server_username:%s)\n", $2)); + free(cfg_parser->cfg->username); + cfg_parser->cfg->username = $2; + } + ; +server_directory: VAR_DIRECTORY STRING_ARG + { + OUTYY(("P(server_directory:%s)\n", $2)); + free(cfg_parser->cfg->directory); + cfg_parser->cfg->directory = $2; + } + ; +server_logfile: VAR_LOGFILE STRING_ARG + { + OUTYY(("P(server_logfile:%s)\n", $2)); + free(cfg_parser->cfg->logfile); + cfg_parser->cfg->logfile = $2; + cfg_parser->cfg->use_syslog = 0; + } + ; +server_pidfile: VAR_PIDFILE STRING_ARG + { + OUTYY(("P(server_pidfile:%s)\n", $2)); + free(cfg_parser->cfg->pidfile); + cfg_parser->cfg->pidfile = $2; + } + ; +server_root_hints: VAR_ROOT_HINTS STRING_ARG + { + OUTYY(("P(server_root_hints:%s)\n", $2)); + if(!cfg_strlist_insert(&cfg_parser->cfg->root_hints, $2)) + yyerror("out of memory"); + } + ; +server_dlv_anchor_file: VAR_DLV_ANCHOR_FILE STRING_ARG + { + OUTYY(("P(server_dlv_anchor_file:%s)\n", $2)); + free(cfg_parser->cfg->dlv_anchor_file); + cfg_parser->cfg->dlv_anchor_file = $2; + } + ; +server_dlv_anchor: VAR_DLV_ANCHOR STRING_ARG + { + OUTYY(("P(server_dlv_anchor:%s)\n", $2)); + if(!cfg_strlist_insert(&cfg_parser->cfg->dlv_anchor_list, $2)) + yyerror("out of memory"); + } + ; +server_auto_trust_anchor_file: VAR_AUTO_TRUST_ANCHOR_FILE STRING_ARG + { + OUTYY(("P(server_auto_trust_anchor_file:%s)\n", $2)); + if(!cfg_strlist_insert(&cfg_parser->cfg-> + auto_trust_anchor_file_list, $2)) + yyerror("out of memory"); + } + ; +server_trust_anchor_file: VAR_TRUST_ANCHOR_FILE STRING_ARG + { + OUTYY(("P(server_trust_anchor_file:%s)\n", $2)); + if(!cfg_strlist_insert(&cfg_parser->cfg-> + trust_anchor_file_list, $2)) + yyerror("out of memory"); + } + ; +server_trusted_keys_file: VAR_TRUSTED_KEYS_FILE STRING_ARG + { + OUTYY(("P(server_trusted_keys_file:%s)\n", $2)); + if(!cfg_strlist_insert(&cfg_parser->cfg-> + trusted_keys_file_list, $2)) + yyerror("out of memory"); + } + ; +server_trust_anchor: VAR_TRUST_ANCHOR STRING_ARG + { + OUTYY(("P(server_trust_anchor:%s)\n", $2)); + if(!cfg_strlist_insert(&cfg_parser->cfg->trust_anchor_list, $2)) + yyerror("out of memory"); + } + ; +server_domain_insecure: VAR_DOMAIN_INSECURE STRING_ARG + { + OUTYY(("P(server_domain_insecure:%s)\n", $2)); + if(!cfg_strlist_insert(&cfg_parser->cfg->domain_insecure, $2)) + yyerror("out of memory"); + } + ; +server_hide_identity: VAR_HIDE_IDENTITY STRING_ARG + { + OUTYY(("P(server_hide_identity:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->hide_identity = (strcmp($2, "yes")==0); + free($2); + } + ; +server_hide_version: VAR_HIDE_VERSION STRING_ARG + { + OUTYY(("P(server_hide_version:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->hide_version = (strcmp($2, "yes")==0); + free($2); + } + ; +server_identity: VAR_IDENTITY STRING_ARG + { + OUTYY(("P(server_identity:%s)\n", $2)); + free(cfg_parser->cfg->identity); + cfg_parser->cfg->identity = $2; + } + ; +server_version: VAR_VERSION STRING_ARG + { + OUTYY(("P(server_version:%s)\n", $2)); + free(cfg_parser->cfg->version); + cfg_parser->cfg->version = $2; + } + ; +server_so_rcvbuf: VAR_SO_RCVBUF STRING_ARG + { + OUTYY(("P(server_so_rcvbuf:%s)\n", $2)); + if(!cfg_parse_memsize($2, &cfg_parser->cfg->so_rcvbuf)) + yyerror("buffer size expected"); + free($2); + } + ; +server_so_sndbuf: VAR_SO_SNDBUF STRING_ARG + { + OUTYY(("P(server_so_sndbuf:%s)\n", $2)); + if(!cfg_parse_memsize($2, &cfg_parser->cfg->so_sndbuf)) + yyerror("buffer size expected"); + free($2); + } + ; +server_edns_buffer_size: VAR_EDNS_BUFFER_SIZE STRING_ARG + { + OUTYY(("P(server_edns_buffer_size:%s)\n", $2)); + if(atoi($2) == 0) + yyerror("number expected"); + else if (atoi($2) < 12) + yyerror("edns buffer size too small"); + else if (atoi($2) > 65535) + cfg_parser->cfg->edns_buffer_size = 65535; + else cfg_parser->cfg->edns_buffer_size = atoi($2); + free($2); + } + ; +server_msg_buffer_size: VAR_MSG_BUFFER_SIZE STRING_ARG + { + OUTYY(("P(server_msg_buffer_size:%s)\n", $2)); + if(atoi($2) == 0) + yyerror("number expected"); + else if (atoi($2) < 4096) + yyerror("message buffer size too small (use 4096)"); + else cfg_parser->cfg->msg_buffer_size = atoi($2); + free($2); + } + ; +server_msg_cache_size: VAR_MSG_CACHE_SIZE STRING_ARG + { + OUTYY(("P(server_msg_cache_size:%s)\n", $2)); + if(!cfg_parse_memsize($2, &cfg_parser->cfg->msg_cache_size)) + yyerror("memory size expected"); + free($2); + } + ; +server_msg_cache_slabs: VAR_MSG_CACHE_SLABS STRING_ARG + { + OUTYY(("P(server_msg_cache_slabs:%s)\n", $2)); + if(atoi($2) == 0) + yyerror("number expected"); + else { + cfg_parser->cfg->msg_cache_slabs = atoi($2); + if(!is_pow2(cfg_parser->cfg->msg_cache_slabs)) + yyerror("must be a power of 2"); + } + free($2); + } + ; +server_num_queries_per_thread: VAR_NUM_QUERIES_PER_THREAD STRING_ARG + { + OUTYY(("P(server_num_queries_per_thread:%s)\n", $2)); + if(atoi($2) == 0) + yyerror("number expected"); + else cfg_parser->cfg->num_queries_per_thread = atoi($2); + free($2); + } + ; +server_jostle_timeout: VAR_JOSTLE_TIMEOUT STRING_ARG + { + OUTYY(("P(server_jostle_timeout:%s)\n", $2)); + if(atoi($2) == 0 && strcmp($2, "0") != 0) + yyerror("number expected"); + else cfg_parser->cfg->jostle_time = atoi($2); + free($2); + } + ; +server_rrset_cache_size: VAR_RRSET_CACHE_SIZE STRING_ARG + { + OUTYY(("P(server_rrset_cache_size:%s)\n", $2)); + if(!cfg_parse_memsize($2, &cfg_parser->cfg->rrset_cache_size)) + yyerror("memory size expected"); + free($2); + } + ; +server_rrset_cache_slabs: VAR_RRSET_CACHE_SLABS STRING_ARG + { + OUTYY(("P(server_rrset_cache_slabs:%s)\n", $2)); + if(atoi($2) == 0) + yyerror("number expected"); + else { + cfg_parser->cfg->rrset_cache_slabs = atoi($2); + if(!is_pow2(cfg_parser->cfg->rrset_cache_slabs)) + yyerror("must be a power of 2"); + } + free($2); + } + ; +server_infra_host_ttl: VAR_INFRA_HOST_TTL STRING_ARG + { + OUTYY(("P(server_infra_host_ttl:%s)\n", $2)); + if(atoi($2) == 0 && strcmp($2, "0") != 0) + yyerror("number expected"); + else cfg_parser->cfg->host_ttl = atoi($2); + free($2); + } + ; +server_infra_lame_ttl: VAR_INFRA_LAME_TTL STRING_ARG + { + OUTYY(("P(server_infra_lame_ttl:%s)\n", $2)); + verbose(VERB_DETAIL, "ignored infra-lame-ttl: %s (option " + "removed, use infra-host-ttl)", $2); + free($2); + } + ; +server_infra_cache_numhosts: VAR_INFRA_CACHE_NUMHOSTS STRING_ARG + { + OUTYY(("P(server_infra_cache_numhosts:%s)\n", $2)); + if(atoi($2) == 0) + yyerror("number expected"); + else cfg_parser->cfg->infra_cache_numhosts = atoi($2); + free($2); + } + ; +server_infra_cache_lame_size: VAR_INFRA_CACHE_LAME_SIZE STRING_ARG + { + OUTYY(("P(server_infra_cache_lame_size:%s)\n", $2)); + verbose(VERB_DETAIL, "ignored infra-cache-lame-size: %s " + "(option removed, use infra-cache-numhosts)", $2); + free($2); + } + ; +server_infra_cache_slabs: VAR_INFRA_CACHE_SLABS STRING_ARG + { + OUTYY(("P(server_infra_cache_slabs:%s)\n", $2)); + if(atoi($2) == 0) + yyerror("number expected"); + else { + cfg_parser->cfg->infra_cache_slabs = atoi($2); + if(!is_pow2(cfg_parser->cfg->infra_cache_slabs)) + yyerror("must be a power of 2"); + } + free($2); + } + ; +server_target_fetch_policy: VAR_TARGET_FETCH_POLICY STRING_ARG + { + OUTYY(("P(server_target_fetch_policy:%s)\n", $2)); + free(cfg_parser->cfg->target_fetch_policy); + cfg_parser->cfg->target_fetch_policy = $2; + } + ; +server_harden_short_bufsize: VAR_HARDEN_SHORT_BUFSIZE STRING_ARG + { + OUTYY(("P(server_harden_short_bufsize:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->harden_short_bufsize = + (strcmp($2, "yes")==0); + free($2); + } + ; +server_harden_large_queries: VAR_HARDEN_LARGE_QUERIES STRING_ARG + { + OUTYY(("P(server_harden_large_queries:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->harden_large_queries = + (strcmp($2, "yes")==0); + free($2); + } + ; +server_harden_glue: VAR_HARDEN_GLUE STRING_ARG + { + OUTYY(("P(server_harden_glue:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->harden_glue = + (strcmp($2, "yes")==0); + free($2); + } + ; +server_harden_dnssec_stripped: VAR_HARDEN_DNSSEC_STRIPPED STRING_ARG + { + OUTYY(("P(server_harden_dnssec_stripped:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->harden_dnssec_stripped = + (strcmp($2, "yes")==0); + free($2); + } + ; +server_harden_below_nxdomain: VAR_HARDEN_BELOW_NXDOMAIN STRING_ARG + { + OUTYY(("P(server_harden_below_nxdomain:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->harden_below_nxdomain = + (strcmp($2, "yes")==0); + free($2); + } + ; +server_harden_referral_path: VAR_HARDEN_REFERRAL_PATH STRING_ARG + { + OUTYY(("P(server_harden_referral_path:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->harden_referral_path = + (strcmp($2, "yes")==0); + free($2); + } + ; +server_use_caps_for_id: VAR_USE_CAPS_FOR_ID STRING_ARG + { + OUTYY(("P(server_use_caps_for_id:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->use_caps_bits_for_id = + (strcmp($2, "yes")==0); + free($2); + } + ; +server_private_address: VAR_PRIVATE_ADDRESS STRING_ARG + { + OUTYY(("P(server_private_address:%s)\n", $2)); + if(!cfg_strlist_insert(&cfg_parser->cfg->private_address, $2)) + yyerror("out of memory"); + } + ; +server_private_domain: VAR_PRIVATE_DOMAIN STRING_ARG + { + OUTYY(("P(server_private_domain:%s)\n", $2)); + if(!cfg_strlist_insert(&cfg_parser->cfg->private_domain, $2)) + yyerror("out of memory"); + } + ; +server_prefetch: VAR_PREFETCH STRING_ARG + { + OUTYY(("P(server_prefetch:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->prefetch = (strcmp($2, "yes")==0); + free($2); + } + ; +server_prefetch_key: VAR_PREFETCH_KEY STRING_ARG + { + OUTYY(("P(server_prefetch_key:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->prefetch_key = (strcmp($2, "yes")==0); + free($2); + } + ; +server_unwanted_reply_threshold: VAR_UNWANTED_REPLY_THRESHOLD STRING_ARG + { + OUTYY(("P(server_unwanted_reply_threshold:%s)\n", $2)); + if(atoi($2) == 0 && strcmp($2, "0") != 0) + yyerror("number expected"); + else cfg_parser->cfg->unwanted_threshold = atoi($2); + free($2); + } + ; +server_do_not_query_address: VAR_DO_NOT_QUERY_ADDRESS STRING_ARG + { + OUTYY(("P(server_do_not_query_address:%s)\n", $2)); + if(!cfg_strlist_insert(&cfg_parser->cfg->donotqueryaddrs, $2)) + yyerror("out of memory"); + } + ; +server_do_not_query_localhost: VAR_DO_NOT_QUERY_LOCALHOST STRING_ARG + { + OUTYY(("P(server_do_not_query_localhost:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->donotquery_localhost = + (strcmp($2, "yes")==0); + free($2); + } + ; +server_access_control: VAR_ACCESS_CONTROL STRING_ARG STRING_ARG + { + OUTYY(("P(server_access_control:%s %s)\n", $2, $3)); + if(strcmp($3, "deny")!=0 && strcmp($3, "refuse")!=0 && + strcmp($3, "allow")!=0 && + strcmp($3, "allow_snoop")!=0) { + yyerror("expected deny, refuse, allow or allow_snoop " + "in access control action"); + } else { + if(!cfg_str2list_insert(&cfg_parser->cfg->acls, $2, $3)) + fatal_exit("out of memory adding acl"); + } + } + ; +server_module_conf: VAR_MODULE_CONF STRING_ARG + { + OUTYY(("P(server_module_conf:%s)\n", $2)); + free(cfg_parser->cfg->module_conf); + cfg_parser->cfg->module_conf = $2; + } + ; +server_val_override_date: VAR_VAL_OVERRIDE_DATE STRING_ARG + { + OUTYY(("P(server_val_override_date:%s)\n", $2)); + if(strlen($2) == 0 || strcmp($2, "0") == 0) { + cfg_parser->cfg->val_date_override = 0; + } else if(strlen($2) == 14) { + cfg_parser->cfg->val_date_override = + cfg_convert_timeval($2); + if(!cfg_parser->cfg->val_date_override) + yyerror("bad date/time specification"); + } else { + if(atoi($2) == 0) + yyerror("number expected"); + cfg_parser->cfg->val_date_override = atoi($2); + } + free($2); + } + ; +server_val_sig_skew_min: VAR_VAL_SIG_SKEW_MIN STRING_ARG + { + OUTYY(("P(server_val_sig_skew_min:%s)\n", $2)); + if(strlen($2) == 0 || strcmp($2, "0") == 0) { + cfg_parser->cfg->val_sig_skew_min = 0; + } else { + cfg_parser->cfg->val_sig_skew_min = atoi($2); + if(!cfg_parser->cfg->val_sig_skew_min) + yyerror("number expected"); + } + free($2); + } + ; +server_val_sig_skew_max: VAR_VAL_SIG_SKEW_MAX STRING_ARG + { + OUTYY(("P(server_val_sig_skew_max:%s)\n", $2)); + if(strlen($2) == 0 || strcmp($2, "0") == 0) { + cfg_parser->cfg->val_sig_skew_max = 0; + } else { + cfg_parser->cfg->val_sig_skew_max = atoi($2); + if(!cfg_parser->cfg->val_sig_skew_max) + yyerror("number expected"); + } + free($2); + } + ; +server_cache_max_ttl: VAR_CACHE_MAX_TTL STRING_ARG + { + OUTYY(("P(server_cache_max_ttl:%s)\n", $2)); + if(atoi($2) == 0 && strcmp($2, "0") != 0) + yyerror("number expected"); + else cfg_parser->cfg->max_ttl = atoi($2); + free($2); + } + ; +server_cache_min_ttl: VAR_CACHE_MIN_TTL STRING_ARG + { + OUTYY(("P(server_cache_min_ttl:%s)\n", $2)); + if(atoi($2) == 0 && strcmp($2, "0") != 0) + yyerror("number expected"); + else cfg_parser->cfg->min_ttl = atoi($2); + free($2); + } + ; +server_bogus_ttl: VAR_BOGUS_TTL STRING_ARG + { + OUTYY(("P(server_bogus_ttl:%s)\n", $2)); + if(atoi($2) == 0 && strcmp($2, "0") != 0) + yyerror("number expected"); + else cfg_parser->cfg->bogus_ttl = atoi($2); + free($2); + } + ; +server_val_clean_additional: VAR_VAL_CLEAN_ADDITIONAL STRING_ARG + { + OUTYY(("P(server_val_clean_additional:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->val_clean_additional = + (strcmp($2, "yes")==0); + free($2); + } + ; +server_val_permissive_mode: VAR_VAL_PERMISSIVE_MODE STRING_ARG + { + OUTYY(("P(server_val_permissive_mode:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->val_permissive_mode = + (strcmp($2, "yes")==0); + free($2); + } + ; +server_ignore_cd_flag: VAR_IGNORE_CD_FLAG STRING_ARG + { + OUTYY(("P(server_ignore_cd_flag:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->ignore_cd = (strcmp($2, "yes")==0); + free($2); + } + ; +server_val_log_level: VAR_VAL_LOG_LEVEL STRING_ARG + { + OUTYY(("P(server_val_log_level:%s)\n", $2)); + if(atoi($2) == 0 && strcmp($2, "0") != 0) + yyerror("number expected"); + else cfg_parser->cfg->val_log_level = atoi($2); + free($2); + } + ; +server_val_nsec3_keysize_iterations: VAR_VAL_NSEC3_KEYSIZE_ITERATIONS STRING_ARG + { + OUTYY(("P(server_val_nsec3_keysize_iterations:%s)\n", $2)); + free(cfg_parser->cfg->val_nsec3_key_iterations); + cfg_parser->cfg->val_nsec3_key_iterations = $2; + } + ; +server_add_holddown: VAR_ADD_HOLDDOWN STRING_ARG + { + OUTYY(("P(server_add_holddown:%s)\n", $2)); + if(atoi($2) == 0 && strcmp($2, "0") != 0) + yyerror("number expected"); + else cfg_parser->cfg->add_holddown = atoi($2); + free($2); + } + ; +server_del_holddown: VAR_DEL_HOLDDOWN STRING_ARG + { + OUTYY(("P(server_del_holddown:%s)\n", $2)); + if(atoi($2) == 0 && strcmp($2, "0") != 0) + yyerror("number expected"); + else cfg_parser->cfg->del_holddown = atoi($2); + free($2); + } + ; +server_keep_missing: VAR_KEEP_MISSING STRING_ARG + { + OUTYY(("P(server_keep_missing:%s)\n", $2)); + if(atoi($2) == 0 && strcmp($2, "0") != 0) + yyerror("number expected"); + else cfg_parser->cfg->keep_missing = atoi($2); + free($2); + } + ; +server_key_cache_size: VAR_KEY_CACHE_SIZE STRING_ARG + { + OUTYY(("P(server_key_cache_size:%s)\n", $2)); + if(!cfg_parse_memsize($2, &cfg_parser->cfg->key_cache_size)) + yyerror("memory size expected"); + free($2); + } + ; +server_key_cache_slabs: VAR_KEY_CACHE_SLABS STRING_ARG + { + OUTYY(("P(server_key_cache_slabs:%s)\n", $2)); + if(atoi($2) == 0) + yyerror("number expected"); + else { + cfg_parser->cfg->key_cache_slabs = atoi($2); + if(!is_pow2(cfg_parser->cfg->key_cache_slabs)) + yyerror("must be a power of 2"); + } + free($2); + } + ; +server_neg_cache_size: VAR_NEG_CACHE_SIZE STRING_ARG + { + OUTYY(("P(server_neg_cache_size:%s)\n", $2)); + if(!cfg_parse_memsize($2, &cfg_parser->cfg->neg_cache_size)) + yyerror("memory size expected"); + free($2); + } + ; +server_local_zone: VAR_LOCAL_ZONE STRING_ARG STRING_ARG + { + OUTYY(("P(server_local_zone:%s %s)\n", $2, $3)); + 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) + yyerror("local-zone type: expected static, deny, " + "refuse, redirect, transparent, " + "typetransparent or nodefault"); + else if(strcmp($3, "nodefault")==0) { + if(!cfg_strlist_insert(&cfg_parser->cfg-> + local_zones_nodefault, $2)) + fatal_exit("out of memory adding local-zone"); + free($3); + } else { + if(!cfg_str2list_insert(&cfg_parser->cfg->local_zones, + $2, $3)) + fatal_exit("out of memory adding local-zone"); + } + } + ; +server_local_data: VAR_LOCAL_DATA STRING_ARG + { + OUTYY(("P(server_local_data:%s)\n", $2)); + if(!cfg_strlist_insert(&cfg_parser->cfg->local_data, $2)) + fatal_exit("out of memory adding local-data"); + } + ; +server_local_data_ptr: VAR_LOCAL_DATA_PTR STRING_ARG + { + char* ptr; + OUTYY(("P(server_local_data_ptr:%s)\n", $2)); + ptr = cfg_ptr_reverse($2); + free($2); + if(ptr) { + if(!cfg_strlist_insert(&cfg_parser->cfg-> + local_data, ptr)) + fatal_exit("out of memory adding local-data"); + } else { + yyerror("local-data-ptr could not be reversed"); + } + } + ; +server_minimal_responses: VAR_MINIMAL_RESPONSES STRING_ARG + { + OUTYY(("P(server_minimal_responses:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->minimal_responses = + (strcmp($2, "yes")==0); + free($2); + } + ; +server_rrset_roundrobin: VAR_RRSET_ROUNDROBIN STRING_ARG + { + OUTYY(("P(server_rrset_roundrobin:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->rrset_roundrobin = + (strcmp($2, "yes")==0); + free($2); + } + ; +stub_name: VAR_NAME STRING_ARG + { + OUTYY(("P(name:%s)\n", $2)); + if(cfg_parser->cfg->stubs->name) + yyerror("stub name override, there must be one name " + "for one stub-zone"); + free(cfg_parser->cfg->stubs->name); + cfg_parser->cfg->stubs->name = $2; + } + ; +stub_host: VAR_STUB_HOST STRING_ARG + { + OUTYY(("P(stub-host:%s)\n", $2)); + if(!cfg_strlist_insert(&cfg_parser->cfg->stubs->hosts, $2)) + yyerror("out of memory"); + } + ; +stub_addr: VAR_STUB_ADDR STRING_ARG + { + OUTYY(("P(stub-addr:%s)\n", $2)); + if(!cfg_strlist_insert(&cfg_parser->cfg->stubs->addrs, $2)) + yyerror("out of memory"); + } + ; +stub_first: VAR_STUB_FIRST STRING_ARG + { + OUTYY(("P(stub-first:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->stubs->isfirst=(strcmp($2, "yes")==0); + free($2); + } + ; +stub_prime: VAR_STUB_PRIME STRING_ARG + { + OUTYY(("P(stub-prime:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->stubs->isprime = + (strcmp($2, "yes")==0); + free($2); + } + ; +forward_name: VAR_NAME STRING_ARG + { + OUTYY(("P(name:%s)\n", $2)); + if(cfg_parser->cfg->forwards->name) + yyerror("forward name override, there must be one " + "name for one forward-zone"); + free(cfg_parser->cfg->forwards->name); + cfg_parser->cfg->forwards->name = $2; + } + ; +forward_host: VAR_FORWARD_HOST STRING_ARG + { + OUTYY(("P(forward-host:%s)\n", $2)); + if(!cfg_strlist_insert(&cfg_parser->cfg->forwards->hosts, $2)) + yyerror("out of memory"); + } + ; +forward_addr: VAR_FORWARD_ADDR STRING_ARG + { + OUTYY(("P(forward-addr:%s)\n", $2)); + if(!cfg_strlist_insert(&cfg_parser->cfg->forwards->addrs, $2)) + yyerror("out of memory"); + } + ; +forward_first: VAR_FORWARD_FIRST STRING_ARG + { + OUTYY(("P(forward-first:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->forwards->isfirst=(strcmp($2, "yes")==0); + free($2); + } + ; +rcstart: VAR_REMOTE_CONTROL + { + OUTYY(("\nP(remote-control:)\n")); + } + ; +contents_rc: contents_rc content_rc + | ; +content_rc: rc_control_enable | rc_control_interface | rc_control_port | + rc_server_key_file | rc_server_cert_file | rc_control_key_file | + rc_control_cert_file + ; +rc_control_enable: VAR_CONTROL_ENABLE STRING_ARG + { + OUTYY(("P(control_enable:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->remote_control_enable = + (strcmp($2, "yes")==0); + free($2); + } + ; +rc_control_port: VAR_CONTROL_PORT STRING_ARG + { + OUTYY(("P(control_port:%s)\n", $2)); + if(atoi($2) == 0) + yyerror("control port number expected"); + else cfg_parser->cfg->control_port = atoi($2); + free($2); + } + ; +rc_control_interface: VAR_CONTROL_INTERFACE STRING_ARG + { + OUTYY(("P(control_interface:%s)\n", $2)); + if(!cfg_strlist_insert(&cfg_parser->cfg->control_ifs, $2)) + yyerror("out of memory"); + } + ; +rc_server_key_file: VAR_SERVER_KEY_FILE STRING_ARG + { + OUTYY(("P(rc_server_key_file:%s)\n", $2)); + free(cfg_parser->cfg->server_key_file); + cfg_parser->cfg->server_key_file = $2; + } + ; +rc_server_cert_file: VAR_SERVER_CERT_FILE STRING_ARG + { + OUTYY(("P(rc_server_cert_file:%s)\n", $2)); + free(cfg_parser->cfg->server_cert_file); + cfg_parser->cfg->server_cert_file = $2; + } + ; +rc_control_key_file: VAR_CONTROL_KEY_FILE STRING_ARG + { + OUTYY(("P(rc_control_key_file:%s)\n", $2)); + free(cfg_parser->cfg->control_key_file); + cfg_parser->cfg->control_key_file = $2; + } + ; +rc_control_cert_file: VAR_CONTROL_CERT_FILE STRING_ARG + { + OUTYY(("P(rc_control_cert_file:%s)\n", $2)); + free(cfg_parser->cfg->control_cert_file); + cfg_parser->cfg->control_cert_file = $2; + } + ; +pythonstart: VAR_PYTHON + { + OUTYY(("\nP(python:)\n")); + } + ; +contents_py: contents_py content_py + | ; +content_py: py_script + ; +py_script: VAR_PYTHON_SCRIPT STRING_ARG + { + OUTYY(("P(python-script:%s)\n", $2)); + free(cfg_parser->cfg->python_script); + cfg_parser->cfg->python_script = $2; + } +%% + +/* parse helper routines could be here */ diff --git a/util/configyyrename.h b/util/configyyrename.h new file mode 100644 index 00000000000..f529be57727 --- /dev/null +++ b/util/configyyrename.h @@ -0,0 +1,88 @@ +/* + * configyyrename.h -- renames for config file yy values to avoid conflicts. + * + * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. + * + * See LICENSE for the license. + * + */ + +#ifndef UTIL_CONFIGYYRENAME_H +#define UTIL_CONFIGYYRENAME_H + +/* defines to change symbols so that no yacc/lex symbols clash */ +#define yymaxdepth ub_c_maxdepth +#define yyparse ub_c_parse +#define yylex ub_c_lex +#define yyerror ub_c_error +#define yylval ub_c_lval +#define yychar ub_c_char +#define yydebug ub_c_debug +#define yypact ub_c_pact +#define yyr1 ub_c_r1 +#define yyr2 ub_c_r2 +#define yydef ub_c_def +#define yychk ub_c_chk +#define yypgo ub_c_pgo +#define yyact ub_c_act +#define yyexca ub_c_exca +#define yyerrflag ub_c_errflag +#define yynerrs ub_c_nerrs +#define yyps ub_c_ps +#define yypv ub_c_pv +#define yys ub_c_s +#define yy_yys ub_c_yys +#define yystate ub_c_state +#define yytmp ub_c_tmp +#define yyv ub_c_v +#define yy_yyv ub_c_yyv +#define yyval ub_c_val +#define yylloc ub_c_lloc +#define yyreds ub_c_reds +#define yytoks ub_c_toks +#define yylhs ub_c_yylhs +#define yylen ub_c_yylen +#define yydefred ub_c_yydefred +#define yydgoto ub_c_yydgoto +#define yysindex ub_c_yysindex +#define yyrindex ub_c_yyrindex +#define yygindex ub_c_yygindex +#define yytable ub_c_yytable +#define yycheck ub_c_yycheck +#define yyname ub_c_yyname +#define yyrule ub_c_yyrule +#define yyin ub_c_in +#define yyout ub_c_out +#define yywrap ub_c_wrap +#define yy_load_buffer_state ub_c_load_buffer_state +#define yy_switch_to_buffer ub_c_switch_to_buffer +#define yy_flush_buffer ub_c_flush_buffer +#define yy_init_buffer ub_c_init_buffer +#define yy_scan_buffer ub_c_scan_buffer +#define yy_scan_bytes ub_c_scan_bytes +#define yy_scan_string ub_c_scan_string +#define yy_create_buffer ub_c_create_buffer +#define yyrestart ub_c_restart +#define yy_delete_buffer ub_c_delete_buffer +#define yypop_buffer_state ub_c_pop_buffer_state +#define yypush_buffer_state ub_c_push_buffer_state +#define yyunput ub_c_unput +#define yyset_in ub_c_set_in +#define yyget_in ub_c_get_in +#define yyset_out ub_c_set_out +#define yyget_out ub_c_get_out +#define yyget_lineno ub_c_get_lineno +#define yyset_lineno ub_c_set_lineno +#define yyset_debug ub_c_set_debug +#define yyget_debug ub_c_get_debug +#define yy_flex_debug ub_c_flex_debug +#define yylex_destroy ub_c_lex_destroy +#define yyfree ub_c_free +#define yyrealloc ub_c_realloc +#define yyalloc ub_c_alloc +#define yymalloc ub_c_malloc +#define yyget_leng ub_c_get_leng +#define yylineno ub_c_lineno +#define yyget_text ub_c_get_text + +#endif /* UTIL_CONFIGYYRENAME_H */ diff --git a/util/data/dname.c b/util/data/dname.c new file mode 100644 index 00000000000..d2b299744fb --- /dev/null +++ b/util/data/dname.c @@ -0,0 +1,781 @@ +/* + * util/data/dname.h - domain name handling + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains domain name handling functions. + */ + +#include "config.h" +#include +#include "util/data/dname.h" +#include "util/data/msgparse.h" +#include "util/log.h" +#include "util/storage/lookup3.h" + +/* determine length of a dname in buffer, no compression pointers allowed */ +size_t +query_dname_len(ldns_buffer* query) +{ + size_t len = 0; + size_t labellen; + while(1) { + if(ldns_buffer_remaining(query) < 1) + return 0; /* parse error, need label len */ + labellen = ldns_buffer_read_u8(query); + if(labellen&0xc0) + return 0; /* no compression allowed in queries */ + len += labellen + 1; + if(len > LDNS_MAX_DOMAINLEN) + return 0; /* too long */ + if(labellen == 0) + return len; + if(ldns_buffer_remaining(query) < labellen) + return 0; /* parse error, need content */ + ldns_buffer_skip(query, (ssize_t)labellen); + } +} + +size_t +dname_valid(uint8_t* dname, size_t maxlen) +{ + size_t len = 0; + size_t labellen; + labellen = *dname++; + while(labellen) { + if(labellen&0xc0) + return 0; /* no compression ptrs allowed */ + len += labellen + 1; + if(len >= LDNS_MAX_DOMAINLEN) + return 0; /* too long */ + if(len > maxlen) + return 0; /* does not fit in memory allocation */ + dname += labellen; + labellen = *dname++; + } + len += 1; + if(len > maxlen) + return 0; /* does not fit in memory allocation */ + return len; +} + +/** compare uncompressed, noncanonical, registers are hints for speed */ +int +query_dname_compare(register uint8_t* d1, register uint8_t* d2) +{ + register uint8_t lab1, lab2; + log_assert(d1 && d2); + lab1 = *d1++; + lab2 = *d2++; + while( lab1 != 0 || lab2 != 0 ) { + /* compare label length */ + /* if one dname ends, it has labellength 0 */ + if(lab1 != lab2) { + if(lab1 < lab2) + return -1; + return 1; + } + log_assert(lab1 == lab2 && lab1 != 0); + /* compare lowercased labels. */ + while(lab1--) { + /* compare bytes first for speed */ + if(*d1 != *d2 && + tolower((int)*d1) != tolower((int)*d2)) { + if(tolower((int)*d1) < tolower((int)*d2)) + return -1; + return 1; + } + d1++; + d2++; + } + /* next pair of labels. */ + lab1 = *d1++; + lab2 = *d2++; + } + return 0; +} + +void +query_dname_tolower(uint8_t* dname) +{ + /* the dname is stored uncompressed */ + uint8_t labellen; + labellen = *dname; + while(labellen) { + dname++; + while(labellen--) { + *dname = (uint8_t)tolower((int)*dname); + dname++; + } + labellen = *dname; + } +} + +void +pkt_dname_tolower(ldns_buffer* pkt, uint8_t* dname) +{ + uint8_t lablen; + int count = 0; + if(dname >= ldns_buffer_end(pkt)) + return; + lablen = *dname++; + while(lablen) { + if(LABEL_IS_PTR(lablen)) { + if((size_t)PTR_OFFSET(lablen, *dname) + >= ldns_buffer_limit(pkt)) + return; + dname = ldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname)); + lablen = *dname++; + if(count++ > MAX_COMPRESS_PTRS) + return; + continue; + } + if(dname+lablen >= ldns_buffer_end(pkt)) + return; + while(lablen--) { + *dname = (uint8_t)tolower((int)*dname); + dname++; + } + if(dname >= ldns_buffer_end(pkt)) + return; + lablen = *dname++; + } +} + + +size_t +pkt_dname_len(ldns_buffer* pkt) +{ + size_t len = 0; + int ptrcount = 0; + uint8_t labellen; + size_t endpos = 0; + + /* read dname and determine length */ + /* check compression pointers, loops, out of bounds */ + while(1) { + /* read next label */ + if(ldns_buffer_remaining(pkt) < 1) + return 0; + labellen = ldns_buffer_read_u8(pkt); + if(LABEL_IS_PTR(labellen)) { + /* compression ptr */ + uint16_t ptr; + if(ldns_buffer_remaining(pkt) < 1) + return 0; + ptr = PTR_OFFSET(labellen, ldns_buffer_read_u8(pkt)); + if(ptrcount++ > MAX_COMPRESS_PTRS) + return 0; /* loop! */ + if(ldns_buffer_limit(pkt) <= ptr) + return 0; /* out of bounds! */ + if(!endpos) + endpos = ldns_buffer_position(pkt); + ldns_buffer_set_position(pkt, ptr); + } else { + /* label contents */ + if(labellen > 0x3f) + return 0; /* label too long */ + len += 1 + labellen; + if(len > LDNS_MAX_DOMAINLEN) + return 0; + if(labellen == 0) { + /* end of dname */ + break; + } + if(ldns_buffer_remaining(pkt) < labellen) + return 0; + ldns_buffer_skip(pkt, (ssize_t)labellen); + } + } + if(endpos) + ldns_buffer_set_position(pkt, endpos); + + return len; +} + +int +dname_pkt_compare(ldns_buffer* pkt, uint8_t* d1, uint8_t* d2) +{ + uint8_t len1, len2; + log_assert(pkt && d1 && d2); + len1 = *d1++; + len2 = *d2++; + while( len1 != 0 || len2 != 0 ) { + /* resolve ptrs */ + if(LABEL_IS_PTR(len1)) { + d1 = ldns_buffer_at(pkt, PTR_OFFSET(len1, *d1)); + len1 = *d1++; + continue; + } + if(LABEL_IS_PTR(len2)) { + d2 = ldns_buffer_at(pkt, PTR_OFFSET(len2, *d2)); + len2 = *d2++; + continue; + } + /* check label length */ + log_assert(len1 <= LDNS_MAX_LABELLEN); + log_assert(len2 <= LDNS_MAX_LABELLEN); + if(len1 != len2) { + if(len1 < len2) return -1; + return 1; + } + log_assert(len1 == len2 && len1 != 0); + /* compare labels */ + while(len1--) { + if(tolower((int)*d1++) != tolower((int)*d2++)) { + if(tolower((int)d1[-1]) < tolower((int)d2[-1])) + return -1; + return 1; + } + } + len1 = *d1++; + len2 = *d2++; + } + return 0; +} + +hashvalue_t +dname_query_hash(uint8_t* dname, hashvalue_t h) +{ + uint8_t labuf[LDNS_MAX_LABELLEN+1]; + uint8_t lablen; + int i; + + /* preserve case of query, make hash label by label */ + lablen = *dname++; + while(lablen) { + log_assert(lablen <= LDNS_MAX_LABELLEN); + labuf[0] = lablen; + i=0; + while(lablen--) + labuf[++i] = (uint8_t)tolower((int)*dname++); + h = hashlittle(labuf, labuf[0] + 1, h); + lablen = *dname++; + } + + return h; +} + +hashvalue_t +dname_pkt_hash(ldns_buffer* pkt, uint8_t* dname, hashvalue_t h) +{ + uint8_t labuf[LDNS_MAX_LABELLEN+1]; + uint8_t lablen; + int i; + + /* preserve case of query, make hash label by label */ + lablen = *dname++; + while(lablen) { + if(LABEL_IS_PTR(lablen)) { + /* follow pointer */ + dname = ldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname)); + lablen = *dname++; + continue; + } + log_assert(lablen <= LDNS_MAX_LABELLEN); + labuf[0] = lablen; + i=0; + while(lablen--) + labuf[++i] = (uint8_t)tolower((int)*dname++); + h = hashlittle(labuf, labuf[0] + 1, h); + lablen = *dname++; + } + + return h; +} + +void dname_pkt_copy(ldns_buffer* pkt, uint8_t* to, uint8_t* dname) +{ + /* copy over the dname and decompress it at the same time */ + size_t len = 0; + uint8_t lablen; + lablen = *dname++; + while(lablen) { + if(LABEL_IS_PTR(lablen)) { + /* follow pointer */ + dname = ldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname)); + lablen = *dname++; + continue; + } + log_assert(lablen <= LDNS_MAX_LABELLEN); + len += (size_t)lablen+1; + if(len >= LDNS_MAX_DOMAINLEN) { + *to = 0; /* end the result prematurely */ + log_err("bad dname in dname_pkt_copy"); + return; + } + *to++ = lablen; + memmove(to, dname, lablen); + dname += lablen; + to += lablen; + lablen = *dname++; + } + /* copy last \0 */ + *to = 0; +} + +void dname_print(FILE* out, ldns_buffer* pkt, uint8_t* dname) +{ + uint8_t lablen; + if(!out) out = stdout; + if(!dname) return; + + lablen = *dname++; + if(!lablen) + fputc('.', out); + while(lablen) { + if(LABEL_IS_PTR(lablen)) { + /* follow pointer */ + if(!pkt) { + fputs("??compressionptr??", out); + return; + } + dname = ldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname)); + lablen = *dname++; + continue; + } + if(lablen > LDNS_MAX_LABELLEN) { + fputs("??extendedlabel??", out); + return; + } + while(lablen--) + fputc((int)*dname++, out); + fputc('.', out); + lablen = *dname++; + } +} + +int +dname_count_labels(uint8_t* dname) +{ + uint8_t lablen; + int labs = 1; + + lablen = *dname++; + while(lablen) { + labs++; + dname += lablen; + lablen = *dname++; + } + return labs; +} + +int +dname_count_size_labels(uint8_t* dname, size_t* size) +{ + uint8_t lablen; + int labs = 1; + size_t sz = 1; + + lablen = *dname++; + while(lablen) { + labs++; + sz += lablen+1; + dname += lablen; + lablen = *dname++; + } + *size = sz; + return labs; +} + +/** + * Compare labels in memory, lowercase while comparing. + * @param p1: label 1 + * @param p2: label 2 + * @param len: number of bytes to compare. + * @return: 0, -1, +1 comparison result. + */ +static int +memlowercmp(uint8_t* p1, uint8_t* p2, uint8_t len) +{ + while(len--) { + if(*p1 != *p2 && tolower((int)*p1) != tolower((int)*p2)) { + if(tolower((int)*p1) < tolower((int)*p2)) + return -1; + return 1; + } + p1++; + p2++; + } + return 0; +} + +int +dname_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, int* mlabs) +{ + uint8_t len1, len2; + int atlabel = labs1; + int lastmlabs; + int lastdiff = 0; + /* first skip so that we compare same label. */ + if(labs1 > labs2) { + while(atlabel > labs2) { + len1 = *d1++; + d1 += len1; + atlabel--; + } + log_assert(atlabel == labs2); + } else if(labs1 < labs2) { + atlabel = labs2; + while(atlabel > labs1) { + len2 = *d2++; + d2 += len2; + atlabel--; + } + log_assert(atlabel == labs1); + } + lastmlabs = atlabel+1; + /* now at same label in d1 and d2, atlabel */ + /* www.example.com. */ + /* 4 3 2 1 atlabel number */ + /* repeat until at root label (which is always the same) */ + while(atlabel > 1) { + len1 = *d1++; + len2 = *d2++; + if(len1 != len2) { + log_assert(len1 != 0 && len2 != 0); + if(len1 com. */ + if(labs1 > labs2) + return 1; + else if(labs1 < labs2) + return -1; + } + return lastdiff; +} + +int +dname_buffer_write(ldns_buffer* pkt, uint8_t* dname) +{ + uint8_t lablen; + + if(ldns_buffer_remaining(pkt) < 1) + return 0; + lablen = *dname++; + ldns_buffer_write_u8(pkt, lablen); + while(lablen) { + if(ldns_buffer_remaining(pkt) < (size_t)lablen+1) + return 0; + ldns_buffer_write(pkt, dname, lablen); + dname += lablen; + lablen = *dname++; + ldns_buffer_write_u8(pkt, lablen); + } + return 1; +} + +void dname_str(uint8_t* dname, char* str) +{ + size_t len = 0; + uint8_t lablen = 0; + char* s = str; + if(!dname || !*dname) { + *s++ = '.'; + *s = 0; + return; + } + lablen = *dname++; + while(lablen) { + if(lablen > LDNS_MAX_LABELLEN) { + *s++ = '#'; + *s = 0; + return; + } + len += lablen+1; + if(len >= LDNS_MAX_DOMAINLEN-1) { + *s++ = '&'; + *s = 0; + return; + } + while(lablen--) { + if(isalnum((int)*dname) + || *dname == '-' || *dname == '_' + || *dname == '*') + *s++ = *(char*)dname++; + else { + *s++ = '?'; + dname++; + } + } + *s++ = '.'; + lablen = *dname++; + } + *s = 0; +} + +int +dname_strict_subdomain(uint8_t* d1, int labs1, uint8_t* d2, int labs2) +{ + int m; + /* check subdomain: d1: www.example.com. and d2: example.com. */ + if(labs2 >= labs1) + return 0; + if(dname_lab_cmp(d1, labs1, d2, labs2, &m) > 0) { + /* subdomain if all labels match */ + return (m == labs2); + } + return 0; +} + +int +dname_strict_subdomain_c(uint8_t* d1, uint8_t* d2) +{ + return dname_strict_subdomain(d1, dname_count_labels(d1), d2, + dname_count_labels(d2)); +} + +int +dname_subdomain_c(uint8_t* d1, uint8_t* d2) +{ + int m; + /* check subdomain: d1: www.example.com. and d2: example.com. */ + /* or d1: example.com. and d2: example.com. */ + int labs1 = dname_count_labels(d1); + int labs2 = dname_count_labels(d2); + if(labs2 > labs1) + return 0; + if(dname_lab_cmp(d1, labs1, d2, labs2, &m) < 0) { + /* must have been example.com , www.example.com - wrong */ + /* or otherwise different dnames */ + return 0; + } + return (m == labs2); +} + +int +dname_is_root(uint8_t* dname) +{ + uint8_t len; + log_assert(dname); + len = dname[0]; + log_assert(!LABEL_IS_PTR(len)); + return (len == 0); +} + +void +dname_remove_label(uint8_t** dname, size_t* len) +{ + size_t lablen; + log_assert(dname && *dname && len); + lablen = (*dname)[0]; + log_assert(!LABEL_IS_PTR(lablen)); + log_assert(*len > lablen); + if(lablen == 0) + return; /* do not modify root label */ + *len -= lablen+1; + *dname += lablen+1; +} + +void +dname_remove_labels(uint8_t** dname, size_t* len, int n) +{ + int i; + for(i=0; i len2) + return 1; + return 0; +} + + +int +dname_canon_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, int* mlabs) +{ + /* like dname_lab_cmp, but with different label comparison, + * empty character sorts before \000. + * So ylyly is before z. */ + uint8_t len1, len2; + int atlabel = labs1; + int lastmlabs; + int lastdiff = 0; + int c; + /* first skip so that we compare same label. */ + if(labs1 > labs2) { + while(atlabel > labs2) { + len1 = *d1++; + d1 += len1; + atlabel--; + } + log_assert(atlabel == labs2); + } else if(labs1 < labs2) { + atlabel = labs2; + while(atlabel > labs1) { + len2 = *d2++; + d2 += len2; + atlabel--; + } + log_assert(atlabel == labs1); + } + lastmlabs = atlabel+1; + /* now at same label in d1 and d2, atlabel */ + /* www.example.com. */ + /* 4 3 2 1 atlabel number */ + /* repeat until at root label (which is always the same) */ + while(atlabel > 1) { + len1 = *d1++; + len2 = *d2++; + + if((c=memcanoncmp(d1, len1, d2, len2)) != 0) { + if(c<0) + lastdiff = -1; + else lastdiff = 1; + lastmlabs = atlabel; + } + + d1 += len1; + d2 += len2; + atlabel--; + } + /* last difference atlabel number, so number of labels matching, + * at the right side, is one less. */ + *mlabs = lastmlabs-1; + if(lastdiff == 0) { + /* all labels compared were equal, check if one has more + * labels, so that example.com. > com. */ + if(labs1 > labs2) + return 1; + else if(labs1 < labs2) + return -1; + } + return lastdiff; +} + +int +dname_canonical_compare(uint8_t* d1, uint8_t* d2) +{ + int labs1, labs2, m; + labs1 = dname_count_labels(d1); + labs2 = dname_count_labels(d2); + return dname_canon_lab_cmp(d1, labs1, d2, labs2, &m); +} + +uint8_t* dname_get_shared_topdomain(uint8_t* d1, uint8_t* d2) +{ + int labs1, labs2, m; + size_t len = LDNS_MAX_DOMAINLEN; + labs1 = dname_count_labels(d1); + labs2 = dname_count_labels(d2); + (void)dname_lab_cmp(d1, labs1, d2, labs2, &m); + dname_remove_labels(&d1, &len, labs1-m); + return d1; +} diff --git a/util/data/dname.h b/util/data/dname.h new file mode 100644 index 00000000000..b942848a9dc --- /dev/null +++ b/util/data/dname.h @@ -0,0 +1,303 @@ +/* + * util/data/dname.h - domain name routines + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions to deal with domain names (dnames). + * + * Some of the functions deal with domain names as a wireformat buffer, + * with a length. + */ + +#ifndef UTIL_DATA_DNAME_H +#define UTIL_DATA_DNAME_H +#include "util/storage/lruhash.h" + +/** max number of compression ptrs to follow */ +#define MAX_COMPRESS_PTRS 256 + +/** + * Determine length of dname in buffer, no compression ptrs allowed, + * @param query: the ldns buffer, current position at start of dname. + * at end, position is at end of the dname. + * @return: 0 on parse failure, or length including ending 0 of dname. + */ +size_t query_dname_len(ldns_buffer* query); + +/** + * Determine if dname in memory is correct. no compression ptrs allowed. + * @param dname: where dname starts in memory. + * @param len: dname is not allowed to exceed this length (i.e. of allocation). + * @return length of dname if dname is ok, 0 on a parse error. + */ +size_t dname_valid(uint8_t* dname, size_t len); + +/** lowercase query dname */ +void query_dname_tolower(uint8_t* dname); + +/** + * lowercase pkt dname (follows compression pointers) + * @param pkt: the packet, used to follow compression pointers. Position + * is unchanged. + * @param dname: start of dname in packet. + */ +void pkt_dname_tolower(ldns_buffer* pkt, uint8_t* dname); + +/** + * Compare query dnames (uncompressed storage). The Dnames passed do not + * have to be lowercased, comparison routine does this. + * + * This routine is special, in that the comparison that it does corresponds + * with the canonical comparison needed when comparing dnames inside rdata + * for RR types that need canonicalization. That means that the first byte + * that is smaller (possibly after lowercasing) makes an RR smaller, or the + * shortest name makes an RR smaller. + * + * This routine does not compute the canonical order needed for NSEC + * processing. + * + * Dnames have to be valid format. + * @param d1: dname to compare + * @param d2: dname to compare + * @return: -1, 0, or +1 depending on comparison results. + * Sort order is first difference found. not the canonical ordering. + */ +int query_dname_compare(uint8_t* d1, uint8_t* d2); + +/** + * Determine correct, compressed, dname present in packet. + * Checks for parse errors. + * @param pkt: packet to read from (from current start position). + * @return: 0 on parse error. + * At exit the position is right after the (compressed) dname. + * Compression pointers are followed and checked for loops. + * The uncompressed wireformat length is returned. + */ +size_t pkt_dname_len(ldns_buffer* pkt); + +/** + * Compare dnames in packet (compressed). Dnames must be valid. + * routine performs lowercasing, so the packet casing is preserved. + * @param pkt: packet, used to resolve compression pointers. + * @param d1: dname to compare + * @param d2: dname to compare + * @return: -1, 0, or +1 depending on comparison results. + * Sort order is first difference found. not the canonical ordering. + */ +int dname_pkt_compare(ldns_buffer* pkt, uint8_t* d1, uint8_t* d2); + +/** + * Hash dname, label by label, lowercasing, into hashvalue. + * Dname in query format (not compressed). + * @param dname: dname to hash. + * @param h: initial hash value. + * @return: result hash value. + */ +hashvalue_t dname_query_hash(uint8_t* dname, hashvalue_t h); + +/** + * Hash dname, label by label, lowercasing, into hashvalue. + * Dname in pkt format (compressed). + * @param pkt: packet, for resolving compression pointers. + * @param dname: dname to hash, pointer to the pkt buffer. + * Must be valid format. No loops, etc. + * @param h: initial hash value. + * @return: result hash value. + * Result is the same as dname_query_hash, even if compression is used. + */ +hashvalue_t dname_pkt_hash(ldns_buffer* pkt, uint8_t* dname, hashvalue_t h); + +/** + * Copy over a valid dname and decompress it. + * @param pkt: packet to resolve compression pointers. + * @param to: buffer of size from pkt_len function to hold result. + * @param dname: pointer into packet where dname starts. + */ +void dname_pkt_copy(ldns_buffer* pkt, uint8_t* to, uint8_t* dname); + +/** + * Copy over a valid dname to a packet. + * @param pkt: packet to copy to. + * @param dname: dname to copy. + * @return: 0 if not enough space in buffer. + */ +int dname_buffer_write(ldns_buffer* pkt, uint8_t* dname); + +/** + * Count the number of labels in an uncompressed dname in memory. + * @param dname: pointer to uncompressed dname. + * @return: count of labels, including root label, "com." has 2 labels. + */ +int dname_count_labels(uint8_t* dname); + +/** + * Count labels and dname length both, for uncompressed dname in memory. + * @param dname: pointer to uncompressed dname. + * @param size: length of dname, including root label. + * @return: count of labels, including root label, "com." has 2 labels. + */ +int dname_count_size_labels(uint8_t* dname, size_t* size); + +/** + * Compare dnames, sorted not canonical, but by label. + * Such that zone contents follows zone apex. + * @param d1: first dname. pointer to uncompressed wireformat. + * @param labs1: number of labels in first dname. + * @param d2: second dname. pointer to uncompressed wireformat. + * @param labs2: number of labels in second dname. + * @param mlabs: number of labels that matched exactly (the shared topdomain). + * @return: 0 for equal, -1 smaller, or +1 d1 larger than d2. + */ +int dname_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, int* mlabs); + +/** + * See if domain name d1 is a strict subdomain of d2. + * That is a subdomain, but not equal. + * @param d1: domain name, uncompressed wireformat + * @param labs1: number of labels in d1, including root label. + * @param d2: domain name, uncompressed wireformat + * @param labs2: number of labels in d2, including root label. + * @return true if d1 is a subdomain of d2, but not equal to d2. + */ +int dname_strict_subdomain(uint8_t* d1, int labs1, uint8_t* d2, int labs2); + +/** + * Like dname_strict_subdomain but counts labels + * @param d1: domain name, uncompressed wireformat + * @param d2: domain name, uncompressed wireformat + * @return true if d1 is a subdomain of d2, but not equal to d2. + */ +int dname_strict_subdomain_c(uint8_t* d1, uint8_t* d2); + +/** + * Counts labels. Tests is d1 is a subdomain of d2. + * @param d1: domain name, uncompressed wireformat + * @param d2: domain name, uncompressed wireformat + * @return true if d1 is a subdomain of d2. + */ +int dname_subdomain_c(uint8_t* d1, uint8_t* d2); + +/** + * Debug helper. Print wireformat dname to output. + * @param out: like stdout or a file. + * @param pkt: if not NULL, the packet for resolving compression ptrs. + * @param dname: pointer to (start of) dname. + */ +void dname_print(FILE* out, ldns_buffer* pkt, uint8_t* dname); + +/** + * Debug helper. Print dname to given string buffer (string buffer must + * be at least 255 chars + 1 for the 0, in printable form. + * This may lose information (? for nonprintable characters, or & if + * the name is too long, # for a bad label length). + * @param dname: uncompressed wireformat. + * @param str: buffer of 255+1 length. + */ +void dname_str(uint8_t* dname, char* str); + +/** + * Returns true if the uncompressed wireformat dname is the root "." + * @param dname: the dname to check + * @return true if ".", false if not. + */ +int dname_is_root(uint8_t* dname); + +/** + * Snip off first label from a dname, returning the parent zone. + * @param dname: from what to strip off. uncompressed wireformat. + * @param len: length, adjusted to become less. + * @return stripped off, or "." if input was ".". + */ +void dname_remove_label(uint8_t** dname, size_t* len); + +/** + * Snip off first N labels from a dname, returning the parent zone. + * @param dname: from what to strip off. uncompressed wireformat. + * @param len: length, adjusted to become less. + * @param n: number of labels to strip off (from the left). + * if 0, nothing happens. + * @return stripped off, or "." if input was ".". + */ +void dname_remove_labels(uint8_t** dname, size_t* len, int n); + +/** + * Count labels for the RRSIG signature label field. + * Like a normal labelcount, but "*" wildcard and "." root are not counted. + * @param dname: valid uncompressed wireformat. + * @return number of labels like in RRSIG; '*' and '.' are not counted. + */ +int dname_signame_label_count(uint8_t* dname); + +/** + * Return true if the label is a wildcard, *.example.com. + * @param dname: valid uncompressed wireformat. + * @return true if wildcard, or false. + */ +int dname_is_wild(uint8_t* dname); + +/** + * Compare dnames, Canonical in rfc4034 sense, but by label. + * Such that zone contents follows zone apex. + * + * @param d1: first dname. pointer to uncompressed wireformat. + * @param labs1: number of labels in first dname. + * @param d2: second dname. pointer to uncompressed wireformat. + * @param labs2: number of labels in second dname. + * @param mlabs: number of labels that matched exactly (the shared topdomain). + * @return: 0 for equal, -1 smaller, or +1 d1 larger than d2. + */ +int dname_canon_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, + int* mlabs); + +/** + * Canonical dname compare. Takes care of counting labels. + * Per rfc 4034 canonical order. + * + * @param d1: first dname. pointer to uncompressed wireformat. + * @param d2: second dname. pointer to uncompressed wireformat. + * @return: 0 for equal, -1 smaller, or +1 d1 larger than d2. + */ +int dname_canonical_compare(uint8_t* d1, uint8_t* d2); + +/** + * Get the shared topdomain between two names. Root "." or longer. + * @param d1: first dname. pointer to uncompressed wireformat. + * @param d2: second dname. pointer to uncompressed wireformat. + * @return pointer to shared topdomain. Ptr to a part of d1. + */ +uint8_t* dname_get_shared_topdomain(uint8_t* d1, uint8_t* d2); + +#endif /* UTIL_DATA_DNAME_H */ diff --git a/util/data/msgencode.c b/util/data/msgencode.c new file mode 100644 index 00000000000..157796deb95 --- /dev/null +++ b/util/data/msgencode.c @@ -0,0 +1,843 @@ +/* + * util/data/msgencode.c - Encode DNS messages, queries and replies. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains a routines to encode DNS messages. + */ + +#include "config.h" +#include +#include "util/data/msgencode.h" +#include "util/data/msgreply.h" +#include "util/data/msgparse.h" +#include "util/data/dname.h" +#include "util/log.h" +#include "util/regional.h" +#include "util/net_help.h" + +/** return code that means the function ran out of memory. negative so it does + * not conflict with DNS rcodes. */ +#define RETVAL_OUTMEM -2 +/** return code that means the data did not fit (completely) in the packet */ +#define RETVAL_TRUNC -4 +/** return code that means all is peachy keen. Equal to DNS rcode NOERROR */ +#define RETVAL_OK 0 + +/** + * Data structure to help domain name compression in outgoing messages. + * A tree of dnames and their offsets in the packet is kept. + * It is kept sorted, not canonical, but by label at least, so that after + * a lookup of a name you know its closest match, and the parent from that + * closest match. These are possible compression targets. + * + * It is a binary tree, not a rbtree or balanced tree, as the effort + * of keeping it balanced probably outweighs usefulness (given typical + * DNS packet size). + */ +struct compress_tree_node { + /** left node in tree, all smaller to this */ + struct compress_tree_node* left; + /** right node in tree, all larger than this */ + struct compress_tree_node* right; + + /** the parent node - not for tree, but zone parent. One less label */ + struct compress_tree_node* parent; + /** the domain name for this node. Pointer to uncompressed memory. */ + uint8_t* dname; + /** number of labels in domain name, kept to help compare func. */ + int labs; + /** offset in packet that points to this dname */ + size_t offset; +}; + +/** + * Find domain name in tree, returns exact and closest match. + * @param tree: root of tree. + * @param dname: pointer to uncompressed dname. + * @param labs: number of labels in domain name. + * @param match: closest or exact match. + * guaranteed to be smaller or equal to the sought dname. + * can be null if the tree is empty. + * @param matchlabels: number of labels that match with closest match. + * can be zero is there is no match. + * @param insertpt: insert location for dname, if not found. + * @return: 0 if no exact match. + */ +static int +compress_tree_search(struct compress_tree_node** tree, uint8_t* dname, + int labs, struct compress_tree_node** match, int* matchlabels, + struct compress_tree_node*** insertpt) +{ + int c, n, closen=0; + struct compress_tree_node* p = *tree; + struct compress_tree_node* close = 0; + struct compress_tree_node** prev = tree; + while(p) { + if((c = dname_lab_cmp(dname, labs, p->dname, p->labs, &n)) + == 0) { + *matchlabels = n; + *match = p; + return 1; + } + if(c<0) { + prev = &p->left; + p = p->left; + } else { + closen = n; + close = p; /* p->dname is smaller than dname */ + prev = &p->right; + p = p->right; + } + } + *insertpt = prev; + *matchlabels = closen; + *match = close; + return 0; +} + +/** + * Lookup a domain name in compression tree. + * @param tree: root of tree (not the node with '.'). + * @param dname: pointer to uncompressed dname. + * @param labs: number of labels in domain name. + * @param insertpt: insert location for dname, if not found. + * @return: 0 if not found or compress treenode with best compression. + */ +static struct compress_tree_node* +compress_tree_lookup(struct compress_tree_node** tree, uint8_t* dname, + int labs, struct compress_tree_node*** insertpt) +{ + struct compress_tree_node* p; + int m; + if(labs <= 1) + return 0; /* do not compress root node */ + if(compress_tree_search(tree, dname, labs, &p, &m, insertpt)) { + /* exact match */ + return p; + } + /* return some ancestor of p that compresses well. */ + if(m>1) { + /* www.example.com. (labs=4) matched foo.example.com.(labs=4) + * then matchcount = 3. need to go up. */ + while(p && p->labs > m) + p = p->parent; + return p; + } + return 0; +} + +/** + * Create node for domain name compression tree. + * @param dname: pointer to uncompressed dname (stored in tree). + * @param labs: number of labels in dname. + * @param offset: offset into packet for dname. + * @param region: how to allocate memory for new node. + * @return new node or 0 on malloc failure. + */ +static struct compress_tree_node* +compress_tree_newnode(uint8_t* dname, int labs, size_t offset, + struct regional* region) +{ + struct compress_tree_node* n = (struct compress_tree_node*) + regional_alloc(region, sizeof(struct compress_tree_node)); + if(!n) return 0; + n->left = 0; + n->right = 0; + n->parent = 0; + n->dname = dname; + n->labs = labs; + n->offset = offset; + return n; +} + +/** + * Store domain name and ancestors into compression tree. + * @param dname: pointer to uncompressed dname (stored in tree). + * @param labs: number of labels in dname. + * @param offset: offset into packet for dname. + * @param region: how to allocate memory for new node. + * @param closest: match from previous lookup, used to compress dname. + * may be NULL if no previous match. + * if the tree has an ancestor of dname already, this must be it. + * @param insertpt: where to insert the dname in tree. + * @return: 0 on memory error. + */ +static int +compress_tree_store(uint8_t* dname, int labs, size_t offset, + struct regional* region, struct compress_tree_node* closest, + struct compress_tree_node** insertpt) +{ + uint8_t lablen; + struct compress_tree_node* newnode; + struct compress_tree_node* prevnode = NULL; + int uplabs = labs-1; /* does not store root in tree */ + if(closest) uplabs = labs - closest->labs; + log_assert(uplabs >= 0); + /* algorithms builds up a vine of dname-labels to hang into tree */ + while(uplabs--) { + if(offset > PTR_MAX_OFFSET) { + /* insertion failed, drop vine */ + return 1; /* compression pointer no longer useful */ + } + if(!(newnode = compress_tree_newnode(dname, labs, offset, + region))) { + /* insertion failed, drop vine */ + return 0; + } + + if(prevnode) { + /* chain nodes together, last one has one label more, + * so is larger than newnode, thus goes right. */ + newnode->right = prevnode; + prevnode->parent = newnode; + } + + /* next label */ + lablen = *dname++; + dname += lablen; + offset += lablen+1; + prevnode = newnode; + labs--; + } + /* if we have a vine, hang the vine into the tree */ + if(prevnode) { + *insertpt = prevnode; + prevnode->parent = closest; + } + return 1; +} + +/** compress a domain name */ +static int +write_compressed_dname(ldns_buffer* pkt, uint8_t* dname, int labs, + struct compress_tree_node* p) +{ + /* compress it */ + int labcopy = labs - p->labs; + uint8_t lablen; + uint16_t ptr; + + if(labs == 1) { + /* write root label */ + if(ldns_buffer_remaining(pkt) < 1) + return 0; + ldns_buffer_write_u8(pkt, 0); + return 1; + } + + /* copy the first couple of labels */ + while(labcopy--) { + lablen = *dname++; + if(ldns_buffer_remaining(pkt) < (size_t)lablen+1) + return 0; + ldns_buffer_write_u8(pkt, lablen); + ldns_buffer_write(pkt, dname, lablen); + dname += lablen; + } + /* insert compression ptr */ + if(ldns_buffer_remaining(pkt) < 2) + return 0; + ptr = PTR_CREATE(p->offset); + ldns_buffer_write_u16(pkt, ptr); + return 1; +} + +/** compress owner name of RR, return RETVAL_OUTMEM RETVAL_TRUNC */ +static int +compress_owner(struct ub_packed_rrset_key* key, ldns_buffer* pkt, + struct regional* region, struct compress_tree_node** tree, + size_t owner_pos, uint16_t* owner_ptr, int owner_labs) +{ + struct compress_tree_node* p; + struct compress_tree_node** insertpt; + if(!*owner_ptr) { + /* compress first time dname */ + if((p = compress_tree_lookup(tree, key->rk.dname, + owner_labs, &insertpt))) { + if(p->labs == owner_labs) + /* avoid ptr chains, since some software is + * not capable of decoding ptr after a ptr. */ + *owner_ptr = htons(PTR_CREATE(p->offset)); + if(!write_compressed_dname(pkt, key->rk.dname, + owner_labs, p)) + return RETVAL_TRUNC; + /* check if typeclass+4 ttl + rdatalen is available */ + if(ldns_buffer_remaining(pkt) < 4+4+2) + return RETVAL_TRUNC; + } else { + /* no compress */ + if(ldns_buffer_remaining(pkt) < key->rk.dname_len+4+4+2) + return RETVAL_TRUNC; + ldns_buffer_write(pkt, key->rk.dname, + key->rk.dname_len); + if(owner_pos <= PTR_MAX_OFFSET) + *owner_ptr = htons(PTR_CREATE(owner_pos)); + } + if(!compress_tree_store(key->rk.dname, owner_labs, + owner_pos, region, p, insertpt)) + return RETVAL_OUTMEM; + } else { + /* always compress 2nd-further RRs in RRset */ + if(owner_labs == 1) { + if(ldns_buffer_remaining(pkt) < 1+4+4+2) + return RETVAL_TRUNC; + ldns_buffer_write_u8(pkt, 0); + } else { + if(ldns_buffer_remaining(pkt) < 2+4+4+2) + return RETVAL_TRUNC; + ldns_buffer_write(pkt, owner_ptr, 2); + } + } + return RETVAL_OK; +} + +/** compress any domain name to the packet, return RETVAL_* */ +static int +compress_any_dname(uint8_t* dname, ldns_buffer* pkt, int labs, + struct regional* region, struct compress_tree_node** tree) +{ + struct compress_tree_node* p; + struct compress_tree_node** insertpt = NULL; + size_t pos = ldns_buffer_position(pkt); + if((p = compress_tree_lookup(tree, dname, labs, &insertpt))) { + if(!write_compressed_dname(pkt, dname, labs, p)) + return RETVAL_TRUNC; + } else { + if(!dname_buffer_write(pkt, dname)) + return RETVAL_TRUNC; + } + if(!compress_tree_store(dname, labs, pos, region, p, insertpt)) + return RETVAL_OUTMEM; + return RETVAL_OK; +} + +/** return true if type needs domain name compression in rdata */ +static const ldns_rr_descriptor* +type_rdata_compressable(struct ub_packed_rrset_key* key) +{ + uint16_t t = ntohs(key->rk.type); + if(ldns_rr_descript(t) && + ldns_rr_descript(t)->_compress == LDNS_RR_COMPRESS) + return ldns_rr_descript(t); + return 0; +} + +/** compress domain names in rdata, return RETVAL_* */ +static int +compress_rdata(ldns_buffer* pkt, uint8_t* rdata, size_t todolen, + struct regional* region, struct compress_tree_node** tree, + const ldns_rr_descriptor* desc) +{ + int labs, r, rdf = 0; + size_t dname_len, len, pos = ldns_buffer_position(pkt); + uint8_t count = desc->_dname_count; + + ldns_buffer_skip(pkt, 2); /* rdata len fill in later */ + /* space for rdatalen checked for already */ + rdata += 2; + todolen -= 2; + while(todolen > 0 && count) { + switch(desc->_wireformat[rdf]) { + case LDNS_RDF_TYPE_DNAME: + labs = dname_count_size_labels(rdata, &dname_len); + if((r=compress_any_dname(rdata, pkt, labs, region, + tree)) != RETVAL_OK) + return r; + rdata += dname_len; + todolen -= dname_len; + count--; + len = 0; + break; + case LDNS_RDF_TYPE_STR: + len = *rdata + 1; + break; + default: + len = get_rdf_size(desc->_wireformat[rdf]); + } + if(len) { + /* copy over */ + if(ldns_buffer_remaining(pkt) < len) + return RETVAL_TRUNC; + ldns_buffer_write(pkt, rdata, len); + todolen -= len; + rdata += len; + } + rdf++; + } + /* copy remainder */ + if(todolen > 0) { + if(ldns_buffer_remaining(pkt) < todolen) + return RETVAL_TRUNC; + ldns_buffer_write(pkt, rdata, todolen); + } + + /* set rdata len */ + ldns_buffer_write_u16_at(pkt, pos, ldns_buffer_position(pkt)-pos-2); + return RETVAL_OK; +} + +/** Returns true if RR type should be included */ +static int +rrset_belongs_in_reply(ldns_pkt_section s, uint16_t rrtype, uint16_t qtype, + int dnssec) +{ + if(dnssec) + return 1; + /* skip non DNSSEC types, except if directly queried for */ + if(s == LDNS_SECTION_ANSWER) { + if(qtype == LDNS_RR_TYPE_ANY || qtype == rrtype) + return 1; + } + /* check DNSSEC-ness */ + switch(rrtype) { + case LDNS_RR_TYPE_SIG: + case LDNS_RR_TYPE_KEY: + case LDNS_RR_TYPE_NXT: + case LDNS_RR_TYPE_DS: + case LDNS_RR_TYPE_RRSIG: + case LDNS_RR_TYPE_NSEC: + case LDNS_RR_TYPE_DNSKEY: + case LDNS_RR_TYPE_NSEC3: + case LDNS_RR_TYPE_NSEC3PARAMS: + return 0; + } + return 1; +} + +/** store rrset in buffer in wireformat, return RETVAL_* */ +static int +packed_rrset_encode(struct ub_packed_rrset_key* key, ldns_buffer* pkt, + uint16_t* num_rrs, uint32_t timenow, struct regional* region, + int do_data, int do_sig, struct compress_tree_node** tree, + ldns_pkt_section s, uint16_t qtype, int dnssec, size_t rr_offset) +{ + size_t i, j, owner_pos; + int r, owner_labs; + uint16_t owner_ptr = 0; + struct packed_rrset_data* data = (struct packed_rrset_data*) + key->entry.data; + + /* does this RR type belong in the answer? */ + if(!rrset_belongs_in_reply(s, ntohs(key->rk.type), qtype, dnssec)) + return RETVAL_OK; + + owner_labs = dname_count_labels(key->rk.dname); + owner_pos = ldns_buffer_position(pkt); + + if(do_data) { + const ldns_rr_descriptor* c = type_rdata_compressable(key); + for(i=0; icount; i++) { + /* rrset roundrobin */ + j = (i + rr_offset) % data->count; + if((r=compress_owner(key, pkt, region, tree, + owner_pos, &owner_ptr, owner_labs)) + != RETVAL_OK) + return r; + ldns_buffer_write(pkt, &key->rk.type, 2); + ldns_buffer_write(pkt, &key->rk.rrset_class, 2); + if(data->rr_ttl[j] < timenow) + ldns_buffer_write_u32(pkt, 0); + else ldns_buffer_write_u32(pkt, + data->rr_ttl[j]-timenow); + if(c) { + if((r=compress_rdata(pkt, data->rr_data[j], + data->rr_len[j], region, tree, c)) + != RETVAL_OK) + return r; + } else { + if(ldns_buffer_remaining(pkt) < data->rr_len[j]) + return RETVAL_TRUNC; + ldns_buffer_write(pkt, data->rr_data[j], + data->rr_len[j]); + } + } + } + /* insert rrsigs */ + if(do_sig && dnssec) { + size_t total = data->count+data->rrsig_count; + for(i=data->count; irr_len[i]) + return RETVAL_TRUNC; + ldns_buffer_write(pkt, &owner_ptr, 2); + } else { + if((r=compress_any_dname(key->rk.dname, + pkt, owner_labs, region, tree)) + != RETVAL_OK) + return r; + if(ldns_buffer_remaining(pkt) < + 4+4+data->rr_len[i]) + return RETVAL_TRUNC; + } + ldns_buffer_write_u16(pkt, LDNS_RR_TYPE_RRSIG); + ldns_buffer_write(pkt, &key->rk.rrset_class, 2); + if(data->rr_ttl[i] < timenow) + ldns_buffer_write_u32(pkt, 0); + else ldns_buffer_write_u32(pkt, + data->rr_ttl[i]-timenow); + /* rrsig rdata cannot be compressed, perform 100+ byte + * memcopy. */ + ldns_buffer_write(pkt, data->rr_data[i], + data->rr_len[i]); + } + } + /* change rrnum only after we are sure it fits */ + if(do_data) + *num_rrs += data->count; + if(do_sig && dnssec) + *num_rrs += data->rrsig_count; + + return RETVAL_OK; +} + +/** store msg section in wireformat buffer, return RETVAL_* */ +static int +insert_section(struct reply_info* rep, size_t num_rrsets, uint16_t* num_rrs, + ldns_buffer* pkt, size_t rrsets_before, uint32_t timenow, + struct regional* region, struct compress_tree_node** tree, + ldns_pkt_section s, uint16_t qtype, int dnssec, size_t rr_offset) +{ + int r; + size_t i, setstart; + *num_rrs = 0; + if(s != LDNS_SECTION_ADDITIONAL) { + if(s == LDNS_SECTION_ANSWER && qtype == LDNS_RR_TYPE_ANY) + dnssec = 1; /* include all types in ANY answer */ + for(i=0; irrsets[rrsets_before+i], + pkt, num_rrs, timenow, region, 1, 1, tree, + s, qtype, dnssec, rr_offset)) + != RETVAL_OK) { + /* Bad, but if due to size must set TC bit */ + /* trim off the rrset neatly. */ + ldns_buffer_set_position(pkt, setstart); + return r; + } + } + } else { + for(i=0; irrsets[rrsets_before+i], + pkt, num_rrs, timenow, region, 1, 0, tree, + s, qtype, dnssec, rr_offset)) + != RETVAL_OK) { + ldns_buffer_set_position(pkt, setstart); + return r; + } + } + if(dnssec) + for(i=0; irrsets[rrsets_before+i], + pkt, num_rrs, timenow, region, 0, 1, tree, + s, qtype, dnssec, rr_offset)) + != RETVAL_OK) { + ldns_buffer_set_position(pkt, setstart); + return r; + } + } + } + return RETVAL_OK; +} + +/** store query section in wireformat buffer, return RETVAL */ +static int +insert_query(struct query_info* qinfo, struct compress_tree_node** tree, + ldns_buffer* buffer, struct regional* region) +{ + if(ldns_buffer_remaining(buffer) < + qinfo->qname_len+sizeof(uint16_t)*2) + return RETVAL_TRUNC; /* buffer too small */ + /* the query is the first name inserted into the tree */ + if(!compress_tree_store(qinfo->qname, + dname_count_labels(qinfo->qname), + ldns_buffer_position(buffer), region, NULL, tree)) + return RETVAL_OUTMEM; + if(ldns_buffer_current(buffer) == qinfo->qname) + ldns_buffer_skip(buffer, (ssize_t)qinfo->qname_len); + else ldns_buffer_write(buffer, qinfo->qname, qinfo->qname_len); + ldns_buffer_write_u16(buffer, qinfo->qtype); + ldns_buffer_write_u16(buffer, qinfo->qclass); + return RETVAL_OK; +} + +static int +positive_answer(struct reply_info* rep, uint16_t qtype) { + size_t i; + if (FLAGS_GET_RCODE(rep->flags) != LDNS_RCODE_NOERROR) + return 0; + + for(i=0;ian_numrrsets; i++) { + if(ntohs(rep->rrsets[i]->rk.type) == qtype) { + /* in case it is a wildcard with DNSSEC, there will + * be NSEC/NSEC3 records in the authority section + * that we cannot remove */ + for(i=rep->an_numrrsets; ian_numrrsets+ + rep->ns_numrrsets; i++) { + if(ntohs(rep->rrsets[i]->rk.type) == + LDNS_RR_TYPE_NSEC || + ntohs(rep->rrsets[i]->rk.type) == + LDNS_RR_TYPE_NSEC3) + return 0; + } + return 1; + } + } + return 0; +} + +int +reply_info_encode(struct query_info* qinfo, struct reply_info* rep, + uint16_t id, uint16_t flags, ldns_buffer* buffer, uint32_t timenow, + struct regional* region, uint16_t udpsize, int dnssec) +{ + uint16_t ancount=0, nscount=0, arcount=0; + struct compress_tree_node* tree = 0; + int r; + size_t rr_offset; + + ldns_buffer_clear(buffer); + if(udpsize < ldns_buffer_limit(buffer)) + ldns_buffer_set_limit(buffer, udpsize); + if(ldns_buffer_remaining(buffer) < LDNS_HEADER_SIZE) + return 0; + + ldns_buffer_write(buffer, &id, sizeof(uint16_t)); + ldns_buffer_write_u16(buffer, flags); + ldns_buffer_write_u16(buffer, rep->qdcount); + /* set an, ns, ar counts to zero in case of small packets */ + ldns_buffer_write(buffer, "\000\000\000\000\000\000", 6); + + /* insert query section */ + if(rep->qdcount) { + if((r=insert_query(qinfo, &tree, buffer, region)) != + RETVAL_OK) { + if(r == RETVAL_TRUNC) { + /* create truncated message */ + ldns_buffer_write_u16_at(buffer, 4, 0); + LDNS_TC_SET(ldns_buffer_begin(buffer)); + ldns_buffer_flip(buffer); + return 1; + } + return 0; + } + } + /* roundrobin offset. using query id for random number */ + rr_offset = RRSET_ROUNDROBIN?id:0; + + /* insert answer section */ + if((r=insert_section(rep, rep->an_numrrsets, &ancount, buffer, + 0, timenow, region, &tree, LDNS_SECTION_ANSWER, qinfo->qtype, + dnssec, rr_offset)) != RETVAL_OK) { + if(r == RETVAL_TRUNC) { + /* create truncated message */ + ldns_buffer_write_u16_at(buffer, 6, ancount); + LDNS_TC_SET(ldns_buffer_begin(buffer)); + ldns_buffer_flip(buffer); + return 1; + } + return 0; + } + ldns_buffer_write_u16_at(buffer, 6, ancount); + + /* if response is positive answer, auth/add sections are not required */ + if( ! (MINIMAL_RESPONSES && positive_answer(rep, qinfo->qtype)) ) { + /* insert auth section */ + if((r=insert_section(rep, rep->ns_numrrsets, &nscount, buffer, + rep->an_numrrsets, timenow, region, &tree, + LDNS_SECTION_AUTHORITY, qinfo->qtype, + dnssec, rr_offset)) != RETVAL_OK) { + if(r == RETVAL_TRUNC) { + /* create truncated message */ + ldns_buffer_write_u16_at(buffer, 8, nscount); + LDNS_TC_SET(ldns_buffer_begin(buffer)); + ldns_buffer_flip(buffer); + return 1; + } + return 0; + } + ldns_buffer_write_u16_at(buffer, 8, nscount); + + /* insert add section */ + if((r=insert_section(rep, rep->ar_numrrsets, &arcount, buffer, + rep->an_numrrsets + rep->ns_numrrsets, timenow, region, + &tree, LDNS_SECTION_ADDITIONAL, qinfo->qtype, + dnssec, rr_offset)) != RETVAL_OK) { + if(r == RETVAL_TRUNC) { + /* no need to set TC bit, this is the additional */ + ldns_buffer_write_u16_at(buffer, 10, arcount); + ldns_buffer_flip(buffer); + return 1; + } + return 0; + } + ldns_buffer_write_u16_at(buffer, 10, arcount); + } else { + ldns_buffer_write_u16_at(buffer, 8, nscount); + ldns_buffer_write_u16_at(buffer, 10, arcount); + } + ldns_buffer_flip(buffer); + return 1; +} + +uint16_t +calc_edns_field_size(struct edns_data* edns) +{ + if(!edns || !edns->edns_present) + return 0; + /* domain root '.' + type + class + ttl + rdatalen(=0) */ + return 1 + 2 + 2 + 4 + 2; +} + +void +attach_edns_record(ldns_buffer* pkt, struct edns_data* edns) +{ + size_t len; + if(!edns || !edns->edns_present) + return; + /* inc additional count */ + ldns_buffer_write_u16_at(pkt, 10, + ldns_buffer_read_u16_at(pkt, 10) + 1); + len = ldns_buffer_limit(pkt); + ldns_buffer_clear(pkt); + ldns_buffer_set_position(pkt, len); + /* write EDNS record */ + ldns_buffer_write_u8(pkt, 0); /* '.' label */ + ldns_buffer_write_u16(pkt, LDNS_RR_TYPE_OPT); /* type */ + ldns_buffer_write_u16(pkt, edns->udp_size); /* class */ + ldns_buffer_write_u8(pkt, edns->ext_rcode); /* ttl */ + ldns_buffer_write_u8(pkt, edns->edns_version); + ldns_buffer_write_u16(pkt, edns->bits); + ldns_buffer_write_u16(pkt, 0); /* rdatalen */ + ldns_buffer_flip(pkt); +} + +int +reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep, + uint16_t id, uint16_t qflags, ldns_buffer* pkt, uint32_t timenow, + int cached, struct regional* region, uint16_t udpsize, + struct edns_data* edns, int dnssec, int secure) +{ + uint16_t flags; + int attach_edns = 1; + + if(!cached || rep->authoritative) { + /* original flags, copy RD and CD bits from query. */ + flags = rep->flags | (qflags & (BIT_RD|BIT_CD)); + } else { + /* remove AA bit, copy RD and CD bits from query. */ + flags = (rep->flags & ~BIT_AA) | (qflags & (BIT_RD|BIT_CD)); + } + if(secure && (dnssec || (qflags&BIT_AD))) + flags |= BIT_AD; + log_assert(flags & BIT_QR); /* QR bit must be on in our replies */ + if(udpsize < LDNS_HEADER_SIZE) + return 0; + if(udpsize < LDNS_HEADER_SIZE + calc_edns_field_size(edns)) { + /* packet too small to contain edns, omit it. */ + attach_edns = 0; + } else { + /* reserve space for edns record */ + udpsize -= calc_edns_field_size(edns); + } + + if(!reply_info_encode(qinf, rep, id, flags, pkt, timenow, region, + udpsize, dnssec)) { + log_err("reply encode: out of memory"); + return 0; + } + if(attach_edns) + attach_edns_record(pkt, edns); + return 1; +} + +void +qinfo_query_encode(ldns_buffer* pkt, struct query_info* qinfo) +{ + uint16_t flags = 0; /* QUERY, NOERROR */ + ldns_buffer_clear(pkt); + log_assert(ldns_buffer_remaining(pkt) >= 12+255+4/*max query*/); + ldns_buffer_skip(pkt, 2); /* id done later */ + ldns_buffer_write_u16(pkt, flags); + ldns_buffer_write_u16(pkt, 1); /* query count */ + ldns_buffer_write(pkt, "\000\000\000\000\000\000", 6); /* counts */ + ldns_buffer_write(pkt, qinfo->qname, qinfo->qname_len); + ldns_buffer_write_u16(pkt, qinfo->qtype); + ldns_buffer_write_u16(pkt, qinfo->qclass); + ldns_buffer_flip(pkt); +} + +void +error_encode(ldns_buffer* buf, int r, struct query_info* qinfo, + uint16_t qid, uint16_t qflags, struct edns_data* edns) +{ + uint16_t flags; + + ldns_buffer_clear(buf); + ldns_buffer_write(buf, &qid, sizeof(uint16_t)); + flags = (uint16_t)(BIT_QR | BIT_RA | r); /* QR and retcode*/ + flags |= (qflags & (BIT_RD|BIT_CD)); /* copy RD and CD bit */ + ldns_buffer_write_u16(buf, flags); + if(qinfo) flags = 1; + else flags = 0; + ldns_buffer_write_u16(buf, flags); + flags = 0; + ldns_buffer_write(buf, &flags, sizeof(uint16_t)); + ldns_buffer_write(buf, &flags, sizeof(uint16_t)); + ldns_buffer_write(buf, &flags, sizeof(uint16_t)); + if(qinfo) { + if(ldns_buffer_current(buf) == qinfo->qname) + ldns_buffer_skip(buf, (ssize_t)qinfo->qname_len); + else ldns_buffer_write(buf, qinfo->qname, qinfo->qname_len); + ldns_buffer_write_u16(buf, qinfo->qtype); + ldns_buffer_write_u16(buf, qinfo->qclass); + } + ldns_buffer_flip(buf); + if(edns) { + struct edns_data es = *edns; + es.edns_version = EDNS_ADVERTISED_VERSION; + es.udp_size = EDNS_ADVERTISED_SIZE; + es.ext_rcode = 0; + es.bits &= EDNS_DO; + if(ldns_buffer_limit(buf) + calc_edns_field_size(&es) > + edns->udp_size) + return; + attach_edns_record(buf, &es); + } +} diff --git a/util/data/msgencode.h b/util/data/msgencode.h new file mode 100644 index 00000000000..74d6c1fb2dd --- /dev/null +++ b/util/data/msgencode.h @@ -0,0 +1,130 @@ +/* + * util/data/msgencode.h - encode compressed DNS messages. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains temporary data structures and routines to create + * compressed DNS messages. + */ + +#ifndef UTIL_DATA_MSGENCODE_H +#define UTIL_DATA_MSGENCODE_H +struct query_info; +struct reply_info; +struct regional; +struct edns_data; + +/** + * Generate answer from reply_info. + * @param qinf: query information that provides query section in packet. + * @param rep: reply to fill in. + * @param id: id word from the query. + * @param qflags: flags word from the query. + * @param dest: buffer to put message into; will truncate if it does not fit. + * @param timenow: time to subtract. + * @param cached: set true if a cached reply (so no AA bit). + * set false for the first reply. + * @param region: where to allocate temp variables (for compression). + * @param udpsize: size of the answer, 512, from EDNS, or 64k for TCP. + * @param edns: EDNS data included in the answer, NULL for none. + * or if edns_present = 0, it is not included. + * @param dnssec: if 0 DNSSEC records are omitted from the answer. + * @param secure: if 1, the AD bit is set in the reply. + * @return: 0 on error (server failure). + */ +int reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep, + uint16_t id, uint16_t qflags, ldns_buffer* dest, uint32_t timenow, + int cached, struct regional* region, uint16_t udpsize, + struct edns_data* edns, int dnssec, int secure); + +/** + * Regenerate the wireformat from the stored msg reply. + * If the buffer is too small then the message is truncated at a whole + * rrset and the TC bit set, or whole rrsets are left out of the additional + * and the TC bit is not set. + * @param qinfo: query info to store. + * @param rep: reply to store. + * @param id: id value to store, network order. + * @param flags: flags value to store, host order. + * @param buffer: buffer to store the packet into. + * @param timenow: time now, to adjust ttl values. + * @param region: to store temporary data in. + * @param udpsize: size of the answer, 512, from EDNS, or 64k for TCP. + * @param dnssec: if 0 DNSSEC records are omitted from the answer. + * @return: nonzero is success, or + * 0 on error: malloc failure (no log_err has been done). + */ +int reply_info_encode(struct query_info* qinfo, struct reply_info* rep, + uint16_t id, uint16_t flags, ldns_buffer* buffer, uint32_t timenow, + struct regional* region, uint16_t udpsize, int dnssec); + +/** + * Encode query packet. Assumes the buffer is large enough. + * @param pkt: where to store the packet. + * @param qinfo: query info. + */ +void qinfo_query_encode(ldns_buffer* pkt, struct query_info* qinfo); + +/** + * Estimate size of EDNS record in packet. EDNS record will be no larger. + * @param edns: edns data or NULL. + * @return octets to reserve for EDNS. + */ +uint16_t calc_edns_field_size(struct edns_data* edns); + +/** + * Attach EDNS record to buffer. Buffer has complete packet. There must + * be enough room left for the EDNS record. + * @param pkt: packet added to. + * @param edns: if NULL or present=0, nothing is added to the packet. + */ +void attach_edns_record(ldns_buffer* pkt, struct edns_data* edns); + +/** + * Encode an error. With QR and RA set. + * + * @param pkt: where to store the packet. + * @param r: RCODE value to encode. + * @param qinfo: if not NULL, the query is included. + * @param qid: query ID to set in packet. network order. + * @param qflags: original query flags (to copy RD and CD bits). host order. + * @param edns: if not NULL, this is the query edns info, + * and an edns reply is attached. Only attached if EDNS record fits reply. + */ +void error_encode(ldns_buffer* pkt, int r, struct query_info* qinfo, + uint16_t qid, uint16_t qflags, struct edns_data* edns); + +#endif /* UTIL_DATA_MSGENCODE_H */ diff --git a/util/data/msgparse.c b/util/data/msgparse.c new file mode 100644 index 00000000000..a03f543e827 --- /dev/null +++ b/util/data/msgparse.c @@ -0,0 +1,1018 @@ +/* + * util/data/msgparse.c - parse wireformat DNS messages. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \file + * Routines for message parsing a packet buffer to a descriptive structure. + */ +#include "config.h" +#include +#include "util/data/msgparse.h" +#include "util/net_help.h" +#include "util/data/dname.h" +#include "util/data/packed_rrset.h" +#include "util/storage/lookup3.h" +#include "util/regional.h" + +/** smart comparison of (compressed, valid) dnames from packet */ +static int +smart_compare(ldns_buffer* pkt, uint8_t* dnow, + uint8_t* dprfirst, uint8_t* dprlast) +{ + if(LABEL_IS_PTR(*dnow)) { + /* ptr points to a previous dname */ + uint8_t* p = ldns_buffer_at(pkt, PTR_OFFSET(dnow[0], dnow[1])); + if( p == dprfirst || p == dprlast ) + return 0; + /* prev dname is also a ptr, both ptrs are the same. */ + if(LABEL_IS_PTR(*dprlast) && + dprlast[0] == dnow[0] && dprlast[1] == dnow[1]) + return 0; + } + return dname_pkt_compare(pkt, dnow, dprlast); +} + +/** + * Allocate new rrset in region, fill with data. + */ +static struct rrset_parse* +new_rrset(struct msg_parse* msg, uint8_t* dname, size_t dnamelen, + uint16_t type, uint16_t dclass, hashvalue_t hash, + uint32_t rrset_flags, ldns_pkt_section section, + struct regional* region) +{ + struct rrset_parse* p = regional_alloc(region, sizeof(*p)); + if(!p) return NULL; + p->rrset_bucket_next = msg->hashtable[hash & (PARSE_TABLE_SIZE-1)]; + msg->hashtable[hash & (PARSE_TABLE_SIZE-1)] = p; + p->rrset_all_next = 0; + if(msg->rrset_last) + msg->rrset_last->rrset_all_next = p; + else msg->rrset_first = p; + msg->rrset_last = p; + p->hash = hash; + p->section = section; + p->dname = dname; + p->dname_len = dnamelen; + p->type = type; + p->rrset_class = dclass; + p->flags = rrset_flags; + p->rr_count = 0; + p->size = 0; + p->rr_first = 0; + p->rr_last = 0; + p->rrsig_count = 0; + p->rrsig_first = 0; + p->rrsig_last = 0; + return p; +} + +/** See if next rrset is nsec at zone apex */ +static int +nsec_at_apex(ldns_buffer* pkt) +{ + /* we are at ttl position in packet. */ + size_t pos = ldns_buffer_position(pkt); + uint16_t rdatalen; + if(ldns_buffer_remaining(pkt) < 7) /* ttl+len+root */ + return 0; /* eek! */ + ldns_buffer_skip(pkt, 4); /* ttl */; + rdatalen = ldns_buffer_read_u16(pkt); + if(ldns_buffer_remaining(pkt) < rdatalen) { + ldns_buffer_set_position(pkt, pos); + return 0; /* parse error happens later */ + } + /* must validate the nsec next domain name format */ + if(pkt_dname_len(pkt) == 0) { + ldns_buffer_set_position(pkt, pos); + return 0; /* parse error */ + } + + /* see if SOA bit is set. */ + if(ldns_buffer_position(pkt) < pos+4+rdatalen) { + /* nsec type bitmap contains items */ + uint8_t win, blen, bits; + /* need: windownum, bitmap len, firstbyte */ + if(ldns_buffer_position(pkt)+3 > pos+4+rdatalen) { + ldns_buffer_set_position(pkt, pos); + return 0; /* malformed nsec */ + } + win = ldns_buffer_read_u8(pkt); + blen = ldns_buffer_read_u8(pkt); + bits = ldns_buffer_read_u8(pkt); + /* 0window always first window. bitlen >=1 or parse + error really. bit 0x2 is SOA. */ + if(win == 0 && blen >= 1 && (bits & 0x02)) { + ldns_buffer_set_position(pkt, pos); + return 1; + } + } + + ldns_buffer_set_position(pkt, pos); + return 0; +} + +/** Calculate rrset flags */ +static uint32_t +pkt_rrset_flags(ldns_buffer* pkt, uint16_t type, ldns_pkt_section sec) +{ + uint32_t f = 0; + if(type == LDNS_RR_TYPE_NSEC && nsec_at_apex(pkt)) { + f |= PACKED_RRSET_NSEC_AT_APEX; + } else if(type == LDNS_RR_TYPE_SOA && sec == LDNS_SECTION_AUTHORITY) { + f |= PACKED_RRSET_SOA_NEG; + } + return f; +} + +hashvalue_t +pkt_hash_rrset(ldns_buffer* pkt, uint8_t* dname, uint16_t type, + uint16_t dclass, uint32_t rrset_flags) +{ + /* note this MUST be identical to rrset_key_hash in packed_rrset.c */ + /* this routine handles compressed names */ + hashvalue_t h = 0xab; + h = dname_pkt_hash(pkt, dname, h); + h = hashlittle(&type, sizeof(type), h); /* host order */ + h = hashlittle(&dclass, sizeof(dclass), h); /* netw order */ + h = hashlittle(&rrset_flags, sizeof(uint32_t), h); + return h; +} + +/** create partial dname hash for rrset hash */ +static hashvalue_t +pkt_hash_rrset_first(ldns_buffer* pkt, uint8_t* dname) +{ + /* works together with pkt_hash_rrset_rest */ + /* note this MUST be identical to rrset_key_hash in packed_rrset.c */ + /* this routine handles compressed names */ + hashvalue_t h = 0xab; + h = dname_pkt_hash(pkt, dname, h); + return h; +} + +/** create a rrset hash from a partial dname hash */ +static hashvalue_t +pkt_hash_rrset_rest(hashvalue_t dname_h, uint16_t type, uint16_t dclass, + uint32_t rrset_flags) +{ + /* works together with pkt_hash_rrset_first */ + /* note this MUST be identical to rrset_key_hash in packed_rrset.c */ + hashvalue_t h; + h = hashlittle(&type, sizeof(type), dname_h); /* host order */ + h = hashlittle(&dclass, sizeof(dclass), h); /* netw order */ + h = hashlittle(&rrset_flags, sizeof(uint32_t), h); + return h; +} + +/** compare rrset_parse with data */ +static int +rrset_parse_equals(struct rrset_parse* p, ldns_buffer* pkt, hashvalue_t h, + uint32_t rrset_flags, uint8_t* dname, size_t dnamelen, + uint16_t type, uint16_t dclass) +{ + if(p->hash == h && p->dname_len == dnamelen && p->type == type && + p->rrset_class == dclass && p->flags == rrset_flags && + dname_pkt_compare(pkt, dname, p->dname) == 0) + return 1; + return 0; +} + + +struct rrset_parse* +msgparse_hashtable_lookup(struct msg_parse* msg, ldns_buffer* pkt, + hashvalue_t h, uint32_t rrset_flags, uint8_t* dname, size_t dnamelen, + uint16_t type, uint16_t dclass) +{ + struct rrset_parse* p = msg->hashtable[h & (PARSE_TABLE_SIZE-1)]; + while(p) { + if(rrset_parse_equals(p, pkt, h, rrset_flags, dname, dnamelen, + type, dclass)) + return p; + p = p->rrset_bucket_next; + } + return NULL; +} + +/** return type networkformat that rrsig in packet covers */ +static int +pkt_rrsig_covered(ldns_buffer* pkt, uint8_t* here, uint16_t* type) +{ + size_t pos = ldns_buffer_position(pkt); + ldns_buffer_set_position(pkt, (size_t)(here-ldns_buffer_begin(pkt))); + /* ttl + len + size of small rrsig(rootlabel, no signature) */ + if(ldns_buffer_remaining(pkt) < 4+2+19) + return 0; + ldns_buffer_skip(pkt, 4); /* ttl */ + if(ldns_buffer_read_u16(pkt) < 19) /* too short */ { + ldns_buffer_set_position(pkt, pos); + return 0; + } + *type = ldns_buffer_read_u16(pkt); + ldns_buffer_set_position(pkt, pos); + return 1; +} + +/** true if covered type equals prevtype */ +static int +pkt_rrsig_covered_equals(ldns_buffer* pkt, uint8_t* here, uint16_t type) +{ + uint16_t t; + if(pkt_rrsig_covered(pkt, here, &t) && t == type) + return 1; + return 0; +} + +void +msgparse_bucket_remove(struct msg_parse* msg, struct rrset_parse* rrset) +{ + struct rrset_parse** p; + p = &msg->hashtable[ rrset->hash & (PARSE_TABLE_SIZE-1) ]; + while(*p) { + if(*p == rrset) { + *p = rrset->rrset_bucket_next; + return; + } + p = &( (*p)->rrset_bucket_next ); + } +} + +/** change section of rrset from previous to current section */ +static void +change_section(struct msg_parse* msg, struct rrset_parse* rrset, + ldns_pkt_section section) +{ + struct rrset_parse *p, *prev; + /* remove from list */ + if(section == rrset->section) + return; + p = msg->rrset_first; + prev = 0; + while(p) { + if(p == rrset) { + if(prev) prev->rrset_all_next = p->rrset_all_next; + else msg->rrset_first = p->rrset_all_next; + if(msg->rrset_last == rrset) + msg->rrset_last = prev; + break; + } + prev = p; + p = p->rrset_all_next; + } + /* remove from count */ + switch(rrset->section) { + case LDNS_SECTION_ANSWER: msg->an_rrsets--; break; + case LDNS_SECTION_AUTHORITY: msg->ns_rrsets--; break; + case LDNS_SECTION_ADDITIONAL: msg->ar_rrsets--; break; + default: log_assert(0); + } + /* insert at end of list */ + rrset->rrset_all_next = 0; + if(msg->rrset_last) + msg->rrset_last->rrset_all_next = rrset; + else msg->rrset_first = rrset; + msg->rrset_last = rrset; + /* up count of new section */ + switch(section) { + case LDNS_SECTION_AUTHORITY: msg->ns_rrsets++; break; + case LDNS_SECTION_ADDITIONAL: msg->ar_rrsets++; break; + default: log_assert(0); + } + rrset->section = section; +} + +/** see if rrset of type RRSIG contains sig over given type */ +static int +rrset_has_sigover(ldns_buffer* pkt, struct rrset_parse* rrset, uint16_t type, + int* hasother) +{ + int res = 0; + struct rr_parse* rr = rrset->rr_first; + log_assert( rrset->type == LDNS_RR_TYPE_RRSIG ); + while(rr) { + if(pkt_rrsig_covered_equals(pkt, rr->ttl_data, type)) + res = 1; + else *hasother = 1; + rr = rr->next; + } + return res; +} + +/** move rrsigs from sigset to dataset */ +static int +moveover_rrsigs(ldns_buffer* pkt, struct regional* region, + struct rrset_parse* sigset, struct rrset_parse* dataset, int duplicate) +{ + struct rr_parse* sig = sigset->rr_first; + struct rr_parse* prev = NULL; + struct rr_parse* insert; + struct rr_parse* nextsig; + while(sig) { + nextsig = sig->next; + if(pkt_rrsig_covered_equals(pkt, sig->ttl_data, + dataset->type)) { + if(duplicate) { + /* new */ + insert = (struct rr_parse*)regional_alloc( + region, sizeof(struct rr_parse)); + if(!insert) return 0; + insert->outside_packet = 0; + insert->ttl_data = sig->ttl_data; + insert->size = sig->size; + /* prev not used */ + } else { + /* remove from sigset */ + if(prev) prev->next = sig->next; + else sigset->rr_first = sig->next; + if(sigset->rr_last == sig) + sigset->rr_last = prev; + sigset->rr_count--; + sigset->size -= sig->size; + insert = sig; + /* prev not changed */ + } + /* add to dataset */ + dataset->rrsig_count++; + insert->next = 0; + if(dataset->rrsig_last) + dataset->rrsig_last->next = insert; + else dataset->rrsig_first = insert; + dataset->rrsig_last = insert; + dataset->size += insert->size; + } else { + prev = sig; + } + sig = nextsig; + } + return 1; +} + +/** change an rrsig rrset for use as data rrset */ +static struct rrset_parse* +change_rrsig_rrset(struct rrset_parse* sigset, struct msg_parse* msg, + ldns_buffer* pkt, uint16_t datatype, uint32_t rrset_flags, + int hasother, ldns_pkt_section section, struct regional* region) +{ + struct rrset_parse* dataset = sigset; + hashvalue_t hash = pkt_hash_rrset(pkt, sigset->dname, datatype, + sigset->rrset_class, rrset_flags); + log_assert( sigset->type == LDNS_RR_TYPE_RRSIG ); + log_assert( datatype != LDNS_RR_TYPE_RRSIG ); + if(hasother) { + /* need to make new rrset to hold data type */ + dataset = new_rrset(msg, sigset->dname, sigset->dname_len, + datatype, sigset->rrset_class, hash, rrset_flags, + section, region); + if(!dataset) + return NULL; + switch(section) { + case LDNS_SECTION_ANSWER: msg->an_rrsets++; break; + case LDNS_SECTION_AUTHORITY: msg->ns_rrsets++; break; + case LDNS_SECTION_ADDITIONAL: msg->ar_rrsets++; break; + default: log_assert(0); + } + if(!moveover_rrsigs(pkt, region, sigset, dataset, + msg->qtype == LDNS_RR_TYPE_RRSIG || + (msg->qtype == LDNS_RR_TYPE_ANY && + section != LDNS_SECTION_ANSWER) )) + return NULL; + return dataset; + } + /* changeover the type of the rrset to data set */ + msgparse_bucket_remove(msg, dataset); + /* insert into new hash bucket */ + dataset->rrset_bucket_next = msg->hashtable[hash&(PARSE_TABLE_SIZE-1)]; + msg->hashtable[hash&(PARSE_TABLE_SIZE-1)] = dataset; + dataset->hash = hash; + /* use section of data item for result */ + change_section(msg, dataset, section); + dataset->type = datatype; + dataset->flags = rrset_flags; + dataset->rrsig_count += dataset->rr_count; + dataset->rr_count = 0; + /* move sigs to end of siglist */ + if(dataset->rrsig_last) + dataset->rrsig_last->next = dataset->rr_first; + else dataset->rrsig_first = dataset->rr_first; + dataset->rrsig_last = dataset->rr_last; + dataset->rr_first = 0; + dataset->rr_last = 0; + return dataset; +} + +/** Find rrset. If equal to previous it is fast. hash if not so. + * @param msg: the message with hash table. + * @param pkt: the packet in wireformat (needed for compression ptrs). + * @param dname: pointer to start of dname (compressed) in packet. + * @param dnamelen: uncompressed wirefmt length of dname. + * @param type: type of current rr. + * @param dclass: class of current rr. + * @param hash: hash value is returned if the rrset could not be found. + * @param rrset_flags: is returned if the rrset could not be found. + * @param prev_dname_first: dname of last seen RR. First seen dname. + * @param prev_dname_last: dname of last seen RR. Last seen dname. + * @param prev_dnamelen: dname len of last seen RR. + * @param prev_type: type of last seen RR. + * @param prev_dclass: class of last seen RR. + * @param rrset_prev: last seen RRset. + * @param section: the current section in the packet. + * @param region: used to allocate temporary parsing data. + * @return 0 on out of memory. + */ +static int +find_rrset(struct msg_parse* msg, ldns_buffer* pkt, uint8_t* dname, + size_t dnamelen, uint16_t type, uint16_t dclass, hashvalue_t* hash, + uint32_t* rrset_flags, + uint8_t** prev_dname_first, uint8_t** prev_dname_last, + size_t* prev_dnamelen, uint16_t* prev_type, + uint16_t* prev_dclass, struct rrset_parse** rrset_prev, + ldns_pkt_section section, struct regional* region) +{ + hashvalue_t dname_h = pkt_hash_rrset_first(pkt, dname); + uint16_t covtype; + if(*rrset_prev) { + /* check if equal to previous item */ + if(type == *prev_type && dclass == *prev_dclass && + dnamelen == *prev_dnamelen && + smart_compare(pkt, dname, *prev_dname_first, + *prev_dname_last) == 0 && + type != LDNS_RR_TYPE_RRSIG) { + /* same as previous */ + *prev_dname_last = dname; + return 1; + } + /* check if rrsig over previous item */ + if(type == LDNS_RR_TYPE_RRSIG && dclass == *prev_dclass && + pkt_rrsig_covered_equals(pkt, ldns_buffer_current(pkt), + *prev_type) && + smart_compare(pkt, dname, *prev_dname_first, + *prev_dname_last) == 0) { + /* covers previous */ + *prev_dname_last = dname; + return 1; + } + } + /* find by hashing and lookup in hashtable */ + *rrset_flags = pkt_rrset_flags(pkt, type, section); + + /* if rrsig - try to lookup matching data set first */ + if(type == LDNS_RR_TYPE_RRSIG && pkt_rrsig_covered(pkt, + ldns_buffer_current(pkt), &covtype)) { + *hash = pkt_hash_rrset_rest(dname_h, covtype, dclass, + *rrset_flags); + *rrset_prev = msgparse_hashtable_lookup(msg, pkt, *hash, + *rrset_flags, dname, dnamelen, covtype, dclass); + if(!*rrset_prev && covtype == LDNS_RR_TYPE_NSEC) { + /* if NSEC try with NSEC apex bit twiddled */ + *rrset_flags ^= PACKED_RRSET_NSEC_AT_APEX; + *hash = pkt_hash_rrset_rest(dname_h, covtype, dclass, + *rrset_flags); + *rrset_prev = msgparse_hashtable_lookup(msg, pkt, + *hash, *rrset_flags, dname, dnamelen, covtype, + dclass); + if(!*rrset_prev) /* untwiddle if not found */ + *rrset_flags ^= PACKED_RRSET_NSEC_AT_APEX; + } + if(!*rrset_prev && covtype == LDNS_RR_TYPE_SOA) { + /* if SOA try with SOA neg flag twiddled */ + *rrset_flags ^= PACKED_RRSET_SOA_NEG; + *hash = pkt_hash_rrset_rest(dname_h, covtype, dclass, + *rrset_flags); + *rrset_prev = msgparse_hashtable_lookup(msg, pkt, + *hash, *rrset_flags, dname, dnamelen, covtype, + dclass); + if(!*rrset_prev) /* untwiddle if not found */ + *rrset_flags ^= PACKED_RRSET_SOA_NEG; + } + if(*rrset_prev) { + *prev_dname_first = (*rrset_prev)->dname; + *prev_dname_last = dname; + *prev_dnamelen = dnamelen; + *prev_type = covtype; + *prev_dclass = dclass; + return 1; + } + } + if(type != LDNS_RR_TYPE_RRSIG) { + int hasother = 0; + /* find matching rrsig */ + *hash = pkt_hash_rrset_rest(dname_h, LDNS_RR_TYPE_RRSIG, + dclass, 0); + *rrset_prev = msgparse_hashtable_lookup(msg, pkt, *hash, + 0, dname, dnamelen, LDNS_RR_TYPE_RRSIG, + dclass); + if(*rrset_prev && rrset_has_sigover(pkt, *rrset_prev, type, + &hasother)) { + /* yes! */ + *prev_dname_first = (*rrset_prev)->dname; + *prev_dname_last = dname; + *prev_dnamelen = dnamelen; + *prev_type = type; + *prev_dclass = dclass; + *rrset_prev = change_rrsig_rrset(*rrset_prev, msg, + pkt, type, *rrset_flags, hasother, section, + region); + if(!*rrset_prev) return 0; + return 1; + } + } + + *hash = pkt_hash_rrset_rest(dname_h, type, dclass, *rrset_flags); + *rrset_prev = msgparse_hashtable_lookup(msg, pkt, *hash, *rrset_flags, + dname, dnamelen, type, dclass); + if(*rrset_prev) + *prev_dname_first = (*rrset_prev)->dname; + else *prev_dname_first = dname; + *prev_dname_last = dname; + *prev_dnamelen = dnamelen; + *prev_type = type; + *prev_dclass = dclass; + return 1; +} + +/** + * Parse query section. + * @param pkt: packet, position at call must be at start of query section. + * at end position is after query section. + * @param msg: store results here. + * @return: 0 if OK, or rcode on error. + */ +static int +parse_query_section(ldns_buffer* pkt, struct msg_parse* msg) +{ + if(msg->qdcount == 0) + return 0; + if(msg->qdcount > 1) + return LDNS_RCODE_FORMERR; + log_assert(msg->qdcount == 1); + if(ldns_buffer_remaining(pkt) <= 0) + return LDNS_RCODE_FORMERR; + msg->qname = ldns_buffer_current(pkt); + if((msg->qname_len = pkt_dname_len(pkt)) == 0) + return LDNS_RCODE_FORMERR; + if(ldns_buffer_remaining(pkt) < sizeof(uint16_t)*2) + return LDNS_RCODE_FORMERR; + msg->qtype = ldns_buffer_read_u16(pkt); + msg->qclass = ldns_buffer_read_u16(pkt); + return 0; +} + +size_t +get_rdf_size(ldns_rdf_type rdf) +{ + switch(rdf) { + case LDNS_RDF_TYPE_CLASS: + case LDNS_RDF_TYPE_ALG: + case LDNS_RDF_TYPE_INT8: + return 1; + break; + case LDNS_RDF_TYPE_INT16: + case LDNS_RDF_TYPE_TYPE: + case LDNS_RDF_TYPE_CERT_ALG: + return 2; + break; + case LDNS_RDF_TYPE_INT32: + case LDNS_RDF_TYPE_TIME: + case LDNS_RDF_TYPE_A: + case LDNS_RDF_TYPE_PERIOD: + return 4; + break; + case LDNS_RDF_TYPE_TSIGTIME: + return 6; + break; + case LDNS_RDF_TYPE_AAAA: + return 16; + break; + default: + log_assert(false); /* add type above */ + /* only types that appear before a domain * + * name are needed. rest is simply copied. */ + } + return 0; +} + +/** calculate the size of one rr */ +static int +calc_size(ldns_buffer* pkt, uint16_t type, struct rr_parse* rr) +{ + const ldns_rr_descriptor* desc; + uint16_t pkt_len; /* length of rr inside the packet */ + rr->size = sizeof(uint16_t); /* the rdatalen */ + ldns_buffer_skip(pkt, 4); /* skip ttl */ + pkt_len = ldns_buffer_read_u16(pkt); + if(ldns_buffer_remaining(pkt) < pkt_len) + return 0; + desc = ldns_rr_descript(type); + if(pkt_len > 0 && desc && desc->_dname_count > 0) { + int count = (int)desc->_dname_count; + int rdf = 0; + size_t len; + size_t oldpos; + /* skip first part. */ + while(pkt_len > 0 && count) { + switch(desc->_wireformat[rdf]) { + case LDNS_RDF_TYPE_DNAME: + /* decompress every domain name */ + oldpos = ldns_buffer_position(pkt); + if((len = pkt_dname_len(pkt)) == 0) + return 0; /* malformed dname */ + if(ldns_buffer_position(pkt)-oldpos > pkt_len) + return 0; /* dname exceeds rdata */ + pkt_len -= ldns_buffer_position(pkt)-oldpos; + rr->size += len; + count--; + len = 0; + break; + case LDNS_RDF_TYPE_STR: + if(pkt_len < 1) + return 0; /* len byte exceeds rdata */ + len = ldns_buffer_current(pkt)[0] + 1; + break; + default: + len = get_rdf_size(desc->_wireformat[rdf]); + } + if(len) { + if(pkt_len < len) + return 0; /* exceeds rdata */ + pkt_len -= len; + ldns_buffer_skip(pkt, (ssize_t)len); + rr->size += len; + } + rdf++; + } + } + /* remaining rdata */ + rr->size += pkt_len; + ldns_buffer_skip(pkt, (ssize_t)pkt_len); + return 1; +} + +/** skip rr ttl and rdata */ +static int +skip_ttl_rdata(ldns_buffer* pkt) +{ + uint16_t rdatalen; + if(ldns_buffer_remaining(pkt) < 6) /* ttl + rdatalen */ + return 0; + ldns_buffer_skip(pkt, 4); /* ttl */ + rdatalen = ldns_buffer_read_u16(pkt); + if(ldns_buffer_remaining(pkt) < rdatalen) + return 0; + ldns_buffer_skip(pkt, (ssize_t)rdatalen); + return 1; +} + +/** see if RRSIG is a duplicate of another */ +static int +sig_is_double(ldns_buffer* pkt, struct rrset_parse* rrset, uint8_t* ttldata) +{ + uint16_t rlen, siglen; + size_t pos = ldns_buffer_position(pkt); + struct rr_parse* sig; + if(ldns_buffer_remaining(pkt) < 6) + return 0; + ldns_buffer_skip(pkt, 4); /* ttl */ + rlen = ldns_buffer_read_u16(pkt); + if(ldns_buffer_remaining(pkt) < rlen) { + ldns_buffer_set_position(pkt, pos); + return 0; + } + ldns_buffer_set_position(pkt, pos); + + sig = rrset->rrsig_first; + while(sig) { + /* check if rdatalen is same */ + memmove(&siglen, sig->ttl_data+4, sizeof(siglen)); + siglen = ntohs(siglen); + /* checks if data in packet is exactly the same, this means + * also dname in rdata is the same, but rrsig is not allowed + * to have compressed dnames anyway. If it is compressed anyway + * it will lead to duplicate rrs for qtype=RRSIG. (or ANY). + * + * Cannot use sig->size because size of the other one is not + * calculated yet. + */ + if(siglen == rlen) { + if(siglen>0 && memcmp(sig->ttl_data+6, ttldata+6, + siglen) == 0) { + /* same! */ + return 1; + } + } + sig = sig->next; + } + return 0; +} + +/** Add rr (from packet here) to rrset, skips rr */ +static int +add_rr_to_rrset(struct rrset_parse* rrset, ldns_buffer* pkt, + struct msg_parse* msg, struct regional* region, + ldns_pkt_section section, uint16_t type) +{ + struct rr_parse* rr; + /* check section of rrset. */ + if(rrset->section != section && type != LDNS_RR_TYPE_RRSIG && + rrset->type != LDNS_RR_TYPE_RRSIG) { + /* silently drop it - we drop the last part, since + * trust in rr data depends on the section it is in. + * the less trustworthy part is discarded. + * also the last part is more likely to be incomplete. + * RFC 2181: must put RRset only once in response. */ + /* + verbose(VERB_QUERY, "Packet contains rrset data in " + "multiple sections, dropped last part."); + log_buf(VERB_QUERY, "packet was", pkt); + */ + /* forwards */ + if(!skip_ttl_rdata(pkt)) + return LDNS_RCODE_FORMERR; + return 0; + } + + if( (msg->qtype == LDNS_RR_TYPE_RRSIG || + msg->qtype == LDNS_RR_TYPE_ANY) + && sig_is_double(pkt, rrset, ldns_buffer_current(pkt))) { + if(!skip_ttl_rdata(pkt)) + return LDNS_RCODE_FORMERR; + return 0; + } + + /* create rr */ + if(!(rr = (struct rr_parse*)regional_alloc(region, sizeof(*rr)))) + return LDNS_RCODE_SERVFAIL; + rr->outside_packet = 0; + rr->ttl_data = ldns_buffer_current(pkt); + rr->next = 0; + if(type == LDNS_RR_TYPE_RRSIG && rrset->type != LDNS_RR_TYPE_RRSIG) { + if(rrset->rrsig_last) + rrset->rrsig_last->next = rr; + else rrset->rrsig_first = rr; + rrset->rrsig_last = rr; + rrset->rrsig_count++; + } else { + if(rrset->rr_last) + rrset->rr_last->next = rr; + else rrset->rr_first = rr; + rrset->rr_last = rr; + rrset->rr_count++; + } + + /* calc decompressed size */ + if(!calc_size(pkt, type, rr)) + return LDNS_RCODE_FORMERR; + rrset->size += rr->size; + + return 0; +} + +/** + * Parse packet RR section, for answer, authority and additional sections. + * @param pkt: packet, position at call must be at start of section. + * at end position is after section. + * @param msg: store results here. + * @param region: how to alloc results. + * @param section: section enum. + * @param num_rrs: how many rrs are in the section. + * @param num_rrsets: returns number of rrsets in the section. + * @return: 0 if OK, or rcode on error. + */ +static int +parse_section(ldns_buffer* pkt, struct msg_parse* msg, + struct regional* region, ldns_pkt_section section, + uint16_t num_rrs, size_t* num_rrsets) +{ + uint16_t i; + uint8_t* dname, *prev_dname_f = NULL, *prev_dname_l = NULL; + size_t dnamelen, prev_dnamelen = 0; + uint16_t type, prev_type = 0; + uint16_t dclass, prev_dclass = 0; + uint32_t rrset_flags = 0; + hashvalue_t hash = 0; + struct rrset_parse* rrset = NULL; + int r; + + if(num_rrs == 0) + return 0; + if(ldns_buffer_remaining(pkt) <= 0) + return LDNS_RCODE_FORMERR; + for(i=0; i_name: "??", + (int)type, + ldns_rr_descript(t)? + ldns_rr_descript(t)->_name: "??", + (int)t); + } else + fprintf(stderr, "parse of %s(%d)", + ldns_rr_descript(type)? + ldns_rr_descript(type)->_name: "??", + (int)type); + fprintf(stderr, " %s(%d) ", + ldns_lookup_by_id(ldns_rr_classes, + (int)ntohs(dclass))?ldns_lookup_by_id( + ldns_rr_classes, (int)ntohs(dclass))->name: + "??", (int)ntohs(dclass)); + dname_print(stderr, pkt, dname); + fprintf(stderr, "\n"); + } + + /* see if it is part of an existing RR set */ + if(!find_rrset(msg, pkt, dname, dnamelen, type, dclass, &hash, + &rrset_flags, &prev_dname_f, &prev_dname_l, + &prev_dnamelen, &prev_type, &prev_dclass, &rrset, + section, region)) + return LDNS_RCODE_SERVFAIL; + if(!rrset) { + /* it is a new RR set. hash&flags already calculated.*/ + (*num_rrsets)++; + rrset = new_rrset(msg, dname, dnamelen, type, dclass, + hash, rrset_flags, section, region); + if(!rrset) + return LDNS_RCODE_SERVFAIL; + } + else if(0) { + fprintf(stderr, "is part of existing: "); + dname_print(stderr, pkt, rrset->dname); + fprintf(stderr, " type %s(%d)\n", + ldns_rr_descript(rrset->type)? + ldns_rr_descript(rrset->type)->_name: "??", + (int)rrset->type); + } + /* add to rrset. */ + if((r=add_rr_to_rrset(rrset, pkt, msg, region, section, + type)) != 0) + return r; + } + return 0; +} + +int +parse_packet(ldns_buffer* pkt, struct msg_parse* msg, struct regional* region) +{ + int ret; + if(ldns_buffer_remaining(pkt) < LDNS_HEADER_SIZE) + return LDNS_RCODE_FORMERR; + /* read the header */ + ldns_buffer_read(pkt, &msg->id, sizeof(uint16_t)); + msg->flags = ldns_buffer_read_u16(pkt); + msg->qdcount = ldns_buffer_read_u16(pkt); + msg->ancount = ldns_buffer_read_u16(pkt); + msg->nscount = ldns_buffer_read_u16(pkt); + msg->arcount = ldns_buffer_read_u16(pkt); + if(msg->qdcount > 1) + return LDNS_RCODE_FORMERR; + if((ret = parse_query_section(pkt, msg)) != 0) + return ret; + if((ret = parse_section(pkt, msg, region, LDNS_SECTION_ANSWER, + msg->ancount, &msg->an_rrsets)) != 0) + return ret; + if((ret = parse_section(pkt, msg, region, LDNS_SECTION_AUTHORITY, + msg->nscount, &msg->ns_rrsets)) != 0) + return ret; + if(ldns_buffer_remaining(pkt) == 0 && msg->arcount == 1) { + /* BIND accepts leniently that an EDNS record is missing. + * so, we do too. */ + } else if((ret = parse_section(pkt, msg, region, + LDNS_SECTION_ADDITIONAL, msg->arcount, &msg->ar_rrsets)) != 0) + return ret; + /* if(ldns_buffer_remaining(pkt) > 0) { */ + /* there is spurious data at end of packet. ignore */ + /* } */ + msg->rrset_count = msg->an_rrsets + msg->ns_rrsets + msg->ar_rrsets; + return 0; +} + +int +parse_extract_edns(struct msg_parse* msg, struct edns_data* edns) +{ + struct rrset_parse* rrset = msg->rrset_first; + struct rrset_parse* prev = 0; + struct rrset_parse* found = 0; + struct rrset_parse* found_prev = 0; + /* since the class encodes the UDP size, we cannot use hash table to + * find the EDNS OPT record. Scan the packet. */ + while(rrset) { + if(rrset->type == LDNS_RR_TYPE_OPT) { + /* only one OPT RR allowed. */ + if(found) return LDNS_RCODE_FORMERR; + /* found it! */ + found_prev = prev; + found = rrset; + } + prev = rrset; + rrset = rrset->rrset_all_next; + } + if(!found) { + memset(edns, 0, sizeof(*edns)); + edns->udp_size = 512; + return 0; + } + /* check the found RRset */ + /* most lenient check possible. ignore dname, use last opt */ + if(found->section != LDNS_SECTION_ADDITIONAL) + return LDNS_RCODE_FORMERR; + if(found->rr_count == 0) + return LDNS_RCODE_FORMERR; + if(0) { /* strict checking of dname and RRcount */ + if(found->dname_len != 1 || !found->dname + || found->dname[0] != 0) return LDNS_RCODE_FORMERR; + if(found->rr_count != 1) return LDNS_RCODE_FORMERR; + } + log_assert(found->rr_first && found->rr_last); + + /* remove from packet */ + if(found_prev) found_prev->rrset_all_next = found->rrset_all_next; + else msg->rrset_first = found->rrset_all_next; + if(found == msg->rrset_last) + msg->rrset_last = found_prev; + msg->arcount --; + msg->ar_rrsets --; + msg->rrset_count --; + + /* take the data ! */ + edns->edns_present = 1; + edns->ext_rcode = found->rr_last->ttl_data[0]; + edns->edns_version = found->rr_last->ttl_data[1]; + edns->bits = ldns_read_uint16(&found->rr_last->ttl_data[2]); + edns->udp_size = ntohs(found->rrset_class); + /* ignore rdata and rrsigs */ + return 0; +} + +int +parse_edns_from_pkt(ldns_buffer* pkt, struct edns_data* edns) +{ + log_assert(LDNS_QDCOUNT(ldns_buffer_begin(pkt)) == 1); + log_assert(LDNS_ANCOUNT(ldns_buffer_begin(pkt)) == 0); + log_assert(LDNS_NSCOUNT(ldns_buffer_begin(pkt)) == 0); + /* check edns section is present */ + if(LDNS_ARCOUNT(ldns_buffer_begin(pkt)) > 1) { + return LDNS_RCODE_FORMERR; + } + if(LDNS_ARCOUNT(ldns_buffer_begin(pkt)) == 0) { + memset(edns, 0, sizeof(*edns)); + edns->udp_size = 512; + return 0; + } + /* domain name must be the root of length 1. */ + if(pkt_dname_len(pkt) != 1) + return LDNS_RCODE_FORMERR; + if(ldns_buffer_remaining(pkt) < 10) /* type, class, ttl, rdatalen */ + return LDNS_RCODE_FORMERR; + if(ldns_buffer_read_u16(pkt) != LDNS_RR_TYPE_OPT) + return LDNS_RCODE_FORMERR; + edns->edns_present = 1; + edns->udp_size = ldns_buffer_read_u16(pkt); /* class is udp size */ + edns->ext_rcode = ldns_buffer_read_u8(pkt); /* ttl used for bits */ + edns->edns_version = ldns_buffer_read_u8(pkt); + edns->bits = ldns_buffer_read_u16(pkt); + /* ignore rdata and rrsigs */ + return 0; +} diff --git a/util/data/msgparse.h b/util/data/msgparse.h new file mode 100644 index 00000000000..830d68e16cd --- /dev/null +++ b/util/data/msgparse.h @@ -0,0 +1,299 @@ +/* + * util/data/msgparse.h - parse wireformat DNS messages. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \file + * Contains message parsing data structures. + * These point back into the packet buffer. + * + * During parsing RRSIGS are put together with the rrsets they (claim to) sign. + * This process works as follows: + * o if RRSIG follows the data rrset, it is added to the rrset rrsig list. + * o if no matching data rrset is found, the RRSIG becomes a new rrset. + * o If the data rrset later follows the RRSIG + * o See if the RRSIG rrset contains multiple types, and needs to + * have the rrsig(s) for that data type split off. + * o Put the data rr as data type in the rrset and rrsig in list. + * o RRSIGs are allowed to move to a different section. The section of + * the data item is used for the final rrset. + * o multiple signatures over an RRset are possible. + * + * For queries of qtype=RRSIG, some special handling is needed, to avoid + * splitting the RRSIG in the answer section. + * o duplicate, not split, RRSIGs from the answer section, if qtype=RRSIG. + * o check for doubles in the rrsig list when adding an RRSIG to data, + * so that a data rrset is signed by RRSIGs with different rdata. + * when qtype=RRSIG. + * This will move the RRSIG from the answer section to sign the data further + * in the packet (if possible). If then after that, more RRSIGs are found + * that sign the data as well, doubles are removed. + */ + +#ifndef UTIL_DATA_MSGPARSE_H +#define UTIL_DATA_MSGPARSE_H +#include "util/storage/lruhash.h" +#include +struct rrset_parse; +struct rr_parse; +struct regional; + +/** number of buckets in parse rrset hash table. Must be power of 2. */ +#define PARSE_TABLE_SIZE 32 +/** Maximum TTL that is allowed. */ +extern uint32_t MAX_TTL; +/** Minimum TTL that is allowed. */ +extern uint32_t MIN_TTL; +/** Negative cache time (for entries without any RRs.) */ +#define NORR_TTL 5 /* seconds */ + +/** + * Data stored in scratch pad memory during parsing. + * Stores the data that will enter into the msgreply and packet result. + */ +struct msg_parse { + /** id from message, network format. */ + uint16_t id; + /** flags from message, host format. */ + uint16_t flags; + /** count of RRs, host format */ + uint16_t qdcount; + /** count of RRs, host format */ + uint16_t ancount; + /** count of RRs, host format */ + uint16_t nscount; + /** count of RRs, host format */ + uint16_t arcount; + /** count of RRsets per section. */ + size_t an_rrsets; + /** count of RRsets per section. */ + size_t ns_rrsets; + /** count of RRsets per section. */ + size_t ar_rrsets; + /** total number of rrsets found. */ + size_t rrset_count; + + /** query dname (pointer to start location in packet, NULL if none */ + uint8_t* qname; + /** length of query dname in octets, 0 if none */ + size_t qname_len; + /** query type, host order. 0 if qdcount=0 */ + uint16_t qtype; + /** query class, host order. 0 if qdcount=0 */ + uint16_t qclass; + + /** + * Hash table array used during parsing to lookup rrset types. + * Based on name, type, class. Same hash value as in rrset cache. + */ + struct rrset_parse* hashtable[PARSE_TABLE_SIZE]; + + /** linked list of rrsets that have been found (in order). */ + struct rrset_parse* rrset_first; + /** last element of rrset list. */ + struct rrset_parse* rrset_last; +}; + +/** + * Data stored for an rrset during parsing. + */ +struct rrset_parse { + /** next in hash bucket */ + struct rrset_parse* rrset_bucket_next; + /** next in list of all rrsets */ + struct rrset_parse* rrset_all_next; + /** hash value of rrset */ + hashvalue_t hash; + /** which section was it found in: one of + * LDNS_SECTION_ANSWER, LDNS_SECTION_AUTHORITY, LDNS_SECTION_ADDITIONAL + */ + ldns_pkt_section section; + /** start of (possibly compressed) dname in packet */ + uint8_t* dname; + /** length of the dname uncompressed wireformat */ + size_t dname_len; + /** type, host order. */ + uint16_t type; + /** class, network order. var name so that it is not a c++ keyword. */ + uint16_t rrset_class; + /** the flags for the rrset, like for packedrrset */ + uint32_t flags; + /** number of RRs in the rr list */ + size_t rr_count; + /** sum of RR rdata sizes */ + size_t size; + /** linked list of RRs in this rrset. */ + struct rr_parse* rr_first; + /** last in list of RRs in this rrset. */ + struct rr_parse* rr_last; + /** number of RRSIGs over this rrset. */ + size_t rrsig_count; + /** linked list of RRsig RRs over this rrset. */ + struct rr_parse* rrsig_first; + /** last in list of RRSIG RRs over this rrset. */ + struct rr_parse* rrsig_last; +}; + +/** + * Data stored for an RR during parsing. + */ +struct rr_parse { + /** + * Pointer to the RR. Points to start of TTL value in the packet. + * Rdata length and rdata follow it. + * its dname, type and class are the same and stored for the rrset. + */ + uint8_t* ttl_data; + /** true if ttl_data is not part of the packet, but elsewhere in mem. + * Set for generated CNAMEs for DNAMEs. */ + int outside_packet; + /** the length of the rdata if allocated (with no dname compression)*/ + size_t size; + /** next in list of RRs. */ + struct rr_parse* next; +}; + +/** Check if label length is first octet of a compression pointer, pass u8. */ +#define LABEL_IS_PTR(x) ( ((x)&0xc0) == 0xc0 ) +/** Calculate destination offset of a compression pointer. pass first and + * second octets of the compression pointer. */ +#define PTR_OFFSET(x, y) ( ((x)&0x3f)<<8 | (y) ) +/** create a compression pointer to the given offset. */ +#define PTR_CREATE(offset) ((uint16_t)(0xc000 | (offset))) + +/** error codes, extended with EDNS, so > 15. */ +#define EDNS_RCODE_BADVERS 16 /** bad EDNS version */ +/** largest valid compression offset */ +#define PTR_MAX_OFFSET 0x3fff + +/** + * EDNS data storage + * EDNS rdata is ignored. + */ +struct edns_data { + /** if EDNS OPT record was present */ + int edns_present; + /** Extended RCODE */ + uint8_t ext_rcode; + /** The EDNS version number */ + uint8_t edns_version; + /** the EDNS bits field from ttl (host order): Z */ + uint16_t bits; + /** UDP reassembly size. */ + uint16_t udp_size; +}; + +/** + * Obtain size in the packet of an rr type, that is before dname type. + * Do TYPE_DNAME, and type STR, yourself. Gives size for most regular types. + * @param rdf: the rdf type from the descriptor. + * @return: size in octets. 0 on failure. + */ +size_t get_rdf_size(ldns_rdf_type rdf); + +/** + * Parse the packet. + * @param pkt: packet, position at call must be at start of packet. + * at end position is after packet. + * @param msg: where to store results. + * @param region: how to alloc results. + * @return: 0 if OK, or rcode on error. + */ +int parse_packet(ldns_buffer* pkt, struct msg_parse* msg, + struct regional* region); + +/** + * After parsing the packet, extract EDNS data from packet. + * If not present this is noted in the data structure. + * If a parse error happens, an error code is returned. + * + * Quirks: + * o ignores OPT rdata. + * o ignores OPT owner name. + * o ignores extra OPT records, except the last one in the packet. + * + * @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. + * @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); + +/** + * If EDNS data follows a query section, extract it and initialize edns struct. + * @param pkt: the packet. position at start must be right after the query + * 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. + * @return: 0 on success, or an RCODE on error. + * RCODE formerr if OPT is badly formatted and so on. + */ +int parse_edns_from_pkt(ldns_buffer* pkt, struct edns_data* edns); + +/** + * Calculate hash value for rrset in packet. + * @param pkt: the packet. + * @param dname: pointer to uncompressed dname, or compressed dname in packet. + * @param type: rrset type in host order. + * @param dclass: rrset class in network order. + * @param rrset_flags: rrset flags (same as packed_rrset flags). + * @return hash value + */ +hashvalue_t pkt_hash_rrset(ldns_buffer* pkt, uint8_t* dname, uint16_t type, + uint16_t dclass, uint32_t rrset_flags); + +/** + * Lookup in msg hashtable to find a rrset. + * @param msg: with the hashtable. + * @param pkt: packet for compressed names. + * @param h: hash value + * @param rrset_flags: flags of rrset sought for. + * @param dname: name of rrset sought for. + * @param dnamelen: len of dname. + * @param type: rrset type, host order. + * @param dclass: rrset class, network order. + * @return NULL or the rrset_parse if found. + */ +struct rrset_parse* msgparse_hashtable_lookup(struct msg_parse* msg, + ldns_buffer* pkt, hashvalue_t h, uint32_t rrset_flags, + uint8_t* dname, size_t dnamelen, uint16_t type, uint16_t dclass); + +/** + * Remove rrset from hash table. + * @param msg: with hashtable. + * @param rrset: with hash value and id info. + */ +void msgparse_bucket_remove(struct msg_parse* msg, struct rrset_parse* rrset); + +#endif /* UTIL_DATA_MSGPARSE_H */ diff --git a/util/data/msgreply.c b/util/data/msgreply.c new file mode 100644 index 00000000000..6d711fff3a2 --- /dev/null +++ b/util/data/msgreply.c @@ -0,0 +1,838 @@ +/* + * util/data/msgreply.c - store message and reply data. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains a data structure to store a message and its reply. + */ + +#include "config.h" +#include +#include "util/data/msgreply.h" +#include "util/storage/lookup3.h" +#include "util/log.h" +#include "util/alloc.h" +#include "util/netevent.h" +#include "util/net_help.h" +#include "util/data/dname.h" +#include "util/regional.h" +#include "util/data/msgparse.h" +#include "util/data/msgencode.h" + +/** MAX TTL default for messages and rrsets */ +uint32_t MAX_TTL = 3600 * 24 * 10; /* ten days */ +/** MIN TTL default for messages and rrsets */ +uint32_t MIN_TTL = 0; + +/** allocate qinfo, return 0 on error */ +static int +parse_create_qinfo(ldns_buffer* pkt, struct msg_parse* msg, + struct query_info* qinf, struct regional* region) +{ + if(msg->qname) { + if(region) + qinf->qname = (uint8_t*)regional_alloc(region, + msg->qname_len); + else qinf->qname = (uint8_t*)malloc(msg->qname_len); + if(!qinf->qname) return 0; + dname_pkt_copy(pkt, qinf->qname, msg->qname); + } else qinf->qname = 0; + qinf->qname_len = msg->qname_len; + qinf->qtype = msg->qtype; + qinf->qclass = msg->qclass; + return 1; +} + +/** constructor for replyinfo */ +static struct reply_info* +construct_reply_info_base(struct regional* region, uint16_t flags, size_t qd, + uint32_t ttl, uint32_t prettl, size_t an, size_t ns, size_t ar, + size_t total, enum sec_status sec) +{ + struct reply_info* rep; + /* rrset_count-1 because the first ref is part of the struct. */ + size_t s = sizeof(struct reply_info) - sizeof(struct rrset_ref) + + sizeof(struct ub_packed_rrset_key*) * total; + if(region) + rep = (struct reply_info*)regional_alloc(region, s); + else rep = (struct reply_info*)malloc(s + + sizeof(struct rrset_ref) * (total)); + if(!rep) + return NULL; + rep->flags = flags; + rep->qdcount = qd; + rep->ttl = ttl; + rep->prefetch_ttl = prettl; + rep->an_numrrsets = an; + rep->ns_numrrsets = ns; + rep->ar_numrrsets = ar; + rep->rrset_count = total; + rep->security = sec; + rep->authoritative = 0; + /* array starts after the refs */ + if(region) + rep->rrsets = (struct ub_packed_rrset_key**)&(rep->ref[0]); + else rep->rrsets = (struct ub_packed_rrset_key**)&(rep->ref[total]); + /* zero the arrays to assist cleanup in case of malloc failure */ + memset( rep->rrsets, 0, sizeof(struct ub_packed_rrset_key*) * total); + if(!region) + memset( &rep->ref[0], 0, sizeof(struct rrset_ref) * total); + return rep; +} + +/** allocate replyinfo, return 0 on error */ +static int +parse_create_repinfo(struct msg_parse* msg, struct reply_info** rep, + struct regional* region) +{ + *rep = construct_reply_info_base(region, msg->flags, msg->qdcount, 0, + 0, msg->an_rrsets, msg->ns_rrsets, msg->ar_rrsets, + msg->rrset_count, sec_status_unchecked); + if(!*rep) + return 0; + return 1; +} + +/** allocate (special) rrset keys, return 0 on error */ +static int +repinfo_alloc_rrset_keys(struct reply_info* rep, struct alloc_cache* alloc, + struct regional* region) +{ + size_t i; + for(i=0; irrset_count; i++) { + if(region) { + rep->rrsets[i] = (struct ub_packed_rrset_key*) + regional_alloc(region, + sizeof(struct ub_packed_rrset_key)); + if(rep->rrsets[i]) { + memset(rep->rrsets[i], 0, + sizeof(struct ub_packed_rrset_key)); + rep->rrsets[i]->entry.key = rep->rrsets[i]; + } + } + else rep->rrsets[i] = alloc_special_obtain(alloc); + if(!rep->rrsets[i]) + return 0; + rep->rrsets[i]->entry.data = NULL; + } + return 1; +} + +/** do the rdata copy */ +static int +rdata_copy(ldns_buffer* pkt, struct packed_rrset_data* data, uint8_t* to, + struct rr_parse* rr, uint32_t* rr_ttl, uint16_t type) +{ + uint16_t pkt_len; + const ldns_rr_descriptor* desc; + + *rr_ttl = ldns_read_uint32(rr->ttl_data); + /* RFC 2181 Section 8. if msb of ttl is set treat as if zero. */ + if(*rr_ttl & 0x80000000U) + *rr_ttl = 0; + if(*rr_ttl < MIN_TTL) + *rr_ttl = MIN_TTL; + if(*rr_ttl < data->ttl) + data->ttl = *rr_ttl; + + if(rr->outside_packet) { + /* uncompressed already, only needs copy */ + memmove(to, rr->ttl_data+sizeof(uint32_t), rr->size); + return 1; + } + + ldns_buffer_set_position(pkt, (size_t) + (rr->ttl_data - ldns_buffer_begin(pkt) + sizeof(uint32_t))); + /* insert decompressed size into rdata len stored in memory */ + /* -2 because rdatalen bytes are not included. */ + pkt_len = htons(rr->size - 2); + memmove(to, &pkt_len, sizeof(uint16_t)); + to += 2; + /* read packet rdata len */ + pkt_len = ldns_buffer_read_u16(pkt); + if(ldns_buffer_remaining(pkt) < pkt_len) + return 0; + desc = ldns_rr_descript(type); + if(pkt_len > 0 && desc && desc->_dname_count > 0) { + int count = (int)desc->_dname_count; + int rdf = 0; + size_t len; + size_t oldpos; + /* decompress dnames. */ + while(pkt_len > 0 && count) { + switch(desc->_wireformat[rdf]) { + case LDNS_RDF_TYPE_DNAME: + oldpos = ldns_buffer_position(pkt); + dname_pkt_copy(pkt, to, + ldns_buffer_current(pkt)); + to += pkt_dname_len(pkt); + pkt_len -= ldns_buffer_position(pkt)-oldpos; + count--; + len = 0; + break; + case LDNS_RDF_TYPE_STR: + len = ldns_buffer_current(pkt)[0] + 1; + break; + default: + len = get_rdf_size(desc->_wireformat[rdf]); + break; + } + if(len) { + memmove(to, ldns_buffer_current(pkt), len); + to += len; + ldns_buffer_skip(pkt, (ssize_t)len); + log_assert(len <= pkt_len); + pkt_len -= len; + } + rdf++; + } + } + /* copy remaining rdata */ + if(pkt_len > 0) + memmove(to, ldns_buffer_current(pkt), pkt_len); + + return 1; +} + +/** copy over the data into packed rrset */ +static int +parse_rr_copy(ldns_buffer* pkt, struct rrset_parse* pset, + struct packed_rrset_data* data) +{ + size_t i; + struct rr_parse* rr = pset->rr_first; + uint8_t* nextrdata; + size_t total = pset->rr_count + pset->rrsig_count; + data->ttl = MAX_TTL; + data->count = pset->rr_count; + data->rrsig_count = pset->rrsig_count; + data->trust = rrset_trust_none; + data->security = sec_status_unchecked; + /* layout: struct - rr_len - rr_data - rr_ttl - rdata - rrsig */ + data->rr_len = (size_t*)((uint8_t*)data + + sizeof(struct packed_rrset_data)); + data->rr_data = (uint8_t**)&(data->rr_len[total]); + data->rr_ttl = (uint32_t*)&(data->rr_data[total]); + nextrdata = (uint8_t*)&(data->rr_ttl[total]); + for(i=0; icount; i++) { + data->rr_len[i] = rr->size; + data->rr_data[i] = nextrdata; + nextrdata += rr->size; + if(!rdata_copy(pkt, data, data->rr_data[i], rr, + &data->rr_ttl[i], pset->type)) + return 0; + rr = rr->next; + } + /* if rrsig, its rdata is at nextrdata */ + rr = pset->rrsig_first; + for(i=data->count; irr_len[i] = rr->size; + data->rr_data[i] = nextrdata; + nextrdata += rr->size; + if(!rdata_copy(pkt, data, data->rr_data[i], rr, + &data->rr_ttl[i], LDNS_RR_TYPE_RRSIG)) + return 0; + rr = rr->next; + } + return 1; +} + +/** create rrset return 0 on failure */ +static int +parse_create_rrset(ldns_buffer* pkt, struct rrset_parse* pset, + struct packed_rrset_data** data, struct regional* region) +{ + /* allocate */ + size_t s = sizeof(struct packed_rrset_data) + + (pset->rr_count + pset->rrsig_count) * + (sizeof(size_t)+sizeof(uint8_t*)+sizeof(uint32_t)) + + pset->size; + if(region) + *data = regional_alloc(region, s); + else *data = malloc(s); + if(!*data) + return 0; + /* copy & decompress */ + if(!parse_rr_copy(pkt, pset, *data)) { + if(!region) free(*data); + return 0; + } + return 1; +} + +/** get trust value for rrset */ +static enum rrset_trust +get_rrset_trust(struct msg_parse* msg, struct rrset_parse* rrset) +{ + uint16_t AA = msg->flags & BIT_AA; + if(rrset->section == LDNS_SECTION_ANSWER) { + if(AA) { + /* RFC2181 says remainder of CNAME chain is nonauth*/ + if(msg->rrset_first && + msg->rrset_first->section==LDNS_SECTION_ANSWER + && msg->rrset_first->type==LDNS_RR_TYPE_CNAME){ + if(rrset == msg->rrset_first) + return rrset_trust_ans_AA; + else return rrset_trust_ans_noAA; + } + if(msg->rrset_first && + msg->rrset_first->section==LDNS_SECTION_ANSWER + && msg->rrset_first->type==LDNS_RR_TYPE_DNAME){ + if(rrset == msg->rrset_first || + rrset == msg->rrset_first->rrset_all_next) + return rrset_trust_ans_AA; + else return rrset_trust_ans_noAA; + } + return rrset_trust_ans_AA; + } + else return rrset_trust_ans_noAA; + } else if(rrset->section == LDNS_SECTION_AUTHORITY) { + if(AA) return rrset_trust_auth_AA; + else return rrset_trust_auth_noAA; + } else { + /* addit section */ + if(AA) return rrset_trust_add_AA; + else return rrset_trust_add_noAA; + } + /* NOTREACHED */ + return rrset_trust_none; +} + +int +parse_copy_decompress_rrset(ldns_buffer* pkt, struct msg_parse* msg, + struct rrset_parse *pset, struct regional* region, + struct ub_packed_rrset_key* pk) +{ + struct packed_rrset_data* data; + pk->rk.flags = pset->flags; + pk->rk.dname_len = pset->dname_len; + if(region) + pk->rk.dname = (uint8_t*)regional_alloc( + region, pset->dname_len); + else pk->rk.dname = + (uint8_t*)malloc(pset->dname_len); + if(!pk->rk.dname) + return 0; + /** copy & decompress dname */ + dname_pkt_copy(pkt, pk->rk.dname, pset->dname); + /** copy over type and class */ + pk->rk.type = htons(pset->type); + pk->rk.rrset_class = pset->rrset_class; + /** read data part. */ + if(!parse_create_rrset(pkt, pset, &data, region)) + return 0; + pk->entry.data = (void*)data; + pk->entry.key = (void*)pk; + pk->entry.hash = pset->hash; + data->trust = get_rrset_trust(msg, pset); + return 1; +} + +/** + * Copy and decompress rrs + * @param pkt: the packet for compression pointer resolution. + * @param msg: the parsed message + * @param rep: reply info to put rrs into. + * @param region: if not NULL, used for allocation. + * @return 0 on failure. + */ +static int +parse_copy_decompress(ldns_buffer* pkt, struct msg_parse* msg, + struct reply_info* rep, struct regional* region) +{ + size_t i; + struct rrset_parse *pset = msg->rrset_first; + struct packed_rrset_data* data; + log_assert(rep); + rep->ttl = MAX_TTL; + rep->security = sec_status_unchecked; + if(rep->rrset_count == 0) + rep->ttl = NORR_TTL; + + for(i=0; irrset_count; i++) { + if(!parse_copy_decompress_rrset(pkt, msg, pset, region, + rep->rrsets[i])) + return 0; + data = (struct packed_rrset_data*)rep->rrsets[i]->entry.data; + if(data->ttl < rep->ttl) + rep->ttl = data->ttl; + + pset = pset->rrset_all_next; + } + rep->prefetch_ttl = PREFETCH_TTL_CALC(rep->ttl); + return 1; +} + +int +parse_create_msg(ldns_buffer* pkt, struct msg_parse* msg, + struct alloc_cache* alloc, struct query_info* qinf, + struct reply_info** rep, struct regional* region) +{ + log_assert(pkt && msg); + if(!parse_create_qinfo(pkt, msg, qinf, region)) + return 0; + if(!parse_create_repinfo(msg, rep, region)) + return 0; + if(!repinfo_alloc_rrset_keys(*rep, alloc, region)) + return 0; + if(!parse_copy_decompress(pkt, msg, *rep, region)) + return 0; + return 1; +} + +int reply_info_parse(ldns_buffer* pkt, struct alloc_cache* alloc, + struct query_info* qinf, struct reply_info** rep, + struct regional* region, struct edns_data* edns) +{ + /* use scratch pad region-allocator during parsing. */ + struct msg_parse* msg; + int ret; + + qinf->qname = NULL; + *rep = NULL; + if(!(msg = regional_alloc(region, sizeof(*msg)))) { + return LDNS_RCODE_SERVFAIL; + } + memset(msg, 0, sizeof(*msg)); + + ldns_buffer_set_position(pkt, 0); + if((ret = parse_packet(pkt, msg, region)) != 0) { + return ret; + } + if((ret = parse_extract_edns(msg, edns)) != 0) + return ret; + + /* parse OK, allocate return structures */ + /* this also performs dname decompression */ + if(!parse_create_msg(pkt, msg, alloc, qinf, rep, NULL)) { + query_info_clear(qinf); + reply_info_parsedelete(*rep, alloc); + *rep = NULL; + return LDNS_RCODE_SERVFAIL; + } + return 0; +} + +/** helper compare function to sort in lock order */ +static int +reply_info_sortref_cmp(const void* a, const void* b) +{ + struct rrset_ref* x = (struct rrset_ref*)a; + struct rrset_ref* y = (struct rrset_ref*)b; + if(x->key < y->key) return -1; + if(x->key > y->key) return 1; + return 0; +} + +void +reply_info_sortref(struct reply_info* rep) +{ + qsort(&rep->ref[0], rep->rrset_count, sizeof(struct rrset_ref), + reply_info_sortref_cmp); +} + +void +reply_info_set_ttls(struct reply_info* rep, uint32_t timenow) +{ + size_t i, j; + rep->ttl += timenow; + rep->prefetch_ttl += timenow; + for(i=0; irrset_count; i++) { + struct packed_rrset_data* data = (struct packed_rrset_data*) + rep->ref[i].key->entry.data; + if(i>0 && rep->ref[i].key == rep->ref[i-1].key) + continue; + data->ttl += timenow; + for(j=0; jcount + data->rrsig_count; j++) { + data->rr_ttl[j] += timenow; + } + } +} + +void +reply_info_parsedelete(struct reply_info* rep, struct alloc_cache* alloc) +{ + size_t i; + if(!rep) + return; + /* no need to lock, since not shared in hashtables. */ + for(i=0; irrset_count; i++) { + ub_packed_rrset_parsedelete(rep->rrsets[i], alloc); + } + free(rep); +} + +int +query_info_parse(struct query_info* m, ldns_buffer* query) +{ + uint8_t* q = ldns_buffer_begin(query); + /* minimum size: header + \0 + qtype + qclass */ + if(ldns_buffer_limit(query) < LDNS_HEADER_SIZE + 5) + return 0; + if(LDNS_OPCODE_WIRE(q) != LDNS_PACKET_QUERY || + LDNS_QDCOUNT(q) != 1 || ldns_buffer_position(query) != 0) + return 0; + ldns_buffer_skip(query, LDNS_HEADER_SIZE); + m->qname = ldns_buffer_current(query); + if((m->qname_len = query_dname_len(query)) == 0) + return 0; /* parse error */ + if(ldns_buffer_remaining(query) < 4) + return 0; /* need qtype, qclass */ + m->qtype = ldns_buffer_read_u16(query); + m->qclass = ldns_buffer_read_u16(query); + return 1; +} + +/** tiny subroutine for msgreply_compare */ +#define COMPARE_IT(x, y) \ + if( (x) < (y) ) return -1; \ + else if( (x) > (y) ) return +1; \ + log_assert( (x) == (y) ); + +int +query_info_compare(void* m1, void* m2) +{ + struct query_info* msg1 = (struct query_info*)m1; + struct query_info* msg2 = (struct query_info*)m2; + int mc; + /* from most different to least different for speed */ + COMPARE_IT(msg1->qtype, msg2->qtype); + if((mc = query_dname_compare(msg1->qname, msg2->qname)) != 0) + return mc; + log_assert(msg1->qname_len == msg2->qname_len); + COMPARE_IT(msg1->qclass, msg2->qclass); + return 0; +#undef COMPARE_IT +} + +void +query_info_clear(struct query_info* m) +{ + free(m->qname); + m->qname = NULL; +} + +size_t +msgreply_sizefunc(void* k, void* d) +{ + struct msgreply_entry* q = (struct msgreply_entry*)k; + struct reply_info* r = (struct reply_info*)d; + size_t s = sizeof(struct msgreply_entry) + sizeof(struct reply_info) + + q->key.qname_len + lock_get_mem(&q->entry.lock) + - sizeof(struct rrset_ref); + s += r->rrset_count * sizeof(struct rrset_ref); + s += r->rrset_count * sizeof(struct ub_packed_rrset_key*); + return s; +} + +void +query_entry_delete(void *k, void* ATTR_UNUSED(arg)) +{ + struct msgreply_entry* q = (struct msgreply_entry*)k; + lock_rw_destroy(&q->entry.lock); + query_info_clear(&q->key); + free(q); +} + +void +reply_info_delete(void* d, void* ATTR_UNUSED(arg)) +{ + struct reply_info* r = (struct reply_info*)d; + free(r); +} + +hashvalue_t +query_info_hash(struct query_info *q) +{ + hashvalue_t h = 0xab; + h = hashlittle(&q->qtype, sizeof(q->qtype), h); + h = hashlittle(&q->qclass, sizeof(q->qclass), h); + h = dname_query_hash(q->qname, h); + return h; +} + +struct msgreply_entry* +query_info_entrysetup(struct query_info* q, struct reply_info* r, + hashvalue_t h) +{ + struct msgreply_entry* e = (struct msgreply_entry*)malloc( + sizeof(struct msgreply_entry)); + if(!e) return NULL; + memcpy(&e->key, q, sizeof(*q)); + e->entry.hash = h; + e->entry.key = e; + e->entry.data = r; + lock_rw_init(&e->entry.lock); + lock_protect(&e->entry.lock, &e->key, sizeof(e->key)); + lock_protect(&e->entry.lock, &e->entry.hash, sizeof(e->entry.hash) + + sizeof(e->entry.key) + sizeof(e->entry.data)); + lock_protect(&e->entry.lock, e->key.qname, e->key.qname_len); + q->qname = NULL; + return e; +} + +/** copy rrsets from replyinfo to dest replyinfo */ +static int +repinfo_copy_rrsets(struct reply_info* dest, struct reply_info* from, + struct regional* region) +{ + size_t i, s; + struct packed_rrset_data* fd, *dd; + struct ub_packed_rrset_key* fk, *dk; + for(i=0; irrset_count; i++) { + fk = from->rrsets[i]; + dk = dest->rrsets[i]; + fd = (struct packed_rrset_data*)fk->entry.data; + dk->entry.hash = fk->entry.hash; + dk->rk = fk->rk; + if(region) { + dk->id = fk->id; + dk->rk.dname = (uint8_t*)regional_alloc_init(region, + fk->rk.dname, fk->rk.dname_len); + } else + dk->rk.dname = (uint8_t*)memdup(fk->rk.dname, + fk->rk.dname_len); + if(!dk->rk.dname) + return 0; + s = packed_rrset_sizeof(fd); + if(region) + dd = (struct packed_rrset_data*)regional_alloc_init( + region, fd, s); + else dd = (struct packed_rrset_data*)memdup(fd, s); + if(!dd) + return 0; + packed_rrset_ptr_fixup(dd); + dk->entry.data = (void*)dd; + } + return 1; +} + +struct reply_info* +reply_info_copy(struct reply_info* rep, struct alloc_cache* alloc, + struct regional* region) +{ + struct reply_info* cp; + cp = construct_reply_info_base(region, rep->flags, rep->qdcount, + rep->ttl, rep->prefetch_ttl, rep->an_numrrsets, + rep->ns_numrrsets, rep->ar_numrrsets, rep->rrset_count, + rep->security); + if(!cp) + return NULL; + /* allocate ub_key structures special or not */ + if(!repinfo_alloc_rrset_keys(cp, alloc, region)) { + if(!region) + reply_info_parsedelete(cp, alloc); + return NULL; + } + if(!repinfo_copy_rrsets(cp, rep, region)) { + if(!region) + reply_info_parsedelete(cp, alloc); + return NULL; + } + return cp; +} + +uint8_t* +reply_find_final_cname_target(struct query_info* qinfo, struct reply_info* rep) +{ + uint8_t* sname = qinfo->qname; + size_t snamelen = qinfo->qname_len; + size_t i; + for(i=0; ian_numrrsets; i++) { + struct ub_packed_rrset_key* s = rep->rrsets[i]; + /* follow CNAME chain (if any) */ + if(ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME && + ntohs(s->rk.rrset_class) == qinfo->qclass && + snamelen == s->rk.dname_len && + query_dname_compare(sname, s->rk.dname) == 0) { + get_cname_target(s, &sname, &snamelen); + } + } + if(sname != qinfo->qname) + return sname; + return NULL; +} + +struct ub_packed_rrset_key* +reply_find_answer_rrset(struct query_info* qinfo, struct reply_info* rep) +{ + uint8_t* sname = qinfo->qname; + size_t snamelen = qinfo->qname_len; + size_t i; + for(i=0; ian_numrrsets; i++) { + struct ub_packed_rrset_key* s = rep->rrsets[i]; + /* first match type, for query of qtype cname */ + if(ntohs(s->rk.type) == qinfo->qtype && + ntohs(s->rk.rrset_class) == qinfo->qclass && + snamelen == s->rk.dname_len && + query_dname_compare(sname, s->rk.dname) == 0) { + return s; + } + /* follow CNAME chain (if any) */ + if(ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME && + ntohs(s->rk.rrset_class) == qinfo->qclass && + snamelen == s->rk.dname_len && + query_dname_compare(sname, s->rk.dname) == 0) { + get_cname_target(s, &sname, &snamelen); + } + } + return NULL; +} + +struct ub_packed_rrset_key* reply_find_rrset_section_an(struct reply_info* rep, + uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass) +{ + size_t i; + for(i=0; ian_numrrsets; i++) { + struct ub_packed_rrset_key* s = rep->rrsets[i]; + if(ntohs(s->rk.type) == type && + ntohs(s->rk.rrset_class) == dclass && + namelen == s->rk.dname_len && + query_dname_compare(name, s->rk.dname) == 0) { + return s; + } + } + return NULL; +} + +struct ub_packed_rrset_key* reply_find_rrset_section_ns(struct reply_info* rep, + uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass) +{ + size_t i; + for(i=rep->an_numrrsets; ian_numrrsets+rep->ns_numrrsets; i++) { + struct ub_packed_rrset_key* s = rep->rrsets[i]; + if(ntohs(s->rk.type) == type && + ntohs(s->rk.rrset_class) == dclass && + namelen == s->rk.dname_len && + query_dname_compare(name, s->rk.dname) == 0) { + return s; + } + } + return NULL; +} + +struct ub_packed_rrset_key* reply_find_rrset(struct reply_info* rep, + uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass) +{ + size_t i; + for(i=0; irrset_count; i++) { + struct ub_packed_rrset_key* s = rep->rrsets[i]; + if(ntohs(s->rk.type) == type && + ntohs(s->rk.rrset_class) == dclass && + namelen == s->rk.dname_len && + query_dname_compare(name, s->rk.dname) == 0) { + return s; + } + } + return NULL; +} + +void +log_dns_msg(const char* str, struct query_info* qinfo, struct reply_info* rep) +{ + /* not particularly fast but flexible, make wireformat and print */ + ldns_buffer* buf = ldns_buffer_new(65535); + struct regional* region = regional_create(); + if(!reply_info_encode(qinfo, rep, 0, rep->flags, buf, 0, + region, 65535, 1)) { + log_info("%s: log_dns_msg: out of memory", str); + } else { + ldns_status s; + ldns_pkt* pkt = NULL; + s = ldns_buffer2pkt_wire(&pkt, buf); + if(s != LDNS_STATUS_OK) { + log_info("%s: log_dns_msg: ldns parse gave: %s", + str, ldns_get_errorstr_by_id(s)); + } else { + ldns_buffer_clear(buf); + s = ldns_pkt2buffer_str(buf, pkt); + if(s != LDNS_STATUS_OK) { + log_info("%s: log_dns_msg: ldns tostr gave: %s", + str, ldns_get_errorstr_by_id(s)); + } else { + log_info("%s %s", + str, (char*)ldns_buffer_begin(buf)); + } + } + ldns_pkt_free(pkt); + } + ldns_buffer_free(buf); + regional_destroy(region); +} + +void +log_query_info(enum verbosity_value v, const char* str, + struct query_info* qinf) +{ + log_nametypeclass(v, str, qinf->qname, qinf->qtype, qinf->qclass); +} + +int +reply_check_cname_chain(struct reply_info* rep) +{ + /* check only answer section rrs for matching cname chain. + * the cache may return changed rdata, but owner names are untouched.*/ + size_t i; + uint8_t* sname = rep->rrsets[0]->rk.dname; + size_t snamelen = rep->rrsets[0]->rk.dname_len; + for(i=0; ian_numrrsets; i++) { + uint16_t t = ntohs(rep->rrsets[i]->rk.type); + if(t == LDNS_RR_TYPE_DNAME) + continue; /* skip dnames; note TTL 0 not cached */ + /* verify that owner matches current sname */ + if(query_dname_compare(sname, rep->rrsets[i]->rk.dname) != 0){ + /* cname chain broken */ + return 0; + } + /* if this is a cname; move on */ + if(t == LDNS_RR_TYPE_CNAME) { + get_cname_target(rep->rrsets[i], &sname, &snamelen); + } + } + return 1; +} + +int +reply_all_rrsets_secure(struct reply_info* rep) +{ + size_t i; + for(i=0; irrset_count; i++) { + if( ((struct packed_rrset_data*)rep->rrsets[i]->entry.data) + ->security != sec_status_secure ) + return 0; + } + return 1; +} diff --git a/util/data/msgreply.h b/util/data/msgreply.h new file mode 100644 index 00000000000..a32f2b1edab --- /dev/null +++ b/util/data/msgreply.h @@ -0,0 +1,417 @@ +/* + * util/data/msgreply.h - store message and reply data. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains a data structure to store a message and its reply. + */ + +#ifndef UTIL_DATA_MSGREPLY_H +#define UTIL_DATA_MSGREPLY_H +#include "util/storage/lruhash.h" +#include "util/data/packed_rrset.h" +struct comm_reply; +struct alloc_cache; +struct iovec; +struct regional; +struct edns_data; +struct msg_parse; +struct rrset_parse; + +/** calculate the prefetch TTL as 90% of original. Calculation + * without numerical overflow (uin32_t) */ +#define PREFETCH_TTL_CALC(ttl) ((ttl) - (ttl)/10) + +/** + * Structure to store query information that makes answers to queries + * different. + */ +struct query_info { + /** + * Salient data on the query: qname, in wireformat. + * can be allocated or a pointer to outside buffer. + * User has to keep track on the status of this. + */ + uint8_t* qname; + /** length of qname (including last 0 octet) */ + size_t qname_len; + /** qtype, host byte order */ + uint16_t qtype; + /** qclass, host byte order */ + uint16_t qclass; +}; + +/** + * Information to reference an rrset + */ +struct rrset_ref { + /** the key with lock, and ptr to packed data. */ + struct ub_packed_rrset_key* key; + /** id needed */ + rrset_id_t id; +}; + +/** + * Structure to store DNS query and the reply packet. + * To use it, copy over the flags from reply and modify using flags from + * the query (RD,CD if not AA). prepend ID. + * + * Memory layout is: + * o struct + * o rrset_ref array + * o packed_rrset_key* array. + * + * Memory layout is sometimes not packed, when the message is synthesized, + * for easy of the generation. It is allocated packed when it is copied + * from the region allocation to the malloc allocation. + */ +struct reply_info { + /** the flags for the answer, host byte order. */ + uint16_t flags; + + /** + * This flag informs unbound the answer is authoritative and + * the AA flag should be preserved. + */ + uint8_t authoritative; + + /** + * Number of RRs in the query section. + * If qdcount is not 0, then it is 1, and the data that appears + * in the reply is the same as the query_info. + * Host byte order. + */ + uint8_t qdcount; + + /** + * TTL of the entire reply (for negative caching). + * only for use when there are 0 RRsets in this message. + * if there are RRsets, check those instead. + */ + uint32_t ttl; + + /** + * TTL for prefetch. After it has expired, a prefetch is suitable. + * Smaller than the TTL, otherwise the prefetch would not happen. + */ + uint32_t prefetch_ttl; + + /** 32 bit padding to pad struct member alignment to 64 bits. */ + uint32_t padding; + + /** + * The security status from DNSSEC validation of this message. + */ + enum sec_status security; + + /** + * Number of RRsets in each section. + * The answer section. Add up the RRs in every RRset to calculate + * the number of RRs, and the count for the dns packet. + * The number of RRs in RRsets can change due to RRset updates. + */ + size_t an_numrrsets; + + /** Count of authority section RRsets */ + size_t ns_numrrsets; + /** Count of additional section RRsets */ + size_t ar_numrrsets; + + /** number of RRsets: an_numrrsets + ns_numrrsets + ar_numrrsets */ + size_t rrset_count; + + /** + * List of pointers (only) to the rrsets in the order in which + * they appear in the reply message. + * Number of elements is ancount+nscount+arcount RRsets. + * This is a pointer to that array. + * Use the accessor function for access. + */ + struct ub_packed_rrset_key** rrsets; + + /** + * Packed array of ids (see counts) and pointers to packed_rrset_key. + * The number equals ancount+nscount+arcount RRsets. + * These are sorted in ascending pointer, the locking order. So + * this list can be locked (and id, ttl checked), to see if + * all the data is available and recent enough. + * + * This is defined as an array of size 1, so that the compiler + * associates the identifier with this position in the structure. + * Array bound overflow on this array then gives access to the further + * elements of the array, which are allocated after the main structure. + * + * It could be more pure to define as array of size 0, ref[0]. + * But ref[1] may be less confusing for compilers. + * Use the accessor function for access. + */ + struct rrset_ref ref[1]; +}; + +/** + * Structure to keep hash table entry for message replies. + */ +struct msgreply_entry { + /** the hash table key */ + struct query_info key; + /** the hash table entry, data is struct reply_info* */ + struct lruhash_entry entry; +}; + +/** + * Parse wire query into a queryinfo structure, return 0 on parse error. + * initialises the (prealloced) queryinfo structure as well. + * This query structure contains a pointer back info the buffer! + * This pointer avoids memory allocation. allocqname does memory allocation. + * @param m: the prealloced queryinfo structure to put query into. + * must be unused, or _clear()ed. + * @param query: the wireformat packet query. starts with ID. + * @return: 0 on format error. + */ +int query_info_parse(struct query_info* m, ldns_buffer* query); + +/** + * Parse query reply. + * Fills in preallocated query_info structure (with ptr into buffer). + * Allocates reply_info and packed_rrsets. These are not yet added to any + * caches or anything, this is only parsing. Returns formerror on qdcount > 1. + * @param pkt: the packet buffer. Must be positioned after the query section. + * @param alloc: creates packed rrset key structures. + * @param rep: allocated reply_info is returned (only on no error). + * @param qinf: query_info is returned (only on no error). + * @param region: where to store temporary data (for parsing). + * @param edns: where to store edns information, does not need to be inited. + * @return: zero is OK, or DNS error code in case of error + * o FORMERR for parse errors. + * o SERVFAIL for memory allocation errors. + */ +int reply_info_parse(ldns_buffer* pkt, struct alloc_cache* alloc, + struct query_info* qinf, struct reply_info** rep, + struct regional* region, struct edns_data* edns); + +/** + * Allocate and decompress parsed message and rrsets. + * @param pkt: for name decompression. + * @param msg: parsed message in scratch region. + * @param alloc: alloc cache for special rrset key structures. + * Not used if region!=NULL, it can be NULL in that case. + * @param qinf: where to store query info. + * qinf itself is allocated by the caller. + * @param rep: reply info is allocated and returned. + * @param region: if this parameter is NULL then malloc and the alloc is used. + * otherwise, everything is allocated in this region. + * In a region, no special rrset key structures are needed (not shared), + * and no rrset_ref array in the reply is built up. + * @return 0 if allocation failed. + */ +int parse_create_msg(ldns_buffer* pkt, struct msg_parse* msg, + struct alloc_cache* alloc, struct query_info* qinf, + struct reply_info** rep, struct regional* region); + +/** + * Sorts the ref array. + * @param rep: reply info. rrsets must be filled in. + */ +void reply_info_sortref(struct reply_info* rep); + +/** + * Set TTLs inside the replyinfo to absolute values. + * @param rep: reply info. rrsets must be filled in. + * Also refs must be filled in. + * @param timenow: the current time. + */ +void reply_info_set_ttls(struct reply_info* rep, uint32_t timenow); + +/** + * Delete reply_info and packed_rrsets (while they are not yet added to the + * hashtables.). Returns rrsets to the alloc cache. + * @param rep: reply_info to delete. + * @param alloc: where to return rrset structures to. + */ +void reply_info_parsedelete(struct reply_info* rep, struct alloc_cache* alloc); + +/** + * Compare two queryinfo structures, on query and type, class. + * It is _not_ sorted in canonical ordering. + * @param m1: struct query_info* , void* here to ease use as function pointer. + * @param m2: struct query_info* , void* here to ease use as function pointer. + * @return: 0 = same, -1 m1 is smaller, +1 m1 is larger. + */ +int query_info_compare(void* m1, void* m2); + +/** clear out query info structure */ +void query_info_clear(struct query_info* m); + +/** calculate size of struct query_info + reply_info */ +size_t msgreply_sizefunc(void* k, void* d); + +/** delete msgreply_entry key structure */ +void query_entry_delete(void *q, void* arg); + +/** delete reply_info data structure */ +void reply_info_delete(void* d, void* arg); + +/** calculate hash value of query_info, lowercases the qname */ +hashvalue_t query_info_hash(struct query_info *q); + +/** + * Setup query info entry + * @param q: query info to copy. Emptied as if clear is called. + * @param r: reply to init data. + * @param h: hash value. + * @return: newly allocated message reply cache item. + */ +struct msgreply_entry* query_info_entrysetup(struct query_info* q, + struct reply_info* r, hashvalue_t h); + +/** + * Copy reply_info and all rrsets in it and allocate. + * @param rep: what to copy, probably inside region, no ref[] array in it. + * @param alloc: how to allocate rrset keys. + * Not used if region!=NULL, it can be NULL in that case. + * @param region: if this parameter is NULL then malloc and the alloc is used. + * otherwise, everything is allocated in this region. + * In a region, no special rrset key structures are needed (not shared), + * and no rrset_ref array in the reply is built up. + * @return new reply info or NULL on memory error. + */ +struct reply_info* reply_info_copy(struct reply_info* rep, + struct alloc_cache* alloc, struct regional* region); + +/** + * Copy a parsed rrset into given key, decompressing and allocating rdata. + * @param pkt: packet for decompression + * @param msg: the parser message (for flags for trust). + * @param pset: the parsed rrset to copy. + * @param region: if NULL - malloc, else data is allocated in this region. + * @param pk: a freshly obtained rrsetkey structure. No dname is set yet, + * will be set on return. + * Note that TTL will still be relative on return. + * @return false on alloc failure. + */ +int parse_copy_decompress_rrset(ldns_buffer* pkt, struct msg_parse* msg, + struct rrset_parse *pset, struct regional* region, + struct ub_packed_rrset_key* pk); + +/** + * Find final cname target in reply, the one matching qinfo. Follows CNAMEs. + * @param qinfo: what to start with. + * @param rep: looks in answer section of this message. + * @return: pointer dname, or NULL if not found. + */ +uint8_t* reply_find_final_cname_target(struct query_info* qinfo, + struct reply_info* rep); + +/** + * Check if cname chain in cached reply is still valid. + * @param rep: reply to check. + * @return: true if valid, false if invalid. + */ +int reply_check_cname_chain(struct reply_info* rep); + +/** + * Check security status of all RRs in the message. + * @param rep: reply to check + * @return: true if all RRs are secure. False if not. + * True if there are zero RRs. + */ +int reply_all_rrsets_secure(struct reply_info* rep); + +/** + * Find answer rrset in reply, the one matching qinfo. Follows CNAMEs, so the + * result may have a different owner name. + * @param qinfo: what to look for. + * @param rep: looks in answer section of this message. + * @return: pointer to rrset, or NULL if not found. + */ +struct ub_packed_rrset_key* reply_find_answer_rrset(struct query_info* qinfo, + struct reply_info* rep); + +/** + * Find rrset in reply, inside the answer section. Does not follow CNAMEs. + * @param rep: looks in answer section of this message. + * @param name: what to look for. + * @param namelen: length of name. + * @param type: looks for (host order). + * @param dclass: looks for (host order). + * @return: pointer to rrset, or NULL if not found. + */ +struct ub_packed_rrset_key* reply_find_rrset_section_an(struct reply_info* rep, + uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass); + +/** + * Find rrset in reply, inside the authority section. Does not follow CNAMEs. + * @param rep: looks in authority section of this message. + * @param name: what to look for. + * @param namelen: length of name. + * @param type: looks for (host order). + * @param dclass: looks for (host order). + * @return: pointer to rrset, or NULL if not found. + */ +struct ub_packed_rrset_key* reply_find_rrset_section_ns(struct reply_info* rep, + uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass); + +/** + * Find rrset in reply, inside any section. Does not follow CNAMEs. + * @param rep: looks in answer,authority and additional section of this message. + * @param name: what to look for. + * @param namelen: length of name. + * @param type: looks for (host order). + * @param dclass: looks for (host order). + * @return: pointer to rrset, or NULL if not found. + */ +struct ub_packed_rrset_key* reply_find_rrset(struct reply_info* rep, + uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass); + +/** + * Debug send the query info and reply info to the log in readable form. + * @param str: descriptive string printed with packet content. + * @param qinfo: query section. + * @param rep: rest of message. + */ +void log_dns_msg(const char* str, struct query_info* qinfo, + struct reply_info* rep); + +/** + * Print string with neat domain name, type, class from query info. + * @param v: at what verbosity level to print this. + * @param str: string of message. + * @param qinf: query info structure with name, type and class. + */ +void log_query_info(enum verbosity_value v, const char* str, + struct query_info* qinf); + +#endif /* UTIL_DATA_MSGREPLY_H */ diff --git a/util/data/packed_rrset.c b/util/data/packed_rrset.c new file mode 100644 index 00000000000..e1fc2e5291e --- /dev/null +++ b/util/data/packed_rrset.c @@ -0,0 +1,488 @@ +/* + * util/data/packed_rrset.c - data storage for a set of resource records. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains the data storage for RRsets. + */ + +#include "config.h" +#include +#include "util/data/packed_rrset.h" +#include "util/data/dname.h" +#include "util/storage/lookup3.h" +#include "util/log.h" +#include "util/alloc.h" +#include "util/regional.h" +#include "util/net_help.h" + +void +ub_packed_rrset_parsedelete(struct ub_packed_rrset_key* pkey, + struct alloc_cache* alloc) +{ + if(!pkey) + return; + if(pkey->entry.data) + free(pkey->entry.data); + pkey->entry.data = NULL; + if(pkey->rk.dname) + free(pkey->rk.dname); + pkey->rk.dname = NULL; + pkey->id = 0; + alloc_special_release(alloc, pkey); +} + +size_t +ub_rrset_sizefunc(void* key, void* data) +{ + struct ub_packed_rrset_key* k = (struct ub_packed_rrset_key*)key; + struct packed_rrset_data* d = (struct packed_rrset_data*)data; + size_t s = sizeof(struct ub_packed_rrset_key) + k->rk.dname_len; + s += packed_rrset_sizeof(d) + lock_get_mem(&k->entry.lock); + return s; +} + +size_t +packed_rrset_sizeof(struct packed_rrset_data* d) +{ + size_t s; + if(d->rrsig_count > 0) { + s = ((uint8_t*)d->rr_data[d->count+d->rrsig_count-1] - + (uint8_t*)d) + d->rr_len[d->count+d->rrsig_count-1]; + } else { + log_assert(d->count > 0); + s = ((uint8_t*)d->rr_data[d->count-1] - (uint8_t*)d) + + d->rr_len[d->count-1]; + } + return s; +} + +int +ub_rrset_compare(void* k1, void* k2) +{ + struct ub_packed_rrset_key* key1 = (struct ub_packed_rrset_key*)k1; + struct ub_packed_rrset_key* key2 = (struct ub_packed_rrset_key*)k2; + int c; + if(key1 == key2) + return 0; + if(key1->rk.type != key2->rk.type) { + if(key1->rk.type < key2->rk.type) + return -1; + return 1; + } + if(key1->rk.dname_len != key2->rk.dname_len) { + if(key1->rk.dname_len < key2->rk.dname_len) + return -1; + return 1; + } + if((c=query_dname_compare(key1->rk.dname, key2->rk.dname)) != 0) + return c; + if(key1->rk.rrset_class != key2->rk.rrset_class) { + if(key1->rk.rrset_class < key2->rk.rrset_class) + return -1; + return 1; + } + if(key1->rk.flags != key2->rk.flags) { + if(key1->rk.flags < key2->rk.flags) + return -1; + return 1; + } + return 0; +} + +void +ub_rrset_key_delete(void* key, void* userdata) +{ + struct ub_packed_rrset_key* k = (struct ub_packed_rrset_key*)key; + struct alloc_cache* a = (struct alloc_cache*)userdata; + k->id = 0; + free(k->rk.dname); + k->rk.dname = NULL; + alloc_special_release(a, k); +} + +void +rrset_data_delete(void* data, void* ATTR_UNUSED(userdata)) +{ + struct packed_rrset_data* d = (struct packed_rrset_data*)data; + free(d); +} + +int +rrsetdata_equal(struct packed_rrset_data* d1, struct packed_rrset_data* d2) +{ + size_t i; + size_t total; + if(d1->count != d2->count || d1->rrsig_count != d2->rrsig_count) + return 0; + total = d1->count + d1->rrsig_count; + for(i=0; irr_len[i] != d2->rr_len[i]) + return 0; + if(memcmp(d1->rr_data[i], d2->rr_data[i], d1->rr_len[i]) != 0) + return 0; + } + return 1; +} + +hashvalue_t +rrset_key_hash(struct packed_rrset_key* key) +{ + /* type is hashed in host order */ + uint16_t t = ntohs(key->type); + /* Note this MUST be identical to pkt_hash_rrset in msgparse.c */ + /* this routine does not have a compressed name */ + hashvalue_t h = 0xab; + h = dname_query_hash(key->dname, h); + h = hashlittle(&t, sizeof(t), h); + h = hashlittle(&key->rrset_class, sizeof(uint16_t), h); + h = hashlittle(&key->flags, sizeof(uint32_t), h); + return h; +} + +void +packed_rrset_ptr_fixup(struct packed_rrset_data* data) +{ + size_t i; + size_t total = data->count + data->rrsig_count; + uint8_t* nextrdata; + /* fixup pointers in packed rrset data */ + data->rr_len = (size_t*)((uint8_t*)data + + sizeof(struct packed_rrset_data)); + data->rr_data = (uint8_t**)&(data->rr_len[total]); + data->rr_ttl = (uint32_t*)&(data->rr_data[total]); + nextrdata = (uint8_t*)&(data->rr_ttl[total]); + for(i=0; irr_data[i] = nextrdata; + nextrdata += data->rr_len[i]; + } +} + +void +get_cname_target(struct ub_packed_rrset_key* rrset, uint8_t** dname, + size_t* dname_len) +{ + struct packed_rrset_data* d; + size_t len; + if(ntohs(rrset->rk.type) != LDNS_RR_TYPE_CNAME && + ntohs(rrset->rk.type) != LDNS_RR_TYPE_DNAME) + return; + d = (struct packed_rrset_data*)rrset->entry.data; + if(d->count < 1) + return; + if(d->rr_len[0] < 3) /* at least rdatalen + 0byte root label */ + return; + len = ldns_read_uint16(d->rr_data[0]); + if(len != d->rr_len[0] - sizeof(uint16_t)) + return; + if(dname_valid(d->rr_data[0]+sizeof(uint16_t), len) != len) + return; + *dname = d->rr_data[0]+sizeof(uint16_t); + *dname_len = len; +} + +void +packed_rrset_ttl_add(struct packed_rrset_data* data, uint32_t add) +{ + size_t i; + size_t total = data->count + data->rrsig_count; + data->ttl += add; + for(i=0; irr_ttl[i] += add; +} + +const char* +rrset_trust_to_string(enum rrset_trust s) +{ + switch(s) { + case rrset_trust_none: return "rrset_trust_none"; + case rrset_trust_add_noAA: return "rrset_trust_add_noAA"; + case rrset_trust_auth_noAA: return "rrset_trust_auth_noAA"; + case rrset_trust_add_AA: return "rrset_trust_add_AA"; + case rrset_trust_nonauth_ans_AA:return "rrset_trust_nonauth_ans_AA"; + case rrset_trust_ans_noAA: return "rrset_trust_ans_noAA"; + case rrset_trust_glue: return "rrset_trust_glue"; + case rrset_trust_auth_AA: return "rrset_trust_auth_AA"; + case rrset_trust_ans_AA: return "rrset_trust_ans_AA"; + case rrset_trust_sec_noglue: return "rrset_trust_sec_noglue"; + case rrset_trust_prim_noglue: return "rrset_trust_prim_noglue"; + case rrset_trust_validated: return "rrset_trust_validated"; + case rrset_trust_ultimate: return "rrset_trust_ultimate"; + } + return "unknown_rrset_trust_value"; +} + +const char* +sec_status_to_string(enum sec_status s) +{ + switch(s) { + case sec_status_unchecked: return "sec_status_unchecked"; + case sec_status_bogus: return "sec_status_bogus"; + case sec_status_indeterminate: return "sec_status_indeterminate"; + case sec_status_insecure: return "sec_status_insecure"; + case sec_status_secure: return "sec_status_secure"; + } + return "unknown_sec_status_value"; +} + +void log_rrset_key(enum verbosity_value v, const char* str, + struct ub_packed_rrset_key* rrset) +{ + if(verbosity >= v) + log_nametypeclass(v, str, rrset->rk.dname, + ntohs(rrset->rk.type), ntohs(rrset->rk.rrset_class)); +} + +uint32_t +ub_packed_rrset_ttl(struct ub_packed_rrset_key* key) +{ + struct packed_rrset_data* d = (struct packed_rrset_data*)key-> + entry.data; + return d->ttl; +} + +struct ub_packed_rrset_key* +packed_rrset_copy_region(struct ub_packed_rrset_key* key, + struct regional* region, uint32_t now) +{ + struct ub_packed_rrset_key* ck = regional_alloc(region, + sizeof(struct ub_packed_rrset_key)); + struct packed_rrset_data* d; + struct packed_rrset_data* data = (struct packed_rrset_data*) + key->entry.data; + size_t dsize, i; + if(!ck) + return NULL; + ck->id = key->id; + memset(&ck->entry, 0, sizeof(ck->entry)); + ck->entry.hash = key->entry.hash; + ck->entry.key = ck; + ck->rk = key->rk; + ck->rk.dname = regional_alloc_init(region, key->rk.dname, + key->rk.dname_len); + if(!ck->rk.dname) + return NULL; + dsize = packed_rrset_sizeof(data); + d = (struct packed_rrset_data*)regional_alloc_init(region, data, dsize); + if(!d) + return NULL; + ck->entry.data = d; + packed_rrset_ptr_fixup(d); + /* make TTLs relative - once per rrset */ + for(i=0; icount + d->rrsig_count; i++) { + if(d->rr_ttl[i] < now) + d->rr_ttl[i] = 0; + else d->rr_ttl[i] -= now; + } + if(d->ttl < now) + d->ttl = 0; + else d->ttl -= now; + return ck; +} + +struct ub_packed_rrset_key* +packed_rrset_copy_alloc(struct ub_packed_rrset_key* key, + struct alloc_cache* alloc, uint32_t now) +{ + struct packed_rrset_data* fd, *dd; + struct ub_packed_rrset_key* dk = alloc_special_obtain(alloc); + if(!dk) return NULL; + fd = (struct packed_rrset_data*)key->entry.data; + dk->entry.hash = key->entry.hash; + dk->rk = key->rk; + dk->rk.dname = (uint8_t*)memdup(key->rk.dname, key->rk.dname_len); + if(!dk->rk.dname) { + alloc_special_release(alloc, dk); + return NULL; + } + dd = (struct packed_rrset_data*)memdup(fd, packed_rrset_sizeof(fd)); + if(!dd) { + free(dk->rk.dname); + alloc_special_release(alloc, dk); + return NULL; + } + packed_rrset_ptr_fixup(dd); + dk->entry.data = (void*)dd; + packed_rrset_ttl_add(dd, now); + return dk; +} + +struct ub_packed_rrset_key* +ub_packed_rrset_heap_key(ldns_rr_list* rrset) +{ + struct ub_packed_rrset_key* k; + ldns_rr* rr; + if(!rrset) + return NULL; + rr = ldns_rr_list_rr(rrset, 0); + if(!rr) + return NULL; + k = (struct ub_packed_rrset_key*)calloc(1, sizeof(*k)); + if(!k) + return NULL; + k->rk.type = htons(ldns_rr_get_type(rr)); + k->rk.rrset_class = htons(ldns_rr_get_class(rr)); + k->rk.dname_len = ldns_rdf_size(ldns_rr_owner(rr)); + k->rk.dname = memdup(ldns_rdf_data(ldns_rr_owner(rr)), + ldns_rdf_size(ldns_rr_owner(rr))); + if(!k->rk.dname) { + free(k); + return NULL; + } + return k; +} + +struct packed_rrset_data* +packed_rrset_heap_data(ldns_rr_list* rrset) +{ + struct packed_rrset_data* data; + size_t count=0, rrsig_count=0, len=0, i, j, total; + uint8_t* nextrdata; + if(!rrset || ldns_rr_list_rr_count(rrset)==0) + return NULL; + /* count sizes */ + for(i=0; ittl = ldns_rr_ttl(ldns_rr_list_rr(rrset, 0)); + data->count = count; + data->rrsig_count = rrsig_count; + data->rr_len = (size_t*)((uint8_t*)data + + sizeof(struct packed_rrset_data)); + data->rr_data = (uint8_t**)&(data->rr_len[total]); + data->rr_ttl = (uint32_t*)&(data->rr_data[total]); + nextrdata = (uint8_t*)&(data->rr_ttl[total]); + + /* fill out len, ttl, fields */ + for(i=0; irr_ttl[i] = ldns_rr_ttl(rr); + if(data->rr_ttl[i] < data->ttl) + data->ttl = data->rr_ttl[i]; + data->rr_len[i] = 2; /* the rdlength */ + for(j=0; jrr_len[i] += ldns_rdf_size(ldns_rr_rdf(rr, j)); + } + + /* fixup rest of ptrs */ + for(i=0; irr_data[i] = nextrdata; + nextrdata += data->rr_len[i]; + } + + /* copy data in there */ + for(i=0; irr_len[i]-2); + size_t p = sizeof(rdlen); + memmove(data->rr_data[i], &rdlen, p); + for(j=0; jrr_data[i]+p, ldns_rdf_data(rd), + ldns_rdf_size(rd)); + p += ldns_rdf_size(rd); + } + } + + if(data->rrsig_count && data->count == 0) { + data->count = data->rrsig_count; /* rrset type is RRSIG */ + data->rrsig_count = 0; + } + return data; +} + +/** convert i'th rr to ldns_rr */ +static ldns_rr* +torr(struct ub_packed_rrset_key* k, ldns_buffer* buf, size_t i) +{ + struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data; + ldns_rr* rr = NULL; + size_t pos = 0; + ldns_status s; + ldns_buffer_clear(buf); + ldns_buffer_write(buf, k->rk.dname, k->rk.dname_len); + if(i < d->count) + ldns_buffer_write(buf, &k->rk.type, sizeof(uint16_t)); + else ldns_buffer_write_u16(buf, LDNS_RR_TYPE_RRSIG); + ldns_buffer_write(buf, &k->rk.rrset_class, sizeof(uint16_t)); + ldns_buffer_write_u32(buf, d->rr_ttl[i]); + ldns_buffer_write(buf, d->rr_data[i], d->rr_len[i]); + ldns_buffer_flip(buf); + s = ldns_wire2rr(&rr, ldns_buffer_begin(buf), ldns_buffer_limit(buf), + &pos, LDNS_SECTION_ANSWER); + if(s == LDNS_STATUS_OK) + return rr; + return NULL; +} + +ldns_rr_list* +packed_rrset_to_rr_list(struct ub_packed_rrset_key* k, ldns_buffer* buf) +{ + struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data; + ldns_rr_list* r = ldns_rr_list_new(); + size_t i; + if(!r) + return NULL; + for(i=0; icount+d->rrsig_count; i++) { + ldns_rr* rr = torr(k, buf, i); + if(!rr) { + ldns_rr_list_deep_free(r); + return NULL; + } + if(!ldns_rr_list_push_rr(r, rr)) { + ldns_rr_free(rr); + ldns_rr_list_deep_free(r); + return NULL; + } + } + return r; +} diff --git a/util/data/packed_rrset.h b/util/data/packed_rrset.h new file mode 100644 index 00000000000..ad11a804226 --- /dev/null +++ b/util/data/packed_rrset.h @@ -0,0 +1,434 @@ +/* + * util/data/packed_rrset.h - data storage for a set of resource records. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains the data storage for RRsets. + */ + +#ifndef UTIL_DATA_PACKED_RRSET_H +#define UTIL_DATA_PACKED_RRSET_H +#include "util/storage/lruhash.h" +#include +struct alloc_cache; +struct regional; + +/** type used to uniquely identify rrsets. Cannot be reused without + * clearing the cache. */ +typedef uint64_t rrset_id_t; + +/** this rrset is NSEC and is at zone apex (at child side of zonecut) */ +#define PACKED_RRSET_NSEC_AT_APEX 0x1 +/** this rrset is A/AAAA and is in-zone-glue (from parent side of zonecut) */ +#define PACKED_RRSET_PARENT_SIDE 0x2 +/** this rrset is SOA and has the negative ttl (from nxdomain or nodata), + * this is set on SOA rrsets in the authority section, to keep its TTL separate + * from the SOA in the answer section from a direct SOA query or ANY query. */ +#define PACKED_RRSET_SOA_NEG 0x4 + +/** + * The identifying information for an RRset. + */ +struct packed_rrset_key { + /** + * The domain name. If not null (for id=0) it is allocated, and + * contains the wireformat domain name. + * This dname is not canonicalized. + */ + uint8_t* dname; + /** + * Length of the domain name, including last 0 root octet. + */ + size_t dname_len; + /** + * Flags. 32bit to be easy for hashing: + * o PACKED_RRSET_NSEC_AT_APEX + * o PACKED_RRSET_PARENT_SIDE + * o PACKED_RRSET_SOA_NEG + */ + uint32_t flags; + /** the rrset type in network format */ + uint16_t type; + /** the rrset class in network format */ + uint16_t rrset_class; +}; + +/** + * This structure contains an RRset. A set of resource records that + * share the same domain name, type and class. + * + * Due to memory management and threading, the key structure cannot be + * deleted, although the data can be. The id can be set to 0 to store and the + * structure can be recycled with a new id. + */ +struct ub_packed_rrset_key { + /** + * entry into hashtable. Note the lock is never destroyed, + * even when this key is retired to the cache. + * the data pointer (if not null) points to a struct packed_rrset. + */ + struct lruhash_entry entry; + /** + * the ID of this rrset. unique, based on threadid + sequenceno. + * ids are not reused, except after flushing the cache. + * zero is an unused entry, and never a valid id. + * Check this value after getting entry.lock. + * The other values in this struct may only be altered after changing + * the id (which needs a writelock on entry.lock). + */ + rrset_id_t id; + /** key data: dname, type and class */ + struct packed_rrset_key rk; +}; + +/** + * RRset trustworthiness. Bigger value is more trust. RFC 2181. + * The rrset_trust_add_noAA, rrset_trust_auth_noAA, rrset_trust_add_AA, + * are mentioned as the same trustworthiness in 2181, but split up here + * for ease of processing. + * + * rrset_trust_nonauth_ans_AA, rrset_trust_ans_noAA + * are also mentioned as the same trustworthiness in 2181, but split up here + * for ease of processing. + * + * Added trust_none for a sane initial value, smaller than anything else. + * Added validated and ultimate trust for keys and rrsig validated content. + */ +enum rrset_trust { + /** initial value for trust */ + rrset_trust_none = 0, + /** Additional information from non-authoritative answers */ + rrset_trust_add_noAA, + /** Data from the authority section of a non-authoritative answer */ + rrset_trust_auth_noAA, + /** Additional information from an authoritative answer */ + rrset_trust_add_AA, + /** non-authoritative data from the answer section of authoritative + * answers */ + rrset_trust_nonauth_ans_AA, + /** Data from the answer section of a non-authoritative answer */ + rrset_trust_ans_noAA, + /** Glue from a primary zone, or glue from a zone transfer */ + rrset_trust_glue, + /** Data from the authority section of an authoritative answer */ + rrset_trust_auth_AA, + /** The authoritative data included in the answer section of an + * authoritative reply */ + rrset_trust_ans_AA, + /** Data from a zone transfer, other than glue */ + rrset_trust_sec_noglue, + /** Data from a primary zone file, other than glue data */ + rrset_trust_prim_noglue, + /** DNSSEC(rfc4034) validated with trusted keys */ + rrset_trust_validated, + /** ultimately trusted, no more trust is possible; + * trusted keys from the unbound configuration setup. */ + rrset_trust_ultimate +}; + +/** + * Security status from validation for data. + * The order is significant; more secure, more proven later. + */ +enum sec_status { + /** UNCHECKED means that object has yet to be validated. */ + sec_status_unchecked = 0, + /** BOGUS means that the object (RRset or message) failed to validate + * (according to local policy), but should have validated. */ + sec_status_bogus, + /** INDETERMINATE means that the object is insecure, but not + * authoritatively so. Generally this means that the RRset is not + * below a configured trust anchor. */ + sec_status_indeterminate, + /** INSECURE means that the object is authoritatively known to be + * insecure. Generally this means that this RRset is below a trust + * anchor, but also below a verified, insecure delegation. */ + sec_status_insecure, + /** SECURE means that the object (RRset or message) validated + * according to local policy. */ + sec_status_secure +}; + +/** + * RRset data. + * + * The data is packed, stored contiguously in memory. + * memory layout: + * o base struct + * o rr_len size_t array + * o rr_data uint8_t* array + * o rr_ttl uint32_t array (after size_t and ptrs because those may be + * 64bit and this array before those would make them unaligned). + * Since the stuff before is 32/64bit, rr_ttl is 32 bit aligned. + * o rr_data rdata wireformats + * o rrsig_data rdata wireformat(s) + * + * Rdata is stored in wireformat. The dname is stored in wireformat. + * TTLs are stored as absolute values (and could be expired). + * + * RRSIGs are stored in the arrays after the regular rrs. + * + * You need the packed_rrset_key to know dname, type, class of the + * resource records in this RRset. (if signed the rrsig gives the type too). + * + * On the wire an RR is: + * name, type, class, ttl, rdlength, rdata. + * So we need to send the following per RR: + * key.dname, ttl, rr_data[i]. + * since key.dname ends with type and class. + * and rr_data starts with the rdlength. + * the ttl value to send changes due to time. + */ +struct packed_rrset_data { + /** TTL (in seconds like time()) of the rrset. + * Same for all RRs see rfc2181(5.2). */ + uint32_t ttl; + /** number of rrs. */ + size_t count; + /** number of rrsigs, if 0 no rrsigs */ + size_t rrsig_count; + /** the trustworthiness of the rrset data */ + enum rrset_trust trust; + /** security status of the rrset data */ + enum sec_status security; + /** length of every rr's rdata, rr_len[i] is size of rr_data[i]. */ + size_t* rr_len; + /** ttl of every rr. rr_ttl[i] ttl of rr i. */ + uint32_t *rr_ttl; + /** + * Array of pointers to every rr's rdata. + * The rr_data[i] rdata is stored in uncompressed wireformat. + * The first uint16_t of rr_data[i] is network format rdlength. + * + * rr_data[count] to rr_data[count+rrsig_count] contain the rrsig data. + */ + uint8_t** rr_data; +}; + +/** + * An RRset can be represented using both key and data together. + * Split into key and data structures to simplify implementation of + * caching schemes. + */ +struct packed_rrset { + /** domain name, type and class */ + struct packed_rrset_key* k; + /** ttl, count and rdatas (and rrsig) */ + struct packed_rrset_data* d; +}; + +/** + * list of packed rrsets + */ +struct packed_rrset_list { + /** next in list */ + struct packed_rrset_list* next; + /** rrset key and data */ + struct packed_rrset rrset; +}; + +/** + * Delete packed rrset key and data, not entered in hashtables yet. + * Used during parsing. + * @param pkey: rrset key structure with locks, key and data pointers. + * @param alloc: where to return the unfree-able key structure. + */ +void ub_packed_rrset_parsedelete(struct ub_packed_rrset_key* pkey, + struct alloc_cache* alloc); + +/** + * Memory size of rrset data. RRset data must be filled in correctly. + * @param data: data to examine. + * @return size in bytes. + */ +size_t packed_rrset_sizeof(struct packed_rrset_data* data); + +/** + * Get TTL of rrset. RRset data must be filled in correctly. + * @param key: rrset key, with data to examine. + * @return ttl value. + */ +uint32_t ub_packed_rrset_ttl(struct ub_packed_rrset_key* key); + +/** + * Calculate memory size of rrset entry. For hash table usage. + * @param key: struct ub_packed_rrset_key*. + * @param data: struct packed_rrset_data*. + * @return size in bytes. + */ +size_t ub_rrset_sizefunc(void* key, void* data); + +/** + * compares two rrset keys. + * @param k1: struct ub_packed_rrset_key*. + * @param k2: struct ub_packed_rrset_key*. + * @return 0 if equal. + */ +int ub_rrset_compare(void* k1, void* k2); + +/** + * compare two rrset data structures. + * Compared rdata and rrsigdata, not the trust or ttl value. + * @param d1: data to compare. + * @param d2: data to compare. + * @return 1 if equal. + */ +int rrsetdata_equal(struct packed_rrset_data* d1, struct packed_rrset_data* d2); + +/** + * Old key to be deleted. RRset keys are recycled via alloc. + * The id is set to 0. So that other threads, after acquiring a lock always + * get the correct value, in this case the 0 deleted-special value. + * @param key: struct ub_packed_rrset_key*. + * @param userdata: alloc structure to use for recycling. + */ +void ub_rrset_key_delete(void* key, void* userdata); + +/** + * Old data to be deleted. + * @param data: what to delete. + * @param userdata: user data ptr. + */ +void rrset_data_delete(void* data, void* userdata); + +/** + * Calculate hash value for a packed rrset key. + * @param key: the rrset key with name, type, class, flags. + * @return hash value. + */ +hashvalue_t rrset_key_hash(struct packed_rrset_key* key); + +/** + * Fixup pointers in fixed data packed_rrset_data blob. + * After a memcpy of the data for example. Will set internal pointers right. + * @param data: rrset data structure. Otherwise correctly filled in. + */ +void packed_rrset_ptr_fixup(struct packed_rrset_data* data); + +/** + * Fixup TTLs in fixed data packed_rrset_data blob. + * @param data: rrset data structure. Otherwise correctly filled in. + * @param add: how many seconds to add, pass time(0) for example. + */ +void packed_rrset_ttl_add(struct packed_rrset_data* data, uint32_t add); + +/** + * Utility procedure to extract CNAME target name from its rdata. + * Failsafes; it will change passed dname to a valid dname or do nothing. + * @param rrset: the rrset structure. Must be a CNAME. + * Only first RR is used (multiple RRs are technically illegal anyway). + * Also works on type DNAME. Returns target name. + * @param dname: this pointer is updated to point into the cname rdata. + * If a failsafe fails, nothing happens to the pointer (such as the + * rdata was not a valid dname, not a CNAME, ...). + * @param dname_len: length of dname is returned. + */ +void get_cname_target(struct ub_packed_rrset_key* rrset, uint8_t** dname, + size_t* dname_len); + +/** + * Get a printable string for a rrset trust value + * @param s: rrset trust value + * @return printable string. + */ +const char* rrset_trust_to_string(enum rrset_trust s); + +/** + * Get a printable string for a security status value + * @param s: security status + * @return printable string. + */ +const char* sec_status_to_string(enum sec_status s); + +/** + * Print string with neat domain name, type, class from rrset. + * @param v: at what verbosity level to print this. + * @param str: string of message. + * @param rrset: structure with name, type and class. + */ +void log_rrset_key(enum verbosity_value v, const char* str, + struct ub_packed_rrset_key* rrset); + +/** + * Allocate rrset in region - no more locks needed + * @param key: a (just from rrset cache looked up) rrset key + valid, + * packed data record. + * @param region: where to alloc the copy + * @param now: adjust the TTLs to be relative (subtract from all TTLs). + * @return new region-alloced rrset key or NULL on alloc failure. + */ +struct ub_packed_rrset_key* packed_rrset_copy_region( + struct ub_packed_rrset_key* key, struct regional* region, + uint32_t now); + +/** + * Allocate rrset with malloc (from region or you are holding the lock). + * @param key: key with data entry. + * @param alloc: alloc_cache to create rrset_keys + * @param now: adjust the TTLs to be absolute (add to all TTLs). + * @return new region-alloced rrset key or NULL on alloc failure. + */ +struct ub_packed_rrset_key* packed_rrset_copy_alloc( + struct ub_packed_rrset_key* key, struct alloc_cache* alloc, + uint32_t now); + +/** + * Create a ub_packed_rrset_key allocated on the heap. + * It therefore does not have the correct ID value, and cannot be used + * inside the cache. It can be used in storage outside of the cache. + * Keys for the cache have to be obtained from alloc.h . + * @param rrset: the ldns rr set. + * @return key allocated or NULL on failure. + */ +struct ub_packed_rrset_key* ub_packed_rrset_heap_key(ldns_rr_list* rrset); + +/** + * Create packed_rrset data on the heap. + * @param rrset: the ldns rr set with the data to copy. + * @return data allocated or NULL on failure. + */ +struct packed_rrset_data* packed_rrset_heap_data(ldns_rr_list* rrset); + +/** + * Convert packed rrset to ldns rr list. + * @param rrset: packed rrset. + * @param buf: scratch buffer. + * @return rr list or NULL on failure. + */ +ldns_rr_list* packed_rrset_to_rr_list(struct ub_packed_rrset_key* rrset, + ldns_buffer* buf); + +#endif /* UTIL_DATA_PACKED_RRSET_H */ diff --git a/util/fptr_wlist.c b/util/fptr_wlist.c new file mode 100644 index 00000000000..6bb95a5318b --- /dev/null +++ b/util/fptr_wlist.c @@ -0,0 +1,401 @@ +/* + * util/fptr_wlist.c - function pointer whitelists. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions that check function pointers. + * The functions contain a whitelist of known good callback values. + * Any other values lead to an error. + * + * Due to the listing nature, this file violates all the modularization + * boundaries in the program. + */ +#include "config.h" +#include "util/fptr_wlist.h" +#include "util/mini_event.h" +#include "daemon/worker.h" +#include "daemon/remote.h" +#include "services/outside_network.h" +#include "services/mesh.h" +#include "services/localzone.h" +#include "services/cache/infra.h" +#include "services/cache/rrset.h" +#include "iterator/iterator.h" +#include "iterator/iter_fwd.h" +#include "validator/validator.h" +#include "validator/val_anchor.h" +#include "validator/val_nsec3.h" +#include "validator/val_sigcrypt.h" +#include "validator/val_kentry.h" +#include "validator/val_neg.h" +#include "validator/autotrust.h" +#include "util/data/msgreply.h" +#include "util/data/packed_rrset.h" +#include "util/storage/slabhash.h" +#include "util/storage/dnstree.h" +#include "util/locks.h" +#include "libunbound/libworker.h" +#include "libunbound/context.h" +#include "util/tube.h" +#include "util/config_file.h" +#ifdef UB_ON_WINDOWS +#include "winrc/win_svc.h" +#endif + +#ifdef WITH_PYTHONMODULE +#include "pythonmod/pythonmod.h" +#endif + +int +fptr_whitelist_comm_point(comm_point_callback_t *fptr) +{ + if(fptr == &worker_handle_request) return 1; + else if(fptr == &outnet_udp_cb) return 1; + else if(fptr == &outnet_tcp_cb) return 1; + else if(fptr == &tube_handle_listen) return 1; + return 0; +} + +int +fptr_whitelist_comm_point_raw(comm_point_callback_t *fptr) +{ + if(fptr == &tube_handle_listen) return 1; + else if(fptr == &tube_handle_write) return 1; + else if(fptr == &remote_accept_callback) return 1; + else if(fptr == &remote_control_callback) return 1; + return 0; +} + +int +fptr_whitelist_comm_timer(void (*fptr)(void*)) +{ + if(fptr == &pending_udp_timer_cb) return 1; + else if(fptr == &outnet_tcptimer) return 1; + else if(fptr == &worker_stat_timer_cb) return 1; + else if(fptr == &worker_probe_timer_cb) return 1; +#ifdef UB_ON_WINDOWS + else if(fptr == &wsvc_cron_cb) return 1; +#endif + return 0; +} + +int +fptr_whitelist_comm_signal(void (*fptr)(int, void*)) +{ + if(fptr == &worker_sighandler) return 1; + return 0; +} + +int fptr_whitelist_start_accept(void (*fptr)(void*)) +{ + if(fptr == &worker_start_accept) return 1; + return 0; +} + +int fptr_whitelist_stop_accept(void (*fptr)(void*)) +{ + if(fptr == &worker_stop_accept) return 1; + return 0; +} + +int +fptr_whitelist_event(void (*fptr)(int, short, void *)) +{ + if(fptr == &comm_point_udp_callback) return 1; + else if(fptr == &comm_point_udp_ancil_callback) return 1; + else if(fptr == &comm_point_tcp_accept_callback) return 1; + else if(fptr == &comm_point_tcp_handle_callback) return 1; + else if(fptr == &comm_timer_callback) return 1; + else if(fptr == &comm_signal_callback) return 1; + else if(fptr == &comm_point_local_handle_callback) return 1; + else if(fptr == &comm_point_raw_handle_callback) return 1; + else if(fptr == &tube_handle_signal) return 1; + else if(fptr == &comm_base_handle_slow_accept) return 1; +#ifdef UB_ON_WINDOWS + else if(fptr == &worker_win_stop_cb) return 1; +#endif + return 0; +} + +int +fptr_whitelist_pending_udp(comm_point_callback_t *fptr) +{ + if(fptr == &serviced_udp_callback) return 1; + else if(fptr == &worker_handle_reply) return 1; + else if(fptr == &libworker_handle_reply) return 1; + return 0; +} + +int +fptr_whitelist_pending_tcp(comm_point_callback_t *fptr) +{ + if(fptr == &serviced_tcp_callback) return 1; + else if(fptr == &worker_handle_reply) return 1; + else if(fptr == &libworker_handle_reply) return 1; + return 0; +} + +int +fptr_whitelist_serviced_query(comm_point_callback_t *fptr) +{ + if(fptr == &worker_handle_service_reply) return 1; + else if(fptr == &libworker_handle_service_reply) return 1; + return 0; +} + +int +fptr_whitelist_rbtree_cmp(int (*fptr) (const void *, const void *)) +{ + if(fptr == &mesh_state_compare) return 1; + else if(fptr == &mesh_state_ref_compare) return 1; + else if(fptr == &addr_tree_compare) return 1; + else if(fptr == &local_zone_cmp) return 1; + else if(fptr == &local_data_cmp) return 1; + else if(fptr == &fwd_cmp) return 1; + else if(fptr == &pending_cmp) return 1; + else if(fptr == &serviced_cmp) return 1; + else if(fptr == &name_tree_compare) return 1; + else if(fptr == &order_lock_cmp) return 1; + else if(fptr == &codeline_cmp) return 1; + else if(fptr == &nsec3_hash_cmp) return 1; + else if(fptr == &mini_ev_cmp) return 1; + else if(fptr == &anchor_cmp) return 1; + else if(fptr == &canonical_tree_compare) return 1; + else if(fptr == &context_query_cmp) return 1; + else if(fptr == &val_neg_data_compare) return 1; + else if(fptr == &val_neg_zone_compare) return 1; + else if(fptr == &probetree_cmp) return 1; + else if(fptr == &replay_var_compare) return 1; + return 0; +} + +int +fptr_whitelist_hash_sizefunc(lruhash_sizefunc_t fptr) +{ + if(fptr == &msgreply_sizefunc) return 1; + else if(fptr == &ub_rrset_sizefunc) return 1; + else if(fptr == &infra_sizefunc) return 1; + else if(fptr == &key_entry_sizefunc) return 1; + else if(fptr == &test_slabhash_sizefunc) return 1; + return 0; +} + +int +fptr_whitelist_hash_compfunc(lruhash_compfunc_t fptr) +{ + if(fptr == &query_info_compare) return 1; + else if(fptr == &ub_rrset_compare) return 1; + else if(fptr == &infra_compfunc) return 1; + else if(fptr == &key_entry_compfunc) return 1; + else if(fptr == &test_slabhash_compfunc) return 1; + return 0; +} + +int +fptr_whitelist_hash_delkeyfunc(lruhash_delkeyfunc_t fptr) +{ + if(fptr == &query_entry_delete) return 1; + else if(fptr == &ub_rrset_key_delete) return 1; + else if(fptr == &infra_delkeyfunc) return 1; + else if(fptr == &key_entry_delkeyfunc) return 1; + else if(fptr == &test_slabhash_delkey) return 1; + return 0; +} + +int +fptr_whitelist_hash_deldatafunc(lruhash_deldatafunc_t fptr) +{ + if(fptr == &reply_info_delete) return 1; + else if(fptr == &rrset_data_delete) return 1; + else if(fptr == &infra_deldatafunc) return 1; + else if(fptr == &key_entry_deldatafunc) return 1; + else if(fptr == &test_slabhash_deldata) return 1; + return 0; +} + +int +fptr_whitelist_hash_markdelfunc(lruhash_markdelfunc_t fptr) +{ + if(fptr == NULL) return 1; + else if(fptr == &rrset_markdel) return 1; + return 0; +} + +/** whitelist env->send_query callbacks */ +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, + struct sockaddr_storage* addr, socklen_t addrlen, + uint8_t* zone, size_t zonelen, + struct module_qstate* q)) +{ + if(fptr == &worker_send_query) return 1; + else if(fptr == &libworker_send_query) return 1; + return 0; +} + +int +fptr_whitelist_modenv_detach_subs(void (*fptr)( + struct module_qstate* qstate)) +{ + if(fptr == &mesh_detach_subs) return 1; + return 0; +} + +int +fptr_whitelist_modenv_attach_sub(int (*fptr)( + struct module_qstate* qstate, struct query_info* qinfo, + uint16_t qflags, int prime, struct module_qstate** newq)) +{ + if(fptr == &mesh_attach_sub) return 1; + return 0; +} + +int +fptr_whitelist_modenv_kill_sub(void (*fptr)(struct module_qstate* newq)) +{ + if(fptr == &mesh_state_delete) return 1; + return 0; +} + +int +fptr_whitelist_modenv_detect_cycle(int (*fptr)( + struct module_qstate* qstate, struct query_info* qinfo, + uint16_t flags, int prime)) +{ + if(fptr == &mesh_detect_cycle) return 1; + return 0; +} + +int +fptr_whitelist_mod_init(int (*fptr)(struct module_env* env, int id)) +{ + if(fptr == &iter_init) return 1; + else if(fptr == &val_init) return 1; +#ifdef WITH_PYTHONMODULE + else if(fptr == &pythonmod_init) return 1; +#endif + return 0; +} + +int +fptr_whitelist_mod_deinit(void (*fptr)(struct module_env* env, int id)) +{ + if(fptr == &iter_deinit) return 1; + else if(fptr == &val_deinit) return 1; +#ifdef WITH_PYTHONMODULE + else if(fptr == &pythonmod_deinit) return 1; +#endif + return 0; +} + +int +fptr_whitelist_mod_operate(void (*fptr)(struct module_qstate* qstate, + enum module_ev event, int id, struct outbound_entry* outbound)) +{ + if(fptr == &iter_operate) return 1; + else if(fptr == &val_operate) return 1; +#ifdef WITH_PYTHONMODULE + else if(fptr == &pythonmod_operate) return 1; +#endif + return 0; +} + +int +fptr_whitelist_mod_inform_super(void (*fptr)( + struct module_qstate* qstate, int id, struct module_qstate* super)) +{ + if(fptr == &iter_inform_super) return 1; + else if(fptr == &val_inform_super) return 1; +#ifdef WITH_PYTHONMODULE + else if(fptr == &pythonmod_inform_super) return 1; +#endif + return 0; +} + +int +fptr_whitelist_mod_clear(void (*fptr)(struct module_qstate* qstate, + int id)) +{ + if(fptr == &iter_clear) return 1; + else if(fptr == &val_clear) return 1; +#ifdef WITH_PYTHONMODULE + else if(fptr == &pythonmod_clear) return 1; +#endif + return 0; +} + +int +fptr_whitelist_mod_get_mem(size_t (*fptr)(struct module_env* env, int id)) +{ + if(fptr == &iter_get_mem) return 1; + else if(fptr == &val_get_mem) return 1; +#ifdef WITH_PYTHONMODULE + else if(fptr == &pythonmod_get_mem) return 1; +#endif + return 0; +} + +int +fptr_whitelist_alloc_cleanup(void (*fptr)(void*)) +{ + if(fptr == &worker_alloc_cleanup) return 1; + return 0; +} + +int fptr_whitelist_tube_listen(tube_callback_t* fptr) +{ + if(fptr == &worker_handle_control_cmd) return 1; + else if(fptr == &libworker_handle_control_cmd) return 1; + return 0; +} + +int fptr_whitelist_mesh_cb(mesh_cb_func_t fptr) +{ + if(fptr == &libworker_fg_done_cb) return 1; + else if(fptr == &libworker_bg_done_cb) return 1; + else if(fptr == &probe_answer_cb) return 1; + return 0; +} + +int fptr_whitelist_print_func(void (*fptr)(char*,void*)) +{ + if(fptr == &config_print_func) return 1; + else if(fptr == &config_collate_func) return 1; + else if(fptr == &remote_get_opt_ssl) return 1; + return 0; +} diff --git a/util/fptr_wlist.h b/util/fptr_wlist.h new file mode 100644 index 00000000000..d204e923884 --- /dev/null +++ b/util/fptr_wlist.h @@ -0,0 +1,359 @@ +/* + * util/fptr_wlist.h - function pointer whitelists. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions that check function pointers. + * The functions contain a whitelist of known good callback values. + * Any other values lead to an error. + * + * This prevent heap overflow based exploits, where the callback pointer + * is overwritten by a buffer overflow (apart from this defense, buffer + * overflows should be fixed of course). + * + * Function pointers are used in + * o network code callbacks. + * o rbtree, lruhash, region data manipulation + * in lruhash, the assertions are before the critical regions. + * in other places, assertions are before the callback. + * o module operations. + */ + +#ifndef UTIL_FPTR_WLIST_H +#define UTIL_FPTR_WLIST_H +#include "util/netevent.h" +#include "util/storage/lruhash.h" +#include "util/module.h" +#include "util/tube.h" +#include "services/mesh.h" + +/** + * Macro to perform an assertion check for fptr wlist checks. + * Does not get disabled in optimize mode. Check adds security by layers. + */ +#if defined(EXPORT_ALL_SYMBOLS) +#define fptr_ok(x) /* nothing, dll-exe memory layout on win disables it */ +#else +#define fptr_ok(x) \ + do { if(!(x)) \ + fatal_exit("%s:%d: %s: pointer whitelist %s failed", \ + __FILE__, __LINE__, __func__, #x); \ + } while(0); +#endif + +/** + * Check function pointer whitelist for comm_point callback values. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_comm_point(comm_point_callback_t *fptr); + +/** + * Check function pointer whitelist for raw comm_point callback values. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_comm_point_raw(comm_point_callback_t *fptr); + +/** + * Check function pointer whitelist for comm_timer callback values. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_comm_timer(void (*fptr)(void*)); + +/** + * Check function pointer whitelist for comm_signal callback values. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_comm_signal(void (*fptr)(int, void*)); + +/** + * Check function pointer whitelist for start_accept callback values. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_start_accept(void (*fptr)(void*)); + +/** + * Check function pointer whitelist for stop_accept callback values. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_stop_accept(void (*fptr)(void*)); + +/** + * Check function pointer whitelist for event structure callback values. + * This is not called by libevent itself, but checked by netevent. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_event(void (*fptr)(int, short, void *)); + +/** + * Check function pointer whitelist for pending udp callback values. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_pending_udp(comm_point_callback_t *fptr); + +/** + * Check function pointer whitelist for pending tcp callback values. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_pending_tcp(comm_point_callback_t *fptr); + +/** + * Check function pointer whitelist for serviced query callback values. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_serviced_query(comm_point_callback_t *fptr); + +/** + * Check function pointer whitelist for rbtree cmp callback values. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_rbtree_cmp(int (*fptr) (const void *, const void *)); + +/** + * Check function pointer whitelist for lruhash sizefunc callback values. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_hash_sizefunc(lruhash_sizefunc_t fptr); + +/** + * Check function pointer whitelist for lruhash compfunc callback values. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_hash_compfunc(lruhash_compfunc_t fptr); + +/** + * Check function pointer whitelist for lruhash delkeyfunc callback values. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_hash_delkeyfunc(lruhash_delkeyfunc_t fptr); + +/** + * Check function pointer whitelist for lruhash deldata callback values. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_hash_deldatafunc(lruhash_deldatafunc_t fptr); + +/** + * Check function pointer whitelist for lruhash markdel callback values. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_hash_markdelfunc(lruhash_markdelfunc_t fptr); + +/** + * Check function pointer whitelist for module_env send_query callback values. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +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, + struct sockaddr_storage* addr, socklen_t addrlen, + uint8_t* zone, size_t zonelen, + struct module_qstate* q)); + +/** + * Check function pointer whitelist for module_env detach_subs callback values. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_modenv_detach_subs(void (*fptr)( + struct module_qstate* qstate)); + +/** + * Check function pointer whitelist for module_env attach_sub callback values. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_modenv_attach_sub(int (*fptr)( + struct module_qstate* qstate, struct query_info* qinfo, + uint16_t qflags, int prime, struct module_qstate** newq)); + +/** + * Check function pointer whitelist for module_env kill_sub callback values. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_modenv_kill_sub(void (*fptr)(struct module_qstate* newq)); + +/** + * Check function pointer whitelist for module_env detect_cycle callback values. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_modenv_detect_cycle(int (*fptr)( + struct module_qstate* qstate, struct query_info* qinfo, + uint16_t flags, int prime)); + +/** + * Check function pointer whitelist for module init call values. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_mod_init(int (*fptr)(struct module_env* env, int id)); + +/** + * Check function pointer whitelist for module deinit call values. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_mod_deinit(void (*fptr)(struct module_env* env, int id)); + +/** + * Check function pointer whitelist for module operate call values. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_mod_operate(void (*fptr)(struct module_qstate* qstate, + enum module_ev event, int id, struct outbound_entry* outbound)); + +/** + * Check function pointer whitelist for module inform_super call values. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_mod_inform_super(void (*fptr)( + struct module_qstate* qstate, int id, struct module_qstate* super)); + +/** + * Check function pointer whitelist for module clear call values. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_mod_clear(void (*fptr)(struct module_qstate* qstate, + int id)); + +/** + * Check function pointer whitelist for module get_mem call values. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_mod_get_mem(size_t (*fptr)(struct module_env* env, int id)); + +/** + * Check function pointer whitelist for alloc clear on id overflow call values. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_alloc_cleanup(void (*fptr)(void*)); + +/** + * Check function pointer whitelist for tube listen handler values. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_tube_listen(tube_callback_t* fptr); + +/** + * Check function pointer whitelist for mesh state callback values. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_mesh_cb(mesh_cb_func_t fptr); + +/** + * Check function pointer whitelist for config_get_option func values. + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_print_func(void (*fptr)(char*,void*)); + +/** Due to module breakage by fptr wlist, these test app declarations + * are presented here */ +/** + * compare two order_ids from lock-verify test app + * @param e1: first order_id + * @param e2: second order_id + * @return compare code -1, 0, +1 (like memcmp). + */ +int order_lock_cmp(const void* e1, const void* e2); + +/** + * compare two codeline structs for rbtree from memstats test app + * @param a: codeline + * @param b: codeline + * @return compare code -1, 0, +1 (like memcmp). + */ +int codeline_cmp(const void* a, const void* b); + +/** compare two replay_vars */ +int replay_var_compare(const void* a, const void* b); + +#endif /* UTIL_FPTR_WLIST_H */ diff --git a/util/iana_ports.inc b/util/iana_ports.inc new file mode 100644 index 00000000000..8508d7e9f01 --- /dev/null +++ b/util/iana_ports.inc @@ -0,0 +1,5347 @@ +1, +2, +3, +5, +7, +9, +11, +13, +17, +18, +19, +20, +21, +22, +23, +24, +25, +27, +29, +31, +33, +35, +37, +38, +39, +41, +42, +43, +44, +45, +46, +47, +48, +49, +50, +51, +52, +53, +54, +55, +56, +57, +58, +59, +61, +62, +63, +64, +65, +66, +67, +68, +69, +70, +71, +72, +73, +74, +75, +76, +77, +78, +79, +80, +82, +83, +84, +85, +86, +87, +88, +89, +90, +91, +92, +93, +94, +95, +96, +97, +98, +99, +101, +102, +103, +104, +105, +106, +107, +108, +109, +110, +111, +112, +113, +115, +116, +117, +118, +119, +120, +121, +122, +123, +124, +125, +126, +127, +128, +129, +130, +131, +132, +133, +134, +135, +136, +137, +138, +139, +140, +141, +142, +143, +144, +145, +146, +147, +148, +149, +150, +151, +152, +153, +154, +155, +156, +157, +158, +159, +160, +161, +162, +163, +164, +165, +166, +167, +168, +169, +170, +171, +172, +173, +174, +175, +176, +177, +178, +179, +180, +181, +182, +183, +184, +185, +186, +187, +188, +189, +190, +191, +192, +193, +194, +195, +196, +197, +198, +199, +200, +201, +202, +203, +204, +205, +206, +207, +208, +209, +210, +211, +212, +213, +214, +215, +216, +217, +218, +219, +220, +221, +222, +223, +224, +242, +243, +244, +245, +246, +247, +248, +256, +257, +259, +260, +261, +262, +263, +264, +265, +266, +267, +268, +269, +270, +280, +281, +282, +283, +284, +286, +287, +308, +309, +310, +311, +312, +313, +314, +315, +316, +317, +318, +319, +320, +321, +322, +333, +344, +345, +346, +347, +348, +349, +350, +351, +352, +353, +354, +355, +356, +357, +358, +359, +360, +361, +362, +363, +364, +365, +366, +367, +368, +369, +370, +371, +372, +373, +374, +375, +376, +377, +378, +379, +380, +381, +382, +383, +384, +385, +386, +387, +388, +389, +390, +391, +392, +393, +394, +395, +396, +397, +398, +399, +400, +401, +402, +403, +404, +405, +406, +407, +408, +409, +410, +411, +412, +413, +414, +415, +416, +417, +418, +419, +420, +421, +422, +423, +424, +425, +426, +427, +428, +429, +430, +431, +432, +433, +434, +435, +436, +437, +438, +439, +440, +441, +442, +443, +444, +445, +446, +447, +448, +449, +450, +451, +452, +453, +454, +455, +456, +457, +458, +459, +460, +461, +462, +463, +464, +465, +466, +467, +468, +469, +470, +471, +472, +473, +474, +475, +476, +477, +478, +479, +480, +481, +482, +483, +484, +485, +486, +487, +488, +489, +490, +491, +492, +493, +494, +495, +496, +497, +498, +499, +500, +501, +502, +503, +504, +505, +506, +507, +508, +509, +510, +511, +512, +513, +514, +515, +516, +517, +518, +519, +520, +521, +522, +523, +524, +525, +526, +527, +528, +529, +530, +531, +532, +533, +534, +535, +536, +537, +538, +539, +540, +541, +542, +543, +544, +545, +546, +547, +548, +549, +550, +551, +552, +553, +554, +555, +556, +557, +558, +559, +560, +561, +562, +563, +564, +565, +566, +567, +568, +569, +570, +571, +572, +573, +574, +575, +576, +577, +578, +579, +580, +581, +582, +583, +584, +586, +587, +588, +589, +590, +591, +592, +593, +594, +595, +596, +597, +598, +599, +600, +601, +602, +603, +604, +605, +606, +607, +608, +609, +610, +611, +612, +613, +614, +615, +616, +617, +618, +619, +620, +621, +622, +623, +624, +625, +626, +627, +628, +629, +630, +631, +632, +633, +634, +635, +636, +637, +638, +639, +640, +641, +642, +643, +644, +645, +646, +647, +648, +649, +650, +651, +652, +653, +654, +655, +656, +657, +658, +660, +661, +662, +663, +664, +665, +666, +667, +668, +669, +670, +671, +672, +673, +674, +675, +676, +677, +678, +679, +680, +681, +682, +683, +684, +685, +686, +687, +688, +689, +690, +691, +692, +693, +694, +695, +696, +697, +698, +699, +700, +701, +702, +704, +705, +706, +707, +709, +710, +711, +712, +713, +714, +715, +716, +729, +730, +731, +741, +742, +744, +747, +748, +749, +750, +751, +752, +753, +754, +758, +759, +760, +761, +762, +763, +764, +765, +767, +769, +770, +771, +772, +773, +774, +775, +776, +777, +780, +800, +801, +810, +828, +829, +830, +831, +832, +833, +847, +848, +860, +861, +862, +873, +886, +887, +888, +900, +901, +902, +903, +910, +911, +912, +913, +989, +990, +991, +992, +993, +995, +996, +997, +998, +999, +1000, +1008, +1010, +1021, +1022, +1025, +1026, +1028, +1029, +1030, +1031, +1032, +1033, +1034, +1035, +1036, +1037, +1038, +1039, +1040, +1041, +1042, +1043, +1044, +1045, +1046, +1047, +1048, +1049, +1050, +1051, +1052, +1053, +1054, +1055, +1056, +1057, +1058, +1059, +1060, +1061, +1062, +1063, +1064, +1065, +1066, +1067, +1068, +1069, +1070, +1071, +1072, +1073, +1074, +1075, +1076, +1077, +1078, +1079, +1080, +1081, +1082, +1083, +1084, +1085, +1086, +1087, +1088, +1089, +1090, +1091, +1092, +1093, +1094, +1095, +1096, +1097, +1098, +1099, +1100, +1101, +1102, +1103, +1104, +1105, +1106, +1107, +1108, +1110, +1111, +1112, +1113, +1114, +1115, +1116, +1117, +1118, +1119, +1120, +1121, +1122, +1123, +1124, +1125, +1126, +1127, +1128, +1129, +1130, +1131, +1132, +1133, +1134, +1135, +1136, +1137, +1138, +1139, +1140, +1141, +1142, +1143, +1144, +1145, +1146, +1147, +1148, +1149, +1150, +1151, +1152, +1153, +1154, +1155, +1156, +1157, +1158, +1159, +1160, +1161, +1162, +1163, +1164, +1165, +1166, +1167, +1168, +1169, +1170, +1171, +1172, +1173, +1174, +1175, +1176, +1177, +1178, +1179, +1180, +1181, +1182, +1183, +1184, +1185, +1186, +1187, +1188, +1189, +1190, +1191, +1192, +1193, +1194, +1195, +1196, +1197, +1198, +1199, +1200, +1201, +1202, +1203, +1204, +1205, +1206, +1207, +1208, +1209, +1210, +1211, +1212, +1213, +1214, +1215, +1216, +1217, +1218, +1219, +1220, +1221, +1222, +1223, +1224, +1225, +1226, +1227, +1228, +1229, +1230, +1231, +1233, +1234, +1235, +1236, +1237, +1238, +1239, +1240, +1241, +1242, +1243, +1244, +1245, +1246, +1247, +1248, +1249, +1250, +1251, +1252, +1253, +1254, +1255, +1256, +1257, +1258, +1259, +1260, +1261, +1262, +1263, +1264, +1265, +1266, +1267, +1268, +1269, +1270, +1271, +1272, +1273, +1274, +1275, +1276, +1277, +1278, +1279, +1280, +1281, +1282, +1283, +1284, +1285, +1286, +1287, +1288, +1289, +1290, +1291, +1292, +1293, +1294, +1295, +1296, +1297, +1298, +1299, +1300, +1301, +1302, +1303, +1304, +1305, +1306, +1307, +1308, +1309, +1310, +1311, +1312, +1313, +1314, +1315, +1316, +1317, +1318, +1319, +1320, +1321, +1322, +1323, +1324, +1325, +1326, +1327, +1328, +1329, +1330, +1331, +1332, +1333, +1334, +1335, +1336, +1337, +1338, +1339, +1340, +1341, +1342, +1343, +1344, +1345, +1346, +1347, +1348, +1349, +1350, +1351, +1352, +1353, +1354, +1355, +1356, +1357, +1358, +1359, +1360, +1361, +1362, +1363, +1364, +1365, +1366, +1367, +1368, +1369, +1370, +1371, +1372, +1373, +1374, +1375, +1376, +1377, +1378, +1379, +1380, +1381, +1382, +1383, +1384, +1385, +1386, +1387, +1388, +1389, +1390, +1391, +1392, +1393, +1394, +1395, +1396, +1397, +1398, +1399, +1400, +1401, +1402, +1403, +1404, +1405, +1406, +1407, +1408, +1409, +1410, +1411, +1412, +1413, +1414, +1415, +1416, +1417, +1418, +1419, +1420, +1421, +1422, +1423, +1424, +1425, +1426, +1427, +1428, +1429, +1430, +1431, +1432, +1433, +1434, +1435, +1436, +1437, +1438, +1439, +1440, +1441, +1442, +1443, +1444, +1445, +1446, +1447, +1448, +1449, +1450, +1451, +1452, +1453, +1454, +1455, +1456, +1457, +1458, +1459, +1460, +1461, +1462, +1463, +1464, +1465, +1466, +1467, +1468, +1469, +1470, +1471, +1472, +1473, +1474, +1475, +1476, +1477, +1478, +1479, +1480, +1481, +1482, +1483, +1484, +1485, +1486, +1487, +1488, +1489, +1490, +1492, +1493, +1494, +1495, +1496, +1497, +1498, +1499, +1500, +1501, +1502, +1503, +1504, +1505, +1506, +1507, +1508, +1509, +1510, +1511, +1512, +1513, +1514, +1515, +1516, +1517, +1518, +1519, +1520, +1521, +1522, +1523, +1524, +1525, +1526, +1527, +1529, +1530, +1531, +1532, +1533, +1534, +1535, +1536, +1537, +1538, +1539, +1540, +1541, +1542, +1543, +1544, +1545, +1546, +1547, +1548, +1549, +1550, +1551, +1552, +1553, +1554, +1555, +1556, +1557, +1558, +1559, +1560, +1561, +1562, +1563, +1564, +1565, +1566, +1567, +1568, +1569, +1570, +1571, +1572, +1573, +1574, +1575, +1576, +1577, +1578, +1579, +1580, +1581, +1582, +1583, +1584, +1585, +1586, +1587, +1588, +1589, +1590, +1591, +1592, +1593, +1594, +1595, +1596, +1597, +1598, +1599, +1600, +1601, +1602, +1603, +1604, +1605, +1606, +1607, +1608, +1609, +1610, +1611, +1612, +1613, +1614, +1615, +1616, +1617, +1618, +1619, +1620, +1621, +1622, +1623, +1624, +1625, +1626, +1627, +1628, +1629, +1630, +1631, +1632, +1633, +1634, +1635, +1636, +1637, +1638, +1639, +1640, +1641, +1642, +1643, +1644, +1645, +1646, +1647, +1648, +1649, +1650, +1651, +1652, +1653, +1654, +1655, +1656, +1657, +1658, +1659, +1660, +1661, +1662, +1663, +1664, +1665, +1666, +1667, +1668, +1669, +1670, +1671, +1672, +1673, +1674, +1675, +1676, +1677, +1678, +1679, +1680, +1681, +1682, +1683, +1684, +1685, +1686, +1687, +1688, +1689, +1690, +1691, +1692, +1693, +1694, +1695, +1696, +1697, +1698, +1699, +1700, +1701, +1702, +1703, +1704, +1705, +1706, +1707, +1708, +1709, +1710, +1711, +1712, +1713, +1714, +1715, +1716, +1717, +1718, +1719, +1720, +1721, +1722, +1723, +1724, +1725, +1726, +1727, +1728, +1729, +1730, +1731, +1732, +1733, +1734, +1735, +1736, +1737, +1738, +1739, +1740, +1741, +1742, +1743, +1744, +1745, +1746, +1747, +1748, +1749, +1750, +1751, +1752, +1754, +1755, +1756, +1757, +1758, +1759, +1760, +1761, +1762, +1763, +1764, +1765, +1766, +1767, +1768, +1769, +1770, +1771, +1772, +1773, +1774, +1776, +1777, +1778, +1779, +1780, +1781, +1782, +1784, +1785, +1786, +1787, +1788, +1789, +1790, +1791, +1792, +1793, +1794, +1795, +1796, +1797, +1798, +1799, +1800, +1801, +1802, +1803, +1804, +1805, +1806, +1807, +1808, +1809, +1810, +1811, +1812, +1813, +1814, +1815, +1816, +1817, +1818, +1819, +1820, +1821, +1822, +1823, +1824, +1825, +1826, +1827, +1828, +1829, +1830, +1831, +1832, +1833, +1834, +1835, +1836, +1837, +1838, +1839, +1840, +1841, +1842, +1843, +1844, +1845, +1846, +1847, +1848, +1849, +1850, +1851, +1852, +1853, +1854, +1855, +1856, +1857, +1858, +1859, +1860, +1861, +1862, +1863, +1864, +1865, +1866, +1867, +1868, +1869, +1870, +1871, +1872, +1873, +1874, +1875, +1876, +1877, +1878, +1879, +1880, +1881, +1882, +1883, +1884, +1885, +1886, +1887, +1888, +1889, +1890, +1891, +1892, +1893, +1894, +1896, +1897, +1898, +1899, +1900, +1901, +1902, +1903, +1904, +1905, +1906, +1907, +1908, +1909, +1910, +1911, +1912, +1913, +1914, +1915, +1916, +1917, +1918, +1919, +1920, +1921, +1922, +1923, +1924, +1925, +1926, +1927, +1928, +1929, +1930, +1931, +1932, +1933, +1934, +1935, +1936, +1937, +1938, +1939, +1940, +1941, +1942, +1943, +1944, +1945, +1946, +1947, +1948, +1949, +1950, +1951, +1952, +1953, +1954, +1955, +1956, +1957, +1958, +1959, +1960, +1961, +1962, +1963, +1964, +1965, +1966, +1967, +1968, +1969, +1970, +1971, +1972, +1973, +1974, +1975, +1976, +1977, +1978, +1979, +1980, +1981, +1982, +1983, +1984, +1985, +1986, +1987, +1988, +1989, +1990, +1991, +1992, +1993, +1994, +1995, +1996, +1997, +1998, +1999, +2000, +2001, +2002, +2003, +2004, +2005, +2006, +2007, +2008, +2009, +2010, +2011, +2012, +2013, +2014, +2015, +2016, +2017, +2018, +2019, +2020, +2021, +2022, +2023, +2024, +2025, +2026, +2027, +2028, +2029, +2030, +2031, +2032, +2033, +2034, +2035, +2036, +2037, +2038, +2039, +2040, +2041, +2042, +2043, +2044, +2045, +2046, +2047, +2048, +2049, +2050, +2051, +2052, +2053, +2054, +2055, +2056, +2057, +2058, +2059, +2060, +2061, +2062, +2063, +2064, +2065, +2066, +2067, +2068, +2069, +2070, +2071, +2072, +2073, +2074, +2075, +2076, +2077, +2078, +2079, +2080, +2081, +2082, +2083, +2084, +2085, +2086, +2087, +2088, +2089, +2090, +2091, +2092, +2093, +2094, +2095, +2096, +2097, +2098, +2099, +2100, +2101, +2102, +2103, +2104, +2105, +2106, +2107, +2108, +2109, +2110, +2111, +2112, +2113, +2114, +2115, +2116, +2117, +2118, +2119, +2120, +2121, +2122, +2123, +2124, +2125, +2126, +2127, +2128, +2129, +2130, +2131, +2132, +2133, +2134, +2135, +2136, +2137, +2138, +2139, +2140, +2141, +2142, +2143, +2144, +2145, +2146, +2147, +2148, +2149, +2150, +2151, +2152, +2153, +2154, +2155, +2156, +2157, +2158, +2159, +2160, +2161, +2162, +2163, +2164, +2165, +2166, +2167, +2168, +2169, +2170, +2171, +2172, +2173, +2174, +2175, +2176, +2177, +2178, +2179, +2180, +2181, +2182, +2183, +2184, +2185, +2186, +2187, +2190, +2191, +2192, +2193, +2197, +2198, +2199, +2200, +2201, +2202, +2203, +2204, +2205, +2206, +2207, +2208, +2209, +2210, +2211, +2212, +2213, +2214, +2215, +2216, +2217, +2218, +2219, +2220, +2221, +2222, +2223, +2224, +2226, +2227, +2228, +2229, +2230, +2231, +2232, +2233, +2234, +2235, +2236, +2237, +2238, +2239, +2240, +2241, +2242, +2243, +2244, +2245, +2246, +2247, +2248, +2249, +2250, +2251, +2252, +2253, +2254, +2255, +2256, +2257, +2258, +2260, +2261, +2262, +2263, +2264, +2265, +2266, +2267, +2268, +2269, +2270, +2271, +2272, +2273, +2274, +2275, +2276, +2277, +2278, +2279, +2280, +2281, +2282, +2283, +2284, +2285, +2286, +2287, +2288, +2289, +2290, +2291, +2292, +2293, +2294, +2295, +2296, +2297, +2298, +2299, +2300, +2301, +2302, +2303, +2304, +2305, +2306, +2307, +2308, +2309, +2310, +2311, +2312, +2313, +2314, +2315, +2316, +2317, +2318, +2319, +2320, +2321, +2322, +2323, +2324, +2325, +2326, +2327, +2328, +2329, +2330, +2331, +2332, +2333, +2334, +2335, +2336, +2337, +2338, +2339, +2340, +2341, +2342, +2343, +2344, +2345, +2346, +2347, +2348, +2349, +2350, +2351, +2352, +2353, +2354, +2355, +2356, +2357, +2358, +2359, +2360, +2361, +2362, +2363, +2364, +2365, +2366, +2367, +2368, +2370, +2371, +2372, +2381, +2382, +2383, +2384, +2385, +2386, +2387, +2388, +2389, +2390, +2391, +2392, +2393, +2394, +2395, +2396, +2397, +2398, +2399, +2400, +2401, +2402, +2403, +2404, +2405, +2406, +2407, +2409, +2410, +2411, +2412, +2413, +2414, +2415, +2416, +2417, +2418, +2419, +2420, +2421, +2422, +2423, +2424, +2425, +2427, +2428, +2429, +2430, +2431, +2432, +2433, +2434, +2435, +2436, +2437, +2438, +2439, +2440, +2441, +2442, +2443, +2444, +2445, +2446, +2447, +2448, +2449, +2450, +2451, +2452, +2453, +2454, +2455, +2456, +2457, +2458, +2459, +2460, +2461, +2462, +2463, +2464, +2465, +2466, +2467, +2468, +2469, +2470, +2471, +2472, +2473, +2474, +2475, +2476, +2477, +2478, +2479, +2480, +2481, +2482, +2483, +2484, +2485, +2486, +2487, +2488, +2489, +2490, +2491, +2492, +2493, +2494, +2495, +2496, +2497, +2498, +2499, +2500, +2501, +2502, +2503, +2504, +2505, +2506, +2507, +2508, +2509, +2510, +2511, +2512, +2513, +2514, +2515, +2516, +2517, +2518, +2519, +2520, +2521, +2522, +2523, +2524, +2525, +2526, +2527, +2528, +2529, +2530, +2531, +2532, +2533, +2534, +2535, +2536, +2537, +2538, +2539, +2540, +2541, +2542, +2543, +2544, +2545, +2546, +2547, +2548, +2549, +2550, +2551, +2552, +2553, +2554, +2555, +2556, +2557, +2558, +2559, +2560, +2561, +2562, +2563, +2564, +2565, +2566, +2567, +2568, +2569, +2570, +2571, +2572, +2573, +2574, +2575, +2576, +2577, +2578, +2579, +2580, +2581, +2582, +2583, +2584, +2585, +2586, +2587, +2588, +2589, +2590, +2591, +2592, +2593, +2594, +2595, +2596, +2597, +2598, +2599, +2600, +2601, +2602, +2603, +2604, +2605, +2606, +2607, +2608, +2609, +2610, +2611, +2612, +2613, +2614, +2615, +2616, +2617, +2618, +2619, +2620, +2621, +2622, +2623, +2624, +2625, +2626, +2627, +2628, +2629, +2630, +2631, +2632, +2633, +2634, +2635, +2636, +2637, +2638, +2639, +2640, +2641, +2642, +2643, +2644, +2645, +2646, +2647, +2648, +2649, +2650, +2651, +2652, +2653, +2654, +2655, +2656, +2657, +2658, +2659, +2660, +2661, +2662, +2663, +2664, +2665, +2666, +2667, +2668, +2669, +2670, +2671, +2672, +2673, +2674, +2675, +2676, +2677, +2678, +2679, +2680, +2681, +2683, +2684, +2685, +2686, +2687, +2688, +2689, +2690, +2691, +2692, +2694, +2695, +2696, +2697, +2698, +2699, +2700, +2701, +2702, +2703, +2704, +2705, +2706, +2707, +2708, +2709, +2710, +2711, +2712, +2713, +2714, +2715, +2716, +2717, +2718, +2719, +2720, +2721, +2722, +2723, +2724, +2725, +2726, +2727, +2728, +2729, +2730, +2731, +2732, +2733, +2734, +2735, +2736, +2737, +2738, +2739, +2740, +2741, +2742, +2743, +2744, +2745, +2746, +2747, +2748, +2749, +2750, +2751, +2752, +2753, +2754, +2755, +2756, +2757, +2758, +2759, +2760, +2761, +2762, +2763, +2764, +2765, +2766, +2767, +2768, +2769, +2770, +2771, +2772, +2773, +2774, +2775, +2776, +2777, +2778, +2779, +2780, +2781, +2782, +2783, +2784, +2785, +2786, +2787, +2788, +2789, +2790, +2791, +2792, +2793, +2795, +2796, +2797, +2798, +2799, +2800, +2801, +2802, +2803, +2804, +2805, +2806, +2807, +2808, +2809, +2810, +2811, +2812, +2813, +2814, +2815, +2816, +2817, +2818, +2819, +2820, +2821, +2822, +2823, +2824, +2826, +2827, +2828, +2829, +2830, +2831, +2832, +2833, +2834, +2835, +2836, +2837, +2838, +2839, +2840, +2841, +2842, +2843, +2844, +2845, +2846, +2847, +2848, +2849, +2850, +2851, +2852, +2853, +2854, +2855, +2856, +2857, +2858, +2859, +2860, +2861, +2862, +2863, +2864, +2865, +2866, +2867, +2868, +2869, +2870, +2871, +2872, +2874, +2875, +2876, +2877, +2878, +2879, +2880, +2881, +2882, +2883, +2884, +2885, +2886, +2887, +2888, +2889, +2890, +2891, +2892, +2893, +2894, +2895, +2896, +2897, +2898, +2899, +2900, +2901, +2902, +2903, +2904, +2906, +2907, +2908, +2909, +2910, +2911, +2912, +2913, +2914, +2915, +2916, +2917, +2918, +2919, +2920, +2921, +2922, +2923, +2924, +2926, +2927, +2928, +2929, +2930, +2931, +2932, +2933, +2934, +2935, +2936, +2937, +2938, +2939, +2940, +2941, +2942, +2943, +2944, +2945, +2946, +2947, +2948, +2949, +2950, +2951, +2952, +2953, +2954, +2955, +2956, +2957, +2958, +2959, +2960, +2961, +2962, +2963, +2964, +2965, +2966, +2967, +2968, +2969, +2970, +2971, +2972, +2973, +2974, +2975, +2976, +2977, +2978, +2979, +2980, +2981, +2982, +2983, +2984, +2985, +2986, +2987, +2988, +2989, +2990, +2991, +2992, +2993, +2994, +2995, +2996, +2997, +2998, +3000, +3002, +3003, +3004, +3005, +3006, +3007, +3008, +3009, +3010, +3011, +3012, +3013, +3014, +3015, +3016, +3017, +3018, +3019, +3020, +3021, +3022, +3023, +3024, +3025, +3026, +3027, +3028, +3029, +3030, +3031, +3032, +3033, +3034, +3035, +3036, +3037, +3038, +3039, +3040, +3041, +3042, +3043, +3044, +3045, +3046, +3047, +3048, +3049, +3050, +3051, +3052, +3053, +3054, +3055, +3056, +3057, +3058, +3059, +3060, +3061, +3062, +3063, +3064, +3065, +3066, +3067, +3068, +3069, +3070, +3071, +3072, +3073, +3074, +3075, +3076, +3077, +3078, +3079, +3080, +3081, +3082, +3083, +3084, +3085, +3086, +3087, +3088, +3089, +3090, +3091, +3093, +3094, +3095, +3096, +3098, +3099, +3100, +3101, +3102, +3103, +3104, +3105, +3106, +3107, +3108, +3109, +3110, +3111, +3112, +3113, +3114, +3115, +3116, +3117, +3118, +3119, +3120, +3122, +3123, +3124, +3125, +3127, +3128, +3129, +3130, +3131, +3132, +3133, +3134, +3135, +3136, +3137, +3138, +3139, +3140, +3141, +3142, +3143, +3144, +3145, +3146, +3147, +3148, +3149, +3150, +3151, +3152, +3153, +3154, +3155, +3156, +3157, +3158, +3159, +3160, +3161, +3162, +3163, +3164, +3165, +3166, +3167, +3168, +3169, +3170, +3171, +3172, +3173, +3174, +3175, +3176, +3177, +3178, +3179, +3180, +3181, +3182, +3183, +3184, +3185, +3186, +3187, +3188, +3189, +3190, +3191, +3192, +3193, +3194, +3195, +3196, +3197, +3198, +3199, +3200, +3201, +3202, +3203, +3204, +3205, +3206, +3207, +3208, +3209, +3210, +3211, +3212, +3213, +3214, +3215, +3216, +3217, +3218, +3219, +3220, +3221, +3222, +3223, +3224, +3225, +3226, +3227, +3228, +3229, +3230, +3231, +3232, +3233, +3234, +3235, +3236, +3237, +3238, +3239, +3240, +3241, +3242, +3243, +3244, +3245, +3246, +3247, +3248, +3249, +3250, +3251, +3252, +3253, +3254, +3255, +3256, +3257, +3258, +3259, +3260, +3261, +3262, +3263, +3264, +3265, +3266, +3267, +3268, +3269, +3270, +3271, +3272, +3273, +3274, +3275, +3276, +3277, +3278, +3279, +3280, +3281, +3282, +3283, +3284, +3285, +3286, +3287, +3288, +3289, +3290, +3291, +3292, +3293, +3294, +3295, +3296, +3297, +3298, +3299, +3302, +3303, +3304, +3305, +3306, +3307, +3308, +3309, +3310, +3311, +3312, +3313, +3314, +3315, +3316, +3317, +3318, +3319, +3320, +3321, +3326, +3327, +3328, +3329, +3330, +3331, +3332, +3333, +3334, +3335, +3336, +3337, +3338, +3339, +3340, +3341, +3342, +3343, +3344, +3345, +3346, +3347, +3348, +3349, +3350, +3351, +3352, +3353, +3354, +3355, +3356, +3357, +3358, +3359, +3360, +3361, +3362, +3363, +3364, +3365, +3366, +3372, +3373, +3374, +3375, +3376, +3377, +3378, +3379, +3380, +3381, +3382, +3383, +3384, +3385, +3386, +3387, +3388, +3389, +3390, +3391, +3392, +3393, +3394, +3395, +3396, +3397, +3398, +3399, +3400, +3401, +3402, +3405, +3406, +3407, +3408, +3409, +3410, +3411, +3412, +3413, +3414, +3415, +3416, +3417, +3418, +3419, +3420, +3421, +3422, +3423, +3424, +3425, +3426, +3427, +3428, +3429, +3430, +3431, +3432, +3433, +3434, +3435, +3436, +3437, +3438, +3439, +3440, +3441, +3442, +3443, +3444, +3445, +3446, +3447, +3448, +3449, +3450, +3451, +3452, +3453, +3454, +3455, +3456, +3457, +3458, +3459, +3460, +3461, +3462, +3463, +3464, +3465, +3466, +3467, +3468, +3469, +3470, +3471, +3472, +3473, +3474, +3475, +3476, +3477, +3478, +3479, +3480, +3481, +3482, +3483, +3484, +3485, +3486, +3487, +3488, +3489, +3490, +3491, +3492, +3493, +3494, +3495, +3496, +3497, +3498, +3499, +3500, +3501, +3502, +3503, +3504, +3505, +3506, +3507, +3508, +3509, +3510, +3511, +3512, +3513, +3514, +3515, +3516, +3517, +3518, +3519, +3520, +3521, +3522, +3523, +3524, +3525, +3526, +3527, +3528, +3529, +3530, +3531, +3532, +3533, +3534, +3535, +3536, +3537, +3538, +3539, +3540, +3541, +3542, +3543, +3544, +3545, +3547, +3548, +3549, +3550, +3551, +3552, +3553, +3554, +3555, +3556, +3557, +3558, +3559, +3560, +3561, +3562, +3563, +3564, +3567, +3568, +3569, +3570, +3571, +3572, +3573, +3574, +3575, +3576, +3577, +3578, +3579, +3580, +3581, +3582, +3583, +3584, +3585, +3586, +3587, +3588, +3589, +3590, +3591, +3592, +3593, +3594, +3595, +3596, +3597, +3598, +3599, +3600, +3601, +3602, +3603, +3604, +3605, +3606, +3607, +3608, +3609, +3610, +3611, +3612, +3613, +3614, +3615, +3616, +3617, +3618, +3619, +3620, +3621, +3622, +3623, +3624, +3625, +3626, +3627, +3628, +3629, +3630, +3631, +3632, +3633, +3634, +3635, +3636, +3637, +3638, +3639, +3640, +3641, +3642, +3643, +3644, +3645, +3646, +3647, +3648, +3649, +3650, +3651, +3652, +3653, +3654, +3655, +3656, +3657, +3658, +3659, +3660, +3661, +3662, +3663, +3664, +3665, +3666, +3667, +3668, +3669, +3670, +3671, +3672, +3673, +3674, +3675, +3676, +3677, +3678, +3679, +3680, +3681, +3682, +3683, +3684, +3685, +3686, +3687, +3688, +3689, +3690, +3691, +3692, +3695, +3696, +3697, +3698, +3699, +3700, +3701, +3702, +3703, +3704, +3705, +3706, +3707, +3708, +3709, +3710, +3711, +3712, +3713, +3714, +3715, +3716, +3717, +3718, +3719, +3720, +3721, +3722, +3723, +3724, +3725, +3726, +3727, +3728, +3729, +3730, +3731, +3732, +3733, +3734, +3735, +3736, +3738, +3739, +3740, +3741, +3742, +3743, +3744, +3745, +3746, +3747, +3748, +3749, +3750, +3751, +3752, +3753, +3754, +3755, +3756, +3757, +3758, +3759, +3760, +3761, +3762, +3763, +3764, +3765, +3767, +3768, +3769, +3770, +3771, +3772, +3773, +3774, +3775, +3776, +3777, +3778, +3779, +3780, +3781, +3782, +3783, +3784, +3785, +3786, +3787, +3788, +3789, +3790, +3791, +3792, +3793, +3794, +3795, +3796, +3797, +3798, +3799, +3800, +3801, +3802, +3803, +3804, +3805, +3806, +3807, +3808, +3809, +3810, +3811, +3812, +3813, +3814, +3815, +3816, +3817, +3818, +3819, +3820, +3821, +3822, +3823, +3824, +3825, +3826, +3827, +3828, +3829, +3830, +3831, +3832, +3833, +3834, +3835, +3836, +3837, +3838, +3839, +3840, +3841, +3842, +3843, +3844, +3845, +3846, +3847, +3848, +3849, +3850, +3851, +3852, +3853, +3854, +3855, +3856, +3857, +3858, +3859, +3860, +3861, +3862, +3863, +3865, +3866, +3867, +3869, +3870, +3871, +3872, +3873, +3874, +3875, +3876, +3877, +3878, +3879, +3880, +3881, +3882, +3883, +3884, +3885, +3886, +3887, +3888, +3889, +3890, +3891, +3892, +3893, +3894, +3895, +3896, +3897, +3898, +3899, +3900, +3901, +3902, +3903, +3904, +3905, +3906, +3907, +3908, +3909, +3910, +3911, +3912, +3913, +3914, +3915, +3916, +3917, +3918, +3919, +3920, +3921, +3922, +3923, +3924, +3925, +3926, +3927, +3928, +3929, +3930, +3931, +3932, +3933, +3934, +3935, +3936, +3937, +3938, +3939, +3940, +3941, +3942, +3943, +3944, +3945, +3946, +3947, +3948, +3949, +3950, +3951, +3952, +3953, +3954, +3955, +3956, +3957, +3958, +3959, +3960, +3961, +3962, +3963, +3964, +3965, +3966, +3967, +3968, +3969, +3970, +3971, +3972, +3973, +3974, +3975, +3976, +3977, +3978, +3979, +3980, +3981, +3982, +3983, +3984, +3985, +3986, +3987, +3988, +3989, +3990, +3991, +3992, +3993, +3995, +3996, +3997, +3998, +3999, +4000, +4001, +4002, +4003, +4004, +4005, +4006, +4007, +4008, +4009, +4010, +4011, +4012, +4013, +4014, +4015, +4016, +4017, +4018, +4019, +4020, +4021, +4022, +4023, +4024, +4025, +4026, +4027, +4028, +4029, +4030, +4031, +4032, +4033, +4034, +4035, +4036, +4037, +4038, +4039, +4040, +4041, +4042, +4043, +4044, +4045, +4046, +4047, +4049, +4050, +4051, +4052, +4053, +4054, +4055, +4056, +4057, +4058, +4059, +4060, +4061, +4062, +4063, +4064, +4065, +4066, +4067, +4068, +4069, +4070, +4071, +4072, +4073, +4074, +4075, +4076, +4077, +4079, +4080, +4081, +4082, +4083, +4084, +4086, +4089, +4090, +4091, +4092, +4093, +4094, +4095, +4096, +4097, +4098, +4099, +4100, +4101, +4102, +4103, +4104, +4105, +4106, +4107, +4108, +4109, +4110, +4111, +4112, +4113, +4114, +4115, +4116, +4117, +4118, +4119, +4121, +4122, +4123, +4124, +4125, +4126, +4127, +4128, +4129, +4130, +4131, +4132, +4133, +4134, +4135, +4136, +4137, +4138, +4139, +4140, +4141, +4142, +4143, +4145, +4146, +4147, +4148, +4149, +4150, +4151, +4152, +4153, +4154, +4155, +4156, +4157, +4158, +4159, +4160, +4161, +4162, +4163, +4164, +4165, +4166, +4167, +4168, +4169, +4172, +4173, +4174, +4177, +4178, +4179, +4180, +4181, +4182, +4183, +4184, +4185, +4188, +4191, +4192, +4199, +4300, +4301, +4302, +4303, +4304, +4305, +4306, +4307, +4308, +4309, +4310, +4320, +4321, +4322, +4323, +4324, +4325, +4326, +4327, +4328, +4340, +4341, +4342, +4343, +4344, +4345, +4346, +4347, +4348, +4349, +4350, +4351, +4352, +4353, +4354, +4355, +4356, +4357, +4358, +4359, +4361, +4362, +4368, +4369, +4370, +4371, +4372, +4373, +4375, +4376, +4377, +4378, +4379, +4389, +4390, +4394, +4395, +4400, +4401, +4402, +4403, +4404, +4405, +4406, +4425, +4426, +4430, +4441, +4442, +4443, +4444, +4445, +4446, +4447, +4448, +4449, +4450, +4451, +4452, +4453, +4454, +4455, +4456, +4457, +4458, +4484, +4486, +4488, +4500, +4535, +4536, +4537, +4538, +4545, +4546, +4547, +4548, +4549, +4550, +4551, +4552, +4554, +4555, +4556, +4557, +4558, +4559, +4566, +4567, +4568, +4569, +4591, +4592, +4593, +4594, +4595, +4596, +4597, +4598, +4599, +4600, +4601, +4658, +4659, +4660, +4661, +4662, +4663, +4664, +4665, +4666, +4667, +4668, +4669, +4670, +4671, +4672, +4673, +4674, +4675, +4676, +4677, +4678, +4679, +4680, +4681, +4682, +4683, +4684, +4685, +4686, +4687, +4688, +4689, +4690, +4691, +4692, +4700, +4701, +4702, +4725, +4726, +4727, +4728, +4729, +4730, +4732, +4737, +4738, +4739, +4740, +4741, +4742, +4743, +4744, +4745, +4749, +4750, +4751, +4752, +4753, +4784, +4785, +4800, +4801, +4802, +4803, +4804, +4827, +4837, +4838, +4839, +4840, +4841, +4842, +4843, +4844, +4845, +4846, +4847, +4848, +4849, +4850, +4851, +4867, +4868, +4869, +4870, +4871, +4876, +4877, +4878, +4881, +4882, +4884, +4885, +4894, +4899, +4900, +4914, +4937, +4940, +4941, +4942, +4949, +4950, +4951, +4952, +4969, +4970, +4986, +4987, +4988, +4989, +4990, +4991, +4999, +5000, +5001, +5002, +5003, +5004, +5005, +5006, +5007, +5008, +5009, +5010, +5011, +5012, +5013, +5014, +5020, +5021, +5022, +5023, +5024, +5025, +5026, +5027, +5029, +5030, +5031, +5042, +5043, +5044, +5046, +5047, +5049, +5050, +5051, +5052, +5055, +5056, +5057, +5058, +5059, +5060, +5061, +5062, +5064, +5065, +5066, +5067, +5069, +5070, +5071, +5072, +5073, +5074, +5079, +5080, +5081, +5082, +5083, +5084, +5085, +5092, +5093, +5094, +5099, +5100, +5101, +5102, +5104, +5105, +5111, +5112, +5116, +5133, +5136, +5137, +5145, +5150, +5151, +5152, +5154, +5155, +5164, +5165, +5166, +5167, +5168, +5190, +5191, +5192, +5193, +5200, +5201, +5202, +5203, +5223, +5224, +5225, +5226, +5227, +5234, +5235, +5236, +5237, +5245, +5246, +5247, +5248, +5249, +5250, +5251, +5252, +5264, +5265, +5270, +5271, +5272, +5282, +5298, +5299, +5300, +5301, +5302, +5303, +5304, +5305, +5306, +5307, +5308, +5309, +5310, +5312, +5313, +5314, +5315, +5343, +5344, +5350, +5351, +5352, +5353, +5354, +5355, +5356, +5357, +5358, +5359, +5360, +5361, +5362, +5363, +5397, +5398, +5399, +5400, +5401, +5402, +5403, +5404, +5405, +5406, +5407, +5408, +5409, +5410, +5411, +5412, +5413, +5414, +5415, +5416, +5417, +5418, +5419, +5420, +5421, +5422, +5423, +5424, +5425, +5426, +5427, +5428, +5429, +5430, +5431, +5432, +5433, +5434, +5435, +5436, +5437, +5443, +5453, +5454, +5455, +5456, +5461, +5462, +5463, +5464, +5465, +5500, +5501, +5502, +5503, +5504, +5505, +5506, +5553, +5554, +5555, +5556, +5567, +5568, +5573, +5580, +5581, +5582, +5583, +5584, +5585, +5597, +5598, +5599, +5600, +5601, +5602, +5603, +5604, +5605, +5627, +5628, +5629, +5630, +5631, +5632, +5633, +5634, +5671, +5672, +5673, +5674, +5675, +5676, +5677, +5678, +5679, +5680, +5681, +5682, +5683, +5688, +5689, +5713, +5714, +5715, +5716, +5717, +5718, +5719, +5720, +5721, +5722, +5723, +5724, +5728, +5729, +5730, +5741, +5742, +5743, +5744, +5745, +5746, +5747, +5748, +5750, +5755, +5757, +5766, +5767, +5768, +5769, +5770, +5771, +5777, +5781, +5782, +5783, +5784, +5785, +5786, +5787, +5793, +5794, +5813, +5814, +5859, +5863, +5900, +5910, +5911, +5912, +5913, +5963, +5968, +5969, +5984, +5985, +5986, +5987, +5988, +5989, +5990, +5991, +5992, +5999, +6000, +6064, +6065, +6066, +6069, +6070, +6071, +6072, +6073, +6074, +6082, +6083, +6085, +6086, +6087, +6100, +6101, +6102, +6103, +6104, +6105, +6106, +6107, +6108, +6109, +6110, +6111, +6112, +6122, +6123, +6124, +6133, +6140, +6141, +6142, +6143, +6144, +6145, +6146, +6147, +6148, +6149, +6160, +6161, +6162, +6163, +6200, +6222, +6241, +6242, +6243, +6244, +6251, +6252, +6253, +6268, +6269, +6300, +6301, +6306, +6315, +6316, +6320, +6321, +6322, +6324, +6343, +6346, +6347, +6350, +6355, +6360, +6370, +6382, +6389, +6390, +6417, +6420, +6421, +6443, +6444, +6445, +6446, +6455, +6456, +6471, +6480, +6481, +6482, +6483, +6484, +6485, +6486, +6487, +6488, +6489, +6500, +6501, +6502, +6503, +6505, +6506, +6507, +6508, +6509, +6510, +6514, +6515, +6543, +6544, +6547, +6548, +6549, +6550, +6551, +6558, +6566, +6568, +6579, +6580, +6581, +6582, +6583, +6619, +6620, +6621, +6622, +6623, +6626, +6627, +6628, +6657, +6670, +6671, +6672, +6673, +6678, +6679, +6689, +6696, +6701, +6702, +6703, +6714, +6715, +6767, +6768, +6769, +6770, +6771, +6785, +6786, +6787, +6788, +6789, +6790, +6791, +6801, +6831, +6841, +6842, +6850, +6868, +6888, +6935, +6936, +6946, +6951, +6961, +6962, +6963, +6964, +6965, +6966, +6969, +6997, +6998, +6999, +7000, +7001, +7002, +7003, +7004, +7005, +7006, +7007, +7008, +7009, +7010, +7011, +7012, +7013, +7014, +7015, +7019, +7020, +7021, +7022, +7023, +7024, +7025, +7030, +7040, +7070, +7071, +7080, +7099, +7100, +7101, +7107, +7121, +7128, +7129, +7161, +7162, +7163, +7164, +7165, +7166, +7169, +7170, +7171, +7174, +7200, +7201, +7227, +7262, +7272, +7273, +7274, +7275, +7276, +7277, +7278, +7279, +7280, +7281, +7282, +7365, +7391, +7392, +7393, +7394, +7395, +7397, +7400, +7401, +7402, +7410, +7421, +7426, +7427, +7428, +7429, +7430, +7431, +7437, +7443, +7473, +7491, +7500, +7501, +7510, +7511, +7542, +7543, +7544, +7545, +7546, +7547, +7548, +7549, +7550, +7560, +7566, +7570, +7588, +7624, +7627, +7628, +7629, +7633, +7648, +7674, +7675, +7676, +7677, +7680, +7689, +7697, +7707, +7708, +7720, +7724, +7725, +7726, +7727, +7734, +7738, +7741, +7743, +7744, +7747, +7777, +7778, +7779, +7781, +7786, +7787, +7789, +7794, +7797, +7798, +7799, +7800, +7801, +7810, +7845, +7846, +7872, +7880, +7887, +7900, +7901, +7902, +7903, +7913, +7932, +7933, +7967, +7979, +7980, +7982, +7998, +7999, +8000, +8001, +8002, +8003, +8005, +8008, +8019, +8020, +8021, +8022, +8025, +8026, +8032, +8033, +8034, +8040, +8052, +8053, +8054, +8055, +8056, +8057, +8058, +8059, +8074, +8080, +8081, +8082, +8083, +8086, +8087, +8088, +8097, +8100, +8115, +8116, +8118, +8121, +8122, +8128, +8129, +8130, +8131, +8132, +8148, +8149, +8160, +8161, +8182, +8184, +8192, +8194, +8195, +8199, +8200, +8201, +8202, +8204, +8205, +8206, +8207, +8208, +8230, +8243, +8276, +8280, +8292, +8294, +8300, +8301, +8320, +8321, +8351, +8376, +8377, +8378, +8379, +8380, +8383, +8400, +8401, +8402, +8403, +8416, +8417, +8442, +8443, +8444, +8450, +8472, +8473, +8474, +8500, +8501, +8554, +8555, +8567, +8600, +8610, +8611, +8612, +8613, +8614, +8675, +8686, +8699, +8732, +8733, +8763, +8764, +8765, +8770, +8786, +8787, +8793, +8800, +8804, +8873, +8880, +8883, +8888, +8889, +8890, +8891, +8892, +8893, +8894, +8899, +8900, +8901, +8910, +8911, +8912, +8913, +8954, +8989, +8990, +8991, +8999, +9000, +9001, +9002, +9007, +9009, +9020, +9021, +9022, +9023, +9024, +9025, +9026, +9080, +9084, +9085, +9086, +9087, +9088, +9089, +9090, +9091, +9092, +9100, +9101, +9102, +9103, +9104, +9105, +9106, +9119, +9131, +9160, +9161, +9162, +9163, +9164, +9191, +9200, +9201, +9202, +9203, +9204, +9205, +9206, +9207, +9208, +9209, +9210, +9211, +9212, +9213, +9214, +9215, +9216, +9217, +9222, +9255, +9278, +9279, +9280, +9281, +9282, +9283, +9284, +9285, +9286, +9287, +9292, +9293, +9294, +9295, +9300, +9318, +9321, +9343, +9344, +9346, +9374, +9380, +9396, +9397, +9400, +9401, +9402, +9418, +9443, +9444, +9450, +9500, +9522, +9535, +9536, +9555, +9592, +9593, +9594, +9595, +9596, +9597, +9598, +9599, +9600, +9612, +9618, +9628, +9629, +9632, +9667, +9668, +9694, +9695, +9700, +9747, +9750, +9753, +9762, +9800, +9801, +9802, +9875, +9876, +9888, +9889, +9898, +9899, +9900, +9901, +9903, +9909, +9911, +9950, +9951, +9952, +9953, +9955, +9956, +9966, +9987, +9990, +9991, +9992, +9993, +9994, +9995, +9996, +9997, +9998, +9999, +10000, +10001, +10002, +10003, +10007, +10008, +10009, +10050, +10051, +10080, +10081, +10100, +10101, +10102, +10103, +10104, +10107, +10110, +10111, +10113, +10114, +10115, +10116, +10117, +10128, +10160, +10161, +10162, +10200, +10201, +10252, +10260, +10288, +10500, +10540, +10541, +10542, +10543, +10544, +10800, +10805, +10810, +10860, +10990, +11000, +11001, +11106, +11111, +11112, +11161, +11162, +11163, +11164, +11165, +11171, +11201, +11208, +11211, +11319, +11320, +11321, +11367, +11371, +11600, +11720, +11751, +11876, +11877, +11967, +12000, +12001, +12002, +12003, +12004, +12005, +12006, +12007, +12008, +12009, +12012, +12013, +12109, +12121, +12168, +12172, +12300, +12321, +12322, +12345, +12753, +13160, +13216, +13217, +13218, +13223, +13224, +13400, +13720, +13721, +13722, +13724, +13782, +13783, +13785, +13786, +13818, +13819, +13820, +13821, +13822, +13929, +14000, +14001, +14033, +14034, +14141, +14142, +14145, +14149, +14154, +14250, +14414, +14936, +14937, +15000, +15118, +15345, +15363, +15555, +15660, +15740, +15998, +16003, +16161, +16309, +16310, +16311, +16360, +16361, +16367, +16368, +16384, +16666, +16900, +16950, +16991, +16992, +16993, +16994, +16995, +17007, +17185, +17219, +17221, +17222, +17234, +17235, +17500, +17729, +17754, +17755, +17756, +18000, +18181, +18182, +18183, +18184, +18185, +18186, +18187, +18241, +18262, +18463, +18634, +18635, +18769, +18881, +18888, +19000, +19191, +19194, +19283, +19315, +19398, +19410, +19411, +19412, +19539, +19540, +19541, +19999, +20000, +20001, +20002, +20003, +20005, +20012, +20014, +20034, +20046, +20048, +20049, +20167, +20202, +20222, +20480, +20670, +20999, +21000, +21554, +21590, +21800, +21845, +21846, +21847, +21848, +21849, +22000, +22001, +22002, +22003, +22004, +22005, +22273, +22305, +22343, +22347, +22350, +22555, +22763, +22800, +22951, +23000, +23001, +23002, +23003, +23004, +23005, +23272, +23333, +23400, +23401, +23402, +24000, +24001, +24002, +24003, +24004, +24005, +24006, +24242, +24249, +24321, +24386, +24465, +24554, +24676, +24677, +24678, +24680, +24922, +25000, +25001, +25002, +25003, +25004, +25005, +25006, +25007, +25008, +25009, +25793, +25900, +25901, +25902, +25903, +26000, +26133, +26208, +26260, +26261, +26262, +26263, +26486, +26487, +26489, +27345, +27442, +27504, +27782, +27999, +28000, +28119, +28240, +29167, +30001, +30002, +30260, +30999, +31029, +31416, +31457, +31620, +31765, +31948, +31949, +32034, +32249, +32483, +32635, +32636, +32767, +32768, +32769, +32770, +32771, +32772, +32773, +32774, +32775, +32776, +32777, +32801, +32896, +33123, +33331, +33334, +33434, +33656, +34249, +34378, +34379, +34962, +34963, +34964, +34980, +35355, +36001, +36865, +37475, +37654, +38201, +38202, +38203, +39681, +40000, +40841, +40842, +40843, +40853, +41111, +41794, +41795, +42508, +42509, +42510, +43188, +43189, +43190, +43439, +43440, +43441, +44321, +44322, +44323, +44544, +44553, +44600, +44818, +45000, +45054, +45678, +45825, +45966, +46999, +47000, +47557, +47624, +47806, +47808, +48000, +48001, +48002, +48003, +48128, +48129, +48556, +48619, diff --git a/util/locks.c b/util/locks.c new file mode 100644 index 00000000000..425f9b9d456 --- /dev/null +++ b/util/locks.c @@ -0,0 +1,264 @@ +/** + * util/locks.c - unbound locking primitives + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * Implementation of locking and threading support. + * A place for locking debug code since most locking functions are macros. + */ + +#include "config.h" +#include "util/locks.h" +#include +#ifdef HAVE_SYS_WAIT_H +#include +#endif + +/** block all signals, masks them away. */ +void +ub_thread_blocksigs(void) +{ +#if defined(HAVE_PTHREAD) || defined(HAVE_SOLARIS_THREADS) || defined(HAVE_SIGPROCMASK) +# if defined(HAVE_PTHREAD) || defined(HAVE_SOLARIS_THREADS) + int err; +# endif + sigset_t sigset; + sigfillset(&sigset); +#ifdef HAVE_PTHREAD + if((err=pthread_sigmask(SIG_SETMASK, &sigset, NULL))) + fatal_exit("pthread_sigmask: %s", strerror(err)); +#else +# ifdef HAVE_SOLARIS_THREADS + if((err=thr_sigsetmask(SIG_SETMASK, &sigset, NULL))) + fatal_exit("thr_sigsetmask: %s", strerror(err)); +# else + /* have nothing, do single process signal mask */ + if(sigprocmask(SIG_SETMASK, &sigset, NULL)) + fatal_exit("sigprocmask: %s", strerror(errno)); +# endif /* HAVE_SOLARIS_THREADS */ +#endif /* HAVE_PTHREAD */ +#endif /* have signal stuff */ +} + +/** unblock one signal, so we can catch it */ +void ub_thread_sig_unblock(int sig) +{ +#if defined(HAVE_PTHREAD) || defined(HAVE_SOLARIS_THREADS) || defined(HAVE_SIGPROCMASK) +# if defined(HAVE_PTHREAD) || defined(HAVE_SOLARIS_THREADS) + int err; +# endif + sigset_t sigset; + sigemptyset(&sigset); + sigaddset(&sigset, sig); +#ifdef HAVE_PTHREAD + if((err=pthread_sigmask(SIG_UNBLOCK, &sigset, NULL))) + fatal_exit("pthread_sigmask: %s", strerror(err)); +#else +# ifdef HAVE_SOLARIS_THREADS + if((err=thr_sigsetmask(SIG_UNBLOCK, &sigset, NULL))) + fatal_exit("thr_sigsetmask: %s", strerror(err)); +# else + /* have nothing, do single thread case */ + if(sigprocmask(SIG_UNBLOCK, &sigset, NULL)) + fatal_exit("sigprocmask: %s", strerror(errno)); +# endif /* HAVE_SOLARIS_THREADS */ +#endif /* HAVE_PTHREAD */ +#else + (void)sig; +#endif /* have signal stuff */ +} + +#if !defined(HAVE_PTHREAD) && !defined(HAVE_SOLARIS_THREADS) && !defined(HAVE_WINDOWS_THREADS) +/** + * No threading available: fork a new process. + * This means no shared data structure, and no locking. + * Only the main thread ever returns. Exits on errors. + * @param thr: the location where to store the thread-id. + * @param func: function body of the thread. Return value of func is lost. + * @param arg: user argument to func. + */ +void +ub_thr_fork_create(ub_thread_t* thr, void* (*func)(void*), void* arg) +{ + pid_t pid = fork(); + switch(pid) { + default: /* main */ + *thr = (ub_thread_t)pid; + return; + case 0: /* child */ + *thr = (ub_thread_t)getpid(); + (void)(*func)(arg); + exit(0); + case -1: /* error */ + fatal_exit("could not fork: %s", strerror(errno)); + } +} + +/** + * There is no threading. Wait for a process to terminate. + * Note that ub_thread_t is defined as pid_t. + * @param thread: the process id to wait for. + */ +void ub_thr_fork_wait(ub_thread_t thread) +{ + int status = 0; + if(waitpid((pid_t)thread, &status, 0) == -1) + log_err("waitpid(%d): %s", (int)thread, strerror(errno)); + if(status != 0) + log_warn("process %d abnormal exit with status %d", + (int)thread, status); +} +#endif /* !defined(HAVE_PTHREAD) && !defined(HAVE_SOLARIS_THREADS) && !defined(HAVE_WINDOWS_THREADS) */ + +#ifdef HAVE_SOLARIS_THREADS +void* ub_thread_key_get(ub_thread_key_t key) +{ + void* ret=NULL; + LOCKRET(thr_getspecific(key, &ret)); + return ret; +} +#endif + +#ifdef HAVE_WINDOWS_THREADS +/** log a windows GetLastError message */ +static void log_win_err(const char* str, DWORD err) +{ + LPTSTR buf; + if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, err, 0, (LPTSTR)&buf, 0, NULL) == 0) { + /* could not format error message */ + log_err("%s, GetLastError=%d", str, (int)err); + return; + } + log_err("%s, (err=%d): %s", str, (int)err, buf); + LocalFree(buf); +} + +void lock_basic_init(lock_basic_t* lock) +{ + /* implement own lock, because windows HANDLE as Mutex usage + * uses too many handles and would bog down the whole system. */ + (void)InterlockedExchange(lock, 0); +} + +void lock_basic_destroy(lock_basic_t* lock) +{ + (void)InterlockedExchange(lock, 0); +} + +void lock_basic_lock(lock_basic_t* lock) +{ + LONG wait = 1; /* wait 1 msec at first */ + + while(InterlockedExchange(lock, 1)) { + /* if the old value was 1 then if was already locked */ + Sleep(wait); /* wait with sleep */ + wait *= 2; /* exponential backoff for waiting */ + } + /* the old value was 0, but we inserted 1, we locked it! */ +} + +void lock_basic_unlock(lock_basic_t* lock) +{ + /* unlock it by inserting the value of 0. xchg for cache coherency. */ + (void)InterlockedExchange(lock, 0); +} + +void ub_thread_key_create(ub_thread_key_t* key, void* f) +{ + *key = TlsAlloc(); + if(*key == TLS_OUT_OF_INDEXES) { + *key = 0; + log_win_err("TlsAlloc Failed(OUT_OF_INDEXES)", GetLastError()); + } + else ub_thread_key_set(*key, f); +} + +void ub_thread_key_set(ub_thread_key_t key, void* v) +{ + if(!TlsSetValue(key, v)) { + log_win_err("TlsSetValue failed", GetLastError()); + } +} + +void* ub_thread_key_get(ub_thread_key_t key) +{ + void* ret = (void*)TlsGetValue(key); + if(ret == NULL && GetLastError() != ERROR_SUCCESS) { + log_win_err("TlsGetValue failed", GetLastError()); + } + return ret; +} + +void ub_thread_create(ub_thread_t* thr, void* (*func)(void*), void* arg) +{ +#ifndef HAVE__BEGINTHREADEX + *thr = CreateThread(NULL, /* default security (no inherit handle) */ + 0, /* default stack size */ + (LPTHREAD_START_ROUTINE)func, arg, + 0, /* default flags, run immediately */ + NULL); /* do not store thread identifier anywhere */ +#else + /* the begintheadex routine setups for the C lib; aligns stack */ + *thr=(ub_thread_t)_beginthreadex(NULL, 0, (void*)func, arg, 0, NULL); +#endif + if(*thr == NULL) { + log_win_err("CreateThread failed", GetLastError()); + fatal_exit("thread create failed"); + } +} + +ub_thread_t ub_thread_self(void) +{ + return GetCurrentThread(); +} + +void ub_thread_join(ub_thread_t thr) +{ + DWORD ret = WaitForSingleObject(thr, INFINITE); + if(ret == WAIT_FAILED) { + log_win_err("WaitForSingleObject(Thread):WAIT_FAILED", + GetLastError()); + } else if(ret == WAIT_TIMEOUT) { + log_win_err("WaitForSingleObject(Thread):WAIT_TIMEOUT", + GetLastError()); + } + /* and close the handle to the thread */ + if(!CloseHandle(thr)) { + log_win_err("CloseHandle(Thread) failed", GetLastError()); + } +} +#endif /* HAVE_WINDOWS_THREADS */ diff --git a/util/locks.h b/util/locks.h new file mode 100644 index 00000000000..91be5c3e26f --- /dev/null +++ b/util/locks.h @@ -0,0 +1,293 @@ +/** + * util/locks.h - unbound locking primitives + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef UTIL_LOCKS_H +#define UTIL_LOCKS_H + +/** + * \file + * Locking primitives. + * If pthreads is available, these are used. + * If no locking exists, they do nothing. + * + * The idea is to have different sorts of locks for different tasks. + * This allows the locking code to be ported more easily. + * + * Types of locks that are supported. + * o lock_rw: lock that has many readers and one writer (to a data entry). + * o lock_basic: simple mutex. Blocking, one person has access only. + * This lock is meant for non performance sensitive uses. + * o lock_quick: speed lock. For performance sensitive locking of critical + * sections. Could be implemented by a mutex or a spinlock. + * + * Also thread creation and deletion functions are defined here. + */ + +#include "util/log.h" + +/** + * The following macro is used to check the return value of the + * pthread calls. They return 0 on success and an errno on error. + * The errno is logged to the logfile with a descriptive comment. + */ +#define LOCKRET(func) do {\ + int lockret_err; \ + if( (lockret_err=(func)) != 0) \ + log_err("%s at %d could not " #func ": %s", \ + __FILE__, __LINE__, strerror(lockret_err)); \ + } while(0) + +/** DEBUG: use thread debug whenever possible */ +#if defined(HAVE_PTHREAD) && defined(HAVE_PTHREAD_SPINLOCK_T) && defined(ENABLE_LOCK_CHECKS) +# define USE_THREAD_DEBUG +#endif + +#ifdef USE_THREAD_DEBUG +/******************* THREAD DEBUG ************************/ +/* (some) checking; to detect races and deadlocks. */ +#include "testcode/checklocks.h" + +#else /* USE_THREAD_DEBUG */ +#define lock_protect(lock, area, size) /* nop */ +#define lock_unprotect(lock, area) /* nop */ +#define lock_get_mem(lock) (0) /* nothing */ +#define checklock_start() /* nop */ +#define checklock_stop() /* nop */ + +#ifdef HAVE_PTHREAD +#include + +/******************* PTHREAD ************************/ + +/** use pthread mutex for basic lock */ +typedef pthread_mutex_t lock_basic_t; +/** small front for pthread init func, NULL is default attrs. */ +#define lock_basic_init(lock) LOCKRET(pthread_mutex_init(lock, NULL)) +#define lock_basic_destroy(lock) LOCKRET(pthread_mutex_destroy(lock)) +#define lock_basic_lock(lock) LOCKRET(pthread_mutex_lock(lock)) +#define lock_basic_unlock(lock) LOCKRET(pthread_mutex_unlock(lock)) + +#ifndef HAVE_PTHREAD_RWLOCK_T +/** in case rwlocks are not supported, use a mutex. */ +typedef pthread_mutex_t lock_rw_t; +#define lock_rw_init(lock) LOCKRET(pthread_mutex_init(lock, NULL)) +#define lock_rw_destroy(lock) LOCKRET(pthread_mutex_destroy(lock)) +#define lock_rw_rdlock(lock) LOCKRET(pthread_mutex_lock(lock)) +#define lock_rw_wrlock(lock) LOCKRET(pthread_mutex_lock(lock)) +#define lock_rw_unlock(lock) LOCKRET(pthread_mutex_unlock(lock)) +#else /* HAVE_PTHREAD_RWLOCK_T */ +/** we use the pthread rwlock */ +typedef pthread_rwlock_t lock_rw_t; +/** small front for pthread init func, NULL is default attrs. */ +#define lock_rw_init(lock) LOCKRET(pthread_rwlock_init(lock, NULL)) +#define lock_rw_destroy(lock) LOCKRET(pthread_rwlock_destroy(lock)) +#define lock_rw_rdlock(lock) LOCKRET(pthread_rwlock_rdlock(lock)) +#define lock_rw_wrlock(lock) LOCKRET(pthread_rwlock_wrlock(lock)) +#define lock_rw_unlock(lock) LOCKRET(pthread_rwlock_unlock(lock)) +#endif /* HAVE_PTHREAD_RWLOCK_T */ + +#ifndef HAVE_PTHREAD_SPINLOCK_T +/** in case spinlocks are not supported, use a mutex. */ +typedef pthread_mutex_t lock_quick_t; +/** small front for pthread init func, NULL is default attrs. */ +#define lock_quick_init(lock) LOCKRET(pthread_mutex_init(lock, NULL)) +#define lock_quick_destroy(lock) LOCKRET(pthread_mutex_destroy(lock)) +#define lock_quick_lock(lock) LOCKRET(pthread_mutex_lock(lock)) +#define lock_quick_unlock(lock) LOCKRET(pthread_mutex_unlock(lock)) + +#else /* HAVE_PTHREAD_SPINLOCK_T */ +/** use pthread spinlock for the quick lock */ +typedef pthread_spinlock_t lock_quick_t; +/** + * allocate process private since this is available whether + * Thread Process-Shared Synchronization is supported or not. + * This means only threads inside this process may access the lock. + * (not threads from another process that shares memory). + * spinlocks are not supported on all pthread platforms. + */ +#define lock_quick_init(lock) LOCKRET(pthread_spin_init(lock, PTHREAD_PROCESS_PRIVATE)) +#define lock_quick_destroy(lock) LOCKRET(pthread_spin_destroy(lock)) +#define lock_quick_lock(lock) LOCKRET(pthread_spin_lock(lock)) +#define lock_quick_unlock(lock) LOCKRET(pthread_spin_unlock(lock)) + +#endif /* HAVE SPINLOCK */ + +/** Thread creation */ +typedef pthread_t ub_thread_t; +/** Pass where to store tread_t in thr. Use default NULL attributes. */ +#define ub_thread_create(thr, func, arg) LOCKRET(pthread_create(thr, NULL, func, arg)) +/** get self id. */ +#define ub_thread_self() pthread_self() +/** wait for another thread to terminate */ +#define ub_thread_join(thread) LOCKRET(pthread_join(thread, NULL)) +typedef pthread_key_t ub_thread_key_t; +#define ub_thread_key_create(key, f) LOCKRET(pthread_key_create(key, f)) +#define ub_thread_key_set(key, v) LOCKRET(pthread_setspecific(key, v)) +#define ub_thread_key_get(key) pthread_getspecific(key) + +#else /* we do not HAVE_PTHREAD */ +#ifdef HAVE_SOLARIS_THREADS + +/******************* SOLARIS THREADS ************************/ +#include +#include + +typedef rwlock_t lock_rw_t; +#define lock_rw_init(lock) LOCKRET(rwlock_init(lock, USYNC_THREAD, NULL)) +#define lock_rw_destroy(lock) LOCKRET(rwlock_destroy(lock)) +#define lock_rw_rdlock(lock) LOCKRET(rw_rdlock(lock)) +#define lock_rw_wrlock(lock) LOCKRET(rw_wrlock(lock)) +#define lock_rw_unlock(lock) LOCKRET(rw_unlock(lock)) + +/** use basic mutex */ +typedef mutex_t lock_basic_t; +#define lock_basic_init(lock) LOCKRET(mutex_init(lock, USYNC_THREAD, NULL)) +#define lock_basic_destroy(lock) LOCKRET(mutex_destroy(lock)) +#define lock_basic_lock(lock) LOCKRET(mutex_lock(lock)) +#define lock_basic_unlock(lock) LOCKRET(mutex_unlock(lock)) + +/** No spinlocks in solaris threads API. Use a mutex. */ +typedef mutex_t lock_quick_t; +#define lock_quick_init(lock) LOCKRET(mutex_init(lock, USYNC_THREAD, NULL)) +#define lock_quick_destroy(lock) LOCKRET(mutex_destroy(lock)) +#define lock_quick_lock(lock) LOCKRET(mutex_lock(lock)) +#define lock_quick_unlock(lock) LOCKRET(mutex_unlock(lock)) + +/** Thread creation, create a default thread. */ +typedef thread_t ub_thread_t; +#define ub_thread_create(thr, func, arg) LOCKRET(thr_create(NULL, NULL, func, arg, NULL, thr)) +#define ub_thread_self() thr_self() +#define ub_thread_join(thread) LOCKRET(thr_join(thread, NULL, NULL)) +typedef thread_key_t ub_thread_key_t; +#define ub_thread_key_create(key, f) LOCKRET(thr_keycreate(key, f)) +#define ub_thread_key_set(key, v) LOCKRET(thr_setspecific(key, v)) +void* ub_thread_key_get(ub_thread_key_t key); + + +#else /* we do not HAVE_SOLARIS_THREADS and no PTHREADS */ +/******************* WINDOWS THREADS ************************/ +#ifdef HAVE_WINDOWS_THREADS +#include + +/* Use a mutex */ +typedef LONG lock_rw_t; +#define lock_rw_init(lock) lock_basic_init(lock) +#define lock_rw_destroy(lock) lock_basic_destroy(lock) +#define lock_rw_rdlock(lock) lock_basic_lock(lock) +#define lock_rw_wrlock(lock) lock_basic_lock(lock) +#define lock_rw_unlock(lock) lock_basic_unlock(lock) + +/** the basic lock is a mutex, implemented opaquely, for error handling. */ +typedef LONG lock_basic_t; +void lock_basic_init(lock_basic_t* lock); +void lock_basic_destroy(lock_basic_t* lock); +void lock_basic_lock(lock_basic_t* lock); +void lock_basic_unlock(lock_basic_t* lock); + +/** on windows no spinlock, use mutex too. */ +typedef LONG lock_quick_t; +#define lock_quick_init(lock) lock_basic_init(lock) +#define lock_quick_destroy(lock) lock_basic_destroy(lock) +#define lock_quick_lock(lock) lock_basic_lock(lock) +#define lock_quick_unlock(lock) lock_basic_unlock(lock) + +/** Thread creation, create a default thread. */ +typedef HANDLE ub_thread_t; +void ub_thread_create(ub_thread_t* thr, void* (*func)(void*), void* arg); +ub_thread_t ub_thread_self(void); +void ub_thread_join(ub_thread_t thr); +typedef DWORD ub_thread_key_t; +void ub_thread_key_create(ub_thread_key_t* key, void* f); +void ub_thread_key_set(ub_thread_key_t key, void* v); +void* ub_thread_key_get(ub_thread_key_t key); + +#else /* we do not HAVE_SOLARIS_THREADS, PTHREADS or WINDOWS_THREADS */ + +/******************* NO THREADS ************************/ +#define THREADS_DISABLED 1 +/** In case there is no thread support, define locks to do nothing */ +typedef int lock_rw_t; +#define lock_rw_init(lock) /* nop */ +#define lock_rw_destroy(lock) /* nop */ +#define lock_rw_rdlock(lock) /* nop */ +#define lock_rw_wrlock(lock) /* nop */ +#define lock_rw_unlock(lock) /* nop */ + +/** define locks to do nothing */ +typedef int lock_basic_t; +#define lock_basic_init(lock) /* nop */ +#define lock_basic_destroy(lock) /* nop */ +#define lock_basic_lock(lock) /* nop */ +#define lock_basic_unlock(lock) /* nop */ + +/** define locks to do nothing */ +typedef int lock_quick_t; +#define lock_quick_init(lock) /* nop */ +#define lock_quick_destroy(lock) /* nop */ +#define lock_quick_lock(lock) /* nop */ +#define lock_quick_unlock(lock) /* nop */ + +/** Thread creation, threads do not exist */ +typedef pid_t ub_thread_t; +/** ub_thread_create is simulated with fork (extremely heavy threads, + * with no shared memory). */ +#define ub_thread_create(thr, func, arg) \ + ub_thr_fork_create(thr, func, arg) +#define ub_thread_self() getpid() +#define ub_thread_join(thread) ub_thr_fork_wait(thread) +void ub_thr_fork_wait(ub_thread_t thread); +void ub_thr_fork_create(ub_thread_t* thr, void* (*func)(void*), void* arg); +typedef void* ub_thread_key_t; +#define ub_thread_key_create(key, f) (*(key)) = NULL +#define ub_thread_key_set(key, v) (key) = (v) +#define ub_thread_key_get(key) (key) + +#endif /* HAVE_WINDOWS_THREADS */ +#endif /* HAVE_SOLARIS_THREADS */ +#endif /* HAVE_PTHREAD */ +#endif /* USE_THREAD_DEBUG */ + +/** + * Block all signals for this thread. + * fatal exit on error. + */ +void ub_thread_blocksigs(void); + +/** + * unblock one signal for this thread. + */ +void ub_thread_sig_unblock(int sig); + +#endif /* UTIL_LOCKS_H */ diff --git a/util/log.c b/util/log.c new file mode 100644 index 00000000000..fc07dc6a9cb --- /dev/null +++ b/util/log.c @@ -0,0 +1,453 @@ +/* + * util/log.c - implementation of the log code + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \file + * Implementation of log.h. + */ + +#include "config.h" +#include "util/log.h" +#include "util/locks.h" +#ifdef HAVE_TIME_H +#include +#endif +#ifdef HAVE_SYSLOG_H +# include +#else +/**define LOG_ constants */ +# define LOG_CRIT 2 +# define LOG_ERR 3 +# define LOG_WARNING 4 +# define LOG_NOTICE 5 +# define LOG_INFO 6 +# define LOG_DEBUG 7 +#endif +#ifdef UB_ON_WINDOWS +# include "winrc/win_svc.h" +#endif + +/* default verbosity */ +enum verbosity_value verbosity = 0; +/** the file logged to. */ +static FILE* logfile = 0; +/** if key has been created */ +static int key_created = 0; +/** pthread key for thread ids in logfile */ +static ub_thread_key_t logkey; +/** the identity of this executable/process */ +static const char* ident="unbound"; +#if defined(HAVE_SYSLOG_H) || defined(UB_ON_WINDOWS) +/** are we using syslog(3) to log to */ +static int logging_to_syslog = 0; +#endif /* HAVE_SYSLOG_H */ +/** time to print in log, if NULL, use time(2) */ +static uint32_t* log_now = NULL; +/** print time in UTC or in secondsfrom1970 */ +static int log_time_asc = 0; + +void +log_init(const char* filename, int use_syslog, const char* chrootdir) +{ + FILE *f; + if(!key_created) { + key_created = 1; + ub_thread_key_create(&logkey, NULL); + } + if(logfile +#if defined(HAVE_SYSLOG_H) || defined(UB_ON_WINDOWS) + || logging_to_syslog +#endif + ) + verbose(VERB_QUERY, "switching log to %s", + use_syslog?"syslog":(filename&&filename[0]?filename:"stderr")); + if(logfile && logfile != stderr) + fclose(logfile); +#ifdef HAVE_SYSLOG_H + if(logging_to_syslog) { + closelog(); + logging_to_syslog = 0; + } + if(use_syslog) { + /* do not delay opening until first write, because we may + * chroot and no longer be able to access dev/log and so on */ + openlog(ident, LOG_NDELAY, LOG_DAEMON); + logging_to_syslog = 1; + return; + } +#elif defined(UB_ON_WINDOWS) + if(logging_to_syslog) { + logging_to_syslog = 0; + } + if(use_syslog) { + logging_to_syslog = 1; + return; + } +#endif /* HAVE_SYSLOG_H */ + if(!filename || !filename[0]) { + logfile = stderr; + return; + } + /* open the file for logging */ + if(chrootdir && chrootdir[0] && strncmp(filename, chrootdir, + strlen(chrootdir)) == 0) + filename += strlen(chrootdir); + f = fopen(filename, "a"); + if(!f) { + log_err("Could not open logfile %s: %s", filename, + strerror(errno)); + return; + } +#ifndef UB_ON_WINDOWS + /* line buffering does not work on windows */ + setvbuf(f, NULL, (int)_IOLBF, 0); +#endif + logfile = f; +} + +void log_file(FILE *f) +{ + logfile = f; +} + +void log_thread_set(int* num) +{ + ub_thread_key_set(logkey, num); +} + +void log_ident_set(const char* id) +{ + ident = id; +} + +void log_set_time(uint32_t* t) +{ + log_now = t; +} + +void log_set_time_asc(int use_asc) +{ + log_time_asc = use_asc; +} + +void +log_vmsg(int pri, const char* type, + const char *format, va_list args) +{ + char message[MAXSYSLOGMSGLEN]; + unsigned int* tid = (unsigned int*)ub_thread_key_get(logkey); + time_t now; +#if defined(HAVE_STRFTIME) && defined(HAVE_LOCALTIME_R) + char tmbuf[32]; + struct tm tm; +#endif + (void)pri; + vsnprintf(message, sizeof(message), format, args); +#ifdef HAVE_SYSLOG_H + if(logging_to_syslog) { + syslog(pri, "[%d:%x] %s: %s", + (int)getpid(), tid?*tid:0, type, message); + return; + } +#elif defined(UB_ON_WINDOWS) + if(logging_to_syslog) { + char m[32768]; + HANDLE* s; + LPCTSTR str = m; + DWORD tp = MSG_GENERIC_ERR; + WORD wt = EVENTLOG_ERROR_TYPE; + if(strcmp(type, "info") == 0) { + tp=MSG_GENERIC_INFO; + wt=EVENTLOG_INFORMATION_TYPE; + } else if(strcmp(type, "warning") == 0) { + tp=MSG_GENERIC_WARN; + wt=EVENTLOG_WARNING_TYPE; + } else if(strcmp(type, "notice") == 0 + || strcmp(type, "debug") == 0) { + tp=MSG_GENERIC_SUCCESS; + wt=EVENTLOG_SUCCESS; + } + snprintf(m, sizeof(m), "[%s:%x] %s: %s", + ident, tid?*tid:0, type, message); + s = RegisterEventSource(NULL, SERVICE_NAME); + if(!s) return; + ReportEvent(s, wt, 0, tp, NULL, 1, 0, &str, NULL); + DeregisterEventSource(s); + return; + } +#endif /* HAVE_SYSLOG_H */ + if(!logfile) return; + if(log_now) + now = (time_t)*log_now; + else now = (time_t)time(NULL); +#if defined(HAVE_STRFTIME) && defined(HAVE_LOCALTIME_R) + if(log_time_asc && strftime(tmbuf, sizeof(tmbuf), "%b %d %H:%M:%S", + localtime_r(&now, &tm))%(sizeof(tmbuf)) != 0) { + /* %sizeof buf!=0 because old strftime returned max on error */ + fprintf(logfile, "%s %s[%d:%x] %s: %s\n", tmbuf, + ident, (int)getpid(), tid?*tid:0, type, message); + } else +#endif + fprintf(logfile, "[%u] %s[%d:%x] %s: %s\n", (unsigned)now, + ident, (int)getpid(), tid?*tid:0, type, message); +#ifdef UB_ON_WINDOWS + /* line buffering does not work on windows */ + fflush(logfile); +#endif +} + +/** + * implementation of log_info + * @param format: format string printf-style. + */ +void +log_info(const char *format, ...) +{ + va_list args; + va_start(args, format); + log_vmsg(LOG_INFO, "info", format, args); + va_end(args); +} + +/** + * implementation of log_err + * @param format: format string printf-style. + */ +void +log_err(const char *format, ...) +{ + va_list args; + va_start(args, format); + log_vmsg(LOG_ERR, "error", format, args); + va_end(args); +} + +/** + * implementation of log_warn + * @param format: format string printf-style. + */ +void +log_warn(const char *format, ...) +{ + va_list args; + va_start(args, format); + log_vmsg(LOG_WARNING, "warning", format, args); + va_end(args); +} + +/** + * implementation of fatal_exit + * @param format: format string printf-style. + */ +void +fatal_exit(const char *format, ...) +{ + va_list args; + va_start(args, format); + log_vmsg(LOG_CRIT, "fatal error", format, args); + va_end(args); + exit(1); +} + +/** + * implementation of verbose + * @param level: verbose level for the message. + * @param format: format string printf-style. + */ +void +verbose(enum verbosity_value level, const char* format, ...) +{ + va_list args; + va_start(args, format); + if(verbosity >= level) { + if(level == VERB_OPS) + log_vmsg(LOG_NOTICE, "notice", format, args); + else if(level == VERB_DETAIL) + log_vmsg(LOG_INFO, "info", format, args); + else log_vmsg(LOG_DEBUG, "debug", format, args); + } + va_end(args); +} + +/** log hex data */ +static void +log_hex_f(enum verbosity_value v, const char* msg, void* data, size_t length) +{ + size_t i, j; + uint8_t* data8 = (uint8_t*)data; + const char* hexchar = "0123456789ABCDEF"; + char buf[1024+1]; /* alloc blocksize hex chars + \0 */ + const size_t blocksize = 512; + size_t len; + + if(length == 0) { + verbose(v, "%s[%u]", msg, (unsigned)length); + return; + } + + for(i=0; i> 4 ]; + buf[j*2 + 1] = hexchar[ data8[i+j] & 0xF ]; + } + buf[len*2] = 0; + verbose(v, "%s[%u:%u] %.*s", msg, (unsigned)length, + (unsigned)i, (int)len*2, buf); + } +} + +void +log_hex(const char* msg, void* data, size_t length) +{ + log_hex_f(verbosity, msg, data, length); +} + +void log_buf(enum verbosity_value level, const char* msg, ldns_buffer* buf) +{ + if(verbosity < level) + return; + log_hex_f(level, msg, ldns_buffer_begin(buf), ldns_buffer_limit(buf)); +} + +#ifdef USE_WINSOCK +char* wsa_strerror(DWORD err) +{ + static char unknown[32]; + + switch(err) { + case WSA_INVALID_HANDLE: return "Specified event object handle is invalid."; + case WSA_NOT_ENOUGH_MEMORY: return "Insufficient memory available."; + case WSA_INVALID_PARAMETER: return "One or more parameters are invalid."; + case WSA_OPERATION_ABORTED: return "Overlapped operation aborted."; + case WSA_IO_INCOMPLETE: return "Overlapped I/O event object not in signaled state."; + case WSA_IO_PENDING: return "Overlapped operations will complete later."; + case WSAEINTR: return "Interrupted function call."; + case WSAEBADF: return "File handle is not valid."; + case WSAEACCES: return "Permission denied."; + case WSAEFAULT: return "Bad address."; + case WSAEINVAL: return "Invalid argument."; + case WSAEMFILE: return "Too many open files."; + case WSAEWOULDBLOCK: return "Resource temporarily unavailable."; + case WSAEINPROGRESS: return "Operation now in progress."; + case WSAEALREADY: return "Operation already in progress."; + case WSAENOTSOCK: return "Socket operation on nonsocket."; + case WSAEDESTADDRREQ: return "Destination address required."; + case WSAEMSGSIZE: return "Message too long."; + case WSAEPROTOTYPE: return "Protocol wrong type for socket."; + case WSAENOPROTOOPT: return "Bad protocol option."; + case WSAEPROTONOSUPPORT: return "Protocol not supported."; + case WSAESOCKTNOSUPPORT: return "Socket type not supported."; + case WSAEOPNOTSUPP: return "Operation not supported."; + case WSAEPFNOSUPPORT: return "Protocol family not supported."; + case WSAEAFNOSUPPORT: return "Address family not supported by protocol family."; + case WSAEADDRINUSE: return "Address already in use."; + case WSAEADDRNOTAVAIL: return "Cannot assign requested address."; + case WSAENETDOWN: return "Network is down."; + case WSAENETUNREACH: return "Network is unreachable."; + case WSAENETRESET: return "Network dropped connection on reset."; + case WSAECONNABORTED: return "Software caused connection abort."; + case WSAECONNRESET: return "Connection reset by peer."; + case WSAENOBUFS: return "No buffer space available."; + case WSAEISCONN: return "Socket is already connected."; + case WSAENOTCONN: return "Socket is not connected."; + case WSAESHUTDOWN: return "Cannot send after socket shutdown."; + case WSAETOOMANYREFS: return "Too many references."; + case WSAETIMEDOUT: return "Connection timed out."; + case WSAECONNREFUSED: return "Connection refused."; + case WSAELOOP: return "Cannot translate name."; + case WSAENAMETOOLONG: return "Name too long."; + case WSAEHOSTDOWN: return "Host is down."; + case WSAEHOSTUNREACH: return "No route to host."; + case WSAENOTEMPTY: return "Directory not empty."; + case WSAEPROCLIM: return "Too many processes."; + case WSAEUSERS: return "User quota exceeded."; + case WSAEDQUOT: return "Disk quota exceeded."; + case WSAESTALE: return "Stale file handle reference."; + case WSAEREMOTE: return "Item is remote."; + case WSASYSNOTREADY: return "Network subsystem is unavailable."; + case WSAVERNOTSUPPORTED: return "Winsock.dll version out of range."; + case WSANOTINITIALISED: return "Successful WSAStartup not yet performed."; + case WSAEDISCON: return "Graceful shutdown in progress."; + case WSAENOMORE: return "No more results."; + case WSAECANCELLED: return "Call has been canceled."; + case WSAEINVALIDPROCTABLE: return "Procedure call table is invalid."; + case WSAEINVALIDPROVIDER: return "Service provider is invalid."; + case WSAEPROVIDERFAILEDINIT: return "Service provider failed to initialize."; + case WSASYSCALLFAILURE: return "System call failure."; + case WSASERVICE_NOT_FOUND: return "Service not found."; + case WSATYPE_NOT_FOUND: return "Class type not found."; + case WSA_E_NO_MORE: return "No more results."; + case WSA_E_CANCELLED: return "Call was canceled."; + case WSAEREFUSED: return "Database query was refused."; + case WSAHOST_NOT_FOUND: return "Host not found."; + case WSATRY_AGAIN: return "Nonauthoritative host not found."; + case WSANO_RECOVERY: return "This is a nonrecoverable error."; + case WSANO_DATA: return "Valid name, no data record of requested type."; + case WSA_QOS_RECEIVERS: return "QOS receivers."; + case WSA_QOS_SENDERS: return "QOS senders."; + case WSA_QOS_NO_SENDERS: return "No QOS senders."; + case WSA_QOS_NO_RECEIVERS: return "QOS no receivers."; + case WSA_QOS_REQUEST_CONFIRMED: return "QOS request confirmed."; + case WSA_QOS_ADMISSION_FAILURE: return "QOS admission error."; + case WSA_QOS_POLICY_FAILURE: return "QOS policy failure."; + case WSA_QOS_BAD_STYLE: return "QOS bad style."; + case WSA_QOS_BAD_OBJECT: return "QOS bad object."; + case WSA_QOS_TRAFFIC_CTRL_ERROR: return "QOS traffic control error."; + case WSA_QOS_GENERIC_ERROR: return "QOS generic error."; + case WSA_QOS_ESERVICETYPE: return "QOS service type error."; + case WSA_QOS_EFLOWSPEC: return "QOS flowspec error."; + case WSA_QOS_EPROVSPECBUF: return "Invalid QOS provider buffer."; + case WSA_QOS_EFILTERSTYLE: return "Invalid QOS filter style."; + case WSA_QOS_EFILTERTYPE: return "Invalid QOS filter type."; + case WSA_QOS_EFILTERCOUNT: return "Incorrect QOS filter count."; + case WSA_QOS_EOBJLENGTH: return "Invalid QOS object length."; + case WSA_QOS_EFLOWCOUNT: return "Incorrect QOS flow count."; + /*case WSA_QOS_EUNKOWNPSOBJ: return "Unrecognized QOS object.";*/ + case WSA_QOS_EPOLICYOBJ: return "Invalid QOS policy object."; + case WSA_QOS_EFLOWDESC: return "Invalid QOS flow descriptor."; + case WSA_QOS_EPSFLOWSPEC: return "Invalid QOS provider-specific flowspec."; + case WSA_QOS_EPSFILTERSPEC: return "Invalid QOS provider-specific filterspec."; + case WSA_QOS_ESDMODEOBJ: return "Invalid QOS shape discard mode object."; + case WSA_QOS_ESHAPERATEOBJ: return "Invalid QOS shaping rate object."; + case WSA_QOS_RESERVED_PETYPE: return "Reserved policy QOS element type."; + default: + snprintf(unknown, sizeof(unknown), + "unknown WSA error code %d", (int)err); + return unknown; + } +} +#endif /* USE_WINSOCK */ diff --git a/util/log.h b/util/log.h new file mode 100644 index 00000000000..270ffc5c180 --- /dev/null +++ b/util/log.h @@ -0,0 +1,198 @@ +/* + * util/log.h - logging service + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains logging functions. + */ + +#ifndef UTIL_LOG_H +#define UTIL_LOG_H +#include + +/** + * verbosity value: + */ +enum verbosity_value { + /** 0 - no verbose messages */ + NO_VERBOSE = 0, + /** 1 - operational information */ + VERB_OPS, + /** 2 - detailed information */ + VERB_DETAIL, + /** 3 - query level information */ + VERB_QUERY, + /** 4 - algorithm level information */ + VERB_ALGO, + /** 5 - querier client information */ + VERB_CLIENT +}; + +/** The global verbosity setting */ +extern enum verbosity_value verbosity; + +/** + * log a verbose message, pass the level for this message. + * It has printf formatted arguments. No trailing newline is needed. + * @param level: verbosity level for this message, compared to global + * verbosity setting. + * @param format: printf-style format string. Arguments follow. + */ +void verbose(enum verbosity_value level, + const char* format, ...) ATTR_FORMAT(printf, 2, 3); + +/** + * call this to initialize logging services. + * @param filename: if NULL stderr is used. + * @param use_syslog: set to true to ignore filename and use syslog(3). + * @param chrootdir: to which directory we have been chrooted, if any. + */ +void log_init(const char* filename, int use_syslog, const char* chrootdir); + +/** + * Set logging to go to the specified file *. + * This setting does not affect the use_syslog setting. + * @param f: to that file, or pass NULL to disable logging. + */ +void log_file(FILE *f); + +/** + * Init a thread (will print this number for the thread log entries). + * Must be called from the thread itself. If not called 0 is printed. + * @param num: number to print for this thread. Owned by caller, must + * continue to exist. + */ +void log_thread_set(int* num); + +/** + * Set identity to print, default is 'unbound'. + * @param id: string to print. Name of executable. + */ +void log_ident_set(const char* id); + +/** + * Set the time value to print in log entries. + * @param t: the point is copied and used to find the time. + * if NULL, time(2) is used. + */ +void log_set_time(uint32_t* t); + +/** + * Set if the time value is printed ascii or decimal in log entries. + * @param use_asc: if true, ascii is printed, otherwise decimal. + * If the conversion fails or you have no time functions, + * decimal is printed. + */ +void log_set_time_asc(int use_asc); + +/** + * Log informational message. + * Pass printf formatted arguments. No trailing newline is needed. + * @param format: printf-style format string. Arguments follow. + */ +void log_info(const char* format, ...) ATTR_FORMAT(printf, 1, 2); + +/** + * Log error message. + * Pass printf formatted arguments. No trailing newline is needed. + * @param format: printf-style format string. Arguments follow. + */ +void log_err(const char* format, ...) ATTR_FORMAT(printf, 1, 2); + +/** + * Log warning message. + * Pass printf formatted arguments. No trailing newline is needed. + * @param format: printf-style format string. Arguments follow. + */ +void log_warn(const char* format, ...) ATTR_FORMAT(printf, 1, 2); + +/** + * Log a hex-string to the log. Can be any length. + * performs mallocs to do so, slow. But debug useful. + * @param msg: string desc to accompany the hexdump. + * @param data: data to dump in hex format. + * @param length: length of data. + */ +void log_hex(const char* msg, void* data, size_t length); + +/** + * Easy alternative for log_hex, takes a ldns_buffer. + * @param level: verbosity level for this message, compared to global + * verbosity setting. + * @param msg: string desc to print + * @param buf: the buffer. + */ +void log_buf(enum verbosity_value level, const char* msg, ldns_buffer* buf); + +/** + * Log fatal error message, and exit the current process. + * Pass printf formatted arguments. No trailing newline is needed. + * @param format: printf-style format string. Arguments follow. + */ +void fatal_exit(const char* format, ...) ATTR_FORMAT(printf, 1, 2); + +/** + * va_list argument version of log_info. + * @param pri: priority type, for example 5 (INFO). + * @param type: string to designate type of message (info, error). + * @param format: the printf style format to print. no newline. + * @param args: arguments for format string. + */ +void log_vmsg(int pri, const char* type, const char* format, va_list args); + +/** + * an assertion that is thrown to the logfile. + */ +#ifdef UNBOUND_DEBUG +# define log_assert(x) \ + do { if(!(x)) \ + fatal_exit("%s:%d: %s: assertion %s failed", \ + __FILE__, __LINE__, __func__, #x); \ + } while(0); +#else +# define log_assert(x) /*nothing*/ +#endif + +#ifdef USE_WINSOCK +/** + * Convert WSA error into string. + * @param err: from WSAGetLastError() + * @return: string. + */ +char* wsa_strerror(DWORD err); +#endif /* USE_WINSOCK */ + +#endif /* UTIL_LOG_H */ diff --git a/util/mini_event.c b/util/mini_event.c new file mode 100644 index 00000000000..f66214ddb8f --- /dev/null +++ b/util/mini_event.c @@ -0,0 +1,394 @@ +/* + * mini_event.c - implementation of part of libevent api, portably. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * \file + * fake libevent implementation. Less broad in functionality, and only + * supports select(2). + */ + +#include "config.h" +#ifdef HAVE_TIME_H +#include +#endif +#include + +#if defined(USE_MINI_EVENT) && !defined(USE_WINSOCK) +#include +#include "util/mini_event.h" +#include "util/fptr_wlist.h" + +/** compare events in tree, based on timevalue, ptr for uniqueness */ +int mini_ev_cmp(const void* a, const void* b) +{ + const struct event *e = (const struct event*)a; + const struct event *f = (const struct event*)b; + if(e->ev_timeout.tv_sec < f->ev_timeout.tv_sec) + return -1; + if(e->ev_timeout.tv_sec > f->ev_timeout.tv_sec) + return 1; + if(e->ev_timeout.tv_usec < f->ev_timeout.tv_usec) + return -1; + if(e->ev_timeout.tv_usec > f->ev_timeout.tv_usec) + return 1; + if(e < f) + return -1; + if(e > f) + return 1; + return 0; +} + +/** set time */ +static int +settime(struct event_base* base) +{ + if(gettimeofday(base->time_tv, NULL) < 0) { + return -1; + } +#ifndef S_SPLINT_S + *base->time_secs = (uint32_t)base->time_tv->tv_sec; +#endif + return 0; +} + +/** create event base */ +void *event_init(uint32_t* time_secs, struct timeval* time_tv) +{ + struct event_base* base = (struct event_base*)malloc( + sizeof(struct event_base)); + if(!base) + return NULL; + memset(base, 0, sizeof(*base)); + base->time_secs = time_secs; + base->time_tv = time_tv; + if(settime(base) < 0) { + event_base_free(base); + return NULL; + } + base->times = rbtree_create(mini_ev_cmp); + if(!base->times) { + event_base_free(base); + return NULL; + } + base->capfd = MAX_FDS; +#ifdef FD_SETSIZE + if((int)FD_SETSIZE < base->capfd) + base->capfd = (int)FD_SETSIZE; +#endif + base->fds = (struct event**)calloc((size_t)base->capfd, + sizeof(struct event*)); + if(!base->fds) { + event_base_free(base); + return NULL; + } + base->signals = (struct event**)calloc(MAX_SIG, sizeof(struct event*)); + if(!base->signals) { + event_base_free(base); + return NULL; + } +#ifndef S_SPLINT_S + FD_ZERO(&base->reads); + FD_ZERO(&base->writes); +#endif + return base; +} + +/** get version */ +const char *event_get_version(void) +{ + return "mini-event-"PACKAGE_VERSION; +} + +/** get polling method, select */ +const char *event_get_method(void) +{ + return "select"; +} + +/** call timeouts handlers, and return how long to wait for next one or -1 */ +static void handle_timeouts(struct event_base* base, struct timeval* now, + struct timeval* wait) +{ + struct event* p; +#ifndef S_SPLINT_S + wait->tv_sec = (time_t)-1; +#endif + + while((rbnode_t*)(p = (struct event*)rbtree_first(base->times)) + !=RBTREE_NULL) { +#ifndef S_SPLINT_S + if(p->ev_timeout.tv_sec > now->tv_sec || + (p->ev_timeout.tv_sec==now->tv_sec && + p->ev_timeout.tv_usec > now->tv_usec)) { + /* there is a next larger timeout. wait for it */ + wait->tv_sec = p->ev_timeout.tv_sec - now->tv_sec; + if(now->tv_usec > p->ev_timeout.tv_usec) { + wait->tv_sec--; + wait->tv_usec = 1000000 - (now->tv_usec - + p->ev_timeout.tv_usec); + } else { + wait->tv_usec = p->ev_timeout.tv_usec + - now->tv_usec; + } + return; + } +#endif + /* event times out, remove it */ + (void)rbtree_delete(base->times, p); + p->ev_events &= ~EV_TIMEOUT; + fptr_ok(fptr_whitelist_event(p->ev_callback)); + (*p->ev_callback)(p->ev_fd, EV_TIMEOUT, p->ev_arg); + } +} + +/** call select and callbacks for that */ +static int handle_select(struct event_base* base, struct timeval* wait) +{ + fd_set r, w; + int ret, i; + +#ifndef S_SPLINT_S + if(wait->tv_sec==(time_t)-1) + wait = NULL; +#endif + memmove(&r, &base->reads, sizeof(fd_set)); + memmove(&w, &base->writes, sizeof(fd_set)); + memmove(&base->ready, &base->content, sizeof(fd_set)); + + if((ret = select(base->maxfd+1, &r, &w, NULL, wait)) == -1) { + ret = errno; + if(settime(base) < 0) + return -1; + errno = ret; + if(ret == EAGAIN || ret == EINTR) + return 0; + return -1; + } + if(settime(base) < 0) + return -1; + + for(i=0; imaxfd+1; i++) { + short bits = 0; + if(!base->fds[i] || !(FD_ISSET(i, &base->ready))) { + continue; + } + if(FD_ISSET(i, &r)) { + bits |= EV_READ; + ret--; + } + if(FD_ISSET(i, &w)) { + bits |= EV_WRITE; + ret--; + } + bits &= base->fds[i]->ev_events; + if(bits) { + fptr_ok(fptr_whitelist_event( + base->fds[i]->ev_callback)); + (*base->fds[i]->ev_callback)(base->fds[i]->ev_fd, + bits, base->fds[i]->ev_arg); + if(ret==0) + break; + } + } + return 0; +} + +/** run select in a loop */ +int event_base_dispatch(struct event_base* base) +{ + struct timeval wait; + if(settime(base) < 0) + return -1; + while(!base->need_to_exit) + { + /* see if timeouts need handling */ + handle_timeouts(base, base->time_tv, &wait); + if(base->need_to_exit) + return 0; + /* do select */ + if(handle_select(base, &wait) < 0) { + if(base->need_to_exit) + return 0; + return -1; + } + } + return 0; +} + +/** exit that loop */ +int event_base_loopexit(struct event_base* base, + struct timeval* ATTR_UNUSED(tv)) +{ + base->need_to_exit = 1; + return 0; +} + +/* free event base, free events yourself */ +void event_base_free(struct event_base* base) +{ + if(!base) + return; + if(base->times) + free(base->times); + if(base->fds) + free(base->fds); + if(base->signals) + free(base->signals); + free(base); +} + +/** set content of event */ +void event_set(struct event* ev, int fd, short bits, + void (*cb)(int, short, void *), void* arg) +{ + ev->node.key = ev; + ev->ev_fd = fd; + ev->ev_events = bits; + ev->ev_callback = cb; + fptr_ok(fptr_whitelist_event(ev->ev_callback)); + ev->ev_arg = arg; + ev->added = 0; +} + +/* add event to a base */ +int event_base_set(struct event_base* base, struct event* ev) +{ + ev->ev_base = base; + ev->added = 0; + return 0; +} + +/* add event to make it active, you may not change it with event_set anymore */ +int event_add(struct event* ev, struct timeval* tv) +{ + if(ev->added) + event_del(ev); + if(ev->ev_fd != -1 && ev->ev_fd >= ev->ev_base->capfd) + return -1; + if( (ev->ev_events&(EV_READ|EV_WRITE)) && ev->ev_fd != -1) { + ev->ev_base->fds[ev->ev_fd] = ev; + if(ev->ev_events&EV_READ) { + FD_SET(FD_SET_T ev->ev_fd, &ev->ev_base->reads); + } + if(ev->ev_events&EV_WRITE) { + FD_SET(FD_SET_T ev->ev_fd, &ev->ev_base->writes); + } + FD_SET(FD_SET_T ev->ev_fd, &ev->ev_base->content); + FD_CLR(FD_SET_T ev->ev_fd, &ev->ev_base->ready); + if(ev->ev_fd > ev->ev_base->maxfd) + ev->ev_base->maxfd = ev->ev_fd; + } + if(tv && (ev->ev_events&EV_TIMEOUT)) { +#ifndef S_SPLINT_S + struct timeval *now = ev->ev_base->time_tv; + ev->ev_timeout.tv_sec = tv->tv_sec + now->tv_sec; + ev->ev_timeout.tv_usec = tv->tv_usec + now->tv_usec; + while(ev->ev_timeout.tv_usec > 1000000) { + ev->ev_timeout.tv_usec -= 1000000; + ev->ev_timeout.tv_sec++; + } +#endif + (void)rbtree_insert(ev->ev_base->times, &ev->node); + } + ev->added = 1; + return 0; +} + +/* remove event, you may change it again */ +int event_del(struct event* ev) +{ + if(ev->ev_fd != -1 && ev->ev_fd >= ev->ev_base->capfd) + return -1; + if((ev->ev_events&EV_TIMEOUT)) + (void)rbtree_delete(ev->ev_base->times, &ev->node); + if((ev->ev_events&(EV_READ|EV_WRITE)) && ev->ev_fd != -1) { + ev->ev_base->fds[ev->ev_fd] = NULL; + FD_CLR(FD_SET_T ev->ev_fd, &ev->ev_base->reads); + FD_CLR(FD_SET_T ev->ev_fd, &ev->ev_base->writes); + FD_CLR(FD_SET_T ev->ev_fd, &ev->ev_base->ready); + FD_CLR(FD_SET_T ev->ev_fd, &ev->ev_base->content); + } + ev->added = 0; + return 0; +} + +/** which base gets to handle signals */ +static struct event_base* signal_base = NULL; +/** signal handler */ +static RETSIGTYPE sigh(int sig) +{ + struct event* ev; + if(!signal_base || sig < 0 || sig >= MAX_SIG) + return; + ev = signal_base->signals[sig]; + if(!ev) + return; + fptr_ok(fptr_whitelist_event(ev->ev_callback)); + (*ev->ev_callback)(sig, EV_SIGNAL, ev->ev_arg); +} + +/** install signal handler */ +int signal_add(struct event* ev, struct timeval* ATTR_UNUSED(tv)) +{ + if(ev->ev_fd == -1 || ev->ev_fd >= MAX_SIG) + return -1; + signal_base = ev->ev_base; + ev->ev_base->signals[ev->ev_fd] = ev; + ev->added = 1; + if(signal(ev->ev_fd, sigh) == SIG_ERR) { + return -1; + } + return 0; +} + +/** remove signal handler */ +int signal_del(struct event* ev) +{ + if(ev->ev_fd == -1 || ev->ev_fd >= MAX_SIG) + return -1; + ev->ev_base->signals[ev->ev_fd] = NULL; + ev->added = 0; + return 0; +} + +#else /* USE_MINI_EVENT */ +#ifndef USE_WINSOCK +int mini_ev_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b)) +{ + return 0; +} +#endif /* not USE_WINSOCK */ +#endif /* USE_MINI_EVENT */ diff --git a/util/mini_event.h b/util/mini_event.h new file mode 100644 index 00000000000..248468ada84 --- /dev/null +++ b/util/mini_event.h @@ -0,0 +1,177 @@ +/* + * mini-event.h - micro implementation of libevent api, using select() only. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * This file implements part of the event(3) libevent api. + * The back end is only select. Max number of fds is limited. + * Max number of signals is limited, one handler per signal only. + * And one handler per fd. + * + * Although limited to select() and a max (1024) open fds, it + * is efficient: + * o dispatch call caches fd_sets to use. + * o handler calling takes time ~ to the number of fds. + * o timeouts are stored in a redblack tree, sorted, so take log(n). + * Timeouts are only accurate to the second (no subsecond accuracy). + * To avoid cpu hogging, fractional timeouts are rounded up to a whole second. + */ + +#ifndef MINI_EVENT_H +#define MINI_EVENT_H + +#if defined(USE_MINI_EVENT) && !defined(USE_WINSOCK) + +#ifndef HAVE_EVENT_BASE_FREE +#define HAVE_EVENT_BASE_FREE +#endif + +/** event timeout */ +#define EV_TIMEOUT 0x01 +/** event fd readable */ +#define EV_READ 0x02 +/** event fd writable */ +#define EV_WRITE 0x04 +/** event signal */ +#define EV_SIGNAL 0x08 +/** event must persist */ +#define EV_PERSIST 0x10 + +/* needs our redblack tree */ +#include "rbtree.h" + +/** max number of file descriptors to support */ +#define MAX_FDS 1024 +/** max number of signals to support */ +#define MAX_SIG 32 + +/** event base */ +struct event_base +{ + /** sorted by timeout (absolute), ptr */ + rbtree_t* times; + /** array of 0 - maxfd of ptr to event for it */ + struct event** fds; + /** max fd in use */ + int maxfd; + /** capacity - size of the fds array */ + int capfd; + /* fdset for read write, for fds ready, and added */ + fd_set + /** fds for reading */ + reads, + /** fds for writing */ + writes, + /** fds determined ready for use */ + ready, + /** ready plus newly added events. */ + content; + /** array of 0 - maxsig of ptr to event for it */ + struct event** signals; + /** if we need to exit */ + int need_to_exit; + /** where to store time in seconds */ + uint32_t* time_secs; + /** where to store time in microseconds */ + struct timeval* time_tv; +}; + +/** + * Event structure. Has some of the event elements. + */ +struct event { + /** node in timeout rbtree */ + rbnode_t node; + /** is event already added */ + int added; + + /** event base it belongs to */ + struct event_base *ev_base; + /** fd to poll or -1 for timeouts. signal number for sigs. */ + int ev_fd; + /** what events this event is interested in, see EV_.. above. */ + short ev_events; + /** timeout value */ + struct timeval ev_timeout; + + /** callback to call: fd, eventbits, userarg */ + void (*ev_callback)(int, short, void *arg); + /** callback user arg */ + void *ev_arg; +}; + +/* function prototypes (some are as they appear in event.h) */ +/** create event base */ +void *event_init(uint32_t* time_secs, struct timeval* time_tv); +/** get version */ +const char *event_get_version(void); +/** get polling method, select */ +const char *event_get_method(void); +/** run select in a loop */ +int event_base_dispatch(struct event_base *); +/** exit that loop */ +int event_base_loopexit(struct event_base *, struct timeval *); +/** free event base. Free events yourself */ +void event_base_free(struct event_base *); +/** set content of event */ +void event_set(struct event *, int, short, void (*)(int, short, void *), void *); +/** add event to a base. You *must* call this for every event. */ +int event_base_set(struct event_base *, struct event *); +/** add event to make it active. You may not change it with event_set anymore */ +int event_add(struct event *, struct timeval *); +/** remove event. You may change it again */ +int event_del(struct event *); + +/** add a timer */ +#define evtimer_add(ev, tv) event_add(ev, tv) +/** remove a timer */ +#define evtimer_del(ev) event_del(ev) + +/* uses different implementation. Cannot mix fd/timeouts and signals inside + * the same struct event. create several event structs for that. */ +/** install signal handler */ +int signal_add(struct event *, struct timeval *); +/** set signal event contents */ +#define signal_set(ev, x, cb, arg) \ + event_set(ev, x, EV_SIGNAL|EV_PERSIST, cb, arg) +/** remove signal handler */ +int signal_del(struct event *); + +#endif /* USE_MINI_EVENT and not USE_WINSOCK */ + +/** compare events in tree, based on timevalue, ptr for uniqueness */ +int mini_ev_cmp(const void* a, const void* b); + +#endif /* MINI_EVENT_H */ diff --git a/util/module.c b/util/module.c new file mode 100644 index 00000000000..b45ec6fc878 --- /dev/null +++ b/util/module.c @@ -0,0 +1,71 @@ +/* + * util/module.c - module interface + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \file + * Implementation of module.h. + */ + +#include "config.h" +#include "util/module.h" + +const char* +strextstate(enum module_ext_state s) +{ + switch(s) { + case module_state_initial: return "module_state_initial"; + case module_wait_reply: return "module_wait_reply"; + case module_wait_module: return "module_wait_module"; + case module_restart_next: return "module_restart_next"; + case module_wait_subquery: return "module_wait_subquery"; + case module_error: return "module_error"; + case module_finished: return "module_finished"; + } + return "bad_extstate_value"; +} + +const char* +strmodulevent(enum module_ev e) +{ + switch(e) { + case module_event_new: return "module_event_new"; + case module_event_pass: return "module_event_pass"; + case module_event_reply: return "module_event_reply"; + case module_event_noreply: return "module_event_noreply"; + case module_event_capsfail: return "module_event_capsfail"; + case module_event_moddone: return "module_event_moddone"; + case module_event_error: return "module_event_error"; + } + return "bad_event_value"; +} diff --git a/util/module.h b/util/module.h new file mode 100644 index 00000000000..8fa4ec25960 --- /dev/null +++ b/util/module.h @@ -0,0 +1,402 @@ +/* + * util/module.h - DNS handling module interface + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains the interface for DNS handling modules. + */ + +#ifndef UTIL_MODULE_H +#define UTIL_MODULE_H +#include "util/storage/lruhash.h" +#include "util/data/msgreply.h" +#include "util/data/msgparse.h" +struct alloc_cache; +struct rrset_cache; +struct key_cache; +struct config_file; +struct slabhash; +struct query_info; +struct edns_data; +struct regional; +struct worker; +struct module_qstate; +struct ub_randstate; +struct mesh_area; +struct mesh_state; +struct val_anchors; +struct val_neg_cache; +struct iter_forwards; +struct iter_hints; + +/** Maximum number of modules in operation */ +#define MAX_MODULE 5 + +/** + * Module environment. + * Services and data provided to the module. + */ +struct module_env { + /* --- data --- */ + /** config file with config options */ + struct config_file* cfg; + /** shared message cache */ + struct slabhash* msg_cache; + /** shared rrset cache */ + struct rrset_cache* rrset_cache; + /** shared infrastructure cache (edns, lameness) */ + struct infra_cache* infra_cache; + /** shared key cache */ + struct key_cache* key_cache; + + /* --- services --- */ + /** + * Send serviced DNS query to server. UDP/TCP and EDNS is handled. + * operate() should return with wait_reply. Later on a callback + * will cause operate() to be called with event timeout or reply. + * The time until a timeout is calculated from roundtrip timing, + * several UDP retries are attempted. + * @param qname: query name. (host order) + * @param qnamelen: length in bytes of qname, including trailing 0. + * @param qtype: query type. (host order) + * @param qclass: query class. (host order) + * @param flags: host order flags word, with opcode and CD bit. + * @param dnssec: if set, EDNS record will have bits set. + * If EDNS_DO bit is set, DO bit is set in EDNS records. + * If BIT_CD is set, CD bit is set in queries with EDNS records. + * @param want_dnssec: if set, the validator wants DNSSEC. Without + * EDNS, the answer is likely to be useless for this domain. + * @param addr: where to. + * @param addrlen: length of addr. + * @param zone: delegation point name. + * @param zonelen: length of zone name. + * @param q: wich query state to reactivate upon return. + * @return: false on failure (memory or socket related). no query was + * sent. Or returns an outbound entry with qsent and qstate set. + * This outbound_entry will be used on later module invocations + * that involve this query (timeout, error or reply). + */ + 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, struct sockaddr_storage* addr, + socklen_t addrlen, uint8_t* zone, size_t zonelen, + struct module_qstate* q); + + /** + * Detach-subqueries. + * Remove all sub-query references from this query state. + * Keeps super-references of those sub-queries correct. + * Updates stat items in mesh_area structure. + * @param qstate: used to find mesh state. + */ + void (*detach_subs)(struct module_qstate* qstate); + + /** + * Attach subquery. + * Creates it if it does not exist already. + * Keeps sub and super references correct. + * Updates stat items in mesh_area structure. + * Pass if it is priming query or not. + * return: + * o if error (malloc) happened. + * o need to initialise the new state (module init; it is a new state). + * so that the next run of the query with this module is successful. + * o no init needed, attachment successful. + * + * @param qstate: the state to find mesh state, and that wants to + * receive the results from the new subquery. + * @param qinfo: what to query for (copied). + * @param qflags: what flags to use (RD, CD flag or not). + * @param prime: if it is a (stub) priming query. + * @param newq: If the new subquery needs initialisation, it is + * returned, otherwise NULL is returned. + * @return: false on error, true if success (and init may be needed). + */ + int (*attach_sub)(struct module_qstate* qstate, + struct query_info* qinfo, uint16_t qflags, int prime, + struct module_qstate** newq); + + /** + * Kill newly attached sub. If attach_sub returns newq for + * initialisation, but that fails, then this routine will cleanup and + * delete the fresly created sub. + * @param newq: the new subquery that is no longer needed. + * It is removed. + */ + void (*kill_sub)(struct module_qstate* newq); + + /** + * Detect if adding a dependency for qstate on name,type,class will + * create a dependency cycle. + * @param qstate: given mesh querystate. + * @param qinfo: query info for dependency. + * @param flags: query flags of dependency, RD/CD flags. + * @param prime: if dependency is a priming query or not. + * @return true if the name,type,class exists and the given + * qstate mesh exists as a dependency of that name. Thus + * if qstate becomes dependent on name,type,class then a + * cycle is created. + */ + int (*detect_cycle)(struct module_qstate* qstate, + struct query_info* qinfo, uint16_t flags, int prime); + + /** region for temporary usage. May be cleared after operate() call. */ + struct regional* scratch; + /** buffer for temporary usage. May be cleared after operate() call. */ + ldns_buffer* scratch_buffer; + /** internal data for daemon - worker thread. */ + struct worker* worker; + /** mesh area with query state dependencies */ + struct mesh_area* mesh; + /** allocation service */ + struct alloc_cache* alloc; + /** random table to generate random numbers */ + struct ub_randstate* rnd; + /** time in seconds, converted to integer */ + uint32_t* now; + /** time in microseconds. Relatively recent. */ + struct timeval* now_tv; + /** is validation required for messages, controls client-facing + * validation status (AD bits) and servfails */ + int need_to_validate; + /** trusted key storage; these are the configured keys, if not NULL, + * otherwise configured by validator. These are the trust anchors, + * and are not primed and ready for validation, but on the bright + * side, they are read only memory, thus no locks and fast. */ + struct val_anchors* anchors; + /** negative cache, configured by the validator. if not NULL, + * contains NSEC record lookup trees. */ + struct val_neg_cache* neg_cache; + /** the 5011-probe timer (if any) */ + struct comm_timer* probe_timer; + /** Mapping of forwarding zones to targets. + * iterator forwarder information. per-thread, created by worker */ + struct iter_forwards* fwds; + /** + * iterator forwarder information. per-thread, created by worker. + * The hints -- these aren't stored in the cache because they don't + * expire. The hints are always used to "prime" the cache. Note + * that both root hints and stub zone "hints" are stored in this + * data structure. + */ + struct iter_hints* hints; + /** module specific data. indexed by module id. */ + void* modinfo[MAX_MODULE]; +}; + +/** + * External visible states of the module state machine + * Modules may also have an internal state. + * Modules are supposed to run to completion or until blocked. + */ +enum module_ext_state { + /** initial state - new query */ + module_state_initial = 0, + /** waiting for reply to outgoing network query */ + module_wait_reply, + /** module is waiting for another module */ + module_wait_module, + /** module is waiting for another module; that other is restarted */ + module_restart_next, + /** module is waiting for sub-query */ + module_wait_subquery, + /** module could not finish the query */ + module_error, + /** module is finished with query */ + module_finished +}; + +/** + * Events that happen to modules, that start or wakeup modules. + */ +enum module_ev { + /** new query */ + module_event_new = 0, + /** query passed by other module */ + module_event_pass, + /** reply inbound from server */ + module_event_reply, + /** no reply, timeout or other error */ + module_event_noreply, + /** reply is there, but capitalisation check failed */ + module_event_capsfail, + /** next module is done, and its reply is awaiting you */ + module_event_moddone, + /** error */ + module_event_error +}; + +/** + * Linked list of sockaddrs + * May be allocated such that only 'len' bytes of addr exist for the structure. + */ +struct sock_list { + /** next in list */ + struct sock_list* next; + /** length of addr */ + socklen_t len; + /** sockaddr */ + struct sockaddr_storage addr; +}; + +/** + * Module state, per query. + */ +struct module_qstate { + /** which query is being answered: name, type, class */ + struct query_info qinfo; + /** flags uint16 from query */ + uint16_t query_flags; + /** if this is a (stub or root) priming query (with hints) */ + int is_priming; + + /** comm_reply contains server replies */ + struct comm_reply* reply; + /** the reply message, with message for client and calling module */ + struct dns_msg* return_msg; + /** the rcode, in case of error, instead of a reply message */ + int return_rcode; + /** origin of the reply (can be NULL from cache, list for cnames) */ + struct sock_list* reply_origin; + /** IP blacklist for queries */ + struct sock_list* blacklist; + /** region for this query. Cleared when query process finishes. */ + struct regional* region; + /** failure reason information if val-log-level is high */ + struct config_strlist* errinf; + + /** which module is executing */ + int curmod; + /** module states */ + enum module_ext_state ext_state[MAX_MODULE]; + /** module specific data for query. indexed by module id. */ + void* minfo[MAX_MODULE]; + /** environment for this query */ + struct module_env* env; + /** mesh related information for this query */ + struct mesh_state* mesh_info; + /** how many seconds before expiry is this prefetched (0 if not) */ + uint32_t prefetch_leeway; +}; + +/** + * Module functionality block + */ +struct module_func_block { + /** text string name of module */ + const char* name; + + /** + * init the module. Called once for the global state. + * This is the place to apply settings from the config file. + * @param env: module environment. + * @param id: module id number. + * return: 0 on error + */ + int (*init)(struct module_env* env, int id); + + /** + * de-init, delete, the module. Called once for the global state. + * @param env: module environment. + * @param id: module id number. + */ + void (*deinit)(struct module_env* env, int id); + + /** + * accept a new query, or work further on existing query. + * Changes the qstate->ext_state to be correct on exit. + * @param ev: event that causes the module state machine to + * (re-)activate. + * @param qstate: the query state. + * Note that this method is not allowed to change the + * query state 'identity', that is query info, qflags, + * and priming status. + * Attach a subquery to get results to a different query. + * @param id: module id number that operate() is called on. + * @param outbound: if not NULL this event is due to the reply/timeout + * or error on this outbound query. + * @return: if at exit the ext_state is: + * o wait_module: next module is started. (with pass event). + * o error or finished: previous module is resumed. + * o otherwise it waits until that event happens (assumes + * the service routine to make subrequest or send message + * have been called. + */ + void (*operate)(struct module_qstate* qstate, enum module_ev event, + int id, struct outbound_entry* outbound); + + /** + * inform super querystate about the results from this subquerystate. + * Is called when the querystate is finished. The method invoked is + * the one from the current module active in the super querystate. + * @param qstate: the query state that is finished. + * Examine return_rcode and return_reply in the qstate. + * @param id: module id for this module. + * This coincides with the current module for the super qstate. + * @param super: the super querystate that needs to be informed. + */ + void (*inform_super)(struct module_qstate* qstate, int id, + struct module_qstate* super); + + /** + * clear module specific data + */ + void (*clear)(struct module_qstate* qstate, int id); + + /** + * How much memory is the module specific data using. + * @param env: module environment. + * @param id: the module id. + * @return the number of bytes that are alloced. + */ + size_t (*get_mem)(struct module_env* env, int id); +}; + +/** + * Debug utility: module external qstate to string + * @param s: the state value. + * @return descriptive string. + */ +const char* strextstate(enum module_ext_state s); + +/** + * Debug utility: module event to string + * @param e: the module event value. + * @return descriptive string. + */ +const char* strmodulevent(enum module_ev e); + +#endif /* UTIL_MODULE_H */ diff --git a/util/net_help.c b/util/net_help.c new file mode 100644 index 00000000000..6be5fcc3132 --- /dev/null +++ b/util/net_help.c @@ -0,0 +1,699 @@ +/* + * util/net_help.c - implementation of the network helper code + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \file + * Implementation of net_help.h. + */ + +#include "config.h" +#include +#include "util/net_help.h" +#include "util/log.h" +#include "util/data/dname.h" +#include "util/module.h" +#include "util/regional.h" +#include +#include +#include + +/** max length of an IP address (the address portion) that we allow */ +#define MAX_ADDR_STRLEN 128 /* characters */ +/** default value for EDNS ADVERTISED size */ +uint16_t EDNS_ADVERTISED_SIZE = 4096; + +/** minimal responses when positive answer: default is no */ +int MINIMAL_RESPONSES = 0; + +/** rrset order roundrobin: default is no */ +int RRSET_ROUNDROBIN = 0; + +/* returns true is string addr is an ip6 specced address */ +int +str_is_ip6(const char* str) +{ + if(strchr(str, ':')) + return 1; + else return 0; +} + +int +fd_set_nonblock(int s) +{ +#ifdef HAVE_FCNTL + int flag; + if((flag = fcntl(s, F_GETFL)) == -1) { + log_err("can't fcntl F_GETFL: %s", strerror(errno)); + flag = 0; + } + flag |= O_NONBLOCK; + if(fcntl(s, F_SETFL, flag) == -1) { + log_err("can't fcntl F_SETFL: %s", strerror(errno)); + return 0; + } +#elif defined(HAVE_IOCTLSOCKET) + unsigned long on = 1; + if(ioctlsocket(s, FIONBIO, &on) != 0) { + log_err("can't ioctlsocket FIONBIO on: %s", + wsa_strerror(WSAGetLastError())); + } +#endif + return 1; +} + +int +fd_set_block(int s) +{ +#ifdef HAVE_FCNTL + int flag; + if((flag = fcntl(s, F_GETFL)) == -1) { + log_err("cannot fcntl F_GETFL: %s", strerror(errno)); + flag = 0; + } + flag &= ~O_NONBLOCK; + if(fcntl(s, F_SETFL, flag) == -1) { + log_err("cannot fcntl F_SETFL: %s", strerror(errno)); + return 0; + } +#elif defined(HAVE_IOCTLSOCKET) + unsigned long off = 0; + if(ioctlsocket(s, FIONBIO, &off) != 0) { + log_err("can't ioctlsocket FIONBIO off: %s", + wsa_strerror(WSAGetLastError())); + } +#endif + return 1; +} + +int +is_pow2(size_t num) +{ + if(num == 0) return 1; + return (num & (num-1)) == 0; +} + +void* +memdup(void* data, size_t len) +{ + void* d; + if(!data) return NULL; + if(len == 0) return NULL; + d = malloc(len); + if(!d) return NULL; + memcpy(d, data, len); + return d; +} + +void +log_addr(enum verbosity_value v, const char* str, + struct sockaddr_storage* addr, socklen_t addrlen) +{ + uint16_t port; + const char* family = "unknown"; + char dest[100]; + int af = (int)((struct sockaddr_in*)addr)->sin_family; + void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; + if(verbosity < v) + return; + switch(af) { + case AF_INET: family="ip4"; break; + case AF_INET6: family="ip6"; + sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; + break; + case AF_UNIX: family="unix"; break; + default: break; + } + if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) { + strncpy(dest, "(inet_ntop error)", sizeof(dest)); + } + dest[sizeof(dest)-1] = 0; + port = ntohs(((struct sockaddr_in*)addr)->sin_port); + if(verbosity >= 4) + verbose(v, "%s %s %s port %d (len %d)", str, family, dest, + (int)port, (int)addrlen); + else verbose(v, "%s %s port %d", str, dest, (int)port); +} + +int +extstrtoaddr(const char* str, struct sockaddr_storage* addr, + socklen_t* addrlen) +{ + char* s; + int port = UNBOUND_DNS_PORT; + if((s=strchr(str, '@'))) { + char buf[MAX_ADDR_STRLEN]; + if(s-str >= MAX_ADDR_STRLEN) { + return 0; + } + strncpy(buf, str, MAX_ADDR_STRLEN); + buf[s-str] = 0; + port = atoi(s+1); + if(port == 0 && strcmp(s+1,"0")!=0) { + return 0; + } + return ipstrtoaddr(buf, port, addr, addrlen); + } + return ipstrtoaddr(str, port, addr, addrlen); +} + + +int +ipstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr, + socklen_t* addrlen) +{ + uint16_t p; + if(!ip) return 0; + p = (uint16_t) port; + if(str_is_ip6(ip)) { + char buf[MAX_ADDR_STRLEN]; + char* s; + struct sockaddr_in6* sa = (struct sockaddr_in6*)addr; + *addrlen = (socklen_t)sizeof(struct sockaddr_in6); + memset(sa, 0, *addrlen); + sa->sin6_family = AF_INET6; + sa->sin6_port = (in_port_t)htons(p); + if((s=strchr(ip, '%'))) { /* ip6%interface, rfc 4007 */ + if(s-ip >= MAX_ADDR_STRLEN) + return 0; + strncpy(buf, ip, MAX_ADDR_STRLEN); + buf[s-ip]=0; + sa->sin6_scope_id = (uint32_t)atoi(s+1); + ip = buf; + } + if(inet_pton((int)sa->sin6_family, ip, &sa->sin6_addr) <= 0) { + return 0; + } + } else { /* ip4 */ + struct sockaddr_in* sa = (struct sockaddr_in*)addr; + *addrlen = (socklen_t)sizeof(struct sockaddr_in); + memset(sa, 0, *addrlen); + sa->sin_family = AF_INET; + sa->sin_port = (in_port_t)htons(p); + if(inet_pton((int)sa->sin_family, ip, &sa->sin_addr) <= 0) { + return 0; + } + } + return 1; +} + +int netblockstrtoaddr(const char* str, int port, struct sockaddr_storage* addr, + socklen_t* addrlen, int* net) +{ + char* s = NULL; + *net = (str_is_ip6(str)?128:32); + if((s=strchr(str, '/'))) { + if(atoi(s+1) > *net) { + log_err("netblock too large: %s", str); + return 0; + } + *net = atoi(s+1); + if(*net == 0 && strcmp(s+1, "0") != 0) { + log_err("cannot parse netblock: '%s'", str); + return 0; + } + if(!(s = strdup(str))) { + log_err("out of memory"); + return 0; + } + *strchr(s, '/') = '\0'; + } + if(!ipstrtoaddr(s?s:str, port, addr, addrlen)) { + free(s); + log_err("cannot parse ip address: '%s'", str); + return 0; + } + if(s) { + free(s); + addr_mask(addr, *addrlen, *net); + } + return 1; +} + +void +log_nametypeclass(enum verbosity_value v, const char* str, uint8_t* name, + uint16_t type, uint16_t dclass) +{ + char buf[LDNS_MAX_DOMAINLEN+1]; + char t[12], c[12]; + const char *ts, *cs; + if(verbosity < v) + return; + dname_str(name, buf); + if(type == LDNS_RR_TYPE_TSIG) ts = "TSIG"; + else if(type == LDNS_RR_TYPE_IXFR) ts = "IXFR"; + else if(type == LDNS_RR_TYPE_AXFR) ts = "AXFR"; + else if(type == LDNS_RR_TYPE_MAILB) ts = "MAILB"; + else if(type == LDNS_RR_TYPE_MAILA) ts = "MAILA"; + else if(type == LDNS_RR_TYPE_ANY) ts = "ANY"; + else if(ldns_rr_descript(type) && ldns_rr_descript(type)->_name) + ts = ldns_rr_descript(type)->_name; + else { + snprintf(t, sizeof(t), "TYPE%d", (int)type); + ts = t; + } + if(ldns_lookup_by_id(ldns_rr_classes, (int)dclass) && + ldns_lookup_by_id(ldns_rr_classes, (int)dclass)->name) + cs = ldns_lookup_by_id(ldns_rr_classes, (int)dclass)->name; + else { + snprintf(c, sizeof(c), "CLASS%d", (int)dclass); + cs = c; + } + log_info("%s %s %s %s", str, buf, ts, cs); +} + +void log_name_addr(enum verbosity_value v, const char* str, uint8_t* zone, + struct sockaddr_storage* addr, socklen_t addrlen) +{ + uint16_t port; + const char* family = "unknown_family "; + char namebuf[LDNS_MAX_DOMAINLEN+1]; + char dest[100]; + int af = (int)((struct sockaddr_in*)addr)->sin_family; + void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; + if(verbosity < v) + return; + switch(af) { + case AF_INET: family=""; break; + case AF_INET6: family=""; + sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; + break; + case AF_UNIX: family="unix_family "; break; + default: break; + } + if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) { + strncpy(dest, "(inet_ntop error)", sizeof(dest)); + } + dest[sizeof(dest)-1] = 0; + port = ntohs(((struct sockaddr_in*)addr)->sin_port); + dname_str(zone, namebuf); + if(af != AF_INET && af != AF_INET6) + verbose(v, "%s <%s> %s%s#%d (addrlen %d)", + str, namebuf, family, dest, (int)port, (int)addrlen); + else verbose(v, "%s <%s> %s%s#%d", + str, namebuf, family, dest, (int)port); +} + +int +sockaddr_cmp(struct sockaddr_storage* addr1, socklen_t len1, + struct sockaddr_storage* addr2, socklen_t len2) +{ + struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1; + struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2; + struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1; + struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2; + if(len1 < len2) + return -1; + if(len1 > len2) + return 1; + log_assert(len1 == len2); + if( p1_in->sin_family < p2_in->sin_family) + return -1; + if( p1_in->sin_family > p2_in->sin_family) + return 1; + log_assert( p1_in->sin_family == p2_in->sin_family ); + /* compare ip4 */ + if( p1_in->sin_family == AF_INET ) { + /* just order it, ntohs not required */ + if(p1_in->sin_port < p2_in->sin_port) + return -1; + if(p1_in->sin_port > p2_in->sin_port) + return 1; + log_assert(p1_in->sin_port == p2_in->sin_port); + return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE); + } else if (p1_in6->sin6_family == AF_INET6) { + /* just order it, ntohs not required */ + if(p1_in6->sin6_port < p2_in6->sin6_port) + return -1; + if(p1_in6->sin6_port > p2_in6->sin6_port) + return 1; + log_assert(p1_in6->sin6_port == p2_in6->sin6_port); + return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr, + INET6_SIZE); + } else { + /* eek unknown type, perform this comparison for sanity. */ + return memcmp(addr1, addr2, len1); + } +} + +int +sockaddr_cmp_addr(struct sockaddr_storage* addr1, socklen_t len1, + struct sockaddr_storage* addr2, socklen_t len2) +{ + struct sockaddr_in* p1_in = (struct sockaddr_in*)addr1; + struct sockaddr_in* p2_in = (struct sockaddr_in*)addr2; + struct sockaddr_in6* p1_in6 = (struct sockaddr_in6*)addr1; + struct sockaddr_in6* p2_in6 = (struct sockaddr_in6*)addr2; + if(len1 < len2) + return -1; + if(len1 > len2) + return 1; + log_assert(len1 == len2); + if( p1_in->sin_family < p2_in->sin_family) + return -1; + if( p1_in->sin_family > p2_in->sin_family) + return 1; + log_assert( p1_in->sin_family == p2_in->sin_family ); + /* compare ip4 */ + if( p1_in->sin_family == AF_INET ) { + return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE); + } else if (p1_in6->sin6_family == AF_INET6) { + return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr, + INET6_SIZE); + } else { + /* eek unknown type, perform this comparison for sanity. */ + return memcmp(addr1, addr2, len1); + } +} + +int +addr_is_ip6(struct sockaddr_storage* addr, socklen_t len) +{ + if(len == (socklen_t)sizeof(struct sockaddr_in6) && + ((struct sockaddr_in6*)addr)->sin6_family == AF_INET6) + return 1; + else return 0; +} + +void +addr_mask(struct sockaddr_storage* addr, socklen_t len, int net) +{ + uint8_t mask[8] = {0x0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe}; + int i, max; + uint8_t* s; + if(addr_is_ip6(addr, len)) { + s = (uint8_t*)&((struct sockaddr_in6*)addr)->sin6_addr; + max = 128; + } else { + s = (uint8_t*)&((struct sockaddr_in*)addr)->sin_addr; + max = 32; + } + if(net >= max) + return; + for(i=net/8+1; isin6_addr; + s2 = (uint8_t*)&((struct sockaddr_in6*)addr2)->sin6_addr; + to = 16; + } else { + s1 = (uint8_t*)&((struct sockaddr_in*)addr1)->sin_addr; + s2 = (uint8_t*)&((struct sockaddr_in*)addr2)->sin_addr; + to = 4; + } + /* match = bits_in_common(s1, s2, to); */ + for(i=0; i min) match = min; + return match; +} + +void +addr_to_str(struct sockaddr_storage* addr, socklen_t addrlen, + char* buf, size_t len) +{ + int af = (int)((struct sockaddr_in*)addr)->sin_family; + void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; + if(addr_is_ip6(addr, addrlen)) + sinaddr = &((struct sockaddr_in6*)addr)->sin6_addr; + if(inet_ntop(af, sinaddr, buf, (socklen_t)len) == 0) { + snprintf(buf, len, "(inet_ntop_error)"); + } +} + +int +addr_is_ip4mapped(struct sockaddr_storage* addr, socklen_t addrlen) +{ + /* prefix for ipv4 into ipv6 mapping is ::ffff:x.x.x.x */ + const uint8_t map_prefix[16] = + {0,0,0,0, 0,0,0,0, 0,0,0xff,0xff, 0,0,0,0}; + uint8_t* s; + if(!addr_is_ip6(addr, addrlen)) + return 0; + /* s is 16 octet ipv6 address string */ + s = (uint8_t*)&((struct sockaddr_in6*)addr)->sin6_addr; + return (memcmp(s, map_prefix, 12) == 0); +} + +int addr_is_broadcast(struct sockaddr_storage* addr, socklen_t addrlen) +{ + int af = (int)((struct sockaddr_in*)addr)->sin_family; + void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; + return af == AF_INET && addrlen>=(socklen_t)sizeof(struct sockaddr_in) + && memcmp(sinaddr, "\377\377\377\377", 4) == 0; +} + +int addr_is_any(struct sockaddr_storage* addr, socklen_t addrlen) +{ + int af = (int)((struct sockaddr_in*)addr)->sin_family; + void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr; + void* sin6addr = &((struct sockaddr_in6*)addr)->sin6_addr; + if(af == AF_INET && addrlen>=(socklen_t)sizeof(struct sockaddr_in) + && memcmp(sinaddr, "\000\000\000\000", 4) == 0) + return 1; + else if(af==AF_INET6 && addrlen>=(socklen_t)sizeof(struct sockaddr_in6) + && memcmp(sin6addr, "\000\000\000\000\000\000\000\000" + "\000\000\000\000\000\000\000\000", 16) == 0) + return 1; + return 0; +} + +void sock_list_insert(struct sock_list** list, struct sockaddr_storage* addr, + socklen_t len, struct regional* region) +{ + struct sock_list* add = (struct sock_list*)regional_alloc(region, + sizeof(*add) - sizeof(add->addr) + (size_t)len); + if(!add) { + log_err("out of memory in socketlist insert"); + return; + } + log_assert(list); + add->next = *list; + add->len = len; + *list = add; + if(len) memmove(&add->addr, addr, len); +} + +void sock_list_prepend(struct sock_list** list, struct sock_list* add) +{ + struct sock_list* last = add; + if(!last) + return; + while(last->next) + last = last->next; + last->next = *list; + *list = add; +} + +int sock_list_find(struct sock_list* list, struct sockaddr_storage* addr, + socklen_t len) +{ + while(list) { + if(len == list->len) { + if(len == 0 || sockaddr_cmp_addr(addr, len, + &list->addr, list->len) == 0) + return 1; + } + list = list->next; + } + return 0; +} + +void sock_list_merge(struct sock_list** list, struct regional* region, + struct sock_list* add) +{ + struct sock_list* p; + for(p=add; p; p=p->next) { + if(!sock_list_find(*list, &p->addr, p->len)) + sock_list_insert(list, &p->addr, p->len, region); + } +} + +void +log_crypto_err(const char* str) +{ + /* error:[error code]:[library name]:[function name]:[reason string] */ + char buf[128]; + unsigned long e; + ERR_error_string_n(ERR_get_error(), buf, sizeof(buf)); + log_err("%s crypto %s", str, buf); + while( (e=ERR_get_error()) ) { + ERR_error_string_n(e, buf, sizeof(buf)); + log_err("and additionally crypto %s", buf); + } +} + +void* listen_sslctx_create(char* key, char* pem, char* verifypem) +{ + SSL_CTX* ctx = SSL_CTX_new(SSLv23_server_method()); + if(!ctx) { + log_crypto_err("could not SSL_CTX_new"); + return NULL; + } + /* no SSLv2 because has defects */ + if(!(SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)){ + log_crypto_err("could not set SSL_OP_NO_SSLv2"); + SSL_CTX_free(ctx); + return NULL; + } + if(!SSL_CTX_use_certificate_file(ctx, pem, SSL_FILETYPE_PEM)) { + log_err("error for cert file: %s", pem); + log_crypto_err("error in SSL_CTX use_certificate_file"); + SSL_CTX_free(ctx); + return NULL; + } + if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) { + log_err("error for private key file: %s", key); + log_crypto_err("Error in SSL_CTX use_PrivateKey_file"); + SSL_CTX_free(ctx); + return NULL; + } + if(!SSL_CTX_check_private_key(ctx)) { + log_err("error for key file: %s", key); + log_crypto_err("Error in SSL_CTX check_private_key"); + SSL_CTX_free(ctx); + return NULL; + } + + if(verifypem && verifypem[0]) { + if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) { + log_crypto_err("Error in SSL_CTX verify locations"); + SSL_CTX_free(ctx); + return NULL; + } + SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file( + verifypem)); + SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); + } + return ctx; +} + +void* connect_sslctx_create(char* key, char* pem, char* verifypem) +{ + SSL_CTX* ctx = SSL_CTX_new(SSLv23_client_method()); + if(!ctx) { + log_crypto_err("could not allocate SSL_CTX pointer"); + return NULL; + } + if(!(SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)) { + log_crypto_err("could not set SSL_OP_NO_SSLv2"); + SSL_CTX_free(ctx); + return NULL; + } + if(key && key[0]) { + if(!SSL_CTX_use_certificate_file(ctx, pem, SSL_FILETYPE_PEM)) { + log_err("error in client certificate %s", pem); + log_crypto_err("error in certificate file"); + SSL_CTX_free(ctx); + return NULL; + } + if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) { + log_err("error in client private key %s", key); + log_crypto_err("error in key file"); + SSL_CTX_free(ctx); + return NULL; + } + if(!SSL_CTX_check_private_key(ctx)) { + log_err("error in client key %s", key); + log_crypto_err("error in SSL_CTX_check_private_key"); + SSL_CTX_free(ctx); + return NULL; + } + } + if(verifypem && verifypem[0]) { + if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL) != 1) { + log_crypto_err("error in SSL_CTX verify"); + SSL_CTX_free(ctx); + return NULL; + } + SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); + } + return ctx; +} + +void* incoming_ssl_fd(void* sslctx, int fd) +{ + SSL* ssl = SSL_new((SSL_CTX*)sslctx); + if(!ssl) { + log_crypto_err("could not SSL_new"); + return NULL; + } + SSL_set_accept_state(ssl); + (void)SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); + if(!SSL_set_fd(ssl, fd)) { + log_crypto_err("could not SSL_set_fd"); + SSL_free(ssl); + return NULL; + } + return ssl; +} + +void* outgoing_ssl_fd(void* sslctx, int fd) +{ + SSL* ssl = SSL_new((SSL_CTX*)sslctx); + if(!ssl) { + log_crypto_err("could not SSL_new"); + return NULL; + } + SSL_set_connect_state(ssl); + (void)SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); + if(!SSL_set_fd(ssl, fd)) { + log_crypto_err("could not SSL_set_fd"); + SSL_free(ssl); + return NULL; + } + return ssl; +} diff --git a/util/net_help.h b/util/net_help.h new file mode 100644 index 00000000000..e0c0ebea175 --- /dev/null +++ b/util/net_help.h @@ -0,0 +1,372 @@ +/* + * util/net_help.h - network help 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions to perform network related tasks. + */ + +#ifndef NET_HELP_H +#define NET_HELP_H +#include "util/log.h" +struct sock_list; +struct regional; + +/** DNS constants for uint16_t style flag manipulation. host byteorder. + * 1 1 1 1 1 1 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * |QR| Opcode |AA|TC|RD|RA| Z|AD|CD| RCODE | + * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + */ +/** CD flag */ +#define BIT_CD 0x0010 +/** AD flag */ +#define BIT_AD 0x0020 +/** Z flag */ +#define BIT_Z 0x0040 +/** RA flag */ +#define BIT_RA 0x0080 +/** RD flag */ +#define BIT_RD 0x0100 +/** TC flag */ +#define BIT_TC 0x0200 +/** AA flag */ +#define BIT_AA 0x0400 +/** QR flag */ +#define BIT_QR 0x8000 +/** get RCODE bits from uint16 flags */ +#define FLAGS_GET_RCODE(f) ((f) & 0xf) +/** set RCODE bits in uint16 flags */ +#define FLAGS_SET_RCODE(f, r) (f = (((f) & 0xfff0) | (r))) + +/** timeout in seconds for UDP queries to auth servers. */ +#define UDP_AUTH_QUERY_TIMEOUT 4 +/** timeout in seconds for TCP queries to auth servers. */ +#define TCP_AUTH_QUERY_TIMEOUT 30 +/** Advertised version of EDNS capabilities */ +#define EDNS_ADVERTISED_VERSION 0 +/** Advertised size of EDNS capabilities */ +extern uint16_t EDNS_ADVERTISED_SIZE; +/** bits for EDNS bitfield */ +#define EDNS_DO 0x8000 /* Dnssec Ok */ +/** byte size of ip4 address */ +#define INET_SIZE 4 +/** byte size of ip6 address */ +#define INET6_SIZE 16 + +/** DNSKEY zone sign key flag */ +#define DNSKEY_BIT_ZSK 0x0100 +/** DNSKEY secure entry point, KSK flag */ +#define DNSKEY_BIT_SEP 0x0001 + +/** minimal responses when positive answer */ +extern int MINIMAL_RESPONSES; + +/** rrset order roundrobin */ +extern int RRSET_ROUNDROBIN; + +/** + * See if string is ip4 or ip6. + * @param str: IP specification. + * @return: true if string addr is an ip6 specced address. + */ +int str_is_ip6(const char* str); + +/** + * Set fd nonblocking. + * @param s: file descriptor. + * @return: 0 on error (error is printed to log). + */ +int fd_set_nonblock(int s); + +/** + * Set fd (back to) blocking. + * @param s: file descriptor. + * @return: 0 on error (error is printed to log). + */ +int fd_set_block(int s); + +/** + * See if number is a power of 2. + * @param num: the value. + * @return: true if the number is a power of 2. + */ +int is_pow2(size_t num); + +/** + * Allocate memory and copy over contents. + * @param data: what to copy over. + * @param len: length of data. + * @return: NULL on malloc failure, or newly malloced data. + */ +void* memdup(void* data, size_t len); + +/** + * Prints the sockaddr in readable format with log_info. Debug helper. + * @param v: at what verbosity level to print this. + * @param str: descriptive string printed with it. + * @param addr: the sockaddr to print. Can be ip4 or ip6. + * @param addrlen: length of addr. + */ +void log_addr(enum verbosity_value v, const char* str, + struct sockaddr_storage* addr, socklen_t addrlen); + +/** + * Prints zone name and sockaddr in readable format with log_info. Debug. + * @param v: at what verbosity level to print this. + * @param str: descriptive string printed with it. + * @param zone: DNS domain name, uncompressed wireformat. + * @param addr: the sockaddr to print. Can be ip4 or ip6. + * @param addrlen: length of addr. + */ +void log_name_addr(enum verbosity_value v, const char* str, uint8_t* zone, + struct sockaddr_storage* addr, socklen_t addrlen); + +/** + * Convert address string, with "@port" appendix, to sockaddr. + * Uses DNS port by default. + * @param str: the string + * @param addr: where to store sockaddr. + * @param addrlen: length of stored sockaddr is returned. + * @return 0 on error. + */ +int extstrtoaddr(const char* str, struct sockaddr_storage* addr, + socklen_t* addrlen); + +/** + * Convert ip address string and port to sockaddr. + * @param ip: ip4 or ip6 address string. + * @param port: port number, host format. + * @param addr: where to store sockaddr. + * @param addrlen: length of stored sockaddr is returned. + * @return 0 on error. + */ +int ipstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr, + socklen_t* addrlen); + +/** + * Convert ip netblock (ip/netsize) string and port to sockaddr. + * *SLOW*, does a malloc internally to avoid writing over 'ip' string. + * @param ip: ip4 or ip6 address string. + * @param port: port number, host format. + * @param addr: where to store sockaddr. + * @param addrlen: length of stored sockaddr is returned. + * @param net: netblock size is returned. + * @return 0 on error. + */ +int netblockstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr, + socklen_t* addrlen, int* net); + +/** + * Print string with neat domain name, type and class. + * @param v: at what verbosity level to print this. + * @param str: string of message. + * @param name: domain name uncompressed wireformat. + * @param type: host format RR type. + * @param dclass: host format RR class. + */ +void log_nametypeclass(enum verbosity_value v, const char* str, + uint8_t* name, uint16_t type, uint16_t dclass); + +/** + * Compare two sockaddrs. Imposes an ordering on the addresses. + * Compares address and port. + * @param addr1: address 1. + * @param len1: lengths of addr1. + * @param addr2: address 2. + * @param len2: lengths of addr2. + * @return: 0 if addr1 == addr2. -1 if addr1 is smaller, +1 if larger. + */ +int sockaddr_cmp(struct sockaddr_storage* addr1, socklen_t len1, + struct sockaddr_storage* addr2, socklen_t len2); + +/** + * Compare two sockaddrs. Compares address, not the port. + * @param addr1: address 1. + * @param len1: lengths of addr1. + * @param addr2: address 2. + * @param len2: lengths of addr2. + * @return: 0 if addr1 == addr2. -1 if addr1 is smaller, +1 if larger. + */ +int sockaddr_cmp_addr(struct sockaddr_storage* addr1, socklen_t len1, + struct sockaddr_storage* addr2, socklen_t len2); + +/** + * Checkout address family. + * @param addr: the sockaddr to examine. + * @param len: the length of addr. + * @return: true if sockaddr is ip6. + */ +int addr_is_ip6(struct sockaddr_storage* addr, socklen_t len); + +/** + * Make sure the sockaddr ends in zeroes. For tree insertion and subsequent + * comparison. + * @param addr: the ip4 or ip6 addr. + * @param len: length of addr. + * @param net: number of bits to leave untouched, the rest of the netblock + * address is zeroed. + */ +void addr_mask(struct sockaddr_storage* addr, socklen_t len, int net); + +/** + * See how many bits are shared, equal, between two addrs. + * @param addr1: first addr. + * @param net1: netblock size of first addr. + * @param addr2: second addr. + * @param net2: netblock size of second addr. + * @param addrlen: length of first addr and of second addr. + * They must be of the same length (i.e. same type IP4, IP6). + * @return: number of bits the same. + */ +int addr_in_common(struct sockaddr_storage* addr1, int net1, + struct sockaddr_storage* addr2, int net2, socklen_t addrlen); + +/** + * Put address into string, works for IPv4 and IPv6. + * @param addr: address + * @param addrlen: length of address + * @param buf: result string stored here + * @param len: length of buf. + * On failure a string with "error" is stored inside. + */ +void addr_to_str(struct sockaddr_storage* addr, socklen_t addrlen, + char* buf, size_t len); + +/** + * See if sockaddr is an ipv6 mapped ipv4 address, "::ffff:0.0.0.0" + * @param addr: address + * @param addrlen: length of address + * @return true if so + */ +int addr_is_ip4mapped(struct sockaddr_storage* addr, socklen_t addrlen); + +/** + * See if sockaddr is 255.255.255.255. + * @param addr: address + * @param addrlen: length of address + * @return true if so + */ +int addr_is_broadcast(struct sockaddr_storage* addr, socklen_t addrlen); + +/** + * See if sockaddr is 0.0.0.0 or ::0. + * @param addr: address + * @param addrlen: length of address + * @return true if so + */ +int addr_is_any(struct sockaddr_storage* addr, socklen_t addrlen); + +/** + * Insert new socket list item. If fails logs error. + * @param list: pointer to pointer to first item. + * @param addr: address or NULL if 'cache'. + * @param len: length of addr, or 0 if 'cache'. + * @param region: where to allocate + */ +void sock_list_insert(struct sock_list** list, struct sockaddr_storage* addr, + socklen_t len, struct regional* region); + +/** + * Append one list to another. Must both be from same qstate(regional). + * @param list: pointer to result list that is modified. + * @param add: item(s) to add. They are prepended to list. + */ +void sock_list_prepend(struct sock_list** list, struct sock_list* add); + +/** + * Find addr in list. + * @param list: to search in + * @param addr: address to look for. + * @param len: length. Can be 0, look for 'cache entry'. + * @return true if found. + */ +int sock_list_find(struct sock_list* list, struct sockaddr_storage* addr, + socklen_t len); + +/** + * Merge socklist into another socket list. Allocates the new entries + * freshly and copies them over, so also performs a region switchover. + * Allocation failures are logged. + * @param list: the destination list (checked for duplicates) + * @param region: where to allocate + * @param add: the list of entries to add. + */ +void sock_list_merge(struct sock_list** list, struct regional* region, + struct sock_list* add); + +/** + * Log libcrypto error with descriptive string. Calls log_err(). + * @param str: what failed. + */ +void log_crypto_err(const char* str); + +/** + * create SSL listen context + * @param key: private key file. + * @param pem: public key cert. + * @param verifypem: if nonNULL, verifylocation file. + * return SSL_CTX* or NULL on failure (logged). + */ +void* listen_sslctx_create(char* key, char* pem, char* verifypem); + +/** + * create SSL connect context + * @param key: if nonNULL (also pem nonNULL), the client private key. + * @param pem: client public key (or NULL if key is NULL). + * @param verifypem: if nonNULL used for verifylocation file. + * @return SSL_CTX* or NULL on failure (logged). + */ +void* connect_sslctx_create(char* key, char* pem, char* verifypem); + +/** + * accept a new fd and wrap it in a BIO in SSL + * @param sslctx: the SSL_CTX to use (from listen_sslctx_create()). + * @param fd: from accept, nonblocking. + * @return SSL or NULL on alloc failure. + */ +void* incoming_ssl_fd(void* sslctx, int fd); + +/** + * connect a new fd and wrap it in a BIO in SSL + * @param sslctx: the SSL_CTX to use (from connect_sslctx_create()) + * @param fd: from connect. + * @return SSL or NULL on alloc failure + */ +void* outgoing_ssl_fd(void* sslctx, int fd); + +#endif /* NET_HELP_H */ diff --git a/util/netevent.c b/util/netevent.c new file mode 100644 index 00000000000..5b869765cc3 --- /dev/null +++ b/util/netevent.c @@ -0,0 +1,2137 @@ +/* + * util/netevent.c - event notification + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains event notification functions. + */ +#include "config.h" +#include +#include "util/netevent.h" +#include "util/log.h" +#include "util/net_help.h" +#include "util/fptr_wlist.h" +#include +#include + +/* -------- Start of local definitions -------- */ +/** if CMSG_ALIGN is not defined on this platform, a workaround */ +#ifndef CMSG_ALIGN +# ifdef _CMSG_DATA_ALIGN +# define CMSG_ALIGN _CMSG_DATA_ALIGN +# else +# define CMSG_ALIGN(len) (((len)+sizeof(long)-1) & ~(sizeof(long)-1)) +# endif +#endif + +/** if CMSG_LEN is not defined on this platform, a workaround */ +#ifndef CMSG_LEN +# define CMSG_LEN(len) (CMSG_ALIGN(sizeof(struct cmsghdr))+(len)) +#endif + +/** if CMSG_SPACE is not defined on this platform, a workaround */ +#ifndef CMSG_SPACE +# ifdef _CMSG_HDR_ALIGN +# define CMSG_SPACE(l) (CMSG_ALIGN(l)+_CMSG_HDR_ALIGN(sizeof(struct cmsghdr))) +# else +# define CMSG_SPACE(l) (CMSG_ALIGN(l)+CMSG_ALIGN(sizeof(struct cmsghdr))) +# endif +#endif + +/** The TCP reading or writing query timeout in seconds */ +#define TCP_QUERY_TIMEOUT 120 + +#ifndef NONBLOCKING_IS_BROKEN +/** number of UDP reads to perform per read indication from select */ +#define NUM_UDP_PER_SELECT 100 +#else +#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 */ +# include +#endif /* USE_MINI_EVENT */ + +/** + * The internal event structure for keeping libevent 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; +}; + +/** + * Internal base structure, so that every thread has its own events. + */ +struct internal_base { + /** libevent event_base type. */ + struct event_base* base; + /** seconds time pointer points here */ + uint32_t secs; + /** timeval with current time */ + struct timeval now; + /** the event used for slow_accept timeouts */ + struct event slow_accept; + /** true if slow_accept is enabled */ + int slow_accept_enabled; +}; + +/** + * Internal timer structure, to store timer event in. + */ +struct internal_timer { + /** the comm base */ + struct comm_base* base; + /** libevent event type, alloced here */ + struct event ev; + /** is timer enabled */ + uint8_t enabled; +}; + +/** + * Internal signal structure, to store signal event in. + */ +struct internal_signal { + /** libevent event type, alloced here */ + struct event ev; + /** next in signal list */ + struct internal_signal* next; +}; + +/** create a tcp handler with a parent */ +static struct comm_point* comm_point_create_tcp_handler( + struct comm_base *base, struct comm_point* parent, size_t bufsize, + comm_point_callback_t* callback, void* callback_arg); + +/* -------- 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 = (uint32_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)); + if(!b) + return NULL; + b->eb = (struct internal_base*)calloc(1, sizeof(struct internal_base)); + if(!b->eb) { + 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 + 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 + ); + return b; +} + +void +comm_base_delete(struct comm_base* b) +{ + if(!b) + return; + if(b->eb->slow_accept_enabled) { + if(event_del(&b->eb->slow_accept) != 0) { + log_err("could not event_del 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 */ + b->eb->base = NULL; + free(b->eb); + free(b); +} + +void +comm_base_timept(struct comm_base* b, uint32_t** tt, struct timeval** tv) +{ + *tt = &b->eb->secs; + *tv = &b->eb->now; +} + +void +comm_base_dispatch(struct comm_base* b) +{ + int retval; + retval = event_base_dispatch(b->eb->base); + if(retval != 0) { + fatal_exit("event_dispatch returned error %d, " + "errno is %s", retval, strerror(errno)); + } +} + +void comm_base_exit(struct comm_base* b) +{ + if(event_base_loopexit(b->eb->base, NULL) != 0) { + log_err("Could not loopexit"); + } +} + +void comm_base_set_slow_accept_handlers(struct comm_base* b, + void (*stop_acc)(void*), void (*start_acc)(void*), void* arg) +{ + b->stop_accept = stop_acc; + b->start_accept = start_acc; + b->cb_arg = arg; +} + +struct event_base* comm_base_internal(struct comm_base* b) +{ + return b->eb->base; +} + +/** see if errno for udp has to be logged or not uses globals */ +static int +udp_send_errno_needs_log(struct sockaddr* addr, socklen_t addrlen) +{ + /* do not log transient errors (unless high verbosity) */ +#if defined(ENETUNREACH) || defined(EHOSTDOWN) || defined(EHOSTUNREACH) || defined(ENETDOWN) + switch(errno) { +# ifdef ENETUNREACH + case ENETUNREACH: +# endif +# ifdef EHOSTDOWN + case EHOSTDOWN: +# endif +# ifdef EHOSTUNREACH + case EHOSTUNREACH: +# endif +# ifdef ENETDOWN + case ENETDOWN: +# endif + if(verbosity < VERB_ALGO) + return 0; + default: + break; + } +#endif + /* squelch errors where people deploy AAAA ::ffff:bla for + * authority servers, which we try for intranets. */ + if(errno == EINVAL && addr_is_ip4mapped( + (struct sockaddr_storage*)addr, addrlen) && + verbosity < VERB_DETAIL) + return 0; + /* SO_BROADCAST sockopt can give access to 255.255.255.255, + * but a dns cache does not need it. */ + if(errno == EACCES && addr_is_broadcast( + (struct sockaddr_storage*)addr, addrlen) && + verbosity < VERB_DETAIL) + return 0; + return 1; +} + +int tcp_connect_errno_needs_log(struct sockaddr* addr, socklen_t addrlen) +{ + return udp_send_errno_needs_log(addr, addrlen); +} + +/* send a UDP reply */ +int +comm_point_send_udp_msg(struct comm_point *c, ldns_buffer* packet, + struct sockaddr* addr, socklen_t addrlen) +{ + ssize_t sent; + log_assert(c->fd != -1); +#ifdef UNBOUND_DEBUG + if(ldns_buffer_remaining(packet) == 0) + log_err("error: send empty UDP packet"); +#endif + log_assert(addr && addrlen > 0); + sent = sendto(c->fd, (void*)ldns_buffer_begin(packet), + ldns_buffer_remaining(packet), 0, + addr, addrlen); + if(sent == -1) { + if(!udp_send_errno_needs_log(addr, addrlen)) + return 0; +#ifndef USE_WINSOCK + verbose(VERB_OPS, "sendto failed: %s", strerror(errno)); +#else + verbose(VERB_OPS, "sendto failed: %s", + wsa_strerror(WSAGetLastError())); +#endif + log_addr(VERB_OPS, "remote address is", + (struct sockaddr_storage*)addr, addrlen); + return 0; + } else if((size_t)sent != ldns_buffer_remaining(packet)) { + log_err("sent %d in place of %d bytes", + (int)sent, (int)ldns_buffer_remaining(packet)); + return 0; + } + return 1; +} + +#if defined(AF_INET6) && defined(IPV6_PKTINFO) && (defined(HAVE_RECVMSG) || defined(HAVE_SENDMSG)) +/** print debug ancillary info */ +static void p_ancil(const char* str, struct comm_reply* r) +{ + if(r->srctype != 4 && r->srctype != 6) { + log_info("%s: unknown srctype %d", str, r->srctype); + return; + } + if(r->srctype == 6) { + char buf[1024]; + if(inet_ntop(AF_INET6, &r->pktinfo.v6info.ipi6_addr, + buf, (socklen_t)sizeof(buf)) == 0) { + strncpy(buf, "(inet_ntop error)", sizeof(buf)); + } + buf[sizeof(buf)-1]=0; + log_info("%s: %s %d", str, buf, r->pktinfo.v6info.ipi6_ifindex); + } else if(r->srctype == 4) { +#ifdef IP_PKTINFO + char buf1[1024], buf2[1024]; + if(inet_ntop(AF_INET, &r->pktinfo.v4info.ipi_addr, + buf1, (socklen_t)sizeof(buf1)) == 0) { + strncpy(buf1, "(inet_ntop error)", sizeof(buf1)); + } + buf1[sizeof(buf1)-1]=0; +#ifdef HAVE_STRUCT_IN_PKTINFO_IPI_SPEC_DST + if(inet_ntop(AF_INET, &r->pktinfo.v4info.ipi_spec_dst, + buf2, (socklen_t)sizeof(buf2)) == 0) { + strncpy(buf2, "(inet_ntop error)", sizeof(buf2)); + } + buf2[sizeof(buf2)-1]=0; +#else + buf2[0]=0; +#endif + log_info("%s: %d %s %s", str, r->pktinfo.v4info.ipi_ifindex, + buf1, buf2); +#elif defined(IP_RECVDSTADDR) + char buf1[1024]; + if(inet_ntop(AF_INET, &r->pktinfo.v4addr, + buf1, (socklen_t)sizeof(buf1)) == 0) { + strncpy(buf1, "(inet_ntop error)", sizeof(buf1)); + } + buf1[sizeof(buf1)-1]=0; + log_info("%s: %s", str, buf1); +#endif /* IP_PKTINFO or PI_RECVDSTDADDR */ + } +} +#endif /* AF_INET6 && IPV6_PKTINFO && HAVE_RECVMSG||HAVE_SENDMSG */ + +/** send a UDP reply over specified interface*/ +static int +comm_point_send_udp_msg_if(struct comm_point *c, ldns_buffer* packet, + struct sockaddr* addr, socklen_t addrlen, struct comm_reply* r) +{ +#if defined(AF_INET6) && defined(IPV6_PKTINFO) && defined(HAVE_SENDMSG) + ssize_t sent; + struct msghdr msg; + struct iovec iov[1]; + char control[256]; +#ifndef S_SPLINT_S + struct cmsghdr *cmsg; +#endif /* S_SPLINT_S */ + + log_assert(c->fd != -1); +#ifdef UNBOUND_DEBUG + if(ldns_buffer_remaining(packet) == 0) + log_err("error: send empty UDP packet"); +#endif + log_assert(addr && addrlen > 0); + + msg.msg_name = addr; + msg.msg_namelen = addrlen; + iov[0].iov_base = ldns_buffer_begin(packet); + iov[0].iov_len = ldns_buffer_remaining(packet); + msg.msg_iov = iov; + msg.msg_iovlen = 1; + msg.msg_control = control; +#ifndef S_SPLINT_S + msg.msg_controllen = sizeof(control); +#endif /* S_SPLINT_S */ + msg.msg_flags = 0; + +#ifndef S_SPLINT_S + cmsg = CMSG_FIRSTHDR(&msg); + if(r->srctype == 4) { +#ifdef IP_PKTINFO + msg.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo)); + log_assert(msg.msg_controllen <= sizeof(control)); + cmsg->cmsg_level = IPPROTO_IP; + cmsg->cmsg_type = IP_PKTINFO; + memmove(CMSG_DATA(cmsg), &r->pktinfo.v4info, + sizeof(struct in_pktinfo)); + cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); +#elif defined(IP_SENDSRCADDR) + msg.msg_controllen = CMSG_SPACE(sizeof(struct in_addr)); + log_assert(msg.msg_controllen <= sizeof(control)); + cmsg->cmsg_level = IPPROTO_IP; + cmsg->cmsg_type = IP_SENDSRCADDR; + memmove(CMSG_DATA(cmsg), &r->pktinfo.v4addr, + sizeof(struct in_addr)); + cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr)); +#else + verbose(VERB_ALGO, "no IP_PKTINFO or IP_SENDSRCADDR"); + msg.msg_control = NULL; +#endif /* IP_PKTINFO or IP_SENDSRCADDR */ + } else if(r->srctype == 6) { + msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); + log_assert(msg.msg_controllen <= sizeof(control)); + cmsg->cmsg_level = IPPROTO_IPV6; + cmsg->cmsg_type = IPV6_PKTINFO; + memmove(CMSG_DATA(cmsg), &r->pktinfo.v6info, + sizeof(struct in6_pktinfo)); + cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); + } else { + /* try to pass all 0 to use default route */ + msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); + log_assert(msg.msg_controllen <= sizeof(control)); + cmsg->cmsg_level = IPPROTO_IPV6; + cmsg->cmsg_type = IPV6_PKTINFO; + memset(CMSG_DATA(cmsg), 0, sizeof(struct in6_pktinfo)); + cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); + } +#endif /* S_SPLINT_S */ + if(verbosity >= VERB_ALGO) + p_ancil("send_udp over interface", r); + sent = sendmsg(c->fd, &msg, 0); + if(sent == -1) { + if(!udp_send_errno_needs_log(addr, addrlen)) + return 0; + verbose(VERB_OPS, "sendmsg failed: %s", strerror(errno)); + log_addr(VERB_OPS, "remote address is", + (struct sockaddr_storage*)addr, addrlen); + return 0; + } else if((size_t)sent != ldns_buffer_remaining(packet)) { + log_err("sent %d in place of %d bytes", + (int)sent, (int)ldns_buffer_remaining(packet)); + return 0; + } + return 1; +#else + (void)c; + (void)packet; + (void)addr; + (void)addrlen; + (void)r; + log_err("sendmsg: IPV6_PKTINFO not supported"); + return 0; +#endif /* AF_INET6 && IPV6_PKTINFO && HAVE_SENDMSG */ +} + +void +comm_point_udp_ancil_callback(int fd, short event, void* arg) +{ +#if defined(AF_INET6) && defined(IPV6_PKTINFO) && defined(HAVE_RECVMSG) + struct comm_reply rep; + struct msghdr msg; + struct iovec iov[1]; + ssize_t rcv; + char ancil[256]; + int i; +#ifndef S_SPLINT_S + struct cmsghdr* cmsg; +#endif /* S_SPLINT_S */ + + rep.c = (struct comm_point*)arg; + log_assert(rep.c->type == comm_udp); + + if(!(event&EV_READ)) + return; + log_assert(rep.c && rep.c->buffer && rep.c->fd == fd); + comm_base_now(rep.c->ev->base); + for(i=0; ibuffer); + rep.addrlen = (socklen_t)sizeof(rep.addr); + log_assert(fd != -1); + log_assert(ldns_buffer_remaining(rep.c->buffer) > 0); + msg.msg_name = &rep.addr; + msg.msg_namelen = (socklen_t)sizeof(rep.addr); + iov[0].iov_base = ldns_buffer_begin(rep.c->buffer); + iov[0].iov_len = ldns_buffer_remaining(rep.c->buffer); + msg.msg_iov = iov; + msg.msg_iovlen = 1; + msg.msg_control = ancil; +#ifndef S_SPLINT_S + msg.msg_controllen = sizeof(ancil); +#endif /* S_SPLINT_S */ + msg.msg_flags = 0; + rcv = recvmsg(fd, &msg, 0); + if(rcv == -1) { + if(errno != EAGAIN && errno != EINTR) { + log_err("recvmsg failed: %s", strerror(errno)); + } + return; + } + rep.addrlen = msg.msg_namelen; + ldns_buffer_skip(rep.c->buffer, rcv); + ldns_buffer_flip(rep.c->buffer); + rep.srctype = 0; +#ifndef S_SPLINT_S + for(cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; + cmsg = CMSG_NXTHDR(&msg, cmsg)) { + if( cmsg->cmsg_level == IPPROTO_IPV6 && + cmsg->cmsg_type == IPV6_PKTINFO) { + rep.srctype = 6; + memmove(&rep.pktinfo.v6info, CMSG_DATA(cmsg), + sizeof(struct in6_pktinfo)); + break; +#ifdef IP_PKTINFO + } else if( cmsg->cmsg_level == IPPROTO_IP && + cmsg->cmsg_type == IP_PKTINFO) { + rep.srctype = 4; + memmove(&rep.pktinfo.v4info, CMSG_DATA(cmsg), + sizeof(struct in_pktinfo)); + break; +#elif defined(IP_RECVDSTADDR) + } else if( cmsg->cmsg_level == IPPROTO_IP && + cmsg->cmsg_type == IP_RECVDSTADDR) { + rep.srctype = 4; + memmove(&rep.pktinfo.v4addr, CMSG_DATA(cmsg), + sizeof(struct in_addr)); + break; +#endif /* IP_PKTINFO or IP_RECVDSTADDR */ + } + } + if(verbosity >= VERB_ALGO) + p_ancil("receive_udp on interface", &rep); +#endif /* S_SPLINT_S */ + fptr_ok(fptr_whitelist_comm_point(rep.c->callback)); + if((*rep.c->callback)(rep.c, rep.c->cb_arg, NETEVENT_NOERROR, &rep)) { + /* send back immediate reply */ + (void)comm_point_send_udp_msg_if(rep.c, rep.c->buffer, + (struct sockaddr*)&rep.addr, rep.addrlen, &rep); + } + if(rep.c->fd == -1) /* commpoint closed */ + break; + } +#else + (void)fd; + (void)event; + (void)arg; + fatal_exit("recvmsg: No support for IPV6_PKTINFO. " + "Please disable interface-automatic"); +#endif /* AF_INET6 && IPV6_PKTINFO && HAVE_RECVMSG */ +} + +void +comm_point_udp_callback(int fd, short event, void* arg) +{ + struct comm_reply rep; + ssize_t rcv; + int i; + + rep.c = (struct comm_point*)arg; + log_assert(rep.c->type == comm_udp); + + if(!(event&EV_READ)) + return; + log_assert(rep.c && rep.c->buffer && rep.c->fd == fd); + comm_base_now(rep.c->ev->base); + for(i=0; ibuffer); + rep.addrlen = (socklen_t)sizeof(rep.addr); + log_assert(fd != -1); + log_assert(ldns_buffer_remaining(rep.c->buffer) > 0); + rcv = recvfrom(fd, (void*)ldns_buffer_begin(rep.c->buffer), + ldns_buffer_remaining(rep.c->buffer), 0, + (struct sockaddr*)&rep.addr, &rep.addrlen); + if(rcv == -1) { +#ifndef USE_WINSOCK + if(errno != EAGAIN && errno != EINTR) + log_err("recvfrom %d failed: %s", + fd, strerror(errno)); +#else + if(WSAGetLastError() != WSAEINPROGRESS && + WSAGetLastError() != WSAECONNRESET && + WSAGetLastError()!= WSAEWOULDBLOCK) + log_err("recvfrom failed: %s", + wsa_strerror(WSAGetLastError())); +#endif + return; + } + ldns_buffer_skip(rep.c->buffer, rcv); + ldns_buffer_flip(rep.c->buffer); + rep.srctype = 0; + fptr_ok(fptr_whitelist_comm_point(rep.c->callback)); + if((*rep.c->callback)(rep.c, rep.c->cb_arg, NETEVENT_NOERROR, &rep)) { + /* send back immediate reply */ + (void)comm_point_send_udp_msg(rep.c, rep.c->buffer, + (struct sockaddr*)&rep.addr, rep.addrlen); + } + if(rep.c->fd != fd) /* commpoint closed to -1 or reused for + another UDP port. Note rep.c cannot be reused with TCP fd. */ + break; + } +} + +/** Use a new tcp handler for new query fd, set to read query */ +static void +setup_tcp_handler(struct comm_point* c, int fd) +{ + log_assert(c->type == comm_tcp); + log_assert(c->fd == -1); + ldns_buffer_clear(c->buffer); + c->tcp_is_reading = 1; + c->tcp_byte_count = 0; + comm_point_start_listening(c, fd, TCP_QUERY_TIMEOUT); +} + +void comm_base_handle_slow_accept(int ATTR_UNUSED(fd), + short ATTR_UNUSED(event), void* arg) +{ + struct comm_base* b = (struct comm_base*)arg; + /* timeout for the slow accept, re-enable accepts again */ + if(b->start_accept) { + verbose(VERB_ALGO, "wait is over, slow accept disabled"); + fptr_ok(fptr_whitelist_start_accept(b->start_accept)); + (*b->start_accept)(b->cb_arg); + b->eb->slow_accept_enabled = 0; + } +} + +int comm_point_perform_accept(struct comm_point* c, + struct sockaddr_storage* addr, socklen_t* addrlen) +{ + int new_fd; + *addrlen = (socklen_t)sizeof(*addr); + new_fd = accept(c->fd, (struct sockaddr*)addr, addrlen); + if(new_fd == -1) { +#ifndef USE_WINSOCK + /* EINTR is signal interrupt. others are closed connection. */ + if( errno == EINTR || errno == EAGAIN +#ifdef EWOULDBLOCK + || errno == EWOULDBLOCK +#endif +#ifdef ECONNABORTED + || errno == ECONNABORTED +#endif +#ifdef EPROTO + || errno == EPROTO +#endif /* EPROTO */ + ) + return -1; +#if defined(ENFILE) && defined(EMFILE) + if(errno == ENFILE || errno == EMFILE) { + /* out of file descriptors, likely outside of our + * control. stop accept() calls for some time */ + if(c->ev->base->stop_accept) { + struct comm_base* b = c->ev->base; + struct timeval tv; + verbose(VERB_ALGO, "out of file descriptors: " + "slow accept"); + b->eb->slow_accept_enabled = 1; + fptr_ok(fptr_whitelist_stop_accept( + b->stop_accept)); + (*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, + comm_base_handle_slow_accept, b); + if(event_base_set(b->eb->base, + &b->eb->slow_accept) != 0) { + /* 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) { + /* we do not want to log here, + * error: "event_add failed." */ + } + } + return -1; + } +#endif + log_err("accept failed: %s", strerror(errno)); +#else /* USE_WINSOCK */ + if(WSAGetLastError() == WSAEINPROGRESS || + WSAGetLastError() == WSAECONNRESET) + return -1; + if(WSAGetLastError() == WSAEWOULDBLOCK) { + winsock_tcp_wouldblock(&c->ev->ev, EV_READ); + return -1; + } + log_err("accept failed: %s", wsa_strerror(WSAGetLastError())); +#endif + log_addr(0, "remote address is", addr, *addrlen); + return -1; + } + fd_set_nonblock(new_fd); + return new_fd; +} + +#ifdef USE_WINSOCK +static long win_bio_cb(BIO *b, int oper, const char* ATTR_UNUSED(argp), + int ATTR_UNUSED(argi), long argl, long retvalue) +{ + verbose(VERB_ALGO, "bio_cb %d, %s %s %s", oper, + (oper&BIO_CB_RETURN)?"return":"before", + (oper&BIO_CB_READ)?"read":((oper&BIO_CB_WRITE)?"write":"other"), + WSAGetLastError()==WSAEWOULDBLOCK?"wsawb":""); + /* on windows, check if previous operation caused EWOULDBLOCK */ + 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); + } + 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); + } + /* return original return value */ + return retvalue; +} + +/** set win bio callbacks for nonblocking operations */ +void +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(SSL_get_wbio(ssl), &win_bio_cb); + BIO_set_callback_arg(SSL_get_wbio(ssl), (char*)&c->ev->ev); +} +#endif + +void +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)) { + log_info("ignoring tcp accept event %d", (int)event); + return; + } + comm_base_now(c->ev->base); + /* find free tcp handler. */ + if(!c->tcp_free) { + log_warn("accepted too many tcp, connections full"); + return; + } + /* accept incoming connection. */ + c_hdl = c->tcp_free; + log_assert(fd != -1); + new_fd = comm_point_perform_accept(c, &c_hdl->repinfo.addr, + &c_hdl->repinfo.addrlen); + if(new_fd == -1) + return; + if(c->ssl) { + c_hdl->ssl = incoming_ssl_fd(c->ssl, new_fd); + if(!c_hdl->ssl) { + c_hdl->fd = new_fd; + comm_point_close(c_hdl); + return; + } + c_hdl->ssl_shake_state = comm_ssl_shake_read; +#ifdef USE_WINSOCK + comm_point_tcp_win_bio_cb(c_hdl, c_hdl->ssl); +#endif + } + + /* grab the tcp handler buffers */ + c->tcp_free = c_hdl->tcp_free; + if(!c->tcp_free) { + /* stop accepting incoming queries for now. */ + comm_point_stop_listening(c); + } + /* addr is dropped. Not needed for tcp reply. */ + setup_tcp_handler(c_hdl, new_fd); +} + +/** Make tcp handler free for next assignment */ +static void +reclaim_tcp_handler(struct comm_point* c) +{ + log_assert(c->type == comm_tcp); + if(c->ssl) { + SSL_shutdown(c->ssl); + SSL_free(c->ssl); + c->ssl = NULL; + } + comm_point_close(c); + if(c->tcp_parent) { + c->tcp_free = c->tcp_parent->tcp_free; + c->tcp_parent->tcp_free = c; + if(!c->tcp_free) { + /* re-enable listening on accept socket */ + comm_point_start_listening(c->tcp_parent, -1, -1); + } + } +} + +/** do the callback when writing is done */ +static void +tcp_callback_writer(struct comm_point* c) +{ + log_assert(c->type == comm_tcp); + ldns_buffer_clear(c->buffer); + if(c->tcp_do_toggle_rw) + c->tcp_is_reading = 1; + c->tcp_byte_count = 0; + /* switch from listening(write) to listening(read) */ + comm_point_stop_listening(c); + comm_point_start_listening(c, -1, -1); +} + +/** do the callback when reading is done */ +static void +tcp_callback_reader(struct comm_point* c) +{ + log_assert(c->type == comm_tcp || c->type == comm_local); + ldns_buffer_flip(c->buffer); + if(c->tcp_do_toggle_rw) + c->tcp_is_reading = 0; + c->tcp_byte_count = 0; + if(c->type == comm_tcp) + 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); + } +} + +/** continue ssl handshake */ +static int +ssl_handshake(struct comm_point* c) +{ + int r; + if(c->ssl_shake_state == comm_ssl_shake_hs_read) { + /* read condition satisfied back to writing */ + comm_point_listen_for_rw(c, 1, 1); + c->ssl_shake_state = comm_ssl_shake_none; + return 1; + } + if(c->ssl_shake_state == comm_ssl_shake_hs_write) { + /* write condition satisfied, back to reading */ + comm_point_listen_for_rw(c, 1, 0); + c->ssl_shake_state = comm_ssl_shake_none; + return 1; + } + + ERR_clear_error(); + r = SSL_do_handshake(c->ssl); + if(r != 1) { + int want = SSL_get_error(c->ssl, r); + if(want == SSL_ERROR_WANT_READ) { + if(c->ssl_shake_state == comm_ssl_shake_read) + return 1; + c->ssl_shake_state = comm_ssl_shake_read; + comm_point_listen_for_rw(c, 1, 0); + return 1; + } else if(want == SSL_ERROR_WANT_WRITE) { + if(c->ssl_shake_state == comm_ssl_shake_write) + return 1; + c->ssl_shake_state = comm_ssl_shake_write; + comm_point_listen_for_rw(c, 0, 1); + return 1; + } else if(r == 0) { + return 0; /* closed */ + } else if(want == SSL_ERROR_SYSCALL) { + /* SYSCALL and errno==0 means closed uncleanly */ + if(errno != 0) + log_err("SSL_handshake syscall: %s", + strerror(errno)); + return 0; + } else { + log_crypto_err("ssl handshake failed"); + log_addr(1, "ssl handshake failed", &c->repinfo.addr, + c->repinfo.addrlen); + return 0; + } + } + /* this is where peer verification could take place */ + log_addr(VERB_ALGO, "SSL DNS connection", &c->repinfo.addr, + c->repinfo.addrlen); + + /* setup listen rw correctly */ + if(c->tcp_is_reading) { + if(c->ssl_shake_state != comm_ssl_shake_read) + comm_point_listen_for_rw(c, 1, 0); + } else { + comm_point_listen_for_rw(c, 1, 1); + } + c->ssl_shake_state = comm_ssl_shake_none; + return 1; +} + +/** ssl read callback on TCP */ +static int +ssl_handle_read(struct comm_point* c) +{ + int r; + if(c->ssl_shake_state != comm_ssl_shake_none) { + if(!ssl_handshake(c)) + return 0; + if(c->ssl_shake_state != comm_ssl_shake_none) + return 1; + } + if(c->tcp_byte_count < sizeof(uint16_t)) { + /* read length bytes */ + ERR_clear_error(); + if((r=SSL_read(c->ssl, (void*)ldns_buffer_at(c->buffer, + c->tcp_byte_count), (int)(sizeof(uint16_t) - + c->tcp_byte_count))) <= 0) { + int want = SSL_get_error(c->ssl, r); + if(want == SSL_ERROR_ZERO_RETURN) { + return 0; /* shutdown, closed */ + } else if(want == SSL_ERROR_WANT_READ) { + return 1; /* read more later */ + } else if(want == SSL_ERROR_WANT_WRITE) { + c->ssl_shake_state = comm_ssl_shake_hs_write; + comm_point_listen_for_rw(c, 0, 1); + return 1; + } else if(want == SSL_ERROR_SYSCALL) { + if(errno != 0) + log_err("SSL_read syscall: %s", + strerror(errno)); + return 0; + } + log_crypto_err("could not SSL_read"); + return 0; + } + c->tcp_byte_count += r; + if(c->tcp_byte_count != sizeof(uint16_t)) + return 1; + if(ldns_buffer_read_u16_at(c->buffer, 0) > + ldns_buffer_capacity(c->buffer)) { + verbose(VERB_QUERY, "ssl: dropped larger than buffer"); + return 0; + } + ldns_buffer_set_limit(c->buffer, + ldns_buffer_read_u16_at(c->buffer, 0)); + if(ldns_buffer_limit(c->buffer) < LDNS_HEADER_SIZE) { + verbose(VERB_QUERY, "ssl: dropped bogus too short."); + return 0; + } + verbose(VERB_ALGO, "Reading ssl tcp query of length %d", + (int)ldns_buffer_limit(c->buffer)); + } + log_assert(ldns_buffer_remaining(c->buffer) > 0); + ERR_clear_error(); + r = SSL_read(c->ssl, (void*)ldns_buffer_current(c->buffer), + (int)ldns_buffer_remaining(c->buffer)); + if(r <= 0) { + int want = SSL_get_error(c->ssl, r); + if(want == SSL_ERROR_ZERO_RETURN) { + return 0; /* shutdown, closed */ + } else if(want == SSL_ERROR_WANT_READ) { + return 1; /* read more later */ + } else if(want == SSL_ERROR_WANT_WRITE) { + c->ssl_shake_state = comm_ssl_shake_hs_write; + comm_point_listen_for_rw(c, 0, 1); + return 1; + } else if(want == SSL_ERROR_SYSCALL) { + if(errno != 0) + log_err("SSL_read syscall: %s", + strerror(errno)); + return 0; + } + log_crypto_err("could not SSL_read"); + return 0; + } + ldns_buffer_skip(c->buffer, (ssize_t)r); + if(ldns_buffer_remaining(c->buffer) <= 0) { + tcp_callback_reader(c); + } + return 1; +} + +/** ssl write callback on TCP */ +static int +ssl_handle_write(struct comm_point* c) +{ + int r; + if(c->ssl_shake_state != comm_ssl_shake_none) { + if(!ssl_handshake(c)) + return 0; + if(c->ssl_shake_state != comm_ssl_shake_none) + return 1; + } + /* ignore return, if fails we may simply block */ + (void)SSL_set_mode(c->ssl, SSL_MODE_ENABLE_PARTIAL_WRITE); + if(c->tcp_byte_count < sizeof(uint16_t)) { + uint16_t len = htons(ldns_buffer_limit(c->buffer)); + ERR_clear_error(); + r = SSL_write(c->ssl, + (void*)(((uint8_t*)&len)+c->tcp_byte_count), + (int)(sizeof(uint16_t)-c->tcp_byte_count)); + if(r <= 0) { + int want = SSL_get_error(c->ssl, r); + if(want == SSL_ERROR_ZERO_RETURN) { + return 0; /* closed */ + } else if(want == SSL_ERROR_WANT_READ) { + c->ssl_shake_state = comm_ssl_shake_read; + comm_point_listen_for_rw(c, 1, 0); + return 1; /* wait for read condition */ + } else if(want == SSL_ERROR_WANT_WRITE) { + return 1; /* write more later */ + } else if(want == SSL_ERROR_SYSCALL) { + if(errno != 0) + log_err("SSL_write syscall: %s", + strerror(errno)); + return 0; + } + log_crypto_err("could not SSL_write"); + return 0; + } + c->tcp_byte_count += r; + if(c->tcp_byte_count < sizeof(uint16_t)) + return 1; + ldns_buffer_set_position(c->buffer, c->tcp_byte_count - + sizeof(uint16_t)); + if(ldns_buffer_remaining(c->buffer) == 0) { + tcp_callback_writer(c); + return 1; + } + } + log_assert(ldns_buffer_remaining(c->buffer) > 0); + ERR_clear_error(); + r = SSL_write(c->ssl, (void*)ldns_buffer_current(c->buffer), + (int)ldns_buffer_remaining(c->buffer)); + if(r <= 0) { + int want = SSL_get_error(c->ssl, r); + if(want == SSL_ERROR_ZERO_RETURN) { + return 0; /* closed */ + } else if(want == SSL_ERROR_WANT_READ) { + c->ssl_shake_state = comm_ssl_shake_read; + comm_point_listen_for_rw(c, 1, 0); + return 1; /* wait for read condition */ + } else if(want == SSL_ERROR_WANT_WRITE) { + return 1; /* write more later */ + } else if(want == SSL_ERROR_SYSCALL) { + if(errno != 0) + log_err("SSL_write syscall: %s", + strerror(errno)); + return 0; + } + log_crypto_err("could not SSL_write"); + return 0; + } + ldns_buffer_skip(c->buffer, (ssize_t)r); + + if(ldns_buffer_remaining(c->buffer) == 0) { + tcp_callback_writer(c); + } + return 1; +} + +/** handle ssl tcp connection with dns contents */ +static int +ssl_handle_it(struct comm_point* c) +{ + if(c->tcp_is_reading) + return ssl_handle_read(c); + return ssl_handle_write(c); +} + +/** Handle tcp reading callback. + * @param fd: file descriptor of socket. + * @param c: comm point to read from into buffer. + * @param short_ok: if true, very short packets are OK (for comm_local). + * @return: 0 on error + */ +static int +comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok) +{ + ssize_t r; + log_assert(c->type == comm_tcp || c->type == comm_local); + if(c->ssl) + return ssl_handle_it(c); + if(!c->tcp_is_reading) + return 0; + + log_assert(fd != -1); + if(c->tcp_byte_count < sizeof(uint16_t)) { + /* read length bytes */ + r = recv(fd,(void*)ldns_buffer_at(c->buffer,c->tcp_byte_count), + sizeof(uint16_t)-c->tcp_byte_count, 0); + if(r == 0) + return 0; + else if(r == -1) { +#ifndef USE_WINSOCK + if(errno == EINTR || errno == EAGAIN) + return 1; +#ifdef ECONNRESET + if(errno == ECONNRESET && verbosity < 2) + return 0; /* silence reset by peer */ +#endif + log_err("read (in tcp s): %s", strerror(errno)); +#else /* USE_WINSOCK */ + if(WSAGetLastError() == WSAECONNRESET) + return 0; + if(WSAGetLastError() == WSAEINPROGRESS) + return 1; + if(WSAGetLastError() == WSAEWOULDBLOCK) { + winsock_tcp_wouldblock(&c->ev->ev, EV_READ); + return 1; + } + log_err("read (in tcp s): %s", + wsa_strerror(WSAGetLastError())); +#endif + log_addr(0, "remote address is", &c->repinfo.addr, + c->repinfo.addrlen); + return 0; + } + c->tcp_byte_count += r; + if(c->tcp_byte_count != sizeof(uint16_t)) + return 1; + if(ldns_buffer_read_u16_at(c->buffer, 0) > + ldns_buffer_capacity(c->buffer)) { + verbose(VERB_QUERY, "tcp: dropped larger than buffer"); + return 0; + } + ldns_buffer_set_limit(c->buffer, + ldns_buffer_read_u16_at(c->buffer, 0)); + if(!short_ok && + ldns_buffer_limit(c->buffer) < LDNS_HEADER_SIZE) { + verbose(VERB_QUERY, "tcp: dropped bogus too short."); + return 0; + } + verbose(VERB_ALGO, "Reading tcp query of length %d", + (int)ldns_buffer_limit(c->buffer)); + } + + log_assert(ldns_buffer_remaining(c->buffer) > 0); + r = recv(fd, (void*)ldns_buffer_current(c->buffer), + ldns_buffer_remaining(c->buffer), 0); + if(r == 0) { + return 0; + } else if(r == -1) { +#ifndef USE_WINSOCK + if(errno == EINTR || errno == EAGAIN) + return 1; + log_err("read (in tcp r): %s", strerror(errno)); +#else /* USE_WINSOCK */ + if(WSAGetLastError() == WSAECONNRESET) + return 0; + if(WSAGetLastError() == WSAEINPROGRESS) + return 1; + if(WSAGetLastError() == WSAEWOULDBLOCK) { + winsock_tcp_wouldblock(&c->ev->ev, EV_READ); + return 1; + } + log_err("read (in tcp r): %s", + wsa_strerror(WSAGetLastError())); +#endif + log_addr(0, "remote address is", &c->repinfo.addr, + c->repinfo.addrlen); + return 0; + } + ldns_buffer_skip(c->buffer, r); + if(ldns_buffer_remaining(c->buffer) <= 0) { + tcp_callback_reader(c); + } + return 1; +} + +/** + * Handle tcp writing callback. + * @param fd: file descriptor of socket. + * @param c: comm point to write buffer out of. + * @return: 0 on error + */ +static int +comm_point_tcp_handle_write(int fd, struct comm_point* c) +{ + ssize_t r; + log_assert(c->type == comm_tcp); + if(c->tcp_is_reading && !c->ssl) + return 0; + log_assert(fd != -1); + if(c->tcp_byte_count == 0 && c->tcp_check_nb_connect) { + /* check for pending error from nonblocking connect */ + /* from Stevens, unix network programming, vol1, 3rd ed, p450*/ + int error = 0; + socklen_t len = (socklen_t)sizeof(error); + if(getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&error, + &len) < 0){ +#ifndef USE_WINSOCK + error = errno; /* on solaris errno is error */ +#else /* USE_WINSOCK */ + error = WSAGetLastError(); +#endif + } +#ifndef USE_WINSOCK +#if defined(EINPROGRESS) && defined(EWOULDBLOCK) + if(error == EINPROGRESS || error == EWOULDBLOCK) + return 1; /* try again later */ + else +#endif + if(error != 0 && verbosity < 2) + return 0; /* silence lots of chatter in the logs */ + else if(error != 0) { + log_err("tcp connect: %s", strerror(error)); +#else /* USE_WINSOCK */ + /* examine error */ + if(error == WSAEINPROGRESS) + return 1; + else if(error == WSAEWOULDBLOCK) { + winsock_tcp_wouldblock(&c->ev->ev, EV_WRITE); + return 1; + } else if(error != 0 && verbosity < 2) + return 0; + else if(error != 0) { + log_err("tcp connect: %s", wsa_strerror(error)); +#endif /* USE_WINSOCK */ + log_addr(0, "remote address is", &c->repinfo.addr, + c->repinfo.addrlen); + return 0; + } + } + if(c->ssl) + return ssl_handle_it(c); + + if(c->tcp_byte_count < sizeof(uint16_t)) { + uint16_t len = htons(ldns_buffer_limit(c->buffer)); +#ifdef HAVE_WRITEV + struct iovec iov[2]; + 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 = ldns_buffer_begin(c->buffer); + iov[1].iov_len = ldns_buffer_limit(c->buffer); + log_assert(iov[0].iov_len > 0); + log_assert(iov[1].iov_len > 0); + r = writev(fd, iov, 2); +#else /* HAVE_WRITEV */ + r = send(fd, (void*)(((uint8_t*)&len)+c->tcp_byte_count), + sizeof(uint16_t)-c->tcp_byte_count, 0); +#endif /* HAVE_WRITEV */ + if(r == -1) { +#ifndef USE_WINSOCK +#ifdef EPIPE + if(errno == EPIPE && verbosity < 2) + return 0; /* silence 'broken pipe' */ +#endif + if(errno == EINTR || errno == EAGAIN) + return 1; + log_err("tcp writev: %s", strerror(errno)); +#else + if(WSAGetLastError() == WSAENOTCONN) + return 1; + if(WSAGetLastError() == WSAEINPROGRESS) + return 1; + if(WSAGetLastError() == WSAEWOULDBLOCK) { + winsock_tcp_wouldblock(&c->ev->ev, EV_WRITE); + return 1; + } + log_err("tcp send s: %s", + wsa_strerror(WSAGetLastError())); +#endif + log_addr(0, "remote address is", &c->repinfo.addr, + c->repinfo.addrlen); + return 0; + } + c->tcp_byte_count += r; + if(c->tcp_byte_count < sizeof(uint16_t)) + return 1; + ldns_buffer_set_position(c->buffer, c->tcp_byte_count - + sizeof(uint16_t)); + if(ldns_buffer_remaining(c->buffer) == 0) { + tcp_callback_writer(c); + return 1; + } + } + log_assert(ldns_buffer_remaining(c->buffer) > 0); + r = send(fd, (void*)ldns_buffer_current(c->buffer), + ldns_buffer_remaining(c->buffer), 0); + if(r == -1) { +#ifndef USE_WINSOCK + if(errno == EINTR || errno == EAGAIN) + return 1; + log_err("tcp send r: %s", strerror(errno)); +#else + if(WSAGetLastError() == WSAEINPROGRESS) + return 1; + if(WSAGetLastError() == WSAEWOULDBLOCK) { + winsock_tcp_wouldblock(&c->ev->ev, EV_WRITE); + return 1; + } + log_err("tcp send r: %s", + wsa_strerror(WSAGetLastError())); +#endif + log_addr(0, "remote address is", &c->repinfo.addr, + c->repinfo.addrlen); + return 0; + } + ldns_buffer_skip(c->buffer, r); + + if(ldns_buffer_remaining(c->buffer) == 0) { + tcp_callback_writer(c); + } + + return 1; +} + +void +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); + + if(event&EV_READ) { + if(!comm_point_tcp_handle_read(fd, c, 0)) { + reclaim_tcp_handler(c); + if(!c->tcp_do_close) { + fptr_ok(fptr_whitelist_comm_point( + c->callback)); + (void)(*c->callback)(c, c->cb_arg, + NETEVENT_CLOSED, NULL); + } + } + return; + } + if(event&EV_WRITE) { + if(!comm_point_tcp_handle_write(fd, c)) { + reclaim_tcp_handler(c); + if(!c->tcp_do_close) { + fptr_ok(fptr_whitelist_comm_point( + c->callback)); + (void)(*c->callback)(c, c->cb_arg, + NETEVENT_CLOSED, NULL); + } + } + return; + } + if(event&EV_TIMEOUT) { + verbose(VERB_QUERY, "tcp took too long, dropped"); + reclaim_tcp_handler(c); + if(!c->tcp_do_close) { + fptr_ok(fptr_whitelist_comm_point(c->callback)); + (void)(*c->callback)(c, c->cb_arg, + NETEVENT_TIMEOUT, NULL); + } + return; + } + log_err("Ignored event %d for tcphdl.", event); +} + +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); + + if(event&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, + NULL); + } + return; + } + log_err("Ignored event %d for localhdl.", event); +} + +void comm_point_raw_handle_callback(int ATTR_UNUSED(fd), + short event, void* arg) +{ + struct comm_point* c = (struct comm_point*)arg; + int err = NETEVENT_NOERROR; + log_assert(c->type == comm_raw); + comm_base_now(c->ev->base); + + if(event&EV_TIMEOUT) + err = NETEVENT_TIMEOUT; + fptr_ok(fptr_whitelist_comm_point_raw(c->callback)); + (void)(*c->callback)(c, c->cb_arg, err, NULL); +} + +struct comm_point* +comm_point_create_udp(struct comm_base *base, int fd, ldns_buffer* buffer, + comm_point_callback_t* callback, void* callback_arg) +{ + struct comm_point* c = (struct comm_point*)calloc(1, + sizeof(struct comm_point)); + short evbits; + if(!c) + return NULL; + c->ev = (struct internal_event*)calloc(1, + sizeof(struct internal_event)); + if(!c->ev) { + free(c); + return NULL; + } + c->ev->base = base; + c->fd = fd; + c->buffer = buffer; + c->timeout = NULL; + c->tcp_is_reading = 0; + c->tcp_byte_count = 0; + c->tcp_parent = NULL; + c->max_tcp_count = 0; + c->tcp_handlers = NULL; + c->tcp_free = NULL; + c->type = comm_udp; + c->tcp_do_close = 0; + c->do_not_close = 0; + c->tcp_do_toggle_rw = 0; + c->tcp_check_nb_connect = 0; + 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) { + log_err("could not baseset udp event"); + comm_point_delete(c); + return NULL; + } + if(fd!=-1 && event_add(&c->ev->ev, c->timeout) != 0 ) { + log_err("could not add udp event"); + comm_point_delete(c); + return NULL; + } + return c; +} + +struct comm_point* +comm_point_create_udp_ancil(struct comm_base *base, int fd, + ldns_buffer* buffer, + comm_point_callback_t* callback, void* callback_arg) +{ + struct comm_point* c = (struct comm_point*)calloc(1, + sizeof(struct comm_point)); + short evbits; + if(!c) + return NULL; + c->ev = (struct internal_event*)calloc(1, + sizeof(struct internal_event)); + if(!c->ev) { + free(c); + return NULL; + } + c->ev->base = base; + c->fd = fd; + c->buffer = buffer; + c->timeout = NULL; + c->tcp_is_reading = 0; + c->tcp_byte_count = 0; + c->tcp_parent = NULL; + c->max_tcp_count = 0; + c->tcp_handlers = NULL; + c->tcp_free = NULL; + c->type = comm_udp; + c->tcp_do_close = 0; + c->do_not_close = 0; + c->inuse = 0; + c->tcp_do_toggle_rw = 0; + c->tcp_check_nb_connect = 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_ancil_callback, c); + if(event_base_set(base->eb->base, &c->ev->ev) != 0) { + log_err("could not baseset udp event"); + comm_point_delete(c); + return NULL; + } + if(fd!=-1 && event_add(&c->ev->ev, c->timeout) != 0 ) { + log_err("could not add udp event"); + comm_point_delete(c); + return NULL; + } + return c; +} + +static struct comm_point* +comm_point_create_tcp_handler(struct comm_base *base, + struct comm_point* parent, size_t bufsize, + comm_point_callback_t* callback, void* callback_arg) +{ + struct comm_point* c = (struct comm_point*)calloc(1, + sizeof(struct comm_point)); + short evbits; + if(!c) + return NULL; + c->ev = (struct internal_event*)calloc(1, + sizeof(struct internal_event)); + if(!c->ev) { + free(c); + return NULL; + } + c->ev->base = base; + c->fd = -1; + c->buffer = ldns_buffer_new(bufsize); + if(!c->buffer) { + free(c->ev); + free(c); + return NULL; + } + c->timeout = (struct timeval*)malloc(sizeof(struct timeval)); + if(!c->timeout) { + ldns_buffer_free(c->buffer); + free(c->ev); + free(c); + return NULL; + } + c->tcp_is_reading = 0; + c->tcp_byte_count = 0; + c->tcp_parent = parent; + c->max_tcp_count = 0; + c->tcp_handlers = NULL; + c->tcp_free = NULL; + c->type = comm_tcp; + c->tcp_do_close = 0; + c->do_not_close = 0; + c->tcp_do_toggle_rw = 1; + c->tcp_check_nb_connect = 0; + 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) + { + log_err("could not basetset tcphdl event"); + parent->tcp_free = c->tcp_free; + free(c->ev); + free(c); + return NULL; + } + return c; +} + +struct comm_point* +comm_point_create_tcp(struct comm_base *base, int fd, int num, size_t bufsize, + comm_point_callback_t* callback, void* callback_arg) +{ + struct comm_point* c = (struct comm_point*)calloc(1, + sizeof(struct comm_point)); + short evbits; + int i; + /* first allocate the TCP accept listener */ + if(!c) + return NULL; + c->ev = (struct internal_event*)calloc(1, + sizeof(struct internal_event)); + if(!c->ev) { + free(c); + return NULL; + } + c->ev->base = base; + c->fd = fd; + c->buffer = NULL; + c->timeout = NULL; + c->tcp_is_reading = 0; + c->tcp_byte_count = 0; + c->tcp_parent = NULL; + c->max_tcp_count = num; + c->tcp_handlers = (struct comm_point**)calloc((size_t)num, + sizeof(struct comm_point*)); + if(!c->tcp_handlers) { + free(c->ev); + free(c); + return NULL; + } + c->tcp_free = NULL; + c->type = comm_tcp_accept; + c->tcp_do_close = 0; + c->do_not_close = 0; + c->tcp_do_toggle_rw = 0; + c->tcp_check_nb_connect = 0; + 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 ) + { + log_err("could not add tcpacc event"); + comm_point_delete(c); + return NULL; + } + + /* now prealloc the tcp handlers */ + for(i=0; itcp_handlers[i] = comm_point_create_tcp_handler(base, + c, bufsize, callback, callback_arg); + if(!c->tcp_handlers[i]) { + comm_point_delete(c); + return NULL; + } + } + + return c; +} + +struct comm_point* +comm_point_create_tcp_out(struct comm_base *base, size_t bufsize, + comm_point_callback_t* callback, void* callback_arg) +{ + struct comm_point* c = (struct comm_point*)calloc(1, + sizeof(struct comm_point)); + short evbits; + if(!c) + return NULL; + c->ev = (struct internal_event*)calloc(1, + sizeof(struct internal_event)); + if(!c->ev) { + free(c); + return NULL; + } + c->ev->base = base; + c->fd = -1; + c->buffer = ldns_buffer_new(bufsize); + if(!c->buffer) { + free(c->ev); + free(c); + return NULL; + } + c->timeout = NULL; + c->tcp_is_reading = 0; + c->tcp_byte_count = 0; + c->tcp_parent = NULL; + c->max_tcp_count = 0; + c->tcp_handlers = NULL; + c->tcp_free = NULL; + c->type = comm_tcp; + c->tcp_do_close = 0; + c->do_not_close = 0; + c->tcp_do_toggle_rw = 1; + c->tcp_check_nb_connect = 1; + 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) + { + log_err("could not basetset tcpout event"); + ldns_buffer_free(c->buffer); + free(c->ev); + free(c); + return NULL; + } + + return c; +} + +struct comm_point* +comm_point_create_local(struct comm_base *base, int fd, size_t bufsize, + comm_point_callback_t* callback, void* callback_arg) +{ + struct comm_point* c = (struct comm_point*)calloc(1, + sizeof(struct comm_point)); + short evbits; + if(!c) + return NULL; + c->ev = (struct internal_event*)calloc(1, + sizeof(struct internal_event)); + if(!c->ev) { + free(c); + return NULL; + } + c->ev->base = base; + c->fd = fd; + c->buffer = ldns_buffer_new(bufsize); + if(!c->buffer) { + free(c->ev); + free(c); + return NULL; + } + c->timeout = NULL; + c->tcp_is_reading = 1; + c->tcp_byte_count = 0; + c->tcp_parent = NULL; + c->max_tcp_count = 0; + c->tcp_handlers = NULL; + c->tcp_free = NULL; + c->type = comm_local; + c->tcp_do_close = 0; + c->do_not_close = 1; + c->tcp_do_toggle_rw = 0; + c->tcp_check_nb_connect = 0; + 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 ) + { + log_err("could not add localhdl event"); + free(c->ev); + free(c); + return NULL; + } + return c; +} + +struct comm_point* +comm_point_create_raw(struct comm_base* base, int fd, int writing, + comm_point_callback_t* callback, void* callback_arg) +{ + struct comm_point* c = (struct comm_point*)calloc(1, + sizeof(struct comm_point)); + short evbits; + if(!c) + return NULL; + c->ev = (struct internal_event*)calloc(1, + sizeof(struct internal_event)); + if(!c->ev) { + free(c); + return NULL; + } + c->ev->base = base; + c->fd = fd; + c->buffer = NULL; + c->timeout = NULL; + c->tcp_is_reading = 0; + c->tcp_byte_count = 0; + c->tcp_parent = NULL; + c->max_tcp_count = 0; + c->tcp_handlers = NULL; + c->tcp_free = NULL; + c->type = comm_raw; + c->tcp_do_close = 0; + c->do_not_close = 1; + c->tcp_do_toggle_rw = 0; + c->tcp_check_nb_connect = 0; + c->callback = callback; + c->cb_arg = callback_arg; + /* libevent 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 ) + { + log_err("could not add rawhdl event"); + free(c->ev); + free(c); + return NULL; + } + return c; +} + +void +comm_point_close(struct comm_point* c) +{ + if(!c) + return; + if(c->fd != -1) + if(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 */ + if(c->fd != -1 && !c->do_not_close) { + verbose(VERB_ALGO, "close fd %d", c->fd); +#ifndef USE_WINSOCK + close(c->fd); +#else + closesocket(c->fd); +#endif + } + c->fd = -1; +} + +void +comm_point_delete(struct comm_point* c) +{ + if(!c) + return; + if(c->type == comm_tcp && c->ssl) { + SSL_shutdown(c->ssl); + SSL_free(c->ssl); + } + comm_point_close(c); + if(c->tcp_handlers) { + int i; + for(i=0; imax_tcp_count; i++) + comm_point_delete(c->tcp_handlers[i]); + free(c->tcp_handlers); + } + free(c->timeout); + if(c->type == comm_tcp || c->type == comm_local) + ldns_buffer_free(c->buffer); + free(c->ev); + free(c); +} + +void +comm_point_send_reply(struct comm_reply *repinfo) +{ + log_assert(repinfo && repinfo->c); + if(repinfo->c->type == comm_udp) { + if(repinfo->srctype) + comm_point_send_udp_msg_if(repinfo->c, + repinfo->c->buffer, (struct sockaddr*)&repinfo->addr, + repinfo->addrlen, repinfo); + else + comm_point_send_udp_msg(repinfo->c, repinfo->c->buffer, + (struct sockaddr*)&repinfo->addr, repinfo->addrlen); + } else { + comm_point_start_listening(repinfo->c, -1, TCP_QUERY_TIMEOUT); + } +} + +void +comm_point_drop_reply(struct comm_reply* repinfo) +{ + if(!repinfo) + return; + log_assert(repinfo && repinfo->c); + log_assert(repinfo->c->type != comm_tcp_accept); + if(repinfo->c->type == comm_udp) + return; + reclaim_tcp_handler(repinfo->c); +} + +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) { + log_err("event_del error to stoplisten"); + } +} + +void +comm_point_start_listening(struct comm_point* c, int newfd, int sec) +{ + verbose(VERB_ALGO, "comm point start listening %d", + c->fd==-1?newfd:c->fd); + if(c->type == comm_tcp_accept && !c->tcp_free) { + /* no use to start listening no free slots. */ + return; + } + if(sec != -1 && sec != 0) { + if(!c->timeout) { + c->timeout = (struct timeval*)malloc(sizeof( + struct timeval)); + if(!c->timeout) { + log_err("cpsl: malloc failed. No net read."); + return; + } + } + c->ev->ev.ev_events |= EV_TIMEOUT; +#ifndef S_SPLINT_S /* splint fails on struct timeval. */ + c->timeout->tv_sec = sec; + c->timeout->tv_usec = 0; +#endif /* S_SPLINT_S */ + } + if(c->type == comm_tcp) { + c->ev->ev.ev_events &= ~(EV_READ|EV_WRITE); + if(c->tcp_is_reading) + c->ev->ev.ev_events |= EV_READ; + else c->ev->ev.ev_events |= EV_WRITE; + } + if(newfd != -1) { + if(c->fd != -1) { +#ifndef USE_WINSOCK + close(c->fd); +#else + closesocket(c->fd); +#endif + } + c->fd = newfd; + c->ev->ev.ev_fd = c->fd; + } + if(event_add(&c->ev->ev, sec==0?NULL:c->timeout) != 0) { + log_err("event_add failed. in cpsl."); + } +} + +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) { + 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) { + log_err("event_add failed. in cplf."); + } +} + +size_t comm_point_get_mem(struct comm_point* c) +{ + size_t s; + if(!c) + return 0; + s = sizeof(*c) + sizeof(*c->ev); + if(c->timeout) + s += sizeof(*c->timeout); + if(c->type == comm_tcp || c->type == comm_local) + s += sizeof(*c->buffer) + ldns_buffer_capacity(c->buffer); + if(c->type == comm_tcp_accept) { + int i; + for(i=0; imax_tcp_count; i++) + s += comm_point_get_mem(c->tcp_handlers[i]); + } + return s; +} + +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, + sizeof(struct internal_timer)); + if(!tm->ev_timer) { + 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) { + log_err("timer_create: event_base_set failed."); + free(tm->ev_timer); + free(tm); + return NULL; + } + return tm; +} + +void +comm_timer_disable(struct comm_timer* timer) +{ + if(!timer) + return; + evtimer_del(&timer->ev_timer->ev); + timer->ev_timer->enabled = 0; +} + +void +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) + log_err("comm_timer_set: evtimer_add failed."); + timer->ev_timer->enabled = 1; +} + +void +comm_timer_delete(struct comm_timer* timer) +{ + if(!timer) + return; + comm_timer_disable(timer); + 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)) + return; + 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); +} + +int +comm_timer_is_set(struct comm_timer* timer) +{ + return (int)timer->ev_timer->enabled; +} + +size_t +comm_timer_get_mem(struct comm_timer* timer) +{ + return sizeof(*timer) + sizeof(struct internal_timer); +} + +struct comm_signal* +comm_signal_create(struct comm_base* base, + void (*callback)(int, void*), void* cb_arg) +{ + struct comm_signal* com = (struct comm_signal*)malloc( + sizeof(struct comm_signal)); + if(!com) { + log_err("malloc failed"); + return NULL; + } + com->base = base; + com->callback = callback; + com->cb_arg = cb_arg; + com->ev_signal = NULL; + return com; +} + +void +comm_signal_callback(int sig, short event, void* arg) +{ + struct comm_signal* comsig = (struct comm_signal*)arg; + if(!(event & EV_SIGNAL)) + return; + comm_base_now(comsig->base); + fptr_ok(fptr_whitelist_comm_signal(comsig->callback)); + (*comsig->callback)(sig, comsig->cb_arg); +} + +int +comm_signal_bind(struct comm_signal* comsig, int sig) +{ + struct internal_signal* entry = (struct internal_signal*)calloc(1, + sizeof(struct internal_signal)); + if(!entry) { + log_err("malloc failed"); + return 0; + } + 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"); + free(entry); + return 0; + } + if(signal_add(&entry->ev, NULL) != 0) { + log_err("Could not add signal handler"); + free(entry); + return 0; + } + /* link into list */ + entry->next = comsig->ev_signal; + comsig->ev_signal = entry; + return 1; +} + +void +comm_signal_delete(struct comm_signal* comsig) +{ + struct internal_signal* p, *np; + if(!comsig) + return; + p=comsig->ev_signal; + while(p) { + np = p->next; + signal_del(&p->ev); + free(p); + p = np; + } + free(comsig); +} diff --git a/util/netevent.h b/util/netevent.h new file mode 100644 index 00000000000..0ea4cf04145 --- /dev/null +++ b/util/netevent.h @@ -0,0 +1,684 @@ +/* + * util/netevent.h - event notification + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains event notification functions. + * + * There are three types of communication points + * o UDP socket - perthread buffer. + * o TCP-accept socket - array of TCP-sockets, socketcount. + * o TCP socket - own buffer, parent-TCPaccept, read/write state, + * number of bytes read/written, timeout. + * + * There are sockets aimed towards our clients and towards the internet. + * o frontside - aimed towards our clients, queries come in, answers back. + * o behind - aimed towards internet, to the authoritative DNS servers. + * + * Several event types are available: + * o comm_base - for thread safety of the comm points, one per thread. + * o comm_point - udp and tcp networking, with callbacks. + * o comm_timer - a timeout with callback. + * o comm_signal - callbacks when signal is caught. + * o comm_reply - holds reply info during networking callback. + * + */ + +#ifndef NET_EVENT_H +#define NET_EVENT_H + +#include +struct comm_point; +struct comm_reply; +struct event_base; + +/* internal event notification data storage structure. */ +struct internal_event; +struct internal_base; +struct internal_timer; + +/** callback from communication point function type */ +typedef int comm_point_callback_t(struct comm_point*, void*, int, + struct comm_reply*); + +/** to pass no_error to callback function */ +#define NETEVENT_NOERROR 0 +/** to pass closed connection to callback function */ +#define NETEVENT_CLOSED -1 +/** to pass timeout happened to callback function */ +#define NETEVENT_TIMEOUT -2 +/** to pass fallback from capsforID to callback function; 0x20 failed */ +#define NETEVENT_CAPSFAIL -3 + +/** timeout to slow accept calls when not possible, in msec. */ +#define NETEVENT_SLOW_ACCEPT_TIME 2000 + +/** + * A communication point dispatcher. Thread specific. + */ +struct comm_base { + /** behind the scenes structure. with say libevent info. alloced */ + struct internal_base* eb; + /** callback to stop listening on accept sockets, + * performed when accept() will not function properly */ + void (*stop_accept)(void*); + /** callback to start listening on accept sockets, performed + * after stop_accept() then a timeout has passed. */ + void (*start_accept)(void*); + /** user argument for stop_accept and start_accept functions */ + void* cb_arg; +}; + +/** + * Reply information for a communication point. + */ +struct comm_reply { + /** the comm_point with fd to send reply on to. */ + struct comm_point* c; + /** the address (for UDP based communication) */ + struct sockaddr_storage addr; + /** length of address */ + socklen_t addrlen; + /** return type 0 (none), 4(IP4), 6(IP6) */ + int srctype; + /** the return source interface data */ + union { +#ifdef IPV6_PKTINFO + struct in6_pktinfo v6info; +#endif +#ifdef IP_PKTINFO + struct in_pktinfo v4info; +#elif defined(IP_RECVDSTADDR) + struct in_addr v4addr; +#endif + } + /** variable with return source data */ + pktinfo; +}; + +/** + * Communication point to the network + * These behaviours can be accomplished by setting the flags + * and passing return values from the callback. + * udp frontside: called after readdone. sendafter. + * tcp frontside: called readdone, sendafter. close. + * udp behind: called after readdone. No send after. + * tcp behind: write done, read done, then called. No send after. + */ +struct comm_point { + /** behind the scenes structure, with say libevent info. alloced. */ + struct internal_event* ev; + + /** file descriptor for communication point */ + int fd; + + /** timeout (NULL if it does not). Malloced. */ + struct timeval* timeout; + + /** buffer pointer. Either to perthread, or own buffer or NULL */ + ldns_buffer* buffer; + + /* -------- TCP Handler -------- */ + /** Read/Write state for TCP */ + int tcp_is_reading; + /** The current read/write count for TCP */ + size_t tcp_byte_count; + /** parent communication point (for TCP sockets) */ + struct comm_point* tcp_parent; + /** sockaddr from peer, for TCP handlers */ + struct comm_reply repinfo; + + /* -------- TCP Accept -------- */ + /** the number of TCP handlers for this tcp-accept socket */ + int max_tcp_count; + /** malloced array of tcp handlers for a tcp-accept, + of size max_tcp_count. */ + struct comm_point** tcp_handlers; + /** linked list of free tcp_handlers to use for new queries. + For tcp_accept the first entry, for tcp_handlers the next one. */ + struct comm_point* tcp_free; + + /* -------- SSL TCP DNS ------- */ + /** the SSL object with rw bio (owned) or for commaccept ctx ref */ + void* ssl; + /** handshake state for init and renegotiate */ + enum { + /** no handshake, it has been done */ + comm_ssl_shake_none = 0, + /** ssl initial handshake wants to read */ + comm_ssl_shake_read, + /** ssl initial handshake wants to write */ + comm_ssl_shake_write, + /** ssl_write wants to read */ + comm_ssl_shake_hs_read, + /** ssl_read wants to write */ + comm_ssl_shake_hs_write + } ssl_shake_state; + + /** is this a UDP, TCP-accept or TCP socket. */ + enum comm_point_type { + /** UDP socket - handle datagrams. */ + comm_udp, + /** TCP accept socket - only creates handlers if readable. */ + comm_tcp_accept, + /** TCP handler socket - handle byteperbyte readwrite. */ + comm_tcp, + /** AF_UNIX socket - for internal commands. */ + comm_local, + /** raw - not DNS format - for pipe readers and writers */ + comm_raw + } + /** variable with type of socket, UDP,TCP-accept,TCP,pipe */ + type; + + /* ---------- Behaviour ----------- */ + /** if set the connection is NOT closed on delete. */ + int do_not_close; + + /** if set, the connection is closed on error, on timeout, + and after read/write completes. No callback is done. */ + int tcp_do_close; + + /** if set, read/write completes: + read/write state of tcp is toggled. + buffer reset/bytecount reset. + this flag cleared. + So that when that is done the callback is called. */ + int tcp_do_toggle_rw; + + /** if set, checks for pending error from nonblocking connect() call.*/ + int tcp_check_nb_connect; + + /** number of queries outstanding on this socket, used by + * outside network for udp ports */ + int inuse; + + /** callback when done. + tcp_accept does not get called back, is NULL then. + If a timeout happens, callback with timeout=1 is called. + If an error happens, callback is called with error set + nonzero. If not NETEVENT_NOERROR, it is an errno value. + If the connection is closed (by remote end) then the + callback is called with error set to NETEVENT_CLOSED=-1. + If a timeout happens on the connection, the error is set to + NETEVENT_TIMEOUT=-2. + The reply_info can be copied if the reply needs to happen at a + later time. It consists of a struct with commpoint and address. + It can be passed to a msg send routine some time later. + Note the reply information is temporary and must be copied. + NULL is passed for_reply info, in cases where error happened. + + declare as: + int my_callback(struct comm_point* c, void* my_arg, int error, + struct comm_reply *reply_info); + + if the routine returns 0, nothing is done. + Notzero, the buffer will be sent back to client. + For UDP this is done without changing the commpoint. + In TCP it sets write state. + */ + comm_point_callback_t* callback; + /** argument to pass to callback. */ + void *cb_arg; +}; + +/** + * Structure only for making timeout events. + */ +struct comm_timer { + /** the internal event stuff */ + struct internal_timer* ev_timer; + + /** callback function, takes user arg only */ + void (*callback)(void*); + + /** callback user argument */ + void* cb_arg; +}; + +/** + * Structure only for signal events. + */ +struct comm_signal { + /** the communication base */ + struct comm_base* base; + + /** the internal event stuff */ + struct internal_signal* ev_signal; + + /** callback function, takes signal number and user arg */ + void (*callback)(int, void*); + + /** callback user argument */ + void* cb_arg; +}; + +/** + * Create a new comm base. + * @param sigs: if true it attempts to create a default loop for + * signal handling. + * @return: the new comm base. NULL on error. + */ +struct comm_base* comm_base_create(int sigs); + +/** + * Destroy a comm base. + * All comm points must have been deleted. + * @param b: the base to delete. + */ +void comm_base_delete(struct comm_base* b); + +/** + * Obtain two pointers. The pointers never change (until base_delete()). + * The pointers point to time values that are updated regularly. + * @param b: the communication base that will update the time values. + * @param tt: pointer to time in seconds is returned. + * @param tv: pointer to time in microseconds is returned. + */ +void comm_base_timept(struct comm_base* b, uint32_t** tt, struct timeval** tv); + +/** + * Dispatch the comm base events. + * @param b: the communication to perform. + */ +void comm_base_dispatch(struct comm_base* b); + +/** + * Exit from dispatch loop. + * @param b: the communication base that is in dispatch(). + */ +void comm_base_exit(struct comm_base* b); + +/** + * Set the slow_accept mode handlers. You can not provide these if you do + * not perform accept() calls. + * @param b: comm base + * @param stop_accept: function that stops listening to accept fds. + * @param start_accept: function that resumes listening to accept fds. + * @param arg: callback arg to pass to the functions. + */ +void comm_base_set_slow_accept_handlers(struct comm_base* b, + void (*stop_accept)(void*), void (*start_accept)(void*), void* arg); + +/** + * Access internal data structure (for util/tube.c on windows) + * @param b: comm base + * @return event_base. Could be libevent, or internal event handler. + */ +struct event_base* comm_base_internal(struct comm_base* b); + +/** + * Create an UDP comm point. Calls malloc. + * setups the structure with the parameters you provide. + * @param base: in which base to alloc the commpoint. + * @param fd : file descriptor of open UDP socket. + * @param buffer: shared buffer by UDP sockets from this thread. + * @param callback: callback function pointer. + * @param callback_arg: will be passed to your callback function. + * @return: returns the allocated communication point. NULL on error. + * Sets timeout to NULL. Turns off TCP options. + */ +struct comm_point* comm_point_create_udp(struct comm_base* base, + int fd, ldns_buffer* buffer, + comm_point_callback_t* callback, void* callback_arg); + +/** + * Create an UDP with ancillary data comm point. Calls malloc. + * Uses recvmsg instead of recv to get udp message. + * setups the structure with the parameters you provide. + * @param base: in which base to alloc the commpoint. + * @param fd : file descriptor of open UDP socket. + * @param buffer: shared buffer by UDP sockets from this thread. + * @param callback: callback function pointer. + * @param callback_arg: will be passed to your callback function. + * @return: returns the allocated communication point. NULL on error. + * Sets timeout to NULL. Turns off TCP options. + */ +struct comm_point* comm_point_create_udp_ancil(struct comm_base* base, + int fd, ldns_buffer* buffer, + comm_point_callback_t* callback, void* callback_arg); + +/** + * Create a TCP listener comm point. Calls malloc. + * Setups the structure with the parameters you provide. + * Also Creates TCP Handlers, pre allocated for you. + * Uses the parameters you provide. + * @param base: in which base to alloc the commpoint. + * @param fd: file descriptor of open TCP socket set to listen nonblocking. + * @param num: becomes max_tcp_count, the routine allocates that + * many tcp handler commpoints. + * @param bufsize: size of buffer to create for handlers. + * @param callback: callback function pointer for TCP handlers. + * @param callback_arg: will be passed to your callback function. + * @return: returns the TCP listener commpoint. You can find the + * TCP handlers in the array inside the listener commpoint. + * returns NULL on error. + * Inits timeout to NULL. All handlers are on the free list. + */ +struct comm_point* comm_point_create_tcp(struct comm_base* base, + int fd, int num, size_t bufsize, + comm_point_callback_t* callback, void* callback_arg); + +/** + * Create an outgoing TCP commpoint. No file descriptor is opened, left at -1. + * @param base: in which base to alloc the commpoint. + * @param bufsize: size of buffer to create for handlers. + * @param callback: callback function pointer for the handler. + * @param callback_arg: will be passed to your callback function. + * @return: the commpoint or NULL on error. + */ +struct comm_point* comm_point_create_tcp_out(struct comm_base* base, + size_t bufsize, comm_point_callback_t* callback, void* callback_arg); + +/** + * Create commpoint to listen to a local domain file descriptor. + * @param base: in which base to alloc the commpoint. + * @param fd: file descriptor of open AF_UNIX socket set to listen nonblocking. + * @param bufsize: size of buffer to create for handlers. + * @param callback: callback function pointer for the handler. + * @param callback_arg: will be passed to your callback function. + * @return: the commpoint or NULL on error. + */ +struct comm_point* comm_point_create_local(struct comm_base* base, + int fd, size_t bufsize, + comm_point_callback_t* callback, void* callback_arg); + +/** + * Create commpoint to listen to a local domain pipe descriptor. + * @param base: in which base to alloc the commpoint. + * @param fd: file descriptor. + * @param writing: true if you want to listen to writes, false for reads. + * @param callback: callback function pointer for the handler. + * @param callback_arg: will be passed to your callback function. + * @return: the commpoint or NULL on error. + */ +struct comm_point* comm_point_create_raw(struct comm_base* base, + int fd, int writing, + comm_point_callback_t* callback, void* callback_arg); + +/** + * Close a comm point fd. + * @param c: comm point to close. + */ +void comm_point_close(struct comm_point* c); + +/** + * Close and deallocate (free) the comm point. If the comm point is + * a tcp-accept point, also its tcp-handler points are deleted. + * @param c: comm point to delete. + */ +void comm_point_delete(struct comm_point* c); + +/** + * Send reply. Put message into commpoint buffer. + * @param repinfo: The reply info copied from a commpoint callback call. + */ +void comm_point_send_reply(struct comm_reply* repinfo); + +/** + * Drop reply. Cleans up. + * @param repinfo: The reply info copied from a commpoint callback call. + */ +void comm_point_drop_reply(struct comm_reply* repinfo); + +/** + * Send an udp message over a commpoint. + * @param c: commpoint to send it from. + * @param packet: what to send. + * @param addr: where to send it to. + * @param addrlen: length of addr. + * @return: false on a failure. + */ +int comm_point_send_udp_msg(struct comm_point* c, ldns_buffer* packet, + struct sockaddr* addr, socklen_t addrlen); + +/** + * Stop listening for input on the commpoint. No callbacks will happen. + * @param c: commpoint to disable. The fd is not closed. + */ +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. + */ +void comm_point_start_listening(struct comm_point* c, int newfd, int sec); + +/** + * Stop listening and start listening again for reading or writing. + * @param c: commpoint + * @param rd: if true, listens for reading. + * @param wr: if true, listens for writing. + */ +void comm_point_listen_for_rw(struct comm_point* c, int rd, int wr); + +/** + * Get size of memory used by comm point. + * For TCP handlers this includes subhandlers. + * For UDP handlers, this does not include the (shared) UDP buffer. + * @param c: commpoint. + * @return size in bytes. + */ +size_t comm_point_get_mem(struct comm_point* c); + +/** + * create timer. Not active upon creation. + * @param base: event handling base. + * @param cb: callback function: void myfunc(void* myarg); + * @param cb_arg: user callback argument. + * @return: the new timer or NULL on error. + */ +struct comm_timer* comm_timer_create(struct comm_base* base, + void (*cb)(void*), void* cb_arg); + +/** + * disable timer. Stops callbacks from happening. + * @param timer: to disable. + */ +void comm_timer_disable(struct comm_timer* timer); + +/** + * reset timevalue for timer. + * @param timer: timer to (re)set. + * @param tv: when the timer should activate. if NULL timer is disabled. + */ +void comm_timer_set(struct comm_timer* timer, struct timeval* tv); + +/** + * delete timer. + * @param timer: to delete. + */ +void comm_timer_delete(struct comm_timer* timer); + +/** + * see if timeout has been set to a value. + * @param timer: the timer to examine. + * @return: false if disabled or not set. + */ +int comm_timer_is_set(struct comm_timer* timer); + +/** + * Get size of memory used by comm timer. + * @param timer: the timer to examine. + * @return size in bytes. + */ +size_t comm_timer_get_mem(struct comm_timer* timer); + +/** + * Create a signal handler. Call signal_bind() later to bind to a signal. + * @param base: communication base to use. + * @param callback: called when signal is caught. + * @param cb_arg: user argument to callback + * @return: the signal struct or NULL on error. + */ +struct comm_signal* comm_signal_create(struct comm_base* base, + void (*callback)(int, void*), void* cb_arg); + +/** + * Bind signal struct to catch a signal. A signle comm_signal can be bound + * to multiple signals, calling comm_signal_bind multiple times. + * @param comsig: the communication point, with callback information. + * @param sig: signal number. + * @return: true on success. false on error. + */ +int comm_signal_bind(struct comm_signal* comsig, int sig); + +/** + * Delete the signal communication point. + * @param comsig: to delete. + */ +void comm_signal_delete(struct comm_signal* comsig); + +/** + * perform accept(2) with error checking. + * @param c: commpoint with accept fd. + * @param addr: remote end returned here. + * @param addrlen: length of remote end returned here. + * @return new fd, or -1 on error. + * if -1, error message has been printed if necessary, simply drop + * out of the reading handler. + */ +int comm_point_perform_accept(struct comm_point* c, + struct sockaddr_storage* addr, socklen_t* addrlen); + +/**** internal routines ****/ + +/** + * This routine is published for checks and tests, and is only used internally. + * handle libevent callback for udp comm point. + * @param fd: file descriptor. + * @param event: event bits from libevent: + * EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT. + * @param arg: the comm_point structure. + */ +void comm_point_udp_callback(int fd, short event, void* arg); + +/** + * This routine is published for checks and tests, and is only used internally. + * handle libevent callback for udp ancillary data comm point. + * @param fd: file descriptor. + * @param event: event bits from libevent: + * EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT. + * @param arg: the comm_point structure. + */ +void comm_point_udp_ancil_callback(int fd, short event, void* arg); + +/** + * This routine is published for checks and tests, and is only used internally. + * handle libevent callback for tcp accept comm point + * @param fd: file descriptor. + * @param event: event bits from libevent: + * EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT. + * @param arg: the comm_point structure. + */ +void comm_point_tcp_accept_callback(int fd, short event, void* arg); + +/** + * This routine is published for checks and tests, and is only used internally. + * handle libevent callback for tcp data comm point + * @param fd: file descriptor. + * @param event: event bits from libevent: + * EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT. + * @param arg: the comm_point structure. + */ +void comm_point_tcp_handle_callback(int fd, short event, void* arg); + +/** + * This routine is published for checks and tests, and is only used internally. + * handle libevent callback for timer comm. + * @param fd: file descriptor (always -1). + * @param event: event bits from libevent: + * EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT. + * @param arg: the comm_timer structure. + */ +void comm_timer_callback(int fd, short event, void* arg); + +/** + * This routine is published for checks and tests, and is only used internally. + * handle libevent callback for signal comm. + * @param fd: file descriptor (used for the signal number). + * @param event: event bits from libevent: + * EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT. + * @param arg: the internal commsignal structure. + */ +void comm_signal_callback(int fd, short event, void* arg); + +/** + * This routine is published for checks and tests, and is only used internally. + * libevent callback for AF_UNIX fds + * @param fd: file descriptor. + * @param event: event bits from libevent: + * EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT. + * @param arg: the comm_point structure. + */ +void comm_point_local_handle_callback(int fd, short event, void* arg); + +/** + * This routine is published for checks and tests, and is only used internally. + * libevent callback for raw fd access. + * @param fd: file descriptor. + * @param event: event bits from libevent: + * EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT. + * @param arg: the comm_point structure. + */ +void comm_point_raw_handle_callback(int fd, short event, void* arg); + +/** + * This routine is published for checks and tests, and is only used internally. + * libevent callback for timeout on slow accept. + * @param fd: file descriptor. + * @param event: event bits from libevent: + * EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT. + * @param arg: the comm_point structure. + */ +void comm_base_handle_slow_accept(int fd, short event, void* arg); + +#ifdef USE_WINSOCK +/** + * Callback for openssl BIO to on windows detect WSAEWOULDBLOCK and notify + * the winsock_event of this for proper TCP nonblocking implementation. + * @param c: comm_point, fd must be set its struct event is registered. + * @param ssl: openssl SSL, fd must be set so it has a bio. + */ +void comm_point_tcp_win_bio_cb(struct comm_point* c, void* ssl); +#endif + +/** see if errno for tcp connect has to be logged or not. This uses errno */ +int tcp_connect_errno_needs_log(struct sockaddr* addr, socklen_t addrlen); + +#endif /* NET_EVENT_H */ diff --git a/util/random.c b/util/random.c new file mode 100644 index 00000000000..72c58a2b4df --- /dev/null +++ b/util/random.c @@ -0,0 +1,203 @@ +/* + * util/random.c - thread safe random generator, which is reasonably secure. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * Thread safe random functions. Similar to arc4random() with an explicit + * initialisation routine. + * + * The code in this file is based on arc4random from + * openssh-4.0p1/openbsd-compat/bsd-arc4random.c + * That code is also BSD licensed. Here is their statement: + * + * Copyright (c) 1996, David Mazieres + * Copyright (c) 2008, Damien Miller + * + * 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. + */ +#include "config.h" +#include "util/random.h" +#include "util/log.h" +#include +#include +#include + +/** + * Struct with per-thread random state. + * Keeps SSL types away from the header file. + */ +struct ub_randstate { + /** key used for arc4random generation */ + RC4_KEY rc4; + /** keeps track of key usage */ + int rc4_ready; +}; + +/** Size of key to use (must be multiple of 8) */ +#define SEED_SIZE 24 + +/** + * Max random value. Similar to RAND_MAX, but more portable + * (mingw uses only 15 bits random). + */ +#define MAX_VALUE 0x7fffffff + +/** Number of bytes to reseed after */ +#define REKEY_BYTES (1 << 24) + +/* (re)setup system seed */ +void +ub_systemseed(unsigned int seed) +{ + /* RAND_ is threadsafe, by the way */ + if(!RAND_status()) { + /* try to seed it */ + unsigned char buf[256]; + unsigned int v = seed; + size_t i; + for(i=0; i<256/sizeof(seed); i++) { + memmove(buf+i*sizeof(seed), &v, sizeof(seed)); + v = v*seed + (unsigned int)i; + } + RAND_seed(buf, 256); + if(!RAND_status()) { + log_err("Random generator has no entropy " + "(error %ld)", ERR_get_error()); + } else { + verbose(VERB_OPS, "openssl has no entropy, " + "seeding with time and pid"); + } + } +} + +/** reseed random generator */ +static void +ub_arc4random_stir(struct ub_randstate* s, struct ub_randstate* from) +{ + /* not as unsigned char, but longerint so that it is + aligned properly on alignment sensitive platforms */ + uint64_t rand_buf[SEED_SIZE/sizeof(uint64_t)]; + int i; + + memset(&s->rc4, 0, sizeof(s->rc4)); + memset(rand_buf, 0xc, sizeof(rand_buf)); + if (from) { + uint8_t* rbuf = (uint8_t*)rand_buf; + for(i=0; irc4_ready = 256; + return; + } + } + RC4_set_key(&s->rc4, SEED_SIZE, (unsigned char*)rand_buf); + + /* + * Discard early keystream, as per recommendations in: + * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps + */ + for(i = 0; i <= 256; i += sizeof(rand_buf)) + RC4(&s->rc4, sizeof(rand_buf), (unsigned char*)rand_buf, + (unsigned char*)rand_buf); + + memset(rand_buf, 0, sizeof(rand_buf)); + + s->rc4_ready = REKEY_BYTES; +} + +struct ub_randstate* +ub_initstate(unsigned int seed, struct ub_randstate* from) +{ + struct ub_randstate* s = (struct ub_randstate*)calloc(1, sizeof(*s)); + if(!s) { + log_err("malloc failure in random init"); + return NULL; + } + ub_systemseed(seed); + ub_arc4random_stir(s, from); + return s; +} + +long int +ub_random(struct ub_randstate* s) +{ + unsigned int r = 0; + if (s->rc4_ready <= 0) { + ub_arc4random_stir(s, NULL); + } + + RC4(&s->rc4, sizeof(r), + (unsigned char *)&r, (unsigned char *)&r); + s->rc4_ready -= sizeof(r); + return (long int)((r) % (((unsigned)MAX_VALUE + 1))); +} + +long int +ub_random_max(struct ub_randstate* state, long int x) +{ + /* make sure we fetch in a range that is divisible by x. ignore + * values from d .. MAX_VALUE, instead draw a new number */ + long int d = MAX_VALUE - (MAX_VALUE % x); /* d is divisible by x */ + long int v = ub_random(state); + while(d <= v) + v = ub_random(state); + return (v % x); +} + +void +ub_randfree(struct ub_randstate* s) +{ + if(s) + free(s); + /* user app must do RAND_cleanup(); */ +} diff --git a/util/random.h b/util/random.h new file mode 100644 index 00000000000..99879dca814 --- /dev/null +++ b/util/random.h @@ -0,0 +1,93 @@ +/* + * util/random.h - thread safe random generator, which is reasonably secure. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef UTIL_RANDOM_H +#define UTIL_RANDOM_H + +/** + * \file + * Thread safe random functions. Similar to arc4random() with an explicit + * initialisation routine. + */ + +/** + * random state structure. + */ +struct ub_randstate; + +/** + * Initialize the system randomness. Obtains entropy from the system + * before a chroot or privilege makes it unavailable. + * You do not have to call this, otherwise ub_initstate does so. + * @param seed: seed value to create state (if no good entropy is found). + */ +void ub_systemseed(unsigned int seed); + +/** + * Initialize a random generator state for use + * @param seed: seed value to create state contents. + * (ignored for arc4random). + * @param from: if not NULL, the seed is taken from this random structure. + * can be used to seed random states via a parent-random-state that + * is itself seeded with entropy. + * @return new state or NULL alloc failure. + */ +struct ub_randstate* ub_initstate(unsigned int seed, + struct ub_randstate* from); + +/** + * Generate next random number from the state passed along. + * Thread safe, so random numbers are repeatable. + * @param state: must have been initialised with ub_initstate. + * @return: random 31 bit value. + */ +long int ub_random(struct ub_randstate* state); + +/** + * Generate random number between 0 and x-1. No modulo bias. + * @param state: must have been initialised with ub_initstate. + * @param x: an upper limit. not (negative or zero). must be smaller than 2**31. + * @return: random value between 0..x-1. Possibly more than one + * random number is picked from the random stream to satisfy this. + */ +long int ub_random_max(struct ub_randstate* state, long int x); + +/** + * Delete the random state. + * @param state: to delete. + */ +void ub_randfree(struct ub_randstate* state); + +#endif /* UTIL_RANDOM_H */ diff --git a/util/rbtree.c b/util/rbtree.c new file mode 100644 index 00000000000..d31afd9c54c --- /dev/null +++ b/util/rbtree.c @@ -0,0 +1,620 @@ +/* + * rbtree.c -- generic red black tree + * + * Copyright (c) 2001-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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * \file + * Implementation of a redblack tree. + */ + +#include "config.h" +#include "log.h" +#include "fptr_wlist.h" +#include "util/rbtree.h" + +/** Node colour black */ +#define BLACK 0 +/** Node colour red */ +#define RED 1 + +/** the NULL node, global alloc */ +rbnode_t rbtree_null_node = { + RBTREE_NULL, /* Parent. */ + RBTREE_NULL, /* Left. */ + RBTREE_NULL, /* Right. */ + NULL, /* Key. */ + BLACK /* Color. */ +}; + +/** rotate subtree left (to preserve redblack property) */ +static void rbtree_rotate_left(rbtree_t *rbtree, rbnode_t *node); +/** rotate subtree right (to preserve redblack property) */ +static void rbtree_rotate_right(rbtree_t *rbtree, rbnode_t *node); +/** Fixup node colours when insert happened */ +static void rbtree_insert_fixup(rbtree_t *rbtree, rbnode_t *node); +/** Fixup node colours when delete happened */ +static void rbtree_delete_fixup(rbtree_t* rbtree, rbnode_t* child, rbnode_t* child_parent); + +/* + * Creates a new red black tree, intializes and returns a pointer to it. + * + * Return NULL on failure. + * + */ +rbtree_t * +rbtree_create (int (*cmpf)(const void *, const void *)) +{ + rbtree_t *rbtree; + + /* Allocate memory for it */ + rbtree = (rbtree_t *) malloc(sizeof(rbtree_t)); + if (!rbtree) { + return NULL; + } + + /* Initialize it */ + rbtree_init(rbtree, cmpf); + + return rbtree; +} + +void +rbtree_init(rbtree_t *rbtree, int (*cmpf)(const void *, const void *)) +{ + /* Initialize it */ + rbtree->root = RBTREE_NULL; + rbtree->count = 0; + rbtree->cmp = cmpf; +} + +/* + * Rotates the node to the left. + * + */ +static void +rbtree_rotate_left(rbtree_t *rbtree, rbnode_t *node) +{ + rbnode_t *right = node->right; + node->right = right->left; + if (right->left != RBTREE_NULL) + right->left->parent = node; + + right->parent = node->parent; + + if (node->parent != RBTREE_NULL) { + if (node == node->parent->left) { + node->parent->left = right; + } else { + node->parent->right = right; + } + } else { + rbtree->root = right; + } + right->left = node; + node->parent = right; +} + +/* + * Rotates the node to the right. + * + */ +static void +rbtree_rotate_right(rbtree_t *rbtree, rbnode_t *node) +{ + rbnode_t *left = node->left; + node->left = left->right; + if (left->right != RBTREE_NULL) + left->right->parent = node; + + left->parent = node->parent; + + if (node->parent != RBTREE_NULL) { + if (node == node->parent->right) { + node->parent->right = left; + } else { + node->parent->left = left; + } + } else { + rbtree->root = left; + } + left->right = node; + node->parent = left; +} + +static void +rbtree_insert_fixup(rbtree_t *rbtree, rbnode_t *node) +{ + rbnode_t *uncle; + + /* While not at the root and need fixing... */ + while (node != rbtree->root && node->parent->color == RED) { + /* If our parent is left child of our grandparent... */ + if (node->parent == node->parent->parent->left) { + uncle = node->parent->parent->right; + + /* If our uncle is red... */ + if (uncle->color == RED) { + /* Paint the parent and the uncle black... */ + node->parent->color = BLACK; + uncle->color = BLACK; + + /* And the grandparent red... */ + node->parent->parent->color = RED; + + /* And continue fixing the grandparent */ + node = node->parent->parent; + } else { /* Our uncle is black... */ + /* Are we the right child? */ + if (node == node->parent->right) { + node = node->parent; + rbtree_rotate_left(rbtree, node); + } + /* Now we're the left child, repaint and rotate... */ + node->parent->color = BLACK; + node->parent->parent->color = RED; + rbtree_rotate_right(rbtree, node->parent->parent); + } + } else { + uncle = node->parent->parent->left; + + /* If our uncle is red... */ + if (uncle->color == RED) { + /* Paint the parent and the uncle black... */ + node->parent->color = BLACK; + uncle->color = BLACK; + + /* And the grandparent red... */ + node->parent->parent->color = RED; + + /* And continue fixing the grandparent */ + node = node->parent->parent; + } else { /* Our uncle is black... */ + /* Are we the right child? */ + if (node == node->parent->left) { + node = node->parent; + rbtree_rotate_right(rbtree, node); + } + /* Now we're the right child, repaint and rotate... */ + node->parent->color = BLACK; + node->parent->parent->color = RED; + rbtree_rotate_left(rbtree, node->parent->parent); + } + } + } + rbtree->root->color = BLACK; +} + + +/* + * Inserts a node into a red black tree. + * + * Returns NULL on failure or the pointer to the newly added node + * otherwise. + */ +rbnode_t * +rbtree_insert (rbtree_t *rbtree, rbnode_t *data) +{ + /* XXX Not necessary, but keeps compiler quiet... */ + int r = 0; + + /* We start at the root of the tree */ + rbnode_t *node = rbtree->root; + rbnode_t *parent = RBTREE_NULL; + + fptr_ok(fptr_whitelist_rbtree_cmp(rbtree->cmp)); + /* Lets find the new parent... */ + while (node != RBTREE_NULL) { + /* Compare two keys, do we have a duplicate? */ + if ((r = rbtree->cmp(data->key, node->key)) == 0) { + return NULL; + } + parent = node; + + if (r < 0) { + node = node->left; + } else { + node = node->right; + } + } + + /* Initialize the new node */ + data->parent = parent; + data->left = data->right = RBTREE_NULL; + data->color = RED; + rbtree->count++; + + /* Insert it into the tree... */ + if (parent != RBTREE_NULL) { + if (r < 0) { + parent->left = data; + } else { + parent->right = data; + } + } else { + rbtree->root = data; + } + + /* Fix up the red-black properties... */ + rbtree_insert_fixup(rbtree, data); + + return data; +} + +/* + * Searches the red black tree, returns the data if key is found or NULL otherwise. + * + */ +rbnode_t * +rbtree_search (rbtree_t *rbtree, const void *key) +{ + rbnode_t *node; + + if (rbtree_find_less_equal(rbtree, key, &node)) { + return node; + } else { + return NULL; + } +} + +/** helpers for delete: swap node colours */ +static void swap_int8(uint8_t* x, uint8_t* y) +{ + uint8_t t = *x; *x = *y; *y = t; +} + +/** helpers for delete: swap node pointers */ +static void swap_np(rbnode_t** x, rbnode_t** y) +{ + rbnode_t* t = *x; *x = *y; *y = t; +} + +/** Update parent pointers of child trees of 'parent' */ +static void change_parent_ptr(rbtree_t* rbtree, rbnode_t* parent, rbnode_t* old, rbnode_t* new) +{ + if(parent == RBTREE_NULL) + { + log_assert(rbtree->root == old); + if(rbtree->root == old) rbtree->root = new; + return; + } + log_assert(parent->left == old || parent->right == old + || parent->left == new || parent->right == new); + if(parent->left == old) parent->left = new; + if(parent->right == old) parent->right = new; +} +/** Update parent pointer of a node 'child' */ +static void change_child_ptr(rbnode_t* child, rbnode_t* old, rbnode_t* new) +{ + if(child == RBTREE_NULL) return; + log_assert(child->parent == old || child->parent == new); + if(child->parent == old) child->parent = new; +} + +rbnode_t* +rbtree_delete(rbtree_t *rbtree, const void *key) +{ + rbnode_t *to_delete; + rbnode_t *child; + if((to_delete = rbtree_search(rbtree, key)) == 0) return 0; + rbtree->count--; + + /* make sure we have at most one non-leaf child */ + if(to_delete->left != RBTREE_NULL && to_delete->right != RBTREE_NULL) + { + /* swap with smallest from right subtree (or largest from left) */ + rbnode_t *smright = to_delete->right; + while(smright->left != RBTREE_NULL) + smright = smright->left; + /* swap the smright and to_delete elements in the tree, + * but the rbnode_t is first part of user data struct + * so cannot just swap the keys and data pointers. Instead + * readjust the pointers left,right,parent */ + + /* swap colors - colors are tied to the position in the tree */ + swap_int8(&to_delete->color, &smright->color); + + /* swap child pointers in parents of smright/to_delete */ + change_parent_ptr(rbtree, to_delete->parent, to_delete, smright); + if(to_delete->right != smright) + change_parent_ptr(rbtree, smright->parent, smright, to_delete); + + /* swap parent pointers in children of smright/to_delete */ + change_child_ptr(smright->left, smright, to_delete); + change_child_ptr(smright->left, smright, to_delete); + change_child_ptr(smright->right, smright, to_delete); + change_child_ptr(smright->right, smright, to_delete); + change_child_ptr(to_delete->left, to_delete, smright); + if(to_delete->right != smright) + change_child_ptr(to_delete->right, to_delete, smright); + if(to_delete->right == smright) + { + /* set up so after swap they work */ + to_delete->right = to_delete; + smright->parent = smright; + } + + /* swap pointers in to_delete/smright nodes */ + swap_np(&to_delete->parent, &smright->parent); + swap_np(&to_delete->left, &smright->left); + swap_np(&to_delete->right, &smright->right); + + /* now delete to_delete (which is at the location where the smright previously was) */ + } + log_assert(to_delete->left == RBTREE_NULL || to_delete->right == RBTREE_NULL); + + if(to_delete->left != RBTREE_NULL) child = to_delete->left; + else child = to_delete->right; + + /* unlink to_delete from the tree, replace to_delete with child */ + change_parent_ptr(rbtree, to_delete->parent, to_delete, child); + change_child_ptr(child, to_delete, to_delete->parent); + + if(to_delete->color == RED) + { + /* if node is red then the child (black) can be swapped in */ + } + else if(child->color == RED) + { + /* change child to BLACK, removing a RED node is no problem */ + if(child!=RBTREE_NULL) child->color = BLACK; + } + else rbtree_delete_fixup(rbtree, child, to_delete->parent); + + /* unlink completely */ + to_delete->parent = RBTREE_NULL; + to_delete->left = RBTREE_NULL; + to_delete->right = RBTREE_NULL; + to_delete->color = BLACK; + return to_delete; +} + +static void rbtree_delete_fixup(rbtree_t* rbtree, rbnode_t* child, rbnode_t* child_parent) +{ + rbnode_t* sibling; + int go_up = 1; + + /* determine sibling to the node that is one-black short */ + if(child_parent->right == child) sibling = child_parent->left; + else sibling = child_parent->right; + + while(go_up) + { + if(child_parent == RBTREE_NULL) + { + /* removed parent==black from root, every path, so ok */ + return; + } + + if(sibling->color == RED) + { /* rotate to get a black sibling */ + child_parent->color = RED; + sibling->color = BLACK; + if(child_parent->right == child) + rbtree_rotate_right(rbtree, child_parent); + else rbtree_rotate_left(rbtree, child_parent); + /* new sibling after rotation */ + if(child_parent->right == child) sibling = child_parent->left; + else sibling = child_parent->right; + } + + if(child_parent->color == BLACK + && sibling->color == BLACK + && sibling->left->color == BLACK + && sibling->right->color == BLACK) + { /* fixup local with recolor of sibling */ + if(sibling != RBTREE_NULL) + sibling->color = RED; + + child = child_parent; + child_parent = child_parent->parent; + /* prepare to go up, new sibling */ + if(child_parent->right == child) sibling = child_parent->left; + else sibling = child_parent->right; + } + else go_up = 0; + } + + if(child_parent->color == RED + && sibling->color == BLACK + && sibling->left->color == BLACK + && sibling->right->color == BLACK) + { + /* move red to sibling to rebalance */ + if(sibling != RBTREE_NULL) + sibling->color = RED; + child_parent->color = BLACK; + return; + } + log_assert(sibling != RBTREE_NULL); + + /* get a new sibling, by rotating at sibling. See which child + of sibling is red */ + if(child_parent->right == child + && sibling->color == BLACK + && sibling->right->color == RED + && sibling->left->color == BLACK) + { + sibling->color = RED; + sibling->right->color = BLACK; + rbtree_rotate_left(rbtree, sibling); + /* new sibling after rotation */ + if(child_parent->right == child) sibling = child_parent->left; + else sibling = child_parent->right; + } + else if(child_parent->left == child + && sibling->color == BLACK + && sibling->left->color == RED + && sibling->right->color == BLACK) + { + sibling->color = RED; + sibling->left->color = BLACK; + rbtree_rotate_right(rbtree, sibling); + /* new sibling after rotation */ + if(child_parent->right == child) sibling = child_parent->left; + else sibling = child_parent->right; + } + + /* now we have a black sibling with a red child. rotate and exchange colors. */ + sibling->color = child_parent->color; + child_parent->color = BLACK; + if(child_parent->right == child) + { + log_assert(sibling->left->color == RED); + sibling->left->color = BLACK; + rbtree_rotate_right(rbtree, child_parent); + } + else + { + log_assert(sibling->right->color == RED); + sibling->right->color = BLACK; + rbtree_rotate_left(rbtree, child_parent); + } +} + +int +rbtree_find_less_equal(rbtree_t *rbtree, const void *key, rbnode_t **result) +{ + int r; + rbnode_t *node; + + log_assert(result); + + /* We start at root... */ + node = rbtree->root; + + *result = NULL; + fptr_ok(fptr_whitelist_rbtree_cmp(rbtree->cmp)); + + /* While there are children... */ + while (node != RBTREE_NULL) { + r = rbtree->cmp(key, node->key); + if (r == 0) { + /* Exact match */ + *result = node; + return 1; + } + if (r < 0) { + node = node->left; + } else { + /* Temporary match */ + *result = node; + node = node->right; + } + } + return 0; +} + +/* + * Finds the first element in the red black tree + * + */ +rbnode_t * +rbtree_first (rbtree_t *rbtree) +{ + rbnode_t *node; + + for (node = rbtree->root; node->left != RBTREE_NULL; node = node->left); + return node; +} + +rbnode_t * +rbtree_last (rbtree_t *rbtree) +{ + rbnode_t *node; + + for (node = rbtree->root; node->right != RBTREE_NULL; node = node->right); + return node; +} + +/* + * Returns the next node... + * + */ +rbnode_t * +rbtree_next (rbnode_t *node) +{ + rbnode_t *parent; + + if (node->right != RBTREE_NULL) { + /* One right, then keep on going left... */ + for (node = node->right; node->left != RBTREE_NULL; node = node->left); + } else { + parent = node->parent; + while (parent != RBTREE_NULL && node == parent->right) { + node = parent; + parent = parent->parent; + } + node = parent; + } + return node; +} + +rbnode_t * +rbtree_previous(rbnode_t *node) +{ + rbnode_t *parent; + + if (node->left != RBTREE_NULL) { + /* One left, then keep on going right... */ + for (node = node->left; node->right != RBTREE_NULL; node = node->right); + } else { + parent = node->parent; + while (parent != RBTREE_NULL && node == parent->left) { + node = parent; + parent = parent->parent; + } + node = parent; + } + return node; +} + +/** recursive descent traverse */ +static void +traverse_post(void (*func)(rbnode_t*, void*), void* arg, rbnode_t* node) +{ + if(!node || node == RBTREE_NULL) + return; + /* recurse */ + traverse_post(func, arg, node->left); + traverse_post(func, arg, node->right); + /* call user func */ + (*func)(node, arg); +} + +void +traverse_postorder(rbtree_t* tree, void (*func)(rbnode_t*, void*), void* arg) +{ + traverse_post(func, arg, tree->root); +} diff --git a/util/rbtree.h b/util/rbtree.h new file mode 100644 index 00000000000..879804dd860 --- /dev/null +++ b/util/rbtree.h @@ -0,0 +1,192 @@ +/* + * rbtree.h -- generic red-black tree + * + * Copyright (c) 2001-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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * \file + * Red black tree. Implementation taken from NSD 3.0.5, adjusted for use + * in unbound (memory allocation, logging and so on). + */ + +#ifndef UTIL_RBTREE_H_ +#define UTIL_RBTREE_H_ + +/** + * This structure must be the first member of the data structure in + * the rbtree. This allows easy casting between an rbnode_t and the + * user data (poor man's inheritance). + */ +typedef struct rbnode_t rbnode_t; +/** + * The rbnode_t struct definition. + */ +struct rbnode_t { + /** parent in rbtree, RBTREE_NULL for root */ + rbnode_t *parent; + /** left node (smaller items) */ + rbnode_t *left; + /** right node (larger items) */ + rbnode_t *right; + /** pointer to sorting key */ + const void *key; + /** colour of this node */ + uint8_t color; +}; + +/** The nullpointer, points to empty node */ +#define RBTREE_NULL &rbtree_null_node +/** the global empty node */ +extern rbnode_t rbtree_null_node; + +/** An entire red black tree */ +typedef struct rbtree_t rbtree_t; +/** definition for tree struct */ +struct rbtree_t { + /** The root of the red-black tree */ + rbnode_t *root; + + /** The number of the nodes in the tree */ + size_t count; + + /** + * Key compare function. <0,0,>0 like strcmp. + * Return 0 on two NULL ptrs. + */ + int (*cmp) (const void *, const void *); +}; + +/** + * Create new tree (malloced) with given key compare function. + * @param cmpf: compare function (like strcmp) takes pointers to two keys. + * @return: new tree, empty. + */ +rbtree_t *rbtree_create(int (*cmpf)(const void *, const void *)); + +/** + * Init a new tree (malloced by caller) with given key compare function. + * @param rbtree: uninitialised memory for new tree, returned empty. + * @param cmpf: compare function (like strcmp) takes pointers to two keys. + */ +void rbtree_init(rbtree_t *rbtree, int (*cmpf)(const void *, const void *)); + +/** + * Insert data into the tree. + * @param rbtree: tree to insert to. + * @param data: element to insert. + * @return: data ptr or NULL if key already present. + */ +rbnode_t *rbtree_insert(rbtree_t *rbtree, rbnode_t *data); + +/** + * Delete element from tree. + * @param rbtree: tree to delete from. + * @param key: key of item to delete. + * @return: node that is now unlinked from the tree. User to delete it. + * returns 0 if node not present + */ +rbnode_t *rbtree_delete(rbtree_t *rbtree, const void *key); + +/** + * Find key in tree. Returns NULL if not found. + * @param rbtree: tree to find in. + * @param key: key that must match. + * @return: node that fits or NULL. + */ +rbnode_t *rbtree_search(rbtree_t *rbtree, const void *key); + +/** + * Find, but match does not have to be exact. + * @param rbtree: tree to find in. + * @param key: key to find position of. + * @param result: set to the exact node if present, otherwise to element that + * precedes the position of key in the tree. NULL if no smaller element. + * @return: true if exact match in result. Else result points to <= element, + * or NULL if key is smaller than the smallest key. + */ +int rbtree_find_less_equal(rbtree_t *rbtree, const void *key, + rbnode_t **result); + +/** + * Returns first (smallest) node in the tree + * @param rbtree: tree + * @return: smallest element or NULL if tree empty. + */ +rbnode_t *rbtree_first(rbtree_t *rbtree); + +/** + * Returns last (largest) node in the tree + * @param rbtree: tree + * @return: largest element or NULL if tree empty. + */ +rbnode_t *rbtree_last(rbtree_t *rbtree); + +/** + * Returns next larger node in the tree + * @param rbtree: tree + * @return: next larger element or NULL if no larger in tree. + */ +rbnode_t *rbtree_next(rbnode_t *rbtree); + +/** + * Returns previous smaller node in the tree + * @param rbtree: tree + * @return: previous smaller element or NULL if no previous in tree. + */ +rbnode_t *rbtree_previous(rbnode_t *rbtree); + +/** + * Call with node=variable of struct* with rbnode_t as first element. + * with type is the type of a pointer to that struct. + */ +#define RBTREE_FOR(node, type, rbtree) \ + for(node=(type)rbtree_first(rbtree); \ + (rbnode_t*)node != RBTREE_NULL; \ + node = (type)rbtree_next((rbnode_t*)node)) + +/** + * Call function for all elements in the redblack tree, such that + * leaf elements are called before parent elements. So that all + * elements can be safely free()d. + * Note that your function must not remove the nodes from the tree. + * Since that may trigger rebalances of the rbtree. + * @param tree: the tree + * @param func: function called with element and user arg. + * The function must not alter the rbtree. + * @param arg: user argument. + */ +void traverse_postorder(rbtree_t* tree, void (*func)(rbnode_t*, void*), + void* arg); + +#endif /* UTIL_RBTREE_H_ */ diff --git a/util/regional.c b/util/regional.c new file mode 100644 index 00000000000..8b1fcdbb2ac --- /dev/null +++ b/util/regional.c @@ -0,0 +1,223 @@ +/* + * regional.c -- region based memory allocator. + * + * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * Regional allocator. Allocates small portions of of larger chunks. + */ + +#include "config.h" +#include "util/log.h" +#include "util/regional.h" + +#ifdef ALIGNMENT +# undef ALIGNMENT +#endif +/** increase size until it fits alignment of s bytes */ +#define ALIGN_UP(x, s) (((x) + s - 1) & (~(s - 1))) +/** what size to align on; make sure a char* fits in it. */ +#define ALIGNMENT (sizeof(uint64_t)) + +/** Default reasonable size for chunks */ +#define REGIONAL_CHUNK_SIZE 8192 +#ifdef UNBOUND_ALLOC_NONREGIONAL +/** All objects allocated outside of chunks, for debug */ +#define REGIONAL_LARGE_OBJECT_SIZE 0 +#else +/** Default size for large objects - allocated outside of chunks. */ +#define REGIONAL_LARGE_OBJECT_SIZE 2048 +#endif + +struct regional* +regional_create(void) +{ + return regional_create_custom(REGIONAL_CHUNK_SIZE); +} + +/** init regional struct with first block */ +static void +regional_init(struct regional* r) +{ + size_t a = ALIGN_UP(sizeof(struct regional), ALIGNMENT); + r->data = (char*)r + a; + r->available = r->first_size - a; + r->next = NULL; + r->large_list = NULL; + r->total_large = 0; +} + +struct regional* +regional_create_custom(size_t size) +{ + struct regional* r = (struct regional*)malloc(size); + log_assert(sizeof(struct regional) <= size); + if(!r) return NULL; + r->first_size = size; + regional_init(r); + return r; +} + +void +regional_free_all(struct regional *r) +{ + char* p = r->next, *np; + while(p) { + np = *(char**)p; + free(p); + p = np; + } + p = r->large_list; + while(p) { + np = *(char**)p; + free(p); + p = np; + } + regional_init(r); +} + +void +regional_destroy(struct regional *r) +{ + if(!r) return; + regional_free_all(r); + free(r); +} + +void * +regional_alloc(struct regional *r, size_t size) +{ + size_t a = ALIGN_UP(size, ALIGNMENT); + void *s; + /* large objects */ + if(a > REGIONAL_LARGE_OBJECT_SIZE) { + s = malloc(ALIGNMENT + size); + if(!s) return NULL; + r->total_large += ALIGNMENT+size; + *(char**)s = r->large_list; + r->large_list = (char*)s; + return (char*)s+ALIGNMENT; + } + /* create a new chunk */ + if(a > r->available) { + s = malloc(REGIONAL_CHUNK_SIZE); + if(!s) return NULL; + *(char**)s = r->next; + r->next = (char*)s; + r->data = (char*)s + ALIGNMENT; + r->available = REGIONAL_CHUNK_SIZE - ALIGNMENT; + } + /* put in this chunk */ + r->available -= a; + s = r->data; + r->data += a; + return s; +} + +void * +regional_alloc_init(struct regional* r, const void *init, size_t size) +{ + void *s = regional_alloc(r, size); + if(!s) return NULL; + memcpy(s, init, size); + return s; +} + +void * +regional_alloc_zero(struct regional *r, size_t size) +{ + void *s = regional_alloc(r, size); + if(!s) return NULL; + memset(s, 0, size); + return s; +} + +char * +regional_strdup(struct regional *r, const char *string) +{ + return (char*)regional_alloc_init(r, string, strlen(string)+1); +} + +/** + * reasonably slow, but stats and get_mem are not supposed to be fast + * count the number of chunks in use + */ +static size_t +count_chunks(struct regional* r) +{ + size_t c = 1; + char* p = r->next; + while(p) { + c++; + p = *(char**)p; + } + return c; +} + +/** + * also reasonably slow, counts the number of large objects + */ +static size_t +count_large(struct regional* r) +{ + size_t c = 0; + char* p = r->large_list; + while(p) { + c++; + p = *(char**)p; + } + return c; +} + +void +regional_log_stats(struct regional *r) +{ + /* some basic assertions put here (non time critical code) */ + log_assert(ALIGNMENT >= sizeof(char*)); + log_assert(REGIONAL_CHUNK_SIZE > ALIGNMENT); + log_assert(REGIONAL_CHUNK_SIZE-ALIGNMENT > REGIONAL_LARGE_OBJECT_SIZE); + log_assert(REGIONAL_CHUNK_SIZE >= sizeof(struct regional)); + /* debug print */ + log_info("regional %u chunks, %u large", + (unsigned)count_chunks(r), (unsigned)count_large(r)); +} + +size_t +regional_get_mem(struct regional* r) +{ + return r->first_size + (count_chunks(r)-1)*REGIONAL_CHUNK_SIZE + + r->total_large; +} diff --git a/util/regional.h b/util/regional.h new file mode 100644 index 00000000000..250523a6d9b --- /dev/null +++ b/util/regional.h @@ -0,0 +1,150 @@ +/* + * regional.h -- region based memory allocator. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * Regional allocator. Allocates small portions of of larger chunks. + * Based on region-allocator from NSD, but rewritten to be light. + * + * Different from (nsd) region-allocator.h + * o does not have recycle bin + * o does not collect stats; just enough to answer get_mem() in use. + * o does not keep cleanup list + * o does not have function pointers to setup + * o allocs the regional struct inside the first block. + * o can take a block to create regional from. + * o blocks and large allocations are kept on singly linked lists. + */ + +#ifndef UTIL_REGIONAL_H_ +#define UTIL_REGIONAL_H_ + +/** + * the regional* is the first block*. + * every block has a ptr to the next in first bytes. + * and so does the regional struct, which is the first block. + */ +struct regional +{ + /** + * next chunk. NULL if first chunk is the only chunk. + * first inside that chunk is the char* next pointer. + * When regional_free_all() has been called this value is NULL. + */ + char* next; + /** first large object, cast to char** to obtain next ptr */ + char* large_list; + /** total large size */ + size_t total_large; + /** initial chunk size */ + size_t first_size; + /** number of bytes available in the current chunk. */ + size_t available; + /** current chunk data position. */ + char* data; +}; + +/** + * Create a new regional. + * @return: newly allocated regional. + */ +struct regional* regional_create(void); + +/** + * Create a new region, with custom settings. + * @param size: length of first block. + * @return: newly allocated regional. + */ +struct regional* regional_create_custom(size_t size); + +/** + * Free all memory associated with regional. Only keeps the first block with + * the regional inside it. + * @param r: the region. + */ +void regional_free_all(struct regional *r); + +/** + * Destroy regional. All memory associated with regional is freed as if + * regional_free_all was called, as well as destroying the regional struct. + * @param r: to delete. + */ +void regional_destroy(struct regional *r); + +/** + * Allocate size bytes of memory inside regional. The memory is + * deallocated when region_free_all is called for this region. + * @param r: the region. + * @param size: number of bytes. + * @return: pointer to memory allocated. + */ +void *regional_alloc(struct regional *r, size_t size); + +/** + * Allocate size bytes of memory inside regional and copy INIT into it. + * The memory is deallocated when region_free_all is called for this + * region. + * @param r: the region. + * @param init: to copy. + * @param size: number of bytes. + * @return: pointer to memory allocated. + */ +void *regional_alloc_init(struct regional* r, const void *init, size_t size); + +/** + * Allocate size bytes of memory inside regional that are initialized to + * 0. The memory is deallocated when region_free_all is called for + * this region. + * @param r: the region. + * @param size: number of bytes. + * @return: pointer to memory allocated. + */ +void *regional_alloc_zero(struct regional *r, size_t size); + +/** + * Duplicate string and allocate the result in regional. + * @param r: the region. + * @param string: null terminated string. + * @return: pointer to memory allocated. + */ +char *regional_strdup(struct regional *r, const char *string); + +/** Debug print regional statistics to log */ +void regional_log_stats(struct regional *r); + +/** get total memory size in use by region */ +size_t regional_get_mem(struct regional* r); + +#endif /* UTIL_REGIONAL_H_ */ diff --git a/util/rtt.c b/util/rtt.c new file mode 100644 index 00000000000..df1d437e479 --- /dev/null +++ b/util/rtt.c @@ -0,0 +1,120 @@ +/* + * util/rtt.c - UDP round trip time estimator for resend timeouts. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains a data type and functions to help estimate good + * round trip times for UDP resend timeout values. + */ +#include "config.h" +#include "util/rtt.h" +#include "util/log.h" + +/** calculate RTO from rtt information */ +static int +calc_rto(const struct rtt_info* rtt) +{ + /* From Stevens, Unix Network Programming, Vol1, 3rd ed., p.598 */ + int rto = rtt->srtt + 4*rtt->rttvar; + if(rto < RTT_MIN_TIMEOUT) + rto = RTT_MIN_TIMEOUT; + if(rto > RTT_MAX_TIMEOUT) + rto = RTT_MAX_TIMEOUT; + return rto; +} + +void +rtt_init(struct rtt_info* rtt) +{ + rtt->srtt = 0; + rtt->rttvar = 94; + rtt->rto = calc_rto(rtt); + /* default value from the book is 0 + 4*0.75 = 3 seconds */ + /* first RTO is 0 + 4*0.094 = 0.376 seconds */ +} + +int +rtt_timeout(const struct rtt_info* rtt) +{ + return rtt->rto; +} + +int +rtt_unclamped(const struct rtt_info* rtt) +{ + if(calc_rto(rtt) != rtt->rto) { + /* timeout fallback has happened */ + return rtt->rto; + } + /* return unclamped value */ + return rtt->srtt + 4*rtt->rttvar; +} + +void +rtt_update(struct rtt_info* rtt, int ms) +{ + int delta = ms - rtt->srtt; + rtt->srtt += delta / 8; /* g = 1/8 */ + if(delta < 0) + delta = -delta; /* |delta| */ + rtt->rttvar += (delta - rtt->rttvar) / 4; /* h = 1/4 */ + rtt->rto = calc_rto(rtt); +} + +void +rtt_lost(struct rtt_info* rtt, int orig) +{ + /* exponential backoff */ + + /* if a query succeeded and put down the rto meanwhile, ignore this */ + if(rtt->rto < orig) + return; + + /* the original rto is doubled, not the current one to make sure + * that the values in the cache are not increased by lots of + * queries simultaneously as they time out at the same time */ + orig *= 2; + if(rtt->rto <= orig) { + rtt->rto = orig; + if(rtt->rto > RTT_MAX_TIMEOUT) + rtt->rto = RTT_MAX_TIMEOUT; + } +} + +int rtt_notimeout(const struct rtt_info* rtt) +{ + return calc_rto(rtt); +} diff --git a/util/rtt.h b/util/rtt.h new file mode 100644 index 00000000000..1af5484c983 --- /dev/null +++ b/util/rtt.h @@ -0,0 +1,107 @@ +/* + * util/rtt.h - UDP round trip time estimator for resend timeouts. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains a data type and functions to help estimate good + * round trip times for UDP resend timeout values. + */ + +#ifndef UTIL_RTT_H +#define UTIL_RTT_H + +/** + * RTT information. Keeps packet Round Trip Time. + */ +struct rtt_info { + /** smoothed rtt estimator, in milliseconds */ + int srtt; + /** smoothed mean deviation, in milliseconds */ + int rttvar; + /** current RTO in use, in milliseconds */ + int rto; +}; + +/** min retransmit timeout value, in milliseconds */ +#define RTT_MIN_TIMEOUT 50 +/** max retransmit timeout value, in milliseconds */ +#define RTT_MAX_TIMEOUT 120000 + +/** + * Initialize RTT estimators. + * @param rtt: The structure. Caller is responsible for allocation of it. + */ +void rtt_init(struct rtt_info* rtt); + +/** + * Get timeout to use for sending a UDP packet. + * @param rtt: round trip statistics structure. + * @return: timeout to use in milliseconds. Relative time value. + */ +int rtt_timeout(const struct rtt_info* rtt); + +/** + * Get unclamped timeout to use for server selection. + * Recent timeouts are reflected in the returned value. + * @param rtt: round trip statistics structure. + * @return: value to use in milliseconds. + */ +int rtt_unclamped(const struct rtt_info* rtt); + +/** + * RTT for valid responses. Without timeouts. + * @param rtt: round trip statistics structure. + * @return: value in msec. + */ +int rtt_notimeout(const struct rtt_info* rtt); + +/** + * Update the statistics with a new roundtrip estimate observation. + * @param rtt: round trip statistics structure. + * @param ms: estimate of roundtrip time in milliseconds. + */ +void rtt_update(struct rtt_info* rtt, int ms); + +/** + * Update the statistics with a new timout expired observation. + * @param rtt: round trip statistics structure. + * @param orig: original rtt time given for the query that timed out. + * Used to calculate the maximum responsible backed off time that + * can reasonably be applied. + */ +void rtt_lost(struct rtt_info* rtt, int orig); + +#endif /* UTIL_RTT_H */ diff --git a/util/storage/dnstree.c b/util/storage/dnstree.c new file mode 100644 index 00000000000..003e8af3ef3 --- /dev/null +++ b/util/storage/dnstree.c @@ -0,0 +1,282 @@ +/* + * util/storage/dnstree.c - support for rbtree types suitable for DNS code. + * + * Copyright (c) 2008, 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains structures combining types and functions to + * manipulate those structures that help building DNS lookup trees. + */ +#include "config.h" +#include "util/storage/dnstree.h" +#include "util/data/dname.h" +#include "util/net_help.h" + +int name_tree_compare(const void* k1, const void* k2) +{ + struct name_tree_node* x = (struct name_tree_node*)k1; + struct name_tree_node* y = (struct name_tree_node*)k2; + int m; + if(x->dclass != y->dclass) { + if(x->dclass < y->dclass) + return -1; + return 1; + } + return dname_lab_cmp(x->name, x->labs, y->name, y->labs, &m); +} + +int addr_tree_compare(const void* k1, const void* k2) +{ + struct addr_tree_node* n1 = (struct addr_tree_node*)k1; + struct addr_tree_node* n2 = (struct addr_tree_node*)k2; + int r = sockaddr_cmp_addr(&n1->addr, n1->addrlen, &n2->addr, + n2->addrlen); + if(r != 0) return r; + if(n1->net < n2->net) + return -1; + if(n1->net > n2->net) + return 1; + return 0; +} + +void name_tree_init(rbtree_t* tree) +{ + rbtree_init(tree, &name_tree_compare); +} + +void addr_tree_init(rbtree_t* tree) +{ + rbtree_init(tree, &addr_tree_compare); +} + +int name_tree_insert(rbtree_t* tree, struct name_tree_node* node, + uint8_t* name, size_t len, int labs, uint16_t dclass) +{ + node->node.key = node; + node->name = name; + node->len = len; + node->labs = labs; + node->dclass = dclass; + node->parent = NULL; + return rbtree_insert(tree, &node->node) != NULL; +} + +int addr_tree_insert(rbtree_t* tree, struct addr_tree_node* node, + struct sockaddr_storage* addr, socklen_t addrlen, int net) +{ + node->node.key = node; + memcpy(&node->addr, addr, addrlen); + node->addrlen = addrlen; + node->net = net; + node->parent = NULL; + return rbtree_insert(tree, &node->node) != NULL; +} + +void addr_tree_init_parents(rbtree_t* tree) +{ + struct addr_tree_node* node, *prev = NULL, *p; + int m; + RBTREE_FOR(node, struct addr_tree_node*, tree) { + node->parent = NULL; + if(!prev || prev->addrlen != node->addrlen) { + prev = node; + continue; + } + m = addr_in_common(&prev->addr, prev->net, &node->addr, + node->net, node->addrlen); + /* sort order like: ::/0, 1::/2, 1::/4, ... 2::/2 */ + /* find the previous, or parent-parent-parent */ + for(p = prev; p; p = p->parent) + if(p->net <= m) { + /* ==: since prev matched m, this is closest*/ + /* <: prev matches more, but is not a parent, + * this one is a (grand)parent */ + node->parent = p; + break; + } + prev = node; + } +} + +void name_tree_init_parents(rbtree_t* tree) +{ + struct name_tree_node* node, *prev = NULL, *p; + int m; + RBTREE_FOR(node, struct name_tree_node*, tree) { + node->parent = NULL; + if(!prev || prev->dclass != node->dclass) { + prev = node; + continue; + } + (void)dname_lab_cmp(prev->name, prev->labs, node->name, + node->labs, &m); /* we know prev is smaller */ + /* sort order like: . com. bla.com. zwb.com. net. */ + /* find the previous, or parent-parent-parent */ + for(p = prev; p; p = p->parent) + if(p->labs <= m) { + /* ==: since prev matched m, this is closest*/ + /* <: prev matches more, but is not a parent, + * this one is a (grand)parent */ + node->parent = p; + break; + } + prev = node; + } +} + +struct name_tree_node* name_tree_find(rbtree_t* tree, uint8_t* name, + size_t len, int labs, uint16_t dclass) +{ + struct name_tree_node key; + key.node.key = &key; + key.name = name; + key.len = len; + key.labs = labs; + key.dclass = dclass; + return (struct name_tree_node*)rbtree_search(tree, &key); +} + +struct name_tree_node* name_tree_lookup(rbtree_t* tree, uint8_t* name, + size_t len, int labs, uint16_t dclass) +{ + rbnode_t* res = NULL; + struct name_tree_node *result; + struct name_tree_node key; + key.node.key = &key; + key.name = name; + key.len = len; + key.labs = labs; + key.dclass = dclass; + if(rbtree_find_less_equal(tree, &key, &res)) { + /* exact */ + result = (struct name_tree_node*)res; + } else { + /* smaller element (or no element) */ + int m; + result = (struct name_tree_node*)res; + if(!result || result->dclass != dclass) + return NULL; + /* count number of labels matched */ + (void)dname_lab_cmp(result->name, result->labs, key.name, + key.labs, &m); + while(result) { /* go up until qname is subdomain of stub */ + if(result->labs <= m) + break; + result = result->parent; + } + } + return result; +} + +struct addr_tree_node* addr_tree_lookup(rbtree_t* tree, + struct sockaddr_storage* addr, socklen_t addrlen) +{ + rbnode_t* res = NULL; + struct addr_tree_node* result; + struct addr_tree_node key; + key.node.key = &key; + memcpy(&key.addr, addr, addrlen); + key.addrlen = addrlen; + key.net = (addr_is_ip6(addr, addrlen)?128:32); + if(rbtree_find_less_equal(tree, &key, &res)) { + /* exact */ + return (struct addr_tree_node*)res; + } else { + /* smaller element (or no element) */ + int m; + result = (struct addr_tree_node*)res; + if(!result || result->addrlen != addrlen) + return 0; + /* count number of bits matched */ + m = addr_in_common(&result->addr, result->net, addr, + key.net, addrlen); + while(result) { /* go up until addr is inside netblock */ + if(result->net <= m) + break; + result = result->parent; + } + } + return result; +} + +int +name_tree_next_root(rbtree_t* tree, uint16_t* dclass) +{ + struct name_tree_node key; + rbnode_t* n; + struct name_tree_node* p; + if(*dclass == 0) { + /* first root item is first item in tree */ + n = rbtree_first(tree); + if(n == RBTREE_NULL) + return 0; + p = (struct name_tree_node*)n; + if(dname_is_root(p->name)) { + *dclass = p->dclass; + return 1; + } + /* root not first item? search for higher items */ + *dclass = p->dclass + 1; + return name_tree_next_root(tree, dclass); + } + /* find class n in tree, we may get a direct hit, or if we don't + * this is the last item of the previous class so rbtree_next() takes + * us to the next root (if any) */ + key.node.key = &key; + key.name = (uint8_t*)"\000"; + key.len = 1; + key.labs = 0; + key.dclass = *dclass; + n = NULL; + if(rbtree_find_less_equal(tree, &key, &n)) { + /* exact */ + return 1; + } else { + /* smaller element */ + if(!n || n == RBTREE_NULL) + return 0; /* nothing found */ + n = rbtree_next(n); + if(n == RBTREE_NULL) + return 0; /* no higher */ + p = (struct name_tree_node*)n; + if(dname_is_root(p->name)) { + *dclass = p->dclass; + return 1; + } + /* not a root node, return next higher item */ + *dclass = p->dclass+1; + return name_tree_next_root(tree, dclass); + } +} diff --git a/util/storage/dnstree.h b/util/storage/dnstree.h new file mode 100644 index 00000000000..3ecbd128f8c --- /dev/null +++ b/util/storage/dnstree.h @@ -0,0 +1,192 @@ +/* + * util/storage/dnstree.h - support for rbtree types suitable for DNS code. + * + * Copyright (c) 2008, 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains structures combining types and functions to + * manipulate those structures that help building DNS lookup trees. + */ + +#ifndef UTIL_STORAGE_DNSTREE_H +#define UTIL_STORAGE_DNSTREE_H +#include "util/rbtree.h" + +/** + * Tree of domain names. Sorted first by class then by name. + * This is not sorted canonically, but fast. + * This can be looked up to obtain a closest encloser parent name. + * + * The tree itself is a rbtree_t. + * This is the element node put as first entry in the client structure. + */ +struct name_tree_node { + /** rbtree node, key is this struct : dclass and name */ + rbnode_t node; + /** parent in tree */ + struct name_tree_node* parent; + /** name in uncompressed wireformat */ + uint8_t* name; + /** length of name */ + size_t len; + /** labels in name */ + int labs; + /** the class of the name (host order) */ + uint16_t dclass; +}; + +/** + * Tree of IP addresses. Sorted first by protocol, then by bits. + * This can be looked up to obtain the enclosing subnet. + * + * The tree itself is a rbtree_t. + * This is the element node put as first entry in the client structure. + */ +struct addr_tree_node { + /** rbtree node, key is this struct : proto and subnet */ + rbnode_t node; + /** parent in tree */ + struct addr_tree_node* parent; + /** address */ + struct sockaddr_storage addr; + /** length of addr */ + socklen_t addrlen; + /** netblock size */ + int net; +}; + +/** + * Init a name tree to be empty + * @param tree: to init. + */ +void name_tree_init(rbtree_t* tree); + +/** + * insert element into name tree. + * @param tree: name tree + * @param node: node element (at start of a structure that caller + * has allocated). + * @param name: name to insert (wireformat) + * this node has been allocated by the caller and it itself inserted. + * @param len: length of name + * @param labs: labels in name + * @param dclass: class of name + * @return false on error (duplicate element). + */ +int name_tree_insert(rbtree_t* tree, struct name_tree_node* node, + uint8_t* name, size_t len, int labs, uint16_t dclass); + +/** + * Initialize parent pointers in name tree. + * Should be performed after insertions are done, before lookups + * @param tree: name tree + */ +void name_tree_init_parents(rbtree_t* tree); + +/** + * Lookup exact match in name tree + * @param tree: name tree + * @param name: wireformat name + * @param len: length of name + * @param labs: labels in name + * @param dclass: class of name + * @return node or NULL if not found. + */ +struct name_tree_node* name_tree_find(rbtree_t* tree, uint8_t* name, + size_t len, int labs, uint16_t dclass); + +/** + * Lookup closest encloser in name tree. + * @param tree: name tree + * @param name: wireformat name + * @param len: length of name + * @param labs: labels in name + * @param dclass: class of name + * @return closest enclosing node (could be equal) or NULL if not found. + */ +struct name_tree_node* name_tree_lookup(rbtree_t* tree, uint8_t* name, + size_t len, int labs, uint16_t dclass); + +/** + * Find next root item in name tree. + * @param tree: the nametree. + * @param dclass: the class to look for next (or higher). + * @return false if no classes found, true means class put into c. + */ +int name_tree_next_root(rbtree_t* tree, uint16_t* dclass); + +/** + * Init addr tree to be empty. + * @param tree: to init. + */ +void addr_tree_init(rbtree_t* tree); + +/** + * insert element into addr tree. + * @param tree: addr tree + * @param node: node element (at start of a structure that caller + * has allocated). + * @param addr: to insert (copied). + * @param addrlen: length of addr + * @param net: size of subnet. + * @return false on error (duplicate element). + */ +int addr_tree_insert(rbtree_t* tree, struct addr_tree_node* node, + struct sockaddr_storage* addr, socklen_t addrlen, int net); + +/** + * Initialize parent pointers in addr tree. + * Should be performed after insertions are done, before lookups + * @param tree: addr tree + */ +void addr_tree_init_parents(rbtree_t* tree); + +/** + * Lookup closest encloser in addr tree. + * @param tree: addr tree + * @param addr: to lookup. + * @param addrlen: length of addr + * @return closest enclosing node (could be equal) or NULL if not found. + */ +struct addr_tree_node* addr_tree_lookup(rbtree_t* tree, + struct sockaddr_storage* addr, socklen_t addrlen); + +/** compare name tree nodes */ +int name_tree_compare(const void* k1, const void* k2); + +/** compare addr tree nodes */ +int addr_tree_compare(const void* k1, const void* k2); + +#endif /* UTIL_STORAGE_DNSTREE_H */ diff --git a/util/storage/lookup3.c b/util/storage/lookup3.c new file mode 100644 index 00000000000..65e0ad2a57c --- /dev/null +++ b/util/storage/lookup3.c @@ -0,0 +1,1011 @@ +/* + January 2012(Wouter) added randomised initial value, fallout from 28c3. + March 2007(Wouter) adapted from lookup3.c original, add config.h include. + added #ifdef VALGRIND to remove 298,384,660 'unused variable k8' warnings. + added include of lookup3.h to check definitions match declarations. + removed include of stdint - config.h takes care of platform independence. + url http://burtleburtle.net/bob/hash/index.html. +*/ +/* +------------------------------------------------------------------------------- +lookup3.c, by Bob Jenkins, May 2006, Public Domain. + +These are functions for producing 32-bit hashes for hash table lookup. +hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final() +are externally useful functions. Routines to test the hash are included +if SELF_TEST is defined. You can use this free for any purpose. It's in +the public domain. It has no warranty. + +You probably want to use hashlittle(). hashlittle() and hashbig() +hash byte arrays. hashlittle() is is faster than hashbig() on +little-endian machines. Intel and AMD are little-endian machines. +On second thought, you probably want hashlittle2(), which is identical to +hashlittle() except it returns two 32-bit hashes for the price of one. +You could implement hashbig2() if you wanted but I haven't bothered here. + +If you want to find a hash of, say, exactly 7 integers, do + a = i1; b = i2; c = i3; + mix(a,b,c); + a += i4; b += i5; c += i6; + mix(a,b,c); + a += i7; + final(a,b,c); +then use c as the hash value. If you have a variable length array of +4-byte integers to hash, use hashword(). If you have a byte array (like +a character string), use hashlittle(). If you have several byte arrays, or +a mix of things, see the comments above hashlittle(). + +Why is this so big? I read 12 bytes at a time into 3 4-byte integers, +then mix those integers. This is fast (you can do a lot more thorough +mixing with 12*3 instructions on 3 integers than you can with 3 instructions +on 1 byte), but shoehorning those bytes into integers efficiently is messy. +------------------------------------------------------------------------------- +*/ +/*#define SELF_TEST 1*/ + +#include "config.h" +#include "util/storage/lookup3.h" +#include /* defines printf for tests */ +#include /* defines time_t for timings in the test */ +/*#include defines uint32_t etc (from config.h) */ +#include /* attempt to define endianness */ +#ifdef linux +# include /* attempt to define endianness */ +#endif + +/* random initial value */ +static uint32_t raninit = 0xdeadbeef; + +void +hash_set_raninit(uint32_t v) +{ + raninit = v; +} + +/* + * My best guess at if you are big-endian or little-endian. This may + * need adjustment. + */ +#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \ + __BYTE_ORDER == __LITTLE_ENDIAN) || \ + (defined(i386) || defined(__i386__) || defined(__i486__) || \ + defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL)) +# define HASH_LITTLE_ENDIAN 1 +# define HASH_BIG_ENDIAN 0 +#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \ + __BYTE_ORDER == __BIG_ENDIAN) || \ + (defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel)) +# define HASH_LITTLE_ENDIAN 0 +# define HASH_BIG_ENDIAN 1 +#else +# define HASH_LITTLE_ENDIAN 0 +# define HASH_BIG_ENDIAN 0 +#endif + +#define hashsize(n) ((uint32_t)1<<(n)) +#define hashmask(n) (hashsize(n)-1) +#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) + +/* +------------------------------------------------------------------------------- +mix -- mix 3 32-bit values reversibly. + +This is reversible, so any information in (a,b,c) before mix() is +still in (a,b,c) after mix(). + +If four pairs of (a,b,c) inputs are run through mix(), or through +mix() in reverse, there are at least 32 bits of the output that +are sometimes the same for one pair and different for another pair. +This was tested for: +* pairs that differed by one bit, by two bits, in any combination + of top bits of (a,b,c), or in any combination of bottom bits of + (a,b,c). +* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed + the output delta to a Gray code (a^(a>>1)) so a string of 1's (as + is commonly produced by subtraction) look like a single 1-bit + difference. +* the base values were pseudorandom, all zero but one bit set, or + all zero plus a counter that starts at zero. + +Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that +satisfy this are + 4 6 8 16 19 4 + 9 15 3 18 27 15 + 14 9 3 7 17 3 +Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing +for "differ" defined as + with a one-bit base and a two-bit delta. I +used http://burtleburtle.net/bob/hash/avalanche.html to choose +the operations, constants, and arrangements of the variables. + +This does not achieve avalanche. There are input bits of (a,b,c) +that fail to affect some output bits of (a,b,c), especially of a. The +most thoroughly mixed value is c, but it doesn't really even achieve +avalanche in c. + +This allows some parallelism. Read-after-writes are good at doubling +the number of bits affected, so the goal of mixing pulls in the opposite +direction as the goal of parallelism. I did what I could. Rotates +seem to cost as much as shifts on every machine I could lay my hands +on, and rotates are much kinder to the top and bottom bits, so I used +rotates. +------------------------------------------------------------------------------- +*/ +#define mix(a,b,c) \ +{ \ + a -= c; a ^= rot(c, 4); c += b; \ + b -= a; b ^= rot(a, 6); a += c; \ + c -= b; c ^= rot(b, 8); b += a; \ + a -= c; a ^= rot(c,16); c += b; \ + b -= a; b ^= rot(a,19); a += c; \ + c -= b; c ^= rot(b, 4); b += a; \ +} + +/* +------------------------------------------------------------------------------- +final -- final mixing of 3 32-bit values (a,b,c) into c + +Pairs of (a,b,c) values differing in only a few bits will usually +produce values of c that look totally different. This was tested for +* pairs that differed by one bit, by two bits, in any combination + of top bits of (a,b,c), or in any combination of bottom bits of + (a,b,c). +* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed + the output delta to a Gray code (a^(a>>1)) so a string of 1's (as + is commonly produced by subtraction) look like a single 1-bit + difference. +* the base values were pseudorandom, all zero but one bit set, or + all zero plus a counter that starts at zero. + +These constants passed: + 14 11 25 16 4 14 24 + 12 14 25 16 4 14 24 +and these came close: + 4 8 15 26 3 22 24 + 10 8 15 26 3 22 24 + 11 8 15 26 3 22 24 +------------------------------------------------------------------------------- +*/ +#define final(a,b,c) \ +{ \ + c ^= b; c -= rot(b,14); \ + a ^= c; a -= rot(c,11); \ + b ^= a; b -= rot(a,25); \ + c ^= b; c -= rot(b,16); \ + a ^= c; a -= rot(c,4); \ + b ^= a; b -= rot(a,14); \ + c ^= b; c -= rot(b,24); \ +} + +/* +-------------------------------------------------------------------- + This works on all machines. To be useful, it requires + -- that the key be an array of uint32_t's, and + -- that the length be the number of uint32_t's in the key + + The function hashword() is identical to hashlittle() on little-endian + machines, and identical to hashbig() on big-endian machines, + except that the length has to be measured in uint32_ts rather than in + bytes. hashlittle() is more complicated than hashword() only because + hashlittle() has to dance around fitting the key bytes into registers. +-------------------------------------------------------------------- +*/ +uint32_t hashword( +const uint32_t *k, /* the key, an array of uint32_t values */ +size_t length, /* the length of the key, in uint32_ts */ +uint32_t initval) /* the previous hash, or an arbitrary value */ +{ + uint32_t a,b,c; + + /* Set up the internal state */ + a = b = c = raninit + (((uint32_t)length)<<2) + initval; + + /*------------------------------------------------- handle most of the key */ + while (length > 3) + { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a,b,c); + length -= 3; + k += 3; + } + + /*------------------------------------------- handle the last 3 uint32_t's */ + switch(length) /* all the case statements fall through */ + { + case 3 : c+=k[2]; + case 2 : b+=k[1]; + case 1 : a+=k[0]; + final(a,b,c); + case 0: /* case 0: nothing left to add */ + break; + } + /*------------------------------------------------------ report the result */ + return c; +} + + +#ifdef SELF_TEST + +/* +-------------------------------------------------------------------- +hashword2() -- same as hashword(), but take two seeds and return two +32-bit values. pc and pb must both be nonnull, and *pc and *pb must +both be initialized with seeds. If you pass in (*pb)==0, the output +(*pc) will be the same as the return value from hashword(). +-------------------------------------------------------------------- +*/ +void hashword2 ( +const uint32_t *k, /* the key, an array of uint32_t values */ +size_t length, /* the length of the key, in uint32_ts */ +uint32_t *pc, /* IN: seed OUT: primary hash value */ +uint32_t *pb) /* IN: more seed OUT: secondary hash value */ +{ + uint32_t a,b,c; + + /* Set up the internal state */ + a = b = c = raninit + ((uint32_t)(length<<2)) + *pc; + c += *pb; + + /*------------------------------------------------- handle most of the key */ + while (length > 3) + { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a,b,c); + length -= 3; + k += 3; + } + + /*------------------------------------------- handle the last 3 uint32_t's */ + switch(length) /* all the case statements fall through */ + { + case 3 : c+=k[2]; + case 2 : b+=k[1]; + case 1 : a+=k[0]; + final(a,b,c); + case 0: /* case 0: nothing left to add */ + break; + } + /*------------------------------------------------------ report the result */ + *pc=c; *pb=b; +} + +#endif /* SELF_TEST */ + +/* +------------------------------------------------------------------------------- +hashlittle() -- hash a variable-length key into a 32-bit value + k : the key (the unaligned variable-length array of bytes) + length : the length of the key, counting by bytes + initval : can be any 4-byte value +Returns a 32-bit value. Every bit of the key affects every bit of +the return value. Two keys differing by one or two bits will have +totally different hash values. + +The best hash table sizes are powers of 2. There is no need to do +mod a prime (mod is sooo slow!). If you need less than 32 bits, +use a bitmask. For example, if you need only 10 bits, do + h = (h & hashmask(10)); +In which case, the hash table should have hashsize(10) elements. + +If you are hashing n strings (uint8_t **)k, do it like this: + for (i=0, h=0; i 12) + { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a,b,c); + length -= 12; + k += 3; + } + + /*----------------------------- handle the last (probably partial) block */ + /* + * "k[2]&0xffffff" actually reads beyond the end of the string, but + * then masks off the part it's not allowed to read. Because the + * string is aligned, the masked-off tail is in the same word as the + * rest of the string. Every machine with memory protection I've seen + * does it on word boundaries, so is OK with this. But VALGRIND will + * still catch it and complain. The masking trick does make the hash + * noticably faster for short strings (like English words). + */ +#ifndef VALGRIND + + switch(length) + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break; + case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break; + case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break; + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=k[1]&0xffffff; a+=k[0]; break; + case 6 : b+=k[1]&0xffff; a+=k[0]; break; + case 5 : b+=k[1]&0xff; a+=k[0]; break; + case 4 : a+=k[0]; break; + case 3 : a+=k[0]&0xffffff; break; + case 2 : a+=k[0]&0xffff; break; + case 1 : a+=k[0]&0xff; break; + case 0 : return c; /* zero length strings require no mixing */ + } + +#else /* make valgrind happy */ + + k8 = (const uint8_t *)k; + switch(length) + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ + case 10: c+=((uint32_t)k8[9])<<8; /* fall through */ + case 9 : c+=k8[8]; /* fall through */ + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ + case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */ + case 5 : b+=k8[4]; /* fall through */ + case 4 : a+=k[0]; break; + case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ + case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */ + case 1 : a+=k8[0]; break; + case 0 : return c; + } + +#endif /* !valgrind */ + + } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) { + const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */ + const uint8_t *k8; + + /*--------------- all but last block: aligned reads and different mixing */ + while (length > 12) + { + a += k[0] + (((uint32_t)k[1])<<16); + b += k[2] + (((uint32_t)k[3])<<16); + c += k[4] + (((uint32_t)k[5])<<16); + mix(a,b,c); + length -= 12; + k += 6; + } + + /*----------------------------- handle the last (probably partial) block */ + k8 = (const uint8_t *)k; + switch(length) + { + case 12: c+=k[4]+(((uint32_t)k[5])<<16); + b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ + case 10: c+=k[4]; + b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 9 : c+=k8[8]; /* fall through */ + case 8 : b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ + case 6 : b+=k[2]; + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 5 : b+=k8[4]; /* fall through */ + case 4 : a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ + case 2 : a+=k[0]; + break; + case 1 : a+=k8[0]; + break; + case 0 : return c; /* zero length requires no mixing */ + } + + } else { /* need to read the key one byte at a time */ + const uint8_t *k = (const uint8_t *)key; + + /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ + while (length > 12) + { + a += k[0]; + a += ((uint32_t)k[1])<<8; + a += ((uint32_t)k[2])<<16; + a += ((uint32_t)k[3])<<24; + b += k[4]; + b += ((uint32_t)k[5])<<8; + b += ((uint32_t)k[6])<<16; + b += ((uint32_t)k[7])<<24; + c += k[8]; + c += ((uint32_t)k[9])<<8; + c += ((uint32_t)k[10])<<16; + c += ((uint32_t)k[11])<<24; + mix(a,b,c); + length -= 12; + k += 12; + } + + /*-------------------------------- last block: affect all 32 bits of (c) */ + switch(length) /* all the case statements fall through */ + { + case 12: c+=((uint32_t)k[11])<<24; + case 11: c+=((uint32_t)k[10])<<16; + case 10: c+=((uint32_t)k[9])<<8; + case 9 : c+=k[8]; + case 8 : b+=((uint32_t)k[7])<<24; + case 7 : b+=((uint32_t)k[6])<<16; + case 6 : b+=((uint32_t)k[5])<<8; + case 5 : b+=k[4]; + case 4 : a+=((uint32_t)k[3])<<24; + case 3 : a+=((uint32_t)k[2])<<16; + case 2 : a+=((uint32_t)k[1])<<8; + case 1 : a+=k[0]; + break; + case 0 : return c; + } + } + + final(a,b,c); + return c; +} + +#ifdef SELF_TEST + +/* + * hashlittle2: return 2 32-bit hash values + * + * This is identical to hashlittle(), except it returns two 32-bit hash + * values instead of just one. This is good enough for hash table + * lookup with 2^^64 buckets, or if you want a second hash if you're not + * happy with the first, or if you want a probably-unique 64-bit ID for + * the key. *pc is better mixed than *pb, so use *pc first. If you want + * a 64-bit value do something like "*pc + (((uint64_t)*pb)<<32)". + */ +void hashlittle2( + const void *key, /* the key to hash */ + size_t length, /* length of the key */ + uint32_t *pc, /* IN: primary initval, OUT: primary hash */ + uint32_t *pb) /* IN: secondary initval, OUT: secondary hash */ +{ + uint32_t a,b,c; /* internal state */ + union { const void *ptr; size_t i; } u; /* needed for Mac Powerbook G4 */ + + /* Set up the internal state */ + a = b = c = raninit + ((uint32_t)length) + *pc; + c += *pb; + + u.ptr = key; + if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) { + const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */ +#ifdef VALGRIND + const uint8_t *k8; +#endif + + /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */ + while (length > 12) + { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a,b,c); + length -= 12; + k += 3; + } + + /*----------------------------- handle the last (probably partial) block */ + /* + * "k[2]&0xffffff" actually reads beyond the end of the string, but + * then masks off the part it's not allowed to read. Because the + * string is aligned, the masked-off tail is in the same word as the + * rest of the string. Every machine with memory protection I've seen + * does it on word boundaries, so is OK with this. But VALGRIND will + * still catch it and complain. The masking trick does make the hash + * noticably faster for short strings (like English words). + */ +#ifndef VALGRIND + + switch(length) + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break; + case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break; + case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break; + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=k[1]&0xffffff; a+=k[0]; break; + case 6 : b+=k[1]&0xffff; a+=k[0]; break; + case 5 : b+=k[1]&0xff; a+=k[0]; break; + case 4 : a+=k[0]; break; + case 3 : a+=k[0]&0xffffff; break; + case 2 : a+=k[0]&0xffff; break; + case 1 : a+=k[0]&0xff; break; + case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */ + } + +#else /* make valgrind happy */ + + k8 = (const uint8_t *)k; + switch(length) + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ + case 10: c+=((uint32_t)k8[9])<<8; /* fall through */ + case 9 : c+=k8[8]; /* fall through */ + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ + case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */ + case 5 : b+=k8[4]; /* fall through */ + case 4 : a+=k[0]; break; + case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ + case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */ + case 1 : a+=k8[0]; break; + case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */ + } + +#endif /* !valgrind */ + + } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) { + const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */ + const uint8_t *k8; + + /*--------------- all but last block: aligned reads and different mixing */ + while (length > 12) + { + a += k[0] + (((uint32_t)k[1])<<16); + b += k[2] + (((uint32_t)k[3])<<16); + c += k[4] + (((uint32_t)k[5])<<16); + mix(a,b,c); + length -= 12; + k += 6; + } + + /*----------------------------- handle the last (probably partial) block */ + k8 = (const uint8_t *)k; + switch(length) + { + case 12: c+=k[4]+(((uint32_t)k[5])<<16); + b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ + case 10: c+=k[4]; + b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 9 : c+=k8[8]; /* fall through */ + case 8 : b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ + case 6 : b+=k[2]; + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 5 : b+=k8[4]; /* fall through */ + case 4 : a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ + case 2 : a+=k[0]; + break; + case 1 : a+=k8[0]; + break; + case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */ + } + + } else { /* need to read the key one byte at a time */ + const uint8_t *k = (const uint8_t *)key; + + /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ + while (length > 12) + { + a += k[0]; + a += ((uint32_t)k[1])<<8; + a += ((uint32_t)k[2])<<16; + a += ((uint32_t)k[3])<<24; + b += k[4]; + b += ((uint32_t)k[5])<<8; + b += ((uint32_t)k[6])<<16; + b += ((uint32_t)k[7])<<24; + c += k[8]; + c += ((uint32_t)k[9])<<8; + c += ((uint32_t)k[10])<<16; + c += ((uint32_t)k[11])<<24; + mix(a,b,c); + length -= 12; + k += 12; + } + + /*-------------------------------- last block: affect all 32 bits of (c) */ + switch(length) /* all the case statements fall through */ + { + case 12: c+=((uint32_t)k[11])<<24; + case 11: c+=((uint32_t)k[10])<<16; + case 10: c+=((uint32_t)k[9])<<8; + case 9 : c+=k[8]; + case 8 : b+=((uint32_t)k[7])<<24; + case 7 : b+=((uint32_t)k[6])<<16; + case 6 : b+=((uint32_t)k[5])<<8; + case 5 : b+=k[4]; + case 4 : a+=((uint32_t)k[3])<<24; + case 3 : a+=((uint32_t)k[2])<<16; + case 2 : a+=((uint32_t)k[1])<<8; + case 1 : a+=k[0]; + break; + case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */ + } + } + + final(a,b,c); + *pc=c; *pb=b; +} + +#endif /* SELF_TEST */ + +#if 0 /* currently not used */ + +/* + * hashbig(): + * This is the same as hashword() on big-endian machines. It is different + * from hashlittle() on all machines. hashbig() takes advantage of + * big-endian byte ordering. + */ +uint32_t hashbig( const void *key, size_t length, uint32_t initval) +{ + uint32_t a,b,c; + union { const void *ptr; size_t i; } u; /* to cast key to (size_t) happily */ + + /* Set up the internal state */ + a = b = c = raninit + ((uint32_t)length) + initval; + + u.ptr = key; + if (HASH_BIG_ENDIAN && ((u.i & 0x3) == 0)) { + const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */ +#ifdef VALGRIND + const uint8_t *k8; +#endif + + /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */ + while (length > 12) + { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a,b,c); + length -= 12; + k += 3; + } + + /*----------------------------- handle the last (probably partial) block */ + /* + * "k[2]<<8" actually reads beyond the end of the string, but + * then shifts out the part it's not allowed to read. Because the + * string is aligned, the illegal read is in the same word as the + * rest of the string. Every machine with memory protection I've seen + * does it on word boundaries, so is OK with this. But VALGRIND will + * still catch it and complain. The masking trick does make the hash + * noticably faster for short strings (like English words). + */ +#ifndef VALGRIND + + switch(length) + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=k[2]&0xffffff00; b+=k[1]; a+=k[0]; break; + case 10: c+=k[2]&0xffff0000; b+=k[1]; a+=k[0]; break; + case 9 : c+=k[2]&0xff000000; b+=k[1]; a+=k[0]; break; + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=k[1]&0xffffff00; a+=k[0]; break; + case 6 : b+=k[1]&0xffff0000; a+=k[0]; break; + case 5 : b+=k[1]&0xff000000; a+=k[0]; break; + case 4 : a+=k[0]; break; + case 3 : a+=k[0]&0xffffff00; break; + case 2 : a+=k[0]&0xffff0000; break; + case 1 : a+=k[0]&0xff000000; break; + case 0 : return c; /* zero length strings require no mixing */ + } + +#else /* make valgrind happy */ + + k8 = (const uint8_t *)k; + switch(length) /* all the case statements fall through */ + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=((uint32_t)k8[10])<<8; /* fall through */ + case 10: c+=((uint32_t)k8[9])<<16; /* fall through */ + case 9 : c+=((uint32_t)k8[8])<<24; /* fall through */ + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=((uint32_t)k8[6])<<8; /* fall through */ + case 6 : b+=((uint32_t)k8[5])<<16; /* fall through */ + case 5 : b+=((uint32_t)k8[4])<<24; /* fall through */ + case 4 : a+=k[0]; break; + case 3 : a+=((uint32_t)k8[2])<<8; /* fall through */ + case 2 : a+=((uint32_t)k8[1])<<16; /* fall through */ + case 1 : a+=((uint32_t)k8[0])<<24; break; + case 0 : return c; + } + +#endif /* !VALGRIND */ + + } else { /* need to read the key one byte at a time */ + const uint8_t *k = (const uint8_t *)key; + + /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ + while (length > 12) + { + a += ((uint32_t)k[0])<<24; + a += ((uint32_t)k[1])<<16; + a += ((uint32_t)k[2])<<8; + a += ((uint32_t)k[3]); + b += ((uint32_t)k[4])<<24; + b += ((uint32_t)k[5])<<16; + b += ((uint32_t)k[6])<<8; + b += ((uint32_t)k[7]); + c += ((uint32_t)k[8])<<24; + c += ((uint32_t)k[9])<<16; + c += ((uint32_t)k[10])<<8; + c += ((uint32_t)k[11]); + mix(a,b,c); + length -= 12; + k += 12; + } + + /*-------------------------------- last block: affect all 32 bits of (c) */ + switch(length) /* all the case statements fall through */ + { + case 12: c+=k[11]; + case 11: c+=((uint32_t)k[10])<<8; + case 10: c+=((uint32_t)k[9])<<16; + case 9 : c+=((uint32_t)k[8])<<24; + case 8 : b+=k[7]; + case 7 : b+=((uint32_t)k[6])<<8; + case 6 : b+=((uint32_t)k[5])<<16; + case 5 : b+=((uint32_t)k[4])<<24; + case 4 : a+=k[3]; + case 3 : a+=((uint32_t)k[2])<<8; + case 2 : a+=((uint32_t)k[1])<<16; + case 1 : a+=((uint32_t)k[0])<<24; + break; + case 0 : return c; + } + } + + final(a,b,c); + return c; +} + +#endif /* 0 == currently not used */ + +#ifdef SELF_TEST + +/* used for timings */ +void driver1() +{ + uint8_t buf[256]; + uint32_t i; + uint32_t h=0; + time_t a,z; + + time(&a); + for (i=0; i<256; ++i) buf[i] = 'x'; + for (i=0; i<1; ++i) + { + h = hashlittle(&buf[0],1,h); + } + time(&z); + if (z-a > 0) printf("time %d %.8x\n", z-a, h); +} + +/* check that every input bit changes every output bit half the time */ +#define HASHSTATE 1 +#define HASHLEN 1 +#define MAXPAIR 60 +#define MAXLEN 70 +void driver2() +{ + 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; + uint32_t e[HASHSTATE],f[HASHSTATE],g[HASHSTATE],h[HASHSTATE]; + uint32_t x[HASHSTATE],y[HASHSTATE]; + uint32_t hlen; + + printf("No more than %d trials should ever be needed \n",MAXPAIR/2); + for (hlen=0; hlen < MAXLEN; ++hlen) + { + z=0; + for (i=0; i>(8-j)); + c[0] = hashlittle(a, hlen, m); + b[i] ^= ((k+1)<>(8-j)); + d[0] = hashlittle(b, hlen, m); + /* check every bit is 1, 0, set, and not set at least once */ + for (l=0; lz) z=k; + if (k==MAXPAIR) + { + printf("Some bit didn't change: "); + printf("%.8x %.8x %.8x %.8x %.8x %.8x ", + e[0],f[0],g[0],h[0],x[0],y[0]); + printf("i %d j %d m %d len %d\n", i, j, m, hlen); + } + if (z==MAXPAIR) goto done; + } + } + } + done: + if (z < MAXPAIR) + { + printf("Mix success %2d bytes %2d initvals ",i,m); + printf("required %d trials\n", z/2); + } + } + printf("\n"); +} + +/* Check for reading beyond the end of the buffer and alignment problems */ +void driver3() +{ + uint8_t buf[MAXLEN+20], *b; + uint32_t len; + uint8_t q[] = "This is the time for all good men to come to the aid of their country..."; + uint32_t h; + uint8_t qq[] = "xThis is the time for all good men to come to the aid of their country..."; + uint32_t i; + uint8_t qqq[] = "xxThis is the time for all good men to come to the aid of their country..."; + uint32_t j; + uint8_t qqqq[] = "xxxThis is the time for all good men to come to the aid of their country..."; + uint32_t ref,x,y; + uint8_t *p; + + printf("Endianness. These lines should all be the same (for values filled in):\n"); + printf("%.8x %.8x %.8x\n", + hashword((const uint32_t *)q, (sizeof(q)-1)/4, 13), + hashword((const uint32_t *)q, (sizeof(q)-5)/4, 13), + hashword((const uint32_t *)q, (sizeof(q)-9)/4, 13)); + p = q; + printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n", + hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13), + hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13), + hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13), + hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13), + hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13), + hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13)); + p = &qq[1]; + printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n", + hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13), + hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13), + hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13), + hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13), + hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13), + hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13)); + p = &qqq[2]; + printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n", + hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13), + hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13), + hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13), + hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13), + hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13), + hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13)); + p = &qqqq[3]; + printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n", + hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13), + hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13), + hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13), + hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13), + hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13), + hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13)); + printf("\n"); + + /* check that hashlittle2 and hashlittle produce the same results */ + i=47; j=0; + hashlittle2(q, sizeof(q), &i, &j); + if (hashlittle(q, sizeof(q), 47) != i) + printf("hashlittle2 and hashlittle mismatch\n"); + + /* check that hashword2 and hashword produce the same results */ + len = raninit; + i=47, j=0; + hashword2(&len, 1, &i, &j); + if (hashword(&len, 1, 47) != i) + printf("hashword2 and hashword mismatch %x %x\n", + i, hashword(&len, 1, 47)); + + /* check hashlittle doesn't read before or after the ends of the string */ + for (h=0, b=buf+1; h<8; ++h, ++b) + { + for (i=0; ilock); + table->sizefunc = sizefunc; + table->compfunc = compfunc; + table->delkeyfunc = delkeyfunc; + table->deldatafunc = deldatafunc; + table->cb_arg = arg; + table->size = start_size; + table->size_mask = (int)(start_size-1); + table->lru_start = NULL; + table->lru_end = NULL; + table->num = 0; + table->space_used = 0; + table->space_max = maxmem; + table->array = calloc(table->size, sizeof(struct lruhash_bin)); + if(!table->array) { + lock_quick_destroy(&table->lock); + free(table); + return NULL; + } + bin_init(table->array, table->size); + lock_protect(&table->lock, table, sizeof(*table)); + lock_protect(&table->lock, table->array, + table->size*sizeof(struct lruhash_bin)); + return table; +} + +void +bin_delete(struct lruhash* table, struct lruhash_bin* bin) +{ + struct lruhash_entry* p, *np; + void *d; + if(!bin) + return; + lock_quick_destroy(&bin->lock); + p = bin->overflow_list; + bin->overflow_list = NULL; + while(p) { + np = p->overflow_next; + d = p->data; + (*table->delkeyfunc)(p->key, table->cb_arg); + (*table->deldatafunc)(d, table->cb_arg); + p = np; + } +} + +void +bin_split(struct lruhash* table, struct lruhash_bin* newa, + int newmask) +{ + size_t i; + struct lruhash_entry *p, *np; + struct lruhash_bin* newbin; + /* move entries to new table. Notice that since hash x is mapped to + * bin x & mask, and new mask uses one more bit, so all entries in + * one bin will go into the old bin or bin | newbit */ +#ifndef THREADS_DISABLED + int newbit = newmask - table->size_mask; +#endif + /* so, really, this task could also be threaded, per bin. */ + /* LRU list is not changed */ + for(i=0; isize; i++) + { + lock_quick_lock(&table->array[i].lock); + p = table->array[i].overflow_list; + /* lock both destination bins */ + lock_quick_lock(&newa[i].lock); + lock_quick_lock(&newa[newbit|i].lock); + while(p) { + np = p->overflow_next; + /* link into correct new bin */ + newbin = &newa[p->hash & newmask]; + p->overflow_next = newbin->overflow_list; + newbin->overflow_list = p; + p=np; + } + lock_quick_unlock(&newa[i].lock); + lock_quick_unlock(&newa[newbit|i].lock); + lock_quick_unlock(&table->array[i].lock); + } +} + +void +lruhash_delete(struct lruhash* table) +{ + size_t i; + if(!table) + return; + /* delete lock on hashtable to force check its OK */ + lock_quick_destroy(&table->lock); + for(i=0; isize; i++) + bin_delete(table, &table->array[i]); + free(table->array); + free(table); +} + +void +bin_overflow_remove(struct lruhash_bin* bin, struct lruhash_entry* entry) +{ + struct lruhash_entry* p = bin->overflow_list; + struct lruhash_entry** prevp = &bin->overflow_list; + while(p) { + if(p == entry) { + *prevp = p->overflow_next; + return; + } + prevp = &p->overflow_next; + p = p->overflow_next; + } +} + +void +reclaim_space(struct lruhash* table, struct lruhash_entry** list) +{ + struct lruhash_entry* d; + struct lruhash_bin* bin; + log_assert(table); + /* does not delete MRU entry, so table will not be empty. */ + while(table->num > 1 && table->space_used > table->space_max) { + /* notice that since we hold the hashtable lock, nobody + can change the lru chain. So it cannot be deleted underneath + us. We still need the hashbin and entry write lock to make + sure we flush all users away from the entry. + which is unlikely, since it is LRU, if someone got a rdlock + it would be moved to front, but to be sure. */ + d = table->lru_end; + /* specialised, delete from end of double linked list, + and we know num>1, so there is a previous lru entry. */ + log_assert(d && d->lru_prev); + table->lru_end = d->lru_prev; + d->lru_prev->lru_next = NULL; + /* schedule entry for deletion */ + bin = &table->array[d->hash & table->size_mask]; + table->num --; + lock_quick_lock(&bin->lock); + bin_overflow_remove(bin, d); + d->overflow_next = *list; + *list = d; + lock_rw_wrlock(&d->lock); + table->space_used -= table->sizefunc(d->key, d->data); + if(table->markdelfunc) + (*table->markdelfunc)(d->key); + lock_rw_unlock(&d->lock); + lock_quick_unlock(&bin->lock); + } +} + +struct lruhash_entry* +bin_find_entry(struct lruhash* table, + struct lruhash_bin* bin, hashvalue_t hash, void* key) +{ + struct lruhash_entry* p = bin->overflow_list; + while(p) { + if(p->hash == hash && table->compfunc(p->key, key) == 0) + return p; + p = p->overflow_next; + } + return NULL; +} + +void +table_grow(struct lruhash* table) +{ + struct lruhash_bin* newa; + int newmask; + size_t i; + if(table->size_mask == (int)(((size_t)-1)>>1)) { + log_err("hash array malloc: size_t too small"); + return; + } + /* try to allocate new array, if not fail */ + newa = calloc(table->size*2, sizeof(struct lruhash_bin)); + if(!newa) { + log_err("hash grow: malloc failed"); + /* continue with smaller array. Though its slower. */ + return; + } + bin_init(newa, table->size*2); + newmask = (table->size_mask << 1) | 1; + bin_split(table, newa, newmask); + /* delete the old bins */ + lock_unprotect(&table->lock, table->array); + for(i=0; isize; i++) { + lock_quick_destroy(&table->array[i].lock); + } + free(table->array); + + table->size *= 2; + table->size_mask = newmask; + table->array = newa; + lock_protect(&table->lock, table->array, + table->size*sizeof(struct lruhash_bin)); + return; +} + +void +lru_front(struct lruhash* table, struct lruhash_entry* entry) +{ + entry->lru_prev = NULL; + entry->lru_next = table->lru_start; + if(!table->lru_start) + table->lru_end = entry; + else table->lru_start->lru_prev = entry; + table->lru_start = entry; +} + +void +lru_remove(struct lruhash* table, struct lruhash_entry* entry) +{ + if(entry->lru_prev) + entry->lru_prev->lru_next = entry->lru_next; + else table->lru_start = entry->lru_next; + if(entry->lru_next) + entry->lru_next->lru_prev = entry->lru_prev; + else table->lru_end = entry->lru_prev; +} + +void +lru_touch(struct lruhash* table, struct lruhash_entry* entry) +{ + log_assert(table && entry); + if(entry == table->lru_start) + return; /* nothing to do */ + /* remove from current lru position */ + lru_remove(table, entry); + /* add at front */ + lru_front(table, entry); +} + +void +lruhash_insert(struct lruhash* table, hashvalue_t hash, + struct lruhash_entry* entry, void* data, void* cb_arg) +{ + struct lruhash_bin* bin; + struct lruhash_entry* found, *reclaimlist=NULL; + size_t need_size; + fptr_ok(fptr_whitelist_hash_sizefunc(table->sizefunc)); + fptr_ok(fptr_whitelist_hash_delkeyfunc(table->delkeyfunc)); + fptr_ok(fptr_whitelist_hash_deldatafunc(table->deldatafunc)); + fptr_ok(fptr_whitelist_hash_compfunc(table->compfunc)); + fptr_ok(fptr_whitelist_hash_markdelfunc(table->markdelfunc)); + need_size = table->sizefunc(entry->key, data); + if(cb_arg == NULL) cb_arg = table->cb_arg; + + /* find bin */ + lock_quick_lock(&table->lock); + bin = &table->array[hash & table->size_mask]; + lock_quick_lock(&bin->lock); + + /* see if entry exists already */ + if(!(found=bin_find_entry(table, bin, hash, entry->key))) { + /* if not: add to bin */ + entry->overflow_next = bin->overflow_list; + bin->overflow_list = entry; + lru_front(table, entry); + table->num++; + table->space_used += need_size; + } else { + /* if so: update data - needs a writelock */ + table->space_used += need_size - + (*table->sizefunc)(found->key, found->data); + (*table->delkeyfunc)(entry->key, cb_arg); + lru_touch(table, found); + lock_rw_wrlock(&found->lock); + (*table->deldatafunc)(found->data, cb_arg); + found->data = data; + lock_rw_unlock(&found->lock); + } + lock_quick_unlock(&bin->lock); + if(table->space_used > table->space_max) + reclaim_space(table, &reclaimlist); + if(table->num >= table->size) + table_grow(table); + lock_quick_unlock(&table->lock); + + /* finish reclaim if any (outside of critical region) */ + while(reclaimlist) { + struct lruhash_entry* n = reclaimlist->overflow_next; + void* d = reclaimlist->data; + (*table->delkeyfunc)(reclaimlist->key, cb_arg); + (*table->deldatafunc)(d, cb_arg); + reclaimlist = n; + } +} + +struct lruhash_entry* +lruhash_lookup(struct lruhash* table, hashvalue_t hash, void* key, int wr) +{ + struct lruhash_entry* entry; + struct lruhash_bin* bin; + fptr_ok(fptr_whitelist_hash_compfunc(table->compfunc)); + + lock_quick_lock(&table->lock); + bin = &table->array[hash & table->size_mask]; + lock_quick_lock(&bin->lock); + if((entry=bin_find_entry(table, bin, hash, key))) + lru_touch(table, entry); + lock_quick_unlock(&table->lock); + + if(entry) { + if(wr) { lock_rw_wrlock(&entry->lock); } + else { lock_rw_rdlock(&entry->lock); } + } + lock_quick_unlock(&bin->lock); + return entry; +} + +void +lruhash_remove(struct lruhash* table, hashvalue_t hash, void* key) +{ + struct lruhash_entry* entry; + struct lruhash_bin* bin; + void *d; + fptr_ok(fptr_whitelist_hash_sizefunc(table->sizefunc)); + fptr_ok(fptr_whitelist_hash_delkeyfunc(table->delkeyfunc)); + fptr_ok(fptr_whitelist_hash_deldatafunc(table->deldatafunc)); + fptr_ok(fptr_whitelist_hash_compfunc(table->compfunc)); + fptr_ok(fptr_whitelist_hash_markdelfunc(table->markdelfunc)); + + lock_quick_lock(&table->lock); + bin = &table->array[hash & table->size_mask]; + lock_quick_lock(&bin->lock); + if((entry=bin_find_entry(table, bin, hash, key))) { + bin_overflow_remove(bin, entry); + lru_remove(table, entry); + } else { + lock_quick_unlock(&table->lock); + lock_quick_unlock(&bin->lock); + return; + } + table->num--; + table->space_used -= (*table->sizefunc)(entry->key, entry->data); + lock_quick_unlock(&table->lock); + lock_rw_wrlock(&entry->lock); + if(table->markdelfunc) + (*table->markdelfunc)(entry->key); + lock_rw_unlock(&entry->lock); + lock_quick_unlock(&bin->lock); + /* finish removal */ + d = entry->data; + (*table->delkeyfunc)(entry->key, table->cb_arg); + (*table->deldatafunc)(d, table->cb_arg); +} + +/** clear bin, respecting locks, does not do space, LRU */ +static void +bin_clear(struct lruhash* table, struct lruhash_bin* bin) +{ + struct lruhash_entry* p, *np; + void *d; + lock_quick_lock(&bin->lock); + p = bin->overflow_list; + while(p) { + lock_rw_wrlock(&p->lock); + np = p->overflow_next; + d = p->data; + if(table->markdelfunc) + (*table->markdelfunc)(p->key); + lock_rw_unlock(&p->lock); + (*table->delkeyfunc)(p->key, table->cb_arg); + (*table->deldatafunc)(d, table->cb_arg); + p = np; + } + bin->overflow_list = NULL; + lock_quick_unlock(&bin->lock); +} + +void +lruhash_clear(struct lruhash* table) +{ + size_t i; + if(!table) + return; + fptr_ok(fptr_whitelist_hash_delkeyfunc(table->delkeyfunc)); + fptr_ok(fptr_whitelist_hash_deldatafunc(table->deldatafunc)); + fptr_ok(fptr_whitelist_hash_markdelfunc(table->markdelfunc)); + + lock_quick_lock(&table->lock); + for(i=0; isize; i++) { + bin_clear(table, &table->array[i]); + } + table->lru_start = NULL; + table->lru_end = NULL; + table->num = 0; + table->space_used = 0; + lock_quick_unlock(&table->lock); +} + +void +lruhash_status(struct lruhash* table, const char* id, int extended) +{ + lock_quick_lock(&table->lock); + log_info("%s: %u entries, memory %u / %u", + id, (unsigned)table->num, (unsigned)table->space_used, + (unsigned)table->space_max); + log_info(" itemsize %u, array %u, mask %d", + (unsigned)(table->num? table->space_used/table->num : 0), + (unsigned)table->size, table->size_mask); + if(extended) { + size_t i; + int min=(int)table->size*2, max=-2; + for(i=0; isize; i++) { + int here = 0; + struct lruhash_entry *en; + lock_quick_lock(&table->array[i].lock); + en = table->array[i].overflow_list; + while(en) { + here ++; + en = en->overflow_next; + } + lock_quick_unlock(&table->array[i].lock); + if(extended >= 2) + log_info("bin[%d] %d", (int)i, here); + if(here > max) max = here; + if(here < min) min = here; + } + log_info(" bin min %d, avg %.2lf, max %d", min, + (double)table->num/(double)table->size, max); + } + lock_quick_unlock(&table->lock); +} + +size_t +lruhash_get_mem(struct lruhash* table) +{ + size_t s; + lock_quick_lock(&table->lock); + s = sizeof(struct lruhash) + table->space_used; +#ifdef USE_THREAD_DEBUG + if(table->size != 0) { + size_t i; + for(i=0; isize; i++) + s += sizeof(struct lruhash_bin) + + lock_get_mem(&table->array[i].lock); + } +#else /* no THREAD_DEBUG */ + if(table->size != 0) + s += (table->size)*(sizeof(struct lruhash_bin) + + lock_get_mem(&table->array[0].lock)); +#endif + lock_quick_unlock(&table->lock); + s += lock_get_mem(&table->lock); + return s; +} + +void +lruhash_setmarkdel(struct lruhash* table, lruhash_markdelfunc_t md) +{ + lock_quick_lock(&table->lock); + table->markdelfunc = md; + lock_quick_unlock(&table->lock); +} + +void +lruhash_traverse(struct lruhash* h, int wr, + void (*func)(struct lruhash_entry*, void*), void* arg) +{ + size_t i; + struct lruhash_entry* e; + + lock_quick_lock(&h->lock); + for(i=0; isize; i++) { + lock_quick_lock(&h->array[i].lock); + for(e = h->array[i].overflow_list; e; e = e->overflow_next) { + if(wr) { + lock_rw_wrlock(&e->lock); + } else { + lock_rw_rdlock(&e->lock); + } + (*func)(e, arg); + lock_rw_unlock(&e->lock); + } + lock_quick_unlock(&h->array[i].lock); + } + lock_quick_unlock(&h->lock); +} diff --git a/util/storage/lruhash.h b/util/storage/lruhash.h new file mode 100644 index 00000000000..d0efe2d3b59 --- /dev/null +++ b/util/storage/lruhash.h @@ -0,0 +1,414 @@ +/* + * util/storage/lruhash.h - hashtable, hash function, LRU keeping. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains a hashtable with LRU keeping of entries. + * + * The hash table keeps a maximum memory size. Old entries are removed + * to make space for new entries. + * + * The locking strategy is as follows: + * o since (almost) every read also implies a LRU update, the + * hashtable lock is a spinlock, not rwlock. + * o the idea is to move every thread through the hash lock quickly, + * so that the next thread can access the lookup table. + * o User performs hash function. + * + * For read: + * o lock hashtable. + * o lookup hash bin. + * o lock hash bin. + * o find entry (if failed, unlock hash, unl bin, exit). + * o swizzle pointers for LRU update. + * o unlock hashtable. + * o lock entry (rwlock). + * o unlock hash bin. + * o work on entry. + * o unlock entry. + * + * To update an entry, gain writelock and change the entry. + * (the entry must keep the same hashvalue, so a data update.) + * (you cannot upgrade a readlock to a writelock, because the item may + * be deleted, it would cause race conditions. So instead, unlock and + * relookup it in the hashtable.) + * + * To delete an entry: + * o unlock the entry if you hold the lock already. + * o lock hashtable. + * o lookup hash bin. + * o lock hash bin. + * o find entry (if failed, unlock hash, unl bin, exit). + * o remove entry from hashtable bin overflow chain. + * o unlock hashtable. + * o lock entry (writelock). + * o unlock hash bin. + * o unlock entry (nobody else should be waiting for this lock, + * since you removed it from hashtable, and you got writelock while + * holding the hashbinlock so you are the only one.) + * Note you are only allowed to obtain a lock while holding hashbinlock. + * o delete entry. + * + * The above sequence is: + * o race free, works with read, write and delete. + * o but has a queue, imagine someone needing a writelock on an item. + * but there are still readlocks. The writelocker waits, but holds + * the hashbinlock. The next thread that comes in and needs the same + * hashbin will wait for the lock while holding the hashtable lock. + * thus halting the entire system on hashtable. + * This is because of the delete protection. + * Readlocks will be easier on the rwlock on entries. + * While the writer is holding writelock, similar problems happen with + * a reader or writer needing the same item. + * the scenario requires more than three threads. + * o so the queue length is 3 threads in a bad situation. The fourth is + * unable to use the hashtable. + * + * If you need to acquire locks on multiple items from the hashtable. + * o you MUST release all locks on items from the hashtable before + * doing the next lookup/insert/delete/whatever. + * o To acquire multiple items you should use a special routine that + * obtains the locks on those multiple items in one go. + */ + +#ifndef UTIL_STORAGE_LRUHASH_H +#define UTIL_STORAGE_LRUHASH_H +#include "util/locks.h" +struct lruhash_bin; +struct lruhash_entry; + +/** default start size for hash arrays */ +#define HASH_DEFAULT_STARTARRAY 1024 /* entries in array */ +/** default max memory for hash arrays */ +#define HASH_DEFAULT_MAXMEM 4*1024*1024 /* bytes */ + +/** the type of a hash value */ +typedef uint32_t hashvalue_t; + +/** + * Type of function that calculates the size of an entry. + * Result must include the size of struct lruhash_entry. + * Keys that are identical must also calculate to the same size. + * size = func(key, data). + */ +typedef size_t (*lruhash_sizefunc_t)(void*, void*); + +/** type of function that compares two keys. return 0 if equal. */ +typedef int (*lruhash_compfunc_t)(void*, void*); + +/** old keys are deleted. + * The RRset type has to revoke its ID number, markdel() is used first. + * This function is called: func(key, userarg) */ +typedef void (*lruhash_delkeyfunc_t)(void*, void*); + +/** old data is deleted. This function is called: func(data, userarg). */ +typedef void (*lruhash_deldatafunc_t)(void*, void*); + +/** mark a key as pending to be deleted (and not to be used by anyone). + * called: func(key) */ +typedef void (*lruhash_markdelfunc_t)(void*); + +/** + * Hash table that keeps LRU list of entries. + */ +struct lruhash { + /** lock for exclusive access, to the lookup array */ + lock_quick_t lock; + /** the size function for entries in this table */ + lruhash_sizefunc_t sizefunc; + /** the compare function for entries in this table. */ + lruhash_compfunc_t compfunc; + /** how to delete keys. */ + lruhash_delkeyfunc_t delkeyfunc; + /** how to delete data. */ + lruhash_deldatafunc_t deldatafunc; + /** how to mark a key pending deletion */ + lruhash_markdelfunc_t markdelfunc; + /** user argument for user functions */ + void* cb_arg; + + /** the size of the lookup array */ + size_t size; + /** size bitmask - since size is a power of 2 */ + int size_mask; + /** lookup array of bins */ + struct lruhash_bin* array; + + /** the lru list, start and end, noncyclical double linked list. */ + struct lruhash_entry* lru_start; + /** lru list end item (least recently used) */ + struct lruhash_entry* lru_end; + + /** the number of entries in the hash table. */ + size_t num; + /** the amount of space used, roughly the number of bytes in use. */ + size_t space_used; + /** the amount of space the hash table is maximally allowed to use. */ + size_t space_max; +}; + +/** + * A single bin with a linked list of entries in it. + */ +struct lruhash_bin { + /** + * Lock for exclusive access to the linked list + * This lock makes deletion of items safe in this overflow list. + */ + lock_quick_t lock; + /** linked list of overflow entries */ + struct lruhash_entry* overflow_list; +}; + +/** + * An entry into the hash table. + * To change overflow_next you need to hold the bin lock. + * To change the lru items you need to hold the hashtable lock. + * This structure is designed as part of key struct. And key pointer helps + * to get the surrounding structure. Data should be allocated on its own. + */ +struct lruhash_entry { + /** + * rwlock for access to the contents of the entry + * Note that it does _not_ cover the lru_ and overflow_ ptrs. + * Even with a writelock, you cannot change hash and key. + * You need to delete it to change hash or key. + */ + lock_rw_t lock; + /** next entry in overflow chain. Covered by hashlock and binlock. */ + struct lruhash_entry* overflow_next; + /** next entry in lru chain. covered by hashlock. */ + struct lruhash_entry* lru_next; + /** prev entry in lru chain. covered by hashlock. */ + struct lruhash_entry* lru_prev; + /** hash value of the key. It may not change, until entry deleted. */ + hashvalue_t hash; + /** key */ + void* key; + /** data */ + void* data; +}; + +/** + * Create new hash table. + * @param start_size: size of hashtable array at start, must be power of 2. + * @param maxmem: maximum amount of memory this table is allowed to use. + * @param sizefunc: calculates memory usage of entries. + * @param compfunc: compares entries, 0 on equality. + * @param delkeyfunc: deletes key. + * Calling both delkey and deldata will also free the struct lruhash_entry. + * Make it part of the key structure and delete it in delkeyfunc. + * @param deldatafunc: deletes data. + * @param arg: user argument that is passed to user function calls. + * @return: new hash table or NULL on malloc failure. + */ +struct lruhash* lruhash_create(size_t start_size, size_t maxmem, + lruhash_sizefunc_t sizefunc, lruhash_compfunc_t compfunc, + lruhash_delkeyfunc_t delkeyfunc, lruhash_deldatafunc_t deldatafunc, + void* arg); + +/** + * Delete hash table. Entries are all deleted. + * @param table: to delete. + */ +void lruhash_delete(struct lruhash* table); + +/** + * Clear hash table. Entries are all deleted, while locking them before + * doing so. At end the table is empty. + * @param table: to make empty. + */ +void lruhash_clear(struct lruhash* table); + +/** + * Insert a new element into the hashtable. + * If key is already present data pointer in that entry is updated. + * The space calculation function is called with the key, data. + * If necessary the least recently used entries are deleted to make space. + * If necessary the hash array is grown up. + * + * @param table: hash table. + * @param hash: hash value. User calculates the hash. + * @param entry: identifies the entry. + * If key already present, this entry->key is deleted immediately. + * But entry->data is set to NULL before deletion, and put into + * the existing entry. The data is then freed. + * @param data: the data. + * @param cb_override: if not null overrides the cb_arg for the deletefunc. + */ +void lruhash_insert(struct lruhash* table, hashvalue_t hash, + struct lruhash_entry* entry, void* data, void* cb_override); + +/** + * Lookup an entry in the hashtable. + * At the end of the function you hold a (read/write)lock on the entry. + * The LRU is updated for the entry (if found). + * @param table: hash table. + * @param hash: hash of key. + * @param key: what to look for, compared against entries in overflow chain. + * the hash value must be set, and must work with compare function. + * @param wr: set to true if you desire a writelock on the entry. + * with a writelock you can update the data part. + * @return: pointer to the entry or NULL. The entry is locked. + * The user must unlock the entry when done. + */ +struct lruhash_entry* lruhash_lookup(struct lruhash* table, hashvalue_t hash, + void* key, int wr); + +/** + * Touch entry, so it becomes the most recently used in the LRU list. + * Caller must hold hash table lock. The entry must be inserted already. + * @param table: hash table. + * @param entry: entry to make first in LRU. + */ +void lru_touch(struct lruhash* table, struct lruhash_entry* entry); + +/** + * Set the markdelfunction (or NULL) + */ +void lruhash_setmarkdel(struct lruhash* table, lruhash_markdelfunc_t md); + +/************************* Internal functions ************************/ +/*** these are only exposed for unit tests. ***/ + +/** + * Remove entry from hashtable. Does nothing if not found in hashtable. + * Delfunc is called for the entry. + * @param table: hash table. + * @param hash: hash of key. + * @param key: what to look for. + */ +void lruhash_remove(struct lruhash* table, hashvalue_t hash, void* key); + +/** init the hash bins for the table */ +void bin_init(struct lruhash_bin* array, size_t size); + +/** delete the hash bin and entries inside it */ +void bin_delete(struct lruhash* table, struct lruhash_bin* bin); + +/** + * Find entry in hash bin. You must have locked the bin. + * @param table: hash table with function pointers. + * @param bin: hash bin to look into. + * @param hash: hash value to look for. + * @param key: key to look for. + * @return: the entry or NULL if not found. + */ +struct lruhash_entry* bin_find_entry(struct lruhash* table, + struct lruhash_bin* bin, hashvalue_t hash, void* key); + +/** + * Remove entry from bin overflow chain. + * You must have locked the bin. + * @param bin: hash bin to look into. + * @param entry: entry ptr that needs removal. + */ +void bin_overflow_remove(struct lruhash_bin* bin, + struct lruhash_entry* entry); + +/** + * Split hash bin into two new ones. Based on increased size_mask. + * Caller must hold hash table lock. + * At the end the routine acquires all hashbin locks (in the old array). + * This makes it wait for other threads to finish with the bins. + * So the bins are ready to be deleted after this function. + * @param table: hash table with function pointers. + * @param newa: new increased array. + * @param newmask: new lookup mask. + */ +void bin_split(struct lruhash* table, struct lruhash_bin* newa, + int newmask); + +/** + * Try to make space available by deleting old entries. + * Assumes that the lock on the hashtable is being held by caller. + * Caller must not hold bin locks. + * @param table: hash table. + * @param list: list of entries that are to be deleted later. + * Entries have been removed from the hash table and writelock is held. + */ +void reclaim_space(struct lruhash* table, struct lruhash_entry** list); + +/** + * Grow the table lookup array. Becomes twice as large. + * Caller must hold the hash table lock. Must not hold any bin locks. + * Tries to grow, on malloc failure, nothing happened. + * @param table: hash table. + */ +void table_grow(struct lruhash* table); + +/** + * Put entry at front of lru. entry must be unlinked from lru. + * Caller must hold hash table lock. + * @param table: hash table with lru head and tail. + * @param entry: entry to make most recently used. + */ +void lru_front(struct lruhash* table, struct lruhash_entry* entry); + +/** + * Remove entry from lru list. + * Caller must hold hash table lock. + * @param table: hash table with lru head and tail. + * @param entry: entry to remove from lru. + */ +void lru_remove(struct lruhash* table, struct lruhash_entry* entry); + +/** + * Output debug info to the log as to state of the hash table. + * @param table: hash table. + * @param id: string printed with table to identify the hash table. + * @param extended: set to true to print statistics on overflow bin lengths. + */ +void lruhash_status(struct lruhash* table, const char* id, int extended); + +/** + * Get memory in use now by the lruhash table. + * @param table: hash table. Will be locked before use. And unlocked after. + * @return size in bytes. + */ +size_t lruhash_get_mem(struct lruhash* table); + +/** + * Traverse a lruhash. Call back for every element in the table. + * @param h: hash table. Locked before use. + * @param wr: if true writelock is obtained on element, otherwise readlock. + * @param func: function for every element. Do not lock or unlock elements. + * @param arg: user argument to func. + */ +void lruhash_traverse(struct lruhash* h, int wr, + void (*func)(struct lruhash_entry*, void*), void* arg); + +#endif /* UTIL_STORAGE_LRUHASH_H */ diff --git a/util/storage/slabhash.c b/util/storage/slabhash.c new file mode 100644 index 00000000000..9c0c5071175 --- /dev/null +++ b/util/storage/slabhash.c @@ -0,0 +1,219 @@ +/* + * util/storage/slabhash.c - hashtable consisting of several smaller tables. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * Implementation of hash table that consists of smaller hash tables. + * This results in a partitioned lruhash table. + * It cannot grow, but that gives it the ability to have multiple + * locks. Also this means there are multiple LRU lists. + */ + +#include "config.h" +#include "util/storage/slabhash.h" + +struct slabhash* slabhash_create(size_t numtables, size_t start_size, + size_t maxmem, lruhash_sizefunc_t sizefunc, + lruhash_compfunc_t compfunc, lruhash_delkeyfunc_t delkeyfunc, + lruhash_deldatafunc_t deldatafunc, void* arg) +{ + size_t i; + struct slabhash* sl = (struct slabhash*)calloc(1, + sizeof(struct slabhash)); + if(!sl) return NULL; + sl->size = numtables; + log_assert(sl->size > 0); + sl->array = (struct lruhash**)calloc(sl->size, sizeof(struct lruhash*)); + if(!sl->array) { + free(sl); + return NULL; + } + sl->mask = (uint32_t)(sl->size - 1); + if(sl->mask == 0) { + sl->shift = 0; + } else { + log_assert( (sl->size & sl->mask) == 0 + /* size must be power of 2 */ ); + sl->shift = 0; + while(!(sl->mask & 0x80000000)) { + sl->mask <<= 1; + sl->shift ++; + } + } + for(i=0; isize; i++) { + sl->array[i] = lruhash_create(start_size, maxmem / sl->size, + sizefunc, compfunc, delkeyfunc, deldatafunc, arg); + if(!sl->array[i]) { + slabhash_delete(sl); + return NULL; + } + } + return sl; +} + +void slabhash_delete(struct slabhash* sl) +{ + if(!sl) + return; + if(sl->array) { + size_t i; + for(i=0; isize; i++) + lruhash_delete(sl->array[i]); + free(sl->array); + } + free(sl); +} + +void slabhash_clear(struct slabhash* sl) +{ + size_t i; + if(!sl) + return; + for(i=0; isize; i++) + lruhash_clear(sl->array[i]); +} + +/** helper routine to calculate the slabhash index */ +static unsigned int +slab_idx(struct slabhash* sl, hashvalue_t hash) +{ + return ((hash & sl->mask) >> sl->shift); +} + +void slabhash_insert(struct slabhash* sl, hashvalue_t hash, + struct lruhash_entry* entry, void* data, void* arg) +{ + lruhash_insert(sl->array[slab_idx(sl, hash)], hash, entry, data, arg); +} + +struct lruhash_entry* slabhash_lookup(struct slabhash* sl, + hashvalue_t hash, void* key, int wr) +{ + return lruhash_lookup(sl->array[slab_idx(sl, hash)], hash, key, wr); +} + +void slabhash_remove(struct slabhash* sl, hashvalue_t hash, void* key) +{ + lruhash_remove(sl->array[slab_idx(sl, hash)], hash, key); +} + +void slabhash_status(struct slabhash* sl, const char* id, int extended) +{ + size_t i; + char num[17]; + log_info("Slabhash %s: %u tables mask=%x shift=%d", + id, (unsigned)sl->size, (unsigned)sl->mask, sl->shift); + for(i=0; isize; i++) { + snprintf(num, sizeof(num), "table %u", (unsigned)i); + lruhash_status(sl->array[i], num, extended); + } +} + +size_t slabhash_get_size(struct slabhash* sl) +{ + size_t i, total = 0; + for(i=0; isize; i++) { + lock_quick_lock(&sl->array[i]->lock); + total += sl->array[i]->space_max; + lock_quick_unlock(&sl->array[i]->lock); + } + return total; +} + +size_t slabhash_get_mem(struct slabhash* sl) +{ + size_t i, total = sizeof(*sl); + total += sizeof(struct lruhash*)*sl->size; + for(i=0; isize; i++) { + total += lruhash_get_mem(sl->array[i]); + } + return total; +} + +struct lruhash* slabhash_gettable(struct slabhash* sl, hashvalue_t hash) +{ + return sl->array[slab_idx(sl, hash)]; +} + +/* test code, here to avoid linking problems with fptr_wlist */ +/** delete key */ +static void delkey(struct slabhash_testkey* k) { + lock_rw_destroy(&k->entry.lock); free(k);} +/** delete data */ +static void deldata(struct slabhash_testdata* d) {free(d);} + +size_t test_slabhash_sizefunc(void* ATTR_UNUSED(key), void* ATTR_UNUSED(data)) +{ + return sizeof(struct slabhash_testkey) + + sizeof(struct slabhash_testdata); +} + +int test_slabhash_compfunc(void* key1, void* key2) +{ + struct slabhash_testkey* k1 = (struct slabhash_testkey*)key1; + struct slabhash_testkey* k2 = (struct slabhash_testkey*)key2; + if(k1->id == k2->id) + return 0; + if(k1->id > k2->id) + return 1; + return -1; +} + +void test_slabhash_delkey(void* key, void* ATTR_UNUSED(arg)) +{ + delkey((struct slabhash_testkey*)key); +} + +void test_slabhash_deldata(void* data, void* ATTR_UNUSED(arg)) +{ + deldata((struct slabhash_testdata*)data); +} + +void slabhash_setmarkdel(struct slabhash* sl, lruhash_markdelfunc_t md) +{ + size_t i; + for(i=0; isize; i++) { + lruhash_setmarkdel(sl->array[i], md); + } +} + +void slabhash_traverse(struct slabhash* sh, int wr, + void (*func)(struct lruhash_entry*, void*), void* arg) +{ + size_t i; + for(i=0; isize; i++) + lruhash_traverse(sh->array[i], wr, func, arg); +} diff --git a/util/storage/slabhash.h b/util/storage/slabhash.h new file mode 100644 index 00000000000..93228febcfe --- /dev/null +++ b/util/storage/slabhash.h @@ -0,0 +1,211 @@ +/* + * util/storage/slabhash.h - hashtable consisting of several smaller tables. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * Hash table that consists of smaller hash tables. + * It cannot grow, but that gives it the ability to have multiple + * locks. Also this means there are multiple LRU lists. + */ + +#ifndef UTIL_STORAGE_SLABHASH_H +#define UTIL_STORAGE_SLABHASH_H +#include "util/storage/lruhash.h" + +/** default number of slabs */ +#define HASH_DEFAULT_SLABS 4 + +/** + * Hash table formed from several smaller ones. + * This results in a partitioned lruhash table, a 'slashtable'. + * None of the data inside the slabhash may be altered. + * Therefore, no locks are needed to access the structure. + */ +struct slabhash { + /** the size of the array - must be power of 2 */ + size_t size; + /** size bitmask - uses high bits. */ + uint32_t mask; + /** shift right this many bits to get index into array. */ + unsigned int shift; + /** lookup array of hash tables */ + struct lruhash** array; +}; + +/** + * Create new slabbed hash table. + * @param numtables: number of hash tables to use, other parameters used to + * initialize these smaller hashtables. + * @param start_size: size of hashtable array at start, must be power of 2. + * @param maxmem: maximum amount of memory this table is allowed to use. + * so every table gets maxmem/numtables to use for itself. + * @param sizefunc: calculates memory usage of entries. + * @param compfunc: compares entries, 0 on equality. + * @param delkeyfunc: deletes key. + * @param deldatafunc: deletes data. + * @param arg: user argument that is passed to user function calls. + * @return: new hash table or NULL on malloc failure. + */ +struct slabhash* slabhash_create(size_t numtables, size_t start_size, + size_t maxmem, lruhash_sizefunc_t sizefunc, + lruhash_compfunc_t compfunc, lruhash_delkeyfunc_t delkeyfunc, + lruhash_deldatafunc_t deldatafunc, void* arg); + +/** + * Delete hash table. Entries are all deleted. + * @param table: to delete. + */ +void slabhash_delete(struct slabhash* table); + +/** + * Clear hash table. Entries are all deleted. + * @param table: to make empty. + */ +void slabhash_clear(struct slabhash* table); + +/** + * Insert a new element into the hashtable, uses lruhash_insert. + * If key is already present data pointer in that entry is updated. + * + * @param table: hash table. + * @param hash: hash value. User calculates the hash. + * @param entry: identifies the entry. + * If key already present, this entry->key is deleted immediately. + * But entry->data is set to NULL before deletion, and put into + * the existing entry. The data is then freed. + * @param data: the data. + * @param cb_override: if not NULL overrides the cb_arg for deletfunc. + */ +void slabhash_insert(struct slabhash* table, hashvalue_t hash, + struct lruhash_entry* entry, void* data, void* cb_override); + +/** + * Lookup an entry in the hashtable. Uses lruhash_lookup. + * At the end of the function you hold a (read/write)lock on the entry. + * The LRU is updated for the entry (if found). + * @param table: hash table. + * @param hash: hash of key. + * @param key: what to look for, compared against entries in overflow chain. + * the hash value must be set, and must work with compare function. + * @param wr: set to true if you desire a writelock on the entry. + * with a writelock you can update the data part. + * @return: pointer to the entry or NULL. The entry is locked. + * The user must unlock the entry when done. + */ +struct lruhash_entry* slabhash_lookup(struct slabhash* table, + hashvalue_t hash, void* key, int wr); + +/** + * Remove entry from hashtable. Does nothing if not found in hashtable. + * Delfunc is called for the entry. Uses lruhash_remove. + * @param table: hash table. + * @param hash: hash of key. + * @param key: what to look for. + */ +void slabhash_remove(struct slabhash* table, hashvalue_t hash, void* key); + +/** + * Output debug info to the log as to state of the hash table. + * @param table: hash table. + * @param id: string printed with table to identify the hash table. + * @param extended: set to true to print statistics on overflow bin lengths. + */ +void slabhash_status(struct slabhash* table, const char* id, int extended); + +/** + * Retrieve slab hash total size. + * @param table: hash table. + * @return size configured as max. + */ +size_t slabhash_get_size(struct slabhash* table); + +/** + * Retrieve slab hash current memory use. + * @param table: hash table. + * @return memory in use. + */ +size_t slabhash_get_mem(struct slabhash* table); + +/** + * Get lruhash table for a given hash value + * @param table: slabbed hash table. + * @param hash: hash value. + * @return the lru hash table. + */ +struct lruhash* slabhash_gettable(struct slabhash* table, hashvalue_t hash); + +/** + * Set markdel function + * @param table: slabbed hash table. + * @param md: markdel function ptr. + */ +void slabhash_setmarkdel(struct slabhash* table, lruhash_markdelfunc_t md); + +/** + * Traverse a slabhash. + * @param table: slabbed hash table. + * @param wr: if true, writelock is obtained, otherwise readlock. + * @param func: function to call for every element. + * @param arg: user argument to function. + */ +void slabhash_traverse(struct slabhash* table, int wr, + void (*func)(struct lruhash_entry*, void*), void* arg); + +/* --- test representation --- */ +/** test structure contains test key */ +struct slabhash_testkey { + /** the key id */ + int id; + /** the entry */ + struct lruhash_entry entry; +}; +/** test structure contains test data */ +struct slabhash_testdata { + /** data value */ + int data; +}; + +/** test sizefunc for lruhash */ +size_t test_slabhash_sizefunc(void*, void*); +/** test comparefunc for lruhash */ +int test_slabhash_compfunc(void*, void*); +/** test delkey for lruhash */ +void test_slabhash_delkey(void*, void*); +/** test deldata for lruhash */ +void test_slabhash_deldata(void*, void*); +/* --- end test representation --- */ + +#endif /* UTIL_STORAGE_SLABHASH_H */ diff --git a/util/timehist.c b/util/timehist.c new file mode 100644 index 00000000000..98d8db1c8f0 --- /dev/null +++ b/util/timehist.c @@ -0,0 +1,246 @@ +/* + * util/timehist.c - make histogram of time values. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions to make a histogram of time values. + */ +#include "config.h" +#ifdef HAVE_TIME_H +#include +#endif +#include +#include "util/timehist.h" +#include "util/log.h" + +/** special timestwo operation for time values in histogram setup */ +static void +timestwo(struct timeval* v) +{ +#ifndef S_SPLINT_S + if(v->tv_sec == 0 && v->tv_usec == 0) { + v->tv_usec = 1; + return; + } + v->tv_sec *= 2; + v->tv_usec *= 2; + if(v->tv_usec == 1024*1024) { + /* nice values and easy to compute */ + v->tv_sec = 1; + v->tv_usec = 0; + } +#endif +} + +/** do setup exponentially */ +static void +dosetup(struct timehist* hist) +{ + struct timeval last; + size_t i; + memset(&last, 0, sizeof(last)); + for(i=0; inum; i++) { + hist->buckets[i].lower = last; + timestwo(&last); + hist->buckets[i].upper = last; + hist->buckets[i].count = 0; + } +} + +struct timehist* timehist_setup(void) +{ + struct timehist* hist = (struct timehist*)calloc(1, + sizeof(struct timehist)); + if(!hist) + return NULL; + hist->num = NUM_BUCKETS_HIST; + hist->buckets = (struct th_buck*)calloc(hist->num, + sizeof(struct th_buck)); + if(!hist->buckets) { + free(hist); + return NULL; + } + /* setup the buckets */ + dosetup(hist); + return hist; +} + +void timehist_delete(struct timehist* hist) +{ + if(!hist) + return; + free(hist->buckets); + free(hist); +} + +void timehist_clear(struct timehist* hist) +{ + size_t i; + for(i=0; inum; i++) + hist->buckets[i].count = 0; +} + +/** histogram compare of time values */ +static int +timeval_smaller(const struct timeval* x, const struct timeval* y) +{ +#ifndef S_SPLINT_S + if(x->tv_sec < y->tv_sec) + return 1; + else if(x->tv_sec == y->tv_sec) { + if(x->tv_usec <= y->tv_usec) + return 1; + else return 0; + } + else return 0; +#endif +} + + +void timehist_insert(struct timehist* hist, struct timeval* tv) +{ + size_t i; + for(i=0; inum; i++) { + if(timeval_smaller(tv, &hist->buckets[i].upper)) { + hist->buckets[i].count++; + return; + } + } + /* dump in last bucket */ + hist->buckets[hist->num-1].count++; +} + +void timehist_print(struct timehist* hist) +{ +#ifndef S_SPLINT_S + size_t i; + for(i=0; inum; i++) { + if(hist->buckets[i].count != 0) { + printf("%4d.%6.6d %4d.%6.6d %u\n", + (int)hist->buckets[i].lower.tv_sec, + (int)hist->buckets[i].lower.tv_usec, + (int)hist->buckets[i].upper.tv_sec, + (int)hist->buckets[i].upper.tv_usec, + (unsigned)hist->buckets[i].count); + } + } +#endif +} + +void timehist_log(struct timehist* hist, const char* name) +{ +#ifndef S_SPLINT_S + size_t i; + log_info("[25%%]=%g median[50%%]=%g [75%%]=%g", + timehist_quartile(hist, 0.25), + timehist_quartile(hist, 0.50), + timehist_quartile(hist, 0.75)); + /* 0000.000000 0000.000000 0 */ + log_info("lower(secs) upper(secs) %s", name); + for(i=0; inum; i++) { + if(hist->buckets[i].count != 0) { + log_info("%4d.%6.6d %4d.%6.6d %u", + (int)hist->buckets[i].lower.tv_sec, + (int)hist->buckets[i].lower.tv_usec, + (int)hist->buckets[i].upper.tv_sec, + (int)hist->buckets[i].upper.tv_usec, + (unsigned)hist->buckets[i].count); + } + } +#endif +} + +/** total number in histogram */ +static size_t +timehist_count(struct timehist* hist) +{ + size_t i, res = 0; + for(i=0; inum; i++) + res += hist->buckets[i].count; + return res; +} + +double +timehist_quartile(struct timehist* hist, double q) +{ + double lookfor, passed, res; + double low = 0, up = 0; + size_t i; + if(!hist || hist->num == 0) + return 0.; + /* look for i'th element, interpolated */ + lookfor = (double)timehist_count(hist); + if(lookfor < 4) + return 0.; /* not enough elements for a good estimate */ + lookfor *= q; + passed = 0; + i = 0; + while(i+1 < hist->num && + passed+(double)hist->buckets[i].count < lookfor) { + passed += (double)hist->buckets[i++].count; + } + /* got the right bucket */ +#ifndef S_SPLINT_S + low = (double)hist->buckets[i].lower.tv_sec + + (double)hist->buckets[i].lower.tv_usec/1000000.; + up = (double)hist->buckets[i].upper.tv_sec + + (double)hist->buckets[i].upper.tv_usec/1000000.; +#endif + res = (lookfor - passed)*(up-low)/((double)hist->buckets[i].count); + return low+res; +} + +void +timehist_export(struct timehist* hist, size_t* array, size_t sz) +{ + size_t i; + if(!hist) return; + if(sz > hist->num) + sz = hist->num; + for(i=0; ibuckets[i].count; +} + +void +timehist_import(struct timehist* hist, size_t* array, size_t sz) +{ + size_t i; + if(!hist) return; + if(sz > hist->num) + sz = hist->num; + for(i=0; ibuckets[i].count = array[i]; +} diff --git a/util/timehist.h b/util/timehist.h new file mode 100644 index 00000000000..d59448399b9 --- /dev/null +++ b/util/timehist.h @@ -0,0 +1,134 @@ +/* + * util/timehist.h - make histogram of time values. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions to make a histogram of time values. + */ + +#ifndef UTIL_TIMEHIST_H +#define UTIL_TIMEHIST_H + +/** Number of buckets in a histogram */ +#define NUM_BUCKETS_HIST 40 + +/** + * Bucket of time history information + */ +struct th_buck { + /** lower bound */ + struct timeval lower; + /** upper bound */ + struct timeval upper; + /** number of items */ + size_t count; +}; + +/** + * Keep histogram of time values. + */ +struct timehist { + /** number of buckets */ + size_t num; + /** bucket array */ + struct th_buck* buckets; +}; + +/** + * Setup a histogram, default + * @return histogram or NULL on malloc failure. + */ +struct timehist* timehist_setup(void); + +/** + * Delete histogram + * @param hist: to delete + */ +void timehist_delete(struct timehist* hist); + +/** + * Clear histogram + * @param hist: to clear all data from + */ +void timehist_clear(struct timehist* hist); + +/** + * Add time value to histogram. + * @param hist: histogram + * @param tv: time value + */ +void timehist_insert(struct timehist* hist, struct timeval* tv); + +/** + * Find time value for given quartile, such as 0.25, 0.50, 0.75. + * The looks up the value for the i-th element in the sorted list of time + * values, as approximated using the histogram. + * @param hist: histogram. Interpolated information is used from it. + * @param q: quartile, 0.50 results in the median. Must be >0 and <1. + * @return: the time in seconds for that percentage. + */ +double timehist_quartile(struct timehist* hist, double q); + +/** + * Printout histogram + * @param hist: histogram + */ +void timehist_print(struct timehist* hist); + +/** + * Log histogram, print it to the logfile. + * @param hist: histogram + * @param name: the name of the value column + */ +void timehist_log(struct timehist* hist, const char* name); + +/** + * Export histogram to an array. + * @param hist: histogram + * @param array: the array to export to. + * @param sz: number of items in array. + */ +void timehist_export(struct timehist* hist, size_t* array, size_t sz); + +/** + * Import histogram from an array. + * @param hist: histogram + * @param array: the array to import from. + * @param sz: number of items in array. + */ +void timehist_import(struct timehist* hist, size_t* array, size_t sz); + +#endif /* UTIL_TIMEHIST_H */ diff --git a/util/tube.c b/util/tube.c new file mode 100644 index 00000000000..67294e056c4 --- /dev/null +++ b/util/tube.c @@ -0,0 +1,726 @@ +/* + * util/tube.c - pipe service + * + * Copyright (c) 2008, 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains pipe service functions. + */ +#include "config.h" +#include "util/tube.h" +#include "util/log.h" +#include "util/net_help.h" +#include "util/netevent.h" +#include "util/fptr_wlist.h" + +#ifndef USE_WINSOCK +/* on unix */ + +#ifndef HAVE_SOCKETPAIR +/** no socketpair() available, like on Minix 3.1.7, use pipe */ +#define socketpair(f, t, p, sv) pipe(sv) +#endif /* HAVE_SOCKETPAIR */ + +struct tube* tube_create(void) +{ + struct tube* tube = (struct tube*)calloc(1, sizeof(*tube)); + int sv[2]; + if(!tube) { + int err = errno; + log_err("tube_create: out of memory"); + errno = err; + return NULL; + } + tube->sr = -1; + tube->sw = -1; + if(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1) { + int err = errno; + log_err("socketpair: %s", strerror(errno)); + free(tube); + errno = err; + return NULL; + } + tube->sr = sv[0]; + tube->sw = sv[1]; + if(!fd_set_nonblock(tube->sr) || !fd_set_nonblock(tube->sw)) { + int err = errno; + log_err("tube: cannot set nonblocking"); + tube_delete(tube); + errno = err; + return NULL; + } + return tube; +} + +void tube_delete(struct tube* tube) +{ + if(!tube) return; + tube_remove_bg_listen(tube); + tube_remove_bg_write(tube); + /* close fds after deleting commpoints, to be sure. + * Also epoll does not like closing fd before event_del */ + tube_close_read(tube); + tube_close_write(tube); + free(tube); +} + +void tube_close_read(struct tube* tube) +{ + if(tube->sr != -1) { + close(tube->sr); + tube->sr = -1; + } +} + +void tube_close_write(struct tube* tube) +{ + if(tube->sw != -1) { + close(tube->sw); + tube->sw = -1; + } +} + +void tube_remove_bg_listen(struct tube* tube) +{ + if(tube->listen_com) { + comm_point_delete(tube->listen_com); + tube->listen_com = NULL; + } + if(tube->cmd_msg) { + free(tube->cmd_msg); + tube->cmd_msg = NULL; + } +} + +void tube_remove_bg_write(struct tube* tube) +{ + if(tube->res_com) { + comm_point_delete(tube->res_com); + tube->res_com = NULL; + } + if(tube->res_list) { + struct tube_res_list* np, *p = tube->res_list; + tube->res_list = NULL; + tube->res_last = NULL; + while(p) { + np = p->next; + free(p->buf); + free(p); + p = np; + } + } +} + +int +tube_handle_listen(struct comm_point* c, void* arg, int error, + struct comm_reply* ATTR_UNUSED(reply_info)) +{ + struct tube* tube = (struct tube*)arg; + ssize_t r; + if(error != NETEVENT_NOERROR) { + fptr_ok(fptr_whitelist_tube_listen(tube->listen_cb)); + (*tube->listen_cb)(tube, NULL, 0, error, tube->listen_arg); + return 0; + } + + if(tube->cmd_read < sizeof(tube->cmd_len)) { + /* complete reading the length of control msg */ + r = read(c->fd, ((uint8_t*)&tube->cmd_len) + tube->cmd_read, + sizeof(tube->cmd_len) - tube->cmd_read); + if(r==0) { + /* error has happened or */ + /* parent closed pipe, must have exited somehow */ + fptr_ok(fptr_whitelist_tube_listen(tube->listen_cb)); + (*tube->listen_cb)(tube, NULL, 0, NETEVENT_CLOSED, + tube->listen_arg); + return 0; + } + if(r==-1) { + if(errno != EAGAIN && errno != EINTR) { + log_err("rpipe error: %s", strerror(errno)); + } + /* nothing to read now, try later */ + return 0; + } + tube->cmd_read += r; + if(tube->cmd_read < sizeof(tube->cmd_len)) { + /* not complete, try later */ + return 0; + } + tube->cmd_msg = (uint8_t*)calloc(1, tube->cmd_len); + if(!tube->cmd_msg) { + log_err("malloc failure"); + tube->cmd_read = 0; + return 0; + } + } + /* cmd_len has been read, read remainder */ + r = read(c->fd, tube->cmd_msg+tube->cmd_read-sizeof(tube->cmd_len), + tube->cmd_len - (tube->cmd_read - sizeof(tube->cmd_len))); + if(r==0) { + /* error has happened or */ + /* parent closed pipe, must have exited somehow */ + fptr_ok(fptr_whitelist_tube_listen(tube->listen_cb)); + (*tube->listen_cb)(tube, NULL, 0, NETEVENT_CLOSED, + tube->listen_arg); + return 0; + } + if(r==-1) { + /* nothing to read now, try later */ + if(errno != EAGAIN && errno != EINTR) { + log_err("rpipe error: %s", strerror(errno)); + } + return 0; + } + tube->cmd_read += r; + if(tube->cmd_read < sizeof(tube->cmd_len) + tube->cmd_len) { + /* not complete, try later */ + return 0; + } + tube->cmd_read = 0; + + fptr_ok(fptr_whitelist_tube_listen(tube->listen_cb)); + (*tube->listen_cb)(tube, tube->cmd_msg, tube->cmd_len, + NETEVENT_NOERROR, tube->listen_arg); + /* also frees the buf */ + tube->cmd_msg = NULL; + return 0; +} + +int +tube_handle_write(struct comm_point* c, void* arg, int error, + struct comm_reply* ATTR_UNUSED(reply_info)) +{ + struct tube* tube = (struct tube*)arg; + struct tube_res_list* item = tube->res_list; + ssize_t r; + if(error != NETEVENT_NOERROR) { + log_err("tube_handle_write net error %d", error); + return 0; + } + + if(!item) { + comm_point_stop_listening(c); + return 0; + } + + if(tube->res_write < sizeof(item->len)) { + r = write(c->fd, ((uint8_t*)&item->len) + tube->res_write, + sizeof(item->len) - tube->res_write); + if(r == -1) { + if(errno != EAGAIN && errno != EINTR) { + log_err("wpipe error: %s", strerror(errno)); + } + return 0; /* try again later */ + } + if(r == 0) { + /* error on pipe, must have exited somehow */ + /* cannot signal this to pipe user */ + return 0; + } + tube->res_write += r; + if(tube->res_write < sizeof(item->len)) + return 0; + } + r = write(c->fd, item->buf + tube->res_write - sizeof(item->len), + item->len - (tube->res_write - sizeof(item->len))); + if(r == -1) { + if(errno != EAGAIN && errno != EINTR) { + log_err("wpipe error: %s", strerror(errno)); + } + return 0; /* try again later */ + } + if(r == 0) { + /* error on pipe, must have exited somehow */ + /* cannot signal this to pipe user */ + return 0; + } + tube->res_write += r; + if(tube->res_write < sizeof(item->len) + item->len) + return 0; + /* done this result, remove it */ + free(item->buf); + item->buf = NULL; + tube->res_list = tube->res_list->next; + free(item); + if(!tube->res_list) { + tube->res_last = NULL; + comm_point_stop_listening(c); + } + tube->res_write = 0; + return 0; +} + +int tube_write_msg(struct tube* tube, uint8_t* buf, uint32_t len, + int nonblock) +{ + ssize_t r, d; + int fd = tube->sw; + + /* test */ + if(nonblock) { + r = write(fd, &len, sizeof(len)); + if(r == -1) { + if(errno==EINTR || errno==EAGAIN) + return -1; + log_err("tube msg write failed: %s", strerror(errno)); + return -1; /* can still continue, perhaps */ + } + } else r = 0; + if(!fd_set_block(fd)) + return 0; + /* write remainder */ + d = r; + while(d != (ssize_t)sizeof(len)) { + if((r=write(fd, ((char*)&len)+d, sizeof(len)-d)) == -1) { + log_err("tube msg write failed: %s", strerror(errno)); + (void)fd_set_nonblock(fd); + return 0; + } + d += r; + } + d = 0; + while(d != (ssize_t)len) { + if((r=write(fd, buf+d, len-d)) == -1) { + log_err("tube msg write failed: %s", strerror(errno)); + (void)fd_set_nonblock(fd); + return 0; + } + d += r; + } + if(!fd_set_nonblock(fd)) + return 0; + return 1; +} + +int tube_read_msg(struct tube* tube, uint8_t** buf, uint32_t* len, + int nonblock) +{ + ssize_t r, d; + int fd = tube->sr; + + /* test */ + *len = 0; + if(nonblock) { + r = read(fd, len, sizeof(*len)); + if(r == -1) { + if(errno==EINTR || errno==EAGAIN) + return -1; + log_err("tube msg read failed: %s", strerror(errno)); + return -1; /* we can still continue, perhaps */ + } + if(r == 0) /* EOF */ + return 0; + } else r = 0; + if(!fd_set_block(fd)) + return 0; + /* read remainder */ + d = r; + while(d != (ssize_t)sizeof(*len)) { + if((r=read(fd, ((char*)len)+d, sizeof(*len)-d)) == -1) { + log_err("tube msg read failed: %s", strerror(errno)); + (void)fd_set_nonblock(fd); + return 0; + } + if(r == 0) /* EOF */ { + (void)fd_set_nonblock(fd); + return 0; + } + d += r; + } + *buf = (uint8_t*)malloc(*len); + if(!*buf) { + log_err("tube read out of memory"); + (void)fd_set_nonblock(fd); + return 0; + } + d = 0; + while(d != (ssize_t)*len) { + if((r=read(fd, (*buf)+d, (size_t)((ssize_t)*len)-d)) == -1) { + log_err("tube msg read failed: %s", strerror(errno)); + (void)fd_set_nonblock(fd); + free(*buf); + return 0; + } + if(r == 0) { /* EOF */ + (void)fd_set_nonblock(fd); + free(*buf); + return 0; + } + d += r; + } + if(!fd_set_nonblock(fd)) { + free(*buf); + return 0; + } + return 1; +} + +/** perform a select() on the fd */ +static int +pollit(int fd, struct timeval* t) +{ + fd_set r; +#ifndef S_SPLINT_S + FD_ZERO(&r); + FD_SET(FD_SET_T fd, &r); +#endif + if(select(fd+1, &r, NULL, NULL, t) == -1) { + return 0; + } + errno = 0; + return (int)(FD_ISSET(fd, &r)); +} + +int tube_poll(struct tube* tube) +{ + struct timeval t; + memset(&t, 0, sizeof(t)); + return pollit(tube->sr, &t); +} + +int tube_wait(struct tube* tube) +{ + return pollit(tube->sr, NULL); +} + +int tube_read_fd(struct tube* tube) +{ + return tube->sr; +} + +int tube_setup_bg_listen(struct tube* tube, struct comm_base* base, + tube_callback_t* cb, void* arg) +{ + tube->listen_cb = cb; + tube->listen_arg = arg; + if(!(tube->listen_com = comm_point_create_raw(base, tube->sr, + 0, tube_handle_listen, tube))) { + int err = errno; + log_err("tube_setup_bg_l: commpoint creation failed"); + errno = err; + return 0; + } + return 1; +} + +int tube_setup_bg_write(struct tube* tube, struct comm_base* base) +{ + if(!(tube->res_com = comm_point_create_raw(base, tube->sw, + 1, tube_handle_write, tube))) { + int err = errno; + log_err("tube_setup_bg_w: commpoint creation failed"); + errno = err; + return 0; + } + return 1; +} + +int tube_queue_item(struct tube* tube, uint8_t* msg, size_t len) +{ + struct tube_res_list* item = + (struct tube_res_list*)malloc(sizeof(*item)); + if(!item) { + free(msg); + log_err("out of memory for async answer"); + return 0; + } + item->buf = msg; + item->len = len; + item->next = NULL; + /* add at back of list, since the first one may be partially written */ + if(tube->res_last) + tube->res_last->next = item; + else tube->res_list = item; + tube->res_last = item; + if(tube->res_list == tube->res_last) { + /* first added item, start the write process */ + comm_point_start_listening(tube->res_com, -1, -1); + } + return 1; +} + +void tube_handle_signal(int ATTR_UNUSED(fd), short ATTR_UNUSED(events), + void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + +#else /* USE_WINSOCK */ +/* on windows */ + + +struct tube* tube_create(void) +{ + /* windows does not have forks like unix, so we only support + * threads on windows. And thus the pipe need only connect + * threads. We use a mutex and a list of datagrams. */ + struct tube* tube = (struct tube*)calloc(1, sizeof(*tube)); + if(!tube) { + int err = errno; + log_err("tube_create: out of memory"); + errno = err; + return NULL; + } + tube->event = WSACreateEvent(); + if(tube->event == WSA_INVALID_EVENT) { + free(tube); + log_err("WSACreateEvent: %s", wsa_strerror(WSAGetLastError())); + } + if(!WSAResetEvent(tube->event)) { + log_err("WSAResetEvent: %s", wsa_strerror(WSAGetLastError())); + } + lock_basic_init(&tube->res_lock); + verbose(VERB_ALGO, "tube created"); + return tube; +} + +void tube_delete(struct tube* tube) +{ + if(!tube) return; + tube_remove_bg_listen(tube); + tube_remove_bg_write(tube); + tube_close_read(tube); + tube_close_write(tube); + if(!WSACloseEvent(tube->event)) + log_err("WSACloseEvent: %s", wsa_strerror(WSAGetLastError())); + lock_basic_destroy(&tube->res_lock); + verbose(VERB_ALGO, "tube deleted"); + free(tube); +} + +void tube_close_read(struct tube* ATTR_UNUSED(tube)) +{ + verbose(VERB_ALGO, "tube close_read"); +} + +void tube_close_write(struct tube* ATTR_UNUSED(tube)) +{ + verbose(VERB_ALGO, "tube close_write"); + /* wake up waiting reader with an empty queue */ + if(!WSASetEvent(tube->event)) { + log_err("WSASetEvent: %s", wsa_strerror(WSAGetLastError())); + } +} + +void tube_remove_bg_listen(struct tube* tube) +{ + verbose(VERB_ALGO, "tube remove_bg_listen"); + winsock_unregister_wsaevent(&tube->ev_listen); +} + +void tube_remove_bg_write(struct tube* tube) +{ + verbose(VERB_ALGO, "tube remove_bg_write"); + if(tube->res_list) { + struct tube_res_list* np, *p = tube->res_list; + tube->res_list = NULL; + tube->res_last = NULL; + while(p) { + np = p->next; + free(p->buf); + free(p); + p = np; + } + } +} + +int tube_write_msg(struct tube* tube, uint8_t* buf, uint32_t len, + int ATTR_UNUSED(nonblock)) +{ + uint8_t* a; + verbose(VERB_ALGO, "tube write_msg len %d", (int)len); + a = (uint8_t*)memdup(buf, len); + if(!a) { + log_err("out of memory in tube_write_msg"); + return 0; + } + /* always nonblocking, this pipe cannot get full */ + return tube_queue_item(tube, a, len); +} + +int tube_read_msg(struct tube* tube, uint8_t** buf, uint32_t* len, + int nonblock) +{ + struct tube_res_list* item = NULL; + verbose(VERB_ALGO, "tube read_msg %s", nonblock?"nonblock":"blocking"); + *buf = NULL; + if(!tube_poll(tube)) { + verbose(VERB_ALGO, "tube read_msg nodata"); + /* nothing ready right now, wait if we want to */ + if(nonblock) + return -1; /* would block waiting for items */ + if(!tube_wait(tube)) + return 0; + } + lock_basic_lock(&tube->res_lock); + if(tube->res_list) { + item = tube->res_list; + tube->res_list = item->next; + if(tube->res_last == item) { + /* the list is now empty */ + tube->res_last = NULL; + verbose(VERB_ALGO, "tube read_msg lastdata"); + if(!WSAResetEvent(tube->event)) { + log_err("WSAResetEvent: %s", + wsa_strerror(WSAGetLastError())); + } + } + } + lock_basic_unlock(&tube->res_lock); + if(!item) + return 0; /* would block waiting for items */ + *buf = item->buf; + *len = item->len; + free(item); + verbose(VERB_ALGO, "tube read_msg len %d", (int)*len); + return 1; +} + +int tube_poll(struct tube* tube) +{ + struct tube_res_list* item = NULL; + lock_basic_lock(&tube->res_lock); + item = tube->res_list; + lock_basic_unlock(&tube->res_lock); + if(item) + return 1; + return 0; +} + +int tube_wait(struct tube* tube) +{ + /* block on eventhandle */ + DWORD res = WSAWaitForMultipleEvents( + 1 /* one event in array */, + &tube->event /* the event to wait for, our pipe signal */, + 0 /* wait for all events is false */, + WSA_INFINITE /* wait, no timeout */, + 0 /* we are not alertable for IO completion routines */ + ); + if(res == WSA_WAIT_TIMEOUT) { + return 0; + } + if(res == WSA_WAIT_IO_COMPLETION) { + /* a bit unexpected, since we were not alertable */ + return 0; + } + return 1; +} + +int tube_read_fd(struct tube* ATTR_UNUSED(tube)) +{ + /* nothing sensible on Windows */ + return -1; +} + +int +tube_handle_listen(struct comm_point* ATTR_UNUSED(c), void* ATTR_UNUSED(arg), + int ATTR_UNUSED(error), struct comm_reply* ATTR_UNUSED(reply_info)) +{ + log_assert(0); + return 0; +} + +int +tube_handle_write(struct comm_point* ATTR_UNUSED(c), void* ATTR_UNUSED(arg), + int ATTR_UNUSED(error), struct comm_reply* ATTR_UNUSED(reply_info)) +{ + log_assert(0); + return 0; +} + +int tube_setup_bg_listen(struct tube* tube, struct comm_base* base, + tube_callback_t* cb, void* arg) +{ + tube->listen_cb = cb; + 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); +} + +int tube_setup_bg_write(struct tube* ATTR_UNUSED(tube), + struct comm_base* ATTR_UNUSED(base)) +{ + /* the queue item routine performs the signaling */ + return 1; +} + +int tube_queue_item(struct tube* tube, uint8_t* msg, size_t len) +{ + struct tube_res_list* item = + (struct tube_res_list*)malloc(sizeof(*item)); + verbose(VERB_ALGO, "tube queue_item len %d", (int)len); + if(!item) { + free(msg); + log_err("out of memory for async answer"); + return 0; + } + item->buf = msg; + item->len = len; + item->next = NULL; + lock_basic_lock(&tube->res_lock); + /* add at back of list, since the first one may be partially written */ + if(tube->res_last) + tube->res_last->next = item; + else tube->res_list = item; + tube->res_last = item; + /* signal the eventhandle */ + if(!WSASetEvent(tube->event)) { + log_err("WSASetEvent: %s", wsa_strerror(WSAGetLastError())); + } + lock_basic_unlock(&tube->res_lock); + return 1; +} + +void tube_handle_signal(int ATTR_UNUSED(fd), short ATTR_UNUSED(events), + void* arg) +{ + struct tube* tube = (struct tube*)arg; + uint8_t* buf; + uint32_t len = 0; + verbose(VERB_ALGO, "tube handle_signal"); + while(tube_poll(tube)) { + if(tube_read_msg(tube, &buf, &len, 1)) { + fptr_ok(fptr_whitelist_tube_listen(tube->listen_cb)); + (*tube->listen_cb)(tube, buf, len, NETEVENT_NOERROR, + tube->listen_arg); + } + } +} + +#endif /* USE_WINSOCK */ diff --git a/util/tube.h b/util/tube.h new file mode 100644 index 00000000000..2e704115637 --- /dev/null +++ b/util/tube.h @@ -0,0 +1,273 @@ +/* + * util/tube.h - pipe service + * + * Copyright (c) 2008, 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains pipe service functions. + */ + +#ifndef UTIL_TUBE_H +#define UTIL_TUBE_H +struct comm_reply; +struct comm_point; +struct comm_base; +struct tube; +struct tube_res_list; +#ifdef USE_WINSOCK +#include "util/locks.h" +#include "util/winsock_event.h" +#endif + +/** + * Callback from pipe listen function + * void mycallback(tube, msg, len, error, user_argument); + * if error is true (NETEVENT_*), msg is probably NULL. + */ +typedef void tube_callback_t(struct tube*, uint8_t*, size_t, int, void*); + +/** + * A pipe + */ +struct tube { +#ifndef USE_WINSOCK + /** pipe end to read from */ + int sr; + /** pipe end to write on */ + int sw; + + /** listen commpoint */ + struct comm_point* listen_com; + /** listen callback */ + tube_callback_t* listen_cb; + /** listen callback user arg */ + void* listen_arg; + /** are we currently reading a command, 0 if not, else bytecount */ + size_t cmd_read; + /** size of current read command, may be partially read */ + uint32_t cmd_len; + /** the current read command content, malloced, can be partially read*/ + uint8_t* cmd_msg; + + /** background write queue, commpoint to write results back */ + struct comm_point* res_com; + /** are we curently writing a result, 0 if not, else bytecount into + * the res_list first entry. */ + size_t res_write; + /** list of outstanding results to be written back */ + struct tube_res_list* res_list; + /** last in list */ + struct tube_res_list* res_last; + +#else /* USE_WINSOCK */ + /** listen callback */ + tube_callback_t* listen_cb; + /** listen callback user arg */ + void* listen_arg; + /** the windows sockets event (signaled if items in pipe) */ + WSAEVENT event; + /** winsock event storage when registered with event base */ + struct event ev_listen; + + /** lock on the list of outstanding items */ + lock_basic_t res_lock; + /** list of outstanding results on pipe */ + struct tube_res_list* res_list; + /** last in list */ + struct tube_res_list* res_last; +#endif /* USE_WINSOCK */ +}; + +/** + * List of results (arbitrary command serializations) to write back + */ +struct tube_res_list { + /** next in list */ + struct tube_res_list* next; + /** serialized buffer to write */ + uint8_t* buf; + /** length to write */ + uint32_t len; +}; + +/** + * Create a pipe + * @return: new tube struct or NULL on error. + */ +struct tube* tube_create(void); + +/** + * Delete and destroy a pipe + * @param tube: to delete + */ +void tube_delete(struct tube* tube); + +/** + * Write length bytes followed by message. + * @param tube: the tube to write on. + * If that tube is a pipe, its write fd is used as + * the socket to write on. Is nonblocking. + * Set to blocking by the function, + * and back to non-blocking at exit of function. + * @param buf: the message. + * @param len: length of message. + * @param nonblock: if set to true, the first write is nonblocking. + * If the first write fails the function returns -1. + * If set false, the first write is blocking. + * @return: all remainder writes are nonblocking. + * return 0 on error, in that case blocking/nonblocking of socket is + * unknown. + * return 1 if all OK. + */ +int tube_write_msg(struct tube* tube, uint8_t* buf, uint32_t len, + int nonblock); + +/** + * Read length bytes followed by message. + * @param tube: The tube to read on. + * If that tube is a pipe, its read fd is used as + * the socket to read on. Is nonblocking. + * Set to blocking by the function, + * and back to non-blocking at exit of function. + * @param buf: the message, malloced. + * @param len: length of message, returned. + * @param nonblock: if set to true, the first read is nonblocking. + * If the first read fails the function returns -1. + * If set false, the first read is blocking. + * @return: all remainder reads are nonblocking. + * return 0 on error, in that case blocking/nonblocking of socket is + * unknown. On EOF 0 is returned. + * return 1 if all OK. + */ +int tube_read_msg(struct tube* tube, uint8_t** buf, uint32_t* len, + int nonblock); + +/** + * Close read part of the pipe. + * The tube can no longer be read from. + * @param tube: tube to operate on. + */ +void tube_close_read(struct tube* tube); + +/** + * Close write part of the pipe. + * The tube can no longer be written to. + * @param tube: tube to operate on. + */ +void tube_close_write(struct tube* tube); + +/** + * See if data is ready for reading on the tube without blocking. + * @param tube: tube to check for readable items + * @return true if readable items are present. False if not (or error). + * true on pipe_closed. + */ +int tube_poll(struct tube* tube); + +/** + * Wait for data to be ready for reading on the tube. is blocking. + * No timeout. + * @param tube: the tube to wait on. + * @return: if there was something to read (false on error). + * true on pipe_closed. + */ +int tube_wait(struct tube* tube); + +/** + * Get FD that is readable when new information arrives. + * @param tube + * @return file descriptor. + */ +int tube_read_fd(struct tube* tube); + +/** + * Start listening for information over the pipe. + * Background registration of a read listener, callback when read completed. + * Do not mix with tube_read_msg style direct reads from the pipe. + * @param tube: tube to listen on + * @param base: what base to register event callback. + * @param cb: callback routine. + * @param arg: user argument for callback routine. + * @return true if successful, false on error. + */ +int tube_setup_bg_listen(struct tube* tube, struct comm_base* base, + tube_callback_t* cb, void* arg); + +/** + * Remove bg listen setup from event base. + * @param tube: what tube to cleanup + */ +void tube_remove_bg_listen(struct tube* tube); + +/** + * Start background write handler for the pipe. + * Do not mix with tube_write_msg style direct writes to the pipe. + * @param tube: tube to write on + * @param base: what base to register event handler on. + * @return true if successful, false on error. + */ +int tube_setup_bg_write(struct tube* tube, struct comm_base* base); + +/** + * Remove bg write setup from event base. + * @param tube: what tube to cleanup + */ +void tube_remove_bg_write(struct tube* tube); + + +/** + * Append data item to background list of writes. + * Mallocs a list entry behind the scenes. + * Not locked behind the scenes, call from one thread or lock on outside. + * @param tube: what tube to queue on. + * @param msg: memory message to send. Is free()d after use. + * Put at the end of the to-send queue. + * @param len: length of item. + * @return 0 on failure (msg freed). + */ +int tube_queue_item(struct tube* tube, uint8_t* msg, size_t len); + +/** for fptr wlist, callback function */ +int tube_handle_listen(struct comm_point* c, void* arg, int error, + struct comm_reply* reply_info); + +/** for fptr wlist, callback function */ +int tube_handle_write(struct comm_point* c, void* arg, int error, + struct comm_reply* reply_info); + +/** for fptr wlist, winsock signal event callback function */ +void tube_handle_signal(int fd, short events, void* arg); + +#endif /* UTIL_TUBE_H */ diff --git a/util/winsock_event.c b/util/winsock_event.c new file mode 100644 index 00000000000..ff5c9b0939d --- /dev/null +++ b/util/winsock_event.c @@ -0,0 +1,692 @@ +/* + * util/winsock_event.c - implementation of the unbound winsock event handler. + * + * Copyright (c) 2008, 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \file + * Implementation of the unbound WinSock2 API event notification handler + * for the Windows port. + */ + +#include "config.h" +#ifdef USE_WINSOCK +#include +#include "util/winsock_event.h" +#include "util/fptr_wlist.h" + +int mini_ev_cmp(const void* a, const void* b) +{ + const struct event *e = (const struct event*)a; + const struct event *f = (const struct event*)b; + if(e->ev_timeout.tv_sec < f->ev_timeout.tv_sec) + return -1; + if(e->ev_timeout.tv_sec > f->ev_timeout.tv_sec) + return 1; + if(e->ev_timeout.tv_usec < f->ev_timeout.tv_usec) + return -1; + if(e->ev_timeout.tv_usec > f->ev_timeout.tv_usec) + return 1; + if(e < f) + return -1; + if(e > f) + return 1; + return 0; +} + +/** set time */ +static int +settime(struct event_base* base) +{ + if(gettimeofday(base->time_tv, NULL) < 0) { + return -1; + } +#ifndef S_SPLINT_S + *base->time_secs = (uint32_t)base->time_tv->tv_sec; +#endif + return 0; +} + +#ifdef UNBOUND_DEBUG +/** + * Find a fd in the list of items. + * Note that not all items have a fd associated (those are -1). + * Signals are stored separately, and not searched. + * @param base: event base to look in. + * @param fd: what socket to look for. + * @return the index in the array, or -1 on failure. + */ +static int +find_fd(struct event_base* base, int fd) +{ + int i; + for(i=0; imax; i++) { + if(base->items[i]->ev_fd == fd) + return i; + } + return -1; +} +#endif + +/** Find ptr in base array */ +static void +zero_waitfor(WSAEVENT waitfor[], WSAEVENT x) +{ + int i; + for(i=0; itime_secs = time_secs; + base->time_tv = time_tv; + if(settime(base) < 0) { + event_base_free(base); + return NULL; + } + base->items = (struct event**)calloc(WSK_MAX_ITEMS, + sizeof(struct event*)); + if(!base->items) { + event_base_free(base); + return NULL; + } + base->cap = WSK_MAX_ITEMS; + base->max = 0; + base->times = rbtree_create(mini_ev_cmp); + if(!base->times) { + event_base_free(base); + return NULL; + } + base->signals = (struct event**)calloc(MAX_SIG, sizeof(struct event*)); + if(!base->signals) { + event_base_free(base); + return NULL; + } + base->tcp_stickies = 0; + base->tcp_reinvigorated = 0; + verbose(VERB_CLIENT, "winsock_event inited"); + return base; +} + +const char *event_get_version(void) +{ + return "winsock-event-"PACKAGE_VERSION; +} + +const char *event_get_method(void) +{ + return "WSAWaitForMultipleEvents"; +} + +/** call timeouts handlers, and return how long to wait for next one or -1 */ +static void handle_timeouts(struct event_base* base, struct timeval* now, + struct timeval* wait) +{ + struct event* p; +#ifndef S_SPLINT_S + wait->tv_sec = (time_t)-1; +#endif + verbose(VERB_CLIENT, "winsock_event handle_timeouts"); + + while((rbnode_t*)(p = (struct event*)rbtree_first(base->times)) + !=RBTREE_NULL) { +#ifndef S_SPLINT_S + if(p->ev_timeout.tv_sec > now->tv_sec || + (p->ev_timeout.tv_sec==now->tv_sec && + p->ev_timeout.tv_usec > now->tv_usec)) { + /* there is a next larger timeout. wait for it */ + wait->tv_sec = p->ev_timeout.tv_sec - now->tv_sec; + if(now->tv_usec > p->ev_timeout.tv_usec) { + wait->tv_sec--; + wait->tv_usec = 1000000 - (now->tv_usec - + p->ev_timeout.tv_usec); + } else { + wait->tv_usec = p->ev_timeout.tv_usec + - now->tv_usec; + } + verbose(VERB_CLIENT, "winsock_event wait=%d.%6.6d", + (int)wait->tv_sec, (int)wait->tv_usec); + return; + } +#endif + /* event times out, remove it */ + (void)rbtree_delete(base->times, p); + p->ev_events &= ~EV_TIMEOUT; + fptr_ok(fptr_whitelist_event(p->ev_callback)); + (*p->ev_callback)(p->ev_fd, EV_TIMEOUT, p->ev_arg); + } + verbose(VERB_CLIENT, "winsock_event wait=(-1)"); +} + +/** handle is_signal events and see if signalled */ +static void handle_signal(struct event* ev) +{ + DWORD ret; + log_assert(ev->is_signal && ev->hEvent); + /* see if the event is signalled */ + ret = WSAWaitForMultipleEvents(1, &ev->hEvent, 0 /* any object */, + 0 /* return immediately */, 0 /* not alertable for IOcomple*/); + if(ret == WSA_WAIT_IO_COMPLETION || ret == WSA_WAIT_FAILED) { + log_err("WSAWaitForMultipleEvents(signal) failed: %s", + wsa_strerror(WSAGetLastError())); + return; + } + if(ret == WSA_WAIT_TIMEOUT) { + /* not signalled */ + return; + } + + /* reset the signal */ + if(!WSAResetEvent(ev->hEvent)) + log_err("WSAResetEvent failed: %s", + wsa_strerror(WSAGetLastError())); + /* do the callback (which may set the signal again) */ + fptr_ok(fptr_whitelist_event(ev->ev_callback)); + (*ev->ev_callback)(ev->ev_fd, ev->ev_events, ev->ev_arg); +} + +/** call select and callbacks for that */ +static int handle_select(struct event_base* base, struct timeval* wait) +{ + DWORD timeout = 0; /* in milliseconds */ + DWORD ret; + struct event* eventlist[WSK_MAX_ITEMS]; + WSANETWORKEVENTS netev; + int i, numwait = 0, startidx = 0, was_timeout = 0; + int newstickies = 0; + struct timeval nultm; + + verbose(VERB_CLIENT, "winsock_event handle_select"); + +#ifndef S_SPLINT_S + if(wait->tv_sec==(time_t)-1) + wait = NULL; + if(wait) + timeout = wait->tv_sec*1000 + wait->tv_usec/1000; + if(base->tcp_stickies) { + wait = &nultm; + nultm.tv_sec = 0; + nultm.tv_usec = 0; + timeout = 0; /* no waiting, we have sticky events */ + } +#endif + + /* prepare event array */ + for(i=0; imax; i++) { + if(base->items[i]->ev_fd == -1 && !base->items[i]->is_signal) + continue; /* skip timer only events */ + eventlist[numwait] = base->items[i]; + base->waitfor[numwait++] = base->items[i]->hEvent; + if(numwait == WSK_MAX_ITEMS) + 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); + + /* do the wait */ + if(numwait == 0) { + /* WSAWaitFor.. doesn't like 0 event objects */ + if(wait) { + Sleep(timeout); + } + was_timeout = 1; + } else { + ret = WSAWaitForMultipleEvents(numwait, base->waitfor, + 0 /* do not wait for all, just one will do */, + wait?timeout:WSA_INFINITE, + 0); /* we are not alertable (IO completion events) */ + if(ret == WSA_WAIT_IO_COMPLETION) { + log_err("WSAWaitForMultipleEvents failed: WSA_WAIT_IO_COMPLETION"); + return -1; + } else if(ret == WSA_WAIT_FAILED) { + log_err("WSAWaitForMultipleEvents failed: %s", + wsa_strerror(WSAGetLastError())); + return -1; + } else if(ret == WSA_WAIT_TIMEOUT) { + was_timeout = 1; + } else + startidx = ret - WSA_WAIT_EVENT_0; + } + verbose(VERB_CLIENT, "winsock_event wake was_timeout=%d startidx=%d", + was_timeout, startidx); + + /* get new time after wait */ + if(settime(base) < 0) + return -1; + + /* callbacks */ + if(base->tcp_stickies) + startidx = 0; /* process all events, some are sticky */ + for(i=startidx; ijust_checked = 1; + + verbose(VERB_CLIENT, "winsock_event signals"); + for(i=startidx; iwaitfor[i]) + continue; /* was deleted */ + if(eventlist[i]->is_signal) { + eventlist[i]->just_checked = 0; + handle_signal(eventlist[i]); + } + } + /* early exit - do not process network, exit quickly */ + if(base->need_to_exit) + return 0; + + verbose(VERB_CLIENT, "winsock_event net"); + for(i=startidx; iwaitfor[i]) + continue; /* was deleted */ + if(!eventlist[i]->just_checked) + continue; /* added by other callback */ + if(eventlist[i]->is_signal) + continue; /* not a network event at all */ + eventlist[i]->just_checked = 0; + + if(WSAEnumNetworkEvents(eventlist[i]->ev_fd, + base->waitfor[i], /* reset the event handle */ + /*NULL,*/ /* do not reset the event handle */ + &netev) != 0) { + log_err("WSAEnumNetworkEvents failed: %s", + wsa_strerror(WSAGetLastError())); + return -1; + } + if((netev.lNetworkEvents & FD_READ)) { + if(netev.iErrorCode[FD_READ_BIT] != 0) + verbose(VERB_ALGO, "FD_READ_BIT error: %s", + wsa_strerror(netev.iErrorCode[FD_READ_BIT])); + bits |= EV_READ; + } + if((netev.lNetworkEvents & FD_WRITE)) { + if(netev.iErrorCode[FD_WRITE_BIT] != 0) + verbose(VERB_ALGO, "FD_WRITE_BIT error: %s", + wsa_strerror(netev.iErrorCode[FD_WRITE_BIT])); + bits |= EV_WRITE; + } + if((netev.lNetworkEvents & FD_CONNECT)) { + if(netev.iErrorCode[FD_CONNECT_BIT] != 0) + verbose(VERB_ALGO, "FD_CONNECT_BIT error: %s", + wsa_strerror(netev.iErrorCode[FD_CONNECT_BIT])); + bits |= EV_READ; + bits |= EV_WRITE; + } + if((netev.lNetworkEvents & FD_ACCEPT)) { + if(netev.iErrorCode[FD_ACCEPT_BIT] != 0) + verbose(VERB_ALGO, "FD_ACCEPT_BIT error: %s", + wsa_strerror(netev.iErrorCode[FD_ACCEPT_BIT])); + bits |= EV_READ; + } + if((netev.lNetworkEvents & FD_CLOSE)) { + if(netev.iErrorCode[FD_CLOSE_BIT] != 0) + verbose(VERB_ALGO, "FD_CLOSE_BIT error: %s", + wsa_strerror(netev.iErrorCode[FD_CLOSE_BIT])); + bits |= EV_READ; + bits |= EV_WRITE; + } + if(eventlist[i]->is_tcp && eventlist[i]->stick_events) { + verbose(VERB_ALGO, "winsock %d pass sticky %s%s", + eventlist[i]->ev_fd, + (eventlist[i]->old_events&EV_READ)?"EV_READ":"", + (eventlist[i]->old_events&EV_WRITE)?"EV_WRITE":""); + bits |= eventlist[i]->old_events; + } + if(eventlist[i]->is_tcp && bits) { + eventlist[i]->old_events = bits; + eventlist[i]->stick_events = 1; + if((eventlist[i]->ev_events & bits)) { + newstickies = 1; + } + verbose(VERB_ALGO, "winsock %d store sticky %s%s", + eventlist[i]->ev_fd, + (eventlist[i]->old_events&EV_READ)?"EV_READ":"", + (eventlist[i]->old_events&EV_WRITE)?"EV_WRITE":""); + } + if((bits & eventlist[i]->ev_events)) { + verbose(VERB_ALGO, "winsock event callback %p fd=%d " + "%s%s%s%s%s ; %s%s%s", + eventlist[i], eventlist[i]->ev_fd, + (netev.lNetworkEvents&FD_READ)?" FD_READ":"", + (netev.lNetworkEvents&FD_WRITE)?" FD_WRITE":"", + (netev.lNetworkEvents&FD_CONNECT)? + " FD_CONNECT":"", + (netev.lNetworkEvents&FD_ACCEPT)? + " FD_ACCEPT":"", + (netev.lNetworkEvents&FD_CLOSE)?" FD_CLOSE":"", + (bits&EV_READ)?" EV_READ":"", + (bits&EV_WRITE)?" EV_WRITE":"", + (bits&EV_TIMEOUT)?" EV_TIMEOUT":""); + + fptr_ok(fptr_whitelist_event( + eventlist[i]->ev_callback)); + (*eventlist[i]->ev_callback)(eventlist[i]->ev_fd, + bits & eventlist[i]->ev_events, + eventlist[i]->ev_arg); + } + if(eventlist[i]->is_tcp && bits) + verbose(VERB_ALGO, "winsock %d got sticky %s%s", + eventlist[i]->ev_fd, + (eventlist[i]->old_events&EV_READ)?"EV_READ":"", + (eventlist[i]->old_events&EV_WRITE)?"EV_WRITE":""); + } + verbose(VERB_CLIENT, "winsock_event net"); + if(base->tcp_reinvigorated) { + verbose(VERB_CLIENT, "winsock_event reinvigorated"); + base->tcp_reinvigorated = 0; + newstickies = 1; + } + base->tcp_stickies = newstickies; + verbose(VERB_CLIENT, "winsock_event handle_select end"); + return 0; +} + +int event_base_dispatch(struct event_base *base) +{ + struct timeval wait; + if(settime(base) < 0) + return -1; + while(!base->need_to_exit) + { + /* see if timeouts need handling */ + handle_timeouts(base, base->time_tv, &wait); + if(base->need_to_exit) + return 0; + /* do select */ + if(handle_select(base, &wait) < 0) { + if(base->need_to_exit) + return 0; + return -1; + } + } + return 0; +} + +int event_base_loopexit(struct event_base *base, + struct timeval * ATTR_UNUSED(tv)) +{ + verbose(VERB_CLIENT, "winsock_event loopexit"); + base->need_to_exit = 1; + return 0; +} + +void event_base_free(struct event_base *base) +{ + verbose(VERB_CLIENT, "winsock_event event_base_free"); + if(!base) + return; + if(base->items) + free(base->items); + if(base->times) + free(base->times); + if(base->signals) + free(base->signals); + free(base); +} + +void event_set(struct event *ev, int fd, short bits, + void (*cb)(int, short, void *), void *arg) +{ + ev->node.key = ev; + ev->ev_fd = fd; + ev->ev_events = bits; + ev->ev_callback = cb; + fptr_ok(fptr_whitelist_event(ev->ev_callback)); + ev->ev_arg = arg; + ev->just_checked = 0; + ev->added = 0; +} + +int event_base_set(struct event_base *base, struct event *ev) +{ + ev->ev_base = base; + ev->old_events = 0; + ev->stick_events = 0; + ev->added = 0; + return 0; +} + +int event_add(struct event *ev, struct timeval *tv) +{ + verbose(VERB_ALGO, "event_add %p added=%d fd=%d tv=%d %s%s%s", + ev, ev->added, ev->ev_fd, + (tv?(int)tv->tv_sec*1000+(int)tv->tv_usec/1000:-1), + (ev->ev_events&EV_READ)?" EV_READ":"", + (ev->ev_events&EV_WRITE)?" EV_WRITE":"", + (ev->ev_events&EV_TIMEOUT)?" EV_TIMEOUT":""); + if(ev->added) + event_del(ev); + log_assert(ev->ev_fd==-1 || find_fd(ev->ev_base, ev->ev_fd) == -1); + ev->is_tcp = 0; + ev->is_signal = 0; + ev->just_checked = 0; + + if((ev->ev_events&(EV_READ|EV_WRITE)) && ev->ev_fd != -1) { + BOOL b=0; + int t, l; + long events = 0; + + if(ev->ev_base->max == ev->ev_base->cap) + return -1; + ev->idx = ev->ev_base->max++; + ev->ev_base->items[ev->idx] = ev; + + if( (ev->ev_events&EV_READ) ) + events |= FD_READ; + if( (ev->ev_events&EV_WRITE) ) + events |= FD_WRITE; + l = sizeof(t); + if(getsockopt(ev->ev_fd, SOL_SOCKET, SO_TYPE, + (void*)&t, &l) != 0) + log_err("getsockopt(SO_TYPE) failed: %s", + wsa_strerror(WSAGetLastError())); + if(t == SOCK_STREAM) { + /* TCP socket */ + ev->is_tcp = 1; + events |= FD_CLOSE; + if( (ev->ev_events&EV_WRITE) ) + events |= FD_CONNECT; + l = sizeof(b); + if(getsockopt(ev->ev_fd, SOL_SOCKET, SO_ACCEPTCONN, + (void*)&b, &l) != 0) + log_err("getsockopt(SO_ACCEPTCONN) failed: %s", + wsa_strerror(WSAGetLastError())); + if(b) /* TCP accept socket */ + events |= FD_ACCEPT; + } + ev->hEvent = WSACreateEvent(); + if(ev->hEvent == WSA_INVALID_EVENT) + log_err("WSACreateEvent failed: %s", + wsa_strerror(WSAGetLastError())); + /* automatically sets fd to nonblocking mode. + * nonblocking cannot be disabled, until wsaES(fd, NULL, 0) */ + if(WSAEventSelect(ev->ev_fd, ev->hEvent, events) != 0) { + log_err("WSAEventSelect failed: %s", + wsa_strerror(WSAGetLastError())); + } + if(ev->is_tcp && ev->stick_events && + (ev->ev_events & ev->old_events)) { + /* go to processing the sticky event right away */ + ev->ev_base->tcp_reinvigorated = 1; + } + } + + if(tv && (ev->ev_events&EV_TIMEOUT)) { +#ifndef S_SPLINT_S + struct timeval *now = ev->ev_base->time_tv; + ev->ev_timeout.tv_sec = tv->tv_sec + now->tv_sec; + ev->ev_timeout.tv_usec = tv->tv_usec + now->tv_usec; + while(ev->ev_timeout.tv_usec > 1000000) { + ev->ev_timeout.tv_usec -= 1000000; + ev->ev_timeout.tv_sec++; + } +#endif + (void)rbtree_insert(ev->ev_base->times, &ev->node); + } + ev->added = 1; + return 0; +} + +int event_del(struct event *ev) +{ + verbose(VERB_ALGO, "event_del %p added=%d fd=%d tv=%d %s%s%s", + ev, ev->added, ev->ev_fd, + (ev->ev_events&EV_TIMEOUT)?(int)ev->ev_timeout.tv_sec*1000+ + (int)ev->ev_timeout.tv_usec/1000:-1, + (ev->ev_events&EV_READ)?" EV_READ":"", + (ev->ev_events&EV_WRITE)?" EV_WRITE":"", + (ev->ev_events&EV_TIMEOUT)?" EV_TIMEOUT":""); + if(!ev->added) + return 0; + log_assert(ev->added); + if((ev->ev_events&EV_TIMEOUT)) + (void)rbtree_delete(ev->ev_base->times, &ev->node); + if((ev->ev_events&(EV_READ|EV_WRITE)) && ev->ev_fd != -1) { + log_assert(ev->ev_base->max > 0); + /* remove item and compact the list */ + ev->ev_base->items[ev->idx] = + ev->ev_base->items[ev->ev_base->max-1]; + ev->ev_base->items[ev->ev_base->max-1] = NULL; + ev->ev_base->max--; + if(ev->idx < ev->ev_base->max) + ev->ev_base->items[ev->idx]->idx = ev->idx; + zero_waitfor(ev->ev_base->waitfor, ev->hEvent); + + if(WSAEventSelect(ev->ev_fd, ev->hEvent, 0) != 0) + log_err("WSAEventSelect(disable) failed: %s", + wsa_strerror(WSAGetLastError())); + if(!WSACloseEvent(ev->hEvent)) + log_err("WSACloseEvent failed: %s", + wsa_strerror(WSAGetLastError())); + } + ev->just_checked = 0; + ev->added = 0; + return 0; +} + +/** which base gets to handle signals */ +static struct event_base* signal_base = NULL; +/** signal handler */ +static RETSIGTYPE sigh(int sig) +{ + struct event* ev; + if(!signal_base || sig < 0 || sig >= MAX_SIG) + return; + ev = signal_base->signals[sig]; + if(!ev) + return; + fptr_ok(fptr_whitelist_event(ev->ev_callback)); + (*ev->ev_callback)(sig, EV_SIGNAL, ev->ev_arg); +} + +int signal_add(struct event *ev, struct timeval * ATTR_UNUSED(tv)) +{ + if(ev->ev_fd == -1 || ev->ev_fd >= MAX_SIG) + return -1; + signal_base = ev->ev_base; + ev->ev_base->signals[ev->ev_fd] = ev; + ev->added = 1; + if(signal(ev->ev_fd, sigh) == SIG_ERR) { + return -1; + } + return 0; +} + +int signal_del(struct event *ev) +{ + if(ev->ev_fd == -1 || ev->ev_fd >= MAX_SIG) + return -1; + ev->ev_base->signals[ev->ev_fd] = NULL; + ev->added = 0; + return 0; +} + +void winsock_tcp_wouldblock(struct event* ev, int eventbits) +{ + verbose(VERB_ALGO, "winsock: tcp wouldblock %s", + eventbits==EV_READ?"EV_READ":"EV_WRITE"); + ev->old_events &= (~eventbits); + if(ev->old_events == 0) + ev->stick_events = 0; + /* in case this is the last sticky event, we could + * possibly run an empty handler loop to reset the base + * tcp_stickies variable + */ +} + +int winsock_register_wsaevent(struct event_base* base, struct event* ev, + WSAEVENT wsaevent, void (*cb)(int, short, void*), void* arg) +{ + if(base->max == base->cap) + return 0; + memset(ev, 0, sizeof(*ev)); + ev->ev_fd = -1; + ev->ev_events = EV_READ; + ev->ev_callback = cb; + ev->ev_arg = arg; + ev->is_signal = 1; + ev->hEvent = wsaevent; + ev->added = 1; + ev->ev_base = base; + ev->idx = ev->ev_base->max++; + ev->ev_base->items[ev->idx] = ev; + return 1; +} + +void winsock_unregister_wsaevent(struct event* ev) +{ + if(!ev || !ev->added) return; + log_assert(ev->added && ev->ev_base->max > 0) + /* remove item and compact the list */ + ev->ev_base->items[ev->idx] = ev->ev_base->items[ev->ev_base->max-1]; + ev->ev_base->items[ev->ev_base->max-1] = NULL; + ev->ev_base->max--; + if(ev->idx < ev->ev_base->max) + ev->ev_base->items[ev->idx]->idx = ev->idx; + ev->added = 0; +} + +#else /* USE_WINSOCK */ +/** symbol so this codefile defines symbols. pleasing ranlib on OSX 10.5 */ +int winsock_unused_symbol = 1; +#endif /* USE_WINSOCK */ diff --git a/util/winsock_event.h b/util/winsock_event.h new file mode 100644 index 00000000000..088283e128a --- /dev/null +++ b/util/winsock_event.h @@ -0,0 +1,264 @@ +/* + * util/winsock_event.h - unbound event handling for winsock on windows + * + * Copyright (c) 2008, 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains interface functions with the WinSock2 API on Windows. + * It uses the winsock WSAWaitForMultipleEvents interface on a number of + * sockets. + * + * Note that windows can only wait for max 64 events at one time. + * + * Also, file descriptors cannot be waited for. + * + * Named pipes are not easily available (and are not usable in select() ). + * For interprocess communication, it is possible to wait for a hEvent to + * be signaled by another thread. + * + * When a socket becomes readable, then it will not be flagged as + * readable again until you have gotten WOULDBLOCK from a recv routine. + * That means the event handler must store the readability (edge notify) + * and process the incoming data until it blocks. + * The function performing recv then has to inform the event handler that + * the socket has blocked, and the event handler can mark it as such. + * Thus, this file transforms the edge notify from windows to a level notify + * that is compatible with UNIX. + * The WSAEventSelect page says that it does do level notify, as long + * as you call a recv/write/accept at least once when it is signalled. + * This last bit is not true, even though documented in server2008 api docs + * from microsoft, it does not happen at all. Instead you have to test for + * WSAEWOULDBLOCK on a tcp stream, and only then retest the socket. + * And before that remember the previous result as still valid. + * + * To stay 'fair', instead of emptying a socket completely, the event handler + * can test the other (marked as blocking) sockets for new events. + * + * Additionally, TCP accept sockets get special event support. + * + * Socket numbers are not starting small, they can be any number (say 33060). + * Therefore, bitmaps are not used, but arrays. + * + * on winsock, you must use recv() and send() for TCP reads and writes, + * not read() and write(), those work only on files. + * + * Also fseek and fseeko do not work if a FILE is not fopen-ed in binary mode. + * + * When under a high load windows gives out lots of errors, from recvfrom + * on udp sockets for example (WSAECONNRESET). Even though the udp socket + * has no connection per se. + */ + +#ifndef UTIL_WINSOCK_EVENT_H +#define UTIL_WINSOCK_EVENT_H + +#ifdef USE_WINSOCK + +#ifndef HAVE_EVENT_BASE_FREE +#define HAVE_EVENT_BASE_FREE +#endif + +/** event timeout */ +#define EV_TIMEOUT 0x01 +/** event fd readable */ +#define EV_READ 0x02 +/** event fd writable */ +#define EV_WRITE 0x04 +/** event signal */ +#define EV_SIGNAL 0x08 +/** event must persist */ +#define EV_PERSIST 0x10 + +/* needs our redblack tree */ +#include "rbtree.h" + +/** max number of signals to support */ +#define MAX_SIG 32 + +/** The number of items that the winsock event handler can service. + * Windows cannot handle more anyway */ +#define WSK_MAX_ITEMS 64 + +/** + * event base for winsock event handler + */ +struct event_base +{ + /** sorted by timeout (absolute), ptr */ + rbtree_t* times; + /** array (first part in use) of handles to work on */ + struct event** items; + /** number of items in use in array */ + int max; + /** capacity of array, size of array in items */ + int cap; + /** array of 0 - maxsig of ptr to event for it */ + struct event** signals; + /** if we need to exit */ + int need_to_exit; + /** where to store time in seconds */ + uint32_t* time_secs; + /** where to store time in microseconds */ + struct timeval* time_tv; + /** + * TCP streams have sticky events to them, these are not + * reported by the windows event system anymore, we have to + * keep reporting those events as present until wouldblock() is + * signalled by the handler back to use. + */ + int tcp_stickies; + /** + * should next cycle process reinvigorated stickies, + * these are stickies that have been stored, but due to a new + * event_add a sudden interest in the event has incepted. + */ + int tcp_reinvigorated; + /** The list of events that is currently being processed. */ + WSAEVENT waitfor[WSK_MAX_ITEMS]; +}; + +/** + * Event structure. Has some of the event elements. + */ +struct event { + /** node in timeout rbtree */ + rbnode_t node; + /** is event already added */ + int added; + + /** event base it belongs to */ + struct event_base *ev_base; + /** fd to poll or -1 for timeouts. signal number for sigs. */ + int ev_fd; + /** what events this event is interested in, see EV_.. above. */ + short ev_events; + /** timeout value */ + struct timeval ev_timeout; + + /** callback to call: fd, eventbits, userarg */ + void (*ev_callback)(int, short, void *); + /** callback user arg */ + void *ev_arg; + + /* ----- nonpublic part, for winsock_event only ----- */ + /** index of this event in the items array (if added) */ + int idx; + /** the event handle to wait for new events to become ready */ + WSAEVENT hEvent; + /** true if this filedes is a TCP socket and needs special attention */ + int is_tcp; + /** remembered EV_ values */ + short old_events; + /** should remembered EV_ values be used for TCP streams. + * Reset after WOULDBLOCK is signaled using the function. */ + int stick_events; + + /** true if this event is a signaling WSAEvent by the user. + * User created and user closed WSAEvent. Only signaled/unsigneled, + * no read/write/distinctions needed. */ + int is_signal; + /** used during callbacks to see which events were just checked */ + int just_checked; +}; + +/** create event base */ +void *event_init(uint32_t* time_secs, struct timeval* time_tv); +/** get version */ +const char *event_get_version(void); +/** get polling method (select,epoll) */ +const char *event_get_method(void); +/** run select in a loop */ +int event_base_dispatch(struct event_base *); +/** exit that loop */ +int event_base_loopexit(struct event_base *, struct timeval *); +/** free event base. Free events yourself */ +void event_base_free(struct event_base *); +/** set content of event */ +void event_set(struct event *, int, short, void (*)(int, short, void *), void *); + +/** add event to a base. You *must* call this for every event. */ +int event_base_set(struct event_base *, struct event *); +/** add event to make it active. You may not change it with event_set anymore */ +int event_add(struct event *, struct timeval *); +/** remove event. You may change it again */ +int event_del(struct event *); + +#define evtimer_add(ev, tv) event_add(ev, tv) +#define evtimer_del(ev) event_del(ev) + +/* uses different implementation. Cannot mix fd/timeouts and signals inside + * the same struct event. create several event structs for that. */ +/** install signal handler */ +int signal_add(struct event *, struct timeval *); +/** set signal event contents */ +#define signal_set(ev, x, cb, arg) \ + event_set(ev, x, EV_SIGNAL|EV_PERSIST, cb, arg) +/** remove signal handler */ +int signal_del(struct event *); + +/** compare events in tree, based on timevalue, ptr for uniqueness */ +int mini_ev_cmp(const void* a, const void* b); + +/** + * Routine for windows only, where the handling layer can signal that + * a TCP stream encountered WSAEWOULDBLOCK for a stream and thus needs + * retesting the event. + * Pass if EV_READ or EV_WRITE gave wouldblock. + */ +void winsock_tcp_wouldblock(struct event* ev, int eventbit); + +/** + * Routine for windows only. where you pass a signal WSAEvent that + * you wait for. When the event is signaled, the callback gets called. + * The callback has to WSAResetEvent to disable the signal. + * @param base: the event base. + * @param ev: the event structure for data storage + * can be passed uninitialised. + * @param wsaevent: the WSAEvent that gets signaled. + * @param cb: callback routine. + * @param arg: user argument to callback routine. + * @return false on error. + */ +int winsock_register_wsaevent(struct event_base* base, struct event* ev, + WSAEVENT wsaevent, void (*cb)(int, short, void*), void* arg); + +/** + * Unregister a wsaevent. User has to close the WSAEVENT itself. + * @param ev: event data storage. + */ +void winsock_unregister_wsaevent(struct event* ev); + +#endif /* USE_WINSOCK */ +#endif /* UTIL_WINSOCK_EVENT_H */ diff --git a/validator/autotrust.c b/validator/autotrust.c new file mode 100644 index 00000000000..9896943245e --- /dev/null +++ b/validator/autotrust.c @@ -0,0 +1,2203 @@ +/* + * validator/autotrust.c - RFC5011 trust anchor management for unbound. + * + * Copyright (c) 2009, 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * Contains autotrust implementation. The implementation was taken from + * the autotrust daemon (BSD licensed), written by Matthijs Mekking. + * It was modified to fit into unbound. The state table process is the same. + */ +#include "config.h" +#include +#include "validator/autotrust.h" +#include "validator/val_anchor.h" +#include "validator/val_utils.h" +#include "validator/val_sigcrypt.h" +#include "util/data/dname.h" +#include "util/data/packed_rrset.h" +#include "util/log.h" +#include "util/module.h" +#include "util/net_help.h" +#include "util/config_file.h" +#include "util/regional.h" +#include "util/random.h" +#include "util/data/msgparse.h" +#include "services/mesh.h" +#include "services/cache/rrset.h" +#include "validator/val_kcache.h" + +/** number of times a key must be seen before it can become valid */ +#define MIN_PENDINGCOUNT 2 + +/** Event: Revoked */ +static void do_revoked(struct module_env* env, struct autr_ta* anchor, int* c); + +struct autr_global_data* autr_global_create(void) +{ + struct autr_global_data* global; + global = (struct autr_global_data*)malloc(sizeof(*global)); + if(!global) + return NULL; + rbtree_init(&global->probe, &probetree_cmp); + return global; +} + +void autr_global_delete(struct autr_global_data* global) +{ + if(!global) + return; + /* elements deleted by parent */ + memset(global, 0, sizeof(*global)); + free(global); +} + +int probetree_cmp(const void* x, const void* y) +{ + struct trust_anchor* a = (struct trust_anchor*)x; + struct trust_anchor* b = (struct trust_anchor*)y; + log_assert(a->autr && b->autr); + if(a->autr->next_probe_time < b->autr->next_probe_time) + return -1; + if(a->autr->next_probe_time > b->autr->next_probe_time) + return 1; + /* time is equal, sort on trust point identity */ + return anchor_cmp(x, y); +} + +size_t +autr_get_num_anchors(struct val_anchors* anchors) +{ + size_t res = 0; + if(!anchors) + return 0; + lock_basic_lock(&anchors->lock); + if(anchors->autr) + res = anchors->autr->probe.count; + lock_basic_unlock(&anchors->lock); + return res; +} + +/** Position in string */ +static int +position_in_string(char *str, const char* sub) +{ + char* pos = strstr(str, sub); + if(pos) + return (int)(pos-str)+(int)strlen(sub); + return -1; +} + +/** Debug routine to print pretty key information */ +static void +verbose_key(struct autr_ta* ta, enum verbosity_value level, + const char* format, ...) ATTR_FORMAT(printf, 3, 4); + +/** + * Implementation of debug pretty key print + * @param ta: trust anchor key with DNSKEY data. + * @param level: verbosity level to print at. + * @param format: printf style format string. + */ +static void +verbose_key(struct autr_ta* ta, enum verbosity_value level, + const char* format, ...) +{ + va_list args; + va_start(args, format); + if(verbosity >= level) { + char* str = ldns_rdf2str(ldns_rr_owner(ta->rr)); + int keytag = (int)ldns_calc_keytag(ta->rr); + char msg[MAXSYSLOGMSGLEN]; + vsnprintf(msg, sizeof(msg), format, args); + verbose(level, "%s key %d %s", str?str:"??", keytag, msg); + free(str); + } + va_end(args); +} + +/** + * Parse comments + * @param str: to parse + * @param ta: trust key autotrust metadata + * @return false on failure. + */ +static int +parse_comments(char* str, struct autr_ta* ta) +{ + int len = (int)strlen(str), pos = 0, timestamp = 0; + char* comment = (char*) malloc(sizeof(char)*len+1); + char* comments = comment; + if(!comment) { + log_err("malloc failure in parse"); + return 0; + } + /* skip over whitespace and data at start of line */ + while (*str != '\0' && *str != ';') + str++; + if (*str == ';') + str++; + /* copy comments */ + while (*str != '\0') + { + *comments = *str; + comments++; + str++; + } + *comments = '\0'; + + comments = comment; + + /* read state */ + pos = position_in_string(comments, "state="); + if (pos >= (int) strlen(comments)) + { + log_err("parse error"); + free(comment); + return 0; + } + if (pos <= 0) + ta->s = AUTR_STATE_VALID; + else + { + int s = (int) comments[pos] - '0'; + switch(s) + { + case AUTR_STATE_START: + case AUTR_STATE_ADDPEND: + case AUTR_STATE_VALID: + case AUTR_STATE_MISSING: + case AUTR_STATE_REVOKED: + case AUTR_STATE_REMOVED: + ta->s = s; + break; + default: + verbose_key(ta, VERB_OPS, "has undefined " + "state, considered NewKey"); + ta->s = AUTR_STATE_START; + break; + } + } + /* read pending count */ + pos = position_in_string(comments, "count="); + if (pos >= (int) strlen(comments)) + { + log_err("parse error"); + free(comment); + return 0; + } + if (pos <= 0) + ta->pending_count = 0; + else + { + comments += pos; + ta->pending_count = (uint8_t)atoi(comments); + } + + /* read last change */ + pos = position_in_string(comments, "lastchange="); + if (pos >= (int) strlen(comments)) + { + log_err("parse error"); + free(comment); + return 0; + } + if (pos >= 0) + { + comments += pos; + timestamp = atoi(comments); + } + if (pos < 0 || !timestamp) + ta->last_change = 0; + else + ta->last_change = (uint32_t)timestamp; + + free(comment); + return 1; +} + +/** Check if a line contains data (besides comments) */ +static int +str_contains_data(char* str, char comment) +{ + while (*str != '\0') { + if (*str == comment || *str == '\n') + return 0; + if (*str != ' ' && *str != '\t') + return 1; + str++; + } + return 0; +} + +/** Get DNSKEY flags */ +static int +dnskey_flags(ldns_rr* rr) +{ + if(ldns_rr_get_type(rr) != LDNS_RR_TYPE_DNSKEY) + return 0; + return (int)ldns_read_uint16(ldns_rdf_data(ldns_rr_dnskey_flags(rr))); +} + + +/** Check if KSK DNSKEY */ +static int +rr_is_dnskey_sep(ldns_rr* rr) +{ + return (dnskey_flags(rr)&DNSKEY_BIT_SEP); +} + +/** Check if REVOKED DNSKEY */ +static int +rr_is_dnskey_revoked(ldns_rr* rr) +{ + return (dnskey_flags(rr)&LDNS_KEY_REVOKE_KEY); +} + +/** create ta */ +static struct autr_ta* +autr_ta_create(ldns_rr* rr) +{ + struct autr_ta* ta = (struct autr_ta*)calloc(1, sizeof(*ta)); + if(!ta) { + ldns_rr_free(rr); + return NULL; + } + ta->rr = rr; + return ta; +} + +/** create tp */ +static struct trust_anchor* +autr_tp_create(struct val_anchors* anchors, ldns_rdf* own, uint16_t dc) +{ + struct trust_anchor* tp = (struct trust_anchor*)calloc(1, sizeof(*tp)); + if(!tp) return NULL; + tp->name = memdup(ldns_rdf_data(own), ldns_rdf_size(own)); + if(!tp->name) { + free(tp); + return NULL; + } + tp->namelen = ldns_rdf_size(own); + tp->namelabs = dname_count_labels(tp->name); + tp->node.key = tp; + tp->dclass = dc; + tp->autr = (struct autr_point_data*)calloc(1, sizeof(*tp->autr)); + if(!tp->autr) { + free(tp->name); + free(tp); + return NULL; + } + tp->autr->pnode.key = tp; + + lock_basic_lock(&anchors->lock); + if(!rbtree_insert(anchors->tree, &tp->node)) { + lock_basic_unlock(&anchors->lock); + log_err("trust anchor presented twice"); + free(tp->name); + free(tp->autr); + free(tp); + return NULL; + } + if(!rbtree_insert(&anchors->autr->probe, &tp->autr->pnode)) { + (void)rbtree_delete(anchors->tree, tp); + lock_basic_unlock(&anchors->lock); + log_err("trust anchor in probetree twice"); + free(tp->name); + free(tp->autr); + free(tp); + return NULL; + } + lock_basic_unlock(&anchors->lock); + lock_basic_init(&tp->lock); + lock_protect(&tp->lock, tp, sizeof(*tp)); + lock_protect(&tp->lock, tp->autr, sizeof(*tp->autr)); + return tp; +} + +/** delete assembled rrsets */ +static void +autr_rrset_delete(struct ub_packed_rrset_key* r) +{ + if(r) { + free(r->rk.dname); + free(r->entry.data); + free(r); + } +} + +void autr_point_delete(struct trust_anchor* tp) +{ + if(!tp) + return; + lock_unprotect(&tp->lock, tp); + lock_unprotect(&tp->lock, tp->autr); + lock_basic_destroy(&tp->lock); + autr_rrset_delete(tp->ds_rrset); + autr_rrset_delete(tp->dnskey_rrset); + if(tp->autr) { + struct autr_ta* p = tp->autr->keys, *np; + while(p) { + np = p->next; + ldns_rr_free(p->rr); + free(p); + p = np; + } + free(tp->autr->file); + free(tp->autr); + } + free(tp->name); + free(tp); +} + +/** find or add a new trust point for autotrust */ +static struct trust_anchor* +find_add_tp(struct val_anchors* anchors, ldns_rr* rr) +{ + struct trust_anchor* tp; + ldns_rdf* own = ldns_rr_owner(rr); + tp = anchor_find(anchors, ldns_rdf_data(own), + dname_count_labels(ldns_rdf_data(own)), + ldns_rdf_size(own), ldns_rr_get_class(rr)); + if(tp) { + if(!tp->autr) { + log_err("anchor cannot be with and without autotrust"); + lock_basic_unlock(&tp->lock); + return NULL; + } + return tp; + } + tp = autr_tp_create(anchors, ldns_rr_owner(rr), ldns_rr_get_class(rr)); + lock_basic_lock(&tp->lock); + return tp; +} + +/** Add trust anchor from RR */ +static struct autr_ta* +add_trustanchor_frm_rr(struct val_anchors* anchors, ldns_rr* rr, + struct trust_anchor** tp) +{ + struct autr_ta* ta = autr_ta_create(rr); + if(!ta) + return NULL; + *tp = find_add_tp(anchors, rr); + if(!*tp) { + ldns_rr_free(ta->rr); + free(ta); + return NULL; + } + /* add ta to tp */ + ta->next = (*tp)->autr->keys; + (*tp)->autr->keys = ta; + lock_basic_unlock(&(*tp)->lock); + return ta; +} + +/** + * Add new trust anchor from a string in file. + * @param anchors: all anchors + * @param str: string with anchor and comments, if any comments. + * @param tp: trust point returned. + * @param origin: what to use for @ + * @param prev: previous rr name + * @param skip: if true, the result is NULL, but not an error, skip it. + * @return new key in trust point. + */ +static struct autr_ta* +add_trustanchor_frm_str(struct val_anchors* anchors, char* str, + struct trust_anchor** tp, ldns_rdf* origin, ldns_rdf** prev, int* skip) +{ + ldns_rr* rr; + ldns_status lstatus; + if (!str_contains_data(str, ';')) { + *skip = 1; + return NULL; /* empty line */ + } + if (LDNS_STATUS_OK != + (lstatus = ldns_rr_new_frm_str(&rr, str, 0, origin, prev))) + { + log_err("ldns error while converting string to RR: %s", + ldns_get_errorstr_by_id(lstatus)); + return NULL; + } + if(ldns_rr_get_type(rr) != LDNS_RR_TYPE_DNSKEY && + ldns_rr_get_type(rr) != LDNS_RR_TYPE_DS) { + ldns_rr_free(rr); + *skip = 1; + return NULL; /* only DS and DNSKEY allowed */ + } + return add_trustanchor_frm_rr(anchors, rr, tp); +} + +/** + * Load single anchor + * @param anchors: all points. + * @param str: comments line + * @param fname: filename + * @param origin: $ORIGIN. + * @param prev: passed to ldns. + * @param skip: if true, the result is NULL, but not an error, skip it. + * @return false on failure, otherwise the tp read. + */ +static struct trust_anchor* +load_trustanchor(struct val_anchors* anchors, char* str, const char* fname, + ldns_rdf* origin, ldns_rdf** prev, int* skip) +{ + struct autr_ta* ta = NULL; + struct trust_anchor* tp = NULL; + + ta = add_trustanchor_frm_str(anchors, str, &tp, origin, prev, skip); + if(!ta) + return NULL; + lock_basic_lock(&tp->lock); + if(!parse_comments(str, ta)) { + lock_basic_unlock(&tp->lock); + return NULL; + } + if(!tp->autr->file) { + tp->autr->file = strdup(fname); + if(!tp->autr->file) { + lock_basic_unlock(&tp->lock); + log_err("malloc failure"); + return NULL; + } + } + lock_basic_unlock(&tp->lock); + return tp; +} + +/** + * Assemble the trust anchors into DS and DNSKEY packed rrsets. + * Uses only VALID and MISSING DNSKEYs. + * Read the ldns_rrs and builds packed rrsets + * @param tp: the trust point. Must be locked. + * @return false on malloc failure. + */ +static int +autr_assemble(struct trust_anchor* tp) +{ + ldns_rr_list* ds, *dnskey; + struct autr_ta* ta; + struct ub_packed_rrset_key* ubds=NULL, *ubdnskey=NULL; + + ds = ldns_rr_list_new(); + dnskey = ldns_rr_list_new(); + if(!ds || !dnskey) { + ldns_rr_list_free(ds); + ldns_rr_list_free(dnskey); + return 0; + } + for(ta = tp->autr->keys; ta; ta = ta->next) { + if(ldns_rr_get_type(ta->rr) == LDNS_RR_TYPE_DS) { + if(!ldns_rr_list_push_rr(ds, ta->rr)) { + ldns_rr_list_free(ds); + ldns_rr_list_free(dnskey); + return 0; + } + } else if(ta->s == AUTR_STATE_VALID || + ta->s == AUTR_STATE_MISSING) { + if(!ldns_rr_list_push_rr(dnskey, ta->rr)) { + ldns_rr_list_free(ds); + ldns_rr_list_free(dnskey); + return 0; + } + } + } + + /* make packed rrset keys - malloced with no ID number, they + * are not in the cache */ + /* make packed rrset data (if there is a key) */ + + if(ldns_rr_list_rr_count(ds) > 0) { + ubds = ub_packed_rrset_heap_key(ds); + if(!ubds) + goto error_cleanup; + ubds->entry.data = packed_rrset_heap_data(ds); + if(!ubds->entry.data) + goto error_cleanup; + } + if(ldns_rr_list_rr_count(dnskey) > 0) { + ubdnskey = ub_packed_rrset_heap_key(dnskey); + if(!ubdnskey) + goto error_cleanup; + ubdnskey->entry.data = packed_rrset_heap_data(dnskey); + if(!ubdnskey->entry.data) { + error_cleanup: + autr_rrset_delete(ubds); + autr_rrset_delete(ubdnskey); + ldns_rr_list_free(ds); + ldns_rr_list_free(dnskey); + return 0; + } + } + /* we have prepared the new keys so nothing can go wrong any more. + * And we are sure we cannot be left without trustanchor after + * any errors. Put in the new keys and remove old ones. */ + + /* free the old data */ + autr_rrset_delete(tp->ds_rrset); + autr_rrset_delete(tp->dnskey_rrset); + + /* assign the data to replace the old */ + tp->ds_rrset = ubds; + tp->dnskey_rrset = ubdnskey; + tp->numDS = ldns_rr_list_rr_count(ds); + tp->numDNSKEY = ldns_rr_list_rr_count(dnskey); + + ldns_rr_list_free(ds); + ldns_rr_list_free(dnskey); + return 1; +} + +/** parse integer */ +static unsigned int +parse_int(char* line, int* ret) +{ + char *e; + unsigned int x = (unsigned int)strtol(line, &e, 10); + if(line == e) { + *ret = -1; /* parse error */ + return 0; + } + *ret = 1; /* matched */ + return x; +} + +/** parse id sequence for anchor */ +static struct trust_anchor* +parse_id(struct val_anchors* anchors, char* line) +{ + struct trust_anchor *tp; + int r; + ldns_rdf* rdf; + uint16_t dclass; + /* read the owner name */ + char* next = strchr(line, ' '); + if(!next) + return NULL; + next[0] = 0; + rdf = ldns_dname_new_frm_str(line); + if(!rdf) + return NULL; + + /* read the class */ + dclass = parse_int(next+1, &r); + if(r == -1) { + ldns_rdf_deep_free(rdf); + return NULL; + } + + /* find the trust point */ + tp = autr_tp_create(anchors, rdf, dclass); + ldns_rdf_deep_free(rdf); + return tp; +} + +/** + * Parse variable from trustanchor header + * @param line: to parse + * @param anchors: the anchor is added to this, if "id:" is seen. + * @param anchor: the anchor as result value or previously returned anchor + * value to read the variable lines into. + * @return: 0 no match, -1 failed syntax error, +1 success line read. + * +2 revoked trust anchor file. + */ +static int +parse_var_line(char* line, struct val_anchors* anchors, + struct trust_anchor** anchor) +{ + struct trust_anchor* tp = *anchor; + int r = 0; + if(strncmp(line, ";;id: ", 6) == 0) { + *anchor = parse_id(anchors, line+6); + if(!*anchor) return -1; + else return 1; + } else if(strncmp(line, ";;REVOKED", 9) == 0) { + if(tp) { + log_err("REVOKED statement must be at start of file"); + return -1; + } + return 2; + } else if(strncmp(line, ";;last_queried: ", 16) == 0) { + if(!tp) return -1; + lock_basic_lock(&tp->lock); + tp->autr->last_queried = (time_t)parse_int(line+16, &r); + lock_basic_unlock(&tp->lock); + } else if(strncmp(line, ";;last_success: ", 16) == 0) { + if(!tp) return -1; + lock_basic_lock(&tp->lock); + tp->autr->last_success = (time_t)parse_int(line+16, &r); + lock_basic_unlock(&tp->lock); + } else if(strncmp(line, ";;next_probe_time: ", 19) == 0) { + if(!tp) return -1; + lock_basic_lock(&anchors->lock); + lock_basic_lock(&tp->lock); + (void)rbtree_delete(&anchors->autr->probe, tp); + tp->autr->next_probe_time = (time_t)parse_int(line+19, &r); + (void)rbtree_insert(&anchors->autr->probe, &tp->autr->pnode); + lock_basic_unlock(&tp->lock); + lock_basic_unlock(&anchors->lock); + } else if(strncmp(line, ";;query_failed: ", 16) == 0) { + if(!tp) return -1; + lock_basic_lock(&tp->lock); + tp->autr->query_failed = (uint8_t)parse_int(line+16, &r); + lock_basic_unlock(&tp->lock); + } else if(strncmp(line, ";;query_interval: ", 18) == 0) { + if(!tp) return -1; + lock_basic_lock(&tp->lock); + tp->autr->query_interval = (uint32_t)parse_int(line+18, &r); + lock_basic_unlock(&tp->lock); + } else if(strncmp(line, ";;retry_time: ", 14) == 0) { + if(!tp) return -1; + lock_basic_lock(&tp->lock); + tp->autr->retry_time = (uint32_t)parse_int(line+14, &r); + lock_basic_unlock(&tp->lock); + } + return r; +} + +/** handle origin lines */ +static int +handle_origin(char* line, ldns_rdf** origin) +{ + while(isspace((int)*line)) + line++; + if(strncmp(line, "$ORIGIN", 7) != 0) + return 0; + ldns_rdf_deep_free(*origin); + line += 7; + while(isspace((int)*line)) + line++; + *origin = ldns_dname_new_frm_str(line); + if(!*origin) + log_warn("malloc failure or parse error in $ORIGIN"); + return 1; +} + +/** Read one line and put multiline RRs onto one line string */ +static int +read_multiline(char* buf, size_t len, FILE* in, int* linenr) +{ + char* pos = buf; + size_t left = len; + int depth = 0; + buf[len-1] = 0; + while(left > 0 && fgets(pos, (int)left, in) != NULL) { + size_t i, poslen = strlen(pos); + (*linenr)++; + + /* check what the new depth is after the line */ + /* this routine cannot handle braces inside quotes, + say for TXT records, but this routine only has to read keys */ + for(i=0; i0) + pos[poslen-1] = 0; /* strip newline */ + if(strchr(pos, ';')) + strchr(pos, ';')[0] = 0; /* strip comments */ + + /* move to paste other lines behind this one */ + poslen = strlen(pos); + pos += poslen; + left -= poslen; + /* the newline is changed into a space */ + if(left <= 2 /* space and eos */) { + log_err("line too long"); + return -1; + } + pos[0] = ' '; + pos[1] = 0; + pos += 1; + left -= 1; + } + if(depth != 0) { + log_err("mismatch: too many '('"); + return -1; + } + if(pos != buf) + return 1; + return 0; +} + +int autr_read_file(struct val_anchors* anchors, const char* nm) +{ + /* the file descriptor */ + FILE* fd; + /* keep track of line numbers */ + int line_nr = 0; + /* single line */ + char line[10240]; + /* trust point being read */ + struct trust_anchor *tp = NULL, *tp2; + int r; + /* for $ORIGIN parsing */ + ldns_rdf *origin=NULL, *prev=NULL; + + if (!(fd = fopen(nm, "r"))) { + log_err("unable to open %s for reading: %s", + nm, strerror(errno)); + return 0; + } + verbose(VERB_ALGO, "reading autotrust anchor file %s", nm); + while ( (r=read_multiline(line, sizeof(line), fd, &line_nr)) != 0) { + if(r == -1 || (r = parse_var_line(line, anchors, &tp)) == -1) { + log_err("could not parse auto-trust-anchor-file " + "%s line %d", nm, line_nr); + fclose(fd); + ldns_rdf_deep_free(origin); + ldns_rdf_deep_free(prev); + return 0; + } else if(r == 1) { + continue; + } else if(r == 2) { + log_warn("trust anchor %s has been revoked", nm); + fclose(fd); + ldns_rdf_deep_free(origin); + ldns_rdf_deep_free(prev); + return 1; + } + if (!str_contains_data(line, ';')) + continue; /* empty lines allowed */ + if(handle_origin(line, &origin)) + continue; + r = 0; + if(!(tp2=load_trustanchor(anchors, line, nm, origin, &prev, + &r))) { + if(!r) log_err("failed to load trust anchor from %s " + "at line %i, skipping", nm, line_nr); + /* try to do the rest */ + continue; + } + if(tp && tp != tp2) { + log_err("file %s has mismatching data inside: " + "the file may only contain keys for one name, " + "remove keys for other domain names", nm); + fclose(fd); + ldns_rdf_deep_free(origin); + ldns_rdf_deep_free(prev); + return 0; + } + tp = tp2; + } + fclose(fd); + ldns_rdf_deep_free(origin); + ldns_rdf_deep_free(prev); + if(!tp) { + log_err("failed to read %s", nm); + return 0; + } + + /* now assemble the data into DNSKEY and DS packed rrsets */ + lock_basic_lock(&tp->lock); + if(!autr_assemble(tp)) { + lock_basic_unlock(&tp->lock); + log_err("malloc failure assembling %s", nm); + return 0; + } + lock_basic_unlock(&tp->lock); + return 1; +} + +/** string for a trustanchor state */ +static const char* +trustanchor_state2str(autr_state_t s) +{ + switch (s) { + case AUTR_STATE_START: return " START "; + case AUTR_STATE_ADDPEND: return " ADDPEND "; + case AUTR_STATE_VALID: return " VALID "; + case AUTR_STATE_MISSING: return " MISSING "; + case AUTR_STATE_REVOKED: return " REVOKED "; + case AUTR_STATE_REMOVED: return " REMOVED "; + } + return " UNKNOWN "; +} + +/** print ID to file */ +static int +print_id(FILE* out, char* fname, struct module_env* env, + uint8_t* nm, size_t nmlen, uint16_t dclass) +{ + ldns_rdf rdf; +#ifdef UNBOUND_DEBUG + ldns_status s; +#endif + + memset(&rdf, 0, sizeof(rdf)); + ldns_rdf_set_data(&rdf, nm); + ldns_rdf_set_size(&rdf, nmlen); + ldns_rdf_set_type(&rdf, LDNS_RDF_TYPE_DNAME); + + ldns_buffer_clear(env->scratch_buffer); +#ifdef UNBOUND_DEBUG + s = +#endif + ldns_rdf2buffer_str_dname(env->scratch_buffer, &rdf); + log_assert(s == LDNS_STATUS_OK); + ldns_buffer_write_u8(env->scratch_buffer, 0); + ldns_buffer_flip(env->scratch_buffer); + if(fprintf(out, ";;id: %s %d\n", + (char*)ldns_buffer_begin(env->scratch_buffer), + (int)dclass) < 0) { + log_err("could not write to %s: %s", fname, strerror(errno)); + return 0; + } + return 1; +} + +static int +autr_write_contents(FILE* out, char* fn, struct module_env* env, + struct trust_anchor* tp) +{ + char tmi[32]; + struct autr_ta* ta; + char* str; + + /* write pretty header */ + if(fprintf(out, "; autotrust trust anchor file\n") < 0) { + log_err("could not write to %s: %s", fn, strerror(errno)); + return 0; + } + if(tp->autr->revoked) { + if(fprintf(out, ";;REVOKED\n") < 0 || + fprintf(out, "; The zone has all keys revoked, and is\n" + "; considered as if it has no trust anchors.\n" + "; the remainder of the file is the last probe.\n" + "; to restart the trust anchor, overwrite this file.\n" + "; with one containing valid DNSKEYs or DSes.\n") < 0) { + log_err("could not write to %s: %s", fn, strerror(errno)); + return 0; + } + } + if(!print_id(out, fn, env, tp->name, tp->namelen, tp->dclass)) { + return 0; + } + if(fprintf(out, ";;last_queried: %u ;;%s", + (unsigned int)tp->autr->last_queried, + ctime_r(&(tp->autr->last_queried), tmi)) < 0 || + fprintf(out, ";;last_success: %u ;;%s", + (unsigned int)tp->autr->last_success, + ctime_r(&(tp->autr->last_success), tmi)) < 0 || + fprintf(out, ";;next_probe_time: %u ;;%s", + (unsigned int)tp->autr->next_probe_time, + ctime_r(&(tp->autr->next_probe_time), tmi)) < 0 || + fprintf(out, ";;query_failed: %d\n", (int)tp->autr->query_failed)<0 + || fprintf(out, ";;query_interval: %d\n", + (int)tp->autr->query_interval) < 0 || + fprintf(out, ";;retry_time: %d\n", (int)tp->autr->retry_time) < 0) { + log_err("could not write to %s: %s", fn, strerror(errno)); + return 0; + } + + /* write anchors */ + for(ta=tp->autr->keys; ta; ta=ta->next) { + /* by default do not store START and REMOVED keys */ + if(ta->s == AUTR_STATE_START) + continue; + if(ta->s == AUTR_STATE_REMOVED) + continue; + /* only store keys */ + if(ldns_rr_get_type(ta->rr) != LDNS_RR_TYPE_DNSKEY) + continue; + str = ldns_rr2str(ta->rr); + if(!str || !str[0]) { + free(str); + log_err("malloc failure writing %s", fn); + return 0; + } + str[strlen(str)-1] = 0; /* remove newline */ + if(fprintf(out, "%s ;;state=%d [%s] ;;count=%d " + ";;lastchange=%u ;;%s", str, (int)ta->s, + trustanchor_state2str(ta->s), (int)ta->pending_count, + (unsigned int)ta->last_change, + ctime_r(&(ta->last_change), tmi)) < 0) { + log_err("could not write to %s: %s", fn, strerror(errno)); + free(str); + return 0; + } + free(str); + } + return 1; +} + +void autr_write_file(struct module_env* env, struct trust_anchor* tp) +{ + FILE* out; + char* fname = tp->autr->file; + char tempf[2048]; + log_assert(tp->autr); + /* unique name with pid number and thread number */ + snprintf(tempf, sizeof(tempf), "%s.%d-%d", fname, (int)getpid(), + env&&env->worker?*(int*)env->worker:0); + verbose(VERB_ALGO, "autotrust: write to disk: %s", tempf); + out = fopen(tempf, "w"); + if(!out) { + log_err("could not open autotrust file for writing, %s: %s", + tempf, strerror(errno)); + return; + } + if(!autr_write_contents(out, tempf, env, tp)) { + /* failed to write contents (completely) */ + fclose(out); + unlink(tempf); + log_err("could not completely write: %s", fname); + return; + } + /* success; overwrite actual file */ + fclose(out); + verbose(VERB_ALGO, "autotrust: replaced %s", fname); +#ifdef UB_ON_WINDOWS + (void)unlink(fname); /* windows does not replace file with rename() */ +#endif + if(rename(tempf, fname) < 0) { + log_err("rename(%s to %s): %s", tempf, fname, strerror(errno)); + } +} + +/** + * Verify if dnskey works for trust point + * @param env: environment (with time) for verification + * @param ve: validator environment (with options) for verification. + * @param tp: trust point to verify with + * @param rrset: DNSKEY rrset to verify. + * @return false on failure, true if verification successful. + */ +static int +verify_dnskey(struct module_env* env, struct val_env* ve, + struct trust_anchor* tp, struct ub_packed_rrset_key* rrset) +{ + char* reason = NULL; + uint8_t sigalg[ALGO_NEEDS_MAX+1]; + int downprot = 1; + enum sec_status sec = val_verify_DNSKEY_with_TA(env, ve, rrset, + tp->ds_rrset, tp->dnskey_rrset, downprot?sigalg:NULL, &reason); + /* sigalg is ignored, it returns algorithms signalled to exist, but + * in 5011 there are no other rrsets to check. if downprot is + * enabled, then it checks that the DNSKEY is signed with all + * algorithms available in the trust store. */ + verbose(VERB_ALGO, "autotrust: validate DNSKEY with anchor: %s", + sec_status_to_string(sec)); + return sec == sec_status_secure; +} + +/** Find minimum expiration interval from signatures */ +static uint32_t +min_expiry(struct module_env* env, ldns_rr_list* rrset) +{ + size_t i; + uint32_t t, r = 15 * 24 * 3600; /* 15 days max */ + for(i=0; inow > 0) { + t -= *env->now; + if(t < r) + r = t; + } + } + return r; +} + +/** Is rr self-signed revoked key */ +static int +rr_is_selfsigned_revoked(struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key* dnskey_rrset, size_t i) +{ + enum sec_status sec; + char* reason = NULL; + verbose(VERB_ALGO, "seen REVOKE flag, check self-signed, rr %d", + (int)i); + /* no algorithm downgrade protection necessary, if it is selfsigned + * revoked it can be removed. */ + sec = dnskey_verify_rrset(env, ve, dnskey_rrset, dnskey_rrset, i, + &reason); + return (sec == sec_status_secure); +} + +/** Set fetched value */ +static void +seen_trustanchor(struct autr_ta* ta, uint8_t seen) +{ + ta->fetched = seen; + if(ta->pending_count < 250) /* no numerical overflow, please */ + ta->pending_count++; +} + +/** set revoked value */ +static void +seen_revoked_trustanchor(struct autr_ta* ta, uint8_t revoked) +{ + ta->revoked = revoked; +} + +/** revoke a trust anchor */ +static void +revoke_dnskey(struct autr_ta* ta, int off) +{ + ldns_rdf* rdf; + uint16_t flags; + log_assert(ta && ta->rr); + if(ldns_rr_get_type(ta->rr) != LDNS_RR_TYPE_DNSKEY) + return; + rdf = ldns_rr_dnskey_flags(ta->rr); + flags = ldns_read_uint16(ldns_rdf_data(rdf)); + + if (off && (flags&LDNS_KEY_REVOKE_KEY)) + flags ^= LDNS_KEY_REVOKE_KEY; /* flip */ + else + flags |= LDNS_KEY_REVOKE_KEY; + ldns_write_uint16(ldns_rdf_data(rdf), flags); +} + +/** Compare two RR buffers skipping the REVOKED bit */ +static int +ldns_rr_compare_wire_skip_revbit(ldns_buffer* rr1_buf, ldns_buffer* rr2_buf) +{ + size_t rr1_len, rr2_len, min_len, i, offset; + rr1_len = ldns_buffer_capacity(rr1_buf); + rr2_len = ldns_buffer_capacity(rr2_buf); + /* jump past dname (checked in earlier part) and especially past TTL */ + offset = 0; + while (offset < rr1_len && *ldns_buffer_at(rr1_buf, offset) != 0) + offset += *ldns_buffer_at(rr1_buf, offset) + 1; + /* jump to rdata section (PAST the rdata length field) */ + offset += 11; /* 0-dname-end + type + class + ttl + rdatalen */ + min_len = (rr1_len < rr2_len) ? rr1_len : rr2_len; + /* compare RRs RDATA byte for byte. */ + for(i = offset; i < min_len; i++) + { + uint8_t *rdf1, *rdf2; + rdf1 = ldns_buffer_at(rr1_buf, i); + rdf2 = ldns_buffer_at(rr2_buf, i); + if (i==(offset+1)) + { + /* this is the second part of the flags field */ + *rdf1 = *rdf1 | LDNS_KEY_REVOKE_KEY; + *rdf2 = *rdf2 | LDNS_KEY_REVOKE_KEY; + } + if (*rdf1 < *rdf2) return -1; + else if (*rdf1 > *rdf2) return 1; + } + return 0; +} + +/** Compare two RRs skipping the REVOKED bit */ +static int +ldns_rr_compare_skip_revbit(const ldns_rr* rr1, const ldns_rr* rr2, int* result) +{ + size_t rr1_len, rr2_len; + ldns_buffer* rr1_buf; + ldns_buffer* rr2_buf; + + *result = ldns_rr_compare_no_rdata(rr1, rr2); + if (*result == 0) + { + rr1_len = ldns_rr_uncompressed_size(rr1); + rr2_len = ldns_rr_uncompressed_size(rr2); + rr1_buf = ldns_buffer_new(rr1_len); + rr2_buf = ldns_buffer_new(rr2_len); + if(!rr1_buf || !rr2_buf) { + ldns_buffer_free(rr1_buf); + ldns_buffer_free(rr2_buf); + return 0; + } + if (ldns_rr2buffer_wire_canonical(rr1_buf, rr1, + LDNS_SECTION_ANY) != LDNS_STATUS_OK) + { + ldns_buffer_free(rr1_buf); + ldns_buffer_free(rr2_buf); + return 0; + } + if (ldns_rr2buffer_wire_canonical(rr2_buf, rr2, + LDNS_SECTION_ANY) != LDNS_STATUS_OK) { + ldns_buffer_free(rr1_buf); + ldns_buffer_free(rr2_buf); + return 0; + } + *result = ldns_rr_compare_wire_skip_revbit(rr1_buf, rr2_buf); + ldns_buffer_free(rr1_buf); + ldns_buffer_free(rr2_buf); + } + return 1; +} + + +/** compare two trust anchors */ +static int +ta_compare(ldns_rr* a, ldns_rr* b, int* result) +{ + if (!a && !b) *result = 0; + else if (!a) *result = -1; + else if (!b) *result = 1; + else if (ldns_rr_get_type(a) != ldns_rr_get_type(b)) + *result = (int)ldns_rr_get_type(a) - (int)ldns_rr_get_type(b); + else if (ldns_rr_get_type(a) == LDNS_RR_TYPE_DNSKEY) { + if(!ldns_rr_compare_skip_revbit(a, b, result)) + return 0; + } + else if (ldns_rr_get_type(a) == LDNS_RR_TYPE_DS) + *result = ldns_rr_compare(a, b); + else *result = -1; + return 1; +} + +/** + * Find key + * @param tp: to search in + * @param rr: to look for + * @param result: returns NULL or the ta key looked for. + * @return false on malloc failure during search. if true examine result. + */ +static int +find_key(struct trust_anchor* tp, ldns_rr* rr, struct autr_ta** result) +{ + struct autr_ta* ta; + int ret; + if(!tp || !rr) + return 0; + for(ta=tp->autr->keys; ta; ta=ta->next) { + if(!ta_compare(ta->rr, rr, &ret)) + return 0; + if(ret == 0) { + *result = ta; + return 1; + } + } + *result = NULL; + return 1; +} + +/** add key and clone RR and tp already locked */ +static struct autr_ta* +add_key(struct trust_anchor* tp, ldns_rr* rr) +{ + ldns_rr* c; + struct autr_ta* ta; + c = ldns_rr_clone(rr); + if(!c) return NULL; + ta = autr_ta_create(c); + if(!ta) { + ldns_rr_free(c); + return NULL; + } + /* link in, tp already locked */ + ta->next = tp->autr->keys; + tp->autr->keys = ta; + return ta; +} + +/** get TTL from DNSKEY rrset */ +static uint32_t +key_ttl(struct ub_packed_rrset_key* k) +{ + struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data; + return d->ttl; +} + +/** update the time values for the trustpoint */ +static void +set_tp_times(struct trust_anchor* tp, uint32_t rrsig_exp_interval, + uint32_t origttl, int* changed) +{ + uint32_t x, qi = tp->autr->query_interval, rt = tp->autr->retry_time; + + /* x = MIN(15days, ttl/2, expire/2) */ + x = 15 * 24 * 3600; + if(origttl/2 < x) + x = origttl/2; + if(rrsig_exp_interval/2 < x) + x = rrsig_exp_interval/2; + /* MAX(1hr, x) */ + if(x < 3600) + tp->autr->query_interval = 3600; + else tp->autr->query_interval = x; + + /* x= MIN(1day, ttl/10, expire/10) */ + x = 24 * 3600; + if(origttl/10 < x) + x = origttl/10; + if(rrsig_exp_interval/10 < x) + x = rrsig_exp_interval/10; + /* MAX(1hr, x) */ + if(x < 3600) + tp->autr->retry_time = 3600; + else tp->autr->retry_time = x; + + if(qi != tp->autr->query_interval || rt != tp->autr->retry_time) { + *changed = 1; + verbose(VERB_ALGO, "orig_ttl is %d", (int)origttl); + verbose(VERB_ALGO, "rrsig_exp_interval is %d", + (int)rrsig_exp_interval); + verbose(VERB_ALGO, "query_interval: %d, retry_time: %d", + (int)tp->autr->query_interval, + (int)tp->autr->retry_time); + } +} + +/** init events to zero */ +static void +init_events(struct trust_anchor* tp) +{ + struct autr_ta* ta; + for(ta=tp->autr->keys; ta; ta=ta->next) { + ta->fetched = 0; + } +} + +/** check for revoked keys without trusting any other information */ +static void +check_contains_revoked(struct module_env* env, struct val_env* ve, + struct trust_anchor* tp, struct ub_packed_rrset_key* dnskey_rrset, + int* changed) +{ + ldns_rr_list* r = packed_rrset_to_rr_list(dnskey_rrset, + env->scratch_buffer); + size_t i; + if(!r) { + log_err("malloc failure"); + return; + } + for(i=0; irevoked) + *changed = 1; + seen_revoked_trustanchor(ta, 1); + do_revoked(env, ta, changed); + } + } + ldns_rr_list_deep_free(r); +} + +/** See if a DNSKEY is verified by one of the DSes */ +static int +key_matches_a_ds(struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key* dnskey_rrset, size_t key_idx, + struct ub_packed_rrset_key* ds_rrset) +{ + struct packed_rrset_data* dd = (struct packed_rrset_data*) + ds_rrset->entry.data; + size_t ds_idx, num = dd->count; + int d = val_favorite_ds_algo(ds_rrset); + char* reason = ""; + for(ds_idx=0; ds_idxscratch_buffer); + size_t i; + if(!r) + return 0; + init_events(tp); + for(i=0; iname, LDNS_RR_TYPE_DNSKEY, tp->dclass); + continue; + } + + /* is it new? if revocation bit set, find the unrevoked key */ + if(!find_key(tp, rr, &ta)) { + ldns_rr_list_deep_free(r); /* malloc fail in compare*/ + return 0; + } + if(!ta) { + ta = add_key(tp, rr); + *changed = 1; + /* first time seen, do we have DSes? if match: VALID */ + if(ta && tp->ds_rrset && key_matches_a_ds(env, ve, + dnskey_rrset, i, tp->ds_rrset)) { + verbose_key(ta, VERB_ALGO, "verified by DS"); + ta->s = AUTR_STATE_VALID; + } + } + if(!ta) { + ldns_rr_list_deep_free(r); + return 0; + } + seen_trustanchor(ta, 1); + verbose_key(ta, VERB_ALGO, "in DNS response"); + } + set_tp_times(tp, min_expiry(env, r), key_ttl(dnskey_rrset), changed); + ldns_rr_list_deep_free(r); + return 1; +} + +/** + * Check if the holddown time has already exceeded + * setting: add-holddown: add holddown timer + * setting: del-holddown: del holddown timer + * @param env: environment with current time + * @param ta: trust anchor to check for. + * @param holddown: the timer value + * @return number of seconds the holddown has passed. + */ +static int +check_holddown(struct module_env* env, struct autr_ta* ta, + unsigned int holddown) +{ + unsigned int elapsed; + if((unsigned)*env->now < (unsigned)ta->last_change) { + log_warn("time goes backwards. delaying key holddown"); + return 0; + } + elapsed = (unsigned)*env->now - (unsigned)ta->last_change; + if (elapsed > holddown) { + return (int) (elapsed-holddown); + } + verbose_key(ta, VERB_ALGO, "holddown time %d seconds to go", + (int) (holddown-elapsed)); + return 0; +} + + +/** Set last_change to now */ +static void +reset_holddown(struct module_env* env, struct autr_ta* ta, int* changed) +{ + ta->last_change = *env->now; + *changed = 1; +} + +/** Set the state for this trust anchor */ +static void +set_trustanchor_state(struct module_env* env, struct autr_ta* ta, int* changed, + autr_state_t s) +{ + verbose_key(ta, VERB_ALGO, "update: %s to %s", + trustanchor_state2str(ta->s), trustanchor_state2str(s)); + ta->s = s; + reset_holddown(env, ta, changed); +} + + +/** Event: NewKey */ +static void +do_newkey(struct module_env* env, struct autr_ta* anchor, int* c) +{ + if (anchor->s == AUTR_STATE_START) + set_trustanchor_state(env, anchor, c, AUTR_STATE_ADDPEND); +} + +/** Event: AddTime */ +static void +do_addtime(struct module_env* env, struct autr_ta* anchor, int* c) +{ + /* This not according to RFC, this is 30 days, but the RFC demands + * MAX(30days, TTL expire time of first DNSKEY set with this key), + * The value may be too small if a very large TTL was used. */ + int exceeded = check_holddown(env, anchor, env->cfg->add_holddown); + if (exceeded && anchor->s == AUTR_STATE_ADDPEND) { + verbose_key(anchor, VERB_ALGO, "add-holddown time exceeded " + "%d seconds ago, and pending-count %d", exceeded, + anchor->pending_count); + if(anchor->pending_count >= MIN_PENDINGCOUNT) { + set_trustanchor_state(env, anchor, c, AUTR_STATE_VALID); + anchor->pending_count = 0; + return; + } + verbose_key(anchor, VERB_ALGO, "add-holddown time sanity check " + "failed (pending count: %d)", anchor->pending_count); + } +} + +/** Event: RemTime */ +static void +do_remtime(struct module_env* env, struct autr_ta* anchor, int* c) +{ + int exceeded = check_holddown(env, anchor, env->cfg->del_holddown); + if(exceeded && anchor->s == AUTR_STATE_REVOKED) { + verbose_key(anchor, VERB_ALGO, "del-holddown time exceeded " + "%d seconds ago", exceeded); + set_trustanchor_state(env, anchor, c, AUTR_STATE_REMOVED); + } +} + +/** Event: KeyRem */ +static void +do_keyrem(struct module_env* env, struct autr_ta* anchor, int* c) +{ + if(anchor->s == AUTR_STATE_ADDPEND) { + set_trustanchor_state(env, anchor, c, AUTR_STATE_START); + anchor->pending_count = 0; + } else if(anchor->s == AUTR_STATE_VALID) + set_trustanchor_state(env, anchor, c, AUTR_STATE_MISSING); +} + +/** Event: KeyPres */ +static void +do_keypres(struct module_env* env, struct autr_ta* anchor, int* c) +{ + if(anchor->s == AUTR_STATE_MISSING) + set_trustanchor_state(env, anchor, c, AUTR_STATE_VALID); +} + +/* Event: Revoked */ +static void +do_revoked(struct module_env* env, struct autr_ta* anchor, int* c) +{ + if(anchor->s == AUTR_STATE_VALID || anchor->s == AUTR_STATE_MISSING) { + set_trustanchor_state(env, anchor, c, AUTR_STATE_REVOKED); + verbose_key(anchor, VERB_ALGO, "old id, prior to revocation"); + revoke_dnskey(anchor, 0); + verbose_key(anchor, VERB_ALGO, "new id, after revocation"); + } +} + +/** Do statestable transition matrix for anchor */ +static void +anchor_state_update(struct module_env* env, struct autr_ta* anchor, int* c) +{ + log_assert(anchor); + switch(anchor->s) { + /* START */ + case AUTR_STATE_START: + /* NewKey: ADDPEND */ + if (anchor->fetched) + do_newkey(env, anchor, c); + break; + /* ADDPEND */ + case AUTR_STATE_ADDPEND: + /* KeyRem: START */ + if (!anchor->fetched) + do_keyrem(env, anchor, c); + /* AddTime: VALID */ + else do_addtime(env, anchor, c); + break; + /* VALID */ + case AUTR_STATE_VALID: + /* RevBit: REVOKED */ + if (anchor->revoked) + do_revoked(env, anchor, c); + /* KeyRem: MISSING */ + else if (!anchor->fetched) + do_keyrem(env, anchor, c); + else if(!anchor->last_change) { + verbose_key(anchor, VERB_ALGO, "first seen"); + reset_holddown(env, anchor, c); + } + break; + /* MISSING */ + case AUTR_STATE_MISSING: + /* RevBit: REVOKED */ + if (anchor->revoked) + do_revoked(env, anchor, c); + /* KeyPres */ + else if (anchor->fetched) + do_keypres(env, anchor, c); + break; + /* REVOKED */ + case AUTR_STATE_REVOKED: + if (anchor->fetched) + reset_holddown(env, anchor, c); + /* RemTime: REMOVED */ + else do_remtime(env, anchor, c); + break; + /* REMOVED */ + case AUTR_STATE_REMOVED: + default: + break; + } +} + +/** if ZSK init then trust KSKs */ +static int +init_zsk_to_ksk(struct module_env* env, struct trust_anchor* tp, int* changed) +{ + /* search for VALID ZSKs */ + struct autr_ta* anchor; + int validzsk = 0; + int validksk = 0; + for(anchor = tp->autr->keys; anchor; anchor = anchor->next) { + /* last_change test makes sure it was manually configured */ + if (ldns_rr_get_type(anchor->rr) == LDNS_RR_TYPE_DNSKEY && + anchor->last_change == 0 && + !rr_is_dnskey_sep(anchor->rr) && + anchor->s == AUTR_STATE_VALID) + validzsk++; + } + if(validzsk == 0) + return 0; + for(anchor = tp->autr->keys; anchor; anchor = anchor->next) { + if (rr_is_dnskey_sep(anchor->rr) && + anchor->s == AUTR_STATE_ADDPEND) { + verbose_key(anchor, VERB_ALGO, "trust KSK from " + "ZSK(config)"); + set_trustanchor_state(env, anchor, changed, + AUTR_STATE_VALID); + validksk++; + } + } + return validksk; +} + +/** Remove missing trustanchors so the list does not grow forever */ +static void +remove_missing_trustanchors(struct module_env* env, struct trust_anchor* tp, + int* changed) +{ + struct autr_ta* anchor; + int exceeded; + int valid = 0; + /* see if we have anchors that are valid */ + for(anchor = tp->autr->keys; anchor; anchor = anchor->next) { + /* Only do KSKs */ + if (!rr_is_dnskey_sep(anchor->rr)) + continue; + if (anchor->s == AUTR_STATE_VALID) + valid++; + } + /* if there are no SEP Valid anchors, see if we started out with + * a ZSK (last-change=0) anchor, which is VALID and there are KSKs + * now that can be made valid. Do this immediately because there + * is no guarantee that the ZSKs get announced long enough. Usually + * this is immediately after init with a ZSK trusted, unless the domain + * was not advertising any KSKs at all. In which case we perfectly + * track the zero number of KSKs. */ + if(valid == 0) { + valid = init_zsk_to_ksk(env, tp, changed); + if(valid == 0) + return; + } + + for(anchor = tp->autr->keys; anchor; anchor = anchor->next) { + /* ignore ZSKs if newly added */ + if(anchor->s == AUTR_STATE_START) + continue; + /* remove ZSKs if a KSK is present */ + if (!rr_is_dnskey_sep(anchor->rr)) { + if(valid > 0) { + verbose_key(anchor, VERB_ALGO, "remove ZSK " + "[%d key(s) VALID]", valid); + set_trustanchor_state(env, anchor, changed, + AUTR_STATE_REMOVED); + } + continue; + } + /* Only do MISSING keys */ + if (anchor->s != AUTR_STATE_MISSING) + continue; + if(env->cfg->keep_missing == 0) + continue; /* keep forever */ + + exceeded = check_holddown(env, anchor, env->cfg->keep_missing); + /* If keep_missing has exceeded and we still have more than + * one valid KSK: remove missing trust anchor */ + if (exceeded && valid > 0) { + verbose_key(anchor, VERB_ALGO, "keep-missing time " + "exceeded %d seconds ago, [%d key(s) VALID]", + exceeded, valid); + set_trustanchor_state(env, anchor, changed, + AUTR_STATE_REMOVED); + } + } +} + +/** Do the statetable from RFC5011 transition matrix */ +static int +do_statetable(struct module_env* env, struct trust_anchor* tp, int* changed) +{ + struct autr_ta* anchor; + for(anchor = tp->autr->keys; anchor; anchor = anchor->next) { + /* Only do KSKs */ + if(!rr_is_dnskey_sep(anchor->rr)) + continue; + anchor_state_update(env, anchor, changed); + } + remove_missing_trustanchors(env, tp, changed); + return 1; +} + +/** See if time alone makes ADDPEND to VALID transition */ +static void +autr_holddown_exceed(struct module_env* env, struct trust_anchor* tp, int* c) +{ + struct autr_ta* anchor; + for(anchor = tp->autr->keys; anchor; anchor = anchor->next) { + if(rr_is_dnskey_sep(anchor->rr) && + anchor->s == AUTR_STATE_ADDPEND) + do_addtime(env, anchor, c); + } +} + +/** cleanup key list */ +static void +autr_cleanup_keys(struct trust_anchor* tp) +{ + struct autr_ta* p, **prevp; + prevp = &tp->autr->keys; + p = tp->autr->keys; + while(p) { + /* do we want to remove this key? */ + if(p->s == AUTR_STATE_START || p->s == AUTR_STATE_REMOVED || + ldns_rr_get_type(p->rr) != LDNS_RR_TYPE_DNSKEY) { + struct autr_ta* np = p->next; + /* remove */ + ldns_rr_free(p->rr); + free(p); + /* snip and go to next item */ + *prevp = np; + p = np; + continue; + } + /* remove pending counts if no longer pending */ + if(p->s != AUTR_STATE_ADDPEND) + p->pending_count = 0; + prevp = &p->next; + p = p->next; + } +} + +/** calculate next probe time */ +static time_t +calc_next_probe(struct module_env* env, uint32_t wait) +{ + /* make it random, 90-100% */ + uint32_t rnd, rest; + if(wait < 3600) + wait = 3600; + rnd = wait/10; + rest = wait-rnd; + rnd = (uint32_t)ub_random_max(env->rnd, (long int)rnd); + return (time_t)(*env->now + rest + rnd); +} + +/** what is first probe time (anchors must be locked) */ +static time_t +wait_probe_time(struct val_anchors* anchors) +{ + rbnode_t* t = rbtree_first(&anchors->autr->probe); + if(t != RBTREE_NULL) + return ((struct trust_anchor*)t->key)->autr->next_probe_time; + return 0; +} + +/** reset worker timer */ +static void +reset_worker_timer(struct module_env* env) +{ + struct timeval tv; +#ifndef S_SPLINT_S + uint32_t next = (uint32_t)wait_probe_time(env->anchors); + /* in case this is libunbound, no timer */ + if(!env->probe_timer) + return; + if(next > *env->now) + tv.tv_sec = (time_t)(next - *env->now); + else tv.tv_sec = 0; +#endif + tv.tv_usec = 0; + comm_timer_set(env->probe_timer, &tv); + verbose(VERB_ALGO, "scheduled next probe in %d sec", (int)tv.tv_sec); +} + +/** set next probe for trust anchor */ +static int +set_next_probe(struct module_env* env, struct trust_anchor* tp, + struct ub_packed_rrset_key* dnskey_rrset) +{ + struct trust_anchor key, *tp2; + time_t mold, mnew; + /* use memory allocated in rrset for temporary name storage */ + key.node.key = &key; + key.name = dnskey_rrset->rk.dname; + key.namelen = dnskey_rrset->rk.dname_len; + key.namelabs = dname_count_labels(key.name); + key.dclass = tp->dclass; + lock_basic_unlock(&tp->lock); + + /* fetch tp again and lock anchors, so that we can modify the trees */ + lock_basic_lock(&env->anchors->lock); + tp2 = (struct trust_anchor*)rbtree_search(env->anchors->tree, &key); + if(!tp2) { + verbose(VERB_ALGO, "trustpoint was deleted in set_next_probe"); + lock_basic_unlock(&env->anchors->lock); + return 0; + } + log_assert(tp == tp2); + lock_basic_lock(&tp->lock); + + /* schedule */ + mold = wait_probe_time(env->anchors); + (void)rbtree_delete(&env->anchors->autr->probe, tp); + tp->autr->next_probe_time = calc_next_probe(env, + tp->autr->query_interval); + (void)rbtree_insert(&env->anchors->autr->probe, &tp->autr->pnode); + mnew = wait_probe_time(env->anchors); + + lock_basic_unlock(&env->anchors->lock); + verbose(VERB_ALGO, "next probe set in %d seconds", + (int)tp->autr->next_probe_time - (int)*env->now); + if(mold != mnew) { + reset_worker_timer(env); + } + return 1; +} + +/** Revoke and Delete a trust point */ +static void +autr_tp_remove(struct module_env* env, struct trust_anchor* tp, + struct ub_packed_rrset_key* dnskey_rrset) +{ + struct trust_anchor key; + struct autr_point_data pd; + time_t mold, mnew; + + log_nametypeclass(VERB_OPS, "trust point was revoked", + tp->name, LDNS_RR_TYPE_DNSKEY, tp->dclass); + tp->autr->revoked = 1; + + /* use space allocated for dnskey_rrset to save name of anchor */ + memset(&key, 0, sizeof(key)); + memset(&pd, 0, sizeof(pd)); + key.autr = &pd; + key.node.key = &key; + pd.pnode.key = &key; + pd.next_probe_time = tp->autr->next_probe_time; + key.name = dnskey_rrset->rk.dname; + key.namelen = tp->namelen; + key.namelabs = tp->namelabs; + key.dclass = tp->dclass; + + /* unlock */ + lock_basic_unlock(&tp->lock); + + /* take from tree. It could be deleted by someone else,hence (void). */ + lock_basic_lock(&env->anchors->lock); + (void)rbtree_delete(env->anchors->tree, &key); + mold = wait_probe_time(env->anchors); + (void)rbtree_delete(&env->anchors->autr->probe, &key); + mnew = wait_probe_time(env->anchors); + anchors_init_parents_locked(env->anchors); + lock_basic_unlock(&env->anchors->lock); + + /* save on disk */ + tp->autr->next_probe_time = 0; /* no more probing for it */ + autr_write_file(env, tp); + + /* delete */ + autr_point_delete(tp); + if(mold != mnew) { + reset_worker_timer(env); + } +} + +int autr_process_prime(struct module_env* env, struct val_env* ve, + struct trust_anchor* tp, struct ub_packed_rrset_key* dnskey_rrset) +{ + int changed = 0; + log_assert(tp && tp->autr); + /* autotrust update trust anchors */ + /* the tp is locked, and stays locked unless it is deleted */ + + /* we could just catch the anchor here while another thread + * is busy deleting it. Just unlock and let the other do its job */ + if(tp->autr->revoked) { + log_nametypeclass(VERB_ALGO, "autotrust not processed, " + "trust point revoked", tp->name, + LDNS_RR_TYPE_DNSKEY, tp->dclass); + lock_basic_unlock(&tp->lock); + return 0; /* it is revoked */ + } + + /* query_dnskeys(): */ + tp->autr->last_queried = *env->now; + + log_nametypeclass(VERB_ALGO, "autotrust process for", + tp->name, LDNS_RR_TYPE_DNSKEY, tp->dclass); + /* see if time alone makes some keys valid */ + autr_holddown_exceed(env, tp, &changed); + if(changed) { + verbose(VERB_ALGO, "autotrust: morekeys, reassemble"); + if(!autr_assemble(tp)) { + log_err("malloc failure assembling autotrust keys"); + return 1; /* unchanged */ + } + } + /* did we get any data? */ + if(!dnskey_rrset) { + verbose(VERB_ALGO, "autotrust: no dnskey rrset"); + /* no update of query_failed, because then we would have + * to write to disk. But we cannot because we maybe are + * still 'initialising' with DS records, that we cannot write + * in the full format (which only contains KSKs). */ + return 1; /* trust point exists */ + } + /* check for revoked keys to remove immediately */ + check_contains_revoked(env, ve, tp, dnskey_rrset, &changed); + if(changed) { + verbose(VERB_ALGO, "autotrust: revokedkeys, reassemble"); + if(!autr_assemble(tp)) { + log_err("malloc failure assembling autotrust keys"); + return 1; /* unchanged */ + } + if(!tp->ds_rrset && !tp->dnskey_rrset) { + /* no more keys, all are revoked */ + /* this is a success for this probe attempt */ + tp->autr->last_success = *env->now; + autr_tp_remove(env, tp, dnskey_rrset); + return 0; /* trust point removed */ + } + } + /* verify the dnskey rrset and see if it is valid. */ + if(!verify_dnskey(env, ve, tp, dnskey_rrset)) { + verbose(VERB_ALGO, "autotrust: dnskey did not verify."); + /* only increase failure count if this is not the first prime, + * this means there was a previous succesful probe */ + if(tp->autr->last_success) { + tp->autr->query_failed += 1; + autr_write_file(env, tp); + } + return 1; /* trust point exists */ + } + + tp->autr->last_success = *env->now; + tp->autr->query_failed = 0; + + /* Add new trust anchors to the data structure + * - note which trust anchors are seen this probe. + * Set trustpoint query_interval and retry_time. + * - find minimum rrsig expiration interval + */ + if(!update_events(env, ve, tp, dnskey_rrset, &changed)) { + log_err("malloc failure in autotrust update_events. " + "trust point unchanged."); + return 1; /* trust point unchanged, so exists */ + } + + /* - for every SEP key do the 5011 statetable. + * - remove missing trustanchors (if veryold and we have new anchors). + */ + if(!do_statetable(env, tp, &changed)) { + log_err("malloc failure in autotrust do_statetable. " + "trust point unchanged."); + return 1; /* trust point unchanged, so exists */ + } + + autr_cleanup_keys(tp); + if(!set_next_probe(env, tp, dnskey_rrset)) + return 0; /* trust point does not exist */ + autr_write_file(env, tp); + if(changed) { + verbose(VERB_ALGO, "autotrust: changed, reassemble"); + if(!autr_assemble(tp)) { + log_err("malloc failure assembling autotrust keys"); + return 1; /* unchanged */ + } + if(!tp->ds_rrset && !tp->dnskey_rrset) { + /* no more keys, all are revoked */ + autr_tp_remove(env, tp, dnskey_rrset); + return 0; /* trust point removed */ + } + } else verbose(VERB_ALGO, "autotrust: no changes"); + + return 1; /* trust point exists */ +} + +/** debug print a trust anchor key */ +static void +autr_debug_print_ta(struct autr_ta* ta) +{ + char buf[32]; + char* str = ldns_rr2str(ta->rr); + if(!str) { + log_info("out of memory in debug_print_ta"); + return; + } + if(str && str[0]) str[strlen(str)-1]=0; /* remove newline */ + ctime_r(&ta->last_change, buf); + if(buf[0]) buf[strlen(buf)-1]=0; /* remove newline */ + log_info("[%s] %s ;;state:%d ;;pending_count:%d%s%s last:%s", + trustanchor_state2str(ta->s), str, ta->s, ta->pending_count, + ta->fetched?" fetched":"", ta->revoked?" revoked":"", buf); + free(str); +} + +/** debug print a trust point */ +static void +autr_debug_print_tp(struct trust_anchor* tp) +{ + struct autr_ta* ta; + char buf[257]; + if(!tp->autr) + return; + dname_str(tp->name, buf); + log_info("trust point %s : %d", buf, (int)tp->dclass); + log_info("assembled %d DS and %d DNSKEYs", + (int)tp->numDS, (int)tp->numDNSKEY); + if(0) { /* turned off because it prints to stderr */ + ldns_buffer* bf = ldns_buffer_new(70000); + ldns_rr_list* list; + if(tp->ds_rrset) { + list = packed_rrset_to_rr_list(tp->ds_rrset, bf); + ldns_rr_list_print(stderr, list); + ldns_rr_list_deep_free(list); + } + if(tp->dnskey_rrset) { + list = packed_rrset_to_rr_list(tp->dnskey_rrset, bf); + ldns_rr_list_print(stderr, list); + ldns_rr_list_deep_free(list); + } + ldns_buffer_free(bf); + } + log_info("file %s", tp->autr->file); + ctime_r(&tp->autr->last_queried, buf); + if(buf[0]) buf[strlen(buf)-1]=0; /* remove newline */ + log_info("last_queried: %u %s", (unsigned)tp->autr->last_queried, buf); + ctime_r(&tp->autr->last_success, buf); + if(buf[0]) buf[strlen(buf)-1]=0; /* remove newline */ + log_info("last_success: %u %s", (unsigned)tp->autr->last_success, buf); + ctime_r(&tp->autr->next_probe_time, buf); + if(buf[0]) buf[strlen(buf)-1]=0; /* remove newline */ + log_info("next_probe_time: %u %s", (unsigned)tp->autr->next_probe_time, + buf); + log_info("query_interval: %u", (unsigned)tp->autr->query_interval); + log_info("retry_time: %u", (unsigned)tp->autr->retry_time); + log_info("query_failed: %u", (unsigned)tp->autr->query_failed); + + for(ta=tp->autr->keys; ta; ta=ta->next) { + autr_debug_print_ta(ta); + } +} + +void +autr_debug_print(struct val_anchors* anchors) +{ + struct trust_anchor* tp; + lock_basic_lock(&anchors->lock); + RBTREE_FOR(tp, struct trust_anchor*, anchors->tree) { + lock_basic_lock(&tp->lock); + autr_debug_print_tp(tp); + lock_basic_unlock(&tp->lock); + } + lock_basic_unlock(&anchors->lock); +} + +void probe_answer_cb(void* arg, int ATTR_UNUSED(rcode), + ldns_buffer* ATTR_UNUSED(buf), enum sec_status ATTR_UNUSED(sec), + char* ATTR_UNUSED(why_bogus)) +{ + /* retry was set before the query was done, + * re-querytime is set when query succeeded, but that may not + * have reset this timer because the query could have been + * handled by another thread. In that case, this callback would + * get called after the original timeout is done. + * By not resetting the timer, it may probe more often, but not + * less often. + * Unless the new lookup resulted in smaller TTLs and thus smaller + * timeout values. In that case one old TTL could be mistakenly done. + */ + struct module_env* env = (struct module_env*)arg; + verbose(VERB_ALGO, "autotrust probe answer cb"); + reset_worker_timer(env); +} + +/** probe a trust anchor DNSKEY and unlocks tp */ +static void +probe_anchor(struct module_env* env, struct trust_anchor* tp) +{ + struct query_info qinfo; + uint16_t qflags = BIT_RD; + struct edns_data edns; + ldns_buffer* buf = env->scratch_buffer; + qinfo.qname = regional_alloc_init(env->scratch, tp->name, tp->namelen); + if(!qinfo.qname) { + log_err("out of memory making 5011 probe"); + return; + } + qinfo.qname_len = tp->namelen; + qinfo.qtype = LDNS_RR_TYPE_DNSKEY; + qinfo.qclass = tp->dclass; + log_query_info(VERB_ALGO, "autotrust probe", &qinfo); + verbose(VERB_ALGO, "retry probe set in %d seconds", + (int)tp->autr->next_probe_time - (int)*env->now); + edns.edns_present = 1; + edns.ext_rcode = 0; + edns.edns_version = 0; + edns.bits = EDNS_DO; + if(ldns_buffer_capacity(buf) < 65535) + edns.udp_size = (uint16_t)ldns_buffer_capacity(buf); + else edns.udp_size = 65535; + + /* can't hold the lock while mesh_run is processing */ + lock_basic_unlock(&tp->lock); + + /* delete the DNSKEY from rrset and key cache so an active probe + * is done. First the rrset so another thread does not use it + * to recreate the key entry in a race condition. */ + rrset_cache_remove(env->rrset_cache, qinfo.qname, qinfo.qname_len, + qinfo.qtype, qinfo.qclass, 0); + key_cache_remove(env->key_cache, qinfo.qname, qinfo.qname_len, + qinfo.qclass); + + if(!mesh_new_callback(env->mesh, &qinfo, qflags, &edns, buf, 0, + &probe_answer_cb, env)) { + log_err("out of memory making 5011 probe"); + } +} + +/** fetch first to-probe trust-anchor and lock it and set retrytime */ +static struct trust_anchor* +todo_probe(struct module_env* env, uint32_t* next) +{ + struct trust_anchor* tp; + rbnode_t* el; + /* get first one */ + lock_basic_lock(&env->anchors->lock); + if( (el=rbtree_first(&env->anchors->autr->probe)) == RBTREE_NULL) { + /* in case of revoked anchors */ + lock_basic_unlock(&env->anchors->lock); + return NULL; + } + tp = (struct trust_anchor*)el->key; + lock_basic_lock(&tp->lock); + + /* is it eligible? */ + if((uint32_t)tp->autr->next_probe_time > *env->now) { + /* no more to probe */ + *next = (uint32_t)tp->autr->next_probe_time - *env->now; + lock_basic_unlock(&tp->lock); + lock_basic_unlock(&env->anchors->lock); + return NULL; + } + + /* reset its next probe time */ + (void)rbtree_delete(&env->anchors->autr->probe, tp); + tp->autr->next_probe_time = calc_next_probe(env, tp->autr->retry_time); + (void)rbtree_insert(&env->anchors->autr->probe, &tp->autr->pnode); + lock_basic_unlock(&env->anchors->lock); + + return tp; +} + +uint32_t +autr_probe_timer(struct module_env* env) +{ + struct trust_anchor* tp; + uint32_t next_probe = 3600; + int num = 0; + verbose(VERB_ALGO, "autotrust probe timer callback"); + /* while there are still anchors to probe */ + while( (tp = todo_probe(env, &next_probe)) ) { + /* make a probe for this anchor */ + probe_anchor(env, tp); + num++; + } + regional_free_all(env->scratch); + if(num == 0) + return 0; /* no trust points to probe */ + verbose(VERB_ALGO, "autotrust probe timer %d callbacks done", num); + return next_probe; +} diff --git a/validator/autotrust.h b/validator/autotrust.h new file mode 100644 index 00000000000..4e88ed32042 --- /dev/null +++ b/validator/autotrust.h @@ -0,0 +1,205 @@ +/* + * validator/autotrust.h - RFC5011 trust anchor management for unbound. + * + * Copyright (c) 2009, 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * Contains autotrust definitions. + */ + +#ifndef VALIDATOR_AUTOTRUST_H +#define VALIDATOR_AUTOTRUST_H +#include "util/rbtree.h" +#include "util/data/packed_rrset.h" +struct val_anchors; +struct trust_anchor; +struct ub_packed_rrset_key; +struct module_env; +struct val_env; + +/** Autotrust anchor states */ +typedef enum { + AUTR_STATE_START = 0, + AUTR_STATE_ADDPEND = 1, + AUTR_STATE_VALID = 2, + AUTR_STATE_MISSING = 3, + AUTR_STATE_REVOKED = 4, + AUTR_STATE_REMOVED = 5 +} autr_state_t; + +/** + * Autotrust metadata for one trust anchor key. + */ +struct autr_ta { + /** next key */ + struct autr_ta* next; + /** the RR */ + ldns_rr* rr; + /** last update of key state (new pending count keeps date the same) */ + time_t last_change; + /** 5011 state */ + autr_state_t s; + /** pending count */ + uint8_t pending_count; + /** fresh TA was seen */ + uint8_t fetched; + /** revoked TA was seen */ + uint8_t revoked; +}; + +/** + * Autotrust metadata for a trust point. + * This is part of the struct trust_anchor data. + */ +struct autr_point_data { + /** file to store the trust point in. chrootdir already applied. */ + char* file; + /** rbtree node for probe sort, key is struct trust_anchor */ + rbnode_t pnode; + + /** the keys */ + struct autr_ta* keys; + + /** last queried DNSKEY set + * Not all failures are captured in this entry. + * If the validator did not even start (e.g. timeout or localservfail), + * then the last_queried and query_failed values are not updated. + */ + time_t last_queried; + /** last successful DNSKEY set */ + time_t last_success; + /** next probe time */ + time_t next_probe_time; + + /** when to query if !failed */ + uint32_t query_interval; + /** when to retry if failed */ + uint32_t retry_time; + + /** + * How many times did it fail. diagnostic only (has no effect). + * Only updated if there was a dnskey rrset that failed to verify. + */ + uint8_t query_failed; + /** true if the trust point has been revoked */ + uint8_t revoked; +}; + +/** + * Autotrust global metadata. + */ +struct autr_global_data { + /** rbtree of autotrust anchors sorted by next probe time. + * When time is equal, sorted by anchor class, name. */ + rbtree_t probe; +}; + +/** + * Create new global 5011 data structure. + * @return new structure or NULL on malloc failure. + */ +struct autr_global_data* autr_global_create(void); + +/** + * Delete global 5011 data structure. + * @param global: global autotrust state to delete. + */ +void autr_global_delete(struct autr_global_data* global); + +/** + * See if autotrust anchors are configured and how many. + * @param anchors: the trust anchors structure. + * @return number of autotrust trust anchors + */ +size_t autr_get_num_anchors(struct val_anchors* anchors); + +/** + * Process probe timer. Add new probes if needed. + * @param env: module environment with time, with anchors and with the mesh. + * @return time of next probe (in seconds from now). + * If 0, then there is no next probe anymore (trust points deleted). + */ +uint32_t autr_probe_timer(struct module_env* env); + +/** probe tree compare function */ +int probetree_cmp(const void* x, const void* y); + +/** + * Read autotrust file. + * @param anchors: the anchors structure. + * @param nm: name of the file (copied). + * @return false on failure. + */ +int autr_read_file(struct val_anchors* anchors, const char* nm); + +/** + * Write autotrust file. + * @param env: environment with scratch space. + * @param tp: trust point to write. + */ +void autr_write_file(struct module_env* env, struct trust_anchor* tp); + +/** + * Delete autr anchor, deletes the autr data but does not do + * unlinking from trees, caller does that. + * @param tp: trust point to delete. + */ +void autr_point_delete(struct trust_anchor* tp); + +/** + * Perform autotrust processing. + * @param env: qstate environment with the anchors structure. + * @param ve: validator environment for verification of rrsigs. + * @param tp: trust anchor to process. + * @param dnskey_rrset: DNSKEY rrset probed (can be NULL if bad prime result). + * allocated in a region. Has not been validated yet. + * @return false if trust anchor was revoked completely. + * Otherwise logs errors to log, does not change return value. + * On errors, likely the trust point has been unchanged. + */ +int autr_process_prime(struct module_env* env, struct val_env* ve, + struct trust_anchor* tp, struct ub_packed_rrset_key* dnskey_rrset); + +/** + * Debug printout of rfc5011 tracked anchors + * @param anchors: all the anchors. + */ +void autr_debug_print(struct val_anchors* anchors); + +/** callback for query answer to 5011 probe */ +void probe_answer_cb(void* arg, int rcode, ldns_buffer* buf, + enum sec_status sec, char* errinf); + +#endif /* VALIDATOR_AUTOTRUST_H */ diff --git a/validator/val_anchor.c b/validator/val_anchor.c new file mode 100644 index 00000000000..200bf5d97be --- /dev/null +++ b/validator/val_anchor.c @@ -0,0 +1,1263 @@ +/* + * validator/val_anchor.c - validator trust anchor storage. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains storage for the trust anchors for the validator. + */ +#include "config.h" +#include +#include +#include +#include "validator/val_anchor.h" +#include "validator/val_sigcrypt.h" +#include "validator/autotrust.h" +#include "util/data/packed_rrset.h" +#include "util/data/dname.h" +#include "util/log.h" +#include "util/net_help.h" +#include "util/config_file.h" +#ifdef HAVE_GLOB_H +#include +#endif + +int +anchor_cmp(const void* k1, const void* k2) +{ + int m; + struct trust_anchor* n1 = (struct trust_anchor*)k1; + struct trust_anchor* n2 = (struct trust_anchor*)k2; + /* no need to ntohs(class) because sort order is irrelevant */ + if(n1->dclass != n2->dclass) { + if(n1->dclass < n2->dclass) + return -1; + return 1; + } + return dname_lab_cmp(n1->name, n1->namelabs, n2->name, n2->namelabs, + &m); +} + +struct val_anchors* +anchors_create(void) +{ + struct val_anchors* a = (struct val_anchors*)calloc(1, sizeof(*a)); + if(!a) + return NULL; + a->tree = rbtree_create(anchor_cmp); + if(!a->tree) { + anchors_delete(a); + return NULL; + } + a->autr = autr_global_create(); + if(!a->autr) { + anchors_delete(a); + return NULL; + } + lock_basic_init(&a->lock); + lock_protect(&a->lock, a, sizeof(*a)); + lock_protect(&a->lock, a->autr, sizeof(*a->autr)); + return a; +} + +/** delete assembled rrset */ +static void +assembled_rrset_delete(struct ub_packed_rrset_key* pkey) +{ + if(!pkey) return; + if(pkey->entry.data) { + struct packed_rrset_data* pd = (struct packed_rrset_data*) + pkey->entry.data; + free(pd->rr_data); + free(pd->rr_ttl); + free(pd->rr_len); + free(pd); + } + free(pkey->rk.dname); + free(pkey); +} + +/** destroy locks in tree and delete autotrust anchors */ +static void +anchors_delfunc(rbnode_t* elem, void* ATTR_UNUSED(arg)) +{ + struct trust_anchor* ta = (struct trust_anchor*)elem; + if(!ta) return; + if(ta->autr) { + autr_point_delete(ta); + } else { + struct ta_key* p, *np; + lock_basic_destroy(&ta->lock); + free(ta->name); + p = ta->keylist; + while(p) { + np = p->next; + free(p->data); + free(p); + p = np; + } + assembled_rrset_delete(ta->ds_rrset); + assembled_rrset_delete(ta->dnskey_rrset); + free(ta); + } +} + +void +anchors_delete(struct val_anchors* anchors) +{ + if(!anchors) + return; + lock_unprotect(&anchors->lock, anchors->autr); + lock_unprotect(&anchors->lock, anchors); + lock_basic_destroy(&anchors->lock); + if(anchors->tree) + traverse_postorder(anchors->tree, anchors_delfunc, NULL); + free(anchors->tree); + autr_global_delete(anchors->autr); + free(anchors); +} + +void +anchors_init_parents_locked(struct val_anchors* anchors) +{ + struct trust_anchor* node, *prev = NULL, *p; + int m; + /* nobody else can grab locks because we hold the main lock. + * Thus the previous items, after unlocked, are not deleted */ + RBTREE_FOR(node, struct trust_anchor*, anchors->tree) { + lock_basic_lock(&node->lock); + node->parent = NULL; + if(!prev || prev->dclass != node->dclass) { + prev = node; + lock_basic_unlock(&node->lock); + continue; + } + (void)dname_lab_cmp(prev->name, prev->namelabs, node->name, + node->namelabs, &m); /* we know prev is smaller */ + /* sort order like: . com. bla.com. zwb.com. net. */ + /* find the previous, or parent-parent-parent */ + for(p = prev; p; p = p->parent) + /* looking for name with few labels, a parent */ + if(p->namelabs <= m) { + /* ==: since prev matched m, this is closest*/ + /* <: prev matches more, but is not a parent, + * this one is a (grand)parent */ + node->parent = p; + break; + } + lock_basic_unlock(&node->lock); + prev = node; + } +} + +/** initialise parent pointers in the tree */ +static void +init_parents(struct val_anchors* anchors) +{ + lock_basic_lock(&anchors->lock); + anchors_init_parents_locked(anchors); + lock_basic_unlock(&anchors->lock); +} + +struct trust_anchor* +anchor_find(struct val_anchors* anchors, uint8_t* name, int namelabs, + size_t namelen, uint16_t dclass) +{ + struct trust_anchor key; + rbnode_t* n; + if(!name) return NULL; + key.node.key = &key; + key.name = name; + key.namelabs = namelabs; + key.namelen = namelen; + key.dclass = dclass; + lock_basic_lock(&anchors->lock); + n = rbtree_search(anchors->tree, &key); + if(n) { + lock_basic_lock(&((struct trust_anchor*)n->key)->lock); + } + lock_basic_unlock(&anchors->lock); + if(!n) + return NULL; + return (struct trust_anchor*)n->key; +} + +/** create new trust anchor object */ +static struct trust_anchor* +anchor_new_ta(struct val_anchors* anchors, uint8_t* name, int namelabs, + size_t namelen, uint16_t dclass, int lockit) +{ +#ifdef UNBOUND_DEBUG + rbnode_t* r; +#endif + struct trust_anchor* ta = (struct trust_anchor*)malloc( + sizeof(struct trust_anchor)); + if(!ta) + return NULL; + memset(ta, 0, sizeof(*ta)); + ta->node.key = ta; + ta->name = memdup(name, namelen); + if(!ta->name) { + free(ta); + return NULL; + } + ta->namelabs = namelabs; + ta->namelen = namelen; + ta->dclass = dclass; + lock_basic_init(&ta->lock); + if(lockit) { + lock_basic_lock(&anchors->lock); + } +#ifdef UNBOUND_DEBUG + r = +#endif + rbtree_insert(anchors->tree, &ta->node); + if(lockit) { + lock_basic_unlock(&anchors->lock); + } + log_assert(r != NULL); + return ta; +} + +/** find trustanchor key by exact data match */ +static struct ta_key* +anchor_find_key(struct trust_anchor* ta, uint8_t* rdata, size_t rdata_len, + uint16_t type) +{ + struct ta_key* k; + for(k = ta->keylist; k; k = k->next) { + if(k->type == type && k->len == rdata_len && + memcmp(k->data, rdata, rdata_len) == 0) + return k; + } + return NULL; +} + +/** create new trustanchor key */ +static struct ta_key* +anchor_new_ta_key(uint8_t* rdata, size_t rdata_len, uint16_t type) +{ + struct ta_key* k = (struct ta_key*)malloc(sizeof(*k)); + if(!k) + return NULL; + memset(k, 0, sizeof(*k)); + k->data = memdup(rdata, rdata_len); + if(!k->data) { + free(k); + return NULL; + } + k->len = rdata_len; + k->type = type; + return k; +} + +/** + * This routine adds a new RR to a trust anchor. The trust anchor may not + * exist yet, and is created if not. The RR can be DS or DNSKEY. + * This routine will also remove duplicates; storing them only once. + * @param anchors: anchor storage. + * @param name: name of trust anchor (wireformat) + * @param type: type or RR + * @param dclass: class of RR + * @param rdata: rdata wireformat, starting with rdlength. + * If NULL, nothing is stored, but an entry is created. + * @param rdata_len: length of rdata including rdlength. + * @return: NULL on error, else the trust anchor. + */ +static struct trust_anchor* +anchor_store_new_key(struct val_anchors* anchors, uint8_t* name, uint16_t type, + uint16_t dclass, uint8_t* rdata, size_t rdata_len) +{ + struct ta_key* k; + struct trust_anchor* ta; + int namelabs; + size_t namelen; + namelabs = dname_count_size_labels(name, &namelen); + if(type != LDNS_RR_TYPE_DS && type != LDNS_RR_TYPE_DNSKEY) { + log_err("Bad type for trust anchor"); + return 0; + } + /* lookup or create trustanchor */ + ta = anchor_find(anchors, name, namelabs, namelen, dclass); + if(!ta) { + ta = anchor_new_ta(anchors, name, namelabs, namelen, dclass, 1); + if(!ta) + return NULL; + lock_basic_lock(&ta->lock); + } + if(!rdata) { + lock_basic_unlock(&ta->lock); + return ta; + } + /* look for duplicates */ + if(anchor_find_key(ta, rdata, rdata_len, type)) { + lock_basic_unlock(&ta->lock); + return ta; + } + k = anchor_new_ta_key(rdata, rdata_len, type); + if(!k) { + lock_basic_unlock(&ta->lock); + return NULL; + } + /* add new key */ + if(type == LDNS_RR_TYPE_DS) + ta->numDS++; + else ta->numDNSKEY++; + k->next = ta->keylist; + ta->keylist = k; + lock_basic_unlock(&ta->lock); + return ta; +} + +/** + * Add new RR. It converts ldns RR to wire format. + * @param anchors: anchor storage. + * @param buffer: parsing buffer. + * @param rr: the rr (allocated by caller). + * @return NULL on error, else the trust anchor. + */ +static struct trust_anchor* +anchor_store_new_rr(struct val_anchors* anchors, ldns_buffer* buffer, + ldns_rr* rr) +{ + struct trust_anchor* ta; + ldns_rdf* owner = ldns_rr_owner(rr); + ldns_status status; + ldns_buffer_clear(buffer); + ldns_buffer_skip(buffer, 2); /* skip rdatalen */ + status = ldns_rr_rdata2buffer_wire(buffer, rr); + if(status != LDNS_STATUS_OK) { + log_err("error converting trustanchor to wireformat: %s", + ldns_get_errorstr_by_id(status)); + return NULL; + } + ldns_buffer_flip(buffer); + ldns_buffer_write_u16_at(buffer, 0, ldns_buffer_limit(buffer) - 2); + + if(!(ta=anchor_store_new_key(anchors, ldns_rdf_data(owner), + ldns_rr_get_type(rr), ldns_rr_get_class(rr), + ldns_buffer_begin(buffer), ldns_buffer_limit(buffer)))) { + return NULL; + } + log_nametypeclass(VERB_QUERY, "adding trusted key", + ldns_rdf_data(owner), + ldns_rr_get_type(rr), ldns_rr_get_class(rr)); + return ta; +} + +/** + * Insert insecure anchor + * @param anchors: anchor storage. + * @param str: the domain name. + * @return NULL on error, Else last trust anchor point + */ +static struct trust_anchor* +anchor_insert_insecure(struct val_anchors* anchors, const char* str) +{ + struct trust_anchor* ta; + ldns_rdf* nm = ldns_dname_new_frm_str(str); + if(!nm) { + log_err("parse error in domain name '%s'", str); + return NULL; + } + ta = anchor_store_new_key(anchors, ldns_rdf_data(nm), LDNS_RR_TYPE_DS, + LDNS_RR_CLASS_IN, NULL, 0); + ldns_rdf_deep_free(nm); + return ta; +} + +struct trust_anchor* +anchor_store_str(struct val_anchors* anchors, ldns_buffer* buffer, + const char* str) +{ + struct trust_anchor* ta; + ldns_rr* rr = NULL; + ldns_status status = ldns_rr_new_frm_str(&rr, str, 0, NULL, NULL); + if(status != LDNS_STATUS_OK) { + log_err("error parsing trust anchor: %s", + ldns_get_errorstr_by_id(status)); + ldns_rr_free(rr); + return NULL; + } + if(!(ta=anchor_store_new_rr(anchors, buffer, rr))) { + log_err("out of memory"); + ldns_rr_free(rr); + return NULL; + } + ldns_rr_free(rr); + return ta; +} + +/** + * Read a file with trust anchors + * @param anchors: anchor storage. + * @param buffer: parsing buffer. + * @param fname: string. + * @param onlyone: only one trust anchor allowed in file. + * @return NULL on error. Else last trust-anchor point. + */ +static struct trust_anchor* +anchor_read_file(struct val_anchors* anchors, ldns_buffer* buffer, + const char* fname, int onlyone) +{ + struct trust_anchor* ta = NULL, *tanew; + uint32_t default_ttl = 3600; + ldns_rdf* origin = NULL, *prev = NULL; + int line_nr = 1; + ldns_status status; + ldns_rr* rr; + int ok = 1; + FILE* in = fopen(fname, "r"); + if(!in) { + log_err("error opening file %s: %s", fname, strerror(errno)); + return 0; + } + while(!feof(in)) { + rr = NULL; + status = ldns_rr_new_frm_fp_l(&rr, in, &default_ttl, &origin, + &prev, &line_nr); + if(status == LDNS_STATUS_SYNTAX_EMPTY /* empty line */ + || status == LDNS_STATUS_SYNTAX_TTL /* $TTL */ + || status == LDNS_STATUS_SYNTAX_ORIGIN /* $ORIGIN */) + continue; + if(status != LDNS_STATUS_OK) { + log_err("parse error in %s:%d : %s", fname, line_nr, + ldns_get_errorstr_by_id(status)); + ldns_rr_free(rr); + ok = 0; + break; + } + if(ldns_rr_get_type(rr) != LDNS_RR_TYPE_DS && + ldns_rr_get_type(rr) != LDNS_RR_TYPE_DNSKEY) { + ldns_rr_free(rr); + continue; + } + if(!(tanew=anchor_store_new_rr(anchors, buffer, rr))) { + log_err("error at %s line %d", fname, line_nr); + ldns_rr_free(rr); + ok = 0; + break; + } + if(onlyone && ta && ta != tanew) { + log_err("error at %s line %d: no multiple anchor " + "domains allowed (you can have multiple " + "keys, but they must have the same name).", + fname, line_nr); + ldns_rr_free(rr); + ok = 0; + break; + } + ta = tanew; + ldns_rr_free(rr); + } + ldns_rdf_deep_free(origin); + ldns_rdf_deep_free(prev); + fclose(in); + if(!ok) return NULL; + /* empty file is OK when multiple anchors are allowed */ + if(!onlyone && !ta) return (struct trust_anchor*)1; + return ta; +} + +/** skip file to end of line */ +static void +skip_to_eol(FILE* in) +{ + int c; + while((c = getc(in)) != EOF ) { + if(c == '\n') + return; + } +} + +/** true for special characters in bind configs */ +static int +is_bind_special(int c) +{ + switch(c) { + case '{': + case '}': + case '"': + case ';': + return 1; + } + return 0; +} + +/** + * Read a keyword skipping bind comments; spaces, specials, restkeywords. + * The file is split into the following tokens: + * * special characters, on their own, rdlen=1, { } doublequote ; + * * whitespace becomes a single ' ' or tab. Newlines become spaces. + * * other words ('keywords') + * * comments are skipped if desired + * / / C++ style comment to end of line + * # to end of line + * / * C style comment * / + * @param in: file to read from. + * @param buf: buffer, what is read is stored after current buffer position. + * Space is left in the buffer to write a terminating 0. + * @param line: line number is increased per line, for error reports. + * @param comments: if 0, comments are not possible and become text. + * if 1, comments are skipped entirely. + * In BIND files, this is when reading quoted strings, for example + * " base 64 text with / / in there " + * @return the number of character written to the buffer. + * 0 on end of file. + */ +static int +readkeyword_bindfile(FILE* in, ldns_buffer* buf, int* line, int comments) +{ + int c; + int numdone = 0; + while((c = getc(in)) != EOF ) { + if(comments && c == '#') { /* # blabla */ + skip_to_eol(in); + (*line)++; + continue; + } else if(comments && c=='/' && numdone>0 && /* /_/ bla*/ + ldns_buffer_read_u8_at(buf, + ldns_buffer_position(buf)-1) == '/') { + ldns_buffer_skip(buf, -1); + numdone--; + skip_to_eol(in); + (*line)++; + continue; + } else if(comments && c=='*' && numdone>0 && /* /_* bla *_/ */ + ldns_buffer_read_u8_at(buf, + ldns_buffer_position(buf)-1) == '/') { + ldns_buffer_skip(buf, -1); + numdone--; + /* skip to end of comment */ + while(c != EOF && (c=getc(in)) != EOF ) { + if(c == '*') { + if((c=getc(in)) == '/') + break; + } + if(c == '\n') + (*line)++; + } + continue; + } + /* not a comment, complete the keyword */ + if(numdone > 0) { + /* check same type */ + if(isspace(c)) { + ungetc(c, in); + return numdone; + } + if(is_bind_special(c)) { + ungetc(c, in); + return numdone; + } + } + if(c == '\n') { + c = ' '; + (*line)++; + } + /* space for 1 char + 0 string terminator */ + if(ldns_buffer_remaining(buf) < 2) { + fatal_exit("trusted-keys, %d, string too long", *line); + } + ldns_buffer_write_u8(buf, (uint8_t)c); + numdone++; + if(isspace(c)) { + /* collate whitespace into ' ' */ + while((c = getc(in)) != EOF ) { + if(c == '\n') + (*line)++; + if(!isspace(c)) { + ungetc(c, in); + break; + } + } + return numdone; + } + if(is_bind_special(c)) + return numdone; + } + return numdone; +} + +/** skip through file to { or ; */ +static int +skip_to_special(FILE* in, ldns_buffer* buf, int* line, int spec) +{ + int rdlen; + ldns_buffer_clear(buf); + while((rdlen=readkeyword_bindfile(in, buf, line, 1))) { + if(rdlen == 1 && isspace((int)*ldns_buffer_begin(buf))) { + ldns_buffer_clear(buf); + continue; + } + if(rdlen != 1 || *ldns_buffer_begin(buf) != (uint8_t)spec) { + ldns_buffer_write_u8(buf, 0); + log_err("trusted-keys, line %d, expected %c", + *line, spec); + return 0; + } + return 1; + } + log_err("trusted-keys, line %d, expected %c got EOF", *line, spec); + return 0; +} + +/** + * read contents of trusted-keys{ ... ; clauses and insert keys into storage. + * @param anchors: where to store keys + * @param buf: buffer to use + * @param line: line number in file + * @param in: file to read from. + * @return 0 on error. + */ +static int +process_bind_contents(struct val_anchors* anchors, ldns_buffer* buf, + int* line, FILE* in) +{ + /* loop over contents, collate strings before ; */ + /* contents is (numbered): 0 1 2 3 4 5 6 7 8 */ + /* name. 257 3 5 base64 base64 */ + /* quoted value: 0 "111" 0 0 0 0 0 0 0 */ + /* comments value: 1 "000" 1 1 1 "0 0 0 0" 1 */ + int contnum = 0; + int quoted = 0; + int comments = 1; + int rdlen; + char* str = 0; + ldns_buffer_clear(buf); + while((rdlen=readkeyword_bindfile(in, buf, line, comments))) { + if(rdlen == 1 && ldns_buffer_position(buf) == 1 + && isspace((int)*ldns_buffer_begin(buf))) { + /* starting whitespace is removed */ + ldns_buffer_clear(buf); + continue; + } else if(rdlen == 1 && ldns_buffer_current(buf)[-1] == '"') { + /* remove " from the string */ + if(contnum == 0) { + quoted = 1; + comments = 0; + } + ldns_buffer_skip(buf, -1); + if(contnum > 0 && quoted) { + if(ldns_buffer_remaining(buf) < 8+1) { + log_err("line %d, too long", *line); + return 0; + } + ldns_buffer_write(buf, " DNSKEY ", 8); + quoted = 0; + comments = 1; + } else if(contnum > 0) + comments = !comments; + continue; + } else if(rdlen == 1 && ldns_buffer_current(buf)[-1] == ';') { + + if(contnum < 5) { + ldns_buffer_write_u8(buf, 0); + log_err("line %d, bad key", *line); + return 0; + } + ldns_buffer_skip(buf, -1); + ldns_buffer_write_u8(buf, 0); + str = strdup((char*)ldns_buffer_begin(buf)); + if(!str) { + log_err("line %d, allocation failure", *line); + return 0; + } + if(!anchor_store_str(anchors, buf, str)) { + log_err("line %d, bad key", *line); + free(str); + return 0; + } + free(str); + ldns_buffer_clear(buf); + contnum = 0; + quoted = 0; + comments = 1; + continue; + } else if(rdlen == 1 && ldns_buffer_current(buf)[-1] == '}') { + if(contnum > 0) { + ldns_buffer_write_u8(buf, 0); + log_err("line %d, bad key before }", *line); + return 0; + } + return 1; + } else if(rdlen == 1 && + isspace((int)ldns_buffer_current(buf)[-1])) { + /* leave whitespace here */ + } else { + /* not space or whatnot, so actual content */ + contnum ++; + if(contnum == 1 && !quoted) { + if(ldns_buffer_remaining(buf) < 8+1) { + log_err("line %d, too long", *line); + return 0; + } + ldns_buffer_write(buf, " DNSKEY ", 8); + } + } + } + + log_err("line %d, EOF before }", *line); + return 0; +} + +/** + * Read a BIND9 like file with trust anchors in named.conf format. + * @param anchors: anchor storage. + * @param buffer: parsing buffer. + * @param fname: string. + * @return false on error. + */ +static int +anchor_read_bind_file(struct val_anchors* anchors, ldns_buffer* buffer, + const char* fname) +{ + int line_nr = 1; + FILE* in = fopen(fname, "r"); + int rdlen = 0; + if(!in) { + log_err("error opening file %s: %s", fname, strerror(errno)); + return 0; + } + verbose(VERB_QUERY, "reading in bind-compat-mode: '%s'", fname); + /* scan for trusted-keys keyword, ignore everything else */ + ldns_buffer_clear(buffer); + while((rdlen=readkeyword_bindfile(in, buffer, &line_nr, 1)) != 0) { + if(rdlen != 12 || strncmp((char*)ldns_buffer_begin(buffer), + "trusted-keys", 12) != 0) { + ldns_buffer_clear(buffer); + /* ignore everything but trusted-keys */ + continue; + } + if(!skip_to_special(in, buffer, &line_nr, '{')) { + log_err("error in trusted key: \"%s\"", fname); + fclose(in); + return 0; + } + /* process contents */ + if(!process_bind_contents(anchors, buffer, &line_nr, in)) { + log_err("error in trusted key: \"%s\"", fname); + fclose(in); + return 0; + } + if(!skip_to_special(in, buffer, &line_nr, ';')) { + log_err("error in trusted key: \"%s\"", fname); + fclose(in); + return 0; + } + ldns_buffer_clear(buffer); + } + fclose(in); + return 1; +} + +/** + * Read a BIND9 like files with trust anchors in named.conf format. + * Performs wildcard processing of name. + * @param anchors: anchor storage. + * @param buffer: parsing buffer. + * @param pat: pattern string. (can be wildcarded) + * @return false on error. + */ +static int +anchor_read_bind_file_wild(struct val_anchors* anchors, ldns_buffer* buffer, + const char* pat) +{ +#ifdef HAVE_GLOB + glob_t g; + size_t i; + int r, flags; + if(!strchr(pat, '*') && !strchr(pat, '?') && !strchr(pat, '[') && + !strchr(pat, '{') && !strchr(pat, '~')) { + return anchor_read_bind_file(anchors, buffer, pat); + } + verbose(VERB_QUERY, "wildcard found, processing %s", pat); + flags = 0 +#ifdef GLOB_ERR + | GLOB_ERR +#endif +#ifdef GLOB_NOSORT + | GLOB_NOSORT +#endif +#ifdef GLOB_BRACE + | GLOB_BRACE +#endif +#ifdef GLOB_TILDE + | GLOB_TILDE +#endif + ; + memset(&g, 0, sizeof(g)); + r = glob(pat, flags, NULL, &g); + if(r) { + /* some error */ + if(r == GLOB_NOMATCH) { + verbose(VERB_QUERY, "trusted-keys-file: " + "no matches for %s", pat); + return 1; + } else if(r == GLOB_NOSPACE) { + log_err("wildcard trusted-keys-file %s: " + "pattern out of memory", pat); + } else if(r == GLOB_ABORTED) { + log_err("wildcard trusted-keys-file %s: expansion " + "aborted (%s)", pat, strerror(errno)); + } else { + log_err("wildcard trusted-keys-file %s: expansion " + "failed (%s)", pat, strerror(errno)); + } + return 0; + } + /* process files found, if any */ + for(i=0; i<(size_t)g.gl_pathc; i++) { + if(!anchor_read_bind_file(anchors, buffer, g.gl_pathv[i])) { + log_err("error reading wildcard " + "trusted-keys-file: %s", g.gl_pathv[i]); + globfree(&g); + return 0; + } + } + globfree(&g); + return 1; +#else /* not HAVE_GLOB */ + return anchor_read_bind_file(anchors, buffer, pat); +#endif /* HAVE_GLOB */ +} + +/** + * Assemble an rrset structure for the type + * @param ta: trust anchor. + * @param num: number of items to fetch from list. + * @param type: fetch only items of this type. + * @return rrset or NULL on error. + */ +static struct ub_packed_rrset_key* +assemble_it(struct trust_anchor* ta, size_t num, uint16_t type) +{ + struct ub_packed_rrset_key* pkey = (struct ub_packed_rrset_key*) + malloc(sizeof(*pkey)); + struct packed_rrset_data* pd; + struct ta_key* tk; + size_t i; + if(!pkey) + return NULL; + memset(pkey, 0, sizeof(*pkey)); + pkey->rk.dname = memdup(ta->name, ta->namelen); + if(!pkey->rk.dname) { + free(pkey); + return NULL; + } + + pkey->rk.dname_len = ta->namelen; + pkey->rk.type = htons(type); + pkey->rk.rrset_class = htons(ta->dclass); + /* The rrset is build in an uncompressed way. This means it + * cannot be copied in the normal way. */ + pd = (struct packed_rrset_data*)malloc(sizeof(*pd)); + if(!pd) { + free(pkey->rk.dname); + free(pkey); + return NULL; + } + memset(pd, 0, sizeof(*pd)); + pd->count = num; + pd->trust = rrset_trust_ultimate; + pd->rr_len = (size_t*)malloc(num*sizeof(size_t)); + if(!pd->rr_len) { + free(pd); + free(pkey->rk.dname); + free(pkey); + return NULL; + } + pd->rr_ttl = (uint32_t*)malloc(num*sizeof(uint32_t)); + if(!pd->rr_ttl) { + free(pd->rr_len); + free(pd); + free(pkey->rk.dname); + free(pkey); + return NULL; + } + pd->rr_data = (uint8_t**)malloc(num*sizeof(uint8_t*)); + if(!pd->rr_data) { + free(pd->rr_ttl); + free(pd->rr_len); + free(pd); + free(pkey->rk.dname); + free(pkey); + return NULL; + } + /* fill in rrs */ + i=0; + for(tk = ta->keylist; tk; tk = tk->next) { + if(tk->type != type) + continue; + pd->rr_len[i] = tk->len; + /* reuse data ptr to allocation in talist */ + pd->rr_data[i] = tk->data; + pd->rr_ttl[i] = 0; + i++; + } + pkey->entry.data = (void*)pd; + return pkey; +} + +/** + * Assemble structures for the trust DS and DNSKEY rrsets. + * @param ta: trust anchor + * @return: false on error. + */ +static int +anchors_assemble(struct trust_anchor* ta) +{ + if(ta->numDS > 0) { + ta->ds_rrset = assemble_it(ta, ta->numDS, LDNS_RR_TYPE_DS); + if(!ta->ds_rrset) + return 0; + } + if(ta->numDNSKEY > 0) { + ta->dnskey_rrset = assemble_it(ta, ta->numDNSKEY, + LDNS_RR_TYPE_DNSKEY); + if(!ta->dnskey_rrset) + return 0; + } + return 1; +} + +/** + * Check DS algos for support, warn if not. + * @param ta: trust anchor + * @return number of DS anchors with unsupported algorithms. + */ +static size_t +anchors_ds_unsupported(struct trust_anchor* ta) +{ + size_t i, num = 0; + for(i=0; inumDS; i++) { + if(!ds_digest_algo_is_supported(ta->ds_rrset, i) || + !ds_key_algo_is_supported(ta->ds_rrset, i)) + num++; + } + return num; +} + +/** + * Check DNSKEY algos for support, warn if not. + * @param ta: trust anchor + * @return number of DNSKEY anchors with unsupported algorithms. + */ +static size_t +anchors_dnskey_unsupported(struct trust_anchor* ta) +{ + size_t i, num = 0; + for(i=0; inumDNSKEY; i++) { + if(!dnskey_algo_is_supported(ta->dnskey_rrset, i)) + num++; + } + return num; +} + +/** + * Assemble the rrsets in the anchors, ready for use by validator. + * @param anchors: trust anchor storage. + * @return: false on error. + */ +static int +anchors_assemble_rrsets(struct val_anchors* anchors) +{ + struct trust_anchor* ta; + struct trust_anchor* next; + size_t nods, nokey; + lock_basic_lock(&anchors->lock); + ta=(struct trust_anchor*)rbtree_first(anchors->tree); + while((rbnode_t*)ta != RBTREE_NULL) { + next = (struct trust_anchor*)rbtree_next(&ta->node); + lock_basic_lock(&ta->lock); + if(ta->autr || (ta->numDS == 0 && ta->numDNSKEY == 0)) { + lock_basic_unlock(&ta->lock); + ta = next; /* skip */ + continue; + } + if(!anchors_assemble(ta)) { + log_err("out of memory"); + lock_basic_unlock(&ta->lock); + lock_basic_unlock(&anchors->lock); + return 0; + } + nods = anchors_ds_unsupported(ta); + nokey = anchors_dnskey_unsupported(ta); + if(nods) { + log_nametypeclass(0, "warning: unsupported " + "algorithm for trust anchor", + ta->name, LDNS_RR_TYPE_DS, ta->dclass); + } + if(nokey) { + log_nametypeclass(0, "warning: unsupported " + "algorithm for trust anchor", + ta->name, LDNS_RR_TYPE_DNSKEY, ta->dclass); + } + if(nods == ta->numDS && nokey == ta->numDNSKEY) { + char b[257]; + dname_str(ta->name, b); + log_warn("trust anchor %s has no supported algorithms," + " the anchor is ignored (check if you need to" + " upgrade unbound and openssl)", b); + (void)rbtree_delete(anchors->tree, &ta->node); + lock_basic_unlock(&ta->lock); + anchors_delfunc(&ta->node, NULL); + ta = next; + continue; + } + lock_basic_unlock(&ta->lock); + ta = next; + } + lock_basic_unlock(&anchors->lock); + return 1; +} + +int +anchors_apply_cfg(struct val_anchors* anchors, struct config_file* cfg) +{ + struct config_strlist* f; + char* nm; + ldns_buffer* parsebuf = ldns_buffer_new(65535); + for(f = cfg->domain_insecure; f; f = f->next) { + if(!f->str || f->str[0] == 0) /* empty "" */ + continue; + if(!anchor_insert_insecure(anchors, f->str)) { + log_err("error in domain-insecure: %s", f->str); + ldns_buffer_free(parsebuf); + return 0; + } + } + for(f = cfg->trust_anchor_file_list; f; f = f->next) { + if(!f->str || f->str[0] == 0) /* empty "" */ + continue; + nm = f->str; + if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(nm, + cfg->chrootdir, strlen(cfg->chrootdir)) == 0) + nm += strlen(cfg->chrootdir); + if(!anchor_read_file(anchors, parsebuf, nm, 0)) { + log_err("error reading trust-anchor-file: %s", f->str); + ldns_buffer_free(parsebuf); + return 0; + } + } + for(f = cfg->trusted_keys_file_list; f; f = f->next) { + if(!f->str || f->str[0] == 0) /* empty "" */ + continue; + nm = f->str; + if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(nm, + cfg->chrootdir, strlen(cfg->chrootdir)) == 0) + nm += strlen(cfg->chrootdir); + if(!anchor_read_bind_file_wild(anchors, parsebuf, nm)) { + log_err("error reading trusted-keys-file: %s", f->str); + ldns_buffer_free(parsebuf); + return 0; + } + } + for(f = cfg->trust_anchor_list; f; f = f->next) { + if(!f->str || f->str[0] == 0) /* empty "" */ + continue; + if(!anchor_store_str(anchors, parsebuf, f->str)) { + log_err("error in trust-anchor: \"%s\"", f->str); + ldns_buffer_free(parsebuf); + return 0; + } + } + if(cfg->dlv_anchor_file && cfg->dlv_anchor_file[0] != 0) { + struct trust_anchor* dlva; + nm = cfg->dlv_anchor_file; + if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(nm, + cfg->chrootdir, strlen(cfg->chrootdir)) == 0) + nm += strlen(cfg->chrootdir); + if(!(dlva = anchor_read_file(anchors, parsebuf, + nm, 1))) { + log_err("error reading dlv-anchor-file: %s", + cfg->dlv_anchor_file); + ldns_buffer_free(parsebuf); + return 0; + } + lock_basic_lock(&anchors->lock); + anchors->dlv_anchor = dlva; + lock_basic_unlock(&anchors->lock); + } + for(f = cfg->dlv_anchor_list; f; f = f->next) { + struct trust_anchor* dlva; + if(!f->str || f->str[0] == 0) /* empty "" */ + continue; + if(!(dlva = anchor_store_str( + anchors, parsebuf, f->str))) { + log_err("error in dlv-anchor: \"%s\"", f->str); + ldns_buffer_free(parsebuf); + return 0; + } + lock_basic_lock(&anchors->lock); + anchors->dlv_anchor = dlva; + lock_basic_unlock(&anchors->lock); + } + /* do autr last, so that it sees what anchors are filled by other + * means can can print errors about double config for the name */ + for(f = cfg->auto_trust_anchor_file_list; f; f = f->next) { + if(!f->str || f->str[0] == 0) /* empty "" */ + continue; + nm = f->str; + if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(nm, + cfg->chrootdir, strlen(cfg->chrootdir)) == 0) + nm += strlen(cfg->chrootdir); + if(!autr_read_file(anchors, nm)) { + log_err("error reading auto-trust-anchor-file: %s", + f->str); + ldns_buffer_free(parsebuf); + return 0; + } + } + /* first assemble, since it may delete useless anchors */ + anchors_assemble_rrsets(anchors); + init_parents(anchors); + ldns_buffer_free(parsebuf); + if(verbosity >= VERB_ALGO) autr_debug_print(anchors); + return 1; +} + +struct trust_anchor* +anchors_lookup(struct val_anchors* anchors, + uint8_t* qname, size_t qname_len, uint16_t qclass) +{ + struct trust_anchor key; + struct trust_anchor* result; + rbnode_t* res = NULL; + key.node.key = &key; + key.name = qname; + key.namelabs = dname_count_labels(qname); + key.namelen = qname_len; + key.dclass = qclass; + lock_basic_lock(&anchors->lock); + if(rbtree_find_less_equal(anchors->tree, &key, &res)) { + /* exact */ + result = (struct trust_anchor*)res; + } else { + /* smaller element (or no element) */ + int m; + result = (struct trust_anchor*)res; + if(!result || result->dclass != qclass) { + lock_basic_unlock(&anchors->lock); + 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 stub */ + if(result->namelabs <= m) + break; + result = result->parent; + } + } + if(result) { + lock_basic_lock(&result->lock); + } + lock_basic_unlock(&anchors->lock); + return result; +} + +size_t +anchors_get_mem(struct val_anchors* anchors) +{ + struct trust_anchor *ta; + size_t s = sizeof(*anchors); + RBTREE_FOR(ta, struct trust_anchor*, anchors->tree) { + s += sizeof(*ta) + ta->namelen; + /* keys and so on */ + } + return s; +} + +int +anchors_add_insecure(struct val_anchors* anchors, uint16_t c, uint8_t* nm) +{ + struct trust_anchor key; + key.node.key = &key; + key.name = nm; + key.namelabs = dname_count_size_labels(nm, &key.namelen); + key.dclass = c; + lock_basic_lock(&anchors->lock); + if(rbtree_search(anchors->tree, &key)) { + lock_basic_unlock(&anchors->lock); + /* nothing to do, already an anchor or insecure point */ + return 1; + } + if(!anchor_new_ta(anchors, nm, key.namelabs, key.namelen, c, 0)) { + log_err("out of memory"); + lock_basic_unlock(&anchors->lock); + return 0; + } + /* no other contents in new ta, because it is insecure point */ + anchors_init_parents_locked(anchors); + lock_basic_unlock(&anchors->lock); + return 1; +} + +void +anchors_delete_insecure(struct val_anchors* anchors, uint16_t c, + uint8_t* nm) +{ + struct trust_anchor key; + struct trust_anchor* ta; + key.node.key = &key; + key.name = nm; + key.namelabs = dname_count_size_labels(nm, &key.namelen); + key.dclass = c; + lock_basic_lock(&anchors->lock); + if(!(ta=(struct trust_anchor*)rbtree_search(anchors->tree, &key))) { + lock_basic_unlock(&anchors->lock); + /* nothing there */ + return; + } + /* lock it to drive away other threads that use it */ + lock_basic_lock(&ta->lock); + /* see if its really an insecure point */ + if(ta->keylist || ta->autr || ta->numDS || ta->numDNSKEY) { + lock_basic_unlock(&ta->lock); + /* its not an insecure point, do not remove it */ + return; + } + + /* remove from tree */ + (void)rbtree_delete(anchors->tree, &ta->node); + anchors_init_parents_locked(anchors); + lock_basic_unlock(&anchors->lock); + + /* actual free of data */ + lock_basic_unlock(&ta->lock); + anchors_delfunc(&ta->node, NULL); +} + diff --git a/validator/val_anchor.h b/validator/val_anchor.h new file mode 100644 index 00000000000..5a3ad409a83 --- /dev/null +++ b/validator/val_anchor.h @@ -0,0 +1,218 @@ +/* + * validator/val_anchor.h - validator trust anchor storage. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains storage for the trust anchors for the validator. + */ + +#ifndef VALIDATOR_VAL_ANCHOR_H +#define VALIDATOR_VAL_ANCHOR_H +#include "util/rbtree.h" +#include "util/locks.h" +struct trust_anchor; +struct config_file; +struct ub_packed_rrset_key; +struct autr_point_data; +struct autr_global_data; + +/** + * Trust anchor store. + * The tree must be locked, while no other locks (from trustanchors) are held. + * And then an anchor searched for. Which can be locked or deleted. Then + * the tree can be unlocked again. This means you have to release the lock + * on a trust anchor and look it up again to delete it. + */ +struct val_anchors { + /** lock on trees */ + lock_basic_t lock; + /** + * Anchors are store in this tree. Sort order is chosen, so that + * dnames are in nsec-like order. A lookup on class, name will return + * an exact match of the closest match, with the ancestor needed. + * contents of type trust_anchor. + */ + rbtree_t* tree; + /** The DLV trust anchor (if one is configured, else NULL) */ + struct trust_anchor* dlv_anchor; + /** Autotrust global data, anchors sorted by next probe time */ + struct autr_global_data* autr; +}; + +/** + * Trust anchor key + */ +struct ta_key { + /** next in list */ + struct ta_key* next; + /** rdata, in wireformat of the key RR. starts with rdlength. */ + uint8_t* data; + /** length of the rdata (including rdlength). */ + size_t len; + /** DNS type (host format) of the key, DS or DNSKEY */ + uint16_t type; +}; + +/** + * A trust anchor in the trust anchor store. + * Unique by name, class. + */ +struct trust_anchor { + /** rbtree node, key is this structure */ + rbnode_t node; + /** lock on the entire anchor and its keys; for autotrust changes */ + lock_basic_t lock; + /** name of this trust anchor */ + uint8_t* name; + /** length of name */ + size_t namelen; + /** number of labels in name of rrset */ + int namelabs; + /** the ancestor in the trustanchor tree */ + struct trust_anchor* parent; + /** + * List of DS or DNSKEY rrs that form the trust anchor. + */ + struct ta_key* keylist; + /** Autotrust anchor point data, or NULL */ + struct autr_point_data* autr; + /** number of DSs in the keylist */ + size_t numDS; + /** number of DNSKEYs in the keylist */ + size_t numDNSKEY; + /** the DS RRset */ + struct ub_packed_rrset_key* ds_rrset; + /** The DNSKEY RRset */ + struct ub_packed_rrset_key* dnskey_rrset; + /** class of the trust anchor */ + uint16_t dclass; +}; + +/** + * Create trust anchor storage + * @return new storage or NULL on error. + */ +struct val_anchors* anchors_create(void); + +/** + * Delete trust anchor storage. + * @param anchors: to delete. + */ +void anchors_delete(struct val_anchors* anchors); + +/** + * Process trust anchor config. + * @param anchors: struct anchor storage + * @param cfg: config options. + * @return 0 on error. + */ +int anchors_apply_cfg(struct val_anchors* anchors, struct config_file* cfg); + +/** + * Recalculate parent pointers. The caller must hold the lock on the + * anchors structure (say after removing an item from the rbtree). + * Caller must not hold any locks on trust anchors. + * After the call is complete the parent pointers are updated and an item + * just removed is no longer referenced in parent pointers. + * @param anchors: the structure to update. + */ +void anchors_init_parents_locked(struct val_anchors* anchors); + +/** + * Given a qname/qclass combination, find the trust anchor closest above it. + * Or return NULL if none exists. + * + * @param anchors: struct anchor storage + * @param qname: query name, uncompressed wireformat. + * @param qname_len: length of qname. + * @param qclass: class to query for. + * @return the trust anchor or NULL if none is found. The anchor is locked. + */ +struct trust_anchor* anchors_lookup(struct val_anchors* anchors, + uint8_t* qname, size_t qname_len, uint16_t qclass); + +/** + * Find a trust anchor. Exact matching. + * @param anchors: anchor storage. + * @param name: name of trust anchor (wireformat) + * @param namelabs: labels in name + * @param namelen: length of name + * @param dclass: class of trust anchor + * @return NULL if not found. The anchor is locked. + */ +struct trust_anchor* anchor_find(struct val_anchors* anchors, + uint8_t* name, int namelabs, size_t namelen, uint16_t dclass); + +/** + * Store one string as trust anchor RR. + * @param anchors: anchor storage. + * @param buffer: parsing buffer, to generate the RR wireformat in. + * @param str: string. + * @return NULL on error. + */ +struct trust_anchor* anchor_store_str(struct val_anchors* anchors, + ldns_buffer* buffer, const char* str); + +/** + * Get memory in use by the trust anchor storage + * @param anchors: anchor storage. + * @return memory in use in bytes. + */ +size_t anchors_get_mem(struct val_anchors* anchors); + +/** compare two trust anchors */ +int anchor_cmp(const void* k1, const void* k2); + +/** + * Add insecure point trust anchor. For external use (locks and init_parents) + * @param anchors: anchor storage. + * @param c: class. + * @param nm: name of insecure trust point. + * @return false on alloc failure. + */ +int anchors_add_insecure(struct val_anchors* anchors, uint16_t c, uint8_t* nm); + +/** + * Delete insecure point trust anchor. Does not remove if no such point. + * For external use (locks and init_parents) + * @param anchors: anchor storage. + * @param c: class. + * @param nm: name of insecure trust point. + */ +void anchors_delete_insecure(struct val_anchors* anchors, uint16_t c, + uint8_t* nm); + +#endif /* VALIDATOR_VAL_ANCHOR_H */ diff --git a/validator/val_kcache.c b/validator/val_kcache.c new file mode 100644 index 00000000000..68e8c3f619b --- /dev/null +++ b/validator/val_kcache.c @@ -0,0 +1,172 @@ +/* + * validator/val_kcache.c - validator key shared cache with validated keys + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions for dealing with the validator key cache. + */ +#include "config.h" +#include "validator/val_kcache.h" +#include "validator/val_kentry.h" +#include "util/log.h" +#include "util/config_file.h" +#include "util/data/dname.h" +#include "util/module.h" + +struct key_cache* +key_cache_create(struct config_file* cfg) +{ + struct key_cache* kcache = (struct key_cache*)calloc(1, + sizeof(*kcache)); + size_t numtables, start_size, maxmem; + if(!kcache) { + log_err("malloc failure"); + return NULL; + } + numtables = cfg->key_cache_slabs; + start_size = HASH_DEFAULT_STARTARRAY; + maxmem = cfg->key_cache_size; + kcache->slab = slabhash_create(numtables, start_size, maxmem, + &key_entry_sizefunc, &key_entry_compfunc, + &key_entry_delkeyfunc, &key_entry_deldatafunc, NULL); + if(!kcache->slab) { + log_err("malloc failure"); + free(kcache); + return NULL; + } + return kcache; +} + +void +key_cache_delete(struct key_cache* kcache) +{ + if(!kcache) + return; + slabhash_delete(kcache->slab); + free(kcache); +} + +void +key_cache_insert(struct key_cache* kcache, struct key_entry_key* kkey, + struct module_qstate* qstate) +{ + struct key_entry_key* k = key_entry_copy(kkey); + if(!k) + return; + if(key_entry_isbad(k) && qstate->errinf && + qstate->env->cfg->val_log_level >= 2) { + /* on malloc failure there is simply no reason string */ + key_entry_set_reason(k, errinf_to_str(qstate)); + } + key_entry_hash(k); + slabhash_insert(kcache->slab, k->entry.hash, &k->entry, + k->entry.data, NULL); +} + +/** + * Lookup exactly in the key cache. Returns pointer to locked entry. + * Caller must unlock it after use. + * @param kcache: the key cache. + * @param name: for what name to look; uncompressed wireformat + * @param namelen: length of the name. + * @param key_class: class of the key. + * @param wr: set true to get a writelock. + * @return key entry, locked, or NULL if not found. No TTL checking is + * performed. + */ +static struct key_entry_key* +key_cache_search(struct key_cache* kcache, uint8_t* name, size_t namelen, + uint16_t key_class, int wr) +{ + struct lruhash_entry* e; + struct key_entry_key lookfor; + lookfor.entry.key = &lookfor; + lookfor.name = name; + lookfor.namelen = namelen; + lookfor.key_class = key_class; + key_entry_hash(&lookfor); + e = slabhash_lookup(kcache->slab, lookfor.entry.hash, &lookfor, wr); + if(!e) + return NULL; + return (struct key_entry_key*)e->key; +} + +struct key_entry_key* +key_cache_obtain(struct key_cache* kcache, uint8_t* name, size_t namelen, + uint16_t key_class, struct regional* region, uint32_t now) +{ + /* keep looking until we find a nonexpired entry */ + while(1) { + struct key_entry_key* k = key_cache_search(kcache, name, + namelen, key_class, 0); + if(k) { + /* see if TTL is OK */ + struct key_entry_data* d = (struct key_entry_data*) + k->entry.data; + if(now <= d->ttl) { + /* copy and return it */ + struct key_entry_key* retkey = + key_entry_copy_toregion(k, region); + lock_rw_unlock(&k->entry.lock); + return retkey; + } + lock_rw_unlock(&k->entry.lock); + } + /* snip off first label to continue */ + if(dname_is_root(name)) + break; + dname_remove_label(&name, &namelen); + } + return NULL; +} + +size_t +key_cache_get_mem(struct key_cache* kcache) +{ + return sizeof(*kcache) + slabhash_get_mem(kcache->slab); +} + +void key_cache_remove(struct key_cache* kcache, + uint8_t* name, size_t namelen, uint16_t key_class) +{ + struct key_entry_key lookfor; + lookfor.entry.key = &lookfor; + lookfor.name = name; + lookfor.namelen = namelen; + lookfor.key_class = key_class; + key_entry_hash(&lookfor); + slabhash_remove(kcache->slab, lookfor.entry.hash, &lookfor); +} diff --git a/validator/val_kcache.h b/validator/val_kcache.h new file mode 100644 index 00000000000..c37cf1ecbaf --- /dev/null +++ b/validator/val_kcache.h @@ -0,0 +1,118 @@ +/* + * validator/val_kcache.h - validator key shared cache with validated keys + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions for caching validated key entries. + */ + +#ifndef VALIDATOR_VAL_KCACHE_H +#define VALIDATOR_VAL_KCACHE_H +#include "util/storage/slabhash.h" +struct key_entry_key; +struct key_entry_data; +struct config_file; +struct regional; +struct module_qstate; + +/** + * Key cache + */ +struct key_cache { + /** uses slabhash for storage, type key_entry_key, key_entry_data */ + struct slabhash* slab; +}; + +/** + * Create the key cache + * @param cfg: config settings for the key cache. + * @return new key cache or NULL on malloc failure. + */ +struct key_cache* key_cache_create(struct config_file* cfg); + +/** + * Delete the key cache + * @param kcache: to delete + */ +void key_cache_delete(struct key_cache* kcache); + +/** + * Insert or update a key cache entry. Note that the insert may silently + * fail if there is not enough memory. + * + * @param kcache: the key cache. + * @param kkey: key entry key, assumed malloced in a region, is copied + * to perform update or insertion. Its data pointer is also copied. + * @param qstate: store errinf reason in case its bad. + */ +void key_cache_insert(struct key_cache* kcache, struct key_entry_key* kkey, + struct module_qstate* qstate); + +/** + * Remove an entry from the key cache. + * @param kcache: the key cache. + * @param name: for what name to look; uncompressed wireformat + * @param namelen: length of the name. + * @param key_class: class of the key. + */ +void key_cache_remove(struct key_cache* kcache, + uint8_t* name, size_t namelen, uint16_t key_class); + +/** + * Lookup key entry in the cache. Looks up the closest key entry above the + * given name. + * @param kcache: the key cache. + * @param name: for what name to look; uncompressed wireformat + * @param namelen: length of the name. + * @param key_class: class of the key. + * @param region: a copy of the key_entry is allocated in this region. + * @param now: current time. + * @return pointer to a newly allocated key_entry copy in the region, if + * a key entry could be found, and allocation succeeded and TTL was OK. + * Otherwise, NULL is returned. + */ +struct key_entry_key* key_cache_obtain(struct key_cache* kcache, + uint8_t* name, size_t namelen, uint16_t key_class, + struct regional* region, uint32_t now); + +/** + * Get memory in use by the key cache. + * @param kcache: the key cache. + * @return memory in use in bytes. + */ +size_t key_cache_get_mem(struct key_cache* kcache); + +#endif /* VALIDATOR_VAL_KCACHE_H */ diff --git a/validator/val_kentry.c b/validator/val_kentry.c new file mode 100644 index 00000000000..ddac140d316 --- /dev/null +++ b/validator/val_kentry.c @@ -0,0 +1,412 @@ +/* + * validator/val_kentry.c - validator key entry definition. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions for dealing with validator key entries. + */ +#include "config.h" +#include +#include "validator/val_kentry.h" +#include "util/data/packed_rrset.h" +#include "util/data/dname.h" +#include "util/storage/lookup3.h" +#include "util/regional.h" +#include "util/net_help.h" + +size_t +key_entry_sizefunc(void* key, void* data) +{ + struct key_entry_key* kk = (struct key_entry_key*)key; + struct key_entry_data* kd = (struct key_entry_data*)data; + size_t s = sizeof(*kk) + kk->namelen; + s += sizeof(*kd) + lock_get_mem(&kk->entry.lock); + if(kd->rrset_data) + s += packed_rrset_sizeof(kd->rrset_data); + if(kd->reason) + s += strlen(kd->reason)+1; + if(kd->algo) + s += strlen((char*)kd->algo)+1; + return s; +} + +int +key_entry_compfunc(void* k1, void* k2) +{ + struct key_entry_key* n1 = (struct key_entry_key*)k1; + struct key_entry_key* n2 = (struct key_entry_key*)k2; + if(n1->key_class != n2->key_class) { + if(n1->key_class < n2->key_class) + return -1; + return 1; + } + return query_dname_compare(n1->name, n2->name); +} + +void +key_entry_delkeyfunc(void* key, void* ATTR_UNUSED(userarg)) +{ + struct key_entry_key* kk = (struct key_entry_key*)key; + if(!key) + return; + lock_rw_destroy(&kk->entry.lock); + free(kk->name); + free(kk); +} + +void +key_entry_deldatafunc(void* data, void* ATTR_UNUSED(userarg)) +{ + struct key_entry_data* kd = (struct key_entry_data*)data; + free(kd->reason); + free(kd->rrset_data); + free(kd->algo); + free(kd); +} + +void +key_entry_hash(struct key_entry_key* kk) +{ + kk->entry.hash = 0x654; + kk->entry.hash = hashlittle(&kk->key_class, sizeof(kk->key_class), + kk->entry.hash); + kk->entry.hash = dname_query_hash(kk->name, kk->entry.hash); +} + +struct key_entry_key* +key_entry_copy_toregion(struct key_entry_key* kkey, struct regional* region) +{ + struct key_entry_key* newk; + newk = regional_alloc_init(region, kkey, sizeof(*kkey)); + if(!newk) + return NULL; + newk->name = regional_alloc_init(region, kkey->name, kkey->namelen); + if(!newk->name) + return NULL; + newk->entry.key = newk; + if(newk->entry.data) { + /* copy data element */ + struct key_entry_data *d = (struct key_entry_data*) + kkey->entry.data; + struct key_entry_data *newd; + newd = regional_alloc_init(region, d, sizeof(*d)); + if(!newd) + return NULL; + /* copy rrset */ + if(d->rrset_data) { + newd->rrset_data = regional_alloc_init(region, + d->rrset_data, + packed_rrset_sizeof(d->rrset_data)); + if(!newd->rrset_data) + return NULL; + packed_rrset_ptr_fixup(newd->rrset_data); + } + if(d->reason) { + newd->reason = regional_strdup(region, d->reason); + if(!newd->reason) + return NULL; + } + if(d->algo) { + newd->algo = (uint8_t*)regional_strdup(region, + (char*)d->algo); + if(!newd->algo) + return NULL; + } + newk->entry.data = newd; + } + return newk; +} + +struct key_entry_key* +key_entry_copy(struct key_entry_key* kkey) +{ + struct key_entry_key* newk; + if(!kkey) + return NULL; + newk = memdup(kkey, sizeof(*kkey)); + if(!newk) + return NULL; + newk->name = memdup(kkey->name, kkey->namelen); + if(!newk->name) { + free(newk); + return NULL; + } + lock_rw_init(&newk->entry.lock); + newk->entry.key = newk; + if(newk->entry.data) { + /* copy data element */ + struct key_entry_data *d = (struct key_entry_data*) + kkey->entry.data; + struct key_entry_data *newd; + newd = memdup(d, sizeof(*d)); + if(!newd) { + free(newk->name); + free(newk); + return NULL; + } + /* copy rrset */ + if(d->rrset_data) { + newd->rrset_data = memdup(d->rrset_data, + packed_rrset_sizeof(d->rrset_data)); + if(!newd->rrset_data) { + free(newd); + free(newk->name); + free(newk); + return NULL; + } + packed_rrset_ptr_fixup(newd->rrset_data); + } + if(d->reason) { + newd->reason = strdup(d->reason); + if(!newd->reason) { + free(newd->rrset_data); + free(newd); + free(newk->name); + free(newk); + return NULL; + } + } + if(d->algo) { + newd->algo = (uint8_t*)strdup((char*)d->algo); + if(!newd->algo) { + free(newd->rrset_data); + free(newd->reason); + free(newd); + free(newk->name); + free(newk); + return NULL; + } + } + newk->entry.data = newd; + } + return newk; +} + +int +key_entry_isnull(struct key_entry_key* kkey) +{ + struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; + return (!d->isbad && d->rrset_data == NULL); +} + +int +key_entry_isgood(struct key_entry_key* kkey) +{ + struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; + return (!d->isbad && d->rrset_data != NULL); +} + +int +key_entry_isbad(struct key_entry_key* kkey) +{ + struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; + return (int)(d->isbad); +} + +void +key_entry_set_reason(struct key_entry_key* kkey, char* reason) +{ + struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; + d->reason = reason; +} + +char* +key_entry_get_reason(struct key_entry_key* kkey) +{ + struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; + return d->reason; +} + +/** setup key entry in region */ +static int +key_entry_setup(struct regional* region, + uint8_t* name, size_t namelen, uint16_t dclass, + struct key_entry_key** k, struct key_entry_data** d) +{ + *k = regional_alloc(region, sizeof(**k)); + if(!*k) + return 0; + memset(*k, 0, sizeof(**k)); + (*k)->entry.key = *k; + (*k)->name = regional_alloc_init(region, name, namelen); + if(!(*k)->name) + return 0; + (*k)->namelen = namelen; + (*k)->key_class = dclass; + *d = regional_alloc(region, sizeof(**d)); + if(!*d) + return 0; + (*k)->entry.data = *d; + return 1; +} + +struct key_entry_key* +key_entry_create_null(struct regional* region, + uint8_t* name, size_t namelen, uint16_t dclass, uint32_t ttl, + uint32_t now) +{ + struct key_entry_key* k; + struct key_entry_data* d; + if(!key_entry_setup(region, name, namelen, dclass, &k, &d)) + return NULL; + d->ttl = now + ttl; + d->isbad = 0; + d->reason = NULL; + d->rrset_type = LDNS_RR_TYPE_DNSKEY; + d->rrset_data = NULL; + d->algo = NULL; + return k; +} + +struct key_entry_key* +key_entry_create_rrset(struct regional* region, + uint8_t* name, size_t namelen, uint16_t dclass, + struct ub_packed_rrset_key* rrset, uint8_t* sigalg, uint32_t now) +{ + struct key_entry_key* k; + struct key_entry_data* d; + struct packed_rrset_data* rd = (struct packed_rrset_data*) + rrset->entry.data; + if(!key_entry_setup(region, name, namelen, dclass, &k, &d)) + return NULL; + d->ttl = rd->ttl + now; + d->isbad = 0; + d->reason = NULL; + d->rrset_type = ntohs(rrset->rk.type); + d->rrset_data = (struct packed_rrset_data*)regional_alloc_init(region, + rd, packed_rrset_sizeof(rd)); + if(!d->rrset_data) + return NULL; + if(sigalg) { + d->algo = (uint8_t*)regional_strdup(region, (char*)sigalg); + if(!d->algo) + return NULL; + } else d->algo = NULL; + packed_rrset_ptr_fixup(d->rrset_data); + return k; +} + +struct key_entry_key* +key_entry_create_bad(struct regional* region, + uint8_t* name, size_t namelen, uint16_t dclass, uint32_t ttl, + uint32_t now) +{ + struct key_entry_key* k; + struct key_entry_data* d; + if(!key_entry_setup(region, name, namelen, dclass, &k, &d)) + return NULL; + d->ttl = now + ttl; + d->isbad = 1; + d->reason = NULL; + d->rrset_type = LDNS_RR_TYPE_DNSKEY; + d->rrset_data = NULL; + d->algo = NULL; + return k; +} + +struct ub_packed_rrset_key* +key_entry_get_rrset(struct key_entry_key* kkey, struct regional* region) +{ + struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; + struct ub_packed_rrset_key* rrk; + struct packed_rrset_data* rrd; + if(!d || !d->rrset_data) + return NULL; + rrk = regional_alloc(region, sizeof(*rrk)); + if(!rrk) + return NULL; + memset(rrk, 0, sizeof(*rrk)); + rrk->rk.dname = regional_alloc_init(region, kkey->name, kkey->namelen); + if(!rrk->rk.dname) + return NULL; + rrk->rk.dname_len = kkey->namelen; + rrk->rk.type = htons(d->rrset_type); + rrk->rk.rrset_class = htons(kkey->key_class); + rrk->entry.key = rrk; + rrd = regional_alloc_init(region, d->rrset_data, + packed_rrset_sizeof(d->rrset_data)); + if(!rrd) + return NULL; + rrk->entry.data = rrd; + packed_rrset_ptr_fixup(rrd); + return rrk; +} + +/** Get size of key in keyset */ +static size_t +dnskey_get_keysize(struct packed_rrset_data* data, size_t idx) +{ + unsigned char* pk; + unsigned int pklen = 0; + int algo; + if(data->rr_len[idx] < 2+5) + return 0; + algo = (int)data->rr_data[idx][2+3]; + pk = (unsigned char*)data->rr_data[idx]+2+4; + pklen = (unsigned)data->rr_len[idx]-2-4; + return ldns_rr_dnskey_key_size_raw(pk, pklen, algo); +} + +/** get dnskey flags from data */ +static uint16_t +kd_get_flags(struct packed_rrset_data* data, size_t idx) +{ + uint16_t f; + if(data->rr_len[idx] < 2+2) + return 0; + memmove(&f, data->rr_data[idx]+2, 2); + f = ntohs(f); + return f; +} + +size_t +key_entry_keysize(struct key_entry_key* kkey) +{ + struct packed_rrset_data* d; + /* compute size of smallest ZSK key in the rrset */ + size_t i; + size_t bits = 0; + if(!key_entry_isgood(kkey)) + return 0; + d = ((struct key_entry_data*)kkey->entry.data)->rrset_data; + for(i=0; icount; i++) { + if(!(kd_get_flags(d, i) & DNSKEY_BIT_ZSK)) + continue; + if(i==0 || dnskey_get_keysize(d, i) < bits) + bits = dnskey_get_keysize(d, i); + } + return bits; +} diff --git a/validator/val_kentry.h b/validator/val_kentry.h new file mode 100644 index 00000000000..d14ffe58801 --- /dev/null +++ b/validator/val_kentry.h @@ -0,0 +1,220 @@ +/* + * validator/val_kentry.h - validator key entry definition. + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions for dealing with validator key entries. + */ + +#ifndef VALIDATOR_VAL_KENTRY_H +#define VALIDATOR_VAL_KENTRY_H +struct packed_rrset_data; +struct regional; +struct ub_packed_rrset_key; +#include "util/storage/lruhash.h" + +/** + * A key entry for the validator. + * This may or may not be a trusted key. + * This is what is stored in the key cache. + * This is the key part for the cache; the key entry key. + */ +struct key_entry_key { + /** lru hash entry */ + struct lruhash_entry entry; + /** name of the key */ + uint8_t* name; + /** length of name */ + size_t namelen; + /** class of the key, host byteorder */ + uint16_t key_class; +}; + +/** + * Key entry for the validator. + * Contains key status. + * This is the data part for the cache, the key entry data. + * + * Can be in three basic states: + * isbad=0: good key + * isbad=1: bad key + * isbad=0 && rrset=0: insecure space. + */ +struct key_entry_data { + /** the TTL of this entry (absolute time) */ + uint32_t ttl; + /** the key rrdata. can be NULL to signal keyless name. */ + struct packed_rrset_data* rrset_data; + /** not NULL sometimes to give reason why bogus */ + char* reason; + /** list of algorithms signalled, ends with 0, or NULL */ + uint8_t* algo; + /** DNS RR type of the rrset data (host order) */ + uint16_t rrset_type; + /** if the key is bad: Bogus or malformed */ + uint8_t isbad; +}; + +/** function for lruhash operation */ +size_t key_entry_sizefunc(void* key, void* data); + +/** function for lruhash operation */ +int key_entry_compfunc(void* k1, void* k2); + +/** function for lruhash operation */ +void key_entry_delkeyfunc(void* key, void* userarg); + +/** function for lruhash operation */ +void key_entry_deldatafunc(void* data, void* userarg); + +/** calculate hash for key entry + * @param kk: key entry. The lruhash entry.hash value is filled in. + */ +void key_entry_hash(struct key_entry_key* kk); + +/** + * Copy a key entry, to be region-allocated. + * @param kkey: the key entry key (and data pointer) to copy. + * @param region: where to allocate it + * @return newly region-allocated entry or NULL on a failure to allocate. + */ +struct key_entry_key* key_entry_copy_toregion(struct key_entry_key* kkey, + struct regional* region); + +/** + * Copy a key entry, malloced. + * @param kkey: the key entry key (and data pointer) to copy. + * @return newly allocated entry or NULL on a failure to allocate memory. + */ +struct key_entry_key* key_entry_copy(struct key_entry_key* kkey); + +/** + * See if this is a null entry. Does not do locking. + * @param kkey: must have data pointer set correctly + * @return true if it is a NULL rrset entry. + */ +int key_entry_isnull(struct key_entry_key* kkey); + +/** + * See if this entry is good. Does not do locking. + * @param kkey: must have data pointer set correctly + * @return true if it is good. + */ +int key_entry_isgood(struct key_entry_key* kkey); + +/** + * See if this entry is bad. Does not do locking. + * @param kkey: must have data pointer set correctly + * @return true if it is bad. + */ +int key_entry_isbad(struct key_entry_key* kkey); + +/** + * Set reason why a key is bad. + * @param kkey: bad key. + * @param reason: string to attach, you must allocate it. + * Not safe to call twice unless you deallocate it yourself. + */ +void key_entry_set_reason(struct key_entry_key* kkey, char* reason); + +/** + * Get reason why a key is bad. + * @param kkey: bad key + * @return pointer to string. + * String is part of key entry and is deleted with it. + */ +char* key_entry_get_reason(struct key_entry_key* kkey); + +/** + * Create a null entry, in the given region. + * @param region: where to allocate + * @param name: the key name + * @param namelen: length of name + * @param dclass: class of key entry. (host order); + * @param ttl: what ttl should the key have. relative. + * @param now: current time (added to ttl). + * @return new key entry or NULL on alloc failure + */ +struct key_entry_key* key_entry_create_null(struct regional* region, + uint8_t* name, size_t namelen, uint16_t dclass, uint32_t ttl, + uint32_t now); + +/** + * Create a key entry from an rrset, in the given region. + * @param region: where to allocate. + * @param name: the key name + * @param namelen: length of name + * @param dclass: class of key entry. (host order); + * @param rrset: data for key entry. This is copied to the region. + * @param sigalg: signalled algorithm list (or NULL). + * @param now: current time (added to ttl of rrset) + * @return new key entry or NULL on alloc failure + */ +struct key_entry_key* key_entry_create_rrset(struct regional* region, + uint8_t* name, size_t namelen, uint16_t dclass, + struct ub_packed_rrset_key* rrset, uint8_t* sigalg, uint32_t now); + +/** + * Create a bad entry, in the given region. + * @param region: where to allocate + * @param name: the key name + * @param namelen: length of name + * @param dclass: class of key entry. (host order); + * @param ttl: what ttl should the key have. relative. + * @param now: current time (added to ttl). + * @return new key entry or NULL on alloc failure + */ +struct key_entry_key* key_entry_create_bad(struct regional* region, + uint8_t* name, size_t namelen, uint16_t dclass, uint32_t ttl, + uint32_t now); + +/** + * Obtain rrset from a key entry, allocated in region. + * @param kkey: key entry to convert to a rrset. + * @param region: where to allocate rrset + * @return rrset copy; if no rrset or alloc error returns NULL. + */ +struct ub_packed_rrset_key* key_entry_get_rrset(struct key_entry_key* kkey, + struct regional* region); + +/** + * Get keysize of the keyentry. + * @param kkey: key, must be a good key, with contents. + * @return size in bits of the key. + */ +size_t key_entry_keysize(struct key_entry_key* kkey); + +#endif /* VALIDATOR_VAL_KENTRY_H */ diff --git a/validator/val_neg.c b/validator/val_neg.c new file mode 100644 index 00000000000..60434db0338 --- /dev/null +++ b/validator/val_neg.c @@ -0,0 +1,1455 @@ +/* + * validator/val_neg.c - validator aggressive negative caching functions. + * + * Copyright (c) 2008, 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains helper functions for the validator module. + * The functions help with aggressive negative caching. + * This creates new denials of existance, and proofs for absence of types + * from cached NSEC records. + */ +#include "config.h" +#ifdef HAVE_OPENSSL_SSL_H +#include "openssl/ssl.h" +#endif +#include "validator/val_neg.h" +#include "validator/val_nsec.h" +#include "validator/val_nsec3.h" +#include "validator/val_utils.h" +#include "util/data/dname.h" +#include "util/data/msgreply.h" +#include "util/log.h" +#include "util/net_help.h" +#include "util/config_file.h" +#include "services/cache/rrset.h" +#include "services/cache/dns.h" + +int val_neg_data_compare(const void* a, const void* b) +{ + struct val_neg_data* x = (struct val_neg_data*)a; + struct val_neg_data* y = (struct val_neg_data*)b; + int m; + return dname_canon_lab_cmp(x->name, x->labs, y->name, y->labs, &m); +} + +int val_neg_zone_compare(const void* a, const void* b) +{ + struct val_neg_zone* x = (struct val_neg_zone*)a; + struct val_neg_zone* y = (struct val_neg_zone*)b; + int m; + if(x->dclass != y->dclass) { + if(x->dclass < y->dclass) + return -1; + return 1; + } + return dname_canon_lab_cmp(x->name, x->labs, y->name, y->labs, &m); +} + +struct val_neg_cache* val_neg_create(struct config_file* cfg, size_t maxiter) +{ + struct val_neg_cache* neg = (struct val_neg_cache*)calloc(1, + sizeof(*neg)); + if(!neg) { + log_err("Could not create neg cache: out of memory"); + return NULL; + } + neg->nsec3_max_iter = maxiter; + neg->max = 1024*1024; /* 1 M is thousands of entries */ + if(cfg) neg->max = cfg->neg_cache_size; + rbtree_init(&neg->tree, &val_neg_zone_compare); + lock_basic_init(&neg->lock); + lock_protect(&neg->lock, neg, sizeof(*neg)); + return neg; +} + +size_t val_neg_get_mem(struct val_neg_cache* neg) +{ + size_t result; + lock_basic_lock(&neg->lock); + result = sizeof(*neg) + neg->use; + lock_basic_unlock(&neg->lock); + return result; +} + +/** clear datas on cache deletion */ +static void +neg_clear_datas(rbnode_t* n, void* ATTR_UNUSED(arg)) +{ + struct val_neg_data* d = (struct val_neg_data*)n; + free(d->name); + free(d); +} + +/** clear zones on cache deletion */ +static void +neg_clear_zones(rbnode_t* n, void* ATTR_UNUSED(arg)) +{ + struct val_neg_zone* z = (struct val_neg_zone*)n; + /* delete all the rrset entries in the tree */ + traverse_postorder(&z->tree, &neg_clear_datas, NULL); + free(z->nsec3_salt); + free(z->name); + free(z); +} + +void neg_cache_delete(struct val_neg_cache* neg) +{ + if(!neg) return; + lock_basic_destroy(&neg->lock); + /* delete all the zones in the tree */ + traverse_postorder(&neg->tree, &neg_clear_zones, NULL); + free(neg); +} + +/** + * Put data element at the front of the LRU list. + * @param neg: negative cache with LRU start and end. + * @param data: this data is fronted. + */ +static void neg_lru_front(struct val_neg_cache* neg, + struct val_neg_data* data) +{ + data->prev = NULL; + data->next = neg->first; + if(!neg->first) + neg->last = data; + else neg->first->prev = data; + neg->first = data; +} + +/** + * Remove data element from LRU list. + * @param neg: negative cache with LRU start and end. + * @param data: this data is removed from the list. + */ +static void neg_lru_remove(struct val_neg_cache* neg, + struct val_neg_data* data) +{ + if(data->prev) + data->prev->next = data->next; + else neg->first = data->next; + if(data->next) + data->next->prev = data->prev; + else neg->last = data->prev; +} + +/** + * Touch LRU for data element, put it at the start of the LRU list. + * @param neg: negative cache with LRU start and end. + * @param data: this data is used. + */ +static void neg_lru_touch(struct val_neg_cache* neg, + struct val_neg_data* data) +{ + if(data == neg->first) + return; /* nothing to do */ + /* remove from current lru position */ + neg_lru_remove(neg, data); + /* add at front */ + neg_lru_front(neg, data); +} + +/** + * Delete a zone element from the negative cache. + * May delete other zone elements to keep tree coherent, or + * only mark the element as 'not in use'. + * @param neg: negative cache. + * @param z: zone element to delete. + */ +static void neg_delete_zone(struct val_neg_cache* neg, struct val_neg_zone* z) +{ + struct val_neg_zone* p, *np; + if(!z) return; + log_assert(z->in_use); + log_assert(z->count > 0); + z->in_use = 0; + + /* go up the tree and reduce counts */ + p = z; + while(p) { + log_assert(p->count > 0); + p->count --; + p = p->parent; + } + + /* remove zones with zero count */ + p = z; + while(p && p->count == 0) { + np = p->parent; + (void)rbtree_delete(&neg->tree, &p->node); + neg->use -= p->len + sizeof(*p); + free(p->nsec3_salt); + free(p->name); + free(p); + p = np; + } +} + +void neg_delete_data(struct val_neg_cache* neg, struct val_neg_data* el) +{ + struct val_neg_zone* z; + struct val_neg_data* p, *np; + if(!el) return; + z = el->zone; + log_assert(el->in_use); + log_assert(el->count > 0); + el->in_use = 0; + + /* remove it from the lru list */ + neg_lru_remove(neg, el); + + /* go up the tree and reduce counts */ + p = el; + while(p) { + log_assert(p->count > 0); + p->count --; + p = p->parent; + } + + /* delete 0 count items from tree */ + p = el; + while(p && p->count == 0) { + np = p->parent; + (void)rbtree_delete(&z->tree, &p->node); + neg->use -= p->len + sizeof(*p); + free(p->name); + free(p); + p = np; + } + + /* check if the zone is now unused */ + if(z->tree.count == 0) { + neg_delete_zone(neg, z); + } +} + +/** + * Create more space in negative cache + * The oldest elements are deleted until enough space is present. + * Empty zones are deleted. + * @param neg: negative cache. + * @param need: how many bytes are needed. + */ +static void neg_make_space(struct val_neg_cache* neg, size_t need) +{ + /* delete elements until enough space or its empty */ + while(neg->last && neg->max < neg->use + need) { + neg_delete_data(neg, neg->last); + } +} + +struct val_neg_zone* neg_find_zone(struct val_neg_cache* neg, + uint8_t* nm, size_t len, uint16_t dclass) +{ + struct val_neg_zone lookfor; + struct val_neg_zone* result; + lookfor.node.key = &lookfor; + lookfor.name = nm; + lookfor.len = len; + lookfor.labs = dname_count_labels(lookfor.name); + lookfor.dclass = dclass; + + result = (struct val_neg_zone*) + rbtree_search(&neg->tree, lookfor.node.key); + return result; +} + +/** + * Find the given data + * @param zone: negative zone + * @param nm: what to look for. + * @param len: length of nm + * @param labs: labels in nm + * @return data or NULL if not found. + */ +static struct val_neg_data* neg_find_data(struct val_neg_zone* zone, + uint8_t* nm, size_t len, int labs) +{ + struct val_neg_data lookfor; + struct val_neg_data* result; + lookfor.node.key = &lookfor; + lookfor.name = nm; + lookfor.len = len; + lookfor.labs = labs; + + result = (struct val_neg_data*) + rbtree_search(&zone->tree, lookfor.node.key); + return result; +} + +/** + * Calculate space needed for the data and all its parents + * @param rep: NSEC entries. + * @return size. + */ +static size_t calc_data_need(struct reply_info* rep) +{ + uint8_t* d; + size_t i, len, res = 0; + + for(i=rep->an_numrrsets; ian_numrrsets+rep->ns_numrrsets; i++) { + if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NSEC) { + d = rep->rrsets[i]->rk.dname; + len = rep->rrsets[i]->rk.dname_len; + res = sizeof(struct val_neg_data) + len; + while(!dname_is_root(d)) { + log_assert(len > 1); /* not root label */ + dname_remove_label(&d, &len); + res += sizeof(struct val_neg_data) + len; + } + } + } + return res; +} + +/** + * Calculate space needed for zone and all its parents + * @param d: name of zone + * @param len: length of name + * @return size. + */ +static size_t calc_zone_need(uint8_t* d, size_t len) +{ + size_t res = sizeof(struct val_neg_zone) + len; + while(!dname_is_root(d)) { + log_assert(len > 1); /* not root label */ + dname_remove_label(&d, &len); + res += sizeof(struct val_neg_zone) + len; + } + return res; +} + +/** + * Find closest existing parent zone of the given name. + * @param neg: negative cache. + * @param nm: name to look for + * @param nm_len: length of nm + * @param labs: labelcount of nm. + * @param qclass: class. + * @return the zone or NULL if none found. + */ +static struct val_neg_zone* neg_closest_zone_parent(struct val_neg_cache* neg, + uint8_t* nm, size_t nm_len, int labs, uint16_t qclass) +{ + struct val_neg_zone key; + struct val_neg_zone* result; + rbnode_t* res = NULL; + key.node.key = &key; + key.name = nm; + key.len = nm_len; + key.labs = labs; + key.dclass = qclass; + if(rbtree_find_less_equal(&neg->tree, &key, &res)) { + /* exact match */ + result = (struct val_neg_zone*)res; + } else { + /* smaller element (or no element) */ + int m; + result = (struct val_neg_zone*)res; + if(!result || result->dclass != qclass) + return NULL; + /* count number of labels matched */ + (void)dname_lab_cmp(result->name, result->labs, key.name, + key.labs, &m); + while(result) { /* go up until qname is subdomain of stub */ + if(result->labs <= m) + break; + result = result->parent; + } + } + return result; +} + +/** + * Find closest existing parent data for the given name. + * @param zone: to look in. + * @param nm: name to look for + * @param nm_len: length of nm + * @param labs: labelcount of nm. + * @return the data or NULL if none found. + */ +static struct val_neg_data* neg_closest_data_parent( + struct val_neg_zone* zone, uint8_t* nm, size_t nm_len, int labs) +{ + struct val_neg_data key; + struct val_neg_data* result; + rbnode_t* res = NULL; + key.node.key = &key; + key.name = nm; + key.len = nm_len; + key.labs = labs; + if(rbtree_find_less_equal(&zone->tree, &key, &res)) { + /* exact match */ + result = (struct val_neg_data*)res; + } else { + /* smaller element (or no element) */ + int m; + result = (struct val_neg_data*)res; + if(!result) + return NULL; + /* count number of labels matched */ + (void)dname_lab_cmp(result->name, result->labs, key.name, + key.labs, &m); + while(result) { /* go up until qname is subdomain of stub */ + if(result->labs <= m) + break; + result = result->parent; + } + } + return result; +} + +/** + * Create a single zone node + * @param nm: name for zone (copied) + * @param nm_len: length of name + * @param labs: labels in name. + * @param dclass: class of zone, host order. + * @return new zone or NULL on failure + */ +static struct val_neg_zone* neg_setup_zone_node( + uint8_t* nm, size_t nm_len, int labs, uint16_t dclass) +{ + struct val_neg_zone* zone = + (struct val_neg_zone*)calloc(1, sizeof(*zone)); + if(!zone) { + return NULL; + } + zone->node.key = zone; + zone->name = memdup(nm, nm_len); + if(!zone->name) { + free(zone); + return NULL; + } + zone->len = nm_len; + zone->labs = labs; + zone->dclass = dclass; + + rbtree_init(&zone->tree, &val_neg_data_compare); + return zone; +} + +/** + * Create a linked list of parent zones, starting at longname ending on + * the parent (can be NULL, creates to the root). + * @param nm: name for lowest in chain + * @param nm_len: length of name + * @param labs: labels in name. + * @param dclass: class of zone. + * @param parent: NULL for to root, else so it fits under here. + * @return zone; a chain of zones and their parents up to the parent. + * or NULL on malloc failure + */ +static struct val_neg_zone* neg_zone_chain( + uint8_t* nm, size_t nm_len, int labs, uint16_t dclass, + struct val_neg_zone* parent) +{ + int i; + int tolabs = parent?parent->labs:0; + struct val_neg_zone* zone, *prev = NULL, *first = NULL; + + /* create the new subtree, i is labelcount of current creation */ + /* this creates a 'first' to z->parent=NULL list of zones */ + for(i=labs; i!=tolabs; i--) { + /* create new item */ + zone = neg_setup_zone_node(nm, nm_len, i, dclass); + if(!zone) { + /* need to delete other allocations in this routine!*/ + struct val_neg_zone* p=first, *np; + while(p) { + np = p->parent; + free(p); + free(p->name); + p = np; + } + return NULL; + } + if(i == labs) { + first = zone; + } else { + prev->parent = zone; + } + /* prepare for next name */ + prev = zone; + dname_remove_label(&nm, &nm_len); + } + return first; +} + +void val_neg_zone_take_inuse(struct val_neg_zone* zone) +{ + if(!zone->in_use) { + struct val_neg_zone* p; + zone->in_use = 1; + /* increase usage count of all parents */ + for(p=zone; p; p = p->parent) { + p->count++; + } + } +} + +struct val_neg_zone* neg_create_zone(struct val_neg_cache* neg, + uint8_t* nm, size_t nm_len, uint16_t dclass) +{ + struct val_neg_zone* zone; + struct val_neg_zone* parent; + struct val_neg_zone* p, *np; + int labs = dname_count_labels(nm); + + /* find closest enclosing parent zone that (still) exists */ + parent = neg_closest_zone_parent(neg, nm, nm_len, labs, dclass); + if(parent && query_dname_compare(parent->name, nm) == 0) + return parent; /* already exists, weird */ + /* if parent exists, it is in use */ + log_assert(!parent || parent->count > 0); + zone = neg_zone_chain(nm, nm_len, labs, dclass, parent); + if(!zone) { + return NULL; + } + + /* insert the list of zones into the tree */ + p = zone; + while(p) { + np = p->parent; + /* mem use */ + neg->use += sizeof(struct val_neg_zone) + p->len; + /* insert in tree */ + (void)rbtree_insert(&neg->tree, &p->node); + /* last one needs proper parent pointer */ + if(np == NULL) + p->parent = parent; + p = np; + } + return zone; +} + +/** find zone name of message, returns the SOA record */ +static struct ub_packed_rrset_key* reply_find_soa(struct reply_info* rep) +{ + size_t i; + for(i=rep->an_numrrsets; i< rep->an_numrrsets+rep->ns_numrrsets; i++){ + if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_SOA) + return rep->rrsets[i]; + } + return NULL; +} + +/** see if the reply has NSEC records worthy of caching */ +static int reply_has_nsec(struct reply_info* rep) +{ + size_t i; + struct packed_rrset_data* d; + if(rep->security != sec_status_secure) + return 0; + for(i=rep->an_numrrsets; i< rep->an_numrrsets+rep->ns_numrrsets; i++){ + if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NSEC) { + d = (struct packed_rrset_data*)rep->rrsets[i]-> + entry.data; + if(d->security == sec_status_secure) + return 1; + } + } + return 0; +} + + +/** + * Create single node of data element. + * @param nm: name (copied) + * @param nm_len: length of name + * @param labs: labels in name. + * @return element with name nm, or NULL malloc failure. + */ +static struct val_neg_data* neg_setup_data_node( + uint8_t* nm, size_t nm_len, int labs) +{ + struct val_neg_data* el; + el = (struct val_neg_data*)calloc(1, sizeof(*el)); + if(!el) { + return NULL; + } + el->node.key = el; + el->name = memdup(nm, nm_len); + if(!el->name) { + free(el); + return NULL; + } + el->len = nm_len; + el->labs = labs; + return el; +} + +/** + * Create chain of data element and parents + * @param nm: name + * @param nm_len: length of name + * @param labs: labels in name. + * @param parent: up to where to make, if NULL up to root label. + * @return lowest element with name nm, or NULL malloc failure. + */ +static struct val_neg_data* neg_data_chain( + uint8_t* nm, size_t nm_len, int labs, struct val_neg_data* parent) +{ + int i; + int tolabs = parent?parent->labs:0; + struct val_neg_data* el, *first = NULL, *prev = NULL; + + /* create the new subtree, i is labelcount of current creation */ + /* this creates a 'first' to z->parent=NULL list of zones */ + for(i=labs; i!=tolabs; i--) { + /* create new item */ + el = neg_setup_data_node(nm, nm_len, i); + if(!el) { + /* need to delete other allocations in this routine!*/ + struct val_neg_data* p = first, *np; + while(p) { + np = p->parent; + free(p); + free(p->name); + p = np; + } + return NULL; + } + if(i == labs) { + first = el; + } else { + prev->parent = el; + } + + /* prepare for next name */ + prev = el; + dname_remove_label(&nm, &nm_len); + } + return first; +} + +/** + * Remove NSEC records between start and end points. + * By walking the tree, the tree is sorted canonically. + * @param neg: negative cache. + * @param zone: the zone + * @param el: element to start walking at. + * @param nsec: the nsec record with the end point + */ +static void wipeout(struct val_neg_cache* neg, struct val_neg_zone* zone, + struct val_neg_data* el, struct ub_packed_rrset_key* nsec) +{ + struct packed_rrset_data* d = (struct packed_rrset_data*)nsec-> + entry.data; + uint8_t* end; + size_t end_len; + int end_labs, m; + rbnode_t* walk, *next; + struct val_neg_data* cur; + uint8_t buf[257]; + /* get endpoint */ + if(!d || d->count == 0 || d->rr_len[0] < 2+1) + return; + if(ntohs(nsec->rk.type) == LDNS_RR_TYPE_NSEC) { + end = d->rr_data[0]+2; + end_len = dname_valid(end, d->rr_len[0]-2); + end_labs = dname_count_labels(end); + } else { + /* NSEC3 */ + if(!nsec3_get_nextowner_b32(nsec, 0, buf, sizeof(buf))) + return; + end = buf; + end_labs = dname_count_size_labels(end, &end_len); + } + + /* sanity check, both owner and end must be below the zone apex */ + if(!dname_subdomain_c(el->name, zone->name) || + !dname_subdomain_c(end, zone->name)) + return; + + /* detect end of zone NSEC ; wipe until the end of zone */ + if(query_dname_compare(end, zone->name) == 0) { + end = NULL; + } + + walk = rbtree_next(&el->node); + while(walk && walk != RBTREE_NULL) { + cur = (struct val_neg_data*)walk; + /* sanity check: must be larger than start */ + if(dname_canon_lab_cmp(cur->name, cur->labs, + el->name, el->labs, &m) <= 0) { + /* r == 0 skip original record. */ + /* r < 0 too small! */ + walk = rbtree_next(walk); + continue; + } + /* stop at endpoint, also data at empty nonterminals must be + * removed (no NSECs there) so everything between + * start and end */ + if(end && dname_canon_lab_cmp(cur->name, cur->labs, + end, end_labs, &m) >= 0) { + break; + } + /* this element has to be deleted, but we cannot do it + * now, because we are walking the tree still ... */ + /* get the next element: */ + next = rbtree_next(walk); + /* now delete the original element, this may trigger + * rbtree rebalances, but really, the next element is + * the one we need. + * But it may trigger delete of other data and the + * entire zone. However, if that happens, this is done + * by deleting the *parents* of the element for deletion, + * and maybe also the entire zone if it is empty. + * But parents are smaller in canonical compare, thus, + * if a larger element exists, then it is not a parent, + * it cannot get deleted, the zone cannot get empty. + * If the next==NULL, then zone can be empty. */ + if(cur->in_use) + neg_delete_data(neg, cur); + walk = next; + } +} + +void neg_insert_data(struct val_neg_cache* neg, + struct val_neg_zone* zone, struct ub_packed_rrset_key* nsec) +{ + struct packed_rrset_data* d; + struct val_neg_data* parent; + struct val_neg_data* el; + uint8_t* nm = nsec->rk.dname; + size_t nm_len = nsec->rk.dname_len; + int labs = dname_count_labels(nsec->rk.dname); + + d = (struct packed_rrset_data*)nsec->entry.data; + if( !(d->security == sec_status_secure || + (d->security == sec_status_unchecked && d->rrsig_count > 0))) + return; + log_nametypeclass(VERB_ALGO, "negcache rr", + nsec->rk.dname, ntohs(nsec->rk.type), + ntohs(nsec->rk.rrset_class)); + + /* find closest enclosing parent data that (still) exists */ + parent = neg_closest_data_parent(zone, nm, nm_len, labs); + if(parent && query_dname_compare(parent->name, nm) == 0) { + /* perfect match already exists */ + log_assert(parent->count > 0); + el = parent; + } else { + struct val_neg_data* p, *np; + + /* create subtree for perfect match */ + /* if parent exists, it is in use */ + log_assert(!parent || parent->count > 0); + + el = neg_data_chain(nm, nm_len, labs, parent); + if(!el) { + log_err("out of memory inserting NSEC negative cache"); + return; + } + el->in_use = 0; /* set on below */ + + /* insert the list of zones into the tree */ + p = el; + while(p) { + np = p->parent; + /* mem use */ + neg->use += sizeof(struct val_neg_data) + p->len; + /* insert in tree */ + p->zone = zone; + (void)rbtree_insert(&zone->tree, &p->node); + /* last one needs proper parent pointer */ + if(np == NULL) + p->parent = parent; + p = np; + } + } + + if(!el->in_use) { + struct val_neg_data* p; + + el->in_use = 1; + /* increase usage count of all parents */ + for(p=el; p; p = p->parent) { + p->count++; + } + + neg_lru_front(neg, el); + } else { + /* in use, bring to front, lru */ + neg_lru_touch(neg, el); + } + + /* if nsec3 store last used parameters */ + if(ntohs(nsec->rk.type) == LDNS_RR_TYPE_NSEC3) { + int h; + uint8_t* s; + size_t slen, it; + if(nsec3_get_params(nsec, 0, &h, &it, &s, &slen) && + it <= neg->nsec3_max_iter && + (h != zone->nsec3_hash || it != zone->nsec3_iter || + slen != zone->nsec3_saltlen || + memcmp(zone->nsec3_salt, s, slen) != 0)) { + uint8_t* sa = memdup(s, slen); + if(sa) { + free(zone->nsec3_salt); + zone->nsec3_salt = sa; + zone->nsec3_saltlen = slen; + zone->nsec3_hash = h; + zone->nsec3_iter = it; + } + } + } + + /* wipe out the cache items between NSEC start and end */ + wipeout(neg, zone, el, nsec); +} + +void val_neg_addreply(struct val_neg_cache* neg, struct reply_info* rep) +{ + size_t i, need; + struct ub_packed_rrset_key* soa; + struct val_neg_zone* zone; + /* see if secure nsecs inside */ + if(!reply_has_nsec(rep)) + return; + /* find the zone name in message */ + soa = reply_find_soa(rep); + if(!soa) + return; + + log_nametypeclass(VERB_ALGO, "negcache insert for zone", + soa->rk.dname, LDNS_RR_TYPE_SOA, ntohs(soa->rk.rrset_class)); + + /* ask for enough space to store all of it */ + need = calc_data_need(rep) + + calc_zone_need(soa->rk.dname, soa->rk.dname_len); + lock_basic_lock(&neg->lock); + neg_make_space(neg, need); + + /* find or create the zone entry */ + zone = neg_find_zone(neg, soa->rk.dname, soa->rk.dname_len, + ntohs(soa->rk.rrset_class)); + if(!zone) { + if(!(zone = neg_create_zone(neg, soa->rk.dname, + soa->rk.dname_len, ntohs(soa->rk.rrset_class)))) { + lock_basic_unlock(&neg->lock); + log_err("out of memory adding negative zone"); + return; + } + } + val_neg_zone_take_inuse(zone); + + /* insert the NSECs */ + for(i=rep->an_numrrsets; i< rep->an_numrrsets+rep->ns_numrrsets; i++){ + if(ntohs(rep->rrsets[i]->rk.type) != LDNS_RR_TYPE_NSEC) + continue; + if(!dname_subdomain_c(rep->rrsets[i]->rk.dname, + zone->name)) continue; + /* insert NSEC into this zone's tree */ + neg_insert_data(neg, zone, rep->rrsets[i]); + } + if(zone->tree.count == 0) { + /* remove empty zone if inserts failed */ + neg_delete_zone(neg, zone); + } + lock_basic_unlock(&neg->lock); +} + +/** + * Lookup closest data record. For NSEC denial. + * @param zone: zone to look in + * @param qname: name to look for. + * @param len: length of name + * @param labs: labels in name + * @param data: data element, exact or smaller or NULL + * @return true if exact match. + */ +static int neg_closest_data(struct val_neg_zone* zone, + uint8_t* qname, size_t len, int labs, struct val_neg_data** data) +{ + struct val_neg_data key; + rbnode_t* r; + key.node.key = &key; + key.name = qname; + key.len = len; + key.labs = labs; + if(rbtree_find_less_equal(&zone->tree, &key, &r)) { + /* exact match */ + *data = (struct val_neg_data*)r; + return 1; + } else { + /* smaller match */ + *data = (struct val_neg_data*)r; + return 0; + } +} + +int val_neg_dlvlookup(struct val_neg_cache* neg, uint8_t* qname, size_t len, + uint16_t qclass, struct rrset_cache* rrset_cache, uint32_t now) +{ + /* lookup closest zone */ + struct val_neg_zone* zone; + struct val_neg_data* data; + int labs; + struct ub_packed_rrset_key* nsec; + struct packed_rrset_data* d; + uint32_t flags; + uint8_t* wc; + struct query_info qinfo; + if(!neg) return 0; + + log_nametypeclass(VERB_ALGO, "negcache dlvlookup", qname, + LDNS_RR_TYPE_DLV, qclass); + + labs = dname_count_labels(qname); + lock_basic_lock(&neg->lock); + zone = neg_closest_zone_parent(neg, qname, len, labs, qclass); + while(zone && !zone->in_use) + zone = zone->parent; + if(!zone) { + lock_basic_unlock(&neg->lock); + return 0; + } + log_nametypeclass(VERB_ALGO, "negcache zone", zone->name, 0, + zone->dclass); + + /* DLV is defined to use NSEC only */ + if(zone->nsec3_hash) { + lock_basic_unlock(&neg->lock); + return 0; + } + + /* lookup closest data record */ + (void)neg_closest_data(zone, qname, len, labs, &data); + while(data && !data->in_use) + data = data->parent; + if(!data) { + lock_basic_unlock(&neg->lock); + return 0; + } + log_nametypeclass(VERB_ALGO, "negcache rr", data->name, + LDNS_RR_TYPE_NSEC, zone->dclass); + + /* lookup rrset in rrset cache */ + flags = 0; + if(query_dname_compare(data->name, zone->name) == 0) + flags = PACKED_RRSET_NSEC_AT_APEX; + nsec = rrset_cache_lookup(rrset_cache, data->name, data->len, + LDNS_RR_TYPE_NSEC, zone->dclass, flags, now, 0); + + /* check if secure and TTL ok */ + if(!nsec) { + lock_basic_unlock(&neg->lock); + return 0; + } + d = (struct packed_rrset_data*)nsec->entry.data; + if(!d || now > d->ttl) { + lock_rw_unlock(&nsec->entry.lock); + /* delete data record if expired */ + neg_delete_data(neg, data); + lock_basic_unlock(&neg->lock); + return 0; + } + if(d->security != sec_status_secure) { + lock_rw_unlock(&nsec->entry.lock); + neg_delete_data(neg, data); + lock_basic_unlock(&neg->lock); + return 0; + } + verbose(VERB_ALGO, "negcache got secure rrset"); + + /* check NSEC security */ + /* check if NSEC proves no DLV type exists */ + /* check if NSEC proves NXDOMAIN for qname */ + qinfo.qname = qname; + qinfo.qtype = LDNS_RR_TYPE_DLV; + qinfo.qclass = qclass; + if(!nsec_proves_nodata(nsec, &qinfo, &wc) && + !val_nsec_proves_name_error(nsec, qname)) { + /* the NSEC is not a denial for the DLV */ + lock_rw_unlock(&nsec->entry.lock); + lock_basic_unlock(&neg->lock); + verbose(VERB_ALGO, "negcache not proven"); + return 0; + } + /* so the NSEC was a NODATA proof, or NXDOMAIN proof. */ + + /* no need to check for wildcard NSEC; no wildcards in DLV repos */ + /* no need to lookup SOA record for client; no response message */ + + lock_rw_unlock(&nsec->entry.lock); + /* if OK touch the LRU for neg_data element */ + neg_lru_touch(neg, data); + lock_basic_unlock(&neg->lock); + verbose(VERB_ALGO, "negcache DLV denial proven"); + return 1; +} + +/** see if the reply has signed NSEC records and return the signer */ +static uint8_t* reply_nsec_signer(struct reply_info* rep, size_t* signer_len, + uint16_t* dclass) +{ + size_t i; + struct packed_rrset_data* d; + uint8_t* s; + for(i=rep->an_numrrsets; i< rep->an_numrrsets+rep->ns_numrrsets; i++){ + if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NSEC || + ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NSEC3) { + d = (struct packed_rrset_data*)rep->rrsets[i]-> + entry.data; + /* return first signer name of first NSEC */ + if(d->rrsig_count != 0) { + val_find_rrset_signer(rep->rrsets[i], + &s, signer_len); + if(s && *signer_len) { + *dclass = ntohs(rep->rrsets[i]-> + rk.rrset_class); + return s; + } + } + } + } + return 0; +} + +void val_neg_addreferral(struct val_neg_cache* neg, struct reply_info* rep, + uint8_t* zone_name) +{ + size_t i, need; + uint8_t* signer; + size_t signer_len; + uint16_t dclass; + struct val_neg_zone* zone; + /* no SOA in this message, find RRSIG over NSEC's signer name. + * note the NSEC records are maybe not validated yet */ + signer = reply_nsec_signer(rep, &signer_len, &dclass); + if(!signer) + return; + if(!dname_subdomain_c(signer, zone_name)) { + /* the signer is not in the bailiwick, throw it out */ + return; + } + + log_nametypeclass(VERB_ALGO, "negcache insert referral ", + signer, LDNS_RR_TYPE_NS, dclass); + + /* ask for enough space to store all of it */ + need = calc_data_need(rep) + calc_zone_need(signer, signer_len); + lock_basic_lock(&neg->lock); + neg_make_space(neg, need); + + /* find or create the zone entry */ + zone = neg_find_zone(neg, signer, signer_len, dclass); + if(!zone) { + if(!(zone = neg_create_zone(neg, signer, signer_len, + dclass))) { + lock_basic_unlock(&neg->lock); + log_err("out of memory adding negative zone"); + return; + } + } + val_neg_zone_take_inuse(zone); + + /* insert the NSECs */ + for(i=rep->an_numrrsets; i< rep->an_numrrsets+rep->ns_numrrsets; i++){ + if(ntohs(rep->rrsets[i]->rk.type) != LDNS_RR_TYPE_NSEC && + ntohs(rep->rrsets[i]->rk.type) != LDNS_RR_TYPE_NSEC3) + continue; + if(!dname_subdomain_c(rep->rrsets[i]->rk.dname, + zone->name)) continue; + /* insert NSEC into this zone's tree */ + neg_insert_data(neg, zone, rep->rrsets[i]); + } + if(zone->tree.count == 0) { + /* remove empty zone if inserts failed */ + neg_delete_zone(neg, zone); + } + lock_basic_unlock(&neg->lock); +} + +/** + * Check that an NSEC3 rrset does not have a type set. + * None of the nsec3s in a hash-collision are allowed to have the type. + * (since we do not know which one is the nsec3 looked at, flags, ..., we + * ignore the cached item and let it bypass negative caching). + * @param k: the nsec3 rrset to check. + * @param t: type to check + * @return true if no RRs have the type. + */ +static int nsec3_no_type(struct ub_packed_rrset_key* k, uint16_t t) +{ + int count = (int)((struct packed_rrset_data*)k->entry.data)->count; + int i; + for(i=0; ientry.data; + if(d->ttl < now) { + lock_rw_unlock(&k->entry.lock); + return NULL; + } + /* only secure or unchecked records that have signatures. */ + if( ! ( d->security == sec_status_secure || + (d->security == sec_status_unchecked && + d->rrsig_count > 0) ) ) { + lock_rw_unlock(&k->entry.lock); + return NULL; + } + /* check if checktype is absent */ + if(checkbit && ( + (qtype == LDNS_RR_TYPE_NSEC && nsec_has_type(k, checktype)) || + (qtype == LDNS_RR_TYPE_NSEC3 && !nsec3_no_type(k, checktype)) + )) { + lock_rw_unlock(&k->entry.lock); + return NULL; + } + /* looks OK! copy to region and return it */ + r = packed_rrset_copy_region(k, region, now); + /* if it failed, we return the NULL */ + lock_rw_unlock(&k->entry.lock); + return r; +} + +/** find nsec3 closest encloser in neg cache */ +static struct val_neg_data* +neg_find_nsec3_ce(struct val_neg_zone* zone, uint8_t* qname, size_t qname_len, + int qlabs, ldns_buffer* buf, uint8_t* hashnc, size_t* nclen) +{ + struct val_neg_data* data; + uint8_t hashce[SHA_DIGEST_LENGTH]; + uint8_t b32[257]; + size_t celen, b32len; + + *nclen = 0; + while(qlabs > 0) { + /* hash */ + if(!(celen=nsec3_get_hashed(buf, qname, qname_len, + zone->nsec3_hash, zone->nsec3_iter, zone->nsec3_salt, + zone->nsec3_saltlen, hashce, sizeof(hashce)))) + return NULL; + if(!(b32len=nsec3_hash_to_b32(hashce, celen, zone->name, + zone->len, b32, sizeof(b32)))) + return NULL; + + /* lookup (exact match only) */ + data = neg_find_data(zone, b32, b32len, zone->labs+1); + if(data && data->in_use) { + /* found ce match! */ + return data; + } + + *nclen = celen; + memmove(hashnc, hashce, celen); + dname_remove_label(&qname, &qname_len); + qlabs --; + } + return NULL; +} + +/** check nsec3 parameters on nsec3 rrset with current zone values */ +static int +neg_params_ok(struct val_neg_zone* zone, struct ub_packed_rrset_key* rrset) +{ + int h; + uint8_t* s; + size_t slen, it; + if(!nsec3_get_params(rrset, 0, &h, &it, &s, &slen)) + return 0; + return (h == zone->nsec3_hash && it == zone->nsec3_iter && + slen == zone->nsec3_saltlen && + memcmp(zone->nsec3_salt, s, slen) == 0); +} + +/** get next closer for nsec3 proof */ +static struct ub_packed_rrset_key* +neg_nsec3_getnc(struct val_neg_zone* zone, uint8_t* hashnc, size_t nclen, + struct rrset_cache* rrset_cache, struct regional* region, + uint32_t now, uint8_t* b32, size_t maxb32) +{ + struct ub_packed_rrset_key* nc_rrset; + struct val_neg_data* data; + size_t b32len; + + if(!(b32len=nsec3_hash_to_b32(hashnc, nclen, zone->name, + zone->len, b32, maxb32))) + return NULL; + (void)neg_closest_data(zone, b32, b32len, zone->labs+1, &data); + if(!data && zone->tree.count != 0) { + /* could be before the first entry ; return the last + * entry (possibly the rollover nsec3 at end) */ + data = (struct val_neg_data*)rbtree_last(&zone->tree); + } + while(data && !data->in_use) + data = data->parent; + if(!data) + return NULL; + /* got a data element in tree, grab it */ + nc_rrset = grab_nsec(rrset_cache, data->name, data->len, + LDNS_RR_TYPE_NSEC3, zone->dclass, 0, region, 0, 0, now); + if(!nc_rrset) + return NULL; + if(!neg_params_ok(zone, nc_rrset)) + return NULL; + return nc_rrset; +} + +/** neg cache nsec3 proof procedure*/ +static struct dns_msg* +neg_nsec3_proof_ds(struct val_neg_zone* zone, uint8_t* qname, size_t qname_len, + int qlabs, ldns_buffer* buf, struct rrset_cache* rrset_cache, + struct regional* region, uint32_t now, uint8_t* topname) +{ + struct dns_msg* msg; + struct val_neg_data* data; + uint8_t hashnc[SHA_DIGEST_LENGTH]; + size_t nclen; + struct ub_packed_rrset_key* ce_rrset, *nc_rrset; + struct nsec3_cached_hash c; + uint8_t nc_b32[257]; + + /* for NSEC3 ; determine the closest encloser for which we + * can find an exact match. Remember the hashed lower name, + * since that is the one we need a closest match for. + * If we find a match straight away, then it becomes NODATA. + * Otherwise, NXDOMAIN or if OPTOUT, an insecure delegation. + * Also check that parameters are the same on closest encloser + * and on closest match. + */ + if(!zone->nsec3_hash) + return NULL; /* not nsec3 zone */ + + if(!(data=neg_find_nsec3_ce(zone, qname, qname_len, qlabs, buf, + hashnc, &nclen))) { + return NULL; + } + + /* grab the ce rrset */ + ce_rrset = grab_nsec(rrset_cache, data->name, data->len, + LDNS_RR_TYPE_NSEC3, zone->dclass, 0, region, 1, + LDNS_RR_TYPE_DS, now); + if(!ce_rrset) + return NULL; + if(!neg_params_ok(zone, ce_rrset)) + return NULL; + + if(nclen == 0) { + /* exact match, just check the type bits */ + /* need: -SOA, -DS, +NS */ + if(nsec3_has_type(ce_rrset, 0, LDNS_RR_TYPE_SOA) || + nsec3_has_type(ce_rrset, 0, LDNS_RR_TYPE_DS) || + !nsec3_has_type(ce_rrset, 0, LDNS_RR_TYPE_NS)) + return NULL; + if(!(msg = dns_msg_create(qname, qname_len, + LDNS_RR_TYPE_DS, zone->dclass, region, 1))) + return NULL; + /* TTL reduced in grab_nsec */ + if(!dns_msg_authadd(msg, region, ce_rrset, 0)) + return NULL; + return msg; + } + + /* optout is not allowed without knowing the trust-anchor in use, + * otherwise the optout could spoof away that anchor */ + if(!topname) + return NULL; + + /* if there is no exact match, it must be in an optout span + * (an existing DS implies an NSEC3 must exist) */ + nc_rrset = neg_nsec3_getnc(zone, hashnc, nclen, rrset_cache, + region, now, nc_b32, sizeof(nc_b32)); + if(!nc_rrset) + return NULL; + if(!neg_params_ok(zone, nc_rrset)) + return NULL; + if(!nsec3_has_optout(nc_rrset, 0)) + return NULL; + c.hash = hashnc; + c.hash_len = nclen; + c.b32 = nc_b32+1; + c.b32_len = (size_t)nc_b32[0]; + if(nsec3_covers(zone->name, &c, nc_rrset, 0, buf)) { + /* nc_rrset covers the next closer name. + * ce_rrset equals a closer encloser. + * nc_rrset is optout. + * No need to check wildcard for type DS */ + /* capacity=3: ce + nc + soa(if needed) */ + if(!(msg = dns_msg_create(qname, qname_len, + LDNS_RR_TYPE_DS, zone->dclass, region, 3))) + return NULL; + /* now=0 because TTL was reduced in grab_nsec */ + if(!dns_msg_authadd(msg, region, ce_rrset, 0)) + return NULL; + if(!dns_msg_authadd(msg, region, nc_rrset, 0)) + return NULL; + return msg; + } + return NULL; +} + +/** + * Add SOA record for external responses. + * @param rrset_cache: to look into. + * @param now: current time. + * @param region: where to perform the allocation + * @param msg: current msg with NSEC. + * @param zone: val_neg_zone if we have one. + * @return false on lookup or alloc failure. + */ +static int add_soa(struct rrset_cache* rrset_cache, uint32_t now, + struct regional* region, struct dns_msg* msg, struct val_neg_zone* zone) +{ + struct ub_packed_rrset_key* soa; + uint8_t* nm; + size_t nmlen; + uint16_t dclass; + if(zone) { + nm = zone->name; + nmlen = zone->len; + dclass = zone->dclass; + } else { + /* Assumes the signer is the zone SOA to add */ + nm = reply_nsec_signer(msg->rep, &nmlen, &dclass); + if(!nm) + return 0; + } + soa = rrset_cache_lookup(rrset_cache, nm, nmlen, LDNS_RR_TYPE_SOA, + dclass, PACKED_RRSET_SOA_NEG, now, 0); + if(!soa) + return 0; + if(!dns_msg_authadd(msg, region, soa, now)) { + lock_rw_unlock(&soa->entry.lock); + return 0; + } + lock_rw_unlock(&soa->entry.lock); + return 1; +} + +struct dns_msg* +val_neg_getmsg(struct val_neg_cache* neg, struct query_info* qinfo, + struct regional* region, struct rrset_cache* rrset_cache, + ldns_buffer* buf, uint32_t now, int addsoa, uint8_t* topname) +{ + struct dns_msg* msg; + struct ub_packed_rrset_key* rrset; + uint8_t* zname; + size_t zname_len; + int zname_labs; + struct val_neg_zone* zone; + + /* only for DS queries */ + if(qinfo->qtype != LDNS_RR_TYPE_DS) + return NULL; + log_assert(!topname || dname_subdomain_c(qinfo->qname, topname)); + + /* see if info from neg cache is available + * For NSECs, because there is no optout; a DS next to a delegation + * always has exactly an NSEC for it itself; check its DS bit. + * flags=0 (not the zone apex). + */ + rrset = grab_nsec(rrset_cache, qinfo->qname, qinfo->qname_len, + LDNS_RR_TYPE_NSEC, qinfo->qclass, 0, region, 1, + qinfo->qtype, now); + if(rrset) { + /* return msg with that rrset */ + if(!(msg = dns_msg_create(qinfo->qname, qinfo->qname_len, + qinfo->qtype, qinfo->qclass, region, 2))) + return NULL; + /* TTL already subtracted in grab_nsec */ + if(!dns_msg_authadd(msg, region, rrset, 0)) + return NULL; + if(addsoa && !add_soa(rrset_cache, now, region, msg, NULL)) + return NULL; + return msg; + } + + /* check NSEC3 neg cache for type DS */ + /* need to look one zone higher for DS type */ + zname = qinfo->qname; + zname_len = qinfo->qname_len; + dname_remove_label(&zname, &zname_len); + zname_labs = dname_count_labels(zname); + + /* lookup closest zone */ + lock_basic_lock(&neg->lock); + zone = neg_closest_zone_parent(neg, zname, zname_len, zname_labs, + qinfo->qclass); + while(zone && !zone->in_use) + zone = zone->parent; + /* check that the zone is not too high up so that we do not pick data + * out of a zone that is above the last-seen key (or trust-anchor). */ + if(zone && topname) { + if(!dname_subdomain_c(zone->name, topname)) + zone = NULL; + } + if(!zone) { + lock_basic_unlock(&neg->lock); + return NULL; + } + + msg = neg_nsec3_proof_ds(zone, qinfo->qname, qinfo->qname_len, + zname_labs+1, buf, rrset_cache, region, now, topname); + if(msg && addsoa && !add_soa(rrset_cache, now, region, msg, zone)) { + lock_basic_unlock(&neg->lock); + return NULL; + } + lock_basic_unlock(&neg->lock); + return msg; +} diff --git a/validator/val_neg.h b/validator/val_neg.h new file mode 100644 index 00000000000..01b423e1afb --- /dev/null +++ b/validator/val_neg.h @@ -0,0 +1,314 @@ +/* + * validator/val_neg.h - validator aggressive negative caching functions. + * + * Copyright (c) 2008, 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains helper functions for the validator module. + * The functions help with aggressive negative caching. + * This creates new denials of existance, and proofs for absence of types + * from cached NSEC records. + */ + +#ifndef VALIDATOR_VAL_NEG_H +#define VALIDATOR_VAL_NEG_H +#include "util/locks.h" +#include "util/rbtree.h" +struct val_neg_data; +struct config_file; +struct reply_info; +struct rrset_cache; +struct regional; +struct query_info; +struct dns_msg; +struct ub_packed_rrset_key; + +/** + * The negative cache. It is shared between the threads, so locked. + * Kept as validator-environ-state. It refers back to the rrset cache for + * data elements. It can be out of date and contain conflicting data + * from zone content changes. + * It contains a tree of zones, every zone has a tree of data elements. + * The data elements are part of one big LRU list, with one memory counter. + */ +struct val_neg_cache { + /** the big lock on the negative cache. Because we use a rbtree + * for the data (quick lookup), we need a big lock */ + lock_basic_t lock; + /** The zone rbtree. contents sorted canonical, type val_neg_zone */ + rbtree_t tree; + /** the first in linked list of LRU of val_neg_data */ + struct val_neg_data* first; + /** last in lru (least recently used element) */ + struct val_neg_data* last; + /** current memory in use (bytes) */ + size_t use; + /** max memory to use (bytes) */ + size_t max; + /** max nsec3 iterations allowed */ + size_t nsec3_max_iter; +}; + +/** + * Per Zone aggressive negative caching data. + */ +struct val_neg_zone { + /** rbtree node element, key is this struct: the name, class */ + rbnode_t node; + /** name; the key */ + uint8_t* name; + /** length of name */ + size_t len; + /** labels in name */ + int labs; + + /** pointer to parent zone in the negative cache */ + struct val_neg_zone* parent; + + /** the number of elements, including this one and the ones whose + * parents (-parents) include this one, that are in_use + * No elements have a count of zero, those are removed. */ + int count; + + /** if 0: NSEC zone, else NSEC3 hash algorithm in use */ + int nsec3_hash; + /** nsec3 iteration count in use */ + size_t nsec3_iter; + /** nsec3 salt in use */ + uint8_t* nsec3_salt; + /** length of salt in bytes */ + size_t nsec3_saltlen; + + /** tree of NSEC data for this zone, sorted canonical + * by NSEC owner name */ + rbtree_t tree; + + /** class of node; host order */ + uint16_t dclass; + /** if this element is in use, boolean */ + uint8_t in_use; +}; + +/** + * Data element for aggressive negative caching. + * The tree of these elements acts as an index onto the rrset cache. + * It shows the NSEC records that (may) exist and are (possibly) secure. + * The rbtree allows for logN search for a covering NSEC record. + * To make tree insertion and deletion logN too, all the parent (one label + * less than the name) data elements are also in the rbtree, with a usage + * count for every data element. + * There is no actual data stored in this data element, if it is in_use, + * then the data can (possibly) be found in the rrset cache. + */ +struct val_neg_data { + /** rbtree node element, key is this struct: the name */ + rbnode_t node; + /** name; the key */ + uint8_t* name; + /** length of name */ + size_t len; + /** labels in name */ + int labs; + + /** pointer to parent node in the negative cache */ + struct val_neg_data* parent; + + /** the number of elements, including this one and the ones whose + * parents (-parents) include this one, that are in use + * No elements have a count of zero, those are removed. */ + int count; + + /** the zone that this denial is part of */ + struct val_neg_zone* zone; + + /** previous in LRU */ + struct val_neg_data* prev; + /** next in LRU (next element was less recently used) */ + struct val_neg_data* next; + + /** if this element is in use, boolean */ + uint8_t in_use; +}; + +/** + * Create negative cache + * @param cfg: config options. + * @param maxiter: max nsec3 iterations allowed. + * @return neg cache, empty or NULL on failure. + */ +struct val_neg_cache* val_neg_create(struct config_file* cfg, size_t maxiter); + +/** + * see how much memory is in use by the negative cache. + * @param neg: negative cache + * @return number of bytes in use. + */ +size_t val_neg_get_mem(struct val_neg_cache* neg); + +/** + * Destroy negative cache. There must no longer be any other threads. + * @param neg: negative cache. + */ +void neg_cache_delete(struct val_neg_cache* neg); + +/** + * Comparison function for rbtree val neg data elements + */ +int val_neg_data_compare(const void* a, const void* b); + +/** + * Comparison function for rbtree val neg zone elements + */ +int val_neg_zone_compare(const void* a, const void* b); + +/** + * Insert NSECs from this message into the negative cache for reference. + * @param neg: negative cache + * @param rep: reply with NSECs. + * Errors are ignored, means that storage is omitted. + */ +void val_neg_addreply(struct val_neg_cache* neg, struct reply_info* rep); + +/** + * Insert NSECs from this referral into the negative cache for reference. + * @param neg: negative cache + * @param rep: referral reply with NS, NSECs. + * @param zone: bailiwick for the referral. + * Errors are ignored, means that storage is omitted. + */ +void val_neg_addreferral(struct val_neg_cache* neg, struct reply_info* rep, + uint8_t* zone); + +/** + * Perform a DLV style lookup + * During the lookup, we could find out that data has expired. In that + * case the neg_cache entries are removed, and lookup fails. + * + * @param neg: negative cache. + * @param qname: name to look for + * @param len: length of qname. + * @param qclass: class to look in. + * @param rrset_cache: the rrset cache, for NSEC lookups. + * @param now: current time for ttl checks. + * @return + * 0 on error + * 0 if no proof of negative + * 1 if indeed negative was proven + * thus, qname DLV qclass does not exist. + */ +int val_neg_dlvlookup(struct val_neg_cache* neg, uint8_t* qname, size_t len, + uint16_t qclass, struct rrset_cache* rrset_cache, uint32_t now); + +/** + * For the given query, try to get a reply out of the negative cache. + * The reply still needs to be validated. + * @param neg: negative cache. + * @param qinfo: query + * @param region: where to allocate reply. + * @param rrset_cache: rrset cache. + * @param buf: temporary buffer. + * @param now: to check TTLs against. + * @param addsoa: if true, produce result for external consumption. + * if false, do not add SOA - for unbound-internal consumption. + * @param topname: do not look higher than this name, + * so that the result cannot be taken from a zone above the current + * trust anchor. Which could happen with multiple islands of trust. + * if NULL, then no trust anchor is used, but also the algorithm becomes + * more conservative, especially for opt-out zones, since the receiver + * may have a trust-anchor below the optout and thus the optout cannot + * be used to create a proof from the negative cache. + * @return a reply message if something was found. + * This reply may still need validation. + * NULL if nothing found (or out of memory). + */ +struct dns_msg* val_neg_getmsg(struct val_neg_cache* neg, + struct query_info* qinfo, struct regional* region, + struct rrset_cache* rrset_cache, ldns_buffer* buf, uint32_t now, + int addsoa, uint8_t* topname); + + +/**** functions exposed for unit test ****/ +/** + * Insert data into the data tree of a zone + * Does not do locking. + * @param neg: negative cache + * @param zone: zone to insert into + * @param nsec: record to insert. + */ +void neg_insert_data(struct val_neg_cache* neg, + struct val_neg_zone* zone, struct ub_packed_rrset_key* nsec); + +/** + * Delete a data element from the negative cache. + * May delete other data elements to keep tree coherent, or + * only mark the element as 'not in use'. + * Does not do locking. + * @param neg: negative cache. + * @param el: data element to delete. + */ +void neg_delete_data(struct val_neg_cache* neg, struct val_neg_data* el); + +/** + * Find the given zone, from the SOA owner name and class + * Does not do locking. + * @param neg: negative cache + * @param nm: what to look for. + * @param len: length of nm + * @param dclass: class to look for. + * @return zone or NULL if not found. + */ +struct val_neg_zone* neg_find_zone(struct val_neg_cache* neg, + uint8_t* nm, size_t len, uint16_t dclass); + +/** + * Create a new zone. + * Does not do locking. + * @param neg: negative cache + * @param nm: what to look for. + * @param nm_len: length of name. + * @param dclass: class of zone, host order. + * @return zone or NULL if out of memory. + */ +struct val_neg_zone* neg_create_zone(struct val_neg_cache* neg, + uint8_t* nm, size_t nm_len, uint16_t dclass); + +/** + * take a zone into use. increases counts of parents. + * Does not do locking. + * @param zone: zone to take into use. + */ +void val_neg_zone_take_inuse(struct val_neg_zone* zone); + +#endif /* VALIDATOR_VAL_NEG_H */ diff --git a/validator/val_nsec.c b/validator/val_nsec.c new file mode 100644 index 00000000000..8bda8dabc93 --- /dev/null +++ b/validator/val_nsec.c @@ -0,0 +1,603 @@ +/* + * validator/val_nsec.c - validator NSEC denial of existance 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains helper functions for the validator module. + * The functions help with NSEC checking, the different NSEC proofs + * for denial of existance, and proofs for presence of types. + */ +#include "config.h" +#include +#include "validator/val_nsec.h" +#include "validator/val_utils.h" +#include "util/data/msgreply.h" +#include "util/data/dname.h" +#include "util/net_help.h" +#include "util/module.h" +#include "services/cache/rrset.h" + +/** get ttl of rrset */ +static uint32_t +rrset_get_ttl(struct ub_packed_rrset_key* k) +{ + struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data; + return d->ttl; +} + +int +nsecbitmap_has_type_rdata(uint8_t* bitmap, size_t len, uint16_t type) +{ + /* Check type present in NSEC typemap with bitmap arg */ + /* bitmasks for determining type-lowerbits presence */ + uint8_t masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; + uint8_t type_window = type>>8; + uint8_t type_low = type&0xff; + uint8_t win, winlen; + /* read each of the type bitmap windows and see if the searched + * type is amongst it */ + while(len > 0) { + if(len < 3) /* bad window, at least window# winlen bitmap */ + return 0; + win = *bitmap++; + winlen = *bitmap++; + len -= 2; + if(len < winlen || winlen < 1 || winlen > 32) + return 0; /* bad window length */ + if(win == type_window) { + /* search window bitmap for the correct byte */ + /* mybyte is 0 if we need the first byte */ + size_t mybyte = type_low>>3; + if(winlen <= mybyte) + return 0; /* window too short */ + return (int)(bitmap[mybyte] & masks[type_low&0x7]); + } else { + /* not the window we are looking for */ + bitmap += winlen; + len -= winlen; + } + } + /* end of bitmap reached, no type found */ + return 0; +} + +int +nsec_has_type(struct ub_packed_rrset_key* nsec, uint16_t type) +{ + struct packed_rrset_data* d = (struct packed_rrset_data*)nsec-> + entry.data; + size_t len; + if(!d || d->count == 0 || d->rr_len[0] < 2+1) + return 0; + len = dname_valid(d->rr_data[0]+2, d->rr_len[0]-2); + if(!len) + return 0; + return nsecbitmap_has_type_rdata(d->rr_data[0]+2+len, + d->rr_len[0]-2-len, type); +} + +/** + * Get next owner name from nsec record + * @param nsec: the nsec RRset. + * If there are multiple RRs, then this will only return one of them. + * @param nm: the next name is returned. + * @param ln: length of nm is returned. + * @return false on a bad NSEC RR (too short, malformed dname). + */ +static int +nsec_get_next(struct ub_packed_rrset_key* nsec, uint8_t** nm, size_t* ln) +{ + struct packed_rrset_data* d = (struct packed_rrset_data*)nsec-> + entry.data; + if(!d || d->count == 0 || d->rr_len[0] < 2+1) { + *nm = 0; + *ln = 0; + return 0; + } + *nm = d->rr_data[0]+2; + *ln = dname_valid(*nm, d->rr_len[0]-2); + if(!*ln) { + *nm = 0; + *ln = 0; + return 0; + } + return 1; +} + +/** + * For an NSEC that matches the DS queried for, check absence of DS type. + * + * @param nsec: NSEC for proof, must be trusted. + * @param qinfo: what is queried for. + * @return if secure the nsec proves that no DS is present, or + * insecure if it proves it is not a delegation point. + * or bogus if something was wrong. + */ +static enum sec_status +val_nsec_proves_no_ds(struct ub_packed_rrset_key* nsec, + struct query_info* qinfo) +{ + log_assert(qinfo->qtype == LDNS_RR_TYPE_DS); + log_assert(ntohs(nsec->rk.type) == LDNS_RR_TYPE_NSEC); + + if(nsec_has_type(nsec, LDNS_RR_TYPE_SOA) && qinfo->qname_len != 1) { + /* SOA present means that this is the NSEC from the child, + * not the parent (so it is the wrong one). */ + return sec_status_bogus; + } + if(nsec_has_type(nsec, LDNS_RR_TYPE_DS)) { + /* DS present means that there should have been a positive + * response to the DS query, so there is something wrong. */ + return sec_status_bogus; + } + + if(!nsec_has_type(nsec, LDNS_RR_TYPE_NS)) { + /* If there is no NS at this point at all, then this + * doesn't prove anything one way or the other. */ + return sec_status_insecure; + } + /* Otherwise, this proves no DS. */ + return sec_status_secure; +} + +/** check security status from cache or verify rrset, returns true if secure */ +static int +nsec_verify_rrset(struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key* nsec, struct key_entry_key* kkey, + char** reason) +{ + struct packed_rrset_data* d = (struct packed_rrset_data*) + nsec->entry.data; + if(d->security == sec_status_secure) + return 1; + rrset_check_sec_status(env->rrset_cache, nsec, *env->now); + if(d->security == sec_status_secure) + return 1; + d->security = val_verify_rrset_entry(env, ve, nsec, kkey, reason); + if(d->security == sec_status_secure) { + rrset_update_sec_status(env->rrset_cache, nsec, *env->now); + return 1; + } + return 0; +} + +enum sec_status +val_nsec_prove_nodata_dsreply(struct module_env* env, struct val_env* ve, + struct query_info* qinfo, struct reply_info* rep, + struct key_entry_key* kkey, uint32_t* proof_ttl, char** reason) +{ + struct ub_packed_rrset_key* nsec = reply_find_rrset_section_ns( + rep, qinfo->qname, qinfo->qname_len, LDNS_RR_TYPE_NSEC, + qinfo->qclass); + enum sec_status sec; + size_t i; + uint8_t* wc = NULL, *ce = NULL; + int valid_nsec = 0; + struct ub_packed_rrset_key* wc_nsec = NULL; + + /* If we have a NSEC at the same name, it must prove one + * of two things + * -- + * 1) this is a delegation point and there is no DS + * 2) this is not a delegation point */ + if(nsec) { + if(!nsec_verify_rrset(env, ve, nsec, kkey, reason)) { + verbose(VERB_ALGO, "NSEC RRset for the " + "referral did not verify."); + return sec_status_bogus; + } + sec = val_nsec_proves_no_ds(nsec, qinfo); + if(sec == sec_status_bogus) { + /* something was wrong. */ + *reason = "NSEC does not prove absence of DS"; + return sec; + } else if(sec == sec_status_insecure) { + /* this wasn't a delegation point. */ + return sec; + } else if(sec == sec_status_secure) { + /* this proved no DS. */ + *proof_ttl = ub_packed_rrset_ttl(nsec); + return sec; + } + /* if unchecked, fall through to next proof */ + } + + /* Otherwise, there is no NSEC at qname. This could be an ENT. + * (ENT=empty non terminal). If not, this is broken. */ + + /* verify NSEC rrsets in auth section */ + for(i=rep->an_numrrsets; i < rep->an_numrrsets+rep->ns_numrrsets; + i++) { + if(rep->rrsets[i]->rk.type != htons(LDNS_RR_TYPE_NSEC)) + continue; + if(!nsec_verify_rrset(env, ve, rep->rrsets[i], kkey, reason)) { + verbose(VERB_ALGO, "NSEC for empty non-terminal " + "did not verify."); + return sec_status_bogus; + } + if(nsec_proves_nodata(rep->rrsets[i], qinfo, &wc)) { + verbose(VERB_ALGO, "NSEC for empty non-terminal " + "proved no DS."); + *proof_ttl = rrset_get_ttl(rep->rrsets[i]); + if(wc && dname_is_wild(rep->rrsets[i]->rk.dname)) + wc_nsec = rep->rrsets[i]; + valid_nsec = 1; + } + if(val_nsec_proves_name_error(rep->rrsets[i], qinfo->qname)) { + ce = nsec_closest_encloser(qinfo->qname, + rep->rrsets[i]); + } + } + if(wc && !ce) + valid_nsec = 0; + else if(wc && ce) { + /* ce and wc must match */ + if(query_dname_compare(wc, ce) != 0) + valid_nsec = 0; + else if(!wc_nsec) + valid_nsec = 0; + } + if(valid_nsec) { + if(wc) { + /* check if this is a delegation */ + *reason = "NSEC for wildcard does not prove absence of DS"; + return val_nsec_proves_no_ds(wc_nsec, qinfo); + } + /* valid nsec proves empty nonterminal */ + return sec_status_insecure; + } + + /* NSEC proof did not conlusively point to DS or no DS */ + return sec_status_unchecked; +} + +int nsec_proves_nodata(struct ub_packed_rrset_key* nsec, + struct query_info* qinfo, uint8_t** wc) +{ + log_assert(wc); + if(query_dname_compare(nsec->rk.dname, qinfo->qname) != 0) { + uint8_t* nm; + size_t ln; + + /* empty-non-terminal checking. + * Done before wildcard, because this is an exact match, + * and would prevent a wildcard from matching. */ + + /* If the nsec is proving that qname is an ENT, the nsec owner + * will be less than qname, and the next name will be a child + * domain of the qname. */ + if(!nsec_get_next(nsec, &nm, &ln)) + return 0; /* bad nsec */ + if(dname_strict_subdomain_c(nm, qinfo->qname) && + dname_canonical_compare(nsec->rk.dname, + qinfo->qname) < 0) { + return 1; /* proves ENT */ + } + + /* wildcard checking. */ + + /* If this is a wildcard NSEC, make sure that a) it was + * possible to have generated qname from the wildcard and + * b) the type map does not contain qtype. Note that this + * does NOT prove that this wildcard was the applicable + * wildcard. */ + if(dname_is_wild(nsec->rk.dname)) { + /* the purported closest encloser. */ + uint8_t* ce = nsec->rk.dname; + size_t ce_len = nsec->rk.dname_len; + dname_remove_label(&ce, &ce_len); + + /* The qname must be a strict subdomain of the + * closest encloser, for the wildcard to apply + */ + if(dname_strict_subdomain_c(qinfo->qname, ce)) { + /* here we have a matching NSEC for the qname, + * perform matching NSEC checks */ + if(nsec_has_type(nsec, LDNS_RR_TYPE_CNAME)) { + /* should have gotten the wildcard CNAME */ + return 0; + } + if(nsec_has_type(nsec, LDNS_RR_TYPE_NS) && + !nsec_has_type(nsec, LDNS_RR_TYPE_SOA)) { + /* wrong parentside (wildcard) NSEC used */ + return 0; + } + if(nsec_has_type(nsec, qinfo->qtype)) { + return 0; + } + *wc = ce; + return 1; + } + } + + /* Otherwise, this NSEC does not prove ENT and is not a + * wildcard, so it does not prove NODATA. */ + return 0; + } + + /* If the qtype exists, then we should have gotten it. */ + if(nsec_has_type(nsec, qinfo->qtype)) { + return 0; + } + + /* if the name is a CNAME node, then we should have gotten the CNAME*/ + if(nsec_has_type(nsec, LDNS_RR_TYPE_CNAME)) { + return 0; + } + + /* If an NS set exists at this name, and NOT a SOA (so this is a + * zone cut, not a zone apex), then we should have gotten a + * referral (or we just got the wrong NSEC). + * The reverse of this check is used when qtype is DS, since that + * must use the NSEC from above the zone cut. */ + if(qinfo->qtype != LDNS_RR_TYPE_DS && + nsec_has_type(nsec, LDNS_RR_TYPE_NS) && + !nsec_has_type(nsec, LDNS_RR_TYPE_SOA)) { + return 0; + } else if(qinfo->qtype == LDNS_RR_TYPE_DS && + nsec_has_type(nsec, LDNS_RR_TYPE_SOA) && + !dname_is_root(qinfo->qname)) { + return 0; + } + + return 1; +} + +int +val_nsec_proves_name_error(struct ub_packed_rrset_key* nsec, uint8_t* qname) +{ + uint8_t* owner = nsec->rk.dname; + uint8_t* next; + size_t nlen; + if(!nsec_get_next(nsec, &next, &nlen)) + return 0; + + /* If NSEC owner == qname, then this NSEC proves that qname exists. */ + if(query_dname_compare(qname, owner) == 0) { + return 0; + } + + /* If NSEC is a parent of qname, we need to check the type map + * If the parent name has a DNAME or is a delegation point, then + * this NSEC is being misused. */ + if(dname_subdomain_c(qname, owner) && + (nsec_has_type(nsec, LDNS_RR_TYPE_DNAME) || + (nsec_has_type(nsec, LDNS_RR_TYPE_NS) + && !nsec_has_type(nsec, LDNS_RR_TYPE_SOA)) + )) { + return 0; + } + + if(query_dname_compare(owner, next) == 0) { + /* this nsec is the only nsec */ + /* zone.name NSEC zone.name, disproves everything else */ + /* but only for subdomains of that zone */ + if(dname_strict_subdomain_c(qname, next)) + return 1; + } + else if(dname_canonical_compare(owner, next) > 0) { + /* this is the last nsec, ....(bigger) NSEC zonename(smaller) */ + /* the names after the last (owner) name do not exist + * there are no names before the zone name in the zone + * but the qname must be a subdomain of the zone name(next). */ + if(dname_canonical_compare(owner, qname) < 0 && + dname_strict_subdomain_c(qname, next)) + return 1; + } else { + /* regular NSEC, (smaller) NSEC (larger) */ + if(dname_canonical_compare(owner, qname) < 0 && + dname_canonical_compare(qname, next) < 0) { + return 1; + } + } + return 0; +} + +int val_nsec_proves_insecuredelegation(struct ub_packed_rrset_key* nsec, + struct query_info* qinfo) +{ + if(nsec_has_type(nsec, LDNS_RR_TYPE_NS) && + !nsec_has_type(nsec, LDNS_RR_TYPE_DS) && + !nsec_has_type(nsec, LDNS_RR_TYPE_SOA)) { + /* see if nsec signals an insecure delegation */ + if(qinfo->qtype == LDNS_RR_TYPE_DS) { + /* if type is DS and qname is equal to nsec, then it + * is an exact match nsec, result not insecure */ + if(dname_strict_subdomain_c(qinfo->qname, + nsec->rk.dname)) + return 1; + } else { + if(dname_subdomain_c(qinfo->qname, nsec->rk.dname)) + return 1; + } + } + return 0; +} + +uint8_t* +nsec_closest_encloser(uint8_t* qname, struct ub_packed_rrset_key* nsec) +{ + uint8_t* next; + size_t nlen; + uint8_t* common1, *common2; + if(!nsec_get_next(nsec, &next, &nlen)) + return NULL; + /* longest common with owner or next name */ + common1 = dname_get_shared_topdomain(nsec->rk.dname, qname); + common2 = dname_get_shared_topdomain(next, qname); + if(dname_count_labels(common1) > dname_count_labels(common2)) + return common1; + return common2; +} + +int val_nsec_proves_positive_wildcard(struct ub_packed_rrset_key* nsec, + struct query_info* qinf, uint8_t* wc) +{ + uint8_t* ce; + /* 1) prove that qname doesn't exist and + * 2) that the correct wildcard was used + * nsec has been verified already. */ + if(!val_nsec_proves_name_error(nsec, qinf->qname)) + return 0; + /* check wildcard name */ + ce = nsec_closest_encloser(qinf->qname, nsec); + if(!ce) + return 0; + if(query_dname_compare(wc, ce) != 0) { + return 0; + } + return 1; +} + +int +val_nsec_proves_no_wc(struct ub_packed_rrset_key* nsec, uint8_t* qname, + size_t qnamelen) +{ + /* Determine if a NSEC record proves the non-existence of a + * wildcard that could have produced qname. */ + int labs; + int i; + uint8_t* ce = nsec_closest_encloser(qname, nsec); + uint8_t* strip; + size_t striplen; + uint8_t buf[LDNS_MAX_DOMAINLEN+3]; + if(!ce) + return 0; + /* we can subtract the closest encloser count - since that is the + * largest shared topdomain with owner and next NSEC name, + * because the NSEC is no proof for names shorter than the owner + * and next names. */ + labs = dname_count_labels(qname) - dname_count_labels(ce); + + for(i=labs; i>0; i--) { + /* i is number of labels to strip off qname, prepend * wild */ + strip = qname; + striplen = qnamelen; + dname_remove_labels(&strip, &striplen, i); + if(striplen > LDNS_MAX_DOMAINLEN-2) + continue; /* too long to prepend wildcard */ + buf[0] = 1; + buf[1] = (uint8_t)'*'; + memmove(buf+2, strip, striplen); + if(val_nsec_proves_name_error(nsec, buf)) { + return 1; + } + } + return 0; +} + +/** + * Find shared topdomain that exists + */ +static void +dlv_topdomain(struct ub_packed_rrset_key* nsec, uint8_t* qname, + uint8_t** nm, size_t* nm_len) +{ + /* make sure reply is part of nm */ + /* take shared topdomain with left of NSEC. */ + + /* because, if empty nonterminal, then right is subdomain of qname. + * and any shared topdomain would be empty nonterminals. + * + * If nxdomain, then the right is bigger, and could have an + * interesting shared topdomain, but if it does have one, it is + * an empty nonterminal. An empty nonterminal shared with the left + * one. */ + int n; + uint8_t* common = dname_get_shared_topdomain(qname, nsec->rk.dname); + n = dname_count_labels(*nm) - dname_count_labels(common); + dname_remove_labels(nm, nm_len, n); +} + +int val_nsec_check_dlv(struct query_info* qinfo, + struct reply_info* rep, uint8_t** nm, size_t* nm_len) +{ + uint8_t* next; + size_t i, nlen; + int c; + /* we should now have a NOERROR/NODATA or NXDOMAIN message */ + if(rep->an_numrrsets != 0) { + return 0; + } + /* is this NOERROR ? */ + if(FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_NOERROR) { + /* it can be a plain NSEC match - go up one more level. */ + /* or its an empty nonterminal - go up to nonempty level */ + for(i=0; ins_numrrsets; i++) { + if(htons(rep->rrsets[i]->rk.type)!=LDNS_RR_TYPE_NSEC || + !nsec_get_next(rep->rrsets[i], &next, &nlen)) + continue; + c = dname_canonical_compare( + rep->rrsets[i]->rk.dname, qinfo->qname); + if(c == 0) { + /* plain match */ + if(nsec_has_type(rep->rrsets[i], + LDNS_RR_TYPE_DLV)) + return 0; + dname_remove_label(nm, nm_len); + return 1; + } else if(c < 0 && + dname_strict_subdomain_c(next, qinfo->qname)) { + /* ENT */ + dlv_topdomain(rep->rrsets[i], qinfo->qname, + nm, nm_len); + return 1; + } + } + return 0; + } + + /* is this NXDOMAIN ? */ + if(FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_NXDOMAIN) { + /* find the qname denial NSEC record. It can tell us + * a closest encloser name; or that we not need bother */ + for(i=0; ins_numrrsets; i++) { + if(htons(rep->rrsets[i]->rk.type) != LDNS_RR_TYPE_NSEC) + continue; + if(val_nsec_proves_name_error(rep->rrsets[i], + qinfo->qname)) { + log_nametypeclass(VERB_ALGO, "topdomain on", + rep->rrsets[i]->rk.dname, + ntohs(rep->rrsets[i]->rk.type), 0); + dlv_topdomain(rep->rrsets[i], qinfo->qname, + nm, nm_len); + return 1; + } + } + return 0; + } + return 0; +} diff --git a/validator/val_nsec.h b/validator/val_nsec.h new file mode 100644 index 00000000000..34f7f63b40e --- /dev/null +++ b/validator/val_nsec.h @@ -0,0 +1,182 @@ +/* + * validator/val_nsec.h - validator NSEC denial of existance 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains helper functions for the validator module. + * The functions help with NSEC checking, the different NSEC proofs + * for denial of existance, and proofs for presence of types. + */ + +#ifndef VALIDATOR_VAL_NSEC_H +#define VALIDATOR_VAL_NSEC_H +#include "util/data/packed_rrset.h" +struct val_env; +struct module_env; +struct ub_packed_rrset_key; +struct reply_info; +struct query_info; +struct key_entry_key; + +/** + * Check DS absence. + * There is a NODATA reply to a DS that needs checking. + * NSECs can prove this is not a delegation point, or sucessfully prove + * that there is no DS. Or this fails. + * + * @param env: module env for rrsig verification routines. + * @param ve: validator env for rrsig verification routines. + * @param qinfo: the DS queried for. + * @param rep: reply received. + * @param kkey: key entry to use for verification of signatures. + * @param proof_ttl: if secure, the TTL of how long this proof lasts. + * @param reason: string explaining why bogus. + * @return security status. + * SECURE: proved absence of DS. + * INSECURE: proved that this was not a delegation point. + * BOGUS: crypto bad, or no absence of DS proven. + * UNCHECKED: there was no way to prove anything (no NSECs, unknown algo). + */ +enum sec_status val_nsec_prove_nodata_dsreply(struct module_env* env, + struct val_env* ve, struct query_info* qinfo, + struct reply_info* rep, struct key_entry_key* kkey, + uint32_t* proof_ttl, char** reason); + +/** + * nsec typemap check, takes an NSEC-type bitmap as argument, checks for type. + * @param bitmap: pointer to the bitmap part of wireformat rdata. + * @param len: length of the bitmap, in bytes. + * @param type: the type (in host order) to check for. + * @return true if the type bit was set in the bitmap. false if not, or + * if the bitmap was malformed in some way. + */ +int nsecbitmap_has_type_rdata(uint8_t* bitmap, size_t len, uint16_t type); + +/** + * Check if type is present in the NSEC typemap + * @param nsec: the nsec RRset. + * If there are multiple RRs, then each must have the same typemap, + * since the typemap represents the types at this domain node. + * @param type: type to check for, host order. + * @return true if present + */ +int nsec_has_type(struct ub_packed_rrset_key* nsec, uint16_t type); + +/** + * Determine if a NSEC proves the NOERROR/NODATA conditions. This will also + * handle the empty non-terminal (ENT) case and partially handle the + * wildcard case. If the ownername of 'nsec' is a wildcard, the validator + * must still be provided proof that qname did not directly exist and that + * the wildcard is, in fact, *.closest_encloser. + * + * @param nsec: the nsec record to check against. + * @param qinfo: the query info. + * @param wc: if the nodata is proven for a wildcard match, the wildcard + * closest encloser is returned, else NULL (wc is unchanged). + * This closest encloser must then match the nameerror given for the + * nextcloser of qname. + * @return true if NSEC proves this. + */ +int nsec_proves_nodata(struct ub_packed_rrset_key* nsec, + struct query_info* qinfo, uint8_t** wc); + +/** + * Determine if the given NSEC proves a NameError (NXDOMAIN) for a given + * qname. + * + * @param nsec: the nsec to check + * @param qname: what was queried. + * @return true if proven. + */ +int val_nsec_proves_name_error(struct ub_packed_rrset_key* nsec, + uint8_t* qname); + +/** + * Determine if the given NSEC proves a positive wildcard response. + * @param nsec: the nsec to check + * @param qinf: what was queried. + * @param wc: wildcard (without *. label) + * @return true if proven. + */ +int val_nsec_proves_positive_wildcard(struct ub_packed_rrset_key* nsec, + struct query_info* qinf, uint8_t* wc); + +/** + * Determine closest encloser of a query name and the NSEC that covers it + * (and thus disproved it). + * A name error must have been proven already, otherwise this will be invalid. + * @param qname: the name queried for. + * @param nsec: the nsec RRset. + * @return closest encloser dname or NULL on error (bad nsec RRset). + */ +uint8_t* nsec_closest_encloser(uint8_t* qname, + struct ub_packed_rrset_key* nsec); + +/** + * Determine if the given NSEC proves that a wildcard match does not exist. + * + * @param nsec: the nsec RRset. + * @param qname: the name queried for. + * @param qnamelen: length of qname. + * @return true if proven. + */ +int val_nsec_proves_no_wc(struct ub_packed_rrset_key* nsec, uint8_t* qname, + size_t qnamelen); + +/** + * Determine the DLV result, what to do with NSEC DLV reply. + * @param qinfo: what was queried for. + * @param rep: the nonpositive reply. + * @param nm: dlv lookup name, to adjust for new lookup name (if needed). + * @param nm_len: length of lookup name. + * @return 0 on error, 1 if a higher point is found. + * If the higher point is above the dlv repo anchor, the qname does + * not exist. + */ +int val_nsec_check_dlv(struct query_info* qinfo, + struct reply_info* rep, uint8_t** nm, size_t* nm_len); + +/** + * Determine if an nsec proves an insecure delegation towards the qname. + * @param nsec: nsec rrset. + * @param qinfo: what was queries for. + * @return 0 if not, 1 if an NSEC that signals an insecure delegation to + * the qname. + */ +int val_nsec_proves_insecuredelegation(struct ub_packed_rrset_key* nsec, + struct query_info* qinfo); + +#endif /* VALIDATOR_VAL_NSEC_H */ diff --git a/validator/val_nsec3.c b/validator/val_nsec3.c new file mode 100644 index 00000000000..a18e3ab31d0 --- /dev/null +++ b/validator/val_nsec3.c @@ -0,0 +1,1446 @@ +/* + * validator/val_nsec3.c - validator NSEC3 denial of existance 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains helper functions for the validator module. + * The functions help with NSEC3 checking, the different NSEC3 proofs + * for denial of existance, and proofs for presence of types. + */ +#include "config.h" +#include +#ifdef HAVE_OPENSSL_SSL_H +#include "openssl/ssl.h" +#endif +#include "validator/val_nsec3.h" +#include "validator/validator.h" +#include "validator/val_kentry.h" +#include "services/cache/rrset.h" +#include "util/regional.h" +#include "util/rbtree.h" +#include "util/module.h" +#include "util/net_help.h" +#include "util/data/packed_rrset.h" +#include "util/data/dname.h" +#include "util/data/msgreply.h" +/* we include nsec.h for the bitmap_has_type function */ +#include "validator/val_nsec.h" + +/** + * This function we get from ldns-compat or from base system + * it returns the number of data bytes stored at the target, or <0 on error. + */ +int ldns_b32_ntop_extended_hex(uint8_t const *src, size_t srclength, + char *target, size_t targsize); +/** + * This function we get from ldns-compat or from base system + * it returns the number of data bytes stored at the target, or <0 on error. + */ +int ldns_b32_pton_extended_hex(char const *src, size_t hashed_owner_str_len, + uint8_t *target, size_t targsize); + +/** + * Closest encloser (ce) proof results + * Contains the ce and the next-closer (nc) proof. + */ +struct ce_response { + /** the closest encloser name */ + uint8_t* ce; + /** length of ce */ + size_t ce_len; + /** NSEC3 record that proved ce. rrset */ + struct ub_packed_rrset_key* ce_rrset; + /** NSEC3 record that proved ce. rr number */ + int ce_rr; + /** NSEC3 record that proved nc. rrset */ + struct ub_packed_rrset_key* nc_rrset; + /** NSEC3 record that proved nc. rr*/ + int nc_rr; +}; + +/** + * Filter conditions for NSEC3 proof + * Used to iterate over the applicable NSEC3 RRs. + */ +struct nsec3_filter { + /** Zone name, only NSEC3 records for this zone are considered */ + uint8_t* zone; + /** length of the zonename */ + size_t zone_len; + /** the list of NSEC3s to filter; array */ + struct ub_packed_rrset_key** list; + /** number of rrsets in list */ + size_t num; + /** class of records for the NSEC3, only this class applies */ + uint16_t fclass; +}; + +/** return number of rrs in an rrset */ +static size_t +rrset_get_count(struct ub_packed_rrset_key* rrset) +{ + struct packed_rrset_data* d = (struct packed_rrset_data*) + rrset->entry.data; + if(!d) return 0; + return d->count; +} + +/** return if nsec3 RR has unknown flags */ +static int +nsec3_unknown_flags(struct ub_packed_rrset_key* rrset, int r) +{ + struct packed_rrset_data* d = (struct packed_rrset_data*) + rrset->entry.data; + log_assert(d && r < (int)d->count); + if(d->rr_len[r] < 2+2) + return 0; /* malformed */ + return (int)(d->rr_data[r][2+1] & NSEC3_UNKNOWN_FLAGS); +} + +int +nsec3_has_optout(struct ub_packed_rrset_key* rrset, int r) +{ + struct packed_rrset_data* d = (struct packed_rrset_data*) + rrset->entry.data; + log_assert(d && r < (int)d->count); + if(d->rr_len[r] < 2+2) + return 0; /* malformed */ + return (int)(d->rr_data[r][2+1] & NSEC3_OPTOUT); +} + +/** return nsec3 RR algorithm */ +static int +nsec3_get_algo(struct ub_packed_rrset_key* rrset, int r) +{ + struct packed_rrset_data* d = (struct packed_rrset_data*) + rrset->entry.data; + log_assert(d && r < (int)d->count); + if(d->rr_len[r] < 2+1) + return 0; /* malformed */ + return (int)(d->rr_data[r][2+0]); +} + +/** return if nsec3 RR has known algorithm */ +static int +nsec3_known_algo(struct ub_packed_rrset_key* rrset, int r) +{ + struct packed_rrset_data* d = (struct packed_rrset_data*) + rrset->entry.data; + log_assert(d && r < (int)d->count); + if(d->rr_len[r] < 2+1) + return 0; /* malformed */ + switch(d->rr_data[r][2+0]) { + case NSEC3_HASH_SHA1: + return 1; + } + return 0; +} + +/** return nsec3 RR iteration count */ +static size_t +nsec3_get_iter(struct ub_packed_rrset_key* rrset, int r) +{ + uint16_t i; + struct packed_rrset_data* d = (struct packed_rrset_data*) + rrset->entry.data; + log_assert(d && r < (int)d->count); + if(d->rr_len[r] < 2+4) + return 0; /* malformed */ + memmove(&i, d->rr_data[r]+2+2, sizeof(i)); + i = ntohs(i); + return (size_t)i; +} + +/** return nsec3 RR salt */ +static int +nsec3_get_salt(struct ub_packed_rrset_key* rrset, int r, + uint8_t** salt, size_t* saltlen) +{ + struct packed_rrset_data* d = (struct packed_rrset_data*) + rrset->entry.data; + log_assert(d && r < (int)d->count); + if(d->rr_len[r] < 2+5) { + *salt = 0; + *saltlen = 0; + return 0; /* malformed */ + } + *saltlen = (size_t)d->rr_data[r][2+4]; + if(d->rr_len[r] < 2+5+(size_t)*saltlen) { + *salt = 0; + *saltlen = 0; + return 0; /* malformed */ + } + *salt = d->rr_data[r]+2+5; + return 1; +} + +int nsec3_get_params(struct ub_packed_rrset_key* rrset, int r, + int* algo, size_t* iter, uint8_t** salt, size_t* saltlen) +{ + if(!nsec3_known_algo(rrset, r) || nsec3_unknown_flags(rrset, r)) + return 0; + if(!nsec3_get_salt(rrset, r, salt, saltlen)) + return 0; + *algo = nsec3_get_algo(rrset, r); + *iter = nsec3_get_iter(rrset, r); + return 1; +} + +int +nsec3_get_nextowner(struct ub_packed_rrset_key* rrset, int r, + uint8_t** next, size_t* nextlen) +{ + size_t saltlen; + struct packed_rrset_data* d = (struct packed_rrset_data*) + rrset->entry.data; + log_assert(d && r < (int)d->count); + if(d->rr_len[r] < 2+5) { + *next = 0; + *nextlen = 0; + return 0; /* malformed */ + } + saltlen = (size_t)d->rr_data[r][2+4]; + if(d->rr_len[r] < 2+5+saltlen+1) { + *next = 0; + *nextlen = 0; + return 0; /* malformed */ + } + *nextlen = (size_t)d->rr_data[r][2+5+saltlen]; + if(d->rr_len[r] < 2+5+saltlen+1+*nextlen) { + *next = 0; + *nextlen = 0; + return 0; /* malformed */ + } + *next = d->rr_data[r]+2+5+saltlen+1; + return 1; +} + +size_t nsec3_hash_to_b32(uint8_t* hash, size_t hashlen, uint8_t* zone, + size_t zonelen, uint8_t* buf, size_t max) +{ + /* write b32 of name, leave one for length */ + int ret; + if(max < hashlen*2+1) /* quick approx of b32, as if hexb16 */ + return 0; + ret = ldns_b32_ntop_extended_hex(hash, hashlen, (char*)buf+1, max-1); + if(ret < 1) + return 0; + buf[0] = (uint8_t)ret; /* length of b32 label */ + ret++; + if(max - ret < zonelen) + return 0; + memmove(buf+ret, zone, zonelen); + return zonelen+(size_t)ret; +} + +size_t nsec3_get_nextowner_b32(struct ub_packed_rrset_key* rrset, int r, + uint8_t* buf, size_t max) +{ + uint8_t* nm, *zone; + size_t nmlen, zonelen; + if(!nsec3_get_nextowner(rrset, r, &nm, &nmlen)) + return 0; + /* append zone name; the owner name must be .zone */ + zone = rrset->rk.dname; + zonelen = rrset->rk.dname_len; + dname_remove_label(&zone, &zonelen); + return nsec3_hash_to_b32(nm, nmlen, zone, zonelen, buf, max); +} + +int +nsec3_has_type(struct ub_packed_rrset_key* rrset, int r, uint16_t type) +{ + uint8_t* bitmap; + size_t bitlen, skiplen; + struct packed_rrset_data* d = (struct packed_rrset_data*) + rrset->entry.data; + log_assert(d && r < (int)d->count); + skiplen = 2+4; + /* skip salt */ + if(d->rr_len[r] < skiplen+1) + return 0; /* malformed, too short */ + skiplen += 1+(size_t)d->rr_data[r][skiplen]; + /* skip next hashed owner */ + if(d->rr_len[r] < skiplen+1) + return 0; /* malformed, too short */ + skiplen += 1+(size_t)d->rr_data[r][skiplen]; + if(d->rr_len[r] < skiplen) + return 0; /* malformed, too short */ + bitlen = d->rr_len[r] - skiplen; + bitmap = d->rr_data[r]+skiplen; + return nsecbitmap_has_type_rdata(bitmap, bitlen, type); +} + +/** + * Iterate through NSEC3 list, per RR + * This routine gives the next RR in the list (or sets rrset null). + * Usage: + * + * size_t rrsetnum; + * int rrnum; + * struct ub_packed_rrset_key* rrset; + * for(rrset=filter_first(filter, &rrsetnum, &rrnum); rrset; + * rrset=filter_next(filter, &rrsetnum, &rrnum)) + * do_stuff; + * + * Also filters out + * o unknown flag NSEC3s + * o unknown algorithm NSEC3s. + * @param filter: nsec3 filter structure. + * @param rrsetnum: in/out rrset number to look at. + * @param rrnum: in/out rr number in rrset to look at. + * @returns ptr to the next rrset (or NULL at end). + */ +static struct ub_packed_rrset_key* +filter_next(struct nsec3_filter* filter, size_t* rrsetnum, int* rrnum) +{ + size_t i; + int r; + uint8_t* nm; + size_t nmlen; + if(!filter->zone) /* empty list */ + return NULL; + for(i=*rrsetnum; inum; i++) { + /* see if RRset qualifies */ + if(ntohs(filter->list[i]->rk.type) != LDNS_RR_TYPE_NSEC3 || + ntohs(filter->list[i]->rk.rrset_class) != + filter->fclass) + continue; + /* check RRset zone */ + nm = filter->list[i]->rk.dname; + nmlen = filter->list[i]->rk.dname_len; + dname_remove_label(&nm, &nmlen); + if(query_dname_compare(nm, filter->zone) != 0) + continue; + if(i == *rrsetnum) + r = (*rrnum) + 1; /* continue at next RR */ + else r = 0; /* new RRset start at first RR */ + for(; r < (int)rrset_get_count(filter->list[i]); r++) { + /* skip unknown flags, algo */ + if(nsec3_unknown_flags(filter->list[i], r) || + !nsec3_known_algo(filter->list[i], r)) + continue; + /* this one is a good target */ + *rrsetnum = i; + *rrnum = r; + return filter->list[i]; + } + } + return NULL; +} + +/** + * Start iterating over NSEC3 records. + * @param filter: the filter structure, must have been filter_init-ed. + * @param rrsetnum: can be undefined on call, inited. + * @param rrnum: can be undefined on call, inited. + * @return first rrset of an NSEC3, together with rrnum this points to + * the first RR to examine. Is NULL on empty list. + */ +static struct ub_packed_rrset_key* +filter_first(struct nsec3_filter* filter, size_t* rrsetnum, int* rrnum) +{ + *rrsetnum = 0; + *rrnum = -1; + return filter_next(filter, rrsetnum, rrnum); +} + +/** see if at least one RR is known (flags, algo) */ +static int +nsec3_rrset_has_known(struct ub_packed_rrset_key* s) +{ + int r; + for(r=0; r < (int)rrset_get_count(s); r++) { + if(!nsec3_unknown_flags(s, r) && nsec3_known_algo(s, r)) + return 1; + } + return 0; +} + +/** + * Initialize the filter structure. + * Finds the zone by looking at available NSEC3 records and best match. + * (skips the unknown flag and unknown algo NSEC3s). + * + * @param filter: nsec3 filter structure. + * @param list: list of rrsets, an array of them. + * @param num: number of rrsets in list. + * @param qinfo: + * query name to match a zone for. + * query type (if DS a higher zone must be chosen) + * qclass, to filter NSEC3s with. + */ +static void +filter_init(struct nsec3_filter* filter, struct ub_packed_rrset_key** list, + size_t num, struct query_info* qinfo) +{ + size_t i; + uint8_t* nm; + size_t nmlen; + filter->zone = NULL; + filter->zone_len = 0; + filter->list = list; + filter->num = num; + filter->fclass = qinfo->qclass; + for(i=0; irk.type) != LDNS_RR_TYPE_NSEC3 || + ntohs(list[i]->rk.rrset_class) != qinfo->qclass) + continue; + /* skip unknown flags, algo */ + if(!nsec3_rrset_has_known(list[i])) + continue; + + /* since NSEC3s are base32.zonename, we can find the zone + * name by stripping off the first label of the record */ + nm = list[i]->rk.dname; + nmlen = list[i]->rk.dname_len; + dname_remove_label(&nm, &nmlen); + /* if we find a domain that can prove about the qname, + * and if this domain is closer to the qname */ + if(dname_subdomain_c(qinfo->qname, nm) && (!filter->zone || + dname_subdomain_c(nm, filter->zone))) { + /* for a type DS do not accept a zone equal to qname*/ + if(qinfo->qtype == LDNS_RR_TYPE_DS && + query_dname_compare(qinfo->qname, nm) == 0 && + !dname_is_root(qinfo->qname)) + continue; + filter->zone = nm; + filter->zone_len = nmlen; + } + } +} + +/** + * Find max iteration count using config settings and key size + * @param ve: validator environment with iteration count config settings. + * @param bits: key size + * @return max iteration count + */ +static size_t +get_max_iter(struct val_env* ve, size_t bits) +{ + int i; + log_assert(ve->nsec3_keyiter_count > 0); + /* round up to nearest config keysize, linear search, keep it small */ + for(i=0; insec3_keyiter_count; i++) { + if(bits <= ve->nsec3_keysize[i]) + return ve->nsec3_maxiter[i]; + } + /* else, use value for biggest key */ + return ve->nsec3_maxiter[ve->nsec3_keyiter_count-1]; +} + +/** + * Determine if any of the NSEC3 rrs iteration count is too high, from key. + * @param ve: validator environment with iteration count config settings. + * @param filter: what NSEC3s to loop over. + * @param kkey: key entry used for verification; used for iteration counts. + * @return 1 if some nsec3s are above the max iteration count. + */ +static int +nsec3_iteration_count_high(struct val_env* ve, struct nsec3_filter* filter, + struct key_entry_key* kkey) +{ + size_t rrsetnum; + int rrnum; + struct ub_packed_rrset_key* rrset; + /* first determine the max number of iterations */ + size_t bits = key_entry_keysize(kkey); + size_t max_iter = get_max_iter(ve, bits); + verbose(VERB_ALGO, "nsec3: keysize %d bits, max iterations %d", + (int)bits, (int)max_iter); + + for(rrset=filter_first(filter, &rrsetnum, &rrnum); rrset; + rrset=filter_next(filter, &rrsetnum, &rrnum)) { + if(nsec3_get_iter(rrset, rrnum) > max_iter) + return 1; + } + return 0; +} + +/* nsec3_cache_compare for rbtree */ +int +nsec3_hash_cmp(const void* c1, const void* c2) +{ + struct nsec3_cached_hash* h1 = (struct nsec3_cached_hash*)c1; + struct nsec3_cached_hash* h2 = (struct nsec3_cached_hash*)c2; + uint8_t* s1, *s2; + size_t s1len, s2len; + int c = query_dname_compare(h1->dname, h2->dname); + if(c != 0) + return c; + /* compare parameters */ + /* if both malformed, its equal, robustness */ + if(nsec3_get_algo(h1->nsec3, h1->rr) != + nsec3_get_algo(h2->nsec3, h2->rr)) { + if(nsec3_get_algo(h1->nsec3, h1->rr) < + nsec3_get_algo(h2->nsec3, h2->rr)) + return -1; + return 1; + } + if(nsec3_get_iter(h1->nsec3, h1->rr) != + nsec3_get_iter(h2->nsec3, h2->rr)) { + if(nsec3_get_iter(h1->nsec3, h1->rr) < + nsec3_get_iter(h2->nsec3, h2->rr)) + return -1; + return 1; + } + (void)nsec3_get_salt(h1->nsec3, h1->rr, &s1, &s1len); + (void)nsec3_get_salt(h2->nsec3, h2->rr, &s2, &s2len); + if(s1len != s2len) { + if(s1len < s2len) + return -1; + return 1; + } + return memcmp(s1, s2, s1len); +} + +size_t +nsec3_get_hashed(ldns_buffer* buf, uint8_t* nm, size_t nmlen, int algo, + size_t iter, uint8_t* salt, size_t saltlen, uint8_t* res, size_t max) +{ + size_t i, hash_len; + /* prepare buffer for first iteration */ + ldns_buffer_clear(buf); + ldns_buffer_write(buf, nm, nmlen); + query_dname_tolower(ldns_buffer_begin(buf)); + ldns_buffer_write(buf, salt, saltlen); + ldns_buffer_flip(buf); + switch(algo) { +#ifdef HAVE_EVP_SHA1 + case NSEC3_HASH_SHA1: + hash_len = SHA_DIGEST_LENGTH; + if(hash_len > max) + return 0; + (void)SHA1((unsigned char*)ldns_buffer_begin(buf), + (unsigned long)ldns_buffer_limit(buf), + (unsigned char*)res); + for(i=0; insec3, c->rr); + size_t iter = nsec3_get_iter(c->nsec3, c->rr); + uint8_t* salt; + size_t saltlen, i; + if(!nsec3_get_salt(c->nsec3, c->rr, &salt, &saltlen)) + return -1; + /* prepare buffer for first iteration */ + ldns_buffer_clear(buf); + ldns_buffer_write(buf, c->dname, c->dname_len); + query_dname_tolower(ldns_buffer_begin(buf)); + ldns_buffer_write(buf, salt, saltlen); + ldns_buffer_flip(buf); + switch(algo) { +#ifdef HAVE_EVP_SHA1 + case NSEC3_HASH_SHA1: + c->hash_len = SHA_DIGEST_LENGTH; + c->hash = (uint8_t*)regional_alloc(region, + c->hash_len); + if(!c->hash) + return 0; + (void)SHA1((unsigned char*)ldns_buffer_begin(buf), + (unsigned long)ldns_buffer_limit(buf), + (unsigned char*)c->hash); + for(i=0; ihash, c->hash_len); + ldns_buffer_write(buf, salt, saltlen); + ldns_buffer_flip(buf); + (void)SHA1( + (unsigned char*)ldns_buffer_begin(buf), + (unsigned long)ldns_buffer_limit(buf), + (unsigned char*)c->hash); + } + break; +#endif /* HAVE_EVP_SHA1 */ + default: + log_err("nsec3 hash of unknown algo %d", algo); + return -1; + } + return 1; +} + +/** perform b32 encoding of hash */ +static int +nsec3_calc_b32(struct regional* region, ldns_buffer* buf, + struct nsec3_cached_hash* c) +{ + int r; + ldns_buffer_clear(buf); + r = ldns_b32_ntop_extended_hex(c->hash, c->hash_len, + (char*)ldns_buffer_begin(buf), ldns_buffer_limit(buf)); + if(r < 1) { + log_err("b32_ntop_extended_hex: error in encoding: %d", r); + return 0; + } + c->b32_len = (size_t)r; + c->b32 = regional_alloc_init(region, ldns_buffer_begin(buf), + c->b32_len); + if(!c->b32) + return 0; + return 1; +} + +int +nsec3_hash_name(rbtree_t* table, struct regional* region, ldns_buffer* buf, + struct ub_packed_rrset_key* nsec3, int rr, uint8_t* dname, + size_t dname_len, struct nsec3_cached_hash** hash) +{ + struct nsec3_cached_hash* c; + struct nsec3_cached_hash looki; +#ifdef UNBOUND_DEBUG + rbnode_t* n; +#endif + int r; + looki.node.key = &looki; + looki.nsec3 = nsec3; + looki.rr = rr; + looki.dname = dname; + looki.dname_len = dname_len; + /* lookup first in cache */ + c = (struct nsec3_cached_hash*)rbtree_search(table, &looki); + if(c) { + *hash = c; + return 1; + } + /* create a new entry */ + c = (struct nsec3_cached_hash*)regional_alloc(region, sizeof(*c)); + if(!c) return 0; + c->node.key = c; + c->nsec3 = nsec3; + c->rr = rr; + c->dname = dname; + c->dname_len = dname_len; + r = nsec3_calc_hash(region, buf, c); + if(r != 1) + return r; + r = nsec3_calc_b32(region, buf, c); + if(r != 1) + return r; +#ifdef UNBOUND_DEBUG + n = +#endif + rbtree_insert(table, &c->node); + log_assert(n); /* cannot be duplicate, just did lookup */ + *hash = c; + return 1; +} + +/** + * compare a label lowercased + */ +static int +label_compare_lower(uint8_t* lab1, uint8_t* lab2, size_t lablen) +{ + size_t i; + for(i=0; irk.dname; + /* compare, does hash of name based on params in this NSEC3 + * match the owner name of this NSEC3? + * name must be: base32 . zone name + * so; first label must not be root label (not zero length), + * and match the b32 encoded hash length, + * and the label content match the b32 encoded hash + * and the rest must be the zone name. + */ + if(hash->b32_len != 0 && (size_t)nm[0] == hash->b32_len && + label_compare_lower(nm+1, hash->b32, hash->b32_len) == 0 && + query_dname_compare(nm+(size_t)nm[0]+1, flt->zone) == 0) { + return 1; + } + return 0; +} + +/** + * Find matching NSEC3 + * Find the NSEC3Record that matches a hash of a name. + * @param env: module environment with temporary region and buffer. + * @param flt: the NSEC3 RR filter, contains zone name and RRs. + * @param ct: cached hashes table. + * @param nm: name to look for. + * @param nmlen: length of name. + * @param rrset: nsec3 that matches is returned here. + * @param rr: rr number in nsec3 rrset that matches. + * @return true if a matching NSEC3 is found, false if not. + */ +static int +find_matching_nsec3(struct module_env* env, struct nsec3_filter* flt, + rbtree_t* ct, uint8_t* nm, size_t nmlen, + struct ub_packed_rrset_key** rrset, int* rr) +{ + size_t i_rs; + int i_rr; + struct ub_packed_rrset_key* s; + struct nsec3_cached_hash* hash; + int r; + + /* this loop skips other-zone and unknown NSEC3s, also non-NSEC3 RRs */ + for(s=filter_first(flt, &i_rs, &i_rr); s; + s=filter_next(flt, &i_rs, &i_rr)) { + /* get name hashed for this NSEC3 RR */ + r = nsec3_hash_name(ct, env->scratch, env->scratch_buffer, + s, i_rr, nm, nmlen, &hash); + if(r == 0) { + log_err("nsec3: malloc failure"); + break; /* alloc failure */ + } else if(r < 0) + continue; /* malformed NSEC3 */ + else if(nsec3_hash_matches_owner(flt, hash, s)) { + *rrset = s; /* rrset with this name */ + *rr = i_rr; /* matches hash with these parameters */ + return 1; + } + } + *rrset = NULL; + *rr = 0; + return 0; +} + +int +nsec3_covers(uint8_t* zone, struct nsec3_cached_hash* hash, + struct ub_packed_rrset_key* rrset, int rr, ldns_buffer* buf) +{ + uint8_t* next, *owner; + size_t nextlen; + int len; + if(!nsec3_get_nextowner(rrset, rr, &next, &nextlen)) + return 0; /* malformed RR proves nothing */ + + /* check the owner name is a hashed value . apex + * base32 encoded values must have equal length. + * hash_value and next hash value must have equal length. */ + if(nextlen != hash->hash_len || hash->hash_len==0||hash->b32_len==0|| + (size_t)*rrset->rk.dname != hash->b32_len || + query_dname_compare(rrset->rk.dname+1+ + (size_t)*rrset->rk.dname, zone) != 0) + return 0; /* bad lengths or owner name */ + + /* This is the "normal case: owner < next and owner < hash < next */ + if(label_compare_lower(rrset->rk.dname+1, hash->b32, + hash->b32_len) < 0 && + memcmp(hash->hash, next, nextlen) < 0) + return 1; + + /* convert owner name from text to binary */ + ldns_buffer_clear(buf); + owner = ldns_buffer_begin(buf); + len = ldns_b32_pton_extended_hex((char*)rrset->rk.dname+1, + hash->b32_len, owner, ldns_buffer_limit(buf)); + if(len<1) + return 0; /* bad owner name in some way */ + if((size_t)len != hash->hash_len || (size_t)len != nextlen) + return 0; /* wrong length */ + + /* this is the end of zone case: next <= owner && + * (hash > owner || hash < next) + * this also covers the only-apex case of next==owner. + */ + if(memcmp(next, owner, nextlen) <= 0 && + ( memcmp(hash->hash, owner, nextlen) > 0 || + memcmp(hash->hash, next, nextlen) < 0)) { + return 1; + } + return 0; +} + +/** + * findCoveringNSEC3 + * Given a name, find a covering NSEC3 from among a list of NSEC3s. + * + * @param env: module environment with temporary region and buffer. + * @param flt: the NSEC3 RR filter, contains zone name and RRs. + * @param ct: cached hashes table. + * @param nm: name to check if covered. + * @param nmlen: length of name. + * @param rrset: covering NSEC3 rrset is returned here. + * @param rr: rr of cover is returned here. + * @return true if a covering NSEC3 is found, false if not. + */ +static int +find_covering_nsec3(struct module_env* env, struct nsec3_filter* flt, + rbtree_t* ct, uint8_t* nm, size_t nmlen, + struct ub_packed_rrset_key** rrset, int* rr) +{ + size_t i_rs; + int i_rr; + struct ub_packed_rrset_key* s; + struct nsec3_cached_hash* hash; + int r; + + /* this loop skips other-zone and unknown NSEC3s, also non-NSEC3 RRs */ + for(s=filter_first(flt, &i_rs, &i_rr); s; + s=filter_next(flt, &i_rs, &i_rr)) { + /* get name hashed for this NSEC3 RR */ + r = nsec3_hash_name(ct, env->scratch, env->scratch_buffer, + s, i_rr, nm, nmlen, &hash); + if(r == 0) { + log_err("nsec3: malloc failure"); + break; /* alloc failure */ + } else if(r < 0) + continue; /* malformed NSEC3 */ + else if(nsec3_covers(flt->zone, hash, s, i_rr, + env->scratch_buffer)) { + *rrset = s; /* rrset with this name */ + *rr = i_rr; /* covers hash with these parameters */ + return 1; + } + } + *rrset = NULL; + *rr = 0; + return 0; +} + +/** + * findClosestEncloser + * Given a name and a list of NSEC3s, find the candidate closest encloser. + * This will be the first ancestor of 'name' (including itself) to have a + * matching NSEC3 RR. + * @param env: module environment with temporary region and buffer. + * @param flt: the NSEC3 RR filter, contains zone name and RRs. + * @param ct: cached hashes table. + * @param qinfo: query that is verified for. + * @param ce: closest encloser information is returned in here. + * @return true if a closest encloser candidate is found, false if not. + */ +static int +nsec3_find_closest_encloser(struct module_env* env, struct nsec3_filter* flt, + rbtree_t* ct, struct query_info* qinfo, struct ce_response* ce) +{ + uint8_t* nm = qinfo->qname; + size_t nmlen = qinfo->qname_len; + + /* This scans from longest name to shortest, so the first match + * we find is the only viable candidate. */ + + /* (David:) FIXME: modify so that the NSEC3 matching the zone apex need + * not be present. (Mark Andrews idea). + * (Wouter:) But make sure you check for DNAME bit in zone apex, + * if the NSEC3 you find is the only NSEC3 in the zone, then this + * may be the case. */ + + while(dname_subdomain_c(nm, flt->zone)) { + if(find_matching_nsec3(env, flt, ct, nm, nmlen, + &ce->ce_rrset, &ce->ce_rr)) { + ce->ce = nm; + ce->ce_len = nmlen; + return 1; + } + dname_remove_label(&nm, &nmlen); + } + return 0; +} + +/** + * Given a qname and its proven closest encloser, calculate the "next + * closest" name. Basically, this is the name that is one label longer than + * the closest encloser that is still a subdomain of qname. + * + * @param qname: query name. + * @param qnamelen: length of qname. + * @param ce: closest encloser + * @param nm: result name. + * @param nmlen: length of nm. + */ +static void +next_closer(uint8_t* qname, size_t qnamelen, uint8_t* ce, + uint8_t** nm, size_t* nmlen) +{ + int strip = dname_count_labels(qname) - dname_count_labels(ce) -1; + *nm = qname; + *nmlen = qnamelen; + if(strip>0) + dname_remove_labels(nm, nmlen, strip); +} + +/** + * proveClosestEncloser + * Given a List of nsec3 RRs, find and prove the closest encloser to qname. + * @param env: module environment with temporary region and buffer. + * @param flt: the NSEC3 RR filter, contains zone name and RRs. + * @param ct: cached hashes table. + * @param qinfo: query that is verified for. + * @param prove_does_not_exist: If true, then if the closest encloser + * turns out to be qname, then null is returned. + * If set true, and the return value is true, then you can be + * certain that the ce.nc_rrset and ce.nc_rr are set properly. + * @param ce: closest encloser information is returned in here. + * @return bogus if no closest encloser could be proven. + * secure if a closest encloser could be proven, ce is set. + * insecure if the closest-encloser candidate turns out to prove + * that an insecure delegation exists above the qname. + */ +static enum sec_status +nsec3_prove_closest_encloser(struct module_env* env, struct nsec3_filter* flt, + rbtree_t* ct, struct query_info* qinfo, int prove_does_not_exist, + struct ce_response* ce) +{ + uint8_t* nc; + size_t nc_len; + /* robust: clean out ce, in case it gets abused later */ + memset(ce, 0, sizeof(*ce)); + + if(!nsec3_find_closest_encloser(env, flt, ct, qinfo, ce)) { + verbose(VERB_ALGO, "nsec3 proveClosestEncloser: could " + "not find a candidate for the closest encloser."); + return sec_status_bogus; + } + log_nametypeclass(VERB_ALGO, "ce candidate", ce->ce, 0, 0); + + if(query_dname_compare(ce->ce, qinfo->qname) == 0) { + if(prove_does_not_exist) { + verbose(VERB_ALGO, "nsec3 proveClosestEncloser: " + "proved that qname existed, bad"); + return sec_status_bogus; + } + /* otherwise, we need to nothing else to prove that qname + * is its own closest encloser. */ + return sec_status_secure; + } + + /* If the closest encloser is actually a delegation, then the + * response should have been a referral. If it is a DNAME, then + * it should have been a DNAME response. */ + if(nsec3_has_type(ce->ce_rrset, ce->ce_rr, LDNS_RR_TYPE_NS) && + !nsec3_has_type(ce->ce_rrset, ce->ce_rr, LDNS_RR_TYPE_SOA)) { + if(!nsec3_has_type(ce->ce_rrset, ce->ce_rr, LDNS_RR_TYPE_DS)) { + verbose(VERB_ALGO, "nsec3 proveClosestEncloser: " + "closest encloser is insecure delegation"); + return sec_status_insecure; + } + verbose(VERB_ALGO, "nsec3 proveClosestEncloser: closest " + "encloser was a delegation, bad"); + return sec_status_bogus; + } + if(nsec3_has_type(ce->ce_rrset, ce->ce_rr, LDNS_RR_TYPE_DNAME)) { + verbose(VERB_ALGO, "nsec3 proveClosestEncloser: closest " + "encloser was a DNAME, bad"); + return sec_status_bogus; + } + + /* Otherwise, we need to show that the next closer name is covered. */ + next_closer(qinfo->qname, qinfo->qname_len, ce->ce, &nc, &nc_len); + if(!find_covering_nsec3(env, flt, ct, nc, nc_len, + &ce->nc_rrset, &ce->nc_rr)) { + verbose(VERB_ALGO, "nsec3: Could not find proof that the " + "candidate encloser was the closest encloser"); + return sec_status_bogus; + } + return sec_status_secure; +} + +/** allocate a wildcard for the closest encloser */ +static uint8_t* +nsec3_ce_wildcard(struct regional* region, uint8_t* ce, size_t celen, + size_t* len) +{ + uint8_t* nm; + if(celen > LDNS_MAX_DOMAINLEN - 2) + return 0; /* too long */ + nm = (uint8_t*)regional_alloc(region, celen+2); + if(!nm) { + log_err("nsec3 wildcard: out of memory"); + return 0; /* alloc failure */ + } + nm[0] = 1; + nm[1] = (uint8_t)'*'; /* wildcard label */ + memmove(nm+2, ce, celen); + *len = celen+2; + return nm; +} + +/** Do the name error proof */ +static enum sec_status +nsec3_do_prove_nameerror(struct module_env* env, struct nsec3_filter* flt, + rbtree_t* ct, struct query_info* qinfo) +{ + struct ce_response ce; + uint8_t* wc; + size_t wclen; + struct ub_packed_rrset_key* wc_rrset; + int wc_rr; + enum sec_status sec; + + /* First locate and prove the closest encloser to qname. We will + * use the variant that fails if the closest encloser turns out + * to be qname. */ + sec = nsec3_prove_closest_encloser(env, flt, ct, qinfo, 1, &ce); + if(sec != sec_status_secure) { + if(sec == sec_status_bogus) + verbose(VERB_ALGO, "nsec3 nameerror proof: failed " + "to prove a closest encloser"); + else verbose(VERB_ALGO, "nsec3 nameerror proof: closest " + "nsec3 is an insecure delegation"); + return sec; + } + log_nametypeclass(VERB_ALGO, "nsec3 namerror: proven ce=", ce.ce,0,0); + + /* At this point, we know that qname does not exist. Now we need + * to prove that the wildcard does not exist. */ + log_assert(ce.ce); + wc = nsec3_ce_wildcard(env->scratch, ce.ce, ce.ce_len, &wclen); + if(!wc || !find_covering_nsec3(env, flt, ct, wc, wclen, + &wc_rrset, &wc_rr)) { + verbose(VERB_ALGO, "nsec3 nameerror proof: could not prove " + "that the applicable wildcard did not exist."); + return sec_status_bogus; + } + + if(ce.nc_rrset && nsec3_has_optout(ce.nc_rrset, ce.nc_rr)) { + verbose(VERB_ALGO, "nsec3 nameerror proof: nc has optout"); + return sec_status_insecure; + } + return sec_status_secure; +} + +enum sec_status +nsec3_prove_nameerror(struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key** list, size_t num, + struct query_info* qinfo, struct key_entry_key* kkey) +{ + rbtree_t ct; + struct nsec3_filter flt; + + if(!list || num == 0 || !kkey || !key_entry_isgood(kkey)) + return sec_status_bogus; /* no valid NSEC3s, bogus */ + rbtree_init(&ct, &nsec3_hash_cmp); /* init names-to-hash cache */ + filter_init(&flt, list, num, qinfo); /* init RR iterator */ + if(!flt.zone) + return sec_status_bogus; /* no RRs */ + if(nsec3_iteration_count_high(ve, &flt, kkey)) + return sec_status_insecure; /* iteration count too high */ + log_nametypeclass(VERB_ALGO, "start nsec3 nameerror proof, zone", + flt.zone, 0, 0); + return nsec3_do_prove_nameerror(env, &flt, &ct, qinfo); +} + +/* + * No code to handle qtype=NSEC3 specially. + * This existed in early drafts, but was later (-05) removed. + */ + +/** Do the nodata proof */ +static enum sec_status +nsec3_do_prove_nodata(struct module_env* env, struct nsec3_filter* flt, + rbtree_t* ct, struct query_info* qinfo) +{ + struct ce_response ce; + uint8_t* wc; + size_t wclen; + struct ub_packed_rrset_key* rrset; + int rr; + enum sec_status sec; + + if(find_matching_nsec3(env, flt, ct, qinfo->qname, qinfo->qname_len, + &rrset, &rr)) { + /* cases 1 and 2 */ + if(nsec3_has_type(rrset, rr, qinfo->qtype)) { + verbose(VERB_ALGO, "proveNodata: Matching NSEC3 " + "proved that type existed, bogus"); + return sec_status_bogus; + } else if(nsec3_has_type(rrset, rr, LDNS_RR_TYPE_CNAME)) { + verbose(VERB_ALGO, "proveNodata: Matching NSEC3 " + "proved that a CNAME existed, bogus"); + return sec_status_bogus; + } + + /* + * If type DS: filter_init zone find already found a parent + * zone, so this nsec3 is from a parent zone. + * o can be not a delegation (unusual query for normal name, + * no DS anyway, but we can verify that). + * o can be a delegation (which is the usual DS check). + * o may not have the SOA bit set (only the top of the + * zone, which must have been above the name, has that). + * Except for the root; which is checked by itself. + * + * If not type DS: matching nsec3 must not be a delegation. + */ + if(qinfo->qtype == LDNS_RR_TYPE_DS && qinfo->qname_len != 1 + && nsec3_has_type(rrset, rr, LDNS_RR_TYPE_SOA && + !dname_is_root(qinfo->qname))) { + verbose(VERB_ALGO, "proveNodata: apex NSEC3 " + "abused for no DS proof, bogus"); + return sec_status_bogus; + } else if(qinfo->qtype != LDNS_RR_TYPE_DS && + nsec3_has_type(rrset, rr, LDNS_RR_TYPE_NS) && + !nsec3_has_type(rrset, rr, LDNS_RR_TYPE_SOA)) { + if(!nsec3_has_type(rrset, rr, LDNS_RR_TYPE_DS)) { + verbose(VERB_ALGO, "proveNodata: matching " + "NSEC3 is insecure delegation"); + return sec_status_insecure; + } + verbose(VERB_ALGO, "proveNodata: matching " + "NSEC3 is a delegation, bogus"); + return sec_status_bogus; + } + return sec_status_secure; + } + + /* For cases 3 - 5, we need the proven closest encloser, and it + * can't match qname. Although, at this point, we know that it + * won't since we just checked that. */ + sec = nsec3_prove_closest_encloser(env, flt, ct, qinfo, 1, &ce); + if(sec == sec_status_bogus) { + verbose(VERB_ALGO, "proveNodata: did not match qname, " + "nor found a proven closest encloser."); + return sec_status_bogus; + } else if(sec==sec_status_insecure && qinfo->qtype!=LDNS_RR_TYPE_DS){ + verbose(VERB_ALGO, "proveNodata: closest nsec3 is insecure " + "delegation."); + return sec_status_insecure; + } + + /* Case 3: removed */ + + /* Case 4: */ + log_assert(ce.ce); + wc = nsec3_ce_wildcard(env->scratch, ce.ce, ce.ce_len, &wclen); + if(wc && find_matching_nsec3(env, flt, ct, wc, wclen, &rrset, &rr)) { + /* found wildcard */ + if(nsec3_has_type(rrset, rr, qinfo->qtype)) { + verbose(VERB_ALGO, "nsec3 nodata proof: matching " + "wildcard had qtype, bogus"); + return sec_status_bogus; + } else if(nsec3_has_type(rrset, rr, LDNS_RR_TYPE_CNAME)) { + verbose(VERB_ALGO, "nsec3 nodata proof: matching " + "wildcard had a CNAME, bogus"); + return sec_status_bogus; + } + if(qinfo->qtype == LDNS_RR_TYPE_DS && qinfo->qname_len != 1 + && nsec3_has_type(rrset, rr, LDNS_RR_TYPE_SOA)) { + verbose(VERB_ALGO, "nsec3 nodata proof: matching " + "wildcard for no DS proof has a SOA, bogus"); + return sec_status_bogus; + } else if(qinfo->qtype != LDNS_RR_TYPE_DS && + nsec3_has_type(rrset, rr, LDNS_RR_TYPE_NS) && + !nsec3_has_type(rrset, rr, LDNS_RR_TYPE_SOA)) { + verbose(VERB_ALGO, "nsec3 nodata proof: matching " + "wilcard is a delegation, bogus"); + return sec_status_bogus; + } + /* everything is peachy keen, except for optout spans */ + if(ce.nc_rrset && nsec3_has_optout(ce.nc_rrset, ce.nc_rr)) { + verbose(VERB_ALGO, "nsec3 nodata proof: matching " + "wildcard is in optout range, insecure"); + return sec_status_insecure; + } + return sec_status_secure; + } + + /* Case 5: */ + /* Due to forwarders, cnames, and other collating effects, we + * can see the ordinary unsigned data from a zone beneath an + * insecure delegation under an optout here */ + if(!ce.nc_rrset) { + verbose(VERB_ALGO, "nsec3 nodata proof: no next closer nsec3"); + return sec_status_bogus; + } + + /* We need to make sure that the covering NSEC3 is opt-out. */ + log_assert(ce.nc_rrset); + if(!nsec3_has_optout(ce.nc_rrset, ce.nc_rr)) { + if(qinfo->qtype == LDNS_RR_TYPE_DS) + verbose(VERB_ALGO, "proveNodata: covering NSEC3 was not " + "opt-out in an opt-out DS NOERROR/NODATA case."); + else verbose(VERB_ALGO, "proveNodata: could not find matching " + "NSEC3, nor matching wildcard, nor optout NSEC3 " + "-- no more options, bogus."); + return sec_status_bogus; + } + /* RFC5155 section 9.2: if nc has optout then no AD flag set */ + return sec_status_insecure; +} + +enum sec_status +nsec3_prove_nodata(struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key** list, size_t num, + struct query_info* qinfo, struct key_entry_key* kkey) +{ + rbtree_t ct; + struct nsec3_filter flt; + + if(!list || num == 0 || !kkey || !key_entry_isgood(kkey)) + return sec_status_bogus; /* no valid NSEC3s, bogus */ + rbtree_init(&ct, &nsec3_hash_cmp); /* init names-to-hash cache */ + filter_init(&flt, list, num, qinfo); /* init RR iterator */ + if(!flt.zone) + return sec_status_bogus; /* no RRs */ + if(nsec3_iteration_count_high(ve, &flt, kkey)) + return sec_status_insecure; /* iteration count too high */ + return nsec3_do_prove_nodata(env, &flt, &ct, qinfo); +} + +enum sec_status +nsec3_prove_wildcard(struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key** list, size_t num, + struct query_info* qinfo, struct key_entry_key* kkey, uint8_t* wc) +{ + rbtree_t ct; + struct nsec3_filter flt; + struct ce_response ce; + uint8_t* nc; + size_t nc_len; + size_t wclen; + (void)dname_count_size_labels(wc, &wclen); + + if(!list || num == 0 || !kkey || !key_entry_isgood(kkey)) + return sec_status_bogus; /* no valid NSEC3s, bogus */ + rbtree_init(&ct, &nsec3_hash_cmp); /* init names-to-hash cache */ + filter_init(&flt, list, num, qinfo); /* init RR iterator */ + if(!flt.zone) + return sec_status_bogus; /* no RRs */ + if(nsec3_iteration_count_high(ve, &flt, kkey)) + return sec_status_insecure; /* iteration count too high */ + + /* We know what the (purported) closest encloser is by just + * looking at the supposed generating wildcard. + * The *. has already been removed from the wc name. + */ + memset(&ce, 0, sizeof(ce)); + ce.ce = wc; + ce.ce_len = wclen; + + /* Now we still need to prove that the original data did not exist. + * Otherwise, we need to show that the next closer name is covered. */ + next_closer(qinfo->qname, qinfo->qname_len, ce.ce, &nc, &nc_len); + if(!find_covering_nsec3(env, &flt, &ct, nc, nc_len, + &ce.nc_rrset, &ce.nc_rr)) { + verbose(VERB_ALGO, "proveWildcard: did not find a covering " + "NSEC3 that covered the next closer name."); + return sec_status_bogus; + } + if(ce.nc_rrset && nsec3_has_optout(ce.nc_rrset, ce.nc_rr)) { + verbose(VERB_ALGO, "proveWildcard: NSEC3 optout"); + return sec_status_insecure; + } + return sec_status_secure; +} + +/** test if list is all secure */ +static int +list_is_secure(struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key** list, size_t num, + struct key_entry_key* kkey, char** reason) +{ + struct packed_rrset_data* d; + size_t i; + for(i=0; ientry.data; + if(list[i]->rk.type != htons(LDNS_RR_TYPE_NSEC3)) + continue; + if(d->security == sec_status_secure) + continue; + rrset_check_sec_status(env->rrset_cache, list[i], *env->now); + if(d->security == sec_status_secure) + continue; + d->security = val_verify_rrset_entry(env, ve, list[i], kkey, + reason); + if(d->security != sec_status_secure) { + verbose(VERB_ALGO, "NSEC3 did not verify"); + return 0; + } + rrset_update_sec_status(env->rrset_cache, list[i], *env->now); + } + return 1; +} + +enum sec_status +nsec3_prove_nods(struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key** list, size_t num, + struct query_info* qinfo, struct key_entry_key* kkey, char** reason) +{ + rbtree_t ct; + struct nsec3_filter flt; + struct ce_response ce; + struct ub_packed_rrset_key* rrset; + int rr; + log_assert(qinfo->qtype == LDNS_RR_TYPE_DS); + + if(!list || num == 0 || !kkey || !key_entry_isgood(kkey)) { + *reason = "no valid NSEC3s"; + return sec_status_bogus; /* no valid NSEC3s, bogus */ + } + if(!list_is_secure(env, ve, list, num, kkey, reason)) + return sec_status_bogus; /* not all NSEC3 records secure */ + rbtree_init(&ct, &nsec3_hash_cmp); /* init names-to-hash cache */ + filter_init(&flt, list, num, qinfo); /* init RR iterator */ + if(!flt.zone) { + *reason = "no NSEC3 records"; + return sec_status_bogus; /* no RRs */ + } + if(nsec3_iteration_count_high(ve, &flt, kkey)) + return sec_status_insecure; /* iteration count too high */ + + /* Look for a matching NSEC3 to qname -- this is the normal + * NODATA case. */ + if(find_matching_nsec3(env, &flt, &ct, qinfo->qname, qinfo->qname_len, + &rrset, &rr)) { + /* If the matching NSEC3 has the SOA bit set, it is from + * the wrong zone (the child instead of the parent). If + * it has the DS bit set, then we were lied to. */ + if(nsec3_has_type(rrset, rr, LDNS_RR_TYPE_SOA) && + qinfo->qname_len != 1) { + verbose(VERB_ALGO, "nsec3 provenods: NSEC3 is from" + " child zone, bogus"); + *reason = "NSEC3 from child zone"; + return sec_status_bogus; + } else if(nsec3_has_type(rrset, rr, LDNS_RR_TYPE_DS)) { + verbose(VERB_ALGO, "nsec3 provenods: NSEC3 has qtype" + " DS, bogus"); + *reason = "NSEC3 has DS in bitmap"; + return sec_status_bogus; + } + /* If the NSEC3 RR doesn't have the NS bit set, then + * this wasn't a delegation point. */ + if(!nsec3_has_type(rrset, rr, LDNS_RR_TYPE_NS)) + return sec_status_indeterminate; + /* Otherwise, this proves no DS. */ + return sec_status_secure; + } + + /* Otherwise, we are probably in the opt-out case. */ + if(nsec3_prove_closest_encloser(env, &flt, &ct, qinfo, 1, &ce) + != sec_status_secure) { + /* an insecure delegation *above* the qname does not prove + * anything about this qname exactly, and bogus is bogus */ + verbose(VERB_ALGO, "nsec3 provenods: did not match qname, " + "nor found a proven closest encloser."); + *reason = "no NSEC3 closest encloser"; + return sec_status_bogus; + } + + /* robust extra check */ + if(!ce.nc_rrset) { + verbose(VERB_ALGO, "nsec3 nods proof: no next closer nsec3"); + *reason = "no NSEC3 next closer"; + return sec_status_bogus; + } + + /* we had the closest encloser proof, then we need to check that the + * covering NSEC3 was opt-out -- the proveClosestEncloser step already + * checked to see if the closest encloser was a delegation or DNAME. + */ + log_assert(ce.nc_rrset); + if(!nsec3_has_optout(ce.nc_rrset, ce.nc_rr)) { + verbose(VERB_ALGO, "nsec3 provenods: covering NSEC3 was not " + "opt-out in an opt-out DS NOERROR/NODATA case."); + *reason = "covering NSEC3 was not opt-out in an opt-out " + "DS NOERROR/NODATA case"; + return sec_status_bogus; + } + /* RFC5155 section 9.2: if nc has optout then no AD flag set */ + return sec_status_insecure; +} + +enum sec_status +nsec3_prove_nxornodata(struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key** list, size_t num, + struct query_info* qinfo, struct key_entry_key* kkey, int* nodata) +{ + enum sec_status sec, secnx; + rbtree_t ct; + struct nsec3_filter flt; + *nodata = 0; + + if(!list || num == 0 || !kkey || !key_entry_isgood(kkey)) + return sec_status_bogus; /* no valid NSEC3s, bogus */ + rbtree_init(&ct, &nsec3_hash_cmp); /* init names-to-hash cache */ + filter_init(&flt, list, num, qinfo); /* init RR iterator */ + if(!flt.zone) + return sec_status_bogus; /* no RRs */ + if(nsec3_iteration_count_high(ve, &flt, kkey)) + return sec_status_insecure; /* iteration count too high */ + + /* try nxdomain and nodata after another, while keeping the + * hash cache intact */ + + secnx = nsec3_do_prove_nameerror(env, &flt, &ct, qinfo); + if(secnx==sec_status_secure) + return sec_status_secure; + sec = nsec3_do_prove_nodata(env, &flt, &ct, qinfo); + if(sec==sec_status_secure) { + *nodata = 1; + } else if(sec == sec_status_insecure) { + *nodata = 1; + } else if(secnx == sec_status_insecure) { + sec = sec_status_insecure; + } + return sec; +} diff --git a/validator/val_nsec3.h b/validator/val_nsec3.h new file mode 100644 index 00000000000..ae4326daffb --- /dev/null +++ b/validator/val_nsec3.h @@ -0,0 +1,378 @@ +/* + * validator/val_nsec3.h - validator NSEC3 denial of existance 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains helper functions for the validator module. + * The functions help with NSEC3 checking, the different NSEC3 proofs + * for denial of existance, and proofs for presence of types. + * + * NSEC3 + * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Hash Alg. | Flags | Iterations | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Salt Length | Salt / + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Hash Length | Next Hashed Owner Name / + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * / Type Bit Maps / + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * NSEC3PARAM + * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Hash Alg. | Flags | Iterations | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Salt Length | Salt / + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + */ + +#ifndef VALIDATOR_VAL_NSEC3_H +#define VALIDATOR_VAL_NSEC3_H +#include "util/rbtree.h" +#include "util/data/packed_rrset.h" +struct val_env; +struct regional; +struct module_env; +struct ub_packed_rrset_key; +struct reply_info; +struct query_info; +struct key_entry_key; + +/** + * 0 1 2 3 4 5 6 7 + * +-+-+-+-+-+-+-+-+ + * | |O| + * +-+-+-+-+-+-+-+-+ + * The OPT-OUT bit in the NSEC3 flags field. + * If enabled, there can be zero or more unsigned delegations in the span. + * If disabled, there are zero unsigned delegations in the span. + */ +#define NSEC3_OPTOUT 0x01 +/** + * The unknown flags in the NSEC3 flags field. + * They must be zero, or the NSEC3 is ignored. + */ +#define NSEC3_UNKNOWN_FLAGS 0xFE + +/** The SHA1 hash algorithm for NSEC3 */ +#define NSEC3_HASH_SHA1 0x01 + +/** + * Determine if the set of NSEC3 records provided with a response prove NAME + * ERROR. This means that the NSEC3s prove a) the closest encloser exists, + * b) the direct child of the closest encloser towards qname doesn't exist, + * and c) *.closest encloser does not exist. + * + * @param env: module environment with temporary region and buffer. + * @param ve: validator environment, with iteration count settings. + * @param list: array of RRsets, some of which are NSEC3s. + * @param num: number of RRsets in the array to examine. + * @param qinfo: query that is verified for. + * @param kkey: key entry that signed the NSEC3s. + * @return: + * sec_status SECURE of the Name Error is proven by the NSEC3 RRs, + * BOGUS if not, INSECURE if all of the NSEC3s could be validly ignored. + */ +enum sec_status +nsec3_prove_nameerror(struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key** list, size_t num, + struct query_info* qinfo, struct key_entry_key* kkey); + +/** + * Determine if the NSEC3s provided in a response prove the NOERROR/NODATA + * status. There are a number of different variants to this: + * + * 1) Normal NODATA -- qname is matched to an NSEC3 record, type is not + * present. + * + * 2) ENT NODATA -- because there must be NSEC3 record for + * empty-non-terminals, this is the same as #1. + * + * 3) NSEC3 ownername NODATA -- qname matched an existing, lone NSEC3 + * ownername, but qtype was not NSEC3. NOTE: as of nsec-05, this case no + * longer exists. + * + * 4) Wildcard NODATA -- A wildcard matched the name, but not the type. + * + * 5) Opt-In DS NODATA -- the qname is covered by an opt-in span and qtype == + * DS. (or maybe some future record with the same parent-side-only property) + * + * @param env: module environment with temporary region and buffer. + * @param ve: validator environment, with iteration count settings. + * @param list: array of RRsets, some of which are NSEC3s. + * @param num: number of RRsets in the array to examine. + * @param qinfo: query that is verified for. + * @param kkey: key entry that signed the NSEC3s. + * @return: + * sec_status SECURE of the proposition is proven by the NSEC3 RRs, + * BOGUS if not, INSECURE if all of the NSEC3s could be validly ignored. + */ +enum sec_status +nsec3_prove_nodata(struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key** list, size_t num, + struct query_info* qinfo, struct key_entry_key* kkey); + + +/** + * Prove that a positive wildcard match was appropriate (no direct match + * RRset). + * + * @param env: module environment with temporary region and buffer. + * @param ve: validator environment, with iteration count settings. + * @param list: array of RRsets, some of which are NSEC3s. + * @param num: number of RRsets in the array to examine. + * @param qinfo: query that is verified for. + * @param kkey: key entry that signed the NSEC3s. + * @param wc: The purported wildcard that matched. This is the wildcard name + * as *.wildcard.name., with the *. label already removed. + * @return: + * sec_status SECURE of the proposition is proven by the NSEC3 RRs, + * BOGUS if not, INSECURE if all of the NSEC3s could be validly ignored. + */ +enum sec_status +nsec3_prove_wildcard(struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key** list, size_t num, + struct query_info* qinfo, struct key_entry_key* kkey, uint8_t* wc); + +/** + * Prove that a DS response either had no DS, or wasn't a delegation point. + * + * Fundamentally there are two cases here: normal NODATA and Opt-In NODATA. + * + * @param env: module environment with temporary region and buffer. + * @param ve: validator environment, with iteration count settings. + * @param list: array of RRsets, some of which are NSEC3s. + * @param num: number of RRsets in the array to examine. + * @param qinfo: query that is verified for. + * @param kkey: key entry that signed the NSEC3s. + * @param reason: string for bogus result. + * @return: + * sec_status SECURE of the proposition is proven by the NSEC3 RRs, + * BOGUS if not, INSECURE if all of the NSEC3s could be validly ignored. + * or if there was no DS in an insecure (i.e., opt-in) way, + * INDETERMINATE if it was clear that this wasn't a delegation point. + */ +enum sec_status +nsec3_prove_nods(struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key** list, size_t num, + struct query_info* qinfo, struct key_entry_key* kkey, char** reason); + +/** + * Prove NXDOMAIN or NODATA. + * + * @param env: module environment with temporary region and buffer. + * @param ve: validator environment, with iteration count settings. + * @param list: array of RRsets, some of which are NSEC3s. + * @param num: number of RRsets in the array to examine. + * @param qinfo: query that is verified for. + * @param kkey: key entry that signed the NSEC3s. + * @param nodata: if return value is secure, this indicates if nodata or + * nxdomain was proven. + * @return: + * sec_status SECURE of the proposition is proven by the NSEC3 RRs, + * BOGUS if not, INSECURE if all of the NSEC3s could be validly ignored. + */ +enum sec_status +nsec3_prove_nxornodata(struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key** list, size_t num, + struct query_info* qinfo, struct key_entry_key* kkey, int* nodata); + +/** + * The NSEC3 hash result storage. + * Consists of an rbtree, with these nodes in it. + * The nodes detail how a set of parameters (from nsec3 rr) plus + * a dname result in a hash. + */ +struct nsec3_cached_hash { + /** rbtree node, key is this structure */ + rbnode_t node; + /** where are the parameters for conversion, in this rrset data */ + struct ub_packed_rrset_key* nsec3; + /** where are the parameters for conversion, this RR number in data */ + int rr; + /** the name to convert */ + uint8_t* dname; + /** length of the dname */ + size_t dname_len; + /** the hash result (not base32 encoded) */ + uint8_t* hash; + /** length of hash in bytes */ + size_t hash_len; + /** the hash result in base32 encoding */ + uint8_t* b32; + /** length of base32 encoding (as a label) */ + size_t b32_len; +}; + +/** + * Rbtree for hash cache comparison function. + * @param c1: key 1. + * @param c2: key 2. + * @return: comparison code, -1, 0, 1, of the keys. + */ +int nsec3_hash_cmp(const void* c1, const void* c2); + +/** + * Obtain the hash of an owner name. + * Used internally by the nsec3 proof functions in this file. + * published to enable unit testing of hash algorithms and cache. + * + * @param table: the cache table. Must be inited at start. + * @param region: scratch region to use for allocation. + * This region holds the tree, if you wipe the region, reinit the tree. + * @param buf: temporary buffer. + * @param nsec3: the rrset with parameters + * @param rr: rr number from d that has the NSEC3 parameters to hash to. + * @param dname: name to hash + * This pointer is used inside the tree, assumed region-alloced. + * @param dname_len: the length of the name. + * @param hash: the hash node is returned on success. + * @return: + * 1 on success, either from cache or newly hashed hash is returned. + * 0 on a malloc failure. + * -1 if the NSEC3 rr was badly formatted (i.e. formerr). + */ +int nsec3_hash_name(rbtree_t* table, struct regional* region, ldns_buffer* buf, + struct ub_packed_rrset_key* nsec3, int rr, uint8_t* dname, + size_t dname_len, struct nsec3_cached_hash** hash); + +/** + * Get next owner name, converted to base32 encoding and with the + * zone name (taken from the nsec3 owner name) appended. + * @param rrset: the NSEC3 rrset. + * @param r: the rr num of the nsec3 in the rrset. + * @param buf: buffer to store name in + * @param max: size of buffer. + * @return length of name on success. 0 on failure (buffer too short or + * bad format nsec3 record). + */ +size_t nsec3_get_nextowner_b32(struct ub_packed_rrset_key* rrset, int r, + uint8_t* buf, size_t max); + +/** + * Convert hash into base32 encoding and with the + * zone name appended. + * @param hash: hashed buffer + * @param hashlen: length of hash + * @param zone: name of zone + * @param zonelen: length of zonename. + * @param buf: buffer to store name in + * @param max: size of buffer. + * @return length of name on success. 0 on failure (buffer too short or + * bad format nsec3 record). + */ +size_t nsec3_hash_to_b32(uint8_t* hash, size_t hashlen, uint8_t* zone, + size_t zonelen, uint8_t* buf, size_t max); + +/** + * Get NSEC3 parameters out of rr. + * @param rrset: the NSEC3 rrset. + * @param r: the rr num of the nsec3 in the rrset. + * @param algo: nsec3 hash algo. + * @param iter: iteration count. + * @param salt: ptr to salt inside rdata. + * @param saltlen: length of salt. + * @return 0 if bad formatted, unknown nsec3 hash algo, or unknown flags set. + */ +int nsec3_get_params(struct ub_packed_rrset_key* rrset, int r, + int* algo, size_t* iter, uint8_t** salt, size_t* saltlen); + +/** + * Get NSEC3 hashed in a buffer + * @param buf: buffer for temp use. + * @param nm: name to hash + * @param nmlen: length of nm. + * @param algo: algo to use, must be known. + * @param iter: iterations + * @param salt: salt for nsec3 + * @param saltlen: length of salt. + * @param res: result of hash stored here. + * @param max: maximum space for result. + * @return 0 on failure, otherwise bytelength stored. + */ +size_t nsec3_get_hashed(ldns_buffer* buf, uint8_t* nm, size_t nmlen, int algo, + size_t iter, uint8_t* salt, size_t saltlen, uint8_t* res, size_t max); + +/** + * see if NSEC3 RR contains given type + * @param rrset: NSEC3 rrset + * @param r: RR in rrset + * @param type: in host order to check bit for. + * @return true if bit set, false if not or error. + */ +int nsec3_has_type(struct ub_packed_rrset_key* rrset, int r, uint16_t type); + +/** + * return if nsec3 RR has the optout flag + * @param rrset: NSEC3 rrset + * @param r: RR in rrset + * @return true if optout, false on error or not optout + */ +int nsec3_has_optout(struct ub_packed_rrset_key* rrset, int r); + +/** + * Return nsec3 RR next hashed owner name + * @param rrset: NSEC3 rrset + * @param r: RR in rrset + * @param next: ptr into rdata to next owner hash + * @param nextlen: length of hash. + * @return false on malformed + */ +int nsec3_get_nextowner(struct ub_packed_rrset_key* rrset, int r, + uint8_t** next, size_t* nextlen); + +/** + * nsec3Covers + * Given a hash and a candidate NSEC3Record, determine if that NSEC3Record + * covers the hash. Covers specifically means that the hash is in between + * the owner and next hashes and does not equal either. + * + * @param zone: the zone name. + * @param hash: the hash of the name + * @param rrset: the rrset of the NSEC3. + * @param rr: which rr in the rrset. + * @param buf: temporary buffer. + * @return true if covers, false if not. + */ +int nsec3_covers(uint8_t* zone, struct nsec3_cached_hash* hash, + struct ub_packed_rrset_key* rrset, int rr, ldns_buffer* buf); + +#endif /* VALIDATOR_VAL_NSEC3_H */ diff --git a/validator/val_sigcrypt.c b/validator/val_sigcrypt.c new file mode 100644 index 00000000000..4c79c004d02 --- /dev/null +++ b/validator/val_sigcrypt.c @@ -0,0 +1,1824 @@ +/* + * validator/val_sigcrypt.c - validator signature crypto 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains helper functions for the validator module. + * The functions help with signature verification and checking, the + * bridging between RR wireformat data and crypto calls. + */ +#include "config.h" +#include +#include "validator/val_sigcrypt.h" +#include "validator/validator.h" +#include "util/data/msgreply.h" +#include "util/data/msgparse.h" +#include "util/data/dname.h" +#include "util/rbtree.h" +#include "util/module.h" +#include "util/net_help.h" +#include "util/regional.h" + +#ifndef HAVE_SSL +#error "Need SSL library to do digital signature cryptography" +#endif + +#ifdef HAVE_OPENSSL_ERR_H +#include +#endif + +#ifdef HAVE_OPENSSL_RAND_H +#include +#endif + +#ifdef HAVE_OPENSSL_CONF_H +#include +#endif + +#ifdef HAVE_OPENSSL_ENGINE_H +#include +#endif + +/** return number of rrs in an rrset */ +static size_t +rrset_get_count(struct ub_packed_rrset_key* rrset) +{ + struct packed_rrset_data* d = (struct packed_rrset_data*) + rrset->entry.data; + if(!d) return 0; + return d->count; +} + +/** + * Get RR signature count + */ +static size_t +rrset_get_sigcount(struct ub_packed_rrset_key* k) +{ + struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data; + return d->rrsig_count; +} + +/** + * Get signature keytag value + * @param k: rrset (with signatures) + * @param sig_idx: signature index. + * @return keytag or 0 if malformed rrsig. + */ +static uint16_t +rrset_get_sig_keytag(struct ub_packed_rrset_key* k, size_t sig_idx) +{ + uint16_t t; + struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data; + log_assert(sig_idx < d->rrsig_count); + if(d->rr_len[d->count + sig_idx] < 2+18) + return 0; + memmove(&t, d->rr_data[d->count + sig_idx]+2+16, 2); + return ntohs(t); +} + +/** + * Get signature signing algorithm value + * @param k: rrset (with signatures) + * @param sig_idx: signature index. + * @return algo or 0 if malformed rrsig. + */ +static int +rrset_get_sig_algo(struct ub_packed_rrset_key* k, size_t sig_idx) +{ + struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data; + log_assert(sig_idx < d->rrsig_count); + if(d->rr_len[d->count + sig_idx] < 2+3) + return 0; + return (int)d->rr_data[d->count + sig_idx][2+2]; +} + +/** get rdata pointer and size */ +static void +rrset_get_rdata(struct ub_packed_rrset_key* k, size_t idx, uint8_t** rdata, + size_t* len) +{ + struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data; + log_assert(d && idx < (d->count + d->rrsig_count)); + *rdata = d->rr_data[idx]; + *len = d->rr_len[idx]; +} + +uint16_t +dnskey_get_flags(struct ub_packed_rrset_key* k, size_t idx) +{ + uint8_t* rdata; + size_t len; + uint16_t f; + rrset_get_rdata(k, idx, &rdata, &len); + if(len < 2+2) + return 0; + memmove(&f, rdata+2, 2); + f = ntohs(f); + return f; +} + +/** + * Get DNSKEY protocol value from rdata + * @param k: DNSKEY rrset. + * @param idx: which key. + * @return protocol octet value + */ +static int +dnskey_get_protocol(struct ub_packed_rrset_key* k, size_t idx) +{ + uint8_t* rdata; + size_t len; + rrset_get_rdata(k, idx, &rdata, &len); + if(len < 2+4) + return 0; + return (int)rdata[2+2]; +} + +int +dnskey_get_algo(struct ub_packed_rrset_key* k, size_t idx) +{ + uint8_t* rdata; + size_t len; + rrset_get_rdata(k, idx, &rdata, &len); + if(len < 2+4) + return 0; + return (int)rdata[2+3]; +} + +/** get public key rdata field from a dnskey RR and do some checks */ +static void +dnskey_get_pubkey(struct ub_packed_rrset_key* k, size_t idx, + unsigned char** pk, unsigned int* pklen) +{ + uint8_t* rdata; + size_t len; + rrset_get_rdata(k, idx, &rdata, &len); + if(len < 2+5) { + *pk = NULL; + *pklen = 0; + return; + } + *pk = (unsigned char*)rdata+2+4; + *pklen = (unsigned)len-2-4; +} + +int +ds_get_key_algo(struct ub_packed_rrset_key* k, size_t idx) +{ + uint8_t* rdata; + size_t len; + rrset_get_rdata(k, idx, &rdata, &len); + if(len < 2+3) + return 0; + return (int)rdata[2+2]; +} + +int +ds_get_digest_algo(struct ub_packed_rrset_key* k, size_t idx) +{ + uint8_t* rdata; + size_t len; + rrset_get_rdata(k, idx, &rdata, &len); + if(len < 2+4) + return 0; + return (int)rdata[2+3]; +} + +uint16_t +ds_get_keytag(struct ub_packed_rrset_key* ds_rrset, size_t ds_idx) +{ + uint16_t t; + uint8_t* rdata; + size_t len; + rrset_get_rdata(ds_rrset, ds_idx, &rdata, &len); + if(len < 2+2) + return 0; + memmove(&t, rdata+2, 2); + return ntohs(t); +} + +/** + * Return pointer to the digest in a DS RR. + * @param k: DS rrset. + * @param idx: which DS. + * @param digest: digest data is returned. + * on error, this is NULL. + * @param len: length of digest is returned. + * on error, the length is 0. + */ +static void +ds_get_sigdata(struct ub_packed_rrset_key* k, size_t idx, uint8_t** digest, + size_t* len) +{ + uint8_t* rdata; + size_t rdlen; + rrset_get_rdata(k, idx, &rdata, &rdlen); + if(rdlen < 2+5) { + *digest = NULL; + *len = 0; + return; + } + *digest = rdata + 2 + 4; + *len = rdlen - 2 - 4; +} + +/** + * Return size of DS digest according to its hash algorithm. + * @param k: DS rrset. + * @param idx: which DS. + * @return size in bytes of digest, or 0 if not supported. + */ +static size_t +ds_digest_size_algo(struct ub_packed_rrset_key* k, size_t idx) +{ + switch(ds_get_digest_algo(k, idx)) { +#ifdef HAVE_EVP_SHA1 + case LDNS_SHA1: + return SHA_DIGEST_LENGTH; +#endif +#ifdef HAVE_EVP_SHA256 + case LDNS_SHA256: + return SHA256_DIGEST_LENGTH; +#endif +#ifdef USE_GOST + case LDNS_HASH_GOST: + if(EVP_get_digestbyname("md_gost94")) + return 32; + else return 0; +#endif +#ifdef USE_ECDSA + case LDNS_SHA384: + return SHA384_DIGEST_LENGTH; +#endif + default: break; + } + return 0; +} + +#ifdef USE_GOST +/** Perform GOST hash */ +static int +do_gost94(unsigned char* data, size_t len, unsigned char* dest) +{ + const EVP_MD* md = EVP_get_digestbyname("md_gost94"); + if(!md) + return 0; + return ldns_digest_evp(data, (unsigned int)len, dest, md); +} +#endif + +/** + * Create a DS digest for a DNSKEY entry. + * + * @param env: module environment. Uses scratch space. + * @param dnskey_rrset: DNSKEY rrset. + * @param dnskey_idx: index of RR in rrset. + * @param ds_rrset: DS rrset + * @param ds_idx: index of RR in DS rrset. + * @param digest: digest is returned in here (must be correctly sized). + * @return false on error. + */ +static int +ds_create_dnskey_digest(struct module_env* env, + struct ub_packed_rrset_key* dnskey_rrset, size_t dnskey_idx, + struct ub_packed_rrset_key* ds_rrset, size_t ds_idx, + uint8_t* digest) +{ + ldns_buffer* b = env->scratch_buffer; + uint8_t* dnskey_rdata; + size_t dnskey_len; + rrset_get_rdata(dnskey_rrset, dnskey_idx, &dnskey_rdata, &dnskey_len); + + /* create digest source material in buffer + * digest = digest_algorithm( DNSKEY owner name | DNSKEY RDATA); + * DNSKEY RDATA = Flags | Protocol | Algorithm | Public Key. */ + ldns_buffer_clear(b); + ldns_buffer_write(b, dnskey_rrset->rk.dname, + dnskey_rrset->rk.dname_len); + query_dname_tolower(ldns_buffer_begin(b)); + ldns_buffer_write(b, dnskey_rdata+2, dnskey_len-2); /* skip rdatalen*/ + ldns_buffer_flip(b); + + switch(ds_get_digest_algo(ds_rrset, ds_idx)) { +#ifdef HAVE_EVP_SHA1 + case LDNS_SHA1: + (void)SHA1((unsigned char*)ldns_buffer_begin(b), + ldns_buffer_limit(b), (unsigned char*)digest); + return 1; +#endif +#ifdef HAVE_EVP_SHA256 + case LDNS_SHA256: + (void)SHA256((unsigned char*)ldns_buffer_begin(b), + ldns_buffer_limit(b), (unsigned char*)digest); + return 1; +#endif +#ifdef USE_GOST + case LDNS_HASH_GOST: + if(do_gost94((unsigned char*)ldns_buffer_begin(b), + ldns_buffer_limit(b), (unsigned char*)digest)) + return 1; +#endif +#ifdef USE_ECDSA + case LDNS_SHA384: + (void)SHA384((unsigned char*)ldns_buffer_begin(b), + ldns_buffer_limit(b), (unsigned char*)digest); + return 1; +#endif + default: + verbose(VERB_QUERY, "unknown DS digest algorithm %d", + (int) ds_get_digest_algo(ds_rrset, ds_idx)); + break; + } + return 0; +} + +int ds_digest_match_dnskey(struct module_env* env, + struct ub_packed_rrset_key* dnskey_rrset, size_t dnskey_idx, + struct ub_packed_rrset_key* ds_rrset, size_t ds_idx) +{ + uint8_t* ds; /* DS digest */ + size_t dslen; + uint8_t* digest; /* generated digest */ + size_t digestlen = ds_digest_size_algo(ds_rrset, ds_idx); + + if(digestlen == 0) { + verbose(VERB_QUERY, "DS fail: not supported, or DS RR " + "format error"); + return 0; /* not supported, or DS RR format error */ + } + /* check digest length in DS with length from hash function */ + ds_get_sigdata(ds_rrset, ds_idx, &ds, &dslen); + if(!ds || dslen != digestlen) { + verbose(VERB_QUERY, "DS fail: DS RR algo and digest do not " + "match each other"); + return 0; /* DS algorithm and digest do not match */ + } + + digest = regional_alloc(env->scratch, digestlen); + if(!digest) { + verbose(VERB_QUERY, "DS fail: out of memory"); + return 0; /* mem error */ + } + if(!ds_create_dnskey_digest(env, dnskey_rrset, dnskey_idx, ds_rrset, + ds_idx, digest)) { + verbose(VERB_QUERY, "DS fail: could not calc key digest"); + return 0; /* digest algo failed */ + } + if(memcmp(digest, ds, dslen) != 0) { + verbose(VERB_QUERY, "DS fail: digest is different"); + return 0; /* digest different */ + } + return 1; +} + +int +ds_digest_algo_is_supported(struct ub_packed_rrset_key* ds_rrset, + size_t ds_idx) +{ + return (ds_digest_size_algo(ds_rrset, ds_idx) != 0); +} + +/** return true if DNSKEY algorithm id is supported */ +static int +dnskey_algo_id_is_supported(int id) +{ + switch(id) { + case LDNS_DSA: + case LDNS_DSA_NSEC3: + case LDNS_RSASHA1: + case LDNS_RSASHA1_NSEC3: + case LDNS_RSAMD5: +#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2) + case LDNS_RSASHA256: +#endif +#if defined(HAVE_EVP_SHA512) && defined(USE_SHA2) + case LDNS_RSASHA512: +#endif +#ifdef USE_ECDSA + case LDNS_ECDSAP256SHA256: + case LDNS_ECDSAP384SHA384: +#endif + return 1; +#ifdef USE_GOST + case LDNS_ECC_GOST: + /* we support GOST if it can be loaded */ + return ldns_key_EVP_load_gost_id(); +#endif + default: + return 0; + } +} + +int +ds_key_algo_is_supported(struct ub_packed_rrset_key* ds_rrset, + size_t ds_idx) +{ + return dnskey_algo_id_is_supported(ds_get_key_algo(ds_rrset, ds_idx)); +} + +uint16_t +dnskey_calc_keytag(struct ub_packed_rrset_key* dnskey_rrset, size_t dnskey_idx) +{ + uint8_t* data; + size_t len; + rrset_get_rdata(dnskey_rrset, dnskey_idx, &data, &len); + /* do not pass rdatalen to ldns */ + return ldns_calc_keytag_raw(data+2, len-2); +} + +int dnskey_algo_is_supported(struct ub_packed_rrset_key* dnskey_rrset, + size_t dnskey_idx) +{ + return dnskey_algo_id_is_supported(dnskey_get_algo(dnskey_rrset, + dnskey_idx)); +} + +void algo_needs_init_dnskey_add(struct algo_needs* n, + struct ub_packed_rrset_key* dnskey, uint8_t* sigalg) +{ + uint8_t algo; + size_t i, total = n->num; + size_t num = rrset_get_count(dnskey); + + for(i=0; ineeds[algo] == 0) { + n->needs[algo] = 1; + sigalg[total] = algo; + total++; + } + } + sigalg[total] = 0; + n->num = total; +} + +void algo_needs_init_list(struct algo_needs* n, uint8_t* sigalg) +{ + uint8_t algo; + size_t total = 0; + + memset(n->needs, 0, sizeof(uint8_t)*ALGO_NEEDS_MAX); + while( (algo=*sigalg++) != 0) { + log_assert(dnskey_algo_id_is_supported((int)algo)); + log_assert(n->needs[algo] == 0); + n->needs[algo] = 1; + total++; + } + n->num = total; +} + +void algo_needs_init_ds(struct algo_needs* n, struct ub_packed_rrset_key* ds, + int fav_ds_algo, uint8_t* sigalg) +{ + uint8_t algo; + size_t i, total = 0; + size_t num = rrset_get_count(ds); + + memset(n->needs, 0, sizeof(uint8_t)*ALGO_NEEDS_MAX); + for(i=0; ineeds[algo] == 0) { + n->needs[algo] = 1; + sigalg[total] = algo; + total++; + } + } + sigalg[total] = 0; + n->num = total; +} + +int algo_needs_set_secure(struct algo_needs* n, uint8_t algo) +{ + if(n->needs[algo]) { + n->needs[algo] = 0; + n->num --; + if(n->num == 0) /* done! */ + return 1; + } + return 0; +} + +void algo_needs_set_bogus(struct algo_needs* n, uint8_t algo) +{ + if(n->needs[algo]) n->needs[algo] = 2; /* need it, but bogus */ +} + +size_t algo_needs_num_missing(struct algo_needs* n) +{ + return n->num; +} + +int algo_needs_missing(struct algo_needs* n) +{ + int i; + /* first check if a needed algo was bogus - report that */ + for(i=0; ineeds[i] == 2) + return 0; + /* now check which algo is missing */ + for(i=0; ineeds[i] == 1) + return i; + return 0; +} + +enum sec_status +dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey, + uint8_t* sigalg, char** reason) +{ + enum sec_status sec; + size_t i, num; + rbtree_t* sortree = NULL; + /* make sure that for all DNSKEY algorithms there are valid sigs */ + struct algo_needs needs; + int alg; + + num = rrset_get_sigcount(rrset); + if(num == 0) { + verbose(VERB_QUERY, "rrset failed to verify due to a lack of " + "signatures"); + *reason = "no signatures"; + return sec_status_bogus; + } + + if(sigalg) { + algo_needs_init_list(&needs, sigalg); + if(algo_needs_num_missing(&needs) == 0) { + verbose(VERB_QUERY, "zone has no known algorithms"); + *reason = "zone has no known algorithms"; + return sec_status_insecure; + } + } + for(i=0; inow, rrset, + dnskey, i, &sortree, reason); + /* see which algorithm has been fixed up */ + if(sec == sec_status_secure) { + if(!sigalg) + return sec; /* done! */ + else if(algo_needs_set_secure(&needs, + (uint8_t)rrset_get_sig_algo(rrset, i))) + return sec; /* done! */ + } else if(sigalg && sec == sec_status_bogus) { + algo_needs_set_bogus(&needs, + (uint8_t)rrset_get_sig_algo(rrset, i)); + } + } + verbose(VERB_ALGO, "rrset failed to verify: no valid signatures for " + "%d algorithms", (int)algo_needs_num_missing(&needs)); + if(sigalg && (alg=algo_needs_missing(&needs)) != 0) { + algo_needs_reason(env, alg, reason, "no signatures"); + } + return sec_status_bogus; +} + +void algo_needs_reason(struct module_env* env, int alg, char** reason, char* s) +{ + char buf[256]; + ldns_lookup_table *t = ldns_lookup_by_id(ldns_algorithms, alg); + if(t&&t->name) + snprintf(buf, sizeof(buf), "%s with algorithm %s", s, t->name); + else snprintf(buf, sizeof(buf), "%s with algorithm ALG%u", s, + (unsigned)alg); + *reason = regional_strdup(env->scratch, buf); + if(!*reason) + *reason = s; +} + +enum sec_status +dnskey_verify_rrset(struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey, + size_t dnskey_idx, char** reason) +{ + enum sec_status sec; + size_t i, num, numchecked = 0; + rbtree_t* sortree = NULL; + int buf_canon = 0; + uint16_t tag = dnskey_calc_keytag(dnskey, dnskey_idx); + int algo = dnskey_get_algo(dnskey, dnskey_idx); + + num = rrset_get_sigcount(rrset); + if(num == 0) { + verbose(VERB_QUERY, "rrset failed to verify due to a lack of " + "signatures"); + *reason = "no signatures"; + return sec_status_bogus; + } + for(i=0; iscratch, + env->scratch_buffer, ve, *env->now, rrset, + dnskey, dnskey_idx, i, &sortree, &buf_canon, reason); + if(sec == sec_status_secure) + return sec; + numchecked ++; + } + verbose(VERB_ALGO, "rrset failed to verify: all signatures are bogus"); + if(!numchecked) *reason = "signature missing"; + return sec_status_bogus; +} + +enum sec_status +dnskeyset_verify_rrset_sig(struct module_env* env, struct val_env* ve, + uint32_t now, struct ub_packed_rrset_key* rrset, + struct ub_packed_rrset_key* dnskey, size_t sig_idx, + struct rbtree_t** sortree, char** reason) +{ + /* find matching keys and check them */ + enum sec_status sec = sec_status_bogus; + uint16_t tag = rrset_get_sig_keytag(rrset, sig_idx); + int algo = rrset_get_sig_algo(rrset, sig_idx); + size_t i, num = rrset_get_count(dnskey); + size_t numchecked = 0; + int buf_canon = 0; + verbose(VERB_ALGO, "verify sig %d %d", (int)tag, algo); + if(!dnskey_algo_id_is_supported(algo)) { + verbose(VERB_QUERY, "verify sig: unknown algorithm"); + return sec_status_insecure; + } + + for(i=0; iscratch, + env->scratch_buffer, ve, now, rrset, dnskey, i, + sig_idx, sortree, &buf_canon, reason); + if(sec == sec_status_secure) + return sec; + } + if(numchecked == 0) { + *reason = "signatures from unknown keys"; + verbose(VERB_QUERY, "verify: could not find appropriate key"); + return sec_status_bogus; + } + return sec_status_bogus; +} + +/** + * RR entries in a canonical sorted tree of RRs + */ +struct canon_rr { + /** rbtree node, key is this structure */ + rbnode_t node; + /** rrset the RR is in */ + struct ub_packed_rrset_key* rrset; + /** which RR in the rrset */ + size_t rr_idx; +}; + +/** + * Compare two RR for canonical order, in a field-style sweep. + * @param d: rrset data + * @param desc: ldns wireformat descriptor. + * @param i: first RR to compare + * @param j: first RR to compare + * @return comparison code. + */ +static int +canonical_compare_byfield(struct packed_rrset_data* d, + const ldns_rr_descriptor* desc, size_t i, size_t j) +{ + /* sweep across rdata, keep track of some state: + * which rr field, and bytes left in field. + * current position in rdata, length left. + * are we in a dname, length left in a label. + */ + int wfi = -1; /* current wireformat rdata field (rdf) */ + int wfj = -1; + uint8_t* di = d->rr_data[i]+2; /* ptr to current rdata byte */ + uint8_t* dj = d->rr_data[j]+2; + size_t ilen = d->rr_len[i]-2; /* length left in rdata */ + size_t jlen = d->rr_len[j]-2; + int dname_i = 0; /* true if these bytes are part of a name */ + int dname_j = 0; + size_t lablen_i = 0; /* 0 for label length byte,for first byte of rdf*/ + size_t lablen_j = 0; /* otherwise remaining length of rdf or label */ + int dname_num_i = (int)desc->_dname_count; /* decreased at root label */ + int dname_num_j = (int)desc->_dname_count; + + /* loop while there are rdata bytes available for both rrs, + * and still some lowercasing needs to be done; either the dnames + * have not been reached yet, or they are currently being processed */ + while(ilen > 0 && jlen > 0 && (dname_num_i > 0 || dname_num_j > 0)) { + /* compare these two bytes */ + /* lowercase if in a dname and not a label length byte */ + if( ((dname_i && lablen_i)?(uint8_t)tolower((int)*di):*di) + != ((dname_j && lablen_j)?(uint8_t)tolower((int)*dj):*dj) + ) { + if(((dname_i && lablen_i)?(uint8_t)tolower((int)*di):*di) + < ((dname_j && lablen_j)?(uint8_t)tolower((int)*dj):*dj)) + return -1; + return 1; + } + ilen--; + jlen--; + /* bytes are equal */ + + /* advance field i */ + /* lablen 0 means that this byte is the first byte of the + * next rdata field; inspect this rdata field and setup + * to process the rest of this rdata field. + * The reason to first read the byte, then setup the rdf, + * is that we are then sure the byte is available and short + * rdata is handled gracefully (even if it is a formerr). */ + if(lablen_i == 0) { + if(dname_i) { + /* scan this dname label */ + /* capture length to lowercase */ + lablen_i = (size_t)*di; + if(lablen_i == 0) { + /* end root label */ + dname_i = 0; + dname_num_i--; + /* if dname num is 0, then the + * remainder is binary only */ + if(dname_num_i == 0) + lablen_i = ilen; + } + } else { + /* scan this rdata field */ + wfi++; + if(desc->_wireformat[wfi] + == LDNS_RDF_TYPE_DNAME) { + dname_i = 1; + lablen_i = (size_t)*di; + if(lablen_i == 0) { + dname_i = 0; + dname_num_i--; + if(dname_num_i == 0) + lablen_i = ilen; + } + } else if(desc->_wireformat[wfi] + == LDNS_RDF_TYPE_STR) + lablen_i = (size_t)*di; + else lablen_i = get_rdf_size( + desc->_wireformat[wfi]) - 1; + } + } else lablen_i--; + + /* advance field j; same as for i */ + if(lablen_j == 0) { + if(dname_j) { + lablen_j = (size_t)*dj; + if(lablen_j == 0) { + dname_j = 0; + dname_num_j--; + if(dname_num_j == 0) + lablen_j = jlen; + } + } else { + wfj++; + if(desc->_wireformat[wfj] + == LDNS_RDF_TYPE_DNAME) { + dname_j = 1; + lablen_j = (size_t)*dj; + if(lablen_j == 0) { + dname_j = 0; + dname_num_j--; + if(dname_num_j == 0) + lablen_j = jlen; + } + } else if(desc->_wireformat[wfj] + == LDNS_RDF_TYPE_STR) + lablen_j = (size_t)*dj; + else lablen_j = get_rdf_size( + desc->_wireformat[wfj]) - 1; + } + } else lablen_j--; + di++; + dj++; + } + /* end of the loop; because we advanced byte by byte; now we have + * that the rdata has ended, or that there is a binary remainder */ + /* shortest first */ + if(ilen == 0 && jlen == 0) + return 0; + if(ilen == 0) + return -1; + if(jlen == 0) + return 1; + /* binary remainder, capture comparison in wfi variable */ + if((wfi = memcmp(di, dj, (ilen. + */ +static int +canonical_compare(struct ub_packed_rrset_key* rrset, size_t i, size_t j) +{ + struct packed_rrset_data* d = (struct packed_rrset_data*) + rrset->entry.data; + const ldns_rr_descriptor* desc; + uint16_t type = ntohs(rrset->rk.type); + size_t minlen; + int c; + + if(i==j) + return 0; + /* in case rdata-len is to be compared for canonical order + c = memcmp(d->rr_data[i], d->rr_data[j], 2); + if(c != 0) + return c; */ + + switch(type) { + /* These RR types have only a name as RDATA. + * This name has to be canonicalized.*/ + case LDNS_RR_TYPE_NS: + case LDNS_RR_TYPE_MD: + case LDNS_RR_TYPE_MF: + case LDNS_RR_TYPE_CNAME: + case LDNS_RR_TYPE_MB: + case LDNS_RR_TYPE_MG: + case LDNS_RR_TYPE_MR: + case LDNS_RR_TYPE_PTR: + case LDNS_RR_TYPE_DNAME: + return query_dname_compare(d->rr_data[i]+2, + d->rr_data[j]+2); + + /* These RR types have STR and fixed size rdata fields + * before one or more name fields that need canonicalizing, + * and after that a byte-for byte remainder can be compared. + */ + /* type starts with the name; remainder is binary compared */ + case LDNS_RR_TYPE_NXT: + /* use rdata field formats */ + case LDNS_RR_TYPE_MINFO: + case LDNS_RR_TYPE_RP: + case LDNS_RR_TYPE_SOA: + case LDNS_RR_TYPE_RT: + case LDNS_RR_TYPE_AFSDB: + case LDNS_RR_TYPE_KX: + case LDNS_RR_TYPE_MX: + case LDNS_RR_TYPE_SIG: + /* RRSIG signer name has to be downcased */ + case LDNS_RR_TYPE_RRSIG: + case LDNS_RR_TYPE_PX: + case LDNS_RR_TYPE_NAPTR: + case LDNS_RR_TYPE_SRV: + desc = ldns_rr_descript(type); + log_assert(desc); + /* this holds for the types that need canonicalizing */ + log_assert(desc->_minimum == desc->_maximum); + return canonical_compare_byfield(d, desc, i, j); + + case LDNS_RR_TYPE_HINFO: /* no longer downcased */ + case LDNS_RR_TYPE_NSEC: + default: + /* For unknown RR types, or types not listed above, + * no canonicalization is needed, do binary compare */ + /* byte for byte compare, equal means shortest first*/ + minlen = d->rr_len[i]-2; + if(minlen > d->rr_len[j]-2) + minlen = d->rr_len[j]-2; + c = memcmp(d->rr_data[i]+2, d->rr_data[j]+2, minlen); + if(c!=0) + return c; + /* rdata equal, shortest is first */ + if(d->rr_len[i] < d->rr_len[j]) + return -1; + if(d->rr_len[i] > d->rr_len[j]) + return 1; + /* rdata equal, length equal */ + break; + } + return 0; +} + +int +canonical_tree_compare(const void* k1, const void* k2) +{ + struct canon_rr* r1 = (struct canon_rr*)k1; + struct canon_rr* r2 = (struct canon_rr*)k2; + log_assert(r1->rrset == r2->rrset); + return canonical_compare(r1->rrset, r1->rr_idx, r2->rr_idx); +} + +/** + * Sort RRs for rrset in canonical order. + * Does not actually canonicalize the RR rdatas. + * Does not touch rrsigs. + * @param rrset: to sort. + * @param d: rrset data. + * @param sortree: tree to sort into. + * @param rrs: rr storage. + */ +static void +canonical_sort(struct ub_packed_rrset_key* rrset, struct packed_rrset_data* d, + rbtree_t* sortree, struct canon_rr* rrs) +{ + size_t i; + /* insert into rbtree to sort and detect duplicates */ + for(i=0; icount; i++) { + rrs[i].node.key = &rrs[i]; + rrs[i].rrset = rrset; + rrs[i].rr_idx = i; + if(!rbtree_insert(sortree, &rrs[i].node)) { + /* this was a duplicate */ + } + } +} + +/** + * Inser canonical owner name into buffer. + * @param buf: buffer to insert into at current position. + * @param k: rrset with its owner name. + * @param sig: signature with signer name and label count. + * must be length checked, at least 18 bytes long. + * @param can_owner: position in buffer returned for future use. + * @param can_owner_len: length of canonical owner name. + */ +static void +insert_can_owner(ldns_buffer* buf, struct ub_packed_rrset_key* k, + uint8_t* sig, uint8_t** can_owner, size_t* can_owner_len) +{ + int rrsig_labels = (int)sig[3]; + int fqdn_labels = dname_signame_label_count(k->rk.dname); + *can_owner = ldns_buffer_current(buf); + if(rrsig_labels == fqdn_labels) { + /* no change */ + ldns_buffer_write(buf, k->rk.dname, k->rk.dname_len); + query_dname_tolower(*can_owner); + *can_owner_len = k->rk.dname_len; + return; + } + log_assert(rrsig_labels < fqdn_labels); + /* *. | fqdn(rightmost rrsig_labels) */ + if(rrsig_labels < fqdn_labels) { + int i; + uint8_t* nm = k->rk.dname; + size_t len = k->rk.dname_len; + /* so skip fqdn_labels-rrsig_labels */ + for(i=0; irk.type)) { + case LDNS_RR_TYPE_NXT: + case LDNS_RR_TYPE_NS: + case LDNS_RR_TYPE_MD: + case LDNS_RR_TYPE_MF: + case LDNS_RR_TYPE_CNAME: + case LDNS_RR_TYPE_MB: + case LDNS_RR_TYPE_MG: + case LDNS_RR_TYPE_MR: + case LDNS_RR_TYPE_PTR: + case LDNS_RR_TYPE_DNAME: + /* type only has a single argument, the name */ + query_dname_tolower(datstart); + return; + case LDNS_RR_TYPE_MINFO: + case LDNS_RR_TYPE_RP: + case LDNS_RR_TYPE_SOA: + /* two names after another */ + query_dname_tolower(datstart); + query_dname_tolower(datstart + + dname_valid(datstart, len-2)); + return; + case LDNS_RR_TYPE_RT: + case LDNS_RR_TYPE_AFSDB: + case LDNS_RR_TYPE_KX: + case LDNS_RR_TYPE_MX: + /* skip fixed part */ + if(len < 2+2+1) /* rdlen, skiplen, 1byteroot */ + return; + datstart += 2; + query_dname_tolower(datstart); + return; + case LDNS_RR_TYPE_SIG: + /* downcase the RRSIG, compat with BIND (kept it from SIG) */ + case LDNS_RR_TYPE_RRSIG: + /* skip fixed part */ + if(len < 2+18+1) + return; + datstart += 18; + query_dname_tolower(datstart); + return; + case LDNS_RR_TYPE_PX: + /* skip, then two names after another */ + if(len < 2+2+1) + return; + datstart += 2; + query_dname_tolower(datstart); + query_dname_tolower(datstart + + dname_valid(datstart, len-2-2)); + return; + case LDNS_RR_TYPE_NAPTR: + if(len < 2+4) + return; + len -= 2+4; + datstart += 4; + if(len < (size_t)datstart[0]+1) /* skip text field */ + return; + len -= (size_t)datstart[0]+1; + datstart += (size_t)datstart[0]+1; + if(len < (size_t)datstart[0]+1) /* skip text field */ + return; + len -= (size_t)datstart[0]+1; + datstart += (size_t)datstart[0]+1; + if(len < (size_t)datstart[0]+1) /* skip text field */ + return; + len -= (size_t)datstart[0]+1; + datstart += (size_t)datstart[0]+1; + if(len < 1) /* check name is at least 1 byte*/ + return; + query_dname_tolower(datstart); + return; + case LDNS_RR_TYPE_SRV: + /* skip fixed part */ + if(len < 2+6+1) + return; + datstart += 6; + query_dname_tolower(datstart); + return; + + /* do not canonicalize NSEC rdata name, compat with + * from bind 9.4 signer, where it does not do so */ + case LDNS_RR_TYPE_NSEC: /* type starts with the name */ + case LDNS_RR_TYPE_HINFO: /* not downcased */ + /* A6 not supported */ + default: + /* nothing to do for unknown types */ + return; + } +} + +/** + * Create canonical form of rrset in the scratch buffer. + * @param region: temporary region. + * @param buf: the buffer to use. + * @param k: the rrset to insert. + * @param sig: RRSIG rdata to include. + * @param siglen: RRSIG rdata len excluding signature field, but inclusive + * signer name length. + * @param sortree: if NULL is passed a new sorted rrset tree is built. + * Otherwise it is reused. + * @return false on alloc error. + */ +static int +rrset_canonical(struct regional* region, ldns_buffer* buf, + struct ub_packed_rrset_key* k, uint8_t* sig, size_t siglen, + struct rbtree_t** sortree) +{ + struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data; + uint8_t* can_owner = NULL; + size_t can_owner_len = 0; + struct canon_rr* walk; + struct canon_rr* rrs; + + if(!*sortree) { + *sortree = (struct rbtree_t*)regional_alloc(region, + sizeof(rbtree_t)); + if(!*sortree) + return 0; + rrs = regional_alloc(region, sizeof(struct canon_rr)*d->count); + if(!rrs) { + *sortree = NULL; + return 0; + } + rbtree_init(*sortree, &canonical_tree_compare); + canonical_sort(k, d, *sortree, rrs); + } + + ldns_buffer_clear(buf); + ldns_buffer_write(buf, sig, siglen); + /* canonicalize signer name */ + query_dname_tolower(ldns_buffer_begin(buf)+18); + RBTREE_FOR(walk, struct canon_rr*, (*sortree)) { + /* see if there is enough space left in the buffer */ + if(ldns_buffer_remaining(buf) < can_owner_len + 2 + 2 + 4 + + d->rr_len[walk->rr_idx]) { + log_err("verify: failed to canonicalize, " + "rrset too big"); + return 0; + } + /* determine canonical owner name */ + if(can_owner) + ldns_buffer_write(buf, can_owner, can_owner_len); + else insert_can_owner(buf, k, sig, &can_owner, + &can_owner_len); + ldns_buffer_write(buf, &k->rk.type, 2); + ldns_buffer_write(buf, &k->rk.rrset_class, 2); + ldns_buffer_write(buf, sig+4, 4); + ldns_buffer_write(buf, d->rr_data[walk->rr_idx], + d->rr_len[walk->rr_idx]); + canonicalize_rdata(buf, k, d->rr_len[walk->rr_idx]); + } + ldns_buffer_flip(buf); + return 1; +} + +/** pretty print rrsig error with dates */ +static void +sigdate_error(const char* str, int32_t expi, int32_t incep, int32_t now) +{ + struct tm tm; + char expi_buf[16]; + char incep_buf[16]; + char now_buf[16]; + time_t te, ti, tn; + + if(verbosity < VERB_QUERY) + return; + te = (time_t)expi; + ti = (time_t)incep; + tn = (time_t)now; + memset(&tm, 0, sizeof(tm)); + if(gmtime_r(&te, &tm) && strftime(expi_buf, 15, "%Y%m%d%H%M%S", &tm) + &&gmtime_r(&ti, &tm) && strftime(incep_buf, 15, "%Y%m%d%H%M%S", &tm) + &&gmtime_r(&tn, &tm) && strftime(now_buf, 15, "%Y%m%d%H%M%S", &tm)) { + log_info("%s expi=%s incep=%s now=%s", str, expi_buf, + incep_buf, now_buf); + } else + log_info("%s expi=%u incep=%u now=%u", str, (unsigned)expi, + (unsigned)incep, (unsigned)now); +} + +/** check rrsig dates */ +static int +check_dates(struct val_env* ve, uint32_t unow, + uint8_t* expi_p, uint8_t* incep_p, char** reason) +{ + /* read out the dates */ + int32_t expi, incep, now; + memmove(&expi, expi_p, sizeof(expi)); + memmove(&incep, incep_p, sizeof(incep)); + expi = ntohl(expi); + incep = ntohl(incep); + + /* get current date */ + if(ve->date_override) { + if(ve->date_override == -1) { + verbose(VERB_ALGO, "date override: ignore date"); + return 1; + } + now = ve->date_override; + verbose(VERB_ALGO, "date override option %d", (int)now); + } else now = (int32_t)unow; + + /* check them */ + if(incep - expi > 0) { + sigdate_error("verify: inception after expiration, " + "signature bad", expi, incep, now); + *reason = "signature inception after expiration"; + return 0; + } + if(incep - now > 0) { + /* within skew ? (calc here to avoid calculation normally) */ + int32_t skew = (expi-incep)/10; + if(skew < ve->skew_min) skew = ve->skew_min; + if(skew > ve->skew_max) skew = ve->skew_max; + if(incep - now > skew) { + sigdate_error("verify: signature bad, current time is" + " before inception date", expi, incep, now); + *reason = "signature before inception date"; + return 0; + } + sigdate_error("verify warning suspicious signature inception " + " or bad local clock", expi, incep, now); + } + if(now - expi > 0) { + int32_t skew = (expi-incep)/10; + if(skew < ve->skew_min) skew = ve->skew_min; + if(skew > ve->skew_max) skew = ve->skew_max; + if(now - expi > skew) { + sigdate_error("verify: signature expired", expi, + incep, now); + *reason = "signature expired"; + return 0; + } + sigdate_error("verify warning suspicious signature expiration " + " or bad local clock", expi, incep, now); + } + return 1; +} + +/** adjust rrset TTL for verified rrset, compare to original TTL and expi */ +static void +adjust_ttl(struct val_env* ve, uint32_t unow, + struct ub_packed_rrset_key* rrset, uint8_t* orig_p, + uint8_t* expi_p, uint8_t* incep_p) +{ + struct packed_rrset_data* d = + (struct packed_rrset_data*)rrset->entry.data; + /* read out the dates */ + int32_t origttl, expittl, expi, incep, now; + memmove(&origttl, orig_p, sizeof(origttl)); + memmove(&expi, expi_p, sizeof(expi)); + memmove(&incep, incep_p, sizeof(incep)); + expi = ntohl(expi); + incep = ntohl(incep); + origttl = ntohl(origttl); + + /* get current date */ + if(ve->date_override) { + now = ve->date_override; + } else now = (int32_t)unow; + expittl = expi - now; + + /* so now: + * d->ttl: rrset ttl read from message or cache. May be reduced + * origttl: original TTL from signature, authoritative TTL max. + * expittl: TTL until the signature expires. + * + * Use the smallest of these. + */ + if(d->ttl > (uint32_t)origttl) { + verbose(VERB_QUERY, "rrset TTL larger than original TTL," + " adjusting TTL downwards"); + d->ttl = origttl; + } + if(expittl > 0 && d->ttl > (uint32_t)expittl) { + verbose(VERB_ALGO, "rrset TTL larger than sig expiration ttl," + " adjusting TTL downwards"); + d->ttl = expittl; + } +} + + +/** + * Output a libcrypto openssl error to the logfile. + * @param str: string to add to it. + * @param e: the error to output, error number from ERR_get_error(). + */ +static void +log_crypto_error(const char* str, unsigned long e) +{ + char buf[128]; + /* or use ERR_error_string if ERR_error_string_n is not avail TODO */ + ERR_error_string_n(e, buf, sizeof(buf)); + /* buf now contains */ + /* error:[error code]:[library name]:[function name]:[reason string] */ + log_err("%s crypto %s", str, buf); +} + +/** + * Setup DSA key digest in DER encoding ... + * @param sig: input is signature output alloced ptr (unless failure). + * caller must free alloced ptr if this routine returns true. + * @param len: input is initial siglen, output is output len. + * @return false on failure. + */ +static int +setup_dsa_sig(unsigned char** sig, unsigned int* len) +{ + unsigned char* orig = *sig; + unsigned int origlen = *len; + int newlen; + BIGNUM *R, *S; + DSA_SIG *dsasig; + + /* extract the R and S field from the sig buffer */ + if(origlen < 1 + 2*SHA_DIGEST_LENGTH) + return 0; + R = BN_new(); + if(!R) return 0; + (void) BN_bin2bn(orig + 1, SHA_DIGEST_LENGTH, R); + S = BN_new(); + if(!S) return 0; + (void) BN_bin2bn(orig + 21, SHA_DIGEST_LENGTH, S); + dsasig = DSA_SIG_new(); + if(!dsasig) return 0; + + dsasig->r = R; + dsasig->s = S; + *sig = NULL; + newlen = i2d_DSA_SIG(dsasig, sig); + if(newlen < 0) { + DSA_SIG_free(dsasig); + free(*sig); + return 0; + } + *len = (unsigned int)newlen; + DSA_SIG_free(dsasig); + return 1; +} + +#ifdef USE_ECDSA +/** + * Setup the ECDSA signature in its encoding that the library wants. + * Converts from plain numbers to ASN formatted. + * @param sig: input is signature, output alloced ptr (unless failure). + * caller must free alloced ptr if this routine returns true. + * @param len: input is initial siglen, output is output len. + * @return false on failure. + */ +static int +setup_ecdsa_sig(unsigned char** sig, unsigned int* len) +{ + ECDSA_SIG* ecdsa_sig; + int newlen; + int bnsize = (int)((*len)/2); + /* 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); + return 0; + } + *len = (unsigned int)newlen; + ECDSA_SIG_free(ecdsa_sig); + return 1; +} +#endif /* USE_ECDSA */ + +/** + * Setup key and digest for verification. Adjust sig if necessary. + * + * @param algo: key algorithm + * @param evp_key: EVP PKEY public key to create. + * @param digest_type: digest type to use + * @param key: key to setup for. + * @param keylen: length of key. + * @return false on failure. + */ +static int +setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type, + unsigned char* key, size_t keylen) +{ + DSA* dsa; + RSA* rsa; + + switch(algo) { + case LDNS_DSA: + case LDNS_DSA_NSEC3: + *evp_key = EVP_PKEY_new(); + if(!*evp_key) { + log_err("verify: malloc failure in crypto"); + return sec_status_unchecked; + } + dsa = ldns_key_buf2dsa_raw(key, keylen); + if(!dsa) { + verbose(VERB_QUERY, "verify: " + "ldns_key_buf2dsa_raw failed"); + return 0; + } + if(EVP_PKEY_assign_DSA(*evp_key, dsa) == 0) { + verbose(VERB_QUERY, "verify: " + "EVP_PKEY_assign_DSA failed"); + return 0; + } + *digest_type = EVP_dss1(); + + break; + case LDNS_RSASHA1: + case LDNS_RSASHA1_NSEC3: +#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2) + case LDNS_RSASHA256: +#endif +#if defined(HAVE_EVP_SHA512) && defined(USE_SHA2) + case LDNS_RSASHA512: +#endif + *evp_key = EVP_PKEY_new(); + if(!*evp_key) { + log_err("verify: malloc failure in crypto"); + return sec_status_unchecked; + } + rsa = ldns_key_buf2rsa_raw(key, keylen); + if(!rsa) { + verbose(VERB_QUERY, "verify: " + "ldns_key_buf2rsa_raw SHA failed"); + return 0; + } + if(EVP_PKEY_assign_RSA(*evp_key, rsa) == 0) { + verbose(VERB_QUERY, "verify: " + "EVP_PKEY_assign_RSA SHA failed"); + return 0; + } + + /* select SHA version */ +#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2) + if(algo == LDNS_RSASHA256) + *digest_type = EVP_sha256(); + else +#endif +#if defined(HAVE_EVP_SHA512) && defined(USE_SHA2) + if(algo == LDNS_RSASHA512) + *digest_type = EVP_sha512(); + else +#endif + *digest_type = EVP_sha1(); + + break; + case LDNS_RSAMD5: + *evp_key = EVP_PKEY_new(); + if(!*evp_key) { + log_err("verify: malloc failure in crypto"); + return sec_status_unchecked; + } + rsa = ldns_key_buf2rsa_raw(key, keylen); + if(!rsa) { + verbose(VERB_QUERY, "verify: " + "ldns_key_buf2rsa_raw MD5 failed"); + return 0; + } + if(EVP_PKEY_assign_RSA(*evp_key, rsa) == 0) { + verbose(VERB_QUERY, "verify: " + "EVP_PKEY_assign_RSA MD5 failed"); + return 0; + } + *digest_type = EVP_md5(); + + break; +#ifdef USE_GOST + case LDNS_ECC_GOST: + *evp_key = ldns_gost2pkey_raw(key, keylen); + if(!*evp_key) { + verbose(VERB_QUERY, "verify: " + "ldns_gost2pkey_raw failed"); + return 0; + } + *digest_type = EVP_get_digestbyname("md_gost94"); + if(!*digest_type) { + verbose(VERB_QUERY, "verify: " + "EVP_getdigest md_gost94 failed"); + return 0; + } + break; +#endif +#ifdef USE_ECDSA + case LDNS_ECDSAP256SHA256: + *evp_key = ldns_ecdsa2pkey_raw(key, keylen, + LDNS_ECDSAP256SHA256); + if(!*evp_key) { + verbose(VERB_QUERY, "verify: " + "ldns_ecdsa2pkey_raw failed"); + 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; + } +#else + *digest_type = EVP_sha256(); +#endif + break; + case LDNS_ECDSAP384SHA384: + *evp_key = ldns_ecdsa2pkey_raw(key, keylen, + LDNS_ECDSAP384SHA384); + if(!*evp_key) { + verbose(VERB_QUERY, "verify: " + "ldns_ecdsa2pkey_raw failed"); + 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; + } +#else + *digest_type = EVP_sha384(); +#endif + break; +#endif /* USE_ECDSA */ + default: + verbose(VERB_QUERY, "verify: unknown algorithm %d", + algo); + return 0; + } + return 1; +} + +/** + * Check a canonical sig+rrset and signature against a dnskey + * @param buf: buffer with data to verify, the first rrsig part and the + * canonicalized rrset. + * @param algo: DNSKEY algorithm. + * @param sigblock: signature rdata field from RRSIG + * @param sigblock_len: length of sigblock data. + * @param key: public key data from DNSKEY RR. + * @param keylen: length of keydata. + * @param reason: bogus reason in more detail. + * @return secure if verification succeeded, bogus on crypto failure, + * unchecked on format errors and alloc failures. + */ +static enum sec_status +verify_canonrrset(ldns_buffer* buf, int algo, unsigned char* sigblock, + unsigned int sigblock_len, unsigned char* key, unsigned int keylen, + char** reason) +{ + const EVP_MD *digest_type; + EVP_MD_CTX ctx; + int res, dofree = 0; + EVP_PKEY *evp_key = NULL; + + if(!setup_key_digest(algo, &evp_key, &digest_type, key, keylen)) { + verbose(VERB_QUERY, "verify: failed to setup key"); + *reason = "use of key for crypto failed"; + EVP_PKEY_free(evp_key); + return sec_status_bogus; + } + /* 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) { + if(!setup_dsa_sig(&sigblock, &sigblock_len)) { + verbose(VERB_QUERY, "verify: failed to setup DSA sig"); + *reason = "use of key for DSA crypto failed"; + EVP_PKEY_free(evp_key); + return sec_status_bogus; + } + dofree = 1; + } +#ifdef USE_ECDSA + else 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"); + *reason = "use of signature for ECDSA crypto failed"; + EVP_PKEY_free(evp_key); + return sec_status_bogus; + } + dofree = 1; + } +#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"); + EVP_PKEY_free(evp_key); + if(dofree) free(sigblock); + return sec_status_unchecked; + } + if(EVP_VerifyUpdate(&ctx, (unsigned char*)ldns_buffer_begin(buf), + (unsigned int)ldns_buffer_limit(buf)) == 0) { + verbose(VERB_QUERY, "verify: EVP_VerifyUpdate failed"); + EVP_PKEY_free(evp_key); + if(dofree) 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"); + EVP_PKEY_free(evp_key); + if(dofree) free(sigblock); + return sec_status_unchecked; + } + EVP_PKEY_free(evp_key); + + if(dofree) + free(sigblock); + + if(res == 1) { + return sec_status_secure; + } else if(res == 0) { + verbose(VERB_QUERY, "verify: signature mismatch"); + *reason = "signature crypto failed"; + return sec_status_bogus; + } + + log_crypto_error("verify:", ERR_get_error()); + return sec_status_unchecked; +} + +enum sec_status +dnskey_verify_rrset_sig(struct regional* region, ldns_buffer* buf, + struct val_env* ve, uint32_t now, + struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey, + size_t dnskey_idx, size_t sig_idx, + struct rbtree_t** sortree, int* buf_canon, char** reason) +{ + enum sec_status sec; + uint8_t* sig; /* RRSIG rdata */ + size_t siglen; + size_t rrnum = rrset_get_count(rrset); + uint8_t* signer; /* rrsig signer name */ + size_t signer_len; + unsigned char* sigblock; /* signature rdata field */ + unsigned int sigblock_len; + uint16_t ktag; /* DNSKEY key tag */ + unsigned char* key; /* public key rdata field */ + unsigned int keylen; + rrset_get_rdata(rrset, rrnum + sig_idx, &sig, &siglen); + /* min length of rdatalen, fixed rrsig, root signer, 1 byte sig */ + if(siglen < 2+20) { + verbose(VERB_QUERY, "verify: signature too short"); + *reason = "signature too short"; + return sec_status_bogus; + } + + if(!(dnskey_get_flags(dnskey, dnskey_idx) & DNSKEY_BIT_ZSK)) { + verbose(VERB_QUERY, "verify: dnskey without ZSK flag"); + *reason = "dnskey without ZSK flag"; + return sec_status_bogus; + } + + if(dnskey_get_protocol(dnskey, dnskey_idx) != LDNS_DNSSEC_KEYPROTO) { + /* RFC 4034 says DNSKEY PROTOCOL MUST be 3 */ + verbose(VERB_QUERY, "verify: dnskey has wrong key protocol"); + *reason = "dnskey has wrong protocolnumber"; + return sec_status_bogus; + } + + /* verify as many fields in rrsig as possible */ + signer = sig+2+18; + signer_len = dname_valid(signer, siglen-2-18); + if(!signer_len) { + verbose(VERB_QUERY, "verify: malformed signer name"); + *reason = "signer name malformed"; + return sec_status_bogus; /* signer name invalid */ + } + if(!dname_subdomain_c(rrset->rk.dname, signer)) { + verbose(VERB_QUERY, "verify: signer name is off-tree"); + *reason = "signer name off-tree"; + return sec_status_bogus; /* signer name offtree */ + } + sigblock = (unsigned char*)signer+signer_len; + if(siglen < 2+18+signer_len+1) { + verbose(VERB_QUERY, "verify: too short, no signature data"); + *reason = "signature too short, no signature data"; + return sec_status_bogus; /* sig rdf is < 1 byte */ + } + sigblock_len = (unsigned int)(siglen - 2 - 18 - signer_len); + + /* verify key dname == sig signer name */ + if(query_dname_compare(signer, dnskey->rk.dname) != 0) { + verbose(VERB_QUERY, "verify: wrong key for rrsig"); + log_nametypeclass(VERB_QUERY, "RRSIG signername is", + signer, 0, 0); + log_nametypeclass(VERB_QUERY, "the key name is", + dnskey->rk.dname, 0, 0); + *reason = "signer name mismatches key name"; + return sec_status_bogus; + } + + /* verify covered type */ + /* memcmp works because type is in network format for rrset */ + if(memcmp(sig+2, &rrset->rk.type, 2) != 0) { + verbose(VERB_QUERY, "verify: wrong type covered"); + *reason = "signature covers wrong type"; + return sec_status_bogus; + } + /* verify keytag and sig algo (possibly again) */ + if((int)sig[2+2] != dnskey_get_algo(dnskey, dnskey_idx)) { + verbose(VERB_QUERY, "verify: wrong algorithm"); + *reason = "signature has wrong algorithm"; + return sec_status_bogus; + } + ktag = htons(dnskey_calc_keytag(dnskey, dnskey_idx)); + if(memcmp(sig+2+16, &ktag, 2) != 0) { + verbose(VERB_QUERY, "verify: wrong keytag"); + *reason = "signature has wrong keytag"; + return sec_status_bogus; + } + + /* verify labels is in a valid range */ + if((int)sig[2+3] > dname_signame_label_count(rrset->rk.dname)) { + verbose(VERB_QUERY, "verify: labelcount out of range"); + *reason = "signature labelcount out of range"; + return sec_status_bogus; + } + + /* original ttl, always ok */ + + if(!*buf_canon) { + /* create rrset canonical format in buffer, ready for + * signature */ + if(!rrset_canonical(region, buf, rrset, sig+2, + 18 + signer_len, sortree)) { + log_err("verify: failed due to alloc error"); + return sec_status_unchecked; + } + *buf_canon = 1; + } + + /* check that dnskey is available */ + dnskey_get_pubkey(dnskey, dnskey_idx, &key, &keylen); + if(!key) { + verbose(VERB_QUERY, "verify: short DNSKEY RR"); + return sec_status_unchecked; + } + + /* verify */ + sec = verify_canonrrset(buf, (int)sig[2+2], + sigblock, sigblock_len, key, keylen, reason); + + if(sec == sec_status_secure) { + /* check if TTL is too high - reduce if so */ + adjust_ttl(ve, now, rrset, sig+2+4, sig+2+8, sig+2+12); + + /* verify inception, expiration dates + * Do this last so that if you ignore expired-sigs the + * rest is sure to be OK. */ + if(!check_dates(ve, now, sig+2+8, sig+2+12, reason)) { + return sec_status_bogus; + } + } + + return sec; +} diff --git a/validator/val_sigcrypt.h b/validator/val_sigcrypt.h new file mode 100644 index 00000000000..c220b0083ac --- /dev/null +++ b/validator/val_sigcrypt.h @@ -0,0 +1,311 @@ +/* + * validator/val_sigcrypt.h - validator signature crypto 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains helper functions for the validator module. + * The functions help with signature verification and checking, the + * bridging between RR wireformat data and crypto calls. + */ + +#ifndef VALIDATOR_VAL_SIGCRYPT_H +#define VALIDATOR_VAL_SIGCRYPT_H +#include "util/data/packed_rrset.h" +struct val_env; +struct module_env; +struct ub_packed_rrset_key; +struct rbtree_t; +struct regional; + +/** number of entries in algorithm needs array */ +#define ALGO_NEEDS_MAX 256 + +/** + * Storage for algorithm needs. DNSKEY algorithms. + */ +struct algo_needs { + /** the algorithms (8-bit) with each a number. + * 0: not marked. + * 1: marked 'necessary but not yet fulfilled' + * 2: marked bogus. + * Indexed by algorithm number. + */ + uint8_t needs[ALGO_NEEDS_MAX]; + /** the number of entries in the array that are unfulfilled */ + size_t num; +}; + +/** + * Initialize algo needs structure, set algos from rrset as needed. + * Results are added to an existing need structure. + * @param n: struct with storage. + * @param dnskey: algos from this struct set as necessary. DNSKEY set. + * @param sigalg: adds to signalled algorithm list too. + */ +void algo_needs_init_dnskey_add(struct algo_needs* n, + struct ub_packed_rrset_key* dnskey, uint8_t* sigalg); + +/** + * Initialize algo needs structure from a signalled algo list. + * @param n: struct with storage. + * @param sigalg: signalled algorithm list, numbers ends with 0. + */ +void algo_needs_init_list(struct algo_needs* n, uint8_t* sigalg); + +/** + * Initialize algo needs structure, set algos from rrset as needed. + * @param n: struct with storage. + * @param ds: algos from this struct set as necessary. DS set. + * @param fav_ds_algo: filter to use only this DS algo. + * @param sigalg: list of signalled algos, constructed as output, + * provide size ALGO_NEEDS_MAX+1. list of algonumbers, ends with a zero. + */ +void algo_needs_init_ds(struct algo_needs* n, struct ub_packed_rrset_key* ds, + int fav_ds_algo, uint8_t* sigalg); + +/** + * Mark this algorithm as a success, sec_secure, and see if we are done. + * @param n: storage structure processed. + * @param algo: the algorithm processed to be secure. + * @return if true, processing has finished successfully, we are satisfied. + */ +int algo_needs_set_secure(struct algo_needs* n, uint8_t algo); + +/** + * Mark this algorithm a failure, sec_bogus. It can later be overridden + * by a success for this algorithm (with a different signature). + * @param n: storage structure processed. + * @param algo: the algorithm processed to be bogus. + */ +void algo_needs_set_bogus(struct algo_needs* n, uint8_t algo); + +/** + * See how many algorithms are missing (not bogus or secure, but not processed) + * @param n: storage structure processed. + * @return number of algorithms missing after processing. + */ +size_t algo_needs_num_missing(struct algo_needs* n); + +/** + * See which algo is missing. + * @param n: struct after processing. + * @return if 0 an algorithm was bogus, if a number, this algorithm was + * missing. So on 0, report why that was bogus, on number report a missing + * algorithm. There could be multiple missing, this reports the first one. + */ +int algo_needs_missing(struct algo_needs* n); + +/** + * Format error reason for algorithm missing. + * @param env: module env with scratch for temp storage of string. + * @param alg: DNSKEY-algorithm missing. + * @param reason: destination. + * @param s: string, appended with 'with algorithm ..'. + */ +void algo_needs_reason(struct module_env* env, int alg, char** reason, char* s); + +/** + * Check if dnskey matches a DS digest + * Does not check dnskey-keyid footprint, just the digest. + * @param env: module environment. Uses scratch space. + * @param dnskey_rrset: DNSKEY rrset. + * @param dnskey_idx: index of RR in rrset. + * @param ds_rrset: DS rrset + * @param ds_idx: index of RR in DS rrset. + * @return true if it matches, false on error, not supported or no match. + */ +int ds_digest_match_dnskey(struct module_env* env, + struct ub_packed_rrset_key* dnskey_rrset, size_t dnskey_idx, + struct ub_packed_rrset_key* ds_rrset, size_t ds_idx); + +/** + * Get dnskey keytag, footprint value + * @param dnskey_rrset: DNSKEY rrset. + * @param dnskey_idx: index of RR in rrset. + * @return the keytag or 0 for badly formatted DNSKEYs. + */ +uint16_t dnskey_calc_keytag(struct ub_packed_rrset_key* dnskey_rrset, + size_t dnskey_idx); + +/** + * Get DS keytag, footprint value that matches the DNSKEY keytag it signs. + * @param ds_rrset: DS rrset + * @param ds_idx: index of RR in DS rrset. + * @return the keytag or 0 for badly formatted DSs. + */ +uint16_t ds_get_keytag(struct ub_packed_rrset_key* ds_rrset, size_t ds_idx); + +/** + * See if DNSKEY algorithm is supported + * @param dnskey_rrset: DNSKEY rrset. + * @param dnskey_idx: index of RR in rrset. + * @return true if supported. + */ +int dnskey_algo_is_supported(struct ub_packed_rrset_key* dnskey_rrset, + size_t dnskey_idx); + +/** + * See if DS digest algorithm is supported + * @param ds_rrset: DS rrset + * @param ds_idx: index of RR in DS rrset. + * @return true if supported. + */ +int ds_digest_algo_is_supported(struct ub_packed_rrset_key* ds_rrset, + size_t ds_idx); + +/** + * Get DS RR digest algorithm + * @param ds_rrset: DS rrset. + * @param ds_idx: which DS. + * @return algorithm or 0 if DS too short. + */ +int ds_get_digest_algo(struct ub_packed_rrset_key* ds_rrset, size_t ds_idx); + +/** + * See if DS key algorithm is supported + * @param ds_rrset: DS rrset + * @param ds_idx: index of RR in DS rrset. + * @return true if supported. + */ +int ds_key_algo_is_supported(struct ub_packed_rrset_key* ds_rrset, + size_t ds_idx); + +/** + * Get DS RR key algorithm. This value should match with the DNSKEY algo. + * @param k: DS rrset. + * @param idx: which DS. + * @return algorithm or 0 if DS too short. + */ +int ds_get_key_algo(struct ub_packed_rrset_key* k, size_t idx); + +/** + * Get DNSKEY RR signature algorithm + * @param k: DNSKEY rrset. + * @param idx: which DNSKEY RR. + * @return algorithm or 0 if DNSKEY too short. + */ +int dnskey_get_algo(struct ub_packed_rrset_key* k, size_t idx); + +/** + * Get DNSKEY RR flags + * @param k: DNSKEY rrset. + * @param idx: which DNSKEY RR. + * @return flags or 0 if DNSKEY too short. + */ +uint16_t dnskey_get_flags(struct ub_packed_rrset_key* k, size_t idx); + +/** + * Verify rrset against dnskey rrset. + * @param env: module environment, scratch space is used. + * @param ve: validator environment, date settings. + * @param rrset: to be validated. + * @param dnskey: DNSKEY rrset, keyset to try. + * @param sigalg: if nonNULL provide downgrade protection otherwise one + * algorithm is enough. + * @param reason: if bogus, a string returned, fixed or alloced in scratch. + * @return SECURE if one key in the set verifies one rrsig. + * UNCHECKED on allocation errors, unsupported algorithms, malformed data, + * and BOGUS on verification failures (no keys match any signatures). + */ +enum sec_status dnskeyset_verify_rrset(struct module_env* env, + struct val_env* ve, struct ub_packed_rrset_key* rrset, + struct ub_packed_rrset_key* dnskey, uint8_t* sigalg, char** reason); + +/** + * verify rrset against one specific dnskey (from rrset) + * @param env: module environment, scratch space is used. + * @param ve: validator environment, date settings. + * @param rrset: to be validated. + * @param dnskey: DNSKEY rrset, keyset. + * @param dnskey_idx: which key from the rrset to try. + * @param reason: if bogus, a string returned, fixed or alloced in scratch. + * @return secure if *this* key signs any of the signatures on rrset. + * unchecked on error or and bogus on bad signature. + */ +enum sec_status dnskey_verify_rrset(struct module_env* env, + struct val_env* ve, struct ub_packed_rrset_key* rrset, + struct ub_packed_rrset_key* dnskey, size_t dnskey_idx, char** reason); + +/** + * verify rrset, with dnskey rrset, for a specific rrsig in rrset + * @param env: module environment, scratch space is used. + * @param ve: validator environment, date settings. + * @param now: current time for validation (can be overridden). + * @param rrset: to be validated. + * @param dnskey: DNSKEY rrset, keyset to try. + * @param sig_idx: which signature to try to validate. + * @param sortree: reused sorted order. Stored in region. Pass NULL at start, + * and for a new rrset. + * @param reason: if bogus, a string returned, fixed or alloced in scratch. + * @return secure if any key signs *this* signature. bogus if no key signs it, + * or unchecked on error. + */ +enum sec_status dnskeyset_verify_rrset_sig(struct module_env* env, + struct val_env* ve, uint32_t now, struct ub_packed_rrset_key* rrset, + struct ub_packed_rrset_key* dnskey, size_t sig_idx, + struct rbtree_t** sortree, char** reason); + +/** + * verify rrset, with specific dnskey(from set), for a specific rrsig + * @param region: scratch region used for temporary allocation. + * @param buf: scratch buffer used for canonicalized rrset data. + * @param ve: validator environment, date settings. + * @param now: current time for validation (can be overridden). + * @param rrset: to be validated. + * @param dnskey: DNSKEY rrset, keyset. + * @param dnskey_idx: which key from the rrset to try. + * @param sig_idx: which signature to try to validate. + * @param sortree: pass NULL at start, the sorted rrset order is returned. + * pass it again for the same rrset. + * @param buf_canon: if true, the buffer is already canonical. + * pass false at start. pass old value only for same rrset and same + * signature (but perhaps different key) for reuse. + * @param reason: if bogus, a string returned, fixed or alloced in scratch. + * @return secure if this key signs this signature. unchecked on error or + * bogus if it did not validate. + */ +enum sec_status dnskey_verify_rrset_sig(struct regional* region, + ldns_buffer* buf, struct val_env* ve, uint32_t now, + struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey, + size_t dnskey_idx, size_t sig_idx, + struct rbtree_t** sortree, int* buf_canon, char** reason); + +/** + * canonical compare for two tree entries + */ +int canonical_tree_compare(const void* k1, const void* k2); + +#endif /* VALIDATOR_VAL_SIGCRYPT_H */ diff --git a/validator/val_utils.c b/validator/val_utils.c new file mode 100644 index 00000000000..b0475d8031c --- /dev/null +++ b/validator/val_utils.c @@ -0,0 +1,1082 @@ +/* + * validator/val_utils.c - validator utility 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains helper functions for the validator module. + */ +#include "config.h" +#include "validator/val_utils.h" +#include "validator/validator.h" +#include "validator/val_kentry.h" +#include "validator/val_sigcrypt.h" +#include "validator/val_anchor.h" +#include "validator/val_nsec.h" +#include "validator/val_neg.h" +#include "services/cache/rrset.h" +#include "services/cache/dns.h" +#include "util/data/msgreply.h" +#include "util/data/packed_rrset.h" +#include "util/data/dname.h" +#include "util/net_help.h" +#include "util/module.h" +#include "util/regional.h" +#include "util/config_file.h" + +enum val_classification +val_classify_response(uint16_t query_flags, struct query_info* origqinf, + struct query_info* qinf, struct reply_info* rep, size_t skip) +{ + int rcode = (int)FLAGS_GET_RCODE(rep->flags); + size_t i; + + /* Normal Name Error's are easy to detect -- but don't mistake a CNAME + * chain ending in NXDOMAIN. */ + if(rcode == LDNS_RCODE_NXDOMAIN && rep->an_numrrsets == 0) + return VAL_CLASS_NAMEERROR; + + /* check for referral: nonRD query and it looks like a nodata */ + if(!(query_flags&BIT_RD) && rep->an_numrrsets == 0 && + rcode == LDNS_RCODE_NOERROR) { + /* SOA record in auth indicates it is NODATA instead. + * All validation requiring NODATA messages have SOA in + * authority section. */ + /* uses fact that answer section is empty */ + int saw_ns = 0; + for(i=0; ins_numrrsets; i++) { + if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_SOA) + return VAL_CLASS_NODATA; + if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_DS) + return VAL_CLASS_REFERRAL; + if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NS) + saw_ns = 1; + } + return saw_ns?VAL_CLASS_REFERRAL:VAL_CLASS_NODATA; + } + /* root referral where NS set is in the answer section */ + if(!(query_flags&BIT_RD) && rep->ns_numrrsets == 0 && + rep->an_numrrsets == 1 && rcode == LDNS_RCODE_NOERROR && + ntohs(rep->rrsets[0]->rk.type) == LDNS_RR_TYPE_NS && + query_dname_compare(rep->rrsets[0]->rk.dname, + origqinf->qname) != 0) + return VAL_CLASS_REFERRAL; + + /* dump bad messages */ + if(rcode != LDNS_RCODE_NOERROR && rcode != LDNS_RCODE_NXDOMAIN) + return VAL_CLASS_UNKNOWN; + /* next check if the skip into the answer section shows no answer */ + if(skip>0 && rep->an_numrrsets <= skip) + return VAL_CLASS_CNAMENOANSWER; + + /* Next is NODATA */ + if(rcode == LDNS_RCODE_NOERROR && rep->an_numrrsets == 0) + return VAL_CLASS_NODATA; + + /* We distinguish between CNAME response and other positive/negative + * responses because CNAME answers require extra processing. */ + + /* We distinguish between ANY and CNAME or POSITIVE because + * ANY responses are validated differently. */ + if(rcode == LDNS_RCODE_NOERROR && qinf->qtype == LDNS_RR_TYPE_ANY) + return VAL_CLASS_ANY; + + /* Note that DNAMEs will be ignored here, unless qtype=DNAME. Unless + * qtype=CNAME, this will yield a CNAME response. */ + for(i=skip; ian_numrrsets; i++) { + if(rcode == LDNS_RCODE_NOERROR && + ntohs(rep->rrsets[i]->rk.type) == qinf->qtype) + return VAL_CLASS_POSITIVE; + if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_CNAME) + return VAL_CLASS_CNAME; + } + log_dns_msg("validator: error. failed to classify response message: ", + qinf, rep); + return VAL_CLASS_UNKNOWN; +} + +/** Get signer name from RRSIG */ +static void +rrsig_get_signer(uint8_t* data, size_t len, uint8_t** sname, size_t* slen) +{ + /* RRSIG rdata is not allowed to be compressed, it is stored + * uncompressed in memory as well, so return a ptr to the name */ + if(len < 21) { + /* too short RRSig: + * short, byte, byte, long, long, long, short, "." is + * 2 1 1 4 4 4 2 1 = 19 + * and a skip of 18 bytes to the name. + * +2 for the rdatalen is 21 bytes len for root label */ + *sname = NULL; + *slen = 0; + return; + } + data += 20; /* skip the fixed size bits */ + len -= 20; + *slen = dname_valid(data, len); + if(!*slen) { + /* bad dname in this rrsig. */ + *sname = NULL; + return; + } + *sname = data; +} + +void +val_find_rrset_signer(struct ub_packed_rrset_key* rrset, uint8_t** sname, + size_t* slen) +{ + struct packed_rrset_data* d = (struct packed_rrset_data*) + rrset->entry.data; + /* return signer for first signature, or NULL */ + if(d->rrsig_count == 0) { + *sname = NULL; + *slen = 0; + return; + } + /* get rrsig signer name out of the signature */ + rrsig_get_signer(d->rr_data[d->count], d->rr_len[d->count], + sname, slen); +} + +/** + * Find best signer name in this set of rrsigs. + * @param rrset: which rrsigs to look through. + * @param qinf: the query name that needs validation. + * @param signer_name: the best signer_name. Updated if a better one is found. + * @param signer_len: length of signer name. + * @param matchcount: count of current best name (starts at 0 for no match). + * Updated if match is improved. + */ +static void +val_find_best_signer(struct ub_packed_rrset_key* rrset, + struct query_info* qinf, uint8_t** signer_name, size_t* signer_len, + int* matchcount) +{ + struct packed_rrset_data* d = (struct packed_rrset_data*) + rrset->entry.data; + uint8_t* sign; + size_t i; + int m; + for(i=d->count; icount+d->rrsig_count; i++) { + sign = d->rr_data[i]+2+18; + /* look at signatures that are valid (long enough), + * and have a signer name that is a superdomain of qname, + * and then check the number of labels in the shared topdomain + * improve the match if possible */ + if(d->rr_len[i] > 2+19 && /* rdata, sig + root label*/ + dname_subdomain_c(qinf->qname, sign)) { + (void)dname_lab_cmp(qinf->qname, + dname_count_labels(qinf->qname), + sign, dname_count_labels(sign), &m); + if(m > *matchcount) { + *matchcount = m; + *signer_name = sign; + (void)dname_count_size_labels(*signer_name, + signer_len); + } + } + } +} + +void +val_find_signer(enum val_classification subtype, struct query_info* qinf, + struct reply_info* rep, size_t skip, uint8_t** signer_name, + size_t* signer_len) +{ + size_t i; + + if(subtype == VAL_CLASS_POSITIVE || subtype == VAL_CLASS_ANY) { + /* check for the answer rrset */ + for(i=skip; ian_numrrsets; i++) { + if(query_dname_compare(qinf->qname, + rep->rrsets[i]->rk.dname) == 0) { + val_find_rrset_signer(rep->rrsets[i], + signer_name, signer_len); + return; + } + } + *signer_name = NULL; + *signer_len = 0; + } else if(subtype == VAL_CLASS_CNAME) { + /* check for the first signed cname/dname rrset */ + for(i=skip; ian_numrrsets; i++) { + val_find_rrset_signer(rep->rrsets[i], + signer_name, signer_len); + if(*signer_name) + return; + if(ntohs(rep->rrsets[i]->rk.type) != LDNS_RR_TYPE_DNAME) + break; /* only check CNAME after a DNAME */ + } + *signer_name = NULL; + *signer_len = 0; + } else if(subtype == VAL_CLASS_NAMEERROR + || subtype == VAL_CLASS_NODATA) { + /*Check to see if the AUTH section NSEC record(s) have rrsigs*/ + for(i=rep->an_numrrsets; i< + rep->an_numrrsets+rep->ns_numrrsets; i++) { + if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NSEC + || ntohs(rep->rrsets[i]->rk.type) == + LDNS_RR_TYPE_NSEC3) { + val_find_rrset_signer(rep->rrsets[i], + signer_name, signer_len); + return; + } + } + } else if(subtype == VAL_CLASS_CNAMENOANSWER) { + /* find closest superdomain signer name in authority section + * NSEC and NSEC3s */ + int matchcount = 0; + *signer_name = NULL; + *signer_len = 0; + for(i=rep->an_numrrsets; ian_numrrsets+rep-> + ns_numrrsets; i++) { + if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NSEC + || ntohs(rep->rrsets[i]->rk.type) == + LDNS_RR_TYPE_NSEC3) { + val_find_best_signer(rep->rrsets[i], qinf, + signer_name, signer_len, &matchcount); + } + } + } else if(subtype == VAL_CLASS_REFERRAL) { + /* find keys for the item at skip */ + if(skip < rep->rrset_count) { + val_find_rrset_signer(rep->rrsets[skip], + signer_name, signer_len); + return; + } + *signer_name = NULL; + *signer_len = 0; + } else { + verbose(VERB_QUERY, "find_signer: could not find signer name" + " for unknown type response"); + *signer_name = NULL; + *signer_len = 0; + } +} + +/** return number of rrs in an rrset */ +static size_t +rrset_get_count(struct ub_packed_rrset_key* rrset) +{ + struct packed_rrset_data* d = (struct packed_rrset_data*) + rrset->entry.data; + if(!d) return 0; + return d->count; +} + +/** return TTL of rrset */ +static uint32_t +rrset_get_ttl(struct ub_packed_rrset_key* rrset) +{ + struct packed_rrset_data* d = (struct packed_rrset_data*) + rrset->entry.data; + if(!d) return 0; + return d->ttl; +} + +enum sec_status +val_verify_rrset(struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* keys, + uint8_t* sigalg, char** reason) +{ + enum sec_status sec; + struct packed_rrset_data* d = (struct packed_rrset_data*)rrset-> + entry.data; + if(d->security == sec_status_secure) { + /* re-verify all other statuses, because keyset may change*/ + log_nametypeclass(VERB_ALGO, "verify rrset cached", + rrset->rk.dname, ntohs(rrset->rk.type), + ntohs(rrset->rk.rrset_class)); + return d->security; + } + /* check in the cache if verification has already been done */ + rrset_check_sec_status(env->rrset_cache, rrset, *env->now); + if(d->security == sec_status_secure) { + log_nametypeclass(VERB_ALGO, "verify rrset from cache", + rrset->rk.dname, ntohs(rrset->rk.type), + ntohs(rrset->rk.rrset_class)); + return d->security; + } + log_nametypeclass(VERB_ALGO, "verify rrset", rrset->rk.dname, + ntohs(rrset->rk.type), ntohs(rrset->rk.rrset_class)); + sec = dnskeyset_verify_rrset(env, ve, rrset, keys, sigalg, reason); + verbose(VERB_ALGO, "verify result: %s", sec_status_to_string(sec)); + regional_free_all(env->scratch); + + /* update rrset security status + * only improves security status + * and bogus is set only once, even if we rechecked the status */ + if(sec > d->security) { + d->security = sec; + if(sec == sec_status_secure) + d->trust = rrset_trust_validated; + else if(sec == sec_status_bogus) { + size_t i; + /* update ttl for rrset to fixed value. */ + d->ttl = ve->bogus_ttl; + for(i=0; icount+d->rrsig_count; i++) + d->rr_ttl[i] = ve->bogus_ttl; + /* leave RR specific TTL: not used for determine + * if RRset timed out and clients see proper value. */ + lock_basic_lock(&ve->bogus_lock); + ve->num_rrset_bogus++; + lock_basic_unlock(&ve->bogus_lock); + } + /* if status updated - store in cache for reuse */ + rrset_update_sec_status(env->rrset_cache, rrset, *env->now); + } + + return sec; +} + +enum sec_status +val_verify_rrset_entry(struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key* rrset, struct key_entry_key* kkey, + char** reason) +{ + /* temporary dnskey rrset-key */ + struct ub_packed_rrset_key dnskey; + struct key_entry_data* kd = (struct key_entry_data*)kkey->entry.data; + enum sec_status sec; + dnskey.rk.type = htons(kd->rrset_type); + dnskey.rk.rrset_class = htons(kkey->key_class); + dnskey.rk.flags = 0; + dnskey.rk.dname = kkey->name; + dnskey.rk.dname_len = kkey->namelen; + dnskey.entry.key = &dnskey; + dnskey.entry.data = kd->rrset_data; + sec = val_verify_rrset(env, ve, rrset, &dnskey, kd->algo, reason); + return sec; +} + +/** verify that a DS RR hashes to a key and that key signs the set */ +static enum sec_status +verify_dnskeys_with_ds_rr(struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key* dnskey_rrset, + struct ub_packed_rrset_key* ds_rrset, size_t ds_idx, char** reason) +{ + enum sec_status sec = sec_status_bogus; + size_t i, num, numchecked = 0, numhashok = 0; + num = rrset_get_count(dnskey_rrset); + for(i=0; i digest_algo) + digest_algo = d; + } + return digest_algo; +} + +enum sec_status +val_verify_DNSKEY_with_DS(struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key* dnskey_rrset, + struct ub_packed_rrset_key* ds_rrset, uint8_t* sigalg, char** reason) +{ + /* as long as this is false, we can consider this DS rrset to be + * equivalent to no DS rrset. */ + int has_useful_ds = 0, digest_algo, alg; + struct algo_needs needs; + size_t i, num; + enum sec_status sec; + + if(dnskey_rrset->rk.dname_len != ds_rrset->rk.dname_len || + query_dname_compare(dnskey_rrset->rk.dname, ds_rrset->rk.dname) + != 0) { + verbose(VERB_QUERY, "DNSKEY RRset did not match DS RRset " + "by name"); + *reason = "DNSKEY RRset did not match DS RRset by name"; + return sec_status_bogus; + } + + digest_algo = val_favorite_ds_algo(ds_rrset); + if(sigalg) + algo_needs_init_ds(&needs, ds_rrset, digest_algo, sigalg); + num = rrset_get_count(ds_rrset); + for(i=0; irk.dname, ds_rrset->rk.dname_len, + ntohs(ds_rrset->rk.rrset_class), dnskey_rrset, + downprot?sigalg:NULL, *env->now); + } else if(sec == sec_status_insecure) { + return key_entry_create_null(region, ds_rrset->rk.dname, + ds_rrset->rk.dname_len, + ntohs(ds_rrset->rk.rrset_class), + rrset_get_ttl(ds_rrset), *env->now); + } + return key_entry_create_bad(region, ds_rrset->rk.dname, + ds_rrset->rk.dname_len, ntohs(ds_rrset->rk.rrset_class), + BOGUS_KEY_TTL, *env->now); +} + +enum sec_status +val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key* dnskey_rrset, + struct ub_packed_rrset_key* ta_ds, + struct ub_packed_rrset_key* ta_dnskey, uint8_t* sigalg, char** reason) +{ + /* as long as this is false, we can consider this anchor to be + * equivalent to no anchor. */ + int has_useful_ta = 0, digest_algo = 0, alg; + struct algo_needs needs; + size_t i, num; + enum sec_status sec; + + if(ta_ds && (dnskey_rrset->rk.dname_len != ta_ds->rk.dname_len || + query_dname_compare(dnskey_rrset->rk.dname, ta_ds->rk.dname) + != 0)) { + verbose(VERB_QUERY, "DNSKEY RRset did not match DS RRset " + "by name"); + *reason = "DNSKEY RRset did not match DS RRset by name"; + return sec_status_bogus; + } + if(ta_dnskey && (dnskey_rrset->rk.dname_len != ta_dnskey->rk.dname_len + || query_dname_compare(dnskey_rrset->rk.dname, ta_dnskey->rk.dname) + != 0)) { + verbose(VERB_QUERY, "DNSKEY RRset did not match anchor RRset " + "by name"); + *reason = "DNSKEY RRset did not match anchor RRset by name"; + return sec_status_bogus; + } + + if(ta_ds) + digest_algo = val_favorite_ds_algo(ta_ds); + if(sigalg) { + if(ta_ds) + algo_needs_init_ds(&needs, ta_ds, digest_algo, sigalg); + else memset(&needs, 0, sizeof(needs)); + if(ta_dnskey) + algo_needs_init_dnskey_add(&needs, ta_dnskey, sigalg); + } + if(ta_ds) { + num = rrset_get_count(ta_ds); + for(i=0; irk.dname, dnskey_rrset->rk.dname_len, + ntohs(dnskey_rrset->rk.rrset_class), dnskey_rrset, + downprot?sigalg:NULL, *env->now); + } else if(sec == sec_status_insecure) { + return key_entry_create_null(region, dnskey_rrset->rk.dname, + dnskey_rrset->rk.dname_len, + ntohs(dnskey_rrset->rk.rrset_class), + rrset_get_ttl(dnskey_rrset), *env->now); + } + return key_entry_create_bad(region, dnskey_rrset->rk.dname, + dnskey_rrset->rk.dname_len, ntohs(dnskey_rrset->rk.rrset_class), + BOGUS_KEY_TTL, *env->now); +} + +int +val_dsset_isusable(struct ub_packed_rrset_key* ds_rrset) +{ + size_t i; + for(i=0; irr_len[sig] < 2+4) + return 0; /* bad sig length */ + return d->rr_data[sig][2+3]; +} + +int +val_rrset_wildcard(struct ub_packed_rrset_key* rrset, uint8_t** wc) +{ + struct packed_rrset_data* d = (struct packed_rrset_data*)rrset-> + entry.data; + uint8_t labcount; + int labdiff; + uint8_t* wn; + size_t i, wl; + if(d->rrsig_count == 0) { + return 1; + } + labcount = rrsig_get_labcount(d, d->count + 0); + /* check rest of signatures identical */ + for(i=1; irrsig_count; i++) { + if(labcount != rrsig_get_labcount(d, d->count + i)) { + return 0; + } + } + /* OK the rrsigs check out */ + /* if the RRSIG label count is shorter than the number of actual + * labels, then this rrset was synthesized from a wildcard. + * Note that the RRSIG label count doesn't count the root label. */ + wn = rrset->rk.dname; + wl = rrset->rk.dname_len; + /* skip a leading wildcard label in the dname (RFC4035 2.2) */ + if(dname_is_wild(wn)) { + wn += 2; + wl -= 2; + } + labdiff = (dname_count_labels(wn) - 1) - (int)labcount; + if(labdiff > 0) { + *wc = wn; + dname_remove_labels(wc, &wl, labdiff); + return 1; + } + return 1; +} + +int +val_chase_cname(struct query_info* qchase, struct reply_info* rep, + size_t* cname_skip) { + size_t i; + /* skip any DNAMEs, go to the CNAME for next part */ + for(i = *cname_skip; i < rep->an_numrrsets; i++) { + if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_CNAME && + query_dname_compare(qchase->qname, rep->rrsets[i]-> + rk.dname) == 0) { + qchase->qname = NULL; + get_cname_target(rep->rrsets[i], &qchase->qname, + &qchase->qname_len); + if(!qchase->qname) + return 0; /* bad CNAME rdata */ + (*cname_skip) = i+1; + return 1; + } + } + return 0; /* CNAME classified but no matching CNAME ?! */ +} + +/** see if rrset has signer name as one of the rrsig signers */ +static int +rrset_has_signer(struct ub_packed_rrset_key* rrset, uint8_t* name, size_t len) +{ + struct packed_rrset_data* d = (struct packed_rrset_data*)rrset-> + entry.data; + size_t i; + for(i = d->count; i< d->count+d->rrsig_count; i++) { + if(d->rr_len[i] > 2+18+len) { + /* at least rdatalen + signature + signame (+1 sig)*/ + if(query_dname_compare(name, d->rr_data[i]+2+18) == 0) + { + return 1; + } + } + } + return 0; +} + +void +val_fill_reply(struct reply_info* chase, struct reply_info* orig, + size_t skip, uint8_t* name, size_t len, uint8_t* signer) +{ + size_t i; + int seen_dname = 0; + chase->rrset_count = 0; + chase->an_numrrsets = 0; + chase->ns_numrrsets = 0; + chase->ar_numrrsets = 0; + /* ANSWER section */ + for(i=skip; ian_numrrsets; i++) { + if(!signer) { + if(query_dname_compare(name, + orig->rrsets[i]->rk.dname) == 0) + chase->rrsets[chase->an_numrrsets++] = + orig->rrsets[i]; + } else if(seen_dname && ntohs(orig->rrsets[i]->rk.type) == + LDNS_RR_TYPE_CNAME) { + chase->rrsets[chase->an_numrrsets++] = orig->rrsets[i]; + seen_dname = 0; + } else if(rrset_has_signer(orig->rrsets[i], name, len)) { + chase->rrsets[chase->an_numrrsets++] = orig->rrsets[i]; + if(ntohs(orig->rrsets[i]->rk.type) == + LDNS_RR_TYPE_DNAME) { + seen_dname = 1; + } + } + } + /* AUTHORITY section */ + for(i = (skip > orig->an_numrrsets)?skip:orig->an_numrrsets; + ian_numrrsets+orig->ns_numrrsets; + i++) { + if(!signer) { + if(query_dname_compare(name, + orig->rrsets[i]->rk.dname) == 0) + chase->rrsets[chase->an_numrrsets+ + chase->ns_numrrsets++] = orig->rrsets[i]; + } else if(rrset_has_signer(orig->rrsets[i], name, len)) { + chase->rrsets[chase->an_numrrsets+ + chase->ns_numrrsets++] = orig->rrsets[i]; + } + } + /* ADDITIONAL section */ + for(i= (skip>orig->an_numrrsets+orig->ns_numrrsets)? + skip:orig->an_numrrsets+orig->ns_numrrsets; + irrset_count; i++) { + if(!signer) { + if(query_dname_compare(name, + orig->rrsets[i]->rk.dname) == 0) + chase->rrsets[chase->an_numrrsets + +orig->ns_numrrsets+chase->ar_numrrsets++] + = orig->rrsets[i]; + } else if(rrset_has_signer(orig->rrsets[i], name, len)) { + chase->rrsets[chase->an_numrrsets+orig->ns_numrrsets+ + chase->ar_numrrsets++] = orig->rrsets[i]; + } + } + chase->rrset_count = chase->an_numrrsets + chase->ns_numrrsets + + chase->ar_numrrsets; +} + +void +val_check_nonsecure(struct val_env* ve, struct reply_info* rep) +{ + size_t i; + /* authority */ + for(i=rep->an_numrrsets; ian_numrrsets+rep->ns_numrrsets; i++) { + if(((struct packed_rrset_data*)rep->rrsets[i]->entry.data) + ->security != sec_status_secure) { + /* because we want to return the authentic original + * message when presented with CD-flagged queries, + * we need to preserve AUTHORITY section data. + * However, this rrset is not signed or signed + * with the wrong keys. Validation has tried to + * verify this rrset with the keysets of import. + * But this rrset did not verify. + * Therefore the message is bogus. + */ + + /* check if authority consists of only an NS record + * which is bad, and there is an answer section with + * data. In that case, delete NS and additional to + * be lenient and make a minimal response */ + if(rep->an_numrrsets != 0 && rep->ns_numrrsets == 1 && + ntohs(rep->rrsets[i]->rk.type) + == LDNS_RR_TYPE_NS) { + verbose(VERB_ALGO, "truncate to minimal"); + rep->ns_numrrsets = 0; + rep->ar_numrrsets = 0; + rep->rrset_count = rep->an_numrrsets; + return; + } + + log_nametypeclass(VERB_QUERY, "message is bogus, " + "non secure rrset", + rep->rrsets[i]->rk.dname, + ntohs(rep->rrsets[i]->rk.type), + ntohs(rep->rrsets[i]->rk.rrset_class)); + rep->security = sec_status_bogus; + return; + } + } + /* additional */ + if(!ve->clean_additional) + return; + for(i=rep->an_numrrsets+rep->ns_numrrsets; irrset_count; i++) { + if(((struct packed_rrset_data*)rep->rrsets[i]->entry.data) + ->security != sec_status_secure) { + /* This does not cause message invalidation. It was + * simply unsigned data in the additional. The + * RRSIG must have been truncated off the message. + * + * However, we do not want to return possible bogus + * data to clients that rely on this service for + * their authentication. + */ + /* remove this unneeded additional rrset */ + memmove(rep->rrsets+i, rep->rrsets+i+1, + sizeof(struct ub_packed_rrset_key*)* + (rep->rrset_count - i - 1)); + rep->ar_numrrsets--; + rep->rrset_count--; + i--; + } + } +} + +/** check no anchor and unlock */ +static int +check_no_anchor(struct val_anchors* anchors, uint8_t* nm, size_t l, uint16_t c) +{ + struct trust_anchor* ta; + if((ta=anchors_lookup(anchors, nm, l, c))) { + lock_basic_unlock(&ta->lock); + } + return !ta; +} + +void +val_mark_indeterminate(struct reply_info* rep, struct val_anchors* anchors, + struct rrset_cache* r, struct module_env* env) +{ + size_t i; + struct packed_rrset_data* d; + for(i=0; irrset_count; i++) { + d = (struct packed_rrset_data*)rep->rrsets[i]->entry.data; + if(d->security == sec_status_unchecked && + check_no_anchor(anchors, rep->rrsets[i]->rk.dname, + rep->rrsets[i]->rk.dname_len, + ntohs(rep->rrsets[i]->rk.rrset_class))) + { + /* mark as indeterminate */ + d->security = sec_status_indeterminate; + rrset_update_sec_status(r, rep->rrsets[i], *env->now); + } + } +} + +void +val_mark_insecure(struct reply_info* rep, uint8_t* kname, + struct rrset_cache* r, struct module_env* env) +{ + size_t i; + struct packed_rrset_data* d; + for(i=0; irrset_count; i++) { + d = (struct packed_rrset_data*)rep->rrsets[i]->entry.data; + if(d->security == sec_status_unchecked && + dname_subdomain_c(rep->rrsets[i]->rk.dname, kname)) { + /* mark as insecure */ + d->security = sec_status_insecure; + rrset_update_sec_status(r, rep->rrsets[i], *env->now); + } + } +} + +size_t +val_next_unchecked(struct reply_info* rep, size_t skip) +{ + size_t i; + struct packed_rrset_data* d; + for(i=skip+1; irrset_count; i++) { + d = (struct packed_rrset_data*)rep->rrsets[i]->entry.data; + if(d->security == sec_status_unchecked) { + return i; + } + } + return rep->rrset_count; +} + +const char* +val_classification_to_string(enum val_classification subtype) +{ + switch(subtype) { + case VAL_CLASS_UNTYPED: return "untyped"; + case VAL_CLASS_UNKNOWN: return "unknown"; + case VAL_CLASS_POSITIVE: return "positive"; + case VAL_CLASS_CNAME: return "cname"; + case VAL_CLASS_NODATA: return "nodata"; + case VAL_CLASS_NAMEERROR: return "nameerror"; + case VAL_CLASS_CNAMENOANSWER: return "cnamenoanswer"; + case VAL_CLASS_REFERRAL: return "referral"; + case VAL_CLASS_ANY: return "qtype_any"; + default: + return "bad_val_classification"; + } +} + +/** log a sock_list entry */ +static void +sock_list_logentry(enum verbosity_value v, const char* s, struct sock_list* p) +{ + if(p->len) + log_addr(v, s, &p->addr, p->len); + else verbose(v, "%s cache", s); +} + +void val_blacklist(struct sock_list** blacklist, struct regional* region, + struct sock_list* origin, int cross) +{ + /* debug printout */ + if(verbosity >= VERB_ALGO) { + struct sock_list* p; + for(p=*blacklist; p; p=p->next) + sock_list_logentry(VERB_ALGO, "blacklist", p); + if(!origin) + verbose(VERB_ALGO, "blacklist add: cache"); + for(p=origin; p; p=p->next) + sock_list_logentry(VERB_ALGO, "blacklist add", p); + } + /* blacklist the IPs or the cache */ + if(!origin) { + /* only add if nothing there. anything else also stops cache*/ + if(!*blacklist) + sock_list_insert(blacklist, NULL, 0, region); + } else if(!cross) + sock_list_prepend(blacklist, origin); + else sock_list_merge(blacklist, region, origin); +} + +int val_has_signed_nsecs(struct reply_info* rep, char** reason) +{ + size_t i, num_nsec = 0, num_nsec3 = 0; + struct packed_rrset_data* d; + for(i=rep->an_numrrsets; ian_numrrsets+rep->ns_numrrsets; i++) { + if(rep->rrsets[i]->rk.type == htons(LDNS_RR_TYPE_NSEC)) + num_nsec++; + else if(rep->rrsets[i]->rk.type == htons(LDNS_RR_TYPE_NSEC3)) + num_nsec3++; + else continue; + d = (struct packed_rrset_data*)rep->rrsets[i]->entry.data; + if(d && d->rrsig_count != 0) { + return 1; + } + } + if(num_nsec == 0 && num_nsec3 == 0) + *reason = "no DNSSEC records"; + else if(num_nsec != 0) + *reason = "no signatures over NSECs"; + else *reason = "no signatures over NSEC3s"; + return 0; +} + +struct dns_msg* +val_find_DS(struct module_env* env, uint8_t* nm, size_t nmlen, uint16_t c, + struct regional* region, uint8_t* topname) +{ + struct dns_msg* msg; + struct query_info qinfo; + struct ub_packed_rrset_key *rrset = rrset_cache_lookup( + env->rrset_cache, nm, nmlen, LDNS_RR_TYPE_DS, c, 0, + *env->now, 0); + if(rrset) { + /* DS rrset exists. Return it to the validator immediately*/ + struct ub_packed_rrset_key* copy = packed_rrset_copy_region( + rrset, region, *env->now); + lock_rw_unlock(&rrset->entry.lock); + if(!copy) + return NULL; + msg = dns_msg_create(nm, nmlen, LDNS_RR_TYPE_DS, c, region, 1); + if(!msg) + return NULL; + msg->rep->rrsets[0] = copy; + msg->rep->rrset_count++; + msg->rep->an_numrrsets++; + return msg; + } + /* lookup in rrset and negative cache for NSEC/NSEC3 */ + qinfo.qname = nm; + qinfo.qname_len = nmlen; + qinfo.qtype = LDNS_RR_TYPE_DS; + qinfo.qclass = c; + /* do not add SOA to reply message, it is going to be used internal */ + msg = val_neg_getmsg(env->neg_cache, &qinfo, region, env->rrset_cache, + env->scratch_buffer, *env->now, 0, topname); + return msg; +} diff --git a/validator/val_utils.h b/validator/val_utils.h new file mode 100644 index 00000000000..f0afc3756e9 --- /dev/null +++ b/validator/val_utils.h @@ -0,0 +1,403 @@ +/* + * validator/val_utils.h - validator utility 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains helper functions for the validator module. + */ + +#ifndef VALIDATOR_VAL_UTILS_H +#define VALIDATOR_VAL_UTILS_H +#include "util/data/packed_rrset.h" +struct query_info; +struct reply_info; +struct val_env; +struct module_env; +struct ub_packed_rrset_key; +struct key_entry_key; +struct regional; +struct val_anchors; +struct rrset_cache; +struct sock_list; + +/** + * Response classifications for the validator. The different types of proofs. + */ +enum val_classification { + /** Not subtyped yet. */ + VAL_CLASS_UNTYPED = 0, + /** Not a recognized subtype. */ + VAL_CLASS_UNKNOWN, + /** A positive, direct, response */ + VAL_CLASS_POSITIVE, + /** A positive response, with a CNAME/DNAME chain. */ + VAL_CLASS_CNAME, + /** A NOERROR/NODATA response. */ + VAL_CLASS_NODATA, + /** A NXDOMAIN response. */ + VAL_CLASS_NAMEERROR, + /** A CNAME/DNAME chain, and the offset is at the end of it, + * but there is no answer here, it can be NAMERROR or NODATA. */ + VAL_CLASS_CNAMENOANSWER, + /** A referral, from cache with a nonRD query. */ + VAL_CLASS_REFERRAL, + /** A response to a qtype=ANY query. */ + VAL_CLASS_ANY +}; + +/** + * Given a response, classify ANSWER responses into a subtype. + * @param query_flags: query flags for the original query. + * @param origqinf: query info. The original query name. + * @param qinf: query info. The chased query name. + * @param rep: response. The original response. + * @param skip: offset into the original response answer section. + * @return A subtype, all values possible except UNTYPED . + * Once CNAME type is returned you can increase skip. + * Then, another CNAME type, CNAME_NOANSWER or POSITIVE are possible. + */ +enum val_classification val_classify_response(uint16_t query_flags, + struct query_info* origqinf, struct query_info* qinf, + struct reply_info* rep, size_t skip); + +/** + * Given a response, determine the name of the "signer". This is primarily + * to determine if the response is, in fact, signed at all, and, if so, what + * is the name of the most pertinent keyset. + * + * @param subtype: the type from classify. + * @param qinf: query, the chased query name. + * @param rep: response to that, original response. + * @param cname_skip: how many answer rrsets have been skipped due to CNAME + * chains being chased around. + * @param signer_name: signer name, if the response is signed + * (even partially), or null if the response isn't signed. + * @param signer_len: length of signer_name of 0 if signer_name is NULL. + */ +void val_find_signer(enum val_classification subtype, + struct query_info* qinf, struct reply_info* rep, + size_t cname_skip, uint8_t** signer_name, size_t* signer_len); + +/** + * Verify RRset with keys + * @param env: module environment (scratch buffer) + * @param ve: validator environment (verification settings) + * @param rrset: what to verify + * @param keys: dnskey rrset to verify with. + * @param sigalg: if nonNULL provide downgrade protection otherwise one + * algorithm is enough. Algo list is constructed in here. + * @param reason: reason of failure. Fixed string or alloced in scratch. + * @return security status of verification. + */ +enum sec_status val_verify_rrset(struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* keys, + uint8_t* sigalg, char** reason); + +/** + * Verify RRset with keys from a keyset. + * @param env: module environment (scratch buffer) + * @param ve: validator environment (verification settings) + * @param rrset: what to verify + * @param kkey: key_entry to verify with. + * @param reason: reason of failure. Fixed string or alloced in scratch. + * @return security status of verification. + */ +enum sec_status val_verify_rrset_entry(struct module_env* env, + struct val_env* ve, struct ub_packed_rrset_key* rrset, + struct key_entry_key* kkey, char** reason); + +/** + * Verify DNSKEYs with DS rrset. Like val_verify_new_DNSKEYs but + * returns a sec_status instead of a key_entry. + * @param env: module environment (scratch buffer) + * @param ve: validator environment (verification settings) + * @param dnskey_rrset: DNSKEY rrset to verify + * @param ds_rrset: DS rrset to verify with. + * @param sigalg: if nonNULL provide downgrade protection otherwise one + * algorithm is enough. The list of signalled algorithms is returned, + * must have enough space for ALGO_NEEDS_MAX+1. + * @param reason: reason of failure. Fixed string or alloced in scratch. + * @return: sec_status_secure if a DS matches. + * sec_status_insecure if end of trust (i.e., unknown algorithms). + * sec_status_bogus if it fails. + */ +enum sec_status val_verify_DNSKEY_with_DS(struct module_env* env, + struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset, + struct ub_packed_rrset_key* ds_rrset, uint8_t* sigalg, char** reason); + +/** + * Verify DNSKEYs with DS and DNSKEY rrset. Like val_verify_DNSKEY_with_DS + * but for a trust anchor. + * @param env: module environment (scratch buffer) + * @param ve: validator environment (verification settings) + * @param dnskey_rrset: DNSKEY rrset to verify + * @param ta_ds: DS rrset to verify with. + * @param ta_dnskey: DNSKEY rrset to verify with. + * @param sigalg: if nonNULL provide downgrade protection otherwise one + * algorithm is enough. The list of signalled algorithms is returned, + * must have enough space for ALGO_NEEDS_MAX+1. + * @param reason: reason of failure. Fixed string or alloced in scratch. + * @return: sec_status_secure if a DS matches. + * sec_status_insecure if end of trust (i.e., unknown algorithms). + * sec_status_bogus if it fails. + */ +enum sec_status val_verify_DNSKEY_with_TA(struct module_env* env, + struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset, + struct ub_packed_rrset_key* ta_ds, + struct ub_packed_rrset_key* ta_dnskey, uint8_t* sigalg, char** reason); + +/** + * Verify new DNSKEYs with DS rrset. The DS contains hash values that should + * match the DNSKEY keys. + * match the DS to a DNSKEY and verify the DNSKEY rrset with that key. + * + * @param region: where to allocate key entry result. + * @param env: module environment (scratch buffer) + * @param ve: validator environment (verification settings) + * @param dnskey_rrset: DNSKEY rrset to verify + * @param ds_rrset: DS rrset to verify with. + * @param downprot: if true provide downgrade protection otherwise one + * algorithm is enough. + * @param reason: reason of failure. Fixed string or alloced in scratch. + * @return a KeyEntry. This will either contain the now trusted + * dnskey_rrset, a "null" key entry indicating that this DS + * rrset/DNSKEY pair indicate an secure end to the island of trust + * (i.e., unknown algorithms), or a "bad" KeyEntry if the dnskey + * rrset fails to verify. Note that the "null" response should + * generally only occur in a private algorithm scenario: normally + * this sort of thing is checked before fetching the matching DNSKEY + * rrset. + * if downprot is set, a key entry with an algo list is made. + */ +struct key_entry_key* val_verify_new_DNSKEYs(struct regional* region, + struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key* dnskey_rrset, + struct ub_packed_rrset_key* ds_rrset, int downprot, char** reason); + + +/** + * Verify rrset with trust anchor: DS and DNSKEY rrset. + * + * @param region: where to allocate key entry result. + * @param env: module environment (scratch buffer) + * @param ve: validator environment (verification settings) + * @param dnskey_rrset: DNSKEY rrset to verify + * @param ta_ds_rrset: DS rrset to verify with. + * @param ta_dnskey_rrset: the DNSKEY rrset to verify with. + * @param downprot: if true provide downgrade protection otherwise one + * algorithm is enough. + * @param reason: reason of failure. Fixed string or alloced in scratch. + * @return a KeyEntry. This will either contain the now trusted + * dnskey_rrset, a "null" key entry indicating that this DS + * rrset/DNSKEY pair indicate an secure end to the island of trust + * (i.e., unknown algorithms), or a "bad" KeyEntry if the dnskey + * rrset fails to verify. Note that the "null" response should + * generally only occur in a private algorithm scenario: normally + * this sort of thing is checked before fetching the matching DNSKEY + * rrset. + * if downprot is set, a key entry with an algo list is made. + */ +struct key_entry_key* val_verify_new_DNSKEYs_with_ta(struct regional* region, + struct module_env* env, struct val_env* ve, + struct ub_packed_rrset_key* dnskey_rrset, + struct ub_packed_rrset_key* ta_ds_rrset, + struct ub_packed_rrset_key* ta_dnskey_rrset, + int downprot, char** reason); + +/** + * Determine if DS rrset is usable for validator or not. + * Returns true if the algorithms for key and DShash are supported, + * for at least one RR. + * + * @param ds_rrset: the newly received DS rrset. + * @return true or false if not usable. + */ +int val_dsset_isusable(struct ub_packed_rrset_key* ds_rrset); + +/** + * Determine by looking at a signed RRset whether or not the RRset name was + * the result of a wildcard expansion. If so, return the name of the + * generating wildcard. + * + * @param rrset The rrset to chedck. + * @param wc: the wildcard name, if the rrset was synthesized from a wildcard. + * unchanged if not. The wildcard name, without "*." in front, is + * returned. This is a pointer into the rrset owner name. + * @return false if the signatures are inconsistent in indicating the + * wildcard status; possible spoofing of wildcard response for other + * responses is being tried. We lost the status which rrsig was verified + * after the verification routine finished, so we simply check if + * the signatures are consistent; inserting a fake signature is a denial + * of service; but in that you could also have removed the real + * signature anyway. + */ +int val_rrset_wildcard(struct ub_packed_rrset_key* rrset, uint8_t** wc); + +/** + * Chase the cname to the next query name. + * @param qchase: the current query name, updated to next target. + * @param rep: original message reply to look at CNAMEs. + * @param cname_skip: the skip into the answer section. Updated to skip + * DNAME and CNAME to the next part of the answer. + * @return false on error (bad rdata). + */ +int val_chase_cname(struct query_info* qchase, struct reply_info* rep, + size_t* cname_skip); + +/** + * Fill up the chased reply with the content from the original reply; + * as pointers to those rrsets. Select the part after the cname_skip into + * the answer section, NS and AR sections that are signed with same signer. + * + * @param chase: chased reply, filled up. + * @param orig: original reply. + * @param cname_skip: which part of the answer section to skip. + * The skipped part contains CNAME(and DNAME)s that have been chased. + * @param name: the signer name to look for. + * @param len: length of name. + * @param signer: signer name or NULL if an unsigned RRset is considered. + * If NULL, rrsets with the lookup name are copied over. + */ +void val_fill_reply(struct reply_info* chase, struct reply_info* orig, + size_t cname_skip, uint8_t* name, size_t len, uint8_t* signer); + +/** + * Remove all unsigned or non-secure status rrsets from NS and AR sections. + * So that unsigned data does not get let through to clients, when we have + * found the data to be secure. + * + * @param ve: validator environment with cleaning options. + * @param rep: reply to dump all nonsecure stuff out of. + */ +void val_check_nonsecure(struct val_env* ve, struct reply_info* rep); + +/** + * Mark all unchecked rrset entries not below a trust anchor as indeterminate. + * Only security==unchecked rrsets are updated. + * @param rep: the reply with rrsets. + * @param anchors: the trust anchors. + * @param r: rrset cache to store updated security status into. + * @param env: module environment + */ +void val_mark_indeterminate(struct reply_info* rep, + struct val_anchors* anchors, struct rrset_cache* r, + struct module_env* env); + +/** + * Mark all unchecked rrset entries below a NULL key entry as insecure. + * Only security==unchecked rrsets are updated. + * @param rep: the reply with rrsets. + * @param kname: end of secure space name. + * @param r: rrset cache to store updated security status into. + * @param env: module environment + */ +void val_mark_insecure(struct reply_info* rep, uint8_t* kname, + struct rrset_cache* r, struct module_env* env); + +/** + * Find next unchecked rrset position, return it for skip. + * @param rep: the original reply to look into. + * @param skip: the skip now. + * @return new skip, which may be at the rep->rrset_count position to signal + * there are no unchecked items. + */ +size_t val_next_unchecked(struct reply_info* rep, size_t skip); + +/** + * Find the signer name for an RRset. + * @param rrset: the rrset. + * @param sname: signer name is returned or NULL if not signed. + * @param slen: length of sname (or 0). + */ +void val_find_rrset_signer(struct ub_packed_rrset_key* rrset, uint8_t** sname, + size_t* slen); + +/** + * Get string to denote the classification result. + * @param subtype: from classification function. + * @return static string to describe the classification. + */ +const char* val_classification_to_string(enum val_classification subtype); + +/** + * Add existing list to blacklist. + * @param blacklist: the blacklist with result + * @param region: the region where blacklist is allocated. + * Allocation failures are logged. + * @param origin: origin list to add, if NULL, a cache-entry is added to + * the blacklist to stop cache from being used. + * @param cross: if true this is a cross-qstate copy, and the 'origin' + * list is not allocated in the same region as the blacklist. + */ +void val_blacklist(struct sock_list** blacklist, struct regional* region, + struct sock_list* origin, int cross); + +/** + * check if has dnssec info, and if it has signed nsecs. gives error reason. + * @param rep: reply to check. + * @param reason: returned on fail. + * @return false if message has no signed nsecs. Can not prove negatives. + */ +int val_has_signed_nsecs(struct reply_info* rep, char** reason); + +/** + * Return algo number for favorite (best) algorithm that we support in DS. + * @param ds_rrset: the DSes in this rrset are inspected and best algo chosen. + * @return algo number or 0 if none supported. 0 is unused as algo number. + */ +int val_favorite_ds_algo(struct ub_packed_rrset_key* ds_rrset); + +/** + * Find DS denial message in cache. Saves new qstate allocation and allows + * the validator to use partial content which is not enough to construct a + * message for network (or user) consumption. Without SOA for example, + * which is a common occurence in the unbound code since the referrals contain + * NSEC/NSEC3 rrs without the SOA element, thus do not allow synthesis of a + * full negative reply, but do allow synthesis of sufficient proof. + * @param env: query env with caches and time. + * @param nm: name of DS record sought. + * @param nmlen: length of name. + * @param c: class of DS RR. + * @param region: where to allocate result. + * @param topname: name of the key that is currently in use, that will get + * used to validate the result, and thus no higher entries from the + * negative cache need to be examined. + * @return a dns_msg on success. NULL on failure. + */ +struct dns_msg* val_find_DS(struct module_env* env, uint8_t* nm, size_t nmlen, + uint16_t c, struct regional* region, uint8_t* topname); + +#endif /* VALIDATOR_VAL_UTILS_H */ diff --git a/validator/validator.c b/validator/validator.c new file mode 100644 index 00000000000..af1d344a691 --- /dev/null +++ b/validator/validator.c @@ -0,0 +1,2958 @@ +/* + * validator/validator.c - secure validator DNS query response module + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains a module that performs validation of DNS queries. + * According to RFC 4034. + */ +#include "config.h" +#include +#include "validator/validator.h" +#include "validator/val_anchor.h" +#include "validator/val_kcache.h" +#include "validator/val_kentry.h" +#include "validator/val_utils.h" +#include "validator/val_nsec.h" +#include "validator/val_nsec3.h" +#include "validator/val_neg.h" +#include "validator/val_sigcrypt.h" +#include "validator/autotrust.h" +#include "services/cache/dns.h" +#include "util/data/dname.h" +#include "util/module.h" +#include "util/log.h" +#include "util/net_help.h" +#include "util/regional.h" +#include "util/config_file.h" +#include "util/fptr_wlist.h" + +/* forward decl for cache response and normal super inform calls of a DS */ +static void process_ds_response(struct module_qstate* qstate, + struct val_qstate* vq, int id, int rcode, struct dns_msg* msg, + struct query_info* qinfo, struct sock_list* origin); + +/** fill up nsec3 key iterations config entry */ +static int +fill_nsec3_iter(struct val_env* ve, char* s, int c) +{ + char* e; + int i; + free(ve->nsec3_keysize); + free(ve->nsec3_maxiter); + ve->nsec3_keysize = (size_t*)calloc(sizeof(size_t), (size_t)c); + ve->nsec3_maxiter = (size_t*)calloc(sizeof(size_t), (size_t)c); + if(!ve->nsec3_keysize || !ve->nsec3_maxiter) { + log_err("out of memory"); + return 0; + } + for(i=0; insec3_keysize[i] = (size_t)strtol(s, &e, 10); + if(s == e) { + log_err("cannot parse: %s", s); + return 0; + } + s = e; + ve->nsec3_maxiter[i] = (size_t)strtol(s, &e, 10); + if(s == e) { + log_err("cannot parse: %s", s); + return 0; + } + s = e; + if(i>0 && ve->nsec3_keysize[i-1] >= ve->nsec3_keysize[i]) { + log_err("nsec3 key iterations not ascending: %d %d", + (int)ve->nsec3_keysize[i-1], + (int)ve->nsec3_keysize[i]); + return 0; + } + verbose(VERB_ALGO, "validator nsec3cfg keysz %d mxiter %d", + (int)ve->nsec3_keysize[i], (int)ve->nsec3_maxiter[i]); + } + return 1; +} + +/** apply config settings to validator */ +static int +val_apply_cfg(struct module_env* env, struct val_env* val_env, + struct config_file* cfg) +{ + int c; + val_env->bogus_ttl = (uint32_t)cfg->bogus_ttl; + val_env->clean_additional = cfg->val_clean_additional; + val_env->permissive_mode = cfg->val_permissive_mode; + if(!env->anchors) + env->anchors = anchors_create(); + if(!env->anchors) { + log_err("out of memory"); + return 0; + } + if(!val_env->kcache) + val_env->kcache = key_cache_create(cfg); + if(!val_env->kcache) { + log_err("out of memory"); + return 0; + } + env->key_cache = val_env->kcache; + if(!anchors_apply_cfg(env->anchors, cfg)) { + log_err("validator: error in trustanchors config"); + return 0; + } + val_env->date_override = cfg->val_date_override; + val_env->skew_min = cfg->val_sig_skew_min; + val_env->skew_max = cfg->val_sig_skew_max; + c = cfg_count_numbers(cfg->val_nsec3_key_iterations); + if(c < 1 || (c&1)) { + log_err("validator: unparseable or odd nsec3 key " + "iterations: %s", cfg->val_nsec3_key_iterations); + return 0; + } + val_env->nsec3_keyiter_count = c/2; + if(!fill_nsec3_iter(val_env, cfg->val_nsec3_key_iterations, c/2)) { + log_err("validator: cannot apply nsec3 key iterations"); + return 0; + } + if(!val_env->neg_cache) + val_env->neg_cache = val_neg_create(cfg, + val_env->nsec3_maxiter[val_env->nsec3_keyiter_count-1]); + if(!val_env->neg_cache) { + log_err("out of memory"); + return 0; + } + env->neg_cache = val_env->neg_cache; + return 1; +} + +int +val_init(struct module_env* env, int id) +{ + struct val_env* val_env = (struct val_env*)calloc(1, + sizeof(struct val_env)); + if(!val_env) { + log_err("malloc failure"); + return 0; + } + env->modinfo[id] = (void*)val_env; + env->need_to_validate = 1; + val_env->permissive_mode = 0; + lock_basic_init(&val_env->bogus_lock); + lock_protect(&val_env->bogus_lock, &val_env->num_rrset_bogus, + sizeof(val_env->num_rrset_bogus)); + if(!val_apply_cfg(env, val_env, env->cfg)) { + log_err("validator: could not apply configuration settings."); + return 0; + } + return 1; +} + +void +val_deinit(struct module_env* env, int id) +{ + struct val_env* val_env; + if(!env || !env->modinfo[id]) + return; + val_env = (struct val_env*)env->modinfo[id]; + lock_basic_destroy(&val_env->bogus_lock); + anchors_delete(env->anchors); + env->anchors = NULL; + key_cache_delete(val_env->kcache); + neg_cache_delete(val_env->neg_cache); + free(val_env->nsec3_keysize); + free(val_env->nsec3_maxiter); + free(val_env); + env->modinfo[id] = NULL; +} + +/** fill in message structure */ +static struct val_qstate* +val_new_getmsg(struct module_qstate* qstate, struct val_qstate* vq) +{ + if(!qstate->return_msg || qstate->return_rcode != LDNS_RCODE_NOERROR) { + /* create a message to verify */ + verbose(VERB_ALGO, "constructing reply for validation"); + vq->orig_msg = (struct dns_msg*)regional_alloc(qstate->region, + sizeof(struct dns_msg)); + if(!vq->orig_msg) + return NULL; + vq->orig_msg->qinfo = qstate->qinfo; + vq->orig_msg->rep = (struct reply_info*)regional_alloc( + qstate->region, sizeof(struct reply_info)); + if(!vq->orig_msg->rep) + return NULL; + memset(vq->orig_msg->rep, 0, sizeof(struct reply_info)); + vq->orig_msg->rep->flags = (uint16_t)(qstate->return_rcode&0xf) + |BIT_QR|BIT_RA|(qstate->query_flags|(BIT_CD|BIT_RD)); + vq->orig_msg->rep->qdcount = 1; + } else { + vq->orig_msg = qstate->return_msg; + } + vq->qchase = qstate->qinfo; + /* chase reply will be an edited (sub)set of the orig msg rrset ptrs */ + vq->chase_reply = regional_alloc_init(qstate->region, + vq->orig_msg->rep, + sizeof(struct reply_info) - sizeof(struct rrset_ref)); + if(!vq->chase_reply) + return NULL; + vq->chase_reply->rrsets = regional_alloc_init(qstate->region, + vq->orig_msg->rep->rrsets, sizeof(struct ub_packed_rrset_key*) + * vq->orig_msg->rep->rrset_count); + if(!vq->chase_reply->rrsets) + return NULL; + vq->rrset_skip = 0; + return vq; +} + +/** allocate new validator query state */ +static struct val_qstate* +val_new(struct module_qstate* qstate, int id) +{ + struct val_qstate* vq = (struct val_qstate*)regional_alloc( + qstate->region, sizeof(*vq)); + log_assert(!qstate->minfo[id]); + if(!vq) + return NULL; + memset(vq, 0, sizeof(*vq)); + qstate->minfo[id] = vq; + vq->state = VAL_INIT_STATE; + return val_new_getmsg(qstate, vq); +} + +/** + * Exit validation with an error status + * + * @param qstate: query state + * @param id: validator id. + * @return false, for use by caller to return to stop processing. + */ +static int +val_error(struct module_qstate* qstate, int id) +{ + qstate->ext_state[id] = module_error; + qstate->return_rcode = LDNS_RCODE_SERVFAIL; + return 0; +} + +/** + * Check to see if a given response needs to go through the validation + * process. Typical reasons for this routine to return false are: CD bit was + * on in the original request, or the response is a kind of message that + * is unvalidatable (i.e., SERVFAIL, REFUSED, etc.) + * + * @param qstate: query state. + * @param ret_rc: rcode for this message (if noerror - examine ret_msg). + * @param ret_msg: return msg, can be NULL; look at rcode instead. + * @return true if the response could use validation (although this does not + * mean we can actually validate this response). + */ +static int +needs_validation(struct module_qstate* qstate, int ret_rc, + struct dns_msg* ret_msg) +{ + int rcode; + + /* If the CD bit is on in the original request, then we don't bother to + * validate anything.*/ + if(qstate->query_flags & BIT_CD) { + verbose(VERB_ALGO, "not validating response due to CD bit"); + return 0; + } + + if(ret_rc != LDNS_RCODE_NOERROR || !ret_msg) + rcode = ret_rc; + else rcode = (int)FLAGS_GET_RCODE(ret_msg->rep->flags); + + if(rcode != LDNS_RCODE_NOERROR && rcode != LDNS_RCODE_NXDOMAIN) { + verbose(VERB_ALGO, "cannot validate non-answer, rcode %s", + ldns_lookup_by_id(ldns_rcodes, rcode)? + ldns_lookup_by_id(ldns_rcodes, rcode)->name:"??"); + return 0; + } + + /* cannot validate positive RRSIG response. (negatives can) */ + if(qstate->qinfo.qtype == LDNS_RR_TYPE_RRSIG && + rcode == LDNS_RCODE_NOERROR && ret_msg && + ret_msg->rep->an_numrrsets > 0) { + verbose(VERB_ALGO, "cannot validate RRSIG, no sigs on sigs."); + return 0; + } + return 1; +} + +/** + * Check to see if the response has already been validated. + * @param ret_msg: return msg, can be NULL + * @return true if the response has already been validated + */ +static int +already_validated(struct dns_msg* ret_msg) +{ + /* validate unchecked, and re-validate bogus messages */ + if (ret_msg && ret_msg->rep->security > sec_status_bogus) + { + verbose(VERB_ALGO, "response has already been validated: %s", + sec_status_to_string(ret_msg->rep->security)); + return 1; + } + return 0; +} + +/** + * Generate a request for DNS data. + * + * @param qstate: query state that is the parent. + * @param id: module id. + * @param name: what name to query for. + * @param namelen: length of name. + * @param qtype: query type. + * @param qclass: query class. + * @param flags: additional flags, such as the CD bit (BIT_CD), or 0. + * @return false on alloc failure. + */ +static int +generate_request(struct module_qstate* qstate, int id, uint8_t* name, + size_t namelen, uint16_t qtype, uint16_t qclass, uint16_t flags) +{ + struct val_qstate* vq = (struct val_qstate*)qstate->minfo[id]; + struct module_qstate* newq; + struct query_info ask; + ask.qname = name; + ask.qname_len = namelen; + ask.qtype = qtype; + ask.qclass = qclass; + log_query_info(VERB_ALGO, "generate request", &ask); + fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub)); + if(!(*qstate->env->attach_sub)(qstate, &ask, + (uint16_t)(BIT_RD|flags), 0, &newq)){ + log_err("Could not generate request: out of memory"); + return 0; + } + /* newq; validator does not need state created for that + * query, and its a 'normal' for iterator as well */ + if(newq) { + /* add our blacklist to the query blacklist */ + sock_list_merge(&newq->blacklist, newq->region, + vq->chain_blacklist); + } + qstate->ext_state[id] = module_wait_subquery; + return 1; +} + +/** + * Prime trust anchor for use. + * Generate and dispatch a priming query for the given trust anchor. + * The trust anchor can be DNSKEY or DS and does not have to be signed. + * + * @param qstate: query state. + * @param vq: validator query state. + * @param id: module id. + * @param toprime: what to prime. + * @return false on a processing error. + */ +static int +prime_trust_anchor(struct module_qstate* qstate, struct val_qstate* vq, + int id, struct trust_anchor* toprime) +{ + int ret = generate_request(qstate, id, toprime->name, toprime->namelen, + LDNS_RR_TYPE_DNSKEY, toprime->dclass, BIT_CD); + if(!ret) { + log_err("Could not prime trust anchor: out of memory"); + return 0; + } + /* ignore newq; validator does not need state created for that + * query, and its a 'normal' for iterator as well */ + vq->wait_prime_ta = 1; /* to elicit PRIME_RESP_STATE processing + from the validator inform_super() routine */ + /* store trust anchor name for later lookup when prime returns */ + vq->trust_anchor_name = regional_alloc_init(qstate->region, + toprime->name, toprime->namelen); + vq->trust_anchor_len = toprime->namelen; + vq->trust_anchor_labs = toprime->namelabs; + if(!vq->trust_anchor_name) { + log_err("Could not prime trust anchor: out of memory"); + return 0; + } + return 1; +} + +/** + * Validate if the ANSWER and AUTHORITY sections contain valid rrsets. + * They must be validly signed with the given key. + * Tries to validate ADDITIONAL rrsets as well, but only to check them. + * Allows unsigned CNAME after a DNAME that expands the DNAME. + * + * Note that by the time this method is called, the process of finding the + * trusted DNSKEY rrset that signs this response must already have been + * completed. + * + * @param qstate: query state. + * @param env: module env for verify. + * @param ve: validator env for verify. + * @param qchase: query that was made. + * @param chase_reply: answer to validate. + * @param key_entry: the key entry, which is trusted, and which matches + * the signer of the answer. The key entry isgood(). + * @return false if any of the rrsets in the an or ns sections of the message + * fail to verify. The message is then set to bogus. + */ +static int +validate_msg_signatures(struct module_qstate* qstate, struct module_env* env, + struct val_env* ve, struct query_info* qchase, + struct reply_info* chase_reply, struct key_entry_key* key_entry) +{ + uint8_t* sname; + size_t i, slen; + struct ub_packed_rrset_key* s; + enum sec_status sec; + int dname_seen = 0; + char* reason = NULL; + + /* validate the ANSWER section */ + for(i=0; ian_numrrsets; i++) { + s = chase_reply->rrsets[i]; + /* Skip the CNAME following a (validated) DNAME. + * Because of the normalization routines in the iterator, + * there will always be an unsigned CNAME following a DNAME + * (unless qtype=DNAME). */ + if(dname_seen && ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME) { + dname_seen = 0; + /* CNAME was synthesized by our own iterator */ + /* since the DNAME verified, mark the CNAME as secure */ + ((struct packed_rrset_data*)s->entry.data)->security = + sec_status_secure; + ((struct packed_rrset_data*)s->entry.data)->trust = + rrset_trust_validated; + continue; + } + + /* Verify the answer rrset */ + sec = val_verify_rrset_entry(env, ve, s, key_entry, &reason); + /* If the (answer) rrset failed to validate, then this + * message is BAD. */ + if(sec != sec_status_secure) { + log_nametypeclass(VERB_QUERY, "validator: response " + "has failed ANSWER rrset:", s->rk.dname, + ntohs(s->rk.type), ntohs(s->rk.rrset_class)); + errinf(qstate, reason); + if(ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME) + errinf(qstate, "for CNAME"); + else if(ntohs(s->rk.type) == LDNS_RR_TYPE_DNAME) + errinf(qstate, "for DNAME"); + errinf_origin(qstate, qstate->reply_origin); + chase_reply->security = sec_status_bogus; + return 0; + } + + /* Notice a DNAME that should be followed by an unsigned + * CNAME. */ + if(qchase->qtype != LDNS_RR_TYPE_DNAME && + ntohs(s->rk.type) == LDNS_RR_TYPE_DNAME) { + dname_seen = 1; + } + } + + /* validate the AUTHORITY section */ + for(i=chase_reply->an_numrrsets; ian_numrrsets+ + chase_reply->ns_numrrsets; i++) { + s = chase_reply->rrsets[i]; + sec = val_verify_rrset_entry(env, ve, s, key_entry, &reason); + /* If anything in the authority section fails to be secure, + * we have a bad message. */ + if(sec != sec_status_secure) { + log_nametypeclass(VERB_QUERY, "validator: response " + "has failed AUTHORITY rrset:", s->rk.dname, + ntohs(s->rk.type), ntohs(s->rk.rrset_class)); + errinf(qstate, reason); + errinf_rrset(qstate, s); + errinf_origin(qstate, qstate->reply_origin); + chase_reply->security = sec_status_bogus; + return 0; + } + } + + /* attempt to validate the ADDITIONAL section rrsets */ + if(!ve->clean_additional) + return 1; + for(i=chase_reply->an_numrrsets+chase_reply->ns_numrrsets; + irrset_count; i++) { + s = chase_reply->rrsets[i]; + /* only validate rrs that have signatures with the key */ + /* leave others unchecked, those get removed later on too */ + val_find_rrset_signer(s, &sname, &slen); + if(sname && query_dname_compare(sname, key_entry->name)==0) + (void)val_verify_rrset_entry(env, ve, s, key_entry, + &reason); + /* the additional section can fail to be secure, + * it is optional, check signature in case we need + * to clean the additional section later. */ + } + + return 1; +} + +/** + * Detect wrong truncated response (say from BIND 9.6.1 that is forwarding + * and saw the NS record without signatures from a referral). + * The positive response has a mangled authority section. + * Remove that authority section and the additional section. + * @param rep: reply + * @return true if a wrongly truncated response. + */ +static int +detect_wrongly_truncated(struct reply_info* rep) +{ + size_t i; + /* only NS in authority, and it is bogus */ + if(rep->ns_numrrsets != 1 || rep->an_numrrsets == 0) + return 0; + if(ntohs(rep->rrsets[ rep->an_numrrsets ]->rk.type) != LDNS_RR_TYPE_NS) + return 0; + if(((struct packed_rrset_data*)rep->rrsets[ rep->an_numrrsets ] + ->entry.data)->security == sec_status_secure) + return 0; + /* answer section is present and secure */ + for(i=0; ian_numrrsets; i++) { + if(((struct packed_rrset_data*)rep->rrsets[ i ] + ->entry.data)->security != sec_status_secure) + return 0; + } + verbose(VERB_ALGO, "truncating to minimal response"); + return 1; +} + + +/** + * Given a "positive" response -- a response that contains an answer to the + * question, and no CNAME chain, validate this response. + * + * The answer and authority RRsets must already be verified as secure. + * + * @param env: module env for verify. + * @param ve: validator env for verify. + * @param qchase: query that was made. + * @param chase_reply: answer to that query to validate. + * @param kkey: the key entry, which is trusted, and which matches + * the signer of the answer. The key entry isgood(). + */ +static void +validate_positive_response(struct module_env* env, struct val_env* ve, + struct query_info* qchase, struct reply_info* chase_reply, + struct key_entry_key* kkey) +{ + uint8_t* wc = NULL; + int wc_NSEC_ok = 0; + int nsec3s_seen = 0; + size_t i; + struct ub_packed_rrset_key* s; + + /* validate the ANSWER section - this will be the answer itself */ + for(i=0; ian_numrrsets; i++) { + s = chase_reply->rrsets[i]; + + /* Check to see if the rrset is the result of a wildcard + * expansion. If so, an additional check will need to be + * made in the authority section. */ + if(!val_rrset_wildcard(s, &wc)) { + log_nametypeclass(VERB_QUERY, "Positive response has " + "inconsistent wildcard sigs:", s->rk.dname, + ntohs(s->rk.type), ntohs(s->rk.rrset_class)); + chase_reply->security = sec_status_bogus; + return; + } + } + + /* validate the AUTHORITY section as well - this will generally be + * the NS rrset (which could be missing, no problem) */ + for(i=chase_reply->an_numrrsets; ian_numrrsets+ + chase_reply->ns_numrrsets; i++) { + s = chase_reply->rrsets[i]; + + /* If this is a positive wildcard response, and we have a + * (just verified) NSEC record, try to use it to 1) prove + * that qname doesn't exist and 2) that the correct wildcard + * was used. */ + if(wc != NULL && ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC) { + if(val_nsec_proves_positive_wildcard(s, qchase, wc)) { + wc_NSEC_ok = 1; + } + /* if not, continue looking for proof */ + } + + /* Otherwise, if this is a positive wildcard response and + * we have NSEC3 records */ + if(wc != NULL && ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC3) { + nsec3s_seen = 1; + } + } + + /* If this was a positive wildcard response that we haven't already + * proven, and we have NSEC3 records, try to prove it using the NSEC3 + * records. */ + if(wc != NULL && !wc_NSEC_ok && nsec3s_seen) { + enum sec_status sec = nsec3_prove_wildcard(env, ve, + chase_reply->rrsets+chase_reply->an_numrrsets, + chase_reply->ns_numrrsets, qchase, kkey, wc); + if(sec == sec_status_insecure) { + verbose(VERB_ALGO, "Positive wildcard response is " + "insecure"); + chase_reply->security = sec_status_insecure; + return; + } else if(sec == sec_status_secure) + wc_NSEC_ok = 1; + } + + /* If after all this, we still haven't proven the positive wildcard + * response, fail. */ + if(wc != NULL && !wc_NSEC_ok) { + verbose(VERB_QUERY, "positive response was wildcard " + "expansion and did not prove original data " + "did not exist"); + chase_reply->security = sec_status_bogus; + return; + } + + verbose(VERB_ALGO, "Successfully validated positive response"); + chase_reply->security = sec_status_secure; +} + +/** + * Validate a NOERROR/NODATA signed response -- a response that has a + * NOERROR Rcode but no ANSWER section RRsets. This consists of making + * certain that the authority section NSEC/NSEC3s proves that the qname + * does exist and the qtype doesn't. + * + * The answer and authority RRsets must already be verified as secure. + * + * @param env: module env for verify. + * @param ve: validator env for verify. + * @param qchase: query that was made. + * @param chase_reply: answer to that query to validate. + * @param kkey: the key entry, which is trusted, and which matches + * the signer of the answer. The key entry isgood(). + */ +static void +validate_nodata_response(struct module_env* env, struct val_env* ve, + struct query_info* qchase, struct reply_info* chase_reply, + struct key_entry_key* kkey) +{ + /* Since we are here, there must be nothing in the ANSWER section to + * validate. */ + /* (Note: CNAME/DNAME responses will not directly get here -- + * instead, they are chased down into indiviual CNAME validations, + * and at the end of the cname chain a POSITIVE, or CNAME_NOANSWER + * validation.) */ + + /* validate the AUTHORITY section */ + int has_valid_nsec = 0; /* If true, then the NODATA has been proven.*/ + uint8_t* ce = NULL; /* for wildcard nodata responses. This is the + proven closest encloser. */ + uint8_t* wc = NULL; /* for wildcard nodata responses. wildcard nsec */ + int nsec3s_seen = 0; /* nsec3s seen */ + struct ub_packed_rrset_key* s; + size_t i; + + for(i=chase_reply->an_numrrsets; ian_numrrsets+ + chase_reply->ns_numrrsets; i++) { + s = chase_reply->rrsets[i]; + /* If we encounter an NSEC record, try to use it to prove + * NODATA. + * This needs to handle the ENT NODATA case. */ + if(ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC) { + if(nsec_proves_nodata(s, qchase, &wc)) { + has_valid_nsec = 1; + /* sets wc-encloser if wildcard applicable */ + } + if(val_nsec_proves_name_error(s, qchase->qname)) { + ce = nsec_closest_encloser(qchase->qname, s); + } + if(val_nsec_proves_insecuredelegation(s, qchase)) { + verbose(VERB_ALGO, "delegation is insecure"); + chase_reply->security = sec_status_insecure; + return; + } + } else if(ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC3) { + nsec3s_seen = 1; + } + } + + /* check to see if we have a wildcard NODATA proof. */ + + /* The wildcard NODATA is 1 NSEC proving that qname does not exist + * (and also proving what the closest encloser is), and 1 NSEC + * showing the matching wildcard, which must be *.closest_encloser. */ + if(wc && !ce) + has_valid_nsec = 0; + else if(wc && ce) { + if(query_dname_compare(wc, ce) != 0) { + has_valid_nsec = 0; + } + } + + if(!has_valid_nsec && nsec3s_seen) { + enum sec_status sec = nsec3_prove_nodata(env, ve, + chase_reply->rrsets+chase_reply->an_numrrsets, + chase_reply->ns_numrrsets, qchase, kkey); + if(sec == sec_status_insecure) { + verbose(VERB_ALGO, "NODATA response is insecure"); + chase_reply->security = sec_status_insecure; + return; + } else if(sec == sec_status_secure) + has_valid_nsec = 1; + } + + if(!has_valid_nsec) { + verbose(VERB_QUERY, "NODATA response failed to prove NODATA " + "status with NSEC/NSEC3"); + if(verbosity >= VERB_ALGO) + log_dns_msg("Failed NODATA", qchase, chase_reply); + chase_reply->security = sec_status_bogus; + return; + } + + verbose(VERB_ALGO, "successfully validated NODATA response."); + chase_reply->security = sec_status_secure; +} + +/** + * Validate a NAMEERROR signed response -- a response that has a NXDOMAIN + * Rcode. + * This consists of making certain that the authority section NSEC proves + * that the qname doesn't exist and the covering wildcard also doesn't exist.. + * + * The answer and authority RRsets must have already been verified as secure. + * + * @param env: module env for verify. + * @param ve: validator env for verify. + * @param qchase: query that was made. + * @param chase_reply: answer to that query to validate. + * @param kkey: the key entry, which is trusted, and which matches + * the signer of the answer. The key entry isgood(). + */ +static void +validate_nameerror_response(struct module_env* env, struct val_env* ve, + struct query_info* qchase, struct reply_info* chase_reply, + struct key_entry_key* kkey) +{ + int has_valid_nsec = 0; + int has_valid_wnsec = 0; + int nsec3s_seen = 0; + struct ub_packed_rrset_key* s; + size_t i; + + for(i=chase_reply->an_numrrsets; ian_numrrsets+ + chase_reply->ns_numrrsets; i++) { + s = chase_reply->rrsets[i]; + if(ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC) { + if(val_nsec_proves_name_error(s, qchase->qname)) + has_valid_nsec = 1; + if(val_nsec_proves_no_wc(s, qchase->qname, + qchase->qname_len)) + has_valid_wnsec = 1; + if(val_nsec_proves_insecuredelegation(s, qchase)) { + verbose(VERB_ALGO, "delegation is insecure"); + chase_reply->security = sec_status_insecure; + return; + } + } else if(ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC3) + nsec3s_seen = 1; + } + + if((!has_valid_nsec || !has_valid_wnsec) && nsec3s_seen) { + /* use NSEC3 proof, both answer and auth rrsets, in case + * NSEC3s end up in the answer (due to qtype=NSEC3 or so) */ + chase_reply->security = nsec3_prove_nameerror(env, ve, + chase_reply->rrsets, chase_reply->an_numrrsets+ + chase_reply->ns_numrrsets, qchase, kkey); + if(chase_reply->security != sec_status_secure) { + verbose(VERB_QUERY, "NameError response failed nsec, " + "nsec3 proof was %s", sec_status_to_string( + chase_reply->security)); + return; + } + has_valid_nsec = 1; + has_valid_wnsec = 1; + } + + /* If the message fails to prove either condition, it is bogus. */ + if(!has_valid_nsec) { + verbose(VERB_QUERY, "NameError response has failed to prove: " + "qname does not exist"); + chase_reply->security = sec_status_bogus; + return; + } + + if(!has_valid_wnsec) { + verbose(VERB_QUERY, "NameError response has failed to prove: " + "covering wildcard does not exist"); + chase_reply->security = sec_status_bogus; + return; + } + + /* Otherwise, we consider the message secure. */ + verbose(VERB_ALGO, "successfully validated NAME ERROR response."); + chase_reply->security = sec_status_secure; +} + +/** + * Given a referral response, validate rrsets and take least trusted rrset + * as the current validation status. + * + * Note that by the time this method is called, the process of finding the + * trusted DNSKEY rrset that signs this response must already have been + * completed. + * + * @param chase_reply: answer to validate. + */ +static void +validate_referral_response(struct reply_info* chase_reply) +{ + size_t i; + enum sec_status s; + /* message security equals lowest rrset security */ + chase_reply->security = sec_status_secure; + for(i=0; irrset_count; i++) { + s = ((struct packed_rrset_data*)chase_reply->rrsets[i] + ->entry.data)->security; + if(s < chase_reply->security) + chase_reply->security = s; + } + verbose(VERB_ALGO, "validated part of referral response as %s", + sec_status_to_string(chase_reply->security)); +} + +/** + * Given an "ANY" response -- a response that contains an answer to a + * qtype==ANY question, with answers. This does no checking that all + * types are present. + * + * NOTE: it may be possible to get parent-side delegation point records + * here, which won't all be signed. Right now, this routine relies on the + * upstream iterative resolver to not return these responses -- instead + * treating them as referrals. + * + * NOTE: RFC 4035 is silent on this issue, so this may change upon + * clarification. Clarification draft -05 says to not check all types are + * present. + * + * Note that by the time this method is called, the process of finding the + * trusted DNSKEY rrset that signs this response must already have been + * completed. + * + * @param env: module env for verify. + * @param ve: validator env for verify. + * @param qchase: query that was made. + * @param chase_reply: answer to that query to validate. + * @param kkey: the key entry, which is trusted, and which matches + * the signer of the answer. The key entry isgood(). + */ +static void +validate_any_response(struct module_env* env, struct val_env* ve, + struct query_info* qchase, struct reply_info* chase_reply, + struct key_entry_key* kkey) +{ + /* all answer and auth rrsets already verified */ + /* but check if a wildcard response is given, then check NSEC/NSEC3 + * for qname denial to see if wildcard is applicable */ + uint8_t* wc = NULL; + int wc_NSEC_ok = 0; + int nsec3s_seen = 0; + size_t i; + struct ub_packed_rrset_key* s; + + if(qchase->qtype != LDNS_RR_TYPE_ANY) { + log_err("internal error: ANY validation called for non-ANY"); + chase_reply->security = sec_status_bogus; + return; + } + + /* validate the ANSWER section - this will be the answer itself */ + for(i=0; ian_numrrsets; i++) { + s = chase_reply->rrsets[i]; + + /* Check to see if the rrset is the result of a wildcard + * expansion. If so, an additional check will need to be + * made in the authority section. */ + if(!val_rrset_wildcard(s, &wc)) { + log_nametypeclass(VERB_QUERY, "Positive ANY response" + " has inconsistent wildcard sigs:", + s->rk.dname, ntohs(s->rk.type), + ntohs(s->rk.rrset_class)); + chase_reply->security = sec_status_bogus; + return; + } + } + + /* if it was a wildcard, check for NSEC/NSEC3s in both answer + * and authority sections (NSEC may be moved to the ANSWER section) */ + if(wc != NULL) + for(i=0; ian_numrrsets+chase_reply->ns_numrrsets; + i++) { + s = chase_reply->rrsets[i]; + + /* If this is a positive wildcard response, and we have a + * (just verified) NSEC record, try to use it to 1) prove + * that qname doesn't exist and 2) that the correct wildcard + * was used. */ + if(ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC) { + if(val_nsec_proves_positive_wildcard(s, qchase, wc)) { + wc_NSEC_ok = 1; + } + /* if not, continue looking for proof */ + } + + /* Otherwise, if this is a positive wildcard response and + * we have NSEC3 records */ + if(ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC3) { + nsec3s_seen = 1; + } + } + + /* If this was a positive wildcard response that we haven't already + * proven, and we have NSEC3 records, try to prove it using the NSEC3 + * records. */ + if(wc != NULL && !wc_NSEC_ok && nsec3s_seen) { + /* look both in answer and auth section for NSEC3s */ + enum sec_status sec = nsec3_prove_wildcard(env, ve, + chase_reply->rrsets, + chase_reply->an_numrrsets+chase_reply->ns_numrrsets, + qchase, kkey, wc); + if(sec == sec_status_insecure) { + verbose(VERB_ALGO, "Positive ANY wildcard response is " + "insecure"); + chase_reply->security = sec_status_insecure; + return; + } else if(sec == sec_status_secure) + wc_NSEC_ok = 1; + } + + /* If after all this, we still haven't proven the positive wildcard + * response, fail. */ + if(wc != NULL && !wc_NSEC_ok) { + verbose(VERB_QUERY, "positive ANY response was wildcard " + "expansion and did not prove original data " + "did not exist"); + chase_reply->security = sec_status_bogus; + return; + } + + verbose(VERB_ALGO, "Successfully validated positive ANY response"); + chase_reply->security = sec_status_secure; +} + +/** + * Validate CNAME response, or DNAME+CNAME. + * This is just like a positive proof, except that this is about a + * DNAME+CNAME. Possible wildcard proof. + * Difference with positive proof is that this routine refuses + * wildcarded DNAMEs. + * + * The answer and authority rrsets must already be verified as secure. + * + * @param env: module env for verify. + * @param ve: validator env for verify. + * @param qchase: query that was made. + * @param chase_reply: answer to that query to validate. + * @param kkey: the key entry, which is trusted, and which matches + * the signer of the answer. The key entry isgood(). + */ +static void +validate_cname_response(struct module_env* env, struct val_env* ve, + struct query_info* qchase, struct reply_info* chase_reply, + struct key_entry_key* kkey) +{ + uint8_t* wc = NULL; + int wc_NSEC_ok = 0; + int nsec3s_seen = 0; + size_t i; + struct ub_packed_rrset_key* s; + + /* validate the ANSWER section - this will be the CNAME (+DNAME) */ + for(i=0; ian_numrrsets; i++) { + s = chase_reply->rrsets[i]; + + /* Check to see if the rrset is the result of a wildcard + * expansion. If so, an additional check will need to be + * made in the authority section. */ + if(!val_rrset_wildcard(s, &wc)) { + log_nametypeclass(VERB_QUERY, "Cname response has " + "inconsistent wildcard sigs:", s->rk.dname, + ntohs(s->rk.type), ntohs(s->rk.rrset_class)); + chase_reply->security = sec_status_bogus; + return; + } + + /* Refuse wildcarded DNAMEs rfc 4597. + * Do not follow a wildcarded DNAME because + * its synthesized CNAME expansion is underdefined */ + if(qchase->qtype != LDNS_RR_TYPE_DNAME && + ntohs(s->rk.type) == LDNS_RR_TYPE_DNAME && wc) { + log_nametypeclass(VERB_QUERY, "cannot validate a " + "wildcarded DNAME:", s->rk.dname, + ntohs(s->rk.type), ntohs(s->rk.rrset_class)); + chase_reply->security = sec_status_bogus; + return; + } + } + + /* AUTHORITY section */ + for(i=chase_reply->an_numrrsets; ian_numrrsets+ + chase_reply->ns_numrrsets; i++) { + s = chase_reply->rrsets[i]; + + /* If this is a positive wildcard response, and we have a + * (just verified) NSEC record, try to use it to 1) prove + * that qname doesn't exist and 2) that the correct wildcard + * was used. */ + if(wc != NULL && ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC) { + if(val_nsec_proves_positive_wildcard(s, qchase, wc)) { + wc_NSEC_ok = 1; + } + /* if not, continue looking for proof */ + } + + /* Otherwise, if this is a positive wildcard response and + * we have NSEC3 records */ + if(wc != NULL && ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC3) { + nsec3s_seen = 1; + } + } + + /* If this was a positive wildcard response that we haven't already + * proven, and we have NSEC3 records, try to prove it using the NSEC3 + * records. */ + if(wc != NULL && !wc_NSEC_ok && nsec3s_seen) { + enum sec_status sec = nsec3_prove_wildcard(env, ve, + chase_reply->rrsets+chase_reply->an_numrrsets, + chase_reply->ns_numrrsets, qchase, kkey, wc); + if(sec == sec_status_insecure) { + verbose(VERB_ALGO, "wildcard CNAME response is " + "insecure"); + chase_reply->security = sec_status_insecure; + return; + } else if(sec == sec_status_secure) + wc_NSEC_ok = 1; + } + + /* If after all this, we still haven't proven the positive wildcard + * response, fail. */ + if(wc != NULL && !wc_NSEC_ok) { + verbose(VERB_QUERY, "CNAME response was wildcard " + "expansion and did not prove original data " + "did not exist"); + chase_reply->security = sec_status_bogus; + return; + } + + verbose(VERB_ALGO, "Successfully validated CNAME response"); + chase_reply->security = sec_status_secure; +} + +/** + * Validate CNAME NOANSWER response, no more data after a CNAME chain. + * This can be a NODATA or a NAME ERROR case, but not both at the same time. + * We don't know because the rcode has been set to NOERROR by the CNAME. + * + * The answer and authority rrsets must already be verified as secure. + * + * @param env: module env for verify. + * @param ve: validator env for verify. + * @param qchase: query that was made. + * @param chase_reply: answer to that query to validate. + * @param kkey: the key entry, which is trusted, and which matches + * the signer of the answer. The key entry isgood(). + */ +static void +validate_cname_noanswer_response(struct module_env* env, struct val_env* ve, + struct query_info* qchase, struct reply_info* chase_reply, + struct key_entry_key* kkey) +{ + int nodata_valid_nsec = 0; /* If true, then NODATA has been proven.*/ + uint8_t* ce = NULL; /* for wildcard nodata responses. This is the + proven closest encloser. */ + uint8_t* wc = NULL; /* for wildcard nodata responses. wildcard nsec */ + int nxdomain_valid_nsec = 0; /* if true, namerror has been proven */ + int nxdomain_valid_wnsec = 0; + int nsec3s_seen = 0; /* nsec3s seen */ + struct ub_packed_rrset_key* s; + size_t i; + + /* the AUTHORITY section */ + for(i=chase_reply->an_numrrsets; ian_numrrsets+ + chase_reply->ns_numrrsets; i++) { + s = chase_reply->rrsets[i]; + + /* If we encounter an NSEC record, try to use it to prove + * NODATA. This needs to handle the ENT NODATA case. + * Also try to prove NAMEERROR, and absence of a wildcard */ + if(ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC) { + if(nsec_proves_nodata(s, qchase, &wc)) { + nodata_valid_nsec = 1; + /* set wc encloser if wildcard applicable */ + } + if(val_nsec_proves_name_error(s, qchase->qname)) { + ce = nsec_closest_encloser(qchase->qname, s); + nxdomain_valid_nsec = 1; + } + if(val_nsec_proves_no_wc(s, qchase->qname, + qchase->qname_len)) + nxdomain_valid_wnsec = 1; + if(val_nsec_proves_insecuredelegation(s, qchase)) { + verbose(VERB_ALGO, "delegation is insecure"); + chase_reply->security = sec_status_insecure; + return; + } + } else if(ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC3) { + nsec3s_seen = 1; + } + } + + /* check to see if we have a wildcard NODATA proof. */ + + /* The wildcard NODATA is 1 NSEC proving that qname does not exists + * (and also proving what the closest encloser is), and 1 NSEC + * showing the matching wildcard, which must be *.closest_encloser. */ + if(wc && !ce) + nodata_valid_nsec = 0; + else if(wc && ce) { + if(query_dname_compare(wc, ce) != 0) { + nodata_valid_nsec = 0; + } + } + if(nxdomain_valid_nsec && !nxdomain_valid_wnsec) { + /* name error is missing wildcard denial proof */ + nxdomain_valid_nsec = 0; + } + + if(nodata_valid_nsec && nxdomain_valid_nsec) { + verbose(VERB_QUERY, "CNAMEchain to noanswer proves that name " + "exists and not exists, bogus"); + chase_reply->security = sec_status_bogus; + return; + } + if(!nodata_valid_nsec && !nxdomain_valid_nsec && nsec3s_seen) { + int nodata; + enum sec_status sec = nsec3_prove_nxornodata(env, ve, + chase_reply->rrsets+chase_reply->an_numrrsets, + chase_reply->ns_numrrsets, qchase, kkey, &nodata); + if(sec == sec_status_insecure) { + verbose(VERB_ALGO, "CNAMEchain to noanswer response " + "is insecure"); + chase_reply->security = sec_status_insecure; + return; + } else if(sec == sec_status_secure) { + if(nodata) + nodata_valid_nsec = 1; + else nxdomain_valid_nsec = 1; + } + } + + if(!nodata_valid_nsec && !nxdomain_valid_nsec) { + verbose(VERB_QUERY, "CNAMEchain to noanswer response failed " + "to prove status with NSEC/NSEC3"); + if(verbosity >= VERB_ALGO) + log_dns_msg("Failed CNAMEnoanswer", qchase, chase_reply); + chase_reply->security = sec_status_bogus; + return; + } + + if(nodata_valid_nsec) + verbose(VERB_ALGO, "successfully validated CNAME chain to a " + "NODATA response."); + else verbose(VERB_ALGO, "successfully validated CNAME chain to a " + "NAMEERROR response."); + chase_reply->security = sec_status_secure; +} + +/** + * Process init state for validator. + * Process the INIT state. First tier responses start in the INIT state. + * This is where they are vetted for validation suitability, and the initial + * key search is done. + * + * Currently, events the come through this routine will be either promoted + * to FINISHED/CNAME_RESP (no validation needed), FINDKEY (next step to + * validation), or will be (temporarily) retired and a new priming request + * event will be generated. + * + * @param qstate: query state. + * @param vq: validator query state. + * @param ve: validator shared global environment. + * @param id: module id. + * @return true if the event should be processed further on return, false if + * not. + */ +static int +processInit(struct module_qstate* qstate, struct val_qstate* vq, + struct val_env* ve, int id) +{ + uint8_t* lookup_name; + size_t lookup_len; + struct trust_anchor* anchor; + enum val_classification subtype = val_classify_response( + qstate->query_flags, &qstate->qinfo, &vq->qchase, + vq->orig_msg->rep, vq->rrset_skip); + if(vq->restart_count > VAL_MAX_RESTART_COUNT) { + verbose(VERB_ALGO, "restart count exceeded"); + return val_error(qstate, id); + } + verbose(VERB_ALGO, "validator classification %s", + val_classification_to_string(subtype)); + if(subtype == VAL_CLASS_REFERRAL && + vq->rrset_skip < vq->orig_msg->rep->rrset_count) { + /* referral uses the rrset name as qchase, to find keys for + * that rrset */ + vq->qchase.qname = vq->orig_msg->rep-> + rrsets[vq->rrset_skip]->rk.dname; + vq->qchase.qname_len = vq->orig_msg->rep-> + rrsets[vq->rrset_skip]->rk.dname_len; + vq->qchase.qtype = ntohs(vq->orig_msg->rep-> + rrsets[vq->rrset_skip]->rk.type); + vq->qchase.qclass = ntohs(vq->orig_msg->rep-> + rrsets[vq->rrset_skip]->rk.rrset_class); + } + lookup_name = vq->qchase.qname; + lookup_len = vq->qchase.qname_len; + /* for type DS look at the parent side for keys/trustanchor */ + /* also for NSEC not at apex */ + if(vq->qchase.qtype == LDNS_RR_TYPE_DS || + (vq->qchase.qtype == LDNS_RR_TYPE_NSEC && + vq->orig_msg->rep->rrset_count > vq->rrset_skip && + ntohs(vq->orig_msg->rep->rrsets[vq->rrset_skip]->rk.type) == + LDNS_RR_TYPE_NSEC && + !(vq->orig_msg->rep->rrsets[vq->rrset_skip]-> + rk.flags&PACKED_RRSET_NSEC_AT_APEX))) { + dname_remove_label(&lookup_name, &lookup_len); + } + + val_mark_indeterminate(vq->chase_reply, qstate->env->anchors, + qstate->env->rrset_cache, qstate->env); + vq->key_entry = NULL; + vq->empty_DS_name = NULL; + vq->ds_rrset = 0; + anchor = anchors_lookup(qstate->env->anchors, + lookup_name, lookup_len, vq->qchase.qclass); + + /* Determine the signer/lookup name */ + val_find_signer(subtype, &vq->qchase, vq->orig_msg->rep, + vq->rrset_skip, &vq->signer_name, &vq->signer_len); + if(vq->signer_name != NULL && + !dname_subdomain_c(lookup_name, vq->signer_name)) { + log_nametypeclass(VERB_ALGO, "this signer name is not a parent " + "of lookupname, omitted", vq->signer_name, 0, 0); + vq->signer_name = NULL; + } + if(vq->signer_name == NULL) { + log_nametypeclass(VERB_ALGO, "no signer, using", lookup_name, + 0, 0); + } else { + lookup_name = vq->signer_name; + lookup_len = vq->signer_len; + log_nametypeclass(VERB_ALGO, "signer is", lookup_name, 0, 0); + } + + /* for NXDOMAIN it could be signed by a parent of the trust anchor */ + if(subtype == VAL_CLASS_NAMEERROR && vq->signer_name && + anchor && dname_strict_subdomain_c(anchor->name, lookup_name)){ + lock_basic_unlock(&anchor->lock); + anchor = anchors_lookup(qstate->env->anchors, + lookup_name, lookup_len, vq->qchase.qclass); + if(!anchor) { /* unsigned parent denies anchor*/ + verbose(VERB_QUERY, "unsigned parent zone denies" + " trust anchor, indeterminate"); + vq->chase_reply->security = sec_status_indeterminate; + vq->state = VAL_FINISHED_STATE; + return 1; + } + verbose(VERB_ALGO, "trust anchor NXDOMAIN by signed parent"); + } else if(subtype == VAL_CLASS_POSITIVE && + qstate->qinfo.qtype == LDNS_RR_TYPE_DNSKEY && + query_dname_compare(lookup_name, qstate->qinfo.qname) == 0) { + /* is a DNSKEY so lookup a bit higher since we want to + * get it from a parent or from trustanchor */ + dname_remove_label(&lookup_name, &lookup_len); + } + + if(vq->rrset_skip > 0 || subtype == VAL_CLASS_CNAME || + subtype == VAL_CLASS_REFERRAL) { + /* extract this part of orig_msg into chase_reply for + * the eventual VALIDATE stage */ + val_fill_reply(vq->chase_reply, vq->orig_msg->rep, + vq->rrset_skip, lookup_name, lookup_len, + vq->signer_name); + if(verbosity >= VERB_ALGO) + log_dns_msg("chased extract", &vq->qchase, + vq->chase_reply); + } + + vq->key_entry = key_cache_obtain(ve->kcache, lookup_name, lookup_len, + vq->qchase.qclass, qstate->region, *qstate->env->now); + + /* there is no key(from DLV) and no trust anchor */ + if(vq->key_entry == NULL && anchor == NULL) { + /*response isn't under a trust anchor, so we cannot validate.*/ + vq->chase_reply->security = sec_status_indeterminate; + /* go to finished state to cache this result */ + vq->state = VAL_FINISHED_STATE; + return 1; + } + /* if not key, or if keyentry is *above* the trustanchor, i.e. + * the keyentry is based on another (higher) trustanchor */ + else if(vq->key_entry == NULL || (anchor && + dname_strict_subdomain_c(anchor->name, vq->key_entry->name))) { + /* trust anchor is an 'unsigned' trust anchor */ + if(anchor && anchor->numDS == 0 && anchor->numDNSKEY == 0) { + vq->chase_reply->security = sec_status_insecure; + val_mark_insecure(vq->chase_reply, anchor->name, + qstate->env->rrset_cache, qstate->env); + lock_basic_unlock(&anchor->lock); + vq->dlv_checked=1; /* skip DLV check */ + /* go to finished state to cache this result */ + vq->state = VAL_FINISHED_STATE; + return 1; + } + /* fire off a trust anchor priming query. */ + verbose(VERB_DETAIL, "prime trust anchor"); + if(!prime_trust_anchor(qstate, vq, id, anchor)) { + lock_basic_unlock(&anchor->lock); + return val_error(qstate, id); + } + lock_basic_unlock(&anchor->lock); + /* and otherwise, don't continue processing this event. + * (it will be reactivated when the priming query returns). */ + vq->state = VAL_FINDKEY_STATE; + return 0; + } + if(anchor) { + lock_basic_unlock(&anchor->lock); + } + + if(key_entry_isnull(vq->key_entry)) { + /* response is under a null key, so we cannot validate + * However, we do set the status to INSECURE, since it is + * essentially proven insecure. */ + vq->chase_reply->security = sec_status_insecure; + val_mark_insecure(vq->chase_reply, vq->key_entry->name, + qstate->env->rrset_cache, qstate->env); + /* go to finished state to cache this result */ + vq->state = VAL_FINISHED_STATE; + return 1; + } else if(key_entry_isbad(vq->key_entry)) { + /* key is bad, chain is bad, reply is bogus */ + errinf_dname(qstate, "key for validation", vq->key_entry->name); + errinf(qstate, "is marked as invalid"); + if(key_entry_get_reason(vq->key_entry)) { + errinf(qstate, "because of a previous"); + errinf(qstate, key_entry_get_reason(vq->key_entry)); + } + /* no retries, stop bothering the authority until timeout */ + vq->restart_count = VAL_MAX_RESTART_COUNT; + vq->chase_reply->security = sec_status_bogus; + vq->state = VAL_FINISHED_STATE; + return 1; + } + + /* otherwise, we have our "closest" cached key -- continue + * processing in the next state. */ + vq->state = VAL_FINDKEY_STATE; + return 1; +} + +/** + * Process the FINDKEY state. Generally this just calculates the next name + * to query and either issues a DS or a DNSKEY query. It will check to see + * if the correct key has already been reached, in which case it will + * advance the event to the next state. + * + * @param qstate: query state. + * @param vq: validator query state. + * @param id: module id. + * @return true if the event should be processed further on return, false if + * not. + */ +static int +processFindKey(struct module_qstate* qstate, struct val_qstate* vq, int id) +{ + uint8_t* target_key_name, *current_key_name; + size_t target_key_len; + int strip_lab; + + log_query_info(VERB_ALGO, "validator: FindKey", &vq->qchase); + /* We know that state.key_entry is not 0 or bad key -- if it were, + * then previous processing should have directed this event to + * a different state. + * It could be an isnull key, which signals that a DLV was just + * done and the DNSKEY after the DLV failed with dnssec-retry state + * and the DNSKEY has to be performed again. */ + log_assert(vq->key_entry && !key_entry_isbad(vq->key_entry)); + if(key_entry_isnull(vq->key_entry)) { + if(!generate_request(qstate, id, vq->ds_rrset->rk.dname, + vq->ds_rrset->rk.dname_len, LDNS_RR_TYPE_DNSKEY, + vq->qchase.qclass, BIT_CD)) { + log_err("mem error generating DNSKEY request"); + return val_error(qstate, id); + } + return 0; + } + + target_key_name = vq->signer_name; + target_key_len = vq->signer_len; + if(!target_key_name) { + target_key_name = vq->qchase.qname; + target_key_len = vq->qchase.qname_len; + } + + current_key_name = vq->key_entry->name; + + /* If our current key entry matches our target, then we are done. */ + if(query_dname_compare(target_key_name, current_key_name) == 0) { + vq->state = VAL_VALIDATE_STATE; + return 1; + } + + if(vq->empty_DS_name) { + /* if the last empty nonterminal/emptyDS name we detected is + * below the current key, use that name to make progress + * along the chain of trust */ + if(query_dname_compare(target_key_name, + vq->empty_DS_name) == 0) { + /* do not query for empty_DS_name again */ + verbose(VERB_ALGO, "Cannot retrieve DS for signature"); + errinf(qstate, "no signatures"); + errinf_origin(qstate, qstate->reply_origin); + vq->chase_reply->security = sec_status_bogus; + vq->state = VAL_FINISHED_STATE; + return 1; + } + current_key_name = vq->empty_DS_name; + } + + log_nametypeclass(VERB_ALGO, "current keyname", current_key_name, + LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN); + log_nametypeclass(VERB_ALGO, "target keyname", target_key_name, + LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN); + /* assert we are walking down the DNS tree */ + if(!dname_subdomain_c(target_key_name, current_key_name)) { + verbose(VERB_ALGO, "bad signer name"); + vq->chase_reply->security = sec_status_bogus; + vq->state = VAL_FINISHED_STATE; + return 1; + } + /* so this value is >= -1 */ + strip_lab = dname_count_labels(target_key_name) - + dname_count_labels(current_key_name) - 1; + log_assert(strip_lab >= -1); + verbose(VERB_ALGO, "striplab %d", strip_lab); + if(strip_lab > 0) { + dname_remove_labels(&target_key_name, &target_key_len, + strip_lab); + } + log_nametypeclass(VERB_ALGO, "next keyname", target_key_name, + LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN); + + /* The next step is either to query for the next DS, or to query + * for the next DNSKEY. */ + if(vq->ds_rrset) + log_nametypeclass(VERB_ALGO, "DS RRset", vq->ds_rrset->rk.dname, LDNS_RR_TYPE_DS, LDNS_RR_CLASS_IN); + else verbose(VERB_ALGO, "No DS RRset"); + + if(vq->ds_rrset && query_dname_compare(vq->ds_rrset->rk.dname, + vq->key_entry->name) != 0) { + if(!generate_request(qstate, id, vq->ds_rrset->rk.dname, + vq->ds_rrset->rk.dname_len, LDNS_RR_TYPE_DNSKEY, + vq->qchase.qclass, BIT_CD)) { + log_err("mem error generating DNSKEY request"); + return val_error(qstate, id); + } + return 0; + } + + if(!vq->ds_rrset || query_dname_compare(vq->ds_rrset->rk.dname, + target_key_name) != 0) { + /* check if there is a cache entry : pick up an NSEC if + * there is no DS, check if that NSEC has DS-bit unset, and + * thus can disprove the secure delagation we seek. + * We can then use that NSEC even in the absence of a SOA + * record that would be required by the iterator to supply + * a completely protocol-correct response. + * Uses negative cache for NSEC3 lookup of DS responses. */ + /* only if cache not blacklisted, of course */ + struct dns_msg* msg; + if(!qstate->blacklist && !vq->chain_blacklist && + (msg=val_find_DS(qstate->env, target_key_name, + target_key_len, vq->qchase.qclass, qstate->region, + vq->key_entry->name)) ) { + verbose(VERB_ALGO, "Process cached DS response"); + process_ds_response(qstate, vq, id, LDNS_RCODE_NOERROR, + msg, &msg->qinfo, NULL); + return 1; /* continue processing ds-response results */ + } + if(!generate_request(qstate, id, target_key_name, + target_key_len, LDNS_RR_TYPE_DS, vq->qchase.qclass, + BIT_CD)) { + log_err("mem error generating DS request"); + return val_error(qstate, id); + } + return 0; + } + + /* Otherwise, it is time to query for the DNSKEY */ + if(!generate_request(qstate, id, vq->ds_rrset->rk.dname, + vq->ds_rrset->rk.dname_len, LDNS_RR_TYPE_DNSKEY, + vq->qchase.qclass, BIT_CD)) { + log_err("mem error generating DNSKEY request"); + return val_error(qstate, id); + } + + return 0; +} + +/** + * Process the VALIDATE stage, the init and findkey stages are finished, + * and the right keys are available to validate the response. + * Or, there are no keys available, in order to invalidate the response. + * + * After validation, the status is recorded in the message and rrsets, + * and finished state is started. + * + * @param qstate: query state. + * @param vq: validator query state. + * @param ve: validator shared global environment. + * @param id: module id. + * @return true if the event should be processed further on return, false if + * not. + */ +static int +processValidate(struct module_qstate* qstate, struct val_qstate* vq, + struct val_env* ve, int id) +{ + enum val_classification subtype; + + if(!vq->key_entry) { + verbose(VERB_ALGO, "validate: no key entry, failed"); + return val_error(qstate, id); + } + + /* This is the default next state. */ + vq->state = VAL_FINISHED_STATE; + + /* Unsigned responses must be underneath a "null" key entry.*/ + if(key_entry_isnull(vq->key_entry)) { + verbose(VERB_DETAIL, "Verified that %sresponse is INSECURE", + vq->signer_name?"":"unsigned "); + vq->chase_reply->security = sec_status_insecure; + val_mark_insecure(vq->chase_reply, vq->key_entry->name, + qstate->env->rrset_cache, qstate->env); + key_cache_insert(ve->kcache, vq->key_entry, qstate); + return 1; + } + + if(key_entry_isbad(vq->key_entry)) { + log_nametypeclass(VERB_DETAIL, "Could not establish a chain " + "of trust to keys for", vq->key_entry->name, + LDNS_RR_TYPE_DNSKEY, vq->key_entry->key_class); + vq->chase_reply->security = sec_status_bogus; + errinf(qstate, "while building chain of trust"); + if(vq->restart_count >= VAL_MAX_RESTART_COUNT) + key_cache_insert(ve->kcache, vq->key_entry, qstate); + return 1; + } + + /* signerName being null is the indicator that this response was + * unsigned */ + if(vq->signer_name == NULL) { + log_query_info(VERB_ALGO, "processValidate: state has no " + "signer name", &vq->qchase); + verbose(VERB_DETAIL, "Could not establish validation of " + "INSECURE status of unsigned response."); + errinf(qstate, "no signatures"); + errinf_origin(qstate, qstate->reply_origin); + vq->chase_reply->security = sec_status_bogus; + return 1; + } + subtype = val_classify_response(qstate->query_flags, &qstate->qinfo, + &vq->qchase, vq->orig_msg->rep, vq->rrset_skip); + + /* check signatures in the message; + * answer and authority must be valid, additional is only checked. */ + if(!validate_msg_signatures(qstate, qstate->env, ve, &vq->qchase, + vq->chase_reply, vq->key_entry)) { + /* workaround bad recursor out there that truncates (even + * with EDNS4k) to 512 by removing RRSIG from auth section + * for positive replies*/ + if((subtype == VAL_CLASS_POSITIVE || subtype == VAL_CLASS_ANY + || subtype == VAL_CLASS_CNAME) && + detect_wrongly_truncated(vq->orig_msg->rep)) { + /* truncate the message some more */ + vq->orig_msg->rep->ns_numrrsets = 0; + vq->orig_msg->rep->ar_numrrsets = 0; + vq->orig_msg->rep->rrset_count = + vq->orig_msg->rep->an_numrrsets; + vq->chase_reply->ns_numrrsets = 0; + vq->chase_reply->ar_numrrsets = 0; + vq->chase_reply->rrset_count = + vq->chase_reply->an_numrrsets; + qstate->errinf = NULL; + } + else { + verbose(VERB_DETAIL, "Validate: message contains " + "bad rrsets"); + return 1; + } + } + + switch(subtype) { + case VAL_CLASS_POSITIVE: + verbose(VERB_ALGO, "Validating a positive response"); + validate_positive_response(qstate->env, ve, + &vq->qchase, vq->chase_reply, vq->key_entry); + verbose(VERB_DETAIL, "validate(positive): %s", + sec_status_to_string( + vq->chase_reply->security)); + break; + + case VAL_CLASS_NODATA: + verbose(VERB_ALGO, "Validating a nodata response"); + validate_nodata_response(qstate->env, ve, + &vq->qchase, vq->chase_reply, vq->key_entry); + verbose(VERB_DETAIL, "validate(nodata): %s", + sec_status_to_string( + vq->chase_reply->security)); + break; + + case VAL_CLASS_NAMEERROR: + verbose(VERB_ALGO, "Validating a nxdomain response"); + validate_nameerror_response(qstate->env, ve, + &vq->qchase, vq->chase_reply, vq->key_entry); + verbose(VERB_DETAIL, "validate(nxdomain): %s", + sec_status_to_string( + vq->chase_reply->security)); + break; + + case VAL_CLASS_CNAME: + verbose(VERB_ALGO, "Validating a cname response"); + validate_cname_response(qstate->env, ve, + &vq->qchase, vq->chase_reply, vq->key_entry); + verbose(VERB_DETAIL, "validate(cname): %s", + sec_status_to_string( + vq->chase_reply->security)); + break; + + case VAL_CLASS_CNAMENOANSWER: + verbose(VERB_ALGO, "Validating a cname noanswer " + "response"); + validate_cname_noanswer_response(qstate->env, ve, + &vq->qchase, vq->chase_reply, vq->key_entry); + verbose(VERB_DETAIL, "validate(cname_noanswer): %s", + sec_status_to_string( + vq->chase_reply->security)); + break; + + case VAL_CLASS_REFERRAL: + verbose(VERB_ALGO, "Validating a referral response"); + validate_referral_response(vq->chase_reply); + verbose(VERB_DETAIL, "validate(referral): %s", + sec_status_to_string( + vq->chase_reply->security)); + break; + + case VAL_CLASS_ANY: + verbose(VERB_ALGO, "Validating a positive ANY " + "response"); + validate_any_response(qstate->env, ve, &vq->qchase, + vq->chase_reply, vq->key_entry); + verbose(VERB_DETAIL, "validate(positive_any): %s", + sec_status_to_string( + vq->chase_reply->security)); + break; + + default: + log_err("validate: unhandled response subtype: %d", + subtype); + } + if(vq->chase_reply->security == sec_status_bogus) { + if(subtype == VAL_CLASS_POSITIVE) + errinf(qstate, "wildcard"); + else errinf(qstate, val_classification_to_string(subtype)); + errinf(qstate, "proof failed"); + errinf_origin(qstate, qstate->reply_origin); + } + + return 1; +} + +/** + * Init DLV check. + * Called when a query is determined by other trust anchors to be insecure + * (or indeterminate). Then we look if there is a key in the DLV. + * Performs aggressive negative cache check to see if there is no key. + * Otherwise, spawns a DLV query, and changes to the DLV wait state. + * + * @param qstate: query state. + * @param vq: validator query state. + * @param ve: validator shared global environment. + * @param id: module id. + * @return true if there is no DLV. + * false: processing is finished for the validator operate(). + * This function may exit in three ways: + * o no DLV (agressive cache), so insecure. (true) + * o error - stop processing (false) + * o DLV lookup was started, stop processing (false) + */ +static int +val_dlv_init(struct module_qstate* qstate, struct val_qstate* vq, + struct val_env* ve, int id) +{ + uint8_t* nm; + size_t nm_len; + /* there must be a DLV configured */ + log_assert(qstate->env->anchors->dlv_anchor); + /* this bool is true to avoid looping in the DLV checks */ + log_assert(vq->dlv_checked); + + /* init the DLV lookup variables */ + vq->dlv_lookup_name = NULL; + vq->dlv_lookup_name_len = 0; + vq->dlv_insecure_at = NULL; + vq->dlv_insecure_at_len = 0; + + /* Determine the name for which we want to lookup DLV. + * This name is for the current message, or + * for the current RRset for CNAME, referral subtypes. + * If there is a signer, use that, otherwise the domain name */ + if(vq->signer_name) { + nm = vq->signer_name; + nm_len = vq->signer_len; + } else { + /* use qchase */ + nm = vq->qchase.qname; + nm_len = vq->qchase.qname_len; + if(vq->qchase.qtype == LDNS_RR_TYPE_DS) + dname_remove_label(&nm, &nm_len); + } + log_nametypeclass(VERB_ALGO, "DLV init look", nm, LDNS_RR_TYPE_DS, + vq->qchase.qclass); + log_assert(nm && nm_len); + /* sanity check: no DLV lookups below the DLV anchor itself. + * Like, an securely insecure delegation there makes no sense. */ + if(dname_subdomain_c(nm, qstate->env->anchors->dlv_anchor->name)) { + verbose(VERB_ALGO, "DLV lookup within DLV repository denied"); + return 1; + } + /* concat name (minus root label) + dlv name */ + vq->dlv_lookup_name_len = nm_len - 1 + + qstate->env->anchors->dlv_anchor->namelen; + vq->dlv_lookup_name = regional_alloc(qstate->region, + vq->dlv_lookup_name_len); + if(!vq->dlv_lookup_name) { + log_err("Out of memory preparing DLV lookup"); + return val_error(qstate, id); + } + memmove(vq->dlv_lookup_name, nm, nm_len-1); + memmove(vq->dlv_lookup_name+nm_len-1, + qstate->env->anchors->dlv_anchor->name, + qstate->env->anchors->dlv_anchor->namelen); + log_nametypeclass(VERB_ALGO, "DLV name", vq->dlv_lookup_name, + LDNS_RR_TYPE_DLV, vq->qchase.qclass); + + /* determine where the insecure point was determined, the DLV must + * be equal or below that to continue building the trust chain + * down. May be NULL if no trust chain was built yet */ + nm = NULL; + if(vq->key_entry && key_entry_isnull(vq->key_entry)) { + nm = vq->key_entry->name; + nm_len = vq->key_entry->namelen; + } + if(nm) { + vq->dlv_insecure_at_len = nm_len - 1 + + qstate->env->anchors->dlv_anchor->namelen; + vq->dlv_insecure_at = regional_alloc(qstate->region, + vq->dlv_insecure_at_len); + if(!vq->dlv_insecure_at) { + log_err("Out of memory preparing DLV lookup"); + return val_error(qstate, id); + } + memmove(vq->dlv_insecure_at, nm, nm_len-1); + memmove(vq->dlv_insecure_at+nm_len-1, + qstate->env->anchors->dlv_anchor->name, + qstate->env->anchors->dlv_anchor->namelen); + log_nametypeclass(VERB_ALGO, "insecure_at", + vq->dlv_insecure_at, 0, vq->qchase.qclass); + } + + /* If we can find the name in the aggressive negative cache, + * give up; insecure is the answer */ + while(val_neg_dlvlookup(ve->neg_cache, vq->dlv_lookup_name, + vq->dlv_lookup_name_len, vq->qchase.qclass, + qstate->env->rrset_cache, *qstate->env->now)) { + /* go up */ + dname_remove_label(&vq->dlv_lookup_name, + &vq->dlv_lookup_name_len); + /* too high? */ + if(!dname_subdomain_c(vq->dlv_lookup_name, + qstate->env->anchors->dlv_anchor->name)) { + verbose(VERB_ALGO, "ask above dlv repo"); + return 1; /* Above the repo is insecure */ + } + /* above chain of trust? */ + if(vq->dlv_insecure_at && !dname_subdomain_c( + vq->dlv_lookup_name, vq->dlv_insecure_at)) { + verbose(VERB_ALGO, "ask above insecure endpoint"); + return 1; + } + } + + /* perform a lookup for the DLV; with validation */ + vq->state = VAL_DLVLOOKUP_STATE; + if(!generate_request(qstate, id, vq->dlv_lookup_name, + vq->dlv_lookup_name_len, LDNS_RR_TYPE_DLV, + vq->qchase.qclass, 0)) { + return val_error(qstate, id); + } + + /* Find the closest encloser DLV from the repository. + * then that is used to build another chain of trust + * This may first require a query 'too low' that has NSECs in + * the answer, from which we determine the closest encloser DLV. + * When determine the closest encloser, skip empty nonterminals, + * since we want a nonempty node in the DLV repository. */ + + return 0; +} + +/** + * The Finished state. The validation status (good or bad) has been determined. + * + * @param qstate: query state. + * @param vq: validator query state. + * @param ve: validator shared global environment. + * @param id: module id. + * @return true if the event should be processed further on return, false if + * not. + */ +static int +processFinished(struct module_qstate* qstate, struct val_qstate* vq, + struct val_env* ve, int id) +{ + enum val_classification subtype = val_classify_response( + qstate->query_flags, &qstate->qinfo, &vq->qchase, + vq->orig_msg->rep, vq->rrset_skip); + + /* if the result is insecure or indeterminate and we have not + * checked the DLV yet, check the DLV */ + if((vq->chase_reply->security == sec_status_insecure || + vq->chase_reply->security == sec_status_indeterminate) && + qstate->env->anchors->dlv_anchor && !vq->dlv_checked) { + vq->dlv_checked = 1; + if(!val_dlv_init(qstate, vq, ve, id)) + return 0; + } + + /* store overall validation result in orig_msg */ + if(vq->rrset_skip == 0) + vq->orig_msg->rep->security = vq->chase_reply->security; + else if(vq->rrset_skip < vq->orig_msg->rep->an_numrrsets + + vq->orig_msg->rep->ns_numrrsets) { + /* ignore sec status of additional section if a referral + * type message skips there and + * use the lowest security status as end result. */ + if(vq->chase_reply->security < vq->orig_msg->rep->security) + vq->orig_msg->rep->security = + vq->chase_reply->security; + } + + if(subtype == VAL_CLASS_REFERRAL) { + /* for a referral, move to next unchecked rrset and check it*/ + vq->rrset_skip = val_next_unchecked(vq->orig_msg->rep, + vq->rrset_skip); + if(vq->rrset_skip < vq->orig_msg->rep->rrset_count) { + /* and restart for this rrset */ + verbose(VERB_ALGO, "validator: go to next rrset"); + vq->chase_reply->security = sec_status_unchecked; + vq->dlv_checked = 0; /* can do DLV for this RR */ + vq->state = VAL_INIT_STATE; + return 1; + } + /* referral chase is done */ + } + if(vq->chase_reply->security != sec_status_bogus && + subtype == VAL_CLASS_CNAME) { + /* chase the CNAME; process next part of the message */ + if(!val_chase_cname(&vq->qchase, vq->orig_msg->rep, + &vq->rrset_skip)) { + verbose(VERB_ALGO, "validator: failed to chase CNAME"); + vq->orig_msg->rep->security = sec_status_bogus; + } else { + /* restart process for new qchase at rrset_skip */ + log_query_info(VERB_ALGO, "validator: chased to", + &vq->qchase); + vq->chase_reply->security = sec_status_unchecked; + vq->dlv_checked = 0; /* can do DLV for this RR */ + vq->state = VAL_INIT_STATE; + return 1; + } + } + + if(vq->orig_msg->rep->security == sec_status_secure) { + /* If the message is secure, check that all rrsets are + * secure (i.e. some inserted RRset for CNAME chain with + * a different signer name). And drop additional rrsets + * that are not secure (if clean-additional option is set) */ + /* this may cause the msg to be marked bogus */ + val_check_nonsecure(ve, vq->orig_msg->rep); + if(vq->orig_msg->rep->security == sec_status_secure) { + log_query_info(VERB_DETAIL, "validation success", + &qstate->qinfo); + } + } + + /* if the result is bogus - set message ttl to bogus ttl to avoid + * endless bogus revalidation */ + if(vq->orig_msg->rep->security == sec_status_bogus) { + /* see if we can try again to fetch data */ + if(vq->restart_count < VAL_MAX_RESTART_COUNT) { + int restart_count = vq->restart_count+1; + verbose(VERB_ALGO, "validation failed, " + "blacklist and retry to fetch data"); + val_blacklist(&qstate->blacklist, qstate->region, + qstate->reply_origin, 0); + qstate->reply_origin = NULL; + qstate->errinf = NULL; + memset(vq, 0, sizeof(*vq)); + vq->restart_count = restart_count; + vq->state = VAL_INIT_STATE; + verbose(VERB_ALGO, "pass back to next module"); + qstate->ext_state[id] = module_restart_next; + return 0; + } + + vq->orig_msg->rep->ttl = ve->bogus_ttl; + vq->orig_msg->rep->prefetch_ttl = + PREFETCH_TTL_CALC(vq->orig_msg->rep->ttl); + if(qstate->env->cfg->val_log_level >= 1 && + !qstate->env->cfg->val_log_squelch) { + if(qstate->env->cfg->val_log_level < 2) + log_query_info(0, "validation failure", + &qstate->qinfo); + else { + char* err = errinf_to_str(qstate); + if(err) log_info("%s", err); + free(err); + } + } + /* If we are in permissive mode, bogus gets indeterminate */ + if(ve->permissive_mode) + vq->orig_msg->rep->security = sec_status_indeterminate; + } + + /* store results in cache */ + if(qstate->query_flags&BIT_RD) { + /* if secure, this will override cache anyway, no need + * to check if from parentNS */ + if(!dns_cache_store(qstate->env, &vq->orig_msg->qinfo, + vq->orig_msg->rep, 0, qstate->prefetch_leeway, 0, NULL)) { + log_err("out of memory caching validator results"); + } + } else { + /* for a referral, store the verified RRsets */ + /* and this does not get prefetched, so no leeway */ + if(!dns_cache_store(qstate->env, &vq->orig_msg->qinfo, + vq->orig_msg->rep, 1, 0, 0, NULL)) { + log_err("out of memory caching validator results"); + } + } + qstate->return_rcode = LDNS_RCODE_NOERROR; + qstate->return_msg = vq->orig_msg; + qstate->ext_state[id] = module_finished; + return 0; +} + +/** + * The DLVLookup state. Process DLV lookups. + * + * @param qstate: query state. + * @param vq: validator query state. + * @param ve: validator shared global environment. + * @param id: module id. + * @return true if the event should be processed further on return, false if + * not. + */ +static int +processDLVLookup(struct module_qstate* qstate, struct val_qstate* vq, + struct val_env* ve, int id) +{ + /* see if this we are ready to continue normal resolution */ + /* we may need more DLV lookups */ + if(vq->dlv_status==dlv_error) + verbose(VERB_ALGO, "DLV woke up with status dlv_error"); + else if(vq->dlv_status==dlv_success) + verbose(VERB_ALGO, "DLV woke up with status dlv_success"); + else if(vq->dlv_status==dlv_ask_higher) + verbose(VERB_ALGO, "DLV woke up with status dlv_ask_higher"); + else if(vq->dlv_status==dlv_there_is_no_dlv) + verbose(VERB_ALGO, "DLV woke up with status dlv_there_is_no_dlv"); + else verbose(VERB_ALGO, "DLV woke up with status unknown"); + + if(vq->dlv_status == dlv_error) { + verbose(VERB_QUERY, "failed DLV lookup"); + return val_error(qstate, id); + } else if(vq->dlv_status == dlv_success) { + uint8_t* nm; + size_t nmlen; + /* chain continues with DNSKEY, continue in FINDKEY */ + vq->state = VAL_FINDKEY_STATE; + + /* strip off the DLV suffix from the name; could result in . */ + log_assert(dname_subdomain_c(vq->ds_rrset->rk.dname, + qstate->env->anchors->dlv_anchor->name)); + nmlen = vq->ds_rrset->rk.dname_len - + qstate->env->anchors->dlv_anchor->namelen + 1; + nm = regional_alloc_init(qstate->region, + vq->ds_rrset->rk.dname, nmlen); + if(!nm) { + log_err("Out of memory in DLVLook"); + return val_error(qstate, id); + } + nm[nmlen-1] = 0; + + vq->ds_rrset->rk.dname = nm; + vq->ds_rrset->rk.dname_len = nmlen; + + /* create a nullentry for the key so the dnskey lookup + * can be retried after a validation failure for it */ + vq->key_entry = key_entry_create_null(qstate->region, + nm, nmlen, vq->qchase.qclass, 0, 0); + if(!vq->key_entry) { + log_err("Out of memory in DLVLook"); + return val_error(qstate, id); + } + + if(!generate_request(qstate, id, vq->ds_rrset->rk.dname, + vq->ds_rrset->rk.dname_len, LDNS_RR_TYPE_DNSKEY, + vq->qchase.qclass, BIT_CD)) { + log_err("mem error generating DNSKEY request"); + return val_error(qstate, id); + } + return 0; + } else if(vq->dlv_status == dlv_there_is_no_dlv) { + /* continue with the insecure result we got */ + vq->state = VAL_FINISHED_STATE; + return 1; + } + log_assert(vq->dlv_status == dlv_ask_higher); + + /* ask higher, make sure we stay in DLV repo, below dlv_at */ + if(!dname_subdomain_c(vq->dlv_lookup_name, + qstate->env->anchors->dlv_anchor->name)) { + /* just like, there is no DLV */ + verbose(VERB_ALGO, "ask above dlv repo"); + vq->state = VAL_FINISHED_STATE; + return 1; + } + if(vq->dlv_insecure_at && !dname_subdomain_c(vq->dlv_lookup_name, + vq->dlv_insecure_at)) { + /* already checked a chain lower than dlv_lookup_name */ + verbose(VERB_ALGO, "ask above insecure endpoint"); + log_nametypeclass(VERB_ALGO, "enpt", vq->dlv_insecure_at, 0, 0); + vq->state = VAL_FINISHED_STATE; + return 1; + } + + /* check negative cache before making new request */ + if(val_neg_dlvlookup(ve->neg_cache, vq->dlv_lookup_name, + vq->dlv_lookup_name_len, vq->qchase.qclass, + qstate->env->rrset_cache, *qstate->env->now)) { + /* does not exist, go up one (go higher). */ + dname_remove_label(&vq->dlv_lookup_name, + &vq->dlv_lookup_name_len); + /* limit number of labels, limited number of recursion */ + return processDLVLookup(qstate, vq, ve, id); + } + + if(!generate_request(qstate, id, vq->dlv_lookup_name, + vq->dlv_lookup_name_len, LDNS_RR_TYPE_DLV, + vq->qchase.qclass, 0)) { + return val_error(qstate, id); + } + + return 0; +} + +/** + * Handle validator state. + * If a method returns true, the next state is started. If false, then + * processing will stop. + * @param qstate: query state. + * @param vq: validator query state. + * @param ve: validator shared global environment. + * @param id: module id. + */ +static void +val_handle(struct module_qstate* qstate, struct val_qstate* vq, + struct val_env* ve, int id) +{ + int cont = 1; + while(cont) { + verbose(VERB_ALGO, "val handle processing q with state %s", + val_state_to_string(vq->state)); + switch(vq->state) { + case VAL_INIT_STATE: + cont = processInit(qstate, vq, ve, id); + break; + case VAL_FINDKEY_STATE: + cont = processFindKey(qstate, vq, id); + break; + case VAL_VALIDATE_STATE: + cont = processValidate(qstate, vq, ve, id); + break; + case VAL_FINISHED_STATE: + cont = processFinished(qstate, vq, ve, id); + break; + case VAL_DLVLOOKUP_STATE: + cont = processDLVLookup(qstate, vq, ve, id); + break; + default: + log_warn("validator: invalid state %d", + vq->state); + cont = 0; + break; + } + } +} + +void +val_operate(struct module_qstate* qstate, enum module_ev event, int id, + struct outbound_entry* outbound) +{ + struct val_env* ve = (struct val_env*)qstate->env->modinfo[id]; + struct val_qstate* vq = (struct val_qstate*)qstate->minfo[id]; + verbose(VERB_QUERY, "validator[module %d] operate: extstate:%s " + "event:%s", id, strextstate(qstate->ext_state[id]), + strmodulevent(event)); + log_query_info(VERB_QUERY, "validator operate: query", + &qstate->qinfo); + if(vq && qstate->qinfo.qname != vq->qchase.qname) + log_query_info(VERB_QUERY, "validator operate: chased to", + &vq->qchase); + (void)outbound; + if(event == module_event_new || + (event == module_event_pass && vq == NULL)) { + /* pass request to next module, to get it */ + verbose(VERB_ALGO, "validator: pass to next module"); + qstate->ext_state[id] = module_wait_module; + return; + } + if(event == module_event_moddone) { + /* check if validation is needed */ + verbose(VERB_ALGO, "validator: nextmodule returned"); + if(!needs_validation(qstate, qstate->return_rcode, + qstate->return_msg)) { + /* no need to validate this */ + if(qstate->return_msg) + qstate->return_msg->rep->security = + sec_status_indeterminate; + qstate->ext_state[id] = module_finished; + return; + } + if(already_validated(qstate->return_msg)) { + qstate->ext_state[id] = module_finished; + return; + } + /* qclass ANY should have validation result from spawned + * queries. If we get here, it is bogus or an internal error */ + if(qstate->qinfo.qclass == LDNS_RR_CLASS_ANY) { + verbose(VERB_ALGO, "cannot validate classANY: bogus"); + if(qstate->return_msg) + qstate->return_msg->rep->security = + sec_status_bogus; + qstate->ext_state[id] = module_finished; + return; + } + /* create state to start validation */ + qstate->ext_state[id] = module_error; /* override this */ + if(!vq) { + vq = val_new(qstate, id); + if(!vq) { + log_err("validator: malloc failure"); + qstate->ext_state[id] = module_error; + return; + } + } else if(!vq->orig_msg) { + if(!val_new_getmsg(qstate, vq)) { + log_err("validator: malloc failure"); + qstate->ext_state[id] = module_error; + return; + } + } + val_handle(qstate, vq, ve, id); + return; + } + if(event == module_event_pass) { + qstate->ext_state[id] = module_error; /* override this */ + /* continue processing, since val_env exists */ + val_handle(qstate, vq, ve, id); + return; + } + log_err("validator: bad event %s", strmodulevent(event)); + qstate->ext_state[id] = module_error; + return; +} + +/** + * Evaluate the response to a priming request. + * + * @param dnskey_rrset: DNSKEY rrset (can be NULL if none) in prime reply. + * (this rrset is allocated in the wrong region, not the qstate). + * @param ta: trust anchor. + * @param qstate: qstate that needs key. + * @param id: module id. + * @return new key entry or NULL on allocation failure. + * The key entry will either contain a validated DNSKEY rrset, or + * represent a Null key (query failed, but validation did not), or a + * Bad key (validation failed). + */ +static struct key_entry_key* +primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset, + struct trust_anchor* ta, struct module_qstate* qstate, int id) +{ + struct val_env* ve = (struct val_env*)qstate->env->modinfo[id]; + struct key_entry_key* kkey = NULL; + enum sec_status sec = sec_status_unchecked; + char* reason = NULL; + int downprot = 1; + + if(!dnskey_rrset) { + log_nametypeclass(VERB_OPS, "failed to prime trust anchor -- " + "could not fetch DNSKEY rrset", + ta->name, LDNS_RR_TYPE_DNSKEY, ta->dclass); + if(qstate->env->cfg->harden_dnssec_stripped) { + errinf(qstate, "no DNSKEY rrset"); + kkey = key_entry_create_bad(qstate->region, ta->name, + ta->namelen, ta->dclass, BOGUS_KEY_TTL, + *qstate->env->now); + } else kkey = key_entry_create_null(qstate->region, ta->name, + ta->namelen, ta->dclass, NULL_KEY_TTL, + *qstate->env->now); + if(!kkey) { + log_err("out of memory: allocate fail prime key"); + return NULL; + } + return kkey; + } + /* attempt to verify with trust anchor DS and DNSKEY */ + kkey = val_verify_new_DNSKEYs_with_ta(qstate->region, qstate->env, ve, + dnskey_rrset, ta->ds_rrset, ta->dnskey_rrset, downprot, + &reason); + if(!kkey) { + log_err("out of memory: verifying prime TA"); + return NULL; + } + if(key_entry_isgood(kkey)) + sec = sec_status_secure; + else + sec = sec_status_bogus; + verbose(VERB_DETAIL, "validate keys with anchor(DS): %s", + sec_status_to_string(sec)); + + if(sec != sec_status_secure) { + log_nametypeclass(VERB_OPS, "failed to prime trust anchor -- " + "DNSKEY rrset is not secure", + ta->name, LDNS_RR_TYPE_DNSKEY, ta->dclass); + /* NOTE: in this case, we should probably reject the trust + * anchor for longer, perhaps forever. */ + if(qstate->env->cfg->harden_dnssec_stripped) { + errinf(qstate, reason); + kkey = key_entry_create_bad(qstate->region, ta->name, + ta->namelen, ta->dclass, BOGUS_KEY_TTL, + *qstate->env->now); + } else kkey = key_entry_create_null(qstate->region, ta->name, + ta->namelen, ta->dclass, NULL_KEY_TTL, + *qstate->env->now); + if(!kkey) { + log_err("out of memory: allocate null prime key"); + return NULL; + } + return kkey; + } + + log_nametypeclass(VERB_DETAIL, "Successfully primed trust anchor", + ta->name, LDNS_RR_TYPE_DNSKEY, ta->dclass); + return kkey; +} + +/** + * In inform supers, with the resulting message and rcode and the current + * keyset in the super state, validate the DS response, returning a KeyEntry. + * + * @param qstate: query state that is validating and asked for a DS. + * @param vq: validator query state + * @param id: module id. + * @param rcode: rcode result value. + * @param msg: result message (if rcode is OK). + * @param qinfo: from the sub query state, query info. + * @param ke: the key entry to return. It returns + * is_bad if the DS response fails to validate, is_null if the + * DS response indicated an end to secure space, is_good if the DS + * validated. It returns ke=NULL if the DS response indicated that the + * request wasn't a delegation point. + * @return 0 on servfail error (malloc failure). + */ +static int +ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq, + int id, int rcode, struct dns_msg* msg, struct query_info* qinfo, + struct key_entry_key** ke) +{ + struct val_env* ve = (struct val_env*)qstate->env->modinfo[id]; + char* reason = NULL; + enum val_classification subtype; + if(rcode != LDNS_RCODE_NOERROR) { + char* rc = ldns_pkt_rcode2str(rcode); + /* errors here pretty much break validation */ + verbose(VERB_DETAIL, "DS response was error, thus bogus"); + errinf(qstate, rc); + errinf(qstate, "no DS"); + free(rc); + goto return_bogus; + } + + subtype = val_classify_response(BIT_RD, qinfo, qinfo, msg->rep, 0); + if(subtype == VAL_CLASS_POSITIVE) { + struct ub_packed_rrset_key* ds; + enum sec_status sec; + ds = reply_find_answer_rrset(qinfo, msg->rep); + /* If there was no DS rrset, then we have mis-classified + * this message. */ + if(!ds) { + log_warn("internal error: POSITIVE DS response was " + "missing DS."); + errinf(qstate, "no DS record"); + goto return_bogus; + } + /* Verify only returns BOGUS or SECURE. If the rrset is + * bogus, then we are done. */ + sec = val_verify_rrset_entry(qstate->env, ve, ds, + vq->key_entry, &reason); + if(sec != sec_status_secure) { + verbose(VERB_DETAIL, "DS rrset in DS response did " + "not verify"); + errinf(qstate, reason); + goto return_bogus; + } + + /* If the DS rrset validates, we still have to make sure + * that they are usable. */ + if(!val_dsset_isusable(ds)) { + /* If they aren't usable, then we treat it like + * there was no DS. */ + *ke = key_entry_create_null(qstate->region, + qinfo->qname, qinfo->qname_len, qinfo->qclass, + ub_packed_rrset_ttl(ds), *qstate->env->now); + return (*ke) != NULL; + } + + /* Otherwise, we return the positive response. */ + log_query_info(VERB_DETAIL, "validated DS", qinfo); + *ke = key_entry_create_rrset(qstate->region, + qinfo->qname, qinfo->qname_len, qinfo->qclass, ds, + NULL, *qstate->env->now); + return (*ke) != NULL; + } else if(subtype == VAL_CLASS_NODATA || + subtype == VAL_CLASS_NAMEERROR) { + /* NODATA means that the qname exists, but that there was + * no DS. This is a pretty normal case. */ + uint32_t proof_ttl = 0; + enum sec_status sec; + + /* make sure there are NSECs or NSEC3s with signatures */ + if(!val_has_signed_nsecs(msg->rep, &reason)) { + verbose(VERB_ALGO, "no NSECs: %s", reason); + errinf(qstate, reason); + goto return_bogus; + } + + /* For subtype Name Error. + * attempt ANS 2.8.1.0 compatibility where it sets rcode + * to nxdomain, but really this is an Nodata/Noerror response. + * Find and prove the empty nonterminal in that case */ + + /* Try to prove absence of the DS with NSEC */ + sec = val_nsec_prove_nodata_dsreply( + qstate->env, ve, qinfo, msg->rep, vq->key_entry, + &proof_ttl, &reason); + switch(sec) { + case sec_status_secure: + verbose(VERB_DETAIL, "NSEC RRset for the " + "referral proved no DS."); + *ke = key_entry_create_null(qstate->region, + qinfo->qname, qinfo->qname_len, + qinfo->qclass, proof_ttl, + *qstate->env->now); + return (*ke) != NULL; + case sec_status_insecure: + verbose(VERB_DETAIL, "NSEC RRset for the " + "referral proved not a delegation point"); + *ke = NULL; + return 1; + case sec_status_bogus: + verbose(VERB_DETAIL, "NSEC RRset for the " + "referral did not prove no DS."); + errinf(qstate, reason); + goto return_bogus; + case sec_status_unchecked: + default: + /* NSEC proof did not work, try next */ + break; + } + + sec = nsec3_prove_nods(qstate->env, ve, + msg->rep->rrsets + msg->rep->an_numrrsets, + msg->rep->ns_numrrsets, qinfo, vq->key_entry, &reason); + switch(sec) { + case sec_status_insecure: + /* case insecure also continues to unsigned + * space. If nsec3-iter-count too high or + * optout, then treat below as unsigned */ + case sec_status_secure: + verbose(VERB_DETAIL, "NSEC3s for the " + "referral proved no DS."); + *ke = key_entry_create_null(qstate->region, + qinfo->qname, qinfo->qname_len, + qinfo->qclass, proof_ttl, + *qstate->env->now); + return (*ke) != NULL; + case sec_status_indeterminate: + verbose(VERB_DETAIL, "NSEC3s for the " + "referral proved no delegation"); + *ke = NULL; + return 1; + case sec_status_bogus: + verbose(VERB_DETAIL, "NSEC3s for the " + "referral did not prove no DS."); + errinf(qstate, reason); + goto return_bogus; + case sec_status_unchecked: + default: + /* NSEC3 proof did not work */ + break; + } + + /* Apparently, no available NSEC/NSEC3 proved NODATA, so + * this is BOGUS. */ + verbose(VERB_DETAIL, "DS %s ran out of options, so return " + "bogus", val_classification_to_string(subtype)); + errinf(qstate, "no DS but also no proof of that"); + goto return_bogus; + } else if(subtype == VAL_CLASS_CNAME || + subtype == VAL_CLASS_CNAMENOANSWER) { + /* if the CNAME matches the exact name we want and is signed + * properly, then also, we are sure that no DS exists there, + * much like a NODATA proof */ + enum sec_status sec; + struct ub_packed_rrset_key* cname; + cname = reply_find_rrset_section_an(msg->rep, qinfo->qname, + qinfo->qname_len, LDNS_RR_TYPE_CNAME, qinfo->qclass); + if(!cname) { + errinf(qstate, "validator classified CNAME but no " + "CNAME of the queried name for DS"); + goto return_bogus; + } + if(((struct packed_rrset_data*)cname->entry.data)->rrsig_count + == 0) { + if(msg->rep->an_numrrsets != 0 && ntohs(msg->rep-> + rrsets[0]->rk.type)==LDNS_RR_TYPE_DNAME) { + errinf(qstate, "DS got DNAME answer"); + } else { + errinf(qstate, "DS got unsigned CNAME answer"); + } + goto return_bogus; + } + sec = val_verify_rrset_entry(qstate->env, ve, cname, + vq->key_entry, &reason); + if(sec == sec_status_secure) { + verbose(VERB_ALGO, "CNAME validated, " + "proof that DS does not exist"); + /* and that it is not a referral point */ + *ke = NULL; + return 1; + } + errinf(qstate, "CNAME in DS response was not secure."); + errinf(qstate, reason); + goto return_bogus; + } else { + verbose(VERB_QUERY, "Encountered an unhandled type of " + "DS response, thus bogus."); + errinf(qstate, "no DS and"); + if(FLAGS_GET_RCODE(msg->rep->flags) != LDNS_RCODE_NOERROR) { + char* rc = ldns_pkt_rcode2str( + FLAGS_GET_RCODE(msg->rep->flags)); + errinf(qstate, rc); + free(rc); + } else errinf(qstate, val_classification_to_string(subtype)); + errinf(qstate, "message fails to prove that"); + goto return_bogus; + } +return_bogus: + *ke = key_entry_create_bad(qstate->region, qinfo->qname, + qinfo->qname_len, qinfo->qclass, + BOGUS_KEY_TTL, *qstate->env->now); + return (*ke) != NULL; +} + +/** + * Process DS response. Called from inform_supers. + * Because it is in inform_supers, the mesh itself is busy doing callbacks + * for a state that is to be deleted soon; don't touch the mesh; instead + * set a state in the super, as the super will be reactivated soon. + * Perform processing to determine what state to set in the super. + * + * @param qstate: query state that is validating and asked for a DS. + * @param vq: validator query state + * @param id: module id. + * @param rcode: rcode result value. + * @param msg: result message (if rcode is OK). + * @param qinfo: from the sub query state, query info. + * @param origin: the origin of msg. + */ +static void +process_ds_response(struct module_qstate* qstate, struct val_qstate* vq, + int id, int rcode, struct dns_msg* msg, struct query_info* qinfo, + struct sock_list* origin) +{ + struct key_entry_key* dske = NULL; + uint8_t* olds = vq->empty_DS_name; + vq->empty_DS_name = NULL; + if(!ds_response_to_ke(qstate, vq, id, rcode, msg, qinfo, &dske)) { + log_err("malloc failure in process_ds_response"); + vq->key_entry = NULL; /* make it error */ + vq->state = VAL_VALIDATE_STATE; + return; + } + if(dske == NULL) { + vq->empty_DS_name = regional_alloc_init(qstate->region, + qinfo->qname, qinfo->qname_len); + if(!vq->empty_DS_name) { + log_err("malloc failure in empty_DS_name"); + vq->key_entry = NULL; /* make it error */ + vq->state = VAL_VALIDATE_STATE; + return; + } + vq->empty_DS_len = qinfo->qname_len; + vq->chain_blacklist = NULL; + /* ds response indicated that we aren't on a delegation point. + * Keep the forState.state on FINDKEY. */ + } else if(key_entry_isgood(dske)) { + vq->ds_rrset = key_entry_get_rrset(dske, qstate->region); + if(!vq->ds_rrset) { + log_err("malloc failure in process DS"); + vq->key_entry = NULL; /* make it error */ + vq->state = VAL_VALIDATE_STATE; + return; + } + vq->chain_blacklist = NULL; /* fresh blacklist for next part*/ + /* Keep the forState.state on FINDKEY. */ + } else if(key_entry_isbad(dske) + && vq->restart_count < VAL_MAX_RESTART_COUNT) { + vq->empty_DS_name = olds; + val_blacklist(&vq->chain_blacklist, qstate->region, origin, 1); + qstate->errinf = NULL; + vq->restart_count++; + } else { + if(key_entry_isbad(dske)) { + errinf_origin(qstate, origin); + errinf_dname(qstate, "for DS", qinfo->qname); + } + /* NOTE: the reason for the DS to be not good (that is, + * either bad or null) should have been logged by + * dsResponseToKE. */ + vq->key_entry = dske; + /* The FINDKEY phase has ended, so move on. */ + vq->state = VAL_VALIDATE_STATE; + } +} + +/** + * Process DNSKEY response. Called from inform_supers. + * Sets the key entry in the state. + * Because it is in inform_supers, the mesh itself is busy doing callbacks + * for a state that is to be deleted soon; don't touch the mesh; instead + * set a state in the super, as the super will be reactivated soon. + * Perform processing to determine what state to set in the super. + * + * @param qstate: query state that is validating and asked for a DNSKEY. + * @param vq: validator query state + * @param id: module id. + * @param rcode: rcode result value. + * @param msg: result message (if rcode is OK). + * @param qinfo: from the sub query state, query info. + * @param origin: the origin of msg. + */ +static void +process_dnskey_response(struct module_qstate* qstate, struct val_qstate* vq, + int id, int rcode, struct dns_msg* msg, struct query_info* qinfo, + struct sock_list* origin) +{ + struct val_env* ve = (struct val_env*)qstate->env->modinfo[id]; + struct key_entry_key* old = vq->key_entry; + struct ub_packed_rrset_key* dnskey = NULL; + int downprot; + char* reason = NULL; + + if(rcode == LDNS_RCODE_NOERROR) + dnskey = reply_find_answer_rrset(qinfo, msg->rep); + + if(dnskey == NULL) { + /* bad response */ + verbose(VERB_DETAIL, "Missing DNSKEY RRset in response to " + "DNSKEY query."); + if(vq->restart_count < VAL_MAX_RESTART_COUNT) { + val_blacklist(&vq->chain_blacklist, qstate->region, + origin, 1); + qstate->errinf = NULL; + vq->restart_count++; + return; + } + vq->key_entry = key_entry_create_bad(qstate->region, + qinfo->qname, qinfo->qname_len, qinfo->qclass, + BOGUS_KEY_TTL, *qstate->env->now); + if(!vq->key_entry) { + log_err("alloc failure in missing dnskey response"); + /* key_entry is NULL for failure in Validate */ + } + errinf(qstate, "No DNSKEY record"); + errinf_origin(qstate, origin); + errinf_dname(qstate, "for key", qinfo->qname); + vq->state = VAL_VALIDATE_STATE; + return; + } + if(!vq->ds_rrset) { + log_err("internal error: no DS rrset for new DNSKEY response"); + vq->key_entry = NULL; + vq->state = VAL_VALIDATE_STATE; + return; + } + downprot = 1; + vq->key_entry = val_verify_new_DNSKEYs(qstate->region, qstate->env, + ve, dnskey, vq->ds_rrset, downprot, &reason); + + if(!vq->key_entry) { + log_err("out of memory in verify new DNSKEYs"); + vq->state = VAL_VALIDATE_STATE; + return; + } + /* If the key entry isBad or isNull, then we can move on to the next + * state. */ + if(!key_entry_isgood(vq->key_entry)) { + if(key_entry_isbad(vq->key_entry)) { + if(vq->restart_count < VAL_MAX_RESTART_COUNT) { + val_blacklist(&vq->chain_blacklist, + qstate->region, origin, 1); + qstate->errinf = NULL; + vq->restart_count++; + vq->key_entry = old; + return; + } + verbose(VERB_DETAIL, "Did not match a DS to a DNSKEY, " + "thus bogus."); + errinf(qstate, reason); + errinf_origin(qstate, origin); + errinf_dname(qstate, "for key", qinfo->qname); + } + vq->chain_blacklist = NULL; + vq->state = VAL_VALIDATE_STATE; + return; + } + vq->chain_blacklist = NULL; + qstate->errinf = NULL; + + /* The DNSKEY validated, so cache it as a trusted key rrset. */ + key_cache_insert(ve->kcache, vq->key_entry, qstate); + + /* If good, we stay in the FINDKEY state. */ + log_query_info(VERB_DETAIL, "validated DNSKEY", qinfo); +} + +/** + * Process prime response + * Sets the key entry in the state. + * + * @param qstate: query state that is validating and primed a trust anchor. + * @param vq: validator query state + * @param id: module id. + * @param rcode: rcode result value. + * @param msg: result message (if rcode is OK). + * @param origin: the origin of msg. + */ +static void +process_prime_response(struct module_qstate* qstate, struct val_qstate* vq, + int id, int rcode, struct dns_msg* msg, struct sock_list* origin) +{ + struct val_env* ve = (struct val_env*)qstate->env->modinfo[id]; + struct ub_packed_rrset_key* dnskey_rrset = NULL; + struct trust_anchor* ta = anchor_find(qstate->env->anchors, + vq->trust_anchor_name, vq->trust_anchor_labs, + vq->trust_anchor_len, vq->qchase.qclass); + if(!ta) { + /* trust anchor revoked, restart with less anchors */ + vq->state = VAL_INIT_STATE; + if(!vq->trust_anchor_name) + vq->state = VAL_VALIDATE_STATE; /* break a loop */ + vq->trust_anchor_name = NULL; + return; + } + /* Fetch and validate the keyEntry that corresponds to the + * current trust anchor. */ + if(rcode == LDNS_RCODE_NOERROR) { + dnskey_rrset = reply_find_rrset_section_an(msg->rep, + ta->name, ta->namelen, LDNS_RR_TYPE_DNSKEY, + ta->dclass); + } + if(ta->autr) { + if(!autr_process_prime(qstate->env, ve, ta, dnskey_rrset)) { + /* trust anchor revoked, restart with less anchors */ + vq->state = VAL_INIT_STATE; + vq->trust_anchor_name = NULL; + return; + } + } + vq->key_entry = primeResponseToKE(dnskey_rrset, ta, qstate, id); + lock_basic_unlock(&ta->lock); + if(vq->key_entry) { + if(key_entry_isbad(vq->key_entry) + && vq->restart_count < VAL_MAX_RESTART_COUNT) { + val_blacklist(&vq->chain_blacklist, qstate->region, + origin, 1); + qstate->errinf = NULL; + vq->restart_count++; + vq->key_entry = NULL; + vq->state = VAL_INIT_STATE; + return; + } + vq->chain_blacklist = NULL; + errinf_origin(qstate, origin); + errinf_dname(qstate, "for trust anchor", ta->name); + /* store the freshly primed entry in the cache */ + key_cache_insert(ve->kcache, vq->key_entry, qstate); + } + + /* If the result of the prime is a null key, skip the FINDKEY state.*/ + if(!vq->key_entry || key_entry_isnull(vq->key_entry) || + key_entry_isbad(vq->key_entry)) { + vq->state = VAL_VALIDATE_STATE; + } + /* the qstate will be reactivated after inform_super is done */ +} + +/** + * Process DLV response. Called from inform_supers. + * Because it is in inform_supers, the mesh itself is busy doing callbacks + * for a state that is to be deleted soon; don't touch the mesh; instead + * set a state in the super, as the super will be reactivated soon. + * Perform processing to determine what state to set in the super. + * + * @param qstate: query state that is validating and asked for a DLV. + * @param vq: validator query state + * @param id: module id. + * @param rcode: rcode result value. + * @param msg: result message (if rcode is OK). + * @param qinfo: from the sub query state, query info. + */ +static void +process_dlv_response(struct module_qstate* qstate, struct val_qstate* vq, + int id, int rcode, struct dns_msg* msg, struct query_info* qinfo) +{ + struct val_env* ve = (struct val_env*)qstate->env->modinfo[id]; + + verbose(VERB_ALGO, "process dlv response to super"); + if(rcode != LDNS_RCODE_NOERROR) { + /* lookup failed, set in vq to give up */ + vq->dlv_status = dlv_error; + verbose(VERB_ALGO, "response is error"); + return; + } + if(msg->rep->security != sec_status_secure) { + vq->dlv_status = dlv_error; + verbose(VERB_ALGO, "response is not secure, %s", + sec_status_to_string(msg->rep->security)); + return; + } + /* was the lookup a success? validated DLV? */ + if(FLAGS_GET_RCODE(msg->rep->flags) == LDNS_RCODE_NOERROR && + msg->rep->an_numrrsets == 1 && + msg->rep->security == sec_status_secure && + ntohs(msg->rep->rrsets[0]->rk.type) == LDNS_RR_TYPE_DLV && + ntohs(msg->rep->rrsets[0]->rk.rrset_class) == qinfo->qclass && + query_dname_compare(msg->rep->rrsets[0]->rk.dname, + vq->dlv_lookup_name) == 0) { + /* yay! it is just like a DS */ + vq->ds_rrset = (struct ub_packed_rrset_key*) + regional_alloc_init(qstate->region, + msg->rep->rrsets[0], sizeof(*vq->ds_rrset)); + if(!vq->ds_rrset) { + log_err("out of memory in process_dlv"); + return; + } + vq->ds_rrset->entry.key = vq->ds_rrset; + vq->ds_rrset->rk.dname = (uint8_t*)regional_alloc_init( + qstate->region, vq->ds_rrset->rk.dname, + vq->ds_rrset->rk.dname_len); + if(!vq->ds_rrset->rk.dname) { + log_err("out of memory in process_dlv"); + vq->dlv_status = dlv_error; + return; + } + vq->ds_rrset->entry.data = regional_alloc_init(qstate->region, + vq->ds_rrset->entry.data, + packed_rrset_sizeof(vq->ds_rrset->entry.data)); + if(!vq->ds_rrset->entry.data) { + log_err("out of memory in process_dlv"); + vq->dlv_status = dlv_error; + return; + } + packed_rrset_ptr_fixup(vq->ds_rrset->entry.data); + /* make vq do a DNSKEY query next up */ + vq->dlv_status = dlv_success; + return; + } + /* store NSECs into negative cache */ + val_neg_addreply(ve->neg_cache, msg->rep); + + /* was the lookup a failure? + * if we have to go up into the DLV for a higher DLV anchor + * then set this in the vq, so it can make queries when activated. + * See if the NSECs indicate that we should look for higher DLV + * or, that there is no DLV securely */ + if(!val_nsec_check_dlv(qinfo, msg->rep, &vq->dlv_lookup_name, + &vq->dlv_lookup_name_len)) { + vq->dlv_status = dlv_error; + verbose(VERB_ALGO, "nsec error"); + return; + } + if(!dname_subdomain_c(vq->dlv_lookup_name, + qstate->env->anchors->dlv_anchor->name)) { + vq->dlv_status = dlv_there_is_no_dlv; + return; + } + vq->dlv_status = dlv_ask_higher; +} + +/* + * inform validator super. + * + * @param qstate: query state that finished. + * @param id: module id. + * @param super: the qstate to inform. + */ +void +val_inform_super(struct module_qstate* qstate, int id, + struct module_qstate* super) +{ + struct val_qstate* vq = (struct val_qstate*)super->minfo[id]; + log_query_info(VERB_ALGO, "validator: inform_super, sub is", + &qstate->qinfo); + log_query_info(VERB_ALGO, "super is", &super->qinfo); + if(!vq) { + verbose(VERB_ALGO, "super: has no validator state"); + return; + } + if(vq->wait_prime_ta) { + vq->wait_prime_ta = 0; + process_prime_response(super, vq, id, qstate->return_rcode, + qstate->return_msg, qstate->reply_origin); + return; + } + if(qstate->qinfo.qtype == LDNS_RR_TYPE_DS) { + process_ds_response(super, vq, id, qstate->return_rcode, + qstate->return_msg, &qstate->qinfo, + qstate->reply_origin); + return; + } else if(qstate->qinfo.qtype == LDNS_RR_TYPE_DNSKEY) { + process_dnskey_response(super, vq, id, qstate->return_rcode, + qstate->return_msg, &qstate->qinfo, + qstate->reply_origin); + return; + } else if(qstate->qinfo.qtype == LDNS_RR_TYPE_DLV) { + process_dlv_response(super, vq, id, qstate->return_rcode, + qstate->return_msg, &qstate->qinfo); + return; + } + log_err("internal error in validator: no inform_supers possible"); +} + +void +val_clear(struct module_qstate* qstate, int id) +{ + if(!qstate) + return; + /* everything is allocated in the region, so assign NULL */ + qstate->minfo[id] = NULL; +} + +size_t +val_get_mem(struct module_env* env, int id) +{ + struct val_env* ve = (struct val_env*)env->modinfo[id]; + if(!ve) + return 0; + return sizeof(*ve) + key_cache_get_mem(ve->kcache) + + val_neg_get_mem(ve->neg_cache) + + sizeof(size_t)*2*ve->nsec3_keyiter_count; +} + +/** + * The validator function block + */ +static struct module_func_block val_block = { + "validator", + &val_init, &val_deinit, &val_operate, &val_inform_super, &val_clear, + &val_get_mem +}; + +struct module_func_block* +val_get_funcblock(void) +{ + return &val_block; +} + +const char* +val_state_to_string(enum val_state state) +{ + switch(state) { + case VAL_INIT_STATE: return "VAL_INIT_STATE"; + case VAL_FINDKEY_STATE: return "VAL_FINDKEY_STATE"; + case VAL_VALIDATE_STATE: return "VAL_VALIDATE_STATE"; + case VAL_FINISHED_STATE: return "VAL_FINISHED_STATE"; + case VAL_DLVLOOKUP_STATE: return "VAL_DLVLOOKUP_STATE"; + } + return "UNKNOWN VALIDATOR STATE"; +} + diff --git a/validator/validator.h b/validator/validator.h new file mode 100644 index 00000000000..18e905efcd2 --- /dev/null +++ b/validator/validator.h @@ -0,0 +1,294 @@ +/* + * validator/validator.h - secure validator DNS query response module + * + * 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains a module that performs validation of DNS queries. + * According to RFC 4034. + */ + +#ifndef VALIDATOR_VALIDATOR_H +#define VALIDATOR_VALIDATOR_H +#include "util/module.h" +#include "util/data/msgreply.h" +#include "validator/val_utils.h" +struct val_anchors; +struct key_cache; +struct key_entry_key; +struct val_neg_cache; +struct config_strlist; + +/** + * This is the TTL to use when a trust anchor fails to prime. A trust anchor + * will be primed no more often than this interval. Used when harden- + * dnssec-stripped is off and the trust anchor fails. + */ +#define NULL_KEY_TTL 900 /* seconds */ + +/** + * TTL for bogus key entries. When a DS or DNSKEY fails in the chain of + * trust the entire zone for that name is blacked out for this TTL. + */ +#define BOGUS_KEY_TTL 900 /* seconds */ + +/** max number of query restarts, number of IPs to probe */ +#define VAL_MAX_RESTART_COUNT 5 + +/** + * Global state for the validator. + */ +struct val_env { + /** key cache; these are validated keys. trusted keys only + * end up here after being primed. */ + struct key_cache* kcache; + + /** aggressive negative cache. index into NSECs in rrset cache. */ + struct val_neg_cache* neg_cache; + + /** for debug testing a fixed validation date can be entered. + * if 0, current time is used for rrsig validation */ + int32_t date_override; + + /** clock skew min for signatures */ + int32_t skew_min; + + /** clock skew max for signatures */ + int32_t skew_max; + + /** TTL for bogus data; used instead of untrusted TTL from data. + * Bogus data will not be verified more often than this interval. + * seconds. */ + uint32_t bogus_ttl; + + /** If set, the validator should clean the additional section of + * secure messages. + */ + int clean_additional; + + /** + * If set, the validator will not make messages bogus, instead + * indeterminate is issued, so that no clients receive SERVFAIL. + * This allows an operator to run validation 'shadow' without + * hurting responses to clients. + */ + int permissive_mode; + + /** + * Number of entries in the NSEC3 maximum iteration count table. + * Keep this table short, and sorted by size + */ + int nsec3_keyiter_count; + + /** + * NSEC3 maximum iteration count per signing key size. + * This array contains key size values (in increasing order) + */ + size_t* nsec3_keysize; + + /** + * NSEC3 maximum iteration count per signing key size. + * This array contains the maximum iteration count for the keysize + * in the keysize array. + */ + size_t* nsec3_maxiter; + + /** lock on bogus counter */ + lock_basic_t bogus_lock; + /** number of times rrsets marked bogus */ + size_t num_rrset_bogus; +}; + +/** + * State of the validator for a query. + */ +enum val_state { + /** initial state for validation */ + VAL_INIT_STATE = 0, + /** find the proper keys for validation, follow trust chain */ + VAL_FINDKEY_STATE, + /** validate the answer, using found key entry */ + VAL_VALIDATE_STATE, + /** finish up */ + VAL_FINISHED_STATE, + /** DLV lookup state, processing DLV queries */ + VAL_DLVLOOKUP_STATE +}; + +/** + * Per query state for the validator module. + */ +struct val_qstate { + /** + * State of the validator module. + */ + enum val_state state; + + /** + * The original message we have been given to validate. + */ + struct dns_msg* orig_msg; + + /** + * The query restart count + */ + int restart_count; + /** The blacklist saved for chainoftrust elements */ + struct sock_list* chain_blacklist; + + /** + * The query name we have chased to; qname after following CNAMEs + */ + struct query_info qchase; + + /** + * The chased reply, extract from original message. Can be: + * o CNAME + * o DNAME + CNAME + * o answer + * plus authority, additional (nsecs) that have same signature. + */ + struct reply_info* chase_reply; + + /** + * The cname skip value; the number of rrsets that have been skipped + * due to chasing cnames. This is the offset into the + * orig_msg->rep->rrsets array, into the answer section. + * starts at 0 - for the full original message. + * if it is >0 - qchase followed the cname, chase_reply setup to be + * that message and relevant authority rrsets. + * + * The skip is also used for referral messages, where it will + * range from 0, over the answer, authority and additional sections. + */ + size_t rrset_skip; + + /** trust anchor name */ + uint8_t* trust_anchor_name; + /** trust anchor labels */ + int trust_anchor_labs; + /** trust anchor length */ + size_t trust_anchor_len; + + /** the DS rrset */ + struct ub_packed_rrset_key* ds_rrset; + + /** domain name for empty nonterminal detection */ + uint8_t* empty_DS_name; + /** length of empty_DS_name */ + size_t empty_DS_len; + + /** the current key entry */ + struct key_entry_key* key_entry; + + /** subtype */ + enum val_classification subtype; + + /** signer name */ + uint8_t* signer_name; + /** length of signer_name */ + size_t signer_len; + + /** true if this state is waiting to prime a trust anchor */ + int wait_prime_ta; + + /** have we already checked the DLV? */ + int dlv_checked; + /** The name for which the DLV is looked up. For the current message + * or for the current RRset (for CNAME, REFERRAL types). + * If there is signer name, that may be it, else a domain name */ + uint8_t* dlv_lookup_name; + /** length of dlv lookup name */ + size_t dlv_lookup_name_len; + /** Name at which chain of trust stopped with insecure, starting DLV + * DLV must result in chain going further down */ + uint8_t* dlv_insecure_at; + /** length of dlv insecure point name */ + size_t dlv_insecure_at_len; + /** status of DLV lookup. Indication to VAL_DLV_STATE what to do */ + enum dlv_status { + dlv_error, /* server failure */ + dlv_success, /* got a DLV */ + dlv_ask_higher, /* ask again */ + dlv_there_is_no_dlv /* got no DLV, sure of it */ + } dlv_status; +}; + +/** + * Get the validator function block. + * @return: function block with function pointers to validator methods. + */ +struct module_func_block* val_get_funcblock(void); + +/** + * Get validator state as a string + * @param state: to convert + * @return constant string that is printable. + */ +const char* val_state_to_string(enum val_state state); + +/** validator init */ +int val_init(struct module_env* env, int id); + +/** validator deinit */ +void val_deinit(struct module_env* env, int id); + +/** validator operate on a query */ +void val_operate(struct module_qstate* qstate, enum module_ev event, int id, + struct outbound_entry* outbound); + +/** + * inform validator super. + * + * @param qstate: query state that finished. + * @param id: module id. + * @param super: the qstate to inform. + */ +void val_inform_super(struct module_qstate* qstate, int id, + struct module_qstate* super); + +/** validator cleanup query state */ +void val_clear(struct module_qstate* qstate, int id); + +/** + * Debug helper routine that assists worker in determining memory in + * use. + * @param env: module environment + * @param id: module id. + * @return memory in use in bytes. + */ +size_t val_get_mem(struct module_env* env, int id); + +#endif /* VALIDATOR_VALIDATOR_H */ diff --git a/winrc/README.txt b/winrc/README.txt new file mode 100644 index 00000000000..dbb6d7fdc9d --- /dev/null +++ b/winrc/README.txt @@ -0,0 +1,110 @@ +README for Unbound on Windows. + +(C) 2009, W.C.A. Wijngaards, NLnet Labs. + +See LICENSE for the license text file. + + ++++ Introduction + +Unbound is a recursive DNS server. It does caching, full recursion, stub +recursion, DNSSEC validation, NSEC3, IPv6. More information can be found +at the http://unbound.net site. Unbound has been built and tested on +Windows XP, Vista and 7. + +At http://unbound.net/documentation is an install and configuration manual +for windows. + +email: unbound-bugs@nlnetlabs.nl + + ++++ How to use it + +In ControlPanels\SystemTasks\Services you can start/stop the daemon. +In ControlPanels\SystemTasks\Logbooks you can see log entries (unless you +configured unbound to log to file). + +By default the daemon provides service only to localhost. See the manual +on how to change that (you need to edit the config file). + +To change options, edit the service.conf file. The example.conf file +contains information on the various configuration options. The config +file is the same as on Unix. The options log-time-ascii, chroot, username +and pidfile are not supported on windows. + + ++++ How to compile + +Unbound is open source under the BSD license. You can compile it yourself. + +1. Install MinGW and MSYS. http://www.mingw.org +This is a free, open source, compiler and build environment. +Note, if your username contains a space, create a directory +C:\msys\...\home\user to work in (click on MSYS; type: mkdir /home/user ). + +2. Install openssl, or compile it yourself. http://www.openssl.org +Ldns and unbound need the header files and libraries. Static linking makes +things easier. This is an open source library for cryptographic functions. + +3. Compile LDNS +Get the source code tarball http://nlnetlabs.nl/ldns +Move it into the C:\msys\...\home\user directory. +Double click on the MSYS icon and give these commands +$ cd /home/user +$ tar xzvf ldns-xxx.tar.gz +$ cd ldns-xxx +$ ./configure +If you compiled openssl yourself, pass --with-ssl=../openssl-xxx +$ make + +4. Compile Unbound +Get the source code tarball http://unbound.net +Move it into the C:\msys\...\home\user directory. +Double click on the MSYS icon and give these commands +$ cd /home/user +$ tar xzvf unbound-xxx.tar.gz +$ cd unbound-xxx +$ ./configure --enable-static-exe --with-ldns=../ldns-xxx +If you compiled openssl yourself, pass --with-ssl=../openssl-xxx too. +If you compiled libexpat yourself, pass --with-libexpat=../expat-install too. +The configure options for libevent or threads are not applicable for +windows, because builtin alternatives for the windows platform are used. +$ make +And you have unbound.exe + +If you run unbound-service-install.exe (double click in the explorer), +unbound is installed as a service in the controlpanels\systemtasks\services, +from the current directory. unbound-service-remove.exe uninstalls the service. + +Unbound and its utilities also work from the commandline (like on unix) if +you prefer. + + ++++ Cross compile + +You can crosscompile unbound. This results in .exe files. +Install the packages: mingw32-binutils mingw32-cpp mingw32-filesystem +mingw32-gcc mingw32-openssl mingw32-openssl-static mingw32-runtime zip +mingw32-termcap mingw32-w32api mingw32-zlib mingw32-zlib-static mingw32-nsis +(package names for fedora 11). + +For dynamic linked executables +$ mingw32-configure +$ make +$ mkdir /home/user/installdir +$ make install DESTDIR=/home/user/installdir +Find the dlls and exes in /home/user/installdir and +crypto in /usr/i686-pc-mingw32/sys-root/mingw/bin + +For static linked executables +Use --enable-staticexe for mingw32-configure, see above. Or use makedist.sh, +copy System.dll from the windows dist of NSIS to /usr/share/nsis/Plugins/ +Then do ./makedist.sh -w and the setup.exe is created using nsis. + + ++++ CREDITS + +Unbound was written in portable C by Wouter Wijngaards (NLnet Labs). +See the CREDITS file in the source package for more contributor information. +Email unbound-bugs@nlnetlabs.nl + diff --git a/winrc/anchor-update.c b/winrc/anchor-update.c new file mode 100644 index 00000000000..bdca174afdf --- /dev/null +++ b/winrc/anchor-update.c @@ -0,0 +1,159 @@ +/* + * winrc/anchor-update.c - windows trust anchor update util + * + * Copyright (c) 2009, 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file is made because contrib/update-anchor.sh does not work on + * windows (no shell). + */ +#include "config.h" +#include +#include "libunbound/unbound.h" + +/** usage */ +static void +usage(void) +{ + printf("usage: { name-of-domain filename }+ \n"); + printf("exit codes: 0 anchors updated, 1 no changes, 2 errors.\n"); + exit(1); +} + +/** fatal exit */ +static void fatal(const char* str) +{ + printf("fatal error: %s\n", str); + exit(2); +} + +/** lookup data */ +static struct ub_result* +do_lookup(struct ub_ctx* ctx, char* domain) +{ + struct ub_result* result = NULL; + int r; + r = ub_resolve(ctx, domain, LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN, + &result); + if(r) { + printf("failed to lookup %s\n", ub_strerror(r)); + fatal("ub_resolve failed"); + } + if(!result->havedata && (result->rcode == LDNS_RCODE_SERVFAIL || + result->rcode == LDNS_RCODE_REFUSED)) + return NULL; /* probably no internet connection */ + if(!result->havedata) fatal("result has no data"); + if(!result->secure) fatal("result is not secure"); + return result; +} + +/** get answer into ldns rr list */ +static ldns_rr_list* +result2answer(struct ub_result* result) +{ + ldns_pkt* p = NULL; + ldns_rr_list* a; + if(ldns_wire2pkt(&p, result->answer_packet, (size_t)result->answer_len) + != LDNS_STATUS_OK) + return NULL; + a = ldns_pkt_answer(p); + ldns_pkt_set_answer(p, NULL); + ldns_pkt_free(p); + return a; +} + +/** print result to file */ +static void +do_print(struct ub_result* result, char* file) +{ + FILE* out; + ldns_rr_list* list = result2answer(result); + if(!list) fatal("result2answer failed"); + + out = fopen(file, "w"); + if(!out) { + perror(file); + fatal("fopen failed"); + } + ldns_rr_list_print(out, list); + fclose(out); + ldns_rr_list_deep_free(list); +} + +/** update domain to file */ +static int +do_update(char* domain, char* file) +{ + struct ub_ctx* ctx; + struct ub_result* result; + int r; + printf("updating %s to %s\n", domain, file); + ctx = ub_ctx_create(); + if(!ctx) fatal("ub_ctx_create failed"); + + if((r=ub_ctx_add_ta_file(ctx, file))) { + printf("%s\n", ub_strerror(r)); + fatal("ub_ctx_add_ta_file failed"); + } + + if(!(result=do_lookup(ctx, domain))) { + ub_ctx_delete(ctx); + return 1; + } + ub_ctx_delete(ctx); + do_print(result, file); + ub_resolve_free(result); + return 0; +} + +/** anchor update main */ +int main(int argc, char** argv) +{ + int retcode = 1; + if(argc == 1) { + usage(); + } + argc--; + argv++; + while(argc > 0) { + int r = do_update(argv[0], argv[1]); + if(r == 0) retcode = 0; + + /* next */ + argc-=2; + argv+=2; + } + return retcode; +} diff --git a/winrc/combined.ico b/winrc/combined.ico new file mode 100644 index 0000000000000000000000000000000000000000..aa65d11e2e6f1bc7b94fb338204b08f6de018186 GIT binary patch literal 10534 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 aBdK0bF+)6sU{&#N5Pezw5B>l3z<&WINN^JX literal 0 HcmV?d00001 diff --git a/winrc/gen_msg.bin b/winrc/gen_msg.bin new file mode 100644 index 0000000000000000000000000000000000000000..6e560057c26813430527e8906f6388206e0c7e82 GIT binary patch literal 116 zcmZQ!U|?WmU{nBM6Cj(3fiVGuU4U$62F3*-90FvsFfcv<;S?ZS0H{Ni!H|KMfeXkZ Goeu!`+XqPi literal 0 HcmV?d00001 diff --git a/winrc/gen_msg.mc b/winrc/gen_msg.mc new file mode 100644 index 00000000000..bde32176e8b --- /dev/null +++ b/winrc/gen_msg.mc @@ -0,0 +1,44 @@ +; for Unbound +; severity default Success Informational Warning Error + +; .bin file created with: +; "/c/Program Files/Microsoft SDKs/Windows/v6.1/Bin/mc" -c gen_msg.mc +; mv MSG00001.bin gen_msg.bin +; rm gen_msg.h +; and pasted contents of gen_msg.rc into rsrc_unbound.rc + +FacilityNames=(Server=0x1) +MessageIdTypeDef=DWORD + +MessageID=0x1 +Severity=Success +Facility=Server +SymbolicName=MSG_GENERIC_SUCCESS +Language=English +%1 +. + +MessageID=0x2 +Severity=Informational +Facility=Server +SymbolicName=MSG_GENERIC_INFO +Language=English +%1 +. + +MessageID=0x3 +Severity=Warning +Facility=Server +SymbolicName=MSG_GENERIC_WARN +Language=English +%1 +. + +MessageID=0x4 +Severity=Error +Facility=Server +SymbolicName=MSG_GENERIC_ERR +Language=English +%1 +. + diff --git a/winrc/rsrc_anchorupd.rc b/winrc/rsrc_anchorupd.rc new file mode 100644 index 00000000000..2419bfad5c4 --- /dev/null +++ b/winrc/rsrc_anchorupd.rc @@ -0,0 +1,40 @@ +/* + Unbound resource file for windows. For use with windres +*/ +#include "winver.h" +#include "config.h" + +1 ICON "winrc/combined.ico" + +1 VERSIONINFO +FILEVERSION RSRC_PACKAGE_VERSION +PRODUCTVERSION RSRC_PACKAGE_VERSION +FILEFLAGSMASK 0 +FILEFLAGS 0 +FILEOS VOS__WINDOWS32 +FILETYPE VFT_APP +FILESUBTYPE 0 +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + BEGIN + VALUE "CompanyName", "NLnet Labs" + VALUE "FileDescription", "Unbound trust anchor tool" + VALUE "FileVersion", PACKAGE_VERSION + VALUE "InternalName", "anchor-update" + VALUE "OriginalFilename", "anchor-update.exe" + VALUE "ProductName", "unbound" + VALUE "ProductVersion", PACKAGE_VERSION + VALUE "LegalCopyright", "(C) 2009 NLnet Labs. Source is BSD licensed." + END + END + BLOCK "VarFileInfo" + BEGIN + /* English(409), windows ANSI codepage (1252) */ + VALUE "Translation", 0x409, 0x1252 + END +END + +/* vista administrator access, show UAC prompt */ +1 RT_MANIFEST "winrc/vista_user.manifest" diff --git a/winrc/rsrc_svcinst.rc b/winrc/rsrc_svcinst.rc new file mode 100644 index 00000000000..cb325f4c493 --- /dev/null +++ b/winrc/rsrc_svcinst.rc @@ -0,0 +1,45 @@ +/* + Unbound resource file for windows. For use with windres +*/ +#include "winver.h" +#include "config.h" + +1 ICON "winrc/combined.ico" + +1 VERSIONINFO +FILEVERSION RSRC_PACKAGE_VERSION +PRODUCTVERSION RSRC_PACKAGE_VERSION +FILEFLAGSMASK 0 +FILEFLAGS 0 +FILEOS VOS__WINDOWS32 +FILETYPE VFT_APP +FILESUBTYPE 0 +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + BEGIN + VALUE "CompanyName", "NLnet Labs" + VALUE "FileDescription", "Unbound Service Install Util" + VALUE "FileVersion", PACKAGE_VERSION + VALUE "InternalName", "unbound-service-install" + VALUE "OriginalFilename", "unbound-service-install.exe" + VALUE "ProductName", "unbound" + VALUE "ProductVersion", PACKAGE_VERSION + VALUE "LegalCopyright", "(C) 2009 NLnet Labs. Source is BSD licensed." + END + END + BLOCK "VarFileInfo" + BEGIN + /* English(409), windows ANSI codepage (1252) */ + VALUE "Translation", 0x409, 0x1252 + END +END + +/* error message formats */ +LANGUAGE 0x9,0x1 +1 11 "winrc/gen_msg.bin" + +/* vista administrator access, show UAC prompt */ +1 RT_MANIFEST "winrc/vista_admin.manifest" + diff --git a/winrc/rsrc_svcuninst.rc b/winrc/rsrc_svcuninst.rc new file mode 100644 index 00000000000..ecff8dcd385 --- /dev/null +++ b/winrc/rsrc_svcuninst.rc @@ -0,0 +1,45 @@ +/* + Unbound resource file for windows. For use with windres +*/ +#include "winver.h" +#include "config.h" + +1 ICON "winrc/combined.ico" + +1 VERSIONINFO +FILEVERSION RSRC_PACKAGE_VERSION +PRODUCTVERSION RSRC_PACKAGE_VERSION +FILEFLAGSMASK 0 +FILEFLAGS 0 +FILEOS VOS__WINDOWS32 +FILETYPE VFT_APP +FILESUBTYPE 0 +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + BEGIN + VALUE "CompanyName", "NLnet Labs" + VALUE "FileDescription", "Unbound Service Remove Util" + VALUE "FileVersion", PACKAGE_VERSION + VALUE "InternalName", "unbound-service-remove" + VALUE "OriginalFilename", "unbound-service-remove.exe" + VALUE "ProductName", "unbound" + VALUE "ProductVersion", PACKAGE_VERSION + VALUE "LegalCopyright", "(C) 2009 NLnet Labs. Source is BSD licensed." + END + END + BLOCK "VarFileInfo" + BEGIN + /* English(409), windows ANSI codepage (1252) */ + VALUE "Translation", 0x409, 0x1252 + END +END + +/* error message formats */ +LANGUAGE 0x9,0x1 +1 11 "winrc/gen_msg.bin" + +/* vista administrator access, show UAC prompt */ +1 RT_MANIFEST "winrc/vista_admin.manifest" + diff --git a/winrc/rsrc_unbound.rc b/winrc/rsrc_unbound.rc new file mode 100644 index 00000000000..cc05d0eeb51 --- /dev/null +++ b/winrc/rsrc_unbound.rc @@ -0,0 +1,48 @@ +/* + Unbound resource file for windows. For use with windres +*/ +#include "winver.h" +#include "config.h" + +1 ICON "winrc/combined.ico" +/* +1 ICON "winrc/unbound64.ico" +2 ICON "winrc/unbound48.ico" +3 ICON "winrc/unbound32.ico" +4 ICON "winrc/unbound16.ico" +*/ + +1 VERSIONINFO +FILEVERSION RSRC_PACKAGE_VERSION +PRODUCTVERSION RSRC_PACKAGE_VERSION +FILEFLAGSMASK 0 +FILEFLAGS 0 +FILEOS VOS__WINDOWS32 +FILETYPE VFT_APP +FILESUBTYPE 0 +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + BEGIN + VALUE "CompanyName", "NLnet Labs" + VALUE "FileDescription", "Unbound DNS Server" + VALUE "FileVersion", PACKAGE_VERSION + VALUE "InternalName", "unbound" + VALUE "OriginalFilename", "unbound.exe" + VALUE "ProductName", "unbound" + VALUE "ProductVersion", PACKAGE_VERSION + VALUE "LegalCopyright", "(C) 2009 NLnet Labs. Source is BSD licensed." + END + END + BLOCK "VarFileInfo" + BEGIN + /* English(409), windows ANSI codepage (1252) */ + VALUE "Translation", 0x409, 0x1252 + END +END + +/* error message formats */ +LANGUAGE 0x9,0x1 +/* id=1 type=RT_MESSAGETABLE */ +1 11 "winrc/gen_msg.bin" diff --git a/winrc/rsrc_unbound_anchor.rc b/winrc/rsrc_unbound_anchor.rc new file mode 100644 index 00000000000..76b96b78563 --- /dev/null +++ b/winrc/rsrc_unbound_anchor.rc @@ -0,0 +1,37 @@ +/* + Unbound resource file for windows. For use with windres +*/ +#include "winver.h" +#include "config.h" + +1 ICON "winrc/combined.ico" + +1 VERSIONINFO +FILEVERSION RSRC_PACKAGE_VERSION +PRODUCTVERSION RSRC_PACKAGE_VERSION +FILEFLAGSMASK 0 +FILEFLAGS 0 +FILEOS VOS__WINDOWS32 +FILETYPE VFT_APP +FILESUBTYPE 0 +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + BEGIN + VALUE "CompanyName", "NLnet Labs" + VALUE "FileDescription", "Unbound Anchor Utility" + VALUE "FileVersion", PACKAGE_VERSION + VALUE "InternalName", "unbound-anchor" + VALUE "OriginalFilename", "unbound-anchor.exe" + VALUE "ProductName", "unbound" + VALUE "ProductVersion", PACKAGE_VERSION + VALUE "LegalCopyright", "(C) 2010 NLnet Labs. Source is BSD licensed." + END + END + BLOCK "VarFileInfo" + BEGIN + /* English(409), windows ANSI codepage (1252) */ + VALUE "Translation", 0x409, 0x1252 + END +END diff --git a/winrc/rsrc_unbound_checkconf.rc b/winrc/rsrc_unbound_checkconf.rc new file mode 100644 index 00000000000..de61900bffb --- /dev/null +++ b/winrc/rsrc_unbound_checkconf.rc @@ -0,0 +1,37 @@ +/* + Unbound resource file for windows. For use with windres +*/ +#include "winver.h" +#include "config.h" + +1 ICON "winrc/combined.ico" + +1 VERSIONINFO +FILEVERSION RSRC_PACKAGE_VERSION +PRODUCTVERSION RSRC_PACKAGE_VERSION +FILEFLAGSMASK 0 +FILEFLAGS 0 +FILEOS VOS__WINDOWS32 +FILETYPE VFT_APP +FILESUBTYPE 0 +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + BEGIN + VALUE "CompanyName", "NLnet Labs" + VALUE "FileDescription", "Unbound Configuration Checker" + VALUE "FileVersion", PACKAGE_VERSION + VALUE "InternalName", "unbound-checkconf" + VALUE "OriginalFilename", "unbound-checkconf.exe" + VALUE "ProductName", "unbound" + VALUE "ProductVersion", PACKAGE_VERSION + VALUE "LegalCopyright", "(C) 2009 NLnet Labs. Source is BSD licensed." + END + END + BLOCK "VarFileInfo" + BEGIN + /* English(409), windows ANSI codepage (1252) */ + VALUE "Translation", 0x409, 0x1252 + END +END diff --git a/winrc/rsrc_unbound_control.rc b/winrc/rsrc_unbound_control.rc new file mode 100644 index 00000000000..f9e1245dbfa --- /dev/null +++ b/winrc/rsrc_unbound_control.rc @@ -0,0 +1,37 @@ +/* + Unbound resource file for windows. For use with windres +*/ +#include "winver.h" +#include "config.h" + +1 ICON "winrc/combined.ico" + +1 VERSIONINFO +FILEVERSION RSRC_PACKAGE_VERSION +PRODUCTVERSION RSRC_PACKAGE_VERSION +FILEFLAGSMASK 0 +FILEFLAGS 0 +FILEOS VOS__WINDOWS32 +FILETYPE VFT_APP +FILESUBTYPE 0 +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + BEGIN + VALUE "CompanyName", "NLnet Labs" + VALUE "FileDescription", "Unbound Remote Control Tool" + VALUE "FileVersion", PACKAGE_VERSION + VALUE "InternalName", "unbound-control" + VALUE "OriginalFilename", "unbound-control.exe" + VALUE "ProductName", "unbound" + VALUE "ProductVersion", PACKAGE_VERSION + VALUE "LegalCopyright", "(C) 2009 NLnet Labs. Source is BSD licensed." + END + END + BLOCK "VarFileInfo" + BEGIN + /* English(409), windows ANSI codepage (1252) */ + VALUE "Translation", 0x409, 0x1252 + END +END diff --git a/winrc/rsrc_unbound_host.rc b/winrc/rsrc_unbound_host.rc new file mode 100644 index 00000000000..d00f95cf4d8 --- /dev/null +++ b/winrc/rsrc_unbound_host.rc @@ -0,0 +1,37 @@ +/* + Unbound resource file for windows. For use with windres +*/ +#include "winver.h" +#include "config.h" + +1 ICON "winrc/combined.ico" + +1 VERSIONINFO +FILEVERSION RSRC_PACKAGE_VERSION +PRODUCTVERSION RSRC_PACKAGE_VERSION +FILEFLAGSMASK 0 +FILEFLAGS 0 +FILEOS VOS__WINDOWS32 +FILETYPE VFT_APP +FILESUBTYPE 0 +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + BEGIN + VALUE "CompanyName", "NLnet Labs" + VALUE "FileDescription", "Unbound Lookup Utility" + VALUE "FileVersion", PACKAGE_VERSION + VALUE "InternalName", "unbound-host" + VALUE "OriginalFilename", "unbound-host.exe" + VALUE "ProductName", "unbound" + VALUE "ProductVersion", PACKAGE_VERSION + VALUE "LegalCopyright", "(C) 2009 NLnet Labs. Source is BSD licensed." + END + END + BLOCK "VarFileInfo" + BEGIN + /* English(409), windows ANSI codepage (1252) */ + VALUE "Translation", 0x409, 0x1252 + END +END diff --git a/winrc/service.conf b/winrc/service.conf new file mode 100644 index 00000000000..e0118a63a91 --- /dev/null +++ b/winrc/service.conf @@ -0,0 +1,13 @@ +# Unbound configuration file on windows. +# See example.conf for more settings and syntax +server: + # verbosity level 0-4 of logging + verbosity: 0 + + # if you want to log to a file use + #logfile: "C:\unbound.log" + + # on Windows, this setting makes reports go into the Application log + # found in ControlPanels - System tasks - Logs + #use-syslog: yes + diff --git a/winrc/setup.nsi b/winrc/setup.nsi new file mode 100644 index 00000000000..3d324f3f3c6 --- /dev/null +++ b/winrc/setup.nsi @@ -0,0 +1,226 @@ +# The NSIS (http://nsis.sourceforge.net) install script. +# This script is BSD licensed. +SetCompressor /solid /final lzma + +!include LogicLib.nsh +!include MUI2.nsh + +!define VERSION "0.0.0" +!define QUADVERSION "0.0.0.0" + +outFile "unbound_setup_${VERSION}.exe" +Name "Unbound" + +# default install directory +installDir "$PROGRAMFILES\Unbound" +installDirRegKey HKLM "Software\Unbound" "InstallLocation" +RequestExecutionLevel admin +#give credits to Nullsoft: BrandingText "" +VIAddVersionKey "ProductName" "Unbound" +VIAddVersionKey "CompanyName" "NLnet Labs" +VIAddVersionKey "FileDescription" "(un)install the unbound DNS resolver" +VIAddVersionKey "LegalCopyright" "Copyright 2009, NLnet Labs" +VIAddVersionKey "FileVersion" "${QUADVERSION}" +VIAddVersionKey "ProductVersion" "${QUADVERSION}" +VIProductVersion "${QUADVERSION}" + +# Global Variables +Var StartMenuFolder + +# use ReserveFile for files required before actual installation +# makes the installer start faster +#ReserveFile "System.dll" +#ReserveFile "NsExec.dll" + +!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\orange-install-nsis.ico" +!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\orange-uninstall-nsis.ico" + +!define MUI_HEADERIMAGE +!define MUI_HEADERIMAGE_RIGHT +!define MUI_HEADERIMAGE_BITMAP "setup_top.bmp" +!define MUI_WELCOMEFINISHPAGE_BITMAP "setup_left.bmp" +!define MUI_ABORTWARNING +#!define MUI_FINISHPAGE_NOAUTOCLOSE # so we can inspect install log. + +!insertmacro MUI_PAGE_WELCOME +!insertmacro MUI_PAGE_LICENSE "..\LICENSE" +!insertmacro MUI_PAGE_COMPONENTS +!insertmacro MUI_PAGE_DIRECTORY + +!define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKLM" +!define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\Unbound" +!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder" +!define MUI_STARTMENUPAGE_DEFAULTFOLDER "Unbound" +!insertmacro MUI_PAGE_STARTMENU UnboundStartMenu $StartMenuFolder + +!insertmacro MUI_PAGE_INSTFILES +!insertmacro MUI_PAGE_FINISH + +!define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the uninstallation of Unbound.$\r$\n$\r$\nClick Next to continue." +!insertmacro MUI_UNPAGE_WELCOME +!insertmacro MUI_UNPAGE_CONFIRM +!insertmacro MUI_UNPAGE_INSTFILES +!insertmacro MUI_UNPAGE_FINISH + +!insertmacro MUI_LANGUAGE "English" + +# default section, one per component, we have one component. +section "Unbound" SectionUnbound + SectionIn RO # cannot unselect this one + # real work in postinstall +sectionEnd + +section "Root anchor - DNSSEC" SectionRootKey + # add estimated size for key (Kb) + AddSize 2 +sectionEnd + +# the /o means it is not selected by default. +section /o "DLV - dlv.isc.org" SectionDLV + # add estimated size for key (Kb) + AddSize 2 + SetOutPath $INSTDIR + + # libgcc exception lib used by NSISdl plugin (in crosscompile). + File /nonfatal "/oname=$PLUGINSDIR\libgcc_s_sjlj-1.dll" "/usr/i686-pc-mingw32/sys-root/mingw/bin/libgcc_s_sjlj-1.dll" + + NSISdl::download "http://ftp.isc.org/www/dlv/dlv.isc.org.key" "$INSTDIR\dlv.isc.org.key" + Pop $R0 # result from Inetc::get + ${If} $R0 != "success" + MessageBox MB_OK|MB_ICONEXCLAMATION "Download error (ftp.isc.org: $R0), click OK to abort installation" /SD IDOK + SetOutPath "C:\" + RMDir "$INSTDIR" # doesnt work directory in use by us ... + Abort + ${EndIf} +sectionEnd + +section "-hidden.postinstall" + # copy files + setOutPath $INSTDIR + File "..\LICENSE" + File "README.txt" + File "..\unbound.exe" + File "..\unbound-checkconf.exe" + File "..\unbound-control.exe" + File "..\unbound-host.exe" + File "..\unbound-anchor.exe" + File "..\unbound-service-install.exe" + File "..\unbound-service-remove.exe" + File "..\anchor-update.exe" + File "unbound-website.url" + File "service.conf" + File "..\doc\example.conf" + + # Store Root Key choice + SectionGetFlags ${SectionRootKey} $R0 + IntOp $R0 $R0 & ${SF_SELECTED} + ${If} $R0 == ${SF_SELECTED} + ClearErrors + FileOpen $R1 "$INSTDIR\service.conf" a + IfErrors done_rk + FileSeek $R1 0 END + FileWrite $R1 "$\nserver: auto-trust-anchor-file: $\"$INSTDIR\root.key$\"$\n" + FileClose $R1 + done_rk: + WriteRegStr HKLM "Software\Unbound" "RootAnchor" "$\"$INSTDIR\unbound-anchor.exe$\" -a $\"$INSTDIR\root.key$\" -c $\"$INSTDIR\icannbundle.pem$\"" + ${Else} + WriteRegStr HKLM "Software\Unbound" "RootAnchor" "" + ${EndIf} + + # Store DLV choice + SectionGetFlags ${SectionDLV} $R0 + IntOp $R0 $R0 & ${SF_SELECTED} + ${If} $R0 == ${SF_SELECTED} + ClearErrors + FileOpen $R1 "$INSTDIR\service.conf" a + IfErrors done_dlv + FileSeek $R1 0 END + FileWrite $R1 "$\nserver: dlv-anchor-file: $\"$INSTDIR\dlv.isc.org.key$\"$\n" + FileClose $R1 + done_dlv: + WriteRegStr HKLM "Software\Unbound" "CronAction" "$\"$INSTDIR\anchor-update.exe$\" dlv.isc.org $\"$INSTDIR\dlv.isc.org.key$\"" + ${Else} + WriteRegStr HKLM "Software\Unbound" "CronAction" "" + ${EndIf} + + # store installation folder + WriteRegStr HKLM "Software\Unbound" "InstallLocation" "$INSTDIR" + WriteRegStr HKLM "Software\Unbound" "ConfigFile" "$INSTDIR\service.conf" + WriteRegDWORD HKLM "Software\Unbound" "CronTime" 86400 + + # uninstaller + WriteUninstaller "uninst.exe" + + # register uninstaller + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Unbound" "DisplayName" "Unbound" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Unbound" "UninstallString" "$\"$INSTDIR\uninst.exe$\"" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Unbound" "QuietUninstallString" "$\"$INSTDIR\uninst.exe$\" /S" + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Unbound" "NoModify" "1" + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Unbound" "NoRepair" "1" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Unbound" "URLInfoAbout" "http://unbound.net" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Unbound" "Publisher" "NLnet Labs" + + # start menu items + !insertmacro MUI_STARTMENU_WRITE_BEGIN UnboundStartMenu + CreateDirectory "$SMPROGRAMS\$StartMenuFolder" + CreateShortCut "$SMPROGRAMS\$StartMenuFolder\unbound.net website.lnk" "$INSTDIR\unbound-website.url" "" "$INSTDIR\unbound.exe" "" "" "" "Visit the unbound website" + CreateShortCut "$SMPROGRAMS\$StartMenuFolder\Uninstall.lnk" "$INSTDIR\uninst.exe" "" "" "" "" "" "Uninstall unbound" + !insertmacro MUI_STARTMENU_WRITE_END + + # install service entry + nsExec::ExecToLog '"$INSTDIR\unbound-service-install.exe"' + # start unbound service + nsExec::ExecToLog '"$INSTDIR\unbound-service-install.exe" start' +sectionEnd + +# set section descriptions +LangString DESC_unbound ${LANG_ENGLISH} "The base unbound DNS(SEC) validating caching resolver. $\r$\n$\r$\nStarted at boot from the Services control panel, logs to the Application Log, and the config file is its Program Files folder." +LangString DESC_rootkey ${LANG_ENGLISH} "Set up to use the DNSSEC root trust anchor. It is automatically updated. $\r$\n$\r$\nThis provides the main key that is used for security verification." +LangString DESC_dlv ${LANG_ENGLISH} "Set up to use DLV with dlv.isc.org. Downloads the key during install. $\r$\n$\r$\nIt fetches additional public keys that are used for security verification by querying the isc.org server with names encountered." + +!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN + !insertmacro MUI_DESCRIPTION_TEXT ${SectionUnbound} $(DESC_unbound) + !insertmacro MUI_DESCRIPTION_TEXT ${SectionRootKey} $(DESC_rootkey) + !insertmacro MUI_DESCRIPTION_TEXT ${SectionDLV} $(DESC_dlv) +!insertmacro MUI_FUNCTION_DESCRIPTION_END + +# setup macros for uninstall functions. +!ifdef UN +!undef UN +!endif +!define UN "un." + +# uninstaller section +section "un.Unbound" + # stop unbound service + nsExec::ExecToLog '"$INSTDIR\unbound-service-remove.exe" stop' + # uninstall service entry + nsExec::ExecToLog '"$INSTDIR\unbound-service-remove.exe"' + # deregister uninstall + DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Unbound" + Delete "$INSTDIR\uninst.exe" # delete self + Delete "$INSTDIR\LICENSE" + Delete "$INSTDIR\README.txt" + Delete "$INSTDIR\unbound.exe" + Delete "$INSTDIR\unbound-checkconf.exe" + Delete "$INSTDIR\unbound-control.exe" + Delete "$INSTDIR\unbound-host.exe" + Delete "$INSTDIR\unbound-anchor.exe" + Delete "$INSTDIR\unbound-service-install.exe" + Delete "$INSTDIR\unbound-service-remove.exe" + Delete "$INSTDIR\anchor-update.exe" + Delete "$INSTDIR\unbound-website.url" + Delete "$INSTDIR\service.conf" + Delete "$INSTDIR\example.conf" + Delete "$INSTDIR\dlv.isc.org.key" + Delete "$INSTDIR\root.key" + RMDir "$INSTDIR" + + # start menu items + !insertmacro MUI_STARTMENU_GETFOLDER UnboundStartMenu $StartMenuFolder + Delete "$SMPROGRAMS\$StartMenuFolder\Uninstall.lnk" + Delete "$SMPROGRAMS\$StartMenuFolder\unbound.net website.lnk" + RMDir "$SMPROGRAMS\$StartMenuFolder" + + DeleteRegKey HKLM "Software\Unbound" +sectionEnd diff --git a/winrc/setup_left.bmp b/winrc/setup_left.bmp new file mode 100644 index 0000000000000000000000000000000000000000..ddc17d07969aa673f16ec9510d7bb49c44604af7 GIT binary patch literal 154542 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 literal 0 HcmV?d00001 diff --git a/winrc/unbound32.ico b/winrc/unbound32.ico new file mode 100644 index 0000000000000000000000000000000000000000..64272eed44b941591533744807161590c2d1f590 GIT binary patch literal 3262 zcmd^Bdr(wm6hC)&@7?>@d+**|7IsfdWoe$KG2j3CoJp*#H5l4k%mu9OMD5tCN{pQ~9JKyj8 z&iT%F&H@nl3l9ez?XblJ5C{MR@xdv$2Oo7_l^1cXw{-pwL{U0DUY`dauMgc-Znn#c z?=MK7&!?chn<@zSPeR^ELs@*6Ef4%t=e%aw8_t zO^*jX?aRIfUjM^Mih7>o)>bFw|V_%aqWJb#}I1s?H%pcD&Pz*qgs2r zx>{CN2k@LAalXenpt|B!6t_xP(PDD?mkX;_Ror=p>TECZpP-s2 z8jXGX8c1q7XL^ShzZS*4g7`VZWbUgzj0#?_w^LCtsk(jfc-&uob9m;=o%TTVw3KFQ zuK`zG!&LmdtZMF@%u%E6ljV_=aT3esNYb~Gxn8o?0KAu&xEa;j+uhv}ZaUMPn^zSZ zTSQS?2%^GbX_V!Qkr6FD@sT-x9z683%k?Zk2tnxZw(AHRNj+$!<~r=(4v0K&m5%X3 zrOlReqVcSsiKn9S=#x+FbU2XkPMWQAI?qM+yCO$i2njvyu>aJJuSMh7@$(^}j|1Fh zFxV-QGOA*y=_z`0y470zz<6(TRI@Cf0is~`tnFKi>PFnP842rj6*k++$jB>^{V&P# zuTICY09!R>{170k7ye_@wgAjyn2`j*`%4uCz|h7gjm#{PS{WaAW^9~$*sUD{qZ@Sk zEJ9brv4_GVnxmuJ`t@rGasC__ST6`)=yY#kKFeW=$uHz;_!{}f#&cH7Ya(B2WTqi_ zm>iM!#@aXE%(pwTIC>pLFLXLeN00Fg8`d^%yvHmS1_gaOWN>Fh*x4Za5sP(?kx~g$ z)H7qo%wNBuxTWQ<;A;u6`-_8meV*A|DM=ViLq^7Yw0@=a>MhY(1Tl*wpD0kwceTEQ=)bb~*f1%<#*PPVErHLL;+;G&~y@m->D|N%O_# zu4t&muxFXl-kUF6b~<0RJASx5rX@J^G(#5w%%qu=0a1BFhvi2_uQp4`n5aSa>R`u- z$y0p8V}2y5#du!H$y*T_gN(4&53!6Fx;F;CBCh=-`p+>YBCdwp*mtg9o?Sf{u}fr8WDH9zWh> zVpC0Au^@gO5Ktuw8yF^yBp1tadP_?y;`BUO4YtRKi|R3{h0tGIrcV2SVY9sP3&J7u+|QFI1J zCsWkDIvrbHUXEMbZa0qQ75ho@KAKK6acM?6h38WMre|bq!lgd(70tUdO_v7^ewiTB zICeI}Jpv%iPfbzxV$JVD$a@_xNUWZm!EjGg^h|(pAAQ_cYeUC1@GGrtci){2kjk3o zG29FQ+2tD9(b1tcs;-Lf^{N3}zkYi_zzBc=SaOq+)V|h-_&Zl;M~7#^Lu&zEGVzNU z23ZXamm^P}Y{ZS&TD9$J6H-%M{XBcFsdU$82M*M$t+C6xf4zH9)sdKgyE0=&0l*rw z^sy)w>h+J>Y+<#vHK?F=!)v7Hq@SKkaMy*22DI$tM8WqF5}78xh(~g z2n8hhqS-v9yj%nSo3PxtEsgoc!tVf<3Ve}?FQne&rH4{BmO4)9}a&2 D`6sgx literal 0 HcmV?d00001 diff --git a/winrc/unbound48.ico b/winrc/unbound48.ico new file mode 100644 index 0000000000000000000000000000000000000000..074d12ebcfd3b47118a61f99fdd43d8bbf90620b GIT binary patch literal 7358 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 literal 0 HcmV?d00001 diff --git a/winrc/unbound64.ico b/winrc/unbound64.ico new file mode 100644 index 0000000000000000000000000000000000000000..c02f68f0a1960b9447de4262fb7f3b0a0730d3c3 GIT binary patch literal 12862 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 KMNUMnLSTZZ`u^1b literal 0 HcmV?d00001 diff --git a/winrc/vista_admin.manifest b/winrc/vista_admin.manifest new file mode 100644 index 00000000000..560801440e4 --- /dev/null +++ b/winrc/vista_admin.manifest @@ -0,0 +1,16 @@ + + + + Installs or removes the unbound service in the services control panel + + + + + + + + + diff --git a/winrc/vista_user.manifest b/winrc/vista_user.manifest new file mode 100644 index 00000000000..24f5164aa95 --- /dev/null +++ b/winrc/vista_user.manifest @@ -0,0 +1,16 @@ + + + + Retrieve latest version of trust anchor + + + + + + + + + diff --git a/winrc/w_inst.c b/winrc/w_inst.c new file mode 100644 index 00000000000..eb80119385b --- /dev/null +++ b/winrc/w_inst.c @@ -0,0 +1,308 @@ +/* + * winrc/w_inst.h - install and remove functions + * + * Copyright (c) 2009, 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * Contains install and remove functions that manipulate the + * windows services API and windows registry. + */ +#include "config.h" +#include "winrc/w_inst.h" +#include "winrc/win_svc.h" + +void wsvc_err2str(char* str, size_t len, const char* fixed, DWORD err) +{ + LPTSTR buf; + if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, err, 0, (LPTSTR)&buf, 0, NULL) == 0) { + /* could not format error message */ + snprintf(str, len, "%s GetLastError=%d", fixed, (int)err); + return; + } + snprintf(str, len, "%s (err=%d): %s", fixed, (int)err, buf); + LocalFree(buf); +} + +/** exit with windows error */ +static void +fatal_win(FILE* out, const char* str) +{ + char e[256]; + wsvc_err2str(e, sizeof(e), str, (int)GetLastError()); + if(out) fprintf(out, "%s\n", e); + else fprintf(stderr, "%s\n", e); + exit(1); +} + +/** install registry entries for eventlog */ +static void +event_reg_install(FILE* out, const char* pathname) +{ + char buf[1024]; + HKEY hk; + DWORD t; + if(out) fprintf(out, "install reg entries for %s\n", pathname); + snprintf(buf, sizeof(buf), "SYSTEM\\CurrentControlSet\\Services" + "\\EventLog\\Application\\%s", SERVICE_NAME); + if(RegCreateKeyEx(HKEY_LOCAL_MACHINE, (LPCTSTR)buf, + 0, /* reserved, mustbezero */ + NULL, /* class of key, ignored */ + REG_OPTION_NON_VOLATILE, /* values saved on disk */ + KEY_WRITE, /* we want write permission */ + NULL, /* use default security descriptor */ + &hk, /* result */ + NULL)) /* not interested if key new or existing */ + fatal_win(out, "could not create registry key"); + + /* message file */ + if(RegSetValueEx(hk, (LPCTSTR)"EventMessageFile", + 0, /* reserved, mustbezero */ + REG_EXPAND_SZ, /* value type (string w env subst) */ + (BYTE*)pathname, /* data */ + (DWORD)strlen(pathname)+1)) /* length of data */ + { + RegCloseKey(hk); + fatal_win(out, "could not registry set EventMessageFile"); + } + + /* event types */ + t = EVENTLOG_SUCCESS | EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE + | EVENTLOG_INFORMATION_TYPE; + if(RegSetValueEx(hk, (LPCTSTR)"TypesSupported", 0, REG_DWORD, + (LPBYTE)&t, sizeof(t))) { + RegCloseKey(hk); + fatal_win(out, "could not registry set TypesSupported"); + } + + /* category message file */ + if(RegSetValueEx(hk, (LPCTSTR)"CategoryMessageFile", 0, REG_EXPAND_SZ, + (BYTE*)pathname, (DWORD)strlen(pathname)+1)) { + RegCloseKey(hk); + fatal_win(out, "could not registry set CategoryMessageFile"); + } + t = 1; + if(RegSetValueEx(hk, (LPCTSTR)"CategoryCount", 0, REG_DWORD, + (LPBYTE)&t, sizeof(t))) { + RegCloseKey(hk); + fatal_win(out, "could not registry set CategoryCount"); + } + + + RegCloseKey(hk); + if(out) fprintf(out, "installed reg entries\n"); +} + +/** remove registry entries for eventlog */ +static void +event_reg_remove(FILE* out) +{ + char buf[1024]; + HKEY hk; + if(out) fprintf(out, "remove reg entries\n"); + snprintf(buf, sizeof(buf), "SYSTEM\\CurrentControlSet\\Services" + "\\EventLog\\Application"); + if(RegCreateKeyEx(HKEY_LOCAL_MACHINE, (LPCTSTR)buf, + 0, /* reserved, mustbezero */ + NULL, /* class of key, ignored */ + REG_OPTION_NON_VOLATILE, /* values saved on disk */ + DELETE, /* we want key delete permission */ + NULL, /* use default security descriptor */ + &hk, /* result */ + NULL)) /* not interested if key new or existing */ + fatal_win(out, "could not open registry key"); + if(RegDeleteKey(hk, (LPCTSTR)SERVICE_NAME)) { + RegCloseKey(hk); + fatal_win(out, "could not delete registry key"); + } + RegCloseKey(hk); + if(out) fprintf(out, "removed reg entries\n"); +} + +/** + * put quotes around string. Needs one space in front + * @param out: debugfile + * @param str: to be quoted. + * @param maxlen: max length of the string buffer. + */ +static void +quote_it(FILE* out, char* str, size_t maxlen) +{ + if(strlen(str) == maxlen) { + if(out) fprintf(out, "string too long %s", str); + exit(1); + } + str[0]='"'; + str[strlen(str)+1]=0; + str[strlen(str)]='"'; +} + +/** change suffix */ +static void +change(FILE* out, char* path, size_t max, const char* from, const char* to) +{ + size_t fromlen = strlen(from); + size_t tolen = strlen(to); + size_t pathlen = strlen(path); + if(pathlen - fromlen + tolen >= max) { + if(out) fprintf(out, "string too long %s", path); + exit(1); + } + snprintf(path+pathlen-fromlen, max-(pathlen-fromlen), "%s", to); +} + +/* Install service in servicecontrolmanager */ +void +wsvc_install(FILE* out, const char* rename) +{ + SC_HANDLE scm; + SC_HANDLE sv; + TCHAR path[MAX_PATH+2+256]; + if(out) fprintf(out, "installing unbound service\n"); + if(!GetModuleFileName(NULL, path+1, MAX_PATH)) + fatal_win(out, "could not GetModuleFileName"); + /* change 'unbound-service-install' to 'unbound' */ + if(rename) + change(out, path+1, sizeof(path)-1, rename, "unbound.exe"); + + event_reg_install(out, path+1); + + /* have to quote it because of spaces in directory names */ + /* could append arguments to be sent to ServiceMain */ + quote_it(out, path, sizeof(path)); + strcat(path, " -w service"); + scm = OpenSCManager(NULL, NULL, (int)SC_MANAGER_CREATE_SERVICE); + if(!scm) fatal_win(out, "could not OpenSCManager"); + sv = CreateService( + scm, + SERVICE_NAME, /* name of service */ + "Unbound DNS validator", /* display name */ + SERVICE_ALL_ACCESS, /* desired access */ + SERVICE_WIN32_OWN_PROCESS, /* service type */ + SERVICE_AUTO_START, /* start type */ + SERVICE_ERROR_NORMAL, /* error control type */ + path, /* path to service's binary */ + NULL, /* no load ordering group */ + NULL, /* no tag identifier */ + NULL, /* no deps */ + NULL, /* on LocalSystem */ + NULL /* no password */ + ); + if(!sv) { + CloseServiceHandle(scm); + fatal_win(out, "could not CreateService"); + } + CloseServiceHandle(sv); + CloseServiceHandle(scm); + if(out) fprintf(out, "unbound service installed\n"); +} + + +/* Remove installed service from servicecontrolmanager */ +void +wsvc_remove(FILE* out) +{ + SC_HANDLE scm; + SC_HANDLE sv; + if(out) fprintf(out, "removing unbound service\n"); + scm = OpenSCManager(NULL, NULL, (int)SC_MANAGER_ALL_ACCESS); + if(!scm) fatal_win(out, "could not OpenSCManager"); + sv = OpenService(scm, SERVICE_NAME, DELETE); + if(!sv) { + CloseServiceHandle(scm); + fatal_win(out, "could not OpenService"); + } + if(!DeleteService(sv)) { + CloseServiceHandle(sv); + CloseServiceHandle(scm); + fatal_win(out, "could not DeleteService"); + } + CloseServiceHandle(sv); + CloseServiceHandle(scm); + event_reg_remove(out); + if(out) fprintf(out, "unbound service removed\n"); +} + + +/* Start daemon */ +void +wsvc_rc_start(FILE* out) +{ + SC_HANDLE scm; + SC_HANDLE sv; + if(out) fprintf(out, "start unbound service\n"); + scm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if(!scm) fatal_win(out, "could not OpenSCManager"); + sv = OpenService(scm, SERVICE_NAME, SERVICE_START); + if(!sv) { + CloseServiceHandle(scm); + fatal_win(out, "could not OpenService"); + } + if(!StartService(sv, 0, NULL)) { + CloseServiceHandle(sv); + CloseServiceHandle(scm); + fatal_win(out, "could not StartService"); + } + CloseServiceHandle(sv); + CloseServiceHandle(scm); + if(out) fprintf(out, "unbound service started\n"); +} + + +/* Stop daemon */ +void +wsvc_rc_stop(FILE* out) +{ + SC_HANDLE scm; + SC_HANDLE sv; + SERVICE_STATUS st; + if(out) fprintf(out, "stop unbound service\n"); + scm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if(!scm) fatal_win(out, "could not OpenSCManager"); + sv = OpenService(scm, SERVICE_NAME, SERVICE_STOP); + if(!sv) { + CloseServiceHandle(scm); + fatal_win(out, "could not OpenService"); + } + if(!ControlService(sv, SERVICE_CONTROL_STOP, &st)) { + CloseServiceHandle(sv); + CloseServiceHandle(scm); + fatal_win(out, "could not ControlService"); + } + CloseServiceHandle(sv); + CloseServiceHandle(scm); + if(out) fprintf(out, "unbound service stopped\n"); +} diff --git a/winrc/w_inst.h b/winrc/w_inst.h new file mode 100644 index 00000000000..2c7864788fa --- /dev/null +++ b/winrc/w_inst.h @@ -0,0 +1,80 @@ +/* + * winrc/w_inst.h - install and remove functions + * + * Copyright (c) 2009, 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * Contains install and remove functions that manipulate the + * windows services API and windows registry. + */ + +#ifndef WINRC_W_INST_H +#define WINRC_W_INST_H + +/** + * Install service in servicecontrolmanager, setup registry + * @param out: debug output printed here (errors). or NULL. + * @param rename: if nonNULL this executable is not unbound.exe but this name. + */ +void wsvc_install(FILE* out, const char* rename); + +/** + * Remove installed service from servicecontrolmanager, registry entries + * @param out: debug output printed here (errors). or NULL. + */ +void wsvc_remove(FILE* out); + +/** + * Start the service from servicecontrolmanager, tells OS to start daemon. + * @param out: debug output printed here (errors). or NULL. + */ +void wsvc_rc_start(FILE* out); + +/** + * Stop the service from servicecontrolmanager, tells OS to stop daemon. + * @param out: debug output printed here (errors). or NULL. + */ +void wsvc_rc_stop(FILE* out); + +/** + * Convert windows GetLastError() value to a neat string. + * @param str: destination buffer + * @param len: length of dest buffer + * @param fixed: fixed text to prepend to string. + * @param err: the GetLastError() value. + */ +void wsvc_err2str(char* str, size_t len, const char* fixed, DWORD err); + +#endif /* WINRC_W_INST_H */ diff --git a/winrc/win_svc.c b/winrc/win_svc.c new file mode 100644 index 00000000000..7ac8b261113 --- /dev/null +++ b/winrc/win_svc.c @@ -0,0 +1,617 @@ +/* + * winrc/win_svc.c - windows services API implementation for unbound + * + * Copyright (c) 2009, 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions to integrate with the windows services API. + * This means it handles the commandline switches to install and remove + * the service (via CreateService and DeleteService), it handles + * the ServiceMain() main service entry point when started as a service, + * and it handles the Handler[_ex]() to process requests to the service + * (such as start and stop and status). + */ +#include "config.h" +#include "winrc/win_svc.h" +#include "winrc/w_inst.h" +#include "daemon/daemon.h" +#include "daemon/worker.h" +#include "daemon/remote.h" +#include "util/config_file.h" +#include "util/netevent.h" +#include "util/winsock_event.h" + +/** global service status */ +static SERVICE_STATUS service_status; +/** global service status handle */ +static SERVICE_STATUS_HANDLE service_status_handle; +/** global service stop event */ +static WSAEVENT service_stop_event = NULL; +/** event struct for stop callbacks */ +static struct event service_stop_ev; +/** if stop even means shutdown or restart */ +static int service_stop_shutdown = 0; +/** config file to open. global communication to service_main() */ +static char* service_cfgfile = CONFIGFILE; +/** commandline verbosity. global communication to service_main() */ +static int service_cmdline_verbose = 0; +/** the cron callback */ +static struct comm_timer* service_cron = NULL; +/** the cron thread */ +static ub_thread_t cron_thread = NULL; +/** if cron has already done its quick check */ +static int cron_was_quick = 0; + +/** + * Report current service status to service control manager + * @param state: current state + * @param exitcode: error code (when stopped) + * @param wait: pending operation estimated time in milliseconds. + */ +static void report_status(DWORD state, DWORD exitcode, DWORD wait) +{ + static DWORD checkpoint = 1; + service_status.dwCurrentState = state; + service_status.dwWin32ExitCode = exitcode; + service_status.dwWaitHint = wait; + if(state == SERVICE_START_PENDING) + service_status.dwControlsAccepted = 0; + else service_status.dwControlsAccepted = SERVICE_ACCEPT_STOP; + if(state == SERVICE_RUNNING || state == SERVICE_STOPPED) + service_status.dwCheckPoint = 0; + else service_status.dwCheckPoint = checkpoint++; + SetServiceStatus(service_status_handle, &service_status); +} + +/** + * Service control handler. Called by serviceControlManager when a control + * code is sent to the service (with ControlService). + * @param ctrl: control code + */ +static void +hdlr(DWORD ctrl) +{ + if(ctrl == SERVICE_CONTROL_STOP) { + report_status(SERVICE_STOP_PENDING, NO_ERROR, 0); + service_stop_shutdown = 1; + /* send signal to stop */ + if(!WSASetEvent(service_stop_event)) + log_err("Could not WSASetEvent: %s", + wsa_strerror(WSAGetLastError())); + return; + } else { + /* ctrl == SERVICE_CONTROL_INTERROGATE or whatever */ + /* update status */ + report_status(service_status.dwCurrentState, NO_ERROR, 0); + } +} + +/** + * report event to system event log + * For use during startup and shutdown. + * @param str: the error + */ +static void +reportev(const char* str) +{ + char b[256]; + char e[256]; + HANDLE* s; + LPCTSTR msg = b; + /* print quickly to keep GetLastError value */ + wsvc_err2str(e, sizeof(e), str, GetLastError()); + snprintf(b, sizeof(b), "%s: %s", SERVICE_NAME, e); + s = RegisterEventSource(NULL, SERVICE_NAME); + if(!s) return; + ReportEvent(s, /* event log */ + EVENTLOG_ERROR_TYPE, /* event type */ + 0, /* event category */ + MSG_GENERIC_ERR, /* event ID (from gen_msg.mc) */ + NULL, /* user security context */ + 1, /* numstrings */ + 0, /* binary size */ + &msg, /* strings */ + NULL); /* binary data */ + DeregisterEventSource(s); +} + +/** + * Obtain registry string (if it exists). + * @param key: key string + * @param name: name of value to fetch. + * @return malloced string with the result or NULL if it did not + * exist on an error (logged) was encountered. + */ +static char* +lookup_reg_str(const char* key, const char* name) +{ + HKEY hk = NULL; + DWORD type = 0; + BYTE buf[1024]; + DWORD len = (DWORD)sizeof(buf); + LONG ret; + char* result = NULL; + ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, key, 0, KEY_READ, &hk); + if(ret == ERROR_FILE_NOT_FOUND) + return NULL; /* key does not exist */ + else if(ret != ERROR_SUCCESS) { + reportev("RegOpenKeyEx failed"); + return NULL; + } + ret = RegQueryValueEx(hk, (LPCTSTR)name, 0, &type, buf, &len); + if(RegCloseKey(hk)) + reportev("RegCloseKey"); + if(ret == ERROR_FILE_NOT_FOUND) + return NULL; /* name does not exist */ + else if(ret != ERROR_SUCCESS) { + reportev("RegQueryValueEx failed"); + return NULL; + } + if(type == REG_SZ || type == REG_MULTI_SZ || type == REG_EXPAND_SZ) { + buf[sizeof(buf)-1] = 0; + buf[sizeof(buf)-2] = 0; /* for multi_sz */ + result = strdup((char*)buf); + if(!result) reportev("out of memory"); + } + return result; +} + +/** + * Obtain registry integer (if it exists). + * @param key: key string + * @param name: name of value to fetch. + * @return integer value (if it exists), or 0 on error. + */ +static int +lookup_reg_int(const char* key, const char* name) +{ + HKEY hk = NULL; + DWORD type = 0; + BYTE buf[1024]; + DWORD len = (DWORD)sizeof(buf); + LONG ret; + int result = 0; + ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, key, 0, KEY_READ, &hk); + if(ret == ERROR_FILE_NOT_FOUND) + return 0; /* key does not exist */ + else if(ret != ERROR_SUCCESS) { + reportev("RegOpenKeyEx failed"); + return 0; + } + ret = RegQueryValueEx(hk, (LPCTSTR)name, 0, &type, buf, &len); + if(RegCloseKey(hk)) + reportev("RegCloseKey"); + if(ret == ERROR_FILE_NOT_FOUND) + return 0; /* name does not exist */ + else if(ret != ERROR_SUCCESS) { + reportev("RegQueryValueEx failed"); + return 0; + } + if(type == REG_SZ || type == REG_MULTI_SZ || type == REG_EXPAND_SZ) { + buf[sizeof(buf)-1] = 0; + buf[sizeof(buf)-2] = 0; /* for multi_sz */ + result = atoi((char*)buf); + } else if(type == REG_DWORD) { + DWORD r; + memmove(&r, buf, sizeof(r)); + result = r; + } + return result; +} + +/** wait for unbound-anchor process to finish */ +static void +waitforubanchor(PROCESS_INFORMATION* pinfo) +{ + /* we have 5 seconds scheduled for it, usually it will be very fast, + * with only a UDP message or two (100 msec or so), but the https + * connections could take some time */ + DWORD count = 7900; + DWORD ret = WAIT_TIMEOUT; + /* decrease timer every 1/10 second, we are still starting up */ + while(ret == WAIT_TIMEOUT) { + ret = WaitForSingleObject(pinfo->hProcess, 100); + if(count > 4000) count -= 100; + else count--; /* go slow, it is taking long */ + if(count > 3000) + report_status(SERVICE_START_PENDING, NO_ERROR, count); + } + verbose(VERB_ALGO, "unbound-anchor done"); + if(ret != WAIT_OBJECT_0) { + return; /* did not end successfully */ + } + if(!GetExitCodeProcess(pinfo->hProcess, &ret)) { + log_err("GetExitCodeProcess failed"); + return; + } + verbose(VERB_ALGO, "unbound-anchor exit code is %d", (int)ret); + if(ret != 0) { + log_info("The root trust anchor has been updated."); + } +} + + +/** + * Perform root anchor update if so configured, by calling that process + */ +static void +call_root_update(void) +{ + char* rootanchor; + rootanchor = lookup_reg_str("Software\\Unbound", "RootAnchor"); + if(rootanchor && strlen(rootanchor)>0) { + STARTUPINFO sinfo; + PROCESS_INFORMATION pinfo; + memset(&pinfo, 0, sizeof(pinfo)); + memset(&sinfo, 0, sizeof(sinfo)); + sinfo.cb = sizeof(sinfo); + verbose(VERB_ALGO, "rootanchor: %s", rootanchor); + report_status(SERVICE_START_PENDING, NO_ERROR, 8000); + if(!CreateProcess(NULL, rootanchor, NULL, NULL, 0, + CREATE_NO_WINDOW, NULL, NULL, &sinfo, &pinfo)) + log_err("CreateProcess error for unbound-anchor.exe"); + else { + waitforubanchor(&pinfo); + CloseHandle(pinfo.hProcess); + CloseHandle(pinfo.hThread); + } + } + free(rootanchor); +} + +/** + * Init service. Keeps calling status pending to tell service control + * manager that this process is not hanging. + * @param r: restart, true on restart + * @param d: daemon returned here. + * @param c: config file returned here. + * @return false if failed. + */ +static int +service_init(int r, struct daemon** d, struct config_file** c) +{ + struct config_file* cfg = NULL; + struct daemon* daemon = NULL; + + if(!service_cfgfile) { + char* newf = lookup_reg_str("Software\\Unbound", "ConfigFile"); + if(newf) service_cfgfile = newf; + else service_cfgfile = strdup(CONFIGFILE); + if(!service_cfgfile) fatal_exit("out of memory"); + } + + /* create daemon */ + if(r) daemon = *d; + else daemon = daemon_init(); + if(!daemon) return 0; + if(!r) report_status(SERVICE_START_PENDING, NO_ERROR, 2800); + + /* read config */ + cfg = config_create(); + if(!cfg) return 0; + if(!config_read(cfg, service_cfgfile, daemon->chroot)) { + if(errno != ENOENT) { + log_err("error in config file"); + return 0; + } + log_warn("could not open config file, using defaults"); + } + if(!r) report_status(SERVICE_START_PENDING, NO_ERROR, 2600); + + verbose(VERB_QUERY, "winservice - apply settings"); + /* apply settings and init */ + verbosity = cfg->verbosity + service_cmdline_verbose; + if(cfg->directory && cfg->directory[0]) { + if(chdir(cfg->directory)) { + log_err("could not chdir to %s: %s", + cfg->directory, strerror(errno)); + if(errno != ENOENT) + return 0; + log_warn("could not change directory - continuing"); + } else + verbose(VERB_QUERY, "chdir to %s", cfg->directory); + } + log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir); + if(!r) report_status(SERVICE_START_PENDING, NO_ERROR, 2400); + verbose(VERB_QUERY, "winservice - apply cfg"); + daemon_apply_cfg(daemon, cfg); + + if(!r) report_status(SERVICE_START_PENDING, NO_ERROR, 2300); + if(!(daemon->rc = daemon_remote_create(cfg))) { + log_err("could not set up remote-control"); + daemon_delete(daemon); + config_delete(cfg); + return 0; + } + + /* open ports */ + /* keep reporting that we are busy starting */ + if(!r) report_status(SERVICE_START_PENDING, NO_ERROR, 2200); + verbose(VERB_QUERY, "winservice - open ports"); + if(!daemon_open_shared_ports(daemon)) return 0; + verbose(VERB_QUERY, "winservice - ports opened"); + if(!r) report_status(SERVICE_START_PENDING, NO_ERROR, 2000); + + *d = daemon; + *c = cfg; + return 1; +} + +/** + * Deinit the service + */ +static void +service_deinit(struct daemon* daemon, struct config_file* cfg) +{ + daemon_cleanup(daemon); + config_delete(cfg); + daemon_delete(daemon); +} + +/** + * The main function for the service. + * Called by the services API when starting unbound on windows in background. + * Arguments could have been present in the string 'path'. + * @param argc: nr args + * @param argv: arg text. + */ +static void +service_main(DWORD ATTR_UNUSED(argc), LPTSTR* ATTR_UNUSED(argv)) +{ + struct config_file* cfg = NULL; + struct daemon* daemon = NULL; + + service_status_handle = RegisterServiceCtrlHandler(SERVICE_NAME, + (LPHANDLER_FUNCTION)hdlr); + if(!service_status_handle) { + reportev("Could not RegisterServiceCtrlHandler"); + return; + } + + service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + service_status.dwServiceSpecificExitCode = 0; + + /* see if we have root anchor update enabled */ + call_root_update(); + + /* we are now starting up */ + report_status(SERVICE_START_PENDING, NO_ERROR, 3000); + if(!service_init(0, &daemon, &cfg)) { + reportev("Could not service_init"); + report_status(SERVICE_STOPPED, NO_ERROR, 0); + return; + } + + /* event that gets signalled when we want to quit; it + * should get registered in the worker-0 waiting loop. */ + service_stop_event = WSACreateEvent(); + if(service_stop_event == WSA_INVALID_EVENT) { + log_err("WSACreateEvent: %s", wsa_strerror(WSAGetLastError())); + reportev("Could not WSACreateEvent"); + report_status(SERVICE_STOPPED, NO_ERROR, 0); + return; + } + if(!WSAResetEvent(service_stop_event)) { + log_err("WSAResetEvent: %s", wsa_strerror(WSAGetLastError())); + } + + /* SetServiceStatus SERVICE_RUNNING;*/ + report_status(SERVICE_RUNNING, NO_ERROR, 0); + verbose(VERB_QUERY, "winservice - init complete"); + + /* daemon performs work */ + while(!service_stop_shutdown) { + daemon_fork(daemon); + if(!service_stop_shutdown) { + daemon_cleanup(daemon); + config_delete(cfg); cfg=NULL; + if(!service_init(1, &daemon, &cfg)) { + reportev("Could not service_init"); + report_status(SERVICE_STOPPED, NO_ERROR, 0); + return; + } + } + } + + /* exit */ + verbose(VERB_ALGO, "winservice - cleanup."); + report_status(SERVICE_STOP_PENDING, NO_ERROR, 0); + service_deinit(daemon, cfg); + free(service_cfgfile); + if(service_stop_event) (void)WSACloseEvent(service_stop_event); + verbose(VERB_QUERY, "winservice - full stop"); + report_status(SERVICE_STOPPED, NO_ERROR, 0); +} + +/** start the service */ +static void +service_start(const char* cfgfile, int v, int c) +{ + SERVICE_TABLE_ENTRY myservices[2] = { + {SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)service_main}, + {NULL, NULL} }; + verbosity=v; + if(verbosity >= VERB_QUERY) { + /* log to file about start sequence */ + fclose(fopen("C:\\unbound.log", "w")); + log_init("C:\\unbound.log", 0, 0); + verbose(VERB_QUERY, "open logfile"); + } else log_init(0, 1, 0); /* otherwise, use Application log */ + if(c) { + service_cfgfile = strdup(cfgfile); + if(!service_cfgfile) fatal_exit("out of memory"); + } else service_cfgfile = NULL; + service_cmdline_verbose = v; + /* this call returns when service has stopped. */ + if(!StartServiceCtrlDispatcher(myservices)) { + reportev("Could not StartServiceCtrlDispatcher"); + } +} + +void +wsvc_command_option(const char* wopt, const char* cfgfile, int v, int c) +{ + if(strcmp(wopt, "install") == 0) + wsvc_install(stdout, NULL); + else if(strcmp(wopt, "remove") == 0) + wsvc_remove(stdout); + else if(strcmp(wopt, "service") == 0) + service_start(cfgfile, v, c); + else if(strcmp(wopt, "start") == 0) + wsvc_rc_start(stdout); + else if(strcmp(wopt, "stop") == 0) + wsvc_rc_stop(stdout); + else fatal_exit("unknown option: %s", wopt); + exit(0); +} + +void +worker_win_stop_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev), void* arg) +{ + struct worker* worker = (struct worker*)arg; + verbose(VERB_QUERY, "caught stop signal (wsaevent)"); + worker->need_to_exit = 1; + comm_base_exit(worker->base); +} + +/** wait for cron process to finish */ +static void +waitforit(PROCESS_INFORMATION* pinfo) +{ + DWORD ret = WaitForSingleObject(pinfo->hProcess, INFINITE); + verbose(VERB_ALGO, "cronaction done"); + if(ret != WAIT_OBJECT_0) { + return; /* did not end successfully */ + } + if(!GetExitCodeProcess(pinfo->hProcess, &ret)) { + log_err("GetExitCodeProcess failed"); + return; + } + verbose(VERB_ALGO, "exit code is %d", (int)ret); + if(ret != 1) { + if(!WSASetEvent(service_stop_event)) + log_err("Could not WSASetEvent: %s", + wsa_strerror(WSAGetLastError())); + } +} + +/** Do the cron action and wait for result exit value */ +static void* +win_do_cron(void* ATTR_UNUSED(arg)) +{ + int mynum=65; + char* cronaction; + log_thread_set(&mynum); + cronaction = lookup_reg_str("Software\\Unbound", "CronAction"); + if(cronaction && strlen(cronaction)>0) { + STARTUPINFO sinfo; + PROCESS_INFORMATION pinfo; + memset(&pinfo, 0, sizeof(pinfo)); + memset(&sinfo, 0, sizeof(sinfo)); + sinfo.cb = sizeof(sinfo); + verbose(VERB_ALGO, "cronaction: %s", cronaction); + if(!CreateProcess(NULL, cronaction, NULL, NULL, 0, + CREATE_NO_WINDOW, NULL, NULL, &sinfo, &pinfo)) + log_err("CreateProcess error"); + else { + waitforit(&pinfo); + CloseHandle(pinfo.hProcess); + CloseHandle(pinfo.hThread); + } + } + free(cronaction); + /* stop self */ + CloseHandle(cron_thread); + cron_thread = NULL; + return NULL; +} + +/** Set the timer for cron for the next wake up */ +static void +set_cron_timer() +{ + struct timeval tv; + int crontime; + if(cron_was_quick == 0) { + cron_was_quick = 1; + crontime = 3600; /* first update some time after boot */ + } else { + crontime = lookup_reg_int("Software\\Unbound", "CronTime"); + if(crontime == 0) crontime = 60*60*24; /* 24 hours */ + } + memset(&tv, 0, sizeof(tv)); + tv.tv_sec = (time_t)crontime; + comm_timer_set(service_cron, &tv); +} + +void +wsvc_cron_cb(void* arg) +{ + struct worker* worker = (struct worker*)arg; + /* perform cronned operation */ + verbose(VERB_ALGO, "cron timer callback"); + if(cron_thread == NULL) { + /* create new thread to do it */ + ub_thread_create(&cron_thread, win_do_cron, worker); + } + /* reschedule */ + set_cron_timer(); +} + +void wsvc_setup_worker(struct worker* worker) +{ + /* if not started with -w service, do nothing */ + if(!service_stop_event) + return; + if(!winsock_register_wsaevent(comm_base_internal(worker->base), + &service_stop_ev, service_stop_event, + &worker_win_stop_cb, worker)) { + fatal_exit("could not register wsaevent"); + return; + } + if(!service_cron) { + service_cron = comm_timer_create(worker->base, + wsvc_cron_cb, worker); + if(!service_cron) + fatal_exit("could not create cron timer"); + set_cron_timer(); + } +} + +void wsvc_desetup_worker(struct worker* ATTR_UNUSED(worker)) +{ + comm_timer_delete(service_cron); + service_cron = NULL; +} diff --git a/winrc/win_svc.h b/winrc/win_svc.h new file mode 100644 index 00000000000..73765872759 --- /dev/null +++ b/winrc/win_svc.h @@ -0,0 +1,90 @@ +/* + * winrc/win_svc.h - windows services API implementation for unbound + * + * Copyright (c) 2009, 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 REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions to integrate with the windows services API. + * This means it handles the commandline switches to install and remove + * the service (via CreateService and DeleteService), it handles + * the ServiceMain() main service entry point when started as a service, + * and it handles the Handler[_ex]() to process requests to the service + * (such as start and stop and status). + */ + +#ifndef WINRC_WIN_SVC_H +#define WINRC_WIN_SVC_H +struct worker; + +/** service name for unbound (internal to ServiceManager) */ +#define SERVICE_NAME "unbound" + +/** from gen_msg.h - success message record for windows message log */ +#define MSG_GENERIC_SUCCESS ((DWORD)0x20010001L) +/** from gen_msg.h - informational message record for windows message log */ +#define MSG_GENERIC_INFO ((DWORD)0x60010002L) +/** from gen_msg.h - warning message record for windows message log */ +#define MSG_GENERIC_WARN ((DWORD)0xA0010003L) +/** from gen_msg.h - error message record for windows message log */ +#define MSG_GENERIC_ERR ((DWORD)0xE0010004L) + +/** + * Handle commandline service for windows. + * @param wopt: windows option string (install, remove, service). + * @param cfgfile: configfile to open (default or passed with -c). + * @param v: amount of commandline verbosity added with -v. + * @param c: true if cfgfile was set by commandline -c option. + */ +void wsvc_command_option(const char* wopt, const char* cfgfile, int v, int c); + +/** + * Setup lead worker events. + * @param worker: the worker + */ +void wsvc_setup_worker(struct worker* worker); + +/** + * Desetup lead worker events. + * @param worker: the worker + */ +void wsvc_desetup_worker(struct worker* worker); + +/** windows worker stop event callback handler */ +void worker_win_stop_cb(int fd, short ev, void* arg); + +/** windows cron timer callback handler */ +void wsvc_cron_cb(void* arg); + +#endif /* WINRC_WIN_SVC_H */ From cda31c70d5ddb1e0db6d44f4714cea76d6684284 Mon Sep 17 00:00:00 2001 From: Xin LI Date: Wed, 16 Jan 2013 23:11:13 +0000 Subject: [PATCH 0003/1476] Update vendor/illumos/dist and vendor-sys/illumos/dist to illumos-gate 13921:9d721847e469 (illumos zfs issue #3035 LZ4 compression support in ZFS and GRUB) --- common/zfs/zfeature_common.c | 4 + common/zfs/zfeature_common.h | 2 + common/zfs/zfs_prop.c | 6 +- man/man1m/zfs.1m | 11 +- man/man5/zpool-features.5 | 34 + uts/common/Makefile.files | 2 + uts/common/fs/zfs/THIRDPARTYLICENSE.lz4 | 30 + .../fs/zfs/THIRDPARTYLICENSE.lz4.descrip | 1 + uts/common/fs/zfs/lz4.c | 1173 +++++++++++++++++ uts/common/fs/zfs/sys/zio.h | 4 + uts/common/fs/zfs/sys/zio_compress.h | 7 + uts/common/fs/zfs/zfs_ioctl.c | 108 ++ uts/common/fs/zfs/zio_compress.c | 4 + 13 files changed, 1383 insertions(+), 3 deletions(-) create mode 100644 uts/common/fs/zfs/THIRDPARTYLICENSE.lz4 create mode 100644 uts/common/fs/zfs/THIRDPARTYLICENSE.lz4.descrip create mode 100644 uts/common/fs/zfs/lz4.c diff --git a/common/zfs/zfeature_common.c b/common/zfs/zfeature_common.c index f79d1f46131..bb552ac14bd 100644 --- a/common/zfs/zfeature_common.c +++ b/common/zfs/zfeature_common.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2012 by Delphix. All rights reserved. + * Copyright (c) 2013 by Saso Kiselkov. All rights reserved. */ #ifdef _KERNEL @@ -156,4 +157,7 @@ zpool_feature_init(void) zfeature_register(SPA_FEATURE_EMPTY_BPOBJ, "com.delphix:empty_bpobj", "empty_bpobj", "Snapshots use less space.", B_TRUE, B_FALSE, NULL); + zfeature_register(SPA_FEATURE_LZ4_COMPRESS, + "org.illumos:lz4_compress", "lz4_compress", + "LZ4 compression algorithm support.", B_FALSE, B_FALSE, NULL); } diff --git a/common/zfs/zfeature_common.h b/common/zfs/zfeature_common.h index 40bc4374cb3..f3a137fb3e9 100644 --- a/common/zfs/zfeature_common.h +++ b/common/zfs/zfeature_common.h @@ -21,6 +21,7 @@ /* * Copyright (c) 2012 by Delphix. All rights reserved. + * Copyright (c) 2013 by Saso Kiselkov. All rights reserved. */ #ifndef _ZFEATURE_COMMON_H @@ -52,6 +53,7 @@ typedef int (zfeature_func_t)(zfeature_info_t *fi, void *arg); enum spa_feature { SPA_FEATURE_ASYNC_DESTROY, SPA_FEATURE_EMPTY_BPOBJ, + SPA_FEATURE_LZ4_COMPRESS, SPA_FEATURES } spa_feature_t; diff --git a/common/zfs/zfs_prop.c b/common/zfs/zfs_prop.c index 4f798369109..9d8365528c3 100644 --- a/common/zfs/zfs_prop.c +++ b/common/zfs/zfs_prop.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011 by Delphix. All rights reserved. + * Copyright (c) 2013 by Saso Kiselkov. All rights reserved. */ /* Portions Copyright 2010 Robert Milkowski */ @@ -96,6 +97,7 @@ zfs_prop_init(void) { "gzip-8", ZIO_COMPRESS_GZIP_8 }, { "gzip-9", ZIO_COMPRESS_GZIP_9 }, { "zle", ZIO_COMPRESS_ZLE }, + { "lz4", ZIO_COMPRESS_LZ4 }, { NULL } }; @@ -211,8 +213,8 @@ zfs_prop_init(void) zprop_register_index(ZFS_PROP_COMPRESSION, "compression", ZIO_COMPRESS_DEFAULT, PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, - "on | off | lzjb | gzip | gzip-[1-9] | zle", "COMPRESS", - compress_table); + "on | off | lzjb | gzip | gzip-[1-9] | zle | lz4", + "COMPRESS", compress_table); zprop_register_index(ZFS_PROP_SNAPDIR, "snapdir", ZFS_SNAPDIR_HIDDEN, PROP_INHERIT, ZFS_TYPE_FILESYSTEM, "hidden | visible", "SNAPDIR", snapdir_table); diff --git a/man/man1m/zfs.1m b/man/man1m/zfs.1m index 87e2a57cc01..fc3e899e53e 100644 --- a/man/man1m/zfs.1m +++ b/man/man1m/zfs.1m @@ -25,6 +25,7 @@ .\" Copyright (c) 2012 by Delphix. All rights reserved. .\" Copyright (c) 2012, Joyent, Inc. All rights reserved. .\" Copyright 2012 Nexenta Systems, Inc. All Rights Reserved. +.\" Copyright (c) 2013 by Saso Kiselkov. All rights reserved. .\" .TH ZFS 1M "Sep 16, 2012" .SH NAME @@ -912,7 +913,7 @@ Changing this property affects only newly-written data. .ne 2 .na \fB\fBcompression\fR=\fBon\fR | \fBoff\fR | \fBlzjb\fR | \fBgzip\fR | -\fBgzip-\fR\fIN\fR | \fBzle\fR\fR +\fBgzip-\fR\fIN\fR | \fBzle\fR\fR | \fBlz4\fR .ad .sp .6 .RS 4n @@ -926,6 +927,14 @@ value \fBgzip-\fR\fIN\fR where \fIN\fR is an integer from 1 (fastest) to 9 (which is also the default for \fBgzip\fR(1)). The \fBzle\fR compression algorithm compresses runs of zeros. .sp +The \fBlz4\fR compression algorithm is a high-performance replacement +for the \fBlzjb\fR algorithm. It features significantly faster +compression and decompression, as well as a moderately higher +compression ratio than \fBlzjb\fR, but can only be used on pools with +the \fBlz4_compress\fR feature set to \fIenabled\fR. See +\fBzpool-features\fR(5) for details on ZFS feature flags and the +\fBlz4_compress\fR feature. +.sp This property can also be referred to by its shortened column name \fBcompress\fR. Changing this property affects only newly-written data. .RE diff --git a/man/man5/zpool-features.5 b/man/man5/zpool-features.5 index 0ab179ef7c9..a306e4388fa 100644 --- a/man/man5/zpool-features.5 +++ b/man/man5/zpool-features.5 @@ -1,5 +1,6 @@ '\" te .\" Copyright (c) 2012 by Delphix. All rights reserved. +.\" Copyright (c) 2013 by Saso Kiselkov. All rights reserved. .\" The contents of this file are subject to the terms of the Common Development .\" and Distribution License (the "License"). You may not use this file except .\" in compliance with the License. You can obtain a copy of the license at @@ -197,5 +198,38 @@ This feature is \fBactive\fR while there are any filesystems, volumes, or snapshots which were created after enabling this feature. .RE +.sp +.ne 2 +.na +\fB\fBlz4_compress\fR\fR +.ad +.RS 4n +.TS +l l . +GUID org.illumos:lz4_compress +READ\-ONLY COMPATIBLE no +DEPENDENCIES none +.TE + +\fBlz4\fR is a high-performance real-time compression algorithm that +features significantly faster compression and decompression as well as a +higher compression ratio than the older \fBlzjb\fR compression. +Typically, \fBlz4\fR compression is approximately 50% faster on +compressible data and 200% faster on incompressible data than +\fBlzjb\fR. It is also approximately 80% faster on decompression, while +giving approximately 10% better compression ratio. + +When the \fBlz4_compress\fR feature is set to \fBenabled\fR, the +administrator can turn on \fBlz4\fR compression on any dataset on the +pool using the \fBzfs\fR(1M) command. Please note that doing so will +immediately activate the \fBlz4_compress\fR feature on the underlying +pool (even before any data is written). Since this feature is not +read-only compatible, this operation will render the pool unimportable +on systems without support for the \fBlz4_compress\fR feature. At the +moment, this operation cannot be reversed. Booting off of +\fBlz4\fR-compressed root pools is supported. + +.RE + .SH "SEE ALSO" \fBzpool\fR(1M) diff --git a/uts/common/Makefile.files b/uts/common/Makefile.files index b20ff8ca79e..1eb0e3158a7 100644 --- a/uts/common/Makefile.files +++ b/uts/common/Makefile.files @@ -23,6 +23,7 @@ # Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2012 Nexenta Systems, Inc. All rights reserved. # Copyright (c) 2012 by Delphix. All rights reserved. +# Copyright (c) 2013 by Saso Kiselkov. All rights reserved. # # @@ -1353,6 +1354,7 @@ ZFS_COMMON_OBJS += \ dsl_scan.o \ zfeature.o \ gzip.o \ + lz4.o \ lzjb.o \ metaslab.o \ refcount.o \ diff --git a/uts/common/fs/zfs/THIRDPARTYLICENSE.lz4 b/uts/common/fs/zfs/THIRDPARTYLICENSE.lz4 new file mode 100644 index 00000000000..722cc75f01e --- /dev/null +++ b/uts/common/fs/zfs/THIRDPARTYLICENSE.lz4 @@ -0,0 +1,30 @@ +LZ4 - Fast LZ compression algorithm +Copyright (C) 2011-2013, Yann Collet. +BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + +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. + +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. + +You can contact the author at : +- LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html +- LZ4 source repository : http://code.google.com/p/lz4/ diff --git a/uts/common/fs/zfs/THIRDPARTYLICENSE.lz4.descrip b/uts/common/fs/zfs/THIRDPARTYLICENSE.lz4.descrip new file mode 100644 index 00000000000..211f679b574 --- /dev/null +++ b/uts/common/fs/zfs/THIRDPARTYLICENSE.lz4.descrip @@ -0,0 +1 @@ +LZ4 COMPRESSION FUNCTIONALITY IN ZFS diff --git a/uts/common/fs/zfs/lz4.c b/uts/common/fs/zfs/lz4.c new file mode 100644 index 00000000000..f710348fed7 --- /dev/null +++ b/uts/common/fs/zfs/lz4.c @@ -0,0 +1,1173 @@ +/* + * LZ4 - Fast LZ compression algorithm + * Header File + * Copyright (C) 2011-2013, Yann Collet. + * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + * + * 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. + * + * 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. + * + * You can contact the author at : + * - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html + * - LZ4 source repository : http://code.google.com/p/lz4/ + */ + +#include + +static int real_LZ4_compress(const char *source, char *dest, int isize, + int osize); +static int real_LZ4_uncompress(const char *source, char *dest, int osize); +static int LZ4_compressBound(int isize); +static int LZ4_uncompress_unknownOutputSize(const char *source, char *dest, + int isize, int maxOutputSize); +static int LZ4_compressCtx(void *ctx, const char *source, char *dest, + int isize, int osize); +static int LZ4_compress64kCtx(void *ctx, const char *source, char *dest, + int isize, int osize); + +/*ARGSUSED*/ +size_t +lz4_compress(void *s_start, void *d_start, size_t s_len, size_t d_len, int n) +{ + uint32_t bufsiz; + char *dest = d_start; + + ASSERT(d_len >= sizeof (bufsiz)); + + bufsiz = real_LZ4_compress(s_start, &dest[sizeof (bufsiz)], s_len, + d_len - sizeof (bufsiz)); + + /* Signal an error if the compression routine returned zero. */ + if (bufsiz == 0) + return (s_len); + + /* + * Encode the compresed buffer size at the start. We'll need this in + * decompression to counter the effects of padding which might be + * added to the compressed buffer and which, if unhandled, would + * confuse the hell out of our decompression function. + */ + *(uint32_t *)dest = BE_32(bufsiz); + + return (bufsiz + sizeof (bufsiz)); +} + +/*ARGSUSED*/ +int +lz4_decompress(void *s_start, void *d_start, size_t s_len, size_t d_len, int n) +{ + const char *src = s_start; + uint32_t bufsiz = BE_IN32(src); + + /* invalid compressed buffer size encoded at start */ + if (bufsiz + sizeof (bufsiz) > s_len) + return (1); + + /* + * Returns 0 on success (decompression function returned non-negative) + * and non-zero on failure (decompression function returned negative. + */ + return (LZ4_uncompress_unknownOutputSize(&src[sizeof (bufsiz)], + d_start, bufsiz, d_len) < 0); +} + +/* + * LZ4 API Description: + * + * Simple Functions: + * real_LZ4_compress() : + * isize : is the input size. Max supported value is ~1.9GB + * return : the number of bytes written in buffer dest + * or 0 if the compression fails (if LZ4_COMPRESSMIN is set). + * note : destination buffer must be already allocated. + * destination buffer must be sized to handle worst cases + * situations (input data not compressible) worst case size + * evaluation is provided by function LZ4_compressBound(). + * + * real_LZ4_uncompress() : + * osize : is the output size, therefore the original size + * return : the number of bytes read in the source buffer. + * If the source stream is malformed, the function will stop + * decoding and return a negative result, indicating the byte + * position of the faulty instruction. This function never + * writes beyond dest + osize, and is therefore protected + * against malicious data packets. + * note : destination buffer must be already allocated + * + * Advanced Functions + * + * LZ4_compressBound() : + * Provides the maximum size that LZ4 may output in a "worst case" + * scenario (input data not compressible) primarily useful for memory + * allocation of output buffer. + * + * isize : is the input size. Max supported value is ~1.9GB + * return : maximum output size in a "worst case" scenario + * note : this function is limited by "int" range (2^31-1) + * + * LZ4_uncompress_unknownOutputSize() : + * isize : is the input size, therefore the compressed size + * maxOutputSize : is the size of the destination buffer (which must be + * already allocated) + * return : the number of bytes decoded in the destination buffer + * (necessarily <= maxOutputSize). If the source stream is + * malformed, the function will stop decoding and return a + * negative result, indicating the byte position of the faulty + * instruction. This function never writes beyond dest + + * maxOutputSize, and is therefore protected against malicious + * data packets. + * note : Destination buffer must be already allocated. + * This version is slightly slower than real_LZ4_uncompress() + * + * LZ4_compressCtx() : + * This function explicitly handles the CTX memory structure. + * + * ILLUMOS CHANGES: the CTX memory structure must be explicitly allocated + * by the caller (either on the stack or using kmem_zalloc). Passing NULL + * isn't valid. + * + * LZ4_compress64kCtx() : + * Same as LZ4_compressCtx(), but specific to small inputs (<64KB). + * isize *Must* be <64KB, otherwise the output will be corrupted. + * + * ILLUMOS CHANGES: the CTX memory structure must be explicitly allocated + * by the caller (either on the stack or using kmem_zalloc). Passing NULL + * isn't valid. + */ + +/* + * Tuning parameters + */ + +/* + * COMPRESSIONLEVEL: Increasing this value improves compression ratio + * Lowering this value reduces memory usage. Reduced memory usage + * typically improves speed, due to cache effect (ex: L1 32KB for Intel, + * L1 64KB for AMD). Memory usage formula : N->2^(N+2) Bytes + * (examples : 12 -> 16KB ; 17 -> 512KB) + */ +#define COMPRESSIONLEVEL 12 + +/* + * NOTCOMPRESSIBLE_CONFIRMATION: Decreasing this value will make the + * algorithm skip faster data segments considered "incompressible". + * This may decrease compression ratio dramatically, but will be + * faster on incompressible data. Increasing this value will make + * the algorithm search more before declaring a segment "incompressible". + * This could improve compression a bit, but will be slower on + * incompressible data. The default value (6) is recommended. + */ +#define NOTCOMPRESSIBLE_CONFIRMATION 6 + +/* + * BIG_ENDIAN_NATIVE_BUT_INCOMPATIBLE: This will provide a boost to + * performance for big endian cpu, but the resulting compressed stream + * will be incompatible with little-endian CPU. You can set this option + * to 1 in situations where data will stay within closed environment. + * This option is useless on Little_Endian CPU (such as x86). + */ +/* #define BIG_ENDIAN_NATIVE_BUT_INCOMPATIBLE 1 */ + +/* + * CPU Feature Detection + */ + +/* 32 or 64 bits ? */ +#if (defined(__x86_64__) || defined(__x86_64) || defined(__amd64__) || \ + defined(__amd64) || defined(__ppc64__) || defined(_WIN64) || \ + defined(__LP64__) || defined(_LP64)) +#define LZ4_ARCH64 1 +/* + * Illumos: On amd64 we have 20k of stack and 24k on sun4u and sun4v, so we + * can spend 16k on the algorithm + */ +#define STACKLIMIT 12 +#else +#define LZ4_ARCH64 0 +/* + * Illumos: On i386 we only have 12k of stack, so in order to maintain the + * same COMPRESSIONLEVEL we have to use heap allocation. Performance will + * suck, but alas, it's ZFS on 32-bit we're talking about, so... + */ +#define STACKLIMIT 11 +#endif + +/* + * Little Endian or Big Endian? + * Note: overwrite the below #define if you know your architecture endianess. + */ +#if (defined(__BIG_ENDIAN__) || defined(__BIG_ENDIAN) || \ + defined(_BIG_ENDIAN) || defined(_ARCH_PPC) || defined(__PPC__) || \ + defined(__PPC) || defined(PPC) || defined(__powerpc__) || \ + defined(__powerpc) || defined(powerpc) || \ + ((defined(__BYTE_ORDER__)&&(__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)))) +#define LZ4_BIG_ENDIAN 1 +#else +/* + * Little Endian assumed. PDP Endian and other very rare endian format + * are unsupported. + */ +#endif + +/* + * Unaligned memory access is automatically enabled for "common" CPU, + * such as x86. For others CPU, the compiler will be more cautious, and + * insert extra code to ensure aligned access is respected. If you know + * your target CPU supports unaligned memory access, you may want to + * force this option manually to improve performance + */ +#if defined(__ARM_FEATURE_UNALIGNED) +#define LZ4_FORCE_UNALIGNED_ACCESS 1 +#endif + +/* + * Illumos: we can't use GCC's __builtin_ctz family of builtins in the + * kernel + */ +#define LZ4_FORCE_SW_BITCOUNT + +/* + * Compiler Options + */ +#if __STDC_VERSION__ >= 199901L /* C99 */ +/* "restrict" is a known keyword */ +#else +/* Disable restrict */ +#define restrict +#endif + +#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) + +#ifdef _MSC_VER +/* Visual Studio */ +/* Visual is not C99, but supports some kind of inline */ +#define inline __forceinline +#if LZ4_ARCH64 +/* For Visual 2005 */ +#pragma intrinsic(_BitScanForward64) +#pragma intrinsic(_BitScanReverse64) +#else /* !LZ4_ARCH64 */ +/* For Visual 2005 */ +#pragma intrinsic(_BitScanForward) +#pragma intrinsic(_BitScanReverse) +#endif /* !LZ4_ARCH64 */ +#endif /* _MSC_VER */ + +#ifdef _MSC_VER +#define lz4_bswap16(x) _byteswap_ushort(x) +#else /* !_MSC_VER */ +#define lz4_bswap16(x) ((unsigned short int) ((((x) >> 8) & 0xffu) | \ + (((x) & 0xffu) << 8))) +#endif /* !_MSC_VER */ + +#if (GCC_VERSION >= 302) || (__INTEL_COMPILER >= 800) || defined(__clang__) +#define expect(expr, value) (__builtin_expect((expr), (value))) +#else +#define expect(expr, value) (expr) +#endif + +#define likely(expr) expect((expr) != 0, 1) +#define unlikely(expr) expect((expr) != 0, 0) + +/* Basic types */ +#if defined(_MSC_VER) +/* Visual Studio does not support 'stdint' natively */ +#define BYTE unsigned __int8 +#define U16 unsigned __int16 +#define U32 unsigned __int32 +#define S32 __int32 +#define U64 unsigned __int64 +#else /* !defined(_MSC_VER) */ +#define BYTE uint8_t +#define U16 uint16_t +#define U32 uint32_t +#define S32 int32_t +#define U64 uint64_t +#endif /* !defined(_MSC_VER) */ + +#ifndef LZ4_FORCE_UNALIGNED_ACCESS +#pragma pack(1) +#endif + +typedef struct _U16_S { + U16 v; +} U16_S; +typedef struct _U32_S { + U32 v; +} U32_S; +typedef struct _U64_S { + U64 v; +} U64_S; + +#ifndef LZ4_FORCE_UNALIGNED_ACCESS +#pragma pack() +#endif + +#define A64(x) (((U64_S *)(x))->v) +#define A32(x) (((U32_S *)(x))->v) +#define A16(x) (((U16_S *)(x))->v) + +/* + * Constants + */ +#define MINMATCH 4 + +#define HASH_LOG COMPRESSIONLEVEL +#define HASHTABLESIZE (1 << HASH_LOG) +#define HASH_MASK (HASHTABLESIZE - 1) + +#define SKIPSTRENGTH (NOTCOMPRESSIBLE_CONFIRMATION > 2 ? \ + NOTCOMPRESSIBLE_CONFIRMATION : 2) + +/* + * Defines if memory is allocated into the stack (local variable), + * or into the heap (kmem_alloc()). + */ +#define HEAPMODE (HASH_LOG > STACKLIMIT) +#define COPYLENGTH 8 +#define LASTLITERALS 5 +#define MFLIMIT (COPYLENGTH + MINMATCH) +#define MINLENGTH (MFLIMIT + 1) + +#define MAXD_LOG 16 +#define MAX_DISTANCE ((1 << MAXD_LOG) - 1) + +#define ML_BITS 4 +#define ML_MASK ((1U<> ((MINMATCH * 8) - \ + HASH_LOG)) +#define LZ4_HASH_VALUE(p) LZ4_HASH_FUNCTION(A32(p)) +#define LZ4_WILDCOPY(s, d, e) do { LZ4_COPYPACKET(s, d) } while (d < e); +#define LZ4_BLINDCOPY(s, d, l) { BYTE* e = (d) + l; LZ4_WILDCOPY(s, d, e); \ + d = e; } + + +/* Private functions */ +#if LZ4_ARCH64 + +static inline int +LZ4_NbCommonBytes(register U64 val) +{ +#if defined(LZ4_BIG_ENDIAN) +#if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) + unsigned long r = 0; + _BitScanReverse64(&r, val); + return (int)(r >> 3); +#elif defined(__GNUC__) && (GCC_VERSION >= 304) && \ + !defined(LZ4_FORCE_SW_BITCOUNT) + return (__builtin_clzll(val) >> 3); +#else + int r; + if (!(val >> 32)) { + r = 4; + } else { + r = 0; + val >>= 32; + } + if (!(val >> 16)) { + r += 2; + val >>= 8; + } else { + val >>= 24; + } + r += (!val); + return (r); +#endif +#else +#if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) + unsigned long r = 0; + _BitScanForward64(&r, val); + return (int)(r >> 3); +#elif defined(__GNUC__) && (GCC_VERSION >= 304) && \ + !defined(LZ4_FORCE_SW_BITCOUNT) + return (__builtin_ctzll(val) >> 3); +#else + static const int DeBruijnBytePos[64] = + { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, + 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, + 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, + 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 + }; + return DeBruijnBytePos[((U64) ((val & -val) * 0x0218A392CDABBD3F)) >> + 58]; +#endif +#endif +} + +#else + +static inline int +LZ4_NbCommonBytes(register U32 val) +{ +#if defined(LZ4_BIG_ENDIAN) +#if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) + unsigned long r = 0; + _BitScanReverse(&r, val); + return (int)(r >> 3); +#elif defined(__GNUC__) && (GCC_VERSION >= 304) && \ + !defined(LZ4_FORCE_SW_BITCOUNT) + return (__builtin_clz(val) >> 3); +#else + int r; + if (!(val >> 16)) { + r = 2; + val >>= 8; + } else { + r = 0; + val >>= 24; + } + r += (!val); + return (r); +#endif +#else +#if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) + unsigned long r = 0; + _BitScanForward(&r, val); + return (int)(r >> 3); +#elif defined(__GNUC__) && (GCC_VERSION >= 304) && \ + !defined(LZ4_FORCE_SW_BITCOUNT) + return (__builtin_ctz(val) >> 3); +#else + static const int DeBruijnBytePos[32] = { + 0, 0, 3, 0, 3, 1, 3, 0, + 3, 2, 2, 1, 3, 2, 0, 1, + 3, 3, 1, 2, 2, 2, 2, 0, + 3, 1, 2, 0, 1, 0, 1, 1 + }; + return DeBruijnBytePos[((U32) ((val & -(S32) val) * 0x077CB531U)) >> + 27]; +#endif +#endif +} + +#endif + +/* Public functions */ + +static int +LZ4_compressBound(int isize) +{ + return (isize + (isize / 255) + 16); +} + +/* Compression functions */ + +/*ARGSUSED*/ +static int +LZ4_compressCtx(void *ctx, const char *source, char *dest, int isize, + int osize) +{ +#if HEAPMODE + struct refTables *srt = (struct refTables *)ctx; + HTYPE *HashTable = (HTYPE *) (srt->hashTable); +#else + HTYPE HashTable[HASHTABLESIZE] = { 0 }; +#endif + + const BYTE *ip = (BYTE *) source; + INITBASE(base); + const BYTE *anchor = ip; + const BYTE *const iend = ip + isize; + const BYTE *const oend = (BYTE *) dest + osize; + const BYTE *const mflimit = iend - MFLIMIT; +#define matchlimit (iend - LASTLITERALS) + + BYTE *op = (BYTE *) dest; + + int len, length; + const int skipStrength = SKIPSTRENGTH; + U32 forwardH; + + + /* Init */ + if (isize < MINLENGTH) + goto _last_literals; + + /* First Byte */ + HashTable[LZ4_HASH_VALUE(ip)] = ip - base; + ip++; + forwardH = LZ4_HASH_VALUE(ip); + + /* Main Loop */ + for (;;) { + int findMatchAttempts = (1U << skipStrength) + 3; + const BYTE *forwardIp = ip; + const BYTE *ref; + BYTE *token; + + /* Find a match */ + do { + U32 h = forwardH; + int step = findMatchAttempts++ >> skipStrength; + ip = forwardIp; + forwardIp = ip + step; + + if unlikely(forwardIp > mflimit) { + goto _last_literals; + } + + forwardH = LZ4_HASH_VALUE(forwardIp); + ref = base + HashTable[h]; + HashTable[h] = ip - base; + + } while ((ref < ip - MAX_DISTANCE) || (A32(ref) != A32(ip))); + + /* Catch up */ + while ((ip > anchor) && (ref > (BYTE *) source) && + unlikely(ip[-1] == ref[-1])) { + ip--; + ref--; + } + + /* Encode Literal length */ + length = ip - anchor; + token = op++; + + /* Check output limit */ + if unlikely(op + length + (2 + 1 + LASTLITERALS) + + (length >> 8) > oend) + return (0); + + if (length >= (int)RUN_MASK) { + *token = (RUN_MASK << ML_BITS); + len = length - RUN_MASK; + for (; len > 254; len -= 255) + *op++ = 255; + *op++ = (BYTE)len; + } else + *token = (length << ML_BITS); + + /* Copy Literals */ + LZ4_BLINDCOPY(anchor, op, length); + + _next_match: + /* Encode Offset */ + LZ4_WRITE_LITTLEENDIAN_16(op, ip - ref); + + /* Start Counting */ + ip += MINMATCH; + ref += MINMATCH; /* MinMatch verified */ + anchor = ip; + while likely(ip < matchlimit - (STEPSIZE - 1)) { + UARCH diff = AARCH(ref) ^ AARCH(ip); + if (!diff) { + ip += STEPSIZE; + ref += STEPSIZE; + continue; + } + ip += LZ4_NbCommonBytes(diff); + goto _endCount; + } +#if LZ4_ARCH64 + if ((ip < (matchlimit - 3)) && (A32(ref) == A32(ip))) { + ip += 4; + ref += 4; + } +#endif + if ((ip < (matchlimit - 1)) && (A16(ref) == A16(ip))) { + ip += 2; + ref += 2; + } + if ((ip < matchlimit) && (*ref == *ip)) + ip++; + _endCount: + + /* Encode MatchLength */ + len = (ip - anchor); + /* Check output limit */ + if unlikely(op + (1 + LASTLITERALS) + (len >> 8) > oend) + return (0); + if (len >= (int)ML_MASK) { + *token += ML_MASK; + len -= ML_MASK; + for (; len > 509; len -= 510) { + *op++ = 255; + *op++ = 255; + } + if (len > 254) { + len -= 255; + *op++ = 255; + } + *op++ = (BYTE)len; + } else + *token += len; + + /* Test end of chunk */ + if (ip > mflimit) { + anchor = ip; + break; + } + /* Fill table */ + HashTable[LZ4_HASH_VALUE(ip - 2)] = ip - 2 - base; + + /* Test next position */ + ref = base + HashTable[LZ4_HASH_VALUE(ip)]; + HashTable[LZ4_HASH_VALUE(ip)] = ip - base; + if ((ref > ip - (MAX_DISTANCE + 1)) && (A32(ref) == A32(ip))) { + token = op++; + *token = 0; + goto _next_match; + } + /* Prepare next loop */ + anchor = ip++; + forwardH = LZ4_HASH_VALUE(ip); + } + + _last_literals: + /* Encode Last Literals */ + { + int lastRun = iend - anchor; + if (op + lastRun + 1 + ((lastRun + 255 - RUN_MASK) / 255) > + oend) + return (0); + if (lastRun >= (int)RUN_MASK) { + *op++ = (RUN_MASK << ML_BITS); + lastRun -= RUN_MASK; + for (; lastRun > 254; lastRun -= 255) { + *op++ = 255; + } + *op++ = (BYTE)lastRun; + } else + *op++ = (lastRun << ML_BITS); + (void) memcpy(op, anchor, iend - anchor); + op += iend - anchor; + } + + /* End */ + return (int)(((char *)op) - dest); +} + + + +/* Note : this function is valid only if isize < LZ4_64KLIMIT */ +#define LZ4_64KLIMIT ((1 << 16) + (MFLIMIT - 1)) +#define HASHLOG64K (HASH_LOG + 1) +#define HASH64KTABLESIZE (1U << HASHLOG64K) +#define LZ4_HASH64K_FUNCTION(i) (((i) * 2654435761U) >> ((MINMATCH*8) - \ + HASHLOG64K)) +#define LZ4_HASH64K_VALUE(p) LZ4_HASH64K_FUNCTION(A32(p)) + +/*ARGSUSED*/ +static int +LZ4_compress64kCtx(void *ctx, const char *source, char *dest, int isize, + int osize) +{ +#if HEAPMODE + struct refTables *srt = (struct refTables *)ctx; + U16 *HashTable = (U16 *) (srt->hashTable); +#else + U16 HashTable[HASH64KTABLESIZE] = { 0 }; +#endif + + const BYTE *ip = (BYTE *) source; + const BYTE *anchor = ip; + const BYTE *const base = ip; + const BYTE *const iend = ip + isize; + const BYTE *const oend = (BYTE *) dest + osize; + const BYTE *const mflimit = iend - MFLIMIT; +#define matchlimit (iend - LASTLITERALS) + + BYTE *op = (BYTE *) dest; + + int len, length; + const int skipStrength = SKIPSTRENGTH; + U32 forwardH; + + /* Init */ + if (isize < MINLENGTH) + goto _last_literals; + + /* First Byte */ + ip++; + forwardH = LZ4_HASH64K_VALUE(ip); + + /* Main Loop */ + for (;;) { + int findMatchAttempts = (1U << skipStrength) + 3; + const BYTE *forwardIp = ip; + const BYTE *ref; + BYTE *token; + + /* Find a match */ + do { + U32 h = forwardH; + int step = findMatchAttempts++ >> skipStrength; + ip = forwardIp; + forwardIp = ip + step; + + if (forwardIp > mflimit) { + goto _last_literals; + } + + forwardH = LZ4_HASH64K_VALUE(forwardIp); + ref = base + HashTable[h]; + HashTable[h] = ip - base; + + } while (A32(ref) != A32(ip)); + + /* Catch up */ + while ((ip > anchor) && (ref > (BYTE *) source) && + (ip[-1] == ref[-1])) { + ip--; + ref--; + } + + /* Encode Literal length */ + length = ip - anchor; + token = op++; + + /* Check output limit */ + if unlikely(op + length + (2 + 1 + LASTLITERALS) + + (length >> 8) > oend) + return (0); + + if (length >= (int)RUN_MASK) { + *token = (RUN_MASK << ML_BITS); + len = length - RUN_MASK; + for (; len > 254; len -= 255) + *op++ = 255; + *op++ = (BYTE)len; + } else + *token = (length << ML_BITS); + + /* Copy Literals */ + LZ4_BLINDCOPY(anchor, op, length); + + _next_match: + /* Encode Offset */ + LZ4_WRITE_LITTLEENDIAN_16(op, ip - ref); + + /* Start Counting */ + ip += MINMATCH; + ref += MINMATCH; /* MinMatch verified */ + anchor = ip; + while (ip < matchlimit - (STEPSIZE - 1)) { + UARCH diff = AARCH(ref) ^ AARCH(ip); + if (!diff) { + ip += STEPSIZE; + ref += STEPSIZE; + continue; + } + ip += LZ4_NbCommonBytes(diff); + goto _endCount; + } +#if LZ4_ARCH64 + if ((ip < (matchlimit - 3)) && (A32(ref) == A32(ip))) { + ip += 4; + ref += 4; + } +#endif + if ((ip < (matchlimit - 1)) && (A16(ref) == A16(ip))) { + ip += 2; + ref += 2; + } + if ((ip < matchlimit) && (*ref == *ip)) + ip++; + _endCount: + + /* Encode MatchLength */ + len = (ip - anchor); + /* Check output limit */ + if unlikely(op + (1 + LASTLITERALS) + (len >> 8) > oend) + return (0); + if (len >= (int)ML_MASK) { + *token += ML_MASK; + len -= ML_MASK; + for (; len > 509; len -= 510) { + *op++ = 255; + *op++ = 255; + } + if (len > 254) { + len -= 255; + *op++ = 255; + } + *op++ = (BYTE)len; + } else + *token += len; + + /* Test end of chunk */ + if (ip > mflimit) { + anchor = ip; + break; + } + /* Fill table */ + HashTable[LZ4_HASH64K_VALUE(ip - 2)] = ip - 2 - base; + + /* Test next position */ + ref = base + HashTable[LZ4_HASH64K_VALUE(ip)]; + HashTable[LZ4_HASH64K_VALUE(ip)] = ip - base; + if (A32(ref) == A32(ip)) { + token = op++; + *token = 0; + goto _next_match; + } + /* Prepare next loop */ + anchor = ip++; + forwardH = LZ4_HASH64K_VALUE(ip); + } + + _last_literals: + /* Encode Last Literals */ + { + int lastRun = iend - anchor; + if (op + lastRun + 1 + ((lastRun + 255 - RUN_MASK) / 255) > + oend) + return (0); + if (lastRun >= (int)RUN_MASK) { + *op++ = (RUN_MASK << ML_BITS); + lastRun -= RUN_MASK; + for (; lastRun > 254; lastRun -= 255) + *op++ = 255; + *op++ = (BYTE)lastRun; + } else + *op++ = (lastRun << ML_BITS); + (void) memcpy(op, anchor, iend - anchor); + op += iend - anchor; + } + + /* End */ + return (int)(((char *)op) - dest); +} + +static int +real_LZ4_compress(const char *source, char *dest, int isize, int osize) +{ +#if HEAPMODE + void *ctx = kmem_zalloc(sizeof (struct refTables), KM_NOSLEEP); + int result; + + /* + * out of kernel memory, gently fall through - this will disable + * compression in zio_compress_data + */ + if (ctx == NULL) + return (0); + + if (isize < LZ4_64KLIMIT) + result = LZ4_compress64kCtx(ctx, source, dest, isize, osize); + else + result = LZ4_compressCtx(ctx, source, dest, isize, osize); + + kmem_free(ctx, sizeof (struct refTables)); + return (result); +#else + if (isize < (int)LZ4_64KLIMIT) + return (LZ4_compress64kCtx(NULL, source, dest, isize, osize)); + return (LZ4_compressCtx(NULL, source, dest, isize, osize)); +#endif +} + +/* Decompression functions */ + +/* + * Note: The decoding functions real_LZ4_uncompress() and + * LZ4_uncompress_unknownOutputSize() are safe against "buffer overflow" + * attack type. They will never write nor read outside of the provided + * output buffers. LZ4_uncompress_unknownOutputSize() also insures that + * it will never read outside of the input buffer. A corrupted input + * will produce an error result, a negative int, indicating the position + * of the error within input stream. + */ + +static int +real_LZ4_uncompress(const char *source, char *dest, int osize) +{ + /* Local Variables */ + const BYTE *restrict ip = (const BYTE *) source; + const BYTE *ref; + + BYTE *op = (BYTE *) dest; + BYTE *const oend = op + osize; + BYTE *cpy; + + unsigned token; + + size_t length; + size_t dec32table[] = {0, 3, 2, 3, 0, 0, 0, 0}; +#if LZ4_ARCH64 + size_t dec64table[] = {0, 0, 0, (size_t)-1, 0, 1, 2, 3}; +#endif + + /* Main Loop */ + for (;;) { + /* get runlength */ + token = *ip++; + if ((length = (token >> ML_BITS)) == RUN_MASK) { + size_t len; + for (; (len = *ip++) == 255; length += 255) { + } + length += len; + } + /* copy literals */ + cpy = op + length; + if unlikely(cpy > oend - COPYLENGTH) { + if (cpy != oend) + /* Error: we must necessarily stand at EOF */ + goto _output_error; + (void) memcpy(op, ip, length); + ip += length; + break; /* EOF */ + } + LZ4_WILDCOPY(ip, op, cpy); + ip -= (op - cpy); + op = cpy; + + /* get offset */ + LZ4_READ_LITTLEENDIAN_16(ref, cpy, ip); + ip += 2; + if unlikely(ref < (BYTE * const) dest) + /* + * Error: offset create reference outside destination + * buffer + */ + goto _output_error; + + /* get matchlength */ + if ((length = (token & ML_MASK)) == ML_MASK) { + for (; *ip == 255; length += 255) { + ip++; + } + length += *ip++; + } + /* copy repeated sequence */ + if unlikely(op - ref < STEPSIZE) { +#if LZ4_ARCH64 + size_t dec64 = dec64table[op-ref]; +#else + const int dec64 = 0; +#endif + op[0] = ref[0]; + op[1] = ref[1]; + op[2] = ref[2]; + op[3] = ref[3]; + op += 4; + ref += 4; + ref -= dec32table[op-ref]; + A32(op) = A32(ref); + op += STEPSIZE - 4; + ref -= dec64; + } else { + LZ4_COPYSTEP(ref, op); + } + cpy = op + length - (STEPSIZE - 4); + if (cpy > oend - COPYLENGTH) { + if (cpy > oend) + /* + * Error: request to write beyond destination + * buffer + */ + goto _output_error; + LZ4_SECURECOPY(ref, op, (oend - COPYLENGTH)); + while (op < cpy) + *op++ = *ref++; + op = cpy; + if (op == oend) + /* + * Check EOF (should never happen, since last + * 5 bytes are supposed to be literals) + */ + goto _output_error; + continue; + } + LZ4_SECURECOPY(ref, op, cpy); + op = cpy; /* correction */ + } + + /* end of decoding */ + return (int)(((char *)ip) - source); + + /* write overflow error detected */ + _output_error: + return (int)(-(((char *)ip) - source)); +} + +static int +LZ4_uncompress_unknownOutputSize(const char *source, char *dest, int isize, + int maxOutputSize) +{ + /* Local Variables */ + const BYTE *restrict ip = (const BYTE *) source; + const BYTE *const iend = ip + isize; + const BYTE *ref; + + BYTE *op = (BYTE *) dest; + BYTE *const oend = op + maxOutputSize; + BYTE *cpy; + + size_t dec32table[] = {0, 3, 2, 3, 0, 0, 0, 0}; +#if LZ4_ARCH64 + size_t dec64table[] = {0, 0, 0, (size_t)-1, 0, 1, 2, 3}; +#endif + + /* Main Loop */ + while (ip < iend) { + unsigned token; + size_t length; + + /* get runlength */ + token = *ip++; + if ((length = (token >> ML_BITS)) == RUN_MASK) { + int s = 255; + while ((ip < iend) && (s == 255)) { + s = *ip++; + length += s; + } + } + /* copy literals */ + cpy = op + length; + if ((cpy > oend - COPYLENGTH) || + (ip + length > iend - COPYLENGTH)) { + if (cpy > oend) + /* Error: writes beyond output buffer */ + goto _output_error; + if (ip + length != iend) + /* + * Error: LZ4 format requires to consume all + * input at this stage + */ + goto _output_error; + (void) memcpy(op, ip, length); + op += length; + /* Necessarily EOF, due to parsing restrictions */ + break; + } + LZ4_WILDCOPY(ip, op, cpy); + ip -= (op - cpy); + op = cpy; + + /* get offset */ + LZ4_READ_LITTLEENDIAN_16(ref, cpy, ip); + ip += 2; + if (ref < (BYTE * const) dest) + /* + * Error: offset creates reference outside of + * destination buffer + */ + goto _output_error; + + /* get matchlength */ + if ((length = (token & ML_MASK)) == ML_MASK) { + while (ip < iend) { + int s = *ip++; + length += s; + if (s == 255) + continue; + break; + } + } + /* copy repeated sequence */ + if unlikely(op - ref < STEPSIZE) { +#if LZ4_ARCH64 + size_t dec64 = dec64table[op-ref]; +#else + const int dec64 = 0; +#endif + op[0] = ref[0]; + op[1] = ref[1]; + op[2] = ref[2]; + op[3] = ref[3]; + op += 4; + ref += 4; + ref -= dec32table[op-ref]; + A32(op) = A32(ref); + op += STEPSIZE - 4; + ref -= dec64; + } else { + LZ4_COPYSTEP(ref, op); + } + cpy = op + length - (STEPSIZE - 4); + if (cpy > oend - COPYLENGTH) { + if (cpy > oend) + /* + * Error: request to write outside of + * destination buffer + */ + goto _output_error; + LZ4_SECURECOPY(ref, op, (oend - COPYLENGTH)); + while (op < cpy) + *op++ = *ref++; + op = cpy; + if (op == oend) + /* + * Check EOF (should never happen, since + * last 5 bytes are supposed to be literals) + */ + goto _output_error; + continue; + } + LZ4_SECURECOPY(ref, op, cpy); + op = cpy; /* correction */ + } + + /* end of decoding */ + return (int)(((char *)op) - dest); + + /* write overflow error detected */ + _output_error: + return (int)(-(((char *)ip) - source)); +} diff --git a/uts/common/fs/zfs/sys/zio.h b/uts/common/fs/zfs/sys/zio.h index 184d4da97bd..ebbd4f83065 100644 --- a/uts/common/fs/zfs/sys/zio.h +++ b/uts/common/fs/zfs/sys/zio.h @@ -23,6 +23,7 @@ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2012 by Delphix. All rights reserved. + * Copyright (c) 2013 by Saso Kiselkov. All rights reserved. */ #ifndef _ZIO_H @@ -106,14 +107,17 @@ enum zio_compress { ZIO_COMPRESS_GZIP_8, ZIO_COMPRESS_GZIP_9, ZIO_COMPRESS_ZLE, + ZIO_COMPRESS_LZ4, ZIO_COMPRESS_FUNCTIONS }; +/* N.B. when altering this value, also change BOOTFS_COMPRESS_VALID below */ #define ZIO_COMPRESS_ON_VALUE ZIO_COMPRESS_LZJB #define ZIO_COMPRESS_DEFAULT ZIO_COMPRESS_OFF #define BOOTFS_COMPRESS_VALID(compress) \ ((compress) == ZIO_COMPRESS_LZJB || \ + (compress) == ZIO_COMPRESS_LZ4 || \ ((compress) == ZIO_COMPRESS_ON && \ ZIO_COMPRESS_ON_VALUE == ZIO_COMPRESS_LZJB) || \ (compress) == ZIO_COMPRESS_OFF) diff --git a/uts/common/fs/zfs/sys/zio_compress.h b/uts/common/fs/zfs/sys/zio_compress.h index 30bed1a676e..34a82a8b818 100644 --- a/uts/common/fs/zfs/sys/zio_compress.h +++ b/uts/common/fs/zfs/sys/zio_compress.h @@ -23,6 +23,9 @@ * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright (c) 2013 by Saso Kiselkov. All rights reserved. + */ #ifndef _SYS_ZIO_COMPRESS_H #define _SYS_ZIO_COMPRESS_H @@ -68,6 +71,10 @@ extern size_t zle_compress(void *src, void *dst, size_t s_len, size_t d_len, int level); extern int zle_decompress(void *src, void *dst, size_t s_len, size_t d_len, int level); +extern size_t lz4_compress(void *src, void *dst, size_t s_len, size_t d_len, + int level); +extern int lz4_decompress(void *src, void *dst, size_t s_len, size_t d_len, + int level); /* * Compress and decompress data if necessary. diff --git a/uts/common/fs/zfs/zfs_ioctl.c b/uts/common/fs/zfs/zfs_ioctl.c index 723d516552f..d7c71044f92 100644 --- a/uts/common/fs/zfs/zfs_ioctl.c +++ b/uts/common/fs/zfs/zfs_ioctl.c @@ -25,6 +25,7 @@ * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2012, Joyent, Inc. All rights reserved. * Copyright (c) 2012 by Delphix. All rights reserved. + * Copyright (c) 2013 by Saso Kiselkov. All rights reserved. */ /* @@ -172,6 +173,7 @@ #include #include #include +#include #include "zfs_namecheck.h" #include "zfs_prop.h" @@ -235,6 +237,12 @@ static int zfs_fill_zplprops_root(uint64_t, nvlist_t *, nvlist_t *, int zfs_set_prop_nvlist(const char *, zprop_source_t, nvlist_t *, nvlist_t *); static int get_nvlist(uint64_t nvl, uint64_t size, int iflag, nvlist_t **nvp); +static int zfs_prop_activate_feature(dsl_pool_t *dp, zfeature_info_t *feature); +static int zfs_prop_activate_feature_check(void *arg1, void *arg2, + dmu_tx_t *tx); +static void zfs_prop_activate_feature_sync(void *arg1, void *arg2, + dmu_tx_t *tx); + /* _NOTE(PRINTFLIKE(4)) - this is printf-like, but lint is too whiney */ void __dprintf(const char *file, const char *func, int line, const char *fmt, ...) @@ -2383,6 +2391,40 @@ zfs_prop_set_special(const char *dsname, zprop_source_t source, } break; } + case ZFS_PROP_COMPRESSION: + { + if (intval == ZIO_COMPRESS_LZ4) { + zfeature_info_t *feature = + &spa_feature_table[SPA_FEATURE_LZ4_COMPRESS]; + spa_t *spa; + dsl_pool_t *dp; + + if ((err = spa_open(dsname, &spa, FTAG)) != 0) + return (err); + + dp = spa->spa_dsl_pool; + + /* + * Setting the LZ4 compression algorithm activates + * the feature. + */ + if (!spa_feature_is_active(spa, feature)) { + if ((err = zfs_prop_activate_feature(dp, + feature)) != 0) { + spa_close(spa, FTAG); + return (err); + } + } + + spa_close(spa, FTAG); + } + /* + * We still want the default set action to be performed in the + * caller, we only performed zfeature settings here. + */ + err = -1; + break; + } default: err = -1; @@ -3627,6 +3669,22 @@ zfs_check_settable(const char *dsname, nvpair_t *pair, cred_t *cr) SPA_VERSION_ZLE_COMPRESSION)) return (ENOTSUP); + if (intval == ZIO_COMPRESS_LZ4) { + zfeature_info_t *feature = + &spa_feature_table[ + SPA_FEATURE_LZ4_COMPRESS]; + spa_t *spa; + + if ((err = spa_open(dsname, &spa, FTAG)) != 0) + return (err); + + if (!spa_feature_is_enabled(spa, feature)) { + spa_close(spa, FTAG); + return (ENOTSUP); + } + spa_close(spa, FTAG); + } + /* * If this is a bootable dataset then * verify that the compression algorithm @@ -3670,6 +3728,56 @@ zfs_check_settable(const char *dsname, nvpair_t *pair, cred_t *cr) return (zfs_secpolicy_setprop(dsname, prop, pair, CRED())); } +/* + * Activates a feature on a pool in response to a property setting. This + * creates a new sync task which modifies the pool to reflect the feature + * as being active. + */ +static int +zfs_prop_activate_feature(dsl_pool_t *dp, zfeature_info_t *feature) +{ + int err; + + /* EBUSY here indicates that the feature is already active */ + err = dsl_sync_task_do(dp, zfs_prop_activate_feature_check, + zfs_prop_activate_feature_sync, dp->dp_spa, feature, 2); + + if (err != 0 && err != EBUSY) + return (err); + else + return (0); +} + +/* + * Checks for a race condition to make sure we don't increment a feature flag + * multiple times. + */ +/*ARGSUSED*/ +static int +zfs_prop_activate_feature_check(void *arg1, void *arg2, dmu_tx_t *tx) +{ + spa_t *spa = arg1; + zfeature_info_t *feature = arg2; + + if (!spa_feature_is_active(spa, feature)) + return (0); + else + return (EBUSY); +} + +/* + * The callback invoked on feature activation in the sync task caused by + * zfs_prop_activate_feature. + */ +static void +zfs_prop_activate_feature_sync(void *arg1, void *arg2, dmu_tx_t *tx) +{ + spa_t *spa = arg1; + zfeature_info_t *feature = arg2; + + spa_feature_incr(spa, feature, tx); +} + /* * Removes properties from the given props list that fail permission checks * needed to clear them and to restore them in case of a receive error. For each diff --git a/uts/common/fs/zfs/zio_compress.c b/uts/common/fs/zfs/zio_compress.c index f148977c446..1dc780d4bf6 100644 --- a/uts/common/fs/zfs/zio_compress.c +++ b/uts/common/fs/zfs/zio_compress.c @@ -23,6 +23,9 @@ * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright (c) 2013 by Saso Kiselkov. All rights reserved. + */ #include #include @@ -50,6 +53,7 @@ zio_compress_info_t zio_compress_table[ZIO_COMPRESS_FUNCTIONS] = { {gzip_compress, gzip_decompress, 8, "gzip-8"}, {gzip_compress, gzip_decompress, 9, "gzip-9"}, {zle_compress, zle_decompress, 64, "zle"}, + {lz4_compress, lz4_decompress, 0, "lz4"}, }; enum zio_compress From f056fd4daf3de662692c67c4581f2b6ef0839506 Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Wed, 6 Feb 2013 07:54:46 +0000 Subject: [PATCH 0004/1476] Update vendor/illumos/dist and vendor-sys/illumos/dist to illumos-gate 13934:9e23a7f7b812 Illumos ZFS issues: 3422 zpool create/syseventd race yield non-importable pool 3425 first write to a new zvol can fail with EFBIG --- lib/libzfs/common/libzfs_import.c | 8 +------- uts/common/fs/zfs/dmu_tx.c | 10 ++-------- uts/common/fs/zfs/vdev.c | 5 +++-- 3 files changed, 6 insertions(+), 17 deletions(-) diff --git a/lib/libzfs/common/libzfs_import.c b/lib/libzfs/common/libzfs_import.c index 36d7420c3bb..ee29c7bbbc4 100644 --- a/lib/libzfs/common/libzfs_import.c +++ b/lib/libzfs/common/libzfs_import.c @@ -528,13 +528,12 @@ get_configs(libzfs_handle_t *hdl, pool_list_t *pl, boolean_t active_ok) * version * pool guid * name - * pool txg (if available) * comment (if available) * pool state * hostid (if available) * hostname (if available) */ - uint64_t state, version, pool_txg; + uint64_t state, version; char *comment = NULL; version = fnvlist_lookup_uint64(tmp, @@ -550,11 +549,6 @@ get_configs(libzfs_handle_t *hdl, pool_list_t *pl, boolean_t active_ok) fnvlist_add_string(config, ZPOOL_CONFIG_POOL_NAME, name); - if (nvlist_lookup_uint64(tmp, - ZPOOL_CONFIG_POOL_TXG, &pool_txg) == 0) - fnvlist_add_uint64(config, - ZPOOL_CONFIG_POOL_TXG, pool_txg); - if (nvlist_lookup_string(tmp, ZPOOL_CONFIG_COMMENT, &comment) == 0) fnvlist_add_string(config, diff --git a/uts/common/fs/zfs/dmu_tx.c b/uts/common/fs/zfs/dmu_tx.c index e44786f1631..556ae6a83a5 100644 --- a/uts/common/fs/zfs/dmu_tx.c +++ b/uts/common/fs/zfs/dmu_tx.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved. - * Copyright (c) 2012 by Delphix. All rights reserved. + * Copyright (c) 2013 by Delphix. All rights reserved. */ #include @@ -284,6 +284,7 @@ dmu_tx_count_write(dmu_tx_hold_t *txh, uint64_t off, uint64_t len) delta = P2NPHASE(off, dn->dn_datablksz); } + min_ibs = max_ibs = dn->dn_indblkshift; if (dn->dn_maxblkid > 0) { /* * The blocksize can't change, @@ -291,13 +292,6 @@ dmu_tx_count_write(dmu_tx_hold_t *txh, uint64_t off, uint64_t len) */ ASSERT(dn->dn_datablkshift != 0); min_bs = max_bs = dn->dn_datablkshift; - min_ibs = max_ibs = dn->dn_indblkshift; - } else if (dn->dn_indblkshift > max_ibs) { - /* - * This ensures that if we reduce DN_MAX_INDBLKSHIFT, - * the code will still work correctly on older pools. - */ - min_ibs = max_ibs = dn->dn_indblkshift; } /* diff --git a/uts/common/fs/zfs/vdev.c b/uts/common/fs/zfs/vdev.c index 18180ecad34..4f5c4e9c4df 100644 --- a/uts/common/fs/zfs/vdev.c +++ b/uts/common/fs/zfs/vdev.c @@ -1327,7 +1327,8 @@ vdev_validate(vdev_t *vd, boolean_t strict) if (vd->vdev_ops->vdev_op_leaf && vdev_readable(vd)) { uint64_t aux_guid = 0; nvlist_t *nvl; - uint64_t txg = strict ? spa->spa_config_txg : -1ULL; + uint64_t txg = spa_last_synced_txg(spa) != 0 ? + spa_last_synced_txg(spa) : -1ULL; if ((label = vdev_label_read_config(vd, txg)) == NULL) { vdev_set_state(vd, B_TRUE, VDEV_STATE_CANT_OPEN, @@ -1511,7 +1512,7 @@ vdev_reopen(vdev_t *vd) !l2arc_vdev_present(vd)) l2arc_add_vdev(spa, vd); } else { - (void) vdev_validate(vd, spa_last_synced_txg(spa)); + (void) vdev_validate(vd, B_TRUE); } /* From 35f5e42185e96bbcc21a93f5580704ca39ba3002 Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Wed, 6 Feb 2013 07:59:14 +0000 Subject: [PATCH 0005/1476] Update vendor/illumos/dist to illumos-gate version 13936:60077db1e2cc Illumos ZFS issues: 3380 zfs man page: documentation for zfs allow is confusing --- man/man1m/zfs.1m | 151 +++++++++++++++++++++++++---------------------- 1 file changed, 82 insertions(+), 69 deletions(-) diff --git a/man/man1m/zfs.1m b/man/man1m/zfs.1m index fc3e899e53e..10382efa785 100644 --- a/man/man1m/zfs.1m +++ b/man/man1m/zfs.1m @@ -24,10 +24,10 @@ .\" Copyright 2011 Joshua M. Clulow .\" Copyright (c) 2012 by Delphix. All rights reserved. .\" Copyright (c) 2012, Joyent, Inc. All rights reserved. -.\" Copyright 2012 Nexenta Systems, Inc. All Rights Reserved. .\" Copyright (c) 2013 by Saso Kiselkov. All rights reserved. +.\" Copyright 2013 Nexenta Systems, Inc. All Rights Reserved. .\" -.TH ZFS 1M "Sep 16, 2012" +.TH ZFS 1M "Jan 26, 2013" .SH NAME zfs \- configures ZFS file systems .SH SYNOPSIS @@ -38,12 +38,12 @@ zfs \- configures ZFS file systems .LP .nf -\fBzfs\fR \fBcreate\fR [\fB-p\fR] [\fB-o\fR \fIproperty\fR=\fIvalue\fR] ... \fIfilesystem\fR +\fBzfs\fR \fBcreate\fR [\fB-p\fR] [\fB-o\fR \fIproperty\fR=\fIvalue\fR]... \fIfilesystem\fR .fi .LP .nf -\fBzfs\fR \fBcreate\fR [\fB-ps\fR] [\fB-b\fR \fIblocksize\fR] [\fB-o\fR \fIproperty\fR=\fIvalue\fR] ... \fB-V\fR \fIsize\fR \fIvolume\fR +\fBzfs\fR \fBcreate\fR [\fB-ps\fR] [\fB-b\fR \fIblocksize\fR] [\fB-o\fR \fIproperty\fR=\fIvalue\fR]... \fB-V\fR \fIsize\fR \fIvolume\fR .fi .LP @@ -53,7 +53,7 @@ zfs \- configures ZFS file systems .LP .nf -\fBzfs\fR \fBdestroy\fR [\fB-dnpRrv\fR] \fIfilesystem\fR|\fIvolume\fR@\fIsnap\fR[%\fIsnap\fR][,...] +\fBzfs\fR \fBdestroy\fR [\fB-dnpRrv\fR] \fIfilesystem\fR|\fIvolume\fR@\fIsnap\fR[%\fIsnap\fR][,\fIsnap\fR[%\fIsnap\fR]]... .fi .LP @@ -69,7 +69,7 @@ zfs \- configures ZFS file systems .LP .nf -\fBzfs\fR \fBclone\fR [\fB-p\fR] [\fB-o\fR \fIproperty\fR=\fIvalue\fR] ... \fIsnapshot\fR \fIfilesystem\fR|\fIvolume\fR +\fBzfs\fR \fBclone\fR [\fB-p\fR] [\fB-o\fR \fIproperty\fR=\fIvalue\fR]... \fIsnapshot\fR \fIfilesystem\fR|\fIvolume\fR .fi .LP @@ -95,24 +95,25 @@ zfs \- configures ZFS file systems .LP .nf -\fBzfs\fR \fBlist\fR [\fB-r\fR|\fB-d\fR \fIdepth\fR][\fB-H\fR][\fB-o\fR \fIproperty\fR[,...]] [\fB-t\fR \fItype\fR[,...]] - [\fB-s\fR \fIproperty\fR] ... [\fB-S\fR \fIproperty\fR] ... [\fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR] ... +\fBzfs\fR \fBlist\fR [\fB-r\fR|\fB-d\fR \fIdepth\fR][\fB-H\fR][\fB-o\fR \fIproperty\fR[,\fIproperty\fR]...] [\fB-t\fR \fItype\fR[,\fItype\fR]...] + [\fB-s\fR \fIproperty\fR]... [\fB-S\fR \fIproperty\fR]... [\fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR]... .fi .LP .nf -\fBzfs\fR \fBset\fR \fIproperty\fR=\fIvalue\fR \fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR ... +\fBzfs\fR \fBset\fR \fIproperty\fR=\fIvalue\fR \fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR... .fi .LP .nf -\fBzfs\fR \fBget\fR [\fB-r\fR|\fB-d\fR \fIdepth\fR][\fB-Hp\fR][\fB-o\fR \fIfield\fR[,...]] [\fB-t\fR \fItype\fR[,...]] - [\fB-s\fR \fIsource\fR[,...]] "\fIall\fR" | \fIproperty\fR[,...] \fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR ... +\fBzfs\fR \fBget\fR [\fB-r\fR|\fB-d\fR \fIdepth\fR][\fB-Hp\fR][\fB-o\fR \fIfield\fR[,\fIfield\fR]...] [\fB-t\fR \fItype\fR[,\fItype\fR]...] + [\fB-s\fR \fIsource\fR[,\fIsource\fR]...] \fBall\fR | \fIproperty\fR[,\fIproperty\fR]... + \fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR... .fi .LP .nf -\fBzfs\fR \fBinherit\fR [\fB-r\fR] \fIproperty\fR \fIfilesystem\fR|\fIvolume|snapshot\fR ... +\fBzfs\fR \fBinherit\fR [\fB-r\fR] \fIproperty\fR \fIfilesystem\fR|\fIvolume|snapshot\fR... .fi .LP @@ -127,14 +128,14 @@ zfs \- configures ZFS file systems .LP .nf -\fBzfs\fR \fBuserspace\fR [\fB-Hinp\fR] [\fB-o\fR \fIfield\fR[,...]] [\fB-s\fR \fIfield\fR] ... - [\fB-S\fR \fIfield\fR] ... [\fB-t\fR \fItype\fR[,...]] \fIfilesystem\fR|\fIsnapshot\fR +\fBzfs\fR \fBuserspace\fR [\fB-Hinp\fR] [\fB-o\fR \fIfield\fR[,\fIfield\fR]...] [\fB-s\fR \fIfield\fR]... + [\fB-S\fR \fIfield\fR]... [\fB-t\fR \fItype\fR[,\fItype\fR]...] \fIfilesystem\fR|\fIsnapshot\fR .fi .LP .nf -\fBzfs\fR \fBgroupspace\fR [\fB-Hinp\fR] [\fB-o\fR \fIfield\fR[,...]] [\fB-s\fR \fIfield\fR] ... - [\fB-S\fR \fIfield\fR] ... [\fB-t\fR \fItype\fR[,...]] \fIfilesystem\fR|\fIsnapshot\fR +\fBzfs\fR \fBgroupspace\fR [\fB-Hinp\fR] [\fB-o\fR \fIfield\fR[,\fIfield\fR]...] [\fB-s\fR \fIfield\fR]... + [\fB-S\fR \fIfield\fR]... [\fB-t\fR \fItype\fR[,\fItype\fR]...] \fIfilesystem\fR|\fIsnapshot\fR .fi .LP @@ -184,44 +185,47 @@ zfs \- configures ZFS file systems .LP .nf -\fBzfs\fR \fBallow\fR [\fB-ldug\fR] "\fIeveryone\fR"|\fIuser\fR|\fIgroup\fR[,...] \fIperm\fR|\fI@setname\fR[,...] +\fBzfs\fR \fBallow\fR [\fB-ldug\fR] \fIuser\fR|\fIgroup\fR[,\fIuser\fR|\fIgroup\fR]... + \fIperm\fR|\fI@setname\fR[,\fIperm\fR|\fI@setname\fR]... \fIfilesystem\fR|\fIvolume\fR +.fi + +.LP +.nf +\fBzfs\fR \fBallow\fR [\fB-ld\fR] \fB-e\fR|\fBeveryone\fR \fIperm\fR|@\fIsetname\fR[,\fIperm\fR|\fI@setname\fR]... \fIfilesystem\fR|\fIvolume\fR .fi .LP .nf -\fBzfs\fR \fBallow\fR [\fB-ld\fR] \fB-e\fR \fIperm\fR|@\fIsetname\fR[,...] \fIfilesystem\fR|\fIvolume\fR +\fBzfs\fR \fBallow\fR \fB-c\fR \fIperm\fR|@\fIsetname\fR[,\fIperm\fR|\fI@setname\fR]... \fIfilesystem\fR|\fIvolume\fR .fi .LP .nf -\fBzfs\fR \fBallow\fR \fB-c\fR \fIperm\fR|@\fIsetname\fR[,...] \fIfilesystem\fR|\fIvolume\fR +\fBzfs\fR \fBallow\fR \fB-s\fR @\fIsetname\fR \fIperm\fR|@\fIsetname\fR[,\fIperm\fR|\fI@setname\fR]... \fIfilesystem\fR|\fIvolume\fR .fi .LP .nf -\fBzfs\fR \fBallow\fR \fB-s\fR @\fIsetname\fR \fIperm\fR|@\fIsetname\fR[,...] \fIfilesystem\fR|\fIvolume\fR +\fBzfs\fR \fBunallow\fR [\fB-rldug\fR] \fIuser\fR|\fIgroup\fR[,\fIuser\fR|\fIgroup\fR]... + [\fIperm\fR|@\fIsetname\fR[,\fIperm\fR|\fI@setname\fR]...] \fIfilesystem\fR|\fIvolume\fR .fi .LP .nf -\fBzfs\fR \fBunallow\fR [\fB-rldug\fR] "\fIeveryone\fR"|\fIuser\fR|\fIgroup\fR[,...] [\fIperm\fR|@\fIsetname\fR[,... ]] +\fBzfs\fR \fBunallow\fR [\fB-rld\fR] \fB-e\fR|\fBeveryone\fR [\fIperm\fR|@\fIsetname\fR[,\fIperm\fR|\fI@setname\fR]...] \fIfilesystem\fR|\fIvolume\fR .fi .LP .nf -\fBzfs\fR \fBunallow\fR [\fB-rld\fR] \fB-e\fR [\fIperm\fR|@\fIsetname\fR[,... ]] \fIfilesystem\fR|\fIvolume\fR +\fBzfs\fR \fBunallow\fR [\fB-r\fR] \fB-c\fR [\fIperm\fR|@\fIsetname\fR[,\fIperm\fR|\fI@setname\fR]...] \fIfilesystem\fR|\fIvolume\fR .fi .LP .nf -\fBzfs\fR \fBunallow\fR [\fB-r\fR] \fB-c\fR [\fIperm\fR|@\fIsetname\fR[ ... ]] \fIfilesystem\fR|\fIvolume\fR -.fi - -.LP -.nf -\fBzfs\fR \fBunallow\fR [\fB-r\fR] \fB-s\fR @\fIsetname\fR [\fIperm\fR|@\fIsetname\fR[,... ]] \fIfilesystem\fR|\fIvolume\fR +\fBzfs\fR \fBunallow\fR [\fB-r\fR] \fB-s\fR @\fIsetname\fR [\fIperm\fR|@\fIsetname\fR[,\fIperm\fR|\fI@setname\fR]...] + \fIfilesystem\fR|\fIvolume\fR .fi .LP @@ -1590,7 +1594,7 @@ Displays a help message. .sp .ne 2 .na -\fB\fBzfs create\fR [\fB-p\fR] [\fB-o\fR \fIproperty\fR=\fIvalue\fR] ... +\fB\fBzfs create\fR [\fB-p\fR] [\fB-o\fR \fIproperty\fR=\fIvalue\fR]... \fIfilesystem\fR\fR .ad .sp .6 @@ -1631,7 +1635,7 @@ property is specified in multiple \fB-o\fR options. .ne 2 .na \fB\fBzfs create\fR [\fB-ps\fR] [\fB-b\fR \fIblocksize\fR] [\fB-o\fR -\fIproperty\fR=\fIvalue\fR] ... \fB-V\fR \fIsize\fR \fIvolume\fR\fR +\fIproperty\fR=\fIvalue\fR]... \fB-V\fR \fIsize\fR \fIvolume\fR\fR .ad .sp .6 .RS 4n @@ -1778,7 +1782,7 @@ behavior for mounted file systems in use. .sp .ne 2 .na -\fBzfs destroy\fR [\fB-dnpRrv\fR] \fIfilesystem\fR|\fIvolume\fR@\fIsnap\fR[%\fIsnap\fR][,...] +\fBzfs destroy\fR [\fB-dnpRrv\fR] \fIfilesystem\fR|\fIvolume\fR@\fIsnap\fR[%\fIsnap\fR][,\fIsnap\fR[%\fIsnap\fR]]... .ad .sp .6 .RS 4n @@ -1874,7 +1878,7 @@ behavior for mounted file systems in use. .sp .ne 2 .na -\fB\fBzfs snapshot\fR [\fB-r\fR] [\fB-o\fR \fIproperty\fR=\fIvalue\fR] ... +\fB\fBzfs snapshot\fR [\fB-r\fR] [\fB-o\fR \fIproperty\fR=\fIvalue\fR]... \fIfilesystem@snapname\fR|\fIvolume@snapname\fR\fR... .ad .sp .6 @@ -1960,7 +1964,7 @@ that are to be destroyed. .sp .ne 2 .na -\fB\fBzfs clone\fR [\fB-p\fR] [\fB-o\fR \fIproperty\fR=\fIvalue\fR] ... +\fB\fBzfs clone\fR [\fB-p\fR] [\fB-o\fR \fIproperty\fR=\fIvalue\fR]... \fIsnapshot\fR \fIfilesystem\fR|\fIvolume\fR\fR .ad .sp .6 @@ -2075,9 +2079,9 @@ only dataset that can be renamed recursively. .ne 2 .na \fB\fBzfs\fR \fBlist\fR [\fB-r\fR|\fB-d\fR \fIdepth\fR] [\fB-H\fR] [\fB-o\fR -\fIproperty\fR[,\fI\&...\fR]] [ \fB-t\fR \fItype\fR[,\fI\&...\fR]] [ \fB-s\fR -\fIproperty\fR ] ... [ \fB-S\fR \fIproperty\fR ] ... -[\fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR] ...\fR +\fIproperty\fR[,\fIproperty\fR]...] [ \fB-t\fR \fItype\fR[,\fItype\fR]...] [ \fB-s\fR +\fIproperty\fR ]... [ \fB-S\fR \fIproperty\fR ]... +[\fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR]...\fR .ad .sp .6 .RS 4n @@ -2228,7 +2232,7 @@ specifying \fB-t snapshot\fR displays only snapshots. .ne 2 .na \fB\fBzfs set\fR \fIproperty\fR=\fIvalue\fR -\fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR ...\fR +\fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR...\fR .ad .sp .6 .RS 4n @@ -2246,8 +2250,8 @@ Properties" section. .ne 2 .na \fB\fBzfs get\fR [\fB-r\fR|\fB-d\fR \fIdepth\fR] [\fB-Hp\fR] [\fB-o\fR -\fIfield\fR[,...] [\fB-t\fR \fItype\fR[,...]] [\fB-s\fR \fIsource\fR[,...] "\fIall\fR" | -\fIproperty\fR[,...] \fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR ...\fR +\fIfield\fR[,\fIfield\fR]... [\fB-t\fR \fItype\fR[,\fItype\fR]...] [\fB-s\fR \fIsource\fR[,\fIsource\fR]... \fBall\fR | +\fIproperty\fR[,\fIproperty\fR]... \fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR...\fR .ad .sp .6 .RS 4n @@ -2346,7 +2350,7 @@ Display numbers in parseable (exact) values. .ne 2 .na \fB\fBzfs inherit\fR [\fB-r\fR] \fIproperty\fR -\fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR ...\fR +\fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR...\fR .ad .sp .6 .RS 4n @@ -2443,10 +2447,10 @@ supported by this software. .sp .ne 2 .na -\fBzfs\fR \fBuserspace\fR [\fB-Hinp\fR] [\fB-o\fR \fIfield\fR[,...]] -[\fB-s\fR \fIfield\fR] ... -[\fB-S\fR \fIfield\fR] ... -[\fB-t\fR \fItype\fR[,...]] \fIfilesystem\fR|\fIsnapshot\fR +\fBzfs\fR \fBuserspace\fR [\fB-Hinp\fR] [\fB-o\fR \fIfield\fR[,\fIfield\fR]...] +[\fB-s\fR \fIfield\fR]... +[\fB-S\fR \fIfield\fR]... +[\fB-t\fR \fItype\fR[,\fItype\fR]...] \fIfilesystem\fR|\fIsnapshot\fR .ad .sp .6 .RS 4n @@ -2486,7 +2490,7 @@ Use exact (parsable) numeric output. .sp .ne 2 .na -\fB\fB-o\fR \fIfield\fR[,...]\fR +\fB\fB-o\fR \fIfield\fR[,\fIfield\fR]...\fR .ad .sp .6 .RS 4n @@ -2519,7 +2523,7 @@ Sort by this field in reverse order. See \fB-s\fR. .sp .ne 2 .na -\fB\fB-t\fR \fItype\fR[,...]\fR +\fB\fB-t\fR \fItype\fR[,\fItype\fR]...\fR .ad .sp .6 .RS 4n @@ -2551,10 +2555,10 @@ will report that the POSIX entity has the total usage and quota for both. .sp .ne 2 .na -\fBzfs\fR \fBgroupspace\fR [\fB-Hinp\fR] [\fB-o\fR \fIfield\fR[,...]] -[\fB-s\fR \fIfield\fR] ... -[\fB-S\fR \fIfield\fR] ... -[\fB-t\fR \fItype\fR[,...]] \fIfilesystem\fR|\fIsnapshot\fR +\fBzfs\fR \fBgroupspace\fR [\fB-Hinp\fR] [\fB-o\fR \fIfield\fR[,\fIfield\fR]...] +[\fB-s\fR \fIfield\fR]... +[\fB-S\fR \fIfield\fR]... +[\fB-t\fR \fItype\fR[,\fItype\fR]...] \fIfilesystem\fR|\fIsnapshot\fR .ad .sp .6 .RS 4n @@ -3003,13 +3007,13 @@ volume. See the other forms of \fBzfs allow\fR for more information. .sp .ne 2 .na -\fB\fBzfs allow\fR [\fB-ldug\fR] "\fIeveryone\fR"|\fIuser\fR|\fIgroup\fR[,...] -\fIperm\fR|@\fIsetname\fR[,...] \fIfilesystem\fR| \fIvolume\fR\fR +\fB\fBzfs allow\fR [\fB-ldug\fR] \fIuser\fR|\fIgroup\fR[,\fIuser\fR|\fIgroup\fR]... +\fIperm\fR|@\fIsetname\fR[,\fIperm\fR|@\fIsetname\fR]... \fIfilesystem\fR|\fIvolume\fR\fR .ad .br .na -\fB\fBzfs allow\fR [\fB-ld\fR] \fB-e\fR \fIperm\fR|@\fIsetname\fR[,...] -\fIfilesystem\fR | \fIvolume\fR\fR +\fB\fBzfs allow\fR [\fB-ld\fR] \fB-e\fR|\fBeveryone\fR \fIperm\fR|@\fIsetname\fR[,\fIperm\fR|@\fIsetname\fR]... +\fIfilesystem\fR|\fIvolume\fR\fR .ad .sp .6 .RS 4n @@ -3018,14 +3022,14 @@ non-privileged users. .sp .ne 2 .na -\fB[\fB-ug\fR] "\fIeveryone\fR"|\fIuser\fR|\fIgroup\fR[,...]\fR +[\fB-ug\fR] \fIuser\fR|\fIgroup\fR[,\fIuser\fR|\fIgroup\fR]... .ad .sp .6 .RS 4n Specifies to whom the permissions are delegated. Multiple entities can be specified as a comma-separated list. If neither of the \fB-ug\fR options are specified, then the argument is interpreted preferentially as the keyword -"everyone", then as a user name, and lastly as a group name. To specify a user +\fBeveryone,\fR then as a user name, and lastly as a group name. To specify a user or group named "everyone", use the \fB-u\fR or \fB-g\fR options. To specify a group with the same name as a user, use the \fB-g\fR options. .RE @@ -3033,11 +3037,21 @@ group with the same name as a user, use the \fB-g\fR options. .sp .ne 2 .na -\fB[\fB-e\fR] \fIperm\fR|@\fIsetname\fR[,...]\fR +\fB-e\fR|\fBeveryone\fR .ad .sp .6 .RS 4n -Specifies that the permissions be delegated to "everyone." Multiple permissions +Specifies that the permissions be delegated to everyone. +.RE + +.sp +.ne 2 +.na +\fIperm\fR|@\fIsetname\fR[,\fIperm\fR|@\fIsetname\fR]... +.ad +.sp .6 +.RS 4n +The permissions to delegate. Multiple permissions may be specified as a comma-separated list. Permission names are the same as \fBZFS\fR subcommand and property names. See the property list below. Property set names, which begin with an at sign (\fB@\fR) , may be specified. See the @@ -3047,7 +3061,7 @@ set names, which begin with an at sign (\fB@\fR) , may be specified. See the .sp .ne 2 .na -\fB[\fB-ld\fR] \fIfilesystem\fR|\fIvolume\fR\fR +[\fB-ld\fR] \fIfilesystem\fR|\fIvolume\fR .ad .sp .6 .RS 4n @@ -3135,7 +3149,7 @@ zoned property .sp .ne 2 .na -\fB\fBzfs allow\fR \fB-c\fR \fIperm\fR|@\fIsetname\fR[,...] +\fB\fBzfs allow\fR \fB-c\fR \fIperm\fR|@\fIsetname\fR[,\fIperm\fR|@\fIsetname\fR]... \fIfilesystem\fR|\fIvolume\fR\fR .ad .sp .6 @@ -3147,7 +3161,7 @@ creator of any newly-created descendent file system. .sp .ne 2 .na -\fB\fBzfs allow\fR \fB-s\fR @\fIsetname\fR \fIperm\fR|@\fIsetname\fR[,...] +\fB\fBzfs allow\fR \fB-s\fR @\fIsetname\fR \fIperm\fR|@\fIsetname\fR[,\fIperm\fR|@\fIsetname\fR]... \fIfilesystem\fR|\fIvolume\fR\fR .ad .sp .6 @@ -3163,18 +3177,17 @@ characters long. .sp .ne 2 .na -\fB\fBzfs unallow\fR [\fB-rldug\fR] -"\fIeveryone\fR"|\fIuser\fR|\fIgroup\fR[,...] -[\fIperm\fR|@\fIsetname\fR[, ...]] \fIfilesystem\fR|\fIvolume\fR\fR +\fB\fBzfs unallow\fR [\fB-rldug\fR] \fIuser\fR|\fIgroup\fR[,\fIuser\fR|\fIgroup\fR]... +[\fIperm\fR|@\fIsetname\fR[,\fIperm\fR|@\fIsetname\fR]...] \fIfilesystem\fR|\fIvolume\fR\fR .ad .br .na -\fB\fBzfs unallow\fR [\fB-rld\fR] \fB-e\fR [\fIperm\fR|@\fIsetname\fR [,...]] +\fB\fBzfs unallow\fR [\fB-rld\fR] \fB-e\fR|\fBeveryone\fR [\fIperm\fR|@\fIsetname\fR[,\fIperm\fR|@\fIsetname\fR]...] \fIfilesystem\fR|\fIvolume\fR\fR .ad .br .na -\fB\fBzfs unallow\fR [\fB-r\fR] \fB-c\fR [\fIperm\fR|@\fIsetname\fR[,...]]\fR +\fB\fBzfs unallow\fR [\fB-r\fR] \fB-c\fR [\fIperm\fR|@\fIsetname\fR[,\fIperm\fR|@\fIsetname\fR]...]\fR .ad .br .na @@ -3186,8 +3199,8 @@ Removes permissions that were granted with the \fBzfs allow\fR command. No permissions are explicitly denied, so other permissions granted are still in effect. For example, if the permission is granted by an ancestor. If no permissions are specified, then all permissions for the specified \fIuser\fR, -\fIgroup\fR, or \fIeveryone\fR are removed. Specifying "everyone" (or using the -\fB-e\fR option) only removes the permissions that were granted to "everyone", +\fIgroup\fR, or everyone are removed. Specifying \fBeveryone\fR (or using the +\fB-e\fR option) only removes the permissions that were granted to everyone, not all permissions for every user and group. See the \fBzfs allow\fR command for a description of the \fB-ldugec\fR options. .sp @@ -3206,7 +3219,7 @@ Recursively remove the permissions from this file system and all descendents. .ne 2 .na \fB\fBzfs unallow\fR [\fB-r\fR] \fB-s\fR @\fIsetname\fR -[\fIperm\fR|@\fIsetname\fR[,...]]\fR +[\fIperm\fR|@\fIsetname\fR[,\fIperm\fR|@\fIsetname\fR]...]\fR .ad .br .na From a277867526daa29d5aa6510211a50443ac1d3bfa Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Wed, 6 Feb 2013 08:14:58 +0000 Subject: [PATCH 0006/1476] Update vendor-sys/illumos/dist to illumos-gate version 13937:6b4f289e7094 Illumos ZFS issues: 3468 mdb enhancements for zfs development (not relevant for FreeBSD) --- uts/common/fs/zfs/sys/refcount.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/uts/common/fs/zfs/sys/refcount.h b/uts/common/fs/zfs/sys/refcount.h index 1752c64e3e8..1dcd467f91a 100644 --- a/uts/common/fs/zfs/sys/refcount.h +++ b/uts/common/fs/zfs/sys/refcount.h @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012 by Delphix. All rights reserved. */ #ifndef _SYS_REFCOUNT_H @@ -52,8 +53,8 @@ typedef struct refcount { kmutex_t rc_mtx; list_t rc_list; list_t rc_removed; - int64_t rc_count; - int64_t rc_removed_count; + uint64_t rc_count; + uint64_t rc_removed_count; } refcount_t; /* Note: refcount_t must be initialized with refcount_create() */ From 2bb4512243ab649d0cee37340152c131be6c2742 Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Wed, 6 Feb 2013 08:17:29 +0000 Subject: [PATCH 0007/1476] Update vendor/illumos/dist and vendor-sys/illumos/dist to illumos-gate 13939:20e4d8d8da6d illumos dtrace issues: 3511 dtrace.c erroneously checks for memory alignment on amd64 --- .../tst/common/pointers/err.InvalidAddress5.d | 53 +++++++++++-------- uts/common/dtrace/dtrace.c | 2 +- 2 files changed, 32 insertions(+), 23 deletions(-) diff --git a/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress5.d b/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress5.d index 64b77289481..c4d35e9e3f5 100644 --- a/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress5.d +++ b/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress5.d @@ -24,7 +24,9 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright (c) 2012 by Delphix. All rights reserved. + */ /* * ASSERTION: @@ -32,44 +34,51 @@ * a runtime error. * * SECTION: Pointers and Arrays/Generic Pointers - * - * NOTES: - * This test doesn't apply to x86; for the time being, we're working - * around this with the preprocessor. */ #pragma D option quiet -int array[3]; -uintptr_t uptr; +#if defined(__i386) || defined(__amd64) +#define __x86 1 +#endif + +int array[2]; +char *ptr; int *p; int *q; int *r; BEGIN { -#ifdef __i386 + array[0] = 0x12345678; + array[1] = 0xabcdefff; + + ptr = (char *) &array[0]; + + p = (int *) (ptr); + q = (int *) (ptr + 2); + r = (int *) (ptr + 3); + + printf("*p: 0x%x\n", *p); + printf("*q: 0x%x\n", *q); + printf("*r: 0x%x\n", *r); + + /* + * On x86, the above unaligned memory accesses are allowed and should + * not result in the ERROR probe firing. + */ +#ifdef __x86 exit(1); #else - array[0] = 20; - array[1] = 40; - array[2] = 80; - - uptr = (uintptr_t) &array[0]; - - p = (int *) (uptr); - q = (int *) (uptr + 2); - r = (int *) (uptr + 3); - - printf("array[0]: %d\t*p: %d\n", array[0], *p); - printf("array[1]: %d\t*q: %d\n", array[1], *q); - printf("array[2]: %d\t*r: %d\n", array[2], *r); - exit(0); #endif } ERROR { +#ifdef __x86 + exit(0); +#else exit(1); +#endif } diff --git a/uts/common/dtrace/dtrace.c b/uts/common/dtrace/dtrace.c index 50136615884..7a5e67ea706 100644 --- a/uts/common/dtrace/dtrace.c +++ b/uts/common/dtrace/dtrace.c @@ -355,7 +355,7 @@ static kmutex_t dtrace_errlock; #define DTRACE_STORE(type, tomax, offset, what) \ *((type *)((uintptr_t)(tomax) + (uintptr_t)offset)) = (type)(what); -#ifndef __i386 +#ifndef __x86 #define DTRACE_ALIGNCHECK(addr, size, flags) \ if (addr & (size - 1)) { \ *flags |= CPU_DTRACE_BADALIGN; \ From 9a11334771b60a8ae086cdf9ee9a1fb140ec9c55 Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Wed, 6 Feb 2013 08:21:40 +0000 Subject: [PATCH 0008/1476] Update vendor/illumos/dist and vendor-sys/illumos/dist to illumos-gate 13941:d48547176ab4 Illumos ZFS issues: 3498 panic in arc_read(): !refcount_is_zero(&pbuf->b_hdr->b_refcnt) --- cmd/zdb/zdb.c | 7 ++- uts/common/fs/zfs/arc.c | 52 ++---------------- uts/common/fs/zfs/bptree.c | 2 +- uts/common/fs/zfs/dbuf.c | 28 ++-------- uts/common/fs/zfs/dmu_diff.c | 8 +-- uts/common/fs/zfs/dmu_objset.c | 12 ++--- uts/common/fs/zfs/dmu_send.c | 20 +++---- uts/common/fs/zfs/dmu_traverse.c | 79 ++++++++++++---------------- uts/common/fs/zfs/dsl_dataset.c | 2 +- uts/common/fs/zfs/dsl_scan.c | 36 ++----------- uts/common/fs/zfs/spa.c | 2 +- uts/common/fs/zfs/sys/arc.h | 8 +-- uts/common/fs/zfs/sys/dmu_traverse.h | 3 +- uts/common/fs/zfs/sys/dsl_pool.h | 6 --- uts/common/fs/zfs/zil.c | 4 +- uts/common/fs/zfs/zio.c | 2 +- uts/common/fs/zfs/zvol.c | 2 +- 17 files changed, 76 insertions(+), 197 deletions(-) diff --git a/cmd/zdb/zdb.c b/cmd/zdb/zdb.c index e636a31a3e7..9075c47ad1a 100644 --- a/cmd/zdb/zdb.c +++ b/cmd/zdb/zdb.c @@ -1016,7 +1016,7 @@ visit_indirect(spa_t *spa, const dnode_phys_t *dnp, arc_buf_t *buf; uint64_t fill = 0; - err = arc_read_nolock(NULL, spa, bp, arc_getbuf_func, &buf, + err = arc_read(NULL, spa, bp, arc_getbuf_func, &buf, ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, &flags, zb); if (err) return (err); @@ -2073,9 +2073,8 @@ zdb_blkptr_done(zio_t *zio) mutex_exit(&spa->spa_scrub_lock); } -/* ARGSUSED */ static int -zdb_blkptr_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, arc_buf_t *pbuf, +zdb_blkptr_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg) { zdb_cb_t *zcb = arg; @@ -2476,7 +2475,7 @@ typedef struct zdb_ddt_entry { /* ARGSUSED */ static int zdb_ddt_add_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, - arc_buf_t *pbuf, const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg) + const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg) { avl_tree_t *t = arg; avl_index_t where; diff --git a/uts/common/fs/zfs/arc.c b/uts/common/fs/zfs/arc.c index 860a3b51a3c..6625debd0cb 100644 --- a/uts/common/fs/zfs/arc.c +++ b/uts/common/fs/zfs/arc.c @@ -823,7 +823,6 @@ buf_cons(void *vbuf, void *unused, int kmflag) bzero(buf, sizeof (arc_buf_t)); mutex_init(&buf->b_evict_lock, NULL, MUTEX_DEFAULT, NULL); - rw_init(&buf->b_data_lock, NULL, RW_DEFAULT, NULL); arc_space_consume(sizeof (arc_buf_t), ARC_SPACE_HDRS); return (0); @@ -853,7 +852,6 @@ buf_dest(void *vbuf, void *unused) arc_buf_t *buf = vbuf; mutex_destroy(&buf->b_evict_lock); - rw_destroy(&buf->b_data_lock); arc_space_return(sizeof (arc_buf_t), ARC_SPACE_HDRS); } @@ -2779,42 +2777,11 @@ arc_read_done(zio_t *zio) * * arc_read_done() will invoke all the requested "done" functions * for readers of this block. - * - * Normal callers should use arc_read and pass the arc buffer and offset - * for the bp. But if you know you don't need locking, you can use - * arc_read_bp. */ int -arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp, arc_buf_t *pbuf, - arc_done_func_t *done, void *private, int priority, int zio_flags, - uint32_t *arc_flags, const zbookmark_t *zb) -{ - int err; - - if (pbuf == NULL) { - /* - * XXX This happens from traverse callback funcs, for - * the objset_phys_t block. - */ - return (arc_read_nolock(pio, spa, bp, done, private, priority, - zio_flags, arc_flags, zb)); - } - - ASSERT(!refcount_is_zero(&pbuf->b_hdr->b_refcnt)); - ASSERT3U((char *)bp - (char *)pbuf->b_data, <, pbuf->b_hdr->b_size); - rw_enter(&pbuf->b_data_lock, RW_READER); - - err = arc_read_nolock(pio, spa, bp, done, private, priority, - zio_flags, arc_flags, zb); - rw_exit(&pbuf->b_data_lock); - - return (err); -} - -int -arc_read_nolock(zio_t *pio, spa_t *spa, const blkptr_t *bp, - arc_done_func_t *done, void *private, int priority, int zio_flags, - uint32_t *arc_flags, const zbookmark_t *zb) +arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp, arc_done_func_t *done, + void *private, int priority, int zio_flags, uint32_t *arc_flags, + const zbookmark_t *zb) { arc_buf_hdr_t *hdr; arc_buf_t *buf; @@ -3294,19 +3261,6 @@ arc_release(arc_buf_t *buf, void *tag) } } -/* - * Release this buffer. If it does not match the provided BP, fill it - * with that block's contents. - */ -/* ARGSUSED */ -int -arc_release_bp(arc_buf_t *buf, void *tag, blkptr_t *bp, spa_t *spa, - zbookmark_t *zb) -{ - arc_release(buf, tag); - return (0); -} - int arc_released(arc_buf_t *buf) { diff --git a/uts/common/fs/zfs/bptree.c b/uts/common/fs/zfs/bptree.c index 1a009cfe573..73922db88be 100644 --- a/uts/common/fs/zfs/bptree.c +++ b/uts/common/fs/zfs/bptree.c @@ -135,7 +135,7 @@ bptree_add(objset_t *os, uint64_t obj, blkptr_t *bp, uint64_t birth_txg, /* ARGSUSED */ static int -bptree_visit_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, arc_buf_t *pbuf, +bptree_visit_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg) { int err; diff --git a/uts/common/fs/zfs/dbuf.c b/uts/common/fs/zfs/dbuf.c index d56dbc95ac3..8bf3d099ef0 100644 --- a/uts/common/fs/zfs/dbuf.c +++ b/uts/common/fs/zfs/dbuf.c @@ -513,7 +513,6 @@ dbuf_read_impl(dmu_buf_impl_t *db, zio_t *zio, uint32_t *flags) spa_t *spa; zbookmark_t zb; uint32_t aflags = ARC_NOWAIT; - arc_buf_t *pbuf; DB_DNODE_ENTER(db); dn = DB_DNODE(db); @@ -575,14 +574,8 @@ dbuf_read_impl(dmu_buf_impl_t *db, zio_t *zio, uint32_t *flags) db->db.db_object, db->db_level, db->db_blkid); dbuf_add_ref(db, NULL); - /* ZIO_FLAG_CANFAIL callers have to check the parent zio's error */ - if (db->db_parent) - pbuf = db->db_parent->db_buf; - else - pbuf = db->db_objset->os_phys_buf; - - (void) dsl_read(zio, spa, db->db_blkptr, pbuf, + (void) arc_read(zio, spa, db->db_blkptr, dbuf_read_done, db, ZIO_PRIORITY_SYNC_READ, (*flags & DB_RF_CANFAIL) ? ZIO_FLAG_CANFAIL : ZIO_FLAG_MUSTSUCCEED, &aflags, &zb); @@ -982,7 +975,6 @@ void dbuf_release_bp(dmu_buf_impl_t *db) { objset_t *os; - zbookmark_t zb; DB_GET_OBJSET(&os, db); ASSERT(dsl_pool_sync_context(dmu_objset_pool(os))); @@ -990,13 +982,7 @@ dbuf_release_bp(dmu_buf_impl_t *db) list_link_active(&os->os_dsl_dataset->ds_synced_link)); ASSERT(db->db_parent == NULL || arc_released(db->db_parent->db_buf)); - zb.zb_objset = os->os_dsl_dataset ? - os->os_dsl_dataset->ds_object : 0; - zb.zb_object = db->db.db_object; - zb.zb_level = db->db_level; - zb.zb_blkid = db->db_blkid; - (void) arc_release_bp(db->db_buf, db, - db->db_blkptr, os->os_spa, &zb); + (void) arc_release(db->db_buf, db); } dbuf_dirty_record_t * @@ -1831,7 +1817,6 @@ dbuf_prefetch(dnode_t *dn, uint64_t blkid) if (bp && !BP_IS_HOLE(bp)) { int priority = dn->dn_type == DMU_OT_DDT_ZAP ? ZIO_PRIORITY_DDT_PREFETCH : ZIO_PRIORITY_ASYNC_READ; - arc_buf_t *pbuf; dsl_dataset_t *ds = dn->dn_objset->os_dsl_dataset; uint32_t aflags = ARC_NOWAIT | ARC_PREFETCH; zbookmark_t zb; @@ -1839,13 +1824,8 @@ dbuf_prefetch(dnode_t *dn, uint64_t blkid) SET_BOOKMARK(&zb, ds ? ds->ds_object : DMU_META_OBJSET, dn->dn_object, 0, blkid); - if (db) - pbuf = db->db_buf; - else - pbuf = dn->dn_objset->os_phys_buf; - - (void) dsl_read(NULL, dn->dn_objset->os_spa, - bp, pbuf, NULL, NULL, priority, + (void) arc_read(NULL, dn->dn_objset->os_spa, + bp, NULL, NULL, priority, ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE, &aflags, &zb); } diff --git a/uts/common/fs/zfs/dmu_diff.c b/uts/common/fs/zfs/dmu_diff.c index 22340ebc537..dc237780c0b 100644 --- a/uts/common/fs/zfs/dmu_diff.c +++ b/uts/common/fs/zfs/dmu_diff.c @@ -105,7 +105,7 @@ report_dnode(struct diffarg *da, uint64_t object, dnode_phys_t *dnp) /* ARGSUSED */ static int -diff_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, arc_buf_t *pbuf, +diff_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg) { struct diffarg *da = arg; @@ -132,9 +132,9 @@ diff_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, arc_buf_t *pbuf, int blksz = BP_GET_LSIZE(bp); int i; - if (dsl_read(NULL, spa, bp, pbuf, - arc_getbuf_func, &abuf, ZIO_PRIORITY_ASYNC_READ, - ZIO_FLAG_CANFAIL, &aflags, zb) != 0) + if (arc_read(NULL, spa, bp, arc_getbuf_func, &abuf, + ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, + &aflags, zb) != 0) return (EIO); blk = abuf->b_data; diff --git a/uts/common/fs/zfs/dmu_objset.c b/uts/common/fs/zfs/dmu_objset.c index b840881486b..00cbe0410ec 100644 --- a/uts/common/fs/zfs/dmu_objset.c +++ b/uts/common/fs/zfs/dmu_objset.c @@ -277,12 +277,7 @@ dmu_objset_open_impl(spa_t *spa, dsl_dataset_t *ds, blkptr_t *bp, aflags |= ARC_L2CACHE; dprintf_bp(os->os_rootbp, "reading %s", ""); - /* - * XXX when bprewrite scrub can change the bp, - * and this is called from dmu_objset_open_ds_os, the bp - * could change, and we'll need a lock. - */ - err = dsl_read_nolock(NULL, spa, os->os_rootbp, + err = arc_read(NULL, spa, os->os_rootbp, arc_getbuf_func, &os->os_phys_buf, ZIO_PRIORITY_SYNC_READ, ZIO_FLAG_CANFAIL, &aflags, &zb); if (err) { @@ -1173,8 +1168,7 @@ dmu_objset_sync(objset_t *os, zio_t *pio, dmu_tx_t *tx) SET_BOOKMARK(&zb, os->os_dsl_dataset ? os->os_dsl_dataset->ds_object : DMU_META_OBJSET, ZB_ROOT_OBJECT, ZB_ROOT_LEVEL, ZB_ROOT_BLKID); - VERIFY3U(0, ==, arc_release_bp(os->os_phys_buf, &os->os_phys_buf, - os->os_rootbp, os->os_spa, &zb)); + arc_release(os->os_phys_buf, &os->os_phys_buf); dmu_write_policy(os, NULL, 0, 0, &zp); @@ -1813,7 +1807,7 @@ dmu_objset_prefetch(const char *name, void *arg) SET_BOOKMARK(&zb, ds->ds_object, ZB_ROOT_OBJECT, ZB_ROOT_LEVEL, ZB_ROOT_BLKID); - (void) dsl_read_nolock(NULL, dsl_dataset_get_spa(ds), + (void) arc_read(NULL, dsl_dataset_get_spa(ds), &ds->ds_phys->ds_bp, NULL, NULL, ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE, diff --git a/uts/common/fs/zfs/dmu_send.c b/uts/common/fs/zfs/dmu_send.c index e5644b5a0c2..c2493357d6d 100644 --- a/uts/common/fs/zfs/dmu_send.c +++ b/uts/common/fs/zfs/dmu_send.c @@ -301,7 +301,7 @@ dump_dnode(dmu_sendarg_t *dsp, uint64_t object, dnode_phys_t *dnp) /* ARGSUSED */ static int -backup_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, arc_buf_t *pbuf, +backup_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg) { dmu_sendarg_t *dsp = arg; @@ -330,9 +330,9 @@ backup_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, arc_buf_t *pbuf, uint32_t aflags = ARC_WAIT; arc_buf_t *abuf; - if (dsl_read(NULL, spa, bp, pbuf, - arc_getbuf_func, &abuf, ZIO_PRIORITY_ASYNC_READ, - ZIO_FLAG_CANFAIL, &aflags, zb) != 0) + if (arc_read(NULL, spa, bp, arc_getbuf_func, &abuf, + ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, + &aflags, zb) != 0) return (EIO); blk = abuf->b_data; @@ -349,9 +349,9 @@ backup_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, arc_buf_t *pbuf, arc_buf_t *abuf; int blksz = BP_GET_LSIZE(bp); - if (arc_read_nolock(NULL, spa, bp, - arc_getbuf_func, &abuf, ZIO_PRIORITY_ASYNC_READ, - ZIO_FLAG_CANFAIL, &aflags, zb) != 0) + if (arc_read(NULL, spa, bp, arc_getbuf_func, &abuf, + ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, + &aflags, zb) != 0) return (EIO); err = dump_spill(dsp, zb->zb_object, blksz, abuf->b_data); @@ -361,9 +361,9 @@ backup_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, arc_buf_t *pbuf, arc_buf_t *abuf; int blksz = BP_GET_LSIZE(bp); - if (dsl_read(NULL, spa, bp, pbuf, - arc_getbuf_func, &abuf, ZIO_PRIORITY_ASYNC_READ, - ZIO_FLAG_CANFAIL, &aflags, zb) != 0) { + if (arc_read(NULL, spa, bp, arc_getbuf_func, &abuf, + ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, + &aflags, zb) != 0) { if (zfs_send_corrupt_data) { /* Send a block filled with 0x"zfs badd bloc" */ abuf = arc_buf_alloc(spa, blksz, &abuf, diff --git a/uts/common/fs/zfs/dmu_traverse.c b/uts/common/fs/zfs/dmu_traverse.c index 34f19cdcbb0..f3d5069d476 100644 --- a/uts/common/fs/zfs/dmu_traverse.c +++ b/uts/common/fs/zfs/dmu_traverse.c @@ -62,9 +62,9 @@ typedef struct traverse_data { } traverse_data_t; static int traverse_dnode(traverse_data_t *td, const dnode_phys_t *dnp, - arc_buf_t *buf, uint64_t objset, uint64_t object); + uint64_t objset, uint64_t object); static void prefetch_dnode_metadata(traverse_data_t *td, const dnode_phys_t *, - arc_buf_t *buf, uint64_t objset, uint64_t object); + uint64_t objset, uint64_t object); static int traverse_zil_block(zilog_t *zilog, blkptr_t *bp, void *arg, uint64_t claim_txg) @@ -81,7 +81,7 @@ traverse_zil_block(zilog_t *zilog, blkptr_t *bp, void *arg, uint64_t claim_txg) SET_BOOKMARK(&zb, td->td_objset, ZB_ZIL_OBJECT, ZB_ZIL_LEVEL, bp->blk_cksum.zc_word[ZIL_ZC_SEQ]); - (void) td->td_func(td->td_spa, zilog, bp, NULL, &zb, NULL, td->td_arg); + (void) td->td_func(td->td_spa, zilog, bp, &zb, NULL, td->td_arg); return (0); } @@ -105,7 +105,7 @@ traverse_zil_record(zilog_t *zilog, lr_t *lrc, void *arg, uint64_t claim_txg) SET_BOOKMARK(&zb, td->td_objset, lr->lr_foid, ZB_ZIL_LEVEL, lr->lr_offset / BP_GET_LSIZE(bp)); - (void) td->td_func(td->td_spa, zilog, bp, NULL, &zb, NULL, + (void) td->td_func(td->td_spa, zilog, bp, &zb, NULL, td->td_arg); } return (0); @@ -182,7 +182,7 @@ traverse_pause(traverse_data_t *td, const zbookmark_t *zb) static void traverse_prefetch_metadata(traverse_data_t *td, - arc_buf_t *pbuf, const blkptr_t *bp, const zbookmark_t *zb) + const blkptr_t *bp, const zbookmark_t *zb) { uint32_t flags = ARC_NOWAIT | ARC_PREFETCH; @@ -200,14 +200,13 @@ traverse_prefetch_metadata(traverse_data_t *td, if (BP_GET_LEVEL(bp) == 0 && BP_GET_TYPE(bp) != DMU_OT_DNODE) return; - (void) arc_read(NULL, td->td_spa, bp, - pbuf, NULL, NULL, ZIO_PRIORITY_ASYNC_READ, - ZIO_FLAG_CANFAIL, &flags, zb); + (void) arc_read(NULL, td->td_spa, bp, NULL, NULL, + ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, &flags, zb); } static int traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp, - arc_buf_t *pbuf, const blkptr_t *bp, const zbookmark_t *zb) + const blkptr_t *bp, const zbookmark_t *zb) { zbookmark_t czb; int err = 0, lasterr = 0; @@ -228,8 +227,7 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp, } if (BP_IS_HOLE(bp)) { - err = td->td_func(td->td_spa, NULL, NULL, pbuf, zb, dnp, - td->td_arg); + err = td->td_func(td->td_spa, NULL, NULL, zb, dnp, td->td_arg); return (err); } @@ -249,7 +247,7 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp, } if (td->td_flags & TRAVERSE_PRE) { - err = td->td_func(td->td_spa, NULL, bp, pbuf, zb, dnp, + err = td->td_func(td->td_spa, NULL, bp, zb, dnp, td->td_arg); if (err == TRAVERSE_VISIT_NO_CHILDREN) return (0); @@ -265,8 +263,7 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp, blkptr_t *cbp; int epb = BP_GET_LSIZE(bp) >> SPA_BLKPTRSHIFT; - err = dsl_read(NULL, td->td_spa, bp, pbuf, - arc_getbuf_func, &buf, + err = arc_read(NULL, td->td_spa, bp, arc_getbuf_func, &buf, ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, &flags, zb); if (err) return (err); @@ -276,7 +273,7 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp, SET_BOOKMARK(&czb, zb->zb_objset, zb->zb_object, zb->zb_level - 1, zb->zb_blkid * epb + i); - traverse_prefetch_metadata(td, buf, &cbp[i], &czb); + traverse_prefetch_metadata(td, &cbp[i], &czb); } /* recursively visitbp() blocks below this */ @@ -284,7 +281,7 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp, SET_BOOKMARK(&czb, zb->zb_objset, zb->zb_object, zb->zb_level - 1, zb->zb_blkid * epb + i); - err = traverse_visitbp(td, dnp, buf, &cbp[i], &czb); + err = traverse_visitbp(td, dnp, &cbp[i], &czb); if (err) { if (!hard) break; @@ -296,21 +293,20 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp, int i; int epb = BP_GET_LSIZE(bp) >> DNODE_SHIFT; - err = dsl_read(NULL, td->td_spa, bp, pbuf, - arc_getbuf_func, &buf, + err = arc_read(NULL, td->td_spa, bp, arc_getbuf_func, &buf, ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, &flags, zb); if (err) return (err); dnp = buf->b_data; for (i = 0; i < epb; i++) { - prefetch_dnode_metadata(td, &dnp[i], buf, zb->zb_objset, + prefetch_dnode_metadata(td, &dnp[i], zb->zb_objset, zb->zb_blkid * epb + i); } /* recursively visitbp() blocks below this */ for (i = 0; i < epb; i++) { - err = traverse_dnode(td, &dnp[i], buf, zb->zb_objset, + err = traverse_dnode(td, &dnp[i], zb->zb_objset, zb->zb_blkid * epb + i); if (err) { if (!hard) @@ -323,24 +319,23 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp, objset_phys_t *osp; dnode_phys_t *dnp; - err = dsl_read_nolock(NULL, td->td_spa, bp, - arc_getbuf_func, &buf, + err = arc_read(NULL, td->td_spa, bp, arc_getbuf_func, &buf, ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, &flags, zb); if (err) return (err); osp = buf->b_data; dnp = &osp->os_meta_dnode; - prefetch_dnode_metadata(td, dnp, buf, zb->zb_objset, + prefetch_dnode_metadata(td, dnp, zb->zb_objset, DMU_META_DNODE_OBJECT); if (arc_buf_size(buf) >= sizeof (objset_phys_t)) { prefetch_dnode_metadata(td, &osp->os_userused_dnode, - buf, zb->zb_objset, DMU_USERUSED_OBJECT); + zb->zb_objset, DMU_USERUSED_OBJECT); prefetch_dnode_metadata(td, &osp->os_groupused_dnode, - buf, zb->zb_objset, DMU_USERUSED_OBJECT); + zb->zb_objset, DMU_USERUSED_OBJECT); } - err = traverse_dnode(td, dnp, buf, zb->zb_objset, + err = traverse_dnode(td, dnp, zb->zb_objset, DMU_META_DNODE_OBJECT); if (err && hard) { lasterr = err; @@ -348,7 +343,7 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp, } if (err == 0 && arc_buf_size(buf) >= sizeof (objset_phys_t)) { dnp = &osp->os_userused_dnode; - err = traverse_dnode(td, dnp, buf, zb->zb_objset, + err = traverse_dnode(td, dnp, zb->zb_objset, DMU_USERUSED_OBJECT); } if (err && hard) { @@ -357,7 +352,7 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp, } if (err == 0 && arc_buf_size(buf) >= sizeof (objset_phys_t)) { dnp = &osp->os_groupused_dnode; - err = traverse_dnode(td, dnp, buf, zb->zb_objset, + err = traverse_dnode(td, dnp, zb->zb_objset, DMU_GROUPUSED_OBJECT); } } @@ -367,8 +362,7 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp, post: if (err == 0 && lasterr == 0 && (td->td_flags & TRAVERSE_POST)) { - err = td->td_func(td->td_spa, NULL, bp, pbuf, zb, dnp, - td->td_arg); + err = td->td_func(td->td_spa, NULL, bp, zb, dnp, td->td_arg); if (err == ERESTART) pause = B_TRUE; } @@ -384,25 +378,25 @@ post: static void prefetch_dnode_metadata(traverse_data_t *td, const dnode_phys_t *dnp, - arc_buf_t *buf, uint64_t objset, uint64_t object) + uint64_t objset, uint64_t object) { int j; zbookmark_t czb; for (j = 0; j < dnp->dn_nblkptr; j++) { SET_BOOKMARK(&czb, objset, object, dnp->dn_nlevels - 1, j); - traverse_prefetch_metadata(td, buf, &dnp->dn_blkptr[j], &czb); + traverse_prefetch_metadata(td, &dnp->dn_blkptr[j], &czb); } if (dnp->dn_flags & DNODE_FLAG_SPILL_BLKPTR) { SET_BOOKMARK(&czb, objset, object, 0, DMU_SPILL_BLKID); - traverse_prefetch_metadata(td, buf, &dnp->dn_spill, &czb); + traverse_prefetch_metadata(td, &dnp->dn_spill, &czb); } } static int traverse_dnode(traverse_data_t *td, const dnode_phys_t *dnp, - arc_buf_t *buf, uint64_t objset, uint64_t object) + uint64_t objset, uint64_t object) { int j, err = 0, lasterr = 0; zbookmark_t czb; @@ -410,7 +404,7 @@ traverse_dnode(traverse_data_t *td, const dnode_phys_t *dnp, for (j = 0; j < dnp->dn_nblkptr; j++) { SET_BOOKMARK(&czb, objset, object, dnp->dn_nlevels - 1, j); - err = traverse_visitbp(td, dnp, buf, &dnp->dn_blkptr[j], &czb); + err = traverse_visitbp(td, dnp, &dnp->dn_blkptr[j], &czb); if (err) { if (!hard) break; @@ -420,7 +414,7 @@ traverse_dnode(traverse_data_t *td, const dnode_phys_t *dnp, if (dnp->dn_flags & DNODE_FLAG_SPILL_BLKPTR) { SET_BOOKMARK(&czb, objset, object, 0, DMU_SPILL_BLKID); - err = traverse_visitbp(td, dnp, buf, &dnp->dn_spill, &czb); + err = traverse_visitbp(td, dnp, &dnp->dn_spill, &czb); if (err) { if (!hard) return (err); @@ -433,8 +427,7 @@ traverse_dnode(traverse_data_t *td, const dnode_phys_t *dnp, /* ARGSUSED */ static int traverse_prefetcher(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, - arc_buf_t *pbuf, const zbookmark_t *zb, const dnode_phys_t *dnp, - void *arg) + const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg) { prefetch_data_t *pfd = arg; uint32_t aflags = ARC_NOWAIT | ARC_PREFETCH; @@ -455,10 +448,8 @@ traverse_prefetcher(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, cv_broadcast(&pfd->pd_cv); mutex_exit(&pfd->pd_mtx); - (void) dsl_read(NULL, spa, bp, pbuf, NULL, NULL, - ZIO_PRIORITY_ASYNC_READ, - ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE, - &aflags, zb); + (void) arc_read(NULL, spa, bp, NULL, NULL, ZIO_PRIORITY_ASYNC_READ, + ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE, &aflags, zb); return (0); } @@ -476,7 +467,7 @@ traverse_prefetch_thread(void *arg) SET_BOOKMARK(&czb, td.td_objset, ZB_ROOT_OBJECT, ZB_ROOT_LEVEL, ZB_ROOT_BLKID); - (void) traverse_visitbp(&td, NULL, NULL, td.td_rootbp, &czb); + (void) traverse_visitbp(&td, NULL, td.td_rootbp, &czb); mutex_enter(&td_main->td_pfd->pd_mtx); td_main->td_pfd->pd_exited = B_TRUE; @@ -540,7 +531,7 @@ traverse_impl(spa_t *spa, dsl_dataset_t *ds, uint64_t objset, blkptr_t *rootbp, SET_BOOKMARK(&czb, td.td_objset, ZB_ROOT_OBJECT, ZB_ROOT_LEVEL, ZB_ROOT_BLKID); - err = traverse_visitbp(&td, NULL, NULL, rootbp, &czb); + err = traverse_visitbp(&td, NULL, rootbp, &czb); mutex_enter(&pd.pd_mtx); pd.pd_cancel = B_TRUE; diff --git a/uts/common/fs/zfs/dsl_dataset.c b/uts/common/fs/zfs/dsl_dataset.c index 6625444e5ab..177c63e230c 100644 --- a/uts/common/fs/zfs/dsl_dataset.c +++ b/uts/common/fs/zfs/dsl_dataset.c @@ -1260,7 +1260,7 @@ struct killarg { /* ARGSUSED */ static int -kill_blkptr(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, arc_buf_t *pbuf, +kill_blkptr(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg) { struct killarg *ka = arg; diff --git a/uts/common/fs/zfs/dsl_scan.c b/uts/common/fs/zfs/dsl_scan.c index 8f08f04a065..aec313ae793 100644 --- a/uts/common/fs/zfs/dsl_scan.c +++ b/uts/common/fs/zfs/dsl_scan.c @@ -366,24 +366,6 @@ dsl_free_sync(zio_t *pio, dsl_pool_t *dp, uint64_t txg, const blkptr_t *bpp) zio_nowait(zio_free_sync(pio, dp->dp_spa, txg, bpp, pio->io_flags)); } -int -dsl_read(zio_t *pio, spa_t *spa, const blkptr_t *bpp, arc_buf_t *pbuf, - arc_done_func_t *done, void *private, int priority, int zio_flags, - uint32_t *arc_flags, const zbookmark_t *zb) -{ - return (arc_read(pio, spa, bpp, pbuf, done, private, - priority, zio_flags, arc_flags, zb)); -} - -int -dsl_read_nolock(zio_t *pio, spa_t *spa, const blkptr_t *bpp, - arc_done_func_t *done, void *private, int priority, int zio_flags, - uint32_t *arc_flags, const zbookmark_t *zb) -{ - return (arc_read_nolock(pio, spa, bpp, done, private, - priority, zio_flags, arc_flags, zb)); -} - static uint64_t dsl_scan_ds_maxtxg(dsl_dataset_t *ds) { @@ -554,12 +536,8 @@ dsl_scan_prefetch(dsl_scan_t *scn, arc_buf_t *buf, blkptr_t *bp, SET_BOOKMARK(&czb, objset, object, BP_GET_LEVEL(bp), blkid); - /* - * XXX need to make sure all of these arc_read() prefetches are - * done before setting xlateall (similar to dsl_read()) - */ (void) arc_read(scn->scn_zio_root, scn->scn_dp->dp_spa, bp, - buf, NULL, NULL, ZIO_PRIORITY_ASYNC_READ, + NULL, NULL, ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL | ZIO_FLAG_SCAN_THREAD, &flags, &czb); } @@ -617,8 +595,7 @@ dsl_scan_recurse(dsl_scan_t *scn, dsl_dataset_t *ds, dmu_objset_type_t ostype, blkptr_t *cbp; int epb = BP_GET_LSIZE(bp) >> SPA_BLKPTRSHIFT; - err = arc_read_nolock(NULL, dp->dp_spa, bp, - arc_getbuf_func, bufp, + err = arc_read(NULL, dp->dp_spa, bp, arc_getbuf_func, bufp, ZIO_PRIORITY_ASYNC_READ, zio_flags, &flags, zb); if (err) { scn->scn_phys.scn_errors++; @@ -640,8 +617,7 @@ dsl_scan_recurse(dsl_scan_t *scn, dsl_dataset_t *ds, dmu_objset_type_t ostype, } else if (BP_GET_TYPE(bp) == DMU_OT_USERGROUP_USED) { uint32_t flags = ARC_WAIT; - err = arc_read_nolock(NULL, dp->dp_spa, bp, - arc_getbuf_func, bufp, + err = arc_read(NULL, dp->dp_spa, bp, arc_getbuf_func, bufp, ZIO_PRIORITY_ASYNC_READ, zio_flags, &flags, zb); if (err) { scn->scn_phys.scn_errors++; @@ -653,8 +629,7 @@ dsl_scan_recurse(dsl_scan_t *scn, dsl_dataset_t *ds, dmu_objset_type_t ostype, int i, j; int epb = BP_GET_LSIZE(bp) >> DNODE_SHIFT; - err = arc_read_nolock(NULL, dp->dp_spa, bp, - arc_getbuf_func, bufp, + err = arc_read(NULL, dp->dp_spa, bp, arc_getbuf_func, bufp, ZIO_PRIORITY_ASYNC_READ, zio_flags, &flags, zb); if (err) { scn->scn_phys.scn_errors++; @@ -676,8 +651,7 @@ dsl_scan_recurse(dsl_scan_t *scn, dsl_dataset_t *ds, dmu_objset_type_t ostype, uint32_t flags = ARC_WAIT; objset_phys_t *osp; - err = arc_read_nolock(NULL, dp->dp_spa, bp, - arc_getbuf_func, bufp, + err = arc_read(NULL, dp->dp_spa, bp, arc_getbuf_func, bufp, ZIO_PRIORITY_ASYNC_READ, zio_flags, &flags, zb); if (err) { scn->scn_phys.scn_errors++; diff --git a/uts/common/fs/zfs/spa.c b/uts/common/fs/zfs/spa.c index 4988b500b16..333bbeea930 100644 --- a/uts/common/fs/zfs/spa.c +++ b/uts/common/fs/zfs/spa.c @@ -1732,7 +1732,7 @@ spa_load_verify_done(zio_t *zio) /*ARGSUSED*/ static int spa_load_verify_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, - arc_buf_t *pbuf, const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg) + const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg) { if (bp != NULL) { zio_t *rio = arg; diff --git a/uts/common/fs/zfs/sys/arc.h b/uts/common/fs/zfs/sys/arc.h index b109dcafbcc..916d2abf147 100644 --- a/uts/common/fs/zfs/sys/arc.h +++ b/uts/common/fs/zfs/sys/arc.h @@ -49,7 +49,6 @@ struct arc_buf { arc_buf_hdr_t *b_hdr; arc_buf_t *b_next; kmutex_t b_evict_lock; - krwlock_t b_data_lock; void *b_data; arc_evict_func_t *b_efunc; void *b_private; @@ -93,8 +92,6 @@ void arc_buf_add_ref(arc_buf_t *buf, void *tag); int arc_buf_remove_ref(arc_buf_t *buf, void *tag); int arc_buf_size(arc_buf_t *buf); void arc_release(arc_buf_t *buf, void *tag); -int arc_release_bp(arc_buf_t *buf, void *tag, blkptr_t *bp, spa_t *spa, - zbookmark_t *zb); int arc_released(arc_buf_t *buf); int arc_has_callback(arc_buf_t *buf); void arc_buf_freeze(arc_buf_t *buf); @@ -104,10 +101,7 @@ boolean_t arc_buf_eviction_needed(arc_buf_t *buf); int arc_referenced(arc_buf_t *buf); #endif -int arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp, arc_buf_t *pbuf, - arc_done_func_t *done, void *private, int priority, int zio_flags, - uint32_t *arc_flags, const zbookmark_t *zb); -int arc_read_nolock(zio_t *pio, spa_t *spa, const blkptr_t *bp, +int arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp, arc_done_func_t *done, void *private, int priority, int flags, uint32_t *arc_flags, const zbookmark_t *zb); zio_t *arc_write(zio_t *pio, spa_t *spa, uint64_t txg, diff --git a/uts/common/fs/zfs/sys/dmu_traverse.h b/uts/common/fs/zfs/sys/dmu_traverse.h index 3cbf42f56a6..bc1590bc3aa 100644 --- a/uts/common/fs/zfs/sys/dmu_traverse.h +++ b/uts/common/fs/zfs/sys/dmu_traverse.h @@ -40,8 +40,7 @@ struct zilog; struct arc_buf; typedef int (blkptr_cb_t)(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, - struct arc_buf *pbuf, const zbookmark_t *zb, const struct dnode_phys *dnp, - void *arg); + const zbookmark_t *zb, const struct dnode_phys *dnp, void *arg); #define TRAVERSE_PRE (1<<0) #define TRAVERSE_POST (1<<1) diff --git a/uts/common/fs/zfs/sys/dsl_pool.h b/uts/common/fs/zfs/sys/dsl_pool.h index f8c98edc20b..ab1229a2e61 100644 --- a/uts/common/fs/zfs/sys/dsl_pool.h +++ b/uts/common/fs/zfs/sys/dsl_pool.h @@ -134,12 +134,6 @@ void dsl_pool_willuse_space(dsl_pool_t *dp, int64_t space, dmu_tx_t *tx); void dsl_free(dsl_pool_t *dp, uint64_t txg, const blkptr_t *bpp); void dsl_free_sync(zio_t *pio, dsl_pool_t *dp, uint64_t txg, const blkptr_t *bpp); -int dsl_read(zio_t *pio, spa_t *spa, const blkptr_t *bpp, arc_buf_t *pbuf, - arc_done_func_t *done, void *private, int priority, int zio_flags, - uint32_t *arc_flags, const zbookmark_t *zb); -int dsl_read_nolock(zio_t *pio, spa_t *spa, const blkptr_t *bpp, - arc_done_func_t *done, void *private, int priority, int zio_flags, - uint32_t *arc_flags, const zbookmark_t *zb); void dsl_pool_create_origin(dsl_pool_t *dp, dmu_tx_t *tx); void dsl_pool_upgrade_clones(dsl_pool_t *dp, dmu_tx_t *tx); void dsl_pool_upgrade_dir_clones(dsl_pool_t *dp, dmu_tx_t *tx); diff --git a/uts/common/fs/zfs/zil.c b/uts/common/fs/zfs/zil.c index 969723471e7..81d2bb5a975 100644 --- a/uts/common/fs/zfs/zil.c +++ b/uts/common/fs/zfs/zil.c @@ -190,7 +190,7 @@ zil_read_log_block(zilog_t *zilog, const blkptr_t *bp, blkptr_t *nbp, void *dst, SET_BOOKMARK(&zb, bp->blk_cksum.zc_word[ZIL_ZC_OBJSET], ZB_ZIL_OBJECT, ZB_ZIL_LEVEL, bp->blk_cksum.zc_word[ZIL_ZC_SEQ]); - error = dsl_read_nolock(NULL, zilog->zl_spa, bp, arc_getbuf_func, &abuf, + error = arc_read(NULL, zilog->zl_spa, bp, arc_getbuf_func, &abuf, ZIO_PRIORITY_SYNC_READ, zio_flags, &aflags, &zb); if (error == 0) { @@ -266,7 +266,7 @@ zil_read_log_data(zilog_t *zilog, const lr_write_t *lr, void *wbuf) SET_BOOKMARK(&zb, dmu_objset_id(zilog->zl_os), lr->lr_foid, ZB_ZIL_LEVEL, lr->lr_offset / BP_GET_LSIZE(bp)); - error = arc_read_nolock(NULL, zilog->zl_spa, bp, arc_getbuf_func, &abuf, + error = arc_read(NULL, zilog->zl_spa, bp, arc_getbuf_func, &abuf, ZIO_PRIORITY_SYNC_READ, zio_flags, &aflags, &zb); if (error == 0) { diff --git a/uts/common/fs/zfs/zio.c b/uts/common/fs/zfs/zio.c index 582c5046ec9..04b8ddfaf71 100644 --- a/uts/common/fs/zfs/zio.c +++ b/uts/common/fs/zfs/zio.c @@ -1994,7 +1994,7 @@ zio_ddt_collision(zio_t *zio, ddt_t *ddt, ddt_entry_t *dde) ddt_exit(ddt); - error = arc_read_nolock(NULL, spa, &blk, + error = arc_read(NULL, spa, &blk, arc_getbuf_func, &abuf, ZIO_PRIORITY_SYNC_READ, ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE, &aflags, &zio->io_bookmark); diff --git a/uts/common/fs/zfs/zvol.c b/uts/common/fs/zfs/zvol.c index 100fdd0303e..da1b0efda5b 100644 --- a/uts/common/fs/zfs/zvol.c +++ b/uts/common/fs/zfs/zvol.c @@ -236,7 +236,7 @@ struct maparg { /*ARGSUSED*/ static int -zvol_map_block(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, arc_buf_t *pbuf, +zvol_map_block(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg) { struct maparg *ma = arg; From dbfa74b7cc1a8513f9e57f34328741fcec75a1ed Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Wed, 6 Feb 2013 08:26:55 +0000 Subject: [PATCH 0009/1476] Update vendor/illumos/dist to illumos-gate version 13944:bbcbb468dc37 Illumos dtrace issues: 3519 DTrace fails to resolve const types from fbt 3520 dtrace internal error -- token type 316 is not a valid D compilation token 3521 clean up dtrace unit tests --- cmd/dtrace/test/tst/common/funcs/tst.copyin.d | 9 +++++- .../test/tst/common/funcs/tst.strjoin.d | 9 +++++- cmd/dtrace/test/tst/common/misc/tst.dynopt.d | 23 ++++++++++----- .../test/tst/common/pointers/err.BadAlign.d | 7 +++-- .../tst/common/pointers/err.InvalidAddress2.d | 5 +++- .../tst/common/pointers/err.InvalidAddress3.d | 7 +++-- .../tst/common/pointers/err.InvalidAddress4.d | 11 ++++--- .../tst/common/print/err.D_PRINT_AGG.bad.d | 29 +++++++++++++++++++ .../tst/common/print/err.D_PRINT_VOID.bad.d | 7 ++++- .../tst/common/print/err.D_PROTO_LEN.bad.d | 7 ++++- .../test/tst/common/safety/tst.copyin.d | 6 ++-- .../test/tst/common/scripting/tst.egid.ksh | 6 ++-- .../speculation/err.BufSizeVariations2.d | 4 ++- .../tst/common/trace/err.D_PROTO_LEN.bad.d | 10 +++++-- .../tst/common/trace/err.D_TRACE_VOID.bad.d | 9 +++++- cmd/dtrace/test/tst/common/types/tst.const.d | 29 +++++++++++++++++++ lib/libdtrace/common/dt_cc.c | 6 ++++ lib/libdtrace/common/dt_decl.c | 6 +--- lib/libdtrace/common/dt_errtags.h | 2 ++ 19 files changed, 158 insertions(+), 34 deletions(-) create mode 100644 cmd/dtrace/test/tst/common/print/err.D_PRINT_AGG.bad.d create mode 100644 cmd/dtrace/test/tst/common/types/tst.const.d diff --git a/cmd/dtrace/test/tst/common/funcs/tst.copyin.d b/cmd/dtrace/test/tst/common/funcs/tst.copyin.d index 186b97419e8..4ecc23e6768 100644 --- a/cmd/dtrace/test/tst/common/funcs/tst.copyin.d +++ b/cmd/dtrace/test/tst/common/funcs/tst.copyin.d @@ -24,7 +24,9 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright (c) 2012 by Delphix. All rights reserved. + */ /* * ASSERTION: @@ -52,3 +54,8 @@ BEGIN printf("envp[0] = \"%s\"", copyinstr(envp)); exit(0); } + +BEGIN +{ + exit(1) +} diff --git a/cmd/dtrace/test/tst/common/funcs/tst.strjoin.d b/cmd/dtrace/test/tst/common/funcs/tst.strjoin.d index 392c18a6df8..0f23737d38f 100644 --- a/cmd/dtrace/test/tst/common/funcs/tst.strjoin.d +++ b/cmd/dtrace/test/tst/common/funcs/tst.strjoin.d @@ -24,7 +24,9 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright (c) 2012 by Delphix. All rights reserved. + */ #pragma D option quiet @@ -36,3 +38,8 @@ BEGIN printf("%s\n", strjoin("", "")); exit(0); } + +BEGIN +{ + exit(1); +} diff --git a/cmd/dtrace/test/tst/common/misc/tst.dynopt.d b/cmd/dtrace/test/tst/common/misc/tst.dynopt.d index cb98d73375c..78d96f00a63 100644 --- a/cmd/dtrace/test/tst/common/misc/tst.dynopt.d +++ b/cmd/dtrace/test/tst/common/misc/tst.dynopt.d @@ -24,38 +24,45 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright (c) 2012 by Delphix. All rights reserved. + */ #pragma D option quiet #pragma D option switchrate=1ms #pragma D option aggrate=1ms -tick-100ms +tick-50ms { i++; } -tick-100ms -/i > 1/ +tick-50ms +/!(i & 1) && i > 1/ { setopt("quiet", "no"); setopt("quiet"); setopt("quiet"); setopt("quiet", "yes"); @["abc"] = count(); +} + +tick-50ms +/(i & 1) && i > 1/ +{ printa("%@d\n", @); } -tick-100ms -/i == 5/ +tick-50ms +/i == 10/ { setopt("switchrate", "5sec"); setopt("aggrate", "5sec"); } -tick-100ms -/i == 31/ +tick-50ms +/i == 61/ { exit(0); } diff --git a/cmd/dtrace/test/tst/common/pointers/err.BadAlign.d b/cmd/dtrace/test/tst/common/pointers/err.BadAlign.d index ab4106dbeef..3923cd910a1 100644 --- a/cmd/dtrace/test/tst/common/pointers/err.BadAlign.d +++ b/cmd/dtrace/test/tst/common/pointers/err.BadAlign.d @@ -24,7 +24,9 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright (c) 2012 by Delphix. All rights reserved. + */ /* * ASSERTION: This test reproduces the alignment error. @@ -39,9 +41,10 @@ BEGIN { - x = (int *) 64; + x = (int *)64; y = *x; trace(y); + exit(0); } ERROR diff --git a/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress2.d b/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress2.d index 324f40113ae..6c79bfa4201 100644 --- a/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress2.d +++ b/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress2.d @@ -24,7 +24,9 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright (c) 2012 by Delphix. All rights reserved. + */ /* * ASSERTION: D pointers do not allow invalid pointer accesses. @@ -44,6 +46,7 @@ BEGIN y = (int *) (x - 3300778156056); *y = 3; trace(*y); + exit(0); } ERROR diff --git a/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress3.d b/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress3.d index 39bd1140bdf..66c203061d0 100644 --- a/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress3.d +++ b/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress3.d @@ -24,7 +24,9 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright (c) 2012 by Delphix. All rights reserved. + */ /* * ASSERTION: D pointers do not allow invalid pointer accesses. @@ -39,9 +41,10 @@ BEGIN { - y = (int *) (-33007); + y = (int *)-33007; *y = 3; trace(*y); + exit(0); } ERROR diff --git a/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress4.d b/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress4.d index 9d6b144086b..f5f49e966fc 100644 --- a/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress4.d +++ b/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress4.d @@ -24,7 +24,9 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright (c) 2012 by Delphix. All rights reserved. + */ /* * ASSERTION: Demonstrating valid memory access. @@ -40,10 +42,11 @@ BEGIN { x = (int *)alloca(sizeof (int)); - printf("Address x: %x\n", (int) x); - y = (int *) (x - 2); + printf("Address x: %x\n", (int)x); + y = (int *)(x - 2); *y = 3; - printf("Address y: %x\tValue: %d\n", (int) y, *y); + printf("Address y: %x\tValue: %d\n", (int)y, *y); + exit(0); } ERROR diff --git a/cmd/dtrace/test/tst/common/print/err.D_PRINT_AGG.bad.d b/cmd/dtrace/test/tst/common/print/err.D_PRINT_AGG.bad.d new file mode 100644 index 00000000000..5479d00126a --- /dev/null +++ b/cmd/dtrace/test/tst/common/print/err.D_PRINT_AGG.bad.d @@ -0,0 +1,29 @@ +/* + * CDDL HEADER START + * + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2012 by Delphix. All rights reserved. + */ + +BEGIN +{ + @ = count(); + print(@); +} + +BEGIN +{ + exit(0); +} diff --git a/cmd/dtrace/test/tst/common/print/err.D_PRINT_VOID.bad.d b/cmd/dtrace/test/tst/common/print/err.D_PRINT_VOID.bad.d index 902f07272dd..4f45885d42a 100644 --- a/cmd/dtrace/test/tst/common/print/err.D_PRINT_VOID.bad.d +++ b/cmd/dtrace/test/tst/common/print/err.D_PRINT_VOID.bad.d @@ -20,10 +20,15 @@ */ /* - * Copyright (c) 2011 by Delphix. All rights reserved. + * Copyright (c) 2012 by Delphix. All rights reserved. */ BEGIN { print((void)`p0); } + +BEGIN +{ + exit(0); +} diff --git a/cmd/dtrace/test/tst/common/print/err.D_PROTO_LEN.bad.d b/cmd/dtrace/test/tst/common/print/err.D_PROTO_LEN.bad.d index a1d3be1f62d..368caebacb8 100644 --- a/cmd/dtrace/test/tst/common/print/err.D_PROTO_LEN.bad.d +++ b/cmd/dtrace/test/tst/common/print/err.D_PROTO_LEN.bad.d @@ -20,10 +20,15 @@ */ /* - * Copyright (c) 2011 by Delphix. All rights reserved. + * Copyright (c) 2012 by Delphix. All rights reserved. */ BEGIN { print(); } + +BEGIN +{ + exit(0); +} diff --git a/cmd/dtrace/test/tst/common/safety/tst.copyin.d b/cmd/dtrace/test/tst/common/safety/tst.copyin.d index 7426d19e1b3..beb1c50bba3 100644 --- a/cmd/dtrace/test/tst/common/safety/tst.copyin.d +++ b/cmd/dtrace/test/tst/common/safety/tst.copyin.d @@ -24,7 +24,9 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright (c) 2012 by Delphix. All rights reserved. + */ /* * ASSERTION: @@ -39,7 +41,7 @@ */ -#pragma D option bufsize=16 +#pragma D option bufsize=32 #pragma D option bufpolicy=ring #pragma D option statusrate=1nsec diff --git a/cmd/dtrace/test/tst/common/scripting/tst.egid.ksh b/cmd/dtrace/test/tst/common/scripting/tst.egid.ksh index 9e1955f2980..b0d985401c9 100644 --- a/cmd/dtrace/test/tst/common/scripting/tst.egid.ksh +++ b/cmd/dtrace/test/tst/common/scripting/tst.egid.ksh @@ -25,7 +25,9 @@ # Use is subject to license terms. # -#ident "%Z%%M% %I% %E% SMI" +# +# Copyright (c) 2012 by Delphix. All rights reserved. +# ############################################################################ # ASSERTION: @@ -70,7 +72,7 @@ EOF #chmod 555 the .d file chmod 555 $dfilename >/dev/null 2>&1 -if [ &? -ne 0 ]; then +if [ $? -ne 0 ]; then print -u2 "chmod $dfilename failed" exit 1 fi diff --git a/cmd/dtrace/test/tst/common/speculation/err.BufSizeVariations2.d b/cmd/dtrace/test/tst/common/speculation/err.BufSizeVariations2.d index f660e9a8f3c..5ac7957ced8 100644 --- a/cmd/dtrace/test/tst/common/speculation/err.BufSizeVariations2.d +++ b/cmd/dtrace/test/tst/common/speculation/err.BufSizeVariations2.d @@ -24,7 +24,9 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright (c) 2012 by Delphix. All rights reserved. + */ /* * ASSERTION: diff --git a/cmd/dtrace/test/tst/common/trace/err.D_PROTO_LEN.bad.d b/cmd/dtrace/test/tst/common/trace/err.D_PROTO_LEN.bad.d index a1ec95ccb4f..68c11950b51 100644 --- a/cmd/dtrace/test/tst/common/trace/err.D_PROTO_LEN.bad.d +++ b/cmd/dtrace/test/tst/common/trace/err.D_PROTO_LEN.bad.d @@ -24,8 +24,9 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - +/* + * Copyright (c) 2012 by Delphix. All rights reserved. + */ /* * ASSERTION: @@ -39,3 +40,8 @@ BEGIN trace(); } + +BEGIN +{ + exit(0); +} diff --git a/cmd/dtrace/test/tst/common/trace/err.D_TRACE_VOID.bad.d b/cmd/dtrace/test/tst/common/trace/err.D_TRACE_VOID.bad.d index eb9f194a73f..ed044b2236f 100644 --- a/cmd/dtrace/test/tst/common/trace/err.D_TRACE_VOID.bad.d +++ b/cmd/dtrace/test/tst/common/trace/err.D_TRACE_VOID.bad.d @@ -24,7 +24,9 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright (c) 2012 by Delphix. All rights reserved. + */ /* * ASSERTION: @@ -37,3 +39,8 @@ BEGIN { trace((void)`kmem_flags); } + +BEGIN +{ + exit(0); +} diff --git a/cmd/dtrace/test/tst/common/types/tst.const.d b/cmd/dtrace/test/tst/common/types/tst.const.d new file mode 100644 index 00000000000..dae3d9041ed --- /dev/null +++ b/cmd/dtrace/test/tst/common/types/tst.const.d @@ -0,0 +1,29 @@ +/* + * CDDL HEADER START + * + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2012 by Delphix. All rights reserved. + */ + +/* + * Make sure we can scope types with modifiers. + */ + +BEGIN +{ + trace((D`int *)0); + trace((const D`int *)0); + exit(0); +} diff --git a/lib/libdtrace/common/dt_cc.c b/lib/libdtrace/common/dt_cc.c index 4163e939944..9661ad9d0b4 100644 --- a/lib/libdtrace/common/dt_cc.c +++ b/lib/libdtrace/common/dt_cc.c @@ -676,6 +676,12 @@ dt_action_trace(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp) "%s( ) may not be applied to a translated pointer\n", act); } + if (dnp->dn_args->dn_kind == DT_NODE_AGG) { + dnerror(dnp->dn_args, istrace ? D_TRACE_AGG : D_PRINT_AGG, + "%s( ) may not be applied to an aggregation%s\n", act, + istrace ? "" : " -- did you mean printa()?"); + } + dt_cg(yypcb, dnp->dn_args); /* diff --git a/lib/libdtrace/common/dt_decl.c b/lib/libdtrace/common/dt_decl.c index d2a0b29ca8e..563c0057da6 100644 --- a/lib/libdtrace/common/dt_decl.c +++ b/lib/libdtrace/common/dt_decl.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012 by Delphix. All rights reserved. */ #include @@ -251,11 +252,6 @@ dt_decl_spec(ushort_t kind, char *name) ddp->dd_kind = kind; ddp->dd_name = name; - if (name != NULL && strchr(name, '`') != NULL) { - xyerror(D_DECL_SCOPE, "D scoping operator may not be used " - "in a type name\n"); - } - return (dt_decl_check(ddp)); } diff --git a/lib/libdtrace/common/dt_errtags.h b/lib/libdtrace/common/dt_errtags.h index 0a9e7c029b4..0dd34e45251 100644 --- a/lib/libdtrace/common/dt_errtags.h +++ b/lib/libdtrace/common/dt_errtags.h @@ -190,8 +190,10 @@ typedef enum { D_PRINTA_AGGPROTO, /* printa() aggregation mismatch */ D_TRACE_VOID, /* trace() argument has void type */ D_TRACE_DYN, /* trace() argument has dynamic type */ + D_TRACE_AGG, /* trace() argument is an aggregation */ D_PRINT_VOID, /* print() argument has void type */ D_PRINT_DYN, /* print() argument has dynamic type */ + D_PRINT_AGG, /* print() argument is an aggregation */ D_TRACEMEM_ADDR, /* tracemem() address bad type */ D_TRACEMEM_SIZE, /* tracemem() size bad type */ D_TRACEMEM_ARGS, /* tracemem() illegal number of args */ From 98d50a301a1c2b38fedd9b945bb3cbfb193348b8 Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Wed, 6 Feb 2013 08:29:00 +0000 Subject: [PATCH 0010/1476] Update vendor-sys/illumos/dist to illumos-gate version 13945:7a9c1d41dfbe Illumos ZFS issues: 3507 Tunable to allow block allocation even on degraded vdevs --- uts/common/fs/zfs/metaslab.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/uts/common/fs/zfs/metaslab.c b/uts/common/fs/zfs/metaslab.c index 6449788c1c3..ceb7c6fa573 100644 --- a/uts/common/fs/zfs/metaslab.c +++ b/uts/common/fs/zfs/metaslab.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012 by Delphix. All rights reserved. + * Copyright (c) 2013 by Saso Kiselkov. All rights reserved. */ #include @@ -90,6 +91,11 @@ int metaslab_prefetch_limit = SPA_DVAS_PER_BP; */ int metaslab_smo_bonus_pct = 150; +/* + * Should we be willing to write data to degraded vdevs? + */ +boolean_t zfs_write_to_degraded = B_FALSE; + /* * ========================================================================== * Metaslab classes @@ -1377,10 +1383,13 @@ top: /* * Avoid writing single-copy data to a failing vdev + * unless the user instructs us that it is okay. */ if ((vd->vdev_stat.vs_write_errors > 0 || vd->vdev_state < VDEV_STATE_HEALTHY) && - d == 0 && dshift == 3) { + d == 0 && dshift == 3 && + !(zfs_write_to_degraded && vd->vdev_state == + VDEV_STATE_DEGRADED)) { all_zero = B_FALSE; goto next; } From 21bca442b925046ac2eed07d3b1fadd461b3a1b8 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Thu, 7 Feb 2013 02:15:25 +0000 Subject: [PATCH 0011/1476] Methodize the process of adding the software TX queue to the taskqueue. Move it (for now) to the TX taskqueue. --- sys/dev/ath/if_ath.c | 4 ++-- sys/dev/ath/if_ath_misc.h | 14 +++++++++++++- sys/dev/ath/if_ath_tx.c | 8 +++++--- sys/dev/ath/if_ath_tx_edma.c | 2 +- 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 41019fbb74b..c492592c594 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -4230,9 +4230,9 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq, int dosched) ieee80211_ff_flush(ic, txq->axq_ac); #endif - /* Kick the TXQ scheduler */ + /* Kick the software TXQ scheduler */ if (dosched) { - taskqueue_enqueue(sc->sc_tx_tq, &sc->sc_txqtask); + ath_tx_swq_kick(sc); } ATH_KTR(sc, ATH_KTR_TXCOMP, 1, diff --git a/sys/dev/ath/if_ath_misc.h b/sys/dev/ath/if_ath_misc.h index a97f897bcda..d81ef4ce8fc 100644 --- a/sys/dev/ath/if_ath_misc.h +++ b/sys/dev/ath/if_ath_misc.h @@ -120,12 +120,24 @@ extern void ath_tx_update_tim(struct ath_softc *sc, extern void ath_start(struct ifnet *ifp); extern void ath_start_task(void *arg, int npending); +/* + * Kick the frame TX task. + */ static inline void ath_tx_kick(struct ath_softc *sc) { - /* XXX eventually try sc_tx_tq? */ taskqueue_enqueue(sc->sc_tx_tq, &sc->sc_txpkttask); } +/* + * Kick the software TX queue task. + */ +static inline void +ath_tx_swq_kick(struct ath_softc *sc) +{ + + taskqueue_enqueue(sc->sc_tx_tq, &sc->sc_txqtask); +} + #endif diff --git a/sys/dev/ath/if_ath_tx.c b/sys/dev/ath/if_ath_tx.c index b3b60796478..e19a63766a2 100644 --- a/sys/dev/ath/if_ath_tx.c +++ b/sys/dev/ath/if_ath_tx.c @@ -2999,9 +2999,11 @@ ath_tx_tid_resume(struct ath_softc *sc, struct ath_tid *tid) } ath_tx_tid_sched(sc, tid); - /* Punt some frames to the hardware if needed */ - //ath_txq_sched(sc, sc->sc_ac2q[tid->ac]); - taskqueue_enqueue(sc->sc_tx_tq, &sc->sc_txqtask); + + /* + * Queue the software TX scheduler. + */ + ath_tx_swq_kick(sc); } /* diff --git a/sys/dev/ath/if_ath_tx_edma.c b/sys/dev/ath/if_ath_tx_edma.c index a2eef65a6b5..6c6889c28ac 100644 --- a/sys/dev/ath/if_ath_tx_edma.c +++ b/sys/dev/ath/if_ath_tx_edma.c @@ -655,7 +655,7 @@ ath_edma_tx_processq(struct ath_softc *sc, int dosched) * the txq task for _one_ TXQ. This should be fixed. */ if (dosched) - taskqueue_enqueue(sc->sc_tx_tq, &sc->sc_txqtask); + ath_tx_swq_kick(sc); } static void From dae3dc73f66189deaff9a2e5ec6f55c1bffaa94a Mon Sep 17 00:00:00 2001 From: Neel Natu Date: Thu, 7 Feb 2013 06:48:47 +0000 Subject: [PATCH 0012/1476] If an interrupt event's assign_cpu method fails, then restore the original cpuset mask for the associated interrupt thread. The text used above is verbatim from r195249 and the code should now be in line with the intent of that commit. --- sys/kern/kern_intr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/kern/kern_intr.c b/sys/kern/kern_intr.c index bce23972b1d..d2c31fd479c 100644 --- a/sys/kern/kern_intr.c +++ b/sys/kern/kern_intr.c @@ -336,7 +336,7 @@ intr_event_bind(struct intr_event *ie, u_char cpu) if (ie->ie_cpu == NOCPU) CPU_COPY(cpuset_root, &mask); else - CPU_SET(cpu, &mask); + CPU_SET(ie->ie_cpu, &mask); id = ie->ie_thread->it_thread->td_tid; mtx_unlock(&ie->ie_lock); (void)cpuset_setthread(id, &mask); From 1b3502e5a1ced38d2580bcc14052732b883b2912 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Thu, 7 Feb 2013 07:50:16 +0000 Subject: [PATCH 0013/1476] Create a new TX lock specifically for queuing frames. This now separates out the act of queuing frames from the act of running TX and TX completion. --- sys/dev/ath/if_ath.c | 22 ++++++++-------------- sys/dev/ath/if_ath_ahb.c | 3 +++ sys/dev/ath/if_ath_pci.c | 3 +++ sys/dev/ath/if_athvar.h | 30 +++++++++++++++++++++++++----- 4 files changed, 39 insertions(+), 19 deletions(-) diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index c492592c594..bcb5e8a1ecd 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -2687,7 +2687,7 @@ ath_txq_qadd(struct ifnet *ifp, struct mbuf *m0) struct mbuf *m; /* XXX recursive TX completion -> TX? */ - ATH_TX_UNLOCK_ASSERT(sc); + ATH_TX_IC_UNLOCK_ASSERT(sc); /* * We grab the node pointer, but we don't deref @@ -2749,7 +2749,7 @@ ath_txq_qadd(struct ifnet *ifp, struct mbuf *m0) * into the driver. */ - ATH_TX_LOCK(sc); + ATH_TX_IC_LOCK(sc); /* * Throw the single frame onto the queue. @@ -2797,7 +2797,7 @@ ath_txq_qadd(struct ifnet *ifp, struct mbuf *m0) m = m->m_nextpkt; } - ATH_TX_UNLOCK(sc); + ATH_TX_IC_UNLOCK(sc); return (0); bad: @@ -2825,13 +2825,13 @@ ath_txq_qflush(struct ifnet *ifp) TAILQ_INIT(&txlist); /* Grab lock */ - ATH_TX_LOCK(sc); + ATH_TX_IC_LOCK(sc); /* Copy everything out of sc_txbuf_list into txlist */ TAILQ_CONCAT(&txlist, &sc->sc_txbuf_list, bf_list); /* Unlock */ - ATH_TX_UNLOCK(sc); + ATH_TX_IC_UNLOCK(sc); /* Now, walk the list, freeing things */ while ((bf = TAILQ_FIRST(&txlist)) != NULL) { @@ -2879,16 +2879,9 @@ ath_txq_qrun(struct ifnet *ifp) */ /* Copy everything out of sc_txbuf_list into txlist */ - ATH_TX_LOCK(sc); + ATH_TX_IC_LOCK(sc); TAILQ_CONCAT(&txlist, &sc->sc_txbuf_list, bf_list); - ATH_TX_UNLOCK(sc); - - /* - * For now, the ath_tx_start() code sits behind the same lock; - * worry about serialising this in a taskqueue later. - */ - - ATH_TX_LOCK(sc); + ATH_TX_IC_UNLOCK(sc); /* * Attempt to transmit each frame. @@ -2899,6 +2892,7 @@ ath_txq_qrun(struct ifnet *ifp) * It would be nice to chain together TX fragments in this * way so they can be aborted together. */ + ATH_TX_LOCK(sc); TAILQ_FOREACH_SAFE(bf, &txlist, bf_list, bf_next) { /* * Clear, because we're going to reuse this diff --git a/sys/dev/ath/if_ath_ahb.c b/sys/dev/ath/if_ath_ahb.c index cca01163149..400ff818bad 100644 --- a/sys/dev/ath/if_ath_ahb.c +++ b/sys/dev/ath/if_ath_ahb.c @@ -195,6 +195,7 @@ ath_ahb_attach(device_t dev) ATH_PCU_LOCK_INIT(sc); ATH_RX_LOCK_INIT(sc); ATH_TX_LOCK_INIT(sc); + ATH_TX_IC_LOCK_INIT(sc); ATH_TXSTATUS_LOCK_INIT(sc); error = ath_attach(AR9130_DEVID, sc); @@ -204,6 +205,7 @@ ath_ahb_attach(device_t dev) ATH_TXSTATUS_LOCK_DESTROY(sc); ATH_RX_LOCK_DESTROY(sc); ATH_TX_LOCK_DESTROY(sc); + ATH_TX_IC_LOCK_DESTROY(sc); ATH_PCU_LOCK_DESTROY(sc); ATH_LOCK_DESTROY(sc); bus_dma_tag_destroy(sc->sc_dmat); @@ -247,6 +249,7 @@ ath_ahb_detach(device_t dev) ATH_TXSTATUS_LOCK_DESTROY(sc); ATH_RX_LOCK_DESTROY(sc); ATH_TX_LOCK_DESTROY(sc); + ATH_TX_IC_LOCK_DESTROY(sc); ATH_PCU_LOCK_DESTROY(sc); ATH_LOCK_DESTROY(sc); diff --git a/sys/dev/ath/if_ath_pci.c b/sys/dev/ath/if_ath_pci.c index 0447688c7c0..91cb425ffc2 100644 --- a/sys/dev/ath/if_ath_pci.c +++ b/sys/dev/ath/if_ath_pci.c @@ -251,6 +251,7 @@ ath_pci_attach(device_t dev) ATH_PCU_LOCK_INIT(sc); ATH_RX_LOCK_INIT(sc); ATH_TX_LOCK_INIT(sc); + ATH_TX_IC_LOCK_INIT(sc); ATH_TXSTATUS_LOCK_INIT(sc); error = ath_attach(pci_get_device(dev), sc); @@ -260,6 +261,7 @@ ath_pci_attach(device_t dev) ATH_TXSTATUS_LOCK_DESTROY(sc); ATH_PCU_LOCK_DESTROY(sc); ATH_RX_LOCK_DESTROY(sc); + ATH_TX_IC_LOCK_DESTROY(sc); ATH_TX_LOCK_DESTROY(sc); ATH_LOCK_DESTROY(sc); bus_dma_tag_destroy(sc->sc_dmat); @@ -302,6 +304,7 @@ ath_pci_detach(device_t dev) ATH_TXSTATUS_LOCK_DESTROY(sc); ATH_PCU_LOCK_DESTROY(sc); ATH_RX_LOCK_DESTROY(sc); + ATH_TX_IC_LOCK_DESTROY(sc); ATH_TX_LOCK_DESTROY(sc); ATH_LOCK_DESTROY(sc); diff --git a/sys/dev/ath/if_athvar.h b/sys/dev/ath/if_athvar.h index 070fe53b221..52ed6d8dc87 100644 --- a/sys/dev/ath/if_athvar.h +++ b/sys/dev/ath/if_athvar.h @@ -520,8 +520,10 @@ struct ath_softc { char sc_pcu_mtx_name[32]; struct mtx sc_rx_mtx; /* RX access mutex */ char sc_rx_mtx_name[32]; - struct mtx sc_tx_mtx; /* TX access mutex */ + struct mtx sc_tx_mtx; /* TX handling/comp mutex */ char sc_tx_mtx_name[32]; + struct mtx sc_tx_ic_mtx; /* TX queue mutex */ + char sc_tx_ic_mtx_name[32]; struct taskqueue *sc_tq; /* private task queue */ struct taskqueue *sc_tx_tq; /* private TX task queue */ struct ath_hal *sc_ah; /* Atheros HAL */ @@ -795,10 +797,8 @@ struct ath_softc { #define ATH_UNLOCK_ASSERT(_sc) mtx_assert(&(_sc)->sc_mtx, MA_NOTOWNED) /* - * The TX lock is non-reentrant and serialises the TX send operations. - * (ath_start(), ath_raw_xmit().) It doesn't yet serialise the TX - * completion operations; thus it can't be used (yet!) to protect - * hardware / software TXQ operations. + * The TX lock is non-reentrant and serialises the TX frame send + * and completion operations. */ #define ATH_TX_LOCK_INIT(_sc) do {\ snprintf((_sc)->sc_tx_mtx_name, \ @@ -816,6 +816,26 @@ struct ath_softc { #define ATH_TX_UNLOCK_ASSERT(_sc) mtx_assert(&(_sc)->sc_tx_mtx, \ MA_NOTOWNED) +/* + * The IC TX lock is non-reentrant and serialises packet queuing from + * the upper layers. + */ +#define ATH_TX_IC_LOCK_INIT(_sc) do {\ + snprintf((_sc)->sc_tx_ic_mtx_name, \ + sizeof((_sc)->sc_tx_ic_mtx_name), \ + "%s IC TX lock", \ + device_get_nameunit((_sc)->sc_dev)); \ + mtx_init(&(_sc)->sc_tx_ic_mtx, (_sc)->sc_tx_ic_mtx_name, \ + NULL, MTX_DEF); \ + } while (0) +#define ATH_TX_IC_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_tx_ic_mtx) +#define ATH_TX_IC_LOCK(_sc) mtx_lock(&(_sc)->sc_tx_ic_mtx) +#define ATH_TX_IC_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_tx_ic_mtx) +#define ATH_TX_IC_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->sc_tx_ic_mtx, \ + MA_OWNED) +#define ATH_TX_IC_UNLOCK_ASSERT(_sc) mtx_assert(&(_sc)->sc_tx_ic_mtx, \ + MA_NOTOWNED) + /* * The PCU lock is non-recursive and should be treated as a spinlock. * Although currently the interrupt code is run in netisr context and From 2ba0f361399b496357a4017f22273986adb3cdff Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Thu, 7 Feb 2013 08:20:03 +0000 Subject: [PATCH 0014/1476] Add support for mute buttons on USB audio devices and use the hwvol interface to adjust the mixer settings. MFC after: 1 week --- sys/dev/sound/pcm/mixer.c | 39 +++++++++++++++++++++++--------- sys/dev/sound/pcm/mixer.h | 2 ++ sys/dev/sound/usb/uaudio.c | 46 +++++++++++++++++++++++--------------- 3 files changed, 58 insertions(+), 29 deletions(-) diff --git a/sys/dev/sound/pcm/mixer.c b/sys/dev/sound/pcm/mixer.c index eea11e6681d..8f9a5fb3a7f 100644 --- a/sys/dev/sound/pcm/mixer.c +++ b/sys/dev/sound/pcm/mixer.c @@ -893,14 +893,8 @@ mixer_hwvol_init(device_t dev) } void -mixer_hwvol_mute(device_t dev) +mixer_hwvol_mute_locked(struct snd_mixer *m) { - struct snd_mixer *m; - struct cdev *pdev; - - pdev = mixer_get_devt(dev); - m = pdev->si_drv1; - snd_mtxlock(m->lock); if (m->hwvol_muted) { m->hwvol_muted = 0; mixer_set(m, m->hwvol_mixer, m->hwvol_mute_level); @@ -909,19 +903,26 @@ mixer_hwvol_mute(device_t dev) m->hwvol_mute_level = mixer_get(m, m->hwvol_mixer); mixer_set(m, m->hwvol_mixer, 0); } - snd_mtxunlock(m->lock); } void -mixer_hwvol_step(device_t dev, int left_step, int right_step) +mixer_hwvol_mute(device_t dev) { struct snd_mixer *m; - int level, left, right; struct cdev *pdev; pdev = mixer_get_devt(dev); m = pdev->si_drv1; snd_mtxlock(m->lock); + mixer_hwvol_mute_locked(m); + snd_mtxunlock(m->lock); +} + +void +mixer_hwvol_step_locked(struct snd_mixer *m, int left_step, int right_step) +{ + int level, left, right; + if (m->hwvol_muted) { m->hwvol_muted = 0; level = m->hwvol_mute_level; @@ -929,15 +930,31 @@ mixer_hwvol_step(device_t dev, int left_step, int right_step) level = mixer_get(m, m->hwvol_mixer); if (level != -1) { left = level & 0xff; - right = level >> 8; + right = (level >> 8) & 0xff; left += left_step * m->hwvol_step; if (left < 0) left = 0; + else if (left > 100) + left = 100; right += right_step * m->hwvol_step; if (right < 0) right = 0; + else if (right > 100) + right = 100; mixer_set(m, m->hwvol_mixer, left | right << 8); } +} + +void +mixer_hwvol_step(device_t dev, int left_step, int right_step) +{ + struct snd_mixer *m; + struct cdev *pdev; + + pdev = mixer_get_devt(dev); + m = pdev->si_drv1; + snd_mtxlock(m->lock); + mixer_hwvol_step_locked(m, left_step, right_step); snd_mtxunlock(m->lock); } diff --git a/sys/dev/sound/pcm/mixer.h b/sys/dev/sound/pcm/mixer.h index 22780abd922..0fb2e914433 100644 --- a/sys/dev/sound/pcm/mixer.h +++ b/sys/dev/sound/pcm/mixer.h @@ -40,7 +40,9 @@ int mixer_ioctl_cmd(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode, struc int mixer_oss_mixerinfo(struct cdev *i_dev, oss_mixerinfo *mi); int mixer_hwvol_init(device_t dev); +void mixer_hwvol_mute_locked(struct snd_mixer *m); void mixer_hwvol_mute(device_t dev); +void mixer_hwvol_step_locked(struct snd_mixer *m, int l_step, int r_step); void mixer_hwvol_step(device_t dev, int left_step, int right_step); int mixer_busy(struct snd_mixer *m); diff --git a/sys/dev/sound/usb/uaudio.c b/sys/dev/sound/usb/uaudio.c index cc7128e6259..4c8f2ba61a6 100644 --- a/sys/dev/sound/usb/uaudio.c +++ b/sys/dev/sound/usb/uaudio.c @@ -287,14 +287,17 @@ struct uaudio_hid { struct usb_xfer *xfer[UAUDIO_HID_N_TRANSFER]; struct hid_location volume_up_loc; struct hid_location volume_down_loc; + struct hid_location mute_loc; uint32_t flags; #define UAUDIO_HID_VALID 0x0001 #define UAUDIO_HID_HAS_ID 0x0002 #define UAUDIO_HID_HAS_VOLUME_UP 0x0004 #define UAUDIO_HID_HAS_VOLUME_DOWN 0x0008 +#define UAUDIO_HID_HAS_MUTE 0x0010 uint8_t iface_index; uint8_t volume_up_id; uint8_t volume_down_id; + uint8_t mute_id; }; struct uaudio_softc { @@ -1012,6 +1015,8 @@ uaudio_attach_sub(device_t dev, kobj_class_t mixer_class, kobj_class_t chan_clas goto detach; sc->sc_mixer_init = 1; + mixer_hwvol_init(dev); + snprintf(status, sizeof(status), "at ? %s", PCM_KLDSTRING(snd_uaudio)); if (pcm_register(dev, sc, @@ -5520,9 +5525,6 @@ uaudio_hid_rx_callback(struct usb_xfer *xfer, usb_error_t error) struct uaudio_softc *sc = usbd_xfer_softc(xfer); const uint8_t *buffer = usbd_xfer_get_frame_buffer(xfer, 0); struct snd_mixer *m; - int v; - int v_l; - int v_r; uint8_t id; int actlen; @@ -5543,6 +5545,16 @@ uaudio_hid_rx_callback(struct usb_xfer *xfer, usb_error_t error) m = sc->sc_mixer_dev; + if ((sc->sc_hid.flags & UAUDIO_HID_HAS_MUTE) && + (sc->sc_hid.mute_id == id) && + hid_get_data(buffer, actlen, + &sc->sc_hid.mute_loc)) { + + DPRINTF("Mute toggle\n"); + + mixer_hwvol_mute_locked(m); + } + if ((sc->sc_hid.flags & UAUDIO_HID_HAS_VOLUME_UP) && (sc->sc_hid.volume_up_id == id) && hid_get_data(buffer, actlen, @@ -5550,13 +5562,7 @@ uaudio_hid_rx_callback(struct usb_xfer *xfer, usb_error_t error) DPRINTF("Volume Up\n"); - v = mix_get_locked(m, SOUND_MIXER_PCM, &v_l, &v_r); - if (v == 0) { - v = ((v_l + v_r) / 2) + 5; - if (v > 100) - v = 100; - mix_set_locked(m, SOUND_MIXER_PCM, v, v); - } + mixer_hwvol_step_locked(m, 1, 1); } if ((sc->sc_hid.flags & UAUDIO_HID_HAS_VOLUME_DOWN) && @@ -5566,13 +5572,7 @@ uaudio_hid_rx_callback(struct usb_xfer *xfer, usb_error_t error) DPRINTF("Volume Down\n"); - v = mix_get_locked(m, SOUND_MIXER_PCM, &v_l, &v_r); - if (v == 0) { - v = ((v_l + v_r) / 2) - 5; - if (v < 0) - v = 0; - mix_set_locked(m, SOUND_MIXER_PCM, v, v); - } + mixer_hwvol_step_locked(m, -1, -1); } case USB_ST_SETUP: @@ -5641,10 +5641,20 @@ uaudio_hid_probe(struct uaudio_softc *sc, DPRINTFN(1, "Found Volume Down key\n"); } + if (hid_locate(d_ptr, d_len, + HID_USAGE2(HUP_CONSUMER, 0xE2 /* Mute */), + hid_input, 0, &sc->sc_hid.mute_loc, &flags, + &sc->sc_hid.mute_id)) { + if (flags & HIO_VARIABLE) + sc->sc_hid.flags |= UAUDIO_HID_HAS_MUTE; + DPRINTFN(1, "Found Mute key\n"); + } + free(d_ptr, M_TEMP); if (!(sc->sc_hid.flags & (UAUDIO_HID_HAS_VOLUME_UP | - UAUDIO_HID_HAS_VOLUME_DOWN))) { + UAUDIO_HID_HAS_VOLUME_DOWN | + UAUDIO_HID_HAS_MUTE))) { DPRINTFN(1, "Did not find any volume related keys\n"); return (-1); } From fe9b3289e67c4558d52b5035a0de1eae3bd96d10 Mon Sep 17 00:00:00 2001 From: David Chisnall Date: Thu, 7 Feb 2013 11:08:03 +0000 Subject: [PATCH 0015/1476] Fix a copy-and-paste error in libcxxrt. --- contrib/libcxxrt/exception.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/libcxxrt/exception.cc b/contrib/libcxxrt/exception.cc index 4ccf38eba7a..7f0d3e8b0f6 100644 --- a/contrib/libcxxrt/exception.cc +++ b/contrib/libcxxrt/exception.cc @@ -1387,7 +1387,7 @@ namespace std { if (thread_local_handlers) { return pathscale::set_unexpected(f); } - return ATOMIC_SWAP(&terminateHandler, f); + return ATOMIC_SWAP(&unexpectedHandler, f); } /** * Sets the function that is called to terminate the program. From c7f918d0681828afdbddfdcc354b6f3dfc2a7b68 Mon Sep 17 00:00:00 2001 From: David Chisnall Date: Thu, 7 Feb 2013 13:09:19 +0000 Subject: [PATCH 0016/1476] Import new libc++ to vendor branch. --- include/__config | 6 ++ include/algorithm | 4 +- include/array | 3 + include/atomic | 22 ++++-- include/cmath | 90 +++++++++++---------- include/functional | 2 +- include/future | 8 +- include/istream | 1 + include/iterator | 4 +- include/limits | 188 ++++++++++++++++++++++++++++++++++++++++++++ include/locale | 20 +++-- include/memory | 5 +- include/ostream | 13 +-- include/random | 122 ++++++++++++++++++++++++++++ include/regex | 21 +++++ include/string | 2 +- include/type_traits | 23 +++++- include/vector | 6 +- src/chrono.cpp | 4 + src/debug.cpp | 2 +- src/exception.cpp | 8 +- src/future.cpp | 2 +- src/hash.cpp | 20 +++-- src/locale.cpp | 150 ++++++++++++++++++++++------------- src/string.cpp | 136 +++++++++++++++++--------------- src/thread.cpp | 6 +- 26 files changed, 654 insertions(+), 214 deletions(-) diff --git a/include/__config b/include/__config index 203be7616cc..8617b866842 100644 --- a/include/__config +++ b/include/__config @@ -66,6 +66,12 @@ # endif #endif // _WIN32 +#ifdef __linux__ +# if defined(__GNUC__) && _GNUC_VER >= 403 +# define _LIBCP_HAS_IS_BASE_OF +# endif +#endif + #ifdef __sun__ # include # ifdef _LITTLE_ENDIAN diff --git a/include/algorithm b/include/algorithm index 0f6107bdde0..e24f9793c50 100644 --- a/include/algorithm +++ b/include/algorithm @@ -1528,10 +1528,10 @@ copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result) // copy_backward -template +template inline _LIBCPP_INLINE_VISIBILITY _OutputIterator -__copy_backward(_InputIterator __first, _InputIterator __last, _OutputIterator __result) +__copy_backward(_BidirectionalIterator __first, _BidirectionalIterator __last, _OutputIterator __result) { while (__first != __last) *--__result = *--__last; diff --git a/include/array b/include/array index 029bfd00a5c..f4a3020aeae 100644 --- a/include/array +++ b/include/array @@ -310,6 +310,7 @@ _LIBCPP_INLINE_VISIBILITY inline _Tp& get(array<_Tp, _Size>& __a) _NOEXCEPT { + static_assert(_Ip < _Size, "Index out of bounds in std::get<> (std::array)"); return __a[_Ip]; } @@ -318,6 +319,7 @@ _LIBCPP_INLINE_VISIBILITY inline const _Tp& get(const array<_Tp, _Size>& __a) _NOEXCEPT { + static_assert(_Ip < _Size, "Index out of bounds in std::get<> (const std::array)"); return __a[_Ip]; } @@ -328,6 +330,7 @@ _LIBCPP_INLINE_VISIBILITY inline _Tp&& get(array<_Tp, _Size>&& __a) _NOEXCEPT { + static_assert(_Ip < _Size, "Index out of bounds in std::get<> (std::array &&)"); return _VSTD::move(__a[_Ip]); } diff --git a/include/atomic b/include/atomic index 6dffdb21fde..db67e7625b8 100644 --- a/include/atomic +++ b/include/atomic @@ -33,6 +33,7 @@ template T kill_dependency(T y) noexcept; // lock-free property +#define ATOMIC_BOOL_LOCK_FREE unspecified #define ATOMIC_CHAR_LOCK_FREE unspecified #define ATOMIC_CHAR16_T_LOCK_FREE unspecified #define ATOMIC_CHAR32_T_LOCK_FREE unspecified @@ -41,6 +42,7 @@ template T kill_dependency(T y) noexcept; #define ATOMIC_INT_LOCK_FREE unspecified #define ATOMIC_LONG_LOCK_FREE unspecified #define ATOMIC_LLONG_LOCK_FREE unspecified +#define ATOMIC_POINTER_LOCK_FREE unspecified // flag type and operations @@ -472,6 +474,7 @@ template // Atomics for standard typedef types +typedef atomic atomic_bool; typedef atomic atomic_char; typedef atomic atomic_schar; typedef atomic atomic_uchar; @@ -1454,6 +1457,7 @@ atomic_signal_fence(memory_order __m) _NOEXCEPT // Atomics for standard typedef types +typedef atomic atomic_bool; typedef atomic atomic_char; typedef atomic atomic_schar; typedef atomic atomic_uchar; @@ -1499,14 +1503,16 @@ typedef atomic atomic_uintmax_t; // lock-free property -#define ATOMIC_CHAR_LOCK_FREE 0 -#define ATOMIC_CHAR16_T_LOCK_FREE 0 -#define ATOMIC_CHAR32_T_LOCK_FREE 0 -#define ATOMIC_WCHAR_T_LOCK_FREE 0 -#define ATOMIC_SHORT_LOCK_FREE 0 -#define ATOMIC_INT_LOCK_FREE 0 -#define ATOMIC_LONG_LOCK_FREE 0 -#define ATOMIC_LLONG_LOCK_FREE 0 +#define ATOMIC_BOOL_LOCK_FREE __GCC_ATOMIC_BOOL_LOCK_FREE +#define ATOMIC_CHAR_LOCK_FREE __GCC_ATOMIC_CHAR_LOCK_FREE +#define ATOMIC_CHAR16_T_LOCK_FREE __GCC_ATOMIC_CHAR16_T_LOCK_FREE +#define ATOMIC_CHAR32_T_LOCK_FREE __GCC_ATOMIC_CHAR32_T_LOCK_FREE +#define ATOMIC_WCHAR_T_LOCK_FREE __GCC_ATOMIC_WCHAR_T_LOCK_FREE +#define ATOMIC_SHORT_LOCK_FREE __GCC_ATOMIC_SHORT_LOCK_FREE +#define ATOMIC_INT_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE +#define ATOMIC_LONG_LOCK_FREE __GCC_ATOMIC_LONG_LOCK_FREE +#define ATOMIC_LLONG_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE +#define ATOMIC_POINTER_LOCK_FREE __GCC_ATOMIC_POINTER_LOCK_FREE #endif // !__has_feature(cxx_atomic) diff --git a/include/cmath b/include/cmath index d3fbfe6d23f..bd6034413ee 100644 --- a/include/cmath +++ b/include/cmath @@ -137,21 +137,21 @@ long double tanhl(long double x); // C99 -bool signbit(floating_point x); +bool signbit(arithmetic x); -int fpclassify(floating_point x); +int fpclassify(arithmetic x); -bool isfinite(floating_point x); -bool isinf(floating_point x); -bool isnan(floating_point x); -bool isnormal(floating_point x); +bool isfinite(arithmetic x); +bool isinf(arithmetic x); +bool isnan(arithmetic x); +bool isnormal(arithmetic x); -bool isgreater(floating_point x, floating_point y); -bool isgreaterequal(floating_point x, floating_point y); -bool isless(floating_point x, floating_point y); -bool islessequal(floating_point x, floating_point y); -bool islessgreater(floating_point x, floating_point y); -bool isunordered(floating_point x, floating_point y); +bool isgreater(arithmetic x, arithmetic y); +bool isgreaterequal(arithmetic x, arithmetic y); +bool isless(arithmetic x, arithmetic y); +bool islessequal(arithmetic x, arithmetic y); +bool islessgreater(arithmetic x, arithmetic y); +bool isunordered(arithmetic x, arithmetic y); floating_point acosh (arithmetic x); float acoshf(float x); @@ -325,10 +325,10 @@ __libcpp_signbit(_A1 __x) _NOEXCEPT template inline _LIBCPP_INLINE_VISIBILITY -typename std::enable_if::value, bool>::type +typename std::enable_if::value, bool>::type signbit(_A1 __x) _NOEXCEPT { - return __libcpp_signbit(__x); + return __libcpp_signbit((typename std::__promote<_A1>::type)__x); } #endif // signbit @@ -349,10 +349,10 @@ __libcpp_fpclassify(_A1 __x) _NOEXCEPT template inline _LIBCPP_INLINE_VISIBILITY -typename std::enable_if::value, int>::type +typename std::enable_if::value, int>::type fpclassify(_A1 __x) _NOEXCEPT { - return __libcpp_fpclassify(__x); + return __libcpp_fpclassify((typename std::__promote<_A1>::type)__x); } #endif // fpclassify @@ -373,10 +373,10 @@ __libcpp_isfinite(_A1 __x) _NOEXCEPT template inline _LIBCPP_INLINE_VISIBILITY -typename std::enable_if::value, bool>::type +typename std::enable_if::value, bool>::type isfinite(_A1 __x) _NOEXCEPT { - return __libcpp_isfinite(__x); + return __libcpp_isfinite((typename std::__promote<_A1>::type)__x); } #endif // isfinite @@ -397,10 +397,10 @@ __libcpp_isinf(_A1 __x) _NOEXCEPT template inline _LIBCPP_INLINE_VISIBILITY -typename std::enable_if::value, bool>::type +typename std::enable_if::value, bool>::type isinf(_A1 __x) _NOEXCEPT { - return __libcpp_isinf(__x); + return __libcpp_isinf((typename std::__promote<_A1>::type)__x); } #endif // isinf @@ -421,10 +421,10 @@ __libcpp_isnan(_A1 __x) _NOEXCEPT template inline _LIBCPP_INLINE_VISIBILITY -typename std::enable_if::value, bool>::type +typename std::enable_if::value, bool>::type isnan(_A1 __x) _NOEXCEPT { - return __libcpp_isnan(__x); + return __libcpp_isnan((typename std::__promote<_A1>::type)__x); } #endif // isnan @@ -445,10 +445,10 @@ __libcpp_isnormal(_A1 __x) _NOEXCEPT template inline _LIBCPP_INLINE_VISIBILITY -typename std::enable_if::value, bool>::type +typename std::enable_if::value, bool>::type isnormal(_A1 __x) _NOEXCEPT { - return __libcpp_isnormal(__x); + return __libcpp_isnormal((typename std::__promote<_A1>::type)__x); } #endif // isnormal @@ -471,13 +471,14 @@ template inline _LIBCPP_INLINE_VISIBILITY typename std::enable_if < - std::is_floating_point<_A1>::value && - std::is_floating_point<_A2>::value, + std::is_arithmetic<_A1>::value && + std::is_arithmetic<_A2>::value, bool >::type isgreater(_A1 __x, _A2 __y) _NOEXCEPT { - return __libcpp_isgreater(__x, __y); + typedef typename std::__promote<_A1, _A2>::type type; + return __libcpp_isgreater((type)__x, (type)__y); } #endif // isgreater @@ -500,13 +501,14 @@ template inline _LIBCPP_INLINE_VISIBILITY typename std::enable_if < - std::is_floating_point<_A1>::value && - std::is_floating_point<_A2>::value, + std::is_arithmetic<_A1>::value && + std::is_arithmetic<_A2>::value, bool >::type isgreaterequal(_A1 __x, _A2 __y) _NOEXCEPT { - return __libcpp_isgreaterequal(__x, __y); + typedef typename std::__promote<_A1, _A2>::type type; + return __libcpp_isgreaterequal((type)__x, (type)__y); } #endif // isgreaterequal @@ -529,13 +531,14 @@ template inline _LIBCPP_INLINE_VISIBILITY typename std::enable_if < - std::is_floating_point<_A1>::value && - std::is_floating_point<_A2>::value, + std::is_arithmetic<_A1>::value && + std::is_arithmetic<_A2>::value, bool >::type isless(_A1 __x, _A2 __y) _NOEXCEPT { - return __libcpp_isless(__x, __y); + typedef typename std::__promote<_A1, _A2>::type type; + return __libcpp_isless((type)__x, (type)__y); } #endif // isless @@ -558,13 +561,14 @@ template inline _LIBCPP_INLINE_VISIBILITY typename std::enable_if < - std::is_floating_point<_A1>::value && - std::is_floating_point<_A2>::value, + std::is_arithmetic<_A1>::value && + std::is_arithmetic<_A2>::value, bool >::type islessequal(_A1 __x, _A2 __y) _NOEXCEPT { - return __libcpp_islessequal(__x, __y); + typedef typename std::__promote<_A1, _A2>::type type; + return __libcpp_islessequal((type)__x, (type)__y); } #endif // islessequal @@ -587,13 +591,14 @@ template inline _LIBCPP_INLINE_VISIBILITY typename std::enable_if < - std::is_floating_point<_A1>::value && - std::is_floating_point<_A2>::value, + std::is_arithmetic<_A1>::value && + std::is_arithmetic<_A2>::value, bool >::type islessgreater(_A1 __x, _A2 __y) _NOEXCEPT { - return __libcpp_islessgreater(__x, __y); + typedef typename std::__promote<_A1, _A2>::type type; + return __libcpp_islessgreater((type)__x, (type)__y); } #endif // islessgreater @@ -616,13 +621,14 @@ template inline _LIBCPP_INLINE_VISIBILITY typename std::enable_if < - std::is_floating_point<_A1>::value && - std::is_floating_point<_A2>::value, + std::is_arithmetic<_A1>::value && + std::is_arithmetic<_A2>::value, bool >::type isunordered(_A1 __x, _A2 __y) _NOEXCEPT { - return __libcpp_isunordered(__x, __y); + typedef typename std::__promote<_A1, _A2>::type type; + return __libcpp_isunordered((type)__x, (type)__y); } #endif // isunordered diff --git a/include/functional b/include/functional index ec5c5e59333..3bee1ed1a0a 100644 --- a/include/functional +++ b/include/functional @@ -1088,7 +1088,7 @@ class _LIBCPP_VISIBLE function<_Rp(_ArgTypes...)> public __function::__maybe_derive_from_binary_function<_Rp(_ArgTypes...)> { typedef __function::__base<_Rp(_ArgTypes...)> __base; - aligned_storage<3*sizeof(void*)>::type __buf_; + typename aligned_storage<3*sizeof(void*)>::type __buf_; __base* __f_; template diff --git a/include/future b/include/future index cf552a9f303..fa605e7d07f 100644 --- a/include/future +++ b/include/future @@ -470,7 +470,11 @@ public: {return (__state_ & __constructed) || (__exception_ != nullptr);} _LIBCPP_INLINE_VISIBILITY - void __set_future_attached() {__state_ |= __future_attached;} + void __set_future_attached() + { + lock_guard __lk(__mut_); + __state_ |= __future_attached; + } _LIBCPP_INLINE_VISIBILITY bool __has_future_attached() const {return __state_ & __future_attached;} @@ -1753,7 +1757,7 @@ template class __packaged_task_function<_Rp(_ArgTypes...)> { typedef __packaged_task_base<_Rp(_ArgTypes...)> __base; - aligned_storage<3*sizeof(void*)>::type __buf_; + typename aligned_storage<3*sizeof(void*)>::type __buf_; __base* __f_; public: diff --git a/include/istream b/include/istream index dc1c52be639..3979e140706 100644 --- a/include/istream +++ b/include/istream @@ -1243,6 +1243,7 @@ template streamsize basic_istream<_CharT, _Traits>::readsome(char_type* __s, streamsize __n) { + __gc_ = 0; streamsize __c = this->rdbuf()->in_avail(); switch (__c) { diff --git a/include/iterator b/include/iterator index bc0ce4759ce..b23310b0940 100644 --- a/include/iterator +++ b/include/iterator @@ -822,9 +822,9 @@ private: public: _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR istreambuf_iterator() _NOEXCEPT : __sbuf_(0) {} _LIBCPP_INLINE_VISIBILITY istreambuf_iterator(istream_type& __s) _NOEXCEPT - : __sbuf_(__s.rdbuf()) {__test_for_eof();} + : __sbuf_(__s.rdbuf()) {} _LIBCPP_INLINE_VISIBILITY istreambuf_iterator(streambuf_type* __s) _NOEXCEPT - : __sbuf_(__s) {__test_for_eof();} + : __sbuf_(__s) {} _LIBCPP_INLINE_VISIBILITY istreambuf_iterator(const __proxy& __p) _NOEXCEPT : __sbuf_(__p.__sbuf_) {} diff --git a/include/limits b/include/limits index 68e63366abe..f089a794dc1 100644 --- a/include/limits +++ b/include/limits @@ -478,6 +478,53 @@ public: static _LIBCPP_CONSTEXPR const float_round_style round_style = __base::round_style; }; +template + _LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::is_specialized; +template + _LIBCPP_CONSTEXPR const int numeric_limits<_Tp>::digits; +template + _LIBCPP_CONSTEXPR const int numeric_limits<_Tp>::digits10; +template + _LIBCPP_CONSTEXPR const int numeric_limits<_Tp>::max_digits10; +template + _LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::is_signed; +template + _LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::is_integer; +template + _LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::is_exact; +template + _LIBCPP_CONSTEXPR const int numeric_limits<_Tp>::radix; +template + _LIBCPP_CONSTEXPR const int numeric_limits<_Tp>::min_exponent; +template + _LIBCPP_CONSTEXPR const int numeric_limits<_Tp>::min_exponent10; +template + _LIBCPP_CONSTEXPR const int numeric_limits<_Tp>::max_exponent; +template + _LIBCPP_CONSTEXPR const int numeric_limits<_Tp>::max_exponent10; +template + _LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::has_infinity; +template + _LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::has_quiet_NaN; +template + _LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::has_signaling_NaN; +template + _LIBCPP_CONSTEXPR const float_denorm_style numeric_limits<_Tp>::has_denorm; +template + _LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::has_denorm_loss; +template + _LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::is_iec559; +template + _LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::is_bounded; +template + _LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::is_modulo; +template + _LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::traps; +template + _LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::tinyness_before; +template + _LIBCPP_CONSTEXPR const float_round_style numeric_limits<_Tp>::round_style; + template class _LIBCPP_VISIBLE numeric_limits : private numeric_limits<_Tp> @@ -524,6 +571,53 @@ public: static _LIBCPP_CONSTEXPR const float_round_style round_style = __base::round_style; }; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::is_specialized; +template + _LIBCPP_CONSTEXPR const int numeric_limits::digits; +template + _LIBCPP_CONSTEXPR const int numeric_limits::digits10; +template + _LIBCPP_CONSTEXPR const int numeric_limits::max_digits10; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::is_signed; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::is_integer; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::is_exact; +template + _LIBCPP_CONSTEXPR const int numeric_limits::radix; +template + _LIBCPP_CONSTEXPR const int numeric_limits::min_exponent; +template + _LIBCPP_CONSTEXPR const int numeric_limits::min_exponent10; +template + _LIBCPP_CONSTEXPR const int numeric_limits::max_exponent; +template + _LIBCPP_CONSTEXPR const int numeric_limits::max_exponent10; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::has_infinity; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::has_quiet_NaN; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::has_signaling_NaN; +template + _LIBCPP_CONSTEXPR const float_denorm_style numeric_limits::has_denorm; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::has_denorm_loss; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::is_iec559; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::is_bounded; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::is_modulo; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::traps; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::tinyness_before; +template + _LIBCPP_CONSTEXPR const float_round_style numeric_limits::round_style; + template class _LIBCPP_VISIBLE numeric_limits : private numeric_limits<_Tp> @@ -570,6 +664,53 @@ public: static _LIBCPP_CONSTEXPR const float_round_style round_style = __base::round_style; }; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::is_specialized; +template + _LIBCPP_CONSTEXPR const int numeric_limits::digits; +template + _LIBCPP_CONSTEXPR const int numeric_limits::digits10; +template + _LIBCPP_CONSTEXPR const int numeric_limits::max_digits10; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::is_signed; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::is_integer; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::is_exact; +template + _LIBCPP_CONSTEXPR const int numeric_limits::radix; +template + _LIBCPP_CONSTEXPR const int numeric_limits::min_exponent; +template + _LIBCPP_CONSTEXPR const int numeric_limits::min_exponent10; +template + _LIBCPP_CONSTEXPR const int numeric_limits::max_exponent; +template + _LIBCPP_CONSTEXPR const int numeric_limits::max_exponent10; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::has_infinity; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::has_quiet_NaN; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::has_signaling_NaN; +template + _LIBCPP_CONSTEXPR const float_denorm_style numeric_limits::has_denorm; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::has_denorm_loss; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::is_iec559; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::is_bounded; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::is_modulo; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::traps; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::tinyness_before; +template + _LIBCPP_CONSTEXPR const float_round_style numeric_limits::round_style; + template class _LIBCPP_VISIBLE numeric_limits : private numeric_limits<_Tp> @@ -616,6 +757,53 @@ public: static _LIBCPP_CONSTEXPR const float_round_style round_style = __base::round_style; }; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::is_specialized; +template + _LIBCPP_CONSTEXPR const int numeric_limits::digits; +template + _LIBCPP_CONSTEXPR const int numeric_limits::digits10; +template + const int numeric_limits::max_digits10; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::is_signed; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::is_integer; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::is_exact; +template + _LIBCPP_CONSTEXPR const int numeric_limits::radix; +template + _LIBCPP_CONSTEXPR const int numeric_limits::min_exponent; +template + _LIBCPP_CONSTEXPR const int numeric_limits::min_exponent10; +template + _LIBCPP_CONSTEXPR const int numeric_limits::max_exponent; +template + _LIBCPP_CONSTEXPR const int numeric_limits::max_exponent10; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::has_infinity; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::has_quiet_NaN; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::has_signaling_NaN; +template + _LIBCPP_CONSTEXPR const float_denorm_style numeric_limits::has_denorm; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::has_denorm_loss; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::is_iec559; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::is_bounded; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::is_modulo; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::traps; +template + _LIBCPP_CONSTEXPR const bool numeric_limits::tinyness_before; +template + _LIBCPP_CONSTEXPR const float_round_style numeric_limits::round_style; + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_LIMITS diff --git a/include/locale b/include/locale index f04a36b4399..91893757c8f 100644 --- a/include/locale +++ b/include/locale @@ -354,7 +354,7 @@ size_t __mbsrtowcs_l(wchar_t *__dest, const char **__src, size_t __len, #endif } -_LIBCPP_ALWAYS_INLINE inline +inline int __sprintf_l(char *__s, locale_t __l, const char *__format, ...) { va_list __va; va_start(__va, __format); @@ -368,7 +368,7 @@ int __sprintf_l(char *__s, locale_t __l, const char *__format, ...) { return __res; } -_LIBCPP_ALWAYS_INLINE inline +inline int __snprintf_l(char *__s, size_t __n, locale_t __l, const char *__format, ...) { va_list __va; va_start(__va, __format); @@ -382,7 +382,7 @@ int __snprintf_l(char *__s, size_t __n, locale_t __l, const char *__format, ...) return __res; } -_LIBCPP_ALWAYS_INLINE inline +inline int __asprintf_l(char **__s, locale_t __l, const char *__format, ...) { va_list __va; va_start(__va, __format); @@ -396,7 +396,7 @@ int __asprintf_l(char **__s, locale_t __l, const char *__format, ...) { return __res; } -_LIBCPP_ALWAYS_INLINE inline +inline int __sscanf_l(const char *__s, locale_t __l, const char *__format, ...) { va_list __va; va_start(__va, __format); @@ -830,11 +830,11 @@ __num_get_signed_integral(const char* __a, const char* __a_end, { if (__a != __a_end) { - int __save_errno = errno; + typename remove_reference::type __save_errno = errno; errno = 0; char *__p2; long long __ll = strtoll_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE); - int __current_errno = errno; + typename remove_reference::type __current_errno = errno; if (__current_errno == 0) errno = __save_errno; if (__p2 != __a_end) @@ -870,11 +870,11 @@ __num_get_unsigned_integral(const char* __a, const char* __a_end, __err = ios_base::failbit; return 0; } - int __save_errno = errno; + typename remove_reference::type __save_errno = errno; errno = 0; char *__p2; unsigned long long __ll = strtoull_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE); - int __current_errno = errno; + typename remove_reference::type __current_errno = errno; if (__current_errno == 0) errno = __save_errno; if (__p2 != __a_end) @@ -2895,6 +2895,10 @@ template locale::id moneypunct<_CharT, _International>::id; +template +const bool +moneypunct<_CharT, _International>::intl; + _LIBCPP_EXTERN_TEMPLATE(class moneypunct) _LIBCPP_EXTERN_TEMPLATE(class moneypunct) _LIBCPP_EXTERN_TEMPLATE(class moneypunct) diff --git a/include/memory b/include/memory index 4c12ad93ab8..f80d699fc0d 100644 --- a/include/memory +++ b/include/memory @@ -1571,7 +1571,10 @@ struct _LIBCPP_VISIBLE allocator_traits __construct_backward(allocator_type& __a, _Ptr __begin1, _Ptr __end1, _Ptr& __end2) { while (__end1 != __begin1) - construct(__a, _VSTD::__to_raw_pointer(--__end2), _VSTD::move_if_noexcept(*--__end1)); + { + construct(__a, _VSTD::__to_raw_pointer(__end2-1), _VSTD::move_if_noexcept(*--__end1)); + --__end2; + } } template diff --git a/include/ostream b/include/ostream index 9d26a41e829..b3b6df573d0 100644 --- a/include/ostream +++ b/include/ostream @@ -1100,17 +1100,8 @@ basic_ostream<_CharT, _Traits>::write(const char_type* __s, streamsize __n) sentry __sen(*this); if (__sen && __n) { - typedef ostreambuf_iterator<_CharT, _Traits> _Op; - _Op __o(*this); - for (; __n; --__n, ++__o, ++__s) - { - *__o = *__s; - if (__o.failed()) - { - this->setstate(ios_base::badbit); - break; - } - } + if (this->rdbuf()->sputn(__s, __n) != __n) + this->setstate(ios_base::badbit); } #ifndef _LIBCPP_NO_EXCEPTIONS } diff --git a/include/random b/include/random index d838289551c..04d942bc876 100644 --- a/include/random +++ b/include/random @@ -1930,6 +1930,22 @@ private: linear_congruential_engine<_Up, _Ap, _Cp, _Np>& __x); }; +template + _LIBCPP_CONSTEXPR const typename linear_congruential_engine<_UIntType, __a, __c, __m>::result_type + linear_congruential_engine<_UIntType, __a, __c, __m>::multiplier; + +template + _LIBCPP_CONSTEXPR const typename linear_congruential_engine<_UIntType, __a, __c, __m>::result_type + linear_congruential_engine<_UIntType, __a, __c, __m>::increment; + +template + _LIBCPP_CONSTEXPR const typename linear_congruential_engine<_UIntType, __a, __c, __m>::result_type + linear_congruential_engine<_UIntType, __a, __c, __m>::modulus; + +template + _LIBCPP_CONSTEXPR const typename linear_congruential_engine<_UIntType, __a, __c, __m>::result_type + linear_congruential_engine<_UIntType, __a, __c, __m>::default_seed; + template template void @@ -2227,6 +2243,90 @@ private: __rshift(result_type) {return result_type(0);} }; +template + _LIBCPP_CONSTEXPR const size_t + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::word_size; + +template + _LIBCPP_CONSTEXPR const size_t + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::state_size; + +template + _LIBCPP_CONSTEXPR const size_t + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::shift_size; + +template + _LIBCPP_CONSTEXPR const size_t + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::mask_bits; + +template + _LIBCPP_CONSTEXPR const typename mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::result_type + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::xor_mask; + +template + _LIBCPP_CONSTEXPR const size_t + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::tempering_u; + +template + _LIBCPP_CONSTEXPR const typename mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::result_type + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::tempering_d; + +template + _LIBCPP_CONSTEXPR const size_t + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::tempering_s; + +template + _LIBCPP_CONSTEXPR const typename mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::result_type + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::tempering_b; + +template + _LIBCPP_CONSTEXPR const size_t + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::tempering_t; + +template + _LIBCPP_CONSTEXPR const typename mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::result_type + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::tempering_c; + +template + _LIBCPP_CONSTEXPR const size_t + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::tempering_l; + +template + _LIBCPP_CONSTEXPR const typename mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::result_type + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::initialization_multiplier; + +template + _LIBCPP_CONSTEXPR const typename mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::result_type + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::default_seed; + template @@ -2551,6 +2651,19 @@ private: void __seed(_Sseq& __q, integral_constant); }; +template + _LIBCPP_CONSTEXPR const size_t subtract_with_carry_engine<_UIntType, __w, __s, __r>::word_size; + +template + _LIBCPP_CONSTEXPR const size_t subtract_with_carry_engine<_UIntType, __w, __s, __r>::short_lag; + +template + _LIBCPP_CONSTEXPR const size_t subtract_with_carry_engine<_UIntType, __w, __s, __r>::long_lag; + +template + _LIBCPP_CONSTEXPR const typename subtract_with_carry_engine<_UIntType, __w, __s, __r>::result_type + subtract_with_carry_engine<_UIntType, __w, __s, __r>::default_seed; + template void subtract_with_carry_engine<_UIntType, __w, __s, __r>::seed(result_type __sd, @@ -2822,6 +2935,12 @@ public: discard_block_engine<_Eng, _Pp, _Rp>& __x); }; +template + _LIBCPP_CONSTEXPR const size_t discard_block_engine<_Engine, __p, __r>::block_size; + +template + _LIBCPP_CONSTEXPR const size_t discard_block_engine<_Engine, __p, __r>::used_block; + template typename discard_block_engine<_Engine, __p, __r>::result_type discard_block_engine<_Engine, __p, __r>::operator()() @@ -3314,6 +3433,9 @@ private: } }; +template + _LIBCPP_CONSTEXPR const size_t shuffle_order_engine<_Engine, __k>::table_size; + template bool operator==( diff --git a/include/regex b/include/regex index 7505f2ea329..982500f35ff 100644 --- a/include/regex +++ b/include/regex @@ -2842,6 +2842,27 @@ private: template friend class __lookahead; }; +template + const regex_constants::syntax_option_type basic_regex<_CharT, _Traits>::icase; +template + const regex_constants::syntax_option_type basic_regex<_CharT, _Traits>::nosubs; +template + const regex_constants::syntax_option_type basic_regex<_CharT, _Traits>::optimize; +template + const regex_constants::syntax_option_type basic_regex<_CharT, _Traits>::collate; +template + const regex_constants::syntax_option_type basic_regex<_CharT, _Traits>::ECMAScript; +template + const regex_constants::syntax_option_type basic_regex<_CharT, _Traits>::basic; +template + const regex_constants::syntax_option_type basic_regex<_CharT, _Traits>::extended; +template + const regex_constants::syntax_option_type basic_regex<_CharT, _Traits>::awk; +template + const regex_constants::syntax_option_type basic_regex<_CharT, _Traits>::grep; +template + const regex_constants::syntax_option_type basic_regex<_CharT, _Traits>::egrep; + template void basic_regex<_CharT, _Traits>::swap(basic_regex& __r) diff --git a/include/string b/include/string index 5bf42f023a4..1a70467940c 100644 --- a/include/string +++ b/include/string @@ -3374,7 +3374,7 @@ basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(value_type __c, { const_pointer __p = data(); const_pointer __pe = __p + __sz; - for (const_pointer __ps = __p + __pos; __p != __pe; ++__ps) + for (const_pointer __ps = __p + __pos; __ps != __pe; ++__ps) if (!traits_type::eq(*__ps, __c)) return static_cast(__ps - __p); } diff --git a/include/type_traits b/include/type_traits index 26c37dfa0c7..8f1c6024c71 100644 --- a/include/type_traits +++ b/include/type_traits @@ -617,7 +617,28 @@ struct _LIBCPP_VISIBLE is_base_of #else // __has_feature(is_base_of) -#error is_base_of not implemented. +namespace __is_base_of_imp +{ +template +struct _Dst +{ + _Dst(const volatile _Tp &); +}; +template +struct _Src +{ + operator const volatile _Tp &(); + template operator const _Dst<_Up> &(); +}; +template struct __one { typedef char type; }; +template typename __one(declval<_Src<_Dp> >()))>::type __test(int); +template __two __test(...); +} + +template +struct _LIBCPP_VISIBLE is_base_of + : public integral_constant::value && + sizeof(__is_base_of_imp::__test<_Bp, _Dp>(0)) == 2> {}; #endif // __has_feature(is_base_of) diff --git a/include/vector b/include/vector index 0c280682833..876b7e5676b 100644 --- a/include/vector +++ b/include/vector @@ -1458,7 +1458,8 @@ vector<_Tp, _Allocator>::__push_back_slow_path(_Up& __x) allocator_type& __a = this->__alloc(); __split_buffer __v(__recommend(size() + 1), size(), __a); // __v.push_back(_VSTD::forward<_Up>(__x)); - __alloc_traits::construct(__a, _VSTD::__to_raw_pointer(__v.__end_++), _VSTD::forward<_Up>(__x)); + __alloc_traits::construct(__a, _VSTD::__to_raw_pointer(__v.__end_), _VSTD::forward<_Up>(__x)); + __v.__end_++; __swap_out_circular_buffer(__v); } @@ -1505,7 +1506,8 @@ vector<_Tp, _Allocator>::__emplace_back_slow_path(_Args&&... __args) allocator_type& __a = this->__alloc(); __split_buffer __v(__recommend(size() + 1), size(), __a); // __v.emplace_back(_VSTD::forward<_Args>(__args)...); - __alloc_traits::construct(__a, _VSTD::__to_raw_pointer(__v.__end_++), _VSTD::forward<_Args>(__args)...); + __alloc_traits::construct(__a, _VSTD::__to_raw_pointer(__v.__end_), _VSTD::forward<_Args>(__args)...); + __v.__end_++; __swap_out_circular_buffer(__v); } diff --git a/src/chrono.cpp b/src/chrono.cpp index 73c83ee084e..1ce2e2807a3 100644 --- a/src/chrono.cpp +++ b/src/chrono.cpp @@ -24,6 +24,8 @@ namespace chrono // system_clock +const bool system_clock::is_steady; + system_clock::time_point system_clock::now() _NOEXCEPT { @@ -46,6 +48,8 @@ system_clock::from_time_t(time_t t) _NOEXCEPT // steady_clock +const bool steady_clock::is_steady; + #if __APPLE__ // mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of // nanoseconds since the computer booted up. MachInfo.numer and MachInfo.denom diff --git a/src/debug.cpp b/src/debug.cpp index b8af4dde774..f3a0262d1d5 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -23,7 +23,7 @@ __get_db() { static __libcpp_db db; return &db; -}; +} _LIBCPP_VISIBLE const __libcpp_db* diff --git a/src/exception.cpp b/src/exception.cpp index 0dbb6604a56..0cd182b716c 100644 --- a/src/exception.cpp +++ b/src/exception.cpp @@ -33,7 +33,7 @@ #if defined(LIBCXXRT) || defined(_LIBCPPABI_VERSION) #define HAVE_DEPENDENT_EH_ABI 1 #endif -#else // __has_include() +#elif !defined(__GLIBCXX__) // __has_include() static std::terminate_handler __terminate_handler; static std::unexpected_handler __unexpected_handler; #endif // __has_include() @@ -41,7 +41,7 @@ namespace std { -#if !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION) +#if !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__) // libcxxrt provides implementations of these functions itself. unexpected_handler @@ -99,7 +99,7 @@ terminate() _NOEXCEPT } #endif // !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION) -#ifndef LIBCXXRT +#if !defined(LIBCXXRT) && !defined(__GLIBCXX__) bool uncaught_exception() _NOEXCEPT { #if __APPLE__ || defined(_LIBCPPABI_VERSION) @@ -124,7 +124,7 @@ const char* exception::what() const _NOEXCEPT #endif // _LIBCPPABI_VERSION #endif //LIBCXXRT -#ifndef _LIBCPPABI_VERSION +#if !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__) bad_exception::~bad_exception() _NOEXCEPT { diff --git a/src/future.cpp b/src/future.cpp index feb37e42db4..7d9a5b5da69 100644 --- a/src/future.cpp +++ b/src/future.cpp @@ -78,8 +78,8 @@ __assoc_sub_state::set_value() throw future_error(make_error_code(future_errc::promise_already_satisfied)); #endif __state_ |= __constructed | ready; - __lk.unlock(); __cv_.notify_all(); + __lk.unlock(); } void diff --git a/src/hash.cpp b/src/hash.cpp index 6f30d5a6058..a013500218e 100644 --- a/src/hash.cpp +++ b/src/hash.cpp @@ -10,6 +10,9 @@ #include "__hash_table" #include "algorithm" #include "stdexcept" +#include "type_traits" + +#pragma clang diagnostic ignored "-Wtautological-constant-out-of-range-compare" _LIBCPP_BEGIN_NAMESPACE_STD @@ -144,21 +147,23 @@ const unsigned indices[] = // are fewer potential primes to search, and fewer potential primes to divide // against. +template inline _LIBCPP_INLINE_VISIBILITY -void -__check_for_overflow(size_t N, integral_constant) +typename enable_if<_Sz == 4, void>::type +__check_for_overflow(size_t N) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_NO_EXCEPTIONS if (N > 0xFFFFFFFB) throw overflow_error("__next_prime overflow"); #endif } +template inline _LIBCPP_INLINE_VISIBILITY -void -__check_for_overflow(size_t N, integral_constant) +typename enable_if<_Sz == 8, void>::type +__check_for_overflow(size_t N) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_NO_EXCEPTIONS if (N > 0xFFFFFFFFFFFFFFC5ull) throw overflow_error("__next_prime overflow"); #endif @@ -174,8 +179,7 @@ __next_prime(size_t n) return *std::lower_bound(small_primes, small_primes + N, n); // Else n > largest small_primes // Check for overflow - __check_for_overflow(n, integral_constant()); + __check_for_overflow(n); // Start searching list of potential primes: L * k0 + indices[in] const size_t M = sizeof(indices) / sizeof(indices[0]); // Select first potential prime >= n diff --git a/src/locale.cpp b/src/locale.cpp index 542c0d7a20f..53a8a4cc1f0 100644 --- a/src/locale.cpp +++ b/src/locale.cpp @@ -81,8 +81,35 @@ make(A0 a0, A1 a1, A2 a2) return *(T*)&buf; } +template +inline +_LIBCPP_CONSTEXPR +size_t +countof(const T (&)[N]) +{ + return N; } +template +inline +_LIBCPP_CONSTEXPR +size_t +countof(const T * const begin, const T * const end) +{ + return static_cast(end - begin); +} + +} + +const locale::category locale::none; +const locale::category locale::collate; +const locale::category locale::ctype; +const locale::category locale::monetary; +const locale::category locale::numeric; +const locale::category locale::time; +const locale::category locale::messages; +const locale::category locale::all; + #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wpadded" @@ -197,6 +224,11 @@ locale::__imp::__imp(const string& name, size_t refs) #endif // _LIBCPP_NO_EXCEPTIONS } +// NOTE avoid the `base class should be explicitly initialized in the +// copy constructor` warning emitted by GCC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wextra" + locale::__imp::__imp(const __imp& other) : facets_(max(N, other.facets_.size())), name_(other.name_) @@ -207,6 +239,8 @@ locale::__imp::__imp(const __imp& other) facets_[i]->__add_shared(); } +#pragma GCC diagnostic pop + locale::__imp::__imp(const __imp& other, const string& name, locale::category c) : facets_(N), name_("*") @@ -691,6 +725,19 @@ collate_byname::do_transform(const char_type* lo, const char_type* hi) // template <> class ctype; +const ctype_base::mask ctype_base::space; +const ctype_base::mask ctype_base::print; +const ctype_base::mask ctype_base::cntrl; +const ctype_base::mask ctype_base::upper; +const ctype_base::mask ctype_base::lower; +const ctype_base::mask ctype_base::alpha; +const ctype_base::mask ctype_base::digit; +const ctype_base::mask ctype_base::punct; +const ctype_base::mask ctype_base::xdigit; +const ctype_base::mask ctype_base::blank; +const ctype_base::mask ctype_base::alnum; +const ctype_base::mask ctype_base::graph; + locale::id ctype::id; ctype::~ctype() @@ -843,7 +890,7 @@ ctype::do_toupper(char_type c) const return isascii(c) ? static_cast(_DefaultRuneLocale.__mapupper[static_cast(c)]) : c; #elif defined(__GLIBC__) - return isascii(c) ? __classic_upper_table()[c] : c; + return isascii(c) ? __classic_upper_table()[static_cast(c)] : c; #else return (isascii(c) && islower_l(c, __cloc())) ? c-'a'+'A' : c; #endif @@ -857,7 +904,7 @@ ctype::do_toupper(char_type* low, const char_type* high) const *low = isascii(*low) ? static_cast(_DefaultRuneLocale.__mapupper[static_cast(*low)]) : *low; #elif defined(__GLIBC__) - *low = isascii(*low) ? __classic_upper_table()[*low] : *low; + *low = isascii(*low) ? __classic_upper_table()[static_cast(*low)] : *low; #else *low = (isascii(*low) && islower_l(*low, __cloc())) ? *low-'a'+'A' : *low; #endif @@ -871,7 +918,7 @@ ctype::do_tolower(char_type c) const return isascii(c) ? static_cast(_DefaultRuneLocale.__maplower[static_cast(c)]) : c; #elif defined(__GLIBC__) - return isascii(c) ? __classic_lower_table()[c] : c; + return isascii(c) ? __classic_lower_table()[static_cast(c)] : c; #else return (isascii(c) && isupper_l(c, __cloc())) ? c-'A'+'a' : c; #endif @@ -884,7 +931,7 @@ ctype::do_tolower(char_type* low, const char_type* high) const #ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE *low = isascii(*low) ? static_cast(_DefaultRuneLocale.__maplower[static_cast(*low)]) : *low; #elif defined(__GLIBC__) - *low = isascii(*low) ? __classic_lower_table()[*low] : *low; + *low = isascii(*low) ? __classic_lower_table()[static_cast(*low)] : *low; #else *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-'A'+'a' : *low; #endif @@ -1207,7 +1254,7 @@ ctype_byname::do_narrow(char_type c, char dfault) const #else int r = __wctob_l(c, __l); #endif - return r != WEOF ? static_cast(r) : dfault; + return r != static_cast(WEOF) ? static_cast(r) : dfault; } const wchar_t* @@ -1220,7 +1267,7 @@ ctype_byname::do_narrow(const char_type* low, const char_type* high, ch #else int r = __wctob_l(*low, __l); #endif - *dest = r != WEOF ? static_cast(r) : dfault; + *dest = r != static_cast(WEOF) ? static_cast(r) : dfault; } return low; } @@ -2619,7 +2666,6 @@ utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end, codecvt_mode mode = codecvt_mode(0)) { const uint8_t* frm_nxt = frm; - frm_nxt = frm; if (mode & consume_header) { if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF) @@ -2752,7 +2798,6 @@ utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end, codecvt_mode mode = codecvt_mode(0)) { const uint8_t* frm_nxt = frm; - frm_nxt = frm; if (mode & consume_header) { if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE) @@ -2847,7 +2892,6 @@ utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end, codecvt_mode mode = codecvt_mode(0)) { const uint8_t* frm_nxt = frm; - frm_nxt = frm; if (mode & consume_header) { if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF) @@ -4559,6 +4603,7 @@ __time_get::~__time_get() } #pragma clang diagnostic ignored "-Wmissing-field-initializers" +#pragma GCC diagnostic ignored "-Wmissing-field-initializers" template <> string @@ -4578,7 +4623,7 @@ __time_get_storage::__analyze(char fmt, const ctype& ct) char f[3] = {0}; f[0] = '%'; f[1] = fmt; - size_t n = strftime_l(buf, 100, f, &t, __loc_); + size_t n = strftime_l(buf, countof(buf), f, &t, __loc_); char* bb = buf; char* be = buf + n; string result; @@ -4724,15 +4769,15 @@ __time_get_storage::__analyze(char fmt, const ctype& ct) char f[3] = {0}; f[0] = '%'; f[1] = fmt; - strftime_l(buf, 100, f, &t, __loc_); + strftime_l(buf, countof(buf), f, &t, __loc_); wchar_t wbuf[100]; wchar_t* wbb = wbuf; mbstate_t mb = {0}; const char* bb = buf; #ifdef _LIBCPP_LOCALE__L_EXTENSIONS - size_t j = mbsrtowcs_l( wbb, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_); + size_t j = mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_); #else - size_t j = __mbsrtowcs_l( wbb, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_); + size_t j = __mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_); #endif if (j == size_t(-1)) __throw_runtime_error("locale not supported"); @@ -4870,26 +4915,26 @@ __time_get_storage::init(const ctype& ct) for (int i = 0; i < 7; ++i) { t.tm_wday = i; - strftime_l(buf, 100, "%A", &t, __loc_); + strftime_l(buf, countof(buf), "%A", &t, __loc_); __weeks_[i] = buf; - strftime_l(buf, 100, "%a", &t, __loc_); + strftime_l(buf, countof(buf), "%a", &t, __loc_); __weeks_[i+7] = buf; } // __months_ for (int i = 0; i < 12; ++i) { t.tm_mon = i; - strftime_l(buf, 100, "%B", &t, __loc_); + strftime_l(buf, countof(buf), "%B", &t, __loc_); __months_[i] = buf; - strftime_l(buf, 100, "%b", &t, __loc_); + strftime_l(buf, countof(buf), "%b", &t, __loc_); __months_[i+12] = buf; } // __am_pm_ t.tm_hour = 1; - strftime_l(buf, 100, "%p", &t, __loc_); + strftime_l(buf, countof(buf), "%p", &t, __loc_); __am_pm_[0] = buf; t.tm_hour = 13; - strftime_l(buf, 100, "%p", &t, __loc_); + strftime_l(buf, countof(buf), "%p", &t, __loc_); __am_pm_[1] = buf; __c_ = __analyze('c', ct); __r_ = __analyze('r', ct); @@ -4903,7 +4948,6 @@ __time_get_storage::init(const ctype& ct) { tm t = {0}; char buf[100]; - size_t be; wchar_t wbuf[100]; wchar_t* wbe; mbstate_t mb = {0}; @@ -4911,25 +4955,25 @@ __time_get_storage::init(const ctype& ct) for (int i = 0; i < 7; ++i) { t.tm_wday = i; - be = strftime_l(buf, 100, "%A", &t, __loc_); + strftime_l(buf, countof(buf), "%A", &t, __loc_); mb = mbstate_t(); const char* bb = buf; #ifdef _LIBCPP_LOCALE__L_EXTENSIONS - size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_); + size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); #else - size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_); + size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); #endif if (j == size_t(-1)) __throw_runtime_error("locale not supported"); wbe = wbuf + j; __weeks_[i].assign(wbuf, wbe); - be = strftime_l(buf, 100, "%a", &t, __loc_); + strftime_l(buf, countof(buf), "%a", &t, __loc_); mb = mbstate_t(); bb = buf; #ifdef _LIBCPP_LOCALE__L_EXTENSIONS - j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_); + j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); #else - j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_); + j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); #endif if (j == size_t(-1)) __throw_runtime_error("locale not supported"); @@ -4940,25 +4984,25 @@ __time_get_storage::init(const ctype& ct) for (int i = 0; i < 12; ++i) { t.tm_mon = i; - be = strftime_l(buf, 100, "%B", &t, __loc_); + strftime_l(buf, countof(buf), "%B", &t, __loc_); mb = mbstate_t(); const char* bb = buf; #ifdef _LIBCPP_LOCALE__L_EXTENSIONS - size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_); + size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); #else - size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_); + size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); #endif if (j == size_t(-1)) __throw_runtime_error("locale not supported"); wbe = wbuf + j; __months_[i].assign(wbuf, wbe); - be = strftime_l(buf, 100, "%b", &t, __loc_); + strftime_l(buf, countof(buf), "%b", &t, __loc_); mb = mbstate_t(); bb = buf; #ifdef _LIBCPP_LOCALE__L_EXTENSIONS - j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_); + j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); #else - j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_); + j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); #endif if (j == size_t(-1)) __throw_runtime_error("locale not supported"); @@ -4967,26 +5011,26 @@ __time_get_storage::init(const ctype& ct) } // __am_pm_ t.tm_hour = 1; - be = strftime_l(buf, 100, "%p", &t, __loc_); + strftime_l(buf, countof(buf), "%p", &t, __loc_); mb = mbstate_t(); const char* bb = buf; #ifdef _LIBCPP_LOCALE__L_EXTENSIONS - size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_); + size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); #else - size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_); + size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); #endif if (j == size_t(-1)) __throw_runtime_error("locale not supported"); wbe = wbuf + j; __am_pm_[0].assign(wbuf, wbe); t.tm_hour = 13; - be = strftime_l(buf, 100, "%p", &t, __loc_); + strftime_l(buf, countof(buf), "%p", &t, __loc_); mb = mbstate_t(); bb = buf; #ifdef _LIBCPP_LOCALE__L_EXTENSIONS - j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_); + j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); #else - j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_); + j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); #endif if (j == size_t(-1)) __throw_runtime_error("locale not supported"); @@ -5249,7 +5293,7 @@ __time_put::__do_put(char* __nb, char*& __ne, const tm* __tm, char fmt[] = {'%', __fmt, __mod, 0}; if (__mod != 0) swap(fmt[1], fmt[2]); - size_t n = strftime_l(__nb, static_cast(__ne-__nb), fmt, __tm, __loc_); + size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_); __ne = __nb + n; } @@ -5263,9 +5307,9 @@ __time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm, mbstate_t mb = {0}; const char* __nb = __nar; #ifdef _LIBCPP_LOCALE__L_EXTENSIONS - size_t j = mbsrtowcs_l(__wb, &__nb, 100, &mb, __loc_); + size_t j = mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_); #else - size_t j = __mbsrtowcs_l(__wb, &__nb, 100, &mb, __loc_); + size_t j = __mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_); #endif if (j == size_t(-1)) __throw_runtime_error("locale not supported"); @@ -5788,9 +5832,9 @@ moneypunct_byname::init(const char* nm) mbstate_t mb = {0}; const char* bb = lc->currency_symbol; #ifdef _LIBCPP_LOCALE__L_EXTENSIONS - size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get()); + size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); #else - size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get()); + size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); #endif if (j == size_t(-1)) __throw_runtime_error("locale not supported"); @@ -5807,9 +5851,9 @@ moneypunct_byname::init(const char* nm) mb = mbstate_t(); bb = lc->positive_sign; #ifdef _LIBCPP_LOCALE__L_EXTENSIONS - j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get()); + j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); #else - j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get()); + j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); #endif if (j == size_t(-1)) __throw_runtime_error("locale not supported"); @@ -5823,9 +5867,9 @@ moneypunct_byname::init(const char* nm) mb = mbstate_t(); bb = lc->negative_sign; #ifdef _LIBCPP_LOCALE__L_EXTENSIONS - j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get()); + j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); #else - j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get()); + j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); #endif if (j == size_t(-1)) __throw_runtime_error("locale not supported"); @@ -5871,9 +5915,9 @@ moneypunct_byname::init(const char* nm) mbstate_t mb = {0}; const char* bb = lc->int_curr_symbol; #ifdef _LIBCPP_LOCALE__L_EXTENSIONS - size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get()); + size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); #else - size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get()); + size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); #endif if (j == size_t(-1)) __throw_runtime_error("locale not supported"); @@ -5894,9 +5938,9 @@ moneypunct_byname::init(const char* nm) mb = mbstate_t(); bb = lc->positive_sign; #ifdef _LIBCPP_LOCALE__L_EXTENSIONS - j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get()); + j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); #else - j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get()); + j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); #endif if (j == size_t(-1)) __throw_runtime_error("locale not supported"); @@ -5914,9 +5958,9 @@ moneypunct_byname::init(const char* nm) mb = mbstate_t(); bb = lc->negative_sign; #ifdef _LIBCPP_LOCALE__L_EXTENSIONS - j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get()); + j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); #else - j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get()); + j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); #endif if (j == size_t(-1)) __throw_runtime_error("locale not supported"); diff --git a/src/string.cpp b/src/string.cpp index 750ba284e36..40723e74a15 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -31,17 +31,17 @@ stoi(const string& str, size_t* idx, int base) { char* ptr; const char* const p = str.c_str(); + typename remove_reference::type errno_save = errno; + errno = 0; long r = strtol(p, &ptr, base); - if (r < numeric_limits::min() || numeric_limits::max() < r) - ptr = const_cast(p); - if (ptr == p) - { + swap(errno, errno_save); #ifndef _LIBCPP_NO_EXCEPTIONS - if (r == 0) - throw invalid_argument("stoi: no conversion"); + if (errno_save == ERANGE || r < numeric_limits::min() || + numeric_limits::max() < r) throw out_of_range("stoi: out of range"); + if (ptr == p) + throw invalid_argument("stoi: no conversion"); #endif // _LIBCPP_NO_EXCEPTIONS - } if (idx) *idx = static_cast(ptr - p); return static_cast(r); @@ -52,17 +52,17 @@ stoi(const wstring& str, size_t* idx, int base) { wchar_t* ptr; const wchar_t* const p = str.c_str(); + typename remove_reference::type errno_save = errno; + errno = 0; long r = wcstol(p, &ptr, base); - if (r < numeric_limits::min() || numeric_limits::max() < r) - ptr = const_cast(p); - if (ptr == p) - { + swap(errno, errno_save); #ifndef _LIBCPP_NO_EXCEPTIONS - if (r == 0) - throw invalid_argument("stoi: no conversion"); + if (errno_save == ERANGE || r < numeric_limits::min() || + numeric_limits::max() < r) throw out_of_range("stoi: out of range"); + if (ptr == p) + throw invalid_argument("stoi: no conversion"); #endif // _LIBCPP_NO_EXCEPTIONS - } if (idx) *idx = static_cast(ptr - p); return static_cast(r); @@ -73,15 +73,16 @@ stol(const string& str, size_t* idx, int base) { char* ptr; const char* const p = str.c_str(); + typename remove_reference::type errno_save = errno; + errno = 0; long r = strtol(p, &ptr, base); - if (ptr == p) - { + swap(errno, errno_save); #ifndef _LIBCPP_NO_EXCEPTIONS - if (r == 0) - throw invalid_argument("stol: no conversion"); + if (errno_save == ERANGE) throw out_of_range("stol: out of range"); + if (ptr == p) + throw invalid_argument("stol: no conversion"); #endif // _LIBCPP_NO_EXCEPTIONS - } if (idx) *idx = static_cast(ptr - p); return r; @@ -92,15 +93,16 @@ stol(const wstring& str, size_t* idx, int base) { wchar_t* ptr; const wchar_t* const p = str.c_str(); + typename remove_reference::type errno_save = errno; + errno = 0; long r = wcstol(p, &ptr, base); - if (ptr == p) - { + swap(errno, errno_save); #ifndef _LIBCPP_NO_EXCEPTIONS - if (r == 0) - throw invalid_argument("stol: no conversion"); + if (errno_save == ERANGE) throw out_of_range("stol: out of range"); + if (ptr == p) + throw invalid_argument("stol: no conversion"); #endif // _LIBCPP_NO_EXCEPTIONS - } if (idx) *idx = static_cast(ptr - p); return r; @@ -111,15 +113,16 @@ stoul(const string& str, size_t* idx, int base) { char* ptr; const char* const p = str.c_str(); + typename remove_reference::type errno_save = errno; + errno = 0; unsigned long r = strtoul(p, &ptr, base); - if (ptr == p) - { + swap(errno, errno_save); #ifndef _LIBCPP_NO_EXCEPTIONS - if (r == 0) - throw invalid_argument("stoul: no conversion"); + if (errno_save == ERANGE) throw out_of_range("stoul: out of range"); + if (ptr == p) + throw invalid_argument("stoul: no conversion"); #endif // _LIBCPP_NO_EXCEPTIONS - } if (idx) *idx = static_cast(ptr - p); return r; @@ -130,15 +133,16 @@ stoul(const wstring& str, size_t* idx, int base) { wchar_t* ptr; const wchar_t* const p = str.c_str(); + typename remove_reference::type errno_save = errno; + errno = 0; unsigned long r = wcstoul(p, &ptr, base); - if (ptr == p) - { + swap(errno, errno_save); #ifndef _LIBCPP_NO_EXCEPTIONS - if (r == 0) - throw invalid_argument("stoul: no conversion"); + if (errno_save == ERANGE) throw out_of_range("stoul: out of range"); + if (ptr == p) + throw invalid_argument("stoul: no conversion"); #endif // _LIBCPP_NO_EXCEPTIONS - } if (idx) *idx = static_cast(ptr - p); return r; @@ -149,15 +153,16 @@ stoll(const string& str, size_t* idx, int base) { char* ptr; const char* const p = str.c_str(); + typename remove_reference::type errno_save = errno; + errno = 0; long long r = strtoll(p, &ptr, base); - if (ptr == p) - { + swap(errno, errno_save); #ifndef _LIBCPP_NO_EXCEPTIONS - if (r == 0) - throw invalid_argument("stoll: no conversion"); + if (errno_save == ERANGE) throw out_of_range("stoll: out of range"); + if (ptr == p) + throw invalid_argument("stoll: no conversion"); #endif // _LIBCPP_NO_EXCEPTIONS - } if (idx) *idx = static_cast(ptr - p); return r; @@ -168,15 +173,16 @@ stoll(const wstring& str, size_t* idx, int base) { wchar_t* ptr; const wchar_t* const p = str.c_str(); + typename remove_reference::type errno_save = errno; + errno = 0; long long r = wcstoll(p, &ptr, base); - if (ptr == p) - { + swap(errno, errno_save); #ifndef _LIBCPP_NO_EXCEPTIONS - if (r == 0) - throw invalid_argument("stoll: no conversion"); + if (errno_save == ERANGE) throw out_of_range("stoll: out of range"); + if (ptr == p) + throw invalid_argument("stoll: no conversion"); #endif // _LIBCPP_NO_EXCEPTIONS - } if (idx) *idx = static_cast(ptr - p); return r; @@ -187,15 +193,16 @@ stoull(const string& str, size_t* idx, int base) { char* ptr; const char* const p = str.c_str(); + typename remove_reference::type errno_save = errno; + errno = 0; unsigned long long r = strtoull(p, &ptr, base); - if (ptr == p) - { + swap(errno, errno_save); #ifndef _LIBCPP_NO_EXCEPTIONS - if (r == 0) - throw invalid_argument("stoull: no conversion"); + if (errno_save == ERANGE) throw out_of_range("stoull: out of range"); + if (ptr == p) + throw invalid_argument("stoull: no conversion"); #endif // _LIBCPP_NO_EXCEPTIONS - } if (idx) *idx = static_cast(ptr - p); return r; @@ -206,15 +213,16 @@ stoull(const wstring& str, size_t* idx, int base) { wchar_t* ptr; const wchar_t* const p = str.c_str(); + typename remove_reference::type errno_save = errno; + errno = 0; unsigned long long r = wcstoull(p, &ptr, base); - if (ptr == p) - { + swap(errno, errno_save); #ifndef _LIBCPP_NO_EXCEPTIONS - if (r == 0) - throw invalid_argument("stoull: no conversion"); + if (errno_save == ERANGE) throw out_of_range("stoull: out of range"); + if (ptr == p) + throw invalid_argument("stoull: no conversion"); #endif // _LIBCPP_NO_EXCEPTIONS - } if (idx) *idx = static_cast(ptr - p); return r; @@ -225,9 +233,9 @@ stof(const string& str, size_t* idx) { char* ptr; const char* const p = str.c_str(); - int errno_save = errno; + typename remove_reference::type errno_save = errno; errno = 0; - double r = strtod(p, &ptr); + float r = strtof(p, &ptr); swap(errno, errno_save); #ifndef _LIBCPP_NO_EXCEPTIONS if (errno_save == ERANGE) @@ -237,7 +245,7 @@ stof(const string& str, size_t* idx) #endif // _LIBCPP_NO_EXCEPTIONS if (idx) *idx = static_cast(ptr - p); - return static_cast(r); + return r; } float @@ -245,9 +253,9 @@ stof(const wstring& str, size_t* idx) { wchar_t* ptr; const wchar_t* const p = str.c_str(); - int errno_save = errno; + typename remove_reference::type errno_save = errno; errno = 0; - double r = wcstod(p, &ptr); + float r = wcstof(p, &ptr); swap(errno, errno_save); #ifndef _LIBCPP_NO_EXCEPTIONS if (errno_save == ERANGE) @@ -257,7 +265,7 @@ stof(const wstring& str, size_t* idx) #endif // _LIBCPP_NO_EXCEPTIONS if (idx) *idx = static_cast(ptr - p); - return static_cast(r); + return r; } double @@ -265,7 +273,7 @@ stod(const string& str, size_t* idx) { char* ptr; const char* const p = str.c_str(); - int errno_save = errno; + typename remove_reference::type errno_save = errno; errno = 0; double r = strtod(p, &ptr); swap(errno, errno_save); @@ -285,7 +293,7 @@ stod(const wstring& str, size_t* idx) { wchar_t* ptr; const wchar_t* const p = str.c_str(); - int errno_save = errno; + typename remove_reference::type errno_save = errno; errno = 0; double r = wcstod(p, &ptr); swap(errno, errno_save); @@ -305,7 +313,7 @@ stold(const string& str, size_t* idx) { char* ptr; const char* const p = str.c_str(); - int errno_save = errno; + typename remove_reference::type errno_save = errno; errno = 0; long double r = strtold(p, &ptr); swap(errno, errno_save); @@ -325,7 +333,7 @@ stold(const wstring& str, size_t* idx) { wchar_t* ptr; const wchar_t* const p = str.c_str(); - int errno_save = errno; + typename remove_reference::type errno_save = errno; errno = 0; long double r = wcstold(p, &ptr); swap(errno, errno_save); diff --git a/src/thread.cpp b/src/thread.cpp index 8747adf0b59..b2bd07e9d3b 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -67,8 +67,10 @@ thread::hardware_concurrency() _NOEXCEPT return n; #elif defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L) && defined(_SC_NPROCESSORS_ONLN) long result = sysconf(_SC_NPROCESSORS_ONLN); - if (result < 0 || result > UINT_MAX) - result = 0; + // sysconf returns -1 if the name is invalid, the option does not exist or + // does not have a definite limit. + if (result == -1) + return 0; return result; #else // defined(CTL_HW) && defined(HW_NCPU) // TODO: grovel through /proc or check cpuid on x86 and similar From f710aaa725318eb03db3cf6c21757ac09793f922 Mon Sep 17 00:00:00 2001 From: Achim Leubner Date: Thu, 7 Feb 2013 14:49:55 +0000 Subject: [PATCH 0017/1476] Add myself as a src committer and my mentor relationship. Approved by: emaste (co-mentor) --- share/misc/committers-src.dot | 3 +++ 1 file changed, 3 insertions(+) diff --git a/share/misc/committers-src.dot b/share/misc/committers-src.dot index a733a0e47c1..5bb879186ec 100644 --- a/share/misc/committers-src.dot +++ b/share/misc/committers-src.dot @@ -93,6 +93,7 @@ node [color=lightblue2, style=filled, bgcolor=black]; # Current src committers go here. Try to keep things sorted. ache [label="Andrey Chernov\nache@FreeBSD.org\n1993/10/31"] +achim [label="Achim Leubner\nachim@FreeBSD.org\n2013/01/23"] adrian [label="Adrian Chadd\nadrian@FreeBSD.org\n2000/07/03"] ae [label="Andrey V. Elsukov\nae@FreeBSD.org\n2010/06/03"] akiyama [label="Shunsuke Akiyama\nakiyama@FreeBSD.org\n2000/06/19"] @@ -380,6 +381,7 @@ ed -> uqs eivind -> des eivind -> rwatson +emaste -> achim emaste -> rstone emaste -> dteske emaste -> markj @@ -616,6 +618,7 @@ sbruno -> jimharris schweikh -> dds +scottl -> achim scottl -> jimharris scottl -> pjd scottl -> sah From 2ca49983425886121b506cb5126b60a705afc38c Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 7 Feb 2013 14:53:33 +0000 Subject: [PATCH 0018/1476] Stop translating the ERESTART error from the open(2) into EINTR. Posix requires that open(2) is restartable for SA_RESTART. For non-posix objects, in particular, devfs nodes, still disable automatic restart of the opens. The open call to a driver could have significant side effects for the hardware. Noted and reviewed by: jilles Discussed with: bde MFC after: 2 weeks --- sys/fs/devfs/devfs_vnops.c | 5 ++++- sys/kern/vfs_syscalls.c | 2 -- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c index 9851229d5c6..7da9b11af2a 100644 --- a/sys/fs/devfs/devfs_vnops.c +++ b/sys/fs/devfs/devfs_vnops.c @@ -1089,8 +1089,11 @@ devfs_open(struct vop_open_args *ap) vn_lock(vp, vlocked | LK_RETRY); dev_relthread(dev, ref); - if (error) + if (error != 0) { + if (error == ERESTART) + error = EINTR; return (error); + } #if 0 /* /dev/console */ KASSERT(fp != NULL, ("Could not vnode bypass device on NULL fp")); diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 1a5f2ae5f75..dd1232cf9ba 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -1106,8 +1106,6 @@ kern_openat(struct thread *td, int fd, char *path, enum uio_seg pathseg, goto success; } - if (error == ERESTART) - error = EINTR; goto bad; } td->td_dupfd = 0; From 9be7626deee071c26487957c65197d8330bf5a28 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 7 Feb 2013 15:11:43 +0000 Subject: [PATCH 0019/1476] Document the ERESTART translation to EINTR for devfs nodes. Based on the submission by: jilles MFC after: 2 weeks --- lib/libc/sys/open.2 | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/libc/sys/open.2 b/lib/libc/sys/open.2 index 041f9dc983b..41a6c6460f9 100644 --- a/lib/libc/sys/open.2 +++ b/lib/libc/sys/open.2 @@ -28,7 +28,7 @@ .\" @(#)open.2 8.2 (Berkeley) 11/16/93 .\" $FreeBSD$ .\" -.Dd March 25, 2011 +.Dd February 7, 2013 .Dt OPEN 2 .Os .Sh NAME @@ -244,6 +244,17 @@ It returns \-1 on failure. The file pointer used to mark the current position within the file is set to the beginning of the file. .Pp +If a sleeping open of a device node from +.Xr devfs 5 +is interrupted by a signal, the call always fails with +.Er EINTR , +even if the +.Dv SA_RESTART +flag is set for the signal. +A sleeping open of a fifo (see +.Xr mkfifo 2 ) +is restarted as normal. +.Pp When a new file is created it is given the group of the directory which contains it. .Pp From ded5ea6a257d26cf323d9237eab59c78c13fdd1a Mon Sep 17 00:00:00 2001 From: Randall Stewart Date: Thu, 7 Feb 2013 15:20:54 +0000 Subject: [PATCH 0020/1476] This fixes a out-of-order problem with several of the newer drivers. The basic problem was that the driver was pulling the mbuf off the drbr ring and then when sending with xmit(), encounting a full transmit ring. Thus the lower layer xmit() function would return an error, and the drivers would then append the data back on to the ring. For TCP this is a horrible scenario sure to bring on a fast-retransmit. The fix is to use drbr_peek() to pull the data pointer but not remove it from the ring. If it fails then we either call the new drbr_putback or drbr_advance method. Advance moves it forward (we do this sometimes when the xmit() function frees the mbuf). When we succeed we always call advance. The putback will always copy the mbuf back to the top of the ring. Note that the putback *cannot* be used with a drbr_dequeue() only with drbr_peek(). We most of the time, in putback, would not need to copy it back since most likey the mbuf is still the same, but sometimes xmit() functions will change the mbuf via a pullup or other call. So the optimial case for the single consumer is to always copy it back. If we ever do a multiple_consumer (for lagg?) we will need a test and atomic in the put back possibly a seperate putback_mc() in the ring buf. Reviewed by: jhb@freebsd.org, jlv@freebsd.org --- sys/dev/bxe/if_bxe.c | 28 +++++----------- sys/dev/e1000/if_em.c | 25 ++++++++------- sys/dev/e1000/if_igb.c | 33 +++++++++++++++---- sys/dev/ixgbe/ixgbe.c | 23 +++++++------- sys/dev/ixgbe/ixv.c | 24 +++++++------- sys/dev/oce/oce_if.c | 18 +++++------ sys/net/if_var.h | 53 ++++++++++++++++++++++++++++++- sys/ofed/drivers/net/mlx4/en_tx.c | 20 ++++++------ sys/sys/buf_ring.h | 48 ++++++++++++++++++++++++++++ 9 files changed, 189 insertions(+), 83 deletions(-) diff --git a/sys/dev/bxe/if_bxe.c b/sys/dev/bxe/if_bxe.c index 52d2c1bc174..9566b27c1e7 100644 --- a/sys/dev/bxe/if_bxe.c +++ b/sys/dev/bxe/if_bxe.c @@ -9506,24 +9506,15 @@ bxe_tx_mq_start_locked(struct ifnet *ifp, BXE_FP_LOCK_ASSERT(fp); - if (m == NULL) { - /* No new work, check for pending frames. */ - next = drbr_dequeue(ifp, fp->br); - } else if (drbr_needs_enqueue(ifp, fp->br)) { - /* Both new and pending work, maintain packet order. */ + if (m != NULL) { rc = drbr_enqueue(ifp, fp->br, m); if (rc != 0) { fp->tx_soft_errors++; goto bxe_tx_mq_start_locked_exit; } - next = drbr_dequeue(ifp, fp->br); - } else - /* New work only, nothing pending. */ - next = m; - + } /* Keep adding entries while there are frames to send. */ - while (next != NULL) { - + while ((next = drbr_peek(ifp, fp->br)) != NULL) { /* The transmit mbuf now belongs to us, keep track of it. */ fp->tx_mbuf_alloc++; @@ -9537,23 +9528,22 @@ bxe_tx_mq_start_locked(struct ifnet *ifp, if (__predict_false(rc != 0)) { fp->tx_encap_failures++; /* Very Bad Frames(tm) may have been dropped. */ - if (next != NULL) { + if (next == NULL) { + drbr_advance(ifp, fp->br); + } else { + drbr_putback(ifp, fp->br, next); /* * Mark the TX queue as full and save * the frame. */ ifp->if_drv_flags |= IFF_DRV_OACTIVE; fp->tx_frame_deferred++; - - /* This may reorder frame. */ - rc = drbr_enqueue(ifp, fp->br, next); fp->tx_mbuf_alloc--; } - /* Stop looking for more work. */ break; } - + drbr_advance(ifp, fp->br); /* The transmit frame was enqueued successfully. */ tx_count++; @@ -9574,8 +9564,6 @@ bxe_tx_mq_start_locked(struct ifnet *ifp, ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; break; } - - next = drbr_dequeue(ifp, fp->br); } /* No TX packets were dequeued. */ diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c index 33446972de5..a43126659be 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -905,22 +905,24 @@ em_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr, struct mbuf *m) } enq = 0; - if (m == NULL) { - next = drbr_dequeue(ifp, txr->br); - } else if (drbr_needs_enqueue(ifp, txr->br)) { - if ((err = drbr_enqueue(ifp, txr->br, m)) != 0) + if (m != NULL) { + err = drbr_enqueue(ifp, txr->br, m); + if (err) { return (err); - next = drbr_dequeue(ifp, txr->br); - } else - next = m; + } + } /* Process the queue */ - while (next != NULL) { + while ((next = drbr_peek(ifp, txr->br)) != NULL) { if ((err = em_xmit(txr, &next)) != 0) { - if (next != NULL) - err = drbr_enqueue(ifp, txr->br, next); - break; + if (next == NULL) { + drbr_advance(ifp, txr->br); + } else { + drbr_putback(ifp, txr->br, next); + } + break; } + drbr_advance(ifp, txr->br); enq++; ifp->if_obytes += next->m_pkthdr.len; if (next->m_flags & M_MCAST) @@ -928,7 +930,6 @@ em_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr, struct mbuf *m) ETHER_BPF_MTAP(ifp, next); if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) break; - next = drbr_dequeue(ifp, txr->br); } if (enq > 0) { diff --git a/sys/dev/e1000/if_igb.c b/sys/dev/e1000/if_igb.c index 2921a91d10b..8c6b429bbeb 100644 --- a/sys/dev/e1000/if_igb.c +++ b/sys/dev/e1000/if_igb.c @@ -350,6 +350,16 @@ TUNABLE_INT("hw.igb.max_interrupt_rate", &igb_max_interrupt_rate); SYSCTL_INT(_hw_igb, OID_AUTO, max_interrupt_rate, CTLFLAG_RDTUN, &igb_max_interrupt_rate, 0, "Maximum interrupts per second"); +#if __FreeBSD_version >= 800000 +/* +** Tuneable number of buffers in the buf-ring (drbr_xxx) +*/ +static int igb_buf_ring_size = IGB_BR_SIZE; +TUNABLE_INT("hw.igb.buf_ring_size", &igb_buf_ring_size); +SYSCTL_INT(_hw_igb, OID_AUTO, buf_ring_size, CTLFLAG_RDTUN, + &igb_buf_ring_size, 0, "Size of the bufring"); +#endif + /* ** Header split causes the packet header to ** be dma'd to a seperate mbuf from the payload. @@ -965,12 +975,13 @@ igb_mq_start(struct ifnet *ifp, struct mbuf *m) ** out-of-order delivery, but ** settle for it if that fails */ - if (m) + if (m != NULL) drbr_enqueue(ifp, txr->br, m); err = igb_mq_start_locked(ifp, txr); IGB_TX_UNLOCK(txr); } else { - err = drbr_enqueue(ifp, txr->br, m); + if (m != NULL) + err = drbr_enqueue(ifp, txr->br, m); taskqueue_enqueue(que->tq, &txr->txq_task); } @@ -994,12 +1005,22 @@ igb_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr) enq = 0; /* Process the queue */ - while ((next = drbr_dequeue(ifp, txr->br)) != NULL) { + while ((next = drbr_peek(ifp, txr->br)) != NULL) { if ((err = igb_xmit(txr, &next)) != 0) { - if (next != NULL) - err = drbr_enqueue(ifp, txr->br, next); + if (next == NULL) { + /* It was freed, move forward */ + drbr_advance(ifp, txr->br); + } else { + /* + * Still have one left, it may not be + * the same since the transmit function + * may have changed it. + */ + drbr_putback(ifp, txr->br, next); + } break; } + drbr_advance(ifp, txr->br); enq++; ifp->if_obytes += next->m_pkthdr.len; if (next->m_flags & M_MCAST) @@ -3301,7 +3322,7 @@ igb_allocate_queues(struct adapter *adapter) } #if __FreeBSD_version >= 800000 /* Allocate a buf ring */ - txr->br = buf_ring_alloc(IGB_BR_SIZE, M_DEVBUF, + txr->br = buf_ring_alloc(igb_buf_ring_size, M_DEVBUF, M_WAITOK, &txr->tx_mtx); #endif } diff --git a/sys/dev/ixgbe/ixgbe.c b/sys/dev/ixgbe/ixgbe.c index cfcc34215b1..0b77437c28d 100644 --- a/sys/dev/ixgbe/ixgbe.c +++ b/sys/dev/ixgbe/ixgbe.c @@ -832,22 +832,24 @@ ixgbe_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr, struct mbuf *m) } enqueued = 0; - if (m == NULL) { - next = drbr_dequeue(ifp, txr->br); - } else if (drbr_needs_enqueue(ifp, txr->br)) { - if ((err = drbr_enqueue(ifp, txr->br, m)) != 0) + if (m != NULL) { + err = drbr_enqueue(ifp, txr->br, m); + if (err) { return (err); - next = drbr_dequeue(ifp, txr->br); - } else - next = m; + } + } /* Process the queue */ - while (next != NULL) { + while ((next = drbr_peek(ifp, txr->br)) != NULL) { if ((err = ixgbe_xmit(txr, &next)) != 0) { - if (next != NULL) - err = drbr_enqueue(ifp, txr->br, next); + if (next == NULL) { + drbr_advance(ifp, txr->br); + } else { + drbr_putback(ifp, txr->br, next); + } break; } + drbr_advance(ifp, txr->br); enqueued++; /* Send a copy of the frame to the BPF listener */ ETHER_BPF_MTAP(ifp, next); @@ -855,7 +857,6 @@ ixgbe_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr, struct mbuf *m) break; if (txr->tx_avail < IXGBE_TX_OP_THRESHOLD) ixgbe_txeof(txr); - next = drbr_dequeue(ifp, txr->br); } if (enqueued > 0) { diff --git a/sys/dev/ixgbe/ixv.c b/sys/dev/ixgbe/ixv.c index ef5f7537f30..b3a3d642872 100644 --- a/sys/dev/ixgbe/ixv.c +++ b/sys/dev/ixgbe/ixv.c @@ -620,22 +620,23 @@ ixv_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr, struct mbuf *m) ixv_txeof(txr); enqueued = 0; - if (m == NULL) { - next = drbr_dequeue(ifp, txr->br); - } else if (drbr_needs_enqueue(ifp, txr->br)) { - if ((err = drbr_enqueue(ifp, txr->br, m)) != 0) + if (m != NULL) { + err = drbr_enqueue(ifp, txr->br, m); + if (err) { return (err); - next = drbr_dequeue(ifp, txr->br); - } else - next = m; - + } + } /* Process the queue */ - while (next != NULL) { + while ((next = drbr_peek(ifp, txr->br)) != NULL) { if ((err = ixv_xmit(txr, &next)) != 0) { - if (next != NULL) - err = drbr_enqueue(ifp, txr->br, next); + if (next == NULL) { + drbr_advance(ifp, txr->br); + } else { + drbr_putback(ifp, txr->br, next); + } break; } + drbr_advance(ifp, txr->br); enqueued++; ifp->if_obytes += next->m_pkthdr.len; if (next->m_flags & M_MCAST) @@ -648,7 +649,6 @@ ixv_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr, struct mbuf *m) ifp->if_drv_flags |= IFF_DRV_OACTIVE; break; } - next = drbr_dequeue(ifp, txr->br); } if (enqueued > 0) { diff --git a/sys/dev/oce/oce_if.c b/sys/dev/oce/oce_if.c index cba57bfa5a6..2b4c181bef6 100644 --- a/sys/dev/oce/oce_if.c +++ b/sys/dev/oce/oce_if.c @@ -1166,29 +1166,27 @@ oce_multiq_transmit(struct ifnet *ifp, struct mbuf *m, struct oce_wq *wq) return status; } - if (m == NULL) - next = drbr_dequeue(ifp, br); - else if (drbr_needs_enqueue(ifp, br)) { + if (m != NULL) { if ((status = drbr_enqueue(ifp, br, m)) != 0) return status; - next = drbr_dequeue(ifp, br); - } else - next = m; - - while (next != NULL) { + } + while ((next = drbr_peek(ifp, br)) != NULL) { if (oce_tx(sc, &next, queue_index)) { - if (next != NULL) { + if (next == NULL) { + drbr_advance(ifp, br); + } else { + drbr_putback(ifp, br, next); wq->tx_stats.tx_stops ++; ifp->if_drv_flags |= IFF_DRV_OACTIVE; status = drbr_enqueue(ifp, br, next); } break; } + drbr_advance(ifp, br); ifp->if_obytes += next->m_pkthdr.len; if (next->m_flags & M_MCAST) ifp->if_omcasts++; ETHER_BPF_MTAP(ifp, next); - next = drbr_dequeue(ifp, br); } return status; diff --git a/sys/net/if_var.h b/sys/net/if_var.h index 2ec73e44c17..7fcbd38ad7f 100644 --- a/sys/net/if_var.h +++ b/sys/net/if_var.h @@ -621,6 +621,45 @@ drbr_enqueue(struct ifnet *ifp, struct buf_ring *br, struct mbuf *m) return (error); } +static __inline void +drbr_putback(struct ifnet *ifp, struct buf_ring *br, struct mbuf *new) +{ + /* + * The top of the list needs to be swapped + * for this one. + */ +#ifdef ALTQ + if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) { + /* + * Peek in altq case dequeued it + * so put it back. + */ + IFQ_DRV_PREPEND(&ifp->if_snd, new); + return; + } +#endif + buf_ring_putback_sc(br, new); +} + +static __inline struct mbuf * +drbr_peek(struct ifnet *ifp, struct buf_ring *br) +{ +#ifdef ALTQ + struct mbuf *m; + if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) { + /* + * Pull it off like a dequeue + * since drbr_advance() does nothing + * for altq and drbr_putback() will + * use the old prepend function. + */ + IFQ_DEQUEUE(&ifp->if_snd, m); + return (m); + } +#endif + return(buf_ring_peek(br)); +} + static __inline void drbr_flush(struct ifnet *ifp, struct buf_ring *br) { @@ -648,7 +687,7 @@ drbr_dequeue(struct ifnet *ifp, struct buf_ring *br) #ifdef ALTQ struct mbuf *m; - if (ALTQ_IS_ENABLED(&ifp->if_snd)) { + if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) { IFQ_DEQUEUE(&ifp->if_snd, m); return (m); } @@ -656,6 +695,18 @@ drbr_dequeue(struct ifnet *ifp, struct buf_ring *br) return (buf_ring_dequeue_sc(br)); } +static __inline void +drbr_advance(struct ifnet *ifp, struct buf_ring *br) +{ +#ifdef ALTQ + /* Nothing to do here since peek dequeues in altq case */ + if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) + return; +#endif + return (buf_ring_advance_sc(br)); +} + + static __inline struct mbuf * drbr_dequeue_cond(struct ifnet *ifp, struct buf_ring *br, int (*func) (struct mbuf *, void *), void *arg) diff --git a/sys/ofed/drivers/net/mlx4/en_tx.c b/sys/ofed/drivers/net/mlx4/en_tx.c index e2e13c2fdcc..fee7afecd5d 100644 --- a/sys/ofed/drivers/net/mlx4/en_tx.c +++ b/sys/ofed/drivers/net/mlx4/en_tx.c @@ -931,22 +931,21 @@ mlx4_en_transmit_locked(struct ifnet *dev, int tx_ind, struct mbuf *m) } enqueued = 0; - if (m == NULL) { - next = drbr_dequeue(dev, ring->br); - } else if (drbr_needs_enqueue(dev, ring->br)) { + if (m != NULL) { if ((err = drbr_enqueue(dev, ring->br, m)) != 0) return (err); - next = drbr_dequeue(dev, ring->br); - } else - next = m; - + } /* Process the queue */ - while (next != NULL) { + while ((next = drbr_peek(ifp, ring->br)) != NULL) { if ((err = mlx4_en_xmit(dev, tx_ind, &next)) != 0) { - if (next != NULL) - err = drbr_enqueue(dev, ring->br, next); + if (next == NULL) { + drbr_advance(ifp, ring->br); + } else { + drbr_putback(ifp, ring->br, next); + } break; } + drbr_advance(ifp, ring->br); enqueued++; dev->if_obytes += next->m_pkthdr.len; if (next->m_flags & M_MCAST) @@ -955,7 +954,6 @@ mlx4_en_transmit_locked(struct ifnet *dev, int tx_ind, struct mbuf *m) ETHER_BPF_MTAP(dev, next); if ((dev->if_drv_flags & IFF_DRV_RUNNING) == 0) break; - next = drbr_dequeue(dev, ring->br); } if (enqueued > 0) diff --git a/sys/sys/buf_ring.h b/sys/sys/buf_ring.h index b660d9ba10c..b1ccaec6b90 100644 --- a/sys/sys/buf_ring.h +++ b/sys/sys/buf_ring.h @@ -207,6 +207,54 @@ buf_ring_dequeue_sc(struct buf_ring *br) return (buf); } +/* + * single-consumer advance after a peek + * use where it is protected by a lock + * e.g. a network driver's tx queue lock + */ +static __inline void +buf_ring_advance_sc(struct buf_ring *br) +{ + uint32_t cons_head, cons_next; + uint32_t prod_tail; + + cons_head = br->br_cons_head; + prod_tail = br->br_prod_tail; + + cons_next = (cons_head + 1) & br->br_cons_mask; + if (cons_head == prod_tail) + return; + br->br_cons_head = cons_next; +#ifdef DEBUG_BUFRING + br->br_ring[cons_head] = NULL; +#endif + br->br_cons_tail = cons_next; +} + +/* + * Used to return a buffer (most likely already there) + * to the top od the ring. The caller should *not* + * have used any dequeue to pull it out of the ring + * but instead should have used the peek() function. + * This is normally used where the transmit queue + * of a driver is full, and an mubf must be returned. + * Most likely whats in the ring-buffer is what + * is being put back (since it was not removed), but + * sometimes the lower transmit function may have + * done a pullup or other function that will have + * changed it. As an optimzation we always put it + * back (since jhb says the store is probably cheaper), + * if we have to do a multi-queue version we will need + * the compare and an atomic. + */ +static __inline void +buf_ring_putback_sc(struct buf_ring *br, void *new) +{ + KASSERT(br->br_cons_head != br->br_prod_tail, + ("Buf-Ring has none in putback")) ; + br->br_ring[br->br_cons_head] = new; +} + /* * return a pointer to the first entry in the ring * without modifying it, or NULL if the ring is empty From 888d4d4f865af1a6b0e1a25189d5157a25314444 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 7 Feb 2013 15:34:22 +0000 Subject: [PATCH 0021/1476] When vforked child is traced, the debugging events are not generated until child performs exec(). The behaviour is reasonable when a debugger is the real parent, because the parent is stopped until exec(), and sending a debugging event to the debugger would deadlock both parent and child. On the other hand, when debugger is not the parent of the vforked child, not sending debugging signals makes it impossible to debug across vfork. Fix the issue by declining generating debug signals only when vfork() was done and child called ptrace(PT_TRACEME). Set a new process flag P_PPTRACE from the attach code for PT_TRACEME, if P_PPWAIT flag is set, which indicates that the process was created with vfork() and still did not execed. Check P_PPTRACE from issignal(), instead of refusing the trace outright for the P_PPWAIT case. The scope of P_PPTRACE is exactly contained in the scope of P_PPWAIT. Found and tested by: zont Reviewed by: pluknet MFC after: 2 weeks --- sys/kern/kern_exec.c | 2 +- sys/kern/kern_exit.c | 2 +- sys/kern/kern_sig.c | 2 +- sys/kern/sys_process.c | 2 ++ sys/sys/proc.h | 1 + 5 files changed, 6 insertions(+), 3 deletions(-) diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index a37b9f134cf..965ce31af77 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -640,7 +640,7 @@ interpret: */ p->p_flag |= P_EXEC; if (p->p_pptr && (p->p_flag & P_PPWAIT)) { - p->p_flag &= ~P_PPWAIT; + p->p_flag &= ~(P_PPWAIT | P_PPTRACE); cv_broadcast(&p->p_pwait); } diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 3a9a3a4cd76..82f0344c829 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -266,7 +266,7 @@ exit1(struct thread *td, int rv) PROC_LOCK(p); rv = p->p_xstat; /* Event handler could change exit status */ stopprofclock(p); - p->p_flag &= ~(P_TRACED | P_PPWAIT); + p->p_flag &= ~(P_TRACED | P_PPWAIT | P_PPTRACE); /* * Stop the real interval timer. If the handler is currently diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index e28bdc41ce1..5bb49a834aa 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -2618,7 +2618,7 @@ issignal(struct thread *td, int stop_allowed) sigqueue_delete(&p->p_sigqueue, sig); continue; } - if (p->p_flag & P_TRACED && (p->p_flag & P_PPWAIT) == 0) { + if (p->p_flag & P_TRACED && (p->p_flag & P_PPTRACE) == 0) { /* * If traced, always stop. * Remove old signal from queue before the stop. diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c index b1f81451eaf..63de37a27de 100644 --- a/sys/kern/sys_process.c +++ b/sys/kern/sys_process.c @@ -822,6 +822,8 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data) case PT_TRACE_ME: /* set my trace flag and "owner" so it can read/write me */ p->p_flag |= P_TRACED; + if (p->p_flag & P_PPWAIT) + p->p_flag |= P_PPTRACE; p->p_oppid = p->p_pptr->p_pid; break; diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 78af5c052bc..ade28642cf0 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -636,6 +636,7 @@ struct proc { #define P_INMEM 0x10000000 /* Loaded into memory. */ #define P_SWAPPINGOUT 0x20000000 /* Process is being swapped out. */ #define P_SWAPPINGIN 0x40000000 /* Process is being swapped in. */ +#define P_PPTRACE 0x80000000 /* PT_TRACEME by vforked child. */ #define P_STOPPED (P_STOPPED_SIG|P_STOPPED_SINGLE|P_STOPPED_TRACE) #define P_SHOULDSTOP(p) ((p)->p_flag & P_STOPPED) From 2ee83a16c0142a253bca069298aabca21513d8bd Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 7 Feb 2013 15:36:24 +0000 Subject: [PATCH 0022/1476] Document the detail of interaction between vfork and PT_TRACEME. MFC after: 2 weeks --- lib/libc/sys/ptrace.2 | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/libc/sys/ptrace.2 b/lib/libc/sys/ptrace.2 index 9dda8ee1b41..90c45442561 100644 --- a/lib/libc/sys/ptrace.2 +++ b/lib/libc/sys/ptrace.2 @@ -2,7 +2,7 @@ .\" $NetBSD: ptrace.2,v 1.2 1995/02/27 12:35:37 cgd Exp $ .\" .\" This file is in the public domain. -.Dd February 19, 2012 +.Dd February 7, 2013 .Dt PTRACE 2 .Os .Sh NAME @@ -100,6 +100,16 @@ or any of the routines built on it it will stop before executing the first instruction of the new image. Also, any setuid or setgid bits on the executable being executed will be ignored. +If the child was created by +.Xr vfork 2 +system call or +.Xr rfork(2) +call with the +.Dv RFMEM +flag specified, the debugging events are reported to the parent +only after the +.Xr execve 2 +is executed. .It Dv PT_READ_I , Dv PT_READ_D These requests read a single .Vt int From 45732078c1abbb1fcfeb9eaa54546afca3f0b1a8 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 7 Feb 2013 15:37:51 +0000 Subject: [PATCH 0023/1476] Document P_PPTRACE. MFC after: 2 weeks --- bin/ps/ps.1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bin/ps/ps.1 b/bin/ps/ps.1 index 21e8eaf37cb..7f691378084 100644 --- a/bin/ps/ps.1 +++ b/bin/ps/ps.1 @@ -29,7 +29,7 @@ .\" @(#)ps.1 8.3 (Berkeley) 4/18/94 .\" $FreeBSD$ .\" -.Dd September 18, 2012 +.Dd February 7, 2013 .Dt PS 1 .Os .Sh NAME @@ -323,6 +323,7 @@ the include file .It Dv "P_INMEM" Ta No "0x10000000" Ta "Loaded into memory" .It Dv "P_SWAPPINGOUT" Ta No "0x20000000" Ta "Process is being swapped out" .It Dv "P_SWAPPINGIN" Ta No "0x40000000" Ta "Process is being swapped in" +.It Dv "P_PPTRACE" Ta No "0x80000000" Ta "Vforked child issued ptrace(PT_TRACEME)" .El .It Cm label The MAC label of the process. From 5be97e72e61a9bcf33277ec83345b3323cd7539f Mon Sep 17 00:00:00 2001 From: Xin LI Date: Thu, 7 Feb 2013 19:00:54 +0000 Subject: [PATCH 0024/1476] Catch TRACE parameters up with r238888. This change is only needed when debugging is enabled. --- bin/sh/jobs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/sh/jobs.c b/bin/sh/jobs.c index d2e1d57ecf2..c86394f0d46 100644 --- a/bin/sh/jobs.c +++ b/bin/sh/jobs.c @@ -1030,7 +1030,7 @@ dowait(int mode, struct job *job) int wflags; int restore_sigchld; - TRACE(("dowait(%d) called\n", block)); + TRACE(("dowait(%d, %p) called\n", mode, job)); restore_sigchld = 0; if ((mode & DOWAIT_SIG) != 0) { sigfillset(&mask); From ff17492f7c349951b0bfa57fd1c4a1e617322e4e Mon Sep 17 00:00:00 2001 From: Monthadar Al Jaberi Date: Thu, 7 Feb 2013 21:12:55 +0000 Subject: [PATCH 0025/1476] Stop a mesh STA from flooding with peer frames. This problem happens when using ACL policy to filter mesh STA but two nodes have different policy. Then one of them will try to peer all the time. This can also help if for any reason one of the peering mesh STA have problems sending/receiving peer frames. * Modified struct ieee80211_node to include two new fields: + struct callout ni_mlhtimer /* link mesh backoff timer */ + uint8_t ni_mlhcnt /* link mesh holding counter */ * Added two new sysctl (check sysctl -d for more info): + net.wlan.mesh.backofftimeout=5000 + net.wlan.mesh.maxholding=2; * When receiving a beacon and we are in IEEE80211_NODE_MESH_IDLE check if ni_mlhcnt >= ieee80211_mesh_maxholding, if so do not do anything; * In mesh_peer_timeout_cb when transitioning from IEEE80211_NODE_MESH_HOLDING to IEEE80211_NODE_MESH_IDLE increment ni_mlhcnt, and eventually start ieee80211_mesh_backofftimeout; Approved by: adrian (mentor) --- sys/net80211/ieee80211_mesh.c | 32 +++++++++++++++++++++++++++++++- sys/net80211/ieee80211_node.h | 2 ++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/sys/net80211/ieee80211_mesh.c b/sys/net80211/ieee80211_mesh.c index 6ab76d92a15..d2f63e5c383 100644 --- a/sys/net80211/ieee80211_mesh.c +++ b/sys/net80211/ieee80211_mesh.c @@ -111,10 +111,20 @@ static int ieee80211_mesh_confirmtimeout = -1; SYSCTL_PROC(_net_wlan_mesh, OID_AUTO, confirmtimeout, CTLTYPE_INT | CTLFLAG_RW, &ieee80211_mesh_confirmtimeout, 0, ieee80211_sysctl_msecs_ticks, "I", "Confirm state timeout (msec)"); +static int ieee80211_mesh_backofftimeout = -1; +SYSCTL_PROC(_net_wlan_mesh, OID_AUTO, backofftimeout, CTLTYPE_INT | CTLFLAG_RW, + &ieee80211_mesh_backofftimeout, 0, ieee80211_sysctl_msecs_ticks, "I", + "Backoff timeout (msec). This is to throutles peering forever when " + "not receving answer or is rejected by a neighbor"); static int ieee80211_mesh_maxretries = 2; SYSCTL_INT(_net_wlan_mesh, OID_AUTO, maxretries, CTLTYPE_INT | CTLFLAG_RW, &ieee80211_mesh_maxretries, 0, "Maximum retries during peer link establishment"); +static int ieee80211_mesh_maxholding = 2; +SYSCTL_INT(_net_wlan_mesh, OID_AUTO, maxholding, CTLTYPE_INT | CTLFLAG_RW, + &ieee80211_mesh_maxholding, 0, + "Maximum times we are allowed to transition to HOLDING state before " + "backinoff during peer link establishment"); static const uint8_t broadcastaddr[IEEE80211_ADDR_LEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; @@ -500,6 +510,7 @@ ieee80211_mesh_init(void) ieee80211_mesh_retrytimeout = msecs_to_ticks(40); ieee80211_mesh_holdingtimeout = msecs_to_ticks(40); ieee80211_mesh_confirmtimeout = msecs_to_ticks(40); + ieee80211_mesh_backofftimeout = msecs_to_ticks(5000); /* * Register action frame handlers. @@ -1696,7 +1707,6 @@ mesh_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, int subtype, } /* * Automatically peer with discovered nodes if possible. - * XXX backoff on repeated failure */ if (ni != vap->iv_bss && (ms->ms_flags & IEEE80211_MESHFLAGS_AP)) { @@ -1705,6 +1715,10 @@ mesh_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, int subtype, { uint16_t args[1]; + /* Wait for backoff callout to reset counter */ + if (ni->ni_mlhcnt >= ieee80211_mesh_maxholding) + return; + ni->ni_mlpid = mesh_generateid(vap); if (ni->ni_mlpid == 0) return; @@ -2578,6 +2592,15 @@ mesh_peer_timeout_stop(struct ieee80211_node *ni) callout_drain(&ni->ni_mltimer); } +static void +mesh_peer_backoff_cb(void *arg) +{ + struct ieee80211_node *ni = (struct ieee80211_node *)arg; + + /* After backoff timeout, try to peer automatically again. */ + ni->ni_mlhcnt = 0; +} + /* * Mesh Peer Link Management FSM timeout handling. */ @@ -2625,6 +2648,11 @@ mesh_peer_timeout_cb(void *arg) mesh_peer_timeout_setup(ni); break; case IEEE80211_NODE_MESH_HOLDING: + ni->ni_mlhcnt++; + if (ni->ni_mlhcnt >= ieee80211_mesh_maxholding) + callout_reset(&ni->ni_mlhtimer, + ieee80211_mesh_backofftimeout, + mesh_peer_backoff_cb, ni); mesh_linkchange(ni, IEEE80211_NODE_MESH_IDLE); break; } @@ -2889,6 +2917,7 @@ ieee80211_mesh_node_init(struct ieee80211vap *vap, struct ieee80211_node *ni) { ni->ni_flags |= IEEE80211_NODE_QOS; callout_init(&ni->ni_mltimer, CALLOUT_MPSAFE); + callout_init(&ni->ni_mlhtimer, CALLOUT_MPSAFE); } /* @@ -2901,6 +2930,7 @@ ieee80211_mesh_node_cleanup(struct ieee80211_node *ni) struct ieee80211_mesh_state *ms = vap->iv_mesh; callout_drain(&ni->ni_mltimer); + callout_drain(&ni->ni_mlhtimer); /* NB: short-circuit callbacks after mesh_vdetach */ if (vap->iv_mesh != NULL) ms->ms_ppath->mpp_peerdown(ni); diff --git a/sys/net80211/ieee80211_node.h b/sys/net80211/ieee80211_node.h index 48eae2d7c6c..bb31136892d 100644 --- a/sys/net80211/ieee80211_node.h +++ b/sys/net80211/ieee80211_node.h @@ -204,6 +204,8 @@ struct ieee80211_node { struct callout ni_mltimer; /* link mesh timer */ uint8_t ni_mlrcnt; /* link mesh retry counter */ uint8_t ni_mltval; /* link mesh timer value */ + struct callout ni_mlhtimer; /* link mesh backoff timer */ + uint8_t ni_mlhcnt; /* link mesh holding counter */ /* 11n state */ uint16_t ni_htcap; /* HT capabilities */ From 8c751dd52830d9a8a28eb72e4a39ae1b00c4f585 Mon Sep 17 00:00:00 2001 From: Monthadar Al Jaberi Date: Thu, 7 Feb 2013 21:17:35 +0000 Subject: [PATCH 0026/1476] Fix mesh path flag. * A bug occurs while in discovery mode which leaves a path marked with both Discover and Valid flag. This happens when receiving/sending PREQ and PREP in a particular order. Solution is to assign the Valid bit instead of oring it; Approved by: adrian (mentor) --- sys/net80211/ieee80211_hwmp.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sys/net80211/ieee80211_hwmp.c b/sys/net80211/ieee80211_hwmp.c index 2f8ec851c81..f15347c6c4c 100644 --- a/sys/net80211/ieee80211_hwmp.c +++ b/sys/net80211/ieee80211_hwmp.c @@ -995,8 +995,11 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni, rtorig->rt_metric = metric; rtorig->rt_nhops = preq->preq_hopcount + 1; ieee80211_mesh_rt_update(rtorig, preq->preq_lifetime); - /* path to orig is valid now */ - rtorig->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID; + /* Path to orig is valid now. + * NB: we know it can't be Proxy, and if it is GATE + * it will be marked below. + */ + rtorig->rt_flags = IEEE80211_MESHRT_FLAGS_VALID; }else if ((hrtarg != NULL && HWMP_SEQ_EQ(hrtarg->hr_seq, PREQ_TSEQ(0)) && ((rtorig->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0)) || From 227da7d10ba5626aabd240351bb09d59263f0812 Mon Sep 17 00:00:00 2001 From: Monthadar Al Jaberi Date: Thu, 7 Feb 2013 21:18:22 +0000 Subject: [PATCH 0027/1476] Add mesh debug for interarction between DS & MBSS. * Add mesh debug information when frames enter or leave the MBSS; * Set IEEE80211_MSG_OUTPUT bit to enable output; Approved by: adrian (mentor) --- sys/net80211/ieee80211_mesh.c | 3 +++ sys/net80211/ieee80211_output.c | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/sys/net80211/ieee80211_mesh.c b/sys/net80211/ieee80211_mesh.c index d2f63e5c383..96ba39900cf 100644 --- a/sys/net80211/ieee80211_mesh.c +++ b/sys/net80211/ieee80211_mesh.c @@ -1246,6 +1246,9 @@ mesh_recv_indiv_data_to_me(struct ieee80211vap *vap, struct mbuf *m, * All other cases: forward of MSDUs from the MBSS to DS indiv. * addressed according to 13.11.3.2. */ + IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_OUTPUT, qwh->i_addr2, + "forward frame to DS, SA(%6D) DA(%6D)", + mc10->mc_addr6, ":", mc10->mc_addr5, ":"); } return (0); /* process locally */ } diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c index 57925f2e038..8f3e51bbcef 100644 --- a/sys/net80211/ieee80211_output.c +++ b/sys/net80211/ieee80211_output.c @@ -262,6 +262,10 @@ ieee80211_start(struct ifnet *ifp) m_freem(m); continue; } + IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT, + "forward frame from DS SA(%6D), DA(%6D)\n", + eh->ether_dhost, ":", + eh->ether_shost, ":"); ieee80211_mesh_proxy_check(vap, eh->ether_shost); } ni = ieee80211_mesh_discover(vap, eh->ether_dhost, m); From 40c44a6bb5d34fa885448cc40ff0ed77db5dffa2 Mon Sep 17 00:00:00 2001 From: Monthadar Al Jaberi Date: Thu, 7 Feb 2013 21:19:44 +0000 Subject: [PATCH 0028/1476] HWMP: Accept a PERR even if path is valid. * An HWMP PERR should be accepted even if path is valid. Because we check if we recevied it from a neighbour that we use as a next hop; Approved by: adrian (mentor) --- sys/net80211/ieee80211_hwmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/net80211/ieee80211_hwmp.c b/sys/net80211/ieee80211_hwmp.c index f15347c6c4c..7c8b3f9ec81 100644 --- a/sys/net80211/ieee80211_hwmp.c +++ b/sys/net80211/ieee80211_hwmp.c @@ -1528,7 +1528,7 @@ hwmp_recv_perr(struct ieee80211vap *vap, struct ieee80211_node *ni, */ for (i = 0; i < perr->perr_ndests; i++) { rt = ieee80211_mesh_rt_find(vap, PERR_DADDR(i)); - if (rt == NULL || rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) + if (rt == NULL) continue; if (!IEEE80211_ADDR_EQ(rt->rt_nexthop, wh->i_addr2)) continue; From e1373e86c43bebdd87b1d52ca69c896f42883d00 Mon Sep 17 00:00:00 2001 From: Monthadar Al Jaberi Date: Thu, 7 Feb 2013 21:20:28 +0000 Subject: [PATCH 0029/1476] Update net80211 mesh struct ieee80211_meshgann_ie. * Change all field prefix from pann_ to gann_; * Added IEEE80211_MESHGANN_BASE_SZ macro to be used in the length field of a GANN frame according to 802.11 standard; * Changed gann_seq field type to uint32_t; * Added a Gate Announcement interval field according to IEEE802.11 2012 standard; * Added IEEE80211_MESHRT_FLAGS_GATE as flag bit to ieee80211_mesh_route; * Added IEEE80211_MESHRT_FLAGS_GATE as flag bit to ieee80211req_mesh_route; Approved by: adrian (mentor) --- sys/net80211/ieee80211_ioctl.h | 1 + sys/net80211/ieee80211_mesh.h | 21 ++++++++++++++------- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/sys/net80211/ieee80211_ioctl.h b/sys/net80211/ieee80211_ioctl.h index 2214b333f6e..ee980263f6f 100644 --- a/sys/net80211/ieee80211_ioctl.h +++ b/sys/net80211/ieee80211_ioctl.h @@ -342,6 +342,7 @@ struct ieee80211req_mesh_route { #define IEEE80211_MESHRT_FLAGS_DISCOVER 0x01 #define IEEE80211_MESHRT_FLAGS_VALID 0x02 #define IEEE80211_MESHRT_FLAGS_PROXY 0x04 +#define IEEE80211_MESHRT_FLAGS_GATE 0x08 uint8_t imr_dest[IEEE80211_ADDR_LEN]; uint8_t imr_nexthop[IEEE80211_ADDR_LEN]; uint16_t imr_nhops; diff --git a/sys/net80211/ieee80211_mesh.h b/sys/net80211/ieee80211_mesh.h index f1610125f84..1e14357e7f2 100644 --- a/sys/net80211/ieee80211_mesh.h +++ b/sys/net80211/ieee80211_mesh.h @@ -194,14 +194,20 @@ struct ieee80211_meshbeacont_ie { #endif /* Gate (GANN) Annoucement */ +/* + * NB: these macros used for the length in the IEs does not include 2 bytes + * for _ie and _len fields as is defined by the standard. + */ +#define IEEE80211_MESHGANN_BASE_SZ (15) struct ieee80211_meshgann_ie { - uint8_t pann_ie; /* IEEE80211_ELEMID_MESHGANN */ - uint8_t pann_len; - uint8_t pann_flags; - uint8_t pann_hopcount; - uint8_t pann_ttl; - uint8_t pann_addr[IEEE80211_ADDR_LEN]; - uint8_t pann_seq; /* PANN Sequence Number */ + uint8_t gann_ie; /* IEEE80211_ELEMID_MESHGANN */ + uint8_t gann_len; + uint8_t gann_flags; + uint8_t gann_hopcount; + uint8_t gann_ttl; + uint8_t gann_addr[IEEE80211_ADDR_LEN]; + uint32_t gann_seq; /* GANN Sequence Number */ + uint16_t gann_interval; /* GANN Interval */ } __packed; /* Root (MP) Annoucement */ @@ -423,6 +429,7 @@ struct ieee80211_mesh_route { #define IEEE80211_MESHRT_FLAGS_DISCOVER 0x01 /* path discovery */ #define IEEE80211_MESHRT_FLAGS_VALID 0x02 /* path discovery complete */ #define IEEE80211_MESHRT_FLAGS_PROXY 0x04 /* proxy entry */ +#define IEEE80211_MESHRT_FLAGS_GATE 0x08 /* mesh gate entry */ uint32_t rt_lifetime; /* route timeout */ uint32_t rt_lastmseq; /* last seq# seen dest */ uint32_t rt_ext_seq; /* proxy seq number */ From 71766338b2472fa14e97140c06af4dd5c20ec9b1 Mon Sep 17 00:00:00 2001 From: Monthadar Al Jaberi Date: Thu, 7 Feb 2013 21:21:05 +0000 Subject: [PATCH 0030/1476] Update in ieee80211_action.c for mesh code handlers. * Removed meshlm_send_action and hwmp_send_action. Introduced one common for all Mesh Action frames meshaction_send_action. According to 802.11 standard Link Metric and HWMP are all under Mesh Action category; * Did similar changes to recv_action part; * The size of meshaction_*_action is set to 12. This is to make room for the rest of Mesh Action category subtypes; Approved by: adrian (mentor) --- sys/net80211/ieee80211_action.c | 65 +++++++-------------------------- 1 file changed, 14 insertions(+), 51 deletions(-) diff --git a/sys/net80211/ieee80211_action.c b/sys/net80211/ieee80211_action.c index 44543b69b6a..d28e2918810 100644 --- a/sys/net80211/ieee80211_action.c +++ b/sys/net80211/ieee80211_action.c @@ -67,10 +67,8 @@ static ieee80211_send_action_func *meshpl_send_action[8] = { send_inval, send_inval, send_inval, send_inval, send_inval, send_inval, send_inval, send_inval, }; -static ieee80211_send_action_func *meshlm_send_action[4] = { +static ieee80211_send_action_func *meshaction_send_action[12] = { send_inval, send_inval, send_inval, send_inval, -}; -static ieee80211_send_action_func *hwmp_send_action[8] = { send_inval, send_inval, send_inval, send_inval, send_inval, send_inval, send_inval, send_inval, }; @@ -100,18 +98,10 @@ ieee80211_send_action_register(int cat, int act, ieee80211_send_action_func *f) meshpl_send_action[act] = f; return 0; case IEEE80211_ACTION_CAT_MESH: - switch (act) { - case IEEE80211_ACTION_MESH_LMETRIC: - if (act >= N(meshlm_send_action)) - break; - meshlm_send_action[act] = f; - return 0; - case IEEE80211_ACTION_MESH_HWMP: - if (act >= N(hwmp_send_action)) - break; - hwmp_send_action[act] = f; - return 0; - } + if (act >= N(meshaction_send_action)) + break; + meshaction_send_action[act] = f; + return 0; break; case IEEE80211_ACTION_CAT_VENDOR: if (act >= N(vendor_send_action)) @@ -149,16 +139,8 @@ ieee80211_send_action(struct ieee80211_node *ni, int cat, int act, void *sa) f = meshpl_send_action[act]; break; case IEEE80211_ACTION_CAT_MESH: - switch (act) { - case IEEE80211_ACTION_MESH_LMETRIC: - if (act < N(meshlm_send_action)) - f = meshlm_send_action[act]; - break; - case IEEE80211_ACTION_MESH_HWMP: - if (act < N(hwmp_send_action)) - f = hwmp_send_action[act]; - break; - } + if (act < N(meshaction_send_action)) + f = meshaction_send_action[act]; break; case IEEE80211_ACTION_CAT_VENDOR: if (act < N(vendor_send_action)) @@ -188,10 +170,8 @@ static ieee80211_recv_action_func *meshpl_recv_action[8] = { recv_inval, recv_inval, recv_inval, recv_inval, recv_inval, recv_inval, recv_inval, recv_inval, }; -static ieee80211_recv_action_func *meshlm_recv_action[4] = { +static ieee80211_recv_action_func *meshaction_recv_action[12] = { recv_inval, recv_inval, recv_inval, recv_inval, -}; -static ieee80211_recv_action_func *hwmp_recv_action[8] = { recv_inval, recv_inval, recv_inval, recv_inval, recv_inval, recv_inval, recv_inval, recv_inval, }; @@ -221,19 +201,10 @@ ieee80211_recv_action_register(int cat, int act, ieee80211_recv_action_func *f) meshpl_recv_action[act] = f; return 0; case IEEE80211_ACTION_CAT_MESH: - switch (act) { - case IEEE80211_ACTION_MESH_LMETRIC: - if (act >= N(meshlm_recv_action)) - break; - meshlm_recv_action[act] = f; - return 0; - case IEEE80211_ACTION_MESH_HWMP: - if (act >= N(hwmp_recv_action)) - break; - hwmp_recv_action[act] = f; - return 0; - } - break; + if (act >= N(meshaction_recv_action)) + break; + meshaction_recv_action[act] = f; + return 0; case IEEE80211_ACTION_CAT_VENDOR: if (act >= N(vendor_recv_action)) break; @@ -274,16 +245,8 @@ ieee80211_recv_action(struct ieee80211_node *ni, f = meshpl_recv_action[ia->ia_action]; break; case IEEE80211_ACTION_CAT_MESH: - switch (ia->ia_action) { - case IEEE80211_ACTION_MESH_LMETRIC: - if (ia->ia_action < N(meshlm_recv_action)) - f = meshlm_recv_action[ia->ia_action]; - break; - case IEEE80211_ACTION_MESH_HWMP: - if (ia->ia_action < N(hwmp_recv_action)) - f = hwmp_recv_action[ia->ia_action]; - break; - } + if (ia->ia_action < N(meshaction_recv_action)) + f = meshaction_recv_action[ia->ia_action]; break; case IEEE80211_ACTION_CAT_VENDOR: if (ia->ia_action < N(vendor_recv_action)) From cd47d75c70ae7d37997b5f61f2c2f0287f7ad6f1 Mon Sep 17 00:00:00 2001 From: Monthadar Al Jaberi Date: Thu, 7 Feb 2013 21:21:40 +0000 Subject: [PATCH 0031/1476] Mesh: management mesh action frames are to be discarded when not peered. * Modified ieee80211_recv_action to check if neighbour is peered for IEEE80211_ACTION_CAT_MESH frames, if not frame is discarded. This is according to IEEE802.11 2012 standard; * Removed duplicate checks in each hwmp_recv_* handlers because HWMP is a subtype of mesh action; Approved by: adrian (mentor) --- sys/net80211/ieee80211_action.c | 10 ++++++++++ sys/net80211/ieee80211_hwmp.c | 15 +-------------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/sys/net80211/ieee80211_action.c b/sys/net80211/ieee80211_action.c index d28e2918810..e3576d6679a 100644 --- a/sys/net80211/ieee80211_action.c +++ b/sys/net80211/ieee80211_action.c @@ -228,6 +228,7 @@ ieee80211_recv_action(struct ieee80211_node *ni, { #define N(a) (sizeof(a) / sizeof(a[0])) ieee80211_recv_action_func *f = recv_inval; + struct ieee80211vap *vap = ni->ni_vap; const struct ieee80211_action *ia = (const struct ieee80211_action *) frm; @@ -245,6 +246,15 @@ ieee80211_recv_action(struct ieee80211_node *ni, f = meshpl_recv_action[ia->ia_action]; break; case IEEE80211_ACTION_CAT_MESH: + if (ni == vap->iv_bss || + ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED) { + IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_MESH, + ni->ni_macaddr, NULL, + "peer link not yet established (%d), cat %s act %u", + ni->ni_mlstate, "mesh action", ia->ia_action); + vap->iv_stats.is_mesh_nolink++; + break; + } if (ia->ia_action < N(meshaction_recv_action)) f = meshaction_recv_action[ia->ia_action]; break; diff --git a/sys/net80211/ieee80211_hwmp.c b/sys/net80211/ieee80211_hwmp.c index 7c8b3f9ec81..07b337cc75e 100644 --- a/sys/net80211/ieee80211_hwmp.c +++ b/sys/net80211/ieee80211_hwmp.c @@ -914,9 +914,6 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni, ieee80211_hwmp_seq preqid; /* last seen preqid for orig */ uint32_t metric = 0; - if (ni == vap->iv_bss || - ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED) - return; /* * Ignore PREQs from us. Could happen because someone forward it * back to us. @@ -1233,10 +1230,6 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni, int is_encap; struct ieee80211_node *ni_encap; - if (ni == vap->iv_bss || - ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED) - return; - IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, "received PREP, orig %6D, targ %6D", prep->prep_origaddr, ":", prep->prep_targetaddr, ":"); @@ -1505,10 +1498,6 @@ hwmp_recv_perr(struct ieee80211vap *vap, struct ieee80211_node *ni, struct ieee80211_meshperr_ie *pperr = NULL; int i, j = 0, forward = 0; - if (ni == vap->iv_bss || - ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED) - return; - IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, "received PERR from %6D", wh->i_addr2, ":"); @@ -1712,9 +1701,7 @@ hwmp_recv_rann(struct ieee80211vap *vap, struct ieee80211_node *ni, struct ieee80211_meshrann_ie prann; uint32_t metric = 0; - if (ni == vap->iv_bss || - ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED || - IEEE80211_ADDR_EQ(rann->rann_addr, vap->iv_myaddr)) + if (IEEE80211_ADDR_EQ(rann->rann_addr, vap->iv_myaddr)) return; rt = ieee80211_mesh_rt_find(vap, rann->rann_addr); From c81ceff7c7fa4d44cef082b4fc196034791dacec Mon Sep 17 00:00:00 2001 From: Monthadar Al Jaberi Date: Thu, 7 Feb 2013 21:22:14 +0000 Subject: [PATCH 0032/1476] Start accepting IEEE80211_ACTION_MESH_GANN frames; * Add IEEE80211_ACTION_MESH_GANN Action frame verification in ieee80211_parse_action; Approved by: adrian (mentor) --- sys/net80211/ieee80211_input.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c index a9acad189b3..ebc4642f497 100644 --- a/sys/net80211/ieee80211_input.c +++ b/sys/net80211/ieee80211_input.c @@ -776,6 +776,10 @@ ieee80211_parse_action(struct ieee80211_node *ni, struct mbuf *m) /* verify something */ break; case IEEE80211_ACTION_MESH_GANN: + IEEE80211_VERIFY_LENGTH(efrm - frm, + sizeof(struct ieee80211_meshgann_ie), + return EINVAL); + break; case IEEE80211_ACTION_MESH_CC: case IEEE80211_ACTION_MESH_MCCA_SREQ: case IEEE80211_ACTION_MESH_MCCA_SREP: From 8904a305ae2b09ef3926bc09d6f428271e3bed02 Mon Sep 17 00:00:00 2001 From: Monthadar Al Jaberi Date: Thu, 7 Feb 2013 21:23:03 +0000 Subject: [PATCH 0033/1476] Mark a mesh path to a mesh gate with a 'G'. Approved by: adrian (mentor) --- sbin/ifconfig/ifieee80211.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sbin/ifconfig/ifieee80211.c b/sbin/ifconfig/ifieee80211.c index c2b767894a1..d0b4917d3b0 100644 --- a/sbin/ifconfig/ifieee80211.c +++ b/sbin/ifconfig/ifieee80211.c @@ -4025,7 +4025,9 @@ list_mesh(int s) (rt->imr_flags & IEEE80211_MESHRT_FLAGS_VALID) ? 'V' : '!', (rt->imr_flags & IEEE80211_MESHRT_FLAGS_PROXY) ? - 'P' : ' '); + 'P' : + (rt->imr_flags & IEEE80211_MESHRT_FLAGS_GATE) ? + 'G' :' '); } } From ed0b544066db4c92731751b87a3939f10f2e0c4e Mon Sep 17 00:00:00 2001 From: Monthadar Al Jaberi Date: Thu, 7 Feb 2013 21:23:43 +0000 Subject: [PATCH 0034/1476] Mesh update: add base Mesh Gate functionality. A Mesh Gate should transmit a Mesh Action frame containing ieee80211_meshgann_ie as its only information element periodically every ieee80211_mesh_gateint ms. Unless the mesh gate is also configure as a ROOT, then these frames should not be send. This is according to 802.11 2012 standard; * Introduce new SYSCTL net.wlan.mesh.gateint, with 10s default; * Add two new functions mesh_gatemode_setup and mesh_gatemode_cb. This is similar to how HWMP setups up a callout; * Add two new action handlers mesh_recv_action_meshgate and mesh_send_action_meshgate; * Added ieee80211_add_meshgate to ieee80211_mesh.h; * Modified mesh_send_action to look similar to hwmp_send_action. This is because we need to send out broadcast management frames. * Introduced a new flag for mesh state IEEE80211_MESHFLAGS_ROOT. This flag is now set by HWMP code when a mesh STA is configured as a ROOT. This is then checked by mesh_gatemode_cb before scheduling a new callout; * Added to new field to ieee80211_mesh_state: + struct callout ms_gatetimer + ieee80211_mesh_seq ms_gateseq; Approved by: adrian (mentor) --- sys/net80211/ieee80211_hwmp.c | 4 + sys/net80211/ieee80211_mesh.c | 197 ++++++++++++++++++++++++++++++++-- sys/net80211/ieee80211_mesh.h | 5 + 3 files changed, 196 insertions(+), 10 deletions(-) diff --git a/sys/net80211/ieee80211_hwmp.c b/sys/net80211/ieee80211_hwmp.c index 07b337cc75e..03051997305 100644 --- a/sys/net80211/ieee80211_hwmp.c +++ b/sys/net80211/ieee80211_hwmp.c @@ -805,19 +805,23 @@ static void hwmp_rootmode_setup(struct ieee80211vap *vap) { struct ieee80211_hwmp_state *hs = vap->iv_hwmp; + struct ieee80211_mesh_state *ms = vap->iv_mesh; switch (hs->hs_rootmode) { case IEEE80211_HWMP_ROOTMODE_DISABLED: callout_drain(&hs->hs_roottimer); + ms->ms_flags &= ~IEEE80211_MESHFLAGS_ROOT; break; case IEEE80211_HWMP_ROOTMODE_NORMAL: case IEEE80211_HWMP_ROOTMODE_PROACTIVE: callout_reset(&hs->hs_roottimer, ieee80211_hwmp_rootint, hwmp_rootmode_cb, vap); + ms->ms_flags |= IEEE80211_MESHFLAGS_ROOT; break; case IEEE80211_HWMP_ROOTMODE_RANN: callout_reset(&hs->hs_roottimer, ieee80211_hwmp_rannint, hwmp_rootmode_rann_cb, vap); + ms->ms_flags |= IEEE80211_MESHFLAGS_ROOT; break; } } diff --git a/sys/net80211/ieee80211_mesh.c b/sys/net80211/ieee80211_mesh.c index 96ba39900cf..0d85ba37987 100644 --- a/sys/net80211/ieee80211_mesh.c +++ b/sys/net80211/ieee80211_mesh.c @@ -68,6 +68,8 @@ static int mesh_select_proto_metric(struct ieee80211vap *, const char *); static void mesh_vattach(struct ieee80211vap *); static int mesh_newstate(struct ieee80211vap *, enum ieee80211_state, int); static void mesh_rt_cleanup_cb(void *); +static void mesh_gatemode_setup(struct ieee80211vap *); +static void mesh_gatemode_cb(void *); static void mesh_linkchange(struct ieee80211_node *, enum ieee80211_mesh_mlstate); static void mesh_checkid(void *, struct ieee80211_node *); @@ -99,6 +101,10 @@ uint32_t mesh_airtime_calc(struct ieee80211_node *); */ static SYSCTL_NODE(_net_wlan, OID_AUTO, mesh, CTLFLAG_RD, 0, "IEEE 802.11s parameters"); +static int ieee80211_mesh_gateint = -1; +SYSCTL_PROC(_net_wlan_mesh, OID_AUTO, gateint, CTLTYPE_INT | CTLFLAG_RW, + &ieee80211_mesh_gateint, 0, ieee80211_sysctl_msecs_ticks, "I", + "mesh gate interval (ms)"); static int ieee80211_mesh_retrytimeout = -1; SYSCTL_PROC(_net_wlan_mesh, OID_AUTO, retrytimeout, CTLTYPE_INT | CTLFLAG_RW, &ieee80211_mesh_retrytimeout, 0, ieee80211_sysctl_msecs_ticks, "I", @@ -133,11 +139,13 @@ static ieee80211_recv_action_func mesh_recv_action_meshpeering_open; static ieee80211_recv_action_func mesh_recv_action_meshpeering_confirm; static ieee80211_recv_action_func mesh_recv_action_meshpeering_close; static ieee80211_recv_action_func mesh_recv_action_meshlmetric; +static ieee80211_recv_action_func mesh_recv_action_meshgate; static ieee80211_send_action_func mesh_send_action_meshpeering_open; static ieee80211_send_action_func mesh_send_action_meshpeering_confirm; static ieee80211_send_action_func mesh_send_action_meshpeering_close; static ieee80211_send_action_func mesh_send_action_meshlmetric; +static ieee80211_send_action_func mesh_send_action_meshgate; static const struct ieee80211_mesh_proto_metric mesh_metric_airtime = { .mpm_descr = "AIRTIME", @@ -497,6 +505,48 @@ mesh_select_proto_metric(struct ieee80211vap *vap, const char *name) } #undef N +static void +mesh_gatemode_setup(struct ieee80211vap *vap) +{ + struct ieee80211_mesh_state *ms = vap->iv_mesh; + + /* + * NB: When a mesh gate is running as a ROOT it shall + * not send out periodic GANNs but instead mark the + * mesh gate flag for the corresponding proactive PREQ + * and RANN frames. + */ + if (ms->ms_flags & IEEE80211_MESHFLAGS_ROOT || + (ms->ms_flags & IEEE80211_MESHFLAGS_GATE) == 0) { + callout_drain(&ms->ms_gatetimer); + return ; + } + callout_reset(&ms->ms_gatetimer, ieee80211_mesh_gateint, + mesh_gatemode_cb, vap); +} + +static void +mesh_gatemode_cb(void *arg) +{ + struct ieee80211vap *vap = (struct ieee80211vap *)arg; + struct ieee80211_mesh_state *ms = vap->iv_mesh; + struct ieee80211_meshgann_ie gann; + + IEEE80211_NOTE(vap, IEEE80211_MSG_MESH, vap->iv_bss, + "%s", "send broadcast GANN"); + + gann.gann_flags = 0; /* Reserved */ + gann.gann_hopcount = 0; + gann.gann_ttl = ms->ms_ttl; + IEEE80211_ADDR_COPY(gann.gann_addr, vap->iv_myaddr); + gann.gann_seq = ms->ms_gateseq++; + gann.gann_interval = ieee80211_mesh_gateint; + + ieee80211_send_action(vap->iv_bss, IEEE80211_ACTION_CAT_MESH, + IEEE80211_ACTION_MESH_GANN, &gann); + mesh_gatemode_setup(vap); +} + static void ieee80211_mesh_init(void) { @@ -507,6 +557,7 @@ ieee80211_mesh_init(void) /* * Setup mesh parameters that depends on the clock frequency. */ + ieee80211_mesh_gateint = msecs_to_ticks(10000); ieee80211_mesh_retrytimeout = msecs_to_ticks(40); ieee80211_mesh_holdingtimeout = msecs_to_ticks(40); ieee80211_mesh_confirmtimeout = msecs_to_ticks(40); @@ -526,6 +577,8 @@ ieee80211_mesh_init(void) mesh_recv_action_meshpeering_close); ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESH, IEEE80211_ACTION_MESH_LMETRIC, mesh_recv_action_meshlmetric); + ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESH, + IEEE80211_ACTION_MESH_GANN, mesh_recv_action_meshgate); ieee80211_send_action_register(IEEE80211_ACTION_CAT_SELF_PROT, IEEE80211_ACTION_MESHPEERING_OPEN, @@ -539,6 +592,9 @@ ieee80211_mesh_init(void) ieee80211_send_action_register(IEEE80211_ACTION_CAT_MESH, IEEE80211_ACTION_MESH_LMETRIC, mesh_send_action_meshlmetric); + ieee80211_send_action_register(IEEE80211_ACTION_CAT_MESH, + IEEE80211_ACTION_MESH_GANN, + mesh_send_action_meshgate); /* * Register Airtime Link Metric. @@ -617,6 +673,8 @@ mesh_vattach(struct ieee80211vap *vap) TAILQ_INIT(&ms->ms_routes); mtx_init(&ms->ms_rt_lock, "MBSS", "802.11s routing table", MTX_DEF); callout_init(&ms->ms_cleantimer, CALLOUT_MPSAFE); + callout_init(&ms->ms_gatetimer, CALLOUT_MPSAFE); + ms->ms_gateseq = 0; mesh_select_proto_metric(vap, "AIRTIME"); KASSERT(ms->ms_pmetric, ("ms_pmetric == NULL")); mesh_select_proto_path(vap, "HWMP"); @@ -645,8 +703,10 @@ mesh_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) if (ostate != IEEE80211_S_SCAN) ieee80211_cancel_scan(vap); /* background scan */ ni = vap->iv_bss; /* NB: no reference held */ - if (nstate != IEEE80211_S_RUN && ostate == IEEE80211_S_RUN) + if (nstate != IEEE80211_S_RUN && ostate == IEEE80211_S_RUN) { callout_drain(&ms->ms_cleantimer); + callout_drain(&ms->ms_gatetimer); + } switch (nstate) { case IEEE80211_S_INIT: switch (ostate) { @@ -771,6 +831,7 @@ mesh_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) ieee80211_node_authorize(vap->iv_bss); callout_reset(&ms->ms_cleantimer, ms->ms_ppath->mpp_inact, mesh_rt_cleanup_cb, vap); + mesh_gatemode_setup(vap); break; default: break; @@ -2300,19 +2361,77 @@ mesh_recv_action_meshlmetric(struct ieee80211_node *ni, return 0; } +/* + * Mesh Gate Announcement handling. + */ static int -mesh_send_action(struct ieee80211_node *ni, struct mbuf *m) +mesh_recv_action_meshgate(struct ieee80211_node *ni, + const struct ieee80211_frame *wh, + const uint8_t *frm, const uint8_t *efrm) { + struct ieee80211vap *vap = ni->ni_vap; + struct ieee80211_mesh_route *rt_gate; + const struct ieee80211_meshgann_ie *ie = + (const struct ieee80211_meshgann_ie *) + (frm+2); /* action + code */ + + IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, ie->gann_addr, + "%s", "received GANN from meshgate"); + + rt_gate = ieee80211_mesh_rt_find(vap, ie->gann_addr); + if (rt_gate != NULL && + rt_gate->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) + rt_gate->rt_flags |= IEEE80211_MESHRT_FLAGS_GATE; + + return 0; +} + +static int +mesh_send_action(struct ieee80211_node *ni, + const uint8_t sa[IEEE80211_ADDR_LEN], + const uint8_t da[IEEE80211_ADDR_LEN], + struct mbuf *m) +{ + struct ieee80211vap *vap = ni->ni_vap; + struct ieee80211com *ic = ni->ni_ic; struct ieee80211_bpf_params params; + struct ieee80211_frame *wh; + + KASSERT(ni != NULL, ("null node")); + + if (vap->iv_state == IEEE80211_S_CAC) { + IEEE80211_NOTE(vap, IEEE80211_MSG_OUTPUT, ni, + "block %s frame in CAC state", "Mesh action"); + vap->iv_stats.is_tx_badstate++; + ieee80211_free_node(ni); + m_freem(m); + return EIO; /* XXX */ + } + + M_PREPEND(m, sizeof(struct ieee80211_frame), M_DONTWAIT); + if (m == NULL) { + ieee80211_free_node(ni); + return ENOMEM; + } + + wh = mtod(m, struct ieee80211_frame *); + ieee80211_send_setup(ni, m, + IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_ACTION, + IEEE80211_NONQOS_TID, sa, da, sa); + m->m_flags |= M_ENCAP; /* mark encapsulated */ memset(¶ms, 0, sizeof(params)); params.ibp_pri = WME_AC_VO; params.ibp_rate0 = ni->ni_txparms->mgmtrate; - /* XXX ucast/mcast */ - params.ibp_try0 = ni->ni_txparms->maxretry; + if (IEEE80211_IS_MULTICAST(da)) + params.ibp_try0 = 1; + else + params.ibp_try0 = ni->ni_txparms->maxretry; params.ibp_power = ni->ni_txpower; - return ieee80211_mgmt_output(ni, m, IEEE80211_FC0_SUBTYPE_ACTION, - ¶ms); + + IEEE80211_NODE_STAT(ni, tx_mgmt); + + return ic->ic_raw_xmit(ni, m, ¶ms); } #define ADDSHORT(frm, v) do { \ @@ -2380,7 +2499,7 @@ mesh_send_action_meshpeering_open(struct ieee80211_node *ni, frm = ieee80211_add_meshpeer(frm, IEEE80211_ACTION_MESHPEERING_OPEN, args[0], 0, 0); m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *); - return mesh_send_action(ni, m); + return mesh_send_action(ni, vap->iv_myaddr, ni->ni_macaddr, m); } else { vap->iv_stats.is_tx_nobuf++; ieee80211_free_node(ni); @@ -2448,7 +2567,7 @@ mesh_send_action_meshpeering_confirm(struct ieee80211_node *ni, IEEE80211_ACTION_MESHPEERING_CONFIRM, args[0], args[1], 0); m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *); - return mesh_send_action(ni, m); + return mesh_send_action(ni, vap->iv_myaddr, ni->ni_macaddr, m); } else { vap->iv_stats.is_tx_nobuf++; ieee80211_free_node(ni); @@ -2497,7 +2616,7 @@ mesh_send_action_meshpeering_close(struct ieee80211_node *ni, IEEE80211_ACTION_MESHPEERING_CLOSE, args[0], args[1], args[2]); m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *); - return mesh_send_action(ni, m); + return mesh_send_action(ni, vap->iv_myaddr, ni->ni_macaddr, m); } else { vap->iv_stats.is_tx_nobuf++; ieee80211_free_node(ni); @@ -2545,7 +2664,46 @@ mesh_send_action_meshlmetric(struct ieee80211_node *ni, frm = ieee80211_add_meshlmetric(frm, ie->lm_flags, ie->lm_metric); m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *); - return mesh_send_action(ni, m); + return mesh_send_action(ni, vap->iv_myaddr, ni->ni_macaddr, m); + } else { + vap->iv_stats.is_tx_nobuf++; + ieee80211_free_node(ni); + return ENOMEM; + } +} + +static int +mesh_send_action_meshgate(struct ieee80211_node *ni, + int category, int action, void *arg0) +{ + struct ieee80211vap *vap = ni->ni_vap; + struct ieee80211com *ic = ni->ni_ic; + struct ieee80211_meshgann_ie *ie = arg0; + struct mbuf *m; + uint8_t *frm; + + IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, + "ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n", __func__, __LINE__, + ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)+1); + ieee80211_ref_node(ni); + + m = ieee80211_getmgtframe(&frm, + ic->ic_headroom + sizeof(struct ieee80211_frame), + sizeof(uint16_t) + /* action+category */ + IEEE80211_MESHGANN_BASE_SZ + ); + if (m != NULL) { + /* + * mesh link metric + * [1] category + * [1] action + * [tlv] mesh gate annoucement + */ + *frm++ = category; + *frm++ = action; + frm = ieee80211_add_meshgate(frm, ie); + m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *); + return mesh_send_action(ni, vap->iv_myaddr, broadcastaddr, m); } else { vap->iv_stats.is_tx_nobuf++; ieee80211_free_node(ni); @@ -2909,6 +3067,24 @@ ieee80211_add_meshlmetric(uint8_t *frm, uint8_t flags, uint32_t metric) ADDWORD(frm, metric); return frm; } + +/* + * Add a Mesh Gate Announcement IE to a frame. + */ +uint8_t * +ieee80211_add_meshgate(uint8_t *frm, struct ieee80211_meshgann_ie *ie) +{ + *frm++ = IEEE80211_ELEMID_MESHGANN; /* ie */ + *frm++ = IEEE80211_MESHGANN_BASE_SZ; /* len */ + *frm++ = ie->gann_flags; + *frm++ = ie->gann_hopcount; + *frm++ = ie->gann_ttl; + IEEE80211_ADDR_COPY(frm, ie->gann_addr); + frm += 6; + ADDWORD(frm, ie->gann_seq); + ADDSHORT(frm, ie->gann_interval); + return frm; +} #undef ADDSHORT #undef ADDWORD @@ -3113,6 +3289,7 @@ mesh_ioctl_set80211(struct ieee80211vap *vap, struct ieee80211req *ireq) ms->ms_flags |= IEEE80211_MESHFLAGS_FWD; else ms->ms_flags &= ~IEEE80211_MESHFLAGS_FWD; + mesh_gatemode_setup(vap); break; case IEEE80211_IOC_MESH_GATE: if (ireq->i_val) diff --git a/sys/net80211/ieee80211_mesh.h b/sys/net80211/ieee80211_mesh.h index 1e14357e7f2..4447a3f0ced 100644 --- a/sys/net80211/ieee80211_mesh.h +++ b/sys/net80211/ieee80211_mesh.h @@ -502,9 +502,12 @@ struct ieee80211_mesh_state { #define IEEE80211_MESHFLAGS_AP 0x01 /* accept peers */ #define IEEE80211_MESHFLAGS_GATE 0x02 /* mesh gate role */ #define IEEE80211_MESHFLAGS_FWD 0x04 /* forward packets */ +#define IEEE80211_MESHFLAGS_ROOT 0x08 /* configured as root */ uint8_t ms_flags; struct mtx ms_rt_lock; struct callout ms_cleantimer; + struct callout ms_gatetimer; + ieee80211_mesh_seq ms_gateseq; TAILQ_HEAD(, ieee80211_mesh_route) ms_routes; struct ieee80211_mesh_proto_metric *ms_pmetric; struct ieee80211_mesh_proto_path *ms_ppath; @@ -537,6 +540,8 @@ uint8_t * ieee80211_add_meshconf(uint8_t *, struct ieee80211vap *); uint8_t * ieee80211_add_meshpeer(uint8_t *, uint8_t, uint16_t, uint16_t, uint16_t); uint8_t * ieee80211_add_meshlmetric(uint8_t *, uint8_t, uint32_t); +uint8_t * ieee80211_add_meshgate(uint8_t *, + struct ieee80211_meshgann_ie *); void ieee80211_mesh_node_init(struct ieee80211vap *, struct ieee80211_node *); From eb64a9137bc03b476ecebe99844f9106a7665fbf Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Thu, 7 Feb 2013 21:24:10 +0000 Subject: [PATCH 0035/1476] sh: Fix a comment. --- bin/sh/parser.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/sh/parser.h b/bin/sh/parser.h index 9a996d04a60..f80d9177878 100644 --- a/bin/sh/parser.h +++ b/bin/sh/parser.h @@ -39,7 +39,7 @@ #define CTLENDVAR '\371' #define CTLBACKQ '\372' #define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */ -/* CTLBACKQ | CTLQUOTE == '\205' */ +/* CTLBACKQ | CTLQUOTE == '\373' */ #define CTLARI '\374' #define CTLENDARI '\375' #define CTLQUOTEMARK '\376' From 4cc361aa037bca0c9838797f3a4f12d9c9c48b43 Mon Sep 17 00:00:00 2001 From: Monthadar Al Jaberi Date: Thu, 7 Feb 2013 21:24:20 +0000 Subject: [PATCH 0036/1476] Propagate GANN frames, and store know gate info. * Modified mesh_recv_action_meshgate to do following: + if mesh STA already knows the mesh gate of the recevied GANN frame + if mesh gate is know, check seq number according to 802.11 standard + if mesh gate is not know, add it to the list of known mesh gates + if forwarding is enabled and ttl >= 1 then propagate the GANN frame; * Declare a new malloc type M_80211_MESH_GT_RT; * Declare a struct to store GANN information, ieee80211_mesh_gate_route. And add it as a TAILQ list to ieee80211_mesh_state; Approved by: adrian (mentor) --- sys/net80211/ieee80211_mesh.c | 72 ++++++++++++++++++++++++++++++++--- sys/net80211/ieee80211_mesh.h | 12 ++++++ 2 files changed, 79 insertions(+), 5 deletions(-) diff --git a/sys/net80211/ieee80211_mesh.c b/sys/net80211/ieee80211_mesh.c index 0d85ba37987..0c3d77da592 100644 --- a/sys/net80211/ieee80211_mesh.c +++ b/sys/net80211/ieee80211_mesh.c @@ -171,7 +171,8 @@ MALLOC_DEFINE(M_80211_MESH_PERR, "80211perr", "802.11 MESH Path Error frame"); /* The longer one of the lifetime should be stored as new lifetime */ #define MESH_ROUTE_LIFETIME_MAX(a, b) (a > b ? a : b) -MALLOC_DEFINE(M_80211_MESH_RT, "80211mesh", "802.11s routing table"); +MALLOC_DEFINE(M_80211_MESH_RT, "80211mesh_rt", "802.11s routing table"); +MALLOC_DEFINE(M_80211_MESH_GT_RT, "80211mesh_gt", "802.11s known gates table"); /* * Helper functions to manipulate the Mesh routing table. @@ -670,6 +671,7 @@ mesh_vattach(struct ieee80211vap *vap) ms->ms_seq = 0; ms->ms_flags = (IEEE80211_MESHFLAGS_AP | IEEE80211_MESHFLAGS_FWD); ms->ms_ttl = IEEE80211_MESH_DEFAULT_TTL; + TAILQ_INIT(&ms->ms_known_gates); TAILQ_INIT(&ms->ms_routes); mtx_init(&ms->ms_rt_lock, "MBSS", "802.11s routing table", MTX_DEF); callout_init(&ms->ms_cleantimer, CALLOUT_MPSAFE); @@ -2370,18 +2372,78 @@ mesh_recv_action_meshgate(struct ieee80211_node *ni, const uint8_t *frm, const uint8_t *efrm) { struct ieee80211vap *vap = ni->ni_vap; + struct ieee80211_mesh_state *ms = vap->iv_mesh; + struct ieee80211_mesh_gate_route *gr, *next; struct ieee80211_mesh_route *rt_gate; + struct ieee80211_meshgann_ie pgann; + int found = 0; const struct ieee80211_meshgann_ie *ie = (const struct ieee80211_meshgann_ie *) (frm+2); /* action + code */ - IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, ie->gann_addr, - "%s", "received GANN from meshgate"); + if (IEEE80211_ADDR_EQ(vap->iv_myaddr, ie->gann_addr)) + return 0; - rt_gate = ieee80211_mesh_rt_find(vap, ie->gann_addr); + IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, ni->ni_macaddr, + "received GANN, meshgate: %6D (seq %u)", ie->gann_addr, ":", + ie->gann_seq); + + if (ms == NULL) + return (0); + MESH_RT_LOCK(ms); + TAILQ_FOREACH_SAFE(gr, &ms->ms_known_gates, gr_next, next) { + if (!IEEE80211_ADDR_EQ(gr->gr_addr, ie->gann_addr)) + continue; + if (ie->gann_seq <= gr->gr_lastseq) { + IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_MESH, + ni->ni_macaddr, NULL, + "GANN old seqno %u <= %u", + ie->gann_seq, gr->gr_lastseq); + MESH_RT_UNLOCK(ms); + return (0); + } + /* corresponding mesh gate found & GANN accepted */ + found = 1; + break; + + } + if (found == 0) { + /* this GANN is from a new mesh Gate add it to known table. */ + IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, ie->gann_addr, + "stored new GANN information, seq %u.", ie->gann_seq); + gr = malloc(ALIGN(sizeof(struct ieee80211_mesh_gate_route)), + M_80211_MESH_GT_RT, M_NOWAIT | M_ZERO); + IEEE80211_ADDR_COPY(gr->gr_addr, ie->gann_addr); + TAILQ_INSERT_TAIL(&ms->ms_known_gates, gr, gr_next); + } + gr->gr_lastseq = ie->gann_seq; + + /* check if we have a path to this gate */ + rt_gate = mesh_rt_find_locked(ms, gr->gr_addr); if (rt_gate != NULL && - rt_gate->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) + rt_gate->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) { + gr->gr_route = rt_gate; rt_gate->rt_flags |= IEEE80211_MESHRT_FLAGS_GATE; + } + + MESH_RT_UNLOCK(ms); + + /* popagate only if decremented ttl >= 1 && forwarding is enabled */ + if ((ie->gann_ttl - 1) < 1 && + !(ms->ms_flags & IEEE80211_MESHFLAGS_FWD)) + return 0; + pgann.gann_flags = ie->gann_flags; /* Reserved */ + pgann.gann_hopcount = ie->gann_hopcount + 1; + pgann.gann_ttl = ie->gann_ttl - 1; + IEEE80211_ADDR_COPY(pgann.gann_addr, ie->gann_addr); + pgann.gann_seq = ie->gann_seq; + pgann.gann_interval = ie->gann_interval; + + IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, ie->gann_addr, + "%s", "propagate GANN"); + + ieee80211_send_action(vap->iv_bss, IEEE80211_ACTION_CAT_MESH, + IEEE80211_ACTION_MESH_GANN, &pgann); return 0; } diff --git a/sys/net80211/ieee80211_mesh.h b/sys/net80211/ieee80211_mesh.h index 4447a3f0ced..6d4a2f74f90 100644 --- a/sys/net80211/ieee80211_mesh.h +++ b/sys/net80211/ieee80211_mesh.h @@ -405,6 +405,7 @@ MALLOC_DECLARE(M_80211_MESH_PREP); MALLOC_DECLARE(M_80211_MESH_PERR); MALLOC_DECLARE(M_80211_MESH_RT); +MALLOC_DECLARE(M_80211_MESH_GT_RT); /* * Basic forwarding information: * o Destination MAC @@ -437,6 +438,16 @@ struct ieee80211_mesh_route { }; #define IEEE80211_MESH_ROUTE_PRIV(rt, cast) ((cast *)rt->rt_priv) +/* + * Stored information about known mesh gates. + */ +struct ieee80211_mesh_gate_route { + TAILQ_ENTRY(ieee80211_mesh_gate_route) gr_next; + uint8_t gr_addr[IEEE80211_ADDR_LEN]; + uint32_t gr_lastseq; + struct ieee80211_mesh_route *gr_route; +}; + #define IEEE80211_MESH_PROTO_DSZ 12 /* description size */ /* * Mesh Path Selection Protocol. @@ -508,6 +519,7 @@ struct ieee80211_mesh_state { struct callout ms_cleantimer; struct callout ms_gatetimer; ieee80211_mesh_seq ms_gateseq; + TAILQ_HEAD(, ieee80211_mesh_gate_route) ms_known_gates; TAILQ_HEAD(, ieee80211_mesh_route) ms_routes; struct ieee80211_mesh_proto_metric *ms_pmetric; struct ieee80211_mesh_proto_path *ms_ppath; From a21c6123ed09380ffabf12b32122f4ced2fb732b Mon Sep 17 00:00:00 2001 From: Monthadar Al Jaberi Date: Thu, 7 Feb 2013 21:24:52 +0000 Subject: [PATCH 0037/1476] Mark root mesh as gate when mesh gate flag set. * Add function ieee80211_mesh_mark_gate in ieee80211_mesh.h; * When received a proactive PREQ or RANN with corresponding mesh gate flag set, create a new entry in the known mesh gate list; Approved by: adrian (mentor) --- sys/net80211/ieee80211_hwmp.c | 19 ++++++++++++++++++ sys/net80211/ieee80211_mesh.c | 37 +++++++++++++++++++++++++++++++++++ sys/net80211/ieee80211_mesh.h | 3 +++ 3 files changed, 59 insertions(+) diff --git a/sys/net80211/ieee80211_hwmp.c b/sys/net80211/ieee80211_hwmp.c index 03051997305..c740afd500b 100644 --- a/sys/net80211/ieee80211_hwmp.c +++ b/sys/net80211/ieee80211_hwmp.c @@ -1092,6 +1092,16 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni, IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, "root mesh station @ %6D", preq->preq_origaddr, ":"); + /* Check if root is a mesh gate, mark it */ + if (preq->preq_flags & IEEE80211_MESHPREQ_FLAGS_GATE) { + struct ieee80211_mesh_gate_route *gr; + + rtorig->rt_flags |= IEEE80211_MESHRT_FLAGS_GATE; + gr = ieee80211_mesh_mark_gate(vap, preq->preq_origaddr, + rtorig); + gr->gr_lastseq = 0; /* NOT GANN */ + } + /* * Reply with a PREP if we don't have a path to the root * or if the root sent us a proactive PREQ. @@ -1745,6 +1755,15 @@ hwmp_recv_rann(struct ieee80211vap *vap, struct ieee80211_node *ni, } } hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route); + /* Check if root is a mesh gate, mark it */ + if (rann->rann_flags & IEEE80211_MESHRANN_FLAGS_GATE) { + struct ieee80211_mesh_gate_route *gr; + + rt->rt_flags |= IEEE80211_MESHRT_FLAGS_GATE; + gr = ieee80211_mesh_mark_gate(vap, rann->rann_addr, + rt); + gr->gr_lastseq = 0; /* NOT GANN */ + } /* discovery timeout */ ieee80211_mesh_rt_update(rt, ticks_to_msecs(ieee80211_hwmp_roottimeout)); diff --git a/sys/net80211/ieee80211_mesh.c b/sys/net80211/ieee80211_mesh.c index 0c3d77da592..9449c62973f 100644 --- a/sys/net80211/ieee80211_mesh.c +++ b/sys/net80211/ieee80211_mesh.c @@ -854,6 +854,43 @@ mesh_rt_cleanup_cb(void *arg) mesh_rt_cleanup_cb, vap); } +/* + * Mark a mesh STA as gate and return a pointer to it. + * If this is first time, we create a new gate route. + * Always update the path route to this mesh gate. + */ +struct ieee80211_mesh_gate_route * +ieee80211_mesh_mark_gate(struct ieee80211vap *vap, const uint8_t *addr, + struct ieee80211_mesh_route *rt) +{ + struct ieee80211_mesh_state *ms = vap->iv_mesh; + struct ieee80211_mesh_gate_route *gr = NULL, *next; + int found = 0; + + MESH_RT_LOCK(ms); + TAILQ_FOREACH_SAFE(gr, &ms->ms_known_gates, gr_next, next) { + if (IEEE80211_ADDR_EQ(gr->gr_addr, addr)) { + found = 1; + break; + } + } + + if (!found) { + /* New mesh gate add it to known table. */ + IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, addr, + "%s", "stored new gate information from pro-PREQ."); + gr = malloc(ALIGN(sizeof(struct ieee80211_mesh_gate_route)), + M_80211_MESH_GT_RT, M_NOWAIT | M_ZERO); + IEEE80211_ADDR_COPY(gr->gr_addr, addr); + TAILQ_INSERT_TAIL(&ms->ms_known_gates, gr, gr_next); + } + gr->gr_route = rt; + /* TODO: link from path route to gate route */ + MESH_RT_UNLOCK(ms); + + return gr; +} + /* * Helper function to note the Mesh Peer Link FSM change. diff --git a/sys/net80211/ieee80211_mesh.h b/sys/net80211/ieee80211_mesh.h index 6d4a2f74f90..9023eee2267 100644 --- a/sys/net80211/ieee80211_mesh.h +++ b/sys/net80211/ieee80211_mesh.h @@ -566,6 +566,9 @@ void ieee80211_mesh_init_neighbor(struct ieee80211_node *, const struct ieee80211_scanparams *); void ieee80211_mesh_update_beacon(struct ieee80211vap *, struct ieee80211_beacon_offsets *); +struct ieee80211_mesh_gate_route * + ieee80211_mesh_mark_gate(struct ieee80211vap *, + const uint8_t *, struct ieee80211_mesh_route *); /* * Return non-zero if proxy operation is enabled. From b79858dac69e571d2280691f8f12e41b09e34bd4 Mon Sep 17 00:00:00 2001 From: Monthadar Al Jaberi Date: Thu, 7 Feb 2013 21:25:32 +0000 Subject: [PATCH 0038/1476] Send frames to mesh gate if 11s discovery fails. * Send frames that have no path to a known valid Mesh Gate; * Added the function ieee80211_mesh_forward_to_gates that sends the frame to the first found Mesh Gate in the forwarding information; * If we try to discover again while we are discovering queue frame, the discovery callout will send the frames either to mesh gates or discards them silently; * Queue frame also if we try to discover to frequently; Approved by: adrian (mentor) --- sys/net80211/ieee80211_hwmp.c | 17 +++++---- sys/net80211/ieee80211_mesh.c | 65 +++++++++++++++++++++++++++++++++++ sys/net80211/ieee80211_mesh.h | 2 ++ 3 files changed, 78 insertions(+), 6 deletions(-) diff --git a/sys/net80211/ieee80211_hwmp.c b/sys/net80211/ieee80211_hwmp.c index c740afd500b..52a315298e4 100644 --- a/sys/net80211/ieee80211_hwmp.c +++ b/sys/net80211/ieee80211_hwmp.c @@ -1839,12 +1839,11 @@ hwmp_rediscover_cb(void *arg) hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route); if (hr->hr_preqretries >= ieee80211_hwmp_maxpreq_retries) { - IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY, - rt->rt_dest, NULL, "%s", - "no valid path , max number of discovery, send GATE"); - /* TODO: send to known gates */ + IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_ANY, + rt->rt_dest, "%s", + "max number of discovery, send queued frames to GATE"); + ieee80211_mesh_forward_to_gates(vap, rt); vap->iv_stats.is_mesh_fwd_nopath++; - rt->rt_flags = 0; /* Mark invalid */ return ; /* XXX: flush queue? */ } @@ -1914,6 +1913,12 @@ hwmp_discover(struct ieee80211vap *vap, } hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route); + if (rt->rt_flags & IEEE80211_MESHRT_FLAGS_DISCOVER) { + IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_HWMP, dest, + "%s", "already discovering queue frame until path found"); + sendpreq = 1; + goto done; + } if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0) { if (hr->hr_lastdiscovery != 0 && (ticks - hr->hr_lastdiscovery < @@ -1921,7 +1926,7 @@ hwmp_discover(struct ieee80211vap *vap, IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY, dest, NULL, "%s", "too frequent discovery requeust"); - /* XXX: stats? */ + sendpreq = 1; goto done; } hr->hr_lastdiscovery = ticks; diff --git a/sys/net80211/ieee80211_mesh.c b/sys/net80211/ieee80211_mesh.c index 9449c62973f..f8eb30bc4ae 100644 --- a/sys/net80211/ieee80211_mesh.c +++ b/sys/net80211/ieee80211_mesh.c @@ -1021,6 +1021,71 @@ mesh_find_txnode(struct ieee80211vap *vap, return ieee80211_find_txnode(vap, rt->rt_nexthop); } +/* + * Forward the queued frames to known valid mesh gates. + * Assume destination to be outside the MBSS (i.e. proxy entry), + * If no valid mesh gates are known silently discard queued frames. + * If there is no 802.2 path route will be timedout. + */ +void +ieee80211_mesh_forward_to_gates(struct ieee80211vap *vap, + struct ieee80211_mesh_route *rt_dest) +{ + struct ieee80211com *ic = vap->iv_ic; + struct ieee80211_mesh_state *ms = vap->iv_mesh; + struct ifnet *ifp = vap->iv_ifp; + struct ieee80211_mesh_route *rt_gate; + struct ieee80211_mesh_gate_route *gr = NULL, *gr_next; + struct mbuf *m, *next; + int gates_found = 0; + + KASSERT( rt_dest->rt_flags == IEEE80211_MESHRT_FLAGS_DISCOVER, + ("Route is not marked with IEEE80211_MESHRT_FLAGS_DISCOVER")); + + /* XXX: send to more than one valid mash gate */ + MESH_RT_LOCK(ms); + TAILQ_FOREACH_SAFE(gr, &ms->ms_known_gates, gr_next, gr_next) { + rt_gate = gr->gr_route; + if (rt_gate == NULL) { + IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_HWMP, + rt_dest->rt_dest, + "mesh gate with no path %6D", + gr->gr_addr, ":"); + continue; + } + gates_found = 1; + /* convert route to a proxy route */ + rt_dest->rt_flags = IEEE80211_MESHRT_FLAGS_PROXY | + IEEE80211_MESHRT_FLAGS_VALID; + rt_dest->rt_ext_seq = 1; /* random value */ + IEEE80211_ADDR_COPY(rt_dest->rt_mesh_gate, rt_gate->rt_dest); + IEEE80211_ADDR_COPY(rt_dest->rt_nexthop, rt_gate->rt_nexthop); + rt_dest->rt_metric = rt_gate->rt_metric; + rt_dest->rt_nhops = rt_gate->rt_nhops; + ieee80211_mesh_rt_update(rt_dest, ms->ms_ppath->mpp_inact); + MESH_RT_UNLOCK(ms); + m = ieee80211_ageq_remove(&ic->ic_stageq, + (struct ieee80211_node *)(uintptr_t) + ieee80211_mac_hash(ic, rt_dest->rt_dest)); + for (; m != NULL; m = next) { + next = m->m_nextpkt; + m->m_nextpkt = NULL; + IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_HWMP, rt_dest->rt_dest, + "flush queued frame %p len %d", m, m->m_pkthdr.len); + ifp->if_transmit(ifp, m); + } + MESH_RT_LOCK(ms); + } + + if (gates_found == 0) { + rt_dest->rt_flags = 0; /* Mark invalid */ + IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_HWMP, rt_dest->rt_dest, + "%s", "no mesh gate found, or no path setup for mesh gate yet"); + } + MESH_RT_UNLOCK(ms); + +} + /* * Forward the specified frame. * Decrement the TTL and set TA to our MAC address. diff --git a/sys/net80211/ieee80211_mesh.h b/sys/net80211/ieee80211_mesh.h index 9023eee2267..84a3ef743a5 100644 --- a/sys/net80211/ieee80211_mesh.h +++ b/sys/net80211/ieee80211_mesh.h @@ -569,6 +569,8 @@ void ieee80211_mesh_update_beacon(struct ieee80211vap *, struct ieee80211_mesh_gate_route * ieee80211_mesh_mark_gate(struct ieee80211vap *, const uint8_t *, struct ieee80211_mesh_route *); +void ieee80211_mesh_forward_to_gates(struct ieee80211vap *, + struct ieee80211_mesh_route *); /* * Return non-zero if proxy operation is enabled. From 15254d455e6297aea4cc60b82fa1cf094c59a338 Mon Sep 17 00:00:00 2001 From: Monthadar Al Jaberi Date: Thu, 7 Feb 2013 21:26:06 +0000 Subject: [PATCH 0039/1476] Mesh gate code to transmit to all mesh gates. * Modified mesh_find_txnode to be able to handle proxy marked entries by recursively calling itself to find the txnode towards the active mesh gate; * Mesh Gate: Added a new function that transmits data frames similar to ieee80211_start; * Modified ieee80211_mesh_forward_to_gates so that: + Frames are duplicated and sent to each valid Mesh Gate; + Route is marked invalid before return of function, this is because we dont know yet which Mesh Gate is we will use; Approved by: adrian (mentor) --- sys/net80211/ieee80211_mesh.c | 192 +++++++++++++++++++++++++++++----- 1 file changed, 167 insertions(+), 25 deletions(-) diff --git a/sys/net80211/ieee80211_mesh.c b/sys/net80211/ieee80211_mesh.c index f8eb30bc4ae..1cc441924b4 100644 --- a/sys/net80211/ieee80211_mesh.c +++ b/sys/net80211/ieee80211_mesh.c @@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -79,6 +80,8 @@ static int mesh_checkpseq(struct ieee80211vap *, static struct ieee80211_node * mesh_find_txnode(struct ieee80211vap *, const uint8_t [IEEE80211_ADDR_LEN]); +static void mesh_transmit_to_gate(struct ieee80211vap *, struct mbuf *, + struct ieee80211_mesh_route *); static void mesh_forward(struct ieee80211vap *, struct mbuf *, const struct ieee80211_meshcntl *); static int mesh_input(struct ieee80211_node *, struct mbuf *, int, int); @@ -1011,21 +1014,151 @@ mesh_find_txnode(struct ieee80211vap *vap, rt = ieee80211_mesh_rt_find(vap, dest); if (rt == NULL) return NULL; - if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0 || - (rt->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY)) { + if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0) { IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, dest, - "%s: !valid or proxy, flags 0x%x", __func__, rt->rt_flags); + "%s: !valid, flags 0x%x", __func__, rt->rt_flags); /* XXX stat */ return NULL; } + if (rt->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY) { + rt = ieee80211_mesh_rt_find(vap, rt->rt_mesh_gate); + if (rt == NULL) return NULL; + if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0) { + IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, dest, + "%s: meshgate !valid, flags 0x%x", __func__, + rt->rt_flags); + /* XXX stat */ + return NULL; + } + } return ieee80211_find_txnode(vap, rt->rt_nexthop); } +static void +mesh_transmit_to_gate(struct ieee80211vap *vap, struct mbuf *m, + struct ieee80211_mesh_route *rt_gate) +{ + struct ifnet *ifp = vap->iv_ifp; + struct ieee80211com *ic = vap->iv_ic; + struct ifnet *parent = ic->ic_ifp; + struct ieee80211_node *ni; + struct ether_header *eh; + int error; + + eh = mtod(m, struct ether_header *); + ni = mesh_find_txnode(vap, rt_gate->rt_dest); + if (ni == NULL) { + ifp->if_oerrors++; + m_freem(m); + return; + } + + if ((ni->ni_flags & IEEE80211_NODE_PWR_MGT) && + (m->m_flags & M_PWR_SAV) == 0) { + /* + * Station in power save mode; pass the frame + * to the 802.11 layer and continue. We'll get + * the frame back when the time is right. + * XXX lose WDS vap linkage? + */ + (void) ieee80211_pwrsave(ni, m); + ieee80211_free_node(ni); + return; + } + + /* calculate priority so drivers can find the tx queue */ + if (ieee80211_classify(ni, m)) { + IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_OUTPUT, + eh->ether_dhost, NULL, + "%s", "classification failure"); + vap->iv_stats.is_tx_classify++; + ifp->if_oerrors++; + m_freem(m); + ieee80211_free_node(ni); + return; + } + /* + * Stash the node pointer. Note that we do this after + * any call to ieee80211_dwds_mcast because that code + * uses any existing value for rcvif to identify the + * interface it (might have been) received on. + */ + m->m_pkthdr.rcvif = (void *)ni; + + BPF_MTAP(ifp, m); /* 802.3 tx */ + + /* + * Check if A-MPDU tx aggregation is setup or if we + * should try to enable it. The sta must be associated + * with HT and A-MPDU enabled for use. When the policy + * routine decides we should enable A-MPDU we issue an + * ADDBA request and wait for a reply. The frame being + * encapsulated will go out w/o using A-MPDU, or possibly + * it might be collected by the driver and held/retransmit. + * The default ic_ampdu_enable routine handles staggering + * ADDBA requests in case the receiver NAK's us or we are + * otherwise unable to establish a BA stream. + */ + if ((ni->ni_flags & IEEE80211_NODE_AMPDU_TX) && + (vap->iv_flags_ht & IEEE80211_FHT_AMPDU_TX) && + (m->m_flags & M_EAPOL) == 0) { + int tid = WME_AC_TO_TID(M_WME_GETAC(m)); + struct ieee80211_tx_ampdu *tap = &ni->ni_tx_ampdu[tid]; + + ieee80211_txampdu_count_packet(tap); + if (IEEE80211_AMPDU_RUNNING(tap)) { + /* + * Operational, mark frame for aggregation. + * + * XXX do tx aggregation here + */ + m->m_flags |= M_AMPDU_MPDU; + } else if (!IEEE80211_AMPDU_REQUESTED(tap) && + ic->ic_ampdu_enable(ni, tap)) { + /* + * Not negotiated yet, request service. + */ + ieee80211_ampdu_request(ni, tap); + /* XXX hold frame for reply? */ + } + } +#ifdef IEEE80211_SUPPORT_SUPERG + else if (IEEE80211_ATH_CAP(vap, ni, IEEE80211_NODE_FF)) { + m = ieee80211_ff_check(ni, m); + if (m == NULL) { + /* NB: any ni ref held on stageq */ + return; + } + } +#endif /* IEEE80211_SUPPORT_SUPERG */ + if (__predict_true((vap->iv_caps & IEEE80211_C_8023ENCAP) == 0)) { + /* + * Encapsulate the packet in prep for transmission. + */ + m = ieee80211_encap(vap, ni, m); + if (m == NULL) { + /* NB: stat+msg handled in ieee80211_encap */ + ieee80211_free_node(ni); + return; + } + } + error = parent->if_transmit(parent, m); + if (error != 0) { + m_freem(m); + ieee80211_free_node(ni); + } else { + ifp->if_opackets++; + } + ic->ic_lastdata = ticks; +} + /* * Forward the queued frames to known valid mesh gates. * Assume destination to be outside the MBSS (i.e. proxy entry), * If no valid mesh gates are known silently discard queued frames. - * If there is no 802.2 path route will be timedout. + * After transmitting frames to all known valid mesh gates, this route + * will be marked invalid, and a new path discovery will happen in the hopes + * that (at least) one of the mesh gates have a new proxy entry for us to use. */ void ieee80211_mesh_forward_to_gates(struct ieee80211vap *vap, @@ -1033,17 +1166,20 @@ ieee80211_mesh_forward_to_gates(struct ieee80211vap *vap, { struct ieee80211com *ic = vap->iv_ic; struct ieee80211_mesh_state *ms = vap->iv_mesh; - struct ifnet *ifp = vap->iv_ifp; struct ieee80211_mesh_route *rt_gate; struct ieee80211_mesh_gate_route *gr = NULL, *gr_next; - struct mbuf *m, *next; - int gates_found = 0; + struct mbuf *m, *mcopy, *next; KASSERT( rt_dest->rt_flags == IEEE80211_MESHRT_FLAGS_DISCOVER, ("Route is not marked with IEEE80211_MESHRT_FLAGS_DISCOVER")); /* XXX: send to more than one valid mash gate */ MESH_RT_LOCK(ms); + + m = ieee80211_ageq_remove(&ic->ic_stageq, + (struct ieee80211_node *)(uintptr_t) + ieee80211_mac_hash(ic, rt_dest->rt_dest)); + TAILQ_FOREACH_SAFE(gr, &ms->ms_known_gates, gr_next, gr_next) { rt_gate = gr->gr_route; if (rt_gate == NULL) { @@ -1053,8 +1189,18 @@ ieee80211_mesh_forward_to_gates(struct ieee80211vap *vap, gr->gr_addr, ":"); continue; } - gates_found = 1; - /* convert route to a proxy route */ + if ((rt_gate->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0) + continue; + KASSERT(rt_gate->rt_flags & IEEE80211_MESHRT_FLAGS_GATE, + ("route not marked as a mesh gate")); + KASSERT((rt_gate->rt_flags & + IEEE80211_MESHRT_FLAGS_PROXY) == 0, + ("found mesh gate that is also marked porxy")); + /* + * convert route to a proxy route gated by the current + * mesh gate, this is needed so encap can built data + * frame with correct address. + */ rt_dest->rt_flags = IEEE80211_MESHRT_FLAGS_PROXY | IEEE80211_MESHRT_FLAGS_VALID; rt_dest->rt_ext_seq = 1; /* random value */ @@ -1064,26 +1210,22 @@ ieee80211_mesh_forward_to_gates(struct ieee80211vap *vap, rt_dest->rt_nhops = rt_gate->rt_nhops; ieee80211_mesh_rt_update(rt_dest, ms->ms_ppath->mpp_inact); MESH_RT_UNLOCK(ms); - m = ieee80211_ageq_remove(&ic->ic_stageq, - (struct ieee80211_node *)(uintptr_t) - ieee80211_mac_hash(ic, rt_dest->rt_dest)); - for (; m != NULL; m = next) { - next = m->m_nextpkt; - m->m_nextpkt = NULL; - IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_HWMP, rt_dest->rt_dest, - "flush queued frame %p len %d", m, m->m_pkthdr.len); - ifp->if_transmit(ifp, m); + /* XXX: lock?? */ + mcopy = m_dup(m, M_NOWAIT); + for (; mcopy != NULL; mcopy = next) { + next = mcopy->m_nextpkt; + mcopy->m_nextpkt = NULL; + IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_HWMP, + rt_dest->rt_dest, + "flush queued frame %p len %d", mcopy, + mcopy->m_pkthdr.len); + mesh_transmit_to_gate(vap, mcopy, rt_gate); } MESH_RT_LOCK(ms); } - - if (gates_found == 0) { - rt_dest->rt_flags = 0; /* Mark invalid */ - IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_HWMP, rt_dest->rt_dest, - "%s", "no mesh gate found, or no path setup for mesh gate yet"); - } + rt_dest->rt_flags = 0; /* Mark invalid */ + m_freem(m); MESH_RT_UNLOCK(ms); - } /* From 4c4f4aa0f353ca2041bf4a4d8956fd9cb5198cd9 Mon Sep 17 00:00:00 2001 From: Monthadar Al Jaberi Date: Thu, 7 Feb 2013 21:26:40 +0000 Subject: [PATCH 0040/1476] HWMP: ic->raw_xmit didn't always point to correct ni. This is a code re-write. ic->raw_xmit need a pointer to ieee80211_node for the destination node (da). I have reorganized the code so that a pointer to the da node is searched for in the end & in one place. * Make mesh_find_txnode public to be used by HWMP, renamed to ieee80211_mesh_finx_txnode; * changed the argument from ieee80211_node to ieee80211vap for all hwmp_send_* functions; * removed the 'sa' argument from hwmp_send_* functions as all HWMP frames have the source address equal to vap->iv_myaddr; * Modified hwmp_send_action so that if da is MULTCAST ni=vap->iv_bss otherwise we called ieee80211_mesh_find_txnode. Also no need to hold a reference in this functions if da is not MULTICAST as by finding the node it became referenced in ieee80211_find_txnode; Approved by: adrian (mentor) --- sys/net80211/ieee80211_hwmp.c | 119 +++++++++++++++------------------- sys/net80211/ieee80211_mesh.c | 11 ++-- sys/net80211/ieee80211_mesh.h | 3 + 3 files changed, 58 insertions(+), 75 deletions(-) diff --git a/sys/net80211/ieee80211_hwmp.c b/sys/net80211/ieee80211_hwmp.c index 52a315298e4..50e4a1e1f64 100644 --- a/sys/net80211/ieee80211_hwmp.c +++ b/sys/net80211/ieee80211_hwmp.c @@ -68,8 +68,7 @@ static void hwmp_vattach(struct ieee80211vap *); static void hwmp_vdetach(struct ieee80211vap *); static int hwmp_newstate(struct ieee80211vap *, enum ieee80211_state, int); -static int hwmp_send_action(struct ieee80211_node *, - const uint8_t [IEEE80211_ADDR_LEN], +static int hwmp_send_action(struct ieee80211vap *, const uint8_t [IEEE80211_ADDR_LEN], uint8_t *, size_t); static uint8_t * hwmp_add_meshpreq(uint8_t *, @@ -86,23 +85,20 @@ static void hwmp_rootmode_rann_cb(void *); static void hwmp_recv_preq(struct ieee80211vap *, struct ieee80211_node *, const struct ieee80211_frame *, const struct ieee80211_meshpreq_ie *); -static int hwmp_send_preq(struct ieee80211_node *, - const uint8_t [IEEE80211_ADDR_LEN], +static int hwmp_send_preq(struct ieee80211vap *, const uint8_t [IEEE80211_ADDR_LEN], struct ieee80211_meshpreq_ie *, struct timeval *, struct timeval *); static void hwmp_recv_prep(struct ieee80211vap *, struct ieee80211_node *, const struct ieee80211_frame *, const struct ieee80211_meshprep_ie *); -static int hwmp_send_prep(struct ieee80211_node *, - const uint8_t [IEEE80211_ADDR_LEN], +static int hwmp_send_prep(struct ieee80211vap *, const uint8_t [IEEE80211_ADDR_LEN], struct ieee80211_meshprep_ie *); static void hwmp_recv_perr(struct ieee80211vap *, struct ieee80211_node *, const struct ieee80211_frame *, const struct ieee80211_meshperr_ie *); -static int hwmp_send_perr(struct ieee80211_node *, - const uint8_t [IEEE80211_ADDR_LEN], +static int hwmp_send_perr(struct ieee80211vap *, const uint8_t [IEEE80211_ADDR_LEN], struct ieee80211_meshperr_ie *); static void hwmp_senderror(struct ieee80211vap *, @@ -111,8 +107,7 @@ static void hwmp_senderror(struct ieee80211vap *, static void hwmp_recv_rann(struct ieee80211vap *, struct ieee80211_node *, const struct ieee80211_frame *, const struct ieee80211_meshrann_ie *); -static int hwmp_send_rann(struct ieee80211_node *, - const uint8_t [IEEE80211_ADDR_LEN], +static int hwmp_send_rann(struct ieee80211vap *, const uint8_t [IEEE80211_ADDR_LEN], struct ieee80211_meshrann_ie *); static struct ieee80211_node * @@ -588,17 +583,30 @@ hwmp_recv_action_meshpath(struct ieee80211_node *ni, } static int -hwmp_send_action(struct ieee80211_node *ni, - const uint8_t sa[IEEE80211_ADDR_LEN], +hwmp_send_action(struct ieee80211vap *vap, const uint8_t da[IEEE80211_ADDR_LEN], uint8_t *ie, size_t len) { - struct ieee80211vap *vap = ni->ni_vap; - struct ieee80211com *ic = ni->ni_ic; + struct ieee80211_node *ni; + struct ieee80211com *ic; struct ieee80211_bpf_params params; struct mbuf *m; uint8_t *frm; + if (IEEE80211_IS_MULTICAST(da)) { + ni = ieee80211_ref_node(vap->iv_bss); +#ifdef IEEE80211_DEBUG_REFCNT + IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, + "ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n", + __func__, __LINE__, + ni, ether_sprintf(ni->ni_macaddr), + ieee80211_node_refcnt(ni)+1); +#endif + ieee80211_ref_node(ni); + } + else + ni = ieee80211_mesh_find_txnode(vap, da); + if (vap->iv_state == IEEE80211_S_CAC) { IEEE80211_NOTE(vap, IEEE80211_MSG_OUTPUT, ni, "block %s frame in CAC state", "HWMP action"); @@ -607,19 +615,7 @@ hwmp_send_action(struct ieee80211_node *ni, } KASSERT(ni != NULL, ("null node")); - /* - * Hold a reference on the node so it doesn't go away until after - * the xmit is complete all the way in the driver. On error we - * will remove our reference. - */ -#ifdef IEEE80211_DEBUG_REFCNT - IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, - "ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n", - __func__, __LINE__, - ni, ether_sprintf(ni->ni_macaddr), - ieee80211_node_refcnt(ni)+1); -#endif - ieee80211_ref_node(ni); + ic = ni->ni_ic; m = ieee80211_getmgtframe(&frm, ic->ic_headroom + sizeof(struct ieee80211_frame), @@ -660,7 +656,7 @@ hwmp_send_action(struct ieee80211_node *ni, } ieee80211_send_setup(ni, m, IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_ACTION, - IEEE80211_NONQOS_TID, sa, da, sa); + IEEE80211_NONQOS_TID, vap->iv_myaddr, da, vap->iv_myaddr); m->m_flags |= M_ENCAP; /* mark encapsulated */ IEEE80211_NODE_STAT(ni, tx_mgmt); @@ -862,8 +858,8 @@ hwmp_rootmode_cb(void *arg) IEEE80211_MESHPREQ_TFLAGS_USN; PREQ_TSEQ(0) = 0; vap->iv_stats.is_hwmp_rootreqs++; - hwmp_send_preq(vap->iv_bss, vap->iv_myaddr, broadcastaddr, &preq, - NULL, NULL); /* NB: we enforce rate check ourself */ + /* NB: we enforce rate check ourself */ + hwmp_send_preq(vap, broadcastaddr, &preq, NULL, NULL); hwmp_rootmode_setup(vap); } #undef PREQ_TFLAGS @@ -896,7 +892,7 @@ hwmp_rootmode_rann_cb(void *arg) rann.rann_metric = IEEE80211_MESHLMETRIC_INITIALVAL; vap->iv_stats.is_hwmp_rootrann++; - hwmp_send_rann(vap->iv_bss, vap->iv_myaddr, broadcastaddr, &rann); + hwmp_send_rann(vap, broadcastaddr, &rann); hwmp_rootmode_setup(vap); } @@ -1060,7 +1056,7 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni, IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, "reply to %6D", preq->preq_origaddr, ":"); - hwmp_send_prep(ni, vap->iv_myaddr, wh->i_addr2, &prep); + hwmp_send_prep(vap, wh->i_addr2, &prep); return; } /* we may update our proxy information for the orig external */ @@ -1119,8 +1115,7 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni, IEEE80211_ADDR_COPY(prep.prep_targetaddr, vap->iv_myaddr); prep.prep_targetseq = ++hs->hs_seq; - hwmp_send_prep(vap->iv_bss, vap->iv_myaddr, - rtorig->rt_nexthop, &prep); + hwmp_send_prep(vap, rtorig->rt_nexthop, &prep); } } @@ -1161,8 +1156,7 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni, IEEE80211_ADDR_COPY(&prep.prep_origaddr, preq->preq_origaddr); prep.prep_origseq = hrorig->hr_seq; - hwmp_send_prep(ni, vap->iv_myaddr, - rtorig->rt_nexthop, &prep); + hwmp_send_prep(vap, rtorig->rt_nexthop, &prep); /* * Set TO and unset RF bits because we have @@ -1181,8 +1175,7 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni, ppreq.preq_metric += ms->ms_pmetric->mpm_metric(ni); /* don't do PREQ ratecheck when we propagate */ - hwmp_send_preq(ni, vap->iv_myaddr, broadcastaddr, - &ppreq, NULL, NULL); + hwmp_send_preq(vap, broadcastaddr, &ppreq, NULL, NULL); } } #undef PREQ_TFLAGS @@ -1190,8 +1183,7 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni, #undef PREQ_TSEQ static int -hwmp_send_preq(struct ieee80211_node *ni, - const uint8_t sa[IEEE80211_ADDR_LEN], +hwmp_send_preq(struct ieee80211vap *vap, const uint8_t da[IEEE80211_ADDR_LEN], struct ieee80211_meshpreq_ie *preq, struct timeval *last, struct timeval *minint) @@ -1220,7 +1212,7 @@ hwmp_send_preq(struct ieee80211_node *ni, preq->preq_len = (preq->preq_flags & IEEE80211_MESHPREQ_FLAGS_AE ? IEEE80211_MESHPREQ_BASE_SZ_AE : IEEE80211_MESHPREQ_BASE_SZ) + preq->preq_tcount * IEEE80211_MESHPREQ_TRGT_SZ; - return hwmp_send_action(ni, sa, da, (uint8_t *)preq, preq->preq_len+2); + return hwmp_send_action(vap, da, (uint8_t *)preq, preq->preq_len+2); } static void @@ -1354,7 +1346,7 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni, pprep.prep_hopcount += 1; pprep.prep_ttl -= 1; pprep.prep_metric += ms->ms_pmetric->mpm_metric(ni); - hwmp_send_prep(ni, vap->iv_myaddr, rtorig->rt_nexthop, &pprep); + hwmp_send_prep(vap, rtorig->rt_nexthop, &pprep); /* precursor list for the Target Mesh STA Address is updated */ } @@ -1436,8 +1428,7 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni, } static int -hwmp_send_prep(struct ieee80211_node *ni, - const uint8_t sa[IEEE80211_ADDR_LEN], +hwmp_send_prep(struct ieee80211vap *vap, const uint8_t da[IEEE80211_ADDR_LEN], struct ieee80211_meshprep_ie *prep) { @@ -1455,8 +1446,7 @@ hwmp_send_prep(struct ieee80211_node *ni, prep->prep_ie = IEEE80211_ELEMID_MESHPREP; prep->prep_len = prep->prep_flags & IEEE80211_MESHPREP_FLAGS_AE ? IEEE80211_MESHPREP_BASE_SZ_AE : IEEE80211_MESHPREP_BASE_SZ; - return hwmp_send_action(ni, sa, da, (uint8_t *)prep, - prep->prep_len + 2); + return hwmp_send_action(vap, da, (uint8_t *)prep, prep->prep_len + 2); } #define PERR_DFLAGS(n) perr.perr_dests[n].dest_flags @@ -1489,7 +1479,7 @@ hwmp_peerdown(struct ieee80211_node *ni) PERR_DRCODE(0) = IEEE80211_REASON_MESH_PERR_DEST_UNREACH; /* NB: flush everything passing through peer */ ieee80211_mesh_rt_flush_peer(vap, ni->ni_macaddr); - hwmp_send_perr(vap->iv_bss, vap->iv_myaddr, broadcastaddr, &perr); + hwmp_send_perr(vap, broadcastaddr, &perr); } #undef PERR_DFLAGS #undef PERR_DADDR @@ -1592,8 +1582,7 @@ hwmp_recv_perr(struct ieee80211vap *vap, struct ieee80211_node *ni, "propagate PERR from %6D", wh->i_addr2, ":"); pperr->perr_ndests = j; pperr->perr_ttl--; - hwmp_send_perr(vap->iv_bss, vap->iv_myaddr, broadcastaddr, - pperr); + hwmp_send_perr(vap, broadcastaddr, pperr); } done: if (pperr != NULL) @@ -1606,12 +1595,11 @@ done: #undef PERR_DRCODE static int -hwmp_send_perr(struct ieee80211_node *ni, - const uint8_t sa[IEEE80211_ADDR_LEN], +hwmp_send_perr(struct ieee80211vap *vap, const uint8_t da[IEEE80211_ADDR_LEN], struct ieee80211_meshperr_ie *perr) { - struct ieee80211_hwmp_state *hs = ni->ni_vap->iv_hwmp; + struct ieee80211_hwmp_state *hs = vap->iv_hwmp; int i; uint8_t length = 0; @@ -1642,7 +1630,7 @@ hwmp_send_perr(struct ieee80211_node *ni, length += IEEE80211_MESHPERR_DEST_SZ; } perr->perr_len =length; - return hwmp_send_action(ni, sa, da, (uint8_t *)perr, perr->perr_len+2); + return hwmp_send_action(vap, da, (uint8_t *)perr, perr->perr_len+2); } /* @@ -1695,7 +1683,7 @@ hwmp_senderror(struct ieee80211vap *vap, default: KASSERT(0, ("unknown reason code for HWMP PERR (%u)", rcode)); } - hwmp_send_perr(vap->iv_bss, vap->iv_myaddr, broadcastaddr, &perr); + hwmp_send_perr(vap, broadcastaddr, &perr); } #undef PERR_DFLAGS #undef PEER_DADDR @@ -1782,8 +1770,8 @@ hwmp_recv_rann(struct ieee80211vap *vap, struct ieee80211_node *ni, IEEE80211_ADDR_COPY(preq.preq_targets[0].target_addr, rann->rann_addr); preq.preq_targets[0].target_seq = rann->rann_seq; /* XXX: if rootconfint have not passed, we built this preq in vain */ - hwmp_send_preq(vap->iv_bss, vap->iv_myaddr, wh->i_addr2, &preq, - &hr->hr_lastrootconf, &ieee80211_hwmp_rootconfint); + hwmp_send_preq(vap, wh->i_addr2, &preq, &hr->hr_lastrootconf, + &ieee80211_hwmp_rootconfint); /* propagate a RANN */ if (rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID && @@ -1794,14 +1782,12 @@ hwmp_recv_rann(struct ieee80211vap *vap, struct ieee80211_node *ni, prann.rann_hopcount += 1; prann.rann_ttl -= 1; prann.rann_metric += ms->ms_pmetric->mpm_metric(ni); - hwmp_send_rann(vap->iv_bss, vap->iv_myaddr, - broadcastaddr, &prann); + hwmp_send_rann(vap, broadcastaddr, &prann); } } static int -hwmp_send_rann(struct ieee80211_node *ni, - const uint8_t sa[IEEE80211_ADDR_LEN], +hwmp_send_rann(struct ieee80211vap *vap, const uint8_t da[IEEE80211_ADDR_LEN], struct ieee80211_meshrann_ie *rann) { @@ -1816,8 +1802,7 @@ hwmp_send_rann(struct ieee80211_node *ni, */ rann->rann_ie = IEEE80211_ELEMID_MESHRANN; rann->rann_len = IEEE80211_MESHRANN_BASE_SZ; - return hwmp_send_action(ni, sa, da, (uint8_t *)rann, - rann->rann_len + 2); + return hwmp_send_action(vap, da, (uint8_t *)rann, rann->rann_len + 2); } #define PREQ_TFLAGS(n) preq.preq_targets[n].target_flags @@ -1872,9 +1857,8 @@ hwmp_rediscover_cb(void *arg) PREQ_TFLAGS(0) |= IEEE80211_MESHPREQ_TFLAGS_USN; PREQ_TSEQ(0) = 0; /* RESERVED when USN flag is set */ /* XXX check return value */ - hwmp_send_preq(vap->iv_bss, vap->iv_myaddr, - broadcastaddr, &preq, &hr->hr_lastpreq, - &ieee80211_hwmp_preqminint); + hwmp_send_preq(vap, broadcastaddr, &preq, &hr->hr_lastpreq, + &ieee80211_hwmp_preqminint); callout_reset(&rt->rt_discovery, ieee80211_hwmp_net_diameter_traversaltime * 2, hwmp_rediscover_cb, rt); @@ -1970,9 +1954,8 @@ hwmp_discover(struct ieee80211vap *vap, PREQ_TFLAGS(0) |= IEEE80211_MESHPREQ_TFLAGS_USN; PREQ_TSEQ(0) = 0; /* RESERVED when USN flag is set */ /* XXX check return value */ - hwmp_send_preq(vap->iv_bss, vap->iv_myaddr, - broadcastaddr, &preq, &hr->hr_lastpreq, - &ieee80211_hwmp_preqminint); + hwmp_send_preq(vap, broadcastaddr, &preq, + &hr->hr_lastpreq, &ieee80211_hwmp_preqminint); callout_reset(&rt->rt_discovery, ieee80211_hwmp_net_diameter_traversaltime * 2, hwmp_rediscover_cb, rt); diff --git a/sys/net80211/ieee80211_mesh.c b/sys/net80211/ieee80211_mesh.c index 1cc441924b4..38b7cea4b59 100644 --- a/sys/net80211/ieee80211_mesh.c +++ b/sys/net80211/ieee80211_mesh.c @@ -77,9 +77,6 @@ static void mesh_checkid(void *, struct ieee80211_node *); static uint32_t mesh_generateid(struct ieee80211vap *); static int mesh_checkpseq(struct ieee80211vap *, const uint8_t [IEEE80211_ADDR_LEN], uint32_t); -static struct ieee80211_node * - mesh_find_txnode(struct ieee80211vap *, - const uint8_t [IEEE80211_ADDR_LEN]); static void mesh_transmit_to_gate(struct ieee80211vap *, struct mbuf *, struct ieee80211_mesh_route *); static void mesh_forward(struct ieee80211vap *, struct mbuf *, @@ -1005,8 +1002,8 @@ mesh_checkpseq(struct ieee80211vap *vap, /* * Iterate the routing table and locate the next hop. */ -static struct ieee80211_node * -mesh_find_txnode(struct ieee80211vap *vap, +struct ieee80211_node * +ieee80211_mesh_find_txnode(struct ieee80211vap *vap, const uint8_t dest[IEEE80211_ADDR_LEN]) { struct ieee80211_mesh_route *rt; @@ -1046,7 +1043,7 @@ mesh_transmit_to_gate(struct ieee80211vap *vap, struct mbuf *m, int error; eh = mtod(m, struct ether_header *); - ni = mesh_find_txnode(vap, rt_gate->rt_dest); + ni = ieee80211_mesh_find_txnode(vap, rt_gate->rt_dest); if (ni == NULL) { ifp->if_oerrors++; m_freem(m); @@ -1293,7 +1290,7 @@ mesh_forward(struct ieee80211vap *vap, struct mbuf *m, ni = ieee80211_ref_node(vap->iv_bss); mcopy->m_flags |= M_MCAST; } else { - ni = mesh_find_txnode(vap, whcopy->i_addr3); + ni = ieee80211_mesh_find_txnode(vap, whcopy->i_addr3); if (ni == NULL) { /* * [Optional] any of the following three actions: diff --git a/sys/net80211/ieee80211_mesh.h b/sys/net80211/ieee80211_mesh.h index 84a3ef743a5..5dc2b2c12b1 100644 --- a/sys/net80211/ieee80211_mesh.h +++ b/sys/net80211/ieee80211_mesh.h @@ -571,6 +571,9 @@ struct ieee80211_mesh_gate_route * const uint8_t *, struct ieee80211_mesh_route *); void ieee80211_mesh_forward_to_gates(struct ieee80211vap *, struct ieee80211_mesh_route *); +struct ieee80211_node * + ieee80211_mesh_find_txnode(struct ieee80211vap *, + const uint8_t [IEEE80211_ADDR_LEN]); /* * Return non-zero if proxy operation is enabled. From 6e839020044df8572a03a08778c26850d318398b Mon Sep 17 00:00:00 2001 From: Monthadar Al Jaberi Date: Thu, 7 Feb 2013 21:27:40 +0000 Subject: [PATCH 0041/1476] Mesh HWMP PREQ update: proxy reply only if mesh STA is a meshgate. * Original PREP frame is transmitted only by the target mesh STA or the mesh STA that is the proxy target; * Fixed so that metric value is not over written incorrectly in hwmp_recv_preq for when replying back with a PREP; Approved by: adrian (mentor) --- sys/net80211/ieee80211_hwmp.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sys/net80211/ieee80211_hwmp.c b/sys/net80211/ieee80211_hwmp.c index 50e4a1e1f64..8f1a1023cc0 100644 --- a/sys/net80211/ieee80211_hwmp.c +++ b/sys/net80211/ieee80211_hwmp.c @@ -1017,10 +1017,12 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni, /* * Check if the PREQ is addressed to us. - * or a Proxy currently supplied by us. + * or a Proxy currently gated by us. */ if (IEEE80211_ADDR_EQ(vap->iv_myaddr, PREQ_TADDR(0)) || - (rttarg != NULL && + (ms->ms_flags & IEEE80211_MESHFLAGS_GATE && + rttarg != NULL && + IEEE80211_ADDR_EQ(vap->iv_myaddr, rttarg->rt_mesh_gate) && rttarg->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY && rttarg->rt_flags & IEEE80211_MESHRT_FLAGS_VALID)) { /* @@ -1031,6 +1033,7 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni, prep.prep_flags = 0; prep.prep_hopcount = 0; + prep.prep_metric = IEEE80211_MESHLMETRIC_INITIALVAL; IEEE80211_ADDR_COPY(prep.prep_targetaddr, vap->iv_myaddr); if (rttarg != NULL && /* if NULL it means we are the target */ rttarg->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY) { @@ -1042,6 +1045,7 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni, /* update proxy seqno to HWMP seqno */ rttarg->rt_ext_seq = hs->hs_seq; prep.prep_hopcount = rttarg->rt_nhops; + prep.prep_metric = rttarg->rt_metric; IEEE80211_ADDR_COPY(prep.prep_targetaddr, rttarg->rt_mesh_gate); } /* @@ -1050,7 +1054,6 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni, prep.prep_ttl = ms->ms_ttl; prep.prep_targetseq = hs->hs_seq; prep.prep_lifetime = preq->preq_lifetime; - prep.prep_metric = IEEE80211_MESHLMETRIC_INITIALVAL; IEEE80211_ADDR_COPY(prep.prep_origaddr, preq->preq_origaddr); prep.prep_origseq = preq->preq_origseq; From 230394c08b58e0aa99415cc9279f9468b9ef9734 Mon Sep 17 00:00:00 2001 From: Monthadar Al Jaberi Date: Thu, 7 Feb 2013 21:28:25 +0000 Subject: [PATCH 0042/1476] Mesh HWMP: don't send an intermediate PREP for proxy entries. * The standard is unclear about what should happen in case a mesh STA (not marked as a mesh gate) recevies a PREQ for a destination that is marked as proxy. Solution for now is not to do intermediate reply at all, and let the PREQ reach the mesh gate; Approved by: adrian (mentor) --- sys/net80211/ieee80211_hwmp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sys/net80211/ieee80211_hwmp.c b/sys/net80211/ieee80211_hwmp.c index 8f1a1023cc0..46026925a73 100644 --- a/sys/net80211/ieee80211_hwmp.c +++ b/sys/net80211/ieee80211_hwmp.c @@ -1133,9 +1133,11 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni, /* * We have a valid route to this node. + * NB: if target is proxy dont reply. */ if (rttarg != NULL && - (rttarg->rt_flags & IEEE80211_MESHRT_FLAGS_VALID)) { + rttarg->rt_flags & IEEE80211_MESHRT_FLAGS_VALID && + !(rttarg->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY)) { /* * Check if we can send an intermediate Path Reply, * i.e., Target Only bit is not set and target is not From 026e280fbf127a1883569bb2d46d521bd4b1721a Mon Sep 17 00:00:00 2001 From: Monthadar Al Jaberi Date: Thu, 7 Feb 2013 21:29:14 +0000 Subject: [PATCH 0043/1476] Mesh HWMP PREQ: fixed conditions for discarding elements. Approved by: adrian (mentor) --- sys/net80211/ieee80211_hwmp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sys/net80211/ieee80211_hwmp.c b/sys/net80211/ieee80211_hwmp.c index 46026925a73..707a7903d90 100644 --- a/sys/net80211/ieee80211_hwmp.c +++ b/sys/net80211/ieee80211_hwmp.c @@ -997,10 +997,10 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni, * it will be marked below. */ rtorig->rt_flags = IEEE80211_MESHRT_FLAGS_VALID; - }else if ((hrtarg != NULL && - HWMP_SEQ_EQ(hrtarg->hr_seq, PREQ_TSEQ(0)) && - ((rtorig->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0)) || - preqid >= preq->preq_id) { + } else if ((hrtarg != NULL && + !HWMP_SEQ_EQ(hrtarg->hr_seq, PREQ_TSEQ(0))) || + (rtorig->rt_flags & IEEE80211_MESHRT_FLAGS_VALID && + preqid >= preq->preq_id)) { IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, "discard PREQ from %6D, old seqno %u <= %u," " or old preqid %u < %u", From 62f0748505173cf8f12ceea9cea7824949427c6f Mon Sep 17 00:00:00 2001 From: Monthadar Al Jaberi Date: Thu, 7 Feb 2013 21:29:48 +0000 Subject: [PATCH 0044/1476] Update ddb to print mesh routing table. * Modified _db_show_vap and _db_show_com to print mesh routing table if the 'm' modifier is specified; Approved by: adrian (mentor) --- sys/net80211/ieee80211_ddb.c | 38 +++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/sys/net80211/ieee80211_ddb.c b/sys/net80211/ieee80211_ddb.c index c8695719054..6f7dabf3b72 100644 --- a/sys/net80211/ieee80211_ddb.c +++ b/sys/net80211/ieee80211_ddb.c @@ -63,9 +63,9 @@ __FBSDID("$FreeBSD$"); } while (0) static void _db_show_sta(const struct ieee80211_node *); -static void _db_show_vap(const struct ieee80211vap *, int); +static void _db_show_vap(const struct ieee80211vap *, int, int); static void _db_show_com(const struct ieee80211com *, - int showvaps, int showsta, int showprocs); + int showvaps, int showsta, int showmesh, int showprocs); static void _db_show_node_table(const char *tag, const struct ieee80211_node_table *); @@ -103,7 +103,7 @@ DB_SHOW_COMMAND(statab, db_show_statab) DB_SHOW_COMMAND(vap, db_show_vap) { - int i, showprocs = 0; + int i, showmesh = 0, showprocs = 0; if (!have_addr) { db_printf("usage: show vap \n"); @@ -113,18 +113,22 @@ DB_SHOW_COMMAND(vap, db_show_vap) switch (modif[i]) { case 'a': showprocs = 1; + showmesh = 1; + break; + case 'm': + showmesh = 1; break; case 'p': showprocs = 1; break; } - _db_show_vap((const struct ieee80211vap *) addr, showprocs); + _db_show_vap((const struct ieee80211vap *) addr, showmesh, showprocs); } DB_SHOW_COMMAND(com, db_show_com) { const struct ieee80211com *ic; - int i, showprocs = 0, showvaps = 0, showsta = 0; + int i, showprocs = 0, showvaps = 0, showsta = 0, showmesh = 0; if (!have_addr) { db_printf("usage: show com \n"); @@ -133,11 +137,14 @@ DB_SHOW_COMMAND(com, db_show_com) for (i = 0; modif[i] != '\0'; i++) switch (modif[i]) { case 'a': - showsta = showvaps = showprocs = 1; + showsta = showmesh = showvaps = showprocs = 1; break; case 's': showsta = 1; break; + case 'm': + showmesh = 1; + break; case 'v': showvaps = 1; break; @@ -147,7 +154,7 @@ DB_SHOW_COMMAND(com, db_show_com) } ic = (const struct ieee80211com *) addr; - _db_show_com(ic, showvaps, showsta, showprocs); + _db_show_com(ic, showvaps, showsta, showmesh, showprocs); } DB_SHOW_ALL_COMMAND(vaps, db_show_all_vaps) @@ -178,7 +185,7 @@ DB_SHOW_ALL_COMMAND(vaps, db_show_all_vaps) vap->iv_ifp->if_xname, vap); db_printf("\n"); } else - _db_show_com(ic, 1, 1, 1); + _db_show_com(ic, 1, 1, 1, 1); } } } @@ -330,7 +337,7 @@ _db_show_tdma(const char *sep, const struct ieee80211_tdma_state *ts, int showpr #endif /* IEEE80211_SUPPORT_TDMA */ static void -_db_show_vap(const struct ieee80211vap *vap, int showprocs) +_db_show_vap(const struct ieee80211vap *vap, int showmesh, int showprocs) { const struct ieee80211com *ic = vap->iv_ic; int i; @@ -341,6 +348,10 @@ _db_show_vap(const struct ieee80211vap *vap, int showprocs) db_printf("\n"); db_printf("\topmode %s", ieee80211_opmode_name[vap->iv_opmode]); +#ifdef IEEE80211_SUPPORT_MESH + if (vap->iv_opmode == IEEE80211_M_MBSS) + db_printf("(%p)", vap->iv_mesh); +#endif db_printf(" state %s", ieee80211_state_name[vap->iv_state]); db_printf(" ifp %p(%s)", vap->iv_ifp, vap->iv_ifp->if_xname); db_printf("\n"); @@ -472,6 +483,10 @@ _db_show_vap(const struct ieee80211vap *vap, int showprocs) db_printf(" acl %p", vap->iv_acl); db_printf(" as %p", vap->iv_as); db_printf("\n"); +#ifdef IEEE80211_SUPPORT_MESH + if (showmesh && vap->iv_mesh != NULL) + _db_show_mesh(vap->iv_mesh); +#endif #ifdef IEEE80211_SUPPORT_TDMA if (vap->iv_tdma != NULL) _db_show_tdma("\t", vap->iv_tdma, showprocs); @@ -495,7 +510,8 @@ _db_show_vap(const struct ieee80211vap *vap, int showprocs) } static void -_db_show_com(const struct ieee80211com *ic, int showvaps, int showsta, int showprocs) +_db_show_com(const struct ieee80211com *ic, int showvaps, int showsta, + int showmesh, int showprocs) { struct ieee80211vap *vap; @@ -651,7 +667,7 @@ _db_show_com(const struct ieee80211com *ic, int showvaps, int showsta, int showp if (showvaps && !TAILQ_EMPTY(&ic->ic_vaps)) { db_printf("\n"); TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) - _db_show_vap(vap, showprocs); + _db_show_vap(vap, showmesh, showprocs); } if (showsta && !TAILQ_EMPTY(&ic->ic_sta.nt_node)) { const struct ieee80211_node_table *nt = &ic->ic_sta; From 4efafd66eb569c6e9dc60624134c357476619da6 Mon Sep 17 00:00:00 2001 From: Monthadar Al Jaberi Date: Thu, 7 Feb 2013 21:30:29 +0000 Subject: [PATCH 0045/1476] Mesh bug: debug infomartion showing swapped SA and DA address. * Fix bug for "forward frame from SA(%6D), DA(%6D)" where addresses where swapped between SA and DA; Approved by: adrian (mentor) --- sys/net80211/ieee80211_output.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c index 8f3e51bbcef..7481488f3e2 100644 --- a/sys/net80211/ieee80211_output.c +++ b/sys/net80211/ieee80211_output.c @@ -264,8 +264,8 @@ ieee80211_start(struct ifnet *ifp) } IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT, "forward frame from DS SA(%6D), DA(%6D)\n", - eh->ether_dhost, ":", - eh->ether_shost, ":"); + eh->ether_shost, ":", + eh->ether_dhost, ":"); ieee80211_mesh_proxy_check(vap, eh->ether_shost); } ni = ieee80211_mesh_discover(vap, eh->ether_dhost, m); From 80e25642f24e830822d40a52e2005986243facab Mon Sep 17 00:00:00 2001 From: Monthadar Al Jaberi Date: Thu, 7 Feb 2013 21:30:58 +0000 Subject: [PATCH 0046/1476] Mesh HWMP PERR bug fixes. * When calling ieee80211_mesh_rt_flush_peer, the rt->rt_dest argument should not be passed because it can get freed before invalidating the other routes that depends on it to compare with next_hop. Use PERR_DADDR(i) instead; Approved by: adrian (mentor) --- sys/net80211/ieee80211_hwmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/net80211/ieee80211_hwmp.c b/sys/net80211/ieee80211_hwmp.c index 707a7903d90..206a4a4695e 100644 --- a/sys/net80211/ieee80211_hwmp.c +++ b/sys/net80211/ieee80211_hwmp.c @@ -1570,7 +1570,7 @@ hwmp_recv_perr(struct ieee80211vap *vap, struct ieee80211_node *ni, "PERR, unknown reason code %u\n", PERR_DFLAGS(i)); goto done; /* XXX: stats?? */ } - ieee80211_mesh_rt_flush_peer(vap, rt->rt_dest); + ieee80211_mesh_rt_flush_peer(vap, PERR_DADDR(i)); KASSERT(j < 32, ("PERR, error ndest >= 32 (%u)", j)); } if (j == 0) { From d68e1a3749c1513b6f37d592bb2045e00a5dae67 Mon Sep 17 00:00:00 2001 From: Monthadar Al Jaberi Date: Thu, 7 Feb 2013 21:31:37 +0000 Subject: [PATCH 0047/1476] Mesh HWMP forwarding information: updating FI for transmitter. * Added hwmp_update_transmitter function that checks if the metric to the transmitter have improved. If old FI is invalid or metric is larger the FI to the transmitter is updated occurdingly. This is a recommendation from the 802.11 2012 standard, table 13-9; Approved by: adrian (mentor) --- sys/net80211/ieee80211_hwmp.c | 49 +++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/sys/net80211/ieee80211_hwmp.c b/sys/net80211/ieee80211_hwmp.c index 206a4a4695e..414ac53f6a7 100644 --- a/sys/net80211/ieee80211_hwmp.c +++ b/sys/net80211/ieee80211_hwmp.c @@ -896,6 +896,45 @@ hwmp_rootmode_rann_cb(void *arg) hwmp_rootmode_setup(vap); } +/* + * Update forwarding information to TA if metric improves. + */ +static void +hwmp_update_transmitter(struct ieee80211vap *vap, struct ieee80211_node *ni, + const char *hwmp_frame) +{ + struct ieee80211_mesh_state *ms = vap->iv_mesh; + struct ieee80211_mesh_route *rttran = NULL; /* Transmitter */ + int metric = 0; + + rttran = ieee80211_mesh_rt_find(vap, ni->ni_macaddr); + if (rttran == NULL) { + rttran = ieee80211_mesh_rt_add(vap, ni->ni_macaddr); + if (rttran == NULL) { + IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, + "unable to add path to transmitter %6D of %s", + ni->ni_macaddr, ":", hwmp_frame); + vap->iv_stats.is_mesh_rtaddfailed++; + return; + } + } + metric = ms->ms_pmetric->mpm_metric(ni); + if (!(rttran->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) || + rttran->rt_metric > metric) + { + IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, + "%s path to transmiter %6D of %s, metric %d:%d", + rttran->rt_flags & IEEE80211_MESHRT_FLAGS_VALID ? + "prefer" : "update", ni->ni_macaddr, ":", hwmp_frame, + rttran->rt_metric, metric); + IEEE80211_ADDR_COPY(rttran->rt_nexthop, ni->ni_macaddr); + rttran->rt_metric = metric; + rttran->rt_nhops = 1; + ieee80211_mesh_rt_update(rttran, ms->ms_ppath->mpp_inact); + rttran->rt_flags = IEEE80211_MESHRT_FLAGS_VALID; + } +} + #define PREQ_TFLAGS(n) preq->preq_targets[n].target_flags #define PREQ_TADDR(n) preq->preq_targets[n].target_addr #define PREQ_TSEQ(n) preq->preq_targets[n].target_seq @@ -1010,10 +1049,8 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni, return; } - /* - * Forwarding information for transmitter mesh STA - * [OPTIONAL: if metric improved] - */ + /* Update forwarding information to TA if metric improves. */ + hwmp_update_transmitter(vap, ni, "PREQ"); /* * Check if the PREQ is addressed to us. @@ -1268,7 +1305,6 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni, * rules defined in 13.10.8.4). If the conditions for creating or * updating the forwarding information have not been met in those * rules, no further steps are applied to the PREP. - * [OPTIONAL]: update forwarding information to TA if metric improves. */ rt = ieee80211_mesh_rt_find(vap, prep->prep_targetaddr); if (rt == NULL) { @@ -1323,6 +1359,9 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni, } rt->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID; /* mark valid */ + /* Update forwarding information to TA if metric improves */ + hwmp_update_transmitter(vap, ni, "PREP"); + /* * If it's NOT for us, propagate the PREP */ From 6db8a9b0f425b0f95105d18aad658a516e6c5ab8 Mon Sep 17 00:00:00 2001 From: Monthadar Al Jaberi Date: Thu, 7 Feb 2013 21:32:09 +0000 Subject: [PATCH 0048/1476] Mesh: recevied GANN frames where not parsed correctly. * Added mesh_parse_meshgate_action that parse all values to host endian; * Add more detailed debug output; Approved by: adrian (mentor) --- sys/net80211/ieee80211_mesh.c | 90 +++++++++++++++++++++++++---------- 1 file changed, 65 insertions(+), 25 deletions(-) diff --git a/sys/net80211/ieee80211_mesh.c b/sys/net80211/ieee80211_mesh.c index 38b7cea4b59..ee9eaedd7e7 100644 --- a/sys/net80211/ieee80211_mesh.c +++ b/sys/net80211/ieee80211_mesh.c @@ -533,9 +533,6 @@ mesh_gatemode_cb(void *arg) struct ieee80211_mesh_state *ms = vap->iv_mesh; struct ieee80211_meshgann_ie gann; - IEEE80211_NOTE(vap, IEEE80211_MSG_MESH, vap->iv_bss, - "%s", "send broadcast GANN"); - gann.gann_flags = 0; /* Reserved */ gann.gann_hopcount = 0; gann.gann_ttl = ms->ms_ttl; @@ -543,6 +540,9 @@ mesh_gatemode_cb(void *arg) gann.gann_seq = ms->ms_gateseq++; gann.gann_interval = ieee80211_mesh_gateint; + IEEE80211_NOTE(vap, IEEE80211_MSG_MESH, vap->iv_bss, + "send broadcast GANN (seq %u)", gann.gann_seq); + ieee80211_send_action(vap->iv_bss, IEEE80211_ACTION_CAT_MESH, IEEE80211_ACTION_MESH_GANN, &gann); mesh_gatemode_setup(vap); @@ -2604,6 +2604,40 @@ mesh_recv_action_meshlmetric(struct ieee80211_node *ni, return 0; } +/* + * Parse meshgate action ie's for GANN frames. + * Returns -1 if parsing fails, otherwise 0. + */ +static int +mesh_parse_meshgate_action(struct ieee80211_node *ni, + const struct ieee80211_frame *wh, /* XXX for VERIFY_LENGTH */ + struct ieee80211_meshgann_ie *ie, const uint8_t *frm, const uint8_t *efrm) +{ + struct ieee80211vap *vap = ni->ni_vap; + const struct ieee80211_meshgann_ie *gannie; + + while (efrm - frm > 1) { + IEEE80211_VERIFY_LENGTH(efrm - frm, frm[1] + 2, return -1); + switch (*frm) { + case IEEE80211_ELEMID_MESHGANN: + gannie = (const struct ieee80211_meshgann_ie *) frm; + memset(ie, 0, sizeof(ie)); + ie->gann_ie = gannie->gann_ie; + ie->gann_len = gannie->gann_len; + ie->gann_flags = gannie->gann_flags; + ie->gann_hopcount = gannie->gann_hopcount; + ie->gann_ttl = gannie->gann_ttl; + IEEE80211_ADDR_COPY(ie->gann_addr, gannie->gann_addr); + ie->gann_seq = LE_READ_4(&gannie->gann_seq); + ie->gann_interval = LE_READ_2(&gannie->gann_interval); + break; + } + frm += frm[1] + 2; + } + + return 0; +} + /* * Mesh Gate Announcement handling. */ @@ -2617,29 +2651,36 @@ mesh_recv_action_meshgate(struct ieee80211_node *ni, struct ieee80211_mesh_gate_route *gr, *next; struct ieee80211_mesh_route *rt_gate; struct ieee80211_meshgann_ie pgann; + struct ieee80211_meshgann_ie ie; int found = 0; - const struct ieee80211_meshgann_ie *ie = - (const struct ieee80211_meshgann_ie *) - (frm+2); /* action + code */ - if (IEEE80211_ADDR_EQ(vap->iv_myaddr, ie->gann_addr)) + /* +2 for action + code */ + if (mesh_parse_meshgate_action(ni, wh, &ie, frm+2, efrm) != 0) { + IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_MESH, + ni->ni_macaddr, NULL, "%s", + "GANN parsing failed"); + vap->iv_stats.is_rx_mgtdiscard++; + return (0); + } + + if (IEEE80211_ADDR_EQ(vap->iv_myaddr, ie.gann_addr)) return 0; IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, ni->ni_macaddr, - "received GANN, meshgate: %6D (seq %u)", ie->gann_addr, ":", - ie->gann_seq); + "received GANN, meshgate: %6D (seq %u)", ie.gann_addr, ":", + ie.gann_seq); if (ms == NULL) return (0); MESH_RT_LOCK(ms); TAILQ_FOREACH_SAFE(gr, &ms->ms_known_gates, gr_next, next) { - if (!IEEE80211_ADDR_EQ(gr->gr_addr, ie->gann_addr)) + if (!IEEE80211_ADDR_EQ(gr->gr_addr, ie.gann_addr)) continue; - if (ie->gann_seq <= gr->gr_lastseq) { + if (ie.gann_seq <= gr->gr_lastseq) { IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_MESH, ni->ni_macaddr, NULL, "GANN old seqno %u <= %u", - ie->gann_seq, gr->gr_lastseq); + ie.gann_seq, gr->gr_lastseq); MESH_RT_UNLOCK(ms); return (0); } @@ -2650,14 +2691,14 @@ mesh_recv_action_meshgate(struct ieee80211_node *ni, } if (found == 0) { /* this GANN is from a new mesh Gate add it to known table. */ - IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, ie->gann_addr, - "stored new GANN information, seq %u.", ie->gann_seq); + IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, ie.gann_addr, + "stored new GANN information, seq %u.", ie.gann_seq); gr = malloc(ALIGN(sizeof(struct ieee80211_mesh_gate_route)), M_80211_MESH_GT_RT, M_NOWAIT | M_ZERO); - IEEE80211_ADDR_COPY(gr->gr_addr, ie->gann_addr); + IEEE80211_ADDR_COPY(gr->gr_addr, ie.gann_addr); TAILQ_INSERT_TAIL(&ms->ms_known_gates, gr, gr_next); } - gr->gr_lastseq = ie->gann_seq; + gr->gr_lastseq = ie.gann_seq; /* check if we have a path to this gate */ rt_gate = mesh_rt_find_locked(ms, gr->gr_addr); @@ -2670,17 +2711,16 @@ mesh_recv_action_meshgate(struct ieee80211_node *ni, MESH_RT_UNLOCK(ms); /* popagate only if decremented ttl >= 1 && forwarding is enabled */ - if ((ie->gann_ttl - 1) < 1 && - !(ms->ms_flags & IEEE80211_MESHFLAGS_FWD)) + if ((ie.gann_ttl - 1) < 1 && !(ms->ms_flags & IEEE80211_MESHFLAGS_FWD)) return 0; - pgann.gann_flags = ie->gann_flags; /* Reserved */ - pgann.gann_hopcount = ie->gann_hopcount + 1; - pgann.gann_ttl = ie->gann_ttl - 1; - IEEE80211_ADDR_COPY(pgann.gann_addr, ie->gann_addr); - pgann.gann_seq = ie->gann_seq; - pgann.gann_interval = ie->gann_interval; + pgann.gann_flags = ie.gann_flags; /* Reserved */ + pgann.gann_hopcount = ie.gann_hopcount + 1; + pgann.gann_ttl = ie.gann_ttl - 1; + IEEE80211_ADDR_COPY(pgann.gann_addr, ie.gann_addr); + pgann.gann_seq = ie.gann_seq; + pgann.gann_interval = ie.gann_interval; - IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, ie->gann_addr, + IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, ie.gann_addr, "%s", "propagate GANN"); ieee80211_send_action(vap->iv_bss, IEEE80211_ACTION_CAT_MESH, From 1767d529f26257018769fae1b639121d384e4c0c Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Thu, 7 Feb 2013 22:42:33 +0000 Subject: [PATCH 0049/1476] sh: Simplify mksyntax and make it fit for cross-compiling. Now it outputs fixed files, which use constants provided by the C standard library to determine appropriate values for the target machine. Before, mksyntax inspected the host machine which resulted in subtle breakage if e.g. char is signed on the host and unsigned on the target such as when cross-compiling on x86 for ARM. Tested using -funsigned-char on amd64. Compiling build-tools without it and sh itself with it causes various tests to fail without this change but not with this change. With consistent -funsigned-char, tests pass with or without this change. The mksyntax program could be removed and syntax.c and syntax.h committed to the repository. Submitted by: Christoph Mallon MFC after: 2 weeks --- bin/sh/mksyntax.c | 164 ++++++++++++++++++++-------------------------- 1 file changed, 71 insertions(+), 93 deletions(-) diff --git a/bin/sh/mksyntax.c b/bin/sh/mksyntax.c index 6594da3a1bd..c6bf480a289 100644 --- a/bin/sh/mksyntax.c +++ b/bin/sh/mksyntax.c @@ -103,23 +103,16 @@ static char writer[] = "\ static FILE *cfile; static FILE *hfile; -static const char *syntax[513]; -static int base; -static int size; /* number of values which a char variable can have */ -static int nbits; /* number of bits in a character */ -static void filltable(const char *); -static void init(void); +static void add_default(void); +static void finish(void); +static void init(const char *); static void add(const char *, const char *); -static void print(const char *); static void output_type_macros(void); int main(int argc __unused, char **argv __unused) { - char c; - char d; - int sign; int i; char buf[80]; int pos; @@ -136,27 +129,8 @@ main(int argc __unused, char **argv __unused) fputs(writer, hfile); fputs(writer, cfile); - /* Determine the characteristics of chars. */ - c = -1; - sign = (c > 0) ? 0 : 1; - for (nbits = 1 ; ; nbits++) { - d = (1 << nbits) - 1; - if (d == c) - break; - } -#if 0 - printf("%s %d bit chars\n", sign? "signed" : "unsigned", nbits); -#endif - if (nbits > 9) { - fputs("Characters can't have more than 9 bits\n", stderr); - exit(2); - } - size = (1 << nbits) + 1; - base = 1; - if (sign) - base += 1 << (nbits - 1); - fputs("#include \n", hfile); + fputs("#include \n\n", hfile); /* Generate the #define statements in the header file */ fputs("/* Syntax classes */\n", hfile); @@ -177,8 +151,8 @@ main(int argc __unused, char **argv __unused) fprintf(hfile, "/* %s */\n", is_entry[i].comment); } putc('\n', hfile); - fprintf(hfile, "#define SYNBASE %d\n", base); - fprintf(hfile, "#define PEOF %d\n\n", -base); + fputs("#define SYNBASE (1 - CHAR_MIN)\n", hfile); + fputs("#define PEOF -SYNBASE\n\n", hfile); putc('\n', hfile); fputs("#define BASESYNTAX (basesyntax + SYNBASE)\n", hfile); fputs("#define DQSYNTAX (dqsyntax + SYNBASE)\n", hfile); @@ -189,10 +163,13 @@ main(int argc __unused, char **argv __unused) putc('\n', hfile); /* Generate the syntax tables. */ + fputs("#include \"parser.h\"\n", cfile); fputs("#include \"shell.h\"\n", cfile); fputs("#include \"syntax.h\"\n\n", cfile); - init(); + fputs("/* syntax table used when not in quotes */\n", cfile); + init("basesyntax"); + add_default(); add("\n", "CNL"); add("\\", "CBACK"); add("'", "CSQUOTE"); @@ -201,9 +178,11 @@ main(int argc __unused, char **argv __unused) add("$", "CVAR"); add("}", "CENDVAR"); add("<>();&| \t", "CSPCL"); - print("basesyntax"); - init(); + finish(); + fputs("\n/* syntax table used when in double quotes */\n", cfile); + init("dqsyntax"); + add_default(); add("\n", "CNL"); add("\\", "CBACK"); add("\"", "CENDQUOTE"); @@ -212,17 +191,21 @@ main(int argc __unused, char **argv __unused) add("}", "CENDVAR"); /* ':/' for tilde expansion, '-^]' for [a\-x] pattern ranges */ add("!*?[]=~:/-^", "CCTL"); - print("dqsyntax"); - init(); + finish(); + fputs("\n/* syntax table used when in single quotes */\n", cfile); + init("sqsyntax"); + add_default(); add("\n", "CNL"); add("\\", "CSBACK"); add("'", "CENDQUOTE"); /* ':/' for tilde expansion, '-^]' for [a\-x] pattern ranges */ add("!*?[]=~:/-^", "CCTL"); - print("sqsyntax"); - init(); + finish(); + fputs("\n/* syntax table used when in arithmetic */\n", cfile); + init("arisyntax"); + add_default(); add("\n", "CNL"); add("\\", "CBACK"); add("`", "CBQUOTE"); @@ -231,52 +214,68 @@ main(int argc __unused, char **argv __unused) add("}", "CENDVAR"); add("(", "CLP"); add(")", "CRP"); - print("arisyntax"); - filltable("0"); + finish(); + fputs("\n/* character classification table */\n", cfile); + init("is_type"); add("0123456789", "ISDIGIT"); add("abcdefghijklmnopqrstuvwxyz", "ISLOWER"); add("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "ISUPPER"); add("_", "ISUNDER"); add("#?$!-*@", "ISSPECL"); - print("is_type"); + finish(); + exit(0); } - /* - * Clear the syntax table. + * Output the header and declaration of a syntax table. */ static void -filltable(const char *dftval) +init(const char *name) { - int i; + fprintf(hfile, "extern const char %s[];\n", name); + fprintf(cfile, "const char %s[SYNBASE + CHAR_MAX + 1] = {\n", name); +} - for (i = 0 ; i < size ; i++) - syntax[i] = dftval; + +static void +add_one(const char *key, const char *type) +{ + fprintf(cfile, "\t[SYNBASE + %s] = %s,\n", key, type); } /* - * Initialize the syntax table with default values. + * Add default values to the syntax table. */ static void -init(void) +add_default(void) { - filltable("CWORD"); - syntax[0] = "CEOF"; - syntax[base + CTLESC] = "CCTL"; - syntax[base + CTLVAR] = "CCTL"; - syntax[base + CTLENDVAR] = "CCTL"; - syntax[base + CTLBACKQ] = "CCTL"; - syntax[base + CTLBACKQ + CTLQUOTE] = "CCTL"; - syntax[base + CTLARI] = "CCTL"; - syntax[base + CTLENDARI] = "CCTL"; - syntax[base + CTLQUOTEMARK] = "CCTL"; - syntax[base + CTLQUOTEEND] = "CCTL"; + add_one("PEOF", "CEOF"); + add_one("CTLESC", "CCTL"); + add_one("CTLVAR", "CCTL"); + add_one("CTLENDVAR", "CCTL"); + add_one("CTLBACKQ", "CCTL"); + add_one("CTLBACKQ + CTLQUOTE", "CCTL"); + add_one("CTLARI", "CCTL"); + add_one("CTLENDARI", "CCTL"); + add_one("CTLQUOTEMARK", "CCTL"); + add_one("CTLQUOTEEND", "CCTL"); +} + + +/* + * Output the footer of a syntax table. + */ + +static void +finish(void) +{ + fputs("};\n", cfile); } @@ -287,44 +286,23 @@ init(void) static void add(const char *p, const char *type) { - while (*p) - syntax[*p++ + base] = type; -} + for (; *p; ++p) { + char c = *p; + switch (c) { + case '\t': c = 't'; break; + case '\n': c = 'n'; break; + case '\'': c = '\''; break; + case '\\': c = '\\'; break; - - -/* - * Output the syntax table. - */ - -static void -print(const char *name) -{ - int i; - int col; - - fprintf(hfile, "extern const char %s[];\n", name); - fprintf(cfile, "const char %s[%d] = {\n", name, size); - col = 0; - for (i = 0 ; i < size ; i++) { - if (i == 0) { - fputs(" ", cfile); - } else if ((i & 03) == 0) { - fputs(",\n ", cfile); - col = 0; - } else { - putc(',', cfile); - while (++col < 9 * (i & 03)) - putc(' ', cfile); + default: + fprintf(cfile, "\t[SYNBASE + '%c'] = %s,\n", c, type); + continue; } - fputs(syntax[i], cfile); - col += strlen(syntax[i]); + fprintf(cfile, "\t[SYNBASE + '\\%c'] = %s,\n", c, type); } - fputs("\n};\n", cfile); } - /* * Output character classification macros (e.g. is_digit). If digits are * contiguous, we can test for them quickly. From c43b08dc6cd0d4a45ba11a6d2aaeafbcd925270c Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Fri, 8 Feb 2013 07:29:07 +0000 Subject: [PATCH 0050/1476] ktr: correctly handle possible wrap-around in the boot buffer Older entries should be 'before' newer entries in the new buffer too and there should be no zero-filled gap between them. Pointed out by: jhb MFC after: 3 days X-MFC with: r246282 --- sys/kern/kern_ktr.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sys/kern/kern_ktr.c b/sys/kern/kern_ktr.c index a11c76cd553..3202b9b2546 100644 --- a/sys/kern/kern_ktr.c +++ b/sys/kern/kern_ktr.c @@ -213,7 +213,11 @@ ktr_entries_initializer(void *dummy __unused) ktr_mask = 0; ktr_buf = malloc(sizeof(*ktr_buf) * KTR_ENTRIES, M_KTR, M_WAITOK | M_ZERO); - memcpy(ktr_buf, ktr_buf_init, sizeof(ktr_buf_init)); + memcpy(ktr_buf, ktr_buf_init + ktr_idx, + (KTR_BOOT_ENTRIES - ktr_idx) * sizeof(*ktr_buf)); + if (ktr_idx != 0) + memcpy(ktr_buf + KTR_BOOT_ENTRIES - ktr_idx, ktr_buf_init, + ktr_idx * sizeof(*ktr_buf)); ktr_entries = KTR_ENTRIES; ktr_mask = mask; } From e2bb19dce531ae994204039cbb945445befdd50c Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Fri, 8 Feb 2013 07:44:15 +0000 Subject: [PATCH 0051/1476] zfs: update comments about zfid_long_t to match the FreeBSD definitions MFC after: 1 week --- .../contrib/opensolaris/uts/common/fs/zfs/sys/zfs_vfsops.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_vfsops.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_vfsops.h index 63cfb0074d7..3559f0de916 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_vfsops.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_vfsops.h @@ -110,7 +110,7 @@ typedef struct zfid_short { } zfid_short_t; /* - * Filesystems under .zfs/snapshot have a total file ID size of 22 bytes + * Filesystems under .zfs/snapshot have a total file ID size of 22[*] bytes * (including the length field). This makes files under .zfs/snapshot * accessible by NFSv3 and NFSv4, but not NFSv2. * @@ -120,10 +120,13 @@ typedef struct zfid_short { * 6 bytes object number (48 bits) * 4 bytes generation number (32 bits) * 6 bytes objset id (48 bits) - * 4 bytes currently just zero (32 bits) + * 4 bytes[**] currently just zero (32 bits) * * We reserve only 48 bits for the object number and objset id, as these are * the limits currently defined and imposed by the DMU. + * + * [*] 20 bytes on FreeBSD to fit into the size of struct fid. + * [**] 2 bytes on FreeBSD for the above reason. */ typedef struct zfid_long { zfid_short_t z_fid; From 0dcab786b8385938cb8d2a970f35c5ece0da6397 Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Fri, 8 Feb 2013 07:49:54 +0000 Subject: [PATCH 0052/1476] zfs_vget, zfs_fhtovp: properly handle the z_shares_dir object A special gfs vnode corresponds to that object. A regular zfs vnode must not be returned. This should be upstreamed. Reported by: pluknet Submitted by: rmacklem Tested by: pluknet MFC after: 10 days --- .../opensolaris/uts/common/fs/zfs/zfs_vfsops.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c index 7f3f7a1c21e..456e5aa6b00 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c @@ -2009,7 +2009,8 @@ zfs_vget(vfs_t *vfsp, ino_t ino, int flags, vnode_t **vpp) * .zfs/snapshot/ directories, that's why we return EOPNOTSUPP. * This will make NFS to switch to LOOKUP instead of using VGET. */ - if (ino == ZFSCTL_INO_ROOT || ino == ZFSCTL_INO_SNAPDIR) + if (ino == ZFSCTL_INO_ROOT || ino == ZFSCTL_INO_SNAPDIR || + (zfsvfs->z_shares_dir != 0 && ino == zfsvfs->z_shares_dir)) return (EOPNOTSUPP); ZFS_ENTER(zfsvfs); @@ -2101,14 +2102,22 @@ zfs_fhtovp(vfs_t *vfsp, fid_t *fidp, int flags, vnode_t **vpp) return (EINVAL); } - /* A zero fid_gen means we are in the .zfs control directories */ - if (fid_gen == 0 && - (object == ZFSCTL_INO_ROOT || object == ZFSCTL_INO_SNAPDIR)) { + /* + * A zero fid_gen means we are in .zfs or the .zfs/snapshot + * directory tree. If the object == zfsvfs->z_shares_dir, then + * we are in the .zfs/shares directory tree. + */ + if ((fid_gen == 0 && + (object == ZFSCTL_INO_ROOT || object == ZFSCTL_INO_SNAPDIR)) || + (zfsvfs->z_shares_dir != 0 && object == zfsvfs->z_shares_dir)) { *vpp = zfsvfs->z_ctldir; ASSERT(*vpp != NULL); if (object == ZFSCTL_INO_SNAPDIR) { VERIFY(zfsctl_root_lookup(*vpp, "snapshot", vpp, NULL, 0, NULL, NULL, NULL, NULL, NULL) == 0); + } else if (object == zfsvfs->z_shares_dir) { + VERIFY(zfsctl_root_lookup(*vpp, "shares", vpp, NULL, + 0, NULL, NULL, NULL, NULL, NULL) == 0); } else { VN_HOLD(*vpp); } From d03904f1dbe5c851f6fd1cf842ada5b45083e427 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Fri, 8 Feb 2013 09:07:03 +0000 Subject: [PATCH 0053/1476] Fix a corner case that I noticed with the AR5416 (and it's currently crappy 802.11n performance, sigh.) With the AR5416, aggregates need to be limited to 8KiB if RTS/CTS is enabled. However, larger aggregates were going out with RTSCTS enabled. The following was going on: * The first buffer in the list would have RTS/CTS enabled in bf->bf_state.txflags; * The aggregate would be formed; * The "copy over the txflags from the first buffer" logic that I added blanked the RTS/CTS TX flags fields, and then copied the bf_first RTS/CTS flags over; * .. but that'd cause bf_first to be blanked out! And thus the flag was cleared; * So the rest of the aggregate formation would run with those flags cleared, and thus > 8KiB aggregates were formed. The driver is now (again) correctly limiting aggregate formation for the AR5416 but there are still other pending issues to resolve. Tested: * AR5416, STA mode --- sys/dev/ath/if_ath_tx_ht.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/sys/dev/ath/if_ath_tx_ht.c b/sys/dev/ath/if_ath_tx_ht.c index e8319cdaa89..60a18630f3d 100644 --- a/sys/dev/ath/if_ath_tx_ht.c +++ b/sys/dev/ath/if_ath_tx_ht.c @@ -687,11 +687,6 @@ ath_tx_form_aggr(struct ath_softc *sc, struct ath_node *an, /* Set this early just so things don't get confused */ bf->bf_next = NULL; - /* - * Don't unlock the tid lock until we're sure we are going - * to queue this frame. - */ - /* * If the frame doesn't have a sequence number that we're * tracking in the BAW (eg NULL QOS data frame), we can't @@ -749,11 +744,13 @@ ath_tx_form_aggr(struct ath_softc *sc, struct ath_node *an, * that differs from the first frame, override the * subsequent frame with this config. */ - bf->bf_state.bfs_txflags &= - ~ (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA); - bf->bf_state.bfs_txflags |= - bf_first->bf_state.bfs_txflags & - (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA); + if (bf != bf_first) { + bf->bf_state.bfs_txflags &= + ~ (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA); + bf->bf_state.bfs_txflags |= + bf_first->bf_state.bfs_txflags & + (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA); + } /* * If the packet has a sequence number, do not From d6aee93f98f72b9473bd0b19f70d47ca8f3f14ed Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Fri, 8 Feb 2013 09:11:55 +0000 Subject: [PATCH 0054/1476] Fix ieee80211_mesh.c compilation. * Add the superg.h header to allow ieee80211_check_ff() to work * Since the assert stuff creates assertions based on line numbers and there was a conflict, just nudge things down a bit. --- sys/net80211/ieee80211_mesh.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sys/net80211/ieee80211_mesh.c b/sys/net80211/ieee80211_mesh.c index ee9eaedd7e7..6d323cdc863 100644 --- a/sys/net80211/ieee80211_mesh.c +++ b/sys/net80211/ieee80211_mesh.c @@ -60,6 +60,9 @@ __FBSDID("$FreeBSD$"); #include #include +#ifdef IEEE80211_SUPPORT_SUPERG +#include +#endif #include #include @@ -110,6 +113,7 @@ SYSCTL_PROC(_net_wlan_mesh, OID_AUTO, retrytimeout, CTLTYPE_INT | CTLFLAG_RW, &ieee80211_mesh_retrytimeout, 0, ieee80211_sysctl_msecs_ticks, "I", "Retry timeout (msec)"); static int ieee80211_mesh_holdingtimeout = -1; + SYSCTL_PROC(_net_wlan_mesh, OID_AUTO, holdingtimeout, CTLTYPE_INT | CTLFLAG_RW, &ieee80211_mesh_holdingtimeout, 0, ieee80211_sysctl_msecs_ticks, "I", "Holding state timeout (msec)"); From 3c56b4f165aa3d1679e137666d7f9e818f8474ab Mon Sep 17 00:00:00 2001 From: Sergey Kandaurov Date: Fri, 8 Feb 2013 09:54:53 +0000 Subject: [PATCH 0055/1476] Fix warning: comparison of unsigned expression < 0 is always false. Reported by: clang --- sys/cddl/dev/dtrace/dtrace_ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/cddl/dev/dtrace/dtrace_ioctl.c b/sys/cddl/dev/dtrace/dtrace_ioctl.c index fbc891d444f..6a01e132ed5 100644 --- a/sys/cddl/dev/dtrace/dtrace_ioctl.c +++ b/sys/cddl/dev/dtrace/dtrace_ioctl.c @@ -215,7 +215,7 @@ dtrace_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, "DTRACEIOC_AGGSNAP":"DTRACEIOC_BUFSNAP", curcpu, desc.dtbd_cpu); - if (desc.dtbd_cpu < 0 || desc.dtbd_cpu >= NCPU) + if (desc.dtbd_cpu >= NCPU) return (ENOENT); if (pcpu_find(desc.dtbd_cpu) == NULL) return (ENOENT); From efef5e5c1ee94d5647ccf63906fb65984150b71a Mon Sep 17 00:00:00 2001 From: Devin Teske Date: Fri, 8 Feb 2013 11:14:01 +0000 Subject: [PATCH 0056/1476] Remove NO_OBJ from Makefiles that generate manuals because this causes the GZIP compressed manuals to appear in ./src instead of the appropriate obj dir. PR: conf/175844 Submitted by: Dominique Goncalves --- usr.sbin/bsdconfig/Makefile | 2 -- usr.sbin/sysrc/Makefile | 2 -- 2 files changed, 4 deletions(-) diff --git a/usr.sbin/bsdconfig/Makefile b/usr.sbin/bsdconfig/Makefile index 75761945739..4faad0b4588 100644 --- a/usr.sbin/bsdconfig/Makefile +++ b/usr.sbin/bsdconfig/Makefile @@ -1,7 +1,5 @@ # $FreeBSD$ -NO_OBJ= - SUBDIR= console \ diskmgmt \ docsinstall \ diff --git a/usr.sbin/sysrc/Makefile b/usr.sbin/sysrc/Makefile index 38c52ee9625..ca3dc56bcf0 100644 --- a/usr.sbin/sysrc/Makefile +++ b/usr.sbin/sysrc/Makefile @@ -1,7 +1,5 @@ # $FreeBSD$ -NO_OBJ= - SCRIPTS= sysrc MAN= sysrc.8 From 5b2acfeca51d39d46173af7b39485eb87213855b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Fri, 8 Feb 2013 14:11:12 +0000 Subject: [PATCH 0057/1476] Cross-reference newgrp(1), and document the use of pw(8) to set the group password. PR: docs/167741 MFC after: 3 weeks --- share/man/man5/group.5 | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/share/man/man5/group.5 b/share/man/man5/group.5 index 4aa6affdd9f..4a366f67a00 100644 --- a/share/man/man5/group.5 +++ b/share/man/man5/group.5 @@ -32,7 +32,7 @@ .\" From: @(#)group.5 8.3 (Berkeley) 4/19/94 .\" $FreeBSD$ .\" -.Dd September 29, 1994 +.Dd February 8, 2013 .Dt GROUP 5 .Os .Sh NAME @@ -139,6 +139,7 @@ may still have this limit. .It Pa /etc/group .El .Sh SEE ALSO +.Xr newgrp 1 , .Xr passwd 1 , .Xr setgroups 2 , .Xr crypt 3 , @@ -156,9 +157,14 @@ file format appeared in .At v6 . Support for comments first appeared in .Fx 3.0 . -.Sh BUGS +.Sh IMPLEMENTATION NOTES The .Xr passwd 1 command does not change the .Nm passwords. +The +.Xr pw 8 +utility's +.Cm groupmod +command should be used instead. From 30c4fc7cf9350cb561bc93e3068b046a6c06120e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Fri, 8 Feb 2013 14:14:00 +0000 Subject: [PATCH 0058/1476] Print a warning if not setuid root. Document the need for the setuid bit and how to set it. Explain why it isn't set by default, and suggest simply adding users to groups instead. PR: docs/167741 MFC after: 3 weeks --- usr.bin/newgrp/newgrp.1 | 13 +++++++++++-- usr.bin/newgrp/newgrp.c | 3 ++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/usr.bin/newgrp/newgrp.1 b/usr.bin/newgrp/newgrp.1 index 44ab9fd5658..463558410a9 100644 --- a/usr.bin/newgrp/newgrp.1 +++ b/usr.bin/newgrp/newgrp.1 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd May 23, 2002 +.Dd February 8, 2013 .Dt NEWGRP 1 .Os .Sh NAME @@ -90,6 +90,15 @@ A utility appeared in .At v6 . .Sh BUGS +For security reasons, the +.Nm +utility is normally installed without the setuid bit. +To enable it, run the following command: +.Bd -literal -offset indent +chmod u+s /usr/bin/newgrp +.Ed +.Pp Group passwords are inherently insecure as there is no way to stop -users obtaining the crypted passwords from the group database. +users obtaining the password hash from the group database. Their use is discouraged. +Instead, users should simply be added to the necessary groups. diff --git a/usr.bin/newgrp/newgrp.c b/usr.bin/newgrp/newgrp.c index b3f6103b3ae..9b3972e9eaf 100644 --- a/usr.bin/newgrp/newgrp.c +++ b/usr.bin/newgrp/newgrp.c @@ -73,7 +73,8 @@ main(int argc, char *argv[]) { int ch, login; - euid = geteuid(); + if ((euid = geteuid()) != 0) + warnx("need root permissions to function properly, check setuid bit"); if (seteuid(getuid()) < 0) err(1, "seteuid"); From 00efd852ccf278ffe97a5034089aca24254cdfad Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Fri, 8 Feb 2013 15:52:20 +0000 Subject: [PATCH 0059/1476] The 'end' word was missed in the comment. MFC after: 3 days --- sys/sparc64/include/vmparam.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/sparc64/include/vmparam.h b/sys/sparc64/include/vmparam.h index 6b33e0f8716..a5ed2456a25 100644 --- a/sys/sparc64/include/vmparam.h +++ b/sys/sparc64/include/vmparam.h @@ -149,8 +149,8 @@ * * We define some interesting address constants: * - * VM_MIN_ADDRESS and VM_MAX_ADDRESS define the start and of the entire 64 bit - * address space, mostly just for convenience. + * VM_MIN_ADDRESS and VM_MAX_ADDRESS define the start and end of the entire + * 64 bit address space, mostly just for convenience. * * VM_MIN_DIRECT_ADDRESS and VM_MAX_DIRECT_ADDRESS define the start and end * of the direct mapped region. This maps virtual addresses to physical From 746ae9df1fd21008c33c2b7773b8e3a70fb66e69 Mon Sep 17 00:00:00 2001 From: Nathan Whitehorn Date: Fri, 8 Feb 2013 17:44:44 +0000 Subject: [PATCH 0060/1476] Avoid use of register variables, which some compilers (e.g. clang) don't like. It makes the code a little clearer as well. MFC after: 1 week --- libexec/rtld-elf/powerpc64/reloc.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/libexec/rtld-elf/powerpc64/reloc.c b/libexec/rtld-elf/powerpc64/reloc.c index b13500f5b43..fb5325f23dc 100644 --- a/libexec/rtld-elf/powerpc64/reloc.c +++ b/libexec/rtld-elf/powerpc64/reloc.c @@ -486,8 +486,7 @@ init_pltgot(Obj_Entry *obj) void allocate_initial_tls(Obj_Entry *list) { - register Elf_Addr **tp __asm__("r13"); - Elf_Addr **_tp; + Elf_Addr **tp; /* * Fix the size of the static TLS block by using the maximum @@ -497,22 +496,19 @@ allocate_initial_tls(Obj_Entry *list) tls_static_space = tls_last_offset + tls_last_size + RTLD_STATIC_TLS_EXTRA; - _tp = (Elf_Addr **) ((char *)allocate_tls(list, NULL, TLS_TCB_SIZE, 16) + tp = (Elf_Addr **) ((char *)allocate_tls(list, NULL, TLS_TCB_SIZE, 16) + TLS_TP_OFFSET + TLS_TCB_SIZE); - /* - * XXX gcc seems to ignore 'tp = _tp;' - */ - - __asm __volatile("mr %0,%1" : "=r"(tp) : "r"(_tp)); + __asm __volatile("mr 13,%0" :: "r"(tp)); } void* __tls_get_addr(tls_index* ti) { - register Elf_Addr **tp __asm__("r13"); + Elf_Addr **tp; char *p; + __asm __volatile("mr %0,13" : "=r"(tp)); p = tls_get_addr_common((Elf_Addr**)((Elf_Addr)tp - TLS_TP_OFFSET - TLS_TCB_SIZE), ti->ti_module, ti->ti_offset); From 5293f9bee4a6817f0a509c2c71a21512f26226a9 Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Fri, 8 Feb 2013 18:02:28 +0000 Subject: [PATCH 0061/1476] In the setfacl(1) manual page, make it clear that for NFSv4 ACLs, one should really use -a and -x instead of -m. MFC after: 1 week --- bin/setfacl/setfacl.1 | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/bin/setfacl/setfacl.1 b/bin/setfacl/setfacl.1 index 3d7b517a341..48878c4901d 100644 --- a/bin/setfacl/setfacl.1 +++ b/bin/setfacl/setfacl.1 @@ -26,7 +26,7 @@ .\" .\" $FreeBSD$ .\" -.Dd September 2, 2012 +.Dd February 8, 2013 .Dt SETFACL 1 .Os .Sh NAME @@ -95,6 +95,11 @@ Modify the ACL entries on the specified files by adding new entries and modifying existing ACL entries with the ACL entries specified in .Ar entries . +For NFSv4 ACLs, it is recommended to use the +.Fl a +and +.Fl x +instead. .It Fl M Ar file Modify the ACL entries on the specified files by adding new ACL entries and modifying existing ACL entries with the ACL From bac44ad2186f60518f547cda182bdea5908e969c Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Fri, 8 Feb 2013 18:12:16 +0000 Subject: [PATCH 0062/1476] Improve description of the "-m" option to setfacl(1). Submitted by: scottl MFC after: 1 week --- bin/setfacl/setfacl.1 | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/bin/setfacl/setfacl.1 b/bin/setfacl/setfacl.1 index 48878c4901d..c2173d30d29 100644 --- a/bin/setfacl/setfacl.1 +++ b/bin/setfacl/setfacl.1 @@ -91,15 +91,16 @@ An error will be reported if any of the specified files cannot have a default entry (i.e.\& non-directories). This option is not applicable to NFSv4 ACLs. .It Fl m Ar entries -Modify the ACL entries on the specified files by adding new -entries and modifying existing ACL entries with the ACL entries -specified in -.Ar entries . +Modify the ACL on the specified file. +New entries will be added, and existing entries will be modified +according to the +.Ar entries +argument. For NFSv4 ACLs, it is recommended to use the .Fl a and .Fl x -instead. +options instead. .It Fl M Ar file Modify the ACL entries on the specified files by adding new ACL entries and modifying existing ACL entries with the ACL From a3bc22a09b4d7f1468285cb6a3936405dc88487f Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Fri, 8 Feb 2013 18:43:47 +0000 Subject: [PATCH 0063/1476] Fix NFSv4 permission description in setfacl(1) manual page: the 'D' means delete_child, not delete. MFC after: 1 week --- bin/setfacl/setfacl.1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/setfacl/setfacl.1 b/bin/setfacl/setfacl.1 index c2173d30d29..83dc41a4265 100644 --- a/bin/setfacl/setfacl.1 +++ b/bin/setfacl/setfacl.1 @@ -325,9 +325,9 @@ write_data execute .It p append_data -.It d -delete_child .It D +delete_child +.It d delete .It a read_attributes From 23a368256d11f038954bd82f20232ce94b85681e Mon Sep 17 00:00:00 2001 From: "Pedro F. Giffuni" Date: Fri, 8 Feb 2013 19:39:15 +0000 Subject: [PATCH 0064/1476] patch: Follow original versioning convention. According to the README file [1] the 12u variant, unlike the 12g variant, contains no copyleft code. It is therefore convenient to keep using the original versioning scheme to prevent confusions. [1] http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/patch/README --- usr.bin/patch/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr.bin/patch/util.c b/usr.bin/patch/util.c index 3895b2c92ce..28a3cb0cf58 100644 --- a/usr.bin/patch/util.c +++ b/usr.bin/patch/util.c @@ -412,7 +412,7 @@ checked_in(char *file) void version(void) { - fprintf(stderr, "patch (BSD patch) 2.0-FreeBSD\n"); + fprintf(stderr, "patch 2.0-12u8 FreeBSD\n"); my_exit(EXIT_SUCCESS); } From a99b51055fa29a117f34b1b946dc4d423bd356f7 Mon Sep 17 00:00:00 2001 From: Alfred Perlstein Date: Fri, 8 Feb 2013 20:13:28 +0000 Subject: [PATCH 0065/1476] add semicolon to end of CALLOUT_HANDLE_INITIALIZER example. --- share/man/man9/timeout.9 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/man/man9/timeout.9 b/share/man/man9/timeout.9 index 543d198bb55..c67146799f6 100644 --- a/share/man/man9/timeout.9 +++ b/share/man/man9/timeout.9 @@ -62,7 +62,7 @@ typedef void timeout_t (void *); .Ft void .Fn callout_handle_init "struct callout_handle *handle" .Bd -literal -struct callout_handle handle = CALLOUT_HANDLE_INITIALIZER(&handle) +struct callout_handle handle = CALLOUT_HANDLE_INITIALIZER(&handle); .Ed .Ft void .Fn untimeout "timeout_t *func" "void *arg" "struct callout_handle handle" From a940ce65cd48c6f6bec61e110ccb8cf07b5ea12d Mon Sep 17 00:00:00 2001 From: "Pedro F. Giffuni" Date: Fri, 8 Feb 2013 20:30:19 +0000 Subject: [PATCH 0066/1476] Remove unused MAXSYMLINKLEN macro. Reviewed by: mckusick PR: kern/175794 MFC after: 1 week --- sys/fs/ext2fs/inode.h | 1 - sys/ufs/ufs/inode.h | 4 ---- 2 files changed, 5 deletions(-) diff --git a/sys/fs/ext2fs/inode.h b/sys/fs/ext2fs/inode.h index ec472164c17..6cb85ca995e 100644 --- a/sys/fs/ext2fs/inode.h +++ b/sys/fs/ext2fs/inode.h @@ -108,7 +108,6 @@ struct inode { */ #define i_shortlink i_db #define i_rdev i_db[0] -#define MAXSYMLINKLEN ((NDADDR + NIADDR) * sizeof(int32_t)) /* File permissions. */ #define IEXEC 0000100 /* Executable. */ diff --git a/sys/ufs/ufs/inode.h b/sys/ufs/ufs/inode.h index 59b170cfef6..6416632f4b4 100644 --- a/sys/ufs/ufs/inode.h +++ b/sys/ufs/ufs/inode.h @@ -151,10 +151,6 @@ struct inode { (ip)->i_din2->d##field = (val); \ } while (0) -#define MAXSYMLINKLEN(ip) \ - ((ip)->i_ump->um_fstype == UFS1) ? \ - ((NDADDR + NIADDR) * sizeof(ufs1_daddr_t)) : \ - ((NDADDR + NIADDR) * sizeof(ufs2_daddr_t)) #define SHORTLINK(ip) \ (((ip)->i_ump->um_fstype == UFS1) ? \ (caddr_t)(ip)->i_din1->di_db : (caddr_t)(ip)->i_din2->di_db) From 1a125d6d8502991bcf7d7b2b59070e60866d7ec6 Mon Sep 17 00:00:00 2001 From: "Pedro F. Giffuni" Date: Fri, 8 Feb 2013 20:58:00 +0000 Subject: [PATCH 0067/1476] ext2fs: make e2fs_maxcontig local and remove tautological check. e2fs_maxcontig was modelled after UFS when bringing the "Orlov allocator" to ext2. On UFS fs_maxcontig is kept in the superblock and is used by userland tools (fsck and growfs), In ext2 this information is volatile so it is not available for userland tools, so in this case it doesn't have sense to carry it in the in-memory superblock. Also remove a pointless check for MAX(1, x) > 0. Submitted by: Christoph Mallon MFC after: 2 weeks --- sys/fs/ext2fs/ext2_vfsops.c | 9 +++------ sys/fs/ext2fs/ext2fs.h | 1 - 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/sys/fs/ext2fs/ext2_vfsops.c b/sys/fs/ext2fs/ext2_vfsops.c index 136f01c3d61..d0f3edb9850 100644 --- a/sys/fs/ext2fs/ext2_vfsops.c +++ b/sys/fs/ext2fs/ext2_vfsops.c @@ -527,6 +527,7 @@ ext2_mountfs(struct vnode *devvp, struct mount *mp) int ronly; int i, size; int32_t *lp; + int32_t e2fs_maxcontig; ronly = vfs_flagopt(mp->mnt_optnew, "ro", NULL, 0); /* XXX: use VOP_ACESS to check FS perms */ @@ -601,12 +602,8 @@ ext2_mountfs(struct vnode *devvp, struct mount *mp) * in ext2fs doesn't have these variables, so we can calculate * them here. */ - ump->um_e2fs->e2fs_maxcontig = MAX(1, MAXPHYS / ump->um_e2fs->e2fs_bsize); - if (ump->um_e2fs->e2fs_maxcontig > 0) - ump->um_e2fs->e2fs_contigsumsize = - MIN(ump->um_e2fs->e2fs_maxcontig, EXT2_MAXCONTIG); - else - ump->um_e2fs->e2fs_contigsumsize = 0; + e2fs_maxcontig = MAX(1, MAXPHYS / ump->um_e2fs->e2fs_bsize); + ump->um_e2fs->e2fs_contigsumsize = MIN(e2fs_maxcontig, EXT2_MAXCONTIG); if (ump->um_e2fs->e2fs_contigsumsize > 0) { size = ump->um_e2fs->e2fs_gcount * sizeof(int32_t); ump->um_e2fs->e2fs_maxcluster = malloc(size, M_EXT2MNT, M_WAITOK); diff --git a/sys/fs/ext2fs/ext2fs.h b/sys/fs/ext2fs/ext2fs.h index c5a4c15cac2..02cdcdab6b0 100644 --- a/sys/fs/ext2fs/ext2fs.h +++ b/sys/fs/ext2fs/ext2fs.h @@ -170,7 +170,6 @@ struct m_ext2fs { char e2fs_wasvalid; /* valid at mount time */ off_t e2fs_maxfilesize; struct ext2_gd *e2fs_gd; /* Group Descriptors */ - int32_t e2fs_maxcontig; /* max number of contiguous blks */ int32_t e2fs_contigsumsize; /* size of cluster summary array */ int32_t *e2fs_maxcluster; /* max cluster in each cyl group */ struct csum *e2fs_clustersum; /* cluster summary in each cyl group */ From 4e1e0e258277deaf1a82b534c998f206ca98b0e1 Mon Sep 17 00:00:00 2001 From: "Pedro F. Giffuni" Date: Fri, 8 Feb 2013 21:09:44 +0000 Subject: [PATCH 0068/1476] ext2fs: Replace redundant EXT2_MIN_BLOCK with EXT2_MIN_BLOCK_SIZE. Submitted by: Christoph Mallon MFC after: 2 weeks --- sys/fs/ext2fs/ext2_vfsops.c | 2 +- sys/fs/ext2fs/ext2fs.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/sys/fs/ext2fs/ext2_vfsops.c b/sys/fs/ext2fs/ext2_vfsops.c index d0f3edb9850..cdb41ba1f36 100644 --- a/sys/fs/ext2fs/ext2_vfsops.c +++ b/sys/fs/ext2fs/ext2_vfsops.c @@ -320,8 +320,8 @@ compute_sb_data(struct vnode *devvp, struct ext2fs *es, struct buf *bp; uint32_t e2fs_descpb; - fs->e2fs_bsize = EXT2_MIN_BLOCK_SIZE << es->e2fs_log_bsize; fs->e2fs_bshift = EXT2_MIN_BLOCK_LOG_SIZE + es->e2fs_log_bsize; + fs->e2fs_bsize = 1U << fs->e2fs_bshift; fs->e2fs_fsbtodb = es->e2fs_log_bsize + 1; fs->e2fs_qbmask = fs->e2fs_bsize - 1; fs->e2fs_fsize = EXT2_MIN_FRAG_SIZE << es->e2fs_log_fsize; diff --git a/sys/fs/ext2fs/ext2fs.h b/sys/fs/ext2fs/ext2fs.h index 02cdcdab6b0..225e05892d6 100644 --- a/sys/fs/ext2fs/ext2fs.h +++ b/sys/fs/ext2fs/ext2fs.h @@ -303,7 +303,6 @@ struct csum { /* * Macro-instructions used to manage several block sizes */ -#define EXT2_MIN_BLOCK_SIZE 1024 #define EXT2_MAX_BLOCK_SIZE 4096 #define EXT2_MIN_BLOCK_LOG_SIZE 10 #define EXT2_BLOCK_SIZE(s) ((s)->e2fs_bsize) From 2d8a425be01526b346810a775893b950bb4ac399 Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Fri, 8 Feb 2013 21:15:47 +0000 Subject: [PATCH 0069/1476] Fix regression issue after r244503: Correct init order to fix a NULL pointer access. MFC after: 1 week Reported by: Ian FREISLICH --- sys/dev/usb/wlan/if_uath.c | 26 +++++++++++++------------- sys/dev/usb/wlan/if_upgt.c | 24 ++++++++++++------------ 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/sys/dev/usb/wlan/if_uath.c b/sys/dev/usb/wlan/if_uath.c index 0ac57afd6a2..37162c08931 100644 --- a/sys/dev/usb/wlan/if_uath.c +++ b/sys/dev/usb/wlan/if_uath.c @@ -358,22 +358,12 @@ uath_attach(device_t dev) callout_init(&sc->stat_ch, 0); callout_init_mtx(&sc->watchdog_ch, &sc->sc_mtx, 0); - /* - * Allocate xfers for firmware commands. - */ - error = uath_alloc_cmd_list(sc, sc->sc_cmd); - if (error != 0) { - device_printf(sc->sc_dev, - "could not allocate Tx command list\n"); - goto fail; - } - error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer, uath_usbconfig, UATH_N_XFERS, sc, &sc->sc_mtx); if (error) { device_printf(dev, "could not allocate USB transfers, " "err=%s\n", usbd_errstr(error)); - goto fail1; + goto fail; } sc->sc_cmd_dma_buf = @@ -381,6 +371,16 @@ uath_attach(device_t dev) sc->sc_tx_dma_buf = usbd_xfer_get_frame_buffer(sc->sc_xfer[UATH_BULK_TX], 0); + /* + * Setup buffers for firmware commands. + */ + error = uath_alloc_cmd_list(sc, sc->sc_cmd); + if (error != 0) { + device_printf(sc->sc_dev, + "could not allocate Tx command list\n"); + goto fail1; + } + /* * We're now ready to send+receive firmware commands. */ @@ -492,8 +492,8 @@ uath_attach(device_t dev) fail4: if_free(ifp); fail3: UATH_UNLOCK(sc); -fail2: usbd_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS); -fail1: uath_free_cmd_list(sc, sc->sc_cmd); +fail2: uath_free_cmd_list(sc, sc->sc_cmd); +fail1: usbd_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS); fail: return (error); } diff --git a/sys/dev/usb/wlan/if_upgt.c b/sys/dev/usb/wlan/if_upgt.c index c625926795f..6b49df1f836 100644 --- a/sys/dev/usb/wlan/if_upgt.c +++ b/sys/dev/usb/wlan/if_upgt.c @@ -259,20 +259,12 @@ upgt_attach(device_t dev) callout_init(&sc->sc_led_ch, 0); callout_init(&sc->sc_watchdog_ch, 0); - /* Allocate TX and RX xfers. */ - error = upgt_alloc_tx(sc); - if (error) - goto fail1; - error = upgt_alloc_rx(sc); - if (error) - goto fail2; - error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer, upgt_config, UPGT_N_XFERS, sc, &sc->sc_mtx); if (error) { device_printf(dev, "could not allocate USB transfers, " "err=%s\n", usbd_errstr(error)); - goto fail3; + goto fail1; } sc->sc_rx_dma_buf = usbd_xfer_get_frame_buffer( @@ -280,6 +272,14 @@ upgt_attach(device_t dev) sc->sc_tx_dma_buf = usbd_xfer_get_frame_buffer( sc->sc_xfer[UPGT_BULK_TX], 0); + /* Setup TX and RX buffers */ + error = upgt_alloc_tx(sc); + if (error) + goto fail2; + error = upgt_alloc_rx(sc); + if (error) + goto fail3; + ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211); if (ifp == NULL) { device_printf(dev, "can not if_alloc()\n"); @@ -382,9 +382,9 @@ upgt_attach(device_t dev) return (0); fail5: if_free(ifp); -fail4: usbd_transfer_unsetup(sc->sc_xfer, UPGT_N_XFERS); -fail3: upgt_free_rx(sc); -fail2: upgt_free_tx(sc); +fail4: upgt_free_rx(sc); +fail3: upgt_free_tx(sc); +fail2: usbd_transfer_unsetup(sc->sc_xfer, UPGT_N_XFERS); fail1: mtx_destroy(&sc->sc_mtx); return (error); From 08c49d655e52c45d2b0da8818d06656a68ecbdfe Mon Sep 17 00:00:00 2001 From: Xin LI Date: Fri, 8 Feb 2013 22:41:48 +0000 Subject: [PATCH 0070/1476] In r246282 the KTR_ENTRIES was specified with syntax error, fix it so 'make universe' would work. MFC after: 12 days X-MFC-with: r246282 --- sys/conf/NOTES | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/conf/NOTES b/sys/conf/NOTES index ff245ede261..5d26093f9fb 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -462,7 +462,7 @@ options KTRACE_REQUEST_POOL=101 # options KTR options KTR_BOOT_ENTRIES=1024 -options KTR_ENTRIES=(128 * 1024) +options KTR_ENTRIES=(128*1024) options KTR_COMPILE=(KTR_INTR|KTR_PROC) options KTR_MASK=KTR_INTR options KTR_CPUMASK=0x3 From 056e0b5dcdc09315d97fa11a6cf9115f19694317 Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Fri, 8 Feb 2013 22:51:09 +0000 Subject: [PATCH 0071/1476] Make sure we don't leak command buffers when a USB command transfer fails. MFC after: 1 week Reported by: Ian FREISLICH --- sys/dev/usb/wlan/if_uath.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sys/dev/usb/wlan/if_uath.c b/sys/dev/usb/wlan/if_uath.c index 37162c08931..938e52ebb76 100644 --- a/sys/dev/usb/wlan/if_uath.c +++ b/sys/dev/usb/wlan/if_uath.c @@ -2436,11 +2436,8 @@ uath_intr_tx_callback(struct usb_xfer *xfer, usb_error_t error) UATH_ASSERT_LOCKED(sc); - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - cmd = STAILQ_FIRST(&sc->sc_cmd_active); - if (cmd == NULL) - goto setup; + cmd = STAILQ_FIRST(&sc->sc_cmd_active); + if (cmd != NULL && USB_GET_STATE(xfer) != USB_ST_SETUP) { STAILQ_REMOVE_HEAD(&sc->sc_cmd_active, next); UATH_STAT_DEC(sc, st_cmd_active); STAILQ_INSERT_TAIL((cmd->flags & UATH_CMD_FLAG_READ) ? @@ -2449,7 +2446,10 @@ uath_intr_tx_callback(struct usb_xfer *xfer, usb_error_t error) UATH_STAT_INC(sc, st_cmd_waiting); else UATH_STAT_INC(sc, st_cmd_inactive); - /* FALLTHROUGH */ + } + + switch (USB_GET_STATE(xfer)) { + case USB_ST_TRANSFERRED: case USB_ST_SETUP: setup: cmd = STAILQ_FIRST(&sc->sc_cmd_pending); From c3400997c48452e75387253a9971ec26fa20cc09 Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Fri, 8 Feb 2013 23:13:46 +0000 Subject: [PATCH 0072/1476] Correctly list the usbloader dependencies. --- sys/boot/usb/Makefile.test | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/boot/usb/Makefile.test b/sys/boot/usb/Makefile.test index a366d36aa43..b7139e72c90 100644 --- a/sys/boot/usb/Makefile.test +++ b/sys/boot/usb/Makefile.test @@ -53,9 +53,9 @@ SRCS+= bsd_usbloader_test.c LDADD+= libusbboot.a DPADD+= libusbboot.a -all: libusbboot.a - .include +${PROG}: libusbboot.a + libusbboot.a: make -f Makefile From bf3db9ebd8e439a6d809cef564240fd523927748 Mon Sep 17 00:00:00 2001 From: Navdeep Parhar Date: Sat, 9 Feb 2013 00:35:28 +0000 Subject: [PATCH 0073/1476] Do not hold locks around hardware context reads. MFC after: 3 days --- sys/dev/cxgbe/t4_main.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c index c22ec21a020..96246a60c74 100644 --- a/sys/dev/cxgbe/t4_main.c +++ b/sys/dev/cxgbe/t4_main.c @@ -5161,23 +5161,24 @@ get_sge_context(struct adapter *sc, struct t4_sge_context *cntxt) cntxt->mem_id != CTXT_FLM && cntxt->mem_id != CTXT_CNM) return (EINVAL); + rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4ctxt"); + if (rc) + return (rc); + if (sc->flags & FW_OK) { - rc = begin_synchronized_op(sc, NULL, HOLD_LOCK, "t4ctxt"); - if (rc == 0) { - rc = -t4_sge_ctxt_rd(sc, sc->mbox, cntxt->cid, - cntxt->mem_id, &cntxt->data[0]); - end_synchronized_op(sc, LOCK_HELD); - if (rc == 0) - return (0); - } + rc = -t4_sge_ctxt_rd(sc, sc->mbox, cntxt->cid, cntxt->mem_id, + &cntxt->data[0]); + if (rc == 0) + goto done; } /* * Read via firmware failed or wasn't even attempted. Read directly via * the backdoor. */ - rc = -t4_sge_ctxt_rd_bd(sc, cntxt->cid, cntxt->mem_id, - &cntxt->data[0]); + rc = -t4_sge_ctxt_rd_bd(sc, cntxt->cid, cntxt->mem_id, &cntxt->data[0]); +done: + end_synchronized_op(sc, 0); return (rc); } From 650da23095c37c66fc753585a11d5411e6877403 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Sat, 9 Feb 2013 02:42:01 +0000 Subject: [PATCH 0074/1476] The encryption type field needs to be preserved for each descriptor making up a frame, in both a sub-frame and for all frames in an aggregate. Tested: * AR5416, STA mode --- sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c b/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c index 0a226ffec05..36f968fc7d7 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c @@ -306,10 +306,14 @@ ar5416FillTxDesc(struct ath_hal *ah, struct ath_desc *ds, & AR_TxIntrReq; ads->ds_ctl2 = __bswap32(AR5416DESC_CONST(ds0)->ds_ctl2); ads->ds_ctl3 = __bswap32(AR5416DESC_CONST(ds0)->ds_ctl3); + /* ctl6 - we only need encrtype; the rest are blank */ + ads->ds_ctl6 = __bswap32(AR5416DESC_CONST(ds0)->ds_ctl6 & AR_EncrType); #else ads->ds_ctl0 = AR5416DESC_CONST(ds0)->ds_ctl0 & AR_TxIntrReq; ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2; ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3; + /* ctl6 - we only need encrtype; the rest are blank */ + ads->ds_ctl6 = AR5416DESC_CONST(ds0)->ds_ctl6 & AR_EncrType; #endif } else { /* !firstSeg && !lastSeg */ /* @@ -318,8 +322,10 @@ ar5416FillTxDesc(struct ath_hal *ah, struct ath_desc *ds, #ifdef AH_NEED_DESC_SWAP ads->ds_ctl0 = __bswap32(AR5416DESC_CONST(ds0)->ds_ctl0) & AR_TxIntrReq; + ads->ds_ctl6 = __bswap32(AR5416DESC_CONST(ds0)->ds_ctl6 & AR_EncrType); #else ads->ds_ctl0 = AR5416DESC_CONST(ds0)->ds_ctl0 & AR_TxIntrReq; + ads->ds_ctl6 = AR5416DESC_CONST(ds0)->ds_ctl6 & AR_EncrType; #endif ads->ds_ctl1 = segLen | AR_TxMore; ads->ds_ctl2 = 0; From 3b9ba32d88837435feb81f675c8a5694755ccfce Mon Sep 17 00:00:00 2001 From: Xin LI Date: Sat, 9 Feb 2013 04:13:45 +0000 Subject: [PATCH 0075/1476] Fix LINT build on amd64. --- sys/ofed/drivers/net/mlx4/en_tx.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sys/ofed/drivers/net/mlx4/en_tx.c b/sys/ofed/drivers/net/mlx4/en_tx.c index fee7afecd5d..d2852208550 100644 --- a/sys/ofed/drivers/net/mlx4/en_tx.c +++ b/sys/ofed/drivers/net/mlx4/en_tx.c @@ -936,16 +936,16 @@ mlx4_en_transmit_locked(struct ifnet *dev, int tx_ind, struct mbuf *m) return (err); } /* Process the queue */ - while ((next = drbr_peek(ifp, ring->br)) != NULL) { + while ((next = drbr_peek(dev, ring->br)) != NULL) { if ((err = mlx4_en_xmit(dev, tx_ind, &next)) != 0) { if (next == NULL) { - drbr_advance(ifp, ring->br); + drbr_advance(dev, ring->br); } else { - drbr_putback(ifp, ring->br, next); + drbr_putback(dev, ring->br, next); } break; } - drbr_advance(ifp, ring->br); + drbr_advance(dev, ring->br); enqueued++; dev->if_obytes += next->m_pkthdr.len; if (next->m_flags & M_MCAST) From 18c573e000c66e025440be55b5ad47b4ab92b063 Mon Sep 17 00:00:00 2001 From: Xin LI Date: Sat, 9 Feb 2013 06:31:22 +0000 Subject: [PATCH 0076/1476] Fix LINT build for ARM. --- sys/modules/usb/smsc/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/modules/usb/smsc/Makefile b/sys/modules/usb/smsc/Makefile index c6f2de80013..eca1c9c520f 100644 --- a/sys/modules/usb/smsc/Makefile +++ b/sys/modules/usb/smsc/Makefile @@ -33,5 +33,6 @@ KMOD= if_smsc SRCS= opt_bus.h opt_usb.h device_if.h bus_if.h usb_if.h usbdevs.h \ miibus_if.h opt_inet.h opt_platform.h \ if_smsc.c +SRCS+= ofw_bus_if.h .include From 1848dd2aece9ab0ea330b400d9d8e7ddd6406451 Mon Sep 17 00:00:00 2001 From: Joel Dahl Date: Sat, 9 Feb 2013 07:01:05 +0000 Subject: [PATCH 0077/1476] mdoc: Remove EOL whitespace. --- cddl/contrib/opensolaris/cmd/zpool/zpool-features.7 | 6 +++--- lib/libc/stdio/fopen.3 | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cddl/contrib/opensolaris/cmd/zpool/zpool-features.7 b/cddl/contrib/opensolaris/cmd/zpool/zpool-features.7 index 2768ef5ee95..caf0751e462 100644 --- a/cddl/contrib/opensolaris/cmd/zpool/zpool-features.7 +++ b/cddl/contrib/opensolaris/cmd/zpool/zpool-features.7 @@ -199,7 +199,7 @@ features significantly faster compression and decompression as well as a higher compression ratio than the older .Sy lzjb compression. -Typically, +Typically, .Sy lz4 compression is approximately 50% faster on compressible data and 200% faster on incompressible data than @@ -207,12 +207,12 @@ compressible data and 200% faster on incompressible data than It is also approximately 80% faster on decompression, while giving approximately 10% better compression ratio. .Pp -When the +When the .Sy lz4_compress feature is set to .Sy enabled , the -administrator can turn on +administrator can turn on .Sy lz4 compression on any dataset on the pool using the diff --git a/lib/libc/stdio/fopen.3 b/lib/libc/stdio/fopen.3 index a07be387327..f11f4e07e3d 100644 --- a/lib/libc/stdio/fopen.3 +++ b/lib/libc/stdio/fopen.3 @@ -332,7 +332,7 @@ but is also supported by glibc. The .Fn fmemopen function -conforms to +conforms to .St -p1003.1-2008 . The ``b'' mode does not conform to any standard but is also supported by glibc. From c39cfa1f7eb2cfeb4fa66b280ff28dae311959bc Mon Sep 17 00:00:00 2001 From: Michael Tuexen Date: Sat, 9 Feb 2013 08:27:08 +0000 Subject: [PATCH 0078/1476] Fix a bug where HEARTBEATs were still sent in SHUTDOWN_SENT or SHUTDOWN_ACK_SENT state. While there, make the corresponding code consistent. MFC after: 1 week --- sys/netinet/sctp_indata.c | 34 +++++++++++++++++----------------- sys/netinet/sctp_input.c | 2 +- sys/netinet/sctp_output.c | 16 +++++++++------- sys/netinet/sctp_pcb.c | 13 +++++++------ sys/netinet/sctp_timer.c | 13 +++++++------ sys/netinet/sctp_usrreq.c | 33 ++++++++++++++++----------------- 6 files changed, 57 insertions(+), 54 deletions(-) diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c index 112920b920f..96e9713c386 100644 --- a/sys/netinet/sctp_indata.c +++ b/sys/netinet/sctp_indata.c @@ -4262,19 +4262,19 @@ again: (asoc->stream_queue_cnt == 0)) { struct sctp_nets *netp; - if (asoc->alternate) { - netp = asoc->alternate; - } else { - netp = asoc->primary_destination; - } if (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT) { goto abort_out_now; } SCTP_STAT_DECR_GAUGE32(sctps_currestab); SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT); SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); - sctp_send_shutdown_ack(stcb, netp); sctp_stop_timers_for_shutdown(stcb); + if (asoc->alternate) { + netp = asoc->alternate; + } else { + netp = asoc->primary_destination; + } + sctp_send_shutdown_ack(stcb, netp); sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK, stcb->sctp_ep, stcb, netp); } @@ -4973,11 +4973,6 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup, } else { struct sctp_nets *netp; - if (asoc->alternate) { - netp = asoc->alternate; - } else { - netp = asoc->primary_destination; - } if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) || (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { SCTP_STAT_DECR_GAUGE32(sctps_currestab); @@ -4985,6 +4980,11 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup, SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT); SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); sctp_stop_timers_for_shutdown(stcb); + if (asoc->alternate) { + netp = asoc->alternate; + } else { + netp = asoc->primary_destination; + } sctp_send_shutdown(stcb, netp); sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, netp); @@ -4996,19 +4996,19 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup, (asoc->stream_queue_cnt == 0)) { struct sctp_nets *netp; - if (asoc->alternate) { - netp = asoc->alternate; - } else { - netp = asoc->primary_destination; - } if (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT) { goto abort_out_now; } SCTP_STAT_DECR_GAUGE32(sctps_currestab); SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT); SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); - sctp_send_shutdown_ack(stcb, netp); sctp_stop_timers_for_shutdown(stcb); + if (asoc->alternate) { + netp = asoc->alternate; + } else { + netp = asoc->primary_destination; + } + sctp_send_shutdown_ack(stcb, netp); sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK, stcb->sctp_ep, stcb, netp); return; diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index c70bc033dd9..511c1e2a6cd 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -956,7 +956,6 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp, } else { /* no outstanding data to send, so move on... */ /* send SHUTDOWN-ACK */ - sctp_send_shutdown_ack(stcb, net); /* move to SHUTDOWN-ACK-SENT state */ if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) || (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { @@ -965,6 +964,7 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp, SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT); SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); sctp_stop_timers_for_shutdown(stcb); + sctp_send_shutdown_ack(stcb, net); sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK, stcb->sctp_ep, stcb, net); } diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 5ec6228e76f..a5a3e5a1300 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -6574,12 +6574,13 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr, * only send SHUTDOWN the first time * through */ - sctp_send_shutdown(stcb, net); if (SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) { SCTP_STAT_DECR_GAUGE32(sctps_currestab); } SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT); SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); + sctp_stop_timers_for_shutdown(stcb); + sctp_send_shutdown(stcb, net); sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net); sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb, @@ -13092,18 +13093,19 @@ dataless_eof: (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) { struct sctp_nets *netp; - if (stcb->asoc.alternate) { - netp = stcb->asoc.alternate; - } else { - netp = stcb->asoc.primary_destination; - } /* only send SHUTDOWN the first time through */ - sctp_send_shutdown(stcb, netp); if (SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) { SCTP_STAT_DECR_GAUGE32(sctps_currestab); } SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT); SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); + sctp_stop_timers_for_shutdown(stcb); + if (stcb->asoc.alternate) { + netp = stcb->asoc.alternate; + } else { + netp = stcb->asoc.primary_destination; + } + sctp_send_shutdown(stcb, netp); sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, netp); sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb, diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c index 4bd8cb8182a..9f817a34fce 100644 --- a/sys/netinet/sctp_pcb.c +++ b/sys/netinet/sctp_pcb.c @@ -3332,22 +3332,23 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) (SCTP_GET_STATE(&asoc->asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) { struct sctp_nets *netp; - if (asoc->asoc.alternate) { - netp = asoc->asoc.alternate; - } else { - netp = asoc->asoc.primary_destination; - } /* * there is nothing queued to send, * so I send shutdown */ - sctp_send_shutdown(asoc, netp); if ((SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_OPEN) || (SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { SCTP_STAT_DECR_GAUGE32(sctps_currestab); } SCTP_SET_STATE(&asoc->asoc, SCTP_STATE_SHUTDOWN_SENT); SCTP_CLEAR_SUBSTATE(&asoc->asoc, SCTP_STATE_SHUTDOWN_PENDING); + sctp_stop_timers_for_shutdown(asoc); + if (asoc->asoc.alternate) { + netp = asoc->asoc.alternate; + } else { + netp = asoc->asoc.primary_destination; + } + sctp_send_shutdown(asoc, netp); sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, asoc->sctp_ep, asoc, netp); sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, asoc->sctp_ep, asoc, diff --git a/sys/netinet/sctp_timer.c b/sys/netinet/sctp_timer.c index 69505c39514..a09ba34ff75 100644 --- a/sys/netinet/sctp_timer.c +++ b/sys/netinet/sctp_timer.c @@ -1560,18 +1560,19 @@ sctp_autoclose_timer(struct sctp_inpcb *inp, /* only send SHUTDOWN 1st time thru */ struct sctp_nets *netp; - if (stcb->asoc.alternate) { - netp = stcb->asoc.alternate; - } else { - netp = stcb->asoc.primary_destination; - } - sctp_send_shutdown(stcb, netp); if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) || (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { SCTP_STAT_DECR_GAUGE32(sctps_currestab); } SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT); SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); + sctp_stop_timers_for_shutdown(stcb); + if (stcb->asoc.alternate) { + netp = stcb->asoc.alternate; + } else { + netp = stcb->asoc.primary_destination; + } + sctp_send_shutdown(stcb, netp); sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, netp); diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c index 0596f87ef3a..383ff0b98fa 100644 --- a/sys/netinet/sctp_usrreq.c +++ b/sys/netinet/sctp_usrreq.c @@ -794,25 +794,24 @@ sctp_disconnect(struct socket *so) /* only send SHUTDOWN 1st time thru */ struct sctp_nets *netp; - if (stcb->asoc.alternate) { - netp = stcb->asoc.alternate; - } else { - netp = stcb->asoc.primary_destination; - } - sctp_stop_timers_for_shutdown(stcb); - sctp_send_shutdown(stcb, netp); - sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_LOCKED); if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) || (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { SCTP_STAT_DECR_GAUGE32(sctps_currestab); } SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT); SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); + sctp_stop_timers_for_shutdown(stcb); + if (stcb->asoc.alternate) { + netp = stcb->asoc.alternate; + } else { + netp = stcb->asoc.primary_destination; + } + sctp_send_shutdown(stcb, netp); sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, netp); sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb, netp); - + sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_LOCKED); } } else { /* @@ -1014,24 +1013,24 @@ sctp_shutdown(struct socket *so) /* only send SHUTDOWN the first time through */ struct sctp_nets *netp; - if (stcb->asoc.alternate) { - netp = stcb->asoc.alternate; - } else { - netp = stcb->asoc.primary_destination; - } - sctp_stop_timers_for_shutdown(stcb); - sctp_send_shutdown(stcb, netp); - sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_LOCKED); if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) || (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { SCTP_STAT_DECR_GAUGE32(sctps_currestab); } SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT); SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); + sctp_stop_timers_for_shutdown(stcb); + if (stcb->asoc.alternate) { + netp = stcb->asoc.alternate; + } else { + netp = stcb->asoc.primary_destination; + } + sctp_send_shutdown(stcb, netp); sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, netp); sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb, netp); + sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_LOCKED); } } else { /* From 8697485a12963b03fdfac4daf67281033b8025f8 Mon Sep 17 00:00:00 2001 From: Antoine Brodin Date: Sat, 9 Feb 2013 13:28:49 +0000 Subject: [PATCH 0079/1476] Add more obsolete files. --- ObsoleteFiles.inc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index 6fda6078134..33bb90b910b 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -45,6 +45,10 @@ OLD_DIRS+=usr/share/man/man1aout OLD_DIRS+=usr/share/man/cat1aout OLD_DIRS+=usr/share/man/en.ISO8859-1/cat1aout OLD_DIRS+=usr/share/man/en.UTF-8/cat1aout +# 20130110: bsd.compat.mk removed +OLD_FILES+=usr/share/mk/bsd.compat.mk +# 20130103: gnats-supfile removed +OLD_FILES+=usr/share/examples/cvsup/gnats-supfile # 20121230: libdisk removed OLD_FILES+=usr/share/man/man3/libdisk.3.gz usr/include/libdisk.h OLD_FILES+=usr/lib/libdisk.a usr/lib32/libdisk.a From 7d493395a1971b9082f4ffbdd11cd52f02773ce0 Mon Sep 17 00:00:00 2001 From: Antoine Brodin Date: Sat, 9 Feb 2013 13:31:59 +0000 Subject: [PATCH 0080/1476] Fix some NLS catalogs broken after r245888. --- usr.bin/ee/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr.bin/ee/Makefile b/usr.bin/ee/Makefile index 22367772b62..7437731ade2 100644 --- a/usr.bin/ee/Makefile +++ b/usr.bin/ee/Makefile @@ -16,7 +16,7 @@ WARNS?= 2 NLS= C fr_FR.ISO8859-1 de_DE.ISO8859-1 pl_PL.ISO8859-2 \ uk_UA.KOI8-U pt_BR.ISO8859-1 ru_RU.KOI8-R hu_HU.ISO8859-2 -NLSLINKS_en_US.US-ASCII= en_US.ISO8859-1 en_US.ISO8859-15 +NLSLINKS_C= en_US.ISO8859-1 en_US.ISO8859-15 NLSLINKS_fr_FR.ISO8859-1= fr_BE.ISO8859-1 fr_BE.ISO8859-15 \ fr_CA.ISO8859-1 fr_CA.ISO8859-15 fr_CH.ISO8859-1 fr_CH.ISO8859-15 \ fr_FR.ISO8859-15 From 4b3d880203e552aa165fe735f87bbcfce838a1d2 Mon Sep 17 00:00:00 2001 From: Eitan Adler Date: Sat, 9 Feb 2013 17:13:51 +0000 Subject: [PATCH 0081/1476] Fix logic inversion. PR: docs/174966 Submitted by: Christian Ullrich Approved by: bcr (mentor) --- lib/libc/sys/chflags.2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/libc/sys/chflags.2 b/lib/libc/sys/chflags.2 index 1c2eb7865de..59979a3058d 100644 --- a/lib/libc/sys/chflags.2 +++ b/lib/libc/sys/chflags.2 @@ -98,7 +98,7 @@ If one of or .Dv SF_NOUNLINK is set a non-super-user cannot change any flags and even the super-user -can change flags only if securelevel is greater than 0. +can change flags only if securelevel is 0. (See .Xr init 8 for details.) From 8b3cc7155e60afc67f7bb576a63ded7b4318d762 Mon Sep 17 00:00:00 2001 From: Eitan Adler Date: Sat, 9 Feb 2013 17:13:54 +0000 Subject: [PATCH 0082/1476] Reference something which exists instead of the non-existent runsocks program. PR: docs/173664 Submitted by: wkoszek Approved by: bcr (mentor) --- usr.bin/csup/csup.1 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/usr.bin/csup/csup.1 b/usr.bin/csup/csup.1 index 5e5d5dd1206..48acbd11afc 100644 --- a/usr.bin/csup/csup.1 +++ b/usr.bin/csup/csup.1 @@ -24,7 +24,7 @@ .\" $Id: cvsup.1,v 1.70 2003/03/04 18:23:46 jdp Exp $ .\" $FreeBSD$ .\" -.Dd February 1, 2006 +.Dd Feburary 8, 2013 .Dt CSUP 1 .Os FreeBSD .Sh NAME @@ -902,14 +902,14 @@ will work through any firewall which permits outbound connections to port 5999 of the server host. .Sh USING csup WITH SOCKS .Nm -can be used through a SOCKS proxy server with the standard -.Nm runsocks +can be used through a SOCKS proxy server with the +.Nm tsocks command. -Your +The .Nm executable needs to be dynamically-linked with the system libraries for -.Nm runsocks +.Nm tsocks to work properly. .Sh USING ssh PORT FORWARDING As an alternative to SOCKS, a user behind a firewall can penetrate it From a1cb341b5d8d84403ce327a15ac4cef64178a472 Mon Sep 17 00:00:00 2001 From: Michael Tuexen Date: Sat, 9 Feb 2013 17:26:14 +0000 Subject: [PATCH 0083/1476] Cleanup the handling of address scopes. Announce in the INIT/INIT-ACK only the supported address types. While there, do some whitespace cleanups. MFC after: 1 week --- sys/netinet/sctp.h | 2 +- sys/netinet/sctp_asconf.c | 30 +++---- sys/netinet/sctp_input.c | 12 +-- sys/netinet/sctp_output.c | 178 +++++++++++-------------------------- sys/netinet/sctp_output.h | 8 +- sys/netinet/sctp_pcb.c | 89 ++++++++++--------- sys/netinet/sctp_structs.h | 12 +-- sys/netinet/sctp_sysctl.c | 30 +++---- sys/netinet/sctp_usrreq.c | 62 ++++++++----- sys/netinet/sctputil.c | 125 ++++++++++++-------------- 10 files changed, 228 insertions(+), 320 deletions(-) diff --git a/sys/netinet/sctp.h b/sys/netinet/sctp.h index 669b02a9f78..493e085d334 100644 --- a/sys/netinet/sctp.h +++ b/sys/netinet/sctp.h @@ -500,12 +500,12 @@ struct sctp_error_unrecognized_chunk { #define SCTP_PCB_FLAGS_SOCKET_GONE 0x10000000 #define SCTP_PCB_FLAGS_SOCKET_ALLGONE 0x20000000 #define SCTP_PCB_FLAGS_SOCKET_CANT_READ 0x40000000 + /* flags to copy to new PCB */ #define SCTP_PCB_COPY_FLAGS (SCTP_PCB_FLAGS_BOUNDALL|\ SCTP_PCB_FLAGS_WAKEINPUT|\ SCTP_PCB_FLAGS_BOUND_V6) - /* * PCB Features (in sctp_features bitmask) */ diff --git a/sys/netinet/sctp_asconf.c b/sys/netinet/sctp_asconf.c index 0b15cd49ab8..32226d53a72 100644 --- a/sys/netinet/sctp_asconf.c +++ b/sys/netinet/sctp_asconf.c @@ -1916,7 +1916,7 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, return; } if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { - if (stcb->asoc.local_scope == 0) { + if (stcb->asoc.scope.local_scope == 0) { return; } /* is it the right link local scope? */ @@ -1924,7 +1924,7 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, return; } } - if (stcb->asoc.site_scope == 0 && + if (stcb->asoc.scope.site_scope == 0 && IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) { return; } @@ -1948,7 +1948,7 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, /* we skip unspecifed addresses */ return; } - if (stcb->asoc.ipv4_local_scope == 0 && + if (stcb->asoc.scope.ipv4_local_scope == 0 && IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) { return; } @@ -2106,7 +2106,7 @@ sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb, continue; } if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { - if (stcb->asoc.local_scope == 0) { + if (stcb->asoc.scope.local_scope == 0) { continue; } /* is it the right link local scope? */ @@ -2135,7 +2135,7 @@ sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb, /* we skip unspecifed addresses */ continue; } - if (stcb->asoc.ipv4_local_scope == 0 && + if (stcb->asoc.scope.ipv4_local_scope == 0 && IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) { continue; } @@ -2198,13 +2198,7 @@ sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb, } } else { /* Need to check scopes for this guy */ - if (sctp_is_address_in_scope(ifa, - stcb->asoc.ipv4_addr_legal, - stcb->asoc.ipv6_addr_legal, - stcb->asoc.loopback_scope, - stcb->asoc.ipv4_local_scope, - stcb->asoc.local_scope, - stcb->asoc.site_scope, 0) == 0) { + if (sctp_is_address_in_scope(ifa, &stcb->asoc.scope, 0) == 0) { continue; } } @@ -2437,7 +2431,7 @@ sctp_find_valid_localaddr(struct sctp_tcb *stcb, int addr_locked) return (NULL); } LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) { - if (stcb->asoc.loopback_scope == 0 && + if (stcb->asoc.scope.loopback_scope == 0 && SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) { /* Skip if loopback_scope not set */ continue; @@ -2446,7 +2440,7 @@ sctp_find_valid_localaddr(struct sctp_tcb *stcb, int addr_locked) switch (sctp_ifa->address.sa.sa_family) { #ifdef INET case AF_INET: - if (stcb->asoc.ipv4_addr_legal) { + if (stcb->asoc.scope.ipv4_addr_legal) { struct sockaddr_in *sin; sin = (struct sockaddr_in *)&sctp_ifa->address.sa; @@ -2454,7 +2448,7 @@ sctp_find_valid_localaddr(struct sctp_tcb *stcb, int addr_locked) /* skip unspecifed addresses */ continue; } - if (stcb->asoc.ipv4_local_scope == 0 && + if (stcb->asoc.scope.ipv4_local_scope == 0 && IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) continue; @@ -2473,7 +2467,7 @@ sctp_find_valid_localaddr(struct sctp_tcb *stcb, int addr_locked) #endif #ifdef INET6 case AF_INET6: - if (stcb->asoc.ipv6_addr_legal) { + if (stcb->asoc.scope.ipv6_addr_legal) { struct sockaddr_in6 *sin6; if (sctp_ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) { @@ -2487,10 +2481,10 @@ sctp_find_valid_localaddr(struct sctp_tcb *stcb, int addr_locked) */ continue; } - if (stcb->asoc.local_scope == 0 && + if (stcb->asoc.scope.local_scope == 0 && IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) continue; - if (stcb->asoc.site_scope == 0 && + if (stcb->asoc.scope.site_scope == 0 && IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) continue; diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index 511c1e2a6cd..0528d3df229 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -2130,13 +2130,13 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, asoc = &stcb->asoc; /* get scope variables out of cookie */ - asoc->ipv4_local_scope = cookie->ipv4_scope; - asoc->site_scope = cookie->site_scope; - asoc->local_scope = cookie->local_scope; - asoc->loopback_scope = cookie->loopback_scope; + asoc->scope.ipv4_local_scope = cookie->ipv4_scope; + asoc->scope.site_scope = cookie->site_scope; + asoc->scope.local_scope = cookie->local_scope; + asoc->scope.loopback_scope = cookie->loopback_scope; - if ((asoc->ipv4_addr_legal != cookie->ipv4_addr_legal) || - (asoc->ipv6_addr_legal != cookie->ipv6_addr_legal)) { + if ((asoc->scope.ipv4_addr_legal != cookie->ipv4_addr_legal) || + (asoc->scope.ipv6_addr_legal != cookie->ipv6_addr_legal)) { struct mbuf *op_err; /* diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index a5a3e5a1300..22215321981 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -1863,15 +1863,10 @@ struct sack_track sack_array[256] = { int sctp_is_address_in_scope(struct sctp_ifa *ifa, - int ipv4_addr_legal, - int ipv6_addr_legal, - int loopback_scope, - int ipv4_local_scope, - int local_scope SCTP_UNUSED,/* XXX */ - int site_scope, + struct sctp_scoping *scope, int do_update) { - if ((loopback_scope == 0) && + if ((scope->loopback_scope == 0) && (ifa->ifn_p) && SCTP_IFN_IS_IFT_LOOP(ifa->ifn_p)) { /* * skip loopback if not in scope * @@ -1881,7 +1876,7 @@ sctp_is_address_in_scope(struct sctp_ifa *ifa, switch (ifa->address.sa.sa_family) { #ifdef INET case AF_INET: - if (ipv4_addr_legal) { + if (scope->ipv4_addr_legal) { struct sockaddr_in *sin; sin = (struct sockaddr_in *)&ifa->address.sin; @@ -1889,7 +1884,7 @@ sctp_is_address_in_scope(struct sctp_ifa *ifa, /* not in scope , unspecified */ return (0); } - if ((ipv4_local_scope == 0) && + if ((scope->ipv4_local_scope == 0) && (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) { /* private address not in scope */ return (0); @@ -1901,7 +1896,7 @@ sctp_is_address_in_scope(struct sctp_ifa *ifa, #endif #ifdef INET6 case AF_INET6: - if (ipv6_addr_legal) { + if (scope->ipv6_addr_legal) { struct sockaddr_in6 *sin6; /* @@ -1924,7 +1919,7 @@ sctp_is_address_in_scope(struct sctp_ifa *ifa, (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))) { return (0); } - if ((site_scope == 0) && + if ((scope->site_scope == 0) && (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) { return (0); } @@ -2063,13 +2058,7 @@ sctp_add_addresses_to_i_ia(struct sctp_inpcb *inp, struct sctp_tcb *stcb, if (sctp_is_addr_restricted(stcb, sctp_ifap)) { continue; } - if (sctp_is_address_in_scope(sctp_ifap, - scope->ipv4_addr_legal, - scope->ipv6_addr_legal, - scope->loopback_scope, - scope->ipv4_local_scope, - scope->local_scope, - scope->site_scope, 1) == 0) { + if (sctp_is_address_in_scope(sctp_ifap, scope, 1) == 0) { continue; } cnt++; @@ -2099,12 +2088,7 @@ skip_count: continue; } if (sctp_is_address_in_scope(sctp_ifap, - scope->ipv4_addr_legal, - scope->ipv6_addr_legal, - scope->loopback_scope, - scope->ipv4_local_scope, - scope->local_scope, - scope->site_scope, 0) == 0) { + scope, 0) == 0) { continue; } if ((chunk_len != NULL) && @@ -2157,12 +2141,7 @@ skip_count: continue; } if (sctp_is_address_in_scope(laddr->ifa, - scope->ipv4_addr_legal, - scope->ipv6_addr_legal, - scope->loopback_scope, - scope->ipv4_local_scope, - scope->local_scope, - scope->site_scope, 1) == 0) { + scope, 1) == 0) { continue; } cnt++; @@ -2182,12 +2161,7 @@ skip_count: continue; } if (sctp_is_address_in_scope(laddr->ifa, - scope->ipv4_addr_legal, - scope->ipv6_addr_legal, - scope->loopback_scope, - scope->ipv4_local_scope, - scope->local_scope, - scope->site_scope, 0) == 0) { + scope, 0) == 0) { continue; } if ((chunk_len != NULL) && @@ -2801,13 +2775,7 @@ sctp_select_nth_preferred_addr_from_ifn_boundall(struct sctp_ifn *ifn, } #endif if (stcb) { - if (sctp_is_address_in_scope(ifa, - stcb->asoc.ipv4_addr_legal, - stcb->asoc.ipv6_addr_legal, - stcb->asoc.loopback_scope, - stcb->asoc.ipv4_local_scope, - stcb->asoc.local_scope, - stcb->asoc.site_scope, 0) == 0) { + if (sctp_is_address_in_scope(ifa, &stcb->asoc.scope, 0) == 0) { continue; } if (((non_asoc_addr_ok == 0) && @@ -2853,13 +2821,7 @@ sctp_count_num_preferred_boundall(struct sctp_ifn *ifn, continue; } if (stcb) { - if (sctp_is_address_in_scope(ifa, - stcb->asoc.ipv4_addr_legal, - stcb->asoc.ipv6_addr_legal, - stcb->asoc.loopback_scope, - stcb->asoc.ipv4_local_scope, - stcb->asoc.local_scope, - stcb->asoc.site_scope, 0) == 0) { + if (sctp_is_address_in_scope(ifa, &stcb->asoc.scope, 0) == 0) { continue; } if (((non_asoc_addr_ok == 0) && @@ -3055,13 +3017,7 @@ again_with_private_addresses_allowed: continue; } if (stcb) { - if (sctp_is_address_in_scope(sifa, - stcb->asoc.ipv4_addr_legal, - stcb->asoc.ipv6_addr_legal, - stcb->asoc.loopback_scope, - stcb->asoc.ipv4_local_scope, - stcb->asoc.local_scope, - stcb->asoc.site_scope, 0) == 0) { + if (sctp_is_address_in_scope(sifa, &stcb->asoc.scope, 0) == 0) { SCTPDBG(SCTP_DEBUG_OUTPUT2, "NOT in scope\n"); sifa = NULL; continue; @@ -3108,13 +3064,7 @@ plan_d: if (sifa == NULL) continue; if (stcb) { - if (sctp_is_address_in_scope(sifa, - stcb->asoc.ipv4_addr_legal, - stcb->asoc.ipv6_addr_legal, - stcb->asoc.loopback_scope, - stcb->asoc.ipv4_local_scope, - stcb->asoc.local_scope, - stcb->asoc.site_scope, 0) == 0) { + if (sctp_is_address_in_scope(sifa, &stcb->asoc.scope, 0) == 0) { sifa = NULL; continue; } @@ -3135,12 +3085,12 @@ plan_d: } } #ifdef INET - if ((retried == 0) && (stcb->asoc.ipv4_local_scope == 0)) { - stcb->asoc.ipv4_local_scope = 1; + if ((retried == 0) && (stcb->asoc.scope.ipv4_local_scope == 0)) { + stcb->asoc.scope.ipv4_local_scope = 1; retried = 1; goto again_with_private_addresses_allowed; } else if (retried == 1) { - stcb->asoc.ipv4_local_scope = 0; + stcb->asoc.scope.ipv4_local_scope = 0; } #endif out: @@ -3169,12 +3119,7 @@ out: } if (stcb) { if (sctp_is_address_in_scope(tmp_sifa, - stcb->asoc.ipv4_addr_legal, - stcb->asoc.ipv6_addr_legal, - stcb->asoc.loopback_scope, - stcb->asoc.ipv4_local_scope, - stcb->asoc.local_scope, - stcb->asoc.site_scope, 0) == 0) { + &stcb->asoc.scope, 0) == 0) { continue; } if (((non_asoc_addr_ok == 0) && @@ -4595,7 +4540,6 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked #endif ) { - struct sctp_scoping scp; struct mbuf *m; struct sctp_nets *net; struct sctp_init_chunk *init; @@ -4675,37 +4619,29 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked init->init.num_inbound_streams = htons(stcb->asoc.max_inbound_streams); init->init.initial_tsn = htonl(stcb->asoc.init_seq_number); -#if defined(INET) || defined(INET6) - /* now the address restriction */ - /* XXX Should we take the address family of the socket into account? */ - sup_addr = (struct sctp_supported_addr_param *)(mtod(m, caddr_t)+chunk_len); - sup_addr->ph.param_type = htons(SCTP_SUPPORTED_ADDRTYPE); -#ifdef INET6 -#ifdef INET - /* we support 2 types: IPv4/IPv6 */ - parameter_len = (uint16_t) (sizeof(struct sctp_paramhdr) + 2 * sizeof(uint16_t)); - sup_addr->ph.param_length = htons(parameter_len); - sup_addr->addr_type[0] = htons(SCTP_IPV4_ADDRESS); - sup_addr->addr_type[1] = htons(SCTP_IPV6_ADDRESS); - padding_len = 0; -#else - /* we support 1 type: IPv6 */ - parameter_len = (uint16_t) (sizeof(struct sctp_paramhdr) + sizeof(uint16_t)); - sup_addr->ph.param_length = htons(parameter_len); - sup_addr->addr_type[0] = htons(SCTP_IPV6_ADDRESS); - sup_addr->addr_type[1] = htons(0); /* this is the padding */ - padding_len = (uint16_t) sizeof(uint16_t); -#endif -#else - /* we support 1 type: IPv4 */ - parameter_len = (uint16_t) (sizeof(struct sctp_paramhdr) + sizeof(uint16_t)); - sup_addr->ph.param_length = htons(parameter_len); - sup_addr->addr_type[0] = htons(SCTP_IPV4_ADDRESS); - sup_addr->addr_type[1] = htons(0); /* this is the padding */ - padding_len = (uint16_t) sizeof(uint16_t); -#endif - chunk_len += parameter_len; -#endif + if (stcb->asoc.scope.ipv4_addr_legal || stcb->asoc.scope.ipv6_addr_legal) { + uint8_t i; + + parameter_len = (uint16_t) sizeof(struct sctp_paramhdr); + if (stcb->asoc.scope.ipv4_addr_legal) { + parameter_len += (uint16_t) sizeof(uint16_t); + } + if (stcb->asoc.scope.ipv6_addr_legal) { + parameter_len += (uint16_t) sizeof(uint16_t); + } + sup_addr = (struct sctp_supported_addr_param *)(mtod(m, caddr_t)+chunk_len); + sup_addr->ph.param_type = htons(SCTP_SUPPORTED_ADDRTYPE); + sup_addr->ph.param_length = htons(parameter_len); + i = 0; + if (stcb->asoc.scope.ipv4_addr_legal) { + sup_addr->addr_type[i++] = htons(SCTP_IPV4_ADDRESS); + } + if (stcb->asoc.scope.ipv6_addr_legal) { + sup_addr->addr_type[i++] = htons(SCTP_IPV6_ADDRESS); + } + padding_len = 4 - 2 * i; + chunk_len += parameter_len; + } /* Adaptation layer indication parameter */ /* XXX: Should we include this always? */ if (padding_len > 0) { @@ -4860,13 +4796,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked * we could just sifa in the address within the stcb. But for now * this is a quick hack to get the address stuff teased apart. */ - scp.ipv4_addr_legal = stcb->asoc.ipv4_addr_legal; - scp.ipv6_addr_legal = stcb->asoc.ipv6_addr_legal; - scp.loopback_scope = stcb->asoc.loopback_scope; - scp.ipv4_local_scope = stcb->asoc.ipv4_local_scope; - scp.local_scope = stcb->asoc.local_scope; - scp.site_scope = stcb->asoc.site_scope; - sctp_add_addresses_to_i_ia(inp, stcb, &scp, m, cnt_inits_to, &padding_len, &chunk_len); + sctp_add_addresses_to_i_ia(inp, stcb, &stcb->asoc.scope, m, cnt_inits_to, &padding_len, &chunk_len); init->ch.chunk_length = htons(chunk_len); if (padding_len > 0) { @@ -5507,24 +5437,16 @@ do_a_abort: */ stc.site_scope = stc.local_scope = stc.loopback_scope = 0; if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { - struct inpcb *in_inp; - - /* Its a V6 socket */ - in_inp = (struct inpcb *)inp; stc.ipv6_addr_legal = 1; - /* Now look at the binding flag to see if V4 will be legal */ - if (SCTP_IPV6_V6ONLY(in_inp) == 0) { - stc.ipv4_addr_legal = 1; - } else { - /* V4 addresses are NOT legal on the association */ + if (SCTP_IPV6_V6ONLY(inp)) { stc.ipv4_addr_legal = 0; + } else { + stc.ipv4_addr_legal = 1; } } else { - /* Its a V4 socket, no - V6 */ - stc.ipv4_addr_legal = 1; stc.ipv6_addr_legal = 0; + stc.ipv4_addr_legal = 1; } - #ifdef SCTP_DONT_DO_PRIVADDR_SCOPE stc.ipv4_scope = 1; #else @@ -5629,10 +5551,10 @@ do_a_abort: #endif - stc.loopback_scope = asoc->loopback_scope; - stc.ipv4_scope = asoc->ipv4_local_scope; - stc.site_scope = asoc->site_scope; - stc.local_scope = asoc->local_scope; + stc.loopback_scope = asoc->scope.loopback_scope; + stc.ipv4_scope = asoc->scope.ipv4_local_scope; + stc.site_scope = asoc->scope.site_scope; + stc.local_scope = asoc->scope.local_scope; #ifdef INET6 /* Why do we not consider IPv4 LL addresses? */ TAILQ_FOREACH(lnet, &asoc->nets, sctp_next) { diff --git a/sys/netinet/sctp_output.h b/sys/netinet/sctp_output.h index b62271b146f..59af5af25a8 100644 --- a/sys/netinet/sctp_output.h +++ b/sys/netinet/sctp_output.h @@ -55,13 +55,9 @@ int sctp_is_addr_restricted(struct sctp_tcb *, struct sctp_ifa *); int sctp_is_address_in_scope(struct sctp_ifa *ifa, - int ipv4_addr_legal, - int ipv6_addr_legal, - int loopback_scope, - int ipv4_local_scope, - int local_scope, - int site_scope, + struct sctp_scoping *scope, int do_update); + int sctp_is_addr_in_ep(struct sctp_inpcb *inp, struct sctp_ifa *ifa); diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c index 9f817a34fce..4d01756673b 100644 --- a/sys/netinet/sctp_pcb.c +++ b/sys/netinet/sctp_pcb.c @@ -94,11 +94,10 @@ sctp_fill_pcbinfo(struct sctp_pcbinfo *spcb) spcb->readq_count = SCTP_BASE_INFO(ipi_count_readq); spcb->stream_oque = SCTP_BASE_INFO(ipi_count_strmoq); spcb->free_chunks = SCTP_BASE_INFO(ipi_free_chunks); - SCTP_INP_INFO_RUNLOCK(); } -/* +/*- * Addresses are added to VRF's (Virtual Router's). For BSD we * have only the default VRF 0. We maintain a hash list of * VRF's. Each VRF has its own list of sctp_ifn's. Each of @@ -214,7 +213,6 @@ sctp_find_ifn(void *ifn, uint32_t ifn_index) } - struct sctp_vrf * sctp_find_vrf(uint32_t vrf_id) { @@ -230,6 +228,7 @@ sctp_find_vrf(uint32_t vrf_id) return (NULL); } + void sctp_free_vrf(struct sctp_vrf *vrf) { @@ -245,6 +244,7 @@ sctp_free_vrf(struct sctp_vrf *vrf) } } + void sctp_free_ifn(struct sctp_ifn *sctp_ifnp) { @@ -258,6 +258,7 @@ sctp_free_ifn(struct sctp_ifn *sctp_ifnp) } } + void sctp_update_ifn_mtu(uint32_t ifn_index, uint32_t mtu) { @@ -283,6 +284,7 @@ sctp_free_ifa(struct sctp_ifa *sctp_ifap) } } + static void sctp_delete_ifn(struct sctp_ifn *sctp_ifnp, int hold_addr_lock) { @@ -305,12 +307,13 @@ sctp_delete_ifn(struct sctp_ifn *sctp_ifnp, int hold_addr_lock) sctp_free_ifn(sctp_ifnp); } + void sctp_mark_ifa_addr_down(uint32_t vrf_id, struct sockaddr *addr, const char *if_name, uint32_t ifn_index) { struct sctp_vrf *vrf; - struct sctp_ifa *sctp_ifap = NULL; + struct sctp_ifa *sctp_ifap; SCTP_IPI_ADDR_RLOCK(); vrf = sctp_find_vrf(vrf_id); @@ -348,12 +351,13 @@ out: SCTP_IPI_ADDR_RUNLOCK(); } + void sctp_mark_ifa_addr_up(uint32_t vrf_id, struct sockaddr *addr, const char *if_name, uint32_t ifn_index) { struct sctp_vrf *vrf; - struct sctp_ifa *sctp_ifap = NULL; + struct sctp_ifa *sctp_ifap; SCTP_IPI_ADDR_RLOCK(); vrf = sctp_find_vrf(vrf_id); @@ -391,6 +395,7 @@ out: SCTP_IPI_ADDR_RUNLOCK(); } + /*- * Add an ifa to an ifn. * Register the interface as necessary. @@ -428,6 +433,7 @@ sctp_add_ifa_to_ifn(struct sctp_ifn *sctp_ifnp, struct sctp_ifa *sctp_ifap) } } + /*- * Remove an ifa from its ifn. * If no more addresses exist, remove the ifn too. Otherwise, re-register @@ -479,6 +485,7 @@ sctp_remove_ifa_from_ifn(struct sctp_ifa *sctp_ifap) } } + struct sctp_ifa * sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index, uint32_t ifn_type, const char *if_name, void *ifa, @@ -1027,6 +1034,7 @@ sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from, return (NULL); } + static int sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to) { @@ -1036,19 +1044,12 @@ sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to) struct sctp_ifn *sctp_ifn; struct sctp_ifa *sctp_ifa; - loopback_scope = stcb->asoc.loopback_scope; - ipv4_local_scope = stcb->asoc.ipv4_local_scope; - local_scope = stcb->asoc.local_scope; - site_scope = stcb->asoc.site_scope; - ipv4_addr_legal = ipv6_addr_legal = 0; - if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { - ipv6_addr_legal = 1; - if (SCTP_IPV6_V6ONLY(stcb->sctp_ep) == 0) { - ipv4_addr_legal = 1; - } - } else { - ipv4_addr_legal = 1; - } + loopback_scope = stcb->asoc.scope.loopback_scope; + ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope; + local_scope = stcb->asoc.scope.local_scope; + site_scope = stcb->asoc.scope.site_scope; + ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal; + ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal; SCTP_IPI_ADDR_RLOCK(); vrf = sctp_find_vrf(stcb->asoc.vrf_id); @@ -1183,6 +1184,7 @@ sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to) return (0); } + /* * rules for use * @@ -1471,11 +1473,11 @@ null_return: return (NULL); } + /* * Find an association for a specific endpoint using the association id given * out in the COMM_UP notification */ - struct sctp_tcb * sctp_findasoc_ep_asocid_locked(struct sctp_inpcb *inp, sctp_assoc_t asoc_id, int want_lock) { @@ -1536,6 +1538,9 @@ sctp_findassociation_ep_asocid(struct sctp_inpcb *inp, sctp_assoc_t asoc_id, int } +/* + * Endpoint probe expects that the INP_INFO is locked. + */ static struct sctp_inpcb * sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head, uint16_t lport, uint32_t vrf_id) @@ -1552,12 +1557,8 @@ sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head, struct sockaddr_in6 *intf_addr6; #endif - int fnd; - /* - * Endpoint probe expects that the INP_INFO is locked. - */ #ifdef INET sin = NULL; #endif @@ -1893,6 +1894,7 @@ sctp_pcb_findep(struct sockaddr *nam, int find_tcp_pool, int have_lock, return (inp); } + /* * Find an association for an endpoint with the pointer to whom you want to * send to and the endpoint pointer. The address can be IPv4 or IPv6. We may @@ -2144,6 +2146,7 @@ sctp_findassoc_by_vtag(struct sockaddr *from, struct sockaddr *to, uint32_t vtag return (NULL); } + /* * Find an association with the pointer to the inbound IP packet. This can be * a IPv4 or IPv6 packet. @@ -3743,13 +3746,13 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr, stcb->ipv4_local_scope = 1; #else if (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) { - stcb->asoc.ipv4_local_scope = 1; + stcb->asoc.scope.ipv4_local_scope = 1; } #endif /* SCTP_DONT_DO_PRIVADDR_SCOPE */ } else { /* Validate the address is in scope */ if ((IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) && - (stcb->asoc.ipv4_local_scope == 0)) { + (stcb->asoc.scope.ipv4_local_scope == 0)) { addr_inscope = 0; } } @@ -3770,10 +3773,10 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr, sin6->sin6_len = sizeof(struct sockaddr_in6); if (set_scope) { if (sctp_is_address_on_local_host(newaddr, stcb->asoc.vrf_id)) { - stcb->asoc.loopback_scope = 1; - stcb->asoc.local_scope = 0; - stcb->asoc.ipv4_local_scope = 1; - stcb->asoc.site_scope = 1; + stcb->asoc.scope.loopback_scope = 1; + stcb->asoc.scope.local_scope = 0; + stcb->asoc.scope.ipv4_local_scope = 1; + stcb->asoc.scope.site_scope = 1; } else if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { /* * If the new destination is a @@ -3785,26 +3788,26 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr, * also be on our private network * for v4 too. */ - stcb->asoc.ipv4_local_scope = 1; - stcb->asoc.site_scope = 1; + stcb->asoc.scope.ipv4_local_scope = 1; + stcb->asoc.scope.site_scope = 1; } else if (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) { /* * If the new destination is * SITE_LOCAL then we must have site * scope in common. */ - stcb->asoc.site_scope = 1; + stcb->asoc.scope.site_scope = 1; } } else { /* Validate the address is in scope */ if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr) && - (stcb->asoc.loopback_scope == 0)) { + (stcb->asoc.scope.loopback_scope == 0)) { addr_inscope = 0; } else if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && - (stcb->asoc.local_scope == 0)) { + (stcb->asoc.scope.local_scope == 0)) { addr_inscope = 0; } else if (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) && - (stcb->asoc.site_scope == 0)) { + (stcb->asoc.scope.site_scope == 0)) { addr_inscope = 0; } } @@ -3839,10 +3842,10 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr, } net->addr_is_local = sctp_is_address_on_local_host(newaddr, stcb->asoc.vrf_id); if (net->addr_is_local && ((set_scope || (from == SCTP_ADDR_IS_CONFIRMED)))) { - stcb->asoc.loopback_scope = 1; - stcb->asoc.ipv4_local_scope = 1; - stcb->asoc.local_scope = 0; - stcb->asoc.site_scope = 1; + stcb->asoc.scope.loopback_scope = 1; + stcb->asoc.scope.ipv4_local_scope = 1; + stcb->asoc.scope.local_scope = 0; + stcb->asoc.scope.site_scope = 1; addr_inscope = 1; } net->failure_threshold = stcb->asoc.def_net_failure; @@ -6071,7 +6074,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, switch (sa->sa_family) { #ifdef INET case AF_INET: - if (stcb->asoc.ipv4_addr_legal) { + if (stcb->asoc.scope.ipv4_addr_legal) { if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_2)) { return (-1); } @@ -6080,7 +6083,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, #endif #ifdef INET6 case AF_INET6: - if (stcb->asoc.ipv6_addr_legal) { + if (stcb->asoc.scope.ipv6_addr_legal) { if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_3)) { return (-2); } @@ -6127,7 +6130,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, } #ifdef INET if (ptype == SCTP_IPV4_ADDRESS) { - if (stcb->asoc.ipv4_addr_legal) { + if (stcb->asoc.scope.ipv4_addr_legal) { struct sctp_ipv4addr_param *p4, p4_buf; /* ok get the v4 address and check/add */ @@ -6213,7 +6216,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, #endif #ifdef INET6 if (ptype == SCTP_IPV6_ADDRESS) { - if (stcb->asoc.ipv6_addr_legal) { + if (stcb->asoc.scope.ipv6_addr_legal) { /* ok get the v6 address and check/add */ struct sctp_ipv6addr_param *p6, p6_buf; diff --git a/sys/netinet/sctp_structs.h b/sys/netinet/sctp_structs.h index 05d5fd1e065..bc18f0e8315 100644 --- a/sys/netinet/sctp_structs.h +++ b/sys/netinet/sctp_structs.h @@ -1177,17 +1177,7 @@ struct sctp_association { */ uint8_t peer_supports_pktdrop; - /* Do we allow V6/V4? */ - uint8_t ipv4_addr_legal; - uint8_t ipv6_addr_legal; - /* Address scoping flags */ - /* scope value for IPv4 */ - uint8_t ipv4_local_scope; - /* scope values for IPv6 */ - uint8_t local_scope; - uint8_t site_scope; - /* loopback scope */ - uint8_t loopback_scope; + struct sctp_scoping scope; /* flags to handle send alternate net tracking */ uint8_t used_alt_onsack; uint8_t used_alt_asconfack; diff --git a/sys/netinet/sctp_sysctl.c b/sys/netinet/sctp_sysctl.c index 14372bb414c..debb8cc0bf0 100644 --- a/sys/netinet/sctp_sysctl.c +++ b/sys/netinet/sctp_sysctl.c @@ -197,29 +197,29 @@ copy_out_local_addresses(struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct s /* Turn on all the appropriate scope */ if (stcb) { /* use association specific values */ - loopback_scope = stcb->asoc.loopback_scope; - ipv4_local_scope = stcb->asoc.ipv4_local_scope; - local_scope = stcb->asoc.local_scope; - site_scope = stcb->asoc.site_scope; + loopback_scope = stcb->asoc.scope.loopback_scope; + ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope; + local_scope = stcb->asoc.scope.local_scope; + site_scope = stcb->asoc.scope.site_scope; + ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal; + ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal; } else { - /* use generic values for endpoints */ + /* Use generic values for endpoints. */ loopback_scope = 1; ipv4_local_scope = 1; local_scope = 1; site_scope = 1; - } - - /* use only address families of interest */ - if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { - ipv6_addr_legal = 1; - if (SCTP_IPV6_V6ONLY(inp)) { - ipv4_addr_legal = 0; + if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { + ipv6_addr_legal = 1; + if (SCTP_IPV6_V6ONLY(inp)) { + ipv4_addr_legal = 0; + } else { + ipv4_addr_legal = 1; + } } else { + ipv6_addr_legal = 0; ipv4_addr_legal = 1; } - } else { - ipv4_addr_legal = 1; - ipv6_addr_legal = 0; } /* neither Mac OS X nor FreeBSD support mulitple routing functions */ diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c index 383ff0b98fa..2b3bf7921bb 100644 --- a/sys/netinet/sctp_usrreq.c +++ b/sys/netinet/sctp_usrreq.c @@ -1143,23 +1143,29 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp, if (stcb) { /* Turn on all the appropriate scope */ - loopback_scope = stcb->asoc.loopback_scope; - ipv4_local_scope = stcb->asoc.ipv4_local_scope; - local_scope = stcb->asoc.local_scope; - site_scope = stcb->asoc.site_scope; + loopback_scope = stcb->asoc.scope.loopback_scope; + ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope; + local_scope = stcb->asoc.scope.local_scope; + site_scope = stcb->asoc.scope.site_scope; + ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal; + ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal; } else { - /* Turn on ALL scope, since we look at the EP */ - loopback_scope = ipv4_local_scope = local_scope = - site_scope = 1; - } - ipv4_addr_legal = ipv6_addr_legal = 0; - if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { - ipv6_addr_legal = 1; - if (SCTP_IPV6_V6ONLY(inp) == 0) { + /* Use generic values for endpoints. */ + loopback_scope = 1; + ipv4_local_scope = 1; + local_scope = 1; + site_scope = 1; + if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { + ipv6_addr_legal = 1; + if (SCTP_IPV6_V6ONLY(inp)) { + ipv4_addr_legal = 0; + } else { + ipv4_addr_legal = 1; + } + } else { + ipv6_addr_legal = 0; ipv4_addr_legal = 1; } - } else { - ipv4_addr_legal = 1; } vrf = sctp_find_vrf(vrf_id); if (vrf == NULL) { @@ -1298,8 +1304,21 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp, } if (sctp_fill_user_address(sas, &laddr->ifa->address.sa)) continue; - - ((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport; + switch (laddr->ifa->address.sa.sa_family) { +#ifdef INET + case AF_INET: + ((struct sockaddr_in *)sas)->sin_port = inp->sctp_lport; + break; +#endif +#ifdef INET6 + case AF_INET6: + ((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport; + break; +#endif + default: + /* TSNH */ + break; + } sas = (struct sockaddr_storage *)((caddr_t)sas + laddr->ifa->address.sa.sa_len); actual += laddr->ifa->address.sa.sa_len; @@ -5948,7 +5967,7 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p) error = EINVAL; goto out_now; } -#endif /* INET6 */ +#endif if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == SCTP_PCB_FLAGS_UNBOUND) { /* Bind a ephemeral port */ @@ -6242,8 +6261,8 @@ sctp_accept(struct socket *so, struct sockaddr **addr) return (ENOMEM); sin->sin_family = AF_INET; sin->sin_len = sizeof(*sin); - sin->sin_port = ((struct sockaddr_in *)&store)->sin_port; - sin->sin_addr = ((struct sockaddr_in *)&store)->sin_addr; + sin->sin_port = store.sin.sin_port; + sin->sin_addr = store.sin.sin_addr; *addr = (struct sockaddr *)sin; break; } @@ -6258,9 +6277,8 @@ sctp_accept(struct socket *so, struct sockaddr **addr) return (ENOMEM); sin6->sin6_family = AF_INET6; sin6->sin6_len = sizeof(*sin6); - sin6->sin6_port = ((struct sockaddr_in6 *)&store)->sin6_port; - - sin6->sin6_addr = ((struct sockaddr_in6 *)&store)->sin6_addr; + sin6->sin6_port = store.sin6.sin6_port; + sin6->sin6_addr = store.sin6.sin6_addr; if ((error = sa6_recoverscope(sin6)) != 0) { SCTP_FREE_SONAME(sin6); return (error); diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c index 1fadf6bedcd..fe2b9459a40 100644 --- a/sys/netinet/sctputil.c +++ b/sys/netinet/sctputil.c @@ -878,7 +878,7 @@ sctp_select_a_tag(struct sctp_inpcb *inp, uint16_t lport, uint16_t rport, int ch } int -sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb, +sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, uint32_t override_tag, uint32_t vrf_id) { struct sctp_association *asoc; @@ -899,23 +899,23 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb, asoc = &stcb->asoc; /* init all variables to a known value. */ SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_INUSE); - asoc->max_burst = m->sctp_ep.max_burst; - asoc->fr_max_burst = m->sctp_ep.fr_max_burst; - asoc->heart_beat_delay = TICKS_TO_MSEC(m->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]); - asoc->cookie_life = m->sctp_ep.def_cookie_life; - asoc->sctp_cmt_on_off = m->sctp_cmt_on_off; - asoc->ecn_allowed = m->sctp_ecn_enable; + asoc->max_burst = inp->sctp_ep.max_burst; + asoc->fr_max_burst = inp->sctp_ep.fr_max_burst; + asoc->heart_beat_delay = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]); + asoc->cookie_life = inp->sctp_ep.def_cookie_life; + asoc->sctp_cmt_on_off = inp->sctp_cmt_on_off; + asoc->ecn_allowed = inp->sctp_ecn_enable; asoc->sctp_nr_sack_on_off = (uint8_t) SCTP_BASE_SYSCTL(sctp_nr_sack_on_off); asoc->sctp_cmt_pf = (uint8_t) 0; - asoc->sctp_frag_point = m->sctp_frag_point; - asoc->sctp_features = m->sctp_features; - asoc->default_dscp = m->sctp_ep.default_dscp; + asoc->sctp_frag_point = inp->sctp_frag_point; + asoc->sctp_features = inp->sctp_features; + asoc->default_dscp = inp->sctp_ep.default_dscp; #ifdef INET6 - if (m->sctp_ep.default_flowlabel) { - asoc->default_flowlabel = m->sctp_ep.default_flowlabel; + if (inp->sctp_ep.default_flowlabel) { + asoc->default_flowlabel = inp->sctp_ep.default_flowlabel; } else { - if (m->ip_inp.inp.inp_flags & IN6P_AUTOFLOWLABEL) { - asoc->default_flowlabel = sctp_select_initial_TSN(&m->sctp_ep); + if (inp->ip_inp.inp.inp_flags & IN6P_AUTOFLOWLABEL) { + asoc->default_flowlabel = sctp_select_initial_TSN(&inp->sctp_ep); asoc->default_flowlabel &= 0x000fffff; asoc->default_flowlabel |= 0x80000000; } else { @@ -927,11 +927,11 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb, if (override_tag) { asoc->my_vtag = override_tag; } else { - asoc->my_vtag = sctp_select_a_tag(m, stcb->sctp_ep->sctp_lport, stcb->rport, 1); + asoc->my_vtag = sctp_select_a_tag(inp, stcb->sctp_ep->sctp_lport, stcb->rport, 1); } /* Get the nonce tags */ - asoc->my_vtag_nonce = sctp_select_a_tag(m, stcb->sctp_ep->sctp_lport, stcb->rport, 0); - asoc->peer_vtag_nonce = sctp_select_a_tag(m, stcb->sctp_ep->sctp_lport, stcb->rport, 0); + asoc->my_vtag_nonce = sctp_select_a_tag(inp, stcb->sctp_ep->sctp_lport, stcb->rport, 0); + asoc->peer_vtag_nonce = sctp_select_a_tag(inp, stcb->sctp_ep->sctp_lport, stcb->rport, 0); asoc->vrf_id = vrf_id; #ifdef SCTP_ASOCLOG_OF_TSNS @@ -948,7 +948,7 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb, asoc->refcnt = 0; asoc->assoc_up_sent = 0; asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number = asoc->sending_seq = - sctp_select_initial_TSN(&m->sctp_ep); + sctp_select_initial_TSN(&inp->sctp_ep); asoc->asconf_seq_out_acked = asoc->asconf_seq_out - 1; /* we are optimisitic here */ asoc->peer_supports_pktdrop = 1; @@ -966,49 +966,42 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb, /* here we are different, we hold the next one we expect */ asoc->str_reset_seq_in = asoc->last_acked_seq + 1; - asoc->initial_init_rto_max = m->sctp_ep.initial_init_rto_max; - asoc->initial_rto = m->sctp_ep.initial_rto; + asoc->initial_init_rto_max = inp->sctp_ep.initial_init_rto_max; + asoc->initial_rto = inp->sctp_ep.initial_rto; - asoc->max_init_times = m->sctp_ep.max_init_times; - asoc->max_send_times = m->sctp_ep.max_send_times; - asoc->def_net_failure = m->sctp_ep.def_net_failure; - asoc->def_net_pf_threshold = m->sctp_ep.def_net_pf_threshold; + asoc->max_init_times = inp->sctp_ep.max_init_times; + asoc->max_send_times = inp->sctp_ep.max_send_times; + asoc->def_net_failure = inp->sctp_ep.def_net_failure; + asoc->def_net_pf_threshold = inp->sctp_ep.def_net_pf_threshold; asoc->free_chunk_cnt = 0; asoc->iam_blocking = 0; - asoc->context = m->sctp_context; - asoc->local_strreset_support = m->local_strreset_support; - asoc->def_send = m->def_send; - asoc->delayed_ack = TICKS_TO_MSEC(m->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]); - asoc->sack_freq = m->sctp_ep.sctp_sack_freq; + asoc->context = inp->sctp_context; + asoc->local_strreset_support = inp->local_strreset_support; + asoc->def_send = inp->def_send; + asoc->delayed_ack = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]); + asoc->sack_freq = inp->sctp_ep.sctp_sack_freq; asoc->pr_sctp_cnt = 0; asoc->total_output_queue_size = 0; - if (m->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { - struct in6pcb *inp6; - - /* Its a V6 socket */ - inp6 = (struct in6pcb *)m; - asoc->ipv6_addr_legal = 1; - /* Now look at the binding flag to see if V4 will be legal */ - if (SCTP_IPV6_V6ONLY(inp6) == 0) { - asoc->ipv4_addr_legal = 1; + if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { + asoc->scope.ipv6_addr_legal = 1; + if (SCTP_IPV6_V6ONLY(inp) == 0) { + asoc->scope.ipv4_addr_legal = 1; } else { - /* V4 addresses are NOT legal on the association */ - asoc->ipv4_addr_legal = 0; + asoc->scope.ipv4_addr_legal = 0; } } else { - /* Its a V4 socket, no - V6 */ - asoc->ipv4_addr_legal = 1; - asoc->ipv6_addr_legal = 0; + asoc->scope.ipv6_addr_legal = 0; + asoc->scope.ipv4_addr_legal = 1; } - asoc->my_rwnd = max(SCTP_SB_LIMIT_RCV(m->sctp_socket), SCTP_MINIMAL_RWND); - asoc->peers_rwnd = SCTP_SB_LIMIT_RCV(m->sctp_socket); + asoc->my_rwnd = max(SCTP_SB_LIMIT_RCV(inp->sctp_socket), SCTP_MINIMAL_RWND); + asoc->peers_rwnd = SCTP_SB_LIMIT_RCV(inp->sctp_socket); - asoc->smallest_mtu = m->sctp_frag_point; - asoc->minrto = m->sctp_ep.sctp_minrto; - asoc->maxrto = m->sctp_ep.sctp_maxrto; + asoc->smallest_mtu = inp->sctp_frag_point; + asoc->minrto = inp->sctp_ep.sctp_minrto; + asoc->maxrto = inp->sctp_ep.sctp_maxrto; asoc->locked_on_sending = NULL; asoc->stream_locked_on = 0; @@ -1025,20 +1018,20 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb, /* Setup to fill the hb random cache at first HB */ asoc->hb_random_idx = 4; - asoc->sctp_autoclose_ticks = m->sctp_ep.auto_close_time; + asoc->sctp_autoclose_ticks = inp->sctp_ep.auto_close_time; - stcb->asoc.congestion_control_module = m->sctp_ep.sctp_default_cc_module; - stcb->asoc.cc_functions = sctp_cc_functions[m->sctp_ep.sctp_default_cc_module]; + stcb->asoc.congestion_control_module = inp->sctp_ep.sctp_default_cc_module; + stcb->asoc.cc_functions = sctp_cc_functions[inp->sctp_ep.sctp_default_cc_module]; - stcb->asoc.stream_scheduling_module = m->sctp_ep.sctp_default_ss_module; - stcb->asoc.ss_functions = sctp_ss_functions[m->sctp_ep.sctp_default_ss_module]; + stcb->asoc.stream_scheduling_module = inp->sctp_ep.sctp_default_ss_module; + stcb->asoc.ss_functions = sctp_ss_functions[inp->sctp_ep.sctp_default_ss_module]; /* * Now the stream parameters, here we allocate space for all streams * that we request by default. */ asoc->strm_realoutsize = asoc->streamoutcnt = asoc->pre_open_streams = - m->sctp_ep.pre_open_stream_count; + inp->sctp_ep.pre_open_stream_count; SCTP_MALLOC(asoc->strmout, struct sctp_stream_out *, asoc->streamoutcnt * sizeof(struct sctp_stream_out), SCTP_M_STRMO); @@ -1093,7 +1086,7 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb, TAILQ_INIT(&asoc->sent_queue); TAILQ_INIT(&asoc->reasmqueue); TAILQ_INIT(&asoc->resetHead); - asoc->max_inbound_streams = m->sctp_ep.max_open_streams_intome; + asoc->max_inbound_streams = inp->sctp_ep.max_open_streams_intome; TAILQ_INIT(&asoc->asconf_queue); /* authentication fields */ asoc->authinfo.random = NULL; @@ -1104,7 +1097,7 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb, asoc->authinfo.recv_keyid = 0; LIST_INIT(&asoc->shared_keys); asoc->marked_retrans = 0; - asoc->port = m->sctp_ep.port; + asoc->port = inp->sctp_ep.port; asoc->timoinit = 0; asoc->timodata = 0; asoc->timosack = 0; @@ -6621,20 +6614,12 @@ sctp_local_addr_count(struct sctp_tcb *stcb) int count = 0; /* Turn on all the appropriate scopes */ - loopback_scope = stcb->asoc.loopback_scope; - ipv4_local_scope = stcb->asoc.ipv4_local_scope; - local_scope = stcb->asoc.local_scope; - site_scope = stcb->asoc.site_scope; - ipv4_addr_legal = ipv6_addr_legal = 0; - if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { - ipv6_addr_legal = 1; - if (SCTP_IPV6_V6ONLY(stcb->sctp_ep) == 0) { - ipv4_addr_legal = 1; - } - } else { - ipv4_addr_legal = 1; - } - + loopback_scope = stcb->asoc.scope.loopback_scope; + ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope; + local_scope = stcb->asoc.scope.local_scope; + site_scope = stcb->asoc.scope.site_scope; + ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal; + ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal; SCTP_IPI_ADDR_RLOCK(); vrf = sctp_find_vrf(stcb->asoc.vrf_id); if (vrf == NULL) { From fe47e2e39b75054ac771f63754a873fdf636950a Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Sat, 9 Feb 2013 18:14:26 +0000 Subject: [PATCH 0084/1476] Add dtc to the build. --- usr.bin/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/usr.bin/Makefile b/usr.bin/Makefile index 2923f74d6c4..b3a23f76eda 100644 --- a/usr.bin/Makefile +++ b/usr.bin/Makefile @@ -37,6 +37,7 @@ SUBDIR= alias \ ctlstat \ cut \ dirname \ + dtc \ du \ ee \ elf2aout \ From 3d98a28bea86dc048a224459db607dfc6f5ab1df Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Sat, 9 Feb 2013 21:36:14 +0000 Subject: [PATCH 0085/1476] Fix breakage introduced in r246318. --- sys/arm/arm/vm_machdep.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/arm/arm/vm_machdep.c b/sys/arm/arm/vm_machdep.c index 9326546374c..97b8b76cf79 100644 --- a/sys/arm/arm/vm_machdep.c +++ b/sys/arm/arm/vm_machdep.c @@ -402,7 +402,8 @@ cpu_thread_alloc(struct thread *td) * the ARM EABI. */ td->td_frame = (struct trapframe *)STACKALIGN((u_int)td->td_kstack + - USPACE_SVC_STACK_TOP - sizeof(struct pcb) - 1); + USPACE_SVC_STACK_TOP - sizeof(struct pcb) - + sizeof(struct trapframe)); #ifdef __XSCALE__ #ifndef CPU_XSCALE_CORE3 pmap_use_minicache(td->td_kstack, td->td_kstack_pages * PAGE_SIZE); From 3e3812572d37fd122734d2df00ad013bc6db2ab7 Mon Sep 17 00:00:00 2001 From: Brooks Davis Date: Sat, 9 Feb 2013 23:17:28 +0000 Subject: [PATCH 0086/1476] Add nmtree to ITOOLS if it is installed on the host instead of keying off the BOOTSTRAPPING variable. The previous test was wrong because BOOTSTRAPPING is 0 in most cases. Tested by: db --- Makefile.inc1 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Makefile.inc1 b/Makefile.inc1 index 771f852c94d..bcb948734ad 100644 --- a/Makefile.inc1 +++ b/Makefile.inc1 @@ -673,6 +673,10 @@ _install-info= install-info _zoneinfo= zic tzsetup .endif +.if exists(/usr/sbin/nmtree) +_nmtree_itools= nmtree +.endif + ITOOLS= [ awk cap_mkdb cat chflags chmod chown \ date echo egrep find grep id install ${_install-info} \ ln lockf make mkdir mtree ${_nmtree_itools} mv pwd_mkdb \ @@ -1134,8 +1138,6 @@ _yacc= usr.bin/yacc .if ${BOOTSTRAPPING} < 1000026 _nmtree= lib/libnetbsd \ usr.sbin/nmtree -.else -_nmtree_itools= nmtree .endif .if ${BOOTSTRAPPING} < 1000027 From 5e60cb948e3aa0710303d5f61b5928329d518387 Mon Sep 17 00:00:00 2001 From: Attilio Rao Date: Sun, 10 Feb 2013 01:04:10 +0000 Subject: [PATCH 0087/1476] Remove a racy checks on resident and cached pages for tmpfs_mapped{read, write}() functions: - tmpfs_mapped{read, write}() are only called within VOP_{READ, WRITE}(), which check before-hand to work only on valid VREG vnodes. Also the vnode is locked for the duration of the work, making vnode reclaiming impossible, during the operation. Hence, vobj can never be NULL. - Currently check on resident pages and cached pages without vm object lock held is racy and can do even more harm than good, as a page could be transitioning between these 2 pools and then be skipped entirely. Skip the checks as lookups on empty splay trees are very cheap. Discussed with: alc Tested by: flo MFC after: 2 weeks --- sys/fs/tmpfs/tmpfs_vnops.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/sys/fs/tmpfs/tmpfs_vnops.c b/sys/fs/tmpfs/tmpfs_vnops.c index 5e2ea658741..bddcf2420ae 100644 --- a/sys/fs/tmpfs/tmpfs_vnops.c +++ b/sys/fs/tmpfs/tmpfs_vnops.c @@ -511,10 +511,6 @@ tmpfs_mappedread(vm_object_t vobj, vm_object_t tobj, size_t len, struct uio *uio offset = addr & PAGE_MASK; tlen = MIN(PAGE_SIZE - offset, len); - if ((vobj == NULL) || - (vobj->resident_page_count == 0 && vobj->cache == NULL)) - goto nocache; - VM_OBJECT_LOCK(vobj); lookupvpg: if (((m = vm_page_lookup(vobj, idx)) != NULL) && @@ -569,7 +565,6 @@ lookupvpg: return (error); } VM_OBJECT_UNLOCK(vobj); -nocache: error = tmpfs_nocacheread(tobj, idx, offset, tlen, uio); return (error); @@ -639,12 +634,6 @@ tmpfs_mappedwrite(vm_object_t vobj, vm_object_t tobj, size_t len, struct uio *ui offset = addr & PAGE_MASK; tlen = MIN(PAGE_SIZE - offset, len); - if ((vobj == NULL) || - (vobj->resident_page_count == 0 && vobj->cache == NULL)) { - vpg = NULL; - goto nocache; - } - VM_OBJECT_LOCK(vobj); lookupvpg: if (((vpg = vm_page_lookup(vobj, idx)) != NULL) && @@ -668,7 +657,6 @@ lookupvpg: VM_OBJECT_UNLOCK(vobj); vpg = NULL; } -nocache: VM_OBJECT_LOCK(tobj); tpg = vm_page_grab(tobj, idx, VM_ALLOC_WIRED | VM_ALLOC_NORMAL | VM_ALLOC_RETRY); From 9604a7f1b82fae840183432b7cefdb75913f0b23 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sun, 10 Feb 2013 10:17:33 +0000 Subject: [PATCH 0088/1476] Fix several unsafe pointer dereferences in the buffered_write() function, implementing the sysctl vfs.ffs.set_bufoutput (not used in the tree yet). - The current directory vnode dereference is unsafe since fd_cdir could be changed and unreferenced, lock the filedesc around and vref the fd_cdir. - The VTOI() conversion of the fd_cdir is unsafe without first checking that the vnode is indeed from an FFS mount, otherwise the code dereferences a random memory. - The cdir could be reclaimed from under us, lock it around the checks. - The type of the fp vnode might be not a disk, or it might have changed while the thread was in flight, check the type. Reviewed and tested by: mckusick MFC after: 2 weeks --- sys/ufs/ffs/ffs_alloc.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c index 5ad5775163f..d462cbb1b26 100644 --- a/sys/ufs/ffs/ffs_alloc.c +++ b/sys/ufs/ffs/ffs_alloc.c @@ -2906,10 +2906,11 @@ buffered_write(fp, uio, active_cred, flags, td) int flags; struct thread *td; { - struct vnode *devvp; + struct vnode *devvp, *vp; struct inode *ip; struct buf *bp; struct fs *fs; + struct filedesc *fdp; int error; daddr_t lbn; @@ -2920,10 +2921,29 @@ buffered_write(fp, uio, active_cred, flags, td) * within the filesystem being written. Yes, this is an ugly hack. */ devvp = fp->f_vnode; - ip = VTOI(td->td_proc->p_fd->fd_cdir); - if (ip->i_devvp != devvp) + if (!vn_isdisk(devvp, NULL)) return (EINVAL); + fdp = td->td_proc->p_fd; + FILEDESC_SLOCK(fdp); + vp = fdp->fd_cdir; + vref(vp); + FILEDESC_SUNLOCK(fdp); + vn_lock(vp, LK_SHARED | LK_RETRY); + /* + * Check that the current directory vnode indeed belongs to + * UFS before trying to dereference UFS-specific v_data fields. + */ + if (vp->v_op != &ffs_vnodeops1 && vp->v_op != &ffs_vnodeops2) { + vput(vp); + return (EINVAL); + } + ip = VTOI(vp); + if (ip->i_devvp != devvp) { + vput(vp); + return (EINVAL); + } fs = ip->i_fs; + vput(vp); foffset_lock_uio(fp, uio, flags); vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); #ifdef DEBUG From 645e4d17f0f07fba7dc76d63ccf2cff7095ceaf2 Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Sun, 10 Feb 2013 10:36:16 +0000 Subject: [PATCH 0089/1476] - Streamline detach logic in wlan drivers, so that freed memory cannot be used during detach. - Remove all panic() calls from the urtw driver because panic() is not appropriate here. - Remove redundant checks for device detached in device detach callbacks. - Use DEVMETHOD_END to mark end of device methods. MFC after: 2 weeks --- sys/dev/usb/wlan/if_rum.c | 18 ++++- sys/dev/usb/wlan/if_rumvar.h | 1 + sys/dev/usb/wlan/if_run.c | 16 +++- sys/dev/usb/wlan/if_runvar.h | 1 + sys/dev/usb/wlan/if_uath.c | 58 ++++++++++----- sys/dev/usb/wlan/if_upgt.c | 43 +++++++++-- sys/dev/usb/wlan/if_upgtvar.h | 1 + sys/dev/usb/wlan/if_ural.c | 17 ++++- sys/dev/usb/wlan/if_uralvar.h | 1 + sys/dev/usb/wlan/if_urtw.c | 133 +++++++++++++++++++++++----------- sys/dev/usb/wlan/if_urtwvar.h | 1 + sys/dev/usb/wlan/if_zyd.c | 33 +++++++-- sys/dev/usb/wlan/if_zydreg.h | 1 + 13 files changed, 237 insertions(+), 87 deletions(-) diff --git a/sys/dev/usb/wlan/if_rum.c b/sys/dev/usb/wlan/if_rum.c index 4c54aebf5f1..e159b24359c 100644 --- a/sys/dev/usb/wlan/if_rum.c +++ b/sys/dev/usb/wlan/if_rum.c @@ -542,6 +542,11 @@ rum_detach(device_t self) struct ifnet *ifp = sc->sc_ifp; struct ieee80211com *ic; + /* Prevent further ioctls */ + RUM_LOCK(sc); + sc->sc_detached = 1; + RUM_UNLOCK(sc); + /* stop all USB transfers */ usbd_transfer_unsetup(sc->sc_xfer, RUM_N_TRANSFER); @@ -556,7 +561,6 @@ rum_detach(device_t self) if_free(ifp); } mtx_destroy(&sc->sc_mtx); - return (0); } @@ -1321,7 +1325,14 @@ rum_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) struct rum_softc *sc = ifp->if_softc; struct ieee80211com *ic = ifp->if_l2com; struct ifreq *ifr = (struct ifreq *) data; - int error = 0, startall = 0; + int error; + int startall = 0; + + RUM_LOCK(sc); + error = sc->sc_detached ? ENXIO : 0; + RUM_UNLOCK(sc); + if (error) + return (error); switch (cmd) { case SIOCSIFFLAGS: @@ -2365,8 +2376,7 @@ static device_method_t rum_methods[] = { DEVMETHOD(device_probe, rum_match), DEVMETHOD(device_attach, rum_attach), DEVMETHOD(device_detach, rum_detach), - - { 0, 0 } + DEVMETHOD_END }; static driver_t rum_driver = { diff --git a/sys/dev/usb/wlan/if_rumvar.h b/sys/dev/usb/wlan/if_rumvar.h index f46634c268d..bc74e57f7bb 100644 --- a/sys/dev/usb/wlan/if_rumvar.h +++ b/sys/dev/usb/wlan/if_rumvar.h @@ -106,6 +106,7 @@ struct rum_softc { uint32_t rf_regs[4]; uint8_t txpow[44]; uint8_t sc_bssid[6]; + uint8_t sc_detached; struct { uint8_t val; diff --git a/sys/dev/usb/wlan/if_run.c b/sys/dev/usb/wlan/if_run.c index 39406363988..dd29b4031b4 100644 --- a/sys/dev/usb/wlan/if_run.c +++ b/sys/dev/usb/wlan/if_run.c @@ -716,11 +716,14 @@ run_detach(device_t self) struct ieee80211com *ic; int i; + RUN_LOCK(sc); + sc->sc_detached = 1; + RUN_UNLOCK(sc); + /* stop all USB transfers */ usbd_transfer_unsetup(sc->sc_xfer, RUN_N_XFER); RUN_LOCK(sc); - sc->ratectl_run = RUN_RATECTL_OFF; sc->cmdq_run = sc->cmdq_key_set = RUN_CMDQ_ABORT; @@ -3441,7 +3444,13 @@ run_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) struct ieee80211com *ic = sc->sc_ifp->if_l2com; struct ifreq *ifr = (struct ifreq *) data; int startall = 0; - int error = 0; + int error; + + RUN_LOCK(sc); + error = sc->sc_detached ? ENXIO : 0; + RUN_UNLOCK(sc); + if (error) + return (error); switch (cmd) { case SIOCSIFFLAGS: @@ -4963,8 +4972,7 @@ static device_method_t run_methods[] = { DEVMETHOD(device_probe, run_match), DEVMETHOD(device_attach, run_attach), DEVMETHOD(device_detach, run_detach), - - { 0, 0 } + DEVMETHOD_END }; static driver_t run_driver = { diff --git a/sys/dev/usb/wlan/if_runvar.h b/sys/dev/usb/wlan/if_runvar.h index 8ee36794379..24f308eae55 100644 --- a/sys/dev/usb/wlan/if_runvar.h +++ b/sys/dev/usb/wlan/if_runvar.h @@ -239,6 +239,7 @@ struct run_softc { uint8_t sta_running; uint8_t rvp_cnt; uint8_t rvp_bmap; + uint8_t sc_detached; union { struct run_rx_radiotap_header th; diff --git a/sys/dev/usb/wlan/if_uath.c b/sys/dev/usb/wlan/if_uath.c index 938e52ebb76..f238d0df4fd 100644 --- a/sys/dev/usb/wlan/if_uath.c +++ b/sys/dev/usb/wlan/if_uath.c @@ -504,29 +504,48 @@ uath_detach(device_t dev) struct uath_softc *sc = device_get_softc(dev); struct ifnet *ifp = sc->sc_ifp; struct ieee80211com *ic = ifp->if_l2com; + unsigned int x; - if (!device_is_attached(dev)) - return (0); - + /* + * Prevent further allocations from RX/TX/CMD + * data lists and ioctls + */ UATH_LOCK(sc); sc->sc_flags |= UATH_FLAG_INVALID; + + STAILQ_INIT(&sc->sc_rx_active); + STAILQ_INIT(&sc->sc_rx_inactive); + + STAILQ_INIT(&sc->sc_tx_active); + STAILQ_INIT(&sc->sc_tx_inactive); + STAILQ_INIT(&sc->sc_tx_pending); + + STAILQ_INIT(&sc->sc_cmd_active); + STAILQ_INIT(&sc->sc_cmd_pending); + STAILQ_INIT(&sc->sc_cmd_waiting); + STAILQ_INIT(&sc->sc_cmd_inactive); UATH_UNLOCK(sc); - ieee80211_ifdetach(ic); uath_stop(ifp); callout_drain(&sc->stat_ch); callout_drain(&sc->watchdog_ch); - usbd_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS); + /* drain USB transfers */ + for (x = 0; x != UATH_N_XFERS; x++) + usbd_transfer_drain(sc->sc_xfer[x]); - /* free buffers */ + /* free data buffers */ UATH_LOCK(sc); uath_free_rx_data_list(sc); uath_free_tx_data_list(sc); uath_free_cmd_list(sc, sc->sc_cmd); UATH_UNLOCK(sc); + /* free USB transfers and some data buffers */ + usbd_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS); + + ieee80211_ifdetach(ic); if_free(ifp); mtx_destroy(&sc->sc_mtx); return (0); @@ -934,10 +953,10 @@ uath_free_data_list(struct uath_softc *sc, struct uath_data data[], int ndata, } else { dp->buf = NULL; } -#ifdef UATH_DEBUG - if (dp->ni != NULL) - device_printf(sc->sc_dev, "Node isn't NULL\n"); -#endif + if (dp->ni != NULL) { + ieee80211_free_node(dp->ni); + dp->ni = NULL; + } } } @@ -1025,10 +1044,6 @@ uath_alloc_tx_data_list(struct uath_softc *sc) static void uath_free_rx_data_list(struct uath_softc *sc) { - - STAILQ_INIT(&sc->sc_rx_active); - STAILQ_INIT(&sc->sc_rx_inactive); - uath_free_data_list(sc, sc->sc_rx, UATH_RX_DATA_LIST_COUNT, 1 /* free mbufs */); } @@ -1036,11 +1051,6 @@ uath_free_rx_data_list(struct uath_softc *sc) static void uath_free_tx_data_list(struct uath_softc *sc) { - - STAILQ_INIT(&sc->sc_tx_active); - STAILQ_INIT(&sc->sc_tx_inactive); - STAILQ_INIT(&sc->sc_tx_pending); - uath_free_data_list(sc, sc->sc_tx, UATH_TX_DATA_LIST_COUNT, 0 /* no mbufs */); } @@ -1543,7 +1553,15 @@ uath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { struct ieee80211com *ic = ifp->if_l2com; struct ifreq *ifr = (struct ifreq *) data; - int error = 0, startall = 0; + struct uath_softc *sc = ifp->if_softc; + int error; + int startall = 0; + + UATH_LOCK(sc); + error = (sc->sc_flags & UATH_FLAG_INVALID) ? ENXIO : 0; + UATH_UNLOCK(sc); + if (error) + return (error); switch (cmd) { case SIOCSIFFLAGS: diff --git a/sys/dev/usb/wlan/if_upgt.c b/sys/dev/usb/wlan/if_upgt.c index 6b49df1f836..7f70d5a27e8 100644 --- a/sys/dev/usb/wlan/if_upgt.c +++ b/sys/dev/usb/wlan/if_upgt.c @@ -466,7 +466,14 @@ upgt_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) struct upgt_softc *sc = ifp->if_softc; struct ieee80211com *ic = ifp->if_l2com; struct ifreq *ifr = (struct ifreq *) data; - int error = 0, startall = 0; + int error; + int startall = 0; + + UPGT_LOCK(sc); + error = (sc->sc_flags & UPGT_FLAG_DETACHED) ? ENXIO : 0; + UPGT_UNLOCK(sc); + if (error) + return (error); switch (cmd) { case SIOCSIFFLAGS: @@ -1976,7 +1983,6 @@ upgt_alloc_rx(struct upgt_softc *sc) data->buf = ((uint8_t *)sc->sc_rx_dma_buf) + (i * MCLBYTES); STAILQ_INSERT_TAIL(&sc->sc_rx_inactive, data, next); } - return (0); } @@ -1986,22 +1992,42 @@ upgt_detach(device_t dev) struct upgt_softc *sc = device_get_softc(dev); struct ifnet *ifp = sc->sc_ifp; struct ieee80211com *ic = ifp->if_l2com; + unsigned int x; - if (!device_is_attached(dev)) - return 0; + /* + * Prevent further allocations from RX/TX/CMD + * data lists and ioctls + */ + UPGT_LOCK(sc); + sc->sc_flags |= UPGT_FLAG_DETACHED; + + STAILQ_INIT(&sc->sc_tx_active); + STAILQ_INIT(&sc->sc_tx_inactive); + STAILQ_INIT(&sc->sc_tx_pending); + + STAILQ_INIT(&sc->sc_rx_active); + STAILQ_INIT(&sc->sc_rx_inactive); + UPGT_UNLOCK(sc); upgt_stop(sc); callout_drain(&sc->sc_led_ch); callout_drain(&sc->sc_watchdog_ch); - ieee80211_ifdetach(ic); - - usbd_transfer_unsetup(sc->sc_xfer, UPGT_N_XFERS); + /* drain USB transfers */ + for (x = 0; x != UPGT_N_XFERS; x++) + usbd_transfer_drain(sc->sc_xfer[x]); + /* free data buffers */ + UPGT_LOCK(sc); upgt_free_rx(sc); upgt_free_tx(sc); + UPGT_UNLOCK(sc); + /* free USB transfers and some data buffers */ + usbd_transfer_unsetup(sc->sc_xfer, UPGT_N_XFERS); + + ieee80211_ifdetach(ic); if_free(ifp); mtx_destroy(&sc->sc_mtx); @@ -2029,6 +2055,9 @@ upgt_free_tx(struct upgt_softc *sc) for (i = 0; i < UPGT_TX_MAXCOUNT; i++) { struct upgt_data *data = &sc->sc_tx_data[i]; + if (data->ni != NULL) + ieee80211_free_node(data->ni); + data->buf = NULL; data->ni = NULL; } diff --git a/sys/dev/usb/wlan/if_upgtvar.h b/sys/dev/usb/wlan/if_upgtvar.h index 6e22de24e03..fd38be1dc1c 100644 --- a/sys/dev/usb/wlan/if_upgtvar.h +++ b/sys/dev/usb/wlan/if_upgtvar.h @@ -429,6 +429,7 @@ struct upgt_softc { int sc_flags; #define UPGT_FLAG_FWLOADED (1 << 0) #define UPGT_FLAG_INITDONE (1 << 1) +#define UPGT_FLAG_DETACHED (1 << 2) int sc_if_flags; int sc_debug; diff --git a/sys/dev/usb/wlan/if_ural.c b/sys/dev/usb/wlan/if_ural.c index 14c28687a6c..f3fa1ca2093 100644 --- a/sys/dev/usb/wlan/if_ural.c +++ b/sys/dev/usb/wlan/if_ural.c @@ -385,8 +385,7 @@ static device_method_t ural_methods[] = { DEVMETHOD(device_probe, ural_match), DEVMETHOD(device_attach, ural_attach), DEVMETHOD(device_detach, ural_detach), - - { 0, 0 } + DEVMETHOD_END }; static driver_t ural_driver = { @@ -528,6 +527,11 @@ ural_detach(device_t self) struct ifnet *ifp = sc->sc_ifp; struct ieee80211com *ic; + /* prevent further ioctls */ + RAL_LOCK(sc); + sc->sc_detached = 1; + RAL_UNLOCK(sc); + /* stop all USB transfers */ usbd_transfer_unsetup(sc->sc_xfer, URAL_N_TRANSFER); @@ -1371,7 +1375,14 @@ ural_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) struct ural_softc *sc = ifp->if_softc; struct ieee80211com *ic = ifp->if_l2com; struct ifreq *ifr = (struct ifreq *) data; - int error = 0, startall = 0; + int error; + int startall = 0; + + RAL_LOCK(sc); + error = sc->sc_detached ? ENXIO : 0; + RAL_UNLOCK(sc); + if (error) + return (error); switch (cmd) { case SIOCSIFFLAGS: diff --git a/sys/dev/usb/wlan/if_uralvar.h b/sys/dev/usb/wlan/if_uralvar.h index 46dbfbddc8b..3bd015e219b 100644 --- a/sys/dev/usb/wlan/if_uralvar.h +++ b/sys/dev/usb/wlan/if_uralvar.h @@ -110,6 +110,7 @@ struct ural_softc { uint32_t rf_regs[4]; uint8_t txpow[14]; uint8_t sc_bssid[6]; + uint8_t sc_detached; struct { uint8_t val; diff --git a/sys/dev/usb/wlan/if_urtw.c b/sys/dev/usb/wlan/if_urtw.c index b0202c5efbe..184317bd3eb 100644 --- a/sys/dev/usb/wlan/if_urtw.c +++ b/sys/dev/usb/wlan/if_urtw.c @@ -651,8 +651,8 @@ static struct ieee80211vap *urtw_vap_create(struct ieee80211com *, const uint8_t [IEEE80211_ADDR_LEN]); static void urtw_vap_delete(struct ieee80211vap *); static void urtw_init(void *); -static void urtw_stop(struct ifnet *, int); -static void urtw_stop_locked(struct ifnet *, int); +static void urtw_stop(struct ifnet *); +static void urtw_stop_locked(struct ifnet *); static int urtw_ioctl(struct ifnet *, u_long, caddr_t); static void urtw_start(struct ifnet *); static int urtw_alloc_rx_data_list(struct urtw_softc *); @@ -933,42 +933,63 @@ urtw_detach(device_t dev) struct urtw_softc *sc = device_get_softc(dev); struct ifnet *ifp = sc->sc_ifp; struct ieee80211com *ic = ifp->if_l2com; + unsigned int x; + unsigned int n_xfers; - if (!device_is_attached(dev)) - return (0); + /* Prevent further ioctls */ + URTW_LOCK(sc); + sc->sc_flags |= URTW_DETACHED; + URTW_UNLOCK(sc); + + urtw_stop(ifp); - urtw_stop(ifp, 1); ieee80211_draintask(ic, &sc->sc_updateslot_task); ieee80211_draintask(ic, &sc->sc_led_task); usb_callout_drain(&sc->sc_led_ch); callout_drain(&sc->sc_watchdog_ch); - ieee80211_ifdetach(ic); + n_xfers = (sc->sc_flags & URTW_RTL8187B) ? + URTW_8187B_N_XFERS : URTW_8187L_N_XFERS; - usbd_transfer_unsetup(sc->sc_xfer, (sc->sc_flags & URTW_RTL8187B) ? - URTW_8187B_N_XFERS : URTW_8187L_N_XFERS); + /* prevent further allocations from RX/TX data lists */ + URTW_LOCK(sc); + STAILQ_INIT(&sc->sc_tx_active); + STAILQ_INIT(&sc->sc_tx_inactive); + STAILQ_INIT(&sc->sc_tx_pending); + STAILQ_INIT(&sc->sc_rx_active); + STAILQ_INIT(&sc->sc_rx_inactive); + URTW_UNLOCK(sc); + + /* drain USB transfers */ + for (x = 0; x != n_xfers; x++) + usbd_transfer_drain(sc->sc_xfer[x]); + + /* free data buffers */ + URTW_LOCK(sc); urtw_free_tx_data_list(sc); urtw_free_rx_data_list(sc); + URTW_UNLOCK(sc); + /* free USB transfers and some data buffers */ + usbd_transfer_unsetup(sc->sc_xfer, n_xfers); + + ieee80211_ifdetach(ic); if_free(ifp); mtx_destroy(&sc->sc_mtx); - return (0); } static void urtw_free_tx_data_list(struct urtw_softc *sc) { - urtw_free_data_list(sc, sc->sc_tx, URTW_TX_DATA_LIST_COUNT, 0); } static void urtw_free_rx_data_list(struct urtw_softc *sc) { - urtw_free_data_list(sc, sc->sc_rx, URTW_RX_DATA_LIST_COUNT, 1); } @@ -1046,7 +1067,7 @@ urtw_init_locked(void *arg) usb_error_t error; if (ifp->if_drv_flags & IFF_DRV_RUNNING) - urtw_stop_locked(ifp, 0); + urtw_stop_locked(ifp); error = (sc->sc_flags & URTW_RTL8187B) ? urtw_adapter_start_b(sc) : urtw_adapter_start(sc); @@ -1309,13 +1330,12 @@ urtw_do_request(struct urtw_softc *sc, } static void -urtw_stop_locked(struct ifnet *ifp, int disable) +urtw_stop_locked(struct ifnet *ifp) { struct urtw_softc *sc = ifp->if_softc; uint8_t data8; usb_error_t error; - (void)disable; ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); error = urtw_intr_disable(sc); @@ -1349,12 +1369,12 @@ fail: } static void -urtw_stop(struct ifnet *ifp, int disable) +urtw_stop(struct ifnet *ifp) { struct urtw_softc *sc = ifp->if_softc; URTW_LOCK(sc); - urtw_stop_locked(ifp, disable); + urtw_stop_locked(ifp); URTW_UNLOCK(sc); } @@ -1379,7 +1399,14 @@ urtw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) struct urtw_softc *sc = ifp->if_softc; struct ieee80211com *ic = ifp->if_l2com; struct ifreq *ifr = (struct ifreq *) data; - int error = 0, startall = 0; + int error; + int startall = 0; + + URTW_LOCK(sc); + error = (sc->sc_flags & URTW_DETACHED) ? ENXIO : 0; + URTW_UNLOCK(sc); + if (error) + return (error); switch (cmd) { case SIOCSIFFLAGS: @@ -1394,7 +1421,7 @@ urtw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) } } else { if (ifp->if_drv_flags & IFF_DRV_RUNNING) - urtw_stop(ifp, 1); + urtw_stop(ifp); } sc->sc_if_flags = ifp->if_flags; if (startall) @@ -1410,7 +1437,6 @@ urtw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) error = EINVAL; break; } - return (error); } @@ -1991,9 +2017,11 @@ urtw_update_msr(struct urtw_softc *sc) data |= URTW_MSR_LINK_HOSTAP; break; default: - panic("unsupported operation mode 0x%x\n", + DPRINTF(sc, URTW_DEBUG_STATE, + "unsupported operation mode 0x%x\n", ic->ic_opmode); - /* never reach */ + error = USB_ERR_INVAL; + goto fail; } } else data |= URTW_MSR_LINK_NONE; @@ -2424,8 +2452,10 @@ urtw_get_rfchip(struct urtw_softc *sc) sc->sc_rf_stop = urtw_8225_rf_stop; break; default: - panic("unsupported RF chip %d\n", data & 0xff); - /* never reach */ + DPRINTF(sc, URTW_DEBUG_STATE, + "unsupported RF chip %d\n", data & 0xff); + error = USB_ERR_INVAL; + goto fail; } device_printf(sc->sc_dev, "%s rf %s hwrev %s\n", @@ -3605,8 +3635,10 @@ urtw_led_ctl(struct urtw_softc *sc, int mode) error = urtw_led_mode3(sc, mode); break; default: - panic("unsupported LED mode %d\n", sc->sc_strategy); - /* never reach */ + DPRINTF(sc, URTW_DEBUG_STATE, + "unsupported LED mode %d\n", sc->sc_strategy); + error = USB_ERR_INVAL; + break; } return (error); @@ -3631,8 +3663,9 @@ urtw_led_mode0(struct urtw_softc *sc, int mode) sc->sc_gpio_ledstate = URTW_LED_ON; break; default: - panic("unsupported LED mode 0x%x", mode); - /* never reach */ + DPRINTF(sc, URTW_DEBUG_STATE, + "unsupported LED mode 0x%x", mode); + return (USB_ERR_INVAL); } switch (sc->sc_gpio_ledstate) { @@ -3655,8 +3688,9 @@ urtw_led_mode0(struct urtw_softc *sc, int mode) urtw_led_off(sc, URTW_LED_GPIO); break; default: - panic("unknown LED status 0x%x", sc->sc_gpio_ledstate); - /* never reach */ + DPRINTF(sc, URTW_DEBUG_STATE, + "unknown LED status 0x%x", sc->sc_gpio_ledstate); + return (USB_ERR_INVAL); } return (0); } @@ -3664,21 +3698,18 @@ urtw_led_mode0(struct urtw_softc *sc, int mode) static usb_error_t urtw_led_mode1(struct urtw_softc *sc, int mode) { - return (USB_ERR_INVAL); } static usb_error_t urtw_led_mode2(struct urtw_softc *sc, int mode) { - return (USB_ERR_INVAL); } static usb_error_t urtw_led_mode3(struct urtw_softc *sc, int mode) { - return (USB_ERR_INVAL); } @@ -3694,13 +3725,17 @@ urtw_led_on(struct urtw_softc *sc, int type) urtw_write8_m(sc, URTW_GP_ENABLE, 0x00); break; default: - panic("unsupported LED PIN type 0x%x", + DPRINTF(sc, URTW_DEBUG_STATE, + "unsupported LED PIN type 0x%x", sc->sc_gpio_ledpin); - /* never reach */ + error = USB_ERR_INVAL; + goto fail; } } else { - panic("unsupported LED type 0x%x", type); - /* never reach */ + DPRINTF(sc, URTW_DEBUG_STATE, + "unsupported LED type 0x%x", type); + error = USB_ERR_INVAL; + goto fail; } sc->sc_gpio_ledon = 1; @@ -3721,13 +3756,17 @@ urtw_led_off(struct urtw_softc *sc, int type) URTW_GP_ENABLE, URTW_GP_ENABLE_DATA_MAGIC1); break; default: - panic("unsupported LED PIN type 0x%x", + DPRINTF(sc, URTW_DEBUG_STATE, + "unsupported LED PIN type 0x%x", sc->sc_gpio_ledpin); - /* never reach */ + error = USB_ERR_INVAL; + goto fail; } } else { - panic("unsupported LED type 0x%x", type); - /* never reach */ + DPRINTF(sc, URTW_DEBUG_STATE, + "unsupported LED type 0x%x", type); + error = USB_ERR_INVAL; + goto fail; } sc->sc_gpio_ledon = 0; @@ -3751,8 +3790,12 @@ urtw_ledtask(void *arg, int pending) { struct urtw_softc *sc = arg; - if (sc->sc_strategy != URTW_SW_LED_MODE0) - panic("could not process a LED strategy 0x%x", sc->sc_strategy); + if (sc->sc_strategy != URTW_SW_LED_MODE0) { + DPRINTF(sc, URTW_DEBUG_STATE, + "could not process a LED strategy 0x%x", + sc->sc_strategy); + return; + } URTW_LOCK(sc); urtw_led_blink(sc); @@ -3799,8 +3842,10 @@ urtw_led_blink(struct urtw_softc *sc) usb_callout_reset(&sc->sc_led_ch, hz, urtw_led_ch, sc); break; default: - panic("unknown LED status 0x%x", sc->sc_gpio_ledstate); - /* never reach */ + DPRINTF(sc, URTW_DEBUG_STATE, + "unknown LED status 0x%x", + sc->sc_gpio_ledstate); + return (USB_ERR_INVAL); } return (0); } diff --git a/sys/dev/usb/wlan/if_urtwvar.h b/sys/dev/usb/wlan/if_urtwvar.h index c8f94ffbad3..6b551065be6 100644 --- a/sys/dev/usb/wlan/if_urtwvar.h +++ b/sys/dev/usb/wlan/if_urtwvar.h @@ -107,6 +107,7 @@ struct urtw_softc { #define URTW_RTL8187B_REV_B (1 << 3) #define URTW_RTL8187B_REV_D (1 << 4) #define URTW_RTL8187B_REV_E (1 << 5) +#define URTW_DETACHED (1 << 6) enum ieee80211_state sc_state; int sc_epromtype; diff --git a/sys/dev/usb/wlan/if_zyd.c b/sys/dev/usb/wlan/if_zyd.c index b960ce02a6f..3d3f2695013 100644 --- a/sys/dev/usb/wlan/if_zyd.c +++ b/sys/dev/usb/wlan/if_zyd.c @@ -438,12 +438,29 @@ zyd_detach(device_t dev) struct zyd_softc *sc = device_get_softc(dev); struct ifnet *ifp = sc->sc_ifp; struct ieee80211com *ic; + unsigned int x; - /* stop all USB transfers */ - usbd_transfer_unsetup(sc->sc_xfer, ZYD_N_TRANSFER); + /* + * Prevent further allocations from RX/TX data + * lists and ioctls: + */ + ZYD_LOCK(sc); + sc->sc_flags |= ZYD_FLAG_DETACHED; + STAILQ_INIT(&sc->tx_q); + STAILQ_INIT(&sc->tx_free); + ZYD_UNLOCK(sc); + + /* drain USB transfers */ + for (x = 0; x != ZYD_N_TRANSFER; x++) + usbd_transfer_drain(sc->sc_xfer[x]); /* free TX list, if any */ + ZYD_LOCK(sc); zyd_unsetup_tx_list(sc); + ZYD_UNLOCK(sc); + + /* free USB transfers and some data buffers */ + usbd_transfer_unsetup(sc->sc_xfer, ZYD_N_TRANSFER); if (ifp) { ic = ifp->if_l2com; @@ -2637,7 +2654,14 @@ zyd_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) struct zyd_softc *sc = ifp->if_softc; struct ieee80211com *ic = ifp->if_l2com; struct ifreq *ifr = (struct ifreq *) data; - int error = 0, startall = 0; + int error; + int startall = 0; + + ZYD_LOCK(sc); + error = (sc->sc_flags & ZYD_FLAG_DETACHED) ? ENXIO : 0; + ZYD_UNLOCK(sc); + if (error) + return (error); switch (cmd) { case SIOCSIFFLAGS: @@ -2928,8 +2952,7 @@ static device_method_t zyd_methods[] = { DEVMETHOD(device_probe, zyd_match), DEVMETHOD(device_attach, zyd_attach), DEVMETHOD(device_detach, zyd_detach), - - { 0, 0 } + DEVMETHOD_END }; static driver_t zyd_driver = { diff --git a/sys/dev/usb/wlan/if_zydreg.h b/sys/dev/usb/wlan/if_zydreg.h index dd11632bf2a..4ecc20da85b 100644 --- a/sys/dev/usb/wlan/if_zydreg.h +++ b/sys/dev/usb/wlan/if_zydreg.h @@ -1259,6 +1259,7 @@ struct zyd_softc { #define ZYD_FLAG_FWLOADED (1 << 0) #define ZYD_FLAG_INITONCE (1 << 1) #define ZYD_FLAG_INITDONE (1 << 2) +#define ZYD_FLAG_DETACHED (1 << 3) struct zyd_rf sc_rf; From 74b50dd979d8277c2629f39f8201b9f51176f812 Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Sun, 10 Feb 2013 10:55:20 +0000 Subject: [PATCH 0090/1476] Fix correct use of USB header files. --- sys/dev/usb/net/if_smsc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/dev/usb/net/if_smsc.c b/sys/dev/usb/net/if_smsc.c index 5c3db72c616..03033cd2771 100644 --- a/sys/dev/usb/net/if_smsc.c +++ b/sys/dev/usb/net/if_smsc.c @@ -99,9 +99,9 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include -#include "if_smscreg.h" + +#include #ifdef USB_DEBUG static int smsc_debug = 0; From 6950c75f401152bfb9b7a0603241434b51cba482 Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Sun, 10 Feb 2013 10:56:13 +0000 Subject: [PATCH 0091/1476] - Move scratch data from the USB bus structure to the USB device structure so that simultaneous access cannot happen. Protect scratch area using the enumeration lock. Also reduce stack usage in usbd_transfer_setup() by moving some big stack members to the scratch area. This saves around 200 bytes of stack. - Fix a whitespace. MFC after: 1 week --- sys/boot/usb/bsd_global.h | 2 +- sys/dev/usb/template/usb_template.c | 65 ++++++----- sys/dev/usb/usb_bus.h | 10 -- sys/dev/usb/usb_controller.h | 45 -------- sys/dev/usb/usb_device.c | 85 +++++++------- sys/dev/usb/usb_device.h | 73 +++++++++++- sys/dev/usb/usb_generic.c | 11 +- sys/dev/usb/usb_handle_request.c | 9 +- sys/dev/usb/usb_msctest.c | 9 +- sys/dev/usb/usb_transfer.c | 167 +++++++++++++++------------- sys/dev/usb/usb_util.c | 22 ++-- 11 files changed, 269 insertions(+), 229 deletions(-) diff --git a/sys/boot/usb/bsd_global.h b/sys/boot/usb/bsd_global.h index 80cbd6366a3..2fb0dcca60a 100644 --- a/sys/boot/usb/bsd_global.h +++ b/sys/boot/usb/bsd_global.h @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -52,7 +53,6 @@ #include #include #include -#include #include #include #include diff --git a/sys/dev/usb/template/usb_template.c b/sys/dev/usb/template/usb_template.c index 36c11d9c515..b815161e898 100644 --- a/sys/dev/usb/template/usb_template.c +++ b/sys/dev/usb/template/usb_template.c @@ -849,20 +849,20 @@ usb_hw_ep_resolve(struct usb_device *udev, struct usb_device_descriptor *dd; uint16_t mps; - if (desc == NULL) { + if (desc == NULL) return (USB_ERR_INVAL); - } + /* get bus methods */ methods = udev->bus->methods; - if (methods->get_hw_ep_profile == NULL) { + if (methods->get_hw_ep_profile == NULL) return (USB_ERR_INVAL); - } + if (desc->bDescriptorType == UDESC_DEVICE) { - if (desc->bLength < sizeof(*dd)) { + if (desc->bLength < sizeof(*dd)) return (USB_ERR_INVAL); - } + dd = (void *)desc; /* get HW control endpoint 0 profile */ @@ -909,13 +909,12 @@ usb_hw_ep_resolve(struct usb_device *udev, } return (0); /* success */ } - if (desc->bDescriptorType != UDESC_CONFIG) { + if (desc->bDescriptorType != UDESC_CONFIG) return (USB_ERR_INVAL); - } - if (desc->bLength < sizeof(*(ues->cd))) { + if (desc->bLength < sizeof(*(ues->cd))) return (USB_ERR_INVAL); - } - ues = udev->bus->scratch[0].hw_ep_scratch; + + ues = udev->scratch.hw_ep_scratch; memset(ues, 0, sizeof(*ues)); @@ -1236,13 +1235,18 @@ usb_temp_setup(struct usb_device *udev, { struct usb_temp_setup *uts; void *buf; + usb_error_t error; uint8_t n; + uint8_t do_unlock; - if (tdd == NULL) { - /* be NULL safe */ + /* be NULL safe */ + if (tdd == NULL) return (0); - } - uts = udev->bus->scratch[0].temp_setup; + + /* Protect scratch area */ + do_unlock = usbd_enum_lock(udev); + + uts = udev->scratch.temp_setup; memset(uts, 0, sizeof(*uts)); @@ -1255,17 +1259,24 @@ usb_temp_setup(struct usb_device *udev, if (uts->err) { /* some error happened */ - return (uts->err); + goto done; } /* sanity check */ if (uts->size == 0) { - return (USB_ERR_INVAL); + uts->err = USB_ERR_INVAL; + goto done; } /* allocate zeroed memory */ uts->buf = malloc(uts->size, M_USB, M_WAITOK | M_ZERO); + /* + * Allow malloc() to return NULL regardless of M_WAITOK flag. + * This helps when porting the software to non-FreeBSD + * systems. + */ if (uts->buf == NULL) { /* could not allocate memory */ - return (USB_ERR_NOMEM); + uts->err = USB_ERR_NOMEM; + goto done; } /* second pass */ @@ -1280,7 +1291,7 @@ usb_temp_setup(struct usb_device *udev, if (uts->err) { /* some error happened during second pass */ - goto error; + goto done; } /* * Resolve all endpoint addresses ! @@ -1291,7 +1302,7 @@ usb_temp_setup(struct usb_device *udev, DPRINTFN(0, "Could not resolve endpoints for " "Device Descriptor, error = %s\n", usbd_errstr(uts->err)); - goto error; + goto done; } for (n = 0;; n++) { @@ -1304,14 +1315,16 @@ usb_temp_setup(struct usb_device *udev, DPRINTFN(0, "Could not resolve endpoints for " "Config Descriptor %u, error = %s\n", n, usbd_errstr(uts->err)); - goto error; + goto done; } } - return (uts->err); - -error: - usb_temp_unsetup(udev); - return (uts->err); +done: + error = uts->err; + if (error) + usb_temp_unsetup(udev); + if (do_unlock) + usbd_enum_unlock(udev); + return (error); } /*------------------------------------------------------------------------* diff --git a/sys/dev/usb/usb_bus.h b/sys/dev/usb/usb_bus.h index dea15f8f71a..2898eee87cb 100644 --- a/sys/dev/usb/usb_bus.h +++ b/sys/dev/usb/usb_bus.h @@ -113,16 +113,6 @@ struct usb_bus { uint8_t devices_max; /* maximum number of USB devices */ uint8_t do_probe; /* set if USB should be re-probed */ uint8_t no_explore; /* don't explore USB ports */ - - /* - * The scratch area can only be used inside the explore thread - * belonging to the give serial bus. - */ - union { - struct usb_hw_ep_scratch hw_ep_scratch[1]; - struct usb_temp_setup temp_setup[1]; - uint8_t data[255]; - } scratch[1]; }; #endif /* _USB_BUS_H_ */ diff --git a/sys/dev/usb/usb_controller.h b/sys/dev/usb/usb_controller.h index 6c144549c7b..3ee6f04ac2a 100644 --- a/sys/dev/usb/usb_controller.h +++ b/sys/dev/usb/usb_controller.h @@ -40,7 +40,6 @@ struct usb_page_cache; struct usb_setup_params; struct usb_hw_ep_profile; struct usb_fs_isoc_schedule; -struct usb_config_descriptor; struct usb_endpoint_descriptor; /* typedefs */ @@ -186,50 +185,6 @@ struct usb_hw_ep_profile { uint8_t support_out:1; /* OUT-token is supported */ }; -/* - * The following structure is used when trying to allocate hardware - * endpoints for an USB configuration in USB device side mode. - */ -struct usb_hw_ep_scratch_sub { - const struct usb_hw_ep_profile *pf; - uint16_t max_frame_size; - uint8_t hw_endpoint_out; - uint8_t hw_endpoint_in; - uint8_t needs_ep_type; - uint8_t needs_in:1; - uint8_t needs_out:1; -}; - -/* - * The following structure is used when trying to allocate hardware - * endpoints for an USB configuration in USB device side mode. - */ -struct usb_hw_ep_scratch { - struct usb_hw_ep_scratch_sub ep[USB_EP_MAX]; - struct usb_hw_ep_scratch_sub *ep_max; - struct usb_config_descriptor *cd; - struct usb_device *udev; - struct usb_bus_methods *methods; - uint8_t bmOutAlloc[(USB_EP_MAX + 15) / 16]; - uint8_t bmInAlloc[(USB_EP_MAX + 15) / 16]; -}; - -/* - * The following structure is used when generating USB descriptors - * from USB templates. - */ -struct usb_temp_setup { - void *buf; - usb_size_t size; - enum usb_dev_speed usb_speed; - uint8_t self_powered; - uint8_t bNumEndpoints; - uint8_t bInterfaceNumber; - uint8_t bAlternateSetting; - uint8_t bConfigurationValue; - usb_error_t err; -}; - /* prototypes */ void usb_bus_mem_flush_all(struct usb_bus *bus, usb_bus_mem_cb_t *cb); diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c index a9aab53e8f3..fdc734c2d58 100644 --- a/sys/dev/usb/usb_device.c +++ b/sys/dev/usb/usb_device.c @@ -460,13 +460,8 @@ usb_unconfigure(struct usb_device *udev, uint8_t flag) { uint8_t do_unlock; - /* automatic locking */ - if (usbd_enum_is_locked(udev)) { - do_unlock = 0; - } else { - do_unlock = 1; - usbd_enum_lock(udev); - } + /* Prevent re-enumeration */ + do_unlock = usbd_enum_lock(udev); /* detach all interface drivers */ usb_detach_device(udev, USB_IFACE_INDEX_ANY, flag); @@ -529,13 +524,8 @@ usbd_set_config_index(struct usb_device *udev, uint8_t index) DPRINTFN(6, "udev=%p index=%d\n", udev, index); - /* automatic locking */ - if (usbd_enum_is_locked(udev)) { - do_unlock = 0; - } else { - do_unlock = 1; - usbd_enum_lock(udev); - } + /* Prevent re-enumeration */ + do_unlock = usbd_enum_lock(udev); usb_unconfigure(udev, 0); @@ -888,13 +878,9 @@ usbd_set_alt_interface_index(struct usb_device *udev, usb_error_t err; uint8_t do_unlock; - /* automatic locking */ - if (usbd_enum_is_locked(udev)) { - do_unlock = 0; - } else { - do_unlock = 1; - usbd_enum_lock(udev); - } + /* Prevent re-enumeration */ + do_unlock = usbd_enum_lock(udev); + if (iface == NULL) { err = USB_ERR_INVAL; goto done; @@ -931,7 +917,6 @@ usbd_set_alt_interface_index(struct usb_device *udev, done: if (do_unlock) usbd_enum_unlock(udev); - return (err); } @@ -1310,13 +1295,8 @@ usb_probe_and_attach(struct usb_device *udev, uint8_t iface_index) DPRINTF("udev == NULL\n"); return (USB_ERR_INVAL); } - /* automatic locking */ - if (usbd_enum_is_locked(udev)) { - do_unlock = 0; - } else { - do_unlock = 1; - usbd_enum_lock(udev); - } + /* Prevent re-enumeration */ + do_unlock = usbd_enum_lock(udev); if (udev->curr_config_index == USB_UNCONFIG_INDEX) { /* do nothing - no configuration has been set */ @@ -1403,7 +1383,6 @@ usb_probe_and_attach(struct usb_device *udev, uint8_t iface_index) done: if (do_unlock) usbd_enum_unlock(udev); - return (0); } @@ -1532,6 +1511,7 @@ usb_alloc_device(device_t parent_dev, struct usb_bus *bus, uint8_t config_index; uint8_t config_quirk; uint8_t set_config_failed; + uint8_t do_unlock; DPRINTF("parent_dev=%p, bus=%p, parent_hub=%p, depth=%u, " "port_index=%u, port_no=%u, speed=%u, usb_mode=%u\n", @@ -1750,7 +1730,11 @@ usb_alloc_device(device_t parent_dev, struct usb_bus *bus, * device descriptor. If no strings are present there we * simply disable all USB strings. */ - scratch_ptr = udev->bus->scratch[0].data; + + /* Protect scratch area */ + do_unlock = usbd_enum_lock(udev); + + scratch_ptr = udev->scratch.data; if (udev->ddesc.iManufacturer || udev->ddesc.iProduct || @@ -1775,7 +1759,7 @@ usb_alloc_device(device_t parent_dev, struct usb_bus *bus, mask = usb_lang_mask; /* align length correctly */ - scratch_ptr[0] &= ~1; + scratch_ptr[0] &= ~1U; /* fix compiler warning */ langid = 0; @@ -1796,6 +1780,9 @@ usb_alloc_device(device_t parent_dev, struct usb_bus *bus, udev->langid = langid; } + if (do_unlock) + usbd_enum_unlock(udev); + /* assume 100mA bus powered for now. Changed when configured. */ udev->power = USB_MIN_POWER; /* fetch the vendor and product strings from the device */ @@ -2295,9 +2282,13 @@ usbd_set_device_strings(struct usb_device *udev) size_t temp_size; uint16_t vendor_id; uint16_t product_id; + uint8_t do_unlock; - temp_ptr = (char *)udev->bus->scratch[0].data; - temp_size = sizeof(udev->bus->scratch[0].data); + /* Protect scratch area */ + do_unlock = usbd_enum_lock(udev); + + temp_ptr = (char *)udev->scratch.data; + temp_size = sizeof(udev->scratch.data); vendor_id = UGETW(udd->idVendor); product_id = UGETW(udd->idProduct); @@ -2352,6 +2343,9 @@ usbd_set_device_strings(struct usb_device *udev) snprintf(temp_ptr, temp_size, "product 0x%04x", product_id); udev->product = strdup(temp_ptr, M_USB); } + + if (do_unlock) + usbd_enum_unlock(udev); } /* @@ -2664,11 +2658,17 @@ usbd_device_attached(struct usb_device *udev) return (udev->state > USB_STATE_DETACHED); } -/* The following function locks enumerating the given USB device. */ - -void +/* + * The following function locks enumerating the given USB device. If + * the lock is already grabbed this function returns zero. Else a + * non-zero value is returned. + */ +uint8_t usbd_enum_lock(struct usb_device *udev) { + if (sx_xlocked(&udev->enum_sx)) + return (0); + sx_xlock(&udev->enum_sx); sx_xlock(&udev->sr_sx); /* @@ -2677,6 +2677,7 @@ usbd_enum_lock(struct usb_device *udev) * locked multiple times. */ mtx_lock(&Giant); + return (1); } /* The following function unlocks enumerating the given USB device. */ @@ -2783,13 +2784,8 @@ usbd_set_endpoint_mode(struct usb_device *udev, struct usb_endpoint *ep, usb_error_t error; uint8_t do_unlock; - /* automatic locking */ - if (usbd_enum_is_locked(udev)) { - do_unlock = 0; - } else { - do_unlock = 1; - usbd_enum_lock(udev); - } + /* Prevent re-enumeration */ + do_unlock = usbd_enum_lock(udev); if (udev->bus->methods->set_endpoint_mode != NULL) { error = (udev->bus->methods->set_endpoint_mode) ( @@ -2805,7 +2801,6 @@ usbd_set_endpoint_mode(struct usb_device *udev, struct usb_endpoint *ep, if (do_unlock) usbd_enum_unlock(udev); - return (error); } diff --git a/sys/dev/usb/usb_device.h b/sys/dev/usb/usb_device.h index 4eaadc730f1..22a4652011a 100644 --- a/sys/dev/usb/usb_device.h +++ b/sys/dev/usb/usb_device.h @@ -27,9 +27,18 @@ #ifndef _USB_DEVICE_H_ #define _USB_DEVICE_H_ -struct usb_symlink; /* UGEN */ +#ifndef USB_GLOBAL_INCLUDE_FILE +#include +#include +#include +#endif + +struct usb_bus_methods; +struct usb_config_descriptor; struct usb_device; /* linux compat */ struct usb_fs_privdata; +struct usb_hw_ep_profile; +struct usb_symlink; /* UGEN */ #define USB_CTRL_XFER_MAX 2 @@ -107,6 +116,64 @@ struct usb_power_save { usb_size_t write_refs; /* data write references */ }; +/* + * The following structure is used when trying to allocate hardware + * endpoints for an USB configuration in USB device side mode. + */ +struct usb_hw_ep_scratch_sub { + const struct usb_hw_ep_profile *pf; + uint16_t max_frame_size; + uint8_t hw_endpoint_out; + uint8_t hw_endpoint_in; + uint8_t needs_ep_type; + uint8_t needs_in:1; + uint8_t needs_out:1; +}; + +/* + * The following structure is used when trying to allocate hardware + * endpoints for an USB configuration in USB device side mode. + */ +struct usb_hw_ep_scratch { + struct usb_hw_ep_scratch_sub ep[USB_EP_MAX]; + struct usb_hw_ep_scratch_sub *ep_max; + struct usb_config_descriptor *cd; + struct usb_device *udev; + struct usb_bus_methods *methods; + uint8_t bmOutAlloc[(USB_EP_MAX + 15) / 16]; + uint8_t bmInAlloc[(USB_EP_MAX + 15) / 16]; +}; + +/* + * The following structure is used when generating USB descriptors + * from USB templates. + */ +struct usb_temp_setup { + void *buf; + usb_size_t size; + enum usb_dev_speed usb_speed; + uint8_t self_powered; + uint8_t bNumEndpoints; + uint8_t bInterfaceNumber; + uint8_t bAlternateSetting; + uint8_t bConfigurationValue; + usb_error_t err; +}; + +/* + * The scratch area for USB devices. Access to this structure is + * protected by the enumeration SX lock. + */ +union usb_device_scratch { + struct usb_hw_ep_scratch hw_ep_scratch[1]; + struct usb_temp_setup temp_setup[1]; + struct { + struct usb_xfer dummy; + struct usb_setup_params parm; + } xfer_setup[1]; + uint8_t data[255]; +}; + /* * The following structure defines an USB device. There exists one of * these structures for every USB device. @@ -191,6 +258,8 @@ struct usb_device { #endif uint32_t clear_stall_errors; /* number of clear-stall failures */ + + union usb_device_scratch scratch; }; /* globals */ @@ -227,7 +296,7 @@ struct usb_endpoint *usb_endpoint_foreach(struct usb_device *udev, struct usb_en void usb_set_device_state(struct usb_device *, enum usb_dev_state); enum usb_dev_state usb_get_device_state(struct usb_device *); -void usbd_enum_lock(struct usb_device *); +uint8_t usbd_enum_lock(struct usb_device *); void usbd_enum_unlock(struct usb_device *); void usbd_sr_lock(struct usb_device *); void usbd_sr_unlock(struct usb_device *); diff --git a/sys/dev/usb/usb_generic.c b/sys/dev/usb/usb_generic.c index 13f5bd685e9..34b7778e1f1 100644 --- a/sys/dev/usb/usb_generic.c +++ b/sys/dev/usb/usb_generic.c @@ -719,13 +719,20 @@ ugen_get_cdesc(struct usb_fifo *f, struct usb_gen_descriptor *ugd) return (error); } +/* + * This function is called having the enumeration SX locked which + * protects the scratch area used. + */ static int ugen_get_sdesc(struct usb_fifo *f, struct usb_gen_descriptor *ugd) { - void *ptr = f->udev->bus->scratch[0].data; - uint16_t size = sizeof(f->udev->bus->scratch[0].data); + void *ptr; + uint16_t size; int error; + ptr = f->udev->scratch.data; + size = sizeof(f->udev->scratch.data); + if (usbd_req_get_string_desc(f->udev, NULL, ptr, size, ugd->ugd_lang_id, ugd->ugd_string_index)) { error = EINVAL; diff --git a/sys/dev/usb/usb_handle_request.c b/sys/dev/usb/usb_handle_request.c index 13fff91efa9..a775d6732fc 100644 --- a/sys/dev/usb/usb_handle_request.c +++ b/sys/dev/usb/usb_handle_request.c @@ -191,13 +191,8 @@ usb_check_alt_setting(struct usb_device *udev, uint8_t do_unlock; usb_error_t err = 0; - /* automatic locking */ - if (usbd_enum_is_locked(udev)) { - do_unlock = 0; - } else { - do_unlock = 1; - usbd_enum_lock(udev); - } + /* Prevent re-enumeration */ + do_unlock = usbd_enum_lock(udev); if (alt_index >= usbd_get_no_alts(udev->cdesc, iface->idesc)) err = USB_ERR_INVAL; diff --git a/sys/dev/usb/usb_msctest.c b/sys/dev/usb/usb_msctest.c index a1bc5fc006a..1f0598ab62c 100644 --- a/sys/dev/usb/usb_msctest.c +++ b/sys/dev/usb/usb_msctest.c @@ -505,13 +505,8 @@ bbb_attach(struct usb_device *udev, uint8_t iface_index) usb_error_t err; uint8_t do_unlock; - /* automatic locking */ - if (usbd_enum_is_locked(udev)) { - do_unlock = 0; - } else { - do_unlock = 1; - usbd_enum_lock(udev); - } + /* Prevent re-enumeration */ + do_unlock = usbd_enum_lock(udev); /* * Make sure any driver which is hooked up to this interface, diff --git a/sys/dev/usb/usb_transfer.c b/sys/dev/usb/usb_transfer.c index edcc5960cea..f2acf700dbc 100644 --- a/sys/dev/usb/usb_transfer.c +++ b/sys/dev/usb/usb_transfer.c @@ -22,7 +22,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - */ + */ #ifdef USB_GLOBAL_INCLUDE_FILE #include USB_GLOBAL_INCLUDE_FILE @@ -855,20 +855,17 @@ usbd_transfer_setup(struct usb_device *udev, const struct usb_config *setup_start, uint16_t n_setup, void *priv_sc, struct mtx *xfer_mtx) { - struct usb_xfer dummy; - struct usb_setup_params parm; const struct usb_config *setup_end = setup_start + n_setup; const struct usb_config *setup; + struct usb_setup_params *parm; struct usb_endpoint *ep; struct usb_xfer_root *info; struct usb_xfer *xfer; void *buf = NULL; + usb_error_t error = 0; uint16_t n; uint16_t refcount; - - parm.err = 0; - refcount = 0; - info = NULL; + uint8_t do_unlock; WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "usbd_transfer_setup can sleep!"); @@ -887,31 +884,40 @@ usbd_transfer_setup(struct usb_device *udev, DPRINTFN(6, "using global lock\n"); xfer_mtx = &Giant; } - /* sanity checks */ + + /* more sanity checks */ + for (setup = setup_start, n = 0; setup != setup_end; setup++, n++) { if (setup->bufsize == (usb_frlength_t)-1) { - parm.err = USB_ERR_BAD_BUFSIZE; + error = USB_ERR_BAD_BUFSIZE; DPRINTF("invalid bufsize\n"); } if (setup->callback == NULL) { - parm.err = USB_ERR_NO_CALLBACK; + error = USB_ERR_NO_CALLBACK; DPRINTF("no callback\n"); } ppxfer[n] = NULL; } - if (parm.err) { - goto done; - } - memset(&parm, 0, sizeof(parm)); + if (error) + return (error); - parm.udev = udev; - parm.speed = usbd_get_speed(udev); - parm.hc_max_packet_count = 1; + /* Protect scratch area */ + do_unlock = usbd_enum_lock(udev); - if (parm.speed >= USB_SPEED_MAX) { - parm.err = USB_ERR_INVAL; + refcount = 0; + info = NULL; + + parm = &udev->scratch.xfer_setup[0].parm; + memset(parm, 0, sizeof(*parm)); + + parm->udev = udev; + parm->speed = usbd_get_speed(udev); + parm->hc_max_packet_count = 1; + + if (parm->speed >= USB_SPEED_MAX) { + parm->err = USB_ERR_INVAL; goto done; } /* setup all transfers */ @@ -926,22 +932,22 @@ usbd_transfer_setup(struct usb_device *udev, info = USB_ADD_BYTES(buf, 0); info->memory_base = buf; - info->memory_size = parm.size[0]; + info->memory_size = parm->size[0]; #if USB_HAVE_BUSDMA - info->dma_page_cache_start = USB_ADD_BYTES(buf, parm.size[4]); - info->dma_page_cache_end = USB_ADD_BYTES(buf, parm.size[5]); + info->dma_page_cache_start = USB_ADD_BYTES(buf, parm->size[4]); + info->dma_page_cache_end = USB_ADD_BYTES(buf, parm->size[5]); #endif - info->xfer_page_cache_start = USB_ADD_BYTES(buf, parm.size[5]); - info->xfer_page_cache_end = USB_ADD_BYTES(buf, parm.size[2]); + info->xfer_page_cache_start = USB_ADD_BYTES(buf, parm->size[5]); + info->xfer_page_cache_end = USB_ADD_BYTES(buf, parm->size[2]); cv_init(&info->cv_drain, "WDRAIN"); info->xfer_mtx = xfer_mtx; #if USB_HAVE_BUSDMA usb_dma_tag_setup(&info->dma_parent_tag, - parm.dma_tag_p, udev->bus->dma_parent_tag[0].tag, - xfer_mtx, &usb_bdma_done_event, 32, parm.dma_tag_max); + parm->dma_tag_p, udev->bus->dma_parent_tag[0].tag, + xfer_mtx, &usb_bdma_done_event, 32, parm->dma_tag_max); #endif info->bus = udev->bus; @@ -976,9 +982,9 @@ usbd_transfer_setup(struct usb_device *udev, } /* reset sizes */ - parm.size[0] = 0; - parm.buf = buf; - parm.size[0] += sizeof(info[0]); + parm->size[0] = 0; + parm->buf = buf; + parm->size[0] += sizeof(info[0]); for (setup = setup_start, n = 0; setup != setup_end; setup++, n++) { @@ -1010,22 +1016,22 @@ usbd_transfer_setup(struct usb_device *udev, if ((setup->usb_mode != USB_MODE_DUAL) && (setup->usb_mode != udev->flags.usb_mode)) continue; - parm.err = USB_ERR_NO_PIPE; + parm->err = USB_ERR_NO_PIPE; goto done; } /* align data properly */ - parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1)); + parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1)); /* store current setup pointer */ - parm.curr_setup = setup; + parm->curr_setup = setup; if (buf) { /* * Common initialization of the * "usb_xfer" structure. */ - xfer = USB_ADD_BYTES(buf, parm.size[0]); + xfer = USB_ADD_BYTES(buf, parm->size[0]); xfer->address = udev->address; xfer->priv_sc = priv_sc; xfer->xroot = info; @@ -1040,8 +1046,8 @@ usbd_transfer_setup(struct usb_device *udev, * before we have allocated any * memory: */ - xfer = &dummy; - memset(&dummy, 0, sizeof(dummy)); + xfer = &udev->scratch.xfer_setup[0].dummy; + memset(xfer, 0, sizeof(*xfer)); refcount++; } @@ -1051,18 +1057,18 @@ usbd_transfer_setup(struct usb_device *udev, /* set transfer stream ID */ xfer->stream_id = setup->stream_id; - parm.size[0] += sizeof(xfer[0]); - parm.methods = xfer->endpoint->methods; - parm.curr_xfer = xfer; + parm->size[0] += sizeof(xfer[0]); + parm->methods = xfer->endpoint->methods; + parm->curr_xfer = xfer; /* * Call the Host or Device controller transfer * setup routine: */ - (udev->bus->methods->xfer_setup) (&parm); + (udev->bus->methods->xfer_setup) (parm); /* check for error */ - if (parm.err) + if (parm->err) goto done; if (buf) { @@ -1077,7 +1083,7 @@ usbd_transfer_setup(struct usb_device *udev, */ USB_BUS_LOCK(info->bus); if (xfer->endpoint->refcount_alloc >= USB_EP_REF_MAX) - parm.err = USB_ERR_INVAL; + parm->err = USB_ERR_INVAL; xfer->endpoint->refcount_alloc++; @@ -1100,22 +1106,22 @@ usbd_transfer_setup(struct usb_device *udev, } /* check for error */ - if (parm.err) + if (parm->err) goto done; } - if (buf || parm.err) { + if (buf != NULL || parm->err != 0) goto done; - } - if (refcount == 0) { - /* no transfers - nothing to do ! */ + + /* if no transfers, nothing to do */ + if (refcount == 0) goto done; - } + /* align data properly */ - parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1)); + parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1)); /* store offset temporarily */ - parm.size[1] = parm.size[0]; + parm->size[1] = parm->size[0]; /* * The number of DMA tags required depends on @@ -1126,72 +1132,72 @@ usbd_transfer_setup(struct usb_device *udev, * 2) for allocating memory * 3) for fixing memory [UHCI] */ - parm.dma_tag_max += 3 * MIN(n_setup, USB_EP_MAX); + parm->dma_tag_max += 3 * MIN(n_setup, USB_EP_MAX); /* * DMA tags for QH, TD, Data and more. */ - parm.dma_tag_max += 8; + parm->dma_tag_max += 8; - parm.dma_tag_p += parm.dma_tag_max; + parm->dma_tag_p += parm->dma_tag_max; - parm.size[0] += ((uint8_t *)parm.dma_tag_p) - + parm->size[0] += ((uint8_t *)parm->dma_tag_p) - ((uint8_t *)0); /* align data properly */ - parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1)); + parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1)); /* store offset temporarily */ - parm.size[3] = parm.size[0]; + parm->size[3] = parm->size[0]; - parm.size[0] += ((uint8_t *)parm.dma_page_ptr) - + parm->size[0] += ((uint8_t *)parm->dma_page_ptr) - ((uint8_t *)0); /* align data properly */ - parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1)); + parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1)); /* store offset temporarily */ - parm.size[4] = parm.size[0]; + parm->size[4] = parm->size[0]; - parm.size[0] += ((uint8_t *)parm.dma_page_cache_ptr) - + parm->size[0] += ((uint8_t *)parm->dma_page_cache_ptr) - ((uint8_t *)0); /* store end offset temporarily */ - parm.size[5] = parm.size[0]; + parm->size[5] = parm->size[0]; - parm.size[0] += ((uint8_t *)parm.xfer_page_cache_ptr) - + parm->size[0] += ((uint8_t *)parm->xfer_page_cache_ptr) - ((uint8_t *)0); /* store end offset temporarily */ - parm.size[2] = parm.size[0]; + parm->size[2] = parm->size[0]; /* align data properly */ - parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1)); + parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1)); - parm.size[6] = parm.size[0]; + parm->size[6] = parm->size[0]; - parm.size[0] += ((uint8_t *)parm.xfer_length_ptr) - + parm->size[0] += ((uint8_t *)parm->xfer_length_ptr) - ((uint8_t *)0); /* align data properly */ - parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1)); + parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1)); /* allocate zeroed memory */ - buf = malloc(parm.size[0], M_USB, M_WAITOK | M_ZERO); + buf = malloc(parm->size[0], M_USB, M_WAITOK | M_ZERO); if (buf == NULL) { - parm.err = USB_ERR_NOMEM; + parm->err = USB_ERR_NOMEM; DPRINTFN(0, "cannot allocate memory block for " "configuration (%d bytes)\n", - parm.size[0]); + parm->size[0]); goto done; } - parm.dma_tag_p = USB_ADD_BYTES(buf, parm.size[1]); - parm.dma_page_ptr = USB_ADD_BYTES(buf, parm.size[3]); - parm.dma_page_cache_ptr = USB_ADD_BYTES(buf, parm.size[4]); - parm.xfer_page_cache_ptr = USB_ADD_BYTES(buf, parm.size[5]); - parm.xfer_length_ptr = USB_ADD_BYTES(buf, parm.size[6]); + parm->dma_tag_p = USB_ADD_BYTES(buf, parm->size[1]); + parm->dma_page_ptr = USB_ADD_BYTES(buf, parm->size[3]); + parm->dma_page_cache_ptr = USB_ADD_BYTES(buf, parm->size[4]); + parm->xfer_page_cache_ptr = USB_ADD_BYTES(buf, parm->size[5]); + parm->xfer_length_ptr = USB_ADD_BYTES(buf, parm->size[6]); } done: @@ -1207,10 +1213,17 @@ done: usbd_transfer_unsetup_sub(info, 0); } } - if (parm.err) { + + /* check if any errors happened */ + if (parm->err) usbd_transfer_unsetup(ppxfer, n_setup); - } - return (parm.err); + + error = parm->err; + + if (do_unlock) + usbd_enum_unlock(udev); + + return (error); } /*------------------------------------------------------------------------* diff --git a/sys/dev/usb/usb_util.c b/sys/dev/usb/usb_util.c index f9fec76b74a..ffd005b6179 100644 --- a/sys/dev/usb/usb_util.c +++ b/sys/dev/usb/usb_util.c @@ -75,6 +75,7 @@ device_set_usb_desc(device_t dev) struct usb_interface *iface; char *temp_p; usb_error_t err; + uint8_t do_unlock; if (dev == NULL) { /* should not happen */ @@ -96,19 +97,26 @@ device_set_usb_desc(device_t dev) err = 0; } - temp_p = (char *)udev->bus->scratch[0].data; + /* Protect scratch area */ + do_unlock = usbd_enum_lock(udev); - if (!err) { + temp_p = (char *)udev->scratch.data; + + if (err == 0) { /* try to get the interface string ! */ - err = usbd_req_get_string_any - (udev, NULL, temp_p, - sizeof(udev->bus->scratch), iface->idesc->iInterface); + err = usbd_req_get_string_any(udev, NULL, temp_p, + sizeof(udev->scratch.data), + iface->idesc->iInterface); } - if (err) { + if (err != 0) { /* use default description */ usb_devinfo(udev, temp_p, - sizeof(udev->bus->scratch)); + sizeof(udev->scratch.data)); } + + if (do_unlock) + usbd_enum_unlock(udev); + device_set_desc_copy(dev, temp_p); device_printf(dev, "<%s> on %s\n", temp_p, device_get_nameunit(udev->bus->bdev)); From 08851ea288ed577060974bf8347dad0350c29a54 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Sun, 10 Feb 2013 13:20:23 +0000 Subject: [PATCH 0092/1476] sigqueue(2): Fix typo (EEPERM -> EPERM). MFC after: 3 days --- lib/libc/sys/sigqueue.2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/libc/sys/sigqueue.2 b/lib/libc/sys/sigqueue.2 index 8069e98efa6..04e101bc344 100644 --- a/lib/libc/sys/sigqueue.2 +++ b/lib/libc/sys/sigqueue.2 @@ -117,7 +117,7 @@ or a system-wide resource limit has been exceeded. The value of the .Fa signo argument is an invalid or unsupported signal number. -.It Bq Er EEPERM +.It Bq Er EPERM The process does not have the appropriate privilege to send the signal to the receiving process. .It Bq Er ESRCH From bc62617630671fffad64dfb8bb404534a59f3476 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Sun, 10 Feb 2013 13:28:02 +0000 Subject: [PATCH 0093/1476] find: In -execdir ... {} +, only pass one file per invocation. This is inefficient but ensures that -execdir ... {} + does not mix files from different directories in one invocation; the command could not access some files. Files from the same directory should really be handled in one invocation but this is somewhat more complicated. --- usr.bin/find/function.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/usr.bin/find/function.c b/usr.bin/find/function.c index 5f8f8130432..4f2eba7433f 100644 --- a/usr.bin/find/function.c +++ b/usr.bin/find/function.c @@ -711,7 +711,13 @@ c_exec(OPTION *option, char ***argvp) for (ep = environ; *ep != NULL; ep++) argmax -= strlen(*ep) + 1 + sizeof(*ep); argmax -= 1 + sizeof(*ep); - new->e_pnummax = argmax / 16; + /* + * Ensure that -execdir ... {} + does not mix files + * from different directories in one invocation. + * Files from the same directory should be handled + * in one invocation but there is no code for it. + */ + new->e_pnummax = new->flags & F_EXECDIR ? 1 : argmax / 16; argmax -= sizeof(char *) * new->e_pnummax; if (argmax <= 0) errx(1, "no space for arguments"); From 9a71ddccd092a74958841d5b0f33f0b8e1dba1dc Mon Sep 17 00:00:00 2001 From: Gavin Atkinson Date: Sun, 10 Feb 2013 14:28:07 +0000 Subject: [PATCH 0094/1476] Correct spelling of "daemon". No .Dd bump. Noticed by: Nathan Rich MFC after: 3 days --- cddl/contrib/opensolaris/cmd/zfs/zfs.8 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cddl/contrib/opensolaris/cmd/zfs/zfs.8 b/cddl/contrib/opensolaris/cmd/zfs/zfs.8 index 7b3069dc860..ded34454260 100644 --- a/cddl/contrib/opensolaris/cmd/zfs/zfs.8 +++ b/cddl/contrib/opensolaris/cmd/zfs/zfs.8 @@ -1165,7 +1165,7 @@ When the .Sy sharenfs property is changed for a dataset, the .Xr mountd 8 -dameon is reloaded. +daemon is reloaded. .It Sy logbias Ns = Ns Cm latency | throughput Provide a hint to .Tn ZFS From d4e5fe17e680449caeb0628ee183d962fbeab0ca Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sun, 10 Feb 2013 15:55:42 +0000 Subject: [PATCH 0095/1476] Use arc4random_buf(3) instead of reimplementing it. --- sbin/geom/class/eli/geom_eli.c | 26 +++++--------------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/sbin/geom/class/eli/geom_eli.c b/sbin/geom/class/eli/geom_eli.c index f20980024bb..ed65fff2bc9 100644 --- a/sbin/geom/class/eli/geom_eli.c +++ b/sbin/geom/class/eli/geom_eli.c @@ -326,22 +326,6 @@ eli_main(struct gctl_req *req, unsigned int flags) gctl_error(req, "Unknown command: %s.", name); } -static void -arc4rand(unsigned char *buf, size_t size) -{ - uint32_t *buf4; - size_t size4; - unsigned int i; - - buf4 = (uint32_t *)buf; - size4 = size / 4; - - for (i = 0; i < size4; i++) - buf4[i] = arc4random(); - for (i *= 4; i < size; i++) - buf[i] = arc4random() % 0xff; -} - static bool eli_is_attached(const char *prov) { @@ -813,8 +797,8 @@ eli_init(struct gctl_req *req) } md.md_keys = 0x01; - arc4rand(md.md_salt, sizeof(md.md_salt)); - arc4rand(md.md_mkeys, sizeof(md.md_mkeys)); + arc4random_buf(md.md_salt, sizeof(md.md_salt)); + arc4random_buf(md.md_mkeys, sizeof(md.md_mkeys)); /* Generate user key. */ if (eli_genkey(req, &md, key, true) == NULL) { @@ -1146,7 +1130,7 @@ eli_delkey_detached(struct gctl_req *req, const char *prov) all = gctl_get_int(req, "all"); if (all) - arc4rand(md.md_mkeys, sizeof(md.md_mkeys)); + arc4random_buf(md.md_mkeys, sizeof(md.md_mkeys)); else { force = gctl_get_int(req, "force"); val = gctl_get_intmax(req, "keyno"); @@ -1170,7 +1154,7 @@ eli_delkey_detached(struct gctl_req *req, const char *prov) return; } mkeydst = md.md_mkeys + nkey * G_ELI_MKEYLEN; - arc4rand(mkeydst, G_ELI_MKEYLEN); + arc4random_buf(mkeydst, G_ELI_MKEYLEN); } eli_metadata_store(req, prov, &md); @@ -1262,7 +1246,7 @@ eli_trash_metadata(struct gctl_req *req, const char *prov, int fd, off_t offset) error = 0; do { - arc4rand(sector, size); + arc4random_buf(sector, size); if (pwrite(fd, sector, size, offset) != size) { if (error == 0) error = errno; From 2d4b50b61eb3a73a6f3fb721710ad8e6a228340f Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sun, 10 Feb 2013 15:56:20 +0000 Subject: [PATCH 0096/1476] Assert that if we are not dealing with keyfile we are dealing with passfile. --- sbin/geom/class/eli/geom_eli.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sbin/geom/class/eli/geom_eli.c b/sbin/geom/class/eli/geom_eli.c index ed65fff2bc9..14f564ed8b9 100644 --- a/sbin/geom/class/eli/geom_eli.c +++ b/sbin/geom/class/eli/geom_eli.c @@ -380,6 +380,8 @@ eli_genkey_files(struct gctl_req *req, bool new, const char *type, while ((done = read(fd, buf, sizeof(buf))) > 0) g_eli_crypto_hmac_update(ctxp, buf, done); } else /* if (strcmp(type, "passfile") == 0) */ { + assert(strcmp(type, "passfile") == 0); + while ((done = read(fd, buf, sizeof(buf) - 1)) > 0) { buf[done] = '\0'; p = strchr(buf, '\n'); From b93ca95c4f8efab32a532ed6fd52c076ed0bff5b Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sun, 10 Feb 2013 15:56:47 +0000 Subject: [PATCH 0097/1476] Fix minor memory leak. --- sbin/geom/class/eli/geom_eli.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sbin/geom/class/eli/geom_eli.c b/sbin/geom/class/eli/geom_eli.c index 14f564ed8b9..1ed72b1154a 100644 --- a/sbin/geom/class/eli/geom_eli.c +++ b/sbin/geom/class/eli/geom_eli.c @@ -1255,6 +1255,7 @@ eli_trash_metadata(struct gctl_req *req, const char *prov, int fd, off_t offset) } (void)g_flush(fd); } while (--overwrites > 0); + free(sector); if (error != 0) { gctl_error(req, "Cannot trash metadata on provider %s: %s.", prov, strerror(error)); From 1af420e0005e4bbe26b72aea86d425cb0732a31c Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Sun, 10 Feb 2013 17:10:07 +0000 Subject: [PATCH 0098/1476] Backport vendor changes in zfs(8) manual page (MFV r246389) Illumos ZFS issues: 3380 zfs man page: documentation for zfs allow is confusing References: https://www.illumos.org/issues/3380 MFC after: 2 weeks --- cddl/contrib/opensolaris/cmd/zfs/zfs.8 | 251 +++++++++++++------------ 1 file changed, 129 insertions(+), 122 deletions(-) diff --git a/cddl/contrib/opensolaris/cmd/zfs/zfs.8 b/cddl/contrib/opensolaris/cmd/zfs/zfs.8 index ded34454260..85f70db38dd 100644 --- a/cddl/contrib/opensolaris/cmd/zfs/zfs.8 +++ b/cddl/contrib/opensolaris/cmd/zfs/zfs.8 @@ -1,5 +1,5 @@ '\" te -.\" Copyright (c) 2012, Martin Matuska . +.\" Copyright (c) 2013, Martin Matuska . .\" All Rights Reserved. .\" .\" The contents of this file are subject to the terms of the @@ -19,16 +19,16 @@ .\" .\" Copyright (c) 2010, Sun Microsystems, Inc. All Rights Reserved. .\" Copyright (c) 2012 by Delphix. All rights reserved. -.\" Copyright (c) 2012 Nexenta Systems, Inc. All Rights Reserved. .\" Copyright (c) 2012, Joyent, Inc. All rights reserved. .\" Copyright (c) 2011, Pawel Jakub Dawidek .\" Copyright (c) 2012, Glen Barber .\" Copyright (c) 2012, Bryan Drewery .\" Copyright (c) 2013 by Saso Kiselkov. All rights reserved. +.\" Copyright (c) 2013 Nexenta Systems, Inc. All Rights Reserved. .\" .\" $FreeBSD$ .\" -.Dd February 8, 2012 +.Dd February 10, 2012 .Dt ZFS 8 .Os .Sh NAME @@ -40,14 +40,12 @@ .Nm .Cm create .Op Fl pu -.Op Fl o Ar property Ns = Ns Ar value -.Ar ... filesystem +.Oo Fl o Ar property Ns = Ns Ar value Oc Ns ... Ar filesystem .Nm .Cm create .Op Fl ps .Op Fl b Ar blocksize -.Op Fl o Ar property Ns = Ns Ar value -.Ar ... +.Oo Fl o Ar property Ns = Ns Ar value Oc Ns ... .Fl V .Ar size volume .Nm @@ -60,13 +58,13 @@ .Sm off .Ar snapshot .Op % Ns Ar snapname -.Op , Ns Ar ... +.Op , Ns ... .Sm on .Nm .Cm snapshot .Op Fl r -.Op Fl o Ar property Ns = Ns Ar value -.Ar ... filesystem@snapname Ns | Ns Ar volume@snapname +.Oo Fl o Ar property Ns = Ns Ar value Oc Ns ... +.Ar filesystem@snapname Ns | Ns Ar volume@snapname .Nm .Cm rollback .Op Fl rRf @@ -74,8 +72,8 @@ .Nm .Cm clone .Op Fl p -.Op Fl o Ar property Ns = Ns Ar value -.Ar ... snapshot filesystem Ns | Ns Ar volume +.Oo Fl o Ar property Ns = Ns Ar value Oc Ns ... +.Ar snapshot filesystem Ns | Ns Ar volume .Nm .Cm promote .Ar clone-filesystem @@ -103,31 +101,29 @@ .Cm list .Op Fl r Ns | Ns Fl d Ar depth .Op Fl H -.Op Fl o Ar property Ns Op , Ns Ar ... -.Op Fl t Ar type Ns Op , Ns Ar ... -.Op Fl s Ar property -.Ar ... -.Op Fl S Ar property -.Ar ... +.Op Fl o Ar property Ns Oo , Ns property Ns Oc Ns ... +.Op Fl t Ar type Ns Oo , Ns type Ns Oc Ns ... +.Oo Fl s Ar property Oc Ns ... +.Oo Fl S Ar property Oc Ns ... .Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot .Nm .Cm set .Ar property Ns = Ns Ar value -.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot +.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot Ns ... .Nm .Cm get .Op Fl r Ns | Ns Fl d Ar depth .Op Fl Hp -.Op Fl o Ar all | field Ns Op , Ns Ar ... -.Op Fl t Ar type Ns Op , Ns Ar ... -.Op Fl s Ar source Ns Op , Ns Ar ... -.Ar all | property Ns Op , Ns Ar ... -.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot +.Op Fl o Ar all | field Ns Oo , Ns Ar field Oc Ns ... +.Op Fl t Ar type Ns Oo Ns , Ar type Oc Ns ... +.Op Fl s Ar source Ns Oo Ns , Ns Ar source Oc Ns ... +.Ar all | property Ns Oo Ns , Ns Ar property Oc Ns ... +.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot Ns ... .Nm .Cm inherit .Op Fl rS .Ar property -.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot +.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot Ns ... .Nm .Cm upgrade .Op Fl v @@ -139,29 +135,25 @@ .Nm .Cm userspace .Op Fl Hinp -.Op Fl o Ar field Ns Op , Ns Ar ... -.Op Fl s Ar field -.Ar ... -.Op Fl S Ar field -.Ar ... -.Op Fl t Ar type Ns Op , Ns Ar ... +.Op Fl o Ar field Ns Oo , Ns Ar field Oc Ns ... +.Oo Fl s Ar field Oc Ns ... +.Oo Fl S Ar field Oc Ns ... +.Op Fl t Ar type Ns Oo Ns , Ns Ar type Oc Ns ... .Ar filesystem Ns | Ns Ar snapshot .Nm .Cm groupspace .Op Fl Hinp -.Op Fl o Ar field Ns Op , Ns Ar ... -.Op Fl s Ar field -.Ar ... -.Op Fl S Ar field -.Ar ... -.Op Fl t Ar type Ns Op , Ns Ar ... +.Op Fl o Ar field Ns Oo , Ns field Oc Ns ... +.Oo Fl s Ar field Oc Ns ... +.Oo Fl S Ar field Oc Ns ... +.Op Fl t Ar type Ns Oo Ns , Ns Ar type Oc Ns ... .Ar filesystem Ns | Ns Ar snapshot .Nm .Cm mount .Nm .Cm mount .Op Fl vO -.Op Fl o Ar property Ns Op , Ns Ar ... +.Op Fl o Ar property Ns Oo , Ns Ar property Oc Ns ... .Fl a | Ar filesystem .Nm .Cm unmount @@ -193,63 +185,71 @@ .Nm .Cm allow .Op Fl ldug -.Cm everyone Ns | Ns Ar user Ns | Ns Ar group Ns Op , Ns Ar ... -.Ar perm Ns | Ns Ar @setname Ns Op , Ns Ar ... +.Ar user Ns | Ns Ar group Ns Oo Ns , Ns Ar user Ns | Ns Ar group Oc Ns ... +.Ar perm Ns | Ns Ar @setname Ns +.Oo Ns , Ns Ar perm Ns | Ns Ar @setname Oc Ns ... .Ar filesystem Ns | Ns Ar volume .Nm .Cm allow .Op Fl ld -.Fl e -.Ar perm Ns | Ns Ar @setname Ns Op , Ns Ar ... +.Fl e Ns | Ns Cm everyone +.Ar perm Ns | Ns Ar @setname Ns Op Ns , Ns Ar perm Ns | Ns Ar @setname Ns +.Ns ... .Ar filesystem Ns | Ns Ar volume .Nm .Cm allow .Fl c -.Ar perm Ns | Ns Ar @setname Ns Op , Ns Ar ... +.Ar perm Ns | Ns Ar @setname Ns Op Ns , Ns Ar perm Ns | Ns Ar @setname Ns +.Ns ... .Ar filesystem Ns | Ns Ar volume .Nm .Cm allow .Fl s .Ar @setname -.Ar perm Ns | Ns Ar @setname Ns Op , Ns Ar ... +.Ar perm Ns | Ns Ar @setname Ns Op Ns , Ns Ar perm Ns | Ns Ar @setname Ns +.Ns ... .Ar filesystem Ns | Ns Ar volume .Nm .Cm unallow .Op Fl rldug -.Cm everyone Ns | Ns Ar user Ns | Ns Ar group Ns Op , Ns Ar ... -.Op Ar perm Ns | Ns Ar @setname Ns Op , Ns Ar ... +.Ar user Ns | Ns Ar group Ns Oo Ns , Ns Ar user Ns | Ns Ar group Oc Ns ... +.Oo Ar perm Ns | Ns Ar @setname Ns Op , Ns Ar perm Ns | Ns Ar @setname Ns +.Ns ... Oc .Ar filesystem Ns | Ns Ar volume .Nm .Cm unallow .Op Fl rld -.Fl e -.Op Ar perm Ns | Ns Ar @setname Ns Op , Ns Ar ... +.Fl e Ns | Ns Cm everyone +.Oo Ar perm Ns | Ns Ar @setname Ns Op , Ns Ar perm Ns | Ns Ar @setname Ns +.Ns ... Oc .Ar filesystem Ns | Ns Ar volume .Nm .Cm unallow .Op Fl r .Fl c -.Op Ar perm Ns | Ns Ar @setname Ns Op , Ns Ar ... +.Oo Ar perm Ns | Ns Ar @setname Ns Op , Ns Ar perm Ns | Ns Ar @setname Ns +.Ns ... Oc .Ar filesystem Ns | Ns Ar volume .Nm .Cm unallow .Op Fl r .Fl s .Ar @setname -.Ar perm Ns | Ns Ar @setname Ns Op , Ns Ar ... +.Oo Ar perm Ns | Ns Ar @setname Ns Op , Ns Ar perm Ns | Ns Ar @setname Ns +.Ns ... Oc .Ar filesystem Ns | Ns Ar volume .Nm .Cm hold .Op Fl r -.Ar tag snapshot ... +.Ar tag snapshot Ns ... .Nm .Cm holds .Op Fl r -.Ar snapshot ... +.Ar snapshot Ns ... .Nm .Cm release .Op Fl r -.Ar tag snapshot ... +.Ar tag snapshot Ns ... .Nm .Cm diff .Op Fl FHt @@ -1411,8 +1411,8 @@ Displays a help message. .Nm .Cm create .Op Fl pu -.Op Fl o Ar property Ns = Ns Ar value -.Ar ... filesystem +.Oo Fl o Ar property Ns = Ns Ar value Oc Ns ... +.Ar filesystem .Xc .Pp Creates a new @@ -1449,8 +1449,7 @@ options. .Cm create .Op Fl ps .Op Fl b Ar blocksize -.Op Fl o Ar property Ns = Ns Ar value -.Ar ... +.Oo Fl o Ar property Ns = Ns Ar value Oc Ns ... .Fl V .Ar size volume .Xc @@ -1550,7 +1549,7 @@ behavior for mounted file systems in use. .Sm off .Ar snapshot .Op % Ns Ar snapname -.Op , Ns Ar ... +.Op , Ns ... .Sm on .Xc .Pp @@ -1611,8 +1610,7 @@ behavior for mounted file systems in use. .Nm .Cm snapshot .Op Fl r -.Op Fl o Ar property Ns = Ns Ar value -.Ar ... +.Oo Fl o Ar property Ns = Ns Ar value Oc Ns ... .Ar filesystem@snapname Ns | Ns volume@snapname .Xc .Pp @@ -1659,8 +1657,8 @@ option to force an unmount of any clone file systems that are to be destroyed. .Nm .Cm clone .Op Fl p -.Op Fl o Ar property Ns = Ns Ar value -.Ar ... snapshot filesystem Ns | Ns Ar volume +.Oo Fl o Ar property Ns = Ns Ar value Oc Ns ... +.Ar snapshot filesystem Ns | Ns Ar volume .Xc .Pp Creates a clone of the given snapshot. See the @@ -1763,13 +1761,11 @@ only dataset that can be renamed recursively. .Cm list .Op Fl r Ns | Ns Fl d Ar depth .Op Fl H -.Op Fl o Ar property Ns Op , Ns Ar ... -.Op Fl t Ar type Ns Op , Ns Ar ... -.Op Fl s Ar property -.Ar ... -.Op Fl S Ar property -.Ar ... -.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot +.Op Fl o Ar property Ns Oo , Ns Ar property Oc Ns ... +.Op Fl t Ar type Ns Oo , Ns Ar type Oc Ns ... +.Oo Fl s Ar property Oc Ns ... +.Oo Fl S Ar property Oc Ns ... +.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot Ns ... .Xc .Pp Lists the property information for the given datasets in tabular form. If @@ -1795,7 +1791,7 @@ will display only the dataset and its direct children. .It Fl H Used for scripting mode. Do not print headers and separate fields by a single tab instead of arbitrary white space. -.It Fl o Ar property Ns Op , Ns Ar ... +.It Fl o Ar property Ns Oo , Ns Ar property Oc Ns ... A comma-separated list of properties to display. The property must be: .Bl -bullet -offset 2n .It @@ -1819,7 +1815,7 @@ shortcut for specifying .Sy filesystem,volume syntax. .El -.It Fl t Ar type Ns Op , Ns Ar ... +.It Fl t Ar type Ns Oo , Ns Ar type Oc Ns ... A comma-separated list of types to display, where .Ar type is one of @@ -1882,11 +1878,11 @@ section. .Cm get .Op Fl r Ns | Ns Fl d Ar depth .Op Fl Hp -.Op Fl o Ar all | field Ns Op , Ns Ar ... -.Op Fl t Ar type Ns Op , Ns Ar ... -.Op Fl s Ar source Ns Op , Ns Ar ... -.Ar all | property Ns Op , Ns Ar ... -.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot +.Op Fl o Ar all | field Ns Oo , Ns Ar field Oc Ns ... +.Op Fl t Ar type Ns Oo , Ns Ar type Oc Ns ... +.Op Fl s Ar source Ns Oo , Ns Ar source Oc Ns ... +.Ar all | property Ns Oo , Ns Ar property Oc Ns ... +.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot Ns ... .Xc .Pp Displays properties for the given datasets. If no datasets are specified, then @@ -1936,7 +1932,7 @@ omitted, and fields are explicitly separated by a single tab instead of an arbitrary amount of space. .It Fl p Display numbers in parseable (exact) values. -.It Fl o Cm all | Ar field Ns Op , Ns Ar ... +.It Fl o Cm all | Ar field Ns Oo , Ns Ar field Oc Ns ... A comma-separated list of columns to display. Supported values are .Sy name,property,value,received,source . Default values are @@ -1944,7 +1940,7 @@ Default values are The keyword .Cm all specifies all columns. -.It Fl t Ar type Ns Op , Ns Ar ... +.It Fl t Ar type Ns Oo , Ns Ar type Oc Ns ... A comma-separated list of types to display, where .Ar type is one of @@ -1952,7 +1948,7 @@ is one of For example, specifying .Fl t Cm snapshot displays only snapshots. -.It Fl s Ar source Ns Op , Ns Ar ... +.It Fl s Ar source Ns Oo , Ns Ar source Oc Ns ... A comma-separated list of sources to display. Those properties coming from a source other than those in this list are ignored. Each source must be one of the following: @@ -1964,7 +1960,7 @@ The default value is all sources. .Cm inherit .Op Fl rS .Ar property -.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot +.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot Ns ... .Xc .Pp Clears the specified property, causing it to be inherited from an ancestor. If @@ -2039,12 +2035,10 @@ Upgrade the specified file system. .Nm .Cm userspace .Op Fl Hinp -.Op Fl o Ar field Ns Op , Ns Ar ... -.Op Fl s Ar field -.Ar ... -.Op Fl S Ar field -.Ar ... -.Op Fl t Ar type Ns Op , Ns Ar ... +.Op Fl o Ar field Ns Oo , Ns Ar field Oc Ns ... +.Oo Fl s Ar field Oc Ns ... +.Oo Fl S Ar field Oc Ns ... +.Op Fl t Ar type Ns Oo , Ns Ar type Oc Ns ... .Ar filesystem Ns | Ns Ar snapshot .Xc .Pp @@ -2061,7 +2055,7 @@ Print numeric ID instead of user/group name. Do not print headers, use tab-delimited output. .It Fl p Use exact (parsable) numeric output. -.It Fl o Ar field Ns Op , Ns Ar ... +.It Fl o Ar field Ns Oo , Ns Ar field Oc Ns ... Display only the specified fields from the following set: .Sy type,name,used,quota . The default is to display all fields. @@ -2076,7 +2070,7 @@ another. The default is .It Fl S Ar field Sort by this field in reverse order. See .Fl s . -.It Fl t Ar type Ns Op , Ns Ar ... +.It Fl t Ar type Ns Oo , Ns Ar type Oc Ns ... Print only the specified types from the following set: .Sy all,posixuser,smbuser,posixgroup,smbgroup . .Pp @@ -2092,12 +2086,10 @@ Translate SID to POSIX ID. This flag currently has no effect on .Nm .Cm groupspace .Op Fl Hinp -.Op Fl o Ar field Ns Op , Ns Ar ... -.Op Fl s Ar field -.Ar ... -.Op Fl S Ar field -.Ar ... -.Op Fl t Ar type Ns Op , Ns Ar ... +.Op Fl o Ar field Ns Oo , Ns Ar field Oc Ns ... +.Oo Fl s Ar field Oc Ns ... +.Oo Fl S Ar field Oc Ns ... +.Op Fl t Ar type Ns Oo , Ns Ar type Oc Ns ... .Ar filesystem Ns | Ns Ar snapshot .Xc .Pp @@ -2121,7 +2113,7 @@ file systems currently mounted. .Nm .Cm mount .Op Fl vO -.Op Fl o Ar property Ns Op , Ns Ar ... +.Op Fl o Ar property Ns Oo , Ns Ar property Oc Ns ... .Fl a | Ar filesystem .Xc .Pp @@ -2134,7 +2126,7 @@ Report mount progress. .It Fl O Perform an overlay mount. Overlay mounts are not supported on .Fx . -.It Fl o Ar property Ns Op , Ns Ar ... +.It Fl o Ar property Ns Oo , Ns Ar property Oc Ns ... An optional, comma-separated list of mount options to use temporarily for the duration of the mount. See the .Qq Sx Temporary Mount Point Properties @@ -2453,16 +2445,18 @@ for more information. .Nm .Cm allow .Op Fl ldug -.Cm everyone Ns | Ns Ar user Ns | Ns Ar group Ns Op , Ns Ar ... -.Ar perm Ns | Ns Ar @setname Ns Op , Ns Ar ... +.Ar user Ns | Ns Ar group Ns Oo Ns , Ns Ar user Ns | Ns Ar group Oc Ns ... +.Ar perm Ns | Ns Ar @setname Ns +.Oo Ns , Ns Ar perm Ns | Ns Ar @setname Oc Ns ... .Ar filesystem Ns | Ns Ar volume .Xc .It Xo .Nm .Cm allow .Op Fl ld -.Fl e -.Ar perm Ns | Ns Ar @setname Ns Op , Ns Ar ... +.Fl e Ns | Ns Cm everyone +.Ar perm Ns | Ns Ar @setname Ns Op Ns , Ns Ar perm Ns | Ns Ar @setname Ns +.Ns ... .Ar filesystem Ns | Ns Ar volume .Xc .Pp @@ -2472,26 +2466,31 @@ administration permission for the file systems to non-privileged users. .Bl -tag -width indent .It Xo .Op Fl ug -.Cm everyone Ns | Ns Ar user Ns | Ns Ar group Ns Op , Ns Ar ... +.Ar user Ns | Ns Ar group Ns Oo , Ar user Ns | Ns Ar group Oc Ns ... .Xc Specifies to whom the permissions are delegated. Multiple entities can be specified as a comma-separated list. If neither of the .Fl ug options are specified, then the argument is interpreted preferentially as the -keyword "everyone", then as a user name, and lastly as a group name. To specify -a user or group named "everyone", use the +keyword +.Cm everyone , +then as a user name, and lastly as a group name. To specify +a user or group named +.Qq everyone , +use the .Fl u or .Fl g options. To specify a group with the same name as a user, use the .Fl g option. +.It Op Fl e Ns | Ns Cm everyone +Specifies that the permissions be delegated to +.Qq everyone . .It Xo -.Op Fl e -.Ar perm Ns | Ns Ar @setname Ns Op , Ns Ar ... +.Ar perm Ns | Ns Ar @setname Ns Oo , Ns Ar perm Ns | Ns Ar @setname Oc Ns ... .Xc -Specifies that the permissions be delegated to "everyone". -Multiple permissions +The permissions to delegate. Multiple permissions may be specified as a comma-separated list. Permission names are the same as .Tn ZFS subcommand and property names. See the property list below. Property set names, @@ -2598,7 +2597,8 @@ protocol .Nm .Cm allow .Fl c -.Ar perm Ns | Ns Ar @setname Ns Op , Ns Ar ... +.Ar perm Ns | Ns Ar @setname Ns Op Ns , Ns Ar perm Ns | Ns Ar @setname Ns +.Ns ... .Ar filesystem Ns | Ns Ar volume .Xc .Pp @@ -2609,7 +2609,8 @@ creator of any newly-created descendent file system. .Cm allow .Fl s .Ar @setname -.Ar perm Ns | Ns Ar @setname Ns Op , Ns Ar ... +.Ar perm Ns | Ns Ar @setname Ns Op Ns , Ns Ar perm Ns | Ns Ar @setname Ns +.Ns ... .Ar filesystem Ns | Ns Ar volume .Xc .Pp @@ -2625,16 +2626,18 @@ and can be no more than 64 characters long. .Nm .Cm unallow .Op Fl rldug -.Cm everyone Ns | Ns Ar user Ns | Ns Ar group Ns Op , Ns Ar ... -.Op Ar perm Ns | Ns Ar @setname Ns Op , Ns Ar ... +.Ar user Ns | Ns Ar group Ns Oo Ns , Ns Ar user Ns | Ns Ar group Oc Ns ... +.Oo Ar perm Ns | Ns Ar @setname Ns Op , Ns Ar perm Ns | Ns Ar @setname Ns +.Ns ... Oc .Ar filesystem Ns | Ns Ar volume .Xc .It Xo .Nm .Cm unallow .Op Fl rld -.Fl e -.Op Ar perm Ns | Ns Ar @setname Ns Op , Ns Ar ... +.Fl e Ns | Ns Cm everyone +.Oo Ar perm Ns | Ns Ar @setname Ns Op , Ns Ar perm Ns | Ns Ar @setname Ns +.Ns ... Oc .Ar filesystem Ns | Ns Ar volume .Xc .It Xo @@ -2642,7 +2645,8 @@ and can be no more than 64 characters long. .Cm unallow .Op Fl r .Fl c -.Op Ar perm Ns | Ns Ar @setname Ns Op , Ns Ar ... +.Oo Ar perm Ns | Ns Ar @setname Ns Op , Ns Ar perm Ns | Ns Ar @setname Ns +.Ns ... Oc .Ar filesystem Ns | Ns Ar volume .Xc .Pp @@ -2651,10 +2655,12 @@ Removes permissions that were granted with the command. No permissions are explicitly denied, so other permissions granted are still in effect. For example, if the permission is granted by an ancestor. If no permissions are specified, then all permissions for the specified -.Ar user , group , No or Ar everyone -are removed. Specifying "everyone" (or using the -.Fl e -option) only removes the permissions that were granted to "everyone", +.Ar user , group , No or everyone +are removed. Specifying +.Cm everyone +.Po or using the Fl e +option +.Pc only removes the permissions that were granted to everyone , not all permissions for every user and group. See the .Qq Nm Cm allow command for a description of the @@ -2670,7 +2676,8 @@ Recursively remove the permissions from this file system and all descendents. .Op Fl r .Fl s .Ar @setname -.Ar perm Ns | Ns Ar @setname Ns Op , Ns Ar ... +.Oo Ar perm Ns | Ns Ar @setname Ns Op , Ns Ar perm Ns | Ns Ar @setname Ns +.Ns ... Oc .Ar filesystem Ns | Ns Ar volume .Xc .Pp @@ -2680,7 +2687,7 @@ then all permissions are removed, thus removing the set entirely. .Nm .Cm hold .Op Fl r -.Ar tag snapshot ... +.Ar tag snapshot Ns ... .Xc .Pp Adds a single reference, named with the @@ -2701,7 +2708,7 @@ snapshots of all descendent file systems. .Nm .Cm holds .Op Fl r -.Ar snapshot ... +.Ar snapshot Ns ... .Xc .Pp Lists all existing user references for the given snapshot or snapshots. @@ -2714,7 +2721,7 @@ listing the holds on the named snapshot. .Nm .Cm release .Op Fl r -.Ar tag snapshot ... +.Ar tag snapshot Ns ... .Xc .Pp Removes a single reference, named with the From 4bd1e0bbf851bf2b400583a7e7310e0581f2d46f Mon Sep 17 00:00:00 2001 From: Colin Percival Date: Sun, 10 Feb 2013 17:58:44 +0000 Subject: [PATCH 0099/1476] Don't try to suppress the inclusion of the build date in named's version string by undefining __DATE__, since (unlike gcc) clang doesn't allow us to do that. Instead, define NO_VERSION_DATE, which was helpfully added to the named source code for exactly this purpose. --- usr.sbin/named/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr.sbin/named/Makefile b/usr.sbin/named/Makefile index 1200c7e2600..4743a7b5f3c 100644 --- a/usr.sbin/named/Makefile +++ b/usr.sbin/named/Makefile @@ -48,7 +48,7 @@ CFLAGS+= -I${SRCDIR}/unix/include -I${SRCDIR}/include -I${LIB_BIND_DIR} CFLAGS+= -I${BIND_DIR}/lib/isc/${ISC_ATOMIC_ARCH}/include # Remove the date stamp to make it more obvious when real changes happen -CFLAGS+= -U__DATE__ +CFLAGS+= -DNO_VERSION_DATE WARNS?= 0 From 17ef6d3ab8a4b005fdcc7ab9f4f6195a2056d50e Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Sun, 10 Feb 2013 18:56:37 +0000 Subject: [PATCH 0100/1476] find: Run when cwd cannot be opened, except with -execdir or -delete. fts(3) can run (albeit more slowly and imposing the {PATH_MAX} limit) when the current directory cannot be opened. Therefore, do not make a failure to open the current directory (for returning to it later in -exec) fatal. If -execdir or -delete are used, the expectation is that fts(3) will use chdir to avoid race conditions (except for -execdir with -L). Do not break this expectation any more than it already is by still failing if the current directory cannot be opened. --- usr.bin/find/function.c | 16 +++++++++++++++- usr.bin/find/main.c | 2 +- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/usr.bin/find/function.c b/usr.bin/find/function.c index 4f2eba7433f..cad6eb15fc8 100644 --- a/usr.bin/find/function.c +++ b/usr.bin/find/function.c @@ -472,6 +472,14 @@ c_delete(OPTION *option, char ***argvp __unused) isoutput = 1; /* possible output */ isdepth = 1; /* -depth implied */ + /* + * Try to avoid the confusing error message about relative paths + * being potentially not safe. + */ + if (ftsoptions & FTS_NOCHDIR) + errx(1, "%s: forbidden when the current directory cannot be opened", + "-delete"); + return palloc(option); } @@ -644,7 +652,8 @@ doexec: if ((plan->flags & F_NEEDOK) && !queryuser(plan->e_argv)) /* NOTREACHED */ case 0: /* change dir back from where we started */ - if (!(plan->flags & F_EXECDIR) && fchdir(dotfd)) { + if (!(plan->flags & F_EXECDIR) && + !(ftsoptions & FTS_NOCHDIR) && fchdir(dotfd)) { warn("chdir"); _exit(1); } @@ -677,6 +686,11 @@ c_exec(OPTION *option, char ***argvp) int cnt, i; char **argv, **ap, **ep, *p; + /* This would defeat -execdir's intended security. */ + if (option->flags & F_EXECDIR && ftsoptions & FTS_NOCHDIR) + errx(1, "%s: forbidden when the current directory cannot be opened", + "-execdir"); + /* XXX - was in c_execdir, but seems unnecessary!? ftsoptions &= ~FTS_NOSTAT; */ diff --git a/usr.bin/find/main.c b/usr.bin/find/main.c index 628441332ab..3a0377fa13c 100644 --- a/usr.bin/find/main.c +++ b/usr.bin/find/main.c @@ -152,7 +152,7 @@ main(int argc, char *argv[]) *p = NULL; if ((dotfd = open(".", O_RDONLY | O_CLOEXEC, 0)) < 0) - err(1, "."); + ftsoptions |= FTS_NOCHDIR; exit(find_execute(find_formplan(argv), start)); } From 4224e03ae733617edef246a2597b31c54840560a Mon Sep 17 00:00:00 2001 From: Michael Tuexen Date: Sun, 10 Feb 2013 19:21:17 +0000 Subject: [PATCH 0101/1476] Improve code style. No functional change. MFC after: 3 days --- lib/libc/net/sctp_sys_calls.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/libc/net/sctp_sys_calls.c b/lib/libc/net/sctp_sys_calls.c index beedf94d065..f5fc5bc7d0a 100644 --- a/lib/libc/net/sctp_sys_calls.c +++ b/lib/libc/net/sctp_sys_calls.c @@ -583,36 +583,36 @@ sctp_sendmsg(int s, if ((tolen > 0) && ((to == NULL) || (tolen < sizeof(struct sockaddr)))) { errno = EINVAL; - return -1; + return (-1); } if (to && (tolen > 0)) { if (to->sa_family == AF_INET) { if (tolen != sizeof(struct sockaddr_in)) { errno = EINVAL; - return -1; + return (-1); } if ((to->sa_len > 0) && (to->sa_len != sizeof(struct sockaddr_in))) { errno = EINVAL; - return -1; + return (-1); } memcpy(&addr, to, sizeof(struct sockaddr_in)); addr.in.sin_len = sizeof(struct sockaddr_in); } else if (to->sa_family == AF_INET6) { if (tolen != sizeof(struct sockaddr_in6)) { errno = EINVAL; - return -1; + return (-1); } if ((to->sa_len > 0) && (to->sa_len != sizeof(struct sockaddr_in6))) { errno = EINVAL; - return -1; + return (-1); } memcpy(&addr, to, sizeof(struct sockaddr_in6)); addr.in6.sin6_len = sizeof(struct sockaddr_in6); } else { errno = EAFNOSUPPORT; - return -1; + return (-1); } who = (struct sockaddr *)&addr; } @@ -836,7 +836,7 @@ sctp_sendmsgx(int sd, sinfo.sinfo_ssn = stream_no; sinfo.sinfo_timetolive = timetolive; sinfo.sinfo_context = context; - return sctp_sendx(sd, msg, len, addrs, addrcnt, &sinfo, 0); + return (sctp_sendx(sd, msg, len, addrs, addrcnt, &sinfo, 0)); } ssize_t From c6e31e81e07d8719a5575e20b2b13ac4b56cd647 Mon Sep 17 00:00:00 2001 From: "Andrey V. Elsukov" Date: Sun, 10 Feb 2013 19:27:17 +0000 Subject: [PATCH 0102/1476] Add bootcamp support to the loader. Tested by: dchagin MFC after: 1 week --- sys/boot/common/part.c | 10 +++++++--- sys/sys/diskmbr.h | 1 + 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/sys/boot/common/part.c b/sys/boot/common/part.c index 31ea82ae083..2b3a16fbd85 100644 --- a/sys/boot/common/part.c +++ b/sys/boot/common/part.c @@ -645,9 +645,13 @@ ptable_open(void *dev, off_t sectors, uint16_t sectorsize, /* Do we have some invalid values? */ if (i != NDOSPART || (table->type == PTABLE_GPT && count > 1)) { - table->type = PTABLE_NONE; - DEBUG("invalid values detected, ignore partition table"); - goto out; + if (dp[1].dp_typ != DOSPTYP_HFS) { + table->type = PTABLE_NONE; + DEBUG("invalid values detected, ignore " + "partition table"); + goto out; + } + DEBUG("Bootcamp detected"); } #ifdef LOADER_GPT_SUPPORT if (table->type == PTABLE_GPT) { diff --git a/sys/sys/diskmbr.h b/sys/sys/diskmbr.h index 94fc4754ac5..747f70b14ba 100644 --- a/sys/sys/diskmbr.h +++ b/sys/sys/diskmbr.h @@ -51,6 +51,7 @@ #define DOSPTYP_PPCBOOT 0x41 /* PReP/CHRP boot partition */ #define DOSPTYP_LDM 0x42 /* Win2k dynamic extended partition */ #define DOSPTYP_386BSD 0xa5 /* 386BSD partition type */ +#define DOSPTYP_HFS 0xaf /* HFS/HFS+ partition type */ #define DOSPTYP_LINSWP 0x82 /* Linux swap partition */ #define DOSPTYP_LINUX 0x83 /* Linux partition */ #define DOSPTYP_LINLVM 0x8e /* Linux LVM partition */ From f37ba7263208005ad42532cf6f4ef20a50a4a99c Mon Sep 17 00:00:00 2001 From: Neel Natu Date: Sun, 10 Feb 2013 19:35:40 +0000 Subject: [PATCH 0103/1476] Use the entire 64 bits of 'bar.pbi_length' when printing the bar size. This allows bar sizes greater than or equal to 4GB to be displayed correctly. --- usr.sbin/pciconf/pciconf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr.sbin/pciconf/pciconf.c b/usr.sbin/pciconf/pciconf.c index 52ad09a7096..58ffddd9cfa 100644 --- a/usr.sbin/pciconf/pciconf.c +++ b/usr.sbin/pciconf/pciconf.c @@ -290,7 +290,7 @@ list_bars(int fd, struct pci_conf *p) } printf(" bar [%02x] = type %s, range %2d, base %#jx, ", PCIR_BAR(i), type, range, (uintmax_t)base); - printf("size %2d, %s\n", (int)bar.pbi_length, + printf("size %ju, %s\n", (uintmax_t)bar.pbi_length, bar.pbi_enabled ? "enabled" : "disabled"); } } From f1a1c55d517b91643ef2fc066361b6783094ca93 Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Sun, 10 Feb 2013 19:41:19 +0000 Subject: [PATCH 0104/1476] Update vendor-sys/illumos/dist to illumos-gate version 13949:4f6a155f70fe Illumos ZFS issues: 3512 rounding discrepancy in sa_find_sizes() 3513 mismatch between SA header size and layout --- uts/common/fs/zfs/sa.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/uts/common/fs/zfs/sa.c b/uts/common/fs/zfs/sa.c index 06607d784e4..7cd4ab00f7c 100644 --- a/uts/common/fs/zfs/sa.c +++ b/uts/common/fs/zfs/sa.c @@ -553,6 +553,7 @@ sa_find_sizes(sa_os_t *sa, sa_bulk_attr_t *attr_desc, int attr_count, { int var_size = 0; int i; + int j = -1; int full_space; int hdrsize; boolean_t done = B_FALSE; @@ -574,10 +575,12 @@ sa_find_sizes(sa_os_t *sa, sa_bulk_attr_t *attr_desc, int attr_count, sizeof (sa_hdr_phys_t); full_space = (buftype == SA_BONUS) ? DN_MAX_BONUSLEN : db->db_size; + ASSERT(IS_P2ALIGNED(full_space, 8)); for (i = 0; i != attr_count; i++) { boolean_t is_var_sz; + *total = P2ROUNDUP(*total, 8); *total += attr_desc[i].sa_length; if (done) goto next; @@ -590,7 +593,14 @@ sa_find_sizes(sa_os_t *sa, sa_bulk_attr_t *attr_desc, int attr_count, if (is_var_sz && var_size > 1) { if (P2ROUNDUP(hdrsize + sizeof (uint16_t), 8) + *total < full_space) { + /* + * Account for header space used by array of + * optional sizes of variable-length attributes. + * Record the index in case this increase needs + * to be reversed due to spill-over. + */ hdrsize += sizeof (uint16_t); + j = i; } else { done = B_TRUE; *index = i; @@ -619,6 +629,14 @@ next: *will_spill = B_TRUE; } + /* + * j holds the index of the last variable-sized attribute for + * which hdrsize was increased. Reverse the increase if that + * attribute will be relocated to the spill block. + */ + if (*will_spill && j == *index) + hdrsize -= sizeof (uint16_t); + hdrsize = P2ROUNDUP(hdrsize, 8); return (hdrsize); } @@ -709,12 +727,15 @@ sa_build_layouts(sa_handle_t *hdl, sa_bulk_attr_t *attr_desc, int attr_count, for (i = 0, len_idx = 0, hash = -1ULL; i != attr_count; i++) { uint16_t length; + ASSERT(IS_P2ALIGNED(data_start, 8)); + ASSERT(IS_P2ALIGNED(buf_space, 8)); attrs[i] = attr_desc[i].sa_attr; length = SA_REGISTERED_LEN(sa, attrs[i]); if (length == 0) length = attr_desc[i].sa_length; if (buf_space < length) { /* switch to spill buffer */ + VERIFY(spilling); VERIFY(bonustype == DMU_OT_SA); if (buftype == SA_BONUS && !sa->sa_force_spill) { sa_find_layout(hdl->sa_os, hash, attrs_start, From a9d1b2999545765bd24d17ee614eec4f739d19ba Mon Sep 17 00:00:00 2001 From: "Pedro F. Giffuni" Date: Sun, 10 Feb 2013 19:49:37 +0000 Subject: [PATCH 0105/1476] ext2fs: Use prototype declarations for function definitions Submitted by: Christoph Mallon MFC after: 2 weeks --- sys/fs/ext2fs/ext2_alloc.c | 43 ++------ sys/fs/ext2fs/ext2_balloc.c | 9 +- sys/fs/ext2fs/ext2_bmap.c | 23 +--- sys/fs/ext2fs/ext2_inode.c | 32 ++---- sys/fs/ext2fs/ext2_inode_cnv.c | 11 +- sys/fs/ext2fs/ext2_lookup.c | 47 ++------ sys/fs/ext2fs/ext2_subr.c | 10 +- sys/fs/ext2fs/ext2_vnops.c | 194 +++++---------------------------- 8 files changed, 65 insertions(+), 304 deletions(-) diff --git a/sys/fs/ext2fs/ext2_alloc.c b/sys/fs/ext2fs/ext2_alloc.c index cafd32df28a..13cb391553f 100644 --- a/sys/fs/ext2fs/ext2_alloc.c +++ b/sys/fs/ext2fs/ext2_alloc.c @@ -80,12 +80,8 @@ static daddr_t ext2_mapsearch(struct m_ext2fs *, char *, daddr_t); * available block is located. */ int -ext2_alloc(ip, lbn, bpref, size, cred, bnp) - struct inode *ip; - int32_t lbn, bpref; - int size; - struct ucred *cred; - int32_t *bnp; +ext2_alloc(struct inode *ip, int32_t lbn, int32_t bpref, int size, + struct ucred *cred, int32_t *bnp) { struct m_ext2fs *fs; struct ext2mount *ump; @@ -159,11 +155,7 @@ static int doreallocblks = 0; SYSCTL_INT(_vfs_ext2fs, OID_AUTO, doreallocblks, CTLFLAG_RW, &doreallocblks, 0, ""); int -ext2_reallocblks(ap) - struct vop_reallocblks_args /* { - struct vnode *a_vp; - struct cluster_save *a_buflist; - } */ *ap; +ext2_reallocblks(struct vop_reallocblks_args *ap) { struct m_ext2fs *fs; struct inode *ip; @@ -350,11 +342,7 @@ fail: * */ int -ext2_valloc(pvp, mode, cred, vpp) - struct vnode *pvp; - int mode; - struct ucred *cred; - struct vnode **vpp; +ext2_valloc(struct vnode *pvp, int mode, struct ucred *cred, struct vnode **vpp) { struct timespec ts; struct inode *pip; @@ -562,12 +550,8 @@ ext2_dirpref(struct inode *pip) * that will hold the pointer */ int32_t -ext2_blkpref(ip, lbn, indx, bap, blocknr) - struct inode *ip; - int32_t lbn; - int indx; - int32_t *bap; - int32_t blocknr; +ext2_blkpref(struct inode *ip, int32_t lbn, int indx, int32_t *bap, + int32_t blocknr) { int tmp; mtx_assert(EXT2_MTX(ip->i_ump), MA_OWNED); @@ -972,10 +956,7 @@ gotit: * */ void -ext2_blkfree(ip, bno, size) - struct inode *ip; - int32_t bno; - long size; +ext2_blkfree(struct inode *ip, int32_t bno, long size) { struct m_ext2fs *fs; struct buf *bp; @@ -1021,10 +1002,7 @@ ext2_blkfree(ip, bno, size) * */ int -ext2_vfree(pvp, ino, mode) - struct vnode *pvp; - ino_t ino; - int mode; +ext2_vfree(struct vnode *pvp, ino_t ino, int mode) { struct m_ext2fs *fs; struct inode *pip; @@ -1113,10 +1091,7 @@ ext2_mapsearch(struct m_ext2fs *fs, char *bbp, daddr_t bpref) * fs: error message */ static void -ext2_fserr(fs, uid, cp) - struct m_ext2fs *fs; - uid_t uid; - char *cp; +ext2_fserr(struct m_ext2fs *fs, uid_t uid, char *cp) { log(LOG_ERR, "uid %u on %s: %s\n", uid, fs->e2fs_fsmnt, cp); diff --git a/sys/fs/ext2fs/ext2_balloc.c b/sys/fs/ext2fs/ext2_balloc.c index 1861f692890..1c0cc0e4bbe 100644 --- a/sys/fs/ext2fs/ext2_balloc.c +++ b/sys/fs/ext2fs/ext2_balloc.c @@ -55,13 +55,8 @@ * the inode and the logical block number in a file. */ int -ext2_balloc(ip, lbn, size, cred, bpp, flags) - struct inode *ip; - int32_t lbn; - int size; - struct ucred *cred; - struct buf **bpp; - int flags; +ext2_balloc(struct inode *ip, int32_t lbn, int size, struct ucred *cred, + struct buf **bpp, int flags) { struct m_ext2fs *fs; struct ext2mount *ump; diff --git a/sys/fs/ext2fs/ext2_bmap.c b/sys/fs/ext2fs/ext2_bmap.c index c2f6e0ee4eb..ba561c61266 100644 --- a/sys/fs/ext2fs/ext2_bmap.c +++ b/sys/fs/ext2fs/ext2_bmap.c @@ -56,15 +56,7 @@ * number to index into the array of block pointers described by the dinode. */ int -ext2_bmap(ap) - struct vop_bmap_args /* { - struct vnode *a_vp; - daddr_t a_bn; - struct bufobj **a_bop; - daddr_t *a_bnp; - int *a_runp; - int *a_runb; - } */ *ap; +ext2_bmap(struct vop_bmap_args *ap) { int32_t blkno; int error; @@ -99,12 +91,7 @@ ext2_bmap(ap) */ int -ext2_bmaparray(vp, bn, bnp, runp, runb) - struct vnode *vp; - int32_t bn; - int32_t *bnp; - int *runp; - int *runb; +ext2_bmaparray(struct vnode *vp, int32_t bn, int32_t *bnp, int *runp, int *runb) { struct inode *ip; struct buf *bp; @@ -252,11 +239,7 @@ ext2_bmaparray(vp, bn, bnp, runp, runb) * once with the offset into the page itself. */ int -ext2_getlbns(vp, bn, ap, nump) - struct vnode *vp; - int32_t bn; - struct indir *ap; - int *nump; +ext2_getlbns(struct vnode *vp, int32_t bn, struct indir *ap, int *nump) { long blockcnt, metalbn, realbn; struct ext2mount *ump; diff --git a/sys/fs/ext2fs/ext2_inode.c b/sys/fs/ext2fs/ext2_inode.c index fe9b50da18a..ab09588d7be 100644 --- a/sys/fs/ext2fs/ext2_inode.c +++ b/sys/fs/ext2fs/ext2_inode.c @@ -66,9 +66,7 @@ static int ext2_indirtrunc(struct inode *, int32_t, int32_t, int32_t, int, * set, then wait for the write to complete. */ int -ext2_update(vp, waitfor) - struct vnode *vp; - int waitfor; +ext2_update(struct vnode *vp, int waitfor) { struct m_ext2fs *fs; struct buf *bp; @@ -108,12 +106,8 @@ ext2_update(vp, waitfor) * disk blocks. */ int -ext2_truncate(vp, length, flags, cred, td) - struct vnode *vp; - off_t length; - int flags; - struct ucred *cred; - struct thread *td; +ext2_truncate(struct vnode *vp, off_t length, int flags, struct ucred *cred, + struct thread *td) { struct vnode *ovp = vp; int32_t lastblock; @@ -361,12 +355,8 @@ done: */ static int -ext2_indirtrunc(ip, lbn, dbn, lastbn, level, countp) - struct inode *ip; - int32_t lbn, lastbn; - int32_t dbn; - int level; - long *countp; +ext2_indirtrunc(struct inode *ip, int32_t lbn, int32_t dbn, int32_t lastbn, + int level, long *countp) { struct buf *bp; struct m_ext2fs *fs = ip->i_e2fs; @@ -470,11 +460,7 @@ ext2_indirtrunc(ip, lbn, dbn, lastbn, level, countp) * discard preallocated blocks */ int -ext2_inactive(ap) - struct vop_inactive_args /* { - struct vnode *a_vp; - struct thread *a_td; - } */ *ap; +ext2_inactive(struct vop_inactive_args *ap) { struct vnode *vp = ap->a_vp; struct inode *ip = VTOI(vp); @@ -510,11 +496,7 @@ out: * Reclaim an inode so that it can be used for other purposes. */ int -ext2_reclaim(ap) - struct vop_reclaim_args /* { - struct vnode *a_vp; - struct thread *a_td; - } */ *ap; +ext2_reclaim(struct vop_reclaim_args *ap) { struct inode *ip; struct vnode *vp = ap->a_vp; diff --git a/sys/fs/ext2fs/ext2_inode_cnv.c b/sys/fs/ext2fs/ext2_inode_cnv.c index 0fa30750083..c63c4f832cc 100644 --- a/sys/fs/ext2fs/ext2_inode_cnv.c +++ b/sys/fs/ext2fs/ext2_inode_cnv.c @@ -41,8 +41,7 @@ #define NSEC_TO_XTIME(t) (le32toh(t << 2) & EXT3_NSEC_MASK) void -ext2_print_inode( in ) - struct inode *in; +ext2_print_inode(struct inode *in) { int i; @@ -68,9 +67,7 @@ ext2_print_inode( in ) * raw ext2 inode to inode */ void -ext2_ei2i(ei, ip) - struct ext2fs_dinode *ei; - struct inode *ip; +ext2_ei2i(struct ext2fs_dinode *ei, struct inode *ip) { int i; @@ -113,9 +110,7 @@ ext2_ei2i(ei, ip) * inode to raw ext2 inode */ void -ext2_i2ei(ip, ei) - struct inode *ip; - struct ext2fs_dinode *ei; +ext2_i2ei(struct inode *ip, struct ext2fs_dinode *ei) { int i; diff --git a/sys/fs/ext2fs/ext2_lookup.c b/sys/fs/ext2fs/ext2_lookup.c index 8827550c0e0..b9a2f801154 100644 --- a/sys/fs/ext2fs/ext2_lookup.c +++ b/sys/fs/ext2fs/ext2_lookup.c @@ -129,12 +129,7 @@ static int ext2_lookup_ino(struct vnode *vdp, struct vnode **vpp, * the whole buffer to uiomove */ int -ext2_readdir(ap) - struct vop_readdir_args /* { - struct vnode *a_vp; - struct uio *a_uio; - struct ucred *a_cred; - } */ *ap; +ext2_readdir(struct vop_readdir_args *ap) { struct uio *uio = ap->a_uio; int count, error; @@ -278,12 +273,7 @@ ext2_readdir(ap) * nor deleting, add name to cache */ int -ext2_lookup(ap) - struct vop_cachedlookup_args /* { - struct vnode *a_dvp; - struct vnode **a_vpp; - struct componentname *a_cnp; - } */ *ap; +ext2_lookup(struct vop_cachedlookup_args *ap) { return (ext2_lookup_ino(ap->a_dvp, ap->a_vpp, ap->a_cnp, NULL)); @@ -722,10 +712,7 @@ found: } void -ext2_dirbad(ip, offset, how) - struct inode *ip; - doff_t offset; - char *how; +ext2_dirbad(struct inode *ip, doff_t offset, char *how) { struct mount *mp; @@ -751,10 +738,8 @@ ext2_dirbad(ip, offset, how) * changed so that it confirms to ext2_check_dir_entry */ static int -ext2_dirbadentry(dp, de, entryoffsetinblock) - struct vnode *dp; - struct ext2fs_direct_2 *de; - int entryoffsetinblock; +ext2_dirbadentry(struct vnode *dp, struct ext2fs_direct_2 *de, + int entryoffsetinblock) { int DIRBLKSIZ = VTOI(dp)->i_e2fs->e2fs_bsize; @@ -791,10 +776,7 @@ ext2_dirbadentry(dp, de, entryoffsetinblock) * entry is to be obtained. */ int -ext2_direnter(ip, dvp, cnp) - struct inode *ip; - struct vnode *dvp; - struct componentname *cnp; +ext2_direnter(struct inode *ip, struct vnode *dvp, struct componentname *cnp) { struct ext2fs_direct_2 *ep, *nep; struct inode *dp; @@ -944,9 +926,7 @@ ext2_direnter(ip, dvp, cnp) * to the size of the previous entry. */ int -ext2_dirremove(dvp, cnp) - struct vnode *dvp; - struct componentname *cnp; +ext2_dirremove(struct vnode *dvp, struct componentname *cnp) { struct inode *dp; struct ext2fs_direct_2 *ep, *rep; @@ -994,9 +974,7 @@ ext2_dirremove(dvp, cnp) * set up by a call to namei. */ int -ext2_dirrewrite(dp, ip, cnp) - struct inode *dp, *ip; - struct componentname *cnp; +ext2_dirrewrite(struct inode *dp, struct inode *ip, struct componentname *cnp) { struct buf *bp; struct ext2fs_direct_2 *ep; @@ -1027,10 +1005,7 @@ ext2_dirrewrite(dp, ip, cnp) * NB: does not handle corrupted directories. */ int -ext2_dirempty(ip, parentino, cred) - struct inode *ip; - ino_t parentino; - struct ucred *cred; +ext2_dirempty(struct inode *ip, ino_t parentino, struct ucred *cred) { off_t off; struct dirtemplate dbuf; @@ -1081,9 +1056,7 @@ ext2_dirempty(ip, parentino, cred) * The target is always vput before returning. */ int -ext2_checkpath(source, target, cred) - struct inode *source, *target; - struct ucred *cred; +ext2_checkpath(struct inode *source, struct inode *target, struct ucred *cred) { struct vnode *vp; int error, namlen; diff --git a/sys/fs/ext2fs/ext2_subr.c b/sys/fs/ext2fs/ext2_subr.c index b8d59bc9575..b5fc62b543f 100644 --- a/sys/fs/ext2fs/ext2_subr.c +++ b/sys/fs/ext2fs/ext2_subr.c @@ -63,11 +63,7 @@ void ext2_checkoverlap(struct buf *, struct inode *); * remaining space in the directory. */ int -ext2_blkatoff(vp, offset, res, bpp) - struct vnode *vp; - off_t offset; - char **res; - struct buf **bpp; +ext2_blkatoff(struct vnode *vp, off_t offset, char **res, struct buf **bpp) { struct inode *ip; struct m_ext2fs *fs; @@ -93,9 +89,7 @@ ext2_blkatoff(vp, offset, res, bpp) #ifdef KDB void -ext2_checkoverlap(bp, ip) - struct buf *bp; - struct inode *ip; +ext2_checkoverlap(struct buf *bp, struct inode *ip) { struct buf *ebp, *ep; int32_t start, last; diff --git a/sys/fs/ext2fs/ext2_vnops.c b/sys/fs/ext2fs/ext2_vnops.c index 7cfc64b0be5..1c0b7a182e1 100644 --- a/sys/fs/ext2fs/ext2_vnops.c +++ b/sys/fs/ext2fs/ext2_vnops.c @@ -223,13 +223,7 @@ ext2_itimes(struct vnode *vp) * Create a regular file */ static int -ext2_create(ap) - struct vop_create_args /* { - struct vnode *a_dvp; - struct vnode **a_vpp; - struct componentname *a_cnp; - struct vattr *a_vap; - } */ *ap; +ext2_create(struct vop_create_args *ap) { int error; @@ -242,13 +236,7 @@ ext2_create(ap) } static int -ext2_open(ap) - struct vop_open_args /* { - struct vnode *a_vp; - int a_mode; - struct ucred *a_cred; - struct thread *a_td; - } */ *ap; +ext2_open(struct vop_open_args *ap) { if (ap->a_vp->v_type == VBLK || ap->a_vp->v_type == VCHR) @@ -272,13 +260,7 @@ ext2_open(ap) * Update the times on the inode. */ static int -ext2_close(ap) - struct vop_close_args /* { - struct vnode *a_vp; - int a_fflag; - struct ucred *a_cred; - struct thread *a_td; - } */ *ap; +ext2_close(struct vop_close_args *ap) { struct vnode *vp = ap->a_vp; @@ -290,13 +272,7 @@ ext2_close(ap) } static int -ext2_access(ap) - struct vop_access_args /* { - struct vnode *a_vp; - accmode_t a_accmode; - struct ucred *a_cred; - struct thread *a_td; - } */ *ap; +ext2_access(struct vop_access_args *ap) { struct vnode *vp = ap->a_vp; struct inode *ip = VTOI(vp); @@ -334,12 +310,7 @@ ext2_access(ap) } static int -ext2_getattr(ap) - struct vop_getattr_args /* { - struct vnode *a_vp; - struct vattr *a_vap; - struct ucred *a_cred; - } */ *ap; +ext2_getattr(struct vop_getattr_args *ap) { struct vnode *vp = ap->a_vp; struct inode *ip = VTOI(vp); @@ -380,12 +351,7 @@ ext2_getattr(ap) * Set attribute vnode op. called from several syscalls */ static int -ext2_setattr(ap) - struct vop_setattr_args /* { - struct vnode *a_vp; - struct vattr *a_vap; - struct ucred *a_cred; - } */ *ap; +ext2_setattr(struct vop_setattr_args *ap) { struct vattr *vap = ap->a_vap; struct vnode *vp = ap->a_vp; @@ -519,11 +485,7 @@ ext2_setattr(ap) * Inode must be locked before calling. */ static int -ext2_chmod(vp, mode, cred, td) - struct vnode *vp; - int mode; - struct ucred *cred; - struct thread *td; +ext2_chmod(struct vnode *vp, int mode, struct ucred *cred, struct thread *td) { struct inode *ip = VTOI(vp); int error; @@ -560,12 +522,8 @@ ext2_chmod(vp, mode, cred, td) * inode must be locked prior to call. */ static int -ext2_chown(vp, uid, gid, cred, td) - struct vnode *vp; - uid_t uid; - gid_t gid; - struct ucred *cred; - struct thread *td; +ext2_chown(struct vnode *vp, uid_t uid, gid_t gid, struct ucred *cred, + struct thread *td) { struct inode *ip = VTOI(vp); uid_t ouid; @@ -610,13 +568,7 @@ ext2_chown(vp, uid, gid, cred, td) */ /* ARGSUSED */ static int -ext2_fsync(ap) - struct vop_fsync_args /* { - struct vnode *a_vp; - struct ucred *a_cred; - int a_waitfor; - struct thread *a_td; - } */ *ap; +ext2_fsync(struct vop_fsync_args *ap) { /* * Flush all dirty buffers associated with a vnode. @@ -632,13 +584,7 @@ ext2_fsync(ap) */ /* ARGSUSED */ static int -ext2_mknod(ap) - struct vop_mknod_args /* { - struct vnode *a_dvp; - struct vnode **a_vpp; - struct componentname *a_cnp; - struct vattr *a_vap; - } */ *ap; +ext2_mknod(struct vop_mknod_args *ap) { struct vattr *vap = ap->a_vap; struct vnode **vpp = ap->a_vpp; @@ -677,12 +623,7 @@ ext2_mknod(ap) } static int -ext2_remove(ap) - struct vop_remove_args /* { - struct vnode *a_dvp; - struct vnode *a_vp; - struct componentname *a_cnp; - } */ *ap; +ext2_remove(struct vop_remove_args *ap) { struct inode *ip; struct vnode *vp = ap->a_vp; @@ -708,12 +649,7 @@ out: * link vnode call */ static int -ext2_link(ap) - struct vop_link_args /* { - struct vnode *a_tdvp; - struct vnode *a_vp; - struct componentname *a_cnp; - } */ *ap; +ext2_link(struct vop_link_args *ap) { struct vnode *vp = ap->a_vp; struct vnode *tdvp = ap->a_tdvp; @@ -776,15 +712,7 @@ out: * directory. */ static int -ext2_rename(ap) - struct vop_rename_args /* { - struct vnode *a_fdvp; - struct vnode *a_fvp; - struct componentname *a_fcnp; - struct vnode *a_tdvp; - struct vnode *a_tvp; - struct componentname *a_tcnp; - } */ *ap; +ext2_rename(struct vop_rename_args *ap) { struct vnode *tvp = ap->a_tvp; struct vnode *tdvp = ap->a_tdvp; @@ -1139,13 +1067,7 @@ out: * Mkdir system call */ static int -ext2_mkdir(ap) - struct vop_mkdir_args /* { - struct vnode *a_dvp; - struct vnode **a_vpp; - struct componentname *a_cnp; - struct vattr *a_vap; - } */ *ap; +ext2_mkdir(struct vop_mkdir_args *ap) { struct vnode *dvp = ap->a_dvp; struct vattr *vap = ap->a_vap; @@ -1276,12 +1198,7 @@ out: * Rmdir system call. */ static int -ext2_rmdir(ap) - struct vop_rmdir_args /* { - struct vnode *a_dvp; - struct vnode *a_vp; - struct componentname *a_cnp; - } */ *ap; +ext2_rmdir(struct vop_rmdir_args *ap) { struct vnode *vp = ap->a_vp; struct vnode *dvp = ap->a_dvp; @@ -1349,14 +1266,7 @@ out: * symlink -- make a symbolic link */ static int -ext2_symlink(ap) - struct vop_symlink_args /* { - struct vnode *a_dvp; - struct vnode **a_vpp; - struct componentname *a_cnp; - struct vattr *a_vap; - char *a_target; - } */ *ap; +ext2_symlink(struct vop_symlink_args *ap) { struct vnode *vp, **vpp = ap->a_vpp; struct inode *ip; @@ -1386,12 +1296,7 @@ ext2_symlink(ap) * Return target name of a symbolic link */ static int -ext2_readlink(ap) - struct vop_readlink_args /* { - struct vnode *a_vp; - struct uio *a_uio; - struct ucred *a_cred; - } */ *ap; +ext2_readlink(struct vop_readlink_args *ap) { struct vnode *vp = ap->a_vp; struct inode *ip = VTOI(vp); @@ -1413,11 +1318,7 @@ ext2_readlink(ap) * deadlock on memory. See ext2_bmap() for details. */ static int -ext2_strategy(ap) - struct vop_strategy_args /* { - struct vnode *a_vp; - struct buf *a_bp; - } */ *ap; +ext2_strategy(struct vop_strategy_args *ap) { struct buf *bp = ap->a_bp; struct vnode *vp = ap->a_vp; @@ -1455,10 +1356,7 @@ ext2_strategy(ap) * Print out the contents of an inode. */ static int -ext2_print(ap) - struct vop_print_args /* { - struct vnode *a_vp; - } */ *ap; +ext2_print(struct vop_print_args *ap) { struct vnode *vp = ap->a_vp; struct inode *ip = VTOI(vp); @@ -1476,13 +1374,7 @@ ext2_print(ap) * Update the times on the inode then do device close. */ static int -ext2fifo_close(ap) - struct vop_close_args /* { - struct vnode *a_vp; - int a_fflag; - struct ucred *a_cred; - struct thread *a_td; - } */ *ap; +ext2fifo_close(struct vop_close_args *ap) { struct vnode *vp = ap->a_vp; @@ -1499,8 +1391,7 @@ ext2fifo_close(ap) * Fall through to ext2 kqfilter routines if needed */ static int -ext2fifo_kqfilter(ap) - struct vop_kqfilter_args *ap; +ext2fifo_kqfilter(struct vop_kqfilter_args *ap) { int error; @@ -1514,12 +1405,7 @@ ext2fifo_kqfilter(ap) * Return POSIX pathconf information applicable to ext2 filesystems. */ static int -ext2_pathconf(ap) - struct vop_pathconf_args /* { - struct vnode *a_vp; - int a_name; - int *a_retval; - } */ *ap; +ext2_pathconf(struct vop_pathconf_args *ap) { switch (ap->a_name) { @@ -1552,11 +1438,7 @@ ext2_pathconf(ap) */ /* ARGSUSED */ static int -ext2_vptofh(ap) - struct vop_vptofh_args /* { - struct vnode *a_vp; - struct fid *a_fhp; - } */ *ap; +ext2_vptofh(struct vop_vptofh_args *ap) { struct inode *ip; struct ufid *ufhp; @@ -1574,10 +1456,7 @@ ext2_vptofh(ap) * vnodes. */ int -ext2_vinit(mntp, fifoops, vpp) - struct mount *mntp; - struct vop_vector *fifoops; - struct vnode **vpp; +ext2_vinit(struct mount *mntp, struct vop_vector *fifoops, struct vnode **vpp) { struct inode *ip; struct vnode *vp; @@ -1599,11 +1478,8 @@ ext2_vinit(mntp, fifoops, vpp) * Allocate a new inode. */ static int -ext2_makeinode(mode, dvp, vpp, cnp) - int mode; - struct vnode *dvp; - struct vnode **vpp; - struct componentname *cnp; +ext2_makeinode(int mode, struct vnode *dvp, struct vnode **vpp, + struct componentname *cnp) { struct inode *ip, *pdir; struct vnode *tvp; @@ -1686,13 +1562,7 @@ bad: * Vnode op for reading. */ static int -ext2_read(ap) - struct vop_read_args /* { - struct vnode *a_vp; - struct uio *a_uio; - int a_ioflag; - struct ucred *a_cred; - } */ *ap; +ext2_read(struct vop_read_args *ap) { struct vnode *vp; struct inode *ip; @@ -1835,13 +1705,7 @@ ext2_read(ap) * Vnode op for writing. */ static int -ext2_write(ap) - struct vop_write_args /* { - struct vnode *a_vp; - struct uio *a_uio; - int a_ioflag; - struct ucred *a_cred; - } */ *ap; +ext2_write(struct vop_write_args *ap) { struct vnode *vp; struct uio *uio; From f0d44a49a08b0935783274e291e68e700a864953 Mon Sep 17 00:00:00 2001 From: Michael Tuexen Date: Sun, 10 Feb 2013 19:57:19 +0000 Subject: [PATCH 0106/1476] Make sure that received packets for removed addresses are handled consistently. While there, make variable names consistent. MFC after: 3 days --- sys/netinet/sctp_pcb.c | 490 +++++++++++++++++++++-------------------- 1 file changed, 251 insertions(+), 239 deletions(-) diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c index 4d01756673b..a2eb8051755 100644 --- a/sys/netinet/sctp_pcb.c +++ b/sys/netinet/sctp_pcb.c @@ -824,217 +824,6 @@ out_now: } -static struct sctp_tcb * -sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from, - struct sockaddr *to, struct sctp_nets **netp, uint32_t vrf_id) -{ - /**** ASSUMES THE CALLER holds the INP_INFO_RLOCK */ - /* - * If we support the TCP model, then we must now dig through to see - * if we can find our endpoint in the list of tcp ep's. - */ - uint16_t lport, rport; - struct sctppcbhead *ephead; - struct sctp_inpcb *inp; - struct sctp_laddr *laddr; - struct sctp_tcb *stcb; - struct sctp_nets *net; - - if ((to == NULL) || (from == NULL)) { - return (NULL); - } - switch (to->sa_family) { -#ifdef INET - case AF_INET: - if (from->sa_family == AF_INET) { - lport = ((struct sockaddr_in *)to)->sin_port; - rport = ((struct sockaddr_in *)from)->sin_port; - } else { - return (NULL); - } - break; -#endif -#ifdef INET6 - case AF_INET6: - if (from->sa_family == AF_INET6) { - lport = ((struct sockaddr_in6 *)to)->sin6_port; - rport = ((struct sockaddr_in6 *)from)->sin6_port; - } else { - return (NULL); - } - break; -#endif - default: - return (NULL); - } - ephead = &SCTP_BASE_INFO(sctp_tcpephash)[SCTP_PCBHASH_ALLADDR((lport | rport), SCTP_BASE_INFO(hashtcpmark))]; - /* - * Ok now for each of the guys in this bucket we must look and see: - * - Does the remote port match. - Does there single association's - * addresses match this address (to). If so we update p_ep to point - * to this ep and return the tcb from it. - */ - LIST_FOREACH(inp, ephead, sctp_hash) { - SCTP_INP_RLOCK(inp); - if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) { - SCTP_INP_RUNLOCK(inp); - continue; - } - if (lport != inp->sctp_lport) { - SCTP_INP_RUNLOCK(inp); - continue; - } - if (inp->def_vrf_id != vrf_id) { - SCTP_INP_RUNLOCK(inp); - continue; - } - /* check to see if the ep has one of the addresses */ - if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) { - /* We are NOT bound all, so look further */ - int match = 0; - - LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { - - if (laddr->ifa == NULL) { - SCTPDBG(SCTP_DEBUG_PCB1, "%s: NULL ifa\n", __FUNCTION__); - continue; - } - if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED) { - SCTPDBG(SCTP_DEBUG_PCB1, "ifa being deleted\n"); - continue; - } - if (laddr->ifa->address.sa.sa_family == - to->sa_family) { - /* see if it matches */ - -#ifdef INET - if (from->sa_family == AF_INET) { - struct sockaddr_in *intf_addr, - *sin; - - intf_addr = &laddr->ifa->address.sin; - sin = (struct sockaddr_in *)to; - if (sin->sin_addr.s_addr == - intf_addr->sin_addr.s_addr) { - match = 1; - break; - } - } -#endif -#ifdef INET6 - if (from->sa_family == AF_INET6) { - struct sockaddr_in6 *intf_addr6; - struct sockaddr_in6 *sin6; - - sin6 = (struct sockaddr_in6 *) - to; - intf_addr6 = &laddr->ifa->address.sin6; - - if (SCTP6_ARE_ADDR_EQUAL(sin6, - intf_addr6)) { - match = 1; - break; - } - } -#endif - } - } - if (match == 0) { - /* This endpoint does not have this address */ - SCTP_INP_RUNLOCK(inp); - continue; - } - } - /* - * Ok if we hit here the ep has the address, does it hold - * the tcb? - */ - - stcb = LIST_FIRST(&inp->sctp_asoc_list); - if (stcb == NULL) { - SCTP_INP_RUNLOCK(inp); - continue; - } - SCTP_TCB_LOCK(stcb); - if (stcb->rport != rport) { - /* remote port does not match. */ - SCTP_TCB_UNLOCK(stcb); - SCTP_INP_RUNLOCK(inp); - continue; - } - if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { - SCTP_TCB_UNLOCK(stcb); - SCTP_INP_RUNLOCK(inp); - continue; - } - /* Does this TCB have a matching address? */ - TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { - - if (net->ro._l_addr.sa.sa_family != from->sa_family) { - /* not the same family, can't be a match */ - continue; - } - switch (from->sa_family) { -#ifdef INET - case AF_INET: - { - struct sockaddr_in *sin, *rsin; - - sin = (struct sockaddr_in *)&net->ro._l_addr; - rsin = (struct sockaddr_in *)from; - if (sin->sin_addr.s_addr == - rsin->sin_addr.s_addr) { - /* found it */ - if (netp != NULL) { - *netp = net; - } - /* - * Update the endpoint - * pointer - */ - *inp_p = inp; - SCTP_INP_RUNLOCK(inp); - return (stcb); - } - break; - } -#endif -#ifdef INET6 - case AF_INET6: - { - struct sockaddr_in6 *sin6, *rsin6; - - sin6 = (struct sockaddr_in6 *)&net->ro._l_addr; - rsin6 = (struct sockaddr_in6 *)from; - if (SCTP6_ARE_ADDR_EQUAL(sin6, - rsin6)) { - /* found it */ - if (netp != NULL) { - *netp = net; - } - /* - * Update the endpoint - * pointer - */ - *inp_p = inp; - SCTP_INP_RUNLOCK(inp); - return (stcb); - } - break; - } -#endif - default: - /* TSNH */ - break; - } - } - SCTP_TCB_UNLOCK(stcb); - SCTP_INP_RUNLOCK(inp); - } - return (NULL); -} - - static int sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to) { @@ -1131,6 +920,10 @@ sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to) struct sctp_laddr *laddr; LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) { + if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED) { + SCTPDBG(SCTP_DEBUG_PCB1, "ifa being deleted\n"); + continue; + } if (sctp_is_addr_restricted(stcb, laddr->ifa) && (!sctp_is_addr_pending(stcb, laddr->ifa))) { /* @@ -1185,6 +978,226 @@ sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to) } +static struct sctp_tcb * +sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from, + struct sockaddr *to, struct sctp_nets **netp, uint32_t vrf_id) +{ + /**** ASSUMES THE CALLER holds the INP_INFO_RLOCK */ + /* + * If we support the TCP model, then we must now dig through to see + * if we can find our endpoint in the list of tcp ep's. + */ + uint16_t lport, rport; + struct sctppcbhead *ephead; + struct sctp_inpcb *inp; + struct sctp_laddr *laddr; + struct sctp_tcb *stcb; + struct sctp_nets *net; + + if ((to == NULL) || (from == NULL)) { + return (NULL); + } + switch (to->sa_family) { +#ifdef INET + case AF_INET: + if (from->sa_family == AF_INET) { + lport = ((struct sockaddr_in *)to)->sin_port; + rport = ((struct sockaddr_in *)from)->sin_port; + } else { + return (NULL); + } + break; +#endif +#ifdef INET6 + case AF_INET6: + if (from->sa_family == AF_INET6) { + lport = ((struct sockaddr_in6 *)to)->sin6_port; + rport = ((struct sockaddr_in6 *)from)->sin6_port; + } else { + return (NULL); + } + break; +#endif + default: + return (NULL); + } + ephead = &SCTP_BASE_INFO(sctp_tcpephash)[SCTP_PCBHASH_ALLADDR((lport | rport), SCTP_BASE_INFO(hashtcpmark))]; + /* + * Ok now for each of the guys in this bucket we must look and see: + * - Does the remote port match. - Does there single association's + * addresses match this address (to). If so we update p_ep to point + * to this ep and return the tcb from it. + */ + LIST_FOREACH(inp, ephead, sctp_hash) { + SCTP_INP_RLOCK(inp); + if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) { + SCTP_INP_RUNLOCK(inp); + continue; + } + if (lport != inp->sctp_lport) { + SCTP_INP_RUNLOCK(inp); + continue; + } + if (inp->def_vrf_id != vrf_id) { + SCTP_INP_RUNLOCK(inp); + continue; + } + /* check to see if the ep has one of the addresses */ + if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) { + /* We are NOT bound all, so look further */ + int match = 0; + + LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { + + if (laddr->ifa == NULL) { + SCTPDBG(SCTP_DEBUG_PCB1, "%s: NULL ifa\n", __FUNCTION__); + continue; + } + if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED) { + SCTPDBG(SCTP_DEBUG_PCB1, "ifa being deleted\n"); + continue; + } + if (laddr->ifa->address.sa.sa_family == + to->sa_family) { + /* see if it matches */ +#ifdef INET + if (from->sa_family == AF_INET) { + struct sockaddr_in *intf_addr, + *sin; + + intf_addr = &laddr->ifa->address.sin; + sin = (struct sockaddr_in *)to; + if (sin->sin_addr.s_addr == + intf_addr->sin_addr.s_addr) { + match = 1; + break; + } + } +#endif +#ifdef INET6 + if (from->sa_family == AF_INET6) { + struct sockaddr_in6 *intf_addr6; + struct sockaddr_in6 *sin6; + + sin6 = (struct sockaddr_in6 *) + to; + intf_addr6 = &laddr->ifa->address.sin6; + + if (SCTP6_ARE_ADDR_EQUAL(sin6, + intf_addr6)) { + match = 1; + break; + } + } +#endif + } + } + if (match == 0) { + /* This endpoint does not have this address */ + SCTP_INP_RUNLOCK(inp); + continue; + } + } + /* + * Ok if we hit here the ep has the address, does it hold + * the tcb? + */ + /* XXX: Why don't we TAILQ_FOREACH through sctp_asoc_list? */ + stcb = LIST_FIRST(&inp->sctp_asoc_list); + if (stcb == NULL) { + SCTP_INP_RUNLOCK(inp); + continue; + } + SCTP_TCB_LOCK(stcb); + if (!sctp_does_stcb_own_this_addr(stcb, to)) { + SCTP_TCB_UNLOCK(stcb); + SCTP_INP_RUNLOCK(inp); + continue; + } + if (stcb->rport != rport) { + /* remote port does not match. */ + SCTP_TCB_UNLOCK(stcb); + SCTP_INP_RUNLOCK(inp); + continue; + } + if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { + SCTP_TCB_UNLOCK(stcb); + SCTP_INP_RUNLOCK(inp); + continue; + } + if (!sctp_does_stcb_own_this_addr(stcb, to)) { + SCTP_TCB_UNLOCK(stcb); + SCTP_INP_RUNLOCK(inp); + continue; + } + /* Does this TCB have a matching address? */ + TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { + + if (net->ro._l_addr.sa.sa_family != from->sa_family) { + /* not the same family, can't be a match */ + continue; + } + switch (from->sa_family) { +#ifdef INET + case AF_INET: + { + struct sockaddr_in *sin, *rsin; + + sin = (struct sockaddr_in *)&net->ro._l_addr; + rsin = (struct sockaddr_in *)from; + if (sin->sin_addr.s_addr == + rsin->sin_addr.s_addr) { + /* found it */ + if (netp != NULL) { + *netp = net; + } + /* + * Update the endpoint + * pointer + */ + *inp_p = inp; + SCTP_INP_RUNLOCK(inp); + return (stcb); + } + break; + } +#endif +#ifdef INET6 + case AF_INET6: + { + struct sockaddr_in6 *sin6, *rsin6; + + sin6 = (struct sockaddr_in6 *)&net->ro._l_addr; + rsin6 = (struct sockaddr_in6 *)from; + if (SCTP6_ARE_ADDR_EQUAL(sin6, + rsin6)) { + /* found it */ + if (netp != NULL) { + *netp = net; + } + /* + * Update the endpoint + * pointer + */ + *inp_p = inp; + SCTP_INP_RUNLOCK(inp); + return (stcb); + } + break; + } +#endif + default: + /* TSNH */ + break; + } + } + SCTP_TCB_UNLOCK(stcb); + SCTP_INP_RUNLOCK(inp); + } + return (NULL); +} + + /* * rules for use * @@ -1906,20 +1919,20 @@ sctp_findassociation_addr_sa(struct sockaddr *from, struct sockaddr *to, uint32_t vrf_id) { struct sctp_inpcb *inp = NULL; - struct sctp_tcb *retval; + struct sctp_tcb *stcb; SCTP_INP_INFO_RLOCK(); if (find_tcp_pool) { if (inp_p != NULL) { - retval = sctp_tcb_special_locate(inp_p, from, to, netp, + stcb = sctp_tcb_special_locate(inp_p, from, to, netp, vrf_id); } else { - retval = sctp_tcb_special_locate(&inp, from, to, netp, + stcb = sctp_tcb_special_locate(&inp, from, to, netp, vrf_id); } - if (retval != NULL) { + if (stcb != NULL) { SCTP_INP_INFO_RUNLOCK(); - return (retval); + return (stcb); } } inp = sctp_pcb_findep(to, 0, 1, vrf_id); @@ -1927,7 +1940,6 @@ sctp_findassociation_addr_sa(struct sockaddr *from, struct sockaddr *to, *inp_p = inp; } SCTP_INP_INFO_RUNLOCK(); - if (inp == NULL) { return (NULL); } @@ -1938,13 +1950,13 @@ sctp_findassociation_addr_sa(struct sockaddr *from, struct sockaddr *to, * inbound packet side. */ if (inp_p != NULL) { - retval = sctp_findassociation_ep_addr(inp_p, from, netp, to, + stcb = sctp_findassociation_ep_addr(inp_p, from, netp, to, NULL); } else { - retval = sctp_findassociation_ep_addr(&inp, from, netp, to, + stcb = sctp_findassociation_ep_addr(&inp, from, netp, to, NULL); } - return retval; + return (stcb); } @@ -1959,7 +1971,7 @@ sctp_findassociation_special_addr(struct mbuf *m, int offset, struct sockaddr *dst) { struct sctp_paramhdr *phdr, parm_buf; - struct sctp_tcb *retval; + struct sctp_tcb *stcb; uint32_t ptype, plen; #ifdef INET @@ -1984,7 +1996,7 @@ sctp_findassociation_special_addr(struct mbuf *m, int offset, sin6.sin6_port = sh->src_port; #endif - retval = NULL; + stcb = NULL; offset += sizeof(struct sctp_init_chunk); phdr = sctp_get_next_param(m, offset, &parm_buf, sizeof(parm_buf)); @@ -2009,10 +2021,10 @@ sctp_findassociation_special_addr(struct mbuf *m, int offset, p4 = (struct sctp_ipv4addr_param *)phdr; memcpy(&sin4.sin_addr, &p4->addr, sizeof(p4->addr)); /* look it up */ - retval = sctp_findassociation_ep_addr(inp_p, + stcb = sctp_findassociation_ep_addr(inp_p, (struct sockaddr *)&sin4, netp, dst, NULL); - if (retval != NULL) { - return (retval); + if (stcb != NULL) { + return (stcb); } } #endif @@ -2030,10 +2042,10 @@ sctp_findassociation_special_addr(struct mbuf *m, int offset, p6 = (struct sctp_ipv6addr_param *)phdr; memcpy(&sin6.sin6_addr, &p6->addr, sizeof(p6->addr)); /* look it up */ - retval = sctp_findassociation_ep_addr(inp_p, + stcb = sctp_findassociation_ep_addr(inp_p, (struct sockaddr *)&sin6, netp, dst, NULL); - if (retval != NULL) { - return (retval); + if (stcb != NULL) { + return (stcb); } } #endif @@ -2158,15 +2170,15 @@ sctp_findassociation_addr(struct mbuf *m, int offset, struct sctp_inpcb **inp_p, struct sctp_nets **netp, uint32_t vrf_id) { int find_tcp_pool; - struct sctp_tcb *retval; + struct sctp_tcb *stcb; struct sctp_inpcb *inp; if (sh->v_tag) { /* we only go down this path if vtag is non-zero */ - retval = sctp_findassoc_by_vtag(src, dst, ntohl(sh->v_tag), + stcb = sctp_findassoc_by_vtag(src, dst, ntohl(sh->v_tag), inp_p, netp, sh->src_port, sh->dest_port, 0, vrf_id, 0); - if (retval) { - return (retval); + if (stcb) { + return (stcb); } } find_tcp_pool = 0; @@ -2178,15 +2190,15 @@ sctp_findassociation_addr(struct mbuf *m, int offset, find_tcp_pool = 1; } if (inp_p) { - retval = sctp_findassociation_addr_sa(src, dst, inp_p, netp, + stcb = sctp_findassociation_addr_sa(src, dst, inp_p, netp, find_tcp_pool, vrf_id); inp = *inp_p; } else { - retval = sctp_findassociation_addr_sa(src, dst, &inp, netp, + stcb = sctp_findassociation_addr_sa(src, dst, &inp, netp, find_tcp_pool, vrf_id); } - SCTPDBG(SCTP_DEBUG_PCB1, "retval:%p inp:%p\n", (void *)retval, (void *)inp); - if (retval == NULL && inp) { + SCTPDBG(SCTP_DEBUG_PCB1, "stcb:%p inp:%p\n", (void *)stcb, (void *)inp); + if (stcb == NULL && inp) { /* Found a EP but not this address */ if ((ch->chunk_type == SCTP_INITIATION) || (ch->chunk_type == SCTP_INITIATION_ACK)) { @@ -2204,15 +2216,15 @@ sctp_findassociation_addr(struct mbuf *m, int offset, } return (NULL); } - retval = sctp_findassociation_special_addr(m, + stcb = sctp_findassociation_special_addr(m, offset, sh, &inp, netp, dst); if (inp_p != NULL) { *inp_p = inp; } } } - SCTPDBG(SCTP_DEBUG_PCB1, "retval is %p\n", (void *)retval); - return (retval); + SCTPDBG(SCTP_DEBUG_PCB1, "stcb is %p\n", (void *)stcb); + return (stcb); } /* From 2871baa49acbc19c7908f6032d961abcc07cf3d9 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sun, 10 Feb 2013 20:08:33 +0000 Subject: [PATCH 0107/1476] Remove the ia64-specific code fragment, which effect is more cleanly done by the call to trans_prot() function a line before. Discussed with: Oliver Pinter MFC after: 1 week --- sys/kern/imgact_elf.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index 4c1cb5b0e03..e6f385a4f8a 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -826,16 +826,6 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) if (phdr[i].p_memsz == 0) break; prot = __elfN(trans_prot)(phdr[i].p_flags); - -#if defined(__ia64__) && __ELF_WORD_SIZE == 32 && defined(IA32_ME_HARDER) - /* - * Some x86 binaries assume read == executable, - * notably the M3 runtime and therefore cvsup - */ - if (prot & VM_PROT_READ) - prot |= VM_PROT_EXECUTE; -#endif - error = __elfN(load_section)(imgp, phdr[i].p_offset, (caddr_t)(uintptr_t)phdr[i].p_vaddr + et_dyn_addr, phdr[i].p_memsz, phdr[i].p_filesz, prot, From ad7d20c921c320e438be9bb783eedf37036cbee5 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Sun, 10 Feb 2013 23:09:15 +0000 Subject: [PATCH 0108/1476] fts: Use O_DIRECTORY when opening name that might be changed by attacker. There are uncommon cases where fts_safe_changedir() may be called with a non-NULL name that is not "..". Do not block or worse if an attacker put (a (symlink to) a fifo or device where a directory used to be. MFC after: 1 week --- lib/libc/gen/fts.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/libc/gen/fts.c b/lib/libc/gen/fts.c index 243320cc871..d15be06b08c 100644 --- a/lib/libc/gen/fts.c +++ b/lib/libc/gen/fts.c @@ -1119,7 +1119,8 @@ fts_safe_changedir(FTS *sp, FTSENT *p, int fd, char *path) newfd = fd; if (ISSET(FTS_NOCHDIR)) return (0); - if (fd < 0 && (newfd = _open(path, O_RDONLY | O_CLOEXEC, 0)) < 0) + if (fd < 0 && (newfd = _open(path, O_RDONLY | O_DIRECTORY | + O_CLOEXEC, 0)) < 0) return (-1); if (_fstat(newfd, &sb)) { ret = -1; From 42f997ba534c9a2c44133c17df33b03e33cab022 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sun, 10 Feb 2013 23:51:26 +0000 Subject: [PATCH 0109/1476] Add CAP_MKNOD right. Sponsored by: The FreeBSD Foundation --- usr.bin/procstat/procstat_files.c | 1 + 1 file changed, 1 insertion(+) diff --git a/usr.bin/procstat/procstat_files.c b/usr.bin/procstat/procstat_files.c index 126ef7e4587..2d50cd64c8f 100644 --- a/usr.bin/procstat/procstat_files.c +++ b/usr.bin/procstat/procstat_files.c @@ -163,6 +163,7 @@ static struct cap_desc { { CAP_MKDIR, "md" }, { CAP_RMDIR, "rm" }, { CAP_MKFIFO, "mf" }, + { CAP_MKNOD, "mn" }, /* Lookups - used to constraint *at() calls. */ { CAP_LOOKUP, "lo" }, From 6a9f247c85e52e467ffc2e16d7a30c104b6aa7c1 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Mon, 11 Feb 2013 00:10:35 +0000 Subject: [PATCH 0110/1476] Capability rights for process management via process descriptors do exist already, so uncomment them. Sponsored by: The FreeBSD Foundation --- usr.bin/procstat/procstat_files.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/usr.bin/procstat/procstat_files.c b/usr.bin/procstat/procstat_files.c index 2d50cd64c8f..377390080a5 100644 --- a/usr.bin/procstat/procstat_files.c +++ b/usr.bin/procstat/procstat_files.c @@ -209,11 +209,10 @@ static struct cap_desc { { CAP_IOCTL, "io" }, { CAP_TTYHOOK, "ty" }, -#ifdef NOTYET + /* Process management via process descriptors. */ { CAP_PDGETPID, "pg" }, - { CAP_PDWAIT4, "pw" }, + { CAP_PDWAIT, "pw" }, { CAP_PDKILL, "pk" }, -#endif }; static const u_int cap_desc_count = sizeof(cap_desc) / sizeof(cap_desc[0]); From 53d21f0bbe643981593626fc9238a9e16b013c64 Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Mon, 11 Feb 2013 02:15:26 +0000 Subject: [PATCH 0111/1476] Provide verbose help for fdt commands on platforms that use it. --- sys/boot/arm/uboot/Makefile | 2 +- sys/boot/fdt/help.fdt | 93 +++++++++++++++++++++++++++++++++ sys/boot/powerpc/ps3/Makefile | 2 +- sys/boot/powerpc/uboot/Makefile | 2 +- 4 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 sys/boot/fdt/help.fdt diff --git a/sys/boot/arm/uboot/Makefile b/sys/boot/arm/uboot/Makefile index 197421893fa..f2cf8ee358d 100644 --- a/sys/boot/arm/uboot/Makefile +++ b/sys/boot/arm/uboot/Makefile @@ -118,7 +118,7 @@ LDADD= ${LIBFICL} ${LIBUBOOT} ${LIBFDT} -lstand vers.c: ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version sh ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version ${NEWVERSWHAT} -loader.help: help.common help.uboot +loader.help: help.common help.uboot ${.CURDIR}/../../fdt/help.fdt cat ${.ALLSRC} | \ awk -f ${.CURDIR}/../../common/merge_help.awk > ${.TARGET} diff --git a/sys/boot/fdt/help.fdt b/sys/boot/fdt/help.fdt new file mode 100644 index 00000000000..665f63c260c --- /dev/null +++ b/sys/boot/fdt/help.fdt @@ -0,0 +1,93 @@ +$FreeBSD$ +############################################################################### +# Tfdt Dfdt manipulation commands + + fdt + + Facilities for loading and manipulating device tree data. + +############################################################################### +# Tfdt Saddr Dload fdt from an address in memory + + fdt addr
    + + Copies compiled device tree from a particular location + in memory. + +############################################################################### +# Tfdt Salias DXXX + + fdt alias
    + + Not Yet Implemented + +############################################################################### +# Tfdt Scd DSelect a particular node for future commands + + fdt cd + + Changes the current node to the node specified by the path. + Path elements are separated by '/'; a leading '/' represents + the root node. + +############################################################################### +# Tfdt Sheader DDump the header of the compiled device tree + + fdt header + + Dumps DTB size, format and other key values. + +############################################################################### +# Tfdt Sls DList subnodes of the current node + + fdt ls + + Lists the nodes under the specified path. + If no path is specified, lists nodes under the current path. + +############################################################################### +# Tfdt Smknode DCreate a new node in the device tree + + fdt mknode + + Creates a new node with the specified name. + +############################################################################### +# Tfdt Smkprop DAdd a new property to the current node + + fdt mkprop ... + + Creates a new property with the specified name and values. + Multiple values can be specified and will be concatenated. + +############################################################################### +# Tfdt Smres DXXX + + fdt mres + + Dumps the list of reserved memory regions. + +############################################################################### +# Tfdt Sprop DDump value of a particular property + + fdt prop ... + + If value is specified, set the given property to the indicated value. + Otherwise, print the value of the property. + +############################################################################### +# Tfdt Spwd DPrint path to current node in device tree + + fdt pwd + + Print path to the current node in the device tree. + The current node can be changed with "fdt cd". + +############################################################################### +# Tfdt Srm DRemove node or property from device tree + + fdt rm + + The named node or property will be removed from the device tree. + +############################################################################### diff --git a/sys/boot/powerpc/ps3/Makefile b/sys/boot/powerpc/ps3/Makefile index 810e4805627..bff41b5b960 100644 --- a/sys/boot/powerpc/ps3/Makefile +++ b/sys/boot/powerpc/ps3/Makefile @@ -108,7 +108,7 @@ font.h: vers.c: ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version sh ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version ${NEWVERSWHAT} -loader.help: help.common help.ps3 +loader.help: help.common help.ps3 ${.CURDIR}/../../fdt/help.fdt cat ${.ALLSRC} | \ awk -f ${.CURDIR}/../../common/merge_help.awk > ${.TARGET} diff --git a/sys/boot/powerpc/uboot/Makefile b/sys/boot/powerpc/uboot/Makefile index 783694d7f09..f40663c4796 100644 --- a/sys/boot/powerpc/uboot/Makefile +++ b/sys/boot/powerpc/uboot/Makefile @@ -103,7 +103,7 @@ LDADD= ${LIBFICL} ${LIBUBOOT} ${LIBFDT} -lstand vers.c: ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version sh ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version ${NEWVERSWHAT} -loader.help: help.common help.uboot +loader.help: help.common help.uboot ${.CURDIR}/../../fdt/help.fdt cat ${.ALLSRC} | \ awk -f ${.CURDIR}/../../common/merge_help.awk > ${.TARGET} From 81561d0459a3e35e6bfa0c8e850d7d45225e28a5 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Mon, 11 Feb 2013 02:48:49 +0000 Subject: [PATCH 0112/1476] Extend the timestamp to be a timeval, rather than ticks. This makes it easier to see TX and RX buffer latencies. --- sys/dev/ath/if_ath_alq.c | 7 ++++++- sys/dev/ath/if_ath_alq.h | 3 ++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/sys/dev/ath/if_ath_alq.c b/sys/dev/ath/if_ath_alq.c index bd839337826..1ad13db5e75 100644 --- a/sys/dev/ath/if_ath_alq.c +++ b/sys/dev/ath/if_ath_alq.c @@ -44,6 +44,7 @@ #include #include #include +#include #include @@ -153,10 +154,13 @@ if_ath_alq_post(struct if_ath_alq *alq, uint16_t op, uint16_t len, { struct if_ath_alq_hdr *ap; struct ale *ale; + struct timeval tv; if (! if_ath_alq_checkdebug(alq, op)) return; + microtime(&tv); + /* * Enforce some semblence of sanity on 'len'. * Although strictly speaking, any length is possible - @@ -172,7 +176,8 @@ if_ath_alq_post(struct if_ath_alq *alq, uint16_t op, uint16_t len, ap = (struct if_ath_alq_hdr *) ale->ae_data; ap->threadid = htobe64((uint64_t) curthread->td_tid); - ap->tstamp = htobe32((uint32_t) ticks); + ap->tstamp_sec = htobe32((uint32_t) tv.tv_sec); + ap->tstamp_usec = htobe32((uint32_t) tv.tv_usec); ap->op = htobe16(op); ap->len = htobe16(len); diff --git a/sys/dev/ath/if_ath_alq.h b/sys/dev/ath/if_ath_alq.h index cb37452499c..3748d50af7e 100644 --- a/sys/dev/ath/if_ath_alq.h +++ b/sys/dev/ath/if_ath_alq.h @@ -116,7 +116,8 @@ struct if_ath_alq { struct if_ath_alq_hdr { uint64_t threadid; - uint32_t tstamp; + uint32_t tstamp_sec; + uint32_t tstamp_usec; uint16_t op; uint16_t len; /* Length of (optional) payload */ }; From 0a83addd18a1d102ba7a9a04fe2948a83c5943d0 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Mon, 11 Feb 2013 02:54:24 +0000 Subject: [PATCH 0113/1476] Teach athalq about the recent if_ath_alq timestamp format change. --- tools/tools/ath/athalq/ar5210_ds.c | 20 ++++++++++++-------- tools/tools/ath/athalq/ar5211_ds.c | 20 ++++++++++++-------- tools/tools/ath/athalq/ar5212_ds.c | 20 ++++++++++++-------- tools/tools/ath/athalq/ar5416_ds.c | 20 ++++++++++++-------- tools/tools/ath/athalq/main.c | 5 +++-- 5 files changed, 51 insertions(+), 34 deletions(-) diff --git a/tools/tools/ath/athalq/ar5210_ds.c b/tools/tools/ath/athalq/ar5210_ds.c index 79b04d940f8..624092ec45e 100644 --- a/tools/tools/ath/athalq/ar5210_ds.c +++ b/tools/tools/ath/athalq/ar5210_ds.c @@ -45,8 +45,9 @@ ar5210_decode_txstatus(struct if_ath_alq_payload *a) /* XXX assumes txs is smaller than PAYLOAD_LEN! */ memcpy(&txs, &a->payload, sizeof(struct ar5210_desc)); - printf("[%u] [%llu] TXSTATUS\n", - (unsigned int) be32toh(a->hdr.tstamp), + printf("[%u.%06u] [%llu] TXSTATUS\n", + (unsigned int) be32toh(a->hdr.tstamp_sec), + (unsigned int) be32toh(a->hdr.tstamp_usec), (unsigned long long) be64toh(a->hdr.threadid)); /* ds_txstatus0 */ @@ -78,8 +79,9 @@ ar5210_decode_txdesc(struct if_ath_alq_payload *a) /* XXX assumes txs is smaller than PAYLOAD_LEN! */ memcpy(&txc, &a->payload, sizeof(struct ar5210_desc)); - printf("[%u] [%llu] TXD\n", - (unsigned int) be32toh(a->hdr.tstamp), + printf("[%u.%06u] [%llu] TXD\n", + (unsigned int) be32toh(a->hdr.tstamp_sec), + (unsigned int) be32toh(a->hdr.tstamp_usec), (unsigned long long) be64toh(a->hdr.threadid)); printf(" link=0x%08x, data=0x%08x\n", @@ -116,8 +118,9 @@ ar5210_decode_rxstatus(struct if_ath_alq_payload *a) /* XXX assumes rxs is smaller than PAYLOAD_LEN! */ memcpy(&rxs, &a->payload, sizeof(struct ar5210_desc)); - printf("[%u] [%llu] RXSTATUS\n", - (unsigned int) be32toh(a->hdr.tstamp), + printf("[%u.%06u] [%llu] RXSTATUS\n", + (unsigned int) be32toh(a->hdr.tstamp_sec), + (unsigned int) be32toh(a->hdr.tstamp_usec), (unsigned long long) be64toh(a->hdr.threadid)); printf(" link=0x%08x, data=0x%08x\n", @@ -167,8 +170,9 @@ ar5210_alq_payload(struct if_ath_alq_payload *a) ar5210_decode_txdesc(a); break; default: - printf("[%d] [%lld] op: %d; len %d\n", - be32toh(a->hdr.tstamp), + printf("[%d.%06d] [%lld] op: %d; len %d\n", + be32toh(a->hdr.tstamp_sec), + be32toh(a->hdr.tstamp_usec), be64toh(a->hdr.threadid), be16toh(a->hdr.op), be16toh(a->hdr.len)); } diff --git a/tools/tools/ath/athalq/ar5211_ds.c b/tools/tools/ath/athalq/ar5211_ds.c index 0f0984fe7da..d389b5a55ca 100644 --- a/tools/tools/ath/athalq/ar5211_ds.c +++ b/tools/tools/ath/athalq/ar5211_ds.c @@ -45,8 +45,9 @@ ar5211_decode_txstatus(struct if_ath_alq_payload *a) /* XXX assumes txs is smaller than PAYLOAD_LEN! */ memcpy(&txs, &a->payload, sizeof(struct ar5211_desc)); - printf("[%u] [%llu] TXSTATUS\n", - (unsigned int) be32toh(a->hdr.tstamp), + printf("[%u.%06u] [%llu] TXSTATUS\n", + (unsigned int) be32toh(a->hdr.tstamp_sec), + (unsigned int) be32toh(a->hdr.tstamp_usec), (unsigned long long) be64toh(a->hdr.threadid)); /* ds_txstatus0 */ @@ -79,8 +80,9 @@ ar5211_decode_txdesc(struct if_ath_alq_payload *a) /* XXX assumes txs is smaller than PAYLOAD_LEN! */ memcpy(&txc, &a->payload, sizeof(struct ar5211_desc)); - printf("[%u] [%llu] TXD\n", - (unsigned int) be32toh(a->hdr.tstamp), + printf("[%u.%06u] [%llu] TXD\n", + (unsigned int) be32toh(a->hdr.tstamp_sec), + (unsigned int) be32toh(a->hdr.tstamp_usec), (unsigned long long) be64toh(a->hdr.threadid)); printf(" link=0x%08x, data=0x%08x\n", @@ -117,8 +119,9 @@ ar5211_decode_rxstatus(struct if_ath_alq_payload *a) /* XXX assumes rxs is smaller than PAYLOAD_LEN! */ memcpy(&rxs, &a->payload, sizeof(struct ar5211_desc)); - printf("[%u] [%llu] RXSTATUS\n", - (unsigned int) be32toh(a->hdr.tstamp), + printf("[%u.%06u] [%llu] RXSTATUS\n", + (unsigned int) be32toh(a->hdr.tstamp_sec), + (unsigned int) be32toh(a->hdr.tstamp_usec), (unsigned long long) be64toh(a->hdr.threadid)); printf(" link=0x%08x, data=0x%08x\n", @@ -168,8 +171,9 @@ ar5211_alq_payload(struct if_ath_alq_payload *a) ar5211_decode_txdesc(a); break; default: - printf("[%d] [%lld] op: %d; len %d\n", - be32toh(a->hdr.tstamp), + printf("[%d.%06d] [%lld] op: %d; len %d\n", + be32toh(a->hdr.tstamp_sec), + be32toh(a->hdr.tstamp_usec), be64toh(a->hdr.threadid), be16toh(a->hdr.op), be16toh(a->hdr.len)); } diff --git a/tools/tools/ath/athalq/ar5212_ds.c b/tools/tools/ath/athalq/ar5212_ds.c index a6364a41172..f752f151d41 100644 --- a/tools/tools/ath/athalq/ar5212_ds.c +++ b/tools/tools/ath/athalq/ar5212_ds.c @@ -45,8 +45,9 @@ ar5212_decode_txstatus(struct if_ath_alq_payload *a) /* XXX assumes txs is smaller than PAYLOAD_LEN! */ memcpy(&txs, &a->payload, sizeof(struct ar5212_desc)); - printf("[%u] [%llu] TXSTATUS: TxDone=%d, TS=0x%08x\n\n", - (unsigned int) be32toh(a->hdr.tstamp), + printf("[%u.%06u] [%llu] TXSTATUS: TxDone=%d, TS=0x%08x\n\n", + (unsigned int) be32toh(a->hdr.tstamp_sec), + (unsigned int) be32toh(a->hdr.tstamp_usec), (unsigned long long) be64toh(a->hdr.threadid), MF(txs.u.tx.status1, AR_Done), MS(txs.u.tx.status0, AR_SendTimestamp)); @@ -85,8 +86,9 @@ ar5212_decode_txdesc(struct if_ath_alq_payload *a) /* XXX assumes txs is smaller than PAYLOAD_LEN! */ memcpy(&txc, &a->payload, sizeof(struct ar5212_desc)); - printf("[%u] [%llu] TXD\n", - (unsigned int) be32toh(a->hdr.tstamp), + printf("[%u.%06u] [%llu] TXD\n", + (unsigned int) be32toh(a->hdr.tstamp_sec), + (unsigned int) be32toh(a->hdr.tstamp_usec), (unsigned long long) be64toh(a->hdr.threadid)); printf(" link=0x%08x, data=0x%08x\n", @@ -149,8 +151,9 @@ ar5212_decode_rxstatus(struct if_ath_alq_payload *a) /* XXX assumes rxs is smaller than PAYLOAD_LEN! */ memcpy(&rxs, &a->payload, sizeof(struct ar5212_desc)); - printf("[%u] [%llu] RXSTATUS: RxOK=%d TS=0x%08x\n", - (unsigned int) be32toh(a->hdr.tstamp), + printf("[%u.%06u] [%llu] RXSTATUS: RxOK=%d TS=0x%08x\n", + (unsigned int) be32toh(a->hdr.tstamp_sec), + (unsigned int) be32toh(a->hdr.tstamp_usec), (unsigned long long) be64toh(a->hdr.threadid), MF(rxs.ds_rxstatus1, AR_Done), MS(rxs.ds_rxstatus1, AR_RcvTimestamp)); @@ -214,8 +217,9 @@ ar5212_alq_payload(struct if_ath_alq_payload *a) ar5212_decode_txdesc(a); break; default: - printf("[%d] [%lld] op: %d; len %d\n", - be32toh(a->hdr.tstamp), + printf("[%d.%06d] [%lld] op: %d; len %d\n", + be32toh(a->hdr.tstamp_sec), + be32toh(a->hdr.tstamp_usec), be64toh(a->hdr.threadid), be16toh(a->hdr.op), be16toh(a->hdr.len)); } diff --git a/tools/tools/ath/athalq/ar5416_ds.c b/tools/tools/ath/athalq/ar5416_ds.c index 55fa1db8ef2..6157c629d1d 100644 --- a/tools/tools/ath/athalq/ar5416_ds.c +++ b/tools/tools/ath/athalq/ar5416_ds.c @@ -45,8 +45,9 @@ ar5416_decode_txstatus(struct if_ath_alq_payload *a) /* XXX assumes txs is smaller than PAYLOAD_LEN! */ memcpy(&txs, &a->payload, sizeof(struct ar5416_desc)); - printf("[%u] [%llu] TXSTATUS: TxDone=%d, TS=0x%08x\n", - (unsigned int) be32toh(a->hdr.tstamp), + printf("[%u.%06u] [%llu] TXSTATUS: TxDone=%d, TS=0x%08x\n", + (unsigned int) be32toh(a->hdr.tstamp_sec), + (unsigned int) be32toh(a->hdr.tstamp_usec), (unsigned long long) be64toh(a->hdr.threadid), MF(txs.u.tx.status[9], AR_TxDone), txs.u.tx.status[2]); @@ -121,8 +122,9 @@ ar5416_decode_txdesc(struct if_ath_alq_payload *a) /* XXX assumes txs is smaller than PAYLOAD_LEN! */ memcpy(&txc, &a->payload, sizeof(struct ar5416_desc)); - printf("[%u] [%llu] TXD\n", - (unsigned int) be32toh(a->hdr.tstamp), + printf("[%u.%06u] [%llu] TXD\n", + (unsigned int) be32toh(a->hdr.tstamp_sec), + (unsigned int) be32toh(a->hdr.tstamp_usec), (unsigned long long) be64toh(a->hdr.threadid)); printf(" link=0x%08x, data=0x%08x\n", @@ -252,8 +254,9 @@ ar5416_decode_rxstatus(struct if_ath_alq_payload *a) /* XXX assumes rxs is smaller than PAYLOAD_LEN! */ memcpy(&rxs, &a->payload, sizeof(struct ar5416_desc)); - printf("[%u] [%llu] RXSTATUS: RxDone=%d, TS=0x%08x\n", - (unsigned int) be32toh(a->hdr.tstamp), + printf("[%u.%06u] [%llu] RXSTATUS: RxDone=%d, TS=0x%08x\n", + (unsigned int) be32toh(a->hdr.tstamp_sec), + (unsigned int) be32toh(a->hdr.tstamp_usec), (unsigned long long) be64toh(a->hdr.threadid), MF(rxs.ds_rxstatus8, AR_RxDone), rxs.ds_rxstatus2); @@ -352,8 +355,9 @@ ar5416_alq_payload(struct if_ath_alq_payload *a) ar5416_decode_txdesc(a); break; default: - printf("[%d] [%lld] op: %d; len %d\n", - be32toh(a->hdr.tstamp), + printf("[%d.%06d] [%lld] op: %d; len %d\n", + be32toh(a->hdr.tstamp_sec), + be32toh(a->hdr.tstamp_usec), be64toh(a->hdr.threadid), be16toh(a->hdr.op), be16toh(a->hdr.len)); } diff --git a/tools/tools/ath/athalq/main.c b/tools/tools/ath/athalq/main.c index 28bbb513147..e8e277c7add 100644 --- a/tools/tools/ath/athalq/main.c +++ b/tools/tools/ath/athalq/main.c @@ -126,8 +126,9 @@ main(int argc, const char *argv[]) ar9300_alq_payload(a); #endif else - printf("[%d] [%lld] op: %d; len %d\n", - be32toh(a->hdr.tstamp), + printf("[%d.%06d] [%lld] op: %d; len %d\n", + be32toh(a->hdr.tstamp_sec), + be32toh(a->hdr.tstamp_usec), be64toh(a->hdr.threadid), be16toh(a->hdr.op), be16toh(a->hdr.len)); From a40880ade483ce09328377610752a38a07b714aa Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Mon, 11 Feb 2013 07:48:26 +0000 Subject: [PATCH 0114/1476] Go back to direct-dispatch of the software queue and frame TX paths when they're being called from the TX completion handler. Going (back) through the taskqueue is just adding extra locking and latency to packet operations. This improves performance a little bit on most NICs. It still hasn't restored the original performance of the AR5416 NIC but the AR9160, AR9280 and later NICs behave very well with this. Tested: * AR5416 STA (still tops out at ~ 70mbit TCP, rather than 150mbit TCP..) * AR9160 hostap (good for both TX and RX) * AR9280 hostap (good for both TX and RX) --- sys/dev/ath/if_ath.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index bcb5e8a1ecd..7679fd2416f 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -4226,7 +4226,9 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq, int dosched) /* Kick the software TXQ scheduler */ if (dosched) { - ath_tx_swq_kick(sc); + ATH_TX_LOCK(sc); + ath_txq_sched(sc, txq); + ATH_TX_UNLOCK(sc); } ATH_KTR(sc, ATH_KTR_TXCOMP, 1, @@ -4271,11 +4273,11 @@ ath_tx_proc_q0(void *arg, int npending) if (sc->sc_softled) ath_led_event(sc, sc->sc_txrix); + ath_txq_qrun(ifp); + ATH_PCU_LOCK(sc); sc->sc_txproc_cnt--; ATH_PCU_UNLOCK(sc); - - ath_tx_kick(sc); } /* @@ -4324,11 +4326,11 @@ ath_tx_proc_q0123(void *arg, int npending) if (sc->sc_softled) ath_led_event(sc, sc->sc_txrix); + ath_txq_qrun(ifp); + ATH_PCU_LOCK(sc); sc->sc_txproc_cnt--; ATH_PCU_UNLOCK(sc); - - ath_tx_kick(sc); } /* @@ -4369,11 +4371,11 @@ ath_tx_proc(void *arg, int npending) if (sc->sc_softled) ath_led_event(sc, sc->sc_txrix); + ath_txq_qrun(ifp); + ATH_PCU_LOCK(sc); sc->sc_txproc_cnt--; ATH_PCU_UNLOCK(sc); - - ath_tx_kick(sc); } #undef TXQACTIVE From 53a835d2dba590ae9d49aee379d7398d11773a88 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Mon, 11 Feb 2013 07:49:40 +0000 Subject: [PATCH 0115/1476] Put this back into the ath taskqueue rather than the ath TX taskqueue. This now should mean all the entry points into the software TX scheduler are back in the same taskqueue. --- sys/dev/ath/if_ath_misc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/ath/if_ath_misc.h b/sys/dev/ath/if_ath_misc.h index d81ef4ce8fc..f35fc11f3b9 100644 --- a/sys/dev/ath/if_ath_misc.h +++ b/sys/dev/ath/if_ath_misc.h @@ -137,7 +137,7 @@ static inline void ath_tx_swq_kick(struct ath_softc *sc) { - taskqueue_enqueue(sc->sc_tx_tq, &sc->sc_txqtask); + taskqueue_enqueue(sc->sc_tq, &sc->sc_txqtask); } #endif From 0518f2c3c1834c8049ca002abdcca8487be1096b Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Mon, 11 Feb 2013 08:06:18 +0000 Subject: [PATCH 0116/1476] Update vendor-sys/illumos/dist to illumos-gate 13952:7a22d0770fc8 Illumos ZFS issues: 3522 zfs module should not allow uninitialized variables --- uts/common/fs/zfs/arc.c | 12 ++++++++---- uts/common/fs/zfs/dmu.c | 3 +-- uts/common/fs/zfs/dmu_objset.c | 3 ++- uts/common/fs/zfs/dsl_dataset.c | 9 +++------ uts/common/fs/zfs/dsl_scan.c | 3 ++- uts/common/fs/zfs/lzjb.c | 7 +++++-- uts/common/fs/zfs/refcount.c | 2 +- uts/common/fs/zfs/sa.c | 8 +++++--- uts/common/fs/zfs/spa.c | 5 +++-- uts/common/fs/zfs/vdev_raidz.c | 3 ++- uts/common/fs/zfs/zap_leaf.c | 2 +- uts/common/fs/zfs/zfs_byteswap.c | 2 +- uts/common/fs/zfs/zfs_fuid.c | 9 ++++++--- uts/common/fs/zfs/zfs_ioctl.c | 2 +- uts/common/fs/zfs/zfs_log.c | 3 +-- uts/common/fs/zfs/zfs_rlock.c | 2 +- uts/common/fs/zfs/zfs_vfsops.c | 18 ++++++++++++------ uts/common/fs/zfs/zfs_vnops.c | 9 +++++---- 18 files changed, 60 insertions(+), 42 deletions(-) diff --git a/uts/common/fs/zfs/arc.c b/uts/common/fs/zfs/arc.c index 6625debd0cb..258a89ff3ff 100644 --- a/uts/common/fs/zfs/arc.c +++ b/uts/common/fs/zfs/arc.c @@ -2784,7 +2784,7 @@ arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp, arc_done_func_t *done, const zbookmark_t *zb) { arc_buf_hdr_t *hdr; - arc_buf_t *buf; + arc_buf_t *buf = NULL; kmutex_t *hash_lock; zio_t *rzio; uint64_t guid = spa_load_guid(spa); @@ -2866,7 +2866,7 @@ top: uint64_t size = BP_GET_LSIZE(bp); arc_callback_t *acb; vdev_t *vd = NULL; - uint64_t addr; + uint64_t addr = 0; boolean_t devw = B_FALSE; if (hdr == NULL) { @@ -2981,6 +2981,10 @@ top: cb->l2rcb_zb = *zb; cb->l2rcb_flags = zio_flags; + ASSERT(addr >= VDEV_LABEL_START_SIZE && + addr + size < vd->vdev_psize - + VDEV_LABEL_END_SIZE); + /* * l2arc read. The SCL_L2ARC lock will be * released by l2arc_read_done(). @@ -3172,8 +3176,8 @@ arc_release(arc_buf_t *buf, void *tag) if (l2hdr) { mutex_enter(&l2arc_buflist_mtx); hdr->b_l2hdr = NULL; - buf_size = hdr->b_size; } + buf_size = hdr->b_size; /* * Do we have more than one buf? @@ -4172,7 +4176,7 @@ l2arc_read_done(zio_t *zio) static list_t * l2arc_list_locked(int list_num, kmutex_t **lock) { - list_t *list; + list_t *list = NULL; ASSERT(list_num >= 0 && list_num <= 3); diff --git a/uts/common/fs/zfs/dmu.c b/uts/common/fs/zfs/dmu.c index 9aebb976bb5..21cdd7c1eda 100644 --- a/uts/common/fs/zfs/dmu.c +++ b/uts/common/fs/zfs/dmu.c @@ -405,8 +405,7 @@ dmu_buf_hold_array_by_dnode(dnode_t *dn, uint64_t offset, uint64_t length, if (dn->dn_objset->os_dsl_dataset) dp = dn->dn_objset->os_dsl_dataset->ds_dir->dd_pool; - if (dp && dsl_pool_sync_context(dp)) - start = gethrtime(); + start = gethrtime(); zio = zio_root(dn->dn_objset->os_spa, NULL, NULL, ZIO_FLAG_CANFAIL); blkid = dbuf_whichblock(dn, offset); for (i = 0; i < nblks; i++) { diff --git a/uts/common/fs/zfs/dmu_objset.c b/uts/common/fs/zfs/dmu_objset.c index 00cbe0410ec..74c1192017b 100644 --- a/uts/common/fs/zfs/dmu_objset.c +++ b/uts/common/fs/zfs/dmu_objset.c @@ -1372,7 +1372,8 @@ dmu_objset_userquota_get_ids(dnode_t *dn, boolean_t before, dmu_tx_t *tx) objset_t *os = dn->dn_objset; void *data = NULL; dmu_buf_impl_t *db = NULL; - uint64_t *user, *group; + uint64_t *user = NULL; + uint64_t *group = NULL; int flags = dn->dn_id_flags; int error; boolean_t have_spill = B_FALSE; diff --git a/uts/common/fs/zfs/dsl_dataset.c b/uts/common/fs/zfs/dsl_dataset.c index 177c63e230c..cf888d2017a 100644 --- a/uts/common/fs/zfs/dsl_dataset.c +++ b/uts/common/fs/zfs/dsl_dataset.c @@ -375,7 +375,7 @@ dsl_dataset_get_ref(dsl_pool_t *dp, uint64_t dsobj, void *tag, ds = dmu_buf_get_user(dbuf); if (ds == NULL) { - dsl_dataset_t *winner; + dsl_dataset_t *winner = NULL; ds = kmem_zalloc(sizeof (dsl_dataset_t), KM_SLEEP); ds->ds_dbuf = dbuf; @@ -460,11 +460,8 @@ dsl_dataset_get_ref(dsl_pool_t *dp, uint64_t dsobj, void *tag, ds->ds_reserved = ds->ds_quota = 0; } - if (err == 0) { - winner = dmu_buf_set_user_ie(dbuf, ds, &ds->ds_phys, - dsl_dataset_evict); - } - if (err || winner) { + if (err != 0 || (winner = dmu_buf_set_user_ie(dbuf, ds, + &ds->ds_phys, dsl_dataset_evict)) != NULL) { bplist_destroy(&ds->ds_pending_deadlist); dsl_deadlist_close(&ds->ds_deadlist); if (ds->ds_prev) diff --git a/uts/common/fs/zfs/dsl_scan.c b/uts/common/fs/zfs/dsl_scan.c index aec313ae793..e1717257990 100644 --- a/uts/common/fs/zfs/dsl_scan.c +++ b/uts/common/fs/zfs/dsl_scan.c @@ -1627,7 +1627,8 @@ dsl_scan_scrub_cb(dsl_pool_t *dp, zio_priority = ZIO_PRIORITY_SCRUB; needs_io = B_TRUE; scan_delay = zfs_scrub_delay; - } else if (scn->scn_phys.scn_func == POOL_SCAN_RESILVER) { + } else { + ASSERT3U(scn->scn_phys.scn_func, ==, POOL_SCAN_RESILVER); zio_flags |= ZIO_FLAG_RESILVER; zio_priority = ZIO_PRIORITY_RESILVER; needs_io = B_FALSE; diff --git a/uts/common/fs/zfs/lzjb.c b/uts/common/fs/zfs/lzjb.c index ab3de51b725..a938fee7a3f 100644 --- a/uts/common/fs/zfs/lzjb.c +++ b/uts/common/fs/zfs/lzjb.c @@ -37,6 +37,7 @@ */ #include +#include #define MATCH_BITS 6 #define MATCH_MIN 3 @@ -50,7 +51,8 @@ lzjb_compress(void *s_start, void *d_start, size_t s_len, size_t d_len, int n) { uchar_t *src = s_start; uchar_t *dst = d_start; - uchar_t *cpy, *copymap; + uchar_t *cpy; + uchar_t *copymap = NULL; int copymask = 1 << (NBBY - 1); int mlen, offset, hash; uint16_t *hp; @@ -99,7 +101,8 @@ lzjb_decompress(void *s_start, void *d_start, size_t s_len, size_t d_len, int n) uchar_t *src = s_start; uchar_t *dst = d_start; uchar_t *d_end = (uchar_t *)d_start + d_len; - uchar_t *cpy, copymap; + uchar_t *cpy; + uchar_t copymap = 0; int copymask = 1 << (NBBY - 1); while (dst < d_end) { diff --git a/uts/common/fs/zfs/refcount.c b/uts/common/fs/zfs/refcount.c index 600132f080e..3a8e144e909 100644 --- a/uts/common/fs/zfs/refcount.c +++ b/uts/common/fs/zfs/refcount.c @@ -110,7 +110,7 @@ refcount_count(refcount_t *rc) int64_t refcount_add_many(refcount_t *rc, uint64_t number, void *holder) { - reference_t *ref; + reference_t *ref = NULL; int64_t count; if (reference_tracking_enable) { diff --git a/uts/common/fs/zfs/sa.c b/uts/common/fs/zfs/sa.c index 7cd4ab00f7c..cd3a58b5fa9 100644 --- a/uts/common/fs/zfs/sa.c +++ b/uts/common/fs/zfs/sa.c @@ -660,7 +660,8 @@ sa_build_layouts(sa_handle_t *hdl, sa_bulk_attr_t *attr_desc, int attr_count, int buf_space; sa_attr_type_t *attrs, *attrs_start; int i, lot_count; - int hdrsize, spillhdrsize; + int hdrsize; + int spillhdrsize = 0; int used; dmu_object_type_t bonustype; sa_lot_t *lot; @@ -834,7 +835,7 @@ sa_attr_table_setup(objset_t *os, sa_attr_reg_t *reg_attrs, int count) { sa_os_t *sa = os->os_sa; uint64_t sa_attr_count = 0; - uint64_t sa_reg_count; + uint64_t sa_reg_count = 0; int error = 0; uint64_t attr_value; sa_attr_table_t *tb; @@ -1639,7 +1640,8 @@ sa_modify_attrs(sa_handle_t *hdl, sa_attr_type_t newattr, sa_bulk_attr_t *attr_desc; void *old_data[2]; int bonus_attr_count = 0; - int bonus_data_size, spill_data_size; + int bonus_data_size = 0; + int spill_data_size = 0; int spill_attr_count = 0; int error; uint16_t length; diff --git a/uts/common/fs/zfs/spa.c b/uts/common/fs/zfs/spa.c index 333bbeea930..09a322bad6b 100644 --- a/uts/common/fs/zfs/spa.c +++ b/uts/common/fs/zfs/spa.c @@ -374,7 +374,7 @@ spa_prop_validate(spa_t *spa, nvlist_t *props) { nvpair_t *elem; int error = 0, reset_bootfs = 0; - uint64_t objnum; + uint64_t objnum = 0; boolean_t has_feature = B_FALSE; elem = NULL; @@ -1342,6 +1342,7 @@ spa_load_l2cache(spa_t *spa) newvdevs = kmem_alloc(nl2cache * sizeof (void *), KM_SLEEP); } else { nl2cache = 0; + newvdevs = NULL; } oldvdevs = sav->sav_vdevs; @@ -4446,7 +4447,7 @@ spa_vdev_detach(spa_t *spa, uint64_t guid, uint64_t pguid, int replace_done) vdev_t *rvd = spa->spa_root_vdev; vdev_t *vd, *pvd, *cvd, *tvd; boolean_t unspare = B_FALSE; - uint64_t unspare_guid; + uint64_t unspare_guid = 0; char *vdpath; ASSERT(spa_writeable(spa)); diff --git a/uts/common/fs/zfs/vdev_raidz.c b/uts/common/fs/zfs/vdev_raidz.c index efae5342572..5c36753407f 100644 --- a/uts/common/fs/zfs/vdev_raidz.c +++ b/uts/common/fs/zfs/vdev_raidz.c @@ -1190,7 +1190,8 @@ vdev_raidz_matrix_reconstruct(raidz_map_t *rm, int n, int nmissing, uint64_t ccount; uint8_t *dst[VDEV_RAIDZ_MAXPARITY]; uint64_t dcount[VDEV_RAIDZ_MAXPARITY]; - uint8_t log, val; + uint8_t log = 0; + uint8_t val; int ll; uint8_t *invlog[VDEV_RAIDZ_MAXPARITY]; uint8_t *p, *pp; diff --git a/uts/common/fs/zfs/zap_leaf.c b/uts/common/fs/zfs/zap_leaf.c index 19a795db825..b867ac40745 100644 --- a/uts/common/fs/zfs/zap_leaf.c +++ b/uts/common/fs/zfs/zap_leaf.c @@ -220,7 +220,7 @@ zap_leaf_array_create(zap_leaf_t *l, const char *buf, uint16_t chunk_head; uint16_t *chunkp = &chunk_head; int byten = 0; - uint64_t value; + uint64_t value = 0; int shift = (integer_size-1)*8; int len = num_integers; diff --git a/uts/common/fs/zfs/zfs_byteswap.c b/uts/common/fs/zfs/zfs_byteswap.c index acf632bdbef..6048eb12452 100644 --- a/uts/common/fs/zfs/zfs_byteswap.c +++ b/uts/common/fs/zfs/zfs_byteswap.c @@ -51,7 +51,7 @@ zfs_ace_byteswap(void *buf, size_t size, boolean_t zfs_layout) { caddr_t end; caddr_t ptr; - zfs_ace_t *zacep; + zfs_ace_t *zacep = NULL; ace_t *acep; uint16_t entry_type; size_t entry_size; diff --git a/uts/common/fs/zfs/zfs_fuid.c b/uts/common/fs/zfs/zfs_fuid.c index a853f4d7356..6eb03c2c184 100644 --- a/uts/common/fs/zfs/zfs_fuid.c +++ b/uts/common/fs/zfs/zfs_fuid.c @@ -556,9 +556,9 @@ zfs_fuid_create(zfsvfs_t *zfsvfs, uint64_t id, cred_t *cr, uint32_t fuid_idx = FUID_INDEX(id); uint32_t rid; idmap_stat status; - uint64_t idx; + uint64_t idx = 0; zfs_fuid_t *zfuid = NULL; - zfs_fuid_info_t *fuidp; + zfs_fuid_info_t *fuidp = NULL; /* * If POSIX ID, or entry is already a FUID then @@ -583,6 +583,9 @@ zfs_fuid_create(zfsvfs_t *zfsvfs, uint64_t id, cred_t *cr, if (fuidp == NULL) return (UID_NOBODY); + VERIFY3U(type, >=, ZFS_OWNER); + VERIFY3U(type, <=, ZFS_ACE_GROUP); + switch (type) { case ZFS_ACE_USER: case ZFS_ACE_GROUP: @@ -599,7 +602,7 @@ zfs_fuid_create(zfsvfs_t *zfsvfs, uint64_t id, cred_t *cr, idx = FUID_INDEX(fuidp->z_fuid_group); break; }; - domain = fuidp->z_domain_table[idx -1]; + domain = fuidp->z_domain_table[idx - 1]; } else { if (type == ZFS_OWNER || type == ZFS_ACE_USER) status = kidmap_getsidbyuid(crgetzone(cr), id, diff --git a/uts/common/fs/zfs/zfs_ioctl.c b/uts/common/fs/zfs/zfs_ioctl.c index d7c71044f92..090d6c9417a 100644 --- a/uts/common/fs/zfs/zfs_ioctl.c +++ b/uts/common/fs/zfs/zfs_ioctl.c @@ -975,7 +975,7 @@ static int zfs_secpolicy_snapshot(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr) { nvlist_t *snaps; - int error; + int error = 0; nvpair_t *pair; if (nvlist_lookup_nvlist(innvl, "snaps", &snaps) != 0) diff --git a/uts/common/fs/zfs/zfs_log.c b/uts/common/fs/zfs/zfs_log.c index 26ab78279b3..de786bf7f45 100644 --- a/uts/common/fs/zfs/zfs_log.c +++ b/uts/common/fs/zfs/zfs_log.c @@ -238,7 +238,7 @@ zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype, itx_t *itx; lr_create_t *lr; lr_acl_create_t *lracl; - size_t aclsize; + size_t aclsize = (vsecp != NULL) ? vsecp->vsa_aclentsz : 0; size_t xvatsize = 0; size_t txsize; xvattr_t *xvap = (xvattr_t *)vap; @@ -268,7 +268,6 @@ zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype, txsize = sizeof (*lr) + namesize + fuidsz + xvatsize; lrsize = sizeof (*lr); } else { - aclsize = (vsecp) ? vsecp->vsa_aclentsz : 0; txsize = sizeof (lr_acl_create_t) + namesize + fuidsz + ZIL_ACE_LENGTH(aclsize) + xvatsize; diff --git a/uts/common/fs/zfs/zfs_rlock.c b/uts/common/fs/zfs/zfs_rlock.c index 08f88b80dea..be562496b0c 100644 --- a/uts/common/fs/zfs/zfs_rlock.c +++ b/uts/common/fs/zfs/zfs_rlock.c @@ -463,7 +463,7 @@ static void zfs_range_unlock_reader(znode_t *zp, rl_t *remove) { avl_tree_t *tree = &zp->z_range_avl; - rl_t *rl, *next; + rl_t *rl, *next = NULL; uint64_t len; /* diff --git a/uts/common/fs/zfs/zfs_vfsops.c b/uts/common/fs/zfs/zfs_vfsops.c index 3278a770417..2a2501707b4 100644 --- a/uts/common/fs/zfs/zfs_vfsops.c +++ b/uts/common/fs/zfs/zfs_vfsops.c @@ -407,12 +407,18 @@ zfs_register_callbacks(vfs_t *vfsp) objset_t *os = NULL; zfsvfs_t *zfsvfs = NULL; uint64_t nbmand; - int readonly, do_readonly = B_FALSE; - int setuid, do_setuid = B_FALSE; - int exec, do_exec = B_FALSE; - int devices, do_devices = B_FALSE; - int xattr, do_xattr = B_FALSE; - int atime, do_atime = B_FALSE; + boolean_t readonly = B_FALSE; + boolean_t do_readonly = B_FALSE; + boolean_t setuid = B_FALSE; + boolean_t do_setuid = B_FALSE; + boolean_t exec = B_FALSE; + boolean_t do_exec = B_FALSE; + boolean_t devices = B_FALSE; + boolean_t do_devices = B_FALSE; + boolean_t xattr = B_FALSE; + boolean_t do_xattr = B_FALSE; + boolean_t atime = B_FALSE; + boolean_t do_atime = B_FALSE; int error = 0; ASSERT(vfsp); diff --git a/uts/common/fs/zfs/zfs_vnops.c b/uts/common/fs/zfs/zfs_vnops.c index de7812f259d..7d7168f9319 100644 --- a/uts/common/fs/zfs/zfs_vnops.c +++ b/uts/common/fs/zfs/zfs_vnops.c @@ -447,7 +447,7 @@ zfs_read(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct) zfsvfs_t *zfsvfs = zp->z_zfsvfs; objset_t *os; ssize_t n, nbytes; - int error; + int error = 0; rl_t *rl; xuio_t *xuio = NULL; @@ -599,9 +599,9 @@ zfs_write(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct) ssize_t n, nbytes; rl_t *rl; int max_blksz = zfsvfs->z_max_blksz; - int error; + int error = 0; arc_buf_t *abuf; - iovec_t *aiov; + iovec_t *aiov = NULL; xuio_t *xuio = NULL; int i_iov = 0; int iovcnt = uio->uio_iovcnt; @@ -2186,6 +2186,7 @@ zfs_readdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp, odp = (struct dirent64 *)outbuf; } else { bufsize = bytes_wanted; + outbuf = NULL; odp = (struct dirent64 *)iovp->iov_base; } eodp = (struct edirent *)odp; @@ -2627,7 +2628,7 @@ zfs_setattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr, vattr_t oldva; xvattr_t tmpxvattr; uint_t mask = vap->va_mask; - uint_t saved_mask; + uint_t saved_mask = 0; int trim_mask = 0; uint64_t new_mode; uint64_t new_uid, new_gid; From aee0fec1fb90a00bd54e6118b677781df7f27daf Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Mon, 11 Feb 2013 08:07:56 +0000 Subject: [PATCH 0117/1476] Update vendor/illumos/dist and vendor-sys/illumos/dist to illumos-gate 13953:0cc6917308f7 Illumos dtrace issues: 3529 iostat should display time used by dtrace --- cmd/stat/common/statcommon.h | 6 +++++- uts/common/dtrace/dtrace.c | 9 +++++++-- uts/common/sys/cpuvar.h | 4 ++++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/cmd/stat/common/statcommon.h b/cmd/stat/common/statcommon.h index 9ee077431dd..fd3e9d2d9ba 100644 --- a/cmd/stat/common/statcommon.h +++ b/cmd/stat/common/statcommon.h @@ -20,7 +20,10 @@ */ /* * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. - * + * Copyright (c) 2012 by Delphix. All rights reserved. + */ + +/* * Common routines for acquiring snapshots of kstats for * iostat, mpstat, and vmstat. */ @@ -221,6 +224,7 @@ struct snapshot { size_t s_iodevs_is_name_maxlen; struct sys_snapshot s_sys; struct biostats s_biostats; + size_t s_nr_active_cpus; }; /* print a message and exit with failure */ diff --git a/uts/common/dtrace/dtrace.c b/uts/common/dtrace/dtrace.c index 7a5e67ea706..4bee43839fd 100644 --- a/uts/common/dtrace/dtrace.c +++ b/uts/common/dtrace/dtrace.c @@ -5861,7 +5861,7 @@ dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1, size_t size; int vtime, onintr; volatile uint16_t *flags; - hrtime_t now; + hrtime_t now, end; /* * Kick out immediately if this CPU is still being born (in which case @@ -5876,6 +5876,8 @@ dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1, cpuid = CPU->cpu_id; onintr = CPU_ON_INTR(CPU); + CPU->cpu_dtrace_probes++; + if (!onintr && probe->dtpr_predcache != DTRACE_CACHEIDNONE && probe->dtpr_predcache == curthread->t_predcache) { /* @@ -6455,8 +6457,11 @@ dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1, buf->dtb_offset = offs + ecb->dte_size; } + end = dtrace_gethrtime(); if (vtime) - curthread->t_dtrace_start = dtrace_gethrtime(); + curthread->t_dtrace_start = end; + + CPU->cpu_dtrace_nsec += end - now; dtrace_interrupt_enable(cookie); } diff --git a/uts/common/sys/cpuvar.h b/uts/common/sys/cpuvar.h index d4075d580be..6c07bcbc8a8 100644 --- a/uts/common/sys/cpuvar.h +++ b/uts/common/sys/cpuvar.h @@ -21,6 +21,7 @@ /* * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012 by Delphix. All rights reserved. */ #ifndef _SYS_CPUVAR_H @@ -187,6 +188,9 @@ typedef struct cpu { uintptr_t cpu_dtrace_caller; /* DTrace: caller, if any */ hrtime_t cpu_dtrace_chillmark; /* DTrace: chill mark time */ hrtime_t cpu_dtrace_chilled; /* DTrace: total chill time */ + uint64_t cpu_dtrace_probes; /* DTrace: total probes fired */ + hrtime_t cpu_dtrace_nsec; /* DTrace: ns in dtrace_probe */ + volatile uint16_t cpu_mstate; /* cpu microstate */ volatile uint16_t cpu_mstate_gen; /* generation counter */ volatile hrtime_t cpu_mstate_start; /* cpu microstate start time */ From 392c880066bcb10437ac8ecfbdc2ebfe849f4e79 Mon Sep 17 00:00:00 2001 From: Rui Paulo Date: Mon, 11 Feb 2013 08:20:21 +0000 Subject: [PATCH 0118/1476] Use DEVMETHOD_END. --- sys/powerpc/wii/wii_gpio.c | 2 +- sys/powerpc/wii/wii_ipc.c | 2 +- sys/powerpc/wii/wii_pic.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sys/powerpc/wii/wii_gpio.c b/sys/powerpc/wii/wii_gpio.c index fbc311827c6..40af773562f 100644 --- a/sys/powerpc/wii/wii_gpio.c +++ b/sys/powerpc/wii/wii_gpio.c @@ -86,7 +86,7 @@ static device_method_t wiigpio_methods[] = { DEVMETHOD(gpio_pin_set, wiigpio_pin_set), DEVMETHOD(gpio_pin_toggle, wiigpio_pin_toggle), - { 0, 0 }, + DEVMETHOD_END }; static driver_t wiigpio_driver = { diff --git a/sys/powerpc/wii/wii_ipc.c b/sys/powerpc/wii/wii_ipc.c index 0db4aaddb21..7f49d31f586 100644 --- a/sys/powerpc/wii/wii_ipc.c +++ b/sys/powerpc/wii/wii_ipc.c @@ -57,7 +57,7 @@ static device_method_t wiiipc_methods[] = { DEVMETHOD(device_probe, wiiipc_probe), DEVMETHOD(device_attach, wiiipc_attach), - { 0, 0 }, + DEVMETHOD_END }; static driver_t wiiipc_driver = { diff --git a/sys/powerpc/wii/wii_pic.c b/sys/powerpc/wii/wii_pic.c index 4088677c34d..e6c6ae4de5f 100644 --- a/sys/powerpc/wii/wii_pic.c +++ b/sys/powerpc/wii/wii_pic.c @@ -73,7 +73,7 @@ static device_method_t wiipic_methods[] = { DEVMETHOD(pic_mask, wiipic_mask), DEVMETHOD(pic_unmask, wiipic_unmask), - { 0, 0 }, + DEVMETHOD_END }; static driver_t wiipic_driver = { From 711781606d6184fa330894c696f136deac7b1d8e Mon Sep 17 00:00:00 2001 From: Brooks Davis Date: Mon, 11 Feb 2013 09:45:24 +0000 Subject: [PATCH 0119/1476] Add -lheimntlm to LDADD directly. With the current binutils, symbols from libheimtlm.so are loaded because it is referenced by DT_NEEDED. This feature is not implemented in mclinker (https://code.google.com/p/mclinker/issues/detail?id=104). I encountered the same issue when linking with a recent devel/binutils invoked via clang. This was the only use of DT_NEEDED in the tree so removing it simplifies toolchain requirements. Submitted by: Pete Chou (mclinker issue) --- kerberos5/libexec/digest-service/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kerberos5/libexec/digest-service/Makefile b/kerberos5/libexec/digest-service/Makefile index 5d851b9f4ab..82a8bc4f78b 100644 --- a/kerberos5/libexec/digest-service/Makefile +++ b/kerberos5/libexec/digest-service/Makefile @@ -11,7 +11,7 @@ CFLAGS+= -I${KRB5DIR}/kdc \ DPADD= ${LIBHDB} ${LIBKDC} ${LIBHEIMIPCS} ${LIBKRB5} ${LIBROKEN} ${LIBASN1} ${LIBCRYPTO} \ ${LIBCRYPT} ${LIBVERS} LDADD= -lhdb -lkdc ${LIBHEIMIPCS} -lkrb5 -lroken -lasn1 -lcrypto -lcrypt \ - ${LIBVERS} + ${LIBVERS} -lheimntlm .include From 98744c5a8436e6d19390495cec329417bfc35fd4 Mon Sep 17 00:00:00 2001 From: Sergey Kandaurov Date: Mon, 11 Feb 2013 10:14:12 +0000 Subject: [PATCH 0120/1476] Cross-reference vfs_unbusy(9). MFC after: 1 week --- share/man/man9/vfs_busy.9 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/share/man/man9/vfs_busy.9 b/share/man/man9/vfs_busy.9 index c62ff394829..30fe79bf122 100644 --- a/share/man/man9/vfs_busy.9 +++ b/share/man/man9/vfs_busy.9 @@ -26,7 +26,7 @@ .\" .\" $FreeBSD$ .\" -.Dd June 14, 2010 +.Dd February 11, 2013 .Dt VFS_BUSY 9 .Os .Sh NAME @@ -84,6 +84,8 @@ The mount point is being unmounted .Dv ( MNTK_UNMOUNT is set). .El +.Sh SEE ALSO +.Xr vfs_unbusy 9 .Sh AUTHORS This manual page was written by .An Chad David Aq davidc@acns.ab.ca . From 24421c1c32659eed1a788f6e8089724cbe8a15d8 Mon Sep 17 00:00:00 2001 From: Gleb Smirnoff Date: Mon, 11 Feb 2013 10:58:22 +0000 Subject: [PATCH 0121/1476] Resolve source address selection in presense of CARP. Add a couple of helper functions: - carp_master() - boolean function which is true if an address is in the MASTER state. - ifa_preferred() - boolean function that compares two addresses, and is aware of CARP. Utilize ifa_preferred() in ifa_ifwithnet(). The previous version of patch also changed source address selection logic in jails using carp_master(), but we failed to negotiate this part with Bjoern. May be we will approach this problem again later. Reported & tested by: Anton Yuzhaninov Sponsored by: Nginx, Inc --- sys/net/if.c | 24 +++++++++++++++++++++--- sys/net/if_var.h | 2 +- sys/netinet/ip_carp.c | 10 ++++++++++ sys/netinet/ip_carp.h | 2 ++ 4 files changed, 34 insertions(+), 4 deletions(-) diff --git a/sys/net/if.c b/sys/net/if.c index 1c887cb1e16..57bd4e183b0 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -130,6 +130,7 @@ void (*lagg_linkstate_p)(struct ifnet *ifp, int state); /* These are external hooks for CARP. */ void (*carp_linkstate_p)(struct ifnet *ifp); void (*carp_demote_adj_p)(int, char *); +int (*carp_master_p)(struct ifaddr *); #if defined(INET) || defined(INET6) int (*carp_forus_p)(struct ifnet *ifp, u_char *dhost); int (*carp_output_p)(struct ifnet *ifp, struct mbuf *m, @@ -1706,11 +1707,13 @@ next: continue; /* * If the netmask of what we just found * is more specific than what we had before - * (if we had one) then remember the new one - * before continuing to search - * for an even better one. + * (if we had one), or if the virtual status + * of new prefix is better than of the old one, + * then remember the new one before continuing + * to search for an even better one. */ if (ifa_maybe == NULL || + ifa_preferred(ifa_maybe, ifa) || rn_refines((caddr_t)ifa->ifa_netmask, (caddr_t)ifa_maybe->ifa_netmask)) { if (ifa_maybe != NULL) @@ -1782,6 +1785,21 @@ done: return (ifa); } +/* + * See whether new ifa is better than current one: + * 1) A non-virtual one is preferred over virtual. + * 2) A virtual in master state preferred over any other state. + * + * Used in several address selecting functions. + */ +int +ifa_preferred(struct ifaddr *cur, struct ifaddr *next) +{ + + return (cur->ifa_carp && (!next->ifa_carp || + ((*carp_master_p)(next) && !(*carp_master_p)(cur)))); +} + #include /* diff --git a/sys/net/if_var.h b/sys/net/if_var.h index 7fcbd38ad7f..6ccf3644173 100644 --- a/sys/net/if_var.h +++ b/sys/net/if_var.h @@ -939,8 +939,8 @@ struct ifaddr *ifa_ifwithdstaddr(struct sockaddr *); struct ifaddr *ifa_ifwithnet(struct sockaddr *, int); struct ifaddr *ifa_ifwithroute(int, struct sockaddr *, struct sockaddr *); struct ifaddr *ifa_ifwithroute_fib(int, struct sockaddr *, struct sockaddr *, u_int); - struct ifaddr *ifaof_ifpforaddr(struct sockaddr *, struct ifnet *); +int ifa_preferred(struct ifaddr *, struct ifaddr *); int if_simloop(struct ifnet *ifp, struct mbuf *m, int af, int hlen); diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c index ac6b043b6dc..ae3da9625e4 100644 --- a/sys/netinet/ip_carp.c +++ b/sys/netinet/ip_carp.c @@ -969,6 +969,14 @@ carp_ifa_delroute(struct ifaddr *ifa) } } +int +carp_master(struct ifaddr *ifa) +{ + struct carp_softc *sc = ifa->ifa_carp; + + return (sc->sc_state == MASTER); +} + #ifdef INET /* * Broadcast a gratuitous ARP request containing @@ -2072,6 +2080,7 @@ carp_mod_cleanup(void) carp_forus_p = NULL; carp_output_p = NULL; carp_demote_adj_p = NULL; + carp_master_p = NULL; mtx_unlock(&carp_mtx); taskqueue_drain(taskqueue_swi, &carp_sendall_task); mtx_destroy(&carp_mtx); @@ -2092,6 +2101,7 @@ carp_mod_load(void) carp_attach_p = carp_attach; carp_detach_p = carp_detach; carp_demote_adj_p = carp_demote_adj; + carp_master_p = carp_master; #ifdef INET6 carp_iamatch6_p = carp_iamatch6; carp_macmatch6_p = carp_macmatch6; diff --git a/sys/netinet/ip_carp.h b/sys/netinet/ip_carp.h index 7be91c015e6..22b08b2400a 100644 --- a/sys/netinet/ip_carp.h +++ b/sys/netinet/ip_carp.h @@ -148,6 +148,7 @@ void carp_carpdev_state(struct ifnet *); void carp_input (struct mbuf *, int); int carp6_input (struct mbuf **, int *, int); int carp_output (struct ifnet *, struct mbuf *, struct sockaddr *); +int carp_master(struct ifaddr *); int carp_iamatch(struct ifaddr *, uint8_t **); struct ifaddr *carp_iamatch6(struct ifnet *, struct in6_addr *); caddr_t carp_macmatch6(struct ifnet *, struct mbuf *, const struct in6_addr *); @@ -160,6 +161,7 @@ extern int (*carp_attach_p)(struct ifaddr *, int); extern void (*carp_detach_p)(struct ifaddr *); extern void (*carp_linkstate_p)(struct ifnet *); extern void (*carp_demote_adj_p)(int, char *); +extern int (*carp_master_p)(struct ifaddr *); /* net/if_bridge.c net/if_ethersubr.c */ extern int (*carp_forus_p)(struct ifnet *, u_char *); /* net/if_ethersubr.c */ From 3748deb755cda61595e52277db2e2d5a7160db19 Mon Sep 17 00:00:00 2001 From: Oleksandr Tymoshenko Date: Mon, 11 Feb 2013 11:31:23 +0000 Subject: [PATCH 0122/1476] Add watchdog driver for Allwinner A10 --- sys/arm/allwinner/a10_wdog.c | 194 ++++++++++++++++++++++++++++++++ sys/arm/allwinner/a10_wdog.h | 35 ++++++ sys/arm/allwinner/files.a10 | 1 + sys/boot/fdt/dts/cubieboard.dts | 6 + 4 files changed, 236 insertions(+) create mode 100644 sys/arm/allwinner/a10_wdog.c create mode 100644 sys/arm/allwinner/a10_wdog.h diff --git a/sys/arm/allwinner/a10_wdog.c b/sys/arm/allwinner/a10_wdog.c new file mode 100644 index 00000000000..efc0752fdfe --- /dev/null +++ b/sys/arm/allwinner/a10_wdog.c @@ -0,0 +1,194 @@ +/*- + * Copyright (c) 2013 Oleksandr Tymoshenko + * 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#define READ(_sc, _r) bus_read_4((_sc)->res, (_r)) +#define WRITE(_sc, _r, _v) bus_write_4((_sc)->res, (_r), (_v)) + +#define WDOG_CTRL 0x00 +#define WDOG_CTRL_RESTART (1 << 0) +#define WDOG_MODE 0x04 +#define WDOG_MODE_INTVL_SHIFT 3 +#define WDOG_MODE_RST_EN (1 << 1) +#define WDOG_MODE_EN (1 << 0) + +struct a10wd_interval { + uint64_t milliseconds; + unsigned int value; +}; + +struct a10wd_interval wd_intervals[] = { + { 500, 0 }, + { 1000, 1 }, + { 2000, 2 }, + { 3000, 3 }, + { 4000, 4 }, + { 5000, 5 }, + { 6000, 6 }, + { 8000, 7 }, + { 10000, 8 }, + { 12000, 9 }, + { 14000, 10 }, + { 16000, 11 }, + { 0, 0 } /* sentinel */ +}; + +static struct a10wd_softc *a10wd_sc = NULL; + +struct a10wd_softc { + device_t dev; + struct resource * res; + struct mtx mtx; +}; + +static void a10wd_watchdog_fn(void *private, u_int cmd, int *error); + +static int +a10wd_probe(device_t dev) +{ + + printf("A10 watchdog probe\n"); + if (ofw_bus_is_compatible(dev, "allwinner,sun4i-wdt")) { + device_set_desc(dev, "Allwinner A10 Watchdog"); + return (BUS_PROBE_DEFAULT); + } + + return (ENXIO); +} + +static int +a10wd_attach(device_t dev) +{ + struct a10wd_softc *sc; + int rid; + + if (a10wd_sc != NULL) + return (ENXIO); + + sc = device_get_softc(dev); + sc->dev = dev; + + rid = 0; + sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); + if (sc->res == NULL) { + device_printf(dev, "could not allocate memory resource\n"); + return (ENXIO); + } + + a10wd_sc = sc; + mtx_init(&sc->mtx, "A10 Watchdog", "a10wd", MTX_DEF); + EVENTHANDLER_REGISTER(watchdog_list, a10wd_watchdog_fn, sc, 0); + + return (0); +} + +static void +a10wd_watchdog_fn(void *private, u_int cmd, int *error) +{ + struct a10wd_softc *sc; + uint64_t ms; + int i; + + sc = private; + mtx_lock(&sc->mtx); + + cmd &= WD_INTERVAL; + + if (cmd > 0) { + ms = ((uint64_t)1 << (cmd & WD_INTERVAL)) / 1000000; + i = 0; + while (wd_intervals[i].milliseconds && + (ms > wd_intervals[i].milliseconds)) + i++; + if (wd_intervals[i].milliseconds) { + WRITE(sc, WDOG_MODE, + (wd_intervals[i].value << WDOG_MODE_INTVL_SHIFT) | + WDOG_MODE_EN | WDOG_MODE_RST_EN); + WRITE(sc, WDOG_CTRL, WDOG_CTRL_RESTART); + } + } + else + WRITE(sc, WDOG_MODE, 0); + + mtx_unlock(&sc->mtx); +} + +void +a10wd_watchdog_reset() +{ + + if (a10wd_sc == NULL) { + printf("Reset: watchdog device has not been initialized\n"); + return; + } + + WRITE(a10wd_sc, WDOG_MODE, + (wd_intervals[0].value << WDOG_MODE_INTVL_SHIFT) | + WDOG_MODE_EN | WDOG_MODE_RST_EN); + + while(1) + ; + +} + +static device_method_t a10wd_methods[] = { + DEVMETHOD(device_probe, a10wd_probe), + DEVMETHOD(device_attach, a10wd_attach), + + DEVMETHOD_END +}; + +static driver_t a10wd_driver = { + "a10wd", + a10wd_methods, + sizeof(struct a10wd_softc), +}; +static devclass_t a10wd_devclass; + +DRIVER_MODULE(a10wd, simplebus, a10wd_driver, a10wd_devclass, 0, 0); diff --git a/sys/arm/allwinner/a10_wdog.h b/sys/arm/allwinner/a10_wdog.h new file mode 100644 index 00000000000..6c8f303244f --- /dev/null +++ b/sys/arm/allwinner/a10_wdog.h @@ -0,0 +1,35 @@ +/*- + * Copyright (c) 2013 Oleksandr Tymoshenko + * 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 __A10_WDOG_H__ +#define __A10_WDOG_H__ + +void a10wd_watchdog_reset(void); + +#endif /*__A10_WDOG_H__*/ + diff --git a/sys/arm/allwinner/files.a10 b/sys/arm/allwinner/files.a10 index 5cf20238545..9e947dec9f7 100644 --- a/sys/arm/allwinner/files.a10 +++ b/sys/arm/allwinner/files.a10 @@ -12,6 +12,7 @@ arm/arm/irq_dispatch.S standard arm/allwinner/a10_clk.c standard arm/allwinner/a10_gpio.c optional gpio arm/allwinner/a10_ehci.c optional ehci +arm/allwinner/a10_wdog.c standard arm/allwinner/timer.c standard arm/allwinner/aintc.c standard arm/allwinner/bus_space.c standard diff --git a/sys/boot/fdt/dts/cubieboard.dts b/sys/boot/fdt/dts/cubieboard.dts index 2d90720b51e..1ef8b42fc01 100644 --- a/sys/boot/fdt/dts/cubieboard.dts +++ b/sys/boot/fdt/dts/cubieboard.dts @@ -76,6 +76,12 @@ clock-frequency = < 24000000 >; }; + watchdog@01c20c90 { + compatible = "allwinner,sun4i-wdt"; + reg = <0x01c20c90 0x08>; + }; + + GPIO: gpio@01c20800 { #gpio-cells = <3>; compatible = "allwinner,sun4i-gpio"; From 2655166c71bbb0e0604e111d246c9403178644b4 Mon Sep 17 00:00:00 2001 From: Oleksandr Tymoshenko Date: Mon, 11 Feb 2013 11:33:56 +0000 Subject: [PATCH 0123/1476] A10 reset mechanism is the same for all boards in this family so remove redundant reset function implementation pointer. We might want to ressurect it later when support for other Allwinner chips is introduced. --- sys/arm/allwinner/a10_machdep.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/sys/arm/allwinner/a10_machdep.c b/sys/arm/allwinner/a10_machdep.c index 1ad9ea11f4a..528201341f3 100644 --- a/sys/arm/allwinner/a10_machdep.c +++ b/sys/arm/allwinner/a10_machdep.c @@ -49,16 +49,16 @@ __FBSDID("$FreeBSD$"); #include +#include + /* Start of address space used for bootstrap map */ #define DEVMAP_BOOTSTRAP_MAP_START 0xE0000000 -void (*a10_cpu_reset)(void); vm_offset_t initarm_lastaddr(void) { - a10_cpu_reset = NULL; return (DEVMAP_BOOTSTRAP_MAP_START - ARM_NOCACHE_KVA_SIZE); } @@ -113,10 +113,7 @@ bus_dma_get_range_nb(void) void cpu_reset() { - if (a10_cpu_reset) - (*a10_cpu_reset)(); - else - printf("no cpu_reset implementation\n"); + a10wd_watchdog_reset(); printf("Reset failed!\n"); while (1); } From b57181586ca9e82482f3286303b5b57273d4c8ee Mon Sep 17 00:00:00 2001 From: Sergey Kandaurov Date: Mon, 11 Feb 2013 12:56:23 +0000 Subject: [PATCH 0124/1476] Major update for unix_cmsg from Andrey Simonenko. Quoting the submitter: - Added tests for SCM_BINTIME, LOCAL_PEERCRED, cmsghdr.cmsg_len - Code that checks correctness of groups was corrected (getgroups(2) change) - unix_cmsg.c was completely redesigned and simplified - Use less timeout value in unix_cmsg.c for faster work - Added support for not sending data in a message, not sending data and data array associated with a cmsghdr structure in a message - Existent tests were improved - unix_cmsg.t was redesigned and simplified Correctness of unix_cmsg verified on 7.1-STABLE, 9.1-STABLE and 10-CURRENT. PR: bin/131567 Submitted by: Andrey Simonenko MFC after: 2 weeks --- tools/regression/sockets/unix_cmsg/README | 195 +- .../regression/sockets/unix_cmsg/unix_cmsg.c | 2895 +++++++++-------- .../regression/sockets/unix_cmsg/unix_cmsg.t | 91 +- 3 files changed, 1792 insertions(+), 1389 deletions(-) diff --git a/tools/regression/sockets/unix_cmsg/README b/tools/regression/sockets/unix_cmsg/README index 359da438c36..df51723b76f 100644 --- a/tools/regression/sockets/unix_cmsg/README +++ b/tools/regression/sockets/unix_cmsg/README @@ -1,127 +1,160 @@ $FreeBSD$ About unix_cmsg -================ +=============== -This program is a collection of regression tests for ancillary (control) -data for PF_LOCAL sockets (local domain or Unix domain sockets). There -are tests for stream and datagram sockets. +This program is a collection of regression tests for ancillary data +(control information) for PF_LOCAL sockets (local domain or Unix domain +sockets). There are tests for stream and datagram sockets. -Usually each test does following steps: create Server, fork Client, -Client sends something to Server, Server verifies if everything -is correct in received message. Sometimes Client sends several -messages to Server. +Usually each test does following steps: creates Server, forks Client, +Client sends something to Server, Server verifies whether everything is +correct in received message(s). It is better to change the owner of unix_cmsg to some safe user -(eg. nobody:nogroup) and set SUID and SGID bits, else some tests -can give correct results for wrong implementation. +(eg. nobody:nogroup) and set SUID and SGID bits, else some tests that +check credentials can give correct results for wrong implementation. + +It is better to run this program by a user that belongs to more +than 16 groups. Available options ================= --d Output debugging information, values of different fields of - received messages, etc. Will produce many lines of information. +usage: unix_cmsg [-dh] [-n num] [-s size] [-t type] [-z value] [testno] --h Output help message and exit. + Options are: + -d Output debugging information + -h Output the help message and exit + -n num Number of messages to send + -s size Specify size of data for IPC + -t type Specify socket type (stream, dgram) for tests + -z value Do not send data in a message (bit 0x1), do not send + data array associated with a cmsghdr structure (bit 0x2) + testno Run one test by its number (require the -t option) --t - Run tests only for the given socket type: "stream" or "dgram". - With this option it is possible to run only particular test, - not all of them. +Description +=========== --z Do not send real control data if possible. Struct cmsghdr{} - should be followed by real control data. It is not clear if - a sender should give control data in all cases (this is not - documented and an arbitrary application can choose anything). +If Client sends something to Server, then it sends 5 messages by default. +Number of messages can be changed in the -n command line option. Number +of messages will be given as N in the following descriptions. - At least for PF_LOCAL sockets' control messages with types - SCM_CREDS and SCM_TIMESTAMP the kernel does not need any - control data. This option allow to not send real control data - for SCM_CREDS and SCM_TIMESTAMP control messages. +If Client sends something to Server, then it sends some data (few bytes) +in each message by default. The size of this data can be changed by the -s +command line option. The "-s 0" command line option means, that Client will +send zero bytes represented by { NULL, 0 } value of struct iovec{}, referenced +by the msg_iov field from struct msghdr{}. The "-z 1" or "-z 3" command line +option means, that Client will send zero bytes represented by the NULL value +in the msg_iov field from struct msghdr{}. -Description of tests -==================== +If Client sends some ancillary data object, then this ancillary data object +always has associated data array by default. The "-z 2" or "-z 3" option +means, that Client will not send associated data array if possible. For SOCK_STREAM sockets: ----------------------- 1: Sending, receiving cmsgcred - Client connects to Server and sends two messages with data and - control message with SCM_CREDS type to Server. Server should - receive two messages, in both messages there should be data and - control message with SCM_CREDS type followed by struct cmsgcred{} - and this structure should contain correct information. + Client connects to Server and sends N messages with SCM_CREDS ancillary + data object. Server should receive N messages, each message should + have SCM_CREDS ancillary data object followed by struct cmsgcred{}. - 2: Receiving sockcred (listening socket has LOCAL_CREDS) + 2: Receiving sockcred (listening socket) - Server creates listen socket and set socket option LOCAL_CREDS - for it. Client connects to Server and sends two messages with data - to Server. Server should receive two messages, in first message - there should be data and control message with SCM_CREDS type followed - by struct sockcred{} and this structure should contain correct - information, in second message there should be data and no control - message. + Server creates a listening stream socket and sets the LOCAL_CREDS + socket option for it. Client connects to Server two times, each time + it sends N messages. Server accepts two connections and receives N + messages from each connection. The first message from each connection + should have SCM_CREDS ancillary data object followed by struct sockcred{}, + next messages from the same connection should not have ancillary data. - 3: Receiving sockcred (accepted socket has LOCAL_CREDS) + 3: Receiving sockcred (accepted socket) - Client connects to Server and sends two messages with data. Server - accepts connection and set socket option LOCAL_CREDS for just accepted - socket (here synchronization is used, to allow Client to see just set - flag on Server's socket before sending messages to Server). Server - should receive two messages, in first message there should be data and - control message with SOCK_CRED type followed by struct sockcred{} and - this structure should contain correct information, in second message - there should be data and no control message. + Client connects to Server. Server accepts connection and sets the + LOCAL_CREDS socket option for just accepted socket. Client sends N + messages to Server. Server should receive N messages, the first + message should have SCM_CREDS ancillary data object followed by + struct sockcred{}, next messages should not have ancillary data. 4: Sending cmsgcred, receiving sockcred - Server creates listen socket and set socket option LOCAL_CREDS - for it. Client connects to Server and sends one message with data - and control message with SCM_CREDS type to Server. Server should - receive one message with data and control message with SCM_CREDS type - followed by struct sockcred{} and this structure should contain - correct information. + Server creates a listening stream socket and sets the LOCAL_CREDS + socket option for it. Client connects to Server and sends N messages + with SCM_CREDS ancillary data object. Server should receive N messages, + the first message should have SCM_CREDS ancillary data object followed + by struct sockcred{}, each of next messages should have SCM_CREDS + ancillary data object followed by struct cmsgcred{}. - 5: Sending, receiving timestamp + 5: Sending, receiving timeval - Client connects to Server and sends message with data and control - message with SCM_TIMESTAMP type to Server. Server should receive - message with data and control message with SCM_TIMESTAMP type - followed by struct timeval{}. + Client connects to Server and sends message with SCM_TIMESTAMP ancillary + data object. Server should receive one message with SCM_TIMESTAMP + ancillary data object followed by struct timeval{}. + + 6: Sending, receiving bintime + + Client connects to Server and sends message with SCM_BINTIME ancillary + data object. Server should receive one message with SCM_BINTIME + ancillary data object followed by struct bintime{}. + + 7: Checking cmsghdr.cmsg_len + + Client connects to Server and tries to send several messages with + SCM_CREDS ancillary data object that has wrong cmsg_len field in its + struct cmsghdr{}. All these attempts should fail, since cmsg_len + in all requests is less than CMSG_LEN(0). + + 8: Check LOCAL_PEERCRED socket option + + This test does not use ancillary data, but can be implemented here. + Client connects to Server. Both Client and Server verify that + credentials of the peer are correct using LOCAL_PEERCRED socket option. For SOCK_DGRAM sockets: ---------------------- 1: Sending, receiving cmsgcred - Client sends to Server two messages with data and control message - with SCM_CREDS type to Server. Server should receive two messages, - in both messages there should be data and control message with - SCM_CREDS type followed by struct cmsgcred{} and this structure - should contain correct information. + Client connects to Server and sends N messages with SCM_CREDS ancillary + data object. Server should receive N messages, each message should + have SCM_CREDS ancillary data object followed by struct cmsgcred{}. 2: Receiving sockcred - Server creates datagram socket and set socket option LOCAL_CREDS - for it. Client sends two messages with data to Server. Server should - receive two messages, in both messages there should be data and control - message with SCM_CREDS type followed by struct sockcred{} and this - structure should contain correct information. + Server creates datagram socket and sets the LOCAL_CREDS socket option + for it. Client sends N messages to Server. Server should receive N + messages, each message should have SCM_CREDS ancillary data object + followed by struct sockcred{}. 3: Sending cmsgcred, receiving sockcred - - Server creates datagram socket and set socket option LOCAL_CREDS - for it. Client sends one message with data and control message with - SOCK_CREDS type to Server. Server should receive one message with - data and control message with SCM_CREDS type followed by struct - sockcred{} and this structure should contain correct information. - 4: Sending, receiving timestamp + Server creates datagram socket and sets the LOCAL_CREDS socket option + for it. Client sends N messages with SCM_CREDS ancillary data object + to Server. Server should receive N messages, the first message should + have SCM_CREDS ancillary data object followed by struct sockcred{}, + each of next messages should have SCM_CREDS ancillary data object + followed by struct cmsgcred{}. - Client sends message with data and control message with SCM_TIMESTAMP - type to Server. Server should receive message with data and control - message with SCM_TIMESTAMP type followed by struct timeval{}. + 4: Sending, receiving timeval + + Client sends one message with SCM_TIMESTAMP ancillary data object + to Server. Server should receive one message with SCM_TIMESTAMP + ancillary data object followed by struct timeval{}. + + 5: Sending, receiving bintime + + Client sends one message with SCM_BINTIME ancillary data object + to Server. Server should receive one message with SCM_BINTIME + ancillary data object followed by struct bintime{}. + + 6: Checking cmsghdr.cmsg_len + + Client tries to send Server several messages with SCM_CREDS ancillary + data object that has wrong cmsg_len field in its struct cmsghdr{}. + All these attempts should fail, since cmsg_len in all requests is less + than CMSG_LEN(0). - Andrey Simonenko -simon@comsys.ntu-kpi.kiev.ua +andreysimonenko@users.sourceforge.net diff --git a/tools/regression/sockets/unix_cmsg/unix_cmsg.c b/tools/regression/sockets/unix_cmsg/unix_cmsg.c index 06728d75a8f..d91cef496a0 100644 --- a/tools/regression/sockets/unix_cmsg/unix_cmsg.c +++ b/tools/regression/sockets/unix_cmsg/unix_cmsg.c @@ -27,48 +27,46 @@ #include __FBSDID("$FreeBSD$"); -#include +#include #include #include +#include #include +#include #include #include -#include #include #include #include +#include #include #include -#include +#include #include #include +#include #include #include #include #include -#include #include /* * There are tables with tests descriptions and pointers to test * functions. Each t_*() function returns 0 if its test passed, - * -1 if its test failed (something wrong was found in local domain - * control messages), -2 if some system error occurred. If test - * function returns -2, then a program exits. + * -1 if its test failed, -2 if some system error occurred. + * If a test function returns -2, then a program exits. * - * Each test function completely control what to do (eg. fork or - * do not fork a client process). If a test function forks a client - * process, then it waits for its termination. If a return code of a - * client process is not equal to zero, or if a client process was - * terminated by a signal, then test function returns -2. + * If a test function forks a client process, then it waits for its + * termination. If a return code of a client process is not equal + * to zero, or if a client process was terminated by a signal, then + * a test function returns -1 or -2 depending on exit status of + * a client process. * - * Each test function and complete program are not optimized - * a lot to allow easy to modify tests. - * - * Each function which can block, is run under TIMEOUT, if timeout - * occurs, then test function returns -2 or a client process exits - * with nonzero return code. + * Each function which can block, is run under TIMEOUT. If timeout + * occurs, then a test function returns -2 or a client process exits + * with a non-zero return code. */ #ifndef LISTENQ @@ -76,207 +74,290 @@ __FBSDID("$FreeBSD$"); #endif #ifndef TIMEOUT -# define TIMEOUT 60 +# define TIMEOUT 2 #endif -#define EXTRA_CMSG_SPACE 512 /* Memory for not expected control data. */ - -static int t_cmsgcred(void), t_sockcred_stream1(void); -static int t_sockcred_stream2(void), t_cmsgcred_sockcred(void); -static int t_sockcred_dgram(void), t_timestamp(void); +static int t_cmsgcred(void); +static int t_sockcred_1(void); +static int t_sockcred_2(void); +static int t_cmsgcred_sockcred(void); +static int t_timeval(void); +static int t_bintime(void); +static int t_cmsg_len(void); +static int t_peercred(void); struct test_func { - int (*func)(void); /* Pointer to function. */ - const char *desc; /* Test description. */ + int (*func)(void); + const char *desc; }; -static struct test_func test_stream_tbl[] = { - { NULL, " 0: All tests" }, - { t_cmsgcred, " 1: Sending, receiving cmsgcred" }, - { t_sockcred_stream1, " 2: Receiving sockcred (listening socket has LOCAL_CREDS)" }, - { t_sockcred_stream2, " 3: Receiving sockcred (accepted socket has LOCAL_CREDS)" }, - { t_cmsgcred_sockcred, " 4: Sending cmsgcred, receiving sockcred" }, - { t_timestamp, " 5: Sending, receiving timestamp" }, - { NULL, NULL } +static const struct test_func test_stream_tbl[] = { + { + .func = NULL, + .desc = "All tests" + }, + { + .func = t_cmsgcred, + .desc = "Sending, receiving cmsgcred" + }, + { + .func = t_sockcred_1, + .desc = "Receiving sockcred (listening socket)" + }, + { + .func = t_sockcred_2, + .desc = "Receiving sockcred (accepted socket)" + }, + { + .func = t_cmsgcred_sockcred, + .desc = "Sending cmsgcred, receiving sockcred" + }, + { + .func = t_timeval, + .desc = "Sending, receiving timeval" + }, + { + .func = t_bintime, + .desc = "Sending, receiving bintime" + }, + { + .func = t_cmsg_len, + .desc = "Check cmsghdr.cmsg_len" + }, + { + .func = t_peercred, + .desc = "Check LOCAL_PEERCRED socket option" + } }; -static struct test_func test_dgram_tbl[] = { - { NULL, " 0: All tests" }, - { t_cmsgcred, " 1: Sending, receiving cmsgcred" }, - { t_sockcred_dgram, " 2: Receiving sockcred" }, - { t_cmsgcred_sockcred, " 3: Sending cmsgcred, receiving sockcred" }, - { t_timestamp, " 4: Sending, receiving timestamp" }, - { NULL, NULL } +#define TEST_STREAM_TBL_SIZE \ + (sizeof(test_stream_tbl) / sizeof(test_stream_tbl[0])) + +static const struct test_func test_dgram_tbl[] = { + { + .func = NULL, + .desc = "All tests" + }, + { + .func = t_cmsgcred, + .desc = "Sending, receiving cmsgcred" + }, + { + .func = t_sockcred_2, + .desc = "Receiving sockcred" + }, + { + .func = t_cmsgcred_sockcred, + .desc = "Sending cmsgcred, receiving sockcred" + }, + { + .func = t_timeval, + .desc = "Sending, receiving timeval" + }, + { + .func = t_bintime, + .desc = "Sending, receiving bintime" + }, + { + .func = t_cmsg_len, + .desc = "Check cmsghdr.cmsg_len" + } }; -#define TEST_STREAM_NO_MAX (sizeof(test_stream_tbl) / sizeof(struct test_func) - 2) -#define TEST_DGRAM_NO_MAX (sizeof(test_dgram_tbl) / sizeof(struct test_func) - 2) +#define TEST_DGRAM_TBL_SIZE \ + (sizeof(test_dgram_tbl) / sizeof(test_dgram_tbl[0])) -static const char *myname = "SERVER"; /* "SERVER" or "CLIENT" */ +static bool debug = false; +static bool server_flag = true; +static bool send_data_flag = true; +static bool send_array_flag = true; +static bool failed_flag = false; -static int debug = 0; /* 1, if -d. */ -static int no_control_data = 0; /* 1, if -z. */ +static int sock_type; +static const char *sock_type_str; -static u_int nfailed = 0; /* Number of failed tests. */ +static const char *proc_name; -static int sock_type; /* SOCK_STREAM or SOCK_DGRAM */ -static const char *sock_type_str; /* "SOCK_STREAM" or "SOCK_DGRAN" */ +static char work_dir[] = _PATH_TMP "unix_cmsg.XXXXXXX"; +static int serv_sock_fd; +static struct sockaddr_un serv_addr_sun; -static char tempdir[] = "/tmp/unix_cmsg.XXXXXXX"; -static char serv_sock_path[PATH_MAX]; +static struct { + char *buf_send; + char *buf_recv; + size_t buf_size; + u_int msg_num; +} ipc_msg; -static char ipc_message[] = "hello"; +#define IPC_MSG_NUM_DEF 5 +#define IPC_MSG_NUM_MAX 10 +#define IPC_MSG_SIZE_DEF 7 +#define IPC_MSG_SIZE_MAX 128 -#define IPC_MESSAGE_SIZE (sizeof(ipc_message)) +static struct { + uid_t uid; + uid_t euid; + gid_t gid; + gid_t egid; + gid_t *gid_arr; + int gid_num; +} proc_cred; -static struct sockaddr_un servaddr; /* Server address. */ +static pid_t client_pid; -static sigjmp_buf env_alrm; +#define SYNC_SERVER 0 +#define SYNC_CLIENT 1 +#define SYNC_RECV 0 +#define SYNC_SEND 1 -static uid_t my_uid; -static uid_t my_euid; -static gid_t my_gid; -static gid_t my_egid; +static int sync_fd[2][2]; -/* - * my_gids[0] is EGID, next items are supplementary GIDs, - * my_ngids determines valid items in my_gids array. - */ -static gid_t my_gids[NGROUPS_MAX]; -static int my_ngids; - -static pid_t client_pid; /* PID of forked client. */ - -#define dbgmsg(x) do { \ - if (debug) \ - logmsgx x ; \ -} while (/* CONSTCOND */0) +#define LOGMSG_SIZE 128 static void logmsg(const char *, ...) __printflike(1, 2); static void logmsgx(const char *, ...) __printflike(1, 2); +static void dbgmsg(const char *, ...) __printflike(1, 2); static void output(const char *, ...) __printflike(1, 2); -extern char *__progname; /* The name of program. */ - -/* - * Output the help message (-h switch). - */ static void -usage(int quick) +usage(bool verbose) { - const struct test_func *test_func; + u_int i; - fprintf(stderr, "Usage: %s [-dhz] [-t ] [testno]\n", - __progname); - if (quick) + printf("usage: %s [-dh] [-n num] [-s size] [-t type] " + "[-z value] [testno]\n", getprogname()); + if (!verbose) return; - fprintf(stderr, "\n Options are:\n\ - -d\t\t\tOutput debugging information\n\ - -h\t\t\tOutput this help message and exit\n\ - -t \t\tRun test only for the given socket type:\n\ -\t\t\tstream or dgram\n\ - -z\t\t\tDo not send real control data if possible\n\n"); - fprintf(stderr, " Available tests for stream sockets:\n"); - for (test_func = test_stream_tbl; test_func->desc != NULL; ++test_func) - fprintf(stderr, " %s\n", test_func->desc); - fprintf(stderr, "\n Available tests for datagram sockets:\n"); - for (test_func = test_dgram_tbl; test_func->desc != NULL; ++test_func) - fprintf(stderr, " %s\n", test_func->desc); + printf("\n Options are:\n\ + -d Output debugging information\n\ + -h Output the help message and exit\n\ + -n num Number of messages to send\n\ + -s size Specify size of data for IPC\n\ + -t type Specify socket type (stream, dgram) for tests\n\ + -z value Do not send data in a message (bit 0x1), do not send\n\ + data array associated with a cmsghdr structure (bit 0x2)\n\ + testno Run one test by its number (require the -t option)\n\n"); + printf(" Available tests for stream sockets:\n"); + for (i = 0; i < TEST_STREAM_TBL_SIZE; ++i) + printf(" %u: %s\n", i, test_stream_tbl[i].desc); + printf("\n Available tests for datagram sockets:\n"); + for (i = 0; i < TEST_DGRAM_TBL_SIZE; ++i) + printf(" %u: %s\n", i, test_dgram_tbl[i].desc); } -/* - * printf-like function for outputting to STDOUT_FILENO. - */ static void output(const char *format, ...) { - char buf[128]; + char buf[LOGMSG_SIZE]; va_list ap; va_start(ap, format); if (vsnprintf(buf, sizeof(buf), format, ap) < 0) - err(EX_SOFTWARE, "output: vsnprintf failed"); + err(EXIT_FAILURE, "output: vsnprintf failed"); write(STDOUT_FILENO, buf, strlen(buf)); va_end(ap); } -/* - * printf-like function for logging, also outputs message for errno. - */ static void logmsg(const char *format, ...) { - char buf[128]; + char buf[LOGMSG_SIZE]; va_list ap; int errno_save; - errno_save = errno; /* Save errno. */ - + errno_save = errno; va_start(ap, format); if (vsnprintf(buf, sizeof(buf), format, ap) < 0) - err(EX_SOFTWARE, "logmsg: vsnprintf failed"); + err(EXIT_FAILURE, "logmsg: vsnprintf failed"); if (errno_save == 0) - output("%s: %s\n", myname, buf); + output("%s: %s\n", proc_name, buf); else - output("%s: %s: %s\n", myname, buf, strerror(errno_save)); + output("%s: %s: %s\n", proc_name, buf, strerror(errno_save)); va_end(ap); - - errno = errno_save; /* Restore errno. */ + errno = errno_save; +} + +static void +vlogmsgx(const char *format, va_list ap) +{ + char buf[LOGMSG_SIZE]; + + if (vsnprintf(buf, sizeof(buf), format, ap) < 0) + err(EXIT_FAILURE, "logmsgx: vsnprintf failed"); + output("%s: %s\n", proc_name, buf); + } -/* - * printf-like function for logging, do not output message for errno. - */ static void logmsgx(const char *format, ...) { - char buf[128]; va_list ap; va_start(ap, format); - if (vsnprintf(buf, sizeof(buf), format, ap) < 0) - err(EX_SOFTWARE, "logmsgx: vsnprintf failed"); - output("%s: %s\n", myname, buf); + vlogmsgx(format, ap); va_end(ap); } -/* - * Run tests from testno1 to testno2. - */ -static int -run_tests(u_int testno1, u_int testno2) +static void +dbgmsg(const char *format, ...) { - const struct test_func *test_func; - u_int i, nfailed1; + va_list ap; + + if (debug) { + va_start(ap, format); + vlogmsgx(format, ap); + va_end(ap); + } +} + +static int +run_tests(int type, u_int testno1) +{ + const struct test_func *tf; + u_int i, testno2, failed_num; + + sock_type = type; + if (type == SOCK_STREAM) { + sock_type_str = "SOCK_STREAM"; + tf = test_stream_tbl; + i = TEST_STREAM_TBL_SIZE - 1; + } else { + sock_type_str = "SOCK_DGRAM"; + tf = test_dgram_tbl; + i = TEST_DGRAM_TBL_SIZE - 1; + } + if (testno1 == 0) { + testno1 = 1; + testno2 = i; + } else + testno2 = testno1; output("Running tests for %s sockets:\n", sock_type_str); - test_func = (sock_type == SOCK_STREAM ? - test_stream_tbl : test_dgram_tbl) + testno1; - - nfailed1 = 0; - for (i = testno1; i <= testno2; ++test_func, ++i) { - output(" %s\n", test_func->desc); - switch (test_func->func()) { + failed_num = 0; + for (i = testno1, tf += testno1; i <= testno2; ++tf, ++i) { + output(" %u: %s\n", i, tf->desc); + switch (tf->func()) { case -1: - ++nfailed1; + ++failed_num; break; case -2: - logmsgx("some system error occurred, exiting"); + logmsgx("some system error or timeout occurred"); return (-1); } } - nfailed += nfailed1; + if (failed_num != 0) + failed_flag = true; if (testno1 != testno2) { - if (nfailed1 == 0) - output("-- all tests were passed!\n"); + if (failed_num == 0) + output("-- all tests passed!\n"); else - output("-- %u test%s failed!\n", nfailed1, - nfailed1 == 1 ? "" : "s"); + output("-- %u test%s failed!\n", + failed_num, failed_num == 1 ? "" : "s"); } else { - if (nfailed == 0) - output("-- test was passed!\n"); + if (failed_num == 0) + output("-- test passed!\n"); else output("-- test failed!\n"); } @@ -284,183 +365,322 @@ run_tests(u_int testno1, u_int testno2) return (0); } -/* ARGSUSED */ -static void -sig_alrm(int signo __unused) +static int +init(void) { - siglongjmp(env_alrm, 1); + struct sigaction sigact; + size_t idx; + int rv; + + proc_name = "SERVER"; + + sigact.sa_handler = SIG_IGN; + sigact.sa_flags = 0; + sigemptyset(&sigact.sa_mask); + if (sigaction(SIGPIPE, &sigact, (struct sigaction *)NULL) < 0) { + logmsg("init: sigaction"); + return (-1); + } + + if (ipc_msg.buf_size == 0) + ipc_msg.buf_send = ipc_msg.buf_recv = NULL; + else { + ipc_msg.buf_send = malloc(ipc_msg.buf_size); + ipc_msg.buf_recv = malloc(ipc_msg.buf_size); + if (ipc_msg.buf_send == NULL || ipc_msg.buf_recv == NULL) { + logmsg("init: malloc"); + return (-1); + } + for (idx = 0; idx < ipc_msg.buf_size; ++idx) + ipc_msg.buf_send[idx] = (char)idx; + } + + proc_cred.uid = getuid(); + proc_cred.euid = geteuid(); + proc_cred.gid = getgid(); + proc_cred.egid = getegid(); + proc_cred.gid_num = getgroups(0, (gid_t *)NULL); + if (proc_cred.gid_num < 0) { + logmsg("init: getgroups"); + return (-1); + } + proc_cred.gid_arr = malloc(proc_cred.gid_num * + sizeof(*proc_cred.gid_arr)); + if (proc_cred.gid_arr == NULL) { + logmsg("init: malloc"); + return (-1); + } + if (getgroups(proc_cred.gid_num, proc_cred.gid_arr) < 0) { + logmsg("init: getgroups"); + return (-1); + } + + memset(&serv_addr_sun, 0, sizeof(serv_addr_sun)); + rv = snprintf(serv_addr_sun.sun_path, sizeof(serv_addr_sun.sun_path), + "%s/%s", work_dir, proc_name); + if (rv < 0) { + logmsg("init: snprintf"); + return (-1); + } + if ((size_t)rv >= sizeof(serv_addr_sun.sun_path)) { + logmsgx("init: not enough space for socket pathname"); + return (-1); + } + serv_addr_sun.sun_family = PF_LOCAL; + serv_addr_sun.sun_len = SUN_LEN(&serv_addr_sun); + + return (0); } -/* - * Initialize signals handlers. - */ -static void -sig_init(void) +static int +client_fork(void) { - struct sigaction sa; + int fd1, fd2; - sa.sa_handler = SIG_IGN; - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - if (sigaction(SIGPIPE, &sa, (struct sigaction *)NULL) < 0) - err(EX_OSERR, "sigaction(SIGPIPE)"); + if (pipe(sync_fd[SYNC_SERVER]) < 0 || + pipe(sync_fd[SYNC_CLIENT]) < 0) { + logmsg("client_fork: pipe"); + return (-1); + } + client_pid = fork(); + if (client_pid == (pid_t)-1) { + logmsg("client_fork: fork"); + return (-1); + } + if (client_pid == 0) { + proc_name = "CLIENT"; + server_flag = false; + fd1 = sync_fd[SYNC_SERVER][SYNC_RECV]; + fd2 = sync_fd[SYNC_CLIENT][SYNC_SEND]; + } else { + fd1 = sync_fd[SYNC_SERVER][SYNC_SEND]; + fd2 = sync_fd[SYNC_CLIENT][SYNC_RECV]; + } + if (close(fd1) < 0 || close(fd2) < 0) { + logmsg("client_fork: close"); + return (-1); + } + return (client_pid != 0); +} - sa.sa_handler = sig_alrm; - if (sigaction(SIGALRM, &sa, (struct sigaction *)NULL) < 0) - err(EX_OSERR, "sigaction(SIGALRM)"); +static void +client_exit(int rv) +{ + if (close(sync_fd[SYNC_SERVER][SYNC_SEND]) < 0 || + close(sync_fd[SYNC_CLIENT][SYNC_RECV]) < 0) { + logmsg("client_exit: close"); + rv = -1; + } + rv = rv == 0 ? EXIT_SUCCESS : -rv; + dbgmsg("exit: code %d", rv); + _exit(rv); +} + +static int +client_wait(void) +{ + int status; + pid_t pid; + + dbgmsg("waiting for client"); + + if (close(sync_fd[SYNC_SERVER][SYNC_RECV]) < 0 || + close(sync_fd[SYNC_CLIENT][SYNC_SEND]) < 0) { + logmsg("client_wait: close"); + return (-1); + } + + pid = waitpid(client_pid, &status, 0); + if (pid == (pid_t)-1) { + logmsg("client_wait: waitpid"); + return (-1); + } + + if (WIFEXITED(status)) { + if (WEXITSTATUS(status) != EXIT_SUCCESS) { + logmsgx("client exit status is %d", + WEXITSTATUS(status)); + return (-WEXITSTATUS(status)); + } + } else { + if (WIFSIGNALED(status)) + logmsgx("abnormal termination of client, signal %d%s", + WTERMSIG(status), WCOREDUMP(status) ? + " (core file generated)" : ""); + else + logmsgx("termination of client, unknown status"); + return (-1); + } + + return (0); } int main(int argc, char *argv[]) { const char *errstr; - int opt, dgramflag, streamflag; - u_int testno1, testno2; + u_int testno, zvalue; + int opt, rv; + bool dgram_flag, stream_flag; - dgramflag = streamflag = 0; - while ((opt = getopt(argc, argv, "dht:z")) != -1) + ipc_msg.buf_size = IPC_MSG_SIZE_DEF; + ipc_msg.msg_num = IPC_MSG_NUM_DEF; + dgram_flag = stream_flag = false; + while ((opt = getopt(argc, argv, "dhn:s:t:z:")) != -1) switch (opt) { case 'd': - debug = 1; + debug = true; break; case 'h': - usage(0); - return (EX_OK); + usage(true); + return (EXIT_SUCCESS); + case 'n': + ipc_msg.msg_num = strtonum(optarg, 1, + IPC_MSG_NUM_MAX, &errstr); + if (errstr != NULL) + errx(EXIT_FAILURE, "option -n: number is %s", + errstr); + break; + case 's': + ipc_msg.buf_size = strtonum(optarg, 0, + IPC_MSG_SIZE_MAX, &errstr); + if (errstr != NULL) + errx(EXIT_FAILURE, "option -s: number is %s", + errstr); + break; case 't': if (strcmp(optarg, "stream") == 0) - streamflag = 1; + stream_flag = true; else if (strcmp(optarg, "dgram") == 0) - dgramflag = 1; + dgram_flag = true; else - errx(EX_USAGE, "wrong socket type in -t option"); + errx(EXIT_FAILURE, "option -t: " + "wrong socket type"); break; case 'z': - no_control_data = 1; + zvalue = strtonum(optarg, 0, 3, &errstr); + if (errstr != NULL) + errx(EXIT_FAILURE, "option -z: number is %s", + errstr); + if (zvalue & 0x1) + send_data_flag = false; + if (zvalue & 0x2) + send_array_flag = false; break; - case '?': default: - usage(1); - return (EX_USAGE); + usage(false); + return (EXIT_FAILURE); } if (optind < argc) { if (optind + 1 != argc) - errx(EX_USAGE, "too many arguments"); - testno1 = strtonum(argv[optind], 0, UINT_MAX, &errstr); + errx(EXIT_FAILURE, "too many arguments"); + testno = strtonum(argv[optind], 0, UINT_MAX, &errstr); if (errstr != NULL) - errx(EX_USAGE, "wrong test number: %s", errstr); + errx(EXIT_FAILURE, "test number is %s", errstr); + if (stream_flag && testno >= TEST_STREAM_TBL_SIZE) + errx(EXIT_FAILURE, "given test %u for stream " + "sockets does not exist", testno); + if (dgram_flag && testno >= TEST_DGRAM_TBL_SIZE) + errx(EXIT_FAILURE, "given test %u for datagram " + "sockets does not exist", testno); } else - testno1 = 0; + testno = 0; - if (dgramflag == 0 && streamflag == 0) - dgramflag = streamflag = 1; - - if (dgramflag && streamflag && testno1 != 0) - errx(EX_USAGE, "you can use particular test, only with datagram or stream sockets"); - - if (streamflag) { - if (testno1 > TEST_STREAM_NO_MAX) - errx(EX_USAGE, "given test %u for stream sockets does not exist", - testno1); - } else { - if (testno1 > TEST_DGRAM_NO_MAX) - errx(EX_USAGE, "given test %u for datagram sockets does not exist", - testno1); + if (!dgram_flag && !stream_flag) { + if (testno != 0) + errx(EXIT_FAILURE, "particular test number " + "can be used with the -t option only"); + dgram_flag = stream_flag = true; } - my_uid = getuid(); - my_euid = geteuid(); - my_gid = getgid(); - my_egid = getegid(); - switch (my_ngids = getgroups(sizeof(my_gids) / sizeof(my_gids[0]), my_gids)) { - case -1: - err(EX_SOFTWARE, "getgroups"); - /* NOTREACHED */ - case 0: - errx(EX_OSERR, "getgroups returned 0 groups"); + if (mkdtemp(work_dir) == NULL) + err(EXIT_FAILURE, "mkdtemp(%s)", work_dir); + + rv = EXIT_FAILURE; + if (init() < 0) + goto done; + + if (stream_flag) + if (run_tests(SOCK_STREAM, testno) < 0) + goto done; + if (dgram_flag) + if (run_tests(SOCK_DGRAM, testno) < 0) + goto done; + + rv = EXIT_SUCCESS; +done: + if (rmdir(work_dir) < 0) { + logmsg("rmdir(%s)", work_dir); + rv = EXIT_FAILURE; } - - sig_init(); - - if (mkdtemp(tempdir) == NULL) - err(EX_OSERR, "mkdtemp"); - - if (streamflag) { - sock_type = SOCK_STREAM; - sock_type_str = "SOCK_STREAM"; - if (testno1 == 0) { - testno1 = 1; - testno2 = TEST_STREAM_NO_MAX; - } else - testno2 = testno1; - if (run_tests(testno1, testno2) < 0) - goto failed; - testno1 = 0; - } - - if (dgramflag) { - sock_type = SOCK_DGRAM; - sock_type_str = "SOCK_DGRAM"; - if (testno1 == 0) { - testno1 = 1; - testno2 = TEST_DGRAM_NO_MAX; - } else - testno2 = testno1; - if (run_tests(testno1, testno2) < 0) - goto failed; - } - - if (rmdir(tempdir) < 0) { - logmsg("rmdir(%s)", tempdir); - return (EX_OSERR); - } - - return (nfailed ? EX_OSERR : EX_OK); - -failed: - if (rmdir(tempdir) < 0) - logmsg("rmdir(%s)", tempdir); - return (EX_OSERR); + return (failed_flag ? EXIT_FAILURE : rv); } -/* - * Create PF_LOCAL socket, if sock_path is not equal to NULL, then - * bind() it. Return socket address in addr. Return file descriptor - * or -1 if some error occurred. - */ static int -create_socket(char *sock_path, size_t sock_path_len, struct sockaddr_un *addr) +socket_close(int fd) { - int rv, fd; + int rv; - if ((fd = socket(PF_LOCAL, sock_type, 0)) < 0) { - logmsg("create_socket: socket(PF_LOCAL, %s, 0)", sock_type_str); + rv = 0; + if (close(fd) < 0) { + logmsg("socket_close: close"); + rv = -1; + } + if (server_flag && fd == serv_sock_fd) + if (unlink(serv_addr_sun.sun_path) < 0) { + logmsg("socket_close: unlink(%s)", + serv_addr_sun.sun_path); + rv = -1; + } + return (rv); +} + +static int +socket_create(void) +{ + struct timeval tv; + int fd; + + fd = socket(PF_LOCAL, sock_type, 0); + if (fd < 0) { + logmsg("socket_create: socket(PF_LOCAL, %s, 0)", sock_type_str); return (-1); } + if (server_flag) + serv_sock_fd = fd; - if (sock_path != NULL) { - if ((rv = snprintf(sock_path, sock_path_len, "%s/%s", - tempdir, myname)) < 0) { - logmsg("create_socket: snprintf failed"); - goto failed; - } - if ((size_t)rv >= sock_path_len) { - logmsgx("create_socket: too long path name for given buffer"); + tv.tv_sec = TIMEOUT; + tv.tv_usec = 0; + if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0 || + setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0) { + logmsg("socket_create: setsockopt(SO_RCVTIMEO/SO_SNDTIMEO)"); + goto failed; + } + + if (server_flag) { + if (bind(fd, (struct sockaddr *)&serv_addr_sun, + serv_addr_sun.sun_len) < 0) { + logmsg("socket_create: bind(%s)", + serv_addr_sun.sun_path); goto failed; } + if (sock_type == SOCK_STREAM) { + int val; - memset(addr, 0, sizeof(*addr)); - addr->sun_family = AF_LOCAL; - if (strlen(sock_path) >= sizeof(addr->sun_path)) { - logmsgx("create_socket: too long path name (>= %lu) for local domain socket", - (u_long)sizeof(addr->sun_path)); - goto failed; - } - strcpy(addr->sun_path, sock_path); - - if (bind(fd, (struct sockaddr *)addr, SUN_LEN(addr)) < 0) { - logmsg("create_socket: bind(%s)", sock_path); - goto failed; + if (listen(fd, LISTENQ) < 0) { + logmsg("socket_create: listen"); + goto failed; + } + val = fcntl(fd, F_GETFL, 0); + if (val < 0) { + logmsg("socket_create: fcntl(F_GETFL)"); + goto failed; + } + if (fcntl(fd, F_SETFL, val | O_NONBLOCK) < 0) { + logmsg("socket_create: fcntl(F_SETFL)"); + goto failed; + } } } @@ -468,1163 +688,1282 @@ create_socket(char *sock_path, size_t sock_path_len, struct sockaddr_un *addr) failed: if (close(fd) < 0) - logmsg("create_socket: close"); + logmsg("socket_create: close"); + if (server_flag) + if (unlink(serv_addr_sun.sun_path) < 0) + logmsg("socket_close: unlink(%s)", + serv_addr_sun.sun_path); return (-1); } -/* - * Call create_socket() for server listening socket. - * Return socket descriptor or -1 if some error occurred. - */ static int -create_server_socket(void) +socket_connect(int fd) { - return (create_socket(serv_sock_path, sizeof(serv_sock_path), &servaddr)); -} + dbgmsg("connect"); -/* - * Create unbound socket. - */ -static int -create_unbound_socket(void) -{ - return (create_socket((char *)NULL, 0, (struct sockaddr_un *)NULL)); -} - -/* - * Close socket descriptor, if sock_path is not equal to NULL, - * then unlink the given path. - */ -static int -close_socket(const char *sock_path, int fd) -{ - int error = 0; - - if (close(fd) < 0) { - logmsg("close_socket: close"); - error = -1; - } - if (sock_path != NULL) - if (unlink(sock_path) < 0) { - logmsg("close_socket: unlink(%s)", sock_path); - error = -1; - } - return (error); -} - -/* - * Connect to server (socket address in servaddr). - */ -static int -connect_server(int fd) -{ - dbgmsg(("connecting to %s", serv_sock_path)); - - /* - * If PF_LOCAL listening socket's queue is full, then connect() - * returns ECONNREFUSED immediately, do not need timeout. - */ - if (connect(fd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { - logmsg("connect_server: connect(%s)", serv_sock_path); + if (connect(fd, (struct sockaddr *)&serv_addr_sun, + serv_addr_sun.sun_len) < 0) { + logmsg("socket_connect: connect(%s)", serv_addr_sun.sun_path); return (-1); } - return (0); } -/* - * sendmsg() with timeout. - */ static int -sendmsg_timeout(int fd, struct msghdr *msg, size_t n) -{ - ssize_t nsent; - - dbgmsg(("sending %lu bytes", (u_long)n)); - - if (sigsetjmp(env_alrm, 1) != 0) { - logmsgx("sendmsg_timeout: cannot send message to %s (timeout)", serv_sock_path); - return (-1); - } - - (void)alarm(TIMEOUT); - - nsent = sendmsg(fd, msg, 0); - - (void)alarm(0); - - if (nsent < 0) { - logmsg("sendmsg_timeout: sendmsg"); - return (-1); - } - - if ((size_t)nsent != n) { - logmsgx("sendmsg_timeout: sendmsg: short send: %ld of %lu bytes", - (long)nsent, (u_long)n); - return (-1); - } - - return (0); -} - -/* - * accept() with timeout. - */ -static int -accept_timeout(int listenfd) +sync_recv(void) { + ssize_t ssize; int fd; - - dbgmsg(("accepting connection")); - - if (sigsetjmp(env_alrm, 1) != 0) { - logmsgx("accept_timeout: cannot accept connection (timeout)"); - return (-1); - } - - (void)alarm(TIMEOUT); - - fd = accept(listenfd, (struct sockaddr *)NULL, (socklen_t *)NULL); - - (void)alarm(0); - - if (fd < 0) { - logmsg("accept_timeout: accept"); - return (-1); - } - - return (fd); -} - -/* - * recvmsg() with timeout. - */ -static int -recvmsg_timeout(int fd, struct msghdr *msg, size_t n) -{ - ssize_t nread; - - dbgmsg(("receiving %lu bytes", (u_long)n)); - - if (sigsetjmp(env_alrm, 1) != 0) { - logmsgx("recvmsg_timeout: cannot receive message (timeout)"); - return (-1); - } - - (void)alarm(TIMEOUT); - - nread = recvmsg(fd, msg, MSG_WAITALL); - - (void)alarm(0); - - if (nread < 0) { - logmsg("recvmsg_timeout: recvmsg"); - return (-1); - } - - if ((size_t)nread != n) { - logmsgx("recvmsg_timeout: recvmsg: short read: %ld of %lu bytes", - (long)nread, (u_long)n); - return (-1); - } - - return (0); -} - -/* - * Wait for synchronization message (1 byte) with timeout. - */ -static int -sync_recv(int fd) -{ - ssize_t nread; char buf; - dbgmsg(("waiting for sync message")); + dbgmsg("sync: wait"); - if (sigsetjmp(env_alrm, 1) != 0) { - logmsgx("sync_recv: cannot receive sync message (timeout)"); - return (-1); - } + fd = sync_fd[server_flag ? SYNC_SERVER : SYNC_CLIENT][SYNC_RECV]; - (void)alarm(TIMEOUT); - - nread = read(fd, &buf, 1); - - (void)alarm(0); - - if (nread < 0) { + ssize = read(fd, &buf, 1); + if (ssize < 0) { logmsg("sync_recv: read"); return (-1); } - - if (nread != 1) { - logmsgx("sync_recv: read: short read: %ld of 1 byte", - (long)nread); + if (ssize < 1) { + logmsgx("sync_recv: read %zd of 1 byte", ssize); return (-1); } + dbgmsg("sync: received"); + return (0); } -/* - * Send synchronization message (1 byte) with timeout. - */ static int -sync_send(int fd) +sync_send(void) { - ssize_t nsent; + ssize_t ssize; + int fd; - dbgmsg(("sending sync message")); + dbgmsg("sync: send"); - if (sigsetjmp(env_alrm, 1) != 0) { - logmsgx("sync_send: cannot send sync message (timeout)"); - return (-1); - } + fd = sync_fd[server_flag ? SYNC_CLIENT : SYNC_SERVER][SYNC_SEND]; - (void)alarm(TIMEOUT); - - nsent = write(fd, "", 1); - - (void)alarm(0); - - if (nsent < 0) { + ssize = write(fd, "", 1); + if (ssize < 0) { logmsg("sync_send: write"); return (-1); } - - if (nsent != 1) { - logmsgx("sync_send: write: short write: %ld of 1 byte", - (long)nsent); + if (ssize < 1) { + logmsgx("sync_send: sent %zd of 1 byte", ssize); return (-1); } return (0); } -/* - * waitpid() for client with timeout. - */ static int -wait_client(void) +message_send(int fd, const struct msghdr *msghdr) { - int status; - pid_t pid; + const struct cmsghdr *cmsghdr; + size_t size; + ssize_t ssize; - if (sigsetjmp(env_alrm, 1) != 0) { - logmsgx("wait_client: cannot get exit status of client PID %ld (timeout)", - (long)client_pid); + size = msghdr->msg_iov != 0 ? msghdr->msg_iov->iov_len : 0; + dbgmsg("send: data size %zu", size); + dbgmsg("send: msghdr.msg_controllen %u", + (u_int)msghdr->msg_controllen); + cmsghdr = CMSG_FIRSTHDR(msghdr); + if (cmsghdr != NULL) + dbgmsg("send: cmsghdr.cmsg_len %u", + (u_int)cmsghdr->cmsg_len); + + ssize = sendmsg(fd, msghdr, 0); + if (ssize < 0) { + logmsg("message_send: sendmsg"); + return (-1); + } + if ((size_t)ssize != size) { + logmsgx("message_send: sendmsg: sent %zd of %zu bytes", + ssize, size); return (-1); } - (void)alarm(TIMEOUT); + if (!send_data_flag) + if (sync_send() < 0) + return (-1); - pid = waitpid(client_pid, &status, 0); + return (0); +} - (void)alarm(0); +static int +message_sendn(int fd, struct msghdr *msghdr) +{ + u_int i; - if (pid == (pid_t)-1) { - logmsg("wait_client: waitpid"); + for (i = 1; i <= ipc_msg.msg_num; ++i) { + dbgmsg("message #%u", i); + if (message_send(fd, msghdr) < 0) + return (-1); + } + return (0); +} + +static int +message_recv(int fd, struct msghdr *msghdr) +{ + const struct cmsghdr *cmsghdr; + size_t size; + ssize_t ssize; + + if (!send_data_flag) + if (sync_recv() < 0) + return (-1); + + size = msghdr->msg_iov != NULL ? msghdr->msg_iov->iov_len : 0; + ssize = recvmsg(fd, msghdr, MSG_WAITALL); + if (ssize < 0) { + logmsg("message_recv: recvmsg"); + return (-1); + } + if ((size_t)ssize != size) { + logmsgx("message_recv: recvmsg: received %zd of %zu bytes", + ssize, size); return (-1); } - if (WIFEXITED(status)) { - if (WEXITSTATUS(status) != 0) { - logmsgx("wait_client: exit status of client PID %ld is %d", - (long)client_pid, WEXITSTATUS(status)); + dbgmsg("recv: data size %zd", ssize); + dbgmsg("recv: msghdr.msg_controllen %u", + (u_int)msghdr->msg_controllen); + cmsghdr = CMSG_FIRSTHDR(msghdr); + if (cmsghdr != NULL) + dbgmsg("recv: cmsghdr.cmsg_len %u", + (u_int)cmsghdr->cmsg_len); + + if (memcmp(ipc_msg.buf_recv, ipc_msg.buf_send, size) != 0) { + logmsgx("message_recv: received message has wrong content"); + return (-1); + } + + return (0); +} + +static int +socket_accept(int listenfd) +{ + fd_set rset; + struct timeval tv; + int fd, rv, val; + + dbgmsg("accept"); + + FD_ZERO(&rset); + FD_SET(listenfd, &rset); + tv.tv_sec = TIMEOUT; + tv.tv_usec = 0; + rv = select(listenfd + 1, &rset, (fd_set *)NULL, (fd_set *)NULL, &tv); + if (rv < 0) { + logmsg("socket_accept: select"); + return (-1); + } + if (rv == 0) { + logmsgx("socket_accept: select timeout"); + return (-1); + } + + fd = accept(listenfd, (struct sockaddr *)NULL, (socklen_t *)NULL); + if (fd < 0) { + logmsg("socket_accept: accept"); + return (-1); + } + + val = fcntl(fd, F_GETFL, 0); + if (val < 0) { + logmsg("socket_accept: fcntl(F_GETFL)"); + goto failed; + } + if (fcntl(fd, F_SETFL, val & ~O_NONBLOCK) < 0) { + logmsg("socket_accept: fcntl(F_SETFL)"); + goto failed; + } + + return (fd); + +failed: + if (close(fd) < 0) + logmsg("socket_accept: close"); + return (-1); +} + +static int +check_msghdr(const struct msghdr *msghdr, size_t size) +{ + if (msghdr->msg_flags & MSG_TRUNC) { + logmsgx("msghdr.msg_flags has MSG_TRUNC"); + return (-1); + } + if (msghdr->msg_flags & MSG_CTRUNC) { + logmsgx("msghdr.msg_flags has MSG_CTRUNC"); + return (-1); + } + if (msghdr->msg_controllen < size) { + logmsgx("msghdr.msg_controllen %u < %zu", + (u_int)msghdr->msg_controllen, size); + return (-1); + } + if (msghdr->msg_controllen > 0 && size == 0) { + logmsgx("msghdr.msg_controllen %u > 0", + (u_int)msghdr->msg_controllen); + return (-1); + } + return (0); +} + +static int +check_cmsghdr(const struct cmsghdr *cmsghdr, int type, size_t size) +{ + if (cmsghdr == NULL) { + logmsgx("cmsghdr is NULL"); + return (-1); + } + if (cmsghdr->cmsg_level != SOL_SOCKET) { + logmsgx("cmsghdr.cmsg_level %d != SOL_SOCKET", + cmsghdr->cmsg_level); + return (-1); + } + if (cmsghdr->cmsg_type != type) { + logmsgx("cmsghdr.cmsg_type %d != %d", + cmsghdr->cmsg_type, type); + return (-1); + } + if (cmsghdr->cmsg_len != CMSG_LEN(size)) { + logmsgx("cmsghdr.cmsg_len %u != %zu", + (u_int)cmsghdr->cmsg_len, CMSG_LEN(size)); + return (-1); + } + return (0); +} + +static int +check_groups(const char *gid_arr_str, const gid_t *gid_arr, + const char *gid_num_str, int gid_num, bool all_gids) +{ + int i; + + for (i = 0; i < gid_num; ++i) + dbgmsg("%s[%d] %lu", gid_arr_str, i, (u_long)gid_arr[i]); + + if (all_gids) { + if (gid_num != proc_cred.gid_num) { + logmsgx("%s %d != %d", gid_num_str, gid_num, + proc_cred.gid_num); return (-1); } } else { - if (WIFSIGNALED(status)) - logmsgx("wait_client: abnormal termination of client PID %ld, signal %d%s", - (long)client_pid, WTERMSIG(status), WCOREDUMP(status) ? " (core file generated)" : ""); - else - logmsgx("wait_client: termination of client PID %ld, unknown status", - (long)client_pid); + if (gid_num > proc_cred.gid_num) { + logmsgx("%s %d > %d", gid_num_str, gid_num, + proc_cred.gid_num); + return (-1); + } + } + if (memcmp(gid_arr, proc_cred.gid_arr, + gid_num * sizeof(*gid_arr)) != 0) { + logmsgx("%s content is wrong", gid_arr_str); + for (i = 0; i < gid_num; ++i) + if (gid_arr[i] != proc_cred.gid_arr[i]) { + logmsgx("%s[%d] %lu != %lu", + gid_arr_str, i, (u_long)gid_arr[i], + (u_long)proc_cred.gid_arr[i]); + break; + } return (-1); } + return (0); +} + +static int +check_xucred(const struct xucred *xucred, socklen_t len) +{ + if (len != sizeof(*xucred)) { + logmsgx("option value size %zu != %zu", + (size_t)len, sizeof(*xucred)); + return (-1); + } + + dbgmsg("xucred.cr_version %u", xucred->cr_version); + dbgmsg("xucred.cr_uid %lu", (u_long)xucred->cr_uid); + dbgmsg("xucred.cr_ngroups %d", xucred->cr_ngroups); + + if (xucred->cr_version != XUCRED_VERSION) { + logmsgx("xucred.cr_version %u != %d", + xucred->cr_version, XUCRED_VERSION); + return (-1); + } + if (xucred->cr_uid != proc_cred.euid) { + logmsgx("xucred.cr_uid %lu != %lu (EUID)", + (u_long)xucred->cr_uid, (u_long)proc_cred.euid); + return (-1); + } + if (xucred->cr_ngroups == 0) { + logmsgx("xucred.cr_ngroups == 0"); + return (-1); + } + if (xucred->cr_ngroups < 0) { + logmsgx("xucred.cr_ngroups < 0"); + return (-1); + } + if (xucred->cr_ngroups > XU_NGROUPS) { + logmsgx("xucred.cr_ngroups %hu > %u (max)", + xucred->cr_ngroups, XU_NGROUPS); + return (-1); + } + if (xucred->cr_groups[0] != proc_cred.egid) { + logmsgx("xucred.cr_groups[0] %lu != %lu (EGID)", + (u_long)xucred->cr_groups[0], (u_long)proc_cred.egid); + return (-1); + } + if (check_groups("xucred.cr_groups", xucred->cr_groups, + "xucred.cr_ngroups", xucred->cr_ngroups, false) < 0) + return (-1); + return (0); +} + +static int +check_scm_creds_cmsgcred(struct cmsghdr *cmsghdr) +{ + const struct cmsgcred *cmsgcred; + + if (check_cmsghdr(cmsghdr, SCM_CREDS, sizeof(*cmsgcred)) < 0) + return (-1); + + cmsgcred = (struct cmsgcred *)CMSG_DATA(cmsghdr); + + dbgmsg("cmsgcred.cmcred_pid %ld", (long)cmsgcred->cmcred_pid); + dbgmsg("cmsgcred.cmcred_uid %lu", (u_long)cmsgcred->cmcred_uid); + dbgmsg("cmsgcred.cmcred_euid %lu", (u_long)cmsgcred->cmcred_euid); + dbgmsg("cmsgcred.cmcred_gid %lu", (u_long)cmsgcred->cmcred_gid); + dbgmsg("cmsgcred.cmcred_ngroups %d", cmsgcred->cmcred_ngroups); + + if (cmsgcred->cmcred_pid != client_pid) { + logmsgx("cmsgcred.cmcred_pid %ld != %ld", + (long)cmsgcred->cmcred_pid, (long)client_pid); + return (-1); + } + if (cmsgcred->cmcred_uid != proc_cred.uid) { + logmsgx("cmsgcred.cmcred_uid %lu != %lu", + (u_long)cmsgcred->cmcred_uid, (u_long)proc_cred.uid); + return (-1); + } + if (cmsgcred->cmcred_euid != proc_cred.euid) { + logmsgx("cmsgcred.cmcred_euid %lu != %lu", + (u_long)cmsgcred->cmcred_euid, (u_long)proc_cred.euid); + return (-1); + } + if (cmsgcred->cmcred_gid != proc_cred.gid) { + logmsgx("cmsgcred.cmcred_gid %lu != %lu", + (u_long)cmsgcred->cmcred_gid, (u_long)proc_cred.gid); + return (-1); + } + if (cmsgcred->cmcred_ngroups == 0) { + logmsgx("cmsgcred.cmcred_ngroups == 0"); + return (-1); + } + if (cmsgcred->cmcred_ngroups < 0) { + logmsgx("cmsgcred.cmcred_ngroups %d < 0", + cmsgcred->cmcred_ngroups); + return (-1); + } + if (cmsgcred->cmcred_ngroups > CMGROUP_MAX) { + logmsgx("cmsgcred.cmcred_ngroups %d > %d", + cmsgcred->cmcred_ngroups, CMGROUP_MAX); + return (-1); + } + if (cmsgcred->cmcred_groups[0] != proc_cred.egid) { + logmsgx("cmsgcred.cmcred_groups[0] %lu != %lu (EGID)", + (u_long)cmsgcred->cmcred_groups[0], (u_long)proc_cred.egid); + return (-1); + } + if (check_groups("cmsgcred.cmcred_groups", cmsgcred->cmcred_groups, + "cmsgcred.cmcred_ngroups", cmsgcred->cmcred_ngroups, false) < 0) + return (-1); + return (0); +} + +static int +check_scm_creds_sockcred(struct cmsghdr *cmsghdr) +{ + const struct sockcred *sockcred; + + if (check_cmsghdr(cmsghdr, SCM_CREDS, + SOCKCREDSIZE(proc_cred.gid_num)) < 0) + return (-1); + + sockcred = (struct sockcred *)CMSG_DATA(cmsghdr); + + dbgmsg("sockcred.sc_uid %lu", (u_long)sockcred->sc_uid); + dbgmsg("sockcred.sc_euid %lu", (u_long)sockcred->sc_euid); + dbgmsg("sockcred.sc_gid %lu", (u_long)sockcred->sc_gid); + dbgmsg("sockcred.sc_egid %lu", (u_long)sockcred->sc_egid); + dbgmsg("sockcred.sc_ngroups %d", sockcred->sc_ngroups); + + if (sockcred->sc_uid != proc_cred.uid) { + logmsgx("sockcred.sc_uid %lu != %lu", + (u_long)sockcred->sc_uid, (u_long)proc_cred.uid); + return (-1); + } + if (sockcred->sc_euid != proc_cred.euid) { + logmsgx("sockcred.sc_euid %lu != %lu", + (u_long)sockcred->sc_euid, (u_long)proc_cred.euid); + return (-1); + } + if (sockcred->sc_gid != proc_cred.gid) { + logmsgx("sockcred.sc_gid %lu != %lu", + (u_long)sockcred->sc_gid, (u_long)proc_cred.gid); + return (-1); + } + if (sockcred->sc_egid != proc_cred.egid) { + logmsgx("sockcred.sc_egid %lu != %lu", + (u_long)sockcred->sc_egid, (u_long)proc_cred.egid); + return (-1); + } + if (sockcred->sc_ngroups == 0) { + logmsgx("sockcred.sc_ngroups == 0"); + return (-1); + } + if (sockcred->sc_ngroups < 0) { + logmsgx("sockcred.sc_ngroups %d < 0", + sockcred->sc_ngroups); + return (-1); + } + if (sockcred->sc_ngroups != proc_cred.gid_num) { + logmsgx("sockcred.sc_ngroups %d != %u", + sockcred->sc_ngroups, proc_cred.gid_num); + return (-1); + } + if (check_groups("sockcred.sc_groups", sockcred->sc_groups, + "sockcred.sc_ngroups", sockcred->sc_ngroups, true) < 0) + return (-1); + return (0); +} + +static int +check_scm_timestamp(struct cmsghdr *cmsghdr) +{ + const struct timeval *timeval; + + if (check_cmsghdr(cmsghdr, SCM_TIMESTAMP, sizeof(struct timeval)) < 0) + return (-1); + + timeval = (struct timeval *)CMSG_DATA(cmsghdr); + + dbgmsg("timeval.tv_sec %"PRIdMAX", timeval.tv_usec %"PRIdMAX, + (intmax_t)timeval->tv_sec, (intmax_t)timeval->tv_usec); return (0); } -/* - * Check if n supplementary GIDs in gids are correct. (my_gids + 1) - * has (my_ngids - 1) supplementary GIDs of current process. - */ static int -check_groups(const gid_t *gids, int n) +check_scm_bintime(struct cmsghdr *cmsghdr) { - char match[NGROUPS_MAX] = { 0 }; - int error, i, j; + const struct bintime *bintime; - if (n != my_ngids - 1) { - logmsgx("wrong number of groups %d != %d (returned from getgroups() - 1)", - n, my_ngids - 1); - error = -1; - } else - error = 0; - for (i = 0; i < n; ++i) { - for (j = 1; j < my_ngids; ++j) { - if (gids[i] == my_gids[j]) { - if (match[j]) { - logmsgx("duplicated GID %lu", - (u_long)gids[i]); - error = -1; - } else - match[j] = 1; - break; - } - } - if (j == my_ngids) { - logmsgx("unexpected GID %lu", (u_long)gids[i]); - error = -1; - } - } - for (j = 1; j < my_ngids; ++j) - if (match[j] == 0) { - logmsgx("did not receive supplementary GID %u", my_gids[j]); - error = -1; - } - return (error); + if (check_cmsghdr(cmsghdr, SCM_BINTIME, sizeof(struct bintime)) < 0) + return (-1); + + bintime = (struct bintime *)CMSG_DATA(cmsghdr); + + dbgmsg("bintime.sec %"PRIdMAX", bintime.frac %"PRIu64, + (intmax_t)bintime->sec, bintime->frac); + + return (0); } -/* - * Send n messages with data and control message with SCM_CREDS type - * to server and exit. - */ static void -t_cmsgcred_client(u_int n) +msghdr_init_generic(struct msghdr *msghdr, struct iovec *iov, void *cmsg_data) { - union { - struct cmsghdr cm; - char control[CMSG_SPACE(sizeof(struct cmsgcred))]; - } control_un; - struct msghdr msg; - struct iovec iov[1]; - struct cmsghdr *cmptr; - int fd; - u_int i; - - assert(n == 1 || n == 2); - - if ((fd = create_unbound_socket()) < 0) - goto failed; - - if (connect_server(fd) < 0) - goto failed_close; - - iov[0].iov_base = ipc_message; - iov[0].iov_len = IPC_MESSAGE_SIZE; - - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_iov = iov; - msg.msg_iovlen = 1; - msg.msg_control = control_un.control; - msg.msg_controllen = no_control_data ? - sizeof(struct cmsghdr) : sizeof(control_un.control); - msg.msg_flags = 0; - - cmptr = CMSG_FIRSTHDR(&msg); - cmptr->cmsg_len = CMSG_LEN(no_control_data ? - 0 : sizeof(struct cmsgcred)); - cmptr->cmsg_level = SOL_SOCKET; - cmptr->cmsg_type = SCM_CREDS; - - for (i = 0; i < n; ++i) { - dbgmsg(("#%u msg_controllen = %u, cmsg_len = %u", i, - (u_int)msg.msg_controllen, (u_int)cmptr->cmsg_len)); - if (sendmsg_timeout(fd, &msg, IPC_MESSAGE_SIZE) < 0) - goto failed_close; + msghdr->msg_name = NULL; + msghdr->msg_namelen = 0; + if (send_data_flag) { + iov->iov_base = server_flag ? + ipc_msg.buf_recv : ipc_msg.buf_send; + iov->iov_len = ipc_msg.buf_size; + msghdr->msg_iov = iov; + msghdr->msg_iovlen = 1; + } else { + msghdr->msg_iov = NULL; + msghdr->msg_iovlen = 0; } - - if (close_socket((const char *)NULL, fd) < 0) - goto failed; - - _exit(0); - -failed_close: - (void)close_socket((const char *)NULL, fd); - -failed: - _exit(1); + msghdr->msg_control = cmsg_data; + msghdr->msg_flags = 0; +} + +static void +msghdr_init_server(struct msghdr *msghdr, struct iovec *iov, + void *cmsg_data, size_t cmsg_size) +{ + msghdr_init_generic(msghdr, iov, cmsg_data); + msghdr->msg_controllen = cmsg_size; + dbgmsg("init: data size %zu", msghdr->msg_iov != NULL ? + msghdr->msg_iov->iov_len : (size_t)0); + dbgmsg("init: msghdr.msg_controllen %u", + (u_int)msghdr->msg_controllen); +} + +static void +msghdr_init_client(struct msghdr *msghdr, struct iovec *iov, + void *cmsg_data, size_t cmsg_size, int type, size_t arr_size) +{ + struct cmsghdr *cmsghdr; + + msghdr_init_generic(msghdr, iov, cmsg_data); + if (cmsg_data != NULL) { + msghdr->msg_controllen = send_array_flag ? + cmsg_size : CMSG_SPACE(0); + cmsghdr = CMSG_FIRSTHDR(msghdr); + cmsghdr->cmsg_level = SOL_SOCKET; + cmsghdr->cmsg_type = type; + cmsghdr->cmsg_len = CMSG_LEN(send_array_flag ? arr_size : 0); + } else + msghdr->msg_controllen = 0; +} + +static int +t_generic(int (*client_func)(int), int (*server_func)(int)) +{ + int fd, rv, rv_client; + + switch (client_fork()) { + case 0: + fd = socket_create(); + if (fd < 0) + rv = -2; + else { + rv = client_func(fd); + if (socket_close(fd) < 0) + rv = -2; + } + client_exit(rv); + break; + case 1: + fd = socket_create(); + if (fd < 0) + rv = -2; + else { + rv = server_func(fd); + rv_client = client_wait(); + if (rv == 0 || (rv == -2 && rv_client != 0)) + rv = rv_client; + if (socket_close(fd) < 0) + rv = -2; + } + break; + default: + rv = -2; + } + return (rv); +} + +static int +t_cmsgcred_client(int fd) +{ + struct msghdr msghdr; + struct iovec iov[1]; + void *cmsg_data; + size_t cmsg_size; + int rv; + + if (sync_recv() < 0) + return (-2); + + rv = -2; + + cmsg_size = CMSG_SPACE(sizeof(struct cmsgcred)); + cmsg_data = malloc(cmsg_size); + if (cmsg_data == NULL) { + logmsg("malloc"); + goto done; + } + msghdr_init_client(&msghdr, iov, cmsg_data, cmsg_size, + SCM_CREDS, sizeof(struct cmsgcred)); + + if (socket_connect(fd) < 0) + goto done; + + if (message_sendn(fd, &msghdr) < 0) + goto done; + + rv = 0; +done: + free(cmsg_data); + return (rv); } -/* - * Receive two messages with data and control message with SCM_CREDS - * type followed by struct cmsgcred{} from client. fd1 is a listen - * socket for stream sockets or simply socket for datagram sockets. - */ static int t_cmsgcred_server(int fd1) { - char buf[IPC_MESSAGE_SIZE]; - union { - struct cmsghdr cm; - char control[CMSG_SPACE(sizeof(struct cmsgcred)) + EXTRA_CMSG_SPACE]; - } control_un; - struct msghdr msg; + struct msghdr msghdr; struct iovec iov[1]; - struct cmsghdr *cmptr; - const struct cmsgcred *cmcredptr; - socklen_t controllen; - int error, error2, fd2; + struct cmsghdr *cmsghdr; + void *cmsg_data; + size_t cmsg_size; u_int i; + int fd2, rv; + + if (sync_send() < 0) + return (-2); + + fd2 = -1; + rv = -2; + + cmsg_size = CMSG_SPACE(sizeof(struct cmsgcred)); + cmsg_data = malloc(cmsg_size); + if (cmsg_data == NULL) { + logmsg("malloc"); + goto done; + } if (sock_type == SOCK_STREAM) { - if ((fd2 = accept_timeout(fd1)) < 0) - return (-2); + fd2 = socket_accept(fd1); + if (fd2 < 0) + goto done; } else fd2 = fd1; - error = 0; + rv = -1; + for (i = 1; i <= ipc_msg.msg_num; ++i) { + dbgmsg("message #%u", i); - controllen = sizeof(control_un.control); - - for (i = 0; i < 2; ++i) { - iov[0].iov_base = buf; - iov[0].iov_len = sizeof(buf); - - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_iov = iov; - msg.msg_iovlen = 1; - msg.msg_control = control_un.control; - msg.msg_controllen = controllen; - msg.msg_flags = 0; - - controllen = CMSG_SPACE(sizeof(struct cmsgcred)); - - if (recvmsg_timeout(fd2, &msg, sizeof(buf)) < 0) - goto failed; - - if (msg.msg_flags & MSG_CTRUNC) { - logmsgx("#%u control data was truncated, MSG_CTRUNC flag is on", - i); - goto next_error; + msghdr_init_server(&msghdr, iov, cmsg_data, cmsg_size); + if (message_recv(fd2, &msghdr) < 0) { + rv = -2; + break; } - if (msg.msg_controllen < sizeof(struct cmsghdr)) { - logmsgx("#%u msg_controllen %u < %lu (sizeof(struct cmsghdr))", - i, (u_int)msg.msg_controllen, (u_long)sizeof(struct cmsghdr)); - goto next_error; - } + if (check_msghdr(&msghdr, sizeof(*cmsghdr)) < 0) + break; - if ((cmptr = CMSG_FIRSTHDR(&msg)) == NULL) { - logmsgx("CMSG_FIRSTHDR is NULL"); - goto next_error; - } - - dbgmsg(("#%u msg_controllen = %u, cmsg_len = %u", i, - (u_int)msg.msg_controllen, (u_int)cmptr->cmsg_len)); - - if (cmptr->cmsg_level != SOL_SOCKET) { - logmsgx("#%u cmsg_level %d != SOL_SOCKET", i, - cmptr->cmsg_level); - goto next_error; - } - - if (cmptr->cmsg_type != SCM_CREDS) { - logmsgx("#%u cmsg_type %d != SCM_CREDS", i, - cmptr->cmsg_type); - goto next_error; - } - - if (cmptr->cmsg_len != CMSG_LEN(sizeof(struct cmsgcred))) { - logmsgx("#%u cmsg_len %u != %lu (CMSG_LEN(sizeof(struct cmsgcred))", - i, (u_int)cmptr->cmsg_len, (u_long)CMSG_LEN(sizeof(struct cmsgcred))); - goto next_error; - } - - cmcredptr = (const struct cmsgcred *)CMSG_DATA(cmptr); - - error2 = 0; - if (cmcredptr->cmcred_pid != client_pid) { - logmsgx("#%u cmcred_pid %ld != %ld (PID of client)", - i, (long)cmcredptr->cmcred_pid, (long)client_pid); - error2 = 1; - } - if (cmcredptr->cmcred_uid != my_uid) { - logmsgx("#%u cmcred_uid %lu != %lu (UID of current process)", - i, (u_long)cmcredptr->cmcred_uid, (u_long)my_uid); - error2 = 1; - } - if (cmcredptr->cmcred_euid != my_euid) { - logmsgx("#%u cmcred_euid %lu != %lu (EUID of current process)", - i, (u_long)cmcredptr->cmcred_euid, (u_long)my_euid); - error2 = 1; - } - if (cmcredptr->cmcred_gid != my_gid) { - logmsgx("#%u cmcred_gid %lu != %lu (GID of current process)", - i, (u_long)cmcredptr->cmcred_gid, (u_long)my_gid); - error2 = 1; - } - if (cmcredptr->cmcred_ngroups == 0) { - logmsgx("#%u cmcred_ngroups = 0, this is wrong", i); - error2 = 1; - } else { - if (cmcredptr->cmcred_ngroups > NGROUPS_MAX) { - logmsgx("#%u cmcred_ngroups %d > %u (NGROUPS_MAX)", - i, cmcredptr->cmcred_ngroups, NGROUPS_MAX); - error2 = 1; - } else if (cmcredptr->cmcred_ngroups < 0) { - logmsgx("#%u cmcred_ngroups %d < 0", - i, cmcredptr->cmcred_ngroups); - error2 = 1; - } else { - dbgmsg(("#%u cmcred_ngroups = %d", i, - cmcredptr->cmcred_ngroups)); - if (cmcredptr->cmcred_groups[0] != my_egid) { - logmsgx("#%u cmcred_groups[0] %lu != %lu (EGID of current process)", - i, (u_long)cmcredptr->cmcred_groups[0], (u_long)my_egid); - error2 = 1; - } - if (check_groups(cmcredptr->cmcred_groups + 1, cmcredptr->cmcred_ngroups - 1) < 0) { - logmsgx("#%u cmcred_groups has wrong GIDs", i); - error2 = 1; - } - } - } - - if (error2) - goto next_error; - - if ((cmptr = CMSG_NXTHDR(&msg, cmptr)) != NULL) { - logmsgx("#%u control data has extra header", i); - goto next_error; - } - - continue; -next_error: - error = -1; + cmsghdr = CMSG_FIRSTHDR(&msghdr); + if (check_scm_creds_cmsgcred(cmsghdr) < 0) + break; } - - if (sock_type == SOCK_STREAM) - if (close(fd2) < 0) { - logmsg("close"); - return (-2); - } - return (error); - -failed: - if (sock_type == SOCK_STREAM) - if (close(fd2) < 0) - logmsg("close"); - return (-2); + if (i > ipc_msg.msg_num) + rv = 0; +done: + free(cmsg_data); + if (sock_type == SOCK_STREAM && fd2 >= 0) + if (socket_close(fd2) < 0) + rv = -2; + return (rv); } static int t_cmsgcred(void) { - int error, fd; - - if ((fd = create_server_socket()) < 0) - return (-2); - - if (sock_type == SOCK_STREAM) - if (listen(fd, LISTENQ) < 0) { - logmsg("listen"); - goto failed; - } - - if ((client_pid = fork()) == (pid_t)-1) { - logmsg("fork"); - goto failed; - } - - if (client_pid == 0) { - myname = "CLIENT"; - if (close_socket((const char *)NULL, fd) < 0) - _exit(1); - t_cmsgcred_client(2); - } - - if ((error = t_cmsgcred_server(fd)) == -2) { - (void)wait_client(); - goto failed; - } - - if (wait_client() < 0) - goto failed; - - if (close_socket(serv_sock_path, fd) < 0) { - logmsgx("close_socket failed"); - return (-2); - } - return (error); - -failed: - if (close_socket(serv_sock_path, fd) < 0) - logmsgx("close_socket failed"); - return (-2); + return (t_generic(t_cmsgcred_client, t_cmsgcred_server)); } -/* - * Send two messages with data to server and exit. - */ -static void -t_sockcred_client(int type) -{ - struct msghdr msg; - struct iovec iov[1]; - int fd; - u_int i; - - assert(type == 0 || type == 1); - - if ((fd = create_unbound_socket()) < 0) - goto failed; - - if (connect_server(fd) < 0) - goto failed_close; - - if (type == 1) - if (sync_recv(fd) < 0) - goto failed_close; - - iov[0].iov_base = ipc_message; - iov[0].iov_len = IPC_MESSAGE_SIZE; - - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_iov = iov; - msg.msg_iovlen = 1; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_flags = 0; - - for (i = 0; i < 2; ++i) - if (sendmsg_timeout(fd, &msg, IPC_MESSAGE_SIZE) < 0) - goto failed_close; - - if (close_socket((const char *)NULL, fd) < 0) - goto failed; - - _exit(0); - -failed_close: - (void)close_socket((const char *)NULL, fd); - -failed: - _exit(1); -} - -/* - * Receive one message with data and control message with SCM_CREDS - * type followed by struct sockcred{} and if n is not equal 1, then - * receive another one message with data. fd1 is a listen socket for - * stream sockets or simply socket for datagram sockets. If type is - * 1, then set LOCAL_CREDS option for accepted stream socket. - */ static int -t_sockcred_server(int type, int fd1, u_int n) +t_sockcred_client(int type, int fd) { - char buf[IPC_MESSAGE_SIZE]; - union { - struct cmsghdr cm; - char control[CMSG_SPACE(SOCKCREDSIZE(NGROUPS_MAX)) + EXTRA_CMSG_SPACE]; - } control_un; - struct msghdr msg; + struct msghdr msghdr; struct iovec iov[1]; - struct cmsghdr *cmptr; - const struct sockcred *sockcred; - int error, error2, fd2, optval; - u_int i; + int rv; - assert(n == 1 || n == 2); - assert(type == 0 || type == 1); + if (sync_recv() < 0) + return (-2); + + rv = -2; + + msghdr_init_client(&msghdr, iov, NULL, 0, 0, 0); + + if (socket_connect(fd) < 0) + goto done; + + if (type == 2) + if (sync_recv() < 0) + goto done; + + if (message_sendn(fd, &msghdr) < 0) + goto done; + + rv = 0; +done: + return (rv); +} + +static int +t_sockcred_server(int type, int fd1) +{ + struct msghdr msghdr; + struct iovec iov[1]; + struct cmsghdr *cmsghdr; + void *cmsg_data; + size_t cmsg_size; + u_int i; + int fd2, rv, val; + + fd2 = -1; + rv = -2; + + cmsg_size = CMSG_SPACE(SOCKCREDSIZE(proc_cred.gid_num)); + cmsg_data = malloc(cmsg_size); + if (cmsg_data == NULL) { + logmsg("malloc"); + goto done; + } + + if (type == 1) { + dbgmsg("setting LOCAL_CREDS"); + val = 1; + if (setsockopt(fd1, 0, LOCAL_CREDS, &val, sizeof(val)) < 0) { + logmsg("setsockopt(LOCAL_CREDS)"); + goto done; + } + } + + if (sync_send() < 0) + goto done; if (sock_type == SOCK_STREAM) { - if ((fd2 = accept_timeout(fd1)) < 0) - return (-2); - if (type == 1) { - optval = 1; - if (setsockopt(fd2, 0, LOCAL_CREDS, &optval, sizeof optval) < 0) { - logmsg("setsockopt(LOCAL_CREDS) for accepted socket"); - if (errno == ENOPROTOOPT) { - error = -1; - goto done_close; - } - goto failed; - } - if (sync_send(fd2) < 0) - goto failed; - } + fd2 = socket_accept(fd1); + if (fd2 < 0) + goto done; } else fd2 = fd1; - error = 0; + if (type == 2) { + dbgmsg("setting LOCAL_CREDS"); + val = 1; + if (setsockopt(fd2, 0, LOCAL_CREDS, &val, sizeof(val)) < 0) { + logmsg("setsockopt(LOCAL_CREDS)"); + goto done; + } + if (sync_send() < 0) + goto done; + } - for (i = 0; i < n; ++i) { - iov[0].iov_base = buf; - iov[0].iov_len = sizeof buf; + rv = -1; + for (i = 1; i <= ipc_msg.msg_num; ++i) { + dbgmsg("message #%u", i); - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_iov = iov; - msg.msg_iovlen = 1; - msg.msg_control = control_un.control; - msg.msg_controllen = sizeof control_un.control; - msg.msg_flags = 0; - - if (recvmsg_timeout(fd2, &msg, sizeof buf) < 0) - goto failed; - - if (msg.msg_flags & MSG_CTRUNC) { - logmsgx("control data was truncated, MSG_CTRUNC flag is on"); - goto next_error; + msghdr_init_server(&msghdr, iov, cmsg_data, cmsg_size); + if (message_recv(fd2, &msghdr) < 0) { + rv = -2; + break; } - if (i != 0 && sock_type == SOCK_STREAM) { - if (msg.msg_controllen != 0) { - logmsgx("second message has control data, this is wrong for stream sockets"); - goto next_error; - } - dbgmsg(("#%u msg_controllen = %u", i, - (u_int)msg.msg_controllen)); - continue; - } - - if (msg.msg_controllen < sizeof(struct cmsghdr)) { - logmsgx("#%u msg_controllen %u < %lu (sizeof(struct cmsghdr))", - i, (u_int)msg.msg_controllen, (u_long)sizeof(struct cmsghdr)); - goto next_error; - } - - if ((cmptr = CMSG_FIRSTHDR(&msg)) == NULL) { - logmsgx("CMSG_FIRSTHDR is NULL"); - goto next_error; - } - - dbgmsg(("#%u msg_controllen = %u, cmsg_len = %u", i, - (u_int)msg.msg_controllen, (u_int)cmptr->cmsg_len)); - - if (cmptr->cmsg_level != SOL_SOCKET) { - logmsgx("#%u cmsg_level %d != SOL_SOCKET", i, - cmptr->cmsg_level); - goto next_error; - } - - if (cmptr->cmsg_type != SCM_CREDS) { - logmsgx("#%u cmsg_type %d != SCM_CREDS", i, - cmptr->cmsg_type); - goto next_error; - } - - if (cmptr->cmsg_len < CMSG_LEN(SOCKCREDSIZE(1))) { - logmsgx("#%u cmsg_len %u != %lu (CMSG_LEN(SOCKCREDSIZE(1)))", - i, (u_int)cmptr->cmsg_len, (u_long)CMSG_LEN(SOCKCREDSIZE(1))); - goto next_error; - } - - sockcred = (const struct sockcred *)CMSG_DATA(cmptr); - - error2 = 0; - if (sockcred->sc_uid != my_uid) { - logmsgx("#%u sc_uid %lu != %lu (UID of current process)", - i, (u_long)sockcred->sc_uid, (u_long)my_uid); - error2 = 1; - } - if (sockcred->sc_euid != my_euid) { - logmsgx("#%u sc_euid %lu != %lu (EUID of current process)", - i, (u_long)sockcred->sc_euid, (u_long)my_euid); - error2 = 1; - } - if (sockcred->sc_gid != my_gid) { - logmsgx("#%u sc_gid %lu != %lu (GID of current process)", - i, (u_long)sockcred->sc_gid, (u_long)my_gid); - error2 = 1; - } - if (sockcred->sc_egid != my_egid) { - logmsgx("#%u sc_egid %lu != %lu (EGID of current process)", - i, (u_long)sockcred->sc_gid, (u_long)my_egid); - error2 = 1; - } - if (sockcred->sc_ngroups > NGROUPS_MAX) { - logmsgx("#%u sc_ngroups %d > %u (NGROUPS_MAX)", - i, sockcred->sc_ngroups, NGROUPS_MAX); - error2 = 1; - } else if (sockcred->sc_ngroups < 0) { - logmsgx("#%u sc_ngroups %d < 0", - i, sockcred->sc_ngroups); - error2 = 1; + if (i > 1 && sock_type == SOCK_STREAM) { + if (check_msghdr(&msghdr, 0) < 0) + break; } else { - dbgmsg(("#%u sc_ngroups = %d", i, sockcred->sc_ngroups)); - if (check_groups(sockcred->sc_groups, sockcred->sc_ngroups) < 0) { - logmsgx("#%u sc_groups has wrong GIDs", i); - error2 = 1; + if (check_msghdr(&msghdr, sizeof(*cmsghdr)) < 0) + break; + + cmsghdr = CMSG_FIRSTHDR(&msghdr); + if (check_scm_creds_sockcred(cmsghdr) < 0) + break; + } + } + if (i > ipc_msg.msg_num) + rv = 0; +done: + free(cmsg_data); + if (sock_type == SOCK_STREAM && fd2 >= 0) + if (socket_close(fd2) < 0) + rv = -2; + return (rv); +} + +static int +t_sockcred_1(void) +{ + u_int i; + int fd, rv, rv_client; + + switch (client_fork()) { + case 0: + for (i = 1; i <= 2; ++i) { + dbgmsg("client #%u", i); + fd = socket_create(); + if (fd < 0) + rv = -2; + else { + rv = t_sockcred_client(1, fd); + if (socket_close(fd) < 0) + rv = -2; } + if (rv != 0) + break; } - - if (error2) - goto next_error; - - if ((cmptr = CMSG_NXTHDR(&msg, cmptr)) != NULL) { - logmsgx("#%u control data has extra header, this is wrong", - i); - goto next_error; + client_exit(rv); + break; + case 1: + fd = socket_create(); + if (fd < 0) + rv = -2; + else { + rv = t_sockcred_server(1, fd); + if (rv == 0) + rv = t_sockcred_server(3, fd); + rv_client = client_wait(); + if (rv == 0 || (rv == -2 && rv_client != 0)) + rv = rv_client; + if (socket_close(fd) < 0) + rv = -2; } - - continue; -next_error: - error = -1; + break; + default: + rv = -2; } -done_close: - if (sock_type == SOCK_STREAM) - if (close(fd2) < 0) { - logmsg("close"); - return (-2); - } - return (error); - -failed: - if (sock_type == SOCK_STREAM) - if (close(fd2) < 0) - logmsg("close"); - return (-2); + return (rv); } static int -t_sockcred(int type) +t_sockcred_2_client(int fd) { - int error, fd, optval; + return (t_sockcred_client(2, fd)); +} - assert(type == 0 || type == 1); +static int +t_sockcred_2_server(int fd) +{ + return (t_sockcred_server(2, fd)); +} - if ((fd = create_server_socket()) < 0) - return (-2); +static int +t_sockcred_2(void) +{ + return (t_generic(t_sockcred_2_client, t_sockcred_2_server)); +} - if (sock_type == SOCK_STREAM) - if (listen(fd, LISTENQ) < 0) { - logmsg("listen"); - goto failed; +static int +t_cmsgcred_sockcred_server(int fd1) +{ + struct msghdr msghdr; + struct iovec iov[1]; + struct cmsghdr *cmsghdr; + void *cmsg_data, *cmsg1_data, *cmsg2_data; + size_t cmsg_size, cmsg1_size, cmsg2_size; + u_int i; + int fd2, rv, val; + + fd2 = -1; + rv = -2; + + cmsg1_size = CMSG_SPACE(SOCKCREDSIZE(proc_cred.gid_num)); + cmsg2_size = CMSG_SPACE(sizeof(struct cmsgcred)); + cmsg1_data = malloc(cmsg1_size); + cmsg2_data = malloc(cmsg2_size); + if (cmsg1_data == NULL || cmsg2_data == NULL) { + logmsg("malloc"); + goto done; + } + + dbgmsg("setting LOCAL_CREDS"); + val = 1; + if (setsockopt(fd1, 0, LOCAL_CREDS, &val, sizeof(val)) < 0) { + logmsg("setsockopt(LOCAL_CREDS)"); + goto done; + } + + if (sync_send() < 0) + goto done; + + if (sock_type == SOCK_STREAM) { + fd2 = socket_accept(fd1); + if (fd2 < 0) + goto done; + } else + fd2 = fd1; + + cmsg_data = cmsg1_data; + cmsg_size = cmsg1_size; + rv = -1; + for (i = 1; i <= ipc_msg.msg_num; ++i) { + dbgmsg("message #%u", i); + + msghdr_init_server(&msghdr, iov, cmsg_data, cmsg_size); + if (message_recv(fd2, &msghdr) < 0) { + rv = -2; + break; } - if (type == 0) { - optval = 1; - if (setsockopt(fd, 0, LOCAL_CREDS, &optval, sizeof optval) < 0) { - logmsg("setsockopt(LOCAL_CREDS) for %s socket", - sock_type == SOCK_STREAM ? "stream listening" : "datagram"); - if (errno == ENOPROTOOPT) { - error = -1; - goto done_close; - } - goto failed; + if (check_msghdr(&msghdr, sizeof(*cmsghdr)) < 0) + break; + + cmsghdr = CMSG_FIRSTHDR(&msghdr); + if (i == 1 || sock_type == SOCK_DGRAM) { + if (check_scm_creds_sockcred(cmsghdr) < 0) + break; + } else { + if (check_scm_creds_cmsgcred(cmsghdr) < 0) + break; } + + cmsg_data = cmsg2_data; + cmsg_size = cmsg2_size; } - - if ((client_pid = fork()) == (pid_t)-1) { - logmsg("fork"); - goto failed; - } - - if (client_pid == 0) { - myname = "CLIENT"; - if (close_socket((const char *)NULL, fd) < 0) - _exit(1); - t_sockcred_client(type); - } - - if ((error = t_sockcred_server(type, fd, 2)) == -2) { - (void)wait_client(); - goto failed; - } - - if (wait_client() < 0) - goto failed; - -done_close: - if (close_socket(serv_sock_path, fd) < 0) { - logmsgx("close_socket failed"); - return (-2); - } - return (error); - -failed: - if (close_socket(serv_sock_path, fd) < 0) - logmsgx("close_socket failed"); - return (-2); -} - -static int -t_sockcred_stream1(void) -{ - return (t_sockcred(0)); -} - -static int -t_sockcred_stream2(void) -{ - return (t_sockcred(1)); -} - -static int -t_sockcred_dgram(void) -{ - return (t_sockcred(0)); + if (i > ipc_msg.msg_num) + rv = 0; +done: + free(cmsg1_data); + free(cmsg2_data); + if (sock_type == SOCK_STREAM && fd2 >= 0) + if (socket_close(fd2) < 0) + rv = -2; + return (rv); } static int t_cmsgcred_sockcred(void) { - int error, fd, optval; - - if ((fd = create_server_socket()) < 0) - return (-2); - - if (sock_type == SOCK_STREAM) - if (listen(fd, LISTENQ) < 0) { - logmsg("listen"); - goto failed; - } - - optval = 1; - if (setsockopt(fd, 0, LOCAL_CREDS, &optval, sizeof optval) < 0) { - logmsg("setsockopt(LOCAL_CREDS) for %s socket", - sock_type == SOCK_STREAM ? "stream listening" : "datagram"); - if (errno == ENOPROTOOPT) { - error = -1; - goto done_close; - } - goto failed; - } - - if ((client_pid = fork()) == (pid_t)-1) { - logmsg("fork"); - goto failed; - } - - if (client_pid == 0) { - myname = "CLIENT"; - if (close_socket((const char *)NULL, fd) < 0) - _exit(1); - t_cmsgcred_client(1); - } - - if ((error = t_sockcred_server(0, fd, 1)) == -2) { - (void)wait_client(); - goto failed; - } - - if (wait_client() < 0) - goto failed; - -done_close: - if (close_socket(serv_sock_path, fd) < 0) { - logmsgx("close_socket failed"); - return (-2); - } - return (error); - -failed: - if (close_socket(serv_sock_path, fd) < 0) - logmsgx("close_socket failed"); - return (-2); + return (t_generic(t_cmsgcred_client, t_cmsgcred_sockcred_server)); } -/* - * Send one message with data and control message with SCM_TIMESTAMP - * type to server and exit. - */ -static void -t_timestamp_client(void) -{ - union { - struct cmsghdr cm; - char control[CMSG_SPACE(sizeof(struct timeval))]; - } control_un; - struct msghdr msg; - struct iovec iov[1]; - struct cmsghdr *cmptr; - int fd; - - if ((fd = create_unbound_socket()) < 0) - goto failed; - - if (connect_server(fd) < 0) - goto failed_close; - - iov[0].iov_base = ipc_message; - iov[0].iov_len = IPC_MESSAGE_SIZE; - - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_iov = iov; - msg.msg_iovlen = 1; - msg.msg_control = control_un.control; - msg.msg_controllen = no_control_data ? - sizeof(struct cmsghdr) :sizeof control_un.control; - msg.msg_flags = 0; - - cmptr = CMSG_FIRSTHDR(&msg); - cmptr->cmsg_len = CMSG_LEN(no_control_data ? - 0 : sizeof(struct timeval)); - cmptr->cmsg_level = SOL_SOCKET; - cmptr->cmsg_type = SCM_TIMESTAMP; - - dbgmsg(("msg_controllen = %u, cmsg_len = %u", - (u_int)msg.msg_controllen, (u_int)cmptr->cmsg_len)); - - if (sendmsg_timeout(fd, &msg, IPC_MESSAGE_SIZE) < 0) - goto failed_close; - - if (close_socket((const char *)NULL, fd) < 0) - goto failed; - - _exit(0); - -failed_close: - (void)close_socket((const char *)NULL, fd); - -failed: - _exit(1); -} - -/* - * Receive one message with data and control message with SCM_TIMESTAMP - * type followed by struct timeval{} from client. - */ static int -t_timestamp_server(int fd1) +t_timeval_client(int fd) { - union { - struct cmsghdr cm; - char control[CMSG_SPACE(sizeof(struct timeval)) + EXTRA_CMSG_SPACE]; - } control_un; - char buf[IPC_MESSAGE_SIZE]; - int error, fd2; - struct msghdr msg; + struct msghdr msghdr; struct iovec iov[1]; - struct cmsghdr *cmptr; - const struct timeval *timeval; + void *cmsg_data; + size_t cmsg_size; + int rv; + + if (sync_recv() < 0) + return (-2); + + rv = -2; + + cmsg_size = CMSG_SPACE(sizeof(struct timeval)); + cmsg_data = malloc(cmsg_size); + if (cmsg_data == NULL) { + logmsg("malloc"); + goto done; + } + msghdr_init_client(&msghdr, iov, cmsg_data, cmsg_size, + SCM_TIMESTAMP, sizeof(struct timeval)); + + if (socket_connect(fd) < 0) + goto done; + + if (message_sendn(fd, &msghdr) < 0) + goto done; + + rv = 0; +done: + free(cmsg_data); + return (rv); +} + +static int +t_timeval_server(int fd1) +{ + struct msghdr msghdr; + struct iovec iov[1]; + struct cmsghdr *cmsghdr; + void *cmsg_data; + size_t cmsg_size; + u_int i; + int fd2, rv; + + if (sync_send() < 0) + return (-2); + + fd2 = -1; + rv = -2; + + cmsg_size = CMSG_SPACE(sizeof(struct timeval)); + cmsg_data = malloc(cmsg_size); + if (cmsg_data == NULL) { + logmsg("malloc"); + goto done; + } if (sock_type == SOCK_STREAM) { - if ((fd2 = accept_timeout(fd1)) < 0) - return (-2); + fd2 = socket_accept(fd1); + if (fd2 < 0) + goto done; } else fd2 = fd1; - iov[0].iov_base = buf; - iov[0].iov_len = sizeof buf; + rv = -1; + for (i = 1; i <= ipc_msg.msg_num; ++i) { + dbgmsg("message #%u", i); - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_iov = iov; - msg.msg_iovlen = 1; - msg.msg_control = control_un.control; - msg.msg_controllen = sizeof control_un.control; - msg.msg_flags = 0; - - if (recvmsg_timeout(fd2, &msg, sizeof buf) < 0) - goto failed; - - error = -1; - - if (msg.msg_flags & MSG_CTRUNC) { - logmsgx("control data was truncated, MSG_CTRUNC flag is on"); - goto done; - } - - if (msg.msg_controllen < sizeof(struct cmsghdr)) { - logmsgx("msg_controllen %u < %lu (sizeof(struct cmsghdr))", - (u_int)msg.msg_controllen, (u_long)sizeof(struct cmsghdr)); - goto done; - } - - if ((cmptr = CMSG_FIRSTHDR(&msg)) == NULL) { - logmsgx("CMSG_FIRSTHDR is NULL"); - goto done; - } - - dbgmsg(("msg_controllen = %u, cmsg_len = %u", - (u_int)msg.msg_controllen, (u_int)cmptr->cmsg_len)); - - if (cmptr->cmsg_level != SOL_SOCKET) { - logmsgx("cmsg_level %d != SOL_SOCKET", cmptr->cmsg_level); - goto done; - } - - if (cmptr->cmsg_type != SCM_TIMESTAMP) { - logmsgx("cmsg_type %d != SCM_TIMESTAMP", cmptr->cmsg_type); - goto done; - } - - if (cmptr->cmsg_len != CMSG_LEN(sizeof(struct timeval))) { - logmsgx("cmsg_len %u != %lu (CMSG_LEN(sizeof(struct timeval))", - (u_int)cmptr->cmsg_len, (u_long)CMSG_LEN(sizeof(struct timeval))); - goto done; - } - - timeval = (const struct timeval *)CMSG_DATA(cmptr); - - dbgmsg(("timeval tv_sec %jd, tv_usec %jd", - (intmax_t)timeval->tv_sec, (intmax_t)timeval->tv_usec)); - - if ((cmptr = CMSG_NXTHDR(&msg, cmptr)) != NULL) { - logmsgx("control data has extra header"); - goto done; - } - - error = 0; - -done: - if (sock_type == SOCK_STREAM) - if (close(fd2) < 0) { - logmsg("close"); - return (-2); + msghdr_init_server(&msghdr, iov, cmsg_data, cmsg_size); + if (message_recv(fd2, &msghdr) < 0) { + rv = -2; + break; } - return (error); -failed: - if (sock_type == SOCK_STREAM) - if (close(fd2) < 0) - logmsg("close"); - return (-2); + if (check_msghdr(&msghdr, sizeof(*cmsghdr)) < 0) + break; + + cmsghdr = CMSG_FIRSTHDR(&msghdr); + if (check_scm_timestamp(cmsghdr) < 0) + break; + } + if (i > ipc_msg.msg_num) + rv = 0; +done: + free(cmsg_data); + if (sock_type == SOCK_STREAM && fd2 >= 0) + if (socket_close(fd2) < 0) + rv = -2; + return (rv); } static int -t_timestamp(void) +t_timeval(void) { - int error, fd; + return (t_generic(t_timeval_client, t_timeval_server)); +} - if ((fd = create_server_socket()) < 0) +static int +t_bintime_client(int fd) +{ + struct msghdr msghdr; + struct iovec iov[1]; + void *cmsg_data; + size_t cmsg_size; + int rv; + + if (sync_recv() < 0) return (-2); - if (sock_type == SOCK_STREAM) - if (listen(fd, LISTENQ) < 0) { - logmsg("listen"); - goto failed; + rv = -2; + + cmsg_size = CMSG_SPACE(sizeof(struct bintime)); + cmsg_data = malloc(cmsg_size); + if (cmsg_data == NULL) { + logmsg("malloc"); + goto done; + } + msghdr_init_client(&msghdr, iov, cmsg_data, cmsg_size, + SCM_BINTIME, sizeof(struct bintime)); + + if (socket_connect(fd) < 0) + goto done; + + if (message_sendn(fd, &msghdr) < 0) + goto done; + + rv = 0; +done: + free(cmsg_data); + return (rv); +} + +static int +t_bintime_server(int fd1) +{ + struct msghdr msghdr; + struct iovec iov[1]; + struct cmsghdr *cmsghdr; + void *cmsg_data; + size_t cmsg_size; + u_int i; + int fd2, rv; + + if (sync_send() < 0) + return (-2); + + fd2 = -1; + rv = -2; + + cmsg_size = CMSG_SPACE(sizeof(struct bintime)); + cmsg_data = malloc(cmsg_size); + if (cmsg_data == NULL) { + logmsg("malloc"); + goto done; + } + + if (sock_type == SOCK_STREAM) { + fd2 = socket_accept(fd1); + if (fd2 < 0) + goto done; + } else + fd2 = fd1; + + rv = -1; + for (i = 1; i <= ipc_msg.msg_num; ++i) { + dbgmsg("message #%u", i); + + msghdr_init_server(&msghdr, iov, cmsg_data, cmsg_size); + if (message_recv(fd2, &msghdr) < 0) { + rv = -2; + break; } - if ((client_pid = fork()) == (pid_t)-1) { - logmsg("fork"); - goto failed; + if (check_msghdr(&msghdr, sizeof(*cmsghdr)) < 0) + break; + + cmsghdr = CMSG_FIRSTHDR(&msghdr); + if (check_scm_bintime(cmsghdr) < 0) + break; } - - if (client_pid == 0) { - myname = "CLIENT"; - if (close_socket((const char *)NULL, fd) < 0) - _exit(1); - t_timestamp_client(); - } - - if ((error = t_timestamp_server(fd)) == -2) { - (void)wait_client(); - goto failed; - } - - if (wait_client() < 0) - goto failed; - - if (close_socket(serv_sock_path, fd) < 0) { - logmsgx("close_socket failed"); - return (-2); - } - return (error); - -failed: - if (close_socket(serv_sock_path, fd) < 0) - logmsgx("close_socket failed"); - return (-2); + if (i > ipc_msg.msg_num) + rv = 0; +done: + free(cmsg_data); + if (sock_type == SOCK_STREAM && fd2 >= 0) + if (socket_close(fd2) < 0) + rv = -2; + return (rv); +} + +static int +t_bintime(void) +{ + return (t_generic(t_bintime_client, t_bintime_server)); +} + +static int +t_cmsg_len_client(int fd) +{ + struct msghdr msghdr; + struct iovec iov[1]; + struct cmsghdr *cmsghdr; + void *cmsg_data; + size_t size, cmsg_size; + socklen_t socklen; + int rv; + + if (sync_recv() < 0) + return (-2); + + rv = -2; + + cmsg_size = CMSG_SPACE(sizeof(struct cmsgcred)); + cmsg_data = malloc(cmsg_size); + if (cmsg_data == NULL) { + logmsg("malloc"); + goto done; + } + msghdr_init_client(&msghdr, iov, cmsg_data, cmsg_size, + SCM_CREDS, sizeof(struct cmsgcred)); + cmsghdr = CMSG_FIRSTHDR(&msghdr); + + if (socket_connect(fd) < 0) + goto done; + + size = msghdr.msg_iov != NULL ? msghdr.msg_iov->iov_len : 0; + rv = -1; + for (socklen = 0; socklen < CMSG_LEN(0); ++socklen) { + cmsghdr->cmsg_len = socklen; + dbgmsg("send: data size %zu", size); + dbgmsg("send: msghdr.msg_controllen %u", + (u_int)msghdr.msg_controllen); + dbgmsg("send: cmsghdr.cmsg_len %u", + (u_int)cmsghdr->cmsg_len); + if (sendmsg(fd, &msghdr, 0) < 0) + continue; + logmsgx("sent message with cmsghdr.cmsg_len %u < %u", + (u_int)cmsghdr->cmsg_len, (u_int)CMSG_LEN(0)); + break; + } + if (socklen == CMSG_LEN(0)) + rv = 0; + + if (sync_send() < 0) { + rv = -2; + goto done; + } +done: + free(cmsg_data); + return (rv); +} + +static int +t_cmsg_len_server(int fd1) +{ + int fd2, rv; + + if (sync_send() < 0) + return (-2); + + rv = -2; + + if (sock_type == SOCK_STREAM) { + fd2 = socket_accept(fd1); + if (fd2 < 0) + goto done; + } else + fd2 = fd1; + + if (sync_recv() < 0) + goto done; + + rv = 0; +done: + if (sock_type == SOCK_STREAM && fd2 >= 0) + if (socket_close(fd2) < 0) + rv = -2; + return (rv); +} + +static int +t_cmsg_len(void) +{ + return (t_generic(t_cmsg_len_client, t_cmsg_len_server)); +} + +static int +t_peercred_client(int fd) +{ + struct xucred xucred; + socklen_t len; + + if (sync_recv() < 0) + return (-1); + + if (socket_connect(fd) < 0) + return (-1); + + len = sizeof(xucred); + if (getsockopt(fd, 0, LOCAL_PEERCRED, &xucred, &len) < 0) { + logmsg("getsockopt(LOCAL_PEERCRED)"); + return (-1); + } + + if (check_xucred(&xucred, len) < 0) + return (-1); + + return (0); +} + +static int +t_peercred_server(int fd1) +{ + struct xucred xucred; + socklen_t len; + int fd2, rv; + + if (sync_send() < 0) + return (-2); + + fd2 = socket_accept(fd1); + if (fd2 < 0) + return (-2); + + len = sizeof(xucred); + if (getsockopt(fd2, 0, LOCAL_PEERCRED, &xucred, &len) < 0) { + logmsg("getsockopt(LOCAL_PEERCRED)"); + rv = -2; + goto done; + } + + if (check_xucred(&xucred, len) < 0) { + rv = -1; + goto done; + } + + rv = 0; +done: + if (socket_close(fd2) < 0) + rv = -2; + return (rv); +} + +static int +t_peercred(void) +{ + return (t_generic(t_peercred_client, t_peercred_server)); } diff --git a/tools/regression/sockets/unix_cmsg/unix_cmsg.t b/tools/regression/sockets/unix_cmsg/unix_cmsg.t index c8dea159669..70d92770d6e 100644 --- a/tools/regression/sockets/unix_cmsg/unix_cmsg.t +++ b/tools/regression/sockets/unix_cmsg/unix_cmsg.t @@ -11,47 +11,78 @@ n=0 run() { - result=`${cmd} -t $2 $3 $4 2>&1` - if [ $? -eq 0 ]; then - echo -n "ok $1" - else - echo -n "not ok $1" + result=`${cmd} -t $2 $3 ${5%% *} 2>&1` + if [ $? -ne 0 ]; then + echo -n "not " fi - echo " -" $5 + echo "ok $1 - $4 ${5#* }" echo ${result} | grep -E "SERVER|CLIENT" | while read line; do echo "# ${line}" done } -echo "1..15" +echo "1..47" -for desc in \ - "Sending, receiving cmsgcred" \ - "Receiving sockcred (listening socket has LOCAL_CREDS) # TODO" \ - "Receiving sockcred (accepted socket has LOCAL_CREDS) # TODO" \ - "Sending cmsgcred, receiving sockcred # TODO" \ - "Sending, receiving timestamp" +for t1 in \ + "1 Sending, receiving cmsgcred" \ + "4 Sending cmsgcred, receiving sockcred" \ + "5 Sending, receiving timeval" \ + "6 Sending, receiving bintime" \ + "7 Check cmsghdr.cmsg_len" do - n=`expr ${n} + 1` - run ${n} stream "" ${n} "STREAM ${desc}" + for t2 in \ + "0 " \ + "1 (no data)" \ + "2 (no array)" \ + "3 (no data, array)" + do + n=$((n + 1)) + run ${n} stream "-z ${t2%% *}" STREAM "${t1} ${t2#* }" + done done -i=0 -for desc in \ - "Sending, receiving cmsgcred" \ - "Receiving sockcred # TODO" \ - "Sending cmsgcred, receiving sockcred # TODO" \ - "Sending, receiving timestamp" +for t1 in \ + "2 Receiving sockcred (listening socket)" \ + "3 Receiving sockcred (accepted socket)" do - i=`expr ${i} + 1` - n=`expr ${n} + 1` - run ${n} dgram "" ${i} "DGRAM ${desc}" + for t2 in \ + "0 " \ + "1 (no data)" + do + n=$((n + 1)) + run ${n} stream "-z ${t2%% *}" STREAM "${t1} ${t2#* }" + done done -run 10 stream -z 1 "STREAM Sending, receiving cmsgcred (no control data)" -run 11 stream -z 4 "STREAM Sending cmsgcred, receiving sockcred (no control data) # TODO" -run 12 stream -z 5 "STREAM Sending, receiving timestamp (no control data)" +n=$((n + 1)) +run ${n} stream "-z 0" STREAM "8 Check LOCAL_PEERCRED socket option" -run 13 dgram -z 1 "DGRAM Sending, receiving cmsgcred (no control data)" -run 14 dgram -z 3 "DGRAM Sending cmsgcred, receiving sockcred (no control data) # TODO" -run 15 dgram -z 4 "DGRAM Sending, receiving timestamp (no control data)" +for t1 in \ + "1 Sending, receiving cmsgcred" \ + "3 Sending cmsgcred, receiving sockcred" \ + "4 Sending, receiving timeval" \ + "5 Sending, receiving bintime" \ + "6 Check cmsghdr.cmsg_len" +do + for t2 in \ + "0 " \ + "1 (no data)" \ + "2 (no array)" \ + "3 (no data, array)" + do + n=$((n + 1)) + run ${n} dgram "-z ${t2%% *}" DGRAM "${t1} ${t2#* }" + done +done + +for t1 in \ + "2 Receiving sockcred" +do + for t2 in \ + "0 " \ + "1 (no data)" + do + n=$((n + 1)) + run ${n} dgram "-z ${t2%% *}" DGRAM "${t1} ${t2#* }" + done +done From c53f854a17d7b81149b86ff298e5fb42ce7e4e43 Mon Sep 17 00:00:00 2001 From: Michael Tuexen Date: Mon, 11 Feb 2013 13:57:03 +0000 Subject: [PATCH 0125/1476] Don't send kernel provided information in the User Initiated ABORT cause, since the user can also provide this kind of information. So the receiver doesn't know who provided the information. While there: Fix a bug where the stack would send a malformed ABORT chunk when using a send() call with SCTP_ABORT|SCT_SENDALL flags. MFC after: 3 days --- sys/netinet/sctp_indata.c | 16 ++++----------- sys/netinet/sctp_output.c | 4 ++-- sys/netinet/sctp_pcb.c | 41 +++++++++++---------------------------- sys/netinet/sctp_usrreq.c | 28 ++++++++------------------ 4 files changed, 25 insertions(+), 64 deletions(-) diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c index 96e9713c386..b4a0d089bf6 100644 --- a/sys/netinet/sctp_indata.c +++ b/sys/netinet/sctp_indata.c @@ -4221,19 +4221,15 @@ again: abort_out_now: *abort_now = 1; /* XXX */ - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), + oper = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), 0, M_NOWAIT, 1, MT_DATA); if (oper) { struct sctp_paramhdr *ph; - uint32_t *ippp; - SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) + - sizeof(uint32_t); + SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr); ph = mtod(oper, struct sctp_paramhdr *); ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT); ph->param_length = htons(SCTP_BUF_LEN(oper)); - ippp = (uint32_t *) (ph + 1); - *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_24); } stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_24; sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED); @@ -4953,19 +4949,15 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup, abort_out_now: *abort_now = 1; /* XXX */ - oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), + oper = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), 0, M_NOWAIT, 1, MT_DATA); if (oper) { struct sctp_paramhdr *ph; - uint32_t *ippp; - SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) + - sizeof(uint32_t); + SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr); ph = mtod(oper, struct sctp_paramhdr *); ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT); ph->param_length = htons(SCTP_BUF_LEN(oper)); - ippp = (uint32_t *) (ph + 1); - *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_31); } stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_31; sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED); diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 22215321981..ed5d767e57d 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -6442,7 +6442,7 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr, if (m) { ph = mtod(m, struct sctp_paramhdr *); ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT); - ph->param_length = htons(ca->sndlen); + ph->param_length = htons(sizeof(struct sctp_paramhdr) + ca->sndlen); } /* * We add one here to keep the assoc from @@ -12498,7 +12498,7 @@ sctp_lower_sosend(struct socket *so, /* now move forward the data pointer */ ph = mtod(mm, struct sctp_paramhdr *); ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT); - ph->param_length = htons((sizeof(struct sctp_paramhdr) + tot_out)); + ph->param_length = htons(sizeof(struct sctp_paramhdr) + tot_out); ph++; SCTP_BUF_LEN(mm) = tot_out + sizeof(struct sctp_paramhdr); if (top == NULL) { diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c index a2eb8051755..f1ab1af0e2a 100644 --- a/sys/netinet/sctp_pcb.c +++ b/sys/netinet/sctp_pcb.c @@ -3308,22 +3308,16 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) /* Left with Data unread */ struct mbuf *op_err; - op_err = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), + op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), 0, M_NOWAIT, 1, MT_DATA); if (op_err) { /* Fill in the user initiated abort */ struct sctp_paramhdr *ph; - uint32_t *ippp; - SCTP_BUF_LEN(op_err) = - sizeof(struct sctp_paramhdr) + sizeof(uint32_t); - ph = mtod(op_err, - struct sctp_paramhdr *); - ph->param_type = htons( - SCTP_CAUSE_USER_INITIATED_ABT); + SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr); + ph = mtod(op_err, struct sctp_paramhdr *); + ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT); ph->param_length = htons(SCTP_BUF_LEN(op_err)); - ippp = (uint32_t *) (ph + 1); - *ippp = htonl(SCTP_FROM_SCTP_PCB + SCTP_LOC_3); } asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB + SCTP_LOC_3; sctp_send_abort_tcb(asoc, op_err, SCTP_SO_LOCKED); @@ -3395,7 +3389,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) struct mbuf *op_err; abort_anyway: - op_err = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), + op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), 0, M_NOWAIT, 1, MT_DATA); if (op_err) { /* @@ -3403,18 +3397,11 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) * initiated abort */ struct sctp_paramhdr *ph; - uint32_t *ippp; - SCTP_BUF_LEN(op_err) = - (sizeof(struct sctp_paramhdr) + - sizeof(uint32_t)); - ph = mtod(op_err, - struct sctp_paramhdr *); - ph->param_type = htons( - SCTP_CAUSE_USER_INITIATED_ABT); + SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr); + ph = mtod(op_err, struct sctp_paramhdr *); + ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT); ph->param_length = htons(SCTP_BUF_LEN(op_err)); - ippp = (uint32_t *) (ph + 1); - *ippp = htonl(SCTP_FROM_SCTP_PCB + SCTP_LOC_5); } asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB + SCTP_LOC_5; sctp_send_abort_tcb(asoc, op_err, SCTP_SO_LOCKED); @@ -3478,23 +3465,17 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) if ((SCTP_GET_STATE(&asoc->asoc) != SCTP_STATE_COOKIE_WAIT) && ((asoc->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) == 0)) { struct mbuf *op_err; - uint32_t *ippp; - op_err = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), + op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), 0, M_NOWAIT, 1, MT_DATA); if (op_err) { /* Fill in the user initiated abort */ struct sctp_paramhdr *ph; - SCTP_BUF_LEN(op_err) = (sizeof(struct sctp_paramhdr) + - sizeof(uint32_t)); + SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr); ph = mtod(op_err, struct sctp_paramhdr *); - ph->param_type = htons( - SCTP_CAUSE_USER_INITIATED_ABT); + ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT); ph->param_length = htons(SCTP_BUF_LEN(op_err)); - ippp = (uint32_t *) (ph + 1); - *ippp = htonl(SCTP_FROM_SCTP_PCB + SCTP_LOC_7); - } asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB + SCTP_LOC_7; sctp_send_abort_tcb(asoc, op_err, SCTP_SO_LOCKED); diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c index 2b3bf7921bb..5330df1011b 100644 --- a/sys/netinet/sctp_usrreq.c +++ b/sys/netinet/sctp_usrreq.c @@ -854,7 +854,7 @@ sctp_disconnect(struct socket *so) struct mbuf *op_err; abort_anyway: - op_err = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), + op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), 0, M_NOWAIT, 1, MT_DATA); if (op_err) { /* @@ -862,17 +862,11 @@ sctp_disconnect(struct socket *so) * initiated abort */ struct sctp_paramhdr *ph; - uint32_t *ippp; - SCTP_BUF_LEN(op_err) = - (sizeof(struct sctp_paramhdr) + sizeof(uint32_t)); - ph = mtod(op_err, - struct sctp_paramhdr *); - ph->param_type = htons( - SCTP_CAUSE_USER_INITIATED_ABT); + SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr); + ph = mtod(op_err, struct sctp_paramhdr *); + ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT); ph->param_length = htons(SCTP_BUF_LEN(op_err)); - ippp = (uint32_t *) (ph + 1); - *ippp = htonl(SCTP_FROM_SCTP_USRREQ + SCTP_LOC_4); } stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ + SCTP_LOC_4; sctp_send_abort_tcb(stcb, op_err, SCTP_SO_LOCKED); @@ -1069,22 +1063,16 @@ sctp_shutdown(struct socket *so) struct mbuf *op_err; abort_anyway: - op_err = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), + op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), 0, M_NOWAIT, 1, MT_DATA); if (op_err) { /* Fill in the user initiated abort */ struct sctp_paramhdr *ph; - uint32_t *ippp; - SCTP_BUF_LEN(op_err) = - sizeof(struct sctp_paramhdr) + sizeof(uint32_t); - ph = mtod(op_err, - struct sctp_paramhdr *); - ph->param_type = htons( - SCTP_CAUSE_USER_INITIATED_ABT); + SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr); + ph = mtod(op_err, struct sctp_paramhdr *); + ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT); ph->param_length = htons(SCTP_BUF_LEN(op_err)); - ippp = (uint32_t *) (ph + 1); - *ippp = htonl(SCTP_FROM_SCTP_USRREQ + SCTP_LOC_6); } stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ + SCTP_LOC_6; sctp_abort_an_association(stcb->sctp_ep, stcb, From f667ff300d0be1dae325385635e2896d9ccb4ac8 Mon Sep 17 00:00:00 2001 From: Xin LI Date: Mon, 11 Feb 2013 18:22:26 +0000 Subject: [PATCH 0126/1476] Use the right year. Noticed by: Denis Ahrens --- cddl/contrib/opensolaris/cmd/zfs/zfs.8 | 2 +- cddl/contrib/opensolaris/cmd/zpool/zpool-features.7 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cddl/contrib/opensolaris/cmd/zfs/zfs.8 b/cddl/contrib/opensolaris/cmd/zfs/zfs.8 index 85f70db38dd..a3009a2da25 100644 --- a/cddl/contrib/opensolaris/cmd/zfs/zfs.8 +++ b/cddl/contrib/opensolaris/cmd/zfs/zfs.8 @@ -28,7 +28,7 @@ .\" .\" $FreeBSD$ .\" -.Dd February 10, 2012 +.Dd February 10, 2013 .Dt ZFS 8 .Os .Sh NAME diff --git a/cddl/contrib/opensolaris/cmd/zpool/zpool-features.7 b/cddl/contrib/opensolaris/cmd/zpool/zpool-features.7 index caf0751e462..c1ac479d939 100644 --- a/cddl/contrib/opensolaris/cmd/zpool/zpool-features.7 +++ b/cddl/contrib/opensolaris/cmd/zpool/zpool-features.7 @@ -22,7 +22,7 @@ .\" .\" $FreeBSD$ .\" -.Dd February 8, 2012 +.Dd February 8, 2013 .Dt ZPOOL-FEATURES 7 .Os .Sh NAME From 485b3300cc125bbeac0632191a0c58268cf82b62 Mon Sep 17 00:00:00 2001 From: Neel Natu Date: Mon, 11 Feb 2013 20:36:07 +0000 Subject: [PATCH 0127/1476] Implement guest vcpu pinning using 'pthread_setaffinity_np(3)'. Prior to this change pinning was implemented via an ioctl (VM_SET_PINNING) that called 'sched_bind()' on behalf of the user thread. The ULE implementation of 'sched_bind()' bumps up 'td_pinned' which in turn runs afoul of the assertion '(td_pinned == 0)' in userret(). Using the cpuset affinity to implement pinning of the vcpu threads works with both 4BSD and ULE schedulers and has the happy side-effect of getting rid of a bunch of code in vmm.ko. Discussed with: grehan --- lib/libvmmapi/vmmapi.c | 28 ----------------- lib/libvmmapi/vmmapi.h | 2 -- sys/amd64/include/vmm.h | 2 -- sys/amd64/include/vmm_dev.h | 11 ------- sys/amd64/vmm/io/ppt.c | 29 ++---------------- sys/amd64/vmm/vmm.c | 59 ------------------------------------ sys/amd64/vmm/vmm_dev.c | 12 -------- usr.sbin/bhyve/bhyverun.c | 6 +++- usr.sbin/bhyvectl/bhyvectl.c | 23 -------------- 9 files changed, 7 insertions(+), 165 deletions(-) diff --git a/lib/libvmmapi/vmmapi.c b/lib/libvmmapi/vmmapi.c index cfb42d09605..6a368b36db4 100644 --- a/lib/libvmmapi/vmmapi.c +++ b/lib/libvmmapi/vmmapi.c @@ -249,34 +249,6 @@ vm_get_register(struct vmctx *ctx, int vcpu, int reg, uint64_t *ret_val) return (error); } -int -vm_get_pinning(struct vmctx *ctx, int vcpu, int *host_cpuid) -{ - int error; - struct vm_pin vmpin; - - bzero(&vmpin, sizeof(vmpin)); - vmpin.vm_cpuid = vcpu; - - error = ioctl(ctx->fd, VM_GET_PINNING, &vmpin); - *host_cpuid = vmpin.host_cpuid; - return (error); -} - -int -vm_set_pinning(struct vmctx *ctx, int vcpu, int host_cpuid) -{ - int error; - struct vm_pin vmpin; - - bzero(&vmpin, sizeof(vmpin)); - vmpin.vm_cpuid = vcpu; - vmpin.host_cpuid = host_cpuid; - - error = ioctl(ctx->fd, VM_SET_PINNING, &vmpin); - return (error); -} - int vm_run(struct vmctx *ctx, int vcpu, uint64_t rip, struct vm_exit *vmexit) { diff --git a/lib/libvmmapi/vmmapi.h b/lib/libvmmapi/vmmapi.h index de042521aa6..e8cc8babea6 100644 --- a/lib/libvmmapi/vmmapi.h +++ b/lib/libvmmapi/vmmapi.h @@ -56,8 +56,6 @@ int vm_get_desc(struct vmctx *ctx, int vcpu, int reg, uint64_t *base, uint32_t *limit, uint32_t *access); int vm_set_register(struct vmctx *ctx, int vcpu, int reg, uint64_t val); int vm_get_register(struct vmctx *ctx, int vcpu, int reg, uint64_t *retval); -int vm_get_pinning(struct vmctx *ctx, int vcpu, int *host_cpuid); -int vm_set_pinning(struct vmctx *ctx, int vcpu, int host_cpuid); int vm_run(struct vmctx *ctx, int vcpu, uint64_t rip, struct vm_exit *ret_vmexit); int vm_apicid2vcpu(struct vmctx *ctx, int apicid); diff --git a/sys/amd64/include/vmm.h b/sys/amd64/include/vmm.h index ec9408338ad..6bd3566b744 100644 --- a/sys/amd64/include/vmm.h +++ b/sys/amd64/include/vmm.h @@ -102,8 +102,6 @@ int vm_get_seg_desc(struct vm *vm, int vcpu, int reg, struct seg_desc *ret_desc); int vm_set_seg_desc(struct vm *vm, int vcpu, int reg, struct seg_desc *desc); -int vm_get_pinning(struct vm *vm, int vcpu, int *cpuid); -int vm_set_pinning(struct vm *vm, int vcpu, int cpuid); int vm_run(struct vm *vm, struct vm_run *vmrun); int vm_inject_event(struct vm *vm, int vcpu, int type, int vector, uint32_t error_code, int error_code_valid); diff --git a/sys/amd64/include/vmm_dev.h b/sys/amd64/include/vmm_dev.h index 2311673e73f..07299276da9 100644 --- a/sys/amd64/include/vmm_dev.h +++ b/sys/amd64/include/vmm_dev.h @@ -51,11 +51,6 @@ struct vm_seg_desc { /* data or code segment */ struct seg_desc desc; }; -struct vm_pin { - int vm_cpuid; - int host_cpuid; /* -1 to unpin */ -}; - struct vm_run { int cpuid; uint64_t rip; /* start running here */ @@ -142,8 +137,6 @@ struct vm_x2apic { enum { IOCNUM_RUN, - IOCNUM_SET_PINNING, - IOCNUM_GET_PINNING, IOCNUM_MAP_MEMORY, IOCNUM_GET_MEMORY_SEG, IOCNUM_SET_REGISTER, @@ -168,10 +161,6 @@ enum { #define VM_RUN \ _IOWR('v', IOCNUM_RUN, struct vm_run) -#define VM_SET_PINNING \ - _IOW('v', IOCNUM_SET_PINNING, struct vm_pin) -#define VM_GET_PINNING \ - _IOWR('v', IOCNUM_GET_PINNING, struct vm_pin) #define VM_MAP_MEMORY \ _IOWR('v', IOCNUM_MAP_MEMORY, struct vm_memory_segment) #define VM_GET_MEMORY_SEG \ diff --git a/sys/amd64/vmm/io/ppt.c b/sys/amd64/vmm/io/ppt.c index 4a05985e69c..5aedaf29342 100644 --- a/sys/amd64/vmm/io/ppt.c +++ b/sys/amd64/vmm/io/ppt.c @@ -402,31 +402,6 @@ pptintr(void *arg) return (FILTER_HANDLED); } -/* - * XXX - * When we try to free the MSI resource the kernel will bind the thread to - * the host cpu was originally handling the MSI. The function freeing the - * MSI vector (apic_free_vector()) will panic the kernel if the thread - * is already bound to a cpu. - * - * So, we temporarily unbind the vcpu thread before freeing the MSI resource. - */ -static void -PPT_TEARDOWN_MSI(struct vm *vm, int vcpu, struct pptdev *ppt) -{ - int pincpu = -1; - - vm_get_pinning(vm, vcpu, &pincpu); - - if (pincpu >= 0) - vm_set_pinning(vm, vcpu, -1); - - ppt_teardown_msi(ppt); - - if (pincpu >= 0) - vm_set_pinning(vm, vcpu, pincpu); -} - int ppt_setup_msi(struct vm *vm, int vcpu, int bus, int slot, int func, int destcpu, int vector, int numvec) @@ -447,7 +422,7 @@ ppt_setup_msi(struct vm *vm, int vcpu, int bus, int slot, int func, return (EBUSY); /* Free any allocated resources */ - PPT_TEARDOWN_MSI(vm, vcpu, ppt); + ppt_teardown_msi(ppt); if (numvec == 0) /* nothing more to do */ return (0); @@ -513,7 +488,7 @@ ppt_setup_msi(struct vm *vm, int vcpu, int bus, int slot, int func, } if (i < numvec) { - PPT_TEARDOWN_MSI(vm, vcpu, ppt); + ppt_teardown_msi(ppt); return (ENXIO); } diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c index 82d4baa35e0..85d277e47ee 100644 --- a/sys/amd64/vmm/vmm.c +++ b/sys/amd64/vmm/vmm.c @@ -70,7 +70,6 @@ struct vcpu { int flags; enum vcpu_state state; struct mtx mtx; - int pincpu; /* host cpuid this vcpu is bound to */ int hostcpu; /* host cpuid this vcpu last ran on */ uint64_t guest_msrs[VMM_MSR_NUM]; struct vlapic *vlapic; @@ -81,18 +80,6 @@ struct vcpu { enum x2apic_state x2apic_state; int nmi_pending; }; -#define VCPU_F_PINNED 0x0001 - -#define VCPU_PINCPU(vm, vcpuid) \ - ((vm->vcpu[vcpuid].flags & VCPU_F_PINNED) ? vm->vcpu[vcpuid].pincpu : -1) - -#define VCPU_UNPIN(vm, vcpuid) (vm->vcpu[vcpuid].flags &= ~VCPU_F_PINNED) - -#define VCPU_PIN(vm, vcpuid, host_cpuid) \ -do { \ - vm->vcpu[vcpuid].flags |= VCPU_F_PINNED; \ - vm->vcpu[vcpuid].pincpu = host_cpuid; \ -} while(0) #define vcpu_lock_init(v) mtx_init(&((v)->mtx), "vcpu lock", 0, MTX_SPIN) #define vcpu_lock(v) mtx_lock_spin(&((v)->mtx)) @@ -594,52 +581,6 @@ vm_set_seg_desc(struct vm *vm, int vcpu, int reg, return (VMSETDESC(vm->cookie, vcpu, reg, desc)); } -int -vm_get_pinning(struct vm *vm, int vcpuid, int *cpuid) -{ - - if (vcpuid < 0 || vcpuid >= VM_MAXCPU) - return (EINVAL); - - *cpuid = VCPU_PINCPU(vm, vcpuid); - - return (0); -} - -int -vm_set_pinning(struct vm *vm, int vcpuid, int host_cpuid) -{ - struct thread *td; - - if (vcpuid < 0 || vcpuid >= VM_MAXCPU) - return (EINVAL); - - td = curthread; /* XXXSMP only safe when muxing vcpus */ - - /* unpin */ - if (host_cpuid < 0) { - VCPU_UNPIN(vm, vcpuid); - thread_lock(td); - sched_unbind(td); - thread_unlock(td); - return (0); - } - - if (CPU_ABSENT(host_cpuid)) - return (EINVAL); - - /* - * XXX we should check that 'host_cpuid' has not already been pinned - * by another vm. - */ - thread_lock(td); - sched_bind(td, host_cpuid); - thread_unlock(td); - VCPU_PIN(vm, vcpuid, host_cpuid); - - return (0); -} - static void restore_guest_fpustate(struct vcpu *vcpu) { diff --git a/sys/amd64/vmm/vmm_dev.c b/sys/amd64/vmm/vmm_dev.c index 0150ebd7aa2..95527ae9ec7 100644 --- a/sys/amd64/vmm/vmm_dev.c +++ b/sys/amd64/vmm/vmm_dev.c @@ -144,7 +144,6 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, struct vm_memory_segment *seg; struct vm_register *vmreg; struct vm_seg_desc* vmsegdesc; - struct vm_pin *vmpin; struct vm_run *vmrun; struct vm_event *vmevent; struct vm_lapic_irq *vmirq; @@ -170,7 +169,6 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, */ switch (cmd) { case VM_RUN: - case VM_SET_PINNING: case VM_GET_REGISTER: case VM_SET_REGISTER: case VM_GET_SEGMENT_DESCRIPTOR: @@ -301,16 +299,6 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, vmirq = (struct vm_lapic_irq *)data; error = lapic_set_intr(sc->vm, vmirq->cpuid, vmirq->vector); break; - case VM_SET_PINNING: - vmpin = (struct vm_pin *)data; - error = vm_set_pinning(sc->vm, vmpin->vm_cpuid, - vmpin->host_cpuid); - break; - case VM_GET_PINNING: - vmpin = (struct vm_pin *)data; - error = vm_get_pinning(sc->vm, vmpin->vm_cpuid, - &vmpin->host_cpuid); - break; case VM_MAP_MEMORY: seg = (struct vm_memory_segment *)data; error = vm_malloc(sc->vm, seg->gpa, seg->len); diff --git a/usr.sbin/bhyve/bhyverun.c b/usr.sbin/bhyve/bhyverun.c index 8d0364970c3..ea4b68c703c 100644 --- a/usr.sbin/bhyve/bhyverun.c +++ b/usr.sbin/bhyve/bhyverun.c @@ -520,13 +520,17 @@ static vmexit_handler_t handler[VM_EXITCODE_MAX] = { static void vm_loop(struct vmctx *ctx, int vcpu, uint64_t rip) { + cpuset_t mask; int error, rc, prevcpu; if (guest_vcpu_mux) setup_timeslice(); if (pincpu >= 0) { - error = vm_set_pinning(ctx, vcpu, pincpu + vcpu); + CPU_ZERO(&mask); + CPU_SET(pincpu + vcpu, &mask); + error = pthread_setaffinity_np(pthread_self(), + sizeof(mask), &mask); assert(error == 0); } diff --git a/usr.sbin/bhyvectl/bhyvectl.c b/usr.sbin/bhyvectl/bhyvectl.c index 35e13883bf6..4eb87f9d5b6 100644 --- a/usr.sbin/bhyvectl/bhyvectl.c +++ b/usr.sbin/bhyvectl/bhyvectl.c @@ -183,8 +183,6 @@ usage(void) " [--get-vmcs-exit-interruption-info]\n" " [--get-vmcs-exit-interruption-error]\n" " [--get-vmcs-interruptibility]\n" - " [--set-pinning=]\n" - " [--get-pinning]\n" " [--set-x2apic-state=]\n" " [--get-x2apic-state]\n" " [--set-lowmem=]\n" @@ -218,7 +216,6 @@ static int set_desc_tr, get_desc_tr; static int set_desc_ldtr, get_desc_ldtr; static int set_cs, set_ds, set_es, set_fs, set_gs, set_ss, set_tr, set_ldtr; static int get_cs, get_ds, get_es, get_fs, get_gs, get_ss, get_tr, get_ldtr; -static int set_pinning, get_pinning, pincpu; static int set_x2apic_state, get_x2apic_state; enum x2apic_state x2apic_state; static int run; @@ -374,7 +371,6 @@ enum { SET_SS, SET_TR, SET_LDTR, - SET_PINNING, SET_X2APIC_STATE, SET_VMCS_EXCEPTION_BITMAP, SET_VMCS_ENTRY_INTERRUPTION_INFO, @@ -423,7 +419,6 @@ main(int argc, char *argv[]) { "set-ss", REQ_ARG, 0, SET_SS }, { "set-tr", REQ_ARG, 0, SET_TR }, { "set-ldtr", REQ_ARG, 0, SET_LDTR }, - { "set-pinning",REQ_ARG, 0, SET_PINNING }, { "set-x2apic-state",REQ_ARG, 0, SET_X2APIC_STATE }, { "set-vmcs-exception-bitmap", REQ_ARG, 0, SET_VMCS_EXCEPTION_BITMAP }, @@ -552,7 +547,6 @@ main(int argc, char *argv[]) NO_ARG, &get_vmcs_exit_interruption_error, 1}, { "get-vmcs-interruptibility", NO_ARG, &get_vmcs_interruptibility, 1 }, - { "get-pinning",NO_ARG, &get_pinning, 1 }, { "get-x2apic-state",NO_ARG, &get_x2apic_state, 1 }, { "get-all", NO_ARG, &get_all, 1 }, { "run", NO_ARG, &run, 1 }, @@ -659,10 +653,6 @@ main(int argc, char *argv[]) ldtr = strtoul(optarg, NULL, 0); set_ldtr = 1; break; - case SET_PINNING: - pincpu = strtol(optarg, NULL, 0); - set_pinning = 1; - break; case SET_X2APIC_STATE: x2apic_state = strtol(optarg, NULL, 0); set_x2apic_state = 1; @@ -812,9 +802,6 @@ main(int argc, char *argv[]) if (!error && set_ldtr) error = vm_set_register(ctx, vcpu, VM_REG_GUEST_LDTR, ldtr); - if (!error && set_pinning) - error = vm_set_pinning(ctx, vcpu, pincpu); - if (!error && set_x2apic_state) error = vm_set_x2apic_state(ctx, vcpu, x2apic_state); @@ -1135,16 +1122,6 @@ main(int argc, char *argv[]) printf("ldtr[%d]\t\t0x%04lx\n", vcpu, ldtr); } - if (!error && (get_pinning || get_all)) { - error = vm_get_pinning(ctx, vcpu, &pincpu); - if (error == 0) { - if (pincpu < 0) - printf("pincpu[%d]\tunpinned\n", vcpu); - else - printf("pincpu[%d]\t%d\n", vcpu, pincpu); - } - } - if (!error && (get_x2apic_state || get_all)) { error = vm_get_x2apic_state(ctx, vcpu, &x2apic_state); if (error == 0) From 2416af26a0e917ed29ee14344f475789812e639c Mon Sep 17 00:00:00 2001 From: Michael Tuexen Date: Mon, 11 Feb 2013 21:02:49 +0000 Subject: [PATCH 0128/1476] Send the adaptation layer indication only if set by the user. MFC after: 3 days Discussed with: rrs --- sys/netinet/sctp_output.c | 40 +++++++++++++++++++++------------------ sys/netinet/sctp_pcb.c | 3 ++- sys/netinet/sctp_pcb.h | 1 + sys/netinet/sctp_usrreq.c | 1 + 4 files changed, 26 insertions(+), 19 deletions(-) diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index ed5d767e57d..5f43ba13bc8 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -4643,19 +4643,19 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked chunk_len += parameter_len; } /* Adaptation layer indication parameter */ - /* XXX: Should we include this always? */ - if (padding_len > 0) { - memset(mtod(m, caddr_t)+chunk_len, 0, padding_len); - chunk_len += padding_len; - padding_len = 0; + if (inp->sctp_ep.adaptation_layer_indicator_provided) { + if (padding_len > 0) { + memset(mtod(m, caddr_t)+chunk_len, 0, padding_len); + chunk_len += padding_len; + padding_len = 0; + } + parameter_len = (uint16_t) sizeof(struct sctp_adaptation_layer_indication); + ali = (struct sctp_adaptation_layer_indication *)(mtod(m, caddr_t)+chunk_len); + ali->ph.param_type = htons(SCTP_ULP_ADAPTATION); + ali->ph.param_length = htons(parameter_len); + ali->indication = ntohl(inp->sctp_ep.adaptation_layer_indicator); + chunk_len += parameter_len; } - parameter_len = (uint16_t) sizeof(struct sctp_adaptation_layer_indication); - ali = (struct sctp_adaptation_layer_indication *)(mtod(m, caddr_t)+chunk_len); - ali->ph.param_type = htons(SCTP_ULP_ADAPTATION); - ali->ph.param_length = htons(parameter_len); - ali->indication = ntohl(inp->sctp_ep.adaptation_layer_indicator); - chunk_len += parameter_len; - if (SCTP_BASE_SYSCTL(sctp_inits_include_nat_friendly)) { /* Add NAT friendly parameter. */ if (padding_len > 0) { @@ -5723,12 +5723,16 @@ do_a_abort: htons(inp->sctp_ep.max_open_streams_intome); /* adaptation layer indication parameter */ - ali = (struct sctp_adaptation_layer_indication *)((caddr_t)initack + sizeof(*initack)); - ali->ph.param_type = htons(SCTP_ULP_ADAPTATION); - ali->ph.param_length = htons(sizeof(*ali)); - ali->indication = ntohl(inp->sctp_ep.adaptation_layer_indicator); - SCTP_BUF_LEN(m) += sizeof(*ali); - ecn = (struct sctp_ecn_supported_param *)((caddr_t)ali + sizeof(*ali)); + if (inp->sctp_ep.adaptation_layer_indicator_provided) { + ali = (struct sctp_adaptation_layer_indication *)((caddr_t)initack + sizeof(*initack)); + ali->ph.param_type = htons(SCTP_ULP_ADAPTATION); + ali->ph.param_length = htons(sizeof(*ali)); + ali->indication = ntohl(inp->sctp_ep.adaptation_layer_indicator); + SCTP_BUF_LEN(m) += sizeof(*ali); + ecn = (struct sctp_ecn_supported_param *)((caddr_t)ali + sizeof(*ali)); + } else { + ecn = (struct sctp_ecn_supported_param *)((caddr_t)initack + sizeof(*initack)); + } /* ECN parameter */ if (((asoc != NULL) && (asoc->ecn_allowed == 1)) || diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c index f1ab1af0e2a..69697934525 100644 --- a/sys/netinet/sctp_pcb.c +++ b/sys/netinet/sctp_pcb.c @@ -2516,7 +2516,8 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id) m->pre_open_stream_count = SCTP_BASE_SYSCTL(sctp_nr_outgoing_streams_default); /* Add adaptation cookie */ - m->adaptation_layer_indicator = 0x504C5253; + m->adaptation_layer_indicator = 0; + m->adaptation_layer_indicator_provided = 0; /* seed random number generator */ m->random_counter = 1; diff --git a/sys/netinet/sctp_pcb.h b/sys/netinet/sctp_pcb.h index c1f04bc67ca..91807c7cd90 100644 --- a/sys/netinet/sctp_pcb.h +++ b/sys/netinet/sctp_pcb.h @@ -323,6 +323,7 @@ struct sctp_pcb { int auto_close_time; uint32_t initial_sequence_debug; uint32_t adaptation_layer_indicator; + uint8_t adaptation_layer_indicator_provided; uint32_t store_at; uint32_t max_burst; uint32_t fr_max_burst; diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c index 5330df1011b..972ea23d1b7 100644 --- a/sys/netinet/sctp_usrreq.c +++ b/sys/netinet/sctp_usrreq.c @@ -4617,6 +4617,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, SCTP_CHECK_AND_CAST(adap_bits, optval, struct sctp_setadaptation, optsize); SCTP_INP_WLOCK(inp); inp->sctp_ep.adaptation_layer_indicator = adap_bits->ssb_adaptation_ind; + inp->sctp_ep.adaptation_layer_indicator_provided = 1; SCTP_INP_WUNLOCK(inp); break; } From 6a33bbc041ba90cd6dee1dcb2258e5be9c35513a Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Mon, 11 Feb 2013 21:10:55 +0000 Subject: [PATCH 0129/1476] Merge zfs_ioctl.c code that should have been merged together with ZFS v28. Fixes several problems if working with read-only pools. Changed code originaly introduced in onnv-gate 13061:bda0decf867b Contains changes up to illumos-gate 13700:4bc0783f6064 PR: kern/175897 Suggested by: avg MFC after: 2 weeks --- .../opensolaris/uts/common/fs/zfs/zfs_ioctl.c | 175 ++++++++++-------- 1 file changed, 100 insertions(+), 75 deletions(-) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c index 7a2334b5868..9925a3bb50c 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c @@ -106,12 +106,18 @@ typedef enum { DATASET_NAME } zfs_ioc_namecheck_t; +typedef enum { + POOL_CHECK_NONE = 1 << 0, + POOL_CHECK_SUSPENDED = 1 << 1, + POOL_CHECK_READONLY = 1 << 2 +} zfs_ioc_poolcheck_t; + typedef struct zfs_ioc_vec { zfs_ioc_func_t *zvec_func; zfs_secpolicy_func_t *zvec_secpolicy; zfs_ioc_namecheck_t zvec_namecheck; boolean_t zvec_his_log; - boolean_t zvec_pool_check; + zfs_ioc_poolcheck_t zvec_pool_check; } zfs_ioc_vec_t; /* This array is indexed by zfs_userquota_prop_t */ @@ -5052,138 +5058,155 @@ zfs_ioc_unjail(zfs_cmd_t *zc) static zfs_ioc_vec_t zfs_ioc_vec[] = { { zfs_ioc_pool_create, zfs_secpolicy_config, POOL_NAME, B_FALSE, - B_FALSE }, + POOL_CHECK_NONE }, { zfs_ioc_pool_destroy, zfs_secpolicy_config, POOL_NAME, B_FALSE, - B_FALSE }, + POOL_CHECK_NONE }, { zfs_ioc_pool_import, zfs_secpolicy_config, POOL_NAME, B_TRUE, - B_FALSE }, + POOL_CHECK_NONE }, { zfs_ioc_pool_export, zfs_secpolicy_config, POOL_NAME, B_FALSE, - B_FALSE }, + POOL_CHECK_NONE }, { zfs_ioc_pool_configs, zfs_secpolicy_none, NO_NAME, B_FALSE, - B_FALSE }, + POOL_CHECK_NONE }, { zfs_ioc_pool_stats, zfs_secpolicy_read, POOL_NAME, B_FALSE, - B_FALSE }, + POOL_CHECK_NONE }, { zfs_ioc_pool_tryimport, zfs_secpolicy_config, NO_NAME, B_FALSE, - B_FALSE }, + POOL_CHECK_NONE }, { zfs_ioc_pool_scan, zfs_secpolicy_config, POOL_NAME, B_TRUE, - B_TRUE }, + POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY }, { zfs_ioc_pool_freeze, zfs_secpolicy_config, NO_NAME, B_FALSE, - B_FALSE }, + POOL_CHECK_READONLY }, { zfs_ioc_pool_upgrade, zfs_secpolicy_config, POOL_NAME, B_TRUE, - B_TRUE }, + POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY }, { zfs_ioc_pool_get_history, zfs_secpolicy_config, POOL_NAME, B_FALSE, - B_FALSE }, + POOL_CHECK_NONE }, { zfs_ioc_vdev_add, zfs_secpolicy_config, POOL_NAME, B_TRUE, - B_TRUE }, + POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY }, { zfs_ioc_vdev_remove, zfs_secpolicy_config, POOL_NAME, B_TRUE, - B_TRUE }, + POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY }, { zfs_ioc_vdev_set_state, zfs_secpolicy_config, POOL_NAME, B_TRUE, - B_FALSE }, + POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY }, { zfs_ioc_vdev_attach, zfs_secpolicy_config, POOL_NAME, B_TRUE, - B_TRUE }, + POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY }, { zfs_ioc_vdev_detach, zfs_secpolicy_config, POOL_NAME, B_TRUE, - B_TRUE }, + POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY }, { zfs_ioc_vdev_setpath, zfs_secpolicy_config, POOL_NAME, B_FALSE, - B_TRUE }, + POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY }, { zfs_ioc_vdev_setfru, zfs_secpolicy_config, POOL_NAME, B_FALSE, - B_TRUE }, + POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY }, { zfs_ioc_objset_stats, zfs_secpolicy_read, DATASET_NAME, B_FALSE, - B_TRUE }, + POOL_CHECK_SUSPENDED }, { zfs_ioc_objset_zplprops, zfs_secpolicy_read, DATASET_NAME, B_FALSE, - B_FALSE }, + POOL_CHECK_NONE }, { zfs_ioc_dataset_list_next, zfs_secpolicy_read, DATASET_NAME, B_FALSE, - B_TRUE }, + POOL_CHECK_SUSPENDED }, { zfs_ioc_snapshot_list_next, zfs_secpolicy_read, DATASET_NAME, B_FALSE, - B_TRUE }, - { zfs_ioc_set_prop, zfs_secpolicy_none, DATASET_NAME, B_TRUE, B_TRUE }, - { zfs_ioc_create, zfs_secpolicy_create, DATASET_NAME, B_TRUE, B_TRUE }, + POOL_CHECK_SUSPENDED }, + { zfs_ioc_set_prop, zfs_secpolicy_none, DATASET_NAME, B_TRUE, + POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY }, + { zfs_ioc_create, zfs_secpolicy_create, DATASET_NAME, B_TRUE, + POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY }, { zfs_ioc_destroy, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE, - B_TRUE}, + POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY}, { zfs_ioc_rollback, zfs_secpolicy_rollback, DATASET_NAME, B_TRUE, - B_TRUE }, - { zfs_ioc_rename, zfs_secpolicy_rename, DATASET_NAME, B_TRUE, B_TRUE }, - { zfs_ioc_recv, zfs_secpolicy_receive, DATASET_NAME, B_TRUE, B_TRUE }, - { zfs_ioc_send, zfs_secpolicy_send, DATASET_NAME, B_FALSE, B_FALSE }, + POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY }, + { zfs_ioc_rename, zfs_secpolicy_rename, DATASET_NAME, B_TRUE, + POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY }, + { zfs_ioc_recv, zfs_secpolicy_receive, DATASET_NAME, B_TRUE, + POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY }, + { zfs_ioc_send, zfs_secpolicy_send, DATASET_NAME, B_FALSE, + POOL_CHECK_NONE }, { zfs_ioc_inject_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE, - B_FALSE }, + POOL_CHECK_NONE }, { zfs_ioc_clear_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE, - B_FALSE }, + POOL_CHECK_NONE }, { zfs_ioc_inject_list_next, zfs_secpolicy_inject, NO_NAME, B_FALSE, - B_FALSE }, + POOL_CHECK_NONE }, { zfs_ioc_error_log, zfs_secpolicy_inject, POOL_NAME, B_FALSE, - B_FALSE }, - { zfs_ioc_clear, zfs_secpolicy_config, POOL_NAME, B_TRUE, B_FALSE }, + POOL_CHECK_NONE }, + { zfs_ioc_clear, zfs_secpolicy_config, POOL_NAME, B_TRUE, + POOL_CHECK_NONE }, { zfs_ioc_promote, zfs_secpolicy_promote, DATASET_NAME, B_TRUE, - B_TRUE }, - { zfs_ioc_destroy_snaps_nvl, zfs_secpolicy_destroy_recursive, DATASET_NAME, - B_TRUE, B_TRUE }, + POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY }, + { zfs_ioc_destroy_snaps_nvl, zfs_secpolicy_destroy_recursive, + DATASET_NAME, B_TRUE, POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY }, { zfs_ioc_snapshot, zfs_secpolicy_snapshot, DATASET_NAME, B_TRUE, - B_TRUE }, + POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY }, { zfs_ioc_dsobj_to_dsname, zfs_secpolicy_diff, POOL_NAME, B_FALSE, - B_FALSE }, + POOL_CHECK_NONE }, { zfs_ioc_obj_to_path, zfs_secpolicy_diff, DATASET_NAME, B_FALSE, - B_TRUE }, + POOL_CHECK_SUSPENDED }, { zfs_ioc_pool_set_props, zfs_secpolicy_config, POOL_NAME, B_TRUE, - B_TRUE }, + POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY }, { zfs_ioc_pool_get_props, zfs_secpolicy_read, POOL_NAME, B_FALSE, - B_FALSE }, + POOL_CHECK_NONE }, { zfs_ioc_set_fsacl, zfs_secpolicy_fsacl, DATASET_NAME, B_TRUE, - B_TRUE }, + POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY }, { zfs_ioc_get_fsacl, zfs_secpolicy_read, DATASET_NAME, B_FALSE, - B_FALSE }, - { zfs_ioc_share, zfs_secpolicy_share, DATASET_NAME, B_FALSE, B_FALSE }, + POOL_CHECK_NONE }, + { zfs_ioc_share, zfs_secpolicy_share, DATASET_NAME, B_FALSE, + POOL_CHECK_NONE }, { zfs_ioc_inherit_prop, zfs_secpolicy_inherit, DATASET_NAME, B_TRUE, - B_TRUE }, + POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY }, { zfs_ioc_smb_acl, zfs_secpolicy_smb_acl, DATASET_NAME, B_FALSE, - B_FALSE }, - { zfs_ioc_userspace_one, zfs_secpolicy_userspace_one, - DATASET_NAME, B_FALSE, B_FALSE }, - { zfs_ioc_userspace_many, zfs_secpolicy_userspace_many, - DATASET_NAME, B_FALSE, B_FALSE }, + POOL_CHECK_NONE }, + { zfs_ioc_userspace_one, zfs_secpolicy_userspace_one, DATASET_NAME, + B_FALSE, POOL_CHECK_NONE }, + { zfs_ioc_userspace_many, zfs_secpolicy_userspace_many, DATASET_NAME, + B_FALSE, POOL_CHECK_NONE }, { zfs_ioc_userspace_upgrade, zfs_secpolicy_userspace_upgrade, - DATASET_NAME, B_FALSE, B_TRUE }, - { zfs_ioc_hold, zfs_secpolicy_hold, DATASET_NAME, B_TRUE, B_TRUE }, + DATASET_NAME, B_FALSE, POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY }, + { zfs_ioc_hold, zfs_secpolicy_hold, DATASET_NAME, B_TRUE, + POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY }, { zfs_ioc_release, zfs_secpolicy_release, DATASET_NAME, B_TRUE, - B_TRUE }, + POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY }, { zfs_ioc_get_holds, zfs_secpolicy_read, DATASET_NAME, B_FALSE, - B_TRUE }, + POOL_CHECK_SUSPENDED }, { zfs_ioc_objset_recvd_props, zfs_secpolicy_read, DATASET_NAME, B_FALSE, - B_FALSE }, + POOL_CHECK_NONE }, { zfs_ioc_vdev_split, zfs_secpolicy_config, POOL_NAME, B_TRUE, - B_TRUE }, + POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY }, { zfs_ioc_next_obj, zfs_secpolicy_read, DATASET_NAME, B_FALSE, - B_FALSE }, - { zfs_ioc_diff, zfs_secpolicy_diff, DATASET_NAME, B_FALSE, B_FALSE }, + POOL_CHECK_NONE }, + { zfs_ioc_diff, zfs_secpolicy_diff, DATASET_NAME, B_FALSE, + POOL_CHECK_NONE }, { zfs_ioc_tmp_snapshot, zfs_secpolicy_tmp_snapshot, DATASET_NAME, - B_FALSE, B_FALSE }, + B_FALSE, POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY }, { zfs_ioc_obj_to_stats, zfs_secpolicy_diff, DATASET_NAME, B_FALSE, - B_TRUE }, - { zfs_ioc_jail, zfs_secpolicy_config, DATASET_NAME, B_TRUE, B_FALSE }, - { zfs_ioc_unjail, zfs_secpolicy_config, DATASET_NAME, B_TRUE, B_FALSE }, + POOL_CHECK_SUSPENDED }, + { zfs_ioc_jail, zfs_secpolicy_config, DATASET_NAME, B_TRUE, + POOL_CHECK_NONE }, + { zfs_ioc_unjail, zfs_secpolicy_config, DATASET_NAME, B_TRUE, + POOL_CHECK_NONE }, { zfs_ioc_pool_reguid, zfs_secpolicy_config, POOL_NAME, B_TRUE, - B_TRUE }, + POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY }, { zfs_ioc_space_written, zfs_secpolicy_read, DATASET_NAME, B_FALSE, - B_TRUE }, + POOL_CHECK_SUSPENDED }, { zfs_ioc_space_snaps, zfs_secpolicy_read, DATASET_NAME, B_FALSE, - B_TRUE }, + POOL_CHECK_SUSPENDED }, { zfs_ioc_send_progress, zfs_secpolicy_read, DATASET_NAME, B_FALSE, - B_FALSE }, + POOL_CHECK_NONE }, { zfs_ioc_pool_reopen, zfs_secpolicy_config, POOL_NAME, B_TRUE, - B_TRUE }, + POOL_CHECK_SUSPENDED }, }; int -pool_status_check(const char *name, zfs_ioc_namecheck_t type) +pool_status_check(const char *name, zfs_ioc_namecheck_t type, + zfs_ioc_poolcheck_t check) { spa_t *spa; int error; ASSERT(type == POOL_NAME || type == DATASET_NAME); + if (check & POOL_CHECK_NONE) + return (0); + error = spa_open(name, &spa, FTAG); if (error == 0) { - if (spa_suspended(spa)) + if ((check & POOL_CHECK_SUSPENDED) && spa_suspended(spa)) error = EAGAIN; + else if ((check & POOL_CHECK_READONLY) && !spa_writeable(spa)) + error = EROFS; spa_close(spa, FTAG); } return (error); @@ -5353,17 +5376,19 @@ zfsdev_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, case POOL_NAME: if (pool_namecheck(zc->zc_name, NULL, NULL) != 0) error = EINVAL; - if (zfs_ioc_vec[vec].zvec_pool_check) + else error = pool_status_check(zc->zc_name, - zfs_ioc_vec[vec].zvec_namecheck); + zfs_ioc_vec[vec].zvec_namecheck, + zfs_ioc_vec[vec].zvec_pool_check); break; case DATASET_NAME: if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0) error = EINVAL; - if (zfs_ioc_vec[vec].zvec_pool_check) + else error = pool_status_check(zc->zc_name, - zfs_ioc_vec[vec].zvec_namecheck); + zfs_ioc_vec[vec].zvec_namecheck, + zfs_ioc_vec[vec].zvec_pool_check); break; case NO_NAME: From bdc5f0172eddb31fe7ec682e203de544d08472e1 Mon Sep 17 00:00:00 2001 From: Marius Strobl Date: Mon, 11 Feb 2013 21:50:00 +0000 Subject: [PATCH 0130/1476] Make SYSCTL_{LONG,QUAD,ULONG,UQUAD}(9) work as advertised and also handle constant values. Reviewed by: kib MFC after: 3 days --- sys/kern/kern_sysctl.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index f294ce3b9a8..521714c5741 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -1051,9 +1051,10 @@ sysctl_handle_long(SYSCTL_HANDLER_ARGS) /* * Attempt to get a coherent snapshot by making a copy of the data. */ - if (!arg1) - return (EINVAL); - tmplong = *(long *)arg1; + if (arg1) + tmplong = *(long *)arg1; + else + tmplong = arg2; #ifdef SCTL_MASK32 if (req->flags & SCTL_MASK32) { tmpint = tmplong; @@ -1065,12 +1066,15 @@ sysctl_handle_long(SYSCTL_HANDLER_ARGS) if (error || !req->newptr) return (error); + if (!arg1) + error = EPERM; #ifdef SCTL_MASK32 - if (req->flags & SCTL_MASK32) { + else if (req->flags & SCTL_MASK32) { error = SYSCTL_IN(req, &tmpint, sizeof(int)); *(long *)arg1 = (long)tmpint; - } else + } #endif + else error = SYSCTL_IN(req, arg1, sizeof(long)); return (error); } @@ -1087,15 +1091,19 @@ sysctl_handle_64(SYSCTL_HANDLER_ARGS) /* * Attempt to get a coherent snapshot by making a copy of the data. */ - if (!arg1) - return (EINVAL); - tmpout = *(uint64_t *)arg1; + if (arg1) + tmpout = *(uint64_t *)arg1; + else + tmpout = arg2; error = SYSCTL_OUT(req, &tmpout, sizeof(uint64_t)); if (error || !req->newptr) return (error); - error = SYSCTL_IN(req, arg1, sizeof(uint64_t)); + if (!arg1) + error = EPERM; + else + error = SYSCTL_IN(req, arg1, sizeof(uint64_t)); return (error); } From 9270ed9d3895ab5a40c47209923cc456fbfae040 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Mon, 11 Feb 2013 22:54:23 +0000 Subject: [PATCH 0131/1476] Style. --- sys/security/audit/audit_private.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/security/audit/audit_private.h b/sys/security/audit/audit_private.h index a5716d0cdc1..10ccd5b296d 100644 --- a/sys/security/audit/audit_private.h +++ b/sys/security/audit/audit_private.h @@ -202,7 +202,7 @@ struct audit_record { mode_t ar_arg_mode; int ar_arg_dev; long ar_arg_value; - void * ar_arg_addr; + void *ar_arg_addr; int ar_arg_len; int ar_arg_mask; u_int ar_arg_signum; @@ -219,7 +219,7 @@ struct audit_record { int ar_arg_svipc_cmd; struct ipc_perm ar_arg_svipc_perm; int ar_arg_svipc_id; - void * ar_arg_svipc_addr; + void *ar_arg_svipc_addr; struct posix_ipc_perm ar_arg_pipc_perm; union auditon_udata ar_arg_auditon; char *ar_arg_argv; From 18716f9f4bb41cdb4ce8685f2df0d7146d9a996a Mon Sep 17 00:00:00 2001 From: Marius Strobl Date: Mon, 11 Feb 2013 23:05:10 +0000 Subject: [PATCH 0132/1476] Update comments to reflect r246689. --- sys/kern/kern_sysctl.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index 521714c5741..33296d3c077 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -1036,7 +1036,10 @@ sysctl_msec_to_ticks(SYSCTL_HANDLER_ARGS) /* - * Handle a long, signed or unsigned. arg1 points to it. + * Handle a long, signed or unsigned. + * Two cases: + * a variable: point arg1 at it. + * a constant: pass it in arg2. */ int @@ -1080,7 +1083,10 @@ sysctl_handle_long(SYSCTL_HANDLER_ARGS) } /* - * Handle a 64 bit int, signed or unsigned. arg1 points to it. + * Handle a 64 bit int, signed or unsigned. + * Two cases: + * a variable: point arg1 at it. + * a constant: pass it in arg2. */ int sysctl_handle_64(SYSCTL_HANDLER_ARGS) From 04f5c326516e57dc92aec08e4d1272ad5e263467 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Mon, 11 Feb 2013 23:14:54 +0000 Subject: [PATCH 0133/1476] Style. --- sys/bsm/audit_kevents.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/bsm/audit_kevents.h b/sys/bsm/audit_kevents.h index 3eb2e3abb7d..d227981ff76 100644 --- a/sys/bsm/audit_kevents.h +++ b/sys/bsm/audit_kevents.h @@ -36,8 +36,8 @@ /* * The reserved event numbers for kernel events are 1...2047 and 43001..44900. */ -#define AUE_IS_A_KEVENT(e) (((e) > 0 && (e) < 2048) || \ - ((e) > 43000 && (e) < 45000)) +#define AUE_IS_A_KEVENT(e) (((e) > 0 && (e) < 2048) || \ + ((e) > 43000 && (e) < 45000)) /* * Values marked as AUE_NULL are not required to be audited as per CAPP. From 8a166cafe0965f6bd72cd3d2f5372704f05cb5e8 Mon Sep 17 00:00:00 2001 From: Andrew Turner Date: Tue, 12 Feb 2013 05:56:00 +0000 Subject: [PATCH 0134/1476] Allow us to build clang for ARM EABI. Clang and llvm use the arm-gnueabi-freebsd10.0 triple for EABI. Use this when we are on arm or armv6 and are building for EABI. Reviewed by: dim --- lib/clang/clang.build.mk | 10 +++++++++- usr.bin/clang/bugpoint/Makefile | 2 ++ usr.bin/clang/clang-tblgen/Makefile | 4 +++- usr.bin/clang/llc/Makefile | 2 ++ usr.bin/clang/lli/Makefile | 2 ++ usr.bin/clang/llvm-ar/Makefile | 2 ++ usr.bin/clang/llvm-as/Makefile | 2 ++ usr.bin/clang/llvm-bcanalyzer/Makefile | 2 ++ usr.bin/clang/llvm-diff/Makefile | 2 ++ usr.bin/clang/llvm-dis/Makefile | 2 ++ usr.bin/clang/llvm-extract/Makefile | 2 ++ usr.bin/clang/llvm-link/Makefile | 2 ++ usr.bin/clang/llvm-mc/Makefile | 4 +++- usr.bin/clang/llvm-nm/Makefile | 2 ++ usr.bin/clang/llvm-objdump/Makefile | 4 +++- usr.bin/clang/llvm-prof/Makefile | 2 ++ usr.bin/clang/llvm-ranlib/Makefile | 2 ++ usr.bin/clang/llvm-rtdyld/Makefile | 4 +++- usr.bin/clang/macho-dump/Makefile | 4 +++- usr.bin/clang/opt/Makefile | 2 ++ usr.bin/clang/tblgen/Makefile | 2 ++ 21 files changed, 54 insertions(+), 6 deletions(-) diff --git a/lib/clang/clang.build.mk b/lib/clang/clang.build.mk index 0015e3d12bd..6de044a3b6b 100644 --- a/lib/clang/clang.build.mk +++ b/lib/clang/clang.build.mk @@ -19,7 +19,15 @@ CFLAGS+= -fno-strict-aliasing TARGET_ARCH?= ${MACHINE_ARCH} BUILD_ARCH?= ${MACHINE_ARCH} -TARGET_TRIPLE?= ${TARGET_ARCH:C/amd64/x86_64/}-unknown-freebsd10.0 + +.if (${TARGET_ARCH} == "arm" || ${TARGET_ARCH} == "armv6") && \ + ${MK_ARM_EABI} != "no" +TARGET_ABI= gnueabi +.else +TARGET_ABI= unknown +.endif + +TARGET_TRIPLE?= ${TARGET_ARCH:C/amd64/x86_64/}-${TARGET_ABI}-freebsd10.0 BUILD_TRIPLE?= ${BUILD_ARCH:C/amd64/x86_64/}-unknown-freebsd10.0 CFLAGS+= -DLLVM_DEFAULT_TARGET_TRIPLE=\"${TARGET_TRIPLE}\" \ -DLLVM_HOSTTRIPLE=\"${BUILD_TRIPLE}\" \ diff --git a/usr.bin/clang/bugpoint/Makefile b/usr.bin/clang/bugpoint/Makefile index 410b91b55c9..a40d1e6d8fd 100644 --- a/usr.bin/clang/bugpoint/Makefile +++ b/usr.bin/clang/bugpoint/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.include + PROG_CXX=bugpoint SRCDIR= tools/bugpoint diff --git a/usr.bin/clang/clang-tblgen/Makefile b/usr.bin/clang/clang-tblgen/Makefile index 9e8af45d2ed..b777f0731f2 100644 --- a/usr.bin/clang/clang-tblgen/Makefile +++ b/usr.bin/clang/clang-tblgen/Makefile @@ -1,7 +1,9 @@ # $FreeBSD$ -PROG_CXX=clang-tblgen NO_MAN= +.include + +PROG_CXX=clang-tblgen SRCDIR= tools/clang/utils/TableGen SRCS= ClangASTNodesEmitter.cpp \ diff --git a/usr.bin/clang/llc/Makefile b/usr.bin/clang/llc/Makefile index 3606fef1518..7be4309c29b 100644 --- a/usr.bin/clang/llc/Makefile +++ b/usr.bin/clang/llc/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.include + PROG_CXX=llc SRCDIR= tools/llc diff --git a/usr.bin/clang/lli/Makefile b/usr.bin/clang/lli/Makefile index d6ecab512a1..4c56961ba5d 100644 --- a/usr.bin/clang/lli/Makefile +++ b/usr.bin/clang/lli/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.include + PROG_CXX=lli SRCDIR= tools/lli diff --git a/usr.bin/clang/llvm-ar/Makefile b/usr.bin/clang/llvm-ar/Makefile index 97ad058204d..b7a4a130482 100644 --- a/usr.bin/clang/llvm-ar/Makefile +++ b/usr.bin/clang/llvm-ar/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.include + PROG_CXX=llvm-ar SRCDIR= tools/llvm-ar diff --git a/usr.bin/clang/llvm-as/Makefile b/usr.bin/clang/llvm-as/Makefile index 7e90878bb12..6d3fd8e60a5 100644 --- a/usr.bin/clang/llvm-as/Makefile +++ b/usr.bin/clang/llvm-as/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.include + PROG_CXX=llvm-as SRCDIR= tools/llvm-as diff --git a/usr.bin/clang/llvm-bcanalyzer/Makefile b/usr.bin/clang/llvm-bcanalyzer/Makefile index 27788cc0a8b..88032cf1696 100644 --- a/usr.bin/clang/llvm-bcanalyzer/Makefile +++ b/usr.bin/clang/llvm-bcanalyzer/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.include + PROG_CXX=llvm-bcanalyzer SRCDIR= tools/llvm-bcanalyzer diff --git a/usr.bin/clang/llvm-diff/Makefile b/usr.bin/clang/llvm-diff/Makefile index aedaff02a99..1a130fbdaa0 100644 --- a/usr.bin/clang/llvm-diff/Makefile +++ b/usr.bin/clang/llvm-diff/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.include + PROG_CXX=llvm-diff SRCDIR= tools/llvm-diff diff --git a/usr.bin/clang/llvm-dis/Makefile b/usr.bin/clang/llvm-dis/Makefile index d6e0157d785..75a57383d7e 100644 --- a/usr.bin/clang/llvm-dis/Makefile +++ b/usr.bin/clang/llvm-dis/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.include + PROG_CXX=llvm-dis SRCDIR= tools/llvm-dis diff --git a/usr.bin/clang/llvm-extract/Makefile b/usr.bin/clang/llvm-extract/Makefile index 7489dd62195..8aac1ab7f3d 100644 --- a/usr.bin/clang/llvm-extract/Makefile +++ b/usr.bin/clang/llvm-extract/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.include + PROG_CXX=llvm-extract SRCDIR= tools/llvm-extract diff --git a/usr.bin/clang/llvm-link/Makefile b/usr.bin/clang/llvm-link/Makefile index bcd6a51cbd2..b76c5f4d512 100644 --- a/usr.bin/clang/llvm-link/Makefile +++ b/usr.bin/clang/llvm-link/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.include + PROG_CXX=llvm-link SRCDIR= tools/llvm-link diff --git a/usr.bin/clang/llvm-mc/Makefile b/usr.bin/clang/llvm-mc/Makefile index c2106e1fe98..c3821c41e1b 100644 --- a/usr.bin/clang/llvm-mc/Makefile +++ b/usr.bin/clang/llvm-mc/Makefile @@ -1,7 +1,9 @@ # $FreeBSD$ -PROG_CXX=llvm-mc NO_MAN= +.include + +PROG_CXX=llvm-mc SRCDIR= tools/llvm-mc SRCS= llvm-mc.cpp \ diff --git a/usr.bin/clang/llvm-nm/Makefile b/usr.bin/clang/llvm-nm/Makefile index 1ac3a3d5d59..bff0cdf0da2 100644 --- a/usr.bin/clang/llvm-nm/Makefile +++ b/usr.bin/clang/llvm-nm/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.include + PROG_CXX=llvm-nm SRCDIR= tools/llvm-nm diff --git a/usr.bin/clang/llvm-objdump/Makefile b/usr.bin/clang/llvm-objdump/Makefile index 38d23aedf6e..b7e5031b7e6 100644 --- a/usr.bin/clang/llvm-objdump/Makefile +++ b/usr.bin/clang/llvm-objdump/Makefile @@ -1,7 +1,9 @@ # $FreeBSD$ -PROG_CXX=llvm-objdump NO_MAN= +.include + +PROG_CXX=llvm-objdump SRCDIR= tools/llvm-objdump SRCS= llvm-objdump.cpp \ diff --git a/usr.bin/clang/llvm-prof/Makefile b/usr.bin/clang/llvm-prof/Makefile index b7b29cd8cf2..3dff62aaa8a 100644 --- a/usr.bin/clang/llvm-prof/Makefile +++ b/usr.bin/clang/llvm-prof/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.include + PROG_CXX=llvm-prof SRCDIR= tools/llvm-prof diff --git a/usr.bin/clang/llvm-ranlib/Makefile b/usr.bin/clang/llvm-ranlib/Makefile index 80e495cfb53..108ca7848f3 100644 --- a/usr.bin/clang/llvm-ranlib/Makefile +++ b/usr.bin/clang/llvm-ranlib/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.include + PROG_CXX=llvm-ranlib SRCDIR= tools/llvm-ranlib diff --git a/usr.bin/clang/llvm-rtdyld/Makefile b/usr.bin/clang/llvm-rtdyld/Makefile index e899d709003..b9b49ce5c99 100644 --- a/usr.bin/clang/llvm-rtdyld/Makefile +++ b/usr.bin/clang/llvm-rtdyld/Makefile @@ -1,7 +1,9 @@ # $FreeBSD$ -PROG_CXX=llvm-rtdyld NO_MAN= +.include + +PROG_CXX=llvm-rtdyld SRCDIR= tools/llvm-rtdyld SRCS= llvm-rtdyld.cpp diff --git a/usr.bin/clang/macho-dump/Makefile b/usr.bin/clang/macho-dump/Makefile index cb170d651f3..bafd15029cd 100644 --- a/usr.bin/clang/macho-dump/Makefile +++ b/usr.bin/clang/macho-dump/Makefile @@ -1,7 +1,9 @@ # $FreeBSD$ -PROG_CXX=macho-dump NO_MAN= +.include + +PROG_CXX=macho-dump SRCDIR= tools/macho-dump SRCS= macho-dump.cpp diff --git a/usr.bin/clang/opt/Makefile b/usr.bin/clang/opt/Makefile index 5afd58dd2e4..3af07d43c4a 100644 --- a/usr.bin/clang/opt/Makefile +++ b/usr.bin/clang/opt/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.include + PROG_CXX=opt SRCDIR= tools/opt diff --git a/usr.bin/clang/tblgen/Makefile b/usr.bin/clang/tblgen/Makefile index 90a5789cdf4..7cae5da9950 100644 --- a/usr.bin/clang/tblgen/Makefile +++ b/usr.bin/clang/tblgen/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.include + PROG_CXX=tblgen SRCDIR= utils/TableGen From b27ca6313e520cf3b020f94ccc45e5da7ff1b986 Mon Sep 17 00:00:00 2001 From: Andrew Turner Date: Tue, 12 Feb 2013 06:04:51 +0000 Subject: [PATCH 0135/1476] When clang builds libc it may insert calls to __aeabi_* functions. Normally this is not a problem as they are resolved by libgcc. The exception is for the __aeabi_mem* functions. These call back into libc to the appropriate function. This causes issues for static binaries as we only link against libc once so there is no way for it to call into libgcc and back. The fix for this is to include these symbols in libc but keep them hidden so binaries use the libgcc version. --- lib/libc/arm/aeabi/Makefile.inc | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/lib/libc/arm/aeabi/Makefile.inc b/lib/libc/arm/aeabi/Makefile.inc index ac147c03992..379eb237029 100644 --- a/lib/libc/arm/aeabi/Makefile.inc +++ b/lib/libc/arm/aeabi/Makefile.inc @@ -7,5 +7,24 @@ SRCS+= aeabi_atexit.c \ aeabi_float.c \ aeabi_unwind_cpp.c +# Add the aeabi_mem* functions. While they live in compiler-rt they call into +# libc. This causes issues when other parts of libc call these functions. +# We work around this by including these functions in libc but mark them as +# hidden so users of libc will not pick up these versions. +.PATH: ${.CURDIR}/../../contrib/compiler-rt/lib/arm + +SRCS+= aeabi_memcmp.S \ + aeabi_memcpy.S \ + aeabi_memmove.S \ + aeabi_memset.S + +# Mark the functions as hidden so they are not available outside of libc. +CFLAGS.aeabi_memcmp.S= -DVISIBILITY_HIDDEN +CFLAGS.aeabi_memcpy.S= -DVISIBILITY_HIDDEN +CFLAGS.aeabi_memmove.S= -DVISIBILITY_HIDDEN +CFLAGS.aeabi_memset.S= -DVISIBILITY_HIDDEN +CFLAGS+= ${CFLAGS.${.IMPSRC:T}} + + SYM_MAPS+=${.CURDIR}/arm/aeabi/Symbol.map From bb2902189e1e903c5eddc730bdb57e6d232e479e Mon Sep 17 00:00:00 2001 From: Oleksandr Tymoshenko Date: Tue, 12 Feb 2013 07:27:40 +0000 Subject: [PATCH 0136/1476] Remove debug output --- sys/arm/allwinner/a10_wdog.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sys/arm/allwinner/a10_wdog.c b/sys/arm/allwinner/a10_wdog.c index efc0752fdfe..05636015a7c 100644 --- a/sys/arm/allwinner/a10_wdog.c +++ b/sys/arm/allwinner/a10_wdog.c @@ -93,7 +93,6 @@ static int a10wd_probe(device_t dev) { - printf("A10 watchdog probe\n"); if (ofw_bus_is_compatible(dev, "allwinner,sun4i-wdt")) { device_set_desc(dev, "Allwinner A10 Watchdog"); return (BUS_PROBE_DEFAULT); From 23f4fd6da409f9bca1ce839776e72e85baeee3e9 Mon Sep 17 00:00:00 2001 From: Gleb Smirnoff Date: Tue, 12 Feb 2013 11:24:37 +0000 Subject: [PATCH 0137/1476] Substitute '#ifdef ALIGNED_POINTER' with '#ifndef __NO_STRICT_ALIGNMENT', since the former is defined everywhere. This cuts off some code not necessary on non strict aligment arches. Reviewed by: adrian Sponsored by: Nginx, Inc. --- sys/net80211/ieee80211_freebsd.c | 2 ++ sys/net80211/ieee80211_input.c | 4 ++-- sys/net80211/ieee80211_mesh.c | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/sys/net80211/ieee80211_freebsd.c b/sys/net80211/ieee80211_freebsd.c index 1c6491551a4..72db2718c43 100644 --- a/sys/net80211/ieee80211_freebsd.c +++ b/sys/net80211/ieee80211_freebsd.c @@ -432,6 +432,7 @@ ieee80211_getmgtframe(uint8_t **frm, int headroom, int pktlen) return m; } +#ifndef __NO_STRICT_ALIGNMENT /* * Re-align the payload in the mbuf. This is mainly used (right now) * to handle IP header alignment requirements on certain architectures. @@ -468,6 +469,7 @@ ieee80211_realign(struct ieee80211vap *vap, struct mbuf *m, size_t align) m_freem(m); return n; } +#endif /* !__NO_STRICT_ALIGNMENT */ int ieee80211_add_callback(struct mbuf *m, diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c index ebc4642f497..91adc6c1ec1 100644 --- a/sys/net80211/ieee80211_input.c +++ b/sys/net80211/ieee80211_input.c @@ -323,13 +323,13 @@ ieee80211_decap(struct ieee80211vap *vap, struct mbuf *m, int hdrlen) IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr4); break; } -#ifdef ALIGNED_POINTER +#ifndef __NO_STRICT_ALIGNMENT if (!ALIGNED_POINTER(mtod(m, caddr_t) + sizeof(*eh), uint32_t)) { m = ieee80211_realign(vap, m, sizeof(*eh)); if (m == NULL) return NULL; } -#endif /* ALIGNED_POINTER */ +#endif /* !__NO_STRICT_ALIGNMENT */ if (llc != NULL) { eh = mtod(m, struct ether_header *); eh->ether_type = htons(m->m_pkthdr.len - sizeof(*eh)); diff --git a/sys/net80211/ieee80211_mesh.c b/sys/net80211/ieee80211_mesh.c index 6d323cdc863..f4f94d18256 100644 --- a/sys/net80211/ieee80211_mesh.c +++ b/sys/net80211/ieee80211_mesh.c @@ -1401,13 +1401,13 @@ mesh_decap(struct ieee80211vap *vap, struct mbuf *m, int hdrlen, int meshdrlen) return NULL; } } -#ifdef ALIGNED_POINTER +#ifndef __NO_STRICT_ALIGNMENT if (!ALIGNED_POINTER(mtod(m, caddr_t) + sizeof(*eh), uint32_t)) { m = ieee80211_realign(vap, m, sizeof(*eh)); if (m == NULL) return NULL; } -#endif /* ALIGNED_POINTER */ +#endif /* !__NO_STRICT_ALIGNMENT */ if (llc != NULL) { eh = mtod(m, struct ether_header *); eh->ether_type = htons(m->m_pkthdr.len - sizeof(*eh)); From e6043cf0e13b2c915a4f96b827b676db85d10e5f Mon Sep 17 00:00:00 2001 From: Sergey Kandaurov Date: Tue, 12 Feb 2013 13:01:34 +0000 Subject: [PATCH 0138/1476] o Bring in sync decoding the first nfssvc(2) parameter (flags) with the current definitions location. o Respect numbers in NFSSVC_* (e.g. NFSSVC_V4ROOTEXPORT). MFC after: 1 week --- usr.bin/kdump/mksubr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr.bin/kdump/mksubr b/usr.bin/kdump/mksubr index 1b0df5e2b78..d56f0303573 100644 --- a/usr.bin/kdump/mksubr +++ b/usr.bin/kdump/mksubr @@ -377,7 +377,7 @@ auto_or_type "mmapprotname" "PROT_[A-Z]+[[:space:]]+0x[0-9A-Fa-f]+" auto_or_type "modename" "S_[A-Z]+[[:space:]]+[0-6]{7}" "sys/stat.h" auto_or_type "mountflagsname" "MNT_[A-Z]+[[:space:]]+0x[0-9]+" "sys/mount.h" auto_switch_type "msyncflagsname" "MS_[A-Z]+[[:space:]]+0x[0-9]+" "sys/mman.h" -auto_or_type "nfssvcname" "NFSSVC_[A-Z]+[[:space:]]+0x[0-9]+" "nfsserver/nfs.h" +auto_or_type "nfssvcname" "NFSSVC_[A-Z0-9]+[[:space:]]+0x[0-9]+" "nfs/nfssvc.h" auto_switch_type "prioname" "PRIO_[A-Z]+[[:space:]]+[0-9]" "sys/resource.h" auto_switch_type "ptraceopname" "PT_[[:alnum:]_]+[[:space:]]+[0-9]+" "sys/ptrace.h" auto_switch_type "quotactlname" "Q_[A-Z]+[[:space:]]+0x[0-9]+" "ufs/ufs/quota.h" From 44c169253de5caec5de2a397c522ad3e359f86e6 Mon Sep 17 00:00:00 2001 From: Marcel Moolenaar Date: Tue, 12 Feb 2013 16:51:43 +0000 Subject: [PATCH 0139/1476] Now that we actually use more memory descriptors, make sure to dump them as well. --- sys/ia64/ia64/dump_machdep.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sys/ia64/ia64/dump_machdep.c b/sys/ia64/ia64/dump_machdep.c index 734acc76e43..6fa860808d6 100644 --- a/sys/ia64/ia64/dump_machdep.c +++ b/sys/ia64/ia64/dump_machdep.c @@ -193,7 +193,10 @@ foreach_chunk(callback_t cb, void *arg) mdp = efi_md_first(); while (mdp != NULL) { if (mdp->md_type == EFI_MD_TYPE_FREE || - mdp->md_type == EFI_MD_TYPE_DATA) { + mdp->md_type == EFI_MD_TYPE_DATA || + mdp->md_type == EFI_MD_TYPE_CODE || + mdp->md_type == EFI_MD_TYPE_BS_DATA || + mdp->md_type == EFI_MD_TYPE_BS_CODE) { error = (*cb)(mdp, seqnr++, arg); if (error) return (-error); From dd0b4fb6d50631c140e800bdfac48d02e7e4c875 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Tue, 12 Feb 2013 16:57:20 +0000 Subject: [PATCH 0140/1476] Reform the busdma API so that new types may be added without modifying every architecture's busdma_machdep.c. It is done by unifying the bus_dmamap_load_buffer() routines so that they may be called from MI code. The MD busdma is then given a chance to do any final processing in the complete() callback. The cam changes unify the bus_dmamap_load* handling in cam drivers. The arm and mips implementations are updated to track virtual addresses for sync(). Previously this was done in a type specific way. Now it is done in a generic way by recording the list of virtuals in the map. Submitted by: jeff (sponsored by EMC/Isilon) Reviewed by: kan (previous version), scottl, mjacob (isp(4), no objections for target mode changes) Discussed with: ian (arm changes) Tested by: marius (sparc64), mips (jmallet), isci(4) on x86 (jharris), amd64 (Fabian Keil ) --- sys/arm/arm/busdma_machdep-v6.c | 592 +++++++++++------------ sys/arm/arm/busdma_machdep.c | 688 ++++++++++++--------------- sys/cam/cam_ccb.h | 10 +- sys/cam/cam_xpt.c | 3 +- sys/cam/ctl/ctl_frontend_cam_sim.c | 43 +- sys/cam/ctl/scsi_ctl.c | 10 +- sys/cam/scsi/scsi_pass.c | 5 +- sys/cam/scsi/scsi_target.c | 2 +- sys/conf/files | 1 + sys/dev/aac/aac_cam.c | 40 +- sys/dev/advansys/advansys.c | 64 +-- sys/dev/advansys/adwcam.c | 73 +-- sys/dev/aha/aha.c | 76 +-- sys/dev/ahb/ahb.c | 73 +-- sys/dev/ahci/ahci.c | 15 +- sys/dev/aic/aic.c | 4 +- sys/dev/aic7xxx/aic79xx_osm.c | 71 +-- sys/dev/aic7xxx/aic7xxx_osm.c | 74 +-- sys/dev/amr/amr_cam.c | 5 +- sys/dev/arcmsr/arcmsr.c | 56 +-- sys/dev/ata/ata-dma.c | 15 +- sys/dev/ata/atapi-cam.c | 6 - sys/dev/buslogic/bt.c | 77 +-- sys/dev/ciss/ciss.c | 30 +- sys/dev/ciss/cissvar.h | 1 + sys/dev/dpt/dpt_scsi.c | 62 +-- sys/dev/firewire/sbp.c | 10 +- sys/dev/hpt27xx/osm_bsd.c | 100 ++-- sys/dev/hptiop/hptiop.c | 61 +-- sys/dev/hptmv/entry.c | 107 ++--- sys/dev/hptrr/hptrr_osm_bsd.c | 106 ++--- sys/dev/iir/iir.c | 99 +--- sys/dev/isci/isci_io_request.c | 35 +- sys/dev/isp/isp_pci.c | 72 +-- sys/dev/isp/isp_sbus.c | 50 +- sys/dev/mfi/mfi.c | 10 +- sys/dev/mfi/mfi_cam.c | 17 +- sys/dev/mfi/mfivar.h | 1 + sys/dev/mly/mly.c | 26 +- sys/dev/mly/mlyvar.h | 1 + sys/dev/mps/mps.c | 3 + sys/dev/mps/mps_sas.c | 27 +- sys/dev/mps/mpsvar.h | 1 + sys/dev/mpt/mpt_cam.c | 120 +---- sys/dev/mvs/mvs.c | 14 +- sys/dev/siis/siis.c | 50 +- sys/dev/sym/sym_hipd.c | 50 +- sys/dev/trm/trm.c | 68 +-- sys/dev/twa/tw_osl.h | 1 + sys/dev/twa/tw_osl_cam.c | 50 +- sys/dev/twa/tw_osl_freebsd.c | 4 + sys/dev/tws/tws.h | 1 + sys/dev/tws/tws_cam.c | 49 +- sys/dev/virtio/scsi/virtio_scsi.c | 41 +- sys/dev/wds/wd7000.c | 2 +- sys/ia64/ia64/busdma_machdep.c | 484 +++++++++---------- sys/kern/subr_bus_dma.c | 460 ++++++++++++++++++ sys/kern/subr_uio.c | 46 ++ sys/mips/mips/busdma_machdep.c | 594 ++++++++++------------- sys/powerpc/powerpc/busdma_machdep.c | 542 ++++++++++----------- sys/powerpc/ps3/ps3cdrom.c | 5 +- sys/sparc64/include/bus_dma.h | 37 +- sys/sparc64/sparc64/bus_machdep.c | 315 +++++------- sys/sparc64/sparc64/iommu.c | 359 +++++++------- sys/sys/bus_dma.h | 108 +++-- sys/sys/memdesc.h | 156 ++++++ sys/sys/uio.h | 2 + sys/x86/x86/busdma_machdep.c | 495 +++++++++---------- 68 files changed, 3108 insertions(+), 3767 deletions(-) create mode 100644 sys/kern/subr_bus_dma.c create mode 100644 sys/sys/memdesc.h diff --git a/sys/arm/arm/busdma_machdep-v6.c b/sys/arm/arm/busdma_machdep-v6.c index 2a7c23ba9bd..0a0bdd85eb6 100644 --- a/sys/arm/arm/busdma_machdep-v6.c +++ b/sys/arm/arm/busdma_machdep-v6.c @@ -46,11 +46,11 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include -#include -#include #include +#include #include #include @@ -111,6 +111,7 @@ struct bounce_page { vm_offset_t vaddr; /* kva of bounce buffer */ bus_addr_t busaddr; /* Physical address */ vm_offset_t datavaddr; /* kva of client data */ + bus_addr_t dataaddr; /* client physical address */ bus_size_t datacount; /* client data count */ STAILQ_ENTRY(bounce_page) links; }; @@ -119,7 +120,6 @@ struct sync_list { vm_offset_t vaddr; /* kva of bounce buffer */ bus_addr_t busaddr; /* Physical address */ bus_size_t datacount; /* client data count */ - STAILQ_ENTRY(sync_list) slinks; }; int busdma_swi_pending; @@ -156,15 +156,15 @@ struct bus_dmamap { int pagesneeded; int pagesreserved; bus_dma_tag_t dmat; - void *buf; /* unmapped buffer pointer */ - bus_size_t buflen; /* unmapped buffer length */ + struct memdesc mem; pmap_t pmap; bus_dmamap_callback_t *callback; void *callback_arg; int flags; #define DMAMAP_COHERENT (1 << 0) STAILQ_ENTRY(bus_dmamap) links; - STAILQ_HEAD(,sync_list) slist; + int sync_count; + struct sync_list slist[]; }; static STAILQ_HEAD(, bus_dmamap) bounce_map_waitinglist; @@ -176,11 +176,16 @@ static int alloc_bounce_pages(bus_dma_tag_t dmat, u_int numpages); static int reserve_bounce_pages(bus_dma_tag_t dmat, bus_dmamap_t map, int commit); static bus_addr_t add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, - vm_offset_t vaddr, bus_size_t size); + vm_offset_t vaddr, bus_addr_t addr, + bus_size_t size); static void free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage); int run_filter(bus_dma_tag_t dmat, bus_addr_t paddr); -static int _bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map, +static void _bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, bus_size_t buflen, int flags); +static void _bus_dmamap_count_phys(bus_dma_tag_t dmat, bus_dmamap_t map, + vm_paddr_t buf, bus_size_t buflen, int flags); +static int _bus_dmamap_reserve_pages(bus_dma_tag_t dmat, bus_dmamap_t map, + int flags); static busdma_bufalloc_t coherent_allocator; /* Cache of coherent buffers */ static busdma_bufalloc_t standard_allocator; /* Cache of standard buffers */ @@ -493,17 +498,18 @@ out: int bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp) { + int mapsize; int error; error = 0; - *mapp = (bus_dmamap_t)malloc(sizeof(**mapp), M_DEVBUF, - M_NOWAIT | M_ZERO); + mapsize = sizeof(**mapp) + (sizeof(struct sync_list) * dmat->nsegments); + *mapp = (bus_dmamap_t)malloc(mapsize, M_DEVBUF, M_NOWAIT | M_ZERO); if (*mapp == NULL) { CTR3(KTR_BUSDMA, "%s: tag %p error %d", __func__, dmat, ENOMEM); return (ENOMEM); } - STAILQ_INIT(&((*mapp)->slist)); + (*mapp)->sync_count = 0; if (dmat->segments == NULL) { dmat->segments = (bus_dma_segment_t *)malloc( @@ -578,8 +584,7 @@ bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp) int bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map) { - if (STAILQ_FIRST(&map->bpages) != NULL || - STAILQ_FIRST(&map->slist) != NULL) { + if (STAILQ_FIRST(&map->bpages) != NULL || map->sync_count != 0) { CTR3(KTR_BUSDMA, "%s: tag %p error %d", __func__, dmat, EBUSY); return (EBUSY); @@ -606,6 +611,7 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, struct busdma_bufzone *bufzone; vm_memattr_t memattr; int mflags; + int mapsize; if (flags & BUS_DMA_NOWAIT) mflags = M_NOWAIT; @@ -614,15 +620,15 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, /* ARM non-snooping caches need a map for the VA cache sync structure */ - *mapp = (bus_dmamap_t)malloc(sizeof(**mapp), M_DEVBUF, - M_NOWAIT | M_ZERO); + mapsize = sizeof(**mapp) + (sizeof(struct sync_list) * dmat->nsegments); + *mapp = (bus_dmamap_t)malloc(mapsize, M_DEVBUF, M_NOWAIT | M_ZERO); if (*mapp == NULL) { CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d", __func__, dmat, dmat->flags, ENOMEM); return (ENOMEM); } - STAILQ_INIT(&((*mapp)->slist)); + (*mapp)->sync_count = 0; if (dmat->segments == NULL) { dmat->segments = (bus_dma_segment_t *)malloc( @@ -733,7 +739,37 @@ bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) CTR3(KTR_BUSDMA, "%s: tag %p flags 0x%x", __func__, dmat, dmat->flags); } -static int +static void +_bus_dmamap_count_phys(bus_dma_tag_t dmat, bus_dmamap_t map, vm_paddr_t buf, + bus_size_t buflen, int flags) +{ + bus_addr_t curaddr; + bus_size_t sgsize; + + if (map->pagesneeded == 0) { + CTR5(KTR_BUSDMA, "lowaddr= %d, boundary= %d, alignment= %d" + " map= %p, pagesneeded= %d", + dmat->lowaddr, dmat->boundary, dmat->alignment, + map, map->pagesneeded); + /* + * Count the number of bounce pages + * needed in order to complete this transfer + */ + curaddr = buf; + while (buflen != 0) { + sgsize = MIN(buflen, dmat->maxsegsz); + if (run_filter(dmat, curaddr) != 0) { + sgsize = MIN(sgsize, PAGE_SIZE); + map->pagesneeded++; + } + curaddr += sgsize; + buflen -= sgsize; + } + CTR1(KTR_BUSDMA, "pagesneeded= %d", map->pagesneeded); + } +} + +static void _bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, bus_size_t buflen, int flags) { @@ -754,12 +790,11 @@ _bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map, vendaddr = (vm_offset_t)buf + buflen; while (vaddr < vendaddr) { - if (__predict_true(map->pmap == pmap_kernel())) + if (__predict_true(map->pmap == kernel_pmap)) paddr = pmap_kextract(vaddr); else paddr = pmap_extract(map->pmap, vaddr); - if (((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) && - run_filter(dmat, paddr) != 0) { + if (run_filter(dmat, paddr) != 0) { map->pagesneeded++; } vaddr += (PAGE_SIZE - ((vm_offset_t)vaddr & PAGE_MASK)); @@ -767,72 +802,190 @@ _bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map, } CTR1(KTR_BUSDMA, "pagesneeded= %d", map->pagesneeded); } +} + +static int +_bus_dmamap_reserve_pages(bus_dma_tag_t dmat, bus_dmamap_t map, int flags) +{ /* Reserve Necessary Bounce Pages */ - if (map->pagesneeded != 0) { - mtx_lock(&bounce_lock); - if (flags & BUS_DMA_NOWAIT) { - if (reserve_bounce_pages(dmat, map, 0) != 0) { - map->pagesneeded = 0; - mtx_unlock(&bounce_lock); - return (ENOMEM); - } - } else { - if (reserve_bounce_pages(dmat, map, 1) != 0) { - /* Queue us for resources */ - map->dmat = dmat; - map->buf = buf; - map->buflen = buflen; - STAILQ_INSERT_TAIL(&bounce_map_waitinglist, - map, links); - mtx_unlock(&bounce_lock); - return (EINPROGRESS); - } + mtx_lock(&bounce_lock); + if (flags & BUS_DMA_NOWAIT) { + if (reserve_bounce_pages(dmat, map, 0) != 0) { + map->pagesneeded = 0; + mtx_unlock(&bounce_lock); + return (ENOMEM); + } + } else { + if (reserve_bounce_pages(dmat, map, 1) != 0) { + /* Queue us for resources */ + STAILQ_INSERT_TAIL(&bounce_map_waitinglist, map, links); + mtx_unlock(&bounce_lock); + return (EINPROGRESS); } - mtx_unlock(&bounce_lock); } + mtx_unlock(&bounce_lock); return (0); } /* - * Utility function to load a linear buffer. lastaddrp holds state - * between invocations (for multiple-buffer loads). segp contains - * the starting segment on entrace, and the ending segment on exit. - * first indicates if this is the first invocation of this function. + * Add a single contiguous physical range to the segment list. */ -static __inline int +static int +_bus_dmamap_addseg(bus_dma_tag_t dmat, bus_dmamap_t map, bus_addr_t curaddr, + bus_size_t sgsize, bus_dma_segment_t *segs, int *segp) +{ + bus_addr_t baddr, bmask; + int seg; + + /* + * Make sure we don't cross any boundaries. + */ + bmask = ~(dmat->boundary - 1); + if (dmat->boundary > 0) { + baddr = (curaddr + dmat->boundary) & bmask; + if (sgsize > (baddr - curaddr)) + sgsize = (baddr - curaddr); + } + + if (dmat->ranges) { + struct arm32_dma_range *dr; + + dr = _bus_dma_inrange(dmat->ranges, dmat->_nranges, + curaddr); + if (dr == NULL) { + _bus_dmamap_unload(dmat, map); + return (EINVAL); + } + /* + * In a valid DMA range. Translate the physical + * memory address to an address in the DMA window. + */ + curaddr = (curaddr - dr->dr_sysbase) + dr->dr_busbase; + } + + /* + * Insert chunk into a segment, coalescing with + * previous segment if possible. + */ + seg = *segp; + if (seg == -1) { + seg = 0; + segs[seg].ds_addr = curaddr; + segs[seg].ds_len = sgsize; + } else { + if (curaddr == segs[seg].ds_addr + segs[seg].ds_len && + (segs[seg].ds_len + sgsize) <= dmat->maxsegsz && + (dmat->boundary == 0 || + (segs[seg].ds_addr & bmask) == (curaddr & bmask))) + segs[seg].ds_len += sgsize; + else { + if (++seg >= dmat->nsegments) + return (0); + segs[seg].ds_addr = curaddr; + segs[seg].ds_len = sgsize; + } + } + *segp = seg; + return (sgsize); +} + +/* + * Utility function to load a physical buffer. segp contains + * the starting segment on entrace, and the ending segment on exit. + */ +int +_bus_dmamap_load_phys(bus_dma_tag_t dmat, + bus_dmamap_t map, + vm_paddr_t buf, bus_size_t buflen, + int flags, + bus_dma_segment_t *segs, + int *segp) +{ + bus_addr_t curaddr; + bus_size_t sgsize; + int error; + + if (segs == NULL) + segs = dmat->segments; + + if ((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) { + _bus_dmamap_count_phys(dmat, map, buf, buflen, flags); + if (map->pagesneeded != 0) { + error = _bus_dmamap_reserve_pages(dmat, map, flags); + if (error) + return (error); + } + } + + while (buflen > 0) { + curaddr = buf; + sgsize = MIN(buflen, dmat->maxsegsz); + if (((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) && + map->pagesneeded != 0 && run_filter(dmat, curaddr)) { + sgsize = MIN(sgsize, PAGE_SIZE); + curaddr = add_bounce_page(dmat, map, 0, curaddr, + sgsize); + } + sgsize = _bus_dmamap_addseg(dmat, map, curaddr, sgsize, segs, + segp); + if (sgsize == 0) + break; + buf += sgsize; + buflen -= sgsize; + } + + /* + * Did we fit? + */ + if (buflen != 0) { + _bus_dmamap_unload(dmat, map); + return (EFBIG); /* XXX better return value here? */ + } + return (0); +} + +/* + * Utility function to load a linear buffer. segp contains + * the starting segment on entrace, and the ending segment on exit. + */ +int _bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, bus_size_t buflen, + pmap_t pmap, int flags, - bus_addr_t *lastaddrp, bus_dma_segment_t *segs, - int *segp, - int first) + int *segp) { bus_size_t sgsize; - bus_addr_t curaddr, lastaddr, baddr, bmask; + bus_addr_t curaddr; vm_offset_t vaddr; struct sync_list *sl; - int seg, error; + int error; + + if (segs == NULL) + segs = dmat->segments; if ((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) { - error = _bus_dmamap_count_pages(dmat, map, buf, buflen, flags); - if (error) - return (error); + _bus_dmamap_count_pages(dmat, map, buf, buflen, flags); + if (map->pagesneeded != 0) { + error = _bus_dmamap_reserve_pages(dmat, map, flags); + if (error) + return (error); + } } sl = NULL; vaddr = (vm_offset_t)buf; - lastaddr = *lastaddrp; - bmask = ~(dmat->boundary - 1); + map->pmap = pmap; - for (seg = *segp; buflen > 0 ; ) { + while (buflen > 0) { /* * Get the physical address for this segment. */ - if (__predict_true(map->pmap == pmap_kernel())) + if (__predict_true(map->pmap == kernel_pmap)) curaddr = pmap_kextract(vaddr); else curaddr = pmap_extract(map->pmap, vaddr); @@ -846,259 +999,63 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dmat, if (buflen < sgsize) sgsize = buflen; - /* - * Make sure we don't cross any boundaries. - */ - if (dmat->boundary > 0) { - baddr = (curaddr + dmat->boundary) & bmask; - if (sgsize > (baddr - curaddr)) - sgsize = (baddr - curaddr); - } - if (((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) && map->pagesneeded != 0 && run_filter(dmat, curaddr)) { - curaddr = add_bounce_page(dmat, map, vaddr, sgsize); + curaddr = add_bounce_page(dmat, map, vaddr, curaddr, + sgsize); } else { - /* add_sync_list(dmat, map, vaddr, sgsize, cflag); */ - sl = (struct sync_list *)malloc(sizeof(struct sync_list), - M_DEVBUF, M_NOWAIT | M_ZERO); - if (sl == NULL) - goto cleanup; - STAILQ_INSERT_TAIL(&(map->slist), sl, slinks); - sl->vaddr = vaddr; - sl->datacount = sgsize; - sl->busaddr = curaddr; + sl = &map->slist[map->sync_count - 1]; + if (map->sync_count == 0 || + vaddr != sl->vaddr + sl->datacount) { + if (++map->sync_count > dmat->nsegments) + goto cleanup; + sl++; + sl->vaddr = vaddr; + sl->datacount = sgsize; + sl->busaddr = curaddr; + } else + sl->datacount += sgsize; } - - - if (dmat->ranges) { - struct arm32_dma_range *dr; - - dr = _bus_dma_inrange(dmat->ranges, dmat->_nranges, - curaddr); - if (dr == NULL) { - _bus_dmamap_unload(dmat, map); - return (EINVAL); - } - /* - * In a valid DMA range. Translate the physical - * memory address to an address in the DMA window. - */ - curaddr = (curaddr - dr->dr_sysbase) + dr->dr_busbase; - } - - /* - * Insert chunk into a segment, coalescing with - * previous segment if possible. - */ - if (first) { - segs[seg].ds_addr = curaddr; - segs[seg].ds_len = sgsize; - first = 0; - } else { - if (curaddr == lastaddr && - (segs[seg].ds_len + sgsize) <= dmat->maxsegsz && - (dmat->boundary == 0 || - (segs[seg].ds_addr & bmask) == (curaddr & bmask))) - segs[seg].ds_len += sgsize; - else { - if (++seg >= dmat->nsegments) - break; - segs[seg].ds_addr = curaddr; - segs[seg].ds_len = sgsize; - } - } - - lastaddr = curaddr + sgsize; + sgsize = _bus_dmamap_addseg(dmat, map, curaddr, sgsize, segs, + segp); + if (sgsize == 0) + break; vaddr += sgsize; buflen -= sgsize; } - *segp = seg; - *lastaddrp = lastaddr; cleanup: /* * Did we fit? */ if (buflen != 0) { _bus_dmamap_unload(dmat, map); - return(EFBIG); /* XXX better return value here? */ + return (EFBIG); /* XXX better return value here? */ } return (0); } -/* - * Map the buffer buf into bus space using the dmamap map. - */ -int -bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, - bus_size_t buflen, bus_dmamap_callback_t *callback, - void *callback_arg, int flags) -{ - bus_addr_t lastaddr = 0; - int error, nsegs = 0; - flags |= BUS_DMA_WAITOK; +void +__bus_dmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map, + struct memdesc *mem, bus_dmamap_callback_t *callback, + void *callback_arg) +{ + + map->mem = *mem; + map->dmat = dmat; map->callback = callback; map->callback_arg = callback_arg; - map->pmap = kernel_pmap; - - error = _bus_dmamap_load_buffer(dmat, map, buf, buflen, flags, - &lastaddr, dmat->segments, &nsegs, 1); - - CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", - __func__, dmat, dmat->flags, error, nsegs + 1); - - if (error == EINPROGRESS) { - return (error); - } - - if (error) - (*callback)(callback_arg, dmat->segments, 0, error); - else - (*callback)(callback_arg, dmat->segments, nsegs + 1, 0); - - /* - * Return ENOMEM to the caller so that it can pass it up the stack. - * This error only happens when NOWAIT is set, so deferal is disabled. - */ - if (error == ENOMEM) - return (error); - - return (0); } - -/* - * Like _bus_dmamap_load(), but for mbufs. - */ -static __inline int -_bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map, - struct mbuf *m0, bus_dma_segment_t *segs, int *nsegs, - int flags) +bus_dma_segment_t * +_bus_dmamap_complete(bus_dma_tag_t dmat, bus_dmamap_t map, + bus_dma_segment_t *segs, int nsegs, int error) { - int error; - M_ASSERTPKTHDR(m0); - map->pmap = kernel_pmap; - - flags |= BUS_DMA_NOWAIT; - *nsegs = 0; - error = 0; - if (m0->m_pkthdr.len <= dmat->maxsize) { - int first = 1; - bus_addr_t lastaddr = 0; - struct mbuf *m; - - for (m = m0; m != NULL && error == 0; m = m->m_next) { - if (m->m_len > 0) { - error = _bus_dmamap_load_buffer(dmat, map, - m->m_data, m->m_len, - flags, &lastaddr, - segs, nsegs, first); - first = 0; - } - } - } else { - error = EINVAL; - } - - /* XXX FIXME: Having to increment nsegs is really annoying */ - ++*nsegs; - CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", - __func__, dmat, dmat->flags, error, *nsegs); - return (error); -} - -int -bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, - struct mbuf *m0, - bus_dmamap_callback2_t *callback, void *callback_arg, - int flags) -{ - int nsegs, error; - - error = _bus_dmamap_load_mbuf_sg(dmat, map, m0, dmat->segments, &nsegs, - flags); - - if (error) { - /* force "no valid mappings" in callback */ - (*callback)(callback_arg, dmat->segments, 0, 0, error); - } else { - (*callback)(callback_arg, dmat->segments, - nsegs, m0->m_pkthdr.len, error); - } - CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", - __func__, dmat, dmat->flags, error, nsegs); - - return (error); -} - -int -bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map, - struct mbuf *m0, bus_dma_segment_t *segs, int *nsegs, - int flags) -{ - return (_bus_dmamap_load_mbuf_sg(dmat, map, m0, segs, nsegs, flags)); -} - -/* - * Like _bus_dmamap_load(), but for uios. - */ -int -bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, - struct uio *uio, - bus_dmamap_callback2_t *callback, void *callback_arg, - int flags) -{ - bus_addr_t lastaddr; - int nsegs, error, first, i; - bus_size_t resid; - struct iovec *iov; - - flags |= BUS_DMA_NOWAIT; - resid = uio->uio_resid; - iov = uio->uio_iov; - - if (uio->uio_segflg == UIO_USERSPACE) { - KASSERT(uio->uio_td != NULL, - ("bus_dmamap_load_uio: USERSPACE but no proc")); - map->pmap = vmspace_pmap(uio->uio_td->td_proc->p_vmspace); - } else - map->pmap = kernel_pmap; - - nsegs = 0; - error = 0; - first = 1; - lastaddr = (bus_addr_t) 0; - for (i = 0; i < uio->uio_iovcnt && resid != 0 && !error; i++) { - /* - * Now at the first iovec to load. Load each iovec - * until we have exhausted the residual count. - */ - bus_size_t minlen = - resid < iov[i].iov_len ? resid : iov[i].iov_len; - caddr_t addr = (caddr_t) iov[i].iov_base; - - if (minlen > 0) { - error = _bus_dmamap_load_buffer(dmat, map, - addr, minlen, flags, &lastaddr, - dmat->segments, &nsegs, first); - first = 0; - resid -= minlen; - } - } - - if (error) { - /* force "no valid mappings" in callback */ - (*callback)(callback_arg, dmat->segments, 0, 0, error); - } else { - (*callback)(callback_arg, dmat->segments, - nsegs+1, uio->uio_resid, error); - } - CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", - __func__, dmat, dmat->flags, error, nsegs + 1); - return (error); + if (segs == NULL) + segs = dmat->segments; + return (segs); } /* @@ -1109,12 +1066,6 @@ _bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map) { struct bounce_page *bpage; struct bounce_zone *bz; - struct sync_list *sl; - - while ((sl = STAILQ_FIRST(&map->slist)) != NULL) { - STAILQ_REMOVE_HEAD(&map->slist, slinks); - free(sl, M_DEVBUF); - } if ((bz = dmat->bounce_zone) != NULL) { while ((bpage = STAILQ_FIRST(&map->bpages)) != NULL) { @@ -1128,6 +1079,7 @@ _bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map) map->pagesreserved = 0; map->pagesneeded = 0; } + map->sync_count = 0; } #ifdef notyetbounceuser @@ -1187,15 +1139,13 @@ void _bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op) { struct bounce_page *bpage; - struct sync_list *sl; + struct sync_list *sl, *end; bus_size_t len, unalign; vm_offset_t buf, ebuf; #ifdef FIX_DMAP_BUS_DMASYNC_POSTREAD vm_offset_t bbuf; char _tmp_cl[arm_dcache_align], _tmp_clend[arm_dcache_align]; #endif - int listcount = 0; - /* if buffer was from user space, it it possible that this * is not the same vm map. The fix is to map each page in * the buffer into the current address space (KVM) and then @@ -1215,9 +1165,14 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op) if (op & BUS_DMASYNC_PREWRITE) { while (bpage != NULL) { - bcopy((void *)bpage->datavaddr, - (void *)bpage->vaddr, - bpage->datacount); + if (bpage->datavaddr != 0) + bcopy((void *)bpage->datavaddr, + (void *)bpage->vaddr, + bpage->datacount); + else + physcopyout(bpage->dataaddr, + (void *)bpage->vaddr, + bpage->datacount); cpu_dcache_wb_range((vm_offset_t)bpage->vaddr, bpage->datacount); l2cache_wb_range((vm_offset_t)bpage->vaddr, @@ -1254,9 +1209,14 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op) arm_dcache_align; cpu_dcache_inv_range(startv, len); l2cache_inv_range(startv, startp, len); - bcopy((void *)bpage->vaddr, - (void *)bpage->datavaddr, - bpage->datacount); + if (bpage->datavaddr != 0) + bcopy((void *)bpage->vaddr, + (void *)bpage->datavaddr, + bpage->datacount); + else + physcopyin((void *)bpage->vaddr, + bpage->dataaddr, + bpage->datacount); bpage = STAILQ_NEXT(bpage, links); } dmat->bounce_zone->total_bounced++; @@ -1265,29 +1225,26 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op) if (map->flags & DMAMAP_COHERENT) return; - sl = STAILQ_FIRST(&map->slist); - while (sl) { - listcount++; - sl = STAILQ_NEXT(sl, slinks); - } - if ((sl = STAILQ_FIRST(&map->slist)) != NULL) { + if (map->sync_count != 0) { /* ARM caches are not self-snooping for dma */ + sl = &map->slist[0]; + end = &map->slist[map->sync_count]; CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x op 0x%x " "performing sync", __func__, dmat, dmat->flags, op); switch (op) { case BUS_DMASYNC_PREWRITE: - while (sl != NULL) { + while (sl != end) { cpu_dcache_wb_range(sl->vaddr, sl->datacount); l2cache_wb_range(sl->vaddr, sl->busaddr, sl->datacount); - sl = STAILQ_NEXT(sl, slinks); + sl++; } break; case BUS_DMASYNC_PREREAD: - while (sl != NULL) { + while (sl != end) { /* write back the unaligned portions */ vm_paddr_t physaddr = sl->busaddr, ephysaddr; buf = sl->vaddr; @@ -1327,16 +1284,16 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op) cpu_dcache_inv_range(buf, len); l2cache_inv_range(buf, physaddr, len); } - sl = STAILQ_NEXT(sl, slinks); + sl++; } break; case BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD: - while (sl != NULL) { + while (sl != end) { cpu_dcache_wbinv_range(sl->vaddr, sl->datacount); l2cache_wbinv_range(sl->vaddr, sl->busaddr, sl->datacount); - sl = STAILQ_NEXT(sl, slinks); + sl++; } break; @@ -1344,7 +1301,7 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op) case BUS_DMASYNC_POSTREAD: if (!pmap_dmap_iscurrent(map->pmap)) panic("_bus_dmamap_sync: wrong user map. apply fix"); - while (sl != NULL) { + while (sl != end) { /* write back the unaligned portions */ vm_paddr_t physaddr; register_t s = 0; @@ -1391,7 +1348,7 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op) intr_restore(s); } - sl = STAILQ_NEXT(sl, slinks); + sl++; } break; #endif /* FIX_DMAP_BUS_DMASYNC_POSTREAD */ @@ -1559,7 +1516,7 @@ reserve_bounce_pages(bus_dma_tag_t dmat, bus_dmamap_t map, int commit) static bus_addr_t add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, vm_offset_t vaddr, - bus_size_t size) + bus_addr_t addr, bus_size_t size) { struct bounce_zone *bz; struct bounce_page *bpage; @@ -1593,6 +1550,7 @@ add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, vm_offset_t vaddr, bpage->busaddr |= vaddr & PAGE_MASK; } bpage->datavaddr = vaddr; + bpage->dataaddr = addr; bpage->datacount = size; STAILQ_INSERT_TAIL(&(map->bpages), bpage, links); return (bpage->busaddr); @@ -1646,8 +1604,8 @@ busdma_swi(void) mtx_unlock(&bounce_lock); dmat = map->dmat; (dmat->lockfunc)(dmat->lockfuncarg, BUS_DMA_LOCK); - bus_dmamap_load(map->dmat, map, map->buf, map->buflen, - map->callback, map->callback_arg, /*flags*/0); + bus_dmamap_load_mem(map->dmat, map, &map->mem, map->callback, + map->callback_arg, BUS_DMA_WAITOK); (dmat->lockfunc)(dmat->lockfuncarg, BUS_DMA_UNLOCK); mtx_lock(&bounce_lock); } diff --git a/sys/arm/arm/busdma_machdep.c b/sys/arm/arm/busdma_machdep.c index fa7afd496ff..f31a7fec336 100644 --- a/sys/arm/arm/busdma_machdep.c +++ b/sys/arm/arm/busdma_machdep.c @@ -61,12 +61,12 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include -#include -#include #include #include #include +#include #include #include @@ -125,10 +125,17 @@ struct bounce_page { vm_offset_t vaddr_nocache; /* kva of bounce buffer uncached */ bus_addr_t busaddr; /* Physical address */ vm_offset_t datavaddr; /* kva of client data */ + bus_addr_t dataaddr; /* client physical address */ bus_size_t datacount; /* client data count */ STAILQ_ENTRY(bounce_page) links; }; +struct sync_list { + vm_offset_t vaddr; /* kva of bounce buffer */ + bus_addr_t busaddr; /* Physical address */ + bus_size_t datacount; /* client data count */ +}; + int busdma_swi_pending; struct bounce_zone { @@ -158,24 +165,21 @@ static SYSCTL_NODE(_hw, OID_AUTO, busdma, CTLFLAG_RD, 0, "Busdma parameters"); SYSCTL_INT(_hw_busdma, OID_AUTO, total_bpages, CTLFLAG_RD, &total_bpages, 0, "Total bounce pages"); -#define DMAMAP_LINEAR 0x1 -#define DMAMAP_MBUF 0x2 -#define DMAMAP_UIO 0x4 -#define DMAMAP_CACHE_ALIGNED 0x10 -#define DMAMAP_TYPE_MASK (DMAMAP_LINEAR|DMAMAP_MBUF|DMAMAP_UIO) #define DMAMAP_COHERENT 0x8 +#define DMAMAP_CACHE_ALIGNED 0x10 + struct bus_dmamap { struct bp_list bpages; int pagesneeded; int pagesreserved; bus_dma_tag_t dmat; + struct memdesc mem; int flags; - void *buffer; - int len; STAILQ_ENTRY(bus_dmamap) links; bus_dmamap_callback_t *callback; void *callback_arg; - + int sync_count; + struct sync_list *slist; }; static STAILQ_HEAD(, bus_dmamap) bounce_map_waitinglist; @@ -191,7 +195,8 @@ static int alloc_bounce_pages(bus_dma_tag_t dmat, u_int numpages); static int reserve_bounce_pages(bus_dma_tag_t dmat, bus_dmamap_t map, int commit); static bus_addr_t add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, - vm_offset_t vaddr, bus_size_t size); + vm_offset_t vaddr, bus_addr_t addr, + bus_size_t size); static void free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage); /* Default tag, as most drivers provide no parent tag. */ @@ -564,13 +569,20 @@ bus_dma_tag_destroy(bus_dma_tag_t dmat) int bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp) { + struct sync_list *slist; bus_dmamap_t map; int error = 0; + slist = malloc(sizeof(*slist) * dmat->nsegments, M_DEVBUF, M_NOWAIT); + if (slist == NULL) + return (ENOMEM); + map = uma_zalloc_arg(dmamap_zone, dmat, M_NOWAIT); *mapp = map; - if (map == NULL) + if (map == NULL) { + free(slist, M_DEVBUF); return (ENOMEM); + } /* * If the tag's segments haven't been allocated yet we need to do it @@ -580,6 +592,7 @@ bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp) dmat->segments = malloc(dmat->nsegments * sizeof(*dmat->segments), M_DEVBUF, M_NOWAIT); if (dmat->segments == NULL) { + free(slist, M_DEVBUF); uma_zfree(dmamap_zone, map); *mapp = NULL; return (ENOMEM); @@ -599,6 +612,7 @@ bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp) if (dmat->bounce_zone == NULL) { if ((error = alloc_bounce_zone(dmat)) != 0) { + free(slist, M_DEVBUF); uma_zfree(dmamap_zone, map); *mapp = NULL; return (error); @@ -633,6 +647,8 @@ bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp) } bz->map_count++; } + map->sync_count = 0; + map->slist = slist; CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d", __func__, dmat, dmat->flags, error); @@ -647,11 +663,12 @@ int bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map) { - if (STAILQ_FIRST(&map->bpages) != NULL) { + if (STAILQ_FIRST(&map->bpages) != NULL || map->sync_count != 0) { CTR3(KTR_BUSDMA, "%s: tag %p error %d", __func__, dmat, EBUSY); return (EBUSY); } + free(map->slist, M_DEVBUF); uma_zfree(dmamap_zone, map); if (dmat->bounce_zone) dmat->bounce_zone->map_count--; @@ -668,6 +685,7 @@ int bus_dmamem_alloc(bus_dma_tag_t dmat, void **vaddrp, int flags, bus_dmamap_t *mapp) { + struct sync_list *slist; void * vaddr; struct busdma_bufzone *bufzone; busdma_bufalloc_t ba; @@ -679,7 +697,6 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void **vaddrp, int flags, mflags = M_NOWAIT; else mflags = M_WAITOK; - /* * If the tag's segments haven't been allocated yet we need to do it * now, because we can't sleep for resources at map load time. @@ -688,10 +705,14 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void **vaddrp, int flags, dmat->segments = malloc(dmat->nsegments * sizeof(*dmat->segments), M_DEVBUF, mflags); - map = uma_zalloc_arg(dmamap_zone, dmat, mflags); - if (map == NULL) + slist = malloc(sizeof(*slist) * dmat->nsegments, M_DEVBUF, M_NOWAIT); + if (slist == NULL) return (ENOMEM); - + map = uma_zalloc_arg(dmamap_zone, dmat, mflags); + if (map == NULL) { + free(slist, M_DEVBUF); + return (ENOMEM); + } if (flags & BUS_DMA_COHERENT) { memattr = VM_MEMATTR_UNCACHEABLE; ba = coherent_allocator; @@ -738,12 +759,14 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void **vaddrp, int flags, mflags, 0, dmat->lowaddr, dmat->alignment, dmat->boundary, memattr); } - if (vaddr == NULL) { + free(slist, M_DEVBUF); uma_zfree(dmamap_zone, map); map = NULL; + } else { + map->slist = slist; + map->sync_count = 0; } - *vaddrp = vaddr; *mapp = map; @@ -762,10 +785,11 @@ bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) if (map->flags & DMAMAP_COHERENT) ba = coherent_allocator; - else + else ba = standard_allocator; - uma_zfree(dmamap_zone, map); + uma_zfree(dmamap_zone, map); + free(map->slist, M_DEVBUF); /* Be careful not to access map from here on. */ bufzone = busdma_bufalloc_findzone(ba, dmat->maxsize); @@ -777,7 +801,37 @@ bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) kmem_free(kernel_map, (vm_offset_t)vaddr, dmat->maxsize); } -static int +static void +_bus_dmamap_count_phys(bus_dma_tag_t dmat, bus_dmamap_t map, vm_paddr_t buf, + bus_size_t buflen, int flags) +{ + bus_addr_t curaddr; + bus_size_t sgsize; + + if ((map->pagesneeded == 0)) { + CTR3(KTR_BUSDMA, "lowaddr= %d, boundary= %d, alignment= %d", + dmat->lowaddr, dmat->boundary, dmat->alignment); + CTR2(KTR_BUSDMA, "map= %p, pagesneeded= %d", + map, map->pagesneeded); + /* + * Count the number of bounce pages + * needed in order to complete this transfer + */ + curaddr = buf; + while (buflen != 0) { + sgsize = MIN(buflen, dmat->maxsegsz); + if (run_filter(dmat, curaddr) != 0) { + sgsize = MIN(sgsize, PAGE_SIZE); + map->pagesneeded++; + } + curaddr += sgsize; + buflen -= sgsize; + } + CTR1(KTR_BUSDMA, "pagesneeded= %d\n", map->pagesneeded); + } +} + +static void _bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map, pmap_t pmap, void *buf, bus_size_t buflen, int flags) { @@ -798,75 +852,183 @@ _bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map, pmap_t pmap, vendaddr = (vm_offset_t)buf + buflen; while (vaddr < vendaddr) { - if (__predict_true(pmap == pmap_kernel())) + if (__predict_true(pmap == kernel_pmap)) paddr = pmap_kextract(vaddr); else paddr = pmap_extract(pmap, vaddr); - if (((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) && - run_filter(dmat, paddr) != 0) + if (run_filter(dmat, paddr) != 0) map->pagesneeded++; vaddr += PAGE_SIZE; } CTR1(KTR_BUSDMA, "pagesneeded= %d\n", map->pagesneeded); } +} + +static int +_bus_dmamap_reserve_pages(bus_dma_tag_t dmat, bus_dmamap_t map, int flags) +{ /* Reserve Necessary Bounce Pages */ - if (map->pagesneeded != 0) { - mtx_lock(&bounce_lock); - if (flags & BUS_DMA_NOWAIT) { - if (reserve_bounce_pages(dmat, map, 0) != 0) { - mtx_unlock(&bounce_lock); - return (ENOMEM); - } - } else { - if (reserve_bounce_pages(dmat, map, 1) != 0) { - /* Queue us for resources */ - STAILQ_INSERT_TAIL(&bounce_map_waitinglist, - map, links); - mtx_unlock(&bounce_lock); - return (EINPROGRESS); - } + mtx_lock(&bounce_lock); + if (flags & BUS_DMA_NOWAIT) { + if (reserve_bounce_pages(dmat, map, 0) != 0) { + mtx_unlock(&bounce_lock); + return (ENOMEM); + } + } else { + if (reserve_bounce_pages(dmat, map, 1) != 0) { + /* Queue us for resources */ + STAILQ_INSERT_TAIL(&bounce_map_waitinglist, map, links); + mtx_unlock(&bounce_lock); + return (EINPROGRESS); } - mtx_unlock(&bounce_lock); } + mtx_unlock(&bounce_lock); return (0); } /* - * Utility function to load a linear buffer. lastaddrp holds state - * between invocations (for multiple-buffer loads). segp contains - * the starting segment on entrance, and the ending segment on exit. - * first indicates if this is the first invocation of this function. + * Add a single contiguous physical range to the segment list. */ -static __inline int -bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dma_segment_t *segs, - bus_dmamap_t map, void *buf, bus_size_t buflen, struct pmap *pmap, - int flags, vm_offset_t *lastaddrp, int *segp) +static int +_bus_dmamap_addseg(bus_dma_tag_t dmat, bus_dmamap_t map, bus_addr_t curaddr, + bus_size_t sgsize, bus_dma_segment_t *segs, int *segp) +{ + bus_addr_t baddr, bmask; + int seg; + + /* + * Make sure we don't cross any boundaries. + */ + bmask = ~(dmat->boundary - 1); + if (dmat->boundary > 0) { + baddr = (curaddr + dmat->boundary) & bmask; + if (sgsize > (baddr - curaddr)) + sgsize = (baddr - curaddr); + } + if (dmat->ranges) { + struct arm32_dma_range *dr; + + dr = _bus_dma_inrange(dmat->ranges, dmat->_nranges, + curaddr); + if (dr == NULL) + return (EINVAL); + /* + * In a valid DMA range. Translate the physical + * memory address to an address in the DMA window. + */ + curaddr = (curaddr - dr->dr_sysbase) + dr->dr_busbase; + + } + + seg = *segp; + /* + * Insert chunk into a segment, coalescing with + * the previous segment if possible. + */ + if (seg >= 0 && + curaddr == segs[seg].ds_addr + segs[seg].ds_len && + (segs[seg].ds_len + sgsize) <= dmat->maxsegsz && + (dmat->boundary == 0 || + (segs[seg].ds_addr & bmask) == (curaddr & bmask))) { + segs[seg].ds_len += sgsize; + } else { + if (++seg >= dmat->nsegments) + return (EFBIG); + segs[seg].ds_addr = curaddr; + segs[seg].ds_len = sgsize; + } + *segp = seg; + return (0); +} + +/* + * Utility function to load a physical buffer. segp contains + * the starting segment on entrace, and the ending segment on exit. + */ +int +_bus_dmamap_load_phys(bus_dma_tag_t dmat, bus_dmamap_t map, vm_paddr_t buf, + bus_size_t buflen, int flags, bus_dma_segment_t *segs, int *segp) { bus_size_t sgsize; - bus_addr_t curaddr, lastaddr, baddr, bmask; - vm_offset_t vaddr = (vm_offset_t)buf; - int seg; - int error = 0; + bus_addr_t curaddr; + int error; - lastaddr = *lastaddrp; - bmask = ~(dmat->boundary - 1); + if (segs == NULL) + segs = dmat->segments; if ((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) { - error = _bus_dmamap_count_pages(dmat, map, pmap, buf, buflen, - flags); - if (error) - return (error); + _bus_dmamap_count_phys(dmat, map, buf, buflen, flags); + if (map->pagesneeded != 0) { + error = _bus_dmamap_reserve_pages(dmat, map, flags); + if (error) + return (error); + } + } + + while (buflen > 0) { + curaddr = buf; + sgsize = MIN(buflen, dmat->maxsegsz); + if (((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) && + map->pagesneeded != 0 && run_filter(dmat, curaddr)) { + sgsize = MIN(sgsize, PAGE_SIZE); + curaddr = add_bounce_page(dmat, map, 0, curaddr, + sgsize); + } + sgsize = _bus_dmamap_addseg(dmat, map, curaddr, sgsize, segs, + segp); + if (sgsize == 0) + break; + buf += sgsize; + buflen -= sgsize; + } + + /* + * Did we fit? + */ + if (buflen != 0) { + _bus_dmamap_unload(dmat, map); + return (EFBIG); /* XXX better return value here? */ + } + return (0); +} +/* + * Utility function to load a linear buffer. segp contains + * the starting segment on entrance, and the ending segment on exit. + */ +int +_bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, + bus_size_t buflen, struct pmap *pmap, int flags, bus_dma_segment_t *segs, + int *segp) +{ + bus_size_t sgsize; + bus_addr_t curaddr; + struct sync_list *sl; + vm_offset_t vaddr = (vm_offset_t)buf; + int error = 0; + + if (segs == NULL) + segs = dmat->segments; + if ((flags & BUS_DMA_LOAD_MBUF) != 0) + map->flags |= DMAMAP_CACHE_ALIGNED; + + if ((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) { + _bus_dmamap_count_pages(dmat, map, pmap, buf, buflen, flags); + if (map->pagesneeded != 0) { + error = _bus_dmamap_reserve_pages(dmat, map, flags); + if (error) + return (error); + } } CTR3(KTR_BUSDMA, "lowaddr= %d boundary= %d, " "alignment= %d", dmat->lowaddr, dmat->boundary, dmat->alignment); - for (seg = *segp; buflen > 0 ; ) { + while (buflen > 0) { /* * Get the physical address for this segment. */ - if (__predict_true(pmap == pmap_kernel())) { + if (__predict_true(pmap == kernel_pmap)) { curaddr = pmap_kextract(vaddr); } else { curaddr = pmap_extract(pmap, vaddr); @@ -882,260 +1044,63 @@ bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dma_segment_t *segs, if (buflen < sgsize) sgsize = buflen; - /* - * Make sure we don't cross any boundaries. - */ - if (dmat->boundary > 0) { - baddr = (curaddr + dmat->boundary) & bmask; - if (sgsize > (baddr - curaddr)) - sgsize = (baddr - curaddr); - } if (((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) && - map->pagesneeded != 0 && run_filter(dmat, curaddr)) - curaddr = add_bounce_page(dmat, map, vaddr, sgsize); - - if (dmat->ranges) { - struct arm32_dma_range *dr; - - dr = _bus_dma_inrange(dmat->ranges, dmat->_nranges, - curaddr); - if (dr == NULL) - return (EINVAL); - /* - * In a valid DMA range. Translate the physical - * memory address to an address in the DMA window. - */ - curaddr = (curaddr - dr->dr_sysbase) + dr->dr_busbase; - - } - - /* - * Insert chunk into a segment, coalescing with - * the previous segment if possible. - */ - if (seg >= 0 && curaddr == lastaddr && - (segs[seg].ds_len + sgsize) <= dmat->maxsegsz && - (dmat->boundary == 0 || - (segs[seg].ds_addr & bmask) == - (curaddr & bmask))) { - segs[seg].ds_len += sgsize; - goto segdone; + map->pagesneeded != 0 && run_filter(dmat, curaddr)) { + curaddr = add_bounce_page(dmat, map, vaddr, curaddr, + sgsize); } else { - if (++seg >= dmat->nsegments) - break; - segs[seg].ds_addr = curaddr; - segs[seg].ds_len = sgsize; + sl = &map->slist[map->sync_count - 1]; + if (map->sync_count == 0 || + vaddr != sl->vaddr + sl->datacount) { + if (++map->sync_count > dmat->nsegments) + goto cleanup; + sl++; + sl->vaddr = vaddr; + sl->datacount = sgsize; + sl->busaddr = curaddr; + } else + sl->datacount += sgsize; } - if (error) + sgsize = _bus_dmamap_addseg(dmat, map, curaddr, sgsize, segs, + segp); + if (sgsize == 0) break; -segdone: - lastaddr = curaddr + sgsize; vaddr += sgsize; buflen -= sgsize; } - *segp = seg; - *lastaddrp = lastaddr; - +cleanup: /* * Did we fit? */ - if (buflen != 0) - error = EFBIG; /* XXX better return value here? */ - return (error); + if (buflen != 0) { + _bus_dmamap_unload(dmat, map); + return (EFBIG); /* XXX better return value here? */ + } + return (0); } -/* - * Map the buffer buf into bus space using the dmamap map. - */ -int -bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, - bus_size_t buflen, bus_dmamap_callback_t *callback, - void *callback_arg, int flags) +void +__bus_dmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map, + struct memdesc *mem, bus_dmamap_callback_t *callback, + void *callback_arg) { - vm_offset_t lastaddr = 0; - int error, nsegs = -1; KASSERT(dmat != NULL, ("dmatag is NULL")); KASSERT(map != NULL, ("dmamap is NULL")); + map->mem = *mem; map->callback = callback; map->callback_arg = callback_arg; - map->flags &= ~DMAMAP_TYPE_MASK; - map->flags |= DMAMAP_LINEAR; - map->buffer = buf; - map->len = buflen; - error = bus_dmamap_load_buffer(dmat, - dmat->segments, map, buf, buflen, kernel_pmap, - flags, &lastaddr, &nsegs); - if (error == EINPROGRESS) - return (error); - if (error) - (*callback)(callback_arg, NULL, 0, error); - else - (*callback)(callback_arg, dmat->segments, nsegs + 1, error); - - CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", - __func__, dmat, dmat->flags, nsegs + 1, error); - - return (error); } -/* - * Like bus_dmamap_load(), but for mbufs. - * - * Note that the manpage states that BUS_DMA_NOWAIT is implied for mbufs. - * - * We know that the way the system allocates and uses mbufs implies that we can - * treat them as DMAMAP_CACHE_ALIGNED in terms of handling partial cache line - * flushes. Even though the flush may reference the data area within the mbuf - * that isn't aligned to a cache line, we know the overall mbuf itself is - * properly aligned, and we know that the CPU will not touch the header fields - * before the data area while the DMA is in progress. - */ -int -bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m0, - bus_dmamap_callback2_t *callback, void *callback_arg, - int flags) +bus_dma_segment_t * +_bus_dmamap_complete(bus_dma_tag_t dmat, bus_dmamap_t map, + bus_dma_segment_t *segs, int nsegs, int error) { - int nsegs = -1, error = 0; - M_ASSERTPKTHDR(m0); - - flags |= BUS_DMA_NOWAIT; - map->flags &= ~DMAMAP_TYPE_MASK; - map->flags |= DMAMAP_MBUF | DMAMAP_CACHE_ALIGNED; - map->buffer = m0; - map->len = 0; - if (m0->m_pkthdr.len <= dmat->maxsize) { - vm_offset_t lastaddr = 0; - struct mbuf *m; - - for (m = m0; m != NULL && error == 0; m = m->m_next) { - if (m->m_len > 0) { - error = bus_dmamap_load_buffer(dmat, - dmat->segments, map, m->m_data, m->m_len, - pmap_kernel(), flags, &lastaddr, &nsegs); - map->len += m->m_len; - } - } - } else { - error = EINVAL; - } - - if (error) { - /* - * force "no valid mappings" on error in callback. - */ - (*callback)(callback_arg, NULL, 0, 0, error); - } else { - (*callback)(callback_arg, dmat->segments, nsegs + 1, - m0->m_pkthdr.len, error); - } - CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", - __func__, dmat, dmat->flags, error, nsegs + 1); - - return (error); -} - -int -bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map, - struct mbuf *m0, bus_dma_segment_t *segs, int *nsegs, - int flags) -{ - int error = 0; - M_ASSERTPKTHDR(m0); - - flags |= BUS_DMA_NOWAIT; - *nsegs = -1; - map->flags &= ~DMAMAP_TYPE_MASK; - map->flags |= DMAMAP_MBUF | DMAMAP_CACHE_ALIGNED; - map->buffer = m0; - map->len = 0; - if (m0->m_pkthdr.len <= dmat->maxsize) { - vm_offset_t lastaddr = 0; - struct mbuf *m; - - for (m = m0; m != NULL && error == 0; m = m->m_next) { - if (m->m_len > 0) { - error = bus_dmamap_load_buffer(dmat, segs, map, - m->m_data, m->m_len, - pmap_kernel(), flags, &lastaddr, - nsegs); - map->len += m->m_len; - } - } - } else { - error = EINVAL; - } - - /* XXX FIXME: Having to increment nsegs is really annoying */ - ++*nsegs; - CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", - __func__, dmat, dmat->flags, error, *nsegs); - return (error); -} - -/* - * Like bus_dmamap_load(), but for uios. - */ -int -bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, struct uio *uio, - bus_dmamap_callback2_t *callback, void *callback_arg, - int flags) -{ - vm_offset_t lastaddr = 0; - int nsegs, i, error; - bus_size_t resid; - struct iovec *iov; - struct pmap *pmap; - - resid = uio->uio_resid; - iov = uio->uio_iov; - map->flags &= ~DMAMAP_TYPE_MASK; - map->flags |= DMAMAP_UIO; - map->buffer = uio; - map->len = 0; - - if (uio->uio_segflg == UIO_USERSPACE) { - KASSERT(uio->uio_td != NULL, - ("bus_dmamap_load_uio: USERSPACE but no proc")); - pmap = vmspace_pmap(uio->uio_td->td_proc->p_vmspace); - } else - pmap = kernel_pmap; - - error = 0; - nsegs = -1; - for (i = 0; i < uio->uio_iovcnt && resid != 0 && !error; i++) { - /* - * Now at the first iovec to load. Load each iovec - * until we have exhausted the residual count. - */ - bus_size_t minlen = - resid < iov[i].iov_len ? resid : iov[i].iov_len; - caddr_t addr = (caddr_t) iov[i].iov_base; - - if (minlen > 0) { - error = bus_dmamap_load_buffer(dmat, dmat->segments, - map, addr, minlen, pmap, flags, &lastaddr, &nsegs); - - map->len += minlen; - resid -= minlen; - } - } - - if (error) { - /* - * force "no valid mappings" on error in callback. - */ - (*callback)(callback_arg, NULL, 0, 0, error); - } else { - (*callback)(callback_arg, dmat->segments, nsegs+1, - uio->uio_resid, error); - } - - CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", - __func__, dmat, dmat->flags, error, nsegs + 1); - return (error); + if (segs == NULL) + segs = dmat->segments; + return (segs); } /* @@ -1146,24 +1111,25 @@ _bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map) { struct bounce_page *bpage; - map->flags &= ~DMAMAP_TYPE_MASK; while ((bpage = STAILQ_FIRST(&map->bpages)) != NULL) { STAILQ_REMOVE_HEAD(&map->bpages, links); free_bounce_page(dmat, bpage); } + map->sync_count = 0; return; } static void -bus_dmamap_sync_buf(void *buf, int len, bus_dmasync_op_t op, int bufaligned) +bus_dmamap_sync_buf(vm_offset_t buf, int len, bus_dmasync_op_t op, + int bufaligned) { char _tmp_cl[arm_dcache_align], _tmp_clend[arm_dcache_align]; register_t s; int partial; if ((op & BUS_DMASYNC_PREWRITE) && !(op & BUS_DMASYNC_PREREAD)) { - cpu_dcache_wb_range((vm_offset_t)buf, len); - cpu_l2cache_wb_range((vm_offset_t)buf, len); + cpu_dcache_wb_range(buf, len); + cpu_l2cache_wb_range(buf, len); } /* @@ -1186,38 +1152,37 @@ bus_dmamap_sync_buf(void *buf, int len, bus_dmasync_op_t op, int bufaligned) if (op & BUS_DMASYNC_PREREAD) { if (!(op & BUS_DMASYNC_PREWRITE) && !partial) { - cpu_dcache_inv_range((vm_offset_t)buf, len); - cpu_l2cache_inv_range((vm_offset_t)buf, len); + cpu_dcache_inv_range(buf, len); + cpu_l2cache_inv_range(buf, len); } else { - cpu_dcache_wbinv_range((vm_offset_t)buf, len); - cpu_l2cache_wbinv_range((vm_offset_t)buf, len); + cpu_dcache_wbinv_range(buf, len); + cpu_l2cache_wbinv_range(buf, len); } } if (op & BUS_DMASYNC_POSTREAD) { if (partial && !bufaligned) { s = intr_disable(); - if ((vm_offset_t)buf & arm_dcache_align_mask) - memcpy(_tmp_cl, (void *)((vm_offset_t)buf & + if (buf & arm_dcache_align_mask) + memcpy(_tmp_cl, (void *)(buf & ~arm_dcache_align_mask), - (vm_offset_t)buf & arm_dcache_align_mask); - if (((vm_offset_t)buf + len) & arm_dcache_align_mask) + buf & arm_dcache_align_mask); + if ((buf + len) & arm_dcache_align_mask) memcpy(_tmp_clend, - (void *)((vm_offset_t)buf + len), - arm_dcache_align - (((vm_offset_t)(buf) + - len) & arm_dcache_align_mask)); + (void *)(buf + len), + arm_dcache_align - + ((buf + len) & arm_dcache_align_mask)); } - cpu_dcache_inv_range((vm_offset_t)buf, len); - cpu_l2cache_inv_range((vm_offset_t)buf, len); + cpu_dcache_inv_range(buf, len); + cpu_l2cache_inv_range(buf, len); if (partial && !bufaligned) { - if ((vm_offset_t)buf & arm_dcache_align_mask) - memcpy((void *)((vm_offset_t)buf & + if (buf & arm_dcache_align_mask) + memcpy((void *)(buf & ~arm_dcache_align_mask), _tmp_cl, - (vm_offset_t)buf & arm_dcache_align_mask); - if (((vm_offset_t)buf + len) & arm_dcache_align_mask) - memcpy((void *)((vm_offset_t)buf + len), + buf & arm_dcache_align_mask); + if ((buf + len) & arm_dcache_align_mask) + memcpy((void *)(buf + len), _tmp_clend, arm_dcache_align - - (((vm_offset_t)(buf) + len) & - arm_dcache_align_mask)); + ((buf + len) & arm_dcache_align_mask)); intr_restore(s); } } @@ -1230,10 +1195,18 @@ _bus_dmamap_sync_bp(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op) STAILQ_FOREACH(bpage, &map->bpages, links) { if (op & BUS_DMASYNC_PREWRITE) { - bcopy((void *)bpage->datavaddr, - (void *)(bpage->vaddr_nocache != 0 ? - bpage->vaddr_nocache : bpage->vaddr), - bpage->datacount); + if (bpage->datavaddr != 0) + bcopy((void *)bpage->datavaddr, + (void *)(bpage->vaddr_nocache != 0 ? + bpage->vaddr_nocache : + bpage->vaddr), + bpage->datacount); + else + physcopyout(bpage->dataaddr, + (void *)(bpage->vaddr_nocache != 0 ? + bpage->vaddr_nocache : + bpage->vaddr), + bpage->datacount); if (bpage->vaddr_nocache == 0) { cpu_dcache_wb_range(bpage->vaddr, bpage->datacount); @@ -1249,36 +1222,23 @@ _bus_dmamap_sync_bp(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op) cpu_l2cache_inv_range(bpage->vaddr, bpage->datacount); } - bcopy((void *)(bpage->vaddr_nocache != 0 ? - bpage->vaddr_nocache : bpage->vaddr), - (void *)bpage->datavaddr, bpage->datacount); + if (bpage->datavaddr != 0) + bcopy((void *)(bpage->vaddr_nocache != 0 ? + bpage->vaddr_nocache : bpage->vaddr), + (void *)bpage->datavaddr, bpage->datacount); + else + physcopyin((void *)(bpage->vaddr_nocache != 0 ? + bpage->vaddr_nocache : bpage->vaddr), + bpage->dataaddr, bpage->datacount); dmat->bounce_zone->total_bounced++; } } } -static __inline int -_bus_dma_buf_is_in_bp(bus_dmamap_t map, void *buf, int len) -{ - struct bounce_page *bpage; - - STAILQ_FOREACH(bpage, &map->bpages, links) { - if ((vm_offset_t)buf >= bpage->datavaddr && - (vm_offset_t)buf + len <= bpage->datavaddr + - bpage->datacount) - return (1); - } - return (0); - -} - void _bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op) { - struct mbuf *m; - struct uio *uio; - int resid; - struct iovec *iov; + struct sync_list *sl, *end; int bufaligned; if (op == BUS_DMASYNC_POSTWRITE) @@ -1289,40 +1249,11 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op) _bus_dmamap_sync_bp(dmat, map, op); CTR3(KTR_BUSDMA, "%s: op %x flags %x", __func__, op, map->flags); bufaligned = (map->flags & DMAMAP_CACHE_ALIGNED); - switch(map->flags & DMAMAP_TYPE_MASK) { - case DMAMAP_LINEAR: - if (!(_bus_dma_buf_is_in_bp(map, map->buffer, map->len))) - bus_dmamap_sync_buf(map->buffer, map->len, op, + if (map->sync_count) { + end = &map->slist[map->sync_count]; + for (sl = &map->slist[0]; sl != end; sl++) + bus_dmamap_sync_buf(sl->vaddr, sl->datacount, op, bufaligned); - break; - case DMAMAP_MBUF: - m = map->buffer; - while (m) { - if (m->m_len > 0 && - !(_bus_dma_buf_is_in_bp(map, m->m_data, m->m_len))) - bus_dmamap_sync_buf(m->m_data, m->m_len, op, - bufaligned); - m = m->m_next; - } - break; - case DMAMAP_UIO: - uio = map->buffer; - iov = uio->uio_iov; - resid = uio->uio_resid; - for (int i = 0; i < uio->uio_iovcnt && resid != 0; i++) { - bus_size_t minlen = resid < iov[i].iov_len ? resid : - iov[i].iov_len; - if (minlen > 0) { - if (!_bus_dma_buf_is_in_bp(map, iov[i].iov_base, - minlen)) - bus_dmamap_sync_buf(iov[i].iov_base, - minlen, op, bufaligned); - resid -= minlen; - } - } - break; - default: - break; } drain: @@ -1489,7 +1420,7 @@ reserve_bounce_pages(bus_dma_tag_t dmat, bus_dmamap_t map, int commit) static bus_addr_t add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, vm_offset_t vaddr, - bus_size_t size) + bus_addr_t addr, bus_size_t size) { struct bounce_zone *bz; struct bounce_page *bpage; @@ -1522,6 +1453,7 @@ add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, vm_offset_t vaddr, bpage->busaddr |= vaddr & PAGE_MASK; } bpage->datavaddr = vaddr; + bpage->dataaddr = addr; bpage->datacount = size; STAILQ_INSERT_TAIL(&(map->bpages), bpage, links); return (bpage->busaddr); @@ -1575,8 +1507,8 @@ busdma_swi(void) mtx_unlock(&bounce_lock); dmat = map->dmat; (dmat->lockfunc)(dmat->lockfuncarg, BUS_DMA_LOCK); - bus_dmamap_load(map->dmat, map, map->buffer, map->len, - map->callback, map->callback_arg, /*flags*/0); + bus_dmamap_load_mem(map->dmat, map, &map->mem, + map->callback, map->callback_arg, BUS_DMA_WAITOK); (dmat->lockfunc)(dmat->lockfuncarg, BUS_DMA_UNLOCK); mtx_lock(&bounce_lock); } diff --git a/sys/cam/cam_ccb.h b/sys/cam/cam_ccb.h index 1f12d91ba26..a80880a144e 100644 --- a/sys/cam/cam_ccb.h +++ b/sys/cam/cam_ccb.h @@ -64,13 +64,19 @@ typedef enum { * Perform transport negotiation * with this command. */ - CAM_SCATTER_VALID = 0x00000010,/* Scatter/gather list is valid */ + CAM_DATA_ISPHYS = 0x00000010,/* Data type with physical addrs */ CAM_DIS_AUTOSENSE = 0x00000020,/* Disable autosense feature */ CAM_DIR_BOTH = 0x00000000,/* Data direction (00:IN/OUT) */ CAM_DIR_IN = 0x00000040,/* Data direction (01:DATA IN) */ CAM_DIR_OUT = 0x00000080,/* Data direction (10:DATA OUT) */ CAM_DIR_NONE = 0x000000C0,/* Data direction (11:no data) */ CAM_DIR_MASK = 0x000000C0,/* Data direction Mask */ + CAM_DATA_VADDR = 0x00000000,/* Data type (000:Virtual) */ + CAM_DATA_PADDR = 0x00000010,/* Data type (001:Physical) */ + CAM_DATA_SG = 0x00040000,/* Data type (010:sglist) */ + CAM_DATA_SG_PADDR = 0x00040010,/* Data type (011:sglist phys) */ + CAM_DATA_BIO = 0x00200000,/* Data type (100:bio) */ + CAM_DATA_MASK = 0x00240010,/* Data type mask */ CAM_SOFT_RST_OP = 0x00000100,/* Use Soft reset alternative */ CAM_ENG_SYNC = 0x00000200,/* Flush resid bytes on complete */ CAM_DEV_QFRZDIS = 0x00000400,/* Disable DEV Q freezing */ @@ -81,10 +87,8 @@ typedef enum { CAM_TAG_ACTION_VALID = 0x00008000,/* Use the tag action in this ccb*/ CAM_PASS_ERR_RECOVER = 0x00010000,/* Pass driver does err. recovery*/ CAM_DIS_DISCONNECT = 0x00020000,/* Disable disconnect */ - CAM_SG_LIST_PHYS = 0x00040000,/* SG list has physical addrs. */ CAM_MSG_BUF_PHYS = 0x00080000,/* Message buffer ptr is physical*/ CAM_SNS_BUF_PHYS = 0x00100000,/* Autosense data ptr is physical*/ - CAM_DATA_PHYS = 0x00200000,/* SG/Buffer data ptrs are phys. */ CAM_CDB_PHYS = 0x00400000,/* CDB poiner is physical */ CAM_ENG_SGLIST = 0x00800000,/* SG list is for the HBA engine */ diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c index 304d8c790b3..6bda94debd6 100644 --- a/sys/cam/cam_xpt.c +++ b/sys/cam/cam_xpt.c @@ -547,7 +547,8 @@ xptioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td * We can't deal with physical addresses for this * type of transaction. */ - if (inccb->ccb_h.flags & CAM_DATA_PHYS) { + if ((inccb->ccb_h.flags & CAM_DATA_MASK) != + CAM_DATA_VADDR) { error = EINVAL; break; } diff --git a/sys/cam/ctl/ctl_frontend_cam_sim.c b/sys/cam/ctl/ctl_frontend_cam_sim.c index 43e4d61dfd5..b885cbf39d3 100644 --- a/sys/cam/ctl/ctl_frontend_cam_sim.c +++ b/sys/cam/ctl/ctl_frontend_cam_sim.c @@ -93,8 +93,8 @@ struct cfcs_softc { * handle physical addresses yet. That would require mapping things in * order to do the copy. */ -#define CFCS_BAD_CCB_FLAGS (CAM_DATA_PHYS | CAM_SG_LIST_PHYS | \ - CAM_MSG_BUF_PHYS | CAM_SNS_BUF_PHYS | CAM_CDB_PHYS | CAM_SENSE_PTR |\ +#define CFCS_BAD_CCB_FLAGS (CAM_DATA_ISPHYS | CAM_MSG_BUF_PHYS | \ + CAM_SNS_BUF_PHYS | CAM_CDB_PHYS | CAM_SENSE_PTR | \ CAM_SENSE_PHYS) int cfcs_init(void); @@ -379,36 +379,35 @@ cfcs_datamove(union ctl_io *io) * Simplify things on both sides by putting single buffers into a * single entry S/G list. */ - if (ccb->ccb_h.flags & CAM_SCATTER_VALID) { - if (ccb->ccb_h.flags & CAM_SG_LIST_PHYS) { - /* We should filter this out on entry */ - panic("%s: physical S/G list, should not get here", - __func__); - } else { - int len_seen; + switch ((ccb->ccb_h.flags & CAM_DATA_MASK)) { + case CAM_DATA_SG: { + int len_seen; - cam_sglist = (bus_dma_segment_t *)ccb->csio.data_ptr; - cam_sg_count = ccb->csio.sglist_cnt; + cam_sglist = (bus_dma_segment_t *)ccb->csio.data_ptr; + cam_sg_count = ccb->csio.sglist_cnt; - for (i = 0, len_seen = 0; i < cam_sg_count; i++) { - if ((len_seen + cam_sglist[i].ds_len) >= - io->scsiio.kern_rel_offset) { - cam_sg_start = i; - cam_sg_offset = - io->scsiio.kern_rel_offset - - len_seen; - break; - } - len_seen += cam_sglist[i].ds_len; + for (i = 0, len_seen = 0; i < cam_sg_count; i++) { + if ((len_seen + cam_sglist[i].ds_len) >= + io->scsiio.kern_rel_offset) { + cam_sg_start = i; + cam_sg_offset = io->scsiio.kern_rel_offset - + len_seen; + break; } + len_seen += cam_sglist[i].ds_len; } - } else { + break; + } + case CAM_DATA_VADDR: cam_sglist = &cam_sg_entry; cam_sglist[0].ds_len = ccb->csio.dxfer_len; cam_sglist[0].ds_addr = (bus_addr_t)ccb->csio.data_ptr; cam_sg_count = 1; cam_sg_start = 0; cam_sg_offset = io->scsiio.kern_rel_offset; + break; + default: + panic("Invalid CAM flags %#x", ccb->ccb_h.flags); } if (io->scsiio.kern_sg_entries > 0) { diff --git a/sys/cam/ctl/scsi_ctl.c b/sys/cam/ctl/scsi_ctl.c index 5dc20e5ee13..e9af88189d2 100644 --- a/sys/cam/ctl/scsi_ctl.c +++ b/sys/cam/ctl/scsi_ctl.c @@ -876,6 +876,7 @@ ctlfestart(struct cam_periph *periph, union ccb *start_ccb) csio->cdb_len = atio->cdb_len; + flags &= ~CAM_DATA_MASK; if (io->scsiio.kern_sg_entries == 0) { /* No S/G list */ data_ptr = io->scsiio.kern_data_ptr; @@ -883,7 +884,9 @@ ctlfestart(struct cam_periph *periph, union ccb *start_ccb) csio->sglist_cnt = 0; if (io->io_hdr.flags & CTL_FLAG_BUS_ADDR) - flags |= CAM_DATA_PHYS; + flags |= CAM_DATA_PADDR; + else + flags |= CAM_DATA_VADDR; } else if (io->scsiio.kern_sg_entries <= (sizeof(cmd_info->cam_sglist)/ sizeof(cmd_info->cam_sglist[0]))) { @@ -907,11 +910,10 @@ ctlfestart(struct cam_periph *periph, union ccb *start_ccb) ctl_sglist[i].len; } csio->sglist_cnt = io->scsiio.kern_sg_entries; - flags |= CAM_SCATTER_VALID; if (io->io_hdr.flags & CTL_FLAG_BUS_ADDR) - flags |= CAM_SG_LIST_PHYS; + flags |= CAM_DATA_SG_PADDR; else - flags &= ~CAM_SG_LIST_PHYS; + flags &= ~CAM_DATA_SG; data_ptr = (uint8_t *)cam_sglist; dxfer_len = io->scsiio.kern_data_len; } else { diff --git a/sys/cam/scsi/scsi_pass.c b/sys/cam/scsi/scsi_pass.c index fa6af7c346f..f3710c8ea58 100644 --- a/sys/cam/scsi/scsi_pass.c +++ b/sys/cam/scsi/scsi_pass.c @@ -696,8 +696,11 @@ passsendccb(struct cam_periph *periph, union ccb *ccb, union ccb *inccb) * do the right thing, even if there isn't data to map, but since CCBs * without data are a reasonably common occurance (e.g. test unit * ready), it will save a few cycles if we check for it here. + * + * XXX What happens if a sg list is supplied? We don't filter that + * out. */ - if (((ccb->ccb_h.flags & CAM_DATA_PHYS) == 0) + if (((ccb->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR) && (((ccb->ccb_h.func_code == XPT_SCSI_IO || ccb->ccb_h.func_code == XPT_ATA_IO) && ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE)) diff --git a/sys/cam/scsi/scsi_target.c b/sys/cam/scsi/scsi_target.c index c45e8d5e4db..963b4e66a5a 100644 --- a/sys/cam/scsi/scsi_target.c +++ b/sys/cam/scsi/scsi_target.c @@ -737,7 +737,7 @@ targsendccb(struct targ_softc *softc, union ccb *ccb, * without data are a reasonably common occurance (e.g. test unit * ready), it will save a few cycles if we check for it here. */ - if (((ccb_h->flags & CAM_DATA_PHYS) == 0) + if (((ccb_h->flags & CAM_DATA_MASK) == CAM_DATA_VADDR) && (((ccb_h->func_code == XPT_CONT_TARGET_IO) && ((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE)) || (ccb_h->func_code == XPT_DEV_MATCH))) { diff --git a/sys/conf/files b/sys/conf/files index 80788404549..374468e1c63 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -2681,6 +2681,7 @@ kern/subr_acl_posix1e.c optional ufs_acl kern/subr_autoconf.c standard kern/subr_blist.c standard kern/subr_bus.c standard +kern/subr_bus_dma.c standard kern/subr_bufring.c standard kern/subr_clock.c standard kern/subr_devstat.c standard diff --git a/sys/dev/aac/aac_cam.c b/sys/dev/aac/aac_cam.c index 57e87da1f20..7f0d7ee1cdc 100644 --- a/sys/dev/aac/aac_cam.c +++ b/sys/dev/aac/aac_cam.c @@ -448,26 +448,28 @@ aac_cam_action(struct cam_sim *sim, union ccb *ccb) /* Map the s/g list. XXX 32bit addresses only! */ if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { - if ((ccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) { + switch ((ccb->ccb_h.flags & CAM_DATA_MASK)) { + case CAM_DATA_VADDR: srb->data_len = csio->dxfer_len; - if (ccb->ccb_h.flags & CAM_DATA_PHYS) { - /* Send a 32bit command */ - fib->Header.Command = ScsiPortCommand; - srb->sg_map.SgCount = 1; - srb->sg_map.SgEntry[0].SgAddress = - (uint32_t)(uintptr_t)csio->data_ptr; - srb->sg_map.SgEntry[0].SgByteCount = - csio->dxfer_len; - } else { - /* - * Arrange things so that the S/G - * map will get set up automagically - */ - cm->cm_data = (void *)csio->data_ptr; - cm->cm_datalen = csio->dxfer_len; - cm->cm_sgtable = &srb->sg_map; - } - } else { + /* + * Arrange things so that the S/G + * map will get set up automagically + */ + cm->cm_data = (void *)csio->data_ptr; + cm->cm_datalen = csio->dxfer_len; + cm->cm_sgtable = &srb->sg_map; + break; + case CAM_DATA_PADDR: + /* Send a 32bit command */ + fib->Header.Command = ScsiPortCommand; + srb->sg_map.SgCount = 1; + srb->sg_map.SgEntry[0].SgAddress = + (uint32_t)(uintptr_t)csio->data_ptr; + srb->sg_map.SgEntry[0].SgByteCount = + csio->dxfer_len; + srb->data_len = csio->dxfer_len; + break; + default: /* XXX Need to handle multiple s/g elements */ panic("aac_cam: multiple s/g elements"); } diff --git a/sys/dev/advansys/advansys.c b/sys/dev/advansys/advansys.c index d804b6df768..c9ccb67c718 100644 --- a/sys/dev/advansys/advansys.c +++ b/sys/dev/advansys/advansys.c @@ -207,6 +207,7 @@ adv_action(struct cam_sim *sim, union ccb *ccb) struct ccb_hdr *ccb_h; struct ccb_scsiio *csio; struct adv_ccb_info *cinfo; + int error; ccb_h = &ccb->ccb_h; csio = &ccb->csio; @@ -217,58 +218,17 @@ adv_action(struct cam_sim *sim, union ccb *ccb) ccb_h->ccb_cinfo_ptr = cinfo; cinfo->ccb = ccb; - /* Only use S/G if there is a transfer */ - if ((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE) { - if ((ccb_h->flags & CAM_SCATTER_VALID) == 0) { - /* - * We've been given a pointer - * to a single buffer - */ - if ((ccb_h->flags & CAM_DATA_PHYS) == 0) { - int error; - - error = - bus_dmamap_load(adv->buffer_dmat, - cinfo->dmamap, - csio->data_ptr, - csio->dxfer_len, - adv_execute_ccb, - csio, /*flags*/0); - if (error == EINPROGRESS) { - /* - * So as to maintain ordering, - * freeze the controller queue - * until our mapping is - * returned. - */ - adv_set_state(adv, - ADV_BUSDMA_BLOCK); - } - } else { - struct bus_dma_segment seg; - - /* Pointer to physical buffer */ - seg.ds_addr = - (bus_addr_t)csio->data_ptr; - seg.ds_len = csio->dxfer_len; - adv_execute_ccb(csio, &seg, 1, 0); - } - } else { - struct bus_dma_segment *segs; - if ((ccb_h->flags & CAM_DATA_PHYS) != 0) - panic("adv_setup_data - Physical " - "segment pointers unsupported"); - - if ((ccb_h->flags & CAM_SG_LIST_PHYS) == 0) - panic("adv_setup_data - Virtual " - "segment addresses unsupported"); - - /* Just use the segments provided */ - segs = (struct bus_dma_segment *)csio->data_ptr; - adv_execute_ccb(ccb, segs, csio->sglist_cnt, 0); - } - } else { - adv_execute_ccb(ccb, NULL, 0, 0); + error = bus_dmamap_load_ccb(adv->buffer_dmat, + cinfo->dmamap, + ccb, + adv_execute_ccb, + csio, /*flags*/0); + if (error == EINPROGRESS) { + /* + * So as to maintain ordering, freeze the controller + * queue until our mapping is returned. + */ + adv_set_state(adv, ADV_BUSDMA_BLOCK); } break; } diff --git a/sys/dev/advansys/adwcam.c b/sys/dev/advansys/adwcam.c index defc7c72a6e..de1f413158f 100644 --- a/sys/dev/advansys/adwcam.c +++ b/sys/dev/advansys/adwcam.c @@ -353,6 +353,7 @@ adw_action(struct cam_sim *sim, union ccb *ccb) struct ccb_scsiio *csio; struct ccb_hdr *ccbh; struct acb *acb; + int error; csio = &ccb->csio; ccbh = &ccb->ccb_h; @@ -427,66 +428,18 @@ adw_action(struct cam_sim *sim, union ccb *ccb) acb->queue.cdb, csio->cdb_len); } - /* - * If we have any data to send with this command, - * map it into bus space. - */ - if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE) { - if ((ccbh->flags & CAM_SCATTER_VALID) == 0) { - /* - * We've been given a pointer - * to a single buffer. - */ - if ((ccbh->flags & CAM_DATA_PHYS) == 0) { - int error; - - error = - bus_dmamap_load(adw->buffer_dmat, - acb->dmamap, - csio->data_ptr, - csio->dxfer_len, - adwexecuteacb, - acb, /*flags*/0); - if (error == EINPROGRESS) { - /* - * So as to maintain ordering, - * freeze the controller queue - * until our mapping is - * returned. - */ - xpt_freeze_simq(sim, 1); - acb->state |= CAM_RELEASE_SIMQ; - } - } else { - struct bus_dma_segment seg; - - /* Pointer to physical buffer */ - seg.ds_addr = - (bus_addr_t)csio->data_ptr; - seg.ds_len = csio->dxfer_len; - adwexecuteacb(acb, &seg, 1, 0); - } - } else { - struct bus_dma_segment *segs; - - if ((ccbh->flags & CAM_DATA_PHYS) != 0) - panic("adw_action - Physical " - "segment pointers " - "unsupported"); - - if ((ccbh->flags&CAM_SG_LIST_PHYS)==0) - panic("adw_action - Virtual " - "segment addresses " - "unsupported"); - - /* Just use the segments provided */ - segs = (struct bus_dma_segment *)csio->data_ptr; - adwexecuteacb(acb, segs, csio->sglist_cnt, - (csio->sglist_cnt < ADW_SGSIZE) - ? 0 : EFBIG); - } - } else { - adwexecuteacb(acb, NULL, 0, 0); + error = bus_dmamap_load_ccb(adw->buffer_dmat, + acb->dmamap, + ccb, + adwexecuteacb, + acb, /*flags*/0); + if (error == EINPROGRESS) { + /* + * So as to maintain ordering, freeze the controller + * queue until our mapping is returned. + */ + xpt_freeze_simq(sim, 1); + acb->state |= CAM_RELEASE_SIMQ; } break; } diff --git a/sys/dev/aha/aha.c b/sys/dev/aha/aha.c index 07b0682f24c..ab2a59a0323 100644 --- a/sys/dev/aha/aha.c +++ b/sys/dev/aha/aha.c @@ -778,6 +778,7 @@ ahaaction(struct cam_sim *sim, union ccb *ccb) if (ccb->ccb_h.func_code == XPT_SCSI_IO) { struct ccb_scsiio *csio; struct ccb_hdr *ccbh; + int error; csio = &ccb->csio; ccbh = &csio->ccb_h; @@ -811,67 +812,22 @@ ahaaction(struct cam_sim *sim, union ccb *ccb) * If we have any data to send with this command, * map it into bus space. */ - /* Only use S/G if there is a transfer */ - if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE) { - if ((ccbh->flags & CAM_SCATTER_VALID) == 0) { - /* - * We've been given a pointer - * to a single buffer. - */ - if ((ccbh->flags & CAM_DATA_PHYS)==0) { - int error; - error = bus_dmamap_load( - aha->buffer_dmat, - accb->dmamap, - csio->data_ptr, - csio->dxfer_len, - ahaexecuteccb, - accb, - /*flags*/0); - if (error == EINPROGRESS) { - /* - * So as to maintain - * ordering, freeze the - * controller queue - * until our mapping is - * returned. - */ - xpt_freeze_simq(aha->sim, - 1); - csio->ccb_h.status |= - CAM_RELEASE_SIMQ; - } - } else { - struct bus_dma_segment seg; - - /* Pointer to physical buffer */ - seg.ds_addr = - (bus_addr_t)csio->data_ptr; - seg.ds_len = csio->dxfer_len; - ahaexecuteccb(accb, &seg, 1, 0); - } - } else { - struct bus_dma_segment *segs; - - if ((ccbh->flags & CAM_DATA_PHYS) != 0) - panic("ahaaction - Physical " - "segment pointers " - "unsupported"); - - if ((ccbh->flags&CAM_SG_LIST_PHYS)==0) - panic("ahaaction - Virtual " - "segment addresses " - "unsupported"); - - /* Just use the segments provided */ - segs = (struct bus_dma_segment *) - csio->data_ptr; - ahaexecuteccb(accb, segs, - csio->sglist_cnt, 0); - } - } else { - ahaexecuteccb(accb, NULL, 0, 0); + error = bus_dmamap_load_ccb( + aha->buffer_dmat, + accb->dmamap, + ccb, + ahaexecuteccb, + accb, + /*flags*/0); + if (error == EINPROGRESS) { + /* + * So as to maintain ordering, freeze the + * controller queue until our mapping is + * returned. + */ + xpt_freeze_simq(aha->sim, 1); + csio->ccb_h.status |= CAM_RELEASE_SIMQ; } } else { hccb->opcode = INITIATOR_BUS_DEV_RESET; diff --git a/sys/dev/ahb/ahb.c b/sys/dev/ahb/ahb.c index b0b4db229f4..fd07c443820 100644 --- a/sys/dev/ahb/ahb.c +++ b/sys/dev/ahb/ahb.c @@ -1006,6 +1006,7 @@ ahbaction(struct cam_sim *sim, union ccb *ccb) { struct ecb *ecb; struct hardware_ecb *hecb; + int error; /* * get an ecb to use. @@ -1056,65 +1057,19 @@ ahbaction(struct cam_sim *sim, union ccb *ccb) hecb->cdb, hecb->cdb_len); } - /* - * If we have any data to send with this command, - * map it into bus space. - */ - if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { - if ((ccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) { - /* - * We've been given a pointer - * to a single buffer. - */ - if ((ccb->ccb_h.flags & CAM_DATA_PHYS)==0) { - int error; - - error = bus_dmamap_load( - ahb->buffer_dmat, - ecb->dmamap, - ccb->csio.data_ptr, - ccb->csio.dxfer_len, - ahbexecuteecb, - ecb, /*flags*/0); - if (error == EINPROGRESS) { - /* - * So as to maintain ordering, - * freeze the controller queue - * until our mapping is - * returned. - */ - xpt_freeze_simq(ahb->sim, 1); - ccb->ccb_h.status |= - CAM_RELEASE_SIMQ; - } - } else { - struct bus_dma_segment seg; - - /* Pointer to physical buffer */ - seg.ds_addr = - (bus_addr_t)ccb->csio.data_ptr; - seg.ds_len = ccb->csio.dxfer_len; - ahbexecuteecb(ecb, &seg, 1, 0); - } - } else { - struct bus_dma_segment *segs; - - if ((ccb->ccb_h.flags & CAM_DATA_PHYS) != 0) - panic("ahbaction - Physical segment " - "pointers unsupported"); - - if ((ccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0) - panic("btaction - Virtual segment " - "addresses unsupported"); - - /* Just use the segments provided */ - segs = (struct bus_dma_segment *) - ccb->csio.data_ptr; - ahbexecuteecb(ecb, segs, ccb->csio.sglist_cnt, - 0); - } - } else { - ahbexecuteecb(ecb, NULL, 0, 0); + error = bus_dmamap_load_ccb( + ahb->buffer_dmat, + ecb->dmamap, + ccb, + ahbexecuteecb, + ecb, /*flags*/0); + if (error == EINPROGRESS) { + /* + * So as to maintain ordering, freeze the controller + * queue until our mapping is returned. + */ + xpt_freeze_simq(ahb->sim, 1); + ccb->ccb_h.status |= CAM_RELEASE_SIMQ; } break; } diff --git a/sys/dev/ahci/ahci.c b/sys/dev/ahci/ahci.c index b17b9f31c35..8e692bd4348 100644 --- a/sys/dev/ahci/ahci.c +++ b/sys/dev/ahci/ahci.c @@ -1683,21 +1683,10 @@ ahci_begin_transaction(device_t dev, union ccb *ccb) (ccb->ataio.cmd.flags & (CAM_ATAIO_CONTROL | CAM_ATAIO_NEEDRESULT))) ch->aslots |= (1 << slot->slot); slot->dma.nsegs = 0; - /* If request moves data, setup and load SG list */ if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { - void *buf; - bus_size_t size; - slot->state = AHCI_SLOT_LOADING; - if (ccb->ccb_h.func_code == XPT_ATA_IO) { - buf = ccb->ataio.data_ptr; - size = ccb->ataio.dxfer_len; - } else { - buf = ccb->csio.data_ptr; - size = ccb->csio.dxfer_len; - } - bus_dmamap_load(ch->dma.data_tag, slot->dma.data_map, - buf, size, ahci_dmasetprd, slot, 0); + bus_dmamap_load_ccb(ch->dma.data_tag, slot->dma.data_map, ccb, + ahci_dmasetprd, slot, 0); } else ahci_execute_transaction(slot); } diff --git a/sys/dev/aic/aic.c b/sys/dev/aic/aic.c index d83df32cbfe..d751b4d699f 100644 --- a/sys/dev/aic/aic.c +++ b/sys/dev/aic/aic.c @@ -146,8 +146,8 @@ aic_action(struct cam_sim *sim, union ccb *ccb) scb->cmd_ptr = ccb->csio.cdb_io.cdb_bytes; } if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { - if ((ccb->ccb_h.flags & CAM_SCATTER_VALID) || - (ccb->ccb_h.flags & CAM_DATA_PHYS)) { + if ((ccb->ccb_h.flags & CAM_DATA_MASK) != + CAM_DATA_VADDR) { ccb->ccb_h.status = CAM_REQ_INVALID; aic_free_scb(aic, scb); xpt_done(ccb); diff --git a/sys/dev/aic7xxx/aic79xx_osm.c b/sys/dev/aic7xxx/aic79xx_osm.c index 3f7b8185831..6ef0f9250cd 100644 --- a/sys/dev/aic7xxx/aic79xx_osm.c +++ b/sys/dev/aic7xxx/aic79xx_osm.c @@ -1071,6 +1071,7 @@ ahd_setup_data(struct ahd_softc *ahd, struct cam_sim *sim, { struct hardware_scb *hscb; struct ccb_hdr *ccb_h; + int error; hscb = scb->hscb; ccb_h = &csio->ccb_h; @@ -1120,64 +1121,18 @@ ahd_setup_data(struct ahd_softc *ahd, struct cam_sim *sim, } } - /* Only use S/G if there is a transfer */ - if ((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE) { - if ((ccb_h->flags & CAM_SCATTER_VALID) == 0) { - /* We've been given a pointer to a single buffer */ - if ((ccb_h->flags & CAM_DATA_PHYS) == 0) { - int s; - int error; - - s = splsoftvm(); - error = bus_dmamap_load(ahd->buffer_dmat, - scb->dmamap, - csio->data_ptr, - csio->dxfer_len, - ahd_execute_scb, - scb, /*flags*/0); - if (error == EINPROGRESS) { - /* - * So as to maintain ordering, - * freeze the controller queue - * until our mapping is - * returned. - */ - xpt_freeze_simq(sim, - /*count*/1); - scb->io_ctx->ccb_h.status |= - CAM_RELEASE_SIMQ; - } - splx(s); - } else { - struct bus_dma_segment seg; - - /* Pointer to physical buffer */ - if (csio->dxfer_len > AHD_MAXTRANSFER_SIZE) - panic("ahd_setup_data - Transfer size " - "larger than can device max"); - - seg.ds_addr = - (bus_addr_t)(vm_offset_t)csio->data_ptr; - seg.ds_len = csio->dxfer_len; - ahd_execute_scb(scb, &seg, 1, 0); - } - } else { - struct bus_dma_segment *segs; - - if ((ccb_h->flags & CAM_DATA_PHYS) != 0) - panic("ahd_setup_data - Physical segment " - "pointers unsupported"); - - if ((ccb_h->flags & CAM_SG_LIST_PHYS) == 0) - panic("ahd_setup_data - Virtual segment " - "addresses unsupported"); - - /* Just use the segments provided */ - segs = (struct bus_dma_segment *)csio->data_ptr; - ahd_execute_scb(scb, segs, csio->sglist_cnt, 0); - } - } else { - ahd_execute_scb(scb, NULL, 0, 0); + error = bus_dmamap_load_ccb(ahd->buffer_dmat, + scb->dmamap, + (union ccb *)csio, + ahd_execute_scb, + scb, /*flags*/0); + if (error == EINPROGRESS) { + /* + * So as to maintain ordering, freeze the controller queue + * until our mapping is returned. + */ + xpt_freeze_simq(sim, /*count*/1); + scb->io_ctx->ccb_h.status |= CAM_RELEASE_SIMQ; } } diff --git a/sys/dev/aic7xxx/aic7xxx_osm.c b/sys/dev/aic7xxx/aic7xxx_osm.c index 281b00ec9e5..a51177c9789 100644 --- a/sys/dev/aic7xxx/aic7xxx_osm.c +++ b/sys/dev/aic7xxx/aic7xxx_osm.c @@ -1138,6 +1138,7 @@ ahc_setup_data(struct ahc_softc *ahc, struct cam_sim *sim, { struct hardware_scb *hscb; struct ccb_hdr *ccb_h; + int error; hscb = scb->hscb; ccb_h = &csio->ccb_h; @@ -1179,64 +1180,21 @@ ahc_setup_data(struct ahc_softc *ahc, struct cam_sim *sim, } } - /* Only use S/G if there is a transfer */ - if ((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE) { - if ((ccb_h->flags & CAM_SCATTER_VALID) == 0) { - /* We've been given a pointer to a single buffer */ - if ((ccb_h->flags & CAM_DATA_PHYS) == 0) { - int s; - int error; - - s = splsoftvm(); - error = bus_dmamap_load(ahc->buffer_dmat, - scb->dmamap, - csio->data_ptr, - csio->dxfer_len, - ahc_execute_scb, - scb, /*flags*/0); - if (error == EINPROGRESS) { - /* - * So as to maintain ordering, - * freeze the controller queue - * until our mapping is - * returned. - */ - xpt_freeze_simq(sim, - /*count*/1); - scb->io_ctx->ccb_h.status |= - CAM_RELEASE_SIMQ; - } - splx(s); - } else { - struct bus_dma_segment seg; - - /* Pointer to physical buffer */ - if (csio->dxfer_len > AHC_MAXTRANSFER_SIZE) - panic("ahc_setup_data - Transfer size " - "larger than can device max"); - - seg.ds_addr = - (bus_addr_t)(vm_offset_t)csio->data_ptr; - seg.ds_len = csio->dxfer_len; - ahc_execute_scb(scb, &seg, 1, 0); - } - } else { - struct bus_dma_segment *segs; - - if ((ccb_h->flags & CAM_DATA_PHYS) != 0) - panic("ahc_setup_data - Physical segment " - "pointers unsupported"); - - if ((ccb_h->flags & CAM_SG_LIST_PHYS) == 0) - panic("ahc_setup_data - Virtual segment " - "addresses unsupported"); - - /* Just use the segments provided */ - segs = (struct bus_dma_segment *)csio->data_ptr; - ahc_execute_scb(scb, segs, csio->sglist_cnt, 0); - } - } else { - ahc_execute_scb(scb, NULL, 0, 0); + error = bus_dmamap_load_ccb(ahc->buffer_dmat, + scb->dmamap, + (union ccb *)csio, + ahc_execute_scb, + scb, + 0); + if (error == EINPROGRESS) { + /* + * So as to maintain ordering, + * freeze the controller queue + * until our mapping is + * returned. + */ + xpt_freeze_simq(sim, /*count*/1); + scb->io_ctx->ccb_h.status |= CAM_RELEASE_SIMQ; } } diff --git a/sys/dev/amr/amr_cam.c b/sys/dev/amr/amr_cam.c index d03ac6d8086..a1e0a88c533 100644 --- a/sys/dev/amr/amr_cam.c +++ b/sys/dev/amr/amr_cam.c @@ -274,12 +274,9 @@ amr_cam_action(struct cam_sim *sim, union ccb *ccb) * address */ if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE) { - if (ccbh->flags & CAM_DATA_PHYS) + if ((ccbh->flags & CAM_DATA_MASK) != CAM_DATA_VADDR) /* we can't map it */ ccbh->status = CAM_REQ_INVALID; - if (ccbh->flags & CAM_SCATTER_VALID) - /* we want to do the s/g setup */ - ccbh->status = CAM_REQ_INVALID; } /* diff --git a/sys/dev/arcmsr/arcmsr.c b/sys/dev/arcmsr/arcmsr.c index 2096a2217c8..c815d02202c 100644 --- a/sys/dev/arcmsr/arcmsr.c +++ b/sys/dev/arcmsr/arcmsr.c @@ -2341,7 +2341,7 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb *p (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[7] << 8 | (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[8]; /* 4 bytes: Areca io control code */ - if((pccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) { + if ((pccb->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR) { buffer = pccb->csio.data_ptr; transfer_len = pccb->csio.dxfer_len; } else { @@ -2731,6 +2731,7 @@ static void arcmsr_action(struct cam_sim *psim, union ccb *pccb) case XPT_SCSI_IO: { struct CommandControlBlock *srb; int target = pccb->ccb_h.target_id; + int error; if(target == 16) { /* virtual device for iop message transfer */ @@ -2745,52 +2746,13 @@ static void arcmsr_action(struct cam_sim *psim, union ccb *pccb) pccb->ccb_h.arcmsr_ccbsrb_ptr = srb; pccb->ccb_h.arcmsr_ccbacb_ptr = acb; srb->pccb = pccb; - if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { - if(!(pccb->ccb_h.flags & CAM_SCATTER_VALID)) { - /* Single buffer */ - if(!(pccb->ccb_h.flags & CAM_DATA_PHYS)) { - /* Buffer is virtual */ - u_int32_t error, s; - - s = splsoftvm(); - error = bus_dmamap_load(acb->dm_segs_dmat - , srb->dm_segs_dmamap - , pccb->csio.data_ptr - , pccb->csio.dxfer_len - , arcmsr_execute_srb, srb, /*flags*/0); - if(error == EINPROGRESS) { - xpt_freeze_simq(acb->psim, 1); - pccb->ccb_h.status |= CAM_RELEASE_SIMQ; - } - splx(s); - } - else { /* Buffer is physical */ -#ifdef PAE - panic("arcmsr: CAM_DATA_PHYS not supported"); -#else - struct bus_dma_segment seg; - - seg.ds_addr = (bus_addr_t)pccb->csio.data_ptr; - seg.ds_len = pccb->csio.dxfer_len; - arcmsr_execute_srb(srb, &seg, 1, 0); -#endif - } - } else { - /* Scatter/gather list */ - struct bus_dma_segment *segs; - - if((pccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0 - || (pccb->ccb_h.flags & CAM_DATA_PHYS) != 0) { - pccb->ccb_h.status |= CAM_PROVIDE_FAIL; - xpt_done(pccb); - free(srb, M_DEVBUF); - return; - } - segs = (struct bus_dma_segment *)pccb->csio.data_ptr; - arcmsr_execute_srb(srb, segs, pccb->csio.sglist_cnt, 0); - } - } else { - arcmsr_execute_srb(srb, NULL, 0, 0); + error = bus_dmamap_load_ccb(acb->dm_segs_dmat + , srb->dm_segs_dmamap + , pccb + , arcmsr_execute_srb, srb, /*flags*/0); + if(error == EINPROGRESS) { + xpt_freeze_simq(acb->psim, 1); + pccb->ccb_h.status |= CAM_RELEASE_SIMQ; } break; } diff --git a/sys/dev/ata/ata-dma.c b/sys/dev/ata/ata-dma.c index ffd2461169a..9aea8458d68 100644 --- a/sys/dev/ata/ata-dma.c +++ b/sys/dev/ata/ata-dma.c @@ -304,10 +304,17 @@ ata_dmaload(struct ata_request *request, void *addr, int *entries) else dspa.dmatab = request->dma->sg; - if ((error = bus_dmamap_load(request->dma->data_tag, request->dma->data_map, - request->data, request->bytecount, - ch->dma.setprd, &dspa, BUS_DMA_NOWAIT)) || - (error = dspa.error)) { +#ifdef ATA_CAM + if (request->ccb) + error = bus_dmamap_load_ccb(request->dma->data_tag, + request->dma->data_map, request->ccb, + ch->dma.setprd, &dspa, BUS_DMA_NOWAIT); + else +#endif + error = bus_dmamap_load(request->dma->data_tag, request->dma->data_map, + request->data, request->bytecount, + ch->dma.setprd, &dspa, BUS_DMA_NOWAIT); + if (error || (error = dspa.error)) { device_printf(request->parent, "FAILURE - load data\n"); goto error; } diff --git a/sys/dev/ata/atapi-cam.c b/sys/dev/ata/atapi-cam.c index 363aa944a9b..01817855874 100644 --- a/sys/dev/ata/atapi-cam.c +++ b/sys/dev/ata/atapi-cam.c @@ -514,12 +514,6 @@ atapi_action(struct cam_sim *sim, union ccb *ccb) ("CAM CCB too long for ATAPI")); goto action_invalid; } - if ((ccb_h->flags & CAM_SCATTER_VALID)) { - /* scatter-gather not supported */ - xpt_print_path(ccb_h->path); - printf("ATAPI/CAM does not support scatter-gather yet!\n"); - goto action_invalid; - } switch (ccb_h->flags & CAM_DIR_MASK) { case CAM_DIR_IN: diff --git a/sys/dev/buslogic/bt.c b/sys/dev/buslogic/bt.c index 51f5fddc4aa..a2c9f4ffe97 100644 --- a/sys/dev/buslogic/bt.c +++ b/sys/dev/buslogic/bt.c @@ -1158,6 +1158,7 @@ btaction(struct cam_sim *sim, union ccb *ccb) if (ccb->ccb_h.func_code == XPT_SCSI_IO) { struct ccb_scsiio *csio; struct ccb_hdr *ccbh; + int error; csio = &ccb->csio; ccbh = &csio->ccb_h; @@ -1205,67 +1206,21 @@ btaction(struct cam_sim *sim, union ccb *ccb) * If we have any data to send with this command, * map it into bus space. */ - /* Only use S/G if there is a transfer */ - if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE) { - if ((ccbh->flags & CAM_SCATTER_VALID) == 0) { - /* - * We've been given a pointer - * to a single buffer. - */ - if ((ccbh->flags & CAM_DATA_PHYS)==0) { - int error; - - error = bus_dmamap_load( - bt->buffer_dmat, - bccb->dmamap, - csio->data_ptr, - csio->dxfer_len, - btexecuteccb, - bccb, - /*flags*/0); - if (error == EINPROGRESS) { - /* - * So as to maintain - * ordering, freeze the - * controller queue - * until our mapping is - * returned. - */ - xpt_freeze_simq(bt->sim, - 1); - csio->ccb_h.status |= - CAM_RELEASE_SIMQ; - } - } else { - struct bus_dma_segment seg; - - /* Pointer to physical buffer */ - seg.ds_addr = - (bus_addr_t)csio->data_ptr; - seg.ds_len = csio->dxfer_len; - btexecuteccb(bccb, &seg, 1, 0); - } - } else { - struct bus_dma_segment *segs; - - if ((ccbh->flags & CAM_DATA_PHYS) != 0) - panic("btaction - Physical " - "segment pointers " - "unsupported"); - - if ((ccbh->flags&CAM_SG_LIST_PHYS)==0) - panic("btaction - Virtual " - "segment addresses " - "unsupported"); - - /* Just use the segments provided */ - segs = (struct bus_dma_segment *) - csio->data_ptr; - btexecuteccb(bccb, segs, - csio->sglist_cnt, 0); - } - } else { - btexecuteccb(bccb, NULL, 0, 0); + error = bus_dmamap_load_ccb( + bt->buffer_dmat, + bccb->dmamap, + ccb, + btexecuteccb, + bccb, + /*flags*/0); + if (error == EINPROGRESS) { + /* + * So as to maintain ordering, freeze the + * controller queue until our mapping is + * returned. + */ + xpt_freeze_simq(bt->sim, 1); + csio->ccb_h.status |= CAM_RELEASE_SIMQ; } } else { hccb->opcode = INITIATOR_BUS_DEV_RESET; diff --git a/sys/dev/ciss/ciss.c b/sys/dev/ciss/ciss.c index a3f0a4aa9d0..9aef998fbde 100644 --- a/sys/dev/ciss/ciss.c +++ b/sys/dev/ciss/ciss.c @@ -2688,9 +2688,14 @@ ciss_map_request(struct ciss_request *cr) BUS_DMASYNC_PREWRITE); if (cr->cr_data != NULL) { - error = bus_dmamap_load(sc->ciss_buffer_dmat, cr->cr_datamap, - cr->cr_data, cr->cr_length, - ciss_request_map_helper, cr, 0); + if (cr->cr_flags & CISS_REQ_CCB) + error = bus_dmamap_load_ccb(sc->ciss_buffer_dmat, + cr->cr_datamap, cr->cr_data, + ciss_request_map_helper, cr, 0); + else + error = bus_dmamap_load(sc->ciss_buffer_dmat, cr->cr_datamap, + cr->cr_data, cr->cr_length, + ciss_request_map_helper, cr, 0); if (error != 0) return (error); } else { @@ -3056,18 +3061,6 @@ ciss_cam_action_io(struct cam_sim *sim, struct ccb_scsiio *csio) csio->ccb_h.status = CAM_REQ_CMP_ERR; } - /* if there is data transfer, it must be to/from a virtual address */ - if ((csio->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { - if (csio->ccb_h.flags & CAM_DATA_PHYS) { /* we can't map it */ - debug(3, " data pointer is to physical address"); - csio->ccb_h.status = CAM_REQ_CMP_ERR; - } - if (csio->ccb_h.flags & CAM_SCATTER_VALID) { /* we want to do the s/g setup */ - debug(3, " data has premature s/g setup"); - csio->ccb_h.status = CAM_REQ_CMP_ERR; - } - } - /* abandon aborted ccbs or those that have failed validation */ if ((csio->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { debug(3, "abandoning CCB due to abort/validation failure"); @@ -3094,7 +3087,7 @@ ciss_cam_action_io(struct cam_sim *sim, struct ccb_scsiio *csio) * Build the command. */ cc = cr->cr_cc; - cr->cr_data = csio->data_ptr; + cr->cr_data = csio; cr->cr_length = csio->dxfer_len; cr->cr_complete = ciss_cam_complete; cr->cr_private = csio; @@ -3112,12 +3105,13 @@ ciss_cam_action_io(struct cam_sim *sim, struct ccb_scsiio *csio) cc->cdb.type = CISS_CDB_TYPE_COMMAND; cc->cdb.attribute = CISS_CDB_ATTRIBUTE_SIMPLE; /* XXX ordered tags? */ if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) { - cr->cr_flags = CISS_REQ_DATAOUT; + cr->cr_flags = CISS_REQ_DATAOUT | CISS_REQ_CCB; cc->cdb.direction = CISS_CDB_DIRECTION_WRITE; } else if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { - cr->cr_flags = CISS_REQ_DATAIN; + cr->cr_flags = CISS_REQ_DATAIN | CISS_REQ_CCB; cc->cdb.direction = CISS_CDB_DIRECTION_READ; } else { + cr->cr_data = NULL; cr->cr_flags = 0; cc->cdb.direction = CISS_CDB_DIRECTION_NONE; } diff --git a/sys/dev/ciss/cissvar.h b/sys/dev/ciss/cissvar.h index e89e4e9831e..b3719cfaf1a 100644 --- a/sys/dev/ciss/cissvar.h +++ b/sys/dev/ciss/cissvar.h @@ -116,6 +116,7 @@ struct ciss_request #define CISS_REQ_DATAOUT (1<<3) /* data host->adapter */ #define CISS_REQ_DATAIN (1<<4) /* data adapter->host */ #define CISS_REQ_BUSY (1<<5) /* controller has req */ +#define CISS_REQ_CCB (1<<6) /* data is ccb */ void (* cr_complete)(struct ciss_request *); void *cr_private; diff --git a/sys/dev/dpt/dpt_scsi.c b/sys/dev/dpt/dpt_scsi.c index b4a73c937c9..908f0f891d9 100644 --- a/sys/dev/dpt/dpt_scsi.c +++ b/sys/dev/dpt/dpt_scsi.c @@ -910,56 +910,22 @@ dpt_action(struct cam_sim *sim, union ccb *ccb) */ /* Only use S/G if there is a transfer */ if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE) { - if ((ccbh->flags & CAM_SCATTER_VALID) == 0) { + int error; + + error = bus_dmamap_load_ccb(dpt->buffer_dmat, + dccb->dmamap, + ccb, + dptexecuteccb, + dccb, /*flags*/0); + if (error == EINPROGRESS) { /* - * We've been given a pointer - * to a single buffer. + * So as to maintain ordering, + * freeze the controller queue + * until our mapping is + * returned. */ - if ((ccbh->flags & CAM_DATA_PHYS) == 0) { - int error; - - error = - bus_dmamap_load(dpt->buffer_dmat, - dccb->dmamap, - csio->data_ptr, - csio->dxfer_len, - dptexecuteccb, - dccb, /*flags*/0); - if (error == EINPROGRESS) { - /* - * So as to maintain ordering, - * freeze the controller queue - * until our mapping is - * returned. - */ - xpt_freeze_simq(sim, 1); - dccb->state |= CAM_RELEASE_SIMQ; - } - } else { - struct bus_dma_segment seg; - - /* Pointer to physical buffer */ - seg.ds_addr = - (bus_addr_t)csio->data_ptr; - seg.ds_len = csio->dxfer_len; - dptexecuteccb(dccb, &seg, 1, 0); - } - } else { - struct bus_dma_segment *segs; - - if ((ccbh->flags & CAM_DATA_PHYS) != 0) - panic("dpt_action - Physical " - "segment pointers " - "unsupported"); - - if ((ccbh->flags&CAM_SG_LIST_PHYS)==0) - panic("dpt_action - Virtual " - "segment addresses " - "unsupported"); - - /* Just use the segments provided */ - segs = (struct bus_dma_segment *)csio->data_ptr; - dptexecuteccb(dccb, segs, csio->sglist_cnt, 0); + xpt_freeze_simq(sim, 1); + dccb->state |= CAM_RELEASE_SIMQ; } } else { /* diff --git a/sys/dev/firewire/sbp.c b/sys/dev/firewire/sbp.c index 92044497fce..8089d99fa03 100644 --- a/sys/dev/firewire/sbp.c +++ b/sys/dev/firewire/sbp.c @@ -2478,11 +2478,6 @@ END_DEBUG ocb->orb[4] |= htonl(ORB_CMD_IN); } - if (csio->ccb_h.flags & CAM_SCATTER_VALID) - printf("sbp: CAM_SCATTER_VALID\n"); - if (csio->ccb_h.flags & CAM_DATA_PHYS) - printf("sbp: CAM_DATA_PHYS\n"); - if (csio->ccb_h.flags & CAM_CDB_POINTER) cdb = (void *)csio->cdb_io.cdb_ptr; else @@ -2496,10 +2491,9 @@ printf("ORB %08x %08x %08x %08x\n", ntohl(ocb->orb[4]), ntohl(ocb->orb[5]), ntoh int s, error; s = splsoftvm(); - error = bus_dmamap_load(/*dma tag*/sbp->dmat, + error = bus_dmamap_load_ccb(/*dma tag*/sbp->dmat, /*dma map*/ocb->dmamap, - ccb->csio.data_ptr, - ccb->csio.dxfer_len, + ccb, sbp_execute_ocb, ocb, /*flags*/0); diff --git a/sys/dev/hpt27xx/osm_bsd.c b/sys/dev/hpt27xx/osm_bsd.c index fab1c71df33..9f4d1b96f07 100644 --- a/sys/dev/hpt27xx/osm_bsd.c +++ b/sys/dev/hpt27xx/osm_bsd.c @@ -474,33 +474,6 @@ static void os_cmddone(PCOMMAND pCmd) static int os_buildsgl(PCOMMAND pCmd, PSG pSg, int logical) { - POS_CMDEXT ext = (POS_CMDEXT)pCmd->priv; - union ccb *ccb = ext->ccb; - bus_dma_segment_t *sgList = (bus_dma_segment_t *)ccb->csio.data_ptr; - int idx; - - if(logical) { - if (ccb->ccb_h.flags & CAM_DATA_PHYS) - panic("physical address unsupported"); - - if (ccb->ccb_h.flags & CAM_SCATTER_VALID) { - if (ccb->ccb_h.flags & CAM_SG_LIST_PHYS) - panic("physical address unsupported"); - - for (idx = 0; idx < ccb->csio.sglist_cnt; idx++) { - os_set_sgptr(&pSg[idx], (HPT_U8 *)(HPT_UPTR)sgList[idx].ds_addr); - pSg[idx].size = sgList[idx].ds_len; - pSg[idx].eot = (idx==ccb->csio.sglist_cnt-1)? 1 : 0; - } - } - else { - os_set_sgptr(pSg, (HPT_U8 *)ccb->csio.data_ptr); - pSg->size = ccb->csio.dxfer_len; - pSg->eot = 1; - } - return TRUE; - } - /* since we have provided physical sg, nobody will ask us to build physical sg */ HPT_ASSERT(0); return FALSE; @@ -515,23 +488,27 @@ static void hpt_io_dmamap_callback(void *arg, bus_dma_segment_t *segs, int nsegs HPT_ASSERT(pCmd->flags.physical_sg); - if (error || nsegs == 0) + if (error) panic("busdma error"); HPT_ASSERT(nsegs<=os_max_sg_descriptors); - for (idx = 0; idx < nsegs; idx++, psg++) { - psg->addr.bus = segs[idx].ds_addr; - psg->size = segs[idx].ds_len; - psg->eot = 0; - } - psg[-1].eot = 1; + if (nsegs != 0) { + for (idx = 0; idx < nsegs; idx++, psg++) { + psg->addr.bus = segs[idx].ds_addr; + psg->size = segs[idx].ds_len; + psg->eot = 0; + } + psg[-1].eot = 1; - if (pCmd->flags.data_in) { - bus_dmamap_sync(ext->vbus_ext->io_dmat, ext->dma_map, BUS_DMASYNC_PREREAD); - } - else if (pCmd->flags.data_out) { - bus_dmamap_sync(ext->vbus_ext->io_dmat, ext->dma_map, BUS_DMASYNC_PREWRITE); + if (pCmd->flags.data_in) { + bus_dmamap_sync(ext->vbus_ext->io_dmat, ext->dma_map, + BUS_DMASYNC_PREREAD); + } + else if (pCmd->flags.data_out) { + bus_dmamap_sync(ext->vbus_ext->io_dmat, ext->dma_map, + BUS_DMASYNC_PREWRITE); + } } ext->ccb->ccb_h.timeout_ch = timeout(hpt_timeout, pCmd, HPT_OSM_TIMEOUT); @@ -661,6 +638,7 @@ static void hpt_scsi_io(PVBUS_EXT vbus_ext, union ccb *ccb) case 0x2f: case 0x8f: /* VERIFY_16 */ { + int error; pCmd = ldm_alloc_cmds(vbus, vd->cmds_per_request); if(!pCmd){ KdPrint(("Failed to allocate command!")); @@ -717,42 +695,20 @@ static void hpt_scsi_io(PVBUS_EXT vbus_ext, union ccb *ccb) pCmd->target = vd; pCmd->done = os_cmddone; pCmd->buildsgl = os_buildsgl; - pCmd->psg = ext->psg; - - if (ccb->ccb_h.flags & CAM_SCATTER_VALID) { - int idx; - bus_dma_segment_t *sgList = (bus_dma_segment_t *)ccb->csio.data_ptr; - - if (ccb->ccb_h.flags & CAM_SG_LIST_PHYS) - pCmd->flags.physical_sg = 1; - - for (idx = 0; idx < ccb->csio.sglist_cnt; idx++) { - pCmd->psg[idx].addr.bus = sgList[idx].ds_addr; - pCmd->psg[idx].size = sgList[idx].ds_len; - pCmd->psg[idx].eot = (idx==ccb->csio.sglist_cnt-1)? 1 : 0; - } - - ccb->ccb_h.timeout_ch = timeout(hpt_timeout, pCmd, HPT_OSM_TIMEOUT); - ldm_queue_cmd(pCmd); - } - else { - int error; - pCmd->flags.physical_sg = 1; - error = bus_dmamap_load(vbus_ext->io_dmat, - ext->dma_map, - ccb->csio.data_ptr, ccb->csio.dxfer_len, - hpt_io_dmamap_callback, pCmd, + pCmd->flags.physical_sg = 1; + error = bus_dmamap_load_ccb(vbus_ext->io_dmat, + ext->dma_map, ccb, + hpt_io_dmamap_callback, pCmd, BUS_DMA_WAITOK ); - KdPrint(("bus_dmamap_load return %d", error)); - if (error && error!=EINPROGRESS) { - os_printk("bus_dmamap_load error %d", error); - cmdext_put(ext); - ldm_free_cmds(pCmd); - ccb->ccb_h.status = CAM_REQ_CMP_ERR; - xpt_done(ccb); - } + KdPrint(("bus_dmamap_load return %d", error)); + if (error && error!=EINPROGRESS) { + os_printk("bus_dmamap_load error %d", error); + cmdext_put(ext); + ldm_free_cmds(pCmd); + ccb->ccb_h.status = CAM_REQ_CMP_ERR; + xpt_done(ccb); } return; } diff --git a/sys/dev/hptiop/hptiop.c b/sys/dev/hptiop/hptiop.c index c4e3d5a5d79..e3190d29fb6 100644 --- a/sys/dev/hptiop/hptiop.c +++ b/sys/dev/hptiop/hptiop.c @@ -2358,6 +2358,7 @@ static void hptiop_action(struct cam_sim *sim, union ccb *ccb) { struct hpt_iop_hba * hba = (struct hpt_iop_hba *)cam_sim_softc(sim); struct hpt_iop_srb * srb; + int error; switch (ccb->ccb_h.func_code) { @@ -2380,52 +2381,22 @@ static void hptiop_action(struct cam_sim *sim, union ccb *ccb) } srb->ccb = ccb; + error = bus_dmamap_load_ccb(hba->io_dmat, + srb->dma_map, + ccb, + hptiop_post_scsi_command, + srb, + 0); - if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE) - hptiop_post_scsi_command(srb, NULL, 0, 0); - else if ((ccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) { - if ((ccb->ccb_h.flags & CAM_DATA_PHYS) == 0) { - int error; - - error = bus_dmamap_load(hba->io_dmat, - srb->dma_map, - ccb->csio.data_ptr, - ccb->csio.dxfer_len, - hptiop_post_scsi_command, - srb, 0); - - if (error && error != EINPROGRESS) { - device_printf(hba->pcidev, - "%d bus_dmamap_load error %d", - hba->pciunit, error); - xpt_freeze_simq(hba->sim, 1); - ccb->ccb_h.status = CAM_REQ_CMP_ERR; -invalid: - hptiop_free_srb(hba, srb); - xpt_done(ccb); - goto scsi_done; - } - } - else { - device_printf(hba->pcidev, - "CAM_DATA_PHYS not supported"); - ccb->ccb_h.status = CAM_REQ_CMP_ERR; - goto invalid; - } - } - else { - struct bus_dma_segment *segs; - - if ((ccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0 || - (ccb->ccb_h.flags & CAM_DATA_PHYS) != 0) { - device_printf(hba->pcidev, "SCSI cmd failed"); - ccb->ccb_h.status=CAM_PROVIDE_FAIL; - goto invalid; - } - - segs = (struct bus_dma_segment *)ccb->csio.data_ptr; - hptiop_post_scsi_command(srb, segs, - ccb->csio.sglist_cnt, 0); + if (error && error != EINPROGRESS) { + device_printf(hba->pcidev, + "%d bus_dmamap_load error %d", + hba->pciunit, error); + xpt_freeze_simq(hba->sim, 1); + ccb->ccb_h.status = CAM_REQ_CMP_ERR; + hptiop_free_srb(hba, srb); + xpt_done(ccb); + goto scsi_done; } scsi_done: diff --git a/sys/dev/hptmv/entry.c b/sys/dev/hptmv/entry.c index 8dfa7e2a0d6..248d6558579 100644 --- a/sys/dev/hptmv/entry.c +++ b/sys/dev/hptmv/entry.c @@ -2620,32 +2620,7 @@ launch_worker_thread(void) int HPTLIBAPI fOsBuildSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSg, int logical) { - union ccb *ccb = (union ccb *)pCmd->pOrgCommand; - bus_dma_segment_t *sgList = (bus_dma_segment_t *)ccb->csio.data_ptr; - int idx; - if(logical) { - if (ccb->ccb_h.flags & CAM_DATA_PHYS) - panic("physical address unsupported"); - - if (ccb->ccb_h.flags & CAM_SCATTER_VALID) { - if (ccb->ccb_h.flags & CAM_SG_LIST_PHYS) - panic("physical address unsupported"); - - for (idx = 0; idx < ccb->csio.sglist_cnt; idx++) { - pSg[idx].dSgAddress = (ULONG_PTR)(UCHAR *)sgList[idx].ds_addr; - pSg[idx].wSgSize = sgList[idx].ds_len; - pSg[idx].wSgFlag = (idx==ccb->csio.sglist_cnt-1)? SG_FLAG_EOT : 0; - } - } - else { - pSg->dSgAddress = (ULONG_PTR)(UCHAR *)ccb->csio.data_ptr; - pSg->wSgSize = ccb->csio.dxfer_len; - pSg->wSgFlag = SG_FLAG_EOT; - } - return TRUE; - } - /* since we have provided physical sg, nobody will ask us to build physical sg */ HPT_ASSERT(0); return FALSE; @@ -2757,24 +2732,28 @@ hpt_io_dmamap_callback(void *arg, bus_dma_segment_t *segs, int nsegs, int error) HPT_ASSERT(pCmd->cf_physical_sg); - if (error || nsegs == 0) + if (error) panic("busdma error"); HPT_ASSERT(nsegs<= MAX_SG_DESCRIPTORS); - for (idx = 0; idx < nsegs; idx++, psg++) { - psg->dSgAddress = (ULONG_PTR)(UCHAR *)segs[idx].ds_addr; - psg->wSgSize = segs[idx].ds_len; - psg->wSgFlag = (idx == nsegs-1)? SG_FLAG_EOT: 0; -/* KdPrint(("psg[%d]:add=%p,size=%x,flag=%x\n", idx, psg->dSgAddress,psg->wSgSize,psg->wSgFlag)); */ - } -/* psg[-1].wSgFlag = SG_FLAG_EOT; */ - - if (pCmd->cf_data_in) { - bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_PREREAD); - } - else if (pCmd->cf_data_out) { - bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_PREWRITE); + if (nsegs != 0) { + for (idx = 0; idx < nsegs; idx++, psg++) { + psg->dSgAddress = (ULONG_PTR)(UCHAR *)segs[idx].ds_addr; + psg->wSgSize = segs[idx].ds_len; + psg->wSgFlag = (idx == nsegs-1)? SG_FLAG_EOT: 0; + /* KdPrint(("psg[%d]:add=%p,size=%x,flag=%x\n", idx, psg->dSgAddress,psg->wSgSize,psg->wSgFlag)); */ + } + /* psg[-1].wSgFlag = SG_FLAG_EOT; */ + + if (pCmd->cf_data_in) { + bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, + BUS_DMASYNC_PREREAD); + } + else if (pCmd->cf_data_out) { + bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, + BUS_DMASYNC_PREWRITE); + } } ccb->ccb_h.timeout_ch = timeout(hpt_timeout, (caddr_t)ccb, 20*hz); @@ -2883,6 +2862,7 @@ OsSendCommand(_VBUS_ARG union ccb *ccb) UCHAR CdbLength; _VBUS_INST(pVDev->pVBus) PCommand pCmd = AllocateCommand(_VBUS_P0); + int error; HPT_ASSERT(pCmd); CdbLength = csio->cdb_len; @@ -2960,40 +2940,21 @@ OsSendCommand(_VBUS_ARG union ccb *ccb) break; } /*///////////////////////// */ - if (ccb->ccb_h.flags & CAM_SCATTER_VALID) { - int idx; - bus_dma_segment_t *sgList = (bus_dma_segment_t *)ccb->csio.data_ptr; - - if (ccb->ccb_h.flags & CAM_SG_LIST_PHYS) - pCmd->cf_physical_sg = 1; - - for (idx = 0; idx < ccb->csio.sglist_cnt; idx++) { - pCmd->pSgTable[idx].dSgAddress = (ULONG_PTR)(UCHAR *)sgList[idx].ds_addr; - pCmd->pSgTable[idx].wSgSize = sgList[idx].ds_len; - pCmd->pSgTable[idx].wSgFlag= (idx==ccb->csio.sglist_cnt-1)?SG_FLAG_EOT: 0; - } - - ccb->ccb_h.timeout_ch = timeout(hpt_timeout, (caddr_t)ccb, 20*hz); - pVDev->pfnSendCommand(_VBUS_P pCmd); - } - else { - int error; - pCmd->cf_physical_sg = 1; - error = bus_dmamap_load(pAdapter->io_dma_parent, - pmap->dma_map, - ccb->csio.data_ptr, ccb->csio.dxfer_len, - hpt_io_dmamap_callback, pCmd, - BUS_DMA_WAITOK - ); - KdPrint(("bus_dmamap_load return %d\n", error)); - if (error && error!=EINPROGRESS) { - hpt_printk(("bus_dmamap_load error %d\n", error)); - FreeCommand(_VBUS_P pCmd); - ccb->ccb_h.status = CAM_REQ_CMP_ERR; - dmamap_put(pmap); - pAdapter->outstandingCommands--; - xpt_done(ccb); - } + pCmd->cf_physical_sg = 1; + error = bus_dmamap_load_ccb(pAdapter->io_dma_parent, + pmap->dma_map, + ccb, + hpt_io_dmamap_callback, + pCmd, BUS_DMA_WAITOK + ); + KdPrint(("bus_dmamap_load return %d\n", error)); + if (error && error!=EINPROGRESS) { + hpt_printk(("bus_dmamap_load error %d\n", error)); + FreeCommand(_VBUS_P pCmd); + ccb->ccb_h.status = CAM_REQ_CMP_ERR; + dmamap_put(pmap); + pAdapter->outstandingCommands--; + xpt_done(ccb); } goto Command_Complished; } diff --git a/sys/dev/hptrr/hptrr_osm_bsd.c b/sys/dev/hptrr/hptrr_osm_bsd.c index cff4254dd53..3c31f8cadd5 100644 --- a/sys/dev/hptrr/hptrr_osm_bsd.c +++ b/sys/dev/hptrr/hptrr_osm_bsd.c @@ -481,32 +481,6 @@ static void os_cmddone(PCOMMAND pCmd) static int os_buildsgl(PCOMMAND pCmd, PSG pSg, int logical) { - POS_CMDEXT ext = (POS_CMDEXT)pCmd->priv; - union ccb *ccb = ext->ccb; - bus_dma_segment_t *sgList = (bus_dma_segment_t *)ccb->csio.data_ptr; - int idx; - - if(logical) { - if (ccb->ccb_h.flags & CAM_DATA_PHYS) - panic("physical address unsupported"); - - if (ccb->ccb_h.flags & CAM_SCATTER_VALID) { - if (ccb->ccb_h.flags & CAM_SG_LIST_PHYS) - panic("physical address unsupported"); - - for (idx = 0; idx < ccb->csio.sglist_cnt; idx++) { - os_set_sgptr(&pSg[idx], (HPT_U8 *)(HPT_UPTR)sgList[idx].ds_addr); - pSg[idx].size = sgList[idx].ds_len; - pSg[idx].eot = (idx==ccb->csio.sglist_cnt-1)? 1 : 0; - } - } - else { - os_set_sgptr(pSg, (HPT_U8 *)ccb->csio.data_ptr); - pSg->size = ccb->csio.dxfer_len; - pSg->eot = 1; - } - return TRUE; - } /* since we have provided physical sg, nobody will ask us to build physical sg */ HPT_ASSERT(0); @@ -522,25 +496,28 @@ static void hpt_io_dmamap_callback(void *arg, bus_dma_segment_t *segs, int nsegs HPT_ASSERT(pCmd->flags.physical_sg); - if (error || nsegs == 0) + if (error) panic("busdma error"); HPT_ASSERT(nsegs<=os_max_sg_descriptors); - for (idx = 0; idx < nsegs; idx++, psg++) { - psg->addr.bus = segs[idx].ds_addr; - psg->size = segs[idx].ds_len; - psg->eot = 0; + if (nsegs != 0) { + for (idx = 0; idx < nsegs; idx++, psg++) { + psg->addr.bus = segs[idx].ds_addr; + psg->size = segs[idx].ds_len; + psg->eot = 0; + } + psg[-1].eot = 1; + + if (pCmd->flags.data_in) { + bus_dmamap_sync(ext->vbus_ext->io_dmat, ext->dma_map, + BUS_DMASYNC_PREREAD); + } + else if (pCmd->flags.data_out) { + bus_dmamap_sync(ext->vbus_ext->io_dmat, ext->dma_map, + BUS_DMASYNC_PREWRITE); + } } - psg[-1].eot = 1; - - if (pCmd->flags.data_in) { - bus_dmamap_sync(ext->vbus_ext->io_dmat, ext->dma_map, BUS_DMASYNC_PREREAD); - } - else if (pCmd->flags.data_out) { - bus_dmamap_sync(ext->vbus_ext->io_dmat, ext->dma_map, BUS_DMASYNC_PREWRITE); - } - ext->ccb->ccb_h.timeout_ch = timeout(hpt_timeout, pCmd, HPT_OSM_TIMEOUT); ldm_queue_cmd(pCmd); } @@ -667,6 +644,8 @@ static void hpt_scsi_io(PVBUS_EXT vbus_ext, union ccb *ccb) case 0x13: case 0x2f: { + int error; + pCmd = ldm_alloc_cmds(vbus, vd->cmds_per_request); if(!pCmd){ KdPrint(("Failed to allocate command!")); @@ -722,42 +701,21 @@ static void hpt_scsi_io(PVBUS_EXT vbus_ext, union ccb *ccb) pCmd->target = vd; pCmd->done = os_cmddone; pCmd->buildsgl = os_buildsgl; - pCmd->psg = ext->psg; - - if (ccb->ccb_h.flags & CAM_SCATTER_VALID) { - int idx; - bus_dma_segment_t *sgList = (bus_dma_segment_t *)ccb->csio.data_ptr; - - if (ccb->ccb_h.flags & CAM_SG_LIST_PHYS) - pCmd->flags.physical_sg = 1; - - for (idx = 0; idx < ccb->csio.sglist_cnt; idx++) { - pCmd->psg[idx].addr.bus = sgList[idx].ds_addr; - pCmd->psg[idx].size = sgList[idx].ds_len; - pCmd->psg[idx].eot = (idx==ccb->csio.sglist_cnt-1)? 1 : 0; - } - - ccb->ccb_h.timeout_ch = timeout(hpt_timeout, pCmd, HPT_OSM_TIMEOUT); - ldm_queue_cmd(pCmd); - } - else { - int error; - pCmd->flags.physical_sg = 1; - error = bus_dmamap_load(vbus_ext->io_dmat, - ext->dma_map, - ccb->csio.data_ptr, ccb->csio.dxfer_len, - hpt_io_dmamap_callback, pCmd, - BUS_DMA_WAITOK + pCmd->flags.physical_sg = 1; + error = bus_dmamap_load_ccb(vbus_ext->io_dmat, + ext->dma_map, + ccb, + hpt_io_dmamap_callback, pCmd, + BUS_DMA_WAITOK ); - KdPrint(("bus_dmamap_load return %d", error)); - if (error && error!=EINPROGRESS) { - os_printk("bus_dmamap_load error %d", error); - cmdext_put(ext); - ldm_free_cmds(pCmd); - ccb->ccb_h.status = CAM_REQ_CMP_ERR; - xpt_done(ccb); - } + KdPrint(("bus_dmamap_load return %d", error)); + if (error && error!=EINPROGRESS) { + os_printk("bus_dmamap_load error %d", error); + cmdext_put(ext); + ldm_free_cmds(pCmd); + ccb->ccb_h.status = CAM_REQ_CMP_ERR; + xpt_done(ccb); } return; } diff --git a/sys/dev/iir/iir.c b/sys/dev/iir/iir.c index 057194a71b5..4c907f01494 100644 --- a/sys/dev/iir/iir.c +++ b/sys/dev/iir/iir.c @@ -794,6 +794,7 @@ gdt_raw_cmd(struct gdt_softc *gdt, union ccb *ccb, int *lock) { struct gdt_ccb *gccb; struct cam_sim *sim; + int error; GDT_DPRINTF(GDT_D_CMD, ("gdt_raw_cmd(%p, %p)\n", gdt, ccb)); @@ -844,51 +845,14 @@ gdt_raw_cmd(struct gdt_softc *gdt, union ccb *ccb, int *lock) gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_RAW_SENSE_DATA, gccb->gc_scratch_busbase); - /* - * If we have any data to send with this command, - * map it into bus space. - */ - /* Only use S/G if there is a transfer */ - if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { - if ((ccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) { - if ((ccb->ccb_h.flags & CAM_DATA_PHYS) == 0) { - int s; - int error; - - /* vorher unlock von splcam() ??? */ - s = splsoftvm(); - error = - bus_dmamap_load(gdt->sc_buffer_dmat, - gccb->gc_dmamap, - ccb->csio.data_ptr, - ccb->csio.dxfer_len, - gdtexecuteccb, - gccb, /*flags*/0); - if (error == EINPROGRESS) { - xpt_freeze_simq(sim, 1); - gccb->gc_ccb->ccb_h.status |= CAM_RELEASE_SIMQ; - } - splx(s); - } else { - panic("iir: CAM_DATA_PHYS not supported"); - } - } else { - struct bus_dma_segment *segs; - - if ((ccb->ccb_h.flags & CAM_DATA_PHYS) != 0) - panic("iir%d: iir_action - Physical " - "segment pointers unsupported", gdt->sc_hanum); - - if ((ccb->ccb_h.flags & CAM_SG_LIST_PHYS)==0) - panic("iir%d: iir_action - Virtual " - "segment addresses unsupported", gdt->sc_hanum); - - /* Just use the segments provided */ - segs = (struct bus_dma_segment *)ccb->csio.data_ptr; - gdtexecuteccb(gccb, segs, ccb->csio.sglist_cnt, 0); - } - } else { - gdtexecuteccb(gccb, NULL, 0, 0); + error = bus_dmamap_load_ccb(gdt->sc_buffer_dmat, + gccb->gc_dmamap, + ccb, + gdtexecuteccb, + gccb, /*flags*/0); + if (error == EINPROGRESS) { + xpt_freeze_simq(sim, 1); + gccb->gc_ccb->ccb_h.status |= CAM_RELEASE_SIMQ; } *lock = splcam(); @@ -903,6 +867,7 @@ gdt_cache_cmd(struct gdt_softc *gdt, union ccb *ccb, int *lock) u_int8_t *cmdp; u_int16_t opcode; u_int32_t blockno, blockcnt; + int error; GDT_DPRINTF(GDT_D_CMD, ("gdt_cache_cmd(%p, %p)\n", gdt, ccb)); @@ -953,49 +918,15 @@ gdt_cache_cmd(struct gdt_softc *gdt, union ccb *ccb, int *lock) gdt_enc32(gccb->gc_cmd + GDT_CMD_UNION + GDT_CACHE_BLOCKCNT, blockcnt); - /* - * If we have any data to send with this command, - * map it into bus space. - */ - /* Only use S/G if there is a transfer */ - if ((ccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) { - if ((ccb->ccb_h.flags & CAM_DATA_PHYS) == 0) { - int s; - int error; - - /* vorher unlock von splcam() ??? */ - s = splsoftvm(); - error = - bus_dmamap_load(gdt->sc_buffer_dmat, + error = bus_dmamap_load_ccb(gdt->sc_buffer_dmat, gccb->gc_dmamap, - ccb->csio.data_ptr, - ccb->csio.dxfer_len, + ccb, gdtexecuteccb, gccb, /*flags*/0); - if (error == EINPROGRESS) { - xpt_freeze_simq(sim, 1); - gccb->gc_ccb->ccb_h.status |= CAM_RELEASE_SIMQ; - } - splx(s); - } else { - panic("iir: CAM_DATA_PHYS not supported"); - } - } else { - struct bus_dma_segment *segs; - - if ((ccb->ccb_h.flags & CAM_DATA_PHYS) != 0) - panic("iir%d: iir_action - Physical " - "segment pointers unsupported", gdt->sc_hanum); - - if ((ccb->ccb_h.flags & CAM_SG_LIST_PHYS)==0) - panic("iir%d: iir_action - Virtual " - "segment addresses unsupported", gdt->sc_hanum); - - /* Just use the segments provided */ - segs = (struct bus_dma_segment *)ccb->csio.data_ptr; - gdtexecuteccb(gccb, segs, ccb->csio.sglist_cnt, 0); + if (error == EINPROGRESS) { + xpt_freeze_simq(sim, 1); + gccb->gc_ccb->ccb_h.status |= CAM_RELEASE_SIMQ; } - *lock = splcam(); return (gccb); } diff --git a/sys/dev/isci/isci_io_request.c b/sys/dev/isci/isci_io_request.c index 719034e5261..9778ed08df7 100644 --- a/sys/dev/isci/isci_io_request.c +++ b/sys/dev/isci/isci_io_request.c @@ -713,7 +713,6 @@ void isci_io_request_execute_scsi_io(union ccb *ccb, struct ISCI_CONTROLLER *controller) { - struct ccb_scsiio *csio = &ccb->csio; target_id_t target_id = ccb->ccb_h.target_id; struct ISCI_REQUEST *request; struct ISCI_IO_REQUEST *io_request; @@ -748,29 +747,21 @@ isci_io_request_execute_scsi_io(union ccb *ccb, io_request->current_sge_index = 0; io_request->parent.remote_device_handle = device->sci_object; - if ((ccb->ccb_h.flags & CAM_SCATTER_VALID) != 0) - panic("Unexpected CAM_SCATTER_VALID flag! flags = 0x%x\n", + if ((ccb->ccb_h.flags & CAM_DATA_MASK) != CAM_DATA_VADDR) + panic("Unexpected cam data format! flags = 0x%x\n", ccb->ccb_h.flags); - if ((ccb->ccb_h.flags & CAM_DATA_PHYS) != 0) - panic("Unexpected CAM_DATA_PHYS flag! flags = 0x%x\n", - ccb->ccb_h.flags); - - if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { - error = bus_dmamap_load(io_request->parent.dma_tag, - io_request->parent.dma_map, csio->data_ptr, csio->dxfer_len, - isci_io_request_construct, io_request, 0x0); - - /* A resource shortage from BUSDMA will be automatically - * continued at a later point, pushing the CCB processing - * forward, which will in turn unfreeze the simq. - */ - if (error == EINPROGRESS) { - xpt_freeze_simq(controller->sim, 1); - ccb->ccb_h.flags |= CAM_RELEASE_SIMQ; - } - } else - isci_io_request_construct(io_request, NULL, 0, 0); + error = bus_dmamap_load_ccb(io_request->parent.dma_tag, + io_request->parent.dma_map, ccb, + isci_io_request_construct, io_request, 0x0); + /* A resource shortage from BUSDMA will be automatically + * continued at a later point, pushing the CCB processing + * forward, which will in turn unfreeze the simq. + */ + if (error == EINPROGRESS) { + xpt_freeze_simq(controller->sim, 1); + ccb->ccb_h.flags |= CAM_RELEASE_SIMQ; + } } void diff --git a/sys/dev/isp/isp_pci.c b/sys/dev/isp/isp_pci.c index e0260d4be6e..795f4324c7f 100644 --- a/sys/dev/isp/isp_pci.c +++ b/sys/dev/isp/isp_pci.c @@ -1922,6 +1922,7 @@ isp_pci_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, void *ff) mush_t mush, *mp; void (*eptr)(void *, bus_dma_segment_t *, int, int); void (*eptr2)(void *, bus_dma_segment_t *, int, bus_size_t, int); + int error; mp = &mush; mp->isp = isp; @@ -1942,70 +1943,17 @@ isp_pci_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, void *ff) } - if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE || (csio->dxfer_len == 0)) { - (*eptr)(mp, NULL, 0, 0); - } else if ((csio->ccb_h.flags & CAM_SCATTER_VALID) == 0) { - if ((csio->ccb_h.flags & CAM_DATA_PHYS) == 0) { - int error; - error = bus_dmamap_load(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, csio->data_ptr, csio->dxfer_len, eptr, mp, 0); -#if 0 - xpt_print(csio->ccb_h.path, "%s: bus_dmamap_load " "ptr %p len %d returned %d\n", __func__, csio->data_ptr, csio->dxfer_len, error); -#endif - - if (error == EINPROGRESS) { - bus_dmamap_unload(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap); - mp->error = EINVAL; - isp_prt(isp, ISP_LOGERR, "deferred dma allocation not supported"); - } else if (error && mp->error == 0) { + error = bus_dmamap_load_ccb(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, + (union ccb *)csio, eptr, mp, 0); + if (error == EINPROGRESS) { + bus_dmamap_unload(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap); + mp->error = EINVAL; + isp_prt(isp, ISP_LOGERR, "deferred dma allocation not supported"); + } else if (error && mp->error == 0) { #ifdef DIAGNOSTIC - isp_prt(isp, ISP_LOGERR, "error %d in dma mapping code", error); + isp_prt(isp, ISP_LOGERR, "error %d in dma mapping code", error); #endif - mp->error = error; - } - } else { - /* Pointer to physical buffer */ - struct bus_dma_segment seg; - seg.ds_addr = (bus_addr_t)(vm_offset_t)csio->data_ptr; - seg.ds_len = csio->dxfer_len; - (*eptr)(mp, &seg, 1, 0); - } - } else { - struct bus_dma_segment *segs; - - if ((csio->ccb_h.flags & CAM_DATA_PHYS) != 0) { - isp_prt(isp, ISP_LOGERR, "Physical segment pointers unsupported"); - mp->error = EINVAL; - } else if ((csio->ccb_h.flags & CAM_SG_LIST_PHYS) == 0) { - struct uio sguio; - int error; - - /* - * We're taking advantage of the fact that - * the pointer/length sizes and layout of the iovec - * structure are the same as the bus_dma_segment - * structure. This might be a little dangerous, - * but only if they change the structures, which - * seems unlikely. - */ - KASSERT((sizeof (sguio.uio_iov) == sizeof (csio->data_ptr) && - sizeof (sguio.uio_iovcnt) >= sizeof (csio->sglist_cnt) && - sizeof (sguio.uio_resid) >= sizeof (csio->dxfer_len)), ("Ken's assumption failed")); - sguio.uio_iov = (struct iovec *)csio->data_ptr; - sguio.uio_iovcnt = csio->sglist_cnt; - sguio.uio_resid = csio->dxfer_len; - sguio.uio_segflg = UIO_SYSSPACE; - - error = bus_dmamap_load_uio(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, &sguio, eptr2, mp, 0); - - if (error != 0 && mp->error == 0) { - isp_prt(isp, ISP_LOGERR, "error %d in dma mapping code", error); - mp->error = error; - } - } else { - /* Just use the segments provided */ - segs = (struct bus_dma_segment *) csio->data_ptr; - (*eptr)(mp, segs, csio->sglist_cnt, 0); - } + mp->error = error; } if (mp->error) { int retval = CMD_COMPLETE; diff --git a/sys/dev/isp/isp_sbus.c b/sys/dev/isp/isp_sbus.c index 0b4f63fb07b..9afcc8e606d 100644 --- a/sys/dev/isp/isp_sbus.c +++ b/sys/dev/isp/isp_sbus.c @@ -635,6 +635,7 @@ isp_sbus_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, void *ff) { mush_t mush, *mp; void (*eptr)(void *, bus_dma_segment_t *, int, int); + int error; mp = &mush; mp->isp = isp; @@ -645,47 +646,18 @@ isp_sbus_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, void *ff) eptr = dma2; - if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE || (csio->dxfer_len == 0)) { - (*eptr)(mp, NULL, 0, 0); - } else if ((csio->ccb_h.flags & CAM_SCATTER_VALID) == 0) { - if ((csio->ccb_h.flags & CAM_DATA_PHYS) == 0) { - int error; - error = bus_dmamap_load(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap, csio->data_ptr, csio->dxfer_len, eptr, mp, 0); -#if 0 - xpt_print(csio->ccb_h.path, "%s: bus_dmamap_load " "ptr %p len %d returned %d\n", __func__, csio->data_ptr, csio->dxfer_len, error); -#endif - - if (error == EINPROGRESS) { - bus_dmamap_unload(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap); - mp->error = EINVAL; - isp_prt(isp, ISP_LOGERR, "deferred dma allocation not supported"); - } else if (error && mp->error == 0) { + error = bus_dmamap_load_ccb(isp->isp_osinfo.dmat, + PISP_PCMD(csio)->dmap, (union ccb *)csio, eptr, mp, 0); + if (error == EINPROGRESS) { + bus_dmamap_unload(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap); + mp->error = EINVAL; + isp_prt(isp, ISP_LOGERR, + "deferred dma allocation not supported"); + } else if (error && mp->error == 0) { #ifdef DIAGNOSTIC - isp_prt(isp, ISP_LOGERR, "error %d in dma mapping code", error); + isp_prt(isp, ISP_LOGERR, "error %d in dma mapping code", error); #endif - mp->error = error; - } - } else { - /* Pointer to physical buffer */ - struct bus_dma_segment seg; - seg.ds_addr = (bus_addr_t)(vm_offset_t)csio->data_ptr; - seg.ds_len = csio->dxfer_len; - (*eptr)(mp, &seg, 1, 0); - } - } else { - struct bus_dma_segment *segs; - - if ((csio->ccb_h.flags & CAM_DATA_PHYS) != 0) { - isp_prt(isp, ISP_LOGERR, "Physical segment pointers unsupported"); - mp->error = EINVAL; - } else if ((csio->ccb_h.flags & CAM_SG_LIST_PHYS) == 0) { - isp_prt(isp, ISP_LOGERR, "Physical SG/LIST Phys segment pointers unsupported"); - mp->error = EINVAL; - } else { - /* Just use the segments provided */ - segs = (struct bus_dma_segment *) csio->data_ptr; - (*eptr)(mp, segs, csio->sglist_cnt, 0); - } + mp->error = error; } if (mp->error) { int retval = CMD_COMPLETE; diff --git a/sys/dev/mfi/mfi.c b/sys/dev/mfi/mfi.c index 7cb19d2cd5f..ed759fc729b 100644 --- a/sys/dev/mfi/mfi.c +++ b/sys/dev/mfi/mfi.c @@ -2267,8 +2267,14 @@ mfi_mapcmd(struct mfi_softc *sc, struct mfi_command *cm) if ((cm->cm_data != NULL) && (cm->cm_frame->header.cmd != MFI_CMD_STP )) { polled = (cm->cm_flags & MFI_CMD_POLLED) ? BUS_DMA_NOWAIT : 0; - error = bus_dmamap_load(sc->mfi_buffer_dmat, cm->cm_dmamap, - cm->cm_data, cm->cm_len, mfi_data_cb, cm, polled); + if (cm->cm_flags & MFI_CMD_CCB) + error = bus_dmamap_load_ccb(sc->mfi_buffer_dmat, + cm->cm_dmamap, cm->cm_data, mfi_data_cb, cm, + polled); + else + error = bus_dmamap_load(sc->mfi_buffer_dmat, + cm->cm_dmamap, cm->cm_data, cm->cm_len, + mfi_data_cb, cm, polled); if (error == EINPROGRESS) { sc->mfi_flags |= MFI_FLAGS_QFRZN; return (0); diff --git a/sys/dev/mfi/mfi_cam.c b/sys/dev/mfi/mfi_cam.c index 2bbfafe83ef..325b064cde9 100644 --- a/sys/dev/mfi/mfi_cam.c +++ b/sys/dev/mfi/mfi_cam.c @@ -265,17 +265,6 @@ mfip_cam_action(struct cam_sim *sim, union ccb *ccb) ccbh->status = CAM_REQ_INVALID; break; } - if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE) { - if (ccbh->flags & CAM_DATA_PHYS) { - ccbh->status = CAM_REQ_INVALID; - break; - } - if (ccbh->flags & CAM_SCATTER_VALID) { - ccbh->status = CAM_REQ_INVALID; - break; - } - } - ccbh->ccb_mfip_ptr = sc; TAILQ_INSERT_TAIL(&mfisc->mfi_cam_ccbq, ccbh, sim_links.tqe); mfi_startio(mfisc); @@ -380,14 +369,14 @@ mfip_start(void *data) cm->cm_private = ccb; cm->cm_sg = &pt->sgl; cm->cm_total_frame_size = MFI_PASS_FRAME_SIZE; - cm->cm_data = csio->data_ptr; + cm->cm_data = ccb; cm->cm_len = csio->dxfer_len; switch (ccbh->flags & CAM_DIR_MASK) { case CAM_DIR_IN: - cm->cm_flags = MFI_CMD_DATAIN; + cm->cm_flags = MFI_CMD_DATAIN | MFI_CMD_CCB; break; case CAM_DIR_OUT: - cm->cm_flags = MFI_CMD_DATAOUT; + cm->cm_flags = MFI_CMD_DATAOUT | MFI_CMD_CCB; break; case CAM_DIR_NONE: default: diff --git a/sys/dev/mfi/mfivar.h b/sys/dev/mfi/mfivar.h index 435ca8d7941..bb2a324b514 100644 --- a/sys/dev/mfi/mfivar.h +++ b/sys/dev/mfi/mfivar.h @@ -107,6 +107,7 @@ struct mfi_command { #define MFI_ON_MFIQ_BUSY (1<<7) #define MFI_ON_MFIQ_MASK ((1<<5)|(1<<6)|(1<<7)) #define MFI_CMD_SCSI (1<<8) +#define MFI_CMD_CCB (1<<9) uint8_t retry_for_fw_reset; void (* cm_complete)(struct mfi_command *cm); void *cm_private; diff --git a/sys/dev/mly/mly.c b/sys/dev/mly/mly.c index 1f0a9e2a66b..9155d6041ce 100644 --- a/sys/dev/mly/mly.c +++ b/sys/dev/mly/mly.c @@ -1864,9 +1864,13 @@ mly_map_command(struct mly_command *mc) /* does the command have a data buffer? */ if (mc->mc_data != NULL) { - bus_dmamap_load(sc->mly_buffer_dmat, mc->mc_datamap, mc->mc_data, mc->mc_length, - mly_map_command_sg, mc, 0); - + if (mc->mc_flags & MLY_CMD_CCB) + bus_dmamap_load_ccb(sc->mly_buffer_dmat, mc->mc_datamap, + mc->mc_data, mly_map_command_sg, mc, 0); + else + bus_dmamap_load(sc->mly_buffer_dmat, mc->mc_datamap, + mc->mc_data, mc->mc_length, + mly_map_command_sg, mc, 0); if (mc->mc_flags & MLY_CMD_DATAIN) bus_dmamap_sync(sc->mly_buffer_dmat, mc->mc_datamap, BUS_DMASYNC_PREREAD); if (mc->mc_flags & MLY_CMD_DATAOUT) @@ -2220,18 +2224,6 @@ mly_cam_action_io(struct cam_sim *sim, struct ccb_scsiio *csio) csio->ccb_h.status = CAM_REQ_CMP_ERR; } - /* if there is data transfer, it must be to/from a virtual address */ - if ((csio->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { - if (csio->ccb_h.flags & CAM_DATA_PHYS) { /* we can't map it */ - debug(0, " data pointer is to physical address"); - csio->ccb_h.status = CAM_REQ_CMP_ERR; - } - if (csio->ccb_h.flags & CAM_SCATTER_VALID) { /* we want to do the s/g setup */ - debug(0, " data has premature s/g setup"); - csio->ccb_h.status = CAM_REQ_CMP_ERR; - } - } - /* abandon aborted ccbs or those that have failed validation */ if ((csio->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { debug(2, "abandoning CCB due to abort/validation failure"); @@ -2251,10 +2243,12 @@ mly_cam_action_io(struct cam_sim *sim, struct ccb_scsiio *csio) } /* build the command */ - mc->mc_data = csio->data_ptr; + mc->mc_data = csio; mc->mc_length = csio->dxfer_len; mc->mc_complete = mly_cam_complete; mc->mc_private = csio; + mc->mc_flags |= MLY_CMD_CCB; + /* XXX This code doesn't set the data direction in mc_flags. */ /* save the bus number in the ccb for later recovery XXX should be a better way */ csio->ccb_h.sim_priv.entries[0].field = bus; diff --git a/sys/dev/mly/mlyvar.h b/sys/dev/mly/mlyvar.h index 62e674c7363..7413fa40e9e 100644 --- a/sys/dev/mly/mlyvar.h +++ b/sys/dev/mly/mlyvar.h @@ -126,6 +126,7 @@ struct mly_command { #define MLY_CMD_MAPPED (1<<3) /* command has had its data mapped */ #define MLY_CMD_DATAIN (1<<4) /* data moves controller->system */ #define MLY_CMD_DATAOUT (1<<5) /* data moves system->controller */ +#define MLY_CMD_CCB (1<<6) /* data is ccb. */ u_int16_t mc_status; /* command completion status */ u_int8_t mc_sense; /* sense data length */ int32_t mc_resid; /* I/O residual count */ diff --git a/sys/dev/mps/mps.c b/sys/dev/mps/mps.c index ce94a06f624..7a3e4f7637d 100644 --- a/sys/dev/mps/mps.c +++ b/sys/dev/mps/mps.c @@ -2278,6 +2278,9 @@ mps_map_command(struct mps_softc *sc, struct mps_command *cm) if (cm->cm_flags & MPS_CM_FLAGS_USE_UIO) { error = bus_dmamap_load_uio(sc->buffer_dmat, cm->cm_dmamap, &cm->cm_uio, mps_data_cb2, cm, 0); + } else if (cm->cm_flags & MPS_CM_FLAGS_USE_CCB) { + error = bus_dmamap_load_ccb(sc->buffer_dmat, cm->cm_dmamap, + cm->cm_data, mps_data_cb, cm, 0); } else if ((cm->cm_data != NULL) && (cm->cm_length != 0)) { error = bus_dmamap_load(sc->buffer_dmat, cm->cm_dmamap, cm->cm_data, cm->cm_length, mps_data_cb, cm, 0); diff --git a/sys/dev/mps/mps_sas.c b/sys/dev/mps/mps_sas.c index a76a0aaf01f..0d8342e5a5a 100644 --- a/sys/dev/mps/mps_sas.c +++ b/sys/dev/mps/mps_sas.c @@ -1755,8 +1755,13 @@ mpssas_action_scsiio(struct mpssas_softc *sassc, union ccb *ccb) } } - cm->cm_data = csio->data_ptr; cm->cm_length = csio->dxfer_len; + if (cm->cm_length != 0) { + cm->cm_data = ccb; + cm->cm_flags |= MPS_CM_FLAGS_USE_CCB; + } else { + cm->cm_data = NULL; + } cm->cm_sge = &req->SGL; cm->cm_sglsize = (32 - 24) * 4; cm->cm_desc.SCSIIO.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO; @@ -2691,19 +2696,15 @@ mpssas_send_smpcmd(struct mpssas_softc *sassc, union ccb *ccb, uint64_t sasaddr) /* * XXX We don't yet support physical addresses here. */ - if (ccb->ccb_h.flags & (CAM_DATA_PHYS|CAM_SG_LIST_PHYS)) { + switch ((ccb->ccb_h.flags & CAM_DATA_MASK)) { + case CAM_DATA_PADDR: + case CAM_DATA_SG_PADDR: mps_printf(sc, "%s: physical addresses not supported\n", __func__); ccb->ccb_h.status = CAM_REQ_INVALID; xpt_done(ccb); return; - } - - /* - * If the user wants to send an S/G list, check to make sure they - * have single buffers. - */ - if (ccb->ccb_h.flags & CAM_SCATTER_VALID) { + case CAM_DATA_SG: /* * The chip does not support more than one buffer for the * request or response. @@ -2741,9 +2742,15 @@ mpssas_send_smpcmd(struct mpssas_softc *sassc, union ccb *ccb, uint64_t sasaddr) response = (uint8_t *)(uintptr_t)rsp_sg[0].ds_addr; } else response = ccb->smpio.smp_response; - } else { + break; + case CAM_DATA_VADDR: request = ccb->smpio.smp_request; response = ccb->smpio.smp_response; + break; + default: + ccb->ccb_h.status = CAM_REQ_INVALID; + xpt_done(ccb); + return; } cm = mps_alloc_command(sc); diff --git a/sys/dev/mps/mpsvar.h b/sys/dev/mps/mpsvar.h index ac0f0da2e7d..5d14b5fe1e7 100644 --- a/sys/dev/mps/mpsvar.h +++ b/sys/dev/mps/mpsvar.h @@ -231,6 +231,7 @@ struct mps_command { #define MPS_CM_FLAGS_SMP_PASS (1 << 8) #define MPS_CM_FLAGS_CHAIN_FAILED (1 << 9) #define MPS_CM_FLAGS_ERROR_MASK MPS_CM_FLAGS_CHAIN_FAILED +#define MPS_CM_FLAGS_USE_CCB (1 << 10) u_int cm_state; #define MPS_CM_STATE_FREE 0 #define MPS_CM_STATE_BUSY 1 diff --git a/sys/dev/mpt/mpt_cam.c b/sys/dev/mpt/mpt_cam.c index d435f77e8a4..119dd503889 100644 --- a/sys/dev/mpt/mpt_cam.c +++ b/sys/dev/mpt/mpt_cam.c @@ -1382,7 +1382,7 @@ bad: } } - if (!(ccb->ccb_h.flags & (CAM_SG_LIST_PHYS|CAM_DATA_PHYS))) { + if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { bus_dmasync_op_t op; if (istgt == 0) { if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { @@ -1623,7 +1623,7 @@ out: mpt_prt(mpt, "mpt_execute_req_a64: I/O cancelled (status 0x%x)\n", ccb->ccb_h.status & CAM_STATUS_MASK); - if (nseg && (ccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0) { + if (nseg) { bus_dmamap_unload(mpt->buffer_dmat, req->dmap); } ccb->ccb_h.status &= ~CAM_SIM_QUEUED; @@ -1785,7 +1785,7 @@ bad: } } - if (!(ccb->ccb_h.flags & (CAM_SG_LIST_PHYS|CAM_DATA_PHYS))) { + if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { bus_dmasync_op_t op; if (istgt) { if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { @@ -2010,7 +2010,7 @@ out: mpt_prt(mpt, "mpt_execute_req: I/O cancelled (status 0x%x)\n", ccb->ccb_h.status & CAM_STATUS_MASK); - if (nseg && (ccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0) { + if (nseg) { bus_dmamap_unload(mpt->buffer_dmat, req->dmap); } ccb->ccb_h.status &= ~CAM_SIM_QUEUED; @@ -2062,6 +2062,7 @@ mpt_start(struct cam_sim *sim, union ccb *ccb) bus_dmamap_callback_t *cb; target_id_t tgt; int raid_passthru; + int error; /* Get the pointer for the physical addapter */ mpt = ccb->ccb_h.ccb_mpt_ptr; @@ -2206,64 +2207,15 @@ mpt_start(struct cam_sim *sim, union ccb *ccb) ccb->ccb_h.target_lun, req, req->serno); } - /* - * If we have any data to send with this command map it into bus space. - */ - if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE) { - if ((ccbh->flags & CAM_SCATTER_VALID) == 0) { - /* - * We've been given a pointer to a single buffer. - */ - if ((ccbh->flags & CAM_DATA_PHYS) == 0) { - /* - * Virtual address that needs to translated into - * one or more physical address ranges. - */ - int error; - int s = splsoftvm(); - error = bus_dmamap_load(mpt->buffer_dmat, - req->dmap, csio->data_ptr, csio->dxfer_len, - cb, req, 0); - splx(s); - if (error == EINPROGRESS) { - /* - * So as to maintain ordering, - * freeze the controller queue - * until our mapping is - * returned. - */ - xpt_freeze_simq(mpt->sim, 1); - ccbh->status |= CAM_RELEASE_SIMQ; - } - } else { - /* - * We have been given a pointer to single - * physical buffer. - */ - struct bus_dma_segment seg; - seg.ds_addr = - (bus_addr_t)(vm_offset_t)csio->data_ptr; - seg.ds_len = csio->dxfer_len; - (*cb)(req, &seg, 1, 0); - } - } else { - /* - * We have been given a list of addresses. - * This case could be easily supported but they are not - * currently generated by the CAM subsystem so there - * is no point in wasting the time right now. - */ - struct bus_dma_segment *segs; - if ((ccbh->flags & CAM_SG_LIST_PHYS) == 0) { - (*cb)(req, NULL, 0, EFAULT); - } else { - /* Just use the segments provided */ - segs = (struct bus_dma_segment *)csio->data_ptr; - (*cb)(req, segs, csio->sglist_cnt, 0); - } - } - } else { - (*cb)(req, NULL, 0, 0); + error = bus_dmamap_load_ccb(mpt->buffer_dmat, req->dmap, ccb, cb, + req, 0); + if (error == EINPROGRESS) { + /* + * So as to maintain ordering, freeze the controller queue + * until our mapping is returned. + */ + xpt_freeze_simq(mpt->sim, 1); + ccbh->status |= CAM_RELEASE_SIMQ; } } @@ -4458,6 +4410,7 @@ mpt_target_start_io(struct mpt_softc *mpt, union ccb *ccb) bus_dmamap_callback_t *cb; PTR_MSG_TARGET_ASSIST_REQUEST ta; request_t *req; + int error; KASSERT((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE, ("dxfer_len %u but direction is NONE", csio->dxfer_len)); @@ -4544,44 +4497,11 @@ mpt_target_start_io(struct mpt_softc *mpt, union ccb *ccb) "nxtstate=%d\n", csio, csio->tag_id, csio->dxfer_len, tgt->resid, ccb->ccb_h.flags, req, req->serno, tgt->state); - if ((ccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) { - if ((ccb->ccb_h.flags & CAM_DATA_PHYS) == 0) { - int error; - int s = splsoftvm(); - error = bus_dmamap_load(mpt->buffer_dmat, - req->dmap, csio->data_ptr, csio->dxfer_len, - cb, req, 0); - splx(s); - if (error == EINPROGRESS) { - xpt_freeze_simq(mpt->sim, 1); - ccb->ccb_h.status |= CAM_RELEASE_SIMQ; - } - } else { - /* - * We have been given a pointer to single - * physical buffer. - */ - struct bus_dma_segment seg; - seg.ds_addr = (bus_addr_t) - (vm_offset_t)csio->data_ptr; - seg.ds_len = csio->dxfer_len; - (*cb)(req, &seg, 1, 0); - } - } else { - /* - * We have been given a list of addresses. - * This case could be easily supported but they are not - * currently generated by the CAM subsystem so there - * is no point in wasting the time right now. - */ - struct bus_dma_segment *sgs; - if ((ccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0) { - (*cb)(req, NULL, 0, EFAULT); - } else { - /* Just use the segments provided */ - sgs = (struct bus_dma_segment *)csio->data_ptr; - (*cb)(req, sgs, csio->sglist_cnt, 0); - } + error = bus_dmamap_load_ccb(mpt->buffer_dmat, req->dmap, ccb, + cb, req, 0); + if (error == EINPROGRESS) { + xpt_freeze_simq(mpt->sim, 1); + ccb->ccb_h.status |= CAM_RELEASE_SIMQ; } } else { uint8_t *sp = NULL, sense[MPT_SENSE_SIZE]; diff --git a/sys/dev/mvs/mvs.c b/sys/dev/mvs/mvs.c index 21c9f9757f4..91ca4f027fd 100644 --- a/sys/dev/mvs/mvs.c +++ b/sys/dev/mvs/mvs.c @@ -1260,19 +1260,9 @@ mvs_begin_transaction(device_t dev, union ccb *ccb) mvs_set_edma_mode(dev, MVS_EDMA_OFF); } if (ch->numpslots == 0 || ch->basic_dma) { - void *buf; - bus_size_t size; - slot->state = MVS_SLOT_LOADING; - if (ccb->ccb_h.func_code == XPT_ATA_IO) { - buf = ccb->ataio.data_ptr; - size = ccb->ataio.dxfer_len; - } else { - buf = ccb->csio.data_ptr; - size = ccb->csio.dxfer_len; - } - bus_dmamap_load(ch->dma.data_tag, slot->dma.data_map, - buf, size, mvs_dmasetprd, slot, 0); + bus_dmamap_load_ccb(ch->dma.data_tag, slot->dma.data_map, + ccb, mvs_dmasetprd, slot, 0); } else mvs_legacy_execute_transaction(slot); } diff --git a/sys/dev/siis/siis.c b/sys/dev/siis/siis.c index a8a1ed22b82..fb8866478a1 100644 --- a/sys/dev/siis/siis.c +++ b/sys/dev/siis/siis.c @@ -996,19 +996,9 @@ siis_begin_transaction(device_t dev, union ccb *ccb) slot->dma.nsegs = 0; /* If request moves data, setup and load SG list */ if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { - void *buf; - bus_size_t size; - slot->state = SIIS_SLOT_LOADING; - if (ccb->ccb_h.func_code == XPT_ATA_IO) { - buf = ccb->ataio.data_ptr; - size = ccb->ataio.dxfer_len; - } else { - buf = ccb->csio.data_ptr; - size = ccb->csio.dxfer_len; - } - bus_dmamap_load(ch->dma.data_tag, slot->dma.data_map, - buf, size, siis_dmasetprd, slot, 0); + bus_dmamap_load_ccb(ch->dma.data_tag, slot->dma.data_map, + ccb, siis_dmasetprd, slot, 0); } else siis_execute_transaction(slot); } @@ -1032,24 +1022,26 @@ siis_dmasetprd(void *arg, bus_dma_segment_t *segs, int nsegs, int error) return; } KASSERT(nsegs <= SIIS_SG_ENTRIES, ("too many DMA segment entries\n")); - /* Get a piece of the workspace for this request */ - ctp = (struct siis_cmd *) - (ch->dma.work + SIIS_CT_OFFSET + (SIIS_CT_SIZE * slot->slot)); - /* Fill S/G table */ - if (slot->ccb->ccb_h.func_code == XPT_ATA_IO) - prd = &ctp->u.ata.prd[0]; - else - prd = &ctp->u.atapi.prd[0]; - for (i = 0; i < nsegs; i++) { - prd[i].dba = htole64(segs[i].ds_addr); - prd[i].dbc = htole32(segs[i].ds_len); - prd[i].control = 0; - } - prd[nsegs - 1].control = htole32(SIIS_PRD_TRM); slot->dma.nsegs = nsegs; - bus_dmamap_sync(ch->dma.data_tag, slot->dma.data_map, - ((slot->ccb->ccb_h.flags & CAM_DIR_IN) ? - BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE)); + if (nsegs != 0) { + /* Get a piece of the workspace for this request */ + ctp = (struct siis_cmd *)(ch->dma.work + SIIS_CT_OFFSET + + (SIIS_CT_SIZE * slot->slot)); + /* Fill S/G table */ + if (slot->ccb->ccb_h.func_code == XPT_ATA_IO) + prd = &ctp->u.ata.prd[0]; + else + prd = &ctp->u.atapi.prd[0]; + for (i = 0; i < nsegs; i++) { + prd[i].dba = htole64(segs[i].ds_addr); + prd[i].dbc = htole32(segs[i].ds_len); + prd[i].control = 0; + } + prd[nsegs - 1].control = htole32(SIIS_PRD_TRM); + bus_dmamap_sync(ch->dma.data_tag, slot->dma.data_map, + ((slot->ccb->ccb_h.flags & CAM_DIR_IN) ? + BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE)); + } siis_execute_transaction(slot); } diff --git a/sys/dev/sym/sym_hipd.c b/sys/dev/sym/sym_hipd.c index 7d0450c2e41..68ad77f68f9 100644 --- a/sys/dev/sym/sym_hipd.c +++ b/sys/dev/sym/sym_hipd.c @@ -7877,51 +7877,15 @@ sym_setup_data_and_start(hcb_p np, struct ccb_scsiio *csio, ccb_p cp) return; } - if (!(ccb_h->flags & CAM_SCATTER_VALID)) { - /* Single buffer */ - if (!(ccb_h->flags & CAM_DATA_PHYS)) { - /* Buffer is virtual */ - cp->dmamapped = (dir == CAM_DIR_IN) ? - SYM_DMA_READ : SYM_DMA_WRITE; - retv = bus_dmamap_load(np->data_dmat, cp->dmamap, - csio->data_ptr, csio->dxfer_len, - sym_execute_ccb, cp, 0); - if (retv == EINPROGRESS) { - cp->host_status = HS_WAIT; - xpt_freeze_simq(np->sim, 1); - csio->ccb_h.status |= CAM_RELEASE_SIMQ; - } - } else { - /* Buffer is physical */ - struct bus_dma_segment seg; - - seg.ds_addr = (bus_addr_t) csio->data_ptr; - sym_execute_ccb(cp, &seg, 1, 0); - } - } else { - /* Scatter/gather list */ - struct bus_dma_segment *segs; - - if ((ccb_h->flags & CAM_SG_LIST_PHYS) != 0) { - /* The SG list pointer is physical */ - sym_set_cam_status(cp->cam_ccb, CAM_REQ_INVALID); - goto out_abort; - } - - if (!(ccb_h->flags & CAM_DATA_PHYS)) { - /* SG buffer pointers are virtual */ - sym_set_cam_status(cp->cam_ccb, CAM_REQ_INVALID); - goto out_abort; - } - - /* SG buffer pointers are physical */ - segs = (struct bus_dma_segment *)csio->data_ptr; - sym_execute_ccb(cp, segs, csio->sglist_cnt, 0); + cp->dmamapped = (dir == CAM_DIR_IN) ? SYM_DMA_READ : SYM_DMA_WRITE; + retv = bus_dmamap_load_ccb(np->data_dmat, cp->dmamap, + (union ccb *)csio, sym_execute_ccb, cp, 0); + if (retv == EINPROGRESS) { + cp->host_status = HS_WAIT; + xpt_freeze_simq(np->sim, 1); + csio->ccb_h.status |= CAM_RELEASE_SIMQ; } return; -out_abort: - sym_xpt_done(np, (union ccb *) csio, cp); - sym_free_ccb(np, cp); } /* diff --git a/sys/dev/trm/trm.c b/sys/dev/trm/trm.c index 765d5eae3e0..60327986606 100644 --- a/sys/dev/trm/trm.c +++ b/sys/dev/trm/trm.c @@ -559,6 +559,7 @@ trm_action(struct cam_sim *psim, union ccb *pccb) PDCB pDCB = NULL; PSRB pSRB; struct ccb_scsiio *pcsio; + int error; pcsio = &pccb->csio; TRM_DPRINTF(" XPT_SCSI_IO \n"); @@ -614,71 +615,18 @@ trm_action(struct cam_sim *psim, union ccb *pccb) } else bcopy(pcsio->cdb_io.cdb_bytes, pSRB->CmdBlock, pcsio->cdb_len); - if ((pccb->ccb_h.flags & CAM_DIR_MASK) - != CAM_DIR_NONE) { - if ((pccb->ccb_h.flags & - CAM_SCATTER_VALID) == 0) { - if ((pccb->ccb_h.flags - & CAM_DATA_PHYS) == 0) { - int vmflags; - int error; - - vmflags = splsoftvm(); - error = bus_dmamap_load( - pACB->buffer_dmat, + error = bus_dmamap_load_ccb(pACB->buffer_dmat, pSRB->dmamap, - pcsio->data_ptr, - pcsio->dxfer_len, + pccb, trm_ExecuteSRB, pSRB, 0); - if (error == EINPROGRESS) { - xpt_freeze_simq( - pACB->psim, - 1); - pccb->ccb_h.status |= - CAM_RELEASE_SIMQ; - } - splx(vmflags); - } else { - struct bus_dma_segment seg; - - /* Pointer to physical buffer */ - seg.ds_addr = - (bus_addr_t)pcsio->data_ptr; - seg.ds_len = pcsio->dxfer_len; - trm_ExecuteSRB(pSRB, &seg, 1, - 0); - } - } else { - /* CAM_SCATTER_VALID */ - struct bus_dma_segment *segs; - - if ((pccb->ccb_h.flags & - CAM_SG_LIST_PHYS) == 0 || - (pccb->ccb_h.flags - & CAM_DATA_PHYS) != 0) { - pSRB->pNextSRB = pACB->pFreeSRB; - pACB->pFreeSRB = pSRB; - pccb->ccb_h.status = - CAM_PROVIDE_FAIL; - xpt_done(pccb); - splx(actionflags); - return; - } - - /* cam SG list is physical, - * cam data is virtual - */ - segs = (struct bus_dma_segment *) - pcsio->data_ptr; - trm_ExecuteSRB(pSRB, segs, - pcsio->sglist_cnt, 1); - } /* CAM_SCATTER_VALID */ - } else - trm_ExecuteSRB(pSRB, NULL, 0, 0); - } + if (error == EINPROGRESS) { + xpt_freeze_simq(pACB->psim, 1); + pccb->ccb_h.status |= CAM_RELEASE_SIMQ; + } break; + } case XPT_GDEV_TYPE: TRM_DPRINTF(" XPT_GDEV_TYPE \n"); pccb->ccb_h.status = CAM_REQ_INVALID; diff --git a/sys/dev/twa/tw_osl.h b/sys/dev/twa/tw_osl.h index 50fa722954e..bed16cda68f 100644 --- a/sys/dev/twa/tw_osl.h +++ b/sys/dev/twa/tw_osl.h @@ -72,6 +72,7 @@ #define TW_OSLI_REQ_FLAGS_PASSTHRU (1<<5) /* pass through request */ #define TW_OSLI_REQ_FLAGS_SLEEPING (1<<6) /* owner sleeping on this cmd */ #define TW_OSLI_REQ_FLAGS_FAILED (1<<7) /* bus_dmamap_load() failed */ +#define TW_OSLI_REQ_FLAGS_CCB (1<<8) /* req is ccb. */ #ifdef TW_OSL_DEBUG diff --git a/sys/dev/twa/tw_osl_cam.c b/sys/dev/twa/tw_osl_cam.c index 2c2d5aea415..9c4de23b02e 100644 --- a/sys/dev/twa/tw_osl_cam.c +++ b/sys/dev/twa/tw_osl_cam.c @@ -261,55 +261,23 @@ tw_osli_execute_scsi(struct tw_osli_req_context *req, union ccb *ccb) scsi_req->cdb = csio->cdb_io.cdb_bytes; scsi_req->cdb_len = csio->cdb_len; - if (!(ccb_h->flags & CAM_DATA_PHYS)) { - /* Virtual data addresses. Need to convert them... */ - tw_osli_dbg_dprintf(3, sc, - "XPT_SCSI_IO: Single virtual address!"); - if (!(ccb_h->flags & CAM_SCATTER_VALID)) { - if (csio->dxfer_len > TW_CL_MAX_IO_SIZE) { - tw_osli_printf(sc, "size = %d", - TW_CL_SEVERITY_ERROR_STRING, - TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, - 0x2106, - "I/O size too big", - csio->dxfer_len); - ccb_h->status = CAM_REQ_TOO_BIG; - ccb_h->status &= ~CAM_SIM_QUEUED; - xpt_done(ccb); - return(1); - } - - if ((req->length = csio->dxfer_len)) { - req->data = csio->data_ptr; - scsi_req->sgl_entries = 1; - } - } else { - tw_osli_printf(sc, "", - TW_CL_SEVERITY_ERROR_STRING, - TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, - 0x2107, - "XPT_SCSI_IO: Got SGList"); - ccb_h->status = CAM_REQ_INVALID; - ccb_h->status &= ~CAM_SIM_QUEUED; - xpt_done(ccb); - return(1); - } - } else { - /* Data addresses are physical. */ - tw_osli_printf(sc, "", + if (csio->dxfer_len > TW_CL_MAX_IO_SIZE) { + tw_osli_printf(sc, "size = %d", TW_CL_SEVERITY_ERROR_STRING, TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, - 0x2108, - "XPT_SCSI_IO: Physical data addresses"); - ccb_h->status = CAM_REQ_INVALID; + 0x2106, + "I/O size too big", + csio->dxfer_len); + ccb_h->status = CAM_REQ_TOO_BIG; ccb_h->status &= ~CAM_SIM_QUEUED; xpt_done(ccb); return(1); } - + req->data = ccb; + req->length = csio->dxfer_len; + req->flags |= TW_OSLI_REQ_FLAGS_CCB; req->deadline = tw_osl_get_local_time() + (ccb_h->timeout / 1000); - /* * twa_map_load_data_callback will fill in the SGL, * and submit the I/O. diff --git a/sys/dev/twa/tw_osl_freebsd.c b/sys/dev/twa/tw_osl_freebsd.c index aedcfe8f8cd..2956df6f0fb 100644 --- a/sys/dev/twa/tw_osl_freebsd.c +++ b/sys/dev/twa/tw_osl_freebsd.c @@ -1473,6 +1473,10 @@ tw_osli_map_request(struct tw_osli_req_context *req) twa_map_load_data_callback, req, BUS_DMA_WAITOK); mtx_unlock_spin(sc->io_lock); + } else if (req->flags & TW_OSLI_REQ_FLAGS_CCB) { + error = bus_dmamap_load_ccb(sc->dma_tag, req->dma_map, + req->data, twa_map_load_data_callback, req, + BUS_DMA_WAITOK); } else { /* * There's only one CAM I/O thread running at a time. diff --git a/sys/dev/tws/tws.h b/sys/dev/tws/tws.h index 5242d9dcca4..e84047d209e 100644 --- a/sys/dev/tws/tws.h +++ b/sys/dev/tws/tws.h @@ -137,6 +137,7 @@ enum tws_req_flags { TWS_DIR_IN = 0x2, TWS_DIR_OUT = 0x4, TWS_DIR_NONE = 0x8, + TWS_DATA_CCB = 0x16, }; enum tws_intrs { diff --git a/sys/dev/tws/tws_cam.c b/sys/dev/tws/tws_cam.c index 18ac2be1c29..657777a68b2 100644 --- a/sys/dev/tws/tws_cam.c +++ b/sys/dev/tws/tws_cam.c @@ -739,39 +739,8 @@ tws_execute_scsi(struct tws_softc *sc, union ccb *ccb) else bcopy(csio->cdb_io.cdb_bytes, cmd_pkt->cmd.pkt_a.cdb, csio->cdb_len); - if (!(ccb_h->flags & CAM_DATA_PHYS)) { - /* Virtual data addresses. Need to convert them... */ - if (!(ccb_h->flags & CAM_SCATTER_VALID)) { - if (csio->dxfer_len > TWS_MAX_IO_SIZE) { - TWS_TRACE(sc, "I/O is big", csio->dxfer_len, 0); - tws_release_request(req); - ccb_h->status = CAM_REQ_TOO_BIG; - xpt_done(ccb); - return(0); - } - - req->length = csio->dxfer_len; - if (req->length) { - req->data = csio->data_ptr; - /* there is 1 sgl_entrie */ - /* cmd_pkt->cmd.pkt_a.lun_h4__sgl_entries |= 1; */ - } - } else { - TWS_TRACE_DEBUG(sc, "got sglist", ccb_h->target_id, ccb_h->target_lun); - tws_release_request(req); - ccb_h->status = CAM_REQ_INVALID; - xpt_done(ccb); - return(0); - } - } else { - /* Data addresses are physical. */ - TWS_TRACE_DEBUG(sc, "Phy data addr", ccb_h->target_id, ccb_h->target_lun); - tws_release_request(req); - ccb_h->status = CAM_REQ_INVALID; - ccb_h->status &= ~CAM_SIM_QUEUED; - xpt_done(ccb); - return(0); - } + req->data = ccb; + req->flags |= TWS_DATA_CCB; /* save ccb ptr */ req->ccb_ptr = ccb; /* @@ -961,10 +930,16 @@ tws_map_request(struct tws_softc *sc, struct tws_request *req) * Map the data buffer into bus space and build the SG list. */ mtx_lock(&sc->io_lock); - error = bus_dmamap_load(sc->data_tag, req->dma_map, - req->data, req->length, - tws_dmamap_data_load_cbfn, req, - my_flags); + if (req->flags & TWS_DATA_CCB) + error = bus_dmamap_load_ccb(sc->data_tag, req->dma_map, + req->data, + tws_dmamap_data_load_cbfn, req, + my_flags); + else + error = bus_dmamap_load(sc->data_tag, req->dma_map, + req->data, req->length, + tws_dmamap_data_load_cbfn, req, + my_flags); mtx_unlock(&sc->io_lock); if (error == EINPROGRESS) { diff --git a/sys/dev/virtio/scsi/virtio_scsi.c b/sys/dev/virtio/scsi/virtio_scsi.c index 86684ba9779..7ebce0985e1 100644 --- a/sys/dev/virtio/scsi/virtio_scsi.c +++ b/sys/dev/virtio/scsi/virtio_scsi.c @@ -961,28 +961,31 @@ vtscsi_sg_append_scsi_buf(struct vtscsi_softc *sc, struct sglist *sg, ccbh = &csio->ccb_h; error = 0; - if ((ccbh->flags & CAM_SCATTER_VALID) == 0) { - - if ((ccbh->flags & CAM_DATA_PHYS) == 0) - error = sglist_append(sg, - csio->data_ptr, csio->dxfer_len); - else - error = sglist_append_phys(sg, - (vm_paddr_t)(vm_offset_t) csio->data_ptr, - csio->dxfer_len); - } else { - + switch ((ccbh->flags & CAM_DATA_MASK)) { + case CAM_DATA_VADDR: + error = sglist_append(sg, csio->data_ptr, csio->dxfer_len); + break; + case CAM_DATA_PADDR: + error = sglist_append_phys(sg, + (vm_paddr_t)(vm_offset_t) csio->data_ptr, csio->dxfer_len); + break; + case CAM_DATA_SG: for (i = 0; i < csio->sglist_cnt && error == 0; i++) { dseg = &((struct bus_dma_segment *)csio->data_ptr)[i]; - - if ((ccbh->flags & CAM_SG_LIST_PHYS) == 0) - error = sglist_append(sg, - (void *)(vm_offset_t) dseg->ds_addr, - dseg->ds_len); - else - error = sglist_append_phys(sg, - (vm_paddr_t) dseg->ds_addr, dseg->ds_len); + error = sglist_append(sg, + (void *)(vm_offset_t) dseg->ds_addr, dseg->ds_len); } + break; + case CAM_DATA_SG_PADDR: + for (i = 0; i < csio->sglist_cnt && error == 0; i++) { + dseg = &((struct bus_dma_segment *)csio->data_ptr)[i]; + error = sglist_append_phys(sg, + (vm_paddr_t) dseg->ds_addr, dseg->ds_len); + } + break; + default: + error = EINVAL; + break; } return (error); diff --git a/sys/dev/wds/wd7000.c b/sys/dev/wds/wd7000.c index 3dcd735e135..194d39e96e6 100644 --- a/sys/dev/wds/wd7000.c +++ b/sys/dev/wds/wd7000.c @@ -1066,7 +1066,7 @@ wds_scsi_io(struct cam_sim * sim, struct ccb_scsiio * csio) xpt_done((union ccb *) csio); return; } - if (ccb_h->flags & (CAM_CDB_PHYS | CAM_SCATTER_VALID | CAM_DATA_PHYS)) { + if ((ccb_h->flags & CAM_DATA_MASK) != CAM_DATA_VADDR) { /* don't support these */ ccb_h->status = CAM_REQ_INVALID; xpt_done((union ccb *) csio); diff --git a/sys/ia64/ia64/busdma_machdep.c b/sys/ia64/ia64/busdma_machdep.c index eaaf03f54c9..770f29f0176 100644 --- a/sys/ia64/ia64/busdma_machdep.c +++ b/sys/ia64/ia64/busdma_machdep.c @@ -31,14 +31,14 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include #include +#include #include -#include #include +#include #include #include @@ -73,6 +73,7 @@ struct bounce_page { vm_offset_t vaddr; /* kva of bounce buffer */ bus_addr_t busaddr; /* Physical address */ vm_offset_t datavaddr; /* kva of client data */ + bus_addr_t dataaddr; /* client physical address */ bus_size_t datacount; /* client data count */ STAILQ_ENTRY(bounce_page) links; }; @@ -107,8 +108,7 @@ struct bus_dmamap { int pagesneeded; int pagesreserved; bus_dma_tag_t dmat; - void *buf; /* unmapped buffer pointer */ - bus_size_t buflen; /* unmapped buffer length */ + struct memdesc mem; bus_dmamap_callback_t *callback; void *callback_arg; STAILQ_ENTRY(bus_dmamap) links; @@ -123,7 +123,7 @@ static int alloc_bounce_pages(bus_dma_tag_t dmat, u_int numpages); static int reserve_bounce_pages(bus_dma_tag_t dmat, bus_dmamap_t map, int commit); static bus_addr_t add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, - vm_offset_t vaddr, bus_size_t size); + vm_offset_t vaddr, bus_addr_t addr, bus_size_t size); static void free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage); static __inline int run_filter(bus_dma_tag_t dmat, bus_addr_t paddr, bus_size_t len); @@ -480,37 +480,44 @@ bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) } } -/* - * Utility function to load a linear buffer. lastaddrp holds state - * between invocations (for multiple-buffer loads). segp contains - * the starting segment on entrace, and the ending segment on exit. - * first indicates if this is the first invocation of this function. - */ -static int -_bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, - bus_size_t buflen, struct thread *td, int flags, bus_addr_t *lastaddrp, - bus_dma_segment_t *segs, int *segp, int first) +static void +_bus_dmamap_count_phys(bus_dma_tag_t dmat, bus_dmamap_t map, vm_paddr_t buf, + bus_size_t buflen, int flags) { + bus_addr_t curaddr; bus_size_t sgsize; - bus_addr_t curaddr, lastaddr, baddr, bmask; - vm_offset_t vaddr; - bus_addr_t paddr; - int seg; - pmap_t pmap; - - if (map == NULL) - map = &nobounce_dmamap; - - if (td != NULL) - pmap = vmspace_pmap(td->td_proc->p_vmspace); - else - pmap = NULL; if ((dmat->lowaddr < paddr_max || dmat->boundary > 0 || dmat->alignment > 1) && map != &nobounce_dmamap && map->pagesneeded == 0) { - vm_offset_t vendaddr; + /* + * Count the number of bounce pages + * needed in order to complete this transfer + */ + curaddr = buf; + while (buflen != 0) { + sgsize = MIN(buflen, dmat->maxsegsz); + if (run_filter(dmat, curaddr, 0) != 0) { + sgsize = MIN(sgsize, PAGE_SIZE); + map->pagesneeded++; + } + curaddr += sgsize; + buflen -= sgsize; + } + } +} +static void +_bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map, pmap_t pmap, + void *buf, bus_size_t buflen, int flags) +{ + vm_offset_t vaddr; + vm_offset_t vendaddr; + bus_addr_t paddr; + + if ((dmat->lowaddr < paddr_max || dmat->boundary > 0 || + dmat->alignment > 1) && map != &nobounce_dmamap && + map->pagesneeded == 0) { /* * Count the number of bounce pages * needed in order to complete this transfer @@ -519,52 +526,177 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, vendaddr = (vm_offset_t)buf + buflen; while (vaddr < vendaddr) { - if (pmap != NULL) - paddr = pmap_extract(pmap, vaddr); - else + if (pmap == kernel_pmap) paddr = pmap_kextract(vaddr); + else + paddr = pmap_extract(pmap, vaddr); if (run_filter(dmat, paddr, 0) != 0) map->pagesneeded++; vaddr += PAGE_SIZE; } } +} + +static int +_bus_dmamap_reserve_pages(bus_dma_tag_t dmat, bus_dmamap_t map, int flags) +{ + + /* Reserve Necessary Bounce Pages */ + mtx_lock(&bounce_lock); + if (flags & BUS_DMA_NOWAIT) { + if (reserve_bounce_pages(dmat, map, 0) != 0) { + mtx_unlock(&bounce_lock); + return (ENOMEM); + } + } else { + if (reserve_bounce_pages(dmat, map, 1) != 0) { + /* Queue us for resources */ + STAILQ_INSERT_TAIL(&bounce_map_waitinglist, + map, links); + mtx_unlock(&bounce_lock); + return (EINPROGRESS); + } + } + mtx_unlock(&bounce_lock); + + return (0); +} + +/* + * Add a single contiguous physical range to the segment list. + */ +static int +_bus_dmamap_addseg(bus_dma_tag_t dmat, bus_dmamap_t map, bus_addr_t curaddr, + bus_size_t sgsize, bus_dma_segment_t *segs, int *segp) +{ + bus_addr_t baddr, bmask; + int seg; + + /* + * Make sure we don't cross any boundaries. + */ + bmask = ~(dmat->boundary - 1); + if (dmat->boundary > 0) { + baddr = (curaddr + dmat->boundary) & bmask; + if (sgsize > (baddr - curaddr)) + sgsize = (baddr - curaddr); + } + + /* + * Insert chunk into a segment, coalescing with + * previous segment if possible. + */ + seg = *segp; + if (seg == -1) { + seg = 0; + segs[seg].ds_addr = curaddr; + segs[seg].ds_len = sgsize; + } else { + if (curaddr == segs[seg].ds_addr + segs[seg].ds_len && + (segs[seg].ds_len + sgsize) <= dmat->maxsegsz && + (dmat->boundary == 0 || + (segs[seg].ds_addr & bmask) == (curaddr & bmask))) + segs[seg].ds_len += sgsize; + else { + if (++seg >= dmat->nsegments) + return (0); + segs[seg].ds_addr = curaddr; + segs[seg].ds_len = sgsize; + } + } + *segp = seg; + return (sgsize); +} + +/* + * Utility function to load a physical buffer. segp contains + * the starting segment on entrace, and the ending segment on exit. + */ +int +_bus_dmamap_load_phys(bus_dma_tag_t dmat, bus_dmamap_t map, + vm_paddr_t buf, bus_size_t buflen, int flags, bus_dma_segment_t *segs, + int *segp) +{ + bus_addr_t curaddr; + bus_size_t sgsize; + int error; + + if (map == NULL) + map = &nobounce_dmamap; + + if (segs == NULL) + segs = dmat->segments; + + if (map != &nobounce_dmamap) { + _bus_dmamap_count_phys(dmat, map, buf, buflen, flags); + if (map->pagesneeded != 0) { + error = _bus_dmamap_reserve_pages(dmat, map, flags); + if (error) + return (error); + } + } + + while (buflen > 0) { + curaddr = buf; + sgsize = MIN(buflen, dmat->maxsegsz); + if (map->pagesneeded != 0 && + run_filter(dmat, curaddr, sgsize)) { + sgsize = MIN(sgsize, PAGE_SIZE); + curaddr = add_bounce_page(dmat, map, 0, curaddr, + sgsize); + } + sgsize = _bus_dmamap_addseg(dmat, map, curaddr, sgsize, segs, + segp); + if (sgsize == 0) + break; + buf += sgsize; + buflen -= sgsize; + } + + /* + * Did we fit? + */ + return (buflen != 0 ? EFBIG : 0); /* XXX better return value here? */ +} +/* + * Utility function to load a linear buffer. segp contains + * the starting segment on entrace, and the ending segment on exit. + */ +int +_bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, + bus_size_t buflen, pmap_t pmap, int flags, + bus_dma_segment_t *segs, int *segp) +{ + bus_size_t sgsize; + bus_addr_t curaddr; + vm_offset_t vaddr; + int error; + + if (map == NULL) + map = &nobounce_dmamap; + + if (segs == NULL) + segs = dmat->segments; + + if (map != &nobounce_dmamap) { + _bus_dmamap_count_pages(dmat, map, pmap, buf, buflen, flags); + if (map->pagesneeded != 0) { + error = _bus_dmamap_reserve_pages(dmat, map, flags); + if (error) + return (error); + } + } vaddr = (vm_offset_t)buf; - /* Reserve Necessary Bounce Pages */ - if (map->pagesneeded != 0) { - mtx_lock(&bounce_lock); - if (flags & BUS_DMA_NOWAIT) { - if (reserve_bounce_pages(dmat, map, 0) != 0) { - mtx_unlock(&bounce_lock); - return (ENOMEM); - } - } else { - if (reserve_bounce_pages(dmat, map, 1) != 0) { - /* Queue us for resources */ - map->dmat = dmat; - map->buf = buf; - map->buflen = buflen; - STAILQ_INSERT_TAIL(&bounce_map_waitinglist, - map, links); - mtx_unlock(&bounce_lock); - return (EINPROGRESS); - } - } - mtx_unlock(&bounce_lock); - } - - lastaddr = *lastaddrp; - bmask = ~(dmat->boundary - 1); - - for (seg = *segp; buflen > 0 ; ) { + while (buflen > 0) { /* * Get the physical address for this segment. */ - if (pmap) - curaddr = pmap_extract(pmap, vaddr); - else + if (pmap == kernel_pmap) curaddr = pmap_kextract(vaddr); + else + curaddr = pmap_extract(pmap, vaddr); /* * Compute the segment size, and adjust counts. @@ -575,211 +707,46 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, if (buflen < sgsize) sgsize = buflen; - /* - * Make sure we don't cross any boundaries. - */ - if (dmat->boundary > 0) { - baddr = (curaddr + dmat->boundary) & bmask; - if (sgsize > (baddr - curaddr)) - sgsize = (baddr - curaddr); - } - if (map->pagesneeded != 0 && run_filter(dmat, curaddr, sgsize)) - curaddr = add_bounce_page(dmat, map, vaddr, sgsize); + curaddr = add_bounce_page(dmat, map, vaddr, curaddr, + sgsize); - /* - * Insert chunk into a segment, coalescing with - * previous segment if possible. - */ - if (first) { - segs[seg].ds_addr = curaddr; - segs[seg].ds_len = sgsize; - first = 0; - } else { - if (curaddr == lastaddr && - (segs[seg].ds_len + sgsize) <= dmat->maxsegsz && - (dmat->boundary == 0 || - (segs[seg].ds_addr & bmask) == (curaddr & bmask))) - segs[seg].ds_len += sgsize; - else { - if (++seg >= dmat->nsegments) - break; - segs[seg].ds_addr = curaddr; - segs[seg].ds_len = sgsize; - } - } + sgsize = _bus_dmamap_addseg(dmat, map, curaddr, sgsize, segs, + segp); + if (sgsize == 0) + break; - lastaddr = curaddr + sgsize; vaddr += sgsize; buflen -= sgsize; } - *segp = seg; - *lastaddrp = lastaddr; - /* * Did we fit? */ return (buflen != 0 ? EFBIG : 0); /* XXX better return value here? */ } -/* - * Map the buffer buf into bus space using the dmamap map. - */ -int -bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, - bus_size_t buflen, bus_dmamap_callback_t *callback, void *callback_arg, - int flags) -{ - bus_addr_t lastaddr = 0; - int error, nsegs = 0; +void +__bus_dmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map, + struct memdesc *mem, bus_dmamap_callback_t *callback, void *callback_arg) +{ if (map != NULL) { - flags |= BUS_DMA_WAITOK; + map->dmat = dmat; + map->mem = *mem; map->callback = callback; map->callback_arg = callback_arg; } - - error = _bus_dmamap_load_buffer(dmat, map, buf, buflen, NULL, flags, - &lastaddr, dmat->segments, &nsegs, 1); - - if (error == EINPROGRESS) - return (error); - - if (error) - (*callback)(callback_arg, dmat->segments, 0, error); - else - (*callback)(callback_arg, dmat->segments, nsegs + 1, 0); - - return (0); } -/* - * Like _bus_dmamap_load(), but for mbufs. - */ -int -bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m0, - bus_dmamap_callback2_t *callback, void *callback_arg, int flags) +bus_dma_segment_t * +_bus_dmamap_complete(bus_dma_tag_t dmat, bus_dmamap_t map, + bus_dma_segment_t *segs, int nsegs, int error) { - int nsegs, error; - M_ASSERTPKTHDR(m0); - - flags |= BUS_DMA_NOWAIT; - nsegs = 0; - error = 0; - if (m0->m_pkthdr.len <= dmat->maxsize) { - int first = 1; - bus_addr_t lastaddr = 0; - struct mbuf *m; - - for (m = m0; m != NULL && error == 0; m = m->m_next) { - if (m->m_len > 0) { - error = _bus_dmamap_load_buffer(dmat, map, - m->m_data, m->m_len, NULL, flags, - &lastaddr, dmat->segments, &nsegs, first); - first = 0; - } - } - } else { - error = EINVAL; - } - - if (error) { - /* force "no valid mappings" in callback */ - (*callback)(callback_arg, dmat->segments, 0, 0, error); - } else { - (*callback)(callback_arg, dmat->segments, nsegs + 1, - m0->m_pkthdr.len, error); - } - return (error); -} - -int -bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m0, - bus_dma_segment_t *segs, int *nsegs, int flags) -{ - int error; - - M_ASSERTPKTHDR(m0); - - flags |= BUS_DMA_NOWAIT; - *nsegs = 0; - error = 0; - if (m0->m_pkthdr.len <= dmat->maxsize) { - int first = 1; - bus_addr_t lastaddr = 0; - struct mbuf *m; - - for (m = m0; m != NULL && error == 0; m = m->m_next) { - if (m->m_len > 0) { - error = _bus_dmamap_load_buffer(dmat, map, - m->m_data, m->m_len, NULL, flags, - &lastaddr, segs, nsegs, first); - first = 0; - } - } - ++*nsegs; - } else { - error = EINVAL; - } - - return (error); -} - -/* - * Like _bus_dmamap_load(), but for uios. - */ -int -bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, struct uio *uio, - bus_dmamap_callback2_t *callback, void *callback_arg, int flags) -{ - bus_addr_t lastaddr; - int nsegs, error, first, i; - bus_size_t resid; - struct iovec *iov; - struct thread *td = NULL; - - flags |= BUS_DMA_NOWAIT; - resid = uio->uio_resid; - iov = uio->uio_iov; - - if (uio->uio_segflg == UIO_USERSPACE) { - td = uio->uio_td; - KASSERT(td != NULL, - ("bus_dmamap_load_uio: USERSPACE but no proc")); - } - - nsegs = 0; - error = 0; - first = 1; - for (i = 0; i < uio->uio_iovcnt && resid != 0 && !error; i++) { - /* - * Now at the first iovec to load. Load each iovec - * until we have exhausted the residual count. - */ - bus_size_t minlen = - resid < iov[i].iov_len ? resid : iov[i].iov_len; - caddr_t addr = (caddr_t) iov[i].iov_base; - - if (minlen > 0) { - error = _bus_dmamap_load_buffer(dmat, map, addr, - minlen, td, flags, &lastaddr, dmat->segments, - &nsegs, first); - first = 0; - - resid -= minlen; - } - } - - if (error) { - /* force "no valid mappings" in callback */ - (*callback)(callback_arg, dmat->segments, 0, 0, error); - } else { - (*callback)(callback_arg, dmat->segments, nsegs + 1, - uio->uio_resid, error); - } - return (error); + if (segs == NULL) + segs = dmat->segments; + return (segs); } /* @@ -810,8 +777,14 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op) if (op & BUS_DMASYNC_PREWRITE) { while (bpage != NULL) { - bcopy((void *)bpage->datavaddr, - (void *)bpage->vaddr, bpage->datacount); + if (bpage->datavaddr != 0) + bcopy((void *)bpage->datavaddr, + (void *)bpage->vaddr, + bpage->datacount); + else + physcopyout(bpage->dataaddr, + (void *)bpage->vaddr, + bpage->datacount); bpage = STAILQ_NEXT(bpage, links); } total_bounced++; @@ -819,8 +792,14 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op) if (op & BUS_DMASYNC_POSTREAD) { while (bpage != NULL) { - bcopy((void *)bpage->vaddr, - (void *)bpage->datavaddr, bpage->datacount); + if (bpage->datavaddr != 0) + bcopy((void *)bpage->vaddr, + (void *)bpage->datavaddr, + bpage->datacount); + else + physcopyin((void *)bpage->vaddr, + bpage->dataaddr, + bpage->datacount); bpage = STAILQ_NEXT(bpage, links); } total_bounced++; @@ -893,7 +872,7 @@ reserve_bounce_pages(bus_dma_tag_t dmat, bus_dmamap_t map, int commit) static bus_addr_t add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, vm_offset_t vaddr, - bus_size_t size) + bus_addr_t addr, bus_size_t size) { struct bounce_page *bpage; @@ -924,6 +903,7 @@ add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, vm_offset_t vaddr, bpage->busaddr |= vaddr & PAGE_MASK; } bpage->datavaddr = vaddr; + bpage->dataaddr = addr; bpage->datacount = size; STAILQ_INSERT_TAIL(&(map->bpages), bpage, links); return (bpage->busaddr); @@ -975,8 +955,8 @@ busdma_swi(void) mtx_unlock(&bounce_lock); dmat = map->dmat; (dmat->lockfunc)(dmat->lockfuncarg, BUS_DMA_LOCK); - bus_dmamap_load(map->dmat, map, map->buf, map->buflen, - map->callback, map->callback_arg, /*flags*/0); + bus_dmamap_load_mem(map->dmat, map, &map->mem, map->callback, + map->callback_arg, BUS_DMA_WAITOK); (dmat->lockfunc)(dmat->lockfuncarg, BUS_DMA_UNLOCK); mtx_lock(&bounce_lock); } diff --git a/sys/kern/subr_bus_dma.c b/sys/kern/subr_bus_dma.c new file mode 100644 index 00000000000..773d01ae2d0 --- /dev/null +++ b/sys/kern/subr_bus_dma.c @@ -0,0 +1,460 @@ +/*- + * Copyright (c) 2012 EMC Corp. + * All rights reserved. + * + * Copyright (c) 1997, 1998 Justin T. Gibbs. + * 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 +__FBSDID("$FreeBSD$"); + +#include "opt_bus.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include + +/* + * Load a list of virtual addresses. + */ +static int +_bus_dmamap_load_vlist(bus_dma_tag_t dmat, bus_dmamap_t map, + bus_dma_segment_t *list, int sglist_cnt, struct pmap *pmap, int *nsegs, + int flags) +{ + int error; + + error = 0; + for (; sglist_cnt > 0; sglist_cnt--, list++) { + error = _bus_dmamap_load_buffer(dmat, map, + (void *)list->ds_addr, list->ds_len, pmap, flags, NULL, + nsegs); + if (error) + break; + } + return (error); +} + +/* + * Load a list of physical addresses. + */ +static int +_bus_dmamap_load_plist(bus_dma_tag_t dmat, bus_dmamap_t map, + bus_dma_segment_t *list, int sglist_cnt, int *nsegs, int flags) +{ + int error; + + error = 0; + for (; sglist_cnt > 0; sglist_cnt--, list++) { + error = _bus_dmamap_load_phys(dmat, map, + (vm_paddr_t)list->ds_addr, list->ds_len, flags, NULL, + nsegs); + if (error) + break; + } + return (error); +} + +/* + * Load an mbuf chain. + */ +static int +_bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map, + struct mbuf *m0, bus_dma_segment_t *segs, int *nsegs, int flags) +{ + struct mbuf *m; + int error; + + M_ASSERTPKTHDR(m0); + + error = 0; + for (m = m0; m != NULL && error == 0; m = m->m_next) { + if (m->m_len > 0) { + error = _bus_dmamap_load_buffer(dmat, map, m->m_data, + m->m_len, kernel_pmap, flags | BUS_DMA_LOAD_MBUF, + segs, nsegs); + } + } + CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", + __func__, dmat, flags, error, *nsegs); + return (error); +} + +/* + * Load from block io. + */ +static int +_bus_dmamap_load_bio(bus_dma_tag_t dmat, bus_dmamap_t map, struct bio *bio, + int *nsegs, int flags) +{ + int error; + + error = _bus_dmamap_load_buffer(dmat, map, bio->bio_data, + bio->bio_bcount, kernel_pmap, flags, NULL, nsegs); + + return (error); +} + +/* + * Load a cam control block. + */ +static int +_bus_dmamap_load_ccb(bus_dma_tag_t dmat, bus_dmamap_t map, union ccb *ccb, + int *nsegs, int flags) +{ + struct ccb_ataio *ataio; + struct ccb_scsiio *csio; + struct ccb_hdr *ccb_h; + void *data_ptr; + int error; + uint32_t dxfer_len; + uint16_t sglist_cnt; + + error = 0; + ccb_h = &ccb->ccb_h; + switch (ccb_h->func_code) { + case XPT_SCSI_IO: + csio = &ccb->csio; + data_ptr = csio->data_ptr; + dxfer_len = csio->dxfer_len; + sglist_cnt = csio->sglist_cnt; + break; + case XPT_ATA_IO: + ataio = &ccb->ataio; + data_ptr = ataio->data_ptr; + dxfer_len = ataio->dxfer_len; + sglist_cnt = 0; + break; + default: + panic("_bus_dmamap_load_ccb: Unsupported func code %d", + ccb_h->func_code); + } + + switch ((ccb_h->flags & CAM_DATA_MASK)) { + case CAM_DATA_VADDR: + error = _bus_dmamap_load_buffer(dmat, map, data_ptr, dxfer_len, + kernel_pmap, flags, NULL, nsegs); + break; + case CAM_DATA_PADDR: + error = _bus_dmamap_load_phys(dmat, map, + (vm_paddr_t)(uintptr_t)data_ptr, dxfer_len, flags, NULL, + nsegs); + break; + case CAM_DATA_SG: + error = _bus_dmamap_load_vlist(dmat, map, + (bus_dma_segment_t *)data_ptr, sglist_cnt, kernel_pmap, + nsegs, flags); + break; + case CAM_DATA_SG_PADDR: + error = _bus_dmamap_load_plist(dmat, map, + (bus_dma_segment_t *)data_ptr, sglist_cnt, nsegs, flags); + break; + case CAM_DATA_BIO: + error = _bus_dmamap_load_bio(dmat, map, (struct bio *)data_ptr, + nsegs, flags); + break; + default: + panic("_bus_dmamap_load_ccb: flags 0x%X unimplemented", + ccb_h->flags); + } + return (error); +} + +/* + * Load a uio. + */ +static int +_bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, struct uio *uio, + int *nsegs, int flags) +{ + bus_size_t resid; + bus_size_t minlen; + struct iovec *iov; + pmap_t pmap; + caddr_t addr; + int error, i; + + if (uio->uio_segflg == UIO_USERSPACE) { + KASSERT(uio->uio_td != NULL, + ("bus_dmamap_load_uio: USERSPACE but no proc")); + pmap = vmspace_pmap(uio->uio_td->td_proc->p_vmspace); + } else + pmap = kernel_pmap; + resid = uio->uio_resid; + iov = uio->uio_iov; + error = 0; + + for (i = 0; i < uio->uio_iovcnt && resid != 0 && !error; i++) { + /* + * Now at the first iovec to load. Load each iovec + * until we have exhausted the residual count. + */ + + addr = (caddr_t) iov[i].iov_base; + minlen = resid < iov[i].iov_len ? resid : iov[i].iov_len; + if (minlen > 0) { + error = _bus_dmamap_load_buffer(dmat, map, addr, + minlen, pmap, flags, NULL, nsegs); + resid -= minlen; + } + } + + return (error); +} + +/* + * Map the buffer buf into bus space using the dmamap map. + */ +int +bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, + bus_size_t buflen, bus_dmamap_callback_t *callback, + void *callback_arg, int flags) +{ + bus_dma_segment_t *segs; + struct memdesc mem; + int error; + int nsegs; + + if ((flags & BUS_DMA_NOWAIT) == 0) { + mem = memdesc_vaddr(buf, buflen); + _bus_dmamap_waitok(dmat, map, &mem, callback, callback_arg); + } + + nsegs = -1; + error = _bus_dmamap_load_buffer(dmat, map, buf, buflen, kernel_pmap, + flags, NULL, &nsegs); + nsegs++; + + CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", + __func__, dmat, flags, error, nsegs + 1); + + if (error == EINPROGRESS) + return (error); + + segs = _bus_dmamap_complete(dmat, map, NULL, nsegs, error); + if (error) + (*callback)(callback_arg, segs, 0, error); + else + (*callback)(callback_arg, segs, nsegs, 0); + + /* + * Return ENOMEM to the caller so that it can pass it up the stack. + * This error only happens when NOWAIT is set, so deferal is disabled. + */ + if (error == ENOMEM) + return (error); + + return (0); +} + +int +bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m0, + bus_dmamap_callback2_t *callback, void *callback_arg, int flags) +{ + bus_dma_segment_t *segs; + int nsegs, error; + + flags |= BUS_DMA_NOWAIT; + nsegs = -1; + error = _bus_dmamap_load_mbuf_sg(dmat, map, m0, NULL, &nsegs, flags); + ++nsegs; + + segs = _bus_dmamap_complete(dmat, map, NULL, nsegs, error); + if (error) + (*callback)(callback_arg, segs, 0, 0, error); + else + (*callback)(callback_arg, segs, nsegs, m0->m_pkthdr.len, error); + + CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", + __func__, dmat, flags, error, nsegs); + return (error); +} + +int +bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m0, + bus_dma_segment_t *segs, int *nsegs, int flags) +{ + int error; + + flags |= BUS_DMA_NOWAIT; + *nsegs = -1; + error = _bus_dmamap_load_mbuf_sg(dmat, map, m0, segs, nsegs, flags); + ++*nsegs; + _bus_dmamap_complete(dmat, map, segs, *nsegs, error); + return (error); +} + +int +bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, struct uio *uio, + bus_dmamap_callback2_t *callback, void *callback_arg, int flags) +{ + bus_dma_segment_t *segs; + int nsegs, error; + + flags |= BUS_DMA_NOWAIT; + nsegs = -1; + error = _bus_dmamap_load_uio(dmat, map, uio, &nsegs, flags); + nsegs++; + + segs = _bus_dmamap_complete(dmat, map, NULL, nsegs, error); + if (error) + (*callback)(callback_arg, segs, 0, 0, error); + else + (*callback)(callback_arg, segs, nsegs, uio->uio_resid, error); + + CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", + __func__, dmat, dmat, error, nsegs + 1); + return (error); +} + +int +bus_dmamap_load_ccb(bus_dma_tag_t dmat, bus_dmamap_t map, union ccb *ccb, + bus_dmamap_callback_t *callback, void *callback_arg, + int flags) +{ + bus_dma_segment_t *segs; + struct ccb_hdr *ccb_h; + struct memdesc mem; + int error; + int nsegs; + + ccb_h = &ccb->ccb_h; + if ((ccb_h->flags & CAM_DIR_MASK) == CAM_DIR_NONE) { + callback(callback_arg, NULL, 0, 0); + return (0); + } + if ((flags & BUS_DMA_NOWAIT) == 0) { + mem = memdesc_ccb(ccb); + _bus_dmamap_waitok(dmat, map, &mem, callback, callback_arg); + } + nsegs = -1; + error = _bus_dmamap_load_ccb(dmat, map, ccb, &nsegs, flags); + nsegs++; + if (error == EINPROGRESS) + return (error); + + segs = _bus_dmamap_complete(dmat, map, NULL, nsegs, error); + if (error) + (*callback)(callback_arg, segs, 0, error); + else + (*callback)(callback_arg, segs, nsegs, error); + /* + * Return ENOMEM to the caller so that it can pass it up the stack. + * This error only happens when NOWAIT is set, so deferal is disabled. + */ + if (error == ENOMEM) + return (error); + + return (0); +} + +int +bus_dmamap_load_mem(bus_dma_tag_t dmat, bus_dmamap_t map, + struct memdesc *mem, bus_dmamap_callback_t *callback, + void *callback_arg, int flags) +{ + bus_dma_segment_t *segs; + int error; + int nsegs; + + if ((flags & BUS_DMA_NOWAIT) == 0) + _bus_dmamap_waitok(dmat, map, mem, callback, callback_arg); + + nsegs = -1; + error = 0; + switch (mem->md_type) { + case MEMDESC_VADDR: + error = _bus_dmamap_load_buffer(dmat, map, mem->u.md_vaddr, + mem->md_opaque, kernel_pmap, flags, NULL, &nsegs); + break; + case MEMDESC_PADDR: + error = _bus_dmamap_load_phys(dmat, map, mem->u.md_paddr, + mem->md_opaque, flags, NULL, &nsegs); + break; + case MEMDESC_VLIST: + error = _bus_dmamap_load_vlist(dmat, map, mem->u.md_list, + mem->md_opaque, kernel_pmap, &nsegs, flags); + break; + case MEMDESC_PLIST: + error = _bus_dmamap_load_plist(dmat, map, mem->u.md_list, + mem->md_opaque, &nsegs, flags); + break; + case MEMDESC_BIO: + error = _bus_dmamap_load_bio(dmat, map, mem->u.md_bio, + &nsegs, flags); + break; + case MEMDESC_UIO: + error = _bus_dmamap_load_uio(dmat, map, mem->u.md_uio, + &nsegs, flags); + break; + case MEMDESC_MBUF: + error = _bus_dmamap_load_mbuf_sg(dmat, map, mem->u.md_mbuf, + NULL, &nsegs, flags); + break; + case MEMDESC_CCB: + error = _bus_dmamap_load_ccb(dmat, map, mem->u.md_ccb, &nsegs, + flags); + break; + } + nsegs++; + + CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", + __func__, dmat, flags, error, nsegs + 1); + + if (error == EINPROGRESS) + return (error); + + segs = _bus_dmamap_complete(dmat, map, NULL, nsegs, error); + if (error) + (*callback)(callback_arg, segs, 0, error); + else + (*callback)(callback_arg, segs, nsegs, 0); + + /* + * Return ENOMEM to the caller so that it can pass it up the stack. + * This error only happens when NOWAIT is set, so deferal is disabled. + */ + if (error == ENOMEM) + return (error); + + return (0); +} diff --git a/sys/kern/subr_uio.c b/sys/kern/subr_uio.c index 7b59348750e..2b4739523d9 100644 --- a/sys/kern/subr_uio.c +++ b/sys/kern/subr_uio.c @@ -152,6 +152,52 @@ copyout_nofault(const void *kaddr, void *udaddr, size_t len) return (error); } +#define PHYS_PAGE_COUNT(len) (howmany(len, PAGE_SIZE) + 1) + +int +physcopyin(void *src, vm_paddr_t dst, size_t len) +{ + vm_page_t m[PHYS_PAGE_COUNT(len)]; + struct iovec iov[1]; + struct uio uio; + int i; + + iov[0].iov_base = src; + iov[0].iov_len = len; + uio.uio_iov = iov; + uio.uio_iovcnt = 1; + uio.uio_offset = 0; + uio.uio_resid = len; + uio.uio_segflg = UIO_SYSSPACE; + uio.uio_rw = UIO_WRITE; + for (i = 0; i < PHYS_PAGE_COUNT(len); i++, dst += PAGE_SIZE) + m[i] = PHYS_TO_VM_PAGE(dst); + return (uiomove_fromphys(m, dst & PAGE_MASK, len, &uio)); +} + +int +physcopyout(vm_paddr_t src, void *dst, size_t len) +{ + vm_page_t m[PHYS_PAGE_COUNT(len)]; + struct iovec iov[1]; + struct uio uio; + int i; + + iov[0].iov_base = dst; + iov[0].iov_len = len; + uio.uio_iov = iov; + uio.uio_iovcnt = 1; + uio.uio_offset = 0; + uio.uio_resid = len; + uio.uio_segflg = UIO_SYSSPACE; + uio.uio_rw = UIO_READ; + for (i = 0; i < PHYS_PAGE_COUNT(len); i++, src += PAGE_SIZE) + m[i] = PHYS_TO_VM_PAGE(src); + return (uiomove_fromphys(m, src & PAGE_MASK, len, &uio)); +} + +#undef PHYS_PAGE_COUNT + int uiomove(void *cp, int n, struct uio *uio) { diff --git a/sys/mips/mips/busdma_machdep.c b/sys/mips/mips/busdma_machdep.c index 2ad118b5da7..f3275e6bec3 100644 --- a/sys/mips/mips/busdma_machdep.c +++ b/sys/mips/mips/busdma_machdep.c @@ -40,12 +40,12 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include -#include -#include #include #include #include +#include #include #include @@ -89,10 +89,17 @@ struct bounce_page { vm_offset_t vaddr_nocache; /* kva of bounce buffer uncached */ bus_addr_t busaddr; /* Physical address */ vm_offset_t datavaddr; /* kva of client data */ + bus_addr_t dataaddr; /* client physical address */ bus_size_t datacount; /* client data count */ STAILQ_ENTRY(bounce_page) links; }; +struct sync_list { + vm_offset_t vaddr; /* kva of bounce buffer */ + bus_addr_t busaddr; /* Physical address */ + bus_size_t datacount; /* client data count */ +}; + int busdma_swi_pending; struct bounce_zone { @@ -122,10 +129,6 @@ static SYSCTL_NODE(_hw, OID_AUTO, busdma, CTLFLAG_RD, 0, "Busdma parameters"); SYSCTL_INT(_hw_busdma, OID_AUTO, total_bpages, CTLFLAG_RD, &total_bpages, 0, "Total bounce pages"); -#define DMAMAP_LINEAR 0x1 -#define DMAMAP_MBUF 0x2 -#define DMAMAP_UIO 0x4 -#define DMAMAP_TYPE_MASK (DMAMAP_LINEAR|DMAMAP_MBUF|DMAMAP_UIO) #define DMAMAP_UNCACHEABLE 0x8 #define DMAMAP_ALLOCATED 0x10 #define DMAMAP_MALLOCUSED 0x20 @@ -135,16 +138,16 @@ struct bus_dmamap { int pagesneeded; int pagesreserved; bus_dma_tag_t dmat; + struct memdesc mem; int flags; - void *buffer; void *origbuffer; void *allocbuffer; TAILQ_ENTRY(bus_dmamap) freelist; - int len; STAILQ_ENTRY(bus_dmamap) links; bus_dmamap_callback_t *callback; void *callback_arg; - + int sync_count; + struct sync_list *slist; }; static STAILQ_HEAD(, bus_dmamap) bounce_map_waitinglist; @@ -166,7 +169,8 @@ static int alloc_bounce_pages(bus_dma_tag_t dmat, u_int numpages); static int reserve_bounce_pages(bus_dma_tag_t dmat, bus_dmamap_t map, int commit); static bus_addr_t add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, - vm_offset_t vaddr, bus_size_t size); + vm_offset_t vaddr, bus_addr_t addr, + bus_size_t size); static void free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage); /* Default tag, as most drivers provide no parent tag. */ @@ -214,11 +218,6 @@ SYSINIT(busdma, SI_SUB_VM, SI_ORDER_ANY, mips_dmamap_freelist_init, NULL); * Check to see if the specified page is in an allowed DMA range. */ -static __inline int -bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dma_segment_t *segs, - bus_dmamap_t map, void *buf, bus_size_t buflen, struct pmap *pmap, - int flags, vm_offset_t *lastaddrp, int *segp); - static __inline int _bus_dma_can_bounce(vm_offset_t lowaddr, vm_offset_t highaddr) { @@ -273,10 +272,14 @@ dflt_lock(void *arg, bus_dma_lock_op_t op) } static __inline bus_dmamap_t -_busdma_alloc_dmamap(void) +_busdma_alloc_dmamap(bus_dma_tag_t dmat) { + struct sync_list *slist; bus_dmamap_t map; + slist = malloc(sizeof(*slist) * dmat->nsegments, M_DEVBUF, M_NOWAIT); + if (slist == NULL) + return (NULL); mtx_lock(&busdma_mtx); map = TAILQ_FIRST(&dmamap_freelist); if (map) @@ -288,13 +291,18 @@ _busdma_alloc_dmamap(void) map->flags = DMAMAP_ALLOCATED; } else map->flags = 0; - STAILQ_INIT(&map->bpages); + if (map != NULL) { + STAILQ_INIT(&map->bpages); + map->slist = slist; + } else + free(slist, M_DEVBUF); return (map); } static __inline void _busdma_free_dmamap(bus_dmamap_t map) { + free(map->slist, M_DEVBUF); if (map->flags & DMAMAP_ALLOCATED) free(map, M_DEVBUF); else { @@ -477,7 +485,7 @@ bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp) } } - newmap = _busdma_alloc_dmamap(); + newmap = _busdma_alloc_dmamap(dmat); if (newmap == NULL) { CTR3(KTR_BUSDMA, "%s: tag %p error %d", __func__, dmat, ENOMEM); return (ENOMEM); @@ -485,6 +493,7 @@ bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp) *mapp = newmap; newmap->dmat = dmat; newmap->allocbuffer = NULL; + newmap->sync_count = 0; dmat->map_count++; /* @@ -549,7 +558,7 @@ int bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map) { - if (STAILQ_FIRST(&map->bpages) != NULL) { + if (STAILQ_FIRST(&map->bpages) != NULL || map->sync_count != 0) { CTR3(KTR_BUSDMA, "%s: tag %p error %d", __func__, dmat, EBUSY); return (EBUSY); @@ -592,7 +601,7 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, if (flags & BUS_DMA_ZERO) mflags |= M_ZERO; - newmap = _busdma_alloc_dmamap(); + newmap = _busdma_alloc_dmamap(dmat); if (newmap == NULL) { CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d", __func__, dmat, dmat->flags, ENOMEM); @@ -601,6 +610,7 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, dmat->map_count++; *mapp = newmap; newmap->dmat = dmat; + newmap->sync_count = 0; /* * If all the memory is coherent with DMA then we don't need to @@ -684,7 +694,37 @@ bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) CTR3(KTR_BUSDMA, "%s: tag %p flags 0x%x", __func__, dmat, dmat->flags); } -static int +static void +_bus_dmamap_count_phys(bus_dma_tag_t dmat, bus_dmamap_t map, vm_paddr_t buf, + bus_size_t buflen, int flags) +{ + bus_addr_t curaddr; + bus_size_t sgsize; + + if ((map->pagesneeded == 0)) { + CTR3(KTR_BUSDMA, "lowaddr= %d, boundary= %d, alignment= %d", + dmat->lowaddr, dmat->boundary, dmat->alignment); + CTR2(KTR_BUSDMA, "map= %p, pagesneeded= %d", + map, map->pagesneeded); + /* + * Count the number of bounce pages + * needed in order to complete this transfer + */ + curaddr = buf; + while (buflen != 0) { + sgsize = MIN(buflen, dmat->maxsegsz); + if (run_filter(dmat, curaddr) != 0) { + sgsize = MIN(sgsize, PAGE_SIZE); + map->pagesneeded++; + } + curaddr += sgsize; + buflen -= sgsize; + } + CTR1(KTR_BUSDMA, "pagesneeded= %d\n", map->pagesneeded); + } +} + +static void _bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map, pmap_t pmap, void *buf, bus_size_t buflen, int flags) { @@ -719,60 +759,157 @@ _bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map, pmap_t pmap, } CTR1(KTR_BUSDMA, "pagesneeded= %d\n", map->pagesneeded); } +} + +static int +_bus_dmamap_reserve_pages(bus_dma_tag_t dmat, bus_dmamap_t map,int flags) +{ /* Reserve Necessary Bounce Pages */ - if (map->pagesneeded != 0) { - mtx_lock(&bounce_lock); - if (flags & BUS_DMA_NOWAIT) { - if (reserve_bounce_pages(dmat, map, 0) != 0) { - mtx_unlock(&bounce_lock); - return (ENOMEM); - } - } else { - if (reserve_bounce_pages(dmat, map, 1) != 0) { - /* Queue us for resources */ - STAILQ_INSERT_TAIL(&bounce_map_waitinglist, - map, links); - mtx_unlock(&bounce_lock); - return (EINPROGRESS); - } + mtx_lock(&bounce_lock); + if (flags & BUS_DMA_NOWAIT) { + if (reserve_bounce_pages(dmat, map, 0) != 0) { + mtx_unlock(&bounce_lock); + return (ENOMEM); + } + } else { + if (reserve_bounce_pages(dmat, map, 1) != 0) { + /* Queue us for resources */ + STAILQ_INSERT_TAIL(&bounce_map_waitinglist, + map, links); + mtx_unlock(&bounce_lock); + return (EINPROGRESS); } - mtx_unlock(&bounce_lock); } + mtx_unlock(&bounce_lock); return (0); } /* - * Utility function to load a linear buffer. lastaddrp holds state - * between invocations (for multiple-buffer loads). segp contains + * Add a single contiguous physical range to the segment list. + */ +static int +_bus_dmamap_addseg(bus_dma_tag_t dmat, bus_dmamap_t map, bus_addr_t curaddr, + bus_size_t sgsize, bus_dma_segment_t *segs, int *segp) +{ + bus_addr_t baddr, bmask; + int seg; + + /* + * Make sure we don't cross any boundaries. + */ + bmask = ~(dmat->boundary - 1); + if (dmat->boundary > 0) { + baddr = (curaddr + dmat->boundary) & bmask; + if (sgsize > (baddr - curaddr)) + sgsize = (baddr - curaddr); + } + /* + * Insert chunk into a segment, coalescing with + * the previous segment if possible. + */ + seg = *segp; + if (seg >= 0 && + curaddr == segs[seg].ds_addr + segs[seg].ds_len && + (segs[seg].ds_len + sgsize) <= dmat->maxsegsz && + (dmat->boundary == 0 || + (segs[seg].ds_addr & bmask) == (curaddr & bmask))) { + segs[seg].ds_len += sgsize; + } else { + if (++seg >= dmat->nsegments) + return (0); + segs[seg].ds_addr = curaddr; + segs[seg].ds_len = sgsize; + } + *segp = seg; + return (sgsize); +} + +/* + * Utility function to load a physical buffer. segp contains + * the starting segment on entrace, and the ending segment on exit. + */ +int +_bus_dmamap_load_phys(bus_dma_tag_t dmat, bus_dmamap_t map, + vm_paddr_t buf, bus_size_t buflen, int flags, bus_dma_segment_t *segs, + int *segp) +{ + bus_addr_t curaddr; + bus_size_t sgsize; + int error; + + if (segs == NULL) + segs = dmat->segments; + + if ((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) { + _bus_dmamap_count_phys(dmat, map, buf, buflen, flags); + if (map->pagesneeded != 0) { + error = _bus_dmamap_reserve_pages(dmat, map, flags); + if (error) + return (error); + } + } + + while (buflen > 0) { + curaddr = buf; + sgsize = MIN(buflen, dmat->maxsegsz); + if (((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) && + map->pagesneeded != 0 && run_filter(dmat, curaddr)) { + sgsize = MIN(sgsize, PAGE_SIZE); + curaddr = add_bounce_page(dmat, map, 0, curaddr, + sgsize); + } + sgsize = _bus_dmamap_addseg(dmat, map, curaddr, sgsize, segs, + segp); + if (sgsize == 0) + break; + buf += sgsize; + buflen -= sgsize; + } + + /* + * Did we fit? + */ + if (buflen != 0) { + _bus_dmamap_unload(dmat, map); + return (EFBIG); /* XXX better return value here? */ + } + return (0); +} + +/* + * Utility function to load a linear buffer. segp contains * the starting segment on entrance, and the ending segment on exit. * first indicates if this is the first invocation of this function. */ -static __inline int -bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dma_segment_t *segs, - bus_dmamap_t map, void *buf, bus_size_t buflen, struct pmap *pmap, - int flags, vm_offset_t *lastaddrp, int *segp) +int +_bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, + bus_size_t buflen, struct pmap *pmap, int flags, bus_dma_segment_t *segs, + int *segp) { bus_size_t sgsize; - bus_addr_t curaddr, lastaddr, baddr, bmask; + bus_addr_t curaddr; + struct sync_list *sl; vm_offset_t vaddr = (vm_offset_t)buf; - int seg; int error = 0; - lastaddr = *lastaddrp; - bmask = ~(dmat->boundary - 1); + + if (segs == NULL) + segs = dmat->segments; if ((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) { - error = _bus_dmamap_count_pages(dmat, map, pmap, buf, buflen, - flags); - if (error) - return (error); + _bus_dmamap_count_pages(dmat, map, pmap, buf, buflen, flags); + if (map->pagesneeded != 0) { + error = _bus_dmamap_reserve_pages(dmat, map, flags); + if (error) + return (error); + } } CTR3(KTR_BUSDMA, "lowaddr= %d boundary= %d, " "alignment= %d", dmat->lowaddr, dmat->boundary, dmat->alignment); - for (seg = *segp; buflen > 0 ; ) { + while (buflen > 0) { /* * Get the physical address for this segment. * @@ -791,237 +928,62 @@ bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dma_segment_t *segs, if (buflen < sgsize) sgsize = buflen; - /* - * Make sure we don't cross any boundaries. - */ - if (dmat->boundary > 0) { - baddr = (curaddr + dmat->boundary) & bmask; - if (sgsize > (baddr - curaddr)) - sgsize = (baddr - curaddr); - } if (((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) && map->pagesneeded != 0 && run_filter(dmat, curaddr)) { - curaddr = add_bounce_page(dmat, map, vaddr, sgsize); - } - - /* - * Insert chunk into a segment, coalescing with - * the previous segment if possible. - */ - if (seg >= 0 && curaddr == lastaddr && - (segs[seg].ds_len + sgsize) <= dmat->maxsegsz && - (dmat->boundary == 0 || - (segs[seg].ds_addr & bmask) == - (curaddr & bmask))) { - segs[seg].ds_len += sgsize; - goto segdone; + curaddr = add_bounce_page(dmat, map, vaddr, curaddr, + sgsize); } else { - if (++seg >= dmat->nsegments) - break; - segs[seg].ds_addr = curaddr; - segs[seg].ds_len = sgsize; + sl = &map->slist[map->sync_count - 1]; + if (map->sync_count == 0 || + vaddr != sl->vaddr + sl->datacount) { + if (++map->sync_count > dmat->nsegments) + goto cleanup; + sl++; + sl->vaddr = vaddr; + sl->datacount = sgsize; + sl->busaddr = curaddr; + } else + sl->datacount += sgsize; } - if (error) + sgsize = _bus_dmamap_addseg(dmat, map, curaddr, sgsize, segs, + segp); + if (sgsize == 0) break; -segdone: - lastaddr = curaddr + sgsize; vaddr += sgsize; buflen -= sgsize; } - *segp = seg; - *lastaddrp = lastaddr; - +cleanup: /* * Did we fit? */ - if (buflen != 0) + if (buflen != 0) { + _bus_dmamap_unload(dmat, map); error = EFBIG; /* XXX better return value here? */ + } return (error); } -/* - * Map the buffer buf into bus space using the dmamap map. - */ -int -bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, - bus_size_t buflen, bus_dmamap_callback_t *callback, - void *callback_arg, int flags) +void +__bus_dmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map, + struct memdesc *mem, bus_dmamap_callback_t *callback, void *callback_arg) { - vm_offset_t lastaddr = 0; - int error, nsegs = -1; KASSERT(dmat != NULL, ("dmatag is NULL")); KASSERT(map != NULL, ("dmamap is NULL")); + map->mem = *mem; map->callback = callback; map->callback_arg = callback_arg; - map->flags &= ~DMAMAP_TYPE_MASK; - map->flags |= DMAMAP_LINEAR; - map->buffer = buf; - map->len = buflen; - error = bus_dmamap_load_buffer(dmat, - dmat->segments, map, buf, buflen, kernel_pmap, - flags, &lastaddr, &nsegs); - if (error == EINPROGRESS) - return (error); - if (error) - (*callback)(callback_arg, NULL, 0, error); - else - (*callback)(callback_arg, dmat->segments, nsegs + 1, error); - - CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", - __func__, dmat, dmat->flags, nsegs + 1, error); - - return (error); } -/* - * Like bus_dmamap_load(), but for mbufs. - */ -int -bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m0, - bus_dmamap_callback2_t *callback, void *callback_arg, - int flags) +bus_dma_segment_t * +_bus_dmamap_complete(bus_dma_tag_t dmat, bus_dmamap_t map, + bus_dma_segment_t *segs, int nsegs, int error) { - int nsegs = -1, error = 0; - M_ASSERTPKTHDR(m0); - - map->flags &= ~DMAMAP_TYPE_MASK; - map->flags |= DMAMAP_MBUF; - map->buffer = m0; - map->len = 0; - if (m0->m_pkthdr.len <= dmat->maxsize) { - vm_offset_t lastaddr = 0; - struct mbuf *m; - - for (m = m0; m != NULL && error == 0; m = m->m_next) { - if (m->m_len > 0) { - error = bus_dmamap_load_buffer(dmat, - dmat->segments, map, m->m_data, m->m_len, - kernel_pmap, flags, &lastaddr, &nsegs); - map->len += m->m_len; - } - } - } else { - error = EINVAL; - } - - if (error) { - /* - * force "no valid mappings" on error in callback. - */ - (*callback)(callback_arg, dmat->segments, 0, 0, error); - } else { - (*callback)(callback_arg, dmat->segments, nsegs + 1, - m0->m_pkthdr.len, error); - } - CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", - __func__, dmat, dmat->flags, error, nsegs + 1); - - return (error); -} - -int -bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map, - struct mbuf *m0, bus_dma_segment_t *segs, int *nsegs, - int flags) -{ - int error = 0; - M_ASSERTPKTHDR(m0); - - flags |= BUS_DMA_NOWAIT; - *nsegs = -1; - map->flags &= ~DMAMAP_TYPE_MASK; - map->flags |= DMAMAP_MBUF; - map->buffer = m0; - map->len = 0; - if (m0->m_pkthdr.len <= dmat->maxsize) { - vm_offset_t lastaddr = 0; - struct mbuf *m; - - for (m = m0; m != NULL && error == 0; m = m->m_next) { - if (m->m_len > 0) { - error = bus_dmamap_load_buffer(dmat, segs, map, - m->m_data, m->m_len, - kernel_pmap, flags, &lastaddr, - nsegs); - map->len += m->m_len; - } - } - } else { - error = EINVAL; - } - - /* XXX FIXME: Having to increment nsegs is really annoying */ - ++*nsegs; - CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", - __func__, dmat, dmat->flags, error, *nsegs); - return (error); -} - -/* - * Like bus_dmamap_load(), but for uios. - */ -int -bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, struct uio *uio, - bus_dmamap_callback2_t *callback, void *callback_arg, - int flags) -{ - vm_offset_t lastaddr = 0; - int nsegs, i, error; - bus_size_t resid; - struct iovec *iov; - struct pmap *pmap; - - resid = uio->uio_resid; - iov = uio->uio_iov; - map->flags &= ~DMAMAP_TYPE_MASK; - map->flags |= DMAMAP_UIO; - map->buffer = uio; - map->len = 0; - - if (uio->uio_segflg == UIO_USERSPACE) { - KASSERT(uio->uio_td != NULL, - ("bus_dmamap_load_uio: USERSPACE but no proc")); - /* XXX: pmap = vmspace_pmap(uio->uio_td->td_proc->p_vmspace); */ - panic("can't do it yet"); - } else - pmap = kernel_pmap; - - error = 0; - nsegs = -1; - for (i = 0; i < uio->uio_iovcnt && resid != 0 && !error; i++) { - /* - * Now at the first iovec to load. Load each iovec - * until we have exhausted the residual count. - */ - bus_size_t minlen = - resid < iov[i].iov_len ? resid : iov[i].iov_len; - caddr_t addr = (caddr_t) iov[i].iov_base; - - if (minlen > 0) { - error = bus_dmamap_load_buffer(dmat, dmat->segments, - map, addr, minlen, pmap, flags, &lastaddr, &nsegs); - - map->len += minlen; - resid -= minlen; - } - } - - if (error) { - /* - * force "no valid mappings" on error in callback. - */ - (*callback)(callback_arg, dmat->segments, 0, 0, error); - } else { - (*callback)(callback_arg, dmat->segments, nsegs+1, - uio->uio_resid, error); - } - - CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", - __func__, dmat, dmat->flags, error, nsegs + 1); - return (error); + if (segs == NULL) + segs = dmat->segments; + return (segs); } /* @@ -1032,16 +994,16 @@ _bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map) { struct bounce_page *bpage; - map->flags &= ~DMAMAP_TYPE_MASK; while ((bpage = STAILQ_FIRST(&map->bpages)) != NULL) { STAILQ_REMOVE_HEAD(&map->bpages, links); free_bounce_page(dmat, bpage); } + map->sync_count = 0; return; } static void -bus_dmamap_sync_buf(void *buf, int len, bus_dmasync_op_t op) +bus_dmamap_sync_buf(vm_offset_t buf, int len, bus_dmasync_op_t op) { char tmp_cl[mips_pdcache_linesize], tmp_clend[mips_pdcache_linesize]; vm_offset_t buf_cl, buf_clend; @@ -1055,9 +1017,9 @@ bus_dmamap_sync_buf(void *buf, int len, bus_dmasync_op_t op) * prevent a data loss we save these chunks in temporary buffer * before invalidation and restore them afer it */ - buf_cl = (vm_offset_t)buf & ~cache_linesize_mask; - size_cl = (vm_offset_t)buf & cache_linesize_mask; - buf_clend = (vm_offset_t)buf + len; + buf_cl = buf & ~cache_linesize_mask; + size_cl = buf & cache_linesize_mask; + buf_clend = buf + len; size_clend = (mips_pdcache_linesize - (buf_clend & cache_linesize_mask)) & cache_linesize_mask; @@ -1072,7 +1034,7 @@ bus_dmamap_sync_buf(void *buf, int len, bus_dmasync_op_t op) memcpy (tmp_cl, (void*)buf_cl, size_cl); if (size_clend) memcpy (tmp_clend, (void*)buf_clend, size_clend); - mips_dcache_inv_range((vm_offset_t)buf, len); + mips_dcache_inv_range(buf, len); /* * Restore them */ @@ -1087,15 +1049,14 @@ bus_dmamap_sync_buf(void *buf, int len, bus_dmasync_op_t op) * necessary. */ if (size_cl) - mips_dcache_wbinv_range((vm_offset_t)buf_cl, size_cl); + mips_dcache_wbinv_range(buf_cl, size_cl); if (size_clend && (size_cl == 0 || buf_clend - buf_cl > mips_pdcache_linesize)) - mips_dcache_wbinv_range((vm_offset_t)buf_clend, - size_clend); + mips_dcache_wbinv_range(buf_clend, size_clend); break; case BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE: - mips_dcache_wbinv_range((vm_offset_t)buf_cl, len); + mips_dcache_wbinv_range(buf_cl, len); break; case BUS_DMASYNC_PREREAD: @@ -1106,7 +1067,7 @@ bus_dmamap_sync_buf(void *buf, int len, bus_dmasync_op_t op) memcpy (tmp_cl, (void *)buf_cl, size_cl); if (size_clend) memcpy (tmp_clend, (void *)buf_clend, size_clend); - mips_dcache_inv_range((vm_offset_t)buf, len); + mips_dcache_inv_range(buf, len); /* * Restore them */ @@ -1121,15 +1082,14 @@ bus_dmamap_sync_buf(void *buf, int len, bus_dmasync_op_t op) * necessary. */ if (size_cl) - mips_dcache_wbinv_range((vm_offset_t)buf_cl, size_cl); + mips_dcache_wbinv_range(buf_cl, size_cl); if (size_clend && (size_cl == 0 || buf_clend - buf_cl > mips_pdcache_linesize)) - mips_dcache_wbinv_range((vm_offset_t)buf_clend, - size_clend); + mips_dcache_wbinv_range(buf_clend, size_clend); break; case BUS_DMASYNC_PREWRITE: - mips_dcache_wb_range((vm_offset_t)buf, len); + mips_dcache_wb_range(buf, len); break; } } @@ -1141,10 +1101,18 @@ _bus_dmamap_sync_bp(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op) STAILQ_FOREACH(bpage, &map->bpages, links) { if (op & BUS_DMASYNC_PREWRITE) { - bcopy((void *)bpage->datavaddr, - (void *)(bpage->vaddr_nocache != 0 ? - bpage->vaddr_nocache : bpage->vaddr), - bpage->datacount); + if (bpage->datavaddr != 0) + bcopy((void *)bpage->datavaddr, + (void *)(bpage->vaddr_nocache != 0 ? + bpage->vaddr_nocache : + bpage->vaddr), + bpage->datacount); + else + physcopyout(bpage->dataaddr, + (void *)(bpage->vaddr_nocache != 0 ? + bpage->vaddr_nocache : + bpage->vaddr), + bpage->datacount); if (bpage->vaddr_nocache == 0) { mips_dcache_wb_range(bpage->vaddr, bpage->datacount); @@ -1156,36 +1124,23 @@ _bus_dmamap_sync_bp(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op) mips_dcache_inv_range(bpage->vaddr, bpage->datacount); } - bcopy((void *)(bpage->vaddr_nocache != 0 ? - bpage->vaddr_nocache : bpage->vaddr), - (void *)bpage->datavaddr, bpage->datacount); + if (bpage->datavaddr != 0) + bcopy((void *)(bpage->vaddr_nocache != 0 ? + bpage->vaddr_nocache : bpage->vaddr), + (void *)bpage->datavaddr, bpage->datacount); + else + physcopyin((void *)(bpage->vaddr_nocache != 0 ? + bpage->vaddr_nocache : bpage->vaddr), + bpage->dataaddr, bpage->datacount); dmat->bounce_zone->total_bounced++; } } } -static __inline int -_bus_dma_buf_is_in_bp(bus_dmamap_t map, void *buf, int len) -{ - struct bounce_page *bpage; - - STAILQ_FOREACH(bpage, &map->bpages, links) { - if ((vm_offset_t)buf >= bpage->datavaddr && - (vm_offset_t)buf + len <= bpage->datavaddr + - bpage->datacount) - return (1); - } - return (0); - -} - void _bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op) { - struct mbuf *m; - struct uio *uio; - int resid; - struct iovec *iov; + struct sync_list *sl, *end; if (op == BUS_DMASYNC_POSTWRITE) return; @@ -1199,38 +1154,10 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op) return; CTR3(KTR_BUSDMA, "%s: op %x flags %x", __func__, op, map->flags); - switch(map->flags & DMAMAP_TYPE_MASK) { - case DMAMAP_LINEAR: - if (!(_bus_dma_buf_is_in_bp(map, map->buffer, map->len))) - bus_dmamap_sync_buf(map->buffer, map->len, op); - break; - case DMAMAP_MBUF: - m = map->buffer; - while (m) { - if (m->m_len > 0 && - !(_bus_dma_buf_is_in_bp(map, m->m_data, m->m_len))) - bus_dmamap_sync_buf(m->m_data, m->m_len, op); - m = m->m_next; - } - break; - case DMAMAP_UIO: - uio = map->buffer; - iov = uio->uio_iov; - resid = uio->uio_resid; - for (int i = 0; i < uio->uio_iovcnt && resid != 0; i++) { - bus_size_t minlen = resid < iov[i].iov_len ? resid : - iov[i].iov_len; - if (minlen > 0) { - if (!_bus_dma_buf_is_in_bp(map, iov[i].iov_base, - minlen)) - bus_dmamap_sync_buf(iov[i].iov_base, - minlen, op); - resid -= minlen; - } - } - break; - default: - break; + if (map->sync_count) { + end = &map->slist[map->sync_count]; + for (sl = &map->slist[0]; sl != end; sl++) + bus_dmamap_sync_buf(sl->vaddr, sl->datacount, op); } } @@ -1393,7 +1320,7 @@ reserve_bounce_pages(bus_dma_tag_t dmat, bus_dmamap_t map, int commit) static bus_addr_t add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, vm_offset_t vaddr, - bus_size_t size) + bus_addr_t addr, bus_size_t size) { struct bounce_zone *bz; struct bounce_page *bpage; @@ -1426,6 +1353,7 @@ add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, vm_offset_t vaddr, bpage->busaddr |= vaddr & PAGE_MASK; } bpage->datavaddr = vaddr; + bpage->dataaddr = addr; bpage->datacount = size; STAILQ_INSERT_TAIL(&(map->bpages), bpage, links); return (bpage->busaddr); @@ -1479,8 +1407,8 @@ busdma_swi(void) mtx_unlock(&bounce_lock); dmat = map->dmat; (dmat->lockfunc)(dmat->lockfuncarg, BUS_DMA_LOCK); - bus_dmamap_load(map->dmat, map, map->buffer, map->len, - map->callback, map->callback_arg, /*flags*/0); + bus_dmamap_load_mem(map->dmat, map, &map->mem, map->callback, + map->callback_arg, BUS_DMA_WAITOK); (dmat->lockfunc)(dmat->lockfuncarg, BUS_DMA_UNLOCK); mtx_lock(&bounce_lock); } diff --git a/sys/powerpc/powerpc/busdma_machdep.c b/sys/powerpc/powerpc/busdma_machdep.c index 7953f913270..7708b943e88 100644 --- a/sys/powerpc/powerpc/busdma_machdep.c +++ b/sys/powerpc/powerpc/busdma_machdep.c @@ -40,10 +40,10 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include -#include -#include #include +#include #include #include @@ -87,6 +87,7 @@ struct bounce_page { vm_offset_t vaddr; /* kva of bounce buffer */ bus_addr_t busaddr; /* Physical address */ vm_offset_t datavaddr; /* kva of client data */ + bus_addr_t dataaddr; /* client physical address */ bus_size_t datacount; /* client data count */ STAILQ_ENTRY(bounce_page) links; }; @@ -125,8 +126,7 @@ struct bus_dmamap { int pagesneeded; int pagesreserved; bus_dma_tag_t dmat; - void *buf; /* unmapped buffer pointer */ - bus_size_t buflen; /* unmapped buffer length */ + struct memdesc mem; bus_dma_segment_t *segments; int nsegs; bus_dmamap_callback_t *callback; @@ -144,7 +144,8 @@ static int alloc_bounce_pages(bus_dma_tag_t dmat, u_int numpages); static int reserve_bounce_pages(bus_dma_tag_t dmat, bus_dmamap_t map, int commit); static bus_addr_t add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, - vm_offset_t vaddr, bus_size_t size); + vm_offset_t vaddr, bus_addr_t addr, + bus_size_t size); static void free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage); static __inline int run_filter(bus_dma_tag_t dmat, bus_addr_t paddr); @@ -564,32 +565,45 @@ bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) CTR3(KTR_BUSDMA, "%s: tag %p flags 0x%x", __func__, dmat, dmat->flags); } -/* - * Utility function to load a linear buffer. lastaddrp holds state - * between invocations (for multiple-buffer loads). segp contains - * the starting segment on entrance, and the ending segment on exit. - * first indicates if this is the first invocation of this function. - */ -static __inline int -_bus_dmamap_load_buffer(bus_dma_tag_t dmat, - bus_dmamap_t map, - void *buf, bus_size_t buflen, - pmap_t pmap, - int flags, - bus_addr_t *lastaddrp, - bus_dma_segment_t *segs, - int *segp, - int first) +static void +_bus_dmamap_count_phys(bus_dma_tag_t dmat, bus_dmamap_t map, vm_paddr_t buf, + bus_size_t buflen, int flags) { + bus_addr_t curaddr; bus_size_t sgsize; - bus_addr_t curaddr, lastaddr, baddr, bmask; - vm_offset_t vaddr; - bus_addr_t paddr; - int seg; - if (map->pagesneeded == 0 && ((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0)) { - vm_offset_t vendaddr; + if (map->pagesneeded == 0) { + CTR4(KTR_BUSDMA, "lowaddr= %d Maxmem= %d, boundary= %d, " + "alignment= %d", dmat->lowaddr, ptoa((vm_paddr_t)Maxmem), + dmat->boundary, dmat->alignment); + CTR2(KTR_BUSDMA, "map= %p, pagesneeded= %d", map, map->pagesneeded); + /* + * Count the number of bounce pages + * needed in order to complete this transfer + */ + curaddr = buf; + while (buflen != 0) { + sgsize = MIN(buflen, dmat->maxsegsz); + if (run_filter(dmat, curaddr) != 0) { + sgsize = MIN(sgsize, PAGE_SIZE); + map->pagesneeded++; + } + curaddr += sgsize; + buflen -= sgsize; + } + CTR1(KTR_BUSDMA, "pagesneeded= %d\n", map->pagesneeded); + } +} +static void +_bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map, pmap_t pmap, + void *buf, bus_size_t buflen, int flags) +{ + vm_offset_t vaddr; + vm_offset_t vendaddr; + bus_addr_t paddr; + + if (map->pagesneeded == 0) { CTR4(KTR_BUSDMA, "lowaddr= %d Maxmem= %d, boundary= %d, " "alignment= %d", dmat->lowaddr, ptoa((vm_paddr_t)Maxmem), dmat->boundary, dmat->alignment); @@ -605,10 +619,10 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_size_t sg_len; sg_len = PAGE_SIZE - ((vm_offset_t)vaddr & PAGE_MASK); - if (pmap) - paddr = pmap_extract(pmap, vaddr); - else + if (pmap == kernel_pmap) paddr = pmap_kextract(vaddr); + else + paddr = pmap_extract(pmap, vaddr); if (run_filter(dmat, paddr) != 0) { sg_len = roundup2(sg_len, dmat->alignment); map->pagesneeded++; @@ -617,44 +631,171 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dmat, } CTR1(KTR_BUSDMA, "pagesneeded= %d\n", map->pagesneeded); } +} + +static int +_bus_dmamap_reserve_pages(bus_dma_tag_t dmat, bus_dmamap_t map, int flags) +{ /* Reserve Necessary Bounce Pages */ - if (map->pagesneeded != 0) { - mtx_lock(&bounce_lock); - if (flags & BUS_DMA_NOWAIT) { - if (reserve_bounce_pages(dmat, map, 0) != 0) { - mtx_unlock(&bounce_lock); - return (ENOMEM); - } - } else { - if (reserve_bounce_pages(dmat, map, 1) != 0) { - /* Queue us for resources */ - map->dmat = dmat; - map->buf = buf; - map->buflen = buflen; - STAILQ_INSERT_TAIL(&bounce_map_waitinglist, - map, links); - mtx_unlock(&bounce_lock); - return (EINPROGRESS); - } + mtx_lock(&bounce_lock); + if (flags & BUS_DMA_NOWAIT) { + if (reserve_bounce_pages(dmat, map, 0) != 0) { + mtx_unlock(&bounce_lock); + return (ENOMEM); + } + } else { + if (reserve_bounce_pages(dmat, map, 1) != 0) { + /* Queue us for resources */ + STAILQ_INSERT_TAIL(&bounce_map_waitinglist, + map, links); + mtx_unlock(&bounce_lock); + return (EINPROGRESS); + } + } + mtx_unlock(&bounce_lock); + + return (0); +} + +/* + * Add a single contiguous physical range to the segment list. + */ +static int +_bus_dmamap_addseg(bus_dma_tag_t dmat, bus_dmamap_t map, bus_addr_t curaddr, + bus_size_t sgsize, bus_dma_segment_t *segs, int *segp) +{ + bus_addr_t baddr, bmask; + int seg; + + /* + * Make sure we don't cross any boundaries. + */ + bmask = ~(dmat->boundary - 1); + if (dmat->boundary > 0) { + baddr = (curaddr + dmat->boundary) & bmask; + if (sgsize > (baddr - curaddr)) + sgsize = (baddr - curaddr); + } + + /* + * Insert chunk into a segment, coalescing with + * previous segment if possible. + */ + seg = *segp; + if (seg == -1) { + seg = 0; + segs[seg].ds_addr = curaddr; + segs[seg].ds_len = sgsize; + } else { + if (curaddr == segs[seg].ds_addr + segs[seg].ds_len && + (segs[seg].ds_len + sgsize) <= dmat->maxsegsz && + (dmat->boundary == 0 || + (segs[seg].ds_addr & bmask) == (curaddr & bmask))) + segs[seg].ds_len += sgsize; + else { + if (++seg >= dmat->nsegments) + return (0); + segs[seg].ds_addr = curaddr; + segs[seg].ds_len = sgsize; + } + } + *segp = seg; + return (sgsize); +} + +/* + * Utility function to load a physical buffer. segp contains + * the starting segment on entrace, and the ending segment on exit. + */ +int +_bus_dmamap_load_phys(bus_dma_tag_t dmat, + bus_dmamap_t map, + vm_paddr_t buf, bus_size_t buflen, + int flags, + bus_dma_segment_t *segs, + int *segp) +{ + bus_addr_t curaddr; + bus_size_t sgsize; + int error; + + if (segs == NULL) + segs = map->segments; + + if ((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) { + _bus_dmamap_count_phys(dmat, map, buf, buflen, flags); + if (map->pagesneeded != 0) { + error = _bus_dmamap_reserve_pages(dmat, map, flags); + if (error) + return (error); + } + } + + while (buflen > 0) { + curaddr = buf; + sgsize = MIN(buflen, dmat->maxsegsz); + if (map->pagesneeded != 0 && run_filter(dmat, curaddr)) { + sgsize = MIN(sgsize, PAGE_SIZE); + curaddr = add_bounce_page(dmat, map, 0, curaddr, + sgsize); + } + sgsize = _bus_dmamap_addseg(dmat, map, curaddr, sgsize, segs, + segp); + if (sgsize == 0) + break; + buf += sgsize; + buflen -= sgsize; + } + + /* + * Did we fit? + */ + return (buflen != 0 ? EFBIG : 0); /* XXX better return value here? */ +} + +/* + * Utility function to load a linear buffer. segp contains + * the starting segment on entrance, and the ending segment on exit. + */ +int +_bus_dmamap_load_buffer(bus_dma_tag_t dmat, + bus_dmamap_t map, + void *buf, bus_size_t buflen, + pmap_t pmap, + int flags, + bus_dma_segment_t *segs, + int *segp) +{ + bus_size_t sgsize; + bus_addr_t curaddr; + vm_offset_t vaddr; + int error; + + if (segs == NULL) + segs = map->segments; + + if ((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) { + _bus_dmamap_count_pages(dmat, map, pmap, buf, buflen, flags); + if (map->pagesneeded != 0) { + error = _bus_dmamap_reserve_pages(dmat, map, flags); + if (error) + return (error); } - mtx_unlock(&bounce_lock); } vaddr = (vm_offset_t)buf; - lastaddr = *lastaddrp; - bmask = ~(dmat->boundary - 1); - for (seg = *segp; buflen > 0 ; ) { + while (buflen > 0) { bus_size_t max_sgsize; /* * Get the physical address for this segment. */ - if (pmap) - curaddr = pmap_extract(pmap, vaddr); - else + if (pmap == kernel_pmap) curaddr = pmap_kextract(vaddr); + else + curaddr = pmap_extract(pmap, vaddr); /* * Compute the segment size, and adjust counts. @@ -664,268 +805,56 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dmat, if (map->pagesneeded != 0 && run_filter(dmat, curaddr)) { sgsize = roundup2(sgsize, dmat->alignment); sgsize = MIN(sgsize, max_sgsize); - curaddr = add_bounce_page(dmat, map, vaddr, sgsize); + curaddr = add_bounce_page(dmat, map, vaddr, curaddr, + sgsize); } else { sgsize = MIN(sgsize, max_sgsize); } - /* - * Make sure we don't cross any boundaries. - */ - if (dmat->boundary > 0) { - baddr = (curaddr + dmat->boundary) & bmask; - if (sgsize > (baddr - curaddr)) - sgsize = (baddr - curaddr); - } - - /* - * Insert chunk into a segment, coalescing with - * previous segment if possible. - */ - if (first) { - segs[seg].ds_addr = curaddr; - segs[seg].ds_len = sgsize; - first = 0; - } else { - if (curaddr == lastaddr && - (segs[seg].ds_len + sgsize) <= dmat->maxsegsz && - (dmat->boundary == 0 || - (segs[seg].ds_addr & bmask) == (curaddr & bmask))) - segs[seg].ds_len += sgsize; - else { - if (++seg >= dmat->nsegments) - break; - segs[seg].ds_addr = curaddr; - segs[seg].ds_len = sgsize; - } - } - - lastaddr = curaddr + sgsize; + sgsize = _bus_dmamap_addseg(dmat, map, curaddr, sgsize, segs, + segp); + if (sgsize == 0) + break; vaddr += sgsize; buflen -= sgsize; } - *segp = seg; - *lastaddrp = lastaddr; - /* * Did we fit? */ return (buflen != 0 ? EFBIG : 0); /* XXX better return value here? */ } -/* - * Map the buffer buf into bus space using the dmamap map. - */ -int -bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, - bus_size_t buflen, bus_dmamap_callback_t *callback, - void *callback_arg, int flags) +void +__bus_dmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map, + struct memdesc *mem, bus_dmamap_callback_t *callback, + void *callback_arg) { - bus_addr_t lastaddr = 0; - int error; if (dmat->flags & BUS_DMA_COULD_BOUNCE) { - flags |= BUS_DMA_WAITOK; + map->dmat = dmat; + map->mem = *mem; map->callback = callback; map->callback_arg = callback_arg; } +} - map->nsegs = 0; - error = _bus_dmamap_load_buffer(dmat, map, buf, buflen, NULL, flags, - &lastaddr, map->segments, &map->nsegs, 1); - map->nsegs++; +bus_dma_segment_t * +_bus_dmamap_complete(bus_dma_tag_t dmat, bus_dmamap_t map, + bus_dma_segment_t *segs, int nsegs, int error) +{ - CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", - __func__, dmat, dmat->flags, error, map->nsegs); - - if (error == EINPROGRESS) { - return (error); - } - - if (dmat->iommu != NULL) - IOMMU_MAP(dmat->iommu, map->segments, &map->nsegs, dmat->lowaddr, - dmat->highaddr, dmat->alignment, dmat->boundary, - dmat->iommu_cookie); - - if (error) - (*callback)(callback_arg, map->segments, 0, error); + if (segs != NULL) + memcpy(map->segments, segs, map->nsegs*sizeof(segs[0])); else - (*callback)(callback_arg, map->segments, map->nsegs, 0); - - /* - * Return ENOMEM to the caller so that it can pass it up the stack. - * This error only happens when NOWAIT is set, so deferal is disabled. - */ - if (error == ENOMEM) - return (error); - - return (0); -} - - -/* - * Like _bus_dmamap_load(), but for mbufs. - */ -int -bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, - struct mbuf *m0, - bus_dmamap_callback2_t *callback, void *callback_arg, - int flags) -{ - int error; - - M_ASSERTPKTHDR(m0); - - flags |= BUS_DMA_NOWAIT; - map->nsegs = 0; - error = 0; - if (m0->m_pkthdr.len <= dmat->maxsize) { - int first = 1; - bus_addr_t lastaddr = 0; - struct mbuf *m; - - for (m = m0; m != NULL && error == 0; m = m->m_next) { - if (m->m_len > 0) { - error = _bus_dmamap_load_buffer(dmat, map, - m->m_data, m->m_len, - NULL, flags, &lastaddr, - map->segments, &map->nsegs, first); - first = 0; - } - } - } else { - error = EINVAL; - } - - map->nsegs++; + segs = map->segments; + map->nsegs = nsegs; if (dmat->iommu != NULL) - IOMMU_MAP(dmat->iommu, map->segments, &map->nsegs, dmat->lowaddr, - dmat->highaddr, dmat->alignment, dmat->boundary, - dmat->iommu_cookie); + IOMMU_MAP(dmat->iommu, map->segments, &map->nsegs, + dmat->lowaddr, dmat->highaddr, dmat->alignment, + dmat->boundary, dmat->iommu_cookie); - if (error) { - /* force "no valid mappings" in callback */ - (*callback)(callback_arg, map->segments, 0, 0, error); - } else { - (*callback)(callback_arg, map->segments, - map->nsegs, m0->m_pkthdr.len, error); - } - CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", - __func__, dmat, dmat->flags, error, map->nsegs); - return (error); -} - -int -bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map, - struct mbuf *m0, bus_dma_segment_t *segs, int *nsegs, - int flags) -{ - int error; - - M_ASSERTPKTHDR(m0); - - flags |= BUS_DMA_NOWAIT; - *nsegs = 0; - error = 0; - if (m0->m_pkthdr.len <= dmat->maxsize) { - int first = 1; - bus_addr_t lastaddr = 0; - struct mbuf *m; - - for (m = m0; m != NULL && error == 0; m = m->m_next) { - if (m->m_len > 0) { - error = _bus_dmamap_load_buffer(dmat, map, - m->m_data, m->m_len, - NULL, flags, &lastaddr, - segs, nsegs, first); - first = 0; - } - } - } else { - error = EINVAL; - } - - /* XXX FIXME: Having to increment nsegs is really annoying */ - ++*nsegs; - - if (dmat->iommu != NULL) - IOMMU_MAP(dmat->iommu, segs, nsegs, dmat->lowaddr, - dmat->highaddr, dmat->alignment, dmat->boundary, - dmat->iommu_cookie); - - map->nsegs = *nsegs; - memcpy(map->segments, segs, map->nsegs*sizeof(segs[0])); - - CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", - __func__, dmat, dmat->flags, error, *nsegs); - return (error); -} - -/* - * Like _bus_dmamap_load(), but for uios. - */ -int -bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, - struct uio *uio, - bus_dmamap_callback2_t *callback, void *callback_arg, - int flags) -{ - bus_addr_t lastaddr = 0; - int error, first, i; - bus_size_t resid; - struct iovec *iov; - pmap_t pmap; - - flags |= BUS_DMA_NOWAIT; - resid = uio->uio_resid; - iov = uio->uio_iov; - - if (uio->uio_segflg == UIO_USERSPACE) { - KASSERT(uio->uio_td != NULL, - ("bus_dmamap_load_uio: USERSPACE but no proc")); - pmap = vmspace_pmap(uio->uio_td->td_proc->p_vmspace); - } else - pmap = NULL; - - map->nsegs = 0; - error = 0; - first = 1; - for (i = 0; i < uio->uio_iovcnt && resid != 0 && !error; i++) { - /* - * Now at the first iovec to load. Load each iovec - * until we have exhausted the residual count. - */ - bus_size_t minlen = - resid < iov[i].iov_len ? resid : iov[i].iov_len; - caddr_t addr = (caddr_t) iov[i].iov_base; - - if (minlen > 0) { - error = _bus_dmamap_load_buffer(dmat, map, - addr, minlen, pmap, flags, &lastaddr, - map->segments, &map->nsegs, first); - first = 0; - - resid -= minlen; - } - } - - map->nsegs++; - if (dmat->iommu != NULL) - IOMMU_MAP(dmat->iommu, map->segments, &map->nsegs, dmat->lowaddr, - dmat->highaddr, dmat->alignment, dmat->boundary, - dmat->iommu_cookie); - - if (error) { - /* force "no valid mappings" in callback */ - (*callback)(callback_arg, map->segments, 0, 0, error); - } else { - (*callback)(callback_arg, map->segments, - map->nsegs, uio->uio_resid, error); - } - CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", - __func__, dmat, dmat->flags, error, map->nsegs); - return (error); + return (segs); } /* @@ -963,9 +892,14 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op) if (op & BUS_DMASYNC_PREWRITE) { while (bpage != NULL) { - bcopy((void *)bpage->datavaddr, - (void *)bpage->vaddr, - bpage->datacount); + if (bpage->datavaddr != 0) + bcopy((void *)bpage->datavaddr, + (void *)bpage->vaddr, + bpage->datacount); + else + physcopyout(bpage->dataaddr, + (void *)bpage->vaddr, + bpage->datacount); bpage = STAILQ_NEXT(bpage, links); } dmat->bounce_zone->total_bounced++; @@ -973,9 +907,13 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op) if (op & BUS_DMASYNC_POSTREAD) { while (bpage != NULL) { - bcopy((void *)bpage->vaddr, - (void *)bpage->datavaddr, - bpage->datacount); + if (bpage->datavaddr != 0) + bcopy((void *)bpage->vaddr, + (void *)bpage->datavaddr, + bpage->datacount); + else + physcopyin((void *)bpage->vaddr, + bpage->dataaddr, bpage->datacount); bpage = STAILQ_NEXT(bpage, links); } dmat->bounce_zone->total_bounced++; @@ -1142,7 +1080,7 @@ reserve_bounce_pages(bus_dma_tag_t dmat, bus_dmamap_t map, int commit) static bus_addr_t add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, vm_offset_t vaddr, - bus_size_t size) + bus_addr_t addr, bus_size_t size) { struct bounce_zone *bz; struct bounce_page *bpage; @@ -1174,6 +1112,7 @@ add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, vm_offset_t vaddr, bpage->busaddr |= vaddr & PAGE_MASK; } bpage->datavaddr = vaddr; + bpage->dataaddr = addr; bpage->datacount = size; STAILQ_INSERT_TAIL(&(map->bpages), bpage, links); return (bpage->busaddr); @@ -1227,8 +1166,9 @@ busdma_swi(void) mtx_unlock(&bounce_lock); dmat = map->dmat; (dmat->lockfunc)(dmat->lockfuncarg, BUS_DMA_LOCK); - bus_dmamap_load(map->dmat, map, map->buf, map->buflen, - map->callback, map->callback_arg, /*flags*/0); + bus_dmamap_load_mem(map->dmat, map, &map->mem, + map->callback, map->callback_arg, + BUS_DMA_WAITOK); (dmat->lockfunc)(dmat->lockfuncarg, BUS_DMA_UNLOCK); mtx_lock(&bounce_lock); } diff --git a/sys/powerpc/ps3/ps3cdrom.c b/sys/powerpc/ps3/ps3cdrom.c index ba3c3adb0f1..a654b4fc1b7 100644 --- a/sys/powerpc/ps3/ps3cdrom.c +++ b/sys/powerpc/ps3/ps3cdrom.c @@ -369,9 +369,8 @@ ps3cdrom_action(struct cam_sim *sim, union ccb *ccb) TAILQ_REMOVE(&sc->sc_free_xferq, xp, x_queue); - err = bus_dmamap_load(sc->sc_dmatag, xp->x_dmamap, - ccb->csio.data_ptr, ccb->csio.dxfer_len, ps3cdrom_transfer, - xp, 0); + err = bus_dmamap_load_ccb(sc->sc_dmatag, xp->x_dmamap, + ccb, ps3cdrom_transfer, xp, 0); if (err && err != EINPROGRESS) { device_printf(dev, "Could not load DMA map (%d)\n", err); diff --git a/sys/sparc64/include/bus_dma.h b/sys/sparc64/include/bus_dma.h index 5f981a7c1ab..7395794692a 100644 --- a/sys/sparc64/include/bus_dma.h +++ b/sys/sparc64/include/bus_dma.h @@ -78,14 +78,17 @@ struct bus_dma_methods { int (*dm_dmamap_create)(bus_dma_tag_t, int, bus_dmamap_t *); int (*dm_dmamap_destroy)(bus_dma_tag_t, bus_dmamap_t); - int (*dm_dmamap_load)(bus_dma_tag_t, bus_dmamap_t, void *, - bus_size_t, bus_dmamap_callback_t *, void *, int); - int (*dm_dmamap_load_mbuf)(bus_dma_tag_t, bus_dmamap_t, - struct mbuf *, bus_dmamap_callback2_t *, void *, int); - int (*dm_dmamap_load_mbuf_sg)(bus_dma_tag_t, bus_dmamap_t, - struct mbuf *, bus_dma_segment_t *segs, int *nsegs, int); - int (*dm_dmamap_load_uio)(bus_dma_tag_t, bus_dmamap_t, struct uio *, - bus_dmamap_callback2_t *, void *, int); + int (*dm_dmamap_load_phys)(bus_dma_tag_t dmat, bus_dmamap_t map, + vm_paddr_t buf, bus_size_t buflen, int flags, + bus_dma_segment_t *segs, int *segp); + int (*dm_dmamap_load_buffer)(bus_dma_tag_t dmat, bus_dmamap_t map, + void *buf, bus_size_t buflen, struct pmap *pmap, int flags, + bus_dma_segment_t *segs, int *segp); + void (*dm_dmamap_waitok)(bus_dma_tag_t dmat, bus_dmamap_t map, + struct memdesc *mem, bus_dmamap_callback_t *callback, + void *callback_arg); + bus_dma_segment_t *(*dm_dmamap_complete)(bus_dma_tag_t dmat, + bus_dmamap_t map, bus_dma_segment_t *segs, int nsegs, int error); void (*dm_dmamap_unload)(bus_dma_tag_t, bus_dmamap_t); void (*dm_dmamap_sync)(bus_dma_tag_t, bus_dmamap_t, bus_dmasync_op_t); @@ -125,14 +128,16 @@ struct bus_dma_tag { ((t)->dt_mt->dm_dmamap_create((t), (f), (p))) #define bus_dmamap_destroy(t, p) \ ((t)->dt_mt->dm_dmamap_destroy((t), (p))) -#define bus_dmamap_load(t, m, p, s, cb, cba, f) \ - ((t)->dt_mt->dm_dmamap_load((t), (m), (p), (s), (cb), (cba), (f))) -#define bus_dmamap_load_mbuf(t, m, mb, cb, cba, f) \ - ((t)->dt_mt->dm_dmamap_load_mbuf((t), (m), (mb), (cb), (cba), (f))) -#define bus_dmamap_load_mbuf_sg(t, m, mb, segs, nsegs, f) \ - ((t)->dt_mt->dm_dmamap_load_mbuf_sg((t), (m), (mb), (segs), (nsegs), (f))) -#define bus_dmamap_load_uio(t, m, ui, cb, cba, f) \ - ((t)->dt_mt->dm_dmamap_load_uio((t), (m), (ui), (cb), (cba), (f))) +#define _bus_dmamap_load_phys(t, m, b, l, f, s, sp) \ + ((t)->dt_mt->dm_dmamap_load_phys((t), (m), (b), (l), \ + (f), (s), (sp))) +#define _bus_dmamap_load_buffer(t, m, b, l, p, f, s, sp) \ + ((t)->dt_mt->dm_dmamap_load_buffer((t), (m), (b), (l), (p), \ + (f), (s), (sp))) +#define _bus_dmamap_waitok(t, m, mem, c, ca) \ + ((t)->dt_mt->dm_dmamap_waitok((t), (m), (mem), (c), (ca))) +#define _bus_dmamap_complete(t, m, s, n, e) \ + ((t)->dt_mt->dm_dmamap_complete((t), (m), (s), (n), (e))) #define bus_dmamap_unload(t, p) \ ((t)->dt_mt->dm_dmamap_unload((t), (p))) #define bus_dmamap_sync(t, m, op) \ diff --git a/sys/sparc64/sparc64/bus_machdep.c b/sys/sparc64/sparc64/bus_machdep.c index 31d28b27506..7f5e76b9363 100644 --- a/sys/sparc64/sparc64/bus_machdep.c +++ b/sys/sparc64/sparc64/bus_machdep.c @@ -98,13 +98,11 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include #include #include -#include #include #include @@ -326,38 +324,106 @@ nexus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map) } /* - * Utility function to load a linear buffer. lastaddrp holds state - * between invocations (for multiple-buffer loads). segp contains - * the starting segment on entrace, and the ending segment on exit. - * first indicates if this is the first invocation of this function. + * Add a single contiguous physical range to the segment list. */ static int -_nexus_dmamap_load_buffer(bus_dma_tag_t dmat, void *buf, bus_size_t buflen, - struct thread *td, int flags, bus_addr_t *lastaddrp, - bus_dma_segment_t *segs, int *segp, int first) +nexus_dmamap_addseg(bus_dma_tag_t dmat, bus_dmamap_t map, bus_addr_t curaddr, + bus_size_t sgsize, bus_dma_segment_t *segs, int *segp) +{ + bus_addr_t baddr, bmask; + int seg; + + /* + * Make sure we don't cross any boundaries. + */ + bmask = ~(dmat->dt_boundary - 1); + if (dmat->dt_boundary > 0) { + baddr = (curaddr + dmat->dt_boundary) & bmask; + if (sgsize > (baddr - curaddr)) + sgsize = (baddr - curaddr); + } + + /* + * Insert chunk into a segment, coalescing with + * previous segment if possible. + */ + seg = *segp; + if (seg == -1) { + seg = 0; + segs[seg].ds_addr = curaddr; + segs[seg].ds_len = sgsize; + } else { + if (curaddr == segs[seg].ds_addr + segs[seg].ds_len && + (segs[seg].ds_len + sgsize) <= dmat->dt_maxsegsz && + (dmat->dt_boundary == 0 || + (segs[seg].ds_addr & bmask) == (curaddr & bmask))) + segs[seg].ds_len += sgsize; + else { + if (++seg >= dmat->dt_nsegments) + return (0); + segs[seg].ds_addr = curaddr; + segs[seg].ds_len = sgsize; + } + } + *segp = seg; + return (sgsize); +} + +/* + * Utility function to load a physical buffer. segp contains + * the starting segment on entrace, and the ending segment on exit. + */ +static int +nexus_dmamap_load_phys(bus_dma_tag_t dmat, bus_dmamap_t map, vm_paddr_t buf, + bus_size_t buflen, int flags, bus_dma_segment_t *segs, int *segp) +{ + bus_addr_t curaddr; + bus_size_t sgsize; + + if (segs == NULL) + segs = dmat->dt_segments; + + curaddr = buf; + while (buflen > 0) { + sgsize = MIN(buflen, dmat->dt_maxsegsz); + sgsize = nexus_dmamap_addseg(dmat, map, curaddr, sgsize, segs, + segp); + if (sgsize == 0) + break; + curaddr += sgsize; + buflen -= sgsize; + } + + /* + * Did we fit? + */ + return (buflen != 0 ? EFBIG : 0); /* XXX better return value here? */ +} + +/* + * Utility function to load a linear buffer. segp contains + * the starting segment on entrace, and the ending segment on exit. + */ +static int +nexus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, + bus_size_t buflen, pmap_t pmap, int flags, bus_dma_segment_t *segs, + int *segp) { bus_size_t sgsize; - bus_addr_t curaddr, lastaddr, baddr, bmask; + bus_addr_t curaddr; vm_offset_t vaddr = (vm_offset_t)buf; - int seg; - pmap_t pmap; - if (td != NULL) - pmap = vmspace_pmap(td->td_proc->p_vmspace); - else - pmap = NULL; + if (segs == NULL) + segs = dmat->dt_segments; - lastaddr = *lastaddrp; - bmask = ~(dmat->dt_boundary - 1); - - for (seg = *segp; buflen > 0 ; ) { + while (buflen > 0) { /* * Get the physical address for this segment. */ - if (pmap) - curaddr = pmap_extract(pmap, vaddr); - else + if (pmap == kernel_pmap) curaddr = pmap_kextract(vaddr); + else + curaddr = pmap_extract(pmap, vaddr); /* * Compute the segment size, and adjust counts. @@ -368,205 +434,36 @@ _nexus_dmamap_load_buffer(bus_dma_tag_t dmat, void *buf, bus_size_t buflen, if (buflen < sgsize) sgsize = buflen; - /* - * Make sure we don't cross any boundaries. - */ - if (dmat->dt_boundary > 0) { - baddr = (curaddr + dmat->dt_boundary) & bmask; - if (sgsize > (baddr - curaddr)) - sgsize = (baddr - curaddr); - } + sgsize = nexus_dmamap_addseg(dmat, map, curaddr, sgsize, segs, + segp); + if (sgsize == 0) + break; - /* - * Insert chunk into a segment, coalescing with - * previous segment if possible. - */ - if (first) { - segs[seg].ds_addr = curaddr; - segs[seg].ds_len = sgsize; - first = 0; - } else { - if (curaddr == lastaddr && - (segs[seg].ds_len + sgsize) <= dmat->dt_maxsegsz && - (dmat->dt_boundary == 0 || - (segs[seg].ds_addr & bmask) == (curaddr & bmask))) - segs[seg].ds_len += sgsize; - else { - if (++seg >= dmat->dt_nsegments) - break; - segs[seg].ds_addr = curaddr; - segs[seg].ds_len = sgsize; - } - } - - lastaddr = curaddr + sgsize; vaddr += sgsize; buflen -= sgsize; } - *segp = seg; - *lastaddrp = lastaddr; - /* * Did we fit? */ return (buflen != 0 ? EFBIG : 0); /* XXX better return value here? */ } -/* - * Common function for loading a DMA map with a linear buffer. May - * be called by bus-specific DMA map load functions. - * - * Most SPARCs have IOMMUs in the bus controllers. In those cases - * they only need one segment and will use virtual addresses for DVMA. - * Those bus controllers should intercept these vectors and should - * *NEVER* call nexus_dmamap_load() which is used only by devices that - * bypass DVMA. - */ -static int -nexus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, - bus_size_t buflen, bus_dmamap_callback_t *callback, void *callback_arg, - int flags) +static void +nexus_dmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map, + struct memdesc *mem, bus_dmamap_callback_t *callback, void *callback_arg) { - bus_addr_t lastaddr; - int error, nsegs; - error = _nexus_dmamap_load_buffer(dmat, buf, buflen, NULL, flags, - &lastaddr, dmat->dt_segments, &nsegs, 1); - - if (error == 0) { - (*callback)(callback_arg, dmat->dt_segments, nsegs + 1, 0); - map->dm_flags |= DMF_LOADED; - } else - (*callback)(callback_arg, NULL, 0, error); - - return (0); } -/* - * Like nexus_dmamap_load(), but for mbufs. - */ -static int -nexus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m0, - bus_dmamap_callback2_t *callback, void *callback_arg, int flags) +static bus_dma_segment_t * +nexus_dmamap_complete(bus_dma_tag_t dmat, bus_dmamap_t map, + bus_dma_segment_t *segs, int nsegs, int error) { - int nsegs, error; - M_ASSERTPKTHDR(m0); - - nsegs = 0; - error = 0; - if (m0->m_pkthdr.len <= dmat->dt_maxsize) { - int first = 1; - bus_addr_t lastaddr = 0; - struct mbuf *m; - - for (m = m0; m != NULL && error == 0; m = m->m_next) { - if (m->m_len > 0) { - error = _nexus_dmamap_load_buffer(dmat, - m->m_data, m->m_len,NULL, flags, &lastaddr, - dmat->dt_segments, &nsegs, first); - first = 0; - } - } - } else { - error = EINVAL; - } - - if (error) { - /* force "no valid mappings" in callback */ - (*callback)(callback_arg, dmat->dt_segments, 0, 0, error); - } else { - map->dm_flags |= DMF_LOADED; - (*callback)(callback_arg, dmat->dt_segments, nsegs + 1, - m0->m_pkthdr.len, error); - } - return (error); -} - -static int -nexus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m0, - bus_dma_segment_t *segs, int *nsegs, int flags) -{ - int error; - - M_ASSERTPKTHDR(m0); - - *nsegs = 0; - error = 0; - if (m0->m_pkthdr.len <= dmat->dt_maxsize) { - int first = 1; - bus_addr_t lastaddr = 0; - struct mbuf *m; - - for (m = m0; m != NULL && error == 0; m = m->m_next) { - if (m->m_len > 0) { - error = _nexus_dmamap_load_buffer(dmat, - m->m_data, m->m_len,NULL, flags, &lastaddr, - segs, nsegs, first); - first = 0; - } - } - } else { - error = EINVAL; - } - - ++*nsegs; - return (error); -} - -/* - * Like nexus_dmamap_load(), but for uios. - */ -static int -nexus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, struct uio *uio, - bus_dmamap_callback2_t *callback, void *callback_arg, int flags) -{ - bus_addr_t lastaddr; - int nsegs, error, first, i; - bus_size_t resid; - struct iovec *iov; - struct thread *td = NULL; - - resid = uio->uio_resid; - iov = uio->uio_iov; - - if (uio->uio_segflg == UIO_USERSPACE) { - td = uio->uio_td; - KASSERT(td != NULL, ("%s: USERSPACE but no proc", __func__)); - } - - nsegs = 0; - error = 0; - first = 1; - for (i = 0; i < uio->uio_iovcnt && resid != 0 && !error; i++) { - /* - * Now at the first iovec to load. Load each iovec - * until we have exhausted the residual count. - */ - bus_size_t minlen = - resid < iov[i].iov_len ? resid : iov[i].iov_len; - caddr_t addr = (caddr_t) iov[i].iov_base; - - if (minlen > 0) { - error = _nexus_dmamap_load_buffer(dmat, addr, minlen, - td, flags, &lastaddr, dmat->dt_segments, &nsegs, - first); - first = 0; - - resid -= minlen; - } - } - - if (error) { - /* force "no valid mappings" in callback */ - (*callback)(callback_arg, dmat->dt_segments, 0, 0, error); - } else { - map->dm_flags |= DMF_LOADED; - (*callback)(callback_arg, dmat->dt_segments, nsegs + 1, - uio->uio_resid, error); - } - return (error); + if (segs == NULL) + segs = dmat->dt_segments; + return (segs); } /* @@ -669,10 +566,10 @@ nexus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) static struct bus_dma_methods nexus_dma_methods = { nexus_dmamap_create, nexus_dmamap_destroy, - nexus_dmamap_load, - nexus_dmamap_load_mbuf, - nexus_dmamap_load_mbuf_sg, - nexus_dmamap_load_uio, + nexus_dmamap_load_phys, + nexus_dmamap_load_buffer, + nexus_dmamap_waitok, + nexus_dmamap_complete, nexus_dmamap_unload, nexus_dmamap_sync, nexus_dmamem_alloc, diff --git a/sys/sparc64/sparc64/iommu.c b/sys/sparc64/sparc64/iommu.c index ace74ec22db..42aa258e88e 100644 --- a/sys/sparc64/sparc64/iommu.c +++ b/sys/sparc64/sparc64/iommu.c @@ -847,31 +847,167 @@ iommu_dvmamap_destroy(bus_dma_tag_t dt, bus_dmamap_t map) } /* - * IOMMU DVMA operations, common to PCI and SBus + * Utility function to load a physical buffer. segp contains + * the starting segment on entrace, and the ending segment on exit. */ static int -iommu_dvmamap_load_buffer(bus_dma_tag_t dt, struct iommu_state *is, - bus_dmamap_t map, void *buf, bus_size_t buflen, struct thread *td, - int flags, bus_dma_segment_t *segs, int *segp, int align) +iommu_dvmamap_load_phys(bus_dma_tag_t dt, bus_dmamap_t map, vm_paddr_t buf, + bus_size_t buflen, int flags, bus_dma_segment_t *segs, int *segp) { bus_addr_t amask, dvmaddr, dvmoffs; bus_size_t sgsize, esize; - vm_offset_t vaddr, voffs; + struct iommu_state *is; + vm_offset_t voffs; vm_paddr_t curaddr; - pmap_t pmap = NULL; int error, firstpg, sgcnt; u_int slot; + is = dt->dt_cookie; + if (*segp == -1) { + if ((map->dm_flags & DMF_LOADED) != 0) { +#ifdef DIAGNOSTIC + printf("%s: map still in use\n", __func__); +#endif + bus_dmamap_unload(dt, map); + } + + /* + * Make sure that the map is not on a queue so that the + * resource list may be safely accessed and modified without + * needing the lock to cover the whole operation. + */ + IS_LOCK(is); + iommu_map_remq(is, map); + IS_UNLOCK(is); + + amask = dt->dt_alignment - 1; + } else + amask = 0; KASSERT(buflen != 0, ("%s: buflen == 0!", __func__)); if (buflen > dt->dt_maxsize) return (EINVAL); - if (td != NULL) - pmap = vmspace_pmap(td->td_proc->p_vmspace); + if (segs == NULL) + segs = dt->dt_segments; + + voffs = buf & IO_PAGE_MASK; + + /* Try to find a slab that is large enough. */ + error = iommu_dvma_vallocseg(dt, is, map, voffs, buflen, amask, + &dvmaddr); + if (error != 0) + return (error); + + sgcnt = *segp; + firstpg = 1; + map->dm_flags &= ~DMF_STREAMED; + map->dm_flags |= iommu_use_streaming(is, map, buflen) != 0 ? + DMF_STREAMED : 0; + for (; buflen > 0; ) { + curaddr = buf; + + /* + * Compute the segment size, and adjust counts. + */ + sgsize = IO_PAGE_SIZE - ((u_long)buf & IO_PAGE_MASK); + if (buflen < sgsize) + sgsize = buflen; + + buflen -= sgsize; + buf += sgsize; + + dvmoffs = trunc_io_page(dvmaddr); + iommu_enter(is, dvmoffs, trunc_io_page(curaddr), + (map->dm_flags & DMF_STREAMED) != 0, flags); + if ((is->is_flags & IOMMU_FLUSH_CACHE) != 0) { + slot = IOTSBSLOT(dvmoffs); + if (buflen <= 0 || slot % 8 == 7) + IOMMU_WRITE8(is, is_iommu, IMR_CACHE_FLUSH, + is->is_ptsb + slot * 8); + } + + /* + * Chop the chunk up into segments of at most maxsegsz, but try + * to fill each segment as well as possible. + */ + if (!firstpg) { + esize = ulmin(sgsize, + dt->dt_maxsegsz - segs[sgcnt].ds_len); + segs[sgcnt].ds_len += esize; + sgsize -= esize; + dvmaddr += esize; + } + while (sgsize > 0) { + sgcnt++; + if (sgcnt >= dt->dt_nsegments) + return (EFBIG); + /* + * No extra alignment here - the common practice in + * the busdma code seems to be that only the first + * segment needs to satisfy the alignment constraints + * (and that only for bus_dmamem_alloc()ed maps). + * It is assumed that such tags have maxsegsize >= + * maxsize. + */ + esize = ulmin(sgsize, dt->dt_maxsegsz); + segs[sgcnt].ds_addr = dvmaddr; + segs[sgcnt].ds_len = esize; + sgsize -= esize; + dvmaddr += esize; + } + + firstpg = 0; + } + *segp = sgcnt; + return (0); +} + +/* + * IOMMU DVMA operations, common to PCI and SBus + */ +static int +iommu_dvmamap_load_buffer(bus_dma_tag_t dt, bus_dmamap_t map, void *buf, + bus_size_t buflen, pmap_t pmap, int flags, bus_dma_segment_t *segs, + int *segp) +{ + bus_addr_t amask, dvmaddr, dvmoffs; + bus_size_t sgsize, esize; + struct iommu_state *is; + vm_offset_t vaddr, voffs; + vm_paddr_t curaddr; + int error, firstpg, sgcnt; + u_int slot; + + is = dt->dt_cookie; + if (*segp == -1) { + if ((map->dm_flags & DMF_LOADED) != 0) { +#ifdef DIAGNOSTIC + printf("%s: map still in use\n", __func__); +#endif + bus_dmamap_unload(dt, map); + } + + /* + * Make sure that the map is not on a queue so that the + * resource list may be safely accessed and modified without + * needing the lock to cover the whole operation. + */ + IS_LOCK(is); + iommu_map_remq(is, map); + IS_UNLOCK(is); + + amask = dt->dt_alignment - 1; + } else + amask = 0; + KASSERT(buflen != 0, ("%s: buflen == 0!", __func__)); + if (buflen > dt->dt_maxsize) + return (EINVAL); + + if (segs == NULL) + segs = dt->dt_segments; vaddr = (vm_offset_t)buf; voffs = vaddr & IO_PAGE_MASK; - amask = align ? dt->dt_alignment - 1 : 0; /* Try to find a slab that is large enough. */ error = iommu_dvma_vallocseg(dt, is, map, voffs, buflen, amask, @@ -888,10 +1024,10 @@ iommu_dvmamap_load_buffer(bus_dma_tag_t dt, struct iommu_state *is, /* * Get the physical address for this page. */ - if (pmap != NULL) - curaddr = pmap_extract(pmap, vaddr); - else + if (pmap == kernel_pmap) curaddr = pmap_kextract(vaddr); + else + curaddr = pmap_extract(pmap, vaddr); /* * Compute the segment size, and adjust counts. @@ -949,129 +1085,17 @@ iommu_dvmamap_load_buffer(bus_dma_tag_t dt, struct iommu_state *is, return (0); } -static int -iommu_dvmamap_load(bus_dma_tag_t dt, bus_dmamap_t map, void *buf, - bus_size_t buflen, bus_dmamap_callback_t *cb, void *cba, - int flags) +static void +iommu_dvmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map, + struct memdesc *mem, bus_dmamap_callback_t *callback, void *callback_arg) { - struct iommu_state *is = dt->dt_cookie; - int error, seg = -1; - - if ((map->dm_flags & DMF_LOADED) != 0) { -#ifdef DIAGNOSTIC - printf("%s: map still in use\n", __func__); -#endif - bus_dmamap_unload(dt, map); - } - - /* - * Make sure that the map is not on a queue so that the resource list - * may be safely accessed and modified without needing the lock to - * cover the whole operation. - */ - IS_LOCK(is); - iommu_map_remq(is, map); - IS_UNLOCK(is); - - error = iommu_dvmamap_load_buffer(dt, is, map, buf, buflen, NULL, - flags, dt->dt_segments, &seg, 1); - - IS_LOCK(is); - iommu_map_insq(is, map); - if (error != 0) { - iommu_dvmamap_vunload(is, map); - IS_UNLOCK(is); - (*cb)(cba, dt->dt_segments, 0, error); - } else { - IS_UNLOCK(is); - map->dm_flags |= DMF_LOADED; - (*cb)(cba, dt->dt_segments, seg + 1, 0); - } - - return (error); } -static int -iommu_dvmamap_load_mbuf(bus_dma_tag_t dt, bus_dmamap_t map, struct mbuf *m0, - bus_dmamap_callback2_t *cb, void *cba, int flags) +static bus_dma_segment_t * +iommu_dvmamap_complete(bus_dma_tag_t dt, bus_dmamap_t map, + bus_dma_segment_t *segs, int nsegs, int error) { struct iommu_state *is = dt->dt_cookie; - struct mbuf *m; - int error = 0, first = 1, nsegs = -1; - - M_ASSERTPKTHDR(m0); - - if ((map->dm_flags & DMF_LOADED) != 0) { -#ifdef DIAGNOSTIC - printf("%s: map still in use\n", __func__); -#endif - bus_dmamap_unload(dt, map); - } - - IS_LOCK(is); - iommu_map_remq(is, map); - IS_UNLOCK(is); - - if (m0->m_pkthdr.len <= dt->dt_maxsize) { - for (m = m0; m != NULL && error == 0; m = m->m_next) { - if (m->m_len == 0) - continue; - error = iommu_dvmamap_load_buffer(dt, is, map, - m->m_data, m->m_len, NULL, flags, dt->dt_segments, - &nsegs, first); - first = 0; - } - } else - error = EINVAL; - - IS_LOCK(is); - iommu_map_insq(is, map); - if (error != 0) { - iommu_dvmamap_vunload(is, map); - IS_UNLOCK(is); - /* force "no valid mappings" in callback */ - (*cb)(cba, dt->dt_segments, 0, 0, error); - } else { - IS_UNLOCK(is); - map->dm_flags |= DMF_LOADED; - (*cb)(cba, dt->dt_segments, nsegs + 1, m0->m_pkthdr.len, 0); - } - return (error); -} - -static int -iommu_dvmamap_load_mbuf_sg(bus_dma_tag_t dt, bus_dmamap_t map, struct mbuf *m0, - bus_dma_segment_t *segs, int *nsegs, int flags) -{ - struct iommu_state *is = dt->dt_cookie; - struct mbuf *m; - int error = 0, first = 1; - - M_ASSERTPKTHDR(m0); - - *nsegs = -1; - if ((map->dm_flags & DMF_LOADED) != 0) { -#ifdef DIAGNOSTIC - printf("%s: map still in use\n", __func__); -#endif - bus_dmamap_unload(dt, map); - } - - IS_LOCK(is); - iommu_map_remq(is, map); - IS_UNLOCK(is); - - if (m0->m_pkthdr.len <= dt->dt_maxsize) { - for (m = m0; m != NULL && error == 0; m = m->m_next) { - if (m->m_len == 0) - continue; - error = iommu_dvmamap_load_buffer(dt, is, map, - m->m_data, m->m_len, NULL, flags, segs, - nsegs, first); - first = 0; - } - } else - error = EINVAL; IS_LOCK(is); iommu_map_insq(is, map); @@ -1081,71 +1105,10 @@ iommu_dvmamap_load_mbuf_sg(bus_dma_tag_t dt, bus_dmamap_t map, struct mbuf *m0, } else { IS_UNLOCK(is); map->dm_flags |= DMF_LOADED; - ++*nsegs; } - return (error); -} - -static int -iommu_dvmamap_load_uio(bus_dma_tag_t dt, bus_dmamap_t map, struct uio *uio, - bus_dmamap_callback2_t *cb, void *cba, int flags) -{ - struct iommu_state *is = dt->dt_cookie; - struct iovec *iov; - struct thread *td = NULL; - bus_size_t minlen, resid; - int nsegs = -1, error = 0, first = 1, i; - - if ((map->dm_flags & DMF_LOADED) != 0) { -#ifdef DIAGNOSTIC - printf("%s: map still in use\n", __func__); -#endif - bus_dmamap_unload(dt, map); - } - - IS_LOCK(is); - iommu_map_remq(is, map); - IS_UNLOCK(is); - - resid = uio->uio_resid; - iov = uio->uio_iov; - - if (uio->uio_segflg == UIO_USERSPACE) { - td = uio->uio_td; - KASSERT(td != NULL, - ("%s: USERSPACE but no proc", __func__)); - } - - for (i = 0; i < uio->uio_iovcnt && resid != 0 && error == 0; i++) { - /* - * Now at the first iovec to load. Load each iovec - * until we have exhausted the residual count. - */ - minlen = resid < iov[i].iov_len ? resid : iov[i].iov_len; - if (minlen == 0) - continue; - - error = iommu_dvmamap_load_buffer(dt, is, map, - iov[i].iov_base, minlen, td, flags, dt->dt_segments, - &nsegs, first); - first = 0; - - resid -= minlen; - } - - IS_LOCK(is); - iommu_map_insq(is, map); - if (error) { - iommu_dvmamap_vunload(is, map); - IS_UNLOCK(is); - /* force "no valid mappings" in callback */ - (*cb)(cba, dt->dt_segments, 0, 0, error); - } else { - IS_UNLOCK(is); - map->dm_flags |= DMF_LOADED; - (*cb)(cba, dt->dt_segments, nsegs + 1, uio->uio_resid, 0); - } - return (error); + if (segs == NULL) + segs = dt->dt_segments; + return (segs); } static void @@ -1241,10 +1204,10 @@ iommu_diag(struct iommu_state *is, vm_offset_t va) struct bus_dma_methods iommu_dma_methods = { iommu_dvmamap_create, iommu_dvmamap_destroy, - iommu_dvmamap_load, - iommu_dvmamap_load_mbuf, - iommu_dvmamap_load_mbuf_sg, - iommu_dvmamap_load_uio, + iommu_dvmamap_load_phys, + iommu_dvmamap_load_buffer, + iommu_dvmamap_waitok, + iommu_dvmamap_complete, iommu_dvmamap_unload, iommu_dvmamap_sync, iommu_dvmamem_alloc, diff --git a/sys/sys/bus_dma.h b/sys/sys/bus_dma.h index 915d0658fea..2be6c7fff09 100644 --- a/sys/sys/bus_dma.h +++ b/sys/sys/bus_dma.h @@ -109,8 +109,14 @@ */ #define BUS_DMA_KEEP_PG_OFFSET 0x400 +#define BUS_DMA_LOAD_MBUF 0x800 + /* Forwards needed by prototypes below. */ +union ccb; +struct bio; struct mbuf; +struct memdesc; +struct pmap; struct uio; /* @@ -190,6 +196,49 @@ typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int); */ typedef void bus_dmamap_callback2_t(void *, bus_dma_segment_t *, int, bus_size_t, int); +/* + * Map the buffer buf into bus space using the dmamap map. + */ +int bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, + bus_size_t buflen, bus_dmamap_callback_t *callback, + void *callback_arg, int flags); + +/* + * Like bus_dmamap_load but for mbufs. Note the use of the + * bus_dmamap_callback2_t interface. + */ +int bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, + struct mbuf *mbuf, + bus_dmamap_callback2_t *callback, void *callback_arg, + int flags); + +int bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map, + struct mbuf *mbuf, bus_dma_segment_t *segs, + int *nsegs, int flags); + +/* + * Like bus_dmamap_load but for uios. Note the use of the + * bus_dmamap_callback2_t interface. + */ +int bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, + struct uio *ui, + bus_dmamap_callback2_t *callback, void *callback_arg, + int flags); + +/* + * Like bus_dmamap_load but for cam control blocks. + */ +int bus_dmamap_load_ccb(bus_dma_tag_t dmat, bus_dmamap_t map, union ccb *ccb, + bus_dmamap_callback_t *callback, void *callback_arg, + int flags); + +/* + * Loads any memory descriptor. + */ +int bus_dmamap_load_mem(bus_dma_tag_t dmat, bus_dmamap_t map, + struct memdesc *mem, bus_dmamap_callback_t *callback, + void *callback_arg, int flags); + /* * XXX sparc64 uses the same interface, but a much different implementation. * for the sparc64 arch contains the equivalent @@ -223,35 +272,6 @@ int bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, */ void bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map); -/* - * Map the buffer buf into bus space using the dmamap map. - */ -int bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, - bus_size_t buflen, bus_dmamap_callback_t *callback, - void *callback_arg, int flags); - -/* - * Like bus_dmamap_load but for mbufs. Note the use of the - * bus_dmamap_callback2_t interface. - */ -int bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, - struct mbuf *mbuf, - bus_dmamap_callback2_t *callback, void *callback_arg, - int flags); - -int bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map, - struct mbuf *mbuf, bus_dma_segment_t *segs, - int *nsegs, int flags); - -/* - * Like bus_dmamap_load but for uios. Note the use of the - * bus_dmamap_callback2_t interface. - */ -int bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, - struct uio *ui, - bus_dmamap_callback2_t *callback, void *callback_arg, - int flags); - /* * Perform a synchronization operation on the given map. */ @@ -272,6 +292,36 @@ void _bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map); _bus_dmamap_unload(dmat, dmamap); \ } while (0) +/* + * The following functions define the interface between the MD and MI + * busdma layers. These are not intended for consumption by driver + * software. + */ +void __bus_dmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map, + struct memdesc *mem, + bus_dmamap_callback_t *callback, + void *callback_arg); + +#define _bus_dmamap_waitok(dmat, map, mem, callback, callback_arg) \ + do { \ + if ((map) != NULL) \ + __bus_dmamap_waitok(dmat, map, mem, callback, \ + callback_arg); \ + } while (0); + +int _bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dmamap_t map, + void *buf, bus_size_t buflen, struct pmap *pmap, + int flags, bus_dma_segment_t *segs, int *segp); + +int _bus_dmamap_load_phys(bus_dma_tag_t dmat, bus_dmamap_t map, + vm_paddr_t paddr, bus_size_t buflen, + int flags, bus_dma_segment_t *segs, int *segp); + +bus_dma_segment_t *_bus_dmamap_complete(bus_dma_tag_t dmat, + bus_dmamap_t map, + bus_dma_segment_t *segs, + int nsegs, int error); + #endif /* __sparc64__ */ #endif /* _BUS_DMA_H_ */ diff --git a/sys/sys/memdesc.h b/sys/sys/memdesc.h new file mode 100644 index 00000000000..8e9f7dd66d5 --- /dev/null +++ b/sys/sys/memdesc.h @@ -0,0 +1,156 @@ +/*- + * Copyright (c) 2012 EMC Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, 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 _SYS_MEMDESC_H_ +#define _SYS_MEMDESC_H_ + +struct bio; +struct bus_dma_segment; +struct uio; +struct mbuf; +union ccb; + +/* + * struct memdesc encapsulates various memory descriptors and provides + * abstract access to them. + */ +struct memdesc { + union { + void *md_vaddr; + vm_paddr_t md_paddr; + struct bus_dma_segment *md_list; + struct bio *md_bio; + struct uio *md_uio; + struct mbuf *md_mbuf; + union ccb *md_ccb; + } u; + size_t md_opaque; /* type specific data. */ + uint32_t md_type; /* Type of memory. */ +}; + +#define MEMDESC_VADDR 1 /* Contiguous virtual address. */ +#define MEMDESC_PADDR 2 /* Contiguous physical address. */ +#define MEMDESC_VLIST 3 /* scatter/gather list of kva addresses. */ +#define MEMDESC_PLIST 4 /* scatter/gather list of physical addresses. */ +#define MEMDESC_BIO 5 /* Pointer to a bio (block io). */ +#define MEMDESC_UIO 6 /* Pointer to a uio (any io). */ +#define MEMDESC_MBUF 7 /* Pointer to a mbuf (network io). */ +#define MEMDESC_CCB 8 /* Cam control block. (scsi/ata io). */ + +static inline struct memdesc +memdesc_vaddr(void *vaddr, size_t len) +{ + struct memdesc mem; + + mem.u.md_vaddr = vaddr; + mem.md_opaque = len; + mem.md_type = MEMDESC_VADDR; + + return (mem); +} + +static inline struct memdesc +memdesc_paddr(vm_paddr_t paddr, size_t len) +{ + struct memdesc mem; + + mem.u.md_paddr = paddr; + mem.md_opaque = len; + mem.md_type = MEMDESC_PADDR; + + return (mem); +} + +static inline struct memdesc +memdesc_vlist(struct bus_dma_segment *vlist, int sglist_cnt) +{ + struct memdesc mem; + + mem.u.md_list = vlist; + mem.md_opaque = sglist_cnt; + mem.md_type = MEMDESC_VLIST; + + return (mem); +} + +static inline struct memdesc +memdesc_plist(struct bus_dma_segment *plist, int sglist_cnt) +{ + struct memdesc mem; + + mem.u.md_list = plist; + mem.md_opaque = sglist_cnt; + mem.md_type = MEMDESC_PLIST; + + return (mem); +} + +static inline struct memdesc +memdesc_bio(struct bio *bio) +{ + struct memdesc mem; + + mem.u.md_bio = bio; + mem.md_type = MEMDESC_BIO; + + return (mem); +} + +static inline struct memdesc +memdesc_uio(struct uio *uio) +{ + struct memdesc mem; + + mem.u.md_uio = uio; + mem.md_type = MEMDESC_UIO; + + return (mem); +} + +static inline struct memdesc +memdesc_mbuf(struct mbuf *mbuf) +{ + struct memdesc mem; + + mem.u.md_mbuf = mbuf; + mem.md_type = MEMDESC_MBUF; + + return (mem); +} + +static inline struct memdesc +memdesc_ccb(union ccb *ccb) +{ + struct memdesc mem; + + mem.u.md_ccb = ccb; + mem.md_type = MEMDESC_CCB; + + return (mem); +} +#endif /* _SYS_MEMDESC_H_ */ diff --git a/sys/sys/uio.h b/sys/sys/uio.h index f3cc20f84e4..8a594f36dbb 100644 --- a/sys/sys/uio.h +++ b/sys/sys/uio.h @@ -96,6 +96,8 @@ int copyinstrfrom(const void * __restrict src, void * __restrict dst, int copyinuio(const struct iovec *iovp, u_int iovcnt, struct uio **uiop); int copyout_map(struct thread *td, vm_offset_t *addr, size_t sz); int copyout_unmap(struct thread *td, vm_offset_t addr, size_t sz); +int physcopyin(void *src, vm_paddr_t dst, size_t len); +int physcopyout(vm_paddr_t src, void *dst, size_t len); int uiomove(void *cp, int n, struct uio *uio); int uiomove_frombuf(void *buf, int buflen, struct uio *uio); int uiomove_fromphys(struct vm_page *ma[], vm_offset_t offset, int n, diff --git a/sys/x86/x86/busdma_machdep.c b/sys/x86/x86/busdma_machdep.c index ffa8807f2d3..d7a083fdf6d 100644 --- a/sys/x86/x86/busdma_machdep.c +++ b/sys/x86/x86/busdma_machdep.c @@ -36,10 +36,10 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include -#include -#include #include +#include #include #include @@ -86,6 +86,7 @@ struct bounce_page { vm_offset_t vaddr; /* kva of bounce buffer */ bus_addr_t busaddr; /* Physical address */ vm_offset_t datavaddr; /* kva of client data */ + bus_addr_t dataaddr; /* client physical address */ bus_size_t datacount; /* client data count */ STAILQ_ENTRY(bounce_page) links; }; @@ -124,8 +125,7 @@ struct bus_dmamap { int pagesneeded; int pagesreserved; bus_dma_tag_t dmat; - void *buf; /* unmapped buffer pointer */ - bus_size_t buflen; /* unmapped buffer length */ + struct memdesc mem; bus_dmamap_callback_t *callback; void *callback_arg; STAILQ_ENTRY(bus_dmamap) links; @@ -141,11 +141,18 @@ static int alloc_bounce_pages(bus_dma_tag_t dmat, u_int numpages); static int reserve_bounce_pages(bus_dma_tag_t dmat, bus_dmamap_t map, int commit); static bus_addr_t add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, - vm_offset_t vaddr, bus_size_t size); + vm_offset_t vaddr, bus_addr_t addr, + bus_size_t size); static void free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage); int run_filter(bus_dma_tag_t dmat, bus_addr_t paddr); -int _bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map, pmap_t pmap, - void *buf, bus_size_t buflen, int flags); +static void _bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map, + pmap_t pmap, void *buf, bus_size_t buflen, + int flags); +static void _bus_dmamap_count_phys(bus_dma_tag_t dmat, bus_dmamap_t map, + vm_paddr_t buf, bus_size_t buflen, + int flags); +static int _bus_dmamap_reserve_pages(bus_dma_tag_t dmat, bus_dmamap_t map, + int flags); #ifdef XEN #undef pmap_kextract @@ -579,7 +586,33 @@ bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) CTR3(KTR_BUSDMA, "%s: tag %p flags 0x%x", __func__, dmat, dmat->flags); } -int +static void +_bus_dmamap_count_phys(bus_dma_tag_t dmat, bus_dmamap_t map, vm_paddr_t buf, + bus_size_t buflen, int flags) +{ + bus_addr_t curaddr; + bus_size_t sgsize; + + if ((map != &nobounce_dmamap && map->pagesneeded == 0)) { + /* + * Count the number of bounce pages + * needed in order to complete this transfer + */ + curaddr = buf; + while (buflen != 0) { + sgsize = MIN(buflen, dmat->maxsegsz); + if (run_filter(dmat, curaddr)) { + sgsize = MIN(sgsize, PAGE_SIZE); + map->pagesneeded++; + } + curaddr += sgsize; + buflen -= sgsize; + } + CTR1(KTR_BUSDMA, "pagesneeded= %d\n", map->pagesneeded); + } +} + +static void _bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map, pmap_t pmap, void *buf, bus_size_t buflen, int flags) { @@ -604,12 +637,11 @@ _bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map, pmap_t pmap, bus_size_t sg_len; sg_len = PAGE_SIZE - ((vm_offset_t)vaddr & PAGE_MASK); - if (pmap) - paddr = pmap_extract(pmap, vaddr); - else + if (pmap == kernel_pmap) paddr = pmap_kextract(vaddr); - if (((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) && - run_filter(dmat, paddr) != 0) { + else + paddr = pmap_extract(pmap, vaddr); + if (run_filter(dmat, paddr) != 0) { sg_len = roundup2(sg_len, dmat->alignment); map->pagesneeded++; } @@ -617,78 +649,177 @@ _bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map, pmap_t pmap, } CTR1(KTR_BUSDMA, "pagesneeded= %d\n", map->pagesneeded); } +} + +static int +_bus_dmamap_reserve_pages(bus_dma_tag_t dmat, bus_dmamap_t map, int flags) +{ /* Reserve Necessary Bounce Pages */ - if (map->pagesneeded != 0) { - mtx_lock(&bounce_lock); - if (flags & BUS_DMA_NOWAIT) { - if (reserve_bounce_pages(dmat, map, 0) != 0) { - mtx_unlock(&bounce_lock); - return (ENOMEM); - } - } else { - if (reserve_bounce_pages(dmat, map, 1) != 0) { - /* Queue us for resources */ - map->dmat = dmat; - map->buf = buf; - map->buflen = buflen; - STAILQ_INSERT_TAIL(&bounce_map_waitinglist, - map, links); - mtx_unlock(&bounce_lock); - return (EINPROGRESS); - } + mtx_lock(&bounce_lock); + if (flags & BUS_DMA_NOWAIT) { + if (reserve_bounce_pages(dmat, map, 0) != 0) { + mtx_unlock(&bounce_lock); + return (ENOMEM); + } + } else { + if (reserve_bounce_pages(dmat, map, 1) != 0) { + /* Queue us for resources */ + STAILQ_INSERT_TAIL(&bounce_map_waitinglist, map, links); + mtx_unlock(&bounce_lock); + return (EINPROGRESS); } - mtx_unlock(&bounce_lock); } + mtx_unlock(&bounce_lock); return (0); } /* - * Utility function to load a linear buffer. lastaddrp holds state - * between invocations (for multiple-buffer loads). segp contains - * the starting segment on entrace, and the ending segment on exit. - * first indicates if this is the first invocation of this function. + * Add a single contiguous physical range to the segment list. */ -static __inline int -_bus_dmamap_load_buffer(bus_dma_tag_t dmat, - bus_dmamap_t map, - void *buf, bus_size_t buflen, - pmap_t pmap, - int flags, - bus_addr_t *lastaddrp, - bus_dma_segment_t *segs, - int *segp, - int first) +static int +_bus_dmamap_addseg(bus_dma_tag_t dmat, bus_dmamap_t map, bus_addr_t curaddr, + bus_size_t sgsize, bus_dma_segment_t *segs, int *segp) +{ + bus_addr_t baddr, bmask; + int seg; + + /* + * Make sure we don't cross any boundaries. + */ + bmask = ~(dmat->boundary - 1); + if (dmat->boundary > 0) { + baddr = (curaddr + dmat->boundary) & bmask; + if (sgsize > (baddr - curaddr)) + sgsize = (baddr - curaddr); + } + + /* + * Insert chunk into a segment, coalescing with + * previous segment if possible. + */ + seg = *segp; + if (seg == -1) { + seg = 0; + segs[seg].ds_addr = curaddr; + segs[seg].ds_len = sgsize; + } else { + if (curaddr == segs[seg].ds_addr + segs[seg].ds_len && + (segs[seg].ds_len + sgsize) <= dmat->maxsegsz && + (dmat->boundary == 0 || + (segs[seg].ds_addr & bmask) == (curaddr & bmask))) + segs[seg].ds_len += sgsize; + else { + if (++seg >= dmat->nsegments) + return (0); + segs[seg].ds_addr = curaddr; + segs[seg].ds_len = sgsize; + } + } + *segp = seg; + return (sgsize); +} + +/* + * Utility function to load a physical buffer. segp contains + * the starting segment on entrace, and the ending segment on exit. + */ +int +_bus_dmamap_load_phys(bus_dma_tag_t dmat, + bus_dmamap_t map, + vm_paddr_t buf, bus_size_t buflen, + int flags, + bus_dma_segment_t *segs, + int *segp) { bus_size_t sgsize; - bus_addr_t curaddr, lastaddr, baddr, bmask; - vm_offset_t vaddr; - int seg, error; + bus_addr_t curaddr; + int error; if (map == NULL || map == &contig_dmamap) map = &nobounce_dmamap; + if (segs == NULL) + segs = dmat->segments; + if ((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) { - error = _bus_dmamap_count_pages(dmat, map, pmap, buf, buflen, flags); - if (error) - return (error); + _bus_dmamap_count_phys(dmat, map, buf, buflen, flags); + if (map->pagesneeded != 0) { + error = _bus_dmamap_reserve_pages(dmat, map, flags); + if (error) + return (error); + } + } + + while (buflen > 0) { + curaddr = buf; + sgsize = MIN(buflen, dmat->maxsegsz); + if (((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) && + map->pagesneeded != 0 && run_filter(dmat, curaddr)) { + sgsize = MIN(sgsize, PAGE_SIZE); + curaddr = add_bounce_page(dmat, map, 0, curaddr, + sgsize); + } + sgsize = _bus_dmamap_addseg(dmat, map, curaddr, sgsize, segs, + segp); + if (sgsize == 0) + break; + buf += sgsize; + buflen -= sgsize; + } + + /* + * Did we fit? + */ + return (buflen != 0 ? EFBIG : 0); /* XXX better return value here? */ +} + +/* + * Utility function to load a linear buffer. segp contains + * the starting segment on entrace, and the ending segment on exit. + */ +int +_bus_dmamap_load_buffer(bus_dma_tag_t dmat, + bus_dmamap_t map, + void *buf, bus_size_t buflen, + pmap_t pmap, + int flags, + bus_dma_segment_t *segs, + int *segp) +{ + bus_size_t sgsize; + bus_addr_t curaddr; + vm_offset_t vaddr; + int error; + + if (map == NULL || map == &contig_dmamap) + map = &nobounce_dmamap; + + if (segs == NULL) + segs = dmat->segments; + + if ((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) { + _bus_dmamap_count_pages(dmat, map, pmap, buf, buflen, flags); + if (map->pagesneeded != 0) { + error = _bus_dmamap_reserve_pages(dmat, map, flags); + if (error) + return (error); + } } vaddr = (vm_offset_t)buf; - lastaddr = *lastaddrp; - bmask = ~(dmat->boundary - 1); - for (seg = *segp; buflen > 0 ; ) { + while (buflen > 0) { bus_size_t max_sgsize; /* * Get the physical address for this segment. */ - if (pmap) - curaddr = pmap_extract(pmap, vaddr); - else + if (pmap == kernel_pmap) curaddr = pmap_kextract(vaddr); + else + curaddr = pmap_extract(pmap, vaddr); /* * Compute the segment size, and adjust counts. @@ -699,228 +830,46 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dmat, map->pagesneeded != 0 && run_filter(dmat, curaddr)) { sgsize = roundup2(sgsize, dmat->alignment); sgsize = MIN(sgsize, max_sgsize); - curaddr = add_bounce_page(dmat, map, vaddr, sgsize); + curaddr = add_bounce_page(dmat, map, vaddr, curaddr, + sgsize); } else { sgsize = MIN(sgsize, max_sgsize); } - - /* - * Make sure we don't cross any boundaries. - */ - if (dmat->boundary > 0) { - baddr = (curaddr + dmat->boundary) & bmask; - if (sgsize > (baddr - curaddr)) - sgsize = (baddr - curaddr); - } - - /* - * Insert chunk into a segment, coalescing with - * previous segment if possible. - */ - if (first) { - segs[seg].ds_addr = curaddr; - segs[seg].ds_len = sgsize; - first = 0; - } else { - if (curaddr == lastaddr && - (segs[seg].ds_len + sgsize) <= dmat->maxsegsz && - (dmat->boundary == 0 || - (segs[seg].ds_addr & bmask) == (curaddr & bmask))) - segs[seg].ds_len += sgsize; - else { - if (++seg >= dmat->nsegments) - break; - segs[seg].ds_addr = curaddr; - segs[seg].ds_len = sgsize; - } - } - - lastaddr = curaddr + sgsize; + sgsize = _bus_dmamap_addseg(dmat, map, curaddr, sgsize, segs, + segp); + if (sgsize == 0) + break; vaddr += sgsize; buflen -= sgsize; } - *segp = seg; - *lastaddrp = lastaddr; - /* * Did we fit? */ return (buflen != 0 ? EFBIG : 0); /* XXX better return value here? */ } -/* - * Map the buffer buf into bus space using the dmamap map. - */ -int -bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, - bus_size_t buflen, bus_dmamap_callback_t *callback, - void *callback_arg, int flags) +void +__bus_dmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map, + struct memdesc *mem, bus_dmamap_callback_t *callback, + void *callback_arg) { - bus_addr_t lastaddr = 0; - int error, nsegs = 0; - if (map != NULL) { - flags |= BUS_DMA_WAITOK; + map->mem = *mem; + map->dmat = dmat; map->callback = callback; map->callback_arg = callback_arg; } - - error = _bus_dmamap_load_buffer(dmat, map, buf, buflen, NULL, flags, - &lastaddr, dmat->segments, &nsegs, 1); - - CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", - __func__, dmat, dmat->flags, error, nsegs + 1); - - if (error == EINPROGRESS) { - return (error); - } - - if (error) - (*callback)(callback_arg, dmat->segments, 0, error); - else - (*callback)(callback_arg, dmat->segments, nsegs + 1, 0); - - /* - * Return ENOMEM to the caller so that it can pass it up the stack. - * This error only happens when NOWAIT is set, so deferal is disabled. - */ - if (error == ENOMEM) - return (error); - - return (0); } - -/* - * Like _bus_dmamap_load(), but for mbufs. - */ -static __inline int -_bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map, - struct mbuf *m0, bus_dma_segment_t *segs, int *nsegs, - int flags) +bus_dma_segment_t * +_bus_dmamap_complete(bus_dma_tag_t dmat, bus_dmamap_t map, + bus_dma_segment_t *segs, int nsegs, int error) { - int error; - M_ASSERTPKTHDR(m0); - - flags |= BUS_DMA_NOWAIT; - *nsegs = 0; - error = 0; - if (m0->m_pkthdr.len <= dmat->maxsize) { - int first = 1; - bus_addr_t lastaddr = 0; - struct mbuf *m; - - for (m = m0; m != NULL && error == 0; m = m->m_next) { - if (m->m_len > 0) { - error = _bus_dmamap_load_buffer(dmat, map, - m->m_data, m->m_len, - NULL, flags, &lastaddr, - segs, nsegs, first); - first = 0; - } - } - } else { - error = EINVAL; - } - - /* XXX FIXME: Having to increment nsegs is really annoying */ - ++*nsegs; - CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", - __func__, dmat, dmat->flags, error, *nsegs); - return (error); -} - -int -bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, - struct mbuf *m0, - bus_dmamap_callback2_t *callback, void *callback_arg, - int flags) -{ - int nsegs, error; - - error = _bus_dmamap_load_mbuf_sg(dmat, map, m0, dmat->segments, &nsegs, - flags); - - if (error) { - /* force "no valid mappings" in callback */ - (*callback)(callback_arg, dmat->segments, 0, 0, error); - } else { - (*callback)(callback_arg, dmat->segments, - nsegs, m0->m_pkthdr.len, error); - } - CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", - __func__, dmat, dmat->flags, error, nsegs); - return (error); -} - -int -bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map, - struct mbuf *m0, bus_dma_segment_t *segs, int *nsegs, - int flags) -{ - return (_bus_dmamap_load_mbuf_sg(dmat, map, m0, segs, nsegs, flags)); -} - -/* - * Like _bus_dmamap_load(), but for uios. - */ -int -bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, - struct uio *uio, - bus_dmamap_callback2_t *callback, void *callback_arg, - int flags) -{ - bus_addr_t lastaddr = 0; - int nsegs, error, first, i; - bus_size_t resid; - struct iovec *iov; - pmap_t pmap; - - flags |= BUS_DMA_NOWAIT; - resid = uio->uio_resid; - iov = uio->uio_iov; - - if (uio->uio_segflg == UIO_USERSPACE) { - KASSERT(uio->uio_td != NULL, - ("bus_dmamap_load_uio: USERSPACE but no proc")); - pmap = vmspace_pmap(uio->uio_td->td_proc->p_vmspace); - } else - pmap = NULL; - - nsegs = 0; - error = 0; - first = 1; - for (i = 0; i < uio->uio_iovcnt && resid != 0 && !error; i++) { - /* - * Now at the first iovec to load. Load each iovec - * until we have exhausted the residual count. - */ - bus_size_t minlen = - resid < iov[i].iov_len ? resid : iov[i].iov_len; - caddr_t addr = (caddr_t) iov[i].iov_base; - - if (minlen > 0) { - error = _bus_dmamap_load_buffer(dmat, map, - addr, minlen, pmap, flags, &lastaddr, - dmat->segments, &nsegs, first); - first = 0; - - resid -= minlen; - } - } - - if (error) { - /* force "no valid mappings" in callback */ - (*callback)(callback_arg, dmat->segments, 0, 0, error); - } else { - (*callback)(callback_arg, dmat->segments, - nsegs+1, uio->uio_resid, error); - } - CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", - __func__, dmat, dmat->flags, error, nsegs + 1); - return (error); + if (segs == NULL) + segs = dmat->segments; + return (segs); } /* @@ -953,9 +902,14 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op) if (op & BUS_DMASYNC_PREWRITE) { while (bpage != NULL) { - bcopy((void *)bpage->datavaddr, - (void *)bpage->vaddr, - bpage->datacount); + if (bpage->datavaddr != 0) + bcopy((void *)bpage->datavaddr, + (void *)bpage->vaddr, + bpage->datacount); + else + physcopyout(bpage->dataaddr, + (void *)bpage->vaddr, + bpage->datacount); bpage = STAILQ_NEXT(bpage, links); } dmat->bounce_zone->total_bounced++; @@ -963,9 +917,14 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op) if (op & BUS_DMASYNC_POSTREAD) { while (bpage != NULL) { - bcopy((void *)bpage->vaddr, - (void *)bpage->datavaddr, - bpage->datacount); + if (bpage->datavaddr != 0) + bcopy((void *)bpage->vaddr, + (void *)bpage->datavaddr, + bpage->datacount); + else + physcopyin((void *)bpage->vaddr, + bpage->dataaddr, + bpage->datacount); bpage = STAILQ_NEXT(bpage, links); } dmat->bounce_zone->total_bounced++; @@ -1137,7 +1096,7 @@ reserve_bounce_pages(bus_dma_tag_t dmat, bus_dmamap_t map, int commit) static bus_addr_t add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, vm_offset_t vaddr, - bus_size_t size) + bus_addr_t addr, bus_size_t size) { struct bounce_zone *bz; struct bounce_page *bpage; @@ -1171,6 +1130,7 @@ add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, vm_offset_t vaddr, bpage->busaddr |= vaddr & PAGE_MASK; } bpage->datavaddr = vaddr; + bpage->dataaddr = addr; bpage->datacount = size; STAILQ_INSERT_TAIL(&(map->bpages), bpage, links); return (bpage->busaddr); @@ -1224,8 +1184,9 @@ busdma_swi(void) mtx_unlock(&bounce_lock); dmat = map->dmat; (dmat->lockfunc)(dmat->lockfuncarg, BUS_DMA_LOCK); - bus_dmamap_load(map->dmat, map, map->buf, map->buflen, - map->callback, map->callback_arg, /*flags*/0); + bus_dmamap_load_mem(map->dmat, map, &map->mem, + map->callback, map->callback_arg, + BUS_DMA_WAITOK); (dmat->lockfunc)(dmat->lockfuncarg, BUS_DMA_UNLOCK); mtx_lock(&bounce_lock); } From 22aa5c496b67557466cee1d721ad450e200f55cd Mon Sep 17 00:00:00 2001 From: Marcel Moolenaar Date: Tue, 12 Feb 2013 17:24:41 +0000 Subject: [PATCH 0141/1476] Eliminate padding by moving 'narg' next to 'code'. Both are 32-bit entities in the syscall_args structure that otherwise has 64-bit only fields. --- sys/ia64/include/proc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/ia64/include/proc.h b/sys/ia64/include/proc.h index d7f0b4a7b0b..b0468720800 100644 --- a/sys/ia64/include/proc.h +++ b/sys/ia64/include/proc.h @@ -44,10 +44,10 @@ struct mdproc { #ifdef _KERNEL struct syscall_args { u_int code; + int narg; struct sysent *callp; register_t *args; register_t args32[8]; - int narg; }; #endif From f1acb9d36e0e25b853bd9a28a8a26dd9690ff50d Mon Sep 17 00:00:00 2001 From: Marcel Moolenaar Date: Tue, 12 Feb 2013 17:38:35 +0000 Subject: [PATCH 0142/1476] Eliminate the PC_CURTHREAD symbol and load the current thread's thread structure pointer atomically from r13 (the pcpu pointer) for the current CPU/core. Add a CTASSERT in machdep.c to make sure that pc_curthread is in fact the first field in struct pcpu. The only non-atomic operations left were those related to process- space operations, such as casuword, subyte, suword16, fubyte, fuword16, copyin, copyout and their variations. The casuword function has been re-structured more complete than the others. This way we have an example of a better bundling without introducing a lot of risk when we get it wrong. The other functions can be rebundled in separate commits and with the appropriate testing. --- sys/ia64/ia64/genassym.c | 1 - sys/ia64/ia64/machdep.c | 16 +++++++++++++ sys/ia64/ia64/support.S | 51 ++++++++++++++-------------------------- 3 files changed, 33 insertions(+), 35 deletions(-) diff --git a/sys/ia64/ia64/genassym.c b/sys/ia64/ia64/genassym.c index 6adaa338645..10ba5abfd77 100644 --- a/sys/ia64/ia64/genassym.c +++ b/sys/ia64/ia64/genassym.c @@ -96,7 +96,6 @@ ASSYM(PAGE_SHIFT, PAGE_SHIFT); ASSYM(PAGE_SIZE, PAGE_SIZE); ASSYM(PC_CURRENT_PMAP, offsetof(struct pcpu, pc_md.current_pmap)); -ASSYM(PC_CURTHREAD, offsetof(struct pcpu, pc_curthread)); ASSYM(PC_IDLETHREAD, offsetof(struct pcpu, pc_idlethread)); ASSYM(PCB_CURRENT_PMAP, offsetof(struct pcb, pcb_current_pmap)); diff --git a/sys/ia64/ia64/machdep.c b/sys/ia64/ia64/machdep.c index fbc35d179a0..98bcf446d7a 100644 --- a/sys/ia64/ia64/machdep.c +++ b/sys/ia64/ia64/machdep.c @@ -98,6 +98,22 @@ __FBSDID("$FreeBSD$"); #include #include +/* + * For atomicity reasons, we demand that pc_curthread is the first + * field in the struct pcpu. It allows us to read the pointer with + * a single atomic instruction: + * ld8 %curthread = [r13] + * Otherwise we would first have to calculate the load address and + * store the result in a temporary register and that for the load: + * add %temp = %offsetof(struct pcpu), r13 + * ld8 %curthread = [%temp] + * A context switch inbetween the add and the ld8 could have the + * thread migrate to a different core. In that case, %curthread + * would be the thread running on the original core and not actually + * the current thread. + */ +CTASSERT(offsetof(struct pcpu, pc_curthread) == 0); + static SYSCTL_NODE(_hw, OID_AUTO, freq, CTLFLAG_RD, 0, ""); static SYSCTL_NODE(_machdep, OID_AUTO, cpu, CTLFLAG_RD, 0, ""); diff --git a/sys/ia64/ia64/support.S b/sys/ia64/ia64/support.S index b8035816af2..46e5972cbe6 100644 --- a/sys/ia64/ia64/support.S +++ b/sys/ia64/ia64/support.S @@ -73,26 +73,25 @@ END(fusufault) */ ENTRY(casuword, 3) { .mlx - add r15=PC_CURTHREAD,r13 + ld8.acq r15=[r13] // r15 = curthread movl r14=VM_MAXUSER_ADDRESS ;; } { .mib - ld8 r15=[r15] // r15 = curthread + add r15=TD_PCB,r15 cmp.geu p6,p0=in0,r14 (p6) br.dpnt.few 1f ;; } { .mlx - add r15=TD_PCB,r15 + ld8 r15=[r15] // r15 = PCB movl r14=fusufault ;; } { .mmi - ld8 r15=[r15] // r15 = PCB - ;; mov ar.ccv=in1 add r15=PCB_ONFAULT,r15 + nop 0 ;; } { .mmi @@ -123,12 +122,11 @@ END(casuword) */ ENTRY(casuword32, 3) { .mlx - add r15=PC_CURTHREAD,r13 movl r14=VM_MAXUSER_ADDRESS ;; } { .mib - ld8 r15=[r15] // r15 = curthread + ld8.acq r15=[r13] // r15 = curthread cmp.geu p6,p0=in0,r14 (p6) br.dpnt.few 1f ;; @@ -177,12 +175,11 @@ END(casuword32) ENTRY(subyte, 2) { .mlx - add r15=PC_CURTHREAD,r13 movl r14=VM_MAXUSER_ADDRESS ;; } { .mib - ld8 r15=[r15] // r15 = curthread + ld8.acq r15=[r13] // r15 = curthread cmp.geu p6,p0=in0,r14 (p6) br.dpnt.few 1f ;; @@ -223,12 +220,11 @@ END(subyte) ENTRY(suword16, 2) { .mlx - add r15=PC_CURTHREAD,r13 movl r14=VM_MAXUSER_ADDRESS ;; } { .mib - ld8 r15=[r15] // r15 = curthread + ld8.acq r15=[r13] // r15 = curthread cmp.geu p6,p0=in0,r14 (p6) br.dpnt.few 1f ;; @@ -269,12 +265,11 @@ END(suword16) ENTRY(suword32, 2) { .mlx - add r15=PC_CURTHREAD,r13 movl r14=VM_MAXUSER_ADDRESS ;; } { .mib - ld8 r15=[r15] // r15 = curthread + ld8.acq r15=[r13] // r15 = curthread cmp.geu p6,p0=in0,r14 (p6) br.dpnt.few 1f ;; @@ -316,12 +311,11 @@ END(suword32) ENTRY(suword64, 2) XENTRY(suword) { .mlx - add r15=PC_CURTHREAD,r13 movl r14=VM_MAXUSER_ADDRESS ;; } { .mib - ld8 r15=[r15] // r15 = curthread + ld8.acq r15=[r13] // r15 = curthread cmp.geu p6,p0=in0,r14 (p6) br.dpnt.few 1f ;; @@ -370,12 +364,11 @@ END(suword64) ENTRY(fubyte, 1) { .mlx - add r15=PC_CURTHREAD,r13 movl r14=VM_MAXUSER_ADDRESS ;; } { .mib - ld8 r15=[r15] // r15 = curthread + ld8.acq r15=[r13] // r15 = curthread cmp.geu p6,p0=in0,r14 (p6) br.dpnt.few 1f ;; @@ -416,12 +409,11 @@ END(fubyte) ENTRY(fuword16, 2) { .mlx - add r15=PC_CURTHREAD,r13 movl r14=VM_MAXUSER_ADDRESS ;; } { .mib - ld8 r15=[r15] // r15 = curthread + ld8.acq r15=[r13] // r15 = curthread cmp.geu p6,p0=in0,r14 (p6) br.dpnt.few 1f ;; @@ -462,12 +454,11 @@ END(fuword16) ENTRY(fuword32, 2) { .mlx - add r15=PC_CURTHREAD,r13 movl r14=VM_MAXUSER_ADDRESS ;; } { .mib - ld8 r15=[r15] // r15 = curthread + ld8.acq r15=[r13] // r15 = curthread cmp.geu p6,p0=in0,r14 (p6) br.dpnt.few 1f ;; @@ -509,12 +500,11 @@ END(fuword32) ENTRY(fuword64, 2) XENTRY(fuword) { .mlx - add r15=PC_CURTHREAD,r13 movl r14=VM_MAXUSER_ADDRESS ;; } { .mib - ld8 r15=[r15] // r15 = curthread + ld8.acq r15=[r13] // r15 = curthread cmp.geu p6,p0=in0,r14 (p6) br.dpnt.few 1f ;; @@ -630,10 +620,8 @@ ENTRY(copyinstr, 4) cmp.geu p6,p0=in0,loc2 // is in user space. ;; (p6) br.cond.spnt.few copyerr // if it's not, error out. + ld8.acq r15=[r13] movl r14=copyerr // set up fault handler. - add r15=PC_CURTHREAD,r13 // find curthread - ;; - ld8 r15=[r15] ;; add r15=TD_PCB,r15 // find pcb ;; @@ -743,10 +731,8 @@ ENTRY(copyin, 3) cmp.geu p6,p0=in0,loc2 // is in user space. ;; (p6) br.cond.spnt.few copyerr // if it's not, error out. + ld8.acq r15=[r13] movl r14=copyerr // set up fault handler. - add r15=PC_CURTHREAD,r13 // find curthread - ;; - ld8 r15=[r15] ;; add r15=TD_PCB,r15 // find pcb ;; @@ -781,10 +767,8 @@ ENTRY(copyout, 3) cmp.geu p6,p0=in1,loc2 // is in user space. ;; (p6) br.cond.spnt.few copyerr // if it's not, error out. + ld8.acq r15=[r13] movl r14=copyerr // set up fault handler. - add r15=PC_CURTHREAD,r13 // find curthread - ;; - ld8 r15=[r15] ;; add r15=TD_PCB,r15 // find pcb ;; @@ -806,8 +790,7 @@ ENTRY(copyout, 3) END(copyout) ENTRY(copyerr, 0) - add r14=PC_CURTHREAD,r13 ;; // find curthread - ld8 r14=[r14] ;; + ld8.acq r14=[r13] ;; add r14=TD_PCB,r14 ;; // curthread->td_addr ld8 r14=[r14] ;; add r14=PCB_ONFAULT,r14 ;; // &curthread->td_pcb->pcb_onfault From 449df4ecb8f60875280938f8ecb9a768428583a5 Mon Sep 17 00:00:00 2001 From: Andrey Zonov Date: Tue, 12 Feb 2013 18:48:11 +0000 Subject: [PATCH 0143/1476] - Use correct size of copying different socket structures. MFC after: 1 week --- usr.bin/kdump/kdump.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/usr.bin/kdump/kdump.c b/usr.bin/kdump/kdump.c index bd3ceab6717..851a457837e 100644 --- a/usr.bin/kdump/kdump.c +++ b/usr.bin/kdump/kdump.c @@ -1443,7 +1443,7 @@ ktrsockaddr(struct sockaddr *sa) struct sockaddr_in sa_in; memset(&sa_in, 0, sizeof(sa_in)); - memcpy(&sa_in, sa, sizeof(sa)); + memcpy(&sa_in, sa, sa->sa_len); check_sockaddr_len(in); inet_ntop(AF_INET, &sa_in.sin_addr, addr, sizeof addr); printf("%s:%u", addr, ntohs(sa_in.sin_port)); @@ -1455,7 +1455,7 @@ ktrsockaddr(struct sockaddr *sa) struct netrange *nr; memset(&sa_at, 0, sizeof(sa_at)); - memcpy(&sa_at, sa, sizeof(sa)); + memcpy(&sa_at, sa, sa->sa_len); check_sockaddr_len(at); nr = &sa_at.sat_range.r_netrange; printf("%d.%d, %d-%d, %d", ntohs(sa_at.sat_addr.s_net), @@ -1468,7 +1468,7 @@ ktrsockaddr(struct sockaddr *sa) struct sockaddr_in6 sa_in6; memset(&sa_in6, 0, sizeof(sa_in6)); - memcpy(&sa_in6, sa, sizeof(sa)); + memcpy(&sa_in6, sa, sa->sa_len); check_sockaddr_len(in6); inet_ntop(AF_INET6, &sa_in6.sin6_addr, addr, sizeof addr); printf("[%s]:%u", addr, htons(sa_in6.sin6_port)); @@ -1479,7 +1479,7 @@ ktrsockaddr(struct sockaddr *sa) struct sockaddr_ipx sa_ipx; memset(&sa_ipx, 0, sizeof(sa_ipx)); - memcpy(&sa_ipx, sa, sizeof(sa)); + memcpy(&sa_ipx, sa, sa->sa_len); check_sockaddr_len(ipx); /* XXX wish we had ipx_ntop */ printf("%s", ipx_ntoa(sa_ipx.sipx_addr)); @@ -1491,7 +1491,7 @@ ktrsockaddr(struct sockaddr *sa) struct sockaddr_un sa_un; memset(&sa_un, 0, sizeof(sa_un)); - memcpy(&sa_un, sa, sizeof(sa)); + memcpy(&sa_un, sa, sa->sa_len); check_sockaddr_len(un); printf("%.*s", (int)sizeof(sa_un.sun_path), sa_un.sun_path); break; From 4b03484ff7eacd7c266db1277fef414f76a6425c Mon Sep 17 00:00:00 2001 From: Andrey Zonov Date: Tue, 12 Feb 2013 19:10:54 +0000 Subject: [PATCH 0144/1476] - Make actually printing path of AF_LOCAL socket types. MFC after: 1 week --- usr.bin/kdump/kdump.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/usr.bin/kdump/kdump.c b/usr.bin/kdump/kdump.c index 851a457837e..2769832f670 100644 --- a/usr.bin/kdump/kdump.c +++ b/usr.bin/kdump/kdump.c @@ -1492,7 +1492,6 @@ ktrsockaddr(struct sockaddr *sa) memset(&sa_un, 0, sizeof(sa_un)); memcpy(&sa_un, sa, sa->sa_len); - check_sockaddr_len(un); printf("%.*s", (int)sizeof(sa_un.sun_path), sa_un.sun_path); break; } @@ -1616,8 +1615,7 @@ ktrstruct(char *buf, size_t buflen) if (datalen > sizeof(ss)) goto invalid; memcpy(&ss, data, datalen); - if (datalen < sizeof(struct sockaddr) || - datalen != ss.ss_len) + if (datalen != ss.ss_len) goto invalid; ktrsockaddr((struct sockaddr *)&ss); } else { From eaba9848dde2799d9264671494a5585cb1a0c2c4 Mon Sep 17 00:00:00 2001 From: Rui Paulo Date: Wed, 13 Feb 2013 02:21:45 +0000 Subject: [PATCH 0145/1476] Introduce PLATFORMMETHOD_END and use it. --- sys/powerpc/booke/platform_bare.c | 2 +- sys/powerpc/include/platformvar.h | 3 ++- sys/powerpc/powermac/platform_powermac.c | 2 +- sys/powerpc/ps3/platform_ps3.c | 2 +- sys/powerpc/wii/platform_wii.c | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/sys/powerpc/booke/platform_bare.c b/sys/powerpc/booke/platform_bare.c index c5739f788aa..65fb55411c0 100644 --- a/sys/powerpc/booke/platform_bare.c +++ b/sys/powerpc/booke/platform_bare.c @@ -89,7 +89,7 @@ static platform_method_t bare_methods[] = { PLATFORMMETHOD(platform_reset, booke_reset), - { 0, 0 } + PLATFORMMETHOD_END }; static platform_def_t bare_platform = { diff --git a/sys/powerpc/include/platformvar.h b/sys/powerpc/include/platformvar.h index b7c011d3985..21a1d047cb0 100644 --- a/sys/powerpc/include/platformvar.h +++ b/sys/powerpc/include/platformvar.h @@ -81,7 +81,8 @@ typedef struct platform_kobj *platform_t; typedef struct kobj_class platform_def_t; #define platform_method_t kobj_method_t -#define PLATFORMMETHOD KOBJMETHOD +#define PLATFORMMETHOD KOBJMETHOD +#define PLATFORMMETHOD_END KOBJMETHOD_END #define PLATFORM_DEF(name) DATA_SET(platform_set, name) diff --git a/sys/powerpc/powermac/platform_powermac.c b/sys/powerpc/powermac/platform_powermac.c index 978b33acd81..52d5c4a3c52 100644 --- a/sys/powerpc/powermac/platform_powermac.c +++ b/sys/powerpc/powermac/platform_powermac.c @@ -77,7 +77,7 @@ static platform_method_t powermac_methods[] = { PLATFORMMETHOD(platform_reset, powermac_reset), - { 0, 0 } + PLATFORMMETHOD_END }; static platform_def_t powermac_platform = { diff --git a/sys/powerpc/ps3/platform_ps3.c b/sys/powerpc/ps3/platform_ps3.c index f06c2cfc7ea..61ce8737a4a 100644 --- a/sys/powerpc/ps3/platform_ps3.c +++ b/sys/powerpc/ps3/platform_ps3.c @@ -89,7 +89,7 @@ static platform_method_t ps3_methods[] = { PLATFORMMETHOD(platform_reset, ps3_reset), - { 0, 0 } + PLATFORMMETHOD_END }; static platform_def_t ps3_platform = { diff --git a/sys/powerpc/wii/platform_wii.c b/sys/powerpc/wii/platform_wii.c index dcf1fc019a8..2bb6022ce9a 100644 --- a/sys/powerpc/wii/platform_wii.c +++ b/sys/powerpc/wii/platform_wii.c @@ -69,7 +69,7 @@ static platform_method_t wii_methods[] = { PLATFORMMETHOD(platform_timebase_freq, wii_timebase_freq), PLATFORMMETHOD(platform_reset, wii_reset), - { 0, 0 } + PLATFORMMETHOD_END }; static platform_def_t wii_platform = { From 1a85141ad436996414e264ea635044e079fd9069 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Wed, 13 Feb 2013 05:32:19 +0000 Subject: [PATCH 0146/1476] Pull out the if_transmit() work and revert back to ath_start(). My changed had some rather significant behavioural changes to throughput. The two issues I noticed: * With if_start and the ifnet mbuf queue, any temporary latency would get eaten up by some mbufs being queued. With ath_transmit() queuing things to ath_buf's, I'd only get 512 TX buffers before I couldn't queue any further frames. * There's also some non-zero latency involved with TX being pushed into a taskqueue via direct dispatch. Any time the scheduler didn't immediately schedule the ath TX task would cause extra latency. Various 1ge/10ge drivers implement both direct dispatch (if the TX lock can be acquired) and deferred task transmission (if the TX lock can't be acquired), with frames being pushed into a drbd queue. I'll have to do this at some point, but until I figure out how to deal with 802.11 fragments, I'll have to wait a while longer. So what I saw: * lots of extra latency, specially under load - if the taskqueue wasn't immediately scheduled, things went pear shaped; * any extra latency would result in TX ath_buf's taking their sweet time being replenished, so any further calls to ath_transmit() would drop mbufs. * .. yes, there's no explicit backpressure here - things are just dropped. Eek. With this, the general performance has gone up, but those subtle if_start() related race conditions are back. For some reason, this is doubly-obvious with the AR5416 NIC and I don't quite understand why yet. There's an unrelated issue with AR5416 performance in STA mode (it's fine in AP mode when bridging frames, weirdly..) that requires a little further investigation. Specifically - it works fine on a Lenovo T40 (single core CPU) running a March 2012 9-STABLE kernel, but a Lenovo T60 (dual core) running an early November 2012 kernel behaves very poorly. The same hardware with an AR9160 or AR9280 behaves perfectly. --- sys/dev/ath/if_ath.c | 551 ++++++++------------------------------ sys/dev/ath/if_ath_misc.h | 4 +- sys/dev/ath/if_ath_tx.c | 8 +- sys/dev/ath/if_athvar.h | 5 +- 4 files changed, 112 insertions(+), 456 deletions(-) diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 7679fd2416f..b6b42172694 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -152,6 +152,7 @@ static void ath_init(void *); static void ath_stop_locked(struct ifnet *); static void ath_stop(struct ifnet *); static int ath_reset_vap(struct ieee80211vap *, u_long); +static void ath_start_queue(struct ifnet *ifp); static int ath_media_change(struct ifnet *); static void ath_watchdog(void *); static int ath_ioctl(struct ifnet *, u_long, caddr_t); @@ -212,14 +213,6 @@ static void ath_dfs_tasklet(void *, int); static void ath_node_powersave(struct ieee80211_node *, int); static int ath_node_set_tim(struct ieee80211_node *, int); -static int ath_transmit(struct ifnet *ifp, struct mbuf *m); -static void ath_qflush(struct ifnet *ifp); - -static void ath_txq_qinit(struct ifnet *ifp); -static void ath_txq_qflush(struct ifnet *ifp); -static int ath_txq_qadd(struct ifnet *ifp, struct mbuf *m0); -static void ath_txq_qrun(struct ifnet *ifp); - #ifdef IEEE80211_SUPPORT_TDMA #include #endif @@ -436,21 +429,6 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) taskqueue_start_threads(&sc->sc_tq, 1, PI_NET, "%s taskq", ifp->if_xname); - /* - * This taskqueue doesn't get any higher priority - * than the ath(4) taskqueue (PI_NET) so TX won't - * pre-empt RX and other task priorities. - * - * This may not be optimal - the previous behaviour - * was to direct-dispatch frames via the sending - * task context, rather than (always) software - * queuing. - */ - sc->sc_tx_tq = taskqueue_create("ath_tx_taskq", M_NOWAIT, - taskqueue_thread_enqueue, &sc->sc_tx_tq); - taskqueue_start_threads(&sc->sc_tx_tq, 1, PI_NET, - "%s TX taskq", ifp->if_xname); - TASK_INIT(&sc->sc_rxtask, 0, sc->sc_rx.recv_tasklet, sc); TASK_INIT(&sc->sc_bmisstask, 0, ath_bmiss_proc, sc); TASK_INIT(&sc->sc_bstucktask,0, ath_bstuck_proc, sc); @@ -579,18 +557,13 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) ifp->if_softc = sc; ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST; - /* XXX net80211 uses if_start to re-start ifnet processing */ - ifp->if_start = ath_start; - ifp->if_transmit = ath_transmit; - ifp->if_qflush = ath_qflush; + ifp->if_start = ath_start_queue; ifp->if_ioctl = ath_ioctl; ifp->if_init = ath_init; IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); - ath_txq_qinit(ifp); - ic->ic_ifp = ifp; /* XXX not right but it's not used anywhere important */ ic->ic_phytype = IEEE80211_T_OFDM; @@ -996,7 +969,6 @@ ath_detach(struct ath_softc *sc) ath_stop(ifp); ieee80211_ifdetach(ifp->if_l2com); taskqueue_free(sc->sc_tq); - taskqueue_free(sc->sc_tx_tq); #ifdef ATH_TX99_DIAG if (sc->sc_tx99 != NULL) sc->sc_tx99->detach(sc->sc_tx99); @@ -1005,7 +977,6 @@ ath_detach(struct ath_softc *sc) #ifdef ATH_DEBUG_ALQ if_ath_alq_tidyup(&sc->sc_alq); #endif - ath_txq_qflush(ifp); ath_spectral_detach(sc); ath_dfs_detach(sc); ath_desc_free(sc); @@ -2145,7 +2116,6 @@ ath_txrx_start(struct ath_softc *sc) { taskqueue_unblock(sc->sc_tq); - taskqueue_unblock(sc->sc_tx_tq); } /* @@ -2246,7 +2216,6 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type) /* Try to (stop any further TX/RX from occuring */ taskqueue_block(sc->sc_tq); - taskqueue_block(sc->sc_tx_tq); ATH_PCU_LOCK(sc); ath_hal_intrset(ah, 0); /* disable interrupts */ @@ -2546,70 +2515,13 @@ ath_getbuf(struct ath_softc *sc, ath_buf_type_t btype) } static void -ath_qflush(struct ifnet *ifp) +ath_start_queue(struct ifnet *ifp) { + struct ath_softc *sc = ifp->if_softc; - /* XXX complete/suspend TX */ - ath_txq_qflush(ifp); - - /* Unsuspend TX? */ -} - -/* - * Transmit a frame from net80211. - */ -static int -ath_transmit(struct ifnet *ifp, struct mbuf *m) -{ - struct ieee80211_node *ni; - struct ath_softc *sc = (struct ath_softc *) ifp->if_softc; - - ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; - - if (ath_txq_qadd(ifp, m) < 0) { - /* - * If queuing fails, the if_transmit() API makes the - * callee responsible for freeing the mbuf (rather than - * the caller, who just assumes the mbuf has been dealt - * with somehow). - * - * BUT, net80211 will free node references if if_transmit() - * fails _on encapsulated buffers_. Since drivers - * only get fully encapsulated frames from net80211 (via - * raw or otherwise APIs), we must be absolutely careful - * to not free the node ref or things will get loopy - * down the track. - * - * For tx fragments, the TX code must free whatever - * new references it created, but NOT the original - * TX node ref that was passed in. - */ - ath_freetx(m); - return (ENOBUFS); - } - - /* - * Unconditionally kick the taskqueue. - * - * Now, there's a subtle race condition possible here if we - * went down the path of only kicking the taskqueue if it - * wasn't running. If we're not absolutely, positively - * careful, we could have a small race window between - * finishing the taskqueue and clearing the TX flag, which - * would be interpreted in _this_ context as "we don't need - * to kick the TX taskqueue, as said taskqueue is already - * running." - * - * It's a problem in some of the 1GE/10GE NIC drivers. - * So until a _correct_ method for implementing this is - * drafted up and written, which avoids (potentially) - * large amounts of locking contention per-frame, let's - * just do the inefficient "kick taskqueue each time" - * method. - */ + ATH_KTR(sc, ATH_KTR_TX, 0, "ath_start_queue: start"); ath_tx_kick(sc); - - return (0); + ATH_KTR(sc, ATH_KTR_TX, 0, "ath_start_queue: finished"); } void @@ -2636,7 +2548,9 @@ ath_start_task(void *arg, int npending) sc->sc_txstart_cnt++; ATH_PCU_UNLOCK(sc); - ath_txq_qrun(ifp); + ATH_TX_LOCK(sc); + ath_start(sc->sc_ifp); + ATH_TX_UNLOCK(sc); ATH_PCU_LOCK(sc); sc->sc_txstart_cnt--; @@ -2644,292 +2558,91 @@ ath_start_task(void *arg, int npending) ATH_KTR(sc, ATH_KTR_TX, 0, "ath_start_task: finished"); } -/* - * Pending TX buffer chain management routines. - */ - - -/* - * Initialise the TX queue! - */ -static void -ath_txq_qinit(struct ifnet *ifp) -{ - struct ath_softc *sc = ifp->if_softc; - - TAILQ_INIT(&sc->sc_txbuf_list); -} - -/* - * Add this mbuf to the TX buffer chain. - * - * This allocates an ath_buf, links the mbuf into it, and - * appends it to the end of the TX buffer chain. - * It doesn't fill out the ath_buf in any way besides - * that. - * - * Since the mbuf may be a list of mbufs representing - * 802.11 fragments, handle allocating ath_bufs for each - * of the mbuf fragments. - * - * If we queued it, 0 is returned. Else, < 0 is returned. - * - * If <0 is returned, the sender is responsible for - * freeing the mbuf if appropriate. - */ -static int -ath_txq_qadd(struct ifnet *ifp, struct mbuf *m0) +void +ath_start(struct ifnet *ifp) { struct ath_softc *sc = ifp->if_softc; + struct ieee80211_node *ni; struct ath_buf *bf; + struct mbuf *m, *next; ath_bufhead frags; - struct ieee80211_node *ni; - struct mbuf *m; - - /* XXX recursive TX completion -> TX? */ - ATH_TX_IC_UNLOCK_ASSERT(sc); - - /* - * We grab the node pointer, but we don't deref - * the node. The caller must be responsible for - * freeing the node reference if it decides to - * free the mbuf. - */ - ni = (struct ieee80211_node *) m0->m_pkthdr.rcvif; - - ATH_TXBUF_LOCK(sc); - if (sc->sc_txbuf_cnt <= sc->sc_txq_data_minfree) { - /* XXX increment counter? */ - ATH_TXBUF_UNLOCK(sc); - IF_LOCK(&ifp->if_snd); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - IF_UNLOCK(&ifp->if_snd); - return (-1); - } - ATH_TXBUF_UNLOCK(sc); - - /* - * Grab a TX buffer and associated resources. - */ - bf = ath_getbuf(sc, ATH_BUFTYPE_NORMAL); - if (bf == NULL) { - device_printf(sc->sc_dev, - "%s: couldn't allocate a buffer\n", - __func__); - return (-1); - } - - /* Setup the initial buffer node contents */ - bf->bf_m = m0; - bf->bf_node = ni; - - /* - * Check for fragmentation. If this frame - * has been broken up verify we have enough - * buffers to send all the fragments so all - * go out or none... - */ - TAILQ_INIT(&frags); - if (m0->m_flags & M_FRAG) - DPRINTF(sc, ATH_DEBUG_XMIT, "%s: txfrag\n", __func__); - if ((m0->m_flags & M_FRAG) && - !ath_txfrag_setup(sc, &frags, m0, ni)) { - DPRINTF(sc, ATH_DEBUG_XMIT, - "%s: out of txfrag buffers\n", __func__); - sc->sc_stats.ast_tx_nofrag++; - ifp->if_oerrors++; - goto bad; - } - - /* - * Don't stuff the non-fragment frame onto the fragment - * queue. ath_txfrag_cleanup() should only be called on fragments - - * ie, the _extra_ ieee80211_node references - and not the single - * node reference already done as part of the net08211 TX call - * into the driver. - */ - - ATH_TX_IC_LOCK(sc); - - /* - * Throw the single frame onto the queue. - */ - TAILQ_INSERT_TAIL(&sc->sc_txbuf_list, bf, bf_list); - - /* - * Update next packet duration length if it's a fragment. - * It's needed for accurate NAV calculations (which for - * fragments include the length of the NEXT fragment.) - */ - if (m0->m_nextpkt != NULL) - bf->bf_state.bfs_nextpktlen = - m0->m_nextpkt->m_pkthdr.len; - - /* - * Append the fragments. We have to populate bf and node - * references here as although the txfrag setup code does - * create buffers and increment the node ref, it doesn't - * populate the fields for us. - */ - m = m0->m_nextpkt; - while ( (bf = TAILQ_FIRST(&frags)) != NULL) { - bf->bf_m = m; - bf->bf_node = ni; - device_printf(sc->sc_dev, "%s: adding bf=%p, m=%p, ni=%p\n", - __func__, - bf, - bf->bf_m, - bf->bf_node); - TAILQ_REMOVE(&frags, bf, bf_list); - TAILQ_INSERT_TAIL(&sc->sc_txbuf_list, bf, bf_list); - - /* - * For duration (NAV) calculations, we need - * to know the next fragment size. - * - * XXX This isn't entirely accurate as it doesn't - * take pad bytes and such into account, but it'll do - * for fragment length / NAV calculations. - */ - if (m->m_nextpkt != NULL) - bf->bf_state.bfs_nextpktlen = - m->m_nextpkt->m_pkthdr.len; - - m = m->m_nextpkt; - } - ATH_TX_IC_UNLOCK(sc); - - return (0); -bad: - device_printf(sc->sc_dev, "%s: bad?!\n", __func__); - bf->bf_m = NULL; - bf->bf_node = NULL; - ATH_TXBUF_LOCK(sc); - ath_returnbuf_head(sc, bf); - ath_txfrag_cleanup(sc, &frags, ni); - ATH_TXBUF_UNLOCK(sc); - return (-1); -} - -/* - * Flush the pending TX buffer chain. - */ -static void -ath_txq_qflush(struct ifnet *ifp) -{ - struct ath_softc *sc = ifp->if_softc; - ath_bufhead txlist; - struct ath_buf *bf; - - device_printf(sc->sc_dev, "%s: called\n", __func__); - TAILQ_INIT(&txlist); - - /* Grab lock */ - ATH_TX_IC_LOCK(sc); - - /* Copy everything out of sc_txbuf_list into txlist */ - TAILQ_CONCAT(&txlist, &sc->sc_txbuf_list, bf_list); - - /* Unlock */ - ATH_TX_IC_UNLOCK(sc); - - /* Now, walk the list, freeing things */ - while ((bf = TAILQ_FIRST(&txlist)) != NULL) { - TAILQ_REMOVE(&txlist, bf, bf_list); - - if (bf->bf_node) - ieee80211_free_node(bf->bf_node); - - m_free(bf->bf_m); - - /* XXX paranoia! */ - bf->bf_m = NULL; - bf->bf_node = NULL; - - /* - * XXX Perhaps do a second pass with the TXBUF lock - * held and free them all at once? - */ - ATH_TXBUF_LOCK(sc); - ath_returnbuf_head(sc, bf); - ATH_TXBUF_UNLOCK(sc); - } -} - -/* - * Walk the TX buffer queue and call ath_tx_start() on each - * of them. - */ -static void -ath_txq_qrun(struct ifnet *ifp) -{ - struct ath_softc *sc = ifp->if_softc; - ath_bufhead txlist; - struct ath_buf *bf, *bf_next; - struct ieee80211_node *ni; - struct mbuf *m; + int npkts = 0; if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->sc_invalid) return; - TAILQ_INIT(&txlist); + ATH_TX_LOCK_ASSERT(sc); - /* - * Grab the frames to transmit from the tx queue - */ + ATH_KTR(sc, ATH_KTR_TX, 0, "ath_start: called"); - /* Copy everything out of sc_txbuf_list into txlist */ - ATH_TX_IC_LOCK(sc); - TAILQ_CONCAT(&txlist, &sc->sc_txbuf_list, bf_list); - ATH_TX_IC_UNLOCK(sc); - - /* - * Attempt to transmit each frame. - * - * In the old code path - if a TX fragment fails, subsequent - * fragments in that group would be aborted. - * - * It would be nice to chain together TX fragments in this - * way so they can be aborted together. - */ - ATH_TX_LOCK(sc); - TAILQ_FOREACH_SAFE(bf, &txlist, bf_list, bf_next) { + for (;;) { + ATH_TXBUF_LOCK(sc); + if (sc->sc_txbuf_cnt <= sc->sc_txq_data_minfree) { + /* XXX increment counter? */ + ATH_TXBUF_UNLOCK(sc); + IF_LOCK(&ifp->if_snd); + ifp->if_drv_flags |= IFF_DRV_OACTIVE; + IF_UNLOCK(&ifp->if_snd); + break; + } + ATH_TXBUF_UNLOCK(sc); + /* - * Clear, because we're going to reuse this - * as a real ath_buf now + * Grab a TX buffer and associated resources. */ - ni = bf->bf_node; - m = bf->bf_m; - - bf->bf_node = NULL; - bf->bf_m = NULL; + bf = ath_getbuf(sc, ATH_BUFTYPE_NORMAL); + if (bf == NULL) + break; + IFQ_DEQUEUE(&ifp->if_snd, m); + if (m == NULL) { + ATH_TXBUF_LOCK(sc); + ath_returnbuf_head(sc, bf); + ATH_TXBUF_UNLOCK(sc); + break; + } + ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; + npkts ++; /* - * Remove it from the list. + * Check for fragmentation. If this frame + * has been broken up verify we have enough + * buffers to send all the fragments so all + * go out or none... */ - TAILQ_REMOVE(&txlist, bf, bf_list); - - /* - * If we fail, free this buffer and go to the next one; - * ath_tx_start() frees the mbuf but not the node - * reference. - */ - if (ath_tx_start(sc, ni, bf, m)) { - /* - * XXX m is freed by ath_tx_start(); node reference - * is not! - */ + TAILQ_INIT(&frags); + if ((m->m_flags & M_FRAG) && + !ath_txfrag_setup(sc, &frags, m, ni)) { DPRINTF(sc, ATH_DEBUG_XMIT, - "%s: failed; bf=%p, ni=%p, m=%p\n", - __func__, - bf, - ni, - m); + "%s: out of txfrag buffers\n", __func__); + sc->sc_stats.ast_tx_nofrag++; ifp->if_oerrors++; + ath_freetx(m); + goto bad; + } + ifp->if_opackets++; + nextfrag: + /* + * Pass the frame to the h/w for transmission. + * Fragmented frames have each frag chained together + * with m_nextpkt. We know there are sufficient ath_buf's + * to send all the frags because of work done by + * ath_txfrag_setup. We leave m_nextpkt set while + * calling ath_tx_start so it can use it to extend the + * the tx duration to cover the subsequent frag and + * so it can reclaim all the mbufs in case of an error; + * ath_tx_start clears m_nextpkt once it commits to + * handing the frame to the hardware. + */ + next = m->m_nextpkt; + if (ath_tx_start(sc, ni, bf, m)) { + bad: + ifp->if_oerrors++; + reclaim: bf->bf_m = NULL; bf->bf_node = NULL; ATH_TXBUF_LOCK(sc); ath_returnbuf_head(sc, bf); + ath_txfrag_cleanup(sc, &frags, ni); ATH_TXBUF_UNLOCK(sc); /* * XXX todo, free the node outside of @@ -2937,86 +2650,38 @@ ath_txq_qrun(struct ifnet *ifp) */ if (ni != NULL) ieee80211_free_node(ni); - } else { + continue; + } + + /* + * Check here if the node is in power save state. + */ + ath_tx_update_tim(sc, ni, 1); + + if (next != NULL) { /* - * Check here if the node is in power save state. - * XXX we should hold a node ref here, and release - * it after the TX has completed. + * Beware of state changing between frags. + * XXX check sta power-save state? */ - ath_tx_update_tim(sc, ni, 1); - ifp->if_opackets++; + if (ni->ni_vap->iv_state != IEEE80211_S_RUN) { + DPRINTF(sc, ATH_DEBUG_XMIT, + "%s: flush fragmented packet, state %s\n", + __func__, + ieee80211_state_name[ni->ni_vap->iv_state]); + ath_freetx(next); + goto reclaim; + } + m = next; + bf = TAILQ_FIRST(&frags); + KASSERT(bf != NULL, ("no buf for txfrag")); + TAILQ_REMOVE(&frags, bf, bf_list); + goto nextfrag; } - /* - * XXX should check for state change and flip out - * if needed. - */ + sc->sc_wd_timer = 5; } - ATH_TX_UNLOCK(sc); - - /* - * If we break out early (eg a state change) we should prepend these - * frames onto the TX queue. - */ + ATH_KTR(sc, ATH_KTR_TX, 1, "ath_start: finished; npkts=%d", npkts); } - -/* - * This is now primarily used by the net80211 layer to kick-start - * queue processing. - */ -void -ath_start(struct ifnet *ifp) -{ - struct mbuf *m; - struct ath_softc *sc = ifp->if_softc; - struct ieee80211_node *ni; - int npkts = 0; - - ATH_TX_UNLOCK_ASSERT(sc); - - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->sc_invalid) - return; - - /* - * If we're below the free buffer limit, don't dequeue anything. - * The original code would not dequeue anything from the queue - * if allocating an ath_buf failed. - * - * For if_transmit, we have to either queue or drop the frame. - * So we have to try and queue it _somewhere_. - */ - for (;;) { - IFQ_DEQUEUE(&ifp->if_snd, m); - if (m == NULL) { - break; - } - - /* - * If we do fail here, just break out for now - * and wait until we've transmitted something - * before we attempt again? - */ - if (ath_txq_qadd(ifp, m) < 0) { - DPRINTF(sc, ATH_DEBUG_XMIT, - "%s: ath_txq_qadd failed\n", - __func__); - ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; - if (ni != NULL) - ieee80211_free_node(ni); - ath_freetx(m); - break; - } - npkts++; - } - - /* - * Kick the taskqueue into activity, but only if we - * queued something. - */ - if (npkts > 0) - ath_tx_kick(sc); -} - static int ath_media_change(struct ifnet *ifp) { @@ -3039,7 +2704,6 @@ ath_key_update_begin(struct ieee80211vap *vap) DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s:\n", __func__); taskqueue_block(sc->sc_tq); - taskqueue_block(sc->sc_tx_tq); IF_LOCK(&ifp->if_snd); /* NB: doesn't block mgmt frames */ } @@ -3052,7 +2716,6 @@ ath_key_update_end(struct ieee80211vap *vap) DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s:\n", __func__); IF_UNLOCK(&ifp->if_snd); taskqueue_unblock(sc->sc_tq); - taskqueue_unblock(sc->sc_tx_tq); } static void @@ -4273,11 +3936,11 @@ ath_tx_proc_q0(void *arg, int npending) if (sc->sc_softled) ath_led_event(sc, sc->sc_txrix); - ath_txq_qrun(ifp); - ATH_PCU_LOCK(sc); sc->sc_txproc_cnt--; ATH_PCU_UNLOCK(sc); + + ath_tx_kick(sc); } /* @@ -4326,11 +3989,11 @@ ath_tx_proc_q0123(void *arg, int npending) if (sc->sc_softled) ath_led_event(sc, sc->sc_txrix); - ath_txq_qrun(ifp); - ATH_PCU_LOCK(sc); sc->sc_txproc_cnt--; ATH_PCU_UNLOCK(sc); + + ath_tx_kick(sc); } /* @@ -4371,11 +4034,11 @@ ath_tx_proc(void *arg, int npending) if (sc->sc_softled) ath_led_event(sc, sc->sc_txrix); - ath_txq_qrun(ifp); - ATH_PCU_LOCK(sc); sc->sc_txproc_cnt--; ATH_PCU_UNLOCK(sc); + + ath_tx_kick(sc); } #undef TXQACTIVE @@ -4726,7 +4389,6 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan) /* (Try to) stop TX/RX from occuring */ taskqueue_block(sc->sc_tq); - taskqueue_block(sc->sc_tx_tq); ATH_PCU_LOCK(sc); ath_hal_intrset(ah, 0); /* Stop new RX/TX completion */ @@ -5116,7 +4778,6 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) sc->sc_imask &= ~(HAL_INT_SWBA | HAL_INT_BMISS); sc->sc_beacons = 0; taskqueue_unblock(sc->sc_tq); - taskqueue_unblock(sc->sc_tx_tq); } ni = ieee80211_ref_node(vap->iv_bss); @@ -5282,7 +4943,6 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) "%s: calibration disabled\n", __func__); } taskqueue_unblock(sc->sc_tq); - taskqueue_unblock(sc->sc_tx_tq); } else if (nstate == IEEE80211_S_INIT) { /* * If there are no vaps left in RUN state then @@ -5296,7 +4956,6 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) /* disable interrupts */ ath_hal_intrset(ah, sc->sc_imask &~ HAL_INT_GLOBAL); taskqueue_block(sc->sc_tq); - taskqueue_block(sc->sc_tx_tq); sc->sc_beacons = 0; } #ifdef IEEE80211_SUPPORT_TDMA diff --git a/sys/dev/ath/if_ath_misc.h b/sys/dev/ath/if_ath_misc.h index f35fc11f3b9..167c8267d9b 100644 --- a/sys/dev/ath/if_ath_misc.h +++ b/sys/dev/ath/if_ath_misc.h @@ -127,7 +127,9 @@ static inline void ath_tx_kick(struct ath_softc *sc) { - taskqueue_enqueue(sc->sc_tx_tq, &sc->sc_txpkttask); + ATH_TX_LOCK(sc); + ath_start(sc->sc_ifp); + ATH_TX_UNLOCK(sc); } /* diff --git a/sys/dev/ath/if_ath_tx.c b/sys/dev/ath/if_ath_tx.c index e19a63766a2..64c43788acd 100644 --- a/sys/dev/ath/if_ath_tx.c +++ b/sys/dev/ath/if_ath_tx.c @@ -1124,11 +1124,7 @@ ath_tx_calc_duration(struct ath_softc *sc, struct ath_buf *bf) dur = rt->info[rix].lpAckDuration; if (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG) { dur += dur; /* additional SIFS+ACK */ - if (bf->bf_state.bfs_nextpktlen == 0) { - device_printf(sc->sc_dev, - "%s: next txfrag len=0?\n", - __func__); - } + KASSERT(bf->bf_m->m_nextpkt != NULL, ("no fragment")); /* * Include the size of next fragment so NAV is * updated properly. The last fragment uses only @@ -1139,7 +1135,7 @@ ath_tx_calc_duration(struct ath_softc *sc, struct ath_buf *bf) * first fragment! */ dur += ath_hal_computetxtime(ah, rt, - bf->bf_state.bfs_nextpktlen, + bf->bf_m->m_nextpkt->m_pkthdr.len, rix, shortPreamble); } if (isfrag) { diff --git a/sys/dev/ath/if_athvar.h b/sys/dev/ath/if_athvar.h index 52ed6d8dc87..36923ccfe0a 100644 --- a/sys/dev/ath/if_athvar.h +++ b/sys/dev/ath/if_athvar.h @@ -279,8 +279,6 @@ struct ath_buf { int32_t bfs_keyix; /* crypto key index */ int32_t bfs_txantenna; /* TX antenna config */ - uint16_t bfs_nextpktlen; /* length of next frag pkt */ - /* Make this an 8 bit value? */ enum ieee80211_protmode bfs_protmode; @@ -525,7 +523,6 @@ struct ath_softc { struct mtx sc_tx_ic_mtx; /* TX queue mutex */ char sc_tx_ic_mtx_name[32]; struct taskqueue *sc_tq; /* private task queue */ - struct taskqueue *sc_tx_tq; /* private TX task queue */ struct ath_hal *sc_ah; /* Atheros HAL */ struct ath_ratectrl *sc_rc; /* tx rate control support */ struct ath_tx99 *sc_tx99; /* tx99 adjunct state */ @@ -815,6 +812,8 @@ struct ath_softc { MA_OWNED) #define ATH_TX_UNLOCK_ASSERT(_sc) mtx_assert(&(_sc)->sc_tx_mtx, \ MA_NOTOWNED) +#define ATH_TX_TRYLOCK(_sc) (mtx_owned(&(_sc)->sc_tx_mtx) != 0 && \ + mtx_trylock(&(_sc)->sc_tx_mtx)) /* * The IC TX lock is non-reentrant and serialises packet queuing from From 3df6c5bf313cd482dfb8fe16dc50668878e019b2 Mon Sep 17 00:00:00 2001 From: Po-Chien Lin Date: Wed, 13 Feb 2013 05:44:35 +0000 Subject: [PATCH 0147/1476] Add myself as a ports committer and my mentor relationship. Approved by: swills (mentor) --- share/misc/committers-ports.dot | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/share/misc/committers-ports.dot b/share/misc/committers-ports.dot index cf48d6ae136..0d755d08055 100644 --- a/share/misc/committers-ports.dot +++ b/share/misc/committers-ports.dot @@ -164,6 +164,7 @@ osa [label="Sergey A. Osokin\nosa@FreeBSD.org\n2003/06/04"] pat [label="Patrick Li\npat@FreeBSD.org\n2001/11/14"] pav [label="Pav Lucistnik\npav@FreeBSD.org\n2003/11/12"] pawel [label="Pawel Pekala\npawel@FreeBSD.org\n2011/03/11"] +pclin [label="Po-Chien Lin\npclin@FreeBSD.org\n2013/02/11"] pgj [label="Gabor Pali\npgj@FreeBSD.org\n2009/04/12"] pgollucci [label="Philip M. Gollucci\npgollucci@FreeBSD.org\n2008/07/21"] philip [label="Philip Paeps\nphilip@FreeBSD.org\n2005/10/19"] @@ -224,6 +225,7 @@ ahze -> shaun ahze -> tmclaugh araujo -> lippe +araujo -> pclin araujo -> pgollucci arved -> markus @@ -474,6 +476,8 @@ stas -> araujo steve -> netchild +swills -> pclin + tabthorpe -> ashish tabthorpe -> avilla tabthorpe -> avl From 3a5c97db68ea3f188de98ee1dd260c557a294fdf Mon Sep 17 00:00:00 2001 From: Gleb Smirnoff Date: Wed, 13 Feb 2013 07:32:09 +0000 Subject: [PATCH 0148/1476] Fix my email. --- share/man/man9/mbuf_tags.9 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/man/man9/mbuf_tags.9 b/share/man/man9/mbuf_tags.9 index d9627e8bc6a..cab22a00f7f 100644 --- a/share/man/man9/mbuf_tags.9 +++ b/share/man/man9/mbuf_tags.9 @@ -1,7 +1,7 @@ .\" $OpenBSD: mbuf_tags.9,v 1.18 2003/12/08 07:07:35 mcbride Exp $ .\" .\" The authors of this manual page are Angelos D. Keromytis -.\" (angelos@cis.upenn.edu), Gleb Smirnoff , and +.\" (angelos@cis.upenn.edu), Gleb Smirnoff , and .\" Robert Watson .\" .\" Copyright (c) 2004 Robert N. M. Watson From dc5f56598f893bae762384edd80ed42c5e7280cf Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Wed, 13 Feb 2013 08:20:29 +0000 Subject: [PATCH 0149/1476] Add specific supported revision of D-Link DWA-140 rev B1, B2. Submitted by: PseudoCylon MFC after: 1 week --- share/man/man4/run.4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/man/man4/run.4 b/share/man/man4/run.4 index 3aeb3db6003..06d9604fe97 100644 --- a/share/man/man4/run.4 +++ b/share/man/man4/run.4 @@ -129,7 +129,7 @@ driver supports the following wireless adapters: .It Corega CG-WLUSB300AGN .It Corega CG-WLUSB300GNM .It D-Link DWA-130 rev B1 -.It D-Link DWA-140 +.It D-Link DWA-140 rev B1, B2 .It DrayTek Vigor N61 .It Edimax EW-7711UAn .It Edimax EW-7711UTn From b7f9bfb502ab41f1900cdf030cf7c136899f695a Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Wed, 13 Feb 2013 08:28:27 +0000 Subject: [PATCH 0150/1476] Add new USB ID to FTDI driver. MFC after: 1 week PR: kern/175893 Submitted by: Tomek --- sys/dev/usb/serial/uftdi.c | 1 + sys/dev/usb/usbdevs | 1 + 2 files changed, 2 insertions(+) diff --git a/sys/dev/usb/serial/uftdi.c b/sys/dev/usb/serial/uftdi.c index 565c26ed197..21479a1c711 100644 --- a/sys/dev/usb/serial/uftdi.c +++ b/sys/dev/usb/serial/uftdi.c @@ -378,6 +378,7 @@ static const STRUCT_USB_HOST_ID uftdi_devs[] = { UFTDI_DEV(FTDI, IPLUS2, UFTDI_TYPE_AUTO), UFTDI_DEV(FTDI, IRTRANS, UFTDI_TYPE_AUTO), UFTDI_DEV(FTDI, KBS, UFTDI_TYPE_8U232AM), + UFTDI_DEV(FTDI, KTLINK, UFTDI_TYPE_8U232AM), UFTDI_DEV(FTDI, LENZ_LIUSB, UFTDI_TYPE_AUTO), UFTDI_DEV(FTDI, LK202, UFTDI_TYPE_8U232AM), UFTDI_DEV(FTDI, LK204, UFTDI_TYPE_8U232AM), diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs index aff55fd1ae6..62420478a8a 100644 --- a/sys/dev/usb/usbdevs +++ b/sys/dev/usb/usbdevs @@ -1717,6 +1717,7 @@ product FTDI 232H 0x6014 FTDI compatible adapter product FTDI SERIAL_2232D 0x9e90 FT2232D Dual port Serial product FTDI SERIAL_4232H 0x6011 FT4232H Quad port Serial product FTDI BEAGLEBONE 0xa6d0 BeagleBone +product FTDI KTLINK 0xbbe2 KT-LINK Embedded Hackers Multitool product FTDI TURTELIZER2 0xbdc8 egnite Turtelizer 2 JTAG/RS232 Adapter /* Gude Analog- und Digitalsysteme products also uses FTDI's id: */ product FTDI TACTRIX_OPENPORT_13M 0xcc48 OpenPort 1.3 Mitsubishi From a18a7a414abca38020879bcb9ae3566e8fb84312 Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Wed, 13 Feb 2013 12:35:17 +0000 Subject: [PATCH 0151/1476] Resolve a LOR after r246616. Protect control requests using the USB device enumeration lock. Make sure all callers of usbd_enum_lock() check the return value. Remove the control transfer specific lock. Bump the FreeBSD version number, hence external USB modules may need to be recompiled due to a USB device structure change. MFC after: 1 week --- sys/dev/usb/controller/usb_controller.c | 18 ++++++++++----- sys/dev/usb/usb_dev.c | 11 ++++----- sys/dev/usb/usb_dev.h | 1 + sys/dev/usb/usb_device.c | 4 ---- sys/dev/usb/usb_device.h | 1 - sys/dev/usb/usb_handle_request.c | 20 ++++++++++++----- sys/dev/usb/usb_hub.c | 13 +++++++---- sys/dev/usb/usb_request.c | 30 +++++++++++-------------- sys/sys/param.h | 2 +- 9 files changed, 56 insertions(+), 44 deletions(-) diff --git a/sys/dev/usb/controller/usb_controller.c b/sys/dev/usb/controller/usb_controller.c index cf2ae7a5569..a28d6126252 100644 --- a/sys/dev/usb/controller/usb_controller.c +++ b/sys/dev/usb/controller/usb_controller.c @@ -427,6 +427,7 @@ usb_bus_suspend(struct usb_proc_msg *pm) struct usb_bus *bus; struct usb_device *udev; usb_error_t err; + uint8_t do_unlock; bus = ((struct usb_bus_msg *)pm)->bus; udev = bus->devices[USB_ROOT_HUB_ADDR]; @@ -447,7 +448,7 @@ usb_bus_suspend(struct usb_proc_msg *pm) bus_generic_shutdown(bus->bdev); - usbd_enum_lock(udev); + do_unlock = usbd_enum_lock(udev); err = usbd_set_config_index(udev, USB_UNCONFIG_INDEX); if (err) @@ -464,7 +465,8 @@ usb_bus_suspend(struct usb_proc_msg *pm) if (bus->methods->set_hw_power_sleep != NULL) (bus->methods->set_hw_power_sleep) (bus, USB_HW_POWER_SUSPEND); - usbd_enum_unlock(udev); + if (do_unlock) + usbd_enum_unlock(udev); USB_BUS_LOCK(bus); } @@ -480,6 +482,7 @@ usb_bus_resume(struct usb_proc_msg *pm) struct usb_bus *bus; struct usb_device *udev; usb_error_t err; + uint8_t do_unlock; bus = ((struct usb_bus_msg *)pm)->bus; udev = bus->devices[USB_ROOT_HUB_ADDR]; @@ -489,7 +492,7 @@ usb_bus_resume(struct usb_proc_msg *pm) USB_BUS_UNLOCK(bus); - usbd_enum_lock(udev); + do_unlock = usbd_enum_lock(udev); #if 0 DEVMETHOD(usb_take_controller, NULL); /* dummy */ #endif @@ -523,7 +526,8 @@ usb_bus_resume(struct usb_proc_msg *pm) "attach root HUB\n"); } - usbd_enum_unlock(udev); + if (do_unlock) + usbd_enum_unlock(udev); USB_BUS_LOCK(bus); } @@ -539,6 +543,7 @@ usb_bus_shutdown(struct usb_proc_msg *pm) struct usb_bus *bus; struct usb_device *udev; usb_error_t err; + uint8_t do_unlock; bus = ((struct usb_bus_msg *)pm)->bus; udev = bus->devices[USB_ROOT_HUB_ADDR]; @@ -550,7 +555,7 @@ usb_bus_shutdown(struct usb_proc_msg *pm) bus_generic_shutdown(bus->bdev); - usbd_enum_lock(udev); + do_unlock = usbd_enum_lock(udev); err = usbd_set_config_index(udev, USB_UNCONFIG_INDEX); if (err) @@ -567,7 +572,8 @@ usb_bus_shutdown(struct usb_proc_msg *pm) if (bus->methods->set_hw_power_sleep != NULL) (bus->methods->set_hw_power_sleep) (bus, USB_HW_POWER_SHUTDOWN); - usbd_enum_unlock(udev); + if (do_unlock) + usbd_enum_unlock(udev); USB_BUS_LOCK(bus); } diff --git a/sys/dev/usb/usb_dev.c b/sys/dev/usb/usb_dev.c index c4264c550a0..9bf430bcf43 100644 --- a/sys/dev/usb/usb_dev.c +++ b/sys/dev/usb/usb_dev.c @@ -218,10 +218,10 @@ usb_ref_device(struct usb_cdev_privdata *cpd, mtx_unlock(&usb_ref_lock); /* - * We need to grab the sx-lock before grabbing the - * FIFO refs to avoid deadlock at detach! + * We need to grab the enumeration SX-lock before + * grabbing the FIFO refs to avoid deadlock at detach! */ - usbd_enum_lock(cpd->udev); + crd->do_unlock = usbd_enum_lock(cpd->udev); mtx_lock(&usb_ref_lock); @@ -282,9 +282,10 @@ usb_ref_device(struct usb_cdev_privdata *cpd, return (0); error: - if (crd->is_uref) { + if (crd->do_unlock) usbd_enum_unlock(cpd->udev); + if (crd->is_uref) { if (--(cpd->udev->refcount) == 0) { cv_signal(&cpd->udev->ref_cv); } @@ -336,7 +337,7 @@ usb_unref_device(struct usb_cdev_privdata *cpd, DPRINTFN(2, "cpd=%p is_uref=%d\n", cpd, crd->is_uref); - if (crd->is_uref) + if (crd->do_unlock) usbd_enum_unlock(cpd->udev); mtx_lock(&usb_ref_lock); diff --git a/sys/dev/usb/usb_dev.h b/sys/dev/usb/usb_dev.h index 3c757019ab8..f87ba53bc1a 100644 --- a/sys/dev/usb/usb_dev.h +++ b/sys/dev/usb/usb_dev.h @@ -84,6 +84,7 @@ struct usb_cdev_refdata { uint8_t is_write; /* location has write access */ uint8_t is_uref; /* USB refcount decr. needed */ uint8_t is_usbfs; /* USB-FS is active */ + uint8_t do_unlock; /* USB enum unlock needed */ }; struct usb_fs_privdata { diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c index fdc734c2d58..1c40815c65b 100644 --- a/sys/dev/usb/usb_device.c +++ b/sys/dev/usb/usb_device.c @@ -1545,9 +1545,6 @@ usb_alloc_device(device_t parent_dev, struct usb_bus *bus, if (udev == NULL) { return (NULL); } - /* initialise our SX-lock */ - sx_init_flags(&udev->ctrl_sx, "USB device SX lock", SX_DUPOK); - /* initialise our SX-lock */ sx_init_flags(&udev->enum_sx, "USB config SX lock", SX_DUPOK); sx_init_flags(&udev->sr_sx, "USB suspend and resume SX lock", SX_NOWITNESS); @@ -2119,7 +2116,6 @@ usb_free_device(struct usb_device *udev, uint8_t flag) &udev->cs_msg[0], &udev->cs_msg[1]); USB_BUS_UNLOCK(udev->bus); - sx_destroy(&udev->ctrl_sx); sx_destroy(&udev->enum_sx); sx_destroy(&udev->sr_sx); diff --git a/sys/dev/usb/usb_device.h b/sys/dev/usb/usb_device.h index 22a4652011a..b194256ed7b 100644 --- a/sys/dev/usb/usb_device.h +++ b/sys/dev/usb/usb_device.h @@ -181,7 +181,6 @@ union usb_device_scratch { struct usb_device { struct usb_clear_stall_msg cs_msg[2]; /* generic clear stall * messages */ - struct sx ctrl_sx; struct sx enum_sx; struct sx sr_sx; struct mtx device_mtx; diff --git a/sys/dev/usb/usb_handle_request.c b/sys/dev/usb/usb_handle_request.c index a775d6732fc..7f3cdc68b26 100644 --- a/sys/dev/usb/usb_handle_request.c +++ b/sys/dev/usb/usb_handle_request.c @@ -149,6 +149,7 @@ usb_handle_set_config(struct usb_xfer *xfer, uint8_t conf_no) { struct usb_device *udev = xfer->xroot->udev; usb_error_t err = 0; + uint8_t do_unlock; /* * We need to protect against other threads doing probe and @@ -156,7 +157,8 @@ usb_handle_set_config(struct usb_xfer *xfer, uint8_t conf_no) */ USB_XFER_UNLOCK(xfer); - usbd_enum_lock(udev); + /* Prevent re-enumeration */ + do_unlock = usbd_enum_lock(udev); if (conf_no == USB_UNCONFIG_NO) { conf_no = USB_UNCONFIG_INDEX; @@ -179,7 +181,8 @@ usb_handle_set_config(struct usb_xfer *xfer, uint8_t conf_no) goto done; } done: - usbd_enum_unlock(udev); + if (do_unlock) + usbd_enum_unlock(udev); USB_XFER_LOCK(xfer); return (err); } @@ -221,6 +224,7 @@ usb_handle_iface_request(struct usb_xfer *xfer, int error; uint8_t iface_index; uint8_t temp_state; + uint8_t do_unlock; if ((req.bmRequestType & 0x1F) == UT_INTERFACE) { iface_index = req.wIndex[0]; /* unicast */ @@ -234,7 +238,8 @@ usb_handle_iface_request(struct usb_xfer *xfer, */ USB_XFER_UNLOCK(xfer); - usbd_enum_lock(udev); + /* Prevent re-enumeration */ + do_unlock = usbd_enum_lock(udev); error = ENXIO; @@ -350,17 +355,20 @@ tr_repeat: goto tr_stalled; } tr_valid: - usbd_enum_unlock(udev); + if (do_unlock) + usbd_enum_unlock(udev); USB_XFER_LOCK(xfer); return (0); tr_short: - usbd_enum_unlock(udev); + if (do_unlock) + usbd_enum_unlock(udev); USB_XFER_LOCK(xfer); return (USB_ERR_SHORT_XFER); tr_stalled: - usbd_enum_unlock(udev); + if (do_unlock) + usbd_enum_unlock(udev); USB_XFER_LOCK(xfer); return (USB_ERR_STALLED); } diff --git a/sys/dev/usb/usb_hub.c b/sys/dev/usb/usb_hub.c index 1d87a3fae3c..a359ee25293 100644 --- a/sys/dev/usb/usb_hub.c +++ b/sys/dev/usb/usb_hub.c @@ -243,7 +243,9 @@ uhub_explore_sub(struct uhub_softc *sc, struct usb_port *up) /* check if device should be re-enumerated */ if (child->flags.usb_mode == USB_MODE_HOST) { - usbd_enum_lock(child); + uint8_t do_unlock; + + do_unlock = usbd_enum_lock(child); if (child->re_enumerate_wait) { err = usbd_set_config_index(child, USB_UNCONFIG_INDEX); @@ -262,7 +264,8 @@ uhub_explore_sub(struct uhub_softc *sc, struct usb_port *up) child->re_enumerate_wait = 0; err = 0; } - usbd_enum_unlock(child); + if (do_unlock) + usbd_enum_unlock(child); } /* check if probe and attach should be done */ @@ -716,6 +719,7 @@ uhub_explore(struct usb_device *udev) usb_error_t err; uint8_t portno; uint8_t x; + uint8_t do_unlock; hub = udev->hub; sc = hub->hubsoftc; @@ -737,7 +741,7 @@ uhub_explore(struct usb_device *udev) * Make sure we don't race against user-space applications * like LibUSB: */ - usbd_enum_lock(udev); + do_unlock = usbd_enum_lock(udev); for (x = 0; x != hub->nports; x++) { up = hub->ports + x; @@ -817,7 +821,8 @@ uhub_explore(struct usb_device *udev) up->restartcnt = 0; } - usbd_enum_unlock(udev); + if (do_unlock) + usbd_enum_unlock(udev); /* initial status checked */ sc->sc_flags |= UHUB_FLAG_DID_EXPLORE; diff --git a/sys/dev/usb/usb_request.c b/sys/dev/usb/usb_request.c index 4db5b7d9b39..1a366d632c5 100644 --- a/sys/dev/usb/usb_request.c +++ b/sys/dev/usb/usb_request.c @@ -389,9 +389,8 @@ usbd_get_hr_func(struct usb_device *udev) * than 30 seconds is treated like a 30 second timeout. This USB stack * does not allow control requests without a timeout. * - * NOTE: This function is thread safe. All calls to - * "usbd_do_request_flags" will be serialised by the use of an - * internal "sx_lock". + * NOTE: This function is thread safe. All calls to "usbd_do_request_flags" + * will be serialized by the use of the USB device enumeration lock. * * Returns: * 0: Success @@ -415,7 +414,7 @@ usbd_do_request_flags(struct usb_device *udev, struct mtx *mtx, uint16_t length; uint16_t temp; uint16_t acttemp; - uint8_t enum_locked; + uint8_t do_unlock; if (timeout < 50) { /* timeout is too small */ @@ -427,8 +426,6 @@ usbd_do_request_flags(struct usb_device *udev, struct mtx *mtx, } length = UGETW(req->wLength); - enum_locked = usbd_enum_is_locked(udev); - DPRINTFN(5, "udev=%p bmRequestType=0x%02x bRequest=0x%02x " "wValue=0x%02x%02x wIndex=0x%02x%02x wLength=0x%02x%02x\n", udev, req->bmRequestType, req->bRequest, @@ -458,18 +455,17 @@ usbd_do_request_flags(struct usb_device *udev, struct mtx *mtx, mtx_assert(mtx, MA_NOTOWNED); } + /* + * Grab the USB device enumeration SX-lock serialization is + * achieved when multiple threads are involved: + */ + do_unlock = usbd_enum_lock(udev); + /* * We need to allow suspend and resume at this point, else the * control transfer will timeout if the device is suspended! */ - if (enum_locked) - usbd_sr_unlock(udev); - - /* - * Grab the default sx-lock so that serialisation - * is achieved when multiple threads are involved: - */ - sx_xlock(&udev->ctrl_sx); + usbd_sr_unlock(udev); hr_func = usbd_get_hr_func(udev); @@ -713,10 +709,10 @@ usbd_do_request_flags(struct usb_device *udev, struct mtx *mtx, USB_XFER_UNLOCK(xfer); done: - sx_xunlock(&udev->ctrl_sx); + usbd_sr_lock(udev); - if (enum_locked) - usbd_sr_lock(udev); + if (do_unlock) + usbd_enum_unlock(udev); if ((mtx != NULL) && (mtx != &Giant)) mtx_lock(mtx); diff --git a/sys/sys/param.h b/sys/sys/param.h index c2904666678..26db635cffd 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -58,7 +58,7 @@ * in the range 5 to 9. */ #undef __FreeBSD_version -#define __FreeBSD_version 1000027 /* Master, propagated to newvers */ +#define __FreeBSD_version 1000028 /* Master, propagated to newvers */ /* * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD, From 74938cbb7f2c538a9185f8af87e38a90167e7372 Mon Sep 17 00:00:00 2001 From: Ian Lepore Date: Wed, 13 Feb 2013 15:09:16 +0000 Subject: [PATCH 0152/1476] Make the F_READAHEAD option to fcntl(2) work as documented: a value of zero now disables read-ahead. It used to effectively restore the system default readahead hueristic if it had been changed; a negative value now restores the default. Reviewed by: kib --- lib/libc/sys/fcntl.2 | 4 ++-- sys/kern/kern_descrip.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/libc/sys/fcntl.2 b/lib/libc/sys/fcntl.2 index c1745636747..8e0ca73c399 100644 --- a/lib/libc/sys/fcntl.2 +++ b/lib/libc/sys/fcntl.2 @@ -28,7 +28,7 @@ .\" @(#)fcntl.2 8.2 (Berkeley) 1/12/94 .\" $FreeBSD$ .\" -.Dd July 27, 2012 +.Dd February 8, 2013 .Dt FCNTL 2 .Os .Sh NAME @@ -171,7 +171,7 @@ argument, which is rounded up to the nearest block size. A zero value in .Fa arg -turns off read ahead. +turns off read ahead, a negative value restores the system default. .It Dv F_RDAHEAD Equivalent to Darwin counterpart which sets read ahead amount of 128KB when the third argument, diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index 87d75ea9ca8..fc74bdbd8d4 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -776,7 +776,7 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) } fhold(fp); FILEDESC_SUNLOCK(fdp); - if (arg != 0) { + if (arg >= 0) { vp = fp->f_vnode; error = vn_lock(vp, LK_SHARED); if (error != 0) { From f72761c6699e81a3c696e9ce043d346828dc79df Mon Sep 17 00:00:00 2001 From: Ian Lepore Date: Wed, 13 Feb 2013 15:13:47 +0000 Subject: [PATCH 0153/1476] Add a dependency so that when compiling in a static dtb, the kernel gets re-linked after changing the .dts source. Reviewed by: cognet, arm@ --- sys/conf/files | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/conf/files b/sys/conf/files index 374468e1c63..f392831b058 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1294,7 +1294,8 @@ dev/fb/splash.c optional splash dev/fdt/fdt_common.c optional fdt dev/fdt/fdt_pci.c optional fdt pci dev/fdt/fdt_slicer.c optional fdt cfi | fdt nand -dev/fdt/fdt_static_dtb.S optional fdt fdt_dtb_static +dev/fdt/fdt_static_dtb.S optional fdt fdt_dtb_static \ + dependency "$S/boot/fdt/dts/${FDT_DTS_FILE}" dev/fdt/fdtbus.c optional fdt dev/fdt/simplebus.c optional fdt dev/fe/if_fe.c optional fe From 626d8465fbf608ec33e89fce543a289fcba3ce1e Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Wed, 13 Feb 2013 15:43:15 +0000 Subject: [PATCH 0154/1476] Remove unused variable. MFC after: 1 week --- sys/dev/usb/wlan/if_upgt.c | 1 - sys/dev/usb/wlan/if_upgtvar.h | 1 - 2 files changed, 2 deletions(-) diff --git a/sys/dev/usb/wlan/if_upgt.c b/sys/dev/usb/wlan/if_upgt.c index 7f70d5a27e8..04671003e8e 100644 --- a/sys/dev/usb/wlan/if_upgt.c +++ b/sys/dev/usb/wlan/if_upgt.c @@ -1567,7 +1567,6 @@ upgt_tx_done(struct upgt_softc *sc, uint8_t *data) data_tx->ni = NULL; data_tx->addr = 0; data_tx->m = NULL; - data_tx->use = 0; DPRINTF(sc, UPGT_DEBUG_TX_PROC, "TX done: memaddr=0x%08x, status=0x%04x, rssi=%d, ", diff --git a/sys/dev/usb/wlan/if_upgtvar.h b/sys/dev/usb/wlan/if_upgtvar.h index fd38be1dc1c..6ef699fb182 100644 --- a/sys/dev/usb/wlan/if_upgtvar.h +++ b/sys/dev/usb/wlan/if_upgtvar.h @@ -352,7 +352,6 @@ struct upgt_data { struct ieee80211_node *ni; struct mbuf *m; uint32_t addr; - uint8_t use; STAILQ_ENTRY(upgt_data) next; }; typedef STAILQ_HEAD(, upgt_data) upgt_datahead; From d902844bbdee76f0f8e5b50c7d88d66f034f75e7 Mon Sep 17 00:00:00 2001 From: Niclas Zeising Date: Wed, 13 Feb 2013 15:46:33 +0000 Subject: [PATCH 0155/1476] Add strchrnul(), a GNU function similar to strchr(), except that it returns a pointer to the end of the string, rather than NULL, if the character was not found. Approved by: theraven --- include/string.h | 3 +++ lib/libc/string/Makefile.inc | 6 ++--- lib/libc/string/Symbol.map | 1 + lib/libc/string/strchr.3 | 31 +++++++++++++++++++++-- lib/libc/string/strchrnul.c | 48 ++++++++++++++++++++++++++++++++++++ 5 files changed, 84 insertions(+), 5 deletions(-) create mode 100644 lib/libc/string/strchrnul.c diff --git a/include/string.h b/include/string.h index e6a910b96fd..dc18a75161d 100644 --- a/include/string.h +++ b/include/string.h @@ -74,6 +74,9 @@ char *strcasestr(const char *, const char *) __pure; #endif char *strcat(char * __restrict, const char * __restrict); char *strchr(const char *, int) __pure; +#if defined(_GNU_SOURCE) +char *strchrnul(const char*, int) __pure; +#endif int strcmp(const char *, const char *) __pure; int strcoll(const char *, const char *); char *strcpy(char * __restrict, const char * __restrict); diff --git a/lib/libc/string/Makefile.inc b/lib/libc/string/Makefile.inc index cd06fc89968..f98dc92f04a 100644 --- a/lib/libc/string/Makefile.inc +++ b/lib/libc/string/Makefile.inc @@ -10,9 +10,9 @@ MISRCS+=bcmp.c bcopy.c bzero.c ffs.c ffsl.c ffsll.c fls.c flsl.c flsll.c \ memccpy.c memchr.c memrchr.c memcmp.c \ memcpy.c memmem.c memmove.c memset.c \ stpcpy.c stpncpy.c strcasecmp.c \ - strcat.c strcasestr.c strchr.c strcmp.c strcoll.c strcpy.c strcspn.c \ - strdup.c strerror.c strlcat.c strlcpy.c strlen.c strmode.c strncat.c \ - strncmp.c strncpy.c strndup.c strnlen.c strnstr.c \ + strcat.c strcasestr.c strchr.c strchrnul.c strcmp.c strcoll.c strcpy.c\ + strcspn.c strdup.c strerror.c strlcat.c strlcpy.c strlen.c strmode.c \ + strncat.c strncmp.c strncpy.c strndup.c strnlen.c strnstr.c \ strpbrk.c strrchr.c strsep.c strsignal.c strspn.c strstr.c strtok.c \ strxfrm.c swab.c wcpcpy.c wcpncpy.c wcscasecmp.c wcscat.c \ wcschr.c wcscmp.c wcscoll.c wcscpy.c wcscspn.c wcsdup.c \ diff --git a/lib/libc/string/Symbol.map b/lib/libc/string/Symbol.map index ef23465e182..8e801659f35 100644 --- a/lib/libc/string/Symbol.map +++ b/lib/libc/string/Symbol.map @@ -94,6 +94,7 @@ FBSD_1.1 { FBSD_1.3 { strcasecmp_l; strcasestr_l; + strchrnul; strncasecmp_l; wcswidth_l; wcwidth_l; diff --git a/lib/libc/string/strchr.3 b/lib/libc/string/strchr.3 index 984eb065dd6..019b9236f42 100644 --- a/lib/libc/string/strchr.3 +++ b/lib/libc/string/strchr.3 @@ -32,11 +32,11 @@ .\" @(#)strchr.3 8.2 (Berkeley) 4/19/94 .\" $FreeBSD$ .\" -.Dd April 19, 1994 +.Dd February 13, 2013 .Dt STRCHR 3 .Os .Sh NAME -.Nm strchr , strrchr +.Nm strchr , strrchr , strchrnul .Nd locate character in string .Sh LIBRARY .Lb libc @@ -46,6 +46,8 @@ .Fn strchr "const char *s" "int c" .Ft "char *" .Fn strrchr "const char *s" "int c" +.Ft "char *" +.Fn strchrnul "const char *s" "int c" .Sh DESCRIPTION The .Fn strchr @@ -69,6 +71,18 @@ function is identical to .Fn strchr except it locates the last occurrence of .Fa c . +.Pp +The +.Fn strchrnul +function is identical to +.Fn strchr +except that if +.Fa c +is not found in +.Fa s +a pointer to the terminating +.Ql \e0 +is returned. .Sh RETURN VALUES The functions .Fn strchr @@ -77,6 +91,11 @@ and return a pointer to the located character, or .Dv NULL if the character does not appear in the string. +.Pp +.Fn strchrnul +returns a pointer to the terminating +.Ql \e0 +if the character does not appear in the string. .Sh SEE ALSO .Xr memchr 3 , .Xr memmem 3 , @@ -94,3 +113,11 @@ and .Fn strrchr conform to .St -isoC . +The +.Fn strchrnul +is a GNU extension . +.Sh History +The +.Fn strchrnul +function first appeared in glibc 2.1.1 and was added in +.Fx 10.0 . diff --git a/lib/libc/string/strchrnul.c b/lib/libc/string/strchrnul.c new file mode 100644 index 00000000000..98e652db83c --- /dev/null +++ b/lib/libc/string/strchrnul.c @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2013 Niclas Zeising + * 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 +__FBSDID("$FreeBSD$"); + +#include +#include + +__weak_reference(__strchrnul, strchrnul); + +char * +__strchrnul(const char *p, int ch) +{ + char c; + + c = ch; + for (;; ++p) { + if (*p == c || *p == '\0') + return ((char *)p); + } + /* NOTREACHED */ +} + From 314caba11ce22f88d01612c204070797143ae8dc Mon Sep 17 00:00:00 2001 From: Xin LI Date: Wed, 13 Feb 2013 17:30:54 +0000 Subject: [PATCH 0156/1476] Restore De Bruijn algorithm for sparc64 where the compiler rely on a library function for __builtin_c?z. Tested by: Michael Moll --- .../opensolaris/uts/common/fs/zfs/lz4.c | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/lz4.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/lz4.c index b3939d47174..d2f2bc3e5a4 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/lz4.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/lz4.c @@ -237,6 +237,16 @@ lz4_decompress(void *s_start, void *d_start, size_t s_len, size_t d_len, int n) #define LZ4_FORCE_UNALIGNED_ACCESS 1 #endif +/* + * FreeBSD: can't use GCC's __builtin_ctz when using sparc64 because + * gcc currently rely on libcompiler_rt. + * + * TODO: revisit this when situation changes. + */ +#if defined(__sparc64__) +#define LZ4_FORCE_SW_BITCOUNT +#endif + /* * Compiler Options */ @@ -378,9 +388,38 @@ static inline int LZ4_NbCommonBytes(register U64 val) { #if defined(LZ4_BIG_ENDIAN) +#if !defined(LZ4_FORCE_SW_BITCOUNT) return (__builtin_clzll(val) >> 3); #else + int r; + if (!(val >> 32)) { + r = 4; + } else { + r = 0; + val >>= 32; + } + if (!(val >> 16)) { + r += 2; + val >>= 8; + } else { + val >>= 24; + } + r += (!val); + return (r); +#endif +#else +#if !defined(LZ4_FORCE_SW_BITCOUNT) return (__builtin_ctzll(val) >> 3); +#else + static const int DeBruijnBytePos[64] = + { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, + 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, + 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, + 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 + }; + return DeBruijnBytePos[((U64) ((val & -val) * 0x0218A392CDABBD3F)) >> + 58]; +#endif #endif } @@ -390,9 +429,33 @@ static inline int LZ4_NbCommonBytes(register U32 val) { #if defined(LZ4_BIG_ENDIAN) +#if !defined(LZ4_FORCE_SW_BITCOUNT) return (__builtin_clz(val) >> 3); #else + int r; + if (!(val >> 16)) { + r = 2; + val >>= 8; + } else { + r = 0; + val >>= 24; + } + r += (!val); + return (r); +#endif +#else +#if !defined(LZ4_FORCE_SW_BITCOUNT) return (__builtin_ctz(val) >> 3); +#else + static const int DeBruijnBytePos[32] = { + 0, 0, 3, 0, 3, 1, 3, 0, + 3, 2, 2, 1, 3, 2, 0, 1, + 3, 3, 1, 2, 2, 2, 2, 0, + 3, 1, 2, 0, 1, 0, 1, 1 + }; + return DeBruijnBytePos[((U32) ((val & -(S32) val) * 0x077CB531U)) >> + 27]; +#endif #endif } From f3b8b34a882a09ff73facc4c6ce7cdcad59b8656 Mon Sep 17 00:00:00 2001 From: Jung-uk Kim Date: Wed, 13 Feb 2013 22:15:56 +0000 Subject: [PATCH 0157/1476] Import OpenSSL 1.0.1e. Approved by: secteam (delphij, simon), benl (silence) --- CHANGES | 47 ++ Configure | 18 +- FAQ | 4 +- FREEBSD-upgrade | 6 +- Makefile | 6 +- Makefile.org | 4 +- NEWS | 12 + PROBLEMS | 14 + README | 4 +- apps/apps.c | 5 +- apps/ca.c | 1 + apps/cms.c | 4 + apps/dgst.c | 4 +- apps/dhparam.c | 1 - apps/dsaparam.c | 9 +- apps/genrsa.c | 2 +- apps/ocsp.c | 2 +- apps/s_cb.c | 6 +- apps/s_client.c | 20 +- apps/s_server.c | 63 +- apps/speed.c | 4 +- apps/srp.c | 30 +- apps/verify.c | 27 +- apps/x509.c | 4 +- crypto/aes/asm/aes-mips.pl | 20 +- crypto/aes/asm/aes-s390x.pl | 95 +-- crypto/aes/asm/aes-x86_64.pl | 3 +- crypto/aes/asm/aesni-sha1-x86_64.pl | 3 +- crypto/aes/asm/aesni-x86_64.pl | 3 +- crypto/aes/asm/bsaes-x86_64.pl | 3 +- crypto/aes/asm/vpaes-x86_64.pl | 3 +- crypto/asn1/a_strex.c | 1 + crypto/asn1/a_verify.c | 6 + crypto/asn1/x_pubkey.c | 5 +- crypto/bio/bss_dgram.c | 85 +- crypto/bn/asm/mips.pl | 2 +- crypto/bn/asm/modexp512-x86_64.pl | 3 +- crypto/bn/asm/x86_64-gf2m.pl | 2 +- crypto/bn/asm/x86_64-mont.pl | 3 +- crypto/bn/asm/x86_64-mont5.pl | 3 +- crypto/bn/bn_div.c | 2 + crypto/bn/bn_gcd.c | 1 + crypto/bn/bn_lcl.h | 11 +- crypto/camellia/asm/cmll-x86_64.pl | 3 +- crypto/cms/cms_cd.c | 2 + crypto/cms/cms_enc.c | 2 +- crypto/cms/cms_lib.c | 2 - crypto/conf/conf_mall.c | 1 + crypto/cryptlib.c | 16 +- crypto/cryptlib.h | 2 +- crypto/crypto.h | 11 +- crypto/des/set_key.c | 3 +- crypto/des/str2key.c | 2 +- crypto/ec/ec.h | 28 +- crypto/ec/ec_key.c | 13 +- crypto/ec/ec_pmeth.c | 2 +- crypto/ec/ecp_mont.c | 1 - crypto/ec/ectest.c | 2 +- crypto/ecdh/Makefile | 17 +- crypto/ecdh/ech_key.c | 3 - crypto/ecdh/ech_lib.c | 11 +- crypto/ecdsa/ecs_lib.c | 11 +- crypto/err/err_all.c | 19 +- crypto/evp/Makefile | 55 +- crypto/evp/digest.c | 1 + crypto/evp/e_aes.c | 5 +- crypto/evp/e_aes_cbc_hmac_sha1.c | 216 ++++- crypto/evp/evp.h | 15 +- crypto/evp/evp_cnf.c | 125 +++ crypto/evp/evp_err.c | 6 + crypto/evp/m_dss.c | 2 +- crypto/evp/m_dss1.c | 2 +- crypto/evp/m_sha1.c | 2 +- crypto/evp/p_sign.c | 2 +- crypto/evp/p_verify.c | 2 +- crypto/md4/md4_dgst.c | 31 +- crypto/md4/md4_locl.h | 8 +- crypto/md5/asm/md5-x86_64.pl | 3 +- crypto/md5/md5_locl.h | 8 +- crypto/mdc2/mdc2dgst.c | 2 +- crypto/mem.c | 2 +- crypto/modes/asm/ghash-x86.pl | 6 +- crypto/modes/asm/ghash-x86_64.pl | 3 +- crypto/modes/gcm128.c | 4 +- crypto/objects/o_names.c | 2 +- crypto/ocsp/ocsp_vfy.c | 10 +- crypto/opensslv.h | 6 +- crypto/pem/pem_all.c | 161 ++++ crypto/pem/pem_lib.c | 27 +- crypto/pem/pem_seal.c | 6 +- crypto/perlasm/cbc.pl | 2 +- crypto/perlasm/x86masm.pl | 1 + crypto/pkcs12/p12_key.c | 24 +- crypto/pkcs7/bio_pk7.c | 2 +- crypto/ppccap.c | 11 + crypto/rand/md_rand.c | 2 +- crypto/rand/rand_lib.c | 7 +- crypto/rand/randfile.c | 2 + crypto/rc4/asm/rc4-md5-x86_64.pl | 3 +- crypto/rc4/asm/rc4-x86_64.pl | 3 +- crypto/ripemd/rmd_dgst.c | 30 +- crypto/ripemd/rmd_locl.h | 10 +- crypto/rsa/rsa.h | 2 +- crypto/rsa/rsa_eay.c | 6 +- crypto/rsa/rsa_oaep.c | 2 +- crypto/sha/asm/sha1-armv4-large.pl | 2 +- crypto/sha/asm/sha1-ia64.pl | 3 +- crypto/sha/asm/sha1-sparcv9a.pl | 2 +- crypto/sha/asm/sha1-x86_64.pl | 3 +- crypto/sha/asm/sha512-586.pl | 16 +- crypto/sha/asm/sha512-x86_64.pl | 3 +- crypto/sha/sha1_one.c | 2 +- crypto/sha/sha1dgst.c | 2 +- crypto/sha/sha256.c | 6 +- crypto/sha/sha_dgst.c | 2 +- crypto/sha/sha_locl.h | 40 +- crypto/sparccpuid.S | 4 +- crypto/srp/srp_vfy.c | 5 +- crypto/symhacks.h | 14 +- crypto/ui/ui_openssl.c | 6 + crypto/whrlpool/asm/wp-mmx.pl | 2 +- crypto/whrlpool/asm/wp-x86_64.pl | 3 +- crypto/x509/x509_cmp.c | 15 +- crypto/x509/x509_vfy.c | 4 +- crypto/x509v3/v3_purp.c | 4 +- crypto/x86_64cpuid.pl | 3 +- crypto/x86cpuid.pl | 4 +- doc/apps/CA.pl.pod | 8 +- doc/apps/verify.pod | 60 +- doc/apps/x509.pod | 5 + doc/crypto/EVP_PKEY_CTX_ctrl.pod | 2 +- doc/crypto/EVP_PKEY_decrypt.pod | 2 +- doc/crypto/EVP_PKEY_derive.pod | 2 +- doc/crypto/EVP_PKEY_encrypt.pod | 2 +- doc/crypto/EVP_PKEY_get_default_digest.pod | 2 +- doc/crypto/EVP_PKEY_keygen.pod | 2 +- doc/crypto/EVP_PKEY_sign.pod | 2 +- doc/crypto/EVP_PKEY_verify.pod | 2 +- ...ecover.pod => EVP_PKEY_verify_recover.pod} | 22 +- engines/ccgost/gost89.c | 14 +- engines/ccgost/gost_crypt.c | 29 +- engines/ccgost/gost_eng.c | 17 +- engines/ccgost/gost_lcl.h | 4 +- engines/ccgost/gosthash.c | 2 +- engines/e_capi.c | 5 +- ssl/Makefile | 24 +- ssl/d1_enc.c | 59 +- ssl/d1_pkt.c | 93 ++- ssl/d1_srtp.c | 5 +- ssl/dtls1.h | 8 +- ssl/s2_clnt.c | 14 +- ssl/s2_pkt.c | 3 +- ssl/s2_srvr.c | 16 +- ssl/s3_both.c | 14 +- ssl/s3_cbc.c | 790 ++++++++++++++++++ ssl/s3_clnt.c | 4 +- ssl/s3_enc.c | 117 ++- ssl/s3_lib.c | 16 +- ssl/s3_pkt.c | 105 +-- ssl/s3_srvr.c | 19 +- ssl/ssl.h | 8 +- ssl/ssl3.h | 6 + ssl/ssl_algs.c | 1 + ssl/ssl_cert.c | 4 +- ssl/ssl_ciph.c | 5 +- ssl/ssl_err.c | 1 + ssl/ssl_lib.c | 26 +- ssl/ssl_locl.h | 44 +- ssl/ssl_rsa.c | 14 +- ssl/ssltest.c | 2 +- ssl/t1_enc.c | 159 ++-- ssl/t1_lib.c | 133 ++- ssl/tls_srp.c | 3 +- util/libeay.num | 3 +- util/pl/VC-32.pl | 2 +- 175 files changed, 2672 insertions(+), 874 deletions(-) create mode 100644 crypto/evp/evp_cnf.c rename doc/crypto/{EVP_PKEY_verifyrecover.pod => EVP_PKEY_verify_recover.pod} (76%) create mode 100644 ssl/s3_cbc.c diff --git a/CHANGES b/CHANGES index 7013e4c12c0..ca82ad295d5 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,53 @@ OpenSSL CHANGES _______________ + Changes between 1.0.1d and 1.0.1e [11 Feb 2013] + + *) + + Changes between 1.0.1c and 1.0.1d [5 Feb 2013] + + *) Make the decoding of SSLv3, TLS and DTLS CBC records constant time. + + This addresses the flaw in CBC record processing discovered by + Nadhem Alfardan and Kenny Paterson. Details of this attack can be found + at: http://www.isg.rhul.ac.uk/tls/ + + Thanks go to Nadhem Alfardan and Kenny Paterson of the Information + Security Group at Royal Holloway, University of London + (www.isg.rhul.ac.uk) for discovering this flaw and Adam Langley and + Emilia Ksper for the initial patch. + (CVE-2013-0169) + [Emilia Ksper, Adam Langley, Ben Laurie, Andy Polyakov, Steve Henson] + + *) Fix flaw in AESNI handling of TLS 1.2 and 1.1 records for CBC mode + ciphersuites which can be exploited in a denial of service attack. + Thanks go to and to Adam Langley for discovering + and detecting this bug and to Wolfgang Ettlinger + for independently discovering this issue. + (CVE-2012-2686) + [Adam Langley] + + *) Return an error when checking OCSP signatures when key is NULL. + This fixes a DoS attack. (CVE-2013-0166) + [Steve Henson] + + *) Make openssl verify return errors. + [Chris Palmer and Ben Laurie] + + *) Call OCSP Stapling callback after ciphersuite has been chosen, so + the right response is stapled. Also change SSL_get_certificate() + so it returns the certificate actually sent. + See http://rt.openssl.org/Ticket/Display.html?id=2836. + [Rob Stradling ] + + *) Fix possible deadlock when decoding public keys. + [Steve Henson] + + *) Don't use TLS 1.0 record version number in initial client hello + if renegotiating. + [Steve Henson] + Changes between 1.0.1b and 1.0.1c [10 May 2012] *) Sanity check record length before skipping explicit IV in TLS diff --git a/Configure b/Configure index cbbf4de8b25..9c803dc0663 100755 --- a/Configure +++ b/Configure @@ -171,20 +171,22 @@ my %table=( "debug-ben-openbsd","gcc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DBN_CTX_DEBUG -DCRYPTO_MDEBUG -DPEDANTIC -DDEBUG_SAFESTACK -DOPENSSL_OPENBSD_DEV_CRYPTO -DOPENSSL_NO_ASM -O2 -pedantic -Wall -Wshadow -Werror -pipe::(unknown)::::", "debug-ben-openbsd-debug","gcc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DBN_CTX_DEBUG -DCRYPTO_MDEBUG -DPEDANTIC -DDEBUG_SAFESTACK -DOPENSSL_OPENBSD_DEV_CRYPTO -DOPENSSL_NO_ASM -g3 -O2 -pedantic -Wall -Wshadow -Werror -pipe::(unknown)::::", "debug-ben-debug", "gcc44:$gcc_devteam_warn -DBN_DEBUG -DCONF_DEBUG -DDEBUG_SAFESTACK -DDEBUG_UNUSED -g3 -O2 -pipe::(unknown)::::::", +"debug-ben-debug-64", "gcc:$gcc_devteam_warn -Wno-error=overlength-strings -DBN_DEBUG -DCONF_DEBUG -DDEBUG_SAFESTACK -DDEBUG_UNUSED -g3 -O3 -pipe::${BSDthreads}:::SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", "debug-ben-macos", "cc:$gcc_devteam_warn -arch i386 -DBN_DEBUG -DCONF_DEBUG -DDEBUG_SAFESTACK -DDEBUG_UNUSED -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -O3 -DL_ENDIAN -g3 -pipe::(unknown)::-Wl,-search_paths_first::::", "debug-ben-macos-gcc46", "gcc-mp-4.6:$gcc_devteam_warn -Wconversion -DBN_DEBUG -DCONF_DEBUG -DDEBUG_SAFESTACK -DDEBUG_UNUSED -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -O3 -DL_ENDIAN -g3 -pipe::(unknown)::::::", +"debug-ben-darwin64","cc:$gcc_devteam_warn -Wno-language-extension-token -Wno-extended-offsetof -arch x86_64 -O3 -DL_ENDIAN -Wall::-D_REENTRANT:MACOSX:-Wl,-search_paths_first%:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL:".eval{my $asm=$x86_64_asm;$asm=~s/rc4\-[^:]+//;$asm}.":macosx:dlfcn:darwin-shared:-fPIC -fno-common:-arch x86_64 -dynamiclib:.\$(SHLIB_MAJOR).\$(SHLIB_MINOR).dylib", "debug-ben-no-opt", "gcc: -Wall -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations -DDEBUG_SAFESTACK -DCRYPTO_MDEBUG -Werror -DL_ENDIAN -DTERMIOS -Wall -g3::(unknown)::::::", "debug-ben-strict", "gcc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DBN_CTX_DEBUG -DCRYPTO_MDEBUG -DCONST_STRICT -O2 -Wall -Wshadow -Werror -Wpointer-arith -Wcast-qual -Wwrite-strings -pipe::(unknown)::::::", "debug-rse","cc:-DTERMIOS -DL_ENDIAN -pipe -O -g -ggdb3 -Wall::(unknown):::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}", "debug-bodo", "gcc:$gcc_devteam_warn -DBN_DEBUG -DBN_DEBUG_RAND -DCONF_DEBUG -DBIO_PAIR_DEBUG -m64 -DL_ENDIAN -DTERMIO -g -DMD32_REG_T=int::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::64", "debug-ulf", "gcc:-DTERMIOS -DL_ENDIAN -march=i486 -Wall -DBN_DEBUG -DBN_DEBUG_RAND -DREF_CHECK -DCONF_DEBUG -DBN_CTX_DEBUG -DCRYPTO_MDEBUG -DOPENSSL_NO_ASM -g -Wformat -Wshadow -Wmissing-prototypes -Wmissing-declarations:::CYGWIN32:::${no_asm}:win32:cygwin-shared:::.dll", -"debug-steve64", "gcc:$gcc_devteam_warn -m64 -DL_ENDIAN -DTERMIO -DCONF_DEBUG -DDEBUG_SAFESTACK -g::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +"debug-steve64", "gcc:$gcc_devteam_warn -m64 -DL_ENDIAN -DTERMIO -DCONF_DEBUG -DDEBUG_SAFESTACK -Wno-overlength-strings -g::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", "debug-steve32", "gcc:$gcc_devteam_warn -m32 -DL_ENDIAN -DCONF_DEBUG -DDEBUG_SAFESTACK -g -pipe::-D_REENTRANT::-rdynamic -ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-fPIC:-m32:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", "debug-steve-opt", "gcc:$gcc_devteam_warn -m64 -O3 -DL_ENDIAN -DTERMIO -DCONF_DEBUG -DDEBUG_SAFESTACK -g::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:linux-shared:-fPIC:-m64:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -"debug-levitte-linux-elf","gcc:-DLEVITTE_DEBUG -DREF_CHECK -DCONF_DEBUG -DBN_DEBUG -DBN_DEBUG_RAND -DCRYPTO_MDEBUG -DENGINE_CONF_DEBUG -DL_ENDIAN -DTERMIO -D_POSIX_SOURCE -DPEDANTIC -ggdb -g3 -mcpu=i486 -pedantic -ansi -Wall -Wshadow -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wno-long-long -Wundef -Wconversion -pipe::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -"debug-levitte-linux-noasm","gcc:-DLEVITTE_DEBUG -DREF_CHECK -DCONF_DEBUG -DBN_DEBUG -DBN_DEBUG_RAND -DCRYPTO_MDEBUG -DENGINE_CONF_DEBUG -DOPENSSL_NO_ASM -DL_ENDIAN -DTERMIO -D_POSIX_SOURCE -DPEDANTIC -ggdb -g3 -mcpu=i486 -pedantic -ansi -Wall -Wshadow -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wno-long-long -Wundef -Wconversion -pipe::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -"debug-levitte-linux-elf-extreme","gcc:-DLEVITTE_DEBUG -DREF_CHECK -DCONF_DEBUG -DBN_DEBUG -DBN_DEBUG_RAND -DCRYPTO_MDEBUG -DENGINE_CONF_DEBUG -DL_ENDIAN -DTERMIO -D_POSIX_SOURCE -DPEDANTIC -ggdb -g3 -mcpu=i486 -pedantic -ansi -Wall -W -Wundef -Wshadow -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wno-long-long -Wundef -Wconversion -pipe::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -"debug-levitte-linux-noasm-extreme","gcc:-DLEVITTE_DEBUG -DREF_CHECK -DCONF_DEBUG -DBN_DEBUG -DBN_DEBUG_RAND -DCRYPTO_MDEBUG -DENGINE_CONF_DEBUG -DOPENSSL_NO_ASM -DL_ENDIAN -DTERMIO -D_POSIX_SOURCE -DPEDANTIC -ggdb -g3 -mcpu=i486 -pedantic -ansi -Wall -W -Wundef -Wshadow -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wno-long-long -Wundef -Wconversion -pipe::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +"debug-levitte-linux-elf","gcc:-DLEVITTE_DEBUG -DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DCRYPTO_MDEBUG -DL_ENDIAN -ggdb -g3 -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +"debug-levitte-linux-noasm","gcc:-DLEVITTE_DEBUG -DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DCRYPTO_MDEBUG -DOPENSSL_NO_ASM -DL_ENDIAN -ggdb -g3 -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +"debug-levitte-linux-elf-extreme","gcc:-DLEVITTE_DEBUG -DREF_CHECK -DCONF_DEBUG -DBN_DEBUG -DBN_DEBUG_RAND -DCRYPTO_MDEBUG -DENGINE_CONF_DEBUG -DL_ENDIAN -DTERMIO -DPEDANTIC -ggdb -g3 -pedantic -ansi -Wall -W -Wundef -Wshadow -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wno-long-long -Wundef -Wconversion -pipe::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", +"debug-levitte-linux-noasm-extreme","gcc:-DLEVITTE_DEBUG -DREF_CHECK -DCONF_DEBUG -DBN_DEBUG -DBN_DEBUG_RAND -DCRYPTO_MDEBUG -DENGINE_CONF_DEBUG -DOPENSSL_NO_ASM -DL_ENDIAN -DTERMIO -DPEDANTIC -ggdb -g3 -pedantic -ansi -Wall -W -Wundef -Wshadow -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wno-long-long -Wundef -Wconversion -pipe::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", "debug-geoff32","gcc:-DBN_DEBUG -DBN_DEBUG_RAND -DBN_STRICT -DPURIFY -DOPENSSL_NO_DEPRECATED -DOPENSSL_NO_ASM -DOPENSSL_NO_INLINE_ASM -DL_ENDIAN -DTERMIO -DPEDANTIC -O1 -ggdb2 -Wall -Werror -Wundef -pedantic -Wshadow -Wpointer-arith -Wbad-function-cast -Wcast-align -Wsign-compare -Wmissing-prototypes -Wmissing-declarations -Wno-long-long::-D_REENTRANT::-ldl:BN_LLONG:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", "debug-geoff64","gcc:-DBN_DEBUG -DBN_DEBUG_RAND -DBN_STRICT -DPURIFY -DOPENSSL_NO_DEPRECATED -DOPENSSL_NO_ASM -DOPENSSL_NO_INLINE_ASM -DL_ENDIAN -DTERMIO -DPEDANTIC -O1 -ggdb2 -Wall -Werror -Wundef -pedantic -Wshadow -Wpointer-arith -Wbad-function-cast -Wcast-align -Wsign-compare -Wmissing-prototypes -Wmissing-declarations -Wno-long-long::-D_REENTRANT::-ldl:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_UNROLL BF_PTR:${no_asm}:dlfcn:linux-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", "debug-linux-pentium","gcc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DBN_CTX_DEBUG -DCRYPTO_MDEBUG -DL_ENDIAN -DTERMIO -g -mcpu=pentium -Wall::-D_REENTRANT::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn", @@ -243,7 +245,7 @@ my %table=( "solaris-sparcv7-cc","cc:-xO5 -xstrconst -xdepend -Xa -DB_ENDIAN -DBN_DIV2W::-D_REENTRANT::-lsocket -lnsl -ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_PTR DES_RISC1 DES_UNROLL BF_PTR:${no_asm}:dlfcn:solaris-shared:-KPIC:-G -dy -z text:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", "solaris-sparcv8-cc","cc:-xarch=v8 -xO5 -xstrconst -xdepend -Xa -DB_ENDIAN -DBN_DIV2W::-D_REENTRANT::-lsocket -lnsl -ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_PTR DES_RISC1 DES_UNROLL BF_PTR:${sparcv8_asm}:dlfcn:solaris-shared:-KPIC:-G -dy -z text:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", "solaris-sparcv9-cc","cc:-xtarget=ultra -xarch=v8plus -xO5 -xstrconst -xdepend -Xa -DB_ENDIAN -DBN_DIV2W::-D_REENTRANT:ULTRASPARC:-lsocket -lnsl -ldl:BN_LLONG RC4_CHAR RC4_CHUNK_LL DES_PTR DES_RISC1 DES_UNROLL BF_PTR:${sparcv9_asm}:dlfcn:solaris-shared:-KPIC:-G -dy -z text:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -"solaris64-sparcv9-cc","cc:-xtarget=ultra -xarch=v9 -xO5 -xstrconst -xdepend -Xa -DB_ENDIAN::-D_REENTRANT:ULTRASPARC:-lsocket -lnsl -ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_PTR DES_RISC1 DES_UNROLL BF_PTR:${sparcv9_asm}:dlfcn:solaris-shared:-KPIC:-xarch=v9 -G -dy -z text:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):/usr/ccs/bin/ar rs::/64", +"solaris64-sparcv9-cc","cc:-xtarget=ultra -xarch=v9 -xO5 -xstrconst -xdepend -Xa -DB_ENDIAN::-D_REENTRANT:ULTRASPARC:-lsocket -lnsl -ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_INT DES_PTR DES_RISC1 DES_UNROLL BF_PTR:${sparcv9_asm}:dlfcn:solaris-shared:-KPIC:-xarch=v9 -G -dy -z text:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):::/64", #### "debug-solaris-sparcv8-cc","cc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DBN_CTX_DEBUG -DCRYPTO_MDEBUG_ALL -xarch=v8 -g -O -xstrconst -Xa -DB_ENDIAN -DBN_DIV2W::-D_REENTRANT::-lsocket -lnsl -ldl:BN_LLONG RC4_CHAR RC4_CHUNK DES_PTR DES_RISC1 DES_UNROLL BF_PTR:${sparcv8_asm}:dlfcn:solaris-shared:-KPIC:-G -dy -z text:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", "debug-solaris-sparcv9-cc","cc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DBN_CTX_DEBUG -DCRYPTO_MDEBUG_ALL -xtarget=ultra -xarch=v8plus -g -O -xstrconst -Xa -DB_ENDIAN -DBN_DIV2W::-D_REENTRANT:ULTRASPARC:-lsocket -lnsl -ldl:BN_LLONG RC4_CHAR RC4_CHUNK_LL DES_PTR DES_RISC1 DES_UNROLL BF_PTR:${sparcv9_asm}:dlfcn:solaris-shared:-KPIC:-G -dy -z text:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", @@ -464,8 +466,8 @@ my %table=( "aix64-gcc","gcc:-maix64 -O -DB_ENDIAN::-pthread:AIX::SIXTY_FOUR_BIT_LONG RC4_CHAR:${ppc64_asm}:aix64:dlfcn:aix-shared::-maix64 -shared -Wl,-G:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)::-X64", # Below targets assume AIX 5. Idea is to effectively disregard $OBJECT_MODE # at build time. $OBJECT_MODE is respected at ./config stage! -"aix-cc", "cc:-q32 -O -DB_ENDIAN -qmaxmem=16384 -qro -qroconst::-qthreaded:AIX::BN_LLONG RC4_CHAR:${ppc32_asm}:aix32:dlfcn:aix-shared::-q32 -G:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)::-X 32", -"aix64-cc", "cc:-q64 -O -DB_ENDIAN -qmaxmem=16384 -qro -qroconst::-qthreaded:AIX::SIXTY_FOUR_BIT_LONG RC4_CHAR:${ppc64_asm}:aix64:dlfcn:aix-shared::-q64 -G:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)::-X 64", +"aix-cc", "cc:-q32 -O -DB_ENDIAN -qmaxmem=16384 -qro -qroconst::-qthreaded -D_THREAD_SAFE:AIX::BN_LLONG RC4_CHAR:${ppc32_asm}:aix32:dlfcn:aix-shared::-q32 -G:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)::-X 32", +"aix64-cc", "cc:-q64 -O -DB_ENDIAN -qmaxmem=16384 -qro -qroconst::-qthreaded -D_THREAD_SAFE:AIX::SIXTY_FOUR_BIT_LONG RC4_CHAR:${ppc64_asm}:aix64:dlfcn:aix-shared::-q64 -G:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)::-X 64", # # Cray T90 and similar (SDSC) diff --git a/FAQ b/FAQ index bb6f7e2d297..35780f807bd 100644 --- a/FAQ +++ b/FAQ @@ -83,11 +83,11 @@ OpenSSL - Frequently Asked Questions * Which is the current version of OpenSSL? The current version is available from . -OpenSSL 1.0.1c was released on May 10th, 2012. +OpenSSL 1.0.1e was released on Feb 11th, 2013. In addition to the current stable release, you can also access daily snapshots of the OpenSSL development version at , or get it by anonymous CVS access. +ftp://ftp.openssl.org/snapshot/>, or get it by anonymous Git access. * Where is the documentation? diff --git a/FREEBSD-upgrade b/FREEBSD-upgrade index 38ba519cfa7..1aa5b7021ee 100644 --- a/FREEBSD-upgrade +++ b/FREEBSD-upgrade @@ -11,8 +11,8 @@ First, read http://wiki.freebsd.org/SubversionPrimer/VendorImports # Xlist setenv XLIST /FreeBSD/work/openssl/svn-FREEBSD-files/FREEBSD-Xlist setenv FSVN "svn+ssh://svn.freebsd.org/base" -setenv OSSLVER 1.0.1c -# OSSLTAG format: v1_0_1c +setenv OSSLVER 1.0.1e +# OSSLTAG format: v1_0_1e ###setenv OSSLTAG v`echo ${OSSLVER} | tr . _` @@ -35,7 +35,7 @@ comm -23 old new # See that files to add makes sense comm -13 old new -tar -cf - -C openssl-${OSSLVER} . | tar xf - -C dist +tar -cf - -C openssl-${OSSLVER} . | tar -xf - -C dist cd dist comm -23 ../old ../new | xargs svn rm # Make sure to remove empty directories diff --git a/Makefile b/Makefile index d5db11b4177..54e3541613a 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ ## Makefile for OpenSSL ## -VERSION=1.0.1c +VERSION=1.0.1e MAJOR=1 MINOR=0.1 SHLIB_VERSION_NUMBER=1.0.0 @@ -71,7 +71,7 @@ RANLIB= /usr/bin/ranlib NM= nm PERL= /usr/bin/perl TAR= tar -TARFLAGS= --no-recursion +TARFLAGS= --no-recursion --record-size=10240 MAKEDEPPROG=makedepend LIBDIR=lib @@ -446,7 +446,7 @@ rehash.time: certs apps [ -x "apps/openssl.exe" ] && OPENSSL="apps/openssl.exe" || :; \ OPENSSL_DEBUG_MEMORY=on; \ export OPENSSL OPENSSL_DEBUG_MEMORY; \ - $(PERL) tools/c_rehash certs) && \ + $(PERL) tools/c_rehash certs/demo) && \ touch rehash.time; \ else :; fi diff --git a/Makefile.org b/Makefile.org index 55273ea364a..2db31ead6fa 100644 --- a/Makefile.org +++ b/Makefile.org @@ -69,7 +69,7 @@ RANLIB= ranlib NM= nm PERL= perl TAR= tar -TARFLAGS= --no-recursion +TARFLAGS= --no-recursion --record-size=10240 MAKEDEPPROG=makedepend LIBDIR=lib @@ -444,7 +444,7 @@ rehash.time: certs apps [ -x "apps/openssl.exe" ] && OPENSSL="apps/openssl.exe" || :; \ OPENSSL_DEBUG_MEMORY=on; \ export OPENSSL OPENSSL_DEBUG_MEMORY; \ - $(PERL) tools/c_rehash certs) && \ + $(PERL) tools/c_rehash certs/demo) && \ touch rehash.time; \ else :; fi diff --git a/NEWS b/NEWS index 4f069cbd14c..0269f2277fc 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,18 @@ This file gives a brief overview of the major changes between each OpenSSL release. For more details please read the CHANGES file. + Major changes between OpenSSL 1.0.1d and OpenSSL 1.0.1e: + + o Corrected fix for CVE-2013-0169 + + Major changes between OpenSSL 1.0.1c and OpenSSL 1.0.1d: + + o Fix renegotiation in TLS 1.1, 1.2 by using the correct TLS version. + o Include the fips configuration module. + o Fix OCSP bad key DoS attack CVE-2013-0166 + o Fix for SSL/TLS/DTLS CBC plaintext recovery attack CVE-2013-0169 + o Fix for TLS AESNI record handling flaw CVE-2012-2686 + Major changes between OpenSSL 1.0.1b and OpenSSL 1.0.1c: o Fix TLS/DTLS record length checking bug CVE-2012-2333 diff --git a/PROBLEMS b/PROBLEMS index d247470f061..3eaab01f2ce 100644 --- a/PROBLEMS +++ b/PROBLEMS @@ -197,3 +197,17 @@ reconfigure with additional no-sse2 [or 386] option passed to ./config. We don't have framework to associate -ldl with no-dso, therefore the only way is to edit Makefile right after ./config no-dso and remove -ldl from EX_LIBS line. + +* hpux-parisc2-cc no-asm build fails with SEGV in ECDSA/DH. + +Compiler bug, presumably at particular patch level. Remaining +hpux*-parisc*-cc configurations can be affected too. Drop optimization +level to +O2 when compiling bn_nist.o. + +* solaris64-sparcv9-cc link failure + +Solaris 8 ar can fail to maintain symbol table in .a, which results in +link failures. Apply 109147-09 or later or modify Makefile generated +by ./Configure solaris64-sparcv9-cc and replace RANLIB assignment with + + RANLIB= /usr/ccs/bin/ar rs diff --git a/README b/README index de51583a6ff..ad2d90f0d1d 100644 --- a/README +++ b/README @@ -1,5 +1,5 @@ - OpenSSL 1.0.1c 10 May 2012 + OpenSSL 1.0.1e 11 Feb 2013 Copyright (c) 1998-2011 The OpenSSL Project Copyright (c) 1995-1998 Eric A. Young, Tim J. Hudson @@ -190,7 +190,7 @@ reason as to why that feature isn't implemented. Patches should be as up to date as possible, preferably relative to the - current CVS or the last snapshot. They should follow the coding style of + current Git or the last snapshot. They should follow the coding style of OpenSSL and compile without warnings. Some of the core team developer targets can be used for testing purposes, (debug-steve64, debug-geoff etc). OpenSSL compiles on many varied platforms: try to ensure you only use portable diff --git a/apps/apps.c b/apps/apps.c index 4e11915b025..1096eee4cfa 100644 --- a/apps/apps.c +++ b/apps/apps.c @@ -2132,7 +2132,7 @@ X509_NAME *parse_name(char *subject, long chtype, int multirdn) X509_NAME *n = NULL; int nid; - if (!buf || !ne_types || !ne_values) + if (!buf || !ne_types || !ne_values || !mval) { BIO_printf(bio_err, "malloc error\n"); goto error; @@ -2236,6 +2236,7 @@ X509_NAME *parse_name(char *subject, long chtype, int multirdn) OPENSSL_free(ne_values); OPENSSL_free(ne_types); OPENSSL_free(buf); + OPENSSL_free(mval); return n; error: @@ -2244,6 +2245,8 @@ error: OPENSSL_free(ne_values); if (ne_types) OPENSSL_free(ne_types); + if (mval) + OPENSSL_free(mval); if (buf) OPENSSL_free(buf); return NULL; diff --git a/apps/ca.c b/apps/ca.c index 2a83d1936e4..1cf50e00294 100644 --- a/apps/ca.c +++ b/apps/ca.c @@ -1408,6 +1408,7 @@ bad: if (!NCONF_get_number(conf,section, ENV_DEFAULT_CRL_HOURS, &crlhours)) crlhours = 0; + ERR_clear_error(); } if ((crldays == 0) && (crlhours == 0) && (crlsec == 0)) { diff --git a/apps/cms.c b/apps/cms.c index d7541409873..5f77f8fbb03 100644 --- a/apps/cms.c +++ b/apps/cms.c @@ -233,6 +233,8 @@ int MAIN(int argc, char **argv) else if (!strcmp(*args,"-camellia256")) cipher = EVP_camellia_256_cbc(); #endif + else if (!strcmp (*args, "-debug_decrypt")) + flags |= CMS_DEBUG_DECRYPT; else if (!strcmp (*args, "-text")) flags |= CMS_TEXT; else if (!strcmp (*args, "-nointern")) @@ -1039,6 +1041,8 @@ int MAIN(int argc, char **argv) ret = 4; if (operation == SMIME_DECRYPT) { + if (flags & CMS_DEBUG_DECRYPT) + CMS_decrypt(cms, NULL, NULL, NULL, NULL, flags); if (secret_key) { diff --git a/apps/dgst.c b/apps/dgst.c index b08e9a7c786..81bd870f991 100644 --- a/apps/dgst.c +++ b/apps/dgst.c @@ -216,10 +216,10 @@ int MAIN(int argc, char **argv) out_bin = 1; else if (strcmp(*argv,"-d") == 0) debug=1; - else if (strcmp(*argv,"-non-fips-allow") == 0) - non_fips_allow=1; else if (!strcmp(*argv,"-fips-fingerprint")) hmac_key = "etaonrishdlcupfm"; + else if (strcmp(*argv,"-non-fips-allow") == 0) + non_fips_allow=1; else if (!strcmp(*argv,"-hmac")) { if (--argc < 1) diff --git a/apps/dhparam.c b/apps/dhparam.c index b47097cbb22..1297d6fb5ec 100644 --- a/apps/dhparam.c +++ b/apps/dhparam.c @@ -332,7 +332,6 @@ bad: BIO_printf(bio_err,"This is going to take a long time\n"); if(!dh || !DH_generate_parameters_ex(dh, num, g, &cb)) { - if(dh) DH_free(dh); ERR_print_errors(bio_err); goto end; } diff --git a/apps/dsaparam.c b/apps/dsaparam.c index fe72c1d3dfa..683d51391b0 100644 --- a/apps/dsaparam.c +++ b/apps/dsaparam.c @@ -326,6 +326,7 @@ bad: goto end; } #endif + ERR_print_errors(bio_err); BIO_printf(bio_err,"Error, DSA key generation failed\n"); goto end; } @@ -429,13 +430,19 @@ bad: assert(need_rand); if ((dsakey=DSAparams_dup(dsa)) == NULL) goto end; - if (!DSA_generate_key(dsakey)) goto end; + if (!DSA_generate_key(dsakey)) + { + ERR_print_errors(bio_err); + DSA_free(dsakey); + goto end; + } if (outformat == FORMAT_ASN1) i=i2d_DSAPrivateKey_bio(out,dsakey); else if (outformat == FORMAT_PEM) i=PEM_write_bio_DSAPrivateKey(out,dsakey,NULL,NULL,0,NULL,NULL); else { BIO_printf(bio_err,"bad output format specified for outfile\n"); + DSA_free(dsakey); goto end; } DSA_free(dsakey); diff --git a/apps/genrsa.c b/apps/genrsa.c index 37e9310910b..ece114c876a 100644 --- a/apps/genrsa.c +++ b/apps/genrsa.c @@ -78,7 +78,7 @@ #include #include -#define DEFBITS 512 +#define DEFBITS 1024 #undef PROG #define PROG genrsa_main diff --git a/apps/ocsp.c b/apps/ocsp.c index 01847dfad74..83c5a767005 100644 --- a/apps/ocsp.c +++ b/apps/ocsp.c @@ -617,7 +617,7 @@ int MAIN(int argc, char **argv) BIO_printf (bio_err, "-ndays n number of days before next update\n"); BIO_printf (bio_err, "-resp_key_id identify reponse by signing certificate key ID\n"); BIO_printf (bio_err, "-nrequest n number of requests to accept (default unlimited)\n"); - BIO_printf (bio_err, "- use specified digest in the request"); + BIO_printf (bio_err, "- use specified digest in the request\n"); goto end; } diff --git a/apps/s_cb.c b/apps/s_cb.c index 2cd73376dfa..84c3b447c29 100644 --- a/apps/s_cb.c +++ b/apps/s_cb.c @@ -237,8 +237,8 @@ int set_cert_stuff(SSL_CTX *ctx, char *cert_file, char *key_file) /* If we are using DSA, we can copy the parameters from * the private key */ - - + + /* Now we know that a key and cert have been set against * the SSL context */ if (!SSL_CTX_check_private_key(ctx)) @@ -436,6 +436,8 @@ void MS_CALLBACK msg_cb(int write_p, int version, int content_type, const void * if (version == SSL3_VERSION || version == TLS1_VERSION || + version == TLS1_1_VERSION || + version == TLS1_2_VERSION || version == DTLS1_VERSION || version == DTLS1_BAD_VER) { diff --git a/apps/s_client.c b/apps/s_client.c index fc806eb6726..3ba66056038 100644 --- a/apps/s_client.c +++ b/apps/s_client.c @@ -357,12 +357,14 @@ static void sc_usage(void) BIO_printf(bio_err," -tlsextdebug - hex dump of all TLS extensions received\n"); BIO_printf(bio_err," -status - request certificate status from server\n"); BIO_printf(bio_err," -no_ticket - disable use of RFC4507bis session tickets\n"); -# if !defined(OPENSSL_NO_NEXTPROTONEG) +# ifndef OPENSSL_NO_NEXTPROTONEG BIO_printf(bio_err," -nextprotoneg arg - enable NPN extension, considering named protocols supported (comma-separated list)\n"); # endif #endif BIO_printf(bio_err," -legacy_renegotiation - enable use of legacy renegotiation (dangerous)\n"); +#ifndef OPENSSL_NO_SRTP BIO_printf(bio_err," -use_srtp profiles - Offer SRTP key management with a colon-separated profile list\n"); +#endif BIO_printf(bio_err," -keymatexport label - Export keying material using label\n"); BIO_printf(bio_err," -keymatexportlen len - Export len bytes of keying material (default 20)\n"); } @@ -502,7 +504,9 @@ static char * MS_CALLBACK ssl_give_srp_client_pwd_cb(SSL *s, void *arg) } #endif +#ifndef OPENSSL_NO_SRTP char *srtp_profiles = NULL; +#endif # ifndef OPENSSL_NO_NEXTPROTONEG /* This the context that we pass to next_proto_cb */ @@ -536,7 +540,7 @@ static int next_proto_cb(SSL *s, unsigned char **out, unsigned char *outlen, con ctx->status = SSL_select_next_proto(out, outlen, in, inlen, ctx->data, ctx->len); return SSL_TLSEXT_ERR_OK; } -# endif +# endif /* ndef OPENSSL_NO_NEXTPROTONEG */ #endif enum @@ -945,11 +949,13 @@ int MAIN(int argc, char **argv) jpake_secret = *++argv; } #endif +#ifndef OPENSSL_NO_SRTP else if (strcmp(*argv,"-use_srtp") == 0) { if (--argc < 1) goto bad; srtp_profiles = *(++argv); } +#endif else if (strcmp(*argv,"-keymatexport") == 0) { if (--argc < 1) goto bad; @@ -1130,6 +1136,8 @@ bad: BIO_printf(bio_c_out, "PSK key given or JPAKE in use, setting client callback\n"); SSL_CTX_set_psk_client_callback(ctx, psk_client_cb); } +#endif +#ifndef OPENSSL_NO_SRTP if (srtp_profiles != NULL) SSL_CTX_set_tlsext_use_srtp(ctx, srtp_profiles); #endif @@ -1890,6 +1898,10 @@ end: print_stuff(bio_c_out,con,1); SSL_free(con); } +#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) + if (next_proto.data) + OPENSSL_free(next_proto.data); +#endif if (ctx != NULL) SSL_CTX_free(ctx); if (cert) X509_free(cert); @@ -1897,6 +1909,8 @@ end: EVP_PKEY_free(key); if (pass) OPENSSL_free(pass); + if (vpm) + X509_VERIFY_PARAM_free(vpm); if (cbuf != NULL) { OPENSSL_cleanse(cbuf,BUFSIZZ); OPENSSL_free(cbuf); } if (sbuf != NULL) { OPENSSL_cleanse(sbuf,BUFSIZZ); OPENSSL_free(sbuf); } if (mbuf != NULL) { OPENSSL_cleanse(mbuf,BUFSIZZ); OPENSSL_free(mbuf); } @@ -2061,6 +2075,7 @@ static void print_stuff(BIO *bio, SSL *s, int full) } #endif +#ifndef OPENSSL_NO_SRTP { SRTP_PROTECTION_PROFILE *srtp_profile=SSL_get_selected_srtp_profile(s); @@ -2068,6 +2083,7 @@ static void print_stuff(BIO *bio, SSL *s, int full) BIO_printf(bio,"SRTP Extension negotiated, profile=%s\n", srtp_profile->name); } +#endif SSL_SESSION_print(bio,SSL_get_session(s)); if (keymatexportlabel != NULL) diff --git a/apps/s_server.c b/apps/s_server.c index 3f9b3704c62..8198d7f0653 100644 --- a/apps/s_server.c +++ b/apps/s_server.c @@ -556,7 +556,9 @@ static void sv_usage(void) # ifndef OPENSSL_NO_NEXTPROTONEG BIO_printf(bio_err," -nextprotoneg arg - set the advertised protocols for the NPN extension (comma-separated list)\n"); # endif +# ifndef OPENSSL_NO_SRTP BIO_printf(bio_err," -use_srtp profiles - Offer SRTP key management with a colon-separated profile list\n"); +# endif #endif BIO_printf(bio_err," -keymatexport label - Export keying material using label\n"); BIO_printf(bio_err," -keymatexportlen len - Export len bytes of keying material (default 20)\n"); @@ -923,7 +925,9 @@ static char *jpake_secret = NULL; #ifndef OPENSSL_NO_SRP static srpsrvparm srp_callback_parm; #endif +#ifndef OPENSSL_NO_SRTP static char *srtp_profiles = NULL; +#endif int MAIN(int argc, char *argv[]) { @@ -1206,13 +1210,13 @@ int MAIN(int argc, char *argv[]) { if (--argc < 1) goto bad; srp_verifier_file = *(++argv); - meth=TLSv1_server_method(); + meth = TLSv1_server_method(); } else if (strcmp(*argv, "-srpuserseed") == 0) { if (--argc < 1) goto bad; srpuserseed = *(++argv); - meth=TLSv1_server_method(); + meth = TLSv1_server_method(); } #endif else if (strcmp(*argv,"-www") == 0) @@ -1319,11 +1323,13 @@ int MAIN(int argc, char *argv[]) jpake_secret = *(++argv); } #endif +#ifndef OPENSSL_NO_SRTP else if (strcmp(*argv,"-use_srtp") == 0) { if (--argc < 1) goto bad; srtp_profiles = *(++argv); } +#endif else if (strcmp(*argv,"-keymatexport") == 0) { if (--argc < 1) goto bad; @@ -1431,25 +1437,24 @@ bad: goto end; } } - -# ifndef OPENSSL_NO_NEXTPROTONEG - if (next_proto_neg_in) - { - unsigned short len; - next_proto.data = next_protos_parse(&len, - next_proto_neg_in); - if (next_proto.data == NULL) - goto end; - next_proto.len = len; - } - else - { - next_proto.data = NULL; - } -# endif #endif } +#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) + if (next_proto_neg_in) + { + unsigned short len; + next_proto.data = next_protos_parse(&len, next_proto_neg_in); + if (next_proto.data == NULL) + goto end; + next_proto.len = len; + } + else + { + next_proto.data = NULL; + } +#endif + if (s_dcert_file) { @@ -1550,8 +1555,10 @@ bad: else SSL_CTX_sess_set_cache_size(ctx,128); +#ifndef OPENSSL_NO_SRTP if (srtp_profiles != NULL) SSL_CTX_set_tlsext_use_srtp(ctx, srtp_profiles); +#endif #if 0 if (cipher == NULL) cipher=getenv("SSL_CIPHER"); @@ -1730,7 +1737,7 @@ bad: } #endif - if (!set_cert_key_stuff(ctx,s_cert,s_key)) + if (!set_cert_key_stuff(ctx, s_cert, s_key)) goto end; #ifndef OPENSSL_NO_TLSEXT if (ctx2 && !set_cert_key_stuff(ctx2,s_cert2,s_key2)) @@ -1738,7 +1745,7 @@ bad: #endif if (s_dcert != NULL) { - if (!set_cert_key_stuff(ctx,s_dcert,s_dkey)) + if (!set_cert_key_stuff(ctx, s_dcert, s_dkey)) goto end; } @@ -1893,7 +1900,15 @@ end: OPENSSL_free(pass); if (dpass) OPENSSL_free(dpass); + if (vpm) + X509_VERIFY_PARAM_free(vpm); #ifndef OPENSSL_NO_TLSEXT + if (tlscstatp.host) + OPENSSL_free(tlscstatp.host); + if (tlscstatp.port) + OPENSSL_free(tlscstatp.port); + if (tlscstatp.path) + OPENSSL_free(tlscstatp.path); if (ctx2 != NULL) SSL_CTX_free(ctx2); if (s_cert2) X509_free(s_cert2); @@ -2433,6 +2448,7 @@ static int init_ssl_connection(SSL *con) BIO_printf(bio_s_out,"Shared ciphers:%s\n",buf); str=SSL_CIPHER_get_name(SSL_get_current_cipher(con)); BIO_printf(bio_s_out,"CIPHER is %s\n",(str != NULL)?str:"(NONE)"); + #if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) SSL_get0_next_proto_negotiated(con, &next_proto_neg, &next_proto_neg_len); if (next_proto_neg) @@ -2442,6 +2458,7 @@ static int init_ssl_connection(SSL *con) BIO_printf(bio_s_out, "\n"); } #endif +#ifndef OPENSSL_NO_SRTP { SRTP_PROTECTION_PROFILE *srtp_profile = SSL_get_selected_srtp_profile(con); @@ -2450,6 +2467,7 @@ static int init_ssl_connection(SSL *con) BIO_printf(bio_s_out,"SRTP Extension negotiated, profile=%s\n", srtp_profile->name); } +#endif if (SSL_cache_hit(con)) BIO_printf(bio_s_out,"Reused session-id\n"); if (SSL_ctrl(con,SSL_CTRL_GET_FLAGS,0,NULL) & TLS1_FLAGS_TLS_PADDING_BUG) @@ -2701,6 +2719,11 @@ static int www_body(char *hostname, int s, unsigned char *context) } BIO_puts(io,"\n"); + BIO_printf(io, + "Secure Renegotiation IS%s supported\n", + SSL_get_secure_renegotiation_support(con) ? + "" : " NOT"); + /* The following is evil and should not really * be done */ BIO_printf(io,"Ciphers supported in s_server binary\n"); diff --git a/apps/speed.c b/apps/speed.c index 8358b12fddb..9886ca37669 100644 --- a/apps/speed.c +++ b/apps/speed.c @@ -254,7 +254,7 @@ static const char *names[ALGOR_NUM]={ "aes-128 cbc","aes-192 cbc","aes-256 cbc", "camellia-128 cbc","camellia-192 cbc","camellia-256 cbc", "evp","sha256","sha512","whirlpool", - "aes-128 ige","aes-192 ige","aes-256 ige","ghash"}; + "aes-128 ige","aes-192 ige","aes-256 ige","ghash" }; static double results[ALGOR_NUM][SIZE_NUM]; static int lengths[SIZE_NUM]={16,64,256,1024,8*1024}; #ifndef OPENSSL_NO_RSA @@ -299,7 +299,7 @@ static SIGRETTYPE sig_done(int sig) #if defined(_WIN32) #if !defined(SIGALRM) -#define SIGALRM +# define SIGALRM #endif static unsigned int lapse,schlock; static void alarm_win32(unsigned int secs) { lapse = secs*1000; } diff --git a/apps/srp.c b/apps/srp.c index 80e1b8a6607..9c7ae184db1 100644 --- a/apps/srp.c +++ b/apps/srp.c @@ -125,13 +125,13 @@ static int get_index(CA_DB *db, char* id, char type) if (type == DB_SRP_INDEX) for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) { - pp = (char **)sk_OPENSSL_PSTRING_value(db->db->data, i); - if (pp[DB_srptype][0] == DB_SRP_INDEX && !strcmp(id, pp[DB_srpid])) + pp = sk_OPENSSL_PSTRING_value(db->db->data,i); + if (pp[DB_srptype][0] == DB_SRP_INDEX && !strcmp(id,pp[DB_srpid])) return i; } else for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) { - pp = (char **)sk_OPENSSL_PSTRING_value(db->db->data, i); + pp = sk_OPENSSL_PSTRING_value(db->db->data,i); if (pp[DB_srptype][0] != DB_SRP_INDEX && !strcmp(id,pp[DB_srpid])) return i; @@ -145,7 +145,7 @@ static void print_entry(CA_DB *db, BIO *bio, int indx, int verbose, char *s) if (indx >= 0 && verbose) { int j; - char **pp = (char **)sk_OPENSSL_PSTRING_value(db->db->data, indx); + char **pp = sk_OPENSSL_PSTRING_value(db->db->data, indx); BIO_printf(bio, "%s \"%s\"\n", s, pp[DB_srpid]); for (j = 0; j < DB_NUMBER; j++) { @@ -163,7 +163,7 @@ static void print_user(CA_DB *db, BIO *bio, int userindex, int verbose) { if (verbose > 0) { - char **pp = (char **)sk_OPENSSL_PSTRING_value(db->db->data, userindex); + char **pp = sk_OPENSSL_PSTRING_value(db->db->data,userindex); if (pp[DB_srptype][0] != 'I') { @@ -517,7 +517,7 @@ bad: /* Lets check some fields */ for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) { - pp = (char **)sk_OPENSSL_PSTRING_value(db->db->data, i); + pp = sk_OPENSSL_PSTRING_value(db->db->data, i); if (pp[DB_srptype][0] == DB_SRP_INDEX) { @@ -533,8 +533,8 @@ bad: if (gNindex >= 0) { - gNrow = (char **)sk_OPENSSL_PSTRING_value(db->db->data, gNindex); - print_entry(db, bio_err, gNindex, verbose > 1, "Default g and N") ; + gNrow = sk_OPENSSL_PSTRING_value(db->db->data,gNindex); + print_entry(db, bio_err, gNindex, verbose > 1, "Default g and N"); } else if (maxgN > 0 && !SRP_get_default_gN(gN)) { @@ -587,7 +587,7 @@ bad: if (userindex >= 0) { /* reactivation of a new user */ - char **row = (char **)sk_OPENSSL_PSTRING_value(db->db->data, userindex); + char **row = sk_OPENSSL_PSTRING_value(db->db->data, userindex); BIO_printf(bio_err, "user \"%s\" reactivated.\n", user); row[DB_srptype][0] = 'V'; @@ -634,7 +634,7 @@ bad: else { - char **row = (char **)sk_OPENSSL_PSTRING_value(db->db->data, userindex); + char **row = sk_OPENSSL_PSTRING_value(db->db->data, userindex); char type = row[DB_srptype][0]; if (type == 'v') { @@ -664,9 +664,9 @@ bad: if (!(gNid=srp_create_user(user,&(row[DB_srpverifier]), &(row[DB_srpsalt]),gNrow?gNrow[DB_srpsalt]:NULL, gNrow?gNrow[DB_srpverifier]:NULL, passout, bio_err,verbose))) { - BIO_printf(bio_err, "Cannot create srp verifier for user \"%s\", operation abandoned.\n", user); - errors++; - goto err; + BIO_printf(bio_err, "Cannot create srp verifier for user \"%s\", operation abandoned.\n", user); + errors++; + goto err; } row[DB_srptype][0] = 'v'; @@ -689,7 +689,7 @@ bad: } else { - char **xpp = (char **)sk_OPENSSL_PSTRING_value(db->db->data, userindex); + char **xpp = sk_OPENSSL_PSTRING_value(db->db->data,userindex); BIO_printf(bio_err, "user \"%s\" revoked. t\n", user); xpp[DB_srptype][0] = 'R'; @@ -714,7 +714,7 @@ bad: /* Lets check some fields */ for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) { - pp = (char **)sk_OPENSSL_PSTRING_value(db->db->data, i); + pp = sk_OPENSSL_PSTRING_value(db->db->data,i); if (pp[DB_srptype][0] == 'v') { diff --git a/apps/verify.c b/apps/verify.c index b9749dcd363..893670ff413 100644 --- a/apps/verify.c +++ b/apps/verify.c @@ -222,11 +222,19 @@ int MAIN(int argc, char **argv) goto end; } - if (argc < 1) check(cert_ctx, NULL, untrusted, trusted, crls, e); + ret = 0; + if (argc < 1) + { + if (1 != check(cert_ctx, NULL, untrusted, trusted, crls, e)) + ret = -1; + } else + { for (i=0; i&1` =~ /Version ([0-9]+)\./ && $1>=10); -open STDOUT,"| $^X $xlate $flavour $output"; +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; # void aesni_cbc_sha1_enc(const void *inp, # void *out, diff --git a/crypto/aes/asm/aesni-x86_64.pl b/crypto/aes/asm/aesni-x86_64.pl index 499f3b3f42f..0dbb194b8d7 100755 --- a/crypto/aes/asm/aesni-x86_64.pl +++ b/crypto/aes/asm/aesni-x86_64.pl @@ -172,7 +172,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or die "can't locate x86_64-xlate.pl"; -open STDOUT,"| $^X $xlate $flavour $output"; +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; $movkey = $PREFIX eq "aesni" ? "movups" : "movups"; @_4args=$win64? ("%rcx","%rdx","%r8", "%r9") : # Win64 order diff --git a/crypto/aes/asm/bsaes-x86_64.pl b/crypto/aes/asm/bsaes-x86_64.pl index c9c6312fa74..ceb02b50ddb 100755 --- a/crypto/aes/asm/bsaes-x86_64.pl +++ b/crypto/aes/asm/bsaes-x86_64.pl @@ -105,7 +105,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or die "can't locate x86_64-xlate.pl"; -open STDOUT,"| $^X $xlate $flavour $output"; +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; my ($inp,$out,$len,$key,$ivp)=("%rdi","%rsi","%rdx","%rcx"); my @XMM=map("%xmm$_",(15,0..14)); # best on Atom, +10% over (0..15) diff --git a/crypto/aes/asm/vpaes-x86_64.pl b/crypto/aes/asm/vpaes-x86_64.pl index 37998db5e13..41f2e46f60c 100755 --- a/crypto/aes/asm/vpaes-x86_64.pl +++ b/crypto/aes/asm/vpaes-x86_64.pl @@ -56,7 +56,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or die "can't locate x86_64-xlate.pl"; -open STDOUT,"| $^X $xlate $flavour $output"; +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; $PREFIX="vpaes"; diff --git a/crypto/asn1/a_strex.c b/crypto/asn1/a_strex.c index 264ebf2393a..ead37ac3258 100644 --- a/crypto/asn1/a_strex.c +++ b/crypto/asn1/a_strex.c @@ -567,6 +567,7 @@ int ASN1_STRING_to_UTF8(unsigned char **out, ASN1_STRING *in) if(mbflag == -1) return -1; mbflag |= MBSTRING_FLAG; stmp.data = NULL; + stmp.length = 0; ret = ASN1_mbstring_copy(&str, in->data, in->length, mbflag, B_ASN1_UTF8STRING); if(ret < 0) return ret; *out = stmp.data; diff --git a/crypto/asn1/a_verify.c b/crypto/asn1/a_verify.c index 432722e4099..fc84cd3d191 100644 --- a/crypto/asn1/a_verify.c +++ b/crypto/asn1/a_verify.c @@ -140,6 +140,12 @@ int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a, int mdnid, pknid; + if (!pkey) + { + ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_PASSED_NULL_PARAMETER); + return -1; + } + EVP_MD_CTX_init(&ctx); /* Convert signature OID into digest and public key OIDs */ diff --git a/crypto/asn1/x_pubkey.c b/crypto/asn1/x_pubkey.c index 627ec87f9f8..b649e1fcf96 100644 --- a/crypto/asn1/x_pubkey.c +++ b/crypto/asn1/x_pubkey.c @@ -175,12 +175,15 @@ EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key) CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY); if (key->pkey) { + CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY); EVP_PKEY_free(ret); ret = key->pkey; } else + { key->pkey = ret; - CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY); + CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY); + } CRYPTO_add(&ret->references, 1, CRYPTO_LOCK_EVP_PKEY); return ret; diff --git a/crypto/bio/bss_dgram.c b/crypto/bio/bss_dgram.c index 1b1e4bec812..8990909971c 100644 --- a/crypto/bio/bss_dgram.c +++ b/crypto/bio/bss_dgram.c @@ -77,10 +77,20 @@ #define OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE 0xc0 #endif -#ifdef OPENSSL_SYS_LINUX +#if defined(OPENSSL_SYS_LINUX) && !defined(IP_MTU) #define IP_MTU 14 /* linux is lame */ #endif +#if defined(__FreeBSD__) && defined(IN6_IS_ADDR_V4MAPPED) +/* Standard definition causes type-punning problems. */ +#undef IN6_IS_ADDR_V4MAPPED +#define s6_addr32 __u6_addr.__u6_addr32 +#define IN6_IS_ADDR_V4MAPPED(a) \ + (((a)->s6_addr32[0] == 0) && \ + ((a)->s6_addr32[1] == 0) && \ + ((a)->s6_addr32[2] == htonl(0x0000ffff))) +#endif + #ifdef WATT32 #define sock_write SockWrite /* Watt-32 uses same names */ #define sock_read SockRead @@ -255,7 +265,7 @@ static void dgram_adjust_rcv_timeout(BIO *b) { #if defined(SO_RCVTIMEO) bio_dgram_data *data = (bio_dgram_data *)b->ptr; - int sz = sizeof(int); + union { size_t s; int i; } sz = {0}; /* Is a timer active? */ if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0) @@ -265,8 +275,10 @@ static void dgram_adjust_rcv_timeout(BIO *b) /* Read current socket timeout */ #ifdef OPENSSL_SYS_WINDOWS int timeout; + + sz.i = sizeof(timeout); if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, - (void*)&timeout, &sz) < 0) + (void*)&timeout, &sz.i) < 0) { perror("getsockopt"); } else { @@ -274,9 +286,12 @@ static void dgram_adjust_rcv_timeout(BIO *b) data->socket_timeout.tv_usec = (timeout % 1000) * 1000; } #else + sz.i = sizeof(data->socket_timeout); if ( getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, &(data->socket_timeout), (void *)&sz) < 0) { perror("getsockopt"); } + else if (sizeof(sz.s)!=sizeof(sz.i) && sz.i==0) + OPENSSL_assert(sz.s<=sizeof(data->socket_timeout)); #endif /* Get current time */ @@ -445,11 +460,10 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) int *ip; struct sockaddr *to = NULL; bio_dgram_data *data = NULL; -#if defined(IP_MTU_DISCOVER) || defined(IP_MTU) - long sockopt_val = 0; - unsigned int sockopt_len = 0; -#endif -#ifdef OPENSSL_SYS_LINUX +#if defined(OPENSSL_SYS_LINUX) && (defined(IP_MTU_DISCOVER) || defined(IP_MTU)) + int sockopt_val = 0; + socklen_t sockopt_len; /* assume that system supporting IP_MTU is + * modern enough to define socklen_t */ socklen_t addr_len; union { struct sockaddr sa; @@ -531,7 +545,7 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) break; /* (Linux)kernel sets DF bit on outgoing IP packets */ case BIO_CTRL_DGRAM_MTU_DISCOVER: -#ifdef OPENSSL_SYS_LINUX +#if defined(OPENSSL_SYS_LINUX) && defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO) addr_len = (socklen_t)sizeof(addr); memset((void *)&addr, 0, sizeof(addr)); if (getsockname(b->num, &addr.sa, &addr_len) < 0) @@ -539,7 +553,6 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) ret = 0; break; } - sockopt_len = sizeof(sockopt_val); switch (addr.sa.sa_family) { case AF_INET: @@ -548,7 +561,7 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) &sockopt_val, sizeof(sockopt_val))) < 0) perror("setsockopt"); break; -#if OPENSSL_USE_IPV6 && defined(IPV6_MTU_DISCOVER) +#if OPENSSL_USE_IPV6 && defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO) case AF_INET6: sockopt_val = IPV6_PMTUDISC_DO; if ((ret = setsockopt(b->num, IPPROTO_IPV6, IPV6_MTU_DISCOVER, @@ -565,7 +578,7 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) break; #endif case BIO_CTRL_DGRAM_QUERY_MTU: -#ifdef OPENSSL_SYS_LINUX +#if defined(OPENSSL_SYS_LINUX) && defined(IP_MTU) addr_len = (socklen_t)sizeof(addr); memset((void *)&addr, 0, sizeof(addr)); if (getsockname(b->num, &addr.sa, &addr_len) < 0) @@ -727,12 +740,15 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) #endif break; case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT: -#ifdef OPENSSL_SYS_WINDOWS { - int timeout, sz = sizeof(timeout); + union { size_t s; int i; } sz = {0}; +#ifdef OPENSSL_SYS_WINDOWS + int timeout; struct timeval *tv = (struct timeval *)ptr; + + sz.i = sizeof(timeout); if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, - (void*)&timeout, &sz) < 0) + (void*)&timeout, &sz.i) < 0) { perror("getsockopt"); ret = -1; } else { @@ -740,12 +756,20 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) tv->tv_usec = (timeout % 1000) * 1000; ret = sizeof(*tv); } - } #else + sz.i = sizeof(struct timeval); if ( getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, - ptr, (void *)&ret) < 0) + ptr, (void *)&sz) < 0) { perror("getsockopt"); ret = -1; } + else if (sizeof(sz.s)!=sizeof(sz.i) && sz.i==0) + { + OPENSSL_assert(sz.s<=sizeof(struct timeval)); + ret = (int)sz.s; + } + else + ret = sz.i; #endif + } break; #endif #if defined(SO_SNDTIMEO) @@ -765,12 +789,15 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) #endif break; case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT: -#ifdef OPENSSL_SYS_WINDOWS { - int timeout, sz = sizeof(timeout); + union { size_t s; int i; } sz = {0}; +#ifdef OPENSSL_SYS_WINDOWS + int timeout; struct timeval *tv = (struct timeval *)ptr; + + sz.i = sizeof(timeout); if (getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, - (void*)&timeout, &sz) < 0) + (void*)&timeout, &sz.i) < 0) { perror("getsockopt"); ret = -1; } else { @@ -778,12 +805,20 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) tv->tv_usec = (timeout % 1000) * 1000; ret = sizeof(*tv); } - } #else + sz.i = sizeof(struct timeval); if ( getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, - ptr, (void *)&ret) < 0) + ptr, (void *)&sz) < 0) { perror("getsockopt"); ret = -1; } + else if (sizeof(sz.s)!=sizeof(sz.i) && sz.i==0) + { + OPENSSL_assert(sz.s<=sizeof(struct timeval)); + ret = (int)sz.s; + } + else + ret = sz.i; #endif + } break; #endif case BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP: @@ -955,7 +990,6 @@ static int dgram_sctp_free(BIO *a) #ifdef SCTP_AUTHENTICATION_EVENT void dgram_sctp_handle_auth_free_key_event(BIO *b, union sctp_notification *snp) { - unsigned int sockopt_len = 0; int ret; struct sctp_authkey_event* authkeyevent = &snp->sn_auth_event; @@ -965,9 +999,8 @@ void dgram_sctp_handle_auth_free_key_event(BIO *b, union sctp_notification *snp) /* delete key */ authkeyid.scact_keynumber = authkeyevent->auth_keynumber; - sockopt_len = sizeof(struct sctp_authkeyid); ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_DELETE_KEY, - &authkeyid, sockopt_len); + &authkeyid, sizeof(struct sctp_authkeyid)); } } #endif @@ -1298,7 +1331,7 @@ static long dgram_sctp_ctrl(BIO *b, int cmd, long num, void *ptr) { long ret=1; bio_dgram_sctp_data *data = NULL; - unsigned int sockopt_len = 0; + socklen_t sockopt_len = 0; struct sctp_authkeyid authkeyid; struct sctp_authkey *authkey; diff --git a/crypto/bn/asm/mips.pl b/crypto/bn/asm/mips.pl index c162a3ec230..38b51645f06 100755 --- a/crypto/bn/asm/mips.pl +++ b/crypto/bn/asm/mips.pl @@ -819,7 +819,7 @@ ___ $code.=<<___; .set reorder move $ta3,$ra - bal bn_div_words + bal bn_div_words_internal move $ra,$ta3 $MULTU $ta2,$v0 $LD $t2,-2*$BNSZ($a3) diff --git a/crypto/bn/asm/modexp512-x86_64.pl b/crypto/bn/asm/modexp512-x86_64.pl index 54aeb01921e..bfd6e975416 100755 --- a/crypto/bn/asm/modexp512-x86_64.pl +++ b/crypto/bn/asm/modexp512-x86_64.pl @@ -68,7 +68,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or die "can't locate x86_64-xlate.pl"; -open STDOUT,"| $^X $xlate $flavour $output"; +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; use strict; my $code=".text\n\n"; diff --git a/crypto/bn/asm/x86_64-gf2m.pl b/crypto/bn/asm/x86_64-gf2m.pl index 1658acbbddd..a30d4ef0295 100755 --- a/crypto/bn/asm/x86_64-gf2m.pl +++ b/crypto/bn/asm/x86_64-gf2m.pl @@ -31,7 +31,7 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or die "can't locate x86_64-xlate.pl"; -open STDOUT,"| $^X $xlate $flavour $output"; +open STDOUT,"| \"$^X\" $xlate $flavour $output"; ($lo,$hi)=("%rax","%rdx"); $a=$lo; ($i0,$i1)=("%rsi","%rdi"); diff --git a/crypto/bn/asm/x86_64-mont.pl b/crypto/bn/asm/x86_64-mont.pl index 5d79b35e1cf..17fb94c84c9 100755 --- a/crypto/bn/asm/x86_64-mont.pl +++ b/crypto/bn/asm/x86_64-mont.pl @@ -40,7 +40,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or die "can't locate x86_64-xlate.pl"; -open STDOUT,"| $^X $xlate $flavour $output"; +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; # int bn_mul_mont( $rp="%rdi"; # BN_ULONG *rp, diff --git a/crypto/bn/asm/x86_64-mont5.pl b/crypto/bn/asm/x86_64-mont5.pl index 057cda28aae..8f8dc5a5979 100755 --- a/crypto/bn/asm/x86_64-mont5.pl +++ b/crypto/bn/asm/x86_64-mont5.pl @@ -28,7 +28,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or die "can't locate x86_64-xlate.pl"; -open STDOUT,"| $^X $xlate $flavour $output"; +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; # int bn_mul_mont_gather5( $rp="%rdi"; # BN_ULONG *rp, diff --git a/crypto/bn/bn_div.c b/crypto/bn/bn_div.c index 52b3304293a..7b2403185e6 100644 --- a/crypto/bn/bn_div.c +++ b/crypto/bn/bn_div.c @@ -141,6 +141,7 @@ int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d, * * */ +#undef bn_div_words # define bn_div_words(n0,n1,d0) \ ({ asm volatile ( \ "divl %4" \ @@ -155,6 +156,7 @@ int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d, * Same story here, but it's 128-bit by 64-bit division. Wow! * */ +# undef bn_div_words # define bn_div_words(n0,n1,d0) \ ({ asm volatile ( \ "divq %4" \ diff --git a/crypto/bn/bn_gcd.c b/crypto/bn/bn_gcd.c index 4a352119ba8..a808f53178f 100644 --- a/crypto/bn/bn_gcd.c +++ b/crypto/bn/bn_gcd.c @@ -205,6 +205,7 @@ err: /* solves ax == 1 (mod n) */ static BIGNUM *BN_mod_inverse_no_branch(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx); + BIGNUM *BN_mod_inverse(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx) { diff --git a/crypto/bn/bn_lcl.h b/crypto/bn/bn_lcl.h index eecfd8cc99e..817c773b659 100644 --- a/crypto/bn/bn_lcl.h +++ b/crypto/bn/bn_lcl.h @@ -282,16 +282,23 @@ extern "C" { # endif # elif defined(__mips) && (defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG)) # if defined(__GNUC__) && __GNUC__>=2 -# define BN_UMULT_HIGH(a,b) ({ \ +# if __GNUC__>=4 && __GNUC_MINOR__>=4 /* "h" constraint is no more since 4.4 */ +# define BN_UMULT_HIGH(a,b) (((__uint128_t)(a)*(b))>>64) +# define BN_UMULT_LOHI(low,high,a,b) ({ \ + __uint128_t ret=(__uint128_t)(a)*(b); \ + (high)=ret>>64; (low)=ret; }) +# else +# define BN_UMULT_HIGH(a,b) ({ \ register BN_ULONG ret; \ asm ("dmultu %1,%2" \ : "=h"(ret) \ : "r"(a), "r"(b) : "l"); \ ret; }) -# define BN_UMULT_LOHI(low,high,a,b) \ +# define BN_UMULT_LOHI(low,high,a,b)\ asm ("dmultu %2,%3" \ : "=l"(low),"=h"(high) \ : "r"(a), "r"(b)); +# endif # endif # endif /* cpu */ #endif /* OPENSSL_NO_ASM */ diff --git a/crypto/camellia/asm/cmll-x86_64.pl b/crypto/camellia/asm/cmll-x86_64.pl index 76955e47265..9f4b82fa482 100755 --- a/crypto/camellia/asm/cmll-x86_64.pl +++ b/crypto/camellia/asm/cmll-x86_64.pl @@ -40,7 +40,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or die "can't locate x86_64-xlate.pl"; -open STDOUT,"| $^X $xlate $flavour $output"; +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; sub hi() { my $r=shift; $r =~ s/%[er]([a-d])x/%\1h/; $r; } sub lo() { my $r=shift; $r =~ s/%[er]([a-d])x/%\1l/; diff --git a/crypto/cms/cms_cd.c b/crypto/cms/cms_cd.c index a5fc2c4e2b4..20216881012 100644 --- a/crypto/cms/cms_cd.c +++ b/crypto/cms/cms_cd.c @@ -58,7 +58,9 @@ #include #include #include +#ifndef OPENSSL_NO_COMP #include +#endif #include "cms_lcl.h" DECLARE_ASN1_ITEM(CMS_CompressedData) diff --git a/crypto/cms/cms_enc.c b/crypto/cms/cms_enc.c index f873ce37944..bebeaf29c7b 100644 --- a/crypto/cms/cms_enc.c +++ b/crypto/cms/cms_enc.c @@ -74,7 +74,7 @@ BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec) X509_ALGOR *calg = ec->contentEncryptionAlgorithm; unsigned char iv[EVP_MAX_IV_LENGTH], *piv = NULL; unsigned char *tkey = NULL; - size_t tkeylen; + size_t tkeylen = 0; int ok = 0; diff --git a/crypto/cms/cms_lib.c b/crypto/cms/cms_lib.c index f88e8f3b525..b62d1bfac02 100644 --- a/crypto/cms/cms_lib.c +++ b/crypto/cms/cms_lib.c @@ -411,9 +411,7 @@ int cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain, * algorithm OID instead of digest. */ || EVP_MD_pkey_type(EVP_MD_CTX_md(mtmp)) == nid) - { return EVP_MD_CTX_copy_ex(mctx, mtmp); - } chain = BIO_next(chain); } } diff --git a/crypto/conf/conf_mall.c b/crypto/conf/conf_mall.c index c6f4cb2d55b..213890e0c28 100644 --- a/crypto/conf/conf_mall.c +++ b/crypto/conf/conf_mall.c @@ -76,5 +76,6 @@ void OPENSSL_load_builtin_modules(void) #ifndef OPENSSL_NO_ENGINE ENGINE_add_conf_module(); #endif + EVP_add_alg_module(); } diff --git a/crypto/cryptlib.c b/crypto/cryptlib.c index 766ea8cac73..304c6b70627 100644 --- a/crypto/cryptlib.c +++ b/crypto/cryptlib.c @@ -504,7 +504,7 @@ void CRYPTO_THREADID_current(CRYPTO_THREADID *id) CRYPTO_THREADID_set_numeric(id, (unsigned long)find_thread(NULL)); #else /* For everything else, default to using the address of 'errno' */ - CRYPTO_THREADID_set_pointer(id, &errno); + CRYPTO_THREADID_set_pointer(id, (void*)&errno); #endif } @@ -704,6 +704,7 @@ void OPENSSL_cpuid_setup(void) } else vec = OPENSSL_ia32_cpuid(); + /* * |(1<<10) sets a reserved bit to signal that variable * was initialized already... This is to avoid interference @@ -924,3 +925,16 @@ void OpenSSLDie(const char *file,int line,const char *assertion) } void *OPENSSL_stderr(void) { return stderr; } + +int CRYPTO_memcmp(const void *in_a, const void *in_b, size_t len) + { + size_t i; + const unsigned char *a = in_a; + const unsigned char *b = in_b; + unsigned char x = 0; + + for (i = 0; i < len; i++) + x |= a[i] ^ b[i]; + + return x; + } diff --git a/crypto/cryptlib.h b/crypto/cryptlib.h index 1761f6b6687..d26f9630ead 100644 --- a/crypto/cryptlib.h +++ b/crypto/cryptlib.h @@ -100,7 +100,7 @@ extern "C" { void OPENSSL_cpuid_setup(void); extern unsigned int OPENSSL_ia32cap_P[]; -void OPENSSL_showfatal(const char *,...); +void OPENSSL_showfatal(const char *fmta,...); void *OPENSSL_stderr(void); extern int OPENSSL_NONPIC_relocated; diff --git a/crypto/crypto.h b/crypto/crypto.h index 6aeda0a9ace..f92fc5182d9 100644 --- a/crypto/crypto.h +++ b/crypto/crypto.h @@ -488,10 +488,10 @@ void CRYPTO_get_mem_debug_functions(void (**m)(void *,int,const char *,int,int), long (**go)(void)); void *CRYPTO_malloc_locked(int num, const char *file, int line); -void CRYPTO_free_locked(void *); +void CRYPTO_free_locked(void *ptr); void *CRYPTO_malloc(int num, const char *file, int line); char *CRYPTO_strdup(const char *str, const char *file, int line); -void CRYPTO_free(void *); +void CRYPTO_free(void *ptr); void *CRYPTO_realloc(void *addr,int num, const char *file, int line); void *CRYPTO_realloc_clean(void *addr,int old_num,int num,const char *file, int line); @@ -574,6 +574,13 @@ void OPENSSL_init(void); #define fips_cipher_abort(alg) while(0) #endif +/* CRYPTO_memcmp returns zero iff the |len| bytes at |a| and |b| are equal. It + * takes an amount of time dependent on |len|, but independent of the contents + * of |a| and |b|. Unlike memcmp, it cannot be used to put elements into a + * defined order as the return value when a != b is undefined, other than to be + * non-zero. */ +int CRYPTO_memcmp(const void *a, const void *b, size_t len); + /* BEGIN ERROR CODES */ /* The following lines are auto generated by the script mkerr.pl. Any changes * made after this point may be overwritten when the script is next run. diff --git a/crypto/des/set_key.c b/crypto/des/set_key.c index d3e69ca8b58..da4d62e1128 100644 --- a/crypto/des/set_key.c +++ b/crypto/des/set_key.c @@ -63,9 +63,8 @@ * 1.1 added norm_expand_bits * 1.0 First working version */ -#include "des_locl.h" - #include +#include "des_locl.h" OPENSSL_IMPLEMENT_GLOBAL(int,DES_check_key,0) /* defaults to false */ diff --git a/crypto/des/str2key.c b/crypto/des/str2key.c index 9c2054bda6b..1077f99d1b2 100644 --- a/crypto/des/str2key.c +++ b/crypto/des/str2key.c @@ -56,8 +56,8 @@ * [including the GNU Public Licence.] */ -#include "des_locl.h" #include +#include "des_locl.h" void DES_string_to_key(const char *str, DES_cblock *key) { diff --git a/crypto/ec/ec.h b/crypto/ec/ec.h index 9d01325af33..dfe8710d330 100644 --- a/crypto/ec/ec.h +++ b/crypto/ec/ec.h @@ -274,10 +274,10 @@ int EC_GROUP_get_curve_name(const EC_GROUP *group); void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag); int EC_GROUP_get_asn1_flag(const EC_GROUP *group); -void EC_GROUP_set_point_conversion_form(EC_GROUP *, point_conversion_form_t); +void EC_GROUP_set_point_conversion_form(EC_GROUP *group, point_conversion_form_t form); point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP *); -unsigned char *EC_GROUP_get0_seed(const EC_GROUP *); +unsigned char *EC_GROUP_get0_seed(const EC_GROUP *x); size_t EC_GROUP_get_seed_len(const EC_GROUP *); size_t EC_GROUP_set_seed(EC_GROUP *, const unsigned char *, size_t len); @@ -626,8 +626,8 @@ int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *c */ int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx); -int EC_POINT_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *); -int EC_POINTs_make_affine(const EC_GROUP *, size_t num, EC_POINT *[], BN_CTX *); +int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx); +int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx); /** Computes r = generator * n sum_{i=0}^num p[i] * m[i] * \param group underlying EC_GROUP object @@ -800,16 +800,24 @@ const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key); int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub); unsigned EC_KEY_get_enc_flags(const EC_KEY *key); -void EC_KEY_set_enc_flags(EC_KEY *, unsigned int); -point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *); -void EC_KEY_set_conv_form(EC_KEY *, point_conversion_form_t); +void EC_KEY_set_enc_flags(EC_KEY *eckey, unsigned int flags); +point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key); +void EC_KEY_set_conv_form(EC_KEY *eckey, point_conversion_form_t cform); /* functions to set/get method specific data */ -void *EC_KEY_get_key_method_data(EC_KEY *, +void *EC_KEY_get_key_method_data(EC_KEY *key, void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *)); -void EC_KEY_insert_key_method_data(EC_KEY *, void *data, +/** Sets the key method data of an EC_KEY object, if none has yet been set. + * \param key EC_KEY object + * \param data opaque data to install. + * \param dup_func a function that duplicates |data|. + * \param free_func a function that frees |data|. + * \param clear_free_func a function that wipes and frees |data|. + * \return the previously set data pointer, or NULL if |data| was inserted. + */ +void *EC_KEY_insert_key_method_data(EC_KEY *key, void *data, void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *)); /* wrapper functions for the underlying EC_GROUP object */ -void EC_KEY_set_asn1_flag(EC_KEY *, int); +void EC_KEY_set_asn1_flag(EC_KEY *eckey, int asn1_flag); /** Creates a table of pre-computed multiples of the generator to * accelerate further EC_KEY operations. diff --git a/crypto/ec/ec_key.c b/crypto/ec/ec_key.c index bf9fd2dc2c4..7fa247593d9 100644 --- a/crypto/ec/ec_key.c +++ b/crypto/ec/ec_key.c @@ -520,18 +520,27 @@ void EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform) void *EC_KEY_get_key_method_data(EC_KEY *key, void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *)) { - return EC_EX_DATA_get_data(key->method_data, dup_func, free_func, clear_free_func); + void *ret; + + CRYPTO_r_lock(CRYPTO_LOCK_EC); + ret = EC_EX_DATA_get_data(key->method_data, dup_func, free_func, clear_free_func); + CRYPTO_r_unlock(CRYPTO_LOCK_EC); + + return ret; } -void EC_KEY_insert_key_method_data(EC_KEY *key, void *data, +void *EC_KEY_insert_key_method_data(EC_KEY *key, void *data, void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *)) { EC_EXTRA_DATA *ex_data; + CRYPTO_w_lock(CRYPTO_LOCK_EC); ex_data = EC_EX_DATA_get_data(key->method_data, dup_func, free_func, clear_free_func); if (ex_data == NULL) EC_EX_DATA_set_data(&key->method_data, data, dup_func, free_func, clear_free_func); CRYPTO_w_unlock(CRYPTO_LOCK_EC); + + return ex_data; } void EC_KEY_set_asn1_flag(EC_KEY *key, int flag) diff --git a/crypto/ec/ec_pmeth.c b/crypto/ec/ec_pmeth.c index d1ed66c37e7..66ee397d86c 100644 --- a/crypto/ec/ec_pmeth.c +++ b/crypto/ec/ec_pmeth.c @@ -188,7 +188,7 @@ static int pkey_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen) pubkey = EC_KEY_get0_public_key(ctx->peerkey->pkey.ec); - /* NB: unlike PKS#3 DH, if *outlen is less than maximum size this is + /* NB: unlike PKCS#3 DH, if *outlen is less than maximum size this is * not an error, the result is truncated. */ diff --git a/crypto/ec/ecp_mont.c b/crypto/ec/ecp_mont.c index 079e47431b4..f04f132c7ad 100644 --- a/crypto/ec/ecp_mont.c +++ b/crypto/ec/ecp_mont.c @@ -114,7 +114,6 @@ const EC_METHOD *EC_GFp_mont_method(void) ec_GFp_mont_field_decode, ec_GFp_mont_field_set_to_one }; - return &ret; #endif } diff --git a/crypto/ec/ectest.c b/crypto/ec/ectest.c index f107782de00..102eaa9b232 100644 --- a/crypto/ec/ectest.c +++ b/crypto/ec/ectest.c @@ -236,7 +236,7 @@ static void group_order_tests(EC_GROUP *group) } static void prime_field_tests(void) - { + { BN_CTX *ctx = NULL; BIGNUM *p, *a, *b; EC_GROUP *group; diff --git a/crypto/ecdh/Makefile b/crypto/ecdh/Makefile index 65d8904ee8a..ba05fea05ca 100644 --- a/crypto/ecdh/Makefile +++ b/crypto/ecdh/Makefile @@ -84,17 +84,12 @@ ech_err.o: ../../include/openssl/ossl_typ.h ../../include/openssl/safestack.h ech_err.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h ech_err.o: ech_err.c ech_key.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h -ech_key.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h -ech_key.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h -ech_key.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h -ech_key.o: ../../include/openssl/engine.h ../../include/openssl/evp.h -ech_key.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h -ech_key.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h -ech_key.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h -ech_key.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h -ech_key.o: ../../include/openssl/sha.h ../../include/openssl/stack.h -ech_key.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h -ech_key.o: ../../include/openssl/x509_vfy.h ech_key.c ech_locl.h +ech_key.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h +ech_key.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h +ech_key.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h +ech_key.o: ../../include/openssl/ossl_typ.h ../../include/openssl/safestack.h +ech_key.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h +ech_key.o: ech_key.c ech_locl.h ech_lib.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h ech_lib.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h ech_lib.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h diff --git a/crypto/ecdh/ech_key.c b/crypto/ecdh/ech_key.c index f44da9298b5..2988899ea2a 100644 --- a/crypto/ecdh/ech_key.c +++ b/crypto/ecdh/ech_key.c @@ -68,9 +68,6 @@ */ #include "ech_locl.h" -#ifndef OPENSSL_NO_ENGINE -#include -#endif int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, EC_KEY *eckey, diff --git a/crypto/ecdh/ech_lib.c b/crypto/ecdh/ech_lib.c index dadbfd3c49f..0644431b756 100644 --- a/crypto/ecdh/ech_lib.c +++ b/crypto/ecdh/ech_lib.c @@ -222,8 +222,15 @@ ECDH_DATA *ecdh_check(EC_KEY *key) ecdh_data = (ECDH_DATA *)ecdh_data_new(); if (ecdh_data == NULL) return NULL; - EC_KEY_insert_key_method_data(key, (void *)ecdh_data, - ecdh_data_dup, ecdh_data_free, ecdh_data_free); + data = EC_KEY_insert_key_method_data(key, (void *)ecdh_data, + ecdh_data_dup, ecdh_data_free, ecdh_data_free); + if (data != NULL) + { + /* Another thread raced us to install the key_method + * data and won. */ + ecdh_data_free(ecdh_data); + ecdh_data = (ECDH_DATA *)data; + } } else ecdh_data = (ECDH_DATA *)data; diff --git a/crypto/ecdsa/ecs_lib.c b/crypto/ecdsa/ecs_lib.c index e477da430ba..814a6bf4046 100644 --- a/crypto/ecdsa/ecs_lib.c +++ b/crypto/ecdsa/ecs_lib.c @@ -200,8 +200,15 @@ ECDSA_DATA *ecdsa_check(EC_KEY *key) ecdsa_data = (ECDSA_DATA *)ecdsa_data_new(); if (ecdsa_data == NULL) return NULL; - EC_KEY_insert_key_method_data(key, (void *)ecdsa_data, - ecdsa_data_dup, ecdsa_data_free, ecdsa_data_free); + data = EC_KEY_insert_key_method_data(key, (void *)ecdsa_data, + ecdsa_data_dup, ecdsa_data_free, ecdsa_data_free); + if (data != NULL) + { + /* Another thread raced us to install the key_method + * data and won. */ + ecdsa_data_free(ecdsa_data); + ecdsa_data = (ECDSA_DATA *)data; + } } else ecdsa_data = (ECDSA_DATA *)data; diff --git a/crypto/err/err_all.c b/crypto/err/err_all.c index bd8946d8ba0..8eb547d98d5 100644 --- a/crypto/err/err_all.c +++ b/crypto/err/err_all.c @@ -64,7 +64,9 @@ #endif #include #include +#ifndef OPENSSL_NO_COMP #include +#endif #ifndef OPENSSL_NO_RSA #include #endif @@ -95,6 +97,9 @@ #include #include #include +#ifdef OPENSSL_FIPS +#include +#endif #include #ifndef OPENSSL_NO_CMS #include @@ -102,11 +107,6 @@ #ifndef OPENSSL_NO_JPAKE #include #endif -#include - -#ifdef OPENSSL_FIPS -#include -#endif void ERR_load_crypto_strings(void) { @@ -130,7 +130,9 @@ void ERR_load_crypto_strings(void) ERR_load_ASN1_strings(); ERR_load_CONF_strings(); ERR_load_CRYPTO_strings(); +#ifndef OPENSSL_NO_COMP ERR_load_COMP_strings(); +#endif #ifndef OPENSSL_NO_EC ERR_load_EC_strings(); #endif @@ -153,15 +155,14 @@ void ERR_load_crypto_strings(void) #endif ERR_load_OCSP_strings(); ERR_load_UI_strings(); +#ifdef OPENSSL_FIPS + ERR_load_FIPS_strings(); +#endif #ifndef OPENSSL_NO_CMS ERR_load_CMS_strings(); #endif #ifndef OPENSSL_NO_JPAKE ERR_load_JPAKE_strings(); #endif - ERR_load_COMP_strings(); -#endif -#ifdef OPENSSL_FIPS - ERR_load_FIPS_strings(); #endif } diff --git a/crypto/evp/Makefile b/crypto/evp/Makefile index 0fe1b96bff4..1e46cebf5e7 100644 --- a/crypto/evp/Makefile +++ b/crypto/evp/Makefile @@ -18,7 +18,7 @@ TESTDATA=evptests.txt APPS= LIB=$(TOP)/libcrypto.a -LIBSRC= encode.c digest.c evp_enc.c evp_key.c evp_acnf.c \ +LIBSRC= encode.c digest.c evp_enc.c evp_key.c evp_acnf.c evp_cnf.c \ e_des.c e_bf.c e_idea.c e_des3.c e_camellia.c\ e_rc4.c e_aes.c names.c e_seed.c \ e_xcbc_d.c e_rc2.c e_cast.c e_rc5.c \ @@ -31,7 +31,7 @@ LIBSRC= encode.c digest.c evp_enc.c evp_key.c evp_acnf.c \ e_old.c pmeth_lib.c pmeth_fn.c pmeth_gn.c m_sigver.c evp_fips.c \ e_aes_cbc_hmac_sha1.c e_rc4_hmac_md5.c -LIBOBJ= encode.o digest.o evp_enc.o evp_key.o evp_acnf.o \ +LIBOBJ= encode.o digest.o evp_enc.o evp_key.o evp_acnf.o evp_cnf.o \ e_des.o e_bf.o e_idea.o e_des3.o e_camellia.o\ e_rc4.o e_aes.o names.o e_seed.o \ e_xcbc_d.o e_rc2.o e_cast.o e_rc5.o \ @@ -67,7 +67,7 @@ files: links: @$(PERL) $(TOP)/util/mklink.pl ../../include/openssl $(EXHEADER) @$(PERL) $(TOP)/util/mklink.pl ../../test $(TEST) - cp $(TESTDATA) ../../test + [ ! -f $(TESTDATA) ] || cp $(TESTDATA) ../../test @$(PERL) $(TOP)/util/mklink.pl ../../apps $(APPS) install: @@ -356,6 +356,20 @@ evp_acnf.o: ../../include/openssl/opensslconf.h evp_acnf.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h evp_acnf.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h evp_acnf.o: ../../include/openssl/symhacks.h ../cryptlib.h evp_acnf.c +evp_cnf.o: ../../e_os.h ../../include/openssl/asn1.h +evp_cnf.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h +evp_cnf.o: ../../include/openssl/conf.h ../../include/openssl/crypto.h +evp_cnf.o: ../../include/openssl/dso.h ../../include/openssl/e_os2.h +evp_cnf.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h +evp_cnf.o: ../../include/openssl/ecdsa.h ../../include/openssl/err.h +evp_cnf.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h +evp_cnf.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h +evp_cnf.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h +evp_cnf.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pkcs7.h +evp_cnf.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h +evp_cnf.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h +evp_cnf.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h +evp_cnf.o: ../../include/openssl/x509v3.h ../cryptlib.h evp_cnf.c evp_enc.o: ../../e_os.h ../../include/openssl/asn1.h evp_enc.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h evp_enc.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h @@ -437,28 +451,22 @@ evp_pkey.o: ../asn1/asn1_locl.h ../cryptlib.h evp_pkey.c m_dss.o: ../../e_os.h ../../include/openssl/asn1.h ../../include/openssl/bio.h m_dss.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h m_dss.o: ../../include/openssl/dsa.h ../../include/openssl/e_os2.h -m_dss.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h -m_dss.o: ../../include/openssl/ecdsa.h ../../include/openssl/err.h -m_dss.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h -m_dss.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h -m_dss.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h -m_dss.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pkcs7.h +m_dss.o: ../../include/openssl/err.h ../../include/openssl/evp.h +m_dss.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h +m_dss.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h +m_dss.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h m_dss.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h m_dss.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h -m_dss.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h m_dss.o: ../cryptlib.h m_dss.c m_dss1.o: ../../e_os.h ../../include/openssl/asn1.h ../../include/openssl/bio.h m_dss1.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h m_dss1.o: ../../include/openssl/dsa.h ../../include/openssl/e_os2.h -m_dss1.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h -m_dss1.o: ../../include/openssl/ecdsa.h ../../include/openssl/err.h -m_dss1.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h -m_dss1.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h -m_dss1.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h -m_dss1.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pkcs7.h +m_dss1.o: ../../include/openssl/err.h ../../include/openssl/evp.h +m_dss1.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h +m_dss1.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h +m_dss1.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h m_dss1.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h m_dss1.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h -m_dss1.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h m_dss1.o: ../cryptlib.h m_dss1.c m_ecdsa.o: ../../e_os.h ../../include/openssl/asn1.h m_ecdsa.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h @@ -563,16 +571,13 @@ m_sha.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h m_sha.o: ../cryptlib.h evp_locl.h m_sha.c m_sha1.o: ../../e_os.h ../../include/openssl/asn1.h ../../include/openssl/bio.h m_sha1.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h -m_sha1.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h -m_sha1.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h -m_sha1.o: ../../include/openssl/err.h ../../include/openssl/evp.h -m_sha1.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h -m_sha1.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h -m_sha1.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h -m_sha1.o: ../../include/openssl/pkcs7.h ../../include/openssl/rsa.h +m_sha1.o: ../../include/openssl/e_os2.h ../../include/openssl/err.h +m_sha1.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h +m_sha1.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h +m_sha1.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h +m_sha1.o: ../../include/openssl/ossl_typ.h ../../include/openssl/rsa.h m_sha1.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h m_sha1.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h -m_sha1.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h m_sha1.o: ../cryptlib.h m_sha1.c m_sigver.o: ../../e_os.h ../../include/openssl/asn1.h m_sigver.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c index 467e6b5ae9c..6fc469f9c45 100644 --- a/crypto/evp/digest.c +++ b/crypto/evp/digest.c @@ -267,6 +267,7 @@ int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size) return FIPS_digestfinal(ctx, md, size); #else int ret; + OPENSSL_assert(ctx->digest->md_size <= EVP_MAX_MD_SIZE); ret=ctx->digest->final(ctx,md); if (size != NULL) diff --git a/crypto/evp/e_aes.c b/crypto/evp/e_aes.c index 1e4af0cb751..1bfb5d92b34 100644 --- a/crypto/evp/e_aes.c +++ b/crypto/evp/e_aes.c @@ -969,8 +969,6 @@ static int aes_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, if (!gctx->iv_set) return -1; - if (!ctx->encrypt && gctx->taglen < 0) - return -1; if (in) { if (out == NULL) @@ -1012,6 +1010,8 @@ static int aes_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, { if (!ctx->encrypt) { + if (gctx->taglen < 0) + return -1; if (CRYPTO_gcm128_finish(&gctx->gcm, ctx->buf, gctx->taglen) != 0) return -1; @@ -1217,6 +1217,7 @@ static int aes_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, vpaes_set_encrypt_key(key, ctx->key_len*8, &cctx->ks); CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L, &cctx->ks, (block128_f)vpaes_encrypt); + cctx->str = NULL; cctx->key_set = 1; break; } diff --git a/crypto/evp/e_aes_cbc_hmac_sha1.c b/crypto/evp/e_aes_cbc_hmac_sha1.c index 710fb79baf4..483e04b605b 100644 --- a/crypto/evp/e_aes_cbc_hmac_sha1.c +++ b/crypto/evp/e_aes_cbc_hmac_sha1.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 2011 The OpenSSL Project. All rights reserved. + * Copyright (c) 2011-2013 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -90,6 +90,10 @@ typedef struct defined(_M_AMD64) || defined(_M_X64) || \ defined(__INTEL__) ) +#if defined(__GNUC__) && __GNUC__>=2 && !defined(PEDANTIC) +# define BSWAP(x) ({ unsigned int r=(x); asm ("bswapl %0":"=r"(r):"0"(r)); r; }) +#endif + extern unsigned int OPENSSL_ia32cap_P[2]; #define AESNI_CAPABLE (1<<(57-32)) @@ -167,6 +171,9 @@ static void sha1_update(SHA_CTX *c,const void *data,size_t len) SHA1_Update(c,ptr,res); } +#ifdef SHA1_Update +#undef SHA1_Update +#endif #define SHA1_Update sha1_update static int aesni_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, @@ -184,6 +191,8 @@ static int aesni_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, sha_off = SHA_CBLOCK-key->md.num; #endif + key->payload_length = NO_PAYLOAD_LENGTH; + if (len%AES_BLOCK_SIZE) return 0; if (ctx->encrypt) { @@ -234,47 +243,210 @@ static int aesni_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, &key->ks,ctx->iv,1); } } else { - unsigned char mac[SHA_DIGEST_LENGTH]; + union { unsigned int u[SHA_DIGEST_LENGTH/sizeof(unsigned int)]; + unsigned char c[32+SHA_DIGEST_LENGTH]; } mac, *pmac; + + /* arrange cache line alignment */ + pmac = (void *)(((size_t)mac.c+31)&((size_t)0-32)); /* decrypt HMAC|padding at once */ aesni_cbc_encrypt(in,out,len, &key->ks,ctx->iv,0); if (plen) { /* "TLS" mode of operation */ - /* figure out payload length */ - if (len<(size_t)(out[len-1]+1+SHA_DIGEST_LENGTH)) - return 0; - - len -= (out[len-1]+1+SHA_DIGEST_LENGTH); + size_t inp_len, mask, j, i; + unsigned int res, maxpad, pad, bitlen; + int ret = 1; + union { unsigned int u[SHA_LBLOCK]; + unsigned char c[SHA_CBLOCK]; } + *data = (void *)key->md.data; if ((key->aux.tls_aad[plen-4]<<8|key->aux.tls_aad[plen-3]) - >= TLS1_1_VERSION) { - len -= AES_BLOCK_SIZE; + >= TLS1_1_VERSION) iv = AES_BLOCK_SIZE; - } - key->aux.tls_aad[plen-2] = len>>8; - key->aux.tls_aad[plen-1] = len; + if (len<(iv+SHA_DIGEST_LENGTH+1)) + return 0; - /* calculate HMAC and verify it */ + /* omit explicit iv */ + out += iv; + len -= iv; + + /* figure out payload length */ + pad = out[len-1]; + maxpad = len-(SHA_DIGEST_LENGTH+1); + maxpad |= (255-maxpad)>>(sizeof(maxpad)*8-8); + maxpad &= 255; + + inp_len = len - (SHA_DIGEST_LENGTH+pad+1); + mask = (0-((inp_len-len)>>(sizeof(inp_len)*8-1))); + inp_len &= mask; + ret &= (int)mask; + + key->aux.tls_aad[plen-2] = inp_len>>8; + key->aux.tls_aad[plen-1] = inp_len; + + /* calculate HMAC */ key->md = key->head; SHA1_Update(&key->md,key->aux.tls_aad,plen); - SHA1_Update(&key->md,out+iv,len); - SHA1_Final(mac,&key->md); +#if 1 + len -= SHA_DIGEST_LENGTH; /* amend mac */ + if (len>=(256+SHA_CBLOCK)) { + j = (len-(256+SHA_CBLOCK))&(0-SHA_CBLOCK); + j += SHA_CBLOCK-key->md.num; + SHA1_Update(&key->md,out,j); + out += j; + len -= j; + inp_len -= j; + } + + /* but pretend as if we hashed padded payload */ + bitlen = key->md.Nl+(inp_len<<3); /* at most 18 bits */ +#ifdef BSWAP + bitlen = BSWAP(bitlen); +#else + mac.c[0] = 0; + mac.c[1] = (unsigned char)(bitlen>>16); + mac.c[2] = (unsigned char)(bitlen>>8); + mac.c[3] = (unsigned char)bitlen; + bitlen = mac.u[0]; +#endif + + pmac->u[0]=0; + pmac->u[1]=0; + pmac->u[2]=0; + pmac->u[3]=0; + pmac->u[4]=0; + + for (res=key->md.num, j=0;j>(sizeof(j)*8-8); + c &= mask; + c |= 0x80&~mask&~((inp_len-j)>>(sizeof(j)*8-8)); + data->c[res++]=(unsigned char)c; + + if (res!=SHA_CBLOCK) continue; + + mask = 0-((inp_len+8-j)>>(sizeof(j)*8-1)); + data->u[SHA_LBLOCK-1] |= bitlen&mask; + sha1_block_data_order(&key->md,data,1); + mask &= 0-((j-inp_len-73)>>(sizeof(j)*8-1)); + pmac->u[0] |= key->md.h0 & mask; + pmac->u[1] |= key->md.h1 & mask; + pmac->u[2] |= key->md.h2 & mask; + pmac->u[3] |= key->md.h3 & mask; + pmac->u[4] |= key->md.h4 & mask; + res=0; + } + + for(i=res;ic[i]=0; + + if (res>SHA_CBLOCK-8) { + mask = 0-((inp_len+8-j)>>(sizeof(j)*8-1)); + data->u[SHA_LBLOCK-1] |= bitlen&mask; + sha1_block_data_order(&key->md,data,1); + mask &= 0-((j-inp_len-73)>>(sizeof(j)*8-1)); + pmac->u[0] |= key->md.h0 & mask; + pmac->u[1] |= key->md.h1 & mask; + pmac->u[2] |= key->md.h2 & mask; + pmac->u[3] |= key->md.h3 & mask; + pmac->u[4] |= key->md.h4 & mask; + + memset(data,0,SHA_CBLOCK); + j+=64; + } + data->u[SHA_LBLOCK-1] = bitlen; + sha1_block_data_order(&key->md,data,1); + mask = 0-((j-inp_len-73)>>(sizeof(j)*8-1)); + pmac->u[0] |= key->md.h0 & mask; + pmac->u[1] |= key->md.h1 & mask; + pmac->u[2] |= key->md.h2 & mask; + pmac->u[3] |= key->md.h3 & mask; + pmac->u[4] |= key->md.h4 & mask; + +#ifdef BSWAP + pmac->u[0] = BSWAP(pmac->u[0]); + pmac->u[1] = BSWAP(pmac->u[1]); + pmac->u[2] = BSWAP(pmac->u[2]); + pmac->u[3] = BSWAP(pmac->u[3]); + pmac->u[4] = BSWAP(pmac->u[4]); +#else + for (i=0;i<5;i++) { + res = pmac->u[i]; + pmac->c[4*i+0]=(unsigned char)(res>>24); + pmac->c[4*i+1]=(unsigned char)(res>>16); + pmac->c[4*i+2]=(unsigned char)(res>>8); + pmac->c[4*i+3]=(unsigned char)res; + } +#endif + len += SHA_DIGEST_LENGTH; +#else + SHA1_Update(&key->md,out,inp_len); + res = key->md.num; + SHA1_Final(pmac->c,&key->md); + + { + unsigned int inp_blocks, pad_blocks; + + /* but pretend as if we hashed padded payload */ + inp_blocks = 1+((SHA_CBLOCK-9-res)>>(sizeof(res)*8-1)); + res += (unsigned int)(len-inp_len); + pad_blocks = res / SHA_CBLOCK; + res %= SHA_CBLOCK; + pad_blocks += 1+((SHA_CBLOCK-9-res)>>(sizeof(res)*8-1)); + for (;inp_blocksmd,data,1); + } +#endif key->md = key->tail; - SHA1_Update(&key->md,mac,SHA_DIGEST_LENGTH); - SHA1_Final(mac,&key->md); + SHA1_Update(&key->md,pmac->c,SHA_DIGEST_LENGTH); + SHA1_Final(pmac->c,&key->md); - if (memcmp(out+iv+len,mac,SHA_DIGEST_LENGTH)) - return 0; + /* verify HMAC */ + out += inp_len; + len -= inp_len; +#if 1 + { + unsigned char *p = out+len-1-maxpad-SHA_DIGEST_LENGTH; + size_t off = out-p; + unsigned int c, cmask; + + maxpad += SHA_DIGEST_LENGTH; + for (res=0,i=0,j=0;j>(sizeof(int)*8-1); + res |= (c^pad)&~cmask; /* ... and padding */ + cmask &= ((int)(off-1-j))>>(sizeof(int)*8-1); + res |= (c^pmac->c[i])&cmask; + i += 1&cmask; + } + maxpad -= SHA_DIGEST_LENGTH; + + res = 0-((0-res)>>(sizeof(res)*8-1)); + ret &= (int)~res; + } +#else + for (res=0,i=0;ic[i]; + res = 0-((0-res)>>(sizeof(res)*8-1)); + ret &= (int)~res; + + /* verify padding */ + pad = (pad&~res) | (maxpad&res); + out = out+len-1-pad; + for (res=0,i=0;i>(sizeof(res)*8-1); + ret &= (int)~res; +#endif + return ret; } else { SHA1_Update(&key->md,out,len); } } - key->payload_length = NO_PAYLOAD_LENGTH; - return 1; } @@ -309,6 +481,8 @@ static int aesni_cbc_hmac_sha1_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void SHA1_Init(&key->tail); SHA1_Update(&key->tail,hmac_key,sizeof(hmac_key)); + OPENSSL_cleanse(hmac_key,sizeof(hmac_key)); + return 1; } case EVP_CTRL_AEAD_TLS1_AAD: diff --git a/crypto/evp/evp.h b/crypto/evp/evp.h index 0d1b20a7d38..faeb3c24e61 100644 --- a/crypto/evp/evp.h +++ b/crypto/evp/evp.h @@ -402,7 +402,6 @@ struct evp_cipher_st /* Length of tag for TLS */ #define EVP_GCM_TLS_TAG_LEN 16 - typedef struct evp_cipher_info_st { const EVP_CIPHER *cipher; @@ -789,8 +788,8 @@ const EVP_CIPHER *EVP_aes_128_cfb128(void); # define EVP_aes_128_cfb EVP_aes_128_cfb128 const EVP_CIPHER *EVP_aes_128_ofb(void); const EVP_CIPHER *EVP_aes_128_ctr(void); -const EVP_CIPHER *EVP_aes_128_gcm(void); const EVP_CIPHER *EVP_aes_128_ccm(void); +const EVP_CIPHER *EVP_aes_128_gcm(void); const EVP_CIPHER *EVP_aes_128_xts(void); const EVP_CIPHER *EVP_aes_192_ecb(void); const EVP_CIPHER *EVP_aes_192_cbc(void); @@ -800,8 +799,8 @@ const EVP_CIPHER *EVP_aes_192_cfb128(void); # define EVP_aes_192_cfb EVP_aes_192_cfb128 const EVP_CIPHER *EVP_aes_192_ofb(void); const EVP_CIPHER *EVP_aes_192_ctr(void); -const EVP_CIPHER *EVP_aes_192_gcm(void); const EVP_CIPHER *EVP_aes_192_ccm(void); +const EVP_CIPHER *EVP_aes_192_gcm(void); const EVP_CIPHER *EVP_aes_256_ecb(void); const EVP_CIPHER *EVP_aes_256_cbc(void); const EVP_CIPHER *EVP_aes_256_cfb1(void); @@ -810,8 +809,8 @@ const EVP_CIPHER *EVP_aes_256_cfb128(void); # define EVP_aes_256_cfb EVP_aes_256_cfb128 const EVP_CIPHER *EVP_aes_256_ofb(void); const EVP_CIPHER *EVP_aes_256_ctr(void); -const EVP_CIPHER *EVP_aes_256_gcm(void); const EVP_CIPHER *EVP_aes_256_ccm(void); +const EVP_CIPHER *EVP_aes_256_gcm(void); const EVP_CIPHER *EVP_aes_256_xts(void); #if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA1) const EVP_CIPHER *EVP_aes_128_cbc_hmac_sha1(void); @@ -1243,6 +1242,8 @@ void EVP_PKEY_meth_set_ctrl(EVP_PKEY_METHOD *pmeth, int (*ctrl_str)(EVP_PKEY_CTX *ctx, const char *type, const char *value)); +void EVP_add_alg_module(void); + /* BEGIN ERROR CODES */ /* The following lines are auto generated by the script mkerr.pl. Any changes * made after this point may be overwritten when the script is next run. @@ -1257,6 +1258,7 @@ void ERR_load_EVP_strings(void); #define EVP_F_AES_INIT_KEY 133 #define EVP_F_AES_XTS 172 #define EVP_F_AES_XTS_CIPHER 175 +#define EVP_F_ALG_MODULE_INIT 177 #define EVP_F_CAMELLIA_INIT_KEY 159 #define EVP_F_CMAC_INIT 173 #define EVP_F_D2I_PKEY 100 @@ -1350,15 +1352,19 @@ void ERR_load_EVP_strings(void); #define EVP_R_DIFFERENT_PARAMETERS 153 #define EVP_R_DISABLED_FOR_FIPS 163 #define EVP_R_ENCODE_ERROR 115 +#define EVP_R_ERROR_LOADING_SECTION 165 +#define EVP_R_ERROR_SETTING_FIPS_MODE 166 #define EVP_R_EVP_PBE_CIPHERINIT_ERROR 119 #define EVP_R_EXPECTING_AN_RSA_KEY 127 #define EVP_R_EXPECTING_A_DH_KEY 128 #define EVP_R_EXPECTING_A_DSA_KEY 129 #define EVP_R_EXPECTING_A_ECDSA_KEY 141 #define EVP_R_EXPECTING_A_EC_KEY 142 +#define EVP_R_FIPS_MODE_NOT_SUPPORTED 167 #define EVP_R_INITIALIZATION_ERROR 134 #define EVP_R_INPUT_NOT_INITIALIZED 111 #define EVP_R_INVALID_DIGEST 152 +#define EVP_R_INVALID_FIPS_MODE 168 #define EVP_R_INVALID_KEY_LENGTH 130 #define EVP_R_INVALID_OPERATION 148 #define EVP_R_IV_TOO_LARGE 102 @@ -1383,6 +1389,7 @@ void ERR_load_EVP_strings(void); #define EVP_R_TOO_LARGE 164 #define EVP_R_UNKNOWN_CIPHER 160 #define EVP_R_UNKNOWN_DIGEST 161 +#define EVP_R_UNKNOWN_OPTION 169 #define EVP_R_UNKNOWN_PBE_ALGORITHM 121 #define EVP_R_UNSUPORTED_NUMBER_OF_ROUNDS 135 #define EVP_R_UNSUPPORTED_ALGORITHM 156 diff --git a/crypto/evp/evp_cnf.c b/crypto/evp/evp_cnf.c new file mode 100644 index 00000000000..2e4db302359 --- /dev/null +++ b/crypto/evp/evp_cnf.c @@ -0,0 +1,125 @@ +/* evp_cnf.c */ +/* Written by Stephen Henson (steve@openssl.org) for the OpenSSL + * project 2007. + */ +/* ==================================================================== + * Copyright (c) 2007 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include +#include +#include "cryptlib.h" +#include +#include +#include +#include +#ifdef OPENSSL_FIPS +#include +#endif + + +/* Algorithm configuration module. */ + +static int alg_module_init(CONF_IMODULE *md, const CONF *cnf) + { + int i; + const char *oid_section; + STACK_OF(CONF_VALUE) *sktmp; + CONF_VALUE *oval; + oid_section = CONF_imodule_get_value(md); + if(!(sktmp = NCONF_get_section(cnf, oid_section))) + { + EVPerr(EVP_F_ALG_MODULE_INIT, EVP_R_ERROR_LOADING_SECTION); + return 0; + } + for(i = 0; i < sk_CONF_VALUE_num(sktmp); i++) + { + oval = sk_CONF_VALUE_value(sktmp, i); + if (!strcmp(oval->name, "fips_mode")) + { + int m; + if (!X509V3_get_value_bool(oval, &m)) + { + EVPerr(EVP_F_ALG_MODULE_INIT, EVP_R_INVALID_FIPS_MODE); + return 0; + } + if (m > 0) + { +#ifdef OPENSSL_FIPS + if (!FIPS_mode() && !FIPS_mode_set(1)) + { + EVPerr(EVP_F_ALG_MODULE_INIT, EVP_R_ERROR_SETTING_FIPS_MODE); + return 0; + } +#else + EVPerr(EVP_F_ALG_MODULE_INIT, EVP_R_FIPS_MODE_NOT_SUPPORTED); + return 0; +#endif + } + } + else + { + EVPerr(EVP_F_ALG_MODULE_INIT, EVP_R_UNKNOWN_OPTION); + ERR_add_error_data(4, "name=", oval->name, + ", value=", oval->value); + } + + } + return 1; + } + +void EVP_add_alg_module(void) + { + CONF_module_add("alg_section", alg_module_init, 0); + } diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c index db0f76d59bc..08eab9882f6 100644 --- a/crypto/evp/evp_err.c +++ b/crypto/evp/evp_err.c @@ -75,6 +75,7 @@ static ERR_STRING_DATA EVP_str_functs[]= {ERR_FUNC(EVP_F_AES_INIT_KEY), "AES_INIT_KEY"}, {ERR_FUNC(EVP_F_AES_XTS), "AES_XTS"}, {ERR_FUNC(EVP_F_AES_XTS_CIPHER), "AES_XTS_CIPHER"}, +{ERR_FUNC(EVP_F_ALG_MODULE_INIT), "ALG_MODULE_INIT"}, {ERR_FUNC(EVP_F_CAMELLIA_INIT_KEY), "CAMELLIA_INIT_KEY"}, {ERR_FUNC(EVP_F_CMAC_INIT), "CMAC_INIT"}, {ERR_FUNC(EVP_F_D2I_PKEY), "D2I_PKEY"}, @@ -171,15 +172,19 @@ static ERR_STRING_DATA EVP_str_reasons[]= {ERR_REASON(EVP_R_DIFFERENT_PARAMETERS) ,"different parameters"}, {ERR_REASON(EVP_R_DISABLED_FOR_FIPS) ,"disabled for fips"}, {ERR_REASON(EVP_R_ENCODE_ERROR) ,"encode error"}, +{ERR_REASON(EVP_R_ERROR_LOADING_SECTION) ,"error loading section"}, +{ERR_REASON(EVP_R_ERROR_SETTING_FIPS_MODE),"error setting fips mode"}, {ERR_REASON(EVP_R_EVP_PBE_CIPHERINIT_ERROR),"evp pbe cipherinit error"}, {ERR_REASON(EVP_R_EXPECTING_AN_RSA_KEY) ,"expecting an rsa key"}, {ERR_REASON(EVP_R_EXPECTING_A_DH_KEY) ,"expecting a dh key"}, {ERR_REASON(EVP_R_EXPECTING_A_DSA_KEY) ,"expecting a dsa key"}, {ERR_REASON(EVP_R_EXPECTING_A_ECDSA_KEY) ,"expecting a ecdsa key"}, {ERR_REASON(EVP_R_EXPECTING_A_EC_KEY) ,"expecting a ec key"}, +{ERR_REASON(EVP_R_FIPS_MODE_NOT_SUPPORTED),"fips mode not supported"}, {ERR_REASON(EVP_R_INITIALIZATION_ERROR) ,"initialization error"}, {ERR_REASON(EVP_R_INPUT_NOT_INITIALIZED) ,"input not initialized"}, {ERR_REASON(EVP_R_INVALID_DIGEST) ,"invalid digest"}, +{ERR_REASON(EVP_R_INVALID_FIPS_MODE) ,"invalid fips mode"}, {ERR_REASON(EVP_R_INVALID_KEY_LENGTH) ,"invalid key length"}, {ERR_REASON(EVP_R_INVALID_OPERATION) ,"invalid operation"}, {ERR_REASON(EVP_R_IV_TOO_LARGE) ,"iv too large"}, @@ -204,6 +209,7 @@ static ERR_STRING_DATA EVP_str_reasons[]= {ERR_REASON(EVP_R_TOO_LARGE) ,"too large"}, {ERR_REASON(EVP_R_UNKNOWN_CIPHER) ,"unknown cipher"}, {ERR_REASON(EVP_R_UNKNOWN_DIGEST) ,"unknown digest"}, +{ERR_REASON(EVP_R_UNKNOWN_OPTION) ,"unknown option"}, {ERR_REASON(EVP_R_UNKNOWN_PBE_ALGORITHM) ,"unknown pbe algorithm"}, {ERR_REASON(EVP_R_UNSUPORTED_NUMBER_OF_ROUNDS),"unsuported number of rounds"}, {ERR_REASON(EVP_R_UNSUPPORTED_ALGORITHM) ,"unsupported algorithm"}, diff --git a/crypto/evp/m_dss.c b/crypto/evp/m_dss.c index 4ad63ada6fe..6fb7e9a8610 100644 --- a/crypto/evp/m_dss.c +++ b/crypto/evp/m_dss.c @@ -60,7 +60,7 @@ #include "cryptlib.h" #include #include -#include +#include #ifndef OPENSSL_NO_DSA #include #endif diff --git a/crypto/evp/m_dss1.c b/crypto/evp/m_dss1.c index f80170efeb9..2df362a6701 100644 --- a/crypto/evp/m_dss1.c +++ b/crypto/evp/m_dss1.c @@ -63,7 +63,7 @@ #include #include -#include +#include #ifndef OPENSSL_NO_DSA #include #endif diff --git a/crypto/evp/m_sha1.c b/crypto/evp/m_sha1.c index 3cb11f1ebb1..bd0c01ad3c4 100644 --- a/crypto/evp/m_sha1.c +++ b/crypto/evp/m_sha1.c @@ -65,7 +65,7 @@ #include #include -#include +#include #ifndef OPENSSL_NO_RSA #include #endif diff --git a/crypto/evp/p_sign.c b/crypto/evp/p_sign.c index dfa48c157cf..8afb664306e 100644 --- a/crypto/evp/p_sign.c +++ b/crypto/evp/p_sign.c @@ -80,7 +80,7 @@ int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, unsigned int *siglen, { unsigned char m[EVP_MAX_MD_SIZE]; unsigned int m_len; - int i=0,ok=0,v; + int i = 0,ok = 0,v; EVP_MD_CTX tmp_ctx; EVP_PKEY_CTX *pkctx = NULL; diff --git a/crypto/evp/p_verify.c b/crypto/evp/p_verify.c index 5f5c409f45f..c66d63ccf85 100644 --- a/crypto/evp/p_verify.c +++ b/crypto/evp/p_verify.c @@ -67,7 +67,7 @@ int EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf, { unsigned char m[EVP_MAX_MD_SIZE]; unsigned int m_len; - int i=-1,ok=0,v; + int i = 0,ok = 0,v; EVP_MD_CTX tmp_ctx; EVP_PKEY_CTX *pkctx = NULL; diff --git a/crypto/md4/md4_dgst.c b/crypto/md4/md4_dgst.c index 82c2cb2d98a..b5b165b0526 100644 --- a/crypto/md4/md4_dgst.c +++ b/crypto/md4/md4_dgst.c @@ -106,22 +106,23 @@ void md4_block_data_order (MD4_CTX *c, const void *data_, size_t num) for (;num--;) { - HOST_c2l(data,l); X( 0)=l; HOST_c2l(data,l); X( 1)=l; + (void)HOST_c2l(data,l); X( 0)=l; + (void)HOST_c2l(data,l); X( 1)=l; /* Round 0 */ - R0(A,B,C,D,X( 0), 3,0); HOST_c2l(data,l); X( 2)=l; - R0(D,A,B,C,X( 1), 7,0); HOST_c2l(data,l); X( 3)=l; - R0(C,D,A,B,X( 2),11,0); HOST_c2l(data,l); X( 4)=l; - R0(B,C,D,A,X( 3),19,0); HOST_c2l(data,l); X( 5)=l; - R0(A,B,C,D,X( 4), 3,0); HOST_c2l(data,l); X( 6)=l; - R0(D,A,B,C,X( 5), 7,0); HOST_c2l(data,l); X( 7)=l; - R0(C,D,A,B,X( 6),11,0); HOST_c2l(data,l); X( 8)=l; - R0(B,C,D,A,X( 7),19,0); HOST_c2l(data,l); X( 9)=l; - R0(A,B,C,D,X( 8), 3,0); HOST_c2l(data,l); X(10)=l; - R0(D,A,B,C,X( 9), 7,0); HOST_c2l(data,l); X(11)=l; - R0(C,D,A,B,X(10),11,0); HOST_c2l(data,l); X(12)=l; - R0(B,C,D,A,X(11),19,0); HOST_c2l(data,l); X(13)=l; - R0(A,B,C,D,X(12), 3,0); HOST_c2l(data,l); X(14)=l; - R0(D,A,B,C,X(13), 7,0); HOST_c2l(data,l); X(15)=l; + R0(A,B,C,D,X( 0), 3,0); (void)HOST_c2l(data,l); X( 2)=l; + R0(D,A,B,C,X( 1), 7,0); (void)HOST_c2l(data,l); X( 3)=l; + R0(C,D,A,B,X( 2),11,0); (void)HOST_c2l(data,l); X( 4)=l; + R0(B,C,D,A,X( 3),19,0); (void)HOST_c2l(data,l); X( 5)=l; + R0(A,B,C,D,X( 4), 3,0); (void)HOST_c2l(data,l); X( 6)=l; + R0(D,A,B,C,X( 5), 7,0); (void)HOST_c2l(data,l); X( 7)=l; + R0(C,D,A,B,X( 6),11,0); (void)HOST_c2l(data,l); X( 8)=l; + R0(B,C,D,A,X( 7),19,0); (void)HOST_c2l(data,l); X( 9)=l; + R0(A,B,C,D,X( 8), 3,0); (void)HOST_c2l(data,l); X(10)=l; + R0(D,A,B,C,X( 9), 7,0); (void)HOST_c2l(data,l); X(11)=l; + R0(C,D,A,B,X(10),11,0); (void)HOST_c2l(data,l); X(12)=l; + R0(B,C,D,A,X(11),19,0); (void)HOST_c2l(data,l); X(13)=l; + R0(A,B,C,D,X(12), 3,0); (void)HOST_c2l(data,l); X(14)=l; + R0(D,A,B,C,X(13), 7,0); (void)HOST_c2l(data,l); X(15)=l; R0(C,D,A,B,X(14),11,0); R0(B,C,D,A,X(15),19,0); /* Round 1 */ diff --git a/crypto/md4/md4_locl.h b/crypto/md4/md4_locl.h index c8085b0eadf..99c3e5004c9 100644 --- a/crypto/md4/md4_locl.h +++ b/crypto/md4/md4_locl.h @@ -77,10 +77,10 @@ void md4_block_data_order (MD4_CTX *c, const void *p,size_t num); #define HASH_FINAL MD4_Final #define HASH_MAKE_STRING(c,s) do { \ unsigned long ll; \ - ll=(c)->A; HOST_l2c(ll,(s)); \ - ll=(c)->B; HOST_l2c(ll,(s)); \ - ll=(c)->C; HOST_l2c(ll,(s)); \ - ll=(c)->D; HOST_l2c(ll,(s)); \ + ll=(c)->A; (void)HOST_l2c(ll,(s)); \ + ll=(c)->B; (void)HOST_l2c(ll,(s)); \ + ll=(c)->C; (void)HOST_l2c(ll,(s)); \ + ll=(c)->D; (void)HOST_l2c(ll,(s)); \ } while (0) #define HASH_BLOCK_DATA_ORDER md4_block_data_order diff --git a/crypto/md5/asm/md5-x86_64.pl b/crypto/md5/asm/md5-x86_64.pl index 867885435e2..f11224d1722 100755 --- a/crypto/md5/asm/md5-x86_64.pl +++ b/crypto/md5/asm/md5-x86_64.pl @@ -120,7 +120,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; my $dir=$1; my $xlate; die "can't locate x86_64-xlate.pl"; no warnings qw(uninitialized); -open STDOUT,"| $^X $xlate $flavour $output"; +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; $code .= <A; HOST_l2c(ll,(s)); \ - ll=(c)->B; HOST_l2c(ll,(s)); \ - ll=(c)->C; HOST_l2c(ll,(s)); \ - ll=(c)->D; HOST_l2c(ll,(s)); \ + ll=(c)->A; (void)HOST_l2c(ll,(s)); \ + ll=(c)->B; (void)HOST_l2c(ll,(s)); \ + ll=(c)->C; (void)HOST_l2c(ll,(s)); \ + ll=(c)->D; (void)HOST_l2c(ll,(s)); \ } while (0) #define HASH_BLOCK_DATA_ORDER md5_block_data_order diff --git a/crypto/mdc2/mdc2dgst.c b/crypto/mdc2/mdc2dgst.c index b74bb1a7594..d66ed6a1c6a 100644 --- a/crypto/mdc2/mdc2dgst.c +++ b/crypto/mdc2/mdc2dgst.c @@ -59,9 +59,9 @@ #include #include #include +#include #include #include -#include #undef c2l #define c2l(c,l) (l =((DES_LONG)(*((c)++))) , \ diff --git a/crypto/mem.c b/crypto/mem.c index 21c00113808..1cc62eafd12 100644 --- a/crypto/mem.c +++ b/crypto/mem.c @@ -121,10 +121,10 @@ static void (*set_debug_options_func)(long) = NULL; static long (*get_debug_options_func)(void) = NULL; #endif - int CRYPTO_set_mem_functions(void *(*m)(size_t), void *(*r)(void *, size_t), void (*f)(void *)) { + /* Dummy call just to ensure OPENSSL_init() gets linked in */ OPENSSL_init(); if (!allow_customize) return 0; diff --git a/crypto/modes/asm/ghash-x86.pl b/crypto/modes/asm/ghash-x86.pl index 6b09669d474..83c727e07f9 100755 --- a/crypto/modes/asm/ghash-x86.pl +++ b/crypto/modes/asm/ghash-x86.pl @@ -635,7 +635,7 @@ sub mmx_loop() { { my @lo = ("mm0","mm1","mm2"); my @hi = ("mm3","mm4","mm5"); my @tmp = ("mm6","mm7"); - my $off1=0,$off2=0,$i; + my ($off1,$off2,$i) = (0,0,); &add ($Htbl,128); # optimize for size &lea ("edi",&DWP(16+128,"esp")); @@ -883,7 +883,7 @@ sub reduction_alg9 { # 17/13 times faster than Intel version my ($Xhi,$Xi) = @_; # 1st phase - &movdqa ($T1,$Xi) # + &movdqa ($T1,$Xi); # &psllq ($Xi,1); &pxor ($Xi,$T1); # &psllq ($Xi,5); # @@ -1019,7 +1019,7 @@ my ($Xhi,$Xi) = @_; &movdqa ($Xhn,$Xn); &pxor ($Xhi,$T1); # "Ii+Xi", consume early - &movdqa ($T1,$Xi) #&reduction_alg9($Xhi,$Xi); 1st phase + &movdqa ($T1,$Xi); #&reduction_alg9($Xhi,$Xi); 1st phase &psllq ($Xi,1); &pxor ($Xi,$T1); # &psllq ($Xi,5); # diff --git a/crypto/modes/asm/ghash-x86_64.pl b/crypto/modes/asm/ghash-x86_64.pl index a5ae180882d..38d779edbcf 100755 --- a/crypto/modes/asm/ghash-x86_64.pl +++ b/crypto/modes/asm/ghash-x86_64.pl @@ -50,7 +50,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or die "can't locate x86_64-xlate.pl"; -open STDOUT,"| $^X $xlate $flavour $output"; +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; # common register layout $nlo="%rax"; diff --git a/crypto/modes/gcm128.c b/crypto/modes/gcm128.c index 7d6d0349702..0e6ff8b0a15 100644 --- a/crypto/modes/gcm128.c +++ b/crypto/modes/gcm128.c @@ -723,7 +723,7 @@ void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx,void *key,block128_f block) # endif gcm_init_4bit(ctx->Htable,ctx->H.u); # if defined(GHASH_ASM_X86) /* x86 only */ -# if defined(OPENSSL_IA32_SSE2) +# if defined(OPENSSL_IA32_SSE2) if (OPENSSL_ia32cap_P[0]&(1<<25)) { /* check SSE bit */ # else if (OPENSSL_ia32cap_P[0]&(1<<23)) { /* check MMX bit */ @@ -1398,7 +1398,7 @@ int CRYPTO_gcm128_finish(GCM128_CONTEXT *ctx,const unsigned char *tag, void (*gcm_gmult_p)(u64 Xi[2],const u128 Htable[16]) = ctx->gmult; #endif - if (ctx->mres) + if (ctx->mres || ctx->ares) GCM_MUL(ctx,Xi); if (is_endian.little) { diff --git a/crypto/objects/o_names.c b/crypto/objects/o_names.c index 84380a96a98..4a548c2ed49 100644 --- a/crypto/objects/o_names.c +++ b/crypto/objects/o_names.c @@ -73,7 +73,7 @@ int OBJ_NAME_new_index(unsigned long (*hash_func)(const char *), name_funcs_stack=sk_NAME_FUNCS_new_null(); MemCheck_on(); } - if ((name_funcs_stack == NULL)) + if (name_funcs_stack == NULL) { /* ERROR */ return(0); diff --git a/crypto/ocsp/ocsp_vfy.c b/crypto/ocsp/ocsp_vfy.c index 415d67e61cf..276718304dd 100644 --- a/crypto/ocsp/ocsp_vfy.c +++ b/crypto/ocsp/ocsp_vfy.c @@ -91,9 +91,12 @@ int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs, { EVP_PKEY *skey; skey = X509_get_pubkey(signer); - ret = OCSP_BASICRESP_verify(bs, skey, 0); - EVP_PKEY_free(skey); - if(ret <= 0) + if (skey) + { + ret = OCSP_BASICRESP_verify(bs, skey, 0); + EVP_PKEY_free(skey); + } + if(!skey || ret <= 0) { OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, OCSP_R_SIGNATURE_FAILURE); goto end; @@ -108,6 +111,7 @@ int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs, init_res = X509_STORE_CTX_init(&ctx, st, signer, bs->certs); if(!init_res) { + ret = -1; OCSPerr(OCSP_F_OCSP_BASIC_VERIFY,ERR_R_X509_LIB); goto end; } diff --git a/crypto/opensslv.h b/crypto/opensslv.h index 71be3590af4..5bc8e53e66a 100644 --- a/crypto/opensslv.h +++ b/crypto/opensslv.h @@ -25,11 +25,11 @@ * (Prior to 0.9.5a beta1, a different scheme was used: MMNNFFRBB for * major minor fix final patch/beta) */ -#define OPENSSL_VERSION_NUMBER 0x1000103fL +#define OPENSSL_VERSION_NUMBER 0x1000105fL #ifdef OPENSSL_FIPS -#define OPENSSL_VERSION_TEXT "OpenSSL 1.0.1c-fips 10 May 2012" +#define OPENSSL_VERSION_TEXT "OpenSSL 1.0.1e-fips 11 Feb 2013" #else -#define OPENSSL_VERSION_TEXT "OpenSSL 1.0.1c 10 May 2012" +#define OPENSSL_VERSION_TEXT "OpenSSL 1.0.1e 11 Feb 2013" #endif #define OPENSSL_VERSION_PTEXT " part of " OPENSSL_VERSION_TEXT diff --git a/crypto/pem/pem_all.c b/crypto/pem/pem_all.c index 3e7a6093ad8..eac0460e3eb 100644 --- a/crypto/pem/pem_all.c +++ b/crypto/pem/pem_all.c @@ -193,7 +193,61 @@ RSA *PEM_read_RSAPrivateKey(FILE *fp, RSA **rsa, pem_password_cb *cb, #endif +#ifdef OPENSSL_FIPS + +int PEM_write_bio_RSAPrivateKey(BIO *bp, RSA *x, const EVP_CIPHER *enc, + unsigned char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + if (FIPS_mode()) + { + EVP_PKEY *k; + int ret; + k = EVP_PKEY_new(); + if (!k) + return 0; + EVP_PKEY_set1_RSA(k, x); + + ret = PEM_write_bio_PrivateKey(bp, k, enc, kstr, klen, cb, u); + EVP_PKEY_free(k); + return ret; + } + else + return PEM_ASN1_write_bio((i2d_of_void *)i2d_RSAPrivateKey, + PEM_STRING_RSA,bp,x,enc,kstr,klen,cb,u); +} + +#ifndef OPENSSL_NO_FP_API +int PEM_write_RSAPrivateKey(FILE *fp, RSA *x, const EVP_CIPHER *enc, + unsigned char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + if (FIPS_mode()) + { + EVP_PKEY *k; + int ret; + k = EVP_PKEY_new(); + if (!k) + return 0; + + EVP_PKEY_set1_RSA(k, x); + + ret = PEM_write_PrivateKey(fp, k, enc, kstr, klen, cb, u); + EVP_PKEY_free(k); + return ret; + } + else + return PEM_ASN1_write((i2d_of_void *)i2d_RSAPrivateKey, + PEM_STRING_RSA,fp,x,enc,kstr,klen,cb,u); +} +#endif + +#else + IMPLEMENT_PEM_write_cb_const(RSAPrivateKey, RSA, PEM_STRING_RSA, RSAPrivateKey) + +#endif + IMPLEMENT_PEM_rw_const(RSAPublicKey, RSA, PEM_STRING_RSA_PUBLIC, RSAPublicKey) IMPLEMENT_PEM_rw(RSA_PUBKEY, RSA, PEM_STRING_PUBLIC, RSA_PUBKEY) @@ -223,7 +277,59 @@ DSA *PEM_read_bio_DSAPrivateKey(BIO *bp, DSA **dsa, pem_password_cb *cb, return pkey_get_dsa(pktmp, dsa); /* will free pktmp */ } +#ifdef OPENSSL_FIPS + +int PEM_write_bio_DSAPrivateKey(BIO *bp, DSA *x, const EVP_CIPHER *enc, + unsigned char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + if (FIPS_mode()) + { + EVP_PKEY *k; + int ret; + k = EVP_PKEY_new(); + if (!k) + return 0; + EVP_PKEY_set1_DSA(k, x); + + ret = PEM_write_bio_PrivateKey(bp, k, enc, kstr, klen, cb, u); + EVP_PKEY_free(k); + return ret; + } + else + return PEM_ASN1_write_bio((i2d_of_void *)i2d_DSAPrivateKey, + PEM_STRING_DSA,bp,x,enc,kstr,klen,cb,u); +} + +#ifndef OPENSSL_NO_FP_API +int PEM_write_DSAPrivateKey(FILE *fp, DSA *x, const EVP_CIPHER *enc, + unsigned char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + if (FIPS_mode()) + { + EVP_PKEY *k; + int ret; + k = EVP_PKEY_new(); + if (!k) + return 0; + EVP_PKEY_set1_DSA(k, x); + ret = PEM_write_PrivateKey(fp, k, enc, kstr, klen, cb, u); + EVP_PKEY_free(k); + return ret; + } + else + return PEM_ASN1_write((i2d_of_void *)i2d_DSAPrivateKey, + PEM_STRING_DSA,fp,x,enc,kstr,klen,cb,u); +} +#endif + +#else + IMPLEMENT_PEM_write_cb_const(DSAPrivateKey, DSA, PEM_STRING_DSA, DSAPrivateKey) + +#endif + IMPLEMENT_PEM_rw(DSA_PUBKEY, DSA, PEM_STRING_PUBLIC, DSA_PUBKEY) #ifndef OPENSSL_NO_FP_API @@ -269,8 +375,63 @@ EC_KEY *PEM_read_bio_ECPrivateKey(BIO *bp, EC_KEY **key, pem_password_cb *cb, IMPLEMENT_PEM_rw_const(ECPKParameters, EC_GROUP, PEM_STRING_ECPARAMETERS, ECPKParameters) + + +#ifdef OPENSSL_FIPS + +int PEM_write_bio_ECPrivateKey(BIO *bp, EC_KEY *x, const EVP_CIPHER *enc, + unsigned char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + if (FIPS_mode()) + { + EVP_PKEY *k; + int ret; + k = EVP_PKEY_new(); + if (!k) + return 0; + EVP_PKEY_set1_EC_KEY(k, x); + + ret = PEM_write_bio_PrivateKey(bp, k, enc, kstr, klen, cb, u); + EVP_PKEY_free(k); + return ret; + } + else + return PEM_ASN1_write_bio((i2d_of_void *)i2d_ECPrivateKey, + PEM_STRING_ECPRIVATEKEY, + bp,x,enc,kstr,klen,cb,u); +} + +#ifndef OPENSSL_NO_FP_API +int PEM_write_ECPrivateKey(FILE *fp, EC_KEY *x, const EVP_CIPHER *enc, + unsigned char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + if (FIPS_mode()) + { + EVP_PKEY *k; + int ret; + k = EVP_PKEY_new(); + if (!k) + return 0; + EVP_PKEY_set1_EC_KEY(k, x); + ret = PEM_write_PrivateKey(fp, k, enc, kstr, klen, cb, u); + EVP_PKEY_free(k); + return ret; + } + else + return PEM_ASN1_write((i2d_of_void *)i2d_ECPrivateKey, + PEM_STRING_ECPRIVATEKEY, + fp,x,enc,kstr,klen,cb,u); +} +#endif + +#else + IMPLEMENT_PEM_write_cb(ECPrivateKey, EC_KEY, PEM_STRING_ECPRIVATEKEY, ECPrivateKey) +#endif + IMPLEMENT_PEM_rw(EC_PUBKEY, EC_KEY, PEM_STRING_PUBLIC, EC_PUBKEY) #ifndef OPENSSL_NO_FP_API diff --git a/crypto/pem/pem_lib.c b/crypto/pem/pem_lib.c index cfc89a99215..5a421fc4b6a 100644 --- a/crypto/pem/pem_lib.c +++ b/crypto/pem/pem_lib.c @@ -394,7 +394,8 @@ int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp, goto err; /* The 'iv' is used as the iv and as a salt. It is * NOT taken from the BytesToKey function */ - EVP_BytesToKey(enc,EVP_md5(),iv,kstr,klen,1,key,NULL); + if (!EVP_BytesToKey(enc,EVP_md5(),iv,kstr,klen,1,key,NULL)) + goto err; if (kstr == (unsigned char *)buf) OPENSSL_cleanse(buf,PEM_BUFSIZE); @@ -406,12 +407,15 @@ int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp, /* k=strlen(buf); */ EVP_CIPHER_CTX_init(&ctx); - EVP_EncryptInit_ex(&ctx,enc,NULL,key,iv); - EVP_EncryptUpdate(&ctx,data,&j,data,i); - EVP_EncryptFinal_ex(&ctx,&(data[j]),&i); + ret = 1; + if (!EVP_EncryptInit_ex(&ctx,enc,NULL,key,iv) + || !EVP_EncryptUpdate(&ctx,data,&j,data,i) + || !EVP_EncryptFinal_ex(&ctx,&(data[j]),&i)) + ret = 0; EVP_CIPHER_CTX_cleanup(&ctx); + if (ret == 0) + goto err; i+=j; - ret=1; } else { @@ -459,14 +463,17 @@ int PEM_do_header(EVP_CIPHER_INFO *cipher, unsigned char *data, long *plen, ebcdic2ascii(buf, buf, klen); #endif - EVP_BytesToKey(cipher->cipher,EVP_md5(),&(cipher->iv[0]), - (unsigned char *)buf,klen,1,key,NULL); + if (!EVP_BytesToKey(cipher->cipher,EVP_md5(),&(cipher->iv[0]), + (unsigned char *)buf,klen,1,key,NULL)) + return 0; j=(int)len; EVP_CIPHER_CTX_init(&ctx); - EVP_DecryptInit_ex(&ctx,cipher->cipher,NULL, key,&(cipher->iv[0])); - EVP_DecryptUpdate(&ctx,data,&i,data,j); - o=EVP_DecryptFinal_ex(&ctx,&(data[i]),&j); + o = EVP_DecryptInit_ex(&ctx,cipher->cipher,NULL, key,&(cipher->iv[0])); + if (o) + o = EVP_DecryptUpdate(&ctx,data,&i,data,j); + if (o) + o = EVP_DecryptFinal_ex(&ctx,&(data[i]),&j); EVP_CIPHER_CTX_cleanup(&ctx); OPENSSL_cleanse((char *)buf,sizeof(buf)); OPENSSL_cleanse((char *)key,sizeof(key)); diff --git a/crypto/pem/pem_seal.c b/crypto/pem/pem_seal.c index 59690b56aee..b6b4e13498e 100644 --- a/crypto/pem/pem_seal.c +++ b/crypto/pem/pem_seal.c @@ -96,7 +96,8 @@ int PEM_SealInit(PEM_ENCODE_SEAL_CTX *ctx, EVP_CIPHER *type, EVP_MD *md_type, EVP_EncodeInit(&ctx->encode); EVP_MD_CTX_init(&ctx->md); - EVP_SignInit(&ctx->md,md_type); + if (!EVP_SignInit(&ctx->md,md_type)) + goto err; EVP_CIPHER_CTX_init(&ctx->cipher); ret=EVP_SealInit(&ctx->cipher,type,ek,ekl,iv,pubk,npubk); @@ -163,7 +164,8 @@ int PEM_SealFinal(PEM_ENCODE_SEAL_CTX *ctx, unsigned char *sig, int *sigl, goto err; } - EVP_EncryptFinal_ex(&ctx->cipher,s,(int *)&i); + if (!EVP_EncryptFinal_ex(&ctx->cipher,s,(int *)&i)) + goto err; EVP_EncodeUpdate(&ctx->encode,out,&j,s,i); *outl=j; out+=j; diff --git a/crypto/perlasm/cbc.pl b/crypto/perlasm/cbc.pl index 6fc2510905b..24561e759ab 100644 --- a/crypto/perlasm/cbc.pl +++ b/crypto/perlasm/cbc.pl @@ -150,7 +150,7 @@ sub cbc &set_label("PIC_point"); &blindpop("edx"); &lea("ecx",&DWP(&label("cbc_enc_jmp_table")."-".&label("PIC_point"),"edx")); - &mov($count,&DWP(0,"ecx",$count,4)) + &mov($count,&DWP(0,"ecx",$count,4)); &add($count,"edx"); &xor("ecx","ecx"); &xor("edx","edx"); diff --git a/crypto/perlasm/x86masm.pl b/crypto/perlasm/x86masm.pl index 96b1b73e1a3..f937d07c87d 100755 --- a/crypto/perlasm/x86masm.pl +++ b/crypto/perlasm/x86masm.pl @@ -33,6 +33,7 @@ sub ::generic sub ::call { &::emit("call",(&::islabel($_[0]) or "$nmdecor$_[0]")); } sub ::call_ptr { &::emit("call",@_); } sub ::jmp_ptr { &::emit("jmp",@_); } +sub ::lock { &::data_byte(0xf0); } sub get_mem { my($size,$addr,$reg1,$reg2,$idx)=@_; diff --git a/crypto/pkcs12/p12_key.c b/crypto/pkcs12/p12_key.c index c55c7b60b34..61d58502fd1 100644 --- a/crypto/pkcs12/p12_key.c +++ b/crypto/pkcs12/p12_key.c @@ -176,24 +176,32 @@ int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt, out += u; for (j = 0; j < v; j++) B[j] = Ai[j % u]; /* Work out B + 1 first then can use B as tmp space */ - if (!BN_bin2bn (B, v, Bpl1)) goto err; - if (!BN_add_word (Bpl1, 1)) goto err; + if (!BN_bin2bn (B, v, Bpl1)) + goto err; + if (!BN_add_word (Bpl1, 1)) + goto err; for (j = 0; j < Ilen ; j+=v) { - if (!BN_bin2bn (I + j, v, Ij)) goto err; - if (!BN_add (Ij, Ij, Bpl1)) goto err; - BN_bn2bin (Ij, B); + if (!BN_bin2bn(I + j, v, Ij)) + goto err; + if (!BN_add(Ij, Ij, Bpl1)) + goto err; + if (!BN_bn2bin(Ij, B)) + goto err; Ijlen = BN_num_bytes (Ij); /* If more than 2^(v*8) - 1 cut off MSB */ if (Ijlen > v) { - BN_bn2bin (Ij, B); + if (!BN_bn2bin (Ij, B)) + goto err; memcpy (I + j, B + 1, v); #ifndef PKCS12_BROKEN_KEYGEN /* If less than v bytes pad with zeroes */ } else if (Ijlen < v) { memset(I + j, 0, v - Ijlen); - BN_bn2bin(Ij, I + j + v - Ijlen); + if (!BN_bn2bin(Ij, I + j + v - Ijlen)) + goto err; #endif - } else BN_bn2bin (Ij, I + j); + } else if (!BN_bn2bin (Ij, I + j)) + goto err; } } diff --git a/crypto/pkcs7/bio_pk7.c b/crypto/pkcs7/bio_pk7.c index c8d06d6cdc8..0fd31e730ff 100644 --- a/crypto/pkcs7/bio_pk7.c +++ b/crypto/pkcs7/bio_pk7.c @@ -56,7 +56,7 @@ #include #include -#ifndef OPENSSL_SYSNAME_NETWARE +#if !defined(OPENSSL_SYSNAME_NETWARE) && !defined(OPENSSL_SYSNAME_VXWORKS) #include #endif #include diff --git a/crypto/ppccap.c b/crypto/ppccap.c index ab89ccaa12c..f71ba66aa38 100644 --- a/crypto/ppccap.c +++ b/crypto/ppccap.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -53,6 +54,7 @@ static sigjmp_buf ill_jmp; static void ill_handler (int sig) { siglongjmp(ill_jmp,sig); } void OPENSSL_ppc64_probe(void); +void OPENSSL_altivec_probe(void); void OPENSSL_cpuid_setup(void) { @@ -82,6 +84,15 @@ void OPENSSL_cpuid_setup(void) OPENSSL_ppccap_P = 0; +#if defined(_AIX) + if (sizeof(size_t)==4 +# if defined(_SC_AIX_KERNEL_BITMODE) + && sysconf(_SC_AIX_KERNEL_BITMODE)!=64 +# endif + ) + return; +#endif + memset(&ill_act,0,sizeof(ill_act)); ill_act.sa_handler = ill_handler; ill_act.sa_mask = all_masked; diff --git a/crypto/rand/md_rand.c b/crypto/rand/md_rand.c index fcdd3f2a845..1e3bcb9bc42 100644 --- a/crypto/rand/md_rand.c +++ b/crypto/rand/md_rand.c @@ -123,10 +123,10 @@ #include "e_os.h" +#include #include #include "rand_lcl.h" -#include #include #ifdef BN_DEBUG diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c index daf1dab9739..476a0cd187e 100644 --- a/crypto/rand/rand_lib.c +++ b/crypto/rand/rand_lib.c @@ -210,8 +210,11 @@ static size_t drbg_get_entropy(DRBG_CTX *ctx, unsigned char **pout, static void drbg_free_entropy(DRBG_CTX *ctx, unsigned char *out, size_t olen) { - OPENSSL_cleanse(out, olen); - OPENSSL_free(out); + if (out) + { + OPENSSL_cleanse(out, olen); + OPENSSL_free(out); + } } /* Set "additional input" when generating random data. This uses the diff --git a/crypto/rand/randfile.c b/crypto/rand/randfile.c index 030e07f4182..7f1428072d2 100644 --- a/crypto/rand/randfile.c +++ b/crypto/rand/randfile.c @@ -57,7 +57,9 @@ */ /* We need to define this to get macros like S_IFBLK and S_IFCHR */ +#if !defined(OPENSSL_SYS_VXWORKS) #define _XOPEN_SOURCE 500 +#endif #include #include diff --git a/crypto/rc4/asm/rc4-md5-x86_64.pl b/crypto/rc4/asm/rc4-md5-x86_64.pl index 7f684092d40..272fa91e1a1 100755 --- a/crypto/rc4/asm/rc4-md5-x86_64.pl +++ b/crypto/rc4/asm/rc4-md5-x86_64.pl @@ -51,7 +51,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; my $dir=$1; my $xlate; ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or die "can't locate x86_64-xlate.pl"; -open STDOUT,"| $^X $xlate $flavour $output"; +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; my ($dat,$in0,$out,$ctx,$inp,$len, $func,$nargs); diff --git a/crypto/rc4/asm/rc4-x86_64.pl b/crypto/rc4/asm/rc4-x86_64.pl index d6eac205e98..75750dbf334 100755 --- a/crypto/rc4/asm/rc4-x86_64.pl +++ b/crypto/rc4/asm/rc4-x86_64.pl @@ -112,7 +112,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or die "can't locate x86_64-xlate.pl"; -open STDOUT,"| $^X $xlate $flavour $output"; +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; $dat="%rdi"; # arg1 $len="%rsi"; # arg2 diff --git a/crypto/ripemd/rmd_dgst.c b/crypto/ripemd/rmd_dgst.c index 63f0d983f7b..d8e72da51bf 100644 --- a/crypto/ripemd/rmd_dgst.c +++ b/crypto/ripemd/rmd_dgst.c @@ -105,21 +105,21 @@ void ripemd160_block_data_order (RIPEMD160_CTX *ctx, const void *p, size_t num) A=ctx->A; B=ctx->B; C=ctx->C; D=ctx->D; E=ctx->E; - HOST_c2l(data,l); X( 0)=l; HOST_c2l(data,l); X( 1)=l; - RIP1(A,B,C,D,E,WL00,SL00); HOST_c2l(data,l); X( 2)=l; - RIP1(E,A,B,C,D,WL01,SL01); HOST_c2l(data,l); X( 3)=l; - RIP1(D,E,A,B,C,WL02,SL02); HOST_c2l(data,l); X( 4)=l; - RIP1(C,D,E,A,B,WL03,SL03); HOST_c2l(data,l); X( 5)=l; - RIP1(B,C,D,E,A,WL04,SL04); HOST_c2l(data,l); X( 6)=l; - RIP1(A,B,C,D,E,WL05,SL05); HOST_c2l(data,l); X( 7)=l; - RIP1(E,A,B,C,D,WL06,SL06); HOST_c2l(data,l); X( 8)=l; - RIP1(D,E,A,B,C,WL07,SL07); HOST_c2l(data,l); X( 9)=l; - RIP1(C,D,E,A,B,WL08,SL08); HOST_c2l(data,l); X(10)=l; - RIP1(B,C,D,E,A,WL09,SL09); HOST_c2l(data,l); X(11)=l; - RIP1(A,B,C,D,E,WL10,SL10); HOST_c2l(data,l); X(12)=l; - RIP1(E,A,B,C,D,WL11,SL11); HOST_c2l(data,l); X(13)=l; - RIP1(D,E,A,B,C,WL12,SL12); HOST_c2l(data,l); X(14)=l; - RIP1(C,D,E,A,B,WL13,SL13); HOST_c2l(data,l); X(15)=l; + (void)HOST_c2l(data,l); X( 0)=l;(void)HOST_c2l(data,l); X( 1)=l; + RIP1(A,B,C,D,E,WL00,SL00); (void)HOST_c2l(data,l); X( 2)=l; + RIP1(E,A,B,C,D,WL01,SL01); (void)HOST_c2l(data,l); X( 3)=l; + RIP1(D,E,A,B,C,WL02,SL02); (void)HOST_c2l(data,l); X( 4)=l; + RIP1(C,D,E,A,B,WL03,SL03); (void)HOST_c2l(data,l); X( 5)=l; + RIP1(B,C,D,E,A,WL04,SL04); (void)HOST_c2l(data,l); X( 6)=l; + RIP1(A,B,C,D,E,WL05,SL05); (void)HOST_c2l(data,l); X( 7)=l; + RIP1(E,A,B,C,D,WL06,SL06); (void)HOST_c2l(data,l); X( 8)=l; + RIP1(D,E,A,B,C,WL07,SL07); (void)HOST_c2l(data,l); X( 9)=l; + RIP1(C,D,E,A,B,WL08,SL08); (void)HOST_c2l(data,l); X(10)=l; + RIP1(B,C,D,E,A,WL09,SL09); (void)HOST_c2l(data,l); X(11)=l; + RIP1(A,B,C,D,E,WL10,SL10); (void)HOST_c2l(data,l); X(12)=l; + RIP1(E,A,B,C,D,WL11,SL11); (void)HOST_c2l(data,l); X(13)=l; + RIP1(D,E,A,B,C,WL12,SL12); (void)HOST_c2l(data,l); X(14)=l; + RIP1(C,D,E,A,B,WL13,SL13); (void)HOST_c2l(data,l); X(15)=l; RIP1(B,C,D,E,A,WL14,SL14); RIP1(A,B,C,D,E,WL15,SL15); diff --git a/crypto/ripemd/rmd_locl.h b/crypto/ripemd/rmd_locl.h index f14b346e662..2bd8957d143 100644 --- a/crypto/ripemd/rmd_locl.h +++ b/crypto/ripemd/rmd_locl.h @@ -88,11 +88,11 @@ void ripemd160_block_data_order (RIPEMD160_CTX *c, const void *p,size_t num); #define HASH_FINAL RIPEMD160_Final #define HASH_MAKE_STRING(c,s) do { \ unsigned long ll; \ - ll=(c)->A; HOST_l2c(ll,(s)); \ - ll=(c)->B; HOST_l2c(ll,(s)); \ - ll=(c)->C; HOST_l2c(ll,(s)); \ - ll=(c)->D; HOST_l2c(ll,(s)); \ - ll=(c)->E; HOST_l2c(ll,(s)); \ + ll=(c)->A; (void)HOST_l2c(ll,(s)); \ + ll=(c)->B; (void)HOST_l2c(ll,(s)); \ + ll=(c)->C; (void)HOST_l2c(ll,(s)); \ + ll=(c)->D; (void)HOST_l2c(ll,(s)); \ + ll=(c)->E; (void)HOST_l2c(ll,(s)); \ } while (0) #define HASH_BLOCK_DATA_ORDER ripemd160_block_data_order diff --git a/crypto/rsa/rsa.h b/crypto/rsa/rsa.h index 4814a2fc15e..5f269e577af 100644 --- a/crypto/rsa/rsa.h +++ b/crypto/rsa/rsa.h @@ -280,7 +280,7 @@ struct rsa_st RSA * RSA_new(void); RSA * RSA_new_method(ENGINE *engine); -int RSA_size(const RSA *); +int RSA_size(const RSA *rsa); /* Deprecated version */ #ifndef OPENSSL_NO_DEPRECATED diff --git a/crypto/rsa/rsa_eay.c b/crypto/rsa/rsa_eay.c index 2e1ddd48d35..88ee2cb557f 100644 --- a/crypto/rsa/rsa_eay.c +++ b/crypto/rsa/rsa_eay.c @@ -847,12 +847,12 @@ static int RSA_eay_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) if (!BN_mod(r0,pr1,rsa->p,ctx)) goto err; /* If p < q it is occasionally possible for the correction of - * adding 'p' if r0 is negative above to leave the result still + * adding 'p' if r0 is negative above to leave the result still * negative. This can break the private key operations: the following * second correction should *always* correct this rare occurrence. * This will *never* happen with OpenSSL generated keys because - * they ensure p > q [steve] - */ + * they ensure p > q [steve] + */ if (BN_is_negative(r0)) if (!BN_add(r0,r0,rsa->p)) goto err; if (!BN_mul(r1,r0,rsa->q,ctx)) goto err; diff --git a/crypto/rsa/rsa_oaep.c b/crypto/rsa/rsa_oaep.c index 553d212ebe9..af4d24a56ef 100644 --- a/crypto/rsa/rsa_oaep.c +++ b/crypto/rsa/rsa_oaep.c @@ -149,7 +149,7 @@ int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen, if (!EVP_Digest((void *)param, plen, phash, NULL, EVP_sha1(), NULL)) return -1; - if (memcmp(db, phash, SHA_DIGEST_LENGTH) != 0 || bad) + if (CRYPTO_memcmp(db, phash, SHA_DIGEST_LENGTH) != 0 || bad) goto decoding_err; else { diff --git a/crypto/sha/asm/sha1-armv4-large.pl b/crypto/sha/asm/sha1-armv4-large.pl index fe8207f77f8..33da3e0e3c0 100755 --- a/crypto/sha/asm/sha1-armv4-large.pl +++ b/crypto/sha/asm/sha1-armv4-large.pl @@ -177,6 +177,7 @@ for($i=0;$i<5;$i++) { $code.=<<___; teq $Xi,sp bne .L_00_15 @ [((11+4)*5+2)*3] + sub sp,sp,#25*4 ___ &BODY_00_15(@V); unshift(@V,pop(@V)); &BODY_16_19(@V); unshift(@V,pop(@V)); @@ -186,7 +187,6 @@ ___ $code.=<<___; ldr $K,.LK_20_39 @ [+15+16*4] - sub sp,sp,#25*4 cmn sp,#0 @ [+3], clear carry to denote 20_39 .L_20_39_or_60_79: ___ diff --git a/crypto/sha/asm/sha1-ia64.pl b/crypto/sha/asm/sha1-ia64.pl index db28f0805a1..02d35d1614c 100644 --- a/crypto/sha/asm/sha1-ia64.pl +++ b/crypto/sha/asm/sha1-ia64.pl @@ -271,7 +271,8 @@ tmp6=loc13; ___ -{ my $i,@V=($A,$B,$C,$D,$E); +{ my $i; + my @V=($A,$B,$C,$D,$E); for($i=0;$i<16;$i++) { &BODY_00_15(\$code,$i,@V); unshift(@V,pop(@V)); } for(;$i<20;$i++) { &BODY_16_19(\$code,$i,@V); unshift(@V,pop(@V)); } diff --git a/crypto/sha/asm/sha1-sparcv9a.pl b/crypto/sha/asm/sha1-sparcv9a.pl index 85e8d68086b..e65291bbd97 100755 --- a/crypto/sha/asm/sha1-sparcv9a.pl +++ b/crypto/sha/asm/sha1-sparcv9a.pl @@ -549,7 +549,7 @@ ___ # programmer detect if current CPU is VIS capable at run-time. sub unvis { my ($mnemonic,$rs1,$rs2,$rd)=@_; -my $ref,$opf; +my ($ref,$opf); my %visopf = ( "fmul8ulx16" => 0x037, "faligndata" => 0x048, "fpadd32" => 0x052, diff --git a/crypto/sha/asm/sha1-x86_64.pl b/crypto/sha/asm/sha1-x86_64.pl index f27c1e3fb03..cfdc45cce6d 100755 --- a/crypto/sha/asm/sha1-x86_64.pl +++ b/crypto/sha/asm/sha1-x86_64.pl @@ -82,7 +82,8 @@ $avx=1 if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) && `ml64 2>&1` =~ /Version ([0-9]+)\./ && $1>=10); -open STDOUT,"| $^X $xlate $flavour $output"; +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; $ctx="%rdi"; # 1st arg $inp="%rsi"; # 2nd arg diff --git a/crypto/sha/asm/sha512-586.pl b/crypto/sha/asm/sha512-586.pl index 5b9f3337add..7eab6a5b88b 100755 --- a/crypto/sha/asm/sha512-586.pl +++ b/crypto/sha/asm/sha512-586.pl @@ -142,9 +142,9 @@ sub BODY_00_15_x86 { &mov ("edx",$Ehi); &mov ("esi","ecx"); - &shr ("ecx",9) # lo>>9 + &shr ("ecx",9); # lo>>9 &mov ("edi","edx"); - &shr ("edx",9) # hi>>9 + &shr ("edx",9); # hi>>9 &mov ("ebx","ecx"); &shl ("esi",14); # lo<<14 &mov ("eax","edx"); @@ -207,9 +207,9 @@ sub BODY_00_15_x86 { &mov ($Dhi,"ebx"); &mov ("esi","ecx"); - &shr ("ecx",2) # lo>>2 + &shr ("ecx",2); # lo>>2 &mov ("edi","edx"); - &shr ("edx",2) # hi>>2 + &shr ("edx",2); # hi>>2 &mov ("ebx","ecx"); &shl ("esi",4); # lo<<4 &mov ("eax","edx"); @@ -452,9 +452,9 @@ if ($sse2) { &mov ("edx",&DWP(8*(9+15+16-1)+4,"esp")); &mov ("esi","ecx"); - &shr ("ecx",1) # lo>>1 + &shr ("ecx",1); # lo>>1 &mov ("edi","edx"); - &shr ("edx",1) # hi>>1 + &shr ("edx",1); # hi>>1 &mov ("eax","ecx"); &shl ("esi",24); # lo<<24 &mov ("ebx","edx"); @@ -488,9 +488,9 @@ if ($sse2) { &mov ("edx",&DWP(8*(9+15+16-14)+4,"esp")); &mov ("esi","ecx"); - &shr ("ecx",6) # lo>>6 + &shr ("ecx",6); # lo>>6 &mov ("edi","edx"); - &shr ("edx",6) # hi>>6 + &shr ("edx",6); # hi>>6 &mov ("eax","ecx"); &shl ("esi",3); # lo<<3 &mov ("ebx","edx"); diff --git a/crypto/sha/asm/sha512-x86_64.pl b/crypto/sha/asm/sha512-x86_64.pl index f611a2d898e..8d516785578 100755 --- a/crypto/sha/asm/sha512-x86_64.pl +++ b/crypto/sha/asm/sha512-x86_64.pl @@ -51,7 +51,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or die "can't locate x86_64-xlate.pl"; -open STDOUT,"| $^X $xlate $flavour $output"; +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; if ($output =~ /512/) { $func="sha512_block_data_order"; diff --git a/crypto/sha/sha1_one.c b/crypto/sha/sha1_one.c index 7c65b60276c..c56ec94020e 100644 --- a/crypto/sha/sha1_one.c +++ b/crypto/sha/sha1_one.c @@ -58,8 +58,8 @@ #include #include -#include #include +#include #ifndef OPENSSL_NO_SHA1 unsigned char *SHA1(const unsigned char *d, size_t n, unsigned char *md) diff --git a/crypto/sha/sha1dgst.c b/crypto/sha/sha1dgst.c index 81219af0883..a98690225fd 100644 --- a/crypto/sha/sha1dgst.c +++ b/crypto/sha/sha1dgst.c @@ -56,8 +56,8 @@ * [including the GNU Public Licence.] */ -#include #include +#include #if !defined(OPENSSL_NO_SHA1) && !defined(OPENSSL_NO_SHA) #undef SHA_0 diff --git a/crypto/sha/sha256.c b/crypto/sha/sha256.c index f88d3d6dadb..4eae0748491 100644 --- a/crypto/sha/sha256.c +++ b/crypto/sha/sha256.c @@ -88,17 +88,17 @@ int SHA224_Final (unsigned char *md, SHA256_CTX *c) switch ((c)->md_len) \ { case SHA224_DIGEST_LENGTH: \ for (nn=0;nnh[nn]; HOST_l2c(ll,(s)); } \ + { ll=(c)->h[nn]; (void)HOST_l2c(ll,(s)); } \ break; \ case SHA256_DIGEST_LENGTH: \ for (nn=0;nnh[nn]; HOST_l2c(ll,(s)); } \ + { ll=(c)->h[nn]; (void)HOST_l2c(ll,(s)); } \ break; \ default: \ if ((c)->md_len > SHA256_DIGEST_LENGTH) \ return 0; \ for (nn=0;nn<(c)->md_len/4;nn++) \ - { ll=(c)->h[nn]; HOST_l2c(ll,(s)); } \ + { ll=(c)->h[nn]; (void)HOST_l2c(ll,(s)); } \ break; \ } \ } while (0) diff --git a/crypto/sha/sha_dgst.c b/crypto/sha/sha_dgst.c index c946ad827d5..fb63b17ff2c 100644 --- a/crypto/sha/sha_dgst.c +++ b/crypto/sha/sha_dgst.c @@ -56,8 +56,8 @@ * [including the GNU Public Licence.] */ -#include #include +#include #if !defined(OPENSSL_NO_SHA0) && !defined(OPENSSL_NO_SHA) #undef SHA_1 diff --git a/crypto/sha/sha_locl.h b/crypto/sha/sha_locl.h index 7a0c3ca8d8c..d673255f78b 100644 --- a/crypto/sha/sha_locl.h +++ b/crypto/sha/sha_locl.h @@ -69,11 +69,11 @@ #define HASH_CBLOCK SHA_CBLOCK #define HASH_MAKE_STRING(c,s) do { \ unsigned long ll; \ - ll=(c)->h0; HOST_l2c(ll,(s)); \ - ll=(c)->h1; HOST_l2c(ll,(s)); \ - ll=(c)->h2; HOST_l2c(ll,(s)); \ - ll=(c)->h3; HOST_l2c(ll,(s)); \ - ll=(c)->h4; HOST_l2c(ll,(s)); \ + ll=(c)->h0; (void)HOST_l2c(ll,(s)); \ + ll=(c)->h1; (void)HOST_l2c(ll,(s)); \ + ll=(c)->h2; (void)HOST_l2c(ll,(s)); \ + ll=(c)->h3; (void)HOST_l2c(ll,(s)); \ + ll=(c)->h4; (void)HOST_l2c(ll,(s)); \ } while (0) #if defined(SHA_0) @@ -256,21 +256,21 @@ static void HASH_BLOCK_DATA_ORDER (SHA_CTX *c, const void *p, size_t num) } else { - HOST_c2l(data,l); X( 0)=l; HOST_c2l(data,l); X( 1)=l; - BODY_00_15( 0,A,B,C,D,E,T,X( 0)); HOST_c2l(data,l); X( 2)=l; - BODY_00_15( 1,T,A,B,C,D,E,X( 1)); HOST_c2l(data,l); X( 3)=l; - BODY_00_15( 2,E,T,A,B,C,D,X( 2)); HOST_c2l(data,l); X( 4)=l; - BODY_00_15( 3,D,E,T,A,B,C,X( 3)); HOST_c2l(data,l); X( 5)=l; - BODY_00_15( 4,C,D,E,T,A,B,X( 4)); HOST_c2l(data,l); X( 6)=l; - BODY_00_15( 5,B,C,D,E,T,A,X( 5)); HOST_c2l(data,l); X( 7)=l; - BODY_00_15( 6,A,B,C,D,E,T,X( 6)); HOST_c2l(data,l); X( 8)=l; - BODY_00_15( 7,T,A,B,C,D,E,X( 7)); HOST_c2l(data,l); X( 9)=l; - BODY_00_15( 8,E,T,A,B,C,D,X( 8)); HOST_c2l(data,l); X(10)=l; - BODY_00_15( 9,D,E,T,A,B,C,X( 9)); HOST_c2l(data,l); X(11)=l; - BODY_00_15(10,C,D,E,T,A,B,X(10)); HOST_c2l(data,l); X(12)=l; - BODY_00_15(11,B,C,D,E,T,A,X(11)); HOST_c2l(data,l); X(13)=l; - BODY_00_15(12,A,B,C,D,E,T,X(12)); HOST_c2l(data,l); X(14)=l; - BODY_00_15(13,T,A,B,C,D,E,X(13)); HOST_c2l(data,l); X(15)=l; + (void)HOST_c2l(data,l); X( 0)=l; (void)HOST_c2l(data,l); X( 1)=l; + BODY_00_15( 0,A,B,C,D,E,T,X( 0)); (void)HOST_c2l(data,l); X( 2)=l; + BODY_00_15( 1,T,A,B,C,D,E,X( 1)); (void)HOST_c2l(data,l); X( 3)=l; + BODY_00_15( 2,E,T,A,B,C,D,X( 2)); (void)HOST_c2l(data,l); X( 4)=l; + BODY_00_15( 3,D,E,T,A,B,C,X( 3)); (void)HOST_c2l(data,l); X( 5)=l; + BODY_00_15( 4,C,D,E,T,A,B,X( 4)); (void)HOST_c2l(data,l); X( 6)=l; + BODY_00_15( 5,B,C,D,E,T,A,X( 5)); (void)HOST_c2l(data,l); X( 7)=l; + BODY_00_15( 6,A,B,C,D,E,T,X( 6)); (void)HOST_c2l(data,l); X( 8)=l; + BODY_00_15( 7,T,A,B,C,D,E,X( 7)); (void)HOST_c2l(data,l); X( 9)=l; + BODY_00_15( 8,E,T,A,B,C,D,X( 8)); (void)HOST_c2l(data,l); X(10)=l; + BODY_00_15( 9,D,E,T,A,B,C,X( 9)); (void)HOST_c2l(data,l); X(11)=l; + BODY_00_15(10,C,D,E,T,A,B,X(10)); (void)HOST_c2l(data,l); X(12)=l; + BODY_00_15(11,B,C,D,E,T,A,X(11)); (void)HOST_c2l(data,l); X(13)=l; + BODY_00_15(12,A,B,C,D,E,T,X(12)); (void)HOST_c2l(data,l); X(14)=l; + BODY_00_15(13,T,A,B,C,D,E,X(13)); (void)HOST_c2l(data,l); X(15)=l; BODY_00_15(14,E,T,A,B,C,D,X(14)); BODY_00_15(15,D,E,T,A,B,C,X(15)); } diff --git a/crypto/sparccpuid.S b/crypto/sparccpuid.S index ae61f7f5ced..0cc247e4897 100644 --- a/crypto/sparccpuid.S +++ b/crypto/sparccpuid.S @@ -235,10 +235,10 @@ _sparcv9_rdtick: .global _sparcv9_vis1_probe .align 8 _sparcv9_vis1_probe: - .word 0x81b00d80 !fxor %f0,%f0,%f0 add %sp,BIAS+2,%o1 - retl .word 0xc19a5a40 !ldda [%o1]ASI_FP16_P,%f0 + retl + .word 0x81b00d80 !fxor %f0,%f0,%f0 .type _sparcv9_vis1_probe,#function .size _sparcv9_vis1_probe,.-_sparcv9_vis1_probe diff --git a/crypto/srp/srp_vfy.c b/crypto/srp/srp_vfy.c index c8be907d7f7..4a3d13edf6c 100644 --- a/crypto/srp/srp_vfy.c +++ b/crypto/srp/srp_vfy.c @@ -390,7 +390,7 @@ int SRP_VBASE_init(SRP_VBASE *vb, char *verifier_file) } for (i = 0; i < sk_OPENSSL_PSTRING_num(tmpdb->data); i++) { - pp = (char **)sk_OPENSSL_PSTRING_value(tmpdb->data,i); + pp = sk_OPENSSL_PSTRING_value(tmpdb->data,i); if (pp[DB_srptype][0] == DB_SRP_INDEX) { /*we add this couple in the internal Stack */ @@ -581,7 +581,8 @@ char *SRP_create_verifier(const char *user, const char *pass, char **salt, if (*salt == NULL) { char *tmp_salt; - if ((tmp_salt = (char *)OPENSSL_malloc(SRP_RANDOM_SALT_LEN * 2)) == NULL) + + if ((tmp_salt = OPENSSL_malloc(SRP_RANDOM_SALT_LEN * 2)) == NULL) { OPENSSL_free(vf); goto err; diff --git a/crypto/symhacks.h b/crypto/symhacks.h index 403f592dcd6..07a412f8458 100644 --- a/crypto/symhacks.h +++ b/crypto/symhacks.h @@ -193,17 +193,17 @@ #undef SSL_CTX_set_srp_username_callback #define SSL_CTX_set_srp_username_callback SSL_CTX_set_srp_un_cb #undef ssl_add_clienthello_use_srtp_ext -#define ssl_add_clienthello_use_srtp_ext ssl_add_clihello_use_srtp_ext +#define ssl_add_clienthello_use_srtp_ext ssl_add_clihello_use_srtp_ext #undef ssl_add_serverhello_use_srtp_ext -#define ssl_add_serverhello_use_srtp_ext ssl_add_serhello_use_srtp_ext +#define ssl_add_serverhello_use_srtp_ext ssl_add_serhello_use_srtp_ext #undef ssl_parse_clienthello_use_srtp_ext -#define ssl_parse_clienthello_use_srtp_ext ssl_parse_clihello_use_srtp_ext +#define ssl_parse_clienthello_use_srtp_ext ssl_parse_clihello_use_srtp_ext #undef ssl_parse_serverhello_use_srtp_ext -#define ssl_parse_serverhello_use_srtp_ext ssl_parse_serhello_use_srtp_ext +#define ssl_parse_serverhello_use_srtp_ext ssl_parse_serhello_use_srtp_ext #undef SSL_CTX_set_next_protos_advertised_cb -#define SSL_CTX_set_next_protos_advertised_cb SSL_CTX_set_next_protos_adv_cb +#define SSL_CTX_set_next_protos_advertised_cb SSL_CTX_set_next_protos_adv_cb #undef SSL_CTX_set_next_proto_select_cb -#define SSL_CTX_set_next_proto_select_cb SSL_CTX_set_next_proto_sel_cb +#define SSL_CTX_set_next_proto_select_cb SSL_CTX_set_next_proto_sel_cb /* Hack some long ENGINE names */ #undef ENGINE_get_default_BN_mod_exp_crt @@ -316,8 +316,6 @@ #define ec_GFp_simple_point_set_to_infinity ec_GFp_simple_pt_set_to_inf #undef ec_GFp_simple_points_make_affine #define ec_GFp_simple_points_make_affine ec_GFp_simple_pts_make_affine -#undef ec_GFp_simple_group_get_curve_GFp -#define ec_GFp_simple_group_get_curve_GFp ec_GFp_simple_grp_get_curve_GFp #undef ec_GFp_simple_set_Jprojective_coordinates_GFp #define ec_GFp_simple_set_Jprojective_coordinates_GFp \ ec_GFp_smp_set_Jproj_coords_GFp diff --git a/crypto/ui/ui_openssl.c b/crypto/ui/ui_openssl.c index 5832a73cf59..a38c7581e6a 100644 --- a/crypto/ui/ui_openssl.c +++ b/crypto/ui/ui_openssl.c @@ -122,9 +122,15 @@ * sigaction and fileno included. -pedantic would be more appropriate for * the intended purposes, but we can't prevent users from adding -ansi. */ +#if defined(OPENSSL_SYSNAME_VXWORKS) +#include +#endif + #if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS) +#ifndef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 2 #endif +#endif #include #include #include diff --git a/crypto/whrlpool/asm/wp-mmx.pl b/crypto/whrlpool/asm/wp-mmx.pl index 32cf16380b5..cb2381c22ba 100755 --- a/crypto/whrlpool/asm/wp-mmx.pl +++ b/crypto/whrlpool/asm/wp-mmx.pl @@ -119,7 +119,7 @@ $tbl="ebp"; &mov ("eax",&DWP(0,"esp")); &mov ("ebx",&DWP(4,"esp")); for($i=0;$i<8;$i++) { - my $func = ($i==0)? movq : pxor; + my $func = ($i==0)? \&movq : \&pxor; &movb (&LB("ecx"),&LB("eax")); &movb (&LB("edx"),&HB("eax")); &scale ("esi","ecx"); diff --git a/crypto/whrlpool/asm/wp-x86_64.pl b/crypto/whrlpool/asm/wp-x86_64.pl index 87c0843dc1d..24b2ff60c38 100755 --- a/crypto/whrlpool/asm/wp-x86_64.pl +++ b/crypto/whrlpool/asm/wp-x86_64.pl @@ -41,7 +41,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; my $dir=$1; my $xlate; ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or die "can't locate x86_64-xlate.pl"; -open STDOUT,"| $^X $xlate $flavour $output"; +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; sub L() { $code.=".byte ".join(',',@_)."\n"; } sub LL(){ $code.=".byte ".join(',',@_).",".join(',',@_)."\n"; } diff --git a/crypto/x509/x509_cmp.c b/crypto/x509/x509_cmp.c index 7c2aaee2e9a..352aa374343 100644 --- a/crypto/x509/x509_cmp.c +++ b/crypto/x509/x509_cmp.c @@ -86,10 +86,9 @@ unsigned long X509_issuer_and_serial_hash(X509 *a) EVP_MD_CTX_init(&ctx); f=X509_NAME_oneline(a->cert_info->issuer,NULL,0); - ret=strlen(f); if (!EVP_DigestInit_ex(&ctx, EVP_md5(), NULL)) goto err; - if (!EVP_DigestUpdate(&ctx,(unsigned char *)f,ret)) + if (!EVP_DigestUpdate(&ctx,(unsigned char *)f,strlen(f))) goto err; OPENSSL_free(f); if(!EVP_DigestUpdate(&ctx,(unsigned char *)a->cert_info->serialNumber->data, @@ -249,14 +248,14 @@ unsigned long X509_NAME_hash_old(X509_NAME *x) i2d_X509_NAME(x,NULL); EVP_MD_CTX_init(&md_ctx); EVP_MD_CTX_set_flags(&md_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); - EVP_DigestInit_ex(&md_ctx, EVP_md5(), NULL); - EVP_DigestUpdate(&md_ctx, x->bytes->data, x->bytes->length); - EVP_DigestFinal_ex(&md_ctx,md,NULL); + if (EVP_DigestInit_ex(&md_ctx, EVP_md5(), NULL) + && EVP_DigestUpdate(&md_ctx, x->bytes->data, x->bytes->length) + && EVP_DigestFinal_ex(&md_ctx,md,NULL)) + ret=(((unsigned long)md[0] )|((unsigned long)md[1]<<8L)| + ((unsigned long)md[2]<<16L)|((unsigned long)md[3]<<24L) + )&0xffffffffL; EVP_MD_CTX_cleanup(&md_ctx); - ret=( ((unsigned long)md[0] )|((unsigned long)md[1]<<8L)| - ((unsigned long)md[2]<<16L)|((unsigned long)md[3]<<24L) - )&0xffffffffL; return(ret); } #endif diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c index b0779db0231..12d71f54e2e 100644 --- a/crypto/x509/x509_vfy.c +++ b/crypto/x509/x509_vfy.c @@ -872,7 +872,7 @@ static int crl_extension_match(X509_CRL *a, X509_CRL *b, int nid) { ASN1_OCTET_STRING *exta, *extb; int i; - i = X509_CRL_get_ext_by_NID(a, nid, 0); + i = X509_CRL_get_ext_by_NID(a, nid, -1); if (i >= 0) { /* Can't have multiple occurrences */ @@ -883,7 +883,7 @@ static int crl_extension_match(X509_CRL *a, X509_CRL *b, int nid) else exta = NULL; - i = X509_CRL_get_ext_by_NID(b, nid, 0); + i = X509_CRL_get_ext_by_NID(b, nid, -1); if (i >= 0) { diff --git a/crypto/x509v3/v3_purp.c b/crypto/x509v3/v3_purp.c index 181bd34979b..ad688657e01 100644 --- a/crypto/x509v3/v3_purp.c +++ b/crypto/x509v3/v3_purp.c @@ -474,11 +474,11 @@ static void x509v3_cache_extensions(X509 *x) for (i = 0; i < X509_get_ext_count(x); i++) { ex = X509_get_ext(x, i); - if (!X509_EXTENSION_get_critical(ex)) - continue; if (OBJ_obj2nid(X509_EXTENSION_get_object(ex)) == NID_freshest_crl) x->ex_flags |= EXFLAG_FRESHEST; + if (!X509_EXTENSION_get_critical(ex)) + continue; if (!X509_supported_extension(ex)) { x->ex_flags |= EXFLAG_CRITICAL; diff --git a/crypto/x86_64cpuid.pl b/crypto/x86_64cpuid.pl index 7b7b93b2232..6ebfd017ea5 100644 --- a/crypto/x86_64cpuid.pl +++ b/crypto/x86_64cpuid.pl @@ -11,7 +11,8 @@ $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; ( $xlate="${dir}perlasm/x86_64-xlate.pl" and -f $xlate) or die "can't locate x86_64-xlate.pl"; -open STDOUT,"| $^X $xlate $flavour $output"; +open OUT,"| \"$^X\" $xlate $flavour $output"; +*STDOUT=*OUT; ($arg1,$arg2,$arg3,$arg4)=$win64?("%rcx","%rdx","%r8", "%r9") : # Win64 order ("%rdi","%rsi","%rdx","%rcx"); # Unix order diff --git a/crypto/x86cpuid.pl b/crypto/x86cpuid.pl index 39fd8f22931..c18b0e2486d 100644 --- a/crypto/x86cpuid.pl +++ b/crypto/x86cpuid.pl @@ -165,7 +165,7 @@ for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); } &jnz (&label("nohalt")); # not enough privileges &pushf (); - &pop ("eax") + &pop ("eax"); &bt ("eax",9); &jnc (&label("nohalt")); # interrupts are disabled @@ -280,7 +280,7 @@ for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); } # arguments is 1 or 2! &function_begin_B("OPENSSL_indirect_call"); { - my $i,$max=7; # $max has to be chosen as 4*n-1 + my ($max,$i)=(7,); # $max has to be chosen as 4*n-1 # in order to preserve eventual # stack alignment &push ("ebp"); diff --git a/doc/apps/CA.pl.pod b/doc/apps/CA.pl.pod index ed69952f379..d326101cde7 100644 --- a/doc/apps/CA.pl.pod +++ b/doc/apps/CA.pl.pod @@ -39,13 +39,13 @@ prints a usage message. =item B<-newcert> -creates a new self signed certificate. The private key and certificate are -written to the file "newreq.pem". +creates a new self signed certificate. The private key is written to the file +"newkey.pem" and the request written to the file "newreq.pem". =item B<-newreq> -creates a new certificate request. The private key and request are -written to the file "newreq.pem". +creates a new certificate request. The private key is written to the file +"newkey.pem" and the request written to the file "newreq.pem". =item B<-newreq-nodes> diff --git a/doc/apps/verify.pod b/doc/apps/verify.pod index 336098f1e3b..da683004bd2 100644 --- a/doc/apps/verify.pod +++ b/doc/apps/verify.pod @@ -54,35 +54,37 @@ in PEM format concatenated together. =item B<-untrusted file> A file of untrusted certificates. The file should contain multiple certificates +in PEM format concatenated together. =item B<-purpose purpose> -the intended use for the certificate. Without this option no chain verification -will be done. Currently accepted uses are B, B, -B, B, B. See the B -section for more information. +The intended use for the certificate. If this option is not specified, +B will not consider certificate purpose during chain verification. +Currently accepted uses are B, B, B, +B, B. See the B section for more +information. =item B<-help> -prints out a usage message. +Print out a usage message. =item B<-verbose> -print extra information about the operations being performed. +Print extra information about the operations being performed. =item B<-issuer_checks> -print out diagnostics relating to searches for the issuer certificate -of the current certificate. This shows why each candidate issuer -certificate was rejected. However the presence of rejection messages -does not itself imply that anything is wrong: during the normal -verify process several rejections may take place. +Print out diagnostics relating to searches for the issuer certificate of the +current certificate. This shows why each candidate issuer certificate was +rejected. The presence of rejection messages does not itself imply that +anything is wrong; during the normal verification process, several +rejections may take place. =item B<-policy arg> -Enable policy processing and add B to the user-initial-policy-set -(see RFC3280 et al). The policy B can be an object name an OID in numeric -form. This argument can appear more than once. +Enable policy processing and add B to the user-initial-policy-set (see +RFC5280). The policy B can be an object name an OID in numeric form. +This argument can appear more than once. =item B<-policy_check> @@ -90,41 +92,40 @@ Enables certificate policy processing. =item B<-explicit_policy> -Set policy variable require-explicit-policy (see RFC3280 et al). +Set policy variable require-explicit-policy (see RFC5280). =item B<-inhibit_any> -Set policy variable inhibit-any-policy (see RFC3280 et al). +Set policy variable inhibit-any-policy (see RFC5280). =item B<-inhibit_map> -Set policy variable inhibit-policy-mapping (see RFC3280 et al). +Set policy variable inhibit-policy-mapping (see RFC5280). =item B<-policy_print> -Print out diagnostics, related to policy checking +Print out diagnostics related to policy processing. =item B<-crl_check> -Checks end entity certificate validity by attempting to lookup a valid CRL. +Checks end entity certificate validity by attempting to look up a valid CRL. If a valid CRL cannot be found an error occurs. =item B<-crl_check_all> Checks the validity of B certificates in the chain by attempting -to lookup valid CRLs. +to look up valid CRLs. =item B<-ignore_critical> Normally if an unhandled critical extension is present which is not -supported by OpenSSL the certificate is rejected (as required by -RFC3280 et al). If this option is set critical extensions are -ignored. +supported by OpenSSL the certificate is rejected (as required by RFC5280). +If this option is set critical extensions are ignored. =item B<-x509_strict> -Disable workarounds for broken certificates which have to be disabled -for strict X.509 compliance. +For strict X.509 compliance, disable non-compliant workarounds for broken +certificates. =item B<-extended_crl> @@ -142,16 +143,15 @@ because it doesn't add any security. =item B<-> -marks the last option. All arguments following this are assumed to be +Indicates the last option. All arguments following this are assumed to be certificate files. This is useful if the first certificate filename begins with a B<->. =item B -one or more certificates to verify. If no certificate filenames are included -then an attempt is made to read a certificate from standard input. They should -all be in PEM format. - +One or more certificates to verify. If no certificates are given, B +will attempt to read a certificate from standard input. Certificates must be +in PEM format. =back diff --git a/doc/apps/x509.pod b/doc/apps/x509.pod index 3002b081235..d2d9eb812af 100644 --- a/doc/apps/x509.pod +++ b/doc/apps/x509.pod @@ -29,6 +29,7 @@ B B [B<-purpose>] [B<-dates>] [B<-modulus>] +[B<-pubkey>] [B<-fingerprint>] [B<-alias>] [B<-noout>] @@ -135,6 +136,10 @@ section for more information. this option prevents output of the encoded version of the request. +=item B<-pubkey> + +outputs the the certificate's SubjectPublicKeyInfo block in PEM format. + =item B<-modulus> this option prints out the value of the modulus of the public key diff --git a/doc/crypto/EVP_PKEY_CTX_ctrl.pod b/doc/crypto/EVP_PKEY_CTX_ctrl.pod index f2f455990f5..13b91f1e6e5 100644 --- a/doc/crypto/EVP_PKEY_CTX_ctrl.pod +++ b/doc/crypto/EVP_PKEY_CTX_ctrl.pod @@ -117,7 +117,7 @@ L, L, L, L, -L, +L, L L diff --git a/doc/crypto/EVP_PKEY_decrypt.pod b/doc/crypto/EVP_PKEY_decrypt.pod index 42b2a8c44ed..847983237b9 100644 --- a/doc/crypto/EVP_PKEY_decrypt.pod +++ b/doc/crypto/EVP_PKEY_decrypt.pod @@ -83,7 +83,7 @@ L, L, L, L, -L, +L, L =head1 HISTORY diff --git a/doc/crypto/EVP_PKEY_derive.pod b/doc/crypto/EVP_PKEY_derive.pod index d9d6d76c721..27464be5718 100644 --- a/doc/crypto/EVP_PKEY_derive.pod +++ b/doc/crypto/EVP_PKEY_derive.pod @@ -84,7 +84,7 @@ L, L, L, L, -L, +L, =head1 HISTORY diff --git a/doc/crypto/EVP_PKEY_encrypt.pod b/doc/crypto/EVP_PKEY_encrypt.pod index 91c9c5d0a5d..e495a81242b 100644 --- a/doc/crypto/EVP_PKEY_encrypt.pod +++ b/doc/crypto/EVP_PKEY_encrypt.pod @@ -83,7 +83,7 @@ L, L, L, L, -L, +L, L =head1 HISTORY diff --git a/doc/crypto/EVP_PKEY_get_default_digest.pod b/doc/crypto/EVP_PKEY_get_default_digest.pod index 1a9c7954c55..8ff597d44ad 100644 --- a/doc/crypto/EVP_PKEY_get_default_digest.pod +++ b/doc/crypto/EVP_PKEY_get_default_digest.pod @@ -32,7 +32,7 @@ public key algorithm. L, L, L, -L, +L, =head1 HISTORY diff --git a/doc/crypto/EVP_PKEY_keygen.pod b/doc/crypto/EVP_PKEY_keygen.pod index 37c6fe95030..fd431ace6dc 100644 --- a/doc/crypto/EVP_PKEY_keygen.pod +++ b/doc/crypto/EVP_PKEY_keygen.pod @@ -151,7 +151,7 @@ L, L, L, L, -L, +L, L =head1 HISTORY diff --git a/doc/crypto/EVP_PKEY_sign.pod b/doc/crypto/EVP_PKEY_sign.pod index 2fb52c34863..a044f2c1312 100644 --- a/doc/crypto/EVP_PKEY_sign.pod +++ b/doc/crypto/EVP_PKEY_sign.pod @@ -86,7 +86,7 @@ L, L, L, L, -L, +L, L =head1 HISTORY diff --git a/doc/crypto/EVP_PKEY_verify.pod b/doc/crypto/EVP_PKEY_verify.pod index f93e5fc6c3a..90612ba2f07 100644 --- a/doc/crypto/EVP_PKEY_verify.pod +++ b/doc/crypto/EVP_PKEY_verify.pod @@ -81,7 +81,7 @@ L, L, L, L, -L, +L, L =head1 HISTORY diff --git a/doc/crypto/EVP_PKEY_verifyrecover.pod b/doc/crypto/EVP_PKEY_verify_recover.pod similarity index 76% rename from doc/crypto/EVP_PKEY_verifyrecover.pod rename to doc/crypto/EVP_PKEY_verify_recover.pod index f3605eb8264..23a28a9c43e 100644 --- a/doc/crypto/EVP_PKEY_verifyrecover.pod +++ b/doc/crypto/EVP_PKEY_verify_recover.pod @@ -2,23 +2,23 @@ =head1 NAME -EVP_PKEY_verifyrecover_init, EVP_PKEY_verifyrecover - recover signature using a public key algorithm +EVP_PKEY_verify_recover_init, EVP_PKEY_verify_recover - recover signature using a public key algorithm =head1 SYNOPSIS #include - int EVP_PKEY_verifyrecover_init(EVP_PKEY_CTX *ctx); - int EVP_PKEY_verifyrecover(EVP_PKEY_CTX *ctx, + int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx); + int EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx, unsigned char *rout, size_t *routlen, const unsigned char *sig, size_t siglen); =head1 DESCRIPTION -The EVP_PKEY_verifyrecover_init() function initializes a public key algorithm +The EVP_PKEY_verify_recover_init() function initializes a public key algorithm context using key B for a verify recover operation. -The EVP_PKEY_verifyrecover() function recovers signed data +The EVP_PKEY_verify_recover() function recovers signed data using B. The signature is specified using the B and B parameters. If B is B then the maximum size of the output buffer is written to the B parameter. If B is not B then @@ -36,16 +36,16 @@ Sometimes however it is useful to obtain the data originally signed using a signing operation. Only certain public key algorithms can recover a signature in this way (for example RSA in PKCS padding mode). -After the call to EVP_PKEY_verifyrecover_init() algorithm specific control +After the call to EVP_PKEY_verify_recover_init() algorithm specific control operations can be performed to set any appropriate parameters for the operation. -The function EVP_PKEY_verifyrecover() can be called more than once on the same +The function EVP_PKEY_verify_recover() can be called more than once on the same context if several operations are performed using the same parameters. =head1 RETURN VALUES -EVP_PKEY_verifyrecover_init() and EVP_PKEY_verifyrecover() return 1 for success +EVP_PKEY_verify_recover_init() and EVP_PKEY_verify_recover() return 1 for success and 0 or a negative value for failure. In particular a return value of -2 indicates the operation is not supported by the public key algorithm. @@ -66,7 +66,7 @@ Recover digest originally signed using PKCS#1 and SHA256 digest: ctx = EVP_PKEY_CTX_new(verify_key); if (!ctx) /* Error occurred */ - if (EVP_PKEY_verifyrecover_init(ctx) <= 0) + if (EVP_PKEY_verify_recover_init(ctx) <= 0) /* Error */ if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) /* Error */ @@ -74,7 +74,7 @@ Recover digest originally signed using PKCS#1 and SHA256 digest: /* Error */ /* Determine buffer length */ - if (EVP_PKEY_verifyrecover(ctx, NULL, &routlen, sig, siglen) <= 0) + if (EVP_PKEY_verify_recover(ctx, NULL, &routlen, sig, siglen) <= 0) /* Error */ rout = OPENSSL_malloc(routlen); @@ -82,7 +82,7 @@ Recover digest originally signed using PKCS#1 and SHA256 digest: if (!rout) /* malloc failure */ - if (EVP_PKEY_verifyrecover(ctx, rout, &routlen, sig, siglen) <= 0) + if (EVP_PKEY_verify_recover(ctx, rout, &routlen, sig, siglen) <= 0) /* Error */ /* Recovered data is routlen bytes written to buffer rout */ diff --git a/engines/ccgost/gost89.c b/engines/ccgost/gost89.c index 7ebae0f71f8..b0568c6b3c8 100644 --- a/engines/ccgost/gost89.c +++ b/engines/ccgost/gost89.c @@ -369,7 +369,13 @@ int gost_mac(gost_ctx *ctx,int mac_len,const unsigned char *data, memset(buf2,0,8); memcpy(buf2,data+i,data_len-i); mac_block(ctx,buffer,buf2); - } + i+=8; + } + if (i==8) + { + memset(buf2,0,8); + mac_block(ctx,buffer,buf2); + } get_mac(buffer,mac_len,mac); return 1; } @@ -389,7 +395,13 @@ int gost_mac_iv(gost_ctx *ctx,int mac_len,const unsigned char *iv,const unsigned memset(buf2,0,8); memcpy(buf2,data+i,data_len-i); mac_block(ctx,buffer,buf2); + i+=8; } + if (i==8) + { + memset(buf2,0,8); + mac_block(ctx,buffer,buf2); + } get_mac(buffer,mac_len,mac); return 1; } diff --git a/engines/ccgost/gost_crypt.c b/engines/ccgost/gost_crypt.c index cde58c0e9b7..52aef15acf4 100644 --- a/engines/ccgost/gost_crypt.c +++ b/engines/ccgost/gost_crypt.c @@ -11,6 +11,14 @@ #include #include "e_gost_err.h" #include "gost_lcl.h" + +#if !defined(CCGOST_DEBUG) && !defined(DEBUG) +# ifndef NDEBUG +# define NDEBUG +# endif +#endif +#include + static int gost_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc); static int gost_cipher_init_cpa(EVP_CIPHER_CTX *ctx, const unsigned char *key, @@ -206,12 +214,13 @@ int gost_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, static void gost_crypt_mesh (void *ctx,unsigned char *iv,unsigned char *buf) { struct ossl_gost_cipher_ctx *c = ctx; - if (c->count&&c->key_meshing && c->count%1024==0) + assert(c->count%8 == 0 && c->count <= 1024); + if (c->key_meshing && c->count==1024) { cryptopro_key_meshing(&(c->cctx),iv); } gostcrypt(&(c->cctx),iv,buf); - c->count+=8; + c->count = c->count%1024 + 8; } static void gost_cnt_next (void *ctx, unsigned char *iv, unsigned char *buf) @@ -219,7 +228,8 @@ static void gost_cnt_next (void *ctx, unsigned char *iv, unsigned char *buf) struct ossl_gost_cipher_ctx *c = ctx; word32 g,go; unsigned char buf1[8]; - if (c->count && c->key_meshing && c->count %1024 ==0) + assert(c->count%8 == 0 && c->count <= 1024); + if (c->key_meshing && c->count==1024) { cryptopro_key_meshing(&(c->cctx),iv); } @@ -248,7 +258,7 @@ static void gost_cnt_next (void *ctx, unsigned char *iv, unsigned char *buf) buf1[7]=(unsigned char)((g>>24)&0xff); memcpy(iv,buf1,8); gostcrypt(&(c->cctx),buf1,buf); - c->count +=8; + c->count = c->count%1024 + 8; } /* GOST encryption in CFB mode */ @@ -511,12 +521,13 @@ static void mac_block_mesh(struct ossl_gost_imit_ctx *c,const unsigned char *dat * interpret internal state of MAC algorithm as iv during keymeshing * (but does initialize internal state from iv in key transport */ - if (c->key_meshing&& c->count && c->count %1024 ==0) + assert(c->count%8 == 0 && c->count <= 1024); + if (c->key_meshing && c->count==1024) { cryptopro_key_meshing(&(c->cctx),buffer); } mac_block(&(c->cctx),c->buffer,data); - c->count +=8; + c->count = c->count%1024 + 8; } int gost_imit_update(EVP_MD_CTX *ctx, const void *data, size_t count) @@ -565,6 +576,12 @@ int gost_imit_final(EVP_MD_CTX *ctx,unsigned char *md) GOSTerr(GOST_F_GOST_IMIT_FINAL, GOST_R_MAC_KEY_NOT_SET); return 0; } + if (c->count==0 && c->bytes_left) + { + unsigned char buffer[8]; + memset(buffer, 0, 8); + gost_imit_update(ctx, buffer, 8); + } if (c->bytes_left) { int i; diff --git a/engines/ccgost/gost_eng.c b/engines/ccgost/gost_eng.c index d2cbe3b8314..8f29bf6f85b 100644 --- a/engines/ccgost/gost_eng.c +++ b/engines/ccgost/gost_eng.c @@ -64,6 +64,13 @@ static int gost_engine_finish(ENGINE *e) static int gost_engine_destroy(ENGINE *e) { gost_param_free(); + + pmeth_GostR3410_94 = NULL; + pmeth_GostR3410_2001 = NULL; + pmeth_Gost28147_MAC = NULL; + ameth_GostR3410_94 = NULL; + ameth_GostR3410_2001 = NULL; + ameth_Gost28147_MAC = NULL; return 1; } @@ -71,6 +78,11 @@ static int bind_gost (ENGINE *e,const char *id) { int ret = 0; if (id && strcmp(id, engine_gost_id)) return 0; + if (ameth_GostR3410_94) + { + printf("GOST engine already loaded\n"); + goto end; + } if (!ENGINE_set_id(e, engine_gost_id)) { @@ -263,7 +275,10 @@ static ENGINE *engine_gost(void) void ENGINE_load_gost(void) { - ENGINE *toadd =engine_gost(); + ENGINE *toadd; + if (pmeth_GostR3410_94) + return; + toadd = engine_gost(); if (!toadd) return; ENGINE_add(toadd); ENGINE_free(toadd); diff --git a/engines/ccgost/gost_lcl.h b/engines/ccgost/gost_lcl.h index 437a48cc86c..00aa42cea43 100644 --- a/engines/ccgost/gost_lcl.h +++ b/engines/ccgost/gost_lcl.h @@ -136,7 +136,7 @@ extern EVP_MD imit_gost_cpa; /* Cipher context used for EVP_CIPHER operation */ struct ossl_gost_cipher_ctx { int paramNID; - off_t count; + unsigned int count; int key_meshing; gost_ctx cctx; }; @@ -151,7 +151,7 @@ struct ossl_gost_imit_ctx { gost_ctx cctx; unsigned char buffer[8]; unsigned char partial_block[8]; - off_t count; + unsigned int count; int key_meshing; int bytes_left; int key_set; diff --git a/engines/ccgost/gosthash.c b/engines/ccgost/gosthash.c index a5c0662ffc3..8c278aa6452 100644 --- a/engines/ccgost/gosthash.c +++ b/engines/ccgost/gosthash.c @@ -42,7 +42,7 @@ static void circle_xor8 (const byte *w, byte *k) byte buf[8]; int i; memcpy(buf,w,8); - memcpy(k,w+8,24); + memmove(k,w+8,24); for(i=0;i<8;i++) k[i+24]=buf[i]^k[i]; } diff --git a/engines/e_capi.c b/engines/e_capi.c index bfedde0eb02..c1085b56cda 100644 --- a/engines/e_capi.c +++ b/engines/e_capi.c @@ -1432,10 +1432,13 @@ static PCCERT_CONTEXT capi_find_cert(CAPI_CTX *ctx, const char *id, HCERTSTORE h static CAPI_KEY *capi_get_key(CAPI_CTX *ctx, const char *contname, char *provname, DWORD ptype, DWORD keyspec) { CAPI_KEY *key; + DWORD dwFlags = 0; key = OPENSSL_malloc(sizeof(CAPI_KEY)); CAPI_trace(ctx, "capi_get_key, contname=%s, provname=%s, type=%d\n", contname, provname, ptype); - if (!CryptAcquireContextA(&key->hprov, contname, provname, ptype, 0)) + if(ctx->store_flags & CERT_SYSTEM_STORE_LOCAL_MACHINE) + dwFlags = CRYPT_MACHINE_KEYSET; + if (!CryptAcquireContextA(&key->hprov, contname, provname, ptype, dwFlags)) { CAPIerr(CAPI_F_CAPI_GET_KEY, CAPI_R_CRYPTACQUIRECONTEXT_ERROR); capi_addlasterror(); diff --git a/ssl/Makefile b/ssl/Makefile index feaf3e358a3..debe07405bf 100644 --- a/ssl/Makefile +++ b/ssl/Makefile @@ -22,7 +22,7 @@ LIB=$(TOP)/libssl.a SHARED_LIB= libssl$(SHLIB_EXT) LIBSRC= \ s2_meth.c s2_srvr.c s2_clnt.c s2_lib.c s2_enc.c s2_pkt.c \ - s3_meth.c s3_srvr.c s3_clnt.c s3_lib.c s3_enc.c s3_pkt.c s3_both.c \ + s3_meth.c s3_srvr.c s3_clnt.c s3_lib.c s3_enc.c s3_pkt.c s3_both.c s3_cbc.c \ s23_meth.c s23_srvr.c s23_clnt.c s23_lib.c s23_pkt.c \ t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c \ d1_meth.c d1_srvr.c d1_clnt.c d1_lib.c d1_pkt.c \ @@ -33,7 +33,7 @@ LIBSRC= \ bio_ssl.c ssl_err.c kssl.c tls_srp.c t1_reneg.c LIBOBJ= \ s2_meth.o s2_srvr.o s2_clnt.o s2_lib.o s2_enc.o s2_pkt.o \ - s3_meth.o s3_srvr.o s3_clnt.o s3_lib.o s3_enc.o s3_pkt.o s3_both.o \ + s3_meth.o s3_srvr.o s3_clnt.o s3_lib.o s3_enc.o s3_pkt.o s3_both.o s3_cbc.o \ s23_meth.o s23_srvr.o s23_clnt.o s23_lib.o s23_pkt.o \ t1_meth.o t1_srvr.o t1_clnt.o t1_lib.o t1_enc.o \ d1_meth.o d1_srvr.o d1_clnt.o d1_lib.o d1_pkt.o \ @@ -547,6 +547,26 @@ s3_both.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h s3_both.o: ../include/openssl/stack.h ../include/openssl/symhacks.h s3_both.o: ../include/openssl/tls1.h ../include/openssl/x509.h s3_both.o: ../include/openssl/x509_vfy.h s3_both.c ssl_locl.h +s3_cbc.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h +s3_cbc.o: ../include/openssl/buffer.h ../include/openssl/comp.h +s3_cbc.o: ../include/openssl/crypto.h ../include/openssl/dsa.h +s3_cbc.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h +s3_cbc.o: ../include/openssl/ec.h ../include/openssl/ecdh.h +s3_cbc.o: ../include/openssl/ecdsa.h ../include/openssl/err.h +s3_cbc.o: ../include/openssl/evp.h ../include/openssl/hmac.h +s3_cbc.o: ../include/openssl/kssl.h ../include/openssl/lhash.h +s3_cbc.o: ../include/openssl/md5.h ../include/openssl/obj_mac.h +s3_cbc.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h +s3_cbc.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h +s3_cbc.o: ../include/openssl/pem.h ../include/openssl/pem2.h +s3_cbc.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h +s3_cbc.o: ../include/openssl/rsa.h ../include/openssl/safestack.h +s3_cbc.o: ../include/openssl/sha.h ../include/openssl/srtp.h +s3_cbc.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h +s3_cbc.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h +s3_cbc.o: ../include/openssl/stack.h ../include/openssl/symhacks.h +s3_cbc.o: ../include/openssl/tls1.h ../include/openssl/x509.h +s3_cbc.o: ../include/openssl/x509_vfy.h s3_cbc.c ssl_locl.h s3_clnt.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h s3_clnt.o: ../include/openssl/bn.h ../include/openssl/buffer.h s3_clnt.o: ../include/openssl/comp.h ../include/openssl/crypto.h diff --git a/ssl/d1_enc.c b/ssl/d1_enc.c index 07a5e97ce5c..712c4647f24 100644 --- a/ssl/d1_enc.c +++ b/ssl/d1_enc.c @@ -126,20 +126,28 @@ #include #endif +/* dtls1_enc encrypts/decrypts the record in |s->wrec| / |s->rrec|, respectively. + * + * Returns: + * 0: (in non-constant time) if the record is publically invalid (i.e. too + * short etc). + * 1: if the record's padding is valid / the encryption was successful. + * -1: if the record's padding/AEAD-authenticator is invalid or, if sending, + * an internal error occured. */ int dtls1_enc(SSL *s, int send) { SSL3_RECORD *rec; EVP_CIPHER_CTX *ds; unsigned long l; - int bs,i,ii,j,k,n=0; + int bs,i,j,k,mac_size=0; const EVP_CIPHER *enc; if (send) { if (EVP_MD_CTX_md(s->write_hash)) { - n=EVP_MD_CTX_size(s->write_hash); - if (n < 0) + mac_size=EVP_MD_CTX_size(s->write_hash); + if (mac_size < 0) return -1; } ds=s->enc_write_ctx; @@ -164,9 +172,8 @@ int dtls1_enc(SSL *s, int send) { if (EVP_MD_CTX_md(s->read_hash)) { - n=EVP_MD_CTX_size(s->read_hash); - if (n < 0) - return -1; + mac_size=EVP_MD_CTX_size(s->read_hash); + OPENSSL_assert(mac_size >= 0); } ds=s->enc_read_ctx; rec= &(s->s3->rrec); @@ -231,7 +238,7 @@ int dtls1_enc(SSL *s, int send) if (!send) { if (l == 0 || l%bs != 0) - return -1; + return 0; } EVP_Cipher(ds,rec->data,rec->input,l); @@ -246,43 +253,7 @@ int dtls1_enc(SSL *s, int send) #endif /* KSSL_DEBUG */ if ((bs != 1) && !send) - { - ii=i=rec->data[l-1]; /* padding_length */ - i++; - if (s->options&SSL_OP_TLS_BLOCK_PADDING_BUG) - { - /* First packet is even in size, so check */ - if ((memcmp(s->s3->read_sequence, - "\0\0\0\0\0\0\0\0",8) == 0) && !(ii & 1)) - s->s3->flags|=TLS1_FLAGS_TLS_PADDING_BUG; - if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG) - i--; - } - /* TLS 1.0 does not bound the number of padding bytes by the block size. - * All of them must have value 'padding_length'. */ - if (i + bs > (int)rec->length) - { - /* Incorrect padding. SSLerr() and ssl3_alert are done - * by caller: we don't want to reveal whether this is - * a decryption error or a MAC verification failure - * (see http://www.openssl.org/~bodo/tls-cbc.txt) - */ - return -1; - } - for (j=(int)(l-i); j<(int)l; j++) - { - if (rec->data[j] != ii) - { - /* Incorrect padding */ - return -1; - } - } - rec->length-=i; - - rec->data += bs; /* skip the implicit IV */ - rec->input += bs; - rec->length -= bs; - } + return tls1_cbc_remove_padding(s, rec, bs, mac_size); } return(1); } diff --git a/ssl/d1_pkt.c b/ssl/d1_pkt.c index 987af608358..0bf87be6d21 100644 --- a/ssl/d1_pkt.c +++ b/ssl/d1_pkt.c @@ -376,15 +376,11 @@ static int dtls1_process_record(SSL *s) { int i,al; - int clear=0; int enc_err; SSL_SESSION *sess; SSL3_RECORD *rr; - unsigned int mac_size; + unsigned int mac_size, orig_len; unsigned char md[EVP_MAX_MD_SIZE]; - int decryption_failed_or_bad_record_mac = 0; - unsigned char *mac = NULL; - rr= &(s->s3->rrec); sess = s->session; @@ -416,12 +412,16 @@ dtls1_process_record(SSL *s) rr->data=rr->input; enc_err = s->method->ssl3_enc->enc(s,0); - if (enc_err <= 0) + /* enc_err is: + * 0: (in non-constant time) if the record is publically invalid. + * 1: if the padding is valid + * -1: if the padding is invalid */ + if (enc_err == 0) { - /* To minimize information leaked via timing, we will always - * perform all computations before discarding the message. - */ - decryption_failed_or_bad_record_mac = 1; + /* For DTLS we simply ignore bad packets. */ + rr->length = 0; + s->packet_length = 0; + goto err; } #ifdef TLS_DEBUG @@ -431,45 +431,62 @@ printf("\n"); #endif /* r->length is now the compressed data plus mac */ - if ( (sess == NULL) || - (s->enc_read_ctx == NULL) || - (s->read_hash == NULL)) - clear=1; - - if (!clear) + if ((sess != NULL) && + (s->enc_read_ctx != NULL) && + (EVP_MD_CTX_md(s->read_hash) != NULL)) { - /* !clear => s->read_hash != NULL => mac_size != -1 */ - int t; - t=EVP_MD_CTX_size(s->read_hash); - OPENSSL_assert(t >= 0); - mac_size=t; + /* s->read_hash != NULL => mac_size != -1 */ + unsigned char *mac = NULL; + unsigned char mac_tmp[EVP_MAX_MD_SIZE]; + mac_size=EVP_MD_CTX_size(s->read_hash); + OPENSSL_assert(mac_size <= EVP_MAX_MD_SIZE); - if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+mac_size) + /* kludge: *_cbc_remove_padding passes padding length in rr->type */ + orig_len = rr->length+((unsigned int)rr->type>>8); + + /* orig_len is the length of the record before any padding was + * removed. This is public information, as is the MAC in use, + * therefore we can safely process the record in a different + * amount of time if it's too short to possibly contain a MAC. + */ + if (orig_len < mac_size || + /* CBC records must have a padding length byte too. */ + (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE && + orig_len < mac_size+1)) { -#if 0 /* OK only for stream ciphers (then rr->length is visible from ciphertext anyway) */ - al=SSL_AD_RECORD_OVERFLOW; - SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_PRE_MAC_LENGTH_TOO_LONG); + al=SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_LENGTH_TOO_SHORT); goto f_err; -#else - decryption_failed_or_bad_record_mac = 1; -#endif } - /* check the MAC for rr->input (it's in mac_size bytes at the tail) */ - if (rr->length >= mac_size) + + if (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE) { + /* We update the length so that the TLS header bytes + * can be constructed correctly but we need to extract + * the MAC in constant time from within the record, + * without leaking the contents of the padding bytes. + * */ + mac = mac_tmp; + ssl3_cbc_copy_mac(mac_tmp, rr, mac_size, orig_len); + rr->length -= mac_size; + } + else + { + /* In this case there's no padding, so |orig_len| + * equals |rec->length| and we checked that there's + * enough bytes for |mac_size| above. */ rr->length -= mac_size; mac = &rr->data[rr->length]; } - else - rr->length = 0; - i=s->method->ssl3_enc->mac(s,md,0); - if (i < 0 || mac == NULL || memcmp(md, mac, mac_size) != 0) - { - decryption_failed_or_bad_record_mac = 1; - } + + i=s->method->ssl3_enc->mac(s,md,0 /* not send */); + if (i < 0 || mac == NULL || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0) + enc_err = -1; + if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+mac_size) + enc_err = -1; } - if (decryption_failed_or_bad_record_mac) + if (enc_err < 0) { /* decryption failed, silently discard message */ rr->length = 0; diff --git a/ssl/d1_srtp.c b/ssl/d1_srtp.c index 928935bd8b4..ab9c41922c4 100644 --- a/ssl/d1_srtp.c +++ b/ssl/d1_srtp.c @@ -115,11 +115,12 @@ Copyright (C) 2011, RTFM, Inc. */ -#ifndef OPENSSL_NO_SRTP - #include #include #include "ssl_locl.h" + +#ifndef OPENSSL_NO_SRTP + #include "srtp.h" diff --git a/ssl/dtls1.h b/ssl/dtls1.h index 5008bf60817..e65d5011915 100644 --- a/ssl/dtls1.h +++ b/ssl/dtls1.h @@ -57,8 +57,8 @@ * */ -#ifndef HEADER_DTLS1_H -#define HEADER_DTLS1_H +#ifndef HEADER_DTLS1_H +#define HEADER_DTLS1_H #include #include @@ -72,8 +72,12 @@ #elif defined(OPENSSL_SYS_NETWARE) && !defined(_WINSOCK2API_) #include #else +#if defined(OPENSSL_SYS_VXWORKS) +#include +#else #include #endif +#endif #ifdef __cplusplus extern "C" { diff --git a/ssl/s2_clnt.c b/ssl/s2_clnt.c index 00ac158f9bb..03b6cf96738 100644 --- a/ssl/s2_clnt.c +++ b/ssl/s2_clnt.c @@ -359,12 +359,14 @@ static int get_server_hello(SSL *s) SSL_R_PEER_ERROR); return(-1); } -#ifdef __APPLE_CC__ - /* The Rhapsody 5.5 (a.k.a. MacOS X) compiler bug - * workaround. */ - s->hit=(i=*(p++))?1:0; -#else +#if 0 s->hit=(*(p++))?1:0; + /* Some [PPC?] compilers fail to increment p in above + statement, e.g. one provided with Rhapsody 5.5, but + most recent example XL C 11.1 for AIX, even without + optimization flag... */ +#else + s->hit=(*p)?1:0; p++; #endif s->s2->tmp.cert_type= *(p++); n2s(p,i); @@ -937,7 +939,7 @@ static int get_server_verify(SSL *s) s->msg_callback(0, s->version, 0, p, len, s, s->msg_callback_arg); /* SERVER-VERIFY */ p += 1; - if (memcmp(p,s->s2->challenge,s->s2->challenge_length) != 0) + if (CRYPTO_memcmp(p,s->s2->challenge,s->s2->challenge_length) != 0) { ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); SSLerr(SSL_F_GET_SERVER_VERIFY,SSL_R_CHALLENGE_IS_DIFFERENT); diff --git a/ssl/s2_pkt.c b/ssl/s2_pkt.c index ac963b2d47d..8bb6ab8baa3 100644 --- a/ssl/s2_pkt.c +++ b/ssl/s2_pkt.c @@ -269,8 +269,7 @@ static int ssl2_read_internal(SSL *s, void *buf, int len, int peek) s->s2->ract_data_length-=mac_size; ssl2_mac(s,mac,0); s->s2->ract_data_length-=s->s2->padding; - if ( (memcmp(mac,s->s2->mac_data, - (unsigned int)mac_size) != 0) || + if ( (CRYPTO_memcmp(mac,s->s2->mac_data,mac_size) != 0) || (s->s2->rlength%EVP_CIPHER_CTX_block_size(s->enc_read_ctx) != 0)) { SSLerr(SSL_F_SSL2_READ_INTERNAL,SSL_R_BAD_MAC_DECODE); diff --git a/ssl/s2_srvr.c b/ssl/s2_srvr.c index bc885e8e7f6..2cba426bb7e 100644 --- a/ssl/s2_srvr.c +++ b/ssl/s2_srvr.c @@ -1059,10 +1059,12 @@ static int request_certificate(SSL *s) EVP_PKEY *pkey=NULL; EVP_MD_CTX_init(&ctx); - EVP_VerifyInit_ex(&ctx,s->ctx->rsa_md5, NULL); - EVP_VerifyUpdate(&ctx,s->s2->key_material, - s->s2->key_material_length); - EVP_VerifyUpdate(&ctx,ccd,SSL2_MIN_CERT_CHALLENGE_LENGTH); + if (!EVP_VerifyInit_ex(&ctx,s->ctx->rsa_md5, NULL) + || !EVP_VerifyUpdate(&ctx,s->s2->key_material, + s->s2->key_material_length) + || !EVP_VerifyUpdate(&ctx,ccd, + SSL2_MIN_CERT_CHALLENGE_LENGTH)) + goto msg_end; i=i2d_X509(s->cert->pkeys[SSL_PKEY_RSA_ENC].x509,NULL); buf2=OPENSSL_malloc((unsigned int)i); @@ -1073,7 +1075,11 @@ static int request_certificate(SSL *s) } p2=buf2; i=i2d_X509(s->cert->pkeys[SSL_PKEY_RSA_ENC].x509,&p2); - EVP_VerifyUpdate(&ctx,buf2,(unsigned int)i); + if (!EVP_VerifyUpdate(&ctx,buf2,(unsigned int)i)) + { + OPENSSL_free(buf2); + goto msg_end; + } OPENSSL_free(buf2); pkey=X509_get_pubkey(x509); diff --git a/ssl/s3_both.c b/ssl/s3_both.c index b63460a56dd..ead01c82a14 100644 --- a/ssl/s3_both.c +++ b/ssl/s3_both.c @@ -204,7 +204,8 @@ int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen) #ifndef OPENSSL_NO_NEXTPROTONEG /* ssl3_take_mac calculates the Finished MAC for the handshakes messages seen to far. */ -static void ssl3_take_mac(SSL *s) { +static void ssl3_take_mac(SSL *s) + { const char *sender; int slen; @@ -221,7 +222,7 @@ static void ssl3_take_mac(SSL *s) { s->s3->tmp.peer_finish_md_len = s->method->ssl3_enc->final_finish_mac(s, sender,slen,s->s3->tmp.peer_finish_md); -} + } #endif int ssl3_get_finished(SSL *s, int a, int b) @@ -231,8 +232,9 @@ int ssl3_get_finished(SSL *s, int a, int b) unsigned char *p; #ifdef OPENSSL_NO_NEXTPROTONEG - /* the mac has already been generated when we received the change - * cipher spec message and is in s->s3->tmp.peer_finish_md. */ + /* the mac has already been generated when we received the + * change cipher spec message and is in s->s3->tmp.peer_finish_md. + */ #endif n=s->method->ssl_get_message(s, @@ -263,7 +265,7 @@ int ssl3_get_finished(SSL *s, int a, int b) goto f_err; } - if (memcmp(p, s->s3->tmp.peer_finish_md, i) != 0) + if (CRYPTO_memcmp(p, s->s3->tmp.peer_finish_md, i) != 0) { al=SSL_AD_DECRYPT_ERROR; SSLerr(SSL_F_SSL3_GET_FINISHED,SSL_R_DIGEST_CHECK_FAILED); @@ -537,12 +539,14 @@ long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) s->init_num += i; n -= i; } + #ifndef OPENSSL_NO_NEXTPROTONEG /* If receiving Finished, record MAC of prior handshake messages for * Finished verification. */ if (*s->init_buf->data == SSL3_MT_FINISHED) ssl3_take_mac(s); #endif + /* Feed this message into MAC computation. */ ssl3_finish_mac(s, (unsigned char *)s->init_buf->data, s->init_num + 4); if (s->msg_callback) diff --git a/ssl/s3_cbc.c b/ssl/s3_cbc.c new file mode 100644 index 00000000000..02edf3f9189 --- /dev/null +++ b/ssl/s3_cbc.c @@ -0,0 +1,790 @@ +/* ssl/s3_cbc.c */ +/* ==================================================================== + * Copyright (c) 2012 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include "ssl_locl.h" + +#include +#include + +/* MAX_HASH_BIT_COUNT_BYTES is the maximum number of bytes in the hash's length + * field. (SHA-384/512 have 128-bit length.) */ +#define MAX_HASH_BIT_COUNT_BYTES 16 + +/* MAX_HASH_BLOCK_SIZE is the maximum hash block size that we'll support. + * Currently SHA-384/512 has a 128-byte block size and that's the largest + * supported by TLS.) */ +#define MAX_HASH_BLOCK_SIZE 128 + +/* Some utility functions are needed: + * + * These macros return the given value with the MSB copied to all the other + * bits. They use the fact that arithmetic shift shifts-in the sign bit. + * However, this is not ensured by the C standard so you may need to replace + * them with something else on odd CPUs. */ +#define DUPLICATE_MSB_TO_ALL(x) ( (unsigned)( (int)(x) >> (sizeof(int)*8-1) ) ) +#define DUPLICATE_MSB_TO_ALL_8(x) ((unsigned char)(DUPLICATE_MSB_TO_ALL(x))) + +/* constant_time_lt returns 0xff if a=b and 0x00 otherwise. */ +static unsigned constant_time_ge(unsigned a, unsigned b) + { + a -= b; + return DUPLICATE_MSB_TO_ALL(~a); + } + +/* constant_time_eq_8 returns 0xff if a==b and 0x00 otherwise. */ +static unsigned char constant_time_eq_8(unsigned a, unsigned b) + { + unsigned c = a ^ b; + c--; + return DUPLICATE_MSB_TO_ALL_8(c); + } + +/* ssl3_cbc_remove_padding removes padding from the decrypted, SSLv3, CBC + * record in |rec| by updating |rec->length| in constant time. + * + * block_size: the block size of the cipher used to encrypt the record. + * returns: + * 0: (in non-constant time) if the record is publicly invalid. + * 1: if the padding was valid + * -1: otherwise. */ +int ssl3_cbc_remove_padding(const SSL* s, + SSL3_RECORD *rec, + unsigned block_size, + unsigned mac_size) + { + unsigned padding_length, good; + const unsigned overhead = 1 /* padding length byte */ + mac_size; + + /* These lengths are all public so we can test them in non-constant + * time. */ + if (overhead > rec->length) + return 0; + + padding_length = rec->data[rec->length-1]; + good = constant_time_ge(rec->length, padding_length+overhead); + /* SSLv3 requires that the padding is minimal. */ + good &= constant_time_ge(block_size, padding_length+1); + padding_length = good & (padding_length+1); + rec->length -= padding_length; + rec->type |= padding_length<<8; /* kludge: pass padding length */ + return (int)((good & 1) | (~good & -1)); +} + +/* tls1_cbc_remove_padding removes the CBC padding from the decrypted, TLS, CBC + * record in |rec| in constant time and returns 1 if the padding is valid and + * -1 otherwise. It also removes any explicit IV from the start of the record + * without leaking any timing about whether there was enough space after the + * padding was removed. + * + * block_size: the block size of the cipher used to encrypt the record. + * returns: + * 0: (in non-constant time) if the record is publicly invalid. + * 1: if the padding was valid + * -1: otherwise. */ +int tls1_cbc_remove_padding(const SSL* s, + SSL3_RECORD *rec, + unsigned block_size, + unsigned mac_size) + { + unsigned padding_length, good, to_check, i; + const unsigned overhead = 1 /* padding length byte */ + mac_size; + /* Check if version requires explicit IV */ + if (s->version >= TLS1_1_VERSION || s->version == DTLS1_VERSION) + { + /* These lengths are all public so we can test them in + * non-constant time. + */ + if (overhead + block_size > rec->length) + return 0; + /* We can now safely skip explicit IV */ + rec->data += block_size; + rec->input += block_size; + rec->length -= block_size; + } + else if (overhead > rec->length) + return 0; + + padding_length = rec->data[rec->length-1]; + + /* NB: if compression is in operation the first packet may not be of + * even length so the padding bug check cannot be performed. This bug + * workaround has been around since SSLeay so hopefully it is either + * fixed now or no buggy implementation supports compression [steve] + */ + if ( (s->options&SSL_OP_TLS_BLOCK_PADDING_BUG) && !s->expand) + { + /* First packet is even in size, so check */ + if ((memcmp(s->s3->read_sequence, "\0\0\0\0\0\0\0\0",8) == 0) && + !(padding_length & 1)) + { + s->s3->flags|=TLS1_FLAGS_TLS_PADDING_BUG; + } + if ((s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG) && + padding_length > 0) + { + padding_length--; + } + } + + if (EVP_CIPHER_flags(s->enc_read_ctx->cipher)&EVP_CIPH_FLAG_AEAD_CIPHER) + { + /* padding is already verified */ + rec->length -= padding_length + 1; + return 1; + } + + good = constant_time_ge(rec->length, overhead+padding_length); + /* The padding consists of a length byte at the end of the record and + * then that many bytes of padding, all with the same value as the + * length byte. Thus, with the length byte included, there are i+1 + * bytes of padding. + * + * We can't check just |padding_length+1| bytes because that leaks + * decrypted information. Therefore we always have to check the maximum + * amount of padding possible. (Again, the length of the record is + * public information so we can use it.) */ + to_check = 255; /* maximum amount of padding. */ + if (to_check > rec->length-1) + to_check = rec->length-1; + + for (i = 0; i < to_check; i++) + { + unsigned char mask = constant_time_ge(padding_length, i); + unsigned char b = rec->data[rec->length-1-i]; + /* The final |padding_length+1| bytes should all have the value + * |padding_length|. Therefore the XOR should be zero. */ + good &= ~(mask&(padding_length ^ b)); + } + + /* If any of the final |padding_length+1| bytes had the wrong value, + * one or more of the lower eight bits of |good| will be cleared. We + * AND the bottom 8 bits together and duplicate the result to all the + * bits. */ + good &= good >> 4; + good &= good >> 2; + good &= good >> 1; + good <<= sizeof(good)*8-1; + good = DUPLICATE_MSB_TO_ALL(good); + + padding_length = good & (padding_length+1); + rec->length -= padding_length; + rec->type |= padding_length<<8; /* kludge: pass padding length */ + + return (int)((good & 1) | (~good & -1)); + } + +/* ssl3_cbc_copy_mac copies |md_size| bytes from the end of |rec| to |out| in + * constant time (independent of the concrete value of rec->length, which may + * vary within a 256-byte window). + * + * ssl3_cbc_remove_padding or tls1_cbc_remove_padding must be called prior to + * this function. + * + * On entry: + * rec->orig_len >= md_size + * md_size <= EVP_MAX_MD_SIZE + * + * If CBC_MAC_ROTATE_IN_PLACE is defined then the rotation is performed with + * variable accesses in a 64-byte-aligned buffer. Assuming that this fits into + * a single or pair of cache-lines, then the variable memory accesses don't + * actually affect the timing. CPUs with smaller cache-lines [if any] are + * not multi-core and are not considered vulnerable to cache-timing attacks. + */ +#define CBC_MAC_ROTATE_IN_PLACE + +void ssl3_cbc_copy_mac(unsigned char* out, + const SSL3_RECORD *rec, + unsigned md_size,unsigned orig_len) + { +#if defined(CBC_MAC_ROTATE_IN_PLACE) + unsigned char rotated_mac_buf[64+EVP_MAX_MD_SIZE]; + unsigned char *rotated_mac; +#else + unsigned char rotated_mac[EVP_MAX_MD_SIZE]; +#endif + + /* mac_end is the index of |rec->data| just after the end of the MAC. */ + unsigned mac_end = rec->length; + unsigned mac_start = mac_end - md_size; + /* scan_start contains the number of bytes that we can ignore because + * the MAC's position can only vary by 255 bytes. */ + unsigned scan_start = 0; + unsigned i, j; + unsigned div_spoiler; + unsigned rotate_offset; + + OPENSSL_assert(orig_len >= md_size); + OPENSSL_assert(md_size <= EVP_MAX_MD_SIZE); + +#if defined(CBC_MAC_ROTATE_IN_PLACE) + rotated_mac = rotated_mac_buf + ((0-(size_t)rotated_mac_buf)&63); +#endif + + /* This information is public so it's safe to branch based on it. */ + if (orig_len > md_size + 255 + 1) + scan_start = orig_len - (md_size + 255 + 1); + /* div_spoiler contains a multiple of md_size that is used to cause the + * modulo operation to be constant time. Without this, the time varies + * based on the amount of padding when running on Intel chips at least. + * + * The aim of right-shifting md_size is so that the compiler doesn't + * figure out that it can remove div_spoiler as that would require it + * to prove that md_size is always even, which I hope is beyond it. */ + div_spoiler = md_size >> 1; + div_spoiler <<= (sizeof(div_spoiler)-1)*8; + rotate_offset = (div_spoiler + mac_start - scan_start) % md_size; + + memset(rotated_mac, 0, md_size); + for (i = scan_start, j = 0; i < orig_len; i++) + { + unsigned char mac_started = constant_time_ge(i, mac_start); + unsigned char mac_ended = constant_time_ge(i, mac_end); + unsigned char b = rec->data[i]; + rotated_mac[j++] |= b & mac_started & ~mac_ended; + j &= constant_time_lt(j,md_size); + } + + /* Now rotate the MAC */ +#if defined(CBC_MAC_ROTATE_IN_PLACE) + j = 0; + for (i = 0; i < md_size; i++) + { + /* in case cache-line is 32 bytes, touch second line */ + ((volatile unsigned char *)rotated_mac)[rotate_offset^32]; + out[j++] = rotated_mac[rotate_offset++]; + rotate_offset &= constant_time_lt(rotate_offset,md_size); + } +#else + memset(out, 0, md_size); + rotate_offset = md_size - rotate_offset; + rotate_offset &= constant_time_lt(rotate_offset,md_size); + for (i = 0; i < md_size; i++) + { + for (j = 0; j < md_size; j++) + out[j] |= rotated_mac[i] & constant_time_eq_8(j, rotate_offset); + rotate_offset++; + rotate_offset &= constant_time_lt(rotate_offset,md_size); + } +#endif + } + +/* u32toLE serialises an unsigned, 32-bit number (n) as four bytes at (p) in + * little-endian order. The value of p is advanced by four. */ +#define u32toLE(n, p) \ + (*((p)++)=(unsigned char)(n), \ + *((p)++)=(unsigned char)(n>>8), \ + *((p)++)=(unsigned char)(n>>16), \ + *((p)++)=(unsigned char)(n>>24)) + +/* These functions serialize the state of a hash and thus perform the standard + * "final" operation without adding the padding and length that such a function + * typically does. */ +static void tls1_md5_final_raw(void* ctx, unsigned char *md_out) + { + MD5_CTX *md5 = ctx; + u32toLE(md5->A, md_out); + u32toLE(md5->B, md_out); + u32toLE(md5->C, md_out); + u32toLE(md5->D, md_out); + } + +static void tls1_sha1_final_raw(void* ctx, unsigned char *md_out) + { + SHA_CTX *sha1 = ctx; + l2n(sha1->h0, md_out); + l2n(sha1->h1, md_out); + l2n(sha1->h2, md_out); + l2n(sha1->h3, md_out); + l2n(sha1->h4, md_out); + } +#define LARGEST_DIGEST_CTX SHA_CTX + +#ifndef OPENSSL_NO_SHA256 +static void tls1_sha256_final_raw(void* ctx, unsigned char *md_out) + { + SHA256_CTX *sha256 = ctx; + unsigned i; + + for (i = 0; i < 8; i++) + { + l2n(sha256->h[i], md_out); + } + } +#undef LARGEST_DIGEST_CTX +#define LARGEST_DIGEST_CTX SHA256_CTX +#endif + +#ifndef OPENSSL_NO_SHA512 +static void tls1_sha512_final_raw(void* ctx, unsigned char *md_out) + { + SHA512_CTX *sha512 = ctx; + unsigned i; + + for (i = 0; i < 8; i++) + { + l2n8(sha512->h[i], md_out); + } + } +#undef LARGEST_DIGEST_CTX +#define LARGEST_DIGEST_CTX SHA512_CTX +#endif + +/* ssl3_cbc_record_digest_supported returns 1 iff |ctx| uses a hash function + * which ssl3_cbc_digest_record supports. */ +char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx) + { +#ifdef OPENSSL_FIPS + if (FIPS_mode()) + return 0; +#endif + switch (EVP_MD_CTX_type(ctx)) + { + case NID_md5: + case NID_sha1: +#ifndef OPENSSL_NO_SHA256 + case NID_sha224: + case NID_sha256: +#endif +#ifndef OPENSSL_NO_SHA512 + case NID_sha384: + case NID_sha512: +#endif + return 1; + default: + return 0; + } + } + +/* ssl3_cbc_digest_record computes the MAC of a decrypted, padded SSLv3/TLS + * record. + * + * ctx: the EVP_MD_CTX from which we take the hash function. + * ssl3_cbc_record_digest_supported must return true for this EVP_MD_CTX. + * md_out: the digest output. At most EVP_MAX_MD_SIZE bytes will be written. + * md_out_size: if non-NULL, the number of output bytes is written here. + * header: the 13-byte, TLS record header. + * data: the record data itself, less any preceeding explicit IV. + * data_plus_mac_size: the secret, reported length of the data and MAC + * once the padding has been removed. + * data_plus_mac_plus_padding_size: the public length of the whole + * record, including padding. + * is_sslv3: non-zero if we are to use SSLv3. Otherwise, TLS. + * + * On entry: by virtue of having been through one of the remove_padding + * functions, above, we know that data_plus_mac_size is large enough to contain + * a padding byte and MAC. (If the padding was invalid, it might contain the + * padding too. ) */ +void ssl3_cbc_digest_record( + const EVP_MD_CTX *ctx, + unsigned char* md_out, + size_t* md_out_size, + const unsigned char header[13], + const unsigned char *data, + size_t data_plus_mac_size, + size_t data_plus_mac_plus_padding_size, + const unsigned char *mac_secret, + unsigned mac_secret_length, + char is_sslv3) + { + union { double align; + unsigned char c[sizeof(LARGEST_DIGEST_CTX)]; } md_state; + void (*md_final_raw)(void *ctx, unsigned char *md_out); + void (*md_transform)(void *ctx, const unsigned char *block); + unsigned md_size, md_block_size = 64; + unsigned sslv3_pad_length = 40, header_length, variance_blocks, + len, max_mac_bytes, num_blocks, + num_starting_blocks, k, mac_end_offset, c, index_a, index_b; + unsigned int bits; /* at most 18 bits */ + unsigned char length_bytes[MAX_HASH_BIT_COUNT_BYTES]; + /* hmac_pad is the masked HMAC key. */ + unsigned char hmac_pad[MAX_HASH_BLOCK_SIZE]; + unsigned char first_block[MAX_HASH_BLOCK_SIZE]; + unsigned char mac_out[EVP_MAX_MD_SIZE]; + unsigned i, j, md_out_size_u; + EVP_MD_CTX md_ctx; + /* mdLengthSize is the number of bytes in the length field that terminates + * the hash. */ + unsigned md_length_size = 8; + char length_is_big_endian = 1; + + /* This is a, hopefully redundant, check that allows us to forget about + * many possible overflows later in this function. */ + OPENSSL_assert(data_plus_mac_plus_padding_size < 1024*1024); + + switch (EVP_MD_CTX_type(ctx)) + { + case NID_md5: + MD5_Init((MD5_CTX*)md_state.c); + md_final_raw = tls1_md5_final_raw; + md_transform = (void(*)(void *ctx, const unsigned char *block)) MD5_Transform; + md_size = 16; + sslv3_pad_length = 48; + length_is_big_endian = 0; + break; + case NID_sha1: + SHA1_Init((SHA_CTX*)md_state.c); + md_final_raw = tls1_sha1_final_raw; + md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA1_Transform; + md_size = 20; + break; +#ifndef OPENSSL_NO_SHA256 + case NID_sha224: + SHA224_Init((SHA256_CTX*)md_state.c); + md_final_raw = tls1_sha256_final_raw; + md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA256_Transform; + md_size = 224/8; + break; + case NID_sha256: + SHA256_Init((SHA256_CTX*)md_state.c); + md_final_raw = tls1_sha256_final_raw; + md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA256_Transform; + md_size = 32; + break; +#endif +#ifndef OPENSSL_NO_SHA512 + case NID_sha384: + SHA384_Init((SHA512_CTX*)md_state.c); + md_final_raw = tls1_sha512_final_raw; + md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA512_Transform; + md_size = 384/8; + md_block_size = 128; + md_length_size = 16; + break; + case NID_sha512: + SHA512_Init((SHA512_CTX*)md_state.c); + md_final_raw = tls1_sha512_final_raw; + md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA512_Transform; + md_size = 64; + md_block_size = 128; + md_length_size = 16; + break; +#endif + default: + /* ssl3_cbc_record_digest_supported should have been + * called first to check that the hash function is + * supported. */ + OPENSSL_assert(0); + if (md_out_size) + *md_out_size = -1; + return; + } + + OPENSSL_assert(md_length_size <= MAX_HASH_BIT_COUNT_BYTES); + OPENSSL_assert(md_block_size <= MAX_HASH_BLOCK_SIZE); + OPENSSL_assert(md_size <= EVP_MAX_MD_SIZE); + + header_length = 13; + if (is_sslv3) + { + header_length = + mac_secret_length + + sslv3_pad_length + + 8 /* sequence number */ + + 1 /* record type */ + + 2 /* record length */; + } + + /* variance_blocks is the number of blocks of the hash that we have to + * calculate in constant time because they could be altered by the + * padding value. + * + * In SSLv3, the padding must be minimal so the end of the plaintext + * varies by, at most, 15+20 = 35 bytes. (We conservatively assume that + * the MAC size varies from 0..20 bytes.) In case the 9 bytes of hash + * termination (0x80 + 64-bit length) don't fit in the final block, we + * say that the final two blocks can vary based on the padding. + * + * TLSv1 has MACs up to 48 bytes long (SHA-384) and the padding is not + * required to be minimal. Therefore we say that the final six blocks + * can vary based on the padding. + * + * Later in the function, if the message is short and there obviously + * cannot be this many blocks then variance_blocks can be reduced. */ + variance_blocks = is_sslv3 ? 2 : 6; + /* From now on we're dealing with the MAC, which conceptually has 13 + * bytes of `header' before the start of the data (TLS) or 71/75 bytes + * (SSLv3) */ + len = data_plus_mac_plus_padding_size + header_length; + /* max_mac_bytes contains the maximum bytes of bytes in the MAC, including + * |header|, assuming that there's no padding. */ + max_mac_bytes = len - md_size - 1; + /* num_blocks is the maximum number of hash blocks. */ + num_blocks = (max_mac_bytes + 1 + md_length_size + md_block_size - 1) / md_block_size; + /* In order to calculate the MAC in constant time we have to handle + * the final blocks specially because the padding value could cause the + * end to appear somewhere in the final |variance_blocks| blocks and we + * can't leak where. However, |num_starting_blocks| worth of data can + * be hashed right away because no padding value can affect whether + * they are plaintext. */ + num_starting_blocks = 0; + /* k is the starting byte offset into the conceptual header||data where + * we start processing. */ + k = 0; + /* mac_end_offset is the index just past the end of the data to be + * MACed. */ + mac_end_offset = data_plus_mac_size + header_length - md_size; + /* c is the index of the 0x80 byte in the final hash block that + * contains application data. */ + c = mac_end_offset % md_block_size; + /* index_a is the hash block number that contains the 0x80 terminating + * value. */ + index_a = mac_end_offset / md_block_size; + /* index_b is the hash block number that contains the 64-bit hash + * length, in bits. */ + index_b = (mac_end_offset + md_length_size) / md_block_size; + /* bits is the hash-length in bits. It includes the additional hash + * block for the masked HMAC key, or whole of |header| in the case of + * SSLv3. */ + + /* For SSLv3, if we're going to have any starting blocks then we need + * at least two because the header is larger than a single block. */ + if (num_blocks > variance_blocks + (is_sslv3 ? 1 : 0)) + { + num_starting_blocks = num_blocks - variance_blocks; + k = md_block_size*num_starting_blocks; + } + + bits = 8*mac_end_offset; + if (!is_sslv3) + { + /* Compute the initial HMAC block. For SSLv3, the padding and + * secret bytes are included in |header| because they take more + * than a single block. */ + bits += 8*md_block_size; + memset(hmac_pad, 0, md_block_size); + OPENSSL_assert(mac_secret_length <= sizeof(hmac_pad)); + memcpy(hmac_pad, mac_secret, mac_secret_length); + for (i = 0; i < md_block_size; i++) + hmac_pad[i] ^= 0x36; + + md_transform(md_state.c, hmac_pad); + } + + if (length_is_big_endian) + { + memset(length_bytes,0,md_length_size-4); + length_bytes[md_length_size-4] = (unsigned char)(bits>>24); + length_bytes[md_length_size-3] = (unsigned char)(bits>>16); + length_bytes[md_length_size-2] = (unsigned char)(bits>>8); + length_bytes[md_length_size-1] = (unsigned char)bits; + } + else + { + memset(length_bytes,0,md_length_size); + length_bytes[md_length_size-5] = (unsigned char)(bits>>24); + length_bytes[md_length_size-6] = (unsigned char)(bits>>16); + length_bytes[md_length_size-7] = (unsigned char)(bits>>8); + length_bytes[md_length_size-8] = (unsigned char)bits; + } + + if (k > 0) + { + if (is_sslv3) + { + /* The SSLv3 header is larger than a single block. + * overhang is the number of bytes beyond a single + * block that the header consumes: either 7 bytes + * (SHA1) or 11 bytes (MD5). */ + unsigned overhang = header_length-md_block_size; + md_transform(md_state.c, header); + memcpy(first_block, header + md_block_size, overhang); + memcpy(first_block + overhang, data, md_block_size-overhang); + md_transform(md_state.c, first_block); + for (i = 1; i < k/md_block_size - 1; i++) + md_transform(md_state.c, data + md_block_size*i - overhang); + } + else + { + /* k is a multiple of md_block_size. */ + memcpy(first_block, header, 13); + memcpy(first_block+13, data, md_block_size-13); + md_transform(md_state.c, first_block); + for (i = 1; i < k/md_block_size; i++) + md_transform(md_state.c, data + md_block_size*i - 13); + } + } + + memset(mac_out, 0, sizeof(mac_out)); + + /* We now process the final hash blocks. For each block, we construct + * it in constant time. If the |i==index_a| then we'll include the 0x80 + * bytes and zero pad etc. For each block we selectively copy it, in + * constant time, to |mac_out|. */ + for (i = num_starting_blocks; i <= num_starting_blocks+variance_blocks; i++) + { + unsigned char block[MAX_HASH_BLOCK_SIZE]; + unsigned char is_block_a = constant_time_eq_8(i, index_a); + unsigned char is_block_b = constant_time_eq_8(i, index_b); + for (j = 0; j < md_block_size; j++) + { + unsigned char b = 0, is_past_c, is_past_cp1; + if (k < header_length) + b = header[k]; + else if (k < data_plus_mac_plus_padding_size + header_length) + b = data[k-header_length]; + k++; + + is_past_c = is_block_a & constant_time_ge(j, c); + is_past_cp1 = is_block_a & constant_time_ge(j, c+1); + /* If this is the block containing the end of the + * application data, and we are at the offset for the + * 0x80 value, then overwrite b with 0x80. */ + b = (b&~is_past_c) | (0x80&is_past_c); + /* If this the the block containing the end of the + * application data and we're past the 0x80 value then + * just write zero. */ + b = b&~is_past_cp1; + /* If this is index_b (the final block), but not + * index_a (the end of the data), then the 64-bit + * length didn't fit into index_a and we're having to + * add an extra block of zeros. */ + b &= ~is_block_b | is_block_a; + + /* The final bytes of one of the blocks contains the + * length. */ + if (j >= md_block_size - md_length_size) + { + /* If this is index_b, write a length byte. */ + b = (b&~is_block_b) | (is_block_b&length_bytes[j-(md_block_size-md_length_size)]); + } + block[j] = b; + } + + md_transform(md_state.c, block); + md_final_raw(md_state.c, block); + /* If this is index_b, copy the hash value to |mac_out|. */ + for (j = 0; j < md_size; j++) + mac_out[j] |= block[j]&is_block_b; + } + + EVP_MD_CTX_init(&md_ctx); + EVP_DigestInit_ex(&md_ctx, ctx->digest, NULL /* engine */); + if (is_sslv3) + { + /* We repurpose |hmac_pad| to contain the SSLv3 pad2 block. */ + memset(hmac_pad, 0x5c, sslv3_pad_length); + + EVP_DigestUpdate(&md_ctx, mac_secret, mac_secret_length); + EVP_DigestUpdate(&md_ctx, hmac_pad, sslv3_pad_length); + EVP_DigestUpdate(&md_ctx, mac_out, md_size); + } + else + { + /* Complete the HMAC in the standard manner. */ + for (i = 0; i < md_block_size; i++) + hmac_pad[i] ^= 0x6a; + + EVP_DigestUpdate(&md_ctx, hmac_pad, md_block_size); + EVP_DigestUpdate(&md_ctx, mac_out, md_size); + } + EVP_DigestFinal(&md_ctx, md_out, &md_out_size_u); + if (md_out_size) + *md_out_size = md_out_size_u; + EVP_MD_CTX_cleanup(&md_ctx); + } + +#ifdef OPENSSL_FIPS + +/* Due to the need to use EVP in FIPS mode we can't reimplement digests but + * we can ensure the number of blocks processed is equal for all cases + * by digesting additional data. + */ + +void tls_fips_digest_extra( + const EVP_CIPHER_CTX *cipher_ctx, EVP_MD_CTX *mac_ctx, + const unsigned char *data, size_t data_len, size_t orig_len) + { + size_t block_size, digest_pad, blocks_data, blocks_orig; + if (EVP_CIPHER_CTX_mode(cipher_ctx) != EVP_CIPH_CBC_MODE) + return; + block_size = EVP_MD_CTX_block_size(mac_ctx); + /* We are in FIPS mode if we get this far so we know we have only SHA* + * digests and TLS to deal with. + * Minimum digest padding length is 17 for SHA384/SHA512 and 9 + * otherwise. + * Additional header is 13 bytes. To get the number of digest blocks + * processed round up the amount of data plus padding to the nearest + * block length. Block length is 128 for SHA384/SHA512 and 64 otherwise. + * So we have: + * blocks = (payload_len + digest_pad + 13 + block_size - 1)/block_size + * equivalently: + * blocks = (payload_len + digest_pad + 12)/block_size + 1 + * HMAC adds a constant overhead. + * We're ultimately only interested in differences so this becomes + * blocks = (payload_len + 29)/128 + * for SHA384/SHA512 and + * blocks = (payload_len + 21)/64 + * otherwise. + */ + digest_pad = block_size == 64 ? 21 : 29; + blocks_orig = (orig_len + digest_pad)/block_size; + blocks_data = (data_len + digest_pad)/block_size; + /* MAC enough blocks to make up the difference between the original + * and actual lengths plus one extra block to ensure this is never a + * no op. The "data" pointer should always have enough space to + * perform this operation as it is large enough for a maximum + * length TLS buffer. + */ + EVP_DigestSignUpdate(mac_ctx, data, + (blocks_orig - blocks_data + 1) * block_size); + } +#endif diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c index b80d052e1f5..344e2eb1af8 100644 --- a/ssl/s3_clnt.c +++ b/ssl/s3_clnt.c @@ -459,7 +459,6 @@ int ssl3_connect(SSL *s) SSL3_ST_CW_CHANGE_A,SSL3_ST_CW_CHANGE_B); if (ret <= 0) goto end; - #if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG) s->state=SSL3_ST_CW_FINISHED_A; #else @@ -987,7 +986,10 @@ int ssl3_get_server_hello(SSL *s) * client authentication. */ if (TLS1_get_version(s) < TLS1_2_VERSION && !ssl3_digest_cached_records(s)) + { + al = SSL_AD_INTERNAL_ERROR; goto f_err; + } /* lets get the compression algorithm */ /* COMPRESSION */ #ifdef OPENSSL_NO_COMP diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c index c5df2cb90ae..e3cd4f062c5 100644 --- a/ssl/s3_enc.c +++ b/ssl/s3_enc.c @@ -466,12 +466,21 @@ void ssl3_cleanup_key_block(SSL *s) s->s3->tmp.key_block_length=0; } +/* ssl3_enc encrypts/decrypts the record in |s->wrec| / |s->rrec|, respectively. + * + * Returns: + * 0: (in non-constant time) if the record is publically invalid (i.e. too + * short etc). + * 1: if the record's padding is valid / the encryption was successful. + * -1: if the record's padding is invalid or, if sending, an internal error + * occured. + */ int ssl3_enc(SSL *s, int send) { SSL3_RECORD *rec; EVP_CIPHER_CTX *ds; unsigned long l; - int bs,i; + int bs,i,mac_size=0; const EVP_CIPHER *enc; if (send) @@ -522,32 +531,16 @@ int ssl3_enc(SSL *s, int send) if (!send) { if (l == 0 || l%bs != 0) - { - SSLerr(SSL_F_SSL3_ENC,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG); - ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECRYPTION_FAILED); return 0; - } /* otherwise, rec->length >= bs */ } EVP_Cipher(ds,rec->data,rec->input,l); + if (EVP_MD_CTX_md(s->read_hash) != NULL) + mac_size = EVP_MD_CTX_size(s->read_hash); if ((bs != 1) && !send) - { - i=rec->data[l-1]+1; - /* SSL 3.0 bounds the number of padding bytes by the block size; - * padding bytes (except the last one) are arbitrary */ - if (i > bs) - { - /* Incorrect padding. SSLerr() and ssl3_alert are done - * by caller: we don't want to reveal whether this is - * a decryption error or a MAC verification failure - * (see http://www.openssl.org/~bodo/tls-cbc.txt) */ - return -1; - } - /* now i <= bs <= rec->length */ - rec->length-=i; - } + return ssl3_cbc_remove_padding(s, rec, bs, mac_size); } return(1); } @@ -716,7 +709,7 @@ int n_ssl3_mac(SSL *ssl, unsigned char *md, int send) EVP_MD_CTX md_ctx; const EVP_MD_CTX *hash; unsigned char *p,rec_char; - unsigned int md_size; + size_t md_size, orig_len; int npad; int t; @@ -741,28 +734,72 @@ int n_ssl3_mac(SSL *ssl, unsigned char *md, int send) md_size=t; npad=(48/md_size)*md_size; - /* Chop the digest off the end :-) */ - EVP_MD_CTX_init(&md_ctx); + /* kludge: ssl3_cbc_remove_padding passes padding length in rec->type */ + orig_len = rec->length+md_size+((unsigned int)rec->type>>8); + rec->type &= 0xff; - EVP_MD_CTX_copy_ex( &md_ctx,hash); - EVP_DigestUpdate(&md_ctx,mac_sec,md_size); - EVP_DigestUpdate(&md_ctx,ssl3_pad_1,npad); - EVP_DigestUpdate(&md_ctx,seq,8); - rec_char=rec->type; - EVP_DigestUpdate(&md_ctx,&rec_char,1); - p=md; - s2n(rec->length,p); - EVP_DigestUpdate(&md_ctx,md,2); - EVP_DigestUpdate(&md_ctx,rec->input,rec->length); - EVP_DigestFinal_ex( &md_ctx,md,NULL); + if (!send && + EVP_CIPHER_CTX_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE && + ssl3_cbc_record_digest_supported(hash)) + { + /* This is a CBC-encrypted record. We must avoid leaking any + * timing-side channel information about how many blocks of + * data we are hashing because that gives an attacker a + * timing-oracle. */ - EVP_MD_CTX_copy_ex( &md_ctx,hash); - EVP_DigestUpdate(&md_ctx,mac_sec,md_size); - EVP_DigestUpdate(&md_ctx,ssl3_pad_2,npad); - EVP_DigestUpdate(&md_ctx,md,md_size); - EVP_DigestFinal_ex( &md_ctx,md,&md_size); + /* npad is, at most, 48 bytes and that's with MD5: + * 16 + 48 + 8 (sequence bytes) + 1 + 2 = 75. + * + * With SHA-1 (the largest hash speced for SSLv3) the hash size + * goes up 4, but npad goes down by 8, resulting in a smaller + * total size. */ + unsigned char header[75]; + unsigned j = 0; + memcpy(header+j, mac_sec, md_size); + j += md_size; + memcpy(header+j, ssl3_pad_1, npad); + j += npad; + memcpy(header+j, seq, 8); + j += 8; + header[j++] = rec->type; + header[j++] = rec->length >> 8; + header[j++] = rec->length & 0xff; - EVP_MD_CTX_cleanup(&md_ctx); + ssl3_cbc_digest_record( + hash, + md, &md_size, + header, rec->input, + rec->length + md_size, orig_len, + mac_sec, md_size, + 1 /* is SSLv3 */); + } + else + { + unsigned int md_size_u; + /* Chop the digest off the end :-) */ + EVP_MD_CTX_init(&md_ctx); + + EVP_MD_CTX_copy_ex( &md_ctx,hash); + EVP_DigestUpdate(&md_ctx,mac_sec,md_size); + EVP_DigestUpdate(&md_ctx,ssl3_pad_1,npad); + EVP_DigestUpdate(&md_ctx,seq,8); + rec_char=rec->type; + EVP_DigestUpdate(&md_ctx,&rec_char,1); + p=md; + s2n(rec->length,p); + EVP_DigestUpdate(&md_ctx,md,2); + EVP_DigestUpdate(&md_ctx,rec->input,rec->length); + EVP_DigestFinal_ex( &md_ctx,md,NULL); + + EVP_MD_CTX_copy_ex( &md_ctx,hash); + EVP_DigestUpdate(&md_ctx,mac_sec,md_size); + EVP_DigestUpdate(&md_ctx,ssl3_pad_2,npad); + EVP_DigestUpdate(&md_ctx,md,md_size); + EVP_DigestFinal_ex( &md_ctx,md,&md_size_u); + md_size = md_size_u; + + EVP_MD_CTX_cleanup(&md_ctx); + } ssl3_record_sequence_update(seq); return(md_size); diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index fb60cde8eed..e7c5dcb809f 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -1125,7 +1125,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={ 0, /* not implemented (non-ephemeral DH) */ TLS1_TXT_DH_DSS_WITH_AES_128_SHA256, TLS1_CK_DH_DSS_WITH_AES_128_SHA256, - SSL_kDHr, + SSL_kDHd, SSL_aDH, SSL_AES128, SSL_SHA256, @@ -1407,7 +1407,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={ 0, /* not implemented (non-ephemeral DH) */ TLS1_TXT_DH_DSS_WITH_AES_256_SHA256, TLS1_CK_DH_DSS_WITH_AES_256_SHA256, - SSL_kDHr, + SSL_kDHd, SSL_aDH, SSL_AES256, SSL_SHA256, @@ -1958,7 +1958,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={ 0, TLS1_TXT_DH_DSS_WITH_AES_128_GCM_SHA256, TLS1_CK_DH_DSS_WITH_AES_128_GCM_SHA256, - SSL_kDHr, + SSL_kDHd, SSL_aDH, SSL_AES128GCM, SSL_AEAD, @@ -1974,7 +1974,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={ 0, TLS1_TXT_DH_DSS_WITH_AES_256_GCM_SHA384, TLS1_CK_DH_DSS_WITH_AES_256_GCM_SHA384, - SSL_kDHr, + SSL_kDHd, SSL_aDH, SSL_AES256GCM, SSL_AEAD, @@ -2669,7 +2669,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={ 1, TLS1_TXT_ECDH_RSA_WITH_AES_128_SHA256, TLS1_CK_ECDH_RSA_WITH_AES_128_SHA256, - SSL_kECDHe, + SSL_kECDHr, SSL_aECDH, SSL_AES128, SSL_SHA256, @@ -2685,7 +2685,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={ 1, TLS1_TXT_ECDH_RSA_WITH_AES_256_SHA384, TLS1_CK_ECDH_RSA_WITH_AES_256_SHA384, - SSL_kECDHe, + SSL_kECDHr, SSL_aECDH, SSL_AES256, SSL_SHA384, @@ -2799,7 +2799,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={ 1, TLS1_TXT_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLS1_CK_ECDH_RSA_WITH_AES_128_GCM_SHA256, - SSL_kECDHe, + SSL_kECDHr, SSL_aECDH, SSL_AES128GCM, SSL_AEAD, @@ -2815,7 +2815,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={ 1, TLS1_TXT_ECDH_RSA_WITH_AES_256_GCM_SHA384, TLS1_CK_ECDH_RSA_WITH_AES_256_GCM_SHA384, - SSL_kECDHe, + SSL_kECDHr, SSL_aECDH, SSL_AES256GCM, SSL_AEAD, diff --git a/ssl/s3_pkt.c b/ssl/s3_pkt.c index adf8c387cc0..804291e27c3 100644 --- a/ssl/s3_pkt.c +++ b/ssl/s3_pkt.c @@ -290,11 +290,8 @@ static int ssl3_get_record(SSL *s) unsigned char *p; unsigned char md[EVP_MAX_MD_SIZE]; short version; - int mac_size; - int clear=0; + unsigned mac_size, orig_len; size_t extra; - int decryption_failed_or_bad_record_mac = 0; - unsigned char *mac = NULL; rr= &(s->s3->rrec); sess=s->session; @@ -403,17 +400,15 @@ fprintf(stderr, "Record type=%d, Length=%d\n", rr->type, rr->length); rr->data=rr->input; enc_err = s->method->ssl3_enc->enc(s,0); - if (enc_err <= 0) + /* enc_err is: + * 0: (in non-constant time) if the record is publically invalid. + * 1: if the padding is valid + * -1: if the padding is invalid */ + if (enc_err == 0) { - if (enc_err == 0) - /* SSLerr() and ssl3_send_alert() have been called */ - goto err; - - /* Otherwise enc_err == -1, which indicates bad padding - * (rec->length has not been changed in this case). - * To minimize information leaked via timing, we will perform - * the MAC computation anyway. */ - decryption_failed_or_bad_record_mac = 1; + al=SSL_AD_DECRYPTION_FAILED; + SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG); + goto f_err; } #ifdef TLS_DEBUG @@ -423,53 +418,62 @@ printf("\n"); #endif /* r->length is now the compressed data plus mac */ - if ( (sess == NULL) || - (s->enc_read_ctx == NULL) || - (EVP_MD_CTX_md(s->read_hash) == NULL)) - clear=1; - - if (!clear) + if ((sess != NULL) && + (s->enc_read_ctx != NULL) && + (EVP_MD_CTX_md(s->read_hash) != NULL)) { - /* !clear => s->read_hash != NULL => mac_size != -1 */ + /* s->read_hash != NULL => mac_size != -1 */ + unsigned char *mac = NULL; + unsigned char mac_tmp[EVP_MAX_MD_SIZE]; mac_size=EVP_MD_CTX_size(s->read_hash); - OPENSSL_assert(mac_size >= 0); + OPENSSL_assert(mac_size <= EVP_MAX_MD_SIZE); - if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+extra+mac_size) + /* kludge: *_cbc_remove_padding passes padding length in rr->type */ + orig_len = rr->length+((unsigned int)rr->type>>8); + + /* orig_len is the length of the record before any padding was + * removed. This is public information, as is the MAC in use, + * therefore we can safely process the record in a different + * amount of time if it's too short to possibly contain a MAC. + */ + if (orig_len < mac_size || + /* CBC records must have a padding length byte too. */ + (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE && + orig_len < mac_size+1)) { -#if 0 /* OK only for stream ciphers (then rr->length is visible from ciphertext anyway) */ - al=SSL_AD_RECORD_OVERFLOW; - SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_PRE_MAC_LENGTH_TOO_LONG); - goto f_err; -#else - decryption_failed_or_bad_record_mac = 1; -#endif - } - /* check the MAC for rr->input (it's in mac_size bytes at the tail) */ - if (rr->length >= (unsigned int)mac_size) - { - rr->length -= mac_size; - mac = &rr->data[rr->length]; - } - else - { - /* record (minus padding) is too short to contain a MAC */ -#if 0 /* OK only for stream ciphers */ al=SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_LENGTH_TOO_SHORT); goto f_err; -#else - decryption_failed_or_bad_record_mac = 1; - rr->length = 0; -#endif } - i=s->method->ssl3_enc->mac(s,md,0); - if (i < 0 || mac == NULL || memcmp(md, mac, (size_t)mac_size) != 0) + + if (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE) { - decryption_failed_or_bad_record_mac = 1; + /* We update the length so that the TLS header bytes + * can be constructed correctly but we need to extract + * the MAC in constant time from within the record, + * without leaking the contents of the padding bytes. + * */ + mac = mac_tmp; + ssl3_cbc_copy_mac(mac_tmp, rr, mac_size, orig_len); + rr->length -= mac_size; } + else + { + /* In this case there's no padding, so |orig_len| + * equals |rec->length| and we checked that there's + * enough bytes for |mac_size| above. */ + rr->length -= mac_size; + mac = &rr->data[rr->length]; + } + + i=s->method->ssl3_enc->mac(s,md,0 /* not send */); + if (i < 0 || mac == NULL || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0) + enc_err = -1; + if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+extra+mac_size) + enc_err = -1; } - if (decryption_failed_or_bad_record_mac) + if (enc_err < 0) { /* A separate 'decryption_failed' alert was introduced with TLS 1.0, * SSL 3.0 only has 'bad_record_mac'. But unless a decryption @@ -744,6 +748,7 @@ static int do_ssl3_write(SSL *s, int type, const unsigned char *buf, * bytes and record version number > TLS 1.0 */ if (s->state == SSL3_ST_CW_CLNT_HELLO_B + && !s->renegotiate && TLS1_get_version(s) > TLS1_VERSION) *(p++) = 0x1; else @@ -1238,7 +1243,7 @@ start: goto f_err; } #ifdef SSL_AD_MISSING_SRP_USERNAME - if (alert_descr == SSL_AD_MISSING_SRP_USERNAME) + else if (alert_descr == SSL_AD_MISSING_SRP_USERNAME) return(0); #endif } diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index 118939fabb1..bfb84805400 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -191,7 +191,8 @@ static int ssl_check_srp_ext_ClientHello(SSL *s, int *al) { if(s->srp_ctx.login == NULL) { - /* There isn't any srp login extension !!! */ + /* RFC 5054 says SHOULD reject, + we do so if There is no srp login name */ ret = SSL3_AL_FATAL; *al = SSL_AD_UNKNOWN_PSK_IDENTITY; } @@ -378,6 +379,7 @@ int ssl3_accept(SSL *s) } } #endif + s->renegotiate = 2; s->state=SSL3_ST_SW_SRVR_HELLO_A; s->init_num=0; @@ -1181,7 +1183,7 @@ int ssl3_get_client_hello(SSL *s) goto f_err; } } - if (ssl_check_clienthello_tlsext(s) <= 0) { + if (ssl_check_clienthello_tlsext_early(s) <= 0) { SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT); goto err; } @@ -1389,7 +1391,10 @@ int ssl3_get_client_hello(SSL *s) if (TLS1_get_version(s) < TLS1_2_VERSION || !(s->verify_mode & SSL_VERIFY_PEER)) { if (!ssl3_digest_cached_records(s)) + { + al = SSL_AD_INTERNAL_ERROR; goto f_err; + } } /* we now have the following setup. @@ -1403,6 +1408,16 @@ int ssl3_get_client_hello(SSL *s) * s->tmp.new_cipher - the new cipher to use. */ + /* Handles TLS extensions that we couldn't check earlier */ + if (s->version >= SSL3_VERSION) + { + if (ssl_check_clienthello_tlsext_late(s) <= 0) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_CLIENTHELLO_TLSEXT); + goto err; + } + } + if (ret < 0) ret=1; if (0) { diff --git a/ssl/ssl.h b/ssl/ssl.h index 8b0c2a2dac4..593579ed367 100644 --- a/ssl/ssl.h +++ b/ssl/ssl.h @@ -493,6 +493,9 @@ struct ssl_session_st char *psk_identity_hint; char *psk_identity; #endif + /* Used to indicate that session resumption is not allowed. + * Applications can also set this bit for a new session via + * not_resumable_session_cb to disable session caching and tickets. */ int not_resumable; /* The cert is the certificate used to establish this connection */ @@ -535,7 +538,7 @@ struct ssl_session_st #endif /* OPENSSL_NO_EC */ /* RFC4507 info */ unsigned char *tlsext_tick; /* Session ticket */ - size_t tlsext_ticklen; /* Session ticket length */ + size_t tlsext_ticklen; /* Session ticket length */ long tlsext_tick_lifetime_hint; /* Session lifetime hint in seconds */ #endif #ifndef OPENSSL_NO_SRP @@ -927,6 +930,7 @@ struct ssl_ctx_st /* Callback for status request */ int (*tlsext_status_cb)(SSL *ssl, void *arg); void *tlsext_status_arg; + /* draft-rescorla-tls-opaque-prf-input-00.txt information */ int (*tlsext_opaque_prf_input_callback)(SSL *, void *peerinput, size_t len, void *arg); void *tlsext_opaque_prf_input_callback_arg; @@ -952,6 +956,7 @@ struct ssl_ctx_st #endif #ifndef OPENSSL_NO_TLSEXT + # ifndef OPENSSL_NO_NEXTPROTONEG /* Next protocol negotiation information */ /* (for experimental NPN extension). */ @@ -2206,6 +2211,7 @@ void ERR_load_SSL_strings(void); #define SSL_F_SSL_GET_NEW_SESSION 181 #define SSL_F_SSL_GET_PREV_SESSION 217 #define SSL_F_SSL_GET_SERVER_SEND_CERT 182 +#define SSL_F_SSL_GET_SERVER_SEND_PKEY 317 #define SSL_F_SSL_GET_SIGN_PKEY 183 #define SSL_F_SSL_INIT_WBIO_BUFFER 184 #define SSL_F_SSL_LOAD_CLIENT_CA_FILE 185 diff --git a/ssl/ssl3.h b/ssl/ssl3.h index 112e627de08..247e88c2d63 100644 --- a/ssl/ssl3.h +++ b/ssl/ssl3.h @@ -578,8 +578,10 @@ typedef struct ssl3_state_st #define SSL3_ST_CW_CERT_VRFY_B (0x191|SSL_ST_CONNECT) #define SSL3_ST_CW_CHANGE_A (0x1A0|SSL_ST_CONNECT) #define SSL3_ST_CW_CHANGE_B (0x1A1|SSL_ST_CONNECT) +#ifndef OPENSSL_NO_NEXTPROTONEG #define SSL3_ST_CW_NEXT_PROTO_A (0x200|SSL_ST_CONNECT) #define SSL3_ST_CW_NEXT_PROTO_B (0x201|SSL_ST_CONNECT) +#endif #define SSL3_ST_CW_FINISHED_A (0x1B0|SSL_ST_CONNECT) #define SSL3_ST_CW_FINISHED_B (0x1B1|SSL_ST_CONNECT) /* read from server */ @@ -629,8 +631,10 @@ typedef struct ssl3_state_st #define SSL3_ST_SR_CERT_VRFY_B (0x1A1|SSL_ST_ACCEPT) #define SSL3_ST_SR_CHANGE_A (0x1B0|SSL_ST_ACCEPT) #define SSL3_ST_SR_CHANGE_B (0x1B1|SSL_ST_ACCEPT) +#ifndef OPENSSL_NO_NEXTPROTONEG #define SSL3_ST_SR_NEXT_PROTO_A (0x210|SSL_ST_ACCEPT) #define SSL3_ST_SR_NEXT_PROTO_B (0x211|SSL_ST_ACCEPT) +#endif #define SSL3_ST_SR_FINISHED_A (0x1C0|SSL_ST_ACCEPT) #define SSL3_ST_SR_FINISHED_B (0x1C1|SSL_ST_ACCEPT) /* write to client */ @@ -655,7 +659,9 @@ typedef struct ssl3_state_st #define SSL3_MT_CLIENT_KEY_EXCHANGE 16 #define SSL3_MT_FINISHED 20 #define SSL3_MT_CERTIFICATE_STATUS 22 +#ifndef OPENSSL_NO_NEXTPROTONEG #define SSL3_MT_NEXT_PROTO 67 +#endif #define DTLS1_MT_HELLO_VERIFY_REQUEST 3 diff --git a/ssl/ssl_algs.c b/ssl/ssl_algs.c index d443143c593..9c34d19725b 100644 --- a/ssl/ssl_algs.c +++ b/ssl/ssl_algs.c @@ -94,6 +94,7 @@ int SSL_library_init(void) EVP_add_cipher(EVP_aes_128_cbc_hmac_sha1()); EVP_add_cipher(EVP_aes_256_cbc_hmac_sha1()); #endif + #endif #ifndef OPENSSL_NO_CAMELLIA EVP_add_cipher(EVP_camellia_128_cbc()); diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c index 917be318760..5123a89182e 100644 --- a/ssl/ssl_cert.c +++ b/ssl/ssl_cert.c @@ -164,14 +164,14 @@ static void ssl_cert_set_default_md(CERT *cert) { /* Set digest values to defaults */ #ifndef OPENSSL_NO_DSA - cert->pkeys[SSL_PKEY_DSA_SIGN].digest = EVP_dss1(); + cert->pkeys[SSL_PKEY_DSA_SIGN].digest = EVP_sha1(); #endif #ifndef OPENSSL_NO_RSA cert->pkeys[SSL_PKEY_RSA_SIGN].digest = EVP_sha1(); cert->pkeys[SSL_PKEY_RSA_ENC].digest = EVP_sha1(); #endif #ifndef OPENSSL_NO_ECDSA - cert->pkeys[SSL_PKEY_ECC].digest = EVP_ecdsa(); + cert->pkeys[SSL_PKEY_ECC].digest = EVP_sha1(); #endif } diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c index 92d1e94d6a9..0aba8e048c5 100644 --- a/ssl/ssl_ciph.c +++ b/ssl/ssl_ciph.c @@ -312,6 +312,7 @@ static const SSL_CIPHER cipher_aliases[]={ {0,SSL_TXT_SSLV2,0, 0,0,0,0,SSL_SSLV2, 0,0,0,0}, {0,SSL_TXT_SSLV3,0, 0,0,0,0,SSL_SSLV3, 0,0,0,0}, {0,SSL_TXT_TLSV1,0, 0,0,0,0,SSL_TLSV1, 0,0,0,0}, + {0,SSL_TXT_TLSV1_2,0, 0,0,0,0,SSL_TLSV1_2, 0,0,0,0}, /* export flag */ {0,SSL_TXT_EXP,0, 0,0,0,0,0,SSL_EXPORT,0,0,0}, @@ -1150,9 +1151,9 @@ static int ssl_cipher_process_rulestr(const char *rule_str, while ( ((ch >= 'A') && (ch <= 'Z')) || ((ch >= '0') && (ch <= '9')) || ((ch >= 'a') && (ch <= 'z')) || - (ch == '-')) + (ch == '-') || (ch == '.')) #else - while ( isalnum(ch) || (ch == '-')) + while ( isalnum(ch) || (ch == '-') || (ch == '.')) #endif { ch = *(++l); diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c index 2577c6895ab..370fb57e3b8 100644 --- a/ssl/ssl_err.c +++ b/ssl/ssl_err.c @@ -228,6 +228,7 @@ static ERR_STRING_DATA SSL_str_functs[]= {ERR_FUNC(SSL_F_SSL_GET_NEW_SESSION), "SSL_GET_NEW_SESSION"}, {ERR_FUNC(SSL_F_SSL_GET_PREV_SESSION), "SSL_GET_PREV_SESSION"}, {ERR_FUNC(SSL_F_SSL_GET_SERVER_SEND_CERT), "SSL_GET_SERVER_SEND_CERT"}, +{ERR_FUNC(SSL_F_SSL_GET_SERVER_SEND_PKEY), "SSL_GET_SERVER_SEND_PKEY"}, {ERR_FUNC(SSL_F_SSL_GET_SIGN_PKEY), "SSL_GET_SIGN_PKEY"}, {ERR_FUNC(SSL_F_SSL_INIT_WBIO_BUFFER), "SSL_INIT_WBIO_BUFFER"}, {ERR_FUNC(SSL_F_SSL_LOAD_CLIENT_CA_FILE), "SSL_load_client_CA_file"}, diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index f82d071d6e7..14d143da044 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -597,8 +597,10 @@ void SSL_free(SSL *s) OPENSSL_free(s->next_proto_negotiated); #endif +#ifndef OPENSSL_NO_SRTP if (s->srtp_profiles) sk_SRTP_PROTECTION_PROFILE_free(s->srtp_profiles); +#endif OPENSSL_free(s); } @@ -1952,8 +1954,10 @@ void SSL_CTX_free(SSL_CTX *a) a->comp_methods = NULL; #endif +#ifndef OPENSSL_NO_SRTP if (a->srtp_profiles) sk_SRTP_PROTECTION_PROFILE_free(a->srtp_profiles); +#endif #ifndef OPENSSL_NO_PSK if (a->psk_identity_hint) @@ -2287,7 +2291,7 @@ int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s) #endif /* THIS NEEDS CLEANING UP */ -X509 *ssl_get_server_send_cert(SSL *s) +CERT_PKEY *ssl_get_server_send_pkey(const SSL *s) { unsigned long alg_k,alg_a; CERT *c; @@ -2342,12 +2346,20 @@ X509 *ssl_get_server_send_cert(SSL *s) i=SSL_PKEY_GOST01; else /* if (alg_a & SSL_aNULL) */ { - SSLerr(SSL_F_SSL_GET_SERVER_SEND_CERT,ERR_R_INTERNAL_ERROR); + SSLerr(SSL_F_SSL_GET_SERVER_SEND_PKEY,ERR_R_INTERNAL_ERROR); return(NULL); } - if (c->pkeys[i].x509 == NULL) return(NULL); - return(c->pkeys[i].x509); + return c->pkeys + i; + } + +X509 *ssl_get_server_send_cert(const SSL *s) + { + CERT_PKEY *cpk; + cpk = ssl_get_server_send_pkey(s); + if (!cpk) + return NULL; + return cpk->x509; } EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *cipher, const EVP_MD **pmd) @@ -2608,7 +2620,7 @@ const char *SSL_get_version(const SSL *s) return("TLSv1.2"); else if (s->version == TLS1_1_VERSION) return("TLSv1.1"); - if (s->version == TLS1_VERSION) + else if (s->version == TLS1_VERSION) return("TLSv1"); else if (s->version == SSL3_VERSION) return("SSLv3"); @@ -2780,7 +2792,9 @@ void ssl_clear_cipher_ctx(SSL *s) /* Fix this function so that it takes an optional type parameter */ X509 *SSL_get_certificate(const SSL *s) { - if (s->cert != NULL) + if (s->server) + return(ssl_get_server_send_cert(s)); + else if (s->cert != NULL) return(s->cert->key->x509); else return(NULL); diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index d87fd51cfa8..1b98947e677 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -215,6 +215,15 @@ *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ *((c)++)=(unsigned char)(((l) )&0xff)) +#define l2n8(l,c) (*((c)++)=(unsigned char)(((l)>>56)&0xff), \ + *((c)++)=(unsigned char)(((l)>>48)&0xff), \ + *((c)++)=(unsigned char)(((l)>>40)&0xff), \ + *((c)++)=(unsigned char)(((l)>>32)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff)) + #define n2l6(c,l) (l =((BN_ULLONG)(*((c)++)))<<40, \ l|=((BN_ULLONG)(*((c)++)))<<32, \ l|=((BN_ULLONG)(*((c)++)))<<24, \ @@ -830,7 +839,8 @@ int ssl_verify_cert_chain(SSL *s,STACK_OF(X509) *sk); int ssl_undefined_function(SSL *s); int ssl_undefined_void_function(void); int ssl_undefined_const_function(const SSL *s); -X509 *ssl_get_server_send_cert(SSL *); +CERT_PKEY *ssl_get_server_send_pkey(const SSL *s); +X509 *ssl_get_server_send_cert(const SSL *); EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *c, const EVP_MD **pmd); int ssl_cert_type(X509 *x,EVP_PKEY *pkey); void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher); @@ -1088,7 +1098,8 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **data, unsigned char *d, int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **data, unsigned char *d, int n, int *al); int ssl_prepare_clienthello_tlsext(SSL *s); int ssl_prepare_serverhello_tlsext(SSL *s); -int ssl_check_clienthello_tlsext(SSL *s); +int ssl_check_clienthello_tlsext_early(SSL *s); +int ssl_check_clienthello_tlsext_late(SSL *s); int ssl_check_serverhello_tlsext(SSL *s); #ifndef OPENSSL_NO_HEARTBEATS @@ -1131,4 +1142,33 @@ int ssl_parse_clienthello_use_srtp_ext(SSL *s, unsigned char *d, int len,int *al int ssl_add_serverhello_use_srtp_ext(SSL *s, unsigned char *p, int *len, int maxlen); int ssl_parse_serverhello_use_srtp_ext(SSL *s, unsigned char *d, int len,int *al); +/* s3_cbc.c */ +void ssl3_cbc_copy_mac(unsigned char* out, + const SSL3_RECORD *rec, + unsigned md_size,unsigned orig_len); +int ssl3_cbc_remove_padding(const SSL* s, + SSL3_RECORD *rec, + unsigned block_size, + unsigned mac_size); +int tls1_cbc_remove_padding(const SSL* s, + SSL3_RECORD *rec, + unsigned block_size, + unsigned mac_size); +char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx); +void ssl3_cbc_digest_record( + const EVP_MD_CTX *ctx, + unsigned char* md_out, + size_t* md_out_size, + const unsigned char header[13], + const unsigned char *data, + size_t data_plus_mac_size, + size_t data_plus_mac_plus_padding_size, + const unsigned char *mac_secret, + unsigned mac_secret_length, + char is_sslv3); + +void tls_fips_digest_extra( + const EVP_CIPHER_CTX *cipher_ctx, EVP_MD_CTX *mac_ctx, + const unsigned char *data, size_t data_len, size_t orig_len); + #endif diff --git a/ssl/ssl_rsa.c b/ssl/ssl_rsa.c index c0960b5712b..60e7b66859d 100644 --- a/ssl/ssl_rsa.c +++ b/ssl/ssl_rsa.c @@ -710,7 +710,7 @@ int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) ERR_clear_error(); /* clear error stack for SSL_CTX_use_certificate() */ - in=BIO_new(BIO_s_file_internal()); + in = BIO_new(BIO_s_file_internal()); if (in == NULL) { SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE,ERR_R_BUF_LIB); @@ -723,14 +723,16 @@ int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) goto end; } - x=PEM_read_bio_X509_AUX(in,NULL,ctx->default_passwd_callback,ctx->default_passwd_callback_userdata); + x=PEM_read_bio_X509_AUX(in,NULL,ctx->default_passwd_callback, + ctx->default_passwd_callback_userdata); if (x == NULL) { SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE,ERR_R_PEM_LIB); goto end; } - ret=SSL_CTX_use_certificate(ctx,x); + ret = SSL_CTX_use_certificate(ctx, x); + if (ERR_peek_error() != 0) ret = 0; /* Key/certificate mismatch doesn't imply ret==0 ... */ if (ret) @@ -742,13 +744,15 @@ int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) int r; unsigned long err; - if (ctx->extra_certs != NULL) + if (ctx->extra_certs != NULL) { sk_X509_pop_free(ctx->extra_certs, X509_free); ctx->extra_certs = NULL; } - while ((ca = PEM_read_bio_X509(in,NULL,ctx->default_passwd_callback,ctx->default_passwd_callback_userdata)) + while ((ca = PEM_read_bio_X509(in, NULL, + ctx->default_passwd_callback, + ctx->default_passwd_callback_userdata)) != NULL) { r = SSL_CTX_add_extra_chain_cert(ctx, ca); diff --git a/ssl/ssltest.c b/ssl/ssltest.c index 0f8fd3902da..316bbb0c958 100644 --- a/ssl/ssltest.c +++ b/ssl/ssltest.c @@ -543,8 +543,8 @@ int main(int argc, char *argv[]) int comp = 0; #ifndef OPENSSL_NO_COMP COMP_METHOD *cm = NULL; -#endif STACK_OF(SSL_COMP) *ssl_comp_methods = NULL; +#endif int test_cipherlist = 0; #ifdef OPENSSL_FIPS int fips_mode=0; diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c index f7bdeb3b9db..809ad2ee1e5 100644 --- a/ssl/t1_enc.c +++ b/ssl/t1_enc.c @@ -361,7 +361,7 @@ int tls1_change_cipher_state(SSL *s, int which) { int i; for (i=0; is3->tmp.key_block_length; i++) - printf("%02x", key_block[i]); printf("\n"); + printf("%02x", s->s3->tmp.key_block[i]); printf("\n"); } #endif /* KSSL_DEBUG */ @@ -667,12 +667,21 @@ err: return(ret); } +/* tls1_enc encrypts/decrypts the record in |s->wrec| / |s->rrec|, respectively. + * + * Returns: + * 0: (in non-constant time) if the record is publically invalid (i.e. too + * short etc). + * 1: if the record's padding is valid / the encryption was successful. + * -1: if the record's padding/AEAD-authenticator is invalid or, if sending, + * an internal error occured. + */ int tls1_enc(SSL *s, int send) { SSL3_RECORD *rec; EVP_CIPHER_CTX *ds; unsigned long l; - int bs,i,ii,j,k,pad=0; + int bs,i,j,k,pad=0,ret,mac_size=0; const EVP_CIPHER *enc; if (send) @@ -729,11 +738,11 @@ int tls1_enc(SSL *s, int send) printf("tls1_enc(%d)\n", send); #endif /* KSSL_DEBUG */ - if ((s->session == NULL) || (ds == NULL) || - (enc == NULL)) + if ((s->session == NULL) || (ds == NULL) || (enc == NULL)) { memmove(rec->data,rec->input,rec->length); rec->input=rec->data; + ret = 1; } else { @@ -797,13 +806,13 @@ int tls1_enc(SSL *s, int send) #ifdef KSSL_DEBUG { - unsigned long ui; + unsigned long ui; printf("EVP_Cipher(ds=%p,rec->data=%p,rec->input=%p,l=%ld) ==>\n", - ds,rec->data,rec->input,l); + ds,rec->data,rec->input,l); printf("\tEVP_CIPHER_CTX: %d buf_len, %d key_len [%d %d], %d iv_len\n", - ds->buf_len, ds->cipher->key_len, - DES_KEY_SZ, DES_SCHEDULE_SZ, - ds->cipher->iv_len); + ds->buf_len, ds->cipher->key_len, + DES_KEY_SZ, DES_SCHEDULE_SZ, + ds->cipher->iv_len); printf("\t\tIV: "); for (i=0; icipher->iv_len; i++) printf("%02X", ds->iv[i]); printf("\n"); @@ -816,13 +825,7 @@ int tls1_enc(SSL *s, int send) if (!send) { if (l == 0 || l%bs != 0) - { - if (s->version >= TLS1_1_VERSION) - return -1; - SSLerr(SSL_F_TLS1_ENC,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG); - ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECRYPTION_FAILED); return 0; - } } i = EVP_Cipher(ds,rec->data,rec->input,l); @@ -839,68 +842,24 @@ int tls1_enc(SSL *s, int send) #ifdef KSSL_DEBUG { - unsigned long i; - printf("\trec->data="); + unsigned long i; + printf("\trec->data="); for (i=0; idata[i]); printf("\n"); - } + printf(" %02x", rec->data[i]); printf("\n"); + } #endif /* KSSL_DEBUG */ + ret = 1; + if (EVP_MD_CTX_md(s->read_hash) != NULL) + mac_size = EVP_MD_CTX_size(s->read_hash); if ((bs != 1) && !send) - { - ii=i=rec->data[l-1]; /* padding_length */ - i++; - /* NB: if compression is in operation the first packet - * may not be of even length so the padding bug check - * cannot be performed. This bug workaround has been - * around since SSLeay so hopefully it is either fixed - * now or no buggy implementation supports compression - * [steve] - */ - if ( (s->options&SSL_OP_TLS_BLOCK_PADDING_BUG) - && !s->expand) - { - /* First packet is even in size, so check */ - if ((memcmp(s->s3->read_sequence, - "\0\0\0\0\0\0\0\0",8) == 0) && !(ii & 1)) - s->s3->flags|=TLS1_FLAGS_TLS_PADDING_BUG; - if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG) - i--; - } - /* TLS 1.0 does not bound the number of padding bytes by the block size. - * All of them must have value 'padding_length'. */ - if (i > (int)rec->length) - { - /* Incorrect padding. SSLerr() and ssl3_alert are done - * by caller: we don't want to reveal whether this is - * a decryption error or a MAC verification failure - * (see http://www.openssl.org/~bodo/tls-cbc.txt) */ - return -1; - } - for (j=(int)(l-i); j<(int)l; j++) - { - if (rec->data[j] != ii) - { - /* Incorrect padding */ - return -1; - } - } - rec->length -=i; - if (s->version >= TLS1_1_VERSION - && EVP_CIPHER_CTX_mode(ds) == EVP_CIPH_CBC_MODE) - { - if (bs > (int)rec->length) - return -1; - rec->data += bs; /* skip the explicit IV */ - rec->input += bs; - rec->length -= bs; - } - } + ret = tls1_cbc_remove_padding(s, rec, bs, mac_size); if (pad && !send) rec->length -= pad; } - return(1); + return ret; } + int tls1_cert_verify_mac(SSL *s, int md_nid, unsigned char *out) { unsigned int ret; @@ -990,10 +949,10 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send) SSL3_RECORD *rec; unsigned char *seq; EVP_MD_CTX *hash; - size_t md_size; + size_t md_size, orig_len; int i; EVP_MD_CTX hmac, *mac_ctx; - unsigned char buf[5]; + unsigned char header[13]; int stream_mac = (send?(ssl->mac_flags & SSL_MAC_FLAG_WRITE_MAC_STREAM):(ssl->mac_flags&SSL_MAC_FLAG_READ_MAC_STREAM)); int t; @@ -1014,12 +973,6 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send) OPENSSL_assert(t >= 0); md_size=t; - buf[0]=rec->type; - buf[1]=(unsigned char)(ssl->version>>8); - buf[2]=(unsigned char)(ssl->version); - buf[3]=rec->length>>8; - buf[4]=rec->length&0xff; - /* I should fix this up TLS TLS TLS TLS TLS XXXXXXXX */ if (stream_mac) { @@ -1038,17 +991,55 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send) s2n(send?ssl->d1->w_epoch:ssl->d1->r_epoch, p); memcpy (p,&seq[2],6); - EVP_DigestSignUpdate(mac_ctx,dtlsseq,8); + memcpy(header, dtlsseq, 8); } else - EVP_DigestSignUpdate(mac_ctx,seq,8); + memcpy(header, seq, 8); - EVP_DigestSignUpdate(mac_ctx,buf,5); - EVP_DigestSignUpdate(mac_ctx,rec->input,rec->length); - t=EVP_DigestSignFinal(mac_ctx,md,&md_size); - OPENSSL_assert(t > 0); + /* kludge: tls1_cbc_remove_padding passes padding length in rec->type */ + orig_len = rec->length+md_size+((unsigned int)rec->type>>8); + rec->type &= 0xff; + + header[8]=rec->type; + header[9]=(unsigned char)(ssl->version>>8); + header[10]=(unsigned char)(ssl->version); + header[11]=(rec->length)>>8; + header[12]=(rec->length)&0xff; + + if (!send && + EVP_CIPHER_CTX_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE && + ssl3_cbc_record_digest_supported(mac_ctx)) + { + /* This is a CBC-encrypted record. We must avoid leaking any + * timing-side channel information about how many blocks of + * data we are hashing because that gives an attacker a + * timing-oracle. */ + ssl3_cbc_digest_record( + mac_ctx, + md, &md_size, + header, rec->input, + rec->length + md_size, orig_len, + ssl->s3->read_mac_secret, + ssl->s3->read_mac_secret_size, + 0 /* not SSLv3 */); + } + else + { + EVP_DigestSignUpdate(mac_ctx,header,sizeof(header)); + EVP_DigestSignUpdate(mac_ctx,rec->input,rec->length); + t=EVP_DigestSignFinal(mac_ctx,md,&md_size); + OPENSSL_assert(t > 0); +#ifdef OPENSSL_FIPS + if (!send && FIPS_mode()) + tls_fips_digest_extra( + ssl->enc_read_ctx, + mac_ctx, rec->input, + rec->length, orig_len); +#endif + } - if (!stream_mac) EVP_MD_CTX_cleanup(&hmac); + if (!stream_mac) + EVP_MD_CTX_cleanup(&hmac); #ifdef TLS_DEBUG printf("sec="); {unsigned int z; for (z=0; zsrtp_profile) { int el; @@ -799,6 +802,7 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha } ret+=el; } +#endif if (((s->s3->tmp.new_cipher->id & 0xFFFF)==0x80 || (s->s3->tmp.new_cipher->id & 0xFFFF)==0x81) && (SSL_get_options(s) & SSL_OP_CRYPTOPRO_TLSEXT_BUG)) @@ -1077,7 +1081,8 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in int ellipticcurvelist_length = (*(sdata++) << 8); ellipticcurvelist_length += (*(sdata++)); - if (ellipticcurvelist_length != size - 2) + if (ellipticcurvelist_length != size - 2 || + ellipticcurvelist_length < 1) { *al = TLS1_AD_DECODE_ERROR; return 0; @@ -1328,12 +1333,14 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in #endif /* session ticket processed earlier */ +#ifndef OPENSSL_NO_SRTP else if (type == TLSEXT_TYPE_use_srtp) - { + { if(ssl_parse_clienthello_use_srtp_ext(s, data, size, al)) return 0; - } + } +#endif data+=size; } @@ -1433,7 +1440,8 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in unsigned char *sdata = data; int ecpointformatlist_length = *(sdata++); - if (ecpointformatlist_length != size - 1) + if (ecpointformatlist_length != size - 1 || + ecpointformatlist_length < 1) { *al = TLS1_AD_DECODE_ERROR; return 0; @@ -1527,7 +1535,7 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in unsigned char selected_len; /* We must have requested it. */ - if ((s->ctx->next_proto_select_cb == NULL)) + if (s->ctx->next_proto_select_cb == NULL) { *al = TLS1_AD_UNSUPPORTED_EXTENSION; return 0; @@ -1577,12 +1585,14 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in } } #endif +#ifndef OPENSSL_NO_SRTP else if (type == TLSEXT_TYPE_use_srtp) - { + { if(ssl_parse_serverhello_use_srtp_ext(s, data, size, al)) return 0; - } + } +#endif data+=size; } @@ -1763,7 +1773,7 @@ int ssl_prepare_serverhello_tlsext(SSL *s) return 1; } -int ssl_check_clienthello_tlsext(SSL *s) +int ssl_check_clienthello_tlsext_early(SSL *s) { int ret=SSL_TLSEXT_ERR_NOACK; int al = SSL_AD_UNRECOGNIZED_NAME; @@ -1782,42 +1792,12 @@ int ssl_check_clienthello_tlsext(SSL *s) else if (s->initial_ctx != NULL && s->initial_ctx->tlsext_servername_callback != 0) ret = s->initial_ctx->tlsext_servername_callback(s, &al, s->initial_ctx->tlsext_servername_arg); - /* If status request then ask callback what to do. - * Note: this must be called after servername callbacks in case - * the certificate has changed. - */ - if ((s->tlsext_status_type != -1) && s->ctx && s->ctx->tlsext_status_cb) - { - int r; - r = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg); - switch (r) - { - /* We don't want to send a status request response */ - case SSL_TLSEXT_ERR_NOACK: - s->tlsext_status_expected = 0; - break; - /* status request response should be sent */ - case SSL_TLSEXT_ERR_OK: - if (s->tlsext_ocsp_resp) - s->tlsext_status_expected = 1; - else - s->tlsext_status_expected = 0; - break; - /* something bad happened */ - case SSL_TLSEXT_ERR_ALERT_FATAL: - ret = SSL_TLSEXT_ERR_ALERT_FATAL; - al = SSL_AD_INTERNAL_ERROR; - goto err; - } - } - else - s->tlsext_status_expected = 0; - #ifdef TLSEXT_TYPE_opaque_prf_input { /* This sort of belongs into ssl_prepare_serverhello_tlsext(), * but we might be sending an alert in response to the client hello, - * so this has to happen here in ssl_check_clienthello_tlsext(). */ + * so this has to happen here in + * ssl_check_clienthello_tlsext_early(). */ int r = 1; @@ -1869,8 +1849,8 @@ int ssl_check_clienthello_tlsext(SSL *s) } } -#endif err: +#endif switch (ret) { case SSL_TLSEXT_ERR_ALERT_FATAL: @@ -1888,6 +1868,71 @@ int ssl_check_clienthello_tlsext(SSL *s) } } +int ssl_check_clienthello_tlsext_late(SSL *s) + { + int ret = SSL_TLSEXT_ERR_OK; + int al; + + /* If status request then ask callback what to do. + * Note: this must be called after servername callbacks in case + * the certificate has changed, and must be called after the cipher + * has been chosen because this may influence which certificate is sent + */ + if ((s->tlsext_status_type != -1) && s->ctx && s->ctx->tlsext_status_cb) + { + int r; + CERT_PKEY *certpkey; + certpkey = ssl_get_server_send_pkey(s); + /* If no certificate can't return certificate status */ + if (certpkey == NULL) + { + s->tlsext_status_expected = 0; + return 1; + } + /* Set current certificate to one we will use so + * SSL_get_certificate et al can pick it up. + */ + s->cert->key = certpkey; + r = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg); + switch (r) + { + /* We don't want to send a status request response */ + case SSL_TLSEXT_ERR_NOACK: + s->tlsext_status_expected = 0; + break; + /* status request response should be sent */ + case SSL_TLSEXT_ERR_OK: + if (s->tlsext_ocsp_resp) + s->tlsext_status_expected = 1; + else + s->tlsext_status_expected = 0; + break; + /* something bad happened */ + case SSL_TLSEXT_ERR_ALERT_FATAL: + ret = SSL_TLSEXT_ERR_ALERT_FATAL; + al = SSL_AD_INTERNAL_ERROR; + goto err; + } + } + else + s->tlsext_status_expected = 0; + + err: + switch (ret) + { + case SSL_TLSEXT_ERR_ALERT_FATAL: + ssl3_send_alert(s,SSL3_AL_FATAL,al); + return -1; + + case SSL_TLSEXT_ERR_ALERT_WARNING: + ssl3_send_alert(s,SSL3_AL_WARNING,al); + return 1; + + default: + return 1; + } + } + int ssl_check_serverhello_tlsext(SSL *s) { int ret=SSL_TLSEXT_ERR_NOACK; @@ -2189,7 +2234,7 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen, HMAC_Update(&hctx, etick, eticklen); HMAC_Final(&hctx, tick_hmac, NULL); HMAC_CTX_cleanup(&hctx); - if (memcmp(tick_hmac, etick + eticklen, mlen)) + if (CRYPTO_memcmp(tick_hmac, etick + eticklen, mlen)) return 2; /* Attempt to decrypt session data */ /* Move p after IV to start of encrypted ticket, update length */ @@ -2414,7 +2459,7 @@ int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize) */ #ifndef OPENSSL_NO_DSA if (!c->pkeys[SSL_PKEY_DSA_SIGN].digest) - c->pkeys[SSL_PKEY_DSA_SIGN].digest = EVP_dss1(); + c->pkeys[SSL_PKEY_DSA_SIGN].digest = EVP_sha1(); #endif #ifndef OPENSSL_NO_RSA if (!c->pkeys[SSL_PKEY_RSA_SIGN].digest) @@ -2425,7 +2470,7 @@ int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize) #endif #ifndef OPENSSL_NO_ECDSA if (!c->pkeys[SSL_PKEY_ECC].digest) - c->pkeys[SSL_PKEY_ECC].digest = EVP_ecdsa(); + c->pkeys[SSL_PKEY_ECC].digest = EVP_sha1(); #endif return 1; } diff --git a/ssl/tls_srp.c b/ssl/tls_srp.c index 8512c4daf65..2315a7c0a2e 100644 --- a/ssl/tls_srp.c +++ b/ssl/tls_srp.c @@ -242,7 +242,8 @@ int SSL_srp_server_param_with_username(SSL *s, int *ad) (s->srp_ctx.v == NULL)) return SSL3_AL_FATAL; - RAND_bytes(b, sizeof(b)); + if (RAND_bytes(b, sizeof(b)) <= 0) + return SSL3_AL_FATAL; s->srp_ctx.b = BN_bin2bn(b,sizeof(b),NULL); OPENSSL_cleanse(b,sizeof(b)); diff --git a/util/libeay.num b/util/libeay.num index 93f80ba0c64..6debdb60a89 100755 --- a/util/libeay.num +++ b/util/libeay.num @@ -3510,6 +3510,7 @@ BIO_get_callback_arg 3902 EXIST::FUNCTION: BIO_set_callback 3903 EXIST::FUNCTION: d2i_ASIdOrRange 3904 EXIST::FUNCTION:RFC3779 i2d_ASIdentifiers 3905 EXIST::FUNCTION:RFC3779 +CRYPTO_memcmp 3906 EXIST::FUNCTION: SEED_decrypt 3908 EXIST::FUNCTION:SEED SEED_encrypt 3909 EXIST::FUNCTION:SEED SEED_cbc_encrypt 3910 EXIST::FUNCTION:SEED @@ -3687,7 +3688,7 @@ FIPS_dh_new 4073 NOEXIST::FUNCTION: FIPS_corrupt_dsa_keygen 4074 NOEXIST::FUNCTION: FIPS_dh_free 4075 NOEXIST::FUNCTION: fips_pkey_signature_test 4076 NOEXIST::FUNCTION: -EVP_add_alg_module 4077 NOEXIST::FUNCTION: +EVP_add_alg_module 4077 EXIST::FUNCTION: int_RAND_init_engine_callbacks 4078 NOEXIST::FUNCTION: int_EVP_CIPHER_set_engine_callbacks 4079 NOEXIST::FUNCTION: int_EVP_MD_init_engine_callbacks 4080 NOEXIST::FUNCTION: diff --git a/util/pl/VC-32.pl b/util/pl/VC-32.pl index c503bd52b9f..6c550f54aed 100644 --- a/util/pl/VC-32.pl +++ b/util/pl/VC-32.pl @@ -118,7 +118,7 @@ elsif ($FLAVOR =~ /CE/) $base_cflags.=' -I$(WCECOMPAT)/include' if (defined($ENV{'WCECOMPAT'})); $base_cflags.=' -I$(PORTSDK_LIBPATH)/../../include' if (defined($ENV{'PORTSDK_LIBPATH'})); $opt_cflags=' /MC /O1i'; # optimize for space, but with intrinsics... - $dbg_clfags=' /MC /Od -DDEBUG -D_DEBUG'; + $dbg_cflags=' /MC /Od -DDEBUG -D_DEBUG'; $lflags="/nologo /opt:ref $wcelflag"; } else # Win32 From b39da7f7212adf316d913e869945fe84597de270 Mon Sep 17 00:00:00 2001 From: Jung-uk Kim Date: Wed, 13 Feb 2013 22:38:20 +0000 Subject: [PATCH 0158/1476] Change "the the" to "the". It is a continuation of r226436 and missed in r237658. Approved by: benl (maintainer, implicit) --- crypto/openssl/doc/apps/dgst.pod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/openssl/doc/apps/dgst.pod b/crypto/openssl/doc/apps/dgst.pod index 7393cec905a..d79fb5cbc1c 100644 --- a/crypto/openssl/doc/apps/dgst.pod +++ b/crypto/openssl/doc/apps/dgst.pod @@ -91,7 +91,7 @@ The output is either "Verification OK" or "Verification Failure". =item B<-prverify filename> -verify the signature using the the private key in "filename". +verify the signature using the private key in "filename". =item B<-signature filename> From 7c695febc95e05582714faf18eab279f356eb3e8 Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Wed, 13 Feb 2013 23:11:25 +0000 Subject: [PATCH 0159/1476] Change vfs.zfs.write_to_degraded from CTLFLAG_RW to CTLFLAG_RWTUN Suggested by: pjd --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c index 53ffa9047f1..e81dc025106 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c @@ -101,9 +101,8 @@ int metaslab_smo_bonus_pct = 150; * Should we be willing to write data to degraded vdevs? */ boolean_t zfs_write_to_degraded = B_FALSE; -SYSCTL_INT(_vfs_zfs, OID_AUTO, write_to_degraded, CTLFLAG_RW, - &zfs_write_to_degraded, 0, - "Allow writing data to degraded vdevs"); +SYSCTL_INT(_vfs_zfs, OID_AUTO, write_to_degraded, CTLFLAG_RWTUN, + &zfs_write_to_degraded, 0, "Allow writing data to degraded vdevs"); TUNABLE_INT("vfs.zfs.write_to_degraded", &zfs_write_to_degraded); /* From 25448de2229dedab00764dce8ff8618ea36b4e61 Mon Sep 17 00:00:00 2001 From: Neel Natu Date: Wed, 13 Feb 2013 23:22:17 +0000 Subject: [PATCH 0160/1476] Requests for invalid CPUID leaves should map to the highest known leaf instead. Reviewed by: grehan Obtained from: NetApp --- sys/amd64/vmm/x86.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/amd64/vmm/x86.c b/sys/amd64/vmm/x86.c index 94abe09b33c..13eaaad99ad 100644 --- a/sys/amd64/vmm/x86.c +++ b/sys/amd64/vmm/x86.c @@ -54,8 +54,6 @@ x86_emulate_cpuid(struct vm *vm, int vcpu_id, unsigned int func, regs[4]; enum x2apic_state x2apic_state; - func = *eax; - /* * Requests for invalid CPUID levels should map to the highest * available level instead. @@ -70,6 +68,8 @@ x86_emulate_cpuid(struct vm *vm, int vcpu_id, *eax = cpu_high; } + func = *eax; + /* * In general the approach used for CPU topology is to * advertise a flat topology where all CPUs are packages with From f33fce48655d0c4398e2b30965b7ff33524378f7 Mon Sep 17 00:00:00 2001 From: Xin LI Date: Thu, 14 Feb 2013 01:01:53 +0000 Subject: [PATCH 0161/1476] Use static for all functions that do not need to be exported. MFC after: 2 weeks --- usr.sbin/nfsd/nfsd.c | 54 ++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/usr.sbin/nfsd/nfsd.c b/usr.sbin/nfsd/nfsd.c index 0e39138f14e..7f7a245590c 100644 --- a/usr.sbin/nfsd/nfsd.c +++ b/usr.sbin/nfsd/nfsd.c @@ -105,20 +105,20 @@ static struct option longopts[] = { { NULL, 0, NULL, 0} }; -void cleanup(int); -void child_cleanup(int); -void killchildren(void); -void nfsd_exit(int); -void nonfs(int); -void reapchild(int); -int setbindhost(struct addrinfo **ia, const char *bindhost, - struct addrinfo hints); -void start_server(int); -void unregistration(void); -void usage(void); -void open_stable(int *, int *); -void copy_stable(int, int); -void backup_stable(int); +static void cleanup(int); +static void child_cleanup(int); +static void killchildren(void); +static void nfsd_exit(int); +static void nonfs(int); +static void reapchild(int); +static int setbindhost(struct addrinfo **ia, const char *bindhost, + struct addrinfo hints); +static void start_server(int); +static void unregistration(void); +static void usage(void); +static void open_stable(int *, int *); +static void copy_stable(int, int); +static void backup_stable(int); /* * Nfs server daemon mostly just a user context for nfssvc() @@ -844,7 +844,7 @@ main(int argc, char **argv) } } -int +static int setbindhost(struct addrinfo **ai, const char *bindhost, struct addrinfo hints) { int ecode; @@ -890,20 +890,20 @@ setbindhost(struct addrinfo **ai, const char *bindhost, struct addrinfo hints) return (0); } -void +static void usage(void) { (void)fprintf(stderr, "%s", getopt_usage); exit(1); } -void +static void nonfs(__unused int signo) { syslog(LOG_ERR, "missing system call: NFS not available"); } -void +static void reapchild(__unused int signo) { pid_t pid; @@ -916,7 +916,7 @@ reapchild(__unused int signo) } } -void +static void unregistration(void) { if ((!rpcb_unset(NFS_PROGRAM, 2, NULL)) || @@ -924,7 +924,7 @@ unregistration(void) syslog(LOG_ERR, "rpcb_unset failed"); } -void +static void killchildren(void) { int i; @@ -938,7 +938,7 @@ killchildren(void) /* * Cleanup master after SIGUSR1. */ -void +static void cleanup(__unused int signo) { nfsd_exit(0); @@ -947,13 +947,13 @@ cleanup(__unused int signo) /* * Cleanup child after SIGUSR1. */ -void +static void child_cleanup(__unused int signo) { exit(0); } -void +static void nfsd_exit(int status) { killchildren(); @@ -984,7 +984,7 @@ get_tuned_nfsdcount(void) return tuned_nfsdcnt; } -void +static void start_server(int master) { char principal[MAXHOSTNAMELEN + 5]; @@ -1066,7 +1066,7 @@ start_server(int master) /* * Open the stable restart file and return the file descriptor for it. */ -void +static void open_stable(int *stable_fdp, int *backup_fdp) { int stable_fd, backup_fd = -1, ret; @@ -1118,7 +1118,7 @@ open_stable(int *stable_fdp, int *backup_fdp) /* * Copy the stable restart file to the backup or vice versa. */ -void +static void copy_stable(int from_fd, int to_fd) { int cnt, ret; @@ -1146,7 +1146,7 @@ copy_stable(int from_fd, int to_fd) /* * Back up the stable restart file when indicated by the kernel. */ -void +static void backup_stable(__unused int signo) { From 2a0b6dc5c3a476318653a7ba94d464080c1c8908 Mon Sep 17 00:00:00 2001 From: Xin LI Date: Thu, 14 Feb 2013 01:25:14 +0000 Subject: [PATCH 0162/1476] Abstract out setting of nfsdcnt and consistently use MAXNFSDCNT when the proposed value is too high and DEFNFSDCNT when proposed value is too low. MFC after: 2 weeks --- usr.sbin/nfsd/nfsd.c | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/usr.sbin/nfsd/nfsd.c b/usr.sbin/nfsd/nfsd.c index 7f7a245590c..3fa267c8a32 100644 --- a/usr.sbin/nfsd/nfsd.c +++ b/usr.sbin/nfsd/nfsd.c @@ -119,6 +119,7 @@ static void usage(void); static void open_stable(int *, int *); static void copy_stable(int, int); static void backup_stable(int); +static void set_nfsdcnt(int); /* * Nfs server daemon mostly just a user context for nfssvc() @@ -178,8 +179,7 @@ main(int argc, char **argv) bindanyflag = 1; break; case 'n': - nfsdcnt_set = 1; - nfsdcnt = atoi(optarg); + set_nfsdcnt(atoi(optarg)); break; case 'h': bindhostc++; @@ -235,15 +235,8 @@ main(int argc, char **argv) */ if (argc > 1) usage(); - if (argc == 1) { - nfsdcnt_set = 1; - nfsdcnt = atoi(argv[0]); - if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) { - warnx("nfsd count %d; reset to %d", nfsdcnt, - DEFNFSDCNT); - nfsdcnt = DEFNFSDCNT; - } - } + if (argc == 1) + set_nfsdcnt(atoi(argv[0])); /* * Unless the "-o" option was specified, try and run "nfsd". @@ -429,16 +422,6 @@ main(int argc, char **argv) } if (!new_syscall) { - if (nfsdcnt < 1) { - warnx("nfsd count too low %d; reset to %d", nfsdcnt, - DEFNFSDCNT); - nfsdcnt = DEFNFSDCNT; - } - if (nfsdcnt > MAXNFSDCNT) { - warnx("nfsd count too high %d; reset to %d", nfsdcnt, - DEFNFSDCNT); - nfsdcnt = MAXNFSDCNT; - } /* If we use UDP only, we start the last server below. */ srvcnt = tcpflag ? nfsdcnt : nfsdcnt - 1; for (i = 0; i < srvcnt; i++) { @@ -890,6 +873,23 @@ setbindhost(struct addrinfo **ai, const char *bindhost, struct addrinfo hints) return (0); } +static void +set_nfsdcnt(int proposed) +{ + + if (proposed < 1) { + warnx("nfsd count too low %d; reset to %d", proposed, + DEFNFSDCNT); + nfsdcnt = DEFNFSDCNT; + } else if (proposed > MAXNFSDCNT) { + warnx("nfsd count too high %d; truncated to %d", proposed, + MAXNFSDCNT); + nfsdcnt = MAXNFSDCNT; + } else + nfsdcnt = proposed; + nfsdcnt_set = 1; +} + static void usage(void) { From 535875c73405235b2d521f86c2ba3b382483307c Mon Sep 17 00:00:00 2001 From: Xin LI Date: Thu, 14 Feb 2013 02:00:41 +0000 Subject: [PATCH 0163/1476] Simplify r243637 and make sure that nfsdargs.{min,max}threads are always set to meaningful value: - When nfsdcnt is set, it dictates all values; - Otherwise, nfsdargs.minthreads is set to user specified value, or the automatically detected value if there is no one specified; nfsdargs.maxthreads is set to the user specified value, or the value of nfsdargs.minthreads if there is no one specified; when it is smaller than nfsdargs.minthreads, the latter's value is always used. MFC after: 2 weeks --- usr.sbin/nfsd/nfsd.c | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/usr.sbin/nfsd/nfsd.c b/usr.sbin/nfsd/nfsd.c index 3fa267c8a32..b114ba6a404 100644 --- a/usr.sbin/nfsd/nfsd.c +++ b/usr.sbin/nfsd/nfsd.c @@ -1014,26 +1014,13 @@ start_server(int master) } nfsdargs.principal = principal; - if (minthreads_set) { - nfsdargs.minthreads = minthreads; - if (!maxthreads_set) - nfsdargs.maxthreads = minthreads; - } - if (maxthreads_set) { - nfsdargs.maxthreads = maxthreads; - if (!minthreads_set) - nfsdargs.minthreads = maxthreads; - } - if (nfsdcnt_set) { - nfsdargs.minthreads = nfsdcnt; - nfsdargs.maxthreads = nfsdcnt; - } - if (!minthreads_set && !maxthreads_set && !nfsdcnt_set) { - int tuned_nfsdcnt; - - tuned_nfsdcnt = get_tuned_nfsdcount(); - nfsdargs.minthreads = tuned_nfsdcnt; - nfsdargs.maxthreads = tuned_nfsdcnt; + if (nfsdcnt_set) + nfsdargs.minthreads = nfsdargs.maxthreads = nfsdcnt; + else { + nfsdargs.minthreads = minthreads_set ? minthreads : get_tuned_nfsdcount(); + nfsdargs.maxthreads = maxthreads_set ? maxthreads : nfsdargs.minthreads; + if (nfsdargs.maxthreads < nfsdargs.minthreads) + nfsdargs.maxthreads = nfsdargs.minthreads; } error = nfssvc(nfssvc_nfsd, &nfsdargs); if (error < 0 && errno == EAUTH) { From af2637db52bc5520a60ae6cb276c792a5ebe8073 Mon Sep 17 00:00:00 2001 From: Philippe Charnier Date: Thu, 14 Feb 2013 08:16:03 +0000 Subject: [PATCH 0164/1476] rework old-style functions prototypes reduce WARNS=6 output --- usr.bin/gprof/aout.c | 1 - usr.bin/gprof/arcs.c | 46 +++++++--------- usr.bin/gprof/dfn.c | 23 +++----- usr.bin/gprof/gprof.c | 45 ++++++--------- usr.bin/gprof/gprof.h | 36 +++++------- usr.bin/gprof/hertz.c | 2 + usr.bin/gprof/kernel.c | 2 +- usr.bin/gprof/lookup.c | 7 +-- usr.bin/gprof/printgprof.c | 110 +++++++++++++++++-------------------- usr.bin/gprof/printlist.c | 8 +-- 10 files changed, 115 insertions(+), 165 deletions(-) diff --git a/usr.bin/gprof/aout.c b/usr.bin/gprof/aout.c index f64d6721139..76ad07ea86d 100644 --- a/usr.bin/gprof/aout.c +++ b/usr.bin/gprof/aout.c @@ -68,7 +68,6 @@ int aout_getnfile(const char *filename, char ***defaultEs) { FILE *nfile; - int valcmp(); nfile = fopen( filename ,"r"); if (nfile == NULL) diff --git a/usr.bin/gprof/arcs.c b/usr.bin/gprof/arcs.c index ad5cb56160c..c5b2e96bbe0 100644 --- a/usr.bin/gprof/arcs.c +++ b/usr.bin/gprof/arcs.c @@ -46,14 +46,13 @@ int newcycle; int oldcycle; #endif /* DEBUG */ +int topcmp(const void *, const void *); + /* * add (or just increment) an arc */ void -addarc( parentp , childp , count ) - nltype *parentp; - nltype *childp; - long count; +addarc(nltype *parentp, nltype *childp, long count) { arctype *arcp; @@ -106,15 +105,16 @@ addarc( parentp , childp , count ) nltype **topsortnlp; int -topcmp( npp1 , npp2 ) - nltype **npp1; - nltype **npp2; +topcmp(const void *v1, const void *v2) { + const nltype **npp1 = (const nltype **)v1; + const nltype **npp2 = (const nltype **)v2; + return (*npp1) -> toporder - (*npp2) -> toporder; } nltype ** -doarcs() +doarcs(void) { nltype *parentp, **timesortnlp; arctype *arcp; @@ -252,7 +252,7 @@ doarcs() } void -dotime() +dotime(void) { int index; @@ -263,8 +263,7 @@ dotime() } void -timepropagate( parentp ) - nltype *parentp; +timepropagate(nltype *parentp) { arctype *arcp; nltype *childp; @@ -352,7 +351,7 @@ timepropagate( parentp ) } void -cyclelink() +cyclelink(void) { register nltype *nlp; register nltype *cyclenlp; @@ -445,7 +444,7 @@ cyclelink() * analyze cycles to determine breakup */ bool -cycleanalyze() +cycleanalyze(void) { arctype **cyclestack; arctype **stkp; @@ -521,10 +520,7 @@ cycleanalyze() } bool -descend( node , stkstart , stkp ) - nltype *node; - arctype **stkstart; - arctype **stkp; +descend(nltype *node, arctype **stkstart, arctype **stkp) { arctype *arcp; bool ret; @@ -556,9 +552,7 @@ descend( node , stkstart , stkp ) } bool -addcycle( stkstart , stkend ) - arctype **stkstart; - arctype **stkend; +addcycle(arctype **stkstart, arctype **stkend) { arctype **arcpp; arctype **stkloc; @@ -632,7 +626,7 @@ addcycle( stkstart , stkend ) } void -compresslist() +compresslist(void) { cltype *clp; cltype **prev; @@ -748,8 +742,7 @@ compresslist() #ifdef DEBUG void -printsubcycle( clp ) - cltype *clp; +printsubcycle(cltype *clp) { arctype **arcpp; arctype **endlist; @@ -764,7 +757,7 @@ printsubcycle( clp ) #endif /* DEBUG */ void -cycletime() +cycletime(void) { int cycle; nltype *cyclenlp; @@ -794,7 +787,7 @@ cycletime() * and while we're here, sum time for functions. */ void -doflags() +doflags(void) { int index; nltype *childp; @@ -889,8 +882,7 @@ doflags() * similarly, deal with propagation fractions from parents. */ void -inheritflags( childp ) - nltype *childp; +inheritflags(nltype *childp) { nltype *headp; arctype *arcp; diff --git a/usr.bin/gprof/dfn.c b/usr.bin/gprof/dfn.c index 4f6eeac0d61..a49cd31d468 100644 --- a/usr.bin/gprof/dfn.c +++ b/usr.bin/gprof/dfn.c @@ -52,7 +52,7 @@ int dfn_depth; int dfn_counter; void -dfn_init() +dfn_init(void) { dfn_depth = 0; @@ -63,8 +63,7 @@ dfn_init() * given this parent, depth first number its children. */ void -dfn( parentp ) - nltype *parentp; +dfn(nltype *parentp) { arctype *arcp; @@ -110,8 +109,7 @@ dfn( parentp ) * push a parent onto the stack and mark it busy */ void -dfn_pre_visit( parentp ) - nltype *parentp; +dfn_pre_visit(nltype *parentp) { dfn_depth += 1; @@ -133,8 +131,7 @@ dfn_pre_visit( parentp ) * are we already numbered? */ bool -dfn_numbered( childp ) - nltype *childp; +dfn_numbered(nltype *childp) { return ( childp -> toporder != DFN_NAN && childp -> toporder != DFN_BUSY ); @@ -144,8 +141,7 @@ dfn_numbered( childp ) * are we already busy? */ bool -dfn_busy( childp ) - nltype *childp; +dfn_busy(nltype *childp) { if ( childp -> toporder == DFN_NAN ) { @@ -158,8 +154,7 @@ dfn_busy( childp ) * MISSING: an explanation */ void -dfn_findcycle( childp ) - nltype *childp; +dfn_findcycle(nltype *childp) { int cycletop; nltype *cycleheadp; @@ -267,8 +262,7 @@ dfn_findcycle( childp ) * for lint: ARGSUSED */ void -dfn_self_cycle( parentp ) - nltype *parentp; +dfn_self_cycle(nltype *parentp) { /* * since we are taking out self-cycles elsewhere @@ -289,8 +283,7 @@ dfn_self_cycle( parentp ) * and pop it off the stack */ void -dfn_post_visit( parentp ) - nltype *parentp; +dfn_post_visit(nltype *parentp) { nltype *memberp; diff --git a/usr.bin/gprof/gprof.c b/usr.bin/gprof/gprof.c index 706439484bf..e05d628e4cf 100644 --- a/usr.bin/gprof/gprof.c +++ b/usr.bin/gprof/gprof.c @@ -51,15 +51,12 @@ __FBSDID("$FreeBSD$"); static int valcmp(const void *, const void *); - static struct gmonhdr gmonhdr; static int lflag; static int Lflag; int -main(argc, argv) - int argc; - char **argv; +main(int argc, char **argv) { char **sp; nltype **timesortnlp; @@ -233,11 +230,9 @@ main(argc, argv) * and the arcs. */ void -getpfile(filename) - char *filename; +getpfile(char *filename) { FILE *pfile; - FILE *openpfile(); struct rawarc arc; pfile = openpfile(filename); @@ -262,8 +257,7 @@ getpfile(filename) } FILE * -openpfile(filename) - char *filename; +openpfile(char *filename) { struct gmonhdr tmp; FILE *pfile; @@ -322,8 +316,7 @@ openpfile(filename) } void -tally( rawp ) - struct rawarc *rawp; +tally(struct rawarc *rawp) { nltype *parentp; nltype *childp; @@ -351,8 +344,7 @@ tally( rawp ) * dump out the gmon.sum file */ void -dumpsum( sumfile ) - char *sumfile; +dumpsum(const char *sumfile) { register nltype *nlp; register arctype *arcp; @@ -393,9 +385,7 @@ dumpsum( sumfile ) } static int -valcmp(v1, v2) - const void *v1; - const void *v2; +valcmp(const void *v1, const void *v2) { const nltype *p1 = (const nltype *)v1; const nltype *p2 = (const nltype *)v2; @@ -410,8 +400,7 @@ valcmp(v1, v2) } void -readsamples(pfile) - FILE *pfile; +readsamples(FILE *pfile) { int i; intmax_t sample; @@ -491,11 +480,11 @@ readsamples(pfile) * have any overlap (the two end cases, above). */ void -asgnsamples() +asgnsamples(void) { register int j; double ccnt; - double time; + double thetime; unsigned long pcl, pch; register int i; unsigned long overlap; @@ -511,14 +500,14 @@ asgnsamples() continue; pcl = lowpc + (unsigned long)(scale * i); pch = lowpc + (unsigned long)(scale * (i + 1)); - time = ccnt; + thetime = ccnt; # ifdef DEBUG if ( debug & SAMPLEDEBUG ) { printf( "[asgnsamples] pcl 0x%lx pch 0x%lx ccnt %.0f\n" , pcl , pch , ccnt ); } # endif /* DEBUG */ - totime += time; + totime += thetime; for (j = j - 1; j < nname; j++) { svalue0 = nl[j].svalue; svalue1 = nl[j+1].svalue; @@ -541,10 +530,10 @@ asgnsamples() printf("[asgnsamples] (0x%lx->0x%lx-0x%lx) %s gets %f ticks %lu overlap\n", nl[j].value / HISTORICAL_SCALE_2, svalue0, svalue1, nl[j].name, - overlap * time / scale, overlap); + overlap * thetime / scale, overlap); } # endif /* DEBUG */ - nl[j].time += overlap * time / scale; + nl[j].time += overlap * thetime / scale; } } } @@ -557,8 +546,7 @@ asgnsamples() unsigned long -min(a, b) - unsigned long a,b; +min(unsigned long a, unsigned long b) { if (ab) return(a); @@ -581,7 +568,7 @@ max(a, b) * for a routine is in the next bucket. */ void -alignentries() +alignentries(void) { register struct nl *nlp; unsigned long bucket_of_entry; diff --git a/usr.bin/gprof/gprof.h b/usr.bin/gprof/gprof.h index bcded0d743f..c841a20e9bd 100644 --- a/usr.bin/gprof/gprof.h +++ b/usr.bin/gprof/gprof.h @@ -258,8 +258,8 @@ bool addcycle(arctype **, arctype **); void addlist(struct stringlist *, char *); void alignentries(void); int aout_getnfile(const char *, char ***); -int arccmp(); -arctype *arclookup(); +int arccmp(arctype *, arctype *); +arctype *arclookup(nltype *, nltype *); void asgnsamples(void); void compresslist(void); bool cycleanalyze(void); @@ -267,41 +267,36 @@ void cyclelink(void); void cycletime(void); bool descend(nltype *, arctype **, arctype **); void dfn(nltype *); -bool dfn_busy(); +bool dfn_busy(nltype *); void dfn_findcycle(nltype *); void dfn_init(void); -bool dfn_numbered(); +bool dfn_numbered(nltype *); void dfn_post_visit(nltype *); void dfn_pre_visit(nltype *); void dfn_self_cycle(nltype *); -nltype **doarcs(); +nltype **doarcs(void); void doflags(void); void dotime(void); -void dumpsum(char *); +void dumpsum(const char *); int elf_getnfile(const char *, char ***); void flatprofheader(void); void flatprofline(nltype *); void getpfile(char *); -/* - gprofheader(); - gprofline(); -*/ +void gprofheader(void); +void gprofline(register nltype *); int hertz(void); void inheritflags(nltype *); int kernel_getnfile(const char *, char ***); /* main(); */ -unsigned long max(); -int membercmp(); -unsigned long min(); -nltype *nllookup(); +unsigned long max(unsigned long, unsigned long); +int membercmp(nltype *, nltype *); +unsigned long min(unsigned long, unsigned long); +nltype *nllookup(unsigned long); bool onlist(struct stringlist *, const char *); -FILE *openpfile(); -long operandlength(); -operandenum operandmode(); -char *operandname(); -void printblurb(char *); +FILE *openpfile(char *); +void printblurb(const char *); void printchildren(nltype *); void printcycle(nltype *); void printgprof(nltype **); @@ -312,13 +307,12 @@ void printparents(nltype *); void printprof(void); void printsubcycle(cltype *); void readsamples(FILE *); -unsigned long reladdr(); void sortchildren(nltype *); void sortmembers(nltype *); void sortparents(nltype *); void tally(struct rawarc *); void timepropagate(nltype *); -int totalcmp(); +int totalcmp(const void *, const void *); #define LESSTHAN -1 #define EQUALTO 0 diff --git a/usr.bin/gprof/hertz.c b/usr.bin/gprof/hertz.c index 4913634ba10..9a8a2b1b161 100644 --- a/usr.bin/gprof/hertz.c +++ b/usr.bin/gprof/hertz.c @@ -44,6 +44,8 @@ __FBSDID("$FreeBSD$"); */ #define HZ_WRONG 0 +int hertz(void); + int hertz(void) { diff --git a/usr.bin/gprof/kernel.c b/usr.bin/gprof/kernel.c index dc456f5f97a..7af98977de2 100644 --- a/usr.bin/gprof/kernel.c +++ b/usr.bin/gprof/kernel.c @@ -16,7 +16,7 @@ __FBSDID("$FreeBSD$"); static char *excludes[] = { ".mcount", "_mcleanup", NULL }; int -kernel_getnfile(const char *unused, char ***defaultEs) +kernel_getnfile(const char *unused __unused, char ***defaultEs) { char *namelist; size_t len; diff --git a/usr.bin/gprof/lookup.c b/usr.bin/gprof/lookup.c index 256136090db..0ef1e0bb1e4 100644 --- a/usr.bin/gprof/lookup.c +++ b/usr.bin/gprof/lookup.c @@ -44,8 +44,7 @@ __FBSDID("$FreeBSD$"); * entry point. */ nltype * -nllookup( address ) - unsigned long address; +nllookup(unsigned long address) { register long low; register long middle; @@ -90,9 +89,7 @@ nllookup( address ) } arctype * -arclookup( parentp , childp ) - nltype *parentp; - nltype *childp; +arclookup(nltype *parentp, nltype *childp) { arctype *arcp; diff --git a/usr.bin/gprof/printgprof.c b/usr.bin/gprof/printgprof.c index 539095a0272..303365a9c0e 100644 --- a/usr.bin/gprof/printgprof.c +++ b/usr.bin/gprof/printgprof.c @@ -42,12 +42,15 @@ __FBSDID("$FreeBSD$"); #include "gprof.h" #include "pathnames.h" +int namecmp(const void *, const void *); +int timecmp(const void *, const void *); + void -printprof() +printprof(void) { register nltype *np; nltype **sortednlp; - int index, timecmp(); + int idx; actime = 0.0; printf( "\f\n" ); @@ -58,12 +61,12 @@ printprof() sortednlp = (nltype **) calloc( nname , sizeof(nltype *) ); if ( sortednlp == (nltype **) 0 ) errx( 1 , "[printprof] ran out of memory for time sorting" ); - for ( index = 0 ; index < nname ; index += 1 ) { - sortednlp[ index ] = &nl[ index ]; + for ( idx = 0 ; idx < nname ; idx += 1 ) { + sortednlp[ idx ] = &nl[ idx ]; } qsort( sortednlp , nname , sizeof(nltype *) , timecmp ); - for ( index = 0 ; index < nname ; index += 1 ) { - np = sortednlp[ index ]; + for ( idx = 0 ; idx < nname ; idx += 1 ) { + np = sortednlp[ idx ]; flatprofline( np ); } actime = 0.0; @@ -71,9 +74,10 @@ printprof() } int -timecmp( npp1 , npp2 ) - nltype **npp1, **npp2; +timecmp(const void *v1, const void *v2) { + const nltype **npp1 = (const nltype **)v1; + const nltype **npp2 = (const nltype **)v2; double timediff; long calldiff; @@ -94,7 +98,7 @@ timecmp( npp1 , npp2 ) * header for flatprofline */ void -flatprofheader() +flatprofheader(void) { if ( bflag ) { @@ -122,8 +126,7 @@ flatprofheader() } void -flatprofline( np ) - register nltype *np; +flatprofline(register nltype *np) { if ( zflag == 0 && np -> ncall == 0 && np -> time == 0 && @@ -161,7 +164,7 @@ flatprofline( np ) } void -gprofheader() +gprofheader(void) { if ( bflag ) { @@ -190,8 +193,7 @@ gprofheader() } void -gprofline( np ) - register nltype *np; +gprofline(register nltype *np) { char kirkbuffer[ BUFSIZ ]; @@ -216,18 +218,17 @@ gprofline( np ) } void -printgprof(timesortnlp) - nltype **timesortnlp; +printgprof(nltype **timesortnlp) { - int index; + int idx; nltype *parentp; /* * Print out the structured profiling list */ gprofheader(); - for ( index = 0 ; index < nname + ncycle ; index ++ ) { - parentp = timesortnlp[ index ]; + for ( idx = 0 ; idx < nname + ncycle ; idx ++ ) { + parentp = timesortnlp[ idx ]; if ( zflag == 0 && parentp -> ncall == 0 && parentp -> selfcalls == 0 && @@ -265,12 +266,12 @@ printgprof(timesortnlp) * all else being equal, sort by names. */ int -totalcmp( npp1 , npp2 ) - nltype **npp1; - nltype **npp2; +totalcmp(const void *v1, const void *v2) { - register nltype *np1 = *npp1; - register nltype *np2 = *npp2; + const nltype **npp1 = (const nltype **)v1; + const nltype **npp2 = (const nltype **)v2; + register const nltype *np1 = *npp1; + register const nltype *np2 = *npp2; double diff; diff = ( np1 -> propself + np1 -> propchild ) @@ -299,8 +300,7 @@ totalcmp( npp1 , npp2 ) } void -printparents( childp ) - nltype *childp; +printparents(nltype *childp) { nltype *parentp; arctype *arcp; @@ -344,8 +344,7 @@ printparents( childp ) } void -printchildren( parentp ) - nltype *parentp; +printchildren(nltype *parentp) { nltype *childp; arctype *arcp; @@ -378,8 +377,7 @@ printchildren( parentp ) } void -printname( selfp ) - nltype *selfp; +printname(nltype *selfp) { if ( selfp -> name != 0 ) { @@ -406,8 +404,7 @@ printname( selfp ) } void -sortchildren( parentp ) - nltype *parentp; +sortchildren(nltype *parentp) { arctype *arcp; arctype *detachedp; @@ -447,8 +444,7 @@ sortchildren( parentp ) } void -sortparents( childp ) - nltype *childp; +sortparents(nltype *childp) { arctype *arcp; arctype *detachedp; @@ -491,8 +487,7 @@ sortparents( childp ) * print a cycle header */ void -printcycle( cyclep ) - nltype *cyclep; +printcycle(nltype *cyclep) { char kirkbuffer[ BUFSIZ ]; @@ -516,8 +511,7 @@ printcycle( cyclep ) * print the members of a cycle */ void -printmembers( cyclep ) - nltype *cyclep; +printmembers(nltype *cyclep) { nltype *memberp; @@ -541,8 +535,7 @@ printmembers( cyclep ) * sort members of a cycle */ void -sortmembers( cyclep ) - nltype *cyclep; +sortmembers(nltype *cyclep) { nltype *todo; nltype *doing; @@ -572,9 +565,7 @@ sortmembers( cyclep ) * next is sort on ncalls + selfcalls. */ int -membercmp( this , that ) - nltype *this; - nltype *that; +membercmp(nltype *this, nltype *that) { double thistime = this -> propself + this -> propchild; double thattime = that -> propself + that -> propchild; @@ -605,9 +596,7 @@ membercmp( this , that ) * arc count as minor key */ int -arccmp( thisp , thatp ) - arctype *thisp; - arctype *thatp; +arccmp(arctype *thisp, arctype *thatp) { nltype *thisparentp = thisp -> arc_parentp; nltype *thischildp = thisp -> arc_childp; @@ -684,8 +673,7 @@ arccmp( thisp , thatp ) } void -printblurb( blurbname ) - char *blurbname; +printblurb(const char *blurbname) { FILE *blurbfile; int input; @@ -702,18 +690,20 @@ printblurb( blurbname ) } int -namecmp( npp1 , npp2 ) - nltype **npp1, **npp2; +namecmp(const void *v1, const void *v2) { + const nltype **npp1 = (const nltype **)v1; + const nltype **npp2 = (const nltype **)v2; + return( strcmp( (*npp1) -> name , (*npp2) -> name ) ); } void -printindex() +printindex(void) { nltype **namesortnlp; register nltype *nlp; - int index, nnames, todo, i, j; + int idx, nnames, todo, i, j; char peterbuffer[ BUFSIZ ]; /* @@ -723,19 +713,19 @@ printindex() namesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) ); if ( namesortnlp == (nltype **) 0 ) errx( 1 , "ran out of memory for sorting"); - for ( index = 0 , nnames = 0 ; index < nname ; index++ ) { - if ( zflag == 0 && nl[index].ncall == 0 && nl[index].time == 0 ) + for ( idx = 0 , nnames = 0 ; idx < nname ; idx++ ) { + if ( zflag == 0 && nl[idx].ncall == 0 && nl[idx].time == 0 ) continue; - namesortnlp[nnames++] = &nl[index]; + namesortnlp[nnames++] = &nl[idx]; } qsort( namesortnlp , nnames , sizeof(nltype *) , namecmp ); - for ( index = 1 , todo = nnames ; index <= ncycle ; index++ ) { - namesortnlp[todo++] = &cyclenl[index]; + for ( idx = 1 , todo = nnames ; idx <= ncycle ; idx++ ) { + namesortnlp[todo++] = &cyclenl[idx]; } printf( "\f\nIndex by function name\n\n" ); - index = ( todo + 2 ) / 3; - for ( i = 0; i < index ; i++ ) { - for ( j = i; j < todo ; j += index ) { + idx = ( todo + 2 ) / 3; + for ( i = 0; i < idx ; i++ ) { + for ( j = i; j < todo ; j += idx ) { nlp = namesortnlp[ j ]; if ( nlp -> printflag ) { sprintf( peterbuffer , "[%d]" , nlp -> index ); diff --git a/usr.bin/gprof/printlist.c b/usr.bin/gprof/printlist.c index fd6efb99be5..a8eb6b6fe23 100644 --- a/usr.bin/gprof/printlist.c +++ b/usr.bin/gprof/printlist.c @@ -61,9 +61,7 @@ struct stringlist Ehead = { 0 , 0 }; struct stringlist *Elist = &Ehead; void -addlist( listp , funcname ) - struct stringlist *listp; - char *funcname; +addlist(struct stringlist *listp, char *funcname) { struct stringlist *slp; @@ -76,9 +74,7 @@ addlist( listp , funcname ) } bool -onlist( listp , funcname ) - struct stringlist *listp; - const char *funcname; +onlist(struct stringlist *listp, const char *funcname) { struct stringlist *slp; From 0af99eef9e4d3c463ece2da2342499cd5b55b8ab Mon Sep 17 00:00:00 2001 From: Hiroki Sato Date: Thu, 14 Feb 2013 08:32:07 +0000 Subject: [PATCH 0165/1476] - Fix libmd dependency. It is needed in the bootstrap library list because usr.bin/xinstall depends on it. - Remove libutil from usr.bin/xinstall/Makefile. No symbol was actually used. Reviewed by: brooks --- Makefile.inc1 | 1 + usr.bin/xinstall/Makefile | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Makefile.inc1 b/Makefile.inc1 index bcb948734ad..8a8f8cd3102 100644 --- a/Makefile.inc1 +++ b/Makefile.inc1 @@ -1207,6 +1207,7 @@ bootstrap-tools: ${_sed} \ ${_yacc} \ ${_lex} \ + lib/libmd \ usr.bin/xinstall \ ${_gensnmptree} \ usr.sbin/config \ diff --git a/usr.bin/xinstall/Makefile b/usr.bin/xinstall/Makefile index d9d587302c0..773dd4ef877 100644 --- a/usr.bin/xinstall/Makefile +++ b/usr.bin/xinstall/Makefile @@ -7,10 +7,12 @@ SRCS= xinstall.c getid.c MAN= install.1 .PATH: ${.CURDIR}/../../contrib/mtree +.PATH: ${.CURDIR}/../../lib/libmd CFLAGS+= -I${.CURDIR}/../../contrib/mtree CFLAGS+= -I${.CURDIR}/../../lib/libnetbsd +CFLAGS+= -I${.CURDIR}/../../lib/libmd -DPADD+= ${LIBUTIL} ${LIBMD} -LDADD+= -lutil -lmd +DPADD+= ${LIBMD} +LDADD+= -lmd .include From aafcb7320759529843b0d0efa3c6a918aa1aaa50 Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Thu, 14 Feb 2013 12:22:40 +0000 Subject: [PATCH 0166/1476] Add USB API to read power draw on USB devices. Update usbconfig to print power draw on USB devices. MFC after: 2 weeks Submitted by: Matt Burke @ icritical.com --- lib/libusb/Makefile | 1 + lib/libusb/libusb20.3 | 10 +++++++++- lib/libusb/libusb20.c | 13 +++++++++++++ lib/libusb/libusb20.h | 1 + lib/libusb/libusb20_int.h | 2 ++ lib/libusb/libusb20_ugen20.c | 13 +++++++++++++ sys/dev/usb/usb_generic.c | 15 +++++++++++++++ sys/dev/usb/usb_ioctl.h | 3 ++- usr.sbin/usbconfig/dump.c | 8 ++++++-- 9 files changed, 62 insertions(+), 4 deletions(-) diff --git a/lib/libusb/Makefile b/lib/libusb/Makefile index d45dd567b43..9c2c9b45a87 100644 --- a/lib/libusb/Makefile +++ b/lib/libusb/Makefile @@ -190,6 +190,7 @@ MLINKS += libusb20.3 libusb20_dev_reset.3 MLINKS += libusb20.3 libusb20_dev_check_connected.3 MLINKS += libusb20.3 libusb20_dev_set_power_mode.3 MLINKS += libusb20.3 libusb20_dev_get_power_mode.3 +MLINKS += libusb20.3 libusb20_dev_get_power_usage.3 MLINKS += libusb20.3 libusb20_dev_set_alt_index.3 MLINKS += libusb20.3 libusb20_dev_get_device_desc.3 MLINKS += libusb20.3 libusb20_dev_alloc_config.3 diff --git a/lib/libusb/libusb20.3 b/lib/libusb/libusb20.3 index af80c6ca564..8d286f13723 100644 --- a/lib/libusb/libusb20.3 +++ b/lib/libusb/libusb20.3 @@ -26,7 +26,7 @@ .\" .\" $FreeBSD$ .\" -.Dd August 13, 2012 +.Dd February 14, 2013 .Dt LIBUSB20 3 .Os .Sh NAME @@ -149,6 +149,8 @@ USB access library (libusb -lusb) .Fn libusb20_dev_set_power_mode "struct libusb20_device *pdev" "uint8_t power_mode" .Ft uint8_t .Fn libusb20_dev_get_power_mode "struct libusb20_device *pdev" +.Ft uint16_t +.Fn libusb20_dev_get_power_usage "struct libusb20_device *pdev" .Ft int .Fn libusb20_dev_set_alt_index "struct libusb20_device *pdev" "uint8_t iface_index" "uint8_t alt_index" .Ft struct LIBUSB20_DEVICE_DESC_DECODED * @@ -740,6 +742,12 @@ USB device. . .Pp . +.Fn libusb20_dev_get_power_usage +returns the reported power usage in milliamps for the given USB device. +A power usage of zero typically means that the device is self powered. +. +.Pp +. .Fn libusb20_dev_set_alt_index will try to set the given alternate index for the given USB interface index. diff --git a/lib/libusb/libusb20.c b/lib/libusb/libusb20.c index aa459913ec9..ce7551131d1 100644 --- a/lib/libusb/libusb20.c +++ b/lib/libusb/libusb20.c @@ -71,6 +71,7 @@ dummy_callback(struct libusb20_transfer *xfer) #define dummy_check_connected (void *)dummy_int #define dummy_set_power_mode (void *)dummy_int #define dummy_get_power_mode (void *)dummy_int +#define dummy_get_power_usage (void *)dummy_int #define dummy_kernel_driver_active (void *)dummy_int #define dummy_detach_kernel_driver (void *)dummy_int #define dummy_do_request_sync (void *)dummy_int @@ -717,6 +718,18 @@ libusb20_dev_get_power_mode(struct libusb20_device *pdev) return (power_mode); } +uint16_t +libusb20_dev_get_power_usage(struct libusb20_device *pdev) +{ + int error; + uint16_t power_usage; + + error = pdev->methods->get_power_usage(pdev, &power_usage); + if (error) + power_usage = 0; + return (power_usage); +} + int libusb20_dev_set_alt_index(struct libusb20_device *pdev, uint8_t ifaceIndex, uint8_t altIndex) { diff --git a/lib/libusb/libusb20.h b/lib/libusb/libusb20.h index 87e05726206..81928b14346 100644 --- a/lib/libusb/libusb20.h +++ b/lib/libusb/libusb20.h @@ -255,6 +255,7 @@ int libusb20_dev_reset(struct libusb20_device *pdev); int libusb20_dev_check_connected(struct libusb20_device *pdev); int libusb20_dev_set_power_mode(struct libusb20_device *pdev, uint8_t power_mode); uint8_t libusb20_dev_get_power_mode(struct libusb20_device *pdev); +uint16_t libusb20_dev_get_power_usage(struct libusb20_device *pdev); int libusb20_dev_set_alt_index(struct libusb20_device *pdev, uint8_t iface_index, uint8_t alt_index); int libusb20_dev_get_info(struct libusb20_device *pdev, struct usb_device_info *pinfo); int libusb20_dev_get_iface_desc(struct libusb20_device *pdev, uint8_t iface_index, char *buf, uint8_t len); diff --git a/lib/libusb/libusb20_int.h b/lib/libusb/libusb20_int.h index 0251c5f6ed0..6705c630c86 100644 --- a/lib/libusb/libusb20_int.h +++ b/lib/libusb/libusb20_int.h @@ -105,6 +105,7 @@ typedef int (libusb20_process_t)(struct libusb20_device *pdev); typedef int (libusb20_reset_device_t)(struct libusb20_device *pdev); typedef int (libusb20_set_power_mode_t)(struct libusb20_device *pdev, uint8_t power_mode); typedef int (libusb20_get_power_mode_t)(struct libusb20_device *pdev, uint8_t *power_mode); +typedef int (libusb20_get_power_usage_t)(struct libusb20_device *pdev, uint16_t *power_usage); typedef int (libusb20_set_alt_index_t)(struct libusb20_device *pdev, uint8_t iface_index, uint8_t alt_index); typedef int (libusb20_set_config_index_t)(struct libusb20_device *pdev, uint8_t index); typedef int (libusb20_check_connected_t)(struct libusb20_device *pdev); @@ -127,6 +128,7 @@ typedef void (libusb20_tr_cancel_async_t)(struct libusb20_transfer *xfer); m(n, check_connected) \ m(n, set_power_mode) \ m(n, get_power_mode) \ + m(n, get_power_usage) \ m(n, set_alt_index) \ m(n, set_config_index) \ m(n, tr_cancel_async) \ diff --git a/lib/libusb/libusb20_ugen20.c b/lib/libusb/libusb20_ugen20.c index 2c677783d85..bff8e02e7c2 100644 --- a/lib/libusb/libusb20_ugen20.c +++ b/lib/libusb/libusb20_ugen20.c @@ -69,6 +69,7 @@ static libusb20_reset_device_t ugen20_reset_device; static libusb20_check_connected_t ugen20_check_connected; static libusb20_set_power_mode_t ugen20_set_power_mode; static libusb20_get_power_mode_t ugen20_get_power_mode; +static libusb20_get_power_usage_t ugen20_get_power_usage; static libusb20_kernel_driver_active_t ugen20_kernel_driver_active; static libusb20_detach_kernel_driver_t ugen20_detach_kernel_driver; static libusb20_do_request_sync_t ugen20_do_request_sync; @@ -638,6 +639,18 @@ ugen20_get_power_mode(struct libusb20_device *pdev, uint8_t *power_mode) return (0); /* success */ } +static int +ugen20_get_power_usage(struct libusb20_device *pdev, uint16_t *power_usage) +{ + int temp; + + if (ioctl(pdev->file_ctrl, USB_GET_POWER_USAGE, &temp)) { + return (LIBUSB20_ERROR_OTHER); + } + *power_usage = temp; + return (0); /* success */ +} + static int ugen20_kernel_driver_active(struct libusb20_device *pdev, uint8_t iface_index) diff --git a/sys/dev/usb/usb_generic.c b/sys/dev/usb/usb_generic.c index 34b7778e1f1..9557686e941 100644 --- a/sys/dev/usb/usb_generic.c +++ b/sys/dev/usb/usb_generic.c @@ -1840,6 +1840,17 @@ ugen_get_power_mode(struct usb_fifo *f) return (udev->power_mode); } +static int +ugen_get_power_usage(struct usb_fifo *f) +{ + struct usb_device *udev = f->udev; + + if (udev == NULL) + return (0); + + return (udev->power); +} + static int ugen_do_port_feature(struct usb_fifo *f, uint8_t port_no, uint8_t set, uint16_t feature) @@ -2202,6 +2213,10 @@ ugen_ioctl_post(struct usb_fifo *f, u_long cmd, void *addr, int fflags) *u.pint = ugen_get_power_mode(f); break; + case USB_GET_POWER_USAGE: + *u.pint = ugen_get_power_usage(f); + break; + case USB_SET_PORT_ENABLE: error = ugen_do_port_feature(f, *u.pint, 1, UHF_PORT_ENABLE); diff --git a/sys/dev/usb/usb_ioctl.h b/sys/dev/usb/usb_ioctl.h index 1d9b2230d05..979240f0573 100644 --- a/sys/dev/usb/usb_ioctl.h +++ b/sys/dev/usb/usb_ioctl.h @@ -277,7 +277,8 @@ struct usb_gen_quirk { #define USB_IFACE_DRIVER_DETACH _IOW ('U', 125, int) #define USB_GET_PLUGTIME _IOR ('U', 126, uint32_t) #define USB_READ_DIR _IOW ('U', 127, struct usb_read_dir) -/* 128 - 135 unused */ +/* 128 - 134 unused */ +#define USB_GET_POWER_USAGE _IOR ('U', 135, int) #define USB_SET_TX_FORCE_SHORT _IOW ('U', 136, int) #define USB_SET_TX_TIMEOUT _IOW ('U', 137, int) #define USB_GET_TX_FRAME_SIZE _IOR ('U', 138, int) diff --git a/usr.sbin/usbconfig/dump.c b/usr.sbin/usbconfig/dump.c index 7ee89dac99f..52dd132095d 100644 --- a/usr.sbin/usbconfig/dump.c +++ b/usr.sbin/usbconfig/dump.c @@ -225,13 +225,17 @@ dump_device_info(struct libusb20_device *pdev, uint8_t show_ifdrv) { char buf[128]; uint8_t n; + unsigned int usage; - printf("%s, cfg=%u md=%s spd=%s pwr=%s\n", + usage = libusb20_dev_get_power_usage(pdev); + + printf("%s, cfg=%u md=%s spd=%s pwr=%s (%umA)\n", libusb20_dev_get_desc(pdev), libusb20_dev_get_config_index(pdev), dump_mode(libusb20_dev_get_mode(pdev)), dump_speed(libusb20_dev_get_speed(pdev)), - dump_power_mode(libusb20_dev_get_power_mode(pdev))); + dump_power_mode(libusb20_dev_get_power_mode(pdev)), + usage); if (!show_ifdrv) return; From 86e220abc9e9754e0d078e4919120e07e4a9ae6b Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Thu, 14 Feb 2013 12:42:09 +0000 Subject: [PATCH 0167/1476] In case of failure of the pkg boostrap advice the user to either change the PACKAGESITE they use or install from ports directly indicating where the port is localted in the port collection Submitted by: kientzle --- usr.sbin/pkg/pkg.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/usr.sbin/pkg/pkg.c b/usr.sbin/pkg/pkg.c index 1b3146b2cf2..a3c3fec1128 100644 --- a/usr.sbin/pkg/pkg.c +++ b/usr.sbin/pkg/pkg.c @@ -411,6 +411,8 @@ bootstrap_pkg(void) fetchfail: warnx("Error fetching %s: %s", url, fetchLastErrString); + fprintf(stderr, "A pre-built version of pkg could not be found for your system.\n"); + fprintf(stderr, "Consider changing PACKAGESITE or installing it from ports: 'ports-mgmt/pkg'.\n"); cleanup: if (remote != NULL) From f4365abd91e82516025bddcc5dbf7b019c929bbe Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Thu, 14 Feb 2013 13:03:15 +0000 Subject: [PATCH 0168/1476] Allow fdescfs to be mounted from inside a jail MFC after: 1 week --- sys/fs/fdescfs/fdesc_vfsops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/fs/fdescfs/fdesc_vfsops.c b/sys/fs/fdescfs/fdesc_vfsops.c index c3dbccfc972..3ca06b9d3fe 100644 --- a/sys/fs/fdescfs/fdesc_vfsops.c +++ b/sys/fs/fdescfs/fdesc_vfsops.c @@ -237,4 +237,4 @@ static struct vfsops fdesc_vfsops = { .vfs_unmount = fdesc_unmount, }; -VFS_SET(fdesc_vfsops, fdescfs, VFCF_SYNTHETIC); +VFS_SET(fdesc_vfsops, fdescfs, VFCF_SYNTHETIC|VFCF_JAIL); From 3e687cf089c976bd6b0f387fb72794cba647f08d Mon Sep 17 00:00:00 2001 From: Philippe Charnier Date: Thu, 14 Feb 2013 14:44:08 +0000 Subject: [PATCH 0169/1476] remove old-style function definition reduce WARNS=6 output --- usr.sbin/kgmon/kgmon.c | 62 ++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 35 deletions(-) diff --git a/usr.sbin/kgmon/kgmon.c b/usr.sbin/kgmon/kgmon.c index c691d6ecf41..3bc53519b3f 100644 --- a/usr.sbin/kgmon/kgmon.c +++ b/usr.sbin/kgmon/kgmon.c @@ -37,10 +37,11 @@ static const char copyright[] = #if 0 static char sccsid[] = "@(#)kgmon.c 8.1 (Berkeley) 6/6/93"; #endif -static const char rcsid[] = - "$FreeBSD$"; #endif /* not lint */ +#include +__FBSDID("$FreeBSD$"); + #include #include #include @@ -77,7 +78,7 @@ int debug = 0; int getprof(struct kvmvars *); int getprofhz(struct kvmvars *); void kern_readonly(int); -int openfiles(char *, char *, struct kvmvars *); +int openfiles(const char *, char *, struct kvmvars *); void setprof(struct kvmvars *kvp, int state); void dumpstate(struct kvmvars *kvp); void reset(struct kvmvars *kvp); @@ -88,13 +89,14 @@ main(int argc, char **argv) { int ch, mode, disp, accessmode; struct kvmvars kvmvars; - char *system, *kmemf; + const char *systemname; + char *kmemf; if (seteuid(getuid()) != 0) { err(1, "seteuid failed\n"); } kmemf = NULL; - system = NULL; + systemname = NULL; while ((ch = getopt(argc, argv, "M:N:Bbhpr")) != -1) { switch((char)ch) { @@ -104,7 +106,7 @@ main(int argc, char **argv) break; case 'N': - system = optarg; + systemname = optarg; break; case 'B': @@ -137,16 +139,16 @@ main(int argc, char **argv) #define BACKWARD_COMPATIBILITY #ifdef BACKWARD_COMPATIBILITY if (*argv) { - system = *argv; + systemname = *argv; if (*++argv) { kmemf = *argv; ++kflag; } } #endif - if (system == NULL) - system = (char *)getbootfile(); - accessmode = openfiles(system, kmemf, &kvmvars); + if (systemname == NULL) + systemname = getbootfile(); + accessmode = openfiles(systemname, kmemf, &kvmvars); mode = getprof(&kvmvars); if (hflag) disp = GMON_PROF_OFF; @@ -173,7 +175,7 @@ main(int argc, char **argv) } static void -usage() +usage(void) { fprintf(stderr, "usage: kgmon [-Bbhrp] [-M core] [-N system]\n"); exit(1); @@ -183,10 +185,7 @@ usage() * Check that profiling is enabled and open any necessary files. */ int -openfiles(system, kmemf, kvp) - char *system; - char *kmemf; - struct kvmvars *kvp; +openfiles(const char *systemname, char *kmemf, struct kvmvars *kvp) { size_t size; int mib[3], state, openmode; @@ -212,11 +211,11 @@ openfiles(system, kmemf, kvp) } openmode = (Bflag || bflag || hflag || pflag || rflag) ? O_RDWR : O_RDONLY; - kvp->kd = kvm_openfiles(system, kmemf, NULL, openmode, errbuf); + kvp->kd = kvm_openfiles(systemname, kmemf, NULL, openmode, errbuf); if (kvp->kd == NULL) { if (openmode == O_RDWR) { openmode = O_RDONLY; - kvp->kd = kvm_openfiles(system, kmemf, NULL, O_RDONLY, + kvp->kd = kvm_openfiles(systemname, kmemf, NULL, O_RDONLY, errbuf); } if (kvp->kd == NULL) @@ -224,7 +223,7 @@ openfiles(system, kmemf, kvp) kern_readonly(GMON_PROF_ON); } if (kvm_nlist(kvp->kd, nl) < 0) - errx(3, "%s: no namelist", system); + errx(3, "%s: no namelist", systemname); if (!nl[N_GMONPARAM].n_value) errx(20, "profiling not defined in kernel"); return (openmode); @@ -234,8 +233,7 @@ openfiles(system, kmemf, kvp) * Suppress options that require a writable kernel. */ void -kern_readonly(mode) - int mode; +kern_readonly(int mode) { (void)fprintf(stderr, "kgmon: kernel read-only: "); @@ -256,8 +254,7 @@ kern_readonly(mode) * Get the state of kernel profiling. */ int -getprof(kvp) - struct kvmvars *kvp; +getprof(struct kvmvars *kvp) { size_t size; int mib[3]; @@ -311,9 +308,7 @@ getprof(kvp) * Enable or disable kernel profiling according to the state variable. */ void -setprof(kvp, state) - struct kvmvars *kvp; - int state; +setprof(struct kvmvars *kvp, int state) { struct gmonparam *p = (struct gmonparam *)nl[N_GMONPARAM].n_value; size_t sz; @@ -335,7 +330,7 @@ setprof(kvp, state) } (void)seteuid(getuid()); } else if (kvm_write(kvp->kd, (u_long)&p->state, (void *)&state, sz) - == sz) + == (ssize_t)sz) return; bad: warnx("warning: cannot turn profiling %s", @@ -346,8 +341,7 @@ bad: * Build the gmon.out file. */ void -dumpstate(kvp) - struct kvmvars *kvp; +dumpstate(struct kvmvars *kvp) { register FILE *fp; struct rawarc rawarc; @@ -463,8 +457,7 @@ dumpstate(kvp) * Get the profiling rate. */ int -getprofhz(kvp) - struct kvmvars *kvp; +getprofhz(struct kvmvars *kvp) { size_t size; int mib[2], profrate; @@ -490,8 +483,7 @@ getprofhz(kvp) * Reset the kernel profiling date structures. */ void -reset(kvp) - struct kvmvars *kvp; +reset(struct kvmvars *kvp) { char *zbuf; u_long biggest; @@ -509,13 +501,13 @@ reset(kvp) bzero(zbuf, biggest); if (kflag) { if (kvm_write(kvp->kd, (u_long)kvp->gpm.kcount, zbuf, - kvp->gpm.kcountsize) != kvp->gpm.kcountsize) + kvp->gpm.kcountsize) != (ssize_t)kvp->gpm.kcountsize) errx(13, "tickbuf zero: %s", kvm_geterr(kvp->kd)); if (kvm_write(kvp->kd, (u_long)kvp->gpm.froms, zbuf, - kvp->gpm.fromssize) != kvp->gpm.fromssize) + kvp->gpm.fromssize) != (ssize_t)kvp->gpm.fromssize) errx(14, "froms zero: %s", kvm_geterr(kvp->kd)); if (kvm_write(kvp->kd, (u_long)kvp->gpm.tos, zbuf, - kvp->gpm.tossize) != kvp->gpm.tossize) + kvp->gpm.tossize) != (ssize_t)kvp->gpm.tossize) errx(15, "tos zero: %s", kvm_geterr(kvp->kd)); return; } From 3c4223a65aaf232b4894657c9d105a799114995c Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Thu, 14 Feb 2013 15:17:53 +0000 Subject: [PATCH 0170/1476] Revert r246791 as it needs a security review first Reported by: gavin, rwatson --- sys/fs/fdescfs/fdesc_vfsops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/fs/fdescfs/fdesc_vfsops.c b/sys/fs/fdescfs/fdesc_vfsops.c index 3ca06b9d3fe..c3dbccfc972 100644 --- a/sys/fs/fdescfs/fdesc_vfsops.c +++ b/sys/fs/fdescfs/fdesc_vfsops.c @@ -237,4 +237,4 @@ static struct vfsops fdesc_vfsops = { .vfs_unmount = fdesc_unmount, }; -VFS_SET(fdesc_vfsops, fdescfs, VFCF_SYNTHETIC|VFCF_JAIL); +VFS_SET(fdesc_vfsops, fdescfs, VFCF_SYNTHETIC); From beb0f7e7d4eeaec7c44855ab2eeb8197b9403c95 Mon Sep 17 00:00:00 2001 From: Josh Paetzel Date: Thu, 14 Feb 2013 17:34:17 +0000 Subject: [PATCH 0171/1476] Resolve issue that caused WITNESS to report LORs. PR: kern/171838 Submitted by: Venkat Duvvuru MFC after: 2 weeks --- sys/dev/oce/oce_if.c | 9 +++++++++ sys/dev/oce/oce_if.h | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/sys/dev/oce/oce_if.c b/sys/dev/oce/oce_if.c index 2b4c181bef6..426acd9fe9a 100644 --- a/sys/dev/oce/oce_if.c +++ b/sys/dev/oce/oce_if.c @@ -1817,6 +1817,9 @@ oce_local_timer(void *arg) } +/* NOTE : This should only be called holding + * DEVICE_LOCK. +*/ static void oce_if_deactivate(POCE_SOFTC sc) { @@ -1846,11 +1849,17 @@ oce_if_deactivate(POCE_SOFTC sc) /* Stop intrs and finish any bottom halves pending */ oce_hw_intr_disable(sc); + /* Since taskqueue_drain takes a Giant Lock, We should not acquire + any other lock. So unlock device lock and require after + completing taskqueue_drain. + */ + UNLOCK(&sc->dev_lock); for (i = 0; i < sc->intr_count; i++) { if (sc->intrs[i].tq != NULL) { taskqueue_drain(sc->intrs[i].tq, &sc->intrs[i].task); } } + LOCK(&sc->dev_lock); /* Delete RX queue in card with flush param */ oce_stop_rx(sc); diff --git a/sys/dev/oce/oce_if.h b/sys/dev/oce/oce_if.h index cd355314717..6428f884bd4 100644 --- a/sys/dev/oce/oce_if.h +++ b/sys/dev/oce/oce_if.h @@ -493,7 +493,7 @@ struct oce_lock { #define LOCK_CREATE(lock, desc) { \ strncpy((lock)->name, (desc), MAX_LOCK_DESC_LEN); \ (lock)->name[MAX_LOCK_DESC_LEN] = '\0'; \ - mtx_init(&(lock)->mutex, (lock)->name, MTX_NETWORK_LOCK, MTX_DEF); \ + mtx_init(&(lock)->mutex, (lock)->name, NULL, MTX_DEF); \ } #define LOCK_DESTROY(lock) \ if (mtx_initialized(&(lock)->mutex))\ From a58ed3e91341136ddb5d15a84a82c6cc75424e25 Mon Sep 17 00:00:00 2001 From: Neel Natu Date: Thu, 14 Feb 2013 18:41:12 +0000 Subject: [PATCH 0172/1476] Add option "--unassign-pptdev=" to allow 'bhyvectl' to detach passthru devices from the guest. Obtained from: NetApp --- usr.sbin/bhyvectl/bhyvectl.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/usr.sbin/bhyvectl/bhyvectl.c b/usr.sbin/bhyvectl/bhyvectl.c index 4eb87f9d5b6..26c6c92b26c 100644 --- a/usr.sbin/bhyvectl/bhyvectl.c +++ b/usr.sbin/bhyvectl/bhyvectl.c @@ -185,6 +185,7 @@ usage(void) " [--get-vmcs-interruptibility]\n" " [--set-x2apic-state=]\n" " [--get-x2apic-state]\n" + " [--unassign-pptdev=]\n" " [--set-lowmem=]\n" " [--get-lowmem]\n" " [--set-highmem=]\n" @@ -218,6 +219,7 @@ static int set_cs, set_ds, set_es, set_fs, set_gs, set_ss, set_tr, set_ldtr; static int get_cs, get_ds, get_es, get_fs, get_gs, get_ss, get_tr, get_ldtr; static int set_x2apic_state, get_x2apic_state; enum x2apic_state x2apic_state; +static int unassign_pptdev, bus, slot, func; static int run; /* @@ -376,6 +378,7 @@ enum { SET_VMCS_ENTRY_INTERRUPTION_INFO, SET_CAP, CAPNAME, + UNASSIGN_PPTDEV, }; int @@ -425,6 +428,7 @@ main(int argc, char *argv[]) { "set-vmcs-entry-interruption-info", REQ_ARG, 0, SET_VMCS_ENTRY_INTERRUPTION_INFO }, { "capname", REQ_ARG, 0, CAPNAME }, + { "unassign-pptdev", REQ_ARG, 0, UNASSIGN_PPTDEV }, { "setcap", REQ_ARG, 0, SET_CAP }, { "getcap", NO_ARG, &getcap, 1 }, { "get-stats", NO_ARG, &get_stats, 1 }, @@ -672,6 +676,11 @@ main(int argc, char *argv[]) case CAPNAME: capname = optarg; break; + case UNASSIGN_PPTDEV: + unassign_pptdev = 1; + if (sscanf(optarg, "%d/%d/%d", &bus, &slot, &func) != 3) + usage(); + break; default: usage(); } @@ -805,6 +814,9 @@ main(int argc, char *argv[]) if (!error && set_x2apic_state) error = vm_set_x2apic_state(ctx, vcpu, x2apic_state); + if (!error && unassign_pptdev) + error = vm_unassign_pptdev(ctx, bus, slot, func); + if (!error && set_exception_bitmap) { error = vm_set_vmcs_field(ctx, vcpu, VMCS_EXCEPTION_BITMAP, exception_bitmap); From 252b1f6e22da42d050c33603294b038f344a01d9 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 14 Feb 2013 19:21:20 +0000 Subject: [PATCH 0173/1476] Assert that user address is never qremoved. No objections from: alc MFC after: 1 week --- sys/amd64/amd64/pmap.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c index c2debf7117e..4bdf38226e4 100644 --- a/sys/amd64/amd64/pmap.c +++ b/sys/amd64/amd64/pmap.c @@ -1481,6 +1481,7 @@ pmap_qremove(vm_offset_t sva, int count) va = sva; while (count-- > 0) { + KASSERT(va >= VM_MIN_KERNEL_ADDRESS, ("usermode va %lx", va)); pmap_kremove(va); va += PAGE_SIZE; } From bf94adb3e102749108abd5cf6923f9f4f97be8ee Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 14 Feb 2013 19:22:15 +0000 Subject: [PATCH 0174/1476] Print slightly more useful information on the 'bad pte' panic. No objections from: alc MFC after: 1 week --- sys/amd64/amd64/pmap.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c index 4bdf38226e4..f30a071d630 100644 --- a/sys/amd64/amd64/pmap.c +++ b/sys/amd64/amd64/pmap.c @@ -4446,8 +4446,10 @@ pmap_remove_pages(pmap_t pmap) pte = &pte[pmap_pte_index(pv->pv_va)]; tpte = *pte & ~PG_PTE_PAT; } - if ((tpte & PG_V) == 0) - panic("bad pte"); + if ((tpte & PG_V) == 0) { + panic("bad pte va %lx pte %lx", + pv->pv_va, tpte); + } /* * We cannot remove wired pages from a process' mapping at this time From 4e95969e0629b90eea5f975d3e0e0881ef69762c Mon Sep 17 00:00:00 2001 From: Niclas Zeising Date: Thu, 14 Feb 2013 19:26:58 +0000 Subject: [PATCH 0175/1476] FreeBSD uses #if __BSD_VISIBLE to hide non-standard functions, fix this. Noticed by: kib Approved by: kib --- include/string.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/string.h b/include/string.h index dc18a75161d..ceffcf6aeaa 100644 --- a/include/string.h +++ b/include/string.h @@ -74,7 +74,7 @@ char *strcasestr(const char *, const char *) __pure; #endif char *strcat(char * __restrict, const char * __restrict); char *strchr(const char *, int) __pure; -#if defined(_GNU_SOURCE) +#if __BSD_VISIBLE char *strchrnul(const char*, int) __pure; #endif int strcmp(const char *, const char *) __pure; From e593549587ada88ac9d3554436af2547d110221b Mon Sep 17 00:00:00 2001 From: Jamie Gritton Date: Thu, 14 Feb 2013 19:27:52 +0000 Subject: [PATCH 0176/1476] Handle (ignore) when a process disappears before it can be tracked. --- usr.sbin/jail/command.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/usr.sbin/jail/command.c b/usr.sbin/jail/command.c index b7d5168d8b4..3bdedad526b 100644 --- a/usr.sbin/jail/command.c +++ b/usr.sbin/jail/command.c @@ -66,7 +66,7 @@ int paralimit = -1; extern char **environ; static int run_command(struct cfjail *j); -static void add_proc(struct cfjail *j, pid_t pid); +static int add_proc(struct cfjail *j, pid_t pid); static void clear_procs(struct cfjail *j); static struct cfjail *find_proc(pid_t pid); static int term_procs(struct cfjail *j); @@ -542,13 +542,12 @@ run_command(struct cfjail *j) if (pid < 0) err(1, "fork"); if (pid > 0) { - if (bg) { + if (bg || !add_proc(j, pid)) { free(j->comline); j->comline = NULL; return 0; } else { paralimit--; - add_proc(j, pid); return 1; } } @@ -622,7 +621,7 @@ run_command(struct cfjail *j) /* * Add a process to the hash, tied to a jail. */ -static void +static int add_proc(struct cfjail *j, pid_t pid) { struct kevent ke; @@ -632,8 +631,11 @@ add_proc(struct cfjail *j, pid_t pid) if (!kq && (kq = kqueue()) < 0) err(1, "kqueue"); EV_SET(&ke, pid, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, NULL); - if (kevent(kq, &ke, 1, NULL, 0, NULL) < 0) + if (kevent(kq, &ke, 1, NULL, 0, NULL) < 0) { + if (errno == ESRCH) + return 0; err(1, "kevent"); + } ph = emalloc(sizeof(struct phash)); ph->j = j; ph->pid = pid; @@ -658,6 +660,7 @@ add_proc(struct cfjail *j, pid_t pid) TAILQ_INSERT_TAIL(&sleeping, j, tq); j->queue = &sleeping; } + return 1; } /* @@ -730,7 +733,7 @@ term_procs(struct cfjail *j) for (i = 0; i < pcnt; i++) if (ki[i].ki_jid == j->jid && kill(ki[i].ki_pid, SIGTERM) == 0) { - add_proc(j, ki[i].ki_pid); + (void)add_proc(j, ki[i].ki_pid); if (verbose > 0) { if (!noted) { noted = 1; From 174b5f385023a583e4a89f1e213ab586d332065a Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Thu, 14 Feb 2013 19:38:04 +0000 Subject: [PATCH 0177/1476] Make VM_NDOMAIN a kernel option so that it can be enabled from a kernel config file. Requested by: phk (ages ago) MFC after: 1 month --- sys/conf/options | 1 + sys/vm/vm_phys.c | 1 + sys/x86/acpica/srat.c | 2 ++ 3 files changed, 4 insertions(+) diff --git a/sys/conf/options b/sys/conf/options index 5722ac4ed78..ab5d1538638 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -588,6 +588,7 @@ VFS_BIO_DEBUG opt_global.h VM_KMEM_SIZE opt_vm.h VM_KMEM_SIZE_SCALE opt_vm.h VM_KMEM_SIZE_MAX opt_vm.h +VM_NDOMAIN opt_vm.h VM_NRESERVLEVEL opt_vm.h VM_LEVEL_0_ORDER opt_vm.h NO_SWAPPING opt_vm.h diff --git a/sys/vm/vm_phys.c b/sys/vm/vm_phys.c index 9cfea239e39..0609895221c 100644 --- a/sys/vm/vm_phys.c +++ b/sys/vm/vm_phys.c @@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$"); #include "opt_ddb.h" +#include "opt_vm.h" #include #include diff --git a/sys/x86/acpica/srat.c b/sys/x86/acpica/srat.c index 6c6eb8f1e3b..d440de71792 100644 --- a/sys/x86/acpica/srat.c +++ b/sys/x86/acpica/srat.c @@ -28,6 +28,8 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_vm.h" + #include #include #include From b2dc8cf4e2a1ea78bfa9524c7d5940a16e2559bb Mon Sep 17 00:00:00 2001 From: Joel Dahl Date: Thu, 14 Feb 2013 19:46:41 +0000 Subject: [PATCH 0178/1476] Fix date. --- usr.bin/csup/csup.1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr.bin/csup/csup.1 b/usr.bin/csup/csup.1 index 48acbd11afc..fcf63edb134 100644 --- a/usr.bin/csup/csup.1 +++ b/usr.bin/csup/csup.1 @@ -24,7 +24,7 @@ .\" $Id: cvsup.1,v 1.70 2003/03/04 18:23:46 jdp Exp $ .\" $FreeBSD$ .\" -.Dd Feburary 8, 2013 +.Dd February 8, 2013 .Dt CSUP 1 .Os FreeBSD .Sh NAME From 0cc7a79be644a760eff46b79319026fb99de3e44 Mon Sep 17 00:00:00 2001 From: Monthadar Al Jaberi Date: Thu, 14 Feb 2013 20:00:38 +0000 Subject: [PATCH 0179/1476] Mesh: QoS Control field bit flags fix. * The following bit flags where incroccetly defined: o Mesh Control Present o Mesh Power Save Level o RSPI This is now corrected according to Table 8.4 as per IEEE 802.11 2012; Approved by: adrian (mentor) --- sys/net80211/ieee80211.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sys/net80211/ieee80211.h b/sys/net80211/ieee80211.h index a25cd7db686..a3da7397825 100644 --- a/sys/net80211/ieee80211.h +++ b/sys/net80211/ieee80211.h @@ -200,11 +200,11 @@ struct ieee80211_qosframe_addr4 { #define IEEE80211_QOS_EOSP_S 4 #define IEEE80211_QOS_TID 0x0f /* qos[1] byte used for all frames sent by mesh STAs in a mesh BSS */ -#define IEEE80211_QOS_MC 0x10 /* Mesh control */ +#define IEEE80211_QOS_MC 0x01 /* Mesh control */ /* Mesh power save level*/ -#define IEEE80211_QOS_MESH_PSL 0x20 +#define IEEE80211_QOS_MESH_PSL 0x02 /* Mesh Receiver Service Period Initiated */ -#define IEEE80211_QOS_RSPI 0x40 +#define IEEE80211_QOS_RSPI 0x04 /* bits 11 to 15 reserved */ /* does frame have QoS sequence control data */ From e469d5a70f7968e2732f1681edf302a77828d127 Mon Sep 17 00:00:00 2001 From: Xin LI Date: Thu, 14 Feb 2013 21:02:18 +0000 Subject: [PATCH 0180/1476] Eliminate real_LZ4_uncompress. It's unused and does not perform sufficient check against input stream (i.e. it could read beyond specified input buffer). --- .../opensolaris/uts/common/fs/zfs/lz4.c | 138 +----------------- 1 file changed, 7 insertions(+), 131 deletions(-) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/lz4.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/lz4.c index d2f2bc3e5a4..0f55cc896f7 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/lz4.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/lz4.c @@ -36,7 +36,6 @@ static int real_LZ4_compress(const char *source, char *dest, int isize, int osize); -static int real_LZ4_uncompress(const char *source, char *dest, int osize); static int LZ4_compressBound(int isize); static int LZ4_uncompress_unknownOutputSize(const char *source, char *dest, int isize, int maxOutputSize); @@ -104,16 +103,6 @@ lz4_decompress(void *s_start, void *d_start, size_t s_len, size_t d_len, int n) * situations (input data not compressible) worst case size * evaluation is provided by function LZ4_compressBound(). * - * real_LZ4_uncompress() : - * osize : is the output size, therefore the original size - * return : the number of bytes read in the source buffer. - * If the source stream is malformed, the function will stop - * decoding and return a negative result, indicating the byte - * position of the faulty instruction. This function never - * writes beyond dest + osize, and is therefore protected - * against malicious data packets. - * note : destination buffer must be already allocated - * * Advanced Functions * * LZ4_compressBound() : @@ -137,7 +126,6 @@ lz4_decompress(void *s_start, void *d_start, size_t s_len, size_t d_len, int n) * maxOutputSize, and is therefore protected against malicious * data packets. * note : Destination buffer must be already allocated. - * This version is slightly slower than real_LZ4_uncompress() * * LZ4_compressCtx() : * This function explicitly handles the CTX memory structure. @@ -879,127 +867,15 @@ real_LZ4_compress(const char *source, char *dest, int isize, int osize) /* Decompression functions */ /* - * Note: The decoding functions real_LZ4_uncompress() and - * LZ4_uncompress_unknownOutputSize() are safe against "buffer overflow" - * attack type. They will never write nor read outside of the provided - * output buffers. LZ4_uncompress_unknownOutputSize() also insures that - * it will never read outside of the input buffer. A corrupted input - * will produce an error result, a negative int, indicating the position - * of the error within input stream. + * Note: The decoding functionLZ4_uncompress_unknownOutputSize() is safe + * against "buffer overflow" attack type. They will never write nor + * read outside of the provided output buffers. + * LZ4_uncompress_unknownOutputSize() also insures that it will never + * read outside of the input buffer. A corrupted input will produce + * an error result, a negative int, indicating the position of the + * error within input stream. */ -static int -real_LZ4_uncompress(const char *source, char *dest, int osize) -{ - /* Local Variables */ - const BYTE *restrict ip = (const BYTE *) source; - const BYTE *ref; - - BYTE *op = (BYTE *) dest; - BYTE *const oend = op + osize; - BYTE *cpy; - - unsigned token; - - size_t length; - size_t dec32table[] = {0, 3, 2, 3, 0, 0, 0, 0}; -#if LZ4_ARCH64 - size_t dec64table[] = {0, 0, 0, (size_t)-1, 0, 1, 2, 3}; -#endif - - /* Main Loop */ - for (;;) { - /* get runlength */ - token = *ip++; - if ((length = (token >> ML_BITS)) == RUN_MASK) { - size_t len; - for (; (len = *ip++) == 255; length += 255) { - } - length += len; - } - /* copy literals */ - cpy = op + length; - if unlikely(cpy > oend - COPYLENGTH) { - if (cpy != oend) - /* Error: we must necessarily stand at EOF */ - goto _output_error; - (void) memcpy(op, ip, length); - ip += length; - break; /* EOF */ - } - LZ4_WILDCOPY(ip, op, cpy); - ip -= (op - cpy); - op = cpy; - - /* get offset */ - LZ4_READ_LITTLEENDIAN_16(ref, cpy, ip); - ip += 2; - if unlikely(ref < (BYTE * const) dest) - /* - * Error: offset create reference outside destination - * buffer - */ - goto _output_error; - - /* get matchlength */ - if ((length = (token & ML_MASK)) == ML_MASK) { - for (; *ip == 255; length += 255) { - ip++; - } - length += *ip++; - } - /* copy repeated sequence */ - if unlikely(op - ref < STEPSIZE) { -#if LZ4_ARCH64 - size_t dec64 = dec64table[op-ref]; -#else - const int dec64 = 0; -#endif - op[0] = ref[0]; - op[1] = ref[1]; - op[2] = ref[2]; - op[3] = ref[3]; - op += 4; - ref += 4; - ref -= dec32table[op-ref]; - A32(op) = A32(ref); - op += STEPSIZE - 4; - ref -= dec64; - } else { - LZ4_COPYSTEP(ref, op); - } - cpy = op + length - (STEPSIZE - 4); - if (cpy > oend - COPYLENGTH) { - if (cpy > oend) - /* - * Error: request to write beyond destination - * buffer - */ - goto _output_error; - LZ4_SECURECOPY(ref, op, (oend - COPYLENGTH)); - while (op < cpy) - *op++ = *ref++; - op = cpy; - if (op == oend) - /* - * Check EOF (should never happen, since last - * 5 bytes are supposed to be literals) - */ - goto _output_error; - continue; - } - LZ4_SECURECOPY(ref, op, cpy); - op = cpy; /* correction */ - } - - /* end of decoding */ - return (int)(((char *)ip) - source); - - /* write overflow error detected */ - _output_error: - return (int)(-(((char *)ip) - source)); -} - static int LZ4_uncompress_unknownOutputSize(const char *source, char *dest, int isize, int maxOutputSize) From d3087c8fe00e8b7340cbbc25d7e7d9b6f7b0b062 Mon Sep 17 00:00:00 2001 From: Niclas Zeising Date: Thu, 14 Feb 2013 21:29:55 +0000 Subject: [PATCH 0181/1476] Change examples to be consistent with what style(9) says. Approved by: joel (mentor) MFC After: 2 weeks --- lib/libc/net/getaddrinfo.3 | 10 +++++----- lib/libc/net/getnameinfo.3 | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/libc/net/getaddrinfo.3 b/lib/libc/net/getaddrinfo.3 index b09c0683e1b..3419809915f 100644 --- a/lib/libc/net/getaddrinfo.3 +++ b/lib/libc/net/getaddrinfo.3 @@ -18,7 +18,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 6, 2009 +.Dd February 14, 2013 .Dt GETADDRINFO 3 .Os .Sh NAME @@ -339,7 +339,7 @@ hints.ai_socktype = SOCK_STREAM; error = getaddrinfo("www.kame.net", "http", &hints, &res0); if (error) { errx(1, "%s", gai_strerror(error)); - /*NOTREACHED*/ + /* NOTREACHED */ } s = -1; for (res = res0; res; res = res->ai_next) { @@ -361,7 +361,7 @@ for (res = res0; res; res = res->ai_next) { } if (s < 0) { err(1, "%s", cause); - /*NOTREACHED*/ + /* NOTREACHED */ } freeaddrinfo(res0); .Ed @@ -383,7 +383,7 @@ hints.ai_flags = AI_PASSIVE; error = getaddrinfo(NULL, "http", &hints, &res0); if (error) { errx(1, "%s", gai_strerror(error)); - /*NOTREACHED*/ + /* NOTREACHED */ } nsock = 0; for (res = res0; res && nsock < MAXSOCK; res = res->ai_next) { @@ -405,7 +405,7 @@ for (res = res0; res && nsock < MAXSOCK; res = res->ai_next) { } if (nsock == 0) { err(1, "%s", cause); - /*NOTREACHED*/ + /* NOTREACHED */ } freeaddrinfo(res0); .Ed diff --git a/lib/libc/net/getnameinfo.3 b/lib/libc/net/getnameinfo.3 index 327c1359778..e508e5ddbd8 100644 --- a/lib/libc/net/getnameinfo.3 +++ b/lib/libc/net/getnameinfo.3 @@ -18,7 +18,7 @@ .\" .\" $FreeBSD$ .\" -.Dd February 28, 2007 +.Dd February 14, 2013 .Dt GETNAMEINFO 3 .Os .Sh NAME @@ -157,7 +157,7 @@ char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV)) { errx(1, "could not get numeric hostname"); - /*NOTREACHED*/ + /* NOTREACHED */ } printf("host=%s, serv=%s\en", hbuf, sbuf); .Ed @@ -170,7 +170,7 @@ char hbuf[NI_MAXHOST]; if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0, NI_NAMEREQD)) { errx(1, "could not resolve hostname"); - /*NOTREACHED*/ + /* NOTREACHED */ } printf("host=%s\en", hbuf); .Ed From 2ec5c91481678d4a57d7cb62c4be11cf61c0c7b1 Mon Sep 17 00:00:00 2001 From: Kirk McKusick Date: Fri, 15 Feb 2013 01:00:48 +0000 Subject: [PATCH 0182/1476] Update fsck_ffs buffer cache manager to use TAILQ macros. No functional changes. --- sbin/fsck_ffs/fsck.h | 17 +++++++++------- sbin/fsck_ffs/fsutil.c | 45 ++++++++++++++++++++---------------------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/sbin/fsck_ffs/fsck.h b/sbin/fsck_ffs/fsck.h index 4717760acad..dfb2ade37d5 100644 --- a/sbin/fsck_ffs/fsck.h +++ b/sbin/fsck_ffs/fsck.h @@ -67,10 +67,13 @@ #include #include +#include + #define MAXDUP 10 /* limit on dup blks (per inode) */ #define MAXBAD 10 /* limit on bad blks (per inode) */ -#define MAXBUFSPACE 40*1024 /* maximum space to allocate to buffers */ -#define INOBUFSIZE 56*1024 /* size of buffer to read inodes in pass1 */ +#define MINBUFS 10 /* minimum number of buffers required */ +#define MAXBUFS 40 /* maximum space to allocate to buffers */ +#define INOBUFSIZE 64*1024 /* size of buffer to read inodes in pass1 */ union dinode { struct ufs1_dinode dp1; @@ -130,8 +133,7 @@ struct inostatlist { * buffer cache structure. */ struct bufarea { - struct bufarea *b_next; /* free list queue */ - struct bufarea *b_prev; /* free list queue */ + TAILQ_ENTRY(bufarea) b_list; /* buffer list */ ufs2_daddr_t b_bno; int b_size; int b_errs; @@ -159,10 +161,11 @@ struct bufarea { (bp)->b_un.b_indir2[i] = (val); \ } while (0) -#define B_INUSE 1 +/* + * Buffer flags + */ +#define B_INUSE 0x00000001 /* Buffer is in use */ -#define MINBUFS 5 /* minimum number of buffers required */ -struct bufarea bufhead; /* head of list of other blks in filesys */ struct bufarea sblk; /* file system superblock */ struct bufarea cgblk; /* cylinder group blocks */ struct bufarea *pdirbp; /* current directory contents */ diff --git a/sbin/fsck_ffs/fsutil.c b/sbin/fsck_ffs/fsutil.c index 9bf61d13633..f3a640af8ee 100644 --- a/sbin/fsck_ffs/fsutil.c +++ b/sbin/fsck_ffs/fsutil.c @@ -67,6 +67,8 @@ long diskreads, totalreads; /* Disk cache statistics */ struct timeval slowio_starttime; int slowio_delay_usec = 10000; /* Initial IO delay for background fsck */ int slowio_pollcnt; +static TAILQ_HEAD(buflist, bufarea) bufhead; /* head of buffer cache list */ +static int numbufs; /* size of buffer cache */ int ftypeok(union dinode *dp) @@ -162,8 +164,8 @@ bufinit(void) errx(EEXIT, "cannot allocate buffer pool"); cgblk.b_un.b_buf = bufp; initbarea(&cgblk); - bufhead.b_next = bufhead.b_prev = &bufhead; - bufcnt = MAXBUFSPACE / sblock.fs_bsize; + TAILQ_INIT(&bufhead); + bufcnt = MAXBUFS; if (bufcnt < MINBUFS) bufcnt = MINBUFS; for (i = 0; i < bufcnt; i++) { @@ -175,13 +177,10 @@ bufinit(void) errx(EEXIT, "cannot allocate buffer pool"); } bp->b_un.b_buf = bufp; - bp->b_prev = &bufhead; - bp->b_next = bufhead.b_next; - bufhead.b_next->b_prev = bp; - bufhead.b_next = bp; + TAILQ_INSERT_HEAD(&bufhead, bp, b_list); initbarea(bp); } - bufhead.b_size = i; /* save number of buffers */ + numbufs = i; /* save number of buffers */ } /* @@ -192,23 +191,19 @@ getdatablk(ufs2_daddr_t blkno, long size) { struct bufarea *bp; - for (bp = bufhead.b_next; bp != &bufhead; bp = bp->b_next) + TAILQ_FOREACH(bp, &bufhead, b_list) if (bp->b_bno == fsbtodb(&sblock, blkno)) goto foundit; - for (bp = bufhead.b_prev; bp != &bufhead; bp = bp->b_prev) + TAILQ_FOREACH_REVERSE(bp, &bufhead, buflist, b_list) if ((bp->b_flags & B_INUSE) == 0) break; - if (bp == &bufhead) + if (bp == NULL) errx(EEXIT, "deadlocked buffer pool"); getblk(bp, blkno, size); /* fall through */ foundit: - bp->b_prev->b_next = bp->b_next; - bp->b_next->b_prev = bp->b_prev; - bp->b_prev = &bufhead; - bp->b_next = bufhead.b_next; - bufhead.b_next->b_prev = bp; - bufhead.b_next = bp; + TAILQ_REMOVE(&bufhead, bp, b_list); + TAILQ_INSERT_HEAD(&bufhead, bp, b_list); bp->b_flags |= B_INUSE; return (bp); } @@ -274,7 +269,7 @@ void ckfini(int markclean) { struct bufarea *bp, *nbp; - int ofsmodified, cnt = 0; + int ofsmodified, cnt; if (bkgrdflag) { unlink(snapname); @@ -295,6 +290,10 @@ ckfini(int markclean) rerun = 1; } } + if (debug && totalreads > 0) + printf("cache with %d buffers missed %ld of %ld (%d%%)\n", + numbufs, diskreads, totalreads, + (int)(diskreads * 100 / totalreads)); if (fswritefd < 0) { (void)close(fsreadfd); return; @@ -309,15 +308,16 @@ ckfini(int markclean) } flush(fswritefd, &cgblk); free(cgblk.b_un.b_buf); - for (bp = bufhead.b_prev; bp && bp != &bufhead; bp = nbp) { + cnt = 0; + TAILQ_FOREACH_REVERSE_SAFE(bp, &bufhead, buflist, b_list, nbp) { + TAILQ_REMOVE(&bufhead, bp, b_list); cnt++; flush(fswritefd, bp); - nbp = bp->b_prev; free(bp->b_un.b_buf); free((char *)bp); } - if (bufhead.b_size != cnt) - errx(EEXIT, "panic: lost %d buffers", bufhead.b_size - cnt); + if (numbufs != cnt) + errx(EEXIT, "panic: lost %d buffers", numbufs - cnt); pbp = pdirbp = (struct bufarea *)0; if (cursnapshot == 0 && sblock.fs_clean != markclean) { if ((sblock.fs_clean = markclean) != 0) { @@ -343,9 +343,6 @@ ckfini(int markclean) rerun = 1; } } - if (debug && totalreads > 0) - printf("cache missed %ld of %ld (%d%%)\n", diskreads, - totalreads, (int)(diskreads * 100 / totalreads)); (void)close(fsreadfd); (void)close(fswritefd); } From dc9b4fcacb1d7c7252064caca283c845fbaa4661 Mon Sep 17 00:00:00 2001 From: Gleb Smirnoff Date: Fri, 15 Feb 2013 07:58:51 +0000 Subject: [PATCH 0183/1476] Fix compilation warning. Sponsored by: Nginx, Inc --- sys/netgraph/ng_parse.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sys/netgraph/ng_parse.c b/sys/netgraph/ng_parse.c index e8cbc9ab28a..10398bcda42 100644 --- a/sys/netgraph/ng_parse.c +++ b/sys/netgraph/ng_parse.c @@ -1236,6 +1236,7 @@ ng_parse_composite(const struct ng_parse_type *type, const char *s, distinguish name from values by seeing if the next token is an equals sign */ if (ctype != CT_STRUCT) { + u_long ul; int len2, off2; char *eptr; @@ -1259,11 +1260,12 @@ ng_parse_composite(const struct ng_parse_type *type, const char *s, } /* Index was specified explicitly; parse it */ - index = (u_int)strtoul(s + *off, &eptr, 0); - if (index < 0 || eptr - (s + *off) != len) { + ul = strtoul(s + *off, &eptr, 0); + if (ul == ULONG_MAX || eptr - (s + *off) != len) { error = EINVAL; goto done; } + index = (u_int)ul; nextIndex = index + 1; *off += len + len2; } else { /* a structure field */ From e2a55a0021dc0b7d7c07300d64d698f9eb62ebdc Mon Sep 17 00:00:00 2001 From: Gleb Smirnoff Date: Fri, 15 Feb 2013 09:03:56 +0000 Subject: [PATCH 0184/1476] Finish the r244185. This fixes ever growing counter of pfsync bad length packets, which was actually harmless. Note that peers with different version of head/ may grow this counter, but it is harmless - all pfsync data is processed. Reported & tested by: Anton Yuzhaninov Sponsored by: Nginx, Inc --- sys/net/if_pfsync.h | 12 ------------ sys/netpfil/pf/if_pfsync.c | 3 +-- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/sys/net/if_pfsync.h b/sys/net/if_pfsync.h index a84a0b8620e..29d4b23ce22 100644 --- a/sys/net/if_pfsync.h +++ b/sys/net/if_pfsync.h @@ -67,8 +67,6 @@ #define PFSYNC_ACT_EOF 12 /* end of frame */ #define PFSYNC_ACT_MAX 13 -#define PFSYNC_HMAC_LEN 20 - /* * A pfsync frame is built from a header followed by several sections which * are all prefixed with their own subheaders. Frames must be terminated with @@ -205,18 +203,8 @@ struct pfsync_tdb { u_int8_t _pad[2]; } __packed; -/* - * EOF - */ - -struct pfsync_eof { - u_int8_t hmac[PFSYNC_HMAC_LEN]; -} __packed; - #define PFSYNC_HDRLEN sizeof(struct pfsync_header) - - /* * Names for PFSYNC sysctl objects */ diff --git a/sys/netpfil/pf/if_pfsync.c b/sys/netpfil/pf/if_pfsync.c index 141ee6d4eff..93f07295674 100644 --- a/sys/netpfil/pf/if_pfsync.c +++ b/sys/netpfil/pf/if_pfsync.c @@ -99,8 +99,7 @@ __FBSDID("$FreeBSD$"); #define PFSYNC_MINPKT ( \ sizeof(struct ip) + \ sizeof(struct pfsync_header) + \ - sizeof(struct pfsync_subheader) + \ - sizeof(struct pfsync_eof)) + sizeof(struct pfsync_subheader) ) struct pfsync_pkt { struct ip *ip; From fa358104b133c9bd4d3d53a34f2bbb6094fea80f Mon Sep 17 00:00:00 2001 From: Sergey Kandaurov Date: Fri, 15 Feb 2013 09:10:01 +0000 Subject: [PATCH 0185/1476] Remove write only assignments and thus fix the build after struct bufarea TAILQ conversion (r246812). --- sbin/fsdb/fsdbutil.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sbin/fsdb/fsdbutil.c b/sbin/fsdb/fsdbutil.c index eaea3db79fd..91153d77f20 100644 --- a/sbin/fsdb/fsdbutil.c +++ b/sbin/fsdb/fsdbutil.c @@ -239,7 +239,6 @@ printindir(ufs2_daddr_t blk, int level, char *bufp) /* for the final indirect level, don't use the cache */ bp = &buf; bp->b_un.b_buf = bufp; - bp->b_prev = bp->b_next = bp; initbarea(bp); getblk(bp, blk, sblock.fs_bsize); From f108ef834e1e4aa3067ab139f1818b4a980f7fb7 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Fri, 15 Feb 2013 10:44:07 +0000 Subject: [PATCH 0186/1476] setbuf(3): Remove bugs section about ancient versions of BSD. --- lib/libc/stdio/setbuf.3 | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/lib/libc/stdio/setbuf.3 b/lib/libc/stdio/setbuf.3 index 2eda0e62b15..337a7c55deb 100644 --- a/lib/libc/stdio/setbuf.3 +++ b/lib/libc/stdio/setbuf.3 @@ -32,7 +32,7 @@ .\" @(#)setbuf.3 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" -.Dd June 4, 1993 +.Dd February 15, 2013 .Dt SETBUF 3 .Os .Sh NAME @@ -195,19 +195,3 @@ and functions conform to .St -isoC . -.Sh BUGS -The -.Fn setbuffer -and -.Fn setlinebuf -functions are not portable to versions of -.Bx -before -.Bx 4.2 . -On -.Bx 4.2 -and -.Bx 4.3 -systems, -.Fn setbuf -always uses a suboptimal buffer size and should be avoided. From ab15d8039eb1bed48f07136aef79fb6893bb920c Mon Sep 17 00:00:00 2001 From: Sergey Kandaurov Date: Fri, 15 Feb 2013 13:00:20 +0000 Subject: [PATCH 0187/1476] Add support of passing SCM_BINTIME ancillary data object for PF_LOCAL sockets. PR: kern/175883 Submitted by: Andrey Simonenko Discussed with: glebius, phk MFC after: 2 weeks --- sys/kern/uipc_usrreq.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index c732c7004df..a6c308f80fb 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -1798,6 +1798,7 @@ unp_internalize(struct mbuf **controlp, struct thread *td) struct mbuf *control = *controlp; struct proc *p = td->td_proc; struct filedesc *fdescp = p->p_fd; + struct bintime *bt; struct cmsghdr *cm = mtod(control, struct cmsghdr *); struct cmsgcred *cmcred; struct file **rp; @@ -1906,6 +1907,18 @@ unp_internalize(struct mbuf **controlp, struct thread *td) microtime(tv); break; + case SCM_BINTIME: + *controlp = sbcreatecontrol(NULL, sizeof(*bt), + SCM_BINTIME, SOL_SOCKET); + if (*controlp == NULL) { + error = ENOBUFS; + goto out; + } + bt = (struct bintime *) + CMSG_DATA(mtod(*controlp, struct cmsghdr *)); + bintime(bt); + break; + default: error = EINVAL; goto out; From 2f10c3e258216a4694be7302c4a039b26be832bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Fri, 15 Feb 2013 13:51:54 +0000 Subject: [PATCH 0188/1476] import ldns 1.6.16 --- Changelog | 48 + Makefile.in | 955 +++--- buffer.c | 3 +- configure | 153 +- configure.ac | 62 +- contrib/python/Changelog | 66 + contrib/python/Makefile | 63 +- contrib/python/docs/source/conf.py | 4 +- contrib/python/docs/source/install.rst | 56 +- contrib/python/examples/ldns-keygen.py | 2 +- .../python/examples/python3/ldns-signzone.py | 65 + contrib/python/examples/test_buffer.py | 843 ++++++ contrib/python/examples/test_dname.py | 474 +++ contrib/python/examples/test_rdf.py | 805 +++++ contrib/python/examples/test_rr.py | 2383 +++++++++++++++ contrib/python/file_py3.i | 3 +- contrib/python/ldns.i | 82 +- contrib/python/ldns_buffer.i | 721 +++-- contrib/python/ldns_dname.i | 645 +++- contrib/python/ldns_dnssec.i | 25 +- contrib/python/ldns_packet.i | 2 +- contrib/python/ldns_rdf.i | 882 ++++-- contrib/python/ldns_rr.i | 2653 ++++++++++++----- dane.c | 742 +++++ dname.c | 91 +- dnssec.c | 43 +- dnssec_sign.c | 33 +- dnssec_verify.c | 61 +- dnssec_zone.c | 27 +- doc/doxyparse.pl | 19 +- doc/function_manpages | 5 + drill/Makefile.in | 8 +- drill/chasetrace.c | 14 +- drill/config.h.in | 3 + drill/configure | 58 +- drill/configure.ac | 26 +- drill/dnssec.c | 107 +- drill/{drill.1 => drill.1.in} | 12 + drill/drill.c | 30 +- drill/drill.h | 1 - drill/drill_util.c | 32 +- drill/drill_util.h | 7 + drill/securetrace.c | 4 +- drill/work.c | 26 +- error.c | 29 + examples/Makefile.in | 39 +- examples/config.h.in | 15 + examples/configure | 123 +- examples/configure.ac | 48 +- examples/ldns-dane.1.in | 179 ++ examples/ldns-dane.c | 1722 +++++++++++ examples/ldns-gen-zone.c | 2 +- examples/ldns-keyfetcher.c | 25 +- examples/ldns-keygen.1 | 8 +- examples/ldns-notify.c | 7 +- examples/ldns-read-zone.1 | 11 + examples/ldns-read-zone.c | 82 +- examples/ldns-signzone.c | 31 +- examples/ldns-test-edns.c | 24 +- examples/ldns-testns.c | 2 +- examples/ldns-testpkts.c | 43 +- examples/ldns-testpkts.h | 7 +- examples/ldns-update.c | 18 +- ...ns-verify-zone.1 => ldns-verify-zone.1.in} | 13 + examples/ldns-verify-zone.c | 34 +- examples/ldns-zsplit.c | 1 + higher.c | 1 + host2str.c | 112 +- host2wire.c | 48 +- keys.c | 50 +- ldns/buffer.h | 5 +- ldns/common.h.in | 5 + ldns/config.h.in | 15 + ldns/dane.h | 244 ++ ldns/dname.h | 9 + ldns/dnssec.h | 1 + ldns/dnssec_verify.h | 1 + ldns/dnssec_zone.h | 1 - ldns/error.h | 17 +- ldns/host2str.h | 18 +- ldns/keys.h | 22 +- ldns/ldns.h | 1 + ldns/rdata.h | 2 + ldns/resolver.h | 4 + ldns/rr.h | 4 +- ldns/util.h.in | 2 + ldns_symbols.def | 783 ----- libdns.doxygen | 189 +- net.c | 17 +- packet.c | 136 +- parse.c | 4 +- resolver.c | 59 +- rr.c | 32 +- str2host.c | 5 +- tsig.c | 12 +- util.c | 9 +- 96 files changed, 13278 insertions(+), 3337 deletions(-) create mode 100644 contrib/python/Changelog create mode 100755 contrib/python/examples/python3/ldns-signzone.py create mode 100755 contrib/python/examples/test_buffer.py create mode 100755 contrib/python/examples/test_dname.py create mode 100755 contrib/python/examples/test_rdf.py create mode 100644 contrib/python/examples/test_rr.py create mode 100644 dane.c rename drill/{drill.1 => drill.1.in} (93%) create mode 100644 examples/ldns-dane.1.in create mode 100644 examples/ldns-dane.c rename examples/{ldns-verify-zone.1 => ldns-verify-zone.1.in} (84%) create mode 100644 ldns/dane.h delete mode 100644 ldns_symbols.def diff --git a/Changelog b/Changelog index 93e53931d84..845d5b8a738 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,51 @@ +1.6.16 2012-11-13 + * Fix Makefile to build pyldns with BSD make + * Fix typo in exporting b32_* symbols to make pyldns load again + * Allow leaving the RR owner name empty in ldns-testns datafiles. + * Fix fail to create NSEC3 bitmap for empty non-terminal (bug + introduced in 1.6.14). + +1.6.15 2012-10-25 + * Remove LDNS_STATUS_EXISTS_ERR from ldns/error.h to make ldns + binary compatible with earlier releases again. + +1.6.14 2012-10-23 + * DANE support (RFC6698), including ldns-dane example tool. + * Configurable default CA certificate repository for ldns-dane with + --with-ca-file=CAFILE and --with-ca-path=CAPATH + * Configurable default trust anchor with --with-trust-anchor=FILE + for drill, ldns-verify-zone and ldns-dane + * bugfix #474: Define socklen_t when undefined (like in Win32) + * bugfix #473: Dead code removal and resource leak fix in drill + * bugfix #471: Let ldns_resolver_push_dnssec_anchor accept DS RR's too. + * Various bugfixes from code reviews from CZ.NIC and Paul Wouters + * ldns-notify TSIG option argument checking + * Let ldns_resolver_nameservers_randomize keep nameservers and rtt's + in sync. + * Let ldns_pkt_push_rr now return false on (memory) errors. + * Make buffer_export comply to documentation and fix buffer2str + * Various improvements and fixes of pyldns from Katel Slany + now documented in their own Changelog. + * bugfix: Make ldns_resolver_pop_nameserver clear the array when + there was only one. + * bugfix #459: Remove ldns_symbols and export symbols based on regex + * bugfix #458: Track all newly created signatures when signing. + * bugfix #454: Only set -g and -O2 CFLAGS when no CFLAGS was given. + * bugfix #457: Memory leak fix for ldns_key_new_frm_algorithm. + * pyldns memory handling fixes and the python3/ldns-signzone.py + examples script contribution from Karel Slany. + * bugfix #450: Base # bytes for P, G and Y (T) on the guaranteed + to be bigger (or equal) P in ldns_key_dsa2bin. + * bugfix #449: Deep free cloned rdf's in ldns_tsig_mac_new. + * bugfix #448: Copy nameserver value (in stead of reference) of the + answering nameserver to the answer packet in ldns_send_buffer, so + the original value may be deep freed with the ldns_resolver struct. + * New -0 option for ldns-read-zone to replace inception, expiration + and signature rdata fields with (null). Thanks Paul Wouters. + * New -p option for ldns-read-zone to prepend-pad SOA serial to take + up ten characters. + * Return error if printing RR fails due to unknown/null RDATA. + 1.6.13 2012-05-21 * New -S option for ldns-verify-zone to chase signatures online. * New -k option for ldns-verify-zone to validate using a trusted key. diff --git a/Makefile.in b/Makefile.in index dfe3f352b13..68ee644b927 100644 --- a/Makefile.in +++ b/Makefile.in @@ -23,6 +23,7 @@ pyldns_uninst = @PYLDNSUNINST@ pyldnsx_inst = @PYLDNSXINST@ pyldnsx_uninst = @PYLDNSXUNINST@ libtool = @libtool@ +CONFIG_FILES = @CONFIG_FILES@ # override $U variable which is used by autotools for deansification (for # K&R C compilers), but causes problems if $U is defined in the env). @@ -41,6 +42,7 @@ PYTHON_X_CFLAGS = @PYTHON_X_CFLAGS@ LIBSSL_CPPFLAGS = @LIBSSL_CPPFLAGS@ LIBSSL_LDFLAGS = @LIBSSL_LDFLAGS@ LIBSSL_LIBS = @LIBSSL_LIBS@ +LIBSSL_SSL_LIBS = @LIBSSL_SSL_LIBS@ LIBPCAP_LIBS = @LIBPCAP_LIBS@ RUNTIME_PATH = @RUNTIME_PATH@ LIBTOOL = $(libtool) --tag=CC --quiet @@ -60,12 +62,12 @@ DEPFLAG = @DEPFLAG@ INSTALL = $(srcdir)/install-sh LIBLOBJS = $(LIBOBJS:.o=.lo) -LDNS_LOBJS = buffer.lo dname.lo dnssec.lo dnssec_sign.lo dnssec_verify.lo dnssec_zone.lo duration.lo error.lo higher.lo host2str.lo host2wire.lo keys.lo net.lo packet.lo parse.lo rbtree.lo rdata.lo resolver.lo rr.lo rr_functions.lo sha1.lo sha2.lo str2host.lo tsig.lo update.lo util.lo wire2host.lo zone.lo +LDNS_LOBJS = buffer.lo dane.lo dname.lo dnssec.lo dnssec_sign.lo dnssec_verify.lo dnssec_zone.lo duration.lo error.lo higher.lo host2str.lo host2wire.lo keys.lo net.lo packet.lo parse.lo rbtree.lo rdata.lo resolver.lo rr.lo rr_functions.lo sha1.lo sha2.lo str2host.lo tsig.lo update.lo util.lo wire2host.lo zone.lo LDNS_LOBJS_EX = ^linktest\.c$$ LDNS_ALL_LOBJS = $(LDNS_LOBJS) $(LIBLOBJS) LIB = libldns.la -LDNS_HEADERS = buffer.h dname.h dnssec.h dnssec_sign.h dnssec_verify.h dnssec_zone.h duration.h error.h higher.h host2str.h host2wire.h keys.h ldns.h packet.h parse.h rbtree.h rdata.h resolver.h rr_functions.h rr.h sha1.h sha2.h str2host.h tsig.h update.h wire2host.h zone.h +LDNS_HEADERS = buffer.h dane.h dname.h dnssec.h dnssec_sign.h dnssec_verify.h dnssec_zone.h duration.h error.h higher.h host2str.h host2wire.h keys.h ldns.h packet.h parse.h rbtree.h rdata.h resolver.h rr_functions.h rr.h sha1.h sha2.h str2host.h tsig.h update.h wire2host.h zone.h LDNS_HEADERS_EX = ^config\.h|common\.h|util\.h|net\.h$$ LDNS_HEADERS_GEN= common.h util.h net.h @@ -73,14 +75,16 @@ PYLDNS_I_FILES = $(pywrapdir)/file_py3.i $(pywrapdir)/ldns_buffer.i $(pywrapdir) DRILL_LOBJS = drill/chasetrace.lo drill/dnssec.lo drill/drill.lo drill/drill_util.lo drill/error.lo drill/root.lo drill/securetrace.lo drill/work.lo -EXAMPLE_LOBJS = examples/ldns-chaos.lo examples/ldns-compare-zones.lo examples/ldnsd.lo examples/ldns-dpa.lo examples/ldns-gen-zone.lo examples/ldns-key2ds.lo examples/ldns-keyfetcher.lo examples/ldns-keygen.lo examples/ldns-mx.lo examples/ldns-notify.lo examples/ldns-nsec3-hash.lo examples/ldns-read-zone.lo examples/ldns-resolver.lo examples/ldns-revoke.lo examples/ldns-rrsig.lo examples/ldns-signzone.lo examples/ldns-test-edns.lo examples/ldns-testns.lo examples/ldns-testpkts.lo examples/ldns-update.lo examples/ldns-verify-zone.lo examples/ldns-version.lo examples/ldns-walk.lo examples/ldns-zcat.lo examples/ldns-zsplit.lo +EXAMPLE_LOBJS = examples/ldns-chaos.lo examples/ldns-compare-zones.lo examples/ldns-dane.lo examples/ldnsd.lo examples/ldns-dpa.lo examples/ldns-gen-zone.lo examples/ldns-key2ds.lo examples/ldns-keyfetcher.lo examples/ldns-keygen.lo examples/ldns-mx.lo examples/ldns-notify.lo examples/ldns-nsec3-hash.lo examples/ldns-read-zone.lo examples/ldns-resolver.lo examples/ldns-revoke.lo examples/ldns-rrsig.lo examples/ldns-signzone.lo examples/ldns-test-edns.lo examples/ldns-testns.lo examples/ldns-testpkts.lo examples/ldns-update.lo examples/ldns-verify-zone.lo examples/ldns-version.lo examples/ldns-walk.lo examples/ldns-zcat.lo examples/ldns-zsplit.lo EXAMPLE_PROGS = examples/ldns-chaos examples/ldns-compare-zones examples/ldnsd examples/ldns-gen-zone examples/ldns-key2ds examples/ldns-keyfetcher examples/ldns-keygen examples/ldns-mx examples/ldns-notify examples/ldns-read-zone examples/ldns-resolver examples/ldns-rrsig examples/ldns-test-edns examples/ldns-update examples/ldns-version examples/ldns-walk examples/ldns-zcat examples/ldns-zsplit -EX_PROGS_BASENM = ldns-chaos ldns-compare-zones ldnsd ldns-dpa ldns-gen-zone ldns-key2ds ldns-keyfetcher ldns-keygen ldns-mx ldns-notify ldns-nsec3-hash ldns-read-zone ldns-resolver ldns-revoke ldns-rrsig ldns-signzone ldns-test-edns ldns-testns ldns-testpkts ldns-update ldns-verify-zone ldns-version ldns-walk ldns-zcat ldns-zsplit -EXAMPLE_PROGS_EX= ^examples/ldns-testpkts\.c|examples/ldns-testns\.c|examples/ldns-dpa\.c|examples/ldns-nsec3-hash\.c|examples/ldns-revoke\.c|examples/ldns-signzone\.c|examples/ldns-verify-zone\.c$$ +EX_PROGS_BASENM = ldns-chaos ldns-compare-zones ldns-dane ldnsd ldns-dpa ldns-gen-zone ldns-key2ds ldns-keyfetcher ldns-keygen ldns-mx ldns-notify ldns-nsec3-hash ldns-read-zone ldns-resolver ldns-revoke ldns-rrsig ldns-signzone ldns-test-edns ldns-testns ldns-testpkts ldns-update ldns-verify-zone ldns-version ldns-walk ldns-zcat ldns-zsplit +EXAMPLE_PROGS_EX= ^examples/ldns-testpkts\.c|examples/ldns-testns\.c|examples/ldns-dane\.c|examples/ldns-dpa\.c|examples/ldns-nsec3-hash\.c|examples/ldns-revoke\.c|examples/ldns-signzone\.c|examples/ldns-verify-zone\.c$$ TESTNS = examples/ldns-testns TESTNS_LOBJS = examples/ldns-testns.lo examples/ldns-testpkts.lo LDNS_DPA = examples/ldns-dpa LDNS_DPA_LOBJS = examples/ldns-dpa.lo +LDNS_DANE = examples/ldns-dane +LDNS_DANE_LOBJS = examples/ldns-dane.lo EX_SSL_PROGS = examples/ldns-nsec3-hash examples/ldns-revoke examples/ldns-signzone examples/ldns-verify-zone EX_SSL_LOBJS = examples/ldns-nsec3-hash.lo examples/ldns-revoke.lo examples/ldns-signzone.lo examples/ldns-verify-zone.lo @@ -140,7 +144,7 @@ install-drill: drill/drill $(INSTALL) -m 755 -d $(DESTDIR)$(mandir) $(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man1 $(LIBTOOL) --mode=install cp drill/drill $(DESTDIR)$(bindir) - $(INSTALL) -m 644 $(srcdir)/drill/drill.1 $(DESTDIR)$(mandir)/man1/drill.1 + $(INSTALL) -m 644 drill/drill.1 $(DESTDIR)$(mandir)/man1/drill.1 uninstall-drill: rm -f $(DESTDIR)$(bindir)/drill $(DESTDIR)$(mandir)/man1/drill.1 @@ -150,7 +154,7 @@ uninstall-drill: clean-drill: $(LIBTOOL) --mode clean rm -f $(DRILL_LOBJS) drill/drill -examples: no-examples-config-h $(EXAMPLE_PROGS) $(TESTNS) $(LDNS_DPA) $(EX_SSL_PROGS) +examples: no-examples-config-h $(EXAMPLE_PROGS) $(TESTNS) $(LDNS_DPA) $(LDNS_DANE) $(EX_SSL_PROGS) no-examples-config-h: @if test -e $(srcdir)/examples/config.h -o -e examples/config.h ; \ then echo "A config.h was detected in the examples subdirectory." ; \ @@ -169,16 +173,23 @@ $(LDNS_DPA): $(LINK_EXE) $(LDNS_DPA_LOBJS) $(LIBS) $(LIBPCAP_LIBS) -lldns \ -o $(LDNS_DPA) +$(LDNS_DANE): + $(LINK_EXE) $(LDNS_DANE_LOBJS) $(LIBS) $(LIBSSL_SSL_LIBS) -lldns \ + -o $(LDNS_DANE) + $(EX_SSL_PROGS): $(LINK_EXE) $@.lo $(LIBS) $(LIBSSL_LIBS) -lldns -o $@ -install-examples: $(EXAMPLE_PROGS) $(TESTNS) $(LDNS_DPA) $(EX_SSL_PROGS) +install-examples: $(EXAMPLE_PROGS) $(TESTNS) $(LDNS_DPA) $(LDNS_DANE) $(EX_SSL_PROGS) $(INSTALL) -m 755 -d $(DESTDIR)$(bindir) $(INSTALL) -m 755 -d $(DESTDIR)$(mandir) $(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man1 - for p in $(EXAMPLE_PROGS) $(TESTNS) $(LDNS_DPA) $(EX_SSL_PROGS) ; do \ + for p in $(EXAMPLE_PROGS) $(TESTNS) $(LDNS_DPA) $(LDNS_DANE) $(EX_SSL_PROGS) ; do \ $(LIBTOOL) --mode=install cp $$p $(DESTDIR)$(bindir) ; \ - $(INSTALL) -m 644 $(srcdir)/$$p.1 $(DESTDIR)$(mandir)/man1 ; \ + if test -f $$p.1 ; \ + then $(INSTALL) -m 644 $$p.1 $(DESTDIR)$(mandir)/man1 ; \ + else $(INSTALL) -m 644 $(srcdir)/$$p.1 $(DESTDIR)$(mandir)/man1 ; \ + fi ; \ done uninstall-examples: @@ -190,7 +201,7 @@ uninstall-examples: clean-examples: $(LIBTOOL) --mode clean rm -f $(EXAMPLE_PROGS) - $(LIBTOOL) --mode clean rm -f $(TESTNS) $(LDNS_DPA) $(EX_SSL_PROGS) + $(LIBTOOL) --mode clean rm -f $(TESTNS) $(LDNS_DPA) $(LDNS_DANE) $(EX_SSL_PROGS) $(LIBTOOL) --mode clean rm -f $(EXAMPLE_LOBJS) linktest: $(srcdir)/linktest.c libldns.la @@ -201,7 +212,7 @@ lib: libldns.la lib-export-all: libldns.la-export-all libldns.la: $(LDNS_ALL_LOBJS) - $(LINK_LIB) $(LIBSSL_LDFLAGS) $(LIBSSL_LIBS) --export-symbols $(srcdir)/ldns_symbols.def -o libldns.la $(LDNS_ALL_LOBJS) -rpath $(libdir) $(RUNTIME_PATH) + $(LINK_LIB) $(LIBSSL_LDFLAGS) $(LIBSSL_LIBS) -export-symbols-regex '^(ldns_|b32_[pn]to[pn]|mktime_from_utc|qsort_rr_compare_nsec3)' -o libldns.la $(LDNS_ALL_LOBJS) -rpath $(libdir) $(RUNTIME_PATH) libldns.la-export-all: $(LDNS_ALL_LOBJS) $(LINK_LIB) -o libldns.la $(LDNS_ALL_LOBJS) -rpath $(libdir) $(RUNTIME_PATH) @@ -231,10 +242,10 @@ $(pywrapdir)/ldns_wrapper.c: $(PYLDNS_I_FILES) ldns/config.h $(swig) $(swigpy_flags) -o $@ $(CPPFLAGS) $(PYTHON_CPPFLAGS) $(pywrapdir)/ldns.i ldns_wrapper.lo: $(pywrapdir)/ldns_wrapper.c ldns/config.h - $(COMP_LIB) -I./include/ldns $(PYTHON_CPPFLAGS) $(PYTHON_X_CFLAGS) -c $< -o $@ + $(COMP_LIB) -I./include/ldns $(PYTHON_CPPFLAGS) $(PYTHON_X_CFLAGS) -c $(pywrapdir)/ldns_wrapper.c -o $@ _ldns.la: ldns_wrapper.lo libldns.la - $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(PYTHON_CFLAGS) $(LDFLAGS) $(PYTHON_LDFLAGS) -module -version-number $(version_info) -no-undefined -o $@ $< -rpath $(python_site) -L. -L.libs -lldns $(LIBS) + $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(PYTHON_CFLAGS) $(LDFLAGS) $(PYTHON_LDFLAGS) -module -version-number $(version_info) -no-undefined -o $@ ldns_wrapper.lo -rpath $(python_site) -L. -L.libs -lldns $(LIBS) install: install-h install-lib @INSTALL_CONFIG@ install-manpages $(pyldns_inst) $(pyldnsx_inst) @INSTALL_DRILL@ @INSTALL_EXAMPLES@ @@ -325,13 +336,8 @@ clean: @CLEAN_DRILL@ @CLEAN_EXAMPLES@ clean-manpages clean-lib putdown-builddir realclean: clean docclean rm -f config.status rm -f config.log - rm -f Makefile + rm -f $(CONFIG_FILES) rm -f ldns/config.h - rm -f ldns/util.h - rm -f ldns/common.h - rm -f ldns/net.h - rm -f packaging/ldns-config - rm -f packaging/libldns.pc if test -d packaging -a ! -f packaging/ldns-config.in ; then \ rmdir packaging || : ; fi rm -f libtool @@ -363,7 +369,8 @@ distclean: realclean ## No need for changes here -lint: @LINT_DRILL@ @LINT_EXAMPLES@ +lint: lint-lib @LINT_DRILL@ @LINT_EXAMPLES@ +lint-lib: for i in $(srcdir)/*.c; do \ $(LINT) $(LINTFLAGS) -I. -I$(srcdir) $(srcdir)/$$i ; \ if test $$? -ne 0 ; then exit 1 ; fi ; \ @@ -449,7 +456,7 @@ depend: >> $(DEPEND_TMP) ;\ done; \ done - for p in $(EXAMPLE_PROGS) $(LDNS_DPA) $(EX_SSL_PROGS); do \ + for p in $(EXAMPLE_PROGS) $(LDNS_DPA) $(LDNS_DANE) $(EX_SSL_PROGS); do \ echo "$$p: $$p.lo $$p.o \$$(LIB)" >> $(DEPEND_TMP) ; done echo "$(TESTNS): `for o in $(TESTNS_LOBJS) ; do \ echo -n "$$o $${o%lo}o " ; done` \$$(LIB)" \ @@ -468,610 +475,515 @@ depend: # Dependencies -buffer.lo buffer.o: $(srcdir)/buffer.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +buffer.lo buffer.o: $(srcdir)/buffer.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h ldns/common.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h \ + $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -dname.lo dname.o: $(srcdir)/dname.c $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +dane.lo dane.o: $(srcdir)/dane.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h ldns/common.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h \ + $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -dnssec.lo dnssec.o: $(srcdir)/dnssec.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +dname.lo dname.o: $(srcdir)/dname.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h ldns/common.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h \ + $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -dnssec_sign.lo dnssec_sign.o: $(srcdir)/dnssec_sign.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +dnssec.lo dnssec.o: $(srcdir)/dnssec.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h ldns/common.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h \ + $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -dnssec_verify.lo dnssec_verify.o: $(srcdir)/dnssec_verify.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +dnssec_sign.lo dnssec_sign.o: $(srcdir)/dnssec_sign.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h \ + ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h \ + $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h \ + $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -dnssec_zone.lo dnssec_zone.o: $(srcdir)/dnssec_zone.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +dnssec_verify.lo dnssec_verify.o: $(srcdir)/dnssec_verify.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h \ + ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h \ + $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h \ + $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -duration.lo duration.o: $(srcdir)/duration.c \ - $(srcdir)/ldns/duration.h -error.lo error.o: $(srcdir)/error.c $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +dnssec_zone.lo dnssec_zone.o: $(srcdir)/dnssec_zone.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h \ + ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h \ + $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h \ + $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -higher.lo higher.o: $(srcdir)/higher.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +duration.lo duration.o: $(srcdir)/duration.c ldns/config.h $(srcdir)/ldns/duration.h +error.lo error.o: $(srcdir)/error.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h ldns/common.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h \ + $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -host2str.lo host2str.o: $(srcdir)/host2str.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +higher.lo higher.o: $(srcdir)/higher.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h ldns/common.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h \ + $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -host2wire.lo host2wire.o: $(srcdir)/host2wire.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +host2str.lo host2str.o: $(srcdir)/host2str.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h \ + ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h \ + $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h \ + $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -keys.lo keys.o: $(srcdir)/keys.c $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +host2wire.lo host2wire.o: $(srcdir)/host2wire.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h \ + ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h \ + $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h \ + $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -linktest.lo linktest.o: $(srcdir)/linktest.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +keys.lo keys.o: $(srcdir)/keys.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h ldns/common.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h \ + $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -net.lo net.o: $(srcdir)/net.c $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +linktest.lo linktest.o: $(srcdir)/linktest.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h \ + ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h \ + $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h \ + $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -packet.lo packet.o: $(srcdir)/packet.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +net.lo net.o: $(srcdir)/net.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h ldns/common.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h \ + $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -parse.lo parse.o: $(srcdir)/parse.c $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +packet.lo packet.o: $(srcdir)/packet.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h ldns/common.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h \ + $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -rbtree.lo rbtree.o: $(srcdir)/rbtree.c \ - $(srcdir)/ldns/rbtree.h \ - -rdata.lo rdata.o: $(srcdir)/rdata.c $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +parse.lo parse.o: $(srcdir)/parse.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h ldns/common.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h \ + $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -resolver.lo resolver.o: $(srcdir)/resolver.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +rbtree.lo rbtree.o: $(srcdir)/rbtree.c ldns/config.h $(srcdir)/ldns/rbtree.h ldns/util.h ldns/common.h +rdata.lo rdata.o: $(srcdir)/rdata.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h ldns/common.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h \ + $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -rr.lo rr.o: $(srcdir)/rr.c $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +resolver.lo resolver.o: $(srcdir)/resolver.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h \ + ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h \ + $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h \ + $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -rr_functions.lo rr_functions.o: $(srcdir)/rr_functions.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +rr.lo rr.o: $(srcdir)/rr.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h ldns/common.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h \ + $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -sha1.lo sha1.o: $(srcdir)/sha1.c $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +rr_functions.lo rr_functions.o: $(srcdir)/rr_functions.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h \ + ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h \ + $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h \ + $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -sha2.lo sha2.o: $(srcdir)/sha2.c $(srcdir)/ldns/sha2.h -str2host.lo str2host.o: $(srcdir)/str2host.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +sha1.lo sha1.o: $(srcdir)/sha1.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h ldns/common.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h \ + $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -tsig.lo tsig.o: $(srcdir)/tsig.c $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +sha2.lo sha2.o: $(srcdir)/sha2.c ldns/config.h $(srcdir)/ldns/sha2.h +str2host.lo str2host.o: $(srcdir)/str2host.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h \ + ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h \ + $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h \ + $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -update.lo update.o: $(srcdir)/update.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +tsig.lo tsig.o: $(srcdir)/tsig.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h ldns/common.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h \ + $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -util.lo util.o: $(srcdir)/util.c $(srcdir)/ldns/rdata.h \ - $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/rr.h $(srcdir)/ldns/buffer.h -wire2host.lo wire2host.o: $(srcdir)/wire2host.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +update.lo update.o: $(srcdir)/update.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h ldns/common.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h \ + $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -zone.lo zone.o: $(srcdir)/zone.c $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +util.lo util.o: $(srcdir)/util.c ldns/config.h $(srcdir)/ldns/rdata.h ldns/common.h $(srcdir)/ldns/error.h \ + ldns/util.h $(srcdir)/ldns/rr.h $(srcdir)/ldns/buffer.h +wire2host.lo wire2host.o: $(srcdir)/wire2host.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h \ + ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h \ + $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h \ + $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -compat/b32_ntop.lo compat/b32_ntop.o: $(srcdir)/compat/b32_ntop.c -compat/b32_pton.lo compat/b32_pton.o: $(srcdir)/compat/b32_pton.c -compat/b64_ntop.lo compat/b64_ntop.o: $(srcdir)/compat/b64_ntop.c -compat/b64_pton.lo compat/b64_pton.o: $(srcdir)/compat/b64_pton.c -compat/calloc.lo compat/calloc.o: $(srcdir)/compat/calloc.c -compat/ctime_r.lo compat/ctime_r.o: $(srcdir)/compat/ctime_r.c -compat/fake-rfc2553.lo compat/fake-rfc2553.o: $(srcdir)/compat/fake-rfc2553.c \ +zone.lo zone.o: $(srcdir)/zone.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h ldns/common.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h \ + $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ + $(srcdir)/ldns/sha2.h +compat/b32_ntop.lo compat/b32_ntop.o: $(srcdir)/compat/b32_ntop.c ldns/config.h +compat/b32_pton.lo compat/b32_pton.o: $(srcdir)/compat/b32_pton.c ldns/config.h +compat/b64_ntop.lo compat/b64_ntop.o: $(srcdir)/compat/b64_ntop.c ldns/config.h +compat/b64_pton.lo compat/b64_pton.o: $(srcdir)/compat/b64_pton.c ldns/config.h +compat/calloc.lo compat/calloc.o: $(srcdir)/compat/calloc.c ldns/config.h +compat/ctime_r.lo compat/ctime_r.o: $(srcdir)/compat/ctime_r.c ldns/config.h +compat/fake-rfc2553.lo compat/fake-rfc2553.o: $(srcdir)/compat/fake-rfc2553.c ldns/config.h ldns/common.h \ $(srcdir)/compat/fake-rfc2553.h -compat/gmtime_r.lo compat/gmtime_r.o: $(srcdir)/compat/gmtime_r.c -compat/inet_aton.lo compat/inet_aton.o: $(srcdir)/compat/inet_aton.c \ - -compat/inet_ntop.lo compat/inet_ntop.o: $(srcdir)/compat/inet_ntop.c \ - -compat/inet_pton.lo compat/inet_pton.o: $(srcdir)/compat/inet_pton.c \ - -compat/isascii.lo compat/isascii.o: $(srcdir)/compat/isascii.c -compat/isblank.lo compat/isblank.o: $(srcdir)/compat/isblank.c -compat/localtime_r.lo compat/localtime_r.o: $(srcdir)/compat/localtime_r.c \ - -compat/malloc.lo compat/malloc.o: $(srcdir)/compat/malloc.c -compat/memmove.lo compat/memmove.o: $(srcdir)/compat/memmove.c -compat/realloc.lo compat/realloc.o: $(srcdir)/compat/realloc.c -compat/snprintf.lo compat/snprintf.o: $(srcdir)/compat/snprintf.c -compat/strlcpy.lo compat/strlcpy.o: $(srcdir)/compat/strlcpy.c -compat/timegm.lo compat/timegm.o: $(srcdir)/compat/timegm.c -examples/ldns-chaos.lo examples/ldns-chaos.o: $(srcdir)/examples/ldns-chaos.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +compat/gmtime_r.lo compat/gmtime_r.o: $(srcdir)/compat/gmtime_r.c ldns/config.h +compat/inet_aton.lo compat/inet_aton.o: $(srcdir)/compat/inet_aton.c ldns/config.h +compat/inet_ntop.lo compat/inet_ntop.o: $(srcdir)/compat/inet_ntop.c ldns/config.h +compat/inet_pton.lo compat/inet_pton.o: $(srcdir)/compat/inet_pton.c ldns/config.h +compat/isascii.lo compat/isascii.o: $(srcdir)/compat/isascii.c ldns/config.h +compat/isblank.lo compat/isblank.o: $(srcdir)/compat/isblank.c ldns/config.h +compat/localtime_r.lo compat/localtime_r.o: $(srcdir)/compat/localtime_r.c ldns/config.h +compat/malloc.lo compat/malloc.o: $(srcdir)/compat/malloc.c ldns/config.h +compat/memmove.lo compat/memmove.o: $(srcdir)/compat/memmove.c ldns/config.h +compat/realloc.lo compat/realloc.o: $(srcdir)/compat/realloc.c ldns/config.h +compat/snprintf.lo compat/snprintf.o: $(srcdir)/compat/snprintf.c ldns/config.h +compat/strlcpy.lo compat/strlcpy.o: $(srcdir)/compat/strlcpy.c ldns/config.h +compat/timegm.lo compat/timegm.o: $(srcdir)/compat/timegm.c ldns/config.h +examples/ldns-chaos.lo examples/ldns-chaos.o: $(srcdir)/examples/ldns-chaos.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h \ + ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h \ + $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h \ + $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -examples/ldns-compare-zones.lo examples/ldns-compare-zones.o: $(srcdir)/examples/ldns-compare-zones.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ +examples/ldns-compare-zones.lo examples/ldns-compare-zones.o: $(srcdir)/examples/ldns-compare-zones.c ldns/config.h $(srcdir)/ldns/ldns.h \ + ldns/util.h ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h \ + $(srcdir)/ldns/rdata.h $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h \ $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h \ + $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h $(srcdir)/ldns/sha2.h +examples/ldns-dane.lo examples/ldns-dane.o: $(srcdir)/examples/ldns-dane.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h \ + ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h \ + $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h \ + $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -examples/ldnsd.lo examples/ldnsd.o: $(srcdir)/examples/ldnsd.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +examples/ldnsd.lo examples/ldnsd.o: $(srcdir)/examples/ldnsd.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h ldns/common.h \ + $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h \ + $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -examples/ldns-dpa.lo examples/ldns-dpa.o: $(srcdir)/examples/ldns-dpa.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +examples/ldns-dpa.lo examples/ldns-dpa.o: $(srcdir)/examples/ldns-dpa.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h \ + ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h \ + $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h \ + $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h $(srcdir)/examples/ldns-dpa.h -examples/ldns-gen-zone.lo examples/ldns-gen-zone.o: $(srcdir)/examples/ldns-gen-zone.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ +examples/ldns-gen-zone.lo examples/ldns-gen-zone.o: $(srcdir)/examples/ldns-gen-zone.c ldns/config.h $(srcdir)/ldns/ldns.h \ + ldns/util.h ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h \ + $(srcdir)/ldns/rdata.h $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h \ $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h \ + $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h $(srcdir)/ldns/sha2.h +examples/ldns-key2ds.lo examples/ldns-key2ds.o: $(srcdir)/examples/ldns-key2ds.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h \ + ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h \ + $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h \ + $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -examples/ldns-key2ds.lo examples/ldns-key2ds.o: $(srcdir)/examples/ldns-key2ds.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ +examples/ldns-keyfetcher.lo examples/ldns-keyfetcher.o: $(srcdir)/examples/ldns-keyfetcher.c ldns/config.h $(srcdir)/ldns/ldns.h \ + ldns/util.h ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h \ + $(srcdir)/ldns/rdata.h $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h \ $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h \ + $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h $(srcdir)/ldns/sha2.h +examples/ldns-keygen.lo examples/ldns-keygen.o: $(srcdir)/examples/ldns-keygen.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h \ + ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h \ + $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h \ + $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -examples/ldns-keyfetcher.lo examples/ldns-keyfetcher.o: $(srcdir)/examples/ldns-keyfetcher.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +examples/ldns-mx.lo examples/ldns-mx.o: $(srcdir)/examples/ldns-mx.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h \ + ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h \ + $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h \ + $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -examples/ldns-keygen.lo examples/ldns-keygen.o: $(srcdir)/examples/ldns-keygen.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +examples/ldns-notify.lo examples/ldns-notify.o: $(srcdir)/examples/ldns-notify.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h \ + ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h \ + $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h \ + $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -examples/ldns-mx.lo examples/ldns-mx.o: $(srcdir)/examples/ldns-mx.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ +examples/ldns-nsec3-hash.lo examples/ldns-nsec3-hash.o: $(srcdir)/examples/ldns-nsec3-hash.c ldns/config.h $(srcdir)/ldns/ldns.h \ + ldns/util.h ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h \ + $(srcdir)/ldns/rdata.h $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h \ $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h \ + $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h $(srcdir)/ldns/sha2.h +examples/ldns-read-zone.lo examples/ldns-read-zone.o: $(srcdir)/examples/ldns-read-zone.c ldns/config.h $(srcdir)/ldns/ldns.h \ + ldns/util.h ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h \ + $(srcdir)/ldns/rdata.h $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h \ + $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h $(srcdir)/ldns/sha2.h +examples/ldns-resolver.lo examples/ldns-resolver.o: $(srcdir)/examples/ldns-resolver.c ldns/config.h $(srcdir)/ldns/ldns.h \ + ldns/util.h ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h \ + $(srcdir)/ldns/rdata.h $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h \ + $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ + $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h \ + $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h $(srcdir)/ldns/sha2.h +examples/ldns-revoke.lo examples/ldns-revoke.o: $(srcdir)/examples/ldns-revoke.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h \ + ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h \ + $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h \ + $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -examples/ldns-notify.lo examples/ldns-notify.o: $(srcdir)/examples/ldns-notify.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +examples/ldns-rrsig.lo examples/ldns-rrsig.o: $(srcdir)/examples/ldns-rrsig.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h \ + ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h \ + $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h \ + $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -examples/ldns-nsec3-hash.lo examples/ldns-nsec3-hash.o: $(srcdir)/examples/ldns-nsec3-hash.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ +examples/ldns-signzone.lo examples/ldns-signzone.o: $(srcdir)/examples/ldns-signzone.c ldns/config.h $(srcdir)/ldns/ldns.h \ + ldns/util.h ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h \ + $(srcdir)/ldns/rdata.h $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h \ $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ - $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ - $(srcdir)/ldns/sha2.h -examples/ldns-read-zone.lo examples/ldns-read-zone.o: $(srcdir)/examples/ldns-read-zone.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h \ + $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h $(srcdir)/ldns/sha2.h +examples/ldns-test-edns.lo examples/ldns-test-edns.o: $(srcdir)/examples/ldns-test-edns.c ldns/config.h $(srcdir)/ldns/ldns.h \ + ldns/util.h ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h \ + $(srcdir)/ldns/rdata.h $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h \ $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ - $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ - $(srcdir)/ldns/sha2.h -examples/ldns-resolver.lo examples/ldns-resolver.o: $(srcdir)/examples/ldns-resolver.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ - $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ - $(srcdir)/ldns/sha2.h -examples/ldns-revoke.lo examples/ldns-revoke.o: $(srcdir)/examples/ldns-revoke.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ - $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ - $(srcdir)/ldns/sha2.h -examples/ldns-rrsig.lo examples/ldns-rrsig.o: $(srcdir)/examples/ldns-rrsig.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ - $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ - $(srcdir)/ldns/sha2.h -examples/ldns-signzone.lo examples/ldns-signzone.o: $(srcdir)/examples/ldns-signzone.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ - $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ - $(srcdir)/ldns/sha2.h -examples/ldns-test-edns.lo examples/ldns-test-edns.o: $(srcdir)/examples/ldns-test-edns.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ - $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ - $(srcdir)/ldns/sha2.h -examples/ldns-testns.lo examples/ldns-testns.o: $(srcdir)/examples/ldns-testns.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h \ + $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h $(srcdir)/ldns/sha2.h +examples/ldns-testns.lo examples/ldns-testns.o: $(srcdir)/examples/ldns-testns.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h \ + ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h \ + $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h \ + $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h $(srcdir)/examples/ldns-testpkts.h -examples/ldns-testpkts.lo examples/ldns-testpkts.o: $(srcdir)/examples/ldns-testpkts.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ +examples/ldns-testpkts.lo examples/ldns-testpkts.o: $(srcdir)/examples/ldns-testpkts.c ldns/config.h $(srcdir)/ldns/ldns.h \ + ldns/util.h ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h \ + $(srcdir)/ldns/rdata.h $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h \ $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ - $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ - $(srcdir)/ldns/sha2.h $(srcdir)/examples/ldns-testpkts.h -examples/ldns-update.lo examples/ldns-update.o: $(srcdir)/examples/ldns-update.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h \ + $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h $(srcdir)/ldns/sha2.h $(srcdir)/examples/ldns-testpkts.h +examples/ldns-update.lo examples/ldns-update.o: $(srcdir)/examples/ldns-update.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h \ + ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h \ + $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h \ + $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -examples/ldns-verify-zone.lo examples/ldns-verify-zone.o: $(srcdir)/examples/ldns-verify-zone.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ +examples/ldns-verify-zone.lo examples/ldns-verify-zone.o: $(srcdir)/examples/ldns-verify-zone.c ldns/config.h $(srcdir)/ldns/ldns.h \ + ldns/util.h ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h \ + $(srcdir)/ldns/rdata.h $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h \ $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ + $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h \ + $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h \ + $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h $(srcdir)/ldns/sha2.h +examples/ldns-version.lo examples/ldns-version.o: $(srcdir)/examples/ldns-version.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h \ + ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h \ + $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h \ + $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -examples/ldns-version.lo examples/ldns-version.o: $(srcdir)/examples/ldns-version.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +examples/ldns-walk.lo examples/ldns-walk.o: $(srcdir)/examples/ldns-walk.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h \ + ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h \ + $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h \ + $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -examples/ldns-walk.lo examples/ldns-walk.o: $(srcdir)/examples/ldns-walk.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +examples/ldns-zcat.lo examples/ldns-zcat.o: $(srcdir)/examples/ldns-zcat.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h \ + ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h \ + $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h \ + $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -examples/ldns-zcat.lo examples/ldns-zcat.o: $(srcdir)/examples/ldns-zcat.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +examples/ldns-zsplit.lo examples/ldns-zsplit.o: $(srcdir)/examples/ldns-zsplit.c ldns/config.h $(srcdir)/ldns/ldns.h ldns/util.h \ + ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h \ + $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h \ + $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h \ + $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h \ + $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -examples/ldns-zsplit.lo examples/ldns-zsplit.o: $(srcdir)/examples/ldns-zsplit.c \ - $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +drill/chasetrace.lo drill/chasetrace.o: $(srcdir)/drill/chasetrace.c $(srcdir)/drill/drill.h ldns/config.h \ + $(srcdir)/drill/drill_util.h $(srcdir)/ldns/ldns.h ldns/util.h ldns/common.h $(srcdir)/ldns/buffer.h \ + $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h \ + $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h \ + $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h \ + $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h \ + $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -drill/chasetrace.lo drill/chasetrace.o: $(srcdir)/drill/chasetrace.c $(srcdir)/drill/drill.h \ - $(srcdir)/drill/drill_util.h $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +drill/dnssec.lo drill/dnssec.o: $(srcdir)/drill/dnssec.c $(srcdir)/drill/drill.h ldns/config.h $(srcdir)/drill/drill_util.h \ + $(srcdir)/ldns/ldns.h ldns/util.h ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h \ + $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h \ + $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h \ + $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h $(srcdir)/ldns/wire2host.h \ + $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h $(srcdir)/ldns/sha2.h +drill/drill.lo drill/drill.o: $(srcdir)/drill/drill.c $(srcdir)/drill/drill.h ldns/config.h $(srcdir)/drill/drill_util.h \ + $(srcdir)/ldns/ldns.h ldns/util.h ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h \ + $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h \ + $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h \ + $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h $(srcdir)/ldns/wire2host.h \ + $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h $(srcdir)/ldns/sha2.h +drill/drill_util.lo drill/drill_util.o: $(srcdir)/drill/drill_util.c $(srcdir)/drill/drill.h ldns/config.h \ + $(srcdir)/drill/drill_util.h $(srcdir)/ldns/ldns.h ldns/util.h ldns/common.h $(srcdir)/ldns/buffer.h \ + $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h \ + $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h \ + $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h \ + $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h \ + $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h -drill/dnssec.lo drill/dnssec.o: $(srcdir)/drill/dnssec.c $(srcdir)/drill/drill.h \ - $(srcdir)/drill/drill_util.h $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ - $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ - $(srcdir)/ldns/sha2.h -drill/drill.lo drill/drill.o: $(srcdir)/drill/drill.c $(srcdir)/drill/drill.h \ - $(srcdir)/drill/drill_util.h $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ - $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ - $(srcdir)/ldns/sha2.h -drill/drill_util.lo drill/drill_util.o: $(srcdir)/drill/drill_util.c $(srcdir)/drill/drill.h \ - $(srcdir)/drill/drill_util.h $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ - $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ - $(srcdir)/ldns/sha2.h -drill/error.lo drill/error.o: $(srcdir)/drill/error.c $(srcdir)/drill/drill.h \ - $(srcdir)/drill/drill_util.h $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ - $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ - $(srcdir)/ldns/sha2.h -drill/root.lo drill/root.o: $(srcdir)/drill/root.c $(srcdir)/drill/drill.h \ - $(srcdir)/drill/drill_util.h $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ - $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ - $(srcdir)/ldns/sha2.h -drill/securetrace.lo drill/securetrace.o: $(srcdir)/drill/securetrace.c $(srcdir)/drill/drill.h \ - $(srcdir)/drill/drill_util.h $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ - $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ - $(srcdir)/ldns/sha2.h -drill/work.lo drill/work.o: $(srcdir)/drill/work.c $(srcdir)/drill/drill.h \ - $(srcdir)/drill/drill_util.h $(srcdir)/ldns/ldns.h \ - $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ - $(srcdir)/ldns/dname.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/rr.h \ - $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h \ - $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h \ - $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ - $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ +drill/error.lo drill/error.o: $(srcdir)/drill/error.c $(srcdir)/drill/drill.h ldns/config.h $(srcdir)/drill/drill_util.h \ + $(srcdir)/ldns/ldns.h ldns/util.h ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h \ + $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h \ + $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h \ + $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h $(srcdir)/ldns/wire2host.h \ + $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h $(srcdir)/ldns/sha2.h +drill/root.lo drill/root.o: $(srcdir)/drill/root.c $(srcdir)/drill/drill.h ldns/config.h $(srcdir)/drill/drill_util.h \ + $(srcdir)/ldns/ldns.h ldns/util.h ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h \ + $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h \ + $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h \ + $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h $(srcdir)/ldns/wire2host.h \ + $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h $(srcdir)/ldns/sha2.h +drill/securetrace.lo drill/securetrace.o: $(srcdir)/drill/securetrace.c $(srcdir)/drill/drill.h ldns/config.h \ + $(srcdir)/drill/drill_util.h $(srcdir)/ldns/ldns.h ldns/util.h ldns/common.h $(srcdir)/ldns/buffer.h \ + $(srcdir)/ldns/error.h $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h \ + $(srcdir)/ldns/dnssec.h $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h \ + $(srcdir)/ldns/tsig.h $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h \ + $(srcdir)/ldns/dnssec_verify.h $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h \ + $(srcdir)/ldns/host2wire.h ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h \ $(srcdir)/ldns/wire2host.h $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h \ $(srcdir)/ldns/sha2.h +drill/work.lo drill/work.o: $(srcdir)/drill/work.c $(srcdir)/drill/drill.h ldns/config.h $(srcdir)/drill/drill_util.h \ + $(srcdir)/ldns/ldns.h ldns/util.h ldns/common.h $(srcdir)/ldns/buffer.h $(srcdir)/ldns/error.h \ + $(srcdir)/ldns/dane.h $(srcdir)/ldns/rdata.h $(srcdir)/ldns/rr.h $(srcdir)/ldns/dname.h $(srcdir)/ldns/dnssec.h \ + $(srcdir)/ldns/packet.h $(srcdir)/ldns/keys.h $(srcdir)/ldns/zone.h $(srcdir)/ldns/resolver.h $(srcdir)/ldns/tsig.h \ + $(srcdir)/ldns/dnssec_zone.h $(srcdir)/ldns/rbtree.h $(srcdir)/ldns/host2str.h $(srcdir)/ldns/dnssec_verify.h \ + $(srcdir)/ldns/dnssec_sign.h $(srcdir)/ldns/duration.h $(srcdir)/ldns/higher.h $(srcdir)/ldns/host2wire.h \ + ldns/net.h $(srcdir)/ldns/str2host.h $(srcdir)/ldns/update.h $(srcdir)/ldns/wire2host.h \ + $(srcdir)/ldns/rr_functions.h $(srcdir)/ldns/parse.h $(srcdir)/ldns/sha1.h $(srcdir)/ldns/sha2.h examples/ldns-chaos: examples/ldns-chaos.lo examples/ldns-chaos.o $(LIB) examples/ldns-compare-zones: examples/ldns-compare-zones.lo examples/ldns-compare-zones.o $(LIB) examples/ldnsd: examples/ldnsd.lo examples/ldnsd.o $(LIB) @@ -1091,6 +1003,7 @@ examples/ldns-walk: examples/ldns-walk.lo examples/ldns-walk.o $(LIB) examples/ldns-zcat: examples/ldns-zcat.lo examples/ldns-zcat.o $(LIB) examples/ldns-zsplit: examples/ldns-zsplit.lo examples/ldns-zsplit.o $(LIB) examples/ldns-dpa: examples/ldns-dpa.lo examples/ldns-dpa.o $(LIB) +examples/ldns-dane: examples/ldns-dane.lo examples/ldns-dane.o $(LIB) examples/ldns-nsec3-hash: examples/ldns-nsec3-hash.lo examples/ldns-nsec3-hash.o $(LIB) examples/ldns-revoke: examples/ldns-revoke.lo examples/ldns-revoke.o $(LIB) examples/ldns-signzone: examples/ldns-signzone.lo examples/ldns-signzone.o $(LIB) diff --git a/buffer.c b/buffer.c index 5a6b0ba74c8..fc6c17e7a9f 100644 --- a/buffer.c +++ b/buffer.c @@ -140,7 +140,8 @@ ldns_buffer_free(ldns_buffer *buffer) return; } - LDNS_FREE(buffer->_data); + if (!buffer->_fixed) + LDNS_FREE(buffer->_data); LDNS_FREE(buffer); } diff --git a/configure b/configure index 36936562102..be312d1e3f1 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.68 for ldns 1.6.13. +# Generated by GNU Autoconf 2.68 for ldns 1.6.16. # # Report bugs to . # @@ -570,8 +570,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='ldns' PACKAGE_TARNAME='libdns' -PACKAGE_VERSION='1.6.13' -PACKAGE_STRING='ldns 1.6.13' +PACKAGE_VERSION='1.6.16' +PACKAGE_STRING='ldns 1.6.16' PACKAGE_BUGREPORT='libdns@nlnetlabs.nl' PACKAGE_URL='' @@ -613,17 +613,23 @@ ac_includes_default="\ #endif" ac_subst_vars='LTLIBOBJS +CONFIG_FILES ldns_build_config_have_attr_unused ldns_build_config_have_attr_format ldns_build_config_have_ssl +DEFAULT_CAPATH +DEFAULT_CAFILE +LDNS_TRUST_ANCHOR_FILE WINDRES LIBOBJS +ldns_build_config_have_socklen_t LIBPCAP_LIBS include_unistd_h include_systypes_h include_inttypes_h ldns_build_config_have_inttypes_h include_sys_socket_h +LIBSSL_SSL_LIBS LIBSSL_LIBS LIBSSL_LDFLAGS LIBSSL_CPPFLAGS @@ -767,6 +773,9 @@ enable_sha2 enable_gost enable_ecdsa enable_rpath +with_trust_anchor +with_ca_file +with_ca_path ' ac_precious_vars='build_alias host_alias @@ -1320,7 +1329,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 ldns 1.6.13 to adapt to many kinds of systems. +\`configure' configures ldns 1.6.16 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1385,7 +1394,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of ldns 1.6.13:";; + short | recursive ) echo "Configuration of ldns 1.6.16:";; esac cat <<\_ACEOF @@ -1421,6 +1430,12 @@ Optional Packages: --with-ssl=pathname enable SSL (will check /usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw /usr) + --with-trust-anchor=KEYFILE + Default location of the trust anchor file for drill + and ldns-dane. [default=SYSCONFDIR/unbound/root.key] + --with-ca-file=CAFILE File containing CA certificates for ldns-dane + --with-ca-path=CAPATH Directory containing CA certificate files for + ldns-dane Some influential environment variables: CC C compiler command @@ -1502,7 +1517,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -ldns configure 1.6.13 +ldns configure 1.6.16 generated by GNU Autoconf 2.68 Copyright (C) 2010 Free Software Foundation, Inc. @@ -2206,7 +2221,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 ldns $as_me 1.6.13, which was +It was created by ldns $as_me 1.6.16, which was generated by GNU Autoconf 2.68. Invocation command line was $ $0 $@ @@ -2556,13 +2571,13 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu # needed to build correct soname -LIBTOOL_VERSION_INFO=1:6:13 +LIBTOOL_VERSION_INFO=1:6:16 LDNS_VERSION_MAJOR=1 LDNS_VERSION_MINOR=6 -LDNS_VERSION_MICRO=13 +LDNS_VERSION_MICRO=16 OURCPPFLAGS='' @@ -4684,6 +4699,7 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test "x$CFLAGS" = "x" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -g" >&5 @@ -4707,7 +4723,7 @@ if eval "test \"`echo '$cv_prog_cc_flag_'$cache`\" = yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } : -CFLAGS="-g $CFLAGS" +CFLAGS="-g" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } @@ -4746,6 +4762,7 @@ $as_echo "no" >&6; } fi +fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wall" >&5 @@ -5931,6 +5948,7 @@ This does not work with the --with-drill option. Please remove the config.h from the drill subdirectory or do not use the --with-drill option." "$LINENO" 5 fi + DRILL_CONFIG=" drill/drill.1" else DRILL="" @@ -5942,6 +5960,7 @@ else LINT_DRILL="" + DRILL_CONFIG="" fi @@ -5971,6 +5990,7 @@ This does not work with the --with-examples option. Please remove the config.h from the examples subdirectory or do not use the --with-examples option." "$LINENO" 5 fi + EXAMPLES_CONFIG=" examples/ldns-dane.1 examples/ldns-verify-zone.1" else EXAMPLES="" @@ -5982,6 +6002,7 @@ else LINT_EXAMPLES="" + EXAMPLES_CONFIG="" fi # add option to disable installation of ldns-config script @@ -6981,7 +7002,6 @@ else fi - # Use libtool # skip these tests, we do not need them. @@ -14706,6 +14726,10 @@ esac +if test "x$HAVE_SSL" = "xyes"; then +LIBSSL_SSL_LIBS="$LIBSSL_LIBS -lssl" + +fi CPPFLAGS=$tmp_CPPFLAGS LDFLAGS=$tmp_LDFLAGS LIBS=$tmp_LIBS @@ -15452,6 +15476,13 @@ $as_echo "#define socklen_t int" >>confdefs.h fi +if test "x$ac_cv_type_socklen_t" = xyes; then + ldns_build_config_have_socklen_t=1 + +else + ldns_build_config_have_socklen_t=0 + +fi ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" if test "x$ac_cv_type_size_t" = xyes; then : @@ -16514,6 +16545,91 @@ $as_echo "#define SYSCONFDIR sysconfdir" >>confdefs.h +# Check whether --with-trust-anchor was given. +if test "${with_trust_anchor+set}" = set; then : + withval=$with_trust_anchor; + LDNS_TRUST_ANCHOR_FILE="$withval" + +else + + if test "x$LDNS_TRUST_ANCHOR_FILE" = "x"; then + if test "x$sysconfdir" = 'x${prefix}/etc' ; then + if test "x$prefix" = 'xNONE' ; then + LDNS_TRUST_ANCHOR_FILE="/etc/unbound/root.key" + else + LDNS_TRUST_ANCHOR_FILE="${prefix}/etc/unbound/root.key" + fi + else + LDNS_TRUST_ANCHOR_FILE="${sysconfdir}/unbound/root.key" + fi + fi + +fi + + +cat >>confdefs.h <<_ACEOF +#define LDNS_TRUST_ANCHOR_FILE "$LDNS_TRUST_ANCHOR_FILE" +_ACEOF + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: Default trust anchor: $LDNS_TRUST_ANCHOR_FILE" >&5 +$as_echo "$as_me: Default trust anchor: $LDNS_TRUST_ANCHOR_FILE" >&6;} + + +# Check whether --with-ca-file was given. +if test "${with_ca_file+set}" = set; then : + withval=$with_ca_file; + +$as_echo "#define HAVE_DANE_CA_FILE 1" >>confdefs.h + + +cat >>confdefs.h <<_ACEOF +#define LDNS_DANE_CA_FILE "$withval" +_ACEOF + + { $as_echo "$as_me:${as_lineno-$LINENO}: Using CAfile: $withval" >&5 +$as_echo "$as_me: Using CAfile: $withval" >&6;} + DEFAULT_CAFILE="Default is $withval" + + +else + + +$as_echo "#define HAVE_DANE_CA_FILE 0" >>confdefs.h + + + +fi + + + +# Check whether --with-ca-path was given. +if test "${with_ca_path+set}" = set; then : + withval=$with_ca_path; + +$as_echo "#define HAVE_DANE_CA_PATH 1" >>confdefs.h + + +cat >>confdefs.h <<_ACEOF +#define LDNS_DANE_CA_PATH "$withval" +_ACEOF + + { $as_echo "$as_me:${as_lineno-$LINENO}: Using CApath: $withval" >&5 +$as_echo "$as_me: Using CApath: $withval" >&6;} + DEFAULT_CAPATH="Default is $withval" + + +else + + +$as_echo "#define HAVE_DANE_CA_PATH 0" >>confdefs.h + + + +fi + + + @@ -16539,7 +16655,9 @@ else fi -ac_config_files="$ac_config_files Makefile ldns/common.h ldns/net.h ldns/util.h packaging/libldns.pc packaging/ldns-config" +CONFIG_FILES="Makefile ldns/common.h ldns/net.h ldns/util.h packaging/libldns.pc packaging/ldns-config $DRILL_CONFIG $EXAMPLES_CONFIG" + +ac_config_files="$ac_config_files $CONFIG_FILES" ac_config_headers="$ac_config_headers ldns/config.h" @@ -17063,7 +17181,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 ldns $as_me 1.6.13, which was +This file was extended by ldns $as_me 1.6.16, which was generated by GNU Autoconf 2.68. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -17129,7 +17247,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="\\ -ldns config.status 1.6.13 +ldns config.status 1.6.16 configured by $0, generated by GNU Autoconf 2.68, with options \\"\$ac_cs_config\\" @@ -17534,12 +17652,7 @@ do case $ac_config_target in "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "disable-rpath") CONFIG_COMMANDS="$CONFIG_COMMANDS disable-rpath" ;; - "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; - "ldns/common.h") CONFIG_FILES="$CONFIG_FILES ldns/common.h" ;; - "ldns/net.h") CONFIG_FILES="$CONFIG_FILES ldns/net.h" ;; - "ldns/util.h") CONFIG_FILES="$CONFIG_FILES ldns/util.h" ;; - "packaging/libldns.pc") CONFIG_FILES="$CONFIG_FILES packaging/libldns.pc" ;; - "packaging/ldns-config") CONFIG_FILES="$CONFIG_FILES packaging/ldns-config" ;; + "$CONFIG_FILES") CONFIG_FILES="$CONFIG_FILES $CONFIG_FILES" ;; "ldns/config.h") CONFIG_HEADERS="$CONFIG_HEADERS ldns/config.h" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; diff --git a/configure.ac b/configure.ac index 500e8e67415..fae43271960 100644 --- a/configure.ac +++ b/configure.ac @@ -6,7 +6,7 @@ sinclude(acx_nlnetlabs.m4) # must be numbers. ac_defun because of later processing. m4_define([VERSION_MAJOR],[1]) m4_define([VERSION_MINOR],[6]) -m4_define([VERSION_MICRO],[13]) +m4_define([VERSION_MICRO],[16]) AC_INIT(ldns, m4_defn([VERSION_MAJOR]).m4_defn([VERSION_MINOR]).m4_defn([VERSION_MICRO]), libdns@nlnetlabs.nl, libdns) AC_CONFIG_SRCDIR([packet.c]) # needed to build correct soname @@ -63,8 +63,10 @@ COPY_FILES($srcdir/$1/*.h, $2) # Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_LANG_C -ACX_CHECK_COMPILER_FLAG(g, [CFLAGS="-g $CFLAGS"]) +if test "x$CFLAGS" = "x" ; then +ACX_CHECK_COMPILER_FLAG(g, [CFLAGS="-g"]) ACX_CHECK_COMPILER_FLAG(O2, [CFLAGS="-O2 $CFLAGS"]) +fi ACX_CHECK_COMPILER_FLAG(Wall, [CFLAGS="-Wall $CFLAGS"]) ACX_CHECK_COMPILER_FLAG(W, [CFLAGS="-W $CFLAGS"]) ACX_CHECK_COMPILER_FLAG(Wwrite-strings, [CFLAGS="-Wwrite-strings $CFLAGS"]) @@ -112,12 +114,14 @@ This does not work with the --with-drill option. Please remove the config.h from the drill subdirectory or do not use the --with-drill option.]) fi + DRILL_CONFIG=" drill/drill.1" else AC_SUBST(DRILL,[""]) AC_SUBST(INSTALL_DRILL,[""]) AC_SUBST(UNINSTALL_DRILL,[""]) AC_SUBST(CLEAN_DRILL,[""]) AC_SUBST(LINT_DRILL,[""]) + DRILL_CONFIG="" fi @@ -137,12 +141,14 @@ This does not work with the --with-examples option. Please remove the config.h from the examples subdirectory or do not use the --with-examples option.]) fi + EXAMPLES_CONFIG=" examples/ldns-dane.1 examples/ldns-verify-zone.1" else AC_SUBST(EXAMPLES,[""]) AC_SUBST(INSTALL_EXAMPLES,[""]) AC_SUBST(UNINSTALL_EXAMPLES,[""]) AC_SUBST(CLEAN_EXAMPLES,[""]) AC_SUBST(LINT_EXAMPLES,[""]) + EXAMPLES_CONFIG="" fi # add option to disable installation of ldns-config script @@ -249,7 +255,6 @@ else AC_SUBST(PYLDNSXUNINST, "") fi - # Use libtool ACX_LIBTOOL_C_ONLY @@ -318,6 +323,9 @@ esac AC_SUBST(LIBSSL_CPPFLAGS) AC_SUBST(LIBSSL_LDFLAGS) AC_SUBST(LIBSSL_LIBS) +if test "x$HAVE_SSL" = "xyes"; then +AC_SUBST(LIBSSL_SSL_LIBS, ["$LIBSSL_LIBS -lssl"]) +fi CPPFLAGS=$tmp_CPPFLAGS LDFLAGS=$tmp_LDFLAGS LIBS=$tmp_LIBS @@ -444,6 +452,11 @@ AC_INCLUDES_DEFAULT fi ACX_TYPE_SOCKLEN_T +if test "x$ac_cv_type_socklen_t" = xyes; then + AC_SUBST(ldns_build_config_have_socklen_t, 1) +else + AC_SUBST(ldns_build_config_have_socklen_t, 0) +fi AC_TYPE_SIZE_T AC_TYPE_SSIZE_T AC_TYPE_INTPTR_T @@ -507,6 +520,45 @@ fi AC_DEFINE([SYSCONFDIR], [sysconfdir], [System configuration dir]) +AC_ARG_WITH(trust-anchor, AC_HELP_STRING([--with-trust-anchor=KEYFILE], [Default location of the trust anchor file for drill and ldns-dane. [default=SYSCONFDIR/unbound/root.key]]), [ + LDNS_TRUST_ANCHOR_FILE="$withval" +],[ + if test "x$LDNS_TRUST_ANCHOR_FILE" = "x"; then + if test "x$sysconfdir" = 'x${prefix}/etc' ; then + if test "x$prefix" = 'xNONE' ; then + LDNS_TRUST_ANCHOR_FILE="/etc/unbound/root.key" + else + LDNS_TRUST_ANCHOR_FILE="${prefix}/etc/unbound/root.key" + fi + else + LDNS_TRUST_ANCHOR_FILE="${sysconfdir}/unbound/root.key" + fi + fi +]) +AC_DEFINE_UNQUOTED([LDNS_TRUST_ANCHOR_FILE], ["$LDNS_TRUST_ANCHOR_FILE"], [Default trust anchor file]) +AC_SUBST(LDNS_TRUST_ANCHOR_FILE) +AC_MSG_NOTICE([Default trust anchor: $LDNS_TRUST_ANCHOR_FILE]) + +AC_ARG_WITH(ca-file, AC_HELP_STRING([--with-ca-file=CAFILE], [File containing CA certificates for ldns-dane]), [ + AC_DEFINE([HAVE_DANE_CA_FILE], [1], [Is a CAFILE given at configure time]) + AC_DEFINE_UNQUOTED([LDNS_DANE_CA_FILE], ["$withval"], [Is a CAFILE given at configure time]) + AC_MSG_NOTICE([Using CAfile: $withval]) + AC_SUBST(DEFAULT_CAFILE, ["Default is $withval"]) +],[ + AC_DEFINE([HAVE_DANE_CA_FILE], [0], [Is a CAFILE given at configure time]) + AC_SUBST(DEFAULT_CAFILE, []) +]) + +AC_ARG_WITH(ca-path, AC_HELP_STRING([--with-ca-path=CAPATH], [Directory containing CA certificate files for ldns-dane]), [ + AC_DEFINE([HAVE_DANE_CA_PATH], [1], [Is a CAPATH given at configure time]) + AC_DEFINE_UNQUOTED([LDNS_DANE_CA_PATH], ["$withval"], [Is a CAPATH given at configure time]) + AC_MSG_NOTICE([Using CApath: $withval]) + AC_SUBST(DEFAULT_CAPATH, ["Default is $withval"]) +],[ + AC_DEFINE([HAVE_DANE_CA_PATH], [0], [Is a CAPATH given at configure time]) + AC_SUBST(DEFAULT_CAPATH, []) +]) + AH_BOTTOM([ #include #include @@ -663,7 +715,9 @@ else AC_SUBST(ldns_build_config_have_attr_unused, 0) fi -AC_CONFIG_FILES([Makefile ldns/common.h ldns/net.h ldns/util.h packaging/libldns.pc packaging/ldns-config]) +CONFIG_FILES="Makefile ldns/common.h ldns/net.h ldns/util.h packaging/libldns.pc packaging/ldns-config $DRILL_CONFIG $EXAMPLES_CONFIG" +AC_SUBST(CONFIG_FILES) +AC_CONFIG_FILES([$CONFIG_FILES]) AC_CONFIG_HEADER([ldns/config.h]) AC_OUTPUT diff --git a/contrib/python/Changelog b/contrib/python/Changelog new file mode 100644 index 00000000000..aaa57e13692 --- /dev/null +++ b/contrib/python/Changelog @@ -0,0 +1,66 @@ +1.6.16 2012-11-13 + * Fix typo in ldns_struct_pkt.opcode2str + +1.6.14 2012-10-23 + * Added rich comparison methods for ldns_dname, ldns_rdf, ldns_rr and + ldns_rr_list classes. + * Added deprecation warnings into ldns_rr.new_frm_fp() and + ldns_rr.new_frm_fp_l() and others. + * Fixed ldns_rr.set_rdf(), which may cause memory leaks, because it + returns new objects (in the scope of Python). Also it leaked memory, + when the call was not successful. + * Fixed ldns_get_rr_list_hosts_frm_file, marked as newobject. + * Fixed ldns_rr_list.cat() to return bool as mentioned in documentation. + * Fixed ldns_rr_list_cat_clone, marked as newobject. + * Fixed ldns_rr_list.new_frm_file(). Exception argument was invalid. + * Fixed ldns_rr_list.push_rr() to return bool as mentioned in + documentation. + * Fixed ldns_rr_list.push_rr_list() to return bool as mentioned in + documentation. + * Fixed ldns_rr_list.set_rr(), which caused memory corruption, double free + problems and memory leaks. (The wrapper used original function instead + of its push cloned variant which was missing.) + * Fixed ldns_rr_list.set_rr_count(), added python exception raise in order + to avoid assertion failure. + * Fixed ldns_rr_list.subtype_by_rdf(), marked as newobject. + * Added ldns_rr.to_canonical(), ldns_rr.is_question(), + ldns_rr.type_by_name(), ldns_rr.class_by_name(), ldns_rr_list.new(), + ldns_rr.set_question(). + * Modified ldns_rr_list.owner() and ldns_rr.owner(), now returns ldns_dname. + * Fixed assertion failures for several methods when receiving incorrect but + syntactically valid arguments (i.e., ldns_rr.a_address(), + ldns_rr.dnskey_algorithm(), ldns_rr.dnskey_flags(), + ldns_rr.dnskey_key(), ldns_rr.dnskey_protocol(), + ldns_rr.mx_exchange(), ldns_rr.mx_preference(), ldns_rr.ns_nsdname(), + ldns_rr.owner(), ldns_rr.rdf(), ldns_rr.rrsig_algorithm(), + ldns_rr.rrsig_expiration(), ldns_rr.rrsig_inception(), + ldns_rr.rrsig_keytag(), ldns_rr.rrsig_labels(), ldns_rr.rrsig_origttl(), + ldns_rr.rrsig_sig(), ldns_rr.rrsig_signame(), + ldns_rr.rrsig_typecovered(), ldns_rr_list.owner(), ldns_rr_list.rr()) + * Fixed ldns_rr.a_address(), which was asserting when called + on non A or AAAA type rr. Now returns None when fails. + * Added scripts for testing the basic functionality of the ldns_rr, + ldns_rr_descriptor and ldns_rr_list class code. + * Improved documentation of ldns_rr, ldns_rr_descriptor and ldns_rr_list. + * Fixed automatic conversion from Python string to ldns_rdf and + ldns_dname. Caused memory corruption when using Python 3. + * The Python 3 wrapper code now raises TypeError instead of ValueError + when receiving a non FILE * argument when it should be a FILE *. + * Fixed wrong handling of _ldns_rr_list_free() and + _ldns_rr_list_deep_free() when compiling with LDNS_DEBUG directive. + * Fixed malfunctioning ldns.ldns_rdf_new_frm_fp_l(). + * Fixed malfunctioning ldns_drf.absolute() and ldns_dname.absolute(). + * Marked several functions related to ldns_rdf and ldns_buffer as + returning new objects. + * Method operating on ldns_dnames and returning dname ldns_rdfs now + return ldns_dname instances. + * Improved documentation of ldns_buffer, ldns_rdf and ldns_dname + classes. + * Methods ldns_buffer.available() and ldns_buffer.available_at() now + return bool types as described in the documentation. + * Added scripts for testing the basic functionality of the ldns_buffer, + ldns_rdf, ldns_dname class code. + * Added deprecation warnings to ldns_rdf methods operating on dname + rdfs. The user is encouraged to converts dname ldns_rdfs to + ldns_dnames. + * Extended ldns_dname constructor to accept ldns_rdfs containing dnames. diff --git a/contrib/python/Makefile b/contrib/python/Makefile index c43970509a4..927685764bb 100644 --- a/contrib/python/Makefile +++ b/contrib/python/Makefile @@ -28,6 +28,9 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. + +.PHONY: help clean testenv test doc te bw bw3 sw sw3 + help: @echo "Please use \`make ' where is one of" @echo " testenv to make test environment and run bash " @@ -41,27 +44,65 @@ help: _ldns.so: ../../Makefile $(MAKE) -C ../.. -../../.libs/ldns.so.1: ../../Makefile +../../.libs/libldns.so.1: ../../Makefile $(MAKE) -C ../.. clean: - rm -rdf examples/ldns + rm -rf examples/ldns rm -f _ldns.so ldns_wrapper.o $(MAKE) -C ../.. clean testenv: ../../.libs/libldns.so.1 _ldns.so - rm -rdf examples/ldns - cd examples && mkdir ldns && ln -s ../../ldns.py ldns/__init__.py && ln -s ../../_ldns.so ldns/_ldns.so && ln -s ../../../../.libs/libldns.so.1 ldns/libldns.so.1 && ls -la + rm -rf examples/ldns + cd examples && mkdir ldns && ln -s ../../ldns.py ldns/__init__.py && ln -s ../../../../.libs/_ldns.so ldns/_ldns.so && ln -s ../../../../.libs/libldns.so.1 ldns/libldns.so.1 && ls -la @echo "Run a script by typing ./script_name.py" cd examples && LD_LIBRARY_PATH=ldns bash - rm -rdf examples/ldns + rm -rf examples/ldns -doc: ../../.libs/ldns.so.1 _ldns.so +test: ../../.libs/libldns.so.1 _ldns.so examples/test_buffer.py examples/test_rdf.py examples/test_dname.py examples/test_rr.py + @rm -rf examples/ldns + @cd examples && mkdir ldns && ln -s ../../ldns.py ldns/__init__.py && ln -s ../../../../.libs/_ldns.so ldns/_ldns.so && ln -s ../../../../.libs/libldns.so.1 ldns/libldns.so.1 + @cd examples && LD_LIBRARY_PATH=ldns ./test_buffer.py 2>/dev/null + @cd examples && LD_LIBRARY_PATH=ldns ./test_rdf.py 2>/dev/null + @cd examples && LD_LIBRARY_PATH=ldns ./test_dname.py 2>/dev/null + @cd examples && LD_LIBRARY_PATH=ldns ./test_rr.py 2>/dev/null + @rm -rf examples/ldns + +doc: ../../.libs/libldns.so.1 _ldns.so + echo @VERSION_MAJOR@ + rm -f _ldns.so + ln -s ../../.libs/_ldns.so $(MAKE) -C docs html + rm -f _ldns.so -#for development only -swig: ldns.i - swig -python -py3 -o ldns_wrapper.c -I../.. ldns.i - gcc -c ldns_wrapper.c -O9 -fPIC -I../.. -I../../ldns -I/usr/include/python3.1 -I. -o ldns_wrapper.o - ld -shared ldns_wrapper.o -L../../.libs -lldns -o _ldns.so +# For development only: +# Test environment, does not build the wrapper from dependencies. +te: + rm -rf examples/ldns + cd examples && mkdir ldns && ln -s ../../ldns.py ldns/__init__.py && ln -s ../../../../.libs/_ldns.so ldns/_ldns.so && ln -s ../../../../.libs/libldns.so.1 ldns/libldns.so.1 && ls -la + @echo "Run a script by typing ./script_name.py" + cd examples && LD_LIBRARY_PATH=ldns bash + rm -rf examples/ldns + +# Builds Python 2 wrapper from present wrapper C code. +bw: + gcc -c ldns_wrapper.c -O9 -fPIC -I../.. -I../../ldns -I/usr/include/python2.7 -I. -o ldns_wrapper.o + mkdir -p ../../.libs + ld -shared ldns_wrapper.o -L../../.libs -lldns -o ../../.libs/_ldns.so + +# Builds Python 3 wrapper from present wrapper C code. +bw3: + gcc -c ldns_wrapper.c -O9 -fPIC -I../.. -I../../ldns -I/usr/include/python3.2 -I. -o ldns_wrapper.o + mkdir -p ../../.libs + ld -shared ldns_wrapper.o -L../../.libs -ldns -o ../../.libs/_ldns.so + +# Builds Python 2 wrapper from interface file. +sw: ldns.i + swig -python -o ldns_wrapper.c -I../.. ldns.i + $(MAKE) bw + +# Builds Python 3 wrapper from interface file. +sw3: ldns.i + swig -python -py3 -DPY3 -o ldns_wrapper.c -I../.. ldns.i + $(MAKE) bw3 diff --git a/contrib/python/docs/source/conf.py b/contrib/python/docs/source/conf.py index 22b73bcd712..4d891543b1a 100644 --- a/contrib/python/docs/source/conf.py +++ b/contrib/python/docs/source/conf.py @@ -43,9 +43,9 @@ copyright = '2009, Karel Slany, Zdenek Vasicek' # other places throughout the built documents. # # The short X.Y version. -version = '1.0' +version = '1.6' # The full version, including alpha/beta/rc tags. -release = '1.0.0' +release = '1.6.16' # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: diff --git a/contrib/python/docs/source/install.rst b/contrib/python/docs/source/install.rst index b3845b6e21b..03d0f53facb 100644 --- a/contrib/python/docs/source/install.rst +++ b/contrib/python/docs/source/install.rst @@ -3,44 +3,70 @@ Installation **Prerequisites** -Python 2.4 or higher, SWIG 1.3 or higher, GNU make +SWIG 1.3 and GNU make are required to build modules for Python 2.4 and higher +(but lower than 3). In order to build modules for Python 3.2 or higher, +SWIG in version 2.0.4 or higher is required. + +Note that Python 3.0 and 3.1 are not supported. + +In order to build this documentation the Sphinx Python documentation generator +is required. **Download** -You can download the source codes `here`_. -The latest release is 1.4.1, Jan 15, 2009. +The lates source codes can be downloaded from `here`_. -.. _here: ldns-1.4.1-py.tar.gz +.. _here: http://nlnetlabs.nl/projects/ldns/ **Compiling** -After downloading, you can compile the library by doing:: +After downloading the source code archive (this example uses +ldns-1.6.13.tar.gz), pyLDNS can be enabled and compiled by typing:: - > tar -xzf ldns-1.4.1-py.tar.gz - > cd ldns-1.4.1 + > tar -xzf ldns-1.6.13.tar.gz + > cd ldns-1.6.13 > ./configure --with-pyldns > make -You need GNU make to compile pyLDNS; SWIG and Python development libraries to compile extension module. +You need GNU make to compile pyLDNS; SWIG and Python development libraries to +compile the extension module. +**Selecting Target Python Interpreter** + +By default, the pyLDNS module builds for the default Python interpreter (i.e., +the Python interpreter which can be accessed by just typing ``python`` in +the command line). If you desire to build the pyLDNS module for a different +Python version then you must specify the desired Python version by setting +the ``PYTHON_VERSION`` variable during the configure phase:: + + > PYTHON_VERSION=3.2 ./configure --with-pyldns + > make + +By default the pyLDNS compiles from sources for a single Python interpreter. +Remember to execute scripts requiring pyLDNS in those Python interpreters which +have pyLDNS installed. **Testing** -If the compilation is successfull, you can test the python LDNS extension module by:: +If the compilation is successful, you can test the python LDNS extension module +by executing the commands:: > cd contrib/python > make testenv > ./ldns-mx.py -This will start a new shell, during which the symbolic links will be working. -When you exit the shell, then symbolic links will be deleted. +Again, remember to use the Python interpreter version which the pyLDNS module +has been compiled with. -In ``contrib/examples`` you can find many simple applications in python which demostrates the capabilities of LDNS library. +The commands will start a new shell, in which several symbolic links will be +set-up. When you exit the shell, then symbolic links will be deleted. + +In ``contrib/python/examples`` several simple Python scripts utilising pyLDNS +can be found. These scripts demonstrate the capabilities of the LDNS library. **Installation** -To install libraries and extension type:: +To install the libraries and it's extensions type:: - > cd ldns-1.4.1 + > cd ldns-1.6.13 > make install - diff --git a/contrib/python/examples/ldns-keygen.py b/contrib/python/examples/ldns-keygen.py index 3ddf41a946e..71375fce205 100755 --- a/contrib/python/examples/ldns-keygen.py +++ b/contrib/python/examples/ldns-keygen.py @@ -7,7 +7,7 @@ import ldns algorithm = ldns.LDNS_SIGN_DSA bits = 512 -ldns.ldns_init_random(open("/dev/random","rb"), (bits+7)//8) +ldns.ldns_init_random(open("/dev/urandom","rb"), (bits+7)//8) domain = ldns.ldns_dname("example.") diff --git a/contrib/python/examples/python3/ldns-signzone.py b/contrib/python/examples/python3/ldns-signzone.py new file mode 100755 index 00000000000..cac5d32165b --- /dev/null +++ b/contrib/python/examples/python3/ldns-signzone.py @@ -0,0 +1,65 @@ +#!/usr/bin/python +# This example shows how to sign a given zone file with private key + +import ldns +import sys, os, time + +#private key TAG which identifies the private key +#use ldns-keygen.py in order to obtain private key +keytag = 30761 + +# Read zone file +#------------------------------------------------------------- + +zone = ldns.ldns_zone.new_frm_fp(open("zone.txt","r"), None, 0, ldns.LDNS_RR_CLASS_IN) +soa = zone.soa() +origin = soa.owner() + +# Prepare keys +#------------------------------------------------------------- + +#Read private key from file +keyfile = open("key-%s-%d.private" % (origin, keytag), "r"); +key = ldns.ldns_key.new_frm_fp(keyfile) + +#Read public key from file +pubfname = "key-%s-%d.key" % (origin, keytag) +pubkey = None +if os.path.isfile(pubfname): + pubkeyfile = open(pubfname, "r"); + pubkey,_,_,_ = ldns.ldns_rr.new_frm_fp(pubkeyfile) + +if not pubkey: + #Create new public key + pubkey = key.key_to_rr() + +#Set key expiration +key.set_expiration(int(time.time()) + 365*60*60*24) #365 days + +#Set key owner (important step) +key.set_pubkey_owner(origin) + +#Insert DNSKEY RR +zone.push_rr(pubkey) + +# Sign zone +#------------------------------------------------------------- + +#Create keylist and push private key +keys = ldns.ldns_key_list() +keys.push_key(key) + +#Add SOA +signed_zone = ldns.ldns_dnssec_zone() +signed_zone.add_rr(soa) + +#Add RRs +for rr in zone.rrs().rrs(): + print("RR:", str(rr), end=" ") + signed_zone.add_rr(rr) + +added_rrs = ldns.ldns_rr_list() +status = signed_zone.sign(added_rrs, keys) +if (status == ldns.LDNS_STATUS_OK): + signed_zone.print_to_file(open("zone_signed.txt","w")) + diff --git a/contrib/python/examples/test_buffer.py b/contrib/python/examples/test_buffer.py new file mode 100755 index 00000000000..0baf76f6ab0 --- /dev/null +++ b/contrib/python/examples/test_buffer.py @@ -0,0 +1,843 @@ +#!/usr/bin/env python + +# +# ldns_buffer testing script. +# +# Do not use constructs that differ between Python 2 and 3. +# Use write on stdout or stderr. +# + + +import ldns +import sys +import os +import inspect + + +class_name = "ldns_buffer" +method_name = None +error_detected = False + + +def set_error(): + """ + Writes an error message and sets error flag. + """ + global class_name + global method_name + global error_detected + error_detected = True + sys.stderr.write("(line %d): malfunctioning method %s.\n" % \ + (inspect.currentframe().f_back.f_lineno, method_name)) + + +# Buffer creation. +capacity = 1024 + +#if not error_detected: +if True: + method_name = "ldns_buffer.__init__()" + try: + buf = ldns.ldns_buffer(1024) + except: + set_error() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.__str__()" + buf.printf("abcedf") + try: + string = buf.__str__() + except: + set_error() + if not isinstance(string, str): + # Should be string. + set_error() + buf.clear() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.at()" + try: + ret = buf.at(512) + except: + set_error() + try: + # Must raise TypeError. + ret = buf.at("") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.available()" + try: + ret = buf.available(capacity) + except: + set_error() + if not isinstance(ret, bool): + # Should be bool. + set_error() + if not buf.available(capacity): + # Should return True. + set_error() + if buf.available(capacity + 1): + # Should return False. + set_error() + try: + # Must raise TypeError. + ret = buf.available("") + set_error() + except TypeError: + pass + except: + set_error() +# try: +# # Must raise ValueError. +# ret = buf.available("") +# set_error() +# except ValueError: +# pass +# except: +# set_error() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.available_at()" + try: + ret = buf.available_at(512, capacity - 512) + except: + set_error() + if not isinstance(ret, bool): + # Should be bool. + set_error() + if not buf.available_at(512, capacity - 512): + # Should return True. + set_error() + if buf.available_at(512, capacity - 512 + 1): + # Should return False. + set_error() + try: + # Must raise TypeError. + ret = buf.available_at("", 1) + set_error() + except TypeError: + pass + except: + set_error() + try: + # Must raise TypeError. + ret = buf.available_at(1, "") + set_error() + except TypeError: + pass + except: + set_error() +# try: +# # Must raise ValueError. +# ret = buf.available_at(-1, 512) +# set_error() +# except ValueError: +# pass +# except: +# set_error() +# try: +# # Must raise ValueError. +# ret = buf.available_at(512, -1) +# set_error() +# except ValueError: +# pass +# except: +# set_error() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.begin()" + try: + ret = buf.begin() + except: + set_error() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.capacity()" + try: + ret = buf.capacity() + except: + set_error() + if not isinstance(ret, int): + # Should be int. + set_error() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.clear()" + try: + buf.clear() + except: + set_error() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.copy()" + sys.stderr.write("%s not tested.\n" % (method_name)) +# buf2 = ldns.ldns_buffer(10) +# buf2.printf("abcdef") +# try: +# buf.copy(buf2) +# print buf.capacity() +# print buf2.capacity() +# except: +# set_error() +# buf.printf("2") +# print buf + + +#if not error_detected: +if True: + method_name = "ldns_buffer.current()" + try: + ret = buf.current() + except: + set_error() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.end()" + try: + ret = buf.end() + except: + set_error() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.export()" + sys.stderr.write("%s not tested.\n" % (method_name)) + + +#if not error_detected: +if True: + mehod_name = "ldns_buffer.flip()" + buf.printf("abcdef") + try: + buf.flip() + except: + set_error() +# if buf.remaining() != capacity: +# # Should be at beginning. +# set_error() + buf.clear() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.getc()" + buf.printf("a") + buf.rewind() + try: + ret = buf.getc() + except: + set_error() + if ret != ord("a"): + set_error() +# Test return value for -1 + buf.clear() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.invariant()" + try: + buf.invariant() + except: + set_error() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.limit()" + try: + ret = buf.limit() + except: + set_error() + if ret != capacity: + set_error() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.position()" + try: + ret = buf.position() + except: + set_error() + if not isinstance(ret, int): + set_error() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.printf()" + try: + ret = buf.printf("abcdef") + except: + set_error() + if not isinstance(ret, int): + set_error() + try: + ret = buf.printf(10) + set_error() + except TypeError: + pass + except: + set_error() + buf.clear() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.read()" + sys.stderr.write("%s not tested.\n" % (method_name)) + + +#if not error_detected: +if True: + method_name = "ldns_buffer.read_at()" + sys.stderr.write("%s not tested.\n" % (method_name)) + + +#if not error_detected: +if True: + method_name = "ldns_buffer.read_u16()" + buf.printf("aac") + buf.rewind() + try: + ret = buf.read_u16() + except: + set_error() + if not isinstance(ret, int): + set_error() + if ret != (ord("a") * 0x0101): + set_error() + buf.clear() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.read_u16_at()" + buf.printf("abbc") + try: + ret = buf.read_u16_at(1) + except: + set_error() + if not isinstance(ret, int): + set_error() + if ret != (ord("b") * 0x0101): + set_error() + try: + ret = buf.read_u16_at("") + set_error() + except TypeError: + pass + except: + set_error() +# try: +# ret = buf.read_u16_at(-1) +# set_error() +# except ValueError: +# pass +# except: +# set_error() + buf.clear() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.read_u32()" + buf.printf("aaaac") + buf.rewind() + try: + ret = buf.read_u32() + except: + set_error() + if not isinstance(ret, int): + set_error() + if ret != (ord("a") * 0x01010101): + set_error() + buf.clear() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.read_u32_at()" + buf.printf("abbbbc") + try: + ret = buf.read_u32_at(1) + except: + set_error() + if not isinstance(ret, int): + set_error() + if ret != (ord("b") * 0x01010101): + set_error() + try: + ret = buf.read_u32_at("") + set_error() + except TypeError: + pass + except: + set_error() +# try: +# ret = buf.read_u32_at(-1) +# set_error() +# except ValueError: +# pass +# except: +# set_error() + buf.clear() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.read_u8()" + buf.printf("ac") + buf.rewind() + try: + ret = buf.read_u8() + except: + set_error() + if not isinstance(ret, int): + set_error() + if ret != ord("a"): + set_error() + buf.clear() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.read_u8_at()" + buf.printf("abc") + try: + ret = buf.read_u8_at(1) + except: + set_error() + if not isinstance(ret, int): + set_error() + if ret != ord("b"): + set_error() + try: + ret = buf.read_u8_at("") + set_error() + except TypeError: + pass + except: + set_error() +# try: +# ret = buf.read_u8_at(-1) +# set_error() +# except ValueError: +# pass +# except: +# set_error() + buf.clear() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.remaining()" + buf.printf("abcdef") + try: + ret = buf.remaining() + except: + set_error() + if not isinstance(ret, int): + set_error() + if ret != (capacity - 6): + set_error() + buf.clear() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.remaining_at()" + buf.printf("abcdef") + try: + ret = buf.remaining_at(1) + except: + set_error() + if not isinstance(ret, int): + set_error() + if ret != (capacity - 1): + set_error() + try: + ret = buf.remaining_at("") + set_error() + except TypeError: + pass + except: + set_error() +# try: +# ret = buf.remaining_at(-1) +# set_error() +# except ValueError: +# pass +# except: +# set_error() + buf.clear() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.reserve()" + buf2 = ldns.ldns_buffer(512) + try: + ret = buf2.reserve(1024) + except: + set_error() + if not isinstance(ret, bool): + set_error() + try: + ret = buf2.reserve("") + set_error() + except TypeError: + pass + except: + set_error() +# try: +# ret = buf2.reserve(-1) +# set_error() +# except ValueError: +# pass +# except: +# set_error() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.rewind()" + buf.printf("abcdef") + try: + buf.rewind() + except: + set_error() + if buf.position() != 0: + set_error() + buf.clear() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.set_capacity()" + try: + ret = buf.set_capacity(capacity) + except: + set_error() + if not isinstance(ret, bool): + set_error() + try: + ret = buf.set_capacity("") + set_error() + except TypeError: + pass + except: + set_error() +# try: +# ret = buf.set_capacity(-1) +# set_error() +# except ValueError: +# pass +# except: +# set_error() + buf.clear() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.set_limit()" + try: + buf.set_limit(0) + except: + set_error() + try: + buf.set_limit("") + set_error() + except TypeError: + pass + except: + set_error() +# try: +# buf.set_limit(-1) +# set_error() +# except ValueError: +# pass +# except: +# set_error() + buf.clear() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.set_position()" + try: + buf.set_position(0) + except: + set_error() + try: + buf.set_position("") + except TypeError: + pass + except: + set_error() +# try: +# buf.set_position(-1) +# except ValueError: +# pass +# except: +# set_error() + buf.clear() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.skip()" + try: + buf.skip(10) + except: + set_error() + try: + buf.skip(-1) + except: + set_error() + try: + buf.skip("") + set_error() + except TypeError: + pass + except: + set_error() + buf.clear() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.status()" + try: + ret = buf.status() + except: + set_error() + # Returned status is an integer. + if not isinstance(ret, int): + set_error() + buf.clear() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.status_ok()" + try: + ret = buf.status_ok() + except: + set_error() + if not isinstance(ret, bool): + set_error() + buf.clear() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.write()" + sys.stderr.write("%s not tested.\n" % (method_name)) + + +#if not error_detected: +if True: + method_name = "ldns_buffer.write_at()" + sys.stderr.write("%s not tested.\n" % (method_name)) + + +#if not error_detected: +if True: + method_name = "ldns_buffer.write_string()" + try: + buf.write_string("abcdef") + except: + set_error() +# try: +# buf.write_sring(-1) +# set_error() +# except TypeError: +# pass +# except: +# set_error() + sys.stderr.write("%s not tested for parameter correctness.\n" % \ + (method_name)) + buf.clear() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.write_string_at()" + sys.stderr.write("%s not tested.\n" % (method_name)) + + +#if not error_detected: +if True: + method_name = "ldns_buffer.write_u16()" + try: + buf.write_u16(ord("b") * 0x0101) + except: + set_error() + try: + buf.write_u16("") + set_error() + except TypeError: + pass + except: + set_error() + buf.clear() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.write_u16_at()" + buf.printf("a") + try: + buf.write_u16_at(1, ord("b") * 0x0101) + except: + set_error() + try: + buf.write_u16_at("", ord("b") * 0x0101) + set_error() + except TypeError: + pass + except: + set_error() +# try: +# buf.write_u16_at(-1, ord("b") * 0x0101) +# set_error() +# except ValueError: +# pass +# except: +# set_error() + try: + buf.write_u16_at(1, "") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.write_u32()" + try: + buf.write_u32(ord("b") * 0x01010101) + except: + set_error() + try: + buf.write_u32("") + set_error() + except TypeError: + pass + except: + set_error() + buf.clear() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.write_u32_at()" + buf.printf("a") + try: + buf.write_u32_at(1, ord("b") * 0x01010101) + except: + set_error() + try: + buf.write_u32_at("", ord("b") * 0x01010101) + set_error() + except TypeError: + pass + except: + set_error() +# try: +# buf.write_u32_at(-1, ord("b") * 0x01010101) +# set_error() +# except ValueError: +# pass +# except: +# set_error() + try: + buf.write_u32_at(1, "") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.write_u8()" + try: + buf.write_u8(ord("b")) + except: + set_error() + try: + buf.write_u8("") + set_error() + except TypeError: + pass + except: + set_error() + buf.clear() + + +#if not error_detected: +if True: + method_name = "ldns_buffer.write_u8_at()" + buf.printf("a") + try: + buf.write_u8_at(1, ord("b")) + except: + set_error() + try: + buf.write_u8_at("", ord("b")) + set_error() + except TypeError: + pass + except: + set_error() +# try: +# buf.write_u8_at(-1, ord("b")) +# set_error() +# except ValueError: +# pass +# except: +# set_error() + try: + buf.write_u8_at(1, "") + set_error() + except TypeError: + pass + except: + set_error() + + +if not error_detected: + sys.stdout.write("%s: passed.\n" % (os.path.basename(__file__))) +else: + sys.stdout.write("%s: errors detected.\n" % (os.path.basename(__file__))) + sys.exit(1) diff --git a/contrib/python/examples/test_dname.py b/contrib/python/examples/test_dname.py new file mode 100755 index 00000000000..d69170737ac --- /dev/null +++ b/contrib/python/examples/test_dname.py @@ -0,0 +1,474 @@ +#!/usr/bin/env python + +# +# ldns_dname testing script. +# +# Do not use constructs that differ between Python 2 and 3. +# Use write on stdout or stderr. +# + + +import ldns +import sys +import os +import inspect + + +class_name = "ldns_dname" +method_name = None +error_detected = False +temp_fname = "tmp_dname.txt" + + +def set_error(): + """ + Writes an error message and sets error flag. + """ + global class_name + global method_name + global error_detected + error_detected = True + sys.stderr.write("(line %d): malfunctioning method %s.\n" % \ + (inspect.currentframe().f_back.f_lineno, method_name)) + + +#if not error_detected: +if True: + method_name = class_name + ".__init__()" + rdf1 = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "test.nic.cz.") + rdf2 = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_A, "217.31.205.50") + try: + dname = ldns.ldns_dname("www.nic.cz.") + if not isinstance(dname, ldns.ldns_dname): + set_error() + except: + set_error() + # + # Error when printing a dname wich was created fron an empty string. + # Must find out why. + # + try: + dname = ldns.ldns_dname(rdf1) + if not isinstance(dname, ldns.ldns_dname): + set_error() + except: + set_error() + # Test whether rdf1 and dname independent. + dname.cat(dname) + if dname.__str__() == rdf1.__str__(): + set_error() + # Test whether rdf1 and dname are dependent. + dname = ldns.ldns_dname(rdf1, clone=False) + dname.cat(dname) + if dname.__str__() != rdf1.__str__(): + set_error() + # Test whether constructs from non-dname rdfs. + try: + dname = ldns.ldns_dname(rdf2) + set_error() + except TypeError: + pass + except: + set_error() + try: + dname = ldns.ldns_dname(1) + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".[comparison operators]" + dn1 = ldns.ldns_dname("a.test") + dn2 = ldns.ldns_dname("b.test") + try: + ret = dn1 < dn2 + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + try: + ret = dn2 < dn1 + if not isinstance(ret, bool): + set_error() + if ret != False: + set_error() + except: + set_error() + try: + ret = dn1 <= dn2 + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + try: + ret = dn2 <= dn1 + if not isinstance(ret, bool): + set_error() + if ret != False: + set_error() + except: + set_error() + try: + ret = dn1 == dn2 + if not isinstance(ret, bool): + set_error() + if ret != False: + set_error() + except: + set_error() + try: + ret = dn1 == dn1 + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + try: + ret = dn1 != dn2 + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + try: + ret = dn1 != dn1 + if not isinstance(ret, bool): + set_error() + if ret != False: + set_error() + except: + set_error() + try: + ret = dn1 > dn2 + if not isinstance(ret, bool): + set_error() + if ret != False: + set_error() + except: + set_error() + try: + ret = dn2 > dn1 + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + try: + ret = dn1 >= dn2 + if not isinstance(ret, bool): + set_error() + if ret != False: + set_error() + except: + set_error() + try: + ret = dn2 >= dn1 + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".absolute()" + dname = ldns.ldns_dname("www.nic.cz.") + try: + ret = dname.absolute() + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".cat()" + rdf1 = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "test.nic.cz.") + rdf2 = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_A, "217.31.205.50") + dname = ldns.ldns_dname("www.nic.cz.") + try: + ret = dname.cat(dname) + if ret != ldns.LDNS_STATUS_OK: + set_error() + if dname.__str__() != "www.nic.cz.www.nic.cz.": + set_error() + except: + set_error() + try: + ret = dname.cat(rdf1) + if ret != ldns.LDNS_STATUS_OK: + set_error() + if dname.__str__() != "www.nic.cz.www.nic.cz.test.nic.cz.": + set_error() + except: + set_error() + try: + ret = dname.cat(rdf2) + if ret == ldns.LDNS_STATUS_OK: + set_error() + except: + set_error() + try: + ret = dname.cat("") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".cat_clone()" + rdf1 = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "test.nic.cz.") + rdf2 = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_A, "217.31.205.50") + dname = ldns.ldns_dname("www.nic.cz.") + try: + ret = dname.cat_clone(dname) + if not isinstance(ret, ldns.ldns_dname): + set_error() + if ret.__str__() != "www.nic.cz.www.nic.cz.": + set_error() + except: + set_error() + try: + ret = dname.cat_clone(rdf1) + if not isinstance(ret, ldns.ldns_dname): + set_error() + if ret.__str__() != "www.nic.cz.test.nic.cz.": + set_error() + except: + set_error() + try: + ret = dname.cat_clone(rdf2) + if ret != None: + set_error() + except: + set_error() + try: + ret = dname.cat_clone("") + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".interval()" + dn1 = ldns.ldns_dname("a.ns.nic.cz.") + dn2 = ldns.ldns_dname("b.ns.nic.cz.") + dn3 = ldns.ldns_dname("c.ns.nic.cz.") + try: + ret = dn1.interval(dn2, dn3) + if ret != -1: + set_error() + except: + set_error() + try: + ret = dn2.interval(dn1, dn3) + if ret != 1: + set_error() + except: + set_error() + rdf4 = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "d.ns.nic.cz.") + rdf5 = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_A, "194.0.12.1") + try: + ret = dn1.interval(dn2, rdf4) + if ret != -1: + set_error() + except: + set_error() + try: + ret = dn2.interval(dn1, rdf4) + if ret != 1: + set_error() + except: + set_error() + try: + ret = dn1.interval(dn2, rdf5) + set_error() + except Exception: + pass + except: + set_error() + try: + ret = dn1.interval(dn2, "") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".is_subdomain()" + dn1 = ldns.ldns_dname("nic.cz.") + dn2 = ldns.ldns_dname("www.nic.cz.") + rdf3 = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "www.nic.cz.") + try: + ret = dn1.is_subdomain(dn2) + if not isinstance(ret, bool): + set_error() + if ret == True: + set_error() + ret = dn2.is_subdomain(dn1) + if ret != True: + set_error() + except: + set_error() + try: + ret = dn1.is_subdomain(rdf3) + if not isinstance(ret, bool): + set_error() + if ret == True: + set_error() + except: + set_error() + rdf4 = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_A, "194.0.12.1") + try: + ret = dn1.is_subdomain(rdf4) + if ret != False: + set_error() + except: + set_error() + try: + ret = dn1.is_subdomain("") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".label()" + dn = ldns.ldns_dname("nic.cz.") + try: + ret = dn.label(0) + if not isinstance(ret, ldns.ldns_dname): + set_error() + except: + set_error() + try: + ret = dn.label(10) + if ret != None: + set_error() + except: + set_error() + try: + ret = dn.label("") + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".label_count()" + dn = ldns.ldns_dname("www.nic.cz.") + try: + ret = dn.label_count() + if not isinstance(ret, int): + set_error() + if ret != 3: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".left_chop()" + dn = ldns.ldns_dname("www.nic.cz.") + try: + ret = dn.left_chop() + if not isinstance(ret, ldns.ldns_dname): + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".make_canonical()" + dn = ldns.ldns_dname("WWW.NIC.CZ.") + try: + dn.make_canonical() + if dn.__str__() != "www.nic.cz.": + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".new_frm_rdf()" + # Tested via constructor call. + + +#if not error_detected: +if True: + method_name = class_name + ".new_frm_str()" + # Tested via constructor call. + + +#if not error_detected: +if True: + method_name = class_name + ".reverse()" + dn = ldns.ldns_dname("www.nic.cz.") + try: + ret = dn.reverse() + if not isinstance(ret, ldns.ldns_dname): + set_error() + if ret.__str__() != "cz.nic.www.": + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".write_to_buffer()" + dn = ldns.ldns_dname("www.nic.cz.") + buf = ldns.ldns_buffer(1024) + try: + ret = dn.write_to_buffer(buf) + if ret != ldns.LDNS_STATUS_OK: + set_error() + if buf.position() != 12: + set_error() + except: + set_error() + try: + ret = dn.write_to_buffer("") + except TypeError: + pass + except: + set_error() + + +if not error_detected: + sys.stdout.write("%s: passed.\n" % (os.path.basename(__file__))) +else: + sys.stdout.write("%s: errors detected.\n" % (os.path.basename(__file__))) + sys.exit(1) diff --git a/contrib/python/examples/test_rdf.py b/contrib/python/examples/test_rdf.py new file mode 100755 index 00000000000..4991288c83f --- /dev/null +++ b/contrib/python/examples/test_rdf.py @@ -0,0 +1,805 @@ +#!/usr/bin/env python + +# +# ldns_rdf testing script. +# +# Do not use constructs that differ between Python 2 and 3. +# Use write on stdout or stderr. +# + + +import ldns +import sys +import os +import inspect + + +class_name = "ldns_rdf" +method_name = None +error_detected = False +temp_fname = "tmp_rdf.txt" + + +def set_error(): + """ + Writes an error message and sets error flag. + """ + global class_name + global method_name + global error_detected + error_detected = True + sys.stderr.write("(line %d): malfunctioning method %s.\n" % \ + (inspect.currentframe().f_back.f_lineno, method_name)) + + +#if not error_detected: +if True: + method_name = class_name + ".__init__()" + try: + # Should raise an Exception + rdf = ldns.ldns_rdf() + set_error() + except Exception as e: + pass + + +#if not error_detected: +if True: + method_name = class_name + ".[comparison operators]" + rdf1 = ldns.ldns_rdf.new_frm_str("0.0.0.0", ldns.LDNS_RDF_TYPE_A) + rdf2 = ldns.ldns_rdf.new_frm_str("1.1.1.1", ldns.LDNS_RDF_TYPE_A) + try: + ret = rdf1 < rdf2 + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + try: + ret = rdf2 < rdf1 + if not isinstance(ret, bool): + set_error() + if ret != False: + set_error() + except: + set_error() + try: + ret = rdf1 <= rdf2 + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + try: + ret = rdf2 <= rdf1 + if not isinstance(ret, bool): + set_error() + if ret != False: + set_error() + except: + set_error() + try: + ret = rdf1 == rdf2 + if not isinstance(ret, bool): + set_error() + if ret != False: + set_error() + except: + set_error() + try: + ret = rdf1 == rdf1 + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + try: + ret = rdf1 != rdf2 + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + try: + ret = rdf1 != rdf1 + if not isinstance(ret, bool): + set_error() + if ret != False: + set_error() + except: + set_error() + try: + ret = rdf1 > rdf2 + if not isinstance(ret, bool): + set_error() + if ret != False: + set_error() + except: + set_error() + try: + ret = rdf2 > rdf1 + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + try: + ret = rdf1 >= rdf2 + if not isinstance(ret, bool): + set_error() + if ret != False: + set_error() + except: + set_error() + try: + ret = rdf2 >= rdf1 + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = "ldns_rdf_new()" + sys.stderr.write("%s not tested.\n" % (method_name)) + + +#if not error_detected: +if True: + method_name = "ldns_rdf_new_frm_data()" + sys.stderr.write("%s not tested.\n" % (method_name)) + + +#if not error_detected: +if True: + method_name = "ldns_rdf_new_frm_str()" + try: + rdf = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "www.nic.cz") + except: + set_error() + try: + rdf = ldns.ldns_rdf_new_frm_str("", "www.nic.cz") + et_error() + except TypeError: + pass + except: + set_error() + try: + rdf = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, 1) + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = "ldns_rdf_new_frm_fp()" + f = open(temp_fname, "w") + f.write("217.31.205.50") + f.close() + f = open(temp_fname, "r") + try: + status, rdf = ldns.ldns_rdf_new_frm_fp(ldns.LDNS_RDF_TYPE_A, f) + if status != ldns.LDNS_STATUS_OK: + set_error() + if rdf == None: + set_error() + except: + set_error() + try: + # Reading past file end. + status, rdf = ldns.ldns_rdf_new_frm_fp(ldns.LDNS_RDF_TYPE_AAAA, f) + if status == ldns.LDNS_STATUS_OK: + set_error() + if rdf != None: + set_error() + except: + set_error() + f.close() + f = open(temp_fname, "r") + try: + status, rdf = ldns.ldns_rdf_new_frm_fp(ldns.LDNS_RDF_TYPE_AAAA, f) + if status != ldns.LDNS_STATUS_OK: + set_error() + if rdf != None: + set_error() + except: + set_error() + f.close() + os.remove(temp_fname) + try: + status, rdf = ldns.ldns_rdf_new_frm_fp("", f) + except TypeError: + pass + except: + set_error() + try: + status, rdf = ldns.ldns_rdf_new_frm_fp(ldns.LDNS_RDF_TYPE_AAAA, "") + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = "ldns_rdf_new_frm_fp_l()" + f = open(temp_fname, "w") + f.write("217.31.205.50\n194.0.12.1") + f.close() + f = open(temp_fname, "r") + try: + status, rdf, line = ldns.ldns_rdf_new_frm_fp_l(ldns.LDNS_RDF_TYPE_A, f) + if status != ldns.LDNS_STATUS_OK: + set_error() + if rdf == None: + set_error() + except: + set_error() + try: + status, rdf, line = ldns.ldns_rdf_new_frm_fp_l(ldns.LDNS_RDF_TYPE_A, f) + if status != ldns.LDNS_STATUS_OK: + set_error() + if rdf == None: + set_error() + except: + set_error() + try: + # Reading past file end. + status, rdf, line = ldns.ldns_rdf_new_frm_fp_l(ldns.LDNS_RDF_TYPE_A, f) + if status == ldns.LDNS_STATUS_OK: + set_error() + if rdf != None: + set_error() + except: + set_error() + f.close() + os.remove(temp_fname) + try: + status, rdf = ldns.ldns_rdf_new_frm_fp_l("", f) + except TypeError: + pass + except: + set_error() + try: + status, rdf = ldns.ldns_rdf_new_frm_fp_l(ldns.LDNS_RDF_TYPE_AAAA, "") + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = "ldns_drf.absolute()" + rdf = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "www.nic.cz.") + try: + ret = rdf.absolute() + if not isinstance(ret, bool): + set_error() + if not ret: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = "ldns_rdf.address_reverse()" + rdf = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_A, "194.0.12.1") + try: + ret = rdf.address_reverse() + if ret == None: + set_error() + except: + set_error() + rdf = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_AAAA, "::1") + try: + ret = rdf.address_reverse() + if ret == None: + set_error() + except: + set_error() + rdf = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "www.nic.cz.") + try: + ret = rdf.address_reverse() + if ret != None: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = "ldns_rdf.cat()" + rdf1 = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "www.nic") + rdf2 = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "cz.") + try: + ret = rdf1.cat(rdf2) + if ret != ldns.LDNS_STATUS_OK: + set_error() + except: + set_error() + rdf1 = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "www.nic.") + rdf2 = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_A, "127.0.0.1") + try: + ret = rdf1.cat(rdf2) + if ret == ldns.LDNS_STATUS_OK: + set_error() + except: + set_error() + try: + ret = rdf2.cat(rdf1) + if ret == ldns.LDNS_STATUS_OK: + set_error() + except: + set_error() + try: + ret = rdf2.cat("") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = "ldns_rdf.cat_clone()" + rdf1 = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "www.nic") + rdf2 = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "cz.") + try: + ret = rdf1.cat_clone(rdf2) + if ret == None: + set_error() + except: + set_error() + rdf1 = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "www.nic.") + rdf2 = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_A, "127.0.0.1") + try: + ret = rdf1.cat_clone(rdf2) + if ret != None: + set_error() + except: + set_error() + try: + ret = rdf2.cat_clone(rdf1) + if ret != None: + set_error() + except: + set_error() + try: + ret = rdf2.cat_clone("") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = "ldns_rdf.clone()" + rdf = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "www.nic.cz.") + try: + ret = rdf.clone() + except: + set_error() + + +#if not error_detected: +if True: + method_name = "ldns_rdf.data()" + rdf = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "www.nic.cz.") + try: + ret = rdf.data() + except: + set_error() + + +#if not error_detected: +if True: + method_name = "ldns_rdf.dname_compare()" + rdf1 = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "www.nic.cz.") + rdf2 = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "nic.cz.") + try: + ret = rdf1.dname_compare(rdf2) + if ret != 1: + set_error() + except: + set_error() + try: + ret = rdf2.dname_compare(rdf1) + if ret != -1: + set_error() + except: + set_error() + try: + ret = rdf1.dname_compare(rdf1) + if ret != 0: + set_error() + except: + set_error() + rdf1 = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "www.nic.cz.") + rdf2 = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_A, "127.0.0.1") + try: + ret = rdf1.dname_compare(rdf2) + set_error() + except Exception: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = "ldns_rdf.dname_new_frm_str()" + try: + rdf = ldns.ldns_rdf.dname_new_frm_str("www.nic.cz.") + if rdf == None: + set_error() + except: + set_error() + try: + rdf = ldns.ldns_rdf.dname_new_frm_str("") + if rdf != None: + set_error() + except: + set_error() + try: + rdf = ldns.ldns_rdf.dname_new_frm_str(1) + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = "ldns_rdf.get_type()" + rdf = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "www.nic.cz.") + try: + ret = rdf.get_type() + if not isinstance(ret, int): + set_error() + if ret != ldns.LDNS_RDF_TYPE_DNAME: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = "ldns_rdf.get_type_str()" + rdf = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "www.nic.cz.") + try: + ret = rdf.get_type_str() + if not isinstance(ret, str): + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = "ldns_rdf.interval()" + rdf1 = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "a.ns.nic.cz.") + rdf2 = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "b.ns.nic.cz.") + rdf3 = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "c.ns.nic.cz.") + try: + ret = rdf1.interval(rdf2, rdf3) + if ret != -1: + set_error() + except: + set_error() + try: + ret = rdf2.interval(rdf1, rdf3) + if ret != 1: + set_error() + except: + set_error() + rdf1 = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_A, "194.0.12.1") + rdf2 = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "b.ns.nic.cz.") + rdf3 = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "c.ns.nic.cz.") + try: + ret = rdf1.interval(rdf2, rdf3) + set_error() + except Exception: + pass + except: + set_error() + try: + ret = rdf2.interval("", rdf3) + set_error() + except TypeError: + pass + except: + set_error() + +#if not error_detected: +if True: + method_name = "ldns_rdf.is_subdomain()" + rdf1 = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "nic.cz.") + rdf2 = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "www.nic.cz.") + try: + ret = rdf1.is_subdomain(rdf2) + if not isinstance(ret, bool): + set_error() + if ret == True: + set_error() + ret = rdf2.is_subdomain(rdf1) + if ret != True: + set_error() + except: + set_error() + rdf1 = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_A, "194.0.12.1") + rdf2 = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "www.nic.cz.") + try: + ret = rdf1.is_subdomain(rdf2) + if ret != False: + set_error() + except: + set_error() + try: + ret = rdf2.is_subdomain(rdf1) + if ret != False: + set_error() + except: + set_error() + try: + ret = rdf2.is_subdomain("") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = "ldns_rdf.label()" + rdf = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "www.nic.cz.") + try: + ret = rdf.label(0) + if not isinstance(ret, ldns.ldns_rdf): + set_error() + except: + set_error() + try: + ret = rdf.label(10) + if ret != None: + set_error() + except: + set_error() + try: + ret = rdf.label("") + except TypeError: + pass + except: + set_error() + rdf = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_A, "127.0.0.1") + try: + ret = rdf.label(0) + if ret != None: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = "ldns_rdf.label_count()" + rdf = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "www.nic.cz.") + try: + ret = rdf.label_count() + if not isinstance(ret, int): + set_error() + if ret != 3: + set_error() + except: + set_error() + rdf = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_A, "127.0.0.1") + try: + ret = rdf.label_count() + if not isinstance(ret, int): + set_error() + if ret != 0: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = "ldns_rdf.left_chop()" + rdf = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "www.nic.cz.") + try: + ret = rdf.left_chop() + if not isinstance(ret, ldns.ldns_rdf): + set_error() + except: + set_error() + rdf = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_A, "127.0.0.1") + try: + ret = rdf.left_chop() + if ret != None: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = "ldns_rdf.make_canonical()" + rdf = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "WWW.NIC.CZ.") + try: + rdf.make_canonical() + if rdf.__str__() != "www.nic.cz.": + set_error() + except: + set_error() + rdf = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_A, "127.0.0.1") + try: + rdf.make_canonical() + except: + set_error() + + +#if not error_detected: +if True: + method_name = "ldns_rdf.new_frm_str()" + try: + rdf = ldns.ldns_rdf.new_frm_str("www.nic.cz.", ldns.LDNS_RDF_TYPE_DNAME) + except: + set_error() + try: + rdf = ldns.ldns_rdf.new_frm_str("www.nic.cz.", ldns.LDNS_RDF_TYPE_AAAA) + set_error() + except Exception: + pass + except: + set_error() + try: + rdf = ldns.ldns_rdf.new_frm_str("www.nic.cz.", ldns.LDNS_RDF_TYPE_AAAA, raiseException = False) + if rdf != None: + set_error() + except: + set_error() + try: + rdf = ldns.ldns_rdf.new_frm_str("", "www.nic.cz") + et_error() + except TypeError: + pass + except: + set_error() + try: + rdf = ldns.ldns_rdf.new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, 1) + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + rdf = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_A, "127.0.0.1") + f = open(temp_fname, "w") + try: + rdf.print_to_file(f) + except: + set_error() + f.close() + f = open(temp_fname, "r") + if f.read() != "127.0.0.1": + set_error() + f.close() + os.remove(temp_fname) + + +#if not error_detected: +if True: + rdf = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "www.nic.cz.") + try: + ret = rdf.reverse() + if not isinstance(ret, ldns.ldns_rdf): + set_error() + if ret.__str__() != "cz.nic.www.": + set_error() + except: + set_error() + rdf = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_A, "127.0.0.1") + try: + ret = rdf.reverse() + if not isinstance(ret, ldns.ldns_rdf): + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = "ldns_rdf.set_data()" + sys.stderr.write("%s not tested.\n" % (method_name)) + + +#if not error_detected: +if True: + method_name = "ldns_rdf.set_size()" + sys.stderr.write("%s not tested.\n" % (method_name)) + + +#if not error_detected: +if True: + method_name = "ldns_rdf.set_type()" + sys.stderr.write("%s not tested.\n" % (method_name)) + + +#if not error_detected: +if True: + method_name = "ldns_rdf.size()" + rdf = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "www.nic.cz.") + try: + ret = rdf.size() + if ret != 12: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = "ldns_rdf.write_to_buffer()" + rdf = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "www.nic.cz.") + buf = ldns.ldns_buffer(1024) + try: + ret = rdf.write_to_buffer(buf) + if ret != ldns.LDNS_STATUS_OK: + set_error() + if buf.position() != 12: + set_error() + except: + set_error() + try: + ret = rdf.write_to_buffer("") + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = "ldns_rdf.write_to_buffer_canonical()" + rdf = ldns.ldns_rdf_new_frm_str(ldns.LDNS_RDF_TYPE_DNAME, "WWW.NIC.CZ.") + buf = ldns.ldns_buffer(1024) + try: + ret = rdf.write_to_buffer_canonical(buf) + if ret != ldns.LDNS_STATUS_OK: + set_error() + if buf.position() != 12: + set_error() + except: + set_error() + try: + ret = rdf.write_to_buffer_canonical("") + except TypeError: + pass + except: + set_error() + + +if not error_detected: + sys.stdout.write("%s: passed.\n" % (os.path.basename(__file__))) +else: + sys.stdout.write("%s: errors detected.\n" % (os.path.basename(__file__))) + sys.exit(1) diff --git a/contrib/python/examples/test_rr.py b/contrib/python/examples/test_rr.py new file mode 100644 index 00000000000..b7bc1e0d971 --- /dev/null +++ b/contrib/python/examples/test_rr.py @@ -0,0 +1,2383 @@ +#!/usr/bin/env python + +# +# ldns_rr and ldns_rr_list testing script. +# +# Do not use constructs that differ between Python 2 and 3. +# Use write on stdout or stderr. +# + + +import ldns +import sys +import os +import inspect + + +class_name = "ldns_rr" +method_name = None +error_detected = False +temp_fname = "tmp_rr.txt" + + +def set_error(): + """ + Writes an error message and sets error flag. + """ + global class_name + global method_name + global error_detected + error_detected = True + sys.stderr.write("(line %d): malfunctioning method %s.\n" % \ + (inspect.currentframe().f_back.f_lineno, method_name)) + + + +#if not error_detected: +if True: + method_name = class_name + ".[comparison operators]" + rr1 = ldns.ldns_rr.new_frm_str("test1 600 IN A 0.0.0.0") + rr2 = ldns.ldns_rr.new_frm_str("test2 600 IN A 1.1.1.1") + try: + ret = rr1 < rr2 + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + try: + ret = rr2 < rr1 + if not isinstance(ret, bool): + set_error() + if ret != False: + set_error() + except: + set_error() + try: + ret = rr1 <= rr2 + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + try: + ret = rr2 <= rr1 + if not isinstance(ret, bool): + set_error() + if ret != False: + set_error() + except: + set_error() + try: + ret = rr1 == rr2 + if not isinstance(ret, bool): + set_error() + if ret != False: + set_error() + except: + set_error() + try: + ret = rr1 == rr1 + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + try: + ret = rr1 != rr2 + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + try: + ret = rr1 != rr1 + if not isinstance(ret, bool): + set_error() + if ret != False: + set_error() + except: + set_error() + try: + ret = rr1 > rr2 + if not isinstance(ret, bool): + set_error() + if ret != False: + set_error() + except: + set_error() + try: + ret = rr2 > rr1 + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + try: + ret = rr1 >= rr2 + if not isinstance(ret, bool): + set_error() + if ret != False: + set_error() + except: + set_error() + try: + ret = rr2 >= rr1 + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + "__init__()" + try: + rr = ldns.ldns_rr() + set_error() + except Exception: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".a_address()" + rr = ldns.ldns_rr.new_frm_str("www.nic.cz 600 IN A 217.31.205.50") + try: + address = rr.a_address() + if not isinstance(address, ldns.ldns_rdf): + set_error() + if address == None: + set_error() + except: + set_error() + rr = ldns.ldns_rr.new_frm_str("www.nic.cz 600 IN AAAA 2002:d91f:cd32::1") + try: + address = rr.a_address() + if not isinstance(address, ldns.ldns_rdf): + set_error() + if address == None: + set_error() + except: + set_error() + rr = ldns.ldns_rr.new_frm_str("www.nic.cz 600 IN TXT text") + try: + address = rr.a_address() + if isinstance(address, ldns.ldns_rdf): + set_error() + if address != None: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".a_set_address()" + rdf = ldns.ldns_rdf.new_frm_str("127.0.0.1", ldns.LDNS_RDF_TYPE_A) + rr = ldns.ldns_rr.new_frm_str("test 600 IN A 0.0.0.0") + try: + ret = rr.a_set_address(rdf) + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + rdf = ldns.ldns_rdf.new_frm_str("::1", ldns.LDNS_RDF_TYPE_AAAA) + rr = ldns.ldns_rr.new_frm_str("test 600 IN AAAA ::") + try: + ret = rr.a_set_address(rdf) + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + try: + ret = rr.a_set_address("") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".class_by_name()" + try: + ret = ldns.ldns_rr.class_by_name("IN") + if not isinstance(ret, int): + set_error() + if ret != ldns.LDNS_RR_CLASS_IN: + set_error() + except: + set_error() + method_name = class_name + ".class_by_name()" + try: + ret = ldns.ldns_rr.class_by_name("AA") + if not isinstance(ret, int): + set_error() + if ret != 0: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".clone()" + rr = ldns.ldns_rr.new_frm_str("test 600 IN TXT text") + try: + ret = rr.clone() + if not isinstance(ret, ldns.ldns_rr): + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".compare_ds()" + pubkey1 = ldns.ldns_rr.new_frm_str("example1. 3600 IN DNSKEY 256 3 3 APw7tG8Nf7MYXjt2Y6DmyWUVxVy73bRKvKbKoGXhAXJx2vbcGGxfXsScT0i4FIC2wsJ/8zy/otB5vymm3JHBf2+7cQvRdp12UMLAnzlfrbgZUpvV36D+q6ch7kbmFzaBfwRjOKhnZkRLCcMYPAdX1SrgKVNXaOzAl9KytbzGQs5MKEHU+a0PAwKfIvEsS/+pW6gKgBnL0uy4Gr5cYJ5rk48iwFXOlZ/B30gUS5dD+rNRJuR0ZgEkxtVIPVxxhQPtEI53JhlJ2nEy0CqNW88nYLmX402b ;{id = 34898 (zsk), size = 512b}") + pubkey2 = ldns.ldns_rr.new_frm_str("example2. 3600 IN DNSKEY 256 3 3 ALBoD2+1xYpzrE7gjU5EwwBHG2HNiD1977LDZGh+8VNifMGjixMpgUN6xRhFjvRSsC/seMVXmUGq+msUDF2pHnUHbW/dbQbBxVMAqx2jT0LTvAx5wUPGltHHsa92K8VdzD8ynTFwPvjmk7g3hqRRzt4UTQIeK7DYgrOOgvDv+DYWVQctLwYP0ktm85b4cMtIUNRIf/N+K25pfK6BM/tHN8HOm4ECvm2U9zqHHfnxJFdiNK2PydkNeJZZGUOubSFVvaOMhZoEeAgkm3q5QcwXHsLAhacZ ;{id = 30944 (zsk), size = 512b}") + ds1 = ldns.ldns_key_rr2ds(pubkey1, ldns.LDNS_SHA1) + ds2 = ldns.ldns_key_rr2ds(pubkey2, ldns.LDNS_SHA1) + try: + ret = pubkey1.compare_ds(pubkey1) + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + try: + ret = pubkey1.compare_ds(pubkey2) + if not isinstance(ret, bool): + set_error() + if ret != False: + set_error() + except: + set_error() + try: + ret = pubkey1.compare_ds(ds1) + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + try: + ret = pubkey1.compare_ds(ds2) + if not isinstance(ret, bool): + set_error() + if ret != False: + set_error() + except: + set_error() + try: + pubkey1.compare_ds("") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".compare_no_rdata()" + rr1 = ldns.ldns_rr.new_frm_str("test 600 IN A 0.0.0.0") + rr2 = ldns.ldns_rr.new_frm_str("test 600 IN AAAA ::") + try: + ret = rr1.compare_no_rdata(rr2) + if not isinstance(ret, int): + set_error() + if ret != -27: + set_error() + except: + set_error() + try: + rr1.compare_no_rdata("") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".dnskey_algorithm()" + pubkey = ldns.ldns_rr.new_frm_str("example1. 3600 IN DNSKEY 256 3 3 APw7tG8Nf7MYXjt2Y6DmyWUVxVy73bRKvKbKoGXhAXJx2vbcGGxfXsScT0i4FIC2wsJ/8zy/otB5vymm3JHBf2+7cQvRdp12UMLAnzlfrbgZUpvV36D+q6ch7kbmFzaBfwRjOKhnZkRLCcMYPAdX1SrgKVNXaOzAl9KytbzGQs5MKEHU+a0PAwKfIvEsS/+pW6gKgBnL0uy4Gr5cYJ5rk48iwFXOlZ/B30gUS5dD+rNRJuR0ZgEkxtVIPVxxhQPtEI53JhlJ2nEy0CqNW88nYLmX402b ;{id = 34898 (zsk), size = 512b}") + try: + ret = pubkey.dnskey_algorithm() + if not isinstance(ret, ldns.ldns_rdf): + set_error() + except: + set_error() + rr = ldns.ldns_rr.new_frm_str("test 600 IN A 0.0.0.0") + try: + ret = rr.dnskey_algorithm() + if isinstance(ret, ldns.ldns_rdf): + set_error() + if ret != None: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".dnskey_flags()" + pubkey = ldns.ldns_rr.new_frm_str("example1. 3600 IN DNSKEY 256 3 3 APw7tG8Nf7MYXjt2Y6DmyWUVxVy73bRKvKbKoGXhAXJx2vbcGGxfXsScT0i4FIC2wsJ/8zy/otB5vymm3JHBf2+7cQvRdp12UMLAnzlfrbgZUpvV36D+q6ch7kbmFzaBfwRjOKhnZkRLCcMYPAdX1SrgKVNXaOzAl9KytbzGQs5MKEHU+a0PAwKfIvEsS/+pW6gKgBnL0uy4Gr5cYJ5rk48iwFXOlZ/B30gUS5dD+rNRJuR0ZgEkxtVIPVxxhQPtEI53JhlJ2nEy0CqNW88nYLmX402b ;{id = 34898 (zsk), size = 512b}") + try: + ret = pubkey.dnskey_flags() + if not isinstance(ret, ldns.ldns_rdf): + set_error() + except: + set_error() + rr = ldns.ldns_rr.new_frm_str("test 600 IN A 0.0.0.0") + try: + ret = rr.dnskey_flags() + if isinstance(ret, ldns.ldns_rdf): + set_error() + if ret != None: + set_error() + except: + set_errror() + + +#if not error_detected: +if True: + method_name = class_name + ".dnskey_key()" + pubkey = ldns.ldns_rr.new_frm_str("example1. 3600 IN DNSKEY 256 3 3 APw7tG8Nf7MYXjt2Y6DmyWUVxVy73bRKvKbKoGXhAXJx2vbcGGxfXsScT0i4FIC2wsJ/8zy/otB5vymm3JHBf2+7cQvRdp12UMLAnzlfrbgZUpvV36D+q6ch7kbmFzaBfwRjOKhnZkRLCcMYPAdX1SrgKVNXaOzAl9KytbzGQs5MKEHU+a0PAwKfIvEsS/+pW6gKgBnL0uy4Gr5cYJ5rk48iwFXOlZ/B30gUS5dD+rNRJuR0ZgEkxtVIPVxxhQPtEI53JhlJ2nEy0CqNW88nYLmX402b ;{id = 34898 (zsk), size = 512b}") + try: + ret = pubkey.dnskey_key() + if not isinstance(ret, ldns.ldns_rdf): + set_error() + except: + set_error() + rr = ldns.ldns_rr.new_frm_str("test 600 IN A 0.0.0.0") + try: + ret = rr.dnskey_key() + if isinstance(ret, ldns.ldns_rdf): + set_error() + if ret != None: + set_error() + except: + set_errror() + + +#if not error_detected: +if True: + method_name = class_name + ".dnskey_key_size()" + pubkey = ldns.ldns_rr.new_frm_str("example1. 3600 IN DNSKEY 256 3 3 APw7tG8Nf7MYXjt2Y6DmyWUVxVy73bRKvKbKoGXhAXJx2vbcGGxfXsScT0i4FIC2wsJ/8zy/otB5vymm3JHBf2+7cQvRdp12UMLAnzlfrbgZUpvV36D+q6ch7kbmFzaBfwRjOKhnZkRLCcMYPAdX1SrgKVNXaOzAl9KytbzGQs5MKEHU+a0PAwKfIvEsS/+pW6gKgBnL0uy4Gr5cYJ5rk48iwFXOlZ/B30gUS5dD+rNRJuR0ZgEkxtVIPVxxhQPtEI53JhlJ2nEy0CqNW88nYLmX402b ;{id = 34898 (zsk), size = 512b}") + try: + ret = pubkey.dnskey_key_size() + if not isinstance(ret, int): + set_error() + if ret != 512: + set_error() + except: + set_error() + rr = ldns.ldns_rr.new_frm_str("test 600 IN A 0.0.0.0") + try: + ret = rr.dnskey_key_size() + if not isinstance(ret, int): + set_error() + if ret != 0: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".dnskey_key_size_raw()" + sys.stderr.write("%s not tested.\n" % (method_name)) + + +#if not error_detected: +if True: + method_name = class_name + ".dnskey_protocol()" + pubkey = ldns.ldns_rr.new_frm_str("example1. 3600 IN DNSKEY 256 3 3 APw7tG8Nf7MYXjt2Y6DmyWUVxVy73bRKvKbKoGXhAXJx2vbcGGxfXsScT0i4FIC2wsJ/8zy/otB5vymm3JHBf2+7cQvRdp12UMLAnzlfrbgZUpvV36D+q6ch7kbmFzaBfwRjOKhnZkRLCcMYPAdX1SrgKVNXaOzAl9KytbzGQs5MKEHU+a0PAwKfIvEsS/+pW6gKgBnL0uy4Gr5cYJ5rk48iwFXOlZ/B30gUS5dD+rNRJuR0ZgEkxtVIPVxxhQPtEI53JhlJ2nEy0CqNW88nYLmX402b ;{id = 34898 (zsk), size = 512b}") + try: + ret = pubkey.dnskey_protocol() + if not isinstance(ret, ldns.ldns_rdf): + set_error() + except: + set_error() + rr = ldns.ldns_rr.new_frm_str("test 600 IN A 0.0.0.0") + try: + ret = rr.dnskey_protocol() + if isinstance(ret, ldns.ldns_rdf): + set_error() + if ret != None: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".dnskey_set_algorithm()" + pubkey = ldns.ldns_rr.new_frm_str("example1. 3600 IN DNSKEY 256 3 3 APw7tG8Nf7MYXjt2Y6DmyWUVxVy73bRKvKbKoGXhAXJx2vbcGGxfXsScT0i4FIC2wsJ/8zy/otB5vymm3JHBf2+7cQvRdp12UMLAnzlfrbgZUpvV36D+q6ch7kbmFzaBfwRjOKhnZkRLCcMYPAdX1SrgKVNXaOzAl9KytbzGQs5MKEHU+a0PAwKfIvEsS/+pW6gKgBnL0uy4Gr5cYJ5rk48iwFXOlZ/B30gUS5dD+rNRJuR0ZgEkxtVIPVxxhQPtEI53JhlJ2nEy0CqNW88nYLmX402b ;{id = 34898 (zsk), size = 512b}") + rdf = ldns.ldns_rdf.new_frm_str("3", ldns.LDNS_RDF_TYPE_ALG) + try: + ret = pubkey.dnskey_set_algorithm(rdf) + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() +# rdf = ldns.ldns_rdf.new_frm_str("0.0.0.0", ldns.LDNS_RDF_TYPE_A) +# try: +# ret = pubkey.dnskey_set_algorithm(rdf) +# if not isinstance(ret, bool): +# set_error() +# if ret != False: +# set_error() +# except: +# set_error() + try: + ret = pubkey.dnskey_set_algorithm("") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".dnskey_set_flags()" + pubkey = ldns.ldns_rr.new_frm_str("example1. 3600 IN DNSKEY 256 3 3 APw7tG8Nf7MYXjt2Y6DmyWUVxVy73bRKvKbKoGXhAXJx2vbcGGxfXsScT0i4FIC2wsJ/8zy/otB5vymm3JHBf2+7cQvRdp12UMLAnzlfrbgZUpvV36D+q6ch7kbmFzaBfwRjOKhnZkRLCcMYPAdX1SrgKVNXaOzAl9KytbzGQs5MKEHU+a0PAwKfIvEsS/+pW6gKgBnL0uy4Gr5cYJ5rk48iwFXOlZ/B30gUS5dD+rNRJuR0ZgEkxtVIPVxxhQPtEI53JhlJ2nEy0CqNW88nYLmX402b ;{id = 34898 (zsk), size = 512b}") + rdf = ldns.ldns_rdf.new_frm_str("256", ldns.LDNS_RDF_TYPE_INT16) + try: + ret = pubkey.dnskey_set_flags(rdf) + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() +# rdf = ldns.ldns_rdf.new_frm_str("0.0.0.0", ldns.LDNS_RDF_TYPE_A) +# try: +# ret = pubkey.dnskey_set_flags(rdf) +# if not isinstance(ret, bool): +# set_error() +# if ret != False: +# set_error() +# except: +# set_error() + try: + ret = pubkey.dnskey_set_flags("") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".dnskey_set_key()" + pubkey = ldns.ldns_rr.new_frm_str("example1. 3600 IN DNSKEY 256 3 3 APw7tG8Nf7MYXjt2Y6DmyWUVxVy73bRKvKbKoGXhAXJx2vbcGGxfXsScT0i4FIC2wsJ/8zy/otB5vymm3JHBf2+7cQvRdp12UMLAnzlfrbgZUpvV36D+q6ch7kbmFzaBfwRjOKhnZkRLCcMYPAdX1SrgKVNXaOzAl9KytbzGQs5MKEHU+a0PAwKfIvEsS/+pW6gKgBnL0uy4Gr5cYJ5rk48iwFXOlZ/B30gUS5dD+rNRJuR0ZgEkxtVIPVxxhQPtEI53JhlJ2nEy0CqNW88nYLmX402b ;{id = 34898 (zsk), size = 512b}") + rdf = ldns.ldns_rdf.new_frm_str("AMLdYflByPu1GEPCnu9qPTqbnC8n5mftFmFVTFQI10aefiDqp5DLpjBdTxdmz/GACMZh1+YG/iLj0QYX7qRVIl0rR00iREozqj44YwUILHo3cASSRSeAzyidvlGT8QSMKOlOsD33ygtETpzW0XDmzWhyU3bv0O7lnGpbtqdzP/nsZDbdtf5XI0YBdi91HftqtQpIlMtCg+zIzATO4+QWGt0oDX/+jdB7Y/vBahxnz13stNYeGYslGBSZNgpB7HBKlTwB70sprZ8XmNGhj/NixqB6Bzae", ldns.LDNS_RDF_TYPE_B64) + try: + ret = pubkey.dnskey_set_key(rdf) + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() +# rdf = ldns.ldns_rdf.new_frm_str("0.0.0.0", ldns.LDNS_RDF_TYPE_A) +# try: +# ret = pubkey.dnskey_set_key(rdf) +# if not isinstance(ret, bool): +# set_error() +# if ret != False: +# set_error() +# except: +# set_error() + try: + ret = pubkey.dnskey_set_key("") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".dnskey_set_protocol()" + pubkey = ldns.ldns_rr.new_frm_str("example1. 3600 IN DNSKEY 256 3 3 APw7tG8Nf7MYXjt2Y6DmyWUVxVy73bRKvKbKoGXhAXJx2vbcGGxfXsScT0i4FIC2wsJ/8zy/otB5vymm3JHBf2+7cQvRdp12UMLAnzlfrbgZUpvV36D+q6ch7kbmFzaBfwRjOKhnZkRLCcMYPAdX1SrgKVNXaOzAl9KytbzGQs5MKEHU+a0PAwKfIvEsS/+pW6gKgBnL0uy4Gr5cYJ5rk48iwFXOlZ/B30gUS5dD+rNRJuR0ZgEkxtVIPVxxhQPtEI53JhlJ2nEy0CqNW88nYLmX402b ;{id = 34898 (zsk), size = 512b}") + rdf = ldns.ldns_rdf.new_frm_str("3", ldns.LDNS_RDF_TYPE_INT8) + try: + ret = pubkey.dnskey_set_protocol(rdf) + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() +# rdf = ldns.ldns_rdf.new_frm_str("0.0.0.0", ldns.LDNS_RDF_TYPE_A) +# try: +# ret = pubkey.dnskey_set_protocol(rdf) +# if not isinstance(ret, bool): +# set_error() +# if ret != False: +# set_error() +# except: +# set_error() + try: + ret = pubkey.dnskey_set_protocol("") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".get_class()" + rr = ldns.ldns_rr.new_frm_str("test IN A 0.0.0.0", 600) + try: + ret = rr.get_class() + if not isinstance(ret, int): + set_error() + if ret != ldns.LDNS_RR_CLASS_IN: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".get_class_str()" + rr = ldns.ldns_rr.new_frm_str("test CH A 0.0.0.0", 600) + try: + ret = rr.get_class_str() + if not isinstance(ret, str): + set_error() + if ret != "CH": + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".get_type()" + rr = ldns.ldns_rr.new_frm_str("test IN A 0.0.0.0", 600) + try: + ret = rr.get_type() + if not isinstance(ret, int): + set_error() + if ret != 1: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".get_type_str()" + rr = ldns.ldns_rr.new_frm_str("test IN A 0.0.0.0", 600) + try: + ret = rr.get_type_str() + if not isinstance(ret, str): + set_error() + if ret != "A": + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".is_question()" + rr = ldns.ldns_rr.new_frm_str("test IN A 0.0.0.0", 600) + try: + ret = rr.is_question() + if not isinstance(ret, bool): + set_error() + if ret != False: + set_error() + except: + set_error() + rr.set_question(True) + try: + ret = rr.is_question() + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".label_count()" + rr = ldns.ldns_rr.new_frm_str("test.dom. IN A 0.0.0.0", 600) + try: + ret = rr.label_count() + if not isinstance(ret, int): + set_error() + if ret != 2: + set_error() + except: + set_error() + rr = ldns.ldns_rr.new_frm_str(". IN A 0.0.0.0", 600) + try: + ret = rr.label_count() + if not isinstance(ret, int): + set_error(string) + if ret != 0: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".mx_exchange()" + rr = ldns.ldns_rr.new_frm_str("nic.cz. IN MX 15 mail4.nic.cz.", 600) + try: + ret = rr.mx_exchange() + if not isinstance(ret, ldns.ldns_rdf): + set_error() + except: + set_error() + rr = ldns.ldns_rr.new_frm_str("test 600 IN A 0.0.0.0") + try: + ret = rr.mx_exchange() + if isinstance(ret, ldns.ldns_rdf): + set_error() + if ret != None: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".mx_preference()" + rr = ldns.ldns_rr.new_frm_str("nic.cz. IN MX 15 mail4.nic.cz.", 600) + try: + ret = rr.mx_preference() + if not isinstance(ret, ldns.ldns_rdf): + set_error() + except: + set_error() + rr = ldns.ldns_rr.new_frm_str("test 600 IN A 0.0.0.0") + try: + ret = rr.mx_preference() + if isinstance(ret, ldns.ldns_rdf): + set_error() + if ret != None: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".new_frm_fp()" + f = open(temp_fname, "w") + f.write("test 600 IN A 0.0.0.0") + f.close() + f = open(temp_fname, "r") + rr, ttl, origin, prev = ldns.ldns_rr.new_frm_fp(f, + origin=ldns.ldns_dname("nic.cz")) + try: + # Reading past file end. + ret = ldns.ldns_rr.new_frm_fp(f, raiseException=False) + if ret != None: + set_error() + except: + set_error() + try: + # Reading past file end. + rr, ttl, origin, prev = ldns.ldns_rr.new_frm_fp(f) + set_error() + except Exception: + pass + except: + set_error() + f.close() + os.remove(temp_fname) + + +#if not error_detected: +if True: + method_name = class_name + ".new_frm_fp_l()" + f = open(temp_fname, "w") + f.write("test 600 IN A 0.0.0.0") + f.close() + f = open(temp_fname, "r") + rr, line, ttl, origin, prev = ldns.ldns_rr.new_frm_fp_l(f, + origin=ldns.ldns_dname("nic.cz")) + try: + # Reading past file end. + ret = ldns.ldns_rr.new_frm_fp_l(f, raiseException=False) + if ret != None: + set_error() + except: + set_error() + try: + # Reading past file end. + rr, ttl, origin, prev = ldns.ldns_rr.new_frm_fp_l(f) + set_error() + except Exception: + pass + except: + set_error() + f.close() + os.remove(temp_fname) + + +#if not error_detected: +if True: + method_name = class_name + ".new_frm_str()" + try: + rr = ldns.ldns_rr.new_frm_str("test IN A 0.0.0.0", 600, + origin=ldns.ldns_dname("nic.cz")) + if not isinstance(rr, ldns.ldns_rr): + set_error() + except: + set_error() + try: + rr = ldns.ldns_rr.new_frm_str(10) + set_error() + except TypeError: + pass + except: + set_error() + try: + rr = ldns.ldns_rr.new_frm_str("") + set_error() + except Exception: + pass + except: + set_error() + try: + rr = ldns.ldns_rr.new_frm_str("", raiseException=False) + if rr != None: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".new_frm_str_prev()" + try: + rr, prev = ldns.ldns_rr.new_frm_str_prev("test IN A 0.0.0.0", 600, + origin=ldns.ldns_dname("nic.cz")) + if not isinstance(rr, ldns.ldns_rr): + set_error() +# if prev != None: +# set_error() + except: + set_error() + try: + rr = ldns.ldns_rr.new_frm_str_prev(10) + set_error() + except TypeError: + pass + except: + set_error() + try: + rr = ldns.ldns_rr.new_frm_str_prev("") + set_error() + except Exception: + pass + except: + set_error() + try: + rr = ldns.ldns_rr.new_frm_str_prev("", raiseException=False) + if rr != None: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".new_question_frm_str()" + try: + rr = ldns.ldns_rr.new_question_frm_str("test IN A", 600, + origin=ldns.ldns_dname("nic.cz")) + if not isinstance(rr, ldns.ldns_rr): + set_error() + except: + set_error() + try: + rr = ldns.ldns_rr.new_question_frm_str(10) + set_error() + except TypeError: + pass + except: + set_error() + try: + rr = ldns.ldns_rr.new_question_frm_str("") + set_error() + except Exception: + pass + except: + set_error() + try: + rr = ldns.ldns_rr.new_question_frm_str("", raiseException=False) + if rr != None: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".ns_nsdname()" + rr = ldns.ldns_rr.new_frm_str("nic.cz. 1800 IN NS a.ns.nic.cz.") + try: + ret = rr.ns_nsdname() + if not isinstance(ret, ldns.ldns_rdf): + set_error() + except: + set_error() + rr = ldns.ldns_rr.new_frm_str("test 600 IN A 0.0.0.0") + try: + ret = rr.ns_nsdname() + if isinstance(ret, ldns.ldns_rdf): + set_error() + if ret != None: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".owner()" + rr = ldns.ldns_rr.new_frm_str("nic.cz. 1800 IN NS a.ns.nic.cz.") + try: + ret = rr.owner() + if not isinstance(ret, ldns.ldns_dname): + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".pop_rdf()" + rr = ldns.ldns_rr.new_frm_str("test 600 IN A 0.0.0.0") + try: + ret = rr.pop_rdf() + if not isinstance(ret, ldns.ldns_rdf): + set_error() + if ret.get_type() != ldns.LDNS_RDF_TYPE_A: + set_error() + except: + set_error() + try: + ret = rr.pop_rdf() + if isinstance(ret, ldns.ldns_rdf): + set_error() + if ret != None: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".print_to_file()" + rr = ldns.ldns_rr.new_frm_str("test 600 IN A 0.0.0.0") + f = open(temp_fname, "w") + try: + rr.print_to_file(f) + except: + set_error() + f.close() + f = open(temp_fname, "r") + if not f.readline(): + set_error() + f.close() + os.remove(temp_fname) + + +#if not error_detected: +if True: + method_name = class_name + ".push_rdf()" + rr = ldns.ldns_rr.new_frm_str("test 600 IN A 0.0.0.0") + rdf = ldns.ldns_rdf.new_frm_str("1.1.1.1", ldns.LDNS_RDF_TYPE_A) + try: + ret = rr.push_rdf(rdf) + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + try: + ret = rr.push_rdf("") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".rd_count()" + rr = ldns.ldns_rr.new_frm_str("test 600 IN A 0.0.0.0") + try: + ret = rr.rd_count() + if not isinstance(ret, int): + set_error() + if ret != 1: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".rdf()" + rr = ldns.ldns_rr.new_frm_str("test 600 IN A 0.0.0.0") + try: + ret = rr.rdf(0) + if not isinstance(ret, ldns.ldns_rdf): + set_error() + except: + set_error() + try: + ret = rr.rdf(1) + if isinstance(ret, ldns.ldns_rdf): + set_error() + if ret != None: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".rdfs()" + rr = ldns.ldns_rr.new_frm_str("test 600 IN A 0.0.0.0") + try: + ret = rr.rdfs() + if len(list(ret)) != 1: + set_error() + except: + set_error() + + + +#if not error_detected: +if True: + method_name = class_name + ".rrsig_algorithm()" + rr = ldns.ldns_rr.new_frm_str("example. 600 IN RRSIG SOA 3 1 600 20130828153754 20120828153754 19031 example. AIoCFhwZJxIgYOBEyo3cxxWFZEsUPqkxnt38xEl1cFAHHC9iQN9mlEg=") + try: + ret = rr.rrsig_algorithm() + if not isinstance(ret, ldns.ldns_rdf): + set_error() + except: + set_error() + rr = ldns.ldns_rr.new_frm_str("test 600 IN A 0.0.0.0") + try: + ret = rr.rrsig_algorithm() + if isinstance(ret, ldns.ldns_rdf): + set_error() + if ret != None: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".rrsig_expiration()" + rr = ldns.ldns_rr.new_frm_str("example. 600 IN RRSIG SOA 3 1 600 20130828153754 20120828153754 19031 example. AIoCFhwZJxIgYOBEyo3cxxWFZEsUPqkxnt38xEl1cFAHHC9iQN9mlEg=") + try: + ret = rr.rrsig_expiration() + if not isinstance(ret, ldns.ldns_rdf): + set_error() + except: + set_error() + rr = ldns.ldns_rr.new_frm_str("test 600 IN A 0.0.0.0") + try: + ret = rr.rrsig_expiration() + if isinstance(ret, ldns.ldns_rdf): + set_error() + if ret != None: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".rrsig_inception()" + rr = ldns.ldns_rr.new_frm_str("example. 600 IN RRSIG SOA 3 1 600 20130828153754 20120828153754 19031 example. AIoCFhwZJxIgYOBEyo3cxxWFZEsUPqkxnt38xEl1cFAHHC9iQN9mlEg=") + try: + ret = rr.rrsig_inception() + if not isinstance(ret, ldns.ldns_rdf): + set_error() + except: + set_error() + rr = ldns.ldns_rr.new_frm_str("test 600 IN A 0.0.0.0") + try: + ret = rr.rrsig_inception() + if isinstance(ret, ldns.ldns_rdf): + set_error() + if ret != None: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".rrsig_keytag()" + rr = ldns.ldns_rr.new_frm_str("example. 600 IN RRSIG SOA 3 1 600 20130828153754 20120828153754 19031 example. AIoCFhwZJxIgYOBEyo3cxxWFZEsUPqkxnt38xEl1cFAHHC9iQN9mlEg=") + try: + ret = rr.rrsig_keytag() + if not isinstance(ret, ldns.ldns_rdf): + set_error() + except: + set_error() + rr = ldns.ldns_rr.new_frm_str("test 600 IN A 0.0.0.0") + try: + ret = rr.rrsig_keytag() + if isinstance(ret, ldns.ldns_rdf): + set_error() + if ret != None: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".rrsig_labels()" + rr = ldns.ldns_rr.new_frm_str("example. 600 IN RRSIG SOA 3 1 600 20130828153754 20120828153754 19031 example. AIoCFhwZJxIgYOBEyo3cxxWFZEsUPqkxnt38xEl1cFAHHC9iQN9mlEg=") + try: + ret = rr.rrsig_labels() + if not isinstance(ret, ldns.ldns_rdf): + set_error() + except: + set_error() + rr = ldns.ldns_rr.new_frm_str("test 600 IN A 0.0.0.0") + try: + ret = rr.rrsig_labels() + if isinstance(ret, ldns.ldns_rdf): + set_error() + if ret != None: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".rrsig_origttl()" + rr = ldns.ldns_rr.new_frm_str("example. 600 IN RRSIG SOA 3 1 600 20130828153754 20120828153754 19031 example. AIoCFhwZJxIgYOBEyo3cxxWFZEsUPqkxnt38xEl1cFAHHC9iQN9mlEg=") + try: + ret = rr.rrsig_origttl() + if not isinstance(ret, ldns.ldns_rdf): + set_error() + except: + set_error() + rr = ldns.ldns_rr.new_frm_str("test 600 IN A 0.0.0.0") + try: + ret = rr.rrsig_origttl() + if isinstance(ret, ldns.ldns_rdf): + set_error() + if ret != None: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".rrsig_set_algorithm()" + rr = ldns.ldns_rr.new_frm_str("example. 600 IN RRSIG SOA 3 1 600 20130828153754 20120828153754 19031 example. AIoCFhwZJxIgYOBEyo3cxxWFZEsUPqkxnt38xEl1cFAHHC9iQN9mlEg=") + rdf = ldns.ldns_rdf.new_frm_str("3", ldns.LDNS_RDF_TYPE_ALG) + try: + ret = rr.rrsig_set_algorithm(rdf) + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() +# rdf = ldns.ldns_rdf.new_frm_str("0.0.0.0", ldns.LDNS_RDF_TYPE_A) +# try: +# ret = rr.rrsig_set_algorithm(rdf) +# if not isinstance(ret, bool): +# set_error() +# if ret != False: +# set_error() +# except: +# set_error() + try: + ret = rr.rrsig_set_algorithm("") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".rrsig_set_expiration()" + rr = ldns.ldns_rr.new_frm_str("example. 600 IN RRSIG SOA 3 1 600 20130828153754 20120828153754 19031 example. AIoCFhwZJxIgYOBEyo3cxxWFZEsUPqkxnt38xEl1cFAHHC9iQN9mlEg=") + rdf = ldns.ldns_rdf.new_frm_str("20130928153754", ldns.LDNS_RDF_TYPE_TIME) + try: + ret = rr.rrsig_set_expiration(rdf) + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() +# rdf = ldns.ldns_rdf.new_frm_str("0.0.0.0", ldns.LDNS_RDF_TYPE_A) +# try: +# ret = rr.rrsig_set_expiration(rdf) +# if not isinstance(ret, bool): +# set_error() +# if ret != False: +# set_error() +# except: +# set_error() + try: + ret = rr.rrsig_set_expiration("") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".rrsig_set_inception()" + rr = ldns.ldns_rr.new_frm_str("example. 600 IN RRSIG SOA 3 1 600 20130828153754 20120828153754 19031 example. AIoCFhwZJxIgYOBEyo3cxxWFZEsUPqkxnt38xEl1cFAHHC9iQN9mlEg=") + rdf = ldns.ldns_rdf.new_frm_str("20120728153754", ldns.LDNS_RDF_TYPE_TIME) + try: + ret = rr.rrsig_set_inception(rdf) + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() +# rdf = ldns.ldns_rdf.new_frm_str("0.0.0.0", ldns.LDNS_RDF_TYPE_A) +# try: +# ret = rr.rrsig_set_inception(rdf) +# if not isinstance(ret, bool): +# set_error() +# if ret != False: +# set_error() +# except: +# set_error() + try: + ret = rr.rrsig_set_inception("") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".rrsig_set_keytag()" + rr = ldns.ldns_rr.new_frm_str("example. 600 IN RRSIG SOA 3 1 600 20130828153754 20120828153754 19031 example. AIoCFhwZJxIgYOBEyo3cxxWFZEsUPqkxnt38xEl1cFAHHC9iQN9mlEg=") + rdf = ldns.ldns_rdf.new_frm_str("19032", ldns.LDNS_RDF_TYPE_INT16) + try: + ret = rr.rrsig_set_keytag(rdf) + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() +# rdf = ldns.ldns_rdf.new_frm_str("0.0.0.0", ldns.LDNS_RDF_TYPE_A) +# try: +# ret = rr.rrsig_set_keytag(rdf) +# if not isinstance(ret, bool): +# set_error() +# if ret != False: +# set_error() +# except: +# set_error() + try: + ret = rr.rrsig_set_keytag("") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".rrsig_set_labels()" + rr = ldns.ldns_rr.new_frm_str("example. 600 IN RRSIG SOA 3 1 600 20130828153754 20120828153754 19031 example. AIoCFhwZJxIgYOBEyo3cxxWFZEsUPqkxnt38xEl1cFAHHC9iQN9mlEg=") + rdf = ldns.ldns_rdf.new_frm_str("1", ldns.LDNS_RDF_TYPE_INT8) + try: + ret = rr.rrsig_set_labels(rdf) + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() +# rdf = ldns.ldns_rdf.new_frm_str("0.0.0.0", ldns.LDNS_RDF_TYPE_A) +# try: +# ret = rr.rrsig_set_labels(rdf) +# if not isinstance(ret, bool): +# set_error() +# if ret != False: +# set_error() +# except: +# set_error() + try: + ret = rr.rrsig_set_labels("") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".rrsig_set_origttl()" + rr = ldns.ldns_rr.new_frm_str("example. 600 IN RRSIG SOA 3 1 600 20130828153754 20120828153754 19031 example. AIoCFhwZJxIgYOBEyo3cxxWFZEsUPqkxnt38xEl1cFAHHC9iQN9mlEg=") + rdf = ldns.ldns_rdf.new_frm_str("1", ldns.LDNS_RDF_TYPE_INT8) + try: + ret = rr.rrsig_set_origttl(rdf) + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() +# rdf = ldns.ldns_rdf.new_frm_str("0.0.0.0", ldns.LDNS_RDF_TYPE_A) +# try: +# ret = rr.rrsig_set_origttl(rdf) +# if not isinstance(ret, bool): +# set_error() +# if ret != False: +# set_error() +# except: +# set_error() + try: + ret = rr.rrsig_set_origttl("") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".rrsig_set_sig()" + rr = ldns.ldns_rr.new_frm_str("example. 600 IN RRSIG SOA 3 1 600 20130828153754 20120828153754 19031 example. AIoCFhwZJxIgYOBEyo3cxxWFZEsUPqkxnt38xEl1cFAHHC9iQN9mlEg=") + rdf = ldns.ldns_rdf.new_frm_str("AIoCFhwZJxIgYOBEyo3cxxWFZEsUPqkxnt38xEl1cFAHHC9iQN9mlEg=", ldns.LDNS_RDF_TYPE_B64) + try: + ret = rr.rrsig_set_sig(rdf) + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() +# rdf = ldns.ldns_rdf.new_frm_str("0.0.0.0", ldns.LDNS_RDF_TYPE_A) +# try: +# ret = rr.rrsig_set_sig(rdf) +# if not isinstance(ret, bool): +# set_error() +# if ret != False: +# set_error() +# except: +# set_error() + try: + ret = rr.rrsig_set_sig("") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".rrsig_set_signame()" + rr = ldns.ldns_rr.new_frm_str("example. 600 IN RRSIG SOA 3 1 600 20130828153754 20120828153754 19031 example. AIoCFhwZJxIgYOBEyo3cxxWFZEsUPqkxnt38xEl1cFAHHC9iQN9mlEg=") + rdf = ldns.ldns_rdf.new_frm_str("example.", ldns.LDNS_RDF_TYPE_DNAME) + try: + ret = rr.rrsig_set_signame(rdf) + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() +# rdf = ldns.ldns_rdf.new_frm_str("0.0.0.0", ldns.LDNS_RDF_TYPE_A) +# try: +# ret = rr.rrsig_set_signame(rdf) +# if not isinstance(ret, bool): +# set_error() +# if ret != False: +# set_error() +# except: +# set_error() + try: + ret = rr.rrsig_set_signame("") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".rrsig_set_typecovered()" + rr = ldns.ldns_rr.new_frm_str("example. 600 IN RRSIG SOA 3 1 600 20130828153754 20120828153754 19031 example. AIoCFhwZJxIgYOBEyo3cxxWFZEsUPqkxnt38xEl1cFAHHC9iQN9mlEg=") + rdf = ldns.ldns_rdf.new_frm_str("SOA", ldns.LDNS_RDF_TYPE_TYPE) + try: + ret = rr.rrsig_set_typecovered(rdf) + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() +# rdf = ldns.ldns_rdf.new_frm_str("0.0.0.0", ldns.LDNS_RDF_TYPE_A) +# try: +# ret = rr.rrsig_set_typecovered(rdf) +# if not isinstance(ret, bool): +# set_error() +# if ret != False: +# set_error() +# except: +# set_error() + try: + ret = rr.rrsig_set_typecovered("") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".rrsig_sig()" + rr = ldns.ldns_rr.new_frm_str("example. 600 IN RRSIG SOA 3 1 600 20130828153754 20120828153754 19031 example. AIoCFhwZJxIgYOBEyo3cxxWFZEsUPqkxnt38xEl1cFAHHC9iQN9mlEg=") + try: + ret = rr.rrsig_sig() + if not isinstance(ret, ldns.ldns_rdf): + set_error() + except: + set_error() + rr = ldns.ldns_rr.new_frm_str("test 600 IN A 0.0.0.0") + try: + ret = rr.rrsig_sig() + if isinstance(ret, ldns.ldns_rdf): + set_error() + if ret != None: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".rrsig_signame()" + rr = ldns.ldns_rr.new_frm_str("example. 600 IN RRSIG SOA 3 1 600 20130828153754 20120828153754 19031 example. AIoCFhwZJxIgYOBEyo3cxxWFZEsUPqkxnt38xEl1cFAHHC9iQN9mlEg=") + try: + ret = rr.rrsig_signame() + if not isinstance(ret, ldns.ldns_rdf): + set_error() + except: + set_error() + rr = ldns.ldns_rr.new_frm_str("test 600 IN A 0.0.0.0") + try: + ret = rr.rrsig_signame() + if isinstance(ret, ldns.ldns_rdf): + set_error() + if ret != None: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".rrsig_typecovered()" + rr = ldns.ldns_rr.new_frm_str("example. 600 IN RRSIG SOA 3 1 600 20130828153754 20120828153754 19031 example. AIoCFhwZJxIgYOBEyo3cxxWFZEsUPqkxnt38xEl1cFAHHC9iQN9mlEg=") + try: + ret = rr.rrsig_typecovered() + if not isinstance(ret, ldns.ldns_rdf): + set_error() + except: + set_error() + rr = ldns.ldns_rr.new_frm_str("test 600 IN A 0.0.0.0") + try: + ret = rr.rrsig_typecovered() + if isinstance(ret, ldns.ldns_rdf): + set_error() + if ret != None: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".set_class()" + rr = ldns.ldns_rr.new_frm_str("test 600 IN A 0.0.0.0") + try: + rr.set_class(ldns.LDNS_RR_CLASS_CH) + except: + set_error() + try: + rr.set_class("") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".set_owner()" + rr = ldns.ldns_rr.new_frm_str("test 600 IN A 0.0.0.0") + rdf = ldns.ldns_dname("test2") + try: + rr.set_owner(rdf) + except: + set_error() + try: + rr.set_owner("") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".set_question()" + rr = ldns.ldns_rr.new_frm_str("test 600 IN A 0.0.0.0") + try: + rr.set_question(True) + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".set_rd_count()" + rr = ldns.ldns_rr.new_frm_str("test 600 IN A 0.0.0.0") + try: + rr.set_rd_count(1) + except: + set_error() + try: + rr.set_rd_count("") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".set_rdf()" + rr = ldns.ldns_rr.new_frm_str("test 600 IN A 0.0.0.0") + rdf = ldns.ldns_rdf.new_frm_str("1.1.1.1", ldns.LDNS_RDF_TYPE_A) + rr.push_rdf(rdf) + try: + ret = rr.set_rdf(rdf, 0) + if not isinstance(ret, ldns.ldns_rdf): + set_error() + except: + set_error() + try: + ret = rr.set_rdf(rdf, 2) + if isinstance(ret, ldns.ldns_rdf): + set_error() + if ret != None: + set_error() + except: + set_error() + try: + rr.set_rdf("", 1) + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".set_ttl()" + rr = ldns.ldns_rr.new_frm_str("test 600 IN A 0.0.0.0") + try: + rr.set_ttl(1) + except: + set_error() + try: + rr.set_ttl("") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".set_type()" + rr = ldns.ldns_rr.new_frm_str("test 600 IN A 0.0.0.0") + try: + rr.set_type(ldns.LDNS_RR_TYPE_A) + except: + set_error() + try: + rr.set_type("") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".to_canonical()" + rr = ldns.ldns_rr.new_frm_str("TEST 600 IN A 0.0.0.0") + try: + rr.to_canonical() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".ttl()" + rr = ldns.ldns_rr.new_frm_str("test 600 IN A 0.0.0.0") + try: + ret = rr.ttl() + if not isinstance(ret, int): + set_error() + if ret != 600: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".type_by_name()" + try: + ret = ldns.ldns_rr.type_by_name("A") + if not isinstance(ret, int): + set_error() + if ret != ldns.LDNS_RR_TYPE_A: + set_error() + except: + set_error() + try: + ret = ldns.ldns_rr.type_by_name("AA") + if not isinstance(ret, int): + set_error() + if ret != 0: + set_error() + except: + set_error() + try: + ret = ldns.ldns_rr.type_by_name(1) + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".uncompressed_size()" + rr = ldns.ldns_rr.new_frm_str("test 600 IN A 0.0.0.0") + try: + ret = rr.uncompressed_size() + if not isinstance(ret, int): + set_error() + if ret != 20: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".write_data_to_buffer()" + sys.stderr.write("%s not tested.\n" % (method_name)) + + +#if not error_detected: +if True: + method_name = class_name + ".write_rrsig_to_buffer()" + sys.stderr.write("%s not tested.\n" % (method_name)) + + +#if not error_detected: +if True: + method_name = class_name + ".write_to_buffer()" + sys.stderr.write("%s not tested.\n" % (method_name)) + + +#if not error_detected: +if True: + method_name = class_name + ".write_to_buffer_canonical()" + sys.stderr.write("%s not tested.\n" % (method_name)) + + +############################################################################### +############################################################################### + + +class_name = "ldns_rr_descriptor" +method_name = None +error_detected = False +temp_fname = "tmp_rr_descriptor.txt" + + +#if not error_detected: +if True: + method_name = class_name + ".field_type()" + desc_a = ldns.ldns_rr_descriptor.ldns_rr_descriptor(ldns.LDNS_RR_TYPE_A) + try: + ret = desc_a.field_type(0) + if not isinstance(ret, int): + set_error() + if ret != ldns.LDNS_RDF_TYPE_A: + set_error() + except: + set_error() + try: + ret = desc_a.field_type("") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".ldns_rr_descriptor()" + try: + ret = ldns.ldns_rr_descriptor.ldns_rr_descriptor(ldns.LDNS_RR_TYPE_A) + if not isinstance(ret, ldns.ldns_rr_descriptor): + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".maximum()" + desc_a = ldns.ldns_rr_descriptor.ldns_rr_descriptor(ldns.LDNS_RR_TYPE_A) + try: + ret = desc_a.maximum() + if not isinstance(ret, int): + set_error() + if ret != 1: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".minimum()" + desc_a = ldns.ldns_rr_descriptor.ldns_rr_descriptor(ldns.LDNS_RR_TYPE_A) + try: + ret = desc_a.minimum() + if not isinstance(ret, int): + set_error() + if ret != 1: + set_error() + except: + set_error() + + +############################################################################### +############################################################################### + + +class_name = "ldns_rr_list" +method_name = None +error_detected = False +temp_fname = "tmp_rr_list.txt" + + +#if not error_detected: +if True: + method_name = class_name + ".[comparison operators]" + rrl1 = ldns.ldns_rr_list.new() + rrl1.push_rr(ldns.ldns_rr.new_frm_str("test1 600 IN A 0.0.0.0")) + rrl2 = ldns.ldns_rr_list.new() + rrl2.push_rr(ldns.ldns_rr.new_frm_str("test2 600 IN A 1.1.1.1")) + try: + ret = rrl1 < rrl2 + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + try: + ret = rrl2 < rrl1 + if not isinstance(ret, bool): + set_error() + if ret != False: + set_error() + except: + set_error() + try: + ret = rrl1 <= rrl2 + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + try: + ret = rrl2 <= rrl1 + if not isinstance(ret, bool): + set_error() + if ret != False: + set_error() + except: + set_error() + try: + ret = rrl1 == rrl2 + if not isinstance(ret, bool): + set_error() + if ret != False: + set_error() + except: + set_error() + try: + ret = rrl1 == rrl1 + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + try: + ret = rrl1 != rrl2 + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + try: + ret = rrl1 != rrl1 + if not isinstance(ret, bool): + set_error() + if ret != False: + set_error() + except: + set_error() + try: + ret = rrl1 > rrl2 + if not isinstance(ret, bool): + set_error() + if ret != False: + set_error() + except: + set_error() + try: + ret = rrl2 > rrl1 + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + try: + ret = rrl1 >= rrl2 + if not isinstance(ret, bool): + set_error() + if ret != False: + set_error() + except: + set_error() + try: + ret = rrl2 >= rrl1 + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".cat()" + rrl1 = ldns.ldns_rr_list.new() + rrl2 = ldns.ldns_rr_list.new() + rrl1.push_rr(ldns.ldns_rr.new_frm_str("test1 600 IN A 0.0.0.0")) + rrl2.push_rr(ldns.ldns_rr.new_frm_str("test2 600 IN A 1.1.1.1")) + try: + ret = rrl1.cat(rrl2) + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + try: + ret = rrl2.cat("") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".cat_clone()" + rrl1 = ldns.ldns_rr_list.new() + rrl2 = ldns.ldns_rr_list.new() + rrl1.push_rr(ldns.ldns_rr.new_frm_str("test1 600 IN A 0.0.0.0")) + rrl2.push_rr(ldns.ldns_rr.new_frm_str("test2 600 IN A 1.1.1.1")) + try: + ret = rrl1.cat_clone(rrl2) + if not isinstance(ret, ldns.ldns_rr_list): + set_error() + except: + set_error() + try: + ret = rrl2.cat_clone("") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".clone()" + rrl = ldns.ldns_rr_list.new() + rrl.push_rr(ldns.ldns_rr.new_frm_str("test1 600 IN A 0.0.0.0")) + try: + ret = rrl.clone() + if not isinstance(ret, ldns.ldns_rr_list): + set_error() + except: + set_error() + +#if not error_detected: +if True: + method_name = class_name + ".contains_rr()" + rrl = ldns.ldns_rr_list.new() + rr1 = ldns.ldns_rr.new_frm_str("test1 600 IN A 0.0.0.0") + rr2 = ldns.ldns_rr.new_frm_str("test2 600 IN A 1.1.1.1") + rrl.push_rr(rr1) + try: + ret = rrl.contains_rr(rr1) + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + try: + ret = rrl.contains_rr(rr2) + if not isinstance(ret, bool): + set_error() + if ret != False: + set_error() + except: + set_error() + try: + ret = rrl.contains_rr("") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".is_rrset()" + rrl = ldns.ldns_rr_list.new() + rr = ldns.ldns_rr.new_frm_str("test1 600 IN A 0.0.0.0") + rrl.push_rr(rr) + try: + ret = rrl.is_rrset() + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".new()" + try: + ret = ldns.ldns_rr_list.new() + if not isinstance(ret, ldns.ldns_rr_list): + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".new_frm_file()" + try: + ret = ldns.ldns_rr_list.new_frm_file() + if not isinstance(ret, ldns.ldns_rr_list): + set_error() + except: + set_error() + try: + ret = ldns.ldns_rr_list.new_frm_file("test") + set_error() + except Exception: + pass + except: + set_error() + try: + ret = ldns.ldns_rr_list.new_frm_file("test", raiseException=False) + if isinstance(ret, ldns.ldns_rr_list): + set_error() + if ret != None: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".owner()" + rrl = ldns.ldns_rr_list.new() + try: + ret = rrl.owner() + if isinstance(ret, ldns.ldns_rdf): + set_error() + if ret != None: + set_error() + except: + set_error() + rr = ldns.ldns_rr.new_frm_str("test1 600 IN A 0.0.0.0") + rrl.push_rr(rr) + try: + ret = rrl.owner() + if not isinstance(ret, ldns.ldns_dname): + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".pop_rr()" + rrl = ldns.ldns_rr_list.new() + rr = ldns.ldns_rr.new_frm_str("test1 600 IN A 0.0.0.0") + rrl.push_rr(rr) + try: + ret = rrl.pop_rr() + if not isinstance(ret, ldns.ldns_rr): + set_error() + except: + set_error() + try: + ret = rrl.pop_rr() + if isinstance(ret, ldns.ldns_rr): + set_error() + if ret != None: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".pop_rr_list()" + rrl = ldns.ldns_rr_list.new() + rr = ldns.ldns_rr.new_frm_str("test1 600 IN A 0.0.0.0") + rrl.push_rr(rr) + rrl.push_rr(rr) + rrl.push_rr(rr) + try: + ret = rrl.pop_rr_list(2) + if not isinstance(ret, ldns.ldns_rr_list): + set_error() + except: + set_error() + try: + ret = rrl.pop_rr_list(2) + if not isinstance(ret, ldns.ldns_rr_list): + set_error() + except: + set_error() + try: + ret = rrl.pop_rr_list(2) + if isinstance(ret, ldns.ldns_rr_list): + set_error() + if ret != None: + set_error() + except: + set_error() + try: + ret = rrl.pop_rr_list("") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".pop_rrset()" + rrl = ldns.ldns_rr_list.new() + rr = ldns.ldns_rr.new_frm_str("test1 600 IN A 0.0.0.0") + rrl.push_rr(rr) + rrl.push_rr(rr) + rrl.push_rr(rr) + try: + ret = rrl.pop_rrset() + if not isinstance(ret, ldns.ldns_rr_list): + set_error() + except: + set_error() + try: + ret = rrl.pop_rrset() + if isinstance(ret, ldns.ldns_rr_list): + set_error() + if ret != None: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".print_to_file()" + rrl = ldns.ldns_rr_list.new() + rr = ldns.ldns_rr.new_frm_str("test1 600 IN A 0.0.0.0") + rrl.push_rr(rr) + rrl.push_rr(rr) + rrl.push_rr(rr) + f = open(temp_fname, "w") + try: + rrl.print_to_file(f) + except: + set_error() + f.close() + f = open(temp_fname, "r") + if len(f.readlines()) != 3: + set_error() + f.close() + os.remove(temp_fname) + + +#if not error_detected: +if True: + method_name = class_name + ".push_rr()" + rrl = ldns.ldns_rr_list.new() + rr = ldns.ldns_rr.new_frm_str("test1 600 IN A 0.0.0.0") + try: + ret = rrl.push_rr(rr) + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + try: + ret = rrl.push_rr("") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".push_rr_list()" + rrl1 = ldns.ldns_rr_list.new() + rr = ldns.ldns_rr.new_frm_str("test1 600 IN A 0.0.0.0") + rrl1.push_rr(rr) + rrl2 = rrl1.new() + try: + ret = rrl1.push_rr_list(rrl2) + if not isinstance(ret, bool): + set_error() + if ret != True: + set_error() + except: + set_error() + try: + ret = rrl.push_rr_list("") + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".rr()" + rrl = ldns.ldns_rr_list.new() + rr = ldns.ldns_rr.new_frm_str("test1 600 IN A 0.0.0.0") + rrl.push_rr(rr) + try: + ret = rrl.rr(0) + if not isinstance(ret, ldns.ldns_rr): + set_error() + except: + set_error() + try: + ret = rrl.rr(1) + if isinstance(ret, ldns.ldns_rr): + set_error() + if ret != None: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".rr_count()" + rrl = ldns.ldns_rr_list.new() + try: + ret = rrl.rr_count() + if not isinstance(ret, int): + set_error() + if ret != 0: + set_error() + except: + set_error() + rr = ldns.ldns_rr.new_frm_str("test1 600 IN A 0.0.0.0") + rrl.push_rr(rr) + try: + ret = rrl.rr_count() + if not isinstance(ret, int): + set_error() + if ret != 1: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".rrs()" + rrl = ldns.ldns_rr_list.new() + rr = ldns.ldns_rr.new_frm_str("test1 600 IN A 0.0.0.0") + rrl.push_rr(rr) + rrl.push_rr(rr) + try: + ret = list(rrl.rrs()) + if not isinstance(ret, list): + set_error() + if len(ret) != 2: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".set_rr()" + rrl = ldns.ldns_rr_list.new() + rr = ldns.ldns_rr.new_frm_str("test1 600 IN A 0.0.0.0") + rrl.push_rr(rr) + rr = ldns.ldns_rr.new_frm_str("test2 600 IN A 1.1.1.1") + ret = rrl.set_rr(rr, 0) + try: + ret = rrl.set_rr(rr, 0) + if not isinstance(ret, ldns.ldns_rr): + set_error() + except: + set_error() + try: + ret = rrl.set_rr(rr, 1) + if isinstance(ret, ldns.ldns_rr): + set_error() + if ret != None: + set_error() + except: + set_error() + try: + ret = rrl.set_rr("", 1) + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".set_rr_count()" + rrl = ldns.ldns_rr_list.new() + try: + rrl.set_rr_count(0) + except: + set_error() + rr = ldns.ldns_rr.new_frm_str("test1 600 IN A 0.0.0.0") + rrl.push_rr(rr) + try: + rrl.set_rr_count("") + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".sort()" + rrl = ldns.ldns_rr_list.new() + try: + rrl.sort() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".subtype_by_rdf()" + rrl = ldns.ldns_rr_list.new() + rr = ldns.ldns_rr.new_frm_str("test1 600 IN A 0.0.0.0") + rrl.push_rr(rr) + rr = ldns.ldns_rr.new_frm_str("test2 600 IN A 1.1.1.1") + rrl.push_rr(rr) + rr = ldns.ldns_rr.new_frm_str("test3 600 IN A 0.0.0.0") + rrl.push_rr(rr) + rdf = ldns.ldns_rdf.new_frm_str("0.0.0.0", ldns.LDNS_RDF_TYPE_A) + try: + ret = rrl.subtype_by_rdf(rdf, 0) + if not isinstance(ret, ldns.ldns_rr_list): + set_error() + if ret.rr_count() != 2: + set_error() + except: + set_error() + rdf = ldns.ldns_rdf.new_frm_str("::", ldns.LDNS_RDF_TYPE_AAAA) + try: + ret = rrl.subtype_by_rdf(rdf, 0) + if isinstance(ret, ldns.ldns_rr_list): + set_error() + if ret != None: + set_error() + except: + set_error() + try: + ret = rrl.subtype_by_rdf("", 0) + set_error() + except TypeError: + pass + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".to_canonical()" + rrl = ldns.ldns_rr_list.new() + rr = ldns.ldns_rr.new_frm_str("TEST1 600 IN A 0.0.0.0") + rrl.push_rr(rr) + try: + rrl.to_canonical() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".type()" + rrl = ldns.ldns_rr_list.new() + try: + ret = rrl.type() + if not isinstance(ret, int): + set_error() + if ret != 0: + set_error() + except: + set_error() + rr = ldns.ldns_rr.new_frm_str("TEST1 600 IN A 0.0.0.0") + rrl.push_rr(rr) + try: + ret = rrl.type() + if not isinstance(ret, int): + set_error() + if ret != ldns.LDNS_RR_TYPE_A: + set_error() + except: + set_error() + + +#if not error_detected: +if True: + method_name = class_name + ".write_to_buffer()" + sys.stderr.write("%s not tested.\n" % (method_name)) + + +if not error_detected: + sys.stdout.write("%s: passed.\n" % (os.path.basename(__file__))) +else: + sys.stdout.write("%s: errors detected.\n" % (os.path.basename(__file__))) + sys.exit(1) diff --git a/contrib/python/file_py3.i b/contrib/python/file_py3.i index b3f55e82ab5..4d9502c5490 100644 --- a/contrib/python/file_py3.i +++ b/contrib/python/file_py3.i @@ -103,7 +103,8 @@ dispose_file(FILE **fp) { %typemap(check, noblock = 1) FILE* { if ($1 == NULL) { - SWIG_exception_fail(SWIG_ValueError, "in method '" "$symname" "', argument " + /* The generated wrapper function raises TypeError on mismatching types. */ + SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname" "', argument " "$argnum"" of type '" "$type""'"); } } diff --git a/contrib/python/ldns.i b/contrib/python/ldns.i index 122ebe18e0a..35e076f8b7c 100644 --- a/contrib/python/ldns.i +++ b/contrib/python/ldns.i @@ -78,6 +78,36 @@ #endif %include "typemaps.i" + +/* ========================================================================= */ +/* Preliminary Python code. */ +/* ========================================================================= */ + +%pythoncode +%{ + # + # Use and don't ignore DeprecationWarning and + # PendingDeprecationWarning. + # + import warnings + warnings.filterwarnings("module", category=DeprecationWarning) + warnings.filterwarnings("module", category=PendingDeprecationWarning) +%} + + +/* Tell SWIG how to handle ssize_t as input parameter. */ +%typemap(in, noblock=1) (ssize_t) +{ + int $1_res = 0; + $1_res = SWIG_AsVal_long($input, &$1); + if (!SWIG_IsOK($1_res)) { + SWIG_exception_fail(SWIG_ArgError($1_res), "in method '" + "$symname" "', argument " "$argnum" " of type '" + "$type""'"); + } +} + + %inline %{ struct timeval* ldns_make_timeval(uint32_t sec, uint32_t usec) { @@ -97,8 +127,9 @@ uint32_t ldns_read_timeval_usec(struct timeval* t) { %immutable ldns_error_str; %immutable ldns_signing_algorithms; -//new_frm_fp_l -%apply int *OUTPUT { int *line_nr}; +//*_new_frm_fp_l +%apply int *OUTPUT { (int *line_nr) }; + %apply uint32_t *OUTPUT { uint32_t *default_ttl}; // wire2pkt @@ -192,8 +223,53 @@ typedef struct ldns_dnssec_zone { }; return tuple; } + PyObject* ldns_rr_new_frm_fp_(FILE *fp, uint32_t default_ttl, ldns_rdf* origin, ldns_rdf* prev) + //returns tuple (status, ldns_rr, ttl, origin, prev) + { + uint32_t defttl = default_ttl; + uint32_t *p_defttl = &defttl; + if (defttl == 0) p_defttl = 0; + + /* origin and prev have to be cloned in order to decouple the data + * from the python wrapper + */ + if (origin != NULL) + origin = ldns_rdf_clone(origin); + if (prev != NULL) + prev = ldns_rdf_clone(prev); + + ldns_rdf *p_origin = origin; + ldns_rdf **pp_origin = &p_origin; + //if (p_origin == 0) pp_origin = 0; + + ldns_rdf *p_prev = prev; + ldns_rdf **pp_prev = &p_prev; + //if (p_prev == 0) pp_prev = 0; + + ldns_rr *p_rr = 0; + ldns_rr **pp_rr = &p_rr; + + ldns_status st = ldns_rr_new_frm_fp(pp_rr, fp, p_defttl, pp_origin, pp_prev); + + PyObject* tuple; + tuple = PyTuple_New(5); + int idx = 0; + PyTuple_SetItem(tuple, idx, SWIG_From_int(st)); + idx++; + PyTuple_SetItem(tuple, idx, (st == LDNS_STATUS_OK) ? + SWIG_NewPointerObj(SWIG_as_voidptr(p_rr), SWIGTYPE_p_ldns_struct_rr, SWIG_POINTER_OWN | 0 ) : + (Py_INCREF(Py_None), Py_None)); + idx++; + PyTuple_SetItem(tuple, idx, SWIG_From_int(defttl)); + idx++; + PyTuple_SetItem(tuple, idx, SWIG_NewPointerObj(SWIG_as_voidptr(p_origin), SWIGTYPE_p_ldns_struct_rdf, SWIG_POINTER_OWN | 0 )); + idx++; + PyTuple_SetItem(tuple, idx, SWIG_NewPointerObj(SWIG_as_voidptr(p_prev), SWIGTYPE_p_ldns_struct_rdf, SWIG_POINTER_OWN | 0 )); + return tuple; + } + PyObject* ldns_rr_new_frm_fp_l_(FILE *fp, uint32_t default_ttl, ldns_rdf* origin, ldns_rdf* prev) - //returns tuple (status, ldns_rr, [line if ret_linenr], ttl, origin, prev) + //returns tuple (status, ldns_rr, line, ttl, origin, prev) { int linenr = 0; int *p_linenr = &linenr; diff --git a/contrib/python/ldns_buffer.i b/contrib/python/ldns_buffer.i index 1e743c00780..f9825c2907b 100644 --- a/contrib/python/ldns_buffer.i +++ b/contrib/python/ldns_buffer.i @@ -14,8 +14,8 @@ * 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 organization nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 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 @@ -28,46 +28,43 @@ * 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. - ******************************************************************************/ + *****************************************************************************/ -%typemap(in,numinputs=0,noblock=1) (ldns_buffer **) + +/* ========================================================================= */ +/* SWIG setting and definitions. */ +/* ========================================================================= */ + +/* Creates a temporary instance of (ldns_buffer *). */ +%typemap(in, numinputs=0, noblock=1) (ldns_buffer **) { - ldns_buffer *$1_buf; - $1 = &$1_buf; + ldns_buffer *$1_buf; + $1 = &$1_buf; } -/* result generation */ -%typemap(argout,noblock=1) (ldns_buffer **) +/* Result generation, appends (ldns_buffer *) after the result. */ +%typemap(argout, noblock=1) (ldns_buffer **) { - $result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(SWIG_as_voidptr($1_buf), SWIGTYPE_p_ldns_struct_buffer, SWIG_POINTER_OWN | 0 )); + $result = SWIG_Python_AppendOutput($result, + SWIG_NewPointerObj(SWIG_as_voidptr($1_buf), + SWIGTYPE_p_ldns_struct_buffer, SWIG_POINTER_OWN | 0)); } -%nodefaultctor ldns_struct_buffer; //no default constructor & destructor -%nodefaultdtor ldns_struct_buffer; - -%delobject ldns_buffer_free; -%newobject ldns_buffer_new; -%newobject ldns_dname_new; -%newobject ldns_dname_new_frm_data; -%newobject ldns_dname_label; - -# limit the number of arguments to 2 and -# deal with variable number of arguments the Python way +/* + * Limit the number of arguments to 2 and deal with variable + * number of arguments in the Python way. + */ %varargs(2, char *arg = NULL) ldns_buffer_printf; -%rename(ldns_buffer) ldns_struct_buffer; +%nodefaultctor ldns_struct_buffer; /* No default constructor. */ +%nodefaultdtor ldns_struct_buffer; /* No default destructor. */ -#ifdef LDNS_DEBUG -%rename(__ldns_buffer_free) ldns_buffer_free; -%inline %{ -void _ldns_buffer_free (ldns_buffer* b) { - printf("******** LDNS_BUFFER free 0x%lX ************\n", (long unsigned int)b); - ldns_buffer_free(b); -} -%} -#else -%rename(_ldns_buffer_free) ldns_buffer_free; -#endif +%newobject ldns_buffer_new; +%newobject ldns_dname_new_frm_data; + +%delobject ldns_buffer_free; + +%rename(ldns_buffer) ldns_struct_buffer; %ignore ldns_struct_buffer::_position; %ignore ldns_struct_buffer::_limit; @@ -76,301 +73,425 @@ void _ldns_buffer_free (ldns_buffer* b) { %ignore ldns_struct_buffer::_fixed; %ignore ldns_struct_buffer::_status; +%ignore ldns_buffer_new_frm_data; + + +/* ========================================================================= */ +/* Debugging related code. */ +/* ========================================================================= */ + +#ifdef LDNS_DEBUG +%rename(__ldns_buffer_free) ldns_buffer_free; +%inline +%{ + /*! + * @brief Frees the buffer and print a message. + */ + void _ldns_buffer_free (ldns_buffer* b) + { + printf("******** LDNS_BUFFER free 0x%lX ************\n", + (long unsigned int) b); + ldns_buffer_free(b); + } +%} +#else /* !LDNS_DEBUG */ +%rename(_ldns_buffer_free) ldns_buffer_free; +#endif /* LDNS_DEBUG */ + + +/* ========================================================================= */ +/* Added C code. */ +/* ========================================================================= */ + +/* None. */ + + +/* ========================================================================= */ +/* Encapsulating Python code. */ +/* ========================================================================= */ + +%feature("docstring") "LDNS buffer." + %extend ldns_struct_buffer { - %pythoncode %{ + %pythoncode + %{ def __init__(self, capacity): - """Creates a new buffer with the specified capacity. + """ + Creates a new buffer with the specified capacity. - :param capacity: the size (in bytes) to allocate for the buffer + :param capacity: Number of bytes to allocate for the buffer. + :type capacity: integer + :throws TypeError: When `capacity` of non-integer type. + :return: (:class:`ldns_buffer`) """ self.this = _ldns.ldns_buffer_new(capacity) __swig_destroy__ = _ldns._ldns_buffer_free def __str__(self): - """Returns the data in the buffer as a string. Buffer data must be char * type.""" + """ + Returns the data in the buffer as a string. + Buffer data must be char * type. + + :return: string + """ return _ldns.ldns_buffer2str(self) def getc(self): - """returns the next character from a buffer. + """ + Returns the next character from a buffer. - Advances the position pointer with 1. When end of buffer is reached returns EOF. This is the buffer's equivalent for getc(). + Advances the position pointer with 1. When end of buffer + is reached returns EOF. This is the buffer's equivalent + for getc(). - :returns: (int) EOF on failure otherwise return the character + :return: (integer) EOF on failure otherwise return + the character. """ return _ldns.ldns_bgetc(self) - #LDNS_BUFFER_METHODS_# - def at(self,at): - """returns a pointer to the data at the indicated position. - - :param at: - position - :returns: (uint8_t \*) the pointer to the data + # + # LDNS_BUFFER_METHODS_ + # + + def at(self, at): """ - return _ldns.ldns_buffer_at(self,at) - #parameters: const ldns_buffer *,size_t, + Returns a pointer to the data at the indicated position. + + :param at: position + :type at: positive integer + :throws TypeError: When `at` of non-integer type. + :return: (uint8_t \*) The pointer to the data. + """ + return _ldns.ldns_buffer_at(self, at) + #parameters: const ldns_buffer *, size_t, #retvals: uint8_t * - def available(self,count): - """checks if the buffer has count bytes available at the current position - - :param count: - how much is available - :returns: (int) true or false + def available(self, count): """ - return _ldns.ldns_buffer_available(self,count) - #parameters: ldns_buffer *,size_t, + Checks whether the buffer has count bytes available at + the current position. + + :param count: How much is available. + :type count: integer + :throws TypeError: When `count` of non-integer type. + :return: (bool) True or False. + """ + return _ldns.ldns_buffer_available(self, count) != 0 + #parameters: ldns_buffer *, size_t, #retvals: int - def available_at(self,at,count): - """checks if the buffer has at least COUNT more bytes available. - - Before reading or writing the caller needs to ensure enough space is available! - - :param at: - indicated position - :param count: - how much is available - :returns: (int) true or false + def available_at(self, at, count): """ - return _ldns.ldns_buffer_available_at(self,at,count) + Checks if the buffer has at least `count` more bytes available. + + Before reading or writing the caller needs to ensure that + enough space is available! + + :param at: Indicated position. + :type at: positive integer + :param count: How much is available. + :type count: positive integer + :throws TypeError: When `at` or `count` of non-integer type. + :return: (bool) True or False. + """ + return _ldns.ldns_buffer_available_at(self, at, count) != 0 #parameters: ldns_buffer *,size_t,size_t, #retvals: int def begin(self): - """returns a pointer to the beginning of the buffer (the data at position 0). + """ + Returns a pointer to the beginning of the buffer + (the data at position 0). - :returns: (uint8_t \*) the pointer + :return: (uint8_t \*) Pointer. """ return _ldns.ldns_buffer_begin(self) #parameters: const ldns_buffer *, #retvals: uint8_t * def capacity(self): - """returns the number of bytes the buffer can hold. + """ + Returns the number of bytes the buffer can hold. - :returns: (size_t) the number of bytes + :return: (size_t) The number of bytes. """ return _ldns.ldns_buffer_capacity(self) #parameters: ldns_buffer *, #retvals: size_t def clear(self): - """clears the buffer and make it ready for writing. + """ + Clears the buffer and make it ready for writing. - The buffer's limit is set to the capacity and the position is set to 0. + The buffer's limit is set to the capacity and the position + is set to 0. """ _ldns.ldns_buffer_clear(self) #parameters: ldns_buffer *, #retvals: - def copy(self,bfrom): - """Copy contents of the other buffer to this buffer. + def copy(self, bfrom): + """ + Copy contents of the other buffer to this buffer. Silently truncated if this buffer is too small. - :param bfrom: other buffer + :param bfrom: Source buffer. + :type bfrom: :class:`ldns_buffer` + :throws TypeError: When `bfrom` of non-:class:`ldns_buffer` + type. """ - _ldns.ldns_buffer_copy(self,bfrom) - #parameters: ldns_buffer *,ldns_buffer *, + _ldns.ldns_buffer_copy(self, bfrom) + #parameters: ldns_buffer *, ldns_buffer *, #retvals: def current(self): - """returns a pointer to the data at the buffer's current position. + """ + Returns a pointer to the data at the buffer's current position. - :returns: (uint8_t \*) the pointer + :return: (uint8_t \*) A pointer. """ return _ldns.ldns_buffer_current(self) #parameters: ldns_buffer *, #retvals: uint8_t * def end(self): - """returns a pointer to the end of the buffer (the data at the buffer's limit). + """ + Returns a pointer to the end of the buffer (the data + at the buffer's limit). - :returns: (uint8_t \*) the pointer + :return: (uint8_t \*) Pointer. """ return _ldns.ldns_buffer_end(self) #parameters: ldns_buffer *, #retvals: uint8_t * def export(self): - """Makes the buffer fixed and returns a pointer to the data. + """ + Makes the buffer fixed and returns a pointer to the data. - The caller is responsible for free'ing the result. + The caller is responsible for freeing the result. - :returns: (void \*) void + :return: (void \*) Void pointer. """ return _ldns.ldns_buffer_export(self) #parameters: ldns_buffer *, #retvals: void * def flip(self): - """makes the buffer ready for reading the data that has been written to the buffer. + """ + Makes the buffer ready for reading the data that has been + written to the buffer. - The buffer's limit is set to the current position and the position is set to 0. + The buffer's limit is set to the current position and + the position is set to 0. """ _ldns.ldns_buffer_flip(self) #parameters: ldns_buffer *, def invariant(self): + """ + Performs no action. + + In debugging mode this method performs a buffer settings + check. It asserts if something is wrong. + """ _ldns.ldns_buffer_invariant(self) #parameters: ldns_buffer *, def limit(self): - """returns the maximum size of the buffer + """ + Returns the maximum size of the buffer. - :returns: (size_t) the size + :return: (size_t) The size. """ return _ldns.ldns_buffer_limit(self) #parameters: ldns_buffer *, #retvals: size_t def position(self): - """returns the current position in the buffer (as a number of bytes) + """ + Returns the current position in the buffer + (as a number of bytes). - :returns: (size_t) the current position + :return: (size_t) The current position. """ return _ldns.ldns_buffer_position(self) #parameters: ldns_buffer *, #retvals: size_t - def printf(self, str, *args): - """Prints to the buffer, increasing the capacity if required using buffer_reserve(). - - The buffer's position is set to the terminating '\0'. Returns the number of characters written (not including the terminating '\0') or -1 on failure. - :param str: a string - :returns: (int) + def printf(self, string, *args): """ - data = str % args - return _ldns.ldns_buffer_printf(self,data) - #parameters: ldns_buffer *,const char *,... + Prints to the buffer, increasing the capacity + if required using buffer_reserve(). + + The buffer's position is set to the terminating '\0'. + Returns the number of characters written (not including + the terminating '\0') or -1 on failure. + + :param string: A string to be written. + :type string: string + :throws: TypeError when `string` not a string. + :return: (int) Number of written characters or -1 on failure. + """ + data = string % args + return _ldns.ldns_buffer_printf(self, data) + #parameters: ldns_buffer *, const char *, ... #retvals: int - def read(self,data,count): - """copies count bytes of data at the current position to the given data-array + def read(self, data, count): + """ + Copies count bytes of data at the current position to the given + `data`-array - :param data: - buffer to copy to - :param count: - the length of the data to copy + :param data: Target buffer to copy to. + :type data: void \* + :param count: The length of the data to copy. + :type count: size_t """ _ldns.ldns_buffer_read(self,data,count) - #parameters: ldns_buffer *,void *,size_t, + #parameters: ldns_buffer *, void *, size_t, #retvals: - def read_at(self,at,data,count): - """copies count bytes of data at the given position to the given data-array + def read_at(self, at, data, count): + """ + Copies count bytes of data at the given position to the + given `data`-array. - :param at: - the position in the buffer to start - :param data: - buffer to copy to - :param count: - the length of the data to copy + :param at: The position in the buffer to start reading. + :type at: size_t + :param data: Target buffer to copy to. + :type data: void \* + :param count: The length of the data to copy. + :type count: size_t """ _ldns.ldns_buffer_read_at(self,at,data,count) - #parameters: ldns_buffer *,size_t,void *,size_t, + #parameters: ldns_buffer *, size_t, void *, size_t, #retvals: def read_u16(self): - """returns the 2-byte integer value at the current position in the buffer + """ + Returns the 2-byte integer value at the current position + from the buffer. - :returns: (uint16_t) 2 byte integer + :return: (uint16_t) Word. """ return _ldns.ldns_buffer_read_u16(self) #parameters: ldns_buffer *, #retvals: uint16_t - def read_u16_at(self,at): - """returns the 2-byte integer value at the given position in the buffer - - :param at: - position in the buffer - :returns: (uint16_t) 2 byte integer + def read_u16_at(self, at): """ - return _ldns.ldns_buffer_read_u16_at(self,at) - #parameters: ldns_buffer *,size_t, + Returns the 2-byte integer value at the given position + from the buffer. + + :param at: Position in the buffer. + :type at: positive integer + :throws TypeError: When `at` of non-integer type. + :return: (uint16_t) Word. + """ + return _ldns.ldns_buffer_read_u16_at(self, at) + #parameters: ldns_buffer *, size_t, #retvals: uint16_t def read_u32(self): - """returns the 4-byte integer value at the current position in the buffer + """ + Returns the 4-byte integer value at the current position + from the buffer. - :returns: (uint32_t) 4 byte integer + :return: (uint32_t) Double-word. """ return _ldns.ldns_buffer_read_u32(self) #parameters: ldns_buffer *, #retvals: uint32_t - def read_u32_at(self,at): - """returns the 4-byte integer value at the given position in the buffer - - :param at: - position in the buffer - :returns: (uint32_t) 4 byte integer + def read_u32_at(self, at): """ - return _ldns.ldns_buffer_read_u32_at(self,at) - #parameters: ldns_buffer *,size_t, + Returns the 4-byte integer value at the given position + from the buffer. + + :param at: Position in the buffer. + :type at: positive integer + :throws TypeError: When `at` of non-integer type. + :return: (uint32_t) Double-word. + """ + return _ldns.ldns_buffer_read_u32_at(self, at) + #parameters: ldns_buffer *, size_t, #retvals: uint32_t def read_u8(self): - """returns the byte value at the current position in the buffer + """ + Returns the byte value at the current position from the buffer. - :returns: (uint8_t) 1 byte integer + :return: (uint8_t) A byte (not a character). """ return _ldns.ldns_buffer_read_u8(self) #parameters: ldns_buffer *, #retvals: uint8_t - def read_u8_at(self,at): - """returns the byte value at the given position in the buffer - - :param at: - the position in the buffer - :returns: (uint8_t) 1 byte integer + def read_u8_at(self, at): """ - return _ldns.ldns_buffer_read_u8_at(self,at) - #parameters: ldns_buffer *,size_t, + Returns the byte value at the given position from the buffer. + + :param at: The position in the buffer. + :type at: positive integer + :throws TypeError: When `at` of non-integer type. + :return: (uint8_t) Byte value. + """ + return _ldns.ldns_buffer_read_u8_at(self, at) + #parameters: ldns_buffer *, size_t, #retvals: uint8_t def remaining(self): - """returns the number of bytes remaining between the buffer's position and limit. + """ + Returns the number of bytes remaining between the buffer's + position and limit. - :returns: (size_t) the number of bytes + :return: (size_t) The number of bytes. """ return _ldns.ldns_buffer_remaining(self) #parameters: ldns_buffer *, #retvals: size_t - def remaining_at(self,at): - """returns the number of bytes remaining between the indicated position and the limit. - - :param at: - indicated position - :returns: (size_t) number of bytes + def remaining_at(self, at): """ - return _ldns.ldns_buffer_remaining_at(self,at) + Returns the number of bytes remaining between the indicated + position and the limit. + + :param at: Indicated position. + :type at: positive integer + :throws TypeError: When `at` of non-integer type. + :return: (size_t) number of bytes + """ + return _ldns.ldns_buffer_remaining_at(self, at) #parameters: ldns_buffer *,size_t, #retvals: size_t - def reserve(self,amount): - """ensures BUFFER can contain at least AMOUNT more bytes. - - The buffer's capacity is increased if necessary using buffer_set_capacity(). - - The buffer's limit is always set to the (possibly increased) capacity. - - :param amount: - amount to use - :returns: (bool) whether this failed or succeeded + def reserve(self, amount): """ - return _ldns.ldns_buffer_reserve(self,amount) - #parameters: ldns_buffer *,size_t, + Ensures that the buffer can contain at least `amount` more + bytes. + + The buffer's capacity is increased if necessary using + buffer_set_capacity(). + + The buffer's limit is always set to the (possibly increased) + capacity. + + :param amount: Amount to use. + :type amount: positive integer + :throws TypeError: When `amount` of non-integer type. + :return: (bool) hether this failed or succeeded. + """ + return _ldns.ldns_buffer_reserve(self, amount) + #parameters: ldns_buffer *, size_t, #retvals: bool def rewind(self): - """make the buffer ready for re-reading the data. + """ + Make the buffer ready for re-reading the data. The buffer's position is reset to 0. """ @@ -378,188 +499,228 @@ void _ldns_buffer_free (ldns_buffer* b) { #parameters: ldns_buffer *, #retvals: - def set_capacity(self,capacity): - """changes the buffer's capacity. - - The data is reallocated so any pointers to the data may become invalid. The buffer's limit is set to the buffer's new capacity. - - :param capacity: - the capacity to use - :returns: (bool) whether this failed or succeeded + def set_capacity(self, capacity): """ - return _ldns.ldns_buffer_set_capacity(self,capacity) - #parameters: ldns_buffer *,size_t, + Changes the buffer's capacity. + + The data is reallocated so any pointers to the data may become + invalid. The buffer's limit is set to the buffer's new capacity. + + :param capacity: The capacity to use. + :type capacity: positive integer + :throws TypeError: When `capacity` of non-integer type. + :return: (bool) whether this failed or succeeded + """ + return _ldns.ldns_buffer_set_capacity(self, capacity) + #parameters: ldns_buffer *, size_t, #retvals: bool - def set_limit(self,limit): - """changes the buffer's limit. - - If the buffer's position is greater than the new limit the position is set to the limit. - - :param limit: - the new limit + def set_limit(self, limit): """ - _ldns.ldns_buffer_set_limit(self,limit) - #parameters: ldns_buffer *,size_t, + Changes the buffer's limit. + + If the buffer's position is greater than the new limit + then the position is set to the limit. + + :param limit: The new limit. + :type limit: positive integer + :throws TypeError: When `limit` of non-integer type. + """ + _ldns.ldns_buffer_set_limit(self, limit) + #parameters: ldns_buffer *, size_t, #retvals: def set_position(self,mark): - """sets the buffer's position to MARK. + """ + Sets the buffer's position to `mark`. The position must be less than or equal to the buffer's limit. - :param mark: - the mark to use + :param mark: The mark to use. + :type mark: positive integer + :throws TypeError: When `mark` of non-integer type. """ _ldns.ldns_buffer_set_position(self,mark) #parameters: ldns_buffer *,size_t, #retvals: - def skip(self,count): - """changes the buffer's position by COUNT bytes. - - The position must not be moved behind the buffer's limit or before the beginning of the buffer. - - :param count: - the count to use + def skip(self, count): """ - _ldns.ldns_buffer_skip(self,count) - #parameters: ldns_buffer *,ssize_t, + Changes the buffer's position by `count` bytes. + + The position must not be moved behind the buffer's limit or + before the beginning of the buffer. + + :param count: The count to use. + :type count: integer + :throws TypeError: When `count` of non-integer type. + """ + _ldns.ldns_buffer_skip(self, count) + #parameters: ldns_buffer *, ssize_t, #retvals: def status(self): - """returns the status of the buffer + """ + Returns the status of the buffer. - :returns: (ldns_status) the status + :return: (ldns_status) The status. """ return _ldns.ldns_buffer_status(self) #parameters: ldns_buffer *, #retvals: ldns_status def status_ok(self): - """returns true if the status of the buffer is LDNS_STATUS_OK, false otherwise + """ + Returns True if the status of the buffer is LDNS_STATUS_OK, + False otherwise. - :returns: (bool) true or false + :return: (bool) True or False. """ return _ldns.ldns_buffer_status_ok(self) #parameters: ldns_buffer *, #retvals: bool - def write(self,data,count): - """writes count bytes of data to the current position of the buffer - - :param data: - the data to write - :param count: - the lenght of the data to write + def write(self, data, count): """ - _ldns.ldns_buffer_write(self,data,count) - #parameters: ldns_buffer *,const void *,size_t, + Writes count bytes of data to the current position of + the buffer. + + :param data: The data to write. + :type data: void \* + :param count: The length of the data to write. + :type count: size_t + """ + _ldns.ldns_buffer_write(self, data, count) + #parameters: ldns_buffer *, const void *, size_t, #retvals: - def write_at(self,at,data,count): - """writes the given data to the buffer at the specified position - - :param at: - the position (in number of bytes) to write the data at - :param data: - pointer to the data to write to the buffer - :param count: - the number of bytes of data to write + def write_at(self, at, data, count): """ - _ldns.ldns_buffer_write_at(self,at,data,count) - #parameters: ldns_buffer *,size_t,const void *,size_t, + Writes the given data to the buffer at the specified position + by `at`. + + :param at: The position (in number of bytes) to write the + data at. + :param data: Pointer to the data to write to the buffer. + :param count: The number of bytes of data to write. + """ + _ldns.ldns_buffer_write_at(self, at, data, count) + #parameters: ldns_buffer *, size_t, const void *, size_t, #retvals: - def write_string(self,str): - """copies the given (null-delimited) string to the current position at the buffer - - :param str: - the string to write + def write_string(self, string): """ - _ldns.ldns_buffer_write_string(self,str) + Copies the given (null-delimited) string to the current + position into the buffer. + + :param string: The string to write. + :type string: string + :throws TypeError: When `string` not a string. + """ + _ldns.ldns_buffer_write_string(self,string) #parameters: ldns_buffer *,const char *, #retvals: - def write_string_at(self,at,str): - """copies the given (null-delimited) string to the specified position at the buffer - - :param at: - the position in the buffer - :param str: - the string to write + def write_string_at(self, at, string): """ - _ldns.ldns_buffer_write_string_at(self,at,str) - #parameters: ldns_buffer *,size_t,const char *, + Copies the given (null-delimited) string to the specified + position `at` into the buffer. + + :param at: The position in the buffer. + :type at: positive integer + :param string: The string to write. + :type string: string + :throws TypeError: When types mismatch. + """ + _ldns.ldns_buffer_write_string_at(self, at, string) + #parameters: ldns_buffer *, size_t, const char *, #retvals: - def write_u16(self,data): - """writes the given 2 byte integer at the current position in the buffer + def write_u16(self, data): + """Writes the given 2 byte integer at the current + position in the buffer. - :param data: - the 16 bits to write + :param data: The word to write. + :type data: uint16_t + :throws TypeError: When `data` of non-integer type. """ - _ldns.ldns_buffer_write_u16(self,data) - #parameters: ldns_buffer *,uint16_t, + _ldns.ldns_buffer_write_u16(self, data) + #parameters: ldns_buffer *, uint16_t, #retvals: - def write_u16_at(self,at,data): - """writes the given 2 byte integer at the given position in the buffer + def write_u16_at(self, at, data): + """ + Writes the given 2 byte integer at the given position + in the buffer. - :param at: - the position in the buffer - :param data: - the 16 bits to write + :param at: The position in the buffer. + :type at: positive integer + :param data: The word to write. + :type data: uint16_t + :throws TypeError: When `at` or `data` of non-integer type. """ _ldns.ldns_buffer_write_u16_at(self,at,data) #parameters: ldns_buffer *,size_t,uint16_t, #retvals: - def write_u32(self,data): - """writes the given 4 byte integer at the current position in the buffer - - :param data: - the 32 bits to write + def write_u32(self, data): """ - _ldns.ldns_buffer_write_u32(self,data) - #parameters: ldns_buffer *,uint32_t, + Writes the given 4 byte integer at the current position + in the buffer. + + :param data: The double-word to write. + :type data: uint32_t + :throws TypeError: When `data` of non-integer type. + """ + _ldns.ldns_buffer_write_u32(self, data) + #parameters: ldns_buffer *, uint32_t, #retvals: - def write_u32_at(self,at,data): - """writes the given 4 byte integer at the given position in the buffer - - :param at: - the position in the buffer - :param data: - the 32 bits to write + def write_u32_at(self, at, data): """ - _ldns.ldns_buffer_write_u32_at(self,at,data) + Writes the given 4 byte integer at the given position + in the buffer. + + :param at: The position in the buffer. + :type at: positive integer + :param data: The double-word to write. + :type data: uint32_t + :throws TypeError: When `at` or `data` of non-integer type. + """ + _ldns.ldns_buffer_write_u32_at(self, at, data) #parameters: ldns_buffer *,size_t,uint32_t, #retvals: - def write_u8(self,data): - """writes the given byte of data at the current position in the buffer - - :param data: - the 8 bits to write + def write_u8(self, data): """ - _ldns.ldns_buffer_write_u8(self,data) - #parameters: ldns_buffer *,uint8_t, + Writes the given byte of data at the current position + in the buffer. + + :param data: The byte to write. + :type data: uint8_t + :throws TypeError: When `data` of non-integer type. + """ + _ldns.ldns_buffer_write_u8(self, data) + #parameters: ldns_buffer *, uint8_t, #retvals: def write_u8_at(self,at,data): - """writes the given byte of data at the given position in the buffer + """ + Writes the given byte of data at the given position + in the buffer. - :param at: - the position in the buffer - :param data: - the 8 bits to write + :param at: The position in the buffer. + :type at: positive integer + :param data: The byte to write. + :type data: uint8_t + :throws TypeError: When `at` or `data` of non-integer type. """ _ldns.ldns_buffer_write_u8_at(self,at,data) #parameters: ldns_buffer *,size_t,uint8_t, #retvals: - #_LDNS_BUFFER_METHODS# - %} + # + # _LDNS_BUFFER_METHODS + # + %} } - diff --git a/contrib/python/ldns_dname.i b/contrib/python/ldns_dname.i index 0aac54c1060..cd3f53ea335 100644 --- a/contrib/python/ldns_dname.i +++ b/contrib/python/ldns_dname.i @@ -14,8 +14,8 @@ * 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 organization nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 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 @@ -28,169 +28,598 @@ * 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. - ******************************************************************************/ -%pythoncode %{ - class ldns_dname(ldns_rdf): - """Domain name + *****************************************************************************/ - This class contains methods to read and manipulate domain names. - Domain names are stored in ldns_rdf structures, with the type LDNS_RDF_TYPE_DNAME + +/* ========================================================================= */ +/* SWIG setting and definitions. */ +/* ========================================================================= */ + +/* + * Not here (with the exception of functions defined in this C code sction), + * must be set in ldns_rdf.i. + */ + + +/* ========================================================================= */ +/* Debugging related code. */ +/* ========================================================================= */ + +/* + * Not here (with the exception of functions defined in this C code sction), + * must be set in ldns_rdf.i. + */ + + +/* ========================================================================= */ +/* Added C code. */ +/* ========================================================================= */ + +/* None */ + + +/* ========================================================================= */ +/* Encapsulating Python code. */ +/* ========================================================================= */ + +%pythoncode +%{ + class ldns_dname(ldns_rdf): + """ + Domain name. + + This class contains methods to read and manipulate domain name drfs. + Domain names are stored in :class:`ldns_rdf` structures, + with the type LDNS_RDF_TYPE_DNAME. This class encapsulates such + rdfs. **Usage** - >>> import ldns - >>> resolver = ldns.ldns_resolver.new_frm_file("/etc/resolv.conf") - >>> dn1 = ldns.ldns_dname("test.nic.cz") - >>> print dn1 - test.nic.cz. - >>> dn2 = ldns.ldns_dname("nic.cz") - >>> if dn2.is_subdomain(dn1): print dn2,"is subdomain of",dn1 - >>> if dn1.is_subdomain(dn2): print dn1,"is subdomain of",dn2 - test.nic.cz. is subdomain of nic.cz. + >>> import ldns + >>> dn1 = ldns.ldns_dname("test.nic.cz") + >>> print dn1 + test.nic.cz. + >>> dn2 = ldns.ldns_dname("nic.cz") + >>> if dn2.is_subdomain(dn1): print dn2, "is sub-domain of", dn1 + >>> if dn1.is_subdomain(dn2): print dn1, "is sub-domain of", dn2 + test.nic.cz. is sub-domain of nic.cz. + + The following two examples show the creation of :class:`ldns_dname` + from :class:`ldns_rdf`. The first shows the creation of + :class:`ldns_dname` instance which is independent of the original + `rdf`. + + + >>> import ldns + >>> rdf = ldns.ldns_rdf.new_frm_str("a.ns.nic.cz", ldns.LDNS_RDF_TYPE_DNAME) + >>> dn = ldns.ldns_dname(rdf) + >>> print dn + a.ns.nic.cz. + + The latter shows the wrapping of a :class:`ldns_rdf` onto + a :class:`ldns_dname` without the creation of a copy. + + >>> import ldns + >>> dn = ldns.ldns_dname(ldns.ldns_rdf.new_frm_str("a.ns.nic.cz", ldns.LDNS_RDF_TYPE_DNAME), clone=False) + >>> print dn + a.ns.nic.cz. """ - def __init__(self, str): - """Creates a new dname rdf from a string. - - :parameter str: str string to use + def __init__(self, initialiser, clone=True): """ - self.this = _ldns.ldns_dname_new_frm_str(str) + Creates a new dname rdf from a string or :class:`ldns_rdf`. + + :param initialiser: string or :class:`ldns_rdf` + :type initialiser: string or :class:`ldns_rdf` containing + a dname + :param clone: Whether to clone or directly grab the parameter. + :type clone: bool + :throws TypeError: When `initialiser` of invalid type. + """ + if isinstance(initialiser, ldns_rdf) and \ + (initialiser.get_type() == _ldns.LDNS_RDF_TYPE_DNAME): + if clone == True: + self.this = _ldns.ldns_rdf_clone(initialiser) + else: + self.this = initialiser + else: + self.this = _ldns.ldns_dname_new_frm_str(initialiser) + + # + # LDNS_DNAME_CONSTRUCTORS_ + # @staticmethod - def new_frm_str(str): - """Creates a new dname rdf instance from a string. - - This static method is equivalent to using of default class constructor. - - :parameter str: str string to use + def new_frm_str(string): """ - return ldns_dname(str) + Creates a new dname rdf instance from a string. + + This static method is equivalent to using default + :class:`ldns_dname` constructor. + + :param string: String to use. + :type string: string + :throws TypeError: When `string` not a string. + :return: (:class:`ldns_dname`) dname rdf. + """ + return ldns_dname(string) + + @staticmethod + def new_frm_rdf(rdf, clone=True): + """ + Creates a new dname rdf instance from a dname :class:`ldns_rdf`. + + This static method is equivalent to using the default + :class:`ldns_dname` constructor. + + :param rdf: A dname :class:`ldns_rdf`. + :type rdf: :class:`ldns_rdf` + :throws TypeError: When `rdf` of inappropriate type. + :param clone: Whether to create a clone or to wrap present + instance. + :type clone: bool + :return: (:class:`ldns_dname`) dname rdf. + """ + return ldns_dname(rdf, clone=clone) + + # + # _LDNS_DNAME_CONSTRUCTORS + # + + def write_to_buffer(self, buffer): + """ + Copies the dname data to the buffer in wire format. + + :param buffer: Buffer to append the result to. + :type param: :class:`ldns_buffer` + :throws TypeError: When `buffer` of non-:class:`ldns_buffer` + type. + :return: (ldns_status) ldns_status + """ + return _ldns.ldns_dname2buffer_wire(buffer, self) + #parameters: ldns_buffer *, const ldns_rdf *, + #retvals: ldns_status + + + # + # LDNS_DNAME_METHODS_ + # def absolute(self): - """Checks whether the given dname string is absolute (i.e. ends with a '.') - - :returns: (bool) True or False """ - return self.endswith(".") + Checks whether the given dname string is absolute (i.e., + ends with a '.'). + :return: (bool) True or False + """ + string = self.__str__() + return _ldns.ldns_dname_str_absolute(string) != 0 def make_canonical(self): - """Put a dname into canonical fmt - ie. lowercase it + """ + Put a dname into canonical format (i.e., convert to lower case). """ _ldns.ldns_dname2canonical(self) - def __cmp__(self,other): - """Compares the two dname rdf's according to the algorithm for ordering in RFC4034 Section 6. - - :param other: - the second dname rdf to compare - :returns: (int) -1 if dname comes before other, 1 if dname comes after other, and 0 if they are equal. + def __cmp__(self, other): """ - return _ldns.ldns_dname_compare(self,other) + Compares two dname rdf according to the algorithm for + ordering in RFC4034 Section 6. + + :param other: The second dname rdf to compare. + :type other: :class:`ldns_dname` + :throws TypeError: When `other` of invalid type. + :return: (int) -1, 0 or 1 if self comes before other, + self is equal or self comes after other respectively. - def write_to_buffer(self,buffer): - """Copies the dname data to the buffer in wire format. - - :param buffer: buffer to append the result to - :returns: (ldns_status) ldns_status + .. note:: + The type checking of parameter `other` is benevolent. + It allows also to pass a dname :class:`ldns_rdf` object. + This will probably change in future. """ - return _ldns.ldns_dname2buffer_wire(buffer,self) - #parameters: ldns_buffer *,const ldns_rdf *, + # + # The wrapped function generates asserts instead of setting + # error status. They cannot be caught from Python so a check + # is necessary. + # + if (not isinstance(other, ldns_dname)) and \ + isinstance(other, ldns_rdf) and \ + other.get_type() == _ldns.LDNS_RDF_TYPE_DNAME: + warnings.warn("The ldns_dname.__cmp__() method will" + + " drop the possibility to compare ldns_rdf." + + " Convert arguments to ldns_dname.", + PendingDeprecationWarning, stacklevel=2) + if not isinstance(other, ldns_rdf): + raise TypeError("Parameter must be derived from ldns_rdf.") + if (other.get_type() != _ldns.LDNS_RDF_TYPE_DNAME): + raise Exception("Operands must be ldns_dname.") + return _ldns.ldns_dname_compare(self, other) + + def __lt__(self, other): + """ + Compares two dname rdf according to the algorithm for + ordering in RFC4034 Section 6. + + :param other: The second dname rdf to compare. + :type other: :class:`ldns_dname` + :throws TypeError: When `other` of invalid type. + :return: (bool) True when `self` is less than 'other'. + + .. note:: + The type checking of parameter `other` is benevolent. + It allows also to pass a dname :class:`ldns_rdf` object. + This will probably change in future. + """ + # + # The wrapped function generates asserts instead of setting + # error status. They cannot be caught from Python so a check + # is necessary. + # + if (not isinstance(other, ldns_dname)) and \ + isinstance(other, ldns_rdf) and \ + other.get_type() == _ldns.LDNS_RDF_TYPE_DNAME: + warnings.warn("The ldns_dname.__lt__() method will" + + " drop the possibility to compare ldns_rdf." + + " Convert arguments to ldns_dname.", + PendingDeprecationWarning, stacklevel=2) + if not isinstance(other, ldns_rdf): + raise TypeError("Parameter must be derived from ldns_rdf.") + if (other.get_type() != _ldns.LDNS_RDF_TYPE_DNAME): + raise Exception("Operands must be ldns_dname.") + return _ldns.ldns_dname_compare(self, other) == -1 + + def __le__(self, other): + """ + Compares two dname rdf according to the algorithm for + ordering in RFC4034 Section 6. + + :param other: The second dname rdf to compare. + :type other: :class:`ldns_dname` + :throws TypeError: When `other` of invalid type. + :return: (bool) True when `self` is less than or equal to + 'other'. + + .. note:: + The type checking of parameter `other` is benevolent. + It allows also to pass a dname :class:`ldns_rdf` object. + This will probably change in future. + """ + # + # The wrapped function generates asserts instead of setting + # error status. They cannot be caught from Python so a check + # is necessary. + # + if (not isinstance(other, ldns_dname)) and \ + isinstance(other, ldns_rdf) and \ + other.get_type() == _ldns.LDNS_RDF_TYPE_DNAME: + warnings.warn("The ldns_dname.__le__() method will" + + " drop the possibility to compare ldns_rdf." + + " Convert arguments to ldns_dname.", + PendingDeprecationWarning, stacklevel=2) + if not isinstance(other, ldns_rdf): + raise TypeError("Parameter must be derived from ldns_rdf.") + if (other.get_type() != _ldns.LDNS_RDF_TYPE_DNAME): + raise Exception("Operands must be ldns_dname.") + return _ldns.ldns_dname_compare(self, other) != 1 + + def __eq__(self, other): + """ + Compares two dname rdf according to the algorithm for + ordering in RFC4034 Section 6. + + :param other: The second dname rdf to compare. + :type other: :class:`ldns_dname` + :throws TypeError: When `other` of invalid type. + :return: (bool) True when `self` is equal to 'other'. + + .. note:: + The type checking of parameter `other` is benevolent. + It allows also to pass a dname :class:`ldns_rdf` object. + This will probably change in future. + """ + # + # The wrapped function generates asserts instead of setting + # error status. They cannot be caught from Python so a check + # is necessary. + # + if (not isinstance(other, ldns_dname)) and \ + isinstance(other, ldns_rdf) and \ + other.get_type() == _ldns.LDNS_RDF_TYPE_DNAME: + warnings.warn("The ldns_dname.__eq__() method will" + + " drop the possibility to compare ldns_rdf." + + " Convert arguments to ldns_dname.", + PendingDeprecationWarning, stacklevel=2) + if not isinstance(other, ldns_rdf): + raise TypeError("Parameter must be derived from ldns_rdf.") + if (other.get_type() != _ldns.LDNS_RDF_TYPE_DNAME): + raise Exception("Operands must be ldns_dname.") + return _ldns.ldns_dname_compare(self, other) == 0 + + def __ne__(self, other): + """ + Compares two dname rdf according to the algorithm for + ordering in RFC4034 Section 6. + + :param other: The second dname rdf to compare. + :type other: :class:`ldns_dname` + :throws TypeError: When `other` of invalid type. + :return: (bool) True when `self` is not equal to 'other'. + + .. note:: + The type checking of parameter `other` is benevolent. + It allows also to pass a dname :class:`ldns_rdf` object. + This will probably change in future. + """ + # + # The wrapped function generates asserts instead of setting + # error status. They cannot be caught from Python so a check + # is necessary. + # + if (not isinstance(other, ldns_dname)) and \ + isinstance(other, ldns_rdf) and \ + other.get_type() == _ldns.LDNS_RDF_TYPE_DNAME: + warnings.warn("The ldns_dname.__ne__() method will" + + " drop the possibility to compare ldns_rdf." + + " Convert arguments to ldns_dname.", + PendingDeprecationWarning, stacklevel=2) + if not isinstance(other, ldns_rdf): + raise TypeError("Parameter must be derived from ldns_rdf.") + if (other.get_type() != _ldns.LDNS_RDF_TYPE_DNAME): + raise Exception("Operands must be ldns_dname.") + return _ldns.ldns_dname_compare(self, other) != 0 + + def __gt__(self, other): + """ + Compares two dname rdf according to the algorithm for + ordering in RFC4034 Section 6. + + :param other: The second dname rdf to compare. + :type other: :class:`ldns_dname` + :throws TypeError: When `other` of invalid type. + :return: (bool) True when `self` is greater than 'other'. + + .. note:: + The type checking of parameter `other` is benevolent. + It allows also to pass a dname :class:`ldns_rdf` object. + This will probably change in future. + """ + # + # The wrapped function generates asserts instead of setting + # error status. They cannot be caught from Python so a check + # is necessary. + # + if (not isinstance(other, ldns_dname)) and \ + isinstance(other, ldns_rdf) and \ + other.get_type() == _ldns.LDNS_RDF_TYPE_DNAME: + warnings.warn("The ldns_dname.__gt__() method will" + + " drop the possibility to compare ldns_rdf." + + " Convert arguments to ldns_dname.", + PendingDeprecationWarning, stacklevel=2) + if not isinstance(other, ldns_rdf): + raise TypeError("Parameter must be derived from ldns_rdf.") + if (other.get_type() != _ldns.LDNS_RDF_TYPE_DNAME): + raise Exception("Operands must be ldns_dname.") + return _ldns.ldns_dname_compare(self, other) == 1 + + def __ge__(self, other): + """ + Compares two dname rdf according to the algorithm for + ordering in RFC4034 Section 6. + + :param other: The second dname rdf to compare. + :type other: :class:`ldns_dname` + :throws TypeError: When `other` of invalid type. + :return: (bool) True when `self` is greater than or equal to + 'other'. + + .. note:: + The type checking of parameter `other` is benevolent. + It allows also to pass a dname :class:`ldns_rdf` object. + This will probably change in future. + """ + # + # The wrapped function generates asserts instead of setting + # error status. They cannot be caught from Python so a check + # is necessary. + # + if (not isinstance(other, ldns_dname)) and \ + isinstance(other, ldns_rdf) and \ + other.get_type() == _ldns.LDNS_RDF_TYPE_DNAME: + warnings.warn("The ldns_dname.__ge__() method will" + + " drop the possibility to compare ldns_rdf." + + " Convert arguments to ldns_dname.", + PendingDeprecationWarning, stacklevel=2) + if not isinstance(other, ldns_rdf): + raise TypeError("Parameter must be derived from ldns_rdf.") + if (other.get_type() != _ldns.LDNS_RDF_TYPE_DNAME): + raise Exception("Operands must be ldns_dname.") + return _ldns.ldns_dname_compare(self, other) != -1 + + def cat(self, rd2): + """ + Concatenates rd2 after this dname (`rd2` is copied, + `this` dname is modified). + + :param rd2: The right-hand side. + :type rd2: :class:`ldns_dname` + :throws TypeError: When `rd2` of invalid type. + :return: (ldns_status) LDNS_STATUS_OK on success + + .. note:: + The type checking of parameter `rd2` is benevolent. + It allows also to pass a dname :class:`ldns_rdf` object. + This will probably change in future. + """ + if (not isinstance(rd2, ldns_dname)) and \ + isinstance(rd2, ldns_rdf) and \ + rd2.get_type() == _ldns.LDNS_RDF_TYPE_DNAME: + warnings.warn("The ldns_dname.cat() method will" + + " drop the support of ldns_rdf." + + " Convert arguments to ldns_dname.", + PendingDeprecationWarning, stacklevel=2) + return _ldns.ldns_dname_cat(self, rd2) + #parameters: ldns_rdf *, ldns_rdf *, #retvals: ldns_status - #LDNS_DNAME_METHODS_# - - def cat(self,rd2): - """concatenates rd2 after this dname (rd2 is copied, this dname is modified) - - :param rd2: - the rightside - :returns: (ldns_status) LDNS_STATUS_OK on success + def cat_clone(self, rd2): """ - return _ldns.ldns_dname_cat(self,rd2) - #parameters: ldns_rdf *,ldns_rdf *, - #retvals: ldns_status - - def cat_clone(self,rd2): - """concatenates two dnames together + Concatenates two dnames together. - :param rd2: - the rightside - :returns: (ldns_rdf \*) a new rdf with leftside/rightside + :param rd2: The right-hand side. + :type rd2: :class:`ldns_dname` + :throws TypeError: When `rd2` of invalid type. + :return: (:class:`ldns_dname`) A new rdf with + left-hand side + right-hand side content None when + error. + + .. note:: + The type checking of parameter `rd2` is benevolent. + It allows also to pass a dname :class:`ldns_rdf` object. + This will probably change in future. """ - return _ldns.ldns_dname_cat_clone(self,rd2) - #parameters: const ldns_rdf *,const ldns_rdf *, + if (not isinstance(rd2, ldns_dname)) and \ + isinstance(rd2, ldns_rdf) and \ + rd2.get_type() == _ldns.LDNS_RDF_TYPE_DNAME: + warnings.warn("The ldns_dname.cat_clone() method will" + + " drop the support of ldns_rdf." + + " Convert arguments to ldns_dname.", + PendingDeprecationWarning, stacklevel=2) + ret = _ldns.ldns_dname_cat_clone(self, rd2) + if ret != None: + ret = ldns_dname(ret, clone=False) + return ret + #parameters: const ldns_rdf *, const ldns_rdf *, #retvals: ldns_rdf * - def interval(self,middle,next): - """check if middle lays in the interval defined by prev and next prev <= middle < next. - - This is usefull for nsec checking - - :param middle: - the dname to check - :param next: - the next dname return 0 on error or unknown, -1 when middle is in the interval, +1 when not - :returns: (int) + def interval(self, middle, next): """ - return _ldns.ldns_dname_interval(self,middle,next) - #parameters: const ldns_rdf *,const ldns_rdf *,const ldns_rdf *, + Check whether `middle` lays in the interval defined by + `this` and `next` (`this` <= `middle` < `next`). + + This method is useful for nsec checking. + + :param middle: The dname to check. + :type middle: :class:`ldns_dname` + :param next: The boundary. + :type next: :class:`ldns_dname` + :throws TypeError: When `middle` or `next` of + non-:class:`ldns_rdf` type. + :throws Exception: When non-dname rdfs compared. + :return: (int) 0 on error or unknown, + -1 when middle is in the interval, 1 when not. + + .. note:: + The type checking of parameters is benevolent. + It allows also to pass a dname :class:`ldns_rdf` object. + This will probably change in future. + """ + # + # The wrapped function generates asserts instead of setting + # error status. They cannot be caught from Python so a check + # is necessary. + # + if (not isinstance(middle, ldns_rdf)) or \ + (not isinstance(next, ldns_rdf)): + raise TypeError("Parameters must be derived from ldns_dname.") + if (self.get_type() != _ldns.LDNS_RDF_TYPE_DNAME) or \ + (middle.get_type() != _ldns.LDNS_RDF_TYPE_DNAME) or \ + (next.get_type() != _ldns.LDNS_RDF_TYPE_DNAME): + raise Exception("All operands must be dname rdfs.") + if (not isinstance(middle, ldns_dname)) or \ + (not isinstance(next, ldns_dname)): + warnings.warn("The ldns_dname.interval() method will" + + " drop the possibility to compare ldns_rdf." + + " Convert arguments to ldns_dname.", + PendingDeprecationWarning, stacklevel=2) + return _ldns.ldns_dname_interval(self, middle, next) + #parameters: const ldns_rdf *, const ldns_rdf *, const ldns_rdf *, #retvals: int - def is_subdomain(self,parent): - """Tests wether the name sub falls under parent (i.e. is a subdomain of parent). + def is_subdomain(self, parent): + """ + Tests whether the name of the instance falls under + `parent` (i.e., is a sub-domain of `parent`). This function will return false if the given dnames are equal. - :param parent: - (ldns_rdf) the parent's name - :returns: (bool) true if sub falls under parent, otherwise false + :param parent: The parent's name. + :type parent: :class:`ldns_dname` + :throws TypeError: When `parent` of non-:class:`ldns_rdf` + or derived type. + :return: (bool) True if `this` falls under `parent`, otherwise + False. + + .. note:: + The type checking of parameters is benevolent. + It allows also to pass a dname :class:`ldns_rdf` object. + This will probably change in future. """ - return _ldns.ldns_dname_is_subdomain(self,parent) - #parameters: const ldns_rdf *,const ldns_rdf *, + if (not isinstance(parent, ldns_dname)) and \ + isinstance(parent, ldns_rdf) and \ + parent.get_type() == _ldns.LDNS_RDF_TYPE_DNAME: + warnings.warn("The ldns_dname.is_subdomain() method will" + + " drop the support of ldns_rdf." + + " Convert arguments to ldns_dname.", + PendingDeprecationWarning, stacklevel=2) + return _ldns.ldns_dname_is_subdomain(self, parent) + #parameters: const ldns_rdf *, const ldns_rdf *, #retvals: bool - def label(self,labelpos): - """look inside the rdf and if it is an LDNS_RDF_TYPE_DNAME try and retrieve a specific label. + def label(self, labelpos): + """ + Look inside the rdf and retrieve a specific label. The labels are numbered starting from 0 (left most). - - :param labelpos: - return the label with this number - :returns: (ldns_rdf \*) a ldns_rdf* with the label as name or NULL on error + + :param labelpos: Index of the label. (Labels are numbered + 0, which is the left most.) + :type labelpos: integer + :throws TypeError: When `labelpos` of non-integer type. + :return: (:class:`ldns_dname`) A new rdf with the label + as name or None on error. """ - return _ldns.ldns_dname_label(self,labelpos) - #parameters: const ldns_rdf *,uint8_t, + ret = _ldns.ldns_dname_label(self, labelpos) + if ret != None: + ret = ldns_dname(ret, clone=False) + return ret + #parameters: const ldns_rdf *, uint8_t, #retvals: ldns_rdf * def label_count(self): - """count the number of labels inside a LDNS_RDF_DNAME type rdf. + """ + Counts the number of labels. - :returns: (uint8_t) the number of labels + :return: (uint8_t) the number of labels. Will return 0 + if not a dname. """ return _ldns.ldns_dname_label_count(self) #parameters: const ldns_rdf *, #retvals: uint8_t def left_chop(self): - """chop one label off the left side of a dname. - - so wwww.nlnetlabs.nl, becomes nlnetlabs.nl - - :returns: (ldns_rdf \*) the remaining dname """ - return _ldns.ldns_dname_left_chop(self) + Chop one label off the left side of a dname. + + (e.g., wwww.nlnetlabs.nl, becomes nlnetlabs.nl) + + :return: (:class:`ldns_dname`) The remaining dname or None + when error. + """ + return ldns_dname(_ldns.ldns_dname_left_chop(self), clone=False) #parameters: const ldns_rdf *, #retvals: ldns_rdf * def reverse(self): - """Returns a clone of the given dname with the labels reversed. - - :returns: (ldns_rdf \*) clone of the dname with the labels reversed. """ - return _ldns.ldns_dname_reverse(self) + Returns a clone of the given dname with the labels reversed. + + :return: (:class:`ldns_dname`) A clone of the dname with + the labels reversed. + """ + return ldns_dname(_ldns.ldns_dname_reverse(self), clone=False) #parameters: const ldns_rdf *, #retvals: ldns_rdf * - #_LDNS_DNAME_METHODS# + # + # _LDNS_DNAME_METHODS + # %} - diff --git a/contrib/python/ldns_dnssec.i b/contrib/python/ldns_dnssec.i index 6c065648466..3c29bb4406c 100644 --- a/contrib/python/ldns_dnssec.i +++ b/contrib/python/ldns_dnssec.i @@ -247,6 +247,29 @@ ldns_status ldns_dnssec_zone_sign_defcb(ldns_dnssec_zone *zone, ldns_rr_list *ne return ldns_dnssec_zone_sign(zone, new_rrs, key_list, ldns_dnssec_default_replace_signatures, NULL); } + +ldns_status ldns_dnssec_zone_add_rr_(ldns_dnssec_zone *zone, ldns_rr *rr) +{ + ldns_rr *new_rr; + ldns_status status; + + new_rr = ldns_rr_clone(rr); + + /* + * A clone of the RR is created to be stored in the DNSSEC zone. + * The Python engine frees a RR object as soon it's reference count + * reaches zero. The code must avoid double freeing or accessing of freed + * memory. + */ + + status = ldns_dnssec_zone_add_rr(zone, new_rr); + + if (status != LDNS_STATUS_OK) { + ldns_rr_free(new_rr); + } + + return status; +} %} %extend ldns_dnssec_zone { @@ -413,7 +436,7 @@ ldns_status ldns_dnssec_zone_sign_defcb(ldns_dnssec_zone *zone, ldns_rr_list *ne The RR to add :returns: (ldns_status) LDNS_STATUS_OK on success, an error code otherwise """ - return _ldns.ldns_dnssec_zone_add_rr(self,rr) + return _ldns.ldns_dnssec_zone_add_rr_(self,rr) #parameters: ldns_dnssec_zone *,ldns_rr *, #retvals: ldns_status diff --git a/contrib/python/ldns_packet.i b/contrib/python/ldns_packet.i index a1ad6b7c821..9316479f13b 100644 --- a/contrib/python/ldns_packet.i +++ b/contrib/python/ldns_packet.i @@ -217,7 +217,7 @@ This simple example instances a resolver in order to resolve NS for nic.cz. def opcode2str(self): """Converts a packet opcode to its mnemonic and returns that as an allocated null-terminated string.""" - return _ldns.ldns_pkt_opcode2str(sefl.get_opcode()) + return _ldns.ldns_pkt_opcode2str(self.get_opcode()) def rcode2str(self): """Converts a packet rcode to its mnemonic and returns that as an allocated null-terminated string.""" diff --git a/contrib/python/ldns_rdf.i b/contrib/python/ldns_rdf.i index 5a7e3007964..edff4d62499 100644 --- a/contrib/python/ldns_rdf.i +++ b/contrib/python/ldns_rdf.i @@ -1,5 +1,5 @@ /****************************************************************************** - * ldns_rdata.i: LDNS record data + * ldns_rdf.i: LDNS record data * * Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz) * Karel Slany (slany AT fit.vutbr.cz) @@ -14,8 +14,8 @@ * 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 organization nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 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 @@ -28,399 +28,815 @@ * 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. - ******************************************************************************/ + *****************************************************************************/ -//automatic conversion of const ldns_rdf* parameter from string -%typemap(in,noblock=1) const ldns_rdf * (void* argp, $1_ltype tmp = 0, int res) { - if (Python_str_Check($input)) { -#ifdef SWIG_Python_str_AsChar - tmp = ldns_dname_new_frm_str(SWIG_Python_str_AsChar($input)); -#else - tmp = ldns_dname_new_frm_str(PyString_AsString($input)); -#endif - if (tmp == NULL) { - %argument_fail(SWIG_TypeError, "char *", $symname, $argnum); - } - $1 = ($1_ltype) tmp; - } else { - res = SWIG_ConvertPtr($input, &argp, SWIGTYPE_p_ldns_struct_rdf, 0 | 0 ); - if (!SWIG_IsOK(res)) { - %argument_fail(res, "ldns_rdf const *", $symname, $argnum); - } - $1 = ($1_ltype) argp; - } -} -%typemap(in,numinputs=0,noblock=1) (ldns_rdf **) +/* ========================================================================= */ +/* SWIG setting and definitions. */ +/* ========================================================================= */ + +/* Creates a temporary instance of (ldns_rdf *). */ +%typemap(in, numinputs=0, noblock=1) (ldns_rdf **) { - ldns_rdf *$1_rdf; - $1 = &$1_rdf; + ldns_rdf *$1_rdf = NULL; + $1 = &$1_rdf; } -// result generation -%typemap(argout,noblock=1) (ldns_rdf **) +/* Result generation, appends (ldns_rdf *) after the result. */ +%typemap(argout, noblock=1) (ldns_rdf **) { - $result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(SWIG_as_voidptr($1_rdf), SWIGTYPE_p_ldns_struct_rdf, SWIG_POINTER_OWN | 0 )); + $result = SWIG_Python_AppendOutput($result, + SWIG_NewPointerObj(SWIG_as_voidptr($1_rdf), + SWIGTYPE_p_ldns_struct_rdf, SWIG_POINTER_OWN | 0)); } -%nodefaultctor ldns_struct_rdf; //no default constructor & destructor -%nodefaultdtor ldns_struct_rdf; +/* + * Automatic conversion of const (ldns_rdf *) parameter from string. + * Argument default value. + */ +%typemap(arginit, noblock=1) const ldns_rdf * +{ + char *$1_str = NULL; +} + +/* + * Automatic conversion of const (ldns_rdf *) parameter from string. + * Preparation of arguments. + */ +%typemap(in, noblock=1) const ldns_rdf * (void* argp, $1_ltype tmp = 0, int res) +{ + if (Python_str_Check($input)) { + $1_str = SWIG_Python_str_AsChar($input); + if ($1_str == NULL) { + %argument_fail(SWIG_TypeError, "char *", $symname, $argnum); + } + tmp = ldns_dname_new_frm_str($1_str); + if (tmp == NULL) { + %argument_fail(SWIG_TypeError, "char *", $symname, $argnum); + } + $1 = ($1_ltype) tmp; + } else { + res = SWIG_ConvertPtr($input, &argp, SWIGTYPE_p_ldns_struct_rdf, 0 | 0); + if (!SWIG_IsOK(res)) { + %argument_fail(res, "ldns_rdf const *", $symname, $argnum); + } + $1 = ($1_ltype) argp; + } +} + +/* + * Automatic conversion of const (ldns_rdf *) parameter from string. + * Freeing of allocated memory (in Python 3 when daling with strings). + */ +%typemap(freearg, noblock=1) const ldns_rdf * +{ + if ($1_str != NULL) { + /* Is not NULL only when a conversion form string occurred. */ + SWIG_Python_str_DelForPy3($1_str); /* Is a empty macro for Python < 3. */ + } +} + +%nodefaultctor ldns_struct_rdf; /* No default constructor. */ +%nodefaultdtor ldns_struct_rdf; /* No default destructor. */ + + +/* + * This file must contain all %newobject and %delobject tags also for + * ldns_dname. This is because the ldns_dname is a derived class from ldns_rdf. + */ -%newobject ldns_dname_new; -%newobject ldns_dname_new_frm_str; -%newobject ldns_dname_new_frm_data; %newobject ldns_rdf_new; %newobject ldns_rdf_new_frm_str; %newobject ldns_rdf_new_frm_data; +%newobject ldns_rdf_address_reverse; +%newobject ldns_rdf_clone; +%newobject ldns_rdf2str; + +%newobject ldns_dname_new; +%newobject ldns_dname_new_frm_str; +%newobject ldns_dname_new_frm_data; + +%newobject ldns_dname_cat_clone; +%newobject ldns_dname_label; +%newobject ldns_dname_left_chop; +%newobject ldns_dname_reverse; + %delobject ldns_rdf_deep_free; %delobject ldns_rdf_free; + +/* + * Should the ldns_rdf_new() also be marked as deleting its data parameter? + */ +%delobject ldns_rdf_set_data; /* Because data are directly coupled into rdf. */ + %rename(ldns_rdf) ldns_struct_rdf; -%inline %{ -const char *ldns_rdf_type2str(const ldns_rdf *rdf) -{ - if (rdf) { - switch(ldns_rdf_get_type(rdf)) { - case LDNS_RDF_TYPE_NONE: return 0; - case LDNS_RDF_TYPE_DNAME: return "DNAME"; - case LDNS_RDF_TYPE_INT8: return "INT8"; - case LDNS_RDF_TYPE_INT16: return "INT16"; - case LDNS_RDF_TYPE_INT32: return "INT32"; - case LDNS_RDF_TYPE_PERIOD: return "PERIOD"; - case LDNS_RDF_TYPE_TSIGTIME: return "TSIGTIME"; - case LDNS_RDF_TYPE_A: return "A"; - case LDNS_RDF_TYPE_AAAA: return "AAAA"; - case LDNS_RDF_TYPE_STR: return "STR"; - case LDNS_RDF_TYPE_APL: return "APL"; - case LDNS_RDF_TYPE_B32_EXT: return "B32_EXT"; - case LDNS_RDF_TYPE_B64: return "B64"; - case LDNS_RDF_TYPE_HEX: return "HEX"; - case LDNS_RDF_TYPE_NSEC: return "NSEC"; - case LDNS_RDF_TYPE_NSEC3_SALT: return "NSEC3_SALT"; - case LDNS_RDF_TYPE_TYPE: return "TYPE"; - case LDNS_RDF_TYPE_CLASS: return "CLASS"; - case LDNS_RDF_TYPE_CERT_ALG: return "CER_ALG"; - case LDNS_RDF_TYPE_ALG: return "ALG"; - case LDNS_RDF_TYPE_UNKNOWN: return "UNKNOWN"; - case LDNS_RDF_TYPE_TIME: return "TIME"; - case LDNS_RDF_TYPE_LOC: return "LOC"; - case LDNS_RDF_TYPE_WKS: return "WKS"; - case LDNS_RDF_TYPE_SERVICE: return "SERVICE"; - case LDNS_RDF_TYPE_NSAP: return "NSAP"; - case LDNS_RDF_TYPE_ATMA: return "ATMA"; - case LDNS_RDF_TYPE_IPSECKEY: return "IPSECKEY"; - case LDNS_RDF_TYPE_TSIG: return "TSIG"; - case LDNS_RDF_TYPE_INT16_DATA: return "INT16_DATA"; - case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER: return "NSEC3_NEXT_OWNER"; - } - } - return 0; -} -%} +/* ========================================================================= */ +/* Debugging related code. */ +/* ========================================================================= */ #ifdef LDNS_DEBUG %rename(__ldns_rdf_deep_free) ldns_rdf_deep_free; %rename(__ldns_rdf_free) ldns_rdf_free; -%inline %{ -void _ldns_rdf_free (ldns_rdf* r) { - printf("******** LDNS_RDF free 0x%lX ************\n", (long unsigned int)r); - ldns_rdf_free(r); -} +%inline +%{ + /*! + * @brief Prints information about deallocated rdf and deallocates. + */ + void _ldns_rdf_deep_free (ldns_rdf *r) + { + printf("******** LDNS_RDF deep free 0x%lX ************\n", + (long unsigned int) r); + ldns_rdf_deep_free(r); + } + + /*! + * @brief Prints information about deallocated rdf and deallocates. + */ + void _ldns_rdf_free (ldns_rdf* r) + { + printf("******** LDNS_RDF free 0x%lX ************\n", + (long unsigned int) r); + ldns_rdf_free(r); + } %} -#else +#else /* !LDNS_DEBUG */ %rename(_ldns_rdf_deep_free) ldns_rdf_deep_free; %rename(_ldns_rdf_free) ldns_rdf_free; -#endif +#endif /* LDNS_DEBUG */ -%newobject ldns_rdf2str; +/* ========================================================================= */ +/* Added C code. */ +/* ========================================================================= */ + + +%inline +%{ + /*! + * @brief returns a human readable string containing rdf type. + */ + const char *ldns_rdf_type2str(const ldns_rdf *rdf) + { + if (rdf) { + switch(ldns_rdf_get_type(rdf)) { + case LDNS_RDF_TYPE_NONE: return 0; + case LDNS_RDF_TYPE_DNAME: return "DNAME"; + case LDNS_RDF_TYPE_INT8: return "INT8"; + case LDNS_RDF_TYPE_INT16: return "INT16"; + case LDNS_RDF_TYPE_INT32: return "INT32"; + case LDNS_RDF_TYPE_A: return "A"; + case LDNS_RDF_TYPE_AAAA: return "AAAA"; + case LDNS_RDF_TYPE_STR: return "STR"; + case LDNS_RDF_TYPE_APL: return "APL"; + case LDNS_RDF_TYPE_B32_EXT: return "B32_EXT"; + case LDNS_RDF_TYPE_B64: return "B64"; + case LDNS_RDF_TYPE_HEX: return "HEX"; + case LDNS_RDF_TYPE_NSEC: return "NSEC"; + case LDNS_RDF_TYPE_TYPE: return "TYPE"; + case LDNS_RDF_TYPE_CLASS: return "CLASS"; + case LDNS_RDF_TYPE_CERT_ALG: return "CER_ALG"; + case LDNS_RDF_TYPE_ALG: return "ALG"; + case LDNS_RDF_TYPE_UNKNOWN: return "UNKNOWN"; + case LDNS_RDF_TYPE_TIME: return "TIME"; + case LDNS_RDF_TYPE_PERIOD: return "PERIOD"; + case LDNS_RDF_TYPE_TSIGTIME: return "TSIGTIME"; + case LDNS_RDF_TYPE_TSIG: return "TSIG"; + case LDNS_RDF_TYPE_INT16_DATA: return "INT16_DATA"; + case LDNS_RDF_TYPE_SERVICE: return "SERVICE"; + case LDNS_RDF_TYPE_LOC: return "LOC"; + case LDNS_RDF_TYPE_WKS: return "WKS"; + case LDNS_RDF_TYPE_NSAP: return "NSAP"; + case LDNS_RDF_TYPE_ATMA: return "ATMA"; + case LDNS_RDF_TYPE_IPSECKEY: return "IPSECKEY"; + case LDNS_RDF_TYPE_NSEC3_SALT: return "NSEC3_SALT"; + case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER: + return "NSEC3_NEXT_OWNER"; + } + } + return 0; + } +%} + + +/* ========================================================================= */ +/* Encapsulating Python code. */ +/* ========================================================================= */ %feature("docstring") ldns_struct_rdf "Resource record data field. -The data is a network ordered array of bytes, which size is specified by the (16-bit) size field. To correctly parse it, use the type specified in the (16-bit) type field with a value from ldns_rdf_type." +The data is a network ordered array of bytes, which size is specified +by the (16-bit) size field. To correctly parse it, use the type +specified in the (16-bit) type field with a value from ldns_rdf_type." %extend ldns_struct_rdf { - %pythoncode %{ + %pythoncode + %{ def __init__(self): - raise Exception("This class can't be created directly. Please use: ldns_rdf_new, ldns_rdf_new_frm_data, ldns_rdf_new_frm_str, ldns_rdf_new_frm_fp, ldns_rdf_new_frm_fp_l") + """ + Cannot be created directly from Python. + """ + raise Exception("This class can't be created directly. " + + "Please use: ldns_rdf_new, ldns_rdf_new_frm_data, " + + "ldns_rdf_new_frm_str, ldns_rdf_new_frm_fp, " + + "ldns_rdf_new_frm_fp_l") __swig_destroy__ = _ldns._ldns_rdf_deep_free - #LDNS_RDF_CONSTRUCTORS_# + # + # LDNS_RDF_CONSTRUCTORS_ + # + @staticmethod - def new_frm_str(str, rr_type, raiseException = True): - """Creates a new rdf from a string of a given type. + def new_frm_str(string, rr_type, raiseException = True): + """ + Creates a new rdf from a string of a given type. - :param str: string to use - :param rr_type: the type of RDF. See predefined `RDF_TYPE_` constants - :param raiseException: if True, an exception occurs in case a RDF object can't be created - :returns: RDF object or None. If the object can't be created and raiseException is True, an exception occurs. + :param string: string to use + :type string: string + :param rr_type: The type of the rdf. See predefined `RDF_TYPE_` + constants. + :type rr_type: integer + :param raiseException: If True, an exception occurs in case + a RDF object can't be created. + :type raiseException: bool + :throws TypeError: When parameters of mismatching types. + :throws Exception: When raiseException set and rdf couldn't + be created. + :return: :class:`ldns_rdf` object or None. If the object + can't be created and `raiseException` is True, + an exception occurs. **Usage** - >>> rdf = ldns.ldns_rdf.new_frm_str("74.125.43.99",ldns.LDNS_RDF_TYPE_A) - >>> print rdf, rdf.get_type_str() - A 74.125.43.99 - >>> name = ldns.ldns_resolver.new_frm_file().get_name_by_addr(rdf) - >>> if (name): print name - 99.43.125.74.in-addr.arpa. 85277 IN PTR bw-in-f99.google.com. + + >>> rdf = ldns.ldns_rdf.new_frm_str("74.125.43.99", ldns.LDNS_RDF_TYPE_A) + >>> print rdf, rdf.get_type_str() + A 74.125.43.99 + >>> name = ldns.ldns_resolver.new_frm_file().get_name_by_addr(rdf) + >>> if (name): print name + 99.43.125.74.in-addr.arpa. 85277 IN PTR bw-in-f99.google.com. """ - rr = _ldns.ldns_rdf_new_frm_str(rr_type, str) - if not rr: - if (raiseException): raise Exception("Can't create query packet, error: %d" % status) + rr = _ldns.ldns_rdf_new_frm_str(rr_type, string) + if (not rr) and raiseException: + raise Exception("Can't create query packet, " + + "error: %d" % status) return rr - #_LDNS_RDF_CONSTRUCTORS# + + # + # _LDNS_RDF_CONSTRUCTORS + # def __str__(self): - """Converts the rdata field to presentation format""" + """ + Converts the rdata field to presentation format. + """ return _ldns.ldns_rdf2str(self) - def __cmp__(self,other): - """compares two rdf's on their wire formats. - - (To order dnames according to rfc4034, use ldns_dname_compare) - - :param other: - the second one RDF - :returns: (int) 0 if equal -1 if self comes before other +1 if other comes before self + def __cmp__(self, other): """ - return _ldns.ldns_rdf_compare(self,other) - - def print_to_file(self,output): - """Prints the data in the rdata field to the given file stream (in presentation format).""" - _ldns.ldns_rdf_print(output,self) + Compares two rdfs on their wire formats. + + (To order dnames according to rfc4034, use ldns_dname_compare.) + + :param other: The second one RDF. + :type other: :class:`ldns_rdf` + :throws TypeError: When `other` of non-:class:`ldns_rdf` type. + :return: (int) -1, 0 or 1 if self comes before other, + is equal or self comes after other respectively. + """ + return _ldns.ldns_rdf_compare(self, other) + + def __lt__(self, other): + """ + Compares two rdfs on their formats. + + :param other: The socond one RDF. + :type other: :class:`ldns_rdf` + :throws TypeError: When `other` of non-:class:`ldns_rdf` type. + :return: (bool) True when `self` is less than 'other'. + """ + return _ldns.ldns_rdf_compare(self, other) == -1 + + def __le__(self, other): + """ + Compares two rdfs on their formats. + + :param other: The socond one RDF. + :type other: :class:`ldns_rdf` + :throws TypeError: When `other` of non-:class:`ldns_rdf` type. + :return: (bool) True when `self` is less than or equal to + 'other'. + """ + return _ldns.ldns_rdf_compare(self, other) != 1 + + def __eq__(self, other): + """ + Compares two rdfs on their formats. + + :param other: The socond one RDF. + :type other: :class:`ldns_rdf` + :throws TypeError: When `other` of non-:class:`ldns_rdf` type. + :return: (bool) True when `self` is equal to 'other'. + """ + return _ldns.ldns_rdf_compare(self, other) == 0 + + def __ne__(self, other): + """ + Compares two rdfs on their formats. + + :param other: The socond one RDF. + :type other: :class:`ldns_rdf` + :throws TypeError: When `other` of non-:class:`ldns_rdf` type. + :return: (bool) True when `self` is not equal to 'other'. + """ + return _ldns.ldns_rdf_compare(self, other) != 0 + + def __gt__(self, other): + """ + Compares two rdfs on their formats. + + :param other: The socond one RDF. + :type other: :class:`ldns_rdf` + :throws TypeError: When `other` of non-:class:`ldns_rdf` type. + :return: (bool) True when `self` is greater than 'other'. + """ + return _ldns.ldns_rdf_compare(self, other) == 1 + + def __ge__(self, other): + """ + Compares two rdfs on their formats. + + :param other: The socond one RDF. + :type other: :class:`ldns_rdf` + :throws TypeError: When `other` of non-:class:`ldns_rdf` type. + :return: (bool) True when `self` is greater than or equal to + 'other'. + """ + return _ldns.ldns_rdf_compare(self, other) != -1 + + def print_to_file(self, output): + """ + Prints the data in the rdata field to the given `output` file + stream (in presentation format). + """ + _ldns.ldns_rdf_print(output, self) def get_type_str(self): - """Converts type to string""" + """ + Returns the type of the rdf as a human readable string. + + :return: String containing rdf type. + """ return ldns_rdf_type2str(self) def write_to_buffer(self, buffer): - """Copies the rdata data to the buffer in wire format. + """ + Copies the rdata data to the buffer in wire format. - :param buffer: buffer to append the result to - :returns: (ldns_status) ldns_status + :param buffer: Buffer to append the rdf to. + :type param: :class:`ldns_buffer` + :throws TypeError: When `buffer` of non-:class:`ldns_buffer` + type. + :return: (ldns_status) ldns_status """ return _ldns.ldns_rdf2buffer_wire(buffer, self) - #parameters: ldns_buffer *,const ldns_rdf *, + #parameters: ldns_buffer *, const ldns_rdf *, #retvals: ldns_status def write_to_buffer_canonical(self, buffer): - """Copies the rdata data to the buffer in wire format If the rdata is a dname, the letters will be lowercased during the conversion. + """ + Copies the rdata data to the buffer in wire format. + If the rdata is a dname, the letters will be converted + to lower case during the conversion. - :param buffer: LDNS buffer - :returns: (ldns_status) ldns_status + :param buffer: LDNS buffer. + :type buffer: :class:`ldns_buffer` + :throws TypeError: When `buffer` of non-:class:`ldns_buffer` + type. + :return: (ldns_status) ldns_status """ return _ldns.ldns_rdf2buffer_wire_canonical(buffer, self) - #parameters: ldns_buffer *,const ldns_rdf *, + #parameters: ldns_buffer *, const ldns_rdf *, #retvals: ldns_status - #LDNS_RDF_METHODS_# + # + # LDNS_RDF_METHODS_ + # + def address_reverse(self): - """reverses an rdf, only actually useful for AAAA and A records. + """ + Reverses an rdf, only actually useful for AAAA and A records. The returned rdf has the type LDNS_RDF_TYPE_DNAME! - :returns: (ldns_rdf \*) the reversed rdf (a newly created rdf) + :return: (:class:`ldns_rdf`) The reversed rdf + (a newly created rdf). """ return _ldns.ldns_rdf_address_reverse(self) #parameters: ldns_rdf *, #retvals: ldns_rdf * def clone(self): - """clones a rdf structure. + """ + Clones a rdf structure. - The data is copied. + The data are copied. - :returns: (ldns_rdf \*) a new rdf structure + :return: (:class:`ldns_rdf`) A new rdf structure. """ return _ldns.ldns_rdf_clone(self) #parameters: const ldns_rdf *, #retvals: ldns_rdf * def data(self): - """returns the data of the rdf. + """ + Returns the data of the rdf. - :returns: (uint8_t \*) uint8_t* pointer to the rdf's data + :return: (uint8_t \*) uint8_t* pointer to the rdf's data. """ return _ldns.ldns_rdf_data(self) #parameters: const ldns_rdf *, #retvals: uint8_t * def get_type(self): - """returns the type of the rdf. + """ + Returns the type of the rdf. - We need to insert _get_ here to prevent conflict the the rdf_type TYPE. + We need to prepend the prefix get_ here to prevent conflict + with the rdf_type TYPE. - :returns: (ldns_rdf_type) ldns_rdf_type with the type + :return: (ldns_rdf_type) Identifier of the type. """ return _ldns.ldns_rdf_get_type(self) #parameters: const ldns_rdf *, #retvals: ldns_rdf_type - def set_data(self,data): - """sets the size of the rdf. - - :param data: + def set_data(self, data): """ - _ldns.ldns_rdf_set_data(self,data) - #parameters: ldns_rdf *,void *, + Sets the data portion of the rdf. + + The data are not copied, but are assigned to the rdf, + `data` are decoupled from the Python engine. + + :param data: Data to be set. + :type data: void \* + """ + _ldns.ldns_rdf_set_data(self, data) + #parameters: ldns_rdf *, void *, #retvals: - def set_size(self,size): - """sets the size of the rdf. + def set_size(self, size): + """ + Sets the size of the rdf. - :param size: - the new size + :param size: The new size. + :type size: integer + :throws TypeError: When size of non-integer type. """ _ldns.ldns_rdf_set_size(self,size) #parameters: ldns_rdf *,size_t, #retvals: - def set_type(self,atype): - """sets the size of the rdf. - - :param atype: + def set_type(self, atype): """ - _ldns.ldns_rdf_set_type(self,atype) - #parameters: ldns_rdf *,ldns_rdf_type, + Sets the type of the rdf. + + :param atype: rdf type + :type atype: integer + :throws TypeError: When atype of non-integer type. + """ + _ldns.ldns_rdf_set_type(self, atype) + #parameters: ldns_rdf *, ldns_rdf_type, #retvals: def size(self): - """returns the size of the rdf. + """ + Returns the size of the rdf. - :returns: (size_t) uint16_t with the size + :return: (size_t) uint16_t with the size. """ return _ldns.ldns_rdf_size(self) #parameters: const ldns_rdf *, #retvals: size_t @staticmethod - def dname_new_frm_str(str): - """Creates a new dname rdf instance from a string. - - This static method is equivalent to using of default class constructor. - - :parameter str: str string to use + def dname_new_frm_str(string): """ - return _ldns.ldns_dname_new_frm_str(str) + Creates a new dname rdf instance from a given string. + + This static method is equivalent to using of default + :class:`ldns_rdf` constructor. + + :parameter string: String to use. + :type string: string + :throws TypeError: When not a string used. + :return: :class:`ldns_rdf` or None if error. + + .. warning:: + + It is scheduled to be deprecated and removed. Use + :class:`ldns_dname` constructor instead. + """ + warnings.warn("The ldns_rdf.dname_new_frm_str() method is" + + " scheduled to be deprecated in future releases." + + " Use ldsn_dname constructor instead.", + PendingDeprecationWarning, stacklevel=2) + return _ldns.ldns_dname_new_frm_str(string) def absolute(self): - """Checks whether the given dname string is absolute (i.e. ends with a '.') - - :returns: (bool) True or False """ - return self.endswith(".") + Checks whether the given dname string is absolute + (i.e., ends with a '.'). + + :return: (bool) True or False + + .. note:: + + This method was malfunctioning in ldns-1.3.16 and also + possibly earlier. + + .. warning:: + + It is scheduled to be deprecated and removed. Convert + :class:`ldns_rdf` to :class:`ldns_dname` to use the method. + """ + warnings.warn("The ldns_rdf.absolute() method is scheduled" + + " to be deprecated in future releases." + + " Convert the ldns_rdf to ldsn_dname and the use its" + + " methods.", PendingDeprecationWarning, stacklevel=2) + if self.get_type() == _ldns.LDNS_RDF_TYPE_DNAME: + string = self.__str__() + return _ldns.ldns_dname_str_absolute(string) != 0 + else: + return False def make_canonical(self): - """Put a dname into canonical fmt - ie. lowercase it """ + Put a dname into canonical format (i.e., convert to lower case). + + Performs no action if not a dname. + + .. warning:: + + This method is scheduled to be deprecated and removed. + Convert :class:`ldns_rdf` to :class:`ldns_dname` to use + the method. + """ + warnings.warn("The ldns_rdf.make_canonical() method is scheduled" + + " to be deprecated in future releases." + + " Convert the ldns_rdf to ldsn_dname and the use its" + + " methods.", PendingDeprecationWarning, stacklevel=2) _ldns.ldns_dname2canonical(self) - def dname_compare(self,other): - """Compares the two dname rdf's according to the algorithm for ordering in RFC4034 Section 6. - - :param other: - the second dname rdf to compare - :returns: (int) -1 if dname comes before other, 1 if dname comes after other, and 0 if they are equal. + def dname_compare(self, other): """ - return _ldns.ldns_dname_compare(self,other) + Compares two dname rdf according to the algorithm + for ordering in RFC4034 Section 6. - def cat(self,rd2): - """concatenates rd2 after this dname (rd2 is copied, this dname is modified) - - :param rd2: - the rightside - :returns: (ldns_status) LDNS_STATUS_OK on success + :param other: The second dname rdf to compare. + :type other: :class:`ldns_rdf` + :throws TypeError: When not a :class:`ldns_rdf` used. + :throws Exception: When not dnames compared. + :return: (int) -1, 0 or 1 if `self` comes before `other`, + `self` is equal or `self` comes after `other` respectively. + + .. warning:: + + It is scheduled to be deprecated and removed. Convert + :class:`ldns_rdf` to :class:`ldns_dname`. """ - return _ldns.ldns_dname_cat(self,rd2) - #parameters: ldns_rdf *,ldns_rdf *, + warnings.warn("The ldns_rdf.dname_compare() method is" + + " scheduled to be deprecated in future releases." + + " Convert the ldns_rdf to ldsn_dname and the use its" + + " methods.", PendingDeprecationWarning, stacklevel=2) + # + # The wrapped function generates asserts instead of setting + # error status. They cannot be caught from Python so a check + # is necessary. + # + if not isinstance(other, ldns_rdf): + raise TypeError("Parameter must be derived from ldns_rdf.") + if (self.get_type() != _ldns.LDNS_RDF_TYPE_DNAME) or \ + (other.get_type() != _ldns.LDNS_RDF_TYPE_DNAME): + raise Exception("Both operands must be dname rdfs.") + return _ldns.ldns_dname_compare(self, other) + + def cat(self, rd2): + """ + Concatenates `rd2` after `this` dname (`rd2` is copied, + `this` dname is modified). + + :param rd2: The right-hand side. + :type rd2: :class:`ldns_rdf` + :throws TypeError: When `rd2` of non-:class:`ldns_rdf` or + non-:class:`ldns_dname` type. + :return: (ldns_status) LDNS_STATUS_OK on success. + + .. warning:: + + It is scheduled to be deprecated and removed. Convert + :class:`ldns_rdf` to :class:`ldns_dname`. + """ + warnings.warn("The ldns_rdf.cat() method is scheduled" + + " to be deprecated in future releases." + + " Convert the ldns_rdf to ldsn_dname and the use its" + + " methods.", PendingDeprecationWarning, stacklevel=2) + return _ldns.ldns_dname_cat(self, rd2) + #parameters: ldns_rdf *, ldns_rdf *, #retvals: ldns_status - def cat_clone(self,rd2): - """concatenates two dnames together - - :param rd2: - the rightside - :returns: (ldns_rdf \*) a new rdf with leftside/rightside + def cat_clone(self, rd2): """ - return _ldns.ldns_dname_cat_clone(self,rd2) - #parameters: const ldns_rdf *,const ldns_rdf *, + Concatenates two dnames together. + + :param rd2: The right-hand side. + :type rd2: :class:`ldns_rdf` + :throws TypeError: When `rd2` of non-:class:`ldns_rdf` or + non-:class:`ldns_dname` type. + :return: (:class:`ldns_rdf`) A new rdf with + left-hand side + right-hand side content None when + error. + + .. warning:: + + It is scheduled to be deprecated and removed. Convert + :class:`ldns_rdf` to :class:`ldns_dname`. + """ + warnings.warn("The ldns_rdf.cat_clone() method is scheduled" + + " to be deprecated in future releases." + + " Convert the ldns_rdf to ldsn_dname and the use its" + + " methods.", PendingDeprecationWarning, stacklevel=2) + return _ldns.ldns_dname_cat_clone(self, rd2) + #parameters: const ldns_rdf *, const ldns_rdf *, #retvals: ldns_rdf * - def interval(self,middle,next): - """check if middle lays in the interval defined by prev and next prev <= middle < next. - - This is usefull for nsec checking - - :param middle: - the dname to check - :param next: - the next dname return 0 on error or unknown, -1 when middle is in the interval, +1 when not - :returns: (int) + def interval(self, middle, next): """ - return _ldns.ldns_dname_interval(self,middle,next) - #parameters: const ldns_rdf *,const ldns_rdf *,const ldns_rdf *, + Check whether the `middle` lays in the interval defined by + `this` and `next` (`this` <= `middle` < `next`). + + This method is useful for nsec checking + + :param middle: The dname to check. + :type middle: :class:`ldns_rdf` + :param next: The boundary. + :type next: :class:`ldns_rdf` + :throws TypeError: When `middle` or `next` of + non-:class:`ldns_rdf` type. + :throws Exception: When non-dname rdfs compared. + :return: (int) 0 on error or unknown, + -1 when middle is in the interval, 1 when not. + + .. warning:: + + It is scheduled to be deprecated and removed. Convert + :class:`ldns_rdf` to :class:`ldns_dname`. + """ + warnings.warn("The ldns_rdf.interval() method is scheduled" + + " to be deprecated in future releases." + + " Convert the ldns_rdf to ldsn_dname and the use its" + + " methods.", PendingDeprecationWarning, stacklevel=2) + # + # The wrapped function generates asserts instead of setting + # error status. They cannot be caught from Python so a check + # is necessary. + # + if (not isinstance(middle, ldns_rdf)) or \ + (not isinstance(next, ldns_rdf)): + raise TypeError("Parameters must be derived from ldns_rdf.") + if (self.get_type() != _ldns.LDNS_RDF_TYPE_DNAME) or \ + (middle.get_type() != _ldns.LDNS_RDF_TYPE_DNAME) or \ + (next.get_type() != _ldns.LDNS_RDF_TYPE_DNAME): + raise Exception("All operands must be dname rdfs.") + return _ldns.ldns_dname_interval(self, middle, next) + #parameters: const ldns_rdf *, const ldns_rdf *, const ldns_rdf *, #retvals: int - def is_subdomain(self,parent): - """Tests wether the name sub falls under parent (i.e. is a subdomain of parent). - - This function will return false if the given dnames are equal. - - :param parent: - (ldns_rdf) the parent's name - :returns: (bool) true if sub falls under parent, otherwise false + def is_subdomain(self, parent): """ - return _ldns.ldns_dname_is_subdomain(self,parent) - #parameters: const ldns_rdf *,const ldns_rdf *, + Tests whether the name of the given instance falls under + `parent` (i.e., is a sub-domain of `parent`). + + This function will return False if the given dnames + are equal. + + :param parent: The parent's name. + :type parent: :class:`ldns_rdf` + :throws TypeError: When `parent` of non-:class:`ldns_rdf` type. + :return: (bool) True if `this` falls under `parent`, otherwise + False. + + .. warning:: + + It is scheduled to be deprecated and removed. Convert + :class:`ldns_rdf` to :class:`ldns_dname`. + """ + warnings.warn("The ldns_rdf.is_subdomain() method is scheduled" + + " to be deprecated in future releases." + + " Convert the ldns_rdf to ldsn_dname and the use its" + + " methods.", PendingDeprecationWarning, stacklevel=2) + return _ldns.ldns_dname_is_subdomain(self, parent) + #parameters: const ldns_rdf *, const ldns_rdf *, #retvals: bool - def label(self,labelpos): - """look inside the rdf and if it is an LDNS_RDF_TYPE_DNAME try and retrieve a specific label. + def label(self, labelpos): + """ + Look inside the rdf and if it is an LDNS_RDF_TYPE_DNAME try + and retrieve a specific label. The labels are numbered starting from 0 (left most). - :param labelpos: - return the label with this number - :returns: (ldns_rdf \*) a ldns_rdf* with the label as name or NULL on error + :param labelpos: Index of the label. (Labels are numbered + 0, which is the left most.) + :type labelpos: integer + :throws TypeError: When `labelpos` of non-integer type. + :return: (:class:`ldns_rdf`) A new rdf with the label + as name or None on error. + + .. warning:: + + It is scheduled to be deprecated and removed. Convert + :class:`ldns_rdf` to :class:`ldns_dname`. """ - return _ldns.ldns_dname_label(self,labelpos) - #parameters: const ldns_rdf *,uint8_t, + warnings.warn("The ldns_rdf.label() method is scheduled" + + " to be deprecated in future releases." + + " Convert the ldns_rdf to ldsn_dname and the use its" + + " methods.", PendingDeprecationWarning, stacklevel=2) + return _ldns.ldns_dname_label(self, labelpos) + #parameters: const ldns_rdf *, uint8_t, #retvals: ldns_rdf * def label_count(self): - """count the number of labels inside a LDNS_RDF_DNAME type rdf. - - :returns: (uint8_t) the number of labels """ + Count the number of labels inside a LDNS_RDF_DNAME type rdf. + + :return: (uint8_t) The number of labels. Will return 0 if + not a dname. + + .. warning:: + + It is scheduled to be deprecated and removed. Convert + :class:`ldns_rdf` to :class:`ldns_dname`. + """ + warnings.warn("The ldns_rdf.label_count() method is scheduled" + + " to be deprecated in future releases." + + " Convert the ldns_rdf to ldsn_dname and the use its" + + " methods.", PendingDeprecationWarning, stacklevel=2) return _ldns.ldns_dname_label_count(self) #parameters: const ldns_rdf *, #retvals: uint8_t def left_chop(self): - """chop one label off the left side of a dname. - - so wwww.nlnetlabs.nl, becomes nlnetlabs.nl - - :returns: (ldns_rdf \*) the remaining dname """ + Chop one label off the left side of a dname. + + (e.g., wwww.nlnetlabs.nl, becomes nlnetlabs.nl) + + :return: (:class:`ldns_rdf`) The remaining dname or None when + error. + + .. warning:: + + It is scheduled to be deprecated and removed. Convert + :class:`ldns_rdf` to :class:`ldns_dname`. + """ + warnings.warn("The ldns_rdf.left_chop() method is scheduled" + + " to be deprecated in future releases." + + " Convert the ldns_rdf to ldsn_dname and the use its" + + " methods.", PendingDeprecationWarning, stacklevel=2) return _ldns.ldns_dname_left_chop(self) #parameters: const ldns_rdf *, #retvals: ldns_rdf * def reverse(self): - """Returns a clone of the given dname with the labels reversed. - - :returns: (ldns_rdf \*) clone of the dname with the labels reversed. """ + Returns a clone of the given dname with the labels reversed. + + When reversing non-dnames a "." (root name) dname is returned. + + :return: (:class:`ldns_rdf`) Clone of the dname with the labels + reversed or ".". + + .. warning:: + + It is scheduled to be deprecated and removed. Convert + :class:`ldns_rdf` to :class:`ldns_dname`. + """ + warnings.warn("The ldns_rdf.reverse() method is scheduled" + + " to be deprecated in future releases." + + " Convert the ldns_rdf to ldsn_dname and the use its" + + " methods.", PendingDeprecationWarning, stacklevel=2) return _ldns.ldns_dname_reverse(self) #parameters: const ldns_rdf *, #retvals: ldns_rdf * - #_LDNS_RDF_METHODS# - %} + # + # _LDNS_RDF_METHODS + # + %} } diff --git a/contrib/python/ldns_rr.i b/contrib/python/ldns_rr.i index 1a9f3f1c21b..726c6cd902a 100644 --- a/contrib/python/ldns_rr.i +++ b/contrib/python/ldns_rr.i @@ -14,8 +14,8 @@ * 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 organization nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 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 @@ -28,1152 +28,1848 @@ * 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. - ******************************************************************************/ + *****************************************************************************/ -%typemap(in,numinputs=0,noblock=1) (ldns_rr **) + +/* ========================================================================= */ +/* SWIG setting and definitions. */ +/* ========================================================================= */ + +/* Creates a temporary instance of (ldns_rr *). */ +%typemap(in, numinputs=0, noblock=1) (ldns_rr **) { - ldns_rr *$1_rr; - $1 = &$1_rr; + ldns_rr *$1_rr; + $1 = &$1_rr; } -/* result generation */ -%typemap(argout,noblock=1) (ldns_rr **) +/* Result generation, appends (ldns_rr *) after the result. */ +%typemap(argout, noblock=1) (ldns_rr **) { - $result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(SWIG_as_voidptr($1_rr), SWIGTYPE_p_ldns_struct_rr, SWIG_POINTER_OWN | 0 )); + $result = SWIG_Python_AppendOutput($result, + SWIG_NewPointerObj(SWIG_as_voidptr($1_rr), + SWIGTYPE_p_ldns_struct_rr, SWIG_POINTER_OWN | 0 )); } -%nodefaultctor ldns_struct_rr; //no default constructor & destructor -%nodefaultdtor ldns_struct_rr; +%nodefaultctor ldns_struct_rr; /* No default constructor. */ +%nodefaultdtor ldns_struct_rr; /* No default destructor. */ %ignore ldns_struct_rr::_rdata_fields; %newobject ldns_rr_clone; %newobject ldns_rr_new; +%newobject ldns_rr_new_frm_type; %newobject ldns_rr_pop_rdf; %delobject ldns_rr_free; %rename(ldns_rr) ldns_struct_rr; -#ifdef LDNS_DEBUG -%rename(__ldns_rr_free) ldns_rr_free; -%inline %{ -void _ldns_rr_free (ldns_rr* r) { - printf("******** LDNS_RR free 0x%lX ************\n", (long unsigned int)r); - ldns_rr_free(r); -} -%} -#else -%rename(_ldns_rr_free) ldns_rr_free; -#endif - %newobject ldns_rr2str; %newobject ldns_rr_type2str; %newobject ldns_rr_class2str; %newobject ldns_read_anchor_file; -// clone rdf data on pull +/* Clone rdf data on pull. */ + +/* Clone will fail with NULL argument. */ %newobject _ldns_rr_rdf; %rename(__ldns_rr_rdf) ldns_rr_rdf; -%inline %{ -ldns_rdf* _ldns_rr_rdf(ldns_rr* rr, size_t i) { - return ldns_rdf_clone(ldns_rr_rdf(rr, i)); -} +%inline +%{ + ldns_rdf * _ldns_rr_rdf(ldns_rr *rr, size_t i) + { + ldns_rdf *rdf; + rdf = ldns_rr_rdf(rr, i); + return (rdf != NULL) ? ldns_rdf_clone(rdf) : NULL; + } %} %newobject _ldns_rr_rrsig_algorithm; %rename(__ldns_rr_rrsig_algorithm) ldns_rr_rrsig_algorithm; -%inline %{ -ldns_rdf* _ldns_rr_rrsig_algorithm(ldns_rr* rr) { - return ldns_rdf_clone(ldns_rr_rrsig_algorithm(rr)); -} +%inline +%{ + ldns_rdf * _ldns_rr_rrsig_algorithm(ldns_rr *rr) { + ldns_rdf *rdf; + rdf = ldns_rr_rrsig_algorithm(rr); + return (rdf != NULL) ? ldns_rdf_clone(rdf) : NULL; + } %} %newobject _ldns_rr_dnskey_algorithm; %rename(__ldns_rr_dnskey_algorithm) ldns_rr_dnskey_algorithm; -%inline %{ -ldns_rdf* _ldns_rr_dnskey_algorithm(ldns_rr* rr) { - return ldns_rdf_clone(ldns_rr_dnskey_algorithm(rr)); -} +%inline +%{ + ldns_rdf * _ldns_rr_dnskey_algorithm(ldns_rr *rr) + { + ldns_rdf *rdf; + rdf = ldns_rr_dnskey_algorithm(rr); + return (rdf != NULL) ? ldns_rdf_clone(rdf) : NULL; + } %} %newobject _ldns_rr_dnskey_flags; %rename(__ldns_rr_dnskey_flags) ldns_rr_dnskey_flags; -%inline %{ -ldns_rdf* _ldns_rr_dnskey_flags(ldns_rr* rr) { - return ldns_rdf_clone(ldns_rr_dnskey_flags(rr)); -} +%inline + %{ + ldns_rdf * _ldns_rr_dnskey_flags(ldns_rr *rr) + { + ldns_rdf *rdf; + rdf = ldns_rr_dnskey_flags(rr); + return (rdf != NULL) ? ldns_rdf_clone(rdf) : NULL; + } %} %newobject _ldns_rr_dnskey_key; %rename(__ldns_rr_dnskey_key) ldns_rr_dnskey_key; -%inline %{ -ldns_rdf* _ldns_rr_dnskey_key(ldns_rr* rr) { - return ldns_rdf_clone(ldns_rr_dnskey_key(rr)); -} +%inline +%{ + ldns_rdf * _ldns_rr_dnskey_key(ldns_rr *rr) + { + ldns_rdf *rdf; + rdf = ldns_rr_dnskey_key(rr); + return (rdf != NULL) ? ldns_rdf_clone(rdf) : NULL; + } %} %newobject _ldns_rr_dnskey_protocol; %rename(__ldns_rr_dnskey_protocol) ldns_rr_dnskey_protocol; -%inline %{ -ldns_rdf* _ldns_rr_dnskey_protocol(ldns_rr* rr) { - return ldns_rdf_clone(ldns_rr_dnskey_protocol(rr)); -} +%inline +%{ + ldns_rdf * _ldns_rr_dnskey_protocol(ldns_rr *rr) + { + ldns_rdf *rdf; + rdf = ldns_rr_dnskey_protocol(rr); + return (rdf != NULL) ? ldns_rdf_clone(rdf) : NULL; + } %} %newobject _ldns_rr_owner; %rename(__ldns_rr_owner) ldns_rr_owner; -%inline %{ -ldns_rdf* _ldns_rr_owner(ldns_rr* rr) { - return ldns_rdf_clone(ldns_rr_owner(rr)); -} +%inline +%{ + ldns_rdf * _ldns_rr_owner(ldns_rr *rr) + { + ldns_rdf *rdf; + rdf = ldns_rr_owner(rr); + return (rdf != NULL) ? ldns_rdf_clone(rdf) : NULL; + } %} %newobject _ldns_rr_a_address; %rename(__ldns_rr_a_address) ldns_rr_a_address; -%inline %{ -ldns_rdf* _ldns_rr_a_address(ldns_rr* rr) { - return ldns_rdf_clone(ldns_rr_a_address(rr)); -} +%inline +%{ + ldns_rdf * _ldns_rr_a_address(ldns_rr *rr) + { + ldns_rdf *rdf; + rdf = ldns_rr_a_address(rr); + return (rdf != NULL) ? ldns_rdf_clone(rdf) : NULL; + } %} %newobject _ldns_rr_mx_exchange; %rename(__ldns_rr_mx_exchange) ldns_rr_mx_exchange; -%inline %{ -ldns_rdf* _ldns_rr_mx_exchange(ldns_rr* rr) { - return ldns_rdf_clone(ldns_rr_mx_exchange(rr)); -} +%inline +%{ + ldns_rdf * _ldns_rr_mx_exchange(ldns_rr *rr) + { + ldns_rdf *rdf; + rdf = ldns_rr_mx_exchange(rr); + return (rdf != NULL) ? ldns_rdf_clone(rdf) : NULL; + } %} %newobject _ldns_rr_mx_preference; %rename(__ldns_rr_mx_preference) ldns_rr_mx_preference; -%inline %{ -ldns_rdf* _ldns_rr_mx_preference(ldns_rr* rr) { - return ldns_rdf_clone(ldns_rr_mx_preference(rr)); -} +%inline +%{ + ldns_rdf * _ldns_rr_mx_preference(ldns_rr *rr) + { + ldns_rdf *rdf; + rdf = ldns_rr_mx_preference(rr); + return (rdf != NULL) ? ldns_rdf_clone(rdf) : NULL; + } %} %newobject _ldns_rr_ns_nsdname; %rename(__ldns_rr_ns_nsdname) ldns_rr_ns_nsdname; -%inline %{ -ldns_rdf* _ldns_rr_ns_nsdname(ldns_rr* rr) { - return ldns_rdf_clone(ldns_rr_ns_nsdname(rr)); -} +%inline +%{ + ldns_rdf * _ldns_rr_ns_nsdname(ldns_rr *rr) + { + ldns_rdf *rdf; + rdf = ldns_rr_ns_nsdname(rr); + return (rdf != NULL) ? ldns_rdf_clone(rdf) : NULL; + } %} %newobject _ldns_rr_rrsig_expiration; %rename(__ldns_rr_rrsig_expiration) ldns_rr_rrsig_expiration; -%inline %{ -ldns_rdf* _ldns_rr_rrsig_expiration(ldns_rr* rr) { - return ldns_rdf_clone(ldns_rr_rrsig_expiration(rr)); -} +%inline +%{ + ldns_rdf * _ldns_rr_rrsig_expiration(ldns_rr *rr) + { + ldns_rdf *rdf; + rdf = ldns_rr_rrsig_expiration(rr); + return (rdf != NULL) ? ldns_rdf_clone(rdf) : NULL; + } %} %newobject _ldns_rr_rrsig_inception; %rename(__ldns_rr_rrsig_inception) ldns_rr_rrsig_inception; -%inline %{ -ldns_rdf* _ldns_rr_rrsig_inception(ldns_rr* rr) { - return ldns_rdf_clone(ldns_rr_rrsig_inception(rr)); -} +%inline +%{ + ldns_rdf * _ldns_rr_rrsig_inception(ldns_rr *rr) + { + ldns_rdf *rdf; + rdf = ldns_rr_rrsig_inception(rr); + return (rdf != NULL) ? ldns_rdf_clone(rdf) : NULL; + } %} %newobject _ldns_rr_rrsig_keytag; %rename(__ldns_rr_rrsig_keytag) ldns_rr_rrsig_keytag; -%inline %{ -ldns_rdf* _ldns_rr_rrsig_keytag(ldns_rr* rr) { - return ldns_rdf_clone(ldns_rr_rrsig_keytag(rr)); -} +%inline +%{ + ldns_rdf * _ldns_rr_rrsig_keytag(ldns_rr *rr) + { + ldns_rdf *rdf; + rdf = ldns_rr_rrsig_keytag(rr); + return (rdf != NULL) ? ldns_rdf_clone(rdf) : NULL; + } %} %newobject _ldns_rr_rrsig_labels; %rename(__ldns_rr_rrsig_labels) ldns_rr_rrsig_labels; -%inline %{ -ldns_rdf* _ldns_rr_rrsig_labels(ldns_rr* rr) { - return ldns_rdf_clone(ldns_rr_rrsig_labels(rr)); -} +%inline +%{ + ldns_rdf * _ldns_rr_rrsig_labels(ldns_rr *rr) + { + ldns_rdf *rdf; + rdf = ldns_rr_rrsig_labels(rr); + return (rdf != NULL) ? ldns_rdf_clone(rdf) : NULL; + } %} %newobject _ldns_rr_rrsig_origttl; %rename(__ldns_rr_rrsig_origttl) ldns_rr_rrsig_origttl; -%inline %{ -ldns_rdf* _ldns_rr_rrsig_origttl(ldns_rr* rr) { - return ldns_rdf_clone(ldns_rr_rrsig_origttl(rr)); -} +%inline +%{ + ldns_rdf * _ldns_rr_rrsig_origttl(ldns_rr *rr) + { + ldns_rdf *rdf; + rdf = ldns_rr_rrsig_origttl(rr); + return (rdf != NULL) ? ldns_rdf_clone(rdf) : NULL; + } %} %newobject _ldns_rr_rrsig_sig; %rename(__ldns_rr_rrsig_sig) ldns_rr_rrsig_sig; -%inline %{ -ldns_rdf* _ldns_rr_rrsig_sig(ldns_rr* rr) { - return ldns_rdf_clone(ldns_rr_rrsig_sig(rr)); -} +%inline +%{ + ldns_rdf * _ldns_rr_rrsig_sig(ldns_rr *rr) + { + ldns_rdf *rdf; + rdf = ldns_rr_rrsig_sig(rr); + return (rdf != NULL) ? ldns_rdf_clone(rdf) : NULL; + } %} %newobject _ldns_rr_rrsig_signame; %rename(__ldns_rr_rrsig_signame) ldns_rr_rrsig_signame; -%inline %{ -ldns_rdf* _ldns_rr_rrsig_signame(ldns_rr* rr) { - return ldns_rdf_clone(ldns_rr_rrsig_signame(rr)); -} +%inline +%{ + ldns_rdf * _ldns_rr_rrsig_signame(ldns_rr *rr) + { + ldns_rdf *rdf; + rdf = ldns_rr_rrsig_signame(rr); + return (rdf != NULL) ? ldns_rdf_clone(rdf) : NULL; + } %} %newobject _ldns_rr_rrsig_typecovered; %rename(__ldns_rr_rrsig_typecovered) ldns_rr_rrsig_typecovered; -%inline %{ -ldns_rdf* _ldns_rr_rrsig_typecovered(ldns_rr* rr) { - return ldns_rdf_clone(ldns_rr_rrsig_typecovered(rr)); -} +%inline +%{ + ldns_rdf * _ldns_rr_rrsig_typecovered(ldns_rr *rr) + { + ldns_rdf *rdf; + rdf = ldns_rr_rrsig_typecovered(rr); + return (rdf != NULL) ? ldns_rdf_clone(rdf) : NULL; + } %} -// end of pull cloning +/* End of pull cloning. */ -// clone rdf data on push +/* Clone rdf data on push. */ %rename(__ldns_rr_a_set_address) ldns_rr_a_set_address; -%inline %{ -bool _ldns_rr_a_set_address(ldns_rr* rr, ldns_rdf* rdf) { - return ldns_rr_a_set_address(rr, ldns_rdf_clone(rdf)); -} +%inline +%{ + bool _ldns_rr_a_set_address(ldns_rr *rr, ldns_rdf *rdf) + { + return ldns_rr_a_set_address(rr, ldns_rdf_clone(rdf)); + } %} %rename(__ldns_rr_dnskey_set_algorithm) ldns_rr_dnskey_set_algorithm; -%inline %{ -bool _ldns_rr_dnskey_set_algorithm(ldns_rr* rr, ldns_rdf* rdf) { - return ldns_rr_dnskey_set_algorithm(rr, ldns_rdf_clone(rdf)); -} +%inline +%{ + bool _ldns_rr_dnskey_set_algorithm(ldns_rr *rr, ldns_rdf *rdf) + { + return ldns_rr_dnskey_set_algorithm(rr, ldns_rdf_clone(rdf)); + } %} %rename(__ldns_rr_dnskey_set_flags) ldns_rr_dnskey_set_flags; -%inline %{ -bool _ldns_rr_dnskey_set_flags(ldns_rr* rr, ldns_rdf* rdf) { - return ldns_rr_dnskey_set_flags(rr, ldns_rdf_clone(rdf)); -} +%inline +%{ + bool _ldns_rr_dnskey_set_flags(ldns_rr *rr, ldns_rdf *rdf) + { + return ldns_rr_dnskey_set_flags(rr, ldns_rdf_clone(rdf)); + } %} %rename(__ldns_rr_dnskey_set_key) ldns_rr_dnskey_set_key; -%inline %{ -bool _ldns_rr_dnskey_set_key(ldns_rr* rr, ldns_rdf* rdf) { - return ldns_rr_dnskey_set_key(rr, ldns_rdf_clone(rdf)); -} +%inline +%{ + bool _ldns_rr_dnskey_set_key(ldns_rr *rr, ldns_rdf *rdf) + { + return ldns_rr_dnskey_set_key(rr, ldns_rdf_clone(rdf)); + } %} %rename(__ldns_rr_dnskey_set_protocol) ldns_rr_dnskey_set_protocol; -%inline %{ -bool _ldns_rr_dnskey_set_protocol(ldns_rr* rr, ldns_rdf* rdf) { - return ldns_rr_dnskey_set_protocol(rr, ldns_rdf_clone(rdf)); -} +%inline +%{ + bool _ldns_rr_dnskey_set_protocol(ldns_rr *rr, ldns_rdf *rdf) + { + return ldns_rr_dnskey_set_protocol(rr, ldns_rdf_clone(rdf)); + } %} %rename(__ldns_rr_push_rdf) ldns_rr_push_rdf; -%inline %{ -bool _ldns_rr_push_rdf(ldns_rr* rr, ldns_rdf* rdf) { - return ldns_rr_push_rdf(rr, ldns_rdf_clone(rdf)); -} +%inline +%{ + bool _ldns_rr_push_rdf(ldns_rr *rr, ldns_rdf *rdf) + { + return ldns_rr_push_rdf(rr, ldns_rdf_clone(rdf)); + } %} %rename(__ldns_rr_rrsig_set_algorithm) ldns_rr_rrsig_set_algorithm; -%inline %{ -bool _ldns_rr_rrsig_set_algorithm(ldns_rr* rr, ldns_rdf* rdf) { - return ldns_rr_rrsig_set_algorithm(rr, ldns_rdf_clone(rdf)); -} +%inline +%{ + bool _ldns_rr_rrsig_set_algorithm(ldns_rr *rr, ldns_rdf *rdf) + { + return ldns_rr_rrsig_set_algorithm(rr, ldns_rdf_clone(rdf)); + } %} %rename(__ldns_rr_rrsig_set_expiration) ldns_rr_rrsig_set_expiration; -%inline %{ -bool _ldns_rr_rrsig_set_expiration(ldns_rr* rr, ldns_rdf* rdf) { - return ldns_rr_rrsig_set_expiration(rr, ldns_rdf_clone(rdf)); -} +%inline +%{ + bool _ldns_rr_rrsig_set_expiration(ldns_rr *rr, ldns_rdf *rdf) + { + return ldns_rr_rrsig_set_expiration(rr, ldns_rdf_clone(rdf)); + } %} %rename(__ldns_rr_rrsig_set_inception) ldns_rr_rrsig_set_inception; -%inline %{ -bool _ldns_rr_rrsig_set_inception(ldns_rr* rr, ldns_rdf* rdf) { - return ldns_rr_rrsig_set_inception(rr, ldns_rdf_clone(rdf)); -} +%inline +%{ + bool _ldns_rr_rrsig_set_inception(ldns_rr *rr, ldns_rdf *rdf) + { + return ldns_rr_rrsig_set_inception(rr, ldns_rdf_clone(rdf)); + } %} %rename(__ldns_rr_rrsig_set_keytag) ldns_rr_rrsig_set_keytag; -%inline %{ -bool _ldns_rr_rrsig_set_keytag(ldns_rr* rr, ldns_rdf* rdf) { - return ldns_rr_rrsig_set_keytag(rr, ldns_rdf_clone(rdf)); -} +%inline +%{ + bool _ldns_rr_rrsig_set_keytag(ldns_rr *rr, ldns_rdf *rdf) + { + return ldns_rr_rrsig_set_keytag(rr, ldns_rdf_clone(rdf)); + } %} %rename(__ldns_rr_rrsig_set_labels) ldns_rr_rrsig_set_labels; -%inline %{ -bool _ldns_rr_rrsig_set_labels(ldns_rr* rr, ldns_rdf* rdf) { - return ldns_rr_rrsig_set_labels(rr, ldns_rdf_clone(rdf)); -} +%inline +%{ + bool _ldns_rr_rrsig_set_labels(ldns_rr *rr, ldns_rdf *rdf) + { + return ldns_rr_rrsig_set_labels(rr, ldns_rdf_clone(rdf)); + } %} %rename(__ldns_rr_rrsig_set_origttl) ldns_rr_rrsig_set_origttl; -%inline %{ -bool _ldns_rr_rrsig_set_origttl(ldns_rr* rr, ldns_rdf* rdf) { - return ldns_rr_rrsig_set_origttl(rr, ldns_rdf_clone(rdf)); -} +%inline +%{ + bool _ldns_rr_rrsig_set_origttl(ldns_rr *rr, ldns_rdf *rdf) + { + return ldns_rr_rrsig_set_origttl(rr, ldns_rdf_clone(rdf)); + } %} %rename(__ldns_rr_rrsig_set_sig) ldns_rr_rrsig_set_sig; -%inline %{ -bool _ldns_rr_rrsig_set_sig(ldns_rr* rr, ldns_rdf* rdf) { - return ldns_rr_rrsig_set_sig(rr, ldns_rdf_clone(rdf)); -} +%inline +%{ + bool _ldns_rr_rrsig_set_sig(ldns_rr *rr, ldns_rdf *rdf) { + return ldns_rr_rrsig_set_sig(rr, ldns_rdf_clone(rdf)); + } %} %rename(__ldns_rr_rrsig_set_signame) ldns_rr_rrsig_set_signame; -%inline %{ -bool _ldns_rr_rrsig_set_signame(ldns_rr* rr, ldns_rdf* rdf) { - return ldns_rr_rrsig_set_signame(rr, ldns_rdf_clone(rdf)); -} +%inline +%{ + bool _ldns_rr_rrsig_set_signame(ldns_rr *rr, ldns_rdf *rdf) + { + return ldns_rr_rrsig_set_signame(rr, ldns_rdf_clone(rdf)); + } %} %rename(__ldns_rr_rrsig_set_typecovered) ldns_rr_rrsig_set_typecovered; -%inline %{ -bool _ldns_rr_rrsig_set_typecovered(ldns_rr* rr, ldns_rdf* rdf) { - return ldns_rr_rrsig_set_typecovered(rr, ldns_rdf_clone(rdf)); -} +%inline +%{ + bool _ldns_rr_rrsig_set_typecovered(ldns_rr *rr, ldns_rdf *rdf) + { + return ldns_rr_rrsig_set_typecovered(rr, ldns_rdf_clone(rdf)); + } %} %rename(__ldns_rr_set_owner) ldns_rr_set_owner; -%inline %{ -void _ldns_rr_set_owner(ldns_rr* rr, ldns_rdf* rdf) { - return ldns_rr_set_owner(rr, ldns_rdf_clone(rdf)); -} +%inline +%{ + void _ldns_rr_set_owner(ldns_rr *rr, ldns_rdf *rdf) + { + return ldns_rr_set_owner(rr, ldns_rdf_clone(rdf)); + } %} +%newobject _ldns_rr_set_rdf; %rename(__ldns_rr_set_rdf) ldns_rr_set_rdf; -%inline %{ - ldns_rdf* _ldns_rr_set_rdf(ldns_rr* rr, ldns_rdf* rdf, size_t pos) { - return ldns_rr_set_rdf(rr, ldns_rdf_clone(rdf), pos); -} +%inline +%{ + ldns_rdf * _ldns_rr_set_rdf(ldns_rr *rr, ldns_rdf *rdf, size_t pos) + { + /* May leak memory on unsuccessful calls. */ + ldns_rdf *new, *ret; + + new = ldns_rdf_clone(rdf); + + if ((ret = ldns_rr_set_rdf(rr, new, pos)) == NULL) { + ldns_rdf_deep_free(new); + } + + return ret; + } %} -// end of push cloning +/* End of push cloning. */ %rename(_ldns_rr_new_frm_str) ldns_rr_new_frm_str; %rename(_ldns_rr_new_frm_fp_l) ldns_rr_new_frm_fp_l; %rename(_ldns_rr_new_frm_fp) ldns_rr_new_frm_fp; -%feature("docstring") ldns_struct_rr "Resource Record (RR) -The RR is the basic DNS element that contains actual data. This class allows to create RR and manipulate with the content." +/* ========================================================================= */ +/* Debugging related code. */ +/* ========================================================================= */ + + +#ifdef LDNS_DEBUG +%rename(__ldns_rr_free) ldns_rr_free; +%inline %{ + void _ldns_rr_free (ldns_rr *r) + { + printf("******** LDNS_RR free 0x%lX ************\n", (long unsigned int)r); + ldns_rr_free(r); + } +%} +#else /* !LDNS_DEBUG */ +%rename(_ldns_rr_free) ldns_rr_free; +#endif /* LDNS_DEBUG */ + + +/* ========================================================================= */ +/* Added C code. */ +/* ========================================================================= */ + +/* None. */ + + +/* ========================================================================= */ +/* Encapsulating Python code. */ +/* ========================================================================= */ + + +%feature("docstring") ldns_struct_rr "Resource Record (RR). + +The RR is the basic DNS element that contains actual data. This class allows +to create RR and manipulate with the content. + +Use :meth:`ldns_rr_new`, :meth:`ldns_rr_new_frm_type`, :meth:`new_frm_fp`, +:meth:`new_frm_fp_l`, :meth:`new_frm_str` or :meth:`new_question_frm_str` +to create :class:`ldns_rr` instances. +" %extend ldns_struct_rr { - %pythoncode %{ + %pythoncode + %{ def __init__(self): - raise Exception("This class can't be created directly. Please use: ldns_rr_new, ldns_rr_new_frm_type, new_frm_fp(), new_frm_fp_l(), new_frm_str() or new_question_frm_str") + raise Exception("This class can't be created directly. " + + "Please use: ldns_rr_new(), ldns_rr_new_frm_type(), " + + "new_frm_fp(), new_frm_fp_l(), new_frm_str() or " + + "new_question_frm_str()") __swig_destroy__ = _ldns._ldns_rr_free - #LDNS_RR_CONSTRUCTORS_# - @staticmethod - def new_frm_str(str, default_ttl=0, origin=None, prev=None, raiseException=True): - """Creates an rr object from a string. + # + # LDNS_RR_CONSTRUCTORS_ + # - The string should be a fully filled-in rr, like ownername [space] TTL [space] CLASS [space] TYPE [space] RDATA. + @staticmethod + def new_frm_str(string, default_ttl=0, origin=None, prev=None, raiseException=True): + """ + Creates an rr object from a string. + + The string should be a fully filled-in rr, like "owner_name + [space] TTL [space] CLASS [space] TYPE [space] RDATA." - :param str: the string to convert - :param default_ttl: default ttl value for the rr. If 0 DEF_TTL will be used - :param origin: when the owner is relative add this - :param prev: the previous ownername - :param raiseException: if True, an exception occurs in case a rr instance can't be created - :returns: - * rr - (ldnsrr) RR instance or None. If the object can't be created and raiseException is True, an exception occurs. + :param string: The string to convert. + :type string: str + :param default_ttl: Default ttl value for the rr. + If 0 DEF_TTL will be used. + :type default_ttl: int + :param origin: When the owner is relative add this. + :type origin: :class:`ldns_dname` + :param prev: The previous owner name. + :type prev: :class:`ldns_rdf` + :param raiseException: If True, an exception occurs in case a rr + instance can't be created. + :throws Exception: If `raiseExceprion` is set and fails. + :throws TypeError: When parameters of incorrect types. + :return: (:class:`ldns_rr`) RR instance or None. + + .. note:: + The type checking of `origin` is benevolent. + It allows also to pass a dname :class:`ldns_rdf` object. + This will probably change in future. **Usage** >>> import ldns - >>> rr = ldns.ldns_rr.new_frm_str("www.nic.cz. IN A 192.168.1.1",300) + >>> rr = ldns.ldns_rr.new_frm_str("www.nic.cz. IN A 192.168.1.1", 300) >>> print rr www.nic.cz. 300 IN A 192.168.1.1 - """ - status, rr, prev = _ldns.ldns_rr_new_frm_str_(str, default_ttl, origin, prev) - if status != LDNS_STATUS_OK: - if (raiseException): raise Exception("Can't create RR, error: %d" % status) - return None - return rr - - @staticmethod - def new_question_frm_str(str, default_ttl=0, origin=None, prev=None, raiseException=True): - """Creates an rr object from a string. - - The string is like new_frm_str but without rdata. - - :param str: the string to convert - :param origin: when the owner is relative add this - :param prev: the previous ownername - :param raiseException: if True, an exception occurs in case a rr instance can't be created - :returns: - * rr - (ldnsrr) RR instance or None. If the object can't be created and raiseException is True, an exception occurs. - """ - status, rr, prev = _ldns.ldns_rr_new_question_frm_str_(str, origin, prev) - if status != LDNS_STATUS_OK: - if (raiseException): raise Exception("Can't create RR, error: %d" % status) - return None - return rr - - @staticmethod - def new_frm_str_prev(str, default_ttl=0, origin=None, prev=None, raiseException=True): - """Creates an rr object from a string. - - The string should be a fully filled-in rr, like ownername [space] TTL [space] CLASS [space] TYPE [space] RDATA. + >>> rr = ldns.ldns_rr.new_frm_str("test.nic.cz. 600 IN A 192.168.1.2") + >>> print rr + test.nic.cz. 600 IN A 192.168.1.2 - :param str: the string to convert - :param default_ttl: default ttl value for the rr. If 0 DEF_TTL will be used - :param origin: when the owner is relative add this - :param prev: the previous ownername - :param raiseException: if True, an exception occurs in case a rr instance can't be created - :returns: - * rr - (ldnsrr) RR instance or None. If the object can't be created and raiseException is True, an exception occurs. - - * prev - (ldns_rdf) ownername found in this string or None """ - status, rr, prev = _ldns.ldns_rr_new_frm_str_(str, default_ttl, origin, prev) + if (not isinstance(origin, ldns_dname)) and \ + isinstance(origin, ldns_rdf) and \ + origin.get_type() == _ldns.LDNS_RDF_TYPE_DNAME: + warnings.warn("The ldns_rr.new_frm_str() method will" + + " drop the possibility to accept ldns_rdf as origin." + + " Convert argument to ldns_dname.", + PendingDeprecationWarning, stacklevel=2) + status, rr, prev = _ldns.ldns_rr_new_frm_str_(string, default_ttl, + origin, prev) if status != LDNS_STATUS_OK: - if (raiseException): raise Exception("Can't create RR, error: %d" % status) + if (raiseException): + raise Exception("Can't create RR, error: %d" % status) + return None + return rr + + @staticmethod + def new_question_frm_str(string, default_ttl=0, origin=None, prev=None, raiseException=True): + """ + Creates an rr object from a string. + + The string is like :meth:`new_frm_str` but without rdata. + + :param string: The string to convert. + :type string: str + :param origin: When the owner is relative add this. + :type origin: :class:`ldns_dname` + :param prev: The previous owner name. + :type prev: :class:`ldns_rdf` + :param raiseException: If True, an exception occurs in case + a rr instance can't be created. + :throws Exception: If `raiseExceprion` is set and fails. + :throws TypeError: When parameters of incorrect types. + :return: (:class:`ldns_rr`) RR instance or None. If the object + can't be created and `raiseException` is True, + an exception occurs. + + .. note:: + The type checking of `origin` is benevolent. + It allows also to pass a dname :class:`ldns_rdf` object. + This will probably change in future. + """ + if (not isinstance(origin, ldns_dname)) and \ + isinstance(origin, ldns_rdf) and \ + origin.get_type() == _ldns.LDNS_RDF_TYPE_DNAME: + warnings.warn("The ldns_rr.new_question_frm_str() method will" + + " drop the possibility to accept ldns_rdf as origin." + + " Convert argument to ldns_dname.", + PendingDeprecationWarning, stacklevel=2) + status, rr, prev = _ldns.ldns_rr_new_question_frm_str_(string, + origin, prev) + if status != LDNS_STATUS_OK: + if (raiseException): + raise Exception("Can't create RR, error: %d" % status) + return None + return rr + + @staticmethod + def new_frm_str_prev(string, default_ttl=0, origin=None, prev=None, raiseException=True): + """ + Creates an rr object from a string. + + The string should be a fully filled-in rr, like "owner_name + [space] TTL [space] CLASS [space] TYPE [space] RDATA". + + :param string: The string to convert. + :type string: str + :param default_ttl: Default ttl value for the rr. + If 0 DEF_TTL will be used. + :type default_ttl: int + :param origin: When the owner is relative add this. + :type origin: :class:`ldns_dname` + :param prev: The previous owner name. + :type prev: :class:`ldns_rdf` + :param raiseException: If True, an exception occurs in case when + a rr instance can't be created. + :throws Exception: If `raiseExceprion` is set and fails. + :throws TypeError: When parameters of incorrect types. + :return: None when fails, otherwise a tuple containing: + + * rr - (:class:`ldns_rr`) RR instance or None. + If the object can't be created and `raiseException` + is True, an exception occurs. + + * prev - (:class:`ldns_rdf`) Owner name found in this string + or None. + + .. note:: + The type checking of `origin` is benevolent. + It allows also to pass a dname :class:`ldns_rdf` object. + This will probably change in future. + """ + if (not isinstance(origin, ldns_dname)) and \ + isinstance(origin, ldns_rdf) and \ + origin.get_type() == _ldns.LDNS_RDF_TYPE_DNAME: + warnings.warn("The ldns_rr.new_frm_str_prev() method will" + + " drop the possibility to accept ldns_rdf as origin." + + " Convert argument to ldns_dname.", + PendingDeprecationWarning, stacklevel=2) + status, rr, prev = _ldns.ldns_rr_new_frm_str_(string, default_ttl, + origin, prev) + if status != LDNS_STATUS_OK: + if (raiseException): + raise Exception("Can't create RR, error: %d" % status) return None return rr, prev @staticmethod def new_frm_fp(file, default_ttl=0, origin=None, prev=None, raiseException=True): - """Creates a new rr from a file containing a string. - - :param file: file pointer - :param default_ttl: If 0 DEF_TTL will be used - :param origin: when the owner is relative add this. - :param prev: when the owner is whitespaces use this. - :param raiseException: if True, an exception occurs in case a resolver object can't be created - :returns: - * rr - (ldns_rr) RR object or None. If the object can't be created and raiseException is True, an exception occurs. - - * ttl - (int) None or TTL if the file contains a $TTL directive - - * origin - (ldns_rdf) None or dname if the file contains a $ORIGIN directive - - * prev - (ldns_rdf) None or updated value of prev parameter """ - res = _ldns.ldns_rr_new_frm_fp_l_(file, default_ttl, origin, prev, 0) + Creates a new rr from a file containing a string. + + :param file: Opened file. + :param default_ttl: If 0 DEF_TTL will be used. + :type default_ttl: int + :param origin: When the owner is relative add this. + :type origin: :class:`ldns_dname` + :param prev: When the owner is white spaces use this. + :type prev: :class:`ldns_rdf` + :param raiseException: If True, an exception occurs in case + a resolver object can't be created. + :throws Exception: If `raiseException` is set and the input + cannot be read. + :throws TypeError: When parameters of incorrect types. + :return: None when fails, otherwise a tuple containing: + + * rr - (:class:`ldns_rr`) RR object or None. If the object + can't be created and `raiseException` is True, + an exception occurs. + + * ttl - (int) None or TTL if the file contains a TTL + directive. + + * origin - (:class:`ldns_rdf`) None or dname rdf if the file + contains a ORIGIN directive. + + * prev - (:class:`ldns_rdf`) None or updated value + of prev parameter. + + .. note:: + The type checking of `origin` is benevolent. + It allows also to pass a dname :class:`ldns_rdf` object. + This will probably change in future. + """ + if (not isinstance(origin, ldns_dname)) and \ + isinstance(origin, ldns_rdf) and \ + origin.get_type() == _ldns.LDNS_RDF_TYPE_DNAME: + warnings.warn("The ldns_rr.new_frm_fp() method will" + + " drop the possibility to accept ldns_rdf as origin." + + " Convert argument to ldns_dname.", + PendingDeprecationWarning, stacklevel=2) + res = _ldns.ldns_rr_new_frm_fp_(file, default_ttl, origin, prev) if res[0] != LDNS_STATUS_OK: - if (raiseException): raise Exception("Can't create RR, error: %d" % res[0]) + if (raiseException): + raise Exception("Can't create RR, error: %d" % res[0]) return None return res[1:] @staticmethod def new_frm_fp_l(file, default_ttl=0, origin=None, prev=None, raiseException=True): - """Creates a new rr from a file containing a string. - - :param file: file pointer - :param default_ttl: If 0 DEF_TTL will be used - :param origin: when the owner is relative add this. - :param prev: when the owner is whitespaces use this. - :param raiseException: if True, an exception occurs in case a resolver object can't be created - :returns: - * rr - (ldns_rr) RR object or None. If the object can't be created and raiseException is True, an exception occurs. - - * line - (int) line number (for debugging) - - * ttl - (int) None or TTL if the file contains a $TTL directive - - * origin - (ldns_rdf) None or dname if the file contains a $ORIGIN directive - - * prev - (ldns_rdf) None or updated value of prev parameter """ - res = _ldns.ldns_rr_new_frm_fp_l_(file, default_ttl, origin, prev, 1) + Creates a new rr from a file containing a string. + + :param file: Opened file. + :param default_ttl: If 0 DEF_TTL will be used. + :type default_ttl: int + :param origin: When the owner is relative add this. + :type origin: :class:`ldns_dname` + :param prev: When the owner is white spaces use this. + :type prev: :class:`ldns_rdf` + :param raiseException: Iif True, an exception occurs in case + a resolver object can't be created. + :throws Exception: If `raiseException` is set and the input + cannot be read. + :throws TypeError: When parameters of incorrect types. + :return: None when fails, otherwise a tuple containing: + + * rr - (:class:`ldns_rr`) RR object or None. If the object + can't be created and `raiseException` is True, + an exception occurs. + + * line - (int) line number (for debugging). + + * ttl - (int) None or TTL if the file contains a TTL + directive . + + * origin - (:class:`ldns_rdf`) None or dname rdf if the file + contains a ORIGIN directive. + + * prev - (:class:`ldns_rdf`) None or updated value of prev + parameter. + + .. note:: + The type checking of `origin` is benevolent. + It allows also to pass a dname :class:`ldns_rdf` object. + This will probably change in future. + """ + if (not isinstance(origin, ldns_dname)) and \ + isinstance(origin, ldns_rdf) and \ + origin.get_type() == _ldns.LDNS_RDF_TYPE_DNAME: + warnings.warn("The ldns_rr.new_frm_fp_l() method will" + + " drop the possibility to accept ldns_rdf as origin." + + " Convert argument to ldns_dname.", + PendingDeprecationWarning, stacklevel=2) + res = _ldns.ldns_rr_new_frm_fp_l_(file, default_ttl, origin, prev) if res[0] != LDNS_STATUS_OK: - if (raiseException): raise Exception("Can't create RR, error: %d" % res[0]) + if (raiseException): + raise Exception("Can't create RR, error: %d" % res[0]) return None return res[1:] - #_LDNS_RR_CONSTRUCTORS# + # + # _LDNS_RR_CONSTRUCTORS + # def __str__(self): - """converts the data in the resource record to presentation format""" + """ + Converts the data in the resource record to presentation format. + + :return: (str) + """ return _ldns.ldns_rr2str(self) def __cmp__(self, other): - """compares two rrs. + """ + Compares two rrs. The TTL is not looked at. - :param other: - the second RR one - :returns: (int) 0 if equal -1 if self comes before other RR +1 if other RR comes before self + :param other: The second RR one. + :type other: :class:`ldns_rr` + :throws TypeError: When `other` of non-:class:`ldns_rr` type. + :return: (int) 0 if equal, -1 if `self` comes before `other`, + 1 if `other` RR comes before `self`. """ - return _ldns.ldns_rr_compare(self,other) + return _ldns.ldns_rr_compare(self, other) + + def __lt__(self, other): + """ + Compares two rrs. + + The TTL is not looked at. + + :param other: The second RR one. + :type other: :class:`ldns_rr` + :throws TypeError: When `other` of non-:class:`ldns_rr` type. + :return: (bool) True when `self` is less than 'other'. + """ + return _ldns.ldns_rr_compare(self, other) == -1 + + def __le__(self, other): + """ + Compares two rrs. + + The TTL is not looked at. + + :param other: The second RR one. + :type other: :class:`ldns_rr` + :throws TypeError: When `other` of non-:class:`ldns_rr` type. + :return: (bool) True when `self` is less than or equal to + 'other'. + """ + return _ldns.ldns_rr_compare(self, other) != 1 + + def __eq__(self, other): + """ + Compares two rrs. + + The TTL is not looked at. + + :param other: The second RR one. + :type other: :class:`ldns_rr` + :throws TypeError: When `other` of non-:class:`ldns_rr` type. + :return: (bool) True when `self` is equal to 'other'. + """ + return _ldns.ldns_rr_compare(self, other) == 0 + + def __ne__(self, other): + """ + Compares two rrs. + + The TTL is not looked at. + + :param other: The second RR one. + :type other: :class:`ldns_rr` + :throws TypeError: When `other` of non-:class:`ldns_rr` type. + :return: (bool) True when `self` is not equal to 'other'. + """ + return _ldns.ldns_rr_compare(self, other) != 0 + + def __gt__(self, other): + """ + Compares two rrs. + + The TTL is not looked at. + + :param other: The second RR one. + :type other: :class:`ldns_rr` + :throws TypeError: When `other` of non-:class:`ldns_rr` type. + :return: (bool) True when `self` is greater than 'other'. + """ + return _ldns.ldns_rr_compare(self, other) == 1 + + def __ge__(self, other): + """ + Compares two rrs. + + The TTL is not looked at. + + :param other: The second RR one. + :type other: :class:`ldns_rr` + :throws TypeError: When `other` of non-:class:`ldns_rr` type. + :return: (bool) True when `self` is greater than or equal to + 'other'. + """ + return _ldns.ldns_rr_compare(self, other) != -1 + + @staticmethod + def class_by_name(string): + """ + Retrieves a class identifier value by looking up its name. + + :param string: Class name. + :type string: str + :throws TypeError: when `string` of inappropriate type. + :return: (int) Class identifier value, or 0 if not valid + class name given. + """ + return _ldns.ldns_get_rr_class_by_name(string) def rdfs(self): - """returns the list of rdata records.""" - for i in range(0,self.rd_count()): + """ + Returns a generator object of rdata records. + + :return: Generator of :class:`ldns_rdf`. + """ + for i in range(0, self.rd_count()): yield self.rdf(i) - def print_to_file(self,output): - """Prints the data in the resource record to the given file stream (in presentation format).""" - _ldns.ldns_rr_print(output,self) - #parameters: FILE *,const ldns_rr *, + def print_to_file(self, output): + """ + Prints the data in the resource record to the given file stream + (in presentation format). + + :param output: Opened file stream. + :throws TypeError: When `output` not a file. + """ + _ldns.ldns_rr_print(output, self) + #parameters: FILE *, const ldns_rr *, def get_type_str(self): - """Converts an RR type value to its string representation, and returns that string.""" + """ + Converts an RR type value to its string representation, + and returns that string. + + :return: (str) containing type identification. + """ return _ldns.ldns_rr_type2str(self.get_type()) #parameters: const ldns_rr_type, def get_class_str(self): - """Converts an RR class value to its string representation, and returns that string.""" + """ + Converts an RR class value to its string representation, + and returns that string. + + :return: (str) containing class identification. + """ return _ldns.ldns_rr_class2str(self.get_class()) #parameters: const ldns_rr_class, @staticmethod - def dnskey_key_size_raw(keydata,len,alg): - """get the length of the keydata in bits""" - return _ldns.ldns_rr_dnskey_key_size_raw(keydata,len,alg) + def dnskey_key_size_raw(keydata, len, alg): + """ + Get the length of the keydata in bits. + + :param keydata: Key raw data. + :type keydata: unsigned char \* + :param len: Number of bytes of `keydata`. + :type len: size_t + :param alg: Algorithm identifier. + :type alg: ldns_algorithm + + :return: (size_t) The length of key data in bits. + """ + return _ldns.ldns_rr_dnskey_key_size_raw(keydata, len, alg) #parameters: const unsigned char *,const size_t,const ldns_algorithm, #retvals: size_t def write_to_buffer(self,buffer,section): - """Copies the rr data to the buffer in wire format. - - :param buffer: buffer to append the result to buffer - :param section: the section in the packet this rr is supposed to be in (to determine whether to add rdata or not) - :returns: (ldns_status) ldns_status """ - return _ldns.ldns_rr2buffer_wire(buffer,self,section) + Copies the rr data to the buffer in wire format. + + :param buffer: Buffer to append the result to. + :type buffer: :class:`ldns_buffer` + :param section: The section in the packet this rr is supposed + to be in (to determine whether to add rdata or not). + :type section: int + :throws TypeError: when arguments of mismatching types passed. + :return: (ldns_status) ldns_status + """ + return _ldns.ldns_rr2buffer_wire(buffer, self, section) #parameters: ldns_buffer *,const ldns_rr *,int, #retvals: ldns_status def write_to_buffer_canonical(self,buffer,section): - """Copies the rr data to the buffer in wire format, in canonical format according to RFC3597 (every dname in rdata fields of RR's mentioned in that RFC will be lowercased). + """ + Copies the rr data to the buffer in wire format, in canonical + format according to RFC3597 (every dname in rdata fields + of RR's mentioned in that RFC will be converted to lower-case). - :param buffer: buffer to append the result to buffer - :param section: the section in the packet this rr is supposed to be in (to determine whether to add rdata or not) - :returns: (ldns_status) ldns_status + :param buffer: Buffer to append the result to. + :type buffer: :class:`ldns_buffer` + :param section: The section in the packet this rr is supposed + to be in (to determine whether to add rdata or not). + :type section: int + :throws TypeError: when arguments of mismatching types passed. + :return: (ldns_status) ldns_status """ return _ldns.ldns_rr2buffer_wire_canonical(buffer,self,section) #parameters: ldns_buffer *,const ldns_rr *,int, #retvals: ldns_status - def write_data_to_buffer(self,buffer): - """Converts an rr's rdata to wireformat, while excluding the ownername and all the stuff before the rdata. + def write_data_to_buffer(self, buffer): + """ + Converts an rr's rdata to wire format, while excluding the + owner name and all the stuff before the rdata. - This is needed in DNSSEC keytag calculation, the ds calcalution from the key and maybe elsewhere. + This is needed in DNSSEC key-tag calculation, the ds + calculation from the key and maybe elsewhere. - :param buffer: buffer to append the result to - :returns: (ldns_status) ldns_status + :param buffer: Buffer to append the result to. + :type buffer: :class:`ldns_buffer` + :throws TypeError: when `buffer` of non-:class:`ldns_buffer` + type. + :return: (ldns_status) ldns_status """ return _ldns.ldns_rr_rdata2buffer_wire(buffer,self) - #parameters: ldns_buffer *,const ldns_rr *, + #parameters: ldns_buffer *, const ldns_rr *, #retvals: ldns_status - def write_rrsig_to_buffer(self,buffer): - """Converts a rrsig to wireformat BUT EXCLUDE the rrsig rdata + def write_rrsig_to_buffer(self, buffer): + """ + Converts a rrsig to wire format BUT EXCLUDE the rrsig rdata. This is needed in DNSSEC verification. - :param buffer: buffer to append the result to - :returns: (ldns_status) ldns_status + :param buffer: Buffer to append the result to. + :type buffer: :class:`ldns_buffer` + :throws TypeError: when `buffer` of non-:class:`ldns_buffer` + type. + :return: (ldns_status) ldns_status """ return _ldns.ldns_rrsig2buffer_wire(buffer,self) #parameters: ldns_buffer *,const ldns_rr *, #retvals: ldns_status - #LDNS_RR_METHODS_# + # + # LDNS_RR_METHODS_ + # + def a_address(self): - """returns the address of a LDNS_RR_TYPE_A rr + """ + Returns the address rdf of a LDNS_RR_TYPE_A or LDNS_RR_TYPE_AAAA + rr. - :returns: (ldns_rdf \*) a ldns_rdf* with the address or NULL on failure + :return: (:class:`ldns_rdf`) with the address or None on + failure. """ return _ldns._ldns_rr_a_address(self) #parameters: const ldns_rr *, #retvals: ldns_rdf * - def a_set_address(self,f): - """sets the address of a LDNS_RR_TYPE_A rr - - :param f: - the address to set - :returns: (bool) true on success, false otherwise + def a_set_address(self, f): """ - return _ldns._ldns_rr_a_set_address(self,f) - #parameters: ldns_rr *,ldns_rdf *, + Sets the address of a LDNS_RR_TYPE_A or LDNS_RR_TYPE_AAAA rr. + + :param f: The address to be set. + :type f: :class:`ldns_rdf` + :throws TypeError: When `f` of non-:class:`ldns_rdf` type. + :return: (bool) True on success, False otherwise. + """ + return _ldns._ldns_rr_a_set_address(self, f) + #parameters: ldns_rr *, ldns_rdf *, #retvals: bool def clone(self): - """clones a rr and all its data + """ + Clones a rr and all its data. - :returns: (ldns_rr \*) the new rr or NULL on failure + :return: (:class:`ldns_rr`) The new rr or None on failure. """ return _ldns.ldns_rr_clone(self) #parameters: const ldns_rr *, #retvals: ldns_rr * - - def compare_ds(self,rr2): - """returns true of the given rr's are equal. - - Also returns true if one record is a DS that represents the same DNSKEY record as the other record - - :param rr2: - the second rr - :returns: (bool) true if equal otherwise false + + def compare_ds(self, rr2): """ - return _ldns.ldns_rr_compare_ds(self,rr2) - #parameters: const ldns_rr *,const ldns_rr *, + Returns True if the given rr's are equal. + + Also returns True if one record is a DS that represents the + same DNSKEY record as the other record. + + :param rr2: The second rr. + :type rr2: :class:`ldns_rr` + :throws TypeError: When `rr2` of non-:class:`ldns_rr` type. + :return: (bool) True if equal otherwise False. + """ + return _ldns.ldns_rr_compare_ds(self, rr2) + #parameters: const ldns_rr *, const ldns_rr *, #retvals: bool - def compare_no_rdata(self,rr2): - """compares two rrs, up to the rdata. - - :param rr2: - the second one - :returns: (int) 0 if equal -1 if rr1 comes before rr2 +1 if rr2 comes before rr1 + def compare_no_rdata(self, rr2): """ - return _ldns.ldns_rr_compare_no_rdata(self,rr2) - #parameters: const ldns_rr *,const ldns_rr *, + Compares two rrs, up to the rdata. + + :param rr2: Rhe second rr. + :type rr2: :class:`ldns_rr` + :throws TypeError: When `rr2` of non-:class:`ldns_rr` type. + :return: (int) 0 if equal, negative integer if `self` comes + before `rr2`, positive integer if `rr2` comes before `self`. + """ + return _ldns.ldns_rr_compare_no_rdata(self, rr2) + #parameters: const ldns_rr *, const ldns_rr *, #retvals: int def dnskey_algorithm(self): - """returns the algorithm of a LDNS_RR_TYPE_DNSKEY rr + """ + Returns the algorithm of a LDNS_RR_TYPE_DNSKEY rr. - :returns: (ldns_rdf \*) a ldns_rdf* with the algorithm or NULL on failure + :return: (:class:`ldns_rdf`) with the algorithm or None + on failure. """ return _ldns._ldns_rr_dnskey_algorithm(self) #parameters: const ldns_rr *, #retvals: ldns_rdf * def dnskey_flags(self): - """returns the flags of a LDNS_RR_TYPE_DNSKEY rr + """ + Returns the flags of a LDNS_RR_TYPE_DNSKEY rr. - :returns: (ldns_rdf \*) a ldns_rdf* with the flags or NULL on failure + :return: (:class:`ldns_rdf`) with the flags or None on failure. """ return _ldns._ldns_rr_dnskey_flags(self) #parameters: const ldns_rr *, #retvals: ldns_rdf * def dnskey_key(self): - """returns the key data of a LDNS_RR_TYPE_DNSKEY rr + """ + Returns the key data of a LDNS_RR_TYPE_DNSKEY rr. - :returns: (ldns_rdf \*) a ldns_rdf* with the key data or NULL on failure + :return: (:class:`ldns_rdf`) with the key data or None on + failure. """ return _ldns._ldns_rr_dnskey_key(self) #parameters: const ldns_rr *, #retvals: ldns_rdf * def dnskey_key_size(self): - """get the length of the keydata in bits + """ + Get the length of the keydata in bits. - :returns: (size_t) the keysize in bits + :return: (size_t) the keysize in bits. """ return _ldns.ldns_rr_dnskey_key_size(self) #parameters: const ldns_rr *, #retvals: size_t def dnskey_protocol(self): - """returns the protocol of a LDNS_RR_TYPE_DNSKEY rr + """ + Returns the protocol of a LDNS_RR_TYPE_DNSKEY rr. - :returns: (ldns_rdf \*) a ldns_rdf* with the protocol or NULL on failure + :return: (:class:`ldns_rdf`) with the protocol or None on + failure. """ return _ldns._ldns_rr_dnskey_protocol(self) #parameters: const ldns_rr *, #retvals: ldns_rdf * - def dnskey_set_algorithm(self,f): - """sets the algorithm of a LDNS_RR_TYPE_DNSKEY rr - - :param f: - the algorithm to set - :returns: (bool) true on success, false otherwise + def dnskey_set_algorithm(self, f): """ - return _ldns._ldns_rr_dnskey_set_algorithm(self,f) - #parameters: ldns_rr *,ldns_rdf *, + Sets the algorithm of a LDNS_RR_TYPE_DNSKEY rr + + :param f: The algorithm to set. + :type f: :class:`ldns_rdf` + :throws TypeError: When `f` of non-:class:`ldns_rdf` type. + :return: (bool) True on success, False otherwise. + """ + return _ldns._ldns_rr_dnskey_set_algorithm(self, f) + #parameters: ldns_rr *, ldns_rdf *, #retvals: bool - def dnskey_set_flags(self,f): - """sets the flags of a LDNS_RR_TYPE_DNSKEY rr - - :param f: - the flags to set - :returns: (bool) true on success, false otherwise + def dnskey_set_flags(self, f): """ - return _ldns._ldns_rr_dnskey_set_flags(self,f) - #parameters: ldns_rr *,ldns_rdf *, + Sets the flags of a LDNS_RR_TYPE_DNSKEY rr. + + :param f: The flags to be set. + :type f: :class:`ldns_rdf` + :throws TypeError: When `f` of non-:class:`ldns_rdf` type. + :return: (bool) True on success, False otherwise. + """ + return _ldns._ldns_rr_dnskey_set_flags(self, f) + #parameters: ldns_rr *, ldns_rdf *, #retvals: bool - def dnskey_set_key(self,f): - """sets the key data of a LDNS_RR_TYPE_DNSKEY rr - - :param f: - the key data to set - :returns: (bool) true on success, false otherwise + def dnskey_set_key(self, f): """ - return _ldns._ldns_rr_dnskey_set_key(self,f) - #parameters: ldns_rr *,ldns_rdf *, + Sets the key data of a LDNS_RR_TYPE_DNSKEY rr. + + :param f: The key data to set. + :type f: :class:`ldns_rdf` + :throws TypeError: When `f` of non-:class:`ldns_rdf` type. + :return: (bool) True on success, False otherwise. + """ + return _ldns._ldns_rr_dnskey_set_key(self, f) + #parameters: ldns_rr *, ldns_rdf *, #retvals: bool def dnskey_set_protocol(self,f): - """sets the protocol of a LDNS_RR_TYPE_DNSKEY rr + """ + Sets the protocol of a LDNS_RR_TYPE_DNSKEY rr. - :param f: - the protocol to set - :returns: (bool) true on success, false otherwise + :param f: The protocol to set. + :type f: :class:`ldns_rdf` + :throws TypeError: When `f` of non-:class:`ldns_rdf` type. + :return: (bool) True on success, False otherwise. """ return _ldns._ldns_rr_dnskey_set_protocol(self,f) #parameters: ldns_rr *,ldns_rdf *, #retvals: bool def get_class(self): - """returns the class of the rr. + """ + Returns the class of the rr. - :returns: (ldns_rr_class) the class of the rr + :return: (int) The class identifier of the rr. """ return _ldns.ldns_rr_get_class(self) #parameters: const ldns_rr *, #retvals: ldns_rr_class def get_type(self): - """returns the type of the rr. + """ + Returns the type of the rr. - :returns: (ldns_rr_type) the type of the rr + :return: (int) The type identifier of the rr. """ return _ldns.ldns_rr_get_type(self) #parameters: const ldns_rr *, #retvals: ldns_rr_type + def is_question(self): + """ + Returns the question flag of a rr structure. + + :return: (bool) True if question flag is set. + """ + return _ldns.ldns_rr_is_question(self) + def label_count(self): - """counts the number of labels of the ownername. + """ + Counts the number of labels of the owner name. - :returns: (uint8_t) the number of labels + :return: (int) The number of labels. """ return _ldns.ldns_rr_label_count(self) #parameters: ldns_rr *, #retvals: uint8_t def mx_exchange(self): - """returns the mx host of a LDNS_RR_TYPE_MX rr + """ + Returns the mx host of a LDNS_RR_TYPE_MX rr. - :returns: (ldns_rdf \*) a ldns_rdf* with the name of the MX host or NULL on failure + :return: (:class:`ldns_rdf`) with the name of the MX host + or None on failure. """ return _ldns._ldns_rr_mx_exchange(self) #parameters: const ldns_rr *, #retvals: ldns_rdf * def mx_preference(self): - """returns the mx pref. + """ + Returns the mx preference of a LDNS_RR_TYPE_MX rr. - of a LDNS_RR_TYPE_MX rr - - :returns: (ldns_rdf \*) a ldns_rdf* with the preference or NULL on failure + :return: (:class:`ldns_rdf`) with the preference or None + on failure. """ return _ldns._ldns_rr_mx_preference(self) #parameters: const ldns_rr *, #retvals: ldns_rdf * def ns_nsdname(self): - """returns the name of a LDNS_RR_TYPE_NS rr + """ + Returns the name of a LDNS_RR_TYPE_NS rr. - :returns: (ldns_rdf \*) a ldns_rdf* with the name or NULL on failure + :return: (:class:`ldns_rdf`) A dname rdf with the name or + None on failure. """ return _ldns._ldns_rr_ns_nsdname(self) #parameters: const ldns_rr *, #retvals: ldns_rdf * def owner(self): - """returns the owner name of an rr structure. - - :returns: (ldns_rdf \*) ldns_rdf * """ - return _ldns._ldns_rr_owner(self) + Returns the owner name of an rr structure. + + :return: (:class:`ldns_dname`) Owner name or None on failure. + """ + rdf = _ldns._ldns_rr_owner(self) + if rdf: + rdf = ldns_dname(rdf, clone=False) + return rdf #parameters: const ldns_rr *, #retvals: ldns_rdf * def pop_rdf(self): - """removes a rd_field member, it will be popped from the last position. + """ + Removes a rd_field member, it will be popped from the last + position. - :returns: (ldns_rdf \*) rdf which was popped (null if nothing) + :return: (:class:`ldns_rdf`) rdf which was popped, None if + nothing. """ return _ldns.ldns_rr_pop_rdf(self) #parameters: ldns_rr *, #retvals: ldns_rdf * def push_rdf(self,f): - """sets rd_field member, it will be placed in the next available spot. - - :param f: - :returns: (bool) bool """ - return _ldns._ldns_rr_push_rdf(self,f) - #parameters: ldns_rr *,const ldns_rdf *, + Sets rd_field member, it will be placed in the next available + spot. + + :param f: The rdf to be appended. + :type f: :class:`ldns_rdf` + :throws TypeError: When `f` of non-:class:`ldns_rdf` type. + :return: (bool) Returns True if success, False otherwise. + """ + return _ldns._ldns_rr_push_rdf(self, f) + #parameters: ldns_rr *, const ldns_rdf *, #retvals: bool def rd_count(self): - """returns the rd_count of an rr structure. + """ + Returns the rd_count of an rr structure. - :returns: (size_t) the rd count of the rr + :return: (size_t) the rd count of the rr. """ return _ldns.ldns_rr_rd_count(self) #parameters: const ldns_rr *, #retvals: size_t - def rdf(self,nr): - """returns the rdata field member counter. - - :param nr: - the number of the rdf to return - :returns: (ldns_rdf \*) ldns_rdf * + def rdf(self, nr): """ - return _ldns._ldns_rr_rdf(self,nr) - #parameters: const ldns_rr *,size_t, + Returns the rdata field with the given index. + + :param nr: The index of the rdf to return. + :type nr: positive int + :throws TypeError: When `nr` not a positive integer. + :return: (:class:`ldns_rdf`) The given rdf or None if fails. + """ + return _ldns._ldns_rr_rdf(self, nr) + #parameters: const ldns_rr *, size_t, #retvals: ldns_rdf * def rrsig_algorithm(self): - """returns the algorithm of a LDNS_RR_TYPE_RRSIG RR + """ + Returns the algorithm identifier of a LDNS_RR_TYPE_RRSIG RR. - :returns: (ldns_rdf \*) a ldns_rdf* with the algorithm or NULL on failure + :return: (:class:`ldns_rdf`) with the algorithm or None + on failure. """ return _ldns._ldns_rr_rrsig_algorithm(self) #parameters: const ldns_rr *, #retvals: ldns_rdf * def rrsig_expiration(self): - """returns the expiration time of a LDNS_RR_TYPE_RRSIG RR + """ + Returns the expiration time of a LDNS_RR_TYPE_RRSIG RR. - :returns: (ldns_rdf \*) a ldns_rdf* with the expiration time or NULL on failure + :return: (:class:`ldns_rdf`) with the expiration time or None + on failure. """ return _ldns._ldns_rr_rrsig_expiration(self) #parameters: const ldns_rr *, #retvals: ldns_rdf * def rrsig_inception(self): - """returns the inception time of a LDNS_RR_TYPE_RRSIG RR + """ + Returns the inception time of a LDNS_RR_TYPE_RRSIG RR. - :returns: (ldns_rdf \*) a ldns_rdf* with the inception time or NULL on failure + :return: (:class:`ldns_rdf`) with the inception time or None + on failure. """ return _ldns._ldns_rr_rrsig_inception(self) #parameters: const ldns_rr *, #retvals: ldns_rdf * def rrsig_keytag(self): - """returns the keytag of a LDNS_RR_TYPE_RRSIG RR + """ + Returns the keytag of a LDNS_RR_TYPE_RRSIG RR. - :returns: (ldns_rdf \*) a ldns_rdf* with the keytag or NULL on failure + :return: (:class:`ldns_rdf`) with the keytag or None on failure. """ return _ldns._ldns_rr_rrsig_keytag(self) #parameters: const ldns_rr *, #retvals: ldns_rdf * def rrsig_labels(self): - """returns the number of labels of a LDNS_RR_TYPE_RRSIG RR + """ + Returns the number of labels of a LDNS_RR_TYPE_RRSIG RR. - :returns: (ldns_rdf \*) a ldns_rdf* with the number of labels or NULL on failure + :return: (:class:`ldns_rdf`) with the number of labels or None + on failure. """ return _ldns._ldns_rr_rrsig_labels(self) #parameters: const ldns_rr *, #retvals: ldns_rdf * def rrsig_origttl(self): - """returns the original TTL of a LDNS_RR_TYPE_RRSIG RR + """ + Returns the original TTL of a LDNS_RR_TYPE_RRSIG RR. - :returns: (ldns_rdf \*) a ldns_rdf* with the original TTL or NULL on failure + :return: (:class:`ldns_rdf`) with the original TTL or None + on failure. """ return _ldns._ldns_rr_rrsig_origttl(self) #parameters: const ldns_rr *, #retvals: ldns_rdf * - def rrsig_set_algorithm(self,f): - """sets the algorithm of a LDNS_RR_TYPE_RRSIG rr - - :param f: - the algorithm to set - :returns: (bool) true on success, false otherwise + def rrsig_set_algorithm(self, f): """ - return _ldns._ldns_rr_rrsig_set_algorithm(self,f) - #parameters: ldns_rr *,ldns_rdf *, + Sets the algorithm of a LDNS_RR_TYPE_RRSIG rr. + + :param f: The algorithm to set. + :type f: :class:`ldns_rdf` + :throws TypeError: when `f` of non-:class:`ldns_rdf` type. + :return: (bool) True on success, False otherwise. + """ + return _ldns._ldns_rr_rrsig_set_algorithm(self, f) + #parameters: ldns_rr *, ldns_rdf *, #retvals: bool - def rrsig_set_expiration(self,f): - """sets the expireation date of a LDNS_RR_TYPE_RRSIG rr - - :param f: - the expireation date to set - :returns: (bool) true on success, false otherwise + def rrsig_set_expiration(self, f): """ - return _ldns._ldns_rr_rrsig_set_expiration(self,f) - #parameters: ldns_rr *,ldns_rdf *, + Sets the expireation date of a LDNS_RR_TYPE_RRSIG rr. + + :param f: The expireation date to set. + :type f: :class:`ldns_rdf` + :throws TypeError: when `f` of non-:class:`ldns_rdf` type. + :return: (bool) True on success, False otherwise. + """ + return _ldns._ldns_rr_rrsig_set_expiration(self, f) + #parameters: ldns_rr *, ldns_rdf *, #retvals: bool - def rrsig_set_inception(self,f): - """sets the inception date of a LDNS_RR_TYPE_RRSIG rr - - :param f: - the inception date to set - :returns: (bool) true on success, false otherwise + def rrsig_set_inception(self, f): """ - return _ldns._ldns_rr_rrsig_set_inception(self,f) - #parameters: ldns_rr *,ldns_rdf *, + Sets the inception date of a LDNS_RR_TYPE_RRSIG rr. + + :param f: The inception date to set. + :type f: :class:`ldns_rdf` + :throws TypeError: when `f` of non-:class:`ldns_rdf` type. + :return: (bool) True on success, False otherwise. + """ + return _ldns._ldns_rr_rrsig_set_inception(self, f) + #parameters: ldns_rr *, ldns_rdf *, #retvals: bool - def rrsig_set_keytag(self,f): - """sets the keytag of a LDNS_RR_TYPE_RRSIG rr - - :param f: - the keytag to set - :returns: (bool) true on success, false otherwise + def rrsig_set_keytag(self, f): """ - return _ldns._ldns_rr_rrsig_set_keytag(self,f) - #parameters: ldns_rr *,ldns_rdf *, + Sets the keytag of a LDNS_RR_TYPE_RRSIG rr. + + :param f: The keytag to set. + :type f: :class:`ldns_rdf` + :throws TypeError: when `f` of non-:class:`ldns_rdf` type. + :return: (bool) True on success, False otherwise. + """ + return _ldns._ldns_rr_rrsig_set_keytag(self, f) + #parameters: ldns_rr *, ldns_rdf *, #retvals: bool - def rrsig_set_labels(self,f): - """sets the number of labels of a LDNS_RR_TYPE_RRSIG rr - - :param f: - the number of labels to set - :returns: (bool) true on success, false otherwise + def rrsig_set_labels(self, f): """ - return _ldns._ldns_rr_rrsig_set_labels(self,f) - #parameters: ldns_rr *,ldns_rdf *, + Sets the number of labels of a LDNS_RR_TYPE_RRSIG rr. + + :param f: The number of labels to set. + :type f: :class:`ldns_rdf` + :throws TypeError: when `f` of non-:class:`ldns_rdf` type. + :return: (bool) True on success, False otherwise. + """ + return _ldns._ldns_rr_rrsig_set_labels(self, f) + #parameters: ldns_rr *, ldns_rdf *, #retvals: bool - def rrsig_set_origttl(self,f): - """sets the original TTL of a LDNS_RR_TYPE_RRSIG rr - - :param f: - the original TTL to set - :returns: (bool) true on success, false otherwise + def rrsig_set_origttl(self, f): """ - return _ldns._ldns_rr_rrsig_set_origttl(self,f) - #parameters: ldns_rr *,ldns_rdf *, + Sets the original TTL of a LDNS_RR_TYPE_RRSIG rr. + + :param f: The original TTL to set. + :type f: :class:`ldns_rdf` + :throws TypeError: when `f` of non-:class:`ldns_rdf` type. + :return: (bool) True on success, False otherwise. + """ + return _ldns._ldns_rr_rrsig_set_origttl(self, f) + #parameters: ldns_rr *, ldns_rdf *, #retvals: bool - def rrsig_set_sig(self,f): - """sets the signature data of a LDNS_RR_TYPE_RRSIG rr - - :param f: - the signature data to set - :returns: (bool) true on success, false otherwise + def rrsig_set_sig(self, f): """ - return _ldns._ldns_rr_rrsig_set_sig(self,f) - #parameters: ldns_rr *,ldns_rdf *, + Sets the signature data of a LDNS_RR_TYPE_RRSIG rr. + + :param f: The signature data to set. + :type f: :class:`ldns_rdf` + :throws TypeError: when `f` of non-:class:`ldns_rdf` type. + :return: (bool) True on success, False otherwise. + """ + return _ldns._ldns_rr_rrsig_set_sig(self, f) + #parameters: ldns_rr *, ldns_rdf *, #retvals: bool - def rrsig_set_signame(self,f): - """sets the signers name of a LDNS_RR_TYPE_RRSIG rr - - :param f: - the signers name to set - :returns: (bool) true on success, false otherwise + def rrsig_set_signame(self, f): """ - return _ldns._ldns_rr_rrsig_set_signame(self,f) - #parameters: ldns_rr *,ldns_rdf *, + Sets the signers name of a LDNS_RR_TYPE_RRSIG rr. + + :param f: The signers name to set. + :type f: :class:`ldns_rdf` + :throws TypeError: when `f` of non-:class:`ldns_rdf` type. + :return: (bool) True on success, False otherwise. + """ + return _ldns._ldns_rr_rrsig_set_signame(self, f) + #parameters: ldns_rr *, ldns_rdf *, #retvals: bool - def rrsig_set_typecovered(self,f): - """sets the typecovered of a LDNS_RR_TYPE_RRSIG rr - - :param f: - the typecovered to set - :returns: (bool) true on success, false otherwise + def rrsig_set_typecovered(self, f): """ - return _ldns._ldns_rr_rrsig_set_typecovered(self,f) - #parameters: ldns_rr *,ldns_rdf *, + Sets the typecovered of a LDNS_RR_TYPE_RRSIG rr. + + :param f: The type covered to set. + :type f: :class:`ldns_rdf` + :throws TypeError: when `f` of non-:class:`ldns_rdf` type. + :return: (bool) True on success, False otherwise. + """ + return _ldns._ldns_rr_rrsig_set_typecovered(self, f) + #parameters: ldns_rr *, ldns_rdf *, #retvals: bool def rrsig_sig(self): - """returns the signature data of a LDNS_RR_TYPE_RRSIG RR + """ + Returns the signature data of a LDNS_RR_TYPE_RRSIG RR. - :returns: (ldns_rdf \*) a ldns_rdf* with the signature data or NULL on failure + :return: (:class:`ldns_rdf`) with the signature data or None + on failure. """ return _ldns._ldns_rr_rrsig_sig(self) #parameters: const ldns_rr *, #retvals: ldns_rdf * def rrsig_signame(self): - """returns the signers name of a LDNS_RR_TYPE_RRSIG RR + """ + Returns the signers name of a LDNS_RR_TYPE_RRSIG RR. - :returns: (ldns_rdf \*) a ldns_rdf* with the signers name or NULL on failure + :return: (:class:`ldns_rdf`) with the signers name or None + on failure. """ return _ldns._ldns_rr_rrsig_signame(self) #parameters: const ldns_rr *, #retvals: ldns_rdf * def rrsig_typecovered(self): - """returns the type covered of a LDNS_RR_TYPE_RRSIG rr + """ + Returns the type covered of a LDNS_RR_TYPE_RRSIG rr. - :returns: (ldns_rdf \*) a ldns_rdf* with the type covered or NULL on failure + :return: (:class:`ldns_rdf`) with the type covered or None + on failure. """ return _ldns._ldns_rr_rrsig_typecovered(self) #parameters: const ldns_rr *, #retvals: ldns_rdf * - def set_class(self,rr_class): - """sets the class in the rr. - - :param rr_class: - set to this class + def set_class(self, rr_class): """ - _ldns.ldns_rr_set_class(self,rr_class) - #parameters: ldns_rr *,ldns_rr_class, + Sets the class in the rr. + + :param rr_class: Set to this class. + :type rr_class: int + :throws TypeError: when `rr_class` of non-integer type. + """ + _ldns.ldns_rr_set_class(self, rr_class) + #parameters: ldns_rr *, ldns_rr_class, #retvals: - def set_owner(self,owner): - """sets the owner in the rr structure. - - :param owner: + def set_owner(self, owner): """ - _ldns._ldns_rr_set_owner(self,owner) - #parameters: ldns_rr *,ldns_rdf *, + Sets the owner in the rr structure. + + :param owner: Owner name. + :type owner: :class:`ldns_dname` + :throws TypeError: when `owner` of non-:class:`ldns_dname` type. + + .. note:: + The type checking of `owner` is benevolent. + It allows also to pass a dname :class:`ldns_rdf` object. + This will probably change in future. + """ + if (not isinstance(owner, ldns_dname)) and \ + isinstance(owner, ldns_rdf) and \ + owner.get_type() == _ldns.LDNS_RDF_TYPE_DNAME: + warnings.warn("The ldns_rr.new_frm_str() method will" + + " drop the possibility to accept ldns_rdf as owner." + + " Convert argument to ldns_dname.", + PendingDeprecationWarning, stacklevel=2) + _ldns._ldns_rr_set_owner(self, owner) + #parameters: ldns_rr *, ldns_rdf *, + #retvals: + + def set_question(self, question): + """ + Sets the question flag in the rr structure. + + :param question: Question flag. + :type question: bool + """ + _ldns.ldns_rr_set_question(self, question) + #parameters: ldns_rr *, bool, + #retvals: + + def set_rd_count(self, count): + """ + Sets the rd_count in the rr. + + :param count: Set to this count. + :type count: positive int + :throws TypeError: when `count` of non-integer type. + """ + _ldns.ldns_rr_set_rd_count(self, count) + #parameters: ldns_rr *, size_t, #retvals: - def set_rd_count(self,count): - """sets the rd_count in the rr. - - :param count: - set to this count + def set_rdf(self, f, position): """ - _ldns.ldns_rr_set_rd_count(self,count) - #parameters: ldns_rr *,size_t, - #retvals: - - def set_rdf(self,f,position): - """sets a rdf member, it will be set on the position given. + Sets a rdf member, it will be set on the position given. The old value is returned, like pop. - :param f: - :param position: - the position the set the rdf - :returns: (ldns_rdf \*) the old value in the rr, NULL on failyre + :param f: The rdf to be set. + :type f: :class:`ldns_rdf` + :param position: The position the set the rdf. + :type position: positive int + :throws TypeError: when mismatching types passed. + :return: (:class:`ldns_rdf`) the old value in the rr, None + on failure. """ - return _ldns._ldns_rr_set_rdf(self,f,position) - #parameters: ldns_rr *,const ldns_rdf *,size_t, + return _ldns._ldns_rr_set_rdf(self, f, position) + #parameters: ldns_rr *, const ldns_rdf *, size_t, #retvals: ldns_rdf * - def set_ttl(self,ttl): - """sets the ttl in the rr structure. - - :param ttl: - set to this ttl + def set_ttl(self, ttl): """ - _ldns.ldns_rr_set_ttl(self,ttl) - #parameters: ldns_rr *,uint32_t, + Sets the ttl in the rr structure. + + :param ttl: Set to this ttl. + :type ttl: positive int + :throws TypeError: when `ttl` of non-integer type. + """ + _ldns.ldns_rr_set_ttl(self, ttl) + #parameters: ldns_rr *, uint32_t, #retvals: - def set_type(self,rr_type): - """sets the type in the rr. - - :param rr_type: - set to this type + def set_type(self, rr_type): """ - _ldns.ldns_rr_set_type(self,rr_type) - #parameters: ldns_rr *,ldns_rr_type, - #retvals: + Sets the type in the rr. + + :param rr_type: Set to this type. + :type rr_type: ineteger + :throws TypeError: when `rr_type` of non-integer type. + """ + _ldns.ldns_rr_set_type(self, rr_type) + #parameters: ldns_rr *, ldns_rr_type, + #retvals: + + def to_canonical(self): + """ + Converts each dname in a rr to its canonical form. + """ + _ldns.ldns_rr2canonical(self) def ttl(self): - """returns the ttl of an rr structure. + """ + Returns the ttl of an rr structure. - :returns: (uint32_t) the ttl of the rr + :return: (int) the ttl of the rr. """ return _ldns.ldns_rr_ttl(self) #parameters: const ldns_rr *, #retvals: uint32_t + @staticmethod + def type_by_name(string): + """ + Retrieves a rr type identifier value by looking up its name. + + Returns 0 if invalid name passed. + + :param string: RR type name. + :type string: str + :throws TypeError: when `string` of inappropriate type. + :return: (int) RR type identifier, or 0 if no matching value + to identifier found. + """ + return _ldns.ldns_get_rr_type_by_name(string) + def uncompressed_size(self): - """calculates the uncompressed size of an RR. + """ + Calculates the uncompressed size of an RR. - :returns: (size_t) size of the rr + :return: (inetger) size of the rr. """ return _ldns.ldns_rr_uncompressed_size(self) #parameters: const ldns_rr *, #retvals: size_t - #_LDNS_RR_METHODS# - %} + # + # _LDNS_RR_METHODS + # + %} } -%nodefaultctor ldns_struct_rr_list; //no default constructor & destructor -%nodefaultdtor ldns_struct_rr_list; + +/* ========================================================================= */ +/* SWIG setting and definitions. */ +/* ========================================================================= */ + + +%nodefaultctor ldns_struct_rr_list; /* No default constructor. */ +%nodefaultdtor ldns_struct_rr_list; /* No default destructor. */ %ignore ldns_struct_rr_list::_rrs; +%newobject ldns_rr_list_cat_clone; %newobject ldns_rr_list_clone; %newobject ldns_rr_list_pop_rr; %newobject ldns_rr_list_pop_rr_list; %newobject ldns_rr_list_pop_rrset; %newobject ldns_rr_list_rr; %newobject ldns_rr_list_new; +%newobject ldns_get_rr_list_hosts_frm_file; +%newobject ldns_rr_list_subtype_by_rdf; +%newobject ldns_rr_list2str; %delobject ldns_rr_list_deep_free; %delobject ldns_rr_list_free; +/* Clone data on push. */ + +%rename(__ldns_rr_list_push_rr) ldns_rr_list_push_rr; +%inline +%{ + bool _ldns_rr_list_push_rr(ldns_rr_list* r, ldns_rr *rr) + { + bool ret; + ldns_rr *new; + + new = ldns_rr_clone(rr); + if (!(ret = ldns_rr_list_push_rr(r, new))) { + ldns_rr_free(new); + } + return ret; + } +%} + +%rename(__ldns_rr_list_push_rr_list) ldns_rr_list_push_rr_list; +%inline +%{ + bool _ldns_rr_list_push_rr_list(ldns_rr_list* r, ldns_rr_list *r2) + { + bool ret; + ldns_rr_list *new; + + new = ldns_rr_list_clone(r2); + if (!(ret = ldns_rr_list_push_rr_list(r, new))) { + ldns_rr_list_deep_free(new); + } + return ret; + } +%} + + +%newobject _ldns_rr_list_set_rr; +%rename(__ldns_rr_list_set_rr) ldns_rr_list_set_rr; +%inline +%{ + ldns_rr * _ldns_rr_list_set_rr(ldns_rr_list * rrl, ldns_rr *rr, + size_t idx) + { + ldns_rr *ret; + ldns_rr *new; + + new = ldns_rr_clone(rr); + if ((ret = ldns_rr_list_set_rr(rrl, new, idx)) == NULL) { + ldns_rr_free(new); + } + return ret; + } +%} + + +%rename(__ldns_rr_list_cat) ldns_rr_list_cat; +%inline +%{ + bool _ldns_rr_list_cat(ldns_rr_list *r, ldns_rr_list *r2) + { + return ldns_rr_list_cat(r, ldns_rr_list_clone(r2)); + } +%} + + +/* End clone data on push. */ + + +/* Clone data on pull. */ + +%newobject _ldns_rr_list_rr; +%rename(__ldns_rr_list_rr) ldns_rr_list_rr; +%inline +%{ + ldns_rr * _ldns_rr_list_rr(ldns_rr_list *r, int i) + { + ldns_rr *rr; + rr = ldns_rr_list_rr(r, i); + return (rr != NULL) ? ldns_rr_clone(rr) : NULL; + } +%} + +%newobject _ldns_rr_list_owner; +%rename(__ldns_rr_list_owner) ldns_rr_list_owner; +%inline +%{ + ldns_rdf * _ldns_rr_list_owner(ldns_rr_list *r) + { + ldns_rdf *rdf; + rdf = ldns_rr_list_owner(r); + return (rdf != NULL) ? ldns_rdf_clone(rdf) : NULL; + } +%} + + +/* End clone data on pull. */ + + +/* ========================================================================= */ +/* Debugging related code. */ +/* ========================================================================= */ + + %rename(ldns_rr_list) ldns_struct_rr_list; #ifdef LDNS_DEBUG %rename(__ldns_rr_list_deep_free) ldns_rr_list_deep_free; %rename(__ldns_rr_list_free) ldns_rr_list_free; -%inline %{ -void _ldns_rr_list_free(ldns_rr_list* r) { - printf("******** LDNS_RR_LIST deep free 0x%lX ************\n", (long unsigned int)r); - ldns_rr_list_deep_free(r); -} +%inline +%{ + void _ldns_rr_list_deep_free(ldns_rr_list *r) + { + printf("******** LDNS_RR_LIST deep free 0x%lX ************\n", + (long unsigned int) r); + ldns_rr_list_deep_free(r); + } + + void _ldns_rr_list_free(ldns_rr_list *r) + { + printf("******** LDNS_RR_LIST deep free 0x%lX ************\n", + (long unsigned int) r); + ldns_rr_list_free(r); + } %} #else %rename(_ldns_rr_list_deep_free) ldns_rr_list_deep_free; %rename(_ldns_rr_list_free) ldns_rr_list_free; #endif -/* clone data on push */ -%rename(__ldns_rr_list_push_rr) ldns_rr_list_push_rr; -%inline %{ -void _ldns_rr_list_push_rr(ldns_rr_list* r, ldns_rr *rr) { - ldns_rr_list_push_rr(r, ldns_rr_clone(rr)); -} -%} - -%rename(__ldns_rr_list_push_rr_list) ldns_rr_list_push_rr_list; -%inline %{ -void _ldns_rr_list_push_rr_list(ldns_rr_list* r, ldns_rr_list *r2) { - ldns_rr_list_push_rr_list(r, ldns_rr_list_clone(r2)); -} -%} - -%rename(__ldns_rr_list_cat) ldns_rr_list_cat; -%inline %{ -void _ldns_rr_list_cat(ldns_rr_list* r, ldns_rr_list *r2) { - ldns_rr_list_cat(r, ldns_rr_list_clone(r2)); -} -%} +/* ========================================================================= */ +/* Added C code. */ +/* ========================================================================= */ -/* clone data on pull */ +/* None. */ -%newobject _ldns_rr_list_rr; - -%rename(__ldns_rr_list_rr) ldns_rr_list_rr; -%inline %{ -ldns_rr* _ldns_rr_list_rr(ldns_rr_list* r, int i) { - return ldns_rr_clone(ldns_rr_list_rr(r, i)); -} -%} - -%newobject ldns_rr_list2str; - -%rename(__ldns_rr_list_owner) ldns_rr_list_owner; -%inline %{ -ldns_rdf* _ldns_rr_list_owner(ldns_rr_list* r) { - return ldns_rdf_clone(ldns_rr_list_owner(r)); -} -%} +/* ========================================================================= */ +/* Encapsulating Python code. */ +/* ========================================================================= */ %feature("docstring") ldns_struct_rr_list "List of Resource Records. @@ -1183,7 +1879,8 @@ This class contains a list of RR's (see :class:`ldns.ldns_rr`). %extend ldns_struct_rr_list { - %pythoncode %{ + %pythoncode + %{ def __init__(self): self.this = _ldns.ldns_rr_list_new() if not self.this: @@ -1191,394 +1888,694 @@ This class contains a list of RR's (see :class:`ldns.ldns_rr`). __swig_destroy__ = _ldns._ldns_rr_list_deep_free - #LDNS_RR_LIST_CONSTRUCTORS_# + # + # LDNS_RR_LIST_CONSTRUCTORS_ + # + + @staticmethod + def new(raiseException=True): + """ + Creates an empty RR List object. + + :param raiseException: Set to True if an exception should + signal an error. + :type raiseException: bool + :throws Exception: when `raiseException` is True and error + occurs. + :return: :class:`ldns_rr_list` Empty RR list. + """ + rrl = _ldns.ldns_rr_list_new() + if (not rrl) and raiseException: + raise Exception("Can't create RR List.") + return rrl + @staticmethod def new_frm_file(filename="/etc/hosts", raiseException=True): - """Creates an RR List object from a file content + """ + Creates an RR List object from file content. - Goes through a file and returns a rr_list containing all the defined hosts in there. + Goes through a file and returns a rr list containing + all the defined hosts in there. - :param filename: the filename to use - :returns: RR List object or None. If the object can't be created and raiseException is True, an exception occurs. + :param filename: The filename to use. + :type filename: str + :param raiseException: Set to True if an exception should + signal an error. + :type raiseException: bool + :throws TypeError: when `filename` of inappropriate type. + :throws Exception: when `raiseException` is True and error + occurs. + :return: RR List object or None. If the object can't be + created and `raiseException` is True, an exception occurs. **Usage** - >>> alist = ldns.ldns_rr_list.new_frm_file() - >>> print alist - localhost. 3600 IN A 127.0.0.1 - ... + + >>> alist = ldns.ldns_rr_list.new_frm_file() + >>> print alist + localhost. 3600 IN A 127.0.0.1 + ... """ rr = _ldns.ldns_get_rr_list_hosts_frm_file(filename) - if (not rr) and (raiseException): raise Exception("Can't create RR List, error: %d" % status) + if (not rr) and (raiseException): + raise Exception("Can't create RR List.") return rr - #_LDNS_RR_LIST_CONSTRUCTORS# + + # + # _LDNS_RR_LIST_CONSTRUCTORS + # def __str__(self): - """converts a list of resource records to presentation format""" + """ + Converts a list of resource records to presentation format. + + :return: (str) Presentation format. + """ return _ldns.ldns_rr_list2str(self) - def print_to_file(self,output): - """print a rr_list to output param[in] output the fd to print to param[in] list the rr_list to print""" - _ldns.ldns_rr_list_print(output,self) + def print_to_file(self, output): + """ + Print a rr_list to output. + + :param output: Opened file to print to. + :throws TypeError: when `output` of inappropriate type. + """ + _ldns.ldns_rr_list_print(output, self) def to_canonical(self): - """converts each dname in each rr in a rr_list to its canonical form.""" + """ + Converts each dname in each rr in a rr_list to its canonical + form. + """ _ldns.ldns_rr_list2canonical(self) #parameters: ldns_rr_list *, #retvals: def rrs(self): - """returns the list of rr records.""" - for i in range(0,self.rr_count()): + """ + Returns a generator object of a list of rr records. + + :return: (generator) generator object. + """ + for i in range(0, self.rr_count()): yield self.rr(i) def is_rrset(self): - """checks if an rr_list is a rrset.""" + """ + Checks if the rr list is a rr set. + + :return: (bool) True if rr list is a rr set. + """ return _ldns.ldns_is_rrset(self) - def __cmp__(self,rrl2): - """compares two rr listss. - - :param rrl2: - the second one - :returns: (int) 0 if equal -1 if this list comes before rrl2 +1 if rrl2 comes before this list + def __cmp__(self, rrl2): """ - return _ldns.ldns_rr_list_compare(self,rrl2) + Compares two rr lists. + + :param rrl2: The second one. + :type rrl2: :class:`ldns_rr_list` + :throws TypeError: when `rrl2` of non-:class:`ldns_rr_list` + type. + :return: (int) 0 if equal, -1 if this list comes before + `rrl2`, 1 if `rrl2` comes before this list. + """ + return _ldns.ldns_rr_list_compare(self, rrl2) + + def __lt__(self, other): + """ + Compares two rr lists. + + :param other: The second one. + :type other: :class:`ldns_rr_list` + :throws TypeError: when `other` of non-:class:`ldns_rr_list` + type. + :return: (bool) True when `self` is less than 'other'. + """ + return _ldns.ldns_rr_list_compare(self, other) == -1 + + def __le__(self, other): + """ + Compares two rr lists. + + :param other: The second one. + :type other: :class:`ldns_rr_list` + :throws TypeError: when `other` of non-:class:`ldns_rr_list` + type. + :return: (bool) True when `self` is less than or equal to + 'other'. + """ + return _ldns.ldns_rr_list_compare(self, other) != 1 + + def __eq__(self, other): + """ + Compares two rr lists. + + :param other: The second one. + :type other: :class:`ldns_rr_list` + :throws TypeError: when `other` of non-:class:`ldns_rr_list` + type. + :return: (bool) True when `self` is equal to 'other'. + """ + return _ldns.ldns_rr_list_compare(self, other) == 0 + + def __ne__(self, other): + """ + Compares two rr lists. + + :param other: The second one. + :type other: :class:`ldns_rr_list` + :throws TypeError: when `other` of non-:class:`ldns_rr_list` + type. + :return: (bool) True when `self` is not equal to 'other'. + """ + return _ldns.ldns_rr_list_compare(self, other) != 0 + + def __gt__(self, other): + """ + Compares two rr lists. + + :param other: The second one. + :type other: :class:`ldns_rr_list` + :throws TypeError: when `other` of non-:class:`ldns_rr_list` + type. + :return: (bool) True when `self` is greater than 'other'. + """ + return _ldns.ldns_rr_list_compare(self, other) == 1 + + def __ge__(self, other): + """ + Compares two rr lists. + + :param other: The second one. + :type other: :class:`ldns_rr_list` + :throws TypeError: when `other` of non-:class:`ldns_rr_list` + type. + :return: (bool) True when `self` is greater than or equal to + 'other'. + """ + return _ldns.ldns_rr_list_compare(self, other) != -1 def write_to_buffer(self, buffer): - """Copies the rr_list data to the buffer in wire format. - - :param buffer: output buffer to append the result to - :returns: (ldns_status) ldns_status """ - return _ldns.ldns_rr_list2buffer_wire(buffer,self) + Copies the rr_list data to the buffer in wire format. + + :param buffer: Output buffer to append the result to. + :type buffer: :class:`ldns_buffer` + :throws TypeError: when `buffer` of non-:class:`ldns_buffer` + type. + :return: (ldns_status) ldns_status + """ + return _ldns.ldns_rr_list2buffer_wire(buffer, self) - #LDNS_RR_LIST_METHODS_# - def cat(self,right): - """concatenates two ldns_rr_lists together. - - This modifies rr list (to extend it and add the pointers from right). - - :param right: - the rightside - :returns: (bool) a left with right concatenated to it + # + # LDNS_RR_LIST_METHODS_ + # + + def cat(self, right): """ - return _ldns._ldns_rr_list_cat(self,right) - #parameters: ldns_rr_list *,ldns_rr_list *, + Concatenates two ldns_rr_lists together. + + This modifies rr list (to extend it and adds RRs from right). + + :param right: The right-hand side. + :type right: :class:`ldns_rr_list` + :throws TypeError: when `right` of non-:class:`ldns_rr_list` + type. + :return: (bool) True if success. + """ + return _ldns._ldns_rr_list_cat(self, right) + #parameters: ldns_rr_list *, ldns_rr_list *, #retvals: bool - def cat_clone(self,right): - """concatenates two ldns_rr_lists together, but makes clones of the rr's (instead of pointer copying). - - :param right: - the rightside - :returns: (ldns_rr_list \*) a new rr_list with leftside/rightside concatenated + def cat_clone(self, right): """ - return _ldns.ldns_rr_list_cat_clone(self,right) - #parameters: ldns_rr_list *,ldns_rr_list *, + Concatenates two ldns_rr_lists together, creates a new list + of the rr's (instead of appending the content to an existing + list). + + :param right: The right-hand side. + :type right: :class:`ldns_rr_list` + :throws TypeError: when `right` of non-:class:`ldns_rr_list` + type. + :return: (:class:`ldns_rr_list`) rr list with left-hand side + + right-hand side concatenated, on None on error. + """ + return _ldns.ldns_rr_list_cat_clone(self, right) + #parameters: ldns_rr_list *, ldns_rr_list *, #retvals: ldns_rr_list * def clone(self): - """clones an rrlist. + """ + Clones an rrlist. - :returns: (ldns_rr_list \*) the cloned rr list + :return: (:class:`ldns_rr_list`) the cloned rr list, + or None on error. """ return _ldns.ldns_rr_list_clone(self) #parameters: const ldns_rr_list *, #retvals: ldns_rr_list * - def contains_rr(self,rr): - """returns true if the given rr is one of the rrs in the list, or if it is equal to one - - :param rr: - the rr to check - :returns: (bool) true if rr_list contains rr, false otherwise + def contains_rr(self, rr): """ - return _ldns.ldns_rr_list_contains_rr(self,rr) - #parameters: const ldns_rr_list *,ldns_rr *, + Returns True if the given rr is one of the rrs in the list, + or if it is equal to one. + + :param rr: The rr to check. + :type rr: :class:`ldns_rr` + :throws TypeError: when `rr` of non-:class:`ldns_rr` type. + :return: (bool) True if rr_list contains `rr`, False otherwise. + """ + return _ldns.ldns_rr_list_contains_rr(self, rr) + #parameters: const ldns_rr_list *, ldns_rr *, #retvals: bool def owner(self): - """Returns the owner domain name rdf of the first element of the RR If there are no elements present, NULL is returned. - - :returns: (ldns_rdf \*) dname of the first element, or NULL if the list is empty """ - return _ldns._ldns_rr_list_owner(self) + Returns the owner domain name rdf of the first element of + the RR. If there are no elements present, None is returned. + + :return: (:class:`ldns_dname`) dname of the first element, + or None if the list is empty. + """ + rdf = _ldns._ldns_rr_list_owner(self) + if rdf: + rdf = ldns_dname(rdf, clone=False) + return rdf #parameters: const ldns_rr_list *, #retvals: ldns_rdf * def pop_rr(self): - """pops the last rr from an rrlist. + """ + Pops the last rr from an rrlist. - :returns: (ldns_rr \*) NULL if nothing to pop. Otherwise the popped RR + :return: (:class:`ldns_rr`) None if nothing to pop. + Otherwise the popped RR. """ rr = _ldns.ldns_rr_list_pop_rr(self) - #if hasattr(self, "_python_rr_refs") and rr in self._python_rr_refs: - # self._python_rr_refs.remove(rr) return rr #parameters: ldns_rr_list *, #retvals: ldns_rr * - def pop_rr_list(self,size): - """pops an rr_list of size s from an rrlist. - - :param size: - the number of rr's to pop - :returns: (ldns_rr_list \*) NULL if nothing to pop. Otherwise the popped rr_list + def pop_rr_list(self, size): """ - return _ldns.ldns_rr_list_pop_rr_list(self,size) - #parameters: ldns_rr_list *,size_t, + Pops an rr_list of size s from an rrlist. + + :param size: The number of rr's to pop. + :type size: positive int + :throws TypeError: when `size` of inappropriate type. + :return: (:class:`ldns_rr_list`) None if nothing to pop. + Otherwise the popped rr list. + """ + return _ldns.ldns_rr_list_pop_rr_list(self, size) + #parameters: ldns_rr_list *, size_t, #retvals: ldns_rr_list * def pop_rrset(self): - """pops the first rrset from the list, the list must be sorted, so that all rr's from each rrset are next to each other + """ + Pops the first rrset from the list, the list must be sorted, + so that all rr's from each rrset are next to each other. - :returns: (ldns_rr_list \*) + :return: (:class:`ldns_rr_list`) the first rrset, or None when + empty. """ return _ldns.ldns_rr_list_pop_rrset(self) #parameters: ldns_rr_list *, #retvals: ldns_rr_list * - def push_rr(self,rr): - """pushes an rr to an rrlist. - - :param rr: - the rr to push - :returns: (bool) false on error, otherwise true + def push_rr(self, rr): """ - #if hasattr(self, "_python_rr_refs"): - # self._python_rr_refs.add(rr) - #else: - # self._python_rr_refs = set([rr]) - return _ldns._ldns_rr_list_push_rr(self,rr) - #parameters: ldns_rr_list *,const ldns_rr *, + Pushes an rr to an rrlist. + + :param rr: The rr to push. + :type rr: :class:`ldns_rr` + :throws TypeError: when `rr` of non-:class:`ldns_rr` type. + :return: (bool) False on error, otherwise True. + """ + return _ldns._ldns_rr_list_push_rr(self, rr) + #parameters: ldns_rr_list *, const ldns_rr *, #retvals: bool - def push_rr_list(self,push_list): - """pushes an rr_list to an rrlist. - - :param push_list: - the rr_list to push - :returns: (bool) false on error, otherwise true + def push_rr_list(self, push_list): """ - return _ldns._ldns_rr_list_push_rr_list(self,push_list) - #parameters: ldns_rr_list *,const ldns_rr_list *, + Pushes an rr list to an rr list. + + :param push_list: The rr_list to push. + :type push_list: :class:`ldns_rr_list` + :throws TypeError: when `push_list` of non-:class:`ldns_rr_list` + type. + :returns: (bool) False on error, otherwise True. + """ + return _ldns._ldns_rr_list_push_rr_list(self, push_list) + #parameters: ldns_rr_list *, const ldns_rr_list *, #retvals: bool - def rr(self,nr): - """returns a specific rr of an rrlist. - - :param nr: - return this rr - :returns: (ldns_rr \*) the rr at position nr + def rr(self, nr): """ - return _ldns._ldns_rr_list_rr(self,nr) - #parameters: const ldns_rr_list *,size_t, + Returns a specific rr of an rrlist. + + :param nr: Index of the desired rr. + :type nr: positive int + :throws TypeError: when `nr` of inappropriate type. + :return: (:class:`ldns_rr`) The rr at position `nr`, or None + if failed. + """ + return _ldns._ldns_rr_list_rr(self, nr) + #parameters: const ldns_rr_list *, size_t, #retvals: ldns_rr * def rr_count(self): - """returns the number of rr's in an rr_list. + """ + Returns the number of rr's in an rr_list. - :returns: (size_t) the number of rr's + :return: (int) The number of rr's. """ return _ldns.ldns_rr_list_rr_count(self) #parameters: const ldns_rr_list *, #retvals: size_t - def set_rr(self,r,count): - """set a rr on a specific index in a ldns_rr_list - - :param r: - the rr to set - :param count: - index into the rr_list - :returns: (ldns_rr \*) the old rr which was stored in the rr_list, or NULL is the index was too large set a specific rr + def set_rr(self, r, idx): """ - return _ldns.ldns_rr_list_set_rr(self,r,count) - #parameters: ldns_rr_list *,const ldns_rr *,size_t, + Set a rr on a specific index in a ldns_rr_list. + + :param r: The rr to set. + :type r: :class:`ldns_rr` + :param idx: Index into the rr_list. + :type idx: positive int + :throws TypeError: when parameters of inappropriate types. + :return: (:class:`ldns_rr`) the old rr which was stored in + the rr_list, or None if the index was too large + to set a specific rr. + """ + return _ldns._ldns_rr_list_set_rr(self, r, idx) + #parameters: ldns_rr_list *, const ldns_rr *, size_t, #retvals: ldns_rr * - def set_rr_count(self,count): - """sets the number of rr's in an rr_list. - - :param count: - the number of rr in this list + def set_rr_count(self, count): """ - _ldns.ldns_rr_list_set_rr_count(self,count) - #parameters: ldns_rr_list *,size_t, + Sets the number of rr's in an rr_list. + + :param count: The number of rr in this list. + :type count: positive int + :throws TypeError: when `count` of non-integer type. + :throws Exception: when `count` out of acceptable range. + + .. warning:: + Don't use this method unless you really know what you + are doing. + """ + # The function C has a tendency to generate an assertion fail when + # the count exceeds the list's capacity -- therefore the checking + # code. + if isinstance(count, int) and \ + ((count < 0) or (count > self._rr_capacity)): + raise Exception("Given count %d is out of range " % (count) + + "of the rr list's capacity %d." % (self._rr_capacity)) + _ldns.ldns_rr_list_set_rr_count(self, count) + #parameters: ldns_rr_list *, size_t, #retvals: def sort(self): - """sorts an rr_list (canonical wire format). - - the sorting is done inband. + """ + Sorts an rr_list (canonical wire format). """ _ldns.ldns_rr_list_sort(self) #parameters: ldns_rr_list *, #retvals: - def subtype_by_rdf(self,r,pos): - """Return the rr_list which matches the rdf at position field. - - Think type-covered stuff for RRSIG - - :param r: - the rdf to use for the comparison - :param pos: - at which position can we find the rdf - :returns: (ldns_rr_list \*) a new rr list with only the RRs that match + def subtype_by_rdf(self, r, pos): """ - return _ldns.ldns_rr_list_subtype_by_rdf(self,r,pos) - #parameters: ldns_rr_list *,ldns_rdf *,size_t, + Return the rr_list which matches the rdf at position field. + + Think type-covered stuff for RRSIG. + + :param r: The rdf to use for the comparison. + :type r: :class:`ldns_rdf` + :param pos: At which position we can find the rdf. + :type pos: positive int + :throws TypeError: when parameters of inappropriate types. + :return: (:class:`ldns_rr_list`) a new rr list with only + the RRs that match, or None when nothing matches. + """ + return _ldns.ldns_rr_list_subtype_by_rdf(self, r, pos) + #parameters: ldns_rr_list *, ldns_rdf *, size_t, #retvals: ldns_rr_list * def type(self): - """Returns the type of the first element of the RR If there are no elements present, 0 is returned (LDNS_RR_TYPE_A). + """ + Returns the type of the first element of the RR. + + If there are no elements present, 0 is returned. - :returns: (ldns_rr_type) rr_type of the first element, or 0 if the list is empty + :return: (int) rr_type of the first element, + or 0 if the list is empty. """ return _ldns.ldns_rr_list_type(self) #parameters: const ldns_rr_list *, #retvals: ldns_rr_type - #_LDNS_RR_LIST_METHODS# - %} + + # + # _LDNS_RR_LIST_METHODS + # + %} } + +/* ========================================================================= */ +/* SWIG setting and definitions. */ +/* ========================================================================= */ + + %newobject ldns_rr_descript; -%nodefaultctor ldns_struct_rr_descriptor; //no default constructor & destructor -%nodefaultdtor ldns_struct_rr_descriptor; +%nodefaultctor ldns_struct_rr_descriptor; /* No default constructor. */ +%nodefaultdtor ldns_struct_rr_descriptor; /* No default destructor.*/ %rename(ldns_rr_descriptor) ldns_struct_rr_descriptor; +/* ========================================================================= */ +/* Debugging related code. */ +/* ========================================================================= */ + +/* None. */ -%feature("docstring") ldns_struct_rr_descriptor "Resource Record descriptor -This structure contains, for all rr types, the rdata fields that are defined." +/* ========================================================================= */ +/* Added C code. */ +/* ========================================================================= */ + + +%inline +%{ + /* + * Does nothing, but keeps the SWIG wrapper quiet about absent destructor. + */ + void ldns_rr_descriptor_dummy_free(const ldns_rr_descriptor *rd) + { + (void) rd; + } +%} + + +/* ========================================================================= */ +/* Encapsulating Python code. */ +/* ========================================================================= */ + + +%feature("docstring") ldns_struct_rr_descriptor "Resource Record descriptor. + +This structure contains, for all rr types, the rdata fields that are defined. + +In order to create a class instance use :meth:`ldns_rr_descriptor`. +" %extend ldns_struct_rr_descriptor { - %pythoncode %{ - def __init__(self): - raise Exception("This class can't be created directly. Please use: ldns_rr_descript") - #LDNS_RR_DESCRIPTOR_METHODS_# - def field_type(self,field): - """returns the rdf type for the given rdata field number of the rr type for the given descriptor. - - :param field: - the field number - :returns: (ldns_rdf_type) the rdf type for the field + %pythoncode + %{ + def __init__(self, rr_type): """ - return _ldns.ldns_rr_descriptor_field_type(self,field) - #parameters: const ldns_rr_descriptor *,size_t, + Returns the resource record descriptor for the given type. + + :param rr_type: RR type. + :type rr_type: int + :throws TypeError: when `rr_type` of inappropriate type. + :return: (:class:`ldns_rr_descriptor`) RR descriptor class. + """ + self.this = self.ldns_rr_descriptor(rr_type) + + def __str__(self): + raise Exception("The content of this class cannot be printed.") + + __swig_destroy__ = _ldns.ldns_rr_descriptor_dummy_free + + # + # LDNS_RR_DESCRIPTOR_CONSTRUCTORS_ + # + + @staticmethod + def ldns_rr_descriptor(rr_type): + """ + Returns the resource record descriptor for the given type. + + :param rr_type: RR type. + :type rr_type: int + :throws TypeError: when `rr_type` of inappropriate type. + :return: (:class:`ldns_rr_descriptor`) RR descriptor class. + """ + return _ldns.ldns_rr_descript(rr_type) + #parameters: uint16_t + #retvals: const ldns_rr_descriptor * + + # + # _LDNS_RR_DESCRIPTOR_CONSTRUCTORS + # + + # + # LDNS_RR_DESCRIPTOR_METHODS_ + # + + def field_type(self, field): + """ + Returns the rdf type for the given rdata field number of the + rr type for the given descriptor. + + :param field: The field number. + :type field: positive int + :throws TypeError: when `field` of non-inetger type. + :return: (int) the rdf type for the field. + """ + return _ldns.ldns_rr_descriptor_field_type(self, field) + #parameters: const ldns_rr_descriptor *, size_t, #retvals: ldns_rdf_type def maximum(self): - """returns the maximum number of rdata fields of the rr type this descriptor describes. + """ + Returns the maximum number of rdata fields of the rr type this + descriptor describes. - :returns: (size_t) the maximum number of rdata fields + :return: (int) the maximum number of rdata fields. """ return _ldns.ldns_rr_descriptor_maximum(self) #parameters: const ldns_rr_descriptor *, #retvals: size_t def minimum(self): - """returns the minimum number of rdata fields of the rr type this descriptor describes. + """ + Returns the minimum number of rdata fields of the rr type this + descriptor describes. - :returns: (size_t) the minimum number of rdata fields + :return: (int) the minimum number of rdata fields. """ return _ldns.ldns_rr_descriptor_minimum(self) #parameters: const ldns_rr_descriptor *, #retvals: size_t - #_LDNS_RR_DESCRIPTOR_METHODS# - %} + # + # _LDNS_RR_DESCRIPTOR_METHODS + # + %} } + +/* ========================================================================= */ +/* Added C code. */ +/* ========================================================================= */ + + /* - -rrsig checking wrappers - - copying of rr pointers into the good_keys list leads to double free - problems, therefore we provide two options - either ignore the keys - or get list of indexes of the keys. The latter allows fetching of the - keys later on from the original key set -*/ + * rrsig checking wrappers + * + * Copying of rr pointers into the good_keys list leads to double free + * problems, therefore we provide two options - either ignore the keys + * or get list of indexes of the keys. The latter allows fetching of the + * keys later on from the original key set. + */ %rename(__ldns_verify_rrsig_keylist) ldns_verify_rrsig_keylist; -%inline %{ -ldns_status ldns_verify_rrsig_keylist_status_only(ldns_rr_list *rrset, - ldns_rr *rrsig, - const ldns_rr_list *keys) { +%inline +%{ + ldns_status ldns_verify_rrsig_keylist_status_only(ldns_rr_list *rrset, + ldns_rr *rrsig, const ldns_rr_list *keys) + { ldns_rr_list *good_keys = ldns_rr_list_new(); - ldns_status status = ldns_verify_rrsig_keylist(rrset, rrsig, keys, good_keys); + ldns_status status = ldns_verify_rrsig_keylist(rrset, rrsig, keys, + good_keys); ldns_rr_list_free(good_keys); return status; -} + } %} %rename(__ldns_verify_rrsig_keylist) ldns_verify_rrsig_keylist; -%inline %{ -PyObject* ldns_verify_rrsig_keylist_(ldns_rr_list *rrset, - ldns_rr *rrsig, - const ldns_rr_list *keys) { - PyObject* tuple; - PyObject* keylist; - ldns_rr_list *good_keys = ldns_rr_list_new(); - ldns_status status = ldns_verify_rrsig_keylist(rrset, rrsig, keys, good_keys); +%inline +%{ + PyObject* ldns_verify_rrsig_keylist_(ldns_rr_list *rrset, + ldns_rr *rrsig, const ldns_rr_list *keys) + { + PyObject* tuple; + PyObject* keylist; + ldns_rr_list *good_keys = ldns_rr_list_new(); + ldns_status status = ldns_verify_rrsig_keylist(rrset, rrsig, keys, + good_keys); - tuple = PyTuple_New(2); - PyTuple_SetItem(tuple, 0, SWIG_From_int(status)); - keylist = PyList_New(0); - if (status == LDNS_STATUS_OK) { - unsigned int i; - for (i = 0; i < ldns_rr_list_rr_count(keys); i++) - if (ldns_rr_list_contains_rr(good_keys, ldns_rr_list_rr(keys, i))) - PyList_Append(keylist, SWIG_From_int(i)); - } - PyTuple_SetItem(tuple, 1, keylist); - ldns_rr_list_free(good_keys); - return tuple; - } + tuple = PyTuple_New(2); + PyTuple_SetItem(tuple, 0, SWIG_From_int(status)); + keylist = PyList_New(0); + if (status == LDNS_STATUS_OK) { + unsigned int i; + for (i = 0; i < ldns_rr_list_rr_count(keys); i++) { + if (ldns_rr_list_contains_rr(good_keys, ldns_rr_list_rr(keys, i))) { + PyList_Append(keylist, SWIG_From_int(i)); + } + } + } + PyTuple_SetItem(tuple, 1, keylist); + ldns_rr_list_free(good_keys); + return tuple; + } %} %rename(__ldns_verify_rrsig_keylist_notime) ldns_verify_rrsig_keylist_notime; -%inline %{ -ldns_status ldns_verify_rrsig_keylist_notime_status_only(ldns_rr_list *rrset, - ldns_rr *rrsig, - const ldns_rr_list *keys) { +%inline +%{ + ldns_status ldns_verify_rrsig_keylist_notime_status_only(ldns_rr_list *rrset, + ldns_rr *rrsig, const ldns_rr_list *keys) + { ldns_rr_list *good_keys = ldns_rr_list_new(); - ldns_status status = ldns_verify_rrsig_keylist_notime(rrset, rrsig, keys, good_keys); + ldns_status status = ldns_verify_rrsig_keylist_notime(rrset, rrsig, keys, + good_keys); ldns_rr_list_free(good_keys); return status; -} + } %} %rename(__ldns_verify_rrsig_keylist_notime) ldns_verify_rrsig_keylist_notime; -%inline %{ -PyObject* ldns_verify_rrsig_keylist_notime_(ldns_rr_list *rrset, - ldns_rr *rrsig, - const ldns_rr_list *keys) { - PyObject* tuple; - PyObject* keylist; - ldns_rr_list *good_keys = ldns_rr_list_new(); - ldns_status status = ldns_verify_rrsig_keylist_notime(rrset, rrsig, keys, good_keys); +%inline +%{ + PyObject* ldns_verify_rrsig_keylist_notime_(ldns_rr_list *rrset, + ldns_rr *rrsig, const ldns_rr_list *keys) + { + PyObject* tuple; + PyObject* keylist; + ldns_rr_list *good_keys = ldns_rr_list_new(); + ldns_status status = ldns_verify_rrsig_keylist_notime(rrset, rrsig, keys, + good_keys); - tuple = PyTuple_New(2); - PyTuple_SetItem(tuple, 0, SWIG_From_int(status)); - keylist = PyList_New(0); - if (status == LDNS_STATUS_OK) { - unsigned int i; - for (i = 0; i < ldns_rr_list_rr_count(keys); i++) - if (ldns_rr_list_contains_rr(good_keys, ldns_rr_list_rr(keys, i))) - PyList_Append(keylist, SWIG_From_int(i)); - } - PyTuple_SetItem(tuple, 1, keylist); - ldns_rr_list_free(good_keys); - return tuple; - } + tuple = PyTuple_New(2); + PyTuple_SetItem(tuple, 0, SWIG_From_int(status)); + keylist = PyList_New(0); + if (status == LDNS_STATUS_OK) { + unsigned int i; + for (i = 0; i < ldns_rr_list_rr_count(keys); i++) { + if (ldns_rr_list_contains_rr(good_keys, ldns_rr_list_rr(keys, i))) { + PyList_Append(keylist, SWIG_From_int(i)); + } + } + } + PyTuple_SetItem(tuple, 1, keylist); + ldns_rr_list_free(good_keys); + return tuple; + } %} -/* -- end of rrsig checking wrappers */ - +/* End of rrsig checking wrappers. */ diff --git a/dane.c b/dane.c new file mode 100644 index 00000000000..793005ddcb3 --- /dev/null +++ b/dane.c @@ -0,0 +1,742 @@ +/* + * Verify or create TLS authentication with DANE (RFC6698) + * + * (c) NLnetLabs 2012 + * + * See the file LICENSE for the license. + * + */ + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#ifdef HAVE_SSL +#include +#include +#include +#endif + +ldns_status +ldns_dane_create_tlsa_owner(ldns_rdf** tlsa_owner, const ldns_rdf* name, + uint16_t port, ldns_dane_transport transport) +{ + char buf[LDNS_MAX_DOMAINLEN]; + size_t s; + + assert(tlsa_owner != NULL); + assert(name != NULL); + assert(ldns_rdf_get_type(name) == LDNS_RDF_TYPE_DNAME); + + s = (size_t)snprintf(buf, LDNS_MAX_DOMAINLEN, "X_%d", (int)port); + buf[0] = (char)(s - 1); + + switch(transport) { + case LDNS_DANE_TRANSPORT_TCP: + s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\004_tcp"); + break; + + case LDNS_DANE_TRANSPORT_UDP: + s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\004_udp"); + break; + + case LDNS_DANE_TRANSPORT_SCTP: + s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\005_sctp"); + break; + + default: + return LDNS_STATUS_DANE_UNKNOWN_TRANSPORT; + } + if (s + ldns_rdf_size(name) > LDNS_MAX_DOMAINLEN) { + return LDNS_STATUS_DOMAINNAME_OVERFLOW; + } + memcpy(buf + s, ldns_rdf_data(name), ldns_rdf_size(name)); + *tlsa_owner = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, + s + ldns_rdf_size(name), buf); + if (*tlsa_owner == NULL) { + return LDNS_STATUS_MEM_ERR; + } + return LDNS_STATUS_OK; +} + + +#ifdef HAVE_SSL +ldns_status +ldns_dane_cert2rdf(ldns_rdf** rdf, X509* cert, + ldns_tlsa_selector selector, + ldns_tlsa_matching_type matching_type) +{ + unsigned char* buf = NULL; + size_t len; + + X509_PUBKEY* xpubkey; + EVP_PKEY* epubkey; + + unsigned char* digest; + + assert(rdf != NULL); + assert(cert != NULL); + + switch(selector) { + case LDNS_TLSA_SELECTOR_FULL_CERTIFICATE: + + len = (size_t)i2d_X509(cert, &buf); + break; + + case LDNS_TLSA_SELECTOR_SUBJECTPUBLICKEYINFO: + +#ifndef S_SPLINT_S + xpubkey = X509_get_X509_PUBKEY(cert); +#endif + if (! xpubkey) { + return LDNS_STATUS_SSL_ERR; + } + epubkey = X509_PUBKEY_get(xpubkey); + if (! epubkey) { + return LDNS_STATUS_SSL_ERR; + } + len = (size_t)i2d_PUBKEY(epubkey, &buf); + break; + + default: + return LDNS_STATUS_DANE_UNKNOWN_SELECTOR; + } + + switch(matching_type) { + case LDNS_TLSA_MATCHING_TYPE_NO_HASH_USED: + + *rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, len, buf); + + return *rdf ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR; + break; + + case LDNS_TLSA_MATCHING_TYPE_SHA256: + + digest = LDNS_XMALLOC(unsigned char, SHA256_DIGEST_LENGTH); + if (digest == NULL) { + LDNS_FREE(buf); + return LDNS_STATUS_MEM_ERR; + } + (void) ldns_sha256(buf, (unsigned int)len, digest); + *rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, SHA256_DIGEST_LENGTH, + digest); + LDNS_FREE(buf); + + return *rdf ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR; + break; + + case LDNS_TLSA_MATCHING_TYPE_SHA512: + + digest = LDNS_XMALLOC(unsigned char, SHA512_DIGEST_LENGTH); + if (digest == NULL) { + LDNS_FREE(buf); + return LDNS_STATUS_MEM_ERR; + } + (void) ldns_sha512(buf, (unsigned int)len, digest); + *rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, SHA512_DIGEST_LENGTH, + digest); + LDNS_FREE(buf); + + return *rdf ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR; + break; + + default: + LDNS_FREE(buf); + return LDNS_STATUS_DANE_UNKNOWN_MATCHING_TYPE; + } +} + + +/* Ordinary PKIX validation of cert (with extra_certs to help) + * against the CA's in store + */ +static ldns_status +ldns_dane_pkix_validate(X509* cert, STACK_OF(X509)* extra_certs, + X509_STORE* store) +{ + X509_STORE_CTX* vrfy_ctx; + ldns_status s; + + if (! store) { + return LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE; + } + vrfy_ctx = X509_STORE_CTX_new(); + if (! vrfy_ctx) { + + return LDNS_STATUS_SSL_ERR; + + } else if (X509_STORE_CTX_init(vrfy_ctx, store, + cert, extra_certs) != 1) { + s = LDNS_STATUS_SSL_ERR; + + } else if (X509_verify_cert(vrfy_ctx) == 1) { + + s = LDNS_STATUS_OK; + + } else { + s = LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE; + } + X509_STORE_CTX_free(vrfy_ctx); + return s; +} + + +/* Orinary PKIX validation of cert (with extra_certs to help) + * against the CA's in store, but also return the validation chain. + */ +static ldns_status +ldns_dane_pkix_validate_and_get_chain(STACK_OF(X509)** chain, X509* cert, + STACK_OF(X509)* extra_certs, X509_STORE* store) +{ + ldns_status s; + X509_STORE* empty_store = NULL; + X509_STORE_CTX* vrfy_ctx; + + assert(chain != NULL); + + if (! store) { + store = empty_store = X509_STORE_new(); + } + s = LDNS_STATUS_SSL_ERR; + vrfy_ctx = X509_STORE_CTX_new(); + if (! vrfy_ctx) { + + goto exit_free_empty_store; + + } else if (X509_STORE_CTX_init(vrfy_ctx, store, + cert, extra_certs) != 1) { + goto exit_free_vrfy_ctx; + + } else if (X509_verify_cert(vrfy_ctx) == 1) { + + s = LDNS_STATUS_OK; + + } else { + s = LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE; + } + *chain = X509_STORE_CTX_get1_chain(vrfy_ctx); + if (! *chain) { + s = LDNS_STATUS_SSL_ERR; + } + +exit_free_vrfy_ctx: + X509_STORE_CTX_free(vrfy_ctx); + +exit_free_empty_store: + if (empty_store) { + X509_STORE_free(empty_store); + } + return s; +} + + +/* Return the validation chain that can be build out of cert, with extra_certs. + */ +static ldns_status +ldns_dane_pkix_get_chain(STACK_OF(X509)** chain, + X509* cert, STACK_OF(X509)* extra_certs) +{ + ldns_status s; + X509_STORE* empty_store = NULL; + X509_STORE_CTX* vrfy_ctx; + + assert(chain != NULL); + + empty_store = X509_STORE_new(); + s = LDNS_STATUS_SSL_ERR; + vrfy_ctx = X509_STORE_CTX_new(); + if (! vrfy_ctx) { + + goto exit_free_empty_store; + + } else if (X509_STORE_CTX_init(vrfy_ctx, empty_store, + cert, extra_certs) != 1) { + goto exit_free_vrfy_ctx; + } + (void) X509_verify_cert(vrfy_ctx); + *chain = X509_STORE_CTX_get1_chain(vrfy_ctx); + if (! *chain) { + s = LDNS_STATUS_SSL_ERR; + } else { + s = LDNS_STATUS_OK; + } +exit_free_vrfy_ctx: + X509_STORE_CTX_free(vrfy_ctx); + +exit_free_empty_store: + X509_STORE_free(empty_store); + return s; +} + + +/* Pop n+1 certs and return the last popped. + */ +static ldns_status +ldns_dane_get_nth_cert_from_validation_chain( + X509** cert, STACK_OF(X509)* chain, int n, bool ca) +{ + if (n >= sk_X509_num(chain) || n < 0) { + return LDNS_STATUS_DANE_OFFSET_OUT_OF_RANGE; + } + *cert = sk_X509_pop(chain); + while (n-- > 0) { + X509_free(*cert); + *cert = sk_X509_pop(chain); + } + if (ca && ! X509_check_ca(*cert)) { + return LDNS_STATUS_DANE_NON_CA_CERTIFICATE; + } + return LDNS_STATUS_OK; +} + + +/* Create validation chain with cert and extra_certs and returns the last + * self-signed (if present). + */ +static ldns_status +ldns_dane_pkix_get_last_self_signed(X509** out_cert, + X509* cert, STACK_OF(X509)* extra_certs) +{ + ldns_status s; + X509_STORE* empty_store = NULL; + X509_STORE_CTX* vrfy_ctx; + + assert(out_cert != NULL); + + empty_store = X509_STORE_new(); + s = LDNS_STATUS_SSL_ERR; + vrfy_ctx = X509_STORE_CTX_new(); + if (! vrfy_ctx) { + goto exit_free_empty_store; + + } else if (X509_STORE_CTX_init(vrfy_ctx, empty_store, + cert, extra_certs) != 1) { + goto exit_free_vrfy_ctx; + + } + (void) X509_verify_cert(vrfy_ctx); + if (vrfy_ctx->error == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN || + vrfy_ctx->error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT){ + + *out_cert = X509_STORE_CTX_get_current_cert( vrfy_ctx); + s = LDNS_STATUS_OK; + } else { + s = LDNS_STATUS_DANE_PKIX_NO_SELF_SIGNED_TRUST_ANCHOR; + } +exit_free_vrfy_ctx: + X509_STORE_CTX_free(vrfy_ctx); + +exit_free_empty_store: + X509_STORE_free(empty_store); + return s; +} + + +ldns_status +ldns_dane_select_certificate(X509** selected_cert, + X509* cert, STACK_OF(X509)* extra_certs, + X509_STORE* pkix_validation_store, + ldns_tlsa_certificate_usage cert_usage, int offset) +{ + ldns_status s; + STACK_OF(X509)* pkix_validation_chain = NULL; + + assert(selected_cert != NULL); + assert(cert != NULL); + + /* With PKIX validation explicitely turned off (pkix_validation_store + * == NULL), treat the "CA constraint" and "Service certificate + * constraint" the same as "Trust anchor assertion" and "Domain issued + * certificate" respectively. + */ + if (pkix_validation_store == NULL) { + switch (cert_usage) { + + case LDNS_TLSA_USAGE_CA_CONSTRAINT: + + cert_usage = LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION; + break; + + case LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT: + + cert_usage = LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE; + break; + + default: + break; + } + } + + /* Now what to do with each Certificate usage... + */ + switch (cert_usage) { + + case LDNS_TLSA_USAGE_CA_CONSTRAINT: + + s = ldns_dane_pkix_validate_and_get_chain( + &pkix_validation_chain, + cert, extra_certs, + pkix_validation_store); + if (! pkix_validation_chain) { + return s; + } + if (s == LDNS_STATUS_OK) { + if (offset == -1) { + offset = 0; + } + s = ldns_dane_get_nth_cert_from_validation_chain( + selected_cert, pkix_validation_chain, + offset, true); + } + sk_X509_pop_free(pkix_validation_chain, X509_free); + return s; + break; + + + case LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT: + + *selected_cert = cert; + return ldns_dane_pkix_validate(cert, extra_certs, + pkix_validation_store); + break; + + + case LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION: + + if (offset == -1) { + s = ldns_dane_pkix_get_last_self_signed( + selected_cert, cert, extra_certs); + return s; + } else { + s = ldns_dane_pkix_get_chain( + &pkix_validation_chain, + cert, extra_certs); + if (s == LDNS_STATUS_OK) { + s = + ldns_dane_get_nth_cert_from_validation_chain( + selected_cert, pkix_validation_chain, + offset, false); + } else if (! pkix_validation_chain) { + return s; + } + sk_X509_pop_free(pkix_validation_chain, X509_free); + return s; + } + break; + + + case LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE: + + *selected_cert = cert; + return LDNS_STATUS_OK; + break; + + default: + return LDNS_STATUS_DANE_UNKNOWN_CERTIFICATE_USAGE; + break; + } +} + + +ldns_status +ldns_dane_create_tlsa_rr(ldns_rr** tlsa, + ldns_tlsa_certificate_usage certificate_usage, + ldns_tlsa_selector selector, + ldns_tlsa_matching_type matching_type, + X509* cert) +{ + ldns_rdf* rdf; + ldns_status s; + + assert(tlsa != NULL); + assert(cert != NULL); + + /* create rr */ + *tlsa = ldns_rr_new_frm_type(LDNS_RR_TYPE_TLSA); + if (*tlsa == NULL) { + return LDNS_STATUS_MEM_ERR; + } + + rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, + (uint8_t)certificate_usage); + if (rdf == NULL) { + goto memerror; + } + (void) ldns_rr_set_rdf(*tlsa, rdf, 0); + + rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, (uint8_t)selector); + if (rdf == NULL) { + goto memerror; + } + (void) ldns_rr_set_rdf(*tlsa, rdf, 1); + + rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, (uint8_t)matching_type); + if (rdf == NULL) { + goto memerror; + } + (void) ldns_rr_set_rdf(*tlsa, rdf, 2); + + s = ldns_dane_cert2rdf(&rdf, cert, selector, matching_type); + if (s == LDNS_STATUS_OK) { + (void) ldns_rr_set_rdf(*tlsa, rdf, 3); + return LDNS_STATUS_OK; + } + ldns_rr_free(*tlsa); + *tlsa = NULL; + return s; + +memerror: + ldns_rr_free(*tlsa); + *tlsa = NULL; + return LDNS_STATUS_MEM_ERR; +} + + +/* Return tlsas that actually are TLSA resource records with known values + * for the Certificate usage, Selector and Matching type rdata fields. + */ +static ldns_rr_list* +ldns_dane_filter_unusable_records(const ldns_rr_list* tlsas) +{ + size_t i; + ldns_rr_list* r = ldns_rr_list_new(); + ldns_rr* tlsa_rr; + + if (! r) { + return NULL; + } + for (i = 0; i < ldns_rr_list_rr_count(tlsas); i++) { + tlsa_rr = ldns_rr_list_rr(tlsas, i); + if (ldns_rr_get_type(tlsa_rr) == LDNS_RR_TYPE_TLSA && + ldns_rr_rd_count(tlsa_rr) == 4 && + ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 0)) <= 3 && + ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 1)) <= 1 && + ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 2)) <= 2) { + + if (! ldns_rr_list_push_rr(r, tlsa_rr)) { + ldns_rr_list_free(r); + return NULL; + } + } + } + return r; +} + + +/* Return whether cert/selector/matching_type matches data. + */ +static ldns_status +ldns_dane_match_cert_with_data(X509* cert, ldns_tlsa_selector selector, + ldns_tlsa_matching_type matching_type, ldns_rdf* data) +{ + ldns_status s; + ldns_rdf* match_data; + + s = ldns_dane_cert2rdf(&match_data, cert, selector, matching_type); + if (s == LDNS_STATUS_OK) { + if (ldns_rdf_compare(data, match_data) != 0) { + s = LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH; + } + ldns_rdf_free(match_data); + } + return s; +} + + +/* Return whether any certificate from the chain with selector/matching_type + * matches data. + * ca should be true if the certificate has to be a CA certificate too. + */ +static ldns_status +ldns_dane_match_any_cert_with_data(STACK_OF(X509)* chain, + ldns_tlsa_selector selector, + ldns_tlsa_matching_type matching_type, + ldns_rdf* data, bool ca) +{ + ldns_status s = LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH; + size_t n, i; + X509* cert; + + n = (size_t)sk_X509_num(chain); + for (i = 0; i < n; i++) { + cert = sk_X509_pop(chain); + if (! cert) { + s = LDNS_STATUS_SSL_ERR; + break; + } + s = ldns_dane_match_cert_with_data(cert, + selector, matching_type, data); + if (ca && s == LDNS_STATUS_OK && ! X509_check_ca(cert)) { + s = LDNS_STATUS_DANE_NON_CA_CERTIFICATE; + } + X509_free(cert); + if (s != LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH) { + break; + } + /* when s == LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH, + * try to match the next certificate + */ + } + return s; +} + + +ldns_status +ldns_dane_verify_rr(const ldns_rr* tlsa_rr, + X509* cert, STACK_OF(X509)* extra_certs, + X509_STORE* pkix_validation_store) +{ + ldns_status s; + + STACK_OF(X509)* pkix_validation_chain = NULL; + + ldns_tlsa_certificate_usage cert_usage; + ldns_tlsa_selector selector; + ldns_tlsa_matching_type matching_type; + ldns_rdf* data; + + if (! tlsa_rr) { + /* No TLSA, so regular PKIX validation + */ + return ldns_dane_pkix_validate(cert, extra_certs, + pkix_validation_store); + } + cert_usage = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 0)); + selector = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 1)); + matching_type = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 2)); + data = ldns_rr_rdf(tlsa_rr, 3) ; + + switch (cert_usage) { + case LDNS_TLSA_USAGE_CA_CONSTRAINT: + s = ldns_dane_pkix_validate_and_get_chain( + &pkix_validation_chain, + cert, extra_certs, + pkix_validation_store); + if (! pkix_validation_chain) { + return s; + } + if (s == LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE) { + /* + * NO PKIX validation. We still try to match *any* + * certificate from the chain, so we return + * TLSA errors over PKIX errors. + * + * i.e. When the TLSA matches no certificate, we return + * TLSA_DID_NOT_MATCH and not PKIX_DID_NOT_VALIDATE + */ + s = ldns_dane_match_any_cert_with_data( + pkix_validation_chain, + selector, matching_type, data, true); + + if (s == LDNS_STATUS_OK) { + /* A TLSA record did match a cert from the + * chain, thus the error is failed PKIX + * validation. + */ + s = LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE; + } + + } else if (s == LDNS_STATUS_OK) { + /* PKIX validated, does the TLSA match too? */ + + s = ldns_dane_match_any_cert_with_data( + pkix_validation_chain, + selector, matching_type, data, true); + } + sk_X509_pop_free(pkix_validation_chain, X509_free); + return s; + break; + + case LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT: + s = ldns_dane_match_cert_with_data(cert, + selector, matching_type, data); + + if (s == LDNS_STATUS_OK) { + return ldns_dane_pkix_validate(cert, extra_certs, + pkix_validation_store); + } + return s; + break; + + case LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION: + s = ldns_dane_pkix_get_chain(&pkix_validation_chain, + cert, extra_certs); + + if (s == LDNS_STATUS_OK) { + s = ldns_dane_match_any_cert_with_data( + pkix_validation_chain, + selector, matching_type, data, false); + + } else if (! pkix_validation_chain) { + return s; + } + sk_X509_pop_free(pkix_validation_chain, X509_free); + return s; + break; + + case LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE: + return ldns_dane_match_cert_with_data(cert, + selector, matching_type, data); + break; + + default: + break; + } + return LDNS_STATUS_DANE_UNKNOWN_CERTIFICATE_USAGE; +} + + +ldns_status +ldns_dane_verify(ldns_rr_list* tlsas, + X509* cert, STACK_OF(X509)* extra_certs, + X509_STORE* pkix_validation_store) +{ + size_t i; + ldns_rr* tlsa_rr; + ldns_status s = LDNS_STATUS_OK, ps; + + assert(cert != NULL); + + if (tlsas && ldns_rr_list_rr_count(tlsas) > 0) { + tlsas = ldns_dane_filter_unusable_records(tlsas); + if (! tlsas) { + return LDNS_STATUS_MEM_ERR; + } + } + if (! tlsas || ldns_rr_list_rr_count(tlsas) == 0) { + /* No TLSA's, so regular PKIX validation + */ + return ldns_dane_pkix_validate(cert, extra_certs, + pkix_validation_store); + } else { + for (i = 0; i < ldns_rr_list_rr_count(tlsas); i++) { + tlsa_rr = ldns_rr_list_rr(tlsas, i); + ps = s; + s = ldns_dane_verify_rr(tlsa_rr, cert, extra_certs, + pkix_validation_store); + + if (s != LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH && + s != LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE) { + + /* which would be LDNS_STATUS_OK (match) + * or some fatal error preventing use from + * trying the next TLSA record. + */ + break; + } + s = (s > ps ? s : ps); /* prefer PKIX_DID_NOT_VALIDATE + * over TLSA_DID_NOT_MATCH + */ + } + ldns_rr_list_free(tlsas); + } + return s; +} +#endif /* HAVE_SSL */ diff --git a/dname.c b/dname.c index f3770feafb5..55aba5d65a1 100644 --- a/dname.c +++ b/dname.c @@ -30,6 +30,24 @@ #include #endif +/* Returns whether the last label in the name is a root label (a empty label). + * Note that it is not enough to just test the last character to be 0, + * because it may be part of the last label itself. + */ +static bool +ldns_dname_last_label_is_root_label(const ldns_rdf* dname) +{ + size_t src_pos; + size_t len = 0; + + for (src_pos = 0; src_pos < ldns_rdf_size(dname); src_pos += len + 1) { + len = ldns_rdf_data(dname)[src_pos]; + } + assert(src_pos == ldns_rdf_size(dname)); + + return src_pos > 0 && len == 0; +} + ldns_rdf * ldns_dname_cat_clone(const ldns_rdf *rd1, const ldns_rdf *rd2) { @@ -47,7 +65,7 @@ ldns_dname_cat_clone(const ldns_rdf *rd1, const ldns_rdf *rd2) * rd, by reducing the size with 1 */ left_size = ldns_rdf_size(rd1); - if (left_size > 0 &&ldns_rdf_data(rd1)[left_size - 1] == 0) { + if (ldns_dname_last_label_is_root_label(rd1)) { left_size--; } @@ -84,7 +102,7 @@ ldns_dname_cat(ldns_rdf *rd1, ldns_rdf *rd2) * rd, by reducing the size with 1 */ left_size = ldns_rdf_size(rd1); - if (left_size > 0 &&ldns_rdf_data(rd1)[left_size - 1] == 0) { + if (ldns_dname_last_label_is_root_label(rd1)) { left_size--; } @@ -102,36 +120,39 @@ ldns_dname_cat(ldns_rdf *rd1, ldns_rdf *rd2) return LDNS_STATUS_OK; } -ldns_rdf * -ldns_dname_reverse(const ldns_rdf *d) +ldns_rdf* +ldns_dname_reverse(const ldns_rdf *dname) { - ldns_rdf *new; - ldns_rdf *tmp; - ldns_rdf *d_tmp; - ldns_status status; + size_t rd_size; + uint8_t* buf; + ldns_rdf* new; + size_t src_pos; + size_t len ; - d_tmp = ldns_rdf_clone(d); - - new = ldns_dname_new_frm_str("."); - if(!new) - return NULL; - - while(ldns_dname_label_count(d_tmp) > 0) { - tmp = ldns_dname_label(d_tmp, 0); - status = ldns_dname_cat(tmp, new); - if(status != LDNS_STATUS_OK) { - ldns_rdf_deep_free(new); - ldns_rdf_deep_free(d_tmp); - return NULL; - } - ldns_rdf_deep_free(new); - new = tmp; - tmp = ldns_dname_left_chop(d_tmp); - ldns_rdf_deep_free(d_tmp); - d_tmp = tmp; + assert(ldns_rdf_get_type(dname) == LDNS_RDF_TYPE_DNAME); + + rd_size = ldns_rdf_size(dname); + buf = LDNS_XMALLOC(uint8_t, rd_size); + if (! buf) { + return NULL; + } + new = ldns_rdf_new(LDNS_RDF_TYPE_DNAME, rd_size, buf); + if (! new) { + LDNS_FREE(buf); + return NULL; + } + + /* If dname ends in a root label, the reverse should too. + */ + if (ldns_dname_last_label_is_root_label(dname)) { + buf[rd_size - 1] = 0; + rd_size -= 1; + } + for (src_pos = 0; src_pos < rd_size; src_pos += len + 1) { + len = ldns_rdf_data(dname)[src_pos]; + memcpy(&buf[rd_size - src_pos - len - 1], + &ldns_rdf_data(dname)[src_pos], len + 1); } - ldns_rdf_deep_free(d_tmp); - return new; } @@ -519,6 +540,18 @@ ldns_dname_str_absolute(const char *dname_str) return 0; } +bool +ldns_dname_absolute(const ldns_rdf *rdf) +{ + char *str = ldns_rdf2str(rdf); + if (str) { + bool r = ldns_dname_str_absolute(str); + LDNS_FREE(str); + return r; + } + return false; +} + ldns_rdf * ldns_dname_label(const ldns_rdf *rdf, uint8_t labelpos) { diff --git a/dnssec.c b/dnssec.c index c6e93211787..684d17169e2 100644 --- a/dnssec.c +++ b/dnssec.c @@ -743,7 +743,6 @@ ldns_dnssec_create_nsec_bitmap(ldns_rr_type rr_type_list[], memcpy(data + cur_data_size + 2, cur_data, cur_window_max+1); cur_data_size += cur_window_max + 3; } - bitmap_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_NSEC, cur_data_size, data); @@ -1154,12 +1153,15 @@ ldns_create_nsec3(ldns_rdf *cur_owner, salt_length, salt); status = ldns_dname_cat(hashed_owner, cur_zone); - if(status != LDNS_STATUS_OK) + if(status != LDNS_STATUS_OK) { + ldns_rdf_deep_free(hashed_owner); return NULL; - + } nsec = ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3); - if(!nsec) + if(!nsec) { + ldns_rdf_deep_free(hashed_owner); return NULL; + } ldns_rr_set_type(nsec, LDNS_RR_TYPE_NSEC3); ldns_rr_set_owner(nsec, hashed_owner); @@ -1443,8 +1445,9 @@ ldns_pkt_verify_time(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o, sigs = s; } else { /* otherwise get them from the packet */ - sigs = ldns_pkt_rr_list_by_name_and_type(p, o, LDNS_RR_TYPE_RRSIG, - LDNS_SECTION_ANY_NOQUESTION); + sigs = ldns_pkt_rr_list_by_name_and_type(p, o, + LDNS_RR_TYPE_RRSIG, + LDNS_SECTION_ANY_NOQUESTION); if (!sigs) { /* no sigs */ return LDNS_STATUS_ERR; @@ -1457,24 +1460,26 @@ ldns_pkt_verify_time(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o, */ t_netorder = htons(t); /* rdf are in network order! */ /* a type identifier is a 16-bit number, so the size is 2 bytes */ - rdf_t = ldns_rdf_new(LDNS_RDF_TYPE_TYPE, - 2, - &t_netorder); + rdf_t = ldns_rdf_new(LDNS_RDF_TYPE_TYPE, 2, &t_netorder); + sigs_covered = ldns_rr_list_subtype_by_rdf(sigs, rdf_t, 0); + ldns_rdf_free(rdf_t); + if (! sigs_covered) { + if (! s) { + ldns_rr_list_deep_free(sigs); + } + return LDNS_STATUS_ERR; + } + ldns_rr_list_deep_free(sigs_covered); - rrset = ldns_pkt_rr_list_by_name_and_type(p, - o, - t, - LDNS_SECTION_ANY_NOQUESTION); - + rrset = ldns_pkt_rr_list_by_name_and_type(p, o, t, + LDNS_SECTION_ANY_NOQUESTION); if (!rrset) { + if (! s) { + ldns_rr_list_deep_free(sigs); + } return LDNS_STATUS_ERR; } - - if (!sigs_covered) { - return LDNS_STATUS_ERR; - } - return ldns_verify_time(rrset, sigs, k, check_time, good_keys); } diff --git a/dnssec_sign.c b/dnssec_sign.c index 88878bad044..f2f9d9dda87 100644 --- a/dnssec_sign.c +++ b/dnssec_sign.c @@ -260,6 +260,8 @@ ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys) ldns_buffer_free(sign_buf); /* ERROR */ ldns_rr_list_deep_free(rrset_clone); + ldns_rr_free(current_sig); + ldns_rr_list_deep_free(signatures); return NULL; } @@ -268,6 +270,8 @@ ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys) != LDNS_STATUS_OK) { ldns_buffer_free(sign_buf); ldns_rr_list_deep_free(rrset_clone); + ldns_rr_free(current_sig); + ldns_rr_list_deep_free(signatures); return NULL; } @@ -276,6 +280,8 @@ ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys) if (!b64rdf) { /* signing went wrong */ ldns_rr_list_deep_free(rrset_clone); + ldns_rr_free(current_sig); + ldns_rr_list_deep_free(signatures); return NULL; } @@ -481,10 +487,7 @@ ldns_sign_public_rsasha1(ldns_buffer *to_sign, RSA *key) (unsigned char*)ldns_buffer_begin(b64sig), &siglen, key); if (result != 1) { - return NULL; - } - - if (result != 1) { + ldns_buffer_free(b64sig); return NULL; } @@ -859,16 +862,14 @@ ldns_dnssec_zone_create_nsec3s_mkmap(ldns_dnssec_zone *zone, ldns_rbtree_next(current_name_node)); } if (result != LDNS_STATUS_OK) { + ldns_rr_list_free(nsec3_list); return result; } ldns_rr_list_sort_nsec3(nsec3_list); result = ldns_dnssec_chain_nsec3_list(nsec3_list); - if (result != LDNS_STATUS_OK) { - return result; - } - ldns_rr_list_free(nsec3_list); + return result; } @@ -1023,9 +1024,9 @@ ldns_key_list_filter_for_non_dnskey(ldns_key_list *key_list) } ldns_status -ldns_dnssec_zone_create_rrsigs_flg( ATTR_UNUSED(ldns_dnssec_zone *zone) - , ATTR_UNUSED(ldns_rr_list *new_rrs) - , ATTR_UNUSED(ldns_key_list *key_list) +ldns_dnssec_zone_create_rrsigs_flg( ldns_dnssec_zone *zone + , ldns_rr_list *new_rrs + , ldns_key_list *key_list , int (*func)(ldns_rr *, void*) , void *arg , int flags @@ -1112,9 +1113,11 @@ ldns_dnssec_zone_create_rrsigs_flg( ATTR_UNUSED(ldns_dnssec_zone *zone) cur_rrset->signatures = ldns_dnssec_rrs_new(); cur_rrset->signatures->rr = ldns_rr_list_rr(siglist, i); + } + if (new_rrs) { ldns_rr_list_push_rr(new_rrs, - ldns_rr_list_rr(siglist, - i)); + ldns_rr_list_rr(siglist, + i)); } } ldns_rr_list_free(siglist); @@ -1146,8 +1149,10 @@ ldns_dnssec_zone_create_rrsigs_flg( ATTR_UNUSED(ldns_dnssec_zone *zone) cur_name->nsec_signatures = ldns_dnssec_rrs_new(); cur_name->nsec_signatures->rr = ldns_rr_list_rr(siglist, i); + } + if (new_rrs) { ldns_rr_list_push_rr(new_rrs, - ldns_rr_list_rr(siglist, i)); + ldns_rr_list_rr(siglist, i)); } } diff --git a/dnssec_verify.c b/dnssec_verify.c index 68c70c5e848..d435eedf6af 100644 --- a/dnssec_verify.c +++ b/dnssec_verify.c @@ -285,9 +285,11 @@ ldns_dnssec_build_data_chain(ldns_resolver *res, ldns_rr_class c = 0; bool other_rrset = false; - + ldns_dnssec_data_chain *new_chain = ldns_dnssec_data_chain_new(); + assert(pkt != NULL); + if (!ldns_dnssec_pkt_has_rrsigs(pkt)) { /* hmm. no dnssec data in the packet. go up to try and deny * DS? */ @@ -402,15 +404,16 @@ ldns_dnssec_build_data_chain(ldns_resolver *res, if (signatures && ldns_rr_list_rr_count(signatures) > 0) { key_name = ldns_rr_rdf(ldns_rr_list_rr(signatures, 0), 7); } - if (!key_name) { + if (signatures) { + ldns_rr_list_deep_free(signatures); + } return ldns_dnssec_build_data_chain_nokeyname(res, qflags, orig_rr, rrset, new_chain); } - if (type != LDNS_RR_TYPE_DNSKEY) { ldns_dnssec_build_data_chain_dnskey(res, qflags, @@ -419,7 +422,7 @@ ldns_dnssec_build_data_chain(ldns_resolver *res, new_chain, key_name, c - ); + ); } else { ldns_dnssec_build_data_chain_other(res, qflags, @@ -427,13 +430,11 @@ ldns_dnssec_build_data_chain(ldns_resolver *res, key_name, c, dss - - ); + ); } if (signatures) { ldns_rr_list_deep_free(signatures); } - return new_chain; } @@ -826,10 +827,7 @@ ldns_dnssec_derive_trust_tree_normal_rrset_time( /* might contain different names! sort and split */ ldns_rr_list_sort(cur_rrset); - if (tmp_rrset && tmp_rrset != cur_rrset) { - ldns_rr_list_deep_free(tmp_rrset); - tmp_rrset = NULL; - } + assert(tmp_rrset == cur_rrset); tmp_rrset = ldns_rr_list_pop_rrset(cur_rrset); /* with nsecs, this might be the wrong one */ @@ -849,6 +847,12 @@ ldns_dnssec_derive_trust_tree_normal_rrset_time( cur_sig_rr, cur_parent_rr, check_time); + if (tmp_rrset && tmp_rrset != cur_rrset + ) { + ldns_rr_list_deep_free( + tmp_rrset); + tmp_rrset = NULL; + } /* avoid dupes */ for (i = 0; i < new_tree->parent_count; i++) { if (cur_parent_rr == new_tree->parents[i]->rr) { @@ -870,9 +874,6 @@ ldns_dnssec_derive_trust_tree_normal_rrset_time( } } done: - if (tmp_rrset && tmp_rrset != cur_rrset) { - ldns_rr_list_deep_free(tmp_rrset); - } ldns_rr_list_deep_free(cur_rrset); } @@ -1077,7 +1078,8 @@ ldns_dnssec_trust_tree_contains_keys(ldns_dnssec_trust_tree *tree, if (tree->parent_status[i] != LDNS_STATUS_OK) { result = tree->parent_status[i]; } else { - if (ldns_rr_get_type(tree->rr) + if (tree->rr && + ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NSEC && parent_result == LDNS_STATUS_OK ) { @@ -1210,8 +1212,8 @@ ldns_fetch_valid_domain_keys_time(const ldns_resolver *res, *status = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY; parent_domain = ldns_dname_left_chop(domain); - while (ldns_rdf_size(parent_domain) > 0) { - /* Fail if we are at the root */ + while (parent_domain && /* Fail if we are at the root*/ + ldns_rdf_size(parent_domain) > 0) { if ((parent_keys = ldns_fetch_valid_domain_keys_time(res, @@ -1247,7 +1249,9 @@ ldns_fetch_valid_domain_keys_time(const ldns_resolver *res, ldns_rdf_deep_free(prev_parent_domain); } } - ldns_rdf_deep_free(parent_domain); + if (parent_domain) { + ldns_rdf_deep_free(parent_domain); + } } } return trusted_keys; @@ -1519,12 +1523,11 @@ ldns_dnssec_verify_denial(ldns_rr *rr, rr_name = ldns_rr_owner(rr); chopped_dname = ldns_dname_left_chop(rr_name); result = ldns_dname_cat(wildcard_name, chopped_dname); + ldns_rdf_deep_free(chopped_dname); if (result != LDNS_STATUS_OK) { return result; } - ldns_rdf_deep_free(chopped_dname); - for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) { cur_nsec = ldns_rr_list_rr(nsecs, i); if (ldns_dname_compare(rr_name, ldns_rr_owner(cur_nsec)) == 0) { @@ -1576,7 +1579,6 @@ ldns_dnssec_verify_denial(ldns_rr *rr, return LDNS_STATUS_OK; } -#ifdef HAVE_SSL ldns_status ldns_dnssec_verify_denial_nsec3_match( ldns_rr *rr , ldns_rr_list *nsecs @@ -1612,7 +1614,7 @@ ldns_dnssec_verify_denial_nsec3_match( ldns_rr *rr ldns_rr_get_type(rr), nsecs); if(!closest_encloser) { - result = LDNS_STATUS_NSEC3_ERR; + result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; goto done; } @@ -1636,16 +1638,14 @@ ldns_dnssec_verify_denial_nsec3_match( ldns_rr *rr ldns_rdf_deep_free(hashed_wildcard_name); } + if (! wildcard_covered) { + result = LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED; + } else { + result = LDNS_STATUS_OK; + } ldns_rdf_deep_free(closest_encloser); ldns_rdf_deep_free(wildcard); - if (!wildcard_covered) { - result = LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED; - } else if (closest_encloser && wildcard_covered) { - result = LDNS_STATUS_OK; - } else { - result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED; - } } else if (packet_nodata && packet_qtype != LDNS_RR_TYPE_DS) { /* section 8.5 */ hashed_name = ldns_nsec3_hash_name_frm_nsec3( @@ -1819,9 +1819,6 @@ ldns_dnssec_verify_denial_nsec3(ldns_rr *rr, ); } - -#endif /* HAVE_SSL */ - #ifdef USE_GOST EVP_PKEY* ldns_gost2pkey_raw(unsigned char* key, size_t keylen) diff --git a/dnssec_zone.c b/dnssec_zone.c index 1f7274bbc96..df71a23c7ed 100644 --- a/dnssec_zone.c +++ b/dnssec_zone.c @@ -708,6 +708,7 @@ ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, ldns_rdf* origin, case LDNS_STATUS_SYNTAX_EMPTY: /* empty line was seen */ case LDNS_STATUS_SYNTAX_TTL: /* the ttl was set*/ case LDNS_STATUS_SYNTAX_ORIGIN: /* the origin was set*/ + status = LDNS_STATUS_OK; break; case LDNS_STATUS_SYNTAX_INCLUDE:/* $include not implemented */ @@ -721,38 +722,42 @@ ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, ldns_rdf* origin, if (ldns_rr_list_rr_count(todo_nsec3s) > 0) { (void) ldns_dnssec_zone_add_empty_nonterminals(newzone); - for (i = 0; i < ldns_rr_list_rr_count(todo_nsec3s); i++) { + for (i = 0; status == LDNS_STATUS_OK && + i < ldns_rr_list_rr_count(todo_nsec3s); i++) { cur_rr = ldns_rr_list_rr(todo_nsec3s, i); status = ldns_dnssec_zone_add_rr(newzone, cur_rr); } - for (i = 0; i < ldns_rr_list_rr_count(todo_nsec3_rrsigs); i++){ + for (i = 0; status == LDNS_STATUS_OK && + i < ldns_rr_list_rr_count(todo_nsec3_rrsigs); + i++){ cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i); status = ldns_dnssec_zone_add_rr(newzone, cur_rr); } } else if (ldns_rr_list_rr_count(todo_nsec3_rrsigs) > 0) { - for (i = 0; i < ldns_rr_list_rr_count(todo_nsec3_rrsigs); i++){ + for (i = 0; status == LDNS_STATUS_OK && + i < ldns_rr_list_rr_count(todo_nsec3_rrsigs); + i++){ cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i); status = ldns_dnssec_zone_add_rr(newzone, cur_rr); } } - ldns_rr_list_free(todo_nsec3_rrsigs); - ldns_rr_list_free(todo_nsec3s); - if (z) { *z = newzone; + newzone = NULL; } else { ldns_dnssec_zone_free(newzone); } - return LDNS_STATUS_OK; - error: #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP if (zone) { ldns_zone_free(zone); } #endif + ldns_rr_list_free(todo_nsec3_rrsigs); + ldns_rr_list_free(todo_nsec3s); + if (my_origin) { ldns_rdf_deep_free(my_origin); } @@ -822,7 +827,6 @@ ldns_dname_compare_v(const void *a, const void *b) { return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b); } -#ifdef HAVE_SSL ldns_rbnode_t * ldns_dnssec_zone_find_nsec3_original(ldns_dnssec_zone *zone, ldns_rr *rr) { @@ -912,7 +916,6 @@ ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr) return result; } -#endif /* HAVE_SSL */ void ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt, @@ -1009,7 +1012,9 @@ ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone) if (next_node == LDNS_RBTREE_NULL) { next_node = ldns_rbtree_first(zone->names); } - + if (! cur_node->data || ! next_node->data) { + return LDNS_STATUS_ERR; + } cur_name = ((ldns_dnssec_name *)cur_node->data)->name; next_name = ((ldns_dnssec_name *)next_node->data)->name; cur_label_count = ldns_dname_label_count(cur_name); diff --git a/doc/doxyparse.pl b/doc/doxyparse.pl index 526c617101b..96a1732f9ed 100755 --- a/doc/doxyparse.pl +++ b/doc/doxyparse.pl @@ -87,7 +87,7 @@ if (defined $options{'m'}) { # 0 - somewhere in the file # 1 - in a doxygen par -# 2 - after doxygen, except funcion +# 2 - after doxygen, expect function # create our pwd mkdir "doc"; @@ -126,7 +126,14 @@ while($i < $max) { } if ($cur_line =~ /\*\// and $state == 1) { #print "END Comment seen!\n"; - $state = 2; + if ($description =~ /^\\\\file/mg) { + # Doxygen text for the file, do not expect + # a function coming. + # + $state = 0; + } else { + $state = 2; + } $i++; next; } @@ -184,6 +191,14 @@ while($i < $max) { $description =~ s/\\param\[out\][ \t]*([\*\w]+)[ \t]+/.br\n\\fB$1\\fR: /g; $description =~ s/\\return[ \t]*/.br\nReturns /g; + # Delete leading spaces to prevent manpages to be ascii format- + # ted and enable justification of text. + # + $description =~ s/^[ \t]*//mg; + + # Prevent hyphening of all caps and underscore words + $description =~ s/\b([A-Z_]+)\b/\\%$1/g; + $description{$key} = $description; $api{$key} = $api; $return{$key} = $return; diff --git a/doc/function_manpages b/doc/function_manpages index 15706fada57..ce05899b7cf 100644 --- a/doc/function_manpages +++ b/doc/function_manpages @@ -39,6 +39,11 @@ ldns_dname_compare, ldns_dname_interval | ldns_dname_is_subdomain | ldns_dname ldns_dname | ldns_dname_left_chop, ldns_dname_label_count, ldns_dname2canonical, ldns_dname_cat, ldns_dname_cat_clone, ldns_dname_new, ldns_dname_new_frm_str, ldns_dname_new_frm_data, ldns_dname_is_subdomain, ldns_dname_str_absolute, ldns_dname_label, ldns_dname_compare, ldns_dname_interval ### /dname.h +### dane.h +ldns_dane_create_tlsa_owner, ldns_dane_cert2rdf, ldns_dane_select_certificate, ldns_dane_create_tlsa_rr | ldns_dane_verify, ldns_dane_verify_rr +ldns_dane_verify, ldns_dane_verify_rr | ldns_dane_create_tlsa_owner, ldns_dane_cert2rdf, ldns_dane_select_certificate, ldns_dane_create_tlsa_rr +### /dane.h + ### rdata.h ldns_rdf, ldns_rdf_type | ldns_rdf_set_size, ldns_rdf_set_type, ldns_rdf_set_data, ldns_rdf_size, ldns_rdf_get_type, ldns_rdf_data, ldns_rdf_compare, ldns_rdf_new, ldns_rdf_clone, ldns_rdf_new_frm_data, ldns_rdf_new_frm_str, ldns_rdf_new_frm_fp, ldns_rdf_free, ldns_rdf_deep_free, ldns_rdf_print, ldns_native2rdf_int8, ldns_native2rdf_int16, ldns_native2rdf_int32, ldns_native2rdf_int16_data, ldns_rdf2native_int8, ldns_rdf2native_int16, ldns_rdf2native_int32, ldns_rdf2native_sockaddr_storage, ldns_rdf2native_time_t, ldns_native2rdf_int8, ldns_native2rdf_int16, ldns_native2rdf_int32, ldns_native2rdf_int16_data, ldns_rdf2native_int8, ldns_rdf2native_int16, ldns_rdf2native_int32, ldns_rdf2native_sockaddr_storage, ldns_rdf2native_time_t, ldns_native2rdf_int8, ldns_native2rdf_int16, ldns_native2rdf_int32, ldns_native2rdf_int16_data, ldns_rdf2native_int8, ldns_rdf2native_int16, ldns_rdf2native_int32, ldns_rdf2native_sockaddr_storage, ldns_rdf2native_time_t ldns_rdf_set_size, ldns_rdf_set_type, ldns_rdf_set_data | ldns_rdf diff --git a/drill/Makefile.in b/drill/Makefile.in index 5730f0809c7..ac555fa1e57 100644 --- a/drill/Makefile.in +++ b/drill/Makefile.in @@ -9,6 +9,7 @@ exec_prefix = @exec_prefix@ bindir = @bindir@ mandir = @mandir@ includedir = @includedir@ +datarootdir = @datarootdir@ CC = @CC@ CFLAGS = -I. @CFLAGS@ @@ -77,7 +78,6 @@ docclean: distclean: clean docclean rm -f config.h - rm -f drill.h realclean: clean docclean rm -f tags @@ -88,9 +88,9 @@ realclean: clean docclean rm -rf autom4te.cache rm -f config.h rm -f config.h.in - rm -f drill.h rm -f configure rm -f Makefile + rm -f drill.1 rm -f aclocal.m4 doc: @@ -99,7 +99,7 @@ doc: install: all $(INSTALL) -d $(DESTDIR)$(bindir) $(INSTALL) drill $(DESTDIR)$(bindir)/drill - $(INSTALL) -m 644 $(srcdir)/drill.1 $(DESTDIR)$(mandir)/man1/drill.1 + $(INSTALL) -m 644 drill.1 $(DESTDIR)$(mandir)/man1/drill.1 uninstall: @echo @@ -116,4 +116,4 @@ lint: done confclean: clean - rm -rf config.log config.status config.h Makefile + rm -rf config.log config.status config.h Makefile drill.1 diff --git a/drill/chasetrace.c b/drill/chasetrace.c index c2bbfd00901..0a37ff3017e 100644 --- a/drill/chasetrace.c +++ b/drill/chasetrace.c @@ -45,7 +45,15 @@ do_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t, p = ldns_pkt_new(); res = ldns_resolver_new(); - if (!p || !res) { + if (!p) { + if (res) { + ldns_resolver_free(res); + } + error("Memory allocation failed"); + return NULL; + } + if (!res) { + ldns_pkt_free(p); error("Memory allocation failed"); return NULL; } @@ -73,6 +81,8 @@ do_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t, if (status != LDNS_STATUS_OK) { fprintf(stderr, "Error adding root servers to resolver: %s\n", ldns_get_errorstr_by_id(status)); ldns_rr_list_print(stdout, global_dns_root); + ldns_resolver_free(res); + ldns_pkt_free(p); return NULL; } @@ -118,7 +128,7 @@ do_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t, drill_pkt_print_footer(stdout, local_res, p); /* remove the old nameserver from the resolver */ - while((pop = ldns_resolver_pop_nameserver(res))) { /* do it */ } + while(ldns_resolver_pop_nameserver(res)) { /* do it */ } /* also check for new_nss emptyness */ diff --git a/drill/config.h.in b/drill/config.h.in index 9b2a282a8e9..75448a07ecc 100644 --- a/drill/config.h.in +++ b/drill/config.h.in @@ -111,6 +111,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_WS2TCPIP_H +/* Default trust anchor file */ +#undef LDNS_TRUST_ANCHOR_FILE + /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT diff --git a/drill/configure b/drill/configure index 95bc4356072..6a4487d9a97 100755 --- a/drill/configure +++ b/drill/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.68 for ldns 1.6.13. +# Generated by GNU Autoconf 2.68 for ldns 1.6.16. # # Report bugs to . # @@ -560,8 +560,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='ldns' PACKAGE_TARNAME='libdns' -PACKAGE_VERSION='1.6.13' -PACKAGE_STRING='ldns 1.6.13' +PACKAGE_VERSION='1.6.16' +PACKAGE_STRING='ldns 1.6.16' PACKAGE_BUGREPORT='libdns@nlnetlabs.nl' PACKAGE_URL='' @@ -604,6 +604,7 @@ ac_includes_default="\ ac_subst_vars='LTLIBOBJS LIBOBJS +LDNS_TRUST_ANCHOR_FILE LDNSDIR LIBS_STC RUNTIME_PATH @@ -664,6 +665,7 @@ enable_option_checking enable_rpath with_ssl with_ldns +with_trust_anchor ' ac_precious_vars='build_alias host_alias @@ -1216,7 +1218,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 ldns 1.6.13 to adapt to many kinds of systems. +\`configure' configures ldns 1.6.16 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1277,7 +1279,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of ldns 1.6.13:";; + short | recursive ) echo "Configuration of ldns 1.6.16:";; esac cat <<\_ACEOF @@ -1296,6 +1298,9 @@ Optional Packages: --with-ldns=PATH specify prefix of path of ldns library to use + --with-trust-anchor=KEYFILE + Default location of the trust anchor file. + [default=SYSCONFDIR/unbound/root.key] Some influential environment variables: CC C compiler command @@ -1373,7 +1378,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -ldns configure 1.6.13 +ldns configure 1.6.16 generated by GNU Autoconf 2.68 Copyright (C) 2010 Free Software Foundation, Inc. @@ -1796,7 +1801,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 ldns $as_me 1.6.13, which was +It was created by ldns $as_me 1.6.16, which was generated by GNU Autoconf 2.68. Invocation command line was $ $0 $@ @@ -5379,7 +5384,6 @@ else as_fn_error $? "Can't find ldns library" "$LINENO" 5 - fi fi @@ -5387,8 +5391,39 @@ fi +# Check whether --with-trust-anchor was given. +if test "${with_trust_anchor+set}" = set; then : + withval=$with_trust_anchor; + LDNS_TRUST_ANCHOR_FILE="$withval" -ac_config_files="$ac_config_files Makefile" +else + + if test "x$LDNS_TRUST_ANCHOR_FILE" = "x"; then + if test "x$sysconfdir" = 'x${prefix}/etc' ; then + if test "x$prefix" = 'xNONE' ; then + LDNS_TRUST_ANCHOR_FILE="/etc/unbound/root.key" + else + LDNS_TRUST_ANCHOR_FILE="${prefix}/etc/unbound/root.key" + fi + else + LDNS_TRUST_ANCHOR_FILE="${sysconfdir}/unbound/root.key" + fi + fi + +fi + + +cat >>confdefs.h <<_ACEOF +#define LDNS_TRUST_ANCHOR_FILE "$LDNS_TRUST_ANCHOR_FILE" +_ACEOF + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: Default trust anchor: $LDNS_TRUST_ANCHOR_FILE" >&5 +$as_echo "$as_me: Default trust anchor: $LDNS_TRUST_ANCHOR_FILE" >&6;} + + + +ac_config_files="$ac_config_files Makefile drill.1" ac_config_headers="$ac_config_headers config.h" @@ -5910,7 +5945,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 ldns $as_me 1.6.13, which was +This file was extended by ldns $as_me 1.6.16, which was generated by GNU Autoconf 2.68. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -5972,7 +6007,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="\\ -ldns config.status 1.6.13 +ldns config.status 1.6.16 configured by $0, generated by GNU Autoconf 2.68, with options \\"\$ac_cs_config\\" @@ -6094,6 +6129,7 @@ for ac_config_target in $ac_config_targets do case $ac_config_target in "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "drill.1") CONFIG_FILES="$CONFIG_FILES drill.1" ;; "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; diff --git a/drill/configure.ac b/drill/configure.ac index afd5c63803b..17d7541c027 100644 --- a/drill/configure.ac +++ b/drill/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.56) -AC_INIT(ldns, 1.6.13, libdns@nlnetlabs.nl,libdns) +AC_INIT(ldns, 1.6.16, libdns@nlnetlabs.nl,libdns) AC_CONFIG_SRCDIR([drill.c]) sinclude(../acx_nlnetlabs.m4) @@ -170,13 +170,33 @@ if test -f $ldns_dev_dir/ldns/util.h && \ else AC_MSG_RESULT([no]) AC_CHECK_LIB(ldns, ldns_rr_new, , [ - AC_MSG_ERROR([Can't find ldns library]) + AC_MSG_ERROR([Can't find ldns library])dnl ' ] ) fi AC_SUBST(LDNSDIR) +AC_ARG_WITH(trust-anchor, AC_HELP_STRING([--with-trust-anchor=KEYFILE], +[Default location of the trust anchor file. [default=SYSCONFDIR/unbound/root.key]]), [ + LDNS_TRUST_ANCHOR_FILE="$withval" +],[ + if test "x$LDNS_TRUST_ANCHOR_FILE" = "x"; then + if test "x$sysconfdir" = 'x${prefix}/etc' ; then + if test "x$prefix" = 'xNONE' ; then + LDNS_TRUST_ANCHOR_FILE="/etc/unbound/root.key" + else + LDNS_TRUST_ANCHOR_FILE="${prefix}/etc/unbound/root.key" + fi + else + LDNS_TRUST_ANCHOR_FILE="${sysconfdir}/unbound/root.key" + fi + fi +]) +AC_DEFINE_UNQUOTED([LDNS_TRUST_ANCHOR_FILE], ["$LDNS_TRUST_ANCHOR_FILE"], [Default trust anchor file]) +AC_SUBST(LDNS_TRUST_ANCHOR_FILE) +AC_MSG_NOTICE([Default trust anchor: $LDNS_TRUST_ANCHOR_FILE]) + AH_BOTTOM([ #include @@ -254,6 +274,6 @@ extern int optind, opterr; #endif ]) -AC_CONFIG_FILES([Makefile]) +AC_CONFIG_FILES([Makefile drill.1]) AC_CONFIG_HEADER([config.h]) AC_OUTPUT diff --git a/drill/dnssec.c b/drill/dnssec.c index b72ffb95dad..b8074be03cc 100644 --- a/drill/dnssec.c +++ b/drill/dnssec.c @@ -22,12 +22,10 @@ get_rr(ldns_resolver *res, ldns_rdf *zname, ldns_rr_type t, ldns_rr_class c) p = ldns_pkt_new(); found = NULL; - if (ldns_resolver_send(&p, res, zname, t, c, 0) != LDNS_STATUS_OK) { - /* oops */ - return NULL; - } else { + if (ldns_resolver_send(&p, res, zname, t, c, 0) == LDNS_STATUS_OK) { found = ldns_pkt_rr_list_by_type(p, t, LDNS_SECTION_ANY_NOQUESTION); } + ldns_pkt_free(p); return found; } @@ -36,6 +34,7 @@ drill_pkt_print(FILE *fd, ldns_resolver *r, ldns_pkt *p) { ldns_rr_list *new_nss; ldns_rr_list *hostnames; + char *answerfrom_str; if (verbosity < 5) { return; @@ -46,8 +45,7 @@ drill_pkt_print(FILE *fd, ldns_resolver *r, ldns_pkt *p) new_nss = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_NS, LDNS_SECTION_ANSWER); ldns_rr_list_print(fd, new_nss); - - /* new_nss can be empty.... */ + ldns_rr_list_deep_free(new_nss); fprintf(fd, ";; Received %d bytes from %s#%d(", (int) ldns_pkt_size(p), @@ -59,7 +57,11 @@ drill_pkt_print(FILE *fd, ldns_resolver *r, ldns_pkt *p) ldns_rr_rdf(ldns_rr_list_rr(hostnames, 0), 0)); ldns_rr_list_deep_free(hostnames); } else { - fprintf(fd, "%s", ldns_rdf2str(ldns_pkt_answerfrom(p))); + answerfrom_str = ldns_rdf2str(ldns_pkt_answerfrom(p)); + if (answerfrom_str) { + fprintf(fd, "%s", answerfrom_str); + LDNS_FREE(answerfrom_str); + } } fprintf(fd, ") in %u ms\n\n", (unsigned int)ldns_pkt_querytime(p)); } @@ -68,6 +70,7 @@ void drill_pkt_print_footer(FILE *fd, ldns_resolver *r, ldns_pkt *p) { ldns_rr_list *hostnames; + char *answerfrom_str; if (verbosity < 5) { return; @@ -85,7 +88,11 @@ drill_pkt_print_footer(FILE *fd, ldns_resolver *r, ldns_pkt *p) ldns_rr_rdf(ldns_rr_list_rr(hostnames, 0), 0)); ldns_rr_list_deep_free(hostnames); } else { - fprintf(fd, "%s", ldns_rdf2str(ldns_pkt_answerfrom(p))); + answerfrom_str = ldns_rdf2str(ldns_pkt_answerfrom(p)); + if (answerfrom_str) { + fprintf(fd, "%s", answerfrom_str); + LDNS_FREE(answerfrom_str); + } } fprintf(fd, ") in %u ms\n\n", (unsigned int)ldns_pkt_querytime(p)); } @@ -98,7 +105,6 @@ get_dnssec_rr(ldns_pkt *p, ldns_rdf *name, ldns_rr_type t, ldns_rr_list **rrlist, ldns_rr_list **sig) { ldns_pkt_type pt = LDNS_PACKET_UNKNOWN; - ldns_rr_list *rr = NULL; ldns_rr_list *sigs = NULL; size_t i; @@ -111,36 +117,52 @@ get_dnssec_rr(ldns_pkt *p, ldns_rdf *name, ldns_rr_type t, pt = ldns_pkt_reply_type(p); if (name) { - rr = ldns_pkt_rr_list_by_name_and_type(p, name, t, LDNS_SECTION_ANSWER); - if (!rr) { - rr = ldns_pkt_rr_list_by_name_and_type(p, name, t, LDNS_SECTION_AUTHORITY); + if (rrlist) { + *rrlist = ldns_pkt_rr_list_by_name_and_type(p, name, t, + LDNS_SECTION_ANSWER); + if (!*rrlist) { + *rrlist = ldns_pkt_rr_list_by_name_and_type( + p, name, t, + LDNS_SECTION_AUTHORITY); + } } - sigs = ldns_pkt_rr_list_by_name_and_type(p, name, LDNS_RR_TYPE_RRSIG, - LDNS_SECTION_ANSWER); - if (!sigs) { - sigs = ldns_pkt_rr_list_by_name_and_type(p, name, LDNS_RR_TYPE_RRSIG, - LDNS_SECTION_AUTHORITY); + if (sig) { + sigs = ldns_pkt_rr_list_by_name_and_type(p, name, + LDNS_RR_TYPE_RRSIG, + LDNS_SECTION_ANSWER); + if (!sigs) { + sigs = ldns_pkt_rr_list_by_name_and_type( + p, name, LDNS_RR_TYPE_RRSIG, + LDNS_SECTION_AUTHORITY); + } } } else { - /* A DS-referral - get the DS records if they are there */ - rr = ldns_pkt_rr_list_by_type(p, t, LDNS_SECTION_AUTHORITY); - sigs = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_RRSIG, - LDNS_SECTION_AUTHORITY); + /* A DS-referral - get the DS records if they are there */ + if (rrlist) { + *rrlist = ldns_pkt_rr_list_by_type( + p, t, LDNS_SECTION_AUTHORITY); + } + if (sig) { + sigs = ldns_pkt_rr_list_by_type(p, + LDNS_RR_TYPE_RRSIG, + LDNS_SECTION_AUTHORITY); + } } if (sig) { *sig = ldns_rr_list_new(); for (i = 0; i < ldns_rr_list_rr_count(sigs); i++) { /* only add the sigs that cover this type */ - if (ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(ldns_rr_list_rr(sigs, i))) == - t) { - ldns_rr_list_push_rr(*sig, ldns_rr_clone(ldns_rr_list_rr(sigs, i))); + if (t == ldns_rdf2rr_type(ldns_rr_rrsig_typecovered( + ldns_rr_list_rr(sigs, i)))) { + + ldns_rr_list_push_rr(*sig, + ldns_rr_clone( + ldns_rr_list_rr( + sigs, i))); } } } ldns_rr_list_deep_free(sigs); - if (rrlist) { - *rrlist = rr; - } if (pt == LDNS_PACKET_NXDOMAIN || pt == LDNS_PACKET_NODATA) { return pt; @@ -153,6 +175,7 @@ get_dnssec_rr(ldns_pkt *p, ldns_rdf *name, ldns_rr_type t, ldns_status ldns_verify_denial(ldns_pkt *pkt, ldns_rdf *name, ldns_rr_type type, ldns_rr_list **nsec_rrs, ldns_rr_list **nsec_rr_sigs) { +#ifdef HAVE_SSL uint16_t nsec_i; ldns_rr_list *nsecs; @@ -216,12 +239,28 @@ ldns_verify_denial(ldns_pkt *pkt, ldns_rdf *name, ldns_rr_type type, ldns_rr_lis ldns_rr_list* sigs = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_RRSIG, LDNS_SECTION_ANY_NOQUESTION); ldns_rr* q = ldns_rr_new(); ldns_rr* match = NULL; - if(!sigs) return LDNS_STATUS_MEM_ERR; - if(!q) return LDNS_STATUS_MEM_ERR; + + if(!sigs) { + if (q) { + ldns_rr_free(q); + } + ldns_rr_list_deep_free(nsecs); + return LDNS_STATUS_MEM_ERR; + } + if(!q) { + ldns_rr_list_deep_free(nsecs); + ldns_rr_list_deep_free(sigs); + return LDNS_STATUS_MEM_ERR; + } ldns_rr_set_question(q, 1); ldns_rr_set_ttl(q, 0); ldns_rr_set_owner(q, ldns_rdf_clone(name)); - if(!ldns_rr_owner(q)) return LDNS_STATUS_MEM_ERR; + if(!ldns_rr_owner(q)) { + ldns_rr_free(q); + ldns_rr_list_deep_free(sigs); + ldns_rr_list_deep_free(nsecs); + return LDNS_STATUS_MEM_ERR; + } ldns_rr_set_type(q, type); /* result = ldns_dnssec_verify_denial_nsec3(q, nsecs, sigs, ldns_pkt_get_rcode(pkt), type, ldns_pkt_ancount(pkt) == 0); */ @@ -234,6 +273,14 @@ ldns_verify_denial(ldns_pkt *pkt, ldns_rdf *name, ldns_rr_type type, ldns_rr_lis ldns_rr_list_deep_free(sigs); } return result; +#else + (void)pkt; + (void)name; + (void)type; + (void)nsec_rrs; + (void)nsec_rr_sigs; + return LDNS_STATUS_ERR; +#endif /* HAVE_SSL */ } /* NSEC3 draft -07 */ diff --git a/drill/drill.1 b/drill/drill.1.in similarity index 93% rename from drill/drill.1 rename to drill/drill.1.in index 24cfd6dabe9..15b15a42533 100644 --- a/drill/drill.1 +++ b/drill/drill.1.in @@ -161,6 +161,11 @@ given \fBdrill\fR tries to validate the current answer with this key. No chasing is done. When \fBdrill\fR is doing a secure trace, this key will be used as trust anchor. Can contain a DNSKEY or a DS record. +Alternatively, when DNSSEC enabled tracing (\fB-TD\fR) or signature +chasing (\fB-S\fR), if \fB-k\fR is not specified, and a default trust anchor +(@LDNS_TRUST_ANCHOR_FILE@) exists and contains a valid DNSKEY or DS record, +it will be used as the trust anchor. + .TP \fB\-o \fImnemonic\fR Use this option to set or unset specific header bits. A bit is @@ -212,6 +217,13 @@ specify named base64 tsig key, and optional an algorithm (defaults to hmac-md5.s \fB\-z \fR don't randomize the nameserver list before sending queries. +.SH "FILES" +.TP +@LDNS_TRUST_ANCHOR_FILE@ +The file from which trusted keys are loaded when no \fB-k\fR option is given. +.SH "SEE ALSO" +.LP +unbound-anchor(8) .SH AUTHOR Jelte Jansen and Miek Gieben. Both of NLnet Labs. diff --git a/drill/drill.c b/drill/drill.c index 2f779634d8e..574c8b98c85 100644 --- a/drill/drill.c +++ b/drill/drill.c @@ -47,19 +47,25 @@ usage(FILE *stream, const char *progname) fprintf(stream, "\t-6\t\tstay on ip6\n"); fprintf(stream, "\t-a\t\tfallback to EDNS0 and TCP if the answer is truncated\n"); fprintf(stream, "\t-b \tuse as the buffer size (defaults to 512 b)\n"); - fprintf(stream, "\t-c \t\tuse file for rescursive nameserver configuration (/etc/resolv.conf)\n"); - fprintf(stream, "\t-k \tspecify a file that contains a trusted DNSSEC key (DNSKEY|DS) [**]\n"); - fprintf(stream, "\t\t\tused to verify any signatures in the current answer\n"); - fprintf(stream, "\t-o \tset flags to: [QR|qr][AA|aa][TC|tc][RD|rd][CD|cd][RA|ra][AD|ad]\n"); + fprintf(stream, "\t-c \tuse file for rescursive nameserver configuration" + "\n\t\t\t(/etc/resolv.conf)\n"); + fprintf(stream, "\t-k \tspecify a file that contains a trusted DNSSEC key [**]\n"); + fprintf(stream, "\t\t\tUsed to verify any signatures in the current answer.\n"); + fprintf(stream, "\t\t\tWhen DNSSEC enabled tracing (-TD) or signature\n" + "\t\t\tchasing (-S) and no key files are given, keys are read\n" + "\t\t\tfrom: %s\n", + LDNS_TRUST_ANCHOR_FILE); + fprintf(stream, "\t-o \tset flags to:" + "\n\t\t\t[QR|qr][AA|aa][TC|tc][RD|rd][CD|cd][RA|ra][AD|ad]\n"); fprintf(stream, "\t\t\tlowercase: unset bit, uppercase: set bit\n"); fprintf(stream, "\t-p \tuse as remote port number\n"); fprintf(stream, "\t-s\t\tshow the DS RR for each key in a packet\n"); fprintf(stream, "\t-u\t\tsend the query with udp (the default)\n"); fprintf(stream, "\t-x\t\tdo a reverse lookup\n"); fprintf(stream, "\twhen doing a secure trace:\n"); - fprintf(stream, "\t-r \t\tuse file as root servers hint file\n"); + fprintf(stream, "\t-r \tuse file as root servers hint file\n"); fprintf(stream, "\t-t\t\tsend the query with tcp (connected)\n"); - fprintf(stream, "\t-d \t\tuse domain as the start point for the trace\n"); + fprintf(stream, "\t-d \tuse domain as the start point for the trace\n"); fprintf(stream, "\t-y \tspecify named base64 tsig key, and optional an\n\t\t\talgorithm (defaults to hmac-md5.sig-alg.reg.int)\n"); fprintf(stream, "\t-z\t\tdon't randomize the nameservers before use\n"); fprintf(stream, "\n [*] = enables/implies DNSSEC\n"); @@ -272,7 +278,8 @@ main(int argc, char *argv[]) qusevc = true; break; case 'k': - status = read_key_file(optarg, key_list); + status = read_key_file(optarg, + key_list, false); if (status != LDNS_STATUS_OK) { error("Could not parse the key file %s: %s", optarg, ldns_get_errorstr_by_id(status)); } @@ -397,6 +404,15 @@ main(int argc, char *argv[]) argc -= optind; argv += optind; + if ((PURPOSE == DRILL_CHASE || (PURPOSE == DRILL_TRACE && qdnssec)) && + ldns_rr_list_rr_count(key_list) == 0) { + + (void) read_key_file(LDNS_TRUST_ANCHOR_FILE, key_list, true); + } + if (ldns_rr_list_rr_count(key_list) > 0) { + printf(";; Number of trusted keys: %d\n", + (int) ldns_rr_list_rr_count(key_list)); + } /* do a secure trace when requested */ if (PURPOSE == DRILL_TRACE && qdnssec) { #ifdef HAVE_SSL diff --git a/drill/drill.h b/drill/drill.h index 69b0396b217..0746fe7bff2 100644 --- a/drill/drill.h +++ b/drill/drill.h @@ -85,7 +85,6 @@ ldns_status ldns_verify_denial(ldns_pkt *pkt, ldns_rr_list **nsec_rrs, ldns_rr_list **nsec_rr_sigs); -ldns_status read_key_file(const char *filename, ldns_rr_list *key_list); ldns_pkt *read_hex_pkt(char *filename); ldns_buffer *read_hex_buffer(char *filename); void init_root(void); diff --git a/drill/drill_util.c b/drill/drill_util.c index 98d88e7942d..db0433e77e1 100644 --- a/drill/drill_util.c +++ b/drill/drill_util.c @@ -13,14 +13,14 @@ #include -static size_t +static int read_line(FILE *input, char *line, size_t len) { - size_t i; + int i; char c; - for (i = 0; i < len-1; i++) { - c = getc(input); + for (i = 0; i < (int)len-1; i++) { + c = (char)getc(input); if (c == EOF) { return -1; } else if (c != '\n') { @@ -35,20 +35,22 @@ read_line(FILE *input, char *line, size_t len) /* key_list must be initialized with ldns_rr_list_new() */ ldns_status -read_key_file(const char *filename, ldns_rr_list *key_list) +read_key_file(const char *filename, ldns_rr_list *key_list, bool silently) { int line_len = 0; int line_nr = 0; int key_count = 0; - char line[LDNS_MAX_PACKETLEN]; + char line[LDNS_MAX_LINELEN]; ldns_status status; FILE *input_file; ldns_rr *rr; input_file = fopen(filename, "r"); if (!input_file) { - fprintf(stderr, "Error opening %s: %s\n", - filename, strerror(errno)); + if (! silently) { + fprintf(stderr, "Error opening %s: %s\n", + filename, strerror(errno)); + } return LDNS_STATUS_ERR; } while (line_len >= 0) { @@ -57,10 +59,13 @@ read_key_file(const char *filename, ldns_rr_list *key_list) if (line_len > 0 && line[0] != ';') { status = ldns_rr_new_frm_str(&rr, line, 0, NULL, NULL); if (status != LDNS_STATUS_OK) { - fprintf(stderr, - "Error parsing DNSKEY RR in line %d: %s\n", - line_nr, - ldns_get_errorstr_by_id(status)); + if (! silently) { + fprintf(stderr, + "Error parsing DNSKEY RR " + "in line %d: %s\n", line_nr, + ldns_get_errorstr_by_id(status) + ); + } } else if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_DNSKEY || ldns_rr_get_type(rr) == LDNS_RR_TYPE_DS) { ldns_rr_list_push_rr(key_list, rr); @@ -70,7 +75,7 @@ read_key_file(const char *filename, ldns_rr_list *key_list) } } } - printf(";; Number of trusted keys: %d\n", key_count); + fclose(input_file); if (key_count > 0) { return LDNS_STATUS_OK; } else { @@ -132,6 +137,7 @@ print_ds_of_keys(ldns_pkt *p) ds = ldns_key_rr2ds(ldns_rr_list_rr(keys, i), LDNS_SHA256); local_print_ds(stdout, "; sha256: ", ds); } + ldns_rr_list_deep_free(keys); } } diff --git a/drill/drill_util.h b/drill/drill_util.h index de7844118db..42b3f32b25d 100644 --- a/drill/drill_util.h +++ b/drill/drill_util.h @@ -12,6 +12,13 @@ #define _DRILL_UTIL_H_ #include + +/** + * Read keys from filename and append to key_list. + */ +ldns_status read_key_file(const char *filename, ldns_rr_list *key_list, + bool silently); + /** * return a address rdf, either A or AAAA * NULL if anything goes wrong diff --git a/drill/securetrace.c b/drill/securetrace.c index 029ebf51d6f..c6e7e588409 100644 --- a/drill/securetrace.c +++ b/drill/securetrace.c @@ -231,7 +231,8 @@ do_secure_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t, if (status != LDNS_STATUS_OK) { printf("ERRRRR: %s\n", ldns_get_errorstr_by_id(status)); ldns_rr_list_print(stdout, global_dns_root); - return status; + result = status; + goto done; } labels_count = ldns_dname_label_count(name); if (start_name) { @@ -392,7 +393,6 @@ do_secure_trace(ldns_resolver *local_res, ldns_rdf *name, ldns_rr_type t, printf(";; There is an empty non-terminal here, continue\n"); continue; } - goto done; } if (ldns_resolver_nameserver_count(res) == 0) { diff --git a/drill/work.c b/drill/work.c index 3a9cb5855d7..653145fe522 100644 --- a/drill/work.c +++ b/drill/work.c @@ -122,11 +122,6 @@ packetbuffromfile(char *filename, uint8_t *wire) hexbuf[hexbufpos] = (uint8_t) c; hexbufpos++; break; - default: - warning("unknown state while reading %s", filename); - xfree(hexbuf); - return 0; - break; } c = fgetc(fp); } @@ -178,20 +173,7 @@ read_hex_buffer(char *filename) size_t wiresize; ldns_buffer *result_buffer = NULL; - FILE *fp = NULL; - - if (strncmp(filename, "-", 2) != 0) { - fp = fopen(filename, "r"); - } else { - fp = stdin; - } - - if (fp == NULL) { - perror(""); - warning("Unable to open %s", filename); - return NULL; - } - + wire = xmalloc(LDNS_MAX_PACKETLEN); wiresize = packetbuffromfile(filename, wire); @@ -199,8 +181,8 @@ read_hex_buffer(char *filename) result_buffer = LDNS_MALLOC(ldns_buffer); ldns_buffer_new_frm_data(result_buffer, wire, wiresize); ldns_buffer_set_position(result_buffer, ldns_buffer_capacity(result_buffer)); - xfree(wire); + return result_buffer; } @@ -236,7 +218,7 @@ read_hex_pkt(char *filename) void dump_hex(const ldns_pkt *pkt, const char *filename) { - uint8_t *wire; + uint8_t *wire = NULL; size_t size, i; FILE *fp; ldns_status status; @@ -252,6 +234,7 @@ dump_hex(const ldns_pkt *pkt, const char *filename) if (status != LDNS_STATUS_OK) { error("Unable to convert packet: error code %u", status); + LDNS_FREE(wire); return; } @@ -273,4 +256,5 @@ dump_hex(const ldns_pkt *pkt, const char *filename) } fprintf(fp, "\n"); fclose(fp); + LDNS_FREE(wire); } diff --git a/error.c b/error.c index cf6788ffb36..2fc63e9b099 100644 --- a/error.c +++ b/error.c @@ -95,6 +95,35 @@ ldns_lookup_table ldns_error_str[] = { "DNSSEC signature will expire too soon" }, { LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED_WITHIN_MARGIN, "DNSSEC signature not incepted long enough" }, + { LDNS_STATUS_DANE_UNKNOWN_CERTIFICATE_USAGE, + "Unknown TLSA Certificate Usage" }, + { LDNS_STATUS_DANE_UNKNOWN_SELECTOR, "Unknown TLSA Selector" }, + { LDNS_STATUS_DANE_UNKNOWN_MATCHING_TYPE, + "Unknown TLSA Matching Type" }, + { LDNS_STATUS_DANE_UNKNOWN_PROTOCOL, + "Unknown protocol. Only IPv4 and IPv6 are understood" }, + { LDNS_STATUS_DANE_UNKNOWN_TRANSPORT, + "Unknown transport. Should be one of {tcp, udp, sctp}" }, + { LDNS_STATUS_DANE_MISSING_EXTRA_CERTS, /* Trust anchor assertion */ + "More than one certificate should be provided" }, + { LDNS_STATUS_DANE_EXTRA_CERTS_NOT_USED, /* Trust anchor assertion */ + "Non of the extra certificates is used to sign the first" }, + { LDNS_STATUS_DANE_OFFSET_OUT_OF_RANGE, /* Trust anchor assertion */ + "The offset was out of range" }, + { LDNS_STATUS_DANE_INSECURE, /* Unused by library */ + "The queried resource records were insecure" }, + { LDNS_STATUS_DANE_BOGUS, /* Unused by library */ + "The queried resource records were bogus" }, + { LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH, + "The TLSA record(s) " + "did not match with the server certificate (chain)" }, + { LDNS_STATUS_DANE_NON_CA_CERTIFICATE, + "The certificate was not a CA certificate" }, + { LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE, + "Could not PKIX validate" }, + { LDNS_STATUS_DANE_PKIX_NO_SELF_SIGNED_TRUST_ANCHOR, + "The validation path " + "did not end in a self-signed certificate" }, { 0, NULL } }; diff --git a/examples/Makefile.in b/examples/Makefile.in index 5344ee6739c..876a4e5ecf7 100644 --- a/examples/Makefile.in +++ b/examples/Makefile.in @@ -9,6 +9,7 @@ exec_prefix = @exec_prefix@ bindir = @bindir@ mandir = @mandir@ libtool = @libtool@ +datarootdir = @datarootdir@ CC = @CC@ CFLAGS = -I. -I${srcdir} @CFLAGS@ @@ -18,6 +19,7 @@ LIBNSL_LIBS = @LIBNSL_LIBS@ LIBSSL_CPPFLAGS = @LIBSSL_CPPFLAGS@ LIBSSL_LDFLAGS = @LIBSSL_LDFLAGS@ LIBSSL_LIBS = @LIBSSL_LIBS@ +LIBSSL_SSL_LIBS = @LIBSSL_SSL_LIBS@ LIBS = @LIBS@ RUNTIME_PATH = @RUNTIME_PATH@ LDNSDIR = @LDNSDIR@ @@ -70,7 +72,8 @@ MAIN_SOURCES = ldns-read-zone.c \ MAIN_SSL_SOURCES = ldns-signzone.c \ ldns-verify-zone.c \ ldns-revoke.c \ - ldns-nsec3-hash.c + ldns-nsec3-hash.c \ + ldns-dane.c OTHER_SOURCES = ldns-testpkts.c @@ -104,6 +107,18 @@ ldnsd.stc: ldnsd.o $(LINK_STATIC) $(LIBNSL_LDFLAGS) -o $@ $^ ; \ fi +ldns-dane.prg-ssl: ldns-dane.o + @if test ! -f $(@:.prg-ssl=) -o $< -nt $(@:.prg-ssl=); then \ + echo $(LINK) $(LIBNSL_LIBS) $(LIBSSL_LDFLAGS) $(LIBSSL_SSL_LIBS) -o $(@:.prg-ssl=) $^ ; \ + $(LINK) $(LIBNSL_LIBS) $(LIBSSL_LDFLAGS) $(LIBSSL_SSL_LIBS) -o $(@:.prg-ssl=) $^ ; \ + fi + +ldns-dane.stc-ssl: ldns-dane.o + @if test ! -f $@ -o $< -nt $@; then \ + echo $(LINK_STATIC) $(LIBNSL_LIBS) $(LIBSSL_LDFLAGS) $(LIBSSL_SSL_LIBS) -o $@ $^ ; \ + $(LINK_STATIC) $(LIBNSL_LIBS) $(LIBSSL_LDFLAGS) $(LIBSSL_SSL_LIBS) -o $@ $^ ; \ + fi + %.prg-ssl: %.o @if test ! -f $(@:.prg-ssl=) -o $< -nt $(@:.prg-ssl=); then \ echo $(LINK) $(LIBNSL_LIBS) $(LIBSSL_LDFLAGS) $(LIBSSL_LIBS) -o $(@:.prg-ssl=) $^ ; \ @@ -142,11 +157,12 @@ clean: realclean: clean rm -rf autom4te.cache/ - rm -f config.log config.status aclocal.m4 config.h.in configure Makefile - rm -f config.h + rm -f config.log config.status aclocal.m4 config.h.in configure + rm -f config.h ldns-dane.1 ldns-verify-zone.1 Makefile confclean: clean - rm -rf config.log config.status config.h Makefile + rm -rf config.log config.status + rm -f config.h ldns-dane.1 ldns-verify-zone.1 Makefile install: $(PROGRAMS) $(SSL_PROGRAMS) $(INSTALL) -d -m 755 $(DESTDIR)$(bindir) @@ -154,7 +170,10 @@ install: $(PROGRAMS) $(SSL_PROGRAMS) $(INSTALL) -d -m 755 $(DESTDIR)$(mandir)/man1 for i in $(PROGRAMS) $(SSL_PROGRAMS); do \ $(libtool) --tag=CC --mode=install ${INSTALL} -c $$i $(DESTDIR)$(bindir) ; \ - $(INSTALL) -c -m 644 $(srcdir)/$$i.1 $(DESTDIR)$(mandir)/man1/$$i.1 ; \ + if test -f $$i.1 ; \ + then $(INSTALL) -c -m 644 $$i.1 $(DESTDIR)$(mandir)/man1/$$i.1 ; \ + else $(INSTALL) -c -m 644 $(srcdir)/$$i.1 $(DESTDIR)$(mandir)/man1/$$i.1 ; \ + fi ; \ done exit 0 @@ -164,11 +183,17 @@ install-static: all-static $(INSTALL) -d -m 755 $(DESTDIR)$(mandir)/man1 for i in $(PROGRAMS); do \ $(libtool) --tag=CC --mode=install ${INSTALL} -c $$i.stc $(DESTDIR)$(bindir) ; \ - $(INSTALL) -c -m 644 $(srcdir)/$$i.1 $(DESTDIR)$(mandir)/man1/$$i.1 ; \ + if test -f $$i.1 ; \ + then $(INSTALL) -c -m 644 $$i.1 $(DESTDIR)$(mandir)/man1/$$i.1 ; \ + else $(INSTALL) -c -m 644 $(srcdir)/$$i.1 $(DESTDIR)$(mandir)/man1/$$i.1 ; \ + fi ; \ done for i in $(SSL_PROGRAMS); do \ $(libtool) --tag=CC --mode=install ${INSTALL} -c $$i.stc-ssl $(DESTDIR)$(bindir) ; \ - $(INSTALL) -c -m 644 $(srcdir)/$$i.1 $(DESTDIR)$(mandir)/man1/$$i.1 ; \ + if test -f $$i.1 ; \ + then $(INSTALL) -c -m 644 $$i.1 $(DESTDIR)$(mandir)/man1/$$i.1 ; \ + else $(INSTALL) -c -m 644 $(srcdir)/$$i.1 $(DESTDIR)$(mandir)/man1/$$i.1 ; \ + fi ; \ done exit 0 diff --git a/examples/config.h.in b/examples/config.h.in index dad78b17a22..1f548a17c8d 100644 --- a/examples/config.h.in +++ b/examples/config.h.in @@ -9,6 +9,12 @@ /* Define to 1 if you have the header file. */ #undef HAVE_CTYPE_H +/* Is a CAFILE given at configure time */ +#undef HAVE_DANE_CA_FILE + +/* Is a CAPATH given at configure time */ +#undef HAVE_DANE_CA_PATH + /* Define to 1 if you have the declaration of `in6addr_any', and to 0 if you don't. */ #undef HAVE_DECL_IN6ADDR_ANY @@ -151,6 +157,15 @@ /* Define to 1 if you have the header file. */ #undef HAVE_WS2TCPIP_H +/* Is a CAFILE given at configure time */ +#undef LDNS_DANE_CA_FILE + +/* Is a CAPATH given at configure time */ +#undef LDNS_DANE_CA_PATH + +/* Default trust anchor file */ +#undef LDNS_TRUST_ANCHOR_FILE + /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT diff --git a/examples/configure b/examples/configure index 46dc9988c1f..66c1e718f9e 100755 --- a/examples/configure +++ b/examples/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.68 for ldns 1.6.13. +# Generated by GNU Autoconf 2.68 for ldns 1.6.16. # # Report bugs to . # @@ -560,8 +560,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='ldns' PACKAGE_TARNAME='libdns' -PACKAGE_VERSION='1.6.13' -PACKAGE_STRING='ldns 1.6.13' +PACKAGE_VERSION='1.6.16' +PACKAGE_STRING='ldns 1.6.16' PACKAGE_BUGREPORT='libdns@nlnetlabs.nl' PACKAGE_URL='' @@ -604,7 +604,11 @@ ac_includes_default="\ ac_subst_vars='LTLIBOBJS LIBOBJS +DEFAULT_CAPATH +DEFAULT_CAFILE +LDNS_TRUST_ANCHOR_FILE LDNSDIR +LIBSSL_SSL_LIBS LIBSSL_LIBS LIBSSL_LDFLAGS LIBSSL_CPPFLAGS @@ -670,6 +674,9 @@ enable_sha2 enable_gost enable_ecdsa with_ldns +with_trust_anchor +with_ca_file +with_ca_path ' ac_precious_vars='build_alias host_alias @@ -1222,7 +1229,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 ldns 1.6.13 to adapt to many kinds of systems. +\`configure' configures ldns 1.6.16 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1283,7 +1290,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of ldns 1.6.13:";; + short | recursive ) echo "Configuration of ldns 1.6.16:";; esac cat <<\_ACEOF @@ -1305,6 +1312,12 @@ Optional Packages: --with-ldns=PATH specify prefix of path of ldns library to use + --with-trust-anchor=KEYFILE + Default location of the trust anchor file for drill + and ldns-dane. [default=SYSCONFDIR/unbound/root.key] + --with-ca-file=CAFILE File containing CA certificates for ldns-dane + --with-ca-path=CAPATH Directory containing CA certificate files for + ldns-dane Some influential environment variables: CC C compiler command @@ -1382,7 +1395,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -ldns configure 1.6.13 +ldns configure 1.6.16 generated by GNU Autoconf 2.68 Copyright (C) 2010 Free Software Foundation, Inc. @@ -1851,7 +1864,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 ldns $as_me 1.6.13, which was +It was created by ldns $as_me 1.6.16, which was generated by GNU Autoconf 2.68. Invocation command line was $ $0 $@ @@ -5258,7 +5271,10 @@ done +if test "x$HAVE_SSL" = "xyes"; then +LIBSSL_SSL_LIBS="$LIBSSL_LIBS -lssl" +fi CPPFLAGS="$tmp_CPPFLAGS" LDFLAGS="$tmp_LDFLAGS" LIBS="$tmp_LIBS" @@ -5858,7 +5874,6 @@ else as_fn_error $? "Can't find ldns library" "$LINENO" 5 - fi fi @@ -5866,9 +5881,93 @@ fi +# Check whether --with-trust-anchor was given. +if test "${with_trust_anchor+set}" = set; then : + withval=$with_trust_anchor; + LDNS_TRUST_ANCHOR_FILE="$withval" + +else + + if test "x$LDNS_TRUST_ANCHOR_FILE" = "x"; then + if test "x$sysconfdir" = 'x${prefix}/etc' ; then + if test "x$prefix" = 'xNONE' ; then + LDNS_TRUST_ANCHOR_FILE="/etc/unbound/root.key" + else + LDNS_TRUST_ANCHOR_FILE="${prefix}/etc/unbound/root.key" + fi + else + LDNS_TRUST_ANCHOR_FILE="${sysconfdir}/unbound/root.key" + fi + fi + +fi -ac_config_files="$ac_config_files Makefile" +cat >>confdefs.h <<_ACEOF +#define LDNS_TRUST_ANCHOR_FILE "$LDNS_TRUST_ANCHOR_FILE" +_ACEOF + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: Default trust anchor: $LDNS_TRUST_ANCHOR_FILE" >&5 +$as_echo "$as_me: Default trust anchor: $LDNS_TRUST_ANCHOR_FILE" >&6;} + + +# Check whether --with-ca-file was given. +if test "${with_ca_file+set}" = set; then : + withval=$with_ca_file; + +$as_echo "#define HAVE_DANE_CA_FILE 1" >>confdefs.h + + +cat >>confdefs.h <<_ACEOF +#define LDNS_DANE_CA_FILE "$withval" +_ACEOF + + { $as_echo "$as_me:${as_lineno-$LINENO}: Using CAfile: $withval" >&5 +$as_echo "$as_me: Using CAfile: $withval" >&6;} + DEFAULT_CAFILE="Default is $withval" + + +else + + +$as_echo "#define HAVE_DANE_CA_FILE 0" >>confdefs.h + + + +fi + + + +# Check whether --with-ca-path was given. +if test "${with_ca_path+set}" = set; then : + withval=$with_ca_path; + +$as_echo "#define HAVE_DANE_CA_PATH 1" >>confdefs.h + + +cat >>confdefs.h <<_ACEOF +#define LDNS_DANE_CA_PATH "$withval" +_ACEOF + + { $as_echo "$as_me:${as_lineno-$LINENO}: Using CApath: $withval" >&5 +$as_echo "$as_me: Using CApath: $withval" >&6;} + DEFAULT_CAPATH="Default is $withval" + + +else + + +$as_echo "#define HAVE_DANE_CA_PATH 0" >>confdefs.h + + + +fi + + + + +ac_config_files="$ac_config_files Makefile ldns-dane.1 ldns-verify-zone.1" ac_config_headers="$ac_config_headers config.h" @@ -6390,7 +6489,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 ldns $as_me 1.6.13, which was +This file was extended by ldns $as_me 1.6.16, which was generated by GNU Autoconf 2.68. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -6452,7 +6551,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="\\ -ldns config.status 1.6.13 +ldns config.status 1.6.16 configured by $0, generated by GNU Autoconf 2.68, with options \\"\$ac_cs_config\\" @@ -6574,6 +6673,8 @@ for ac_config_target in $ac_config_targets do case $ac_config_target in "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "ldns-dane.1") CONFIG_FILES="$CONFIG_FILES ldns-dane.1" ;; + "ldns-verify-zone.1") CONFIG_FILES="$CONFIG_FILES ldns-verify-zone.1" ;; "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; diff --git a/examples/configure.ac b/examples/configure.ac index 67345dac7cd..9bd74ff41aa 100644 --- a/examples/configure.ac +++ b/examples/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.56) -AC_INIT(ldns, 1.6.13, libdns@nlnetlabs.nl,libdns) +AC_INIT(ldns, 1.6.16, libdns@nlnetlabs.nl,libdns) AC_CONFIG_SRCDIR([ldns-read-zone.c]) sinclude(../acx_nlnetlabs.m4) @@ -136,7 +136,9 @@ ACX_WITH_SSL_OPTIONAL AC_SUBST(LIBSSL_CPPFLAGS) AC_SUBST(LIBSSL_LDFLAGS) AC_SUBST(LIBSSL_LIBS) - +if test "x$HAVE_SSL" = "xyes"; then +AC_SUBST(LIBSSL_SSL_LIBS, ["$LIBSSL_LIBS -lssl"]) +fi CPPFLAGS="$tmp_CPPFLAGS" LDFLAGS="$tmp_LDFLAGS" LIBS="$tmp_LIBS" @@ -313,13 +315,51 @@ if test -f $ldns_dev_dir/ldns/util.h && \ else AC_MSG_RESULT([no]) AC_CHECK_LIB(ldns, ldns_rr_new,, [ - AC_MSG_ERROR([Can't find ldns library]) + AC_MSG_ERROR([Can't find ldns library])dnl' ] ) fi AC_SUBST(LDNSDIR) +AC_ARG_WITH(trust-anchor, AC_HELP_STRING([--with-trust-anchor=KEYFILE], [Default location of the trust anchor file for drill and ldns-dane. [default=SYSCONFDIR/unbound/root.key]]), [ + LDNS_TRUST_ANCHOR_FILE="$withval" +],[ + if test "x$LDNS_TRUST_ANCHOR_FILE" = "x"; then + if test "x$sysconfdir" = 'x${prefix}/etc' ; then + if test "x$prefix" = 'xNONE' ; then + LDNS_TRUST_ANCHOR_FILE="/etc/unbound/root.key" + else + LDNS_TRUST_ANCHOR_FILE="${prefix}/etc/unbound/root.key" + fi + else + LDNS_TRUST_ANCHOR_FILE="${sysconfdir}/unbound/root.key" + fi + fi +]) +AC_DEFINE_UNQUOTED([LDNS_TRUST_ANCHOR_FILE], ["$LDNS_TRUST_ANCHOR_FILE"], [Default trust anchor file]) +AC_SUBST(LDNS_TRUST_ANCHOR_FILE) +AC_MSG_NOTICE([Default trust anchor: $LDNS_TRUST_ANCHOR_FILE]) + +AC_ARG_WITH(ca-file, AC_HELP_STRING([--with-ca-file=CAFILE], [File containing CA certificates for ldns-dane]), [ + AC_DEFINE([HAVE_DANE_CA_FILE], [1], [Is a CAFILE given at configure time]) + AC_DEFINE_UNQUOTED([LDNS_DANE_CA_FILE], ["$withval"], [Is a CAFILE given at configure time]) + AC_MSG_NOTICE([Using CAfile: $withval]) + AC_SUBST(DEFAULT_CAFILE, ["Default is $withval"]) +],[ + AC_DEFINE([HAVE_DANE_CA_FILE], [0], [Is a CAFILE given at configure time]) + AC_SUBST(DEFAULT_CAFILE, []) +]) + +AC_ARG_WITH(ca-path, AC_HELP_STRING([--with-ca-path=CAPATH], [Directory containing CA certificate files for ldns-dane]), [ + AC_DEFINE([HAVE_DANE_CA_PATH], [1], [Is a CAPATH given at configure time]) + AC_DEFINE_UNQUOTED([LDNS_DANE_CA_PATH], ["$withval"], [Is a CAPATH given at configure time]) + AC_MSG_NOTICE([Using CApath: $withval]) + AC_SUBST(DEFAULT_CAPATH, ["Default is $withval"]) +],[ + AC_DEFINE([HAVE_DANE_CA_PATH], [0], [Is a CAPATH given at configure time]) + AC_SUBST(DEFAULT_CAPATH, []) +]) AH_BOTTOM([ @@ -416,6 +456,6 @@ extern int optind, opterr; #endif ]) -AC_CONFIG_FILES([Makefile]) +AC_CONFIG_FILES([Makefile ldns-dane.1 ldns-verify-zone.1]) AC_CONFIG_HEADER([config.h]) AC_OUTPUT diff --git a/examples/ldns-dane.1.in b/examples/ldns-dane.1.in new file mode 100644 index 00000000000..8f05d7f681a --- /dev/null +++ b/examples/ldns-dane.1.in @@ -0,0 +1,179 @@ +.TH ldns-dane 1 "17 September 2012" +.SH NAME +ldns-dane \- verify or create TLS authentication with DANE (RFC6698) +.SH SYNOPSIS +.PD 0 +.B ldns-dane +.IR [OPTIONS] +.IR verify +.IR name +.IR port +.PP +.B ldns-dane +.IR [OPTIONS] +.IR -t +.IR tlsafile +.IR verify + +.B ldns-dane +.IR [OPTIONS] +.IR name +.IR port +.IR create +.PP + [ +.IR Certificate-usage +[ +.IR Selector +[ +.IR Matching-type +] ] ] + +.B ldns-dane +.IR -h +.PP +.B ldns-dane +.IR -v +.PD 1 + +.SH DESCRIPTION + +In the first form: +A TLS connection to \fIname\fR:\fIport\fR is established. +The TLSA resource record(s) for \fIname\fR are used to authenticate +the connection. + +In the second form: +The TLSA record(s) are read from \fItlsafile\fR and used to authenticate +the TLS service they reference. + +In the third form: +A TLS connection to \fIname\fR:\fIport\fR is established and used to +create the TLSA resource record(s) that would authenticate the connection. +The parameters for TLSA rr creation are: + +.PD 0 +.I Certificate-usage\fR: +.RS +.IP 0 +CA constraint +.IP 1 +Service certificate constraint +.IP 2 +Trust anchor assertion +.IP 3 +Domain-issued certificate (default) +.RE + +.I Selector\fR: +.RS +.IP 0 +Full certificate (default) +.IP 1 +SubjectPublicKeyInfo +.RE + +.I Matching-type\fR: +.RS +.IP 0 +No hash used +.IP 1 +SHA-256 (default) +.IP 2 +SHA-512 +.RE +.PD 1 + +In stead of numbers the first few letters of the value may be used. +Except for the hash algorithm name, where the full name must be specified. + +.SH OPTIONS +.IP -4 +TLS connect IPv4 only +.IP -6 +TLS connect IPv6 only +.IP "-a \fIaddress\fR" +Don't try to resolve \fIname\fR, but connect to \fIaddress\fR instead. + +This option may be given more than once. +.IP -b +print "\fIname\fR\. TYPE52 \\# \fIsize\fR \fIhexdata\fR" form instead +of TLSA presentation format. +.IP "-c \fIcertfile\fR" +Do not TLS connect to \fIname\fR:\fIport\fR, but authenticate (or make +TLSA records) for the certificate (chain) in \fIcertfile\fR instead. +.IP -d +Assume DNSSEC validity even when the TLSA records were acquired insecure +or were bogus. +.IP "-f \fICAfile\fR" +Use CAfile to validate. @DEFAULT_CAFILE@ +.IP -h +Print short usage help +.IP -i +Interact after connecting. +.IP "-k \fIkeyfile\fR" +Specify a file that contains a trusted DNSKEY or DS rr. +Key(s) are used when chasing signatures (i.e. \fI-S\fR is given). + +This option may be given more than once. + +Alternatively, if \fB-k\fR is not specified, and a default trust anchor +(@LDNS_TRUST_ANCHOR_FILE@) exists and contains a valid DNSKEY or DS record, +it will be used as the trust anchor. +.IP -n +Do \fBnot\fR verify server name in certificate. +.IP "-o \fIoffset\fR" +When creating a "Trust anchor assertion" TLSA resource record, +select the \fIoffset\fRth certificate offset from the end +of the validation chain. 0 means the last certificate, 1 the one but last, +2 the second but last, etc. + +When \fIoffset\fR is -1 (the default), the last certificate +is used (like with 0) that MUST be self-signed. This can help to make +sure that the intended (self signed) trust anchor is actually present +in the server certificate chain (which is a DANE requirement). +.IP "-p \fICApath\fR" +Use certificates in the \fICApath\fR directory to validate. @DEFAULT_CAPATH@ +.IP -s +When creating TLSA resource records with the "CA Constraint" and the +"Service Certificate Constraint" certificate usage, do not validate and +assume PKIX is valid. + +For "CA Constraint" this means that verification should end with a +self-signed certificate. +.IP -S +Chase signature(s) to a known key. + +Without this option, the local network is trusted to provide +a DNSSEC resolver (i.e. AD bit is checked). +.IP "-t \fItlsafile\fR" +Read TLSA record(s) from \fItlsafile\fR. When \fIname\fR and \fIport\fR +are also given, only TLSA records that match the \fIname\fR, \fIport\fR and +\fItransport\fR are used. Otherwise the owner name of the TLSA record(s) +will be used to determine \fIname\fR, \fIport\fR and \fItransport\fR. +.IP -u +Use UDP transport instead of TCP. +.IP -v +Show version and exit. + +.SH "FILES" +.TP +@LDNS_TRUST_ANCHOR_FILE@ +The file from which trusted keys are loaded for signature chasing, +when no \fB-k\fR option is given. + +.SH "SEE ALSO" +.LP +unbound-anchor(8) + +.SH AUTHOR +Written by the ldns team as an example for ldns usage. + +.SH REPORTING BUGS +Report bugs to \fIldns-team@nlnetlabs.nl\fR. + +.SH COPYRIGHT +Copyright (C) 2012 NLnet Labs. This is free software. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. + diff --git a/examples/ldns-dane.c b/examples/ldns-dane.c new file mode 100644 index 00000000000..3ae35881329 --- /dev/null +++ b/examples/ldns-dane.c @@ -0,0 +1,1722 @@ +/* + * Verify or create TLS authentication with DANE (RFC6698) + * + * (c) NLnetLabs 2012 + * + * See the file LICENSE for the license. + * + * wish list: + * - nicer reporting (tracing of evaluation process) + * - verbosity levels + * - STARTTLS support + */ + +#include "config.h" +#include +#include +#include +#include +#include + +#include + +#include + +#ifdef HAVE_SSL +#include +#include +#include + +#ifndef IPPROTO_SCTP +#define IPPROTO_SCTP 132 +#endif + +#define LDNS_ERR(code, msg) do { if (code != LDNS_STATUS_OK) \ + ldns_err(msg, code); } while (false) +#define MEMERR(msg) do { fprintf(stderr, "memory error in %s\n", msg); \ + exit(EXIT_FAILURE); } while (false) +#define BUFSIZE 16384 + +/* int verbosity = 3; */ + +void +print_usage(const char* progname) +{ + printf("Usage: %s [OPTIONS] verify \n", progname); + printf(" or: %s [OPTIONS] -t verify\n", progname); + printf("\n\tVerify the TLS connection at : or" + "\n\tuse TLSA record(s) from to verify the\n" + "\tTLS service they reference.\n"); + printf("\n or: %s [OPTIONS] create [ " + "[ []]]\n", progname); + printf("\n\tUse the TLS connection(s) to " + "to create the TLSA\n\t" + "resource record(s) that would " + "authenticate the connection.\n"); + printf("\n\t" + "\t\t0: CA constraint\n" + "\t\t\t1: Service certificate constraint\n" + "\t\t\t2: Trust anchor assertion\n" + "\t\t\t3: Domain-issued certificate (default)\n"); + printf("\n\t" + "\t0: Full certificate (default)\n" + "\t\t\t1: SubjectPublicKeyInfo\n"); + printf("\n\t" + "\t\t0: No hash used\n" + "\t\t\t1: SHA-256 (default)\n" + "\t\t\t2: SHA-512\n"); + + printf("OPTIONS:\n"); + printf("\t-h\t\tshow this text\n"); + printf("\t-4\t\tTLS connect IPv4 only\n"); + printf("\t-6\t\tTLS connect IPv6 only\n"); + printf("\t-a
    \t" + "don't resolve , but connect to
    (es)\n"); + printf("\t-b\t\t" + "print \". TYPE52 \\# \" form\n" + ); + printf("\t-c \t" + "verify or create TLSA records for the\n" + "\t\t\tcertificate (chain) in \n" + ); + printf("\t-d\t\tassume DNSSEC validity even when insecure or bogus\n"); + printf("\t-f \tuse CAfile to validate\n"); +#if HAVE_DANE_CA_FILE + printf("\t\t\tDefault is %s\n", LDNS_DANE_CA_FILE); +#endif + printf("\t-i\t\tinteract after connecting\n"); + printf("\t-k \t" + "use DNSKEY/DS rr(s) in to validate TLSAs\n" + "\t\t\twhen signature chasing (i.e. -S)\n" + ); + printf("\t\t\tDefault is %s\n", LDNS_TRUST_ANCHOR_FILE); + printf("\t-n\t\tdo *not* verify server name in certificate\n"); + printf("\t-o \t" + "select th certificate from the end of\n" + "\t\t\tthe validation chain. -1 means self-signed at end\n" + ); + printf("\t-p \t" + "use certificates in the directory to validate\n" + ); +#if HAVE_DANE_CA_PATH + printf("\t\t\tDefaults is %s\n", LDNS_DANE_CA_PATH); +#endif + printf("\t-s\t\tassume PKIX validity\n"); + printf("\t-S\t\tChase signature(s) to a known key\n"); + printf("\t-t \tdo not use DNS, " + "but read TLSA record(s) from \n" + ); + printf("\t-u\t\tuse UDP transport instead of TCP\n"); + printf("\t-v\t\tshow version and exit\n"); + /* printf("\t-V [0-5]\tset verbosity level (defaul 3)\n"); */ + exit(EXIT_SUCCESS); +} + +int +dane_int_within_range(const char* arg, int max, const char* name) +{ + char* endptr; /* utility var for strtol usage */ + int val = strtol(arg, &endptr, 10); + + if ((val < 0 || val > max) + || (errno != 0 && val == 0) /* out of range */ + || endptr == arg /* no digits */ + || *endptr != '\0' /* more chars */ + ) { + fprintf(stderr, "<%s> should be in range [0-%d]\n", name, max); + exit(EXIT_FAILURE); + } + return val; +} + +struct dane_param_choice_struct { + const char* name; + int number; +}; +typedef struct dane_param_choice_struct dane_param_choice; + +dane_param_choice dane_certificate_usage_table[] = { + { "CA constraint" , 0 }, + { "CA-constraint" , 0 }, + { "Service certificate constraint" , 1 }, + { "Service-certificate-constraint" , 1 }, + { "Trust anchor assertion" , 2 }, + { "Trust-anchor-assertion" , 2 }, + { "anchor" , 2 }, + { "Domain-issued certificate" , 3 }, + { "Domain-issued-certificate" , 3 }, + { NULL, -1 } +}; + +dane_param_choice dane_selector_table[] = { + { "Full certificate" , 0 }, + { "Full-certificate" , 0 }, + { "certificate" , 0 }, + { "SubjectPublicKeyInfo", 1 }, + { "PublicKey" , 1 }, + { "pubkey" , 1 }, + { "key" , 1 }, + { NULL, -1 } +}; + +int +dane_int_within_range_table(const char* arg, int max, const char* name, + dane_param_choice table[]) +{ + dane_param_choice* t; + + if (*arg) { + for (t = table; t->name; t++) { + if (strncasecmp(arg, t->name, strlen(arg)) == 0) { + return t->number; + } + } + } + return dane_int_within_range(arg, max, name); +} + +void +ssl_err(const char* s) +{ + fprintf(stderr, "error: %s\n", s); + ERR_print_errors_fp(stderr); + exit(EXIT_FAILURE); +} + +void +ldns_err(const char* s, ldns_status err) +{ + if (err == LDNS_STATUS_SSL_ERR) { + ssl_err(s); + } else { + fprintf(stderr, "%s: %s\n", s, ldns_get_errorstr_by_id(err)); + exit(EXIT_FAILURE); + } +} + +ldns_status +ssl_connect_and_get_cert_chain( + X509** cert, STACK_OF(X509)** extra_certs, + SSL* ssl, ldns_rdf* address, uint16_t port, + ldns_dane_transport transport) +{ + struct sockaddr_storage *a = NULL; + size_t a_len = 0; + int sock; + int r; + + assert(cert != NULL); + assert(extra_certs != NULL); + + a = ldns_rdf2native_sockaddr_storage(address, port, &a_len); + switch (transport) { + case LDNS_DANE_TRANSPORT_TCP: + + sock = socket((int)((struct sockaddr*)a)->sa_family, + SOCK_STREAM, IPPROTO_TCP); + break; + + case LDNS_DANE_TRANSPORT_UDP: + + sock = socket((int)((struct sockaddr*)a)->sa_family, + SOCK_DGRAM, IPPROTO_UDP); + break; + + case LDNS_DANE_TRANSPORT_SCTP: + + sock = socket((int)((struct sockaddr*)a)->sa_family, + SOCK_STREAM, IPPROTO_SCTP); + break; + + default: + LDNS_FREE(a); + return LDNS_STATUS_DANE_UNKNOWN_TRANSPORT; + } + if (sock == -1) { + LDNS_FREE(a); + return LDNS_STATUS_NETWORK_ERR; + } + if (connect(sock, (struct sockaddr*)a, (socklen_t)a_len) == -1) { + LDNS_FREE(a); + return LDNS_STATUS_NETWORK_ERR; + } + LDNS_FREE(a); + if (! SSL_clear(ssl)) { + close(sock); + fprintf(stderr, "SSL_clear\n"); + return LDNS_STATUS_SSL_ERR; + } + SSL_set_connect_state(ssl); + (void) SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); + if (! SSL_set_fd(ssl, sock)) { + close(sock); + fprintf(stderr, "SSL_set_fd\n"); + return LDNS_STATUS_SSL_ERR; + } + for (;;) { + ERR_clear_error(); + if ((r = SSL_do_handshake(ssl)) == 1) { + break; + } + r = SSL_get_error(ssl, r); + if (r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE) { + fprintf(stderr, "handshaking SSL_get_error: %d\n", r); + return LDNS_STATUS_SSL_ERR; + } + } + *cert = SSL_get_peer_certificate(ssl); + *extra_certs = SSL_get_peer_cert_chain(ssl); + + return LDNS_STATUS_OK; +} + + +void +ssl_interact(SSL* ssl) +{ + fd_set rfds; + int maxfd; + int sock; + int r; + + char buf[BUFSIZE]; + char* bufptr; + int to_write; + int written; + + sock = SSL_get_fd(ssl); + if (sock == -1) { + return; + } + maxfd = (STDIN_FILENO > sock ? STDIN_FILENO : sock) + 1; + for (;;) { +#ifndef S_SPLINT_S + FD_ZERO(&rfds); +#endif /* splint */ + FD_SET(sock, &rfds); + FD_SET(STDIN_FILENO, &rfds); + + r = select(maxfd, &rfds, NULL, NULL, NULL); + if (r == -1) { + perror("select"); + break; + } + if (FD_ISSET(sock, &rfds)) { + to_write = SSL_read(ssl, buf, BUFSIZE); + if (to_write <= 0) { + r = SSL_get_error(ssl, to_write); + if (r != SSL_ERROR_ZERO_RETURN) { + fprintf(stderr, + "reading SSL_get_error:" + " %d\n", r); + } + break; + } + bufptr = buf; + while (to_write > 0) { + written = (int) fwrite(bufptr, 1, + (size_t) to_write, stdout); + if (written == 0) { + perror("fwrite"); + break; + } + to_write -= written; + bufptr += written; + } + } /* if (FD_ISSET(sock, &rfds)) */ + + if (FD_ISSET(STDIN_FILENO, &rfds)) { + to_write = (int) read(STDIN_FILENO, buf, BUFSIZE - 1); + if (to_write <= 0) { + if (to_write == -1) { + perror("read"); + } + break; + } + if (buf[to_write - 1] == '\n') { + buf[to_write - 1] = '\r'; + buf[to_write ] = '\n'; + to_write += 1; + } + bufptr = buf; + while (to_write > 0) { + written = SSL_write(ssl, bufptr, to_write); + if (written <= 0) { + r = SSL_get_error(ssl, to_write); + if (r != SSL_ERROR_ZERO_RETURN) { + fprintf(stderr, + "writing SSL_get_error" + ": %d\n", r); + } + break; + } + to_write -= written; + bufptr += written; + } + } /* if (FD_ISSET(STDIN_FILENO, &rfds)) */ + + } /* for (;;) */ +} + + +void +ssl_shutdown(SSL* ssl) +{ + while (SSL_shutdown(ssl) == 0); +} + +ldns_rr_list* +rr_list_filter_rr_type(ldns_rr_list* l, ldns_rr_type t) +{ + size_t i; + ldns_rr* rr; + ldns_rr_list* r = ldns_rr_list_new(); + + if (r == NULL) { + return r; + } + for (i = 0; i < ldns_rr_list_rr_count(l); i++) { + rr = ldns_rr_list_rr(l, i); + if (ldns_rr_get_type(rr) == t) { + if (! ldns_rr_list_push_rr(r, rr)) { + ldns_rr_list_free(r); + return NULL; + } + } + } + return r; +} + + +/* Return a copy of the list of tlsa records where the usage types + * "CA constraint" are replaced with "Trust anchor assertion" and the usage + * types "Service certificate constraint" are replaced with + * "Domain-issued certificate". + * + * This to check what would happen if PKIX validation was successfull always. + */ +ldns_rr_list* +dane_no_pkix_transform(const ldns_rr_list* tlas) +{ + size_t i; + ldns_rr* rr; + ldns_rr* new_rr; + ldns_rdf* rdf; + ldns_rr_list* r = ldns_rr_list_new(); + + if (r == NULL) { + return r; + } + for (i = 0; i < ldns_rr_list_rr_count(tlas); i++) { + rr = ldns_rr_list_rr(tlas, i); + if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_TLSA) { + + new_rr = ldns_rr_clone(rr); + if (!new_rr) { + ldns_rr_list_deep_free(r); + return NULL; + } + switch(ldns_rdf2native_int8(ldns_rr_rdf(new_rr, 0))) { + + case LDNS_TLSA_USAGE_CA_CONSTRAINT: + + rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, + (uint8_t) LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION); + if (! rdf) { + ldns_rr_free(new_rr); + ldns_rr_list_deep_free(r); + return NULL; + } + (void) ldns_rr_set_rdf(new_rr, rdf, 0); + break; + + + case LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT: + + rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, + (uint8_t) LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE); + if (! rdf) { + ldns_rr_free(new_rr); + ldns_rr_list_deep_free(r); + return NULL; + } + (void) ldns_rr_set_rdf(new_rr, rdf, 0); + break; + + + default: + break; + } + if (! ldns_rr_list_push_rr(r, new_rr)) { + ldns_rr_free(new_rr); + ldns_rr_list_deep_free(r); + return NULL; + } + } + } + return r; +} + +void +print_rr_as_TYPEXXX(FILE* out, ldns_rr* rr) +{ + size_t i, sz; + ldns_status s; + ldns_buffer* buf = ldns_buffer_new(LDNS_MAX_PACKETLEN); + char* str; + + ldns_buffer_clear(buf); + s = ldns_rdf2buffer_str_dname(buf, ldns_rr_owner(rr)); + LDNS_ERR(s, "could not ldns_rdf2buffer_str_dname"); + ldns_buffer_printf(buf, "\t%d", ldns_rr_ttl(rr)); + ldns_buffer_printf(buf, "\t"); + s = ldns_rr_class2buffer_str(buf, ldns_rr_get_class(rr)); + LDNS_ERR(s, "could not ldns_rr_class2buffer_str"); + ldns_buffer_printf(buf, "\tTYPE%d", ldns_rr_get_type(rr)); + sz = 0; + for (i = 0; i < ldns_rr_rd_count(rr); i++) { + sz += ldns_rdf_size(ldns_rr_rdf(rr, i)); + } + ldns_buffer_printf(buf, "\t\\# %d ", sz); + for (i = 0; i < ldns_rr_rd_count(rr); i++) { + s = ldns_rdf2buffer_str_hex(buf, ldns_rr_rdf(rr, i)); + LDNS_ERR(s, "could not ldns_rdf2buffer_str_hex"); + } + str = ldns_buffer_export2str(buf); + ldns_buffer_free(buf); + fprintf(out, "%s\n", str); + LDNS_FREE(str); +} + +void +print_rr_list_as_TYPEXXX(FILE* out, ldns_rr_list* l) +{ + size_t i; + + for (i = 0; i < ldns_rr_list_rr_count(l); i++) { + print_rr_as_TYPEXXX(out, ldns_rr_list_rr(l, i)); + } +} + +ldns_status +read_key_file(const char *filename, ldns_rr_list *keys) +{ + ldns_status status = LDNS_STATUS_ERR; + ldns_rr *rr; + FILE *fp; + uint32_t my_ttl = 0; + ldns_rdf *my_origin = NULL; + ldns_rdf *my_prev = NULL; + int line_nr; + + if (!(fp = fopen(filename, "r"))) { + return LDNS_STATUS_FILE_ERR; + } + while (!feof(fp)) { + status = ldns_rr_new_frm_fp_l(&rr, fp, &my_ttl, &my_origin, + &my_prev, &line_nr); + + if (status == LDNS_STATUS_OK) { + + if ( ldns_rr_get_type(rr) == LDNS_RR_TYPE_DS + || ldns_rr_get_type(rr) == LDNS_RR_TYPE_DNSKEY) + + ldns_rr_list_push_rr(keys, rr); + + } else if ( status == LDNS_STATUS_SYNTAX_EMPTY + || status == LDNS_STATUS_SYNTAX_TTL + || status == LDNS_STATUS_SYNTAX_ORIGIN + || status == LDNS_STATUS_SYNTAX_INCLUDE) + + status = LDNS_STATUS_OK; + else + break; + } + fclose(fp); + return status; +} + + +ldns_status +dane_setup_resolver(ldns_resolver** res, + ldns_rr_list* keys, bool dnssec_off) +{ + ldns_status s; + + assert(res != NULL); + + s = ldns_resolver_new_frm_file(res, NULL); + if (s == LDNS_STATUS_OK) { + ldns_resolver_set_dnssec(*res, ! dnssec_off); + + if (keys && ldns_rr_list_rr_count(keys) > 0) { + /* anchors must trigger signature chasing */ + ldns_resolver_set_dnssec_anchors(*res, keys); + ldns_resolver_set_dnssec_cd(*res, true); + } + } + return s; +} + + +ldns_status +dane_query(ldns_rr_list** rrs, ldns_resolver* r, + ldns_rdf *name, ldns_rr_type t, ldns_rr_class c, + bool insecure_is_ok) +{ + ldns_pkt* p = NULL; + ldns_rr_list* keys = NULL; + ldns_rr_list* rrsigs = NULL; + ldns_rdf* signame = NULL; + ldns_status s; + + assert(rrs != NULL); + + p = ldns_resolver_query(r, name, t, c, LDNS_RD); + if (! p) { + return LDNS_STATUS_MEM_ERR; + } + *rrs = ldns_pkt_rr_list_by_type(p, t, LDNS_SECTION_ANSWER); + + if (! ldns_resolver_dnssec(r)) { /* DNSSEC explicitely disabled, + anything goes */ + ldns_pkt_free(p); + return LDNS_STATUS_OK; + } + if (ldns_rr_list_rr_count(*rrs) == 0) { /* assert(*rrs == NULL) */ + + if (ldns_pkt_get_rcode(p) == LDNS_RCODE_SERVFAIL) { + + ldns_pkt_free(p); + return LDNS_STATUS_DANE_BOGUS; + } else { + ldns_pkt_free(p); + return LDNS_STATUS_OK; + } + } + /* We have answers and we have dnssec. */ + + if (! ldns_pkt_cd(p)) { /* we act as stub resolver (no sigchase) */ + + if (! ldns_pkt_ad(p)) { /* Not secure */ + + goto insecure; + } + ldns_pkt_free(p); + return LDNS_STATUS_OK; + } + + /* sigchase */ + + /* TODO: handle cname reference check */ + + rrsigs = ldns_pkt_rr_list_by_type(p, + LDNS_RR_TYPE_RRSIG, + LDNS_SECTION_ANSWER); + + if (! rrsigs || ldns_rr_list_rr_count(rrsigs) == 0) { + goto insecure; + } + + signame = ldns_rr_rrsig_signame(ldns_rr_list_rr(rrsigs, 0)); + if (! signame) { + s = LDNS_STATUS_ERR; + goto error; + } + /* First try with the keys we already have */ + s = ldns_verify(*rrs, rrsigs, ldns_resolver_dnssec_anchors(r), NULL); + if (s == LDNS_STATUS_OK) { + goto cleanup; + } + /* Fetch the necessary keys and recheck */ + keys = ldns_fetch_valid_domain_keys(r, signame, + ldns_resolver_dnssec_anchors(r), &s); + + if (s != LDNS_STATUS_OK) { + goto error; + } + if (ldns_rr_list_rr_count(keys) == 0) { /* An insecure island */ + goto insecure; + } + s = ldns_verify(*rrs, rrsigs, keys, NULL); + switch (s) { + case LDNS_STATUS_CRYPTO_BOGUS: goto bogus; + case LDNS_STATUS_OK : goto cleanup; + default : break; + } +insecure: + s = LDNS_STATUS_DANE_INSECURE; +bogus: + if (! insecure_is_ok) { +error: + ldns_rr_list_deep_free(*rrs); + *rrs = ldns_rr_list_new(); + } +cleanup: + if (keys) { + ldns_rr_list_deep_free(keys); + } + if (rrsigs) { + ldns_rr_list_deep_free(rrsigs); + } + ldns_pkt_free(p); + return s; +} + + +ldns_rr_list* +dane_lookup_addresses(ldns_resolver* res, ldns_rdf* dname, + int ai_family) +{ + ldns_status s; + ldns_rr_list *as = NULL; + ldns_rr_list *aaas = NULL; + ldns_rr_list *r = ldns_rr_list_new(); + + if (r == NULL) { + MEMERR("ldns_rr_list_new"); + } + if (ai_family == AF_UNSPEC || ai_family == AF_INET) { + + s = dane_query(&as, res, + dname, LDNS_RR_TYPE_A, LDNS_RR_CLASS_IN, + true); + + if (s == LDNS_STATUS_DANE_INSECURE && + ldns_rr_list_rr_count(as) > 0) { + fprintf(stderr, "Warning! Insecure IPv4 addresses. " + "Continuing with them...\n"); + + } else if (s == LDNS_STATUS_DANE_BOGUS || + LDNS_STATUS_CRYPTO_BOGUS == s) { + fprintf(stderr, "Warning! Bogus IPv4 addresses. " + "Discarding...\n"); + ldns_rr_list_deep_free(as); + as = ldns_rr_list_new(); + + } else if (s != LDNS_STATUS_OK) { + LDNS_ERR(s, "dane_query"); + + } + if (! ldns_rr_list_push_rr_list(r, as)) { + MEMERR("ldns_rr_list_push_rr_list"); + } + } + if (ai_family == AF_UNSPEC || ai_family == AF_INET6) { + + s = dane_query(&aaas, res, + dname, LDNS_RR_TYPE_AAAA, LDNS_RR_CLASS_IN, + true); + + if (s == LDNS_STATUS_DANE_INSECURE && + ldns_rr_list_rr_count(aaas) > 0) { + fprintf(stderr, "Warning! Insecure IPv6 addresses. " + "Continuing with them...\n"); + + } else if (s == LDNS_STATUS_DANE_BOGUS || + LDNS_STATUS_CRYPTO_BOGUS == s) { + fprintf(stderr, "Warning! Bogus IPv4 addresses. " + "Discarding...\n"); + ldns_rr_list_deep_free(aaas); + aaas = ldns_rr_list_new(); + + } else if (s != LDNS_STATUS_OK) { + LDNS_ERR(s, "dane_query"); + + } + if (! ldns_rr_list_push_rr_list(r, aaas)) { + MEMERR("ldns_rr_list_push_rr_list"); + } + } + return r; +} + +ldns_status +dane_read_tlsas_from_file(ldns_rr_list** tlsas, + char* filename, ldns_rdf* origin) +{ + FILE* fp = NULL; + ldns_rr* rr = NULL; + ldns_rdf *my_origin = NULL; + ldns_rdf *my_prev = NULL; + ldns_rdf *origin_lc = NULL; + int line_nr; + ldns_status s = LDNS_STATUS_MEM_ERR; + + assert(tlsas != NULL); + assert(filename != NULL); + + if (strcmp(filename, "-") == 0) { + fp = stdin; + } else { + fp = fopen(filename, "r"); + if (!fp) { + fprintf(stderr, "Unable to open %s: %s\n", + filename, strerror(errno)); + exit(EXIT_FAILURE); + } + } + if (origin) { + my_origin = ldns_rdf_clone(origin); + if (! my_origin) { + goto error; + } + my_prev = ldns_rdf_clone(origin); + if (! my_prev) { + goto error; + } + origin_lc = ldns_rdf_clone(origin); + if (! origin_lc) { + goto error; + } + ldns_dname2canonical(origin_lc); + } + *tlsas = ldns_rr_list_new(); + if (! *tlsas) { + goto error; + } + while (! feof(fp)) { + s = ldns_rr_new_frm_fp_l(&rr, fp, NULL, + &my_origin, &my_prev, &line_nr); + if (s != LDNS_STATUS_OK) { + goto error; + } + if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_TLSA) { + ldns_dname2canonical(ldns_rr_owner(rr)); + if (! origin || ldns_dname_compare(ldns_rr_owner(rr), + origin_lc) == 0) { + if (ldns_rr_list_push_rr(*tlsas, rr)) { + continue; + } else { + s = LDNS_STATUS_MEM_ERR; + goto error; + } + } + } + ldns_rr_free(rr); + } + + ldns_rdf_deep_free(origin_lc); + ldns_rdf_deep_free(my_prev); + ldns_rdf_deep_free(my_origin); + fclose(fp); + + return LDNS_STATUS_OK; + +error: + if (*tlsas) { + ldns_rr_list_deep_free(*tlsas); + *tlsas = NULL; + } + if (origin_lc) { + ldns_rdf_deep_free(origin_lc); + } + if (my_prev) { + ldns_rdf_deep_free(my_prev); + } + if (my_origin) { + ldns_rdf_deep_free(my_origin); + } + if (fp && fp != stdin) { + fclose(fp); + } + return s; +} + +bool +dane_wildcard_label_cmp(uint8_t iw, const char* w, uint8_t il, const char* l) +{ + if (iw == 0) { /* End of match label */ + if (il == 0) { /* And end in the to be matched label */ + return true; + } + return false; + } + do { + if (*w == '*') { + if (iw == 1) { /* '*' is the last match char, + remainder matches wildcard */ + return true; + } + while (il > 0) { /* more to match? */ + + if (w[1] == *l) { /* Char after '*' matches. + * Recursion for backtracking + */ + if (dane_wildcard_label_cmp( + iw - 1, w + 1, + il , l)) { + return true; + } + } + l += 1; + il -= 1; + } + } + /* Skip up till next wildcard (if possible) */ + while (il > 0 && iw > 0 && *w != '*' && *w == *l) { + w += 1; + l += 1; + il -= 1; + iw -= 1; + } + } while (iw > 0 && *w == '*' && /* More to match a next wildcard? */ + (il > 0 || iw == 1)); + + return iw == 0 && il == 0; +} + +bool +dane_label_matches_label(ldns_rdf* w, ldns_rdf* l) +{ + uint8_t iw; + uint8_t il; + + iw = ldns_rdf_data(w)[0]; + il = ldns_rdf_data(l)[0]; + return dane_wildcard_label_cmp( + iw, (const char*)ldns_rdf_data(w) + 1, + il, (const char*)ldns_rdf_data(l) + 1); +} + +bool +dane_name_matches_server_name(const char* name_str, ldns_rdf* server_name) +{ + ldns_rdf* name; + uint8_t nn, ns, i; + ldns_rdf* ln; + ldns_rdf* ls; + + name = ldns_dname_new_frm_str((const char*)name_str); + if (! name) { + LDNS_ERR(LDNS_STATUS_ERR, "ldns_dname_new_frm_str"); + } + nn = ldns_dname_label_count(name); + ns = ldns_dname_label_count(server_name); + if (nn != ns) { + ldns_rdf_free(name); + return false; + } + ldns_dname2canonical(name); + for (i = 0; i < nn; i++) { + ln = ldns_dname_label(name, i); + if (! ln) { + return false; + } + ls = ldns_dname_label(server_name, i); + if (! ls) { + ldns_rdf_free(ln); + return false; + } + if (! dane_label_matches_label(ln, ls)) { + ldns_rdf_free(ln); + ldns_rdf_free(ls); + return false; + } + ldns_rdf_free(ln); + ldns_rdf_free(ls); + } + return true; +} + +bool +dane_X509_any_subject_alt_name_matches_server_name( + X509 *cert, ldns_rdf* server_name) +{ + GENERAL_NAMES* names; + GENERAL_NAME* name; + unsigned char* subject_alt_name_str = NULL; + int i, n; + + names = X509_get_ext_d2i(cert, NID_subject_alt_name, 0, 0 ); + if (! names) { /* No subjectAltName extension */ + return false; + } + n = sk_GENERAL_NAME_num(names); + for (i = 0; i < n; i++) { + name = sk_GENERAL_NAME_value(names, i); + if (name->type == GEN_DNS) { + (void) ASN1_STRING_to_UTF8(&subject_alt_name_str, + name->d.dNSName); + if (subject_alt_name_str) { + if (dane_name_matches_server_name((char*) + subject_alt_name_str, + server_name)) { + OPENSSL_free(subject_alt_name_str); + return true; + } + OPENSSL_free(subject_alt_name_str); + } + } + } + /* sk_GENERAL_NAMES_pop_free(names, sk_GENERAL_NAME_free); */ + return false; +} + +bool +dane_X509_subject_name_matches_server_name(X509 *cert, ldns_rdf* server_name) +{ + X509_NAME* subject_name; + int i; + X509_NAME_ENTRY* entry; + ASN1_STRING* entry_data; + unsigned char* subject_name_str = NULL; + bool r; + + subject_name = X509_get_subject_name(cert); + if (! subject_name ) { + ssl_err("could not X509_get_subject_name"); + } + i = X509_NAME_get_index_by_NID(subject_name, NID_commonName, -1); + entry = X509_NAME_get_entry(subject_name, i); + entry_data = X509_NAME_ENTRY_get_data(entry); + (void) ASN1_STRING_to_UTF8(&subject_name_str, entry_data); + if (subject_name_str) { + r = dane_name_matches_server_name( + (char*)subject_name_str, server_name); + OPENSSL_free(subject_name_str); + return r; + } else { + return false; + } +} + +bool +dane_verify_server_name(X509* cert, ldns_rdf* server_name) +{ + ldns_rdf* server_name_lc; + bool r; + server_name_lc = ldns_rdf_clone(server_name); + if (! server_name_lc) { + LDNS_ERR(LDNS_STATUS_MEM_ERR, "ldns_rdf_clone"); + } + ldns_dname2canonical(server_name_lc); + r = dane_X509_any_subject_alt_name_matches_server_name( + cert, server_name_lc) || + dane_X509_subject_name_matches_server_name( + cert, server_name_lc); + ldns_rdf_free(server_name_lc); + return r; +} + +void +dane_create(ldns_rr_list* tlsas, ldns_rdf* tlsa_owner, + ldns_tlsa_certificate_usage certificate_usage, int offset, + ldns_tlsa_selector selector, + ldns_tlsa_matching_type matching_type, + X509* cert, STACK_OF(X509)* extra_certs, + X509_STORE* validate_store, + bool verify_server_name, ldns_rdf* name) +{ + ldns_status s; + X509* selected_cert; + ldns_rr* tlsa_rr; + + if (verify_server_name && ! dane_verify_server_name(cert, name)) { + fprintf(stderr, "The certificate does not match the " + "server name\n"); + exit(EXIT_FAILURE); + } + + s = ldns_dane_select_certificate(&selected_cert, + cert, extra_certs, validate_store, + certificate_usage, offset); + LDNS_ERR(s, "could not select certificate"); + + s = ldns_dane_create_tlsa_rr(&tlsa_rr, + certificate_usage, selector, matching_type, + selected_cert); + LDNS_ERR(s, "could not create tlsa rr"); + + ldns_rr_set_owner(tlsa_rr, tlsa_owner); + + if (! ldns_rr_list_contains_rr(tlsas, tlsa_rr)) { + if (! ldns_rr_list_push_rr(tlsas, tlsa_rr)) { + MEMERR("ldns_rr_list_push_rr"); + } + } +} + +bool +dane_verify(ldns_rr_list* tlsas, ldns_rdf* address, + X509* cert, STACK_OF(X509)* extra_certs, + X509_STORE* validate_store, + bool verify_server_name, ldns_rdf* name) +{ + ldns_status s; + char* address_str = NULL; + + s = ldns_dane_verify(tlsas, cert, extra_certs, validate_store); + if (address) { + address_str = ldns_rdf2str(address); + fprintf(stdout, "%s", address_str ? address_str : "
    "); + free(address_str); + } else { + X509_NAME_print_ex_fp(stdout, + X509_get_subject_name(cert), 0, 0); + } + if (s == LDNS_STATUS_OK) { + if (verify_server_name && + ! dane_verify_server_name(cert, name)) { + + fprintf(stdout, " did not dane-validate, because:" + " the certificate name did not match" + " the server name\n"); + return false; + } + fprintf(stdout, " dane-validated successfully\n"); + return true; + } + fprintf(stdout, " did not dane-validate, because: %s\n", + ldns_get_errorstr_by_id(s)); + return false; +} + + +int +main(int argc, char* const* argv) +{ + int c; + enum { UNDETERMINED, VERIFY, CREATE } mode = UNDETERMINED; + + ldns_status s; + size_t i; + + bool print_tlsa_as_type52 = false; + bool assume_dnssec_validity = false; + bool assume_pkix_validity = false; + bool verify_server_name = true; + bool interact = false; + +#if HAVE_DANE_CA_FILE + const char* CAfile = LDNS_DANE_CA_FILE; +#else + const char* CAfile = NULL; +#endif +#if HAVE_DANE_CA_PATH + const char* CApath = LDNS_DANE_CA_PATH; +#else + const char* CApath = NULL; +#endif + char* cert_file = NULL; + X509* cert = NULL; + STACK_OF(X509)* extra_certs = NULL; + + ldns_rr_list* keys = ldns_rr_list_new(); + size_t nkeys = 0; + bool do_sigchase = false; + + ldns_rr_list* addresses = ldns_rr_list_new(); + ldns_rr* address_rr; + ldns_rdf* address; + + int ai_family = AF_UNSPEC; + int transport = LDNS_DANE_TRANSPORT_TCP; + + char* name_str = NULL; /* supress uninitialized warning */ + ldns_rdf* name; + uint16_t port = 0; /* supress uninitialized warning */ + + ldns_resolver* res = NULL; + ldns_rdf* tlsa_owner = NULL; + char* tlsa_owner_str = NULL; + ldns_rr_list* tlsas = NULL; + char* tlsas_file = NULL; + + /* For extracting service port and transport from tla_owner. */ + ldns_rdf* port_rdf = NULL; + char* port_str = NULL; + ldns_rdf* transport_rdf = NULL; + char* transport_str = NULL; + + ldns_rr_list* originals = NULL; /* original tlsas (before + * transform), but also used + * as temporary. + */ + + ldns_tlsa_certificate_usage certificate_usage = 666; + int offset = -1; + ldns_tlsa_selector selector = 666; + ldns_tlsa_matching_type matching_type = 666; + + + X509_STORE *store = NULL; + + SSL_CTX* ctx = NULL; + SSL* ssl = NULL; + + bool success = true; + + if (! keys || ! addresses) { + MEMERR("ldns_rr_list_new"); + } + while((c = getopt(argc, argv, "46a:bc:df:hik:no:p:sSt:uvV:")) != -1) { + switch(c) { + case 'h': + print_usage("ldns-dane"); + break; + case '4': + ai_family = AF_INET; + break; + case '6': + ai_family = AF_INET6; + break; + case 'a': + s = ldns_str2rdf_a(&address, optarg); + if (s == LDNS_STATUS_OK) { + address_rr = ldns_rr_new_frm_type( + LDNS_RR_TYPE_A); + } else { + s = ldns_str2rdf_aaaa(&address, optarg); + if (s == LDNS_STATUS_OK) { + address_rr = ldns_rr_new_frm_type( + LDNS_RR_TYPE_AAAA); + } else { + fprintf(stderr, + "Could not interpret address " + "%s\n", + optarg); + exit(EXIT_FAILURE); + } + } + (void) ldns_rr_a_set_address(address_rr, address); + for (i = 0; i < ldns_rr_list_rr_count(addresses); i++){ + if (ldns_rdf_compare(address, + ldns_rr_a_address( + ldns_rr_list_rr(addresses, i))) == 0) { + break; + } + } + if (i >= ldns_rr_list_rr_count(addresses)) { + if (! ldns_rr_list_push_rr(addresses, + address_rr)) { + MEMERR("ldns_rr_list_push_rr"); + } + } + break; + case 'b': + print_tlsa_as_type52 = true; + /* TODO: do it with output formats... maybe... */ + break; + case 'c': + cert_file = optarg; /* checking in SSL stuff below */ + break; + case 'd': + assume_dnssec_validity = true; + break; + case 'f': + CAfile = optarg; + break; + case 'i': + interact = true; + break; + case 'k': + s = read_key_file(optarg, keys); + if (s == LDNS_STATUS_FILE_ERR) { + fprintf(stderr, "Error opening %s: %s\n", + optarg, strerror(errno)); + } + LDNS_ERR(s, "Could not parse key file"); + if (ldns_rr_list_rr_count(keys) == nkeys) { + fprintf(stderr, "No keys found in file" + " %s\n", optarg); + exit(EXIT_FAILURE); + } + nkeys = ldns_rr_list_rr_count(keys); + break; + case 'n': + verify_server_name = false; + break; + case 'o': + offset = atoi(optarg); /* todo check if all numeric */ + break; + case 'p': + CApath = optarg; + break; + case 's': + assume_pkix_validity = true; + break; + case 'S': + do_sigchase = true; + break; + case 't': + tlsas_file = optarg; + break; + case 'u': + transport = LDNS_DANE_TRANSPORT_UDP; + break; + case 'v': + printf("ldns-dane version %s (ldns version %s)\n", + LDNS_VERSION, ldns_version()); + exit(EXIT_SUCCESS); + break; +/* case 'V': + verbosity = atoi(optarg); + break; + */ + } + } + + /* Filter out given IPv4 addresses when -6 was given, + * and IPv6 addresses when -4 was given. + */ + if (ldns_rr_list_rr_count(addresses) > 0 && + ai_family != AF_UNSPEC) { + originals = addresses; + addresses = rr_list_filter_rr_type(originals, + (ai_family == AF_INET + ? LDNS_RR_TYPE_A : LDNS_RR_TYPE_AAAA)); + ldns_rr_list_free(originals); + if (addresses == NULL) { + MEMERR("rr_list_filter_rr_type"); + } + if (ldns_rr_list_rr_count(addresses) == 0) { + fprintf(stderr, + "No addresses of the specified type remain\n"); + exit(EXIT_FAILURE); + } + } + + if (do_sigchase) { + if (nkeys == 0) { + (void) read_key_file(LDNS_TRUST_ANCHOR_FILE, keys); + nkeys = ldns_rr_list_rr_count(keys); + + if (nkeys == 0) { + fprintf(stderr, "Unable to chase " + "signature without keys.\n"); + exit(EXIT_FAILURE); + } + } + } else { + keys = NULL; + } + + argc -= optind; + argv += optind; + + if (argc == 0) { + + print_usage("ldns-dane"); + } + if (strncasecmp(*argv, "create", strlen(*argv)) == 0) { + + mode = CREATE; + argc--; + argv++; + + } else if (strncasecmp(*argv, "verify", strlen(*argv)) == 0) { + + mode = VERIFY; + argc--; + argv++; + + } else { + fprintf(stderr, "Specify create or verify mode\n"); + exit(EXIT_FAILURE); + } + + if (mode == VERIFY && argc == 0) { + + if (! tlsas_file) { + fprintf(stderr, "ERROR! Nothing given to verify\n"); + exit(EXIT_FAILURE); + } + s = dane_read_tlsas_from_file(&tlsas, tlsas_file, NULL); + LDNS_ERR(s, "could not read tlas from file"); + + /* extract port, transport and hostname from TLSA owner name */ + + if (ldns_rr_list_rr_count(tlsas) == 0) { + + fprintf(stderr, "ERROR! No TLSA records to extract " + "service port, transport and hostname" + "\n"); + exit(EXIT_FAILURE); + } + tlsa_owner = ldns_rr_list_owner(tlsas); + if (ldns_dname_label_count(tlsa_owner) < 2) { + fprintf(stderr, "ERROR! To few labels in TLSA owner\n"); + exit(EXIT_FAILURE); + } + do { + s = LDNS_STATUS_MEM_ERR; + port_rdf = ldns_dname_label(tlsa_owner, 0); + if (! port_rdf) { + break; + } + port_str = ldns_rdf2str(port_rdf); + if (! port_str) { + break; + } + if (*port_str != '_') { + fprintf(stderr, "ERROR! Badly formatted " + "service port label in the " + "TLSA owner name\n"); + exit(EXIT_FAILURE); + } + if (port_str[strlen(port_str) - 1] == '.') { + port_str[strlen(port_str) - 1] = '\000'; + } + port = (uint16_t) dane_int_within_range( + port_str + 1, 65535, "port"); + s = LDNS_STATUS_OK; + } while (false); + LDNS_ERR(s, "could not extract service port from TLSA owner"); + + do { + s = LDNS_STATUS_MEM_ERR; + transport_rdf = ldns_dname_label(tlsa_owner, 1); + if (! transport_rdf) { + break; + } + transport_str = ldns_rdf2str(transport_rdf); + if (! transport_str) { + break; + } + if (transport_str[strlen(transport_str) - 1] == '.') { + transport_str[strlen(transport_str) - 1] = + '\000'; + } + if (strcmp(transport_str, "_tcp") == 0) { + + transport = LDNS_DANE_TRANSPORT_TCP; + + } else if (strcmp(transport_str, "_udp") == 0) { + + transport = LDNS_DANE_TRANSPORT_UDP; + + } else if (strcmp(transport_str, "_sctp") == 0) { + + transport = LDNS_DANE_TRANSPORT_SCTP; + + } else { + fprintf(stderr, "ERROR! Badly formatted " + "transport label in the " + "TLSA owner name\n"); + exit(EXIT_FAILURE); + } + s = LDNS_STATUS_OK; + break; + } while(false); + LDNS_ERR(s, "could not extract transport from TLSA owner"); + + tlsa_owner_str = ldns_rdf2str(tlsa_owner); + if (! tlsa_owner_str) { + MEMERR("ldns_rdf2str"); + } + name = ldns_dname_clone_from(tlsa_owner, 2); + if (! name) { + MEMERR("ldns_dname_clone_from"); + } + name_str = ldns_rdf2str(name); + if (! name_str) { + MEMERR("ldns_rdf2str"); + } + + + } else if (argc < 2) { + + print_usage("ldns-dane"); + + } else { + name_str = *argv++; argc--; + s = ldns_str2rdf_dname(&name, name_str); + LDNS_ERR(s, "could not ldns_str2rdf_dname"); + + port = (uint16_t)dane_int_within_range(*argv++, 65535, "port"); + --argc; + + s = ldns_dane_create_tlsa_owner(&tlsa_owner, + name, port, transport); + LDNS_ERR(s, "could not create TLSA owner name"); + tlsa_owner_str = ldns_rdf2str(tlsa_owner); + if (! tlsa_owner_str) { + MEMERR("ldns_rdf2str"); + } + } + + switch (mode) { + case VERIFY: + if (argc > 0) { + + print_usage("ldns-dane"); + } + if (tlsas_file) { + + s = dane_read_tlsas_from_file(&tlsas, tlsas_file, + tlsa_owner); + LDNS_ERR(s, "could not read tlas from file"); + } else { + /* lookup tlsas */ + s = dane_setup_resolver(&res, keys, + assume_dnssec_validity); + LDNS_ERR(s, "could not dane_setup_resolver"); + s = dane_query(&tlsas, res, tlsa_owner, + LDNS_RR_TYPE_TLSA, LDNS_RR_CLASS_IN, + false); + ldns_resolver_free(res); + } + + if (s == LDNS_STATUS_DANE_INSECURE) { + + fprintf(stderr, "Warning! TLSA records for %s " + "were found, but were insecure.\n" + "PKIX validation without DANE will be " + "performed. If you wish to perform DANE\n" + "even though the RR's are insecure, " + "se the -d option.\n", tlsa_owner_str); + + } else if (s != LDNS_STATUS_OK) { + + ldns_err("dane_query", s); + + } else if (ldns_rr_list_rr_count(tlsas) == 0) { + + fprintf(stderr, "Warning! No TLSA records for %s " + "were found.\n" + "PKIX validation without DANE will be " + "performed.\n", ldns_rdf2str(tlsa_owner)); + + } else if (assume_pkix_validity) { /* number of tlsa's > 0 */ + + /* transform type "CA constraint" to "Trust anchor + * assertion" and "Service Certificate Constraint" + * to "Domain Issues Certificate" + */ + originals = tlsas; + tlsas = dane_no_pkix_transform(originals); + } + + break; + + case CREATE: + if (argc > 0) { + certificate_usage = dane_int_within_range_table( + *argv++, 3, "certificate usage", + dane_certificate_usage_table); + argc--; + } else { + certificate_usage = + LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE; + } + if (argc > 0) { + selector = dane_int_within_range_table( + *argv++, 1, "selector", + dane_selector_table); + argc--; + } else { + selector = LDNS_TLSA_SELECTOR_FULL_CERTIFICATE; + } + if (argc > 0) { + if (*argv && /* strlen(argv) > 0 */ + (strncasecmp(*argv, "no-hash-used", + strlen(*argv)) == 0 || + strncasecmp(*argv, "no hash used", + strlen(*argv)) == 0 )) { + matching_type = + LDNS_TLSA_MATCHING_TYPE_NO_HASH_USED; + + } else if (strcasecmp(*argv, "sha256") == 0 || + strcasecmp(*argv, "sha-256") == 0) { + + matching_type = LDNS_TLSA_MATCHING_TYPE_SHA256; + + } else if (strcasecmp(*argv, "sha512") == 0 || + strcasecmp(*argv, "sha-512") == 0) { + + matching_type = LDNS_TLSA_MATCHING_TYPE_SHA512; + + } else { + matching_type = dane_int_within_range( + *argv, 2, "matching type"); + } + argv++; + argc--; + } else { + matching_type = LDNS_TLSA_MATCHING_TYPE_SHA256; + } + if (argc > 0) { + + print_usage("ldns-dane"); + } + if ((certificate_usage == LDNS_TLSA_USAGE_CA_CONSTRAINT || + certificate_usage == + LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT) && + ! CAfile && ! CApath && ! assume_pkix_validity) { + + fprintf(stderr, + "When using the \"CA constraint\" or " + "\"Service certificate constraint\",\n" + "-f and/or -p options " + "must be given to perform PKIX validation.\n\n" + "PKIX validation may be turned off " + "with the -s option. Note that with\n" + "\"CA constraint\" the verification process " + "should then end with a self-signed\n" + "certificate which must be present " + "in the server certificate chain.\n\n"); + + exit(EXIT_FAILURE); + } + tlsas = ldns_rr_list_new(); + break; + default: + fprintf(stderr, "Unreachable code\n"); + assert(0); + } + + /* ssl inititalize */ + SSL_load_error_strings(); + SSL_library_init(); + + /* ssl load validation store */ + if (! assume_pkix_validity || CAfile || CApath) { + store = X509_STORE_new(); + if (! store) { + ssl_err("could not X509_STORE_new"); + } + if ((CAfile || CApath) && X509_STORE_load_locations( + store, CAfile, CApath) != 1) { + ssl_err("error loading CA certificates"); + } + } + + ctx = SSL_CTX_new(SSLv23_client_method()); + if (! ctx) { + ssl_err("could not SSL_CTX_new"); + } + if (cert_file && + SSL_CTX_use_certificate_chain_file(ctx, cert_file) != 1) { + ssl_err("error loading certificate"); + } + ssl = SSL_new(ctx); + if (! ssl) { + ssl_err("could not SSL_new"); + } + + if (cert_file) { /* ssl load certificate */ + + cert = SSL_get_certificate(ssl); + if (! cert) { + ssl_err("could not SSL_get_certificate"); + } +#ifndef S_SPLINT_S + extra_certs = ctx->extra_certs; +#endif + + switch (mode) { + case CREATE: dane_create(tlsas, tlsa_owner, certificate_usage, + offset, selector, matching_type, + cert, extra_certs, store, + verify_server_name, name); + break; + case VERIFY: if (! dane_verify(tlsas, NULL, + cert, extra_certs, store, + verify_server_name, name)) { + success = false; + } + break; + default: break; /* suppress warning */ + } + + } else {/* No certificate file given, creation/validation via TLS. */ + + /* We need addresses to connect to */ + if (ldns_rr_list_rr_count(addresses) == 0) { + s = dane_setup_resolver(&res, keys, + assume_dnssec_validity); + LDNS_ERR(s, "could not dane_setup_resolver"); + ldns_rr_list_free(addresses); + addresses =dane_lookup_addresses(res, name, ai_family); + ldns_resolver_free(res); + } + if (ldns_rr_list_rr_count(addresses) == 0) { + fprintf(stderr, "No addresses for %s\n", name_str); + exit(EXIT_FAILURE); + } + + /* for all addresses, setup SSL and retrieve certificates */ + for (i = 0; i < ldns_rr_list_rr_count(addresses); i++) { + + address = ldns_rr_a_address( + ldns_rr_list_rr(addresses, i)); + assert(address != NULL); + + s = ssl_connect_and_get_cert_chain(&cert, &extra_certs, + ssl, address, port, transport); + if (s == LDNS_STATUS_NETWORK_ERR) { + fprintf(stderr, "Could not connect to "); + ldns_rdf_print(stderr, address); + fprintf(stderr, " %d\n", (int) port); + + /* All addresses should succeed */ + success = false; + continue; + } + LDNS_ERR(s, "could not get cert chain from ssl"); + switch (mode) { + + case CREATE: dane_create(tlsas, tlsa_owner, + certificate_usage, offset, + selector, matching_type, + cert, extra_certs, store, + verify_server_name, name); + break; + + case VERIFY: if (! dane_verify(tlsas, address, + cert, extra_certs, store, + verify_server_name, name)) { + success = false; + + } else if (interact) { + ssl_interact(ssl); + } + break; + default: break; /* suppress warning */ + } + ssl_shutdown(ssl); + } /* end for all addresses */ + } /* end No certification file */ + + if (mode == CREATE) { + if (print_tlsa_as_type52) { + print_rr_list_as_TYPEXXX(stdout, tlsas); + } else { + ldns_rr_list_print(stdout, tlsas); + } + } + ldns_rr_list_deep_free(tlsas); + + /* cleanup */ + SSL_free(ssl); + SSL_CTX_free(ctx); + + if (store) { + X509_STORE_free(store); + } + if (tlsa_owner_str) { + LDNS_FREE(tlsa_owner_str); + } + if (tlsa_owner) { + ldns_rdf_free(tlsa_owner); + } + if (addresses) { + ldns_rr_list_deep_free(addresses); + } + if (success) { + exit(EXIT_SUCCESS); + } else { + exit(EXIT_FAILURE); + } +} +#else + +int +main(int argc, char **argv) +{ + fprintf(stderr, "ldns-dane needs OpenSSL support, " + "which has not been compiled in\n"); + return 1; +} +#endif /* HAVE_SSL */ diff --git a/examples/ldns-gen-zone.c b/examples/ldns-gen-zone.c index cf5e5fd8d7a..c19d0f6dc05 100644 --- a/examples/ldns-gen-zone.c +++ b/examples/ldns-gen-zone.c @@ -133,7 +133,7 @@ main(int argc, char **argv) { break; case 'p': dsperc = atoi(optarg); - if (dsperc <= 0 || dsperc > 100) { + if (dsperc < 0 || dsperc > 100) { fprintf(stderr, "error: percentage of signed delegations must be between [0-100].\n"); exit(EXIT_FAILURE); } diff --git a/examples/ldns-keyfetcher.c b/examples/ldns-keyfetcher.c index 267822f8868..fa78b432b39 100644 --- a/examples/ldns-keyfetcher.c +++ b/examples/ldns-keyfetcher.c @@ -649,13 +649,26 @@ main(int argc, char *argv[]) fprintf(stderr, "Warning: Unable to create stub resolver from /etc/resolv.conf:\n"); fprintf(stderr, "%s\n", ldns_get_errorstr_by_id(status)); fprintf(stderr, "defaulting to nameserver at 127.0.0.1 for separate nameserver name lookups\n"); - res = ldns_resolver_new(); - ns = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, "127.0.0.1"); - status = ldns_resolver_push_nameserver(res, ns); - if (status != LDNS_STATUS_OK) { - fprintf(stderr, "Unable to create stub resolver: %s\n", ldns_get_errorstr_by_id(status)); + do { + res = ldns_resolver_new(); + if (res) { + ns = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, + "127.0.0.1"); + if (ns) { + status = ldns_resolver_push_nameserver( + res, ns); + if (status == LDNS_STATUS_OK) { + break; + } + ldns_rdf_deep_free(ns); + } + ldns_resolver_free(res); + } + fprintf(stderr, "Unable to create stub resolver: %s\n", + ldns_get_errorstr_by_id(status)); exit(EXIT_FAILURE); - } + + } while (false); ldns_rdf_deep_free(ns); } diff --git a/examples/ldns-keygen.1 b/examples/ldns-keygen.1 index 36124d52a47..734ad6d1636 100644 --- a/examples/ldns-keygen.1 +++ b/examples/ldns-keygen.1 @@ -14,7 +14,13 @@ will create 3 files; a .key file with the public DNSKEY, a .private file with the private keydata and a .ds with the DS record of the DNSKEY record. -It prints out the basename for these files: K++ +\fBldns-keygen\fR can also be used to create symmetric keys (for TSIG) by +selecting the appropriate algorithm: \%\fIhmac-md5.sig-alg.reg.int\fR, +\%\fIhmac-sha1\fR or \%\fIhmac-sha256\fR. +In that case no DS record will be created and no .ds file. + +\fBldns-keygen\fR prints the basename for the key files: +K++ .SH OPTIONS .TP diff --git a/examples/ldns-notify.c b/examples/ldns-notify.c index 018a716faad..50da6e606af 100644 --- a/examples/ldns-notify.c +++ b/examples/ldns-notify.c @@ -204,6 +204,11 @@ main(int argc, char **argv) tsig_cred.algorithm = (char*)"hmac-md5.sig-alg.reg.int."; tsig_cred.keyname = optarg; tsig_cred.keydata = strchr(optarg, ':'); + if (tsig_cred.keydata == NULL) { + printf("TSIG argument is not in form " + "key:data: %s\n", optarg); + exit(1); + } *tsig_cred.keydata = '\0'; tsig_cred.keydata++; printf("Sign with %s : %s\n", tsig_cred.keyname, @@ -250,7 +255,7 @@ main(int argc, char **argv) ldns_pkt_set_opcode(notify, LDNS_PACKET_NOTIFY); ldns_pkt_push_rr(notify, LDNS_SECTION_QUESTION, question); ldns_pkt_set_aa(notify, true); - ldns_pkt_set_id(notify, random()&0xffff); + ldns_pkt_set_random_id(notify); if(include_soa) { char buf[10240]; ldns_rr *soa_rr=NULL; diff --git a/examples/ldns-read-zone.1 b/examples/ldns-read-zone.1 index 81f238d601c..7d4fd7d9494 100644 --- a/examples/ldns-read-zone.1 +++ b/examples/ldns-read-zone.1 @@ -21,6 +21,12 @@ Only print DNSSEC data from the zone. This option skips every record that is not of type NSEC, NSEC3, RRSIG or DNSKEY. DS records are not printed. +.TP +\fB-0\fR +Print a (null) for the RRSIG inception, expiry and key data. This option +can be used when comparing different signing systems that use the same +DNSKEYs for signing but would have a slightly different timings/jitter. + .TP \fB-h\fR Show usage and exit @@ -29,6 +35,11 @@ Show usage and exit \fB-n\fR Do not print the SOA record +.TP +\fB-p\fR +Pad the SOA serial number with spaces so the number and the spaces together +take ten characters. This is useful for in file serial number increments. + .TP \fB-s\fR Strip DNSSEC data from the zone. This option skips every record diff --git a/examples/ldns-read-zone.c b/examples/ldns-read-zone.c index ac32bac7f73..efe187e6a22 100644 --- a/examples/ldns-read-zone.c +++ b/examples/ldns-read-zone.c @@ -33,14 +33,23 @@ main(int argc, char **argv) ldns_rr_list *stripped_list; ldns_rr *cur_rr; ldns_rr_type cur_rr_type; - const ldns_output_format *fmt = NULL; + ldns_output_format fmt = { + ldns_output_format_default->flags, + ldns_output_format_default->data + }; ldns_soa_serial_increment_func_t soa_serial_increment_func = NULL; int soa_serial_increment_func_data = 0; - while ((c = getopt(argc, argv, "bcdhnsvzS:")) != -1) { + while ((c = getopt(argc, argv, "0bcdhnpsvzS:")) != -1) { switch(c) { case 'b': - fmt = ldns_output_format_bubblebabble; + fmt.flags |= + ( LDNS_COMMENT_BUBBLEBABBLE | + LDNS_COMMENT_FLAGS ); + break; + case '0': + fmt.flags |= LDNS_FMT_ZEROIZE_RRSIGS; + break; case 'c': canonicalize = true; break; @@ -51,14 +60,17 @@ main(int argc, char **argv) } break; case 'h': - printf("Usage: %s [-c] [-v] [-z] \n", argv[0]); + printf("Usage: %s [OPTIONS] \n", argv[0]); printf("\tReads the zonefile and prints it.\n"); printf("\tThe RR count of the zone is printed to stderr.\n"); printf("\t-b include bubblebabble of DS's.\n"); + printf("\t-0 zeroize timestamps and signature in RRSIG records.\n"); printf("\t-c canonicalize all rrs in the zone.\n"); printf("\t-d only show DNSSEC data from the zone\n"); printf("\t-h show this text\n"); printf("\t-n do not print the SOA record\n"); + printf("\t-p prepend SOA serial with spaces so" + " it takes exactly ten characters.\n"); printf("\t-s strip DNSSEC data from the zone\n"); printf("\t-S [[+|-] | YYYYMMDDxx | " " unixtime ]\n" @@ -80,6 +92,9 @@ main(int argc, char **argv) case 'n': print_soa = false; break; + case 'p': + fmt.flags |= LDNS_FMT_PAD_SOA_SERIAL; + break; case 's': strip = true; if (only_dnssec) { @@ -141,6 +156,15 @@ main(int argc, char **argv) s = ldns_zone_new_frm_fp_l(&z, fp, NULL, 0, LDNS_RR_CLASS_IN, &line_nr); + fclose(fp); + if (s != LDNS_STATUS_OK) { + fprintf(stderr, "%s at %d\n", + ldns_get_errorstr_by_id(s), + line_nr); + exit(EXIT_FAILURE); + } + + if (strip) { stripped_list = ldns_rr_list_new(); while ((cur_rr = ldns_rr_list_pop_rr(ldns_zone_rrs(z)))) { @@ -176,37 +200,29 @@ main(int argc, char **argv) ldns_zone_set_rrs(z, stripped_list); } - if (s == LDNS_STATUS_OK) { - if (canonicalize) { - ldns_rr2canonical(ldns_zone_soa(z)); - for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(z)); i++) { - ldns_rr2canonical(ldns_rr_list_rr(ldns_zone_rrs(z), i)); - } + if (canonicalize) { + ldns_rr2canonical(ldns_zone_soa(z)); + for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(z)); i++) { + ldns_rr2canonical(ldns_rr_list_rr(ldns_zone_rrs(z), i)); } - if (sort) { - ldns_zone_sort(z); - } - - if (print_soa && ldns_zone_soa(z)) { - if (soa_serial_increment_func) { - ldns_rr_soa_increment_func_int( - ldns_zone_soa(z) - , soa_serial_increment_func - , soa_serial_increment_func_data - ); - } - ldns_rr_print_fmt(stdout, fmt, ldns_zone_soa(z)); - } - ldns_rr_list_print_fmt(stdout, fmt, ldns_zone_rrs(z)); - - ldns_zone_deep_free(z); - } else { - fprintf(stderr, "%s at %d\n", - ldns_get_errorstr_by_id(s), - line_nr); - exit(EXIT_FAILURE); } - fclose(fp); + if (sort) { + ldns_zone_sort(z); + } + + if (print_soa && ldns_zone_soa(z)) { + if (soa_serial_increment_func) { + ldns_rr_soa_increment_func_int( + ldns_zone_soa(z) + , soa_serial_increment_func + , soa_serial_increment_func_data + ); + } + ldns_rr_print_fmt(stdout, &fmt, ldns_zone_soa(z)); + } + ldns_rr_list_print_fmt(stdout, &fmt, ldns_zone_rrs(z)); + + ldns_zone_deep_free(z); exit(EXIT_SUCCESS); } diff --git a/examples/ldns-signzone.c b/examples/ldns-signzone.c index 34839b053dc..25ece3a651e 100644 --- a/examples/ldns-signzone.c +++ b/examples/ldns-signzone.c @@ -411,14 +411,16 @@ main(int argc, char *argv[]) tm.tm_year -= 1900; tm.tm_mon--; check_tm(tm); - expiration = (uint32_t) mktime_from_utc(&tm); + expiration = + (uint32_t) ldns_mktime_from_utc(&tm); } else if (strlen(optarg) == 14 && sscanf(optarg, "%4d%2d%2d%2d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) ) { tm.tm_year -= 1900; tm.tm_mon--; check_tm(tm); - expiration = (uint32_t) mktime_from_utc(&tm); + expiration = + (uint32_t) ldns_mktime_from_utc(&tm); } else { expiration = (uint32_t) atol(optarg); } @@ -436,14 +438,16 @@ main(int argc, char *argv[]) tm.tm_year -= 1900; tm.tm_mon--; check_tm(tm); - inception = (uint32_t) mktime_from_utc(&tm); + inception = + (uint32_t) ldns_mktime_from_utc(&tm); } else if (strlen(optarg) == 14 && sscanf(optarg, "%4d%2d%2d%2d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) ) { tm.tm_year -= 1900; tm.tm_mon--; check_tm(tm); - inception = (uint32_t) mktime_from_utc(&tm); + inception = + (uint32_t) ldns_mktime_from_utc(&tm); } else { inception = (uint32_t) atol(optarg); } @@ -509,13 +513,6 @@ main(int argc, char *argv[]) printf("Engine key id: %s, algo %d\n", eng_key_id, eng_key_algo); - if (expiration != 0) { - ldns_key_set_expiration(key, expiration); - } - if (inception != 0) { - ldns_key_set_inception(key, inception); - } - s = ldns_key_new_frm_engine(&key, engine, eng_key_id, eng_key_algo); if (s == LDNS_STATUS_OK) { /* must be dnssec key */ @@ -540,6 +537,14 @@ main(int argc, char *argv[]) fprintf(stderr, "Warning, key not suitable for signing, ignoring key with algorithm %u\n", ldns_key_algorithm(key)); break; } + if (expiration != 0) { + ldns_key_set_expiration(key, + expiration); + } + if (inception != 0) { + ldns_key_set_inception(key, + inception); + } } else { printf("Error reading key '%s' from engine: %s\n", eng_key_id, ldns_get_errorstr_by_id(s)); #ifdef HAVE_SSL @@ -674,10 +679,6 @@ main(int argc, char *argv[]) } } - if (!origin) { - origin = ldns_rr_owner(orig_soa); - } - /* read the ZSKs */ argi = 1; while (argi < argc) { diff --git a/examples/ldns-test-edns.c b/examples/ldns-test-edns.c index d9d708c7f31..b4292a0fa5d 100644 --- a/examples/ldns-test-edns.c +++ b/examples/ldns-test-edns.c @@ -15,6 +15,18 @@ /** print error details */ static int verb = 1; +struct sockaddr_in6* cast_sockaddr_storage2sockaddr_in6( + struct sockaddr_storage* s) +{ + return (struct sockaddr_in6*)s; +} + +struct sockaddr_in* cast_sockaddr_storage2sockaddr_in( + struct sockaddr_storage* s) +{ + return (struct sockaddr_in*)s; +} + /** parse IP address */ static int convert_addr(char* str, int p, struct sockaddr_storage* addr, socklen_t* len) @@ -22,8 +34,10 @@ convert_addr(char* str, int p, struct sockaddr_storage* addr, socklen_t* len) #ifdef AF_INET6 if(strchr(str, ':')) { *len = (socklen_t)sizeof(struct sockaddr_in6); - ((struct sockaddr_in6*)addr)->sin6_family = AF_INET6; - ((struct sockaddr_in6*)addr)->sin6_port = htons((uint16_t)p); + cast_sockaddr_storage2sockaddr_in6(addr)->sin6_family = + AF_INET6; + cast_sockaddr_storage2sockaddr_in6(addr)->sin6_port = + htons((uint16_t)p); if(inet_pton(AF_INET6, str, &((struct sockaddr_in6*)addr)->sin6_addr) == 1) return 1; @@ -31,9 +45,11 @@ convert_addr(char* str, int p, struct sockaddr_storage* addr, socklen_t* len) #endif *len = (socklen_t)sizeof(struct sockaddr_in); #ifndef S_SPLINT_S - ((struct sockaddr_in*)addr)->sin_family = AF_INET; + cast_sockaddr_storage2sockaddr_in(addr)->sin_family = + AF_INET; #endif - ((struct sockaddr_in*)addr)->sin_port = htons((uint16_t)p); + cast_sockaddr_storage2sockaddr_in(addr)->sin_port = + htons((uint16_t)p); if(inet_pton(AF_INET, str, &((struct sockaddr_in*)addr)->sin_addr) == 1) return 1; diff --git a/examples/ldns-testns.c b/examples/ldns-testns.c index eb007107eb2..86219d605c5 100644 --- a/examples/ldns-testns.c +++ b/examples/ldns-testns.c @@ -492,7 +492,7 @@ main(int argc, char **argv) datafile = argv[0]; log_msg("Reading datafile %s\n", datafile); - entries = read_datafile(datafile); + entries = read_datafile(datafile, 0); #ifdef USE_WINSOCK if(WSAStartup(MAKEWORD(2,2), &wsa_data) != 0) diff --git a/examples/ldns-testpkts.c b/examples/ldns-testpkts.c index d8139511ab5..be94eb2fe43 100644 --- a/examples/ldns-testpkts.c +++ b/examples/ldns-testpkts.c @@ -323,7 +323,7 @@ data_buffer2wire(ldns_buffer *data_buffer) uint8_t *hexbuf; int hexbufpos = 0; size_t wirelen; - uint8_t *data_wire = (uint8_t *) ldns_buffer_export(data_buffer); + uint8_t *data_wire = (uint8_t *) ldns_buffer_begin(data_buffer); uint8_t *wire = LDNS_XMALLOC(uint8_t, LDNS_MAX_PACKETLEN); hexbuf = LDNS_XMALLOC(uint8_t, LDNS_MAX_PACKETLEN); @@ -340,6 +340,12 @@ data_buffer2wire(ldns_buffer *data_buffer) (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') ) { + if (hexbufpos >= LDNS_MAX_PACKETLEN) { + error("buffer overflow"); + LDNS_FREE(hexbuf); + return 0; + + } hexbuf[hexbufpos] = (uint8_t) c; hexbufpos++; } else if (c == ';') { @@ -354,14 +360,14 @@ data_buffer2wire(ldns_buffer *data_buffer) } break; case 2: + if (hexbufpos >= LDNS_MAX_PACKETLEN) { + error("buffer overflow"); + LDNS_FREE(hexbuf); + return 0; + } hexbuf[hexbufpos] = (uint8_t) c; hexbufpos++; break; - default: - error("unknown state while reading"); - LDNS_FREE(hexbuf); - return 0; - break; } } @@ -371,6 +377,11 @@ data_buffer2wire(ldns_buffer *data_buffer) /* lenient mode: length must be multiple of 2 */ if (hexbufpos % 2 != 0) { + if (hexbufpos >= LDNS_MAX_PACKETLEN) { + error("buffer overflow"); + LDNS_FREE(hexbuf); + return 0; + } hexbuf[hexbufpos] = (uint8_t) '0'; hexbufpos++; } @@ -415,7 +426,7 @@ get_origin(const char* name, int lineno, ldns_rdf** origin, char* parse) /* Reads one entry from file. Returns entry or NULL on error. */ struct entry* read_entry(FILE* in, const char* name, int *lineno, uint32_t* default_ttl, - ldns_rdf** origin, ldns_rdf** prev_rr) + ldns_rdf** origin, ldns_rdf** prev_rr, int skip_whitespace) { struct entry* current = NULL; char line[MAX_LINE]; @@ -485,7 +496,10 @@ read_entry(FILE* in, const char* name, int *lineno, uint32_t* default_ttl, reading_hex = false; cur_reply->reply_from_hex = data_buffer2wire(hex_data_buffer); ldns_buffer_free(hex_data_buffer); + hex_data_buffer = NULL; } else if(str_keyword(&parse, "ENTRY_END")) { + if (hex_data_buffer) + ldns_buffer_free(hex_data_buffer); return current; } else if(reading_hex) { ldns_buffer_printf(hex_data_buffer, line); @@ -493,14 +507,17 @@ read_entry(FILE* in, const char* name, int *lineno, uint32_t* default_ttl, /* it must be a RR, parse and add to packet. */ ldns_rr* n = NULL; ldns_status status; + char* rrstr = line; + if (skip_whitespace) + rrstr = parse; if(add_section == LDNS_SECTION_QUESTION) status = ldns_rr_new_question_frm_str( - &n, parse, *origin, prev_rr); - else status = ldns_rr_new_frm_str(&n, parse, + &n, rrstr, *origin, prev_rr); + else status = ldns_rr_new_frm_str(&n, rrstr, *default_ttl, *origin, prev_rr); if(status != LDNS_STATUS_OK) error("%s line %d:\n\t%s: %s", name, *lineno, - ldns_get_errorstr_by_id(status), parse); + ldns_get_errorstr_by_id(status), rrstr); ldns_pkt_push_rr(cur_reply->reply, add_section, n); } @@ -518,7 +535,7 @@ read_entry(FILE* in, const char* name, int *lineno, uint32_t* default_ttl, /* reads the canned reply file and returns a list of structs */ struct entry* -read_datafile(const char* name) +read_datafile(const char* name, int skip_whitespace) { struct entry* list = NULL; struct entry* last = NULL; @@ -535,7 +552,7 @@ read_datafile(const char* name) } while((current = read_entry(in, name, &lineno, &default_ttl, - &origin, &prev_rr))) + &origin, &prev_rr, skip_whitespace))) { if(last) last->next = current; @@ -815,7 +832,7 @@ handle_query(uint8_t* inbuf, ssize_t inlen, struct entry* entries, int* count, /* still try to adjust ID */ answer_size = ldns_buffer_capacity(p->reply_from_hex); outbuf = LDNS_XMALLOC(uint8_t, answer_size); - memcpy(outbuf, ldns_buffer_export(p->reply_from_hex), answer_size); + memcpy(outbuf, ldns_buffer_begin(p->reply_from_hex), answer_size); if(entry->copy_id) { ldns_write_uint16(outbuf, ldns_pkt_id(query_pkt)); diff --git a/examples/ldns-testpkts.h b/examples/ldns-testpkts.h index 59e42895275..4941525250f 100644 --- a/examples/ldns-testpkts.h +++ b/examples/ldns-testpkts.h @@ -197,8 +197,9 @@ struct entry { /** * reads the canned reply file and returns a list of structs * does an exit on error. + * @param skip_withespace: skip leftside whitespace. */ -struct entry* read_datafile(const char* name); +struct entry* read_datafile(const char* name, int skip_whitespace); /** * Delete linked list of entries. @@ -217,10 +218,12 @@ void delete_entry(struct entry* list); * later it stores the $ORIGIN value last seen. Often &NULL or the zone * name on first call. * @param prev_rr: previous rr name for correcter parsing. &NULL on first call. + * @param skip_whitespace: skip leftside whitespace. * @return: The entry read (malloced) or NULL if no entry could be read. */ struct entry* read_entry(FILE* in, const char* name, int *lineno, - uint32_t* default_ttl, ldns_rdf** origin, ldns_rdf** prev_rr); + uint32_t* default_ttl, ldns_rdf** origin, ldns_rdf** prev_rr, + int skip_whitespace); /** * finds entry in list, or returns NULL. diff --git a/examples/ldns-update.c b/examples/ldns-update.c index e3047dceb12..dca4cbe7a5c 100644 --- a/examples/ldns-update.c +++ b/examples/ldns-update.c @@ -19,7 +19,7 @@ ldns_update_resolver_new(const char *fqdn, const char *zone, ldns_resolver *r1, *r2; ldns_pkt *query = NULL, *resp; ldns_rr_list *nslist, *iplist; - ldns_rdf *soa_zone, *soa_mname, *ns_name; + ldns_rdf *soa_zone, *soa_mname = NULL, *ns_name; size_t i; ldns_status s; @@ -96,6 +96,7 @@ ldns_update_resolver_new(const char *fqdn, const char *zone, /* Match */ iplist = ldns_get_rr_list_addr_by_name(r1, ns_name, class, 0); (void) ldns_resolver_push_nameserver_rr_list(r2, iplist); + ldns_rr_list_deep_free(iplist); break; } } @@ -109,12 +110,15 @@ ldns_update_resolver_new(const char *fqdn, const char *zone, /* No match, add it now. */ iplist = ldns_get_rr_list_addr_by_name(r1, ns_name, class, 0); (void) ldns_resolver_push_nameserver_rr_list(r2, iplist); + ldns_rr_list_deep_free(iplist); } } ldns_resolver_set_random(r2, false); ldns_pkt_free(resp); ldns_resolver_deep_free(r1); + if (soa_mname) + ldns_rdf_deep_free(soa_mname); return r2; bad: @@ -126,6 +130,8 @@ ldns_update_resolver_new(const char *fqdn, const char *zone, ldns_pkt_free(query); if (resp) ldns_pkt_free(resp); + if (soa_mname) + ldns_rdf_deep_free(soa_mname); return NULL; } @@ -138,7 +144,7 @@ ldns_update_send_simple_addr(const char *fqdn, const char *zone, ldns_pkt *u_pkt = NULL, *r_pkt; ldns_rr_list *up_rrlist; ldns_rr *up_rr; - ldns_rdf *zone_rdf; + ldns_rdf *zone_rdf = NULL; char *rrstr; uint32_t rrstrlen, status = LDNS_STATUS_OK; @@ -231,6 +237,8 @@ ldns_update_send_simple_addr(const char *fqdn, const char *zone, ldns_resolver_deep_free(res); if (u_pkt) ldns_pkt_free(u_pkt); + if (zone_rdf) + ldns_rdf_deep_free(zone_rdf); return LDNS_STATUS_ERR; } @@ -302,8 +310,10 @@ main(int argc, char **argv) printf(";; trying UPDATE with FQDN \"%s\" and IP \"%s\"\n", fqdn, ipaddr ? ipaddr : ""); - printf(";; tsig: \"%s\" \"%s\" \"%s\"\n", tsig_cr.keyname, - tsig_cr.algorithm, tsig_cr.keydata); + if (argc == 6 || argc == 7) { + printf(";; tsig: \"%s\" \"%s\" \"%s\"\n", tsig_cr.keyname, + tsig_cr.algorithm, tsig_cr.keydata); + } ret = ldns_update_send_simple_addr(fqdn, zone, ipaddr, port, defttl, tsig_cred); exit(ret); diff --git a/examples/ldns-verify-zone.1 b/examples/ldns-verify-zone.1.in similarity index 84% rename from examples/ldns-verify-zone.1 rename to examples/ldns-verify-zone.1.in index a4cb767d279..e03b7003eb7 100644 --- a/examples/ldns-verify-zone.1 +++ b/examples/ldns-verify-zone.1.in @@ -37,6 +37,9 @@ Default signatures should just be valid now. A file that contains a trusted DNSKEY or DS rr. This option may be given more than once. +Alternatively, if \fB-k\fR is not specified, and a default trust anchor +(@LDNS_TRUST_ANCHOR_FILE@) exists and contains a valid DNSKEY or DS record, +it will be used as the trust anchor. .TP \fB-p\fR \fI[0-100]\fR Only check this percentage of the zone. @@ -77,6 +80,16 @@ P[n]Y[n]M[n]DT[n]H[n]M[n]S .LP If no file is given standard input is read. +.SH "FILES" +.TP +@LDNS_TRUST_ANCHOR_FILE@ +The file from which trusted keys are loaded for signature chasing, +when no \fB-k\fR option is given. + +.SH "SEE ALSO" +.LP +unbound-anchor(8) + .SH AUTHOR Written by the ldns team as an example for ldns usage. diff --git a/examples/ldns-verify-zone.c b/examples/ldns-verify-zone.c index 1dd9aaea8b6..0bbb97f412b 100644 --- a/examples/ldns-verify-zone.c +++ b/examples/ldns-verify-zone.c @@ -66,10 +66,6 @@ read_key_file(const char *filename, ldns_rr_list *keys) int line_nr; if (!(fp = fopen(filename, "r"))) { - if (verbosity > 0) { - fprintf(myerr, "Error opening %s: %s\n", filename, - strerror(errno)); - } return LDNS_STATUS_FILE_ERR; } while (!feof(fp)) { @@ -92,6 +88,7 @@ read_key_file(const char *filename, ldns_rr_list *keys) else break; } + fclose(fp); return status; } @@ -308,6 +305,10 @@ verify_next_hashed_name(ldns_dnssec_zone* zone, ldns_dnssec_name *name) if (!cur_next_name) { cur_next_name = cur_first_name; } + assert(cur_next_name != NULL); + /* Because this function is called on nsec occurrence, + * there must be a cur_next_name! + */ next_owner_str = ldns_rdf2str(ldns_nsec3_next_owner(name->nsec)); next_owner_dname = ldns_dname_new_frm_str(next_owner_str); @@ -749,7 +750,8 @@ main(int argc, char **argv) "now)\n"); printf("\t-k \tspecify a file that contains a " "trusted DNSKEY or DS rr.\n\t\t\t" - "This option may be given more than once.\n"); + "This option may be given more than once.\n" + "\t\t\tDefault is %s", LDNS_TRUST_ANCHOR_FILE); printf("\t-p [0-100]\tonly checks this percentage of " "the zone.\n\t\t\tDefaults to 100\n"); printf("\t-S\t\tchase signature(s) to a known key. " @@ -794,6 +796,13 @@ main(int argc, char **argv) break; case 'k': s = read_key_file(optarg, keys); + if (s == LDNS_STATUS_FILE_ERR) { + if (verbosity > 0) { + fprintf(myerr, + "Error opening %s: %s\n", + optarg, strerror(errno)); + } + } if (s != LDNS_STATUS_OK) { if (verbosity > 0) { fprintf(myerr, @@ -838,7 +847,7 @@ main(int argc, char **argv) tm.tm_year -= 1900; tm.tm_mon--; - check_time = mktime_from_utc(&tm); + check_time = ldns_mktime_from_utc(&tm); } else { check_time += atoi(optarg); @@ -855,11 +864,16 @@ main(int argc, char **argv) } } if (do_sigchase && nkeys == 0) { - if (verbosity > 0) { - fprintf(myerr, - "Unable to chase signature without keys.\n"); + (void) read_key_file(LDNS_TRUST_ANCHOR_FILE, keys); + nkeys = ldns_rr_list_rr_count(keys); + + if (nkeys == 0) { + if (verbosity > 0) { + fprintf(myerr, "Unable to chase " + "signature without keys.\n"); + } + exit(EXIT_FAILURE); } - exit(EXIT_FAILURE); } argc -= optind; diff --git a/examples/ldns-zsplit.c b/examples/ldns-zsplit.c index 84f2ddb9675..0843c589e9c 100644 --- a/examples/ldns-zsplit.c +++ b/examples/ldns-zsplit.c @@ -63,6 +63,7 @@ open_keyfiles(char **files, uint16_t filec) } if (ldns_rr_new_frm_fp(&k, kfp, NULL, NULL, NULL) != LDNS_STATUS_OK) { fprintf(stderr, "Error parsing the key file %s: %s\n", files[i], strerror(errno)); + ldns_rr_list_deep_free(pubkeys); return NULL; } fclose(kfp); diff --git a/higher.c b/higher.c index c9eb1731ae2..990fb6afb25 100644 --- a/higher.c +++ b/higher.c @@ -126,6 +126,7 @@ ldns_get_rr_list_name_by_addr(ldns_resolver *res, ldns_rdf *addr, ldns_rr_class /* add the RD flags, because we want an answer */ pkt = ldns_resolver_query(res, name, LDNS_RR_TYPE_PTR, c, flags | LDNS_RD); + ldns_rdf_deep_free(name); if (pkt) { /* extract the data we need */ names = ldns_pkt_rr_list_by_type(pkt, diff --git a/host2str.c b/host2str.c index c185e0f04db..521e2468ecd 100644 --- a/host2str.c +++ b/host2str.c @@ -123,6 +123,7 @@ const ldns_output_format *ldns_output_format_onlykeyids = &ldns_output_format_onlykeyids_record; const ldns_output_format *ldns_output_format_default = &ldns_output_format_onlykeyids_record; + const ldns_output_format ldns_output_format_bubblebabble_record = { LDNS_COMMENT_KEY | LDNS_COMMENT_BUBBLEBABBLE | LDNS_COMMENT_FLAGS, NULL }; @@ -195,7 +196,7 @@ ldns_pkt_opcode2str(ldns_pkt_opcode opcode) str = NULL; if (ldns_pkt_opcode2buffer_str(buf, opcode) == LDNS_STATUS_OK) { - str = ldns_buffer2str(buf); + str = ldns_buffer_export2str(buf); } ldns_buffer_free(buf); @@ -215,7 +216,7 @@ ldns_pkt_rcode2str(ldns_pkt_rcode rcode) str = NULL; if (ldns_pkt_rcode2buffer_str(buf, rcode) == LDNS_STATUS_OK) { - str = ldns_buffer2str(buf); + str = ldns_buffer_export2str(buf); } ldns_buffer_free(buf); @@ -236,7 +237,7 @@ ldns_pkt_algorithm2str(ldns_algorithm algorithm) str = NULL; if (ldns_algorithm2buffer_str(buf, algorithm) == LDNS_STATUS_OK) { - str = ldns_buffer2str(buf); + str = ldns_buffer_export2str(buf); } ldns_buffer_free(buf); @@ -257,7 +258,7 @@ ldns_pkt_cert_algorithm2str(ldns_cert_algorithm cert_algorithm) str = NULL; if (ldns_cert_algorithm2buffer_str(buf, cert_algorithm) == LDNS_STATUS_OK) { - str = ldns_buffer2str(buf); + str = ldns_buffer_export2str(buf); } ldns_buffer_free(buf); @@ -567,7 +568,7 @@ ldns_rr_type2str(const ldns_rr_type type) str = NULL; if (ldns_rr_type2buffer_str(buf, type) == LDNS_STATUS_OK) { - str = ldns_buffer2str(buf); + str = ldns_buffer_export2str(buf); } ldns_buffer_free(buf); @@ -603,7 +604,7 @@ ldns_rr_class2str(const ldns_rr_class klass) str = NULL; if (ldns_rr_class2buffer_str(buf, klass) == LDNS_STATUS_OK) { - str = ldns_buffer2str(buf); + str = ldns_buffer_export2str(buf); } ldns_buffer_free(buf); return str; @@ -1149,8 +1150,9 @@ ldns_rdf2buffer_str(ldns_buffer *buffer, const ldns_rdf *rdf) break; } } else { + /** This will write mangled RRs */ ldns_buffer_printf(buffer, "(null) "); - res = ldns_buffer_status(buffer); + res = LDNS_STATUS_ERR; } return res; } @@ -1230,7 +1232,33 @@ ldns_rr2buffer_str_fmt(ldns_buffer *output, for (i = 0; i < ldns_rr_rd_count(rr); i++) { /* ldns_rdf2buffer_str handles NULL input fine! */ - status = ldns_rdf2buffer_str(output, ldns_rr_rdf(rr, i)); + if ((fmt->flags & LDNS_FMT_ZEROIZE_RRSIGS) && + (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) && + ((/* inception */ i == 4 && + ldns_rdf_get_type(ldns_rr_rdf(rr, 4)) == + LDNS_RDF_TYPE_TIME) || + (/* expiration */ i == 5 && + ldns_rdf_get_type(ldns_rr_rdf(rr, 5)) == + LDNS_RDF_TYPE_TIME) || + (/* signature */ i == 8 && + ldns_rdf_get_type(ldns_rr_rdf(rr, 8)) == + LDNS_RDF_TYPE_B64))) { + + ldns_buffer_printf(output, "(null)"); + status = ldns_buffer_status(output); + } else if ((fmt->flags & LDNS_FMT_PAD_SOA_SERIAL) && + (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) && + /* serial */ i == 2 && + ldns_rdf_get_type(ldns_rr_rdf(rr, 2)) == + LDNS_RDF_TYPE_INT32) { + ldns_buffer_printf(output, "%10lu", + (unsigned long) ldns_read_uint32( + ldns_rdf_data(ldns_rr_rdf(rr, 2)))); + status = ldns_buffer_status(output); + } else { + status = ldns_rdf2buffer_str(output, + ldns_rr_rdf(rr, i)); + } if(status != LDNS_STATUS_OK) return status; if (i < ldns_rr_rd_count(rr) - 1) { @@ -1633,12 +1661,12 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) { ldns_status status = LDNS_STATUS_OK; unsigned char *bignum; -#ifndef S_SPLINT_S - uint16_t i; -#endif - #ifdef HAVE_SSL +# ifndef S_SPLINT_S + uint16_t i; +# endif /* not used when ssl is not defined */ + /*@unused@*/ ldns_rdf *b64_bignum = NULL; RSA *rsa; @@ -1716,6 +1744,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) } b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + ldns_rdf_deep_free(b64_bignum); goto error; } ldns_rdf_deep_free(b64_bignum); @@ -1727,6 +1756,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) } b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + ldns_rdf_deep_free(b64_bignum); goto error; } ldns_rdf_deep_free(b64_bignum); @@ -1740,6 +1770,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) } b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + ldns_rdf_deep_free(b64_bignum); goto error; } ldns_rdf_deep_free(b64_bignum); @@ -1756,6 +1787,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) } b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + ldns_rdf_deep_free(b64_bignum); goto error; } ldns_rdf_deep_free(b64_bignum); @@ -1772,6 +1804,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) } b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + ldns_rdf_deep_free(b64_bignum); goto error; } ldns_rdf_deep_free(b64_bignum); @@ -1788,6 +1821,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) } b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + ldns_rdf_deep_free(b64_bignum); goto error; } ldns_rdf_deep_free(b64_bignum); @@ -1804,6 +1838,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) } b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + ldns_rdf_deep_free(b64_bignum); goto error; } ldns_rdf_deep_free(b64_bignum); @@ -1820,6 +1855,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) } b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + ldns_rdf_deep_free(b64_bignum); goto error; } ldns_rdf_deep_free(b64_bignum); @@ -1853,6 +1889,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) } b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + ldns_rdf_deep_free(b64_bignum); goto error; } ldns_rdf_deep_free(b64_bignum); @@ -1869,6 +1906,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) } b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + ldns_rdf_deep_free(b64_bignum); goto error; } ldns_rdf_deep_free(b64_bignum); @@ -1885,6 +1923,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) } b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + ldns_rdf_deep_free(b64_bignum); goto error; } ldns_rdf_deep_free(b64_bignum); @@ -1901,6 +1940,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) } b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + ldns_rdf_deep_free(b64_bignum); goto error; } ldns_rdf_deep_free(b64_bignum); @@ -1917,6 +1957,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) } b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + ldns_rdf_deep_free(b64_bignum); goto error; } ldns_rdf_deep_free(b64_bignum); @@ -1960,6 +2001,7 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) } b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum); if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) { + ldns_rdf_deep_free(b64_bignum); goto error; } ldns_rdf_deep_free(b64_bignum); @@ -1993,9 +2035,6 @@ ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k) } #endif /* HAVE_SSL */ } else { -#ifdef HAVE_SSL - LDNS_FREE(b64_bignum); -#endif LDNS_FREE(bignum); return ldns_buffer_status(output); } @@ -2012,12 +2051,11 @@ error: } /* - * Zero terminate the buffer and fix it to the size of the string. + * Zero terminate the buffer and copy data. */ char * ldns_buffer2str(ldns_buffer *buffer) { - char *tmp_str; char *str; /* check if buffer ends with \0, if not, and @@ -2032,16 +2070,30 @@ ldns_buffer2str(ldns_buffer *buffer) } } - tmp_str = ldns_buffer_export(buffer); - str = LDNS_XMALLOC(char, strlen(tmp_str) + 1); + str = strdup((const char *)ldns_buffer_begin(buffer)); if(!str) { return NULL; } - memcpy(str, tmp_str, strlen(tmp_str) + 1); - return str; } +/* + * Zero terminate the buffer and export data. + */ +char * +ldns_buffer_export2str(ldns_buffer *buffer) +{ + /* Append '\0' as string terminator */ + if (! ldns_buffer_reserve(buffer, 1)) { + return NULL; + } + ldns_buffer_write_u8(buffer, 0); + + /* reallocate memory to the size of the string and export */ + ldns_buffer_set_capacity(buffer, ldns_buffer_position(buffer)); + return ldns_buffer_export(buffer); +} + char * ldns_rdf2str(const ldns_rdf *rdf) { @@ -2053,7 +2105,7 @@ ldns_rdf2str(const ldns_rdf *rdf) } if (ldns_rdf2buffer_str(tmp_buffer, rdf) == LDNS_STATUS_OK) { /* export and return string, destroy rest */ - result = ldns_buffer2str(tmp_buffer); + result = ldns_buffer_export2str(tmp_buffer); } ldns_buffer_free(tmp_buffer); return result; @@ -2071,7 +2123,7 @@ ldns_rr2str_fmt(const ldns_output_format *fmt, const ldns_rr *rr) if (ldns_rr2buffer_str_fmt(tmp_buffer, fmt, rr) == LDNS_STATUS_OK) { /* export and return string, destroy rest */ - result = ldns_buffer2str(tmp_buffer); + result = ldns_buffer_export2str(tmp_buffer); } ldns_buffer_free(tmp_buffer); return result; @@ -2095,7 +2147,7 @@ ldns_pkt2str_fmt(const ldns_output_format *fmt, const ldns_pkt *pkt) if (ldns_pkt2buffer_str_fmt(tmp_buffer, fmt, pkt) == LDNS_STATUS_OK) { /* export and return string, destroy rest */ - result = ldns_buffer2str(tmp_buffer); + result = ldns_buffer_export2str(tmp_buffer); } ldns_buffer_free(tmp_buffer); @@ -2119,7 +2171,7 @@ ldns_key2str(const ldns_key *k) } if (ldns_key2buffer_str(tmp_buffer, k) == LDNS_STATUS_OK) { /* export and return string, destroy rest */ - result = ldns_buffer2str(tmp_buffer); + result = ldns_buffer_export2str(tmp_buffer); } ldns_buffer_free(tmp_buffer); return result; @@ -2149,7 +2201,7 @@ ldns_rr_list2str_fmt(const ldns_output_format *fmt, const ldns_rr_list *list) } /* export and return string, destroy rest */ - result = ldns_buffer2str(tmp_buffer); + result = ldns_buffer_export2str(tmp_buffer); ldns_buffer_free(tmp_buffer); return result; } @@ -2167,20 +2219,20 @@ ldns_rdf_print(FILE *output, const ldns_rdf *rdf) if (str) { fprintf(output, "%s", str); } else { - fprintf(output, "Unable to convert rdf to string\n"); + fprintf(output, ";Unable to convert rdf to string\n"); } LDNS_FREE(str); } void -ldns_rr_print_fmt(FILE *output, +ldns_rr_print_fmt(FILE *output, const ldns_output_format *fmt, const ldns_rr *rr) { char *str = ldns_rr2str_fmt(fmt, rr); if (str) { fprintf(output, "%s", str); } else { - fprintf(output, "Unable to convert rr to string\n"); + fprintf(output, ";Unable to convert rr to string\n"); } LDNS_FREE(str); } @@ -2199,7 +2251,7 @@ ldns_pkt_print_fmt(FILE *output, if (str) { fprintf(output, "%s", str); } else { - fprintf(output, "Unable to convert packet to string\n"); + fprintf(output, ";Unable to convert packet to string\n"); } LDNS_FREE(str); } diff --git a/host2wire.c b/host2wire.c index b5b0ba8ff20..de1e01e9ba3 100644 --- a/host2wire.c +++ b/host2wire.c @@ -341,7 +341,6 @@ ldns_status ldns_rdf2wire(uint8_t **dest, const ldns_rdf *rdf, size_t *result_size) { ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN); - uint8_t *result = NULL; ldns_status status; *result_size = 0; *dest = NULL; @@ -350,21 +349,8 @@ ldns_rdf2wire(uint8_t **dest, const ldns_rdf *rdf, size_t *result_size) status = ldns_rdf2buffer_wire(buffer, rdf); if (status == LDNS_STATUS_OK) { *result_size = ldns_buffer_position(buffer); - result = (uint8_t *) ldns_buffer_export(buffer); - } else { - ldns_buffer_free(buffer); - return status; + *dest = (uint8_t *) ldns_buffer_export(buffer); } - - if (result) { - *dest = LDNS_XMALLOC(uint8_t, ldns_buffer_position(buffer)); - if(!*dest) { - ldns_buffer_free(buffer); - return LDNS_STATUS_MEM_ERR; - } - memcpy(*dest, result, ldns_buffer_position(buffer)); - } - ldns_buffer_free(buffer); return status; } @@ -373,7 +359,6 @@ ldns_status ldns_rr2wire(uint8_t **dest, const ldns_rr *rr, int section, size_t *result_size) { ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN); - uint8_t *result = NULL; ldns_status status; *result_size = 0; *dest = NULL; @@ -382,21 +367,8 @@ ldns_rr2wire(uint8_t **dest, const ldns_rr *rr, int section, size_t *result_size status = ldns_rr2buffer_wire(buffer, rr, section); if (status == LDNS_STATUS_OK) { *result_size = ldns_buffer_position(buffer); - result = (uint8_t *) ldns_buffer_export(buffer); - } else { - ldns_buffer_free(buffer); - return status; + *dest = (uint8_t *) ldns_buffer_export(buffer); } - - if (result) { - *dest = LDNS_XMALLOC(uint8_t, ldns_buffer_position(buffer)); - if(!*dest) { - ldns_buffer_free(buffer); - return LDNS_STATUS_MEM_ERR; - } - memcpy(*dest, result, ldns_buffer_position(buffer)); - } - ldns_buffer_free(buffer); return status; } @@ -405,7 +377,6 @@ ldns_status ldns_pkt2wire(uint8_t **dest, const ldns_pkt *packet, size_t *result_size) { ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN); - uint8_t *result = NULL; ldns_status status; *result_size = 0; *dest = NULL; @@ -414,21 +385,8 @@ ldns_pkt2wire(uint8_t **dest, const ldns_pkt *packet, size_t *result_size) status = ldns_pkt2buffer_wire(buffer, packet); if (status == LDNS_STATUS_OK) { *result_size = ldns_buffer_position(buffer); - result = (uint8_t *) ldns_buffer_export(buffer); - } else { - ldns_buffer_free(buffer); - return status; + *dest = (uint8_t *) ldns_buffer_export(buffer); } - - if (result) { - *dest = LDNS_XMALLOC(uint8_t, ldns_buffer_position(buffer)); - if(!*dest) { - ldns_buffer_free(buffer); - return LDNS_STATUS_MEM_ERR; - } - memcpy(*dest, result, ldns_buffer_position(buffer)); - } - ldns_buffer_free(buffer); return status; } diff --git a/keys.c b/keys.c index 54f26681494..de7c94610d8 100644 --- a/keys.c +++ b/keys.c @@ -431,8 +431,7 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr) ldns_key_free(k); return LDNS_STATUS_ERR; } - ldns_key_set_rsa_key(k, rsa); - RSA_free(rsa); + ldns_key_assign_rsa_key(k, rsa); #endif /* HAVE_SSL */ break; case LDNS_SIGN_DSA: @@ -444,8 +443,7 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr) ldns_key_free(k); return LDNS_STATUS_ERR; } - ldns_key_set_dsa_key(k, dsa); - DSA_free(dsa); + ldns_key_assign_dsa_key(k, dsa); #endif /* HAVE_SSL */ break; case LDNS_SIGN_HMACMD5: @@ -505,6 +503,7 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr) *key = k; return LDNS_STATUS_OK; } + ldns_key_free(k); return LDNS_STATUS_ERR; } @@ -751,28 +750,21 @@ ldns_key_new_frm_fp_hmac_l( FILE *f , size_t *hmac_size ) { - size_t i; - char *d; - unsigned char *buf; - - d = LDNS_XMALLOC(char, LDNS_MAX_LINELEN); - buf = LDNS_XMALLOC(unsigned char, LDNS_MAX_LINELEN); - if(!d || !buf) { - goto error; - } + size_t i, bufsz; + char d[LDNS_MAX_LINELEN]; + unsigned char *buf = NULL; if (ldns_fget_keyword_data_l(f, "Key", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) { goto error; } - i = (size_t) ldns_b64_pton((const char*)d, - buf, - ldns_b64_ntop_calculate_size(strlen(d))); + bufsz = ldns_b64_ntop_calculate_size(strlen(d)); + buf = LDNS_XMALLOC(unsigned char, bufsz); + i = (size_t) ldns_b64_pton((const char*)d, buf, bufsz); *hmac_size = i; return buf; error: - LDNS_FREE(d); LDNS_FREE(buf); *hmac_size = 0; return NULL; @@ -850,6 +842,7 @@ ldns_key_new_frm_algorithm(ldns_signing_algorithm alg, uint16_t size) return NULL; } ldns_key_set_rsa_key(k, r); + RSA_free(r); #endif /* HAVE_SSL */ break; case LDNS_SIGN_DSA: @@ -865,6 +858,7 @@ ldns_key_new_frm_algorithm(ldns_signing_algorithm alg, uint16_t size) return NULL; } ldns_key_set_dsa_key(k, d); + DSA_free(d); #endif /* HAVE_SSL */ break; case LDNS_SIGN_HMACMD5: @@ -1005,6 +999,22 @@ ldns_key_set_dsa_key(ldns_key *k, DSA *d) EVP_PKEY_set1_DSA(key, d); k->_key.key = key; } + +void +ldns_key_assign_rsa_key(ldns_key *k, RSA *r) +{ + EVP_PKEY *key = EVP_PKEY_new(); + EVP_PKEY_assign_RSA(key, r); + k->_key.key = key; +} + +void +ldns_key_assign_dsa_key(ldns_key *k, DSA *d) +{ + EVP_PKEY *key = EVP_PKEY_new(); + EVP_PKEY_assign_DSA(key, d); + k->_key.key = key; +} #endif /* splint */ #endif /* HAVE_SSL */ @@ -1302,7 +1312,7 @@ ldns_key_dsa2bin(unsigned char *data, DSA *k, uint16_t *size) } /* See RFC2536 */ - *size = (uint16_t)BN_num_bytes(k->g); + *size = (uint16_t)BN_num_bytes(k->p); T = (*size - 64) / 8; memcpy(data, &T, 1); @@ -1365,10 +1375,10 @@ ldns_key2rr(const ldns_key *k) #endif int internal_data = 0; - pubkey = ldns_rr_new(); if (!k) { return NULL; } + pubkey = ldns_rr_new(); switch (ldns_key_algorithm(k)) { case LDNS_SIGN_HMACMD5: @@ -1638,7 +1648,7 @@ ldns_key_get_file_base_name(ldns_key *key) "+%03u+%05u", ldns_key_algorithm(key), ldns_key_keytag(key)); - file_base_name = strdup(ldns_buffer_export(buffer)); + file_base_name = ldns_buffer_export(buffer); ldns_buffer_free(buffer); return file_base_name; } diff --git a/ldns/buffer.h b/ldns/buffer.h index 03df14c9915..3b64198d8d5 100644 --- a/ldns/buffer.h +++ b/ldns/buffer.h @@ -630,8 +630,9 @@ void ldns_buffer_free(ldns_buffer *buffer); void *ldns_buffer_export(ldns_buffer *buffer); /** - * Copy contents of the other buffer to this buffer. Silently truncated - * if this buffer is too small. + * Copy contents of the from buffer to the result buffer and then flips + * the result buffer. Data will be silently truncated if the result buffer is + * too small. * \param[out] *result resulting buffer which is copied to. * \param[in] *from what to copy to result. */ diff --git a/ldns/common.h.in b/ldns/common.h.in index 5d6254752a5..aedfc96da7f 100644 --- a/ldns/common.h.in +++ b/ldns/common.h.in @@ -23,6 +23,7 @@ #define LDNS_BUILD_CONFIG_HAVE_INTTYPES_H @ldns_build_config_have_inttypes_h@ #define LDNS_BUILD_CONFIG_HAVE_ATTR_FORMAT @ldns_build_config_have_attr_format@ #define LDNS_BUILD_CONFIG_HAVE_ATTR_UNUSED @ldns_build_config_have_attr_unused@ +#define LDNS_BUILD_CONFIG_HAVE_SOCKLEN_T @ldns_build_config_have_socklen_t@ /* * HAVE_STDBOOL_H is not available when distributed as a library, but no build @@ -65,4 +66,8 @@ typedef bool _Bool; #define ATTR_UNUSED(x) x #endif /* !LDNS_BUILD_CONFIG_HAVE_ATTR_UNUSED */ +#if !LDNS_BUILD_CONFIG_HAVE_SOCKLEN_T +typedef int socklen_t; +#endif + #endif /* LDNS_COMMON_H */ diff --git a/ldns/config.h.in b/ldns/config.h.in index 3393e99767e..98cf357074b 100644 --- a/ldns/config.h.in +++ b/ldns/config.h.in @@ -33,6 +33,12 @@ /* Define to 1 if you have the `ctime_r' function. */ #undef HAVE_CTIME_R +/* Is a CAFILE given at configure time */ +#undef HAVE_DANE_CA_FILE + +/* Is a CAPATH given at configure time */ +#undef HAVE_DANE_CA_PATH + /* Define to 1 if you have the declaration of `NID_secp384r1', and to 0 if you don't. */ #undef HAVE_DECL_NID_SECP384R1 @@ -250,6 +256,15 @@ /* Define to 1 if the system has the type `_Bool'. */ #undef HAVE__BOOL +/* Is a CAFILE given at configure time */ +#undef LDNS_DANE_CA_FILE + +/* Is a CAPATH given at configure time */ +#undef LDNS_DANE_CA_PATH + +/* Default trust anchor file */ +#undef LDNS_TRUST_ANCHOR_FILE + /* Define to the sub-directory in which libtool stores uninstalled libraries. */ #undef LT_OBJDIR diff --git a/ldns/dane.h b/ldns/dane.h new file mode 100644 index 00000000000..c1c4e2d75ca --- /dev/null +++ b/ldns/dane.h @@ -0,0 +1,244 @@ +/* + * dane.h -- defines for the DNS-Based Authentication of Named Entities (DANE) + * Transport Layer Security (TLS) Protocol: TLSA + * + * Copyright (c) 2012, NLnet Labs. All rights reserved. + * + * See LICENSE for the license. + * + */ + +/** + * \file + * + * This module contains base functions for creating and verifying TLSA RR's + * with PKIX certificates, certificate chains and validation stores. + * (See RFC6394 and RFC6698). + * + * Since those functions heavily rely op cryptographic operations, + * this module is dependent on openssl. + */ + + +#ifndef LDNS_DANE_H +#define LDNS_DANE_H + +#include +#include +#include +#if LDNS_BUILD_CONFIG_HAVE_SSL +#include +#include +#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * The different "Certificate usage" rdata field values for a TLSA RR. + */ +enum ldns_enum_tlsa_certificate_usage +{ + /** CA constraint */ + LDNS_TLSA_USAGE_CA_CONSTRAINT = 0, + /** Sevice certificate constraint */ + LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT = 1, + /** Trust anchor assertion */ + LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION = 2, + /** Domain issued certificate */ + LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE = 3 +}; +typedef enum ldns_enum_tlsa_certificate_usage ldns_tlsa_certificate_usage; + +/** + * The different "Selector" rdata field values for a TLSA RR. + */ +enum ldns_enum_tlsa_selector +{ + /** + * Full certificate: the Certificate binary structure + * as defined in [RFC5280] + */ + LDNS_TLSA_SELECTOR_FULL_CERTIFICATE = 0, + + /** + * SubjectPublicKeyInfo: DER-encoded binary structure + * as defined in [RFC5280] + */ + LDNS_TLSA_SELECTOR_SUBJECTPUBLICKEYINFO = 1 +}; +typedef enum ldns_enum_tlsa_selector ldns_tlsa_selector; + +/** + * The different "Matching type" rdata field values for a TLSA RR. + */ +enum ldns_enum_tlsa_matching_type +{ + /** Exact match on selected content */ + LDNS_TLSA_MATCHING_TYPE_NO_HASH_USED = 0, + /** SHA-256 hash of selected content [RFC6234] */ + LDNS_TLSA_MATCHING_TYPE_SHA256 = 1, + /** SHA-512 hash of selected content [RFC6234] */ + LDNS_TLSA_MATCHING_TYPE_SHA512 = 2 +}; +typedef enum ldns_enum_tlsa_matching_type ldns_tlsa_matching_type; + +/** + * Known transports to use with TLSA owner names. + */ +enum ldns_enum_dane_transport +{ + /** TCP */ + LDNS_DANE_TRANSPORT_TCP = 0, + /** UDP */ + LDNS_DANE_TRANSPORT_UDP = 1, + /** SCTP */ + LDNS_DANE_TRANSPORT_SCTP = 2 +}; +typedef enum ldns_enum_dane_transport ldns_dane_transport; + + +/** + * Creates a dname consisting of the given name, prefixed by the service port + * and type of transport: _port._transport.name. + * + * \param[out] tlsa_owner The created dname. + * \param[in] name The dname that should be prefixed. + * \param[in] port The service port number for wich the name should be created. + * \param[in] transport The transport for wich the name should be created. + * \return LDNS_STATUS_OK on success or an error code otherwise. + */ +ldns_status ldns_dane_create_tlsa_owner(ldns_rdf** tlsa_owner, + const ldns_rdf* name, uint16_t port, + ldns_dane_transport transport); + + +#if LDNS_BUILD_CONFIG_HAVE_SSL +/** + * Creates a LDNS_RDF_TYPE_HEX type rdf based on the binary data choosen by + * the selector and encoded using matching_type. + * + * \param[out] rdf The created created rdf of type LDNS_RDF_TYPE_HEX. + * \param[in] cert The certificate from which the data is selected + * \param[in] selector The full certificate or the public key + * \param[in] matching_type The full data or the SHA256 or SHA512 hash + * of the selected data + * \return LDNS_STATUS_OK on success or an error code otherwise. + */ +ldns_status ldns_dane_cert2rdf(ldns_rdf** rdf, X509* cert, + ldns_tlsa_selector selector, + ldns_tlsa_matching_type matching_type); + + +/** + * Selects the certificate from cert, extra_certs or the pkix_validation_store + * based on the value of cert_usage and index. + * + * \param[out] selected_cert The selected cert. + * \param[in] cert The certificate to validate (or not) + * \param[in] extra_certs Intermediate certificates that might be necessary + * during validation. May be NULL, except when the certificate + * usage is "Trust Anchor Assertion" because the trust anchor has + * to be provided.(otherwise choose a "Domain issued certificate!" + * \param[in] pkix_validation_store Used when the certificate usage is + * "CA constraint" or "Service Certificate Constraint" to + * validate the certificate and, in case of "CA constraint", + * select the CA. + * When pkix_validation_store is NULL, validation is explicitely + * turned off and the behaviour is then the same as for "Trust + * anchor assertion" and "Domain issued certificate" respectively. + * \param[in] cert_usage Which certificate to use and how to validate. + * \param[in] index Used to select the trust anchor when certificate usage + * is "Trust Anchor Assertion". 0 is the last certificate in the + * validation chain. 1 the one but last, etc. When index is -1, + * the last certificate is used that MUST be self-signed. + * This can help to make sure that the intended (self signed) + * trust anchor is actually present in extra_certs (which is a + * DANE requirement). + * + * \return LDNS_STATUS_OK on success or an error code otherwise. + */ +ldns_status ldns_dane_select_certificate(X509** selected_cert, + X509* cert, STACK_OF(X509)* extra_certs, + X509_STORE* pkix_validation_store, + ldns_tlsa_certificate_usage cert_usage, int index); + +/** + * Creates a TLSA resource record from the certificate. + * No PKIX validation is performed! The given certificate is used as data + * regardless the value of certificate_usage. + * + * \param[out] tlsa The created TLSA resource record. + * \param[in] certificate_usage The value for the Certificate Usage field + * \param[in] selector The value for the Selector field + * \param[in] matching_type The value for the Matching Type field + * \param[in] cert The certificate which data will be represented + * + * \return LDNS_STATUS_OK on success or an error code otherwise. + */ +ldns_status ldns_dane_create_tlsa_rr(ldns_rr** tlsa, + ldns_tlsa_certificate_usage certificate_usage, + ldns_tlsa_selector selector, + ldns_tlsa_matching_type matching_type, + X509* cert); + +/** + * Verify if the given TLSA resource record matches the given certificate. + * Reporting on a TLSA rr mismatch (LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH) + * is preferred over PKIX failure (LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE). + * So when PKIX validation is required by the TLSA Certificate usage, + * but the TLSA data does not match, LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH + * is returned whether the PKIX validated or not. + * + * \param[in] tlsa_rr The resource record that specifies what and how to + * match the certificate. With tlsa_rr == NULL, regular PKIX + * validation is performed. + * \param[in] cert The certificate to match (and validate) + * \param[in] extra_certs Intermediate certificates that might be necessary + * creating the validation chain. + * \param[in] pkix_validation_store Used when the certificate usage is + * "CA constraint" or "Service Certificate Constraint" to + * validate the certificate. + * + * \return LDNS_STATUS_OK on success, + * LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH on TLSA data mismatch, + * LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE when TLSA matched, + * but the PKIX validation failed, or other ldns_status errors. + */ +ldns_status ldns_dane_verify_rr(const ldns_rr* tlsa_rr, + X509* cert, STACK_OF(X509)* extra_certs, + X509_STORE* pkix_validation_store); + +/** + * Verify if any of the given TLSA resource records matches the given + * certificate. + * + * \param[in] tlsas The resource records that specify what and how to + * match the certificate. One must match for this function + * to succeed. With tlsas == NULL or the number of TLSA records + * in tlsas == 0, regular PKIX validation is performed. + * \param[in] cert The certificate to match (and validate) + * \param[in] extra_certs Intermediate certificates that might be necessary + * creating the validation chain. + * \param[in] pkix_validation_store Used when the certificate usage is + * "CA constraint" or "Service Certificate Constraint" to + * validate the certificate. + * + * \return LDNS_STATUS_OK on success, + * LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE when one of the TLSA's + * matched but the PKIX validation failed, + * LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH when none of the TLSA's matched, + * or other ldns_status errors. + */ +ldns_status ldns_dane_verify(ldns_rr_list* tlsas, + X509* cert, STACK_OF(X509)* extra_certs, + X509_STORE* pkix_validation_store); +#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ + +#ifdef __cplusplus +} +#endif + +#endif /* LDNS_DANE_H */ + diff --git a/ldns/dname.h b/ldns/dname.h index a91f075257c..16b45429fb2 100644 --- a/ldns/dname.h +++ b/ldns/dname.h @@ -111,6 +111,7 @@ ldns_rdf *ldns_dname_new_frm_str(const char *str); * Create a new dname rdf from a string * \param[in] s the size of the new dname * \param[in] *data pointer to the actual data + * * \return ldns_rdf* */ ldns_rdf *ldns_dname_new(uint16_t s, void *data); @@ -119,6 +120,7 @@ ldns_rdf *ldns_dname_new(uint16_t s, void *data); * Create a new dname rdf from data (the data is copied) * \param[in] size the size of the data * \param[in] *data pointer to the actual data + * * \return ldns_rdf* */ ldns_rdf *ldns_dname_new_frm_data(uint16_t size, const void *data); @@ -177,6 +179,13 @@ int ldns_dname_interval(const ldns_rdf *prev, const ldns_rdf *middle, const ldns */ bool ldns_dname_str_absolute(const char *dname_str); +/** + * Checks whether the given dname is absolute (i.e. ends with a '.') + * \param[in] *dname a rdf representing the dname + * \return true or false + */ +bool ldns_dname_absolute(const ldns_rdf *dname); + /** * look inside the rdf and if it is an LDNS_RDF_TYPE_DNAME * try and retrieve a specific label. The labels are numbered diff --git a/ldns/dnssec.h b/ldns/dnssec.h index 9e602b5bc1d..34f63714c34 100644 --- a/ldns/dnssec.h +++ b/ldns/dnssec.h @@ -198,6 +198,7 @@ RSA *ldns_key_buf2rsa_raw(unsigned char* key, size_t len); * * \param[in] *key the key to convert * \param[in] h the hash to use LDNS_SHA1/LDNS_SHA256 + * * \return ldns_rr* a new rr pointer to a DS */ ldns_rr *ldns_key_rr2ds(const ldns_rr *key, ldns_hash h); diff --git a/ldns/dnssec_verify.h b/ldns/dnssec_verify.h index 32036a8c0b0..b6bdeca539b 100644 --- a/ldns/dnssec_verify.h +++ b/ldns/dnssec_verify.h @@ -367,6 +367,7 @@ void ldns_dnssec_derive_trust_tree_no_sig_time( * * \param *tree The trust tree so search * \param *keys A ldns_rr_list of DNSKEY and DS rrs to look for + * * \return LDNS_STATUS_OK if there is a trusted path to one of * the keys, or the *first* error encountered * if there were no paths diff --git a/ldns/dnssec_zone.h b/ldns/dnssec_zone.h index 4d2642fd1b4..70c81b04793 100644 --- a/ldns/dnssec_zone.h +++ b/ldns/dnssec_zone.h @@ -8,7 +8,6 @@ #ifndef LDNS_DNSSEC_ZONE_H #define LDNS_DNSSEC_ZONE_H -#include #include #include diff --git a/ldns/error.h b/ldns/error.h index 6396a934664..bac38ff8714 100644 --- a/ldns/error.h +++ b/ldns/error.h @@ -102,7 +102,22 @@ enum ldns_enum_status { LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG, LDNS_STATUS_MISSING_RDATA_FIELDS_KEY, LDNS_STATUS_CRYPTO_SIG_EXPIRED_WITHIN_MARGIN, - LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED_WITHIN_MARGIN + LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED_WITHIN_MARGIN, + LDNS_STATUS_DANE_STATUS_MESSAGES, + LDNS_STATUS_DANE_UNKNOWN_CERTIFICATE_USAGE, + LDNS_STATUS_DANE_UNKNOWN_SELECTOR, + LDNS_STATUS_DANE_UNKNOWN_MATCHING_TYPE, + LDNS_STATUS_DANE_UNKNOWN_PROTOCOL, + LDNS_STATUS_DANE_UNKNOWN_TRANSPORT, + LDNS_STATUS_DANE_MISSING_EXTRA_CERTS, + LDNS_STATUS_DANE_EXTRA_CERTS_NOT_USED, + LDNS_STATUS_DANE_OFFSET_OUT_OF_RANGE, + LDNS_STATUS_DANE_INSECURE, + LDNS_STATUS_DANE_BOGUS, + LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH, + LDNS_STATUS_DANE_NON_CA_CERTIFICATE, + LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE, + LDNS_STATUS_DANE_PKIX_NO_SELF_SIGNED_TRUST_ANCHOR }; typedef enum ldns_enum_status ldns_status; diff --git a/ldns/host2str.h b/ldns/host2str.h index f0a14a4304a..bbf932767b3 100644 --- a/ldns/host2str.h +++ b/ldns/host2str.h @@ -64,6 +64,8 @@ extern "C" { #define LDNS_COMMENT_LAYOUT 0x0080 /** Also comment KEY_ID with RRSIGS **/ #define LDNS_COMMENT_RRSIGS 0x0100 +#define LDNS_FMT_ZEROIZE_RRSIGS 0x0200 +#define LDNS_FMT_PAD_SOA_SERIAL 0x0400 /** * Output format specifier @@ -601,14 +603,26 @@ char *ldns_rr_list2str_fmt( const ldns_output_format *fmt, const ldns_rr_list *rr_list); /** - * Returns the data in the buffer as a null terminated char * string - * Buffer data must be char * type, and must be freed by the caller + * Returns a copy of the data in the buffer as a null terminated + * char * string. The returned string must be freed by the caller. + * The buffer must be in write modus and may thus not have been flipped. * * \param[in] buffer buffer containing char * data * \return null terminated char * data, or NULL on error */ char *ldns_buffer2str(ldns_buffer *buffer); +/** + * Exports and returns the data in the buffer as a null terminated + * char * string. The returned string must be freed by the caller. + * The buffer must be in write modus and may thus not have been flipped. + * The buffer is fixed after this function returns. + * + * \param[in] buffer buffer containing char * data + * \return null terminated char * data, or NULL on error + */ +char *ldns_buffer_export2str(ldns_buffer *buffer); + /** * Prints the data in the rdata field to the given file stream * (in presentation format) diff --git a/ldns/keys.h b/ldns/keys.h index c4bf536911f..3e156233ba2 100644 --- a/ldns/keys.h +++ b/ldns/keys.h @@ -25,7 +25,6 @@ #if LDNS_BUILD_CONFIG_HAVE_SSL #include #endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ -#include #include #include @@ -299,18 +298,37 @@ void ldns_key_set_algorithm(ldns_key *k, ldns_signing_algorithm l); void ldns_key_set_evp_key(ldns_key *k, EVP_PKEY *e); /** - * Set the key's rsa data + * Set the key's rsa data. + * The rsa data should be freed by the user. * \param[in] k the key * \param[in] r the rsa data */ void ldns_key_set_rsa_key(ldns_key *k, RSA *r); + /** * Set the key's dsa data + * The dsa data should be freed by the user. * \param[in] k the key * \param[in] d the dsa data */ void ldns_key_set_dsa_key(ldns_key *k, DSA *d); +/** + * Assign the key's rsa data + * The rsa data will be freed automatically when the key is freed. + * \param[in] k the key + * \param[in] r the rsa data + */ +void ldns_key_assign_rsa_key(ldns_key *k, RSA *r); + +/** + * Assign the key's dsa data + * The dsa data will be freed automatically when the key is freed. + * \param[in] k the key + * \param[in] d the dsa data + */ +void ldns_key_assign_dsa_key(ldns_key *k, DSA *d); + /** * Get the PKEY id for GOST, loads GOST into openssl as a side effect. * Only available if GOST is compiled into the library and openssl. diff --git a/ldns/ldns.h b/ldns/ldns.h index 79152543348..a41e0325d67 100644 --- a/ldns/ldns.h +++ b/ldns/ldns.h @@ -95,6 +95,7 @@ Or you can just use the menu above to browse through the API docs. #include #include #include +#include #include #include #include diff --git a/ldns/rdata.h b/ldns/rdata.h index 90dcbf13818..229a4d4c5b5 100644 --- a/ldns/rdata.h +++ b/ldns/rdata.h @@ -194,6 +194,7 @@ ldns_rdf_type ldns_rdf_get_type(const ldns_rdf *rd); /** * returns the data of the rdf. * \param[in] *rd the rdf to read from + * * \return uint8_t* pointer to the rdf's data */ uint8_t *ldns_rdf_data(const ldns_rdf *rd); @@ -303,6 +304,7 @@ ldns_rdf *ldns_native2rdf_int32(ldns_rdf_type type, uint32_t value); * The memory is copied, and an LDNS_RDF_TYPE_INT16DATA is returned * \param[in] size the size of the data * \param[in] *data pointer to the actual data + * * \return ldns_rd* the rdf with the data */ ldns_rdf *ldns_native2rdf_int16_data(size_t size, uint8_t *data); diff --git a/ldns/resolver.h b/ldns/resolver.h index f887aaf676e..7af5d401e65 100644 --- a/ldns/resolver.h +++ b/ldns/resolver.h @@ -578,6 +578,7 @@ ldns_status ldns_resolver_push_nameserver_rr_list(ldns_resolver *r, ldns_rr_list * \param[in] t query for this type (may be 0, defaults to A) * \param[in] c query for this class (may be 0, default to IN) * \param[in] flags the query flags + * * \return ldns_pkt* a packet with the reply from the nameserver */ ldns_pkt* ldns_resolver_search(const ldns_resolver *r, const ldns_rdf *rdf, ldns_rr_type t, ldns_rr_class c, uint16_t flags); @@ -590,6 +591,7 @@ ldns_pkt* ldns_resolver_search(const ldns_resolver *r, const ldns_rdf *rdf, ldns * \param[in] t query for this type (may be 0, defaults to A) * \param[in] c query for this class (may be 0, default to IN) * \param[in] f the query flags + * * \return ldns_pkt* a packet with the reply from the nameserver */ ldns_status ldns_resolver_prepare_query_pkt(ldns_pkt **q, ldns_resolver *r, const ldns_rdf *name, ldns_rr_type t, ldns_rr_class c, uint16_t f); @@ -602,6 +604,7 @@ ldns_status ldns_resolver_prepare_query_pkt(ldns_pkt **q, ldns_resolver *r, cons * \param[in] t query for this type (may be 0, defaults to A) * \param[in] c query for this class (may be 0, default to IN) * \param[in] flags the query flags + * * \return ldns_pkt* a packet with the reply from the nameserver */ ldns_status ldns_resolver_send(ldns_pkt **answer, ldns_resolver *r, const ldns_rdf *name, ldns_rr_type t, ldns_rr_class c, uint16_t flags); @@ -621,6 +624,7 @@ ldns_status ldns_resolver_send_pkt(ldns_pkt **answer, ldns_resolver *r, ldns_pkt * \param[in] *t query for this type (may be 0, defaults to A) * \param[in] *c query for this class (may be 0, default to IN) * \param[in] flags the query flags + * * \return ldns_pkt* a packet with the reply from the nameserver * if _defnames is true the default domain will be added */ diff --git a/ldns/rr.h b/ldns/rr.h index 9882931b488..0520dcfe102 100644 --- a/ldns/rr.h +++ b/ldns/rr.h @@ -37,7 +37,7 @@ extern "C" { #define LDNS_RR_OVERHEAD 10 /* The first fields are 'common' and can be referenced instantly */ -#define LDNS_RDATA_FIELD_DESCRIPTORS_COMMON 52 +#define LDNS_RDATA_FIELD_DESCRIPTORS_COMMON 53 @@ -179,6 +179,8 @@ enum ldns_enum_rr_type LDNS_RR_TYPE_NSEC3 = 50, /* RFC 5155 */ LDNS_RR_TYPE_NSEC3PARAM = 51, /* RFC 5155 */ LDNS_RR_TYPE_NSEC3PARAMS = 51, + /** draft-ietf-dane-protocol */ + LDNS_RR_TYPE_TLSA = 52, /** draft-ietf-dnsop-trust-history */ LDNS_RR_TYPE_TALINK = 58, diff --git a/ldns/util.h.in b/ldns/util.h.in index f9fb10420cc..fe4ff3720b0 100644 --- a/ldns/util.h.in +++ b/ldns/util.h.in @@ -268,6 +268,8 @@ const char * ldns_version(void); * \param[in] tm a struct tm* with the date * \return the seconds since epoch */ +time_t ldns_mktime_from_utc(const struct tm *tm); + time_t mktime_from_utc(const struct tm *tm); /** diff --git a/ldns_symbols.def b/ldns_symbols.def deleted file mode 100644 index 1ed0f9e2137..00000000000 --- a/ldns_symbols.def +++ /dev/null @@ -1,783 +0,0 @@ -ldns_algorithm2buffer_str -ldns_algorithms -ldns_axfr_complete -ldns_axfr_last_pkt -ldns_axfr_next -ldns_axfr_start -ldns_b32_ntop -ldns_b32_ntop_ar -ldns_b32_ntop_extended_hex -ldns_b32_pton -ldns_b32_pton_ar -ldns_b32_pton_extended_hex -ldns_b64_ntop -ldns_b64_pton -ldns_bgetc -ldns_bget_keyword_data -ldns_bget_token -ldns_bskipc -ldns_bskipcs -ldns_bubblebabble -ldns_buffer2pkt_wire -ldns_buffer2str -ldns_buffer_copy -ldns_buffer_export -ldns_buffer_free -ldns_buffer_new -ldns_buffer_new_frm_data -ldns_buffer_printf -ldns_buffer_reserve -ldns_buffer_set_capacity -ldns_calc_keytag -ldns_calc_keytag_raw -ldns_cert_algorithm2buffer_str -ldns_cert_algorithms -ldns_convert_dsa_rrsig_asn12rdf -ldns_convert_dsa_rrsig_rdf2asn1 -ldns_convert_ecdsa_rrsig_asn12rdf -ldns_convert_ecdsa_rrsig_rdf2asn1 -ldns_create_empty_rrsig -ldns_create_nsec -ldns_create_nsec3 -ldns_digest_evp -ldns_directive_types -ldns_dname2buffer_wire -ldns_dname2canonical -ldns_dname_cat -ldns_dname_cat_clone -ldns_dname_clone_from -ldns_dname_compare -ldns_dname_compare_v -ldns_dname_interval -ldns_dname_is_subdomain -ldns_dname_is_wildcard -ldns_dname_label -ldns_dname_label_count -ldns_dname_left_chop -ldns_dname_match_wildcard -ldns_dname_new -ldns_dname_new_frm_data -ldns_dname_new_frm_str -ldns_dname_reverse -ldns_dname_str_absolute -ldns_dnssec_build_data_chain -ldns_dnssec_build_data_chain_nokeyname -ldns_dnssec_chain_nsec3_list -ldns_dnssec_create_nsec -ldns_dnssec_create_nsec3 -ldns_dnssec_create_nsec_bitmap -ldns_dnssec_data_chain_deep_free -ldns_dnssec_data_chain_free -ldns_dnssec_data_chain_new -ldns_dnssec_data_chain_print -ldns_dnssec_data_chain_print_fmt -ldns_dnssec_default_add_to_signatures -ldns_dnssec_default_delete_signatures -ldns_dnssec_default_leave_signatures -ldns_dnssec_default_replace_signatures -ldns_dnssec_derive_trust_tree -ldns_dnssec_derive_trust_tree_dnskey_rrset -ldns_dnssec_derive_trust_tree_dnskey_rrset_time -ldns_dnssec_derive_trust_tree_ds_rrset -ldns_dnssec_derive_trust_tree_ds_rrset_time -ldns_dnssec_derive_trust_tree_normal_rrset -ldns_dnssec_derive_trust_tree_normal_rrset_time -ldns_dnssec_derive_trust_tree_no_sig -ldns_dnssec_derive_trust_tree_no_sig_time -ldns_dnssec_derive_trust_tree_time -ldns_dnssec_get_dnskey_for_rrsig -ldns_dnssec_get_rrsig_for_name_and_type -ldns_dnssec_name_add_rr -ldns_dnssec_name_cmp -ldns_dnssec_name_deep_free -ldns_dnssec_name_find_rrset -ldns_dnssec_name_free -ldns_dnssec_name_is_glue -ldns_dnssec_name_name -ldns_dnssec_name_new -ldns_dnssec_name_new_frm_rr -ldns_dnssec_name_node_deep_free -ldns_dnssec_name_node_free -ldns_dnssec_name_node_next_nonglue -ldns_dnssec_name_nsec -ldns_dnssec_name_print -ldns_dnssec_name_print_fmt -ldns_dnssec_name_print_soa -ldns_dnssec_name_print_soa_fmt -ldns_dnssec_name_set_name -ldns_dnssec_name_set_nsec -ldns_dnssec_nsec3_closest_encloser -ldns_dnssec_pkt_get_rrsigs_for_name_and_type -ldns_dnssec_pkt_get_rrsigs_for_type -ldns_dnssec_pkt_has_rrsigs -ldns_dnssec_remove_signatures -ldns_dnssec_rrs_add_rr -ldns_dnssec_rrs_deep_free -ldns_dnssec_rrsets_add_rr -ldns_dnssec_rrsets_contains_type -ldns_dnssec_rrsets_deep_free -ldns_dnssec_rrsets_free -ldns_dnssec_rrsets_new -ldns_dnssec_rrsets_new_frm_rr -ldns_dnssec_rrsets_print -ldns_dnssec_rrsets_print_fmt -ldns_dnssec_rrsets_print_soa -ldns_dnssec_rrsets_print_soa_fmt -ldns_dnssec_rrsets_set_type -ldns_dnssec_rrsets_type -ldns_dnssec_rrs_free -ldns_dnssec_rrs_new -ldns_dnssec_rrs_print -ldns_dnssec_rrs_print_fmt -ldns_dnssec_trust_tree_add_parent -ldns_dnssec_trust_tree_contains_keys -ldns_dnssec_trust_tree_depth -ldns_dnssec_trust_tree_free -ldns_dnssec_trust_tree_new -ldns_dnssec_trust_tree_print -ldns_dnssec_trust_tree_print_fmt -ldns_dnssec_trust_tree_print_sm -ldns_dnssec_trust_tree_print_sm_fmt -ldns_dnssec_verify_denial -ldns_dnssec_verify_denial_nsec3 -ldns_dnssec_zone_add_empty_nonterminals -ldns_dnssec_zone_add_rr -ldns_dnssec_zone_create_nsec3s -ldns_dnssec_zone_create_nsecs -ldns_dnssec_zone_create_rrsigs -ldns_dnssec_zone_create_rrsigs_flg -ldns_dnssec_zone_deep_free -ldns_dnssec_zone_find_nsec3_original -ldns_dnssec_zone_find_rrset -ldns_dnssec_zone_free -ldns_dnssec_zone_is_nsec3_optout -ldns_dnssec_zone_mark_and_get_glue -ldns_dnssec_zone_mark_glue -ldns_dnssec_zone_names_print -ldns_dnssec_zone_names_print_fmt -ldns_dnssec_zone_new -ldns_dnssec_zone_new_frm_fp -ldns_dnssec_zone_new_frm_fp_l -ldns_dnssec_zone_print -ldns_dnssec_zone_print_fmt -ldns_dnssec_zone_sign -ldns_dnssec_zone_sign_flg -ldns_dnssec_zone_sign_nsec3 -ldns_dnssec_zone_sign_nsec3_flg -ldns_dnssec_zone_sign_nsec3_flg_mkmap -ldns_ecdsa2pkey_raw -ldns_edns_flags -ldns_error_str -ldns_fetch_valid_domain_keys -ldns_fetch_valid_domain_keys_time -ldns_fget_keyword_data -ldns_fget_keyword_data_l -ldns_fget_token -ldns_fget_token_l -ldns_fskipc -ldns_fskipcs -ldns_fskipcs_l -ldns_getaddrinfo -ldns_get_bit -ldns_get_bit_r -ldns_get_errorstr_by_id -ldns_get_random -ldns_get_rr_class_by_name -ldns_get_rr_list_addr_by_name -ldns_get_rr_list_hosts_frm_file -ldns_get_rr_list_hosts_frm_fp -ldns_get_rr_list_hosts_frm_fp_l -ldns_get_rr_list_name_by_addr -ldns_get_rr_type_by_name -ldns_get_signing_algorithm_by_name -ldns_gost2pkey_raw -ldns_hexdigit_to_int -ldns_hexstring_to_data -ldns_init_random -ldns_int_to_hexdigit -ldns_is_rrset -ldns_key2buffer_str -ldns_key2rr -ldns_key2str -ldns_key_algorithm -ldns_key_algo_supported -ldns_key_buf2dsa -ldns_key_buf2dsa_raw -ldns_key_buf2rsa -ldns_key_buf2rsa_raw -ldns_key_deep_free -ldns_key_dsa_key -ldns_key_evp_key -ldns_key_EVP_load_gost_id -ldns_key_EVP_unload_gost -ldns_key_expiration -ldns_key_external_key -ldns_key_flags -ldns_key_free -ldns_key_get_file_base_name -ldns_key_hmac_key -ldns_key_hmac_size -ldns_key_inception -ldns_key_keytag -ldns_key_list_free -ldns_key_list_key -ldns_key_list_key_count -ldns_key_list_new -ldns_key_list_pop_key -ldns_key_list_push_key -ldns_key_list_set_key_count -ldns_key_list_set_use -ldns_key_new -ldns_key_new_frm_algorithm -ldns_key_new_frm_engine -ldns_key_new_frm_fp -ldns_key_new_frm_fp_dsa -ldns_key_new_frm_fp_dsa_l -ldns_key_new_frm_fp_hmac -ldns_key_new_frm_fp_hmac_l -ldns_key_new_frm_fp_l -ldns_key_new_frm_fp_rsa -ldns_key_new_frm_fp_rsa_l -ldns_key_origttl -ldns_key_print -ldns_key_pubkey_owner -ldns_key_rr2ds -ldns_key_rsa_key -ldns_key_set_algorithm -ldns_key_set_dsa_key -ldns_key_set_evp_key -ldns_key_set_expiration -ldns_key_set_external_key -ldns_key_set_flags -ldns_key_set_hmac_key -ldns_key_set_hmac_size -ldns_key_set_inception -ldns_key_set_keytag -ldns_key_set_origttl -ldns_key_set_pubkey_owner -ldns_key_set_rsa_key -ldns_key_set_use -ldns_key_use -ldns_lookup_by_id -ldns_lookup_by_name -ldns_native2rdf_int16 -ldns_native2rdf_int16_data -ldns_native2rdf_int32 -ldns_native2rdf_int8 -ldns_nsec3_add_param_rdfs -ldns_nsec3_algorithm -ldns_nsec3_bitmap -ldns_nsec3_flags -ldns_nsec3_hash_name -ldns_nsec3_hash_name_frm_nsec3 -ldns_nsec3_iterations -ldns_nsec3_next_owner -ldns_nsec3_optout -ldns_nsec3_salt -ldns_nsec3_salt_data -ldns_nsec3_salt_length -ldns_nsec_bitmap_covers_type -ldns_nsec_covers_name -ldns_nsec_get_bitmap -ldns_nsec_type_check -ldns_octet -ldns_opcodes -ldns_pkt2buffer_str -ldns_pkt2buffer_str_fmt -ldns_pkt2buffer_wire -ldns_pkt2str -ldns_pkt2str_fmt -ldns_pkt2wire -ldns_pkt_aa -ldns_pkt_ad -ldns_pkt_additional -ldns_pkt_algorithm2str -ldns_pkt_all -ldns_pkt_all_noquestion -ldns_pkt_ancount -ldns_pkt_answer -ldns_pkt_answerfrom -ldns_pkt_arcount -ldns_pkt_authority -ldns_pkt_cd -ldns_pkt_cert_algorithm2str -ldns_pkt_clone -ldns_pkt_edns -ldns_pkt_edns_data -ldns_pkt_edns_do -ldns_pkt_edns_extended_rcode -ldns_pkt_edns_udp_size -ldns_pkt_edns_version -ldns_pkt_edns_z -ldns_pkt_empty -ldns_pkt_free -ldns_pkt_get_opcode -ldns_pkt_get_rcode -ldns_pkt_get_section_clone -ldns_pktheader2buffer_str -ldns_pkt_id -ldns_pkt_new -ldns_pkt_nscount -ldns_pkt_opcode2buffer_str -ldns_pkt_opcode2str -ldns_pkt_print -ldns_pkt_print_fmt -ldns_pkt_push_rr -ldns_pkt_push_rr_list -ldns_pkt_qdcount -ldns_pkt_qr -ldns_pkt_query_new -ldns_pkt_query_new_frm_str -ldns_pkt_querytime -ldns_pkt_question -ldns_pkt_ra -ldns_pkt_rcode2buffer_str -ldns_pkt_rcode2str -ldns_pkt_rd -ldns_pkt_reply_type -ldns_pkt_rr -ldns_pkt_rr_list_by_name -ldns_pkt_rr_list_by_name_and_type -ldns_pkt_rr_list_by_type -ldns_pkt_safe_push_rr -ldns_pkt_safe_push_rr_list -ldns_pkt_section_count -ldns_pkt_set_aa -ldns_pkt_set_ad -ldns_pkt_set_additional -ldns_pkt_set_ancount -ldns_pkt_set_answer -ldns_pkt_set_answerfrom -ldns_pkt_set_arcount -ldns_pkt_set_authority -ldns_pkt_set_cd -ldns_pkt_set_edns_data -ldns_pkt_set_edns_do -ldns_pkt_set_edns_extended_rcode -ldns_pkt_set_edns_udp_size -ldns_pkt_set_edns_version -ldns_pkt_set_edns_z -ldns_pkt_set_flags -ldns_pkt_set_id -ldns_pkt_set_nscount -ldns_pkt_set_opcode -ldns_pkt_set_qdcount -ldns_pkt_set_qr -ldns_pkt_set_querytime -ldns_pkt_set_question -ldns_pkt_set_ra -ldns_pkt_set_random_id -ldns_pkt_set_rcode -ldns_pkt_set_rd -ldns_pkt_set_section_count -ldns_pkt_set_size -ldns_pkt_set_tc -ldns_pkt_set_timestamp -ldns_pkt_set_tsig -ldns_pkt_size -ldns_pkt_tc -ldns_pkt_timestamp -ldns_pkt_tsig -ldns_pkt_tsig_sign -ldns_pkt_tsig_sign_next -ldns_pkt_tsig_verify -ldns_pkt_tsig_verify_next -ldns_pkt_verify -ldns_pkt_verify_time -ldns_print_rr_rdf -ldns_rbtree_create -ldns_rbtree_delete -ldns_rbtree_find_less_equal -ldns_rbtree_first -ldns_rbtree_free -ldns_rbtree_init -ldns_rbtree_insert -ldns_rbtree_insert_vref -ldns_rbtree_join -ldns_rbtree_last -ldns_rbtree_next -ldns_rbtree_null_node -ldns_rbtree_previous -ldns_rbtree_search -ldns_rbtree_split -ldns_rcodes -ldns_rdf2buffer_str -ldns_rdf2buffer_str_a -ldns_rdf2buffer_str_aaaa -ldns_rdf2buffer_str_alg -ldns_rdf2buffer_str_apl -ldns_rdf2buffer_str_b32_ext -ldns_rdf2buffer_str_b64 -ldns_rdf2buffer_str_cert_alg -ldns_rdf2buffer_str_class -ldns_rdf2buffer_str_dname -ldns_rdf2buffer_str_hex -ldns_rdf2buffer_str_int16 -ldns_rdf2buffer_str_int16_data -ldns_rdf2buffer_str_int32 -ldns_rdf2buffer_str_int8 -ldns_rdf2buffer_str_ipseckey -ldns_rdf2buffer_str_loc -ldns_rdf2buffer_str_nsap -ldns_rdf2buffer_str_nsec -ldns_rdf2buffer_str_nsec3_salt -ldns_rdf2buffer_str_period -ldns_rdf2buffer_str_str -ldns_rdf2buffer_str_time -ldns_rdf2buffer_str_tsig -ldns_rdf2buffer_str_tsigtime -ldns_rdf2buffer_str_type -ldns_rdf2buffer_str_unknown -ldns_rdf2buffer_str_wks -ldns_rdf2buffer_wire -ldns_rdf2buffer_wire_canonical -ldns_rdf2native_int16 -ldns_rdf2native_int32 -ldns_rdf2native_int8 -ldns_rdf2native_sockaddr_storage -ldns_rdf2native_time_t -ldns_rdf2rr_type -ldns_rdf2str -ldns_rdf2wire -ldns_rdf_address_reverse -ldns_rdf_clone -ldns_rdf_compare -ldns_rdf_data -ldns_rdf_deep_free -ldns_rdf_free -ldns_rdf_get_type -ldns_rdf_new -ldns_rdf_new_frm_data -ldns_rdf_new_frm_fp -ldns_rdf_new_frm_fp_l -ldns_rdf_new_frm_str -ldns_rdf_print -ldns_rdf_set_data -ldns_rdf_set_size -ldns_rdf_set_type -ldns_rdf_size -ldns_read_anchor_file -ldns_resolver_debug -ldns_resolver_dec_nameserver_count -ldns_resolver_deep_free -ldns_resolver_defnames -ldns_resolver_dnsrch -ldns_resolver_dnssec -ldns_resolver_dnssec_anchors -ldns_resolver_dnssec_cd -ldns_resolver_domain -ldns_resolver_edns_udp_size -ldns_resolver_fail -ldns_resolver_fallback -ldns_resolver_free -ldns_resolver_igntc -ldns_resolver_incr_nameserver_count -ldns_resolver_ip6 -ldns_resolver_nameserver_count -ldns_resolver_nameserver_rtt -ldns_resolver_nameservers -ldns_resolver_nameservers_randomize -ldns_resolver_new -ldns_resolver_new_frm_file -ldns_resolver_new_frm_fp -ldns_resolver_new_frm_fp_l -ldns_resolver_pop_nameserver -ldns_resolver_port -ldns_resolver_prepare_query_pkt -ldns_resolver_print -ldns_resolver_print_fmt -ldns_resolver_push_dnssec_anchor -ldns_resolver_push_nameserver -ldns_resolver_push_nameserver_rr -ldns_resolver_push_nameserver_rr_list -ldns_resolver_push_searchlist -ldns_resolver_query -ldns_resolver_random -ldns_resolver_recursive -ldns_resolver_retrans -ldns_resolver_retry -ldns_resolver_rtt -ldns_resolver_search -ldns_resolver_searchlist -ldns_resolver_searchlist_count -ldns_resolver_send -ldns_resolver_send_pkt -ldns_resolver_set_debug -ldns_resolver_set_defnames -ldns_resolver_set_dnsrch -ldns_resolver_set_dnssec -ldns_resolver_set_dnssec_anchors -ldns_resolver_set_dnssec_cd -ldns_resolver_set_domain -ldns_resolver_set_edns_udp_size -ldns_resolver_set_fail -ldns_resolver_set_fallback -ldns_resolver_set_igntc -ldns_resolver_set_ip6 -ldns_resolver_set_nameserver_count -ldns_resolver_set_nameserver_rtt -ldns_resolver_set_nameservers -ldns_resolver_set_port -ldns_resolver_set_random -ldns_resolver_set_recursive -ldns_resolver_set_retrans -ldns_resolver_set_retry -ldns_resolver_set_rtt -ldns_resolver_set_searchlist_count -ldns_resolver_set_timeout -ldns_resolver_set_tsig_algorithm -ldns_resolver_set_tsig_keydata -ldns_resolver_set_tsig_keyname -ldns_resolver_set_usevc -ldns_resolver_timeout -ldns_resolver_trusted_key -ldns_resolver_tsig_algorithm -ldns_resolver_tsig_keydata -ldns_resolver_tsig_keyname -ldns_resolver_usevc -ldns_rr2buffer_str -ldns_rr2buffer_str_fmt -ldns_rr2buffer_wire -ldns_rr2buffer_wire_canonical -ldns_rr2canonical -ldns_rr2str -ldns_rr2str_fmt -ldns_rr2wire -ldns_rr_a_address -ldns_rr_a_set_address -ldns_rr_class2buffer_str -ldns_rr_class2str -ldns_rr_classes -ldns_rr_clone -ldns_rr_compare -ldns_rr_compare_ds -ldns_rr_compare_no_rdata -ldns_rr_compare_wire -ldns_rr_descript -ldns_rr_descriptor_field_type -ldns_rr_descriptor_maximum -ldns_rr_descriptor_minimum -ldns_rr_dnskey_algorithm -ldns_rr_dnskey_flags -ldns_rr_dnskey_key -ldns_rr_dnskey_key_size -ldns_rr_dnskey_key_size_raw -ldns_rr_dnskey_protocol -ldns_rr_dnskey_set_algorithm -ldns_rr_dnskey_set_flags -ldns_rr_dnskey_set_key -ldns_rr_dnskey_set_protocol -ldns_rr_free -ldns_rr_get_class -ldns_rr_get_type -ldns_rr_label_count -ldns_rr_list2buffer_str -ldns_rr_list2buffer_str_fmt -ldns_rr_list2buffer_wire -ldns_rr_list2canonical -ldns_rr_list2str -ldns_rr_list2str_fmt -ldns_rr_list_cat -ldns_rr_list_cat_clone -ldns_rr_list_clone -ldns_rr_list_compare -ldns_rr_list_contains_rr -ldns_rr_list_deep_free -ldns_rr_list_free -ldns_rr_list_new -ldns_rr_list_owner -ldns_rr_list_pop_rr -ldns_rr_list_pop_rr_list -ldns_rr_list_pop_rrset -ldns_rr_list_print -ldns_rr_list_print_fmt -ldns_rr_list_push_rr -ldns_rr_list_push_rr_list -ldns_rr_list_rr -ldns_rr_list_rr_count -ldns_rr_list_set_rr -ldns_rr_list_set_rr_count -ldns_rr_list_sort -ldns_rr_list_sort_nsec3 -ldns_rr_list_subtype_by_rdf -ldns_rr_list_type -ldns_rr_mx_exchange -ldns_rr_mx_preference -ldns_rr_new -ldns_rr_new_frm_fp -ldns_rr_new_frm_fp_l -ldns_rr_new_frm_str -ldns_rr_new_frm_type -ldns_rr_new_question_frm_str -ldns_rr_ns_nsdname -ldns_rr_owner -ldns_rr_pop_rdf -ldns_rr_print -ldns_rr_print_fmt -ldns_rr_push_rdf -ldns_rr_rdata2buffer_wire -ldns_rr_rd_count -ldns_rr_rdf -ldns_rr_rrsig_algorithm -ldns_rr_rrsig_expiration -ldns_rr_rrsig_inception -ldns_rr_rrsig_keytag -ldns_rr_rrsig_labels -ldns_rr_rrsig_origttl -ldns_rr_rrsig_set_algorithm -ldns_rr_rrsig_set_expiration -ldns_rr_rrsig_set_inception -ldns_rr_rrsig_set_keytag -ldns_rr_rrsig_set_labels -ldns_rr_rrsig_set_origttl -ldns_rr_rrsig_set_sig -ldns_rr_rrsig_set_signame -ldns_rr_rrsig_set_typecovered -ldns_rr_rrsig_sig -ldns_rr_rrsig_signame -ldns_rr_rrsig_typecovered -ldns_rr_set_class -ldns_rr_set_owner -ldns_rr_set_pop_rr -ldns_rr_set_push_rr -ldns_rr_set_rd_count -ldns_rr_set_rdf -ldns_rr_set_ttl -ldns_rr_set_type -ldns_rr_soa_increment -ldns_rr_soa_increment_func -ldns_rr_soa_increment_func_data -ldns_rr_soa_increment_func_int -ldns_rrsig2buffer_wire -ldns_rr_ttl -ldns_rr_type2buffer_str -ldns_rr_type2str -ldns_rr_uncompressed_size -ldns_send -ldns_send_buffer -ldns_serial_arithmitics_gmtime_r -ldns_set_bit -ldns_sha1 -ldns_sha1_final -ldns_sha1_init -ldns_sha1_transform -ldns_sha1_update -ldns_signing_algorithms -ldns_sign_public -ldns_sign_public_buffer -ldns_sign_public_dsa -ldns_sign_public_evp -ldns_sign_public_rsamd5 -ldns_sign_public_rsasha1 -ldns_soa_serial_datecounter -ldns_soa_serial_identity -ldns_soa_serial_increment -ldns_soa_serial_increment_by -ldns_soa_serial_unixtime -ldns_sockaddr_storage2rdf -ldns_str2period -ldns_str2rdf_a -ldns_str2rdf_aaaa -ldns_str2rdf_alg -ldns_str2rdf_apl -ldns_str2rdf_b32_ext -ldns_str2rdf_b64 -ldns_str2rdf_cert_alg -ldns_str2rdf_class -ldns_str2rdf_dname -ldns_str2rdf_hex -ldns_str2rdf_int16 -ldns_str2rdf_int32 -ldns_str2rdf_int8 -ldns_str2rdf_loc -ldns_str2rdf_nsap -ldns_str2rdf_nsec -ldns_str2rdf_nsec3_salt -ldns_str2rdf_period -ldns_str2rdf_service -ldns_str2rdf_str -ldns_str2rdf_time -ldns_str2rdf_tsig -ldns_str2rdf_type -ldns_str2rdf_unknown -ldns_str2rdf_wks -ldns_tcp_bgsend -ldns_tcp_connect -ldns_tcp_read_wire -ldns_tcp_read_wire_timeout -ldns_tcp_send -ldns_tcp_send_query -ldns_traverse_postorder -ldns_tsig_algorithm -ldns_tsig_keydata -ldns_tsig_keydata_clone -ldns_tsig_keyname -ldns_tsig_keyname_clone -ldns_tsig_prepare_pkt_wire -ldns_udp_bgsend -ldns_udp_connect -ldns_udp_read_wire -ldns_udp_send -ldns_udp_send_query -ldns_update_ad -ldns_update_pkt_new -ldns_update_pkt_tsig_add -ldns_update_prcount -ldns_update_set_adcount -ldns_update_set_prcount -ldns_update_set_upcount -ldns_update_set_zo -ldns_update_soa_mname -ldns_update_soa_zone_mname -ldns_update_upcount -ldns_update_zocount -ldns_validate_domain_dnskey -ldns_validate_domain_dnskey_time -ldns_validate_domain_ds -ldns_validate_domain_ds_time -ldns_verify -ldns_verify_notime -ldns_verify_rrsig -ldns_verify_rrsig_buffers -ldns_verify_rrsig_buffers_raw -ldns_verify_rrsig_dsa -ldns_verify_rrsig_dsa_raw -ldns_verify_rrsig_evp -ldns_verify_rrsig_evp_raw -ldns_verify_rrsig_keylist -ldns_verify_rrsig_keylist_notime -ldns_verify_rrsig_keylist_time -ldns_verify_rrsig_rsamd5 -ldns_verify_rrsig_rsamd5_raw -ldns_verify_rrsig_rsasha1 -ldns_verify_rrsig_rsasha1_raw -ldns_verify_rrsig_rsasha256_raw -ldns_verify_rrsig_rsasha512_raw -ldns_verify_rrsig_time -ldns_verify_time -ldns_verify_trusted -ldns_verify_trusted_time -ldns_version -ldns_wire2dname -ldns_wire2pkt -ldns_wire2rdf -ldns_wire2rr -ldns_zone_deep_free -ldns_zone_free -ldns_zone_glue_rr_list -ldns_zone_new -ldns_zone_new_frm_fp -ldns_zone_new_frm_fp_l -ldns_zone_print -ldns_zone_print_fmt -ldns_zone_push_rr -ldns_zone_push_rr_list -ldns_zone_rr_count -ldns_zone_rrs -ldns_zone_set_rrs -ldns_zone_set_soa -ldns_zone_sign -ldns_zone_sign_nsec3 -ldns_zone_soa -ldns_zone_sort -ldns_zone_strip_glue_rrs diff --git a/libdns.doxygen b/libdns.doxygen index 3325db94af4..0f84b73435e 100644 --- a/libdns.doxygen +++ b/libdns.doxygen @@ -1,4 +1,4 @@ -# Doxyfile 1.7.3 +# Doxyfile 1.7.6.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. @@ -22,8 +22,9 @@ DOXYFILE_ENCODING = UTF-8 -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. +# The PROJECT_NAME tag is a single word (or sequence of words) that should +# identify the project. Note that if you do not use Doxywizard you need +# to put quotes around the project name if it contains spaces. PROJECT_NAME = ldns @@ -33,7 +34,9 @@ PROJECT_NAME = ldns PROJECT_NUMBER = 1.6.7 -# Using the PROJECT_BRIEF tag one can provide an optional one line description for a project that appears at the top of each page and should give viewer a quick idea about the purpose of the project. Keep the description short. +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer +# a quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = @@ -192,6 +195,13 @@ TAB_SIZE = 8 ALIASES = +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding +# "class=itcl::class" will allow you to use the command class in the +# itcl::class meaning. + +TCL_SUBST = + # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list @@ -274,6 +284,22 @@ DISTRIBUTE_GROUP_DOC = NO SUBGROUPING = YES +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and +# unions are shown inside the group in which they are included (e.g. using +# @ingroup) instead of on a separate page (for HTML and Man pages) or +# section (for LaTeX and RTF). + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and +# unions with only public data fields will be shown inline in the documentation +# of the scope in which they are defined (i.e. file, namespace, or group +# documentation), provided this scope is documented. If set to NO (the default), +# structs, classes, and unions are shown on a separate page (for HTML and Man +# pages) or section (for LaTeX and RTF). + +INLINE_SIMPLE_STRUCTS = NO + # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct @@ -296,10 +322,21 @@ TYPEDEF_HIDES_STRUCT = NO # a logarithmic scale so increasing the size by one will roughly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols +# corresponding to a cache size of 2^16 = 65536 symbols. SYMBOL_CACHE_SIZE = 0 +# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be +# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given +# their name and scope. Since this can be an expensive process and often the +# same symbol appear multiple times in the code, doxygen keeps a cache of +# pre-resolved symbols. If the cache is too small doxygen will become slower. +# If the cache is too large, memory is wasted. The cache size is given by this +# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +LOOKUP_CACHE_SIZE = 0 + #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- @@ -449,8 +486,11 @@ SORT_GROUP_NAMES = NO SORT_BY_SCOPE_NAME = NO -# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper type resolution of all parameters of a function it will reject a -# match between the prototype and the implementation of a member function even if there is only one candidate or it is obvious which candidate to choose by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to +# do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even +# if there is only one candidate or it is obvious which candidate to choose +# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen # will still accept a match between prototype and implementation in such cases. STRICT_PROTO_MATCHING = NO @@ -538,6 +578,16 @@ FILE_VERSION_FILTER = LAYOUT_FILE = +# The CITE_BIB_FILES tag can be used to specify one or more bib files +# containing the references data. This must be a list of .bib files. The +# .bib extension is automatically appended if omitted. Using this command +# requires the bibtex tool to be installed. See also +# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style +# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this +# feature you need bibtex and perl available in the search path. + +CITE_BIB_FILES = + #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- @@ -629,13 +679,15 @@ FILE_PATTERNS = RECURSIVE = NO -# The EXCLUDE tag can be used to specify files and/or directories that should +# The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. +# Note that relative paths are relative to the directory from which doxygen is +# run. EXCLUDE = -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. @@ -821,7 +873,14 @@ HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a -# standard header. +# standard header. Note that when using a custom header you are responsible +# for the proper inclusion of any scripts and style sheets that doxygen +# needs, which is dependent on the configuration options used. +# It is advised to generate a default header using "doxygen -w html +# header.html footer.html stylesheet.css YourConfigFile" and then modify +# that header. Note that the header is subject to change so you typically +# have to redo this when upgrading to a newer version of doxygen or when +# changing the value of configuration settings such as GENERATE_TREEVIEW! HTML_HEADER = doc/header.html @@ -836,12 +895,21 @@ HTML_FOOTER = # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own -# stylesheet in the HTML output directory as well, or it will be erased! +# style sheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that +# the files will be copied as-is; there are no commands or markers available. + +HTML_EXTRA_FILES = + # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. -# Doxygen will adjust the colors in the stylesheet and background images +# Doxygen will adjust the colors in the style sheet and background images # according to this color. Hue is specified as an angle on a colorwheel, # see http://en.wikipedia.org/wiki/Hue for more information. # For instance the value 0 represents red, 60 is yellow, 120 is green, @@ -871,12 +939,6 @@ HTML_COLORSTYLE_GAMMA = 80 HTML_TIMESTAMP = YES -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports @@ -1036,18 +1098,14 @@ GENERATE_ECLIPSEHELP = NO ECLIPSE_DOC_ID = org.doxygen.Project -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. +# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) +# at top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. Since the tabs have the same information as the +# navigation tree you can set this option to NO if you already set +# GENERATE_TREEVIEW to YES. DISABLE_INDEX = NO -# This tag can be used to set the number of enum values (range [0,1..20]) -# that doxygen will group on one line in the generated HTML documentation. -# Note that a value of 0 will completely suppress the enum values from appearing in the overview section. - -ENUM_VALUES_PER_LINE = 4 - # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to YES, a side panel will be generated @@ -1055,13 +1113,17 @@ ENUM_VALUES_PER_LINE = 4 # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. +# Since the tree basically has the same information as the tab index you +# could consider to set DISABLE_INDEX to NO when enabling this option. GENERATE_TREEVIEW = NO -# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, -# and Class Hierarchy pages using a tree view instead of an ordered list. +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values +# (range [0,1..20]) that doxygen will group on one line in the generated HTML +# documentation. Note that a value of 0 will completely suppress the enum +# values from appearing in the overview section. -USE_INLINE_TREES = NO +ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree @@ -1103,12 +1165,18 @@ USE_MATHJAX = NO # HTML output directory using the MATHJAX_RELPATH option. The destination # directory should contain the MathJax.js script. For instance, if the mathjax # directory is located at the same level as the HTML output directory, then -# MATHJAX_RELPATH should be ../mathjax. The default value points to the mathjax.org site, so you can quickly see the result without installing +# MATHJAX_RELPATH should be ../mathjax. The default value points to the +# mathjax.org site, so you can quickly see the result without installing # MathJax, but it is strongly recommended to install a local copy of MathJax # before deployment. MATHJAX_RELPATH = http://www.mathjax.org/mathjax +# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension +# names that should be enabled during MathJax rendering. + +MATHJAX_EXTENSIONS = + # When the SEARCHENGINE tag is enabled doxygen will generate a search box # for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using @@ -1182,6 +1250,13 @@ EXTRA_PACKAGES = LATEX_HEADER = +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for +# the generated latex document. The footer should contain everything after +# the last chapter. If it is left blank doxygen will generate a +# standard footer. Notice: only use this tag if you know what you are doing! + +LATEX_FOOTER = + # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references @@ -1215,6 +1290,12 @@ LATEX_HIDE_INDICES = NO LATEX_SOURCE_CODE = NO +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See +# http://en.wikipedia.org/wiki/BibTeX for more info. + +LATEX_BIB_STYLE = plain + #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- @@ -1246,7 +1327,7 @@ COMPACT_RTF = NO RTF_HYPERLINKS = NO -# Load stylesheet definitions from file. Syntax is similar to doxygen's +# Load style sheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. @@ -1391,7 +1472,7 @@ MACRO_EXPANSION = YES EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# in the INCLUDE_PATH (see below) will be search if a #include is found. +# pointed to by INCLUDE_PATH will be searched when a #include is found. SEARCH_INCLUDES = YES @@ -1399,7 +1480,7 @@ SEARCH_INCLUDES = YES # contain include files that are not input files but should be processed by # the preprocessor. -INCLUDE_PATH = +INCLUDE_PATH = . # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the @@ -1421,7 +1502,8 @@ PREDEFINED = HAVE_SSL # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition that overrules the definition found in the source code. +# Use the PREDEFINED tag if you want to use a different macro definition that +# overrules the definition found in the source code. EXPAND_AS_DEFINED = @@ -1519,13 +1601,12 @@ HAVE_DOT = NO DOT_NUM_THREADS = 0 -# By default doxygen will write a font called Helvetica to the output -# directory and reference it in all dot files that doxygen generates. -# When you want a differently looking font you can specify the font name -# using DOT_FONTNAME. You need to make sure dot is able to find the font, -# which can be done by putting it in a standard location or by setting the -# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory -# containing the font. +# By default doxygen will use the Helvetica font for all dot files that +# doxygen generates. When you want a differently looking font you can specify +# the font name using DOT_FONTNAME. You need to make sure dot is able to find +# the font, which can be done by putting it in a standard location or by setting +# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. DOT_FONTNAME = Helvetica @@ -1534,17 +1615,16 @@ DOT_FONTNAME = Helvetica DOT_FONTSIZE = 10 -# By default doxygen will tell dot to use the output directory to look for the -# FreeSans.ttf font (which doxygen will put there itself). If you specify a -# different font using DOT_FONTNAME you can set the path where dot -# can find it using this tag. +# By default doxygen will tell dot to use the Helvetica font. +# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to +# set the path where dot can find it. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the -# the CLASS_DIAGRAMS tag to NO. +# CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES @@ -1614,11 +1694,22 @@ GRAPHICAL_HIERARCHY = YES DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are png, svg, gif or svg. -# If left blank png will be used. +# generated by dot. Possible values are svg, png, jpg, or gif. +# If left blank png will be used. If you choose svg you need to set +# HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible in IE 9+ (other browsers do not have this requirement). DOT_IMAGE_FORMAT = png +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# Note that this requires a modern browser other than Internet Explorer. +# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you +# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible. Older versions of IE do not have SVG support. + +INTERACTIVE_SVG = NO + # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. diff --git a/net.c b/net.c index 870511a75b2..6b444da677b 100644 --- a/net.c +++ b/net.c @@ -110,12 +110,14 @@ ldns_send_buffer(ldns_pkt **result, ldns_resolver *r, ldns_buffer *qb, ldns_rdf if ((ns->ss_family == AF_INET) && (ldns_resolver_ip6(r) == LDNS_RESOLV_INET6)) { /* not reachable */ + LDNS_FREE(ns); continue; } if ((ns->ss_family == AF_INET6) && (ldns_resolver_ip6(r) == LDNS_RESOLV_INET)) { /* not reachable */ + LDNS_FREE(ns); continue; } #endif @@ -182,7 +184,8 @@ ldns_send_buffer(ldns_pkt **result, ldns_resolver *r, ldns_buffer *qb, ldns_rdf ldns_pkt_set_querytime(reply, (uint32_t) ((tv_e.tv_sec - tv_s.tv_sec) * 1000) + (tv_e.tv_usec - tv_s.tv_usec) / 1000); - ldns_pkt_set_answerfrom(reply, ns_array[i]); + ldns_pkt_set_answerfrom(reply, + ldns_rdf_clone(ns_array[i])); ldns_pkt_set_timestamp(reply, tv_s); ldns_pkt_set_size(reply, reply_size); break; @@ -203,7 +206,7 @@ ldns_send_buffer(ldns_pkt **result, ldns_resolver *r, ldns_buffer *qb, ldns_rdf return LDNS_STATUS_RES_NO_NS; } #ifdef HAVE_SSL - if (tsig_mac && reply_bytes) { + if (tsig_mac && reply && reply_bytes) { if (!ldns_pkt_tsig_verify(reply, reply_bytes, reply_size, @@ -470,7 +473,7 @@ ldns_tcp_send_query(ldns_buffer *qbin, int sockfd, sendbuf = LDNS_XMALLOC(uint8_t, ldns_buffer_position(qbin) + 2); if(!sendbuf) return 0; ldns_write_uint16(sendbuf, ldns_buffer_position(qbin)); - memcpy(sendbuf + 2, ldns_buffer_export(qbin), ldns_buffer_position(qbin)); + memcpy(sendbuf + 2, ldns_buffer_begin(qbin), ldns_buffer_position(qbin)); bytes = sendto(sockfd, (void*)sendbuf, ldns_buffer_position(qbin) + 2, 0, (struct sockaddr *)to, tolen); @@ -669,7 +672,7 @@ ldns_tcp_send(uint8_t **result, ldns_buffer *qbin, const struct sockaddr_storag } /* resize accordingly */ - *result = (uint8_t*)LDNS_XREALLOC(answer, uint8_t *, (size_t)*answer_size); + *result = LDNS_XREALLOC(answer, uint8_t, (size_t)*answer_size); if(!*result) { LDNS_FREE(answer); return LDNS_STATUS_MEM_ERR; @@ -807,6 +810,9 @@ ldns_axfr_start(ldns_resolver *resolver, ldns_rdf *domain, ldns_rr_class class) ns_i < ldns_resolver_nameserver_count(resolver) && resolver->_socket == 0; ns_i++) { + if (ns != NULL) { + LDNS_FREE(ns); + } ns = ldns_rdf2native_sockaddr_storage( resolver->_nameservers[ns_i], ldns_resolver_port(resolver), &ns_len); @@ -837,6 +843,9 @@ ldns_axfr_start(ldns_resolver *resolver, ldns_rdf *domain, ldns_rr_class class) #endif resolver->_socket = 0; + ldns_pkt_free(query); + LDNS_FREE(ns); + return LDNS_STATUS_CRYPTO_TSIG_ERR; } } diff --git a/packet.c b/packet.c index 0ac5ca8ba31..b44c0add645 100644 --- a/packet.c +++ b/packet.c @@ -255,7 +255,6 @@ ldns_pkt_rr_list_by_name(ldns_pkt *packet, ldns_pkt_section sec) { ldns_rr_list *rrs; - ldns_rr_list *new; ldns_rr_list *ret; uint16_t i; @@ -264,7 +263,6 @@ ldns_pkt_rr_list_by_name(ldns_pkt *packet, } rrs = ldns_pkt_get_section_clone(packet, sec); - new = ldns_rr_list_new(); ret = NULL; for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) { @@ -272,8 +270,10 @@ ldns_pkt_rr_list_by_name(ldns_pkt *packet, ldns_rr_list_rr(rrs, i)), ownername) == 0) { /* owner names match */ - ldns_rr_list_push_rr(new, ldns_rr_list_rr(rrs, i)); - ret = new; + if (ret == NULL) { + ret = ldns_rr_list_new(); + } + ldns_rr_list_push_rr(ret, ldns_rr_list_rr(rrs, i)); } } return ret; @@ -649,19 +649,27 @@ ldns_pkt_push_rr(ldns_pkt *packet, ldns_pkt_section section, ldns_rr *rr) { switch(section) { case LDNS_SECTION_QUESTION: - ldns_rr_list_push_rr(ldns_pkt_question(packet), rr); + if (!ldns_rr_list_push_rr(ldns_pkt_question(packet), rr)) { + return false; + } ldns_pkt_set_qdcount(packet, ldns_pkt_qdcount(packet) + 1); break; case LDNS_SECTION_ANSWER: - ldns_rr_list_push_rr(ldns_pkt_answer(packet), rr); + if (!ldns_rr_list_push_rr(ldns_pkt_answer(packet), rr)) { + return false; + } ldns_pkt_set_ancount(packet, ldns_pkt_ancount(packet) + 1); break; case LDNS_SECTION_AUTHORITY: - ldns_rr_list_push_rr(ldns_pkt_authority(packet), rr); + if (!ldns_rr_list_push_rr(ldns_pkt_authority(packet), rr)) { + return false; + } ldns_pkt_set_nscount(packet, ldns_pkt_nscount(packet) + 1); break; case LDNS_SECTION_ADDITIONAL: - ldns_rr_list_push_rr(ldns_pkt_additional(packet), rr); + if (!ldns_rr_list_push_rr(ldns_pkt_additional(packet), rr)) { + return false; + } ldns_pkt_set_arcount(packet, ldns_pkt_arcount(packet) + 1); break; case LDNS_SECTION_ANY: @@ -783,6 +791,7 @@ ldns_pkt_free(ldns_pkt *packet) ldns_rr_list_deep_free(packet->_additional); ldns_rr_free(packet->_tsig_rr); ldns_rdf_deep_free(packet->_edns_data); + ldns_rdf_deep_free(packet->_answerfrom); LDNS_FREE(packet); } } @@ -817,6 +826,86 @@ ldns_pkt_set_flags(ldns_pkt *packet, uint16_t flags) return true; } + +static ldns_status +ldns_pkt_add_authsoa(ldns_pkt* packet, ldns_rdf* rr_name, ldns_rr_class rr_class) +{ + ldns_rr* soa_rr = ldns_rr_new(); + ldns_rdf *owner_rdf; + ldns_rdf *mname_rdf; + ldns_rdf *rname_rdf; + ldns_rdf *serial_rdf; + ldns_rdf *refresh_rdf; + ldns_rdf *retry_rdf; + ldns_rdf *expire_rdf; + ldns_rdf *minimum_rdf; + + if (!soa_rr) { + return LDNS_STATUS_MEM_ERR; + } + owner_rdf = ldns_rdf_clone(rr_name); + if (!owner_rdf) { + ldns_rr_free(soa_rr); + return LDNS_STATUS_MEM_ERR; + } + + ldns_rr_set_owner(soa_rr, owner_rdf); + ldns_rr_set_type(soa_rr, LDNS_RR_TYPE_SOA); + ldns_rr_set_class(soa_rr, rr_class); + ldns_rr_set_question(soa_rr, false); + + if (ldns_str2rdf_dname(&mname_rdf, ".") != LDNS_STATUS_OK) { + ldns_rr_free(soa_rr); + return LDNS_STATUS_MEM_ERR; + } else { + ldns_rr_push_rdf(soa_rr, mname_rdf); + } + if (ldns_str2rdf_dname(&rname_rdf, ".") != LDNS_STATUS_OK) { + ldns_rr_free(soa_rr); + return LDNS_STATUS_MEM_ERR; + } else { + ldns_rr_push_rdf(soa_rr, rname_rdf); + } + serial_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0); + if (!serial_rdf) { + ldns_rr_free(soa_rr); + return LDNS_STATUS_MEM_ERR; + } else { + ldns_rr_push_rdf(soa_rr, serial_rdf); + } + refresh_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0); + if (!refresh_rdf) { + ldns_rr_free(soa_rr); + return LDNS_STATUS_MEM_ERR; + } else { + ldns_rr_push_rdf(soa_rr, refresh_rdf); + } + retry_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0); + if (!retry_rdf) { + ldns_rr_free(soa_rr); + return LDNS_STATUS_MEM_ERR; + } else { + ldns_rr_push_rdf(soa_rr, retry_rdf); + } + expire_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0); + if (!expire_rdf) { + ldns_rr_free(soa_rr); + return LDNS_STATUS_MEM_ERR; + } else { + ldns_rr_push_rdf(soa_rr, expire_rdf); + } + minimum_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0); + if (!minimum_rdf) { + ldns_rr_free(soa_rr); + return LDNS_STATUS_MEM_ERR; + } else { + ldns_rr_push_rdf(soa_rr, minimum_rdf); + } + ldns_pkt_push_rr(packet, LDNS_SECTION_AUTHORITY, soa_rr); + return LDNS_STATUS_OK; +} + + ldns_status ldns_pkt_query_new_frm_str(ldns_pkt **p, const char *name, ldns_rr_type rr_type, ldns_rr_class rr_class, uint16_t flags) @@ -851,21 +940,29 @@ ldns_pkt_query_new_frm_str(ldns_pkt **p, const char *name, ldns_rr_type rr_type, ldns_rr_set_type(question_rr, rr_type); ldns_rr_set_class(question_rr, rr_class); ldns_rr_set_question(question_rr, true); - + ldns_pkt_push_rr(packet, LDNS_SECTION_QUESTION, question_rr); } else { ldns_rr_free(question_rr); ldns_pkt_free(packet); return LDNS_STATUS_ERR; } - + + /** IXFR? */ + if (rr_type == LDNS_RR_TYPE_IXFR) { + if (ldns_pkt_add_authsoa(packet, name_rdf, rr_class) != LDNS_STATUS_OK) { + ldns_pkt_free(packet); + return LDNS_STATUS_ERR; + } + } + packet->_tsig_rr = NULL; - ldns_pkt_set_answerfrom(packet, NULL); if (p) { *p = packet; return LDNS_STATUS_OK; } else { + ldns_pkt_free(packet); return LDNS_STATUS_NULL; } } @@ -888,6 +985,7 @@ ldns_pkt_query_new(ldns_rdf *rr_name, ldns_rr_type rr_type, ldns_rr_class rr_cla question_rr = ldns_rr_new(); if (!question_rr) { + ldns_pkt_free(packet); return NULL; } @@ -902,11 +1000,17 @@ ldns_pkt_query_new(ldns_rdf *rr_name, ldns_rr_type rr_type, ldns_rr_class rr_cla ldns_rr_set_type(question_rr, rr_type); ldns_rr_set_class(question_rr, rr_class); ldns_rr_set_question(question_rr, true); - - packet->_tsig_rr = NULL; - ldns_pkt_push_rr(packet, LDNS_SECTION_QUESTION, question_rr); + /** IXFR? */ + if (rr_type == LDNS_RR_TYPE_IXFR) { + if (ldns_pkt_add_authsoa(packet, rr_name, rr_class) != LDNS_STATUS_OK) { + ldns_pkt_free(packet); + return NULL; + } + } + + packet->_tsig_rr = NULL; return packet; } @@ -980,7 +1084,9 @@ ldns_pkt_clone(ldns_pkt *pkt) ldns_pkt_set_ancount(new_pkt, ldns_pkt_ancount(pkt)); ldns_pkt_set_nscount(new_pkt, ldns_pkt_nscount(pkt)); ldns_pkt_set_arcount(new_pkt, ldns_pkt_arcount(pkt)); - ldns_pkt_set_answerfrom(new_pkt, ldns_pkt_answerfrom(pkt)); + if (ldns_pkt_answerfrom(pkt)) + ldns_pkt_set_answerfrom(new_pkt, + ldns_rdf_clone(ldns_pkt_answerfrom(pkt))); ldns_pkt_set_querytime(new_pkt, ldns_pkt_querytime(pkt)); ldns_pkt_set_size(new_pkt, ldns_pkt_size(pkt)); ldns_pkt_set_tsig(new_pkt, ldns_rr_clone(ldns_pkt_tsig(pkt))); diff --git a/parse.c b/parse.c index ac9bdbdd556..ea5ffad026f 100644 --- a/parse.c +++ b/parse.c @@ -161,7 +161,7 @@ ldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *li return (ssize_t)i; tokenread: - ldns_fskipcs_l(f, delim, line_nr); + ldns_fskipcs_l(f, del, line_nr); *t = '\0'; if (p != 0) { return -1; @@ -331,7 +331,7 @@ ldns_bget_token(ldns_buffer *b, char *token, const char *delim, size_t limit) return (ssize_t)i; tokenread: - ldns_bskipcs(b, delim); + ldns_bskipcs(b, del); *t = '\0'; if (p != 0) { diff --git a/resolver.c b/resolver.c index 1a788a363fe..2cee9fff194 100644 --- a/resolver.c +++ b/resolver.c @@ -253,13 +253,20 @@ ldns_resolver_pop_nameserver(ldns_resolver *r) pop = nameservers[ns_count - 1]; - nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *, (ns_count - 1)); - rtt = LDNS_XREALLOC(rtt, size_t, (ns_count - 1)); + if (ns_count == 1) { + LDNS_FREE(nameservers); + LDNS_FREE(rtt); + + ldns_resolver_set_nameservers(r, NULL); + ldns_resolver_set_rtt(r, NULL); + } else { + nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *, + (ns_count - 1)); + rtt = LDNS_XREALLOC(rtt, size_t, (ns_count - 1)); - if(nameservers) ldns_resolver_set_nameservers(r, nameservers); - if(rtt) ldns_resolver_set_rtt(r, rtt); + } /* decr the count */ ldns_resolver_dec_nameserver_count(r); return pop; @@ -385,7 +392,9 @@ ldns_resolver_push_dnssec_anchor(ldns_resolver *r, ldns_rr *rr) { ldns_rr_list * trust_anchors; - if ((!rr) || (ldns_rr_get_type(rr) != LDNS_RR_TYPE_DNSKEY)) { + if ((!rr) || (ldns_rr_get_type(rr) != LDNS_RR_TYPE_DNSKEY && + ldns_rr_get_type(rr) != LDNS_RR_TYPE_DS)) { + return LDNS_STATUS_ERR; } @@ -800,8 +809,7 @@ ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr) gtr -= bgtr; if(word[0] == '#') { expect = LDNS_RESOLV_KEYWORD; - ldns_buffer_free(b); - continue; + break; } tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word); if (!tmp) { @@ -817,8 +825,10 @@ ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr) (size_t) gtr + 1); } ldns_buffer_free(b); - gtr = 1; - expect = LDNS_RESOLV_KEYWORD; + if (expect != LDNS_RESOLV_KEYWORD) { + gtr = 1; + expect = LDNS_RESOLV_KEYWORD; + } break; case LDNS_RESOLV_SORTLIST: gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr); @@ -885,6 +895,7 @@ ldns_resolver_new_frm_file(ldns_resolver **res, const char *filename) *res = r; return LDNS_STATUS_OK; } else { + ldns_resolver_free(r); return LDNS_STATUS_NULL; } } @@ -947,15 +958,12 @@ ldns_resolver_search(const ldns_resolver *r,const ldns_rdf *name, ldns_rr_type t, ldns_rr_class c, uint16_t flags) { - char *str_dname; ldns_rdf *new_name; ldns_rdf **search_list; size_t i; ldns_pkt *p; - str_dname = ldns_rdf2str(name); - - if (ldns_dname_str_absolute(str_dname)) { + if (ldns_dname_absolute(name)) { /* query as-is */ return ldns_resolver_query(r, name, t, c, flags); } else if (ldns_resolver_dnsrch(r)) { @@ -1017,9 +1025,6 @@ ldns_resolver_query(const ldns_resolver *r, const ldns_rdf *name, newname = ldns_dname_cat_clone((const ldns_rdf*)name, ldns_resolver_domain(r)); if (!newname) { - if (pkt) { - ldns_pkt_free(pkt); - } return NULL; } @@ -1212,9 +1217,11 @@ ldns_resolver_send(ldns_pkt **answer, ldns_resolver *r, const ldns_rdf *name, ldns_resolver_tsig_keydata(r), 300, ldns_resolver_tsig_algorithm(r), NULL); if (status != LDNS_STATUS_OK) { + ldns_pkt_free(query_pkt); return LDNS_STATUS_CRYPTO_TSIG_ERR; } #else + ldns_pkt_free(query_pkt); return LDNS_STATUS_CRYPTO_TSIG_ERR; #endif /* HAVE_SSL */ } @@ -1294,7 +1301,14 @@ ldns_axfr_next(ldns_resolver *resolver) return NULL; } else if (ldns_pkt_get_rcode(resolver->_cur_axfr_pkt) != 0) { rcode = ldns_lookup_by_id(ldns_rcodes, (int) ldns_pkt_get_rcode(resolver->_cur_axfr_pkt)); - fprintf(stderr, "Error in AXFR: %s\n", rcode->name); + if (rcode) { + fprintf(stderr, "Error in AXFR: %s\n", + rcode->name); + } else { + fprintf(stderr, "Error in AXFR: %d\n", + (int) ldns_pkt_get_rcode( + resolver->_cur_axfr_pkt)); + } /* RoRi: we must now also close the socket, otherwise subsequent uses of the same resolver structure will fail because the link is still open or @@ -1333,17 +1347,22 @@ void ldns_resolver_nameservers_randomize(ldns_resolver *r) { uint16_t i, j; - ldns_rdf **ns, *tmp; + ldns_rdf **ns, *tmpns; + size_t *rtt, tmprtt; /* should I check for ldns_resolver_random?? */ assert(r != NULL); ns = ldns_resolver_nameservers(r); + rtt = ldns_resolver_rtt(r); for (i = 0; i < ldns_resolver_nameserver_count(r); i++) { j = ldns_get_random() % ldns_resolver_nameserver_count(r); - tmp = ns[i]; + tmpns = ns[i]; ns[i] = ns[j]; - ns[j] = tmp; + ns[j] = tmpns; + tmprtt = rtt[i]; + rtt[i] = rtt[j]; + rtt[j] = tmprtt; } ldns_resolver_set_nameservers(r, ns); } diff --git a/rr.c b/rr.c index 8f4ce85c7eb..72076d40c58 100644 --- a/rr.c +++ b/rr.c @@ -119,7 +119,7 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, char *type = NULL; char *rdata = NULL; char *rd = NULL; - char *b64 = NULL; + char * b64 = NULL; size_t rd_strlen; const char *delimiters; ssize_t c; @@ -477,6 +477,7 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, ldns_buffer_free(rr_buf); LDNS_FREE(rdata); ldns_rr_free(new); + LDNS_FREE(hex_data); return s; } LDNS_FREE(hex_data); @@ -600,6 +601,9 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str, if (newrr) { *newrr = new; + } else { + /* Maybe the caller just wanted to see if it would parse? */ + ldns_rr_free(new); } return LDNS_STATUS_OK; @@ -724,8 +728,13 @@ ldns_rr_new_frm_fp_l(ldns_rr **newrr, FILE *fp, uint32_t *default_ttl, ldns_rdf } } LDNS_FREE(line); - if (newrr && s == LDNS_STATUS_OK) { - *newrr = rr; + if (s == LDNS_STATUS_OK) { + if (newrr) { + *newrr = rr; + } else { + /* Just testing if it would parse? */ + ldns_rr_free(rr); + } } return s; } @@ -1156,7 +1165,8 @@ ldns_rr_list_pop_rr_list(ldns_rr_list *rr_list, size_t howmany) i--; } - if (i == howmany) { + if (i == howmany) { /* so i <= 0 */ + ldns_rr_list_free(popped); return NULL; } else { return popped; @@ -1480,6 +1490,7 @@ ldns_rr_list_sort(ldns_rr_list *unsorted) LDNS_FREE(sortables[i]); } /* no way to return error */ + LDNS_FREE(sortables); return; } sortables[i]->original_object = ldns_rr_list_rr(unsorted, i); @@ -1941,6 +1952,12 @@ static const ldns_rdf_type type_tsig_wireformat[] = { LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_INT16_DATA }; +static const ldns_rdf_type type_tlsa_wireformat[] = { + LDNS_RDF_TYPE_INT8, + LDNS_RDF_TYPE_INT8, + LDNS_RDF_TYPE_INT8, + LDNS_RDF_TYPE_HEX +}; /** \endcond */ /** \cond */ @@ -2048,13 +2065,14 @@ static ldns_rr_descriptor rdata_field_descriptors[] = { /* 48 */ {LDNS_RR_TYPE_DNSKEY, "DNSKEY", 4, 4, type_dnskey_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, /* 49 */ -{LDNS_RR_TYPE_DHCID, "DHCID", 1, 1, type_dhcid_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + {LDNS_RR_TYPE_DHCID, "DHCID", 1, 1, type_dhcid_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, /* 50 */ {LDNS_RR_TYPE_NSEC3, "NSEC3", 5, 6, type_nsec3_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, /* 51 */ -{LDNS_RR_TYPE_NSEC3PARAM, "NSEC3PARAM", 4, 4, type_nsec3param_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + {LDNS_RR_TYPE_NSEC3PARAM, "NSEC3PARAM", 4, 4, type_nsec3param_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, /* 52 */ -{LDNS_RR_TYPE_NULL, "TYPE52", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + {LDNS_RR_TYPE_TLSA, "TLSA", 4, 4, type_tlsa_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + {LDNS_RR_TYPE_NULL, "TYPE53", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, {LDNS_RR_TYPE_NULL, "TYPE54", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, {LDNS_RR_TYPE_NULL, "TYPE55", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, diff --git a/str2host.c b/str2host.c index 2783f0805a4..51357cc3176 100644 --- a/str2host.c +++ b/str2host.c @@ -96,7 +96,7 @@ ldns_str2rdf_time(ldns_rdf **rd, const char *time) goto bad_format; } - l = htonl(mktime_from_utc(&tm)); + l = htonl(ldns_mktime_from_utc(&tm)); memcpy(r, &l, sizeof(uint32_t)); *rd = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_TIME, sizeof(uint32_t), r); @@ -534,6 +534,7 @@ ldns_str2rdf_apl(ldns_rdf **rd, const char *str) data = LDNS_XMALLOC(uint8_t, 4 + afdlength); if(!data) { + LDNS_FREE(afdpart); LDNS_FREE(my_ip_str); return LDNS_STATUS_INVALID_STR; } @@ -1104,8 +1105,6 @@ ldns_str2rdf_wks(ldns_rdf **rd, const char *str) data[0] = (uint8_t) proto->p_proto; } else if (proto_str) { data[0] = (uint8_t) atoi(proto_str); - } else { - data[0] = 0; } memcpy(data + 1, bitmap, (size_t) bm_len); diff --git a/tsig.c b/tsig.c index 90c20a03ea0..41693463df3 100644 --- a/tsig.c +++ b/tsig.c @@ -179,10 +179,12 @@ ldns_tsig_mac_new(ldns_rdf **tsig_mac, uint8_t *pkt_wire, size_t pkt_wire_size, return LDNS_STATUS_NULL; } canonical_key_name_rdf = ldns_rdf_clone(key_name_rdf); + if (canonical_key_name_rdf == NULL) { + return LDNS_STATUS_MEM_ERR; + } canonical_algorithm_rdf = ldns_rdf_clone(algorithm_rdf); - - if (canonical_key_name_rdf == NULL - || canonical_algorithm_rdf == NULL) { + if (canonical_algorithm_rdf == NULL) { + ldns_rdf_deep_free(canonical_key_name_rdf); return LDNS_STATUS_MEM_ERR; } /* @@ -266,8 +268,8 @@ ldns_tsig_mac_new(ldns_rdf **tsig_mac, uint8_t *pkt_wire, size_t pkt_wire_size, LDNS_FREE(key_bytes); LDNS_FREE(algorithm_name); ldns_buffer_free(data_buffer); - ldns_rdf_free(canonical_algorithm_rdf); - ldns_rdf_free(canonical_key_name_rdf); + ldns_rdf_deep_free(canonical_algorithm_rdf); + ldns_rdf_deep_free(canonical_key_name_rdf); return status; } #endif /* HAVE_SSL */ diff --git a/util.c b/util.c index a7ab96080ce..f5462c4b08f 100644 --- a/util.c +++ b/util.c @@ -227,7 +227,7 @@ leap_days(int y1, int y2) * Code adapted from Python 2.4.1 sources (Lib/calendar.py). */ time_t -mktime_from_utc(const struct tm *tm) +ldns_mktime_from_utc(const struct tm *tm) { int year = 1900 + tm->tm_year; time_t days = 365 * ((time_t) year - 1970) + leap_days(1970, year); @@ -251,6 +251,12 @@ mktime_from_utc(const struct tm *tm) return seconds; } +time_t +mktime_from_utc(const struct tm *tm) +{ + return ldns_mktime_from_utc(tm); +} + #if SIZEOF_TIME_T <= 4 static void @@ -398,6 +404,7 @@ ldns_init_random(FILE *fd, unsigned int size) if (read < size) { LDNS_FREE(seed); + if (!fd) fclose(rand_f); return 1; } else { #ifdef HAVE_SSL From 5ab27407773db3624e505028e9ef00cde5d77e38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Fri, 15 Feb 2013 13:57:51 +0000 Subject: [PATCH 0189/1476] Oops, I flipped LDNS_UTILS but forgot to update the description. --- tools/build/options/WITH_LDNS_UTILS | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/build/options/WITH_LDNS_UTILS b/tools/build/options/WITH_LDNS_UTILS index 05dc9fb9179..e54d5546093 100644 --- a/tools/build/options/WITH_LDNS_UTILS +++ b/tools/build/options/WITH_LDNS_UTILS @@ -1,6 +1,5 @@ .\" $FreeBSD$ -Setting this variable will prevent the LDNS-based versions of +Setting this variable will enable the LDNS-based versions of .Xr dig 1 and -.Xr host 1 -from being built. +.Xr host 1 . From 0acc2e1d2b915d4f89113bc0853654f4277fe7a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Fri, 15 Feb 2013 14:17:27 +0000 Subject: [PATCH 0190/1476] Update src.conf(5) up to but not including my LDNS commits. --- share/man/man5/src.conf.5 | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/share/man/man5/src.conf.5 b/share/man/man5/src.conf.5 index f621307f0c6..21bfa6e8f0f 100644 --- a/share/man/man5/src.conf.5 +++ b/share/man/man5/src.conf.5 @@ -1,7 +1,7 @@ .\" DO NOT EDIT-- this file is automatically generated. .\" from FreeBSD: head/tools/build/options/makeman 236279 2012-05-30 02:37:20Z gjb .\" $FreeBSD$ -.Dd February 2, 2013 +.Dd February 15, 2013 .Dt SRC.CONF 5 .Os .Sh NAME @@ -291,7 +291,7 @@ When set, it also enforces the following options: Set to not build the Clang C/C++ compiler. .Pp It is a default setting on -arm/arm, arm/armeb, arm/armv6, arm/armv6eb, ia64/ia64, mips/mipsel, mips/mips, mips/mips64el, mips/mips64, mips/mipsn32 and sparc64/sparc64. +arm/armeb, arm/armv6eb, ia64/ia64, mips/mipsel, mips/mips, mips/mips64el, mips/mips64, mips/mipsn32 and sparc64/sparc64. When set, it also enforces the following options: .Pp .Bl -item -compact @@ -302,12 +302,6 @@ When set, it also enforces the following options: .It .Va WITHOUT_CLANG_IS_CC .El -.It Va WITH_CLANG -.\" from FreeBSD: head/tools/build/options/WITH_CLANG 221730 2011-05-10 11:14:40Z ru -Set to build the Clang C/C++ compiler. -.Pp -It is a default setting on -amd64/amd64, i386/i386, pc98/i386, powerpc/powerpc and powerpc/powerpc64. .It Va WITH_CLANG_EXTRAS .\" from FreeBSD: head/tools/build/options/WITH_CLANG_EXTRAS 231057 2012-02-05 23:56:22Z dim Set to build additional clang and llvm tools, such as bugpoint. @@ -435,13 +429,6 @@ This includes the device tree compiler (dtc) and libfdt support library. .Pp It is a default setting on amd64/amd64, i386/i386, ia64/ia64, pc98/i386 and sparc64/sparc64. -.It Va WITH_FDT -.\" from FreeBSD: head/tools/build/options/WITH_FDT 221730 2011-05-10 11:14:40Z ru -Set to build Flattened Device Tree support as part of the base system. -This includes the device tree compiler (dtc) and libfdt support library. -.Pp -It is a default setting on -arm/arm, arm/armeb, arm/armv6, arm/armv6eb, mips/mipsel, mips/mips, mips/mips64el, mips/mips64, mips/mipsn32, powerpc/powerpc and powerpc/powerpc64. .It Va WITHOUT_FLOPPY .\" from FreeBSD: head/tools/build/options/WITHOUT_FLOPPY 221540 2011-05-06 19:13:03Z ru Set to not build or install programs From d7ffa24831c7837cd2d7c8e94a7d29e43f3c99bf Mon Sep 17 00:00:00 2001 From: Sergey Kandaurov Date: Fri, 15 Feb 2013 14:22:05 +0000 Subject: [PATCH 0191/1476] vn_io_faults_cnt: - use u_long consistently - use SYSCTL_ULONG to match the type of variable Reviewed by: kib MFC after: 1 week --- sys/kern/vfs_vnops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index 4ebf4b58020..32c09781a1c 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -872,8 +872,8 @@ static const int io_hold_cnt = 16; static int vn_io_fault_enable = 1; SYSCTL_INT(_debug, OID_AUTO, vn_io_fault_enable, CTLFLAG_RW, &vn_io_fault_enable, 0, "Enable vn_io_fault lock avoidance"); -static unsigned long vn_io_faults_cnt; -SYSCTL_LONG(_debug, OID_AUTO, vn_io_faults, CTLFLAG_RD, +static u_long vn_io_faults_cnt; +SYSCTL_ULONG(_debug, OID_AUTO, vn_io_faults, CTLFLAG_RD, &vn_io_faults_cnt, 0, "Count of vn_io_fault lock avoidance triggers"); /* From 4e7b60a46c3906291cd6fead0fe8149c8e1cdd3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Fri, 15 Feb 2013 14:22:23 +0000 Subject: [PATCH 0192/1476] The relationship between LDNS_UTILS and BIND_UTILS was inverted. --- share/mk/bsd.own.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/mk/bsd.own.mk b/share/mk/bsd.own.mk index f2101bedba7..baac40e9207 100644 --- a/share/mk/bsd.own.mk +++ b/share/mk/bsd.own.mk @@ -477,7 +477,7 @@ MK_BIND_UTILS:= no MK_LDNS_UTILS:= no .endif -.if ${MK_LDNS_UTILS} == "no" +.if ${MK_LDNS_UTILS} != "no" MK_BIND_UTILS:= no .endif From 421ccedd2643363281305943f6df21e6f7db2c12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Fri, 15 Feb 2013 15:09:24 +0000 Subject: [PATCH 0193/1476] Manually add the correct text for the LDNS and LDNS_UTILS options. There seems to be a bug in makeman that causes it to misunderstand the relationship between LDNS_UTILS and BIND_UTILS. --- share/man/man5/src.conf.5 | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/share/man/man5/src.conf.5 b/share/man/man5/src.conf.5 index 21bfa6e8f0f..17afca25875 100644 --- a/share/man/man5/src.conf.5 +++ b/share/man/man5/src.conf.5 @@ -646,6 +646,26 @@ When set, it also enforces the following options: Set to build some programs without optional .Nm libkvm support. +.It Va WITHOUT_LDNS +.\" from FreeBSD: head/tools/build/options/WITHOUT_LDNS 246827 2013-02-15 13:44:18Z des +Setting this variable will prevent LDNS from being built. +When set, it also enforces the following options: +.Pp +.Bl -item -compact +.It +.Va WITHOUT_LDNS_UTILS +.El +.It Va WITH_LDNS_UTILS +.\" from FreeBSD: head/tools/build/options/WITH_LDNS_UTILS 246830 2013-02-15 13:57:51Z des +Setting this variable will enable the LDNS-based versions of +.Xr dig 1 +and +.Xr host 1 . +When set, the following options are also in effect: +.Pp +.Bl -inset -compact +.It Va WITHOUT_BIND_UTILS +.El .It Va WITHOUT_LEGACY_CONSOLE .\" from FreeBSD: head/tools/build/options/WITHOUT_LEGACY_CONSOLE 183242 2008-09-21 22:02:26Z sam Set to not build programs that support a legacy PC console; e.g. From a1137de941cf687a4ef5fcc3d2f20aba59c0b81a Mon Sep 17 00:00:00 2001 From: Ian Lepore Date: Fri, 15 Feb 2013 18:30:32 +0000 Subject: [PATCH 0194/1476] Add PPS_CANWAIT support for time_pps_fetch(). This adds support for all three blocking modes described in section 3.4.3 of RFC 2783, allowing the caller to retrieve the most recent values without blocking, to block for a specified time, or to block forever. Reviewed by: discussion on hackers@ --- sys/kern/kern_tc.c | 57 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c index 2ffa2f9426f..6e1f486f446 100644 --- a/sys/kern/kern_tc.c +++ b/sys/kern/kern_tc.c @@ -1446,6 +1446,50 @@ SYSCTL_PROC(_kern_timecounter, OID_AUTO, choice, CTLTYPE_STRING | CTLFLAG_RD, * RFC 2783 PPS-API implementation. */ +static int +pps_fetch(struct pps_fetch_args *fapi, struct pps_state *pps) +{ + int err, timo; + pps_seq_t aseq, cseq; + struct timeval tv; + + if (fapi->tsformat && fapi->tsformat != PPS_TSFMT_TSPEC) + return (EINVAL); + + /* + * If no timeout is requested, immediately return whatever values were + * most recently captured. If timeout seconds is -1, that's a request + * to block without a timeout. WITNESS won't let us sleep forever + * without a lock (we really don't need a lock), so just repeatedly + * sleep a long time. + */ + if (fapi->timeout.tv_sec || fapi->timeout.tv_nsec) { + if (fapi->timeout.tv_sec == -1) + timo = 0x7fffffff; + else { + tv.tv_sec = fapi->timeout.tv_sec; + tv.tv_usec = fapi->timeout.tv_nsec / 1000; + timo = tvtohz(&tv); + } + aseq = pps->ppsinfo.assert_sequence; + cseq = pps->ppsinfo.clear_sequence; + while (aseq == pps->ppsinfo.assert_sequence && + cseq == pps->ppsinfo.clear_sequence) { + err = tsleep(pps, PCATCH, "ppsfch", timo); + if (err == EWOULDBLOCK && fapi->timeout.tv_sec == -1) { + continue; + } else if (err != 0) { + return (err); + } + } + } + + pps->ppsinfo.current_mode = pps->ppsparam.mode; + fapi->pps_info_buf = pps->ppsinfo; + + return (0); +} + int pps_ioctl(u_long cmd, caddr_t data, struct pps_state *pps) { @@ -1485,13 +1529,7 @@ pps_ioctl(u_long cmd, caddr_t data, struct pps_state *pps) return (0); case PPS_IOC_FETCH: fapi = (struct pps_fetch_args *)data; - if (fapi->tsformat && fapi->tsformat != PPS_TSFMT_TSPEC) - return (EINVAL); - if (fapi->timeout.tv_sec || fapi->timeout.tv_nsec) - return (EOPNOTSUPP); - pps->ppsinfo.current_mode = pps->ppsparam.mode; - fapi->pps_info_buf = pps->ppsinfo; - return (0); + return (pps_fetch(fapi, pps)); #ifdef FFCLOCK case PPS_IOC_FETCH_FFCOUNTER: fapi_ffc = (struct pps_fetch_ffc_args *)data; @@ -1540,7 +1578,7 @@ pps_ioctl(u_long cmd, caddr_t data, struct pps_state *pps) void pps_init(struct pps_state *pps) { - pps->ppscap |= PPS_TSFMT_TSPEC; + pps->ppscap |= PPS_TSFMT_TSPEC | PPS_CANWAIT; if (pps->ppscap & PPS_CAPTUREASSERT) pps->ppscap |= PPS_OFFSETASSERT; if (pps->ppscap & PPS_CAPTURECLEAR) @@ -1680,6 +1718,9 @@ pps_event(struct pps_state *pps, int event) hardpps(tsp, ts.tv_nsec + 1000000000 * ts.tv_sec); } #endif + + /* Wakeup anyone sleeping in pps_fetch(). */ + wakeup(pps); } /* From 74f80b236d360d1bcbac8475ac777d992556e325 Mon Sep 17 00:00:00 2001 From: Neel Natu Date: Fri, 15 Feb 2013 18:41:36 +0000 Subject: [PATCH 0195/1476] Advertise PCI-E capability in the hostbridge device presented to the guest. FreeBSD wants to see this capability in at least one device in the PCI hierarchy before it allows use of MSI or MSI-X. Obtained from: NetApp --- usr.sbin/bhyve/pci_emul.c | 35 +++++++++++++++++++++++++++++++++ usr.sbin/bhyve/pci_emul.h | 35 +++++++++++++++++++++++++++++++++ usr.sbin/bhyve/pci_hostbridge.c | 2 ++ 3 files changed, 72 insertions(+) diff --git a/usr.sbin/bhyve/pci_emul.c b/usr.sbin/bhyve/pci_emul.c index 32a3deba03e..d883a540fc6 100644 --- a/usr.sbin/bhyve/pci_emul.c +++ b/usr.sbin/bhyve/pci_emul.c @@ -740,6 +740,38 @@ msicap_cfgwrite(struct pci_devinst *pi, int capoff, int offset, CFGWRITE(pi, offset, val, bytes); } +void +pciecap_cfgwrite(struct pci_devinst *pi, int capoff, int offset, + int bytes, uint32_t val) +{ + + /* XXX don't write to the readonly parts */ + CFGWRITE(pi, offset, val, bytes); +} + +#define PCIECAP_VERSION 0x2 +int +pci_emul_add_pciecap(struct pci_devinst *pi, int type) +{ + int err; + struct pciecap pciecap; + + CTASSERT(sizeof(struct pciecap) == 60); + + if (type != PCIEM_TYPE_ROOT_PORT) + return (-1); + + bzero(&pciecap, sizeof(pciecap)); + + pciecap.capid = PCIY_EXPRESS; + pciecap.pcie_capabilities = PCIECAP_VERSION | PCIEM_TYPE_ROOT_PORT; + pciecap.link_capabilities = 0x411; /* gen1, x1 */ + pciecap.link_status = 0x11; /* gen1, x1 */ + + err = pci_emul_add_capability(pi, (u_char *)&pciecap, sizeof(pciecap)); + return (err); +} + /* * This function assumes that 'coff' is in the capabilities region of the * config space. @@ -782,6 +814,9 @@ pci_emul_capwrite(struct pci_devinst *pi, int offset, int bytes, uint32_t val) case PCIY_MSIX: msixcap_cfgwrite(pi, capoff, offset, bytes, val); break; + case PCIY_EXPRESS: + pciecap_cfgwrite(pi, capoff, offset, bytes, val); + break; default: break; } diff --git a/usr.sbin/bhyve/pci_emul.h b/usr.sbin/bhyve/pci_emul.h index 8c6260cee6b..079d5f2460a 100644 --- a/usr.sbin/bhyve/pci_emul.h +++ b/usr.sbin/bhyve/pci_emul.h @@ -150,6 +150,40 @@ struct msixcap { uint32_t pba_info; /* bar index and offset within it */ } __packed; +struct pciecap { + uint8_t capid; + uint8_t nextptr; + uint16_t pcie_capabilities; + + uint32_t dev_capabilities; /* all devices */ + uint16_t dev_control; + uint16_t dev_status; + + uint32_t link_capabilities; /* devices with links */ + uint16_t link_control; + uint16_t link_status; + + uint32_t slot_capabilities; /* ports with slots */ + uint16_t slot_control; + uint16_t slot_status; + + uint16_t root_control; /* root ports */ + uint16_t root_capabilities; + uint32_t root_status; + + uint32_t dev_capabilities2; /* all devices */ + uint16_t dev_control2; + uint16_t dev_status2; + + uint32_t link_capabilities2; /* devices with links */ + uint16_t link_control2; + uint16_t link_status2; + + uint32_t slot_capabilities2; /* ports with slots */ + uint16_t slot_control2; + uint16_t slot_status2; +} __packed; + void init_pci(struct vmctx *ctx); void msicap_cfgwrite(struct pci_devinst *pi, int capoff, int offset, int bytes, uint32_t val); @@ -161,6 +195,7 @@ int pci_emul_alloc_bar(struct pci_devinst *pdi, int idx, int pci_emul_alloc_pbar(struct pci_devinst *pdi, int idx, uint64_t hostbase, enum pcibar_type type, uint64_t size); int pci_emul_add_msicap(struct pci_devinst *pi, int msgnum); +int pci_emul_add_pciecap(struct pci_devinst *pi, int pcie_device_type); int pci_is_legacy(struct pci_devinst *pi); void pci_generate_msi(struct pci_devinst *pi, int msgnum); void pci_generate_msix(struct pci_devinst *pi, int msgnum); diff --git a/usr.sbin/bhyve/pci_hostbridge.c b/usr.sbin/bhyve/pci_hostbridge.c index c77762d8f92..dee0a47e5d7 100644 --- a/usr.sbin/bhyve/pci_hostbridge.c +++ b/usr.sbin/bhyve/pci_hostbridge.c @@ -42,6 +42,8 @@ pci_hostbridge_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_BRIDGE); pci_set_cfgdata8(pi, PCIR_SUBCLASS, PCIS_BRIDGE_HOST); + pci_emul_add_pciecap(pi, PCIEM_TYPE_ROOT_PORT); + return (0); } From 6bb10c5e2fa82c104e57c7468335930ba9e47d4f Mon Sep 17 00:00:00 2001 From: Jung-uk Kim Date: Fri, 15 Feb 2013 19:12:35 +0000 Subject: [PATCH 0196/1476] Import ACPICA 20130215. --- changes.txt | 96 +++- generate/unix/Makefile.config | 87 +-- generate/unix/acpibin/Makefile | 42 +- generate/unix/acpiexec/Makefile | 370 ++++++------- generate/unix/acpihelp/Makefile | 22 +- generate/unix/acpinames/Makefile | 162 +++--- generate/unix/acpisrc/Makefile | 24 +- generate/unix/acpixtract/Makefile | 10 +- generate/unix/iasl/Makefile | 367 ++++++------- source/common/adisasm.c | 9 +- source/common/adwalk.c | 2 +- source/common/dmextern.c | 218 +++++++- source/common/dmtable.c | 4 + source/common/dmtbdump.c | 104 ++++ source/common/dmtbinfo.c | 45 ++ source/compiler/aslcompile.c | 84 +++ source/compiler/aslcompiler.h | 20 + source/compiler/asldefine.h | 5 +- source/compiler/aslfiles.c | 7 + source/compiler/aslmain.c | 37 +- source/compiler/aslmessages.h | 2 + source/compiler/aslpredef.c | 140 +++-- source/compiler/aslprepkg.c | 661 +++++++++++++++++++++++ source/compiler/aslstartup.c | 163 ++++-- source/compiler/aslsupport.l | 10 +- source/compiler/dtcompiler.h | 10 + source/compiler/dttable.c | 50 ++ source/compiler/dttemplate.h | 27 + source/components/debugger/dbcmds.c | 8 +- source/components/debugger/dbinput.c | 4 +- source/components/disassembler/dmresrc.c | 2 +- source/components/dispatcher/dsutils.c | 10 +- source/components/events/evevent.c | 12 +- source/components/events/evgpe.c | 6 +- source/components/events/evsci.c | 4 +- source/components/events/evxface.c | 18 +- source/components/events/evxfevnt.c | 14 + source/components/executer/exprep.c | 4 +- source/components/executer/exutils.c | 4 +- source/components/hardware/hwacpi.c | 23 +- source/components/namespace/nsconvert.c | 481 +++++++++++++++++ source/components/namespace/nspredef.c | 154 +++--- source/components/namespace/nsprepkg.c | 11 +- source/components/namespace/nsrepair.c | 396 +++++--------- source/components/namespace/nsrepair2.c | 8 +- source/components/namespace/nsutils.c | 8 +- source/components/parser/psargs.c | 2 +- source/components/resources/rscalc.c | 7 + source/components/resources/rsdump.c | 9 + source/components/resources/rslist.c | 9 + source/components/resources/rsxface.c | 9 +- source/components/utilities/utaddress.c | 4 +- source/components/utilities/utexcep.c | 29 +- source/components/utilities/utglobal.c | 2 + source/include/acdisasm.h | 16 + source/include/acexcep.h | 419 +++++++------- source/include/acglobal.h | 4 +- source/include/aclocal.h | 18 + source/include/acnamesp.h | 31 +- source/include/acoutput.h | 9 +- source/include/acpixf.h | 2 +- source/include/actbl2.h | 57 ++ source/include/actbl3.h | 63 ++- source/include/acutils.h | 3 +- source/tools/acpihelp/ahdecode.c | 29 +- source/tools/acpisrc/astable.c | 9 + 66 files changed, 3383 insertions(+), 1293 deletions(-) create mode 100644 source/compiler/aslprepkg.c create mode 100644 source/components/namespace/nsconvert.c diff --git a/changes.txt b/changes.txt index 58483351c0f..cf247faf826 100644 --- a/changes.txt +++ b/changes.txt @@ -1,7 +1,101 @@ +---------------------------------------- +14 February 2013. Summary of changes for version 20130214: + +1) ACPICA Kernel-resident Subsystem: + +Fixed a possible regression on some hosts: Reinstated the safe return +macros (return_ACPI_STATUS, etc.) that ensure that the argument is +evaluated only once. Although these macros are not needed for the ACPICA +code itself, they are often used by ACPI-related host device drivers where +the safe feature may be necessary. + +Fixed several issues related to the ACPI 5.0 reduced hardware support +(SOC): Now ensure that if the platform declares itself as hardware-reduced +via the FADT, the following functions become NOOPs (and always return +AE_OK) because ACPI is always enabled by definition on these machines: + AcpiEnable + AcpiDisable + AcpiHwGetMode + AcpiHwSetMode + +Dynamic Object Repair: Implemented additional runtime repairs for +predefined name return values. Both of these repairs can simplify code in +the related device drivers that invoke these methods: +1) For the _STR and _MLS names, automatically repair/convert an ASCII +string to a Unicode buffer. +2) For the _CRS, _PRS, and _DMA names, return a resource descriptor with a +lone end tag descriptor in the following cases: A Return(0) was executed, +a null buffer was returned, or no object at all was returned (non-slack +mode only). Adds a new file, nsconvert.c +ACPICA BZ 998. Bob Moore, Lv Zheng. + +Resource Manager: Added additional code to prevent possible infinite loops +while traversing corrupted or ill-formed resource template buffers. Check +for zero-length resource descriptors in all code that loops through +resource templates (the length field is used to index through the +template). This change also hardens the external AcpiWalkResources and +AcpiWalkResourceBuffer interfaces. + +Local Cache Manager: Enhanced the main data structure to eliminate an +unnecessary mechanism to access the next object in the list. Actually +provides a small performance enhancement for hosts that use the local +ACPICA cache manager. Jung-uk Kim. + +Example Code and Data Size: These are the sizes for the OS-independent +acpica.lib produced by the Microsoft Visual C++ 9.0 32-bit compiler. The +debug version of the code includes the debug output trace mechanism and +has a much larger code and data size. + + Previous Release: + Non-Debug Version: 94.5K Code, 25.4K Data, 119.9K Total + Debug Version: 182.3K Code, 75.0K Data, 257.3K Total + Current Release: + Non-Debug Version: 95.0K Code, 25.9K Data, 120.9K Total + Debug Version: 182.9K Code, 75.6K Data, 258.5K Total + + +2) iASL Compiler/Disassembler and Tools: + +iASL/Disassembler: Fixed several issues with the definition of the ACPI +5.0 RASF table (RAS Feature Table). This change incorporates late changes +that were made to the ACPI 5.0 specification. + +iASL/Disassembler: Added full support for the following new ACPI tables: + 1) The MTMR table (MID Timer Table) + 2) The VRTC table (Virtual Real Time Clock Table). +Includes header file, disassembler, table compiler, and template support +for both tables. + +iASL: Implemented compile-time validation of package objects returned by +predefined names. This new feature validates static package objects +returned by the various predefined names defined to return packages. Both +object types and package lengths are validated, for both parent packages +and sub-packages, if any. The code is similar in structure and behavior to +the runtime repair mechanism within the AML interpreter and uses the +existing predefined name information table. Adds a new file, aslprepkg.c. +ACPICA BZ 938. + +iASL: Implemented auto-detection of binary ACPI tables for disassembly. +This feature detects a binary file with a valid ACPI table header and +invokes the disassembler automatically. Eliminates the need to +specifically invoke the disassembler with the -d option. ACPICA BZ 862. + +iASL/Disassembler: Added several warnings for the case where there are +unresolved control methods during the disassembly. This can potentially +cause errors when the output file is compiled, because the disassembler +assumes zero method arguments in these cases (it cannot determine the +actual number of arguments without resolution/definition of the method). + +Debugger: Added support to display all resources with a single command. +Invocation of the resources command with no arguments will now display all +resources within the current namespace. + +AcpiHelp: Added descriptive text for each ACPICA exception code displayed +via the -e option. + ---------------------------------------- 17 January 2013. Summary of changes for version 20130117: - 1) ACPICA Kernel-resident Subsystem: Updated the AcpiGetSleepTypeData interface: Allow the \_Sx methods to diff --git a/generate/unix/Makefile.config b/generate/unix/Makefile.config index 5a42cc84184..65242e0a983 100644 --- a/generate/unix/Makefile.config +++ b/generate/unix/Makefile.config @@ -19,12 +19,16 @@ # # Configuration +# +# OPT_CFLAGS can be overridden on the make command line by +# adding OPT_CFLAGS="..." to the invocation. +# # Notes: # $(BITS) must be set to either 32 or 64 # gcc should be version 4 or greater, otherwise some of the options # used will not be recognized. -# Global optimization flags (such as -O2, -Os) are not used, since -# they cause issues on some compilers. +# Global optimization flags (such as -O2, -Os) may cause issues on +# some compilers. # The _GNU_SOURCE symbol is required for many hosts. # .SUFFIXES : @@ -38,7 +42,7 @@ CC = gcc OBJDIR = obj$(BITS) BINDIR = bin$(BITS) BITSFLAG = -m$(BITS) -COMPILEOBJ = $(CC) -c $(CFLAGS) $(CWARNINGFLAGS) -o$@ $< +COMPILEOBJ = $(CC) -c $(CFLAGS) $(OPT_CFLAGS) -o $@ $< LINKPROG = $(CC) $(OBJECTS) -o $(PROG) $(LDFLAGS) INSTALLDIR = /usr/bin INSTALLPROG = install -D ../$(BINDIR)/$(PROG) $(DESTDIR)$(INSTALLDIR)/$(PROG) @@ -100,58 +104,65 @@ ACPICA_HEADERS = \ $(wildcard $(ACPICA_INCLUDE)/platform/*.h) # -# Common compiler flags. The warning flags in addition to -Wall are not -# automatically included in -Wall. +# Common compiler flags # +OPT_CFLAGS ?= \ + -D_FORTIFY_SOURCE=2\ + -O2\ + $(CWARNINGFLAGS) + CFLAGS += \ - $(BITSFLAG) \ - -D$(HOST) \ - -D_GNU_SOURCE \ - -D_FORTIFY_SOURCE=2 \ + $(BITSFLAG)\ + -D$(HOST)\ + -D_GNU_SOURCE\ -I$(ACPICA_INCLUDE) LDFLAGS += $(BITSFLAG) +# +# Common compiler warning flags. The warning flags in addition +# to -Wall are not automatically included in -Wall. +# CWARNINGFLAGS = \ - -ansi \ - -Wall \ - -Wbad-function-cast \ - -Wdeclaration-after-statement \ - -Werror \ - -Wformat=2 \ - -Wmissing-declarations \ - -Wmissing-prototypes \ - -Wstrict-aliasing=0 \ - -Wstrict-prototypes \ - -Wswitch-default \ - -Wpointer-arith \ + -ansi\ + -Wall\ + -Wbad-function-cast\ + -Wdeclaration-after-statement\ + -Werror\ + -Wformat=2\ + -Wmissing-declarations\ + -Wmissing-prototypes\ + -Wstrict-aliasing=0\ + -Wstrict-prototypes\ + -Wswitch-default\ + -Wpointer-arith\ -Wundef # -# gcc 4+ flags +# Additional gcc 4+ warning flags # CWARNINGFLAGS += \ - -Waddress \ - -Waggregate-return \ - -Wchar-subscripts \ - -Wempty-body \ - -Wlogical-op \ - -Wmissing-declarations \ - -Wmissing-field-initializers \ - -Wmissing-parameter-type \ - -Wnested-externs \ - -Wold-style-declaration \ - -Wold-style-definition \ - -Wredundant-decls \ + -Waddress\ + -Waggregate-return\ + -Wchar-subscripts\ + -Wempty-body\ + -Wlogical-op\ + -Wmissing-declarations\ + -Wmissing-field-initializers\ + -Wmissing-parameter-type\ + -Wnested-externs\ + -Wold-style-declaration\ + -Wold-style-definition\ + -Wredundant-decls\ -Wtype-limits # -# Extra warning flags (possible future use) +# Extra warning flags (for possible future use) # #CWARNINGFLAGS += \ -# -Wcast-qual \ -# -Wconversion -# -Wshadow \ +# -Wcast-qual\ +# -Wconversion\ +# -Wshadow\ # # Bison/Flex configuration diff --git a/generate/unix/acpibin/Makefile b/generate/unix/acpibin/Makefile index ccc5d52c949..1f6eb80e8b8 100644 --- a/generate/unix/acpibin/Makefile +++ b/generate/unix/acpibin/Makefile @@ -18,38 +18,38 @@ PROG = $(OBJDIR)/acpibin # Search paths for source files # vpath %.c \ - $(ACPIBIN) \ - $(ACPICA_UTILITIES) \ - $(ACPICA_COMMON) \ + $(ACPIBIN)\ + $(ACPICA_UTILITIES)\ + $(ACPICA_COMMON)\ $(ACPICA_OSL) HEADERS = \ $(wildcard $(ACPIBIN)/*.h) OBJECTS = \ - $(OBJDIR)/abcompare.o \ - $(OBJDIR)/abmain.o \ - $(OBJDIR)/utalloc.o \ - $(OBJDIR)/utcache.o \ - $(OBJDIR)/utdebug.o \ - $(OBJDIR)/utdecode.o \ - $(OBJDIR)/utexcep.o \ - $(OBJDIR)/utglobal.o \ - $(OBJDIR)/utlock.o \ - $(OBJDIR)/utmath.o \ - $(OBJDIR)/utmisc.o \ - $(OBJDIR)/utmutex.o \ - $(OBJDIR)/utstate.o \ - $(OBJDIR)/utstring.o \ - $(OBJDIR)/utxferror.o \ - $(OBJDIR)/osunixxf.o \ + $(OBJDIR)/abcompare.o\ + $(OBJDIR)/abmain.o\ + $(OBJDIR)/utalloc.o\ + $(OBJDIR)/utcache.o\ + $(OBJDIR)/utdebug.o\ + $(OBJDIR)/utdecode.o\ + $(OBJDIR)/utexcep.o\ + $(OBJDIR)/utglobal.o\ + $(OBJDIR)/utlock.o\ + $(OBJDIR)/utmath.o\ + $(OBJDIR)/utmisc.o\ + $(OBJDIR)/utmutex.o\ + $(OBJDIR)/utstate.o\ + $(OBJDIR)/utstring.o\ + $(OBJDIR)/utxferror.o\ + $(OBJDIR)/osunixxf.o\ $(OBJDIR)/getopt.o # # Flags specific to acpibin # -CFLAGS+= \ - -DACPI_BIN_APP \ +CFLAGS += \ + -DACPI_BIN_APP\ -I$(ACPIBIN) # diff --git a/generate/unix/acpiexec/Makefile b/generate/unix/acpiexec/Makefile index 61b5119b03b..5ac3da32641 100644 --- a/generate/unix/acpiexec/Makefile +++ b/generate/unix/acpiexec/Makefile @@ -20,202 +20,204 @@ PROG = $(OBJDIR)/acpiexec # Search paths for source files # vpath %.c \ - $(ACPIEXEC) \ - $(ACPICA_DEBUGGER) \ - $(ACPICA_DISASSEMBLER) \ - $(ACPICA_DISPATCHER) \ - $(ACPICA_EVENTS) \ - $(ACPICA_EXECUTER) \ - $(ACPICA_HARDWARE) \ - $(ACPICA_NAMESPACE) \ - $(ACPICA_PARSER) \ - $(ACPICA_RESOURCES) \ - $(ACPICA_TABLES) \ - $(ACPICA_UTILITIES) \ - $(ACPICA_COMMON) \ + $(ACPIEXEC)\ + $(ACPICA_DEBUGGER)\ + $(ACPICA_DISASSEMBLER)\ + $(ACPICA_DISPATCHER)\ + $(ACPICA_EVENTS)\ + $(ACPICA_EXECUTER)\ + $(ACPICA_HARDWARE)\ + $(ACPICA_NAMESPACE)\ + $(ACPICA_PARSER)\ + $(ACPICA_RESOURCES)\ + $(ACPICA_TABLES)\ + $(ACPICA_UTILITIES)\ + $(ACPICA_COMMON)\ $(ACPICA_OSL) HEADERS = \ $(wildcard $(ACPIEXEC)/*.h) OBJECTS = \ - $(OBJDIR)/aeexec.o \ - $(OBJDIR)/aehandlers.o \ - $(OBJDIR)/aemain.o \ - $(OBJDIR)/aetables.o \ - $(OBJDIR)/dbcmds.o \ - $(OBJDIR)/dbconvert.o \ - $(OBJDIR)/dbdisply.o \ - $(OBJDIR)/dbexec.o \ - $(OBJDIR)/dbfileio.o \ - $(OBJDIR)/dbhistry.o \ - $(OBJDIR)/dbinput.o \ - $(OBJDIR)/dbmethod.o \ - $(OBJDIR)/dbnames.o \ - $(OBJDIR)/dbstats.o \ - $(OBJDIR)/dbutils.o \ - $(OBJDIR)/dbxface.o \ - $(OBJDIR)/dmbuffer.o \ - $(OBJDIR)/dmdeferred.o \ - $(OBJDIR)/dmnames.o \ - $(OBJDIR)/dmobject.o \ - $(OBJDIR)/dmopcode.o \ - $(OBJDIR)/dmresrc.o \ - $(OBJDIR)/dmresrcl.o \ - $(OBJDIR)/dmresrcl2.o \ - $(OBJDIR)/dmresrcs.o \ - $(OBJDIR)/dmutils.o \ - $(OBJDIR)/dmwalk.o \ - $(OBJDIR)/dsargs.o \ - $(OBJDIR)/dscontrol.o \ - $(OBJDIR)/dsfield.o \ - $(OBJDIR)/dsinit.o \ - $(OBJDIR)/dsmethod.o \ - $(OBJDIR)/dsmthdat.o \ - $(OBJDIR)/dsobject.o \ - $(OBJDIR)/dsopcode.o \ - $(OBJDIR)/dsutils.o \ - $(OBJDIR)/dswexec.o \ - $(OBJDIR)/dswload.o \ - $(OBJDIR)/dswload2.o \ - $(OBJDIR)/dswscope.o \ - $(OBJDIR)/dswstate.o \ - $(OBJDIR)/evevent.o \ - $(OBJDIR)/evglock.o \ - $(OBJDIR)/evgpe.o \ - $(OBJDIR)/evgpeblk.o \ - $(OBJDIR)/evgpeinit.o \ - $(OBJDIR)/evgpeutil.o \ - $(OBJDIR)/evhandler.o \ - $(OBJDIR)/evmisc.o \ - $(OBJDIR)/evregion.o \ - $(OBJDIR)/evrgnini.o \ - $(OBJDIR)/evsci.o \ - $(OBJDIR)/evxface.o \ - $(OBJDIR)/evxfevnt.o \ - $(OBJDIR)/evxfgpe.o \ - $(OBJDIR)/evxfregn.o \ - $(OBJDIR)/exconfig.o \ - $(OBJDIR)/exconvrt.o \ - $(OBJDIR)/excreate.o \ - $(OBJDIR)/exdebug.o \ - $(OBJDIR)/exdump.o \ - $(OBJDIR)/exfield.o \ - $(OBJDIR)/exfldio.o \ - $(OBJDIR)/exmisc.o \ - $(OBJDIR)/exmutex.o \ - $(OBJDIR)/exnames.o \ - $(OBJDIR)/exoparg1.o \ - $(OBJDIR)/exoparg2.o \ - $(OBJDIR)/exoparg3.o \ - $(OBJDIR)/exoparg6.o \ - $(OBJDIR)/exprep.o \ - $(OBJDIR)/exregion.o \ - $(OBJDIR)/exresnte.o \ - $(OBJDIR)/exresolv.o \ - $(OBJDIR)/exresop.o \ - $(OBJDIR)/exstore.o \ - $(OBJDIR)/exstoren.o \ - $(OBJDIR)/exstorob.o \ - $(OBJDIR)/exsystem.o \ - $(OBJDIR)/exutils.o \ - $(OBJDIR)/getopt.o \ - $(OBJDIR)/hwacpi.o \ - $(OBJDIR)/hwesleep.o \ - $(OBJDIR)/hwgpe.o \ - $(OBJDIR)/hwpci.o \ - $(OBJDIR)/hwregs.o \ - $(OBJDIR)/hwsleep.o \ - $(OBJDIR)/hwvalid.o \ - $(OBJDIR)/hwxface.o \ - $(OBJDIR)/hwxfsleep.o \ - $(OBJDIR)/nsaccess.o \ - $(OBJDIR)/nsalloc.o \ - $(OBJDIR)/nsdump.o \ - $(OBJDIR)/nsdumpdv.o \ - $(OBJDIR)/nseval.o \ - $(OBJDIR)/nsinit.o \ - $(OBJDIR)/nsload.o \ - $(OBJDIR)/nsnames.o \ - $(OBJDIR)/nsobject.o \ - $(OBJDIR)/nsparse.o \ - $(OBJDIR)/nspredef.o \ - $(OBJDIR)/nsprepkg.o \ - $(OBJDIR)/nsrepair.o \ - $(OBJDIR)/nsrepair2.o \ - $(OBJDIR)/nssearch.o \ - $(OBJDIR)/nsutils.o \ - $(OBJDIR)/nswalk.o \ - $(OBJDIR)/nsxfeval.o \ - $(OBJDIR)/nsxfname.o \ - $(OBJDIR)/nsxfobj.o \ - $(OBJDIR)/osunixxf.o \ - $(OBJDIR)/psargs.o \ - $(OBJDIR)/psloop.o \ - $(OBJDIR)/psobject.o \ - $(OBJDIR)/psopcode.o \ - $(OBJDIR)/psopinfo.o \ - $(OBJDIR)/psparse.o \ - $(OBJDIR)/psscope.o \ - $(OBJDIR)/pstree.o \ - $(OBJDIR)/psutils.o \ - $(OBJDIR)/pswalk.o \ - $(OBJDIR)/psxface.o \ - $(OBJDIR)/rsaddr.o \ - $(OBJDIR)/rscalc.o \ - $(OBJDIR)/rscreate.o \ - $(OBJDIR)/rsdump.o \ - $(OBJDIR)/rsdumpinfo.o \ - $(OBJDIR)/rsinfo.o \ - $(OBJDIR)/rsio.o \ - $(OBJDIR)/rsirq.o \ - $(OBJDIR)/rslist.o \ - $(OBJDIR)/rsmemory.o \ - $(OBJDIR)/rsmisc.o \ - $(OBJDIR)/rsserial.o \ - $(OBJDIR)/rsutils.o \ - $(OBJDIR)/rsxface.o \ - $(OBJDIR)/tbfadt.o \ - $(OBJDIR)/tbfind.o \ - $(OBJDIR)/tbinstal.o \ - $(OBJDIR)/tbutils.o \ - $(OBJDIR)/tbxface.o \ - $(OBJDIR)/tbxfload.o \ - $(OBJDIR)/tbxfroot.o \ - $(OBJDIR)/utaddress.o \ - $(OBJDIR)/utalloc.o \ - $(OBJDIR)/utcache.o \ - $(OBJDIR)/utcopy.o \ - $(OBJDIR)/utdebug.o \ - $(OBJDIR)/utdecode.o \ - $(OBJDIR)/utdelete.o \ - $(OBJDIR)/uteval.o \ - $(OBJDIR)/utexcep.o \ - $(OBJDIR)/utglobal.o \ - $(OBJDIR)/utids.o \ - $(OBJDIR)/utinit.o \ - $(OBJDIR)/utlock.o \ - $(OBJDIR)/utmath.o \ - $(OBJDIR)/utmisc.o \ - $(OBJDIR)/utmutex.o \ - $(OBJDIR)/utobject.o \ - $(OBJDIR)/utosi.o \ - $(OBJDIR)/utownerid.o \ - $(OBJDIR)/utresrc.o \ - $(OBJDIR)/utstate.o \ - $(OBJDIR)/utstring.o \ - $(OBJDIR)/uttrack.o \ - $(OBJDIR)/utxface.o \ - $(OBJDIR)/utxferror.o \ - $(OBJDIR)/utxfinit.o \ + $(OBJDIR)/aeexec.o\ + $(OBJDIR)/aehandlers.o\ + $(OBJDIR)/aemain.o\ + $(OBJDIR)/aetables.o\ + $(OBJDIR)/dbcmds.o\ + $(OBJDIR)/dbconvert.o\ + $(OBJDIR)/dbdisply.o\ + $(OBJDIR)/dbexec.o\ + $(OBJDIR)/dbfileio.o\ + $(OBJDIR)/dbhistry.o\ + $(OBJDIR)/dbinput.o\ + $(OBJDIR)/dbmethod.o\ + $(OBJDIR)/dbnames.o\ + $(OBJDIR)/dbstats.o\ + $(OBJDIR)/dbutils.o\ + $(OBJDIR)/dbxface.o\ + $(OBJDIR)/dmbuffer.o\ + $(OBJDIR)/dmdeferred.o\ + $(OBJDIR)/dmnames.o\ + $(OBJDIR)/dmobject.o\ + $(OBJDIR)/dmopcode.o\ + $(OBJDIR)/dmresrc.o\ + $(OBJDIR)/dmresrcl.o\ + $(OBJDIR)/dmresrcl2.o\ + $(OBJDIR)/dmresrcs.o\ + $(OBJDIR)/dmutils.o\ + $(OBJDIR)/dmwalk.o\ + $(OBJDIR)/dsargs.o\ + $(OBJDIR)/dscontrol.o\ + $(OBJDIR)/dsfield.o\ + $(OBJDIR)/dsinit.o\ + $(OBJDIR)/dsmethod.o\ + $(OBJDIR)/dsmthdat.o\ + $(OBJDIR)/dsobject.o\ + $(OBJDIR)/dsopcode.o\ + $(OBJDIR)/dsutils.o\ + $(OBJDIR)/dswexec.o\ + $(OBJDIR)/dswload.o\ + $(OBJDIR)/dswload2.o\ + $(OBJDIR)/dswscope.o\ + $(OBJDIR)/dswstate.o\ + $(OBJDIR)/evevent.o\ + $(OBJDIR)/evglock.o\ + $(OBJDIR)/evgpe.o\ + $(OBJDIR)/evgpeblk.o\ + $(OBJDIR)/evgpeinit.o\ + $(OBJDIR)/evgpeutil.o\ + $(OBJDIR)/evhandler.o\ + $(OBJDIR)/evmisc.o\ + $(OBJDIR)/evregion.o\ + $(OBJDIR)/evrgnini.o\ + $(OBJDIR)/evsci.o\ + $(OBJDIR)/evxface.o\ + $(OBJDIR)/evxfevnt.o\ + $(OBJDIR)/evxfgpe.o\ + $(OBJDIR)/evxfregn.o\ + $(OBJDIR)/exconfig.o\ + $(OBJDIR)/exconvrt.o\ + $(OBJDIR)/excreate.o\ + $(OBJDIR)/exdebug.o\ + $(OBJDIR)/exdump.o\ + $(OBJDIR)/exfield.o\ + $(OBJDIR)/exfldio.o\ + $(OBJDIR)/exmisc.o\ + $(OBJDIR)/exmutex.o\ + $(OBJDIR)/exnames.o\ + $(OBJDIR)/exoparg1.o\ + $(OBJDIR)/exoparg2.o\ + $(OBJDIR)/exoparg3.o\ + $(OBJDIR)/exoparg6.o\ + $(OBJDIR)/exprep.o\ + $(OBJDIR)/exregion.o\ + $(OBJDIR)/exresnte.o\ + $(OBJDIR)/exresolv.o\ + $(OBJDIR)/exresop.o\ + $(OBJDIR)/exstore.o\ + $(OBJDIR)/exstoren.o\ + $(OBJDIR)/exstorob.o\ + $(OBJDIR)/exsystem.o\ + $(OBJDIR)/exutils.o\ + $(OBJDIR)/getopt.o\ + $(OBJDIR)/hwacpi.o\ + $(OBJDIR)/hwesleep.o\ + $(OBJDIR)/hwgpe.o\ + $(OBJDIR)/hwpci.o\ + $(OBJDIR)/hwregs.o\ + $(OBJDIR)/hwsleep.o\ + $(OBJDIR)/hwvalid.o\ + $(OBJDIR)/hwxface.o\ + $(OBJDIR)/hwxfsleep.o\ + $(OBJDIR)/nsaccess.o\ + $(OBJDIR)/nsalloc.o\ + $(OBJDIR)/nsconvert.o\ + $(OBJDIR)/nsdump.o\ + $(OBJDIR)/nsdumpdv.o\ + $(OBJDIR)/nseval.o\ + $(OBJDIR)/nsinit.o\ + $(OBJDIR)/nsload.o\ + $(OBJDIR)/nsnames.o\ + $(OBJDIR)/nsobject.o\ + $(OBJDIR)/nsparse.o\ + $(OBJDIR)/nspredef.o\ + $(OBJDIR)/nsprepkg.o\ + $(OBJDIR)/nsrepair.o\ + $(OBJDIR)/nsrepair2.o\ + $(OBJDIR)/nssearch.o\ + $(OBJDIR)/nsutils.o\ + $(OBJDIR)/nswalk.o\ + $(OBJDIR)/nsxfeval.o\ + $(OBJDIR)/nsxfname.o\ + $(OBJDIR)/nsxfobj.o\ + $(OBJDIR)/osunixxf.o\ + $(OBJDIR)/psargs.o\ + $(OBJDIR)/psloop.o\ + $(OBJDIR)/psobject.o\ + $(OBJDIR)/psopcode.o\ + $(OBJDIR)/psopinfo.o\ + $(OBJDIR)/psparse.o\ + $(OBJDIR)/psscope.o\ + $(OBJDIR)/pstree.o\ + $(OBJDIR)/psutils.o\ + $(OBJDIR)/pswalk.o\ + $(OBJDIR)/psxface.o\ + $(OBJDIR)/rsaddr.o\ + $(OBJDIR)/rscalc.o\ + $(OBJDIR)/rscreate.o\ + $(OBJDIR)/rsdump.o\ + $(OBJDIR)/rsdumpinfo.o\ + $(OBJDIR)/rsinfo.o\ + $(OBJDIR)/rsio.o\ + $(OBJDIR)/rsirq.o\ + $(OBJDIR)/rslist.o\ + $(OBJDIR)/rsmemory.o\ + $(OBJDIR)/rsmisc.o\ + $(OBJDIR)/rsserial.o\ + $(OBJDIR)/rsutils.o\ + $(OBJDIR)/rsxface.o\ + $(OBJDIR)/tbfadt.o\ + $(OBJDIR)/tbfind.o\ + $(OBJDIR)/tbinstal.o\ + $(OBJDIR)/tbutils.o\ + $(OBJDIR)/tbxface.o\ + $(OBJDIR)/tbxfload.o\ + $(OBJDIR)/tbxfroot.o\ + $(OBJDIR)/utaddress.o\ + $(OBJDIR)/utalloc.o\ + $(OBJDIR)/utcache.o\ + $(OBJDIR)/utcopy.o\ + $(OBJDIR)/utdebug.o\ + $(OBJDIR)/utdecode.o\ + $(OBJDIR)/utdelete.o\ + $(OBJDIR)/uteval.o\ + $(OBJDIR)/utexcep.o\ + $(OBJDIR)/utglobal.o\ + $(OBJDIR)/utids.o\ + $(OBJDIR)/utinit.o\ + $(OBJDIR)/utlock.o\ + $(OBJDIR)/utmath.o\ + $(OBJDIR)/utmisc.o\ + $(OBJDIR)/utmutex.o\ + $(OBJDIR)/utobject.o\ + $(OBJDIR)/utosi.o\ + $(OBJDIR)/utownerid.o\ + $(OBJDIR)/utresrc.o\ + $(OBJDIR)/utstate.o\ + $(OBJDIR)/utstring.o\ + $(OBJDIR)/uttrack.o\ + $(OBJDIR)/utxface.o\ + $(OBJDIR)/utxferror.o\ + $(OBJDIR)/utxfinit.o\ $(OBJDIR)/utxfmutex.o # # Flags specific to acpiexec utility # -CFLAGS+= \ - -DACPI_EXEC_APP \ +CFLAGS += \ + -DACPI_EXEC_APP\ -I$(ACPIEXEC) + LDFLAGS += -lpthread -lrt # diff --git a/generate/unix/acpihelp/Makefile b/generate/unix/acpihelp/Makefile index c44bffefb5f..817cf98feab 100644 --- a/generate/unix/acpihelp/Makefile +++ b/generate/unix/acpihelp/Makefile @@ -19,28 +19,28 @@ PROG = $(OBJDIR)/acpihelp # Search paths for source files # vpath %.c \ - $(ACPIHELP) \ - $(ACPICA_COMMON) \ + $(ACPIHELP)\ + $(ACPICA_COMMON)\ $(ACPICA_UTILITIES) HEADERS = \ $(wildcard $(ACPIHELP)/*.h) OBJECTS = \ - $(OBJDIR)/ahamlops.o \ - $(OBJDIR)/ahaslkey.o \ - $(OBJDIR)/ahaslops.o \ - $(OBJDIR)/ahdecode.o \ - $(OBJDIR)/ahpredef.o \ - $(OBJDIR)/ahmain.o \ - $(OBJDIR)/getopt.o \ + $(OBJDIR)/ahamlops.o\ + $(OBJDIR)/ahaslkey.o\ + $(OBJDIR)/ahaslops.o\ + $(OBJDIR)/ahdecode.o\ + $(OBJDIR)/ahpredef.o\ + $(OBJDIR)/ahmain.o\ + $(OBJDIR)/getopt.o\ $(OBJDIR)/utexcep.o # # Flags specific to acpihelp # -CFLAGS+= \ - -DACPI_HELP_APP \ +CFLAGS += \ + -DACPI_HELP_APP\ -I$(ACPIHELP) # diff --git a/generate/unix/acpinames/Makefile b/generate/unix/acpinames/Makefile index 6aa7666de0a..98d95866246 100644 --- a/generate/unix/acpinames/Makefile +++ b/generate/unix/acpinames/Makefile @@ -20,98 +20,98 @@ PROG = $(OBJDIR)/acpinames # Search paths for source files # vpath %.c \ - $(ACPINAMES) \ - $(ACPICA_DEBUGGER) \ - $(ACPICA_DISPATCHER) \ - $(ACPICA_EXECUTER) \ - $(ACPICA_NAMESPACE) \ - $(ACPICA_PARSER) \ - $(ACPICA_TABLES) \ - $(ACPICA_UTILITIES) \ - $(ACPICA_COMMON) \ + $(ACPINAMES)\ + $(ACPICA_DEBUGGER)\ + $(ACPICA_DISPATCHER)\ + $(ACPICA_EXECUTER)\ + $(ACPICA_NAMESPACE)\ + $(ACPICA_PARSER)\ + $(ACPICA_TABLES)\ + $(ACPICA_UTILITIES)\ + $(ACPICA_COMMON)\ $(ACPICA_OSL) HEADERS = \ $(wildcard $(ACPINAMES)/*.h) OBJECTS = \ - $(OBJDIR)/anmain.o \ - $(OBJDIR)/anstubs.o \ - $(OBJDIR)/antables.o \ - $(OBJDIR)/dbfileio.o \ - $(OBJDIR)/dsfield.o \ - $(OBJDIR)/dsmthdat.o \ - $(OBJDIR)/dsobject.o \ - $(OBJDIR)/dsutils.o \ - $(OBJDIR)/dswload.o \ - $(OBJDIR)/dswload2.o \ - $(OBJDIR)/dswscope.o \ - $(OBJDIR)/dswstate.o \ - $(OBJDIR)/excreate.o \ - $(OBJDIR)/exnames.o \ - $(OBJDIR)/exresnte.o \ - $(OBJDIR)/exresolv.o \ - $(OBJDIR)/exutils.o \ - $(OBJDIR)/getopt.o \ - $(OBJDIR)/nsaccess.o \ - $(OBJDIR)/nsalloc.o \ - $(OBJDIR)/nsdump.o \ - $(OBJDIR)/nsinit.o \ - $(OBJDIR)/nsload.o \ - $(OBJDIR)/nsnames.o \ - $(OBJDIR)/nsobject.o \ - $(OBJDIR)/nsparse.o \ - $(OBJDIR)/nssearch.o \ - $(OBJDIR)/nsutils.o \ - $(OBJDIR)/nswalk.o \ - $(OBJDIR)/nsxfeval.o \ - $(OBJDIR)/nsxfname.o \ - $(OBJDIR)/nsxfobj.o \ - $(OBJDIR)/osunixxf.o \ - $(OBJDIR)/psargs.o \ - $(OBJDIR)/psloop.o \ - $(OBJDIR)/psobject.o \ - $(OBJDIR)/psopcode.o \ - $(OBJDIR)/psopinfo.o \ - $(OBJDIR)/psparse.o \ - $(OBJDIR)/psscope.o \ - $(OBJDIR)/pstree.o \ - $(OBJDIR)/psutils.o \ - $(OBJDIR)/pswalk.o \ - $(OBJDIR)/psxface.o \ - $(OBJDIR)/tbfadt.o \ - $(OBJDIR)/tbfind.o \ - $(OBJDIR)/tbinstal.o \ - $(OBJDIR)/tbutils.o \ - $(OBJDIR)/tbxface.o \ - $(OBJDIR)/tbxfload.o \ - $(OBJDIR)/tbxfroot.o \ - $(OBJDIR)/utaddress.o \ - $(OBJDIR)/utalloc.o \ - $(OBJDIR)/utcache.o \ - $(OBJDIR)/utdebug.o \ - $(OBJDIR)/utdecode.o \ - $(OBJDIR)/utdelete.o \ - $(OBJDIR)/utexcep.o \ - $(OBJDIR)/utglobal.o \ - $(OBJDIR)/utlock.o \ - $(OBJDIR)/utmath.o \ - $(OBJDIR)/utmisc.o \ - $(OBJDIR)/utmutex.o \ - $(OBJDIR)/utobject.o \ - $(OBJDIR)/utosi.o \ - $(OBJDIR)/utownerid.o \ - $(OBJDIR)/utstate.o \ - $(OBJDIR)/utstring.o \ - $(OBJDIR)/utxface.o \ - $(OBJDIR)/utxferror.o \ + $(OBJDIR)/anmain.o\ + $(OBJDIR)/anstubs.o\ + $(OBJDIR)/antables.o\ + $(OBJDIR)/dbfileio.o\ + $(OBJDIR)/dsfield.o\ + $(OBJDIR)/dsmthdat.o\ + $(OBJDIR)/dsobject.o\ + $(OBJDIR)/dsutils.o\ + $(OBJDIR)/dswload.o\ + $(OBJDIR)/dswload2.o\ + $(OBJDIR)/dswscope.o\ + $(OBJDIR)/dswstate.o\ + $(OBJDIR)/excreate.o\ + $(OBJDIR)/exnames.o\ + $(OBJDIR)/exresnte.o\ + $(OBJDIR)/exresolv.o\ + $(OBJDIR)/exutils.o\ + $(OBJDIR)/getopt.o\ + $(OBJDIR)/nsaccess.o\ + $(OBJDIR)/nsalloc.o\ + $(OBJDIR)/nsdump.o\ + $(OBJDIR)/nsinit.o\ + $(OBJDIR)/nsload.o\ + $(OBJDIR)/nsnames.o\ + $(OBJDIR)/nsobject.o\ + $(OBJDIR)/nsparse.o\ + $(OBJDIR)/nssearch.o\ + $(OBJDIR)/nsutils.o\ + $(OBJDIR)/nswalk.o\ + $(OBJDIR)/nsxfeval.o\ + $(OBJDIR)/nsxfname.o\ + $(OBJDIR)/nsxfobj.o\ + $(OBJDIR)/osunixxf.o\ + $(OBJDIR)/psargs.o\ + $(OBJDIR)/psloop.o\ + $(OBJDIR)/psobject.o\ + $(OBJDIR)/psopcode.o\ + $(OBJDIR)/psopinfo.o\ + $(OBJDIR)/psparse.o\ + $(OBJDIR)/psscope.o\ + $(OBJDIR)/pstree.o\ + $(OBJDIR)/psutils.o\ + $(OBJDIR)/pswalk.o\ + $(OBJDIR)/psxface.o\ + $(OBJDIR)/tbfadt.o\ + $(OBJDIR)/tbfind.o\ + $(OBJDIR)/tbinstal.o\ + $(OBJDIR)/tbutils.o\ + $(OBJDIR)/tbxface.o\ + $(OBJDIR)/tbxfload.o\ + $(OBJDIR)/tbxfroot.o\ + $(OBJDIR)/utaddress.o\ + $(OBJDIR)/utalloc.o\ + $(OBJDIR)/utcache.o\ + $(OBJDIR)/utdebug.o\ + $(OBJDIR)/utdecode.o\ + $(OBJDIR)/utdelete.o\ + $(OBJDIR)/utexcep.o\ + $(OBJDIR)/utglobal.o\ + $(OBJDIR)/utlock.o\ + $(OBJDIR)/utmath.o\ + $(OBJDIR)/utmisc.o\ + $(OBJDIR)/utmutex.o\ + $(OBJDIR)/utobject.o\ + $(OBJDIR)/utosi.o\ + $(OBJDIR)/utownerid.o\ + $(OBJDIR)/utstate.o\ + $(OBJDIR)/utstring.o\ + $(OBJDIR)/utxface.o\ + $(OBJDIR)/utxferror.o\ $(OBJDIR)/utxfinit.o # # Flags specific to acpinames utility # -CFLAGS+= \ - -DACPI_NAMES_APP \ +CFLAGS += \ + -DACPI_NAMES_APP\ -I$(ACPINAMES) # diff --git a/generate/unix/acpisrc/Makefile b/generate/unix/acpisrc/Makefile index 9c9c578c419..bf878179a7f 100644 --- a/generate/unix/acpisrc/Makefile +++ b/generate/unix/acpisrc/Makefile @@ -18,29 +18,29 @@ PROG = $(OBJDIR)/acpisrc # Search path for source files and individual source files # vpath %.c \ - $(ACPISRC) \ - $(ACPICA_COMMON) \ + $(ACPISRC)\ + $(ACPICA_COMMON)\ $(ACPICA_OSL) HEADERS = \ $(wildcard $(ACPISRC)/*.h) OBJECTS = \ - $(OBJDIR)/ascase.o \ - $(OBJDIR)/asconvrt.o \ - $(OBJDIR)/asfile.o \ - $(OBJDIR)/asmain.o \ - $(OBJDIR)/asremove.o \ - $(OBJDIR)/astable.o \ - $(OBJDIR)/asutils.o \ - $(OBJDIR)/osunixdir.o \ + $(OBJDIR)/ascase.o\ + $(OBJDIR)/asconvrt.o\ + $(OBJDIR)/asfile.o\ + $(OBJDIR)/asmain.o\ + $(OBJDIR)/asremove.o\ + $(OBJDIR)/astable.o\ + $(OBJDIR)/asutils.o\ + $(OBJDIR)/osunixdir.o\ $(OBJDIR)/getopt.o # # Compile flags specific to acpisrc # -CFLAGS+= \ - -DACPI_SRC_APP \ +CFLAGS += \ + -DACPI_SRC_APP\ -I$(ACPISRC) # diff --git a/generate/unix/acpixtract/Makefile b/generate/unix/acpixtract/Makefile index 183aa0d94b5..1e5b1013d43 100644 --- a/generate/unix/acpixtract/Makefile +++ b/generate/unix/acpixtract/Makefile @@ -18,22 +18,22 @@ PROG = $(OBJDIR)/acpixtract # Search paths for source files # vpath %.c \ - $(ACPIXTRACT) \ + $(ACPIXTRACT)\ $(ACPICA_COMMON) HEADERS = \ $(wildcard $(ACPIXTRACT)/*.h) OBJECTS = \ - $(OBJDIR)/acpixtract.o \ - $(OBJDIR)/axmain.o \ + $(OBJDIR)/acpixtract.o\ + $(OBJDIR)/axmain.o\ $(OBJDIR)/getopt.o # # Flags specific to acpixtract # -CFLAGS+= \ - -DACPI_XTRACT_APP \ +CFLAGS += \ + -DACPI_XTRACT_APP # # Common Rules diff --git a/generate/unix/iasl/Makefile b/generate/unix/iasl/Makefile index 6ebe16bba00..0f66301b11b 100644 --- a/generate/unix/iasl/Makefile +++ b/generate/unix/iasl/Makefile @@ -18,206 +18,207 @@ PROG = $(OBJDIR)/iasl # Search paths for source files # vpath %.c \ - $(ASL_COMPILER) \ - $(ACPICA_DEBUGGER) \ - $(ACPICA_DISASSEMBLER) \ - $(ACPICA_DISPATCHER) \ - $(ACPICA_EXECUTER) \ - $(ACPICA_NAMESPACE) \ - $(ACPICA_PARSER) \ - $(ACPICA_TABLES) \ - $(ACPICA_UTILITIES) \ - $(ACPICA_COMMON) \ + $(ASL_COMPILER)\ + $(ACPICA_DEBUGGER)\ + $(ACPICA_DISASSEMBLER)\ + $(ACPICA_DISPATCHER)\ + $(ACPICA_EXECUTER)\ + $(ACPICA_NAMESPACE)\ + $(ACPICA_PARSER)\ + $(ACPICA_TABLES)\ + $(ACPICA_UTILITIES)\ + $(ACPICA_COMMON)\ $(ACPICA_OSL) HEADERS = \ - $(wildcard $(ASL_COMPILER)/*.h) \ - $(OBJDIR)/aslcompiler.y.h \ - $(OBJDIR)/dtparser.y.h \ + $(wildcard $(ASL_COMPILER)/*.h)\ + $(OBJDIR)/aslcompiler.y.h\ + $(OBJDIR)/dtparser.y.h\ $(OBJDIR)/prparser.y.h OBJECTS = \ - $(OBJDIR)/aslcompilerlex.o \ - $(OBJDIR)/aslcompilerparse.o \ - $(OBJDIR)/dtparserlex.o \ - $(OBJDIR)/dtparserparse.o \ - $(OBJDIR)/prparserlex.o \ - $(OBJDIR)/prparserparse.o \ - $(OBJDIR)/adfile.o \ - $(OBJDIR)/adisasm.o \ - $(OBJDIR)/adwalk.o \ - $(OBJDIR)/ahpredef.o \ - $(OBJDIR)/aslanalyze.o \ - $(OBJDIR)/aslbtypes.o \ - $(OBJDIR)/aslcodegen.o \ - $(OBJDIR)/aslcompile.o \ - $(OBJDIR)/aslerror.o \ - $(OBJDIR)/aslfiles.o \ - $(OBJDIR)/aslfileio.o \ - $(OBJDIR)/aslfold.o \ - $(OBJDIR)/aslhex.o \ - $(OBJDIR)/asllength.o \ - $(OBJDIR)/asllisting.o \ - $(OBJDIR)/aslload.o \ - $(OBJDIR)/asllookup.o \ - $(OBJDIR)/aslmain.o \ - $(OBJDIR)/aslmap.o \ - $(OBJDIR)/aslmethod.o \ - $(OBJDIR)/aslnamesp.o \ - $(OBJDIR)/aslopcodes.o \ - $(OBJDIR)/asloperands.o \ - $(OBJDIR)/aslopt.o \ - $(OBJDIR)/aslpredef.o \ - $(OBJDIR)/aslresource.o \ - $(OBJDIR)/aslrestype1.o \ - $(OBJDIR)/aslrestype1i.o \ - $(OBJDIR)/aslrestype2.o \ - $(OBJDIR)/aslrestype2d.o \ - $(OBJDIR)/aslrestype2e.o \ - $(OBJDIR)/aslrestype2q.o \ - $(OBJDIR)/aslrestype2s.o \ - $(OBJDIR)/aslrestype2w.o \ - $(OBJDIR)/aslstartup.o \ - $(OBJDIR)/aslstubs.o \ - $(OBJDIR)/asltransform.o \ - $(OBJDIR)/asltree.o \ - $(OBJDIR)/aslutils.o \ - $(OBJDIR)/asluuid.o \ - $(OBJDIR)/aslwalks.o \ - $(OBJDIR)/aslxref.o \ - $(OBJDIR)/dtcompile.o \ - $(OBJDIR)/dtexpress.o \ - $(OBJDIR)/dtfield.o \ - $(OBJDIR)/dtio.o \ - $(OBJDIR)/dtsubtable.o \ - $(OBJDIR)/dttable.o \ - $(OBJDIR)/dttemplate.o \ - $(OBJDIR)/dtutils.o \ - $(OBJDIR)/dbfileio.o \ - $(OBJDIR)/dmbuffer.o \ - $(OBJDIR)/dmdeferred.o \ - $(OBJDIR)/dmextern.o \ - $(OBJDIR)/dmnames.o \ - $(OBJDIR)/dmobject.o \ - $(OBJDIR)/dmopcode.o \ - $(OBJDIR)/dmresrc.o \ - $(OBJDIR)/dmresrcl.o \ - $(OBJDIR)/dmresrcl2.o \ - $(OBJDIR)/dmresrcs.o \ - $(OBJDIR)/dmrestag.o \ - $(OBJDIR)/dmtable.o \ - $(OBJDIR)/dmtbdump.o \ - $(OBJDIR)/dmtbinfo.o \ - $(OBJDIR)/dmutils.o \ - $(OBJDIR)/dmwalk.o \ - $(OBJDIR)/dsargs.o \ - $(OBJDIR)/dscontrol.o \ - $(OBJDIR)/dsfield.o \ - $(OBJDIR)/dsobject.o \ - $(OBJDIR)/dsopcode.o \ - $(OBJDIR)/dsutils.o \ - $(OBJDIR)/dswexec.o \ - $(OBJDIR)/dswload.o \ - $(OBJDIR)/dswload2.o \ - $(OBJDIR)/dswscope.o \ - $(OBJDIR)/dswstate.o \ - $(OBJDIR)/exconvrt.o \ - $(OBJDIR)/excreate.o \ - $(OBJDIR)/exdump.o \ - $(OBJDIR)/exmisc.o \ - $(OBJDIR)/exmutex.o \ - $(OBJDIR)/exnames.o \ - $(OBJDIR)/exoparg1.o \ - $(OBJDIR)/exoparg2.o \ - $(OBJDIR)/exoparg3.o \ - $(OBJDIR)/exoparg6.o \ - $(OBJDIR)/exprep.o \ - $(OBJDIR)/exregion.o \ - $(OBJDIR)/exresnte.o \ - $(OBJDIR)/exresolv.o \ - $(OBJDIR)/exresop.o \ - $(OBJDIR)/exstore.o \ - $(OBJDIR)/exstoren.o \ - $(OBJDIR)/exstorob.o \ - $(OBJDIR)/exsystem.o \ - $(OBJDIR)/exutils.o \ - $(OBJDIR)/getopt.o \ - $(OBJDIR)/nsaccess.o \ - $(OBJDIR)/nsalloc.o \ - $(OBJDIR)/nsdump.o \ - $(OBJDIR)/nsnames.o \ - $(OBJDIR)/nsobject.o \ - $(OBJDIR)/nsparse.o \ - $(OBJDIR)/nssearch.o \ - $(OBJDIR)/nsutils.o \ - $(OBJDIR)/nswalk.o \ - $(OBJDIR)/nsxfobj.o \ - $(OBJDIR)/osunixxf.o \ - $(OBJDIR)/prexpress.o \ - $(OBJDIR)/prmacros.o \ - $(OBJDIR)/prscan.o \ - $(OBJDIR)/prutils.o \ - $(OBJDIR)/psargs.o \ - $(OBJDIR)/psloop.o \ - $(OBJDIR)/psobject.o \ - $(OBJDIR)/psopcode.o \ - $(OBJDIR)/psopinfo.o \ - $(OBJDIR)/psparse.o \ - $(OBJDIR)/psscope.o \ - $(OBJDIR)/pstree.o \ - $(OBJDIR)/psutils.o \ - $(OBJDIR)/pswalk.o \ - $(OBJDIR)/tbfadt.o \ - $(OBJDIR)/tbinstal.o \ - $(OBJDIR)/tbutils.o \ - $(OBJDIR)/tbxface.o \ - $(OBJDIR)/utaddress.o \ - $(OBJDIR)/utalloc.o \ - $(OBJDIR)/utcache.o \ - $(OBJDIR)/utcopy.o \ - $(OBJDIR)/utdebug.o \ - $(OBJDIR)/utdecode.o \ - $(OBJDIR)/utdelete.o \ - $(OBJDIR)/utexcep.o \ - $(OBJDIR)/utglobal.o \ - $(OBJDIR)/utinit.o \ - $(OBJDIR)/utlock.o \ - $(OBJDIR)/utmath.o \ - $(OBJDIR)/utmisc.o \ - $(OBJDIR)/utmutex.o \ - $(OBJDIR)/utobject.o \ - $(OBJDIR)/utownerid.o \ - $(OBJDIR)/utresrc.o \ - $(OBJDIR)/utstate.o \ - $(OBJDIR)/utstring.o \ - $(OBJDIR)/utxface.o \ + $(OBJDIR)/aslcompilerlex.o\ + $(OBJDIR)/aslcompilerparse.o\ + $(OBJDIR)/dtparserlex.o\ + $(OBJDIR)/dtparserparse.o\ + $(OBJDIR)/prparserlex.o\ + $(OBJDIR)/prparserparse.o\ + $(OBJDIR)/adfile.o\ + $(OBJDIR)/adisasm.o\ + $(OBJDIR)/adwalk.o\ + $(OBJDIR)/ahpredef.o\ + $(OBJDIR)/aslanalyze.o\ + $(OBJDIR)/aslbtypes.o\ + $(OBJDIR)/aslcodegen.o\ + $(OBJDIR)/aslcompile.o\ + $(OBJDIR)/aslerror.o\ + $(OBJDIR)/aslfiles.o\ + $(OBJDIR)/aslfileio.o\ + $(OBJDIR)/aslfold.o\ + $(OBJDIR)/aslhex.o\ + $(OBJDIR)/asllength.o\ + $(OBJDIR)/asllisting.o\ + $(OBJDIR)/aslload.o\ + $(OBJDIR)/asllookup.o\ + $(OBJDIR)/aslmain.o\ + $(OBJDIR)/aslmap.o\ + $(OBJDIR)/aslmethod.o\ + $(OBJDIR)/aslnamesp.o\ + $(OBJDIR)/aslopcodes.o\ + $(OBJDIR)/asloperands.o\ + $(OBJDIR)/aslopt.o\ + $(OBJDIR)/aslpredef.o\ + $(OBJDIR)/aslprepkg.o\ + $(OBJDIR)/aslresource.o\ + $(OBJDIR)/aslrestype1.o\ + $(OBJDIR)/aslrestype1i.o\ + $(OBJDIR)/aslrestype2.o\ + $(OBJDIR)/aslrestype2d.o\ + $(OBJDIR)/aslrestype2e.o\ + $(OBJDIR)/aslrestype2q.o\ + $(OBJDIR)/aslrestype2s.o\ + $(OBJDIR)/aslrestype2w.o\ + $(OBJDIR)/aslstartup.o\ + $(OBJDIR)/aslstubs.o\ + $(OBJDIR)/asltransform.o\ + $(OBJDIR)/asltree.o\ + $(OBJDIR)/aslutils.o\ + $(OBJDIR)/asluuid.o\ + $(OBJDIR)/aslwalks.o\ + $(OBJDIR)/aslxref.o\ + $(OBJDIR)/dtcompile.o\ + $(OBJDIR)/dtexpress.o\ + $(OBJDIR)/dtfield.o\ + $(OBJDIR)/dtio.o\ + $(OBJDIR)/dtsubtable.o\ + $(OBJDIR)/dttable.o\ + $(OBJDIR)/dttemplate.o\ + $(OBJDIR)/dtutils.o\ + $(OBJDIR)/dbfileio.o\ + $(OBJDIR)/dmbuffer.o\ + $(OBJDIR)/dmdeferred.o\ + $(OBJDIR)/dmextern.o\ + $(OBJDIR)/dmnames.o\ + $(OBJDIR)/dmobject.o\ + $(OBJDIR)/dmopcode.o\ + $(OBJDIR)/dmresrc.o\ + $(OBJDIR)/dmresrcl.o\ + $(OBJDIR)/dmresrcl2.o\ + $(OBJDIR)/dmresrcs.o\ + $(OBJDIR)/dmrestag.o\ + $(OBJDIR)/dmtable.o\ + $(OBJDIR)/dmtbdump.o\ + $(OBJDIR)/dmtbinfo.o\ + $(OBJDIR)/dmutils.o\ + $(OBJDIR)/dmwalk.o\ + $(OBJDIR)/dsargs.o\ + $(OBJDIR)/dscontrol.o\ + $(OBJDIR)/dsfield.o\ + $(OBJDIR)/dsobject.o\ + $(OBJDIR)/dsopcode.o\ + $(OBJDIR)/dsutils.o\ + $(OBJDIR)/dswexec.o\ + $(OBJDIR)/dswload.o\ + $(OBJDIR)/dswload2.o\ + $(OBJDIR)/dswscope.o\ + $(OBJDIR)/dswstate.o\ + $(OBJDIR)/exconvrt.o\ + $(OBJDIR)/excreate.o\ + $(OBJDIR)/exdump.o\ + $(OBJDIR)/exmisc.o\ + $(OBJDIR)/exmutex.o\ + $(OBJDIR)/exnames.o\ + $(OBJDIR)/exoparg1.o\ + $(OBJDIR)/exoparg2.o\ + $(OBJDIR)/exoparg3.o\ + $(OBJDIR)/exoparg6.o\ + $(OBJDIR)/exprep.o\ + $(OBJDIR)/exregion.o\ + $(OBJDIR)/exresnte.o\ + $(OBJDIR)/exresolv.o\ + $(OBJDIR)/exresop.o\ + $(OBJDIR)/exstore.o\ + $(OBJDIR)/exstoren.o\ + $(OBJDIR)/exstorob.o\ + $(OBJDIR)/exsystem.o\ + $(OBJDIR)/exutils.o\ + $(OBJDIR)/getopt.o\ + $(OBJDIR)/nsaccess.o\ + $(OBJDIR)/nsalloc.o\ + $(OBJDIR)/nsdump.o\ + $(OBJDIR)/nsnames.o\ + $(OBJDIR)/nsobject.o\ + $(OBJDIR)/nsparse.o\ + $(OBJDIR)/nssearch.o\ + $(OBJDIR)/nsutils.o\ + $(OBJDIR)/nswalk.o\ + $(OBJDIR)/nsxfobj.o\ + $(OBJDIR)/osunixxf.o\ + $(OBJDIR)/prexpress.o\ + $(OBJDIR)/prmacros.o\ + $(OBJDIR)/prscan.o\ + $(OBJDIR)/prutils.o\ + $(OBJDIR)/psargs.o\ + $(OBJDIR)/psloop.o\ + $(OBJDIR)/psobject.o\ + $(OBJDIR)/psopcode.o\ + $(OBJDIR)/psopinfo.o\ + $(OBJDIR)/psparse.o\ + $(OBJDIR)/psscope.o\ + $(OBJDIR)/pstree.o\ + $(OBJDIR)/psutils.o\ + $(OBJDIR)/pswalk.o\ + $(OBJDIR)/tbfadt.o\ + $(OBJDIR)/tbinstal.o\ + $(OBJDIR)/tbutils.o\ + $(OBJDIR)/tbxface.o\ + $(OBJDIR)/utaddress.o\ + $(OBJDIR)/utalloc.o\ + $(OBJDIR)/utcache.o\ + $(OBJDIR)/utcopy.o\ + $(OBJDIR)/utdebug.o\ + $(OBJDIR)/utdecode.o\ + $(OBJDIR)/utdelete.o\ + $(OBJDIR)/utexcep.o\ + $(OBJDIR)/utglobal.o\ + $(OBJDIR)/utinit.o\ + $(OBJDIR)/utlock.o\ + $(OBJDIR)/utmath.o\ + $(OBJDIR)/utmisc.o\ + $(OBJDIR)/utmutex.o\ + $(OBJDIR)/utobject.o\ + $(OBJDIR)/utownerid.o\ + $(OBJDIR)/utresrc.o\ + $(OBJDIR)/utstate.o\ + $(OBJDIR)/utstring.o\ + $(OBJDIR)/utxface.o\ $(OBJDIR)/utxferror.o INTERMEDIATES = \ - $(OBJDIR)/aslcompilerlex.c \ - $(OBJDIR)/aslcompilerparse.c \ - $(OBJDIR)/dtparserlex.c \ - $(OBJDIR)/dtparserparse.c \ - $(OBJDIR)/prparserlex.c \ + $(OBJDIR)/aslcompilerlex.c\ + $(OBJDIR)/aslcompilerparse.c\ + $(OBJDIR)/dtparserlex.c\ + $(OBJDIR)/dtparserparse.c\ + $(OBJDIR)/prparserlex.c\ $(OBJDIR)/prparserparse.c MISC = \ - $(OBJDIR)/aslcompilerparse.h \ - $(OBJDIR)/aslcompiler.y.h \ - $(OBJDIR)/aslcompilerparse.output \ - $(OBJDIR)/dtparserparse.h \ - $(OBJDIR)/dtparser.y.h \ - $(OBJDIR)/dtparserparse.output \ - $(OBJDIR)/prparserparse.h \ - $(OBJDIR)/prparser.y.h \ + $(OBJDIR)/aslcompilerparse.h\ + $(OBJDIR)/aslcompiler.y.h\ + $(OBJDIR)/aslcompilerparse.output\ + $(OBJDIR)/dtparserparse.h\ + $(OBJDIR)/dtparser.y.h\ + $(OBJDIR)/dtparserparse.output\ + $(OBJDIR)/prparserparse.h\ + $(OBJDIR)/prparser.y.h\ $(OBJDIR)/prparserparse.output # # Flags specific to iASL compiler # -CFLAGS+= \ - -DACPI_ASL_COMPILER \ - -I$(ASL_COMPILER) \ +CFLAGS += \ + -DACPI_ASL_COMPILER\ + -I$(ASL_COMPILER)\ -I$(OBJDIR) # diff --git a/source/common/adisasm.c b/source/common/adisasm.c index c5fcf81ab72..511366faac2 100644 --- a/source/common/adisasm.c +++ b/source/common/adisasm.c @@ -372,7 +372,7 @@ AdAmlDisassemble ( } /* - * Output: ASL code. Redirect to a file if requested + * Output: ASL code. Redirect to a file if requested */ if (OutToFile) { @@ -540,11 +540,6 @@ Cleanup: ACPI_FREE (Table); } - if (DisasmFilename) - { - ACPI_FREE (DisasmFilename); - } - if (OutToFile && File) { if (AslCompilerdebug) /* Display final namespace, with transforms */ @@ -667,7 +662,7 @@ AdCreateTableHeader ( AcpiOsPrintf (" * OEM Revision 0x%8.8X (%u)\n", Table->OemRevision, Table->OemRevision); AcpiOsPrintf (" * Compiler ID \"%.4s\"\n", Table->AslCompilerId); AcpiOsPrintf (" * Compiler Version 0x%8.8X (%u)\n", Table->AslCompilerRevision, Table->AslCompilerRevision); - AcpiOsPrintf (" */\n\n"); + AcpiOsPrintf (" */\n"); /* Create AML output filename based on input filename */ diff --git a/source/common/adwalk.c b/source/common/adwalk.c index d1c6d74fd93..0a3a8485fe7 100644 --- a/source/common/adwalk.c +++ b/source/common/adwalk.c @@ -837,7 +837,7 @@ AcpiDmXrefDescendingOp ( } } - AcpiDmAddToExternalList (Op, Path, (UINT8) ObjectType2, ParamCount); + AcpiDmAddToExternalList (Op, Path, (UINT8) ObjectType2, ParamCount | 0x80); Op->Common.Node = Node; } else diff --git a/source/common/dmextern.c b/source/common/dmextern.c index 501a9ee3d9c..7825ab11acb 100644 --- a/source/common/dmextern.c +++ b/source/common/dmextern.c @@ -46,6 +46,7 @@ #include "amlcode.h" #include "acnamesp.h" #include "acdisasm.h" +#include /* @@ -373,6 +374,7 @@ AcpiDmAddToExternalList ( ACPI_EXTERNAL_LIST *NextExternal; ACPI_EXTERNAL_LIST *PrevExternal = NULL; ACPI_STATUS Status; + BOOLEAN Resolved = FALSE; if (!Path) @@ -380,6 +382,15 @@ AcpiDmAddToExternalList ( return; } + if (Type == ACPI_TYPE_METHOD) + { + if (Value & 0x80) + { + Resolved = TRUE; + } + Value &= 0x07; + } + /* * We don't want External() statements to contain a leading '\'. * This prevents duplicate external statements of the form: @@ -464,6 +475,7 @@ AcpiDmAddToExternalList ( NewExternal->Path = ExternalPath; NewExternal->Type = Type; NewExternal->Value = Value; + NewExternal->Resolved = Resolved; NewExternal->Length = (UINT16) ACPI_STRLEN (ExternalPath); /* Was the external path with parent prefix normalized to a fullpath? */ @@ -683,6 +695,29 @@ AcpiDmEmitExternals ( return; } + /* + * Determine the number of control methods in the external list, and + * also how many of those externals were resolved via the namespace. + */ + NextExternal = AcpiGbl_ExternalList; + while (NextExternal) + { + if (NextExternal->Type == ACPI_TYPE_METHOD) + { + AcpiGbl_NumExternalMethods++; + if (NextExternal->Resolved) + { + AcpiGbl_ResolvedExternalMethods++; + } + } + + NextExternal = NextExternal->Next; + } + + /* Check if any control methods were unresolved */ + + AcpiDmUnresolvedWarning (1); + /* * Walk the list of externals (unresolved references) * found during the AML parsing @@ -695,8 +730,17 @@ AcpiDmEmitExternals ( if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD) { - AcpiOsPrintf (") // %u Arguments\n", - AcpiGbl_ExternalList->Value); + if (AcpiGbl_ExternalList->Resolved) + { + AcpiOsPrintf (") // %u Arguments\n", + AcpiGbl_ExternalList->Value); + } + else + { + AcpiOsPrintf (") // Warning: unresolved Method, " + "assuming %u arguments (may be incorrect, see warning above)\n", + AcpiGbl_ExternalList->Value); + } } else { @@ -718,3 +762,173 @@ AcpiDmEmitExternals ( AcpiOsPrintf ("\n"); } + + +/******************************************************************************* + * + * FUNCTION: AcpiDmUnresolvedWarning + * + * PARAMETERS: Type - Where to output the warning. + * 0 means write to stderr + * 1 means write to AcpiOsPrintf + * + * RETURN: None + * + * DESCRIPTION: Issue warning message if there are unresolved external control + * methods within the disassembly. + * + ******************************************************************************/ + +#if 0 +Summary of the external control method problem: + +When the -e option is used with disassembly, the various SSDTs are simply +loaded into a global namespace for the disassembler to use in order to +resolve control method references (invocations). + +The disassembler tracks any such references, and will emit an External() +statement for these types of methods, with the proper number of arguments . + +Without the SSDTs, the AML does not contain enough information to properly +disassemble the control method invocation -- because the disassembler does +not know how many arguments to parse. + +An example: Assume we have two control methods. ABCD has one argument, and +EFGH has zero arguments. Further, we have two additional control methods +that invoke ABCD and EFGH, named T1 and T2: + + Method (ABCD, 1) + { + } + Method (EFGH, 0) + { + } + Method (T1) + { + ABCD (Add (2, 7, Local0)) + } + Method (T2) + { + EFGH () + Add (2, 7, Local0) + } + +Here is the AML code that is generated for T1 and T2: + + 185: Method (T1) + +0000034C: 14 10 54 31 5F 5F 00 ... "..T1__." + + 186: { + 187: ABCD (Add (2, 7, Local0)) + +00000353: 41 42 43 44 ............ "ABCD" +00000357: 72 0A 02 0A 07 60 ...... "r....`" + + 188: } + + 190: Method (T2) + +0000035D: 14 10 54 32 5F 5F 00 ... "..T2__." + + 191: { + 192: EFGH () + +00000364: 45 46 47 48 ............ "EFGH" + + 193: Add (2, 7, Local0) + +00000368: 72 0A 02 0A 07 60 ...... "r....`" + 194: } + +Note that the AML code for T1 and T2 is essentially identical. When +disassembling this code, the methods ABCD and EFGH must be known to the +disassembler, otherwise it does not know how to handle the method invocations. + +In other words, if ABCD and EFGH are actually external control methods +appearing in an SSDT, the disassembler does not know what to do unless +the owning SSDT has been loaded via the -e option. +#endif + +void +AcpiDmUnresolvedWarning ( + UINT8 Type) +{ + + if (!AcpiGbl_NumExternalMethods) + { + return; + } + + if (Type) + { + if (!AcpiGbl_ExternalFileList) + { + /* The -e option was not specified */ + + AcpiOsPrintf (" /*\n" + " * iASL Warning: There were %u external control methods found during\n" + " * disassembly, but additional ACPI tables to resolve these externals\n" + " * were not specified. This resulting disassembler output file may not\n" + " * compile because the disassembler did not know how many arguments\n" + " * to assign to these methods. To specify the tables needed to resolve\n" + " * external control method references, use the one of the following\n" + " * example iASL invocations:\n" + " * iasl -e -d \n" + " * iasl -e -d \n" + " */\n", + AcpiGbl_NumExternalMethods); + } + else if (AcpiGbl_NumExternalMethods != AcpiGbl_ResolvedExternalMethods) + { + /* The -e option was specified, but there are still some unresolved externals */ + + AcpiOsPrintf (" /*\n" + " * iASL Warning: There were %u external control methods found during\n" + " * disassembly, but only %u %s resolved (%u unresolved). Additional\n" + " * ACPI tables are required to properly disassemble the code. This\n" + " * resulting disassembler output file may not compile because the\n" + " * disassembler did not know how many arguments to assign to the\n" + " * unresolved methods.\n" + " */\n", + AcpiGbl_NumExternalMethods, AcpiGbl_ResolvedExternalMethods, + (AcpiGbl_ResolvedExternalMethods > 1 ? "were" : "was"), + (AcpiGbl_NumExternalMethods - AcpiGbl_ResolvedExternalMethods)); + } + } + else + { + if (!AcpiGbl_ExternalFileList) + { + /* The -e option was not specified */ + + fprintf (stderr, "\n" + "iASL Warning: There were %u external control methods found during\n" + "disassembly, but additional ACPI tables to resolve these externals\n" + "were not specified. The resulting disassembler output file may not\n" + "compile because the disassembler did not know how many arguments\n" + "to assign to these methods. To specify the tables needed to resolve\n" + "external control method references, use the one of the following\n" + "example iASL invocations:\n" + " iasl -e -d \n" + " iasl -e -d \n", + AcpiGbl_NumExternalMethods); + } + else if (AcpiGbl_NumExternalMethods != AcpiGbl_ResolvedExternalMethods) + { + /* The -e option was specified, but there are still some unresolved externals */ + + fprintf (stderr, "\n" + "iASL Warning: There were %u external control methods found during\n" + "disassembly, but only %u %s resolved (%u unresolved). Additional\n" + "ACPI tables are required to properly disassemble the code. The\n" + "resulting disassembler output file may not compile because the\n" + "disassembler did not know how many arguments to assign to the\n" + "unresolved methods.\n", + AcpiGbl_NumExternalMethods, AcpiGbl_ResolvedExternalMethods, + (AcpiGbl_ResolvedExternalMethods > 1 ? "were" : "was"), + (AcpiGbl_NumExternalMethods - AcpiGbl_ResolvedExternalMethods)); + } + } + +} diff --git a/source/common/dmtable.c b/source/common/dmtable.c index cde16643d21..0c1c39b99ea 100644 --- a/source/common/dmtable.c +++ b/source/common/dmtable.c @@ -299,6 +299,7 @@ ACPI_DMTABLE_DATA AcpiDmTableData[] = {ACPI_SIG_MCHI, AcpiDmTableInfoMchi, NULL, NULL, TemplateMchi, "Management Controller Host Interface table"}, {ACPI_SIG_MPST, AcpiDmTableInfoMpst, AcpiDmDumpMpst, DtCompileMpst, TemplateMpst, "Memory Power State Table"}, {ACPI_SIG_MSCT, NULL, AcpiDmDumpMsct, DtCompileMsct, TemplateMsct, "Maximum System Characteristics Table"}, + {ACPI_SIG_MTMR, NULL, AcpiDmDumpMtmr, DtCompileMtmr, TemplateMtmr, "MID Timer Table"}, {ACPI_SIG_PCCT, NULL, AcpiDmDumpPcct, NULL, NULL, "Platform Communications Channel Table"}, {ACPI_SIG_PMTT, NULL, AcpiDmDumpPmtt, DtCompilePmtt, TemplatePmtt, "Platform Memory Topology Table"}, {ACPI_SIG_RSDT, NULL, AcpiDmDumpRsdt, DtCompileRsdt, TemplateRsdt, "Root System Description Table"}, @@ -312,6 +313,7 @@ ACPI_DMTABLE_DATA AcpiDmTableData[] = {ACPI_SIG_TCPA, AcpiDmTableInfoTcpa, NULL, NULL, TemplateTcpa, "Trusted Computing Platform Alliance table"}, {ACPI_SIG_TPM2, AcpiDmTableInfoTpm2, NULL, NULL, TemplateTpm2, "Trusted Platform Module hardware interface table"}, {ACPI_SIG_UEFI, AcpiDmTableInfoUefi, NULL, DtCompileUefi, TemplateUefi, "UEFI Boot Optimization Table"}, + {ACPI_SIG_VRTC, AcpiDmTableInfoVrtc, AcpiDmDumpVrtc, DtCompileVrtc, TemplateVrtc, "Virtual Real-Time Clock Table"}, {ACPI_SIG_WAET, AcpiDmTableInfoWaet, NULL, NULL, TemplateWaet, "Windows ACPI Emulated Devices Table"}, {ACPI_SIG_WDAT, NULL, AcpiDmDumpWdat, DtCompileWdat, TemplateWdat, "Watchdog Action Table"}, {ACPI_SIG_WDDT, AcpiDmTableInfoWddt, NULL, NULL, TemplateWddt, "Watchdog Description Table"}, @@ -475,6 +477,8 @@ AcpiDmDumpDataTable ( { AcpiOsPrintf ("\n**** Unknown ACPI table type [%4.4s]\n\n", Table->Signature); + fprintf (stderr, "Unknown ACPI table signature [%4.4s], decoding header only\n", + Table->Signature); } } else if (TableData->TableHandler) diff --git a/source/common/dmtbdump.c b/source/common/dmtbdump.c index c5a5cef67c1..b5e052e7de3 100644 --- a/source/common/dmtbdump.c +++ b/source/common/dmtbdump.c @@ -1794,6 +1794,58 @@ AcpiDmDumpMsct ( } +/******************************************************************************* + * + * FUNCTION: AcpiDmDumpMtmr + * + * PARAMETERS: Table - A MTMR table + * + * RETURN: None + * + * DESCRIPTION: Format the contents of a MTMR + * + ******************************************************************************/ + +void +AcpiDmDumpMtmr ( + ACPI_TABLE_HEADER *Table) +{ + ACPI_STATUS Status; + UINT32 Offset = sizeof (ACPI_TABLE_MTMR); + ACPI_MTMR_ENTRY *SubTable; + + + /* Main table */ + + Status = AcpiDmDumpTable (Table->Length, 0, Table, 0, AcpiDmTableInfoMtmr); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Sub-tables */ + + SubTable = ACPI_ADD_PTR (ACPI_MTMR_ENTRY, Table, Offset); + while (Offset < Table->Length) + { + /* Common sub-table header */ + + AcpiOsPrintf ("\n"); + Status = AcpiDmDumpTable (Table->Length, Offset, SubTable, + sizeof (ACPI_MTMR_ENTRY), AcpiDmTableInfoMtmr0); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Point to next sub-table */ + + Offset += sizeof (ACPI_MTMR_ENTRY); + SubTable = ACPI_ADD_PTR (ACPI_MTMR_ENTRY, SubTable, sizeof (ACPI_MTMR_ENTRY)); + } +} + + /******************************************************************************* * * FUNCTION: AcpiDmDumpPcct @@ -2376,6 +2428,58 @@ NextSubTable: } +/******************************************************************************* + * + * FUNCTION: AcpiDmDumpVrtc + * + * PARAMETERS: Table - A VRTC table + * + * RETURN: None + * + * DESCRIPTION: Format the contents of a VRTC + * + ******************************************************************************/ + +void +AcpiDmDumpVrtc ( + ACPI_TABLE_HEADER *Table) +{ + ACPI_STATUS Status; + UINT32 Offset = sizeof (ACPI_TABLE_VRTC); + ACPI_VRTC_ENTRY *SubTable; + + + /* Main table */ + + Status = AcpiDmDumpTable (Table->Length, 0, Table, 0, AcpiDmTableInfoVrtc); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Sub-tables */ + + SubTable = ACPI_ADD_PTR (ACPI_VRTC_ENTRY, Table, Offset); + while (Offset < Table->Length) + { + /* Common sub-table header */ + + AcpiOsPrintf ("\n"); + Status = AcpiDmDumpTable (Table->Length, Offset, SubTable, + sizeof (ACPI_VRTC_ENTRY), AcpiDmTableInfoVrtc0); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Point to next sub-table */ + + Offset += sizeof (ACPI_VRTC_ENTRY); + SubTable = ACPI_ADD_PTR (ACPI_VRTC_ENTRY, SubTable, sizeof (ACPI_VRTC_ENTRY)); + } +} + + /******************************************************************************* * * FUNCTION: AcpiDmDumpWdat diff --git a/source/common/dmtbinfo.c b/source/common/dmtbinfo.c index 5b8321d6165..033f7ef8e77 100644 --- a/source/common/dmtbinfo.c +++ b/source/common/dmtbinfo.c @@ -179,6 +179,7 @@ #define ACPI_MPST1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MPST_DATA_HDR,f) #define ACPI_MPST2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MPST_POWER_DATA,f) #define ACPI_MSCT0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MSCT_PROXIMITY,f) +#define ACPI_MTMR0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MTMR_ENTRY,f) #define ACPI_PCCT0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_PCCT_SUBSPACE,f) #define ACPI_PMTT0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_PMTT_SOCKET,f) #define ACPI_PMTT1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_PMTT_CONTROLLER,f) @@ -195,6 +196,7 @@ #define ACPI_SRAT0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_SRAT_CPU_AFFINITY,f) #define ACPI_SRAT1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_SRAT_MEM_AFFINITY,f) #define ACPI_SRAT2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_SRAT_X2APIC_CPU_AFFINITY,f) +#define ACPI_VRTC0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_VRTC_ENTRY,f) #define ACPI_WDAT0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_WDAT_ENTRY,f) /* @@ -1642,6 +1644,28 @@ ACPI_DMTABLE_INFO AcpiDmTableInfoMsct0[] = }; +/******************************************************************************* + * + * MTMR - MID Timer Table + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoMtmr[] = +{ + ACPI_DMT_TERMINATOR +}; + +/* MTMR Subtables - MTMR Entry */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoMtmr0[] = +{ + {ACPI_DMT_GAS, ACPI_MTMR0_OFFSET (PhysicalAddress), "PhysicalAddress", 0}, + {ACPI_DMT_UINT32, ACPI_MTMR0_OFFSET (Frequency), "Frequency", 0}, + {ACPI_DMT_UINT32, ACPI_MTMR0_OFFSET (Irq), "IRQ", 0}, + ACPI_DMT_TERMINATOR +}; + + /******************************************************************************* * * PCCT - Platform Communications Channel Table (ACPI 5.0) @@ -2033,6 +2057,27 @@ ACPI_DMTABLE_INFO AcpiDmTableInfoUefi[] = }; +/******************************************************************************* + * + * VRTC - Virtual Real Time Clock Table + * + ******************************************************************************/ + +ACPI_DMTABLE_INFO AcpiDmTableInfoVrtc[] = +{ + ACPI_DMT_TERMINATOR +}; + +/* VRTC Subtables - VRTC Entry */ + +ACPI_DMTABLE_INFO AcpiDmTableInfoVrtc0[] = +{ + {ACPI_DMT_GAS, ACPI_VRTC0_OFFSET (PhysicalAddress), "PhysicalAddress", 0}, + {ACPI_DMT_UINT32, ACPI_VRTC0_OFFSET (Irq), "IRQ", 0}, + ACPI_DMT_TERMINATOR +}; + + /******************************************************************************* * * WAET - Windows ACPI Emulated devices Table diff --git a/source/compiler/aslcompile.c b/source/compiler/aslcompile.c index af7e1b8c03b..c7528704f92 100644 --- a/source/compiler/aslcompile.c +++ b/source/compiler/aslcompile.c @@ -42,6 +42,7 @@ */ #include "aslcompiler.h" +#include "dtcompiler.h" #include #include @@ -341,6 +342,89 @@ FlConsumeNewComment ( } +/******************************************************************************* + * + * FUNCTION: FlCheckForAcpiTable + * + * PARAMETERS: Handle - Open input file + * + * RETURN: Status + * + * DESCRIPTION: Determine if a file seems to be a binary ACPI table, via the + * following checks on what would be the table header: + * 0) File must be at least as long as an ACPI_TABLE_HEADER + * 1) The header length field must match the file size + * 2) Signature, OemId, OemTableId, AslCompilerId must be ASCII + * + ******************************************************************************/ + +ACPI_STATUS +FlCheckForAcpiTable ( + FILE *Handle) +{ + ACPI_TABLE_HEADER Table; + UINT32 FileSize; + size_t Actual; + UINT32 i; + + + /* Read a potential table header */ + + Actual = fread (&Table, 1, sizeof (ACPI_TABLE_HEADER), Handle); + fseek (Handle, 0, SEEK_SET); + + if (Actual < sizeof (ACPI_TABLE_HEADER)) + { + return (AE_ERROR); + } + + /* Header length field must match the file size */ + + FileSize = DtGetFileSize (Handle); + if (Table.Length != FileSize) + { + return (AE_ERROR); + } + + /* + * These fields must be ASCII: + * Signature, OemId, OemTableId, AslCompilerId. + * We allow a NULL terminator in OemId and OemTableId. + */ + for (i = 0; i < ACPI_NAME_SIZE; i++) + { + if (!ACPI_IS_ASCII ((UINT8) Table.Signature[i])) + { + return (AE_ERROR); + } + + if (!ACPI_IS_ASCII ((UINT8) Table.AslCompilerId[i])) + { + return (AE_ERROR); + } + } + + for (i = 0; (i < ACPI_OEM_ID_SIZE) && (Table.OemId[i]); i++) + { + if (!ACPI_IS_ASCII ((UINT8) Table.OemId[i])) + { + return (AE_ERROR); + } + } + + for (i = 0; (i < ACPI_OEM_TABLE_ID_SIZE) && (Table.OemTableId[i]); i++) + { + if (!ACPI_IS_ASCII ((UINT8) Table.OemTableId[i])) + { + return (AE_ERROR); + } + } + + printf ("Binary file appears to be a valid ACPI table, disassembling\n"); + return (AE_OK); +} + + /******************************************************************************* * * FUNCTION: FlCheckForAscii diff --git a/source/compiler/aslcompiler.h b/source/compiler/aslcompiler.h index 3ee60318a66..4f899fc5dad 100644 --- a/source/compiler/aslcompiler.h +++ b/source/compiler/aslcompiler.h @@ -159,6 +159,10 @@ void CmCleanupAndExit ( void); +ACPI_STATUS +FlCheckForAcpiTable ( + FILE *Handle); + ACPI_STATUS FlCheckForAscii ( FILE *Handle, @@ -509,11 +513,27 @@ ApCheckForPredefinedObject ( ACPI_PARSE_OBJECT *Op, char *Name); +ACPI_STATUS +ApCheckObjectType ( + const char *PredefinedName, + ACPI_PARSE_OBJECT *Op, + UINT32 ExpectedBtypes, + UINT32 PackageIndex); + void ApDisplayReservedNames ( void); +/* + * aslprepkg - ACPI predefined names support for packages + */ +void +ApCheckPackage ( + ACPI_PARSE_OBJECT *ParentOp, + const ACPI_PREDEFINED_INFO *Predefined); + + /* * asltransform - parse tree transformations */ diff --git a/source/compiler/asldefine.h b/source/compiler/asldefine.h index 7c8bd66e5c5..75c8fad0e19 100644 --- a/source/compiler/asldefine.h +++ b/source/compiler/asldefine.h @@ -125,8 +125,9 @@ /* Types for input files */ #define ASL_INPUT_TYPE_BINARY 0 -#define ASL_INPUT_TYPE_ASCII_ASL 1 -#define ASL_INPUT_TYPE_ASCII_DATA 2 +#define ASL_INPUT_TYPE_ACPI_TABLE 1 +#define ASL_INPUT_TYPE_ASCII_ASL 2 +#define ASL_INPUT_TYPE_ASCII_DATA 3 /* Misc */ diff --git a/source/compiler/aslfiles.c b/source/compiler/aslfiles.c index e54f6fe943a..5676df15af8 100644 --- a/source/compiler/aslfiles.c +++ b/source/compiler/aslfiles.c @@ -513,6 +513,13 @@ FlOpenMiscOutputFiles ( char *Filename; + /* All done for disassembler */ + + if (Gbl_FileType == ASL_INPUT_TYPE_ACPI_TABLE) + { + return (AE_OK); + } + /* Create/Open a hex output file if asked */ if (Gbl_HexOutputFlag) diff --git a/source/compiler/aslmain.c b/source/compiler/aslmain.c index 261f81fffa0..71a7cec0b30 100644 --- a/source/compiler/aslmain.c +++ b/source/compiler/aslmain.c @@ -111,7 +111,8 @@ AslDoResponseFile ( * * RETURN: None * - * DESCRIPTION: Display option help message + * DESCRIPTION: Display option help message. + * Optional items in square brackets. * ******************************************************************************/ @@ -132,7 +133,7 @@ Options ( ACPI_OPTION ("-P", "Preprocess only and create preprocessor output file (*.i)"); ACPI_OPTION ("-Pn", "Disable preprocessor"); - printf ("\nGeneral Output:\n"); + printf ("\nGeneral Processing:\n"); ACPI_OPTION ("-p ", "Specify path/filename prefix for all output files"); ACPI_OPTION ("-va", "Disable all errors and warnings (summary only)"); ACPI_OPTION ("-vi", "Less verbose errors and warnings for use with IDEs"); @@ -142,12 +143,7 @@ Options ( ACPI_OPTION ("-w1 -w2 -w3", "Set warning reporting level"); ACPI_OPTION ("-we", "Report warnings as errors"); - printf ("\nAML and Data Output Files:\n"); - ACPI_OPTION ("-sa -sc", "Create assembler or C source file (*.asm or *.c)"); - ACPI_OPTION ("-ia -ic", "Create assembler or C include file (*.inc or *.h)"); - ACPI_OPTION ("-ta -tc -ts", "Create assembler, C, or ASL hex table (*.hex)"); - - printf ("\nAML Code Generation:\n"); + printf ("\nAML Code Generation (*.aml):\n"); ACPI_OPTION ("-oa", "Disable all optimizations (compatibility mode)"); ACPI_OPTION ("-of", "Disable constant folding"); ACPI_OPTION ("-oi", "Disable integer optimization to Zero/One/Ones"); @@ -156,22 +152,28 @@ Options ( ACPI_OPTION ("-in", "Ignore NoOp operators"); ACPI_OPTION ("-r ", "Override table header Revision (1-255)"); - printf ("\nASL Listing Files:\n"); + printf ("\nOptional Source Code Output Files:\n"); + ACPI_OPTION ("-sc -sa", "Create source file in C or assembler (*.c or *.asm)"); + ACPI_OPTION ("-ic -ia", "Create include file in C or assembler (*.h or *.inc)"); + ACPI_OPTION ("-tc -ta -ts", "Create hex AML table in C, assembler, or ASL (*.hex)"); + + printf ("\nOptional Listing Files:\n"); ACPI_OPTION ("-l", "Create mixed listing file (ASL source and AML) (*.lst)"); ACPI_OPTION ("-ln", "Create namespace file (*.nsp)"); ACPI_OPTION ("-ls", "Create combined source file (expanded includes) (*.src)"); - printf ("\nACPI Data Tables:\n"); - ACPI_OPTION ("-G", "Compile custom table containing generic operators"); - ACPI_OPTION ("-vt", "Create verbose templates (full disassembly)"); + printf ("\nData Table Compiler:\n"); + ACPI_OPTION ("-G", "Compile custom table that contains generic operators"); + ACPI_OPTION ("-vt", "Create verbose template files (full disassembly)"); printf ("\nAML Disassembler:\n"); - ACPI_OPTION ("-d [file]", "Disassemble or decode binary ACPI table to file (*.dsl)"); - ACPI_OPTION ("-da [f1,f2]", "Disassemble multiple tables from single namespace"); + ACPI_OPTION ("-d ", "Disassemble or decode binary ACPI tables to file (*.dsl)"); + ACPI_OPTION ("", " (Optional, file type is automatically detected)"); + ACPI_OPTION ("-da ", "Disassemble multiple tables from single namespace"); ACPI_OPTION ("-db", "Do not translate Buffers to Resource Templates"); - ACPI_OPTION ("-dc [file]", "Disassemble AML and immediately compile it"); - ACPI_OPTION ("", "(Obtain DSDT from current system if no input file)"); - ACPI_OPTION ("-e [f1,f2]", "Include ACPI table(s) for external symbol resolution"); + ACPI_OPTION ("-dc ", "Disassemble AML and immediately compile it"); + ACPI_OPTION ("", " (Obtain DSDT from current system if no input file)"); + ACPI_OPTION ("-e ", "Include ACPI table(s) for external symbol resolution"); ACPI_OPTION ("-g", "Get ACPI tables and write to files (*.dat)"); ACPI_OPTION ("-in", "Ignore NoOp opcodes"); ACPI_OPTION ("-vt", "Dump binary table data in hex format within output file"); @@ -186,6 +188,7 @@ Options ( printf ("\nDebug Options:\n"); ACPI_OPTION ("-bf -bt", "Create debug file (full or parse tree only) (*.txt)"); ACPI_OPTION ("-f", "Ignore errors, force creation of AML output file(s)"); + ACPI_OPTION ("-m ", "Set internal line buffer size (in Kbytes)"); ACPI_OPTION ("-n", "Parse only, no output generation"); ACPI_OPTION ("-ot", "Display compile times and statistics"); ACPI_OPTION ("-x ", "Set debug level for trace output"); diff --git a/source/compiler/aslmessages.h b/source/compiler/aslmessages.h index be7a3f95269..102148dffb9 100644 --- a/source/compiler/aslmessages.h +++ b/source/compiler/aslmessages.h @@ -166,6 +166,7 @@ typedef enum ASL_MSG_RESERVED_METHOD, ASL_MSG_RESERVED_NO_RETURN_VAL, ASL_MSG_RESERVED_OPERAND_TYPE, + ASL_MSG_RESERVED_PACKAGE_LENGTH, ASL_MSG_RESERVED_RETURN_VALUE, ASL_MSG_RESERVED_USE, ASL_MSG_RESERVED_WORD, @@ -343,6 +344,7 @@ char *AslMessages [] = { /* ASL_MSG_RESERVED_METHOD */ "Reserved name must be a control method", /* ASL_MSG_RESERVED_NO_RETURN_VAL */ "Reserved method should not return a value", /* ASL_MSG_RESERVED_OPERAND_TYPE */ "Invalid object type for reserved name", +/* ASL_MSG_RESERVED_PACKAGE_LENGTH */ "Invalid package length for reserved name", /* ASL_MSG_RESERVED_RETURN_VALUE */ "Reserved method must return a value", /* ASL_MSG_RESERVED_USE */ "Invalid use of reserved name", /* ASL_MSG_RESERVED_WORD */ "Use of reserved name", diff --git a/source/compiler/aslpredef.c b/source/compiler/aslpredef.c index 8704bb6ab2e..ca877a8ada5 100644 --- a/source/compiler/aslpredef.c +++ b/source/compiler/aslpredef.c @@ -46,6 +46,7 @@ #include "aslcompiler.h" #include "aslcompiler.y.h" #include "acpredef.h" +#include "acnamesp.h" #define _COMPONENT ACPI_COMPILER @@ -64,12 +65,6 @@ ApCheckForSpecialName ( ACPI_PARSE_OBJECT *Op, char *Name); -static void -ApCheckObjectType ( - const char *PredefinedName, - ACPI_PARSE_OBJECT *Op, - UINT32 ExpectedBtypes); - static void ApGetExpectedTypes ( char *Buffer, @@ -386,7 +381,15 @@ ApCheckPredefinedReturnValue ( ApCheckObjectType (PredefinedNames[Index].Info.Name, ReturnValueOp, - PredefinedNames[Index].Info.ExpectedBtypes); + PredefinedNames[Index].Info.ExpectedBtypes, + ACPI_NOT_PACKAGE_ELEMENT); + + /* For packages, check the individual package elements */ + + if (ReturnValueOp->Asl.ParseOpcode == PARSEOP_PACKAGE) + { + ApCheckPackage (ReturnValueOp, &PredefinedNames[Index]); + } break; default: @@ -428,6 +431,7 @@ ApCheckForPredefinedObject ( char *Name) { UINT32 Index; + ACPI_PARSE_OBJECT *ObjectOp; /* @@ -456,39 +460,50 @@ ApCheckForPredefinedObject ( "with zero arguments"); return; - default: /* A standard predefined ACPI name */ + default: + break; + } - /* - * If this predefined name requires input arguments, then - * it must be implemented as a control method - */ - if (PredefinedNames[Index].Info.ParamCount > 0) - { - AslError (ASL_ERROR, ASL_MSG_RESERVED_METHOD, Op, - "with arguments"); - return; - } + /* A standard predefined ACPI name */ - /* - * If no return value is expected from this predefined name, then - * it follows that it must be implemented as a control method - * (with zero args, because the args > 0 case was handled above) - * Examples are: _DIS, _INI, _IRC, _OFF, _ON, _PSx - */ - if (!PredefinedNames[Index].Info.ExpectedBtypes) - { - AslError (ASL_ERROR, ASL_MSG_RESERVED_METHOD, Op, - "with zero arguments"); - return; - } - - /* Typecheck the actual object, it is the next argument */ - - ApCheckObjectType (PredefinedNames[Index].Info.Name, - Op->Asl.Child->Asl.Next, - PredefinedNames[Index].Info.ExpectedBtypes); + /* + * If this predefined name requires input arguments, then + * it must be implemented as a control method + */ + if (PredefinedNames[Index].Info.ParamCount > 0) + { + AslError (ASL_ERROR, ASL_MSG_RESERVED_METHOD, Op, + "with arguments"); return; } + + /* + * If no return value is expected from this predefined name, then + * it follows that it must be implemented as a control method + * (with zero args, because the args > 0 case was handled above) + * Examples are: _DIS, _INI, _IRC, _OFF, _ON, _PSx + */ + if (!PredefinedNames[Index].Info.ExpectedBtypes) + { + AslError (ASL_ERROR, ASL_MSG_RESERVED_METHOD, Op, + "with zero arguments"); + return; + } + + /* Typecheck the actual object, it is the next argument */ + + ObjectOp = Op->Asl.Child->Asl.Next; + ApCheckObjectType (PredefinedNames[Index].Info.Name, + Op->Asl.Child->Asl.Next, + PredefinedNames[Index].Info.ExpectedBtypes, + ACPI_NOT_PACKAGE_ELEMENT); + + /* For packages, check the individual package elements */ + + if (ObjectOp->Asl.ParseOpcode == PARSEOP_PACKAGE) + { + ApCheckPackage (ObjectOp, &PredefinedNames[Index]); + } } @@ -646,6 +661,9 @@ ApCheckForSpecialName ( * PARAMETERS: PredefinedName - Name of the predefined object we are checking * Op - Current parse node * ExpectedBtypes - Bitmap of expected return type(s) + * PackageIndex - Index of object within parent package (if + * applicable - ACPI_NOT_PACKAGE_ELEMENT + * otherwise) * * RETURN: None * @@ -655,15 +673,24 @@ ApCheckForSpecialName ( * ******************************************************************************/ -static void +ACPI_STATUS ApCheckObjectType ( const char *PredefinedName, ACPI_PARSE_OBJECT *Op, - UINT32 ExpectedBtypes) + UINT32 ExpectedBtypes, + UINT32 PackageIndex) { UINT32 ReturnBtype; + char *TypeName; + if (!Op) + { + return (AE_TYPE); + } + + /* Map the parse opcode to a bitmapped return type (RTYPE) */ + switch (Op->Asl.ParseOpcode) { case PARSEOP_ZERO: @@ -671,24 +698,35 @@ ApCheckObjectType ( case PARSEOP_ONES: case PARSEOP_INTEGER: ReturnBtype = ACPI_RTYPE_INTEGER; - break; - - case PARSEOP_BUFFER: - ReturnBtype = ACPI_RTYPE_BUFFER; + TypeName = "Integer"; break; case PARSEOP_STRING_LITERAL: ReturnBtype = ACPI_RTYPE_STRING; + TypeName = "String"; + break; + + case PARSEOP_BUFFER: + ReturnBtype = ACPI_RTYPE_BUFFER; + TypeName = "Buffer"; break; case PARSEOP_PACKAGE: case PARSEOP_VAR_PACKAGE: ReturnBtype = ACPI_RTYPE_PACKAGE; + TypeName = "Package"; + break; + + case PARSEOP_NAMESEG: + case PARSEOP_NAMESTRING: + ReturnBtype = ACPI_RTYPE_REFERENCE; + TypeName = "Reference"; break; default: /* Not one of the supported object types */ + TypeName = UtGetOpName (Op->Asl.ParseOpcode); goto TypeErrorExit; } @@ -696,7 +734,7 @@ ApCheckObjectType ( if (ReturnBtype & ExpectedBtypes) { - return; + return (AE_OK); } @@ -706,11 +744,19 @@ TypeErrorExit: ApGetExpectedTypes (StringBuffer, ExpectedBtypes); - sprintf (MsgBuffer, "%s: found %s, requires %s", - PredefinedName, UtGetOpName (Op->Asl.ParseOpcode), StringBuffer); + if (PackageIndex == ACPI_NOT_PACKAGE_ELEMENT) + { + sprintf (MsgBuffer, "%s: found %s, %s required", + PredefinedName, TypeName, StringBuffer); + } + else + { + sprintf (MsgBuffer, "%s: found %s at index %u, %s required", + PredefinedName, TypeName, PackageIndex, StringBuffer); + } - AslError (ASL_ERROR, ASL_MSG_RESERVED_OPERAND_TYPE, Op, - MsgBuffer); + AslError (ASL_ERROR, ASL_MSG_RESERVED_OPERAND_TYPE, Op, MsgBuffer); + return (AE_TYPE); } diff --git a/source/compiler/aslprepkg.c b/source/compiler/aslprepkg.c new file mode 100644 index 00000000000..e8434d52925 --- /dev/null +++ b/source/compiler/aslprepkg.c @@ -0,0 +1,661 @@ +/****************************************************************************** + * + * Module Name: aslprepkg - support for ACPI predefined name package objects + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2013, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include "aslcompiler.h" +#include "aslcompiler.y.h" +#include "acpredef.h" + + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("aslprepkg") + + +/* Local prototypes */ + +static void +ApCheckPackageElements ( + const char *PredefinedName, + ACPI_PARSE_OBJECT *Op, + UINT8 Type1, + UINT32 Count1, + UINT8 Type2, + UINT32 Count2); + +static void +ApCheckPackageList ( + const char *PredefinedName, + ACPI_PARSE_OBJECT *ParentOp, + const ACPI_PREDEFINED_INFO *Package, + UINT32 StartIndex, + UINT32 Count); + +static void +ApPackageTooSmall ( + const char *PredefinedName, + ACPI_PARSE_OBJECT *Op, + UINT32 Count, + UINT32 ExpectedCount); + +static void +ApZeroLengthPackage ( + const char *PredefinedName, + ACPI_PARSE_OBJECT *Op); + +static void +ApPackageTooLarge ( + const char *PredefinedName, + ACPI_PARSE_OBJECT *Op, + UINT32 Count, + UINT32 ExpectedCount); + + +/******************************************************************************* + * + * FUNCTION: ApCheckPackage + * + * PARAMETERS: ParentOp - Parser op for the package + * Predefined - Pointer to package-specific info for method + * + * RETURN: None + * + * DESCRIPTION: Top-level validation for predefined name return package + * objects. + * + ******************************************************************************/ + +void +ApCheckPackage ( + ACPI_PARSE_OBJECT *ParentOp, + const ACPI_PREDEFINED_INFO *Predefined) +{ + ACPI_PARSE_OBJECT *Op; + const ACPI_PREDEFINED_INFO *Package; + ACPI_STATUS Status; + UINT32 ExpectedCount; + UINT32 Count; + UINT32 i; + + + /* The package info for this name is in the next table entry */ + + Package = Predefined + 1; + + /* First child is the package length */ + + Op = ParentOp->Asl.Child; + Count = (UINT32) Op->Asl.Value.Integer; + + /* + * Most packages must have at least one element. The only exception + * is the variable-length package (ACPI_PTYPE1_VAR). + */ + if (!Count) + { + if (Package->RetInfo.Type != ACPI_PTYPE1_VAR) + { + ApZeroLengthPackage (Predefined->Info.Name, ParentOp); + } + return; + } + + /* Get the first element of the package */ + + Op = Op->Asl.Next; + + /* Decode the package type */ + + switch (Package->RetInfo.Type) + { + case ACPI_PTYPE1_FIXED: + /* + * The package count is fixed and there are no sub-packages + * + * If package is too small, exit. + * If package is larger than expected, issue warning but continue + */ + ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2; + if (Count < ExpectedCount) + { + goto PackageTooSmall; + } + else if (Count > ExpectedCount) + { + ApPackageTooLarge (Predefined->Info.Name, ParentOp, + Count, ExpectedCount); + } + + /* Validate all elements of the package */ + + ApCheckPackageElements (Predefined->Info.Name, Op, + Package->RetInfo.ObjectType1, Package->RetInfo.Count1, + Package->RetInfo.ObjectType2, Package->RetInfo.Count2); + break; + + case ACPI_PTYPE1_VAR: + /* + * The package count is variable, there are no sub-packages, and all + * elements must be of the same type + */ + for (i = 0; i < Count; i++) + { + ApCheckObjectType (Predefined->Info.Name, Op, + Package->RetInfo.ObjectType1, i); + Op = Op->Asl.Next; + } + break; + + case ACPI_PTYPE1_OPTION: + /* + * The package count is variable, there are no sub-packages. There are + * a fixed number of required elements, and a variable number of + * optional elements. + * + * Check if package is at least as large as the minimum required + */ + ExpectedCount = Package->RetInfo3.Count; + if (Count < ExpectedCount) + { + goto PackageTooSmall; + } + + /* Variable number of sub-objects */ + + for (i = 0; i < Count; i++) + { + if (i < Package->RetInfo3.Count) + { + /* These are the required package elements (0, 1, or 2) */ + + ApCheckObjectType (Predefined->Info.Name, Op, + Package->RetInfo3.ObjectType[i], i); + } + else + { + /* These are the optional package elements */ + + ApCheckObjectType (Predefined->Info.Name, Op, + Package->RetInfo3.TailObjectType, i); + } + Op = Op->Asl.Next; + } + break; + + case ACPI_PTYPE2_REV_FIXED: + + /* First element is the (Integer) revision */ + + ApCheckObjectType (Predefined->Info.Name, Op, + ACPI_RTYPE_INTEGER, 0); + + Op = Op->Asl.Next; + Count--; + + /* Examine the sub-packages */ + + ApCheckPackageList (Predefined->Info.Name, Op, + Package, 1, Count); + break; + + case ACPI_PTYPE2_PKG_COUNT: + + /* First element is the (Integer) count of sub-packages to follow */ + + Status = ApCheckObjectType (Predefined->Info.Name, Op, + ACPI_RTYPE_INTEGER, 0); + + /* We must have an integer count from above (otherwise, use Count) */ + + if (ACPI_SUCCESS (Status)) + { + /* + * Count cannot be larger than the parent package length, but allow it + * to be smaller. The >= accounts for the Integer above. + */ + ExpectedCount = (UINT32) Op->Asl.Value.Integer; + if (ExpectedCount >= Count) + { + goto PackageTooSmall; + } + + Count = ExpectedCount; + } + + Op = Op->Asl.Next; + + /* Examine the sub-packages */ + + ApCheckPackageList (Predefined->Info.Name, Op, + Package, 1, Count); + break; + + case ACPI_PTYPE2: + case ACPI_PTYPE2_FIXED: + case ACPI_PTYPE2_MIN: + case ACPI_PTYPE2_COUNT: + case ACPI_PTYPE2_FIX_VAR: + /* + * These types all return a single Package that consists of a + * variable number of sub-Packages. + */ + + /* Examine the sub-packages */ + + ApCheckPackageList (Predefined->Info.Name, Op, + Package, 0, Count); + break; + + default: + return; + } + + return; + +PackageTooSmall: + ApPackageTooSmall (Predefined->Info.Name, ParentOp, + Count, ExpectedCount); +} + + +/******************************************************************************* + * + * FUNCTION: ApCheckPackageElements + * + * PARAMETERS: PredefinedName - Pointer to validation data structure + * Op - Parser op for the package + * Type1 - Object type for first group + * Count1 - Count for first group + * Type2 - Object type for second group + * Count2 - Count for second group + * + * RETURN: None + * + * DESCRIPTION: Validate all elements of a package. Works with packages that + * are defined to contain up to two groups of different object + * types. + * + ******************************************************************************/ + +static void +ApCheckPackageElements ( + const char *PredefinedName, + ACPI_PARSE_OBJECT *Op, + UINT8 Type1, + UINT32 Count1, + UINT8 Type2, + UINT32 Count2) +{ + UINT32 i; + + + /* + * Up to two groups of package elements are supported by the data + * structure. All elements in each group must be of the same type. + * The second group can have a count of zero. + * + * Aborts check upon a NULL package element, as this means (at compile + * time) that the remainder of the package elements are also NULL + * (This is the only way to create NULL package elements.) + */ + for (i = 0; (i < Count1) && Op; i++) + { + ApCheckObjectType (PredefinedName, Op, Type1, i); + Op = Op->Asl.Next; + } + + for (i = 0; (i < Count2) && Op; i++) + { + ApCheckObjectType (PredefinedName, Op, Type2, (i + Count1)); + Op = Op->Asl.Next; + } +} + + +/******************************************************************************* + * + * FUNCTION: ApCheckPackageList + * + * PARAMETERS: PredefinedName - Name of the predefined object + * ParentOp - Parser op of the parent package + * Package - Package info for this predefined name + * StartIndex - Index in parent package where list begins + * ParentCount - Element count of parent package + * + * RETURN: None + * + * DESCRIPTION: Validate the individual package elements for a predefined name. + * Handles the cases where the predefined name is defined as a + * Package of Packages (subpackages). These are the types: + * + * ACPI_PTYPE2 + * ACPI_PTYPE2_FIXED + * ACPI_PTYPE2_MIN + * ACPI_PTYPE2_COUNT + * ACPI_PTYPE2_FIX_VAR + * + ******************************************************************************/ + +static void +ApCheckPackageList ( + const char *PredefinedName, + ACPI_PARSE_OBJECT *ParentOp, + const ACPI_PREDEFINED_INFO *Package, + UINT32 StartIndex, + UINT32 ParentCount) +{ + ACPI_PARSE_OBJECT *SubPackageOp = ParentOp; + ACPI_PARSE_OBJECT *Op; + ACPI_STATUS Status; + UINT32 Count; + UINT32 ExpectedCount; + UINT32 i; + UINT32 j; + + + /* + * Validate each subpackage in the parent Package + * + * Note: We ignore NULL package elements on the assumption that + * they will be initialized by the BIOS or other ASL code. + */ + for (i = 0; (i < ParentCount) && SubPackageOp; i++) + { + /* Each object in the list must be of type Package */ + + Status = ApCheckObjectType (PredefinedName, SubPackageOp, + ACPI_RTYPE_PACKAGE, i + StartIndex); + if (ACPI_FAILURE (Status)) + { + goto NextSubpackage; + } + + /* Examine the different types of expected subpackages */ + + Op = SubPackageOp->Asl.Child; + + /* First child is the package length */ + + Count = (UINT32) Op->Asl.Value.Integer; + Op = Op->Asl.Next; + + /* The subpackage must have at least one element */ + + if (!Count) + { + ApZeroLengthPackage (PredefinedName, SubPackageOp); + goto NextSubpackage; + } + + /* + * Decode the package type. + * PTYPE2 indicates that a "package of packages" is expected for + * this name. The various flavors of PTYPE2 indicate the number + * and format of the subpackages. + */ + switch (Package->RetInfo.Type) + { + case ACPI_PTYPE2: + case ACPI_PTYPE2_PKG_COUNT: + case ACPI_PTYPE2_REV_FIXED: + + /* Each subpackage has a fixed number of elements */ + + ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2; + if (Count < ExpectedCount) + { + ApPackageTooSmall (PredefinedName, SubPackageOp, + Count, ExpectedCount); + break; + } + + ApCheckPackageElements (PredefinedName, Op, + Package->RetInfo.ObjectType1, Package->RetInfo.Count1, + Package->RetInfo.ObjectType2, Package->RetInfo.Count2); + break; + + case ACPI_PTYPE2_FIX_VAR: + /* + * Each subpackage has a fixed number of elements and an + * optional element + */ + ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2; + if (Count < ExpectedCount) + { + ApPackageTooSmall (PredefinedName, SubPackageOp, + Count, ExpectedCount); + break; + } + + ApCheckPackageElements (PredefinedName, Op, + Package->RetInfo.ObjectType1, Package->RetInfo.Count1, + Package->RetInfo.ObjectType2, + Count - Package->RetInfo.Count1); + break; + + case ACPI_PTYPE2_FIXED: + + /* Each sub-package has a fixed length */ + + ExpectedCount = Package->RetInfo2.Count; + if (Count < ExpectedCount) + { + ApPackageTooSmall (PredefinedName, SubPackageOp, + Count, ExpectedCount); + break; + } + + /* Check each object/type combination */ + + for (j = 0; j < ExpectedCount; j++) + { + ApCheckObjectType (PredefinedName, Op, + Package->RetInfo2.ObjectType[j], j); + + Op = Op->Asl.Next; + } + break; + + case ACPI_PTYPE2_MIN: + + /* Each sub-package has a variable but minimum length */ + + ExpectedCount = Package->RetInfo.Count1; + if (Count < ExpectedCount) + { + ApPackageTooSmall (PredefinedName, SubPackageOp, + Count, ExpectedCount); + break; + } + + /* Check the type of each sub-package element */ + + ApCheckPackageElements (PredefinedName, Op, + Package->RetInfo.ObjectType1, Count, 0, 0); + break; + + case ACPI_PTYPE2_COUNT: + /* + * First element is the (Integer) count of elements, including + * the count field (the ACPI name is NumElements) + */ + Status = ApCheckObjectType (PredefinedName, Op, + ACPI_RTYPE_INTEGER, 0); + + /* We must have an integer count from above (otherwise, use Count) */ + + if (ACPI_SUCCESS (Status)) + { + /* + * Make sure package is large enough for the Count and is + * is as large as the minimum size + */ + ExpectedCount = (UINT32) Op->Asl.Value.Integer; + + if (Count < ExpectedCount) + { + ApPackageTooSmall (PredefinedName, SubPackageOp, + Count, ExpectedCount); + break; + } + else if (Count > ExpectedCount) + { + ApPackageTooLarge (PredefinedName, SubPackageOp, + Count, ExpectedCount); + } + + /* Some names of this type have a minimum length */ + + if (Count < Package->RetInfo.Count1) + { + ExpectedCount = Package->RetInfo.Count1; + ApPackageTooSmall (PredefinedName, SubPackageOp, + Count, ExpectedCount); + break; + } + + Count = ExpectedCount; + } + + /* Check the type of each sub-package element */ + + Op = Op->Asl.Next; + ApCheckPackageElements (PredefinedName, Op, + Package->RetInfo.ObjectType1, (Count - 1), 0, 0); + break; + + default: + break; + } + +NextSubpackage: + SubPackageOp = SubPackageOp->Asl.Next; + } +} + + +/******************************************************************************* + * + * FUNCTION: ApPackageTooSmall + * + * PARAMETERS: PredefinedName - Name of the predefined object + * Op - Current parser op + * Count - Actual package element count + * ExpectedCount - Expected package element count + * + * RETURN: None + * + * DESCRIPTION: Issue error message for a package that is smaller than + * required. + * + ******************************************************************************/ + +static void +ApPackageTooSmall ( + const char *PredefinedName, + ACPI_PARSE_OBJECT *Op, + UINT32 Count, + UINT32 ExpectedCount) +{ + + sprintf (MsgBuffer, "%s: length %u, required minimum is %u", + PredefinedName, Count, ExpectedCount); + + AslError (ASL_ERROR, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer); +} + + +/******************************************************************************* + * + * FUNCTION: ApZeroLengthPackage + * + * PARAMETERS: PredefinedName - Name of the predefined object + * Op - Current parser op + * + * RETURN: None + * + * DESCRIPTION: Issue error message for a zero-length package (a package that + * is required to have a non-zero length). Variable length + * packages seem to be allowed to have zero length, however. + * Even if not allowed, BIOS code does it. + * + ******************************************************************************/ + +static void +ApZeroLengthPackage ( + const char *PredefinedName, + ACPI_PARSE_OBJECT *Op) +{ + + sprintf (MsgBuffer, "%s: length is zero", PredefinedName); + + AslError (ASL_ERROR, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer); +} + + +/******************************************************************************* + * + * FUNCTION: ApPackageTooLarge + * + * PARAMETERS: PredefinedName - Name of the predefined object + * Op - Current parser op + * Count - Actual package element count + * ExpectedCount - Expected package element count + * + * RETURN: None + * + * DESCRIPTION: Issue a remark for a package that is larger than expected. + * + ******************************************************************************/ + +static void +ApPackageTooLarge ( + const char *PredefinedName, + ACPI_PARSE_OBJECT *Op, + UINT32 Count, + UINT32 ExpectedCount) +{ + + sprintf (MsgBuffer, "%s: length is %u, only %u required", + PredefinedName, Count, ExpectedCount); + + AslError (ASL_REMARK, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer); +} diff --git a/source/compiler/aslstartup.c b/source/compiler/aslstartup.c index c8c64490e45..ad9a2bb932d 100644 --- a/source/compiler/aslstartup.c +++ b/source/compiler/aslstartup.c @@ -44,6 +44,7 @@ #include "aslcompiler.h" #include "actables.h" +#include "acdisasm.h" #include "acapps.h" #define _COMPONENT ACPI_COMPILER @@ -66,6 +67,10 @@ static UINT8 AslDetectSourceFileType ( ASL_FILE_INFO *Info); +static ACPI_STATUS +AslDoDisassembly ( + void); + /******************************************************************************* * @@ -224,6 +229,15 @@ AslDetectSourceFileType ( ACPI_STATUS Status; + /* Check for a valid binary ACPI table */ + + Status = FlCheckForAcpiTable (Info->Handle); + if (ACPI_SUCCESS (Status)) + { + Type = ASL_INPUT_TYPE_ACPI_TABLE; + goto Cleanup; + } + /* Check for 100% ASCII source file (comments are ignored) */ Status = FlCheckForAscii (Info->Handle, Info->Filename, TRUE); @@ -277,6 +291,86 @@ Cleanup: } +/******************************************************************************* + * + * FUNCTION: AslDoDisassembly + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Initiate AML file disassembly. Uses ACPICA subsystem to build + * namespace. + * + ******************************************************************************/ + +static ACPI_STATUS +AslDoDisassembly ( + void) +{ + ACPI_STATUS Status; + + + /* ACPICA subsystem initialization */ + + Status = AdInitialize (); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + Status = AcpiAllocateRootTable (4); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("Could not initialize ACPI Table Manager, %s\n", + AcpiFormatException (Status)); + return (Status); + } + + /* This is where the disassembly happens */ + + AcpiGbl_DbOpt_disasm = TRUE; + Status = AdAmlDisassemble (AslToFile, + Gbl_Files[ASL_FILE_INPUT].Filename, Gbl_OutputFilenamePrefix, + &Gbl_Files[ASL_FILE_INPUT].Filename, Gbl_GetAllTables); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Check if any control methods were unresolved */ + + AcpiDmUnresolvedWarning (0); + +#if 0 + /* TBD: Handle additional output files for disassembler */ + + Status = FlOpenMiscOutputFiles (Gbl_OutputFilenamePrefix); + NsDisplayNamespace (); +#endif + + /* Shutdown compiler and ACPICA subsystem */ + + AeClearErrorLog (); + (void) AcpiTerminate (); + + /* + * Gbl_Files[ASL_FILE_INPUT].Filename was replaced with the + * .DSL disassembly file, which can now be compiled if requested + */ + if (Gbl_DoCompile) + { + AcpiOsPrintf ("\nCompiling \"%s\"\n", + Gbl_Files[ASL_FILE_INPUT].Filename); + return (AE_CTRL_CONTINUE); + } + + ACPI_FREE (Gbl_Files[ASL_FILE_INPUT].Filename); + Gbl_Files[ASL_FILE_INPUT].Filename = NULL; + return (AE_OK); +} + + /******************************************************************************* * * FUNCTION: AslDoOneFile @@ -308,61 +402,11 @@ AslDoOneFile ( */ if (Gbl_DisasmFlag || Gbl_GetAllTables) { - /* ACPICA subsystem initialization */ - - Status = AdInitialize (); - if (ACPI_FAILURE (Status)) + Status = AslDoDisassembly (); + if (Status != AE_CTRL_CONTINUE) { return (Status); } - - Status = AcpiAllocateRootTable (4); - if (ACPI_FAILURE (Status)) - { - AcpiOsPrintf ("Could not initialize ACPI Table Manager, %s\n", - AcpiFormatException (Status)); - return (Status); - } - - /* This is where the disassembly happens */ - - AcpiGbl_DbOpt_disasm = TRUE; - Status = AdAmlDisassemble (AslToFile, - Gbl_Files[ASL_FILE_INPUT].Filename, - Gbl_OutputFilenamePrefix, - &Gbl_Files[ASL_FILE_INPUT].Filename, - Gbl_GetAllTables); - if (ACPI_FAILURE (Status)) - { - return (Status); - } - -#if 0 - /* TBD: Handle additional output files for disassembler */ - - Status = FlOpenMiscOutputFiles (Gbl_OutputFilenamePrefix); - NsDisplayNamespace (); -#endif - - /* Shutdown compiler and ACPICA subsystem */ - - AeClearErrorLog (); - (void) AcpiTerminate (); - - /* - * Gbl_Files[ASL_FILE_INPUT].Filename was replaced with the - * .DSL disassembly file, which can now be compiled if requested - */ - if (Gbl_DoCompile) - { - AcpiOsPrintf ("\nCompiling \"%s\"\n", - Gbl_Files[ASL_FILE_INPUT].Filename); - } - else - { - Gbl_Files[ASL_FILE_INPUT].Filename = NULL; - return (AE_OK); - } } /* @@ -469,6 +513,21 @@ AslDoOneFile ( PrTerminatePreprocessor (); return (AE_OK); + /* + * Binary ACPI table was auto-detected, disassemble it + */ + case ASL_INPUT_TYPE_ACPI_TABLE: + + /* We have what appears to be an ACPI table, disassemble it */ + + FlCloseFile (ASL_FILE_INPUT); + Gbl_DoCompile = FALSE; + Gbl_DisasmFlag = TRUE; + Status = AslDoDisassembly (); + return (Status); + + /* Unknown binary table */ + case ASL_INPUT_TYPE_BINARY: AePrintErrorLog (ASL_FILE_STDERR); diff --git a/source/compiler/aslsupport.l b/source/compiler/aslsupport.l index 90af04932b5..52389eefa57 100644 --- a/source/compiler/aslsupport.l +++ b/source/compiler/aslsupport.l @@ -403,6 +403,9 @@ count ( TotalKeywords++; TotalExecutableOpcodes++; break; + + default: + break; } for (i = 0; (yytext[i] != 0) && (yytext[i] != EOF); i++) @@ -570,7 +573,6 @@ AslDoStringLiteral ( AslInsertLineBuffer (StringChar); DoCharacter: - switch (State) { case ASL_NORMAL_CHAR: @@ -590,6 +592,9 @@ DoCharacter: /* String terminator */ goto CompletedString; + + default: + break; } break; @@ -748,6 +753,9 @@ DoCharacter: ConvertBuffer[i] = StringChar; i++; continue; + + default: + break; } /* Save the finished character */ diff --git a/source/compiler/dtcompiler.h b/source/compiler/dtcompiler.h index f557ca3063c..f83ef7707d4 100644 --- a/source/compiler/dtcompiler.h +++ b/source/compiler/dtcompiler.h @@ -443,6 +443,10 @@ ACPI_STATUS DtCompileMsct ( void **PFieldList); +ACPI_STATUS +DtCompileMtmr ( + void **PFieldList); + ACPI_STATUS DtCompilePmtt ( void **PFieldList); @@ -471,6 +475,10 @@ ACPI_STATUS DtCompileUefi ( void **PFieldList); +ACPI_STATUS +DtCompileVrtc ( + void **PFieldList); + ACPI_STATUS DtCompileWdat ( void **PFieldList); @@ -511,6 +519,7 @@ extern const unsigned char TemplateMcfg[]; extern const unsigned char TemplateMchi[]; extern const unsigned char TemplateMpst[]; extern const unsigned char TemplateMsct[]; +extern const unsigned char TemplateMtmr[]; extern const unsigned char TemplatePmtt[]; extern const unsigned char TemplateRsdt[]; extern const unsigned char TemplateS3pt[]; @@ -523,6 +532,7 @@ extern const unsigned char TemplateSrat[]; extern const unsigned char TemplateTcpa[]; extern const unsigned char TemplateTpm2[]; extern const unsigned char TemplateUefi[]; +extern const unsigned char TemplateVrtc[]; extern const unsigned char TemplateWaet[]; extern const unsigned char TemplateWdat[]; extern const unsigned char TemplateWddt[]; diff --git a/source/compiler/dttable.c b/source/compiler/dttable.c index 922159f1ffd..b3ce5de2102 100644 --- a/source/compiler/dttable.c +++ b/source/compiler/dttable.c @@ -1410,6 +1410,31 @@ DtCompileMsct ( } +/****************************************************************************** + * + * FUNCTION: DtCompileMtmr + * + * PARAMETERS: List - Current field list pointer + * + * RETURN: Status + * + * DESCRIPTION: Compile MTMR. + * + *****************************************************************************/ + +ACPI_STATUS +DtCompileMtmr ( + void **List) +{ + ACPI_STATUS Status; + + + Status = DtCompileTwoSubtables (List, + AcpiDmTableInfoMtmr, AcpiDmTableInfoMtmr0); + return (Status); +} + + /****************************************************************************** * * FUNCTION: DtCompilePmtt @@ -1972,6 +1997,31 @@ DtCompileUefi ( } +/****************************************************************************** + * + * FUNCTION: DtCompileVrtc + * + * PARAMETERS: List - Current field list pointer + * + * RETURN: Status + * + * DESCRIPTION: Compile VRTC. + * + *****************************************************************************/ + +ACPI_STATUS +DtCompileVrtc ( + void **List) +{ + ACPI_STATUS Status; + + + Status = DtCompileTwoSubtables (List, + AcpiDmTableInfoVrtc, AcpiDmTableInfoVrtc0); + return (Status); +} + + /****************************************************************************** * * FUNCTION: DtCompileWdat diff --git a/source/compiler/dttemplate.h b/source/compiler/dttemplate.h index 07d1f91eea3..d3fadf504ef 100644 --- a/source/compiler/dttemplate.h +++ b/source/compiler/dttemplate.h @@ -632,6 +632,20 @@ const unsigned char TemplateMsct[] = 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 /* 00000088 "........" */ }; +const unsigned char TemplateMtmr[] = +{ + 0x4D,0x54,0x4D,0x52,0x4C,0x00,0x00,0x00, /* 00000000 "MTMRL..." */ + 0x01,0xB0,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x03,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x17,0x01,0x13,0x20,0x00,0x20,0x00,0x03, /* 00000020 "... . .." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000028 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000030 "........" */ + 0x00,0x20,0x00,0x03,0x00,0x00,0x00,0x00, /* 00000038 ". ......" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000040 "........" */ + 0x00,0x00,0x00,0x00 /* 00000048 "...." */ +}; + const unsigned char TemplatePmtt[] = { 0x50,0x4D,0x54,0x54,0xB4,0x00,0x00,0x00, /* 00000000 "PMTT...." */ @@ -893,6 +907,19 @@ const unsigned char TemplateUefi[] = 0x0C,0x0D,0x0E,0x0F,0x00,0x00 /* 00000030 "......" */ }; +const unsigned char TemplateVrtc[] = +{ + 0x56,0x52,0x54,0x43,0x44,0x00,0x00,0x00, /* 00000000 "VRTCD..." */ + 0x01,0xEF,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */ + 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */ + 0x03,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ + 0x17,0x01,0x13,0x20,0x00,0x08,0x00,0x00, /* 00000020 "... ...." */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000028 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00, /* 00000030 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000038 "........" */ + 0x00,0x00,0x00,0x00 /* 00000040 "...." */ +}; + const unsigned char TemplateWaet[] = { 0x57,0x41,0x45,0x54,0x28,0x00,0x00,0x00, /* 00000000 "WAET(..." */ diff --git a/source/components/debugger/dbcmds.c b/source/components/debugger/dbcmds.c index 5755772a629..3a1afa2ce74 100644 --- a/source/components/debugger/dbcmds.c +++ b/source/components/debugger/dbcmds.c @@ -1024,6 +1024,8 @@ GetCrs: /* Execute _SRS with the resource list */ + AcpiOsPrintf ("Evaluating _SRS\n"); + Status = AcpiSetCurrentResources (Node, &ReturnBuffer); if (ACPI_FAILURE (Status)) { @@ -1114,8 +1116,8 @@ Cleanup: * FUNCTION: AcpiDbDisplayResources * * PARAMETERS: ObjectArg - String object name or object pointer. - * "*" means "display resources for all - * devices" + * NULL or "*" means "display resources for + * all devices" * * RETURN: None * @@ -1135,7 +1137,7 @@ AcpiDbDisplayResources ( /* Asterisk means "display resources for all devices" */ - if (!ACPI_STRCMP (ObjectArg, "*")) + if (!ObjectArg || (!ACPI_STRCMP (ObjectArg, "*"))) { (void) AcpiWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, AcpiDbDeviceResources, NULL, NULL, NULL); diff --git a/source/components/debugger/dbinput.c b/source/components/debugger/dbinput.c index b7ee073345a..d8918722628 100644 --- a/source/components/debugger/dbinput.c +++ b/source/components/debugger/dbinput.c @@ -207,7 +207,7 @@ static const ACPI_DB_COMMAND_INFO AcpiGbl_DbCommands[] = {"PREFIX", 0}, {"QUIT", 0}, {"REFERENCES", 1}, - {"RESOURCES", 1}, + {"RESOURCES", 0}, {"RESULTS", 0}, {"SET", 3}, {"SLEEP", 0}, @@ -272,7 +272,7 @@ static const ACPI_DB_COMMAND_HELP AcpiGbl_DbCommandHelp[] = {1, " Predefined", "Check all predefined names\n"}, {1, " Prefix []", "Set or Get current execution prefix\n"}, {1, " References ", "Find all references to object at addr\n"}, - {1, " Resources ", "Display Device resources (* = all devices)\n"}, + {1, " Resources [DeviceName]", "Display Device resources (no arg = all devices)\n"}, {1, " Set N ", "Set value for named integer\n"}, {1, " Sleep [SleepState]", "Simulate sleep/wake sequence(s) (0-5)\n"}, {1, " Template ", "Format/dump a Buffer/ResourceTemplate\n"}, diff --git a/source/components/disassembler/dmresrc.c b/source/components/disassembler/dmresrc.c index 29f2eb74c3a..5041e889ee7 100644 --- a/source/components/disassembler/dmresrc.c +++ b/source/components/disassembler/dmresrc.c @@ -416,7 +416,7 @@ AcpiDmIsResourceTemplate ( /* Walk the byte list, abort on any invalid descriptor type or length */ Status = AcpiUtWalkAmlResources (WalkState, Aml, Length, - NULL, (void **) &EndAml); + NULL, ACPI_CAST_INDIRECT_PTR (void, &EndAml)); if (ACPI_FAILURE (Status)) { return (AE_TYPE); diff --git a/source/components/dispatcher/dsutils.c b/source/components/dispatcher/dsutils.c index 41a66859c82..a7cc232d641 100644 --- a/source/components/dispatcher/dsutils.c +++ b/source/components/dispatcher/dsutils.c @@ -201,7 +201,7 @@ AcpiDsIsResultUsed ( if (!Op) { ACPI_ERROR ((AE_INFO, "Null Op")); - return_VALUE (TRUE); + return_UINT8 (TRUE); } /* @@ -231,7 +231,7 @@ AcpiDsIsResultUsed ( ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "At Method level, result of [%s] not used\n", AcpiPsGetOpcodeName (Op->Common.AmlOpcode))); - return_VALUE (FALSE); + return_UINT8 (FALSE); } /* Get info on the parent. The RootOp is AML_SCOPE */ @@ -241,7 +241,7 @@ AcpiDsIsResultUsed ( { ACPI_ERROR ((AE_INFO, "Unknown parent opcode Op=%p", Op)); - return_VALUE (FALSE); + return_UINT8 (FALSE); } /* @@ -331,7 +331,7 @@ ResultUsed: AcpiPsGetOpcodeName (Op->Common.AmlOpcode), AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op)); - return_VALUE (TRUE); + return_UINT8 (TRUE); ResultNotUsed: @@ -340,7 +340,7 @@ ResultNotUsed: AcpiPsGetOpcodeName (Op->Common.AmlOpcode), AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op)); - return_VALUE (FALSE); + return_UINT8 (FALSE); } diff --git a/source/components/events/evevent.c b/source/components/events/evevent.c index ae505dd1479..fd0b5fba9e9 100644 --- a/source/components/events/evevent.c +++ b/source/components/events/evevent.c @@ -291,6 +291,8 @@ AcpiEvFixedEventDetect ( * * DESCRIPTION: Clears the status bit for the requested event, calls the * handler that previously registered for the event. + * NOTE: If there is no handler for the event, the event is + * disabled to prevent futher interrupts. * ******************************************************************************/ @@ -309,18 +311,18 @@ AcpiEvFixedEventDispatch ( ACPI_CLEAR_STATUS); /* - * Make sure we've got a handler. If not, report an error. The event is - * disabled to prevent further interrupts. + * Make sure that a handler exists. If not, report an error + * and disable the event to prevent further interrupts. */ - if (NULL == AcpiGbl_FixedEventHandlers[Event].Handler) + if (!AcpiGbl_FixedEventHandlers[Event].Handler) { (void) AcpiWriteBitRegister ( AcpiGbl_FixedEventInfo[Event].EnableRegisterId, ACPI_DISABLE_EVENT); ACPI_ERROR ((AE_INFO, - "No installed handler for fixed event [0x%08X]", - Event)); + "No installed handler for fixed event - %s (%u), disabling", + AcpiUtGetEventName (Event), Event)); return (ACPI_INTERRUPT_NOT_HANDLED); } diff --git a/source/components/events/evgpe.c b/source/components/events/evgpe.c index 9c6c41692cb..b6388a371dc 100644 --- a/source/components/events/evgpe.c +++ b/source/components/events/evgpe.c @@ -770,7 +770,7 @@ AcpiEvGpeDispatch ( { ACPI_EXCEPTION ((AE_INFO, Status, "Unable to clear GPE%02X", GpeNumber)); - return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); + return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); } } @@ -788,7 +788,7 @@ AcpiEvGpeDispatch ( { ACPI_EXCEPTION ((AE_INFO, Status, "Unable to disable GPE%02X", GpeNumber)); - return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); + return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); } /* @@ -846,7 +846,7 @@ AcpiEvGpeDispatch ( break; } - return_VALUE (ACPI_INTERRUPT_HANDLED); + return_UINT32 (ACPI_INTERRUPT_HANDLED); } #endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/source/components/events/evsci.c b/source/components/events/evsci.c index 34352688499..eca143f8d12 100644 --- a/source/components/events/evsci.c +++ b/source/components/events/evsci.c @@ -101,7 +101,7 @@ AcpiEvSciXruptHandler ( InterruptHandled |= AcpiEvGpeDetect (GpeXruptList); AcpiSciCount++; - return_VALUE (InterruptHandled); + return_UINT32 (InterruptHandled); } @@ -137,7 +137,7 @@ AcpiEvGpeXruptHandler ( InterruptHandled |= AcpiEvGpeDetect (GpeXruptList); - return_VALUE (InterruptHandled); + return_UINT32 (InterruptHandled); } diff --git a/source/components/events/evxface.c b/source/components/events/evxface.c index 7c9b3e8052d..99ea6cc7ae0 100644 --- a/source/components/events/evxface.c +++ b/source/components/events/evxface.c @@ -534,9 +534,9 @@ AcpiInstallFixedEventHandler ( return_ACPI_STATUS (Status); } - /* Don't allow two handlers. */ + /* Do not allow multiple handlers */ - if (NULL != AcpiGbl_FixedEventHandlers[Event].Handler) + if (AcpiGbl_FixedEventHandlers[Event].Handler) { Status = AE_ALREADY_EXISTS; goto Cleanup; @@ -550,7 +550,9 @@ AcpiInstallFixedEventHandler ( Status = AcpiEnableEvent (Event, 0); if (ACPI_FAILURE (Status)) { - ACPI_WARNING ((AE_INFO, "Could not enable fixed event 0x%X", Event)); + ACPI_WARNING ((AE_INFO, + "Could not enable fixed event - %s (%u)", + AcpiUtGetEventName (Event), Event)); /* Remove the handler */ @@ -560,7 +562,8 @@ AcpiInstallFixedEventHandler ( else { ACPI_DEBUG_PRINT ((ACPI_DB_INFO, - "Enabled fixed event %X, Handler=%p\n", Event, Handler)); + "Enabled fixed event %s (%X), Handler=%p\n", + AcpiUtGetEventName (Event), Event, Handler)); } @@ -621,11 +624,14 @@ AcpiRemoveFixedEventHandler ( if (ACPI_FAILURE (Status)) { ACPI_WARNING ((AE_INFO, - "Could not write to fixed event enable register 0x%X", Event)); + "Could not disable fixed event - %s (%u)", + AcpiUtGetEventName (Event), Event)); } else { - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Disabled fixed event %X\n", Event)); + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "Disabled fixed event - %s (%X)\n", + AcpiUtGetEventName (Event), Event)); } (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); diff --git a/source/components/events/evxfevnt.c b/source/components/events/evxfevnt.c index 1b3d1da567e..ae3378e2c00 100644 --- a/source/components/events/evxfevnt.c +++ b/source/components/events/evxfevnt.c @@ -82,6 +82,13 @@ AcpiEnable ( return_ACPI_STATUS (AE_NO_ACPI_TABLES); } + /* If the Hardware Reduced flag is set, machine is always in acpi mode */ + + if (AcpiGbl_ReducedHardware) + { + return_ACPI_STATUS (AE_OK); + } + /* Check current mode */ if (AcpiHwGetMode() == ACPI_SYS_MODE_ACPI) @@ -131,6 +138,13 @@ AcpiDisable ( ACPI_FUNCTION_TRACE (AcpiDisable); + /* If the Hardware Reduced flag is set, machine is always in acpi mode */ + + if (AcpiGbl_ReducedHardware) + { + return_ACPI_STATUS (AE_OK); + } + if (AcpiHwGetMode() == ACPI_SYS_MODE_LEGACY) { ACPI_DEBUG_PRINT ((ACPI_DB_INIT, diff --git a/source/components/executer/exprep.c b/source/components/executer/exprep.c index 2ccf4a1fdc7..90687a5839a 100644 --- a/source/components/executer/exprep.c +++ b/source/components/executer/exprep.c @@ -292,7 +292,7 @@ AcpiExDecodeFieldAccess ( ACPI_ERROR ((AE_INFO, "Unknown field access type 0x%X", Access)); - return_VALUE (0); + return_UINT32 (0); } if (ObjDesc->Common.Type == ACPI_TYPE_BUFFER_FIELD) @@ -306,7 +306,7 @@ AcpiExDecodeFieldAccess ( } *ReturnByteAlignment = ByteAlignment; - return_VALUE (BitLength); + return_UINT32 (BitLength); } diff --git a/source/components/executer/exutils.c b/source/components/executer/exutils.c index f31f2925594..c8f1b6ef12d 100644 --- a/source/components/executer/exutils.c +++ b/source/components/executer/exutils.c @@ -391,7 +391,7 @@ AcpiExDigitsNeeded ( if (Value == 0) { - return_VALUE (1); + return_UINT32 (1); } CurrentValue = Value; @@ -405,7 +405,7 @@ AcpiExDigitsNeeded ( NumDigits++; } - return_VALUE (NumDigits); + return_UINT32 (NumDigits); } diff --git a/source/components/hardware/hwacpi.c b/source/components/hardware/hwacpi.c index d63c3648029..d4d5b55a523 100644 --- a/source/components/hardware/hwacpi.c +++ b/source/components/hardware/hwacpi.c @@ -75,6 +75,14 @@ AcpiHwSetMode ( ACPI_FUNCTION_TRACE (HwSetMode); + + /* If the Hardware Reduced flag is set, machine is always in acpi mode */ + + if (AcpiGbl_ReducedHardware) + { + return_ACPI_STATUS (AE_OK); + } + /* * ACPI 2.0 clarified that if SMI_CMD in FADT is zero, * system does not support mode transition. @@ -180,28 +188,35 @@ AcpiHwGetMode ( ACPI_FUNCTION_TRACE (HwGetMode); + /* If the Hardware Reduced flag is set, machine is always in acpi mode */ + + if (AcpiGbl_ReducedHardware) + { + return_UINT32 (ACPI_SYS_MODE_ACPI); + } + /* * ACPI 2.0 clarified that if SMI_CMD in FADT is zero, * system does not support mode transition. */ if (!AcpiGbl_FADT.SmiCommand) { - return_VALUE (ACPI_SYS_MODE_ACPI); + return_UINT32 (ACPI_SYS_MODE_ACPI); } Status = AcpiReadBitRegister (ACPI_BITREG_SCI_ENABLE, &Value); if (ACPI_FAILURE (Status)) { - return_VALUE (ACPI_SYS_MODE_LEGACY); + return_UINT32 (ACPI_SYS_MODE_LEGACY); } if (Value) { - return_VALUE (ACPI_SYS_MODE_ACPI); + return_UINT32 (ACPI_SYS_MODE_ACPI); } else { - return_VALUE (ACPI_SYS_MODE_LEGACY); + return_UINT32 (ACPI_SYS_MODE_LEGACY); } } diff --git a/source/components/namespace/nsconvert.c b/source/components/namespace/nsconvert.c new file mode 100644 index 00000000000..e3ff375f253 --- /dev/null +++ b/source/components/namespace/nsconvert.c @@ -0,0 +1,481 @@ +/****************************************************************************** + * + * Module Name: nsconvert - Object conversions for objects returned by + * predefined methods + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2013, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __NSCONVERT_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" +#include "acinterp.h" +#include "acpredef.h" +#include "amlresrc.h" + +#define _COMPONENT ACPI_NAMESPACE + ACPI_MODULE_NAME ("nsconvert") + + +/******************************************************************************* + * + * FUNCTION: AcpiNsConvertToInteger + * + * PARAMETERS: OriginalObject - Object to be converted + * ReturnObject - Where the new converted object is returned + * + * RETURN: Status. AE_OK if conversion was successful. + * + * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsConvertToInteger ( + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ReturnObject) +{ + ACPI_OPERAND_OBJECT *NewObject; + ACPI_STATUS Status; + UINT64 Value = 0; + UINT32 i; + + + switch (OriginalObject->Common.Type) + { + case ACPI_TYPE_STRING: + + /* String-to-Integer conversion */ + + Status = AcpiUtStrtoul64 (OriginalObject->String.Pointer, + ACPI_ANY_BASE, &Value); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + break; + + case ACPI_TYPE_BUFFER: + + /* Buffer-to-Integer conversion. Max buffer size is 64 bits. */ + + if (OriginalObject->Buffer.Length > 8) + { + return (AE_AML_OPERAND_TYPE); + } + + /* Extract each buffer byte to create the integer */ + + for (i = 0; i < OriginalObject->Buffer.Length; i++) + { + Value |= ((UINT64) OriginalObject->Buffer.Pointer[i] << (i * 8)); + } + break; + + default: + return (AE_AML_OPERAND_TYPE); + } + + NewObject = AcpiUtCreateIntegerObject (Value); + if (!NewObject) + { + return (AE_NO_MEMORY); + } + + *ReturnObject = NewObject; + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsConvertToString + * + * PARAMETERS: OriginalObject - Object to be converted + * ReturnObject - Where the new converted object is returned + * + * RETURN: Status. AE_OK if conversion was successful. + * + * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsConvertToString ( + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ReturnObject) +{ + ACPI_OPERAND_OBJECT *NewObject; + ACPI_SIZE Length; + ACPI_STATUS Status; + + + switch (OriginalObject->Common.Type) + { + case ACPI_TYPE_INTEGER: + /* + * Integer-to-String conversion. Commonly, convert + * an integer of value 0 to a NULL string. The last element of + * _BIF and _BIX packages occasionally need this fix. + */ + if (OriginalObject->Integer.Value == 0) + { + /* Allocate a new NULL string object */ + + NewObject = AcpiUtCreateStringObject (0); + if (!NewObject) + { + return (AE_NO_MEMORY); + } + } + else + { + Status = AcpiExConvertToString (OriginalObject, &NewObject, + ACPI_IMPLICIT_CONVERT_HEX); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + } + break; + + case ACPI_TYPE_BUFFER: + /* + * Buffer-to-String conversion. Use a ToString + * conversion, no transform performed on the buffer data. The best + * example of this is the _BIF method, where the string data from + * the battery is often (incorrectly) returned as buffer object(s). + */ + Length = 0; + while ((Length < OriginalObject->Buffer.Length) && + (OriginalObject->Buffer.Pointer[Length])) + { + Length++; + } + + /* Allocate a new string object */ + + NewObject = AcpiUtCreateStringObject (Length); + if (!NewObject) + { + return (AE_NO_MEMORY); + } + + /* + * Copy the raw buffer data with no transform. String is already NULL + * terminated at Length+1. + */ + ACPI_MEMCPY (NewObject->String.Pointer, + OriginalObject->Buffer.Pointer, Length); + break; + + default: + return (AE_AML_OPERAND_TYPE); + } + + *ReturnObject = NewObject; + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsConvertToBuffer + * + * PARAMETERS: OriginalObject - Object to be converted + * ReturnObject - Where the new converted object is returned + * + * RETURN: Status. AE_OK if conversion was successful. + * + * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsConvertToBuffer ( + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ReturnObject) +{ + ACPI_OPERAND_OBJECT *NewObject; + ACPI_STATUS Status; + ACPI_OPERAND_OBJECT **Elements; + UINT32 *DwordBuffer; + UINT32 Count; + UINT32 i; + + + switch (OriginalObject->Common.Type) + { + case ACPI_TYPE_INTEGER: + /* + * Integer-to-Buffer conversion. + * Convert the Integer to a packed-byte buffer. _MAT and other + * objects need this sometimes, if a read has been performed on a + * Field object that is less than or equal to the global integer + * size (32 or 64 bits). + */ + Status = AcpiExConvertToBuffer (OriginalObject, &NewObject); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + break; + + case ACPI_TYPE_STRING: + + /* String-to-Buffer conversion. Simple data copy */ + + NewObject = AcpiUtCreateBufferObject (OriginalObject->String.Length); + if (!NewObject) + { + return (AE_NO_MEMORY); + } + + ACPI_MEMCPY (NewObject->Buffer.Pointer, + OriginalObject->String.Pointer, OriginalObject->String.Length); + break; + + case ACPI_TYPE_PACKAGE: + /* + * This case is often seen for predefined names that must return a + * Buffer object with multiple DWORD integers within. For example, + * _FDE and _GTM. The Package can be converted to a Buffer. + */ + + /* All elements of the Package must be integers */ + + Elements = OriginalObject->Package.Elements; + Count = OriginalObject->Package.Count; + + for (i = 0; i < Count; i++) + { + if ((!*Elements) || + ((*Elements)->Common.Type != ACPI_TYPE_INTEGER)) + { + return (AE_AML_OPERAND_TYPE); + } + Elements++; + } + + /* Create the new buffer object to replace the Package */ + + NewObject = AcpiUtCreateBufferObject (ACPI_MUL_4 (Count)); + if (!NewObject) + { + return (AE_NO_MEMORY); + } + + /* Copy the package elements (integers) to the buffer as DWORDs */ + + Elements = OriginalObject->Package.Elements; + DwordBuffer = ACPI_CAST_PTR (UINT32, NewObject->Buffer.Pointer); + + for (i = 0; i < Count; i++) + { + *DwordBuffer = (UINT32) (*Elements)->Integer.Value; + DwordBuffer++; + Elements++; + } + break; + + default: + return (AE_AML_OPERAND_TYPE); + } + + *ReturnObject = NewObject; + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsConvertToUnicode + * + * PARAMETERS: OriginalObject - ASCII String Object to be converted + * ReturnObject - Where the new converted object is returned + * + * RETURN: Status. AE_OK if conversion was successful. + * + * DESCRIPTION: Attempt to convert a String object to a Unicode string Buffer. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsConvertToUnicode ( + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ReturnObject) +{ + ACPI_OPERAND_OBJECT *NewObject; + char *AsciiString; + UINT16 *UnicodeBuffer; + UINT32 UnicodeLength; + UINT32 i; + + + if (!OriginalObject) + { + return (AE_OK); + } + + /* If a Buffer was returned, it must be at least two bytes long */ + + if (OriginalObject->Common.Type == ACPI_TYPE_BUFFER) + { + if (OriginalObject->Buffer.Length < 2) + { + return (AE_AML_OPERAND_VALUE); + } + + *ReturnObject = NULL; + return (AE_OK); + } + + /* + * The original object is an ASCII string. Convert this string to + * a unicode buffer. + */ + AsciiString = OriginalObject->String.Pointer; + UnicodeLength = (OriginalObject->String.Length * 2) + 2; + + /* Create a new buffer object for the Unicode data */ + + NewObject = AcpiUtCreateBufferObject (UnicodeLength); + if (!NewObject) + { + return (AE_NO_MEMORY); + } + + UnicodeBuffer = ACPI_CAST_PTR (UINT16, NewObject->Buffer.Pointer); + + /* Convert ASCII to Unicode */ + + for (i = 0; i < OriginalObject->String.Length; i++) + { + UnicodeBuffer[i] = (UINT16) AsciiString[i]; + } + + *ReturnObject = NewObject; + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsConvertToResource + * + * PARAMETERS: OriginalObject - Object to be converted + * ReturnObject - Where the new converted object is returned + * + * RETURN: Status. AE_OK if conversion was successful + * + * DESCRIPTION: Attempt to convert a Integer object to a ResourceTemplate + * Buffer. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsConvertToResource ( + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ReturnObject) +{ + ACPI_OPERAND_OBJECT *NewObject; + UINT8 *Buffer; + + + /* + * We can fix the following cases for an expected resource template: + * 1. No return value (interpreter slack mode is disabled) + * 2. A "Return (Zero)" statement + * 3. A "Return empty buffer" statement + * + * We will return a buffer containing a single EndTag + * resource descriptor. + */ + if (OriginalObject) + { + switch (OriginalObject->Common.Type) + { + case ACPI_TYPE_INTEGER: + + /* We can only repair an Integer==0 */ + + if (OriginalObject->Integer.Value) + { + return (AE_AML_OPERAND_TYPE); + } + break; + + case ACPI_TYPE_BUFFER: + + if (OriginalObject->Buffer.Length) + { + /* Additional checks can be added in the future */ + + *ReturnObject = NULL; + return (AE_OK); + } + break; + + case ACPI_TYPE_STRING: + default: + + return (AE_AML_OPERAND_TYPE); + } + } + + /* Create the new buffer object for the resource descriptor */ + + NewObject = AcpiUtCreateBufferObject (2); + if (!NewObject) + { + return (AE_NO_MEMORY); + } + + Buffer = ACPI_CAST_PTR (UINT8, NewObject->Buffer.Pointer); + + /* Initialize the Buffer with a single EndTag descriptor */ + + Buffer[0] = (ACPI_RESOURCE_NAME_END_TAG | ASL_RDESC_END_TAG_SIZE); + Buffer[1] = 0x00; + + *ReturnObject = NewObject; + return (AE_OK); +} diff --git a/source/components/namespace/nspredef.c b/source/components/namespace/nspredef.c index b588bb638fd..f12bc155ac0 100644 --- a/source/components/namespace/nspredef.c +++ b/source/components/namespace/nspredef.c @@ -87,6 +87,11 @@ AcpiNsGetExpectedTypes ( char *Buffer, UINT32 ExpectedBtypes); +static UINT32 +AcpiNsGetBitmappedType ( + ACPI_OPERAND_OBJECT *ReturnObject); + + /* * Names for the types that can be returned by the predefined objects. * Used for warning messages. Must be in the same order as the ACPI_RTYPEs @@ -124,7 +129,6 @@ AcpiNsCheckPredefinedNames ( ACPI_STATUS ReturnStatus, ACPI_OPERAND_OBJECT **ReturnObjectPtr) { - ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; ACPI_STATUS Status = AE_OK; const ACPI_PREDEFINED_INFO *Predefined; char *Pathname; @@ -166,26 +170,6 @@ AcpiNsCheckPredefinedNames ( goto Cleanup; } - /* - * If there is no return value, check if we require a return value for - * this predefined name. Either one return value is expected, or none, - * for both methods and other objects. - * - * Exit now if there is no return object. Warning if one was expected. - */ - if (!ReturnObject) - { - if ((Predefined->Info.ExpectedBtypes) && - (!(Predefined->Info.ExpectedBtypes & ACPI_RTYPE_NONE))) - { - ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, - "Missing expected return value")); - - Status = AE_AML_NO_RETURN_VALUE; - } - goto Cleanup; - } - /* * Return value validation and possible repair. * @@ -447,30 +431,13 @@ AcpiNsCheckObjectType ( { ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; ACPI_STATUS Status = AE_OK; - UINT32 ReturnBtype; char TypeBuffer[48]; /* Room for 5 types */ - /* - * If we get a NULL ReturnObject here, it is a NULL package element. - * Since all extraneous NULL package elements were removed earlier by a - * call to AcpiNsRemoveNullElements, this is an unexpected NULL element. - * We will attempt to repair it. - */ - if (!ReturnObject) - { - Status = AcpiNsRepairNullElement (Data, ExpectedBtypes, - PackageIndex, ReturnObjectPtr); - if (ACPI_SUCCESS (Status)) - { - return (AE_OK); /* Repair was successful */ - } - goto TypeErrorExit; - } - /* A Namespace node should not get here, but make sure */ - if (ACPI_GET_DESCRIPTOR_TYPE (ReturnObject) == ACPI_DESC_TYPE_NAMED) + if (ReturnObject && + ACPI_GET_DESCRIPTOR_TYPE (ReturnObject) == ACPI_DESC_TYPE_NAMED) { ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, "Invalid return type - Found a Namespace node [%4.4s] type %s", @@ -487,56 +454,26 @@ AcpiNsCheckObjectType ( * from all of the predefined names (including elements of returned * packages) */ - switch (ReturnObject->Common.Type) + Data->ReturnBtype = AcpiNsGetBitmappedType (ReturnObject); + if (Data->ReturnBtype == ACPI_RTYPE_ANY) { - case ACPI_TYPE_INTEGER: - ReturnBtype = ACPI_RTYPE_INTEGER; - break; - - case ACPI_TYPE_BUFFER: - ReturnBtype = ACPI_RTYPE_BUFFER; - break; - - case ACPI_TYPE_STRING: - ReturnBtype = ACPI_RTYPE_STRING; - break; - - case ACPI_TYPE_PACKAGE: - ReturnBtype = ACPI_RTYPE_PACKAGE; - break; - - case ACPI_TYPE_LOCAL_REFERENCE: - ReturnBtype = ACPI_RTYPE_REFERENCE; - break; - - default: /* Not one of the supported objects, must be incorrect */ - goto TypeErrorExit; } - /* Is the object one of the expected types? */ + /* For reference objects, check that the reference type is correct */ - if (ReturnBtype & ExpectedBtypes) + if ((Data->ReturnBtype & ExpectedBtypes) == ACPI_RTYPE_REFERENCE) { - /* For reference objects, check that the reference type is correct */ - - if (ReturnObject->Common.Type == ACPI_TYPE_LOCAL_REFERENCE) - { - Status = AcpiNsCheckReference (Data, ReturnObject); - } - + Status = AcpiNsCheckReference (Data, ReturnObject); return (Status); } - /* Type mismatch -- attempt repair of the returned object */ + /* Attempt simple repair of the returned object if necessary */ - Status = AcpiNsRepairObject (Data, ExpectedBtypes, + Status = AcpiNsSimpleRepair (Data, ExpectedBtypes, PackageIndex, ReturnObjectPtr); - if (ACPI_SUCCESS (Status)) - { - return (AE_OK); /* Repair was successful */ - } + return (Status); TypeErrorExit: @@ -604,6 +541,67 @@ AcpiNsCheckReference ( } +/******************************************************************************* + * + * FUNCTION: AcpiNsGetBitmappedType + * + * PARAMETERS: ReturnObject - Object returned from method/obj evaluation + * + * RETURN: Object return type. ACPI_RTYPE_ANY indicates that the object + * type is not supported. ACPI_RTYPE_NONE indicates that no + * object was returned (ReturnObject is NULL). + * + * DESCRIPTION: Convert object type into a bitmapped object return type. + * + ******************************************************************************/ + +static UINT32 +AcpiNsGetBitmappedType ( + ACPI_OPERAND_OBJECT *ReturnObject) +{ + UINT32 ReturnBtype; + + + if (!ReturnObject) + { + return (ACPI_RTYPE_NONE); + } + + /* Map ACPI_OBJECT_TYPE to internal bitmapped type */ + + switch (ReturnObject->Common.Type) + { + case ACPI_TYPE_INTEGER: + ReturnBtype = ACPI_RTYPE_INTEGER; + break; + + case ACPI_TYPE_BUFFER: + ReturnBtype = ACPI_RTYPE_BUFFER; + break; + + case ACPI_TYPE_STRING: + ReturnBtype = ACPI_RTYPE_STRING; + break; + + case ACPI_TYPE_PACKAGE: + ReturnBtype = ACPI_RTYPE_PACKAGE; + break; + + case ACPI_TYPE_LOCAL_REFERENCE: + ReturnBtype = ACPI_RTYPE_REFERENCE; + break; + + default: + /* Not one of the supported objects, must be incorrect */ + + ReturnBtype = ACPI_RTYPE_ANY; + break; + } + + return (ReturnBtype); +} + + /******************************************************************************* * * FUNCTION: AcpiNsGetExpectedTypes diff --git a/source/components/namespace/nsprepkg.c b/source/components/namespace/nsprepkg.c index 9b10a4076f5..d18205c83fd 100644 --- a/source/components/namespace/nsprepkg.c +++ b/source/components/namespace/nsprepkg.c @@ -122,10 +122,17 @@ AcpiNsCheckPackage ( Elements = ReturnObject->Package.Elements; Count = ReturnObject->Package.Count; - /* The package must have at least one element, else invalid */ - + /* + * Most packages must have at least one element. The only exception + * is the variable-length package (ACPI_PTYPE1_VAR). + */ if (!Count) { + if (Package->RetInfo.Type == ACPI_PTYPE1_VAR) + { + return (AE_OK); + } + ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, "Return Package has no elements (empty)")); diff --git a/source/components/namespace/nsrepair.c b/source/components/namespace/nsrepair.c index 7b170d0b826..e06502811d3 100644 --- a/source/components/namespace/nsrepair.c +++ b/source/components/namespace/nsrepair.c @@ -48,6 +48,7 @@ #include "acnamesp.h" #include "acinterp.h" #include "acpredef.h" +#include "amlresrc.h" #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME ("nsrepair") @@ -74,6 +75,11 @@ * Buffer -> String * Buffer -> Package of Integers * Package -> Package of one Package + * + * Additional conversions that are available: + * Convert a null return or zero return value to an EndTag descriptor + * Convert an ASCII string to a Unicode buffer + * * An incorrect standalone object is wrapped with required outer package * * Additional possible repairs: @@ -84,25 +90,46 @@ /* Local prototypes */ -static ACPI_STATUS -AcpiNsConvertToInteger ( - ACPI_OPERAND_OBJECT *OriginalObject, - ACPI_OPERAND_OBJECT **ReturnObject); +static const ACPI_SIMPLE_REPAIR_INFO * +AcpiNsMatchSimpleRepair ( + ACPI_NAMESPACE_NODE *Node, + UINT32 ReturnBtype, + UINT32 PackageIndex); -static ACPI_STATUS -AcpiNsConvertToString ( - ACPI_OPERAND_OBJECT *OriginalObject, - ACPI_OPERAND_OBJECT **ReturnObject); -static ACPI_STATUS -AcpiNsConvertToBuffer ( - ACPI_OPERAND_OBJECT *OriginalObject, - ACPI_OPERAND_OBJECT **ReturnObject); +/* + * Special but simple repairs for some names. + * + * 2nd argument: Unexpected types that can be repaired + */ +static const ACPI_SIMPLE_REPAIR_INFO AcpiObjectRepairInfo[] = +{ + /* Resource descriptor conversions */ + + { "_CRS", ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER | ACPI_RTYPE_NONE, + ACPI_NOT_PACKAGE_ELEMENT, + AcpiNsConvertToResource }, + { "_DMA", ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER | ACPI_RTYPE_NONE, + ACPI_NOT_PACKAGE_ELEMENT, + AcpiNsConvertToResource }, + { "_PRS", ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER | ACPI_RTYPE_NONE, + ACPI_NOT_PACKAGE_ELEMENT, + AcpiNsConvertToResource }, + + /* Unicode conversions */ + + { "_MLS", ACPI_RTYPE_STRING, 1, + AcpiNsConvertToUnicode }, + { "_STR", ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER, + ACPI_NOT_PACKAGE_ELEMENT, + AcpiNsConvertToUnicode }, + { {0,0,0,0}, 0, 0, NULL } /* Table terminator */ +}; /******************************************************************************* * - * FUNCTION: AcpiNsRepairObject + * FUNCTION: AcpiNsSimpleRepair * * PARAMETERS: Data - Pointer to validation data structure * ExpectedBtypes - Object types expected @@ -120,26 +147,84 @@ AcpiNsConvertToBuffer ( ******************************************************************************/ ACPI_STATUS -AcpiNsRepairObject ( +AcpiNsSimpleRepair ( ACPI_PREDEFINED_DATA *Data, UINT32 ExpectedBtypes, UINT32 PackageIndex, ACPI_OPERAND_OBJECT **ReturnObjectPtr) { ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; - ACPI_OPERAND_OBJECT *NewObject; + ACPI_OPERAND_OBJECT *NewObject = NULL; ACPI_STATUS Status; + const ACPI_SIMPLE_REPAIR_INFO *Predefined; - ACPI_FUNCTION_NAME (NsRepairObject); + ACPI_FUNCTION_NAME (NsSimpleRepair); + /* + * Special repairs for certain names that are in the repair table. + * Check if this name is in the list of repairable names. + */ + Predefined = AcpiNsMatchSimpleRepair (Data->Node, + Data->ReturnBtype, PackageIndex); + if (Predefined) + { + if (!ReturnObject) + { + ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, + ACPI_WARN_ALWAYS, "Missing expected return value")); + } + + Status = Predefined->ObjectConverter (ReturnObject, &NewObject); + if (ACPI_FAILURE (Status)) + { + /* A fatal error occurred during a conversion */ + + ACPI_EXCEPTION ((AE_INFO, Status, + "During return object analysis")); + return (Status); + } + if (NewObject) + { + goto ObjectRepaired; + } + } + + /* + * Do not perform simple object repair unless the return type is not + * expected. + */ + if (Data->ReturnBtype & ExpectedBtypes) + { + return (AE_OK); + } + /* * At this point, we know that the type of the returned object was not * one of the expected types for this predefined name. Attempt to * repair the object by converting it to one of the expected object * types for this predefined name. */ + + /* + * If there is no return value, check if we require a return value for + * this predefined name. Either one return value is expected, or none, + * for both methods and other objects. + * + * Exit now if there is no return object. Warning if one was expected. + */ + if (!ReturnObject) + { + if (ExpectedBtypes && (!(ExpectedBtypes & ACPI_RTYPE_NONE))) + { + ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, + ACPI_WARN_ALWAYS, "Missing expected return value")); + + return (AE_AML_NO_RETURN_VALUE); + } + } + if (ExpectedBtypes & ACPI_RTYPE_INTEGER) { Status = AcpiNsConvertToInteger (ReturnObject, &NewObject); @@ -240,273 +325,52 @@ ObjectRepaired: } -/******************************************************************************* +/****************************************************************************** * - * FUNCTION: AcpiNsConvertToInteger + * FUNCTION: AcpiNsMatchSimpleRepair * - * PARAMETERS: OriginalObject - Object to be converted - * ReturnObject - Where the new converted object is returned + * PARAMETERS: Node - Namespace node for the method/object + * ReturnBtype - Object type that was returned + * PackageIndex - Index of object within parent package (if + * applicable - ACPI_NOT_PACKAGE_ELEMENT + * otherwise) * - * RETURN: Status. AE_OK if conversion was successful. + * RETURN: Pointer to entry in repair table. NULL indicates not found. * - * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer. + * DESCRIPTION: Check an object name against the repairable object list. * - ******************************************************************************/ + *****************************************************************************/ -static ACPI_STATUS -AcpiNsConvertToInteger ( - ACPI_OPERAND_OBJECT *OriginalObject, - ACPI_OPERAND_OBJECT **ReturnObject) +static const ACPI_SIMPLE_REPAIR_INFO * +AcpiNsMatchSimpleRepair ( + ACPI_NAMESPACE_NODE *Node, + UINT32 ReturnBtype, + UINT32 PackageIndex) { - ACPI_OPERAND_OBJECT *NewObject; - ACPI_STATUS Status; - UINT64 Value = 0; - UINT32 i; + const ACPI_SIMPLE_REPAIR_INFO *ThisName; - switch (OriginalObject->Common.Type) + /* Search info table for a repairable predefined method/object name */ + + ThisName = AcpiObjectRepairInfo; + while (ThisName->ObjectConverter) { - case ACPI_TYPE_STRING: - - /* String-to-Integer conversion */ - - Status = AcpiUtStrtoul64 (OriginalObject->String.Pointer, - ACPI_ANY_BASE, &Value); - if (ACPI_FAILURE (Status)) + if (ACPI_COMPARE_NAME (Node->Name.Ascii, ThisName->Name)) { - return (Status); - } - break; + /* Check if we can actually repair this name/type combination */ - case ACPI_TYPE_BUFFER: - - /* Buffer-to-Integer conversion. Max buffer size is 64 bits. */ - - if (OriginalObject->Buffer.Length > 8) - { - return (AE_AML_OPERAND_TYPE); - } - - /* Extract each buffer byte to create the integer */ - - for (i = 0; i < OriginalObject->Buffer.Length; i++) - { - Value |= ((UINT64) OriginalObject->Buffer.Pointer[i] << (i * 8)); - } - break; - - default: - return (AE_AML_OPERAND_TYPE); - } - - NewObject = AcpiUtCreateIntegerObject (Value); - if (!NewObject) - { - return (AE_NO_MEMORY); - } - - *ReturnObject = NewObject; - return (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: AcpiNsConvertToString - * - * PARAMETERS: OriginalObject - Object to be converted - * ReturnObject - Where the new converted object is returned - * - * RETURN: Status. AE_OK if conversion was successful. - * - * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String. - * - ******************************************************************************/ - -static ACPI_STATUS -AcpiNsConvertToString ( - ACPI_OPERAND_OBJECT *OriginalObject, - ACPI_OPERAND_OBJECT **ReturnObject) -{ - ACPI_OPERAND_OBJECT *NewObject; - ACPI_SIZE Length; - ACPI_STATUS Status; - - - switch (OriginalObject->Common.Type) - { - case ACPI_TYPE_INTEGER: - /* - * Integer-to-String conversion. Commonly, convert - * an integer of value 0 to a NULL string. The last element of - * _BIF and _BIX packages occasionally need this fix. - */ - if (OriginalObject->Integer.Value == 0) - { - /* Allocate a new NULL string object */ - - NewObject = AcpiUtCreateStringObject (0); - if (!NewObject) + if ((ReturnBtype & ThisName->UnexpectedBtypes) && + (PackageIndex == ThisName->PackageIndex)) { - return (AE_NO_MEMORY); + return (ThisName); } + + return (NULL); } - else - { - Status = AcpiExConvertToString (OriginalObject, &NewObject, - ACPI_IMPLICIT_CONVERT_HEX); - if (ACPI_FAILURE (Status)) - { - return (Status); - } - } - break; - - case ACPI_TYPE_BUFFER: - /* - * Buffer-to-String conversion. Use a ToString - * conversion, no transform performed on the buffer data. The best - * example of this is the _BIF method, where the string data from - * the battery is often (incorrectly) returned as buffer object(s). - */ - Length = 0; - while ((Length < OriginalObject->Buffer.Length) && - (OriginalObject->Buffer.Pointer[Length])) - { - Length++; - } - - /* Allocate a new string object */ - - NewObject = AcpiUtCreateStringObject (Length); - if (!NewObject) - { - return (AE_NO_MEMORY); - } - - /* - * Copy the raw buffer data with no transform. String is already NULL - * terminated at Length+1. - */ - ACPI_MEMCPY (NewObject->String.Pointer, - OriginalObject->Buffer.Pointer, Length); - break; - - default: - return (AE_AML_OPERAND_TYPE); + ThisName++; } - *ReturnObject = NewObject; - return (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: AcpiNsConvertToBuffer - * - * PARAMETERS: OriginalObject - Object to be converted - * ReturnObject - Where the new converted object is returned - * - * RETURN: Status. AE_OK if conversion was successful. - * - * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer. - * - ******************************************************************************/ - -static ACPI_STATUS -AcpiNsConvertToBuffer ( - ACPI_OPERAND_OBJECT *OriginalObject, - ACPI_OPERAND_OBJECT **ReturnObject) -{ - ACPI_OPERAND_OBJECT *NewObject; - ACPI_STATUS Status; - ACPI_OPERAND_OBJECT **Elements; - UINT32 *DwordBuffer; - UINT32 Count; - UINT32 i; - - - switch (OriginalObject->Common.Type) - { - case ACPI_TYPE_INTEGER: - /* - * Integer-to-Buffer conversion. - * Convert the Integer to a packed-byte buffer. _MAT and other - * objects need this sometimes, if a read has been performed on a - * Field object that is less than or equal to the global integer - * size (32 or 64 bits). - */ - Status = AcpiExConvertToBuffer (OriginalObject, &NewObject); - if (ACPI_FAILURE (Status)) - { - return (Status); - } - break; - - case ACPI_TYPE_STRING: - - /* String-to-Buffer conversion. Simple data copy */ - - NewObject = AcpiUtCreateBufferObject (OriginalObject->String.Length); - if (!NewObject) - { - return (AE_NO_MEMORY); - } - - ACPI_MEMCPY (NewObject->Buffer.Pointer, - OriginalObject->String.Pointer, OriginalObject->String.Length); - break; - - case ACPI_TYPE_PACKAGE: - /* - * This case is often seen for predefined names that must return a - * Buffer object with multiple DWORD integers within. For example, - * _FDE and _GTM. The Package can be converted to a Buffer. - */ - - /* All elements of the Package must be integers */ - - Elements = OriginalObject->Package.Elements; - Count = OriginalObject->Package.Count; - - for (i = 0; i < Count; i++) - { - if ((!*Elements) || - ((*Elements)->Common.Type != ACPI_TYPE_INTEGER)) - { - return (AE_AML_OPERAND_TYPE); - } - Elements++; - } - - /* Create the new buffer object to replace the Package */ - - NewObject = AcpiUtCreateBufferObject (ACPI_MUL_4 (Count)); - if (!NewObject) - { - return (AE_NO_MEMORY); - } - - /* Copy the package elements (integers) to the buffer as DWORDs */ - - Elements = OriginalObject->Package.Elements; - DwordBuffer = ACPI_CAST_PTR (UINT32, NewObject->Buffer.Pointer); - - for (i = 0; i < Count; i++) - { - *DwordBuffer = (UINT32) (*Elements)->Integer.Value; - DwordBuffer++; - Elements++; - } - break; - - default: - return (AE_AML_OPERAND_TYPE); - } - - *ReturnObject = NewObject; - return (AE_OK); + return (NULL); /* Name was not found in the repair table */ } diff --git a/source/components/namespace/nsrepair2.c b/source/components/namespace/nsrepair2.c index 5650e338746..b81c0dd0d52 100644 --- a/source/components/namespace/nsrepair2.c +++ b/source/components/namespace/nsrepair2.c @@ -72,7 +72,7 @@ typedef struct acpi_repair_info /* Local prototypes */ static const ACPI_REPAIR_INFO * -AcpiNsMatchRepairableName ( +AcpiNsMatchComplexRepair ( ACPI_NAMESPACE_NODE *Node); static ACPI_STATUS @@ -197,7 +197,7 @@ AcpiNsComplexRepairs ( /* Check if this name is in the list of repairable names */ - Predefined = AcpiNsMatchRepairableName (Node); + Predefined = AcpiNsMatchComplexRepair (Node); if (!Predefined) { return (ValidateStatus); @@ -210,7 +210,7 @@ AcpiNsComplexRepairs ( /****************************************************************************** * - * FUNCTION: AcpiNsMatchRepairableName + * FUNCTION: AcpiNsMatchComplexRepair * * PARAMETERS: Node - Namespace node for the method/object * @@ -221,7 +221,7 @@ AcpiNsComplexRepairs ( *****************************************************************************/ static const ACPI_REPAIR_INFO * -AcpiNsMatchRepairableName ( +AcpiNsMatchComplexRepair ( ACPI_NAMESPACE_NODE *Node) { const ACPI_REPAIR_INFO *ThisName; diff --git a/source/components/namespace/nsutils.c b/source/components/namespace/nsutils.c index 7002200e318..16a6bdb9644 100644 --- a/source/components/namespace/nsutils.c +++ b/source/components/namespace/nsutils.c @@ -128,10 +128,10 @@ AcpiNsGetType ( if (!Node) { ACPI_WARNING ((AE_INFO, "Null Node parameter")); - return_VALUE (ACPI_TYPE_ANY); + return_UINT8 (ACPI_TYPE_ANY); } - return_VALUE (Node->Type); + return_UINT8 (Node->Type); } @@ -160,10 +160,10 @@ AcpiNsLocal ( /* Type code out of range */ ACPI_WARNING ((AE_INFO, "Invalid Object Type 0x%X", Type)); - return_VALUE (ACPI_NS_NORMAL); + return_UINT32 (ACPI_NS_NORMAL); } - return_VALUE (AcpiGbl_NsProperties[Type] & ACPI_NS_LOCAL); + return_UINT32 (AcpiGbl_NsProperties[Type] & ACPI_NS_LOCAL); } diff --git a/source/components/parser/psargs.c b/source/components/parser/psargs.c index a548c2944fa..2bf7be799ca 100644 --- a/source/components/parser/psargs.c +++ b/source/components/parser/psargs.c @@ -118,7 +118,7 @@ AcpiPsGetNextPackageLength ( /* Byte 0 is a special case, either bits [0:3] or [0:5] are used */ PackageLength |= (Aml[0] & ByteZeroMask); - return_VALUE (PackageLength); + return_UINT32 (PackageLength); } diff --git a/source/components/resources/rscalc.c b/source/components/resources/rscalc.c index 6136fc671b0..5c373ec9cde 100644 --- a/source/components/resources/rscalc.c +++ b/source/components/resources/rscalc.c @@ -230,6 +230,13 @@ AcpiRsGetAmlLength ( return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE); } + /* Sanity check the length. It must not be zero, or we loop forever */ + + if (!Resource->Length) + { + return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH); + } + /* Get the base size of the (external stream) resource descriptor */ TotalSize = AcpiGbl_AmlResourceSizes [Resource->Type]; diff --git a/source/components/resources/rsdump.c b/source/components/resources/rsdump.c index 0d2636e02af..063be020659 100644 --- a/source/components/resources/rsdump.c +++ b/source/components/resources/rsdump.c @@ -438,6 +438,15 @@ AcpiRsDumpResourceList ( return; } + /* Sanity check the length. It must not be zero, or we loop forever */ + + if (!ResourceList->Length) + { + AcpiOsPrintf ( + "Invalid zero length descriptor in resource list\n"); + return; + } + /* Dump the resource descriptor */ if (Type == ACPI_RESOURCE_TYPE_SERIAL_BUS) diff --git a/source/components/resources/rslist.c b/source/components/resources/rslist.c index a9fd8759727..80d6f78d2c7 100644 --- a/source/components/resources/rslist.c +++ b/source/components/resources/rslist.c @@ -199,6 +199,15 @@ AcpiRsConvertResourcesToAml ( return_ACPI_STATUS (AE_BAD_DATA); } + /* Sanity check the length. It must not be zero, or we loop forever */ + + if (!Resource->Length) + { + ACPI_ERROR ((AE_INFO, + "Invalid zero length descriptor in resource list\n")); + return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH); + } + /* Perform the conversion */ if (Resource->Type == ACPI_RESOURCE_TYPE_SERIAL_BUS) diff --git a/source/components/resources/rsxface.c b/source/components/resources/rsxface.c index b107ddde5dd..36edc81cc59 100644 --- a/source/components/resources/rsxface.c +++ b/source/components/resources/rsxface.c @@ -630,7 +630,7 @@ AcpiWalkResourceBuffer ( while (Resource < ResourceEnd) { - /* Sanity check the resource */ + /* Sanity check the resource type */ if (Resource->Type > ACPI_RESOURCE_TYPE_MAX) { @@ -638,6 +638,13 @@ AcpiWalkResourceBuffer ( break; } + /* Sanity check the length. It must not be zero, or we loop forever */ + + if (!Resource->Length) + { + return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH); + } + /* Invoke the user function, abort on any error returned */ Status = UserFunction (Resource, Context); diff --git a/source/components/utilities/utaddress.c b/source/components/utilities/utaddress.c index 5606cbe1316..7eae5a5025e 100644 --- a/source/components/utilities/utaddress.c +++ b/source/components/utilities/utaddress.c @@ -237,7 +237,7 @@ AcpiUtCheckAddressRange ( if ((SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) && (SpaceId != ACPI_ADR_SPACE_SYSTEM_IO)) { - return_VALUE (0); + return_UINT32 (0); } RangeInfo = AcpiGbl_AddressRangeList[SpaceId]; @@ -278,7 +278,7 @@ AcpiUtCheckAddressRange ( RangeInfo = RangeInfo->Next; } - return_VALUE (OverlapCount); + return_UINT32 (OverlapCount); } diff --git a/source/components/utilities/utexcep.c b/source/components/utilities/utexcep.c index a3eac017f48..1aead78b6c9 100644 --- a/source/components/utilities/utexcep.c +++ b/source/components/utilities/utexcep.c @@ -71,7 +71,7 @@ const char * AcpiFormatException ( ACPI_STATUS Status) { - const char *Exception = NULL; + const ACPI_EXCEPTION_INFO *Exception; ACPI_FUNCTION_ENTRY (); @@ -85,10 +85,10 @@ AcpiFormatException ( ACPI_ERROR ((AE_INFO, "Unknown exception code: 0x%8.8X", Status)); - Exception = "UNKNOWN_STATUS_CODE"; + return ("UNKNOWN_STATUS_CODE"); } - return (ACPI_CAST_PTR (const char, Exception)); + return (Exception->Name); } ACPI_EXPORT_SYMBOL (AcpiFormatException) @@ -108,12 +108,12 @@ ACPI_EXPORT_SYMBOL (AcpiFormatException) * ******************************************************************************/ -const char * +const ACPI_EXCEPTION_INFO * AcpiUtValidateException ( ACPI_STATUS Status) { - UINT32 SubStatus; - const char *Exception = NULL; + UINT32 SubStatus; + const ACPI_EXCEPTION_INFO *Exception = NULL; ACPI_FUNCTION_ENTRY (); @@ -130,7 +130,7 @@ AcpiUtValidateException ( if (SubStatus <= AE_CODE_ENV_MAX) { - Exception = AcpiGbl_ExceptionNames_Env [SubStatus]; + Exception = &AcpiGbl_ExceptionNames_Env [SubStatus]; } break; @@ -138,7 +138,7 @@ AcpiUtValidateException ( if (SubStatus <= AE_CODE_PGM_MAX) { - Exception = AcpiGbl_ExceptionNames_Pgm [SubStatus]; + Exception = &AcpiGbl_ExceptionNames_Pgm [SubStatus]; } break; @@ -146,7 +146,7 @@ AcpiUtValidateException ( if (SubStatus <= AE_CODE_TBL_MAX) { - Exception = AcpiGbl_ExceptionNames_Tbl [SubStatus]; + Exception = &AcpiGbl_ExceptionNames_Tbl [SubStatus]; } break; @@ -154,7 +154,7 @@ AcpiUtValidateException ( if (SubStatus <= AE_CODE_AML_MAX) { - Exception = AcpiGbl_ExceptionNames_Aml [SubStatus]; + Exception = &AcpiGbl_ExceptionNames_Aml [SubStatus]; } break; @@ -162,7 +162,7 @@ AcpiUtValidateException ( if (SubStatus <= AE_CODE_CTRL_MAX) { - Exception = AcpiGbl_ExceptionNames_Ctrl [SubStatus]; + Exception = &AcpiGbl_ExceptionNames_Ctrl [SubStatus]; } break; @@ -170,5 +170,10 @@ AcpiUtValidateException ( break; } - return (ACPI_CAST_PTR (const char, Exception)); + if (!Exception || !Exception->Name) + { + return (NULL); + } + + return (Exception); } diff --git a/source/components/utilities/utglobal.c b/source/components/utilities/utglobal.c index 2c2dd26f616..83b05266ad5 100644 --- a/source/components/utilities/utglobal.c +++ b/source/components/utilities/utglobal.c @@ -343,6 +343,8 @@ AcpiUtInitGlobals ( #ifdef ACPI_DISASSEMBLER AcpiGbl_ExternalList = NULL; + AcpiGbl_NumExternalMethods = 0; + AcpiGbl_ResolvedExternalMethods = 0; #endif #ifdef ACPI_DEBUG_OUTPUT diff --git a/source/include/acdisasm.h b/source/include/acdisasm.h index 43ab2c07671..5abf24ecde1 100644 --- a/source/include/acdisasm.h +++ b/source/include/acdisasm.h @@ -314,6 +314,8 @@ extern ACPI_DMTABLE_INFO AcpiDmTableInfoMpst1[]; extern ACPI_DMTABLE_INFO AcpiDmTableInfoMpst2[]; extern ACPI_DMTABLE_INFO AcpiDmTableInfoMsct[]; extern ACPI_DMTABLE_INFO AcpiDmTableInfoMsct0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMtmr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMtmr0[]; extern ACPI_DMTABLE_INFO AcpiDmTableInfoPmtt[]; extern ACPI_DMTABLE_INFO AcpiDmTableInfoPmtt0[]; extern ACPI_DMTABLE_INFO AcpiDmTableInfoPmtt1[]; @@ -343,6 +345,8 @@ extern ACPI_DMTABLE_INFO AcpiDmTableInfoSrat2[]; extern ACPI_DMTABLE_INFO AcpiDmTableInfoTcpa[]; extern ACPI_DMTABLE_INFO AcpiDmTableInfoTpm2[]; extern ACPI_DMTABLE_INFO AcpiDmTableInfoUefi[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoVrtc[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoVrtc0[]; extern ACPI_DMTABLE_INFO AcpiDmTableInfoWaet[]; extern ACPI_DMTABLE_INFO AcpiDmTableInfoWdat[]; extern ACPI_DMTABLE_INFO AcpiDmTableInfoWdat0[]; @@ -456,6 +460,10 @@ void AcpiDmDumpMsct ( ACPI_TABLE_HEADER *Table); +void +AcpiDmDumpMtmr ( + ACPI_TABLE_HEADER *Table); + void AcpiDmDumpPcct ( ACPI_TABLE_HEADER *Table); @@ -488,6 +496,10 @@ void AcpiDmDumpSrat ( ACPI_TABLE_HEADER *Table); +void +AcpiDmDumpVrtc ( + ACPI_TABLE_HEADER *Table); + void AcpiDmDumpWdat ( ACPI_TABLE_HEADER *Table); @@ -677,6 +689,10 @@ void AcpiDmEmitExternals ( void); +void +AcpiDmUnresolvedWarning ( + UINT8 Type); + /* * dmresrc diff --git a/source/include/acexcep.h b/source/include/acexcep.h index 110ef18ede8..9961acc2356 100644 --- a/source/include/acexcep.h +++ b/source/include/acexcep.h @@ -45,55 +45,88 @@ #define __ACEXCEP_H__ +/* This module contains all possible exception codes for ACPI_STATUS */ + /* - * Exceptions returned by external ACPI interfaces + * Exception code classes */ -#define AE_CODE_ENVIRONMENTAL 0x0000 -#define AE_CODE_PROGRAMMER 0x1000 -#define AE_CODE_ACPI_TABLES 0x2000 -#define AE_CODE_AML 0x3000 -#define AE_CODE_CONTROL 0x4000 +#define AE_CODE_ENVIRONMENTAL 0x0000 /* General ACPICA environment */ +#define AE_CODE_PROGRAMMER 0x1000 /* External ACPICA interface caller */ +#define AE_CODE_ACPI_TABLES 0x2000 /* ACPI tables */ +#define AE_CODE_AML 0x3000 /* From executing AML code */ +#define AE_CODE_CONTROL 0x4000 /* Internal control codes */ + #define AE_CODE_MAX 0x4000 #define AE_CODE_MASK 0xF000 +/* + * Macros to insert the exception code classes + */ +#define EXCEP_ENV(code) ((ACPI_STATUS) (code | AE_CODE_ENVIRONMENTAL)) +#define EXCEP_PGM(code) ((ACPI_STATUS) (code | AE_CODE_PROGRAMMER)) +#define EXCEP_TBL(code) ((ACPI_STATUS) (code | AE_CODE_ACPI_TABLES)) +#define EXCEP_AML(code) ((ACPI_STATUS) (code | AE_CODE_AML)) +#define EXCEP_CTL(code) ((ACPI_STATUS) (code | AE_CODE_CONTROL)) +/* + * Exception info table. The "Description" field is used only by the + * ACPICA help application (acpihelp). + */ +typedef struct acpi_exception_info +{ + char *Name; + +#ifdef ACPI_HELP_APP + char *Description; +#endif +} ACPI_EXCEPTION_INFO; + +#ifdef ACPI_HELP_APP +#define EXCEP_TXT(Name,Description) {Name, Description} +#else +#define EXCEP_TXT(Name,Description) {Name} +#endif + + +/* + * Success is always zero, failure is non-zero + */ #define ACPI_SUCCESS(a) (!(a)) #define ACPI_FAILURE(a) (a) - #define AE_OK (ACPI_STATUS) 0x0000 /* * Environmental exceptions */ -#define AE_ERROR (ACPI_STATUS) (0x0001 | AE_CODE_ENVIRONMENTAL) -#define AE_NO_ACPI_TABLES (ACPI_STATUS) (0x0002 | AE_CODE_ENVIRONMENTAL) -#define AE_NO_NAMESPACE (ACPI_STATUS) (0x0003 | AE_CODE_ENVIRONMENTAL) -#define AE_NO_MEMORY (ACPI_STATUS) (0x0004 | AE_CODE_ENVIRONMENTAL) -#define AE_NOT_FOUND (ACPI_STATUS) (0x0005 | AE_CODE_ENVIRONMENTAL) -#define AE_NOT_EXIST (ACPI_STATUS) (0x0006 | AE_CODE_ENVIRONMENTAL) -#define AE_ALREADY_EXISTS (ACPI_STATUS) (0x0007 | AE_CODE_ENVIRONMENTAL) -#define AE_TYPE (ACPI_STATUS) (0x0008 | AE_CODE_ENVIRONMENTAL) -#define AE_NULL_OBJECT (ACPI_STATUS) (0x0009 | AE_CODE_ENVIRONMENTAL) -#define AE_NULL_ENTRY (ACPI_STATUS) (0x000A | AE_CODE_ENVIRONMENTAL) -#define AE_BUFFER_OVERFLOW (ACPI_STATUS) (0x000B | AE_CODE_ENVIRONMENTAL) -#define AE_STACK_OVERFLOW (ACPI_STATUS) (0x000C | AE_CODE_ENVIRONMENTAL) -#define AE_STACK_UNDERFLOW (ACPI_STATUS) (0x000D | AE_CODE_ENVIRONMENTAL) -#define AE_NOT_IMPLEMENTED (ACPI_STATUS) (0x000E | AE_CODE_ENVIRONMENTAL) -#define AE_SUPPORT (ACPI_STATUS) (0x000F | AE_CODE_ENVIRONMENTAL) -#define AE_LIMIT (ACPI_STATUS) (0x0010 | AE_CODE_ENVIRONMENTAL) -#define AE_TIME (ACPI_STATUS) (0x0011 | AE_CODE_ENVIRONMENTAL) -#define AE_ACQUIRE_DEADLOCK (ACPI_STATUS) (0x0012 | AE_CODE_ENVIRONMENTAL) -#define AE_RELEASE_DEADLOCK (ACPI_STATUS) (0x0013 | AE_CODE_ENVIRONMENTAL) -#define AE_NOT_ACQUIRED (ACPI_STATUS) (0x0014 | AE_CODE_ENVIRONMENTAL) -#define AE_ALREADY_ACQUIRED (ACPI_STATUS) (0x0015 | AE_CODE_ENVIRONMENTAL) -#define AE_NO_HARDWARE_RESPONSE (ACPI_STATUS) (0x0016 | AE_CODE_ENVIRONMENTAL) -#define AE_NO_GLOBAL_LOCK (ACPI_STATUS) (0x0017 | AE_CODE_ENVIRONMENTAL) -#define AE_ABORT_METHOD (ACPI_STATUS) (0x0018 | AE_CODE_ENVIRONMENTAL) -#define AE_SAME_HANDLER (ACPI_STATUS) (0x0019 | AE_CODE_ENVIRONMENTAL) -#define AE_NO_HANDLER (ACPI_STATUS) (0x001A | AE_CODE_ENVIRONMENTAL) -#define AE_OWNER_ID_LIMIT (ACPI_STATUS) (0x001B | AE_CODE_ENVIRONMENTAL) -#define AE_NOT_CONFIGURED (ACPI_STATUS) (0x001C | AE_CODE_ENVIRONMENTAL) +#define AE_ERROR EXCEP_ENV (0x0001) +#define AE_NO_ACPI_TABLES EXCEP_ENV (0x0002) +#define AE_NO_NAMESPACE EXCEP_ENV (0x0003) +#define AE_NO_MEMORY EXCEP_ENV (0x0004) +#define AE_NOT_FOUND EXCEP_ENV (0x0005) +#define AE_NOT_EXIST EXCEP_ENV (0x0006) +#define AE_ALREADY_EXISTS EXCEP_ENV (0x0007) +#define AE_TYPE EXCEP_ENV (0x0008) +#define AE_NULL_OBJECT EXCEP_ENV (0x0009) +#define AE_NULL_ENTRY EXCEP_ENV (0x000A) +#define AE_BUFFER_OVERFLOW EXCEP_ENV (0x000B) +#define AE_STACK_OVERFLOW EXCEP_ENV (0x000C) +#define AE_STACK_UNDERFLOW EXCEP_ENV (0x000D) +#define AE_NOT_IMPLEMENTED EXCEP_ENV (0x000E) +#define AE_SUPPORT EXCEP_ENV (0x000F) +#define AE_LIMIT EXCEP_ENV (0x0010) +#define AE_TIME EXCEP_ENV (0x0011) +#define AE_ACQUIRE_DEADLOCK EXCEP_ENV (0x0012) +#define AE_RELEASE_DEADLOCK EXCEP_ENV (0x0013) +#define AE_NOT_ACQUIRED EXCEP_ENV (0x0014) +#define AE_ALREADY_ACQUIRED EXCEP_ENV (0x0015) +#define AE_NO_HARDWARE_RESPONSE EXCEP_ENV (0x0016) +#define AE_NO_GLOBAL_LOCK EXCEP_ENV (0x0017) +#define AE_ABORT_METHOD EXCEP_ENV (0x0018) +#define AE_SAME_HANDLER EXCEP_ENV (0x0019) +#define AE_NO_HANDLER EXCEP_ENV (0x001A) +#define AE_OWNER_ID_LIMIT EXCEP_ENV (0x001B) +#define AE_NOT_CONFIGURED EXCEP_ENV (0x001C) #define AE_CODE_ENV_MAX 0x001C @@ -101,15 +134,15 @@ /* * Programmer exceptions */ -#define AE_BAD_PARAMETER (ACPI_STATUS) (0x0001 | AE_CODE_PROGRAMMER) -#define AE_BAD_CHARACTER (ACPI_STATUS) (0x0002 | AE_CODE_PROGRAMMER) -#define AE_BAD_PATHNAME (ACPI_STATUS) (0x0003 | AE_CODE_PROGRAMMER) -#define AE_BAD_DATA (ACPI_STATUS) (0x0004 | AE_CODE_PROGRAMMER) -#define AE_BAD_HEX_CONSTANT (ACPI_STATUS) (0x0005 | AE_CODE_PROGRAMMER) -#define AE_BAD_OCTAL_CONSTANT (ACPI_STATUS) (0x0006 | AE_CODE_PROGRAMMER) -#define AE_BAD_DECIMAL_CONSTANT (ACPI_STATUS) (0x0007 | AE_CODE_PROGRAMMER) -#define AE_MISSING_ARGUMENTS (ACPI_STATUS) (0x0008 | AE_CODE_PROGRAMMER) -#define AE_BAD_ADDRESS (ACPI_STATUS) (0x0009 | AE_CODE_PROGRAMMER) +#define AE_BAD_PARAMETER EXCEP_PGM (0x0001) +#define AE_BAD_CHARACTER EXCEP_PGM (0x0002) +#define AE_BAD_PATHNAME EXCEP_PGM (0x0003) +#define AE_BAD_DATA EXCEP_PGM (0x0004) +#define AE_BAD_HEX_CONSTANT EXCEP_PGM (0x0005) +#define AE_BAD_OCTAL_CONSTANT EXCEP_PGM (0x0006) +#define AE_BAD_DECIMAL_CONSTANT EXCEP_PGM (0x0007) +#define AE_MISSING_ARGUMENTS EXCEP_PGM (0x0008) +#define AE_BAD_ADDRESS EXCEP_PGM (0x0009) #define AE_CODE_PGM_MAX 0x0009 @@ -117,11 +150,11 @@ /* * Acpi table exceptions */ -#define AE_BAD_SIGNATURE (ACPI_STATUS) (0x0001 | AE_CODE_ACPI_TABLES) -#define AE_BAD_HEADER (ACPI_STATUS) (0x0002 | AE_CODE_ACPI_TABLES) -#define AE_BAD_CHECKSUM (ACPI_STATUS) (0x0003 | AE_CODE_ACPI_TABLES) -#define AE_BAD_VALUE (ACPI_STATUS) (0x0004 | AE_CODE_ACPI_TABLES) -#define AE_INVALID_TABLE_LENGTH (ACPI_STATUS) (0x0005 | AE_CODE_ACPI_TABLES) +#define AE_BAD_SIGNATURE EXCEP_TBL (0x0001) +#define AE_BAD_HEADER EXCEP_TBL (0x0002) +#define AE_BAD_CHECKSUM EXCEP_TBL (0x0003) +#define AE_BAD_VALUE EXCEP_TBL (0x0004) +#define AE_INVALID_TABLE_LENGTH EXCEP_TBL (0x0005) #define AE_CODE_TBL_MAX 0x0005 @@ -130,39 +163,39 @@ * AML exceptions. These are caused by problems with * the actual AML byte stream */ -#define AE_AML_BAD_OPCODE (ACPI_STATUS) (0x0001 | AE_CODE_AML) -#define AE_AML_NO_OPERAND (ACPI_STATUS) (0x0002 | AE_CODE_AML) -#define AE_AML_OPERAND_TYPE (ACPI_STATUS) (0x0003 | AE_CODE_AML) -#define AE_AML_OPERAND_VALUE (ACPI_STATUS) (0x0004 | AE_CODE_AML) -#define AE_AML_UNINITIALIZED_LOCAL (ACPI_STATUS) (0x0005 | AE_CODE_AML) -#define AE_AML_UNINITIALIZED_ARG (ACPI_STATUS) (0x0006 | AE_CODE_AML) -#define AE_AML_UNINITIALIZED_ELEMENT (ACPI_STATUS) (0x0007 | AE_CODE_AML) -#define AE_AML_NUMERIC_OVERFLOW (ACPI_STATUS) (0x0008 | AE_CODE_AML) -#define AE_AML_REGION_LIMIT (ACPI_STATUS) (0x0009 | AE_CODE_AML) -#define AE_AML_BUFFER_LIMIT (ACPI_STATUS) (0x000A | AE_CODE_AML) -#define AE_AML_PACKAGE_LIMIT (ACPI_STATUS) (0x000B | AE_CODE_AML) -#define AE_AML_DIVIDE_BY_ZERO (ACPI_STATUS) (0x000C | AE_CODE_AML) -#define AE_AML_BAD_NAME (ACPI_STATUS) (0x000D | AE_CODE_AML) -#define AE_AML_NAME_NOT_FOUND (ACPI_STATUS) (0x000E | AE_CODE_AML) -#define AE_AML_INTERNAL (ACPI_STATUS) (0x000F | AE_CODE_AML) -#define AE_AML_INVALID_SPACE_ID (ACPI_STATUS) (0x0010 | AE_CODE_AML) -#define AE_AML_STRING_LIMIT (ACPI_STATUS) (0x0011 | AE_CODE_AML) -#define AE_AML_NO_RETURN_VALUE (ACPI_STATUS) (0x0012 | AE_CODE_AML) -#define AE_AML_METHOD_LIMIT (ACPI_STATUS) (0x0013 | AE_CODE_AML) -#define AE_AML_NOT_OWNER (ACPI_STATUS) (0x0014 | AE_CODE_AML) -#define AE_AML_MUTEX_ORDER (ACPI_STATUS) (0x0015 | AE_CODE_AML) -#define AE_AML_MUTEX_NOT_ACQUIRED (ACPI_STATUS) (0x0016 | AE_CODE_AML) -#define AE_AML_INVALID_RESOURCE_TYPE (ACPI_STATUS) (0x0017 | AE_CODE_AML) -#define AE_AML_INVALID_INDEX (ACPI_STATUS) (0x0018 | AE_CODE_AML) -#define AE_AML_REGISTER_LIMIT (ACPI_STATUS) (0x0019 | AE_CODE_AML) -#define AE_AML_NO_WHILE (ACPI_STATUS) (0x001A | AE_CODE_AML) -#define AE_AML_ALIGNMENT (ACPI_STATUS) (0x001B | AE_CODE_AML) -#define AE_AML_NO_RESOURCE_END_TAG (ACPI_STATUS) (0x001C | AE_CODE_AML) -#define AE_AML_BAD_RESOURCE_VALUE (ACPI_STATUS) (0x001D | AE_CODE_AML) -#define AE_AML_CIRCULAR_REFERENCE (ACPI_STATUS) (0x001E | AE_CODE_AML) -#define AE_AML_BAD_RESOURCE_LENGTH (ACPI_STATUS) (0x001F | AE_CODE_AML) -#define AE_AML_ILLEGAL_ADDRESS (ACPI_STATUS) (0x0020 | AE_CODE_AML) -#define AE_AML_INFINITE_LOOP (ACPI_STATUS) (0x0021 | AE_CODE_AML) +#define AE_AML_BAD_OPCODE EXCEP_AML (0x0001) +#define AE_AML_NO_OPERAND EXCEP_AML (0x0002) +#define AE_AML_OPERAND_TYPE EXCEP_AML (0x0003) +#define AE_AML_OPERAND_VALUE EXCEP_AML (0x0004) +#define AE_AML_UNINITIALIZED_LOCAL EXCEP_AML (0x0005) +#define AE_AML_UNINITIALIZED_ARG EXCEP_AML (0x0006) +#define AE_AML_UNINITIALIZED_ELEMENT EXCEP_AML (0x0007) +#define AE_AML_NUMERIC_OVERFLOW EXCEP_AML (0x0008) +#define AE_AML_REGION_LIMIT EXCEP_AML (0x0009) +#define AE_AML_BUFFER_LIMIT EXCEP_AML (0x000A) +#define AE_AML_PACKAGE_LIMIT EXCEP_AML (0x000B) +#define AE_AML_DIVIDE_BY_ZERO EXCEP_AML (0x000C) +#define AE_AML_BAD_NAME EXCEP_AML (0x000D) +#define AE_AML_NAME_NOT_FOUND EXCEP_AML (0x000E) +#define AE_AML_INTERNAL EXCEP_AML (0x000F) +#define AE_AML_INVALID_SPACE_ID EXCEP_AML (0x0010) +#define AE_AML_STRING_LIMIT EXCEP_AML (0x0011) +#define AE_AML_NO_RETURN_VALUE EXCEP_AML (0x0012) +#define AE_AML_METHOD_LIMIT EXCEP_AML (0x0013) +#define AE_AML_NOT_OWNER EXCEP_AML (0x0014) +#define AE_AML_MUTEX_ORDER EXCEP_AML (0x0015) +#define AE_AML_MUTEX_NOT_ACQUIRED EXCEP_AML (0x0016) +#define AE_AML_INVALID_RESOURCE_TYPE EXCEP_AML (0x0017) +#define AE_AML_INVALID_INDEX EXCEP_AML (0x0018) +#define AE_AML_REGISTER_LIMIT EXCEP_AML (0x0019) +#define AE_AML_NO_WHILE EXCEP_AML (0x001A) +#define AE_AML_ALIGNMENT EXCEP_AML (0x001B) +#define AE_AML_NO_RESOURCE_END_TAG EXCEP_AML (0x001C) +#define AE_AML_BAD_RESOURCE_VALUE EXCEP_AML (0x001D) +#define AE_AML_CIRCULAR_REFERENCE EXCEP_AML (0x001E) +#define AE_AML_BAD_RESOURCE_LENGTH EXCEP_AML (0x001F) +#define AE_AML_ILLEGAL_ADDRESS EXCEP_AML (0x0020) +#define AE_AML_INFINITE_LOOP EXCEP_AML (0x0021) #define AE_CODE_AML_MAX 0x0021 @@ -170,19 +203,19 @@ /* * Internal exceptions used for control */ -#define AE_CTRL_RETURN_VALUE (ACPI_STATUS) (0x0001 | AE_CODE_CONTROL) -#define AE_CTRL_PENDING (ACPI_STATUS) (0x0002 | AE_CODE_CONTROL) -#define AE_CTRL_TERMINATE (ACPI_STATUS) (0x0003 | AE_CODE_CONTROL) -#define AE_CTRL_TRUE (ACPI_STATUS) (0x0004 | AE_CODE_CONTROL) -#define AE_CTRL_FALSE (ACPI_STATUS) (0x0005 | AE_CODE_CONTROL) -#define AE_CTRL_DEPTH (ACPI_STATUS) (0x0006 | AE_CODE_CONTROL) -#define AE_CTRL_END (ACPI_STATUS) (0x0007 | AE_CODE_CONTROL) -#define AE_CTRL_TRANSFER (ACPI_STATUS) (0x0008 | AE_CODE_CONTROL) -#define AE_CTRL_BREAK (ACPI_STATUS) (0x0009 | AE_CODE_CONTROL) -#define AE_CTRL_CONTINUE (ACPI_STATUS) (0x000A | AE_CODE_CONTROL) -#define AE_CTRL_SKIP (ACPI_STATUS) (0x000B | AE_CODE_CONTROL) -#define AE_CTRL_PARSE_CONTINUE (ACPI_STATUS) (0x000C | AE_CODE_CONTROL) -#define AE_CTRL_PARSE_PENDING (ACPI_STATUS) (0x000D | AE_CODE_CONTROL) +#define AE_CTRL_RETURN_VALUE EXCEP_CTL (0x0001) +#define AE_CTRL_PENDING EXCEP_CTL (0x0002) +#define AE_CTRL_TERMINATE EXCEP_CTL (0x0003) +#define AE_CTRL_TRUE EXCEP_CTL (0x0004) +#define AE_CTRL_FALSE EXCEP_CTL (0x0005) +#define AE_CTRL_DEPTH EXCEP_CTL (0x0006) +#define AE_CTRL_END EXCEP_CTL (0x0007) +#define AE_CTRL_TRANSFER EXCEP_CTL (0x0008) +#define AE_CTRL_BREAK EXCEP_CTL (0x0009) +#define AE_CTRL_CONTINUE EXCEP_CTL (0x000A) +#define AE_CTRL_SKIP EXCEP_CTL (0x000B) +#define AE_CTRL_PARSE_CONTINUE EXCEP_CTL (0x000C) +#define AE_CTRL_PARSE_PENDING EXCEP_CTL (0x000D) #define AE_CODE_CTRL_MAX 0x000D @@ -195,117 +228,117 @@ * String versions of the exception codes above * These strings must match the corresponding defines exactly */ -char const *AcpiGbl_ExceptionNames_Env[] = +static const ACPI_EXCEPTION_INFO AcpiGbl_ExceptionNames_Env[] = { - "AE_OK", - "AE_ERROR", - "AE_NO_ACPI_TABLES", - "AE_NO_NAMESPACE", - "AE_NO_MEMORY", - "AE_NOT_FOUND", - "AE_NOT_EXIST", - "AE_ALREADY_EXISTS", - "AE_TYPE", - "AE_NULL_OBJECT", - "AE_NULL_ENTRY", - "AE_BUFFER_OVERFLOW", - "AE_STACK_OVERFLOW", - "AE_STACK_UNDERFLOW", - "AE_NOT_IMPLEMENTED", - "AE_SUPPORT", - "AE_LIMIT", - "AE_TIME", - "AE_ACQUIRE_DEADLOCK", - "AE_RELEASE_DEADLOCK", - "AE_NOT_ACQUIRED", - "AE_ALREADY_ACQUIRED", - "AE_NO_HARDWARE_RESPONSE", - "AE_NO_GLOBAL_LOCK", - "AE_ABORT_METHOD", - "AE_SAME_HANDLER", - "AE_NO_HANDLER", - "AE_OWNER_ID_LIMIT", - "AE_NOT_CONFIGURED" + EXCEP_TXT ("AE_OK", "No error"), + EXCEP_TXT ("AE_ERROR", "Unspecified error"), + EXCEP_TXT ("AE_NO_ACPI_TABLES", "ACPI tables could not be found"), + EXCEP_TXT ("AE_NO_NAMESPACE", "A namespace has not been loaded"), + EXCEP_TXT ("AE_NO_MEMORY", "Insufficient dynamic memory"), + EXCEP_TXT ("AE_NOT_FOUND", "The name was not found in the namespace"), + EXCEP_TXT ("AE_NOT_EXIST", "A required entity does not exist"), + EXCEP_TXT ("AE_ALREADY_EXISTS", "An entity already exists"), + EXCEP_TXT ("AE_TYPE", "The object type is incorrect"), + EXCEP_TXT ("AE_NULL_OBJECT", "A required object was missing"), + EXCEP_TXT ("AE_NULL_ENTRY", "The requested object does not exist"), + EXCEP_TXT ("AE_BUFFER_OVERFLOW", "The buffer provided is too small"), + EXCEP_TXT ("AE_STACK_OVERFLOW", "An internal stack overflowed"), + EXCEP_TXT ("AE_STACK_UNDERFLOW", "An internal stack underflowed"), + EXCEP_TXT ("AE_NOT_IMPLEMENTED", "The feature is not implemented"), + EXCEP_TXT ("AE_SUPPORT", "The feature is not supported"), + EXCEP_TXT ("AE_LIMIT", "A predefined limit was exceeded"), + EXCEP_TXT ("AE_TIME", "A time limit or timeout expired"), + EXCEP_TXT ("AE_ACQUIRE_DEADLOCK", "Internal error, attempt was made to acquire a mutex in improper order"), + EXCEP_TXT ("AE_RELEASE_DEADLOCK", "Internal error, attempt was made to release a mutex in improper order"), + EXCEP_TXT ("AE_NOT_ACQUIRED", "An attempt to release a mutex or Global Lock without a previous acquire"), + EXCEP_TXT ("AE_ALREADY_ACQUIRED", "Internal error, attempt was made to acquire a mutex twice"), + EXCEP_TXT ("AE_NO_HARDWARE_RESPONSE", "Hardware did not respond after an I/O operation"), + EXCEP_TXT ("AE_NO_GLOBAL_LOCK", "There is no FACS Global Lock"), + EXCEP_TXT ("AE_ABORT_METHOD", "A control method was aborted"), + EXCEP_TXT ("AE_SAME_HANDLER", "Attempt was made to install the same handler that is already installed"), + EXCEP_TXT ("AE_NO_HANDLER", "A handler for the operation is not installed"), + EXCEP_TXT ("AE_OWNER_ID_LIMIT", "There are no more Owner IDs available for ACPI tables or control methods"), + EXCEP_TXT ("AE_NOT_CONFIGURED", "The interface is not part of the current subsystem configuration") }; -char const *AcpiGbl_ExceptionNames_Pgm[] = +static const ACPI_EXCEPTION_INFO AcpiGbl_ExceptionNames_Pgm[] = { - NULL, - "AE_BAD_PARAMETER", - "AE_BAD_CHARACTER", - "AE_BAD_PATHNAME", - "AE_BAD_DATA", - "AE_BAD_HEX_CONSTANT", - "AE_BAD_OCTAL_CONSTANT", - "AE_BAD_DECIMAL_CONSTANT", - "AE_MISSING_ARGUMENTS", - "AE_BAD_ADDRESS" + EXCEP_TXT (NULL, NULL), + EXCEP_TXT ("AE_BAD_PARAMETER", "A parameter is out of range or invalid"), + EXCEP_TXT ("AE_BAD_CHARACTER", "An invalid character was found in a name"), + EXCEP_TXT ("AE_BAD_PATHNAME", "An invalid character was found in a pathname"), + EXCEP_TXT ("AE_BAD_DATA", "A package or buffer contained incorrect data"), + EXCEP_TXT ("AE_BAD_HEX_CONSTANT", "Invalid character in a Hex constant"), + EXCEP_TXT ("AE_BAD_OCTAL_CONSTANT", "Invalid character in an Octal constant"), + EXCEP_TXT ("AE_BAD_DECIMAL_CONSTANT", "Invalid character in a Decimal constant"), + EXCEP_TXT ("AE_MISSING_ARGUMENTS", "Too few arguments were passed to a control method"), + EXCEP_TXT ("AE_BAD_ADDRESS", "An illegal null I/O address") }; -char const *AcpiGbl_ExceptionNames_Tbl[] = +static const ACPI_EXCEPTION_INFO AcpiGbl_ExceptionNames_Tbl[] = { - NULL, - "AE_BAD_SIGNATURE", - "AE_BAD_HEADER", - "AE_BAD_CHECKSUM", - "AE_BAD_VALUE", - "AE_INVALID_TABLE_LENGTH" + EXCEP_TXT (NULL, NULL), + EXCEP_TXT ("AE_BAD_SIGNATURE", "An ACPI table has an invalid signature"), + EXCEP_TXT ("AE_BAD_HEADER", "Invalid field in an ACPI table header"), + EXCEP_TXT ("AE_BAD_CHECKSUM", "An ACPI table checksum is not correct"), + EXCEP_TXT ("AE_BAD_VALUE", "An invalid value was found in a table"), + EXCEP_TXT ("AE_INVALID_TABLE_LENGTH", "The FADT or FACS has improper length") }; -char const *AcpiGbl_ExceptionNames_Aml[] = +static const ACPI_EXCEPTION_INFO AcpiGbl_ExceptionNames_Aml[] = { - NULL, - "AE_AML_BAD_OPCODE", - "AE_AML_NO_OPERAND", - "AE_AML_OPERAND_TYPE", - "AE_AML_OPERAND_VALUE", - "AE_AML_UNINITIALIZED_LOCAL", - "AE_AML_UNINITIALIZED_ARG", - "AE_AML_UNINITIALIZED_ELEMENT", - "AE_AML_NUMERIC_OVERFLOW", - "AE_AML_REGION_LIMIT", - "AE_AML_BUFFER_LIMIT", - "AE_AML_PACKAGE_LIMIT", - "AE_AML_DIVIDE_BY_ZERO", - "AE_AML_BAD_NAME", - "AE_AML_NAME_NOT_FOUND", - "AE_AML_INTERNAL", - "AE_AML_INVALID_SPACE_ID", - "AE_AML_STRING_LIMIT", - "AE_AML_NO_RETURN_VALUE", - "AE_AML_METHOD_LIMIT", - "AE_AML_NOT_OWNER", - "AE_AML_MUTEX_ORDER", - "AE_AML_MUTEX_NOT_ACQUIRED", - "AE_AML_INVALID_RESOURCE_TYPE", - "AE_AML_INVALID_INDEX", - "AE_AML_REGISTER_LIMIT", - "AE_AML_NO_WHILE", - "AE_AML_ALIGNMENT", - "AE_AML_NO_RESOURCE_END_TAG", - "AE_AML_BAD_RESOURCE_VALUE", - "AE_AML_CIRCULAR_REFERENCE", - "AE_AML_BAD_RESOURCE_LENGTH", - "AE_AML_ILLEGAL_ADDRESS", - "AE_AML_INFINITE_LOOP" + EXCEP_TXT (NULL, NULL), + EXCEP_TXT ("AE_AML_BAD_OPCODE", "Invalid AML opcode encountered"), + EXCEP_TXT ("AE_AML_NO_OPERAND", "A required operand is missing"), + EXCEP_TXT ("AE_AML_OPERAND_TYPE", "An operand of an incorrect type was encountered"), + EXCEP_TXT ("AE_AML_OPERAND_VALUE", "The operand had an inappropriate or invalid value"), + EXCEP_TXT ("AE_AML_UNINITIALIZED_LOCAL", "Method tried to use an uninitialized local variable"), + EXCEP_TXT ("AE_AML_UNINITIALIZED_ARG", "Method tried to use an uninitialized argument"), + EXCEP_TXT ("AE_AML_UNINITIALIZED_ELEMENT", "Method tried to use an empty package element"), + EXCEP_TXT ("AE_AML_NUMERIC_OVERFLOW", "Overflow during BCD conversion or other"), + EXCEP_TXT ("AE_AML_REGION_LIMIT", "Tried to access beyond the end of an Operation Region"), + EXCEP_TXT ("AE_AML_BUFFER_LIMIT", "Tried to access beyond the end of a buffer"), + EXCEP_TXT ("AE_AML_PACKAGE_LIMIT", "Tried to access beyond the end of a package"), + EXCEP_TXT ("AE_AML_DIVIDE_BY_ZERO", "During execution of AML Divide operator"), + EXCEP_TXT ("AE_AML_BAD_NAME", "An ACPI name contains invalid character(s)"), + EXCEP_TXT ("AE_AML_NAME_NOT_FOUND", "Could not resolve a named reference"), + EXCEP_TXT ("AE_AML_INTERNAL", "An internal error within the interprete"), + EXCEP_TXT ("AE_AML_INVALID_SPACE_ID", "An Operation Region SpaceID is invalid"), + EXCEP_TXT ("AE_AML_STRING_LIMIT", "String is longer than 200 characters"), + EXCEP_TXT ("AE_AML_NO_RETURN_VALUE", "A method did not return a required value"), + EXCEP_TXT ("AE_AML_METHOD_LIMIT", "A control method reached the maximum reentrancy limit of 255"), + EXCEP_TXT ("AE_AML_NOT_OWNER", "A thread tried to release a mutex that it does not own"), + EXCEP_TXT ("AE_AML_MUTEX_ORDER", "Mutex SyncLevel release mismatch"), + EXCEP_TXT ("AE_AML_MUTEX_NOT_ACQUIRED", "Attempt to release a mutex that was not previously acquired"), + EXCEP_TXT ("AE_AML_INVALID_RESOURCE_TYPE", "Invalid resource type in resource list"), + EXCEP_TXT ("AE_AML_INVALID_INDEX", "Invalid Argx or Localx (x too large)"), + EXCEP_TXT ("AE_AML_REGISTER_LIMIT", "Bank value or Index value beyond range of register"), + EXCEP_TXT ("AE_AML_NO_WHILE", "Break or Continue without a While"), + EXCEP_TXT ("AE_AML_ALIGNMENT", "Non-aligned memory transfer on platform that does not support this"), + EXCEP_TXT ("AE_AML_NO_RESOURCE_END_TAG", "No End Tag in a resource list"), + EXCEP_TXT ("AE_AML_BAD_RESOURCE_VALUE", "Invalid value of a resource element"), + EXCEP_TXT ("AE_AML_CIRCULAR_REFERENCE", "Two references refer to each other"), + EXCEP_TXT ("AE_AML_BAD_RESOURCE_LENGTH", "The length of a Resource Descriptor in the AML is incorrect"), + EXCEP_TXT ("AE_AML_ILLEGAL_ADDRESS", "A memory, I/O, or PCI configuration address is invalid"), + EXCEP_TXT ("AE_AML_INFINITE_LOOP", "An apparent infinite AML While loop, method was aborted") }; -char const *AcpiGbl_ExceptionNames_Ctrl[] = +static const ACPI_EXCEPTION_INFO AcpiGbl_ExceptionNames_Ctrl[] = { - NULL, - "AE_CTRL_RETURN_VALUE", - "AE_CTRL_PENDING", - "AE_CTRL_TERMINATE", - "AE_CTRL_TRUE", - "AE_CTRL_FALSE", - "AE_CTRL_DEPTH", - "AE_CTRL_END", - "AE_CTRL_TRANSFER", - "AE_CTRL_BREAK", - "AE_CTRL_CONTINUE", - "AE_CTRL_SKIP", - "AE_CTRL_PARSE_CONTINUE", - "AE_CTRL_PARSE_PENDING" + EXCEP_TXT (NULL, NULL), + EXCEP_TXT ("AE_CTRL_RETURN_VALUE", "A Method returned a value"), + EXCEP_TXT ("AE_CTRL_PENDING", "Method is calling another method"), + EXCEP_TXT ("AE_CTRL_TERMINATE", "Terminate the executing method"), + EXCEP_TXT ("AE_CTRL_TRUE", "An If or While predicate result"), + EXCEP_TXT ("AE_CTRL_FALSE", "An If or While predicate result"), + EXCEP_TXT ("AE_CTRL_DEPTH", "Maximum search depth has been reached"), + EXCEP_TXT ("AE_CTRL_END", "An If or While predicate is false"), + EXCEP_TXT ("AE_CTRL_TRANSFER", "Transfer control to called method"), + EXCEP_TXT ("AE_CTRL_BREAK", "A Break has been executed"), + EXCEP_TXT ("AE_CTRL_CONTINUE", "A Continue has been executed"), + EXCEP_TXT ("AE_CTRL_SKIP", "Not currently used"), + EXCEP_TXT ("AE_CTRL_PARSE_CONTINUE", "Used to skip over bad opcodes"), + EXCEP_TXT ("AE_CTRL_PARSE_PENDING", "Used to implement AML While loops") }; #endif /* EXCEPTION_TABLE */ diff --git a/source/include/acglobal.h b/source/include/acglobal.h index c528974711f..987fc6126ef 100644 --- a/source/include/acglobal.h +++ b/source/include/acglobal.h @@ -420,10 +420,12 @@ ACPI_EXTERN UINT8 AcpiGbl_DbOutputFlags; #ifdef ACPI_DISASSEMBLER -BOOLEAN ACPI_INIT_GLOBAL (AcpiGbl_IgnoreNoopOperator, FALSE); +ACPI_EXTERN BOOLEAN ACPI_INIT_GLOBAL (AcpiGbl_IgnoreNoopOperator, FALSE); ACPI_EXTERN BOOLEAN AcpiGbl_DbOpt_disasm; ACPI_EXTERN BOOLEAN AcpiGbl_DbOpt_verbose; +ACPI_EXTERN BOOLEAN AcpiGbl_NumExternalMethods; +ACPI_EXTERN UINT32 AcpiGbl_ResolvedExternalMethods; ACPI_EXTERN ACPI_EXTERNAL_LIST *AcpiGbl_ExternalList; ACPI_EXTERN ACPI_EXTERNAL_FILE *AcpiGbl_ExternalFileList; #endif diff --git a/source/include/aclocal.h b/source/include/aclocal.h index 798c4cb3825..ab03935a9c4 100644 --- a/source/include/aclocal.h +++ b/source/include/aclocal.h @@ -417,6 +417,7 @@ typedef struct acpi_predefined_data union acpi_operand_object *ParentPackage; ACPI_NAMESPACE_NODE *Node; UINT32 Flags; + UINT32 ReturnBtype; UINT8 NodeFlags; } ACPI_PREDEFINED_DATA; @@ -427,6 +428,22 @@ typedef struct acpi_predefined_data #define ACPI_OBJECT_WRAPPED 2 +/* Return object auto-repair info */ + +typedef ACPI_STATUS (*ACPI_OBJECT_CONVERTER) ( + union acpi_operand_object *OriginalObject, + union acpi_operand_object **ConvertedObject); + +typedef struct acpi_simple_repair_info +{ + char Name[ACPI_NAME_SIZE]; + UINT32 UnexpectedBtypes; + UINT32 PackageIndex; + ACPI_OBJECT_CONVERTER ObjectConverter; + +} ACPI_SIMPLE_REPAIR_INFO; + + /* * Bitmapped return value types * Note: the actual data types must be contiguous, a loop in nspredef.c @@ -1217,6 +1234,7 @@ typedef struct acpi_external_list UINT16 Length; UINT8 Type; UINT8 Flags; + BOOLEAN Resolved; } ACPI_EXTERNAL_LIST; diff --git a/source/include/acnamesp.h b/source/include/acnamesp.h index 7a92143328f..4009c2d1443 100644 --- a/source/include/acnamesp.h +++ b/source/include/acnamesp.h @@ -203,6 +203,35 @@ AcpiNsCompareNames ( char *Name2); +/* + * nsconvert - Dynamic object conversion routines + */ +ACPI_STATUS +AcpiNsConvertToInteger ( + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ReturnObject); + +ACPI_STATUS +AcpiNsConvertToString ( + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ReturnObject); + +ACPI_STATUS +AcpiNsConvertToBuffer ( + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ReturnObject); + +ACPI_STATUS +AcpiNsConvertToUnicode ( + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ReturnObject); + +ACPI_STATUS +AcpiNsConvertToResource ( + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ReturnObject); + + /* * nsdump - Namespace dump/print utilities */ @@ -377,7 +406,7 @@ AcpiNsGetAttachedData ( * predefined methods/objects */ ACPI_STATUS -AcpiNsRepairObject ( +AcpiNsSimpleRepair ( ACPI_PREDEFINED_DATA *Data, UINT32 ExpectedBtypes, UINT32 PackageIndex, diff --git a/source/include/acoutput.h b/source/include/acoutput.h index 4b5ca9c78e2..371ce7fc8fb 100644 --- a/source/include/acoutput.h +++ b/source/include/acoutput.h @@ -409,6 +409,11 @@ #define return_VALUE(Value) \ ACPI_TRACE_EXIT (AcpiUtValueExit, UINT64, Value) +#define return_UINT32(Value) \ + ACPI_TRACE_EXIT (AcpiUtValueExit, UINT32, Value) + +#define return_UINT8(Value) \ + ACPI_TRACE_EXIT (AcpiUtValueExit, UINT8, Value) /* Conditional execution */ @@ -457,8 +462,10 @@ #define return_VOID return #define return_ACPI_STATUS(s) return(s) -#define return_VALUE(s) return(s) #define return_PTR(s) return(s) +#define return_VALUE(s) return(s) +#define return_UINT8(s) return(s) +#define return_UINT32(s) return(s) #endif /* ACPI_DEBUG_OUTPUT */ diff --git a/source/include/acpixf.h b/source/include/acpixf.h index 76f9afbc47b..a547bcc8bb1 100644 --- a/source/include/acpixf.h +++ b/source/include/acpixf.h @@ -47,7 +47,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20130117 +#define ACPI_CA_VERSION 0x20130214 #include "acconfig.h" #include "actypes.h" diff --git a/source/include/actbl2.h b/source/include/actbl2.h index 49b9578b682..327a8105e6c 100644 --- a/source/include/actbl2.h +++ b/source/include/actbl2.h @@ -74,11 +74,13 @@ #define ACPI_SIG_IVRS "IVRS" /* I/O Virtualization Reporting Structure */ #define ACPI_SIG_MCFG "MCFG" /* PCI Memory Mapped Configuration table */ #define ACPI_SIG_MCHI "MCHI" /* Management Controller Host Interface table */ +#define ACPI_SIG_MTMR "MTMR" /* MID Timer table */ #define ACPI_SIG_SLIC "SLIC" /* Software Licensing Description Table */ #define ACPI_SIG_SPCR "SPCR" /* Serial Port Console Redirection table */ #define ACPI_SIG_SPMI "SPMI" /* Server Platform Management Interface table */ #define ACPI_SIG_TCPA "TCPA" /* Trusted Computing Platform Alliance table */ #define ACPI_SIG_UEFI "UEFI" /* Uefi Boot Optimization Table */ +#define ACPI_SIG_VRTC "VRTC" /* Virtual Real Time Clock Table */ #define ACPI_SIG_WAET "WAET" /* Windows ACPI Emulated devices Table */ #define ACPI_SIG_WDAT "WDAT" /* Watchdog Action Table */ #define ACPI_SIG_WDDT "WDDT" /* Watchdog Timer Description Table */ @@ -981,6 +983,34 @@ typedef struct acpi_table_mchi } ACPI_TABLE_MCHI; +/******************************************************************************* + * + * MTMR - MID Timer Table + * Version 1 + * + * Conforms to "Simple Firmware Interface Specification", + * Draft 0.8.2, Oct 19, 2010 + * NOTE: The ACPI MTMR is equivalent to the SFI MTMR table. + * + ******************************************************************************/ + +typedef struct acpi_table_mtmr +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + +} ACPI_TABLE_MTMR; + +/* MTMR entry */ + +typedef struct acpi_mtmr_entry +{ + ACPI_GENERIC_ADDRESS PhysicalAddress; + UINT32 Frequency; + UINT32 Irq; + +} ACPI_MTMR_ENTRY; + + /******************************************************************************* * * SLIC - Software Licensing Description Table @@ -1180,6 +1210,33 @@ typedef struct acpi_table_uefi } ACPI_TABLE_UEFI; +/******************************************************************************* + * + * VRTC - Virtual Real Time Clock Table + * Version 1 + * + * Conforms to "Simple Firmware Interface Specification", + * Draft 0.8.2, Oct 19, 2010 + * NOTE: The ACPI VRTC is equivalent to The SFI MRTC table. + * + ******************************************************************************/ + +typedef struct acpi_table_vrtc +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + +} ACPI_TABLE_VRTC; + +/* VRTC entry */ + +typedef struct acpi_vrtc_entry +{ + ACPI_GENERIC_ADDRESS PhysicalAddress; + UINT32 Irq; + +} ACPI_VRTC_ENTRY; + + /******************************************************************************* * * WAET - Windows ACPI Emulated devices Table diff --git a/source/include/actbl3.h b/source/include/actbl3.h index 46c3c6d70f1..acf2e13560d 100644 --- a/source/include/actbl3.h +++ b/source/include/actbl3.h @@ -195,7 +195,7 @@ typedef struct acpi_fpdt_header enum AcpiFpdtType { ACPI_FPDT_TYPE_BOOT = 0, - ACPI_FPDT_TYPE_S3PERF = 1, + ACPI_FPDT_TYPE_S3PERF = 1 }; @@ -257,7 +257,7 @@ typedef struct acpi_s3pt_header enum AcpiS3ptType { ACPI_S3PT_TYPE_RESUME = 0, - ACPI_S3PT_TYPE_SUSPEND = 1, + ACPI_S3PT_TYPE_SUSPEND = 1 }; typedef struct acpi_s3pt_resume @@ -599,28 +599,67 @@ typedef struct acpi_rasf_shared_memory UINT32 Signature; UINT16 Command; UINT16 Status; - UINT64 RequestedAddress; - UINT64 RequestedLength; - UINT64 ActualAddress; - UINT64 ActualLength; - UINT16 Flags; - UINT8 Speed; + UINT16 Version; + UINT8 Capabilities[16]; + UINT8 SetCapabilities[16]; + UINT16 NumParameterBlocks; + UINT32 SetCapabilitiesStatus; } ACPI_RASF_SHARED_MEMORY; +/* RASF Parameter Block Structure Header */ + +typedef struct acpi_rasf_parameter_block +{ + UINT16 Type; + UINT16 Version; + UINT16 Length; + +} ACPI_RASF_PARAMETER_BLOCK; + +/* RASF Parameter Block Structure for PATROL_SCRUB */ + +typedef struct acpi_rasf_patrol_scrub_parameter +{ + ACPI_RASF_PARAMETER_BLOCK Header; + UINT16 PatrolScrubCommand; + UINT64 RequestedAddressRange[2]; + UINT64 ActualAddressRange[2]; + UINT16 Flags; + UINT8 RequestedSpeed; + +} ACPI_RASF_PATROL_SCRUB_PARAMETER; + /* Masks for Flags and Speed fields above */ #define ACPI_RASF_SCRUBBER_RUNNING 1 #define ACPI_RASF_SPEED (7<<1) +#define ACPI_RASF_SPEED_SLOW (0<<1) +#define ACPI_RASF_SPEED_MEDIUM (4<<1) +#define ACPI_RASF_SPEED_FAST (7<<1) /* Channel Commands */ enum AcpiRasfCommands { - ACPI_RASF_GET_RAS_CAPABILITIES = 1, - ACPI_RASF_GET_PATROL_PARAMETERS = 2, - ACPI_RASF_START_PATROL_SCRUBBER = 3, - ACPI_RASF_STOP_PATROL_SCRUBBER = 4 + ACPI_RASF_EXECUTE_RASF_COMMAND = 1 +}; + +/* Platform RAS Capabilities */ + +enum AcpiRasfCapabiliities +{ + ACPI_HW_PATROL_SCRUB_SUPPORTED = 0, + ACPI_SW_PATROL_SCRUB_EXPOSED = 1 +}; + +/* Patrol Scrub Commands */ + +enum AcpiRasfPatrolScrubCommands +{ + ACPI_RASF_GET_PATROL_PARAMETERS = 1, + ACPI_RASF_START_PATROL_SCRUBBER = 2, + ACPI_RASF_STOP_PATROL_SCRUBBER = 3 }; /* Channel Command flags */ diff --git a/source/include/acutils.h b/source/include/acutils.h index e75e248931c..165a1587e71 100644 --- a/source/include/acutils.h +++ b/source/include/acutils.h @@ -706,10 +706,11 @@ AcpiUtShortDivide ( UINT64 *OutQuotient, UINT32 *OutRemainder); + /* * utmisc */ -const char * +const ACPI_EXCEPTION_INFO * AcpiUtValidateException ( ACPI_STATUS Status); diff --git a/source/tools/acpihelp/ahdecode.c b/source/tools/acpihelp/ahdecode.c index 74d42df1003..633b0db0a41 100644 --- a/source/tools/acpihelp/ahdecode.c +++ b/source/tools/acpihelp/ahdecode.c @@ -85,6 +85,9 @@ static const AH_DEVICE_ID AhDeviceIds[] = #define AH_DISPLAY_EXCEPTION(Status, Name) \ printf ("%.4X: %s\n", Status, Name) +#define AH_DISPLAY_EXCEPTION_TEXT(Status, Exception) \ + printf ("%.4X: %-28s (%s)\n", Status, Exception->Name, Exception->Description) + #define BUFFER_LENGTH 128 #define LINE_BUFFER_LENGTH 512 @@ -878,9 +881,9 @@ void AhDecodeException ( char *HexString) { - const char *ExceptionName; - UINT32 Status; - UINT32 i; + const ACPI_EXCEPTION_INFO *ExceptionInfo; + UINT32 Status; + UINT32 i; /* @@ -889,8 +892,8 @@ AhDecodeException ( */ if (!HexString) { - printf ("All defined ACPI exception codes:\n\n"); - AH_DISPLAY_EXCEPTION (0, "AE_OK"); + printf ("All defined ACPICA exception codes:\n\n"); + AH_DISPLAY_EXCEPTION (0, "AE_OK (No error occurred)"); /* Display codes in each block of exception types */ @@ -899,14 +902,14 @@ AhDecodeException ( Status = i; do { - ExceptionName = AcpiUtValidateException ((ACPI_STATUS) Status); - if (ExceptionName) + ExceptionInfo = AcpiUtValidateException ((ACPI_STATUS) Status); + if (ExceptionInfo) { - AH_DISPLAY_EXCEPTION (Status, ExceptionName); + AH_DISPLAY_EXCEPTION_TEXT (Status, ExceptionInfo); } Status++; - } while (ExceptionName); + } while (ExceptionInfo); } return; } @@ -916,7 +919,7 @@ AhDecodeException ( Status = ACPI_STRTOUL (HexString, NULL, 16); if (!Status) { - printf ("%s: Invalid hexadecimal exception code\n", HexString); + printf ("%s: Invalid hexadecimal exception code value\n", HexString); return; } @@ -926,12 +929,12 @@ AhDecodeException ( return; } - ExceptionName = AcpiUtValidateException ((ACPI_STATUS) Status); - if (!ExceptionName) + ExceptionInfo = AcpiUtValidateException ((ACPI_STATUS) Status); + if (!ExceptionInfo) { AH_DISPLAY_EXCEPTION (Status, "Unknown exception code"); return; } - AH_DISPLAY_EXCEPTION (Status, ExceptionName); + AH_DISPLAY_EXCEPTION_TEXT (Status, ExceptionInfo); } diff --git a/source/tools/acpisrc/astable.c b/source/tools/acpisrc/astable.c index e655818464f..1bd757534f0 100644 --- a/source/tools/acpisrc/astable.c +++ b/source/tools/acpisrc/astable.c @@ -215,6 +215,7 @@ ACPI_TYPED_IDENTIFIER_TABLE AcpiIdentifiers[] = { {"ACPI_EVENT_STATUS", SRC_TYPE_SIMPLE}, {"ACPI_EVENT_TYPE", SRC_TYPE_SIMPLE}, {"ACPI_EXCEPTION_HANDLER", SRC_TYPE_SIMPLE}, + {"ACPI_EXCEPTION_INFO", SRC_TYPE_STRUCT}, {"ACPI_EXDUMP_INFO", SRC_TYPE_STRUCT}, {"ACPI_EXECUTE_OP", SRC_TYPE_SIMPLE}, {"ACPI_EXECUTE_TYPE", SRC_TYPE_SIMPLE}, @@ -259,6 +260,7 @@ ACPI_TYPED_IDENTIFIER_TABLE AcpiIdentifiers[] = { {"ACPI_MEM_SPACE_CONTEXT", SRC_TYPE_STRUCT}, {"ACPI_MEMORY_ATTRIBUTE", SRC_TYPE_STRUCT}, {"ACPI_MEMORY_LIST", SRC_TYPE_STRUCT}, + {"ACPI_MTMR_ENTRY", SRC_TYPE_STRUCT}, {"ACPI_MUTEX", SRC_TYPE_SIMPLE}, {"ACPI_MUTEX_HANDLE", SRC_TYPE_SIMPLE}, {"ACPI_MUTEX_INFO", SRC_TYPE_STRUCT}, @@ -337,6 +339,9 @@ ACPI_TYPED_IDENTIFIER_TABLE AcpiIdentifiers[] = { {"ACPI_PREDEFINED_INFO", SRC_TYPE_UNION}, {"ACPI_PREDEFINED_NAMES", SRC_TYPE_STRUCT}, {"ACPI_PSCOPE_STATE", SRC_TYPE_STRUCT}, + {"ACPI_RASF_PARAMETER_BLOCK", SRC_TYPE_STRUCT}, + {"ACPI_RASF_PATROL_SCRUB_PARAMETER", SRC_TYPE_STRUCT}, + {"ACPI_RASF_SHARED_MEMORY", SRC_TYPE_STRUCT}, {"ACPI_REPAIR_FUNCTION", SRC_TYPE_SIMPLE}, {"ACPI_REPAIR_INFO", SRC_TYPE_STRUCT}, {"ACPI_RESOURCE", SRC_TYPE_STRUCT}, @@ -380,6 +385,7 @@ ACPI_TYPED_IDENTIFIER_TABLE AcpiIdentifiers[] = { {"ACPI_SCOPE_STATE", SRC_TYPE_STRUCT}, {"ACPI_SEMAPHORE", SRC_TYPE_SIMPLE}, {"ACPI_SIGNAL_FATAL_INFO", SRC_TYPE_STRUCT}, + {"ACPI_SIMPLE_REPAIR_INFO", SRC_TYPE_STRUCT}, {"ACPI_SIZE", SRC_TYPE_SIMPLE}, {"ACPI_SLEEP_FUNCTION", SRC_TYPE_SIMPLE}, {"ACPI_SLEEP_FUNCTIONS", SRC_TYPE_STRUCT}, @@ -395,8 +401,10 @@ ACPI_TYPED_IDENTIFIER_TABLE AcpiIdentifiers[] = { {"ACPI_TABLE_HEADER", SRC_TYPE_STRUCT}, {"ACPI_TABLE_INFO", SRC_TYPE_STRUCT}, {"ACPI_TABLE_LIST", SRC_TYPE_STRUCT}, + {"ACPI_TABLE_MTMR", SRC_TYPE_STRUCT}, {"ACPI_TABLE_SUPPORT", SRC_TYPE_STRUCT}, {"ACPI_TABLE_TYPE", SRC_TYPE_SIMPLE}, + {"ACPI_TABLE_VRTC", SRC_TYPE_STRUCT}, {"ACPI_TAG_INFO", SRC_TYPE_STRUCT}, {"ACPI_THREAD_ID", SRC_TYPE_SIMPLE}, {"ACPI_THREAD_STATE", SRC_TYPE_STRUCT}, @@ -406,6 +414,7 @@ ACPI_TYPED_IDENTIFIER_TABLE AcpiIdentifiers[] = { {"ACPI_UUID", SRC_TYPE_STRUCT}, {"ACPI_VENDOR_UUID", SRC_TYPE_STRUCT}, {"ACPI_VENDOR_WALK_INFO", SRC_TYPE_STRUCT}, + {"ACPI_VRTC_ENTRY", SRC_TYPE_STRUCT}, {"ACPI_WALK_AML_CALLBACK", SRC_TYPE_SIMPLE}, {"ACPI_WALK_CALLBACK", SRC_TYPE_SIMPLE}, {"ACPI_WALK_RESOURCE_CALLBACK", SRC_TYPE_SIMPLE}, From e589740522da1cd5c6bec2aa7ef72f29bcab1f92 Mon Sep 17 00:00:00 2001 From: Oleksandr Tymoshenko Date: Fri, 15 Feb 2013 21:24:21 +0000 Subject: [PATCH 0197/1476] Fix copy-paste error in bus_space_unmap argument While I'm at it - fix some style(9) issues Submitted by: Mikael Urankar --- sys/arm/ti/ti_cpuid.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/sys/arm/ti/ti_cpuid.c b/sys/arm/ti/ti_cpuid.c index 89046c43b3c..027dd6d0a3d 100644 --- a/sys/arm/ti/ti_cpuid.c +++ b/sys/arm/ti/ti_cpuid.c @@ -109,8 +109,7 @@ omap4_get_revision(void) * STD_FUSE_PROD_ID_0 0x4A00 2214 * STD_FUSE_PROD_ID_1 0x4A00 2218 */ - // id_code = REG_READ32(OMAP44XX_L4_CORE_VBASE + OMAP4_ID_CODE); - //FIXME Should we map somewhere else? + /* FIXME Should we map somewhere else? */ bus_space_map(fdtbus_bs_tag,OMAP44XX_L4_CORE_HWBASE, 0x4000, 0, &bsh); id_code = bus_space_read_4(fdtbus_bs_tag, bsh, OMAP4_ID_CODE); bus_space_unmap(fdtbus_bs_tag, bsh, 0x4000); @@ -228,10 +227,9 @@ omap3_get_revision(void) * * */ - //id_code = REG_READ32(OMAP35XX_L4_WAKEUP_VBASE + OMAP3_ID_CODE); - bus_space_map(fdtbus_bs_tag,OMAP35XX_L4_WAKEUP_HWBASE, 0x10000, 0, &bsh); + bus_space_map(fdtbus_bs_tag, OMAP35XX_L4_WAKEUP_HWBASE, 0x10000, 0, &bsh); id_code = bus_space_read_4(fdtbus_bs_tag, bsh, OMAP3_ID_CODE); - bus_space_unmap(fdtbus_bs_tag, bsh, 0x4000); + bus_space_unmap(fdtbus_bs_tag, bsh, 0x10000); hawkeye = ((id_code >> 12) & 0xffff); revision = ((id_code >> 28) & 0xf); From aaa54dd138331655f210c64674c357422cd82d14 Mon Sep 17 00:00:00 2001 From: Oleksandr Tymoshenko Date: Fri, 15 Feb 2013 21:29:03 +0000 Subject: [PATCH 0198/1476] Enable USB1 (which is EHCI0) for Allwinner A10 Tested by: ganbold@ --- sys/arm/allwinner/a10_clk.c | 1 + sys/arm/allwinner/a10_clk.h | 1 + sys/arm/allwinner/a10_ehci.c | 5 +++++ sys/boot/fdt/dts/cubieboard.dts | 9 ++++++++- 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/sys/arm/allwinner/a10_clk.c b/sys/arm/allwinner/a10_clk.c index 275ec4b85c1..64251fb44cd 100644 --- a/sys/arm/allwinner/a10_clk.c +++ b/sys/arm/allwinner/a10_clk.c @@ -129,6 +129,7 @@ a10_clk_usb_activate(void) /* Gating AHB clock for USB */ reg_value = ccm_read_4(sc, CCM_AHB_GATING0); reg_value |= CCM_AHB_GATING_USB0; /* AHB clock gate usb0 */ + reg_value |= CCM_AHB_GATING_EHCI0; /* AHB clock gate ehci1 */ reg_value |= CCM_AHB_GATING_EHCI1; /* AHB clock gate ehci1 */ ccm_write_4(sc, CCM_AHB_GATING0, reg_value); diff --git a/sys/arm/allwinner/a10_clk.h b/sys/arm/allwinner/a10_clk.h index 7316a221109..a2a6bc95e85 100644 --- a/sys/arm/allwinner/a10_clk.h +++ b/sys/arm/allwinner/a10_clk.h @@ -101,6 +101,7 @@ #define CCM_MALI400_CLK 0x0154 #define CCM_AHB_GATING_USB0 (1 << 0) +#define CCM_AHB_GATING_EHCI0 (1 << 1) #define CCM_AHB_GATING_EHCI1 (1 << 3) #define CCM_USB_PHY (1 << 8) diff --git a/sys/arm/allwinner/a10_ehci.c b/sys/arm/allwinner/a10_ehci.c index 0d1636b7bfa..4145a5c3a75 100644 --- a/sys/arm/allwinner/a10_ehci.c +++ b/sys/arm/allwinner/a10_ehci.c @@ -75,6 +75,7 @@ __FBSDID("$FreeBSD$"); #define SW_AHB_INCRX_ALIGN (1 << 8) #define SW_AHB_INCR4 (1 << 9) #define SW_AHB_INCR8 (1 << 10) +#define GPIO_USB1_PWR 230 #define GPIO_USB2_PWR 227 #define A10_READ_4(sc, reg) \ @@ -182,6 +183,10 @@ a10_ehci_attach(device_t self) GPIO_PIN_SETFLAGS(sc_gpio_dev, GPIO_USB2_PWR, GPIO_PIN_OUTPUT); GPIO_PIN_SET(sc_gpio_dev, GPIO_USB2_PWR, GPIO_PIN_HIGH); + /* Give power to USB */ + GPIO_PIN_SETFLAGS(sc_gpio_dev, GPIO_USB1_PWR, GPIO_PIN_OUTPUT); + GPIO_PIN_SET(sc_gpio_dev, GPIO_USB1_PWR, GPIO_PIN_HIGH); + /* Enable passby */ reg_value = A10_READ_4(sc, SW_USB_PMU_IRQ_ENABLE); reg_value |= SW_AHB_INCR8; /* AHB INCR8 enable */ diff --git a/sys/boot/fdt/dts/cubieboard.dts b/sys/boot/fdt/dts/cubieboard.dts index 1ef8b42fc01..abb3f454bea 100644 --- a/sys/boot/fdt/dts/cubieboard.dts +++ b/sys/boot/fdt/dts/cubieboard.dts @@ -91,7 +91,14 @@ interrupt-parent = <&AINTC>; }; - usb1: usb@01c1c000 { + usb1: usb@01c14000 { + compatible = "allwinner,usb-ehci", "usb-ehci"; + reg = <0x01c14000 0x1000>; + interrupts = < 39 >; + interrupt-parent = <&AINTC>; + }; + + usb2: usb@01c1c000 { compatible = "allwinner,usb-ehci", "usb-ehci"; reg = <0x01c1c000 0x1000>; interrupts = < 40 >; From 9c9425b781322acd2512333c1a30d32fb257a3b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Fri, 15 Feb 2013 21:31:01 +0000 Subject: [PATCH 0199/1476] fix leftover from an earlier experiment --- share/mk/bsd.libnames.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/mk/bsd.libnames.mk b/share/mk/bsd.libnames.mk index 82cb76d5941..d7421423d87 100644 --- a/share/mk/bsd.libnames.mk +++ b/share/mk/bsd.libnames.mk @@ -86,7 +86,7 @@ LIBKRB5?= ${DESTDIR}${LIBDIR}/libkrb5.a LIBKVM?= ${DESTDIR}${LIBDIR}/libkvm.a LIBL?= ${DESTDIR}${LIBDIR}/libl.a .if ${MK_LDNS} != "no" -LIBLDNS?= ${DESTDIR}${LIBDIR}/lib_ldns.a +LIBLDNS?= ${DESTDIR}${LIBDIR}/libldns.a .endif LIBLN?= "don't use LIBLN, use LIBL" .if ${MK_BIND} != "no" From 6709dfe57acb55966880c1027552f9d27e1e45cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Fri, 15 Feb 2013 21:33:05 +0000 Subject: [PATCH 0200/1476] Add generated files --- contrib/ldns/ldns/common.h | 68 +++++ contrib/ldns/ldns/config.h | 556 +++++++++++++++++++++++++++++++++++++ contrib/ldns/ldns/net.h | 208 ++++++++++++++ contrib/ldns/ldns/util.h | 367 ++++++++++++++++++++++++ 4 files changed, 1199 insertions(+) create mode 100644 contrib/ldns/ldns/common.h create mode 100644 contrib/ldns/ldns/config.h create mode 100644 contrib/ldns/ldns/net.h create mode 100644 contrib/ldns/ldns/util.h diff --git a/contrib/ldns/ldns/common.h b/contrib/ldns/ldns/common.h new file mode 100644 index 00000000000..4a32112d224 --- /dev/null +++ b/contrib/ldns/ldns/common.h @@ -0,0 +1,68 @@ +/** + * \file common.h + * + * Common definitions for LDNS + */ + +/** + * a Net::DNS like library for C + * + * (c) NLnet Labs, 2004-2006 + * + * See the file LICENSE for the license + */ + +#ifndef LDNS_COMMON_H +#define LDNS_COMMON_H + +/* + * The build configuration that is used in the distributed headers, + * as detected and determined by the auto configure script. + */ +#define LDNS_BUILD_CONFIG_HAVE_SSL 1 +#define LDNS_BUILD_CONFIG_HAVE_INTTYPES_H 1 +#define LDNS_BUILD_CONFIG_HAVE_ATTR_FORMAT 1 +#define LDNS_BUILD_CONFIG_HAVE_ATTR_UNUSED 1 + +/* + * HAVE_STDBOOL_H is not available when distributed as a library, but no build + * configuration variables may be used (like those above) because the header + * is sometimes only available when using special compiler flags to enable the + * c99 environment. Because we cannot force the usage of this flag, we have to + * provide a default type. Below what is suggested by the autoconf manual. + */ +/*@ignore@*/ +/* splint barfs on this construct */ +#ifdef HAVE_STDBOOL_H +# include +#else +# ifndef HAVE__BOOL +# ifdef __cplusplus +typedef bool _Bool; +# else +# define _Bool signed char +# endif +# endif +# define bool _Bool +# define false 0 +# define true 1 +# define __bool_true_false_are_defined 1 +#endif +/*@end@*/ + +#if LDNS_BUILD_CONFIG_HAVE_ATTR_FORMAT +#define ATTR_FORMAT(archetype, string_index, first_to_check) \ + __attribute__ ((format (archetype, string_index, first_to_check))) +#else /* !LDNS_BUILD_CONFIG_HAVE_ATTR_FORMAT */ +#define ATTR_FORMAT(archetype, string_index, first_to_check) /* empty */ +#endif /* !LDNS_BUILD_CONFIG_HAVE_ATTR_FORMAT */ + +#if defined(__cplusplus) +#define ATTR_UNUSED(x) +#elif LDNS_BUILD_CONFIG_HAVE_ATTR_UNUSED +#define ATTR_UNUSED(x) x __attribute__((unused)) +#else /* !LDNS_BUILD_CONFIG_HAVE_ATTR_UNUSED */ +#define ATTR_UNUSED(x) x +#endif /* !LDNS_BUILD_CONFIG_HAVE_ATTR_UNUSED */ + +#endif /* LDNS_COMMON_H */ diff --git a/contrib/ldns/ldns/config.h b/contrib/ldns/ldns/config.h new file mode 100644 index 00000000000..705e1df74d4 --- /dev/null +++ b/contrib/ldns/ldns/config.h @@ -0,0 +1,556 @@ +/* ldns/config.h. Generated from config.h.in by configure. */ +/* ldns/config.h.in. Generated from configure.ac by autoheader. */ + +/* Define if building universal (internal helper macro) */ +/* #undef AC_APPLE_UNIVERSAL_BUILD */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Whether the C compiler accepts the "format" attribute */ +#define HAVE_ATTR_FORMAT 1 + +/* Whether the C compiler accepts the "unused" attribute */ +#define HAVE_ATTR_UNUSED 1 + +/* Define to 1 if you have the `b32_ntop' function. */ +/* #undef HAVE_B32_NTOP */ + +/* Define to 1 if you have the `b32_pton' function. */ +/* #undef HAVE_B32_PTON */ + +/* Define to 1 if you have the `b64_ntop' function. */ +/* #undef HAVE_B64_NTOP */ + +/* Define to 1 if you have the `b64_pton' function. */ +/* #undef HAVE_B64_PTON */ + +/* Define to 1 if you have the `bzero' function. */ +#define HAVE_BZERO 1 + +/* Define to 1 if you have the `calloc' function. */ +#define HAVE_CALLOC 1 + +/* Define to 1 if you have the `ctime_r' function. */ +#define HAVE_CTIME_R 1 + +/* Define to 1 if you have the declaration of `NID_secp384r1', and to 0 if you + don't. */ +#define HAVE_DECL_NID_SECP384R1 1 + +/* Define to 1 if you have the declaration of `NID_X9_62_prime256v1', and to 0 + if you don't. */ +#define HAVE_DECL_NID_X9_62_PRIME256V1 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the `endprotoent' function. */ +#define HAVE_ENDPROTOENT 1 + +/* Define to 1 if you have the `endservent' function. */ +#define HAVE_ENDSERVENT 1 + +/* Define to 1 if you have the `EVP_sha256' function. */ +#define HAVE_EVP_SHA256 1 + +/* Define to 1 if you have the `fcntl' function. */ +#define HAVE_FCNTL 1 + +/* Define to 1 if you have the `fork' function. */ +#define HAVE_FORK 1 + +/* Whether getaddrinfo is available */ +#define HAVE_GETADDRINFO 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_GETOPT_H 1 + +/* Define to 1 if you have the `gmtime_r' function. */ +#define HAVE_GMTIME_R 1 + +/* If you have HMAC_CTX_init */ +#define HAVE_HMAC_CTX_INIT 1 + +/* Define to 1 if you have the `inet_aton' function. */ +#define HAVE_INET_ATON 1 + +/* Define to 1 if you have the `inet_ntop' function. */ +#define HAVE_INET_NTOP 1 + +/* Define to 1 if you have the `inet_pton' function. */ +#define HAVE_INET_PTON 1 + +/* Define to 1 if the system has the type `intptr_t'. */ +#define HAVE_INTPTR_T 1 + +/* define if you have inttypes.h */ +#define HAVE_INTTYPES_H 1 + +/* if the function 'ioctlsocket' is available */ +/* #undef HAVE_IOCTLSOCKET */ + +/* Define to 1 if you have the `isascii' function. */ +#define HAVE_ISASCII 1 + +/* Define to 1 if you have the `isblank' function. */ +#define HAVE_ISBLANK 1 + +/* Define to 1 if you have the `pcap' library (-lpcap). */ +/* #undef HAVE_LIBPCAP */ + +/* Define to 1 if you have the `localtime_r' function. */ +#define HAVE_LOCALTIME_R 1 + +/* Define to 1 if your system has a GNU libc compatible `malloc' function, and + to 0 otherwise. */ +#define HAVE_MALLOC 1 + +/* Define to 1 if you have the `memmove' function. */ +#define HAVE_MEMMOVE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `memset' function. */ +#define HAVE_MEMSET 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NETINET_IF_ETHER_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NETINET_IGMP_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NETINET_IN_SYSTM_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NETINET_IP6_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NETINET_IP_COMPAT_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NETINET_IP_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NETINET_UDP_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NET_ETHERNET_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NET_IF_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_ERR_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_RAND_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_SSL_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PCAP_H */ + +/* If available, contains the Python version number currently in use. */ +/* #undef HAVE_PYTHON */ + +/* Define to 1 if you have the `random' function. */ +#define HAVE_RANDOM 1 + +/* Define to 1 if your system has a GNU libc compatible `realloc' function, + and to 0 otherwise. */ +#define HAVE_REALLOC 1 + +/* Define to 1 if you have the `sleep' function. */ +#define HAVE_SLEEP 1 + +/* Define to 1 if you have the `snprintf' function. */ +#define HAVE_SNPRINTF 1 + +/* Define if you have the SSL libraries installed. */ +#define HAVE_SSL /**/ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDARG_H 1 + +/* Define to 1 if stdbool.h conforms to C99. */ +#define HAVE_STDBOOL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strlcpy' function. */ +#define HAVE_STRLCPY 1 + +/* Define to 1 if you have the `strtoul' function. */ +#define HAVE_STRTOUL 1 + +/* Define if you have SWIG libraries and header files. */ +/* #undef HAVE_SWIG */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_MOUNT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* define if you have sys/socket.h */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* define if you have sys/types.h */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the `timegm' function. */ +#define HAVE_TIMEGM 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TIME_H 1 + +/* define if you have unistd.h */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `vfork' function. */ +#define HAVE_VFORK 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_VFORK_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_WINSOCK2_H */ + +/* Define to 1 if `fork' works. */ +#define HAVE_WORKING_FORK 1 + +/* Define to 1 if `vfork' works. */ +#define HAVE_WORKING_VFORK 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_WS2TCPIP_H */ + +/* Define to 1 if the system has the type `_Bool'. */ +#define HAVE__BOOL 1 + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "libdns@nlnetlabs.nl" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "ldns" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "ldns 1.6.13" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "libdns" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.6.13" + +/* The size of `time_t', as computed by sizeof. */ +#define SIZEOF_TIME_T 8 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* System configuration dir */ +#define SYSCONFDIR sysconfdir + +/* Define this to enable ECDSA support. */ +#define USE_ECDSA 1 + +/* Define this to enable GOST support. */ +#define USE_GOST 1 + +/* Define this to enable SHA256 and SHA512 support. */ +#define USE_SHA2 1 + +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# define _ALL_SOURCE 1 +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# define _POSIX_PTHREAD_SEMANTICS 1 +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# define _TANDEM_SOURCE 1 +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# define __EXTENSIONS__ 1 +#endif + + +/* Whether the windows socket API is used */ +/* #undef USE_WINSOCK */ + +/* the version of the windows API enabled */ +#define WINVER 0x0502 + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif + +/* Define to 1 if on MINIX. */ +/* #undef _MINIX */ + +/* Define to 2 if the system does not provide POSIX.1 features except with + this defined. */ +/* #undef _POSIX_1_SOURCE */ + +/* Define to 1 if you need to in order for `stat' and other things to work. */ +/* #undef _POSIX_SOURCE */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* in_addr_t */ +/* #undef in_addr_t */ + +/* in_port_t */ +/* #undef in_port_t */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to `short' if does not define. */ +/* #undef int16_t */ + +/* Define to `int' if does not define. */ +/* #undef int32_t */ + +/* Define to `long long' if does not define. */ +/* #undef int64_t */ + +/* Define to `char' if does not define. */ +/* #undef int8_t */ + +/* Define to the type of a signed integer type wide enough to hold a pointer, + if such a type exists, and if the system does not define it. */ +/* #undef intptr_t */ + +/* Define to rpl_malloc if the replacement function should be used. */ +/* #undef malloc */ + +/* Define to `int' if does not define. */ +/* #undef pid_t */ + +/* Define to rpl_realloc if the replacement function should be used. */ +/* #undef realloc */ + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ + +/* Define to 'int' if not defined */ +/* #undef socklen_t */ + +/* Fallback member name for socket family in struct sockaddr_storage */ +/* #undef ss_family */ + +/* Define to `int' if does not define. */ +/* #undef ssize_t */ + +/* Define to `unsigned short' if does not define. */ +/* #undef uint16_t */ + +/* Define to `unsigned int' if does not define. */ +/* #undef uint32_t */ + +/* Define to `unsigned long long' if does not define. */ +/* #undef uint64_t */ + +/* Define to `unsigned char' if does not define. */ +/* #undef uint8_t */ + +/* Define as `fork' if `vfork' does not work. */ +/* #undef vfork */ + + +#include +#include +#include +#include + +#ifndef LITTLE_ENDIAN +#define LITTLE_ENDIAN 1234 +#endif + +#ifndef BIG_ENDIAN +#define BIG_ENDIAN 4321 +#endif + +#ifndef BYTE_ORDER +#ifdef WORDS_BIGENDIAN +#define BYTE_ORDER BIG_ENDIAN +#else +#define BYTE_ORDER LITTLE_ENDIAN +#endif /* WORDS_BIGENDIAN */ +#endif /* BYTE_ORDER */ + +#if STDC_HEADERS +#include +#include +#endif + +#ifdef HAVE_STDINT_H +#include +#endif + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#ifdef HAVE_WINSOCK2_H +#include +#endif + +#ifdef HAVE_WS2TCPIP_H +#include +#endif + + +/* detect if we need to cast to unsigned int for FD_SET to avoid warnings */ +#ifdef HAVE_WINSOCK2_H +#define FD_SET_T (u_int) +#else +#define FD_SET_T +#endif + + + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef B64_PTON +int ldns_b64_ntop(uint8_t const *src, size_t srclength, + char *target, size_t targsize); +/** + * calculates the size needed to store the result of b64_ntop + */ +/*@unused@*/ +static inline size_t ldns_b64_ntop_calculate_size(size_t srcsize) +{ + return ((((srcsize + 2) / 3) * 4) + 1); +} +#endif /* !B64_PTON */ +#ifndef B64_NTOP +int ldns_b64_pton(char const *src, uint8_t *target, size_t targsize); +/** + * calculates the size needed to store the result of ldns_b64_pton + */ +/*@unused@*/ +static inline size_t ldns_b64_pton_calculate_size(size_t srcsize) +{ + return (((((srcsize + 3) / 4) * 3)) + 1); +} +#endif /* !B64_NTOP */ + +#ifndef HAVE_SLEEP +/* use windows sleep, in millisecs, instead */ +#define sleep(x) Sleep((x)*1000) +#endif + +#ifndef HAVE_RANDOM +#define srandom(x) srand(x) +#define random(x) rand(x) +#endif + +#ifndef HAVE_TIMEGM +#include +time_t timegm (struct tm *tm); +#endif /* !TIMEGM */ +#ifndef HAVE_GMTIME_R +struct tm *gmtime_r(const time_t *timep, struct tm *result); +#endif +#ifndef HAVE_LOCALTIME_R +struct tm *localtime_r(const time_t *timep, struct tm *result); +#endif +#ifndef HAVE_ISBLANK +int isblank(int c); +#endif /* !HAVE_ISBLANK */ +#ifndef HAVE_ISASCII +int isascii(int c); +#endif /* !HAVE_ISASCII */ +#ifndef HAVE_SNPRINTF +#include +int snprintf (char *str, size_t count, const char *fmt, ...); +int vsnprintf (char *str, size_t count, const char *fmt, va_list arg); +#endif /* HAVE_SNPRINTF */ +#ifndef HAVE_INET_PTON +int inet_pton(int af, const char* src, void* dst); +#endif /* HAVE_INET_PTON */ +#ifndef HAVE_INET_NTOP +const char *inet_ntop(int af, const void *src, char *dst, size_t size); +#endif +#ifndef HAVE_INET_ATON +int inet_aton(const char *cp, struct in_addr *addr); +#endif +#ifndef HAVE_MEMMOVE +void *memmove(void *dest, const void *src, size_t n); +#endif +#ifndef HAVE_STRLCPY +size_t strlcpy(char *dst, const char *src, size_t siz); +#endif +#ifdef __cplusplus +} +#endif +#ifndef HAVE_GETADDRINFO +#include "compat/fake-rfc2553.h" +#endif +#ifndef HAVE_STRTOUL +#define strtoul (unsigned long)strtol +#endif + diff --git a/contrib/ldns/ldns/net.h b/contrib/ldns/ldns/net.h new file mode 100644 index 00000000000..cd7bc4beb75 --- /dev/null +++ b/contrib/ldns/ldns/net.h @@ -0,0 +1,208 @@ +/* + * net.h + * + * DNS Resolver definitions + * + * a Net::DNS like library for C + * + * (c) NLnet Labs, 2005-2006 + * + * See the file LICENSE for the license + */ + +#ifndef LDNS_NET_H +#define LDNS_NET_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define LDNS_DEFAULT_TIMEOUT_SEC 5 +#define LDNS_DEFAULT_TIMEOUT_USEC 0 + +/** + * \file + * + * Contains functions to send and receive packets over a network. + */ + +/** + * Sends a buffer to an ip using udp and return the respons as a ldns_pkt + * \param[in] qbin the ldns_buffer to be send + * \param[in] to the ip addr to send to + * \param[in] tolen length of the ip addr + * \param[in] timeout the timeout value for the network + * \param[out] answersize size of the packet + * \param[out] result packet with the answer + * \return status + */ +ldns_status ldns_udp_send(uint8_t **result, ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout, size_t *answersize); + +/** + * Send an udp query and don't wait for an answer but return + * the socket + * \param[in] qbin the ldns_buffer to be send + * \param[in] to the ip addr to send to + * \param[in] tolen length of the ip addr + * \param[in] timeout *unused*, was the timeout value for the network + * \return the socket used + */ + +int ldns_udp_bgsend(ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout); + +/** + * Send an tcp query and don't wait for an answer but return + * the socket + * \param[in] qbin the ldns_buffer to be send + * \param[in] to the ip addr to send to + * \param[in] tolen length of the ip addr + * \param[in] timeout the timeout value for the connect attempt + * \return the socket used + */ +int ldns_tcp_bgsend(ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout); + +/** + * Sends a buffer to an ip using tcp and return the respons as a ldns_pkt + * \param[in] qbin the ldns_buffer to be send + * \param[in] qbin the ldns_buffer to be send + * \param[in] to the ip addr to send to + * \param[in] tolen length of the ip addr + * \param[in] timeout the timeout value for the network + * \param[out] answersize size of the packet + * \param[out] result packet with the answer + * \return status + */ +ldns_status ldns_tcp_send(uint8_t **result, ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout, size_t *answersize); + +/** + * Sends ptk to the nameserver at the resolver object. Returns the data + * as a ldns_pkt + * + * \param[out] pkt packet received from the nameserver + * \param[in] r the resolver to use + * \param[in] query_pkt the query to send + * \return status + */ +ldns_status ldns_send(ldns_pkt **pkt, ldns_resolver *r, const ldns_pkt *query_pkt); + +/** + * Sends and ldns_buffer (presumably containing a packet to the nameserver at the resolver object. Returns the data + * as a ldns_pkt + * + * \param[out] pkt packet received from the nameserver + * \param[in] r the resolver to use + * \param[in] qb the buffer to send + * \param[in] tsig_mac the tsig MAC to authenticate the response with (NULL to do no TSIG authentication) + * \return status + */ +ldns_status ldns_send_buffer(ldns_pkt **pkt, ldns_resolver *r, ldns_buffer *qb, ldns_rdf *tsig_mac); + +/** + * Create a tcp socket to the specified address + * \param[in] to ip and family + * \param[in] tolen length of to + * \param[in] timeout timeout for the connect attempt + * \return a socket descriptor + */ +int ldns_tcp_connect(const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout); + +/** + * Create a udp socket to the specified address + * \param[in] to ip and family + * \param[in] timeout *unused*, was timeout for the socket + * \return a socket descriptor + */ +int ldns_udp_connect(const struct sockaddr_storage *to, struct timeval timeout); + +/** + * send a query via tcp to a server. Don't want for the answer + * + * \param[in] qbin the buffer to send + * \param[in] sockfd the socket to use + * \param[in] to which ip to send it + * \param[in] tolen socketlen + * \return number of bytes sent + */ +ssize_t ldns_tcp_send_query(ldns_buffer *qbin, int sockfd, const struct sockaddr_storage *to, socklen_t tolen); + +/** + * send a query via udp to a server. Don;t want for the answer + * + * \param[in] qbin the buffer to send + * \param[in] sockfd the socket to use + * \param[in] to which ip to send it + * \param[in] tolen socketlen + * \return number of bytes sent + */ +ssize_t ldns_udp_send_query(ldns_buffer *qbin, int sockfd, const struct sockaddr_storage *to, socklen_t tolen); + +/** + * Gives back a raw packet from the wire and reads the header data from the given + * socket. Allocates the data (of size size) itself, so don't forget to free + * + * \param[in] sockfd the socket to read from + * \param[out] size the number of bytes that are read + * \param[in] timeout the time allowed between packets. + * \return the data read + */ +uint8_t *ldns_tcp_read_wire_timeout(int sockfd, size_t *size, struct timeval timeout); + +/** + * This routine may block. Use ldns_tcp_read_wire_timeout, it checks timeouts. + * Gives back a raw packet from the wire and reads the header data from the given + * socket. Allocates the data (of size size) itself, so don't forget to free + * + * \param[in] sockfd the socket to read from + * \param[out] size the number of bytes that are read + * \return the data read + */ +uint8_t *ldns_tcp_read_wire(int sockfd, size_t *size); + +/** + * Gives back a raw packet from the wire and reads the header data from the given + * socket. Allocates the data (of size size) itself, so don't forget to free + * + * \param[in] sockfd the socket to read from + * \param[in] fr the address of the client (if applicable) + * \param[in] *frlen the lenght of the client's addr (if applicable) + * \param[out] size the number of bytes that are read + * \return the data read + */ +uint8_t *ldns_udp_read_wire(int sockfd, size_t *size, struct sockaddr_storage *fr, socklen_t *frlen); + +/** + * returns the native sockaddr representation from the rdf. + * \param[in] rd the ldns_rdf to operate on + * \param[in] port what port to use. 0 means; use default (53) + * \param[out] size what is the size of the sockaddr_storage + * \return struct sockaddr* the address in the format so other + * functions can use it (sendto) + */ +struct sockaddr_storage * ldns_rdf2native_sockaddr_storage(const ldns_rdf *rd, uint16_t port, size_t *size); + +/** + * returns an rdf with the sockaddr info. works for ip4 and ip6 + * \param[in] sock the struct sockaddr_storage to convert + * \param[in] port what port was used. When NULL this is not set + * \return ldns_rdf* wth the address + */ +ldns_rdf * ldns_sockaddr_storage2rdf(struct sockaddr_storage *sock, uint16_t *port); + +/** + * Prepares the resolver for an axfr query + * The query is sent and the answers can be read with ldns_axfr_next + * \param[in] resolver the resolver to use + * \param[in] domain the domain to exfr + * \param[in] c the class to use + * \return ldns_status the status of the transfer + */ +ldns_status ldns_axfr_start(ldns_resolver *resolver, ldns_rdf *domain, ldns_rr_class c); + +#ifdef __cplusplus +} +#endif + +#endif /* LDNS_NET_H */ diff --git a/contrib/ldns/ldns/util.h b/contrib/ldns/ldns/util.h new file mode 100644 index 00000000000..82dd83277b5 --- /dev/null +++ b/contrib/ldns/ldns/util.h @@ -0,0 +1,367 @@ +/* + * util.h + * + * helper function header file + * + * a Net::DNS like library for C + * + * (c) NLnet Labs, 2004 + * + * See the file LICENSE for the license + */ + +#ifndef _UTIL_H +#define _UTIL_H + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define dprintf(X,Y) fprintf(stderr, (X), (Y)) +/* #define dprintf(X, Y) */ + +#define LDNS_VERSION "1.6.13" +#define LDNS_REVISION ((1<<16)|(6<<8)|(13)) + +/** + * splint static inline workaround + */ +#ifdef S_SPLINT_S +# define INLINE +#else +# ifdef SWIG +# define INLINE static +# else +# define INLINE static inline +# endif +#endif + +/** + * Memory management macros + */ +#define LDNS_MALLOC(type) LDNS_XMALLOC(type, 1) + +#define LDNS_XMALLOC(type, count) ((type *) malloc((count) * sizeof(type))) + +#define LDNS_CALLOC(type, count) ((type *) calloc((count), sizeof(type))) + +#define LDNS_REALLOC(ptr, type) LDNS_XREALLOC((ptr), type, 1) + +#define LDNS_XREALLOC(ptr, type, count) \ + ((type *) realloc((ptr), (count) * sizeof(type))) + +#define LDNS_FREE(ptr) \ + do { free((ptr)); (ptr) = NULL; } while (0) + +#define LDNS_DEP printf("DEPRECATED FUNCTION!\n"); + +/* + * Copy data allowing for unaligned accesses in network byte order + * (big endian). + */ +INLINE uint16_t +ldns_read_uint16(const void *src) +{ +#ifdef ALLOW_UNALIGNED_ACCESSES + return ntohs(*(uint16_t *) src); +#else + uint8_t *p = (uint8_t *) src; + return ((uint16_t) p[0] << 8) | (uint16_t) p[1]; +#endif +} + +INLINE uint32_t +ldns_read_uint32(const void *src) +{ +#ifdef ALLOW_UNALIGNED_ACCESSES + return ntohl(*(uint32_t *) src); +#else + uint8_t *p = (uint8_t *) src; + return ( ((uint32_t) p[0] << 24) + | ((uint32_t) p[1] << 16) + | ((uint32_t) p[2] << 8) + | (uint32_t) p[3]); +#endif +} + +/* + * Copy data allowing for unaligned accesses in network byte order + * (big endian). + */ +INLINE void +ldns_write_uint16(void *dst, uint16_t data) +{ +#ifdef ALLOW_UNALIGNED_ACCESSES + * (uint16_t *) dst = htons(data); +#else + uint8_t *p = (uint8_t *) dst; + p[0] = (uint8_t) ((data >> 8) & 0xff); + p[1] = (uint8_t) (data & 0xff); +#endif +} + +INLINE void +ldns_write_uint32(void *dst, uint32_t data) +{ +#ifdef ALLOW_UNALIGNED_ACCESSES + * (uint32_t *) dst = htonl(data); +#else + uint8_t *p = (uint8_t *) dst; + p[0] = (uint8_t) ((data >> 24) & 0xff); + p[1] = (uint8_t) ((data >> 16) & 0xff); + p[2] = (uint8_t) ((data >> 8) & 0xff); + p[3] = (uint8_t) (data & 0xff); +#endif +} + +/* warning. */ +INLINE void +ldns_write_uint64_as_uint48(void *dst, uint64_t data) +{ + uint8_t *p = (uint8_t *) dst; + p[0] = (uint8_t) ((data >> 40) & 0xff); + p[1] = (uint8_t) ((data >> 32) & 0xff); + p[2] = (uint8_t) ((data >> 24) & 0xff); + p[3] = (uint8_t) ((data >> 16) & 0xff); + p[4] = (uint8_t) ((data >> 8) & 0xff); + p[5] = (uint8_t) (data & 0xff); +} + + +/** + * Structure to do a Schwartzian-like transformation, for instance when + * sorting. If you need a transformation on the objects that are sorted, + * you can sue this to store the transformed values, so you do not + * need to do the transformation again for each comparison + */ +struct ldns_schwartzian_compare_struct { + void *original_object; + void *transformed_object; +}; + +/** A general purpose lookup table + * + * Lookup tables are arrays of (id, name) pairs, + * So you can for instance lookup the RCODE 3, which is "NXDOMAIN", + * and vice versa. The lookup tables themselves are defined wherever needed, + * for instance in \ref host2str.c + */ +struct ldns_struct_lookup_table { + int id; + const char *name; +}; +typedef struct ldns_struct_lookup_table ldns_lookup_table; + +/** + * Looks up the table entry by name, returns NULL if not found. + * \param[in] table the lookup table to search in + * \param[in] name what to search for + * \return the item found + */ +ldns_lookup_table *ldns_lookup_by_name(ldns_lookup_table table[], + const char *name); + +/** + * Looks up the table entry by id, returns NULL if not found. + * \param[in] table the lookup table to search in + * \param[in] id what to search for + * \return the item found + */ +ldns_lookup_table *ldns_lookup_by_id(ldns_lookup_table table[], int id); + +/** + * Returns the value of the specified bit + * The bits are counted from left to right, so bit #0 is the + * left most bit. + * \param[in] bits array holding the bits + * \param[in] index to the wanted bit + * \return + */ +int ldns_get_bit(uint8_t bits[], size_t index); + + +/** + * Returns the value of the specified bit + * The bits are counted from right to left, so bit #0 is the + * right most bit. + * \param[in] bits array holding the bits + * \param[in] index to the wanted bit + * \return 1 or 0 depending no the bit state + */ +int ldns_get_bit_r(uint8_t bits[], size_t index); + +/** + * sets the specified bit in the specified byte to + * 1 if value is true, 0 if false + * The bits are counted from right to left, so bit #0 is the + * right most bit. + * \param[in] byte the bit to set the bit in + * \param[in] bit_nr the bit to set (0 <= n <= 7) + * \param[in] value whether to set the bit to 1 or 0 + * \return 1 or 0 depending no the bit state + */ +void ldns_set_bit(uint8_t *byte, int bit_nr, bool value); + +/** + * Returns the value of a to the power of b + * (or 1 of b < 1) + */ +/*@unused@*/ +INLINE long +ldns_power(long a, long b) { + long result = 1; + while (b > 0) { + if (b & 1) { + result *= a; + if (b == 1) { + return result; + } + } + a *= a; + b /= 2; + } + return result; +} + +/** + * Returns the int value of the given (hex) digit + * \param[in] ch the hex char to convert + * \return the converted decimal value + */ +int ldns_hexdigit_to_int(char ch); + +/** + * Returns the char (hex) representation of the given int + * \param[in] ch the int to convert + * \return the converted hex char + */ +char ldns_int_to_hexdigit(int ch); + +/** + * Converts a hex string to binary data + * + * \param[out] data The binary result is placed here. + * At least strlen(str)/2 bytes should be allocated + * \param[in] str The hex string to convert. + * This string should not contain spaces + * \return The number of bytes of converted data, or -1 if one of the arguments * is NULL, or -2 if the string length is not an even number + */ +int +ldns_hexstring_to_data(uint8_t *data, const char *str); + +/** + * Show the internal library version + * \return a string with the version in it + */ +const char * ldns_version(void); + +/** + * Convert TM to seconds since epoch (midnight, January 1st, 1970). + * Like timegm(3), which is not always available. + * \param[in] tm a struct tm* with the date + * \return the seconds since epoch + */ +time_t mktime_from_utc(const struct tm *tm); + +/** + * The function interprets time as the number of seconds since epoch + * with respect to now using serial arithmitics (rfc1982). + * That number of seconds is then converted to broken-out time information. + * This is especially usefull when converting the inception and expiration + * fields of RRSIG records. + * + * \param[in] time number of seconds since epoch (midnight, January 1st, 1970) + * to be intepreted as a serial arithmitics number relative to now. + * \param[in] now number of seconds since epoch (midnight, January 1st, 1970) + * to which the time value is compared to determine the final value. + * \param[out] result the struct with the broken-out time information + * \return result on success or NULL on error + */ +struct tm * ldns_serial_arithmitics_gmtime_r(int32_t time, time_t now, struct tm *result); + +/** + * Seed the random function. + * If the file descriptor is specified, the random generator is seeded with + * data from that file. If not, /dev/urandom is used. + * + * applications should call this if they need entropy data within ldns + * If openSSL is available, it is automatically seeded from /dev/urandom + * or /dev/random. + * + * If you need more entropy, or have no openssl available, this function + * MUST be called at the start of the program + * + * If openssl *is* available, this function just adds more entropy + * + * \param[in] fd a file providing entropy data for the seed + * \param[in] size the number of bytes to use as entropy data. If this is 0, + * only the minimal amount is taken (usually 4 bytes) + * \return 0 if seeding succeeds, 1 if it fails + */ +int ldns_init_random(FILE *fd, unsigned int size); + +/** + * Get random number. + * \return random number. + * + */ +uint16_t ldns_get_random(void); + +/** + * Encode data as BubbleBabble + * + * \param[in] data a pointer to data to be encoded + * \param[in] len size the number of bytes of data + * \return a string of BubbleBabble + */ +char *ldns_bubblebabble(uint8_t *data, size_t len); + +#ifndef B32_NTOP +int ldns_b32_ntop(uint8_t const *src, size_t srclength, + char *target, size_t targsize); +int b32_ntop(uint8_t const *src, size_t srclength, + char *target, size_t targsize); +int ldns_b32_ntop_extended_hex(uint8_t const *src, size_t srclength, + char *target, size_t targsize); +int b32_ntop_extended_hex(uint8_t const *src, size_t srclength, + char *target, size_t targsize); +/** + * calculates the size needed to store the result of b32_ntop + */ +/*@unused@*/ +INLINE size_t ldns_b32_ntop_calculate_size(size_t srcsize) +{ + size_t result = ((((srcsize / 5) * 8) - 2) + 2); + return result; +} +#endif /* !B32_NTOP */ +#ifndef B32_PTON +int ldns_b32_pton(char const *src, size_t hashed_owner_str_len, uint8_t *target, size_t targsize); +int b32_pton(char const *src, size_t hashed_owner_str_len, uint8_t *target, size_t targsize); +int ldns_b32_pton_extended_hex(char const *src, size_t hashed_owner_str_len, uint8_t *target, size_t targsize); +int b32_pton_extended_hex(char const *src, size_t hashed_owner_str_len, uint8_t *target, size_t targsize); +/** + * calculates the size needed to store the result of b32_pton + */ +/*@unused@*/ +INLINE size_t ldns_b32_pton_calculate_size(size_t srcsize) +{ + size_t result = ((((srcsize) / 8) * 5)); + return result; +} +#endif /* !B32_PTON */ + +INLINE time_t ldns_time(time_t *t) { return time(t); } + +#ifdef __cplusplus +} +#endif + +#endif /* !_UTIL_H */ From 00a54dfb1c66cbf101a9b3d5f9c00b4a4e4251ee Mon Sep 17 00:00:00 2001 From: Jung-uk Kim Date: Fri, 15 Feb 2013 22:43:08 +0000 Subject: [PATCH 0201/1476] Consistently use round_page(x) rather than roundup(x, PAGE_SIZE). There is no functional change. --- sys/amd64/acpica/acpi_machdep.c | 4 ++-- sys/amd64/amd64/pmap.c | 6 +++--- sys/i386/acpica/acpi_machdep.c | 4 ++-- sys/i386/i386/pmap.c | 6 +++--- sys/i386/xen/pmap.c | 6 +++--- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/sys/amd64/acpica/acpi_machdep.c b/sys/amd64/acpica/acpi_machdep.c index f57bdc20968..e5dd4c306d1 100644 --- a/sys/amd64/acpica/acpi_machdep.c +++ b/sys/amd64/acpica/acpi_machdep.c @@ -122,7 +122,7 @@ table_map(vm_paddr_t pa, int offset, vm_offset_t length) void *data; off = pa & PAGE_MASK; - length = roundup(length + off, PAGE_SIZE); + length = round_page(length + off); pa = pa & PG_FRAME; va = (vm_offset_t)pmap_kenter_temporary(pa, offset) + (offset * PAGE_SIZE); @@ -146,7 +146,7 @@ table_unmap(void *data, vm_offset_t length) va = (vm_offset_t)data; off = va & PAGE_MASK; - length = roundup(length + off, PAGE_SIZE); + length = round_page(length + off); va &= ~PAGE_MASK; while (length > 0) { pmap_kremove(va); diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c index f30a071d630..c6c62ae8636 100644 --- a/sys/amd64/amd64/pmap.c +++ b/sys/amd64/amd64/pmap.c @@ -5015,7 +5015,7 @@ pmap_mapdev_attr(vm_paddr_t pa, vm_size_t size, int mode) return ((void *)va); } offset = pa & PAGE_MASK; - size = roundup(offset + size, PAGE_SIZE); + size = round_page(offset + size); va = kmem_alloc_nofault(kernel_map, size); if (!va) panic("pmap_mapdev: Couldn't alloc kernel virtual memory"); @@ -5051,7 +5051,7 @@ pmap_unmapdev(vm_offset_t va, vm_size_t size) return; base = trunc_page(va); offset = va & PAGE_MASK; - size = roundup(offset + size, PAGE_SIZE); + size = round_page(offset + size); kmem_free(kernel_map, base, size); } @@ -5173,7 +5173,7 @@ pmap_change_attr_locked(vm_offset_t va, vm_size_t size, int mode) PMAP_LOCK_ASSERT(kernel_pmap, MA_OWNED); base = trunc_page(va); offset = va & PAGE_MASK; - size = roundup(offset + size, PAGE_SIZE); + size = round_page(offset + size); /* * Only supported on kernel virtual addresses, including the direct diff --git a/sys/i386/acpica/acpi_machdep.c b/sys/i386/acpica/acpi_machdep.c index 08721279b6c..a244e7377c9 100644 --- a/sys/i386/acpica/acpi_machdep.c +++ b/sys/i386/acpica/acpi_machdep.c @@ -139,7 +139,7 @@ table_map(vm_paddr_t pa, int offset, vm_offset_t length) void *data; off = pa & PAGE_MASK; - length = roundup(length + off, PAGE_SIZE); + length = round_page(length + off); pa = pa & PG_FRAME; va = (vm_offset_t)pmap_kenter_temporary(pa, offset) + (offset * PAGE_SIZE); @@ -163,7 +163,7 @@ table_unmap(void *data, vm_offset_t length) va = (vm_offset_t)data; off = va & PAGE_MASK; - length = roundup(length + off, PAGE_SIZE); + length = round_page(length + off); va &= ~PAGE_MASK; while (length > 0) { pmap_kremove(va); diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c index a9d031d9096..5fee565962c 100644 --- a/sys/i386/i386/pmap.c +++ b/sys/i386/i386/pmap.c @@ -4989,7 +4989,7 @@ pmap_mapdev_attr(vm_paddr_t pa, vm_size_t size, int mode) vm_size_t tmpsize; offset = pa & PAGE_MASK; - size = roundup(offset + size, PAGE_SIZE); + size = round_page(offset + size); pa = pa & PG_FRAME; if (pa < KERNLOAD && pa + size <= KERNLOAD) @@ -5029,7 +5029,7 @@ pmap_unmapdev(vm_offset_t va, vm_size_t size) return; base = trunc_page(va); offset = va & PAGE_MASK; - size = roundup(offset + size, PAGE_SIZE); + size = round_page(offset + size); kmem_free(kernel_map, base, size); } @@ -5120,7 +5120,7 @@ pmap_change_attr(vm_offset_t va, vm_size_t size, int mode) base = trunc_page(va); offset = va & PAGE_MASK; - size = roundup(offset + size, PAGE_SIZE); + size = round_page(offset + size); /* * Only supported on kernel virtual addresses above the recursive map. diff --git a/sys/i386/xen/pmap.c b/sys/i386/xen/pmap.c index 7f65a218958..a8f11a46d13 100644 --- a/sys/i386/xen/pmap.c +++ b/sys/i386/xen/pmap.c @@ -3973,7 +3973,7 @@ pmap_mapdev_attr(vm_paddr_t pa, vm_size_t size, int mode) vm_size_t tmpsize; offset = pa & PAGE_MASK; - size = roundup(offset + size, PAGE_SIZE); + size = round_page(offset + size); pa = pa & PG_FRAME; if (pa < KERNLOAD && pa + size <= KERNLOAD) @@ -4013,7 +4013,7 @@ pmap_unmapdev(vm_offset_t va, vm_size_t size) return; base = trunc_page(va); offset = va & PAGE_MASK; - size = roundup(offset + size, PAGE_SIZE); + size = round_page(offset + size); kmem_free(kernel_map, base, size); } @@ -4105,7 +4105,7 @@ pmap_change_attr(vm_offset_t va, vm_size_t size, int mode) base = trunc_page(va); offset = va & PAGE_MASK; - size = roundup(offset + size, PAGE_SIZE); + size = round_page(offset + size); /* Only supported on kernel virtual addresses. */ if (base <= VM_MAXUSER_ADDRESS) From 835ef82e3bfe54806527fc38875d925580b300be Mon Sep 17 00:00:00 2001 From: Jung-uk Kim Date: Fri, 15 Feb 2013 22:58:44 +0000 Subject: [PATCH 0202/1476] Revert r227528 and r227787. This hack is no longer necessary since r233580. --- etc/rc.resume | 4 ---- 1 file changed, 4 deletions(-) diff --git a/etc/rc.resume b/etc/rc.resume index b68f9819f64..4d171901be8 100755 --- a/etc/rc.resume +++ b/etc/rc.resume @@ -43,10 +43,6 @@ if [ -r /var/run/rc.suspend.pid ]; then echo 'rc.resume: killed rc.suspend that was still around' fi -if [ -r /var/run/moused.pid ]; then - pkill -HUP -F /var/run/moused.pid -fi - # Turns on a power supply of a card in the slot inactivated. # See also contrib/pccardq.c (only for PAO users). # pccardq | awk -F '~' '$5 == "inactive" \ From cc636314f023958f9bf8d7d933835c7903cea77f Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Fri, 15 Feb 2013 23:12:35 +0000 Subject: [PATCH 0203/1476] Regenerate libstdc++'s config.h, synchronizing it with our current almost-C99 headers. MFC after: 1 week --- gnu/lib/libstdc++/config.h | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/gnu/lib/libstdc++/config.h b/gnu/lib/libstdc++/config.h index 7955ab62a60..33514198101 100644 --- a/gnu/lib/libstdc++/config.h +++ b/gnu/lib/libstdc++/config.h @@ -22,7 +22,7 @@ #define HAVE_ATAN2F 1 /* Define to 1 if you have the `atan2l' function. */ -/* #undef HAVE_ATAN2L */ +#define HAVE_ATAN2L 1 /* Define to 1 if you have the `atanf' function. */ #define HAVE_ATANF 1 @@ -67,7 +67,7 @@ #define HAVE_EXPF 1 /* Define to 1 if you have the `expl' function. */ -/* #undef HAVE_EXPL */ +#define HAVE_EXPL 1 /* Define to 1 if you have the `fabsf' function. */ #define HAVE_FABSF 1 @@ -100,7 +100,7 @@ #define HAVE_FMODF 1 /* Define to 1 if you have the `fmodl' function. */ -/* #undef HAVE_FMODL */ +#define HAVE_FMODL 1 /* Define to 1 if you have the `fpclass' function. */ /* #undef HAVE_FPCLASS */ @@ -134,7 +134,7 @@ #define HAVE_HYPOTF 1 /* Define to 1 if you have the `hypotl' function. */ -/* #undef HAVE_HYPOTL */ +#define HAVE_HYPOTL 1 /* Define to 1 if you have the `iconv' function. */ /* #undef HAVE_ICONV */ @@ -293,7 +293,7 @@ #define HAVE_SQRTF 1 /* Define to 1 if you have the `sqrtl' function. */ -/* #undef HAVE_SQRTL */ +#define HAVE_SQRTL 1 /* Define to 1 if you have the header file. */ #define HAVE_STDBOOL_H 1 @@ -304,6 +304,12 @@ /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 +/* Define if strerror_l is available in . */ +/* #undef HAVE_STRERROR_L */ + +/* Define if strerror_r is available in . */ +#define HAVE_STRERROR_R 1 + /* Define to 1 if you have the header file. */ #define HAVE_STRINGS_H 1 @@ -316,6 +322,9 @@ /* Define to 1 if you have the `strtold' function. */ #define HAVE_STRTOLD 1 +/* Define if strxfrm_l is available in . */ +/* #undef HAVE_STRXFRM_L */ + /* Define to 1 if you have the header file. */ #define HAVE_SYS_FILIO_H 1 From 74870cdedfea37a5e5d6156abb4971bef368a881 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Fri, 15 Feb 2013 23:12:58 +0000 Subject: [PATCH 0204/1476] Pull in r175057 from upstream llvm trunk: X86: Disable generation of rep;movsl when %esi is used as a base pointer. This happens when there is both stack realignment and a dynamic alloca in the function. If we overwrite %esi (rep;movsl uses fixed registers) we'll lose the base pointer and the next register spill will write into oblivion. Fixes PR15249 and unbreaks firefox on i386/freebsd. Mozilla uses dynamic allocas and freebsd a 4 byte stack alignment. MFC after: 1 week --- contrib/llvm/lib/Target/X86/X86SelectionDAGInfo.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/contrib/llvm/lib/Target/X86/X86SelectionDAGInfo.cpp b/contrib/llvm/lib/Target/X86/X86SelectionDAGInfo.cpp index 723e50cc188..efc34904ba5 100644 --- a/contrib/llvm/lib/Target/X86/X86SelectionDAGInfo.cpp +++ b/contrib/llvm/lib/Target/X86/X86SelectionDAGInfo.cpp @@ -202,6 +202,14 @@ X86SelectionDAGInfo::EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl, SrcPtrInfo.getAddrSpace() >= 256) return SDValue(); + // ESI might be used as a base pointer, in that case we can't simply overwrite + // the register. Fall back to generic code. + const X86RegisterInfo *TRI = + static_cast(DAG.getTarget().getRegisterInfo()); + if (TRI->hasBasePointer(DAG.getMachineFunction()) && + TRI->getBaseRegister() == X86::ESI) + return SDValue(); + MVT AVT; if (Align & 1) AVT = MVT::i8; From 3cbc3249253e682577c931a1d7827c0a61c224ea Mon Sep 17 00:00:00 2001 From: Ian Lepore Date: Fri, 15 Feb 2013 23:41:47 +0000 Subject: [PATCH 0205/1476] Set map->pmap before _bus_dmamap_count_pages() tries to use it. Obtained from: Thomas Skibo --- sys/arm/arm/busdma_machdep-v6.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/arm/arm/busdma_machdep-v6.c b/sys/arm/arm/busdma_machdep-v6.c index 0a0bdd85eb6..1ac2c975286 100644 --- a/sys/arm/arm/busdma_machdep-v6.c +++ b/sys/arm/arm/busdma_machdep-v6.c @@ -968,6 +968,8 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dmat, if (segs == NULL) segs = dmat->segments; + map->pmap = pmap; + if ((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) { _bus_dmamap_count_pages(dmat, map, buf, buflen, flags); if (map->pagesneeded != 0) { @@ -979,7 +981,6 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dmat, sl = NULL; vaddr = (vm_offset_t)buf; - map->pmap = pmap; while (buflen > 0) { /* From ca83b9753272a56a8c9e06c2fda743e8c2789427 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Fri, 15 Feb 2013 23:59:57 +0000 Subject: [PATCH 0206/1476] Fix undefined behaviour in usr.bin/mail/util.c. Reported by: deeptech71@gmail.com MFC after: 3 days --- usr.bin/mail/util.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usr.bin/mail/util.c b/usr.bin/mail/util.c index 4e3a0f6dde9..b869fb0a3e8 100644 --- a/usr.bin/mail/util.c +++ b/usr.bin/mail/util.c @@ -236,8 +236,8 @@ istrncpy(char *dest, const char *src, size_t dsize) { strlcpy(dest, src, dsize); - while (*dest) - *dest++ = tolower((unsigned char)*dest); + for (; *dest; dest++) + *dest = tolower((unsigned char)*dest); } /* From 8c67042b721d766fc42e7b77b9413d169e9e2696 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Sat, 16 Feb 2013 00:12:21 +0000 Subject: [PATCH 0207/1476] Fix an incorrect sizeof() Spotted by: clang Submitted by: dim --- sys/net80211/ieee80211_mesh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/net80211/ieee80211_mesh.c b/sys/net80211/ieee80211_mesh.c index f4f94d18256..9750a4a4b94 100644 --- a/sys/net80211/ieee80211_mesh.c +++ b/sys/net80211/ieee80211_mesh.c @@ -2625,7 +2625,7 @@ mesh_parse_meshgate_action(struct ieee80211_node *ni, switch (*frm) { case IEEE80211_ELEMID_MESHGANN: gannie = (const struct ieee80211_meshgann_ie *) frm; - memset(ie, 0, sizeof(ie)); + memset(ie, 0, sizeof(*ie)); ie->gann_ie = gannie->gann_ie; ie->gann_len = gannie->gann_len; ie->gann_flags = gannie->gann_flags; From a9c09aee21911f5f4d9999631fb08be74ed5ee9a Mon Sep 17 00:00:00 2001 From: David Xu Date: Sat, 16 Feb 2013 06:07:07 +0000 Subject: [PATCH 0208/1476] Simplify code by using flag O_EXLOCK. PR: kern/175674 --- lib/libc/gen/sem_new.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/lib/libc/gen/sem_new.c b/lib/libc/gen/sem_new.c index b11d54721ba..0393face489 100644 --- a/lib/libc/gen/sem_new.c +++ b/lib/libc/gen/sem_new.c @@ -198,15 +198,11 @@ _sem_open(const char *name, int flags, ...) goto error; } - fd = _open(path, flags|O_RDWR|O_CLOEXEC, mode); + fd = _open(path, flags|O_RDWR|O_CLOEXEC|O_EXLOCK, mode); if (fd == -1) goto error; - if (flock(fd, LOCK_EX) == -1) + if (_fstat(fd, &sb)) goto error; - if (_fstat(fd, &sb)) { - flock(fd, LOCK_UN); - goto error; - } if (sb.st_size < sizeof(sem_t)) { sem_t tmp; @@ -214,10 +210,8 @@ _sem_open(const char *name, int flags, ...) tmp._kern._has_waiters = 0; tmp._kern._count = value; tmp._kern._flags = USYNC_PROCESS_SHARED | SEM_NAMED; - if (_write(fd, &tmp, sizeof(tmp)) != sizeof(tmp)) { - flock(fd, LOCK_UN); + if (_write(fd, &tmp, sizeof(tmp)) != sizeof(tmp)) goto error; - } } flock(fd, LOCK_UN); sem = (sem_t *)mmap(NULL, sizeof(sem_t), PROT_READ|PROT_WRITE, From a9fb907e0b8a8e3d678864b002d783b8c44c7b1e Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sat, 16 Feb 2013 12:45:57 +0000 Subject: [PATCH 0209/1476] In contrib/opie/opiekey.c, use the correct length to zero the secret. Found by: clang ToT Reviewed by: delphij MFC after: 3 days --- contrib/opie/opiekey.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contrib/opie/opiekey.c b/contrib/opie/opiekey.c index 20ba658710e..698834968b8 100644 --- a/contrib/opie/opiekey.c +++ b/contrib/opie/opiekey.c @@ -109,19 +109,19 @@ static void getsecret FUNCTION((secret, promptextra, retype), char *secret AND c if (!opiereadpass(verify, OPIE_SECRET_MAX, 0)) { fprintf(stderr, "Error reading %ssecret pass phrase!\n", promptextra); memset(verify, 0, sizeof(verify)); - memset(secret, 0, sizeof(secret)); + memset(secret, 0, OPIE_SECRET_MAX + 1); exit(1); } if (verify[0] && strcmp(verify, secret)) { fprintf(stderr, "They don't match. Try again.\n"); memset(verify, 0, sizeof(verify)); - memset(secret, 0, sizeof(secret)); + memset(secret, 0, OPIE_SECRET_MAX + 1); exit(1); } memset(verify, 0, sizeof(verify)); } if (!(flags & 2) && !aflag && opiepasscheck(secret)) { - memset(secret, 0, sizeof(secret)); + memset(secret, 0, OPIE_SECRET_MAX + 1); fprintf(stderr, "Secret pass phrases must be between %d and %d characters long.\n", OPIE_SECRET_MIN, OPIE_SECRET_MAX); exit(1); }; From d21f31a1a7d27d47ce29ad7b365614bc0140b686 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sat, 16 Feb 2013 12:48:06 +0000 Subject: [PATCH 0210/1476] Fix two instances of undefined behaviour in contrib/nvi. Found by: clang ToT Obtained from: NetBSD Reviewed by: jh MFC after: 3 days --- contrib/nvi/ex/ex_txt.c | 4 ++-- contrib/nvi/vi/v_txt.c | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/contrib/nvi/ex/ex_txt.c b/contrib/nvi/ex/ex_txt.c index 2f62ff51a47..30bcf977f3f 100644 --- a/contrib/nvi/ex/ex_txt.c +++ b/contrib/nvi/ex/ex_txt.c @@ -398,8 +398,8 @@ txt_dent(sp, tp) ++scno; /* Get the previous shiftwidth column. */ - cno = scno; - scno -= --scno % sw; + cno = scno--; + scno -= scno % sw; /* * Since we don't know what comes before the character(s) being diff --git a/contrib/nvi/vi/v_txt.c b/contrib/nvi/vi/v_txt.c index 4a3e80a181d..0cb1ff5a89a 100644 --- a/contrib/nvi/vi/v_txt.c +++ b/contrib/nvi/vi/v_txt.c @@ -1956,8 +1956,10 @@ txt_dent(sp, tp, isindent) target = current; if (isindent) target += COL_OFF(target, sw); - else - target -= --target % sw; + else { + --target; + target -= target % sw; + } /* * The AI characters will be turned into overwrite characters if the From 5f3303983408d6019189e244692aee0ad30b8c24 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sat, 16 Feb 2013 12:52:40 +0000 Subject: [PATCH 0211/1476] Import change 40eebf235370b6fe6353784ccf01ab92eed062a5 from upstream wpa: From: Jouni Malinen Date: Fri, 15 Jul 2011 13:42:06 +0300 Subject: [PATCH] MD5: Fix clearing of temporary stack memory to use correct length sizeof of the structure instead of the pointer was supposed to be used here. Fix this to clear the full structure at the end of MD5Final(). Found by: clang ToT Reviewed by: rpaulo MFC after: 3 days --- contrib/wpa/src/crypto/md5-internal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/wpa/src/crypto/md5-internal.c b/contrib/wpa/src/crypto/md5-internal.c index f8692a9557a..137ad9150f4 100644 --- a/contrib/wpa/src/crypto/md5-internal.c +++ b/contrib/wpa/src/crypto/md5-internal.c @@ -188,7 +188,7 @@ void MD5Final(unsigned char digest[16], struct MD5Context *ctx) MD5Transform(ctx->buf, (u32 *) ctx->in); byteReverse((unsigned char *) ctx->buf, 4); os_memcpy(digest, ctx->buf, 16); - os_memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ + os_memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */ } /* The four core functions - F1 is optimized somewhat */ From 2bc1a1fe5c9253f33abf0a5fe34035d869bf0183 Mon Sep 17 00:00:00 2001 From: Kirk McKusick Date: Sat, 16 Feb 2013 14:51:30 +0000 Subject: [PATCH 0212/1476] Add barrier write capability to the VFS buffer interface. A barrier write is a disk write request that tells the disk that the buffer being written must be committed to the media along with any writes that preceeded it before any future blocks may be written to the drive. Barrier writes are provided by adding the functions bbarrierwrite (bwrite with barrier) and babarrierwrite (bawrite with barrier). Following a bbarrierwrite the client knows that the requested buffer is on the media. It does not ensure that buffers written before that buffer are on the media. It only ensure that buffers written before that buffer will get to the media before any buffers written after that buffer. A flush command must be sent to the disk to ensure that all earlier written buffers are on the media. Reviewed by: kib Tested by: Peter Holm --- sys/geom/geom_vfs.c | 4 ++++ sys/kern/vfs_bio.c | 42 ++++++++++++++++++++++++++++++++++++++++++ sys/kern/vfs_cluster.c | 12 +++++++++--- sys/sys/buf.h | 4 +++- 4 files changed, 58 insertions(+), 4 deletions(-) diff --git a/sys/geom/geom_vfs.c b/sys/geom/geom_vfs.c index afc65499c56..bbed550df06 100644 --- a/sys/geom/geom_vfs.c +++ b/sys/geom/geom_vfs.c @@ -192,6 +192,10 @@ g_vfs_strategy(struct bufobj *bo, struct buf *bp) bip->bio_done = g_vfs_done; bip->bio_caller2 = bp; bip->bio_length = bp->b_bcount; + if (bp->b_flags & B_BARRIER) { + bip->bio_flags |= BIO_ORDERED; + bp->b_flags &= ~B_BARRIER; + } g_io_request(bip, cp); } diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c index 96c844252a3..63933991e18 100644 --- a/sys/kern/vfs_bio.c +++ b/sys/kern/vfs_bio.c @@ -206,6 +206,9 @@ SYSCTL_INT(_vfs, OID_AUTO, flushbufqtarget, CTLFLAG_RW, &flushbufqtarget, 0, static long notbufdflashes; SYSCTL_LONG(_vfs, OID_AUTO, notbufdflashes, CTLFLAG_RD, ¬bufdflashes, 0, "Number of dirty buffer flushes done by the bufdaemon helpers"); +static long barrierwrites; +SYSCTL_LONG(_vfs, OID_AUTO, barrierwrites, CTLFLAG_RW, &barrierwrites, 0, + "Number of barrier writes"); /* * Wakeup point for bufdaemon, as well as indicator of whether it is already @@ -888,6 +891,9 @@ bufwrite(struct buf *bp) return (0); } + if (bp->b_flags & B_BARRIER) + barrierwrites++; + oldflags = bp->b_flags; BUF_ASSERT_HELD(bp); @@ -1007,6 +1013,8 @@ bdwrite(struct buf *bp) CTR3(KTR_BUF, "bdwrite(%p) vp %p flags %X", bp, bp->b_vp, bp->b_flags); KASSERT(bp->b_bufobj != NULL, ("No b_bufobj %p", bp)); + KASSERT((bp->b_flags & B_BARRIER) == 0, + ("Barrier request in delayed write %p", bp)); BUF_ASSERT_HELD(bp); if (bp->b_flags & B_INVAL) { @@ -1166,6 +1174,40 @@ bawrite(struct buf *bp) (void) bwrite(bp); } +/* + * babarrierwrite: + * + * Asynchronous barrier write. Start output on a buffer, but do not + * wait for it to complete. Place a write barrier after this write so + * that this buffer and all buffers written before it are committed to + * the disk before any buffers written after this write are committed + * to the disk. The buffer is released when the output completes. + */ +void +babarrierwrite(struct buf *bp) +{ + + bp->b_flags |= B_ASYNC | B_BARRIER; + (void) bwrite(bp); +} + +/* + * bbarrierwrite: + * + * Synchronous barrier write. Start output on a buffer and wait for + * it to complete. Place a write barrier after this write so that + * this buffer and all buffers written before it are committed to + * the disk before any buffers written after this write are committed + * to the disk. The buffer is released when the output completes. + */ +int +bbarrierwrite(struct buf *bp) +{ + + bp->b_flags |= B_BARRIER; + return (bwrite(bp)); +} + /* * bwillwrite: * diff --git a/sys/kern/vfs_cluster.c b/sys/kern/vfs_cluster.c index 19ee05f9d70..663b66f3e63 100644 --- a/sys/kern/vfs_cluster.c +++ b/sys/kern/vfs_cluster.c @@ -944,11 +944,17 @@ cluster_wbuild(vp, size, start_lbn, len) } bp->b_bcount += size; bp->b_bufsize += size; - bundirty(tbp); - tbp->b_flags &= ~B_DONE; - tbp->b_ioflags &= ~BIO_ERROR; + /* + * If any of the clustered buffers have their + * B_BARRIER flag set, transfer that request to + * the cluster. + */ + bp->b_flags |= (tbp->b_flags & B_BARRIER); + tbp->b_flags &= ~(B_DONE | B_BARRIER); tbp->b_flags |= B_ASYNC; + tbp->b_ioflags &= ~BIO_ERROR; tbp->b_iocmd = BIO_WRITE; + bundirty(tbp); reassignbuf(tbp); /* put on clean list */ bufobj_wref(tbp->b_bufobj); BUF_KERNPROC(tbp); diff --git a/sys/sys/buf.h b/sys/sys/buf.h index 418d6c5c356..672ef5a1003 100644 --- a/sys/sys/buf.h +++ b/sys/sys/buf.h @@ -205,7 +205,7 @@ struct buf { #define B_00000800 0x00000800 /* Available flag. */ #define B_00001000 0x00001000 /* Available flag. */ #define B_INVAL 0x00002000 /* Does not contain valid info. */ -#define B_00004000 0x00004000 /* Available flag. */ +#define B_BARRIER 0x00004000 /* Write this and all preceeding first. */ #define B_NOCACHE 0x00008000 /* Do not cache block after use. */ #define B_MALLOC 0x00010000 /* malloced b_data */ #define B_CLUSTEROK 0x00020000 /* Pagein op, so swap() can count it. */ @@ -488,6 +488,8 @@ int breadn_flags(struct vnode *, daddr_t, int, daddr_t *, int *, int, void breada(struct vnode *, daddr_t *, int *, int, struct ucred *); void bdwrite(struct buf *); void bawrite(struct buf *); +void babarrierwrite(struct buf *); +int bbarrierwrite(struct buf *); void bdirty(struct buf *); void bundirty(struct buf *); void bufstrategy(struct bufobj *, struct buf *); From 7839b23f008a108df149b2f2d12db6240cc8ead8 Mon Sep 17 00:00:00 2001 From: Kirk McKusick Date: Sat, 16 Feb 2013 15:11:40 +0000 Subject: [PATCH 0213/1476] The UFS2 filesystem allocates new blocks of inodes as they are needed. When a cylinder group runs short of inodes, a new block for inodes is allocated, zero'ed, and written to the disk. The zero'ed inodes must be on the disk before the cylinder group can be updated to claim them. If the cylinder group claiming the new inodes were written before the zero'ed block of inodes, the system could crash with the filesystem in an unrecoverable state. Rather than adding a soft updates dependency to ensure that the new inode block is written before it is claimed by the cylinder group map, we just do a barrier write of the zero'ed inode block to ensure that it will get written before the updated cylinder group map can be written. This change should only slow down bulk loading of newly created filesystems since that is the primary time that new inode blocks need to be created. Reported by: Robert Watson Reviewed by: kib Tested by: Peter Holm --- sys/ufs/ffs/ffs_alloc.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c index d462cbb1b26..abe4073f16b 100644 --- a/sys/ufs/ffs/ffs_alloc.c +++ b/sys/ufs/ffs/ffs_alloc.c @@ -1861,7 +1861,6 @@ gotit: /* * Check to see if we need to initialize more inodes. */ - ibp = NULL; if (fs->fs_magic == FS_UFS2_MAGIC && ipref + INOPB(fs) > cgp->cg_initediblk && cgp->cg_initediblk < cgp->cg_niblk) { @@ -1874,6 +1873,16 @@ gotit: dp2->di_gen = arc4random() / 2 + 1; dp2++; } + /* + * Rather than adding a soft updates dependency to ensure + * that the new inode block is written before it is claimed + * by the cylinder group map, we just do a barrier write + * here. The barrier write will ensure that the inode block + * gets written before the updated cylinder group map can be + * written. The barrier write should only slow down bulk + * loading of newly created filesystems. + */ + babarrierwrite(ibp); cgp->cg_initediblk += INOPB(fs); } UFS_LOCK(ump); @@ -1892,8 +1901,6 @@ gotit: if (DOINGSOFTDEP(ITOV(ip))) softdep_setup_inomapdep(bp, ip, cg * fs->fs_ipg + ipref, mode); bdwrite(bp); - if (ibp != NULL) - bawrite(ibp); return ((ino_t)(cg * fs->fs_ipg + ipref)); } From 1844ff169f794f6408e965cad0b2d24a447a6811 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Sat, 16 Feb 2013 19:11:57 +0000 Subject: [PATCH 0214/1476] * Reduce the PCU lock overhead a little by only re-acquiring it if we actually do have to reinitialise the RX side of things after an RX descriptor EOL error. * Revert a change of mine from quite a while ago - don't shortcut the RX initialisation path. There's a RX FIFO bug in the earlier chips (I'm not sure when it was fixed in this series, but it's fixed with the AR9380 and later) which causes the same RX descriptor to be written to over and over. This causes the descriptor to be marked as "done", and this ends up causing the whole RX path to go very strange. This should fixed the "kickpcu; handled X packets" message spam where "X" is consistently small. --- sys/dev/ath/if_ath_rx.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/sys/dev/ath/if_ath_rx.c b/sys/dev/ath/if_ath_rx.c index c8d95361b80..139e8946f35 100644 --- a/sys/dev/ath/if_ath_rx.c +++ b/sys/dev/ath/if_ath_rx.c @@ -954,16 +954,31 @@ rx_proc_next: * need to be handled, kick the PCU if there's * been an RXEOL condition. */ - ATH_PCU_LOCK(sc); - if (resched && sc->sc_kickpcu) { + if (resched && kickpcu) { + ATH_PCU_LOCK(sc); ATH_KTR(sc, ATH_KTR_ERROR, 0, "ath_rx_proc: kickpcu"); device_printf(sc->sc_dev, "%s: kickpcu; handled %d packets\n", __func__, npkts); - /* XXX rxslink? */ -#if 0 + /* + * Go through the process of fully tearing down + * the RX buffers and reinitialising them. + * + * There's a hardware bug that causes the RX FIFO + * to get confused under certain conditions and + * constantly write over the same frame, leading + * the RX driver code here to get heavily confused. + */ +#if 1 ath_startrecv(sc); #else + /* + * Disabled for now - it'd be nice to be able to do + * this in order to limit the amount of CPU time spent + * reinitialising the RX side (and thus minimise RX + * drops) however there's a hardware issue that + * causes things to get too far out of whack. + */ /* * XXX can we hold the PCU lock here? * Are there any net80211 buffer calls involved? @@ -977,8 +992,8 @@ rx_proc_next: ath_hal_intrset(ah, sc->sc_imask); sc->sc_kickpcu = 0; + ATH_PCU_UNLOCK(sc); } - ATH_PCU_UNLOCK(sc); /* XXX check this inside of IF_LOCK? */ if (resched && (ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) { From a7449e3cca7f54cb46bc1505204297d06f7e6afc Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sat, 16 Feb 2013 20:17:31 +0000 Subject: [PATCH 0215/1476] Since clang 3.2 now has an option to suppress warnings about implicitly promoted K&R parameters, remove the workarounds added for sendmail components in r228558. MFC after: 1 week --- lib/libsm/Makefile | 5 ----- libexec/mail.local/Makefile | 5 ----- libexec/smrsh/Makefile | 5 ----- share/mk/bsd.sys.mk | 2 +- usr.bin/vacation/Makefile | 5 ----- usr.sbin/sendmail/Makefile | 5 ----- 6 files changed, 1 insertion(+), 26 deletions(-) diff --git a/lib/libsm/Makefile b/lib/libsm/Makefile index f2f19fb4cf4..ce590d71f05 100644 --- a/lib/libsm/Makefile +++ b/lib/libsm/Makefile @@ -18,11 +18,6 @@ CFLAGS+=${SENDMAIL_CFLAGS} WARNS?= 2 -# Unfortunately, clang gives warnings about sendmail code that cannot -# be turned off yet. Since this is contrib code, and we don't really -# care about the warnings, just make them non-fatal for now. -NO_WERROR.clang= - LIB= sm SRCS+= sm_os.h diff --git a/libexec/mail.local/Makefile b/libexec/mail.local/Makefile index 1487decf621..3e59609e893 100644 --- a/libexec/mail.local/Makefile +++ b/libexec/mail.local/Makefile @@ -12,11 +12,6 @@ CFLAGS+=-I${SENDMAIL_DIR}/include -I. WARNS?= 2 WFORMAT=0 -# Unfortunately, clang gives warnings about sendmail code that cannot -# be turned off yet. Since this is contrib code, and we don't really -# care about the warnings, just make them non-fatal for now. -NO_WERROR.clang= - LIBSMDIR= ${.OBJDIR}/../../lib/libsm LIBSM= ${LIBSMDIR}/libsm.a diff --git a/libexec/smrsh/Makefile b/libexec/smrsh/Makefile index 0de820d0227..ae86155d0d0 100644 --- a/libexec/smrsh/Makefile +++ b/libexec/smrsh/Makefile @@ -17,11 +17,6 @@ LDADD= ${LIBSM} WARNS?= 2 -# Unfortunately, clang gives warnings about sendmail code that cannot -# be turned off yet. Since this is contrib code, and we don't really -# care about the warnings, just make them non-fatal for now. -NO_WERROR.clang= - SRCS+= sm_os.h CLEANFILES+=sm_os.h diff --git a/share/mk/bsd.sys.mk b/share/mk/bsd.sys.mk index 847e571e0d1..1d8b49d4142 100644 --- a/share/mk/bsd.sys.mk +++ b/share/mk/bsd.sys.mk @@ -72,7 +72,7 @@ CWARNFLAGS+= -Wno-tautological-compare -Wno-unused-value\ -Wno-parentheses-equality -Wno-unused-function -Wno-conversion .endif # WARNS <= 3 .if ${WARNS} <= 2 -CWARNFLAGS+= -Wno-switch -Wno-switch-enum +CWARNFLAGS+= -Wno-switch -Wno-switch-enum -Wno-knr-promoted-parameter .endif # WARNS <= 2 .if ${WARNS} <= 1 CWARNFLAGS+= -Wno-parentheses diff --git a/usr.bin/vacation/Makefile b/usr.bin/vacation/Makefile index ad77dbae8c7..056f5764fa0 100644 --- a/usr.bin/vacation/Makefile +++ b/usr.bin/vacation/Makefile @@ -11,11 +11,6 @@ CFLAGS+=-D_FFR_LISTDB -D_FFR_DEBUG WARNS?= 2 -# Unfortunately, clang gives warnings about sendmail code that cannot -# be turned off yet. Since this is contrib code, and we don't really -# care about the warnings, just make them non-fatal for now. -NO_WERROR.clang= - LIBSMDIR= ${.OBJDIR}/../../lib/libsm LIBSM= ${LIBSMDIR}/libsm.a diff --git a/usr.sbin/sendmail/Makefile b/usr.sbin/sendmail/Makefile index b68ed0fad71..a9f7fbbafd6 100644 --- a/usr.sbin/sendmail/Makefile +++ b/usr.sbin/sendmail/Makefile @@ -45,11 +45,6 @@ CFLAGS+= -DNETINET6 WARNS?= 1 -# Unfortunately, clang gives warnings about sendmail code that cannot -# be turned off yet. Since this is contrib code, and we don't really -# care about the warnings, just make them non-fatal for now. -NO_WERROR.clang= - DPADD= ${LIBUTIL} ${LIBWRAP} LDADD= -lutil -lwrap From 7a4accc1f0530a3f7bdb68b35964d9b1e9e33954 Mon Sep 17 00:00:00 2001 From: Ian Lepore Date: Sat, 16 Feb 2013 20:43:16 +0000 Subject: [PATCH 0216/1476] In _bus_dmamap_addseg(), the return value must be zero for error, or the size actually added to the segment (possibly smaller than the requested size if boundary crossings had to be avoided). --- sys/arm/arm/busdma_machdep-v6.c | 2 +- sys/arm/arm/busdma_machdep.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sys/arm/arm/busdma_machdep-v6.c b/sys/arm/arm/busdma_machdep-v6.c index 1ac2c975286..c87f857866f 100644 --- a/sys/arm/arm/busdma_machdep-v6.c +++ b/sys/arm/arm/busdma_machdep-v6.c @@ -856,7 +856,7 @@ _bus_dmamap_addseg(bus_dma_tag_t dmat, bus_dmamap_t map, bus_addr_t curaddr, curaddr); if (dr == NULL) { _bus_dmamap_unload(dmat, map); - return (EINVAL); + return (0); } /* * In a valid DMA range. Translate the physical diff --git a/sys/arm/arm/busdma_machdep.c b/sys/arm/arm/busdma_machdep.c index f31a7fec336..10760b4ce4f 100644 --- a/sys/arm/arm/busdma_machdep.c +++ b/sys/arm/arm/busdma_machdep.c @@ -913,7 +913,7 @@ _bus_dmamap_addseg(bus_dma_tag_t dmat, bus_dmamap_t map, bus_addr_t curaddr, dr = _bus_dma_inrange(dmat->ranges, dmat->_nranges, curaddr); if (dr == NULL) - return (EINVAL); + return (0); /* * In a valid DMA range. Translate the physical * memory address to an address in the DMA window. @@ -935,12 +935,12 @@ _bus_dmamap_addseg(bus_dma_tag_t dmat, bus_dmamap_t map, bus_addr_t curaddr, segs[seg].ds_len += sgsize; } else { if (++seg >= dmat->nsegments) - return (EFBIG); + return (0); segs[seg].ds_addr = curaddr; segs[seg].ds_len = sgsize; } *segp = seg; - return (0); + return (sgsize); } /* From cb35030ab3bf63589280eb34810cb1acc5d1a44c Mon Sep 17 00:00:00 2001 From: Marcel Moolenaar Date: Sat, 16 Feb 2013 21:46:27 +0000 Subject: [PATCH 0217/1476] Return EFAULT when the address is not a kernel virtual address. --- sys/ia64/ia64/mem.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/ia64/ia64/mem.c b/sys/ia64/ia64/mem.c index 339985d662d..70dcf7bfcc6 100644 --- a/sys/ia64/ia64/mem.c +++ b/sys/ia64/ia64/mem.c @@ -128,6 +128,8 @@ kmemphys: */ addr = trunc_page(v); eaddr = round_page(v + c); + if (addr < VM_MAXUSER_ADDRESS) + return (EFAULT); for (; addr < eaddr; addr += PAGE_SIZE) { if (pmap_kextract(addr) == 0) return (EFAULT); From c81beee50ec67679de0d4e9ac2952639b8159425 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Sat, 16 Feb 2013 22:16:14 +0000 Subject: [PATCH 0218/1476] #if out unused functions which trip up gcc but not clang. --- contrib/ldns/dnssec_verify.c | 2 ++ contrib/ldns/dnssec_zone.c | 7 ++++++- contrib/ldns/parse.c | 5 ++++- contrib/ldns/rr.c | 3 ++- contrib/ldns/util.c | 2 ++ contrib/ldns/zone.c | 2 ++ 6 files changed, 18 insertions(+), 3 deletions(-) diff --git a/contrib/ldns/dnssec_verify.c b/contrib/ldns/dnssec_verify.c index 40f7889c189..02d136a566d 100644 --- a/contrib/ldns/dnssec_verify.c +++ b/contrib/ldns/dnssec_verify.c @@ -628,6 +628,7 @@ ldns_dnssec_trust_tree_print_sm_fmt(FILE *out, } } +#if 0 static void ldns_dnssec_trust_tree_print_sm(FILE *out, ldns_dnssec_trust_tree *tree, @@ -639,6 +640,7 @@ ldns_dnssec_trust_tree_print_sm(FILE *out, ldns_dnssec_trust_tree_print_sm_fmt(out, ldns_output_format_default, tree, tabs, extended, sibmap, treedepth); } +#endif void ldns_dnssec_trust_tree_print_fmt(FILE *out, const ldns_output_format *fmt, diff --git a/contrib/ldns/dnssec_zone.c b/contrib/ldns/dnssec_zone.c index 64ff9f1badf..c71038276f1 100644 --- a/contrib/ldns/dnssec_zone.c +++ b/contrib/ldns/dnssec_zone.c @@ -298,6 +298,7 @@ ldns_dnssec_rrsets_print_soa_fmt(FILE *out, const ldns_output_format *fmt, } } +#if 0 static void ldns_dnssec_rrsets_print_soa(FILE *out, ldns_dnssec_rrsets *rrsets, @@ -307,7 +308,7 @@ ldns_dnssec_rrsets_print_soa(FILE *out, ldns_dnssec_rrsets_print_soa_fmt(out, ldns_output_format_default, rrsets, follow, show_soa); } - +#endif void ldns_dnssec_rrsets_print_fmt(FILE *out, const ldns_output_format *fmt, @@ -428,6 +429,7 @@ ldns_dnssec_name_set_name(ldns_dnssec_name *rrset, } } +#if 0 static ldns_rr * ldns_dnssec_name_nsec(ldns_dnssec_name *rrset) { @@ -436,6 +438,7 @@ ldns_dnssec_name_nsec(ldns_dnssec_name *rrset) } return NULL; } +#endif void ldns_dnssec_name_set_nsec(ldns_dnssec_name *rrset, ldns_rr *nsec) @@ -589,12 +592,14 @@ ldns_dnssec_name_print_soa_fmt(FILE *out, const ldns_output_format *fmt, } } +#if 0 static void ldns_dnssec_name_print_soa(FILE *out, ldns_dnssec_name *name, bool show_soa) { ldns_dnssec_name_print_soa_fmt(out, ldns_output_format_default, name, show_soa); } +#endif void ldns_dnssec_name_print_fmt(FILE *out, const ldns_output_format *fmt, diff --git a/contrib/ldns/parse.c b/contrib/ldns/parse.c index 8559da51573..4a3a4a70262 100644 --- a/contrib/ldns/parse.c +++ b/contrib/ldns/parse.c @@ -340,6 +340,7 @@ tokenread: return (ssize_t)i; } +#if 0 static void ldns_bskipc(ldns_buffer *buffer, char c) { @@ -352,6 +353,7 @@ ldns_bskipc(ldns_buffer *buffer, char c) } } } +#endif void ldns_bskipcs(ldns_buffer *buffer, const char *s) @@ -376,11 +378,12 @@ ldns_bskipcs(ldns_buffer *buffer, const char *s) } } +#if 0 static void ldns_fskipc(ATTR_UNUSED(FILE *fp), ATTR_UNUSED(char c)) { } - +#endif void ldns_fskipcs(FILE *fp, const char *s) diff --git a/contrib/ldns/rr.c b/contrib/ldns/rr.c index f68d57db666..484fa306243 100644 --- a/contrib/ldns/rr.c +++ b/contrib/ldns/rr.c @@ -1394,7 +1394,7 @@ ldns_rr_list_clone(const ldns_rr_list *rrlist) return new_list; } - +#if 0 static int qsort_rr_compare(const void *a, const void *b) { @@ -1412,6 +1412,7 @@ qsort_rr_compare(const void *a, const void *b) } return ldns_rr_compare(rr1, rr2); } +#endif static int qsort_schwartz_rr_compare(const void *a, const void *b) diff --git a/contrib/ldns/util.c b/contrib/ldns/util.c index fa3a45f2da9..fc8df863bd7 100644 --- a/contrib/ldns/util.c +++ b/contrib/ldns/util.c @@ -25,6 +25,7 @@ #include #endif +#if 0 /* put this here tmp. for debugging */ static void xprintf_rdf(ldns_rdf *rd) @@ -62,6 +63,7 @@ xprintf_hex(uint8_t *data, size_t len) } printf("\n"); } +#endif ldns_lookup_table * ldns_lookup_by_name(ldns_lookup_table *table, const char *name) diff --git a/contrib/ldns/zone.c b/contrib/ldns/zone.c index b33e198cc4d..6dd4df61d83 100644 --- a/contrib/ldns/zone.c +++ b/contrib/ldns/zone.c @@ -56,6 +56,7 @@ ldns_zone_push_rr(ldns_zone *z, ldns_rr *rr) return ldns_rr_list_push_rr( ldns_zone_rrs(z), rr); } +#if 0 /* return a clone of the given rr list, without the glue records * rr list should be the complete zone * if present, stripped records are added to the list *glue_records @@ -153,6 +154,7 @@ memory_error: } return NULL; } +#endif /* * Get the list of glue records in a zone From 1f2ce2a086982fffd25133608419c6fa6eb3e142 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sat, 16 Feb 2013 22:21:46 +0000 Subject: [PATCH 0219/1476] Put one file per line so it is easier to read diffs against those files. --- lib/libc/gen/Makefile.inc | 543 +++++++++++++++++++++++++++++--------- lib/libc/sys/Makefile.inc | 292 ++++++++++++++++---- 2 files changed, 652 insertions(+), 183 deletions(-) diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc index 0bbbb33060e..711cbff9a7b 100644 --- a/lib/libc/gen/Makefile.inc +++ b/lib/libc/gen/Makefile.inc @@ -4,37 +4,144 @@ # machine-independent gen sources .PATH: ${.CURDIR}/${LIBC_ARCH}/gen ${.CURDIR}/gen -SRCS+= __getosreldate.c __xuname.c \ - _once_stub.c _pthread_stubs.c _rand48.c _spinlock_stub.c \ +SRCS+= __getosreldate.c \ + __xuname.c \ + _once_stub.c \ + _pthread_stubs.c \ + _rand48.c \ + _spinlock_stub.c \ _thread_init.c \ - alarm.c arc4random.c assert.c auxv.c basename.c check_utility_compat.c \ - clock.c clock_getcpuclockid.c closedir.c confstr.c \ - crypt.c ctermid.c daemon.c devname.c dirfd.c dirname.c disklabel.c \ - dlfcn.c drand48.c elf_utils.c erand48.c err.c errlst.c errno.c \ - exec.c fdevname.c feature_present.c fmtcheck.c fmtmsg.c fnmatch.c \ - fpclassify.c frexp.c fstab.c ftok.c fts.c fts-compat.c ftw.c \ - getbootfile.c getbsize.c \ - getcap.c getcwd.c getdomainname.c getgrent.c getgrouplist.c \ - gethostname.c getloadavg.c getlogin.c getmntinfo.c getnetgrent.c \ - getosreldate.c getpagesize.c getpagesizes.c \ - getpeereid.c getprogname.c getpwent.c getttyent.c \ - getusershell.c getutxent.c getvfsbyname.c glob.c \ - initgroups.c isatty.c isinf.c isnan.c jrand48.c lcong48.c \ + alarm.c \ + arc4random.c \ + assert.c \ + auxv.c \ + basename.c \ + check_utility_compat.c \ + clock.c \ + clock_getcpuclockid.c \ + closedir.c \ + confstr.c \ + crypt.c \ + ctermid.c \ + daemon.c \ + devname.c \ + dirfd.c \ + dirname.c \ + disklabel.c \ + dlfcn.c \ + drand48.c \ + elf_utils.c \ + erand48.c \ + err.c \ + errlst.c \ + errno.c \ + exec.c \ + fdevname.c \ + feature_present.c \ + fmtcheck.c \ + fmtmsg.c \ + fnmatch.c \ + fpclassify.c \ + frexp.c \ + fstab.c \ + ftok.c \ + fts.c \ + fts-compat.c \ + ftw.c \ + getbootfile.c \ + getbsize.c \ + getcap.c \ + getcwd.c \ + getdomainname.c \ + getgrent.c \ + getgrouplist.c \ + gethostname.c \ + getloadavg.c \ + getlogin.c \ + getmntinfo.c \ + getnetgrent.c \ + getosreldate.c \ + getpagesize.c \ + getpagesizes.c \ + getpeereid.c \ + getprogname.c \ + getpwent.c \ + getttyent.c \ + getusershell.c \ + getutxent.c \ + getvfsbyname.c \ + glob.c \ + initgroups.c \ + isatty.c \ + isinf.c \ + isnan.c \ + jrand48.c \ + lcong48.c \ libc_dlopen.c \ - lockf.c lrand48.c mrand48.c nftw.c nice.c \ - nlist.c nrand48.c opendir.c \ - pause.c pmadvise.c popen.c posix_spawn.c \ - psignal.c pututxline.c pw_scan.c \ - raise.c readdir.c readpassphrase.c rewinddir.c \ - scandir.c seed48.c seekdir.c semctl.c \ - setdomainname.c sethostname.c setjmperr.c setmode.c \ - setproctitle.c setprogname.c siginterrupt.c siglist.c signal.c \ - sigsetops.c sleep.c srand48.c statvfs.c stringlist.c strtofflags.c \ - sysconf.c sysctl.c sysctlbyname.c sysctlnametomib.c \ - syslog.c telldir.c termios.c time.c times.c timezone.c tls.c \ - ttyname.c ttyslot.c ualarm.c ulimit.c uname.c unvis-compat.c \ - usleep.c utime.c utxdb.c valloc.c wait.c wait3.c waitpid.c \ - waitid.c wordexp.c + lockf.c \ + lrand48.c \ + mrand48.c \ + nftw.c \ + nice.c \ + nlist.c \ + nrand48.c \ + opendir.c \ + pause.c \ + pmadvise.c \ + popen.c \ + posix_spawn.c \ + psignal.c \ + pututxline.c \ + pw_scan.c \ + raise.c \ + readdir.c \ + readpassphrase.c \ + rewinddir.c \ + scandir.c \ + seed48.c \ + seekdir.c \ + semctl.c \ + setdomainname.c \ + sethostname.c \ + setjmperr.c \ + setmode.c \ + setproctitle.c \ + setprogname.c \ + siginterrupt.c \ + siglist.c \ + signal.c \ + sigsetops.c \ + sleep.c \ + srand48.c \ + statvfs.c \ + stringlist.c \ + strtofflags.c \ + sysconf.c \ + sysctl.c \ + sysctlbyname.c \ + sysctlnametomib.c \ + syslog.c \ + telldir.c \ + termios.c \ + time.c \ + times.c \ + timezone.c \ + tls.c \ + ttyname.c \ + ttyslot.c \ + ualarm.c \ + ulimit.c \ + uname.c \ + unvis-compat.c \ + usleep.c \ + utime.c \ + utxdb.c \ + valloc.c \ + wait.c \ + wait3.c \ + waitpid.c \ + waitid.c \ + wordexp.c .PATH: ${.CURDIR}/../../contrib/libc-pwcache SRCS+= pwcache.c pwcache.h @@ -58,101 +165,257 @@ SYM_MAPS+=${.CURDIR}/gen/Symbol.map # machine-dependent gen sources .sinclude "${.CURDIR}/${LIBC_ARCH}/gen/Makefile.inc" -MAN+= alarm.3 arc4random.3 \ - basename.3 check_utility_compat.3 clock.3 clock_getcpuclockid.3 \ - confstr.3 ctermid.3 daemon.3 devname.3 directory.3 dirname.3 \ - dl_iterate_phdr.3 dladdr.3 dlinfo.3 dllockinit.3 dlopen.3 \ - err.3 exec.3 \ - feature_present.3 fmtcheck.3 fmtmsg.3 fnmatch.3 fpclassify.3 frexp.3 \ - ftok.3 fts.3 ftw.3 \ - getbootfile.3 getbsize.3 getcap.3 getcontext.3 getcwd.3 \ - getdiskbyname.3 getdomainname.3 getfsent.3 \ - getgrent.3 getgrouplist.3 gethostname.3 getloadavg.3 \ - getmntinfo.3 getnetgrent.3 getosreldate.3 getpagesize.3 \ - getpagesizes.3 getpass.3 getpeereid.3 getprogname.3 getpwent.3 \ - getttyent.3 getusershell.3 getutxent.3 getvfsbyname.3 \ - glob.3 initgroups.3 isgreater.3 ldexp.3 lockf.3 makecontext.3 \ +MAN+= alarm.3 \ + arc4random.3 \ + basename.3 \ + check_utility_compat.3 \ + clock.3 \ + clock_getcpuclockid.3 \ + confstr.3 \ + ctermid.3 \ + daemon.3 \ + devname.3 \ + directory.3 \ + dirname.3 \ + dl_iterate_phdr.3 \ + dladdr.3 \ + dlinfo.3 \ + dllockinit.3 \ + dlopen.3 \ + err.3 \ + exec.3 \ + feature_present.3 \ + fmtcheck.3 \ + fmtmsg.3 \ + fnmatch.3 \ + fpclassify.3 \ + frexp.3 \ + ftok.3 \ + fts.3 \ + ftw.3 \ + getbootfile.3 \ + getbsize.3 \ + getcap.3 \ + getcontext.3 \ + getcwd.3 \ + getdiskbyname.3 \ + getdomainname.3 \ + getfsent.3 \ + getgrent.3 \ + getgrouplist.3 \ + gethostname.3 \ + getloadavg.3 \ + getmntinfo.3 \ + getnetgrent.3 \ + getosreldate.3 \ + getpagesize.3 \ + getpagesizes.3 \ + getpass.3 \ + getpeereid.3 \ + getprogname.3 \ + getpwent.3 \ + getttyent.3 \ + getusershell.3 \ + getutxent.3 \ + getvfsbyname.3 \ + glob.3 \ + initgroups.3 \ + isgreater.3 \ + ldexp.3 \ + lockf.3 \ + makecontext.3 \ modf.3 \ - nice.3 nlist.3 pause.3 popen.3 \ - posix_spawn.3 posix_spawn_file_actions_addopen.3 \ - posix_spawn_file_actions_init.3 posix_spawnattr_getflags.3 \ - posix_spawnattr_getpgroup.3 posix_spawnattr_getschedparam.3 \ - posix_spawnattr_getschedpolicy.3 posix_spawnattr_init.3 \ - posix_spawnattr_getsigdefault.3 posix_spawnattr_getsigmask.3 \ - psignal.3 pwcache.3 \ - raise.3 rand48.3 readpassphrase.3 rfork_thread.3 \ - scandir.3 sem_destroy.3 sem_getvalue.3 sem_init.3 \ - sem_open.3 sem_post.3 sem_timedwait.3 sem_wait.3 \ - setjmp.3 setmode.3 setproctitle.3 \ - siginterrupt.3 signal.3 sigsetops.3 sleep.3 \ - statvfs.3 stringlist.3 \ - strtofflags.3 sysconf.3 sysctl.3 syslog.3 tcgetpgrp.3 tcgetsid.3 \ - tcsendbreak.3 tcsetattr.3 tcsetpgrp.3 tcsetsid.3 time.3 times.3 \ - timezone.3 ttyname.3 tzset.3 ualarm.3 ucontext.3 ulimit.3 uname.3 \ - unvis.3 usleep.3 utime.3 valloc.3 vis.3 wordexp.3 + nice.3 \ + nlist.3 \ + pause.3 \ + popen.3 \ + posix_spawn.3 \ + posix_spawn_file_actions_addopen.3 \ + posix_spawn_file_actions_init.3 \ + posix_spawnattr_getflags.3 \ + posix_spawnattr_getpgroup.3 \ + posix_spawnattr_getschedparam.3 \ + posix_spawnattr_getschedpolicy.3 \ + posix_spawnattr_init.3 \ + posix_spawnattr_getsigdefault.3 \ + posix_spawnattr_getsigmask.3 \ + psignal.3 \ + pwcache.3 \ + raise.3 \ + rand48.3 \ + readpassphrase.3 \ + rfork_thread.3 \ + scandir.3 \ + sem_destroy.3 \ + sem_getvalue.3 \ + sem_init.3 \ + sem_open.3 \ + sem_post.3 \ + sem_timedwait.3 \ + sem_wait.3 \ + setjmp.3 \ + setmode.3 \ + setproctitle.3 \ + siginterrupt.3 \ + signal.3 \ + sigsetops.3 \ + sleep.3 \ + statvfs.3 \ + stringlist.3 \ + strtofflags.3 \ + sysconf.3 \ + sysctl.3 \ + syslog.3 \ + tcgetpgrp.3 \ + tcgetsid.3 \ + tcsendbreak.3 \ + tcsetattr.3 \ + tcsetpgrp.3 \ + tcsetsid.3 \ + time.3 \ + times.3 \ + timezone.3 \ + ttyname.3 \ + tzset.3 \ + ualarm.3 \ + ucontext.3 \ + ulimit.3 \ + uname.3 \ + unvis.3 \ + usleep.3 \ + utime.3 \ + valloc.3 \ + vis.3 \ + wordexp.3 -MLINKS+=arc4random.3 arc4random_addrandom.3 arc4random.3 arc4random_stir.3 \ - arc4random.3 arc4random_buf.3 arc4random.3 arc4random_uniform.3 +MLINKS+=arc4random.3 arc4random_addrandom.3 \ + arc4random.3 arc4random_stir.3 \ + arc4random.3 arc4random_buf.3 \ + arc4random.3 arc4random_uniform.3 MLINKS+=basename.3 basename_r.3 MLINKS+=ctermid.3 ctermid_r.3 MLINKS+=devname.3 devname_r.3 MLINKS+=devname.3 fdevname.3 MLINKS+=devname.3 fdevname_r.3 -MLINKS+=directory.3 closedir.3 directory.3 dirfd.3 directory.3 opendir.3 \ +MLINKS+=directory.3 closedir.3 \ + directory.3 dirfd.3 \ + directory.3 opendir.3 \ directory.3 fdopendir.3 \ - directory.3 readdir.3 directory.3 readdir_r.3 directory.3 rewinddir.3 \ - directory.3 seekdir.3 directory.3 telldir.3 -MLINKS+=dlopen.3 fdlopen.3 dlopen.3 dlclose.3 dlopen.3 dlerror.3 \ - dlopen.3 dlfunc.3 dlopen.3 dlsym.3 -MLINKS+=err.3 err_set_exit.3 err.3 err_set_file.3 err.3 errc.3 err.3 errx.3 \ - err.3 verr.3 err.3 verrc.3 err.3 verrx.3 err.3 vwarn.3 err.3 vwarnc.3 \ - err.3 vwarnx.3 err.3 warnc.3 err.3 warn.3 err.3 warnx.3 -MLINKS+=exec.3 execl.3 exec.3 execle.3 exec.3 execlp.3 exec.3 exect.3 \ - exec.3 execv.3 exec.3 execvP.3 exec.3 execvp.3 -MLINKS+=fpclassify.3 finite.3 fpclassify.3 finitef.3 \ - fpclassify.3 isfinite.3 fpclassify.3 isinf.3 fpclassify.3 isnan.3 \ + directory.3 readdir.3 \ + directory.3 readdir_r.3 \ + directory.3 rewinddir.3 \ + directory.3 seekdir.3 \ + directory.3 telldir.3 +MLINKS+=dlopen.3 fdlopen.3 \ + dlopen.3 dlclose.3 \ + dlopen.3 dlerror.3 \ + dlopen.3 dlfunc.3 \ + dlopen.3 dlsym.3 +MLINKS+=err.3 err_set_exit.3 \ + err.3 err_set_file.3 \ + err.3 errc.3 \ + err.3 errx.3 \ + err.3 verr.3 \ + err.3 verrc.3 \ + err.3 verrx.3 \ + err.3 vwarn.3 \ + err.3 vwarnc.3 \ + err.3 vwarnx.3 \ + err.3 warnc.3 \ + err.3 warn.3 \ + err.3 warnx.3 +MLINKS+=exec.3 execl.3 \ + exec.3 execle.3 \ + exec.3 execlp.3 \ + exec.3 exect.3 \ + exec.3 execv.3 \ + exec.3 execvP.3 \ + exec.3 execvp.3 +MLINKS+=fpclassify.3 finite.3 \ + fpclassify.3 finitef.3 \ + fpclassify.3 isfinite.3 \ + fpclassify.3 isinf.3 \ + fpclassify.3 isnan.3 \ fpclassify.3 isnormal.3 -MLINKS+=frexp.3 frexpf.3 frexp.3 frexpl.3 -MLINKS+=fts.3 fts_children.3 fts.3 fts_close.3 fts.3 fts_open.3 \ - fts.3 fts_read.3 fts.3 fts_set.3 fts.3 fts_set_clientptr.3 \ - fts.3 fts_get_clientptr.3 fts.3 fts_get_stream.3 +MLINKS+=frexp.3 frexpf.3 \ + frexp.3 frexpl.3 +MLINKS+=fts.3 fts_children.3 \ + fts.3 fts_close.3 \ + fts.3 fts_open.3 \ + fts.3 fts_read.3 \ + fts.3 fts_set.3 \ + fts.3 fts_set_clientptr.3 \ + fts.3 fts_get_clientptr.3 \ + fts.3 fts_get_stream.3 MLINKS+=ftw.3 nftw.3 -MLINKS+=getcap.3 cgetcap.3 getcap.3 cgetclose.3 getcap.3 cgetent.3 \ - getcap.3 cgetfirst.3 getcap.3 cgetmatch.3 getcap.3 cgetnext.3 \ - getcap.3 cgetnum.3 getcap.3 cgetset.3 getcap.3 cgetstr.3 \ +MLINKS+=getcap.3 cgetcap.3 \ + getcap.3 cgetclose.3 \ + getcap.3 cgetent.3 \ + getcap.3 cgetfirst.3 \ + getcap.3 cgetmatch.3 \ + getcap.3 cgetnext.3 \ + getcap.3 cgetnum.3 \ + getcap.3 cgetset.3 \ + getcap.3 cgetstr.3 \ getcap.3 cgetustr.3 MLINKS+=getcwd.3 getwd.3 MLINKS+=getcontext.3 setcontext.3 MLINKS+=getdomainname.3 setdomainname.3 -MLINKS+=getfsent.3 endfsent.3 getfsent.3 getfsfile.3 getfsent.3 getfsspec.3 \ - getfsent.3 getfstype.3 getfsent.3 setfsent.3 \ - getfsent.3 setfstab.3 getfsent.3 getfstab.3 -MLINKS+=getgrent.3 endgrent.3 getgrent.3 getgrgid.3 getgrent.3 getgrnam.3 \ - getgrent.3 setgrent.3 getgrent.3 setgroupent.3 \ - getgrent.3 getgrent_r.3 getgrent.3 getgrnam_r.3 getgrent.3 getgrgid_r.3 +MLINKS+=getfsent.3 endfsent.3 \ + getfsent.3 getfsfile.3 \ + getfsent.3 getfsspec.3 \ + getfsent.3 getfstype.3 \ + getfsent.3 setfsent.3 \ + getfsent.3 setfstab.3 \ + getfsent.3 getfstab.3 +MLINKS+=getgrent.3 endgrent.3 \ + getgrent.3 getgrgid.3 \ + getgrent.3 getgrnam.3 \ + getgrent.3 setgrent.3 \ + getgrent.3 setgroupent.3 \ + getgrent.3 getgrent_r.3 \ + getgrent.3 getgrnam_r.3 \ + getgrent.3 getgrgid_r.3 MLINKS+=gethostname.3 sethostname.3 -MLINKS+=getnetgrent.3 endnetgrent.3 getnetgrent.3 innetgr.3 \ +MLINKS+=getnetgrent.3 endnetgrent.3 \ + getnetgrent.3 innetgr.3 \ getnetgrent.3 setnetgrent.3 MLINKS+=getprogname.3 setprogname.3 -MLINKS+=getpwent.3 endpwent.3 getpwent.3 getpwnam.3 getpwent.3 getpwuid.3 \ - getpwent.3 setpassent.3 getpwent.3 setpwent.3 getpwent.3 setpwfile.3 \ - getpwent.3 getpwent_r.3 getpwent.3 getpwnam_r.3 \ +MLINKS+=getpwent.3 endpwent.3 \ + getpwent.3 getpwnam.3 \ + getpwent.3 getpwuid.3 \ + getpwent.3 setpassent.3 \ + getpwent.3 setpwent.3 \ + getpwent.3 setpwfile.3 \ + getpwent.3 getpwent_r.3 \ + getpwent.3 getpwnam_r.3 \ getpwent.3 getpwuid_r.3 -MLINKS+=getttyent.3 endttyent.3 getttyent.3 getttynam.3 \ - getttyent.3 isdialuptty.3 getttyent.3 isnettty.3 \ +MLINKS+=getttyent.3 endttyent.3 \ + getttyent.3 getttynam.3 \ + getttyent.3 isdialuptty.3 \ + getttyent.3 isnettty.3 \ getttyent.3 setttyent.3 -MLINKS+=getusershell.3 endusershell.3 getusershell.3 setusershell.3 -MLINKS+=getutxent.3 endutxent.3 getutxent.3 getutxid.3 \ - getutxent.3 getutxline.3 getutxent.3 getutxuser.3 \ - getutxent.3 pututxline.3 getutxent.3 setutxdb.3 \ - getutxent.3 setutxent.3 getutxent.3 utmpx.3 +MLINKS+=getusershell.3 endusershell.3 \ + getusershell.3 setusershell.3 +MLINKS+=getutxent.3 endutxent.3 \ + getutxent.3 getutxid.3 \ + getutxent.3 getutxline.3 \ + getutxent.3 getutxuser.3 \ + getutxent.3 pututxline.3 \ + getutxent.3 setutxdb.3 \ + getutxent.3 setutxent.3 \ + getutxent.3 utmpx.3 MLINKS+=glob.3 globfree.3 -MLINKS+=isgreater.3 isgreaterequal.3 isgreater.3 isless.3 \ - isgreater.3 islessequal.3 isgreater.3 islessgreater.3 \ +MLINKS+=isgreater.3 isgreaterequal.3 \ + isgreater.3 isless.3 \ + isgreater.3 islessequal.3 \ + isgreater.3 islessgreater.3 \ isgreater.3 isunordered.3 -MLINKS+=ldexp.3 ldexpf.3 ldexp.3 ldexpl.3 +MLINKS+=ldexp.3 ldexpf.3 \ + ldexp.3 ldexpl.3 MLINKS+=makecontext.3 swapcontext.3 -MLINKS+=modf.3 modff.3 modf.3 modfl.3 +MLINKS+=modf.3 modff.3 \ + modf.3 modfl.3 MLINKS+=popen.3 pclose.3 MLINKS+=posix_spawn.3 posix_spawnp.3 \ posix_spawn_file_actions_addopen.3 posix_spawn_file_actions_addclose.3 \ @@ -165,36 +428,66 @@ MLINKS+=posix_spawn.3 posix_spawnp.3 \ posix_spawnattr_getsigdefault.3 posix_spawnattr_setsigdefault.3 \ posix_spawnattr_getsigmask.3 posix_spawnattr_setsigmask.3 \ posix_spawnattr_init.3 posix_spawnattr_destroy.3 -MLINKS+=psignal.3 strsignal.3 psignal.3 sys_siglist.3 psignal.3 sys_signame.3 -MLINKS+=pwcache.3 group_from_gid.3 pwcache.3 user_from_uid.3 -MLINKS+=rand48.3 _rand48.3 rand48.3 drand48.3 rand48.3 erand48.3 \ - rand48.3 jrand48.3 rand48.3 lcong48.3 rand48.3 lrand48.3 \ - rand48.3 mrand48.3 rand48.3 nrand48.3 rand48.3 seed48.3 \ +MLINKS+=psignal.3 strsignal.3 \ + psignal.3 sys_siglist.3 \ + psignal.3 sys_signame.3 +MLINKS+=pwcache.3 group_from_gid.3 \ + pwcache.3 user_from_uid.3 +MLINKS+=rand48.3 _rand48.3 \ + rand48.3 drand48.3 \ + rand48.3 erand48.3 \ + rand48.3 jrand48.3 \ + rand48.3 lcong48.3 \ + rand48.3 lrand48.3 \ + rand48.3 mrand48.3 \ + rand48.3 nrand48.3 \ + rand48.3 seed48.3 \ rand48.3 srand48.3 MLINKS+=scandir.3 alphasort.3 -MLINKS+=sem_open.3 sem_close.3 sem_open.3 sem_unlink.3 +MLINKS+=sem_open.3 sem_close.3 \ + sem_open.3 sem_unlink.3 MLINKS+=sem_wait.3 sem_trywait.3 -MLINKS+=setjmp.3 _longjmp.3 setjmp.3 _setjmp.3 setjmp.3 longjmp.3 \ - setjmp.3 longjmperr.3 setjmp.3 longjmperror.3 \ - setjmp.3 siglongjmp.3 setjmp.3 sigsetjmp.3 +MLINKS+=setjmp.3 _longjmp.3 \ + setjmp.3 _setjmp.3 \ + setjmp.3 longjmp.3 \ + setjmp.3 longjmperr.3 \ + setjmp.3 longjmperror.3 \ + setjmp.3 siglongjmp.3 \ + setjmp.3 sigsetjmp.3 MLINKS+=setmode.3 getmode.3 -MLINKS+=sigsetops.3 sigaddset.3 sigsetops.3 sigdelset.3 \ - sigsetops.3 sigemptyset.3 sigsetops.3 sigfillset.3 \ +MLINKS+=sigsetops.3 sigaddset.3 \ + sigsetops.3 sigdelset.3 \ + sigsetops.3 sigemptyset.3 \ + sigsetops.3 sigfillset.3 \ sigsetops.3 sigismember.3 MLINKS+=statvfs.3 fstatvfs.3 -MLINKS+=stringlist.3 sl_add.3 stringlist.3 sl_find.3 \ - stringlist.3 sl_free.3 stringlist.3 sl_init.3 +MLINKS+=stringlist.3 sl_add.3 \ + stringlist.3 sl_find.3 \ + stringlist.3 sl_free.3 \ + stringlist.3 sl_init.3 MLINKS+=strtofflags.3 fflagstostr.3 -MLINKS+=sysctl.3 sysctlbyname.3 sysctl.3 sysctlnametomib.3 -MLINKS+=syslog.3 closelog.3 syslog.3 openlog.3 syslog.3 setlogmask.3 \ +MLINKS+=sysctl.3 sysctlbyname.3 \ + sysctl.3 sysctlnametomib.3 +MLINKS+=syslog.3 closelog.3 \ + syslog.3 openlog.3 \ + syslog.3 setlogmask.3 \ syslog.3 vsyslog.3 -MLINKS+=tcsendbreak.3 tcdrain.3 tcsendbreak.3 tcflow.3 tcsendbreak.3 tcflush.3 -MLINKS+=tcsetattr.3 cfgetispeed.3 tcsetattr.3 cfgetospeed.3 \ - tcsetattr.3 cfmakeraw.3 tcsetattr.3 cfmakesane.3 \ - tcsetattr.3 cfsetispeed.3 tcsetattr.3 cfsetospeed.3 \ - tcsetattr.3 cfsetspeed.3 tcsetattr.3 tcgetattr.3 -MLINKS+=ttyname.3 isatty.3 ttyname.3 ttyname_r.3 +MLINKS+=tcsendbreak.3 tcdrain.3 \ + tcsendbreak.3 tcflow.3 \ + tcsendbreak.3 tcflush.3 +MLINKS+=tcsetattr.3 cfgetispeed.3 \ + tcsetattr.3 cfgetospeed.3 \ + tcsetattr.3 cfmakeraw.3 \ + tcsetattr.3 cfmakesane.3 \ + tcsetattr.3 cfsetispeed.3 \ + tcsetattr.3 cfsetospeed.3 \ + tcsetattr.3 cfsetspeed.3 \ + tcsetattr.3 tcgetattr.3 +MLINKS+=ttyname.3 isatty.3 \ + ttyname.3 ttyname_r.3 MLINKS+=tzset.3 tzsetwall.3 -MLINKS+=unvis.3 strunvis.3 unvis.3 strunvisx.3 -MLINKS+=vis.3 strvis.3 vis.3 strvisx.3 +MLINKS+=unvis.3 strunvis.3 \ + unvis.3 strunvisx.3 +MLINKS+=vis.3 strvis.3 \ + vis.3 strvisx.3 MLINKS+=wordexp.3 wordfree.3 diff --git a/lib/libc/sys/Makefile.inc b/lib/libc/sys/Makefile.inc index a35ed5df57b..9f216dc5cc0 100644 --- a/lib/libc/sys/Makefile.inc +++ b/lib/libc/sys/Makefile.inc @@ -78,59 +78,212 @@ ${SPSEUDO}: >> ${.TARGET} printf ${NOTE_GNU_STACK} >>${.TARGET} -MAN+= abort2.2 accept.2 access.2 acct.2 adjtime.2 \ - aio_cancel.2 aio_error.2 aio_read.2 aio_return.2 \ - aio_suspend.2 aio_waitcomplete.2 aio_write.2 \ - bind.2 brk.2 cap_enter.2 cap_new.2 chdir.2 chflags.2 \ - chmod.2 chown.2 chroot.2 clock_gettime.2 close.2 closefrom.2 \ - connect.2 cpuset.2 cpuset_getaffinity.2 dup.2 execve.2 _exit.2 \ - extattr_get_file.2 fcntl.2 ffclock.2 fhopen.2 flock.2 fork.2 fsync.2 \ - getdirentries.2 getdtablesize.2 \ - getfh.2 getfsstat.2 getgid.2 getgroups.2 getitimer.2 getlogin.2 \ - getloginclass.2 getpeername.2 getpgrp.2 getpid.2 getpriority.2 \ - getrlimit.2 getrusage.2 getsid.2 getsockname.2 \ - getsockopt.2 gettimeofday.2 getuid.2 \ - intro.2 ioctl.2 issetugid.2 jail.2 kenv.2 kill.2 \ - kldfind.2 kldfirstmod.2 kldload.2 kldnext.2 kldstat.2 kldsym.2 \ - kldunload.2 kqueue.2 ktrace.2 link.2 lio_listio.2 listen.2 \ +MAN+= abort2.2 \ + accept.2 \ + access.2 \ + acct.2 \ + adjtime.2 \ + aio_cancel.2 \ + aio_error.2 \ + aio_read.2 \ + aio_return.2 \ + aio_suspend.2 \ + aio_waitcomplete.2 \ + aio_write.2 \ + bind.2 \ + brk.2 \ + cap_enter.2 \ + cap_new.2 \ + chdir.2 \ + chflags.2 \ + chmod.2 \ + chown.2 \ + chroot.2 \ + clock_gettime.2 \ + close.2 \ + closefrom.2 \ + connect.2 \ + cpuset.2 \ + cpuset_getaffinity.2 \ + dup.2 \ + execve.2 \ + _exit.2 \ + extattr_get_file.2 \ + fcntl.2 \ + ffclock.2 \ + fhopen.2 \ + flock.2 \ + fork.2 \ + fsync.2 \ + getdirentries.2 \ + getdtablesize.2 \ + getfh.2 \ + getfsstat.2 \ + getgid.2 \ + getgroups.2 \ + getitimer.2 \ + getlogin.2 \ + getloginclass.2 \ + getpeername.2 \ + getpgrp.2 \ + getpid.2 \ + getpriority.2 \ + getrlimit.2 \ + getrusage.2 \ + getsid.2 \ + getsockname.2 \ + getsockopt.2 \ + gettimeofday.2 \ + getuid.2 \ + intro.2 \ + ioctl.2 \ + issetugid.2 \ + jail.2 \ + kenv.2 \ + kill.2 \ + kldfind.2 \ + kldfirstmod.2 \ + kldload.2 \ + kldnext.2 \ + kldstat.2 \ + kldsym.2 \ + kldunload.2 \ + kqueue.2 \ + ktrace.2 \ + link.2 \ + lio_listio.2 \ + listen.2 \ lseek.2 \ - madvise.2 mincore.2 minherit.2 mkdir.2 mkfifo.2 mknod.2 mlock.2 \ - mlockall.2 mmap.2 modfind.2 modnext.2 modstat.2 mount.2 mprotect.2 \ - mq_close.2 mq_getattr.2 mq_notify.2 mq_open.2 mq_receive.2 mq_send.2 \ + madvise.2 \ + mincore.2 \ + minherit.2 \ + mkdir.2 \ + mkfifo.2 \ + mknod.2 \ + mlock.2 \ + mlockall.2 \ + mmap.2 \ + modfind.2 \ + modnext.2 \ + modstat.2 \ + mount.2 \ + mprotect.2 \ + mq_close.2 \ + mq_getattr.2 \ + mq_notify.2 \ + mq_open.2 \ + mq_receive.2 \ + mq_send.2 \ mq_setattr.2 \ - msgctl.2 msgget.2 msgrcv.2 msgsnd.2 \ - msync.2 munmap.2 nanosleep.2 nfssvc.2 ntp_adjtime.2 open.2 \ - pathconf.2 pdfork.2 pipe.2 poll.2 posix_fadvise.2 posix_fallocate.2 \ - posix_openpt.2 profil.2 \ - pselect.2 ptrace.2 quotactl.2 \ - read.2 readlink.2 reboot.2 recv.2 rename.2 revoke.2 rfork.2 rmdir.2 \ + msgctl.2 \ + msgget.2 \ + msgrcv.2 \ + msgsnd.2 \ + msync.2 \ + munmap.2 \ + nanosleep.2 \ + nfssvc.2 \ + ntp_adjtime.2 \ + open.2 \ + pathconf.2 \ + pdfork.2 \ + pipe.2 \ + poll.2 \ + posix_fadvise.2 \ + posix_fallocate.2 \ + posix_openpt.2 \ + profil.2 \ + pselect.2 \ + ptrace.2 \ + quotactl.2 \ + read.2 \ + readlink.2 \ + reboot.2 \ + recv.2 \ + rename.2 \ + revoke.2 \ + rfork.2 \ + rmdir.2 \ rtprio.2 .if !defined(NO_P1003_1B) -MAN+= sched_get_priority_max.2 sched_setparam.2 \ - sched_setscheduler.2 sched_yield.2 +MAN+= sched_get_priority_max.2 \ + sched_setparam.2 \ + sched_setscheduler.2 \ + sched_yield.2 .endif -MAN+= sctp_generic_recvmsg.2 sctp_generic_sendmsg.2 sctp_peeloff.2 \ - select.2 semctl.2 semget.2 semop.2 send.2 setfib.2 sendfile.2 \ - setgroups.2 setpgid.2 setregid.2 setresuid.2 setreuid.2 setsid.2 \ - setuid.2 shmat.2 shmctl.2 shmget.2 shm_open.2 shutdown.2 \ - sigaction.2 sigaltstack.2 sigpending.2 sigprocmask.2 sigqueue.2 \ - sigreturn.2 sigstack.2 sigsuspend.2 sigwait.2 sigwaitinfo.2 \ - socket.2 socketpair.2 stat.2 statfs.2 \ - swapon.2 symlink.2 sync.2 sysarch.2 syscall.2 \ - timer_create.2 timer_delete.2 timer_settime.2 \ - truncate.2 umask.2 undelete.2 \ - unlink.2 utimes.2 utrace.2 uuidgen.2 vfork.2 wait.2 write.2 +MAN+= sctp_generic_recvmsg.2 \ + sctp_generic_sendmsg.2 \ + sctp_peeloff.2 \ + select.2 \ + semctl.2 \ + semget.2 \ + semop.2 \ + send.2 \ + setfib.2 \ + sendfile.2 \ + setgroups.2 \ + setpgid.2 \ + setregid.2 \ + setresuid.2 \ + setreuid.2 \ + setsid.2 \ + setuid.2 \ + shmat.2 \ + shmctl.2 \ + shmget.2 \ + shm_open.2 \ + shutdown.2 \ + sigaction.2 \ + sigaltstack.2 \ + sigpending.2 \ + sigprocmask.2 \ + sigqueue.2 \ + sigreturn.2 \ + sigstack.2 \ + sigsuspend.2 \ + sigwait.2 \ + sigwaitinfo.2 \ + socket.2 \ + socketpair.2 \ + stat.2 \ + statfs.2 \ + swapon.2 \ + symlink.2 \ + sync.2 \ + sysarch.2 \ + syscall.2 \ + timer_create.2 \ + timer_delete.2 \ + timer_settime.2 \ + truncate.2 \ + umask.2 \ + undelete.2 \ + unlink.2 \ + utimes.2 \ + utrace.2 \ + uuidgen.2 \ + vfork.2 \ + wait.2 \ + write.2 -MLINKS+=access.2 eaccess.2 access.2 faccessat.2 +MLINKS+=access.2 eaccess.2 \ + access.2 faccessat.2 MLINKS+=brk.2 sbrk.2 MLINKS+=cap_enter.2 cap_getmode.2 MLINKS+=cap_new.2 cap_getrights.2 MLINKS+=chdir.2 fchdir.2 -MLINKS+=chflags.2 fchflags.2 chflags.2 lchflags.2 -MLINKS+=chmod.2 fchmod.2 chmod.2 fchmodat.2 chmod.2 lchmod.2 -MLINKS+=chown.2 fchown.2 chown.2 fchownat.2 chown.2 lchown.2 -MLINKS+=clock_gettime.2 clock_getres.2 clock_gettime.2 clock_settime.2 -MLINKS+=cpuset.2 cpuset_getid.2 cpuset.2 cpuset_setid.2 +MLINKS+=chflags.2 fchflags.2 \ + chflags.2 lchflags.2 +MLINKS+=chmod.2 fchmod.2 \ + chmod.2 fchmodat.2 \ + chmod.2 lchmod.2 +MLINKS+=chown.2 fchown.2 \ + chown.2 fchownat.2 \ + chown.2 lchown.2 +MLINKS+=clock_gettime.2 clock_getres.2 \ + clock_gettime.2 clock_settime.2 +MLINKS+=cpuset.2 cpuset_getid.2 \ + cpuset.2 cpuset_setid.2 MLINKS+=cpuset_getaffinity.2 cpuset_setaffinity.2 MLINKS+=dup.2 dup2.2 MLINKS+=execve.2 fexecve.2 @@ -146,7 +299,8 @@ MLINKS+=extattr_get_file.2 extattr.2 \ extattr_get_file.2 extattr_set_fd.2 \ extattr_get_file.2 extattr_set_file.2 \ extattr_get_file.2 extattr_set_link.2 -MLINKS+=ffclock.2 ffclock_getcounter.2 ffclock.2 ffclock_getestimate.2 \ +MLINKS+=ffclock.2 ffclock_getcounter.2 \ + ffclock.2 ffclock_getestimate.2 \ ffclock.2 ffclock_setestimate.2 MLINKS+=fhopen.2 fhstat.2 fhopen.2 fhstatfs.2 MLINKS+=getdirentries.2 getdents.2 @@ -169,7 +323,8 @@ MLINKS+=jail.2 jail_attach.2 \ jail.2 jail_remove.2 \ jail.2 jail_set.2 MLINKS+=kldunload.2 kldunloadf.2 -MLINKS+=kqueue.2 kevent.2 kqueue.2 EV_SET.3 +MLINKS+=kqueue.2 kevent.2 \ + kqueue.2 EV_SET.3 MLINKS+=link.2 linkat.2 MLINKS+=madvise.2 posix_madvise.2 MLINKS+=mkdir.2 mkdirat.2 @@ -178,7 +333,8 @@ MLINKS+=mknod.2 mknodat.2 MLINKS+=mlock.2 munlock.2 MLINKS+=mlockall.2 munlockall.2 MLINKS+=modnext.2 modfnext.2 -MLINKS+=mount.2 nmount.2 mount.2 unmount.2 +MLINKS+=mount.2 nmount.2 \ + mount.2 unmount.2 MLINKS+=mq_receive.2 mq_timedreceive.2 MLINKS+=mq_send.2 mq_timedsend.2 MLINKS+=ntp_adjtime.2 ntp_gettime.2 @@ -188,9 +344,12 @@ MLINKS+=pathconf.2 lpathconf.2 MLINKS+=pdfork.2 pdgetpid.2\ pdfork.2 pdkill.2 \ pdfork.2 pdwait4.2 -MLINKS+=read.2 pread.2 read.2 preadv.2 read.2 readv.2 +MLINKS+=read.2 pread.2 \ + read.2 preadv.2 \ + read.2 readv.2 MLINKS+=readlink.2 readlinkat.2 -MLINKS+=recv.2 recvfrom.2 recv.2 recvmsg.2 +MLINKS+=recv.2 recvfrom.2 \ + recv.2 recvmsg.2 MLINKS+=rename.2 renameat.2 MLINKS+=rtprio.2 rtprio_thread.2 .if !defined(NO_P1003_1B) @@ -199,24 +358,41 @@ MLINKS+=sched_get_priority_max.2 sched_get_priority_min.2 \ MLINKS+=sched_setparam.2 sched_getparam.2 MLINKS+=sched_setscheduler.2 sched_getscheduler.2 .endif -MLINKS+=select.2 FD_CLR.3 select.2 FD_ISSET.3 select.2 FD_SET.3 \ +MLINKS+=select.2 FD_CLR.3 \ + select.2 FD_ISSET.3 \ + select.2 FD_SET.3 \ select.2 FD_ZERO.3 -MLINKS+=send.2 sendmsg.2 send.2 sendto.2 +MLINKS+=send.2 sendmsg.2 \ + send.2 sendto.2 MLINKS+=setpgid.2 setpgrp.2 -MLINKS+=setresuid.2 getresgid.2 setresuid.2 getresuid.2 setresuid.2 setresgid.2 -MLINKS+=setuid.2 setegid.2 setuid.2 seteuid.2 setuid.2 setgid.2 +MLINKS+=setresuid.2 getresgid.2 \ + setresuid.2 getresuid.2 \ + setresuid.2 setresgid.2 +MLINKS+=setuid.2 setegid.2 \ + setuid.2 seteuid.2 \ + setuid.2 setgid.2 MLINKS+=shmat.2 shmdt.2 MLINKS+=shm_open.2 shm_unlink.2 MLINKS+=sigwaitinfo.2 sigtimedwait.2 -MLINKS+=stat.2 fstat.2 stat.2 fstatat.2 stat.2 lstat.2 +MLINKS+=stat.2 fstat.2 \ + stat.2 fstatat.2 \ + stat.2 lstat.2 MLINKS+=statfs.2 fstatfs.2 MLINKS+=swapon.2 swapoff.2 MLINKS+=symlink.2 symlinkat.2 MLINKS+=syscall.2 __syscall.2 -MLINKS+=timer_settime.2 timer_getoverrun.2 timer_settime.2 timer_gettime.2 +MLINKS+=timer_settime.2 timer_getoverrun.2 \ + timer_settime.2 timer_gettime.2 MLINKS+=truncate.2 ftruncate.2 MLINKS+=unlink.2 unlinkat.2 -MLINKS+=utimes.2 futimes.2 utimes.2 futimesat.2 utimes.2 lutimes.2 -MLINKS+=wait.2 wait3.2 wait.2 wait4.2 wait.2 waitpid.2 \ - wait.2 waitid.2 wait.2 wait6.2 -MLINKS+=write.2 pwrite.2 write.2 pwritev.2 write.2 writev.2 +MLINKS+=utimes.2 futimes.2 \ + utimes.2 futimesat.2 \ + utimes.2 lutimes.2 +MLINKS+=wait.2 wait3.2 \ + wait.2 wait4.2 \ + wait.2 waitpid.2 \ + wait.2 waitid.2 \ + wait.2 wait6.2 +MLINKS+=write.2 pwrite.2 \ + write.2 pwritev.2 \ + write.2 writev.2 From 57677a3a4ac5cc5dab4e945547396d068328edb4 Mon Sep 17 00:00:00 2001 From: Oleksandr Tymoshenko Date: Sat, 16 Feb 2013 23:12:06 +0000 Subject: [PATCH 0220/1476] Various timing-related fixes: - Replace divisor numbers with more descirptive names - Properly calculate minimum frequency for SDHCI 3.0 - Properly calculate frequency for SDHCI 3.0 in mmcbr_set_clock - Add min_freq method to sdhci_if.m and provide default implementation. By re-implementing this method hardware drivers can control frequency controller operates when executing initialization sequence --- sys/dev/sdhci/sdhci.c | 56 +++++++++++++++++++++++++++++++--------- sys/dev/sdhci/sdhci.h | 1 + sys/dev/sdhci/sdhci_if.m | 16 ++++++++++++ 3 files changed, 61 insertions(+), 12 deletions(-) diff --git a/sys/dev/sdhci/sdhci.c b/sys/dev/sdhci/sdhci.c index 0ef0617e81f..978eb55bcae 100644 --- a/sys/dev/sdhci/sdhci.c +++ b/sys/dev/sdhci/sdhci.c @@ -65,7 +65,7 @@ struct sdhci_softc { static SYSCTL_NODE(_hw, OID_AUTO, sdhci, CTLFLAG_RD, 0, "sdhci driver"); -int sdhci_debug = 0; +int sdhci_debug = 1; TUNABLE_INT("hw.sdhci.debug", &sdhci_debug); SYSCTL_INT(_hw_sdhci, OID_AUTO, debug, CTLFLAG_RW, &sdhci_debug, 0, "Debug level"); @@ -98,6 +98,9 @@ static void sdhci_card_task(void *, int); #define SDHCI_DEFAULT_MAX_FREQ 50 +#define SDHCI_200_MAX_DIVIDER 256 +#define SDHCI_300_MAX_DIVIDER 2046 + static void sdhci_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error) { @@ -238,7 +241,7 @@ sdhci_set_clock(struct sdhci_slot *slot, uint32_t clock) if (slot->version < SDHCI_SPEC_300) { /* Looking for highest freq <= clock. */ res = slot->max_clk; - for (div = 1; div < 256; div <<= 1) { + for (div = 1; div < SDHCI_200_MAX_DIVIDER; div <<= 1) { if (res <= clock) break; res >>= 1; @@ -248,10 +251,10 @@ sdhci_set_clock(struct sdhci_slot *slot, uint32_t clock) } else { /* Version 3.0 divisors are multiples of two up to 1023*2 */ - if (clock > slot->max_clk) - div = 2; + if (clock >= slot->max_clk) + div = 0; else { - for (div = 2; div < 1023*2; div += 2) { + for (div = 2; div < SDHCI_300_MAX_DIVIDER; div += 2) { if ((slot->max_clk / div) <= clock) break; } @@ -545,7 +548,7 @@ sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num) "frequency.\n"); } - slot->host.f_min = slot->max_clk / 256; + slot->host.f_min = SDHCI_MIN_FREQ(slot->bus, slot); slot->host.f_max = slot->max_clk; slot->host.host_ocr = 0; if (caps & SDHCI_CAN_VDD_330) @@ -635,6 +638,15 @@ sdhci_generic_resume(struct sdhci_slot *slot) return (0); } +uint32_t +sdhci_generic_min_freq(device_t brdev, struct sdhci_slot *slot) +{ + if (slot->version >= SDHCI_SPEC_300) + return (slot->max_clk / SDHCI_300_MAX_DIVIDER); + else + return (slot->max_clk / SDHCI_200_MAX_DIVIDER); +} + int sdhci_generic_update_ios(device_t brdev, device_t reqdev) { @@ -1078,8 +1090,12 @@ sdhci_data_irq(struct sdhci_slot *slot, uint32_t intmask) } if (intmask & SDHCI_INT_DATA_TIMEOUT) slot->curcmd->error = MMC_ERR_TIMEOUT; - else if (intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_END_BIT)) + else if (intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_END_BIT)) { + if (intmask & SDHCI_INT_DATA_CRC) { + panic("DATA CRC error\n"); + } slot->curcmd->error = MMC_ERR_BADCRC; + } if (slot->curcmd->data == NULL && (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | SDHCI_INT_DMA_END))) { @@ -1299,14 +1315,30 @@ sdhci_generic_write_ivar(device_t bus, device_t child, int which, uintptr_t valu break; case MMCBR_IVAR_CLOCK: if (value > 0) { - uint32_t clock = slot->max_clk; + uint32_t max_clock; + uint32_t clock; int i; - for (i = 0; i < 8; i++) { - if (clock <= value) - break; - clock >>= 1; + max_clock = slot->max_clk; + clock = max_clock; + + if (slot->version < SDHCI_SPEC_300) { + for (i = 0; i < SDHCI_200_MAX_DIVIDER; + i <<= 1) { + if (clock <= value) + break; + clock >>= 1; + } } + else { + for (i = 0; i < SDHCI_300_MAX_DIVIDER; + i += 2) { + if (clock <= value) + break; + clock = max_clock / (i + 2); + } + } + slot->host.ios.clock = clock; } else slot->host.ios.clock = 0; diff --git a/sys/dev/sdhci/sdhci.h b/sys/dev/sdhci/sdhci.h index 400f98ec700..31fbe6889f1 100644 --- a/sys/dev/sdhci/sdhci.h +++ b/sys/dev/sdhci/sdhci.h @@ -266,5 +266,6 @@ int sdhci_generic_get_ro(device_t brdev, device_t reqdev); int sdhci_generic_acquire_host(device_t brdev, device_t reqdev); int sdhci_generic_release_host(device_t brdev, device_t reqdev); void sdhci_generic_intr(struct sdhci_slot *slot); +uint32_t sdhci_generic_min_freq(device_t brdev, struct sdhci_slot *slot); #endif /* __SDHCI_H__ */ diff --git a/sys/dev/sdhci/sdhci_if.m b/sys/dev/sdhci/sdhci_if.m index cc8a7d39e28..b434fd29d94 100644 --- a/sys/dev/sdhci/sdhci_if.m +++ b/sys/dev/sdhci/sdhci_if.m @@ -58,7 +58,18 @@ # that mmc/sd card drivers call to make requests. # +#include +#include +#include +#include +#include + #include + +#include +#include +#include + CODE { struct sdhci_slot; } @@ -119,3 +130,8 @@ METHOD void write_multi_4 { uint32_t *data; bus_size_t count; } + +METHOD uint32_t min_freq { + device_t brdev; + struct sdhci_slot *slot; +} DEFAULT sdhci_generic_min_freq; From 7337a22fb00decfa1168eb8ffebfc1b5eec091d3 Mon Sep 17 00:00:00 2001 From: Oleksandr Tymoshenko Date: Sat, 16 Feb 2013 23:52:14 +0000 Subject: [PATCH 0221/1476] Disable debug accidentally enabled by previous commit --- sys/dev/sdhci/sdhci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/sdhci/sdhci.c b/sys/dev/sdhci/sdhci.c index 978eb55bcae..c89f60fc96a 100644 --- a/sys/dev/sdhci/sdhci.c +++ b/sys/dev/sdhci/sdhci.c @@ -65,7 +65,7 @@ struct sdhci_softc { static SYSCTL_NODE(_hw, OID_AUTO, sdhci, CTLFLAG_RD, 0, "sdhci driver"); -int sdhci_debug = 1; +int sdhci_debug = 0; TUNABLE_INT("hw.sdhci.debug", &sdhci_debug); SYSCTL_INT(_hw_sdhci, OID_AUTO, debug, CTLFLAG_RW, &sdhci_debug, 0, "Debug level"); From d3d7f709ce4264bfe28287329e524b5af30e2a88 Mon Sep 17 00:00:00 2001 From: Oleksandr Tymoshenko Date: Sun, 17 Feb 2013 00:23:42 +0000 Subject: [PATCH 0222/1476] - Add hw.bcm2835.sdhci.hs tunable to enable/disable highspeed mode in SDHCI driver Suggested by: Daisuke Aoyama - Set initilization sequence frequency to 8MHz. It should fix Data CRC errors. Standard requires initialization sequence to be executed at 400KHz but on this hardware low frequncies seems to cause Data CRC errors. Value was derived from analyzing hardware signals after Raspberry Pi is powered up. Before any data is read though DATA line adapter's clock frequency is changed to 8MHz. Modern cards should function fine at 8MHz but for older MMC cards it can be overriden by setting hw.bcm2835.sdhci.min_freq tunable. --- sys/arm/broadcom/bcm2835/bcm2835_sdhci.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c b/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c index 14422e25f80..1b099866f40 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c @@ -78,6 +78,12 @@ __FBSDID("$FreeBSD$"); #define dprintf(fmt, args...) #endif +static int bcm2835_sdhci_min_freq = 8000000; +static int bcm2835_sdhci_hs = 1; + +TUNABLE_INT("hw.bcm2835.sdhci.min_freq", &bcm2835_sdhci_min_freq); +TUNABLE_INT("hw.bcm2835.sdhci.hs", &bcm2835_sdhci_hs); + struct bcm_sdhci_dmamap_arg { bus_addr_t sc_dma_busaddr; }; @@ -180,7 +186,9 @@ bcm_sdhci_attach(device_t dev) goto fail; } - sc->sc_slot.caps = SDHCI_CAN_VDD_330 | SDHCI_CAN_VDD_180 | SDHCI_CAN_DO_HISPD; + sc->sc_slot.caps = SDHCI_CAN_VDD_330 | SDHCI_CAN_VDD_180; + if (bcm2835_sdhci_hs) + sc->sc_slot.caps |= SDHCI_CAN_DO_HISPD; sc->sc_slot.caps |= (default_freq << SDHCI_CLOCK_BASE_SHIFT); sc->sc_slot.quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL @@ -334,6 +342,19 @@ bcm_sdhci_write_multi_4(device_t dev, struct sdhci_slot *slot, bus_size_t off, bus_space_write_multi_4(sc->sc_bst, sc->sc_bsh, off, data, count); } +static uint32_t +bcm_sdhci_min_freq(device_t dev, struct sdhci_slot *slot) +{ + + /* + * Arasan HC seems to have problem with + * Data CRC on lower frequencies. Cap minimum + * frequncy at 8MHz (or whatever set via tunable) + * to work around this issue + */ + return bcm2835_sdhci_min_freq; +} + static device_method_t bcm_sdhci_methods[] = { /* Device interface */ DEVMETHOD(device_probe, bcm_sdhci_probe), @@ -353,6 +374,7 @@ static device_method_t bcm_sdhci_methods[] = { DEVMETHOD(mmcbr_release_host, sdhci_generic_release_host), /* SDHCI registers accessors */ + DEVMETHOD(sdhci_min_freq, bcm_sdhci_min_freq), DEVMETHOD(sdhci_read_1, bcm_sdhci_read_1), DEVMETHOD(sdhci_read_2, bcm_sdhci_read_2), DEVMETHOD(sdhci_read_4, bcm_sdhci_read_4), From 51a325a7f9986b553c3155accb422f65c6d9032f Mon Sep 17 00:00:00 2001 From: Marcel Moolenaar Date: Sun, 17 Feb 2013 00:51:34 +0000 Subject: [PATCH 0223/1476] Close a race relating to setting the PCPU pointer (r13). Register r13 points to the TLS in user space and points to the PCPU structure in the kernel. The race is the result of having the exception handler on the one hand and the RPC system call entry on the other. The EPC syscall path is non-atomic in that interrupts are enabled while the two stacks are switched. The register stack is switched last as that is the stack used to determine whether we're going back to user space by the exception handler. If we go back to user space, we restore r13, otherwise we leave r13 alone. The EPC syscall path however set r13 to the PCPU structure *before* switching the register stack, which means that there was a window in which the exception handler would restore r13 when it was already pointing to the PCPU structure. This is fatal when the exception happened on CPU x, but left from the exception on anotehr CPU. In that case r13 would point to the PCPU of the CPU the thread was running on. This immediately results in getting the wrong value for curthread. The fix is to make sure we assign r13 *after* we set ar.bspstore to point to the kernel register stack for the thread. --- sys/ia64/ia64/syscall.S | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sys/ia64/ia64/syscall.S b/sys/ia64/ia64/syscall.S index ef559e8bce1..84a03dae8a1 100644 --- a/sys/ia64/ia64/syscall.S +++ b/sys/ia64/ia64/syscall.S @@ -228,7 +228,7 @@ ENTRY_NOPROFILE(epc_syscall, 8) { .mmi mov r16=ar.rsc mov ar.rsc=0 - mov r17=r13 + nop 0 ;; } { .mmi @@ -239,13 +239,13 @@ ENTRY_NOPROFILE(epc_syscall, 8) ;; } { .mmi - mov r13=ar.k4 + mov r21=ar.unat add r30=-SIZEOF_TRAPFRAME,r14 mov r20=sp ;; } { .mii - mov r21=ar.unat + mov r17=r13 dep r30=0,r30,0,10 ;; add sp=-16,r30 @@ -258,10 +258,10 @@ ENTRY_NOPROFILE(epc_syscall, 8) add r31=8,r30 ;; } -{ .mii +{ .mmi + mov r13=ar.k4 mov r22=ar.fpsr sub r29=r14,r30 - nop 0 } { .mmi mov r23=ar.bsp From acbaa69f312968dd2ff85e79b8adf52a1c26ade4 Mon Sep 17 00:00:00 2001 From: Oleksandr Tymoshenko Date: Sun, 17 Feb 2013 01:34:25 +0000 Subject: [PATCH 0224/1476] Remove accidentally committed debug panic(9) call --- sys/dev/sdhci/sdhci.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sys/dev/sdhci/sdhci.c b/sys/dev/sdhci/sdhci.c index c89f60fc96a..1044bb64b3e 100644 --- a/sys/dev/sdhci/sdhci.c +++ b/sys/dev/sdhci/sdhci.c @@ -1090,12 +1090,8 @@ sdhci_data_irq(struct sdhci_slot *slot, uint32_t intmask) } if (intmask & SDHCI_INT_DATA_TIMEOUT) slot->curcmd->error = MMC_ERR_TIMEOUT; - else if (intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_END_BIT)) { - if (intmask & SDHCI_INT_DATA_CRC) { - panic("DATA CRC error\n"); - } + else if (intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_END_BIT)) slot->curcmd->error = MMC_ERR_BADCRC; - } if (slot->curcmd->data == NULL && (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | SDHCI_INT_DMA_END))) { From d7aa5f02d0b6501ba8b055ad31b16adf50538f1f Mon Sep 17 00:00:00 2001 From: Marcel Moolenaar Date: Sun, 17 Feb 2013 02:15:19 +0000 Subject: [PATCH 0225/1476] In kthr.c, obtain the address of the PCB for threads that were running on a core, when the core was stopped, by calling kgdb_trgt_core_pcb(). This has 2 advantages: 1. We don't need to include a machine-specific header anymore and as such kthr.c is truly machine independent. This allows the code to be used in a cross-debugger. 2. We don't need to lookup stoppcbs in generic code when it's an inherently target-spicific symbol. It does not exist for ia64. Implement kgdb_trgt_core_pcb() for all architectures, except ia64, by calling a common function called kgdb_trgt_stop_pcb(). This function differs from kgdb_trgt_core_pcb() in that it gets the size of the PCB structure as an argument and as such remains machine independent. On ia64 the PCB for stopped cores is in the PCPU structure itself. This for better scaling. The implementation of kgdb_trgt_core_pcb() for ia64 uses the cpuid_to_pcpu[] array to to obtain the address of the PCB structure. --- gnu/usr.bin/gdb/kgdb/kgdb.h | 2 ++ gnu/usr.bin/gdb/kgdb/kthr.c | 9 ++------- gnu/usr.bin/gdb/kgdb/trgt.c | 17 +++++++++++++++++ gnu/usr.bin/gdb/kgdb/trgt_amd64.c | 6 ++++++ gnu/usr.bin/gdb/kgdb/trgt_arm.c | 6 ++++++ gnu/usr.bin/gdb/kgdb/trgt_i386.c | 6 ++++++ gnu/usr.bin/gdb/kgdb/trgt_ia64.c | 12 ++++++++++++ gnu/usr.bin/gdb/kgdb/trgt_mips.c | 6 ++++++ gnu/usr.bin/gdb/kgdb/trgt_powerpc.c | 6 ++++++ gnu/usr.bin/gdb/kgdb/trgt_powerpc64.c | 6 ++++++ gnu/usr.bin/gdb/kgdb/trgt_sparc64.c | 6 ++++++ 11 files changed, 75 insertions(+), 7 deletions(-) diff --git a/gnu/usr.bin/gdb/kgdb/kgdb.h b/gnu/usr.bin/gdb/kgdb/kgdb.h index e828f56bbc7..1a32d8a125a 100644 --- a/gnu/usr.bin/gdb/kgdb/kgdb.h +++ b/gnu/usr.bin/gdb/kgdb/kgdb.h @@ -49,6 +49,8 @@ extern struct kthr *curkthr; void initialize_kld_target(void); void initialize_kgdb_target(void); void kgdb_dmesg(void); +CORE_ADDR kgdb_trgt_core_pcb(u_int); +CORE_ADDR kgdb_trgt_stop_pcb(u_int, u_int); void kgdb_trgt_new_objfile(struct objfile *); void kgdb_trgt_fetch_registers(int); void kgdb_trgt_store_registers(int); diff --git a/gnu/usr.bin/gdb/kgdb/kthr.c b/gnu/usr.bin/gdb/kgdb/kthr.c index b12d07c28e2..713b93b6895 100644 --- a/gnu/usr.bin/gdb/kgdb/kthr.c +++ b/gnu/usr.bin/gdb/kgdb/kthr.c @@ -44,12 +44,10 @@ __FBSDID("$FreeBSD$"); #include #include "kgdb.h" -#include static CORE_ADDR dumppcb; static int dumptid; -static CORE_ADDR stoppcbs; static cpuset_t stopped_cpus; static struct kthr *first; @@ -98,10 +96,9 @@ kgdb_thr_add_procs(uintptr_t paddr) kt->kaddr = addr; if (td.td_tid == dumptid) kt->pcb = dumppcb; - else if (td.td_state == TDS_RUNNING && stoppcbs != 0 && + else if (td.td_state == TDS_RUNNING && CPU_ISSET(td.td_oncpu, &stopped_cpus)) - kt->pcb = (uintptr_t)stoppcbs + - sizeof(struct pcb) * td.td_oncpu; + kt->pcb = kgdb_trgt_core_pcb(td.td_oncpu); else kt->pcb = (uintptr_t)td.td_pcb; kt->kstack = td.td_kstack; @@ -152,8 +149,6 @@ kgdb_thr_init(void) addr != 0) kvm_read(kvm, addr, &stopped_cpus, cpusetsize); - stoppcbs = kgdb_lookup("stoppcbs"); - kgdb_thr_add_procs(paddr); addr = kgdb_lookup("zombproc"); if (addr != 0) { diff --git a/gnu/usr.bin/gdb/kgdb/trgt.c b/gnu/usr.bin/gdb/kgdb/trgt.c index 14449b93af3..85065ccc383 100644 --- a/gnu/usr.bin/gdb/kgdb/trgt.c +++ b/gnu/usr.bin/gdb/kgdb/trgt.c @@ -53,6 +53,8 @@ __FBSDID("$FreeBSD$"); #include "kgdb.h" +static CORE_ADDR stoppcbs; + static void kgdb_core_cleanup(void *); static char *vmcore; @@ -352,3 +354,18 @@ initialize_kgdb_target(void) add_com ("tid", class_obscure, kgdb_set_tid_cmd, "Set current thread context"); } + +CORE_ADDR +kgdb_trgt_stop_pcb(u_int cpuid, u_int pcbsz) +{ + static int once = 0; + + if (stoppcbs == 0 && !once) { + once = 1; + stoppcbs = kgdb_lookup("stoppcbs"); + } + if (stoppcbs == 0) + return 0; + + return (stoppcbs + pcbsz * cpuid); +} diff --git a/gnu/usr.bin/gdb/kgdb/trgt_amd64.c b/gnu/usr.bin/gdb/kgdb/trgt_amd64.c index cdab77538af..cb13d7172a6 100644 --- a/gnu/usr.bin/gdb/kgdb/trgt_amd64.c +++ b/gnu/usr.bin/gdb/kgdb/trgt_amd64.c @@ -44,6 +44,12 @@ __FBSDID("$FreeBSD$"); #include "kgdb.h" +CORE_ADDR +kgdb_trgt_core_pcb(u_int cpuid) +{ + return (kgdb_trgt_stop_pcb(cpuid, sizeof(struct pcb))); +} + void kgdb_trgt_fetch_registers(int regno __unused) { diff --git a/gnu/usr.bin/gdb/kgdb/trgt_arm.c b/gnu/usr.bin/gdb/kgdb/trgt_arm.c index f2e292e5735..ca18ae3696a 100644 --- a/gnu/usr.bin/gdb/kgdb/trgt_arm.c +++ b/gnu/usr.bin/gdb/kgdb/trgt_arm.c @@ -47,6 +47,12 @@ __FBSDID("$FreeBSD$"); #include "kgdb.h" +CORE_ADDR +kgdb_trgt_core_pcb(u_int cpuid) +{ + return (kgdb_trgt_stop_pcb(cpuid, sizeof(struct pcb))); +} + void kgdb_trgt_fetch_registers(int regno __unused) { diff --git a/gnu/usr.bin/gdb/kgdb/trgt_i386.c b/gnu/usr.bin/gdb/kgdb/trgt_i386.c index aba8b658634..02c99182fcf 100644 --- a/gnu/usr.bin/gdb/kgdb/trgt_i386.c +++ b/gnu/usr.bin/gdb/kgdb/trgt_i386.c @@ -49,6 +49,12 @@ __FBSDID("$FreeBSD$"); static int ofs_fix; +CORE_ADDR +kgdb_trgt_core_pcb(u_int cpuid) +{ + return (kgdb_trgt_stop_pcb(cpuid, sizeof(struct pcb))); +} + void kgdb_trgt_fetch_registers(int regno __unused) { diff --git a/gnu/usr.bin/gdb/kgdb/trgt_ia64.c b/gnu/usr.bin/gdb/kgdb/trgt_ia64.c index 4efa6eb5f6c..6ba800bd014 100644 --- a/gnu/usr.bin/gdb/kgdb/trgt_ia64.c +++ b/gnu/usr.bin/gdb/kgdb/trgt_ia64.c @@ -52,6 +52,18 @@ __FBSDID("$FreeBSD$"); #include "kgdb.h" +CORE_ADDR +kgdb_trgt_core_pcb(u_int cpuid) +{ + CORE_ADDR addr; + char *expr; + + asprintf(&expr, "&cpuid_to_pcpu[%d]->pc_md.pcb", cpuid); + addr = kgdb_parse(expr); + free(expr); + return (addr); +} + void kgdb_trgt_fetch_registers(int regno __unused) { diff --git a/gnu/usr.bin/gdb/kgdb/trgt_mips.c b/gnu/usr.bin/gdb/kgdb/trgt_mips.c index 423cacd8a06..6ad2274681e 100644 --- a/gnu/usr.bin/gdb/kgdb/trgt_mips.c +++ b/gnu/usr.bin/gdb/kgdb/trgt_mips.c @@ -52,6 +52,12 @@ __FBSDID("$FreeBSD$"); #include "kgdb.h" +CORE_ADDR +kgdb_trgt_core_pcb(u_int cpuid) +{ + return (kgdb_trgt_stop_pcb(cpuid, sizeof(struct pcb))); +} + void kgdb_trgt_fetch_registers(int regno __unused) { diff --git a/gnu/usr.bin/gdb/kgdb/trgt_powerpc.c b/gnu/usr.bin/gdb/kgdb/trgt_powerpc.c index a83c2d0a31c..ef8d7f18011 100644 --- a/gnu/usr.bin/gdb/kgdb/trgt_powerpc.c +++ b/gnu/usr.bin/gdb/kgdb/trgt_powerpc.c @@ -49,6 +49,12 @@ __FBSDID("$FreeBSD$"); #include "kgdb.h" +CORE_ADDR +kgdb_trgt_core_pcb(u_int cpuid) +{ + return (kgdb_trgt_stop_pcb(cpuid, sizeof(struct pcb))); +} + void kgdb_trgt_fetch_registers(int regno __unused) { diff --git a/gnu/usr.bin/gdb/kgdb/trgt_powerpc64.c b/gnu/usr.bin/gdb/kgdb/trgt_powerpc64.c index d20a4d6afc8..65f7ab53810 100644 --- a/gnu/usr.bin/gdb/kgdb/trgt_powerpc64.c +++ b/gnu/usr.bin/gdb/kgdb/trgt_powerpc64.c @@ -44,6 +44,12 @@ __FBSDID("$FreeBSD$"); #include "kgdb.h" +CORE_ADDR +kgdb_trgt_core_pcb(u_int cpuid) +{ + return (kgdb_trgt_stop_pcb(cpuid, sizeof(struct pcb))); +} + void kgdb_trgt_fetch_registers(int regno __unused) { diff --git a/gnu/usr.bin/gdb/kgdb/trgt_sparc64.c b/gnu/usr.bin/gdb/kgdb/trgt_sparc64.c index 8fece2419a9..070194a7500 100644 --- a/gnu/usr.bin/gdb/kgdb/trgt_sparc64.c +++ b/gnu/usr.bin/gdb/kgdb/trgt_sparc64.c @@ -46,6 +46,12 @@ __FBSDID("$FreeBSD$"); #include "kgdb.h" +CORE_ADDR +kgdb_trgt_core_pcb(u_int cpuid) +{ + return (kgdb_trgt_stop_pcb(cpuid, sizeof(struct pcb))); +} + void kgdb_trgt_fetch_registers(int regno __unused) { From 17001e0b94ef19d53e04c7476f3ff5e04c080d77 Mon Sep 17 00:00:00 2001 From: David Xu Date: Sun, 17 Feb 2013 02:52:42 +0000 Subject: [PATCH 0226/1476] Make more code be protected by internal mutex, and now it is fork-safe, in error case, the file exclusive lock is now released as soon as possible, in previous code, child process can still hold the exclusive lock. --- lib/libc/gen/sem_new.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/libc/gen/sem_new.c b/lib/libc/gen/sem_new.c index 0393face489..1bf84ea3645 100644 --- a/lib/libc/gen/sem_new.c +++ b/lib/libc/gen/sem_new.c @@ -229,18 +229,18 @@ _sem_open(const char *name, int flags, ...) ni->open_count = 1; ni->sem = sem; LIST_INSERT_HEAD(&sem_list, ni, next); - _pthread_mutex_unlock(&sem_llock); _close(fd); + _pthread_mutex_unlock(&sem_llock); return (sem); error: errsave = errno; - _pthread_mutex_unlock(&sem_llock); if (fd != -1) _close(fd); if (sem != NULL) munmap(sem, sizeof(sem_t)); free(ni); + _pthread_mutex_unlock(&sem_llock); errno = errsave; return (SEM_FAILED); } From f8e4e36a0a75f35ef23acbd5a52ec644bb294be8 Mon Sep 17 00:00:00 2001 From: Luigi Rizzo Date: Sun, 17 Feb 2013 04:43:22 +0000 Subject: [PATCH 0227/1476] update the netmap example programs merging some common code in nm_util.c pkt-gen now implements several functions (unlimited transmit, receive, ping-pong) and can operate on a 'tap' device. --- tools/tools/netmap/Makefile | 9 +- tools/tools/netmap/bridge.c | 235 +------ tools/tools/netmap/nm_util.c | 251 +++++++ tools/tools/netmap/nm_util.h | 183 +++++ tools/tools/netmap/pcap.c | 337 +++------ tools/tools/netmap/pkt-gen.c | 1286 ++++++++++++++++++++++------------ 6 files changed, 1368 insertions(+), 933 deletions(-) create mode 100644 tools/tools/netmap/nm_util.c create mode 100644 tools/tools/netmap/nm_util.h diff --git a/tools/tools/netmap/Makefile b/tools/tools/netmap/Makefile index 4b682e52a31..2593a27175e 100644 --- a/tools/tools/netmap/Makefile +++ b/tools/tools/netmap/Makefile @@ -5,7 +5,7 @@ # we can just define 'progs' and create custom targets. PROGS = pkt-gen bridge testpcap libnetmap.so -CLEANFILES = $(PROGS) pcap.o +CLEANFILES = $(PROGS) pcap.o nm_util.o NO_MAN= CFLAGS += -Werror -Wall -nostdinc -I/usr/include -I../../../sys CFLAGS += -Wextra @@ -17,9 +17,12 @@ LDFLAGS += -lpthread -lpcap all: $(PROGS) +pkt-gen bridge: nm_util.o + $(CC) $(CFLAGS) -o ${.TARGET} ${.TARGET:=.c} nm_util.o $(LDFLAGS) + testpcap: pcap.c libnetmap.so - $(CC) $(CFLAGS) -L. -lnetmap -o ${.TARGET} pcap.c + $(CC) $(CFLAGS) -DTEST -L. -lnetmap -o ${.TARGET} pcap.c -libnetmap.so: pcap.c +libnetmap.so: pcap.c nm_util.c $(CC) $(CFLAGS) -fpic -c ${.ALLSRC} $(CC) -shared -o ${.TARGET} ${.ALLSRC:.c=.o} diff --git a/tools/tools/netmap/bridge.c b/tools/tools/netmap/bridge.c index 0e9e4421642..473ee0c70e5 100644 --- a/tools/tools/netmap/bridge.c +++ b/tools/tools/netmap/bridge.c @@ -9,195 +9,24 @@ * $FreeBSD$ */ -#include -#include /* signal */ -#include -#include -#include /* strcmp */ -#include /* open */ -#include /* close */ +#include "nm_util.h" -#include /* le64toh */ -#include /* PROT_* */ -#include /* ioctl */ -#include -#include -#include /* sockaddr.. */ -#include /* ntohs */ - -#include /* ifreq */ -#include -#include -#include - -#include /* sockaddr_in */ - -#define MIN(a, b) ((a) < (b) ? (a) : (b)) int verbose = 0; -/* debug support */ -#define ND(format, ...) {} -#define D(format, ...) do { \ - if (!verbose) break; \ - struct timeval _xxts; \ - gettimeofday(&_xxts, NULL); \ - fprintf(stderr, "%03d.%06d %s [%d] " format "\n", \ - (int)_xxts.tv_sec %1000, (int)_xxts.tv_usec, \ - __FUNCTION__, __LINE__, ##__VA_ARGS__); \ - } while (0) - - -char *version = "$Id: bridge.c 10857 2012-04-06 12:18:22Z luigi $"; +char *version = "$Id: bridge.c 12016 2013-01-23 17:24:22Z luigi $"; static int do_abort = 0; -/* - * info on a ring we handle - */ -struct my_ring { - const char *ifname; - int fd; - char *mem; /* userspace mmap address */ - u_int memsize; - u_int queueid; - u_int begin, end; /* first..last+1 rings to check */ - struct netmap_if *nifp; - struct netmap_ring *tx, *rx; /* shortcuts */ - - uint32_t if_flags; - uint32_t if_reqcap; - uint32_t if_curcap; -}; - static void -sigint_h(__unused int sig) +sigint_h(int sig) { + (void)sig; /* UNUSED */ do_abort = 1; signal(SIGINT, SIG_DFL); } -static int -do_ioctl(struct my_ring *me, unsigned long what) -{ - struct ifreq ifr; - int error; - - bzero(&ifr, sizeof(ifr)); - strncpy(ifr.ifr_name, me->ifname, sizeof(ifr.ifr_name)); - switch (what) { - case SIOCSIFFLAGS: - ifr.ifr_flagshigh = me->if_flags >> 16; - ifr.ifr_flags = me->if_flags & 0xffff; - break; - case SIOCSIFCAP: - ifr.ifr_reqcap = me->if_reqcap; - ifr.ifr_curcap = me->if_curcap; - break; - } - error = ioctl(me->fd, what, &ifr); - if (error) { - D("ioctl error 0x%lx", what); - return error; - } - switch (what) { - case SIOCGIFFLAGS: - me->if_flags = (ifr.ifr_flagshigh << 16) | - (0xffff & ifr.ifr_flags); - if (verbose) - D("flags are 0x%x", me->if_flags); - break; - - case SIOCGIFCAP: - me->if_reqcap = ifr.ifr_reqcap; - me->if_curcap = ifr.ifr_curcap; - if (verbose) - D("curcap are 0x%x", me->if_curcap); - break; - } - return 0; -} - -/* - * open a device. if me->mem is null then do an mmap. - */ -static int -netmap_open(struct my_ring *me, int ringid) -{ - int fd, err, l; - struct nmreq req; - - me->fd = fd = open("/dev/netmap", O_RDWR); - if (fd < 0) { - D("Unable to open /dev/netmap"); - return (-1); - } - bzero(&req, sizeof(req)); - strncpy(req.nr_name, me->ifname, sizeof(req.nr_name)); - req.nr_ringid = ringid; - req.nr_version = NETMAP_API; - err = ioctl(fd, NIOCGINFO, &req); - if (err) { - D("cannot get info on %s", me->ifname); - goto error; - } - me->memsize = l = req.nr_memsize; - if (verbose) - D("memsize is %d MB", l>>20); - err = ioctl(fd, NIOCREGIF, &req); - if (err) { - D("Unable to register %s", me->ifname); - goto error; - } - - if (me->mem == NULL) { - me->mem = mmap(0, l, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0); - if (me->mem == MAP_FAILED) { - D("Unable to mmap"); - me->mem = NULL; - goto error; - } - } - - me->nifp = NETMAP_IF(me->mem, req.nr_offset); - me->queueid = ringid; - if (ringid & NETMAP_SW_RING) { - me->begin = req.nr_rx_rings; - me->end = me->begin + 1; - me->tx = NETMAP_TXRING(me->nifp, req.nr_tx_rings); - me->rx = NETMAP_RXRING(me->nifp, req.nr_rx_rings); - } else if (ringid & NETMAP_HW_RING) { - D("XXX check multiple threads"); - me->begin = ringid & NETMAP_RING_MASK; - me->end = me->begin + 1; - me->tx = NETMAP_TXRING(me->nifp, me->begin); - me->rx = NETMAP_RXRING(me->nifp, me->begin); - } else { - me->begin = 0; - me->end = req.nr_rx_rings; // XXX max of the two - me->tx = NETMAP_TXRING(me->nifp, 0); - me->rx = NETMAP_RXRING(me->nifp, 0); - } - return (0); -error: - close(me->fd); - return -1; -} - - -static int -netmap_close(struct my_ring *me) -{ - D(""); - if (me->mem) - munmap(me->mem, me->memsize); - ioctl(me->fd, NIOCUNREGIF, NULL); - close(me->fd); - return (0); -} - - /* * move up to 'limit' pkts from rxring to txring swapping buffers. */ @@ -237,7 +66,7 @@ process_rings(struct netmap_ring *rxring, struct netmap_ring *txring, if (rs->len < 14 || rs->len > 2048) D("wrong len %d rx[%d] -> tx[%d]", rs->len, j, k); else if (verbose > 1) - D("send len %d rx[%d] -> tx[%d]", rs->len, j, k); + D("%s send len %d rx[%d] -> tx[%d]", msg, rs->len, j, k); ts->len = rs->len; /* report the buffer change. */ @@ -251,7 +80,7 @@ process_rings(struct netmap_ring *rxring, struct netmap_ring *txring, rxring->cur = j; txring->cur = k; if (verbose && m > 0) - D("sent %d packets to %p", m, txring); + D("%s sent %d packets to %p", msg, m, txring); return (m); } @@ -287,7 +116,7 @@ move(struct my_ring *src, struct my_ring *dst, u_int limit) * how many packets on this set of queues ? */ static int -howmany(struct my_ring *me, int tx) +pkt_queued(struct my_ring *me, int tx) { u_int i, tot = 0; @@ -337,6 +166,7 @@ main(int argc, char **argv) while ( (ch = getopt(argc, argv, "b:i:vw:")) != -1) { switch (ch) { + default: D("bad option %c %s", ch, optarg); usage(); break; @@ -361,6 +191,7 @@ main(int argc, char **argv) } } + argc -= optind; argv += optind; @@ -394,44 +225,12 @@ main(int argc, char **argv) /* two different interfaces. Take all rings on if1 */ i = 0; // all hw rings } - if (netmap_open(me, i)) + if (netmap_open(me, i, 1)) return (1); me[1].mem = me[0].mem; /* copy the pointer, so only one mmap */ - if (netmap_open(me+1, 0)) + if (netmap_open(me+1, 0, 1)) return (1); - /* if bridging two interfaces, set promisc mode */ - if (i != NETMAP_SW_RING) { - do_ioctl(me, SIOCGIFFLAGS); - if ((me[0].if_flags & IFF_UP) == 0) { - D("%s is down, bringing up...", me[0].ifname); - me[0].if_flags |= IFF_UP; - } - me[0].if_flags |= IFF_PPROMISC; - do_ioctl(me, SIOCSIFFLAGS); - - do_ioctl(me+1, SIOCGIFFLAGS); - me[1].if_flags |= IFF_PPROMISC; - do_ioctl(me+1, SIOCSIFFLAGS); - - /* also disable checksums etc. */ - do_ioctl(me, SIOCGIFCAP); - me[0].if_reqcap = me[0].if_curcap; - me[0].if_reqcap &= ~(IFCAP_HWCSUM | IFCAP_TSO | IFCAP_TOE); - do_ioctl(me+0, SIOCSIFCAP); - } - do_ioctl(me+1, SIOCGIFFLAGS); - if ((me[1].if_flags & IFF_UP) == 0) { - D("%s is down, bringing up...", me[1].ifname); - me[1].if_flags |= IFF_UP; - } - do_ioctl(me+1, SIOCSIFFLAGS); - - do_ioctl(me+1, SIOCGIFCAP); - me[1].if_reqcap = me[1].if_curcap; - me[1].if_reqcap &= ~(IFCAP_HWCSUM | IFCAP_TSO | IFCAP_TOE); - do_ioctl(me+1, SIOCSIFCAP); - /* setup poll(2) variables. */ memset(pollfd, 0, sizeof(pollfd)); for (i = 0; i < 2; i++) { @@ -451,8 +250,8 @@ main(int argc, char **argv) int n0, n1, ret; pollfd[0].events = pollfd[1].events = 0; pollfd[0].revents = pollfd[1].revents = 0; - n0 = howmany(me, 0); - n1 = howmany(me + 1, 0); + n0 = pkt_queued(me, 0); + n1 = pkt_queued(me + 1, 0); if (n0) pollfd[1].events |= POLLOUT; else @@ -468,14 +267,14 @@ main(int argc, char **argv) ret <= 0 ? "timeout" : "ok", pollfd[0].events, pollfd[0].revents, - howmany(me, 0), + pkt_queued(me, 0), me[0].rx->cur, - howmany(me, 1), + pkt_queued(me, 1), pollfd[1].events, pollfd[1].revents, - howmany(me+1, 0), + pkt_queued(me+1, 0), me[1].rx->cur, - howmany(me+1, 1) + pkt_queued(me+1, 1) ); if (ret < 0) continue; diff --git a/tools/tools/netmap/nm_util.c b/tools/tools/netmap/nm_util.c new file mode 100644 index 00000000000..2b2c0ca3f6a --- /dev/null +++ b/tools/tools/netmap/nm_util.c @@ -0,0 +1,251 @@ +/* + * Copyright (C) 2012 Luigi Rizzo. 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$ + * $Id$ + * + * utilities to use netmap devices. + * This does the basic functions of opening a device and issuing + * ioctls() + */ + +#include "nm_util.h" + +extern int verbose; + +int +nm_do_ioctl(struct my_ring *me, u_long what, int subcmd) +{ + struct ifreq ifr; + int error; +#if defined( __FreeBSD__ ) || defined (__APPLE__) + int fd = me->fd; +#endif +#ifdef linux + struct ethtool_value eval; + int fd; + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + printf("Error: cannot get device control socket.\n"); + return -1; + } +#endif /* linux */ + + (void)subcmd; // unused + bzero(&ifr, sizeof(ifr)); + strncpy(ifr.ifr_name, me->ifname, sizeof(ifr.ifr_name)); + switch (what) { + case SIOCSIFFLAGS: +#ifndef __APPLE__ + ifr.ifr_flagshigh = me->if_flags >> 16; +#endif + ifr.ifr_flags = me->if_flags & 0xffff; + break; + +#if defined( __FreeBSD__ ) + case SIOCSIFCAP: + ifr.ifr_reqcap = me->if_reqcap; + ifr.ifr_curcap = me->if_curcap; + break; +#endif +#ifdef linux + case SIOCETHTOOL: + eval.cmd = subcmd; + eval.data = 0; + ifr.ifr_data = (caddr_t)&eval; + break; +#endif /* linux */ + } + error = ioctl(fd, what, &ifr); + if (error) + goto done; + switch (what) { + case SIOCGIFFLAGS: +#ifndef __APPLE__ + me->if_flags = (ifr.ifr_flagshigh << 16) | + (0xffff & ifr.ifr_flags); +#endif + if (verbose) + D("flags are 0x%x", me->if_flags); + break; + +#if defined( __FreeBSD__ ) + case SIOCGIFCAP: + me->if_reqcap = ifr.ifr_reqcap; + me->if_curcap = ifr.ifr_curcap; + if (verbose) + D("curcap are 0x%x", me->if_curcap); + break; +#endif /* __FreeBSD__ */ + } +done: +#ifdef linux + close(fd); +#endif + if (error) + D("ioctl error %d %lu", error, what); + return error; +} + +/* + * open a device. if me->mem is null then do an mmap. + * Returns the file descriptor. + * The extra flag checks configures promisc mode. + */ +int +netmap_open(struct my_ring *me, int ringid, int promisc) +{ + int fd, err, l; + struct nmreq req; + + me->fd = fd = open("/dev/netmap", O_RDWR); + if (fd < 0) { + D("Unable to open /dev/netmap"); + return (-1); + } + bzero(&req, sizeof(req)); + req.nr_version = NETMAP_API; + strncpy(req.nr_name, me->ifname, sizeof(req.nr_name)); + req.nr_ringid = ringid; + err = ioctl(fd, NIOCGINFO, &req); + if (err) { + D("cannot get info on %s, errno %d ver %d", + me->ifname, errno, req.nr_version); + goto error; + } + me->memsize = l = req.nr_memsize; + if (verbose) + D("memsize is %d MB", l>>20); + err = ioctl(fd, NIOCREGIF, &req); + if (err) { + D("Unable to register %s", me->ifname); + goto error; + } + + if (me->mem == NULL) { + me->mem = mmap(0, l, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0); + if (me->mem == MAP_FAILED) { + D("Unable to mmap"); + me->mem = NULL; + goto error; + } + } + + + /* Set the operating mode. */ + if (ringid != NETMAP_SW_RING) { + nm_do_ioctl(me, SIOCGIFFLAGS, 0); + if ((me[0].if_flags & IFF_UP) == 0) { + D("%s is down, bringing up...", me[0].ifname); + me[0].if_flags |= IFF_UP; + } + if (promisc) { + me[0].if_flags |= IFF_PPROMISC; + nm_do_ioctl(me, SIOCSIFFLAGS, 0); + } + +#ifdef __FreeBSD__ + /* also disable checksums etc. */ + nm_do_ioctl(me, SIOCGIFCAP, 0); + me[0].if_reqcap = me[0].if_curcap; + me[0].if_reqcap &= ~(IFCAP_HWCSUM | IFCAP_TSO | IFCAP_TOE); + nm_do_ioctl(me+0, SIOCSIFCAP, 0); +#endif +#ifdef linux + /* disable: + * - generic-segmentation-offload + * - tcp-segmentation-offload + * - rx-checksumming + * - tx-checksumming + * XXX check how to set back the caps. + */ + nm_do_ioctl(me, SIOCETHTOOL, ETHTOOL_SGSO); + nm_do_ioctl(me, SIOCETHTOOL, ETHTOOL_STSO); + nm_do_ioctl(me, SIOCETHTOOL, ETHTOOL_SRXCSUM); + nm_do_ioctl(me, SIOCETHTOOL, ETHTOOL_STXCSUM); +#endif /* linux */ + } + + me->nifp = NETMAP_IF(me->mem, req.nr_offset); + me->queueid = ringid; + if (ringid & NETMAP_SW_RING) { + me->begin = req.nr_rx_rings; + me->end = me->begin + 1; + me->tx = NETMAP_TXRING(me->nifp, req.nr_tx_rings); + me->rx = NETMAP_RXRING(me->nifp, req.nr_rx_rings); + } else if (ringid & NETMAP_HW_RING) { + D("XXX check multiple threads"); + me->begin = ringid & NETMAP_RING_MASK; + me->end = me->begin + 1; + me->tx = NETMAP_TXRING(me->nifp, me->begin); + me->rx = NETMAP_RXRING(me->nifp, me->begin); + } else { + me->begin = 0; + me->end = req.nr_rx_rings; // XXX max of the two + me->tx = NETMAP_TXRING(me->nifp, 0); + me->rx = NETMAP_RXRING(me->nifp, 0); + } + return (0); +error: + close(me->fd); + return -1; +} + + +int +netmap_close(struct my_ring *me) +{ + D(""); + if (me->mem) + munmap(me->mem, me->memsize); + ioctl(me->fd, NIOCUNREGIF, NULL); + close(me->fd); + return (0); +} + + +/* + * how many packets on this set of queues ? + */ +int +pkt_queued(struct my_ring *me, int tx) +{ + u_int i, tot = 0; + + ND("me %p begin %d end %d", me, me->begin, me->end); + for (i = me->begin; i < me->end; i++) { + struct netmap_ring *ring = tx ? + NETMAP_TXRING(me->nifp, i) : NETMAP_RXRING(me->nifp, i); + tot += ring->avail; + } + if (0 && verbose && tot && !tx) + D("ring %s %s %s has %d avail at %d", + me->ifname, tx ? "tx": "rx", + me->end >= me->nifp->ni_tx_rings ? // XXX who comes first ? + "host":"net", + tot, NETMAP_TXRING(me->nifp, me->begin)->cur); + return tot; +} diff --git a/tools/tools/netmap/nm_util.h b/tools/tools/netmap/nm_util.h new file mode 100644 index 00000000000..0d64f131f28 --- /dev/null +++ b/tools/tools/netmap/nm_util.h @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2012 Luigi Rizzo. 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$ + * $Id$ + * + * Some utilities to build netmap-based programs. + */ + +#ifndef _NM_UTIL_H +#define _NM_UTIL_H +#include +#include /* signal */ +#include +#include +#include /* PRI* macros */ +#include /* strcmp */ +#include /* open */ +#include /* close */ +#include /* getifaddrs */ + +#include /* PROT_* */ +#include /* ioctl */ +#include +#include /* sockaddr.. */ +#include /* ntohs */ +#include +#include /* sysctl */ +#include /* timersub */ + +#include +#include /* ifreq */ + +#include +#include +#include + +#include +#include + +#ifndef MY_PCAP /* use the system's pcap if available */ + +#ifdef NO_PCAP +#define PCAP_ERRBUF_SIZE 512 +typedef void pcap_t; +struct pcap_pkthdr; +#define pcap_inject(a,b,c) ((void)a, (void)b, (void)c, -1) +#define pcap_dispatch(a, b, c, d) (void)c +#define pcap_open_live(a, b, c, d, e) ((void)e, NULL) +#else /* !NO_PCAP */ +#include // XXX do we need it ? +#endif /* !NO_PCAP */ + +#endif // XXX hack + +#include /* pthread_* */ + +#ifdef linux +#define ifr_flagshigh ifr_flags +#define ifr_curcap ifr_flags +#define ifr_reqcap ifr_flags +#define IFF_PPROMISC IFF_PROMISC +#include +#include + +#define CLOCK_REALTIME_PRECISE CLOCK_REALTIME +#include /* ether_aton */ +#include /* sockaddr_ll */ +#endif /* linux */ + +#ifdef __FreeBSD__ +#include /* le64toh */ +#include + +#include /* pthread w/ affinity */ +#include /* cpu_set */ +#include /* LLADDR */ +#endif /* __FreeBSD__ */ + +#ifdef __APPLE__ +#define ifr_flagshigh ifr_flags // XXX +#define IFF_PPROMISC IFF_PROMISC +#include /* LLADDR */ +#define clock_gettime(a,b) \ + do {struct timespec t0 = {0,0}; *(b) = t0; } while (0) +#endif /* __APPLE__ */ + +static inline int min(int a, int b) { return a < b ? a : b; } +extern int time_second; + +/* debug support */ +#define ND(format, ...) do {} while(0) +#define D(format, ...) \ + fprintf(stderr, "%s [%d] " format "\n", \ + __FUNCTION__, __LINE__, ##__VA_ARGS__) + +#define RD(lps, format, ...) \ + do { \ + static int t0, cnt; \ + if (t0 != time_second) { \ + t0 = time_second; \ + cnt = 0; \ + } \ + if (cnt++ < lps) \ + D(format, ##__VA_ARGS__); \ + } while (0) + + + +// XXX does it work on 32-bit machines ? +static inline void prefetch (const void *x) +{ + __asm volatile("prefetcht0 %0" :: "m" (*(const unsigned long *)x)); +} + +// XXX only for multiples of 64 bytes, non overlapped. +static inline void +pkt_copy(const void *_src, void *_dst, int l) +{ + const uint64_t *src = _src; + uint64_t *dst = _dst; +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) + if (unlikely(l >= 1024)) { + bcopy(src, dst, l); + return; + } + for (; l > 0; l-=64) { + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + } +} + +/* + * info on a ring we handle + */ +struct my_ring { + const char *ifname; + int fd; + char *mem; /* userspace mmap address */ + u_int memsize; + u_int queueid; + u_int begin, end; /* first..last+1 rings to check */ + struct netmap_if *nifp; + struct netmap_ring *tx, *rx; /* shortcuts */ + + uint32_t if_flags; + uint32_t if_reqcap; + uint32_t if_curcap; +}; +int netmap_open(struct my_ring *me, int ringid, int promisc); +int netmap_close(struct my_ring *me); +int nm_do_ioctl(struct my_ring *me, u_long what, int subcmd); +#endif /* _NM_UTIL_H */ diff --git a/tools/tools/netmap/pcap.c b/tools/tools/netmap/pcap.c index 2125176b623..c2acd1a4b4e 100644 --- a/tools/tools/netmap/pcap.c +++ b/tools/tools/netmap/pcap.c @@ -1,5 +1,5 @@ /* - * (C) 2011 Luigi Rizzo + * (C) 2011-2012 Luigi Rizzo * * BSD license * @@ -10,81 +10,18 @@ * $FreeBSD$ */ -#include -#include /* signal */ -#include -#include -#include /* strcmp */ -#include /* open */ -#include /* close */ +#define MY_PCAP +#include "nm_util.h" -#include /* le64toh */ -#include /* PROT_* */ -#include /* ioctl */ -#include -#include -#include /* sockaddr.. */ -#include /* ntohs */ - -#include /* ifreq */ -#include -#include -#include - -#include /* sockaddr_in */ - -#include -#include - -#define MIN(a, b) ((a) < (b) ? (a) : (b)) - -const char *version = "$Id$"; +char *version = "$Id: pcap.c 11463 2012-07-30 15:26:02Z luigi $"; int verbose = 0; -/* debug support */ -#define ND(format, ...) do {} while (0) -#define D(format, ...) do { \ - if (verbose) \ - fprintf(stderr, "--- %s [%d] " format "\n", \ - __FUNCTION__, __LINE__, ##__VA_ARGS__); \ - } while (0) - -static inline void prefetch (const void *x) -{ - __asm volatile("prefetcht0 %0" :: "m" (*(const unsigned long *)x)); -} - -// XXX only for multiples of 64 bytes, non overlapped. -static inline void -pkt_copy(const void *_src, void *_dst, int l) -{ - const uint64_t *src = _src; - uint64_t *dst = _dst; -#define likely(x) __builtin_expect(!!(x), 1) -#define unlikely(x) __builtin_expect(!!(x), 0) - if (unlikely(l >= 1024)) { - bcopy(src, dst, l); - return; - } - for (; l > 0; l-=64) { - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - } -} - /* * We redefine here a number of structures that are in pcap.h * so we can compile this file without the system header. */ #ifndef PCAP_ERRBUF_SIZE #define PCAP_ERRBUF_SIZE 128 - /* * Each packet is accompanied by a header including the timestamp, * captured size and actual size. @@ -135,12 +72,13 @@ typedef enum { PCAP_D_OUT } pcap_direction_t; -struct bpf_program; typedef void (*pcap_handler)(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes); +char errbuf[PCAP_ERRBUF_SIZE]; + pcap_t *pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, char *errbuf); @@ -154,24 +92,6 @@ char *pcap_lookupdev(char *errbuf); int pcap_inject(pcap_t *p, const void *buf, size_t size); int pcap_fileno(pcap_t *p); const char *pcap_lib_version(void); -void pcap_freealldevs(pcap_if_t *); -pcap_t *pcap_create(const char *, char *); -int pcap_activate(pcap_t *); -int pcap_can_set_rfmon(pcap_t *); -int pcap_set_snaplen(pcap_t *, int); -int pcap_snapshot(pcap_t *); -int pcap_lookupnet(const char *, uint32_t *, uint32_t *, char *); -int pcap_set_promisc(pcap_t *, int); -int pcap_set_timeout(pcap_t *, int); -int pcap_compile(pcap_t *, struct bpf_program *, const char *, int, - uint32_t); -int pcap_setfilter(pcap_t *, struct bpf_program *); -int pcap_datalink(pcap_t *); -const char *pcap_datalink_val_to_name(int); -const char *pcap_datalink_val_to_description(int); -int pcap_stats(pcap_t *, struct pcap_stat *); -int pcap_loop(pcap_t *, int, pcap_handler, u_char *); -char *pcap_geterr(pcap_t *); struct eproto { @@ -180,7 +100,7 @@ struct eproto { }; #endif /* !PCAP_ERRBUF_SIZE */ -#ifdef __PIC__ +#ifndef TEST /* * build as a shared library */ @@ -190,8 +110,12 @@ char pcap_version[] = "libnetmap version 0.3"; /* * Our equivalent of pcap_t */ -struct my_ring { - struct nmreq nmr; +struct pcap_ring { + struct my_ring me; +#if 0 + const char *ifname; + + //struct nmreq nmr; int fd; char *mem; /* userspace mmap address */ @@ -200,6 +124,10 @@ struct my_ring { u_int begin, end; /* first..last+1 rings to check */ struct netmap_if *nifp; + uint32_t if_flags; + uint32_t if_reqcap; + uint32_t if_curcap; +#endif int snaplen; char *errbuf; int promisc; @@ -207,9 +135,6 @@ struct my_ring { struct pcap_pkthdr hdr; - uint32_t if_flags; - uint32_t if_reqcap; - uint32_t if_curcap; struct pcap_stat st; @@ -217,114 +142,6 @@ struct my_ring { }; -static int -do_ioctl(struct my_ring *me, unsigned long what) -{ - struct ifreq ifr; - int error; - - bzero(&ifr, sizeof(ifr)); - strncpy(ifr.ifr_name, me->nmr.nr_name, sizeof(ifr.ifr_name)); - switch (what) { - case SIOCSIFFLAGS: - D("call SIOCSIFFLAGS 0x%x", me->if_flags); - ifr.ifr_flagshigh = (me->if_flags >> 16) & 0xffff; - ifr.ifr_flags = me->if_flags & 0xffff; - break; - case SIOCSIFCAP: - ifr.ifr_reqcap = me->if_reqcap; - ifr.ifr_curcap = me->if_curcap; - break; - } - error = ioctl(me->fd, what, &ifr); - if (error) { - D("ioctl 0x%lx error %d", what, error); - return error; - } - switch (what) { - case SIOCSIFFLAGS: - case SIOCGIFFLAGS: - me->if_flags = (ifr.ifr_flagshigh << 16) | - (0xffff & ifr.ifr_flags); - D("flags are L 0x%x H 0x%x 0x%x", - (uint16_t)ifr.ifr_flags, - (uint16_t)ifr.ifr_flagshigh, me->if_flags); - break; - - case SIOCGIFCAP: - me->if_reqcap = ifr.ifr_reqcap; - me->if_curcap = ifr.ifr_curcap; - D("curcap are 0x%x", me->if_curcap); - break; - } - return 0; -} - - -/* - * open a device. if me->mem is null then do an mmap. - */ -static int -netmap_open(struct my_ring *me, int ringid) -{ - int fd, err, l; - u_int i; - struct nmreq req; - - me->fd = fd = open("/dev/netmap", O_RDWR); - if (fd < 0) { - D("Unable to open /dev/netmap"); - return (-1); - } - bzero(&req, sizeof(req)); - strncpy(req.nr_name, me->nmr.nr_name, sizeof(req.nr_name)); - req.nr_ringid = ringid; - req.nr_version = NETMAP_API; - err = ioctl(fd, NIOCGINFO, &req); - if (err) { - D("cannot get info on %s", me->nmr.nr_name); - goto error; - } - me->memsize = l = req.nr_memsize; - ND("memsize is %d MB", l>>20); - err = ioctl(fd, NIOCREGIF, &req); - if (err) { - D("Unable to register %s", me->nmr.nr_name); - goto error; - } - - if (me->mem == NULL) { - me->mem = mmap(0, l, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0); - if (me->mem == MAP_FAILED) { - D("Unable to mmap"); - me->mem = NULL; - goto error; - } - } - - me->nifp = NETMAP_IF(me->mem, req.nr_offset); - me->queueid = ringid; - if (ringid & NETMAP_SW_RING) { - me->begin = req.nr_rx_rings; - me->end = me->begin + 1; - } else if (ringid & NETMAP_HW_RING) { - me->begin = ringid & NETMAP_RING_MASK; - me->end = me->begin + 1; - } else { - me->begin = 0; - me->end = req.nr_rx_rings; - } - /* request timestamps for packets */ - for (i = me->begin; i < me->end; i++) { - struct netmap_ring *ring = NETMAP_RXRING(me->nifp, i); - ring->flags = NR_TIMESTAMP; - } - //me->tx = NETMAP_TXRING(me->nifp, 0); - return (0); -error: - close(me->fd); - return -1; -} /* * There is a set of functions that tcpdump expects even if probably @@ -343,10 +160,12 @@ const char *pcap_lib_version(void) } int -pcap_findalldevs(pcap_if_t **alldevsp, __unused char *errbuf) +pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) { + pcap_if_t *top = NULL; +#ifndef linux struct ifaddrs *i_head, *i; - pcap_if_t *top = NULL, *cur; + pcap_if_t *cur; struct pcap_addr *tail = NULL; int l; @@ -397,7 +216,7 @@ pcap_findalldevs(pcap_if_t **alldevsp, __unused char *errbuf) } #define SA_NEXT(x) ((struct sockaddr *)((char *)(x) + (x)->sa_len)) pca->addr = (struct sockaddr *)(pca + 1); - bcopy(i->ifa_addr, pca->addr, i->ifa_addr->sa_len); + pkt_copy(i->ifa_addr, pca->addr, i->ifa_addr->sa_len); if (i->ifa_netmask) { pca->netmask = SA_NEXT(pca->addr); bcopy(i->ifa_netmask, pca->netmask, i->ifa_netmask->sa_len); @@ -415,12 +234,15 @@ pcap_findalldevs(pcap_if_t **alldevsp, __unused char *errbuf) } freeifaddrs(i_head); +#endif /* !linux */ + (void)errbuf; /* UNUSED */ *alldevsp = top; return 0; } -void pcap_freealldevs(__unused pcap_if_t *alldevs) +void pcap_freealldevs(pcap_if_t *alldevs) { + (void)alldevs; /* UNUSED */ D("unimplemented"); } @@ -447,8 +269,9 @@ pcap_activate(pcap_t *p) } int -pcap_can_set_rfmon(__unused pcap_t *p) +pcap_can_set_rfmon(pcap_t *p) { + (void)p; /* UNUSED */ D(""); return 0; /* no we can't */ } @@ -456,7 +279,7 @@ pcap_can_set_rfmon(__unused pcap_t *p) int pcap_set_snaplen(pcap_t *p, int snaplen) { - struct my_ring *me = p; + struct pcap_ring *me = p; D("len %d", snaplen); me->snaplen = snaplen; @@ -466,7 +289,7 @@ pcap_set_snaplen(pcap_t *p, int snaplen) int pcap_snapshot(pcap_t *p) { - struct my_ring *me = p; + struct pcap_ring *me = p; D("len %d", me->snaplen); return me->snaplen; @@ -474,9 +297,10 @@ pcap_snapshot(pcap_t *p) int pcap_lookupnet(const char *device, uint32_t *netp, - uint32_t *maskp, __unused char *errbuf) + uint32_t *maskp, char *errbuf) { + (void)errbuf; /* UNUSED */ D("device %s", device); inet_aton("10.0.0.255", (struct in_addr *)netp); inet_aton("255.255.255.0",(struct in_addr *) maskp); @@ -486,17 +310,17 @@ pcap_lookupnet(const char *device, uint32_t *netp, int pcap_set_promisc(pcap_t *p, int promisc) { - struct my_ring *me = p; + struct pcap_ring *me = p; D("promisc %d", promisc); - if (do_ioctl(me, SIOCGIFFLAGS)) + if (nm_do_ioctl(&me->me, SIOCGIFFLAGS, 0)) D("SIOCGIFFLAGS failed"); if (promisc) { - me->if_flags |= IFF_PPROMISC; + me->me.if_flags |= IFF_PPROMISC; } else { - me->if_flags &= ~IFF_PPROMISC; + me->me.if_flags &= ~IFF_PPROMISC; } - if (do_ioctl(me, SIOCSIFFLAGS)) + if (nm_do_ioctl(&me->me, SIOCSIFFLAGS, 0)) D("SIOCSIFFLAGS failed"); return 0; } @@ -504,7 +328,7 @@ pcap_set_promisc(pcap_t *p, int promisc) int pcap_set_timeout(pcap_t *p, int to_ms) { - struct my_ring *me = p; + struct pcap_ring *me = p; D("%d ms", to_ms); me->to_ms = to_ms; @@ -514,23 +338,30 @@ pcap_set_timeout(pcap_t *p, int to_ms) struct bpf_program; int -pcap_compile(__unused pcap_t *p, __unused struct bpf_program *fp, - const char *str, __unused int optimize, __unused uint32_t netmask) +pcap_compile(pcap_t *p, struct bpf_program *fp, + const char *str, int optimize, uint32_t netmask) { + (void)p; /* UNUSED */ + (void)fp; /* UNUSED */ + (void)optimize; /* UNUSED */ + (void)netmask; /* UNUSED */ D("%s", str); return 0; } int -pcap_setfilter(__unused pcap_t *p, __unused struct bpf_program *fp) +pcap_setfilter(pcap_t *p, struct bpf_program *fp) { + (void)p; /* UNUSED */ + (void)fp; /* UNUSED */ D(""); return 0; } int -pcap_datalink(__unused pcap_t *p) +pcap_datalink(pcap_t *p) { + (void)p; /* UNUSED */ D("returns 1"); return 1; // ethernet } @@ -553,7 +384,7 @@ struct pcap_stat; int pcap_stats(pcap_t *p, struct pcap_stat *ps) { - struct my_ring *me = p; + struct pcap_ring *me = p; ND(""); *ps = me->st; @@ -563,44 +394,42 @@ pcap_stats(pcap_t *p, struct pcap_stat *ps) char * pcap_geterr(pcap_t *p) { - struct my_ring *me = p; + struct pcap_ring *me = p; D(""); return me->msg; } pcap_t * -pcap_open_live(const char *device, __unused int snaplen, - int promisc, int to_ms, __unused char *errbuf) +pcap_open_live(const char *device, int snaplen, + int promisc, int to_ms, char *errbuf) { - struct my_ring *me; + struct pcap_ring *me; + int l; + (void)snaplen; /* UNUSED */ + (void)errbuf; /* UNUSED */ + if (!device) { + D("missing device name"); + return NULL; + } + + l = strlen(device) + 1; D("request to open %s snaplen %d promisc %d timeout %dms", device, snaplen, promisc, to_ms); - me = calloc(1, sizeof(*me)); + me = calloc(1, sizeof(*me) + l); if (me == NULL) { D("failed to allocate struct for %s", device); return NULL; } - strncpy(me->nmr.nr_name, device, sizeof(me->nmr.nr_name)); - if (netmap_open(me, 0)) { + me->me.ifname = (char *)(me + 1); + strcpy((char *)me->me.ifname, device); + if (netmap_open(&me->me, 0, promisc)) { D("error opening %s", device); free(me); return NULL; } me->to_ms = to_ms; - if (do_ioctl(me, SIOCGIFFLAGS)) - D("SIOCGIFFLAGS failed"); - if (promisc) { - me->if_flags |= IFF_PPROMISC; - if (do_ioctl(me, SIOCSIFFLAGS)) - D("SIOCSIFFLAGS failed"); - } - if (do_ioctl(me, SIOCGIFCAP)) - D("SIOCGIFCAP failed"); - me->if_reqcap &= ~(IFCAP_HWCSUM | IFCAP_TSO | IFCAP_TOE); - if (do_ioctl(me, SIOCSIFCAP)) - D("SIOCSIFCAP failed"); return (pcap_t *)me; } @@ -640,15 +469,19 @@ pcap_get_selectable_fd(pcap_t *p) } int -pcap_setnonblock(__unused pcap_t *p, int nonblock, __unused char *errbuf) +pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf) { + (void)p; /* UNUSED */ + (void)errbuf; /* UNUSED */ D("mode is %d", nonblock); return 0; /* ignore */ } int -pcap_setdirection(__unused pcap_t *p, __unused pcap_direction_t d) +pcap_setdirection(pcap_t *p, pcap_direction_t d) { + (void)p; /* UNUSED */ + (void)d; /* UNUSED */ D(""); return 0; /* ignore */ }; @@ -656,7 +489,8 @@ pcap_setdirection(__unused pcap_t *p, __unused pcap_direction_t d) int pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { - struct my_ring *me = p; + struct pcap_ring *pme = p; + struct my_ring *me = &pme->me; int got = 0; u_int si; @@ -669,7 +503,7 @@ pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user) ND("ring has %d pkts", ring->avail); if (ring->avail == 0) continue; - me->hdr.ts = ring->ts; + pme->hdr.ts = ring->ts; /* * XXX a proper prefetch should be done as * prefetch(i); callback(i-1); ... @@ -684,15 +518,15 @@ pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user) } u_char *buf = (u_char *)NETMAP_BUF(ring, idx); prefetch(buf); - me->hdr.len = me->hdr.caplen = ring->slot[i].len; + pme->hdr.len = pme->hdr.caplen = ring->slot[i].len; // D("call %p len %d", p, me->hdr.len); - callback(user, &me->hdr, buf); + callback(user, &pme->hdr, buf); ring->cur = NETMAP_RING_NEXT(ring, i); ring->avail--; got++; } } - me->st.ps_recv += got; + pme->st.ps_recv += got; return got; } @@ -732,13 +566,13 @@ pcap_inject(pcap_t *p, const void *buf, size_t size) int pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { - struct my_ring *me = p; + struct pcap_ring *me = p; struct pollfd fds[1]; int i; ND("cnt %d", cnt); memset(fds, 0, sizeof(fds)); - fds[0].fd = me->fd; + fds[0].fd = me->me.fd; fds[0].events = (POLLIN); while (cnt == -1 || cnt > 0) { @@ -753,11 +587,10 @@ pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user) return 0; } -#endif /* __PIC__ */ +#endif /* !TEST */ -#ifndef __PIC__ -static void -do_send(u_char *user, const struct pcap_pkthdr *h, const u_char *buf) +#ifdef TEST /* build test code */ +void do_send(u_char *user, const struct pcap_pkthdr *h, const u_char *buf) { pcap_inject((pcap_t *)user, buf, h->caplen); } @@ -819,4 +652,4 @@ main(int argc, char **argv) return (0); } -#endif /* !__PIC__ */ +#endif /* TEST */ diff --git a/tools/tools/netmap/pkt-gen.c b/tools/tools/netmap/pkt-gen.c index d0e64094edb..7c2ad984a2a 100644 --- a/tools/tools/netmap/pkt-gen.c +++ b/tools/tools/netmap/pkt-gen.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Matteo Landi, Luigi Rizzo. All rights reserved. + * Copyright (C) 2011-2012 Matteo Landi, Luigi Rizzo. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,7 +25,7 @@ /* * $FreeBSD$ - * $Id: pkt-gen.c 10967 2012-05-03 11:29:23Z luigi $ + * $Id: pkt-gen.c 12024 2013-01-25 05:41:51Z luigi $ * * Example program to show how to build a multithreaded packet * source/sink using the netmap device. @@ -36,120 +36,17 @@ * */ -const char *default_payload="netmap pkt-gen Luigi Rizzo and Matteo Landi\n" +#include "nm_util.h" + +const char *default_payload="netmap pkt-gen payload\n" "http://info.iet.unipi.it/~luigi/netmap/ "; -#include -#include /* pthread_* */ -#include /* pthread w/ affinity */ -#include /* signal */ -#include -#include -#include /* PRI* macros */ -#include /* strcmp */ -#include /* open */ -#include /* close */ -#include /* getifaddrs */ - -#include /* PROT_* */ -#include /* ioctl */ -#include -#include /* sockaddr.. */ -#include /* ntohs */ -#include -#include /* cpu_set */ -#include /* sysctl */ -#include /* timersub */ - -#include -#include /* ifreq */ -#include /* LLADDR */ - -#include -#include -#include - -#include -#include -#include - - -static inline int min(int a, int b) { return a < b ? a : b; } - -/* debug support */ -#define D(format, ...) \ - fprintf(stderr, "%s [%d] " format "\n", \ - __FUNCTION__, __LINE__, ##__VA_ARGS__) - -#ifndef EXPERIMENTAL -#define EXPERIMENTAL 0 -#endif +int time_second; // support for RD() debugging macro int verbose = 0; -#define MAX_QUEUES 64 /* no need to limit */ #define SKIP_PAYLOAD 1 /* do not check payload. */ -inline void prefetch (const void *x) -{ - __asm volatile("prefetcht0 %0" :: "m" (*(const unsigned long *)x)); -} - -// XXX only for multiples of 64 bytes, non overlapped. -static inline void -pkt_copy(void *_src, void *_dst, int l) -{ - uint64_t *src = _src; - uint64_t *dst = _dst; -#define likely(x) __builtin_expect(!!(x), 1) -#define unlikely(x) __builtin_expect(!!(x), 0) - if (unlikely(l >= 1024)) { - bcopy(src, dst, l); - return; - } - for (; l > 0; l-=64) { - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - } -} - - -#if EXPERIMENTAL -/* Wrapper around `rdtsc' to take reliable timestamps flushing the pipeline */ -#define netmap_rdtsc(t) \ - do { \ - u_int __regs[4]; \ - \ - do_cpuid(0, __regs); \ - (t) = rdtsc(); \ - } while (0) - -static __inline void -do_cpuid(u_int ax, u_int *p) -{ - __asm __volatile("cpuid" - : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3]) - : "0" (ax)); -} - -static __inline uint64_t -rdtsc(void) -{ - uint64_t rv; - - __asm __volatile("rdtsc" : "=A" (rv)); - return (rv); -} -#define MAX_SAMPLES 100000 -#endif /* EXPERIMENTAL */ - - struct pkt { struct ether_header eh; struct ip ip; @@ -157,16 +54,29 @@ struct pkt { uint8_t body[2048]; // XXX hardwired } __attribute__((__packed__)); +struct ip_range { + char *name; + struct in_addr start, end, cur; + uint16_t port0, port1, cur_p; +}; + +struct mac_range { + char *name; + struct ether_addr start, end; +}; + /* * global arguments for all threads */ + struct glob_arg { - const char *src_ip; - const char *dst_ip; - const char *src_mac; - const char *dst_mac; + struct ip_range src_ip; + struct ip_range dst_ip; + struct mac_range dst_mac; + struct mac_range src_mac; int pkt_size; int burst; + int forever; int npackets; /* total packets to send */ int nthreads; int cpus; @@ -175,13 +85,20 @@ struct glob_arg { #define OPT_ACCESS 2 #define OPT_COPY 4 #define OPT_MEMCPY 8 - int use_pcap; +#define OPT_TS 16 /* add a timestamp */ + int dev_type; pcap_t *p; -}; -struct mystat { - uint64_t containers[8]; + int affinity; + int main_fd; + int report_interval; + void *(*td_body)(void *); + void *mmap_addr; + int mmap_size; + char *ifname; }; +enum dev_type { DEV_NONE, DEV_NETMAP, DEV_PCAP, DEV_TAP }; + /* * Arguments for a new thread. The same structure is used by @@ -196,43 +113,106 @@ struct targ { struct nmreq nmr; struct netmap_if *nifp; uint16_t qfirst, qlast; /* range of queues to scan */ - uint64_t count; + volatile uint64_t count; struct timeval tic, toc; int me; pthread_t thread; int affinity; - uint8_t dst_mac[6]; - uint8_t src_mac[6]; - u_int dst_mac_range; - u_int src_mac_range; - uint32_t dst_ip; - uint32_t src_ip; - u_int dst_ip_range; - u_int src_ip_range; - struct pkt pkt; }; +/* + * extract the extremes from a range of ipv4 addresses. + * addr_lo[-addr_hi][:port_lo[-port_hi]] + */ +static void +extract_ip_range(struct ip_range *r) +{ + char *p_lo, *p_hi; + char buf1[16]; // one ip address + + D("extract IP range from %s", r->name); + p_lo = index(r->name, ':'); /* do we have ports ? */ + if (p_lo) { + D(" found ports at %s", p_lo); + *p_lo++ = '\0'; + p_hi = index(p_lo, '-'); + if (p_hi) + *p_hi++ = '\0'; + else + p_hi = p_lo; + r->port0 = strtol(p_lo, NULL, 0); + r->port1 = strtol(p_hi, NULL, 0); + if (r->port1 < r->port0) { + r->cur_p = r->port0; + r->port0 = r->port1; + r->port1 = r->cur_p; + } + r->cur_p = r->port0; + D("ports are %d to %d", r->port0, r->port1); + } + p_hi = index(r->name, '-'); /* do we have upper ip ? */ + if (p_hi) { + *p_hi++ = '\0'; + } else + p_hi = r->name; + inet_aton(r->name, &r->start); + inet_aton(p_hi, &r->end); + if (r->start.s_addr > r->end.s_addr) { + r->cur = r->start; + r->start = r->end; + r->end = r->cur; + } + r->cur = r->start; + strncpy(buf1, inet_ntoa(r->end), sizeof(buf1)); + D("range is %s %d to %s %d", inet_ntoa(r->start), r->port0, + buf1, r->port1); +} + +static void +extract_mac_range(struct mac_range *r) +{ + D("extract MAC range from %s", r->name); + bcopy(ether_aton(r->name), &r->start, 6); + bcopy(ether_aton(r->name), &r->end, 6); +#if 0 + bcopy(targ->src_mac, eh->ether_shost, 6); + p = index(targ->g->src_mac, '-'); + if (p) + targ->src_mac_range = atoi(p+1); + + bcopy(ether_aton(targ->g->dst_mac), targ->dst_mac, 6); + bcopy(targ->dst_mac, eh->ether_dhost, 6); + p = index(targ->g->dst_mac, '-'); + if (p) + targ->dst_mac_range = atoi(p+1); +#endif + D("%s starts at %s", r->name, ether_ntoa(&r->start)); +} + static struct targ *targs; static int global_nthreads; /* control-C handler */ static void -sigint_h(__unused int sig) +sigint_h(int sig) { - for (int i = 0; i < global_nthreads; i++) - targs[i].cancel = 1; + int i; + (void)sig; /* UNUSED */ + for (i = 0; i < global_nthreads; i++) { + targs[i].cancel = 1; + } signal(SIGINT, SIG_DFL); } - /* sysctl wrapper to return the number of active CPUs */ static int system_ncpus(void) { +#ifdef __FreeBSD__ int mib[2], ncpus; size_t len; @@ -242,8 +222,32 @@ system_ncpus(void) sysctl(mib, 2, &ncpus, &len, NULL, 0); return (ncpus); +#else + return 1; +#endif /* !__FreeBSD__ */ } +#ifdef __linux__ +#define sockaddr_dl sockaddr_ll +#define sdl_family sll_family +#define AF_LINK AF_PACKET +#define LLADDR(s) s->sll_addr; +#include +#define TAP_CLONEDEV "/dev/net/tun" +#endif /* __linux__ */ + +#ifdef __FreeBSD__ +#include +#define TAP_CLONEDEV "/dev/tap" +#endif /* __FreeBSD */ + +#ifdef __APPLE__ +// #warning TAP not supported on apple ? +#include +#define TAP_CLONEDEV "/dev/tap" +#endif /* __APPLE__ */ + + /* * locate the src mac address for our interface, put it * into the user-supplied buffer. return 0 if ok, -1 on error. @@ -285,6 +289,7 @@ source_hwaddr(const char *ifname, char *buf) static int setaffinity(pthread_t me, int i) { +#ifdef __FreeBSD__ cpuset_t cpumask; if (i == -1) @@ -298,36 +303,57 @@ setaffinity(pthread_t me, int i) D("Unable to set affinity"); return 1; } +#else + (void)me; /* suppress 'unused' warnings */ + (void)i; +#endif /* __FreeBSD__ */ return 0; } /* Compute the checksum of the given ip header. */ static uint16_t -checksum(const void *data, uint16_t len) +checksum(const void *data, uint16_t len, uint32_t sum) { const uint8_t *addr = data; - uint32_t sum = 0; + uint32_t i; - while (len > 1) { - sum += addr[0] * 256 + addr[1]; - addr += 2; - len -= 2; + /* Checksum all the pairs of bytes first... */ + for (i = 0; i < (len & ~1U); i += 2) { + sum += (u_int16_t)ntohs(*((u_int16_t *)(addr + i))); + if (sum > 0xFFFF) + sum -= 0xFFFF; } + /* + * If there's a single byte left over, checksum it, too. + * Network byte order is big-endian, so the remaining byte is + * the high byte. + */ + if (i < len) { + sum += addr[i] << 8; + if (sum > 0xFFFF) + sum -= 0xFFFF; + } + return sum; +} - if (len == 1) - sum += *addr * 256; - - sum = (sum >> 16) + (sum & 0xffff); - sum += (sum >> 16); - - sum = htons(sum); - - return ~sum; +static u_int16_t +wrapsum(u_int32_t sum) +{ + sum = ~sum & 0xFFFF; + return (htons(sum)); } /* * Fill a packet with some payload. + * We create a UDP packet so the payload starts at + * 14+20+8 = 42 bytes. */ +#ifdef __linux__ +#define uh_sport source +#define uh_dport dest +#define uh_ulen len +#define uh_sum check +#endif /* linux */ static void initialize_packet(struct targ *targ) { @@ -335,9 +361,8 @@ initialize_packet(struct targ *targ) struct ether_header *eh; struct ip *ip; struct udphdr *udp; - uint16_t paylen = targ->g->pkt_size - sizeof(*eh) - sizeof(*ip); + uint16_t paylen = targ->g->pkt_size - sizeof(*eh) - sizeof(struct ip); int i, l, l0 = strlen(default_payload); - char *p; for (i = 0; i < paylen;) { l = min(l0, paylen - i); @@ -345,14 +370,8 @@ initialize_packet(struct targ *targ) i += l; } pkt->body[i-1] = '\0'; - - udp = &pkt->udp; - udp->uh_sport = htons(1234); - udp->uh_dport = htons(4321); - udp->uh_ulen = htons(paylen); - udp->uh_sum = 0; // checksum(udp, sizeof(*udp)); - ip = &pkt->ip; + ip->ip_v = IPVERSION; ip->ip_hl = 5; ip->ip_id = 0; @@ -362,29 +381,36 @@ initialize_packet(struct targ *targ) ip->ip_off = htons(IP_DF); /* Don't fragment */ ip->ip_ttl = IPDEFTTL; ip->ip_p = IPPROTO_UDP; - inet_aton(targ->g->src_ip, (struct in_addr *)&ip->ip_src); - inet_aton(targ->g->dst_ip, (struct in_addr *)&ip->ip_dst); - targ->dst_ip = ip->ip_dst.s_addr; - targ->src_ip = ip->ip_src.s_addr; - p = index(targ->g->src_ip, '-'); - if (p) { - targ->dst_ip_range = atoi(p+1); - D("dst-ip sweep %d addresses", targ->dst_ip_range); - } - ip->ip_sum = checksum(ip, sizeof(*ip)); + ip->ip_dst.s_addr = targ->g->dst_ip.cur.s_addr; + if (++targ->g->dst_ip.cur.s_addr > targ->g->dst_ip.end.s_addr) + targ->g->dst_ip.cur.s_addr = targ->g->dst_ip.start.s_addr; + ip->ip_src.s_addr = targ->g->src_ip.cur.s_addr; + if (++targ->g->src_ip.cur.s_addr > targ->g->src_ip.end.s_addr) + targ->g->src_ip.cur.s_addr = targ->g->src_ip.start.s_addr; + ip->ip_sum = wrapsum(checksum(ip, sizeof(*ip), 0)); + + + udp = &pkt->udp; + udp->uh_sport = htons(targ->g->src_ip.cur_p); + if (++targ->g->src_ip.cur_p > targ->g->src_ip.port1) + targ->g->src_ip.cur_p = targ->g->src_ip.port0; + udp->uh_dport = htons(targ->g->dst_ip.cur_p); + if (++targ->g->dst_ip.cur_p > targ->g->dst_ip.port1) + targ->g->dst_ip.cur_p = targ->g->dst_ip.port0; + udp->uh_ulen = htons(paylen); + /* Magic: taken from sbin/dhclient/packet.c */ + udp->uh_sum = wrapsum(checksum(udp, sizeof(*udp), + checksum(pkt->body, + paylen - sizeof(*udp), + checksum(&ip->ip_src, 2 * sizeof(ip->ip_src), + IPPROTO_UDP + (u_int32_t)ntohs(udp->uh_ulen) + ) + ) + )); eh = &pkt->eh; - bcopy(ether_aton(targ->g->src_mac), targ->src_mac, 6); - bcopy(targ->src_mac, eh->ether_shost, 6); - p = index(targ->g->src_mac, '-'); - if (p) - targ->src_mac_range = atoi(p+1); - - bcopy(ether_aton(targ->g->dst_mac), targ->dst_mac, 6); - bcopy(targ->dst_mac, eh->ether_dhost, 6); - p = index(targ->g->dst_mac, '-'); - if (p) - targ->dst_mac_range = atoi(p+1); + bcopy(&targ->g->src_mac.start, eh->ether_shost, 6); + bcopy(&targ->g->dst_mac.start, eh->ether_dhost, 6); eh->ether_type = htons(ETHERTYPE_IP); } @@ -452,7 +478,6 @@ send_packets(struct netmap_ring *ring, struct pkt *pkt, memcpy(p, pkt, size); else if (options & OPT_PREFETCH) prefetch(p); - slot->len = size; if (sent == count - 1) slot->flags |= NS_REPORT; @@ -464,23 +489,198 @@ send_packets(struct netmap_ring *ring, struct pkt *pkt, return (sent); } +/* + * Send a packet, and wait for a response. + * The payload (after UDP header, ofs 42) has a 4-byte sequence + * followed by a struct timeval (or bintime?) + */ +#define PAY_OFS 42 /* where in the pkt... */ + static void * -sender_body(void *data) +pinger_body(void *data) { struct targ *targ = (struct targ *) data; struct pollfd fds[1]; struct netmap_if *nifp = targ->nifp; - struct netmap_ring *txring; - int i, pkts_per_td = targ->g->npackets / targ->g->nthreads, sent = 0; - int continuous = 0; - int options = targ->g->options | OPT_COPY; - int retval; + int i, rx = 0, n = targ->g->npackets; -D("start"); - if (pkts_per_td == 0) { - continuous = 1; - pkts_per_td = 100000; + fds[0].fd = targ->fd; + fds[0].events = (POLLIN); + static uint32_t sent; + struct timespec ts, now, last_print; + uint32_t count = 0, min = 1000000000, av = 0; + + if (targ->g->nthreads > 1) { + D("can only ping with 1 thread"); + return NULL; } + + clock_gettime(CLOCK_REALTIME_PRECISE, &last_print); + while (n == 0 || (int)sent < n) { + struct netmap_ring *ring = NETMAP_TXRING(nifp, 0); + struct netmap_slot *slot; + char *p; + for (i = 0; i < 1; i++) { + slot = &ring->slot[ring->cur]; + slot->len = targ->g->pkt_size; + p = NETMAP_BUF(ring, slot->buf_idx); + + if (ring->avail == 0) { + D("-- ouch, cannot send"); + } else { + pkt_copy(&targ->pkt, p, targ->g->pkt_size); + clock_gettime(CLOCK_REALTIME_PRECISE, &ts); + bcopy(&sent, p+42, sizeof(sent)); + bcopy(&ts, p+46, sizeof(ts)); + sent++; + ring->cur = NETMAP_RING_NEXT(ring, ring->cur); + ring->avail--; + } + } + /* should use a parameter to decide how often to send */ + if (poll(fds, 1, 3000) <= 0) { + D("poll error/timeout on queue %d", targ->me); + continue; + } + /* see what we got back */ + for (i = targ->qfirst; i < targ->qlast; i++) { + ring = NETMAP_RXRING(nifp, i); + while (ring->avail > 0) { + uint32_t seq; + slot = &ring->slot[ring->cur]; + p = NETMAP_BUF(ring, slot->buf_idx); + + clock_gettime(CLOCK_REALTIME_PRECISE, &now); + bcopy(p+42, &seq, sizeof(seq)); + bcopy(p+46, &ts, sizeof(ts)); + ts.tv_sec = now.tv_sec - ts.tv_sec; + ts.tv_nsec = now.tv_nsec - ts.tv_nsec; + if (ts.tv_nsec < 0) { + ts.tv_nsec += 1000000000; + ts.tv_sec--; + } + if (1) D("seq %d/%d delta %d.%09d", seq, sent, + (int)ts.tv_sec, (int)ts.tv_nsec); + if (ts.tv_nsec < (int)min) + min = ts.tv_nsec; + count ++; + av += ts.tv_nsec; + ring->avail--; + ring->cur = NETMAP_RING_NEXT(ring, ring->cur); + rx++; + } + } + //D("tx %d rx %d", sent, rx); + //usleep(100000); + ts.tv_sec = now.tv_sec - last_print.tv_sec; + ts.tv_nsec = now.tv_nsec - last_print.tv_nsec; + if (ts.tv_nsec < 0) { + ts.tv_nsec += 1000000000; + ts.tv_sec--; + } + if (ts.tv_sec >= 1) { + D("count %d min %d av %d", + count, min, av/count); + count = 0; + av = 0; + min = 100000000; + last_print = now; + } + } + return NULL; +} + + +/* + * reply to ping requests + */ +static void * +ponger_body(void *data) +{ + struct targ *targ = (struct targ *) data; + struct pollfd fds[1]; + struct netmap_if *nifp = targ->nifp; + struct netmap_ring *txring, *rxring; + int i, rx = 0, sent = 0, n = targ->g->npackets; + fds[0].fd = targ->fd; + fds[0].events = (POLLIN); + + if (targ->g->nthreads > 1) { + D("can only reply ping with 1 thread"); + return NULL; + } + D("understood ponger %d but don't know how to do it", n); + while (n == 0 || sent < n) { + uint32_t txcur, txavail; +//#define BUSYWAIT +#ifdef BUSYWAIT + ioctl(fds[0].fd, NIOCRXSYNC, NULL); +#else + if (poll(fds, 1, 1000) <= 0) { + D("poll error/timeout on queue %d", targ->me); + continue; + } +#endif + txring = NETMAP_TXRING(nifp, 0); + txcur = txring->cur; + txavail = txring->avail; + /* see what we got back */ + for (i = targ->qfirst; i < targ->qlast; i++) { + rxring = NETMAP_RXRING(nifp, i); + while (rxring->avail > 0) { + uint16_t *spkt, *dpkt; + uint32_t cur = rxring->cur; + struct netmap_slot *slot = &rxring->slot[cur]; + char *src, *dst; + src = NETMAP_BUF(rxring, slot->buf_idx); + //D("got pkt %p of size %d", src, slot->len); + rxring->avail--; + rxring->cur = NETMAP_RING_NEXT(rxring, cur); + rx++; + if (txavail == 0) + continue; + dst = NETMAP_BUF(txring, + txring->slot[txcur].buf_idx); + /* copy... */ + dpkt = (uint16_t *)dst; + spkt = (uint16_t *)src; + pkt_copy(src, dst, slot->len); + dpkt[0] = spkt[3]; + dpkt[1] = spkt[4]; + dpkt[2] = spkt[5]; + dpkt[3] = spkt[0]; + dpkt[4] = spkt[1]; + dpkt[5] = spkt[2]; + txring->slot[txcur].len = slot->len; + /* XXX swap src dst mac */ + txcur = NETMAP_RING_NEXT(txring, txcur); + txavail--; + sent++; + } + } + txring->cur = txcur; + txring->avail = txavail; + targ->count = sent; +#ifdef BUSYWAIT + ioctl(fds[0].fd, NIOCTXSYNC, NULL); +#endif + //D("tx %d rx %d", sent, rx); + } + return NULL; +} + + +static void * +sender_body(void *data) +{ + struct targ *targ = (struct targ *) data; + + struct pollfd fds[1]; + struct netmap_if *nifp = targ->nifp; + struct netmap_ring *txring; + int i, n = targ->g->npackets / targ->g->nthreads, sent = 0; + int options = targ->g->options | OPT_COPY; +D("start"); if (setaffinity(targ->thread, targ->affinity)) goto quit; /* setup poll(2) mechanism. */ @@ -490,45 +690,56 @@ D("start"); /* main loop.*/ gettimeofday(&targ->tic, NULL); - if (targ->g->use_pcap) { - int size = targ->g->pkt_size; - void *pkt = &targ->pkt; - pcap_t *p = targ->g->p; - for (i = 0; (sent < pkts_per_td && !targ->cancel) || continuous; i++) { + if (targ->g->dev_type == DEV_PCAP) { + int size = targ->g->pkt_size; + void *pkt = &targ->pkt; + pcap_t *p = targ->g->p; + + for (i = 0; !targ->cancel && (n == 0 || sent < n); i++) { if (pcap_inject(p, pkt, size) != -1) sent++; if (i > 10000) { targ->count = sent; i = 0; } - } + } + } else if (targ->g->dev_type == DEV_TAP) { /* tap */ + int size = targ->g->pkt_size; + void *pkt = &targ->pkt; + D("writing to file desc %d", targ->g->main_fd); + + for (i = 0; !targ->cancel && (n == 0 || sent < n); i++) { + if (write(targ->g->main_fd, pkt, size) != -1) + sent++; + if (i > 10000) { + targ->count = sent; + i = 0; + } + } } else { - while (sent < pkts_per_td || continuous) { + while (!targ->cancel && (n == 0 || sent < n)) { /* * wait for available room in the send queue(s) */ - if ((retval = poll(fds, 1, 2000)) <= 0) { + if (poll(fds, 1, 2000) <= 0) { if (targ->cancel) break; - if (retval == 0) - D("poll timeout on queue %d\n", targ->me); - else - D("poll error on queue %d: %s\n", targ->me, - strerror(errno)); + D("poll error/timeout on queue %d", targ->me); goto quit; } /* * scan our queues and send on those with room */ - if (sent > 100000 && !(targ->g->options & OPT_COPY) ) + if (options & OPT_COPY && sent > 100000 && !(targ->g->options & OPT_COPY) ) { + D("drop copy"); options &= ~OPT_COPY; - for (i = targ->qfirst; i < targ->qlast && !targ->cancel; i++) { + } + for (i = targ->qfirst; i < targ->qlast; i++) { int m, limit = targ->g->burst; - if (!continuous && pkts_per_td - sent < limit) - limit = pkts_per_td - sent; - + if (n > 0 && n - sent < limit) + limit = n - sent; txring = NETMAP_TXRING(nifp, i); if (txring->avail == 0) continue; @@ -537,8 +748,6 @@ D("start"); sent += m; targ->count = sent; } - if (targ->cancel) - break; } /* flush any remaining packets */ ioctl(fds[0].fd, NIOCTXSYNC, NULL); @@ -566,10 +775,12 @@ quit: static void -receive_pcap(u_char *user, __unused const struct pcap_pkthdr * h, - __unused const u_char * bytes) +receive_pcap(u_char *user, const struct pcap_pkthdr * h, + const u_char * bytes) { int *count = (int *)user; + (void)h; /* UNUSED */ + (void)bytes; /* UNUSED */ (*count)++; } @@ -603,7 +814,8 @@ receiver_body(void *data) struct pollfd fds[1]; struct netmap_if *nifp = targ->nifp; struct netmap_ring *rxring; - int i, received = 0; + int i; + uint64_t received = 0; if (setaffinity(targ->thread, targ->affinity)) goto quit; @@ -614,7 +826,7 @@ receiver_body(void *data) fds[0].events = (POLLIN); /* unbounded wait for the first packet. */ - while (!targ->cancel) { + for (;;) { i = poll(fds, 1, 1000); if (i > 0 && !(fds[0].revents & POLLERR)) break; @@ -623,15 +835,24 @@ receiver_body(void *data) /* main loop, exit after 1s silence */ gettimeofday(&targ->tic, NULL); - if (targ->g->use_pcap) { + if (targ->g->dev_type == DEV_PCAP) { while (!targ->cancel) { + /* XXX should we poll ? */ pcap_dispatch(targ->g->p, targ->g->burst, receive_pcap, NULL); } + } else if (targ->g->dev_type == DEV_TAP) { + D("reading from %s fd %d", targ->g->ifname, targ->g->main_fd); + while (!targ->cancel) { + char buf[2048]; + /* XXX should we poll ? */ + if (read(targ->g->main_fd, buf, sizeof(buf)) > 0) + targ->count++; + } } else { while (!targ->cancel) { /* Once we started to receive packets, wait at most 1 seconds before quitting. */ - if (poll(fds, 1, 1 * 1000) <= 0) { + if (poll(fds, 1, 1 * 1000) <= 0 && targ->g->forever == 0) { gettimeofday(&targ->toc, NULL); targ->toc.tv_sec -= 1; /* Subtract timeout time. */ break; @@ -647,8 +868,8 @@ receiver_body(void *data) m = receive_packets(rxring, targ->g->burst, SKIP_PAYLOAD); received += m; - targ->count = received; } + targ->count = received; // tell the card we have read the data //ioctl(fds[0].fd, NIOCRXSYNC, NULL); @@ -665,59 +886,55 @@ quit: return (NULL); } -static char * -scaled_val(double val) +/* very crude code to print a number in normalized form. + * Caller has to make sure that the buffer is large enough. + */ +static const char * +norm(char *buf, double val) { - static char buf[64]; - const char *units[] = {"", "K", "M", "G"}; - int i = 0; + char *units[] = { "", "K", "M", "G" }; + u_int i; - while (val >= 1000 && i < 3) { + for (i = 0; val >=1000 && i < sizeof(units)/sizeof(char *); i++) val /= 1000; - i++; - } - snprintf(buf, sizeof(buf), "%.2f%s", val, units[i]); - return (buf); + sprintf(buf, "%.2f %s", val, units[i]); + return buf; } static void tx_output(uint64_t sent, int size, double delta) { - uint64_t bytes_sent = sent * size; - double bw = 8.0 * bytes_sent / delta; - double pps = sent / delta; - /* - * Assume Ethernet overhead of 24 bytes per packet excluding header: - * FCS 4 bytes - * Preamble 8 bytes - * IFG 12 bytes - */ - double bw_with_overhead = 8.0 * (bytes_sent + sent * 24) / delta; + double bw, raw_bw, pps; + char b1[40], b2[80], b3[80]; printf("Sent %" PRIu64 " packets, %d bytes each, in %.2f seconds.\n", sent, size, delta); - printf("Speed: %spps. ", scaled_val(pps)); - printf("Bandwidth: %sbps ", scaled_val(bw)); - printf("(%sbps with overhead).\n", scaled_val(bw_with_overhead)); + if (delta == 0) + delta = 1e-6; + if (size < 60) /* correct for min packet size */ + size = 60; + pps = sent / delta; + bw = (8.0 * size * sent) / delta; + /* raw packets have4 bytes crc + 20 bytes framing */ + raw_bw = (8.0 * (size + 24) * sent) / delta; + printf("Speed: %spps Bandwidth: %sbps (raw %sbps)\n", + norm(b1, pps), norm(b2, bw), norm(b3, raw_bw) ); } static void rx_output(uint64_t received, double delta) { - - double pps = received / delta; - char units[4] = { '\0', 'K', 'M', 'G' }; - int punit = 0; - - while (pps >= 1000) { - pps /= 1000; - punit += 1; - } + double pps; + char b1[40]; printf("Received %" PRIu64 " packets, in %.2f seconds.\n", received, delta); - printf("Speed: %.2f%cpps.\n", pps, units[punit]); + + if (delta == 0) + delta = 1e-6; + pps = received / delta; + printf("Speed: %spps\n", norm(b1, pps)); } static void @@ -728,17 +945,21 @@ usage(void) "Usage:\n" "%s arguments\n" "\t-i interface interface name\n" - "\t-t pkts_to_send also forces send mode, 0 = continuous\n" - "\t-r pkts_to_receive also forces receive mode\n" + "\t-f function tx rx ping pong\n" + "\t-n count number of iterations (can be 0)\n" + "\t-t pkts_to_send also forces tx mode\n" + "\t-r pkts_to_receive also forces rx mode\n" "\t-l pkts_size in bytes excluding CRC\n" "\t-d dst-ip end with %%n to sweep n addresses\n" "\t-s src-ip end with %%n to sweep n addresses\n" "\t-D dst-mac end with %%n to sweep n addresses\n" "\t-S src-mac end with %%n to sweep n addresses\n" + "\t-a cpu_id use setaffinity\n" "\t-b burst size testing, mostly\n" "\t-c cores cores to use\n" "\t-p threads processes/threads to use\n" "\t-T report_ms milliseconds between reports\n" + "\t-P use libpcap instead of netmap\n" "\t-w wait_for_link_time in seconds\n" "", cmd); @@ -746,71 +967,341 @@ usage(void) exit(0); } +static void +start_threads(struct glob_arg *g) +{ + int i; + + targs = calloc(g->nthreads, sizeof(*targs)); + /* + * Now create the desired number of threads, each one + * using a single descriptor. + */ + for (i = 0; i < g->nthreads; i++) { + bzero(&targs[i], sizeof(targs[i])); + targs[i].fd = -1; /* default, with pcap */ + targs[i].g = g; + + if (g->dev_type == DEV_NETMAP) { + struct nmreq tifreq; + int tfd; + + /* register interface. */ + tfd = open("/dev/netmap", O_RDWR); + if (tfd == -1) { + D("Unable to open /dev/netmap"); + continue; + } + targs[i].fd = tfd; + + bzero(&tifreq, sizeof(tifreq)); + strncpy(tifreq.nr_name, g->ifname, sizeof(tifreq.nr_name)); + tifreq.nr_version = NETMAP_API; + tifreq.nr_ringid = (g->nthreads > 1) ? (i | NETMAP_HW_RING) : 0; + + /* + * if we are acting as a receiver only, do not touch the transmit ring. + * This is not the default because many apps may use the interface + * in both directions, but a pure receiver does not. + */ + if (g->td_body == receiver_body) { + tifreq.nr_ringid |= NETMAP_NO_TX_POLL; + } + + if ((ioctl(tfd, NIOCREGIF, &tifreq)) == -1) { + D("Unable to register %s", g->ifname); + continue; + } + targs[i].nmr = tifreq; + targs[i].nifp = NETMAP_IF(g->mmap_addr, tifreq.nr_offset); + /* start threads. */ + targs[i].qfirst = (g->nthreads > 1) ? i : 0; + targs[i].qlast = (g->nthreads > 1) ? i+1 : + (g->td_body == receiver_body ? tifreq.nr_rx_rings : tifreq.nr_tx_rings); + } else { + targs[i].fd = g->main_fd; + } + targs[i].used = 1; + targs[i].me = i; + if (g->affinity >= 0) { + if (g->affinity < g->cpus) + targs[i].affinity = g->affinity; + else + targs[i].affinity = i % g->cpus; + } else + targs[i].affinity = -1; + /* default, init packets */ + initialize_packet(&targs[i]); + + if (pthread_create(&targs[i].thread, NULL, g->td_body, + &targs[i]) == -1) { + D("Unable to create thread %d", i); + targs[i].used = 0; + } + } +} + +static void +main_thread(struct glob_arg *g) +{ + int i; + + uint64_t prev = 0; + uint64_t count = 0; + double delta_t; + struct timeval tic, toc; + + gettimeofday(&toc, NULL); + for (;;) { + struct timeval now, delta; + uint64_t pps, usec, my_count, npkts; + int done = 0; + + delta.tv_sec = g->report_interval/1000; + delta.tv_usec = (g->report_interval%1000)*1000; + select(0, NULL, NULL, NULL, &delta); + gettimeofday(&now, NULL); + time_second = now.tv_sec; + timersub(&now, &toc, &toc); + my_count = 0; + for (i = 0; i < g->nthreads; i++) { + my_count += targs[i].count; + if (targs[i].used == 0) + done++; + } + usec = toc.tv_sec* 1000000 + toc.tv_usec; + if (usec < 10000) + continue; + npkts = my_count - prev; + pps = (npkts*1000000 + usec/2) / usec; + D("%" PRIu64 " pps (%" PRIu64 " pkts in %" PRIu64 " usec)", + pps, npkts, usec); + prev = my_count; + toc = now; + if (done == g->nthreads) + break; + } + + timerclear(&tic); + timerclear(&toc); + for (i = 0; i < g->nthreads; i++) { + /* + * Join active threads, unregister interfaces and close + * file descriptors. + */ + pthread_join(targs[i].thread, NULL); + close(targs[i].fd); + + if (targs[i].completed == 0) + D("ouch, thread %d exited with error", i); + + /* + * Collect threads output and extract information about + * how long it took to send all the packets. + */ + count += targs[i].count; + if (!timerisset(&tic) || timercmp(&targs[i].tic, &tic, <)) + tic = targs[i].tic; + if (!timerisset(&toc) || timercmp(&targs[i].toc, &toc, >)) + toc = targs[i].toc; + } + + /* print output. */ + timersub(&toc, &tic, &toc); + delta_t = toc.tv_sec + 1e-6* toc.tv_usec; + if (g->td_body == sender_body) + tx_output(count, g->pkt_size, delta_t); + else + rx_output(count, delta_t); + + if (g->dev_type == DEV_NETMAP) { + ioctl(g->main_fd, NIOCUNREGIF, NULL); // XXX deprecated + munmap(g->mmap_addr, g->mmap_size); + close(g->main_fd); + } +} + + +struct sf { + char *key; + void *f; +}; + +static struct sf func[] = { + { "tx", sender_body }, + { "rx", receiver_body }, + { "ping", pinger_body }, + { "pong", ponger_body }, + { NULL, NULL } +}; + +static int +tap_alloc(char *dev) +{ + struct ifreq ifr; + int fd, err; + char *clonedev = TAP_CLONEDEV; + + (void)err; + (void)dev; + /* Arguments taken by the function: + * + * char *dev: the name of an interface (or '\0'). MUST have enough + * space to hold the interface name if '\0' is passed + * int flags: interface flags (eg, IFF_TUN etc.) + */ + +#ifdef __FreeBSD__ + if (dev[3]) { /* tapSomething */ + static char buf[128]; + snprintf(buf, sizeof(buf), "/dev/%s", dev); + clonedev = buf; + } +#endif + /* open the device */ + if( (fd = open(clonedev, O_RDWR)) < 0 ) { + return fd; + } + D("%s open successful", clonedev); + + /* preparation of the struct ifr, of type "struct ifreq" */ + memset(&ifr, 0, sizeof(ifr)); + +#ifdef linux + ifr.ifr_flags = IFF_TAP | IFF_NO_PI; + + if (*dev) { + /* if a device name was specified, put it in the structure; otherwise, + * the kernel will try to allocate the "next" device of the + * specified type */ + strncpy(ifr.ifr_name, dev, IFNAMSIZ); + } + + /* try to create the device */ + if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ) { + D("failed to to a TUNSETIFF"); + close(fd); + return err; + } + + /* if the operation was successful, write back the name of the + * interface to the variable "dev", so the caller can know + * it. Note that the caller MUST reserve space in *dev (see calling + * code below) */ + strcpy(dev, ifr.ifr_name); + D("new name is %s", dev); +#endif /* linux */ + + /* this is the special file descriptor that the caller will use to talk + * with the virtual interface */ + return fd; +} int main(int arc, char **argv) { - int i, fd; - char pcap_errbuf[PCAP_ERRBUF_SIZE]; + int i; struct glob_arg g; struct nmreq nmr; - void *mmap_addr; /* the mmap address */ - void *(*td_body)(void *) = receiver_body; int ch; - int report_interval = 1000; /* report interval */ - char *ifname = NULL; int wait_link = 2; int devqueues = 1; /* how many device queues */ bzero(&g, sizeof(g)); - g.src_ip = "10.0.0.1"; - g.dst_ip = "10.1.0.1"; - g.dst_mac = "ff:ff:ff:ff:ff:ff"; - g.src_mac = NULL; + g.main_fd = -1; + g.td_body = receiver_body; + g.report_interval = 1000; /* report interval */ + g.affinity = -1; + /* ip addresses can also be a range x.x.x.x-x.x.x.y */ + g.src_ip.name = "10.0.0.1"; + g.dst_ip.name = "10.1.0.1"; + g.dst_mac.name = "ff:ff:ff:ff:ff:ff"; + g.src_mac.name = NULL; g.pkt_size = 60; g.burst = 512; // default g.nthreads = 1; g.cpus = 1; while ( (ch = getopt(arc, argv, - "i:t:r:l:d:s:D:S:b:c:o:p:PT:w:v")) != -1) { + "a:f:n:i:t:r:l:d:s:D:S:b:c:o:p:PT:w:Wv")) != -1) { + struct sf *fn; + switch(ch) { default: D("bad option %c %s", ch, optarg); usage(); break; - case 'o': + + case 'n': + g.npackets = atoi(optarg); + break; + + case 'f': + for (fn = func; fn->key; fn++) { + if (!strcmp(fn->key, optarg)) + break; + } + if (fn->key) + g.td_body = fn->f; + else + D("unrecognised function %s", optarg); + break; + + case 'o': /* data generation options */ g.options = atoi(optarg); break; + + case 'a': /* force affinity */ + g.affinity = atoi(optarg); + break; + case 'i': /* interface */ - ifname = optarg; + g.ifname = optarg; + if (!strncmp(optarg, "tap", 3)) + g.dev_type = DEV_TAP; + else + g.dev_type = DEV_NETMAP; break; - case 't': /* send */ - td_body = sender_body; + + case 't': /* send, deprecated */ + D("-t deprecated, please use -f tx -n %s", optarg); + g.td_body = sender_body; g.npackets = atoi(optarg); break; + case 'r': /* receive */ - td_body = receiver_body; + D("-r deprecated, please use -f rx -n %s", optarg); + g.td_body = receiver_body; g.npackets = atoi(optarg); break; + case 'l': /* pkt_size */ g.pkt_size = atoi(optarg); break; + case 'd': - g.dst_ip = optarg; + g.dst_ip.name = optarg; break; + case 's': - g.src_ip = optarg; + g.src_ip.name = optarg; break; + case 'T': /* report interval */ - report_interval = atoi(optarg); + g.report_interval = atoi(optarg); break; + case 'w': wait_link = atoi(optarg); break; + + case 'W': + g.forever = 1; /* do not exit rx even with no traffic */ + break; + case 'b': /* burst */ g.burst = atoi(optarg); break; @@ -822,61 +1313,71 @@ main(int arc, char **argv) break; case 'P': - g.use_pcap = 1; + g.dev_type = DEV_PCAP; break; case 'D': /* destination mac */ - g.dst_mac = optarg; - { - struct ether_addr *mac = ether_aton(g.dst_mac); - D("ether_aton(%s) gives %p", g.dst_mac, mac); - } + g.dst_mac.name = optarg; break; + case 'S': /* source mac */ - g.src_mac = optarg; + g.src_mac.name = optarg; break; case 'v': verbose++; } } - if (ifname == NULL) { + if (g.ifname == NULL) { D("missing ifname"); usage(); } - { - int n = system_ncpus(); - if (g.cpus < 0 || g.cpus > n) { - D("%d cpus is too high, have only %d cpus", g.cpus, n); - usage(); - } - if (g.cpus == 0) - g.cpus = n; + + i = system_ncpus(); + if (g.cpus < 0 || g.cpus > i) { + D("%d cpus is too high, have only %d cpus", g.cpus, i); + usage(); } + if (g.cpus == 0) + g.cpus = i; + if (g.pkt_size < 16 || g.pkt_size > 1536) { D("bad pktsize %d\n", g.pkt_size); usage(); } - if (td_body == sender_body && g.src_mac == NULL) { - static char mybuf[20] = "ff:ff:ff:ff:ff:ff"; + if (g.src_mac.name == NULL) { + static char mybuf[20] = "00:00:00:00:00:00"; /* retrieve source mac address. */ - if (source_hwaddr(ifname, mybuf) == -1) { + if (source_hwaddr(g.ifname, mybuf) == -1) { D("Unable to retrieve source mac"); // continue, fail later } - g.src_mac = mybuf; + g.src_mac.name = mybuf; } + /* extract address ranges */ + extract_ip_range(&g.src_ip); + extract_ip_range(&g.dst_ip); + extract_mac_range(&g.src_mac); + extract_mac_range(&g.dst_mac); - if (g.use_pcap) { - D("using pcap on %s", ifname); - g.p = pcap_open_live(ifname, 0, 1, 100, pcap_errbuf); - if (g.p == NULL) { - D("cannot open pcap on %s", ifname); + if (g.dev_type == DEV_TAP) { + D("want to use tap %s", g.ifname); + g.main_fd = tap_alloc(g.ifname); + if (g.main_fd < 0) { + D("cannot open tap %s", g.ifname); + usage(); + } + } else if (g.dev_type > DEV_NETMAP) { + char pcap_errbuf[PCAP_ERRBUF_SIZE]; + + D("using pcap on %s", g.ifname); + pcap_errbuf[0] = '\0'; // init the buffer + g.p = pcap_open_live(g.ifname, 0, 1, 100, pcap_errbuf); + if (g.p == NULL) { + D("cannot open pcap on %s", g.ifname); usage(); } - mmap_addr = NULL; - fd = -1; } else { bzero(&nmr, sizeof(nmr)); nmr.nr_version = NETMAP_API; @@ -889,21 +1390,21 @@ main(int arc, char **argv) * which in turn may take some time for the PHY to * reconfigure. */ - fd = open("/dev/netmap", O_RDWR); - if (fd == -1) { + g.main_fd = open("/dev/netmap", O_RDWR); + if (g.main_fd == -1) { D("Unable to open /dev/netmap"); - exit(1); + // fail later } else { - if ((ioctl(fd, NIOCGINFO, &nmr)) == -1) { + if ((ioctl(g.main_fd, NIOCGINFO, &nmr)) == -1) { D("Unable to get if info without name"); } else { D("map size is %d Kb", nmr.nr_memsize >> 10); } bzero(&nmr, sizeof(nmr)); nmr.nr_version = NETMAP_API; - strncpy(nmr.nr_name, ifname, sizeof(nmr.nr_name)); - if ((ioctl(fd, NIOCGINFO, &nmr)) == -1) { - D("Unable to get if info for %s", ifname); + strncpy(nmr.nr_name, g.ifname, sizeof(nmr.nr_name)); + if ((ioctl(g.main_fd, NIOCGINFO, &nmr)) == -1) { + D("Unable to get if info for %s", g.ifname); } devqueues = nmr.nr_rx_rings; } @@ -919,11 +1420,12 @@ main(int arc, char **argv) * inside the body of the threads, we prefer to keep this * operation here to simplify the thread logic. */ - D("mmapping %d Kbytes", nmr.nr_memsize>>10); - mmap_addr = (struct netmap_d *) mmap(0, nmr.nr_memsize, + D("mapping %d Kbytes", nmr.nr_memsize>>10); + g.mmap_size = nmr.nr_memsize; + g.mmap_addr = (struct netmap_d *) mmap(0, nmr.nr_memsize, PROT_WRITE | PROT_READ, - MAP_SHARED, fd, 0); - if (mmap_addr == MAP_FAILED) { + MAP_SHARED, g.main_fd, 0); + if (g.mmap_addr == MAP_FAILED) { D("Unable to mmap %d KB", nmr.nr_memsize >> 10); // continue, fail later } @@ -937,8 +1439,8 @@ main(int arc, char **argv) * give time to cards that take a long time to reset the PHY. */ nmr.nr_version = NETMAP_API; - if (ioctl(fd, NIOCREGIF, &nmr) == -1) { - D("Unable to register interface %s", ifname); + if (ioctl(g.main_fd, NIOCREGIF, &nmr) == -1) { + D("Unable to register interface %s", g.ifname); //continue, fail later } @@ -946,19 +1448,19 @@ main(int arc, char **argv) /* Print some debug information. */ fprintf(stdout, "%s %s: %d queues, %d threads and %d cpus.\n", - (td_body == sender_body) ? "Sending on" : "Receiving from", - ifname, + (g.td_body == sender_body) ? "Sending on" : "Receiving from", + g.ifname, devqueues, g.nthreads, g.cpus); - if (td_body == sender_body) { + if (g.td_body == sender_body) { fprintf(stdout, "%s -> %s (%s -> %s)\n", - g.src_ip, g.dst_ip, - g.src_mac, g.dst_mac); + g.src_ip.name, g.dst_ip.name, + g.src_mac.name, g.dst_mac.name); } /* Exit if something went wrong. */ - if (fd < 0) { + if (g.main_fd < 0) { D("aborting"); usage(); } @@ -980,155 +1482,19 @@ main(int arc, char **argv) global_nthreads = g.nthreads; signal(SIGINT, sigint_h); - if (g.use_pcap) { - g.p = pcap_open_live(ifname, 0, 1, 100, NULL); +#if 0 // XXX this is not needed, i believe + if (g.dev_type > DEV_NETMAP) { + g.p = pcap_open_live(g.ifname, 0, 1, 100, NULL); if (g.p == NULL) { - D("cannot open pcap on %s", ifname); + D("cannot open pcap on %s", g.ifname); usage(); } else - D("using pcap %p on %s", g.p, ifname); + D("using pcap %p on %s", g.p, g.ifname); } - - targs = calloc(g.nthreads, sizeof(*targs)); - /* - * Now create the desired number of threads, each one - * using a single descriptor. - */ - for (i = 0; i < g.nthreads; i++) { - struct netmap_if *tnifp; - struct nmreq tifreq; - int tfd; - - if (g.use_pcap) { - tfd = -1; - tnifp = NULL; - } else { - /* register interface. */ - tfd = open("/dev/netmap", O_RDWR); - if (tfd == -1) { - D("Unable to open /dev/netmap"); - continue; - } - - bzero(&tifreq, sizeof(tifreq)); - strncpy(tifreq.nr_name, ifname, sizeof(tifreq.nr_name)); - tifreq.nr_version = NETMAP_API; - tifreq.nr_ringid = (g.nthreads > 1) ? (i | NETMAP_HW_RING) : 0; - - /* - * if we are acting as a receiver only, do not touch the transmit ring. - * This is not the default because many apps may use the interface - * in both directions, but a pure receiver does not. - */ - if (td_body == receiver_body) { - tifreq.nr_ringid |= NETMAP_NO_TX_POLL; - } - - if ((ioctl(tfd, NIOCREGIF, &tifreq)) == -1) { - D("Unable to register %s", ifname); - continue; - } - tnifp = NETMAP_IF(mmap_addr, tifreq.nr_offset); - } - /* start threads. */ - bzero(&targs[i], sizeof(targs[i])); - targs[i].g = &g; - targs[i].used = 1; - targs[i].completed = 0; - targs[i].fd = tfd; - targs[i].nmr = tifreq; - targs[i].nifp = tnifp; - targs[i].qfirst = (g.nthreads > 1) ? i : 0; - targs[i].qlast = (g.nthreads > 1) ? i+1 : - (td_body == receiver_body ? tifreq.nr_rx_rings : tifreq.nr_tx_rings); - targs[i].me = i; - targs[i].affinity = g.cpus ? i % g.cpus : -1; - if (td_body == sender_body) { - /* initialize the packet to send. */ - initialize_packet(&targs[i]); - } - - if (pthread_create(&targs[i].thread, NULL, td_body, - &targs[i]) == -1) { - D("Unable to create thread %d", i); - targs[i].used = 0; - } - } - - { - uint64_t my_count = 0, prev = 0; - uint64_t count = 0; - double delta_t; - struct timeval tic, toc; - - gettimeofday(&toc, NULL); - for (;;) { - struct timeval now, delta; - uint64_t pps; - int done = 0; - - delta.tv_sec = report_interval/1000; - delta.tv_usec = (report_interval%1000)*1000; - select(0, NULL, NULL, NULL, &delta); - gettimeofday(&now, NULL); - timersub(&now, &toc, &toc); - my_count = 0; - for (i = 0; i < g.nthreads; i++) { - my_count += targs[i].count; - if (targs[i].used == 0) - done++; - } - pps = toc.tv_sec* 1000000 + toc.tv_usec; - if (pps < 10000) - continue; - pps = ((my_count - prev) * 1000000 + pps / 2) / pps; - D("%" PRIu64 " pps", pps); - prev = my_count; - toc = now; - if (done == g.nthreads) - break; - } - - timerclear(&tic); - timerclear(&toc); - for (i = 0; i < g.nthreads; i++) { - /* - * Join active threads, unregister interfaces and close - * file descriptors. - */ - pthread_join(targs[i].thread, NULL); - ioctl(targs[i].fd, NIOCUNREGIF, &targs[i].nmr); - close(targs[i].fd); - - if (targs[i].completed == 0) - continue; - - /* - * Collect threads output and extract information about - * how long it took to send all the packets. - */ - count += targs[i].count; - if (!timerisset(&tic) || timercmp(&targs[i].tic, &tic, <)) - tic = targs[i].tic; - if (!timerisset(&toc) || timercmp(&targs[i].toc, &toc, >)) - toc = targs[i].toc; - } - - /* print output. */ - timersub(&toc, &tic, &toc); - delta_t = toc.tv_sec + 1e-6* toc.tv_usec; - if (td_body == sender_body) - tx_output(count, g.pkt_size, delta_t); - else - rx_output(count, delta_t); - } - - if (g.use_pcap == 0) { - ioctl(fd, NIOCUNREGIF, &nmr); - munmap(mmap_addr, nmr.nr_memsize); - close(fd); - } - - return (0); +#endif // XXX + start_threads(&g); + main_thread(&g); + return 0; } + /* end of file */ From cbc9087cba94662399cc4ff26b36d4c09292beb1 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sun, 17 Feb 2013 11:36:13 +0000 Subject: [PATCH 0228/1476] Remove trailing spaces. --- sys/sys/protosw.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/sys/protosw.h b/sys/sys/protosw.h index a74771e8e9e..d79e243af2c 100644 --- a/sys/sys/protosw.h +++ b/sys/sys/protosw.h @@ -203,7 +203,7 @@ struct pr_usrreqs { int (*pru_peeraddr)(struct socket *so, struct sockaddr **nam); int (*pru_rcvd)(struct socket *so, int flags); int (*pru_rcvoob)(struct socket *so, struct mbuf *m, int flags); - int (*pru_send)(struct socket *so, int flags, struct mbuf *m, + int (*pru_send)(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr, struct mbuf *control, struct thread *td); #define PRUS_OOB 0x1 @@ -211,7 +211,7 @@ struct pr_usrreqs { #define PRUS_MORETOCOME 0x4 int (*pru_sense)(struct socket *so, struct stat *sb); int (*pru_shutdown)(struct socket *so); - int (*pru_flush)(struct socket *so, int direction); + int (*pru_flush)(struct socket *so, int direction); int (*pru_sockaddr)(struct socket *so, struct sockaddr **nam); int (*pru_sosend)(struct socket *so, struct sockaddr *addr, struct uio *uio, struct mbuf *top, struct mbuf *control, From 5d48c4778a59ff6cb602f8e9f6fdd6db0bd74cd0 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sun, 17 Feb 2013 11:36:41 +0000 Subject: [PATCH 0229/1476] Remove redundant space. --- sys/sys/namei.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/sys/namei.h b/sys/sys/namei.h index 04e7b59fb46..3b439160bc2 100644 --- a/sys/sys/namei.h +++ b/sys/sys/namei.h @@ -145,7 +145,7 @@ struct nameidata { #define NOCROSSMOUNT 0x00400000 /* do not cross mount points */ #define NOMACCHECK 0x00800000 /* do not perform MAC checks */ #define AUDITVNODE1 0x04000000 /* audit the looked up vnode information */ -#define AUDITVNODE2 0x08000000 /* audit the looked up vnode information */ +#define AUDITVNODE2 0x08000000 /* audit the looked up vnode information */ #define TRAILINGSLASH 0x10000000 /* path ended in a slash */ #define NOCAPCHECK 0x20000000 /* do not perform capability checks */ #define PARAMASK 0x3ffffe00 /* mask of parameter descriptors */ From de26549841451dbd8b2221b894a3ee593cbf9b5d Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sun, 17 Feb 2013 11:47:01 +0000 Subject: [PATCH 0230/1476] Remove redundant parenthesis. --- sys/kern/kern_fork.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 0d2709f5f6f..287d202eed9 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -942,7 +942,7 @@ fail1: vmspace_free(vm2); uma_zfree(proc_zone, newproc); #ifdef PROCDESC - if (((flags & RFPROCDESC) != 0) && (fp_procdesc != NULL)) { + if ((flags & RFPROCDESC) != 0 && fp_procdesc != NULL) { fdclose(td->td_proc->p_fd, fp_procdesc, *procdescp, td); fdrop(fp_procdesc, td); } From 4881a5950eaca332365672a8aa6e6e199d6ffaa6 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sun, 17 Feb 2013 11:47:30 +0000 Subject: [PATCH 0231/1476] Don't treat pointers as booleans. --- sys/kern/kern_descrip.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index fc74bdbd8d4..9de55e82443 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -1949,11 +1949,11 @@ fdfree(struct thread *td) fdp->fd_jdir = NULL; FILEDESC_XUNLOCK(fdp); - if (cdir) + if (cdir != NULL) vrele(cdir); - if (rdir) + if (rdir != NULL) vrele(rdir); - if (jdir) + if (jdir != NULL) vrele(jdir); fddrop(fdp); From 6c08be2b88801aa6628671bcf802df340f924710 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sun, 17 Feb 2013 11:47:58 +0000 Subject: [PATCH 0232/1476] Add break to the default case. --- sys/kern/kern_sig.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 5bb49a834aa..7d3634d337d 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -3130,6 +3130,7 @@ corefile_open(const char *comm, uid_t uid, pid_t pid, struct thread *td, break; default: sbuf_putc(&sb, format[i]); + break; } } free(hostname, M_TEMP); From 49549b18949b0a9b834e74af74a7e1aa57510ef5 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sun, 17 Feb 2013 11:48:16 +0000 Subject: [PATCH 0233/1476] Remove redundant space. --- sys/kern/sys_pipe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c index 338256c7209..5d0c4344f0e 100644 --- a/sys/kern/sys_pipe.c +++ b/sys/kern/sys_pipe.c @@ -473,7 +473,7 @@ sys_pipe(struct thread *td, struct pipe_args *uap) error = kern_pipe(td, fildes); if (error) return (error); - + td->td_retval[0] = fildes[0]; td->td_retval[1] = fildes[1]; From 11b0cfe3cd5e0dfb756eb587781d22d676e7a908 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sun, 17 Feb 2013 11:49:21 +0000 Subject: [PATCH 0234/1476] Remove redundant parenthesis. --- sys/kern/sys_capability.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/kern/sys_capability.c b/sys/kern/sys_capability.c index fa763561682..6fb4feee559 100644 --- a/sys/kern/sys_capability.c +++ b/sys/kern/sys_capability.c @@ -113,7 +113,7 @@ sys_cap_getmode(struct thread *td, struct cap_getmode_args *uap) { u_int i; - i = (IN_CAPABILITY_MODE(td)) ? 1 : 0; + i = IN_CAPABILITY_MODE(td) ? 1 : 0; return (copyout(&i, uap->modep, sizeof(i))); } From 8e1d51ab40c56eee8bc24a2825ea0a128fd47bb0 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sun, 17 Feb 2013 11:53:51 +0000 Subject: [PATCH 0235/1476] - Require CAP_FSYNC capability right when opening a file with O_SYNC or O_FSYNC flags. - While here simplify check for locking flags. Sponsored by: The FreeBSD Foundation --- sys/kern/vfs_syscalls.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index dd1232cf9ba..12855a2c3d9 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -980,7 +980,10 @@ flags_to_rights(int flags) if (flags & O_TRUNC) rights |= CAP_FTRUNCATE; - if ((flags & O_EXLOCK) || (flags & O_SHLOCK)) + if (flags & (O_SYNC | O_FSYNC)) + rights |= CAP_FSYNC; + + if (flags & (O_EXLOCK | O_SHLOCK)) rights |= CAP_FLOCK; return (rights); From f0ad2ecb9ca363436ba130649401adaf5178065e Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sun, 17 Feb 2013 11:56:36 +0000 Subject: [PATCH 0236/1476] Style. --- sys/kern/vfs_syscalls.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 12855a2c3d9..bbda70d53be 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -3268,8 +3268,7 @@ kern_futimes(struct thread *td, int fd, struct timeval *tptr, AUDIT_ARG_FD(fd); if ((error = getutimes(tptr, tptrseg, ts)) != 0) return (error); - if ((error = getvnode(td->td_proc->p_fd, fd, CAP_FUTIMES, &fp)) - != 0) + if ((error = getvnode(td->td_proc->p_fd, fd, CAP_FUTIMES, &fp)) != 0) return (error); #ifdef AUDIT vn_lock(fp->f_vnode, LK_SHARED | LK_RETRY); @@ -3419,8 +3418,7 @@ sys_fsync(td, uap) int error, lock_flags; AUDIT_ARG_FD(uap->fd); - if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_FSYNC, - &fp)) != 0) + if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_FSYNC, &fp)) != 0) return (error); vp = fp->f_vnode; if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) @@ -3529,8 +3527,7 @@ kern_renameat(struct thread *td, int oldfd, char *old, int newfd, char *new, goto out1; } NDINIT_ATRIGHTS(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | - SAVESTART | AUDITVNODE2, pathseg, new, newfd, CAP_CREATE, - td); + SAVESTART | AUDITVNODE2, pathseg, new, newfd, CAP_CREATE, td); if (fromnd.ni_vp->v_type == VDIR) tond.ni_cnd.cn_flags |= WILLBEDIR; if ((error = namei(&tond)) != 0) { @@ -3829,8 +3826,7 @@ kern_ogetdirentries(struct thread *td, struct ogetdirentries_args *uap, /* XXX arbitrary sanity limit on `count'. */ if (uap->count > 64 * 1024) return (EINVAL); - if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_READ, - &fp)) != 0) + if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_READ, &fp)) != 0) return (error); if ((fp->f_flag & FREAD) == 0) { fdrop(fp, td); @@ -4621,7 +4617,7 @@ kern_posix_fadvise(struct thread *td, int fd, off_t offset, off_t len, error = fget(td, fd, 0, &fp); if (error != 0) goto out; - + switch (fp->f_type) { case DTYPE_VNODE: break; From 89adaea91f57433a370057204942ecef211827eb Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sun, 17 Feb 2013 11:57:47 +0000 Subject: [PATCH 0237/1476] Remove redundant check. --- sys/security/audit/audit_bsm.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sys/security/audit/audit_bsm.c b/sys/security/audit/audit_bsm.c index b02d677e45b..8881ceaf556 100644 --- a/sys/security/audit/audit_bsm.c +++ b/sys/security/audit/audit_bsm.c @@ -223,9 +223,7 @@ kau_free(struct au_record *rec) } while (0) #define UPATH1_VNODE1_TOKENS do { \ - if (ARG_IS_VALID(kar, ARG_UPATH1)) { \ - UPATH1_TOKENS; \ - } \ + UPATH1_TOKENS; \ if (ARG_IS_VALID(kar, ARG_VNODE1)) { \ tok = au_to_attr32(&ar->ar_arg_vnode1); \ kau_write(rec, tok); \ From 09abcabae689a95e7f561ebf40d0f16bdcdef962 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sun, 17 Feb 2013 11:58:30 +0000 Subject: [PATCH 0238/1476] Remove space before tab. --- sys/sys/filedesc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h index 855d2b3bb0c..07cfb1f921d 100644 --- a/sys/sys/filedesc.h +++ b/sys/sys/filedesc.h @@ -88,7 +88,7 @@ struct filedesc_to_leader { /* * Per-process open flags. */ -#define UF_EXCLOSE 0x01 /* auto-close on exec */ +#define UF_EXCLOSE 0x01 /* auto-close on exec */ #ifdef _KERNEL From 312c5e1aeb675367019790eada379522a91a65e9 Mon Sep 17 00:00:00 2001 From: "Andrey A. Chernov" Date: Sun, 17 Feb 2013 13:06:59 +0000 Subject: [PATCH 0239/1476] In 'make hierarchy' don't install /sys/sys pointing to usr/src/sys but just /sys pointing there --- etc/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/Makefile b/etc/Makefile index 81ef45a09f1..7c4cea51cff 100644 --- a/etc/Makefile +++ b/etc/Makefile @@ -354,7 +354,7 @@ distrib-dirs: ${METALOG.add} ; \ done; true .endif - ${INSTALL_SYMLINK} usr/src/sys ${DESTDIR}/sys + ${INSTALL_SYMLINK} usr/src/sys ${DESTDIR}/ cd ${DESTDIR}/usr/share/man; \ for mandir in man*; do \ ${INSTALL_SYMLINK} ../$$mandir \ From a937c5078f846614248794a0f01f02aa012d21b5 Mon Sep 17 00:00:00 2001 From: Alexander Motin Date: Sun, 17 Feb 2013 18:42:30 +0000 Subject: [PATCH 0240/1476] MFcalloutng: Microoptimize i8254 one-shot operation mode (disabled by default to allow timecounter functionality) by not writing to mode and MSB registers when it is not required. This saves several microseconds of CPU time per call, reducing minimal measured interrupts interval to 19.5us. --- sys/x86/isa/clock.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/sys/x86/isa/clock.c b/sys/x86/isa/clock.c index a74c11f563a..42cc4485aa6 100644 --- a/sys/x86/isa/clock.c +++ b/sys/x86/isa/clock.c @@ -125,6 +125,8 @@ struct attimer_softc { static struct attimer_softc *attimer_sc = NULL; static int timer0_period = -2; +static int timer0_mode = 0xffff; +static int timer0_last = 0xffff; /* Values for timerX_state: */ #define RELEASED 0 @@ -404,7 +406,7 @@ DELAY(int n) static void set_i8254_freq(int mode, uint32_t period) { - int new_count; + int new_count, new_mode; mtx_lock_spin(&clock_lock); if (mode == MODE_STOP) { @@ -423,21 +425,34 @@ set_i8254_freq(int mode, uint32_t period) timer0_period = (mode == MODE_PERIODIC) ? new_count : -1; switch (mode) { case MODE_STOP: - outb(TIMER_MODE, TIMER_SEL0 | TIMER_INTTC | TIMER_16BIT); + new_mode = TIMER_SEL0 | TIMER_INTTC | TIMER_16BIT; + outb(TIMER_MODE, new_mode); outb(TIMER_CNTR0, 0); outb(TIMER_CNTR0, 0); break; case MODE_PERIODIC: - outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); + new_mode = TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT; + outb(TIMER_MODE, new_mode); outb(TIMER_CNTR0, new_count & 0xff); outb(TIMER_CNTR0, new_count >> 8); break; case MODE_ONESHOT: - outb(TIMER_MODE, TIMER_SEL0 | TIMER_INTTC | TIMER_16BIT); + if (new_count < 256 && timer0_last < 256) { + new_mode = TIMER_SEL0 | TIMER_INTTC | TIMER_LSB; + if (new_mode != timer0_mode) + outb(TIMER_MODE, new_mode); + outb(TIMER_CNTR0, new_count & 0xff); + break; + } + new_mode = TIMER_SEL0 | TIMER_INTTC | TIMER_16BIT; + if (new_mode != timer0_mode) + outb(TIMER_MODE, new_mode); outb(TIMER_CNTR0, new_count & 0xff); outb(TIMER_CNTR0, new_count >> 8); break; } + timer0_mode = new_mode; + timer0_last = new_count; out: mtx_unlock_spin(&clock_lock); } @@ -447,6 +462,8 @@ i8254_restore(void) { timer0_period = -2; + timer0_mode = 0xffff; + timer0_last = 0xffff; if (attimer_sc != NULL) set_i8254_freq(attimer_sc->mode, attimer_sc->period); else From 43e1adfa058948faea5664afc3abfdfdf902408d Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Sun, 17 Feb 2013 19:48:23 +0000 Subject: [PATCH 0241/1476] Strengthen the check in IS_OUT_OF_BOUNDS to ensure that (j - 1) is a valid index into the input buffer. PR: bin/175213 Reviewed by: gabor Approved by: emaste (co-mentor) MFC after: 1 week --- usr.bin/grep/regex/tre-fastmatch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr.bin/grep/regex/tre-fastmatch.c b/usr.bin/grep/regex/tre-fastmatch.c index b7a7c91fbcf..640ee3d6344 100644 --- a/usr.bin/grep/regex/tre-fastmatch.c +++ b/usr.bin/grep/regex/tre-fastmatch.c @@ -103,7 +103,7 @@ static int fastcmp(const fastmatch_t *fg, const void *data, ((!fg->reversed \ ? ((type == STR_WIDE) ? ((j + fg->wlen) > len) \ : ((j + fg->len) > len)) \ - : (j < 0))) + : (j <= 0))) /* * Checks whether the new position after shifting in the input string From bb7ca8229d836df951d46e4a93828d2a0a68c829 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sun, 17 Feb 2013 20:35:54 +0000 Subject: [PATCH 0242/1476] Do not update the fsinfo block on each update of any fat block, this is excessive. Postpone the flush of the fsinfo to VFS_SYNC(), remembering the need for update with the flag MSDOSFS_FSIMOD, stored in pm_flags. FAT32 specification describes both FSI_Free_Count and FSI_Nxt_Free as the advisory hints, not requiring them to be correct. Based on the patch from bde, modified by me. Reviewed by: bde MFC after: 2 weeks --- sys/fs/msdosfs/msdosfs_fat.c | 36 ++++++------------------------- sys/fs/msdosfs/msdosfs_vfsops.c | 38 +++++++++++++++++++++++++++++++++ sys/fs/msdosfs/msdosfsmount.h | 1 + 3 files changed, 45 insertions(+), 30 deletions(-) diff --git a/sys/fs/msdosfs/msdosfs_fat.c b/sys/fs/msdosfs/msdosfs_fat.c index 39940422b9f..c660601126b 100644 --- a/sys/fs/msdosfs/msdosfs_fat.c +++ b/sys/fs/msdosfs/msdosfs_fat.c @@ -328,29 +328,6 @@ updatefats(pmp, bp, fatbn) printf("updatefats(pmp %p, bp %p, fatbn %lu)\n", pmp, bp, fatbn); #endif - /* - * If we have an FSInfo block, update it. - */ - if (pmp->pm_fsinfo) { - if (bread(pmp->pm_devvp, pmp->pm_fsinfo, pmp->pm_BytesPerSec, - NOCRED, &bpn) != 0) { - /* - * Ignore the error, but turn off FSInfo update for the future. - */ - pmp->pm_fsinfo = 0; - brelse(bpn); - } else { - struct fsinfo *fp = (struct fsinfo *)bpn->b_data; - - putulong(fp->fsinfree, pmp->pm_freeclustercount); - putulong(fp->fsinxtfree, pmp->pm_nxtfree); - if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT) - bwrite(bpn); - else - bdwrite(bpn); - } - } - if (pmp->pm_flags & MSDOSFS_FATMIRROR) { /* * Now copy the block(s) of the modified fat to the other copies of @@ -393,9 +370,6 @@ updatefats(pmp, bp, fatbn) bwrite(bp); else bdwrite(bp); - /* - * Maybe update fsinfo sector here? - */ } /* @@ -431,6 +405,7 @@ usemap_alloc(pmp, cn) pmp->pm_inusemap[cn / N_INUSEBITS] |= 1 << (cn % N_INUSEBITS); KASSERT(pmp->pm_freeclustercount > 0, ("usemap_alloc: too little")); pmp->pm_freeclustercount--; + pmp->pm_flags |= MSDOSFS_FSIMOD; } static __inline void @@ -441,6 +416,7 @@ usemap_free(pmp, cn) MSDOSFS_ASSERT_MP_LOCKED(pmp); pmp->pm_freeclustercount++; + pmp->pm_flags |= MSDOSFS_FSIMOD; KASSERT((pmp->pm_inusemap[cn / N_INUSEBITS] & (1 << (cn % N_INUSEBITS))) != 0, ("Freeing unused sector %ld %ld %x", cn, cn % N_INUSEBITS, (unsigned)pmp->pm_inusemap[cn / N_INUSEBITS])); @@ -742,7 +718,10 @@ chainalloc(pmp, start, count, fillwith, retcluster, got) for (cl = start, n = count; n-- > 0;) usemap_alloc(pmp, cl++); - + pmp->pm_nxtfree = start + count; + if (pmp->pm_nxtfree > pmp->pm_maxcluster) + pmp->pm_nxtfree = CLUST_FIRST; + pmp->pm_flags |= MSDOSFS_FSIMOD; error = fatchain(pmp, start, count, fillwith); if (error != 0) return (error); @@ -754,9 +733,6 @@ chainalloc(pmp, start, count, fillwith, retcluster, got) *retcluster = start; if (got) *got = count; - pmp->pm_nxtfree = start + count; - if (pmp->pm_nxtfree > pmp->pm_maxcluster) - pmp->pm_nxtfree = CLUST_FIRST; return (0); } diff --git a/sys/fs/msdosfs/msdosfs_vfsops.c b/sys/fs/msdosfs/msdosfs_vfsops.c index a209970922e..213dd00f2d1 100644 --- a/sys/fs/msdosfs/msdosfs_vfsops.c +++ b/sys/fs/msdosfs/msdosfs_vfsops.c @@ -896,6 +896,40 @@ msdosfs_statfs(struct mount *mp, struct statfs *sbp) return (0); } +/* + * If we have an FSInfo block, update it. + */ +static int +msdosfs_fsiflush(struct msdosfsmount *pmp, int waitfor) +{ + struct fsinfo *fp; + struct buf *bp; + int error; + + MSDOSFS_LOCK_MP(pmp); + if (pmp->pm_fsinfo == 0 || (pmp->pm_flags & MSDOSFS_FSIMOD) == 0) { + error = 0; + goto unlock; + } + error = bread(pmp->pm_devvp, pmp->pm_fsinfo, pmp->pm_BytesPerSec, + NOCRED, &bp); + if (error != 0) { + brelse(bp); + goto unlock; + } + fp = (struct fsinfo *)bp->b_data; + putulong(fp->fsinfree, pmp->pm_freeclustercount); + putulong(fp->fsinxtfree, pmp->pm_nxtfree); + pmp->pm_flags &= ~MSDOSFS_FSIMOD; + if (waitfor == MNT_WAIT) + error = bwrite(bp); + else + bawrite(bp); +unlock: + MSDOSFS_UNLOCK_MP(pmp); + return (error); +} + static int msdosfs_sync(struct mount *mp, int waitfor) { @@ -958,6 +992,10 @@ loop: allerror = error; VOP_UNLOCK(pmp->pm_devvp, 0); } + + error = msdosfs_fsiflush(pmp, waitfor); + if (error != 0) + allerror = error; return (allerror); } diff --git a/sys/fs/msdosfs/msdosfsmount.h b/sys/fs/msdosfs/msdosfsmount.h index 673095ed69f..10ed95b542f 100644 --- a/sys/fs/msdosfs/msdosfsmount.h +++ b/sys/fs/msdosfs/msdosfsmount.h @@ -262,6 +262,7 @@ struct msdosfs_args { #define MSDOSFSMNT_WAITONFAT 0x40000000 /* mounted synchronous */ #define MSDOSFS_FATMIRROR 0x20000000 /* FAT is mirrored */ #define MSDOSFS_LARGEFS 0x10000000 /* perform fileno mapping */ +#define MSDOSFS_FSIMOD 0x01000000 #define MSDOSFS_ARGSMAGIC 0xe4eff300 From d6e636c98852fbae89c94bde764872f0d510dca0 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sun, 17 Feb 2013 21:12:34 +0000 Subject: [PATCH 0243/1476] - Add support for 'memsync' mode. This is the fastest replication mode that's why it will now be the default. - Bump protocol version to 2 and add backward compatibility for version 1. - Allow to specify hosts by kern.hostid as well (in addition to hostname and kern.hostuuid) in configuration file. Sponsored by: Panzura Tested by: trociny --- sbin/hastd/hast.conf.5 | 11 +-- sbin/hastd/hast.h | 9 +- sbin/hastd/hast_proto.c | 4 +- sbin/hastd/hastd.c | 21 ++++- sbin/hastd/parse.y | 41 +++++++-- sbin/hastd/primary.c | 186 +++++++++++++++++++++++++++++++++++----- sbin/hastd/refcnt.h | 57 ++++++++++++ sbin/hastd/secondary.c | 48 ++++++++++- 8 files changed, 334 insertions(+), 43 deletions(-) create mode 100644 sbin/hastd/refcnt.h diff --git a/sbin/hastd/hast.conf.5 b/sbin/hastd/hast.conf.5 index f6368bcf913..3d921e46c03 100644 --- a/sbin/hastd/hast.conf.5 +++ b/sbin/hastd/hast.conf.5 @@ -129,9 +129,13 @@ The .Aq node argument can be replaced either by a full hostname as obtained by .Xr gethostname 3 , -only first part of the hostname, or by node's UUID as found in the +only first part of the hostname, by node's UUID as found in the .Va kern.hostuuid .Xr sysctl 8 +variable +or by node's hostid as found in the +.Va kern.hostid +.Xr sysctl 8 variable. .Pp The following statements are available: @@ -208,15 +212,12 @@ to the application was lost. The risk of such a situation is very small. The .Ic memsync -replication mode is currently not implemented. +replication mode is the default. .It Ic fullsync .Pp Mark the write operation as completed when local as well as remote write completes. This is the safest and the slowest replication mode. -The -.Ic fullsync -replication mode is the default. .It Ic async .Pp The write operation is reported as complete right after the local write diff --git a/sbin/hastd/hast.h b/sbin/hastd/hast.h index 263e9841094..c7a6b49b292 100644 --- a/sbin/hastd/hast.h +++ b/sbin/hastd/hast.h @@ -53,8 +53,9 @@ * Version history: * 0 - initial version * 1 - HIO_KEEPALIVE added + * 2 - "memsync" and "received" attributes added for memsync mode */ -#define HAST_PROTO_VERSION 1 +#define HAST_PROTO_VERSION 2 #define EHAST_OK 0 #define EHAST_NOENTRY 1 @@ -142,8 +143,10 @@ struct hastd_config { struct hast_resource { /* Resource name. */ char hr_name[NAME_MAX]; - /* Replication mode (HAST_REPLICATION_*). */ + /* Negotiated replication mode (HAST_REPLICATION_*). */ int hr_replication; + /* Configured replication mode (HAST_REPLICATION_*). */ + int hr_original_replication; /* Provider name that will appear in /dev/hast/. */ char hr_provname[NAME_MAX]; /* Synchronization extent size. */ @@ -156,6 +159,8 @@ struct hast_resource { int hr_compression; /* Checksum algorithm. */ int hr_checksum; + /* Protocol version. */ + int hr_version; /* Path to local component. */ char hr_localpath[PATH_MAX]; diff --git a/sbin/hastd/hast_proto.c b/sbin/hastd/hast_proto.c index 039e7671587..dd41fb1aaba 100644 --- a/sbin/hastd/hast_proto.c +++ b/sbin/hastd/hast_proto.c @@ -112,7 +112,7 @@ hast_proto_send(const struct hast_resource *res, struct proto_conn *conn, if (eb == NULL) goto end; - hdr.version = HAST_PROTO_VERSION; + hdr.version = res != NULL ? res->hr_version : HAST_PROTO_VERSION; hdr.size = htole32((uint32_t)ebuf_size(eb)); if (ebuf_add_head(eb, &hdr, sizeof(hdr)) == -1) goto end; @@ -144,7 +144,7 @@ hast_proto_recv_hdr(const struct proto_conn *conn, struct nv **nvp) if (proto_recv(conn, &hdr, sizeof(hdr)) == -1) goto fail; - if (hdr.version != HAST_PROTO_VERSION) { + if (hdr.version > HAST_PROTO_VERSION) { errno = ERPCMISMATCH; goto fail; } diff --git a/sbin/hastd/hastd.c b/sbin/hastd/hastd.c index ccce81daad7..06b38e91331 100644 --- a/sbin/hastd/hastd.c +++ b/sbin/hastd/hastd.c @@ -68,7 +68,7 @@ static struct hastd_config *cfg; bool sigexit_received = false; /* Path to pidfile. */ static const char *pidfile; -/* PID file handle. */ +/* Pidfile handle. */ struct pidfh *pfh; /* Do we run in foreground? */ static bool foreground; @@ -748,6 +748,7 @@ listen_accept(struct hastd_listen *lst) const char *resname; const unsigned char *token; char laddr[256], raddr[256]; + uint8_t version; size_t size; pid_t pid; int status; @@ -797,6 +798,20 @@ listen_accept(struct hastd_listen *lst) goto close; } pjdlog_debug(2, "%s: resource=%s", raddr, resname); + version = nv_get_uint8(nvin, "version"); + pjdlog_debug(2, "%s: version=%hhu", raddr, version); + if (version == 0) { + /* + * If no version is sent, it means this is protocol version 1. + */ + version = 1; + } + if (version > HAST_PROTO_VERSION) { + pjdlog_info("Remote protocol version %hhu is not supported, falling back to version %hhu.", + version, (unsigned char)HAST_PROTO_VERSION); + version = HAST_PROTO_VERSION; + } + pjdlog_debug(1, "Negotiated protocol version %hhu.", version); token = nv_get_uint8_array(nvin, &size, "token"); /* * NULL token means that this is first connection. @@ -910,8 +925,10 @@ listen_accept(struct hastd_listen *lst) */ if (token == NULL) { + res->hr_version = version; arc4random_buf(res->hr_token, sizeof(res->hr_token)); nvout = nv_alloc(); + nv_add_uint8(nvout, version, "version"); nv_add_uint8_array(nvout, res->hr_token, sizeof(res->hr_token), "token"); if (nv_error(nvout) != 0) { @@ -922,7 +939,7 @@ listen_accept(struct hastd_listen *lst) strerror(nv_error(nvout))); goto fail; } - if (hast_proto_send(NULL, conn, nvout, NULL, 0) == -1) { + if (hast_proto_send(res, conn, nvout, NULL, 0) == -1) { int error = errno; pjdlog_errno(LOG_ERR, "Unable to send response to %s", diff --git a/sbin/hastd/parse.y b/sbin/hastd/parse.y index 04ea7ab2513..bd0690a02ab 100644 --- a/sbin/hastd/parse.y +++ b/sbin/hastd/parse.y @@ -236,6 +236,7 @@ replication_statement: REPLICATION replication_type case 1: PJDLOG_ASSERT(curres != NULL); curres->hr_replication = $2; + curres->hr_original_replication = $2; break; default: PJDLOG_ABORT("replication at wrong depth level"); @@ -533,8 +534,10 @@ resource_start: STR curres->hr_role = HAST_ROLE_INIT; curres->hr_previous_role = HAST_ROLE_INIT; curres->hr_replication = -1; + curres->hr_original_replication = -1; curres->hr_checksum = -1; curres->hr_compression = -1; + curres->hr_version = 1; curres->hr_timeout = -1; curres->hr_exec[0] = '\0'; curres->hr_provname[0] = '\0'; @@ -724,6 +727,7 @@ static int isitme(const char *name) { char buf[MAXHOSTNAMELEN]; + unsigned long hostid; char *pos; size_t bufsize; @@ -738,7 +742,7 @@ isitme(const char *name) return (1); /* - * Now check if it matches first part of the host name. + * Check if it matches first part of the host name. */ pos = strchr(buf, '.'); if (pos != NULL && (size_t)(pos - buf) == strlen(name) && @@ -747,7 +751,7 @@ isitme(const char *name) } /* - * At the end check if name is equal to our host's UUID. + * Check if it matches host UUID. */ bufsize = sizeof(buf); if (sysctlbyname("kern.hostuuid", buf, &bufsize, NULL, 0) < 0) { @@ -757,6 +761,18 @@ isitme(const char *name) if (strcasecmp(buf, name) == 0) return (1); + /* + * Check if it matches hostid. + */ + bufsize = sizeof(hostid); + if (sysctlbyname("kern.hostid", &hostid, &bufsize, NULL, 0) < 0) { + pjdlog_errno(LOG_ERR, "sysctlbyname(kern.hostid) failed"); + return (-1); + } + (void)snprintf(buf, sizeof(buf), "hostid%lu", hostid); + if (strcmp(buf, name) == 0) + return (1); + /* * Looks like this isn't about us. */ @@ -769,7 +785,7 @@ family_supported(int family) int sock; sock = socket(family, SOCK_STREAM, 0); - if (sock == -1 && errno == EAFNOSUPPORT) + if (sock == -1 && errno == EPROTONOSUPPORT) return (false); if (sock >= 0) (void)close(sock); @@ -781,6 +797,7 @@ node_names(char **namesp) { static char names[MAXHOSTNAMELEN * 3]; char buf[MAXHOSTNAMELEN]; + unsigned long hostid; char *pos; size_t bufsize; @@ -808,6 +825,16 @@ node_names(char **namesp) return (-1); } (void)strlcat(names, buf, sizeof(names)); + (void)strlcat(names, ", ", sizeof(names)); + + /* Host ID. */ + bufsize = sizeof(hostid); + if (sysctlbyname("kern.hostid", &hostid, &bufsize, NULL, 0) < 0) { + pjdlog_errno(LOG_ERR, "sysctlbyname(kern.hostid) failed"); + return (-1); + } + (void)snprintf(buf, sizeof(buf), "hostid%lu", hostid); + (void)strlcat(names, buf, sizeof(names)); *namesp = names; @@ -833,7 +860,7 @@ yy_config_parse(const char *config, bool exitonerror) lineno = 0; depth0_timeout = HAST_TIMEOUT; - depth0_replication = HAST_REPLICATION_FULLSYNC; + depth0_replication = HAST_REPLICATION_MEMSYNC; depth0_checksum = HAST_CHECKSUM_NONE; depth0_compression = HAST_COMPRESSION_HOLE; strlcpy(depth0_control, HAST_CONTROL, sizeof(depth0_control)); @@ -943,11 +970,7 @@ yy_config_parse(const char *config, bool exitonerror) * Use global or default setting. */ curres->hr_replication = depth0_replication; - } - if (curres->hr_replication == HAST_REPLICATION_MEMSYNC) { - pjdlog_warning("Replication mode \"%s\" is not implemented, falling back to \"%s\".", - "memsync", "fullsync"); - curres->hr_replication = HAST_REPLICATION_FULLSYNC; + curres->hr_original_replication = depth0_replication; } if (curres->hr_checksum == -1) { /* diff --git a/sbin/hastd/primary.c b/sbin/hastd/primary.c index 88159cb6bec..fb49ef61f05 100644 --- a/sbin/hastd/primary.c +++ b/sbin/hastd/primary.c @@ -35,7 +35,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include @@ -65,6 +64,7 @@ __FBSDID("$FreeBSD$"); #include "metadata.h" #include "proto.h" #include "pjdlog.h" +#include "refcnt.h" #include "subr.h" #include "synch.h" @@ -543,7 +543,7 @@ primary_connect(struct hast_resource *res, struct proto_conn **connp) return (0); } - + /* * Function instructs GEOM_GATE to handle reads directly from within the kernel. */ @@ -577,6 +577,7 @@ init_remote(struct hast_resource *res, struct proto_conn **inp, int32_t extentsize; int64_t datasize; uint32_t mapsize; + uint8_t version; size_t size; int error; @@ -597,6 +598,7 @@ init_remote(struct hast_resource *res, struct proto_conn **inp, */ nvout = nv_alloc(); nv_add_string(nvout, res->hr_name, "resource"); + nv_add_uint8(nvout, HAST_PROTO_VERSION, "version"); if (nv_error(nvout) != 0) { pjdlog_common(LOG_WARNING, 0, nv_error(nvout), "Unable to allocate header for connection with %s", @@ -626,6 +628,20 @@ init_remote(struct hast_resource *res, struct proto_conn **inp, nv_free(nvin); goto close; } + version = nv_get_uint8(nvin, "version"); + if (version == 0) { + /* + * If no version is sent, it means this is protocol version 1. + */ + version = 1; + } + if (version > HAST_PROTO_VERSION) { + pjdlog_warning("Invalid version received (%hhu).", version); + nv_free(nvin); + goto close; + } + res->hr_version = version; + pjdlog_debug(1, "Negotiated protocol version %d.", res->hr_version); token = nv_get_uint8_array(nvin, &size, "token"); if (token == NULL) { pjdlog_warning("Handshake header from %s has no 'token' field.", @@ -776,6 +792,16 @@ init_remote(struct hast_resource *res, struct proto_conn **inp, pjdlog_errno(LOG_WARNING, "Unable to set connection direction"); #endif pjdlog_info("Connected to %s.", res->hr_remoteaddr); + if (res->hr_original_replication == HAST_REPLICATION_MEMSYNC && + res->hr_version < 2) { + pjdlog_warning("The 'memsync' replication mode is not supported by the remote node, falling back to 'fullsync' mode."); + res->hr_replication = HAST_REPLICATION_FULLSYNC; + } else if (res->hr_replication != res->hr_original_replication) { + /* + * This is in case hastd disconnected and was upgraded. + */ + res->hr_replication = res->hr_original_replication; + } if (inp != NULL && outp != NULL) { *inp = in; *outp = out; @@ -1009,7 +1035,8 @@ hastd_primary(struct hast_resource *res) } static void -reqlog(int loglevel, int debuglevel, struct g_gate_ctl_io *ggio, const char *fmt, ...) +reqlog(int loglevel, int debuglevel, struct g_gate_ctl_io *ggio, + const char *fmt, ...) { char msg[1024]; va_list ap; @@ -1020,21 +1047,18 @@ reqlog(int loglevel, int debuglevel, struct g_gate_ctl_io *ggio, const char *fmt switch (ggio->gctl_cmd) { case BIO_READ: (void)snprlcat(msg, sizeof(msg), "READ(%ju, %ju).", - (uintmax_t)ggio->gctl_offset, - (uintmax_t)ggio->gctl_length); + (uintmax_t)ggio->gctl_offset, (uintmax_t)ggio->gctl_length); break; case BIO_DELETE: (void)snprlcat(msg, sizeof(msg), "DELETE(%ju, %ju).", - (uintmax_t)ggio->gctl_offset, - (uintmax_t)ggio->gctl_length); + (uintmax_t)ggio->gctl_offset, (uintmax_t)ggio->gctl_length); break; case BIO_FLUSH: (void)snprlcat(msg, sizeof(msg), "FLUSH."); break; case BIO_WRITE: (void)snprlcat(msg, sizeof(msg), "WRITE(%ju, %ju).", - (uintmax_t)ggio->gctl_offset, - (uintmax_t)ggio->gctl_length); + (uintmax_t)ggio->gctl_offset, (uintmax_t)ggio->gctl_length); break; default: (void)snprlcat(msg, sizeof(msg), "UNKNOWN(%u).", @@ -1274,8 +1298,13 @@ ggate_recv_thread(void *arg) } pjdlog_debug(2, "ggate_recv: (%p) Moving request to the send queues.", hio); - refcount_init(&hio->hio_countdown, ncomps); - for (ii = ncomp; ii < ncomp + ncomps; ii++) + hio->hio_countdown = ncomps; + if (hio->hio_replication == HAST_REPLICATION_MEMSYNC && + ggio->gctl_cmd == BIO_WRITE) { + /* Each remote request needs two responses in memsync. */ + hio->hio_countdown++; + } + for (ii = ncomp; ii < ncomps; ii++) QUEUE_INSERT1(hio, send, ii); } /* NOTREACHED */ @@ -1346,8 +1375,7 @@ local_send_thread(void *arg) } else { hio->hio_errors[ncomp] = 0; if (hio->hio_replication == - HAST_REPLICATION_ASYNC && - !ISSYNCREQ(hio)) { + HAST_REPLICATION_ASYNC) { ggio->gctl_error = 0; write_complete(res, hio); } @@ -1385,8 +1413,42 @@ local_send_thread(void *arg) } break; } - if (!refcount_release(&hio->hio_countdown)) - continue; + + if (hio->hio_replication != HAST_REPLICATION_MEMSYNC || + ggio->gctl_cmd != BIO_WRITE || ISSYNCREQ(hio)) { + if (refcnt_release(&hio->hio_countdown) > 0) + continue; + } else { + /* + * Depending on hio_countdown value, requests finished + * in the following order: + * 0: remote memsync, remote final, local write + * 1: remote memsync, local write, (remote final) + * 2: local write, (remote memsync), (remote final) + */ + switch (refcnt_release(&hio->hio_countdown)) { + case 0: + /* + * Local write finished as last. + */ + break; + case 1: + /* + * Local write finished after remote memsync + * reply arrvied. We can complete the write now. + */ + if (hio->hio_errors[0] == 0) + write_complete(res, hio); + continue; + case 2: + /* + * Local write finished as first. + */ + continue; + default: + PJDLOG_ABORT("Invalid hio_countdown."); + } + } if (ISSYNCREQ(hio)) { mtx_lock(&sync_lock); SYNCREQDONE(hio); @@ -1508,6 +1570,10 @@ remote_send_thread(void *arg) nv_add_uint64(nv, (uint64_t)ggio->gctl_seq, "seq"); nv_add_uint64(nv, offset, "offset"); nv_add_uint64(nv, length, "length"); + if (hio->hio_replication == HAST_REPLICATION_MEMSYNC && + ggio->gctl_cmd == BIO_WRITE && !ISSYNCREQ(hio)) { + nv_add_uint8(nv, 1, "memsync"); + } if (nv_error(nv) != 0) { hio->hio_errors[ncomp] = nv_error(nv); pjdlog_debug(2, @@ -1568,7 +1634,7 @@ remote_send_thread(void *arg) done_queue: nv_free(nv); if (ISSYNCREQ(hio)) { - if (!refcount_release(&hio->hio_countdown)) + if (refcnt_release(&hio->hio_countdown) > 0) continue; mtx_lock(&sync_lock); SYNCREQDONE(hio); @@ -1583,8 +1649,10 @@ done_queue: (void)hast_activemap_flush(res); } mtx_unlock(&res->hr_amp_lock); + if (hio->hio_replication == HAST_REPLICATION_MEMSYNC) + (void)refcnt_release(&hio->hio_countdown); } - if (!refcount_release(&hio->hio_countdown)) + if (refcnt_release(&hio->hio_countdown) > 0) continue; pjdlog_debug(2, "remote_send: (%p) Moving request to the done queue.", @@ -1608,6 +1676,7 @@ remote_recv_thread(void *arg) struct nv *nv; unsigned int ncomp; uint64_t seq; + bool memsyncack; int error; /* Remote component is 1 for now. */ @@ -1623,6 +1692,8 @@ remote_recv_thread(void *arg) } mtx_unlock(&hio_recv_list_lock[ncomp]); + memsyncack = false; + rw_rlock(&hio_remote_lock[ncomp]); if (!ISCONNECTED(res, ncomp)) { rw_unlock(&hio_remote_lock[ncomp]); @@ -1652,6 +1723,7 @@ remote_recv_thread(void *arg) nv_free(nv); continue; } + memsyncack = nv_exists(nv, "received"); mtx_lock(&hio_recv_list_lock[ncomp]); TAILQ_FOREACH(hio, &hio_recv_list[ncomp], hio_next[ncomp]) { if (hio->hio_ggio.gctl_seq == seq) { @@ -1707,8 +1779,80 @@ remote_recv_thread(void *arg) hio->hio_errors[ncomp] = 0; nv_free(nv); done_queue: - if (!refcount_release(&hio->hio_countdown)) - continue; + if (hio->hio_replication != HAST_REPLICATION_MEMSYNC || + hio->hio_ggio.gctl_cmd != BIO_WRITE || ISSYNCREQ(hio)) { + if (refcnt_release(&hio->hio_countdown) > 0) + continue; + } else { + /* + * Depending on hio_countdown value, requests finished + * in the following order: + * + * 0: local write, remote memsync, remote final + * or + * 0: remote memsync, local write, remote final + * + * 1: local write, remote memsync, (remote final) + * or + * 1: remote memsync, remote final, (local write) + * + * 2: remote memsync, (local write), (remote final) + * or + * 2: remote memsync, (remote final), (local write) + */ + switch (refcnt_release(&hio->hio_countdown)) { + case 0: + /* + * Remote final reply arrived. + */ + PJDLOG_ASSERT(!memsyncack); + break; + case 1: + if (memsyncack) { + /* + * Local request already finished, so we + * can complete the write. + */ + if (hio->hio_errors[0] == 0) + write_complete(res, hio); + /* + * We still need to wait for final + * remote reply. + */ + pjdlog_debug(2, + "remote_recv: (%p) Moving request back to the recv queue.", + hio); + mtx_lock(&hio_recv_list_lock[ncomp]); + TAILQ_INSERT_TAIL(&hio_recv_list[ncomp], + hio, hio_next[ncomp]); + mtx_unlock(&hio_recv_list_lock[ncomp]); + } else { + /* + * Remote final reply arrived before + * local write finished. + * Nothing to do in such case. + */ + } + continue; + case 2: + /* + * We received remote memsync reply even before + * local write finished. + */ + PJDLOG_ASSERT(memsyncack); + + pjdlog_debug(2, + "remote_recv: (%p) Moving request back to the recv queue.", + hio); + mtx_lock(&hio_recv_list_lock[ncomp]); + TAILQ_INSERT_TAIL(&hio_recv_list[ncomp], hio, + hio_next[ncomp]); + mtx_unlock(&hio_recv_list_lock[ncomp]); + continue; + default: + PJDLOG_ABORT("Invalid hio_countdown."); + } + } if (ISSYNCREQ(hio)) { mtx_lock(&sync_lock); SYNCREQDONE(hio); @@ -1977,7 +2121,7 @@ sync_thread(void *arg __unused) ncomp = 1; } mtx_unlock(&metadata_lock); - refcount_init(&hio->hio_countdown, 1); + hio->hio_countdown = 1; QUEUE_INSERT1(hio, send, ncomp); /* @@ -2027,7 +2171,7 @@ sync_thread(void *arg __unused) pjdlog_debug(2, "sync: (%p) Moving request to the send queue.", hio); - refcount_init(&hio->hio_countdown, 1); + hio->hio_countdown = 1; QUEUE_INSERT1(hio, send, ncomp); /* diff --git a/sbin/hastd/refcnt.h b/sbin/hastd/refcnt.h new file mode 100644 index 00000000000..a989df04885 --- /dev/null +++ b/sbin/hastd/refcnt.h @@ -0,0 +1,57 @@ +/*- + * Copyright (c) 2005 John Baldwin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef __REFCNT_H__ +#define __REFCNT_H__ + +#include + +#include "pjdlog.h" + +static __inline void +refcnt_acquire(volatile unsigned int *count) +{ + + atomic_add_acq_int(count, 1); +} + +static __inline unsigned int +refcnt_release(volatile unsigned int *count) +{ + unsigned int old; + + /* XXX: Should this have a rel membar? */ + old = atomic_fetchadd_int(count, -1); + PJDLOG_ASSERT(old > 0); + return (old - 1); +} + +#endif /* ! __REFCNT_H__ */ diff --git a/sbin/hastd/secondary.c b/sbin/hastd/secondary.c index 8ebcd48efb5..71524e90a26 100644 --- a/sbin/hastd/secondary.c +++ b/sbin/hastd/secondary.c @@ -71,6 +71,7 @@ struct hio { uint8_t hio_cmd; uint64_t hio_offset; uint64_t hio_length; + bool hio_memsync; TAILQ_ENTRY(hio) hio_next; }; @@ -135,6 +136,22 @@ hio_clear(struct hio *hio) hio->hio_cmd = HIO_UNDEF; hio->hio_offset = 0; hio->hio_length = 0; + hio->hio_memsync = false; +} + +static void +hio_copy(const struct hio *srchio, struct hio *dsthio) +{ + + /* + * We don't copy hio_error, hio_data and hio_next fields. + */ + + dsthio->hio_seq = srchio->hio_seq; + dsthio->hio_cmd = srchio->hio_cmd; + dsthio->hio_offset = srchio->hio_offset; + dsthio->hio_length = srchio->hio_length; + dsthio->hio_memsync = srchio->hio_memsync; } static void @@ -543,8 +560,10 @@ requnpack(struct hast_resource *res, struct hio *hio, struct nv *nv) case HIO_FLUSH: case HIO_KEEPALIVE: break; - case HIO_READ: case HIO_WRITE: + hio->hio_memsync = nv_exists(nv, "memsync"); + /* FALLTHROUGH */ + case HIO_READ: case HIO_DELETE: hio->hio_offset = nv_get_uint64(nv, "offset"); if (nv_error(nv) != 0) { @@ -621,7 +640,7 @@ static void * recv_thread(void *arg) { struct hast_resource *res = arg; - struct hio *hio; + struct hio *hio, *mshio; struct nv *nv; for (;;) { @@ -675,6 +694,27 @@ recv_thread(void *arg) secondary_exit(EX_TEMPFAIL, "Unable to receive request data"); } + if (hio->hio_memsync) { + /* + * For memsync requests we expect two replies. + * Clone the hio so we can handle both of them. + */ + pjdlog_debug(2, "recv: Taking free request."); + QUEUE_TAKE(free, mshio); + pjdlog_debug(2, "recv: (%p) Got request.", + mshio); + hio_copy(hio, mshio); + mshio->hio_error = 0; + /* + * We want to keep 'memsync' tag only on the + * request going onto send queue (mshio). + */ + hio->hio_memsync = false; + pjdlog_debug(2, + "recv: (%p) Moving memsync request to the send queue.", + mshio); + QUEUE_INSERT(send, mshio); + } } nv_free(nv); pjdlog_debug(2, "recv: (%p) Moving request to the disk queue.", @@ -818,6 +858,10 @@ send_thread(void *arg) nvout = nv_alloc(); /* Copy sequence number. */ nv_add_uint64(nvout, hio->hio_seq, "seq"); + if (hio->hio_memsync) { + PJDLOG_ASSERT(hio->hio_cmd == HIO_WRITE); + nv_add_int8(nvout, 1, "received"); + } switch (hio->hio_cmd) { case HIO_READ: if (hio->hio_error == 0) { From b2e054b0d42fa25514eae30706af00a5b4ab87ec Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sun, 17 Feb 2013 21:37:32 +0000 Subject: [PATCH 0244/1476] Update the comment: we do show the backtrace of misbehaving thread. --- sys/kern/subr_turnstile.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sys/kern/subr_turnstile.c b/sys/kern/subr_turnstile.c index 76fb9640036..0a21ad92949 100644 --- a/sys/kern/subr_turnstile.c +++ b/sys/kern/subr_turnstile.c @@ -215,10 +215,9 @@ propagate_priority(struct thread *td) /* * If the thread is asleep, then we are probably about - * to deadlock. To make debugging this easier, just - * panic and tell the user which thread misbehaved so - * they can hopefully get a stack trace from the truly - * misbehaving thread. + * to deadlock. To make debugging this easier, show + * backtrace of misbehaving thread and panic to not + * leave the kernel deadlocked. */ if (TD_IS_SLEEPING(td)) { printf( From 7e46ff5f4cb541537722f87bb20a57bc41493d54 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Mon, 18 Feb 2013 00:38:40 +0000 Subject: [PATCH 0245/1476] Allow [] in remote address, which fixes IPv6 support. Reported by: simon --- contrib/openbsm/bin/auditdistd/token.l | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/openbsm/bin/auditdistd/token.l b/contrib/openbsm/bin/auditdistd/token.l index 9cebac1e22d..5e58e872883 100644 --- a/contrib/openbsm/bin/auditdistd/token.l +++ b/contrib/openbsm/bin/auditdistd/token.l @@ -74,7 +74,7 @@ sender { DP; return SENDER; } source { DP; return SOURCE; } timeout { DP; return TIMEOUT; } [0-9]+ { DP; yylval.num = atoi(yytext); return NUM; } -\"[a-zA-Z0-9_/ !@#\$%\^\&\*\(\)\+\=\|\;\?\,\.\-\:]*\" { DP; yylval.str = strndup(yytext + 1, strlen(yytext) - 2); return STR; } +\"[a-zA-Z0-9_/ !@#\$%\^\&\*\(\)\+\=\|\;\?\,\.\[\]\-\:]*\" { DP; yylval.str = strndup(yytext + 1, strlen(yytext) - 2); return STR; } \{ { DP; depth++; return OB; } \} { DP; depth--; return CB; } #.*$ /* ignore comments */; From fc23011bc33e844e820af50b3a63b71f582ecc01 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 18 Feb 2013 01:02:48 +0000 Subject: [PATCH 0246/1476] On arm, like sparc64, the end of the kernel map varies from one type of machine to another. Therefore, VM_MAX_KERNEL_ADDRESS can't be a constant. Instead, #define it to be a variable, vm_max_kernel_address, just like we do on sparc64. Reviewed by: kib Tested by: ian --- sys/arm/arm/machdep.c | 5 ++--- sys/arm/arm/pmap-v6.c | 2 ++ sys/arm/arm/pmap.c | 2 ++ sys/arm/include/vmparam.h | 4 +++- sys/vm/vm_kern.c | 2 +- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/sys/arm/arm/machdep.c b/sys/arm/arm/machdep.c index 5c4d92c6a2c..28d1902d71c 100644 --- a/sys/arm/arm/machdep.c +++ b/sys/arm/arm/machdep.c @@ -1178,7 +1178,6 @@ initarm(struct arm_boot_params *abp) struct pv_addr kernel_l1pt; struct pv_addr dpcpu; vm_offset_t dtbp, freemempos, l2_start, lastaddr; - vm_offset_t pmap_bootstrap_lastaddr; uint32_t memsize, l2size; char *env; void *kmdp; @@ -1288,7 +1287,7 @@ initarm(struct arm_boot_params *abp) availmem_regions_sz = curr; /* Platform-specific initialisation */ - pmap_bootstrap_lastaddr = initarm_lastaddr(); + vm_max_kernel_address = initarm_lastaddr(); pcpu0_init(); @@ -1477,7 +1476,7 @@ initarm(struct arm_boot_params *abp) arm_intrnames_init(); arm_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL); arm_dump_avail_init(memsize, sizeof(dump_avail) / sizeof(dump_avail[0])); - pmap_bootstrap(freemempos, pmap_bootstrap_lastaddr, &kernel_l1pt); + pmap_bootstrap(freemempos, vm_max_kernel_address, &kernel_l1pt); msgbufp = (void *)msgbufpv.pv_va; msgbufinit(msgbufp, msgbufsize); mutex_init(); diff --git a/sys/arm/arm/pmap-v6.c b/sys/arm/arm/pmap-v6.c index d3e386d015b..f05f120ab85 100644 --- a/sys/arm/arm/pmap-v6.c +++ b/sys/arm/arm/pmap-v6.c @@ -231,6 +231,8 @@ vm_paddr_t kernel_l1pa; vm_offset_t kernel_vm_end = 0; +vm_offset_t vm_max_kernel_address; + struct pmap kernel_pmap_store; static pt_entry_t *csrc_pte, *cdst_pte; diff --git a/sys/arm/arm/pmap.c b/sys/arm/arm/pmap.c index 7170a98978a..c9cb42c638e 100644 --- a/sys/arm/arm/pmap.c +++ b/sys/arm/arm/pmap.c @@ -220,6 +220,8 @@ vm_paddr_t kernel_l1pa; vm_offset_t kernel_vm_end = 0; +vm_offset_t vm_max_kernel_address; + struct pmap kernel_pmap_store; static pt_entry_t *csrc_pte, *cdst_pte; diff --git a/sys/arm/include/vmparam.h b/sys/arm/include/vmparam.h index 267ba6e87fd..50c575bda63 100644 --- a/sys/arm/include/vmparam.h +++ b/sys/arm/include/vmparam.h @@ -133,7 +133,7 @@ #define VM_MIN_KERNEL_ADDRESS KERNBASE #endif -#define VM_MAX_KERNEL_ADDRESS 0xffffffff +#define VM_MAX_KERNEL_ADDRESS (vm_max_kernel_address) /* * Virtual size (bytes) for various kernel submaps. @@ -166,6 +166,8 @@ #define UMA_MD_SMALL_ALLOC #endif /* ARM_USE_SMALL_ALLOC */ +extern vm_offset_t vm_max_kernel_address; + #define ZERO_REGION_SIZE (64 * 1024) /* 64KB */ #endif /* _MACHINE_VMPARAM_H_ */ diff --git a/sys/vm/vm_kern.c b/sys/vm/vm_kern.c index 4d789cec208..ad9aa0dfa7e 100644 --- a/sys/vm/vm_kern.c +++ b/sys/vm/vm_kern.c @@ -98,7 +98,7 @@ SYSCTL_ULONG(_vm, OID_AUTO, min_kernel_address, CTLFLAG_RD, NULL, VM_MIN_KERNEL_ADDRESS, "Min kernel address"); SYSCTL_ULONG(_vm, OID_AUTO, max_kernel_address, CTLFLAG_RD, -#ifdef __sparc64__ +#if defined(__arm__) || defined(__sparc64__) &vm_max_kernel_address, 0, #else NULL, VM_MAX_KERNEL_ADDRESS, From 32d384a45c83f88ae5812185960347a543c7702c Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Mon, 18 Feb 2013 01:08:59 +0000 Subject: [PATCH 0247/1476] Disable this code and add a note as to why. It wasn't currently being called anyway - but being explicit about it can't hurt. --- sys/net80211/ieee80211_adhoc.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/sys/net80211/ieee80211_adhoc.c b/sys/net80211/ieee80211_adhoc.c index b0998f54fe6..e504718d0fb 100644 --- a/sys/net80211/ieee80211_adhoc.c +++ b/sys/net80211/ieee80211_adhoc.c @@ -768,8 +768,23 @@ adhoc_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, IEEE80211_RSSI_LPF(ni->ni_avgrssi, rssi); ni->ni_noise = nf; } + /* + * Same here - the channel width change should + * be applied to the specific peer node, not + * to the ic. Ie, the interface configuration + * should stay in its current channel width; + * but it should change the rate control and + * any queued frames for the given node only. + * + * Since there's no (current) way to inform + * the driver that a channel width change has + * occured for a single node, just stub this + * out. + */ +#if 0 if (ht_state_change) ieee80211_update_chw(ic); +#endif } break; } From 837a2c513dc6d0ccb4598344476f9ab000b328f2 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 18 Feb 2013 01:22:20 +0000 Subject: [PATCH 0248/1476] Place a cap on the size of the kernel's heap, also known as the kmem submap. Otherwise, after r246204, the auto-scaling logic in kern_malloc.c tries to create a kmem submap that consumes the entire kernel map on a Pandaboard with 1 GB of RAM. Tested by: gonzo --- sys/arm/include/vmparam.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sys/arm/include/vmparam.h b/sys/arm/include/vmparam.h index 50c575bda63..94caeefddf6 100644 --- a/sys/arm/include/vmparam.h +++ b/sys/arm/include/vmparam.h @@ -145,6 +145,14 @@ #define VM_KMEM_SIZE_SCALE (2) #endif +/* + * Ceiling on the size of the kmem submap: 60% of the kernel map. + */ +#ifndef VM_KMEM_SIZE_MAX +#define VM_KMEM_SIZE_MAX ((vm_max_kernel_address - \ + VM_MIN_KERNEL_ADDRESS + 1) * 3 / 5) +#endif + #define MAXTSIZ (16*1024*1024) #ifndef DFLDSIZ #define DFLDSIZ (128*1024*1024) From 341177e1d818d0c66fe72f3fadc973393b75db4e Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Mon, 18 Feb 2013 01:37:55 +0000 Subject: [PATCH 0249/1476] Disable this variable; the code using it is also disabled. --- sys/net80211/ieee80211_adhoc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/net80211/ieee80211_adhoc.c b/sys/net80211/ieee80211_adhoc.c index e504718d0fb..ecf3a8793bf 100644 --- a/sys/net80211/ieee80211_adhoc.c +++ b/sys/net80211/ieee80211_adhoc.c @@ -688,7 +688,9 @@ adhoc_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, struct ieee80211_frame *wh; uint8_t *frm, *efrm, *sfrm; uint8_t *ssid, *rates, *xrates; +#if 0 int ht_state_change = 0; +#endif wh = mtod(m0, struct ieee80211_frame *); frm = (uint8_t *)&wh[1]; From 341cee15f6be494491855948b60f9eed4b9cf125 Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Mon, 18 Feb 2013 01:55:53 +0000 Subject: [PATCH 0250/1476] Add strtoul() to libstand by copying from libc and clipping out locale code. --- lib/libstand/Makefile | 2 +- lib/libstand/stand.h | 1 + lib/libstand/strtoul.c | 123 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 lib/libstand/strtoul.c diff --git a/lib/libstand/Makefile b/lib/libstand/Makefile index 807136d116d..cfc39e91854 100644 --- a/lib/libstand/Makefile +++ b/lib/libstand/Makefile @@ -39,7 +39,7 @@ CFLAGS+= -msoft-float -D_STANDALONE # standalone components and stuff we have modified locally SRCS+= gzguts.h zutil.h __main.c assert.c bcd.c bswap.c environment.c getopt.c gets.c \ - globals.c pager.c printf.c strdup.c strerror.c strtol.c random.c \ + globals.c pager.c printf.c strdup.c strerror.c strtol.c strtoul.c random.c \ sbrk.c twiddle.c zalloc.c zalloc_malloc.c # private (pruned) versions of libc string functions diff --git a/lib/libstand/stand.h b/lib/libstand/stand.h index 10bb829c4ce..2a1e9a99327 100644 --- a/lib/libstand/stand.h +++ b/lib/libstand/stand.h @@ -261,6 +261,7 @@ extern u_long random(void); /* imports from stdlib, locally modified */ extern long strtol(const char *, char **, int); +extern unsigned long strtoul(const char *, char **, int); extern char *optarg; /* getopt(3) external variables */ extern int optind, opterr, optopt, optreset; extern int getopt(int, char * const [], const char *); diff --git a/lib/libstand/strtoul.c b/lib/libstand/strtoul.c new file mode 100644 index 00000000000..c1609fb3d20 --- /dev/null +++ b/lib/libstand/strtoul.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)strtoul.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +/* + * Convert a string to an unsigned long integer. + * + * Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +unsigned long +strtoul(const char * __restrict nptr, char ** __restrict endptr, int base) +{ + const char *s; + unsigned long acc; + char c; + unsigned long cutoff; + int neg, any, cutlim; + + /* + * See strtol for comments as to the logic used. + */ + s = nptr; + do { + c = *s++; + } while (isspace((unsigned char)c)); + if (c == '-') { + neg = 1; + c = *s++; + } else { + neg = 0; + if (c == '+') + c = *s++; + } + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X') && + ((s[1] >= '0' && s[1] <= '9') || + (s[1] >= 'A' && s[1] <= 'F') || + (s[1] >= 'a' && s[1] <= 'f'))) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + acc = any = 0; + if (base < 2 || base > 36) + goto noconv; + + cutoff = ULONG_MAX / base; + cutlim = ULONG_MAX % base; + for ( ; ; c = *s++) { + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'Z') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'z') + c -= 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = ULONG_MAX; + errno = ERANGE; + } else if (!any) { +noconv: + errno = EINVAL; + } else if (neg) + acc = -acc; + if (endptr != NULL) + *endptr = (char *)(any ? s - 1 : nptr); + return (acc); +} From afad0b868fa9d25a1da06942a2018d71f5f0fadc Mon Sep 17 00:00:00 2001 From: Luigi Rizzo Date: Mon, 18 Feb 2013 02:08:41 +0000 Subject: [PATCH 0251/1476] the NO_PAM option has been finally removed in favor of WITHOUT_PAM. --- release/picobsd/bridge/crunch.conf | 2 +- release/picobsd/qemu/crunch.conf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/release/picobsd/bridge/crunch.conf b/release/picobsd/bridge/crunch.conf index 2a64021fad9..227414bbab1 100644 --- a/release/picobsd/bridge/crunch.conf +++ b/release/picobsd/bridge/crunch.conf @@ -29,7 +29,7 @@ # Default build options. Basically tell the Makefiles # that to use the most compact possible version of the code. -buildopts -DNO_PAM -DRELEASE_CRUNCH -DPPP_NO_NETGRAPH +buildopts -DWITHOUT_PAM -DRELEASE_CRUNCH -DPPP_NO_NETGRAPH buildopts -DTRACEROUTE_NO_IPSEC -DNO_INET6 buildopts -DWITHOUT_IPX diff --git a/release/picobsd/qemu/crunch.conf b/release/picobsd/qemu/crunch.conf index 340ddb12de5..5dbb5190a3b 100644 --- a/release/picobsd/qemu/crunch.conf +++ b/release/picobsd/qemu/crunch.conf @@ -29,7 +29,7 @@ # Default build options. Basically tell the Makefiles # that to use the most compact possible version of the code. -buildopts -DNO_PAM -DRELEASE_CRUNCH -DPPP_NO_NETGRAPH +buildopts -DWITHOUT_PAM -DRELEASE_CRUNCH -DPPP_NO_NETGRAPH buildopts -DTRACEROUTE_NO_IPSEC -DNO_INET6 buildopts -DWITHOUT_IPX From d97c06b3a4a0678bd1c50c2b501ef5e76bf29dcf Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Mon, 18 Feb 2013 04:10:38 +0000 Subject: [PATCH 0252/1476] Add a new ATH KTR debug method to log the interrupt status. --- sys/dev/ath/if_ath_alq.h | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/sys/dev/ath/if_ath_alq.h b/sys/dev/ath/if_ath_alq.h index 3748d50af7e..52a022d4963 100644 --- a/sys/dev/ath/if_ath_alq.h +++ b/sys/dev/ath/if_ath_alq.h @@ -92,6 +92,13 @@ struct if_ath_alq_tdma_timer_set { uint32_t sc_tdmaswbaprep; }; +#define ATH_ALQ_INTR_STATUS 10 +struct if_ath_alq_interrupt { + uint32_t intr_status; + uint32_t intr_state[8]; + uint32_t intr_syncstate; +}; + /* * These will always be logged, regardless. */ @@ -144,6 +151,27 @@ extern int if_ath_alq_start(struct if_ath_alq *alq); extern int if_ath_alq_stop(struct if_ath_alq *alq); extern void if_ath_alq_post(struct if_ath_alq *alq, uint16_t op, uint16_t len, const char *buf); + +/* XXX maybe doesn't belong here? */ +static inline void +if_ath_alq_post_intr(struct if_ath_alq *alq, uint32_t status, + uint32_t *state, uint32_t sync_state) +{ + int i; + struct if_ath_alq_interrupt intr; + + if (! if_ath_alq_checkdebug(alq, ATH_ALQ_INTR_STATUS)) + return; + + intr.intr_status = htobe32(status); + for (i = 0; i < 8; i++) + intr.intr_state[i] = htobe32(state[i]); + intr.intr_syncstate = htobe32(sync_state); + + if_ath_alq_post(alq, ATH_ALQ_INTR_STATUS, sizeof(&intr), + (const char *) &intr); +} + #endif /* _KERNEL */ #endif From fec3d03df08a00f8ee0dfc47b24ceabaa8ccf44c Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Mon, 18 Feb 2013 04:19:21 +0000 Subject: [PATCH 0253/1476] Make this output more terse. --- tools/tools/ath/athalq/ar5416_ds.c | 95 +++++++++++++++--------------- 1 file changed, 49 insertions(+), 46 deletions(-) diff --git a/tools/tools/ath/athalq/ar5416_ds.c b/tools/tools/ath/athalq/ar5416_ds.c index 6157c629d1d..a8c827a1785 100644 --- a/tools/tools/ath/athalq/ar5416_ds.c +++ b/tools/tools/ath/athalq/ar5416_ds.c @@ -45,23 +45,34 @@ ar5416_decode_txstatus(struct if_ath_alq_payload *a) /* XXX assumes txs is smaller than PAYLOAD_LEN! */ memcpy(&txs, &a->payload, sizeof(struct ar5416_desc)); - printf("[%u.%06u] [%llu] TXSTATUS: TxDone=%d, TS=0x%08x\n", + printf("[%u.%06u] [%llu] TXSTATUS: TxDone=%d, FrmOk=%d, filt=%d, TS=0x%08x\n", (unsigned int) be32toh(a->hdr.tstamp_sec), (unsigned int) be32toh(a->hdr.tstamp_usec), (unsigned long long) be64toh(a->hdr.threadid), MF(txs.u.tx.status[9], AR_TxDone), + MF(txs.u.tx.status[1], AR_FrmXmitOK), + MF(txs.u.tx.status[1], AR_Filtered), txs.u.tx.status[2]); /* ds_txstatus0 */ - printf(" RX RSSI 0 [%d %d %d]\n", + printf(" RX RSSI 0 [%d %d %d]", MS(txs.u.tx.status[0], AR_TxRSSIAnt00), MS(txs.u.tx.status[0], AR_TxRSSIAnt01), MS(txs.u.tx.status[0], AR_TxRSSIAnt02)); - printf(" BA Valid=%d\n", + + /* ds_txstatus5 */ + printf(" RX RSSI 1 [%d %d %d] Comb=%d\n", + MS(txs.u.tx.status[5], AR_TxRSSIAnt10), + MS(txs.u.tx.status[5], AR_TxRSSIAnt11), + MS(txs.u.tx.status[5], AR_TxRSSIAnt12), + MS(txs.u.tx.status[5], AR_TxRSSICombined)); + + /* ds_txstatus0 */ + printf(" BA Valid=%d", MF(txs.u.tx.status[0], AR_TxBaStatus)); /* ds_txstatus1 */ - printf(" Frmok=%d, xretries=%d, fifounderrun=%d, filt=%d\n", + printf(", Frmok=%d, xretries=%d, fifounderrun=%d, filt=%d\n", MF(txs.u.tx.status[1], AR_FrmXmitOK), MF(txs.u.tx.status[1], AR_ExcessiveRetries), MF(txs.u.tx.status[1], AR_FIFOUnderrun), @@ -79,19 +90,13 @@ ar5416_decode_txstatus(struct if_ath_alq_payload *a) MS(txs.u.tx.status[1], AR_VirtRetryCnt)); /* ds_txstatus2 */ - printf(" TxTimestamp=0x%08x\n", txs.u.tx.status[2]); + printf(" TxTimestamp=0x%08x", txs.u.tx.status[2]); /* ds_txstatus3 */ /* ds_txstatus4 */ - printf(" BALow=0x%08x\n", txs.u.tx.status[3]); - printf(" BAHigh=0x%08x\n", txs.u.tx.status[4]); + printf(", BALow=0x%08x", txs.u.tx.status[3]); + printf(", BAHigh=0x%08x\n", txs.u.tx.status[4]); - /* ds_txstatus5 */ - printf(" RX RSSI 1 [%d %d %d] Comb=%d\n", - MS(txs.u.tx.status[5], AR_TxRSSIAnt10), - MS(txs.u.tx.status[5], AR_TxRSSIAnt11), - MS(txs.u.tx.status[5], AR_TxRSSIAnt12), - MS(txs.u.tx.status[5], AR_TxRSSICombined)); /* ds_txstatus6 */ /* ds_txstatus7 */ @@ -174,26 +179,23 @@ ar5416_decode_txdesc(struct if_ath_alq_payload *a) MS(txc.ds_ctl2, AR_XmitDataTries2), MS(txc.ds_ctl2, AR_XmitDataTries3)); - /* ds_ctl3 */ - printf(" rate0=0x%02x, rate1=0x%02x, rate2=0x%02x, rate3=0x%02x\n", + /* ds_ctl3, 4 */ + printf(" try 0: Rate=0x%02x, PktDur=%d, RTS/CTS ena=%d\n", MS(txc.ds_ctl3, AR_XmitRate0), - MS(txc.ds_ctl3, AR_XmitRate1), - MS(txc.ds_ctl3, AR_XmitRate2), - MS(txc.ds_ctl3, AR_XmitRate3)); - - /* ds_ctl4 */ - printf(" try 0: PktDur=%d, RTS/CTS ena=%d\n", MS(txc.ds_ctl4, AR_PacketDur0), MF(txc.ds_ctl4, AR_RTSCTSQual0)); - printf(" try 1: PktDur=%d, RTS/CTS ena=%d\n", + printf(" try 1: Rate=0x%02x, PktDur=%d, RTS/CTS ena=%d\n", + MS(txc.ds_ctl3, AR_XmitRate1), MS(txc.ds_ctl4, AR_PacketDur1), MF(txc.ds_ctl4, AR_RTSCTSQual1)); - /* ds_ctl5 */ - printf(" try 2: PktDur=%d, RTS/CTS ena=%d\n", + /* ds_ctl3, 5 */ + printf(" try 2: Rate=0x%02x, PktDur=%d, RTS/CTS ena=%d\n", + MS(txc.ds_ctl3, AR_XmitRate2), MS(txc.ds_ctl5, AR_PacketDur2), MF(txc.ds_ctl5, AR_RTSCTSQual2)); - printf(" try 3: PktDur=%d, RTS/CTS ena=%d\n", + printf(" try 3: Rate=0x%02x, PktDur=%d, RTS/CTS ena=%d\n", + MS(txc.ds_ctl3, AR_XmitRate3), MS(txc.ds_ctl5, AR_PacketDur3), MF(txc.ds_ctl5, AR_RTSCTSQual3)); @@ -254,11 +256,12 @@ ar5416_decode_rxstatus(struct if_ath_alq_payload *a) /* XXX assumes rxs is smaller than PAYLOAD_LEN! */ memcpy(&rxs, &a->payload, sizeof(struct ar5416_desc)); - printf("[%u.%06u] [%llu] RXSTATUS: RxDone=%d, TS=0x%08x\n", + printf("[%u.%06u] [%llu] RXSTATUS: RxDone=%d, RxRate=0x%02x, TS=0x%08x\n", (unsigned int) be32toh(a->hdr.tstamp_sec), (unsigned int) be32toh(a->hdr.tstamp_usec), (unsigned long long) be64toh(a->hdr.threadid), MF(rxs.ds_rxstatus8, AR_RxDone), + MS(rxs.ds_rxstatus0, AR_RxRate), rxs.ds_rxstatus2); printf(" link=0x%08x, data=0x%08x, ctl0=0x%08x, ctl2=0x%08x\n", @@ -277,15 +280,22 @@ ar5416_decode_rxstatus(struct if_ath_alq_payload *a) MS(rxs.ds_rxstatus0, AR_RxRSSIAnt01), MS(rxs.ds_rxstatus0, AR_RxRSSIAnt02)); + /* status4 */ + printf(" RSSIExt[0]=%d, RSSIExt[1]=%d, RSSIExt[2]=%d, RSSIComb=%d\n", + MS(rxs.ds_rxstatus4, AR_RxRSSIAnt10), + MS(rxs.ds_rxstatus4, AR_RxRSSIAnt11), + MS(rxs.ds_rxstatus4, AR_RxRSSIAnt12), + MS(rxs.ds_rxstatus4, AR_RxRSSICombined)); + + /* status2 */ + printf(" RxTimestamp=0x%08x,", rxs.ds_rxstatus2); + /* status1 */ - printf(" DataLen=%d, RxMore=%d, NumDelim=%d\n", + printf(" DataLen=%d, RxMore=%d, NumDelim=%d\n", rxs.ds_rxstatus1 & AR_DataLen, MF(rxs.ds_rxstatus1, AR_RxMore), MS(rxs.ds_rxstatus1, AR_NumDelim)); - /* status2 */ - printf(" RxTimestamp=0x%08x\n", rxs.ds_rxstatus2); - /* status3 - RxRate however is for Owl 2.0 */ printf(" GI=%d, 2040=%d, RxRate=0x%02x, DupFrame=%d, RxAnt=0x%08x\n", MF(rxs.ds_rxstatus3, AR_GI), @@ -294,13 +304,6 @@ ar5416_decode_rxstatus(struct if_ath_alq_payload *a) MF(rxs.ds_rxstatus3, AR_DupFrame), MS(rxs.ds_rxstatus3, AR_RxAntenna)); - /* status4 */ - printf(" RSSIExt[0]=%d, RSSIExt[1]=%d, RSSIExt[2]=%d, RSSIComb=%d\n", - MS(rxs.ds_rxstatus4, AR_RxRSSIAnt10), - MS(rxs.ds_rxstatus4, AR_RxRSSIAnt11), - MS(rxs.ds_rxstatus4, AR_RxRSSIAnt12), - MS(rxs.ds_rxstatus4, AR_RxRSSICombined)); - /* status5 */ /* status6 */ /* status7 */ @@ -321,20 +324,20 @@ ar5416_decode_rxstatus(struct if_ath_alq_payload *a) MF(rxs.ds_rxstatus8, AR_PreDelimCRCErr), MF(rxs.ds_rxstatus8, AR_RxKeyIdxValid)); - /* If PHY error, print that out. Otherwise, the key index */ - if (MF(rxs.ds_rxstatus8, AR_PHYErr)) - printf(" PhyErrCode=0x%02x\n", - MS(rxs.ds_rxstatus8, AR_PHYErrCode)); - else - printf(" KeyIdx=0x%02x\n", - MS(rxs.ds_rxstatus8, AR_KeyIdx)); - printf(" RxMoreAggr=%d, RxAggr=%d, PostDelimCRCErr=%d, HiRxChain=%d\n", MF(rxs.ds_rxstatus8, AR_RxMoreAggr), MF(rxs.ds_rxstatus8, AR_RxAggr), MF(rxs.ds_rxstatus8, AR_PostDelimCRCErr), MF(rxs.ds_rxstatus8, AR_HiRxChain)); - printf(" KeyMiss=%d\n", + + /* If PHY error, print that out. Otherwise, the key index */ + if (MF(rxs.ds_rxstatus8, AR_PHYErr)) + printf(" PhyErrCode=0x%02x", + MS(rxs.ds_rxstatus8, AR_PHYErrCode)); + else + printf(" KeyIdx=0x%02x", + MS(rxs.ds_rxstatus8, AR_KeyIdx)); + printf(", KeyMiss=%d\n", MF(rxs.ds_rxstatus8, AR_KeyMiss)); printf("\n ------\n"); From 6e1ff18743e0d942a61598ffe3e19a12548ed6a7 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Mon, 18 Feb 2013 04:20:43 +0000 Subject: [PATCH 0254/1476] * Add initial debugging of the interrupt status entry * Add in the TDMA debugging entries that I added a while ago --- tools/tools/ath/athalq/Makefile | 2 +- tools/tools/ath/athalq/main.c | 35 ++++++++++ tools/tools/ath/athalq/tdma.c | 117 ++++++++++++++++++++++++++++++++ tools/tools/ath/athalq/tdma.h | 28 ++++++++ 4 files changed, 181 insertions(+), 1 deletion(-) create mode 100644 tools/tools/ath/athalq/tdma.c create mode 100644 tools/tools/ath/athalq/tdma.h diff --git a/tools/tools/ath/athalq/Makefile b/tools/tools/ath/athalq/Makefile index 9ad4b140542..60c9bf8235b 100644 --- a/tools/tools/ath/athalq/Makefile +++ b/tools/tools/ath/athalq/Makefile @@ -3,7 +3,7 @@ PROG= athalq NOMAN= yes -SRCS= main.c ar5210_ds.c ar5211_ds.c ar5212_ds.c ar5416_ds.c +SRCS= main.c ar5210_ds.c ar5211_ds.c ar5212_ds.c ar5416_ds.c tdma.c # SRCS+= ar9300_ds.c .include <../Makefile.inc> diff --git a/tools/tools/ath/athalq/main.c b/tools/tools/ath/athalq/main.c index e8e277c7add..1d5447d0581 100644 --- a/tools/tools/ath/athalq/main.c +++ b/tools/tools/ath/athalq/main.c @@ -38,6 +38,8 @@ __FBSDID("$FreeBSD$"); #include "ar5212_ds.h" #include "ar5416_ds.h" +#include "tdma.h" + #define AR5210_MAGIC 0x19980124 #define AR5211_MAGIC 0x19570405 #define AR5212_MAGIC 0x19541014 @@ -58,6 +60,21 @@ ath_alq_print_hdr(struct if_ath_alq_init_state *hdr) be32toh(hdr->sc_hal_magic)); } +static void +ath_alq_print_intr_status(struct if_ath_alq_payload *a) +{ + struct if_ath_alq_interrupt is; + + /* XXX len check! */ + memcpy(&is, &a->payload, sizeof(is)); + + printf("[%u.%06u] [%llu] INTR: status=0x%08x\n", + (unsigned int) be32toh(a->hdr.tstamp_sec), + (unsigned int) be32toh(a->hdr.tstamp_usec), + (unsigned long long) be64toh(a->hdr.threadid), + be32toh(is.intr_status)); +} + int main(int argc, const char *argv[]) { @@ -112,6 +129,24 @@ main(int argc, const char *argv[]) memcpy(&hdr, a->payload, sizeof(hdr)); ath_alq_print_hdr(&hdr); break; + case ATH_ALQ_TDMA_BEACON_STATE: + ath_tdma_beacon_state(a); + break; + case ATH_ALQ_TDMA_TIMER_CONFIG: + ath_tdma_timer_config(a); + break; + case ATH_ALQ_TDMA_SLOT_CALC: + ath_tdma_slot_calc(a); + break; + case ATH_ALQ_TDMA_TSF_ADJUST: + ath_tdma_tsf_adjust(a); + break; + case ATH_ALQ_TDMA_TIMER_SET: + ath_tdma_timer_set(a); + break; + case ATH_ALQ_INTR_STATUS: + ath_alq_print_intr_status(a); + break; default: if (be32toh(hdr.sc_hal_magic) == AR5210_MAGIC) ar5210_alq_payload(a); diff --git a/tools/tools/ath/athalq/tdma.c b/tools/tools/ath/athalq/tdma.c new file mode 100644 index 00000000000..55772de33f9 --- /dev/null +++ b/tools/tools/ath/athalq/tdma.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2013 Adrian Chadd + * All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "tdma.h" + +void +ath_tdma_beacon_state(struct if_ath_alq_payload *a) +{ + struct if_ath_alq_tdma_beacon_state t; + static uint64_t last_beacon_tx = 0; + + memcpy(&t, &a->payload, sizeof(t)); + + printf("[%u.%06u] [%llu] BEACON: RX TSF=%llu Beacon TSF=%llu (%d)\n", + (unsigned int) be32toh(a->hdr.tstamp_sec), + (unsigned int) be32toh(a->hdr.tstamp_usec), + (unsigned long long) be64toh(a->hdr.threadid), + (unsigned long long) be64toh(t.rx_tsf), + (unsigned long long) be64toh(t.beacon_tsf), + be64toh(t.beacon_tsf) - last_beacon_tx); + + last_beacon_tx = be64toh(t.beacon_tsf); +} + +void +ath_tdma_timer_config(struct if_ath_alq_payload *a) +{ + struct if_ath_alq_tdma_timer_config t; + + memcpy(&t, &a->payload, sizeof(t)); +} + +void +ath_tdma_slot_calc(struct if_ath_alq_payload *a) +{ + struct if_ath_alq_tdma_slot_calc t; + + memcpy(&t, &a->payload, sizeof(t)); + printf("[%u.%06u] [%llu] SLOTCALC: NEXTTBTT=%llu nextslot=%llu " + "tsfdelta=%d avg (%d/%d)\n", + (unsigned int) be32toh(a->hdr.tstamp_sec), + (unsigned int) be32toh(a->hdr.tstamp_usec), + (unsigned long long) be64toh(a->hdr.threadid), + (unsigned long long) be64toh(t.nexttbtt), + (unsigned long long) be64toh(t.next_slot), + (int) be32toh(t.tsfdelta), + (int) be32toh(t.avg_plus), + (int) be32toh(t.avg_minus)); +} + +void +ath_tdma_tsf_adjust(struct if_ath_alq_payload *a) +{ + struct if_ath_alq_tdma_tsf_adjust t; + + memcpy(&t, &a->payload, sizeof(t)); + printf("[%u.%06u] [%llu] TSFADJUST: TSF64 was %llu, adj=%d, " + "now %llu\n", + (unsigned int) be32toh(a->hdr.tstamp_sec), + (unsigned int) be32toh(a->hdr.tstamp_usec), + (unsigned long long) be64toh(a->hdr.threadid), + (unsigned long long) be64toh(t.tsf64_old), + (int) be32toh(t.tsfdelta), + (unsigned long long) be64toh(t.tsf64_new)); +} + +void +ath_tdma_timer_set(struct if_ath_alq_payload *a) +{ + struct if_ath_alq_tdma_timer_set t; + + memcpy(&t, &a->payload, sizeof(t)); + printf("[%u.%06u] [%llu] TIMERSET: bt_intval=%d nexttbtt=%d " + "nextdba=%d nextswba=%d nextatim=%d flags=0x%x tdmadbaprep=%d " + "tdmaswbaprep=%d\n", + (unsigned int) be32toh(a->hdr.tstamp_sec), + (unsigned int) be32toh(a->hdr.tstamp_usec), + (unsigned long long) be64toh(a->hdr.threadid), + be32toh(t.bt_intval), + be32toh(t.bt_nexttbtt), + be32toh(t.bt_nextdba), + be32toh(t.bt_nextswba), + be32toh(t.bt_nextatim), + be32toh(t.bt_flags), + be32toh(t.sc_tdmadbaprep), + be32toh(t.sc_tdmaswbaprep)); +} diff --git a/tools/tools/ath/athalq/tdma.h b/tools/tools/ath/athalq/tdma.h new file mode 100644 index 00000000000..25fa7dea44e --- /dev/null +++ b/tools/tools/ath/athalq/tdma.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2013 Adrian Chadd + * All Rights Reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ +#ifndef __TDMA_H__ +#define __TDMA_H__ + +extern void ath_tdma_beacon_state(struct if_ath_alq_payload *a); +extern void ath_tdma_timer_config(struct if_ath_alq_payload *a); +extern void ath_tdma_slot_calc(struct if_ath_alq_payload *a); +extern void ath_tdma_tsf_adjust(struct if_ath_alq_payload *a); +extern void ath_tdma_timer_set(struct if_ath_alq_payload *a); + +#endif /* __TDMA_H__ */ From 28c0619e5e4478c645d77b874f1fd66817afaab3 Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Mon, 18 Feb 2013 11:48:08 +0000 Subject: [PATCH 0255/1476] Update vendor/illumos/dist and vendor-sys/illumos/dist to illumos-gate 13957:512faafc0eaf Illumos ZFS issues: 3537 want pool io kstats --- lib/libzpool/common/kernel.c | 34 ++++++++++++++++- lib/libzpool/common/sys/zfs_context.h | 10 ++++- uts/common/fs/zfs/spa_misc.c | 12 ++++++ uts/common/fs/zfs/sys/spa_impl.h | 2 + uts/common/fs/zfs/vdev_queue.c | 54 +++++++++++++++++++++++++-- 5 files changed, 105 insertions(+), 7 deletions(-) diff --git a/lib/libzpool/common/kernel.c b/lib/libzpool/common/kernel.c index c698c23ef69..cc0d5428bee 100644 --- a/lib/libzpool/common/kernel.c +++ b/lib/libzpool/common/kernel.c @@ -80,8 +80,8 @@ zk_thread_create(void (*func)(), void *arg) */ /*ARGSUSED*/ kstat_t * -kstat_create(char *module, int instance, char *name, char *class, - uchar_t type, ulong_t ndata, uchar_t ks_flag) +kstat_create(const char *module, int instance, const char *name, + const char *class, uchar_t type, ulong_t ndata, uchar_t ks_flag) { return (NULL); } @@ -96,6 +96,36 @@ void kstat_delete(kstat_t *ksp) {} +/*ARGSUSED*/ +void +kstat_waitq_enter(kstat_io_t *kiop) +{} + +/*ARGSUSED*/ +void +kstat_waitq_exit(kstat_io_t *kiop) +{} + +/*ARGSUSED*/ +void +kstat_runq_enter(kstat_io_t *kiop) +{} + +/*ARGSUSED*/ +void +kstat_runq_exit(kstat_io_t *kiop) +{} + +/*ARGSUSED*/ +void +kstat_waitq_to_runq(kstat_io_t *kiop) +{} + +/*ARGSUSED*/ +void +kstat_runq_back_to_waitq(kstat_io_t *kiop) +{} + /* * ========================================================================= * mutexes diff --git a/lib/libzpool/common/sys/zfs_context.h b/lib/libzpool/common/sys/zfs_context.h index c638482d2ec..bcb27cf1a5c 100644 --- a/lib/libzpool/common/sys/zfs_context.h +++ b/lib/libzpool/common/sys/zfs_context.h @@ -255,10 +255,16 @@ extern void cv_broadcast(kcondvar_t *cv); /* * kstat creation, installation and deletion */ -extern kstat_t *kstat_create(char *, int, - char *, char *, uchar_t, ulong_t, uchar_t); +extern kstat_t *kstat_create(const char *, int, + const char *, const char *, uchar_t, ulong_t, uchar_t); extern void kstat_install(kstat_t *); extern void kstat_delete(kstat_t *); +extern void kstat_waitq_enter(kstat_io_t *); +extern void kstat_waitq_exit(kstat_io_t *); +extern void kstat_runq_enter(kstat_io_t *); +extern void kstat_runq_exit(kstat_io_t *); +extern void kstat_waitq_to_runq(kstat_io_t *); +extern void kstat_runq_back_to_waitq(kstat_io_t *); /* * Kernel memory diff --git a/uts/common/fs/zfs/spa_misc.c b/uts/common/fs/zfs/spa_misc.c index 0e2d0efda34..405d93c6ced 100644 --- a/uts/common/fs/zfs/spa_misc.c +++ b/uts/common/fs/zfs/spa_misc.c @@ -480,6 +480,7 @@ spa_add(const char *name, nvlist_t *config, const char *altroot) mutex_init(&spa->spa_scrub_lock, NULL, MUTEX_DEFAULT, NULL); mutex_init(&spa->spa_suspend_lock, NULL, MUTEX_DEFAULT, NULL); mutex_init(&spa->spa_vdev_top_lock, NULL, MUTEX_DEFAULT, NULL); + mutex_init(&spa->spa_iokstat_lock, NULL, MUTEX_DEFAULT, NULL); cv_init(&spa->spa_async_cv, NULL, CV_DEFAULT, NULL); cv_init(&spa->spa_proc_cv, NULL, CV_DEFAULT, NULL); @@ -559,6 +560,13 @@ spa_add(const char *name, nvlist_t *config, const char *altroot) KM_SLEEP) == 0); } + spa->spa_iokstat = kstat_create("zfs", 0, name, + "disk", KSTAT_TYPE_IO, 1, 0); + if (spa->spa_iokstat) { + spa->spa_iokstat->ks_lock = &spa->spa_iokstat_lock; + kstat_install(spa->spa_iokstat); + } + return (spa); } @@ -608,6 +616,9 @@ spa_remove(spa_t *spa) spa_config_lock_destroy(spa); + kstat_delete(spa->spa_iokstat); + spa->spa_iokstat = NULL; + for (int t = 0; t < TXG_SIZE; t++) bplist_destroy(&spa->spa_free_bplist[t]); @@ -625,6 +636,7 @@ spa_remove(spa_t *spa) mutex_destroy(&spa->spa_scrub_lock); mutex_destroy(&spa->spa_suspend_lock); mutex_destroy(&spa->spa_vdev_top_lock); + mutex_destroy(&spa->spa_iokstat_lock); kmem_free(spa, sizeof (spa_t)); } diff --git a/uts/common/fs/zfs/sys/spa_impl.h b/uts/common/fs/zfs/sys/spa_impl.h index 42ce5556d37..ffd676e2ed7 100644 --- a/uts/common/fs/zfs/sys/spa_impl.h +++ b/uts/common/fs/zfs/sys/spa_impl.h @@ -231,6 +231,8 @@ struct spa { uint64_t spa_deadman_calls; /* number of deadman calls */ uint64_t spa_sync_starttime; /* starting time fo spa_sync */ uint64_t spa_deadman_synctime; /* deadman expiration timer */ + kmutex_t spa_iokstat_lock; /* protects spa_iokstat_* */ + struct kstat *spa_iokstat; /* kstat of io to this pool */ /* * spa_refcnt & spa_config_lock must be the last elements * because refcount_t changes size based on compilation options. diff --git a/uts/common/fs/zfs/vdev_queue.c b/uts/common/fs/zfs/vdev_queue.c index 2b06040c51b..a806e933620 100644 --- a/uts/common/fs/zfs/vdev_queue.c +++ b/uts/common/fs/zfs/vdev_queue.c @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -142,15 +143,62 @@ vdev_queue_fini(vdev_t *vd) static void vdev_queue_io_add(vdev_queue_t *vq, zio_t *zio) { + spa_t *spa = zio->io_spa; avl_add(&vq->vq_deadline_tree, zio); avl_add(zio->io_vdev_tree, zio); + + if (spa->spa_iokstat != NULL) { + mutex_enter(&spa->spa_iokstat_lock); + kstat_waitq_enter(spa->spa_iokstat->ks_data); + mutex_exit(&spa->spa_iokstat_lock); + } } static void vdev_queue_io_remove(vdev_queue_t *vq, zio_t *zio) { + spa_t *spa = zio->io_spa; avl_remove(&vq->vq_deadline_tree, zio); avl_remove(zio->io_vdev_tree, zio); + + if (spa->spa_iokstat != NULL) { + mutex_enter(&spa->spa_iokstat_lock); + kstat_waitq_exit(spa->spa_iokstat->ks_data); + mutex_exit(&spa->spa_iokstat_lock); + } +} + +static void +vdev_queue_pending_add(vdev_queue_t *vq, zio_t *zio) +{ + spa_t *spa = zio->io_spa; + avl_add(&vq->vq_pending_tree, zio); + if (spa->spa_iokstat != NULL) { + mutex_enter(&spa->spa_iokstat_lock); + kstat_runq_enter(spa->spa_iokstat->ks_data); + mutex_exit(&spa->spa_iokstat_lock); + } +} + +static void +vdev_queue_pending_remove(vdev_queue_t *vq, zio_t *zio) +{ + spa_t *spa = zio->io_spa; + avl_remove(&vq->vq_pending_tree, zio); + if (spa->spa_iokstat != NULL) { + kstat_io_t *ksio = spa->spa_iokstat->ks_data; + + mutex_enter(&spa->spa_iokstat_lock); + kstat_runq_exit(spa->spa_iokstat->ks_data); + if (zio->io_type == ZIO_TYPE_READ) { + ksio->reads++; + ksio->nread += zio->io_size; + } else if (zio->io_type == ZIO_TYPE_WRITE) { + ksio->writes++; + ksio->nwritten += zio->io_size; + } + mutex_exit(&spa->spa_iokstat_lock); + } } static void @@ -317,7 +365,7 @@ again: zio_execute(dio); } while (dio != lio); - avl_add(&vq->vq_pending_tree, aio); + vdev_queue_pending_add(vq, aio); return (aio); } @@ -339,7 +387,7 @@ again: goto again; } - avl_add(&vq->vq_pending_tree, fio); + vdev_queue_pending_add(vq, fio); return (fio); } @@ -395,7 +443,7 @@ vdev_queue_io_done(zio_t *zio) mutex_enter(&vq->vq_lock); - avl_remove(&vq->vq_pending_tree, zio); + vdev_queue_pending_remove(vq, zio); vq->vq_io_complete_ts = ddi_get_lbolt64(); vq->vq_io_delta_ts = vq->vq_io_complete_ts - zio->io_timestamp; From 1b9c9ab29ae92dcf5b567df0834baace9f87bd63 Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Mon, 18 Feb 2013 17:55:27 +0000 Subject: [PATCH 0256/1476] Fix bad EEPROM parsing code. MFC after: 2 weeks --- sys/dev/usb/wlan/if_upgt.c | 34 ++++++++++++++++++++++++++++++---- sys/dev/usb/wlan/if_upgtvar.h | 2 +- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/sys/dev/usb/wlan/if_upgt.c b/sys/dev/usb/wlan/if_upgt.c index 04671003e8e..eff792222fa 100644 --- a/sys/dev/usb/wlan/if_upgt.c +++ b/sys/dev/usb/wlan/if_upgt.c @@ -1132,12 +1132,23 @@ upgt_eeprom_parse(struct upgt_softc *sc) (sizeof(struct upgt_eeprom_header) + preamble_len)); while (!option_end) { + + /* sanity check */ + if (eeprom_option >= (struct upgt_eeprom_option *) + (sc->sc_eeprom + UPGT_EEPROM_SIZE)) { + return (EINVAL); + } + /* the eeprom option length is stored in words */ option_len = (le16toh(eeprom_option->len) - 1) * sizeof(uint16_t); option_type = le16toh(eeprom_option->type); + /* sanity check */ + if (option_len == 0 || option_len >= UPGT_EEPROM_SIZE) + return (EINVAL); + switch (option_type) { case UPGT_EEPROM_TYPE_NAME: DPRINTF(sc, UPGT_DEBUG_FW, @@ -1208,7 +1219,6 @@ upgt_eeprom_parse(struct upgt_softc *sc) eeprom_option = (struct upgt_eeprom_option *) (eeprom_option->data + option_len); } - return (0); } @@ -1217,7 +1227,9 @@ upgt_eeprom_parse_freq3(struct upgt_softc *sc, uint8_t *data, int len) { struct upgt_eeprom_freq3_header *freq3_header; struct upgt_lmac_freq3 *freq3; - int i, elements, flags; + int i; + int elements; + int flags; unsigned channel; freq3_header = (struct upgt_eeprom_freq3_header *)data; @@ -1229,6 +1241,9 @@ upgt_eeprom_parse_freq3(struct upgt_softc *sc, uint8_t *data, int len) DPRINTF(sc, UPGT_DEBUG_FW, "flags=0x%02x elements=%d\n", flags, elements); + if (elements >= (int)(UPGT_EEPROM_SIZE / sizeof(freq3[0]))) + return; + for (i = 0; i < elements; i++) { channel = ieee80211_mhz2ieee(le16toh(freq3[i].freq), 0); if (channel >= IEEE80211_CHAN_MAX) @@ -1247,7 +1262,11 @@ upgt_eeprom_parse_freq4(struct upgt_softc *sc, uint8_t *data, int len) struct upgt_eeprom_freq4_header *freq4_header; struct upgt_eeprom_freq4_1 *freq4_1; struct upgt_eeprom_freq4_2 *freq4_2; - int i, j, elements, settings, flags; + int i; + int j; + int elements; + int settings; + int flags; unsigned channel; freq4_header = (struct upgt_eeprom_freq4_header *)data; @@ -1262,6 +1281,9 @@ upgt_eeprom_parse_freq4(struct upgt_softc *sc, uint8_t *data, int len) DPRINTF(sc, UPGT_DEBUG_FW, "flags=0x%02x elements=%d settings=%d\n", flags, elements, settings); + if (elements >= (int)(UPGT_EEPROM_SIZE / sizeof(freq4_1[0]))) + return; + for (i = 0; i < elements; i++) { channel = ieee80211_mhz2ieee(le16toh(freq4_1[i].freq), 0); if (channel >= IEEE80211_CHAN_MAX) @@ -1282,7 +1304,8 @@ void upgt_eeprom_parse_freq6(struct upgt_softc *sc, uint8_t *data, int len) { struct upgt_lmac_freq6 *freq6; - int i, elements; + int i; + int elements; unsigned channel; freq6 = (struct upgt_lmac_freq6 *)data; @@ -1290,6 +1313,9 @@ upgt_eeprom_parse_freq6(struct upgt_softc *sc, uint8_t *data, int len) DPRINTF(sc, UPGT_DEBUG_FW, "elements=%d\n", elements); + if (elements >= (int)(UPGT_EEPROM_SIZE / sizeof(freq6[0]))) + return; + for (i = 0; i < elements; i++) { channel = ieee80211_mhz2ieee(le16toh(freq6[i].freq), 0); if (channel >= IEEE80211_CHAN_MAX) diff --git a/sys/dev/usb/wlan/if_upgtvar.h b/sys/dev/usb/wlan/if_upgtvar.h index 6ef699fb182..070f9f6769e 100644 --- a/sys/dev/usb/wlan/if_upgtvar.h +++ b/sys/dev/usb/wlan/if_upgtvar.h @@ -453,7 +453,7 @@ struct upgt_softc { struct upgt_memory sc_memory; /* data which we found in the EEPROM */ - uint8_t sc_eeprom[UPGT_EEPROM_SIZE]; + uint8_t sc_eeprom[2 * UPGT_EEPROM_SIZE] __aligned(4); uint16_t sc_eeprom_hwrx; struct upgt_lmac_freq3 sc_eeprom_freq3[IEEE80211_CHAN_MAX]; struct upgt_lmac_freq4 sc_eeprom_freq4[IEEE80211_CHAN_MAX][8]; From feb043c69c8f987b32e69b71e426e7b079d39b8a Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Mon, 18 Feb 2013 18:39:15 +0000 Subject: [PATCH 0257/1476] Fix an incorrect sizeof() PR: kern/176238 Submitted by: Christoph Mallon --- sys/dev/ath/if_ath_alq.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/ath/if_ath_alq.h b/sys/dev/ath/if_ath_alq.h index 52a022d4963..541f2d7dcbb 100644 --- a/sys/dev/ath/if_ath_alq.h +++ b/sys/dev/ath/if_ath_alq.h @@ -168,7 +168,7 @@ if_ath_alq_post_intr(struct if_ath_alq *alq, uint32_t status, intr.intr_state[i] = htobe32(state[i]); intr.intr_syncstate = htobe32(sync_state); - if_ath_alq_post(alq, ATH_ALQ_INTR_STATUS, sizeof(&intr), + if_ath_alq_post(alq, ATH_ALQ_INTR_STATUS, sizeof(intr), (const char *) &intr); } From ccc63572aba0ca6725bc7b7cc14413c33fba01f5 Mon Sep 17 00:00:00 2001 From: Gregory Neil Shapiro Date: Mon, 18 Feb 2013 19:23:41 +0000 Subject: [PATCH 0258/1476] Fix regression in sendmail 8.14.6 release based on errata published at: http://www.sendmail.com/sm/open_source/download/8.14.6/ --- src/milter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/milter.c b/src/milter.c index 9774a91efde..a403a164351 100644 --- a/src/milter.c +++ b/src/milter.c @@ -4048,7 +4048,7 @@ milter_helo(helo, e, state) } response = milter_command(SMFIC_HELO, helo, strlen(helo) + 1, - SMFIM_EOH, e, state, "helo", false); + SMFIM_HELO, e, state, "helo", false); milter_per_connection_check(e); return response; } From 3772ab21ab433743cfe564230ae4e191ef0baad2 Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Mon, 18 Feb 2013 20:11:20 +0000 Subject: [PATCH 0259/1476] Clarify an error message. The addresses here are really offsets within the primary mapped memory block (which may not start at address zero). --- sys/boot/uboot/lib/copy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/boot/uboot/lib/copy.c b/sys/boot/uboot/lib/copy.c index 71b7a94bbb9..3adf7ebf5bc 100644 --- a/sys/boot/uboot/lib/copy.c +++ b/sys/boot/uboot/lib/copy.c @@ -66,7 +66,7 @@ uboot_vm_translate(vm_offset_t o) { */ } if (o > size) - panic("Address 0x%08jX bigger than size 0x%08X\n", + panic("Address offset 0x%08jX bigger than size 0x%08X\n", (intmax_t)o, size); return (void *)(start + o); } From fea692b5f6cfedb06fd8ff67140d3cf041345a2e Mon Sep 17 00:00:00 2001 From: Joel Dahl Date: Mon, 18 Feb 2013 20:21:26 +0000 Subject: [PATCH 0260/1476] mdoc: sort sections. --- share/man/man5/group.5 | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/share/man/man5/group.5 b/share/man/man5/group.5 index 4a366f67a00..8cf52b886ad 100644 --- a/share/man/man5/group.5 +++ b/share/man/man5/group.5 @@ -116,6 +116,17 @@ file. .\" char **gr_mem; /* group members */ .\" }; .\" .Ed +.Sh IMPLEMENTATION NOTES +The +.Xr passwd 1 +command does not change the +.Nm +passwords. +The +.Xr pw 8 +utility's +.Cm groupmod +command should be used instead. .Sh LIMITS There are various limitations which are explained in the function where they occur; see section @@ -157,14 +168,3 @@ file format appeared in .At v6 . Support for comments first appeared in .Fx 3.0 . -.Sh IMPLEMENTATION NOTES -The -.Xr passwd 1 -command does not change the -.Nm -passwords. -The -.Xr pw 8 -utility's -.Cm groupmod -command should be used instead. From e42412a96695d0e9116de5c6ac75823d2711218d Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Mon, 18 Feb 2013 22:47:16 +0000 Subject: [PATCH 0261/1476] Mark the coretemp(4) sysctls as MPSAFE, ensuring that Giant won't be held unnecessarily by a user thread waiting to run on a specific CPU after calling sched_bind(). Reviewed by: rstone Approved by: emaste (co-mentor) Sponsored by: Sandvine Incorporated MFC after: 1 week --- sys/dev/coretemp/coretemp.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sys/dev/coretemp/coretemp.c b/sys/dev/coretemp/coretemp.c index 55efca232b1..a7d5fdca312 100644 --- a/sys/dev/coretemp/coretemp.c +++ b/sys/dev/coretemp/coretemp.c @@ -274,23 +274,23 @@ coretemp_attach(device_t dev) * Add the MIBs to dev.cpu.N and dev.cpu.N.coretemp. */ SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(device_get_sysctl_tree(pdev)), - OID_AUTO, "temperature", CTLTYPE_INT | CTLFLAG_RD, dev, - CORETEMP_TEMP, coretemp_get_val_sysctl, "IK", + OID_AUTO, "temperature", CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, + dev, CORETEMP_TEMP, coretemp_get_val_sysctl, "IK", "Current temperature"); SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "delta", - CTLTYPE_INT | CTLFLAG_RD, dev, CORETEMP_DELTA, + CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, CORETEMP_DELTA, coretemp_get_val_sysctl, "I", "Delta between TCC activation and current temperature"); SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "resolution", - CTLTYPE_INT | CTLFLAG_RD, dev, CORETEMP_RESOLUTION, + CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, CORETEMP_RESOLUTION, coretemp_get_val_sysctl, "I", "Resolution of CPU thermal sensor"); SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "tjmax", - CTLTYPE_INT | CTLFLAG_RD, dev, CORETEMP_TJMAX, + CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, CORETEMP_TJMAX, coretemp_get_val_sysctl, "IK", "TCC activation temperature"); SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO, - "throttle_log", CTLTYPE_INT | CTLFLAG_RW, dev, 0, + "throttle_log", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, 0, coretemp_throttle_log_sysctl, "I", "Set to 1 if the thermal sensor has tripped"); From 5a9ecb5bb2cad995cd97d2ca4be64f2d337ef2e4 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Mon, 18 Feb 2013 22:47:59 +0000 Subject: [PATCH 0262/1476] setbuf(3): Restore a BUGS section about setbuf(). The brokenness of setbuf() is not specific to 4.2BSD and 4.3BSD but inherent in the API definition. Reported by: bde --- lib/libc/stdio/setbuf.3 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/libc/stdio/setbuf.3 b/lib/libc/stdio/setbuf.3 index 337a7c55deb..d1ae70b0334 100644 --- a/lib/libc/stdio/setbuf.3 +++ b/lib/libc/stdio/setbuf.3 @@ -32,7 +32,7 @@ .\" @(#)setbuf.3 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" -.Dd February 15, 2013 +.Dd February 18, 2013 .Dt SETBUF 3 .Os .Sh NAME @@ -195,3 +195,6 @@ and functions conform to .St -isoC . +.Sh BUGS +.Fn setbuf +usually uses a suboptimal buffer size and should be avoided. From 3e256ed76489eb5e0a0943638a558a1e21f33454 Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Mon, 18 Feb 2013 23:13:13 +0000 Subject: [PATCH 0263/1476] Add mem_load_raw() for loading data from another location in memory. This will be used by some upcoming changes to loader(8) FDT handling to allow it to use an FDT provided by an earlier boot stage the same as an FDT loaded from disk. --- sys/boot/common/bootstrap.h | 2 ++ sys/boot/common/module.c | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/sys/boot/common/bootstrap.h b/sys/boot/common/bootstrap.h index 516b8a58646..78b3895b71c 100644 --- a/sys/boot/common/bootstrap.h +++ b/sys/boot/common/bootstrap.h @@ -237,6 +237,8 @@ void file_discard(struct preloaded_file *fp); void file_addmetadata(struct preloaded_file *fp, int type, size_t size, void *p); int file_addmodule(struct preloaded_file *fp, char *modname, int version, struct kernel_module **newmp); +/* Load from a buffer in memory. */ +struct preloaded_file *mem_load_raw(char *type, char *name, const void *p, size_t len); /* MI module loaders */ #ifdef __elfN diff --git a/sys/boot/common/module.c b/sys/boot/common/module.c index 96c0a58d5e1..3b74ab7856e 100644 --- a/sys/boot/common/module.c +++ b/sys/boot/common/module.c @@ -351,6 +351,7 @@ file_load_dependencies(struct preloaded_file *base_file) } return (error); } + /* * We've been asked to load (name) as (type), so just suck it in, * no arguments or anything. @@ -420,6 +421,42 @@ file_loadraw(char *type, char *name) return(CMD_OK); } +/* + * Load a chunk of data as if it had been read from a file. + */ +struct preloaded_file * +mem_load_raw(char *type, char *name, const void *p, size_t len) +{ + struct preloaded_file *fp; + + /* We can't load first */ + if ((file_findfile(NULL, NULL)) == NULL) { + command_errmsg = "can't load file before kernel"; + return(NULL); + } + + if (archsw.arch_loadaddr != NULL) + loadaddr = archsw.arch_loadaddr(LOAD_RAW, name, loadaddr); + archsw.arch_copyin(p, loadaddr, len); + + /* Looks OK so far; create & populate control structure */ + fp = file_alloc(); + fp->f_name = strdup(name); + fp->f_type = strdup(type); + fp->f_args = NULL; + fp->f_metadata = NULL; + fp->f_loader = -1; + fp->f_addr = loadaddr; + fp->f_size = len; + + /* recognise space consumption */ + loadaddr += len; + + /* Add to the list of loaded files */ + file_insert_tail(fp); + return fp; +} + /* * Load the module (name), pass it (argc),(argv), add container file * to the list of loaded files. From e5ed2130827d4aabad648b387fd54aa5982ad5f7 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Mon, 18 Feb 2013 23:58:05 +0000 Subject: [PATCH 0264/1476] More white-space cleanups. Reported by: zont (the first one) --- sys/sys/protosw.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/sys/protosw.h b/sys/sys/protosw.h index d79e243af2c..78d6e069a05 100644 --- a/sys/sys/protosw.h +++ b/sys/sys/protosw.h @@ -210,7 +210,7 @@ struct pr_usrreqs { #define PRUS_EOF 0x2 #define PRUS_MORETOCOME 0x4 int (*pru_sense)(struct socket *so, struct stat *sb); - int (*pru_shutdown)(struct socket *so); + int (*pru_shutdown)(struct socket *so); int (*pru_flush)(struct socket *so, int direction); int (*pru_sockaddr)(struct socket *so, struct sockaddr **nam); int (*pru_sosend)(struct socket *so, struct sockaddr *addr, @@ -266,7 +266,7 @@ int pru_sopoll_notsupp(struct socket *so, int events, struct ucred *cred, */ #define PRC_IFDOWN 0 /* interface transition */ #define PRC_ROUTEDEAD 1 /* select new route if possible ??? */ -#define PRC_IFUP 2 /* interface has come back up */ +#define PRC_IFUP 2 /* interface has come back up */ #define PRC_QUENCH2 3 /* DEC congestion bit says slow down */ #define PRC_QUENCH 4 /* some one said to slow down */ #define PRC_MSGSIZE 5 /* message size forced drop */ From bf4e1ed0bcd549fdc437725f98981e15aaf32990 Mon Sep 17 00:00:00 2001 From: Ganbold Tsagaankhuu Date: Tue, 19 Feb 2013 02:01:35 +0000 Subject: [PATCH 0265/1476] Define gpio constants rather than using enum. Fix pull-up and pull-down values of gpio. According to A10 user manual possible pull register values are 00 Pull-up/down disable, 01 Pull-up, 10 Pull-down. Approved by: gonzo@ --- sys/arm/allwinner/a10_gpio.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/sys/arm/allwinner/a10_gpio.c b/sys/arm/allwinner/a10_gpio.c index b70d0364bd8..bc0d92a21b7 100644 --- a/sys/arm/allwinner/a10_gpio.c +++ b/sys/arm/allwinner/a10_gpio.c @@ -66,6 +66,13 @@ __FBSDID("$FreeBSD$"); #define A10_GPIO_DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | \ GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN) +#define A10_GPIO_NONE 0 +#define A10_GPIO_PULLUP 1 +#define A10_GPIO_PULLDOWN 2 + +#define A10_GPIO_INPUT 0 +#define A10_GPIO_OUTPUT 1 + struct a10_gpio_softc { device_t sc_dev; struct mtx sc_mtx; @@ -78,17 +85,6 @@ struct a10_gpio_softc { struct gpio_pin sc_gpio_pins[A10_GPIO_PINS]; }; -enum a10_gpio_fsel { - A10_GPIO_INPUT, - A10_GPIO_OUTPUT, -}; - -enum a10_gpio_pud { - A10_GPIO_NONE, - A10_GPIO_PULLDOWN, - A10_GPIO_PULLUP, -}; - #define A10_GPIO_LOCK(_sc) mtx_lock(&_sc->sc_mtx) #define A10_GPIO_UNLOCK(_sc) mtx_unlock(&_sc->sc_mtx) #define A10_GPIO_LOCK_ASSERT(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED) From bab63de28670859bd799917dc6807320f5be86ba Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Tue, 19 Feb 2013 02:09:18 +0000 Subject: [PATCH 0266/1476] kgdb enhancements! * document the kgdb -b flag * better verify what's valid with -b * add more comprehensive command line help PR: kern/175743 Submitted by: Christoph Mallon --- gnu/usr.bin/gdb/kgdb/kgdb.1 | 4 ++++ gnu/usr.bin/gdb/kgdb/main.c | 19 +++++++++---------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/gnu/usr.bin/gdb/kgdb/kgdb.1 b/gnu/usr.bin/gdb/kgdb/kgdb.1 index 4073d705f8b..58d0786dbed 100644 --- a/gnu/usr.bin/gdb/kgdb/kgdb.1 +++ b/gnu/usr.bin/gdb/kgdb/kgdb.1 @@ -33,6 +33,7 @@ .Sh SYNOPSIS .Nm .Op Fl a | Fl f | Fl fullname +.Op Fl b Ar rate .Op Fl q | Fl quiet .Op Fl v .Op Fl w @@ -62,6 +63,9 @@ The or .Fl fullname options are supported for backward compatibility as well. +.It Fl b Ar rate +Set the baudrate to +.Ar rate . .It Fl q Suppress printing of the banner when the debugger starts. The diff --git a/gnu/usr.bin/gdb/kgdb/main.c b/gnu/usr.bin/gdb/kgdb/main.c index 45a3dc0040f..aa062a2dd8c 100644 --- a/gnu/usr.bin/gdb/kgdb/main.c +++ b/gnu/usr.bin/gdb/kgdb/main.c @@ -83,7 +83,7 @@ usage(void) { fprintf(stderr, - "usage: %s [-afqvw] [-d crashdir] [-c core | -n dumpnr | -r device]\n" + "usage: %s [-afqvw] [-b rate] [-d crashdir] [-c core | -n dumpnr | -r device]\n" "\t[kernel [core]]\n", getprogname()); exit(1); } @@ -338,19 +338,18 @@ main(int argc, char *argv[]) case 'a': annotation_level++; break; - case 'b': - { - int i; - char *p; + case 'b': { + int i; + char *p; - i = strtol (optarg, &p, 0); - if (i == 0 && p == optarg) + i = strtol(optarg, &p, 0); + if (*p != '\0' || p == optarg) warnx("warning: could not set baud rate to `%s'.\n", optarg); - else - baud_rate = i; - } + else + baud_rate = i; break; + } case 'c': /* use given core file. */ if (vmcore != NULL) { warnx("option %c: can only be specified once", From 9be24c38b82ec7d9cb0b88d680d0b28ae8c8358b Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Tue, 19 Feb 2013 03:23:13 +0000 Subject: [PATCH 0267/1476] - Make sure to set an error code when trying to obtain a data descriptor for a section of type SHT_NULL. - Update the man page to reflect the fact that elf_getdata() and elf_rawdata() may return with an error of ELF_E_SECTION. PR: bin/175491 Approved by: emaste (co-mentor) MFC after: 1 week --- lib/libelf/elf_data.c | 8 ++++++-- lib/libelf/elf_getdata.3 | 19 ++++++++++++++++++- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/lib/libelf/elf_data.c b/lib/libelf/elf_data.c index c34c4ad358b..d3bd3907218 100644 --- a/lib/libelf/elf_data.c +++ b/lib/libelf/elf_data.c @@ -78,8 +78,10 @@ elf_getdata(Elf_Scn *s, Elf_Data *d) sh_align = s->s_shdr.s_shdr64.sh_addralign; } - if (sh_type == SHT_NULL) + if (sh_type == SHT_NULL) { + LIBELF_SET_ERROR(SECTION, 0); return (NULL); + } if ((elftype = _libelf_xlate_shtype(sh_type)) < ELF_T_FIRST || elftype > ELF_T_LAST || (sh_type != SHT_NOBITS && @@ -219,8 +221,10 @@ elf_rawdata(Elf_Scn *s, Elf_Data *d) sh_align = s->s_shdr.s_shdr64.sh_addralign; } - if (sh_type == SHT_NULL) + if (sh_type == SHT_NULL) { + LIBELF_SET_ERROR(SECTION, 0); return (NULL); + } if ((d = _libelf_allocate_data(s)) == NULL) return (NULL); diff --git a/lib/libelf/elf_getdata.3 b/lib/libelf/elf_getdata.3 index 97766d8e8c9..79612207b42 100644 --- a/lib/libelf/elf_getdata.3 +++ b/lib/libelf/elf_getdata.3 @@ -23,7 +23,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 26, 2011 +.Dd February 18, 2013 .Dt ELF_GETDATA 3 .Os .Sh NAME @@ -186,6 +186,23 @@ was not associated with section descriptor .Ar scn . .It Bq Er ELF_E_RESOURCE An out of memory condition was detected. +.It Bq Er ELF_E_SECTION +Section +.Ar scn +had type +.Dv SHT_NULL . +.It Bq Er ELF_E_SECTION +The type of the section +.Ar scn +was not recognized by the library. +.It Bq Er ELF_E_SECTION +The size of the section +.Ar scn +is not a multiple of the file size for its section type. +.It Bq Er ELF_E_SECTION +The file offset for section +.Ar scn +is incorrect. .El .Sh SEE ALSO .Xr elf 3 , From b5a44455d68a42bf3a29566b6888aab7c702863e Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Tue, 19 Feb 2013 06:42:12 +0000 Subject: [PATCH 0268/1476] Print out the RTS/CTS rate in the TX descriptor. --- tools/tools/ath/athalq/ar5416_ds.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/tools/ath/athalq/ar5416_ds.c b/tools/tools/ath/athalq/ar5416_ds.c index a8c827a1785..c7d1bb42ec5 100644 --- a/tools/tools/ath/athalq/ar5416_ds.c +++ b/tools/tools/ath/athalq/ar5416_ds.c @@ -227,6 +227,8 @@ ar5416_decode_txdesc(struct if_ath_alq_payload *a) MF(txc.ds_ctl7, AR_2040_3), MF(txc.ds_ctl7, AR_STBC3)); + printf(" RTSCtsRate=0x%02x\n", MS(txc.ds_ctl7, AR_RTSCTSRate)); + /* ds_ctl8 */ printf(" try 0: ant=0x%08x\n", txc.ds_ctl8 & AR_AntCtl0); From 6dcf64df0047f596b9e8c9615d6d607f81de675c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulrich=20Sp=C3=B6rlein?= Date: Tue, 19 Feb 2013 10:25:51 +0000 Subject: [PATCH 0269/1476] Fix typo Submitted by: Matt Burke --- sys/dev/sound/pci/hda/hdaa.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/dev/sound/pci/hda/hdaa.c b/sys/dev/sound/pci/hda/hdaa.c index 69fab04a5b3..ac10d0ac5c1 100644 --- a/sys/dev/sound/pci/hda/hdaa.c +++ b/sys/dev/sound/pci/hda/hdaa.c @@ -557,7 +557,7 @@ hdaa_presence_handler(struct hdaa_widget *w) HDA_BOOTVERBOSE( if (connected || old != 2) { device_printf(devinfo->dev, - "Pin sense: nid=%d sence=0x%08x (%sconnected)\n", + "Pin sense: nid=%d sense=0x%08x (%sconnected)\n", w->nid, res, !connected ? "dis" : ""); } ); @@ -706,7 +706,7 @@ hdaa_eld_handler(struct hdaa_widget *w) } HDA_BOOTVERBOSE( device_printf(devinfo->dev, - "Pin sense: nid=%d sence=0x%08x " + "Pin sense: nid=%d sense=0x%08x " "(%sconnected, ELD %svalid)\n", w->nid, res, (res & HDA_CMD_GET_PIN_SENSE_PRESENCE_DETECT) ? "" : "dis", From 00c31a91ef14fe363778d41d3ea51669523b48a9 Mon Sep 17 00:00:00 2001 From: Philippe Charnier Date: Tue, 19 Feb 2013 12:57:07 +0000 Subject: [PATCH 0270/1476] Remove old-style function definition --- usr.bin/systat/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr.bin/systat/main.c b/usr.bin/systat/main.c index a429f572b4e..1aed28ab4a8 100644 --- a/usr.bin/systat/main.c +++ b/usr.bin/systat/main.c @@ -192,7 +192,7 @@ labels(void) } void -display() +display(void) { int i, j; From 321ae07f36f17c1a2b5128719eb6297337bc19f7 Mon Sep 17 00:00:00 2001 From: Philippe Charnier Date: Tue, 19 Feb 2013 13:17:16 +0000 Subject: [PATCH 0271/1476] WARNS=6 compliance --- usr.bin/netstat/inet.c | 2 +- usr.bin/netstat/inet6.c | 2 +- usr.bin/netstat/main.c | 4 +--- usr.bin/netstat/netisr.c | 6 +++--- usr.bin/netstat/sctp.c | 6 +++--- usr.bin/netstat/unix.c | 1 + 6 files changed, 10 insertions(+), 11 deletions(-) diff --git a/usr.bin/netstat/inet.c b/usr.bin/netstat/inet.c index 8094e5bbf16..57123a7f6ad 100644 --- a/usr.bin/netstat/inet.c +++ b/usr.bin/netstat/inet.c @@ -89,7 +89,7 @@ static int udp_done, tcp_done, sdp_done; #endif /* INET6 */ static int -pcblist_sysctl(int proto, const char *name, char **bufp, int istcp) +pcblist_sysctl(int proto, const char *name, char **bufp, int istcp __unused) { const char *mibvar; char *buf; diff --git a/usr.bin/netstat/inet6.c b/usr.bin/netstat/inet6.c index 1a19fa535b5..9f51d067776 100644 --- a/usr.bin/netstat/inet6.c +++ b/usr.bin/netstat/inet6.c @@ -335,7 +335,7 @@ static const char *ip6nh[] = { "#255", }; -static char *srcrule_str[] = { +static const char *srcrule_str[] = { "first candidate", "same address", "appropriate scope", diff --git a/usr.bin/netstat/main.c b/usr.bin/netstat/main.c index 09c00968567..2a996ae9fed 100644 --- a/usr.bin/netstat/main.c +++ b/usr.bin/netstat/main.c @@ -640,9 +640,7 @@ main(int argc, char *argv[]) * is not in the namelist, ignore this one. */ static void -printproto(tp, name) - struct protox *tp; - const char *name; +printproto(struct protox *tp, const char *name) { void (*pr)(u_long, const char *, int, int); u_long off; diff --git a/usr.bin/netstat/netisr.c b/usr.bin/netstat/netisr.c index cc05c38b76e..6c945c32d91 100644 --- a/usr.bin/netstat/netisr.c +++ b/usr.bin/netstat/netisr.c @@ -76,12 +76,12 @@ static u_int *nws_array; static u_int maxprot; static void -netisr_dispatch_policy_to_string(u_int dispatch_policy, char *buf, +netisr_dispatch_policy_to_string(u_int policy, char *buf, size_t buflen) { const char *str; - switch (dispatch_policy) { + switch (policy) { case NETISR_DISPATCH_DEFAULT: str = "default"; break; @@ -102,7 +102,7 @@ netisr_dispatch_policy_to_string(u_int dispatch_policy, char *buf, } static void -netisr_load_kvm_uint(kvm_t *kd, char *name, u_int *p) +netisr_load_kvm_uint(kvm_t *kd, const char *name, u_int *p) { struct nlist nl[] = { { .n_name = name }, diff --git a/usr.bin/netstat/sctp.c b/usr.bin/netstat/sctp.c index 2f67b0cde06..a2ef7d5682f 100644 --- a/usr.bin/netstat/sctp.c +++ b/usr.bin/netstat/sctp.c @@ -77,7 +77,7 @@ static void sctp_statesprint(uint32_t state); #define NETSTAT_SCTP_STATES_SHUTDOWN_ACK_SENT 0x8 #define NETSTAT_SCTP_STATES_SHUTDOWN_PENDING 0x9 -char *sctpstates[] = { +const char *sctpstates[] = { "CLOSED", "BOUND", "LISTEN", @@ -393,7 +393,7 @@ sctp_process_inpcb(struct xsctp_inpcb *xinpcb, { int indent = 0, xladdr_total = 0, is_listening = 0; static int first = 1; - char *tname, *pname; + const char *tname, *pname; struct xsctp_tcb *xstcb; struct xsctp_laddr *xladdr; size_t offset_laddr; @@ -527,7 +527,7 @@ retry: */ void sctp_protopr(u_long off __unused, - const char *name, int af1, int proto) + const char *name __unused, int af1 __unused, int proto) { char *buf; const char *mibvar = "net.inet.sctp.assoclist"; diff --git a/usr.bin/netstat/unix.c b/usr.bin/netstat/unix.c index 9a643c201cd..027e812cf7c 100644 --- a/usr.bin/netstat/unix.c +++ b/usr.bin/netstat/unix.c @@ -199,6 +199,7 @@ unixpr(u_long count_off, u_long gencnt_off, u_long dhead_off, u_long shead_off, struct xunpcb *xunp; u_long head_off; + buf = NULL; for (type = SOCK_STREAM; type <= SOCK_SEQPACKET; type++) { if (live) ret = pcblist_sysctl(type, &buf); From 589db6893119ff1c6ed73d2f5b1a6d81cc28f973 Mon Sep 17 00:00:00 2001 From: Philippe Charnier Date: Tue, 19 Feb 2013 13:32:26 +0000 Subject: [PATCH 0272/1476] WARNS=6 compliance --- usr.bin/keylogin/keylogin.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/usr.bin/keylogin/keylogin.c b/usr.bin/keylogin/keylogin.c index 8e10d957b3e..3f4bdba94d2 100644 --- a/usr.bin/keylogin/keylogin.c +++ b/usr.bin/keylogin/keylogin.c @@ -48,8 +48,10 @@ __FBSDID("$FreeBSD$"); #include #include +extern int key_setnet(struct key_netstarg *); + int -main() +main(void) { char fullname[MAXNETNAMELEN + 1]; struct key_netstarg netst; From 353374b525ffdd9f7702eeda9369e3abbcbd45b6 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Tue, 19 Feb 2013 16:35:27 +0000 Subject: [PATCH 0273/1476] Fix a few typos. --- sys/kern/kern_thread.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c index bee267f6278..4f0266b668e 100644 --- a/sys/kern/kern_thread.c +++ b/sys/kern/kern_thread.c @@ -748,10 +748,10 @@ stopme: * P_SINGLE_EXIT | return_instead == 0| return_instead != 0 *---------------+--------------------+--------------------- * 0 | returns 0 | returns 0 or 1 - * | when ST ends | immediatly + * | when ST ends | immediately *---------------+--------------------+--------------------- * 1 | thread exits | returns 1 - * | | immediatly + * | | immediately * 0 = thread_exit() or suspension ok, * other = return error instead of stopping the thread. * From ce4642ecd54e7f1db9e1a63e6733304fabd09dc7 Mon Sep 17 00:00:00 2001 From: Davide Italiano Date: Tue, 19 Feb 2013 16:43:48 +0000 Subject: [PATCH 0274/1476] Fixup r246916 in case gcc is used to build. Reported by: attilio, simon --- sys/x86/isa/clock.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/x86/isa/clock.c b/sys/x86/isa/clock.c index 42cc4485aa6..6c69759ac67 100644 --- a/sys/x86/isa/clock.c +++ b/sys/x86/isa/clock.c @@ -450,6 +450,8 @@ set_i8254_freq(int mode, uint32_t period) outb(TIMER_CNTR0, new_count & 0xff); outb(TIMER_CNTR0, new_count >> 8); break; + default: + panic("set_i8254_freq: unknown operational mode"); } timer0_mode = new_mode; timer0_last = new_count; From 4faa1dea0b24bab0e66e25ee808c98a56ce67799 Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Tue, 19 Feb 2013 17:09:23 +0000 Subject: [PATCH 0275/1476] Fix includes for use in libstand. --- lib/libstand/strtoul.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/libstand/strtoul.c b/lib/libstand/strtoul.c index c1609fb3d20..5735d20d25e 100644 --- a/lib/libstand/strtoul.c +++ b/lib/libstand/strtoul.c @@ -38,10 +38,8 @@ static char sccsid[] = "@(#)strtoul.c 8.1 (Berkeley) 6/4/93"; #include __FBSDID("$FreeBSD$"); +#include "stand.h" #include -#include -#include -#include /* * Convert a string to an unsigned long integer. From d2a99d8189d769f6138c8258b927cb475336dd24 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Tue, 19 Feb 2013 17:38:18 +0000 Subject: [PATCH 0276/1476] Import change 6d783560e4aad1e680097d11e89755647a5aba87 from upstream heimdal: fix sizeof(uuid) Found by: clang ToT Reviewed by: stas --- crypto/heimdal/kcm/cache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/heimdal/kcm/cache.c b/crypto/heimdal/kcm/cache.c index 1bd220c8a70..47442c353f0 100644 --- a/crypto/heimdal/kcm/cache.c +++ b/crypto/heimdal/kcm/cache.c @@ -102,7 +102,7 @@ kcm_ccache_resolve_by_uuid(krb5_context context, for (p = ccache_head; p != NULL; p = p->next) { if ((p->flags & KCM_FLAGS_VALID) == 0) continue; - if (memcmp(p->uuid, uuid, sizeof(uuid)) == 0) { + if (memcmp(p->uuid, uuid, sizeof(kcmuuid_t)) == 0) { ret = 0; break; } From 953290ffde5e53c99a26f1dff12ed0fa0aa9c536 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Tue, 19 Feb 2013 17:53:32 +0000 Subject: [PATCH 0277/1476] Pull in r175360 from upstream llvm trunk: MCParser: Reject .balign with non-pow2 alignments. GNU as rejects them and there are configure scripts in the wild that check if the assembler rejects ".align 3" to determine whether the alignment is in bytes or powers of two. MFC after: 3 days --- contrib/llvm/lib/MC/MCParser/AsmParser.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/contrib/llvm/lib/MC/MCParser/AsmParser.cpp b/contrib/llvm/lib/MC/MCParser/AsmParser.cpp index 6f2e85e5533..414d2d5eba1 100644 --- a/contrib/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/contrib/llvm/lib/MC/MCParser/AsmParser.cpp @@ -2372,6 +2372,10 @@ bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) { } Alignment = 1ULL << Alignment; + } else { + // Reject alignments that aren't a power of two, for gas compatibility. + if (!isPowerOf2_64(Alignment)) + Error(AlignmentLoc, "alignment must be a power of 2"); } // Diagnose non-sensical max bytes to align. From fd7e68271969f2a6a2b4a10cbc451c090ac276a3 Mon Sep 17 00:00:00 2001 From: Alexander Motin Date: Tue, 19 Feb 2013 18:22:25 +0000 Subject: [PATCH 0278/1476] MFcalloutng: Make dcons input polling adaptive, reducing poll rate to 1Hz after several minutes of inactivty to reduce global interrupt rate. Most of users never used FireWire debugging, so it is not very useful to consume power by it. --- sys/dev/dcons/dcons_os.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/sys/dev/dcons/dcons_os.c b/sys/dev/dcons/dcons_os.c index a37d64c8706..bf0be0b29cb 100644 --- a/sys/dev/dcons/dcons_os.c +++ b/sys/dev/dcons/dcons_os.c @@ -74,6 +74,10 @@ #define DCONS_POLL_HZ 25 #endif +#ifndef DCONS_POLL_IDLE +#define DCONS_POLL_IDLE 256 +#endif + #ifndef DCONS_BUF_SIZE #define DCONS_BUF_SIZE (16*1024) #endif @@ -90,6 +94,7 @@ static char bssbuf[DCONS_BUF_SIZE]; /* buf in bss */ static struct dcons_global dg; struct dcons_global *dcons_conf; static int poll_hz = DCONS_POLL_HZ; +static u_int poll_idle = DCONS_POLL_HZ * DCONS_POLL_IDLE; static struct dcons_softc sc[DCONS_NPORT]; @@ -214,14 +219,17 @@ dcons_timeout(void *v) tp = dc->tty; tty_lock(tp); - while ((c = dcons_os_checkc_nopoll(dc)) != -1) + while ((c = dcons_os_checkc_nopoll(dc)) != -1) { ttydisc_rint(tp, c, 0); + poll_idle = 0; + } ttydisc_rint_done(tp); tty_unlock(tp); } - polltime = hz / poll_hz; - if (polltime < 1) - polltime = 1; + poll_idle++; + polltime = hz; + if (poll_idle <= (poll_hz * DCONS_POLL_IDLE)) + polltime /= poll_hz; callout_reset(&dcons_callout, polltime, dcons_timeout, tp); } @@ -368,8 +376,6 @@ dcons_attach(void) dcons_attach_port(DCONS_GDB, "dgdb", DC_GDB); callout_init(&dcons_callout, CALLOUT_MPSAFE); polltime = hz / poll_hz; - if (polltime < 1) - polltime = 1; callout_reset(&dcons_callout, polltime, dcons_timeout, NULL); return(0); } From eaef137cbea2de74694b479ca41d4d1dd38d2d18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulrich=20Sp=C3=B6rlein?= Date: Tue, 19 Feb 2013 18:28:25 +0000 Subject: [PATCH 0279/1476] dtc: fix bootstrapping from 8.2-STABLE MFC after: 1 week Approved by: theraven --- usr.bin/dtc/input_buffer.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/usr.bin/dtc/input_buffer.cc b/usr.bin/dtc/input_buffer.cc index 2a483f32864..10b3a0018be 100644 --- a/usr.bin/dtc/input_buffer.cc +++ b/usr.bin/dtc/input_buffer.cc @@ -43,6 +43,10 @@ #include #include +#ifndef MAP_PREFAULT_READ +#define MAP_PREFAULT_READ 0 +#endif + namespace dtc { From 69c2a7707dfbb0fec7d1eb9b7f2856e94a83b423 Mon Sep 17 00:00:00 2001 From: Alexander Motin Date: Tue, 19 Feb 2013 19:25:50 +0000 Subject: [PATCH 0280/1476] MFcalloutng: Make led(4) fire callouts at 10Hz only when there is at least one LED that is requested to blink. Do not fire if all LEDs are static (usual case). --- sys/dev/led/led.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/sys/dev/led/led.c b/sys/dev/led/led.c index e2a4370e496..fe0b66b8782 100644 --- a/sys/dev/led/led.c +++ b/sys/dev/led/led.c @@ -43,6 +43,7 @@ static struct mtx led_mtx; static struct sx led_sx; static LIST_HEAD(, ledsc) led_list = LIST_HEAD_INITIALIZER(led_list); static struct callout led_ch; +static int blinkers = 0; static MALLOC_DEFINE(M_LED, "LED", "LED driver"); @@ -51,7 +52,6 @@ led_timeout(void *p) { struct ledsc *sc; - mtx_lock(&led_mtx); LIST_FOREACH(sc, &led_list, list) { if (sc->ptr == NULL) continue; @@ -61,6 +61,7 @@ led_timeout(void *p) } if (*sc->ptr == '.') { sc->ptr = NULL; + blinkers--; continue; } else if (*sc->ptr == 'U' || *sc->ptr == 'u') { if (sc->last_second == time_second) @@ -78,9 +79,8 @@ led_timeout(void *p) if (*sc->ptr == '\0') sc->ptr = sc->str; } - mtx_unlock(&led_mtx); - callout_reset(&led_ch, hz / 10, led_timeout, p); - return; + if (blinkers > 0) + callout_reset(&led_ch, hz / 10, led_timeout, p); } static int @@ -92,9 +92,15 @@ led_state(struct ledsc *sc, struct sbuf **sb, int state) sc->spec = *sb; if (*sb != NULL) { sc->str = sbuf_data(*sb); + if (sc->ptr == NULL) { + blinkers++; + callout_reset(&led_ch, hz / 10, led_timeout, NULL); + } sc->ptr = sc->str; } else { sc->str = NULL; + if (sc->ptr != NULL) + blinkers--; sc->ptr = NULL; sc->func(sc->private, state); } @@ -286,8 +292,6 @@ led_create_state(led_t *func, void *priv, char const *name, int state) mtx_lock(&led_mtx); sc->dev->si_drv1 = sc; - if (LIST_EMPTY(&led_list)) - callout_reset(&led_ch, hz / 10, led_timeout, NULL); LIST_INSERT_HEAD(&led_list, sc, list); sc->func(sc->private, state != 0); mtx_unlock(&led_mtx); @@ -303,7 +307,8 @@ led_destroy(struct cdev *dev) mtx_lock(&led_mtx); sc = dev->si_drv1; dev->si_drv1 = NULL; - + if (sc->ptr != NULL) + blinkers--; LIST_REMOVE(sc, list); if (LIST_EMPTY(&led_list)) callout_stop(&led_ch); @@ -326,7 +331,7 @@ led_drvinit(void *unused) led_unit = new_unrhdr(0, INT_MAX, NULL); mtx_init(&led_mtx, "LED mtx", NULL, MTX_DEF); sx_init(&led_sx, "LED sx"); - callout_init(&led_ch, CALLOUT_MPSAFE); + callout_init_mtx(&led_ch, &led_mtx, 0); } SYSINIT(leddev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, led_drvinit, NULL); From f91360b1749c2a4f6bc79415290d7d77ef68dd49 Mon Sep 17 00:00:00 2001 From: Oleksandr Tymoshenko Date: Tue, 19 Feb 2013 20:33:55 +0000 Subject: [PATCH 0281/1476] Roll back change of frequency for initialization sequence since it seems to cause more problems then previous behavior: it either breaks initilization sequence in other places or uncovers problems with high-speed mode timing for SDHCI 3.0 --- sys/arm/broadcom/bcm2835/bcm2835_sdhci.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c b/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c index 1b099866f40..f96fd4ce674 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c @@ -78,7 +78,12 @@ __FBSDID("$FreeBSD$"); #define dprintf(fmt, args...) #endif -static int bcm2835_sdhci_min_freq = 8000000; +/* + * Arasan HC seems to have problem with Data CRC on lower frequencies. + * Use this tunable to cap intilization sequence frequency at higher + * value. Default is standard 400KHz + */ +static int bcm2835_sdhci_min_freq = 400000; static int bcm2835_sdhci_hs = 1; TUNABLE_INT("hw.bcm2835.sdhci.min_freq", &bcm2835_sdhci_min_freq); @@ -346,12 +351,6 @@ static uint32_t bcm_sdhci_min_freq(device_t dev, struct sdhci_slot *slot) { - /* - * Arasan HC seems to have problem with - * Data CRC on lower frequencies. Cap minimum - * frequncy at 8MHz (or whatever set via tunable) - * to work around this issue - */ return bcm2835_sdhci_min_freq; } From 8635d479c2f1e2760b46b3064d8b68309c6ef015 Mon Sep 17 00:00:00 2001 From: Oleksandr Tymoshenko Date: Tue, 19 Feb 2013 21:24:52 +0000 Subject: [PATCH 0282/1476] Spelling fixes Spotted by: N. J. Mann --- sys/arm/broadcom/bcm2835/bcm2835_sdhci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c b/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c index f96fd4ce674..cfba2cd43f1 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c @@ -80,8 +80,8 @@ __FBSDID("$FreeBSD$"); /* * Arasan HC seems to have problem with Data CRC on lower frequencies. - * Use this tunable to cap intilization sequence frequency at higher - * value. Default is standard 400KHz + * Use this tunable to cap initialization sequence frequency at higher + * value. Default is standard 400kHz */ static int bcm2835_sdhci_min_freq = 400000; static int bcm2835_sdhci_hs = 1; From 0a7a780eee27bfb92b03e34899de5e1e4b82b4d5 Mon Sep 17 00:00:00 2001 From: Andrew Gallatin Date: Tue, 19 Feb 2013 21:33:21 +0000 Subject: [PATCH 0283/1476] Add support to mxge for IPv6 TX csum offload & IPv6 TSO. Sponsored by: Myricom, Inc. MFC after: 7 days --- sys/dev/mxge/if_mxge.c | 232 +++++++++++++++++++++++++-------- sys/dev/mxge/if_mxge_var.h | 46 +++++++ sys/modules/mxge/mxge/Makefile | 2 +- 3 files changed, 227 insertions(+), 53 deletions(-) diff --git a/sys/dev/mxge/if_mxge.c b/sys/dev/mxge/if_mxge.c index feefc3b4e82..68afbf9a850 100644 --- a/sys/dev/mxge/if_mxge.c +++ b/sys/dev/mxge/if_mxge.c @@ -62,7 +62,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include #include #include @@ -91,6 +93,7 @@ __FBSDID("$FreeBSD$"); #endif #include "opt_inet.h" +#include "opt_inet6.h" /* tunable params */ static int mxge_nvidia_ecrc_enable = 1; @@ -1810,21 +1813,99 @@ mxge_submit_req(mxge_tx_ring_t *tx, mcp_kreq_ether_send_t *src, wmb(); } +static int +mxge_parse_tx(struct mxge_slice_state *ss, struct mbuf *m, + struct mxge_pkt_info *pi) +{ + struct ether_vlan_header *eh; + uint16_t etype; + int tso = m->m_pkthdr.csum_flags & (CSUM_TSO); +#if IFCAP_TSO6 && defined(INET6) + int nxt; +#endif + + eh = mtod(m, struct ether_vlan_header *); + if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) { + etype = ntohs(eh->evl_proto); + pi->ip_off = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN; + } else { + etype = ntohs(eh->evl_encap_proto); + pi->ip_off = ETHER_HDR_LEN; + } + + switch (etype) { + case ETHERTYPE_IP: + /* + * ensure ip header is in first mbuf, copy it to a + * scratch buffer if not + */ + pi->ip = (struct ip *)(m->m_data + pi->ip_off); + pi->ip6 = NULL; + if (__predict_false(m->m_len < pi->ip_off + sizeof(*pi->ip))) { + m_copydata(m, 0, pi->ip_off + sizeof(*pi->ip), + ss->scratch); + pi->ip = (struct ip *)(ss->scratch + pi->ip_off); + } + pi->ip_hlen = pi->ip->ip_hl << 2; + if (!tso) + return 0; + + if (__predict_false(m->m_len < pi->ip_off + pi->ip_hlen + + sizeof(struct tcphdr))) { + m_copydata(m, 0, pi->ip_off + pi->ip_hlen + + sizeof(struct tcphdr), ss->scratch); + pi->ip = (struct ip *)(ss->scratch + pi->ip_off); + } + pi->tcp = (struct tcphdr *)((char *)pi->ip + pi->ip_hlen); + break; +#if IFCAP_TSO6 && defined(INET6) + case ETHERTYPE_IPV6: + pi->ip6 = (struct ip6_hdr *)(m->m_data + pi->ip_off); + if (__predict_false(m->m_len < pi->ip_off + sizeof(*pi->ip6))) { + m_copydata(m, 0, pi->ip_off + sizeof(*pi->ip6), + ss->scratch); + pi->ip6 = (struct ip6_hdr *)(ss->scratch + pi->ip_off); + } + nxt = 0; + pi->ip_hlen = ip6_lasthdr(m, pi->ip_off, IPPROTO_IPV6, &nxt); + pi->ip_hlen -= pi->ip_off; + if (nxt != IPPROTO_TCP && nxt != IPPROTO_UDP) + return EINVAL; + + if (!tso) + return 0; + + if (pi->ip_off + pi->ip_hlen > ss->sc->max_tso6_hlen) + return EINVAL; + + if (__predict_false(m->m_len < pi->ip_off + pi->ip_hlen + + sizeof(struct tcphdr))) { + m_copydata(m, 0, pi->ip_off + pi->ip_hlen + + sizeof(struct tcphdr), ss->scratch); + pi->ip6 = (struct ip6_hdr *)(ss->scratch + pi->ip_off); + } + pi->tcp = (struct tcphdr *)((char *)pi->ip6 + pi->ip_hlen); + break; +#endif + default: + return EINVAL; + } + return 0; +} + #if IFCAP_TSO4 static void mxge_encap_tso(struct mxge_slice_state *ss, struct mbuf *m, - int busdma_seg_cnt, int ip_off) + int busdma_seg_cnt, struct mxge_pkt_info *pi) { mxge_tx_ring_t *tx; mcp_kreq_ether_send_t *req; bus_dma_segment_t *seg; - struct ip *ip; - struct tcphdr *tcp; uint32_t low, high_swapped; int len, seglen, cum_len, cum_len_next; int next_is_first, chop, cnt, rdma_count, small; - uint16_t pseudo_hdr_offset, cksum_offset, mss; + uint16_t pseudo_hdr_offset, cksum_offset, mss, sum; uint8_t flags, flags_next; static int once; @@ -1835,38 +1916,33 @@ mxge_encap_tso(struct mxge_slice_state *ss, struct mbuf *m, * header portion of the TSO packet. */ - /* ensure we have the ethernet, IP and TCP - header together in the first mbuf, copy - it to a scratch buffer if not */ - if (__predict_false(m->m_len < ip_off + sizeof (*ip))) { - m_copydata(m, 0, ip_off + sizeof (*ip), - ss->scratch); - ip = (struct ip *)(ss->scratch + ip_off); - } else { - ip = (struct ip *)(mtod(m, char *) + ip_off); - } - if (__predict_false(m->m_len < ip_off + (ip->ip_hl << 2) - + sizeof (*tcp))) { - m_copydata(m, 0, ip_off + (ip->ip_hl << 2) - + sizeof (*tcp), ss->scratch); - ip = (struct ip *)(mtod(m, char *) + ip_off); - } - - tcp = (struct tcphdr *)((char *)ip + (ip->ip_hl << 2)); - cum_len = -(ip_off + ((ip->ip_hl + tcp->th_off) << 2)); - cksum_offset = ip_off + (ip->ip_hl << 2); + cksum_offset = pi->ip_off + pi->ip_hlen; + cum_len = -(cksum_offset + (pi->tcp->th_off << 2)); /* TSO implies checksum offload on this hardware */ - if (__predict_false((m->m_pkthdr.csum_flags & (CSUM_TCP)) == 0)) { + if (__predict_false((m->m_pkthdr.csum_flags & (CSUM_TCP|CSUM_TCP_IPV6)) == 0)) { /* * If packet has full TCP csum, replace it with pseudo hdr * sum that the NIC expects, otherwise the NIC will emit * packets with bad TCP checksums. */ - m->m_pkthdr.csum_flags = CSUM_TCP; m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum); - tcp->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, - htons(IPPROTO_TCP + (m->m_pkthdr.len - cksum_offset))); + if (pi->ip6) { +#if (CSUM_TCP_IPV6 != 0) && defined(INET6) + m->m_pkthdr.csum_flags |= CSUM_TCP_IPV6; + sum = in6_cksum_pseudo(pi->ip6, + m->m_pkthdr.len - cksum_offset, + IPPROTO_TCP, 0); +#endif + } else { + m->m_pkthdr.csum_flags |= CSUM_TCP; + sum = in_pseudo(pi->ip->ip_src.s_addr, + pi->ip->ip_dst.s_addr, + htons(IPPROTO_TCP + (m->m_pkthdr.len - + cksum_offset))); + } + m_copyback(m, offsetof(struct tcphdr, th_sum) + + cksum_offset, sizeof(sum), (caddr_t)&sum); } flags = MXGEFW_FLAGS_TSO_HDR | MXGEFW_FLAGS_FIRST; @@ -1876,6 +1952,14 @@ mxge_encap_tso(struct mxge_slice_state *ss, struct mbuf *m, * the checksum by parsing the header. */ pseudo_hdr_offset = htobe16(mss); + if (pi->ip6) { + /* + * for IPv6 TSO, the "checksum offset" is re-purposed + * to store the TCP header len + */ + cksum_offset = (pi->tcp->th_off << 2); + } + tx = &ss->tx; req = tx->req_list; seg = tx->seg_list; @@ -1947,10 +2031,12 @@ mxge_encap_tso(struct mxge_slice_state *ss, struct mbuf *m, req++; cnt++; rdma_count++; - if (__predict_false(cksum_offset > seglen)) - cksum_offset -= seglen; - else - cksum_offset = 0; + if (cksum_offset != 0 && !pi->ip6) { + if (__predict_false(cksum_offset > seglen)) + cksum_offset -= seglen; + else + cksum_offset = 0; + } if (__predict_false(cnt > tx->max_desc)) goto drop; } @@ -2030,14 +2116,14 @@ mxge_vlan_tag_insert(struct mbuf *m) static void mxge_encap(struct mxge_slice_state *ss, struct mbuf *m) { + struct mxge_pkt_info pi = {0,0,0,0}; mxge_softc_t *sc; mcp_kreq_ether_send_t *req; bus_dma_segment_t *seg; struct mbuf *m_tmp; struct ifnet *ifp; mxge_tx_ring_t *tx; - struct ip *ip; - int cnt, cum_len, err, i, idx, odd_flag, ip_off; + int cnt, cum_len, err, i, idx, odd_flag; uint16_t pseudo_hdr_offset; uint8_t flags, cksum_offset; @@ -2046,15 +2132,19 @@ mxge_encap(struct mxge_slice_state *ss, struct mbuf *m) ifp = sc->ifp; tx = &ss->tx; - ip_off = sizeof (struct ether_header); #ifdef MXGE_NEW_VLAN_API if (m->m_flags & M_VLANTAG) { m = mxge_vlan_tag_insert(m); if (__predict_false(m == NULL)) - goto drop; - ip_off += ETHER_VLAN_ENCAP_LEN; + goto drop_without_m; } #endif + if (m->m_pkthdr.csum_flags & + (CSUM_TSO | CSUM_DELAY_DATA | CSUM_DELAY_DATA_IPV6)) { + if (mxge_parse_tx(ss, m, &pi)) + goto drop; + } + /* (try to) map the frame for DMA */ idx = tx->req & tx->mask; err = bus_dmamap_load_mbuf_sg(tx->dmat, tx->info[idx].map, @@ -2086,7 +2176,7 @@ mxge_encap(struct mxge_slice_state *ss, struct mbuf *m) #if IFCAP_TSO4 /* TSO is different enough, we handle it in another routine */ if (m->m_pkthdr.csum_flags & (CSUM_TSO)) { - mxge_encap_tso(ss, m, cnt, ip_off); + mxge_encap_tso(ss, m, cnt, &pi); return; } #endif @@ -2097,17 +2187,11 @@ mxge_encap(struct mxge_slice_state *ss, struct mbuf *m) flags = MXGEFW_FLAGS_NO_TSO; /* checksum offloading? */ - if (m->m_pkthdr.csum_flags & (CSUM_DELAY_DATA)) { + if (m->m_pkthdr.csum_flags & + (CSUM_DELAY_DATA | CSUM_DELAY_DATA_IPV6)) { /* ensure ip header is in first mbuf, copy it to a scratch buffer if not */ - if (__predict_false(m->m_len < ip_off + sizeof (*ip))) { - m_copydata(m, 0, ip_off + sizeof (*ip), - ss->scratch); - ip = (struct ip *)(ss->scratch + ip_off); - } else { - ip = (struct ip *)(mtod(m, char *) + ip_off); - } - cksum_offset = ip_off + (ip->ip_hl << 2); + cksum_offset = pi.ip_off + pi.ip_hlen; pseudo_hdr_offset = cksum_offset + m->m_pkthdr.csum_data; pseudo_hdr_offset = htobe16(pseudo_hdr_offset); req->cksum_offset = cksum_offset; @@ -2190,6 +2274,7 @@ mxge_encap(struct mxge_slice_state *ss, struct mbuf *m) drop: m_freem(m); +drop_without_m: ss->oerrors++; return; } @@ -4126,8 +4211,7 @@ mxge_ioctl(struct ifnet *ifp, u_long command, caddr_t data) if (mask & IFCAP_TXCSUM) { if (IFCAP_TXCSUM & ifp->if_capenable) { ifp->if_capenable &= ~(IFCAP_TXCSUM|IFCAP_TSO4); - ifp->if_hwassist &= ~(CSUM_TCP | CSUM_UDP - | CSUM_TSO); + ifp->if_hwassist &= ~(CSUM_TCP | CSUM_UDP); } else { ifp->if_capenable |= IFCAP_TXCSUM; ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP); @@ -4144,7 +4228,6 @@ mxge_ioctl(struct ifnet *ifp, u_long command, caddr_t data) if (mask & IFCAP_TSO4) { if (IFCAP_TSO4 & ifp->if_capenable) { ifp->if_capenable &= ~IFCAP_TSO4; - ifp->if_hwassist &= ~CSUM_TSO; } else if (IFCAP_TXCSUM & ifp->if_capenable) { ifp->if_capenable |= IFCAP_TSO4; ifp->if_hwassist |= CSUM_TSO; @@ -4154,6 +4237,43 @@ mxge_ioctl(struct ifnet *ifp, u_long command, caddr_t data) err = EINVAL; } } +#if IFCAP_TSO6 + if (mask & IFCAP_TXCSUM_IPV6) { + if (IFCAP_TXCSUM_IPV6 & ifp->if_capenable) { + ifp->if_capenable &= ~(IFCAP_TXCSUM_IPV6 + | IFCAP_TSO6); + ifp->if_hwassist &= ~(CSUM_TCP_IPV6 + | CSUM_UDP); + } else { + ifp->if_capenable |= IFCAP_TXCSUM_IPV6; + ifp->if_hwassist |= (CSUM_TCP_IPV6 + | CSUM_UDP_IPV6); + } +#ifdef NOTYET + } else if (mask & IFCAP_RXCSUM6) { + if (IFCAP_RXCSUM6 & ifp->if_capenable) { + ifp->if_capenable &= ~IFCAP_RXCSUM6; + sc->csum_flag = 0; + } else { + ifp->if_capenable |= IFCAP_RXCSUM6; + sc->csum_flag = 1; + } +#endif + } + if (mask & IFCAP_TSO6) { + if (IFCAP_TSO6 & ifp->if_capenable) { + ifp->if_capenable &= ~IFCAP_TSO6; + } else if (IFCAP_TXCSUM_IPV6 & ifp->if_capenable) { + ifp->if_capenable |= IFCAP_TSO6; + ifp->if_hwassist |= CSUM_TSO; + } else { + printf("mxge requires tx checksum offload" + " be enabled to use TSO\n"); + err = EINVAL; + } + } +#endif /*IFCAP_TSO6 */ + if (mask & IFCAP_LRO) { if (IFCAP_LRO & ifp->if_capenable) err = mxge_change_lro_locked(sc, 0); @@ -4646,6 +4766,7 @@ mxge_add_irq(mxge_softc_t *sc) static int mxge_attach(device_t dev) { + mxge_cmd_t cmd; mxge_softc_t *sc = device_get_softc(dev); struct ifnet *ifp; int err, rid; @@ -4776,7 +4897,7 @@ mxge_attach(device_t dev) if_initbaudrate(ifp, IF_Gbps(10)); ifp->if_capabilities = IFCAP_RXCSUM | IFCAP_TXCSUM | IFCAP_TSO4 | - IFCAP_VLAN_MTU | IFCAP_LINKSTATE; + IFCAP_VLAN_MTU | IFCAP_LINKSTATE | IFCAP_TXCSUM_IPV6; #ifdef INET ifp->if_capabilities |= IFCAP_LRO; #endif @@ -4789,7 +4910,6 @@ mxge_attach(device_t dev) sc->fw_ver_tiny >= 32) ifp->if_capabilities |= IFCAP_VLAN_HWTSO; #endif - sc->max_mtu = mxge_max_mtu(sc); if (sc->max_mtu >= 9000) ifp->if_capabilities |= IFCAP_JUMBO_MTU; @@ -4798,6 +4918,14 @@ mxge_attach(device_t dev) "latest firmware for 9000 byte jumbo support\n", sc->max_mtu - ETHER_HDR_LEN); ifp->if_hwassist = CSUM_TCP | CSUM_UDP | CSUM_TSO; + ifp->if_hwassist |= CSUM_TCP_IPV6 | CSUM_UDP_IPV6; + /* check to see if f/w supports TSO for IPv6 */ + if (!mxge_send_cmd(sc, MXGEFW_CMD_GET_MAX_TSO6_HDR_SIZE, &cmd)) { + if (CSUM_TCP_IPV6) + ifp->if_capabilities |= IFCAP_TSO6; + sc->max_tso6_hlen = min(cmd.data0, + sizeof (sc->ss[0].scratch)); + } ifp->if_capenable = ifp->if_capabilities; if (sc->lro_cnt == 0) ifp->if_capenable &= ~IFCAP_LRO; diff --git a/sys/dev/mxge/if_mxge_var.h b/sys/dev/mxge/if_mxge_var.h index c85a29bfb58..9393577106f 100644 --- a/sys/dev/mxge/if_mxge_var.h +++ b/sys/dev/mxge/if_mxge_var.h @@ -50,6 +50,19 @@ $FreeBSD$ #define IFNET_BUF_RING 1 #endif +#if (__FreeBSD_version < 1000020) +#undef IF_Kbps +#undef IF_Mbps +#undef IF_Gbps +#define IF_Kbps(x) ((uintmax_t)(x) * 1000) /* kilobits/sec. */ +#define IF_Mbps(x) (IF_Kbps((x) * 1000)) /* megabits/sec. */ +#define IF_Gbps(x) (IF_Mbps((x) * 1000)) /* gigabits/sec. */ +static __inline void +if_initbaudrate(struct ifnet *ifp, uintmax_t baud) +{ + ifp->if_baudrate = baud; +} +#endif #ifndef VLAN_CAPABILITIES #define VLAN_CAPABILITIES(ifp) #define mxge_vlans_active(sc) (sc)->ifp->if_nvlans @@ -73,10 +86,33 @@ $FreeBSD$ #define IFCAP_TSO4 0 #endif +#ifndef IFCAP_TSO6 +#define IFCAP_TSO6 0 +#endif + +#ifndef IFCAP_TXCSUM_IPV6 +#define IFCAP_TXCSUM_IPV6 0 +#endif + +#ifndef IFCAP_RXCSUM_IPV6 +#define IFCAP_RXCSUM_IPV6 0 +#endif + #ifndef CSUM_TSO #define CSUM_TSO 0 #endif +#ifndef CSUM_TCP_IPV6 +#define CSUM_TCP_IPV6 0 +#endif + +#ifndef CSUM_UDP_IPV6 +#define CSUM_UDP_IPV6 0 +#endif + +#ifndef CSUM_DELAY_DATA_IPV6 +#define CSUM_DELAY_DATA_IPV6 0 +#endif typedef struct { void *addr; @@ -270,6 +306,7 @@ struct mxge_softc { int dying; int connector; int current_media; + int max_tso6_hlen; mxge_dma_t dmabench_dma; struct callout co_hdl; struct taskqueue *tq; @@ -312,6 +349,15 @@ struct mxge_media_type char *name; }; +struct mxge_pkt_info { + int ip_off; + int ip_hlen; + struct ip *ip; + struct ip6_hdr *ip6; + struct tcphdr *tcp; +}; + + /* implement our own memory barriers, since bus_space_barrier cannot handle write-combining regions */ diff --git a/sys/modules/mxge/mxge/Makefile b/sys/modules/mxge/mxge/Makefile index c4784625fa7..90c30eb84b8 100644 --- a/sys/modules/mxge/mxge/Makefile +++ b/sys/modules/mxge/mxge/Makefile @@ -3,6 +3,6 @@ .PATH: ${.CURDIR}/../../../dev/mxge KMOD= if_mxge -SRCS= if_mxge.c mxge_lro.c device_if.h bus_if.h pci_if.h opt_inet.h +SRCS= if_mxge.c mxge_lro.c device_if.h bus_if.h pci_if.h opt_inet.h opt_inet6.h .include From c9ad52275536cc08e683ebbfcb958340104e3ff1 Mon Sep 17 00:00:00 2001 From: John-Mark Gurney Date: Tue, 19 Feb 2013 21:35:17 +0000 Subject: [PATCH 0284/1476] add support for AES and PCLMULQDQ instructions to binutils... Thanks to Mike Belopuhov for the pointer to the OpenBSD patch, though OpenBSD's gcc is very different that it only helped w/ where to modify, not how... Thanks to jhb for some early reviews... Reviewed by: imp, kib MFC after: 1 month --- contrib/binutils/gas/config/tc-i386.c | 4 +- contrib/binutils/opcodes/i386-dis.c | 83 +++++++++++++++++++++++---- contrib/binutils/opcodes/i386-opc.h | 6 +- contrib/binutils/opcodes/i386-tbl.h | 48 ++++++++++++++++ 4 files changed, 128 insertions(+), 13 deletions(-) diff --git a/contrib/binutils/gas/config/tc-i386.c b/contrib/binutils/gas/config/tc-i386.c index 9af47c56e9d..5ba2ce29c2b 100644 --- a/contrib/binutils/gas/config/tc-i386.c +++ b/contrib/binutils/gas/config/tc-i386.c @@ -3981,7 +3981,7 @@ output_insn (void) SSE4 instructions have 3 bytes. We may use one more higher byte to specify a prefix the instruction requires. Exclude instructions which are in both SSE4 and ABM. */ - if ((i.tm.cpu_flags & (CpuSSSE3 | CpuSSE4)) != 0 + if ((i.tm.cpu_flags & (CpuSSSE3 | CpuSSE4 | CpuAES | CpuPCLMUL)) != 0 && (i.tm.cpu_flags & CpuABM) == 0) { if (i.tm.base_opcode & 0xff000000) @@ -4033,7 +4033,7 @@ output_insn (void) } else { - if ((i.tm.cpu_flags & (CpuSSSE3 | CpuSSE4)) != 0 + if ((i.tm.cpu_flags & (CpuSSSE3 | CpuSSE4 | CpuAES | CpuPCLMUL)) != 0 && (i.tm.cpu_flags & CpuABM) == 0) { p = frag_more (3); diff --git a/contrib/binutils/opcodes/i386-dis.c b/contrib/binutils/opcodes/i386-dis.c index 62581b5e6a2..6ef04348d76 100644 --- a/contrib/binutils/opcodes/i386-dis.c +++ b/contrib/binutils/opcodes/i386-dis.c @@ -543,6 +543,13 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr) #define PREGRP97 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 97 } } #define PREGRP98 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 98 } } #define PREGRP99 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 99 } } +#define PREGRP100 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 100 } } +#define PREGRP101 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 101 } } +#define PREGRP102 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 102 } } +#define PREGRP103 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 103 } } +#define PREGRP104 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 104 } } +#define PREGRP105 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 105 } } +#define PREGRP106 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 106 } } #define X86_64_0 NULL, { { NULL, X86_64_SPECIAL }, { NULL, 0 } } @@ -1319,7 +1326,7 @@ static const unsigned char threebyte_0x38_uses_DATA_prefix[256] = { /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */ /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */ /* c0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */ - /* d0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* df */ + /* d0 */ 0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1, /* df */ /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ef */ /* f0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */ /* ------------------------------- */ @@ -1382,7 +1389,7 @@ static const unsigned char threebyte_0x3a_uses_DATA_prefix[256] = { /* 10 */ 0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0, /* 1f */ /* 20 */ 1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 2f */ /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */ - /* 40 */ 1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */ + /* 40 */ 1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0, /* 4f */ /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 5f */ /* 60 */ 1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0, /* 6f */ /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 7f */ @@ -1391,7 +1398,7 @@ static const unsigned char threebyte_0x3a_uses_DATA_prefix[256] = { /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */ /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */ /* c0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */ - /* d0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* df */ + /* d0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, /* df */ /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ef */ /* f0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */ /* ------------------------------- */ @@ -2605,6 +2612,62 @@ static const struct dis386 prefix_user_table[][4] = { { "invvpid",{ Gm, Mo } }, { "(bad)", { XX } }, }, + + /* PREGRP100 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "aesimc", { XM, EXx } }, + { "(bad)", { XX } }, + }, + + /* PREGRP101 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "aesenc",{ XM, EXx } }, + { "(bad)", { XX } }, + }, + + /* PREGRP102 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "aesenclast", { XM, EXx } }, + { "(bad)", { XX } }, + }, + + /* PREGRP103 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "aesdec", { XM, EXx } }, + { "(bad)", { XX } }, + }, + + /* PREGRP104 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "aesdeclast", { XM, EXx } }, + { "(bad)", { XX } }, + }, + + /* PREGRP105 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "aeskeygenassist", { XM, EXx, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP106 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pclmulqdq", { XM, EXx, Ib } }, + { "(bad)", { XX } }, + }, }; static const struct dis386 x86_64_table[][2] = { @@ -2876,11 +2939,11 @@ static const struct dis386 three_byte_table[][256] = { { "(bad)", { XX } }, { "(bad)", { XX } }, { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, + { PREGRP100 }, + { PREGRP101 }, + { PREGRP102 }, + { PREGRP103 }, + { PREGRP104 }, /* e0 */ { "(bad)", { XX } }, { "(bad)", { XX } }, @@ -2997,7 +3060,7 @@ static const struct dis386 three_byte_table[][256] = { { PREGRP84 }, { PREGRP85 }, { "(bad)", { XX } }, - { "(bad)", { XX } }, + { PREGRP106 }, { "(bad)", { XX } }, { "(bad)", { XX } }, { "(bad)", { XX } }, @@ -3171,7 +3234,7 @@ static const struct dis386 three_byte_table[][256] = { { "(bad)", { XX } }, { "(bad)", { XX } }, { "(bad)", { XX } }, - { "(bad)", { XX } }, + { PREGRP105 }, /* e0 */ { "(bad)", { XX } }, { "(bad)", { XX } }, diff --git a/contrib/binutils/opcodes/i386-opc.h b/contrib/binutils/opcodes/i386-opc.h index 7605b521f8a..45589d8b355 100644 --- a/contrib/binutils/opcodes/i386-opc.h +++ b/contrib/binutils/opcodes/i386-opc.h @@ -72,6 +72,8 @@ typedef struct template #define CpuSSE4_1 0x400000 /* SSE4.1 Instructions required */ #define CpuSSE4_2 0x800000 /* SSE4.2 Instructions required */ #define CpuXSAVE 0x1000000 /* XSAVE Instructions required */ +#define CpuAES 0x2000000 /* AES Instructions required */ +#define CpuPCLMUL 0x4000000 /* Carry-less Multiplication extensions */ /* SSE4.1/4.2 Instructions required */ #define CpuSSE4 (CpuSSE4_1|CpuSSE4_2) @@ -84,7 +86,7 @@ typedef struct template #define CpuUnknownFlags (Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686 \ |CpuP4|CpuSledgehammer|CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuVMX \ |Cpu3dnow|Cpu3dnowA|CpuK6|CpuPadLock|CpuSVME|CpuSSSE3|CpuSSE4_1 \ - |CpuSSE4_2|CpuABM|CpuSSE4a|CpuXSAVE) + |CpuSSE4_2|CpuABM|CpuSSE4a|CpuXSAVE|CpuAES|CpuPCLMUL) /* the bits in opcode_modifier are used to generate the final opcode from the base_opcode. These bits also are used to detect alternate forms of @@ -126,6 +128,8 @@ typedef struct template #define Rex64 0x10000000 /* instruction require Rex64 prefix. */ #define Ugh 0x20000000 /* deprecated fp insn, gets a warning */ +#define NoSuf (No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_xSuf) + /* operand_types[i] describes the type of operand i. This is made by OR'ing together all of the possible type masks. (e.g. 'operand_types[i] = Reg|Imm' specifies that operand i can be diff --git a/contrib/binutils/opcodes/i386-tbl.h b/contrib/binutils/opcodes/i386-tbl.h index 453cb2daef8..4ee72a4806b 100644 --- a/contrib/binutils/opcodes/i386-tbl.h +++ b/contrib/binutils/opcodes/i386-tbl.h @@ -4319,6 +4319,54 @@ const template i386_optab[] = { "xrstor", 1, 0xfae, 0x5, CpuXSAVE, Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_xSuf, { BaseIndex|Disp8|Disp16|Disp32|Disp32S } }, + /* Intel AES extensions */ + {"aesdec", 2, 0x660f38de, None, CpuAES, + Modrm|IgnoreSize|NoSuf, + { RegXMM|LLongMem, + RegXMM } }, + {"aesdeclast", 2, 0x660f38df, None, CpuAES, + Modrm|IgnoreSize|NoSuf, + { RegXMM|LLongMem, + RegXMM } }, + {"aesenc", 2, 0x660f38dc, None, CpuAES, + Modrm|IgnoreSize|NoSuf, + { RegXMM|LLongMem, + RegXMM } }, + {"aesenclast", 2, 0x660f38dd, None, CpuAES, + Modrm|IgnoreSize|NoSuf, + { RegXMM|LLongMem, + RegXMM } }, + {"aesimc", 2, 0x660f38db, None, CpuAES, + Modrm|IgnoreSize|NoSuf, + { RegXMM|LLongMem, + RegXMM } }, + {"aeskeygenassist", 3, 0x660f3adf, None, CpuAES, + Modrm|IgnoreSize|NoSuf, + { Imm8, RegXMM|LLongMem, + RegXMM } }, + + /* Intel Carry-less Multiplication extensions */ + {"pclmulqdq", 3, 0x660f3a44, None, CpuPCLMUL, + Modrm|IgnoreSize|NoSuf, + { Imm8, RegXMM|LLongMem, + RegXMM } }, + {"pclmullqlqdq", 2, 0x660f3a44, 0x0, CpuPCLMUL, + Modrm|IgnoreSize|NoSuf|ImmExt, + { RegXMM|LLongMem, + RegXMM } }, + {"pclmulhqlqdq", 2, 0x660f3a44, 0x1, CpuPCLMUL, + Modrm|IgnoreSize|NoSuf|ImmExt, + { RegXMM|LLongMem, + RegXMM } }, + {"pclmullqhqdq", 2, 0x660f3a44, 0x10, CpuPCLMUL, + Modrm|IgnoreSize|NoSuf|ImmExt, + { RegXMM|LLongMem, + RegXMM } }, + {"pclmulhqhqdq", 2, 0x660f3a44, 0x11, CpuPCLMUL, + Modrm|IgnoreSize|NoSuf|ImmExt, + { RegXMM|LLongMem, + RegXMM } }, + { NULL, 0, 0, 0, 0, 0, { 0 } } }; From e9e92235467d694725623203b47a787bacc2d679 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Tue, 19 Feb 2013 23:46:51 +0000 Subject: [PATCH 0285/1476] sh: Fix a crash with the stackmark code. If a stack mark is set while the current stack block is empty, the stack block may move later on (because of realloc()) and the stack mark needs to be updated. This updating does not happen after popstackmark() has been called; therefore, call setstackmark() again if the stack mark is still being used. For some reason, this only affects a few users. I cannot reproduce it. The situation seems quite rare as well because an empty stack block would usually be freed (by popstackmark()) before execution reaches a setstackmark() call. PR: 175922 Tested by: KT Sin --- bin/sh/eval.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bin/sh/eval.c b/bin/sh/eval.c index 66ae40e5167..b40fffde85a 100644 --- a/bin/sh/eval.c +++ b/bin/sh/eval.c @@ -174,6 +174,7 @@ evalstring(char *s, int flags) any = 1; } popstackmark(&smark); + setstackmark(&smark); } popfile(); popstackmark(&smark); @@ -296,6 +297,7 @@ evaltree(union node *n, int flags) } n = next; popstackmark(&smark); + setstackmark(&smark); } while (n != NULL); out: popstackmark(&smark); From 8ce3e01e09403c2f34b7fd373a301e0f2eaa1504 Mon Sep 17 00:00:00 2001 From: Giorgos Keramidas Date: Tue, 19 Feb 2013 23:57:39 +0000 Subject: [PATCH 0286/1476] Add a sample program that shows how a custom comparison function and qsort(3) can work together to sort an array of integers. PR: docs/176197 Submitted by: Fernando, fapesteguia at opensistemas.com Approved by: gjb (mentor) MFC after: 1 week --- lib/libc/stdlib/qsort.3 | 48 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/lib/libc/stdlib/qsort.3 b/lib/libc/stdlib/qsort.3 index 0f7ef733447..83d914021d6 100644 --- a/lib/libc/stdlib/qsort.3 +++ b/lib/libc/stdlib/qsort.3 @@ -32,7 +32,7 @@ .\" @(#)qsort.3 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" -.Dd September 30, 2003 +.Dd February 20, 2013 .Dt QSORT 3 .Os .Sh NAME @@ -211,6 +211,52 @@ Previous versions of did not permit the comparison routine itself to call .Fn qsort 3 . This is no longer true. +.Sh EXAMPLES +A sample program that sorts an array of +.Vt int +values in place using +.Fn qsort , +and then prints the sorted array to standard output is: +.Bd -literal +#include +#include +#include + +/* + * Custom comparison function that can compare 'int' values through pointers + * passed by qsort(3). + */ +static int +int_compare(const void *p1, const void *p2) +{ + int *left = (int *)p1; + int *right = (int *)p2; + + if (*left < *right) + return (-1); + else if (*left > *right) + return (1); + else + return (0); +} + +/* + * Sort an array of 'int' values and print it to standard output. + */ +int +main(void) +{ + int int_array[] = { 4, 5, 9, 3, 0, 1, 7, 2, 8, 6 }; + const int array_size = sizeof(int_array) / sizeof(int_array[0]); + int k; + + qsort(&int_array, array_size, sizeof(int), int_compare); + for (k = 0; k < array_size; k++) + printf(" %d", int_array[k]); + printf("\\n"); + exit(EXIT_SUCCESS); +} +.Ed .Sh ERRORS The .Fn heapsort From 158cb431db62c70bb7acec539a05b2b229b47b7a Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Wed, 20 Feb 2013 11:14:55 +0000 Subject: [PATCH 0287/1476] CFG_ERR, DATA_UNDERRUN and DELIM_UNDERRUN are all flags, rather than part of ts_status. Thus: * make sure we decode them from ts_flags, rather than ts_status; * make sure we decode them regardless of whether there's an error or not. This correctly exposes descriptor configuration errors, TX delimiter underruns and TX data underruns. --- sys/dev/ath/if_ath.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index b6b42172694..1e796a01b4d 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -3581,17 +3581,24 @@ ath_tx_update_stats(struct ath_softc *sc, struct ath_tx_status *ts, if (ts->ts_status & HAL_TXERR_TIMER_EXPIRED) sc->sc_stats.ast_tx_timerexpired++; - if (ts->ts_status & HAL_TX_DATA_UNDERRUN) - sc->sc_stats.ast_tx_data_underrun++; - if (ts->ts_status & HAL_TX_DELIM_UNDERRUN) - sc->sc_stats.ast_tx_delim_underrun++; - if (bf->bf_m->m_flags & M_FF) sc->sc_stats.ast_ff_txerr++; } /* XXX when is this valid? */ - if (ts->ts_status & HAL_TX_DESC_CFG_ERR) + if (ts->ts_flags & HAL_TX_DESC_CFG_ERR) sc->sc_stats.ast_tx_desccfgerr++; + /* + * This can be valid for successful frame transmission! + * If there's a TX FIFO underrun during aggregate transmission, + * the MAC will pad the rest of the aggregate with delimiters. + * If a BA is returned, the frame is marked as "OK" and it's up + * to the TX completion code to notice which frames weren't + * successfully transmitted. + */ + if (ts->ts_flags & HAL_TX_DATA_UNDERRUN) + sc->sc_stats.ast_tx_data_underrun++; + if (ts->ts_flags & HAL_TX_DELIM_UNDERRUN) + sc->sc_stats.ast_tx_delim_underrun++; sr = ts->ts_shortretry; lr = ts->ts_longretry; From a26f33276f54275acc44fb5a9ee3cc4cc67826a9 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Wed, 20 Feb 2013 11:17:03 +0000 Subject: [PATCH 0288/1476] Post interrupts in the ath alq trace. --- sys/dev/ath/if_ath.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 1e796a01b4d..23664f11410 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -1588,6 +1588,10 @@ ath_intr(void *arg) ath_hal_getisr(ah, &status); /* NB: clears ISR too */ DPRINTF(sc, ATH_DEBUG_INTR, "%s: status 0x%x\n", __func__, status); ATH_KTR(sc, ATH_KTR_INTERRUPTS, 1, "ath_intr: mask=0x%.8x", status); +#ifdef ATH_DEBUG_ALQ + if_ath_alq_post_intr(&sc->sc_alq, status, ah->ah_intrstate, + ah->ah_syncstate); +#endif /* ATH_DEBUG_ALQ */ #ifdef ATH_KTR_INTR_DEBUG ATH_KTR(sc, ATH_KTR_INTERRUPTS, 5, "ath_intr: ISR=0x%.8x, ISR_S0=0x%.8x, ISR_S1=0x%.8x, ISR_S2=0x%.8x, ISR_S5=0x%.8x", From bab336db2765cf356f3a68754d7c6508b6d32554 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Wed, 20 Feb 2013 11:17:29 +0000 Subject: [PATCH 0289/1476] oops, tab! --- sys/dev/ath/if_ath.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 23664f11410..fdd91118b7c 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -1591,7 +1591,7 @@ ath_intr(void *arg) #ifdef ATH_DEBUG_ALQ if_ath_alq_post_intr(&sc->sc_alq, status, ah->ah_intrstate, ah->ah_syncstate); -#endif /* ATH_DEBUG_ALQ */ +#endif /* ATH_DEBUG_ALQ */ #ifdef ATH_KTR_INTR_DEBUG ATH_KTR(sc, ATH_KTR_INTERRUPTS, 5, "ath_intr: ISR=0x%.8x, ISR_S0=0x%.8x, ISR_S1=0x%.8x, ISR_S2=0x%.8x, ISR_S5=0x%.8x", From 69930f8794462c175e69a5ca1af7afb337f4ea9d Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Wed, 20 Feb 2013 11:20:51 +0000 Subject: [PATCH 0290/1476] Enable TX FIFO underrun interrupts. This allows the TX FIFO threshold adjustment code to now run. Tested: * AR5416, STA TODO: * Much more thorough testing on the other chips, AR5210 -> AR9287 --- sys/dev/ath/if_ath.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index fdd91118b7c..6f08fa79b81 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -1983,6 +1983,7 @@ ath_init(void *arg) */ sc->sc_imask = HAL_INT_RX | HAL_INT_TX | HAL_INT_RXEOL | HAL_INT_RXORN + | HAL_INT_TXURN | HAL_INT_FATAL | HAL_INT_GLOBAL; /* From f274e91f675a82f166234fad28ca7dbaa1d2d8eb Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Wed, 20 Feb 2013 11:22:44 +0000 Subject: [PATCH 0291/1476] A couple of quick tidyups: * Delete this debugging print - I used it when debugging the initial TX descriptor chaining code. It now works, so let's toss it. It just confuses people if they enable TX descriptor debugging as they get two slightly different versions of the same descriptor. * Indenting. --- sys/dev/ath/if_ath_tx.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/sys/dev/ath/if_ath_tx.c b/sys/dev/ath/if_ath_tx.c index 64c43788acd..f3ce0e754dc 100644 --- a/sys/dev/ath/if_ath_tx.c +++ b/sys/dev/ath/if_ath_tx.c @@ -473,11 +473,6 @@ ath_tx_chaindesclist(struct ath_softc *sc, struct ath_desc *ds0, bf->bf_state.bfs_ndelim); } isFirstDesc = 0; -#ifdef ATH_DEBUG - if (sc->sc_debug & ATH_DEBUG_XMIT) - ath_printtxbuf(sc, bf, bf->bf_state.bfs_tx_queue, - 0, 0); -#endif bf->bf_lastds = (struct ath_desc *) ds; /* @@ -3154,7 +3149,7 @@ ath_tx_tid_filt_comp_aggr(struct ath_softc *sc, struct ath_tid *tid, * Don't allow a filtered frame to live forever. */ if (bf->bf_state.bfs_retries > SWMAX_RETRIES) { - sc->sc_stats.ast_tx_swretrymax++; + sc->sc_stats.ast_tx_swretrymax++; DPRINTF(sc, ATH_DEBUG_SW_TX_FILT, "%s: bf=%p, seqno=%d, exceeded retries\n", __func__, From 71d6fe723e2f1c42dc93aece38ae201057ce2b21 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Wed, 20 Feb 2013 11:24:11 +0000 Subject: [PATCH 0292/1476] If any of the TX queues have underrun reporting enabled, enable HAL_INT_TXURN in the interrupt mask register. This should now allow for TXURN interrupts to be posted. --- sys/dev/ath/ath_hal/ar5416/ar5416_interrupts.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_interrupts.c b/sys/dev/ath/ath_hal/ar5416/ar5416_interrupts.c index 29aed1fc561..631ca2fca2e 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_interrupts.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_interrupts.c @@ -307,6 +307,8 @@ ar5416SetInterrupts(struct ath_hal *ah, HAL_INT ints) mask |= AR_IMR_TXDESC; if (ahp->ah_txEolInterruptMask) mask |= AR_IMR_TXEOL; + if (ahp->ah_txUrnInterruptMask) + mask |= AR_IMR_TXURN; } if (ints & (HAL_INT_BMISC)) { mask |= AR_IMR_BCNMISC; From d7cc11edcecebe23521a58a772a2bfedfc627e67 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Wed, 20 Feb 2013 12:14:49 +0000 Subject: [PATCH 0293/1476] Configure larger TX FIFO default and maximum level values. This has reduced the number of TX delimiter and data underruns when doing large UDP transfers (>100mbit). This stops any HAL_INT_TXURN interrupts from occuring, which is a good sign! Obtained from: Qualcomm Atheros --- sys/dev/ath/ath_hal/ar5416/ar5416_attach.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c b/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c index d165540ece2..30d1161a546 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c @@ -241,8 +241,24 @@ ar5416InitState(struct ath_hal_5416 *ahp5416, uint16_t devid, HAL_SOFTC sc, /* Enable all ANI functions to begin with */ AH5416(ah)->ah_ani_function = 0xffffffff; - /* Set overridable ANI methods */ - AH5212(ah)->ah_aniControl = ar5416AniControl; + /* Set overridable ANI methods */ + AH5212(ah)->ah_aniControl = ar5416AniControl; + + /* Default FIFO Trigger levels */ +#define AR_FTRIG_512B 0x00000080 // 5 bits total + /* AR9285/AR9271 need to use half the TX FIFOs */ + if (AR_SREV_KITE(ah) || AR_SREV_9271(ah)) { + AH5212(ah)->ah_txTrigLev = (AR_FTRIG_256B >> AR_FTRIG_S); + AH5212(ah)->ah_maxTxTrigLev = ((2048 / 64) - 1); + } else { + AH5212(ah)->ah_txTrigLev = (AR_FTRIG_512B >> AR_FTRIG_S); + AH5212(ah)->ah_maxTxTrigLev = ((4096 / 64) - 1); + } + ath_hal_printf(ah, "%s: trigLev=%d, maxTxTrigLev=%d\n", + __func__, + AH5212(ah)->ah_txTrigLev, + AH5212(ah)->ah_maxTxTrigLev); +#undef AR_FTRIG_512B } uint32_t From dcdc127b07a5f565b407bf510a98f4bfaa1071b1 Mon Sep 17 00:00:00 2001 From: Sergey Kandaurov Date: Wed, 20 Feb 2013 12:40:26 +0000 Subject: [PATCH 0294/1476] Check if the -sec option is given without an argument. PR: bin/170413 Submitted by: Andrey Simonenko MFC after: 1 week --- usr.sbin/mountd/mountd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr.sbin/mountd/mountd.c b/usr.sbin/mountd/mountd.c index bc290d6d9cf..19134104ed8 100644 --- a/usr.sbin/mountd/mountd.c +++ b/usr.sbin/mountd/mountd.c @@ -2235,7 +2235,7 @@ do_opt(char **cpp, char **endcpp, struct exportlist *ep, struct grouplist *grp, ep->ex_indexfile = strdup(cpoptarg); } else if (!strcmp(cpopt, "quiet")) { opt_flags |= OP_QUIET; - } else if (!strcmp(cpopt, "sec")) { + } else if (cpoptarg && !strcmp(cpopt, "sec")) { if (parsesec(cpoptarg, ep)) return (1); opt_flags |= OP_SEC; From c9263bd2883b9f4d6a52af01ee14119521230cd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Wed, 20 Feb 2013 12:59:21 +0000 Subject: [PATCH 0295/1476] Reduce excessive nesting. --- sys/dev/ixgbe/ixgbe_phy.c | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/sys/dev/ixgbe/ixgbe_phy.c b/sys/dev/ixgbe/ixgbe_phy.c index 3f262f9b3b2..4a1e3a12197 100644 --- a/sys/dev/ixgbe/ixgbe_phy.c +++ b/sys/dev/ixgbe/ixgbe_phy.c @@ -1194,25 +1194,23 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) /* Make sure we're a supported PHY type */ if (hw->phy.type == ixgbe_phy_sfp_intel) { status = IXGBE_SUCCESS; + } else if (hw->allow_unsupported_sfp == TRUE) { + EWARN(hw, "WARNING: Intel (R) Network " + "Connections are quality tested " + "using Intel (R) Ethernet Optics." + " Using untested modules is not " + "supported and may cause unstable" + " operation or damage to the " + "module or the adapter. Intel " + "Corporation is not responsible " + "for any harm caused by using " + "untested modules.\n", status); + status = IXGBE_SUCCESS; } else { - if (hw->allow_unsupported_sfp == TRUE) { - EWARN(hw, "WARNING: Intel (R) Network " - "Connections are quality tested " - "using Intel (R) Ethernet Optics." - " Using untested modules is not " - "supported and may cause unstable" - " operation or damage to the " - "module or the adapter. Intel " - "Corporation is not responsible " - "for any harm caused by using " - "untested modules.\n", status); - status = IXGBE_SUCCESS; - } else { - DEBUGOUT("SFP+ module not supported\n"); - hw->phy.type = - ixgbe_phy_sfp_unsupported; - status = IXGBE_ERR_SFP_NOT_SUPPORTED; - } + DEBUGOUT("SFP+ module not supported\n"); + hw->phy.type = + ixgbe_phy_sfp_unsupported; + status = IXGBE_ERR_SFP_NOT_SUPPORTED; } } else { status = IXGBE_SUCCESS; From b0214723994c4a515e72f6b17da068aa2bfda20a Mon Sep 17 00:00:00 2001 From: "Alexander V. Chernikov" Date: Wed, 20 Feb 2013 13:47:05 +0000 Subject: [PATCH 0296/1476] Add interface name filtering via 'match' cmd. Add 'pps' cmd for switching beetween interface packets/bytes statistics. Submitted by: vsevolod MFC after: 2 weeks --- usr.bin/systat/ifcmds.c | 28 +++++++- usr.bin/systat/ifstat.c | 137 +++++++++++++++++++++++++++++++++------- usr.bin/systat/systat.1 | 22 +++++++ 3 files changed, 162 insertions(+), 25 deletions(-) diff --git a/usr.bin/systat/ifcmds.c b/usr.bin/systat/ifcmds.c index 0c03e595bf3..6e6f1d27343 100644 --- a/usr.bin/systat/ifcmds.c +++ b/usr.bin/systat/ifcmds.c @@ -28,11 +28,19 @@ * $FreeBSD$ */ +#include + #include "systat.h" #include "extern.h" #include "convtbl.h" +#include +#include + int curscale = SC_AUTO; +char *matchline = NULL; +int showpps = 0; +int needsort = 0; int ifcmd(const char *cmd, const char *args) @@ -48,6 +56,24 @@ ifcmd(const char *cmd, const char *args) addstr("what scale? "); addstr(get_helplist()); } - } + } else if (prefix(cmd, "match")) { + if (args != NULL && *args != '\0' && memcmp(args, "*", 2) != 0) { + /* We got a valid match line */ + if (matchline != NULL) { + free(matchline); + } + needsort = 1; + matchline = strdup(args); + } else { + /* Empty or * pattern, turn filtering off */ + if (matchline != NULL) { + free(matchline); + } + needsort = 1; + matchline = NULL; + } + } else if (prefix(cmd, "pps")) + showpps = !showpps; + return (1); } diff --git a/usr.bin/systat/ifstat.c b/usr.bin/systat/ifstat.c index 3e4549921c0..6bf588c3ab0 100644 --- a/usr.bin/systat/ifstat.c +++ b/usr.bin/systat/ifstat.c @@ -38,6 +38,7 @@ #include #include #include +#include #include "systat.h" #include "extern.h" @@ -71,12 +72,22 @@ struct if_stat { u_long if_out_curtraffic; u_long if_in_traffic_peak; u_long if_out_traffic_peak; + u_long if_in_curpps; + u_long if_out_curpps; + u_long if_in_pps_peak; + u_long if_out_pps_peak; u_int if_row; /* Index into ifmib sysctl */ u_int if_ypos; /* 0 if not being displayed */ u_int display; + u_int match; }; -extern u_int curscale; +extern int curscale; +extern char *matchline; +extern int showpps; +extern int needsort; + +static int needclear = 0; static void right_align_string(struct if_stat *); static void getifmibdata(const int, struct ifmibdata *); @@ -96,34 +107,48 @@ static u_int getifnum(void); #define STARTING_ROW (TOPLINE + 1) #define ROW_SPACING (3) -#define CLEAR_LINE(y, x) do { \ - wmove(wnd, y, x); \ - wclrtoeol(wnd); \ -} while (0) - -#define IN_col2 (ifp->if_in_curtraffic) -#define OUT_col2 (ifp->if_out_curtraffic) -#define IN_col3 (ifp->if_in_traffic_peak) -#define OUT_col3 (ifp->if_out_traffic_peak) -#define IN_col4 (ifp->if_mib.ifmd_data.ifi_ibytes) -#define OUT_col4 (ifp->if_mib.ifmd_data.ifi_obytes) +#define IN_col2 (showpps ? ifp->if_in_curpps : ifp->if_in_curtraffic) +#define OUT_col2 (showpps ? ifp->if_out_curpps : ifp->if_out_curtraffic) +#define IN_col3 (showpps ? \ + ifp->if_in_pps_peak : ifp->if_in_traffic_peak) +#define OUT_col3 (showpps ? \ + ifp->if_out_pps_peak : ifp->if_out_traffic_peak) +#define IN_col4 (showpps ? \ + ifp->if_mib.ifmd_data.ifi_ipackets : ifp->if_mib.ifmd_data.ifi_ibytes) +#define OUT_col4 (showpps ? \ + ifp->if_mib.ifmd_data.ifi_opackets : ifp->if_mib.ifmd_data.ifi_obytes) #define EMPTY_COLUMN " " #define CLEAR_COLUMN(y, x) mvprintw((y), (x), "%20s", EMPTY_COLUMN); #define DOPUTRATE(c, r, d) do { \ CLEAR_COLUMN(r, c); \ - mvprintw(r, (c), "%10.3f %s%s ", \ - convert(d##_##c, curscale), \ - get_string(d##_##c, curscale), \ - "/s"); \ + if (showpps) { \ + mvprintw(r, (c), "%10.3f %cp%s ", \ + convert(d##_##c, curscale), \ + *get_string(d##_##c, curscale), \ + "/s"); \ + } \ + else { \ + mvprintw(r, (c), "%10.3f %s%s ", \ + convert(d##_##c, curscale), \ + get_string(d##_##c, curscale), \ + "/s"); \ + } \ } while (0) #define DOPUTTOTAL(c, r, d) do { \ CLEAR_COLUMN((r), (c)); \ - mvprintw((r), (c), "%12.3f %s ", \ - convert(d##_##c, SC_AUTO), \ - get_string(d##_##c, SC_AUTO)); \ + if (showpps) { \ + mvprintw((r), (c), "%12.3f %cp ", \ + convert(d##_##c, SC_AUTO), \ + *get_string(d##_##c, SC_AUTO)); \ + } \ + else { \ + mvprintw((r), (c), "%12.3f %s ", \ + convert(d##_##c, SC_AUTO), \ + get_string(d##_##c, SC_AUTO)); \ + } \ } while (0) #define PUTRATE(c, r) do { \ @@ -183,8 +208,10 @@ void showifstat(void) { struct if_stat *ifp = NULL; + SLIST_FOREACH(ifp, &curlist, link) { - if (ifp->display == 0) + if (ifp->display == 0 || (ifp->match == 0) || + ifp->if_ypos > LINES - 3 - 1) continue; PUTNAME(ifp); PUTRATE(col2, ifp->if_ypos); @@ -215,6 +242,7 @@ initifstat(void) p->if_row = i+1; getifmibdata(p->if_row, &p->if_mib); right_align_string(p); + p->match = 1; /* * Initially, we only display interfaces that have @@ -236,7 +264,7 @@ fetchifstat(void) struct timeval tv, new_tv, old_tv; double elapsed = 0.0; u_int new_inb, new_outb, old_inb, old_outb = 0; - u_int we_need_to_sort_interface_list = 0; + u_int new_inp, new_outp, old_inp, old_outp = 0; SLIST_FOREACH(ifp, &curlist, link) { /* @@ -245,6 +273,8 @@ fetchifstat(void) */ old_inb = ifp->if_mib.ifmd_data.ifi_ibytes; old_outb = ifp->if_mib.ifmd_data.ifi_obytes; + old_inp = ifp->if_mib.ifmd_data.ifi_ipackets; + old_outp = ifp->if_mib.ifmd_data.ifi_opackets; ifp->tv_lastchanged = ifp->if_mib.ifmd_data.ifi_lastchange; (void)gettimeofday(&new_tv, NULL); @@ -252,11 +282,13 @@ fetchifstat(void) new_inb = ifp->if_mib.ifmd_data.ifi_ibytes; new_outb = ifp->if_mib.ifmd_data.ifi_obytes; + new_inp = ifp->if_mib.ifmd_data.ifi_ipackets; + new_outp = ifp->if_mib.ifmd_data.ifi_opackets; /* Display interface if it's received some traffic. */ if (new_inb > 0 && old_inb == 0) { ifp->display = 1; - we_need_to_sort_interface_list++; + needsort = 1; } /* @@ -271,6 +303,9 @@ fetchifstat(void) ifp->if_in_curtraffic = new_inb - old_inb; ifp->if_out_curtraffic = new_outb - old_outb; + ifp->if_in_curpps = new_inp - old_inp; + ifp->if_out_curpps = new_outp - old_outp; + /* * Rather than divide by the time specified on the comm- * and line, we divide by ``elapsed'' as this is likely @@ -278,6 +313,8 @@ fetchifstat(void) */ ifp->if_in_curtraffic /= elapsed; ifp->if_out_curtraffic /= elapsed; + ifp->if_in_curpps /= elapsed; + ifp->if_out_curpps /= elapsed; if (ifp->if_in_curtraffic > ifp->if_in_traffic_peak) ifp->if_in_traffic_peak = ifp->if_in_curtraffic; @@ -285,12 +322,18 @@ fetchifstat(void) if (ifp->if_out_curtraffic > ifp->if_out_traffic_peak) ifp->if_out_traffic_peak = ifp->if_out_curtraffic; + if (ifp->if_in_curpps > ifp->if_in_pps_peak) + ifp->if_in_pps_peak = ifp->if_in_curpps; + + if (ifp->if_out_curpps > ifp->if_out_pps_peak) + ifp->if_out_pps_peak = ifp->if_out_curpps; + ifp->tv.tv_sec = new_tv.tv_sec; ifp->tv.tv_usec = new_tv.tv_usec; } - if (we_need_to_sort_interface_list) + if (needsort) sort_interface_list(); return; @@ -323,6 +366,40 @@ right_align_string(struct if_stat *ifp) return; } +static int +check_match(const char *ifname) +{ + char *p = matchline, *c, t; + int match = 0, mlen; + + if (matchline == NULL) { + return 0; + } + /* Strip leading whitespaces */ + while (*p == ' ') + p ++; + + c = p; + while ((mlen = strcspn(c, " ;,")) != 0) { + p = c + mlen; + t = *p; + if (p - c > 0) { + *p = '\0'; + if (fnmatch(c, ifname, FNM_CASEFOLD) == 0) { + *p = t; + return 1; + } + *p = t; + c = p + strspn(p, " ;,"); + } + else { + c = p + strspn(p, " ;,"); + } + } + + return match; +} + /* * This function iterates through our list of interfaces, identifying * those that are to be displayed (ifp->display = 1). For each interf- @@ -340,11 +417,18 @@ sort_interface_list(void) y = STARTING_ROW; SLIST_FOREACH(ifp, &curlist, link) { - if (ifp->display) { + if (matchline && !check_match(ifp->if_mib.ifmd_name)) + ifp->match = 0; + else + ifp->match = 1; + if (ifp->display && ifp->match) { ifp->if_ypos = y; y += ROW_SPACING; } } + + needsort = 0; + needclear = 1; } static @@ -394,6 +478,11 @@ cmdifstat(const char *cmd, const char *args) if (retval == 1) { showifstat(); refresh(); + if (needclear) { + werase(wnd); + labelifstat(); + needclear = 0; + } } return retval; diff --git a/usr.bin/systat/systat.1 b/usr.bin/systat/systat.1 index 1b142092270..7637673c435 100644 --- a/usr.bin/systat/systat.1 +++ b/usr.bin/systat/systat.1 @@ -511,6 +511,28 @@ Modify the scale used to display the current and peak traffic over all interfaces. The following units are recognised: kbit, kbyte, mbit, mbyte, gbit, gbyte and auto. +.It Cm pps +Show statistics in packets per second instead of bytes/bits per second. +A subsequent call of +.Ic pps +switches this mode off. +.It Cm match Op Ar patterns +Display only interfaces that match pattern provided as an argument. +Patterns should be in shell syntax separated by whitespaces or commas. +If this command is called without arguments then all interfaces are displayed. +For example: +.Pp +.Dl match em0, bge1 +.Pp +This will display em0 and bge1 interfaces. +.Pp +.Dl match em*, bge*, lo0 +.Pp +This will display all +.Ic em +interfaces, all +.Ic bge +interfaces and the loopback interface. .El .El .Pp From 297c1ec1248b127230cb3eef2be3692102ca7c88 Mon Sep 17 00:00:00 2001 From: "Alexander V. Chernikov" Date: Wed, 20 Feb 2013 14:19:09 +0000 Subject: [PATCH 0297/1476] Fix several new & old style issues. Pointed by: ae, pluknet, zont MFC with: r247036 --- usr.bin/systat/ifcmds.c | 6 ++---- usr.bin/systat/ifstat.c | 18 +++++++++--------- usr.bin/systat/systat.1 | 2 +- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/usr.bin/systat/ifcmds.c b/usr.bin/systat/ifcmds.c index 6e6f1d27343..101c93991cc 100644 --- a/usr.bin/systat/ifcmds.c +++ b/usr.bin/systat/ifcmds.c @@ -59,16 +59,14 @@ ifcmd(const char *cmd, const char *args) } else if (prefix(cmd, "match")) { if (args != NULL && *args != '\0' && memcmp(args, "*", 2) != 0) { /* We got a valid match line */ - if (matchline != NULL) { + if (matchline != NULL) free(matchline); - } needsort = 1; matchline = strdup(args); } else { /* Empty or * pattern, turn filtering off */ - if (matchline != NULL) { + if (matchline != NULL) free(matchline); - } needsort = 1; matchline = NULL; } diff --git a/usr.bin/systat/ifstat.c b/usr.bin/systat/ifstat.c index 6bf588c3ab0..16328906832 100644 --- a/usr.bin/systat/ifstat.c +++ b/usr.bin/systat/ifstat.c @@ -230,7 +230,7 @@ initifstat(void) n = getifnum(); if (n <= 0) - return -1; + return (-1); SLIST_INIT(&curlist); @@ -254,7 +254,7 @@ initifstat(void) sort_interface_list(); - return 1; + return (1); } void @@ -372,9 +372,9 @@ check_match(const char *ifname) char *p = matchline, *c, t; int match = 0, mlen; - if (matchline == NULL) { - return 0; - } + if (matchline == NULL) + return (0); + /* Strip leading whitespaces */ while (*p == ' ') p ++; @@ -387,7 +387,7 @@ check_match(const char *ifname) *p = '\0'; if (fnmatch(c, ifname, FNM_CASEFOLD) == 0) { *p = t; - return 1; + return (1); } *p = t; c = p + strspn(p, " ;,"); @@ -397,7 +397,7 @@ check_match(const char *ifname) } } - return match; + return (match); } /* @@ -447,7 +447,7 @@ getifnum(void) if (sysctl(name, 5, (void *)&data, (size_t *)&datalen, (void *)NULL, (size_t)0) != 0) IFSTAT_ERR(1, "sysctl error"); - return data; + return (data); } static void @@ -485,5 +485,5 @@ cmdifstat(const char *cmd, const char *args) } } - return retval; + return (retval); } diff --git a/usr.bin/systat/systat.1 b/usr.bin/systat/systat.1 index 7637673c435..fa8f789365b 100644 --- a/usr.bin/systat/systat.1 +++ b/usr.bin/systat/systat.1 @@ -28,7 +28,7 @@ .\" @(#)systat.1 8.2 (Berkeley) 12/30/93 .\" $FreeBSD$ .\" -.Dd September 17, 2012 +.Dd February 20, 2013 .Dt SYSTAT 1 .Os .Sh NAME From b0d9adde8024d1d067bbf905fd6a4f30b1560e62 Mon Sep 17 00:00:00 2001 From: Brooks Davis Date: Wed, 20 Feb 2013 15:18:42 +0000 Subject: [PATCH 0298/1476] Add a -D flag that causes duplicate entries in an mtree manifest to be treated as warnings rather than errors. Reviewed by: marcel Sponsored by: DARPA, AFRL --- usr.sbin/makefs/makefs.8 | 4 +++- usr.sbin/makefs/makefs.c | 7 ++++++- usr.sbin/makefs/makefs.h | 1 + usr.sbin/makefs/mtree.c | 10 ++++++++-- 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/usr.sbin/makefs/makefs.8 b/usr.sbin/makefs/makefs.8 index b1a57513862..81bf3341b65 100644 --- a/usr.sbin/makefs/makefs.8 +++ b/usr.sbin/makefs/makefs.8 @@ -43,7 +43,7 @@ .Nd create a file system image from a directory tree or a mtree manifest .Sh SYNOPSIS .Nm -.Op Fl px +.Op Fl Dpx .Op Fl B Ar byte-order .Op Fl b Ar free-blocks .Op Fl d Ar debug-mask @@ -106,6 +106,8 @@ An optional suffix may be provided to indicate that .Ar free-blocks indicates a percentage of the calculated image size. +.It Fl D +Treat duplicate paths in an mtree manifest as warnings not error. .It Fl d Ar debug-mask Enable various levels of debugging, depending upon which bits are set in diff --git a/usr.sbin/makefs/makefs.c b/usr.sbin/makefs/makefs.c index b2da82b426d..03ff1ac38b1 100644 --- a/usr.sbin/makefs/makefs.c +++ b/usr.sbin/makefs/makefs.c @@ -73,6 +73,7 @@ static fstype_t fstypes[] = { }; u_int debug; +int dupsok; struct timespec start_time; static fstype_t *get_fstype(const char *); @@ -112,7 +113,7 @@ main(int argc, char *argv[]) start_time.tv_sec = start.tv_sec; start_time.tv_nsec = start.tv_usec * 1000; - while ((ch = getopt(argc, argv, "B:b:d:f:F:M:m:N:o:ps:S:t:x")) != -1) { + while ((ch = getopt(argc, argv, "B:b:Dd:f:F:M:m:N:o:ps:S:t:x")) != -1) { switch (ch) { case 'B': @@ -148,6 +149,10 @@ main(int argc, char *argv[]) } break; + case 'D': + dupsok = 1; + break; + case 'd': debug = strtoll(optarg, NULL, 0); break; diff --git a/usr.sbin/makefs/makefs.h b/usr.sbin/makefs/makefs.h index 483ccff9614..614637620d2 100644 --- a/usr.sbin/makefs/makefs.h +++ b/usr.sbin/makefs/makefs.h @@ -169,6 +169,7 @@ void cd9660_makefs(const char *, const char *, fsnode *, fsinfo_t *); extern u_int debug; +extern int dupsok; extern struct timespec start_time; /* diff --git a/usr.sbin/makefs/mtree.c b/usr.sbin/makefs/mtree.c index 836e7665635..f5eb5fc8cf8 100644 --- a/usr.sbin/makefs/mtree.c +++ b/usr.sbin/makefs/mtree.c @@ -881,8 +881,14 @@ read_mtree_spec1(FILE *fp, bool def, const char *name) if (strcmp(name, node->name) == 0) { if (def == true) { - mtree_error("duplicate definition of %s", - name); + if (!dupsok) + mtree_error( + "duplicate definition of %s", + name); + else + mtree_warning( + "duplicate definition of %s", + name); return (0); } From e9a03238b07457697468a52a46c6f31b178a71bc Mon Sep 17 00:00:00 2001 From: Brooks Davis Date: Wed, 20 Feb 2013 15:25:40 +0000 Subject: [PATCH 0299/1476] Fix the -N option in manifest mode by using pwcache(3). This also speeds up image creation appreciably. Reviewed by: marcel Sponsored by: DARPA, AFRL --- usr.sbin/makefs/mtree.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/usr.sbin/makefs/mtree.c b/usr.sbin/makefs/mtree.c index f5eb5fc8cf8..12893df26ce 100644 --- a/usr.sbin/makefs/mtree.c +++ b/usr.sbin/makefs/mtree.c @@ -508,8 +508,8 @@ read_mtree_keywords(FILE *fp, fsnode *node) { char keyword[PATH_MAX]; char *name, *p, *value; - struct group *grent; - struct passwd *pwent; + gid_t gid; + uid_t uid; struct stat *st, sb; intmax_t num; u_long flset, flclr; @@ -585,11 +585,10 @@ read_mtree_keywords(FILE *fp, fsnode *node) error = ENOATTR; break; } - grent = getgrnam(value); - if (grent != NULL) - st->st_gid = grent->gr_gid; + if (gid_from_group(value, &gid) == 0) + st->st_gid = gid; else - error = errno; + error = EINVAL; } else error = ENOSYS; break; @@ -698,11 +697,10 @@ read_mtree_keywords(FILE *fp, fsnode *node) error = ENOATTR; break; } - pwent = getpwnam(value); - if (pwent != NULL) - st->st_uid = pwent->pw_uid; + if (uid_from_user(value, &uid) == 0) + st->st_uid = uid; else - error = errno; + error = EINVAL; } else error = ENOSYS; break; From 17b3e6f7469ea7f774c32bd8ef406ec1a7ade679 Mon Sep 17 00:00:00 2001 From: Brooks Davis Date: Wed, 20 Feb 2013 15:28:40 +0000 Subject: [PATCH 0300/1476] Allow '.' components in manifest paths. They are always the first component of mtree -C and install -M output and are easily skipped. Reviewed by: marcel Sponsored by: DARPA, AFRL --- usr.sbin/makefs/mtree.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/usr.sbin/makefs/mtree.c b/usr.sbin/makefs/mtree.c index 12893df26ce..2f2400ab26e 100644 --- a/usr.sbin/makefs/mtree.c +++ b/usr.sbin/makefs/mtree.c @@ -974,15 +974,15 @@ read_mtree_spec(FILE *fp) do { *cp++ = '\0'; - /* Disallow '.' and '..' as components. */ - if (IS_DOT(pathspec) || IS_DOTDOT(pathspec)) { - mtree_error("absolute path cannot contain . " - "or .. components"); + /* Disallow '..' as a component. */ + if (IS_DOTDOT(pathspec)) { + mtree_error("absolute path cannot contain " + ".. component"); goto out; } - /* Ignore multiple adjacent slashes. */ - if (pathspec[0] != '\0') + /* Ignore multiple adjacent slashes and '.'. */ + if (pathspec[0] != '\0' && !IS_DOT(pathspec)) error = read_mtree_spec1(fp, false, pathspec); memmove(pathspec, cp, strlen(cp) + 1); cp = strchr(pathspec, '/'); From 46f2df9c137dbbf184098204dd05bb459cae51b9 Mon Sep 17 00:00:00 2001 From: Sergey Kandaurov Date: Wed, 20 Feb 2013 15:44:40 +0000 Subject: [PATCH 0301/1476] ip_savecontrol() style fixes. No functional changes. - fix indentation - put the operator at the end of the line for long statements - remove spaces between the type and the variable in a cast - remove excessive parentheses Tested by: md5 --- sys/netinet/ip_input.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 0e559a652b8..555b5d08216 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -1592,8 +1592,8 @@ ip_savecontrol(struct inpcb *inp, struct mbuf **mp, struct ip *ip, bintime(&bt); if (inp->inp_socket->so_options & SO_BINTIME) { - *mp = sbcreatecontrol((caddr_t) &bt, sizeof(bt), - SCM_BINTIME, SOL_SOCKET); + *mp = sbcreatecontrol((caddr_t)&bt, sizeof(bt), + SCM_BINTIME, SOL_SOCKET); if (*mp) mp = &(*mp)->m_next; } @@ -1601,20 +1601,20 @@ ip_savecontrol(struct inpcb *inp, struct mbuf **mp, struct ip *ip, struct timeval tv; bintime2timeval(&bt, &tv); - *mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv), - SCM_TIMESTAMP, SOL_SOCKET); + *mp = sbcreatecontrol((caddr_t)&tv, sizeof(tv), + SCM_TIMESTAMP, SOL_SOCKET); if (*mp) mp = &(*mp)->m_next; } } if (inp->inp_flags & INP_RECVDSTADDR) { - *mp = sbcreatecontrol((caddr_t) &ip->ip_dst, + *mp = sbcreatecontrol((caddr_t)&ip->ip_dst, sizeof(struct in_addr), IP_RECVDSTADDR, IPPROTO_IP); if (*mp) mp = &(*mp)->m_next; } if (inp->inp_flags & INP_RECVTTL) { - *mp = sbcreatecontrol((caddr_t) &ip->ip_ttl, + *mp = sbcreatecontrol((caddr_t)&ip->ip_ttl, sizeof(u_char), IP_RECVTTL, IPPROTO_IP); if (*mp) mp = &(*mp)->m_next; @@ -1626,14 +1626,14 @@ ip_savecontrol(struct inpcb *inp, struct mbuf **mp, struct ip *ip, */ /* options were tossed already */ if (inp->inp_flags & INP_RECVOPTS) { - *mp = sbcreatecontrol((caddr_t) opts_deleted_above, + *mp = sbcreatecontrol((caddr_t)opts_deleted_above, sizeof(struct in_addr), IP_RECVOPTS, IPPROTO_IP); if (*mp) mp = &(*mp)->m_next; } /* ip_srcroute doesn't do what we want here, need to fix */ if (inp->inp_flags & INP_RECVRETOPTS) { - *mp = sbcreatecontrol((caddr_t) ip_srcroute(m), + *mp = sbcreatecontrol((caddr_t)ip_srcroute(m), sizeof(struct in_addr), IP_RECVRETOPTS, IPPROTO_IP); if (*mp) mp = &(*mp)->m_next; @@ -1648,32 +1648,32 @@ ip_savecontrol(struct inpcb *inp, struct mbuf **mp, struct ip *ip, struct sockaddr_dl *sdp; struct sockaddr_dl *sdl2 = &sdlbuf.sdl; - if (((ifp = m->m_pkthdr.rcvif)) - && ( ifp->if_index && (ifp->if_index <= V_if_index))) { + if ((ifp = m->m_pkthdr.rcvif) && + ifp->if_index && ifp->if_index <= V_if_index) { sdp = (struct sockaddr_dl *)ifp->if_addr->ifa_addr; /* * Change our mind and don't try copy. */ - if ((sdp->sdl_family != AF_LINK) - || (sdp->sdl_len > sizeof(sdlbuf))) { + if (sdp->sdl_family != AF_LINK || + sdp->sdl_len > sizeof(sdlbuf)) { goto makedummy; } bcopy(sdp, sdl2, sdp->sdl_len); } else { makedummy: - sdl2->sdl_len - = offsetof(struct sockaddr_dl, sdl_data[0]); + sdl2->sdl_len = + offsetof(struct sockaddr_dl, sdl_data[0]); sdl2->sdl_family = AF_LINK; sdl2->sdl_index = 0; sdl2->sdl_nlen = sdl2->sdl_alen = sdl2->sdl_slen = 0; } - *mp = sbcreatecontrol((caddr_t) sdl2, sdl2->sdl_len, - IP_RECVIF, IPPROTO_IP); + *mp = sbcreatecontrol((caddr_t)sdl2, sdl2->sdl_len, + IP_RECVIF, IPPROTO_IP); if (*mp) mp = &(*mp)->m_next; } if (inp->inp_flags & INP_RECVTOS) { - *mp = sbcreatecontrol((caddr_t) &ip->ip_tos, + *mp = sbcreatecontrol((caddr_t)&ip->ip_tos, sizeof(u_char), IP_RECVTOS, IPPROTO_IP); if (*mp) mp = &(*mp)->m_next; From f87223581e8252fd73449801f5c3a6231319b7a8 Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Wed, 20 Feb 2013 16:32:38 +0000 Subject: [PATCH 0302/1476] Fix "fdt addr" to accept literal addresses rather than va offsets. When initializing the fdt, query U-Boot as well. With this change, it is now feasible to have U-Boot load the FDT, ubldr will pull it from U-Boot and hand it to the kernel. --- sys/boot/fdt/fdt_loader_cmd.c | 60 ++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 19 deletions(-) diff --git a/sys/boot/fdt/fdt_loader_cmd.c b/sys/boot/fdt/fdt_loader_cmd.c index c7297f412d9..37cf75dfcca 100644 --- a/sys/boot/fdt/fdt_loader_cmd.c +++ b/sys/boot/fdt/fdt_loader_cmd.c @@ -235,26 +235,47 @@ fdt_load_dtb(vm_offset_t va) } static int -fdt_setup_fdtp() +fdt_load_dtb_addr(struct fdt_header *header) { struct preloaded_file *bfp; - vm_offset_t va; - bfp = file_findfile(NULL, "dtb"); + bfp = mem_load_raw("dtb", "memory.dtb", header, fdt_totalsize(header)); if (bfp == NULL) { - if ((va = fdt_find_static_dtb()) == 0) { - command_errmsg = "no device tree blob found!"; - return (1); - } - } else { - /* Dynamic blob has precedence over static. */ - va = bfp->f_addr; - } - - if (fdt_load_dtb(va) != 0) + command_errmsg = "unable to copy DTB into module directory"; return (1); - - return (0); + } + return fdt_load_dtb(bfp->f_addr); +} + +static int +fdt_setup_fdtp() +{ + struct preloaded_file *bfp; + struct fdt_header *hdr; + const char *s, *p; + vm_offset_t va; + + if ((bfp = file_findfile(NULL, "dtb")) != NULL) { + printf("Using DTB from loaded file.\n"); + return fdt_load_dtb(bfp->f_addr); + } + + s = ub_env_get("fdtaddr"); + if (s != NULL && *s != '\0') { + hdr = (struct fdt_header *)strtoul(s, &p, 16); + if (*p == '\0') { + printf("Using DTB provided by U-Boot.\n"); + return fdt_load_dtb_addr(hdr); + } + } + + if ((va = fdt_find_static_dtb()) != 0) { + printf("Using DTB compiled into kernel.\n"); + return (fdt_load_dtb(va)); + } + + command_errmsg = "no device tree blob found!"; + return (1); } #define fdt_strtovect(str, cellbuf, lim, cellsize) _fdt_strtovect((str), \ @@ -789,8 +810,8 @@ command_fdt_internal(int argc, char *argv[]) static int fdt_cmd_addr(int argc, char *argv[]) { - vm_offset_t va; - char *addr, *cp; + struct fdt_header *hdr; + const char *addr, *cp; if (argc > 2) addr = argv[2]; @@ -799,13 +820,13 @@ fdt_cmd_addr(int argc, char *argv[]) return (CMD_ERROR); } - va = strtol(addr, &cp, 0); + hdr = (struct fdt_header *)strtoul(addr, &cp, 0); if (cp == addr) { sprintf(command_errbuf, "Invalid address: %s", addr); return (CMD_ERROR); } - if (fdt_load_dtb(va) != 0) + if (fdt_load_dtb_addr(hdr) != 0) return (CMD_ERROR); return (CMD_OK); @@ -1484,6 +1505,7 @@ fdt_cmd_mkprop(int argc, char *argv[]) if (fdt_modprop(o, propname, value, 1)) return (CMD_ERROR); + COPYIN(fdtp, fdtp_va, fdtp_size); return (CMD_OK); } From 5c9f7b1a91bf48732ba2766e3aaa296ec2c1ab29 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 20 Feb 2013 16:48:52 +0000 Subject: [PATCH 0303/1476] Initialize vm_max_kernel_address on non-FDT platforms. (This should have been included in r246926.) The second parameter to pmap_bootstrap() is redundant. Eliminate it. Reviewed by: andrew --- sys/arm/arm/machdep.c | 2 +- sys/arm/arm/pmap-v6.c | 11 ++++++----- sys/arm/arm/pmap.c | 11 ++++++----- sys/arm/at91/at91_machdep.c | 3 ++- sys/arm/econa/econa_machdep.c | 3 ++- sys/arm/include/pmap.h | 2 +- sys/arm/s3c2xx0/s3c24x0_machdep.c | 3 ++- sys/arm/sa11x0/assabet_machdep.c | 3 ++- sys/arm/xscale/i80321/ep80219_machdep.c | 4 ++-- sys/arm/xscale/i80321/iq31244_machdep.c | 4 ++-- sys/arm/xscale/i8134x/crb_machdep.c | 4 ++-- sys/arm/xscale/ixp425/avila_machdep.c | 3 ++- sys/arm/xscale/pxa/pxa_machdep.c | 3 ++- 13 files changed, 32 insertions(+), 24 deletions(-) diff --git a/sys/arm/arm/machdep.c b/sys/arm/arm/machdep.c index 28d1902d71c..ec65c04b18b 100644 --- a/sys/arm/arm/machdep.c +++ b/sys/arm/arm/machdep.c @@ -1476,7 +1476,7 @@ initarm(struct arm_boot_params *abp) arm_intrnames_init(); arm_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL); arm_dump_avail_init(memsize, sizeof(dump_avail) / sizeof(dump_avail[0])); - pmap_bootstrap(freemempos, vm_max_kernel_address, &kernel_l1pt); + pmap_bootstrap(freemempos, &kernel_l1pt); msgbufp = (void *)msgbufpv.pv_va; msgbufinit(msgbufp, msgbufsize); mutex_init(); diff --git a/sys/arm/arm/pmap-v6.c b/sys/arm/arm/pmap-v6.c index f05f120ab85..72ef310d918 100644 --- a/sys/arm/arm/pmap-v6.c +++ b/sys/arm/arm/pmap-v6.c @@ -1538,7 +1538,7 @@ pmap_alloc_specials(vm_offset_t *availp, int pages, vm_offset_t *vap, #define PMAP_STATIC_L2_SIZE 16 void -pmap_bootstrap(vm_offset_t firstaddr, vm_offset_t lastaddr, struct pv_addr *l1pt) +pmap_bootstrap(vm_offset_t firstaddr, struct pv_addr *l1pt) { static struct l1_ttable static_l1; static struct l2_dtable static_l2[PMAP_STATIC_L2_SIZE]; @@ -1554,7 +1554,7 @@ pmap_bootstrap(vm_offset_t firstaddr, vm_offset_t lastaddr, struct pv_addr *l1pt int l1idx, l2idx, l2next = 0; PDEBUG(1, printf("firstaddr = %08x, lastaddr = %08x\n", - firstaddr, lastaddr)); + firstaddr, vm_max_kernel_address)); virtual_avail = firstaddr; kernel_pmap->pm_l1 = l1; @@ -1670,7 +1670,8 @@ pmap_bootstrap(vm_offset_t firstaddr, vm_offset_t lastaddr, struct pv_addr *l1pt pmap_set_pt_cache_mode(kernel_l1pt, (vm_offset_t)csrc_pte); pmap_alloc_specials(&virtual_avail, 1, &cdstp, &cdst_pte); pmap_set_pt_cache_mode(kernel_l1pt, (vm_offset_t)cdst_pte); - size = ((lastaddr - pmap_curmaxkvaddr) + L1_S_OFFSET) / L1_S_SIZE; + size = ((vm_max_kernel_address - pmap_curmaxkvaddr) + L1_S_OFFSET) / + L1_S_SIZE; pmap_alloc_specials(&virtual_avail, round_page(size * L2_TABLE_SIZE_REAL) / PAGE_SIZE, &pmap_kernel_l2ptp_kva, NULL); @@ -1692,9 +1693,9 @@ pmap_bootstrap(vm_offset_t firstaddr, vm_offset_t lastaddr, struct pv_addr *l1pt cpu_l2cache_wbinv_all(); virtual_avail = round_page(virtual_avail); - virtual_end = lastaddr; + virtual_end = vm_max_kernel_address; kernel_vm_end = pmap_curmaxkvaddr; - arm_nocache_startaddr = lastaddr; + arm_nocache_startaddr = vm_max_kernel_address; mtx_init(&cmtx, "TMP mappings mtx", NULL, MTX_DEF); pmap_set_pcb_pagedir(kernel_pmap, thread0.td_pcb); diff --git a/sys/arm/arm/pmap.c b/sys/arm/arm/pmap.c index c9cb42c638e..28b4912d6e0 100644 --- a/sys/arm/arm/pmap.c +++ b/sys/arm/arm/pmap.c @@ -2254,7 +2254,7 @@ extern struct mtx smallalloc_mtx; #endif void -pmap_bootstrap(vm_offset_t firstaddr, vm_offset_t lastaddr, struct pv_addr *l1pt) +pmap_bootstrap(vm_offset_t firstaddr, struct pv_addr *l1pt) { static struct l1_ttable static_l1; static struct l2_dtable static_l2[PMAP_STATIC_L2_SIZE]; @@ -2270,7 +2270,7 @@ pmap_bootstrap(vm_offset_t firstaddr, vm_offset_t lastaddr, struct pv_addr *l1pt int l1idx, l2idx, l2next = 0; PDEBUG(1, printf("firstaddr = %08x, lastaddr = %08x\n", - firstaddr, lastaddr)); + firstaddr, vm_max_kernel_address)); virtual_avail = firstaddr; kernel_pmap->pm_l1 = l1; @@ -2388,7 +2388,8 @@ pmap_bootstrap(vm_offset_t firstaddr, vm_offset_t lastaddr, struct pv_addr *l1pt pmap_set_pt_cache_mode(kernel_l1pt, (vm_offset_t)csrc_pte); pmap_alloc_specials(&virtual_avail, 1, &cdstp, &cdst_pte); pmap_set_pt_cache_mode(kernel_l1pt, (vm_offset_t)cdst_pte); - size = ((lastaddr - pmap_curmaxkvaddr) + L1_S_OFFSET) / L1_S_SIZE; + size = ((vm_max_kernel_address - pmap_curmaxkvaddr) + L1_S_OFFSET) / + L1_S_SIZE; pmap_alloc_specials(&virtual_avail, round_page(size * L2_TABLE_SIZE_REAL) / PAGE_SIZE, &pmap_kernel_l2ptp_kva, NULL); @@ -2410,9 +2411,9 @@ pmap_bootstrap(vm_offset_t firstaddr, vm_offset_t lastaddr, struct pv_addr *l1pt cpu_l2cache_wbinv_all(); virtual_avail = round_page(virtual_avail); - virtual_end = lastaddr; + virtual_end = vm_max_kernel_address; kernel_vm_end = pmap_curmaxkvaddr; - arm_nocache_startaddr = lastaddr; + arm_nocache_startaddr = vm_max_kernel_address; mtx_init(&cmtx, "TMP mappings mtx", NULL, MTX_DEF); #ifdef ARM_USE_SMALL_ALLOC diff --git a/sys/arm/at91/at91_machdep.c b/sys/arm/at91/at91_machdep.c index f2b63cbdac3..3df922ef336 100644 --- a/sys/arm/at91/at91_machdep.c +++ b/sys/arm/at91/at91_machdep.c @@ -624,7 +624,8 @@ initarm(struct arm_boot_params *abp) pmap_curmaxkvaddr = afterkern + L1_S_SIZE * (KERNEL_PT_KERN_NUM - 1); arm_dump_avail_init(memsize, sizeof(dump_avail)/sizeof(dump_avail[0])); - pmap_bootstrap(freemempos, KERNVIRTADDR + 3 * memsize, &kernel_l1pt); + vm_max_kernel_address = KERNVIRTADDR + 3 * memsize; + pmap_bootstrap(freemempos, &kernel_l1pt); msgbufp = (void*)msgbufpv.pv_va; msgbufinit(msgbufp, msgbufsize); mutex_init(); diff --git a/sys/arm/econa/econa_machdep.c b/sys/arm/econa/econa_machdep.c index e9a98eee630..177d45b7789 100644 --- a/sys/arm/econa/econa_machdep.c +++ b/sys/arm/econa/econa_machdep.c @@ -324,7 +324,8 @@ initarm(struct arm_boot_params *abp) pmap_curmaxkvaddr = afterkern + L1_S_SIZE * (KERNEL_PT_KERN_NUM - 1); arm_dump_avail_init(memsize, sizeof(dump_avail) / sizeof(dump_avail[0])); - pmap_bootstrap(freemempos, KERNVIRTADDR + 3 * memsize, &kernel_l1pt); + vm_max_kernel_address = KERNVIRTADDR + 3 * memsize; + pmap_bootstrap(freemempos, &kernel_l1pt); msgbufp = (void*)msgbufpv.pv_va; msgbufinit(msgbufp, msgbufsize); diff --git a/sys/arm/include/pmap.h b/sys/arm/include/pmap.h index 4f7566ea35b..523499f3cc6 100644 --- a/sys/arm/include/pmap.h +++ b/sys/arm/include/pmap.h @@ -222,7 +222,7 @@ extern vm_paddr_t phys_avail[]; extern vm_offset_t virtual_avail; extern vm_offset_t virtual_end; -void pmap_bootstrap(vm_offset_t, vm_offset_t, struct pv_addr *); +void pmap_bootstrap(vm_offset_t firstaddr, struct pv_addr *l1pt); int pmap_change_attr(vm_offset_t, vm_size_t, int); void pmap_kenter(vm_offset_t va, vm_paddr_t pa); void pmap_kenter_nocache(vm_offset_t va, vm_paddr_t pa); diff --git a/sys/arm/s3c2xx0/s3c24x0_machdep.c b/sys/arm/s3c2xx0/s3c24x0_machdep.c index 8d2538b809b..f19e3f295f7 100644 --- a/sys/arm/s3c2xx0/s3c24x0_machdep.c +++ b/sys/arm/s3c2xx0/s3c24x0_machdep.c @@ -386,7 +386,8 @@ initarm(struct arm_boot_params *abp) pmap_curmaxkvaddr = afterkern + 0x100000 * (KERNEL_PT_KERN_NUM - 1); arm_dump_avail_init(memsize, sizeof(dump_avail) / sizeof(dump_avail[0])); - pmap_bootstrap(freemempos, KERNVIRTADDR + 3 * memsize, &kernel_l1pt); + vm_max_kernel_address = KERNVIRTADDR + 3 * memsize; + pmap_bootstrap(freemempos, &kernel_l1pt); msgbufp = (void*)msgbufpv.pv_va; msgbufinit(msgbufp, msgbufsize); mutex_init(); diff --git a/sys/arm/sa11x0/assabet_machdep.c b/sys/arm/sa11x0/assabet_machdep.c index 9fd1633abfc..9266939bbdf 100644 --- a/sys/arm/sa11x0/assabet_machdep.c +++ b/sys/arm/sa11x0/assabet_machdep.c @@ -381,7 +381,8 @@ initarm(struct arm_boot_params *abp) dump_avail[3] = phys_avail[3] = 0; mutex_init(); - pmap_bootstrap(freemempos, 0xd0000000, &kernel_l1pt); + vm_max_kernel_address = 0xd0000000; + pmap_bootstrap(freemempos, &kernel_l1pt); init_param2(physmem); kdb_init(); diff --git a/sys/arm/xscale/i80321/ep80219_machdep.c b/sys/arm/xscale/i80321/ep80219_machdep.c index b7621cadb40..d3c65b2ac88 100644 --- a/sys/arm/xscale/i80321/ep80219_machdep.c +++ b/sys/arm/xscale/i80321/ep80219_machdep.c @@ -368,8 +368,8 @@ initarm(struct arm_boot_params *abp) dump_avail[2] = 0; dump_avail[3] = 0; - pmap_bootstrap(pmap_curmaxkvaddr, - 0xd0000000, &kernel_l1pt); + vm_max_kernel_address = 0xd0000000; + pmap_bootstrap(pmap_curmaxkvaddr, &kernel_l1pt); msgbufp = (void*)msgbufpv.pv_va; msgbufinit(msgbufp, msgbufsize); mutex_init(); diff --git a/sys/arm/xscale/i80321/iq31244_machdep.c b/sys/arm/xscale/i80321/iq31244_machdep.c index 869c248024a..e7f34f5bebd 100644 --- a/sys/arm/xscale/i80321/iq31244_machdep.c +++ b/sys/arm/xscale/i80321/iq31244_machdep.c @@ -369,8 +369,8 @@ initarm(struct arm_boot_params *abp) dump_avail[2] = 0; dump_avail[3] = 0; - pmap_bootstrap(pmap_curmaxkvaddr, - 0xd0000000, &kernel_l1pt); + vm_max_kernel_address = 0xd0000000; + pmap_bootstrap(pmap_curmaxkvaddr, &kernel_l1pt); msgbufp = (void*)msgbufpv.pv_va; msgbufinit(msgbufp, msgbufsize); mutex_init(); diff --git a/sys/arm/xscale/i8134x/crb_machdep.c b/sys/arm/xscale/i8134x/crb_machdep.c index e0f21db0d8c..7c62c725717 100644 --- a/sys/arm/xscale/i8134x/crb_machdep.c +++ b/sys/arm/xscale/i8134x/crb_machdep.c @@ -347,8 +347,8 @@ initarm(struct arm_boot_params *abp) dump_avail[2] = 0; dump_avail[3] = 0; - pmap_bootstrap(pmap_curmaxkvaddr, - 0xd0000000, &kernel_l1pt); + vm_max_kernel_address = 0xd0000000; + pmap_bootstrap(pmap_curmaxkvaddr, &kernel_l1pt); msgbufp = (void*)msgbufpv.pv_va; msgbufinit(msgbufp, msgbufsize); mutex_init(); diff --git a/sys/arm/xscale/ixp425/avila_machdep.c b/sys/arm/xscale/ixp425/avila_machdep.c index dde3be7cb3d..82b0e0219cc 100644 --- a/sys/arm/xscale/ixp425/avila_machdep.c +++ b/sys/arm/xscale/ixp425/avila_machdep.c @@ -432,7 +432,8 @@ initarm(struct arm_boot_params *abp) pmap_curmaxkvaddr = afterkern + PAGE_SIZE; arm_dump_avail_init(memsize, sizeof(dump_avail) / sizeof(dump_avail[0])); - pmap_bootstrap(pmap_curmaxkvaddr, 0xd0000000, &kernel_l1pt); + vm_max_kernel_address = 0xd0000000; + pmap_bootstrap(pmap_curmaxkvaddr, &kernel_l1pt); msgbufp = (void*)msgbufpv.pv_va; msgbufinit(msgbufp, msgbufsize); mutex_init(); diff --git a/sys/arm/xscale/pxa/pxa_machdep.c b/sys/arm/xscale/pxa/pxa_machdep.c index 71f77857868..440812f909a 100644 --- a/sys/arm/xscale/pxa/pxa_machdep.c +++ b/sys/arm/xscale/pxa/pxa_machdep.c @@ -365,7 +365,8 @@ initarm(struct arm_boot_params *abp) } dump_avail[i] = 0; dump_avail[i] = 0; - pmap_bootstrap(pmap_curmaxkvaddr, 0xd0000000, &kernel_l1pt); + vm_max_kernel_address = 0xd0000000; + pmap_bootstrap(pmap_curmaxkvaddr, &kernel_l1pt); msgbufp = (void*)msgbufpv.pv_va; msgbufinit(msgbufp, msgbufsize); mutex_init(); From 31a53cd03625e31cbbf63b78cf3c9b711301869a Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Wed, 20 Feb 2013 17:39:52 +0000 Subject: [PATCH 0304/1476] Convert machine/elf.h, machine/frame.h, machine/sigframe.h, machine/signal.h and machine/ucontext.h into common x86 includes, copying from amd64 and merging with i386. Kernel-only compat definitions are kept in the i386/include/sigframe.h and i386/include/signal.h, to reduce amd64 kernel namespace pollution. The amd64 compat uses its own definitions so far. The _MACHINE_ELF_WANT_32BIT definition is to allow the sys/boot/userboot/userboot/elf32_freebsd.c to use i386 ELF definitions on the amd64 compile host. The same hack could be usefully abused by other code too. --- sys/amd64/include/elf.h | 124 +----------- sys/amd64/include/frame.h | 87 +-------- sys/amd64/include/sigframe.h | 46 +---- sys/amd64/include/signal.h | 109 +---------- sys/amd64/include/ucontext.h | 103 +--------- sys/boot/userboot/userboot/elf32_freebsd.c | 1 + sys/i386/include/elf.h | 118 +---------- sys/i386/include/frame.h | 100 +--------- sys/i386/include/sigframe.h | 21 +- sys/i386/include/signal.h | 73 +------ sys/i386/include/ucontext.h | 60 +----- sys/x86/include/elf.h | 215 +++++++++++++++++++++ sys/x86/include/frame.h | 148 ++++++++++++++ sys/x86/include/sigframe.h | 72 +++++++ sys/x86/include/signal.h | 167 ++++++++++++++++ sys/x86/include/ucontext.h | 165 ++++++++++++++++ 16 files changed, 793 insertions(+), 816 deletions(-) create mode 100644 sys/x86/include/elf.h create mode 100644 sys/x86/include/frame.h create mode 100644 sys/x86/include/sigframe.h create mode 100644 sys/x86/include/signal.h create mode 100644 sys/x86/include/ucontext.h diff --git a/sys/amd64/include/elf.h b/sys/amd64/include/elf.h index d69c6b44bd1..f9323775dc2 100644 --- a/sys/amd64/include/elf.h +++ b/sys/amd64/include/elf.h @@ -1,124 +1,6 @@ /*- - * Copyright (c) 1996-1997 John D. Polstra. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ + * This file is in the public domain. */ +/* $FreeBSD$ */ -#ifndef _MACHINE_ELF_H_ -#define _MACHINE_ELF_H_ 1 - -/* - * ELF definitions for the AMD64 architecture. - */ - - -#ifndef __ELF_WORD_SIZE -#define __ELF_WORD_SIZE 64 /* Used by */ -#endif -#include /* Definitions common to all 32 bit architectures. */ -#include /* Definitions common to all 64 bit architectures. */ -#include - -#define ELF_ARCH EM_X86_64 -#define ELF_ARCH32 EM_386 - -#define ELF_MACHINE_OK(x) ((x) == EM_X86_64) - -/* - * Auxiliary vector entries for passing information to the interpreter. - * - * The i386 supplement to the SVR4 ABI specification names this "auxv_t", - * but POSIX lays claim to all symbols ending with "_t". - */ -typedef struct { /* Auxiliary vector entry on initial stack */ - int a_type; /* Entry type. */ - union { - int a_val; /* Integer value. */ - } a_un; -} Elf32_Auxinfo; - - -typedef struct { /* Auxiliary vector entry on initial stack */ - long a_type; /* Entry type. */ - union { - long a_val; /* Integer value. */ - void *a_ptr; /* Address. */ - void (*a_fcn)(void); /* Function pointer (not used). */ - } a_un; -} Elf64_Auxinfo; - -__ElfType(Auxinfo); - -/* Values for a_type. */ -#define AT_NULL 0 /* Terminates the vector. */ -#define AT_IGNORE 1 /* Ignored entry. */ -#define AT_EXECFD 2 /* File descriptor of program to load. */ -#define AT_PHDR 3 /* Program header of program already loaded. */ -#define AT_PHENT 4 /* Size of each program header entry. */ -#define AT_PHNUM 5 /* Number of program header entries. */ -#define AT_PAGESZ 6 /* Page size in bytes. */ -#define AT_BASE 7 /* Interpreter's base address. */ -#define AT_FLAGS 8 /* Flags (unused for i386). */ -#define AT_ENTRY 9 /* Where interpreter should transfer control. */ -#define AT_NOTELF 10 /* Program is not ELF ?? */ -#define AT_UID 11 /* Real uid. */ -#define AT_EUID 12 /* Effective uid. */ -#define AT_GID 13 /* Real gid. */ -#define AT_EGID 14 /* Effective gid. */ -#define AT_EXECPATH 15 /* Path to the executable. */ -#define AT_CANARY 16 /* Canary for SSP */ -#define AT_CANARYLEN 17 /* Length of the canary. */ -#define AT_OSRELDATE 18 /* OSRELDATE. */ -#define AT_NCPUS 19 /* Number of CPUs. */ -#define AT_PAGESIZES 20 /* Pagesizes. */ -#define AT_PAGESIZESLEN 21 /* Number of pagesizes. */ -#define AT_TIMEKEEP 22 /* Pointer to timehands. */ -#define AT_STACKPROT 23 /* Initial stack protection. */ - -#define AT_COUNT 24 /* Count of defined aux entry types. */ - -/* - * Relocation types. - */ - -#define R_X86_64_COUNT 24 /* Count of defined relocation types. */ - -/* Define "machine" characteristics */ -#if __ELF_WORD_SIZE == 32 -#define ELF_TARG_CLASS ELFCLASS32 -#else -#define ELF_TARG_CLASS ELFCLASS64 -#endif -#define ELF_TARG_DATA ELFDATA2LSB -#define ELF_TARG_MACH EM_X86_64 -#define ELF_TARG_VER 1 - -#if __ELF_WORD_SIZE == 32 -#define ET_DYN_LOAD_ADDR 0x01001000 -#else -#define ET_DYN_LOAD_ADDR 0x01021000 -#endif - -#endif /* !_MACHINE_ELF_H_ */ +#include diff --git a/sys/amd64/include/frame.h b/sys/amd64/include/frame.h index e171407d236..0953be70087 100644 --- a/sys/amd64/include/frame.h +++ b/sys/amd64/include/frame.h @@ -1,87 +1,6 @@ /*- - * Copyright (c) 2003 Peter Wemm. - * Copyright (c) 1990 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * William Jolitz. - * - * 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. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#)frame.h 5.2 (Berkeley) 1/18/91 - * $FreeBSD$ + * This file is in the public domain. */ +/* $FreeBSD$ */ -#ifndef _MACHINE_FRAME_H_ -#define _MACHINE_FRAME_H_ 1 - -/* - * System stack frames. - */ - -/* - * Exception/Trap Stack Frame - * - * The ordering of this is specifically so that we can take first 6 - * the syscall arguments directly from the beginning of the frame. - */ - -struct trapframe { - register_t tf_rdi; - register_t tf_rsi; - register_t tf_rdx; - register_t tf_rcx; - register_t tf_r8; - register_t tf_r9; - register_t tf_rax; - register_t tf_rbx; - register_t tf_rbp; - register_t tf_r10; - register_t tf_r11; - register_t tf_r12; - register_t tf_r13; - register_t tf_r14; - register_t tf_r15; - uint32_t tf_trapno; - uint16_t tf_fs; - uint16_t tf_gs; - register_t tf_addr; - uint32_t tf_flags; - uint16_t tf_es; - uint16_t tf_ds; - /* below portion defined in hardware */ - register_t tf_err; - register_t tf_rip; - register_t tf_cs; - register_t tf_rflags; - register_t tf_rsp; - register_t tf_ss; -}; - -#define TF_HASSEGS 0x1 -#define TF_HASBASES 0x2 -#define TF_HASFPXSTATE 0x4 - -#endif /* _MACHINE_FRAME_H_ */ +#include diff --git a/sys/amd64/include/sigframe.h b/sys/amd64/include/sigframe.h index d104507d52f..d5cdb56289a 100644 --- a/sys/amd64/include/sigframe.h +++ b/sys/amd64/include/sigframe.h @@ -1,46 +1,6 @@ /*- - * Copyright (c) 1999 Marcel Moolenaar - * 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 - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ + * This file is in the public domain. */ +/* $FreeBSD$ */ -#ifndef _MACHINE_SIGFRAME_H_ -#define _MACHINE_SIGFRAME_H_ - -/* - * Signal frames, arguments passed to application signal handlers. - */ -struct sigframe { - union { - __siginfohandler_t *sf_action; - __sighandler_t *sf_handler; - } sf_ahu; - ucontext_t sf_uc; /* = *sf_ucontext */ - siginfo_t sf_si; /* = *sf_siginfo (SA_SIGINFO case) */ -}; - -#endif /* !_MACHINE_SIGFRAME_H_ */ +#include diff --git a/sys/amd64/include/signal.h b/sys/amd64/include/signal.h index 085d43a9f0c..db9fe6ad597 100644 --- a/sys/amd64/include/signal.h +++ b/sys/amd64/include/signal.h @@ -1,109 +1,6 @@ /*- - * Copyright (c) 2003 Peter Wemm. - * Copyright (c) 1986, 1989, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)signal.h 8.1 (Berkeley) 6/11/93 - * $FreeBSD$ + * This file is in the public domain. */ +/* $FreeBSD$ */ -#ifndef _MACHINE_SIGNAL_H_ -#define _MACHINE_SIGNAL_H_ - -#include -#include - -/* - * Machine-dependent signal definitions - */ - -typedef long sig_atomic_t; - -#if __BSD_VISIBLE -#include /* codes for SIGILL, SIGFPE */ - -/* - * Information pushed on stack when a signal is delivered. - * This is used by the kernel to restore state following - * execution of the signal handler. It is also made available - * to the handler to allow it to restore state properly if - * a non-standard exit is performed. - * - * The sequence of the fields/registers after sc_mask in struct - * sigcontext must match those in mcontext_t and struct trapframe. - */ -struct sigcontext { - struct __sigset sc_mask; /* signal mask to restore */ - long sc_onstack; /* sigstack state to restore */ - long sc_rdi; /* machine state (struct trapframe) */ - long sc_rsi; - long sc_rdx; - long sc_rcx; - long sc_r8; - long sc_r9; - long sc_rax; - long sc_rbx; - long sc_rbp; - long sc_r10; - long sc_r11; - long sc_r12; - long sc_r13; - long sc_r14; - long sc_r15; - int sc_trapno; - short sc_fs; - short sc_gs; - long sc_addr; - int sc_flags; - short sc_es; - short sc_ds; - long sc_err; - long sc_rip; - long sc_cs; - long sc_rflags; - long sc_rsp; - long sc_ss; - long sc_len; /* sizeof(mcontext_t) */ - /* - * See and for the following - * fields. - */ - long sc_fpformat; - long sc_ownedfp; - long sc_fpstate[64] __aligned(16); - - long sc_fsbase; - long sc_gsbase; - - long sc_xfpustate; - long sc_xfpustate_len; - - long sc_spare[4]; -}; -#endif /* __BSD_VISIBLE */ - -#endif /* !_MACHINE_SIGNAL_H_ */ +#include diff --git a/sys/amd64/include/ucontext.h b/sys/amd64/include/ucontext.h index 5ab841e29b5..aea80e3845a 100644 --- a/sys/amd64/include/ucontext.h +++ b/sys/amd64/include/ucontext.h @@ -1,103 +1,6 @@ /*- - * Copyright (c) 2003 Peter Wemm - * Copyright (c) 1999 Marcel Moolenaar - * 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 - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ + * This file is in the public domain. */ +/* $FreeBSD$ */ -#ifndef _MACHINE_UCONTEXT_H_ -#define _MACHINE_UCONTEXT_H_ - -/* - * mc_trapno bits. Shall be in sync with TF_XXX. - */ -#define _MC_HASSEGS 0x1 -#define _MC_HASBASES 0x2 -#define _MC_HASFPXSTATE 0x4 -#define _MC_FLAG_MASK (_MC_HASSEGS | _MC_HASBASES | _MC_HASFPXSTATE) - -typedef struct __mcontext { - /* - * The definition of mcontext_t must match the layout of - * struct sigcontext after the sc_mask member. This is so - * that we can support sigcontext and ucontext_t at the same - * time. - */ - __register_t mc_onstack; /* XXX - sigcontext compat. */ - __register_t mc_rdi; /* machine state (struct trapframe) */ - __register_t mc_rsi; - __register_t mc_rdx; - __register_t mc_rcx; - __register_t mc_r8; - __register_t mc_r9; - __register_t mc_rax; - __register_t mc_rbx; - __register_t mc_rbp; - __register_t mc_r10; - __register_t mc_r11; - __register_t mc_r12; - __register_t mc_r13; - __register_t mc_r14; - __register_t mc_r15; - __uint32_t mc_trapno; - __uint16_t mc_fs; - __uint16_t mc_gs; - __register_t mc_addr; - __uint32_t mc_flags; - __uint16_t mc_es; - __uint16_t mc_ds; - __register_t mc_err; - __register_t mc_rip; - __register_t mc_cs; - __register_t mc_rflags; - __register_t mc_rsp; - __register_t mc_ss; - - long mc_len; /* sizeof(mcontext_t) */ - -#define _MC_FPFMT_NODEV 0x10000 /* device not present or configured */ -#define _MC_FPFMT_XMM 0x10002 - long mc_fpformat; -#define _MC_FPOWNED_NONE 0x20000 /* FP state not used */ -#define _MC_FPOWNED_FPU 0x20001 /* FP state came from FPU */ -#define _MC_FPOWNED_PCB 0x20002 /* FP state came from PCB */ - long mc_ownedfp; - /* - * See for the internals of mc_fpstate[]. - */ - long mc_fpstate[64] __aligned(16); - - __register_t mc_fsbase; - __register_t mc_gsbase; - - __register_t mc_xfpustate; - __register_t mc_xfpustate_len; - - long mc_spare[4]; -} mcontext_t; - -#endif /* !_MACHINE_UCONTEXT_H_ */ +#include diff --git a/sys/boot/userboot/userboot/elf32_freebsd.c b/sys/boot/userboot/userboot/elf32_freebsd.c index 848938524fc..bb5b693ca31 100644 --- a/sys/boot/userboot/userboot/elf32_freebsd.c +++ b/sys/boot/userboot/userboot/elf32_freebsd.c @@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#define _MACHINE_ELF_WANT_32BIT #include #include #include diff --git a/sys/i386/include/elf.h b/sys/i386/include/elf.h index 93fa1fd8f5a..f9323775dc2 100644 --- a/sys/i386/include/elf.h +++ b/sys/i386/include/elf.h @@ -1,118 +1,6 @@ /*- - * Copyright (c) 1996-1997 John D. Polstra. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ + * This file is in the public domain. */ +/* $FreeBSD$ */ -#ifndef _MACHINE_ELF_H_ -#define _MACHINE_ELF_H_ 1 - -/* - * ELF definitions for the i386 architecture. - */ - -#include /* Definitions common to all 32 bit architectures. */ -#if defined(__ELF_WORD_SIZE) && __ELF_WORD_SIZE == 64 -#include /* Definitions common to all 64 bit architectures. */ -#endif - -#ifndef __ELF_WORD_SIZE -#define __ELF_WORD_SIZE 32 /* Used by */ -#endif - -#include - -#define ELF_ARCH EM_386 - -#define ELF_MACHINE_OK(x) ((x) == EM_386 || (x) == EM_486) - -/* - * Auxiliary vector entries for passing information to the interpreter. - * - * The i386 supplement to the SVR4 ABI specification names this "auxv_t", - * but POSIX lays claim to all symbols ending with "_t". - */ - -typedef struct { /* Auxiliary vector entry on initial stack */ - int a_type; /* Entry type. */ - union { - long a_val; /* Integer value. */ - void *a_ptr; /* Address. */ - void (*a_fcn)(void); /* Function pointer (not used). */ - } a_un; -} Elf32_Auxinfo; - -#if __ELF_WORD_SIZE == 64 -/* Fake for amd64 loader support */ -typedef struct { - int fake; -} Elf64_Auxinfo; -#endif - -__ElfType(Auxinfo); - -/* Values for a_type. */ -#define AT_NULL 0 /* Terminates the vector. */ -#define AT_IGNORE 1 /* Ignored entry. */ -#define AT_EXECFD 2 /* File descriptor of program to load. */ -#define AT_PHDR 3 /* Program header of program already loaded. */ -#define AT_PHENT 4 /* Size of each program header entry. */ -#define AT_PHNUM 5 /* Number of program header entries. */ -#define AT_PAGESZ 6 /* Page size in bytes. */ -#define AT_BASE 7 /* Interpreter's base address. */ -#define AT_FLAGS 8 /* Flags (unused for i386). */ -#define AT_ENTRY 9 /* Where interpreter should transfer control. */ -#define AT_NOTELF 10 /* Program is not ELF ?? */ -#define AT_UID 11 /* Real uid. */ -#define AT_EUID 12 /* Effective uid. */ -#define AT_GID 13 /* Real gid. */ -#define AT_EGID 14 /* Effective gid. */ -#define AT_EXECPATH 15 /* Path to the executable. */ -#define AT_CANARY 16 /* Canary for SSP. */ -#define AT_CANARYLEN 17 /* Length of the canary. */ -#define AT_OSRELDATE 18 /* OSRELDATE. */ -#define AT_NCPUS 19 /* Number of CPUs. */ -#define AT_PAGESIZES 20 /* Pagesizes. */ -#define AT_PAGESIZESLEN 21 /* Number of pagesizes. */ -#define AT_TIMEKEEP 22 /* Pointer to timehands. */ -#define AT_STACKPROT 23 /* Initial stack protection. */ - -#define AT_COUNT 24 /* Count of defined aux entry types. */ - -/* - * Relocation types. - */ - -#define R_386_COUNT 38 /* Count of defined relocation types. */ - -/* Define "machine" characteristics */ -#define ELF_TARG_CLASS ELFCLASS32 -#define ELF_TARG_DATA ELFDATA2LSB -#define ELF_TARG_MACH EM_386 -#define ELF_TARG_VER 1 - -#define ET_DYN_LOAD_ADDR 0x01001000 - -#endif /* !_MACHINE_ELF_H_ */ +#include diff --git a/sys/i386/include/frame.h b/sys/i386/include/frame.h index 3558b98d14c..0953be70087 100644 --- a/sys/i386/include/frame.h +++ b/sys/i386/include/frame.h @@ -1,100 +1,6 @@ /*- - * Copyright (c) 1990 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * William Jolitz. - * - * 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. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#)frame.h 5.2 (Berkeley) 1/18/91 - * $FreeBSD$ + * This file is in the public domain. */ +/* $FreeBSD$ */ -#ifndef _MACHINE_FRAME_H_ -#define _MACHINE_FRAME_H_ 1 - -/* - * System stack frames. - */ - -/* - * Exception/Trap Stack Frame - */ - -struct trapframe { - int tf_fs; - int tf_es; - int tf_ds; - int tf_edi; - int tf_esi; - int tf_ebp; - int tf_isp; - int tf_ebx; - int tf_edx; - int tf_ecx; - int tf_eax; - int tf_trapno; - /* below portion defined in 386 hardware */ - int tf_err; - int tf_eip; - int tf_cs; - int tf_eflags; - /* below only when crossing rings (e.g. user to kernel) */ - int tf_esp; - int tf_ss; -}; - -/* Superset of trap frame, for traps from virtual-8086 mode */ - -struct trapframe_vm86 { - int tf_fs; - int tf_es; - int tf_ds; - int tf_edi; - int tf_esi; - int tf_ebp; - int tf_isp; - int tf_ebx; - int tf_edx; - int tf_ecx; - int tf_eax; - int tf_trapno; - /* below portion defined in 386 hardware */ - int tf_err; - int tf_eip; - int tf_cs; - int tf_eflags; - /* below only when crossing rings (e.g. user to kernel) */ - int tf_esp; - int tf_ss; - /* below only when switching out of VM86 mode */ - int tf_vm86_es; - int tf_vm86_ds; - int tf_vm86_fs; - int tf_vm86_gs; -}; - -#endif /* _MACHINE_FRAME_H_ */ +#include diff --git a/sys/i386/include/sigframe.h b/sys/i386/include/sigframe.h index 98be731d8f1..8de466452e4 100644 --- a/sys/i386/include/sigframe.h +++ b/sys/i386/include/sigframe.h @@ -89,25 +89,6 @@ struct sigframe4 { #endif #endif -struct sigframe { - /* - * The first four members may be used by applications. - * - * NOTE: The 4th argument is undocumented, ill commented - * on and seems to be somewhat BSD "standard". Handlers - * installed with sigvec may be using it. - */ - register_t sf_signum; - register_t sf_siginfo; /* code or pointer to sf_si */ - register_t sf_ucontext; /* points to sf_uc */ - register_t sf_addr; /* undocumented 4th arg */ - - union { - __siginfohandler_t *sf_action; - __sighandler_t *sf_handler; - } sf_ahu; - ucontext_t sf_uc; /* = *sf_ucontext */ - siginfo_t sf_si; /* = *sf_siginfo (SA_SIGINFO case) */ -}; +#include #endif /* !_MACHINE_SIGFRAME_H_ */ diff --git a/sys/i386/include/signal.h b/sys/i386/include/signal.h index 892115b7d36..26c1ee63638 100644 --- a/sys/i386/include/signal.h +++ b/sys/i386/include/signal.h @@ -33,25 +33,7 @@ #ifndef _MACHINE_SIGNAL_H_ #define _MACHINE_SIGNAL_H_ -#include -#include - -/* - * Machine-dependent signal definitions - */ - -typedef int sig_atomic_t; - -#if __BSD_VISIBLE -#include /* codes for SIGILL, SIGFPE */ - -/* - * Information pushed on stack when a signal is delivered. - * This is used by the kernel to restore state following - * execution of the signal handler. It is also made available - * to the handler to allow it to restore state properly if - * a non-standard exit is performed. - */ +#include #if defined(_KERNEL) && defined(COMPAT_43) /* @@ -82,57 +64,4 @@ struct osigcontext { }; #endif -/* - * The sequence of the fields/registers in struct sigcontext should match - * those in mcontext_t and struct trapframe. - */ -struct sigcontext { - struct __sigset sc_mask; /* signal mask to restore */ - int sc_onstack; /* sigstack state to restore */ - int sc_gs; /* machine state (struct trapframe) */ - int sc_fs; - int sc_es; - int sc_ds; - int sc_edi; - int sc_esi; - int sc_ebp; - int sc_isp; - int sc_ebx; - int sc_edx; - int sc_ecx; - int sc_eax; - int sc_trapno; - int sc_err; - int sc_eip; - int sc_cs; - int sc_efl; - int sc_esp; - int sc_ss; - int sc_len; /* sizeof(mcontext_t) */ - /* - * See and for - * the following fields. - */ - int sc_fpformat; - int sc_ownedfp; - int sc_flags; - int sc_fpstate[128] __aligned(16); - - int sc_fsbase; - int sc_gsbase; - - int sc_xfpustate; - int sc_xfpustate_len; - - int sc_spare2[4]; -}; - -#define sc_sp sc_esp -#define sc_fp sc_ebp -#define sc_pc sc_eip -#define sc_ps sc_efl -#define sc_eflags sc_efl - -#endif /* __BSD_VISIBLE */ - #endif /* !_MACHINE_SIGNAL_H_ */ diff --git a/sys/i386/include/ucontext.h b/sys/i386/include/ucontext.h index 79aabd755fc..fe21b346266 100644 --- a/sys/i386/include/ucontext.h +++ b/sys/i386/include/ucontext.h @@ -31,64 +31,6 @@ #ifndef _MACHINE_UCONTEXT_H_ #define _MACHINE_UCONTEXT_H_ -/* Keep _MC_* values similar to amd64 */ -#define _MC_HASSEGS 0x1 -#define _MC_HASBASES 0x2 -#define _MC_HASFPXSTATE 0x4 -#define _MC_FLAG_MASK (_MC_HASSEGS | _MC_HASBASES | _MC_HASFPXSTATE) - -typedef struct __mcontext { - /* - * The definition of mcontext_t must match the layout of - * struct sigcontext after the sc_mask member. This is so - * that we can support sigcontext and ucontext_t at the same - * time. - */ - __register_t mc_onstack; /* XXX - sigcontext compat. */ - __register_t mc_gs; /* machine state (struct trapframe) */ - __register_t mc_fs; - __register_t mc_es; - __register_t mc_ds; - __register_t mc_edi; - __register_t mc_esi; - __register_t mc_ebp; - __register_t mc_isp; - __register_t mc_ebx; - __register_t mc_edx; - __register_t mc_ecx; - __register_t mc_eax; - __register_t mc_trapno; - __register_t mc_err; - __register_t mc_eip; - __register_t mc_cs; - __register_t mc_eflags; - __register_t mc_esp; - __register_t mc_ss; - - int mc_len; /* sizeof(mcontext_t) */ -#define _MC_FPFMT_NODEV 0x10000 /* device not present or configured */ -#define _MC_FPFMT_387 0x10001 -#define _MC_FPFMT_XMM 0x10002 - int mc_fpformat; -#define _MC_FPOWNED_NONE 0x20000 /* FP state not used */ -#define _MC_FPOWNED_FPU 0x20001 /* FP state came from FPU */ -#define _MC_FPOWNED_PCB 0x20002 /* FP state came from PCB */ - int mc_ownedfp; - __register_t mc_flags; - /* - * See for the internals of mc_fpstate[]. - */ - int mc_fpstate[128] __aligned(16); - - __register_t mc_fsbase; - __register_t mc_gsbase; - - __register_t mc_xfpustate; - __register_t mc_xfpustate_len; - - int mc_spare2[4]; -} mcontext_t; - #if defined(_KERNEL) && defined(COMPAT_FREEBSD4) struct mcontext4 { __register_t mc_onstack; /* XXX - sigcontext compat. */ @@ -116,4 +58,6 @@ struct mcontext4 { }; #endif +#include + #endif /* !_MACHINE_UCONTEXT_H_ */ diff --git a/sys/x86/include/elf.h b/sys/x86/include/elf.h new file mode 100644 index 00000000000..cde395b30bf --- /dev/null +++ b/sys/x86/include/elf.h @@ -0,0 +1,215 @@ +/*- + * Copyright (c) 1996-1997 John D. Polstra. + * 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 _MACHINE_ELF_H_ +#define _MACHINE_ELF_H_ 1 + +#if defined(__i386__) || defined(_MACHINE_ELF_WANT_32BIT) + +/* + * ELF definitions for the i386 architecture. + */ + +#include /* Definitions common to all 32 bit architectures. */ +#if defined(__ELF_WORD_SIZE) && __ELF_WORD_SIZE == 64 +#include /* Definitions common to all 64 bit architectures. */ +#endif + +#ifndef __ELF_WORD_SIZE +#define __ELF_WORD_SIZE 32 /* Used by */ +#endif + +#include + +#define ELF_ARCH EM_386 + +#define ELF_MACHINE_OK(x) ((x) == EM_386 || (x) == EM_486) + +/* + * Auxiliary vector entries for passing information to the interpreter. + * + * The i386 supplement to the SVR4 ABI specification names this "auxv_t", + * but POSIX lays claim to all symbols ending with "_t". + */ + +typedef struct { /* Auxiliary vector entry on initial stack */ + int a_type; /* Entry type. */ + union { + long a_val; /* Integer value. */ + void *a_ptr; /* Address. */ + void (*a_fcn)(void); /* Function pointer (not used). */ + } a_un; +} Elf32_Auxinfo; + +#if __ELF_WORD_SIZE == 64 +/* Fake for amd64 loader support */ +typedef struct { + int fake; +} Elf64_Auxinfo; +#endif + +__ElfType(Auxinfo); + +/* Values for a_type. */ +#define AT_NULL 0 /* Terminates the vector. */ +#define AT_IGNORE 1 /* Ignored entry. */ +#define AT_EXECFD 2 /* File descriptor of program to load. */ +#define AT_PHDR 3 /* Program header of program already loaded. */ +#define AT_PHENT 4 /* Size of each program header entry. */ +#define AT_PHNUM 5 /* Number of program header entries. */ +#define AT_PAGESZ 6 /* Page size in bytes. */ +#define AT_BASE 7 /* Interpreter's base address. */ +#define AT_FLAGS 8 /* Flags (unused for i386). */ +#define AT_ENTRY 9 /* Where interpreter should transfer control. */ +#define AT_NOTELF 10 /* Program is not ELF ?? */ +#define AT_UID 11 /* Real uid. */ +#define AT_EUID 12 /* Effective uid. */ +#define AT_GID 13 /* Real gid. */ +#define AT_EGID 14 /* Effective gid. */ +#define AT_EXECPATH 15 /* Path to the executable. */ +#define AT_CANARY 16 /* Canary for SSP. */ +#define AT_CANARYLEN 17 /* Length of the canary. */ +#define AT_OSRELDATE 18 /* OSRELDATE. */ +#define AT_NCPUS 19 /* Number of CPUs. */ +#define AT_PAGESIZES 20 /* Pagesizes. */ +#define AT_PAGESIZESLEN 21 /* Number of pagesizes. */ +#define AT_TIMEKEEP 22 /* Pointer to timehands. */ +#define AT_STACKPROT 23 /* Initial stack protection. */ + +#define AT_COUNT 24 /* Count of defined aux entry types. */ + +/* + * Relocation types. + */ + +#define R_386_COUNT 38 /* Count of defined relocation types. */ + +/* Define "machine" characteristics */ +#define ELF_TARG_CLASS ELFCLASS32 +#define ELF_TARG_DATA ELFDATA2LSB +#define ELF_TARG_MACH EM_386 +#define ELF_TARG_VER 1 + +#define ET_DYN_LOAD_ADDR 0x01001000 + +#elif defined(__amd64__) + +/* + * ELF definitions for the AMD64 architecture. + */ + +#ifndef __ELF_WORD_SIZE +#define __ELF_WORD_SIZE 64 /* Used by */ +#endif +#include /* Definitions common to all 32 bit architectures. */ +#include /* Definitions common to all 64 bit architectures. */ +#include + +#define ELF_ARCH EM_X86_64 +#define ELF_ARCH32 EM_386 + +#define ELF_MACHINE_OK(x) ((x) == EM_X86_64) + +/* + * Auxiliary vector entries for passing information to the interpreter. + * + * The i386 supplement to the SVR4 ABI specification names this "auxv_t", + * but POSIX lays claim to all symbols ending with "_t". + */ +typedef struct { /* Auxiliary vector entry on initial stack */ + int a_type; /* Entry type. */ + union { + int a_val; /* Integer value. */ + } a_un; +} Elf32_Auxinfo; + + +typedef struct { /* Auxiliary vector entry on initial stack */ + long a_type; /* Entry type. */ + union { + long a_val; /* Integer value. */ + void *a_ptr; /* Address. */ + void (*a_fcn)(void); /* Function pointer (not used). */ + } a_un; +} Elf64_Auxinfo; + +__ElfType(Auxinfo); + +/* Values for a_type. */ +#define AT_NULL 0 /* Terminates the vector. */ +#define AT_IGNORE 1 /* Ignored entry. */ +#define AT_EXECFD 2 /* File descriptor of program to load. */ +#define AT_PHDR 3 /* Program header of program already loaded. */ +#define AT_PHENT 4 /* Size of each program header entry. */ +#define AT_PHNUM 5 /* Number of program header entries. */ +#define AT_PAGESZ 6 /* Page size in bytes. */ +#define AT_BASE 7 /* Interpreter's base address. */ +#define AT_FLAGS 8 /* Flags (unused for i386). */ +#define AT_ENTRY 9 /* Where interpreter should transfer control. */ +#define AT_NOTELF 10 /* Program is not ELF ?? */ +#define AT_UID 11 /* Real uid. */ +#define AT_EUID 12 /* Effective uid. */ +#define AT_GID 13 /* Real gid. */ +#define AT_EGID 14 /* Effective gid. */ +#define AT_EXECPATH 15 /* Path to the executable. */ +#define AT_CANARY 16 /* Canary for SSP */ +#define AT_CANARYLEN 17 /* Length of the canary. */ +#define AT_OSRELDATE 18 /* OSRELDATE. */ +#define AT_NCPUS 19 /* Number of CPUs. */ +#define AT_PAGESIZES 20 /* Pagesizes. */ +#define AT_PAGESIZESLEN 21 /* Number of pagesizes. */ +#define AT_TIMEKEEP 22 /* Pointer to timehands. */ +#define AT_STACKPROT 23 /* Initial stack protection. */ + +#define AT_COUNT 24 /* Count of defined aux entry types. */ + +/* + * Relocation types. + */ + +#define R_X86_64_COUNT 24 /* Count of defined relocation types. */ + +/* Define "machine" characteristics */ +#if __ELF_WORD_SIZE == 32 +#define ELF_TARG_CLASS ELFCLASS32 +#else +#define ELF_TARG_CLASS ELFCLASS64 +#endif +#define ELF_TARG_DATA ELFDATA2LSB +#define ELF_TARG_MACH EM_X86_64 +#define ELF_TARG_VER 1 + +#if __ELF_WORD_SIZE == 32 +#define ET_DYN_LOAD_ADDR 0x01001000 +#else +#define ET_DYN_LOAD_ADDR 0x01021000 +#endif + +#endif /* __i386__, __amd64__ */ + +#endif /* !_MACHINE_ELF_H_ */ diff --git a/sys/x86/include/frame.h b/sys/x86/include/frame.h new file mode 100644 index 00000000000..a32ef7c9bee --- /dev/null +++ b/sys/x86/include/frame.h @@ -0,0 +1,148 @@ +/*- + * Copyright (c) 2003 Peter Wemm. + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * 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. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)frame.h 5.2 (Berkeley) 1/18/91 + * $FreeBSD$ + */ + +#ifndef _MACHINE_FRAME_H_ +#define _MACHINE_FRAME_H_ 1 + +/* + * System stack frames. + */ + +#ifdef __i386__ +/* + * Exception/Trap Stack Frame + */ + +struct trapframe { + int tf_fs; + int tf_es; + int tf_ds; + int tf_edi; + int tf_esi; + int tf_ebp; + int tf_isp; + int tf_ebx; + int tf_edx; + int tf_ecx; + int tf_eax; + int tf_trapno; + /* below portion defined in 386 hardware */ + int tf_err; + int tf_eip; + int tf_cs; + int tf_eflags; + /* below only when crossing rings (e.g. user to kernel) */ + int tf_esp; + int tf_ss; +}; + +/* Superset of trap frame, for traps from virtual-8086 mode */ + +struct trapframe_vm86 { + int tf_fs; + int tf_es; + int tf_ds; + int tf_edi; + int tf_esi; + int tf_ebp; + int tf_isp; + int tf_ebx; + int tf_edx; + int tf_ecx; + int tf_eax; + int tf_trapno; + /* below portion defined in 386 hardware */ + int tf_err; + int tf_eip; + int tf_cs; + int tf_eflags; + /* below only when crossing rings (e.g. user to kernel) */ + int tf_esp; + int tf_ss; + /* below only when switching out of VM86 mode */ + int tf_vm86_es; + int tf_vm86_ds; + int tf_vm86_fs; + int tf_vm86_gs; +}; +#endif /* __i386__ */ + +#ifdef __amd64__ +/* + * Exception/Trap Stack Frame + * + * The ordering of this is specifically so that we can take first 6 + * the syscall arguments directly from the beginning of the frame. + */ + +struct trapframe { + register_t tf_rdi; + register_t tf_rsi; + register_t tf_rdx; + register_t tf_rcx; + register_t tf_r8; + register_t tf_r9; + register_t tf_rax; + register_t tf_rbx; + register_t tf_rbp; + register_t tf_r10; + register_t tf_r11; + register_t tf_r12; + register_t tf_r13; + register_t tf_r14; + register_t tf_r15; + uint32_t tf_trapno; + uint16_t tf_fs; + uint16_t tf_gs; + register_t tf_addr; + uint32_t tf_flags; + uint16_t tf_es; + uint16_t tf_ds; + /* below portion defined in hardware */ + register_t tf_err; + register_t tf_rip; + register_t tf_cs; + register_t tf_rflags; + register_t tf_rsp; + register_t tf_ss; +}; + +#define TF_HASSEGS 0x1 +#define TF_HASBASES 0x2 +#define TF_HASFPXSTATE 0x4 +#endif /* __amd64__ */ + +#endif /* _MACHINE_FRAME_H_ */ diff --git a/sys/x86/include/sigframe.h b/sys/x86/include/sigframe.h new file mode 100644 index 00000000000..972a78e9bba --- /dev/null +++ b/sys/x86/include/sigframe.h @@ -0,0 +1,72 @@ +/*- + * Copyright (c) 1999 Marcel Moolenaar + * 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 + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _X86_SIGFRAME_H_ +#define _X86_SIGFRAME_H_ + +/* + * Signal frames, arguments passed to application signal handlers. + */ + +#ifdef __i386__ +struct sigframe { + /* + * The first four members may be used by applications. + * + * NOTE: The 4th argument is undocumented, ill commented + * on and seems to be somewhat BSD "standard". Handlers + * installed with sigvec may be using it. + */ + register_t sf_signum; + register_t sf_siginfo; /* code or pointer to sf_si */ + register_t sf_ucontext; /* points to sf_uc */ + register_t sf_addr; /* undocumented 4th arg */ + + union { + __siginfohandler_t *sf_action; + __sighandler_t *sf_handler; + } sf_ahu; + ucontext_t sf_uc; /* = *sf_ucontext */ + siginfo_t sf_si; /* = *sf_siginfo (SA_SIGINFO case) */ +}; +#endif /* __i386__ */ + +#ifdef __amd64__ +struct sigframe { + union { + __siginfohandler_t *sf_action; + __sighandler_t *sf_handler; + } sf_ahu; + ucontext_t sf_uc; /* = *sf_ucontext */ + siginfo_t sf_si; /* = *sf_siginfo (SA_SIGINFO case) */ +}; +#endif /* __amd64__ */ + +#endif /* _X86_SIGFRAME_H_ */ diff --git a/sys/x86/include/signal.h b/sys/x86/include/signal.h new file mode 100644 index 00000000000..dee908f82b9 --- /dev/null +++ b/sys/x86/include/signal.h @@ -0,0 +1,167 @@ +/*- + * Copyright (c) 1986, 1989, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 2003 Peter Wemm. + * + * 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. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)signal.h 8.1 (Berkeley) 6/11/93 + * $FreeBSD$ + */ + +#ifndef _X86_SIGNAL_H +#define _X86_SIGNAL_H 1 + +/* + * Machine-dependent signal definitions + */ + +#include +#include + +#if __BSD_VISIBLE +#include /* codes for SIGILL, SIGFPE */ +#endif + +#ifdef __i386__ +typedef int sig_atomic_t; + +#if __BSD_VISIBLE +struct sigcontext { + struct __sigset sc_mask; /* signal mask to restore */ + int sc_onstack; /* sigstack state to restore */ + int sc_gs; /* machine state (struct trapframe) */ + int sc_fs; + int sc_es; + int sc_ds; + int sc_edi; + int sc_esi; + int sc_ebp; + int sc_isp; + int sc_ebx; + int sc_edx; + int sc_ecx; + int sc_eax; + int sc_trapno; + int sc_err; + int sc_eip; + int sc_cs; + int sc_efl; + int sc_esp; + int sc_ss; + int sc_len; /* sizeof(mcontext_t) */ + /* + * See and for + * the following fields. + */ + int sc_fpformat; + int sc_ownedfp; + int sc_flags; + int sc_fpstate[128] __aligned(16); + + int sc_fsbase; + int sc_gsbase; + + int sc_xfpustate; + int sc_xfpustate_len; + + int sc_spare2[4]; +}; + +#define sc_sp sc_esp +#define sc_fp sc_ebp +#define sc_pc sc_eip +#define sc_ps sc_efl +#define sc_eflags sc_efl + +#endif /* __BSD_VISIBLE */ +#endif /* __i386__ */ + +#ifdef __amd64__ +typedef long sig_atomic_t; + +#if __BSD_VISIBLE +/* + * Information pushed on stack when a signal is delivered. + * This is used by the kernel to restore state following + * execution of the signal handler. It is also made available + * to the handler to allow it to restore state properly if + * a non-standard exit is performed. + * + * The sequence of the fields/registers after sc_mask in struct + * sigcontext must match those in mcontext_t and struct trapframe. + */ +struct sigcontext { + struct __sigset sc_mask; /* signal mask to restore */ + long sc_onstack; /* sigstack state to restore */ + long sc_rdi; /* machine state (struct trapframe) */ + long sc_rsi; + long sc_rdx; + long sc_rcx; + long sc_r8; + long sc_r9; + long sc_rax; + long sc_rbx; + long sc_rbp; + long sc_r10; + long sc_r11; + long sc_r12; + long sc_r13; + long sc_r14; + long sc_r15; + int sc_trapno; + short sc_fs; + short sc_gs; + long sc_addr; + int sc_flags; + short sc_es; + short sc_ds; + long sc_err; + long sc_rip; + long sc_cs; + long sc_rflags; + long sc_rsp; + long sc_ss; + long sc_len; /* sizeof(mcontext_t) */ + /* + * See and for the following + * fields. + */ + long sc_fpformat; + long sc_ownedfp; + long sc_fpstate[64] __aligned(16); + + long sc_fsbase; + long sc_gsbase; + + long sc_xfpustate; + long sc_xfpustate_len; + + long sc_spare[4]; +}; +#endif /* __BSD_VISIBLE */ +#endif /* __amd64__ */ + +#endif diff --git a/sys/x86/include/ucontext.h b/sys/x86/include/ucontext.h new file mode 100644 index 00000000000..2173efd590c --- /dev/null +++ b/sys/x86/include/ucontext.h @@ -0,0 +1,165 @@ +/*- + * Copyright (c) 2003 Peter Wemm + * Copyright (c) 1999 Marcel Moolenaar + * 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 + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _X86_UCONTEXT_H_ +#define _X86_UCONTEXT_H_ + +#ifdef __i386__ +/* Keep _MC_* values similar to amd64 */ +#define _MC_HASSEGS 0x1 +#define _MC_HASBASES 0x2 +#define _MC_HASFPXSTATE 0x4 +#define _MC_FLAG_MASK (_MC_HASSEGS | _MC_HASBASES | _MC_HASFPXSTATE) + +typedef struct __mcontext { + /* + * The definition of mcontext_t must match the layout of + * struct sigcontext after the sc_mask member. This is so + * that we can support sigcontext and ucontext_t at the same + * time. + */ + __register_t mc_onstack; /* XXX - sigcontext compat. */ + __register_t mc_gs; /* machine state (struct trapframe) */ + __register_t mc_fs; + __register_t mc_es; + __register_t mc_ds; + __register_t mc_edi; + __register_t mc_esi; + __register_t mc_ebp; + __register_t mc_isp; + __register_t mc_ebx; + __register_t mc_edx; + __register_t mc_ecx; + __register_t mc_eax; + __register_t mc_trapno; + __register_t mc_err; + __register_t mc_eip; + __register_t mc_cs; + __register_t mc_eflags; + __register_t mc_esp; + __register_t mc_ss; + + int mc_len; /* sizeof(mcontext_t) */ +#define _MC_FPFMT_NODEV 0x10000 /* device not present or configured */ +#define _MC_FPFMT_387 0x10001 +#define _MC_FPFMT_XMM 0x10002 + int mc_fpformat; +#define _MC_FPOWNED_NONE 0x20000 /* FP state not used */ +#define _MC_FPOWNED_FPU 0x20001 /* FP state came from FPU */ +#define _MC_FPOWNED_PCB 0x20002 /* FP state came from PCB */ + int mc_ownedfp; + __register_t mc_flags; + /* + * See for the internals of mc_fpstate[]. + */ + int mc_fpstate[128] __aligned(16); + + __register_t mc_fsbase; + __register_t mc_gsbase; + + __register_t mc_xfpustate; + __register_t mc_xfpustate_len; + + int mc_spare2[4]; +} mcontext_t; +#endif /* __i386__ */ + +#ifdef __amd64__ +/* + * mc_trapno bits. Shall be in sync with TF_XXX. + */ +#define _MC_HASSEGS 0x1 +#define _MC_HASBASES 0x2 +#define _MC_HASFPXSTATE 0x4 +#define _MC_FLAG_MASK (_MC_HASSEGS | _MC_HASBASES | _MC_HASFPXSTATE) + +typedef struct __mcontext { + /* + * The definition of mcontext_t must match the layout of + * struct sigcontext after the sc_mask member. This is so + * that we can support sigcontext and ucontext_t at the same + * time. + */ + __register_t mc_onstack; /* XXX - sigcontext compat. */ + __register_t mc_rdi; /* machine state (struct trapframe) */ + __register_t mc_rsi; + __register_t mc_rdx; + __register_t mc_rcx; + __register_t mc_r8; + __register_t mc_r9; + __register_t mc_rax; + __register_t mc_rbx; + __register_t mc_rbp; + __register_t mc_r10; + __register_t mc_r11; + __register_t mc_r12; + __register_t mc_r13; + __register_t mc_r14; + __register_t mc_r15; + __uint32_t mc_trapno; + __uint16_t mc_fs; + __uint16_t mc_gs; + __register_t mc_addr; + __uint32_t mc_flags; + __uint16_t mc_es; + __uint16_t mc_ds; + __register_t mc_err; + __register_t mc_rip; + __register_t mc_cs; + __register_t mc_rflags; + __register_t mc_rsp; + __register_t mc_ss; + + long mc_len; /* sizeof(mcontext_t) */ + +#define _MC_FPFMT_NODEV 0x10000 /* device not present or configured */ +#define _MC_FPFMT_XMM 0x10002 + long mc_fpformat; +#define _MC_FPOWNED_NONE 0x20000 /* FP state not used */ +#define _MC_FPOWNED_FPU 0x20001 /* FP state came from FPU */ +#define _MC_FPOWNED_PCB 0x20002 /* FP state came from PCB */ + long mc_ownedfp; + /* + * See for the internals of mc_fpstate[]. + */ + long mc_fpstate[64] __aligned(16); + + __register_t mc_fsbase; + __register_t mc_gsbase; + + __register_t mc_xfpustate; + __register_t mc_xfpustate_len; + + long mc_spare[4]; +} mcontext_t; +#endif /* __amd64__ */ + +#endif /* !_X86_UCONTEXT_H_ */ From cf4e0cc15ed384be7564c81ee181d66e46093e91 Mon Sep 17 00:00:00 2001 From: "Justin T. Gibbs" Date: Wed, 20 Feb 2013 17:46:38 +0000 Subject: [PATCH 0305/1476] Orphaned processes that are being traced are killed by the kernel. Properly restore, continue, and detach from processes being DTraced when DTrace exits with an error so the program being inspected is not terminated. cddl/contrib/opensolaris/cmd/dtrace/dtrace.c: In fatal(), the generic error handler, close the DTrace handle as is done in the "probe/script" error handler dfatal(). fatal() can be invoked after DTrace attaches to processes (e.g. a script specified by command line argument can't be found) and closing the handle will release them. Submitted by: Spectra Logic Corporation Reviewed by: rpaulo, gnn --- cddl/contrib/opensolaris/cmd/dtrace/dtrace.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cddl/contrib/opensolaris/cmd/dtrace/dtrace.c b/cddl/contrib/opensolaris/cmd/dtrace/dtrace.c index a2766593607..cc7959f99cd 100644 --- a/cddl/contrib/opensolaris/cmd/dtrace/dtrace.c +++ b/cddl/contrib/opensolaris/cmd/dtrace/dtrace.c @@ -195,6 +195,13 @@ fatal(const char *fmt, ...) verror(fmt, ap); va_end(ap); + /* + * Close the DTrace handle to ensure that any controlled processes are + * correctly restored and continued. + */ + if (g_dtp) + dtrace_close(g_dtp); + exit(E_ERROR); } From 6a8f90edf538421f5885ba99da2184a20a774dfa Mon Sep 17 00:00:00 2001 From: "Justin T. Gibbs" Date: Wed, 20 Feb 2013 17:55:17 +0000 Subject: [PATCH 0306/1476] Avoid panic when tearing down the DTrace pid provider for a process that has crashed. sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c: In fasttrap_pid_disable(), we cannot PHOLD the proc structure for a process that no longer exists, but we still have other, fasttrap specific, state that must be cleaned up for probes that existed in the dead process. Instead of returning early if the process related to our probes isn't found, conditionalize the locking and carry on with a NULL proc pointer. The rest of the fasttrap code already understands that a NULL proc is possible and does the right things in this case. Sponsored by: Spectra Logic Corporation Reviewed by: rpaulo, gnn MFC after: 1 week --- .../opensolaris/uts/common/dtrace/fasttrap.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c b/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c index 4599a3238b0..ad3b2d5c13c 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c +++ b/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c @@ -1124,14 +1124,12 @@ fasttrap_pid_disable(void *arg, dtrace_id_t id, void *parg) * provider lock as a point of mutual exclusion to prevent other * DTrace consumers from disabling this probe. */ - if ((p = pfind(probe->ftp_pid)) == NULL) { - mutex_exit(&provider->ftp_mtx); - return; - } + if ((p = pfind(probe->ftp_pid)) != NULL) { #ifdef __FreeBSD__ - _PHOLD(p); - PROC_UNLOCK(p); + _PHOLD(p); + PROC_UNLOCK(p); #endif + } /* * Disable all the associated tracepoints (for fully enabled probes). @@ -1168,7 +1166,8 @@ fasttrap_pid_disable(void *arg, dtrace_id_t id, void *parg) fasttrap_pid_cleanup(); #ifdef __FreeBSD__ - PRELE(p); + if (p != NULL) + PRELE(p); #endif if (!probe->ftp_enabled) return; From 302318d549dbac9e4803c93259cc1e590776774c Mon Sep 17 00:00:00 2001 From: Giorgos Keramidas Date: Wed, 20 Feb 2013 18:31:55 +0000 Subject: [PATCH 0307/1476] Various improvements to the qsort(3) usage example: - Remove unused #include. - Do not cast away const. - Use the canonical idiom to compare two numbers. - Use proper type for sizes, i.e. size_t instead of int. - Correct indentation. - Simplify printf("\n") to puts(""). - Use return instead of exit() in main(). Submitted by: Christoph Mallon, christoph.mallon at gmx.de Approved by: gjb (mentor) Reviewed by: stefanf MFC after: 1 week --- lib/libc/stdlib/qsort.3 | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/lib/libc/stdlib/qsort.3 b/lib/libc/stdlib/qsort.3 index 83d914021d6..a39517fb03a 100644 --- a/lib/libc/stdlib/qsort.3 +++ b/lib/libc/stdlib/qsort.3 @@ -220,7 +220,6 @@ and then prints the sorted array to standard output is: .Bd -literal #include #include -#include /* * Custom comparison function that can compare 'int' values through pointers @@ -229,15 +228,10 @@ and then prints the sorted array to standard output is: static int int_compare(const void *p1, const void *p2) { - int *left = (int *)p1; - int *right = (int *)p2; + int left = *(const int *)p1; + int right = *(const int *)p2; - if (*left < *right) - return (-1); - else if (*left > *right) - return (1); - else - return (0); + return ((left > right) - (left < right)); } /* @@ -247,14 +241,14 @@ int main(void) { int int_array[] = { 4, 5, 9, 3, 0, 1, 7, 2, 8, 6 }; - const int array_size = sizeof(int_array) / sizeof(int_array[0]); - int k; + const size_t array_size = sizeof(int_array) / sizeof(int_array[0]); + size_t k; - qsort(&int_array, array_size, sizeof(int), int_compare); + qsort(&int_array, array_size, sizeof(int_array[0]), int_compare); for (k = 0; k < array_size; k++) printf(" %d", int_array[k]); - printf("\\n"); - exit(EXIT_SUCCESS); + puts(""); + return (EXIT_SUCCESS); } .Ed .Sh ERRORS From 954349a63c1afb1aef157e223eefa33668d53691 Mon Sep 17 00:00:00 2001 From: Joel Dahl Date: Wed, 20 Feb 2013 19:05:13 +0000 Subject: [PATCH 0308/1476] Sort sections. --- lib/libc/stdlib/qsort.3 | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/libc/stdlib/qsort.3 b/lib/libc/stdlib/qsort.3 index a39517fb03a..f34d260b7fc 100644 --- a/lib/libc/stdlib/qsort.3 +++ b/lib/libc/stdlib/qsort.3 @@ -205,12 +205,6 @@ functions return no value. .Pp .Rv -std heapsort mergesort -.Sh COMPATIBILITY -Previous versions of -.Fn qsort -did not permit the comparison routine itself to call -.Fn qsort 3 . -This is no longer true. .Sh EXAMPLES A sample program that sorts an array of .Vt int @@ -251,6 +245,12 @@ main(void) return (EXIT_SUCCESS); } .Ed +.Sh COMPATIBILITY +Previous versions of +.Fn qsort +did not permit the comparison routine itself to call +.Fn qsort 3 . +This is no longer true. .Sh ERRORS The .Fn heapsort From 1f0ed3c00ee1011cd97a7eddb3f8d723100636dd Mon Sep 17 00:00:00 2001 From: Brooks Davis Date: Wed, 20 Feb 2013 19:32:31 +0000 Subject: [PATCH 0309/1476] Support hardlinks in manifest files by the same logic as the treewalk code. Reviewed by: marcel Sponsored by: DARPA, AFRL --- usr.sbin/makefs/makefs.h | 2 ++ usr.sbin/makefs/mtree.c | 18 ++++++++++++++++++ usr.sbin/makefs/walk.c | 3 +-- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/usr.sbin/makefs/makefs.h b/usr.sbin/makefs/makefs.h index 614637620d2..c6707d93f1d 100644 --- a/usr.sbin/makefs/makefs.h +++ b/usr.sbin/makefs/makefs.h @@ -280,6 +280,8 @@ extern struct timespec start_time; struct fs; void ffs_fragacct_swap(struct fs *, int, int32_t [], int, int); +fsinode *link_check(fsinode *); + /* * Declarations for compat routines. */ diff --git a/usr.sbin/makefs/mtree.c b/usr.sbin/makefs/mtree.c index 2f2400ab26e..c90c974d6c7 100644 --- a/usr.sbin/makefs/mtree.c +++ b/usr.sbin/makefs/mtree.c @@ -779,6 +779,24 @@ read_mtree_keywords(FILE *fp, fsnode *node) return (0); } + /* + * Check for hardlinks. If the contents key is used, then the check + * will only trigger if the contents file is a link even if it is used + * by more than one file + */ + if (sb.st_nlink > 1) { + fsinode *curino; + + st->st_ino = sb.st_ino; + st->st_dev = sb.st_dev; + curino = link_check(node->inode); + if (curino != NULL) { + free(node->inode); + node->inode = curino; + node->inode->nlink++; + } + } + free(node->contents); node->contents = name; st->st_size = sb.st_size; diff --git a/usr.sbin/makefs/walk.c b/usr.sbin/makefs/walk.c index 0664c8489bc..7af92bb7e21 100644 --- a/usr.sbin/makefs/walk.c +++ b/usr.sbin/makefs/walk.c @@ -59,7 +59,6 @@ static void apply_specdir(const char *, NODE *, fsnode *, int); static void apply_specentry(const char *, NODE *, fsnode *); static fsnode *create_fsnode(const char *, const char *, const char *, struct stat *); -static fsinode *link_check(fsinode *); /* @@ -644,7 +643,7 @@ inode_type(mode_t mode) /* This was borrowed from du.c and tweaked to keep an fsnode * pointer instead. -- dbj@netbsd.org */ -static fsinode * +fsinode * link_check(fsinode *entry) { static struct entry { From 0d1fce25cb8b35228b4b1b844d7a8c1946ef13cc Mon Sep 17 00:00:00 2001 From: Ed Maste Date: Wed, 20 Feb 2013 20:42:56 +0000 Subject: [PATCH 0310/1476] Fix parallel build race with DEBUG_FLAGS Reported by: Jan Beich on freebsd-current Tested by: markj --- share/mk/bsd.lib.mk | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/share/mk/bsd.lib.mk b/share/mk/bsd.lib.mk index f406c231ade..3664210bc03 100644 --- a/share/mk/bsd.lib.mk +++ b/share/mk/bsd.lib.mk @@ -113,12 +113,20 @@ PO_FLAG=-pg all: objwarn +.if defined(SHLIB_NAME) +.if defined(DEBUG_FLAGS) +SHLIB_NAME_FULL=${SHLIB_NAME}.debug +.else +SHLIB_NAME_FULL=${SHLIB_NAME} +.endif +.endif + .include # Allow libraries to specify their own version map or have it # automatically generated (see bsd.symver.mk above). .if ${MK_SYMVER} == "yes" && !empty(VERSION_MAP) -${SHLIB_NAME}: ${VERSION_MAP} +${SHLIB_NAME_FULL}: ${VERSION_MAP} LDFLAGS+= -Wl,--version-script=${VERSION_MAP} .endif @@ -165,12 +173,6 @@ SOBJS+= ${OBJS:.o=.So} .if defined(SHLIB_NAME) _LIBS+= ${SHLIB_NAME} -.if defined(DEBUG_FLAGS) -SHLIB_NAME_FULL=${SHLIB_NAME}.debug -.else -SHLIB_NAME_FULL=${SHLIB_NAME} -.endif - SOLINKOPTS= -shared -Wl,-x .if !defined(ALLOW_SHARED_TEXTREL) SOLINKOPTS+= -Wl,--fatal-warnings -Wl,--warn-shared-textrel From cdc1296734c8dd8c98518ec2c6763ce37fac0a7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Wed, 20 Feb 2013 21:16:50 +0000 Subject: [PATCH 0311/1476] revert 247035 --- sys/dev/ixgbe/ixgbe_phy.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/sys/dev/ixgbe/ixgbe_phy.c b/sys/dev/ixgbe/ixgbe_phy.c index 4a1e3a12197..3f262f9b3b2 100644 --- a/sys/dev/ixgbe/ixgbe_phy.c +++ b/sys/dev/ixgbe/ixgbe_phy.c @@ -1194,23 +1194,25 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) /* Make sure we're a supported PHY type */ if (hw->phy.type == ixgbe_phy_sfp_intel) { status = IXGBE_SUCCESS; - } else if (hw->allow_unsupported_sfp == TRUE) { - EWARN(hw, "WARNING: Intel (R) Network " - "Connections are quality tested " - "using Intel (R) Ethernet Optics." - " Using untested modules is not " - "supported and may cause unstable" - " operation or damage to the " - "module or the adapter. Intel " - "Corporation is not responsible " - "for any harm caused by using " - "untested modules.\n", status); - status = IXGBE_SUCCESS; } else { - DEBUGOUT("SFP+ module not supported\n"); - hw->phy.type = - ixgbe_phy_sfp_unsupported; - status = IXGBE_ERR_SFP_NOT_SUPPORTED; + if (hw->allow_unsupported_sfp == TRUE) { + EWARN(hw, "WARNING: Intel (R) Network " + "Connections are quality tested " + "using Intel (R) Ethernet Optics." + " Using untested modules is not " + "supported and may cause unstable" + " operation or damage to the " + "module or the adapter. Intel " + "Corporation is not responsible " + "for any harm caused by using " + "untested modules.\n", status); + status = IXGBE_SUCCESS; + } else { + DEBUGOUT("SFP+ module not supported\n"); + hw->phy.type = + ixgbe_phy_sfp_unsupported; + status = IXGBE_ERR_SFP_NOT_SUPPORTED; + } } } else { status = IXGBE_SUCCESS; From c2e38b5216eed0746da75ade721d85e2d7b6fb9d Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Wed, 20 Feb 2013 22:20:49 +0000 Subject: [PATCH 0312/1476] Remove the unused spl functions: spl0, splsoftcam, splsofttty, splsofttq and splstatclock. Other used spl functions to follow. --- sys/sys/systm.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sys/sys/systm.h b/sys/sys/systm.h index dd96d70e831..d9fdef00925 100644 --- a/sys/sys/systm.h +++ b/sys/sys/systm.h @@ -324,19 +324,14 @@ caddr_t kern_timeout_callwheel_alloc(caddr_t v); void kern_timeout_callwheel_init(void); /* Stubs for obsolete functions that used to be for interrupt management */ -static __inline void spl0(void) { return; } static __inline intrmask_t splbio(void) { return 0; } static __inline intrmask_t splcam(void) { return 0; } static __inline intrmask_t splclock(void) { return 0; } static __inline intrmask_t splhigh(void) { return 0; } static __inline intrmask_t splimp(void) { return 0; } static __inline intrmask_t splnet(void) { return 0; } -static __inline intrmask_t splsoftcam(void) { return 0; } static __inline intrmask_t splsoftclock(void) { return 0; } -static __inline intrmask_t splsofttty(void) { return 0; } static __inline intrmask_t splsoftvm(void) { return 0; } -static __inline intrmask_t splsofttq(void) { return 0; } -static __inline intrmask_t splstatclock(void) { return 0; } static __inline intrmask_t spltty(void) { return 0; } static __inline intrmask_t splvm(void) { return 0; } static __inline void splx(intrmask_t ipl __unused) { return; } From ff75c36ae19dcde309ec7057535e0fac52f07bef Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Wed, 20 Feb 2013 22:51:42 +0000 Subject: [PATCH 0313/1476] Do not use deprecated functions from libarchive --- usr.sbin/pkg/pkg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usr.sbin/pkg/pkg.c b/usr.sbin/pkg/pkg.c index a3c3fec1128..32591f3dbb1 100644 --- a/usr.sbin/pkg/pkg.c +++ b/usr.sbin/pkg/pkg.c @@ -212,7 +212,7 @@ extract_pkg_static(int fd, char *p, int sz) warn("archive_read_new"); return (ret); } - archive_read_support_compression_all(a); + archive_read_support_filter_all(a); archive_read_support_format_tar(a); if (lseek(fd, 0, 0) == -1) { @@ -247,7 +247,7 @@ extract_pkg_static(int fd, char *p, int sz) warnx("fail to extract pkg-static"); cleanup: - archive_read_finish(a); + archive_read_free(a); return (ret); } From 45b56a6ba2b75a2f49e2c85188f8c71012effb4a Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Wed, 20 Feb 2013 22:59:53 +0000 Subject: [PATCH 0314/1476] When porting XTS-related code from OpenBSD I forgot to update copyright (only OpenBSD was credited in one of two commits). Fix it. Reported by: Theo de Raadt Reviewed by: Damien Miller --- sys/crypto/aesni/aesni_wrap.c | 1 + sys/opencrypto/xform.c | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/sys/crypto/aesni/aesni_wrap.c b/sys/crypto/aesni/aesni_wrap.c index 787c1a91542..3340b1fcb6c 100644 --- a/sys/crypto/aesni/aesni_wrap.c +++ b/sys/crypto/aesni/aesni_wrap.c @@ -1,4 +1,5 @@ /*- + * Copyright (C) 2008 Damien Miller * Copyright (c) 2010 Konstantin Belousov * Copyright (c) 2010-2011 Pawel Jakub Dawidek * All rights reserved. diff --git a/sys/opencrypto/xform.c b/sys/opencrypto/xform.c index 26e383c0645..bfb061b5417 100644 --- a/sys/opencrypto/xform.c +++ b/sys/opencrypto/xform.c @@ -1,8 +1,9 @@ /* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */ /*- * The authors of this code are John Ioannidis (ji@tla.org), - * Angelos D. Keromytis (kermit@csd.uch.gr) and - * Niels Provos (provos@physnet.uni-hamburg.de). + * Angelos D. Keromytis (kermit@csd.uch.gr), + * Niels Provos (provos@physnet.uni-hamburg.de) and + * Damien Miller (djm@mindrot.org). * * This code was written by John Ioannidis for BSD/OS in Athens, Greece, * in November 1995. @@ -15,11 +16,15 @@ * * Additional features in 1999 by Angelos D. Keromytis. * + * AES XTS implementation in 2008 by Damien Miller + * * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, * Angelos D. Keromytis and Niels Provos. * * Copyright (C) 2001, Angelos D. Keromytis. * + * Copyright (C) 2008, Damien Miller + * * Permission to use, copy, and modify this software with or without fee * is hereby granted, provided that this entire notice is included in * all copies of any software which is or includes a copy or From b85313804dcf1634e1c3971239435ae034f2b760 Mon Sep 17 00:00:00 2001 From: Navdeep Parhar Date: Wed, 20 Feb 2013 23:15:40 +0000 Subject: [PATCH 0315/1476] cxgbe(4): Assume that CSUM_TSO in the transmit path implies CSUM_IP and CSUM_TCP too. They are all set explicitly by the kernel usually. While here, fix an unrelated bug where hardware L4 checksum calculation was accidentally disabled for some IPv6 packets. Reported by: alfred@ MFC after: 3 days --- sys/dev/cxgbe/t4_sge.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/sys/dev/cxgbe/t4_sge.c b/sys/dev/cxgbe/t4_sge.c index 62ceec4c633..94dca53289c 100644 --- a/sys/dev/cxgbe/t4_sge.c +++ b/sys/dev/cxgbe/t4_sge.c @@ -2950,13 +2950,13 @@ write_txpkt_wr(struct port_info *pi, struct sge_txq *txq, struct mbuf *m, /* Checksum offload */ ctrl1 = 0; - if (!(m->m_pkthdr.csum_flags & CSUM_IP)) + if (!(m->m_pkthdr.csum_flags & (CSUM_IP | CSUM_TSO))) ctrl1 |= F_TXPKT_IPCSUM_DIS; if (!(m->m_pkthdr.csum_flags & (CSUM_TCP | CSUM_UDP | CSUM_UDP_IPV6 | - CSUM_TCP_IPV6))) + CSUM_TCP_IPV6 | CSUM_TSO))) ctrl1 |= F_TXPKT_L4CSUM_DIS; if (m->m_pkthdr.csum_flags & (CSUM_IP | CSUM_TCP | CSUM_UDP | - CSUM_UDP_IPV6 | CSUM_TCP_IPV6)) + CSUM_UDP_IPV6 | CSUM_TCP_IPV6 | CSUM_TSO)) txq->txcsum++; /* some hardware assistance provided */ /* VLAN tag insertion */ @@ -3152,11 +3152,13 @@ write_ulp_cpl_sgl(struct port_info *pi, struct sge_txq *txq, /* Checksum offload */ ctrl = 0; - if (!(m->m_pkthdr.csum_flags & CSUM_IP)) + if (!(m->m_pkthdr.csum_flags & (CSUM_IP | CSUM_TSO))) ctrl |= F_TXPKT_IPCSUM_DIS; - if (!(m->m_pkthdr.csum_flags & (CSUM_TCP | CSUM_UDP))) + if (!(m->m_pkthdr.csum_flags & (CSUM_TCP | CSUM_UDP | CSUM_UDP_IPV6 | + CSUM_TCP_IPV6 | CSUM_TSO))) ctrl |= F_TXPKT_L4CSUM_DIS; - if (m->m_pkthdr.csum_flags & (CSUM_IP | CSUM_TCP | CSUM_UDP)) + if (m->m_pkthdr.csum_flags & (CSUM_IP | CSUM_TCP | CSUM_UDP | + CSUM_UDP_IPV6 | CSUM_TCP_IPV6 | CSUM_TSO)) txq->txcsum++; /* some hardware assistance provided */ /* VLAN tag insertion */ From 6ab6bfe32f39c069fd03940966b2dd56d6494851 Mon Sep 17 00:00:00 2001 From: Jack F Vogel Date: Thu, 21 Feb 2013 00:25:45 +0000 Subject: [PATCH 0316/1476] Refresh on the shared code for the E1000 drivers. - bear with me, there are lots of white space changes, I would not do them, but I am a mere consumer of this stuff and if these drivers are to stay in shape they need to be taken. em driver changes: support for the new i217/i218 interfaces igb driver changes: - TX mq start has a quick turnaround to the stack - Link/media handling improvement - When link status changes happen the current flow control state will now be displayed. - A few white space/style changes. lem driver changes: - the shared code uncovered a bogus write to the RLPML register (which does not exist in this hardware) in the vlan code,this is removed. --- sys/dev/e1000/e1000_82571.c | 348 +++---- sys/dev/e1000/e1000_82575.c | 290 +++--- sys/dev/e1000/e1000_82575.h | 5 +- sys/dev/e1000/e1000_api.c | 47 +- sys/dev/e1000/e1000_api.h | 8 +- sys/dev/e1000/e1000_defines.h | 601 ++--------- sys/dev/e1000/e1000_hw.h | 32 +- sys/dev/e1000/e1000_i210.c | 140 +-- sys/dev/e1000/e1000_i210.h | 18 +- sys/dev/e1000/e1000_ich8lan.c | 1802 ++++++++++++++++++++++----------- sys/dev/e1000/e1000_ich8lan.h | 137 +-- sys/dev/e1000/e1000_mac.c | 324 ++++-- sys/dev/e1000/e1000_mac.h | 8 +- sys/dev/e1000/e1000_manage.c | 27 +- sys/dev/e1000/e1000_nvm.c | 352 +++++-- sys/dev/e1000/e1000_nvm.h | 17 +- sys/dev/e1000/e1000_osdep.h | 5 +- sys/dev/e1000/e1000_phy.c | 256 +++-- sys/dev/e1000/e1000_phy.h | 16 +- sys/dev/e1000/e1000_regs.h | 39 +- sys/dev/e1000/if_em.c | 44 +- sys/dev/e1000/if_igb.c | 106 +- sys/dev/e1000/if_lem.c | 4 - 23 files changed, 2529 insertions(+), 2097 deletions(-) diff --git a/sys/dev/e1000/e1000_82571.c b/sys/dev/e1000/e1000_82571.c index 30015c1eaa4..ca7a1d021f7 100644 --- a/sys/dev/e1000/e1000_82571.c +++ b/sys/dev/e1000/e1000_82571.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2011, Intel Corporation + Copyright (c) 2001-2013, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -32,8 +32,7 @@ ******************************************************************************/ /*$FreeBSD$*/ -/* - * 82571EB Gigabit Ethernet Controller +/* 82571EB Gigabit Ethernet Controller * 82571EB Gigabit Ethernet Controller (Copper) * 82571EB Gigabit Ethernet Controller (Fiber) * 82571EB Dual Port Gigabit Mezzanine Adapter @@ -51,9 +50,6 @@ #include "e1000_api.h" -static s32 e1000_init_phy_params_82571(struct e1000_hw *hw); -static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw); -static s32 e1000_init_mac_params_82571(struct e1000_hw *hw); static s32 e1000_acquire_nvm_82571(struct e1000_hw *hw); static void e1000_release_nvm_82571(struct e1000_hw *hw); static s32 e1000_write_nvm_82571(struct e1000_hw *hw, u16 offset, @@ -78,7 +74,6 @@ static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw); static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw); static s32 e1000_get_phy_id_82571(struct e1000_hw *hw); static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw); -static s32 e1000_get_hw_semaphore_82573(struct e1000_hw *hw); static void e1000_put_hw_semaphore_82573(struct e1000_hw *hw); static s32 e1000_get_hw_semaphore_82574(struct e1000_hw *hw); static void e1000_put_hw_semaphore_82574(struct e1000_hw *hw); @@ -99,13 +94,13 @@ static void e1000_power_down_phy_copper_82571(struct e1000_hw *hw); static s32 e1000_init_phy_params_82571(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; + s32 ret_val; DEBUGFUNC("e1000_init_phy_params_82571"); if (hw->phy.media_type != e1000_media_type_copper) { phy->type = e1000_phy_none; - goto out; + return E1000_SUCCESS; } phy->addr = 1; @@ -165,8 +160,7 @@ static s32 e1000_init_phy_params_82571(struct e1000_hw *hw) phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82574; break; default: - ret_val = -E1000_ERR_PHY; - goto out; + return -E1000_ERR_PHY; break; } @@ -174,7 +168,7 @@ static s32 e1000_init_phy_params_82571(struct e1000_hw *hw) ret_val = e1000_get_phy_id_82571(hw); if (ret_val) { DEBUGOUT("Error getting PHY ID\n"); - goto out; + return ret_val; } /* Verify phy id */ @@ -201,7 +195,6 @@ static s32 e1000_init_phy_params_82571(struct e1000_hw *hw) if (ret_val) DEBUGOUT1("PHY ID unknown: type = 0x%08x\n", phy->id); -out: return ret_val; } @@ -241,8 +234,7 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw) if (((eecd >> 15) & 0x3) == 0x3) { nvm->type = e1000_nvm_flash_hw; nvm->word_size = 2048; - /* - * Autonomous Flash update bit must be cleared due + /* Autonomous Flash update bit must be cleared due * to Flash update issue. */ eecd &= ~E1000_EECD_AUPDEN; @@ -254,8 +246,7 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw) nvm->type = e1000_nvm_eeprom_spi; size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >> E1000_EECD_SIZE_EX_SHIFT); - /* - * Added to a constant, "size" becomes the left-shift value + /* Added to a constant, "size" becomes the left-shift value * for setting word_size. */ size += NVM_WORD_SIZE_BASE_SHIFT; @@ -382,12 +373,11 @@ static s32 e1000_init_mac_params_82571(struct e1000_hw *hw) /* FWSM register */ mac->has_fwsm = TRUE; - /* - * ARC supported; valid only if manageability features are + /* ARC supported; valid only if manageability features are * enabled. */ - mac->arc_subsystem_valid = (E1000_READ_REG(hw, E1000_FWSM) & - E1000_FWSM_MODE_MASK) ? TRUE : FALSE; + mac->arc_subsystem_valid = !!(E1000_READ_REG(hw, E1000_FWSM) & + E1000_FWSM_MODE_MASK); break; case e1000_82574: case e1000_82583: @@ -405,8 +395,7 @@ static s32 e1000_init_mac_params_82571(struct e1000_hw *hw) break; } - /* - * Ensure that the inter-port SWSM.SMBI lock bit is clear before + /* Ensure that the inter-port SWSM.SMBI lock bit is clear before * first NVM or PHY acess. This should be done for single-port * devices, and for one port only on dual-port devices so that * for those devices we can still use the SMBI lock to synchronize @@ -422,8 +411,9 @@ static s32 e1000_init_mac_params_82571(struct e1000_hw *hw) E1000_WRITE_REG(hw, E1000_SWSM2, swsm2 | E1000_SWSM2_LOCK); force_clear_smbi = TRUE; - } else + } else { force_clear_smbi = FALSE; + } break; default: force_clear_smbi = TRUE; @@ -443,10 +433,7 @@ static s32 e1000_init_mac_params_82571(struct e1000_hw *hw) E1000_WRITE_REG(hw, E1000_SWSM, swsm & ~E1000_SWSM_SMBI); } - /* - * Initialze device specific counter of SMBI acquisition - * timeouts. - */ + /* Initialze device specific counter of SMBI acquisition timeouts. */ hw->dev_spec._82571.smb_counter = 0; return E1000_SUCCESS; @@ -477,7 +464,7 @@ void e1000_init_function_pointers_82571(struct e1000_hw *hw) static s32 e1000_get_phy_id_82571(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; + s32 ret_val; u16 phy_id = 0; DEBUGFUNC("e1000_get_phy_id_82571"); @@ -485,8 +472,7 @@ static s32 e1000_get_phy_id_82571(struct e1000_hw *hw) switch (hw->mac.type) { case e1000_82571: case e1000_82572: - /* - * The 82571 firmware may still be configuring the PHY. + /* The 82571 firmware may still be configuring the PHY. * In this case, we cannot access the PHY until the * configuration is done. So we explicitly set the * PHY ID. @@ -494,29 +480,29 @@ static s32 e1000_get_phy_id_82571(struct e1000_hw *hw) phy->id = IGP01E1000_I_PHY_ID; break; case e1000_82573: - ret_val = e1000_get_phy_id(hw); + return e1000_get_phy_id(hw); break; case e1000_82574: case e1000_82583: ret_val = phy->ops.read_reg(hw, PHY_ID1, &phy_id); if (ret_val) - goto out; + return ret_val; phy->id = (u32)(phy_id << 16); usec_delay(20); ret_val = phy->ops.read_reg(hw, PHY_ID2, &phy_id); if (ret_val) - goto out; + return ret_val; phy->id |= (u32)(phy_id); phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK); break; default: - ret_val = -E1000_ERR_PHY; + return -E1000_ERR_PHY; break; } -out: - return ret_val; + + return E1000_SUCCESS; } /** @@ -528,15 +514,13 @@ out: static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw) { u32 swsm; - s32 ret_val = E1000_SUCCESS; s32 sw_timeout = hw->nvm.word_size + 1; s32 fw_timeout = hw->nvm.word_size + 1; s32 i = 0; DEBUGFUNC("e1000_get_hw_semaphore_82571"); - /* - * If we have timedout 3 times on trying to acquire + /* If we have timedout 3 times on trying to acquire * the inter-port SMBI semaphore, there is old code * operating on the other port, and it is not * releasing SMBI. Modify the number of times that @@ -576,12 +560,10 @@ static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw) /* Release semaphores */ e1000_put_hw_semaphore_82571(hw); DEBUGOUT("Driver can't access the NVM\n"); - ret_val = -E1000_ERR_NVM; - goto out; + return -E1000_ERR_NVM; } -out: - return ret_val; + return E1000_SUCCESS; } /** @@ -613,22 +595,19 @@ static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw) static s32 e1000_get_hw_semaphore_82573(struct e1000_hw *hw) { u32 extcnf_ctrl; - s32 ret_val = E1000_SUCCESS; s32 i = 0; DEBUGFUNC("e1000_get_hw_semaphore_82573"); extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); - extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP; do { + extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP; E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl); extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); if (extcnf_ctrl & E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP) break; - extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP; - msec_delay(2); i++; } while (i < MDIO_OWNERSHIP_TIMEOUT); @@ -637,12 +616,10 @@ static s32 e1000_get_hw_semaphore_82573(struct e1000_hw *hw) /* Release semaphores */ e1000_put_hw_semaphore_82573(hw); DEBUGOUT("Driver can't access the PHY\n"); - ret_val = -E1000_ERR_PHY; - goto out; + return -E1000_ERR_PHY; } -out: - return ret_val; + return E1000_SUCCESS; } /** @@ -712,7 +689,7 @@ static void e1000_put_hw_semaphore_82574(struct e1000_hw *hw) **/ static s32 e1000_set_d0_lplu_state_82574(struct e1000_hw *hw, bool active) { - u16 data = E1000_READ_REG(hw, E1000_POEMB); + u32 data = E1000_READ_REG(hw, E1000_POEMB); DEBUGFUNC("e1000_set_d0_lplu_state_82574"); @@ -738,7 +715,7 @@ static s32 e1000_set_d0_lplu_state_82574(struct e1000_hw *hw, bool active) **/ static s32 e1000_set_d3_lplu_state_82574(struct e1000_hw *hw, bool active) { - u16 data = E1000_READ_REG(hw, E1000_POEMB); + u32 data = E1000_READ_REG(hw, E1000_POEMB); DEBUGFUNC("e1000_set_d3_lplu_state_82574"); @@ -771,7 +748,7 @@ static s32 e1000_acquire_nvm_82571(struct e1000_hw *hw) ret_val = e1000_get_hw_semaphore_82571(hw); if (ret_val) - goto out; + return ret_val; switch (hw->mac.type) { case e1000_82573: @@ -784,7 +761,6 @@ static s32 e1000_acquire_nvm_82571(struct e1000_hw *hw) if (ret_val) e1000_put_hw_semaphore_82571(hw); -out: return ret_val; } @@ -817,7 +793,7 @@ static void e1000_release_nvm_82571(struct e1000_hw *hw) static s32 e1000_write_nvm_82571(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) { - s32 ret_val = E1000_SUCCESS; + s32 ret_val; DEBUGFUNC("e1000_write_nvm_82571"); @@ -857,31 +833,27 @@ static s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw) ret_val = e1000_update_nvm_checksum_generic(hw); if (ret_val) - goto out; + return ret_val; - /* - * If our nvm is an EEPROM, then we're done + /* If our nvm is an EEPROM, then we're done * otherwise, commit the checksum to the flash NVM. */ if (hw->nvm.type != e1000_nvm_flash_hw) - goto out; + return E1000_SUCCESS; /* Check for pending operations. */ for (i = 0; i < E1000_FLASH_UPDATES; i++) { msec_delay(1); - if ((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_FLUPD) == 0) + if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_FLUPD)) break; } - if (i == E1000_FLASH_UPDATES) { - ret_val = -E1000_ERR_NVM; - goto out; - } + if (i == E1000_FLASH_UPDATES) + return -E1000_ERR_NVM; /* Reset the firmware if using STM opcode. */ if ((E1000_READ_REG(hw, E1000_FLOP) & 0xFF00) == E1000_STM_OPCODE) { - /* - * The enabling of and the actual reset must be done + /* The enabling of and the actual reset must be done * in two write cycles. */ E1000_WRITE_REG(hw, E1000_HICR, E1000_HICR_FW_RESET_ENABLE); @@ -895,17 +867,14 @@ static s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw) for (i = 0; i < E1000_FLASH_UPDATES; i++) { msec_delay(1); - if ((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_FLUPD) == 0) + if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_FLUPD)) break; } - if (i == E1000_FLASH_UPDATES) { - ret_val = -E1000_ERR_NVM; - goto out; - } + if (i == E1000_FLASH_UPDATES) + return -E1000_ERR_NVM; -out: - return ret_val; + return E1000_SUCCESS; } /** @@ -944,19 +913,17 @@ static s32 e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset, { struct e1000_nvm_info *nvm = &hw->nvm; u32 i, eewr = 0; - s32 ret_val = 0; + s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_write_nvm_eewr_82571"); - /* - * A check for invalid values: offset too large, too many words, + /* A check for invalid values: offset too large, too many words, * and not enough words. */ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || (words == 0)) { DEBUGOUT("nvm parameter(s) out of bounds\n"); - ret_val = -E1000_ERR_NVM; - goto out; + return -E1000_ERR_NVM; } for (i = 0; i < words; i++) { @@ -975,7 +942,6 @@ static s32 e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset, break; } -out: return ret_val; } @@ -988,7 +954,6 @@ out: static s32 e1000_get_cfg_done_82571(struct e1000_hw *hw) { s32 timeout = PHY_CFG_TIMEOUT; - s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_get_cfg_done_82571"); @@ -1001,12 +966,10 @@ static s32 e1000_get_cfg_done_82571(struct e1000_hw *hw) } if (!timeout) { DEBUGOUT("MNG configuration cycle has not completed.\n"); - ret_val = -E1000_ERR_RESET; - goto out; + return -E1000_ERR_RESET; } -out: - return ret_val; + return E1000_SUCCESS; } /** @@ -1023,39 +986,40 @@ out: static s32 e1000_set_d0_lplu_state_82571(struct e1000_hw *hw, bool active) { struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; + s32 ret_val; u16 data; DEBUGFUNC("e1000_set_d0_lplu_state_82571"); if (!(phy->ops.read_reg)) - goto out; + return E1000_SUCCESS; ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data); if (ret_val) - goto out; + return ret_val; if (active) { data |= IGP02E1000_PM_D0_LPLU; ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, data); if (ret_val) - goto out; + return ret_val; /* When LPLU is enabled, we should disable SmartSpeed */ ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); + if (ret_val) + return ret_val; data &= ~IGP01E1000_PSCFR_SMART_SPEED; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) - goto out; + return ret_val; } else { data &= ~IGP02E1000_PM_D0_LPLU; ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, data); - /* - * LPLU and SmartSpeed are mutually exclusive. LPLU is used + /* LPLU and SmartSpeed are mutually exclusive. LPLU is used * during Dx states where the power conservation is most * important. During driver activity we should enable * SmartSpeed, so performance is maintained. @@ -1065,32 +1029,31 @@ static s32 e1000_set_d0_lplu_state_82571(struct e1000_hw *hw, bool active) IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) - goto out; + return ret_val; data |= IGP01E1000_PSCFR_SMART_SPEED; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) - goto out; + return ret_val; } else if (phy->smart_speed == e1000_smart_speed_off) { ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) - goto out; + return ret_val; data &= ~IGP01E1000_PSCFR_SMART_SPEED; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) - goto out; + return ret_val; } } -out: - return ret_val; + return E1000_SUCCESS; } /** @@ -1101,13 +1064,12 @@ out: **/ static s32 e1000_reset_hw_82571(struct e1000_hw *hw) { - u32 ctrl, ctrl_ext; + u32 ctrl, ctrl_ext, eecd, tctl; s32 ret_val; DEBUGFUNC("e1000_reset_hw_82571"); - /* - * Prevent the PCI-E bus from sticking if there is no TLP connection + /* Prevent the PCI-E bus from sticking if there is no TLP connection * on the last TLP read/write transaction when MAC is reset. */ ret_val = e1000_disable_pcie_master_generic(hw); @@ -1118,13 +1080,14 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw) E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); E1000_WRITE_REG(hw, E1000_RCTL, 0); - E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); + tctl = E1000_READ_REG(hw, E1000_TCTL); + tctl &= ~E1000_TCTL_EN; + E1000_WRITE_REG(hw, E1000_TCTL, tctl); E1000_WRITE_FLUSH(hw); msec_delay(10); - /* - * Must acquire the MDIO ownership before MAC reset. + /* Must acquire the MDIO ownership before MAC reset. * Ownership defaults to firmware after a reset. */ switch (hw->mac.type) { @@ -1167,15 +1130,23 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw) ret_val = e1000_get_auto_rd_done_generic(hw); if (ret_val) /* We don't want to continue accessing MAC registers. */ - goto out; + return ret_val; - /* - * Phy configuration from NVM just starts after EECD_AUTO_RD is set. + /* Phy configuration from NVM just starts after EECD_AUTO_RD is set. * Need to wait for Phy configuration completion before accessing * NVM and Phy. */ switch (hw->mac.type) { + case e1000_82571: + case e1000_82572: + /* REQ and GNT bits need to be cleared when using AUTO_RD + * to access the EEPROM. + */ + eecd = E1000_READ_REG(hw, E1000_EECD); + eecd &= ~(E1000_EECD_REQ | E1000_EECD_GNT); + E1000_WRITE_REG(hw, E1000_EECD, eecd); + break; case e1000_82573: case e1000_82574: case e1000_82583: @@ -1193,7 +1164,7 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw) /* Install any alternate MAC address into RAR0 */ ret_val = e1000_check_alt_mac_addr_generic(hw); if (ret_val) - goto out; + return ret_val; e1000_set_laa_state_82571(hw, TRUE); } @@ -1202,8 +1173,7 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw) if (hw->phy.media_type == e1000_media_type_internal_serdes) hw->mac.serdes_link_state = e1000_serdes_link_down; -out: - return ret_val; + return E1000_SUCCESS; } /** @@ -1225,16 +1195,15 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw) /* Initialize identification LED */ ret_val = mac->ops.id_led_init(hw); + /* An error is not fatal and we should not stop init due to this */ if (ret_val) DEBUGOUT("Error initializing identification LED\n"); - /* This is not fatal and we should not stop init due to this */ /* Disabling VLAN filtering */ DEBUGOUT("Initializing the IEEE VLAN\n"); mac->ops.clear_vfta(hw); - /* Setup the receive address. */ - /* + /* Setup the receive address. * If, however, a locally administered address was assigned to the * 82571, we must reserve a RAR for it to work around an issue where * resetting one port will reload the MAC on the other port. @@ -1277,8 +1246,7 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw) break; } - /* - * Clear all of the statistics registers (clear on read). It is + /* Clear all of the statistics registers (clear on read). It is * important that we do this after we have tried to establish link * because the symbol error count will increment wildly if there * is no link. @@ -1377,8 +1345,7 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw) E1000_WRITE_REG(hw, E1000_PBA_ECC, reg); } - /* - * Workaround for hardware errata. + /* Workaround for hardware errata. * Ensure that DMA Dynamic Clock gating is disabled on 82571 and 82572 */ if ((hw->mac.type == e1000_82571) || @@ -1388,6 +1355,15 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw) E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg); } + /* Disable IPv6 extension header parsing because some malformed + * IPv6 headers can hang the Rx. + */ + if (hw->mac.type <= e1000_82573) { + reg = E1000_READ_REG(hw, E1000_RFCTL); + reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS); + E1000_WRITE_REG(hw, E1000_RFCTL, reg); + } + /* PCI-Ex Control Registers */ switch (hw->mac.type) { case e1000_82574: @@ -1396,8 +1372,7 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw) reg |= (1 << 22); E1000_WRITE_REG(hw, E1000_GCR, reg); - /* - * Workaround for hardware errata. + /* Workaround for hardware errata. * apply workaround for hardware errata documented in errata * docs Fixes issue where some error prone or unreliable PCIe * completions are occurring, particularly with ASPM enabled. @@ -1435,25 +1410,25 @@ static void e1000_clear_vfta_82571(struct e1000_hw *hw) case e1000_82574: case e1000_82583: if (hw->mng_cookie.vlan_id != 0) { - /* - * The VFTA is a 4096b bit-field, each identifying + /* The VFTA is a 4096b bit-field, each identifying * a single VLAN ID. The following operations * determine which 32b entry (i.e. offset) into the * array we want to set the VLAN ID (i.e. bit) of * the manageability unit. */ vfta_offset = (hw->mng_cookie.vlan_id >> - E1000_VFTA_ENTRY_SHIFT) & E1000_VFTA_ENTRY_MASK; - vfta_bit_in_reg = 1 << (hw->mng_cookie.vlan_id & - E1000_VFTA_ENTRY_BIT_SHIFT_MASK); + E1000_VFTA_ENTRY_SHIFT) & + E1000_VFTA_ENTRY_MASK; + vfta_bit_in_reg = + 1 << (hw->mng_cookie.vlan_id & + E1000_VFTA_ENTRY_BIT_SHIFT_MASK); } break; default: break; } for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) { - /* - * If the offset we want to clear is the same offset of the + /* If the offset we want to clear is the same offset of the * manageability VLAN ID, then clear all bits except that of * the manageability unit. */ @@ -1495,8 +1470,7 @@ static s32 e1000_led_on_82574(struct e1000_hw *hw) ctrl = hw->mac.ledctl_mode2; if (!(E1000_STATUS_LU & E1000_READ_REG(hw, E1000_STATUS))) { - /* - * If no link, then turn LED on by setting the invert bit + /* If no link, then turn LED on by setting the invert bit * for each LED that's "on" (0x0E) in ledctl_mode2. */ for (i = 0; i < 4; i++) @@ -1519,30 +1493,28 @@ bool e1000_check_phy_82574(struct e1000_hw *hw) { u16 status_1kbt = 0; u16 receive_errors = 0; - bool phy_hung = FALSE; - s32 ret_val = E1000_SUCCESS; + s32 ret_val; DEBUGFUNC("e1000_check_phy_82574"); - /* - * Read PHY Receive Error counter first, if its is max - all F's then + /* Read PHY Receive Error counter first, if its is max - all F's then * read the Base1000T status register If both are max then PHY is hung. */ ret_val = hw->phy.ops.read_reg(hw, E1000_RECEIVE_ERROR_COUNTER, &receive_errors); if (ret_val) - goto out; + return FALSE; if (receive_errors == E1000_RECEIVE_ERROR_MAX) { ret_val = hw->phy.ops.read_reg(hw, E1000_BASE1000T_STATUS, &status_1kbt); if (ret_val) - goto out; + return FALSE; if ((status_1kbt & E1000_IDLE_ERROR_COUNT_MASK) == E1000_IDLE_ERROR_COUNT_MASK) - phy_hung = TRUE; + return TRUE; } -out: - return phy_hung; + + return FALSE; } @@ -1560,8 +1532,7 @@ static s32 e1000_setup_link_82571(struct e1000_hw *hw) { DEBUGFUNC("e1000_setup_link_82571"); - /* - * 82573 does not have a word in the NVM to determine + /* 82573 does not have a word in the NVM to determine * the default flow control setting, so we explicitly * set it to full. */ @@ -1608,17 +1579,14 @@ static s32 e1000_setup_copper_link_82571(struct e1000_hw *hw) ret_val = e1000_copper_link_setup_igp(hw); break; default: - ret_val = -E1000_ERR_PHY; + return -E1000_ERR_PHY; break; } if (ret_val) - goto out; + return ret_val; - ret_val = e1000_setup_copper_link_generic(hw); - -out: - return ret_val; + return e1000_setup_copper_link_generic(hw); } /** @@ -1635,8 +1603,7 @@ static s32 e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw) switch (hw->mac.type) { case e1000_82571: case e1000_82572: - /* - * If SerDes loopback mode is entered, there is no form + /* If SerDes loopback mode is entered, there is no form * of reset to take the adapter out of that mode. So we * have to explicitly take the adapter out of loopback * mode. This prevents drivers from twiddling their thumbs @@ -1685,16 +1652,17 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw) ctrl = E1000_READ_REG(hw, E1000_CTRL); status = E1000_READ_REG(hw, E1000_STATUS); + E1000_READ_REG(hw, E1000_RXCW); + /* SYNCH bit and IV bit are sticky */ + usec_delay(10); rxcw = E1000_READ_REG(hw, E1000_RXCW); if ((rxcw & E1000_RXCW_SYNCH) && !(rxcw & E1000_RXCW_IV)) { - /* Receiver is synchronized with no invalid bits. */ switch (mac->serdes_link_state) { case e1000_serdes_link_autoneg_complete: if (!(status & E1000_STATUS_LU)) { - /* - * We have lost link, retry autoneg before + /* We have lost link, retry autoneg before * reporting link failure */ mac->serdes_link_state = @@ -1707,15 +1675,12 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw) break; case e1000_serdes_link_forced_up: - /* - * If we are receiving /C/ ordered sets, re-enable + /* If we are receiving /C/ ordered sets, re-enable * auto-negotiation in the TXCW register and disable * forced link in the Device Control register in an * attempt to auto-negotiate with our link partner. - * If the partner code word is null, stop forcing - * and restart auto negotiation. */ - if ((rxcw & E1000_RXCW_C) || !(rxcw & E1000_RXCW_CW)) { + if (rxcw & E1000_RXCW_C) { /* Enable autoneg, and unforce link up */ E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw); E1000_WRITE_REG(hw, E1000_CTRL, @@ -1731,8 +1696,7 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw) case e1000_serdes_link_autoneg_progress: if (rxcw & E1000_RXCW_C) { - /* - * We received /C/ ordered sets, meaning the + /* We received /C/ ordered sets, meaning the * link partner has autonegotiated, and we can * trust the Link Up (LU) status bit. */ @@ -1748,8 +1712,7 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw) DEBUGOUT("AN_PROG -> DOWN\n"); } } else { - /* - * The link partner did not autoneg. + /* The link partner did not autoneg. * Force link up and full duplex, and change * state to forced. */ @@ -1774,8 +1737,7 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw) case e1000_serdes_link_down: default: - /* - * The link was down but the receiver has now gained + /* The link was down but the receiver has now gained * valid sync, so lets see if we can bring the link * up. */ @@ -1794,17 +1756,18 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw) mac->serdes_link_state = e1000_serdes_link_down; DEBUGOUT("ANYSTATE -> DOWN\n"); } else { - /* - * Check several times, if Sync and Config - * both are consistently 1 then simply ignore - * the Invalid bit and restart Autoneg + /* Check several times, if SYNCH bit and CONFIG + * bit both are consistently 1 then simply ignore + * the IV bit and restart Autoneg */ for (i = 0; i < AN_RETRY_COUNT; i++) { usec_delay(10); rxcw = E1000_READ_REG(hw, E1000_RXCW); - if ((rxcw & E1000_RXCW_IV) && - !((rxcw & E1000_RXCW_SYNCH) && - (rxcw & E1000_RXCW_C))) { + if ((rxcw & E1000_RXCW_SYNCH) && + (rxcw & E1000_RXCW_C)) + continue; + + if (rxcw & E1000_RXCW_IV) { mac->serdes_has_link = FALSE; mac->serdes_link_state = e1000_serdes_link_down; @@ -1845,7 +1808,7 @@ static s32 e1000_valid_led_default_82571(struct e1000_hw *hw, u16 *data) ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); - goto out; + return ret_val; } switch (hw->mac.type) { @@ -1862,8 +1825,7 @@ static s32 e1000_valid_led_default_82571(struct e1000_hw *hw, u16 *data) break; } -out: - return ret_val; + return E1000_SUCCESS; } /** @@ -1900,15 +1862,14 @@ void e1000_set_laa_state_82571(struct e1000_hw *hw, bool state) /* If workaround is activated... */ if (state) - /* - * Hold a copy of the LAA in RAR[14] This is done so that + /* Hold a copy of the LAA in RAR[14] This is done so that * between the time RAR[0] gets clobbered and the time it * gets fixed, the actual LAA is in one of the RARs and no * incoming packets directed to this port are dropped. * Eventually the LAA will be in RAR[0] and RAR[14]. */ hw->mac.ops.rar_set(hw, hw->mac.addr, - hw->mac.rar_entry_count - 1); + hw->mac.rar_entry_count - 1); return; } @@ -1925,25 +1886,23 @@ void e1000_set_laa_state_82571(struct e1000_hw *hw, bool state) static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw) { struct e1000_nvm_info *nvm = &hw->nvm; - s32 ret_val = E1000_SUCCESS; + s32 ret_val; u16 data; DEBUGFUNC("e1000_fix_nvm_checksum_82571"); if (nvm->type != e1000_nvm_flash_hw) - goto out; + return E1000_SUCCESS; - /* - * Check bit 4 of word 10h. If it is 0, firmware is done updating + /* Check bit 4 of word 10h. If it is 0, firmware is done updating * 10h-12h. Checksum may need to be fixed. */ ret_val = nvm->ops.read(hw, 0x10, 1, &data); if (ret_val) - goto out; + return ret_val; if (!(data & 0x10)) { - /* - * Read 0x23 and check bit 15. This bit is a 1 + /* Read 0x23 and check bit 15. This bit is a 1 * when the checksum has already been fixed. If * the checksum is still wrong and this bit is a * 1, we need to return bad checksum. Otherwise, @@ -1952,19 +1911,20 @@ static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw) */ ret_val = nvm->ops.read(hw, 0x23, 1, &data); if (ret_val) - goto out; + return ret_val; if (!(data & 0x8000)) { data |= 0x8000; ret_val = nvm->ops.write(hw, 0x23, 1, &data); if (ret_val) - goto out; + return ret_val; ret_val = nvm->ops.update(hw); + if (ret_val) + return ret_val; } } -out: - return ret_val; + return E1000_SUCCESS; } @@ -1974,25 +1934,21 @@ out: **/ static s32 e1000_read_mac_addr_82571(struct e1000_hw *hw) { - s32 ret_val = E1000_SUCCESS; - DEBUGFUNC("e1000_read_mac_addr_82571"); if (hw->mac.type == e1000_82571) { - /* - * If there's an alternate MAC address place it in RAR0 + s32 ret_val; + + /* If there's an alternate MAC address place it in RAR0 * so that it will override the Si installed default perm * address. */ ret_val = e1000_check_alt_mac_addr_generic(hw); if (ret_val) - goto out; + return ret_val; } - ret_val = e1000_read_mac_addr_generic(hw); - -out: - return ret_val; + return e1000_read_mac_addr_generic(hw); } /** @@ -2007,7 +1963,7 @@ static void e1000_power_down_phy_copper_82571(struct e1000_hw *hw) struct e1000_phy_info *phy = &hw->phy; struct e1000_mac_info *mac = &hw->mac; - if (!(phy->ops.check_reset_block)) + if (!phy->ops.check_reset_block) return; /* If the management interface is not enabled, then power down */ diff --git a/sys/dev/e1000/e1000_82575.c b/sys/dev/e1000/e1000_82575.c index a0d48b36d9e..5722f4688ca 100644 --- a/sys/dev/e1000/e1000_82575.c +++ b/sys/dev/e1000/e1000_82575.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2012, Intel Corporation + Copyright (c) 2001-2013, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -144,6 +144,8 @@ static bool e1000_sgmii_uses_mdio_82575(struct e1000_hw *hw) break; case e1000_82580: case e1000_i350: + case e1000_i210: + case e1000_i211: reg = E1000_READ_REG(hw, E1000_MDICNFG); ext_mdio = !!(reg & E1000_MDICNFG_EXT_MDIO); break; @@ -332,6 +334,7 @@ s32 e1000_init_nvm_params_82575(struct e1000_hw *hw) } else { nvm->type = e1000_nvm_flash_hw; } + /* Function Pointers */ nvm->ops.acquire = e1000_acquire_nvm_82575; nvm->ops.release = e1000_release_nvm_82575; @@ -385,11 +388,16 @@ static s32 e1000_init_mac_params_82575(struct e1000_hw *hw) mac->rar_entry_count = E1000_RAR_ENTRIES_82576; if (mac->type == e1000_82580) mac->rar_entry_count = E1000_RAR_ENTRIES_82580; - if (mac->type == e1000_i350) { + if (mac->type == e1000_i350) mac->rar_entry_count = E1000_RAR_ENTRIES_I350; - /* Enable EEE default settings for i350 */ + + /* Enable EEE default settings for EEE supported devices */ + if (mac->type >= e1000_i350) dev_spec->eee_disable = FALSE; - } + + /* Allow a single clear of the SW semaphore on I210 and newer */ + if (mac->type >= e1000_i210) + dev_spec->clear_semaphore_once = TRUE; /* Set if part includes ASF firmware */ mac->asf_firmware_present = TRUE; @@ -428,7 +436,7 @@ static s32 e1000_init_mac_params_82575(struct e1000_hw *hw) mac->ops.config_collision_dist = e1000_config_collision_dist_82575; /* multicast address update */ mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic; - if (hw->mac.type == e1000_i350) { + if (mac->type == e1000_i350) { /* writing VFTA */ mac->ops.write_vfta = e1000_write_vfta_i350; /* clearing VFTA */ @@ -439,6 +447,9 @@ static s32 e1000_init_mac_params_82575(struct e1000_hw *hw) /* clearing VFTA */ mac->ops.clear_vfta = e1000_clear_vfta_generic; } + if (hw->mac.type >= e1000_82580) + mac->ops.validate_mdi_setting = + e1000_validate_mdi_setting_crossover_generic; /* ID LED init */ mac->ops.id_led_init = e1000_id_led_init_generic; /* blink LED */ @@ -634,6 +645,8 @@ static s32 e1000_get_phy_id_82575(struct e1000_hw *hw) break; case e1000_82580: case e1000_i350: + case e1000_i210: + case e1000_i211: mdic = E1000_READ_REG(hw, E1000_MDICNFG); mdic &= E1000_MDICNFG_PHY_MASK; phy->addr = mdic >> E1000_MDICNFG_PHY_SHIFT; @@ -1143,6 +1156,15 @@ static s32 e1000_check_for_link_82575(struct e1000_hw *hw) */ hw->mac.get_link_status = !hw->mac.serdes_has_link; + /* + * Configure Flow Control now that Auto-Neg has completed. + * First, we need to restore the desired flow control + * settings because we may have had to re-autoneg with a + * different link partner. + */ + ret_val = e1000_config_fc_after_link_up_generic(hw); + if (ret_val) + DEBUGOUT("Error configuring flow control\n"); } else { ret_val = e1000_check_for_copper_link_generic(hw); } @@ -1222,6 +1244,7 @@ static s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw, *duplex = FULL_DUPLEX; else *duplex = HALF_DUPLEX; + } else { mac->serdes_has_link = FALSE; *speed = 0; @@ -1397,7 +1420,8 @@ static s32 e1000_init_hw_82575(struct e1000_hw *hw) static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw) { u32 ctrl; - s32 ret_val; + s32 ret_val; + u32 phpm_reg; DEBUGFUNC("e1000_setup_copper_link_82575"); @@ -1406,6 +1430,13 @@ static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw) ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); E1000_WRITE_REG(hw, E1000_CTRL, ctrl); + /* Clear Go Link Disconnect bit */ + if (hw->mac.type >= e1000_82580) { + phpm_reg = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT); + phpm_reg &= ~E1000_82580_PM_GO_LINKD; + E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, phpm_reg); + } + ret_val = e1000_setup_serdes_link_82575(hw); if (ret_val) goto out; @@ -1423,12 +1454,17 @@ static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw) switch (hw->phy.type) { case e1000_phy_i210: case e1000_phy_m88: - if (hw->phy.id == I347AT4_E_PHY_ID || - hw->phy.id == M88E1112_E_PHY_ID || - hw->phy.id == M88E1340M_E_PHY_ID) + switch (hw->phy.id) { + case I347AT4_E_PHY_ID: + case M88E1112_E_PHY_ID: + case M88E1340M_E_PHY_ID: + case I210_I_PHY_ID: ret_val = e1000_copper_link_setup_m88_gen2(hw); - else + break; + default: ret_val = e1000_copper_link_setup_m88(hw); + break; + } break; case e1000_phy_igp_3: ret_val = e1000_copper_link_setup_igp(hw); @@ -1460,7 +1496,7 @@ out: **/ static s32 e1000_setup_serdes_link_82575(struct e1000_hw *hw) { - u32 ctrl_ext, ctrl_reg, reg; + u32 ctrl_ext, ctrl_reg, reg, anadv_reg; bool pcs_autoneg; s32 ret_val = E1000_SUCCESS; u16 data; @@ -1544,26 +1580,47 @@ static s32 e1000_setup_serdes_link_82575(struct e1000_hw *hw) reg &= ~(E1000_PCS_LCTL_AN_ENABLE | E1000_PCS_LCTL_FLV_LINK_UP | E1000_PCS_LCTL_FSD | E1000_PCS_LCTL_FORCE_LINK); - /* - * We force flow control to prevent the CTRL register values from being - * overwritten by the autonegotiated flow control values - */ - reg |= E1000_PCS_LCTL_FORCE_FCTRL; - if (pcs_autoneg) { /* Set PCS register for autoneg */ reg |= E1000_PCS_LCTL_AN_ENABLE | /* Enable Autoneg */ E1000_PCS_LCTL_AN_RESTART; /* Restart autoneg */ + + /* Disable force flow control for autoneg */ + reg &= ~E1000_PCS_LCTL_FORCE_FCTRL; + + /* Configure flow control advertisement for autoneg */ + anadv_reg = E1000_READ_REG(hw, E1000_PCS_ANADV); + anadv_reg &= ~(E1000_TXCW_ASM_DIR | E1000_TXCW_PAUSE); + + switch (hw->fc.requested_mode) { + case e1000_fc_full: + case e1000_fc_rx_pause: + anadv_reg |= E1000_TXCW_ASM_DIR; + anadv_reg |= E1000_TXCW_PAUSE; + break; + case e1000_fc_tx_pause: + anadv_reg |= E1000_TXCW_ASM_DIR; + break; + default: + break; + } + + E1000_WRITE_REG(hw, E1000_PCS_ANADV, anadv_reg); + DEBUGOUT1("Configuring Autoneg:PCS_LCTL=0x%08X\n", reg); } else { /* Set PCS register for forced link */ reg |= E1000_PCS_LCTL_FSD; /* Force Speed */ + + /* Force flow control for forced link */ + reg |= E1000_PCS_LCTL_FORCE_FCTRL; + DEBUGOUT1("Configuring Forced Link:PCS_LCTL=0x%08X\n", reg); } E1000_WRITE_REG(hw, E1000_PCS_LCTL, reg); - if (!e1000_sgmii_active_82575(hw)) + if (!pcs_autoneg && !e1000_sgmii_active_82575(hw)) e1000_force_mac_fc_generic(hw); return ret_val; @@ -1582,137 +1639,70 @@ static s32 e1000_setup_serdes_link_82575(struct e1000_hw *hw) **/ static s32 e1000_get_media_type_82575(struct e1000_hw *hw) { - u32 lan_id = 0; - s32 ret_val = E1000_ERR_CONFIG; struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; + s32 ret_val = E1000_SUCCESS; u32 ctrl_ext = 0; - u32 current_link_mode = 0; - u16 init_ctrl_wd_3 = 0; - u8 init_ctrl_wd_3_offset = 0; - u8 init_ctrl_wd_3_bit_offset = 0; + u32 link_mode = 0; /* Set internal phy as default */ dev_spec->sgmii_active = FALSE; dev_spec->module_plugged = FALSE; - /* - * Check if NVM access method is attached already. - * If it is then Init Control Word #3 is considered - * otherwise runtime CSR register content is taken. - */ - /* Get CSR setting */ ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); - /* Get link mode setting */ - if ((hw->nvm.ops.read) && (hw->nvm.ops.read != e1000_null_read_nvm)) { - /* Take link mode from EEPROM */ - - /* - * Get LAN port ID to derive its - * adequate Init Control Word #3 - */ - lan_id = ((E1000_READ_REG(hw, E1000_STATUS) & - E1000_STATUS_LAN_ID_MASK) >> E1000_STATUS_LAN_ID_OFFSET); - /* - * Derive Init Control Word #3 offset - * and mask to pick up link mode setting. - */ - if (hw->mac.type < e1000_82580) { - init_ctrl_wd_3_offset = lan_id ? - NVM_INIT_CONTROL3_PORT_A : NVM_INIT_CONTROL3_PORT_B; - init_ctrl_wd_3_bit_offset = NVM_WORD24_LNK_MODE_OFFSET; - } else { - init_ctrl_wd_3_offset = - NVM_82580_LAN_FUNC_OFFSET(lan_id) + - NVM_INIT_CONTROL3_PORT_A; - init_ctrl_wd_3_bit_offset = - NVM_WORD24_82580_LNK_MODE_OFFSET; - } - /* Read Init Control Word #3*/ - hw->nvm.ops.read(hw, init_ctrl_wd_3_offset, 1, &init_ctrl_wd_3); - - /* - * Align link mode bits to - * their CTRL_EXT location. - */ - current_link_mode = init_ctrl_wd_3; - current_link_mode <<= (E1000_CTRL_EXT_LINK_MODE_OFFSET - - init_ctrl_wd_3_bit_offset); - current_link_mode &= E1000_CTRL_EXT_LINK_MODE_MASK; - - /* - * Switch to CSR for all but internal PHY. - */ - if (current_link_mode != E1000_CTRL_EXT_LINK_MODE_GMII) - /* Take link mode from CSR */ - current_link_mode = ctrl_ext & - E1000_CTRL_EXT_LINK_MODE_MASK; - } else { - /* Take link mode from CSR */ - current_link_mode = ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK; - } - - switch (current_link_mode) { + /* extract link mode setting */ + link_mode = ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK; + switch (link_mode) { case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX: hw->phy.media_type = e1000_media_type_internal_serdes; - current_link_mode = E1000_CTRL_EXT_LINK_MODE_1000BASE_KX; break; case E1000_CTRL_EXT_LINK_MODE_GMII: hw->phy.media_type = e1000_media_type_copper; - current_link_mode = E1000_CTRL_EXT_LINK_MODE_GMII; break; case E1000_CTRL_EXT_LINK_MODE_SGMII: - case E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES: /* Get phy control interface type set (MDIO vs. I2C)*/ if (e1000_sgmii_uses_mdio_82575(hw)) { hw->phy.media_type = e1000_media_type_copper; dev_spec->sgmii_active = TRUE; - current_link_mode = E1000_CTRL_EXT_LINK_MODE_SGMII; - } else { - ret_val = e1000_set_sfp_media_type_82575(hw); - if (ret_val != E1000_SUCCESS) - goto out; - if (hw->phy.media_type == - e1000_media_type_internal_serdes) { - current_link_mode = - E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES; - } else if (hw->phy.media_type == - e1000_media_type_copper) { - current_link_mode = - E1000_CTRL_EXT_LINK_MODE_SGMII; - } + break; } - break; - default: - DEBUGOUT("Link mode mask doesn't fit bit field size\n"); - goto out; - } - /* - * Do not change current link mode setting - * if media type is fibre or has not been - * recognized. - */ - if ((hw->phy.media_type != e1000_media_type_unknown) && - (hw->phy.media_type != e1000_media_type_fiber)) { - /* Update link mode */ - ctrl_ext &= ~E1000_CTRL_EXT_LINK_MODE_MASK; - E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext | - current_link_mode); - } - - ret_val = E1000_SUCCESS; -out: - /* - * If media type was not identified then return media type - * defined by the CTRL_EXT settings. - */ - if (hw->phy.media_type == e1000_media_type_unknown) { - if (current_link_mode == E1000_CTRL_EXT_LINK_MODE_SGMII) - hw->phy.media_type = e1000_media_type_copper; - else + /* fall through for I2C based SGMII */ + case E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES: + /* read media type from SFP EEPROM */ + ret_val = e1000_set_sfp_media_type_82575(hw); + if ((ret_val != E1000_SUCCESS) || + (hw->phy.media_type == e1000_media_type_unknown)) { + /* + * If media type was not identified then return media + * type defined by the CTRL_EXT settings. + */ hw->phy.media_type = e1000_media_type_internal_serdes; + + if (link_mode == E1000_CTRL_EXT_LINK_MODE_SGMII) { + hw->phy.media_type = e1000_media_type_copper; + dev_spec->sgmii_active = TRUE; + } + + break; + } + + /* do not change link mode for 100BaseFX */ + if (dev_spec->eth_flags.e100_base_fx) + break; + + /* change current link mode setting */ + ctrl_ext &= ~E1000_CTRL_EXT_LINK_MODE_MASK; + + if (hw->phy.media_type == e1000_media_type_copper) + ctrl_ext |= E1000_CTRL_EXT_LINK_MODE_SGMII; + else + ctrl_ext |= E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES; + + E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); + + break; } return ret_val; @@ -1730,40 +1720,52 @@ static s32 e1000_set_sfp_media_type_82575(struct e1000_hw *hw) s32 ret_val = E1000_ERR_CONFIG; u32 ctrl_ext = 0; struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; - struct sfp_e1000_flags eth_flags = {0}; + struct sfp_e1000_flags *eth_flags = &dev_spec->eth_flags; u8 tranceiver_type = 0; + s32 timeout = 3; - /* Turn I2C interface ON */ + /* Turn I2C interface ON and power on sfp cage */ ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); + ctrl_ext &= ~E1000_CTRL_EXT_SDP3_DATA; E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext | E1000_CTRL_I2C_ENA); + E1000_WRITE_FLUSH(hw); + /* Read SFP module data */ - ret_val = e1000_read_sfp_data_byte(hw, + while (timeout) { + ret_val = e1000_read_sfp_data_byte(hw, E1000_I2CCMD_SFP_DATA_ADDR(E1000_SFF_IDENTIFIER_OFFSET), &tranceiver_type); + if (ret_val == E1000_SUCCESS) + break; + msec_delay(100); + timeout--; + } if (ret_val != E1000_SUCCESS) goto out; + ret_val = e1000_read_sfp_data_byte(hw, E1000_I2CCMD_SFP_DATA_ADDR(E1000_SFF_ETH_FLAGS_OFFSET), - (u8 *)ð_flags); + (u8 *)eth_flags); if (ret_val != E1000_SUCCESS) goto out; - /* - * Check if there is some SFP - * module plugged and powered - */ + + /* Check if there is some SFP module plugged and powered */ if ((tranceiver_type == E1000_SFF_IDENTIFIER_SFP) || (tranceiver_type == E1000_SFF_IDENTIFIER_SFF)) { dev_spec->module_plugged = TRUE; - if (eth_flags.e1000_base_lx || eth_flags.e1000_base_sx) { + if (eth_flags->e1000_base_lx || eth_flags->e1000_base_sx) { hw->phy.media_type = e1000_media_type_internal_serdes; - } else if (eth_flags.e1000_base_t) { + } else if (eth_flags->e100_base_fx) { + dev_spec->sgmii_active = TRUE; + hw->phy.media_type = e1000_media_type_internal_serdes; + } else if (eth_flags->e1000_base_t) { dev_spec->sgmii_active = TRUE; hw->phy.media_type = e1000_media_type_copper; } else { - hw->phy.media_type = e1000_media_type_unknown; - DEBUGOUT("PHY module has not been recognized\n"); - goto out; + hw->phy.media_type = e1000_media_type_unknown; + DEBUGOUT("PHY module has not been recognized\n"); + goto out; } } else { hw->phy.media_type = e1000_media_type_unknown; @@ -2280,7 +2282,7 @@ out: * e1000_reset_mdicnfg_82580 - Reset MDICNFG destination and com_mdio bits * @hw: pointer to the HW structure * - * This resets the MDICNFG.Destination and MDICNFG.Com_MDIO bits based on + * This resets the the MDICNFG.Destination and MDICNFG.Com_MDIO bits based on * the values found in the EEPROM. This addresses an issue in which these * bits are not restored from EEPROM after reset. **/ @@ -2334,6 +2336,10 @@ static s32 e1000_reset_hw_82580(struct e1000_hw *hw) hw->dev_spec._82575.global_device_reset = FALSE; + /* 82580 does not reliably do global_device_reset due to hw errata */ + if (hw->mac.type == e1000_82580) + global_device_reset = FALSE; + /* Get current control state. */ ctrl = E1000_READ_REG(hw, E1000_CTRL); @@ -2660,10 +2666,15 @@ s32 e1000_set_eee_i350(struct e1000_hw *hw) /* enable or disable per user setting */ if (!(hw->dev_spec._82575.eee_disable)) { + u32 eee_su = E1000_READ_REG(hw, E1000_EEE_SU); + ipcnfg |= (E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN); eeer |= (E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN | E1000_EEER_LPI_FC); + /* This bit should not be set in normal operation. */ + if (eee_su & E1000_EEE_SU_LPI_CLK_STP) + DEBUGOUT("LPI Clock Stop Bit should not be set!\n"); } else { ipcnfg &= ~(E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN); eeer &= ~(E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN | @@ -3275,3 +3286,4 @@ void e1000_i2c_bus_clear(struct e1000_hw *hw) e1000_i2c_stop(hw); } + diff --git a/sys/dev/e1000/e1000_82575.h b/sys/dev/e1000/e1000_82575.h index 4b2b245f3de..c6bbe186c0d 100644 --- a/sys/dev/e1000/e1000_82575.h +++ b/sys/dev/e1000/e1000_82575.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2011, Intel Corporation + Copyright (c) 2001-2013, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -360,10 +360,13 @@ struct e1000_adv_tx_context_desc { #define E1000_DCA_RXCTRL_DESC_DCA_EN (1 << 5) /* DCA Rx Desc enable */ #define E1000_DCA_RXCTRL_HEAD_DCA_EN (1 << 6) /* DCA Rx Desc header ena */ #define E1000_DCA_RXCTRL_DATA_DCA_EN (1 << 7) /* DCA Rx Desc payload ena */ +#define E1000_DCA_RXCTRL_DESC_RRO_EN (1 << 9) /* DCA Rx Desc Relax Order */ #define E1000_DCA_TXCTRL_CPUID_MASK 0x0000001F /* Tx CPUID Mask */ #define E1000_DCA_TXCTRL_DESC_DCA_EN (1 << 5) /* DCA Tx Desc enable */ +#define E1000_DCA_TXCTRL_DESC_RRO_EN (1 << 9) /* Tx rd Desc Relax Order */ #define E1000_DCA_TXCTRL_TX_WB_RO_EN (1 << 11) /* Tx Desc writeback RO bit */ +#define E1000_DCA_TXCTRL_DATA_RRO_EN (1 << 13) /* Tx rd data Relax Order */ #define E1000_DCA_TXCTRL_CPUID_MASK_82576 0xFF000000 /* Tx CPUID Mask */ #define E1000_DCA_RXCTRL_CPUID_MASK_82576 0xFF000000 /* Rx CPUID Mask */ diff --git a/sys/dev/e1000/e1000_api.c b/sys/dev/e1000/e1000_api.c index 4b2a43d7286..158191304ba 100644 --- a/sys/dev/e1000/e1000_api.c +++ b/sys/dev/e1000/e1000_api.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2012, Intel Corporation + Copyright (c) 2001-2013, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -289,6 +289,12 @@ s32 e1000_set_mac_type(struct e1000_hw *hw) case E1000_DEV_ID_PCH2_LV_V: mac->type = e1000_pch2lan; break; + case E1000_DEV_ID_PCH_LPT_I217_LM: + case E1000_DEV_ID_PCH_LPT_I217_V: + case E1000_DEV_ID_PCH_LPTLP_I218_LM: + case E1000_DEV_ID_PCH_LPTLP_I218_V: + mac->type = e1000_pch_lpt; + break; case E1000_DEV_ID_82575EB_COPPER: case E1000_DEV_ID_82575EB_FIBER_SERDES: case E1000_DEV_ID_82575GB_QUAD_COPPER: @@ -323,6 +329,9 @@ s32 e1000_set_mac_type(struct e1000_hw *hw) case E1000_DEV_ID_I350_DA4: mac->type = e1000_i350; break; +#if defined(QV_RELEASE) && defined(SPRINGVILLE_FLASHLESS_HW) + case E1000_DEV_ID_I210_NVMLESS: +#endif /* QV_RELEASE && SPRINGVILLE_FLASHLESS_HW */ case E1000_DEV_ID_I210_COPPER: case E1000_DEV_ID_I210_COPPER_OEM1: case E1000_DEV_ID_I210_COPPER_IT: @@ -332,14 +341,17 @@ s32 e1000_set_mac_type(struct e1000_hw *hw) mac->type = e1000_i210; break; case E1000_DEV_ID_I211_COPPER: - mac->type = e1000_i211; - break; + mac->type = e1000_i211; + break; case E1000_DEV_ID_82576_VF: + case E1000_DEV_ID_82576_VF_HV: mac->type = e1000_vfadapt; break; case E1000_DEV_ID_I350_VF: + case E1000_DEV_ID_I350_VF_HV: mac->type = e1000_vfadapt_i350; break; + default: /* Should never have loaded on this device */ ret_val = -E1000_ERR_MAC_INIT; @@ -428,6 +440,7 @@ s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device) case e1000_ich10lan: case e1000_pchlan: case e1000_pch2lan: + case e1000_pch_lpt: e1000_init_function_pointers_ich8lan(hw); break; case e1000_82575: @@ -873,11 +886,7 @@ bool e1000_enable_tx_pkt_filtering(struct e1000_hw *hw) s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer, u16 length, u16 offset, u8 *sum) { - if (hw->mac.ops.mng_host_if_write) - return hw->mac.ops.mng_host_if_write(hw, buffer, length, - offset, sum); - - return E1000_NOT_IMPLEMENTED; + return e1000_mng_host_if_write_generic(hw, buffer, length, offset, sum); } /** @@ -890,10 +899,7 @@ s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer, u16 length, s32 e1000_mng_write_cmd_header(struct e1000_hw *hw, struct e1000_host_mng_command_header *hdr) { - if (hw->mac.ops.mng_write_cmd_header) - return hw->mac.ops.mng_write_cmd_header(hw, hdr); - - return E1000_NOT_IMPLEMENTED; + return e1000_mng_write_cmd_header_generic(hw, hdr); } /** @@ -908,23 +914,20 @@ s32 e1000_mng_write_cmd_header(struct e1000_hw *hw, **/ s32 e1000_mng_enable_host_if(struct e1000_hw *hw) { - if (hw->mac.ops.mng_enable_host_if) - return hw->mac.ops.mng_enable_host_if(hw); - - return E1000_NOT_IMPLEMENTED; + return e1000_mng_enable_host_if_generic(hw); } /** - * e1000_wait_autoneg - Waits for autonegotiation completion + * e1000_set_obff_timer - Set Optimized Buffer Flush/Fill timer * @hw: pointer to the HW structure + * @itr: u32 indicating itr value * - * Waits for autoneg to complete. Currently no func pointer exists and all - * implementations are handled in the generic version of this function. + * Set the OBFF timer based on the given interrupt rate. **/ -s32 e1000_wait_autoneg(struct e1000_hw *hw) +s32 e1000_set_obff_timer(struct e1000_hw *hw, u32 itr) { - if (hw->mac.ops.wait_autoneg) - return hw->mac.ops.wait_autoneg(hw); + if (hw->mac.ops.set_obff_timer) + return hw->mac.ops.set_obff_timer(hw, itr); return E1000_SUCCESS; } diff --git a/sys/dev/e1000/e1000_api.h b/sys/dev/e1000/e1000_api.h index 4c061c0958b..69db1be90db 100644 --- a/sys/dev/e1000/e1000_api.h +++ b/sys/dev/e1000/e1000_api.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2012, Intel Corporation + Copyright (c) 2001-2013, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -51,6 +51,7 @@ extern void e1000_power_up_fiber_serdes_link(struct e1000_hw *hw); extern void e1000_shutdown_fiber_serdes_link(struct e1000_hw *hw); extern void e1000_init_function_pointers_i210(struct e1000_hw *hw); +s32 e1000_set_obff_timer(struct e1000_hw *hw, u32 itr); s32 e1000_set_mac_type(struct e1000_hw *hw); s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device); s32 e1000_init_mac_params(struct e1000_hw *hw); @@ -105,7 +106,6 @@ s32 e1000_read_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); s32 e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_write_nvm(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); -s32 e1000_wait_autoneg(struct e1000_hw *hw); s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active); s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active); bool e1000_check_mng_mode(struct e1000_hw *hw); @@ -162,4 +162,6 @@ u32 e1000_translate_register_82542(u32 reg); (((length) > min_frame_size) && \ ((length) <= (max_frame_size + VLAN_TAG_SIZE + 1))))) -#endif +#define E1000_MAX(a, b) ((a) > (b) ? (a) : (b)) +#define E1000_DIVIDE_ROUND_UP(a, b) (((a) + (b) - 1) / (b)) /* ceil(a/b) */ +#endif /* _E1000_API_H_ */ diff --git a/sys/dev/e1000/e1000_defines.h b/sys/dev/e1000/e1000_defines.h index a4a0ed05004..48c04b013db 100644 --- a/sys/dev/e1000/e1000_defines.h +++ b/sys/dev/e1000/e1000_defines.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2012, Intel Corporation + Copyright (c) 2001-2013, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -43,15 +43,7 @@ /* Wake Up Control */ #define E1000_WUC_APME 0x00000001 /* APM Enable */ #define E1000_WUC_PME_EN 0x00000002 /* PME Enable */ -#define E1000_WUC_PME_STATUS 0x00000004 /* PME Status */ -#define E1000_WUC_APMPME 0x00000008 /* Assert PME on APM Wakeup */ -#define E1000_WUC_LSCWE 0x00000010 /* Link Status wake up enable */ -#define E1000_WUC_PPROXYE 0x00000010 /* Protocol Proxy Enable */ -#define E1000_WUC_LSCWO 0x00000020 /* Link Status wake up override */ -#define E1000_WUC_SPM 0x80000000 /* Enable SPM */ #define E1000_WUC_PHY_WAKE 0x00000100 /* if PHY supports wakeup */ -#define E1000_WUC_FLX6_PHY 0x4000 /* Flexible Filter 6 Enable */ -#define E1000_WUC_FLX7_PHY 0x8000 /* Flexible Filter 7 Enable */ /* Wake Up Filter Control */ #define E1000_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */ @@ -61,41 +53,7 @@ #define E1000_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */ #define E1000_WUFC_ARP 0x00000020 /* ARP Request Packet Wakeup Enable */ #define E1000_WUFC_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Enable */ -#define E1000_WUFC_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Enable */ -#define E1000_WUFC_IGNORE_TCO_PHY 0x00000800 /* Ignore WakeOn TCO packets */ -#define E1000_WUFC_FLX0_PHY 0x00001000 /* Flexible Filter 0 Enable */ -#define E1000_WUFC_FLX1_PHY 0x00002000 /* Flexible Filter 1 Enable */ -#define E1000_WUFC_FLX2_PHY 0x00004000 /* Flexible Filter 2 Enable */ -#define E1000_WUFC_FLX3_PHY 0x00008000 /* Flexible Filter 3 Enable */ -#define E1000_WUFC_FLX4_PHY 0x00000200 /* Flexible Filter 4 Enable */ -#define E1000_WUFC_FLX5_PHY 0x00000400 /* Flexible Filter 5 Enable */ -#define E1000_WUFC_IGNORE_TCO 0x00008000 /* Ignore WakeOn TCO packets */ #define E1000_WUFC_FLX0 0x00010000 /* Flexible Filter 0 Enable */ -#define E1000_WUFC_FLX1 0x00020000 /* Flexible Filter 1 Enable */ -#define E1000_WUFC_FLX2 0x00040000 /* Flexible Filter 2 Enable */ -#define E1000_WUFC_FLX3 0x00080000 /* Flexible Filter 3 Enable */ -#define E1000_WUFC_FLX4 0x00100000 /* Flexible Filter 4 Enable */ -#define E1000_WUFC_FLX5 0x00200000 /* Flexible Filter 5 Enable */ -#define E1000_WUFC_FLX6 0x00400000 /* Flexible Filter 6 Enable */ -#define E1000_WUFC_FLX7 0x00800000 /* Flexible Filter 7 Enable */ -#define E1000_WUFC_FW_RST 0x80000000 /* Wake on FW Reset Enable */ -#define E1000_WUFC_ALL_FILTERS_PHY_4 0x0000F0FF /* wakeup filters mask */ -#define E1000_WUFC_FLX_OFFSET_PHY 12 /* Flexible Filters bits offset */ -#define E1000_WUFC_FLX_FILTERS_PHY_4 0x0000F000 /* 4 flexible filters mask */ -#define E1000_WUFC_ALL_FILTERS_PHY_6 0x0000F6FF /* 6 wakeup filters mask */ -#define E1000_WUFC_FLX_FILTERS_PHY_6 0x0000F600 /* 6 flexible filters mask */ -#define E1000_WUFC_ALL_FILTERS 0x000F00FF /* all wakeup filters mask */ -#define E1000_WUFC_ALL_FILTERS_6 0x003F00FF /* Mask all 6 wu filters */ -#define E1000_WUFC_ALL_FILTERS_8 0x00FF00FF /* Mask all 8 wu filters */ -#define E1000_WUFC_FLX_OFFSET 16 /* Flexible Filters bits offset */ -#define E1000_WUFC_FLX_FILTERS 0x000F0000 /* 4 flexible filters mask */ -#define E1000_WUFC_FLX_FILTERS_6 0x003F0000 /* 6 flexible filters mask */ -#define E1000_WUFC_FLX_FILTERS_8 0x00FF0000 /* 8 flexible filters mask */ -/* - * For 82576 to utilize Extended filter masks in addition to - * existing (filter) masks - */ -#define E1000_WUFC_EXT_FLX_FILTERS 0x00300000 /* Ext. FLX filter mask */ /* Wake Up Status */ #define E1000_WUS_LNKC E1000_WUFC_LNKC @@ -103,74 +61,18 @@ #define E1000_WUS_EX E1000_WUFC_EX #define E1000_WUS_MC E1000_WUFC_MC #define E1000_WUS_BC E1000_WUFC_BC -#define E1000_WUS_ARP E1000_WUFC_ARP -#define E1000_WUS_IPV4 E1000_WUFC_IPV4 -#define E1000_WUS_IPV6 E1000_WUFC_IPV6 -#define E1000_WUS_FLX0_PHY E1000_WUFC_FLX0_PHY -#define E1000_WUS_FLX1_PHY E1000_WUFC_FLX1_PHY -#define E1000_WUS_FLX2_PHY E1000_WUFC_FLX2_PHY -#define E1000_WUS_FLX3_PHY E1000_WUFC_FLX3_PHY -#define E1000_WUS_FLX_FILTERS_PHY_4 E1000_WUFC_FLX_FILTERS_PHY_4 -#define E1000_WUS_FLX0 E1000_WUFC_FLX0 -#define E1000_WUS_FLX1 E1000_WUFC_FLX1 -#define E1000_WUS_FLX2 E1000_WUFC_FLX2 -#define E1000_WUS_FLX3 E1000_WUFC_FLX3 -#define E1000_WUS_FLX4 E1000_WUFC_FLX4 -#define E1000_WUS_FLX5 E1000_WUFC_FLX5 -#define E1000_WUS_FLX6 E1000_WUFC_FLX6 -#define E1000_WUS_FLX7 E1000_WUFC_FLX7 -#define E1000_WUS_FLX4_PHY E1000_WUFC_FLX4_PHY -#define E1000_WUS_FLX5_PHY E1000_WUFC_FLX5_PHY -#define E1000_WUS_FLX6_PHY 0x0400 -#define E1000_WUS_FLX7_PHY 0x0800 -#define E1000_WUS_FLX_FILTERS E1000_WUFC_FLX_FILTERS -#define E1000_WUS_FLX_FILTERS_6 E1000_WUFC_FLX_FILTERS_6 -#define E1000_WUS_FLX_FILTERS_8 E1000_WUFC_FLX_FILTERS_8 -#define E1000_WUS_FLX_FILTERS_PHY_6 E1000_WUFC_FLX_FILTERS_PHY_6 - -/* Wake Up Packet Length */ -#define E1000_WUPL_LENGTH_MASK 0x0FFF /* Only the lower 12 bits are valid */ - -/* Four Flexible Filters are supported */ -#define E1000_FLEXIBLE_FILTER_COUNT_MAX 4 -/* Six Flexible Filters are supported */ -#define E1000_FLEXIBLE_FILTER_COUNT_MAX_6 6 -/* Eight Flexible Filters are supported */ -#define E1000_FLEXIBLE_FILTER_COUNT_MAX_8 8 -/* Two Extended Flexible Filters are supported (82576) */ -#define E1000_EXT_FLEXIBLE_FILTER_COUNT_MAX 2 -#define E1000_FHFT_LENGTH_OFFSET 0xFC /* Length byte in FHFT */ -#define E1000_FHFT_LENGTH_MASK 0x0FF /* Length in lower byte */ - -/* Each Flexible Filter is at most 128 (0x80) bytes in length */ -#define E1000_FLEXIBLE_FILTER_SIZE_MAX 128 - -#define E1000_FFLT_SIZE E1000_FLEXIBLE_FILTER_COUNT_MAX -#define E1000_FFLT_SIZE_6 E1000_FLEXIBLE_FILTER_COUNT_MAX_6 -#define E1000_FFLT_SIZE_8 E1000_FLEXIBLE_FILTER_COUNT_MAX_8 -#define E1000_FFMT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX -#define E1000_FFVT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX /* Extended Device Control */ -#define E1000_CTRL_EXT_GPI0_EN 0x00000001 /* Maps SDP4 to GPI0 */ -#define E1000_CTRL_EXT_GPI1_EN 0x00000002 /* Maps SDP5 to GPI1 */ -#define E1000_CTRL_EXT_PHYINT_EN E1000_CTRL_EXT_GPI1_EN -#define E1000_CTRL_EXT_GPI2_EN 0x00000004 /* Maps SDP6 to GPI2 */ -#define E1000_CTRL_EXT_GPI3_EN 0x00000008 /* Maps SDP7 to GPI3 */ -/* Reserved (bits 4,5) in >= 82575 */ +#define E1000_CTRL_EXT_LPCD 0x00000004 /* LCD Power Cycle Done */ #define E1000_CTRL_EXT_SDP4_DATA 0x00000010 /* SW Definable Pin 4 data */ -#define E1000_CTRL_EXT_SDP5_DATA 0x00000020 /* SW Definable Pin 5 data */ -#define E1000_CTRL_EXT_PHY_INT E1000_CTRL_EXT_SDP5_DATA #define E1000_CTRL_EXT_SDP6_DATA 0x00000040 /* SW Definable Pin 6 data */ #define E1000_CTRL_EXT_SDP3_DATA 0x00000080 /* SW Definable Pin 3 data */ /* SDP 4/5 (bits 8,9) are reserved in >= 82575 */ #define E1000_CTRL_EXT_SDP4_DIR 0x00000100 /* Direction of SDP4 0=in 1=out */ -#define E1000_CTRL_EXT_SDP5_DIR 0x00000200 /* Direction of SDP5 0=in 1=out */ #define E1000_CTRL_EXT_SDP6_DIR 0x00000400 /* Direction of SDP6 0=in 1=out */ #define E1000_CTRL_EXT_SDP3_DIR 0x00000800 /* Direction of SDP3 0=in 1=out */ -#define E1000_CTRL_EXT_ASDCHK 0x00001000 /* Initiate an ASD sequence */ +#define E1000_CTRL_EXT_FORCE_SMBUS 0x00000800 /* Force SMBus mode */ #define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */ -#define E1000_CTRL_EXT_IPS 0x00004000 /* Invert Power State */ /* Physical Func Reset Done Indication */ #define E1000_CTRL_EXT_PFRSTD 0x00004000 #define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */ @@ -179,42 +81,22 @@ #define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000 /* Offset of the link mode field in Ctrl Ext register */ #define E1000_CTRL_EXT_LINK_MODE_OFFSET 22 -#define E1000_CTRL_EXT_LINK_MODE_82580_MASK 0x01C00000 /*82580 bit 24:22*/ #define E1000_CTRL_EXT_LINK_MODE_1000BASE_KX 0x00400000 #define E1000_CTRL_EXT_LINK_MODE_GMII 0x00000000 -#define E1000_CTRL_EXT_LINK_MODE_TBI 0x00C00000 -#define E1000_CTRL_EXT_LINK_MODE_KMRN 0x00000000 #define E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES 0x00C00000 -#define E1000_CTRL_EXT_LINK_MODE_PCIX_SERDES 0x00800000 #define E1000_CTRL_EXT_LINK_MODE_SGMII 0x00800000 #define E1000_CTRL_EXT_EIAME 0x01000000 #define E1000_CTRL_EXT_IRCA 0x00000001 -#define E1000_CTRL_EXT_WR_WMARK_MASK 0x03000000 -#define E1000_CTRL_EXT_WR_WMARK_256 0x00000000 -#define E1000_CTRL_EXT_WR_WMARK_320 0x01000000 -#define E1000_CTRL_EXT_WR_WMARK_384 0x02000000 -#define E1000_CTRL_EXT_WR_WMARK_448 0x03000000 -#define E1000_CTRL_EXT_CANC 0x04000000 /* Int delay cancellation */ #define E1000_CTRL_EXT_DRV_LOAD 0x10000000 /* Drv loaded bit for FW */ -/* IAME enable bit (27) was removed in >= 82575 */ #define E1000_CTRL_EXT_IAME 0x08000000 /* Int ACK Auto-mask */ -/* packet buffer parity error detection enabled */ -#define E1000_CRTL_EXT_PB_PAREN 0x01000000 -/* descriptor FIFO parity error detection enable */ -#define E1000_CTRL_EXT_DF_PAREN 0x02000000 -#define E1000_CTRL_EXT_GHOST_PAREN 0x40000000 #define E1000_CTRL_EXT_PBA_CLR 0x80000000 /* PBA Clear */ #define E1000_CTRL_EXT_LSECCK 0x00001000 #define E1000_CTRL_EXT_PHYPDEN 0x00100000 #define E1000_I2CCMD_REG_ADDR_SHIFT 16 -#define E1000_I2CCMD_REG_ADDR 0x00FF0000 #define E1000_I2CCMD_PHY_ADDR_SHIFT 24 -#define E1000_I2CCMD_PHY_ADDR 0x07000000 #define E1000_I2CCMD_OPCODE_READ 0x08000000 #define E1000_I2CCMD_OPCODE_WRITE 0x00000000 -#define E1000_I2CCMD_RESET 0x10000000 #define E1000_I2CCMD_READY 0x20000000 -#define E1000_I2CCMD_INTERRUPT_ENA 0x40000000 #define E1000_I2CCMD_ERROR 0x80000000 #define E1000_I2CCMD_SFP_DATA_ADDR(a) (0x0000 + (a)) #define E1000_I2CCMD_SFP_DIAG_ADDR(a) (0x0100 + (a)) @@ -235,11 +117,9 @@ #define E1000_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */ #define E1000_RXD_STAT_IPCS 0x40 /* IP xsum calculated */ #define E1000_RXD_STAT_PIF 0x80 /* passed in-exact filter */ -#define E1000_RXD_STAT_CRCV 0x100 /* Speculative CRC Valid */ #define E1000_RXD_STAT_IPIDV 0x200 /* IP identification valid */ #define E1000_RXD_STAT_UDPV 0x400 /* Valid UDP checksum */ #define E1000_RXD_STAT_DYNINT 0x800 /* Pkt caused INT via DYNINT */ -#define E1000_RXD_STAT_ACK 0x8000 /* ACK Packet indication */ #define E1000_RXD_ERR_CE 0x01 /* CRC Error */ #define E1000_RXD_ERR_SE 0x02 /* Symbol Error */ #define E1000_RXD_ERR_SEQ 0x04 /* Sequence Error */ @@ -248,11 +128,8 @@ #define E1000_RXD_ERR_IPE 0x40 /* IP Checksum Error */ #define E1000_RXD_ERR_RXE 0x80 /* Rx Data Error */ #define E1000_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */ -#define E1000_RXD_SPC_PRI_MASK 0xE000 /* Priority is in upper 3 bits */ -#define E1000_RXD_SPC_PRI_SHIFT 13 -#define E1000_RXD_SPC_CFI_MASK 0x1000 /* CFI is bit 12 */ -#define E1000_RXD_SPC_CFI_SHIFT 12 +#define E1000_RXDEXT_STATERR_TST 0x00000100 /* Time Stamp taken */ #define E1000_RXDEXT_STATERR_LB 0x00040000 #define E1000_RXDEXT_STATERR_CE 0x01000000 #define E1000_RXDEXT_STATERR_SE 0x02000000 @@ -262,13 +139,6 @@ #define E1000_RXDEXT_STATERR_IPE 0x40000000 #define E1000_RXDEXT_STATERR_RXE 0x80000000 -#define E1000_RXDEXT_LSECH 0x01000000 -#define E1000_RXDEXT_LSECE_MASK 0x60000000 -#define E1000_RXDEXT_LSECE_NO_ERROR 0x00000000 -#define E1000_RXDEXT_LSECE_NO_SA_MATCH 0x20000000 -#define E1000_RXDEXT_LSECE_REPLAY_DETECT 0x40000000 -#define E1000_RXDEXT_LSECE_BAD_SIG 0x60000000 - /* mask to determine if packets should be dropped due to frame errors */ #define E1000_RXD_ERR_FRAME_ERR_MASK ( \ E1000_RXD_ERR_CE | \ @@ -285,57 +155,25 @@ E1000_RXDEXT_STATERR_CXE | \ E1000_RXDEXT_STATERR_RXE) -#define E1000_MRQC_ENABLE_MASK 0x00000007 -#define E1000_MRQC_ENABLE_RSS_2Q 0x00000001 -#define E1000_MRQC_ENABLE_RSS_INT 0x00000004 #define E1000_MRQC_RSS_FIELD_MASK 0xFFFF0000 #define E1000_MRQC_RSS_FIELD_IPV4_TCP 0x00010000 #define E1000_MRQC_RSS_FIELD_IPV4 0x00020000 #define E1000_MRQC_RSS_FIELD_IPV6_TCP_EX 0x00040000 -#define E1000_MRQC_RSS_FIELD_IPV6_EX 0x00080000 #define E1000_MRQC_RSS_FIELD_IPV6 0x00100000 #define E1000_MRQC_RSS_FIELD_IPV6_TCP 0x00200000 #define E1000_RXDPS_HDRSTAT_HDRSP 0x00008000 -#define E1000_RXDPS_HDRSTAT_HDRLEN_MASK 0x000003FF /* Management Control */ #define E1000_MANC_SMBUS_EN 0x00000001 /* SMBus Enabled - RO */ #define E1000_MANC_ASF_EN 0x00000002 /* ASF Enabled - RO */ -#define E1000_MANC_R_ON_FORCE 0x00000004 /* Reset on Force TCO - RO */ -#define E1000_MANC_RMCP_EN 0x00000100 /* Enable RCMP 026Fh Filtering */ -#define E1000_MANC_0298_EN 0x00000200 /* Enable RCMP 0298h Filtering */ -#define E1000_MANC_IPV4_EN 0x00000400 /* Enable IPv4 */ -#define E1000_MANC_IPV6_EN 0x00000800 /* Enable IPv6 */ -#define E1000_MANC_SNAP_EN 0x00001000 /* Accept LLC/SNAP */ #define E1000_MANC_ARP_EN 0x00002000 /* Enable ARP Request Filtering */ -/* Enable Neighbor Discovery Filtering */ -#define E1000_MANC_NEIGHBOR_EN 0x00004000 -#define E1000_MANC_ARP_RES_EN 0x00008000 /* Enable ARP response Filtering */ -#define E1000_MANC_TCO_RESET 0x00010000 /* TCO Reset Occurred */ #define E1000_MANC_RCV_TCO_EN 0x00020000 /* Receive TCO Packets Enabled */ -#define E1000_MANC_REPORT_STATUS 0x00040000 /* Status Reporting Enabled */ -#define E1000_MANC_RCV_ALL 0x00080000 /* Receive All Enabled */ #define E1000_MANC_BLK_PHY_RST_ON_IDE 0x00040000 /* Block phy resets */ /* Enable MAC address filtering */ #define E1000_MANC_EN_MAC_ADDR_FILTER 0x00100000 /* Enable MNG packets to host memory */ #define E1000_MANC_EN_MNG2HOST 0x00200000 -/* Enable IP address filtering */ -#define E1000_MANC_EN_IP_ADDR_FILTER 0x00400000 -#define E1000_MANC_EN_XSUM_FILTER 0x00800000 /* Ena checksum filtering */ -#define E1000_MANC_BR_EN 0x01000000 /* Ena broadcast filtering */ -#define E1000_MANC_SMB_REQ 0x01000000 /* SMBus Request */ -#define E1000_MANC_SMB_GNT 0x02000000 /* SMBus Grant */ -#define E1000_MANC_SMB_CLK_IN 0x04000000 /* SMBus Clock In */ -#define E1000_MANC_SMB_DATA_IN 0x08000000 /* SMBus Data In */ -#define E1000_MANC_SMB_DATA_OUT 0x10000000 /* SMBus Data Out */ -#define E1000_MANC_SMB_CLK_OUT 0x20000000 /* SMBus Clock Out */ -#define E1000_MANC_MPROXYE 0x40000000 /* Mngment Proxy Enable */ -#define E1000_MANC_EN_BMC2OS 0x10000000 /* OS2BMC is enabld or not */ - -#define E1000_MANC_SMB_DATA_OUT_SHIFT 28 /* SMBus Data Out Shift */ -#define E1000_MANC_SMB_CLK_OUT_SHIFT 29 /* SMBus Clock Out Shift */ #define E1000_MANC2H_PORT_623 0x00000020 /* Port 0x26f */ #define E1000_MANC2H_PORT_664 0x00000040 /* Port 0x298 */ @@ -351,19 +189,11 @@ #define E1000_RCTL_LPE 0x00000020 /* long packet enable */ #define E1000_RCTL_LBM_NO 0x00000000 /* no loopback mode */ #define E1000_RCTL_LBM_MAC 0x00000040 /* MAC loopback mode */ -#define E1000_RCTL_LBM_SLP 0x00000080 /* serial link loopback mode */ #define E1000_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */ -#define E1000_RCTL_DTYP_MASK 0x00000C00 /* Descriptor type mask */ #define E1000_RCTL_DTYP_PS 0x00000400 /* Packet Split descriptor */ #define E1000_RCTL_RDMTS_HALF 0x00000000 /* Rx desc min thresh size */ -#define E1000_RCTL_RDMTS_QUAT 0x00000100 /* Rx desc min thresh size */ -#define E1000_RCTL_RDMTS_EIGTH 0x00000200 /* Rx desc min thresh size */ #define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift */ -#define E1000_RCTL_MO_0 0x00000000 /* multicast offset 11:0 */ -#define E1000_RCTL_MO_1 0x00001000 /* multicast offset 12:1 */ -#define E1000_RCTL_MO_2 0x00002000 /* multicast offset 13:2 */ #define E1000_RCTL_MO_3 0x00003000 /* multicast offset 15:4 */ -#define E1000_RCTL_MDR 0x00004000 /* multicast desc ring 0 */ #define E1000_RCTL_BAM 0x00008000 /* broadcast enable */ /* these buffer sizes are valid if E1000_RCTL_BSEX is 0 */ #define E1000_RCTL_SZ_2048 0x00000000 /* Rx buffer size 2048 */ @@ -381,11 +211,8 @@ #define E1000_RCTL_PMCF 0x00800000 /* pass MAC control frames */ #define E1000_RCTL_BSEX 0x02000000 /* Buffer size extension */ #define E1000_RCTL_SECRC 0x04000000 /* Strip Ethernet CRC */ -#define E1000_RCTL_FLXBUF_MASK 0x78000000 /* Flexible buffer size */ -#define E1000_RCTL_FLXBUF_SHIFT 27 /* Flexible buffer shift */ -/* - * Use byte values for the following shift parameters +/* Use byte values for the following shift parameters * Usage: * psrctl |= (((ROUNDUP(value0, 128) >> E1000_PSRCTL_BSIZE0_SHIFT) & * E1000_PSRCTL_BSIZE0_MASK) | @@ -420,16 +247,11 @@ #define E1000_SWFW_PHY3_SM 0x40 #define E1000_SWFW_SW_MNG_SM 0x400 -/* FACTPS Definitions */ -#define E1000_FACTPS_LFS 0x40000000 /* LAN Function Select */ /* Device Control */ #define E1000_CTRL_FD 0x00000001 /* Full duplex.0=half; 1=full */ -#define E1000_CTRL_BEM 0x00000002 /* Endian Mode.0=little,1=big */ #define E1000_CTRL_PRIOR 0x00000004 /* Priority on PCI. 0=rx,1=fair */ #define E1000_CTRL_GIO_MASTER_DISABLE 0x00000004 /*Blocks new Master reqs */ #define E1000_CTRL_LRST 0x00000008 /* Link reset. 0=normal,1=reset */ -#define E1000_CTRL_TME 0x00000010 /* Test mode. 0=normal,1=test */ -#define E1000_CTRL_SLE 0x00000020 /* Serial Link on 0=dis,1=en */ #define E1000_CTRL_ASDE 0x00000020 /* Auto-speed detect enable */ #define E1000_CTRL_SLU 0x00000040 /* Set link up (Force Link) */ #define E1000_CTRL_ILOS 0x00000080 /* Invert Loss-Of Signal */ @@ -437,50 +259,35 @@ #define E1000_CTRL_SPD_10 0x00000000 /* Force 10Mb */ #define E1000_CTRL_SPD_100 0x00000100 /* Force 100Mb */ #define E1000_CTRL_SPD_1000 0x00000200 /* Force 1Gb */ -#define E1000_CTRL_BEM32 0x00000400 /* Big Endian 32 mode */ #define E1000_CTRL_FRCSPD 0x00000800 /* Force Speed */ #define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */ -#define E1000_CTRL_D_UD_EN 0x00002000 /* Dock/Undock enable */ -/* Defined polarity of Dock/Undock indication in SDP[0] */ -#define E1000_CTRL_D_UD_POLARITY 0x00004000 -/* Reset both PHY ports, through PHYRST_N pin */ -#define E1000_CTRL_FORCE_PHY_RESET 0x00008000 -/* enable link status from external LINK_0 and LINK_1 pins */ -#define E1000_CTRL_EXT_LINK_EN 0x00010000 #define E1000_CTRL_LANPHYPC_OVERRIDE 0x00010000 /* SW control of LANPHYPC */ #define E1000_CTRL_LANPHYPC_VALUE 0x00020000 /* SW value of LANPHYPC */ +#define E1000_CTRL_MEHE 0x00080000 /* Memory Error Handling Enable */ #define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */ #define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */ #define E1000_CTRL_SWDPIN2 0x00100000 /* SWDPIN 2 value */ #define E1000_CTRL_ADVD3WUC 0x00100000 /* D3 WUC */ +#define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000 /* PHY PM enable */ #define E1000_CTRL_SWDPIN3 0x00200000 /* SWDPIN 3 value */ #define E1000_CTRL_SWDPIO0 0x00400000 /* SWDPIN 0 Input or output */ -#define E1000_CTRL_SWDPIO1 0x00800000 /* SWDPIN 1 input or output */ #define E1000_CTRL_SWDPIO2 0x01000000 /* SWDPIN 2 input or output */ #define E1000_CTRL_SWDPIO3 0x02000000 /* SWDPIN 3 input or output */ #define E1000_CTRL_RST 0x04000000 /* Global reset */ #define E1000_CTRL_RFCE 0x08000000 /* Receive Flow Control enable */ #define E1000_CTRL_TFCE 0x10000000 /* Transmit flow control enable */ -#define E1000_CTRL_RTE 0x20000000 /* Routing tag enable */ #define E1000_CTRL_VME 0x40000000 /* IEEE VLAN mode enable */ #define E1000_CTRL_PHY_RST 0x80000000 /* PHY Reset */ -#define E1000_CTRL_SW2FW_INT 0x02000000 /* Initiate an interrupt to ME */ #define E1000_CTRL_I2C_ENA 0x02000000 /* I2C enable */ -/* - * Bit definitions for the Management Data IO (MDIO) and Management Data - * Clock (MDC) pins in the Device Control Register. - */ -#define E1000_CTRL_PHY_RESET_DIR E1000_CTRL_SWDPIO0 -#define E1000_CTRL_PHY_RESET E1000_CTRL_SWDPIN0 #define E1000_CTRL_MDIO_DIR E1000_CTRL_SWDPIO2 #define E1000_CTRL_MDIO E1000_CTRL_SWDPIN2 #define E1000_CTRL_MDC_DIR E1000_CTRL_SWDPIO3 #define E1000_CTRL_MDC E1000_CTRL_SWDPIN3 -#define E1000_CTRL_PHY_RESET_DIR4 E1000_CTRL_EXT_SDP4_DIR -#define E1000_CTRL_PHY_RESET4 E1000_CTRL_EXT_SDP4_DATA #define E1000_CONNSW_ENRGSRC 0x4 +#define E1000_CONNSW_PHYSD 0x400 +#define E1000_CONNSW_SERDESD 0x200 #define E1000_PCS_CFG_PCS_EN 8 #define E1000_PCS_LCTL_FLV_LINK_UP 1 #define E1000_PCS_LCTL_FSV_10 0 @@ -489,65 +296,37 @@ #define E1000_PCS_LCTL_FDV_FULL 8 #define E1000_PCS_LCTL_FSD 0x10 #define E1000_PCS_LCTL_FORCE_LINK 0x20 -#define E1000_PCS_LCTL_LOW_LINK_LATCH 0x40 #define E1000_PCS_LCTL_FORCE_FCTRL 0x80 #define E1000_PCS_LCTL_AN_ENABLE 0x10000 #define E1000_PCS_LCTL_AN_RESTART 0x20000 #define E1000_PCS_LCTL_AN_TIMEOUT 0x40000 -#define E1000_PCS_LCTL_AN_SGMII_BYPASS 0x80000 -#define E1000_PCS_LCTL_AN_SGMII_TRIGGER 0x100000 -#define E1000_PCS_LCTL_FAST_LINK_TIMER 0x1000000 -#define E1000_PCS_LCTL_LINK_OK_FIX 0x2000000 -#define E1000_PCS_LCTL_CRS_ON_NI 0x4000000 #define E1000_ENABLE_SERDES_LOOPBACK 0x0410 #define E1000_PCS_LSTS_LINK_OK 1 -#define E1000_PCS_LSTS_SPEED_10 0 #define E1000_PCS_LSTS_SPEED_100 2 #define E1000_PCS_LSTS_SPEED_1000 4 #define E1000_PCS_LSTS_DUPLEX_FULL 8 #define E1000_PCS_LSTS_SYNK_OK 0x10 #define E1000_PCS_LSTS_AN_COMPLETE 0x10000 -#define E1000_PCS_LSTS_AN_PAGE_RX 0x20000 -#define E1000_PCS_LSTS_AN_TIMED_OUT 0x40000 -#define E1000_PCS_LSTS_AN_REMOTE_FAULT 0x80000 -#define E1000_PCS_LSTS_AN_ERROR_RWS 0x100000 /* Device Status */ #define E1000_STATUS_FD 0x00000001 /* Duplex 0=half 1=full */ #define E1000_STATUS_LU 0x00000002 /* Link up.0=no,1=link */ #define E1000_STATUS_FUNC_MASK 0x0000000C /* PCI Function Mask */ #define E1000_STATUS_FUNC_SHIFT 2 -#define E1000_STATUS_FUNC_0 0x00000000 /* Function 0 */ #define E1000_STATUS_FUNC_1 0x00000004 /* Function 1 */ #define E1000_STATUS_TXOFF 0x00000010 /* transmission paused */ -#define E1000_STATUS_TBIMODE 0x00000020 /* TBI mode */ -#define E1000_STATUS_SPEED_MASK 0x000000C0 +#define E1000_STATUS_SPEED_MASK 0x000000C0 #define E1000_STATUS_SPEED_10 0x00000000 /* Speed 10Mb/s */ #define E1000_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */ #define E1000_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */ #define E1000_STATUS_LAN_INIT_DONE 0x00000200 /* Lan Init Compltn by NVM */ -#define E1000_STATUS_ASDV 0x00000300 /* Auto speed detect value */ #define E1000_STATUS_PHYRA 0x00000400 /* PHY Reset Asserted */ -/* Change in Dock/Undock state clear on write '0'. */ -#define E1000_STATUS_DOCK_CI 0x00000800 #define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Master request status */ -#define E1000_STATUS_MTXCKOK 0x00000400 /* MTX clock running OK */ #define E1000_STATUS_PCI66 0x00000800 /* In 66Mhz slot */ #define E1000_STATUS_BUS64 0x00001000 /* In 64 bit slot */ #define E1000_STATUS_PCIX_MODE 0x00002000 /* PCI-X mode */ #define E1000_STATUS_PCIX_SPEED 0x0000C000 /* PCI-X bus speed */ -#define E1000_STATUS_BMC_SKU_0 0x00100000 /* BMC USB redirect disbld */ -#define E1000_STATUS_BMC_SKU_1 0x00200000 /* BMC SRAM disabled */ -#define E1000_STATUS_BMC_SKU_2 0x00400000 /* BMC SDRAM disabled */ -#define E1000_STATUS_BMC_CRYPTO 0x00800000 /* BMC crypto disabled */ -/* BMC external code execution disabled */ -#define E1000_STATUS_BMC_LITE 0x01000000 -#define E1000_STATUS_RGMII_ENABLE 0x02000000 /* RGMII disabled */ -#define E1000_STATUS_FUSE_8 0x04000000 -#define E1000_STATUS_FUSE_9 0x08000000 -#define E1000_STATUS_SERDES0_DIS 0x10000000 /* SERDES disbld on port 0 */ -#define E1000_STATUS_SERDES1_DIS 0x20000000 /* SERDES disbld on port 1 */ /* Constants used to interpret the masked PCI-X bus speed. */ #define E1000_STATUS_PCIX_SPEED_66 0x00000000 /* PCI-X bus spd 50-66MHz */ @@ -578,8 +357,6 @@ ADVERTISE_100_FULL) #define E1000_ALL_100_SPEED (ADVERTISE_100_HALF | ADVERTISE_100_FULL) #define E1000_ALL_10_SPEED (ADVERTISE_10_HALF | ADVERTISE_10_FULL) -#define E1000_ALL_FULL_DUPLEX ( \ - ADVERTISE_10_FULL | ADVERTISE_100_FULL | ADVERTISE_1000_FULL) #define E1000_ALL_HALF_DUPLEX (ADVERTISE_10_HALF | ADVERTISE_100_HALF) #define AUTONEG_ADVERTISE_SPEED_DEFAULT E1000_ALL_SPEED_DUPLEX @@ -587,51 +364,20 @@ /* LED Control */ #define E1000_PHY_LED0_MODE_MASK 0x00000007 #define E1000_PHY_LED0_IVRT 0x00000008 -#define E1000_PHY_LED0_BLINK 0x00000010 #define E1000_PHY_LED0_MASK 0x0000001F #define E1000_LEDCTL_LED0_MODE_MASK 0x0000000F #define E1000_LEDCTL_LED0_MODE_SHIFT 0 -#define E1000_LEDCTL_LED0_BLINK_RATE 0x00000020 #define E1000_LEDCTL_LED0_IVRT 0x00000040 #define E1000_LEDCTL_LED0_BLINK 0x00000080 -#define E1000_LEDCTL_LED1_MODE_MASK 0x00000F00 -#define E1000_LEDCTL_LED1_MODE_SHIFT 8 -#define E1000_LEDCTL_LED1_BLINK_RATE 0x00002000 -#define E1000_LEDCTL_LED1_IVRT 0x00004000 -#define E1000_LEDCTL_LED1_BLINK 0x00008000 -#define E1000_LEDCTL_LED2_MODE_MASK 0x000F0000 -#define E1000_LEDCTL_LED2_MODE_SHIFT 16 -#define E1000_LEDCTL_LED2_BLINK_RATE 0x00200000 -#define E1000_LEDCTL_LED2_IVRT 0x00400000 -#define E1000_LEDCTL_LED2_BLINK 0x00800000 -#define E1000_LEDCTL_LED3_MODE_MASK 0x0F000000 -#define E1000_LEDCTL_LED3_MODE_SHIFT 24 -#define E1000_LEDCTL_LED3_BLINK_RATE 0x20000000 -#define E1000_LEDCTL_LED3_IVRT 0x40000000 -#define E1000_LEDCTL_LED3_BLINK 0x80000000 -#define E1000_LEDCTL_MODE_LINK_10_1000 0x0 -#define E1000_LEDCTL_MODE_LINK_100_1000 0x1 #define E1000_LEDCTL_MODE_LINK_UP 0x2 -#define E1000_LEDCTL_MODE_ACTIVITY 0x3 -#define E1000_LEDCTL_MODE_LINK_ACTIVITY 0x4 -#define E1000_LEDCTL_MODE_LINK_10 0x5 -#define E1000_LEDCTL_MODE_LINK_100 0x6 -#define E1000_LEDCTL_MODE_LINK_1000 0x7 -#define E1000_LEDCTL_MODE_PCIX_MODE 0x8 -#define E1000_LEDCTL_MODE_FULL_DUPLEX 0x9 -#define E1000_LEDCTL_MODE_COLLISION 0xA -#define E1000_LEDCTL_MODE_BUS_SPEED 0xB -#define E1000_LEDCTL_MODE_BUS_SIZE 0xC -#define E1000_LEDCTL_MODE_PAUSED 0xD #define E1000_LEDCTL_MODE_LED_ON 0xE #define E1000_LEDCTL_MODE_LED_OFF 0xF /* Transmit Descriptor bit definitions */ #define E1000_TXD_DTYP_D 0x00100000 /* Data Descriptor */ #define E1000_TXD_DTYP_C 0x00000000 /* Context Descriptor */ -#define E1000_TXD_POPTS_SHIFT 8 /* POPTS shift */ #define E1000_TXD_POPTS_IXSM 0x01 /* Insert IP checksum */ #define E1000_TXD_POPTS_TXSM 0x02 /* Insert TCP/UDP checksum */ #define E1000_TXD_CMD_EOP 0x01000000 /* End of Packet */ @@ -650,21 +396,14 @@ #define E1000_TXD_CMD_IP 0x02000000 /* IP packet */ #define E1000_TXD_CMD_TSE 0x04000000 /* TCP Seg enable */ #define E1000_TXD_STAT_TC 0x00000004 /* Tx Underrun */ -/* Extended desc bits for Linksec and timesync */ -#define E1000_TXD_CMD_LINKSEC 0x10000000 /* Apply LinkSec on packet */ #define E1000_TXD_EXTCMD_TSTAMP 0x00000010 /* IEEE1588 Timestamp packet */ /* Transmit Control */ -#define E1000_TCTL_RST 0x00000001 /* software reset */ #define E1000_TCTL_EN 0x00000002 /* enable Tx */ -#define E1000_TCTL_BCE 0x00000004 /* busy check enable */ #define E1000_TCTL_PSP 0x00000008 /* pad short packets */ #define E1000_TCTL_CT 0x00000ff0 /* collision threshold */ #define E1000_TCTL_COLD 0x003ff000 /* collision distance */ -#define E1000_TCTL_SWXOFF 0x00400000 /* SW Xoff transmission */ -#define E1000_TCTL_PBE 0x00800000 /* Packet Burst Enable */ #define E1000_TCTL_RTLC 0x01000000 /* Re-transmit on late collision */ -#define E1000_TCTL_NRTU 0x02000000 /* No Re-transmit on underrun */ #define E1000_TCTL_MULR 0x10000000 /* Multiple request support */ /* Transmit Arbitration Count */ @@ -672,29 +411,19 @@ /* SerDes Control */ #define E1000_SCTL_DISABLE_SERDES_LOOPBACK 0x0400 +#define E1000_SCTL_ENABLE_SERDES_LOOPBACK 0x0410 /* Receive Checksum Control */ -#define E1000_RXCSUM_PCSS_MASK 0x000000FF /* Packet Checksum Start */ #define E1000_RXCSUM_IPOFL 0x00000100 /* IPv4 checksum offload */ #define E1000_RXCSUM_TUOFL 0x00000200 /* TCP / UDP checksum offload */ -#define E1000_RXCSUM_IPV6OFL 0x00000400 /* IPv6 checksum offload */ #define E1000_RXCSUM_CRCOFL 0x00000800 /* CRC32 offload enable */ #define E1000_RXCSUM_IPPCSE 0x00001000 /* IP payload checksum enable */ #define E1000_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */ /* Header split receive */ -#define E1000_RFCTL_ISCSI_DIS 0x00000001 -#define E1000_RFCTL_ISCSI_DWC_MASK 0x0000003E -#define E1000_RFCTL_ISCSI_DWC_SHIFT 1 #define E1000_RFCTL_NFSW_DIS 0x00000040 #define E1000_RFCTL_NFSR_DIS 0x00000080 -#define E1000_RFCTL_NFS_VER_MASK 0x00000300 -#define E1000_RFCTL_NFS_VER_SHIFT 8 -#define E1000_RFCTL_IPV6_DIS 0x00000400 -#define E1000_RFCTL_IPV6_XSUM_DIS 0x00000800 #define E1000_RFCTL_ACK_DIS 0x00001000 -#define E1000_RFCTL_ACKD_DIS 0x00002000 -#define E1000_RFCTL_IPFRSP_DIS 0x00004000 #define E1000_RFCTL_EXTEN 0x00008000 #define E1000_RFCTL_IPV6_EX_DIS 0x00010000 #define E1000_RFCTL_NEW_IPV6_EXT_DIS 0x00020000 @@ -712,8 +441,6 @@ #define DEFAULT_82543_TIPG_IPGT_COPPER 8 #define E1000_TIPG_IPGT_MASK 0x000003FF -#define E1000_TIPG_IPGR1_MASK 0x000FFC00 -#define E1000_TIPG_IPGR2_MASK 0x3FF00000 #define DEFAULT_82542_TIPG_IPGR1 2 #define DEFAULT_82543_TIPG_IPGR1 8 @@ -741,7 +468,6 @@ #define E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK 0x0FFF0000 #define E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT 16 -#define E1000_PHY_CTRL_SPD_EN 0x00000001 #define E1000_PHY_CTRL_D0A_LPLU 0x00000002 #define E1000_PHY_CTRL_NOND0A_LPLU 0x00000004 #define E1000_PHY_CTRL_NOND0A_GBE_DISABLE 0x00000008 @@ -749,8 +475,10 @@ #define E1000_KABGTXD_BGSQLBIAS 0x00050000 +/* Low Power IDLE Control */ +#define E1000_LPIC_LPIET_SHIFT 24 /* Low Power Idle Entry Time */ + /* PBA constants */ -#define E1000_PBA_6K 0x0006 /* 6KB */ #define E1000_PBA_8K 0x0008 /* 8KB */ #define E1000_PBA_10K 0x000A /* 10KB */ #define E1000_PBA_12K 0x000C /* 12KB */ @@ -770,10 +498,15 @@ #define E1000_PBA_48K 0x0030 /* 48KB */ #define E1000_PBA_64K 0x0040 /* 64KB */ -#define E1000_PBA_RXA_MASK 0xFFFF; +#define E1000_PBA_RXA_MASK 0xFFFF #define E1000_PBS_16K E1000_PBA_16K -#define E1000_PBS_24K E1000_PBA_24K + +/* Uncorrectable/correctable ECC Error counts and enable bits */ +#define E1000_PBECCSTS_CORR_ERR_CNT_MASK 0x000000FF +#define E1000_PBECCSTS_UNCORR_ERR_CNT_MASK 0x0000FF00 +#define E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT 8 +#define E1000_PBECCSTS_ECC_ENABLE 0x00010000 #define IFS_MAX 80 #define IFS_MIN 40 @@ -784,7 +517,6 @@ /* SW Semaphore Register */ #define E1000_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */ #define E1000_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */ -#define E1000_SWSM_WMNG 0x00000004 /* Wake MNG Clock */ #define E1000_SWSM_DRV_LOAD 0x00000008 /* Driver Loaded Bit */ #define E1000_SWSM2_LOCK 0x00000002 /* Secondary driver semaphore bit */ @@ -798,33 +530,19 @@ #define E1000_ICR_RXO 0x00000040 /* Rx overrun */ #define E1000_ICR_RXT0 0x00000080 /* Rx timer intr (ring 0) */ #define E1000_ICR_VMMB 0x00000100 /* VM MB event */ -#define E1000_ICR_MDAC 0x00000200 /* MDIO access complete */ #define E1000_ICR_RXCFG 0x00000400 /* Rx /c/ ordered set */ #define E1000_ICR_GPI_EN0 0x00000800 /* GP Int 0 */ #define E1000_ICR_GPI_EN1 0x00001000 /* GP Int 1 */ #define E1000_ICR_GPI_EN2 0x00002000 /* GP Int 2 */ #define E1000_ICR_GPI_EN3 0x00004000 /* GP Int 3 */ #define E1000_ICR_TXD_LOW 0x00008000 -#define E1000_ICR_SRPD 0x00010000 -#define E1000_ICR_ACK 0x00020000 /* Receive Ack frame */ #define E1000_ICR_MNG 0x00040000 /* Manageability event */ -#define E1000_ICR_DOCK 0x00080000 /* Dock/Undock */ +#define E1000_ICR_ECCER 0x00400000 /* Uncorrectable ECC Error */ +#define E1000_ICR_TS 0x00080000 /* Time Sync Interrupt */ #define E1000_ICR_DRSTA 0x40000000 /* Device Reset Asserted */ /* If this bit asserted, the driver should claim the interrupt */ #define E1000_ICR_INT_ASSERTED 0x80000000 -#define E1000_ICR_RXD_FIFO_PAR0 0x00100000 /* Q0 Rx desc FIFO parity error */ -#define E1000_ICR_TXD_FIFO_PAR0 0x00200000 /* Q0 Tx desc FIFO parity error */ -#define E1000_ICR_HOST_ARB_PAR 0x00400000 /* host arb read buffer parity err */ -#define E1000_ICR_PB_PAR 0x00800000 /* packet buffer parity error */ -#define E1000_ICR_RXD_FIFO_PAR1 0x01000000 /* Q1 Rx desc FIFO parity error */ -#define E1000_ICR_TXD_FIFO_PAR1 0x02000000 /* Q1 Tx desc FIFO parity error */ -#define E1000_ICR_ALL_PARITY 0x03F00000 /* all parity error bits */ -/* FW changed the status of DISSW bit in the FWSM */ -#define E1000_ICR_DSW 0x00000020 -/* LAN connected device generates an interrupt */ -#define E1000_ICR_PHYINT 0x00001000 #define E1000_ICR_DOUTSYNC 0x10000000 /* NIC DMA out of sync */ -#define E1000_ICR_EPRST 0x00100000 /* ME hardware reset occurs */ #define E1000_ICR_RXQ0 0x00100000 /* Rx Queue 0 Interrupt */ #define E1000_ICR_RXQ1 0x00200000 /* Rx Queue 1 Interrupt */ #define E1000_ICR_TXQ0 0x00400000 /* Tx Queue 0 Interrupt */ @@ -862,18 +580,7 @@ #define E1000_TCPTIMER_COUNT_FINISH 0x00000400 /* Count finish */ #define E1000_TCPTIMER_LOOP 0x00000800 /* Loop */ -/* - * This defines the bits that are set in the Interrupt Mask - * Set/Read Register. Each bit is documented below: - * o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0) - * o RXSEQ = Receive Sequence Error - */ -#define POLL_IMS_ENABLE_MASK ( \ - E1000_IMS_RXDMT0 | \ - E1000_IMS_RXSEQ) - -/* - * This defines the bits that are set in the Interrupt Mask +/* This defines the bits that are set in the Interrupt Mask * Set/Read Register. Each bit is documented below: * o RXT0 = Receiver Timer Interrupt (ring 0) * o TXDW = Transmit Descriptor Written Back @@ -897,34 +604,11 @@ #define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* Rx desc min. threshold */ #define E1000_IMS_RXO E1000_ICR_RXO /* Rx overrun */ #define E1000_IMS_RXT0 E1000_ICR_RXT0 /* Rx timer intr */ -#define E1000_IMS_MDAC E1000_ICR_MDAC /* MDIO access complete */ -#define E1000_IMS_RXCFG E1000_ICR_RXCFG /* Rx /c/ ordered set */ -#define E1000_IMS_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */ -#define E1000_IMS_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */ -#define E1000_IMS_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */ -#define E1000_IMS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */ #define E1000_IMS_TXD_LOW E1000_ICR_TXD_LOW -#define E1000_IMS_SRPD E1000_ICR_SRPD -#define E1000_IMS_ACK E1000_ICR_ACK /* Receive Ack frame */ -#define E1000_IMS_MNG E1000_ICR_MNG /* Manageability event */ -#define E1000_IMS_DOCK E1000_ICR_DOCK /* Dock/Undock */ +#define E1000_IMS_ECCER E1000_ICR_ECCER /* Uncorrectable ECC Error */ +#define E1000_IMS_TS E1000_ICR_TS /* Time Sync Interrupt */ #define E1000_IMS_DRSTA E1000_ICR_DRSTA /* Device Reset Asserted */ -/* Q0 Rx desc FIFO parity error */ -#define E1000_IMS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 -/* Q0 Tx desc FIFO parity error */ -#define E1000_IMS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 -/* host arb read buffer parity error */ -#define E1000_IMS_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR -/* packet buffer parity error */ -#define E1000_IMS_PB_PAR E1000_ICR_PB_PAR -/* Q1 Rx desc FIFO parity error */ -#define E1000_IMS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 -/* Q1 Tx desc FIFO parity error */ -#define E1000_IMS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 -#define E1000_IMS_DSW E1000_ICR_DSW -#define E1000_IMS_PHYINT E1000_ICR_PHYINT #define E1000_IMS_DOUTSYNC E1000_ICR_DOUTSYNC /* NIC DMA out of sync */ -#define E1000_IMS_EPRST E1000_ICR_EPRST #define E1000_IMS_RXQ0 E1000_ICR_RXQ0 /* Rx Queue 0 Interrupt */ #define E1000_IMS_RXQ1 E1000_ICR_RXQ1 /* Rx Queue 1 Interrupt */ #define E1000_IMS_TXQ0 E1000_ICR_TXQ0 /* Tx Queue 0 Interrupt */ @@ -947,41 +631,9 @@ #define E1000_EIMS_OTHER E1000_EICR_OTHER /* Interrupt Cause Active */ /* Interrupt Cause Set */ -#define E1000_ICS_TXDW E1000_ICR_TXDW /* Tx desc written back */ -#define E1000_ICS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ #define E1000_ICS_LSC E1000_ICR_LSC /* Link Status Change */ #define E1000_ICS_RXSEQ E1000_ICR_RXSEQ /* Rx sequence error */ #define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* Rx desc min. threshold */ -#define E1000_ICS_RXO E1000_ICR_RXO /* Rx overrun */ -#define E1000_ICS_RXT0 E1000_ICR_RXT0 /* Rx timer intr */ -#define E1000_ICS_MDAC E1000_ICR_MDAC /* MDIO access complete */ -#define E1000_ICS_RXCFG E1000_ICR_RXCFG /* Rx /c/ ordered set */ -#define E1000_ICS_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */ -#define E1000_ICS_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */ -#define E1000_ICS_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */ -#define E1000_ICS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */ -#define E1000_ICS_TXD_LOW E1000_ICR_TXD_LOW -#define E1000_ICS_SRPD E1000_ICR_SRPD -#define E1000_ICS_ACK E1000_ICR_ACK /* Receive Ack frame */ -#define E1000_ICS_MNG E1000_ICR_MNG /* Manageability event */ -#define E1000_ICS_DOCK E1000_ICR_DOCK /* Dock/Undock */ -#define E1000_ICS_DRSTA E1000_ICR_DRSTA /* Device Reset Aserted */ -/* Q0 Rx desc FIFO parity error */ -#define E1000_ICS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 -/* Q0 Tx desc FIFO parity error */ -#define E1000_ICS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 -/* host arb read buffer parity error */ -#define E1000_ICS_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR -/* packet buffer parity error */ -#define E1000_ICS_PB_PAR E1000_ICR_PB_PAR -/* Q1 Rx desc FIFO parity error */ -#define E1000_ICS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 -/* Q1 Tx desc FIFO parity error */ -#define E1000_ICS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 -#define E1000_ICS_DSW E1000_ICR_DSW -#define E1000_ICS_DOUTSYNC E1000_ICR_DOUTSYNC /* NIC DMA out of sync */ -#define E1000_ICS_PHYINT E1000_ICR_PHYINT -#define E1000_ICS_EPRST E1000_ICR_EPRST /* Extended Interrupt Cause Set */ #define E1000_EICS_RX_QUEUE0 E1000_EICR_RX_QUEUE0 /* Rx Queue 0 Interrupt */ @@ -1004,7 +656,6 @@ #define E1000_TXDCTL_HTHRESH 0x00003F00 /* TXDCTL Host Threshold */ #define E1000_TXDCTL_WTHRESH 0x003F0000 /* TXDCTL Writeback Threshold */ #define E1000_TXDCTL_GRAN 0x01000000 /* TXDCTL Granularity */ -#define E1000_TXDCTL_LWTHRESH 0xFE000000 /* TXDCTL Low Threshold */ #define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */ #define E1000_TXDCTL_MAX_TX_DESC_PREFETCH 0x0100001F /* GRAN=1, PTHRESH=31 */ /* Enable the counting of descriptors still to be processed. */ @@ -1019,8 +670,7 @@ #define VLAN_TAG_SIZE 4 /* 802.3ac tag (not DMA'd) */ #define E1000_VLAN_FILTER_TBL_SIZE 128 /* VLAN Filter Table (4096 bits) */ -/* Receive Address */ -/* +/* Receive Address * Number of high/low register pairs in the RAR. The RAR (Receive Address * Registers) holds the directed and multicast addresses that we monitor. * Technically, we have 16 spots. However, we reserve one of these spots @@ -1032,8 +682,6 @@ #define E1000_RAL_MAC_ADDR_LEN 4 #define E1000_RAH_MAC_ADDR_LEN 2 #define E1000_RAH_QUEUE_MASK_82575 0x000C0000 -#define E1000_RAH_POOL_MASK 0x03FC0000 -#define E1000_RAH_POOL_SHIFT 18 #define E1000_RAH_POOL_1 0x00040000 /* Error Codes */ @@ -1073,30 +721,21 @@ /* Flow Control */ #define E1000_FCRTH_RTH 0x0000FFF8 /* Mask Bits[15:3] for RTH */ -#define E1000_FCRTH_XFCE 0x80000000 /* External Flow Control Enable */ #define E1000_FCRTL_RTL 0x0000FFF8 /* Mask Bits[15:3] for RTL */ #define E1000_FCRTL_XONE 0x80000000 /* Enable XON frame transmission */ /* Transmit Configuration Word */ #define E1000_TXCW_FD 0x00000020 /* TXCW full duplex */ -#define E1000_TXCW_HD 0x00000040 /* TXCW half duplex */ #define E1000_TXCW_PAUSE 0x00000080 /* TXCW sym pause request */ #define E1000_TXCW_ASM_DIR 0x00000100 /* TXCW astm pause direction */ #define E1000_TXCW_PAUSE_MASK 0x00000180 /* TXCW pause request mask */ -#define E1000_TXCW_RF 0x00003000 /* TXCW remote fault */ -#define E1000_TXCW_NP 0x00008000 /* TXCW next page */ -#define E1000_TXCW_CW 0x0000ffff /* TxConfigWord mask */ -#define E1000_TXCW_TXC 0x40000000 /* Transmit Config control */ #define E1000_TXCW_ANE 0x80000000 /* Auto-neg enable */ /* Receive Configuration Word */ #define E1000_RXCW_CW 0x0000ffff /* RxConfigWord mask */ -#define E1000_RXCW_NC 0x04000000 /* Receive config no carrier */ #define E1000_RXCW_IV 0x08000000 /* Receive config invalid */ -#define E1000_RXCW_CC 0x10000000 /* Receive config change */ #define E1000_RXCW_C 0x20000000 /* Receive config */ #define E1000_RXCW_SYNCH 0x40000000 /* Receive config synch */ -#define E1000_RXCW_ANC 0x80000000 /* Auto-neg complete */ #define E1000_TSYNCTXCTL_VALID 0x00000001 /* Tx timestamp valid */ #define E1000_TSYNCTXCTL_ENABLED 0x00000010 /* enable Tx timestamping */ @@ -1109,6 +748,13 @@ #define E1000_TSYNCRXCTL_TYPE_ALL 0x08 #define E1000_TSYNCRXCTL_TYPE_EVENT_V2 0x0A #define E1000_TSYNCRXCTL_ENABLED 0x00000010 /* enable Rx timestamping */ +#define E1000_TSYNCRXCTL_SYSCFI 0x00000020 /* Sys clock frequency */ + +#define E1000_RXMTRL_PTP_V1_SYNC_MESSAGE 0x00000000 +#define E1000_RXMTRL_PTP_V1_DELAY_REQ_MESSAGE 0x00010000 + +#define E1000_RXMTRL_PTP_V2_SYNC_MESSAGE 0x00000000 +#define E1000_RXMTRL_PTP_V2_DELAY_REQ_MESSAGE 0x01000000 #define E1000_TSYNCRXCFG_PTP_V1_CTRLT_MASK 0x000000FF #define E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE 0x00 @@ -1130,6 +776,11 @@ #define E1000_TSYNCRXCFG_PTP_V2_MANAGEMENT_MESSAGE 0x0D00 #define E1000_TIMINCA_16NS_SHIFT 24 +#define E1000_TIMINCA_INCPERIOD_SHIFT 24 +#define E1000_TIMINCA_INCVALUE_MASK 0x00FFFFFF + +#define E1000_TSICR_TXTS 0x00000002 +#define E1000_TSIM_TXTS 0x00000002 /* TUPLE Filtering Configuration */ #define E1000_TTQF_DISABLE_MASK 0xF0008000 /* TTQF Disable Mask */ #define E1000_TTQF_QUEUE_ENABLE 0x100 /* TTQF Queue Enable Bit */ @@ -1170,7 +821,7 @@ #define E1000_EEER_EEE_NEG 0x20000000 /* EEE capability nego */ #define E1000_EEER_RX_LPI_STATUS 0x40000000 /* Rx in LPI state */ #define E1000_EEER_TX_LPI_STATUS 0x80000000 /* Tx in LPI state */ - +#define E1000_EEE_SU_LPI_CLK_STP 0x00800000 /* EEE LPI Clock Stop */ /* PCI Express Control */ #define E1000_GCR_RXD_NO_SNOOP 0x00000001 #define E1000_GCR_RXDSCW_NO_SNOOP 0x00000002 @@ -1314,10 +965,6 @@ #define E1000_EECD_CS 0x00000002 /* NVM Chip Select */ #define E1000_EECD_DI 0x00000004 /* NVM Data In */ #define E1000_EECD_DO 0x00000008 /* NVM Data Out */ -#define E1000_EECD_FWE_MASK 0x00000030 -#define E1000_EECD_FWE_DIS 0x00000010 /* Disable FLASH writes */ -#define E1000_EECD_FWE_EN 0x00000020 /* Enable FLASH writes */ -#define E1000_EECD_FWE_SHIFT 4 #define E1000_EECD_REQ 0x00000040 /* NVM Access Request */ #define E1000_EECD_GNT 0x00000080 /* NVM Access Grant */ #define E1000_EECD_PRES 0x00000100 /* NVM Present */ @@ -1335,28 +982,28 @@ #define E1000_EECD_AUTO_RD 0x00000200 /* NVM Auto Read done */ #define E1000_EECD_SIZE_EX_MASK 0x00007800 /* NVM Size */ #define E1000_EECD_SIZE_EX_SHIFT 11 -#define E1000_EECD_NVADDS 0x00018000 /* NVM Address Size */ -#define E1000_EECD_SELSHAD 0x00020000 /* Select Shadow RAM */ -#define E1000_EECD_INITSRAM 0x00040000 /* Initialize Shadow RAM */ #define E1000_EECD_FLUPD 0x00080000 /* Update FLASH */ #define E1000_EECD_AUPDEN 0x00100000 /* Ena Auto FLASH update */ -#define E1000_EECD_SHADV 0x00200000 /* Shadow RAM Data Valid */ #define E1000_EECD_SEC1VAL 0x00400000 /* Sector One Valid */ -#define E1000_EECD_SECVAL_SHIFT 22 #define E1000_EECD_SEC1VAL_VALID_MASK (E1000_EECD_AUTO_RD | E1000_EECD_PRES) #define E1000_EECD_FLUPD_I210 0x00800000 /* Update FLASH */ #define E1000_EECD_FLUDONE_I210 0x04000000 /* Update FLASH done */ #define E1000_EECD_FLASH_DETECTED_I210 0x00080000 /* FLASH detected */ +#define E1000_EECD_SEC1VAL_I210 0x02000000 /* Sector One Valid */ #define E1000_FLUDONE_ATTEMPTS 20000 #define E1000_EERD_EEWR_MAX_COUNT 512 /* buffered EEPROM words rw */ -#define E1000_I210_FIFO_SEL_RX 0x00 +#define E1000_I210_FIFO_SEL_RX 0x00 #define E1000_I210_FIFO_SEL_TX_QAV(_i) (0x02 + (_i)) #define E1000_I210_FIFO_SEL_TX_LEGACY E1000_I210_FIFO_SEL_TX_QAV(0) #define E1000_I210_FIFO_SEL_BMC2OS_TX 0x06 #define E1000_I210_FIFO_SEL_BMC2OS_RX 0x01 -#define E1000_NVM_SWDPIN0 0x0001 /* SWDPIN 0 NVM Value */ -#define E1000_NVM_LED_LOGIC 0x0020 /* Led Logic Word */ +#define E1000_I210_FLASH_SECTOR_SIZE 0x1000 /* 4KB FLASH sector unit size */ +/* Secure FLASH mode requires removing MSb */ +#define E1000_I210_FW_PTR_MASK 0x7FFF +/* Firmware code revision field word offset*/ +#define E1000_I210_FW_VER_OFFSET 328 + #define E1000_NVM_RW_REG_DATA 16 /* Offset to data in NVM read/write regs */ #define E1000_NVM_RW_REG_DONE 2 /* Offset to READ/WRITE done bit */ #define E1000_NVM_RW_REG_START 1 /* Start operation */ @@ -1368,13 +1015,11 @@ /* NVM Word Offsets */ #define NVM_COMPAT 0x0003 #define NVM_ID_LED_SETTINGS 0x0004 -#define NVM_VERSION 0x0005 #define NVM_SERDES_AMPLITUDE 0x0006 /* SERDES output amplitude */ #define NVM_PHY_CLASS_WORD 0x0007 -#define NVM_ETRACK_WORD 0x0042 -#define NVM_COMB_VER_OFF 0x0083 -#define NVM_COMB_VER_PTR 0x003d - +#define E1000_I210_NVM_FW_MODULE_PTR 0x0010 +#define E1000_I350_NVM_FW_MODULE_PTR 0x0051 +#define NVM_FUTURE_INIT_WORD1 0x0019 #define NVM_MAC_ADDR 0x0000 #define NVM_SUB_DEV_ID 0x000B #define NVM_SUB_VEN_ID 0x000C @@ -1385,15 +1030,15 @@ #define NVM_LED_1_CFG 0x001C #define NVM_LED_0_2_CFG 0x001F -#define NVM_INIT_CONTROL1_REG 0x000A +#define NVM_COMPAT_VALID_CSUM 0x0001 +#define NVM_FUTURE_INIT_WORD1_VALID_CSUM 0x0040 + #define NVM_INIT_CONTROL2_REG 0x000F -#define NVM_SWDEF_PINS_CTRL_PORT_1 0x0010 #define NVM_INIT_CONTROL3_PORT_B 0x0014 #define NVM_INIT_3GIO_3 0x001A #define NVM_SWDEF_PINS_CTRL_PORT_0 0x0020 #define NVM_INIT_CONTROL3_PORT_A 0x0024 #define NVM_CFG 0x0012 -#define NVM_FLASH_VERSION 0x0032 #define NVM_ALT_MAC_ADDR_PTR 0x0037 #define NVM_CHECKSUM_REG 0x003F #define NVM_COMPATIBILITY_REG_3 0x0003 @@ -1419,9 +1064,7 @@ #define NVM_WORD0F_PAUSE_MASK 0x3000 #define NVM_WORD0F_PAUSE 0x1000 #define NVM_WORD0F_ASM_DIR 0x2000 -#define NVM_WORD0F_ANE 0x0800 #define NVM_WORD0F_SWPDIO_EXT_MASK 0x00F0 -#define NVM_WORD0F_LPLU 0x0001 /* Mask bits for fields in Word 0x1a of the NVM */ #define NVM_WORD1A_ASPM_MASK 0x000C @@ -1435,7 +1078,7 @@ /* For checksumming, the sum of all words in the NVM should equal 0xBABA. */ #define NVM_SUM 0xBABA -#define NVM_MAC_ADDR_OFFSET 0 +/* PBA (printed board assembly) number words */ #define NVM_PBA_OFFSET_0 8 #define NVM_PBA_OFFSET_1 9 #define NVM_PBA_PTR_GUARD 0xFAFA @@ -1460,16 +1103,10 @@ #define NVM_WRITE_OPCODE_SPI 0x02 /* NVM write opcode */ #define NVM_A8_OPCODE_SPI 0x08 /* opcode bit-3 = address bit-8 */ #define NVM_WREN_OPCODE_SPI 0x06 /* NVM set Write Enable latch */ -#define NVM_WRDI_OPCODE_SPI 0x04 /* NVM reset Write Enable latch */ #define NVM_RDSR_OPCODE_SPI 0x05 /* NVM read Status register */ -#define NVM_WRSR_OPCODE_SPI 0x01 /* NVM write Status register */ /* SPI NVM Status Register */ #define NVM_STATUS_RDY_SPI 0x01 -#define NVM_STATUS_WEN_SPI 0x02 -#define NVM_STATUS_BP0_SPI 0x04 -#define NVM_STATUS_BP1_SPI 0x08 -#define NVM_STATUS_WPEN_SPI 0x80 /* Word definitions for ID LED Settings */ #define ID_LED_RESERVED_0000 0x0000 @@ -1523,8 +1160,7 @@ #define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */ #define MAX_PHY_MULTI_PAGE_REG 0xF -/* Bit definitions for valid PHY IDs. */ -/* +/* Bit definitions for valid PHY IDs. * I = Integrated * E = External */ @@ -1532,7 +1168,6 @@ #define M88E1000_I_PHY_ID 0x01410C30 #define M88E1011_I_PHY_ID 0x01410C20 #define IGP01E1000_I_PHY_ID 0x02A80380 -#define M88E1011_I_REV_4 0x04 #define M88E1111_I_PHY_ID 0x01410CC0 #define M88E1112_E_PHY_ID 0x01410C90 #define I347AT4_E_PHY_ID 0x01410DC0 @@ -1547,6 +1182,7 @@ #define I82577_E_PHY_ID 0x01540050 #define I82578_E_PHY_ID 0x004DD040 #define I82579_E_PHY_ID 0x01540090 +#define I217_E_PHY_ID 0x015400A0 #define I82580_I_PHY_ID 0x015403A0 #define I350_I_PHY_ID 0x015403B0 #define I210_I_PHY_ID 0x01410C00 @@ -1556,8 +1192,6 @@ /* M88E1000 Specific Registers */ #define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Reg */ #define M88E1000_PHY_SPEC_STATUS 0x11 /* PHY Specific Status Reg */ -#define M88E1000_INT_ENABLE 0x12 /* Interrupt Enable Reg */ -#define M88E1000_INT_STATUS 0x13 /* Interrupt Status Reg */ #define M88E1000_EXT_PHY_SPEC_CTRL 0x14 /* Extended PHY Specific Cntrl */ #define M88E1000_RX_ERR_CNTR 0x15 /* Receive Error Counter */ @@ -1568,11 +1202,7 @@ #define M88E1000_PHY_VCO_REG_BIT11 0x800 /* improved BER performance */ /* M88E1000 PHY Specific Control Register */ -#define M88E1000_PSCR_JABBER_DISABLE 0x0001 /* 1=Jabber Function disabled */ #define M88E1000_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reverse enabled */ -#define M88E1000_PSCR_SQE_TEST 0x0004 /* 1=SQE Test enabled */ -/* 1=CLK125 low, 0=CLK125 toggling */ -#define M88E1000_PSCR_CLK125_DISABLE 0x0010 /* MDI Crossover Mode bits 6:5 Manual MDI configuration */ #define M88E1000_PSCR_MDI_MANUAL_MODE 0x0000 #define M88E1000_PSCR_MDIX_MANUAL_MODE 0x0020 /* Manual MDIX configuration */ @@ -1580,24 +1210,13 @@ #define M88E1000_PSCR_AUTO_X_1000T 0x0040 /* Auto crossover enabled all speeds */ #define M88E1000_PSCR_AUTO_X_MODE 0x0060 -/* - * 1=Enable Extended 10BASE-T distance (Lower 10BASE-T Rx Threshold - * 0=Normal 10BASE-T Rx Threshold - */ -#define M88E1000_PSCR_EN_10BT_EXT_DIST 0x0080 -/* 1=5-bit interface in 100BASE-TX, 0=MII interface in 100BASE-TX */ -#define M88E1000_PSCR_MII_5BIT_ENABLE 0x0100 -#define M88E1000_PSCR_SCRAMBLER_DISABLE 0x0200 /* 1=Scrambler disable */ -#define M88E1000_PSCR_FORCE_LINK_GOOD 0x0400 /* 1=Force link good */ #define M88E1000_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Tx */ /* M88E1000 PHY Specific Status Register */ -#define M88E1000_PSSR_JABBER 0x0001 /* 1=Jabber */ #define M88E1000_PSSR_REV_POLARITY 0x0002 /* 1=Polarity reversed */ #define M88E1000_PSSR_DOWNSHIFT 0x0020 /* 1=Downshifted */ #define M88E1000_PSSR_MDIX 0x0040 /* 1=MDIX; 0=MDI */ -/* - * 0 = <50M +/* 0 = <50M * 1 = 50-80M * 2 = 80-110M * 3 = 110-140M @@ -1606,64 +1225,33 @@ #define M88E1000_PSSR_CABLE_LENGTH 0x0380 #define M88E1000_PSSR_LINK 0x0400 /* 1=Link up, 0=Link down */ #define M88E1000_PSSR_SPD_DPLX_RESOLVED 0x0800 /* 1=Speed & Duplex resolved */ -#define M88E1000_PSSR_PAGE_RCVD 0x1000 /* 1=Page received */ #define M88E1000_PSSR_DPLX 0x2000 /* 1=Duplex 0=Half Duplex */ #define M88E1000_PSSR_SPEED 0xC000 /* Speed, bits 14:15 */ -#define M88E1000_PSSR_10MBS 0x0000 /* 00=10Mbs */ #define M88E1000_PSSR_100MBS 0x4000 /* 01=100Mbs */ #define M88E1000_PSSR_1000MBS 0x8000 /* 10=1000Mbs */ #define M88E1000_PSSR_CABLE_LENGTH_SHIFT 7 -/* M88E1000 Extended PHY Specific Control Register */ -#define M88E1000_EPSCR_FIBER_LOOPBACK 0x4000 /* 1=Fiber loopback */ -/* - * 1 = Lost lock detect enabled. - * Will assert lost lock and bring - * link down if idle not seen - * within 1ms in 1000BASE-T - */ -#define M88E1000_EPSCR_DOWN_NO_IDLE 0x8000 -/* - * Number of times we will attempt to autonegotiate before downshifting if we +/* Number of times we will attempt to autonegotiate before downshifting if we * are the master */ #define M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK 0x0C00 #define M88E1000_EPSCR_MASTER_DOWNSHIFT_1X 0x0000 -#define M88E1000_EPSCR_MASTER_DOWNSHIFT_2X 0x0400 -#define M88E1000_EPSCR_MASTER_DOWNSHIFT_3X 0x0800 -#define M88E1000_EPSCR_MASTER_DOWNSHIFT_4X 0x0C00 -/* - * Number of times we will attempt to autonegotiate before downshifting if we +/* Number of times we will attempt to autonegotiate before downshifting if we * are the slave */ #define M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK 0x0300 -#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_DIS 0x0000 #define M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X 0x0100 -#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_2X 0x0200 -#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_3X 0x0300 -#define M88E1000_EPSCR_TX_CLK_2_5 0x0060 /* 2.5 MHz TX_CLK */ #define M88E1000_EPSCR_TX_CLK_25 0x0070 /* 25 MHz TX_CLK */ -#define M88E1000_EPSCR_TX_CLK_0 0x0000 /* NO TX_CLK */ - -/* M88E1111 Specific Registers */ -#define M88E1111_PHY_PAGE_SELECT1 0x16 /* for registers 0-28 */ -#define M88E1111_PHY_PAGE_SELECT2 0x1D /* for registers 30-31 */ - -/* M88E1111 page select register mask */ -#define M88E1111_PHY_PAGE_SELECT_MASK1 0xFF -#define M88E1111_PHY_PAGE_SELECT_MASK2 0x3F /* Intel I347AT4 Registers */ - #define I347AT4_PCDL 0x10 /* PHY Cable Diagnostics Length */ #define I347AT4_PCDC 0x15 /* PHY Cable Diagnostics Control */ #define I347AT4_PAGE_SELECT 0x16 /* I347AT4 Extended PHY Specific Control Register */ -/* - * Number of times we will attempt to autonegotiate before downshifting if we +/* Number of times we will attempt to autonegotiate before downshifting if we * are the master */ #define I347AT4_PSCR_DOWNSHIFT_ENABLE 0x0800 @@ -1685,14 +1273,7 @@ /* M88EC018 Rev 2 specific DownShift settings */ #define M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK 0x0E00 -#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_1X 0x0000 -#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_2X 0x0200 -#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_3X 0x0400 -#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_4X 0x0600 #define M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X 0x0800 -#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_6X 0x0A00 -#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_7X 0x0C00 -#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_8X 0x0E00 #define I82578_EPSCR_DOWNSHIFT_ENABLE 0x0020 #define I82578_EPSCR_DOWNSHIFT_COUNTER_MASK 0x001C @@ -1700,8 +1281,7 @@ /* BME1000 PHY Specific Control Register */ #define BME1000_PSCR_ENABLE_DOWNSHIFT 0x0800 /* 1 = enable downshift */ -/* - * Bits... +/* Bits... * 15-5: page * 4-0: register offset */ @@ -1712,49 +1292,24 @@ /* GG82563 Specific Registers */ #define GG82563_PHY_SPEC_CTRL GG82563_REG(0, 16) /* PHY Spec Cntrl */ -#define GG82563_PHY_SPEC_STATUS GG82563_REG(0, 17) /* PHY Spec Status */ -#define GG82563_PHY_INT_ENABLE GG82563_REG(0, 18) /* Interrupt Ena */ -#define GG82563_PHY_SPEC_STATUS_2 GG82563_REG(0, 19) /* PHY Spec Stat2 */ -#define GG82563_PHY_RX_ERR_CNTR GG82563_REG(0, 21) /* Rx Err Counter */ #define GG82563_PHY_PAGE_SELECT GG82563_REG(0, 22) /* Page Select */ #define GG82563_PHY_SPEC_CTRL_2 GG82563_REG(0, 26) /* PHY Spec Cntrl2 */ #define GG82563_PHY_PAGE_SELECT_ALT GG82563_REG(0, 29) /* Alt Page Select */ -/* Test Clock Control (use reg. 29 to select) */ -#define GG82563_PHY_TEST_CLK_CTRL GG82563_REG(0, 30) /* MAC Specific Control Register */ #define GG82563_PHY_MAC_SPEC_CTRL GG82563_REG(2, 21) -#define GG82563_PHY_MAC_SPEC_CTRL_2 GG82563_REG(2, 26) /* MAC Spec Ctrl 2 */ #define GG82563_PHY_DSP_DISTANCE GG82563_REG(5, 26) /* DSP Distance */ /* Page 193 - Port Control Registers */ /* Kumeran Mode Control */ #define GG82563_PHY_KMRN_MODE_CTRL GG82563_REG(193, 16) -#define GG82563_PHY_PORT_RESET GG82563_REG(193, 17) /* Port Reset */ -#define GG82563_PHY_REVISION_ID GG82563_REG(193, 18) /* Revision ID */ -#define GG82563_PHY_DEVICE_ID GG82563_REG(193, 19) /* Device ID */ #define GG82563_PHY_PWR_MGMT_CTRL GG82563_REG(193, 20) /* Pwr Mgt Ctrl */ -/* Rate Adaptation Control */ -#define GG82563_PHY_RATE_ADAPT_CTRL GG82563_REG(193, 25) /* Page 194 - KMRN Registers */ -/* FIFO's Control/Status */ -#define GG82563_PHY_KMRN_FIFO_CTRL_STAT GG82563_REG(194, 16) -#define GG82563_PHY_KMRN_CTRL GG82563_REG(194, 17) /* Control */ #define GG82563_PHY_INBAND_CTRL GG82563_REG(194, 18) /* Inband Ctrl */ -#define GG82563_PHY_KMRN_DIAGNOSTIC GG82563_REG(194, 19) /* Diagnostic */ -#define GG82563_PHY_ACK_TIMEOUTS GG82563_REG(194, 20) /* Ack Timeouts */ -#define GG82563_PHY_ADV_ABILITY GG82563_REG(194, 21) /* Adver Ability */ -/* Link Partner Advertised Ability */ -#define GG82563_PHY_LINK_PARTNER_ADV_ABILITY GG82563_REG(194, 23) -#define GG82563_PHY_ADV_NEXT_PAGE GG82563_REG(194, 24) /* Adver Next Pg */ -/* Link Partner Advertised Next page */ -#define GG82563_PHY_LINK_PARTNER_ADV_NEXT_PAGE GG82563_REG(194, 25) -#define GG82563_PHY_KMRN_MISC GG82563_REG(194, 26) /* Misc. */ /* MDI Control */ -#define E1000_MDIC_DATA_MASK 0x0000FFFF #define E1000_MDIC_REG_MASK 0x001F0000 #define E1000_MDIC_REG_SHIFT 16 #define E1000_MDIC_PHY_MASK 0x03E00000 @@ -1762,7 +1317,6 @@ #define E1000_MDIC_OP_WRITE 0x04000000 #define E1000_MDIC_OP_READ 0x08000000 #define E1000_MDIC_READY 0x10000000 -#define E1000_MDIC_INT_EN 0x20000000 #define E1000_MDIC_ERROR 0x40000000 #define E1000_MDIC_DEST 0x80000000 @@ -1834,38 +1388,13 @@ /* Lx power decision based on DMA coal */ #define E1000_PCIEMISC_LX_DECISION 0x00000080 +#define E1000_RXPBS_CFG_TS_EN 0x80000000 /* Timestamp in Rx buffer */ #define E1000_RXPBS_SIZE_I210_MASK 0x0000003F /* Rx packet buffer size */ #define E1000_TXPB0S_SIZE_I210_MASK 0x0000003F /* Tx packet buffer 0 size */ -#define E1000_LTRC_EEEMS_EN 0x00000020 /* Enable EEE LTR max send */ -/* Minimum time for 1000BASE-T where no data will be transmit following move out - * of EEE LPI Tx state - */ -#define E1000_TW_SYSTEM_1000_MASK 0x000000FF -/* Minimum time for 100BASE-T where no data will be transmit following move out - * of EEE LPI Tx state - */ -#define E1000_TW_SYSTEM_100_MASK 0x0000FF00 -#define E1000_TW_SYSTEM_100_SHIFT 8 -#define E1000_LTRMINV_LTRV_MASK 0x000003FF /* LTR minimum value */ -#define E1000_LTRMAXV_LTRV_MASK 0x000003FF /* LTR maximum value */ -#define E1000_LTRMINV_SCALE_MASK 0x00001C00 /* LTR minimum scale */ -#define E1000_LTRMINV_SCALE_SHIFT 10 -/* Reg val to set scale to 1024 nsec */ -#define E1000_LTRMINV_SCALE_1024 2 -/* Reg val to set scale to 32768 nsec */ -#define E1000_LTRMINV_SCALE_32768 3 -#define E1000_LTRMINV_LSNP_REQ 0x00008000 /* LTR Snoop Requirement */ -#define E1000_LTRMAXV_SCALE_MASK 0x00001C00 /* LTR maximum scale */ -#define E1000_LTRMAXV_SCALE_SHIFT 10 -/* Reg val to set scale to 1024 nsec */ -#define E1000_LTRMAXV_SCALE_1024 2 -/* Reg val to set scale to 32768 nsec */ -#define E1000_LTRMAXV_SCALE_32768 3 -#define E1000_LTRMAXV_LSNP_REQ 0x00008000 /* LTR Snoop Requirement */ #define E1000_DOBFFCTL_OBFFTHR_MASK 0x000000FF /* OBFF threshold */ #define E1000_DOBFFCTL_EXIT_ACT_MASK 0x01000000 /* Exit active CB */ -/* Proxy Filer Control */ +/* Proxy Filter Control */ #define E1000_PROXYFC_D0 0x00000001 /* Enable offload in D0 */ #define E1000_PROXYFC_EX 0x00000004 /* Directed exact proxy */ #define E1000_PROXYFC_MC 0x00000008 /* Directed MC Proxy */ @@ -1873,7 +1402,7 @@ #define E1000_PROXYFC_ARP_DIRECTED 0x00000020 /* Directed ARP Proxy Ena */ #define E1000_PROXYFC_IPV4 0x00000040 /* Directed IPv4 Enable */ #define E1000_PROXYFC_IPV6 0x00000080 /* Directed IPv6 Enable */ -#define E1000_PROXYFC_NS 0x00000200 /* IPv4 NBRHD Solicitation */ +#define E1000_PROXYFC_NS 0x00000200 /* IPv6 Neighbor Solicitation */ #define E1000_PROXYFC_ARP 0x00000800 /* ARP Request Proxy Ena */ /* Proxy Status */ #define E1000_PROXYS_CLEAR 0xFFFFFFFF /* Clear */ diff --git a/sys/dev/e1000/e1000_hw.h b/sys/dev/e1000/e1000_hw.h index 50a5ce2c28d..e8a8c174ca0 100644 --- a/sys/dev/e1000/e1000_hw.h +++ b/sys/dev/e1000/e1000_hw.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2012, Intel Corporation + Copyright (c) 2001-2013, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -123,13 +123,16 @@ struct e1000_hw; #define E1000_DEV_ID_ICH10_D_BM_LM 0x10DE #define E1000_DEV_ID_ICH10_D_BM_LF 0x10DF #define E1000_DEV_ID_ICH10_D_BM_V 0x1525 - #define E1000_DEV_ID_PCH_M_HV_LM 0x10EA #define E1000_DEV_ID_PCH_M_HV_LC 0x10EB #define E1000_DEV_ID_PCH_D_HV_DM 0x10EF #define E1000_DEV_ID_PCH_D_HV_DC 0x10F0 #define E1000_DEV_ID_PCH2_LV_LM 0x1502 #define E1000_DEV_ID_PCH2_LV_V 0x1503 +#define E1000_DEV_ID_PCH_LPT_I217_LM 0x153A +#define E1000_DEV_ID_PCH_LPT_I217_V 0x153B +#define E1000_DEV_ID_PCH_LPTLP_I218_LM 0x155A +#define E1000_DEV_ID_PCH_LPTLP_I218_V 0x1559 #define E1000_DEV_ID_82576 0x10C9 #define E1000_DEV_ID_82576_FIBER 0x10E6 #define E1000_DEV_ID_82576_SERDES 0x10E7 @@ -139,7 +142,9 @@ struct e1000_hw; #define E1000_DEV_ID_82576_NS_SERDES 0x1518 #define E1000_DEV_ID_82576_SERDES_QUAD 0x150D #define E1000_DEV_ID_82576_VF 0x10CA +#define E1000_DEV_ID_82576_VF_HV 0x152D #define E1000_DEV_ID_I350_VF 0x1520 +#define E1000_DEV_ID_I350_VF_HV 0x152F #define E1000_DEV_ID_82575EB_COPPER 0x10A7 #define E1000_DEV_ID_82575EB_FIBER_SERDES 0x10A9 #define E1000_DEV_ID_82575GB_QUAD_COPPER 0x10D6 @@ -165,6 +170,7 @@ struct e1000_hw; #define E1000_DEV_ID_DH89XXCC_SERDES 0x043A #define E1000_DEV_ID_DH89XXCC_BACKPLANE 0x043C #define E1000_DEV_ID_DH89XXCC_SFP 0x0440 + #define E1000_REVISION_0 0 #define E1000_REVISION_1 1 #define E1000_REVISION_2 2 @@ -206,6 +212,7 @@ enum e1000_mac_type { e1000_ich10lan, e1000_pchlan, e1000_pch2lan, + e1000_pch_lpt, e1000_82575, e1000_82576, e1000_82580, @@ -255,6 +262,7 @@ enum e1000_phy_type { e1000_phy_82578, e1000_phy_82577, e1000_phy_82579, + e1000_phy_i217, e1000_phy_82580, e1000_phy_vf, e1000_phy_i210, @@ -651,13 +659,13 @@ struct e1000_host_mng_command_info { #include "e1000_manage.h" #include "e1000_mbx.h" +/* Function pointers for the MAC. */ struct e1000_mac_operations { - /* Function pointers for the MAC. */ s32 (*init_params)(struct e1000_hw *); s32 (*id_led_init)(struct e1000_hw *); s32 (*blink_led)(struct e1000_hw *); + bool (*check_mng_mode)(struct e1000_hw *); s32 (*check_for_link)(struct e1000_hw *); - bool (*check_mng_mode)(struct e1000_hw *hw); s32 (*cleanup_led)(struct e1000_hw *); void (*clear_hw_cntrs)(struct e1000_hw *); void (*clear_vfta)(struct e1000_hw *); @@ -679,17 +687,12 @@ struct e1000_mac_operations { void (*rar_set)(struct e1000_hw *, u8*, u32); s32 (*read_mac_addr)(struct e1000_hw *); s32 (*validate_mdi_setting)(struct e1000_hw *); - s32 (*mng_host_if_write)(struct e1000_hw *, u8*, u16, u16, u8*); - s32 (*mng_write_cmd_header)(struct e1000_hw *hw, - struct e1000_host_mng_command_header*); - s32 (*mng_enable_host_if)(struct e1000_hw *); - s32 (*wait_autoneg)(struct e1000_hw *); + s32 (*set_obff_timer)(struct e1000_hw *, u32); s32 (*acquire_swfw_sync)(struct e1000_hw *, u16); void (*release_swfw_sync)(struct e1000_hw *, u16); }; -/* - * When to use various PHY register access functions: +/* When to use various PHY register access functions: * * Func Caller * Function Does Does When to use @@ -731,6 +734,7 @@ struct e1000_phy_operations { s32 (*write_i2c_byte)(struct e1000_hw *, u8, u8, u8); }; +/* Function pointers for the NVM. */ struct e1000_nvm_operations { s32 (*init_params)(struct e1000_hw *); s32 (*acquire)(struct e1000_hw *); @@ -785,6 +789,7 @@ struct e1000_mac_info { enum e1000_serdes_link_state serdes_link_state; bool serdes_has_link; bool tx_pkt_filtering; + u32 max_frame_size; }; struct e1000_phy_info { @@ -915,7 +920,7 @@ struct e1000_shadow_ram { bool modified; }; -#define E1000_SHADOW_RAM_WORDS 2048 +#define E1000_SHADOW_RAM_WORDS 2048 struct e1000_dev_spec_ich8lan { bool kmrn_lock_loss_workaround_enabled; @@ -924,6 +929,7 @@ struct e1000_dev_spec_ich8lan { E1000_MUTEX swflag_mutex; bool nvm_k1_enabled; bool eee_disable; + u16 eee_lp_ability; }; struct e1000_dev_spec_82575 { @@ -931,7 +937,9 @@ struct e1000_dev_spec_82575 { bool global_device_reset; bool eee_disable; bool module_plugged; + bool clear_semaphore_once; u32 mtu; + struct sfp_e1000_flags eth_flags; }; struct e1000_dev_spec_vf { diff --git a/sys/dev/e1000/e1000_i210.c b/sys/dev/e1000/e1000_i210.c index f8e8bad0d84..63302c0d376 100644 --- a/sys/dev/e1000/e1000_i210.c +++ b/sys/dev/e1000/e1000_i210.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2012, Intel Corporation + Copyright (c) 2001-2013, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -38,7 +38,6 @@ static s32 e1000_acquire_nvm_i210(struct e1000_hw *hw); static void e1000_release_nvm_i210(struct e1000_hw *hw); static s32 e1000_get_hw_semaphore_i210(struct e1000_hw *hw); -static void e1000_put_hw_semaphore_i210(struct e1000_hw *hw); static s32 e1000_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); static s32 e1000_pool_flash_update_done_i210(struct e1000_hw *hw); @@ -105,13 +104,14 @@ s32 e1000_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask) } swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC); - if (!(swfw_sync & fwmask)) + if (!(swfw_sync & (fwmask | swmask))) break; /* * Firmware currently using resource (fwmask) + * or other software thread using resource (swmask) */ - e1000_put_hw_semaphore_i210(hw); + e1000_put_hw_semaphore_generic(hw); msec_delay_irq(5); i++; } @@ -125,7 +125,7 @@ s32 e1000_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask) swfw_sync |= swmask; E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync); - e1000_put_hw_semaphore_i210(hw); + e1000_put_hw_semaphore_generic(hw); out: return ret_val; @@ -152,7 +152,7 @@ void e1000_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask) swfw_sync &= ~mask; E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync); - e1000_put_hw_semaphore_i210(hw); + e1000_put_hw_semaphore_generic(hw); } /** @@ -164,12 +164,45 @@ void e1000_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask) static s32 e1000_get_hw_semaphore_i210(struct e1000_hw *hw) { u32 swsm; - s32 ret_val = E1000_SUCCESS; s32 timeout = hw->nvm.word_size + 1; s32 i = 0; DEBUGFUNC("e1000_get_hw_semaphore_i210"); + /* Get the SW semaphore */ + while (i < timeout) { + swsm = E1000_READ_REG(hw, E1000_SWSM); + if (!(swsm & E1000_SWSM_SMBI)) + break; + + usec_delay(50); + i++; + } + + if (i == timeout) { + /* + * In rare circumstances, the driver may not have released the + * SW semaphore. Clear the semaphore once before giving up. + */ + if (hw->dev_spec._82575.clear_semaphore_once) { + hw->dev_spec._82575.clear_semaphore_once = FALSE; + e1000_put_hw_semaphore_generic(hw); + for (i = 0; i < timeout; i++) { + swsm = E1000_READ_REG(hw, E1000_SWSM); + if (!(swsm & E1000_SWSM_SMBI)) + break; + + usec_delay(50); + } + } + + /* If we do not have the semaphore here, we have to give up. */ + if (i == timeout) { + DEBUGOUT("Driver can't access device - SMBI bit is set.\n"); + return -E1000_ERR_NVM; + } + } + /* Get the FW semaphore. */ for (i = 0; i < timeout; i++) { swsm = E1000_READ_REG(hw, E1000_SWSM); @@ -186,31 +219,10 @@ static s32 e1000_get_hw_semaphore_i210(struct e1000_hw *hw) /* Release semaphores */ e1000_put_hw_semaphore_generic(hw); DEBUGOUT("Driver can't access the NVM\n"); - ret_val = -E1000_ERR_NVM; - goto out; + return -E1000_ERR_NVM; } -out: - return ret_val; -} - -/** - * e1000_put_hw_semaphore_i210 - Release hardware semaphore - * @hw: pointer to the HW structure - * - * Release hardware semaphore used to access the PHY or NVM - **/ -static void e1000_put_hw_semaphore_i210(struct e1000_hw *hw) -{ - u32 swsm; - - DEBUGFUNC("e1000_put_hw_semaphore_i210"); - - swsm = E1000_READ_REG(hw, E1000_SWSM); - - swsm &= ~E1000_SWSM_SWESMBI; - - E1000_WRITE_REG(hw, E1000_SWSM, swsm); + return E1000_SUCCESS; } /** @@ -364,8 +376,8 @@ out: * * Wrapper function to return data formerly found in the NVM. **/ -static s32 e1000_read_nvm_i211(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data) +static s32 e1000_read_nvm_i211(struct e1000_hw *hw, u16 offset, + u16 words, u16 *data) { s32 ret_val = E1000_SUCCESS; @@ -380,15 +392,40 @@ static s32 e1000_read_nvm_i211(struct e1000_hw *hw, u16 offset, u16 words, if (ret_val != E1000_SUCCESS) DEBUGOUT("MAC Addr not found in iNVM\n"); break; - case NVM_ID_LED_SETTINGS: case NVM_INIT_CTRL_2: - case NVM_INIT_CTRL_4: - case NVM_LED_1_CFG: - case NVM_LED_0_2_CFG: - e1000_read_invm_i211(hw, (u8)offset, data); + ret_val = e1000_read_invm_i211(hw, (u8)offset, data); + if (ret_val != E1000_SUCCESS) { + *data = NVM_INIT_CTRL_2_DEFAULT_I211; + ret_val = E1000_SUCCESS; + } break; - case NVM_COMPAT: - *data = ID_LED_DEFAULT_I210; + case NVM_INIT_CTRL_4: + ret_val = e1000_read_invm_i211(hw, (u8)offset, data); + if (ret_val != E1000_SUCCESS) { + *data = NVM_INIT_CTRL_4_DEFAULT_I211; + ret_val = E1000_SUCCESS; + } + break; + case NVM_LED_1_CFG: + ret_val = e1000_read_invm_i211(hw, (u8)offset, data); + if (ret_val != E1000_SUCCESS) { + *data = NVM_LED_1_CFG_DEFAULT_I211; + ret_val = E1000_SUCCESS; + } + break; + case NVM_LED_0_2_CFG: + ret_val = e1000_read_invm_i211(hw, (u8)offset, data); + if (ret_val != E1000_SUCCESS) { + *data = NVM_LED_0_2_CFG_DEFAULT_I211; + ret_val = E1000_SUCCESS; + } + break; + case NVM_ID_LED_SETTINGS: + ret_val = e1000_read_invm_i211(hw, (u8)offset, data); + if (ret_val != E1000_SUCCESS) { + *data = ID_LED_RESERVED_FFFF; + ret_val = E1000_SUCCESS; + } break; case NVM_SUB_DEV_ID: *data = hw->subsystem_device_id; @@ -554,26 +591,6 @@ out: return ret_val; } -/** - * e1000_get_flash_presence_i210 - Check if flash device is detected. - * @hw: pointer to the HW structure - * - **/ -static bool e1000_get_flash_presence_i210(struct e1000_hw *hw) -{ - u32 eec = 0; - bool ret_val = FALSE; - - DEBUGFUNC("e1000_get_flash_presence_i210"); - - eec = E1000_READ_REG(hw, E1000_EECD); - - if (eec & E1000_EECD_FLASH_DETECTED_I210) - ret_val = TRUE; - - return ret_val; -} - /** * e1000_update_flash_i210 - Commit EEPROM to the flash * @hw: pointer to the HW structure @@ -690,10 +707,7 @@ void e1000_init_function_pointers_i210(struct e1000_hw *hw) switch (hw->mac.type) { case e1000_i210: - if (e1000_get_flash_presence_i210(hw)) - hw->nvm.ops.init_params = e1000_init_nvm_params_i210; - else - hw->nvm.ops.init_params = e1000_init_nvm_params_i211; + hw->nvm.ops.init_params = e1000_init_nvm_params_i210; break; case e1000_i211: hw->nvm.ops.init_params = e1000_init_nvm_params_i211; diff --git a/sys/dev/e1000/e1000_i210.h b/sys/dev/e1000/e1000_i210.h index a0cd93576d5..d7711fe093f 100644 --- a/sys/dev/e1000/e1000_i210.h +++ b/sys/dev/e1000/e1000_i210.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2012, Intel Corporation + Copyright (c) 2001-2013, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -43,8 +43,6 @@ s32 e1000_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, s32 e1000_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); s32 e1000_read_invm_i211(struct e1000_hw *hw, u8 address, u16 *data); -s32 e1000_check_for_copper_link_i210(struct e1000_hw *hw); -s32 e1000_set_ltr_i210(struct e1000_hw *hw, bool link); s32 e1000_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask); void e1000_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask); @@ -69,6 +67,15 @@ enum E1000_INVM_STRUCTURE_TYPE { #define E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS 8 #define E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS 1 +#define E1000_INVM_ULT_BYTES_SIZE 8 +#define E1000_INVM_RECORD_SIZE_IN_BYTES 4 +#define E1000_INVM_VER_FIELD_ONE 0x1FF8 +#define E1000_INVM_VER_FIELD_TWO 0x7FE000 +#define E1000_INVM_IMGTYPE_FIELD 0x1F800000 + +#define E1000_INVM_MAJOR_MASK 0x3F0 +#define E1000_INVM_MINOR_MASK 0xF +#define E1000_INVM_MAJOR_SHIFT 4 #define ID_LED_DEFAULT_I210 ((ID_LED_OFF1_ON2 << 8) | \ (ID_LED_DEF1_DEF2 << 4) | \ @@ -77,4 +84,9 @@ enum E1000_INVM_STRUCTURE_TYPE { (ID_LED_DEF1_DEF2 << 4) | \ (ID_LED_DEF1_DEF2)) +/* NVM offset defaults for I211 devices */ +#define NVM_INIT_CTRL_2_DEFAULT_I211 0X7243 +#define NVM_INIT_CTRL_4_DEFAULT_I211 0x00C1 +#define NVM_LED_1_CFG_DEFAULT_I211 0x0184 +#define NVM_LED_0_2_CFG_DEFAULT_I211 0x200C #endif diff --git a/sys/dev/e1000/e1000_ich8lan.c b/sys/dev/e1000/e1000_ich8lan.c index 906ce85680a..bd943555275 100644 --- a/sys/dev/e1000/e1000_ich8lan.c +++ b/sys/dev/e1000/e1000_ich8lan.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2011, Intel Corporation + Copyright (c) 2001-2013, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -32,8 +32,7 @@ ******************************************************************************/ /*$FreeBSD$*/ -/* - * 82562G 10/100 Network Connection +/* 82562G 10/100 Network Connection * 82562G-2 10/100 Network Connection * 82562GT 10/100 Network Connection * 82562GT-2 10/100 Network Connection @@ -64,10 +63,6 @@ #include "e1000_api.h" -static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw); -static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw); -static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw); -static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw); static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw); static void e1000_release_swflag_ich8lan(struct e1000_hw *hw); static s32 e1000_acquire_nvm_ich8lan(struct e1000_hw *hw); @@ -75,6 +70,7 @@ static void e1000_release_nvm_ich8lan(struct e1000_hw *hw); static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw); static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw); static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index); +static void e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index); static void e1000_update_mc_addr_list_pch2lan(struct e1000_hw *hw, u8 *mc_addr_list, u32 mc_addr_count); @@ -99,6 +95,7 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw); static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw); static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw); static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw); +static s32 e1000_setup_copper_link_pch_lpt(struct e1000_hw *hw); static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed, u16 *duplex); static s32 e1000_cleanup_led_ich8lan(struct e1000_hw *hw); @@ -111,8 +108,6 @@ static s32 e1000_led_on_pchlan(struct e1000_hw *hw); static s32 e1000_led_off_pchlan(struct e1000_hw *hw); static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw); static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank); -static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout); -static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw); static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw); static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw); static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, @@ -123,21 +118,13 @@ static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, u32 offset, u16 *data); static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, u8 byte); -static s32 e1000_write_flash_byte_ich8lan(struct e1000_hw *hw, - u32 offset, u8 data); -static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, - u8 size, u16 data); static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw); static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw); static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw); -static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw); -static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw); static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw); static s32 e1000_k1_workaround_lv(struct e1000_hw *hw); static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate); -#if defined(NAHUM6_HW) && (defined(LTR_SUPPORT) || defined(OBFF_SUPPORT)) - -#endif /* NAHUM6_HW && (LTR_SUPPORT || OBFF_SUPPORT) */ +static s32 e1000_set_obff_timer_pch_lpt(struct e1000_hw *hw, u32 itr); /* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */ /* Offset 04h HSFSTS */ @@ -180,20 +167,190 @@ union ich8_hws_flash_regacc { u16 regval; }; -static void e1000_toggle_lanphypc_value_ich8lan(struct e1000_hw *hw) +/** + * e1000_phy_is_accessible_pchlan - Check if able to access PHY registers + * @hw: pointer to the HW structure + * + * Test access to the PHY registers by reading the PHY ID registers. If + * the PHY ID is already known (e.g. resume path) compare it with known ID, + * otherwise assume the read PHY ID is correct if it is valid. + * + * Assumes the sw/fw/hw semaphore is already acquired. + **/ +static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw) { - u32 ctrl; + u16 phy_reg = 0; + u32 phy_id = 0; + s32 ret_val; + u16 retry_count; - DEBUGFUNC("e1000_toggle_lanphypc_value_ich8lan"); + for (retry_count = 0; retry_count < 2; retry_count++) { + ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID1, &phy_reg); + if (ret_val || (phy_reg == 0xFFFF)) + continue; + phy_id = (u32)(phy_reg << 16); - ctrl = E1000_READ_REG(hw, E1000_CTRL); - ctrl |= E1000_CTRL_LANPHYPC_OVERRIDE; - ctrl &= ~E1000_CTRL_LANPHYPC_VALUE; - E1000_WRITE_REG(hw, E1000_CTRL, ctrl); - E1000_WRITE_FLUSH(hw); - usec_delay(10); - ctrl &= ~E1000_CTRL_LANPHYPC_OVERRIDE; - E1000_WRITE_REG(hw, E1000_CTRL, ctrl); + ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID2, &phy_reg); + if (ret_val || (phy_reg == 0xFFFF)) { + phy_id = 0; + continue; + } + phy_id |= (u32)(phy_reg & PHY_REVISION_MASK); + break; + } + + if (hw->phy.id) { + if (hw->phy.id == phy_id) + return TRUE; + } else if (phy_id) { + hw->phy.id = phy_id; + hw->phy.revision = (u32)(phy_reg & ~PHY_REVISION_MASK); + return TRUE; + } + + /* In case the PHY needs to be in mdio slow mode, + * set slow mode and try to get the PHY id again. + */ + hw->phy.ops.release(hw); + ret_val = e1000_set_mdio_slow_mode_hv(hw); + if (!ret_val) + ret_val = e1000_get_phy_id(hw); + hw->phy.ops.acquire(hw); + + return !ret_val; +} + +/** + * e1000_init_phy_workarounds_pchlan - PHY initialization workarounds + * @hw: pointer to the HW structure + * + * Workarounds/flow necessary for PHY initialization during driver load + * and resume paths. + **/ +static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw) +{ + u32 mac_reg, fwsm = E1000_READ_REG(hw, E1000_FWSM); + s32 ret_val; + u16 phy_reg; + + DEBUGFUNC("e1000_init_phy_workarounds_pchlan"); + + /* Gate automatic PHY configuration by hardware on managed and + * non-managed 82579 and newer adapters. + */ + e1000_gate_hw_phy_config_ich8lan(hw, TRUE); + + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) { + DEBUGOUT("Failed to initialize PHY flow\n"); + goto out; + } + + /* The MAC-PHY interconnect may be in SMBus mode. If the PHY is + * inaccessible and resetting the PHY is not blocked, toggle the + * LANPHYPC Value bit to force the interconnect to PCIe mode. + */ + switch (hw->mac.type) { + case e1000_pch_lpt: + if (e1000_phy_is_accessible_pchlan(hw)) + break; + + /* Before toggling LANPHYPC, see if PHY is accessible by + * forcing MAC to SMBus mode first. + */ + mac_reg = E1000_READ_REG(hw, E1000_CTRL_EXT); + mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS; + E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg); + + /* fall-through */ + case e1000_pch2lan: + if (e1000_phy_is_accessible_pchlan(hw)) { + if (hw->mac.type == e1000_pch_lpt) { + /* Unforce SMBus mode in PHY */ + hw->phy.ops.read_reg_locked(hw, CV_SMB_CTRL, + &phy_reg); + phy_reg &= ~CV_SMB_CTRL_FORCE_SMBUS; + hw->phy.ops.write_reg_locked(hw, CV_SMB_CTRL, + phy_reg); + + /* Unforce SMBus mode in MAC */ + mac_reg = E1000_READ_REG(hw, E1000_CTRL_EXT); + mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS; + E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg); + } + break; + } + + /* fall-through */ + case e1000_pchlan: + if ((hw->mac.type == e1000_pchlan) && + (fwsm & E1000_ICH_FWSM_FW_VALID)) + break; + + if (hw->phy.ops.check_reset_block(hw)) { + DEBUGOUT("Required LANPHYPC toggle blocked by ME\n"); + break; + } + + DEBUGOUT("Toggling LANPHYPC\n"); + + /* Set Phy Config Counter to 50msec */ + mac_reg = E1000_READ_REG(hw, E1000_FEXTNVM3); + mac_reg &= ~E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK; + mac_reg |= E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC; + E1000_WRITE_REG(hw, E1000_FEXTNVM3, mac_reg); + + if (hw->mac.type == e1000_pch_lpt) { + /* Toggling LANPHYPC brings the PHY out of SMBus mode + * So ensure that the MAC is also out of SMBus mode + */ + mac_reg = E1000_READ_REG(hw, E1000_CTRL_EXT); + mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS; + E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg); + } + + /* Toggle LANPHYPC Value bit */ + mac_reg = E1000_READ_REG(hw, E1000_CTRL); + mac_reg |= E1000_CTRL_LANPHYPC_OVERRIDE; + mac_reg &= ~E1000_CTRL_LANPHYPC_VALUE; + E1000_WRITE_REG(hw, E1000_CTRL, mac_reg); + E1000_WRITE_FLUSH(hw); + usec_delay(10); + mac_reg &= ~E1000_CTRL_LANPHYPC_OVERRIDE; + E1000_WRITE_REG(hw, E1000_CTRL, mac_reg); + E1000_WRITE_FLUSH(hw); + if (hw->mac.type < e1000_pch_lpt) { + msec_delay(50); + } else { + u16 count = 20; + do { + msec_delay(5); + } while (!(E1000_READ_REG(hw, E1000_CTRL_EXT) & + E1000_CTRL_EXT_LPCD) && count--); + } + break; + default: + break; + } + + hw->phy.ops.release(hw); + + /* Reset the PHY before any access to it. Doing so, ensures + * that the PHY is in a known good state before we read/write + * PHY registers. The generic reset is sufficient here, + * because we haven't determined the PHY type yet. + */ + ret_val = e1000_phy_hw_reset_generic(hw); + +out: + /* Ungate automatic PHY configuration on non-managed 82579 */ + if ((hw->mac.type == e1000_pch2lan) && + !(fwsm & E1000_ICH_FWSM_FW_VALID)) { + msec_delay(10); + e1000_gate_hw_phy_config_ich8lan(hw, FALSE); + } + + return ret_val; } /** @@ -205,7 +362,7 @@ static void e1000_toggle_lanphypc_value_ich8lan(struct e1000_hw *hw) static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; + s32 ret_val; DEBUGFUNC("e1000_init_phy_params_pchlan"); @@ -230,70 +387,40 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) phy->ops.power_down = e1000_power_down_phy_copper_ich8lan; phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; - if (!hw->phy.ops.check_reset_block(hw)) { - u32 fwsm = E1000_READ_REG(hw, E1000_FWSM); - - /* - * The MAC-PHY interconnect may still be in SMBus mode after - * Sx->S0. If resetting the PHY is not blocked, toggle the - * LANPHYPC Value bit to force the interconnect to PCIe mode. - */ - e1000_toggle_lanphypc_value_ich8lan(hw); - msec_delay(50); - - /* - * Gate automatic PHY configuration by hardware on - * non-managed 82579 - */ - if ((hw->mac.type == e1000_pch2lan) && - !(fwsm & E1000_ICH_FWSM_FW_VALID)) - e1000_gate_hw_phy_config_ich8lan(hw, TRUE); - - /* - * Reset the PHY before any access to it. Doing so, ensures - * that the PHY is in a known good state before we read/write - * PHY registers. The generic reset is sufficient here, - * because we haven't determined the PHY type yet. - */ - ret_val = e1000_phy_hw_reset_generic(hw); - if (ret_val) - goto out; - - /* Ungate automatic PHY configuration on non-managed 82579 */ - if ((hw->mac.type == e1000_pch2lan) && - !(fwsm & E1000_ICH_FWSM_FW_VALID)) { - msec_delay(10); - e1000_gate_hw_phy_config_ich8lan(hw, FALSE); - } - } - phy->id = e1000_phy_unknown; - switch (hw->mac.type) { - default: - ret_val = e1000_get_phy_id(hw); - if (ret_val) - goto out; - if ((phy->id != 0) && (phy->id != PHY_REVISION_MASK)) + + ret_val = e1000_init_phy_workarounds_pchlan(hw); + if (ret_val) + return ret_val; + + if (phy->id == e1000_phy_unknown) + switch (hw->mac.type) { + default: + ret_val = e1000_get_phy_id(hw); + if (ret_val) + return ret_val; + if ((phy->id != 0) && (phy->id != PHY_REVISION_MASK)) + break; + /* fall-through */ + case e1000_pch2lan: + case e1000_pch_lpt: + /* In case the PHY needs to be in mdio slow mode, + * set slow mode and try to get the PHY id again. + */ + ret_val = e1000_set_mdio_slow_mode_hv(hw); + if (ret_val) + return ret_val; + ret_val = e1000_get_phy_id(hw); + if (ret_val) + return ret_val; break; - /* fall-through */ - case e1000_pch2lan: - /* - * In case the PHY needs to be in mdio slow mode, - * set slow mode and try to get the PHY id again. - */ - ret_val = e1000_set_mdio_slow_mode_hv(hw); - if (ret_val) - goto out; - ret_val = e1000_get_phy_id(hw); - if (ret_val) - goto out; - break; - } + } phy->type = e1000_get_phy_type_from_id(phy->id); switch (phy->type) { case e1000_phy_82577: case e1000_phy_82579: + case e1000_phy_i217: phy->ops.check_polarity = e1000_check_polarity_82577; phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_82577; @@ -312,7 +439,6 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) break; } -out: return ret_val; } @@ -325,7 +451,7 @@ out: static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = E1000_SUCCESS; + s32 ret_val; u16 i = 0; DEBUGFUNC("e1000_init_phy_params_ich8lan"); @@ -346,8 +472,7 @@ static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw) phy->ops.power_up = e1000_power_up_phy_copper; phy->ops.power_down = e1000_power_down_phy_copper_ich8lan; - /* - * We may need to do this twice - once for IGP and if that fails, + /* We may need to do this twice - once for IGP and if that fails, * we'll set BM func pointers and try again */ ret_val = e1000_determine_phy_address(hw); @@ -357,7 +482,7 @@ static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw) ret_val = e1000_determine_phy_address(hw); if (ret_val) { DEBUGOUT("Cannot determine PHY addr. Erroring out\n"); - goto out; + return ret_val; } } @@ -367,7 +492,7 @@ static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw) msec_delay(1); ret_val = e1000_get_phy_id(hw); if (ret_val) - goto out; + return ret_val; } /* Verify phy id */ @@ -401,12 +526,11 @@ static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw) phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88; break; default: - ret_val = -E1000_ERR_PHY; - goto out; + return -E1000_ERR_PHY; + break; } -out: - return ret_val; + return E1000_SUCCESS; } /** @@ -421,7 +545,6 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) struct e1000_nvm_info *nvm = &hw->nvm; struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; u32 gfpreg, sector_base_addr, sector_end_addr; - s32 ret_val = E1000_SUCCESS; u16 i; DEBUGFUNC("e1000_init_nvm_params_ich8lan"); @@ -429,16 +552,14 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) /* Can't read flash registers if the register set isn't mapped. */ if (!hw->flash_address) { DEBUGOUT("ERROR: Flash registers not mapped\n"); - ret_val = -E1000_ERR_CONFIG; - goto out; + return -E1000_ERR_CONFIG; } nvm->type = e1000_nvm_flash_sw; gfpreg = E1000_READ_FLASH_REG(hw, ICH_FLASH_GFPREG); - /* - * sector_X_addr is a "sector"-aligned address (4096 bytes) + /* sector_X_addr is a "sector"-aligned address (4096 bytes) * Add 1 to sector_end_addr since this sector is included in * the overall size. */ @@ -448,8 +569,7 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) /* flash_base_addr is byte-aligned */ nvm->flash_base_addr = sector_base_addr << FLASH_SECTOR_ADDR_SHIFT; - /* - * find total size of the NVM, then cut in half since the total + /* find total size of the NVM, then cut in half since the total * size represents two separate NVM banks. */ nvm->flash_bank_size = (sector_end_addr - sector_base_addr) @@ -478,8 +598,7 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) nvm->ops.validate = e1000_validate_nvm_checksum_ich8lan; nvm->ops.write = e1000_write_nvm_ich8lan; -out: - return ret_val; + return E1000_SUCCESS; } /** @@ -536,7 +655,7 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw) /* clear hardware counters */ mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_ich8lan; - /* LED operations */ + /* LED and other operations */ switch (mac->type) { case e1000_ich8lan: case e1000_ich9lan: @@ -558,10 +677,11 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw) case e1000_pch2lan: mac->rar_entry_count = E1000_PCH2_RAR_ENTRIES; mac->ops.rar_set = e1000_rar_set_pch2lan; + /* fall-through */ + case e1000_pch_lpt: /* multicast address update for pch2 */ mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_pch2lan; - /* fall-through */ case e1000_pchlan: /* check management mode */ mac->ops.check_mng_mode = e1000_check_mng_mode_pchlan; @@ -579,55 +699,385 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw) break; } -#if defined(NAHUM6_HW) && (defined(LTR_SUPPORT) || defined(OBFF_SUPPORT)) if (mac->type == e1000_pch_lpt) { + mac->rar_entry_count = E1000_PCH_LPT_RAR_ENTRIES; + mac->ops.rar_set = e1000_rar_set_pch_lpt; + mac->ops.setup_physical_interface = e1000_setup_copper_link_pch_lpt; + mac->ops.set_obff_timer = e1000_set_obff_timer_pch_lpt; } -#endif /* NAHUM6_HW && (LTR_SUPPORT || OBFF_SUPPORT) */ /* Enable PCS Lock-loss workaround for ICH8 */ if (mac->type == e1000_ich8lan) e1000_set_kmrn_lock_loss_workaround_ich8lan(hw, TRUE); - /* Gate automatic PHY configuration by hardware on managed 82579 */ - if ((mac->type == e1000_pch2lan) && - (E1000_READ_REG(hw, E1000_FWSM) & E1000_ICH_FWSM_FW_VALID)) - e1000_gate_hw_phy_config_ich8lan(hw, TRUE); - return E1000_SUCCESS; } +/** + * __e1000_access_emi_reg_locked - Read/write EMI register + * @hw: pointer to the HW structure + * @addr: EMI address to program + * @data: pointer to value to read/write from/to the EMI address + * @read: boolean flag to indicate read or write + * + * This helper function assumes the SW/FW/HW Semaphore is already acquired. + **/ +static s32 __e1000_access_emi_reg_locked(struct e1000_hw *hw, u16 address, + u16 *data, bool read) +{ + s32 ret_val; + + DEBUGFUNC("__e1000_access_emi_reg_locked"); + + ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_ADDR, address); + if (ret_val) + return ret_val; + + if (read) + ret_val = hw->phy.ops.read_reg_locked(hw, I82579_EMI_DATA, + data); + else + ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_DATA, + *data); + + return ret_val; +} + +/** + * e1000_read_emi_reg_locked - Read Extended Management Interface register + * @hw: pointer to the HW structure + * @addr: EMI address to program + * @data: value to be read from the EMI address + * + * Assumes the SW/FW/HW Semaphore is already acquired. + **/ +s32 e1000_read_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 *data) +{ + DEBUGFUNC("e1000_read_emi_reg_locked"); + + return __e1000_access_emi_reg_locked(hw, addr, data, TRUE); +} + +/** + * e1000_write_emi_reg_locked - Write Extended Management Interface register + * @hw: pointer to the HW structure + * @addr: EMI address to program + * @data: value to be written to the EMI address + * + * Assumes the SW/FW/HW Semaphore is already acquired. + **/ +static s32 e1000_write_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 data) +{ + DEBUGFUNC("e1000_read_emi_reg_locked"); + + return __e1000_access_emi_reg_locked(hw, addr, &data, FALSE); +} + /** * e1000_set_eee_pchlan - Enable/disable EEE support * @hw: pointer to the HW structure * - * Enable/disable EEE based on setting in dev_spec structure. The bits in - * the LPI Control register will remain set only if/when link is up. + * Enable/disable EEE based on setting in dev_spec structure, the duplex of + * the link and the EEE capabilities of the link partner. The LPI Control + * register bits will remain set only if/when link is up. **/ static s32 e1000_set_eee_pchlan(struct e1000_hw *hw) { struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; - s32 ret_val = E1000_SUCCESS; - u16 phy_reg; + s32 ret_val; + u16 lpi_ctrl; DEBUGFUNC("e1000_set_eee_pchlan"); - if (hw->phy.type != e1000_phy_82579) - goto out; + if ((hw->phy.type != e1000_phy_82579) && + (hw->phy.type != e1000_phy_i217)) + return E1000_SUCCESS; - ret_val = hw->phy.ops.read_reg(hw, I82579_LPI_CTRL, &phy_reg); + ret_val = hw->phy.ops.acquire(hw); if (ret_val) - goto out; + return ret_val; - if (dev_spec->eee_disable) - phy_reg &= ~I82579_LPI_CTRL_ENABLE_MASK; - else - phy_reg |= I82579_LPI_CTRL_ENABLE_MASK; + ret_val = hw->phy.ops.read_reg_locked(hw, I82579_LPI_CTRL, &lpi_ctrl); + if (ret_val) + goto release; + + /* Clear bits that enable EEE in various speeds */ + lpi_ctrl &= ~I82579_LPI_CTRL_ENABLE_MASK; + + /* Enable EEE if not disabled by user */ + if (!dev_spec->eee_disable) { + u16 lpa, pcs_status, data; + + /* Save off link partner's EEE ability */ + switch (hw->phy.type) { + case e1000_phy_82579: + lpa = I82579_EEE_LP_ABILITY; + pcs_status = I82579_EEE_PCS_STATUS; + break; + case e1000_phy_i217: + lpa = I217_EEE_LP_ABILITY; + pcs_status = I217_EEE_PCS_STATUS; + break; + default: + ret_val = -E1000_ERR_PHY; + goto release; + } + ret_val = e1000_read_emi_reg_locked(hw, lpa, + &dev_spec->eee_lp_ability); + if (ret_val) + goto release; + + /* Enable EEE only for speeds in which the link partner is + * EEE capable. + */ + if (dev_spec->eee_lp_ability & I82579_EEE_1000_SUPPORTED) + lpi_ctrl |= I82579_LPI_CTRL_1000_ENABLE; + + if (dev_spec->eee_lp_ability & I82579_EEE_100_SUPPORTED) { + hw->phy.ops.read_reg_locked(hw, PHY_LP_ABILITY, &data); + if (data & NWAY_LPAR_100TX_FD_CAPS) + lpi_ctrl |= I82579_LPI_CTRL_100_ENABLE; + else + /* EEE is not supported in 100Half, so ignore + * partner's EEE in 100 ability if full-duplex + * is not advertised. + */ + dev_spec->eee_lp_ability &= + ~I82579_EEE_100_SUPPORTED; + } + + /* R/Clr IEEE MMD 3.1 bits 11:10 - Tx/Rx LPI Received */ + ret_val = e1000_read_emi_reg_locked(hw, pcs_status, &data); + if (ret_val) + goto release; + } + + ret_val = hw->phy.ops.write_reg_locked(hw, I82579_LPI_CTRL, lpi_ctrl); +release: + hw->phy.ops.release(hw); - ret_val = hw->phy.ops.write_reg(hw, I82579_LPI_CTRL, phy_reg); -out: return ret_val; } +/** + * e1000_k1_workaround_lpt_lp - K1 workaround on Lynxpoint-LP + * @hw: pointer to the HW structure + * @link: link up bool flag + * + * When K1 is enabled for 1Gbps, the MAC can miss 2 DMA completion indications + * preventing further DMA write requests. Workaround the issue by disabling + * the de-assertion of the clock request when in 1Gpbs mode. + **/ +static s32 e1000_k1_workaround_lpt_lp(struct e1000_hw *hw, bool link) +{ + u32 fextnvm6 = E1000_READ_REG(hw, E1000_FEXTNVM6); + s32 ret_val = E1000_SUCCESS; + + if (link && (E1000_READ_REG(hw, E1000_STATUS) & + E1000_STATUS_SPEED_1000)) { + u16 kmrn_reg; + + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + return ret_val; + + ret_val = + e1000_read_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_K1_CONFIG, + &kmrn_reg); + if (ret_val) + goto release; + + ret_val = + e1000_write_kmrn_reg_locked(hw, + E1000_KMRNCTRLSTA_K1_CONFIG, + kmrn_reg & + ~E1000_KMRNCTRLSTA_K1_ENABLE); + if (ret_val) + goto release; + + usec_delay(10); + + E1000_WRITE_REG(hw, E1000_FEXTNVM6, + fextnvm6 | E1000_FEXTNVM6_REQ_PLL_CLK); + + ret_val = + e1000_write_kmrn_reg_locked(hw, + E1000_KMRNCTRLSTA_K1_CONFIG, + kmrn_reg); +release: + hw->phy.ops.release(hw); + } else { + /* clear FEXTNVM6 bit 8 on link down or 10/100 */ + E1000_WRITE_REG(hw, E1000_FEXTNVM6, + fextnvm6 & ~E1000_FEXTNVM6_REQ_PLL_CLK); + } + + return ret_val; +} + +static u64 e1000_ltr2ns(u16 ltr) +{ + u32 value, scale; + + /* Determine the latency in nsec based on the LTR value & scale */ + value = ltr & E1000_LTRV_VALUE_MASK; + scale = (ltr & E1000_LTRV_SCALE_MASK) >> E1000_LTRV_SCALE_SHIFT; + + return value * (1 << (scale * E1000_LTRV_SCALE_FACTOR)); +} + +/** + * e1000_platform_pm_pch_lpt - Set platform power management values + * @hw: pointer to the HW structure + * @link: bool indicating link status + * + * Set the Latency Tolerance Reporting (LTR) values for the "PCIe-like" + * GbE MAC in the Lynx Point PCH based on Rx buffer size and link speed + * when link is up (which must not exceed the maximum latency supported + * by the platform), otherwise specify there is no LTR requirement. + * Unlike TRUE-PCIe devices which set the LTR maximum snoop/no-snoop + * latencies in the LTR Extended Capability Structure in the PCIe Extended + * Capability register set, on this device LTR is set by writing the + * equivalent snoop/no-snoop latencies in the LTRV register in the MAC and + * set the SEND bit to send an Intel On-chip System Fabric sideband (IOSF-SB) + * message to the PMC. + * + * Use the LTR value to calculate the Optimized Buffer Flush/Fill (OBFF) + * high-water mark. + **/ +static s32 e1000_platform_pm_pch_lpt(struct e1000_hw *hw, bool link) +{ + u32 reg = link << (E1000_LTRV_REQ_SHIFT + E1000_LTRV_NOSNOOP_SHIFT) | + link << E1000_LTRV_REQ_SHIFT | E1000_LTRV_SEND; + u16 lat_enc = 0; /* latency encoded */ + s32 obff_hwm = 0; + + DEBUGFUNC("e1000_platform_pm_pch_lpt"); + + if (link) { + u16 speed, duplex, scale = 0; + u16 max_snoop, max_nosnoop; + u16 max_ltr_enc; /* max LTR latency encoded */ + s64 lat_ns; /* latency (ns) */ + s64 value; + u32 rxa; + + if (!hw->mac.max_frame_size) { + DEBUGOUT("max_frame_size not set.\n"); + return -E1000_ERR_CONFIG; + } + + hw->mac.ops.get_link_up_info(hw, &speed, &duplex); + if (!speed) { + DEBUGOUT("Speed not set.\n"); + return -E1000_ERR_CONFIG; + } + + /* Rx Packet Buffer Allocation size (KB) */ + rxa = E1000_READ_REG(hw, E1000_PBA) & E1000_PBA_RXA_MASK; + + /* Determine the maximum latency tolerated by the device. + * + * Per the PCIe spec, the tolerated latencies are encoded as + * a 3-bit encoded scale (only 0-5 are valid) multiplied by + * a 10-bit value (0-1023) to provide a range from 1 ns to + * 2^25*(2^10-1) ns. The scale is encoded as 0=2^0ns, + * 1=2^5ns, 2=2^10ns,...5=2^25ns. + */ + lat_ns = ((s64)rxa * 1024 - + (2 * (s64)hw->mac.max_frame_size)) * 8 * 1000; + if (lat_ns < 0) + lat_ns = 0; + else + lat_ns /= speed; + + value = lat_ns; + while (value > E1000_LTRV_VALUE_MASK) { + scale++; + value = E1000_DIVIDE_ROUND_UP(value, (1 << 5)); + } + if (scale > E1000_LTRV_SCALE_MAX) { + DEBUGOUT1("Invalid LTR latency scale %d\n", scale); + return -E1000_ERR_CONFIG; + } + lat_enc = (u16)((scale << E1000_LTRV_SCALE_SHIFT) | value); + + /* Determine the maximum latency tolerated by the platform */ + e1000_read_pci_cfg(hw, E1000_PCI_LTR_CAP_LPT, &max_snoop); + e1000_read_pci_cfg(hw, E1000_PCI_LTR_CAP_LPT + 2, &max_nosnoop); + max_ltr_enc = E1000_MAX(max_snoop, max_nosnoop); + + if (lat_enc > max_ltr_enc) { + lat_enc = max_ltr_enc; + lat_ns = e1000_ltr2ns(max_ltr_enc); + } + + if (lat_ns) { + lat_ns *= speed * 1000; + lat_ns /= 8; + lat_ns /= 1000000000; + obff_hwm = (s32)(rxa - lat_ns); + } + + if ((obff_hwm < 0) || (obff_hwm > E1000_SVT_OFF_HWM_MASK)) { + DEBUGOUT1("Invalid high water mark %d\n", obff_hwm); + return -E1000_ERR_CONFIG; + } + } + + /* Set Snoop and No-Snoop latencies the same */ + reg |= lat_enc | (lat_enc << E1000_LTRV_NOSNOOP_SHIFT); + E1000_WRITE_REG(hw, E1000_LTRV, reg); + + /* Set OBFF high water mark */ + reg = E1000_READ_REG(hw, E1000_SVT) & ~E1000_SVT_OFF_HWM_MASK; + reg |= obff_hwm; + E1000_WRITE_REG(hw, E1000_SVT, reg); + + /* Enable OBFF */ + reg = E1000_READ_REG(hw, E1000_SVCR); + reg |= E1000_SVCR_OFF_EN; + /* Always unblock interrupts to the CPU even when the system is + * in OBFF mode. This ensures that small round-robin traffic + * (like ping) does not get dropped or experience long latency. + */ + reg |= E1000_SVCR_OFF_MASKINT; + E1000_WRITE_REG(hw, E1000_SVCR, reg); + + return E1000_SUCCESS; +} + +/** + * e1000_set_obff_timer_pch_lpt - Update Optimized Buffer Flush/Fill timer + * @hw: pointer to the HW structure + * @itr: interrupt throttling rate + * + * Configure OBFF with the updated interrupt rate. + **/ +static s32 e1000_set_obff_timer_pch_lpt(struct e1000_hw *hw, u32 itr) +{ + u32 svcr; + s32 timer; + + DEBUGFUNC("e1000_set_obff_timer_pch_lpt"); + + /* Convert ITR value into microseconds for OBFF timer */ + timer = itr & E1000_ITR_MASK; + timer = (timer * E1000_ITR_MULT) / 1000; + + if ((timer < 0) || (timer > E1000_ITR_MASK)) { + DEBUGOUT1("Invalid OBFF timer %d\n", timer); + return -E1000_ERR_CONFIG; + } + + svcr = E1000_READ_REG(hw, E1000_SVCR); + svcr &= ~E1000_SVCR_OFF_TIMER_MASK; + svcr |= timer << E1000_SVCR_OFF_TIMER_SHIFT; + E1000_WRITE_REG(hw, E1000_SVCR, svcr); + + return E1000_SUCCESS; +} + /** * e1000_check_for_copper_link_ich8lan - Check for link (Copper) * @hw: pointer to the HW structure @@ -645,39 +1095,77 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) DEBUGFUNC("e1000_check_for_copper_link_ich8lan"); - /* - * We only want to go out to the PHY registers to see if Auto-Neg + /* We only want to go out to the PHY registers to see if Auto-Neg * has completed and/or if our link status has changed. The * get_link_status flag is set upon receiving a Link Status * Change or Rx Sequence Error interrupt. */ - if (!mac->get_link_status) { - ret_val = E1000_SUCCESS; - goto out; - } + if (!mac->get_link_status) + return E1000_SUCCESS; - /* - * First we want to see if the MII Status Register reports + /* First we want to see if the MII Status Register reports * link. If so, then we want to get the current speed/duplex * of the PHY. */ ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); if (ret_val) - goto out; + return ret_val; if (hw->mac.type == e1000_pchlan) { ret_val = e1000_k1_gig_workaround_hv(hw, link); if (ret_val) - goto out; + return ret_val; + } + + /* When connected at 10Mbps half-duplex, 82579 parts are excessively + * aggressive resulting in many collisions. To avoid this, increase + * the IPG and reduce Rx latency in the PHY. + */ + if ((hw->mac.type == e1000_pch2lan) && link) { + u32 reg; + reg = E1000_READ_REG(hw, E1000_STATUS); + if (!(reg & (E1000_STATUS_FD | E1000_STATUS_SPEED_MASK))) { + reg = E1000_READ_REG(hw, E1000_TIPG); + reg &= ~E1000_TIPG_IPGT_MASK; + reg |= 0xFF; + E1000_WRITE_REG(hw, E1000_TIPG, reg); + + /* Reduce Rx latency in analog PHY */ + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + return ret_val; + + ret_val = e1000_write_emi_reg_locked(hw, I82579_RX_CONFIG, 0); + + hw->phy.ops.release(hw); + + if (ret_val) + return ret_val; + } + } + + /* Work-around I218 hang issue */ + if ((hw->device_id == E1000_DEV_ID_PCH_LPTLP_I218_LM) || + (hw->device_id == E1000_DEV_ID_PCH_LPTLP_I218_V)) { + ret_val = e1000_k1_workaround_lpt_lp(hw, link); + if (ret_val) + return ret_val; } -#if defined(NAHUM6_HW) && (defined(LTR_SUPPORT) || defined(OBFF_SUPPORT)) if (hw->mac.type == e1000_pch_lpt) { + /* Set platform power management values for Latency Tolerance + * Reporting (LTR) and Optimized Buffer Flush/Fill (OBFF). + */ + ret_val = e1000_platform_pm_pch_lpt(hw, link); + if (ret_val) + return ret_val; } -#endif /* NAHUM6_HW && (LTR_SUPPORT || OBFF_SUPPORT) */ + /* Clear link partner's EEE ability */ + hw->dev_spec.ich8lan.eee_lp_ability = 0; + if (!link) - goto out; /* No link detected */ + return E1000_SUCCESS; /* No link detected */ mac->get_link_status = FALSE; @@ -685,17 +1173,16 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) case e1000_pch2lan: ret_val = e1000_k1_workaround_lv(hw); if (ret_val) - goto out; + return ret_val; /* fall-thru */ case e1000_pchlan: if (hw->phy.type == e1000_phy_82578) { ret_val = e1000_link_stall_workaround_hv(hw); if (ret_val) - goto out; + return ret_val; } - /* - * Workaround for PCHx parts in half-duplex: + /* Workaround for PCHx parts in half-duplex: * Set the number of preambles removed from the packet * when it is passed from the PHY to the MAC to prevent * the MAC from misinterpreting the packet type. @@ -713,8 +1200,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) break; } - /* - * Check if there was DownShift, must be checked + /* Check if there was DownShift, must be checked * immediately after link-up */ e1000_check_downshift_generic(hw); @@ -722,26 +1208,21 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) /* Enable/Disable EEE after link up */ ret_val = e1000_set_eee_pchlan(hw); if (ret_val) - goto out; + return ret_val; - /* - * If we are forcing speed/duplex, then we simply return since + /* If we are forcing speed/duplex, then we simply return since * we have already determined whether we have link or not. */ - if (!mac->autoneg) { - ret_val = -E1000_ERR_CONFIG; - goto out; - } + if (!mac->autoneg) + return -E1000_ERR_CONFIG; - /* - * Auto-Neg is enabled. Auto Speed Detection takes care + /* Auto-Neg is enabled. Auto Speed Detection takes care * of MAC speed/duplex configuration. So we only need to * configure Collision Distance in the MAC. */ - hw->mac.ops.config_collision_dist(hw); + mac->ops.config_collision_dist(hw); - /* - * Configure Flow Control now that Auto-Neg has completed. + /* Configure Flow Control now that Auto-Neg has completed. * First, we need to restore the desired flow control * settings because we may have had to re-autoneg with a * different link partner. @@ -750,7 +1231,6 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) if (ret_val) DEBUGOUT("Error configuring flow control\n"); -out: return ret_val; } @@ -774,6 +1254,7 @@ void e1000_init_function_pointers_ich8lan(struct e1000_hw *hw) break; case e1000_pchlan: case e1000_pch2lan: + case e1000_pch_lpt: hw->phy.ops.init_params = e1000_init_phy_params_pchlan; break; default: @@ -957,8 +1438,7 @@ static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index) DEBUGFUNC("e1000_rar_set_pch2lan"); - /* - * HW expects these in little endian so we reverse the byte order + /* HW expects these in little endian so we reverse the byte order * from network order (big endian) to little endian */ rar_low = ((u32) addr[0] | @@ -980,11 +1460,19 @@ static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index) } if (index < hw->mac.rar_entry_count) { + s32 ret_val; + + ret_val = e1000_acquire_swflag_ich8lan(hw); + if (ret_val) + goto out; + E1000_WRITE_REG(hw, E1000_SHRAL(index - 1), rar_low); E1000_WRITE_FLUSH(hw); E1000_WRITE_REG(hw, E1000_SHRAH(index - 1), rar_high); E1000_WRITE_FLUSH(hw); + e1000_release_swflag_ich8lan(hw); + /* verify the register updates */ if ((E1000_READ_REG(hw, E1000_SHRAL(index - 1)) == rar_low) && (E1000_READ_REG(hw, E1000_SHRAH(index - 1)) == rar_high)) @@ -994,6 +1482,85 @@ static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index) (index - 1), E1000_READ_REG(hw, E1000_FWSM)); } +out: + DEBUGOUT1("Failed to write receive address at index %d\n", index); +} + +/** + * e1000_rar_set_pch_lpt - Set receive address registers + * @hw: pointer to the HW structure + * @addr: pointer to the receive address + * @index: receive address array register + * + * Sets the receive address register array at index to the address passed + * in by addr. For LPT, RAR[0] is the base address register that is to + * contain the MAC address. SHRA[0-10] are the shared receive address + * registers that are shared between the Host and manageability engine (ME). + **/ +static void e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index) +{ + u32 rar_low, rar_high; + u32 wlock_mac; + + DEBUGFUNC("e1000_rar_set_pch_lpt"); + + /* HW expects these in little endian so we reverse the byte order + * from network order (big endian) to little endian + */ + rar_low = ((u32) addr[0] | ((u32) addr[1] << 8) | + ((u32) addr[2] << 16) | ((u32) addr[3] << 24)); + + rar_high = ((u32) addr[4] | ((u32) addr[5] << 8)); + + /* If MAC address zero, no need to set the AV bit */ + if (rar_low || rar_high) + rar_high |= E1000_RAH_AV; + + if (index == 0) { + E1000_WRITE_REG(hw, E1000_RAL(index), rar_low); + E1000_WRITE_FLUSH(hw); + E1000_WRITE_REG(hw, E1000_RAH(index), rar_high); + E1000_WRITE_FLUSH(hw); + return; + } + + /* The manageability engine (ME) can lock certain SHRAR registers that + * it is using - those registers are unavailable for use. + */ + if (index < hw->mac.rar_entry_count) { + wlock_mac = E1000_READ_REG(hw, E1000_FWSM) & + E1000_FWSM_WLOCK_MAC_MASK; + wlock_mac >>= E1000_FWSM_WLOCK_MAC_SHIFT; + + /* Check if all SHRAR registers are locked */ + if (wlock_mac == 1) + goto out; + + if ((wlock_mac == 0) || (index <= wlock_mac)) { + s32 ret_val; + + ret_val = e1000_acquire_swflag_ich8lan(hw); + + if (ret_val) + goto out; + + E1000_WRITE_REG(hw, E1000_SHRAL_PCH_LPT(index - 1), + rar_low); + E1000_WRITE_FLUSH(hw); + E1000_WRITE_REG(hw, E1000_SHRAH_PCH_LPT(index - 1), + rar_high); + E1000_WRITE_FLUSH(hw); + + e1000_release_swflag_ich8lan(hw); + + /* verify the register updates */ + if ((E1000_READ_REG(hw, E1000_SHRAL_PCH_LPT(index - 1)) == rar_low) && + (E1000_READ_REG(hw, E1000_SHRAH_PCH_LPT(index - 1)) == rar_high)) + return; + } + } + +out: DEBUGOUT1("Failed to write receive address at index %d\n", index); } @@ -1072,21 +1639,34 @@ static s32 e1000_write_smbus_addr(struct e1000_hw *hw) { u16 phy_data; u32 strap = E1000_READ_REG(hw, E1000_STRAP); - s32 ret_val = E1000_SUCCESS; + u32 freq = (strap & E1000_STRAP_SMT_FREQ_MASK) >> + E1000_STRAP_SMT_FREQ_SHIFT; + s32 ret_val; strap &= E1000_STRAP_SMBUS_ADDRESS_MASK; ret_val = e1000_read_phy_reg_hv_locked(hw, HV_SMB_ADDR, &phy_data); if (ret_val) - goto out; + return ret_val; phy_data &= ~HV_SMB_ADDR_MASK; phy_data |= (strap >> E1000_STRAP_SMBUS_ADDRESS_SHIFT); phy_data |= HV_SMB_ADDR_PEC_EN | HV_SMB_ADDR_VALID; - ret_val = e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR, phy_data); -out: - return ret_val; + if (hw->phy.type == e1000_phy_i217) { + /* Restore SMBus frequency */ + if (freq--) { + phy_data &= ~HV_SMB_ADDR_FREQ_MASK; + phy_data |= (freq & (1 << 0)) << + HV_SMB_ADDR_FREQ_LOW_SHIFT; + phy_data |= (freq & (1 << 1)) << + (HV_SMB_ADDR_FREQ_HIGH_SHIFT - 1); + } else { + DEBUGOUT("Unsupported SMB frequency in PHY\n"); + } + } + + return e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR, phy_data); } /** @@ -1105,8 +1685,7 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) DEBUGFUNC("e1000_sw_lcd_config_ich8lan"); - /* - * Initialize the PHY from the NVM on ICH platforms. This + /* Initialize the PHY from the NVM on ICH platforms. This * is needed due to an issue where the NVM configuration is * not properly autoloaded after power transitions. * Therefore, after each PHY reset, we will load the @@ -1125,6 +1704,7 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) /* Fall-thru */ case e1000_pchlan: case e1000_pch2lan: + case e1000_pch_lpt: sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M; break; default: @@ -1137,45 +1717,42 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) data = E1000_READ_REG(hw, E1000_FEXTNVM); if (!(data & sw_cfg_mask)) - goto out; + goto release; - /* - * Make sure HW does not configure LCD from PHY + /* Make sure HW does not configure LCD from PHY * extended configuration before SW configuration */ data = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); - if (!(hw->mac.type == e1000_pch2lan)) { - if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE) - goto out; - } + if ((hw->mac.type < e1000_pch2lan) && + (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)) + goto release; cnf_size = E1000_READ_REG(hw, E1000_EXTCNF_SIZE); cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK; cnf_size >>= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT; if (!cnf_size) - goto out; + goto release; cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK; cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT; - if ((!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) && - (hw->mac.type == e1000_pchlan)) || - (hw->mac.type == e1000_pch2lan)) { - /* - * HW configures the SMBus address and LEDs when the + if (((hw->mac.type == e1000_pchlan) && + !(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE)) || + (hw->mac.type > e1000_pchlan)) { + /* HW configures the SMBus address and LEDs when the * OEM and LCD Write Enable bits are set in the NVM. * When both NVM bits are cleared, SW will configure * them instead. */ ret_val = e1000_write_smbus_addr(hw); if (ret_val) - goto out; + goto release; data = E1000_READ_REG(hw, E1000_LEDCTL); ret_val = e1000_write_phy_reg_hv_locked(hw, HV_LED_CONFIG, (u16)data); if (ret_val) - goto out; + goto release; } /* Configure LCD from extended configuration region. */ @@ -1187,12 +1764,12 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) ret_val = hw->nvm.ops.read(hw, (word_addr + i * 2), 1, ®_data); if (ret_val) - goto out; + goto release; ret_val = hw->nvm.ops.read(hw, (word_addr + i * 2 + 1), 1, ®_addr); if (ret_val) - goto out; + goto release; /* Save off the PHY page for future writes. */ if (reg_addr == IGP01E1000_PHY_PAGE_SELECT) { @@ -1206,10 +1783,10 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) ret_val = phy->ops.write_reg_locked(hw, (u32)reg_addr, reg_data); if (ret_val) - goto out; + goto release; } -out: +release: hw->phy.ops.release(hw); return ret_val; } @@ -1233,12 +1810,12 @@ static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link) DEBUGFUNC("e1000_k1_gig_workaround_hv"); if (hw->mac.type != e1000_pchlan) - goto out; + return E1000_SUCCESS; /* Wrap the whole flow with the sw flag */ ret_val = hw->phy.ops.acquire(hw); if (ret_val) - goto out; + return ret_val; /* Disable K1 when link is 1Gbps, otherwise use the NVM setting */ if (link) { @@ -1292,7 +1869,7 @@ static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link) release: hw->phy.ops.release(hw); -out: + return ret_val; } @@ -1308,7 +1885,7 @@ out: **/ s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable) { - s32 ret_val = E1000_SUCCESS; + s32 ret_val; u32 ctrl_reg = 0; u32 ctrl_ext = 0; u32 reg = 0; @@ -1319,7 +1896,7 @@ s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable) ret_val = e1000_read_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_K1_CONFIG, &kmrn_reg); if (ret_val) - goto out; + return ret_val; if (k1_enable) kmrn_reg |= E1000_KMRNCTRLSTA_K1_ENABLE; @@ -1329,7 +1906,7 @@ s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable) ret_val = e1000_write_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_K1_CONFIG, kmrn_reg); if (ret_val) - goto out; + return ret_val; usec_delay(20); ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); @@ -1347,8 +1924,7 @@ s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable) E1000_WRITE_FLUSH(hw); usec_delay(20); -out: - return ret_val; + return E1000_SUCCESS; } /** @@ -1368,28 +1944,28 @@ static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state) DEBUGFUNC("e1000_oem_bits_config_ich8lan"); - if ((hw->mac.type != e1000_pch2lan) && (hw->mac.type != e1000_pchlan)) + if (hw->mac.type < e1000_pchlan) return ret_val; ret_val = hw->phy.ops.acquire(hw); if (ret_val) return ret_val; - if (!(hw->mac.type == e1000_pch2lan)) { + if (hw->mac.type == e1000_pchlan) { mac_reg = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) - goto out; + goto release; } mac_reg = E1000_READ_REG(hw, E1000_FEXTNVM); if (!(mac_reg & E1000_FEXTNVM_SW_CONFIG_ICH8M)) - goto out; + goto release; mac_reg = E1000_READ_REG(hw, E1000_PHY_CTRL); ret_val = hw->phy.ops.read_reg_locked(hw, HV_OEM_BITS, &oem_reg); if (ret_val) - goto out; + goto release; oem_reg &= ~(HV_OEM_BITS_GBE_DIS | HV_OEM_BITS_LPLU); @@ -1399,10 +1975,6 @@ static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state) if (mac_reg & E1000_PHY_CTRL_D0A_LPLU) oem_reg |= HV_OEM_BITS_LPLU; - - /* Set Restart auto-neg to activate the bits */ - if (!hw->phy.ops.check_reset_block(hw)) - oem_reg |= HV_OEM_BITS_RESTART_AN; } else { if (mac_reg & (E1000_PHY_CTRL_GBE_DISABLE | E1000_PHY_CTRL_NOND0A_GBE_DISABLE)) @@ -1413,9 +1985,14 @@ static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state) oem_reg |= HV_OEM_BITS_LPLU; } + /* Set Restart auto-neg to activate the bits */ + if ((d0_state || (hw->mac.type != e1000_pchlan)) && + !hw->phy.ops.check_reset_block(hw)) + oem_reg |= HV_OEM_BITS_RESTART_AN; + ret_val = hw->phy.ops.write_reg_locked(hw, HV_OEM_BITS, oem_reg); -out: +release: hw->phy.ops.release(hw); return ret_val; @@ -1456,13 +2033,13 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw) DEBUGFUNC("e1000_hv_phy_workarounds_ich8lan"); if (hw->mac.type != e1000_pchlan) - goto out; + return E1000_SUCCESS; /* Set MDIO slow mode before any other MDIO access */ if (hw->phy.type == e1000_phy_82577) { ret_val = e1000_set_mdio_slow_mode_hv(hw); if (ret_val) - goto out; + return ret_val; } if (((hw->phy.type == e1000_phy_82577) && @@ -1471,18 +2048,17 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw) /* Disable generation of early preamble */ ret_val = hw->phy.ops.write_reg(hw, PHY_REG(769, 25), 0x4431); if (ret_val) - goto out; + return ret_val; /* Preamble tuning for SSC */ ret_val = hw->phy.ops.write_reg(hw, HV_KMRN_FIFO_CTRLSTA, 0xA204); if (ret_val) - goto out; + return ret_val; } if (hw->phy.type == e1000_phy_82578) { - /* - * Return registers to default by doing a soft reset then + /* Return registers to default by doing a soft reset then * writing 0x3140 to the control register. */ if (hw->phy.revision < 2) { @@ -1495,34 +2071,38 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw) /* Select page 0 */ ret_val = hw->phy.ops.acquire(hw); if (ret_val) - goto out; + return ret_val; hw->phy.addr = 1; ret_val = e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0); hw->phy.ops.release(hw); if (ret_val) - goto out; + return ret_val; - /* - * Configure the K1 Si workaround during phy reset assuming there is + /* Configure the K1 Si workaround during phy reset assuming there is * link so that it disables K1 if link is in 1Gbps. */ ret_val = e1000_k1_gig_workaround_hv(hw, TRUE); if (ret_val) - goto out; + return ret_val; /* Workaround for link disconnects on a busy hub in half duplex */ ret_val = hw->phy.ops.acquire(hw); if (ret_val) - goto out; + return ret_val; ret_val = hw->phy.ops.read_reg_locked(hw, BM_PORT_GEN_CFG, &phy_data); if (ret_val) goto release; ret_val = hw->phy.ops.write_reg_locked(hw, BM_PORT_GEN_CFG, phy_data & 0x00FF); + if (ret_val) + goto release; + + /* set MSE higher to enable link to stay up when noise is high */ + ret_val = e1000_write_emi_reg_locked(hw, I82577_MSE_THRESHOLD, 0x0034); release: hw->phy.ops.release(hw); -out: + return ret_val; } @@ -1600,19 +2180,18 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable) DEBUGFUNC("e1000_lv_jumbo_workaround_ich8lan"); - if (hw->mac.type != e1000_pch2lan) - goto out; + if (hw->mac.type < e1000_pch2lan) + return E1000_SUCCESS; /* disable Rx path while enabling/disabling workaround */ hw->phy.ops.read_reg(hw, PHY_REG(769, 20), &phy_reg); ret_val = hw->phy.ops.write_reg(hw, PHY_REG(769, 20), phy_reg | (1 << 14)); if (ret_val) - goto out; + return ret_val; if (enable) { - /* - * Write Rx addresses (rar_entry_count for RAL/H, +4 for + /* Write Rx addresses (rar_entry_count for RAL/H, +4 for * SHRAL/H) and initial CRC values to the MAC */ for (i = 0; i < (hw->mac.rar_entry_count + 4); i++) { @@ -1651,24 +2230,24 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable) E1000_KMRNCTRLSTA_CTRL_OFFSET, &data); if (ret_val) - goto out; + return ret_val; ret_val = e1000_write_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_CTRL_OFFSET, data | (1 << 0)); if (ret_val) - goto out; + return ret_val; ret_val = e1000_read_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_HD_CTRL, &data); if (ret_val) - goto out; + return ret_val; data &= ~(0xF << 8); data |= (0xB << 8); ret_val = e1000_write_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_HD_CTRL, data); if (ret_val) - goto out; + return ret_val; /* Enable jumbo frame workaround in the PHY */ hw->phy.ops.read_reg(hw, PHY_REG(769, 23), &data); @@ -1676,26 +2255,26 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable) data |= (0x37 << 5); ret_val = hw->phy.ops.write_reg(hw, PHY_REG(769, 23), data); if (ret_val) - goto out; + return ret_val; hw->phy.ops.read_reg(hw, PHY_REG(769, 16), &data); data &= ~(1 << 13); ret_val = hw->phy.ops.write_reg(hw, PHY_REG(769, 16), data); if (ret_val) - goto out; + return ret_val; hw->phy.ops.read_reg(hw, PHY_REG(776, 20), &data); data &= ~(0x3FF << 2); data |= (0x1A << 2); ret_val = hw->phy.ops.write_reg(hw, PHY_REG(776, 20), data); if (ret_val) - goto out; + return ret_val; ret_val = hw->phy.ops.write_reg(hw, PHY_REG(776, 23), 0xF100); if (ret_val) - goto out; + return ret_val; hw->phy.ops.read_reg(hw, HV_PM_CTRL, &data); ret_val = hw->phy.ops.write_reg(hw, HV_PM_CTRL, data | (1 << 10)); if (ret_val) - goto out; + return ret_val; } else { /* Write MAC register values back to h/w defaults */ mac_reg = E1000_READ_REG(hw, E1000_FFLT_DBG); @@ -1710,58 +2289,55 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable) E1000_KMRNCTRLSTA_CTRL_OFFSET, &data); if (ret_val) - goto out; + return ret_val; ret_val = e1000_write_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_CTRL_OFFSET, data & ~(1 << 0)); if (ret_val) - goto out; + return ret_val; ret_val = e1000_read_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_HD_CTRL, &data); if (ret_val) - goto out; + return ret_val; data &= ~(0xF << 8); data |= (0xB << 8); ret_val = e1000_write_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_HD_CTRL, data); if (ret_val) - goto out; + return ret_val; /* Write PHY register values back to h/w defaults */ hw->phy.ops.read_reg(hw, PHY_REG(769, 23), &data); data &= ~(0x7F << 5); ret_val = hw->phy.ops.write_reg(hw, PHY_REG(769, 23), data); if (ret_val) - goto out; + return ret_val; hw->phy.ops.read_reg(hw, PHY_REG(769, 16), &data); data |= (1 << 13); ret_val = hw->phy.ops.write_reg(hw, PHY_REG(769, 16), data); if (ret_val) - goto out; + return ret_val; hw->phy.ops.read_reg(hw, PHY_REG(776, 20), &data); data &= ~(0x3FF << 2); data |= (0x8 << 2); ret_val = hw->phy.ops.write_reg(hw, PHY_REG(776, 20), data); if (ret_val) - goto out; + return ret_val; ret_val = hw->phy.ops.write_reg(hw, PHY_REG(776, 23), 0x7E00); if (ret_val) - goto out; + return ret_val; hw->phy.ops.read_reg(hw, HV_PM_CTRL, &data); ret_val = hw->phy.ops.write_reg(hw, HV_PM_CTRL, data & ~(1 << 10)); if (ret_val) - goto out; + return ret_val; } /* re-enable Rx path after enabling/disabling workaround */ - ret_val = hw->phy.ops.write_reg(hw, PHY_REG(769, 20), phy_reg & - ~(1 << 14)); - -out: - return ret_val; + return hw->phy.ops.write_reg(hw, PHY_REG(769, 20), phy_reg & + ~(1 << 14)); } /** @@ -1775,34 +2351,25 @@ static s32 e1000_lv_phy_workarounds_ich8lan(struct e1000_hw *hw) DEBUGFUNC("e1000_lv_phy_workarounds_ich8lan"); if (hw->mac.type != e1000_pch2lan) - goto out; + return E1000_SUCCESS; /* Set MDIO slow mode before any other MDIO access */ ret_val = e1000_set_mdio_slow_mode_hv(hw); + if (ret_val) + return ret_val; ret_val = hw->phy.ops.acquire(hw); if (ret_val) - goto out; - ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_ADDR, - I82579_MSE_THRESHOLD); - if (ret_val) - goto release; + return ret_val; /* set MSE higher to enable link to stay up when noise is high */ - ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_DATA, - 0x0034); - if (ret_val) - goto release; - ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_ADDR, - I82579_MSE_LINK_DOWN); + ret_val = e1000_write_emi_reg_locked(hw, I82579_MSE_THRESHOLD, 0x0034); if (ret_val) goto release; /* drop link after 5 times MSE threshold was reached */ - ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_DATA, - 0x0005); + ret_val = e1000_write_emi_reg_locked(hw, I82579_MSE_LINK_DOWN, 0x0005); release: hw->phy.ops.release(hw); -out: return ret_val; } @@ -1822,12 +2389,12 @@ static s32 e1000_k1_workaround_lv(struct e1000_hw *hw) DEBUGFUNC("e1000_k1_workaround_lv"); if (hw->mac.type != e1000_pch2lan) - goto out; + return E1000_SUCCESS; /* Set K1 beacon duration based on 1Gbps speed or otherwise */ ret_val = hw->phy.ops.read_reg(hw, HV_M_STATUS, &status_reg); if (ret_val) - goto out; + return ret_val; if ((status_reg & (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE)) == (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE)) { @@ -1836,11 +2403,23 @@ static s32 e1000_k1_workaround_lv(struct e1000_hw *hw) ret_val = hw->phy.ops.read_reg(hw, I82579_LPI_CTRL, &phy_reg); if (ret_val) - goto out; + return ret_val; if (status_reg & HV_M_STATUS_SPEED_1000) { + u16 pm_phy_reg; + mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_8USEC; phy_reg &= ~I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT; + /* LV 1G Packet drop issue wa */ + ret_val = hw->phy.ops.read_reg(hw, HV_PM_CTRL, + &pm_phy_reg); + if (ret_val) + return ret_val; + pm_phy_reg &= ~HV_PM_CTRL_PLL_STOP_IN_K1_GIGA; + ret_val = hw->phy.ops.write_reg(hw, HV_PM_CTRL, + pm_phy_reg); + if (ret_val) + return ret_val; } else { mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_16USEC; phy_reg |= I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT; @@ -1849,7 +2428,6 @@ static s32 e1000_k1_workaround_lv(struct e1000_hw *hw) ret_val = hw->phy.ops.write_reg(hw, I82579_LPI_CTRL, phy_reg); } -out: return ret_val; } @@ -1867,7 +2445,7 @@ static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate) DEBUGFUNC("e1000_gate_hw_phy_config_ich8lan"); - if (hw->mac.type != e1000_pch2lan) + if (hw->mac.type < e1000_pch2lan) return; extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL); @@ -1878,7 +2456,6 @@ static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate) extcnf_ctrl &= ~E1000_EXTCNF_CTRL_GATE_PHY_CFG; E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl); - return; } /** @@ -1901,8 +2478,7 @@ static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw) usec_delay(100); } while ((!data) && --loop); - /* - * If basic configuration is incomplete before the above loop + /* If basic configuration is incomplete before the above loop * count reaches 0, loading the configuration from NVM will * leave the PHY in a bad state possibly resulting in no link. */ @@ -1927,7 +2503,7 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw) DEBUGFUNC("e1000_post_phy_reset_ich8lan"); if (hw->phy.ops.check_reset_block(hw)) - goto out; + return E1000_SUCCESS; /* Allow time for h/w to get to quiescent state after reset */ msec_delay(10); @@ -1937,12 +2513,12 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw) case e1000_pchlan: ret_val = e1000_hv_phy_workarounds_ich8lan(hw); if (ret_val) - goto out; + return ret_val; break; case e1000_pch2lan: ret_val = e1000_lv_phy_workarounds_ich8lan(hw); if (ret_val) - goto out; + return ret_val; break; default: break; @@ -1958,7 +2534,7 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw) /* Configure the LCD with the extended configuration region in NVM */ ret_val = e1000_sw_lcd_config_ich8lan(hw); if (ret_val) - goto out; + return ret_val; /* Configure the LCD with the OEM bits in NVM */ ret_val = e1000_oem_bits_config_ich8lan(hw, TRUE); @@ -1974,18 +2550,13 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw) /* Set EEE LPI Update Timer to 200usec */ ret_val = hw->phy.ops.acquire(hw); if (ret_val) - goto out; - ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_ADDR, - I82579_LPI_UPDATE_TIMER); - if (ret_val) - goto release; - ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_DATA, - 0x1387); -release: + return ret_val; + ret_val = e1000_write_emi_reg_locked(hw, + I82579_LPI_UPDATE_TIMER, + 0x1387); hw->phy.ops.release(hw); } -out: return ret_val; } @@ -2010,12 +2581,9 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw) ret_val = e1000_phy_hw_reset_generic(hw); if (ret_val) - goto out; + return ret_val; - ret_val = e1000_post_phy_reset_ich8lan(hw); - -out: - return ret_val; + return e1000_post_phy_reset_ich8lan(hw); } /** @@ -2031,14 +2599,14 @@ out: **/ static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active) { - s32 ret_val = E1000_SUCCESS; + s32 ret_val; u16 oem_reg; DEBUGFUNC("e1000_set_lplu_state_pchlan"); ret_val = hw->phy.ops.read_reg(hw, HV_OEM_BITS, &oem_reg); if (ret_val) - goto out; + return ret_val; if (active) oem_reg |= HV_OEM_BITS_LPLU; @@ -2048,10 +2616,7 @@ static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active) if (!hw->phy.ops.check_reset_block(hw)) oem_reg |= HV_OEM_BITS_RESTART_AN; - ret_val = hw->phy.ops.write_reg(hw, HV_OEM_BITS, oem_reg); - -out: - return ret_val; + return hw->phy.ops.write_reg(hw, HV_OEM_BITS, oem_reg); } /** @@ -2077,7 +2642,7 @@ static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active) DEBUGFUNC("e1000_set_d0_lplu_state_ich8lan"); if (phy->type == e1000_phy_ife) - goto out; + return E1000_SUCCESS; phy_ctrl = E1000_READ_REG(hw, E1000_PHY_CTRL); @@ -2086,10 +2651,9 @@ static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active) E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl); if (phy->type != e1000_phy_igp_3) - goto out; + return E1000_SUCCESS; - /* - * Call gig speed drop workaround on LPLU before accessing + /* Call gig speed drop workaround on LPLU before accessing * any PHY registers */ if (hw->mac.type == e1000_ich8lan) @@ -2099,21 +2663,22 @@ static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active) ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); + if (ret_val) + return ret_val; data &= ~IGP01E1000_PSCFR_SMART_SPEED; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) - goto out; + return ret_val; } else { phy_ctrl &= ~E1000_PHY_CTRL_D0A_LPLU; E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl); if (phy->type != e1000_phy_igp_3) - goto out; + return E1000_SUCCESS; - /* - * LPLU and SmartSpeed are mutually exclusive. LPLU is used + /* LPLU and SmartSpeed are mutually exclusive. LPLU is used * during Dx states where the power conservation is most * important. During driver activity we should enable * SmartSpeed, so performance is maintained. @@ -2123,32 +2688,31 @@ static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active) IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) - goto out; + return ret_val; data |= IGP01E1000_PSCFR_SMART_SPEED; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) - goto out; + return ret_val; } else if (phy->smart_speed == e1000_smart_speed_off) { ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) - goto out; + return ret_val; data &= ~IGP01E1000_PSCFR_SMART_SPEED; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) - goto out; + return ret_val; } } -out: - return ret_val; + return E1000_SUCCESS; } /** @@ -2180,10 +2744,9 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active) E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl); if (phy->type != e1000_phy_igp_3) - goto out; + return E1000_SUCCESS; - /* - * LPLU and SmartSpeed are mutually exclusive. LPLU is used + /* LPLU and SmartSpeed are mutually exclusive. LPLU is used * during Dx states where the power conservation is most * important. During driver activity we should enable * SmartSpeed, so performance is maintained. @@ -2193,27 +2756,27 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active) IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) - goto out; + return ret_val; data |= IGP01E1000_PSCFR_SMART_SPEED; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) - goto out; + return ret_val; } else if (phy->smart_speed == e1000_smart_speed_off) { ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) - goto out; + return ret_val; data &= ~IGP01E1000_PSCFR_SMART_SPEED; ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, data); if (ret_val) - goto out; + return ret_val; } } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) || (phy->autoneg_advertised == E1000_ALL_NOT_GIG) || @@ -2222,10 +2785,9 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active) E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl); if (phy->type != e1000_phy_igp_3) - goto out; + return E1000_SUCCESS; - /* - * Call gig speed drop workaround on LPLU before accessing + /* Call gig speed drop workaround on LPLU before accessing * any PHY registers */ if (hw->mac.type == e1000_ich8lan) @@ -2236,7 +2798,7 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active) IGP01E1000_PHY_PORT_CONFIG, &data); if (ret_val) - goto out; + return ret_val; data &= ~IGP01E1000_PSCFR_SMART_SPEED; ret_val = phy->ops.write_reg(hw, @@ -2244,7 +2806,6 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active) data); } -out: return ret_val; } @@ -2263,7 +2824,7 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank) u32 bank1_offset = nvm->flash_bank_size * sizeof(u16); u32 act_offset = E1000_ICH_NVM_SIG_WORD * 2 + 1; u8 sig_byte = 0; - s32 ret_val = E1000_SUCCESS; + s32 ret_val; DEBUGFUNC("e1000_valid_nvm_bank_detect_ich8lan"); @@ -2278,7 +2839,7 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank) else *bank = 0; - goto out; + return E1000_SUCCESS; } DEBUGOUT("Unable to determine valid NVM bank via EEC - reading flash signature\n"); /* fall-thru */ @@ -2290,11 +2851,11 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank) ret_val = e1000_read_flash_byte_ich8lan(hw, act_offset, &sig_byte); if (ret_val) - goto out; + return ret_val; if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) == E1000_ICH_NVM_SIG_VALUE) { *bank = 0; - goto out; + return E1000_SUCCESS; } /* Check bank 1 */ @@ -2302,19 +2863,16 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank) bank1_offset, &sig_byte); if (ret_val) - goto out; + return ret_val; if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) == E1000_ICH_NVM_SIG_VALUE) { *bank = 1; - goto out; + return E1000_SUCCESS; } DEBUGOUT("ERROR: No valid NVM bank present\n"); - ret_val = -E1000_ERR_NVM; - break; + return -E1000_ERR_NVM; } -out: - return ret_val; } /** @@ -2396,9 +2954,9 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw) hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS); /* Check if the flash descriptor is valid */ - if (hsfsts.hsf_status.fldesvalid == 0) { + if (!hsfsts.hsf_status.fldesvalid) { DEBUGOUT("Flash descriptor invalid. SW Sequencing must be used.\n"); - goto out; + return -E1000_ERR_NVM; } /* Clear FCERR and DAEL in hw status by writing 1 */ @@ -2407,8 +2965,7 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw) E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval); - /* - * Either we should have a hardware SPI cycle in progress + /* Either we should have a hardware SPI cycle in progress * bit to check against, in order to start a new cycle or * FDONE bit should be changed in the hardware so that it * is 1 after hardware reset, which can then be used as an @@ -2416,9 +2973,8 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw) * completed. */ - if (hsfsts.hsf_status.flcinprog == 0) { - /* - * There is no cycle running at present, + if (!hsfsts.hsf_status.flcinprog) { + /* There is no cycle running at present, * so we can start a cycle. * Begin by setting Flash Cycle Done. */ @@ -2428,22 +2984,20 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw) } else { s32 i; - /* - * Otherwise poll for sometime so the current + /* Otherwise poll for sometime so the current * cycle has a chance to end before giving up. */ for (i = 0; i < ICH_FLASH_READ_COMMAND_TIMEOUT; i++) { hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS); - if (hsfsts.hsf_status.flcinprog == 0) { + if (!hsfsts.hsf_status.flcinprog) { ret_val = E1000_SUCCESS; break; } usec_delay(1); } if (ret_val == E1000_SUCCESS) { - /* - * Successful in waiting for previous cycle to timeout, + /* Successful in waiting for previous cycle to timeout, * now set the Flash Cycle Done. */ hsfsts.hsf_status.flcdone = 1; @@ -2454,7 +3008,6 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw) } } -out: return ret_val; } @@ -2469,7 +3022,6 @@ static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout) { union ich8_hws_flash_ctrl hsflctl; union ich8_hws_flash_status hsfsts; - s32 ret_val = -E1000_ERR_NVM; u32 i = 0; DEBUGFUNC("e1000_flash_cycle_ich8lan"); @@ -2482,15 +3034,15 @@ static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout) /* wait till FDONE bit is set to 1 */ do { hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS); - if (hsfsts.hsf_status.flcdone == 1) + if (hsfsts.hsf_status.flcdone) break; usec_delay(1); } while (i++ < timeout); - if (hsfsts.hsf_status.flcdone == 1 && hsfsts.hsf_status.flcerr == 0) - ret_val = E1000_SUCCESS; + if (hsfsts.hsf_status.flcdone && !hsfsts.hsf_status.flcerr) + return E1000_SUCCESS; - return ret_val; + return -E1000_ERR_NVM; } /** @@ -2505,22 +3057,15 @@ static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout) static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, u32 offset, u16 *data) { - s32 ret_val; - DEBUGFUNC("e1000_read_flash_word_ich8lan"); - if (!data) { - ret_val = -E1000_ERR_NVM; - goto out; - } + if (!data) + return -E1000_ERR_NVM; /* Must convert offset into bytes. */ offset <<= 1; - ret_val = e1000_read_flash_data_ich8lan(hw, offset, 2, data); - -out: - return ret_val; + return e1000_read_flash_data_ich8lan(hw, offset, 2, data); } /** @@ -2534,17 +3079,16 @@ out: static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, u8 *data) { - s32 ret_val = E1000_SUCCESS; + s32 ret_val; u16 word = 0; ret_val = e1000_read_flash_data_ich8lan(hw, offset, 1, &word); if (ret_val) - goto out; + return ret_val; *data = (u8)word; -out: - return ret_val; + return E1000_SUCCESS; } /** @@ -2569,7 +3113,7 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, DEBUGFUNC("e1000_read_flash_data_ich8lan"); if (size < 1 || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK) - goto out; + return -E1000_ERR_NVM; flash_linear_addr = (ICH_FLASH_LINEAR_ADDR_MASK & offset) + hw->nvm.flash_base_addr; @@ -2592,8 +3136,7 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, ret_val = e1000_flash_cycle_ich8lan(hw, ICH_FLASH_READ_COMMAND_TIMEOUT); - /* - * Check if FCERR is set to 1, if set to 1, clear it + /* Check if FCERR is set to 1, if set to 1, clear it * and try the whole sequence a few more times, else * read in (shift in) the Flash Data0, the order is * least significant byte first msb to lsb @@ -2606,25 +3149,23 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, *data = (u16)(flash_data & 0x0000FFFF); break; } else { - /* - * If we've gotten here, then things are probably + /* If we've gotten here, then things are probably * completely hosed, but if the error condition is * detected, it won't hurt to give it another try... * ICH_FLASH_CYCLE_REPEAT_COUNT times. */ hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS); - if (hsfsts.hsf_status.flcerr == 1) { + if (hsfsts.hsf_status.flcerr) { /* Repeat for some time before giving up. */ continue; - } else if (hsfsts.hsf_status.flcdone == 0) { + } else if (!hsfsts.hsf_status.flcdone) { DEBUGOUT("Timeout error - flash cycle did not complete.\n"); break; } } } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT); -out: return ret_val; } @@ -2642,7 +3183,6 @@ static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, { struct e1000_nvm_info *nvm = &hw->nvm; struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; - s32 ret_val = E1000_SUCCESS; u16 i; DEBUGFUNC("e1000_write_nvm_ich8lan"); @@ -2650,8 +3190,7 @@ static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) || (words == 0)) { DEBUGOUT("nvm parameter(s) out of bounds\n"); - ret_val = -E1000_ERR_NVM; - goto out; + return -E1000_ERR_NVM; } nvm->ops.acquire(hw); @@ -2663,8 +3202,7 @@ static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, nvm->ops.release(hw); -out: - return ret_val; + return E1000_SUCCESS; } /** @@ -2697,8 +3235,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) nvm->ops.acquire(hw); - /* - * We're writing to the opposite bank so if we're on bank 1, + /* We're writing to the opposite bank so if we're on bank 1, * write to bank 0 etc. We also need to erase the segment that * is going to be written */ @@ -2723,8 +3260,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) } for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) { - /* - * Determine whether to write the value stored + /* Determine whether to write the value stored * in the other NVM bank or a modified value stored * in the shadow RAM */ @@ -2738,8 +3274,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) break; } - /* - * If the word is 0x13, then make sure the signature bits + /* If the word is 0x13, then make sure the signature bits * (15:14) are 11b until the commit has completed. * This will allow us to write 10b which indicates the * signature is valid. We want to do this after the write @@ -2768,8 +3303,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) break; } - /* - * Don't bother writing the segment valid bits if sector + /* Don't bother writing the segment valid bits if sector * programming failed. */ if (ret_val) { @@ -2777,8 +3311,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) goto release; } - /* - * Finally validate the new segment by setting bit 15:14 + /* Finally validate the new segment by setting bit 15:14 * to 10b in word 0x13 , this can be done without an * erase as well since these bits are 11 to start with * and we need to change bit 14 to 0b @@ -2795,8 +3328,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) if (ret_val) goto release; - /* - * And invalidate the previously valid segment by setting + /* And invalidate the previously valid segment by setting * its signature word (0x13) high_byte to 0b. This can be * done without an erase because flash erase sets all bits * to 1's. We can write 1's to 0's without an erase @@ -2815,8 +3347,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) release: nvm->ops.release(hw); - /* - * Reload the EEPROM, or else modifications will not appear + /* Reload the EEPROM, or else modifications will not appear * until after the next adapter reset. */ if (!ret_val) { @@ -2841,35 +3372,44 @@ out: **/ static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw) { - s32 ret_val = E1000_SUCCESS; + s32 ret_val; u16 data; + u16 word; + u16 valid_csum_mask; DEBUGFUNC("e1000_validate_nvm_checksum_ich8lan"); - /* - * Read 0x19 and check bit 6. If this bit is 0, the checksum - * needs to be fixed. This bit is an indication that the NVM - * was prepared by OEM software and did not calculate the - * checksum...a likely scenario. + /* Read NVM and check Invalid Image CSUM bit. If this bit is 0, + * the checksum needs to be fixed. This bit is an indication that + * the NVM was prepared by OEM software and did not calculate + * the checksum...a likely scenario. */ - ret_val = hw->nvm.ops.read(hw, 0x19, 1, &data); - if (ret_val) - goto out; - - if ((data & 0x40) == 0) { - data |= 0x40; - ret_val = hw->nvm.ops.write(hw, 0x19, 1, &data); - if (ret_val) - goto out; - ret_val = hw->nvm.ops.update(hw); - if (ret_val) - goto out; + switch (hw->mac.type) { + case e1000_pch_lpt: + word = NVM_COMPAT; + valid_csum_mask = NVM_COMPAT_VALID_CSUM; + break; + default: + word = NVM_FUTURE_INIT_WORD1; + valid_csum_mask = NVM_FUTURE_INIT_WORD1_VALID_CSUM; + break; } - ret_val = e1000_validate_nvm_checksum_generic(hw); + ret_val = hw->nvm.ops.read(hw, word, 1, &data); + if (ret_val) + return ret_val; -out: - return ret_val; + if (!(data & valid_csum_mask)) { + data |= valid_csum_mask; + ret_val = hw->nvm.ops.write(hw, word, 1, &data); + if (ret_val) + return ret_val; + ret_val = hw->nvm.ops.update(hw); + if (ret_val) + return ret_val; + } + + return e1000_validate_nvm_checksum_generic(hw); } /** @@ -2888,14 +3428,14 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, union ich8_hws_flash_ctrl hsflctl; u32 flash_linear_addr; u32 flash_data = 0; - s32 ret_val = -E1000_ERR_NVM; + s32 ret_val; u8 count = 0; DEBUGFUNC("e1000_write_ich8_data"); if (size < 1 || size > 2 || data > size * 0xff || offset > ICH_FLASH_LINEAR_ADDR_MASK) - goto out; + return -E1000_ERR_NVM; flash_linear_addr = (ICH_FLASH_LINEAR_ADDR_MASK & offset) + hw->nvm.flash_base_addr; @@ -2922,8 +3462,7 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FDATA0, flash_data); - /* - * check if FCERR is set to 1 , if set to 1, clear it + /* check if FCERR is set to 1 , if set to 1, clear it * and try the whole sequence a few more times else done */ ret_val = e1000_flash_cycle_ich8lan(hw, @@ -2931,23 +3470,21 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, if (ret_val == E1000_SUCCESS) break; - /* - * If we're here, then things are most likely + /* If we're here, then things are most likely * completely hosed, but if the error condition * is detected, it won't hurt to give it another * try...ICH_FLASH_CYCLE_REPEAT_COUNT times. */ hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS); - if (hsfsts.hsf_status.flcerr == 1) + if (hsfsts.hsf_status.flcerr) /* Repeat for some time before giving up. */ continue; - if (hsfsts.hsf_status.flcdone == 0) { + if (!hsfsts.hsf_status.flcdone) { DEBUGOUT("Timeout error - flash cycle did not complete.\n"); break; } } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT); -out: return ret_val; } @@ -2987,8 +3524,8 @@ static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw, DEBUGFUNC("e1000_retry_write_flash_byte_ich8lan"); ret_val = e1000_write_flash_byte_ich8lan(hw, offset, byte); - if (ret_val == E1000_SUCCESS) - goto out; + if (!ret_val) + return ret_val; for (program_retries = 0; program_retries < 100; program_retries++) { DEBUGOUT2("Retrying Byte %2.2X at offset %u\n", byte, offset); @@ -2997,13 +3534,10 @@ static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw, if (ret_val == E1000_SUCCESS) break; } - if (program_retries == 100) { - ret_val = -E1000_ERR_NVM; - goto out; - } + if (program_retries == 100) + return -E1000_ERR_NVM; -out: - return ret_val; + return E1000_SUCCESS; } /** @@ -3022,7 +3556,7 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) u32 flash_linear_addr; /* bank size is in 16bit words - adjust to bytes */ u32 flash_bank_size = nvm->flash_bank_size * 2; - s32 ret_val = E1000_SUCCESS; + s32 ret_val; s32 count = 0; s32 j, iteration, sector_size; @@ -3030,8 +3564,7 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS); - /* - * Determine HW Sector size: Read BERASE bits of hw flash status + /* Determine HW Sector size: Read BERASE bits of hw flash status * register * 00: The Hw sector is 256 bytes, hence we need to erase 16 * consecutive sectors. The start index for the nth Hw sector @@ -3062,8 +3595,7 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) iteration = 1; break; default: - ret_val = -E1000_ERR_NVM; - goto out; + return -E1000_ERR_NVM; } /* Start with the base address, then add the sector offset. */ @@ -3075,10 +3607,9 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) /* Steps */ ret_val = e1000_flash_cycle_init_ich8lan(hw); if (ret_val) - goto out; + return ret_val; - /* - * Write a value 11 (block Erase) in Flash + /* Write a value 11 (block Erase) in Flash * Cycle field in hw flash control */ hsflctl.regval = E1000_READ_FLASH_REG16(hw, @@ -3087,8 +3618,7 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval); - /* - * Write the last 24 bits of an index within the + /* Write the last 24 bits of an index within the * block into Flash Linear address field in Flash * Address. */ @@ -3101,23 +3631,21 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) if (ret_val == E1000_SUCCESS) break; - /* - * Check if FCERR is set to 1. If 1, + /* Check if FCERR is set to 1. If 1, * clear it and try the whole sequence * a few more times else Done */ hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS); - if (hsfsts.hsf_status.flcerr == 1) + if (hsfsts.hsf_status.flcerr) /* repeat for some time before giving up */ continue; - else if (hsfsts.hsf_status.flcdone == 0) - goto out; + else if (!hsfsts.hsf_status.flcdone) + return ret_val; } while (++count < ICH_FLASH_CYCLE_REPEAT_COUNT); } -out: - return ret_val; + return E1000_SUCCESS; } /** @@ -3138,14 +3666,13 @@ static s32 e1000_valid_led_default_ich8lan(struct e1000_hw *hw, u16 *data) ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); - goto out; + return ret_val; } if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) *data = ID_LED_DEFAULT_ICH8LAN; -out: - return ret_val; + return E1000_SUCCESS; } /** @@ -3174,7 +3701,7 @@ static s32 e1000_id_led_init_pchlan(struct e1000_hw *hw) /* Get default ID LED modes */ ret_val = hw->nvm.ops.valid_led_default(hw, &data); if (ret_val) - goto out; + return ret_val; mac->ledctl_default = E1000_READ_REG(hw, E1000_LEDCTL); mac->ledctl_mode1 = mac->ledctl_default; @@ -3219,8 +3746,7 @@ static s32 e1000_id_led_init_pchlan(struct e1000_hw *hw) } } -out: - return ret_val; + return E1000_SUCCESS; } /** @@ -3228,7 +3754,7 @@ out: * @hw: pointer to the HW structure * * ICH8 use the PCI Express bus, but does not contain a PCI Express Capability - * register, so the bus width is hard coded. + * register, so the the bus width is hard coded. **/ static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw) { @@ -3239,8 +3765,7 @@ static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw) ret_val = e1000_get_bus_info_pcie_generic(hw); - /* - * ICH devices are "PCI Express"-ish. They have + /* ICH devices are "PCI Express"-ish. They have * a configuration space, but do not contain * PCI Express Capability registers, so bus width * must be hardcoded. @@ -3261,14 +3786,13 @@ static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw) static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) { struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; - u16 reg; - u32 ctrl, kab; + u16 kum_cfg; + u32 ctrl, reg; s32 ret_val; DEBUGFUNC("e1000_reset_hw_ich8lan"); - /* - * Prevent the PCI-E bus from sticking if there is no TLP connection + /* Prevent the PCI-E bus from sticking if there is no TLP connection * on the last TLP read/write transaction when MAC is reset. */ ret_val = e1000_disable_pcie_master_generic(hw); @@ -3278,8 +3802,7 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) DEBUGOUT("Masking off all interrupts\n"); E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); - /* - * Disable the Transmit and Receive units. Then delay to allow + /* Disable the Transmit and Receive units. Then delay to allow * any pending transactions to complete before we hit the MAC * with the global reset. */ @@ -3299,11 +3822,11 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) if (hw->mac.type == e1000_pchlan) { /* Save the NVM K1 bit setting*/ - ret_val = e1000_read_nvm(hw, E1000_NVM_K1_CONFIG, 1, ®); + ret_val = e1000_read_nvm(hw, E1000_NVM_K1_CONFIG, 1, &kum_cfg); if (ret_val) return ret_val; - if (reg & E1000_NVM_K1_ENABLE) + if (kum_cfg & E1000_NVM_K1_ENABLE) dev_spec->nvm_k1_enabled = TRUE; else dev_spec->nvm_k1_enabled = FALSE; @@ -3312,15 +3835,13 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) ctrl = E1000_READ_REG(hw, E1000_CTRL); if (!hw->phy.ops.check_reset_block(hw)) { - /* - * Full-chip reset requires MAC and PHY reset at the same + /* Full-chip reset requires MAC and PHY reset at the same * time to make sure the interface between MAC and the * external PHY is reset. */ ctrl |= E1000_CTRL_PHY_RST; - /* - * Gate automatic PHY configuration by hardware on + /* Gate automatic PHY configuration by hardware on * non-managed 82579 */ if ((hw->mac.type == e1000_pch2lan) && @@ -3333,21 +3854,28 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) /* cannot issue a flush here because it hangs the hardware */ msec_delay(20); + /* Set Phy Config Counter to 50msec */ + if (hw->mac.type == e1000_pch2lan) { + reg = E1000_READ_REG(hw, E1000_FEXTNVM3); + reg &= ~E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK; + reg |= E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC; + E1000_WRITE_REG(hw, E1000_FEXTNVM3, reg); + } + if (!ret_val) E1000_MUTEX_UNLOCK(&hw->dev_spec.ich8lan.swflag_mutex); if (ctrl & E1000_CTRL_PHY_RST) { ret_val = hw->phy.ops.get_cfg_done(hw); if (ret_val) - goto out; + return ret_val; ret_val = e1000_post_phy_reset_ich8lan(hw); if (ret_val) - goto out; + return ret_val; } - /* - * For PCH, this write will make sure that any noise + /* For PCH, this write will make sure that any noise * will be detected as a CRC error and be dropped rather than show up * as a bad packet to the DMA engine. */ @@ -3357,12 +3885,11 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); E1000_READ_REG(hw, E1000_ICR); - kab = E1000_READ_REG(hw, E1000_KABGTXD); - kab |= E1000_KABGTXD_BGSQLBIAS; - E1000_WRITE_REG(hw, E1000_KABGTXD, kab); + reg = E1000_READ_REG(hw, E1000_KABGTXD); + reg |= E1000_KABGTXD_BGSQLBIAS; + E1000_WRITE_REG(hw, E1000_KABGTXD, reg); -out: - return ret_val; + return E1000_SUCCESS; } /** @@ -3390,9 +3917,9 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw) /* Initialize identification LED */ ret_val = mac->ops.id_led_init(hw); + /* An error is not fatal and we should not stop init due to this */ if (ret_val) DEBUGOUT("Error initializing identification LED\n"); - /* This is not fatal and we should not stop init due to this */ /* Setup the receive address. */ e1000_init_rx_addrs_generic(hw, mac->rar_entry_count); @@ -3402,8 +3929,7 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw) for (i = 0; i < mac->mta_reg_count; i++) E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); - /* - * The 82578 Rx buffer will stall if wakeup is enabled in host and + /* The 82578 Rx buffer will stall if wakeup is enabled in host and * the ME. Disable wakeup by clearing the host wakeup bit. * Reset the phy after disabling host wakeup to reset the Rx buffer. */ @@ -3433,8 +3959,7 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw) E1000_TXDCTL_MAX_TX_DESC_PREFETCH; E1000_WRITE_REG(hw, E1000_TXDCTL(1), txdctl); - /* - * ICH8 has opposite polarity of no_snoop bits. + /* ICH8 has opposite polarity of no_snoop bits. * By default, we should use snoop behavior. */ if (mac->type == e1000_ich8lan) @@ -3447,8 +3972,7 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw) ctrl_ext |= E1000_CTRL_EXT_RO_DIS; E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); - /* - * Clear all of the statistics registers (clear on read). It is + /* Clear all of the statistics registers (clear on read). It is * important that we do this after we have tried to establish link * because the symbol error count will increment wildly if there * is no link. @@ -3457,6 +3981,7 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw) return ret_val; } + /** * e1000_initialize_hw_bits_ich8lan - Initialize required hardware bits * @hw: pointer to the HW structure @@ -3511,14 +4036,29 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw) E1000_WRITE_REG(hw, E1000_STATUS, reg); } - /* - * work-around descriptor data corruption issue during nfs v2 udp + /* work-around descriptor data corruption issue during nfs v2 udp * traffic, just disable the nfs filtering capability */ reg = E1000_READ_REG(hw, E1000_RFCTL); reg |= (E1000_RFCTL_NFSW_DIS | E1000_RFCTL_NFSR_DIS); + /* Disable IPv6 extension header parsing because some malformed + * IPv6 headers can hang the Rx. + */ + if (hw->mac.type == e1000_ich8lan) + reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS); E1000_WRITE_REG(hw, E1000_RFCTL, reg); + /* Enable ECC on Lynxpoint */ + if (hw->mac.type == e1000_pch_lpt) { + reg = E1000_READ_REG(hw, E1000_PBECCSTS); + reg |= E1000_PBECCSTS_ECC_ENABLE; + E1000_WRITE_REG(hw, E1000_PBECCSTS, reg); + + reg = E1000_READ_REG(hw, E1000_CTRL); + reg |= E1000_CTRL_MEHE; + E1000_WRITE_REG(hw, E1000_CTRL, reg); + } + return; } @@ -3534,23 +4074,21 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw) **/ static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw) { - s32 ret_val = E1000_SUCCESS; + s32 ret_val; DEBUGFUNC("e1000_setup_link_ich8lan"); if (hw->phy.ops.check_reset_block(hw)) - goto out; + return E1000_SUCCESS; - /* - * ICH parts do not have a word in the NVM to determine + /* ICH parts do not have a word in the NVM to determine * the default flow control setting, so we explicitly * set it to full. */ if (hw->fc.requested_mode == e1000_fc_default) hw->fc.requested_mode = e1000_fc_full; - /* - * Save off the requested flow control mode for use later. Depending + /* Save off the requested flow control mode for use later. Depending * on the link partner's capabilities, we may or may not use this mode. */ hw->fc.current_mode = hw->fc.requested_mode; @@ -3561,11 +4099,12 @@ static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw) /* Continue to configure the copper link. */ ret_val = hw->mac.ops.setup_physical_interface(hw); if (ret_val) - goto out; + return ret_val; E1000_WRITE_REG(hw, E1000_FCTTV, hw->fc.pause_time); if ((hw->phy.type == e1000_phy_82578) || (hw->phy.type == e1000_phy_82579) || + (hw->phy.type == e1000_phy_i217) || (hw->phy.type == e1000_phy_82577)) { E1000_WRITE_REG(hw, E1000_FCRTV_PCH, hw->fc.refresh_time); @@ -3573,13 +4112,10 @@ static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw) PHY_REG(BM_PORT_CTRL_PAGE, 27), hw->fc.pause_time); if (ret_val) - goto out; + return ret_val; } - ret_val = e1000_set_fc_watermarks_generic(hw); - -out: - return ret_val; + return e1000_set_fc_watermarks_generic(hw); } /** @@ -3603,50 +4139,49 @@ static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw) ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); E1000_WRITE_REG(hw, E1000_CTRL, ctrl); - /* - * Set the mac to wait the maximum time between each iteration + /* Set the mac to wait the maximum time between each iteration * and increase the max iterations when polling the phy; * this fixes erroneous timeouts at 10Mbps. */ ret_val = e1000_write_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_TIMEOUTS, 0xFFFF); if (ret_val) - goto out; + return ret_val; ret_val = e1000_read_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, ®_data); if (ret_val) - goto out; + return ret_val; reg_data |= 0x3F; ret_val = e1000_write_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, reg_data); if (ret_val) - goto out; + return ret_val; switch (hw->phy.type) { case e1000_phy_igp_3: ret_val = e1000_copper_link_setup_igp(hw); if (ret_val) - goto out; + return ret_val; break; case e1000_phy_bm: case e1000_phy_82578: ret_val = e1000_copper_link_setup_m88(hw); if (ret_val) - goto out; + return ret_val; break; case e1000_phy_82577: case e1000_phy_82579: ret_val = e1000_copper_link_setup_82577(hw); if (ret_val) - goto out; + return ret_val; break; case e1000_phy_ife: ret_val = hw->phy.ops.read_reg(hw, IFE_PHY_MDIX_CONTROL, ®_data); if (ret_val) - goto out; + return ret_val; reg_data &= ~IFE_PMC_AUTO_MDIX; @@ -3665,15 +4200,40 @@ static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw) ret_val = hw->phy.ops.write_reg(hw, IFE_PHY_MDIX_CONTROL, reg_data); if (ret_val) - goto out; + return ret_val; break; default: break; } - ret_val = e1000_setup_copper_link_generic(hw); -out: - return ret_val; + return e1000_setup_copper_link_generic(hw); +} + +/** + * e1000_setup_copper_link_pch_lpt - Configure MAC/PHY interface + * @hw: pointer to the HW structure + * + * Calls the PHY specific link setup function and then calls the + * generic setup_copper_link to finish configuring the link for + * Lynxpoint PCH devices + **/ +static s32 e1000_setup_copper_link_pch_lpt(struct e1000_hw *hw) +{ + u32 ctrl; + s32 ret_val; + + DEBUGFUNC("e1000_setup_copper_link_pch_lpt"); + + ctrl = E1000_READ_REG(hw, E1000_CTRL); + ctrl |= E1000_CTRL_SLU; + ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); + E1000_WRITE_REG(hw, E1000_CTRL, ctrl); + + ret_val = e1000_copper_link_setup_82577(hw); + if (ret_val) + return ret_val; + + return e1000_setup_copper_link_generic(hw); } /** @@ -3695,7 +4255,7 @@ static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed, ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed, duplex); if (ret_val) - goto out; + return ret_val; if ((hw->mac.type == e1000_ich8lan) && (hw->phy.type == e1000_phy_igp_3) && @@ -3703,7 +4263,6 @@ static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed, ret_val = e1000_kmrn_lock_loss_workaround_ich8lan(hw); } -out: return ret_val; } @@ -3726,41 +4285,36 @@ static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw) { struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; u32 phy_ctrl; - s32 ret_val = E1000_SUCCESS; + s32 ret_val; u16 i, data; bool link; DEBUGFUNC("e1000_kmrn_lock_loss_workaround_ich8lan"); if (!dev_spec->kmrn_lock_loss_workaround_enabled) - goto out; + return E1000_SUCCESS; - /* - * Make sure link is up before proceeding. If not just return. + /* Make sure link is up before proceeding. If not just return. * Attempting this while link is negotiating fouled up link * stability */ ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); - if (!link) { - ret_val = E1000_SUCCESS; - goto out; - } + if (!link) + return E1000_SUCCESS; for (i = 0; i < 10; i++) { /* read once to clear */ ret_val = hw->phy.ops.read_reg(hw, IGP3_KMRN_DIAG, &data); if (ret_val) - goto out; + return ret_val; /* and again to get new status */ ret_val = hw->phy.ops.read_reg(hw, IGP3_KMRN_DIAG, &data); if (ret_val) - goto out; + return ret_val; /* check for PCS lock */ - if (!(data & IGP3_KMRN_DIAG_PCS_LOCK_LOSS)) { - ret_val = E1000_SUCCESS; - goto out; - } + if (!(data & IGP3_KMRN_DIAG_PCS_LOCK_LOSS)) + return E1000_SUCCESS; /* Issue PHY reset */ hw->phy.ops.reset(hw); @@ -3772,17 +4326,13 @@ static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw) E1000_PHY_CTRL_NOND0A_GBE_DISABLE); E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl); - /* - * Call gig speed drop workaround on Gig disable before accessing + /* Call gig speed drop workaround on Gig disable before accessing * any PHY registers */ e1000_gig_downshift_workaround_ich8lan(hw); /* unable to acquire PCS lock */ - ret_val = -E1000_ERR_PHY; - -out: - return ret_val; + return -E1000_ERR_PHY; } /** @@ -3829,7 +4379,7 @@ void e1000_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw) DEBUGFUNC("e1000_igp3_phy_powerdown_workaround_ich8lan"); if (hw->phy.type != e1000_phy_igp_3) - goto out; + return; /* Try the workaround twice (if needed) */ do { @@ -3839,8 +4389,7 @@ void e1000_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw) E1000_PHY_CTRL_NOND0A_GBE_DISABLE); E1000_WRITE_REG(hw, E1000_PHY_CTRL, reg); - /* - * Call gig speed drop workaround on Gig disable before + /* Call gig speed drop workaround on Gig disable before * accessing any PHY registers */ if (hw->mac.type == e1000_ich8lan) @@ -3863,9 +4412,6 @@ void e1000_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw) E1000_WRITE_REG(hw, E1000_CTRL, reg | E1000_CTRL_PHY_RST); retry++; } while (retry); - -out: - return; } /** @@ -3880,31 +4426,28 @@ out: **/ void e1000_gig_downshift_workaround_ich8lan(struct e1000_hw *hw) { - s32 ret_val = E1000_SUCCESS; + s32 ret_val; u16 reg_data; DEBUGFUNC("e1000_gig_downshift_workaround_ich8lan"); if ((hw->mac.type != e1000_ich8lan) || (hw->phy.type == e1000_phy_ife)) - goto out; + return; ret_val = e1000_read_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET, ®_data); if (ret_val) - goto out; + return; reg_data |= E1000_KMRNCTRLSTA_DIAG_NELPBK; ret_val = e1000_write_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET, reg_data); if (ret_val) - goto out; + return; reg_data &= ~E1000_KMRNCTRLSTA_DIAG_NELPBK; - ret_val = e1000_write_kmrn_reg_generic(hw, - E1000_KMRNCTRLSTA_DIAG_OFFSET, - reg_data); -out: - return; + e1000_write_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET, + reg_data); } /** @@ -3917,9 +4460,13 @@ out: * the LPLU setting in the NVM or custom setting. For PCH and newer parts, * the OEM bits PHY register (LED, GbE disable and LPLU configurations) also * needs to be written. + * Parts that support (and are linked to a partner which support) EEE in + * 100Mbps should disable LPLU since 100Mbps w/ EEE requires less power + * than 10Mbps w/o EEE. **/ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw) { + struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; u32 phy_ctrl; s32 ret_val; @@ -3927,13 +4474,96 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw) phy_ctrl = E1000_READ_REG(hw, E1000_PHY_CTRL); phy_ctrl |= E1000_PHY_CTRL_GBE_DISABLE; + + if (hw->phy.type == e1000_phy_i217) { + u16 phy_reg, device_id = hw->device_id; + + if ((device_id == E1000_DEV_ID_PCH_LPTLP_I218_LM) || + (device_id == E1000_DEV_ID_PCH_LPTLP_I218_V)) { + u32 fextnvm6 = E1000_READ_REG(hw, E1000_FEXTNVM6); + + E1000_WRITE_REG(hw, E1000_FEXTNVM6, + fextnvm6 & ~E1000_FEXTNVM6_REQ_PLL_CLK); + } + + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + goto out; + + if (!dev_spec->eee_disable) { + u16 eee_advert; + + ret_val = + e1000_read_emi_reg_locked(hw, + I217_EEE_ADVERTISEMENT, + &eee_advert); + if (ret_val) + goto release; + + /* Disable LPLU if both link partners support 100BaseT + * EEE and 100Full is advertised on both ends of the + * link. + */ + if ((eee_advert & I82579_EEE_100_SUPPORTED) && + (dev_spec->eee_lp_ability & + I82579_EEE_100_SUPPORTED) && + (hw->phy.autoneg_advertised & ADVERTISE_100_FULL)) + phy_ctrl &= ~(E1000_PHY_CTRL_D0A_LPLU | + E1000_PHY_CTRL_NOND0A_LPLU); + } + + /* For i217 Intel Rapid Start Technology support, + * when the system is going into Sx and no manageability engine + * is present, the driver must configure proxy to reset only on + * power good. LPI (Low Power Idle) state must also reset only + * on power good, as well as the MTA (Multicast table array). + * The SMBus release must also be disabled on LCD reset. + */ + if (!(E1000_READ_REG(hw, E1000_FWSM) & + E1000_ICH_FWSM_FW_VALID)) { + /* Enable proxy to reset only on power good. */ + hw->phy.ops.read_reg_locked(hw, I217_PROXY_CTRL, + &phy_reg); + phy_reg |= I217_PROXY_CTRL_AUTO_DISABLE; + hw->phy.ops.write_reg_locked(hw, I217_PROXY_CTRL, + phy_reg); + + /* Set bit enable LPI (EEE) to reset only on + * power good. + */ + hw->phy.ops.read_reg_locked(hw, I217_SxCTRL, &phy_reg); + phy_reg |= I217_SxCTRL_ENABLE_LPI_RESET; + hw->phy.ops.write_reg_locked(hw, I217_SxCTRL, phy_reg); + + /* Disable the SMB release on LCD reset. */ + hw->phy.ops.read_reg_locked(hw, I217_MEMPWR, &phy_reg); + phy_reg &= ~I217_MEMPWR_DISABLE_SMB_RELEASE; + hw->phy.ops.write_reg_locked(hw, I217_MEMPWR, phy_reg); + } + + /* Enable MTA to reset for Intel Rapid Start Technology + * Support + */ + hw->phy.ops.read_reg_locked(hw, I217_CGFREG, &phy_reg); + phy_reg |= I217_CGFREG_ENABLE_MTA_RESET; + hw->phy.ops.write_reg_locked(hw, I217_CGFREG, phy_reg); + +release: + hw->phy.ops.release(hw); + } +out: E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl); + if (hw->mac.type == e1000_ich8lan) e1000_gig_downshift_workaround_ich8lan(hw); if (hw->mac.type >= e1000_pchlan) { e1000_oem_bits_config_ich8lan(hw, FALSE); - e1000_phy_hw_reset_ich8lan(hw); + + /* Reset PHY to activate OEM bits on 82577/8 */ + if (hw->mac.type == e1000_pchlan) + e1000_phy_hw_reset_generic(hw); + ret_val = hw->phy.ops.acquire(hw); if (ret_val) return; @@ -3952,48 +4582,64 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw) * on which PHY resets are not blocked, if the PHY registers cannot be * accessed properly by the s/w toggle the LANPHYPC value to power cycle * the PHY. + * On i217, setup Intel Rapid Start Technology. **/ void e1000_resume_workarounds_pchlan(struct e1000_hw *hw) { - u16 phy_id1, phy_id2; s32 ret_val; DEBUGFUNC("e1000_resume_workarounds_pchlan"); - if ((hw->mac.type != e1000_pch2lan) || - hw->phy.ops.check_reset_block(hw)) + if (hw->mac.type < e1000_pch2lan) return; - ret_val = hw->phy.ops.acquire(hw); + ret_val = e1000_init_phy_workarounds_pchlan(hw); if (ret_val) { - DEBUGOUT("Failed to acquire PHY semaphore in resume\n"); + DEBUGOUT1("Failed to init PHY flow ret_val=%d\n", ret_val); return; } - /* Test access to the PHY registers by reading the ID regs */ - ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID1, &phy_id1); - if (ret_val) - goto release; - ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID2, &phy_id2); - if (ret_val) - goto release; + /* For i217 Intel Rapid Start Technology support when the system + * is transitioning from Sx and no manageability engine is present + * configure SMBus to restore on reset, disable proxy, and enable + * the reset on MTA (Multicast table array). + */ + if (hw->phy.type == e1000_phy_i217) { + u16 phy_reg; - if (hw->phy.id == ((u32)(phy_id1 << 16) | - (u32)(phy_id2 & PHY_REVISION_MASK))) - goto release; + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) { + DEBUGOUT("Failed to setup iRST\n"); + return; + } - e1000_toggle_lanphypc_value_ich8lan(hw); - - hw->phy.ops.release(hw); - msec_delay(50); - hw->phy.ops.reset(hw); - msec_delay(50); - return; + if (!(E1000_READ_REG(hw, E1000_FWSM) & + E1000_ICH_FWSM_FW_VALID)) { + /* Restore clear on SMB if no manageability engine + * is present + */ + ret_val = hw->phy.ops.read_reg_locked(hw, I217_MEMPWR, + &phy_reg); + if (ret_val) + goto release; + phy_reg |= I217_MEMPWR_DISABLE_SMB_RELEASE; + hw->phy.ops.write_reg_locked(hw, I217_MEMPWR, phy_reg); + /* Disable Proxy */ + hw->phy.ops.write_reg_locked(hw, I217_PROXY_CTRL, 0); + } + /* Enable reset on MTA */ + ret_val = hw->phy.ops.read_reg_locked(hw, I217_CGFREG, + &phy_reg); + if (ret_val) + goto release; + phy_reg &= ~I217_CGFREG_ENABLE_MTA_RESET; + hw->phy.ops.write_reg_locked(hw, I217_CGFREG, phy_reg); release: - hw->phy.ops.release(hw); - - return; + if (ret_val) + DEBUGOUT1("Error %d in resume workarounds\n", ret_val); + hw->phy.ops.release(hw); + } } /** @@ -4091,8 +4737,7 @@ static s32 e1000_led_on_pchlan(struct e1000_hw *hw) DEBUGFUNC("e1000_led_on_pchlan"); - /* - * If no link, then turn LED on by setting the invert bit + /* If no link, then turn LED on by setting the invert bit * for each LED that's mode is "link_up" in ledctl_mode2. */ if (!(E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)) { @@ -4124,8 +4769,7 @@ static s32 e1000_led_off_pchlan(struct e1000_hw *hw) DEBUGFUNC("e1000_led_off_pchlan"); - /* - * If no link, then turn LED off by clearing the invert bit + /* If no link, then turn LED off by clearing the invert bit * for each LED that's mode is "link_up" in ledctl_mode1. */ if (!(E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)) { @@ -4172,8 +4816,7 @@ static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw) } else { ret_val = e1000_get_auto_rd_done_generic(hw); if (ret_val) { - /* - * When auto config read does not complete, do not + /* When auto config read does not complete, do not * return with an error. This can happen in situations * where there is no eeprom and prevents getting link. */ @@ -4191,7 +4834,7 @@ static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw) /* If EEPROM is not marked present, init the IGP 3 PHY manually */ if (hw->mac.type <= e1000_ich9lan) { - if (((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) == 0) && + if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) && (hw->phy.type == e1000_phy_igp_3)) { e1000_phy_init_script_igp3(hw); } @@ -4256,6 +4899,7 @@ static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw) /* Clear PHY statistics registers */ if ((hw->phy.type == e1000_phy_82578) || (hw->phy.type == e1000_phy_82579) || + (hw->phy.type == e1000_phy_i217) || (hw->phy.type == e1000_phy_82577)) { ret_val = hw->phy.ops.acquire(hw); if (ret_val) diff --git a/sys/dev/e1000/e1000_ich8lan.h b/sys/dev/e1000/e1000_ich8lan.h index 2eccb30046d..bf928981709 100644 --- a/sys/dev/e1000/e1000_ich8lan.h +++ b/sys/dev/e1000/e1000_ich8lan.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2011, Intel Corporation + Copyright (c) 2001-2013, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -59,12 +59,8 @@ #define ICH_FLASH_SEG_SIZE_4K 4096 #define ICH_FLASH_SEG_SIZE_8K 8192 #define ICH_FLASH_SEG_SIZE_64K 65536 -#define ICH_FLASH_SECTOR_SIZE 4096 - -#define ICH_FLASH_REG_MAPSIZE 0x00A0 #define E1000_ICH_FWSM_RSPCIPHY 0x00000040 /* Reset PHY on PCI Reset */ -#define E1000_ICH_FWSM_DISSW 0x10000000 /* FW Disables SW Writes */ /* FW established a valid mode */ #define E1000_ICH_FWSM_FW_VALID 0x00008000 #define E1000_ICH_FWSM_PCIM2PCI 0x01000000 /* ME PCIm-to-PCI active */ @@ -72,23 +68,12 @@ #define E1000_ICH_MNG_IAMT_MODE 0x2 -#define E1000_FWSM_PROXY_MODE 0x00000008 /* FW is in proxy mode */ -#define E1000_FWSM_MEMC 0x00000010 /* ME Messaging capable */ +#define E1000_FWSM_WLOCK_MAC_MASK 0x0380 +#define E1000_FWSM_WLOCK_MAC_SHIFT 7 /* Shared Receive Address Registers */ -#define E1000_SHRAL(_i) (0x05438 + ((_i) * 8)) -#define E1000_SHRAH(_i) (0x0543C + ((_i) * 8)) -#define E1000_SHRAH_AV 0x80000000 /* Addr Valid bit */ -#define E1000_SHRAH_MAV 0x40000000 /* Multicast Addr Valid bit */ - -#define E1000_H2ME 0x05B50 /* Host to ME */ -#define E1000_H2ME_LSECREQ 0x00000001 /* Linksec Request */ -#define E1000_H2ME_LSECA 0x00000002 /* Linksec Active */ -#define E1000_H2ME_LSECSF 0x00000004 /* Linksec Failed */ -#define E1000_H2ME_LSECD 0x00000008 /* Linksec Disabled */ -#define E1000_H2ME_SLCAPD 0x00000010 /* Start LCAPD */ -#define E1000_H2ME_IPV4_ARP_EN 0x00000020 /* Arp Offload enable bit */ -#define E1000_H2ME_IPV6_NS_EN 0x00000040 /* NS Offload enable bit */ +#define E1000_SHRAL_PCH_LPT(_i) (0x05408 + ((_i) * 8)) +#define E1000_SHRAH_PCH_LPT(_i) (0x0540C + ((_i) * 8)) #define ID_LED_DEFAULT_ICH8LAN ((ID_LED_DEF1_DEF2 << 12) | \ (ID_LED_OFF1_OFF2 << 8) | \ @@ -105,27 +90,30 @@ #define E1000_FEXTNVM_SW_CONFIG 1 #define E1000_FEXTNVM_SW_CONFIG_ICH8M (1 << 27) /* Bit redefined for ICH8M */ +#define E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK 0x0C000000 +#define E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC 0x08000000 + #define E1000_FEXTNVM4_BEACON_DURATION_MASK 0x7 #define E1000_FEXTNVM4_BEACON_DURATION_8USEC 0x7 #define E1000_FEXTNVM4_BEACON_DURATION_16USEC 0x3 +#define E1000_FEXTNVM6_REQ_PLL_CLK 0x00000100 + #define PCIE_ICH8_SNOOP_ALL PCIE_NO_SNOOP_ALL #define E1000_ICH_RAR_ENTRIES 7 #define E1000_PCH2_RAR_ENTRIES 5 /* RAR[0], SHRA[0-3] */ +#define E1000_PCH_LPT_RAR_ENTRIES 12 /* RAR[0], SHRA[0-10] */ #define PHY_PAGE_SHIFT 5 #define PHY_REG(page, reg) (((page) << PHY_PAGE_SHIFT) | \ ((reg) & MAX_PHY_REG_ADDRESS)) #define IGP3_KMRN_DIAG PHY_REG(770, 19) /* KMRN Diagnostic */ #define IGP3_VR_CTRL PHY_REG(776, 18) /* Voltage Regulator Control */ -#define IGP3_CAPABILITY PHY_REG(776, 19) /* Capability */ -#define IGP3_PM_CTRL PHY_REG(769, 20) /* Power Management Control */ #define IGP3_KMRN_DIAG_PCS_LOCK_LOSS 0x0002 #define IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK 0x0300 #define IGP3_VR_CTRL_MODE_SHUTDOWN 0x0200 -#define IGP3_PM_CTRL_FORCE_PWR_DOWN 0x0020 /* PHY Wakeup Registers and defines */ #define BM_PORT_GEN_CFG PHY_REG(BM_PORT_CTRL_PAGE, 17) @@ -138,14 +126,6 @@ #define BM_RAR_H(_i) (BM_PHY_REG(BM_WUC_PAGE, 18 + ((_i) << 2))) #define BM_RAR_CTRL(_i) (BM_PHY_REG(BM_WUC_PAGE, 19 + ((_i) << 2))) #define BM_MTA(_i) (BM_PHY_REG(BM_WUC_PAGE, 128 + ((_i) << 1))) -#define BM_IPAV (BM_PHY_REG(BM_WUC_PAGE, 64)) -#define BM_IP4AT_L(_i) (BM_PHY_REG(BM_WUC_PAGE, 82 + ((_i) * 2))) -#define BM_IP4AT_H(_i) (BM_PHY_REG(BM_WUC_PAGE, 83 + ((_i) * 2))) - -#define BM_SHRAL_LOWER(_i) (BM_PHY_REG(BM_WUC_PAGE, 44 + ((_i) * 4))) -#define BM_SHRAL_UPPER(_i) (BM_PHY_REG(BM_WUC_PAGE, 45 + ((_i) * 4))) -#define BM_SHRAH_LOWER(_i) (BM_PHY_REG(BM_WUC_PAGE, 46 + ((_i) * 4))) -#define BM_SHRAH_UPPER(_i) (BM_PHY_REG(BM_WUC_PAGE, 47 + ((_i) * 4))) #define BM_RCTL_UPE 0x0001 /* Unicast Promiscuous Mode */ #define BM_RCTL_MPE 0x0002 /* Multicast Promiscuous Mode */ @@ -177,28 +157,28 @@ #define E1000_FCRTV_PCH 0x05F40 /* PCH Flow Control Refresh Timer Value */ -/* - * For ICH, the name used for NVM word 17h is LED1 Config. - * For PCH, the word was re-named to OEM Config. - */ -#define E1000_NVM_LED1_CONFIG 0x17 /* NVM LED1/LPLU Config Word */ -#define E1000_NVM_LED1_CONFIG_LPLU_NONDOA 0x0400 /* NVM LPLU in non-D0a Bit */ -#define E1000_NVM_OEM_CONFIG E1000_NVM_LED1_CONFIG -#define E1000_NVM_OEM_CONFIG_LPLU_NONDOA E1000_NVM_LED1_CONFIG_LPLU_NONDOA - #define E1000_NVM_K1_CONFIG 0x1B /* NVM K1 Config Word */ #define E1000_NVM_K1_ENABLE 0x1 /* NVM Enable K1 bit */ +/* SMBus Control Phy Register */ +#define CV_SMB_CTRL PHY_REG(769, 23) +#define CV_SMB_CTRL_FORCE_SMBUS 0x0001 + /* SMBus Address Phy Register */ #define HV_SMB_ADDR PHY_REG(768, 26) #define HV_SMB_ADDR_MASK 0x007F #define HV_SMB_ADDR_PEC_EN 0x0200 #define HV_SMB_ADDR_VALID 0x0080 +#define HV_SMB_ADDR_FREQ_MASK 0x1100 +#define HV_SMB_ADDR_FREQ_LOW_SHIFT 8 +#define HV_SMB_ADDR_FREQ_HIGH_SHIFT 12 /* Strapping Option Register - RO */ #define E1000_STRAP 0x0000C #define E1000_STRAP_SMBUS_ADDRESS_MASK 0x00FE0000 #define E1000_STRAP_SMBUS_ADDRESS_SHIFT 17 +#define E1000_STRAP_SMT_FREQ_MASK 0x00003000 +#define E1000_STRAP_SMT_FREQ_SHIFT 12 /* OEM Bits Phy Register */ #define HV_OEM_BITS PHY_REG(768, 25) @@ -206,8 +186,6 @@ #define HV_OEM_BITS_GBE_DIS 0x0040 /* Gigabit Disable */ #define HV_OEM_BITS_RESTART_AN 0x0400 /* Restart Auto-negotiation */ -#define LCD_CFG_PHY_ADDR_BIT 0x0020 /* Phy addr bit from LCD Config word */ - /* KMRN Mode Control */ #define HV_KMRN_MODE_CTRL PHY_REG(769, 16) #define HV_KMRN_MDIO_SLOW 0x0400 @@ -219,47 +197,73 @@ /* PHY Power Management Control */ #define HV_PM_CTRL PHY_REG(770, 17) +#define HV_PM_CTRL_PLL_STOP_IN_K1_GIGA 0x100 #define SW_FLAG_TIMEOUT 1000 /* SW Semaphore flag timeout in ms */ /* PHY Low Power Idle Control */ #define I82579_LPI_CTRL PHY_REG(772, 20) +#define I82579_LPI_CTRL_100_ENABLE 0x2000 +#define I82579_LPI_CTRL_1000_ENABLE 0x4000 #define I82579_LPI_CTRL_ENABLE_MASK 0x6000 #define I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT 0x80 -/* EMI Registers */ +/* Extended Management Interface (EMI) Registers */ #define I82579_EMI_ADDR 0x10 #define I82579_EMI_DATA 0x11 #define I82579_LPI_UPDATE_TIMER 0x4805 /* in 40ns units + 40 ns base value */ -#define I82579_MSE_THRESHOLD 0x084F /* Mean Square Error Threshold */ +#define I82579_MSE_THRESHOLD 0x084F /* 82579 Mean Square Error Threshold */ +#define I82577_MSE_THRESHOLD 0x0887 /* 82577 Mean Square Error Threshold */ #define I82579_MSE_LINK_DOWN 0x2411 /* MSE count before dropping link */ +#define I82579_RX_CONFIG 0x3412 /* Receive configuration */ +#define I82579_EEE_PCS_STATUS 0x182D /* IEEE MMD Register 3.1 >> 8 */ +#define I82579_EEE_CAPABILITY 0x0410 /* IEEE MMD Register 3.20 */ +#define I82579_EEE_ADVERTISEMENT 0x040E /* IEEE MMD Register 7.60 */ +#define I82579_EEE_LP_ABILITY 0x040F /* IEEE MMD Register 7.61 */ +#define I82579_EEE_100_SUPPORTED (1 << 1) /* 100BaseTx EEE supported */ +#define I82579_EEE_1000_SUPPORTED (1 << 2) /* 1000BaseTx EEE supported */ +#define I217_EEE_PCS_STATUS 0x9401 /* IEEE MMD Register 3.1 */ +#define I217_EEE_CAPABILITY 0x8000 /* IEEE MMD Register 3.20 */ +#define I217_EEE_ADVERTISEMENT 0x8001 /* IEEE MMD Register 7.60 */ +#define I217_EEE_LP_ABILITY 0x8002 /* IEEE MMD Register 7.61 */ -/* - * Additional interrupts need to be handled for ICH family: - * DSW = The FW changed the status of the DISSW bit in FWSM - * PHYINT = The LAN connected device generates an interrupt - * EPRST = Manageability reset event - */ -#define IMS_ICH_ENABLE_MASK (\ - E1000_IMS_DSW | \ - E1000_IMS_PHYINT | \ - E1000_IMS_EPRST) +#define E1000_EEE_RX_LPI_RCVD 0x0400 /* Tx LP idle received */ +#define E1000_EEE_TX_LPI_RCVD 0x0800 /* Rx LP idle received */ -/* Additional interrupt register bit definitions */ -#define E1000_ICR_LSECPNC 0x00004000 /* PN threshold - client */ -#define E1000_IMS_LSECPNC E1000_ICR_LSECPNC /* PN threshold - client */ -#define E1000_ICS_LSECPNC E1000_ICR_LSECPNC /* PN threshold - client */ - -/* Security Processing bit Indication */ -#define E1000_RXDEXT_LINKSEC_STATUS_LSECH 0x01000000 -#define E1000_RXDEXT_LINKSEC_ERROR_BIT_MASK 0x60000000 -#define E1000_RXDEXT_LINKSEC_ERROR_NO_SA_MATCH 0x20000000 -#define E1000_RXDEXT_LINKSEC_ERROR_REPLAY_ERROR 0x40000000 -#define E1000_RXDEXT_LINKSEC_ERROR_BAD_SIG 0x60000000 +/* Intel Rapid Start Technology Support */ +#define I217_PROXY_CTRL BM_PHY_REG(BM_WUC_PAGE, 70) +#define I217_PROXY_CTRL_AUTO_DISABLE 0x0080 +#define I217_SxCTRL PHY_REG(BM_PORT_CTRL_PAGE, 28) +#define I217_SxCTRL_ENABLE_LPI_RESET 0x1000 +#define I217_CGFREG PHY_REG(772, 29) +#define I217_CGFREG_ENABLE_MTA_RESET 0x0002 +#define I217_MEMPWR PHY_REG(772, 26) +#define I217_MEMPWR_DISABLE_SMB_RELEASE 0x0010 /* Receive Address Initial CRC Calculation */ #define E1000_PCH_RAICC(_n) (0x05F50 + ((_n) * 4)) +/* Latency Tolerance Reporting */ +#define E1000_LTRV 0x000F8 +#define E1000_LTRV_VALUE_MASK 0x000003FF +#define E1000_LTRV_SCALE_MAX 5 +#define E1000_LTRV_SCALE_FACTOR 5 +#define E1000_LTRV_SCALE_SHIFT 10 +#define E1000_LTRV_SCALE_MASK 0x00001C00 +#define E1000_LTRV_REQ_SHIFT 15 +#define E1000_LTRV_NOSNOOP_SHIFT 16 +#define E1000_LTRV_SEND (1 << 30) + +/* Proprietary Latency Tolerance Reporting PCI Capability */ +#define E1000_PCI_LTR_CAP_LPT 0xA8 + +/* OBFF Control & Threshold Defines */ +#define E1000_SVCR_OFF_EN 0x00000001 +#define E1000_SVCR_OFF_MASKINT 0x00001000 +#define E1000_SVCR_OFF_TIMER_MASK 0xFFFF0000 +#define E1000_SVCR_OFF_TIMER_SHIFT 16 +#define E1000_SVT_OFF_HWM_MASK 0x0000001F + void e1000_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw, bool state); void e1000_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw); @@ -269,4 +273,5 @@ void e1000_resume_workarounds_pchlan(struct e1000_hw *hw); s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable); void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw); s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable); -#endif +s32 e1000_read_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 *data); +#endif /* _E1000_ICH8LAN_H_ */ diff --git a/sys/dev/e1000/e1000_mac.c b/sys/dev/e1000/e1000_mac.c index 95d6873b13f..9e6b30c49f5 100644 --- a/sys/dev/e1000/e1000_mac.c +++ b/sys/dev/e1000/e1000_mac.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2012, Intel Corporation + Copyright (c) 2001-2013, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -70,12 +70,9 @@ void e1000_init_mac_ops_generic(struct e1000_hw *hw) mac->ops.setup_link = e1000_null_ops_generic; mac->ops.get_link_up_info = e1000_null_link_info; mac->ops.check_for_link = e1000_null_ops_generic; - mac->ops.wait_autoneg = e1000_wait_autoneg_generic; + mac->ops.set_obff_timer = e1000_null_set_obff_timer; /* Management */ mac->ops.check_mng_mode = e1000_null_mng_mode; - mac->ops.mng_host_if_write = e1000_mng_host_if_write_generic; - mac->ops.mng_write_cmd_header = e1000_mng_write_cmd_header_generic; - mac->ops.mng_enable_host_if = e1000_mng_enable_host_if_generic; /* VLAN, MC, etc. */ mac->ops.update_mc_addr_list = e1000_null_update_mc; mac->ops.clear_vfta = e1000_null_mac_generic; @@ -118,8 +115,7 @@ s32 e1000_null_link_info(struct e1000_hw *hw, u16 *s, u16 *d) * e1000_null_mng_mode - No-op function, return FALSE * @hw: pointer to the HW structure **/ -bool e1000_null_mng_mode(struct e1000_hw *hw) -{ +bool e1000_null_mng_mode(struct e1000_hw *hw) { DEBUGFUNC("e1000_null_mng_mode"); return FALSE; } @@ -154,6 +150,16 @@ void e1000_null_rar_set(struct e1000_hw *hw, u8 *h, u32 a) return; } +/** + * e1000_null_set_obff_timer - No-op function, return 0 + * @hw: pointer to the HW structure + **/ +s32 e1000_null_set_obff_timer(struct e1000_hw *hw, u32 a) +{ + DEBUGFUNC("e1000_null_set_obff_timer"); + return E1000_SUCCESS; +} + /** * e1000_get_bus_info_pci_generic - Get PCI(x) bus information * @hw: pointer to the HW structure @@ -268,8 +274,7 @@ static void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw) struct e1000_bus_info *bus = &hw->bus; u32 reg; - /* - * The status register reports the correct function number + /* The status register reports the correct function number * for the device regardless of function swap state. */ reg = E1000_READ_REG(hw, E1000_STATUS); @@ -389,7 +394,7 @@ void e1000_init_rx_addrs_generic(struct e1000_hw *hw, u16 rar_count) s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw) { u32 i; - s32 ret_val = E1000_SUCCESS; + s32 ret_val; u16 offset, nvm_alt_mac_addr_offset, nvm_data; u8 alt_mac_addr[ETH_ADDR_LEN]; @@ -403,8 +408,7 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw) if ((hw->mac.type < e1000_82571) || (hw->mac.type == e1000_82573)) return E1000_SUCCESS; - /* - * Alternate MAC address is handled by the option ROM for 82580 + /* Alternate MAC address is handled by the option ROM for 82580 * and newer. SW support not required. */ if (hw->mac.type >= e1000_82580) @@ -447,8 +451,7 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw) return E1000_SUCCESS; } - /* - * We have a valid alternate MAC address, and we want to treat it the + /* We have a valid alternate MAC address, and we want to treat it the * same as the normal permanent MAC address stored by the HW into the * RAR. Do this by mapping this address into RAR0. */ @@ -472,8 +475,7 @@ static void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index) DEBUGFUNC("e1000_rar_set_generic"); - /* - * HW expects these in little endian so we reverse the byte order + /* HW expects these in little endian so we reverse the byte order * from network order (big endian) to little endian */ rar_low = ((u32) addr[0] | ((u32) addr[1] << 8) | @@ -485,8 +487,7 @@ static void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index) if (rar_low || rar_high) rar_high |= E1000_RAH_AV; - /* - * Some bridges will combine consecutive 32-bit writes into + /* Some bridges will combine consecutive 32-bit writes into * a single burst write, which will malfunction on some parts. * The flushes avoid this. */ @@ -514,15 +515,13 @@ u32 e1000_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr) /* Register count multiplied by bits per register */ hash_mask = (hw->mac.mta_reg_count * 32) - 1; - /* - * For a mc_filter_type of 0, bit_shift is the number of left-shifts + /* For a mc_filter_type of 0, bit_shift is the number of left-shifts * where 0xFF would still fall within the hash mask. */ while (hash_mask >> bit_shift != 0xFF) bit_shift++; - /* - * The portion of the address that is used for the hash table + /* The portion of the address that is used for the hash table * is determined by the mc_filter_type setting. * The algorithm is such that there is a total of 8 bits of shifting. * The bit_shift for a mc_filter_type of 0 represents the number of @@ -707,8 +706,7 @@ s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw) DEBUGFUNC("e1000_check_for_copper_link"); - /* - * We only want to go out to the PHY registers to see if Auto-Neg + /* We only want to go out to the PHY registers to see if Auto-Neg * has completed and/or if our link status has changed. The * get_link_status flag is set upon receiving a Link Status * Change or Rx Sequence Error interrupt. @@ -716,8 +714,7 @@ s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw) if (!mac->get_link_status) return E1000_SUCCESS; - /* - * First we want to see if the MII Status Register reports + /* First we want to see if the MII Status Register reports * link. If so, then we want to get the current speed/duplex * of the PHY. */ @@ -730,28 +727,24 @@ s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw) mac->get_link_status = FALSE; - /* - * Check if there was DownShift, must be checked + /* Check if there was DownShift, must be checked * immediately after link-up */ e1000_check_downshift_generic(hw); - /* - * If we are forcing speed/duplex, then we simply return since + /* If we are forcing speed/duplex, then we simply return since * we have already determined whether we have link or not. */ if (!mac->autoneg) return -E1000_ERR_CONFIG; - /* - * Auto-Neg is enabled. Auto Speed Detection takes care + /* Auto-Neg is enabled. Auto Speed Detection takes care * of MAC speed/duplex configuration. So we only need to * configure Collision Distance in the MAC. */ mac->ops.config_collision_dist(hw); - /* - * Configure Flow Control now that Auto-Neg has completed. + /* Configure Flow Control now that Auto-Neg has completed. * First, we need to restore the desired flow control * settings because we may have had to re-autoneg with a * different link partner. @@ -784,8 +777,7 @@ s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw) status = E1000_READ_REG(hw, E1000_STATUS); rxcw = E1000_READ_REG(hw, E1000_RXCW); - /* - * If we don't have link (auto-negotiation failed or link partner + /* If we don't have link (auto-negotiation failed or link partner * cannot auto-negotiate), the cable is plugged in (we have signal), * and our link partner is not trying to auto-negotiate with us (we * are receiving idles or data), we need to force link up. We also @@ -816,8 +808,7 @@ s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw) return ret_val; } } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { - /* - * If we are forcing link and we are receiving /C/ ordered + /* If we are forcing link and we are receiving /C/ ordered * sets, re-enable auto-negotiation in the TXCW register * and disable forced link in the Device Control register * in an attempt to auto-negotiate with our link partner. @@ -853,8 +844,7 @@ s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw) status = E1000_READ_REG(hw, E1000_STATUS); rxcw = E1000_READ_REG(hw, E1000_RXCW); - /* - * If we don't have link (auto-negotiation failed or link partner + /* If we don't have link (auto-negotiation failed or link partner * cannot auto-negotiate), and our link partner is not trying to * auto-negotiate with us (we are receiving idles or data), * we need to force link up. We also need to give auto-negotiation @@ -883,8 +873,7 @@ s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw) return ret_val; } } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { - /* - * If we are forcing link and we are receiving /C/ ordered + /* If we are forcing link and we are receiving /C/ ordered * sets, re-enable auto-negotiation in the TXCW register * and disable forced link in the Device Control register * in an attempt to auto-negotiate with our link partner. @@ -895,8 +884,7 @@ s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw) mac->serdes_has_link = TRUE; } else if (!(E1000_TXCW_ANE & E1000_READ_REG(hw, E1000_TXCW))) { - /* - * If we force link for non-auto-negotiation switch, check + /* If we force link for non-auto-negotiation switch, check * link status based on MAC synchronization for internal * serdes media type. */ @@ -955,8 +943,7 @@ s32 e1000_set_default_fc_generic(struct e1000_hw *hw) DEBUGFUNC("e1000_set_default_fc_generic"); - /* - * Read and store word 0x0F of the EEPROM. This word contains bits + /* Read and store word 0x0F of the EEPROM. This word contains bits * that determine the hardware's default PAUSE (flow control) mode, * a bit that determines whether the HW defaults to enabling or * disabling auto-negotiation, and the direction of the @@ -998,15 +985,13 @@ s32 e1000_setup_link_generic(struct e1000_hw *hw) DEBUGFUNC("e1000_setup_link_generic"); - /* - * In the case of the phy reset being blocked, we already have a link. + /* In the case of the phy reset being blocked, we already have a link. * We do not need to set it up again. */ if (hw->phy.ops.check_reset_block && hw->phy.ops.check_reset_block(hw)) return E1000_SUCCESS; - /* - * If requested flow control is set to default, set flow control + /* If requested flow control is set to default, set flow control * based on the EEPROM flow control settings. */ if (hw->fc.requested_mode == e1000_fc_default) { @@ -1015,8 +1000,7 @@ s32 e1000_setup_link_generic(struct e1000_hw *hw) return ret_val; } - /* - * Save off the requested flow control mode for use later. Depending + /* Save off the requested flow control mode for use later. Depending * on the link partner's capabilities, we may or may not use this mode. */ hw->fc.current_mode = hw->fc.requested_mode; @@ -1029,8 +1013,7 @@ s32 e1000_setup_link_generic(struct e1000_hw *hw) if (ret_val) return ret_val; - /* - * Initialize the flow control address, type, and PAUSE timer + /* Initialize the flow control address, type, and PAUSE timer * registers to their default values. This is done even if flow * control is disabled, because it does not hurt anything to * initialize these registers. @@ -1059,8 +1042,7 @@ s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw) DEBUGFUNC("e1000_commit_fc_settings_generic"); - /* - * Check for a software override of the flow control settings, and + /* Check for a software override of the flow control settings, and * setup the device accordingly. If auto-negotiation is enabled, then * software will have to set the "PAUSE" bits to the correct value in * the Transmit Config Word Register (TXCW) and re-start auto- @@ -1082,8 +1064,7 @@ s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw) txcw = (E1000_TXCW_ANE | E1000_TXCW_FD); break; case e1000_fc_rx_pause: - /* - * Rx Flow control is enabled and Tx Flow control is disabled + /* Rx Flow control is enabled and Tx Flow control is disabled * by a software over-ride. Since there really isn't a way to * advertise that we are capable of Rx Pause ONLY, we will * advertise that we support both symmetric and asymmetric Rx @@ -1093,15 +1074,13 @@ s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw) txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); break; case e1000_fc_tx_pause: - /* - * Tx Flow control is enabled, and Rx Flow control is disabled, + /* Tx Flow control is enabled, and Rx Flow control is disabled, * by a software over-ride. */ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR); break; case e1000_fc_full: - /* - * Flow control (both Rx and Tx) is enabled by a software + /* Flow control (both Rx and Tx) is enabled by a software * over-ride. */ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); @@ -1133,8 +1112,7 @@ s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw) DEBUGFUNC("e1000_poll_fiber_serdes_link_generic"); - /* - * If we have a signal (the cable is plugged in, or assumed TRUE for + /* If we have a signal (the cable is plugged in, or assumed TRUE for * serdes media) then poll for a "Link-Up" indication in the Device * Status Register. Time-out if a link isn't seen in 500 milliseconds * seconds (Auto-negotiation should complete in less than 500 @@ -1149,8 +1127,7 @@ s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw) if (i == FIBER_LINK_UP_LIMIT) { DEBUGOUT("Never got a valid link from auto-neg!!!\n"); mac->autoneg_failed = TRUE; - /* - * AutoNeg failed to achieve a link, so we'll call + /* AutoNeg failed to achieve a link, so we'll call * mac->check_for_link. This routine will force the * link up if we detect a signal. This will allow us to * communicate with non-autonegotiating link partners. @@ -1194,8 +1171,7 @@ s32 e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw) if (ret_val) return ret_val; - /* - * Since auto-negotiation is enabled, take the link out of reset (the + /* Since auto-negotiation is enabled, take the link out of reset (the * link will be in reset, because we previously reset the chip). This * will restart auto-negotiation. If auto-negotiation is successful * then the link-up status bit will be set and the flow control enable @@ -1207,8 +1183,7 @@ s32 e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw) E1000_WRITE_FLUSH(hw); msec_delay(1); - /* - * For these adapters, the SW definable pin 1 is set when the optics + /* For these adapters, the SW definable pin 1 is set when the optics * detect a signal. If we have a signal, then poll for a "Link-Up" * indication. */ @@ -1258,16 +1233,14 @@ s32 e1000_set_fc_watermarks_generic(struct e1000_hw *hw) DEBUGFUNC("e1000_set_fc_watermarks_generic"); - /* - * Set the flow control receive threshold registers. Normally, + /* Set the flow control receive threshold registers. Normally, * these registers will be set to a default threshold that may be * adjusted later by the driver's runtime code. However, if the * ability to transmit pause frames is not enabled, then these * registers will be set to 0. */ if (hw->fc.current_mode & e1000_fc_tx_pause) { - /* - * We need to set up the Receive Threshold high and low water + /* We need to set up the Receive Threshold high and low water * marks as well as (optionally) enabling the transmission of * XON frames. */ @@ -1301,8 +1274,7 @@ s32 e1000_force_mac_fc_generic(struct e1000_hw *hw) ctrl = E1000_READ_REG(hw, E1000_CTRL); - /* - * Because we didn't get link via the internal auto-negotiation + /* Because we didn't get link via the internal auto-negotiation * mechanism (we either forced link or we got link via PHY * auto-neg), we have to manually enable/disable transmit an * receive flow control. @@ -1360,13 +1332,13 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; s32 ret_val = E1000_SUCCESS; + u32 pcs_status_reg, pcs_adv_reg, pcs_lp_ability_reg, pcs_ctrl_reg; u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg; u16 speed, duplex; DEBUGFUNC("e1000_config_fc_after_link_up_generic"); - /* - * Check for the case where we have fiber media and auto-neg failed + /* Check for the case where we have fiber media and auto-neg failed * so we had to force link. In this case, we need to force the * configuration of the MAC to match the "fc" parameter. */ @@ -1384,15 +1356,13 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) return ret_val; } - /* - * Check for the case where we have copper media and auto-neg is + /* Check for the case where we have copper media and auto-neg is * enabled. In this case, we need to check and see if Auto-Neg * has completed, and if so, how the PHY and link partner has * flow control configured. */ if ((hw->phy.media_type == e1000_media_type_copper) && mac->autoneg) { - /* - * Read the MII Status Register and check to see if AutoNeg + /* Read the MII Status Register and check to see if AutoNeg * has completed. We read this twice because this reg has * some "sticky" (latched) bits. */ @@ -1408,8 +1378,7 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) return ret_val; } - /* - * The AutoNeg process has completed, so we now need to + /* The AutoNeg process has completed, so we now need to * read both the Auto Negotiation Advertisement * Register (Address 4) and the Auto_Negotiation Base * Page Ability Register (Address 5) to determine how @@ -1424,8 +1393,7 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) if (ret_val) return ret_val; - /* - * Two bits in the Auto Negotiation Advertisement Register + /* Two bits in the Auto Negotiation Advertisement Register * (Address 4) and two bits in the Auto Negotiation Base * Page Ability Register (Address 5) determine flow control * for both the PHY and the link partner. The following @@ -1460,8 +1428,7 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) */ if ((mii_nway_adv_reg & NWAY_AR_PAUSE) && (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) { - /* - * Now we need to check if the user selected Rx ONLY + /* Now we need to check if the user selected Rx ONLY * of pause frames. In this case, we had to advertise * FULL flow control because we could not advertise Rx * ONLY. Hence, we must now check to see if we need to @@ -1475,8 +1442,7 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) DEBUGOUT("Flow Control = Rx PAUSE frames only.\n"); } } - /* - * For receiving PAUSE frames ONLY. + /* For receiving PAUSE frames ONLY. * * LOCAL DEVICE | LINK PARTNER * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result @@ -1490,8 +1456,7 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) hw->fc.current_mode = e1000_fc_tx_pause; DEBUGOUT("Flow Control = Tx PAUSE frames only.\n"); } - /* - * For transmitting PAUSE frames ONLY. + /* For transmitting PAUSE frames ONLY. * * LOCAL DEVICE | LINK PARTNER * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result @@ -1505,16 +1470,14 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) hw->fc.current_mode = e1000_fc_rx_pause; DEBUGOUT("Flow Control = Rx PAUSE frames only.\n"); } else { - /* - * Per the IEEE spec, at this point flow control + /* Per the IEEE spec, at this point flow control * should be disabled. */ hw->fc.current_mode = e1000_fc_none; DEBUGOUT("Flow Control = NONE.\n"); } - /* - * Now we need to do one last check... If we auto- + /* Now we need to do one last check... If we auto- * negotiated to HALF DUPLEX, flow control should not be * enabled per IEEE 802.3 spec. */ @@ -1527,8 +1490,7 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) if (duplex == HALF_DUPLEX) hw->fc.current_mode = e1000_fc_none; - /* - * Now we call a subroutine to actually force the MAC + /* Now we call a subroutine to actually force the MAC * controller to use the correct flow control settings. */ ret_val = e1000_force_mac_fc_generic(hw); @@ -1538,6 +1500,130 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw) } } + /* Check for the case where we have SerDes media and auto-neg is + * enabled. In this case, we need to check and see if Auto-Neg + * has completed, and if so, how the PHY and link partner has + * flow control configured. + */ + if ((hw->phy.media_type == e1000_media_type_internal_serdes) && + mac->autoneg) { + /* Read the PCS_LSTS and check to see if AutoNeg + * has completed. + */ + pcs_status_reg = E1000_READ_REG(hw, E1000_PCS_LSTAT); + + if (!(pcs_status_reg & E1000_PCS_LSTS_AN_COMPLETE)) { + DEBUGOUT("PCS Auto Neg has not completed.\n"); + return ret_val; + } + + /* The AutoNeg process has completed, so we now need to + * read both the Auto Negotiation Advertisement + * Register (PCS_ANADV) and the Auto_Negotiation Base + * Page Ability Register (PCS_LPAB) to determine how + * flow control was negotiated. + */ + pcs_adv_reg = E1000_READ_REG(hw, E1000_PCS_ANADV); + pcs_lp_ability_reg = E1000_READ_REG(hw, E1000_PCS_LPAB); + + /* Two bits in the Auto Negotiation Advertisement Register + * (PCS_ANADV) and two bits in the Auto Negotiation Base + * Page Ability Register (PCS_LPAB) determine flow control + * for both the PHY and the link partner. The following + * table, taken out of the IEEE 802.3ab/D6.0 dated March 25, + * 1999, describes these PAUSE resolution bits and how flow + * control is determined based upon these settings. + * NOTE: DC = Don't Care + * + * LOCAL DEVICE | LINK PARTNER + * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution + *-------|---------|-------|---------|-------------------- + * 0 | 0 | DC | DC | e1000_fc_none + * 0 | 1 | 0 | DC | e1000_fc_none + * 0 | 1 | 1 | 0 | e1000_fc_none + * 0 | 1 | 1 | 1 | e1000_fc_tx_pause + * 1 | 0 | 0 | DC | e1000_fc_none + * 1 | DC | 1 | DC | e1000_fc_full + * 1 | 1 | 0 | 0 | e1000_fc_none + * 1 | 1 | 0 | 1 | e1000_fc_rx_pause + * + * Are both PAUSE bits set to 1? If so, this implies + * Symmetric Flow Control is enabled at both ends. The + * ASM_DIR bits are irrelevant per the spec. + * + * For Symmetric Flow Control: + * + * LOCAL DEVICE | LINK PARTNER + * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result + *-------|---------|-------|---------|-------------------- + * 1 | DC | 1 | DC | e1000_fc_full + * + */ + if ((pcs_adv_reg & E1000_TXCW_PAUSE) && + (pcs_lp_ability_reg & E1000_TXCW_PAUSE)) { + /* Now we need to check if the user selected Rx ONLY + * of pause frames. In this case, we had to advertise + * FULL flow control because we could not advertise Rx + * ONLY. Hence, we must now check to see if we need to + * turn OFF the TRANSMISSION of PAUSE frames. + */ + if (hw->fc.requested_mode == e1000_fc_full) { + hw->fc.current_mode = e1000_fc_full; + DEBUGOUT("Flow Control = FULL.\n"); + } else { + hw->fc.current_mode = e1000_fc_rx_pause; + DEBUGOUT("Flow Control = Rx PAUSE frames only.\n"); + } + } + /* For receiving PAUSE frames ONLY. + * + * LOCAL DEVICE | LINK PARTNER + * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result + *-------|---------|-------|---------|-------------------- + * 0 | 1 | 1 | 1 | e1000_fc_tx_pause + */ + else if (!(pcs_adv_reg & E1000_TXCW_PAUSE) && + (pcs_adv_reg & E1000_TXCW_ASM_DIR) && + (pcs_lp_ability_reg & E1000_TXCW_PAUSE) && + (pcs_lp_ability_reg & E1000_TXCW_ASM_DIR)) { + hw->fc.current_mode = e1000_fc_tx_pause; + DEBUGOUT("Flow Control = Tx PAUSE frames only.\n"); + } + /* For transmitting PAUSE frames ONLY. + * + * LOCAL DEVICE | LINK PARTNER + * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result + *-------|---------|-------|---------|-------------------- + * 1 | 1 | 0 | 1 | e1000_fc_rx_pause + */ + else if ((pcs_adv_reg & E1000_TXCW_PAUSE) && + (pcs_adv_reg & E1000_TXCW_ASM_DIR) && + !(pcs_lp_ability_reg & E1000_TXCW_PAUSE) && + (pcs_lp_ability_reg & E1000_TXCW_ASM_DIR)) { + hw->fc.current_mode = e1000_fc_rx_pause; + DEBUGOUT("Flow Control = Rx PAUSE frames only.\n"); + } else { + /* Per the IEEE spec, at this point flow control + * should be disabled. + */ + hw->fc.current_mode = e1000_fc_none; + DEBUGOUT("Flow Control = NONE.\n"); + } + + /* Now we call a subroutine to actually force the MAC + * controller to use the correct flow control settings. + */ + pcs_ctrl_reg = E1000_READ_REG(hw, E1000_PCS_LCTL); + pcs_ctrl_reg |= E1000_PCS_LCTL_FORCE_FCTRL; + E1000_WRITE_REG(hw, E1000_PCS_LCTL, pcs_ctrl_reg); + + ret_val = e1000_force_mac_fc_generic(hw); + if (ret_val) { + DEBUGOUT("Error forcing flow control settings\n"); + return ret_val; + } + } + return E1000_SUCCESS; } @@ -1854,16 +1940,28 @@ s32 e1000_blink_led_generic(struct e1000_hw *hw) ledctl_blink = E1000_LEDCTL_LED0_BLINK | (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT); } else { - /* - * set the blink bit for each LED that's "on" (0x0E) - * in ledctl_mode2 + /* Set the blink bit for each LED that's "on" (0x0E) + * (or "off" if inverted) in ledctl_mode2. The blink + * logic in hardware only works when mode is set to "on" + * so it must be changed accordingly when the mode is + * "off" and inverted. */ ledctl_blink = hw->mac.ledctl_mode2; - for (i = 0; i < 4; i++) - if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) == - E1000_LEDCTL_MODE_LED_ON) - ledctl_blink |= (E1000_LEDCTL_LED0_BLINK << - (i * 8)); + for (i = 0; i < 32; i += 8) { + u32 mode = (hw->mac.ledctl_mode2 >> i) & + E1000_LEDCTL_LED0_MODE_MASK; + u32 led_default = hw->mac.ledctl_default >> i; + + if ((!(led_default & E1000_LEDCTL_LED0_IVRT) && + (mode == E1000_LEDCTL_MODE_LED_ON)) || + ((led_default & E1000_LEDCTL_LED0_IVRT) && + (mode == E1000_LEDCTL_MODE_LED_OFF))) { + ledctl_blink &= + ~(E1000_LEDCTL_LED0_MODE_MASK << i); + ledctl_blink |= (E1000_LEDCTL_LED0_BLINK | + E1000_LEDCTL_MODE_LED_ON) << i; + } + } } E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl_blink); @@ -2082,6 +2180,20 @@ static s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw) return E1000_SUCCESS; } +/** + * e1000_validate_mdi_setting_crossover_generic - Verify MDI/MDIx settings + * @hw: pointer to the HW structure + * + * Validate the MDI/MDIx setting, allowing for auto-crossover during forced + * operation. + **/ +s32 e1000_validate_mdi_setting_crossover_generic(struct e1000_hw *hw) +{ + DEBUGFUNC("e1000_validate_mdi_setting_crossover_generic"); + + return E1000_SUCCESS; +} + /** * e1000_write_8bit_ctrl_reg_generic - Write a 8bit CTRL register * @hw: pointer to the HW structure diff --git a/sys/dev/e1000/e1000_mac.h b/sys/dev/e1000/e1000_mac.h index c18a7ec1293..3e2ccdedb14 100644 --- a/sys/dev/e1000/e1000_mac.h +++ b/sys/dev/e1000/e1000_mac.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2012, Intel Corporation + Copyright (c) 2001-2013, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -35,10 +35,6 @@ #ifndef _E1000_MAC_H_ #define _E1000_MAC_H_ -/* - * Functions that should not be called directly from drivers but can be used - * by other files in this 'shared code' - */ void e1000_init_mac_ops_generic(struct e1000_hw *hw); void e1000_null_mac_generic(struct e1000_hw *hw); s32 e1000_null_ops_generic(struct e1000_hw *hw); @@ -47,6 +43,7 @@ bool e1000_null_mng_mode(struct e1000_hw *hw); void e1000_null_update_mc(struct e1000_hw *hw, u8 *h, u32 a); void e1000_null_write_vfta(struct e1000_hw *hw, u32 a, u32 b); void e1000_null_rar_set(struct e1000_hw *hw, u8 *h, u32 a); +s32 e1000_null_set_obff_timer(struct e1000_hw *hw, u32 a); s32 e1000_blink_led_generic(struct e1000_hw *hw); s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw); s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw); @@ -77,6 +74,7 @@ s32 e1000_set_fc_watermarks_generic(struct e1000_hw *hw); s32 e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw); s32 e1000_setup_led_generic(struct e1000_hw *hw); s32 e1000_setup_link_generic(struct e1000_hw *hw); +s32 e1000_validate_mdi_setting_crossover_generic(struct e1000_hw *hw); s32 e1000_write_8bit_ctrl_reg_generic(struct e1000_hw *hw, u32 reg, u32 offset, u8 data); diff --git a/sys/dev/e1000/e1000_manage.c b/sys/dev/e1000/e1000_manage.c index f11b18d20e0..c58d32d16b1 100644 --- a/sys/dev/e1000/e1000_manage.c +++ b/sys/dev/e1000/e1000_manage.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2012, Intel Corporation + Copyright (c) 2001-2013, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -145,11 +145,10 @@ bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw) return hw->mac.tx_pkt_filtering; } - /* - * If we can't read from the host interface for whatever + /* If we can't read from the host interface for whatever * reason, disable filtering. */ - ret_val = hw->mac.ops.mng_enable_host_if(hw); + ret_val = e1000_mng_enable_host_if_generic(hw); if (ret_val != E1000_SUCCESS) { hw->mac.tx_pkt_filtering = FALSE; return hw->mac.tx_pkt_filtering; @@ -165,8 +164,7 @@ bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw) hdr->checksum = 0; csum = e1000_calculate_checksum((u8 *)hdr, E1000_MNG_DHCP_COOKIE_LENGTH); - /* - * If either the checksums or signature don't match, then + /* If either the checksums or signature don't match, then * the cookie area isn't considered valid, in which case we * take the safe route of assuming Tx filtering is enabled. */ @@ -259,8 +257,7 @@ s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer, /* Calculate length in DWORDs */ length >>= 2; - /* - * The device driver writes the relevant command block into the + /* The device driver writes the relevant command block into the * ram area. */ for (i = 0; i < length; i++) { @@ -312,18 +309,18 @@ s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer, hdr.checksum = 0; /* Enable the host interface */ - ret_val = hw->mac.ops.mng_enable_host_if(hw); + ret_val = e1000_mng_enable_host_if_generic(hw); if (ret_val) return ret_val; /* Populate the host interface with the contents of "buffer". */ - ret_val = hw->mac.ops.mng_host_if_write(hw, buffer, length, - sizeof(hdr), &(hdr.checksum)); + ret_val = e1000_mng_host_if_write_generic(hw, buffer, length, + sizeof(hdr), &(hdr.checksum)); if (ret_val) return ret_val; /* Write the manageability command header */ - ret_val = hw->mac.ops.mng_write_cmd_header(hw, &hdr); + ret_val = e1000_mng_write_cmd_header_generic(hw, &hdr); if (ret_val) return ret_val; @@ -424,8 +421,7 @@ s32 e1000_host_interface_command(struct e1000_hw *hw, u8 *buffer, u32 length) /* Calculate length in DWORDs */ length >>= 2; - /* - * The device driver writes the relevant command block + /* The device driver writes the relevant command block * into the ram area. */ for (i = 0; i < length; i++) @@ -537,8 +533,7 @@ s32 e1000_load_firmware(struct e1000_hw *hw, u8 *buffer, u32 length) /* Calculate length in DWORDs */ length >>= 2; - /* - * The device driver writes the relevant FW code block + /* The device driver writes the relevant FW code block * into the ram area in DWORDs via 1kB ram addressing window. */ for (i = 0; i < length; i++) { diff --git a/sys/dev/e1000/e1000_nvm.c b/sys/dev/e1000/e1000_nvm.c index d8df089efec..a39b8478150 100644 --- a/sys/dev/e1000/e1000_nvm.c +++ b/sys/dev/e1000/e1000_nvm.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2011, Intel Corporation + Copyright (c) 2001-2013, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -227,7 +227,6 @@ s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg) { u32 attempts = 100000; u32 i, reg = 0; - s32 ret_val = -E1000_ERR_NVM; DEBUGFUNC("e1000_poll_eerd_eewr_done"); @@ -237,15 +236,13 @@ s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg) else reg = E1000_READ_REG(hw, E1000_EEWR); - if (reg & E1000_NVM_RW_REG_DONE) { - ret_val = E1000_SUCCESS; - break; - } + if (reg & E1000_NVM_RW_REG_DONE) + return E1000_SUCCESS; usec_delay(5); } - return ret_val; + return -E1000_ERR_NVM; } /** @@ -260,7 +257,6 @@ s32 e1000_acquire_nvm_generic(struct e1000_hw *hw) { u32 eecd = E1000_READ_REG(hw, E1000_EECD); s32 timeout = E1000_NVM_GRANT_ATTEMPTS; - s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_acquire_nvm_generic"); @@ -279,10 +275,10 @@ s32 e1000_acquire_nvm_generic(struct e1000_hw *hw) eecd &= ~E1000_EECD_REQ; E1000_WRITE_REG(hw, E1000_EECD, eecd); DEBUGOUT("Could not acquire NVM grant\n"); - ret_val = -E1000_ERR_NVM; + return -E1000_ERR_NVM; } - return ret_val; + return E1000_SUCCESS; } /** @@ -381,7 +377,6 @@ static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw) { struct e1000_nvm_info *nvm = &hw->nvm; u32 eecd = E1000_READ_REG(hw, E1000_EECD); - s32 ret_val = E1000_SUCCESS; u8 spi_stat_reg; DEBUGFUNC("e1000_ready_nvm_eeprom"); @@ -402,8 +397,7 @@ static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw) E1000_WRITE_FLUSH(hw); usec_delay(1); - /* - * Read "Status Register" repeatedly until the LSB is cleared. + /* Read "Status Register" repeatedly until the LSB is cleared. * The EEPROM will signal that the command has been completed * by clearing bit 0 of the internal status register. If it's * not cleared within 'timeout', then error out. @@ -422,13 +416,11 @@ static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw) if (!timeout) { DEBUGOUT("SPI NVM Status error\n"); - ret_val = -E1000_ERR_NVM; - goto out; + return -E1000_ERR_NVM; } } -out: - return ret_val; + return E1000_SUCCESS; } /** @@ -450,20 +442,18 @@ s32 e1000_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) DEBUGFUNC("e1000_read_nvm_spi"); - /* - * A check for invalid values: offset too large, too many words, + /* A check for invalid values: offset too large, too many words, * and not enough words. */ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || (words == 0)) { DEBUGOUT("nvm parameter(s) out of bounds\n"); - ret_val = -E1000_ERR_NVM; - goto out; + return -E1000_ERR_NVM; } ret_val = nvm->ops.acquire(hw); if (ret_val) - goto out; + return ret_val; ret_val = e1000_ready_nvm_eeprom(hw); if (ret_val) @@ -478,8 +468,7 @@ s32 e1000_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) e1000_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits); e1000_shift_out_eec_bits(hw, (u16)(offset*2), nvm->address_bits); - /* - * Read the data. SPI NVMs increment the address with each byte + /* Read the data. SPI NVMs increment the address with each byte * read and will roll over if reading beyond the end. This allows * us to read the whole NVM from any offset */ @@ -491,7 +480,6 @@ s32 e1000_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) release: nvm->ops.release(hw); -out: return ret_val; } @@ -514,20 +502,18 @@ s32 e1000_read_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words, DEBUGFUNC("e1000_read_nvm_microwire"); - /* - * A check for invalid values: offset too large, too many words, + /* A check for invalid values: offset too large, too many words, * and not enough words. */ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || (words == 0)) { DEBUGOUT("nvm parameter(s) out of bounds\n"); - ret_val = -E1000_ERR_NVM; - goto out; + return -E1000_ERR_NVM; } ret_val = nvm->ops.acquire(hw); if (ret_val) - goto out; + return ret_val; ret_val = e1000_ready_nvm_eeprom(hw); if (ret_val) @@ -539,8 +525,7 @@ s32 e1000_read_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words, e1000_shift_out_eec_bits(hw, (u16)(offset + i), nvm->address_bits); - /* - * Read the data. For microwire, each word requires the + /* Read the data. For microwire, each word requires the * overhead of setup and tear-down. */ data[i] = e1000_shift_in_eec_bits(hw, 16); @@ -550,7 +535,6 @@ s32 e1000_read_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words, release: nvm->ops.release(hw); -out: return ret_val; } @@ -571,15 +555,13 @@ s32 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) DEBUGFUNC("e1000_read_nvm_eerd"); - /* - * A check for invalid values: offset too large, too many words, + /* A check for invalid values: offset too large, too many words, * too many words for the offset, and not enough words. */ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || (words == 0)) { DEBUGOUT("nvm parameter(s) out of bounds\n"); - ret_val = -E1000_ERR_NVM; - goto out; + return -E1000_ERR_NVM; } for (i = 0; i < words; i++) { @@ -595,7 +577,6 @@ s32 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) E1000_NVM_RW_REG_DATA); } -out: return ret_val; } @@ -614,32 +595,32 @@ out: s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) { struct e1000_nvm_info *nvm = &hw->nvm; - s32 ret_val; + s32 ret_val = -E1000_ERR_NVM; u16 widx = 0; DEBUGFUNC("e1000_write_nvm_spi"); - /* - * A check for invalid values: offset too large, too many words, + /* A check for invalid values: offset too large, too many words, * and not enough words. */ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || (words == 0)) { DEBUGOUT("nvm parameter(s) out of bounds\n"); - ret_val = -E1000_ERR_NVM; - goto out; + return -E1000_ERR_NVM; } - ret_val = nvm->ops.acquire(hw); - if (ret_val) - goto out; - while (widx < words) { u8 write_opcode = NVM_WRITE_OPCODE_SPI; - ret_val = e1000_ready_nvm_eeprom(hw); + ret_val = nvm->ops.acquire(hw); if (ret_val) - goto release; + return ret_val; + + ret_val = e1000_ready_nvm_eeprom(hw); + if (ret_val) { + nvm->ops.release(hw); + return ret_val; + } e1000_standby_nvm(hw); @@ -649,8 +630,7 @@ s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) e1000_standby_nvm(hw); - /* - * Some SPI eeproms use the 8th address bit embedded in the + /* Some SPI eeproms use the 8th address bit embedded in the * opcode */ if ((nvm->address_bits == 8) && (offset >= 128)) @@ -673,13 +653,10 @@ s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) break; } } + msec_delay(10); + nvm->ops.release(hw); } - msec_delay(10); -release: - nvm->ops.release(hw); - -out: return ret_val; } @@ -706,20 +683,18 @@ s32 e1000_write_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words, DEBUGFUNC("e1000_write_nvm_microwire"); - /* - * A check for invalid values: offset too large, too many words, + /* A check for invalid values: offset too large, too many words, * and not enough words. */ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || (words == 0)) { DEBUGOUT("nvm parameter(s) out of bounds\n"); - ret_val = -E1000_ERR_NVM; - goto out; + return -E1000_ERR_NVM; } ret_val = nvm->ops.acquire(hw); if (ret_val) - goto out; + return ret_val; ret_val = e1000_ready_nvm_eeprom(hw); if (ret_val) @@ -769,7 +744,6 @@ s32 e1000_write_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words, release: nvm->ops.release(hw); -out: return ret_val; } @@ -795,32 +769,30 @@ s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num, if (pba_num == NULL) { DEBUGOUT("PBA string buffer was null\n"); - ret_val = E1000_ERR_INVALID_ARGUMENT; - goto out; + return -E1000_ERR_INVALID_ARGUMENT; } ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); - goto out; + return ret_val; } ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr); if (ret_val) { DEBUGOUT("NVM Read Error\n"); - goto out; + return ret_val; } - /* - * if nvm_data is not ptr guard the PBA must be in legacy format which + /* if nvm_data is not ptr guard the PBA must be in legacy format which * means pba_ptr is actually our second data word for the PBA number * and we can decode it into an ascii string */ if (nvm_data != NVM_PBA_PTR_GUARD) { DEBUGOUT("NVM PBA number is not stored as string\n"); - /* we will need 11 characters to store the PBA */ - if (pba_num_size < 11) { + /* make sure callers buffer is big enough to store the PBA */ + if (pba_num_size < E1000_PBANUM_LENGTH) { DEBUGOUT("PBA string buffer too small\n"); return E1000_ERR_NO_SPACE; } @@ -848,25 +820,23 @@ s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num, pba_num[offset] += 'A' - 0xA; } - goto out; + return E1000_SUCCESS; } ret_val = hw->nvm.ops.read(hw, pba_ptr, 1, &length); if (ret_val) { DEBUGOUT("NVM Read Error\n"); - goto out; + return ret_val; } if (length == 0xFFFF || length == 0) { DEBUGOUT("NVM PBA number section invalid length\n"); - ret_val = E1000_ERR_NVM_PBA_SECTION; - goto out; + return -E1000_ERR_NVM_PBA_SECTION; } /* check if pba_num buffer is big enough */ if (pba_num_size < (((u32)length * 2) - 1)) { DEBUGOUT("PBA string buffer too small\n"); - ret_val = E1000_ERR_NO_SPACE; - goto out; + return -E1000_ERR_NO_SPACE; } /* trim pba length from start of string */ @@ -877,15 +847,14 @@ s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num, ret_val = hw->nvm.ops.read(hw, pba_ptr + offset, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); - goto out; + return ret_val; } pba_num[offset * 2] = (u8)(nvm_data >> 8); pba_num[(offset * 2) + 1] = (u8)(nvm_data & 0xFF); } pba_num[offset * 2] = '\0'; -out: - return ret_val; + return E1000_SUCCESS; } /** @@ -907,48 +876,233 @@ s32 e1000_read_pba_length_generic(struct e1000_hw *hw, u32 *pba_num_size) if (pba_num_size == NULL) { DEBUGOUT("PBA buffer size was null\n"); - ret_val = E1000_ERR_INVALID_ARGUMENT; - goto out; + return -E1000_ERR_INVALID_ARGUMENT; } ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); - goto out; + return ret_val; } ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr); if (ret_val) { DEBUGOUT("NVM Read Error\n"); - goto out; + return ret_val; } /* if data is not ptr guard the PBA must be in legacy format */ if (nvm_data != NVM_PBA_PTR_GUARD) { - *pba_num_size = 11; - goto out; + *pba_num_size = E1000_PBANUM_LENGTH; + return E1000_SUCCESS; } ret_val = hw->nvm.ops.read(hw, pba_ptr, 1, &length); if (ret_val) { DEBUGOUT("NVM Read Error\n"); - goto out; + return ret_val; } if (length == 0xFFFF || length == 0) { DEBUGOUT("NVM PBA number section invalid length\n"); - ret_val = E1000_ERR_NVM_PBA_SECTION; - goto out; + return -E1000_ERR_NVM_PBA_SECTION; } - /* - * Convert from length in u16 values to u8 chars, add 1 for NULL, + /* Convert from length in u16 values to u8 chars, add 1 for NULL, * and subtract 2 because length field is included in length. */ *pba_num_size = ((u32)length * 2) - 1; -out: - return ret_val; + return E1000_SUCCESS; +} + + +/** + * e1000_read_pba_raw + * @hw: pointer to the HW structure + * @eeprom_buf: optional pointer to EEPROM image + * @eeprom_buf_size: size of EEPROM image in words + * @max_pba_block_size: PBA block size limit + * @pba: pointer to output PBA structure + * + * Reads PBA from EEPROM image when eeprom_buf is not NULL. + * Reads PBA from physical EEPROM device when eeprom_buf is NULL. + * + **/ +s32 e1000_read_pba_raw(struct e1000_hw *hw, u16 *eeprom_buf, + u32 eeprom_buf_size, u16 max_pba_block_size, + struct e1000_pba *pba) +{ + s32 ret_val; + u16 pba_block_size; + + if (pba == NULL) + return -E1000_ERR_PARAM; + + if (eeprom_buf == NULL) { + ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_0, 2, + &pba->word[0]); + if (ret_val) + return ret_val; + } else { + if (eeprom_buf_size > NVM_PBA_OFFSET_1) { + pba->word[0] = eeprom_buf[NVM_PBA_OFFSET_0]; + pba->word[1] = eeprom_buf[NVM_PBA_OFFSET_1]; + } else { + return -E1000_ERR_PARAM; + } + } + + if (pba->word[0] == NVM_PBA_PTR_GUARD) { + if (pba->pba_block == NULL) + return -E1000_ERR_PARAM; + + ret_val = e1000_get_pba_block_size(hw, eeprom_buf, + eeprom_buf_size, + &pba_block_size); + if (ret_val) + return ret_val; + + if (pba_block_size > max_pba_block_size) + return -E1000_ERR_PARAM; + + if (eeprom_buf == NULL) { + ret_val = e1000_read_nvm(hw, pba->word[1], + pba_block_size, + pba->pba_block); + if (ret_val) + return ret_val; + } else { + if (eeprom_buf_size > (u32)(pba->word[1] + + pba->pba_block[0])) { + memcpy(pba->pba_block, + &eeprom_buf[pba->word[1]], + pba_block_size * sizeof(u16)); + } else { + return -E1000_ERR_PARAM; + } + } + } + + return E1000_SUCCESS; +} + +/** + * e1000_write_pba_raw + * @hw: pointer to the HW structure + * @eeprom_buf: optional pointer to EEPROM image + * @eeprom_buf_size: size of EEPROM image in words + * @pba: pointer to PBA structure + * + * Writes PBA to EEPROM image when eeprom_buf is not NULL. + * Writes PBA to physical EEPROM device when eeprom_buf is NULL. + * + **/ +s32 e1000_write_pba_raw(struct e1000_hw *hw, u16 *eeprom_buf, + u32 eeprom_buf_size, struct e1000_pba *pba) +{ + s32 ret_val; + + if (pba == NULL) + return -E1000_ERR_PARAM; + + if (eeprom_buf == NULL) { + ret_val = e1000_write_nvm(hw, NVM_PBA_OFFSET_0, 2, + &pba->word[0]); + if (ret_val) + return ret_val; + } else { + if (eeprom_buf_size > NVM_PBA_OFFSET_1) { + eeprom_buf[NVM_PBA_OFFSET_0] = pba->word[0]; + eeprom_buf[NVM_PBA_OFFSET_1] = pba->word[1]; + } else { + return -E1000_ERR_PARAM; + } + } + + if (pba->word[0] == NVM_PBA_PTR_GUARD) { + if (pba->pba_block == NULL) + return -E1000_ERR_PARAM; + + if (eeprom_buf == NULL) { + ret_val = e1000_write_nvm(hw, pba->word[1], + pba->pba_block[0], + pba->pba_block); + if (ret_val) + return ret_val; + } else { + if (eeprom_buf_size > (u32)(pba->word[1] + + pba->pba_block[0])) { + memcpy(&eeprom_buf[pba->word[1]], + pba->pba_block, + pba->pba_block[0] * sizeof(u16)); + } else { + return -E1000_ERR_PARAM; + } + } + } + + return E1000_SUCCESS; +} + +/** + * e1000_get_pba_block_size + * @hw: pointer to the HW structure + * @eeprom_buf: optional pointer to EEPROM image + * @eeprom_buf_size: size of EEPROM image in words + * @pba_data_size: pointer to output variable + * + * Returns the size of the PBA block in words. Function operates on EEPROM + * image if the eeprom_buf pointer is not NULL otherwise it accesses physical + * EEPROM device. + * + **/ +s32 e1000_get_pba_block_size(struct e1000_hw *hw, u16 *eeprom_buf, + u32 eeprom_buf_size, u16 *pba_block_size) +{ + s32 ret_val; + u16 pba_word[2]; + u16 length; + + DEBUGFUNC("e1000_get_pba_block_size"); + + if (eeprom_buf == NULL) { + ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_0, 2, &pba_word[0]); + if (ret_val) + return ret_val; + } else { + if (eeprom_buf_size > NVM_PBA_OFFSET_1) { + pba_word[0] = eeprom_buf[NVM_PBA_OFFSET_0]; + pba_word[1] = eeprom_buf[NVM_PBA_OFFSET_1]; + } else { + return -E1000_ERR_PARAM; + } + } + + if (pba_word[0] == NVM_PBA_PTR_GUARD) { + if (eeprom_buf == NULL) { + ret_val = e1000_read_nvm(hw, pba_word[1] + 0, 1, + &length); + if (ret_val) + return ret_val; + } else { + if (eeprom_buf_size > pba_word[1]) + length = eeprom_buf[pba_word[1] + 0]; + else + return -E1000_ERR_PARAM; + } + + if (length == 0xFFFF || length == 0) + return -E1000_ERR_NVM_PBA_SECTION; + } else { + /* PBA number in legacy format, there is no PBA Block. */ + length = 0; + } + + if (pba_block_size != NULL) + *pba_block_size = length; + + return E1000_SUCCESS; } /** @@ -989,7 +1143,7 @@ s32 e1000_read_mac_addr_generic(struct e1000_hw *hw) **/ s32 e1000_validate_nvm_checksum_generic(struct e1000_hw *hw) { - s32 ret_val = E1000_SUCCESS; + s32 ret_val; u16 checksum = 0; u16 i, nvm_data; @@ -999,19 +1153,17 @@ s32 e1000_validate_nvm_checksum_generic(struct e1000_hw *hw) ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); - goto out; + return ret_val; } checksum += nvm_data; } if (checksum != (u16) NVM_SUM) { DEBUGOUT("NVM Checksum Invalid\n"); - ret_val = -E1000_ERR_NVM; - goto out; + return -E1000_ERR_NVM; } -out: - return ret_val; + return E1000_SUCCESS; } /** @@ -1034,7 +1186,7 @@ s32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw) ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error while updating checksum.\n"); - goto out; + return ret_val; } checksum += nvm_data; } @@ -1043,7 +1195,6 @@ s32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw) if (ret_val) DEBUGOUT("NVM Write Error while updating checksum.\n"); -out: return ret_val; } @@ -1067,3 +1218,4 @@ static void e1000_reload_nvm_generic(struct e1000_hw *hw) E1000_WRITE_FLUSH(hw); } + diff --git a/sys/dev/e1000/e1000_nvm.h b/sys/dev/e1000/e1000_nvm.h index ed23eb3e37a..34077b24984 100644 --- a/sys/dev/e1000/e1000_nvm.h +++ b/sys/dev/e1000/e1000_nvm.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2011, Intel Corporation + Copyright (c) 2001-2013, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -35,6 +35,14 @@ #ifndef _E1000_NVM_H_ #define _E1000_NVM_H_ +#if !defined(NO_READ_PBA_RAW) || !defined(NO_WRITE_PBA_RAW) +struct e1000_pba { + u16 word[2]; + u16 *pba_block; +}; +#endif + + void e1000_init_nvm_ops_generic(struct e1000_hw *hw); s32 e1000_null_read_nvm(struct e1000_hw *hw, u16 a, u16 b, u16 *c); void e1000_null_nvm_generic(struct e1000_hw *hw); @@ -47,6 +55,13 @@ s32 e1000_read_mac_addr_generic(struct e1000_hw *hw); s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num, u32 pba_num_size); s32 e1000_read_pba_length_generic(struct e1000_hw *hw, u32 *pba_num_size); +s32 e1000_read_pba_raw(struct e1000_hw *hw, u16 *eeprom_buf, + u32 eeprom_buf_size, u16 max_pba_block_size, + struct e1000_pba *pba); +s32 e1000_write_pba_raw(struct e1000_hw *hw, u16 *eeprom_buf, + u32 eeprom_buf_size, struct e1000_pba *pba); +s32 e1000_get_pba_block_size(struct e1000_hw *hw, u16 *eeprom_buf, + u32 eeprom_buf_size, u16 *pba_block_size); s32 e1000_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); s32 e1000_read_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); diff --git a/sys/dev/e1000/e1000_osdep.h b/sys/dev/e1000/e1000_osdep.h index e6d131a52e2..dd19613e0b3 100644 --- a/sys/dev/e1000/e1000_osdep.h +++ b/sys/dev/e1000/e1000_osdep.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2010, Intel Corporation + Copyright (c) 2001-2013, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -66,7 +66,8 @@ #define MSGOUT(S, A, B) printf(S "\n", A, B) #define DEBUGFUNC(F) DEBUGOUT(F); #define DEBUGOUT(S) do {} while (0) -#define DEBUGOUT1(S,A) do {} while (0) +/* This define is needed or shared code will not build */ +#define DEBUGOUT1(S,A) if (0) printf(S,A); #define DEBUGOUT2(S,A,B) do {} while (0) #define DEBUGOUT3(S,A,B,C) do {} while (0) #define DEBUGOUT7(S,A,B,C,D,E,F,G) do {} while (0) diff --git a/sys/dev/e1000/e1000_phy.c b/sys/dev/e1000/e1000_phy.c index fd253ba92f9..241c1d5d307 100644 --- a/sys/dev/e1000/e1000_phy.c +++ b/sys/dev/e1000/e1000_phy.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2012, Intel Corporation + Copyright (c) 2001-2013, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -34,7 +34,7 @@ #include "e1000_api.h" -static u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg); +static s32 e1000_wait_autoneg(struct e1000_hw *hw); static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data, bool read, bool page_set); static u32 e1000_get_phy_addr_for_hv_page(u32 page); @@ -173,8 +173,10 @@ s32 e1000_read_i2c_byte_null(struct e1000_hw *hw, u8 byte_offset, * @data: data value to write * **/ -s32 e1000_write_i2c_byte_null(struct e1000_hw *hw, u8 byte_offset, - u8 dev_addr, u8 data) +s32 e1000_write_i2c_byte_null(struct e1000_hw *hw, + u8 byte_offset, + u8 dev_addr, + u8 data) { DEBUGFUNC("e1000_write_i2c_byte_null"); return E1000_SUCCESS; @@ -285,8 +287,7 @@ s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data) return -E1000_ERR_PARAM; } - /* - * Set up Op-code, Phy Address, and register offset in the MDI + /* Set up Op-code, Phy Address, and register offset in the MDI * Control register. The MAC will take care of interfacing with the * PHY to retrieve the desired data. */ @@ -296,8 +297,7 @@ s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data) E1000_WRITE_REG(hw, E1000_MDIC, mdic); - /* - * Poll the ready bit to see if the MDI read completed + /* Poll the ready bit to see if the MDI read completed * Increasing the time out as testing showed failures with * the lower time out */ @@ -315,10 +315,15 @@ s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data) DEBUGOUT("MDI Error\n"); return -E1000_ERR_PHY; } + if (((mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT) != offset) { + DEBUGOUT2("MDI Read offset error - requested %d, returned %d\n", + offset, + (mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT); + return -E1000_ERR_PHY; + } *data = (u16) mdic; - /* - * Allow some time after each MDIC transaction to avoid + /* Allow some time after each MDIC transaction to avoid * reading duplicate data in the next MDIC transaction. */ if (hw->mac.type == e1000_pch2lan) @@ -347,8 +352,7 @@ s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data) return -E1000_ERR_PARAM; } - /* - * Set up Op-code, Phy Address, and register offset in the MDI + /* Set up Op-code, Phy Address, and register offset in the MDI * Control register. The MAC will take care of interfacing with the * PHY to retrieve the desired data. */ @@ -359,8 +363,7 @@ s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data) E1000_WRITE_REG(hw, E1000_MDIC, mdic); - /* - * Poll the ready bit to see if the MDI read completed + /* Poll the ready bit to see if the MDI read completed * Increasing the time out as testing showed failures with * the lower time out */ @@ -378,9 +381,14 @@ s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data) DEBUGOUT("MDI Error\n"); return -E1000_ERR_PHY; } + if (((mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT) != offset) { + DEBUGOUT2("MDI Write offset error - requested %d, returned %d\n", + offset, + (mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT); + return -E1000_ERR_PHY; + } - /* - * Allow some time after each MDIC transaction to avoid + /* Allow some time after each MDIC transaction to avoid * reading duplicate data in the next MDIC transaction. */ if (hw->mac.type == e1000_pch2lan) @@ -405,8 +413,7 @@ s32 e1000_read_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 *data) DEBUGFUNC("e1000_read_phy_reg_i2c"); - /* - * Set up Op-code, Phy Address, and register address in the I2CCMD + /* Set up Op-code, Phy Address, and register address in the I2CCMD * register. The MAC will take care of interfacing with the * PHY to retrieve the desired data. */ @@ -464,8 +471,7 @@ s32 e1000_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data) /* Swap the data bytes for the I2C interface */ phy_data_swapped = ((data >> 8) & 0x00FF) | ((data << 8) & 0xFF00); - /* - * Set up Op-code, Phy Address, and register address in the I2CCMD + /* Set up Op-code, Phy Address, and register address in the I2CCMD * register. The MAC will take care of interfacing with the * PHY to retrieve the desired data. */ @@ -521,8 +527,7 @@ s32 e1000_read_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 *data) return -E1000_ERR_PHY; } - /* - * Set up Op-code, EEPROM Address,in the I2CCMD + /* Set up Op-code, EEPROM Address,in the I2CCMD * register. The MAC will take care of interfacing with the * EEPROM to retrieve the desired data. */ @@ -576,14 +581,12 @@ s32 e1000_write_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 data) DEBUGOUT("I2CCMD command address exceeds upper limit\n"); return -E1000_ERR_PHY; } - /* - * The programming interface is 16 bits wide + /* The programming interface is 16 bits wide * so we need to read the whole word first * then update appropriate byte lane and write * the updated word back. */ - /* - * Set up Op-code, EEPROM Address,in the I2CCMD + /* Set up Op-code, EEPROM Address,in the I2CCMD * register. The MAC will take care of interfacing * with an EEPROM to write the data given. */ @@ -593,8 +596,7 @@ s32 e1000_write_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 data) E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd); for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) { usec_delay(50); - /* - * Poll the ready bit to see if lastly + /* Poll the ready bit to see if lastly * launched I2C operation completed */ i2ccmd = E1000_READ_REG(hw, E1000_I2CCMD); @@ -602,8 +604,7 @@ s32 e1000_write_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 data) /* Check if this is READ or WRITE phase */ if ((i2ccmd & E1000_I2CCMD_OPCODE_READ) == E1000_I2CCMD_OPCODE_READ) { - /* - * Write the selected byte + /* Write the selected byte * lane and update whole word */ data_local = i2ccmd & 0xFF00; @@ -1053,12 +1054,16 @@ s32 e1000_copper_link_setup_82577(struct e1000_hw *hw) } } - /* Enable CRS on Tx. This must be set for half-duplex operation. */ + /* Enable CRS on Tx. This must be set for half-duplex operation. + * Not required on some PHYs. + */ ret_val = hw->phy.ops.read_reg(hw, I82577_CFG_REG, &phy_data); if (ret_val) return ret_val; - phy_data |= I82577_CFG_ASSERT_CRS_ON_TX; + if ((hw->phy.type != e1000_phy_82579) && + (hw->phy.type != e1000_phy_i217)) + phy_data |= I82577_CFG_ASSERT_CRS_ON_TX; /* Enable downshift */ phy_data |= I82577_CFG_ENABLE_DOWNSHIFT; @@ -1072,8 +1077,7 @@ s32 e1000_copper_link_setup_82577(struct e1000_hw *hw) if (ret_val) return ret_val; phy_data &= ~I82577_PHY_CTRL2_MDIX_CFG_MASK; - /* - * Options: + /* Options: * 0 - Auto (default) * 1 - MDI mode * 2 - MDI-X mode @@ -1121,8 +1125,7 @@ s32 e1000_copper_link_setup_m88(struct e1000_hw *hw) if (phy->type != e1000_phy_bm) phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; - /* - * Options: + /* Options: * MDI/MDI-X = 0 (default) * 0 - Auto for all speeds * 1 - MDI mode @@ -1147,8 +1150,7 @@ s32 e1000_copper_link_setup_m88(struct e1000_hw *hw) break; } - /* - * Options: + /* Options: * disable_polarity_correction = 0 (default) * Automatic Correction for Reversed Cable Polarity * 0 - Disabled @@ -1185,8 +1187,7 @@ s32 e1000_copper_link_setup_m88(struct e1000_hw *hw) if ((phy->type == e1000_phy_m88) && (phy->revision < E1000_REVISION_4) && (phy->id != BME1000_E_PHY_ID_R2)) { - /* - * Force TX_CLK in the Extended PHY Specific Control Register + /* Force TX_CLK in the Extended PHY Specific Control Register * to 25MHz clock. */ ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, @@ -1278,8 +1279,7 @@ s32 e1000_copper_link_setup_m88_gen2(struct e1000_hw *hw) if (ret_val) return ret_val; - /* - * Options: + /* Options: * MDI/MDI-X = 0 (default) * 0 - Auto for all speeds * 1 - MDI mode @@ -1307,8 +1307,7 @@ s32 e1000_copper_link_setup_m88_gen2(struct e1000_hw *hw) break; } - /* - * Options: + /* Options: * disable_polarity_correction = 0 (default) * Automatic Correction for Reversed Cable Polarity * 0 - Disabled @@ -1359,14 +1358,12 @@ s32 e1000_copper_link_setup_igp(struct e1000_hw *hw) return ret_val; } - /* - * Wait 100ms for MAC to configure PHY from NVM settings, to avoid + /* Wait 100ms for MAC to configure PHY from NVM settings, to avoid * timeout issues when LFS is enabled. */ msec_delay(100); - /* - * The NVM settings will configure LPLU in D3 for + /* The NVM settings will configure LPLU in D3 for * non-IGP1 PHYs. */ if (phy->type == e1000_phy_igp) { @@ -1411,8 +1408,7 @@ s32 e1000_copper_link_setup_igp(struct e1000_hw *hw) /* set auto-master slave resolution settings */ if (hw->mac.autoneg) { - /* - * when autonegotiation advertisement is only 1000Mbps then we + /* when autonegotiation advertisement is only 1000Mbps then we * should disable SmartSpeed and enable Auto MasterSlave * resolution as hardware default. */ @@ -1481,16 +1477,14 @@ s32 e1000_phy_setup_autoneg(struct e1000_hw *hw) return ret_val; } - /* - * Need to parse both autoneg_advertised and fc and set up + /* Need to parse both autoneg_advertised and fc and set up * the appropriate PHY registers. First we will parse for * autoneg_advertised software override. Since we can advertise * a plethora of combinations, we need to check each bit * individually. */ - /* - * First we clear all the 10/100 mb speed bits in the Auto-Neg + /* First we clear all the 10/100 mb speed bits in the Auto-Neg * Advertisement Register (Address 4) and the 1000 mb speed bits in * the 1000Base-T Control Register (Address 9). */ @@ -1536,8 +1530,7 @@ s32 e1000_phy_setup_autoneg(struct e1000_hw *hw) mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS; } - /* - * Check for a software override of the flow control settings, and + /* Check for a software override of the flow control settings, and * setup the PHY advertisement registers accordingly. If * auto-negotiation is enabled, then software will have to set the * "PAUSE" bits to the correct value in the Auto-Negotiation @@ -1556,15 +1549,13 @@ s32 e1000_phy_setup_autoneg(struct e1000_hw *hw) */ switch (hw->fc.current_mode) { case e1000_fc_none: - /* - * Flow control (Rx & Tx) is completely disabled by a + /* Flow control (Rx & Tx) is completely disabled by a * software over-ride. */ mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); break; case e1000_fc_rx_pause: - /* - * Rx Flow control is enabled, and Tx Flow control is + /* Rx Flow control is enabled, and Tx Flow control is * disabled, by a software over-ride. * * Since there really isn't a way to advertise that we are @@ -1576,16 +1567,14 @@ s32 e1000_phy_setup_autoneg(struct e1000_hw *hw) mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); break; case e1000_fc_tx_pause: - /* - * Tx Flow control is enabled, and Rx Flow control is + /* Tx Flow control is enabled, and Rx Flow control is * disabled, by a software over-ride. */ mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR; mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE; break; case e1000_fc_full: - /* - * Flow control (both Rx and Tx) is enabled by a software + /* Flow control (both Rx and Tx) is enabled by a software * over-ride. */ mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); @@ -1625,14 +1614,12 @@ s32 e1000_copper_link_autoneg(struct e1000_hw *hw) DEBUGFUNC("e1000_copper_link_autoneg"); - /* - * Perform some bounds checking on the autoneg advertisement + /* Perform some bounds checking on the autoneg advertisement * parameter. */ phy->autoneg_advertised &= phy->autoneg_mask; - /* - * If autoneg_advertised is zero, we assume it was not defaulted + /* If autoneg_advertised is zero, we assume it was not defaulted * by the calling code so we set to advertise full capability. */ if (!phy->autoneg_advertised) @@ -1646,8 +1633,7 @@ s32 e1000_copper_link_autoneg(struct e1000_hw *hw) } DEBUGOUT("Restarting Auto-Neg\n"); - /* - * Restart auto-negotiation by setting the Auto Neg Enable bit and + /* Restart auto-negotiation by setting the Auto Neg Enable bit and * the Auto Neg Restart bit in the PHY control register. */ ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_ctrl); @@ -1659,12 +1645,11 @@ s32 e1000_copper_link_autoneg(struct e1000_hw *hw) if (ret_val) return ret_val; - /* - * Does the user want to wait for Auto-Neg to complete here, or + /* Does the user want to wait for Auto-Neg to complete here, or * check at a later time (for example, callback routine). */ if (phy->autoneg_wait_to_complete) { - ret_val = hw->mac.ops.wait_autoneg(hw); + ret_val = e1000_wait_autoneg(hw); if (ret_val) { DEBUGOUT("Error while waiting for autoneg to complete\n"); return ret_val; @@ -1693,16 +1678,14 @@ s32 e1000_setup_copper_link_generic(struct e1000_hw *hw) DEBUGFUNC("e1000_setup_copper_link_generic"); if (hw->mac.autoneg) { - /* - * Setup autoneg and flow control advertisement and perform + /* Setup autoneg and flow control advertisement and perform * autonegotiation. */ ret_val = e1000_copper_link_autoneg(hw); if (ret_val) return ret_val; } else { - /* - * PHY will be set to 10H, 10F, 100H or 100F + /* PHY will be set to 10H, 10F, 100H or 100F * depending on user settings. */ DEBUGOUT("Forcing Speed and Duplex\n"); @@ -1713,8 +1696,7 @@ s32 e1000_setup_copper_link_generic(struct e1000_hw *hw) } } - /* - * Check link status. Wait up to 100 microseconds for link to become + /* Check link status. Wait up to 100 microseconds for link to become * valid. */ ret_val = e1000_phy_has_link_generic(hw, COPPER_LINK_UP_LIMIT, 10, @@ -1760,8 +1742,7 @@ s32 e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw) if (ret_val) return ret_val; - /* - * Clear Auto-Crossover to force MDI manually. IGP requires MDI + /* Clear Auto-Crossover to force MDI manually. IGP requires MDI * forced whenever speed and duplex are forced. */ ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data); @@ -1817,18 +1798,22 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw) DEBUGFUNC("e1000_phy_force_speed_duplex_m88"); - /* - * Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI - * forced whenever speed and duplex are forced. - */ - ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - return ret_val; + /* I210 and I211 devices support Auto-Crossover in forced operation. */ + if (phy->type != e1000_phy_i210) { + /* Clear Auto-Crossover to force MDI manually. M88E1000 + * requires MDI forced whenever speed and duplex are forced. + */ + ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, + &phy_data); + if (ret_val) + return ret_val; - phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; - ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); - if (ret_val) - return ret_val; + phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; + ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, + phy_data); + if (ret_val) + return ret_val; + } DEBUGOUT1("M88E1000 PSCR: %X\n", phy_data); @@ -1874,8 +1859,7 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw) if (!reset_dsp) { DEBUGOUT("Link taking longer than expected.\n"); } else { - /* - * We didn't get link. + /* We didn't get link. * Reset the DSP and cross our fingers. */ ret_val = phy->ops.write_reg(hw, @@ -1909,8 +1893,7 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw) if (ret_val) return ret_val; - /* - * Resetting the phy means we need to re-force TX_CLK in the + /* Resetting the phy means we need to re-force TX_CLK in the * Extended PHY Specific Control Register to 25MHz clock from * the reset value of 2.5MHz. */ @@ -1919,8 +1902,7 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw) if (ret_val) return ret_val; - /* - * In addition, we must re-enable CRS on Tx for both half and full + /* In addition, we must re-enable CRS on Tx for both half and full * duplex. */ ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); @@ -2045,11 +2027,10 @@ void e1000_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl) if (mac->forced_speed_duplex & E1000_ALL_100_SPEED) { ctrl |= E1000_CTRL_SPD_100; *phy_ctrl |= MII_CR_SPEED_100; - *phy_ctrl &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_10); + *phy_ctrl &= ~MII_CR_SPEED_1000; DEBUGOUT("Forcing 100mb\n"); } else { ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100); - *phy_ctrl |= MII_CR_SPEED_10; *phy_ctrl &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_100); DEBUGOUT("Forcing 10mb\n"); } @@ -2094,8 +2075,7 @@ s32 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active) data); if (ret_val) return ret_val; - /* - * LPLU and SmartSpeed are mutually exclusive. LPLU is used + /* LPLU and SmartSpeed are mutually exclusive. LPLU is used * during Dx states where the power conservation is most * important. During driver activity we should enable * SmartSpeed, so performance is maintained. @@ -2238,8 +2218,7 @@ s32 e1000_check_polarity_igp(struct e1000_hw *hw) DEBUGFUNC("e1000_check_polarity_igp"); - /* - * Polarity is determined based on the speed of + /* Polarity is determined based on the speed of * our connection. */ ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data); @@ -2251,8 +2230,7 @@ s32 e1000_check_polarity_igp(struct e1000_hw *hw) offset = IGP01E1000_PHY_PCS_INIT_REG; mask = IGP01E1000_PHY_POLARITY_MASK; } else { - /* - * This really only applies to 10Mbps since + /* This really only applies to 10Mbps since * there is no polarity for 100Mbps (always 0). */ offset = IGP01E1000_PHY_PORT_STATUS; @@ -2283,8 +2261,7 @@ s32 e1000_check_polarity_ife(struct e1000_hw *hw) DEBUGFUNC("e1000_check_polarity_ife"); - /* - * Polarity is determined based on the reversal feature being enabled. + /* Polarity is determined based on the reversal feature being enabled. */ if (phy->polarity_correction) { offset = IFE_PHY_EXTENDED_STATUS_CONTROL; @@ -2305,18 +2282,18 @@ s32 e1000_check_polarity_ife(struct e1000_hw *hw) } /** - * e1000_wait_autoneg_generic - Wait for auto-neg completion + * e1000_wait_autoneg - Wait for auto-neg completion * @hw: pointer to the HW structure * * Waits for auto-negotiation to complete or for the auto-negotiation time * limit to expire, which ever happens first. **/ -s32 e1000_wait_autoneg_generic(struct e1000_hw *hw) +static s32 e1000_wait_autoneg(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS; u16 i, phy_status; - DEBUGFUNC("e1000_wait_autoneg_generic"); + DEBUGFUNC("e1000_wait_autoneg"); if (!hw->phy.ops.read_reg) return E1000_SUCCESS; @@ -2334,8 +2311,7 @@ s32 e1000_wait_autoneg_generic(struct e1000_hw *hw) msec_delay(100); } - /* - * PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation + /* PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation * has completed. */ return ret_val; @@ -2362,15 +2338,13 @@ s32 e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, return E1000_SUCCESS; for (i = 0; i < iterations; i++) { - /* - * Some PHYs require the PHY_STATUS register to be read + /* Some PHYs require the PHY_STATUS register to be read * twice due to the link bit being sticky. No harm doing * it across the board. */ ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); if (ret_val) - /* - * If the first read fails, another entity may have + /* If the first read fails, another entity may have * ownership of the resources, wait and try again to * see if they have relinquished the resources yet. */ @@ -2436,7 +2410,8 @@ s32 e1000_get_cable_length_m88_gen2(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val; - u16 phy_data, phy_data2, index, default_page, is_cm; + u16 phy_data, phy_data2, is_cm; + u16 index, default_page; DEBUGFUNC("e1000_get_cable_length_m88_gen2"); @@ -2574,8 +2549,7 @@ s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw) if (ret_val) return ret_val; - /* - * Getting bits 15:9, which represent the combination of + /* Getting bits 15:9, which represent the combination of * coarse and fine gain values. The result is a number * that can be put into the lookup table to obtain the * approximate cable length. @@ -2961,15 +2935,13 @@ s32 e1000_phy_init_script_igp3(struct e1000_hw *hw) hw->phy.ops.write_reg(hw, 0x1796, 0x0008); /* Change cg_icount + enable integbp for channels BCD */ hw->phy.ops.write_reg(hw, 0x1798, 0xD008); - /* - * Change cg_icount + enable integbp + change prop_factor_master + /* Change cg_icount + enable integbp + change prop_factor_master * to 8 for channel A */ hw->phy.ops.write_reg(hw, 0x1898, 0xD918); /* Disable AHT in Slave mode on channel A */ hw->phy.ops.write_reg(hw, 0x187A, 0x0800); - /* - * Enable LPLU and disable AN to 1000 in non-D0a states, + /* Enable LPLU and disable AN to 1000 in non-D0a states, * Enable SPD+B2B */ hw->phy.ops.write_reg(hw, 0x0019, 0x008D); @@ -3030,6 +3002,9 @@ enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id) case I82579_E_PHY_ID: phy_type = e1000_phy_82579; break; + case I217_E_PHY_ID: + phy_type = e1000_phy_i217; + break; case I82580_I_PHY_ID: phy_type = e1000_phy_82580; break; @@ -3067,8 +3042,7 @@ s32 e1000_determine_phy_address(struct e1000_hw *hw) e1000_get_phy_id(hw); phy_type = e1000_get_phy_type_from_id(hw->phy.id); - /* - * If phy_type is valid, break - we found our + /* If phy_type is valid, break - we found our * PHY address */ if (phy_type != e1000_phy_unknown) @@ -3130,8 +3104,7 @@ s32 e1000_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data) if (offset > MAX_PHY_MULTI_PAGE_REG) { u32 page_shift, page_select; - /* - * Page select is register 31 for phy address 1 and 22 for + /* Page select is register 31 for phy address 1 and 22 for * phy address 2 and 3. Page select is shifted only for * phy address 1. */ @@ -3191,8 +3164,7 @@ s32 e1000_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data) if (offset > MAX_PHY_MULTI_PAGE_REG) { u32 page_shift, page_select; - /* - * Page select is register 31 for phy address 1 and 22 for + /* Page select is register 31 for phy address 1 and 22 for * phy address 2 and 3. Page select is shifted only for * phy address 1. */ @@ -3249,7 +3221,6 @@ s32 e1000_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data) hw->phy.addr = 1; if (offset > MAX_PHY_MULTI_PAGE_REG) { - /* Page is shifted left, PHY expects (page x 32) */ ret_val = e1000_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT, page); @@ -3346,8 +3317,7 @@ s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg) return ret_val; } - /* - * Enable both PHY wakeup mode and Wakeup register page writes. + /* Enable both PHY wakeup mode and Wakeup register page writes. * Prevent a power state change by disabling ME and Host PHY wakeup. */ temp = *phy_reg; @@ -3361,8 +3331,7 @@ s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg) return ret_val; } - /* - * Select Host Wakeup Registers page - caller now able to write + /* Select Host Wakeup Registers page - caller now able to write * registers on the Wakeup registers page */ return e1000_set_page_igp(hw, (BM_WUC_PAGE << IGP_PAGE_SHIFT)); @@ -3381,7 +3350,7 @@ s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg) **/ s32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg) { - s32 ret_val = E1000_SUCCESS; + s32 ret_val; DEBUGFUNC("e1000_disable_phy_wakeup_reg_access_bm"); @@ -3434,6 +3403,7 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, { s32 ret_val; u16 reg = BM_PHY_REG_NUM(offset); + u16 page = BM_PHY_REG_PAGE(offset); u16 phy_reg = 0; DEBUGFUNC("e1000_access_phy_wakeup_reg_bm"); @@ -3687,8 +3657,7 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data, if (page == HV_INTC_FC_PAGE_START) page = 0; - /* - * Workaround MDIO accesses being disabled after entering IEEE + /* Workaround MDIO accesses being disabled after entering IEEE * Power Down (when bit 11 of the PHY Control register is set) */ if ((hw->phy.type == e1000_phy_82578) && @@ -3801,8 +3770,8 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, u16 *data, bool read) { s32 ret_val; - u32 addr_reg = 0; - u32 data_reg = 0; + u32 addr_reg; + u32 data_reg; DEBUGFUNC("e1000_access_phy_debug_regs_hv"); @@ -3875,8 +3844,8 @@ s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw) /* flush the packets in the fifo buffer */ ret_val = hw->phy.ops.write_reg(hw, HV_MUX_DATA_CTRL, - HV_MUX_DATA_CTRL_GEN_TO_MAC | - HV_MUX_DATA_CTRL_FORCE_SPEED); + (HV_MUX_DATA_CTRL_GEN_TO_MAC | + HV_MUX_DATA_CTRL_FORCE_SPEED)); if (ret_val) return ret_val; @@ -4044,7 +4013,7 @@ s32 e1000_get_cable_length_82577(struct e1000_hw *hw) I82577_DSTATUS_CABLE_LENGTH_SHIFT; if (length == E1000_CABLE_LENGTH_UNDEFINED) - ret_val = -E1000_ERR_PHY; + return -E1000_ERR_PHY; phy->cable_length = length; @@ -4113,3 +4082,4 @@ release: hw->phy.ops.release(hw); return ret_val; } + diff --git a/sys/dev/e1000/e1000_phy.h b/sys/dev/e1000/e1000_phy.h index edcbcabe446..9911df772d9 100644 --- a/sys/dev/e1000/e1000_phy.h +++ b/sys/dev/e1000/e1000_phy.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2012, Intel Corporation + Copyright (c) 2001-2013, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -78,13 +78,11 @@ s32 e1000_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active); s32 e1000_setup_copper_link_generic(struct e1000_hw *hw); -s32 e1000_wait_autoneg_generic(struct e1000_hw *hw); s32 e1000_write_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000_phy_reset_dsp(struct e1000_hw *hw); s32 e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, u32 usec_interval, bool *success); s32 e1000_phy_init_script_igp3(struct e1000_hw *hw); @@ -127,7 +125,6 @@ s32 e1000_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data); #define IGP01E1000_PHY_PORT_CTRL 0x12 /* Control */ #define IGP01E1000_PHY_LINK_HEALTH 0x13 /* PHY Link Health */ #define IGP01E1000_GMII_FIFO 0x14 /* GMII FIFO */ -#define IGP01E1000_PHY_CHANNEL_QUALITY 0x15 /* PHY Channel Quality */ #define IGP02E1000_PHY_POWER_MGMT 0x19 /* Power Management */ #define IGP01E1000_PHY_PAGE_SELECT 0x1F /* Page Select */ #define BM_PHY_PAGE_SELECT 22 /* Page Select for BM */ @@ -147,7 +144,6 @@ s32 e1000_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data); /* BM/HV Specific Registers */ #define BM_PORT_CTRL_PAGE 769 -#define BM_PCIE_PAGE 770 #define BM_WUC_PAGE 800 #define BM_WUC_ADDRESS_OPCODE 0x11 #define BM_WUC_DATA_OPCODE 0x12 @@ -188,7 +184,6 @@ s32 e1000_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data); #define I82577_PHY_STATUS2_MDIX 0x0800 #define I82577_PHY_STATUS2_SPEED_MASK 0x0300 #define I82577_PHY_STATUS2_SPEED_1000MBPS 0x0200 -#define I82577_PHY_STATUS2_SPEED_100MBPS 0x0100 /* I82577 PHY Control 2 */ #define I82577_PHY_CTRL2_MANUAL_MDIX 0x0200 @@ -204,14 +199,13 @@ s32 e1000_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data); #define E1000_82580_PM_SPD 0x0001 /* Smart Power Down */ #define E1000_82580_PM_D0_LPLU 0x0002 /* For D0a states */ #define E1000_82580_PM_D3_LPLU 0x0004 /* For all other states */ +#define E1000_82580_PM_GO_LINKD 0x0020 /* Go Link Disconnect */ /* BM PHY Copper Specific Control 1 */ #define BM_CS_CTRL1 16 -#define BM_CS_CTRL1_ENERGY_DETECT 0x0300 /* Enable Energy Detect */ /* BM PHY Copper Specific Status */ #define BM_CS_STATUS 17 -#define BM_CS_STATUS_ENERGY_DETECT 0x0010 /* Energy Detect Status */ #define BM_CS_STATUS_LINK_UP 0x0400 #define BM_CS_STATUS_RESOLVED 0x0800 #define BM_CS_STATUS_SPEED_MASK 0xC000 @@ -257,9 +251,6 @@ s32 e1000_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data); #define IGP02E1000_AGC_LENGTH_MASK 0x7F #define IGP02E1000_AGC_RANGE 15 -#define IGP03E1000_PHY_MISC_CTRL 0x1B -#define IGP03E1000_PHY_MISC_DUPLEX_MANUAL_SET 0x1000 /* Manually Set Duplex */ - #define E1000_CABLE_LENGTH_UNDEFINED 0xFF #define E1000_KMRNCTRLSTA_OFFSET 0x001F0000 @@ -272,7 +263,7 @@ s32 e1000_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data); #define E1000_KMRNCTRLSTA_IBIST_DISABLE 0x0200 /* Kumeran IBIST Disable */ #define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */ #define E1000_KMRNCTRLSTA_K1_CONFIG 0x7 -#define E1000_KMRNCTRLSTA_K1_ENABLE 0x0002 +#define E1000_KMRNCTRLSTA_K1_ENABLE 0x0002 /* enable K1 */ #define E1000_KMRNCTRLSTA_HD_CTRL 0x10 /* Kumeran HD Control */ #define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10 @@ -286,7 +277,6 @@ s32 e1000_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data); /* IFE PHY Special Control */ #define IFE_PSC_AUTO_POLARITY_DISABLE 0x0010 #define IFE_PSC_FORCE_POLARITY 0x0020 -#define IFE_PSC_DISABLE_DYNAMIC_POWER_DOWN 0x0100 /* IFE PHY Special Control and LED Control */ #define IFE_PSCL_PROBE_MODE 0x0020 diff --git a/sys/dev/e1000/e1000_regs.h b/sys/dev/e1000/e1000_regs.h index 8c4e4afd13b..516d377af40 100644 --- a/sys/dev/e1000/e1000_regs.h +++ b/sys/dev/e1000/e1000_regs.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2012, Intel Corporation + Copyright (c) 2001-2013, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -55,9 +55,11 @@ #define E1000_SCTL 0x00024 /* SerDes Control - RW */ #define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */ #define E1000_FCAH 0x0002C /* Flow Control Address High -RW */ -#define E1000_FEXT 0x0002C /* Future Extended - RW */ -#define E1000_FEXTNVM4 0x00024 /* Future Extended NVM 4 - RW */ #define E1000_FEXTNVM 0x00028 /* Future Extended NVM - RW */ +#define E1000_FEXTNVM3 0x0003C /* Future Extended NVM 3 - RW */ +#define E1000_FEXTNVM4 0x00024 /* Future Extended NVM 4 - RW */ +#define E1000_FEXTNVM6 0x00010 /* Future Extended NVM 6 - RW */ +#define E1000_FEXTNVM7 0x000E4 /* Future Extended NVM 7 - RW */ #define E1000_FCT 0x00030 /* Flow Control Type - RW */ #define E1000_CONNSW 0x00034 /* Copper/Fiber switch control - RW */ #define E1000_VET 0x00038 /* VLAN Ether Type - RW */ @@ -70,6 +72,7 @@ #define E1000_IVAR 0x000E4 /* Interrupt Vector Allocation Register - RW */ #define E1000_SVCR 0x000F0 #define E1000_SVT 0x000F4 +#define E1000_LPIC 0x000FC /* Low Power IDLE control */ #define E1000_RCTL 0x00100 /* Rx Control - RW */ #define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */ #define E1000_TXCW 0x00178 /* Tx Configuration Word - RW */ @@ -97,6 +100,7 @@ #define E1000_POEMB E1000_PHY_CTRL /* PHY OEM Bits */ #define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */ #define E1000_PBS 0x01008 /* Packet Buffer Size */ +#define E1000_PBECCSTS 0x0100C /* Packet Buffer ECC Status - RW */ #define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */ #define E1000_EEARBC 0x01024 /* EEPROM Auto Read Bus Control */ #define E1000_FLASHT 0x01028 /* FLASH Timer Register */ @@ -129,7 +133,11 @@ #define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */ #define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */ #define E1000_PSRCTL 0x02170 /* Packet Split Receive Control - RW */ -#define E1000_RDFPCQ(_n) (0x02430 + (0x4 * (_n))) +#define E1000_RDFH 0x02410 /* Rx Data FIFO Head - RW */ +#define E1000_RDFT 0x02418 /* Rx Data FIFO Tail - RW */ +#define E1000_RDFHS 0x02420 /* Rx Data FIFO Head Saved - RW */ +#define E1000_RDFTS 0x02428 /* Rx Data FIFO Tail Saved - RW */ +#define E1000_RDFPC 0x02430 /* Rx Data FIFO Packet Count - RW */ #define E1000_PBRTH 0x02458 /* PB Rx Arbitration Threshold - RW */ #define E1000_FCRTV 0x02460 /* Flow Control Refresh Timer Value - RW */ /* Split and Replication Rx Control - RW */ @@ -200,8 +208,7 @@ /* Queues packet buffer size masks where _n can be 0-3 and _s 0-63 [kB] */ #define E1000_I210_TXPBS_SIZE(_n, _s) ((_s) << (6 * _n)) -/* - * Convenience macros +/* Convenience macros * * Note: "_n" is the queue number of the register to be written to. * @@ -413,8 +420,7 @@ #define E1000_LSECTXKEY1(_n) (0x0B030 + (0x04 * (_n))) #define E1000_LSECRXSA(_n) (0x0B310 + (0x04 * (_n))) /* Rx SAs - RW */ #define E1000_LSECRXPN(_n) (0x0B330 + (0x04 * (_n))) /* Rx SAs - RW */ -/* - * LinkSec Rx Keys - where _n is the SA no. and _m the 4 dwords of the 128 bit +/* LinkSec Rx Keys - where _n is the SA no. and _m the 4 dwords of the 128 bit * key - RW. */ #define E1000_LSECRXKEY(_n, _m) (0x0B350 + (0x10 * (_n)) + (0x04 * (_m))) @@ -454,7 +460,6 @@ #define E1000_PCS_LPAB 0x0421C /* Link Partner Ability - RW */ #define E1000_PCS_NPTX 0x04220 /* AN Next Page Transmit - RW */ #define E1000_PCS_LPABNP 0x04224 /* Link Partner Ability Next Pg - RW */ -#define E1000_1GSTAT_RCV 0x04228 /* 1GSTAT Code Violation Pkt Cnt - RW */ #define E1000_RXCSUM 0x05000 /* Rx Checksum Control - RW */ #define E1000_RLPML 0x05004 /* Rx Long Packet Max Length */ #define E1000_RFCTL 0x05008 /* Receive Filter Control*/ @@ -489,7 +494,6 @@ #define E1000_KMRNCTRLSTA 0x00034 /* MAC-PHY interface - RW */ -#define E1000_MDPHYA 0x0003C /* PHY address - RW */ #define E1000_MANC2H 0x05860 /* Management Control To Host - RW */ /* Management Decision Filters */ #define E1000_MDEF(_n) (0x05890 + (4 * (_n))) @@ -522,15 +526,6 @@ #define E1000_IMIREXT(_i) (0x05AA0 + ((_i) * 4)) /* Immediate INTR Ext*/ #define E1000_IMIRVP 0x05AC0 /* Immediate INT Rx VLAN Priority -RW */ #define E1000_MSIXBM(_i) (0x01600 + ((_i) * 4)) /* MSI-X Alloc Reg -RW */ -/* MSI-X Table entry addr low reg - RW */ -#define E1000_MSIXTADD(_i) (0x0C000 + ((_i) * 0x10)) -/* MSI-X Table entry addr upper reg - RW */ -#define E1000_MSIXTUADD(_i) (0x0C004 + ((_i) * 0x10)) -/* MSI-X Table entry message reg - RW */ -#define E1000_MSIXTMSG(_i) (0x0C008 + ((_i) * 0x10)) -/* MSI-X Table entry vector ctrl reg - RW */ -#define E1000_MSIXVCTRL(_i) (0x0C00C + ((_i) * 0x10)) -#define E1000_MSIXPBA 0x0E000 /* MSI-X Pending bit array */ #define E1000_RETA(_i) (0x05C00 + ((_i) * 4)) /* Redirection Table - RW */ #define E1000_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* RSS Random Key - RW */ #define E1000_RSSIM 0x05864 /* RSS Interrupt Mask */ @@ -580,8 +575,12 @@ #define E1000_SYSTIML 0x0B600 /* System time register Low - RO */ #define E1000_SYSTIMH 0x0B604 /* System time register High - RO */ #define E1000_TIMINCA 0x0B608 /* Increment attributes register - RW */ +#define E1000_TIMADJL 0x0B60C /* Time sync time adjustment offset Low - RW */ +#define E1000_TIMADJH 0x0B610 /* Time sync time adjustment offset High - RW */ #define E1000_TSAUXC 0x0B640 /* Timesync Auxiliary Control register */ #define E1000_SYSTIMR 0x0B6F8 /* System time register Residue */ +#define E1000_TSICR 0x0B66C /* Interrupt Cause Register */ +#define E1000_TSIM 0x0B674 /* Interrupt Mask Register */ #define E1000_RXMTRL 0x0B634 /* Time sync Rx EtherType and Msg Type - RW */ #define E1000_RXUDP 0x0B638 /* Time Sync Rx UDP Port - RW */ @@ -671,8 +670,6 @@ #define E1000_O2BGPTC 0x08FE4 /* OS2BMC packets received by BMC */ #define E1000_O2BSPC 0x0415C /* OS2BMC packets transmitted by host */ -#define E1000_LTRMINV 0x5BB0 /* LTR Minimum Value */ -#define E1000_LTRMAXV 0x5BB4 /* LTR Maximum Value */ #define E1000_DOBFFCTL 0x3F24 /* DMA OBFF Control Register */ diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c index a43126659be..64be42dc0a3 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2011, Intel Corporation + Copyright (c) 2001-2013, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -94,7 +94,7 @@ int em_display_debug_stats = 0; /********************************************************************* * Driver version: *********************************************************************/ -char em_driver_version[] = "7.3.2"; +char em_driver_version[] = "7.3.7"; /********************************************************************* * PCI Device ID Table @@ -172,6 +172,12 @@ static em_vendor_info_t em_vendor_info_array[] = { 0x8086, E1000_DEV_ID_PCH_D_HV_DC, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_PCH2_LV_LM, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_PCH2_LV_V, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_PCH_LPT_I217_LM, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_PCH_LPT_I217_V, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_PCH_LPTLP_I218_LM, + PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_PCH_LPTLP_I218_V, + PCI_ANY_ID, PCI_ANY_ID, 0}, /* required last entry */ { 0, 0, 0, 0, 0} }; @@ -520,7 +526,8 @@ em_attach(device_t dev) (hw->mac.type == e1000_ich9lan) || (hw->mac.type == e1000_ich10lan) || (hw->mac.type == e1000_pchlan) || - (hw->mac.type == e1000_pch2lan)) { + (hw->mac.type == e1000_pch2lan) || + (hw->mac.type == e1000_pch_lpt)) { int rid = EM_BAR_TYPE_FLASH; adapter->flash = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); @@ -605,8 +612,8 @@ em_attach(device_t dev) * Set the frame limits assuming * standard ethernet sized frames. */ - adapter->max_frame_size = ETHERMTU + ETHER_HDR_LEN + ETHERNET_FCS_SIZE; - adapter->min_frame_size = ETH_ZLEN + ETHERNET_FCS_SIZE; + adapter->hw.mac.max_frame_size = + ETHERMTU + ETHER_HDR_LEN + ETHERNET_FCS_SIZE; /* * This controls when hardware reports transmit completion @@ -907,19 +914,17 @@ em_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr, struct mbuf *m) enq = 0; if (m != NULL) { err = drbr_enqueue(ifp, txr->br, m); - if (err) { + if (err) return (err); - } } /* Process the queue */ while ((next = drbr_peek(ifp, txr->br)) != NULL) { if ((err = em_xmit(txr, &next)) != 0) { - if (next == NULL) { + if (next == NULL) drbr_advance(ifp, txr->br); - } else { + else drbr_putback(ifp, txr->br, next); - } break; } drbr_advance(ifp, txr->br); @@ -1108,6 +1113,7 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data) case e1000_ich9lan: case e1000_ich10lan: case e1000_pch2lan: + case e1000_pch_lpt: case e1000_82574: case e1000_82583: case e1000_80003es2lan: /* 9K Jumbo Frame size */ @@ -1131,7 +1137,7 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data) } ifp->if_mtu = ifr->ifr_mtu; - adapter->max_frame_size = + adapter->hw.mac.max_frame_size = ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN; em_init_locked(adapter); EM_CORE_UNLOCK(adapter); @@ -1326,9 +1332,9 @@ em_init_locked(struct adapter *adapter) ** Figure out the desired mbuf ** pool for doing jumbos */ - if (adapter->max_frame_size <= 2048) + if (adapter->hw.mac.max_frame_size <= 2048) adapter->rx_mbuf_sz = MCLBYTES; - else if (adapter->max_frame_size <= 4096) + else if (adapter->hw.mac.max_frame_size <= 4096) adapter->rx_mbuf_sz = MJUMPAGESIZE; else adapter->rx_mbuf_sz = MJUM9BYTES; @@ -2817,17 +2823,18 @@ em_reset(struct adapter *adapter) case e1000_ich9lan: case e1000_ich10lan: /* Boost Receive side for jumbo frames */ - if (adapter->max_frame_size > 4096) + if (adapter->hw.mac.max_frame_size > 4096) pba = E1000_PBA_14K; else pba = E1000_PBA_10K; break; case e1000_pchlan: case e1000_pch2lan: + case e1000_pch_lpt: pba = E1000_PBA_26K; break; default: - if (adapter->max_frame_size > 8192) + if (adapter->hw.mac.max_frame_size > 8192) pba = E1000_PBA_40K; /* 40K for Rx, 24K for Tx */ else pba = E1000_PBA_48K; /* 48K for Rx, 16K for Tx */ @@ -2850,7 +2857,7 @@ em_reset(struct adapter *adapter) */ rx_buffer_size = ((E1000_READ_REG(hw, E1000_PBA) & 0xffff) << 10 ); hw->fc.high_water = rx_buffer_size - - roundup2(adapter->max_frame_size, 1024); + roundup2(adapter->hw.mac.max_frame_size, 1024); hw->fc.low_water = hw->fc.high_water - 1500; if (adapter->fc) /* locally set flow control value? */ @@ -2881,6 +2888,7 @@ em_reset(struct adapter *adapter) hw->fc.refresh_time = 0x1000; break; case e1000_pch2lan: + case e1000_pch_lpt: hw->fc.high_water = 0x5C20; hw->fc.low_water = 0x5048; hw->fc.pause_time = 0x0650; @@ -4341,7 +4349,7 @@ em_initialize_receive_unit(struct adapter *adapter) E1000_WRITE_REG(hw, E1000_RXDCTL(0), rxdctl | 3); } - if (adapter->hw.mac.type == e1000_pch2lan) { + if (adapter->hw.mac.type >= e1000_pch2lan) { if (ifp->if_mtu > ETHERMTU) e1000_lv_jumbo_workaround_ich8lan(hw, TRUE); else @@ -4475,7 +4483,7 @@ em_rxeof(struct rx_ring *rxr, int count, int *done) ifp->if_ipackets++; em_receive_checksum(cur, sendmp); #ifndef __NO_STRICT_ALIGNMENT - if (adapter->max_frame_size > + if (adapter->hw.mac.max_frame_size > (MCLBYTES - ETHER_ALIGN) && em_fixup_rx(rxr) != 0) goto skip; diff --git a/sys/dev/e1000/if_igb.c b/sys/dev/e1000/if_igb.c index 8c6b429bbeb..30bb052ae2c 100644 --- a/sys/dev/e1000/if_igb.c +++ b/sys/dev/e1000/if_igb.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2012, Intel Corporation + Copyright (c) 2001-2013, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -100,7 +100,7 @@ int igb_display_debug_stats = 0; /********************************************************************* * Driver version: *********************************************************************/ -char igb_driver_version[] = "version - 2.3.5"; +char igb_driver_version[] = "version - 2.3.9"; /********************************************************************* @@ -949,7 +949,8 @@ igb_start(struct ifnet *ifp) #else /* __FreeBSD_version >= 800000 */ /* -** Multiqueue Transmit driver +** Multiqueue Transmit Entry: +** quick turnaround to the stack ** */ static int @@ -965,25 +966,11 @@ igb_mq_start(struct ifnet *ifp, struct mbuf *m) i = m->m_pkthdr.flowid % adapter->num_queues; else i = curcpu % adapter->num_queues; - txr = &adapter->tx_rings[i]; que = &adapter->queues[i]; - if (((txr->queue_status & IGB_QUEUE_DEPLETED) == 0) && - IGB_TX_TRYLOCK(txr)) { - /* - ** Try to queue first to avoid - ** out-of-order delivery, but - ** settle for it if that fails - */ - if (m != NULL) - drbr_enqueue(ifp, txr->br, m); - err = igb_mq_start_locked(ifp, txr); - IGB_TX_UNLOCK(txr); - } else { - if (m != NULL) - err = drbr_enqueue(ifp, txr->br, m); - taskqueue_enqueue(que->tq, &txr->txq_task); - } + + err = drbr_enqueue(ifp, txr->br, m); + taskqueue_enqueue(que->tq, &txr->txq_task); return (err); } @@ -998,9 +985,8 @@ igb_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr) IGB_TX_LOCK_ASSERT(txr); if (((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) || - (txr->queue_status & IGB_QUEUE_DEPLETED) || adapter->link_active == 0) - return (err); + return (ENETDOWN); enq = 0; @@ -1702,7 +1688,6 @@ static void igb_media_status(struct ifnet *ifp, struct ifmediareq *ifmr) { struct adapter *adapter = ifp->if_softc; - u_char fiber_type = IFM_1000_SX; INIT_DEBUGOUT("igb_media_status: begin"); @@ -1719,26 +1704,31 @@ igb_media_status(struct ifnet *ifp, struct ifmediareq *ifmr) ifmr->ifm_status |= IFM_ACTIVE; - if ((adapter->hw.phy.media_type == e1000_media_type_fiber) || - (adapter->hw.phy.media_type == e1000_media_type_internal_serdes)) - ifmr->ifm_active |= fiber_type | IFM_FDX; - else { - switch (adapter->link_speed) { - case 10: - ifmr->ifm_active |= IFM_10_T; - break; - case 100: - ifmr->ifm_active |= IFM_100_TX; - break; - case 1000: - ifmr->ifm_active |= IFM_1000_T; - break; - } - if (adapter->link_duplex == FULL_DUPLEX) - ifmr->ifm_active |= IFM_FDX; + switch (adapter->link_speed) { + case 10: + ifmr->ifm_active |= IFM_10_T; + break; + case 100: + /* + ** Support for 100Mb SFP - these are Fiber + ** but the media type appears as serdes + */ + if (adapter->hw.phy.media_type == + e1000_media_type_internal_serdes) + ifmr->ifm_active |= IFM_100_FX; else - ifmr->ifm_active |= IFM_HDX; + ifmr->ifm_active |= IFM_100_TX; + break; + case 1000: + ifmr->ifm_active |= IFM_1000_T; + break; } + + if (adapter->link_duplex == FULL_DUPLEX) + ifmr->ifm_active |= IFM_FDX; + else + ifmr->ifm_active |= IFM_HDX; + IGB_CORE_UNLOCK(adapter); } @@ -2241,11 +2231,13 @@ timeout: static void igb_update_link_status(struct adapter *adapter) { - struct e1000_hw *hw = &adapter->hw; - struct ifnet *ifp = adapter->ifp; - device_t dev = adapter->dev; - struct tx_ring *txr = adapter->tx_rings; - u32 link_check, thstat, ctrl; + struct e1000_hw *hw = &adapter->hw; + struct e1000_fc_info *fc = &hw->fc; + struct ifnet *ifp = adapter->ifp; + device_t dev = adapter->dev; + struct tx_ring *txr = adapter->tx_rings; + u32 link_check, thstat, ctrl; + char *flowctl = NULL; link_check = thstat = ctrl = 0; @@ -2283,15 +2275,33 @@ igb_update_link_status(struct adapter *adapter) ctrl = E1000_READ_REG(hw, E1000_CTRL_EXT); } + /* Get the flow control for display */ + switch (fc->current_mode) { + case e1000_fc_rx_pause: + flowctl = "RX"; + break; + case e1000_fc_tx_pause: + flowctl = "TX"; + break; + case e1000_fc_full: + flowctl = "Full"; + break; + case e1000_fc_none: + default: + flowctl = "None"; + break; + } + /* Now we check if a transition has happened */ if (link_check && (adapter->link_active == 0)) { e1000_get_speed_and_duplex(&adapter->hw, &adapter->link_speed, &adapter->link_duplex); if (bootverbose) - device_printf(dev, "Link is up %d Mbps %s\n", + device_printf(dev, "Link is up %d Mbps %s," + " Flow Control: %s\n", adapter->link_speed, ((adapter->link_duplex == FULL_DUPLEX) ? - "Full Duplex" : "Half Duplex")); + "Full Duplex" : "Half Duplex"), flowctl); adapter->link_active = 1; ifp->if_baudrate = adapter->link_speed * 1000000; if ((ctrl & E1000_CTRL_EXT_LINK_MODE_GMII) && diff --git a/sys/dev/e1000/if_lem.c b/sys/dev/e1000/if_lem.c index 6b2b4f7ea55..b7d2359cbd4 100644 --- a/sys/dev/e1000/if_lem.c +++ b/sys/dev/e1000/if_lem.c @@ -3782,10 +3782,6 @@ lem_setup_vlan_hw_support(struct adapter *adapter) reg &= ~E1000_RCTL_CFIEN; reg |= E1000_RCTL_VFE; E1000_WRITE_REG(hw, E1000_RCTL, reg); - - /* Update the frame size */ - E1000_WRITE_REG(&adapter->hw, E1000_RLPML, - adapter->max_frame_size + VLAN_TAG_SIZE); } static void From 37270a177d8c215612973ae21f1bee31c6c3711c Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 21 Feb 2013 00:26:31 +0000 Subject: [PATCH 0317/1476] No longer need splhigh() since locking was done, delete it and comments about it. --- sys/dev/ppc/ppc_isa.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/sys/dev/ppc/ppc_isa.c b/sys/dev/ppc/ppc_isa.c index 14424a3cc86..a40fc8e8ef3 100644 --- a/sys/dev/ppc/ppc_isa.c +++ b/sys/dev/ppc/ppc_isa.c @@ -141,7 +141,7 @@ ppc_isa_write(device_t dev, char *buf, int len, int how) { struct ppc_data *ppc = device_get_softc(dev); char ecr, ecr_sav, ctr, ctr_sav; - int s, error = 0; + int error = 0; int spin; PPC_ASSERT_LOCKED(ppc); @@ -190,12 +190,6 @@ ppc_isa_write(device_t dev, char *buf, int len, int how) w_ecr(ppc, ecr); ecr = r_ecr(ppc); - /* enter splhigh() not to be preempted - * by the dma interrupt, we may miss - * the wakeup otherwise - */ - s = splhigh(); - ppc->ppc_dmastat = PPC_DMA_INIT; /* enable interrupts */ @@ -221,8 +215,6 @@ ppc_isa_write(device_t dev, char *buf, int len, int how) "ppcdma", 0); } while (error == EWOULDBLOCK); - splx(s); - if (error) { #ifdef PPC_DEBUG printf("i"); From 1eb7e5fe859d466fb67255b868647cea41bbc28d Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 21 Feb 2013 00:27:51 +0000 Subject: [PATCH 0318/1476] Replace splhigh() with critical_enter()/leave() to ensure we write the config mode unlock sequence quickly enough. This likely isn't too critical, since splhigh() has been a noop for a decade... --- sys/dev/ppc/ppc.c | 43 ++++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/sys/dev/ppc/ppc.c b/sys/dev/ppc/ppc.c index 5da180cc592..6c59e02d5b8 100644 --- a/sys/dev/ppc/ppc.c +++ b/sys/dev/ppc/ppc.c @@ -74,6 +74,22 @@ static void ppcintr(void *arg); #define DEVTOSOFTC(dev) ((struct ppc_data *)device_get_softc(dev)) +/* + * We use critical enter/leave for the simple config locking needed to + * detect the devices. We just want to make sure that both of our writes + * happen without someone else also writing to those config registers. Since + * we just do this at startup, Giant keeps multiple threads from executing, + * and critical_enter() then is all that's needed to keep us from being preempted + * during the critical sequences with the hardware. + * + * Note: this doesn't prevent multiple threads from putting the chips into + * config mode, but since we only do that to detect the type at startup the + * extra overhead isn't needed since Giant protects us from multiple entry + * and no other code changes these registers. + */ +#define PPC_CONFIG_LOCK(ppc) critical_enter() +#define PPC_CONFIG_UNLOCK(ppc) critical_leave() + devclass_t ppc_devclass; const char ppc_driver_name[] = "ppc"; @@ -689,7 +705,7 @@ ppc_pc873xx_detect(struct ppc_data *ppc, int chipset_mode) /* XXX mode never for static int ppc_smc37c66xgt_detect(struct ppc_data *ppc, int chipset_mode) { - int s, i; + int i; u_char r; int type = -1; int csr = SMC66x_CSR; /* initial value is 0x3F0 */ @@ -702,11 +718,10 @@ ppc_smc37c66xgt_detect(struct ppc_data *ppc, int chipset_mode) /* * Detection: enter configuration mode and read CRD register. */ - - s = splhigh(); + PPC_CONFIG_LOCK(ppc); outb(csr, SMC665_iCODE); outb(csr, SMC665_iCODE); - splx(s); + PPC_CONFIG_UNLOCK(ppc); outb(csr, 0xd); if (inb(cio) == 0x65) { @@ -715,10 +730,10 @@ ppc_smc37c66xgt_detect(struct ppc_data *ppc, int chipset_mode) } for (i = 0; i < 2; i++) { - s = splhigh(); + PPC_CONFIG_LOCK(ppc); outb(csr, SMC666_iCODE); outb(csr, SMC666_iCODE); - splx(s); + PPC_CONFIG_UNLOCK(ppc); outb(csr, 0xd); if (inb(cio) == 0x66) { @@ -734,16 +749,20 @@ config: /* * If chipset not found, do not continue. */ - if (type == -1) + if (type == -1) { + outb(csr, 0xaa); /* end config mode */ return (-1); + } /* select CR1 */ outb(csr, 0x1); /* read the port's address: bits 0 and 1 of CR1 */ r = inb(cio) & SMC_CR1_ADDR; - if (port_address[(int)r] != ppc->ppc_base) + if (port_address[(int)r] != ppc->ppc_base) { + outb(csr, 0xaa); /* end config mode */ return (-1); + } ppc->ppc_model = type; @@ -881,8 +900,7 @@ end_detect: outb(cio, (r | SMC_CR4_EPPTYPE)); } - /* end config mode */ - outb(csr, 0xaa); + outb(csr, 0xaa); /* end config mode */ ppc->ppc_type = PPC_TYPE_SMCLIKE; ppc_smclike_setmode(ppc, chipset_mode); @@ -897,13 +915,12 @@ end_detect: static int ppc_smc37c935_detect(struct ppc_data *ppc, int chipset_mode) { - int s; int type = -1; - s = splhigh(); + PPC_CONFIG_LOCK(ppc); outb(SMC935_CFG, 0x55); /* enter config mode */ outb(SMC935_CFG, 0x55); - splx(s); + PPC_CONFIG_UNLOCK(ppc); outb(SMC935_IND, SMC935_ID); /* check device id */ if (inb(SMC935_DAT) == 0x2) From 34bed74372d0d1b0ee7dbeb622583f483bfff4ff Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 21 Feb 2013 00:36:12 +0000 Subject: [PATCH 0319/1476] Kill now-bogus splhigh() -- it is a nop --- sys/pci/ncr.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sys/pci/ncr.c b/sys/pci/ncr.c index ead7d4389c0..123b6843b80 100644 --- a/sys/pci/ncr.c +++ b/sys/pci/ncr.c @@ -5544,7 +5544,6 @@ static void ncr_exception (ncb_p np) ** Freeze system to be able to read the messages. */ printf ("ncr: fatal error: system halted - press reset to reboot ..."); - (void) splhigh(); for (;;); #endif From 7fe826349c33def572b85e0cc004c6302c1aaa11 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 21 Feb 2013 00:40:08 +0000 Subject: [PATCH 0320/1476] Fix broken usage of splhigh() by removing it. --- sys/x86/isa/atrtc.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/sys/x86/isa/atrtc.c b/sys/x86/isa/atrtc.c index 29800983d50..b42beac5825 100644 --- a/sys/x86/isa/atrtc.c +++ b/sys/x86/isa/atrtc.c @@ -328,7 +328,6 @@ static int atrtc_gettime(device_t dev, struct timespec *ts) { struct clocktime ct; - int s; /* Look if we have a RTC present and the time is valid */ if (!(rtcin(RTC_STATUSD) & RTCSD_PWR)) { @@ -338,11 +337,8 @@ atrtc_gettime(device_t dev, struct timespec *ts) /* wait for time update to complete */ /* If RTCSA_TUP is zero, we have at least 244us before next update */ - s = splhigh(); - while (rtcin(RTC_STATUSA) & RTCSA_TUP) { - splx(s); - s = splhigh(); - } + while (rtcin(RTC_STATUSA) & RTCSA_TUP) + continue; ct.nsec = 0; ct.sec = readrtc(RTC_SEC); ct.min = readrtc(RTC_MIN); From e1a1297625a34acf94cb8818a506c53cfd529500 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 21 Feb 2013 02:34:04 +0000 Subject: [PATCH 0321/1476] The other giant locked storage drivers have removed splbio(), for the most part, so remove it here too. Anybody locking this driver will need far more than locks where splbio() were, so remove these nops. --- sys/dev/mcd/mcd.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/sys/dev/mcd/mcd.c b/sys/dev/mcd/mcd.c index 86e40c47443..3e9617de70e 100644 --- a/sys/dev/mcd/mcd.c +++ b/sys/dev/mcd/mcd.c @@ -289,7 +289,6 @@ static void mcdstrategy(struct bio *bp) { struct mcd_softc *sc; - int s; sc = (struct mcd_softc *)bp->bio_dev->si_drv1; @@ -318,9 +317,7 @@ mcdstrategy(struct bio *bp) bp->bio_resid = 0; /* queue it */ - s = splbio(); bioq_disksort(&sc->data.head, bp); - splx(s); /* now check whether we can perform processing */ mcd_start(sc); @@ -338,10 +335,8 @@ static void mcd_start(struct mcd_softc *sc) { struct bio *bp; - int s = splbio(); if (sc->data.flags & MCDMBXBSY) { - splx(s); return; } @@ -350,10 +345,8 @@ mcd_start(struct mcd_softc *sc) /* block found to process, dequeue */ /*MCD_TRACE("mcd_start: found block bp=0x%x\n",bp,0,0,0);*/ sc->data.flags |= MCDMBXBSY; - splx(s); } else { /* nothing to do */ - splx(s); return; } From 62c658aa9f7f9953d18259a12e110d65c30c4102 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 21 Feb 2013 02:40:20 +0000 Subject: [PATCH 0322/1476] Most other giant locked storage drivers in the tree don't use splsoftclock to note the need for future locking, so remove it from here. --- sys/pci/ncr.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sys/pci/ncr.c b/sys/pci/ncr.c index 123b6843b80..ee8c2bc79ac 100644 --- a/sys/pci/ncr.c +++ b/sys/pci/ncr.c @@ -6396,12 +6396,8 @@ static nccb_p ncr_get_nccb (ncb_p np, u_long target, u_long lun) { lcb_p lp; - int s; nccb_p cp = NULL; - /* Keep our timeout handler out */ - s = splsoftclock(); - /* ** Lun structure available ? */ @@ -6434,7 +6430,6 @@ static nccb_p ncr_get_nccb } cp->magic = 1; } - splx(s); return (cp); } From ffc72591b1f5871a1871caa0f0b56ec10faeb8d0 Mon Sep 17 00:00:00 2001 From: Jamie Gritton Date: Thu, 21 Feb 2013 02:41:37 +0000 Subject: [PATCH 0323/1476] Don't worry if a module is already loaded when looking for a fstype to mount (possible in a race condition). Reviewed by: kib MFC after: 1 week --- sys/kern/vfs_init.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sys/kern/vfs_init.c b/sys/kern/vfs_init.c index 8172f18ed2b..eab48fbea79 100644 --- a/sys/kern/vfs_init.c +++ b/sys/kern/vfs_init.c @@ -122,7 +122,7 @@ struct vfsconf * vfs_byname_kld(const char *fstype, struct thread *td, int *error) { struct vfsconf *vfsp; - int fileid; + int fileid, loaded; vfsp = vfs_byname(fstype); if (vfsp != NULL) @@ -130,13 +130,17 @@ vfs_byname_kld(const char *fstype, struct thread *td, int *error) /* Try to load the respective module. */ *error = kern_kldload(td, fstype, &fileid); + loaded = (*error == 0); + if (*error == EEXIST) + *error = 0; if (*error) return (NULL); /* Look up again to see if the VFS was loaded. */ vfsp = vfs_byname(fstype); if (vfsp == NULL) { - (void)kern_kldunload(td, fileid, LINKER_UNLOAD_FORCE); + if (loaded) + (void)kern_kldunload(td, fileid, LINKER_UNLOAD_FORCE); *error = ENODEV; return (NULL); } From b96f7e0a60239f2b434bece369aeee2de12c91a1 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 21 Feb 2013 02:43:44 +0000 Subject: [PATCH 0324/1476] The request queue is already locked, so we don't need the splsofclock/splx here to note future work. --- sys/fs/nfsclient/nfs_clstate.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sys/fs/nfsclient/nfs_clstate.c b/sys/fs/nfsclient/nfs_clstate.c index a7741031caf..c62000cac3d 100644 --- a/sys/fs/nfsclient/nfs_clstate.c +++ b/sys/fs/nfsclient/nfs_clstate.c @@ -1888,7 +1888,7 @@ nfscl_recover(struct nfsclclient *clp, struct ucred *cred, NFSPROC_T *p) struct nfsreq *rep; u_int64_t len; u_int32_t delegtype = NFSV4OPEN_DELEGATEWRITE, mode; - int i, igotlock = 0, error, trycnt, firstlock, s; + int i, igotlock = 0, error, trycnt, firstlock; struct nfscllayout *lyp, *nlyp; /* @@ -1945,14 +1945,12 @@ nfscl_recover(struct nfsclclient *clp, struct ucred *cred, NFSPROC_T *p) * This will be translated to NFSERR_STALEDONTRECOVER when * R_DONTRECOVER is set. */ - s = splsoftclock(); NFSLOCKREQ(); TAILQ_FOREACH(rep, &nfsd_reqq, r_chain) { if (rep->r_nmp == nmp) rep->r_flags |= R_DONTRECOVER; } NFSUNLOCKREQ(); - splx(s); /* * Now, mark all delegations "need reclaim". From 054eace83f8c557d90574d646796234fd69ca789 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Thu, 21 Feb 2013 02:52:13 +0000 Subject: [PATCH 0325/1476] Remove this unneeded printf(), sorry! --- sys/dev/ath/ath_hal/ar5416/ar5416_attach.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c b/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c index 30d1161a546..6dc5a6106d4 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c @@ -254,10 +254,6 @@ ar5416InitState(struct ath_hal_5416 *ahp5416, uint16_t devid, HAL_SOFTC sc, AH5212(ah)->ah_txTrigLev = (AR_FTRIG_512B >> AR_FTRIG_S); AH5212(ah)->ah_maxTxTrigLev = ((4096 / 64) - 1); } - ath_hal_printf(ah, "%s: trigLev=%d, maxTxTrigLev=%d\n", - __func__, - AH5212(ah)->ah_txTrigLev, - AH5212(ah)->ah_maxTxTrigLev); #undef AR_FTRIG_512B } From 4a502c332a307838f537502ce7f791054ad962ed Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Thu, 21 Feb 2013 06:18:40 +0000 Subject: [PATCH 0326/1476] Add a new option to limit the maximum size of aggregates. The default is to limit them to what the hardware is capable of. Add sysctl twiddles for both the non-RTS and RTS protected aggregate generation. Whilst here, add some comments about stuff that I've discovered during my exploration of the TX aggregate / delimiter setup path from the reference driver. --- sys/dev/ath/if_ath.c | 1 + sys/dev/ath/if_ath_sysctl.c | 8 +++++++- sys/dev/ath/if_ath_tx.h | 5 +++++ sys/dev/ath/if_ath_tx_ht.c | 19 ++++++++++++++++++- sys/dev/ath/if_athvar.h | 1 + 5 files changed, 32 insertions(+), 2 deletions(-) diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 6f08fa79b81..4388399353d 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -799,6 +799,7 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) sc->sc_hwq_limit = ATH_AGGR_MIN_QDEPTH; sc->sc_tid_hwq_lo = ATH_AGGR_SCHED_LOW; sc->sc_tid_hwq_hi = ATH_AGGR_SCHED_HIGH; + sc->sc_aggr_limit = ATH_AGGR_MAXSIZE; /* * Check if the hardware requires PCI register serialisation. diff --git a/sys/dev/ath/if_ath_sysctl.c b/sys/dev/ath/if_ath_sysctl.c index abb180b7717..bce4ee603cb 100644 --- a/sys/dev/ath/if_ath_sysctl.c +++ b/sys/dev/ath/if_ath_sysctl.c @@ -704,7 +704,7 @@ ath_sysctlattach(struct ath_softc *sc) SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "hwq_limit", CTLFLAG_RW, &sc->sc_hwq_limit, 0, - ""); + "Hardware queue depth before software-queuing TX frames"); SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "tid_hwq_lo", CTLFLAG_RW, &sc->sc_tid_hwq_lo, 0, ""); @@ -712,6 +712,12 @@ ath_sysctlattach(struct ath_softc *sc) "tid_hwq_hi", CTLFLAG_RW, &sc->sc_tid_hwq_hi, 0, ""); + /* Aggregate length twiddles */ + SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "aggr_limit", CTLFLAG_RW, &sc->sc_aggr_limit, 0, ""); + SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "rts_aggr_limit", CTLFLAG_RW, &sc->sc_rts_aggr_limit, 0, ""); + SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "txq_data_minfree", CTLFLAG_RW, &sc->sc_txq_data_minfree, 0, "Minimum free buffers before adding a data frame" diff --git a/sys/dev/ath/if_ath_tx.h b/sys/dev/ath/if_ath_tx.h index 1397faaf2fe..1437d7fb9a5 100644 --- a/sys/dev/ath/if_ath_tx.h +++ b/sys/dev/ath/if_ath_tx.h @@ -79,6 +79,11 @@ #define BAW_WITHIN(_start, _bawsz, _seqno) \ ((((_seqno) - (_start)) & 4095) < (_bawsz)) +/* + * Maximum aggregate size + */ +#define ATH_AGGR_MAXSIZE 65530 + extern void ath_freetx(struct mbuf *m); extern void ath_tx_node_flush(struct ath_softc *sc, struct ath_node *an); extern void ath_tx_txq_drain(struct ath_softc *sc, struct ath_txq *txq); diff --git a/sys/dev/ath/if_ath_tx_ht.c b/sys/dev/ath/if_ath_tx_ht.c index 60a18630f3d..022a00a4546 100644 --- a/sys/dev/ath/if_ath_tx_ht.c +++ b/sys/dev/ath/if_ath_tx_ht.c @@ -346,12 +346,19 @@ ath_compute_num_delims(struct ath_softc *sc, struct ath_buf *first_bf, * crypto hardware catch up. This could be tuned per-MAC and * per-rate, but for now we'll simply assume encryption is * always enabled. + * + * Also note that the Atheros reference driver inserts two + * delimiters by default for pre-AR9380 peers. This will + * include "that" required delimiter. */ ndelim += ATH_AGGR_ENCRYPTDELIM; /* * For AR9380, there's a minimum number of delimeters * required when doing RTS. + * + * XXX TODO: this is only needed if (a) RTS/CTS is enabled, and + * XXX (b) this is the first sub-frame in the aggregate. */ if (sc->sc_use_ent && (sc->sc_ent_cfg & AH_ENT_RTSCTS_DELIM_WAR) && ndelim < AH_FIRST_DESC_NDELIMS) @@ -420,9 +427,12 @@ ath_compute_num_delims(struct ath_softc *sc, struct ath_buf *first_bf, static int ath_get_aggr_limit(struct ath_softc *sc, struct ath_buf *bf) { - int amin = 65530; + int amin = ATH_AGGR_MAXSIZE; int i; + if (sc->sc_aggr_limit > 0 && sc->sc_aggr_limit < ATH_AGGR_MAXSIZE) + amin = sc->sc_aggr_limit; + for (i = 0; i < ATH_RC_NUM; i++) { if (bf->bf_state.bfs_rc[i].tries == 0) continue; @@ -488,6 +498,13 @@ ath_rateseries_setup(struct ath_softc *sc, struct ieee80211_node *ni, * XXX It's overridden in the HAL rate scenario function * XXX for now. */ + /* + * XXX TODO: When the NIC is capable of three stream TX, + * transmit 1/2 stream rates on two streams. + * + * This reduces the power consumption of the NIC and + * keeps it within the PCIe slot power limits. + */ series[i].ChSel = sc->sc_txchainmask; if (flags & (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA)) diff --git a/sys/dev/ath/if_athvar.h b/sys/dev/ath/if_athvar.h index 36923ccfe0a..09d03bc506f 100644 --- a/sys/dev/ath/if_athvar.h +++ b/sys/dev/ath/if_athvar.h @@ -718,6 +718,7 @@ struct ath_softc { int sc_txchainmask; /* currently configured TX chainmask */ int sc_rxchainmask; /* currently configured RX chainmask */ int sc_rts_aggr_limit; /* TX limit on RTS aggregates */ + int sc_aggr_limit; /* TX limit on all aggregates */ /* Queue limits */ From 85e51e49180a2e3e38b2202c0d243f480f866ee8 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 21 Feb 2013 06:38:24 +0000 Subject: [PATCH 0327/1476] Correct comment about use of pmtimer, and the real reason it isn't used or desirable for amd64. --- sys/x86/isa/clock.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sys/x86/isa/clock.c b/sys/x86/isa/clock.c index 6c69759ac67..232c913674f 100644 --- a/sys/x86/isa/clock.c +++ b/sys/x86/isa/clock.c @@ -478,9 +478,10 @@ i8254_restore(void) * * This function is called from pmtimer_resume() to restore all the timers. * This should not be necessary, but there are broken laptops that do not - * restore all the timers on resume. - * As long as pmtimer is not part of amd64 suport, skip this for the amd64 - * case. + * restore all the timers on resume. The APM spec was at best vague on the + * subject. + * pmtimer is used only with the old APM power management, and not with + * acpi, which is required for amd64, so skip it in that case. */ void timer_restore(void) From a54ecf784a3cd3bfbb1d230f6b4a0b65d4a1cb28 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Thu, 21 Feb 2013 06:38:49 +0000 Subject: [PATCH 0328/1476] Add an option to allow the minimum number of delimiters to be tweaked. This is primarily for debugging purposes. Tested: * AR5416, STA mode --- sys/dev/ath/if_ath.c | 1 + sys/dev/ath/if_ath_sysctl.c | 11 +++++++++-- sys/dev/ath/if_ath_tx_ht.c | 7 +++++++ sys/dev/ath/if_athvar.h | 1 + 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 4388399353d..98c219bb76c 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -800,6 +800,7 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) sc->sc_tid_hwq_lo = ATH_AGGR_SCHED_LOW; sc->sc_tid_hwq_hi = ATH_AGGR_SCHED_HIGH; sc->sc_aggr_limit = ATH_AGGR_MAXSIZE; + sc->sc_delim_min_pad = 0; /* * Check if the hardware requires PCI register serialisation. diff --git a/sys/dev/ath/if_ath_sysctl.c b/sys/dev/ath/if_ath_sysctl.c index bce4ee603cb..bbd1fe82571 100644 --- a/sys/dev/ath/if_ath_sysctl.c +++ b/sys/dev/ath/if_ath_sysctl.c @@ -714,9 +714,16 @@ ath_sysctlattach(struct ath_softc *sc) /* Aggregate length twiddles */ SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "aggr_limit", CTLFLAG_RW, &sc->sc_aggr_limit, 0, ""); + "aggr_limit", CTLFLAG_RW, &sc->sc_aggr_limit, 0, + "Maximum A-MPDU size, or 0 for 'default'"); SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "rts_aggr_limit", CTLFLAG_RW, &sc->sc_rts_aggr_limit, 0, ""); + "rts_aggr_limit", CTLFLAG_RW, &sc->sc_rts_aggr_limit, 0, + "Maximum A-MPDU size for RTS-protected frames, or '0' " + "for default"); + SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "delim_min_pad", CTLFLAG_RW, &sc->sc_delim_min_pad, 0, + "Enforce a minimum number of delimiters per A-MPDU " + " sub-frame"); SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "txq_data_minfree", CTLFLAG_RW, &sc->sc_txq_data_minfree, diff --git a/sys/dev/ath/if_ath_tx_ht.c b/sys/dev/ath/if_ath_tx_ht.c index 022a00a4546..7245d060fbc 100644 --- a/sys/dev/ath/if_ath_tx_ht.c +++ b/sys/dev/ath/if_ath_tx_ht.c @@ -364,6 +364,13 @@ ath_compute_num_delims(struct ath_softc *sc, struct ath_buf *first_bf, && ndelim < AH_FIRST_DESC_NDELIMS) ndelim = AH_FIRST_DESC_NDELIMS; + /* + * If sc_delim_min_pad is non-zero, enforce it as the minimum + * pad delimiter count. + */ + if (sc->sc_delim_min_pad != 0) + ndelim = MAX(ndelim, sc->sc_delim_min_pad); + DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR, "%s: pktlen=%d, ndelim=%d, mpdudensity=%d\n", __func__, pktlen, ndelim, mpdudensity); diff --git a/sys/dev/ath/if_athvar.h b/sys/dev/ath/if_athvar.h index 09d03bc506f..1b6e160dc10 100644 --- a/sys/dev/ath/if_athvar.h +++ b/sys/dev/ath/if_athvar.h @@ -719,6 +719,7 @@ struct ath_softc { int sc_rxchainmask; /* currently configured RX chainmask */ int sc_rts_aggr_limit; /* TX limit on RTS aggregates */ int sc_aggr_limit; /* TX limit on all aggregates */ + int sc_delim_min_pad; /* Minimum delimiter count */ /* Queue limits */ From ebf43195031bef307e8b06b484146401c809203c Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 21 Feb 2013 07:16:40 +0000 Subject: [PATCH 0329/1476] Locking for todr got pushed down into inittodr and the client libraries it calls (although some might not be doing it right). We are serialized right now by giant as well. This means the splsoftclock are now an anachronism that has no benefit, even marking where locking needs to happen. Remove them. --- sys/i386/isa/pmtimer.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/sys/i386/isa/pmtimer.c b/sys/i386/isa/pmtimer.c index d8e6d1f7647..b5a030266db 100644 --- a/sys/i386/isa/pmtimer.c +++ b/sys/i386/isa/pmtimer.c @@ -82,26 +82,21 @@ static struct timeval diff_time; static int pmtimer_suspend(device_t dev) { - int pl; - pl = splsoftclock(); microtime(&diff_time); inittodr(0); microtime(&suspend_time); timevalsub(&diff_time, &suspend_time); - splx(pl); return (0); } static int pmtimer_resume(device_t dev) { - int pl; u_int second, minute, hour; struct timeval resume_time, tmp_time; /* modified for adjkerntz */ - pl = splsoftclock(); timer_restore(); /* restore the all timers */ inittodr(0); /* adjust time to RTC */ microtime(&resume_time); @@ -118,16 +113,13 @@ pmtimer_resume(device_t dev) timevalsub(&resume_time, &suspend_time); /* Fixup the calltodo list with the delta time. */ adjust_timeout_calltodo(&resume_time); -#endif /* PMTIMER_FIXUP_CALLTODOK */ - splx(pl); -#ifndef PMTIMER_FIXUP_CALLTODO - second = resume_time.tv_sec - suspend_time.tv_sec; -#else /* PMTIMER_FIXUP_CALLTODO */ /* * We've already calculated resume_time to be the delta between * the suspend and the resume. */ second = resume_time.tv_sec; +#else /* !PMTIMER_FIXUP_CALLTODO */ + second = resume_time.tv_sec - suspend_time.tv_sec; #endif /* PMTIMER_FIXUP_CALLTODO */ hour = second / 3600; second %= 3600; From b441301d0589e5002191b0220bb8936a17dcb2db Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 21 Feb 2013 07:19:50 +0000 Subject: [PATCH 0330/1476] Remove incorrect comment about splsoftclock. --- sys/dev/si/si.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sys/dev/si/si.c b/sys/dev/si/si.c index 416771cf1c7..c9d1c831148 100644 --- a/sys/dev/si/si.c +++ b/sys/dev/si/si.c @@ -1446,7 +1446,6 @@ si_start(struct tty *tp) #if 0 /* - * Note: called at splsoftclock from the timeout code * This has to deal with two things... cause wakeups while waiting for * tty drains on last process exit, and call l_start at about the right * time for protocols like ppp. From de2d9111ecb81e215b7484eb5b1230b291e1e0b5 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Thu, 21 Feb 2013 08:42:40 +0000 Subject: [PATCH 0331/1476] Be slightly more paranoid with the TX DMA buffer maximum threshold. Specifically - never jack the TX FIFO threshold up to the absolute maximum; always leave enough space for two DMA transactions to appear. This is a paranoia from the Linux ath9k driver. It can't hurt. Obtained from: Linux ath9k --- sys/dev/ath/ath_hal/ar5416/ar5416_attach.c | 21 +++++++++++++++++++-- sys/dev/ath/ath_hal/ar5416/ar5416_reset.c | 4 ++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c b/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c index 6dc5a6106d4..c26ca4bb783 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c @@ -244,9 +244,23 @@ ar5416InitState(struct ath_hal_5416 *ahp5416, uint16_t devid, HAL_SOFTC sc, /* Set overridable ANI methods */ AH5212(ah)->ah_aniControl = ar5416AniControl; - /* Default FIFO Trigger levels */ + /* + * Default FIFO Trigger levels + * + * These define how filled the TX FIFO needs to be before + * the baseband begins to be given some data. + * + * To be paranoid, we ensure that the TX trigger level always + * has at least enough space for two TX DMA to occur. + * The TX DMA size is currently hard-coded to AR_TXCFG_DMASZ_128B. + * That means we need to leave at least 256 bytes available in + * the TX DMA FIFO. + */ #define AR_FTRIG_512B 0x00000080 // 5 bits total - /* AR9285/AR9271 need to use half the TX FIFOs */ + /* + * AR9285/AR9271 have half the size TX FIFO compared to + * other devices + */ if (AR_SREV_KITE(ah) || AR_SREV_9271(ah)) { AH5212(ah)->ah_txTrigLev = (AR_FTRIG_256B >> AR_FTRIG_S); AH5212(ah)->ah_maxTxTrigLev = ((2048 / 64) - 1); @@ -255,6 +269,9 @@ ar5416InitState(struct ath_hal_5416 *ahp5416, uint16_t devid, HAL_SOFTC sc, AH5212(ah)->ah_maxTxTrigLev = ((4096 / 64) - 1); } #undef AR_FTRIG_512B + + /* And now leave some headspace - 256 bytes */ + AH5212(ah)->ah_maxTxTrigLev -= 4; } uint32_t diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c b/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c index 51ac0a1a2da..75df5e995b4 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c @@ -570,6 +570,10 @@ ar5416InitDMA(struct ath_hal *ah) /* * let mac dma writes be in 128 byte chunks */ + /* + * XXX If you change this, you must change the headroom + * assigned in ah_maxTxTrigLev - see ar5416InitState(). + */ OS_REG_WRITE(ah, AR_RXCFG, (OS_REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_DMASZ_MASK) | AR_RXCFG_DMASZ_128B); From d0741ed4c3030d4eeaed706ee31321743d2ec70c Mon Sep 17 00:00:00 2001 From: Gleb Smirnoff Date: Thu, 21 Feb 2013 12:40:52 +0000 Subject: [PATCH 0332/1476] Fix build. --- sys/dev/ppc/ppc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/dev/ppc/ppc.c b/sys/dev/ppc/ppc.c index 6c59e02d5b8..e1edc4d87ae 100644 --- a/sys/dev/ppc/ppc.c +++ b/sys/dev/ppc/ppc.c @@ -75,7 +75,7 @@ static void ppcintr(void *arg); #define DEVTOSOFTC(dev) ((struct ppc_data *)device_get_softc(dev)) /* - * We use critical enter/leave for the simple config locking needed to + * We use critical enter/exit for the simple config locking needed to * detect the devices. We just want to make sure that both of our writes * happen without someone else also writing to those config registers. Since * we just do this at startup, Giant keeps multiple threads from executing, @@ -88,7 +88,7 @@ static void ppcintr(void *arg); * and no other code changes these registers. */ #define PPC_CONFIG_LOCK(ppc) critical_enter() -#define PPC_CONFIG_UNLOCK(ppc) critical_leave() +#define PPC_CONFIG_UNLOCK(ppc) critical_exit() devclass_t ppc_devclass; const char ppc_driver_name[] = "ppc"; From c43b22be02a16eb68f68fee095c965a8c3b580d5 Mon Sep 17 00:00:00 2001 From: Gleb Smirnoff Date: Thu, 21 Feb 2013 12:52:18 +0000 Subject: [PATCH 0333/1476] Fix build. --- sys/pci/ncr.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sys/pci/ncr.c b/sys/pci/ncr.c index ee8c2bc79ac..70b08c70aa2 100644 --- a/sys/pci/ncr.c +++ b/sys/pci/ncr.c @@ -6425,7 +6425,6 @@ static nccb_p ncr_get_nccb if (cp != NULL) { if (cp->magic) { printf("%s: Bogus free cp found\n", ncr_name(np)); - splx(s); return (NULL); } cp->magic = 1; From 22e61bc2c1b90bdb32ca875a41ec3a27540a242b Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 21 Feb 2013 15:35:48 +0000 Subject: [PATCH 0334/1476] Use critical_enter/critical_exit around the time sensitive part of this code to depessimize the worst case we've lived with silently and uneventfully for the past 12 years. Add a comment about a refinement for those needing more assurance of accuracy. Fix ddb's show rtc command deadlock potential when debugging rtc code by not taking the lock if we're in the debugger. If you need a thumb to count the number of people that have encountered this, I'd be surprised. Submitted by: bde --- sys/x86/isa/atrtc.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/sys/x86/isa/atrtc.c b/sys/x86/isa/atrtc.c index b42beac5825..c6a6f8c9a23 100644 --- a/sys/x86/isa/atrtc.c +++ b/sys/x86/isa/atrtc.c @@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -52,8 +53,8 @@ __FBSDID("$FreeBSD$"); #include #include "clock_if.h" -#define RTC_LOCK mtx_lock_spin(&clock_lock) -#define RTC_UNLOCK mtx_unlock_spin(&clock_lock) +#define RTC_LOCK do { if (!kdb_active) mtx_lock_spin(&clock_lock); } while (0) +#define RTC_UNLOCK do { if (!kdb_active) mtx_unlock_spin(&clock_lock); } while (0) int atrtcclock_disable = 0; @@ -335,10 +336,16 @@ atrtc_gettime(device_t dev, struct timespec *ts) return (EINVAL); } - /* wait for time update to complete */ - /* If RTCSA_TUP is zero, we have at least 244us before next update */ + /* + * wait for time update to complete + * If RTCSA_TUP is zero, we have at least 244us before next update. + * This is fast enough on most hardware, but a refinement would be + * to make sure that no more than 240us pass after we start reading, + * and try again if so. + */ while (rtcin(RTC_STATUSA) & RTCSA_TUP) continue; + critical_enter(); ct.nsec = 0; ct.sec = readrtc(RTC_SEC); ct.min = readrtc(RTC_MIN); @@ -352,6 +359,7 @@ atrtc_gettime(device_t dev, struct timespec *ts) #else ct.year += 2000; #endif + critical_exit(); /* Set dow = -1 because some clocks don't set it correctly. */ ct.dow = -1; return (clock_ct_to_ts(&ct, ts)); From 07b9a28adb3b553a4986a351961e0e183dcf315b Mon Sep 17 00:00:00 2001 From: Sergey Kandaurov Date: Thu, 21 Feb 2013 15:41:09 +0000 Subject: [PATCH 0335/1476] In the EXAMPLES section: append the subsystem regular expression with a typical interface name pattern as devd(8) uses full string match. Discussed with: avg, glebius --- share/man/man4/carp.4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/share/man/man4/carp.4 b/share/man/man4/carp.4 index d051377cb3d..84e87d6edee 100644 --- a/share/man/man4/carp.4 +++ b/share/man/man4/carp.4 @@ -26,7 +26,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 25, 2012 +.Dd February 21, 2013 .Dt CARP 4 .Os .Sh NAME @@ -281,7 +281,7 @@ status change events can be set up by using the following devd.conf rule: .Bd -literal -offset indent notify 0 { match "system" "CARP"; - match "subsystem" "[0-9]+@"; + match "subsystem" "[0-9]+@[0-9a-z]+"; match "type" "(MASTER|BACKUP)"; action "/root/carpcontrol.sh $subsystem $type"; }; From e5ca1ffab55c23f8415cc57f5ae62540181f46b6 Mon Sep 17 00:00:00 2001 From: Andrew Gallatin Date: Thu, 21 Feb 2013 17:00:35 +0000 Subject: [PATCH 0336/1476] Fix tcp_lro_rx_ipv4() for drivers that do not set CSUM_IP_CHECKED. Specifcially, in_cksum_hdr() returns 0 (not 0xffff) when the IPv4 checksum is correct. Without this fix, the tcp_lro code will reject good IPv4 traffic from drivers that do not implement IPv4 header harder csum offload. Sponsored by: Myricom Inc. MFC after: 7 days --- sys/netinet/tcp_lro.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/netinet/tcp_lro.c b/sys/netinet/tcp_lro.c index 3718e4d034a..032d47c2fe7 100644 --- a/sys/netinet/tcp_lro.c +++ b/sys/netinet/tcp_lro.c @@ -333,7 +333,7 @@ tcp_lro_rx_ipv4(struct lro_ctrl *lc, struct mbuf *m, struct ip *ip4, } } else { csum = in_cksum_hdr(ip4); - if (__predict_false((csum ^ 0xffff) != 0)) { + if (__predict_false((csum) != 0)) { lc->lro_bad_csum++; return (TCP_LRO_CANNOT); } From 54d86215281a78e7bca1bead5378d3059e48a525 Mon Sep 17 00:00:00 2001 From: Brooks Davis Date: Thu, 21 Feb 2013 17:16:04 +0000 Subject: [PATCH 0337/1476] Vendor import of NetBSD's (un)vis(3) at 2013-02-21 --- unvis.3 | 35 ++- unvis.c | 6 +- vis.3 | 143 +++++++--- vis.c | 839 ++++++++++++++++++++++++++++++++------------------------ vis.h | 5 +- 5 files changed, 609 insertions(+), 419 deletions(-) diff --git a/unvis.3 b/unvis.3 index 69e1f729a01..b856a730e11 100644 --- a/unvis.3 +++ b/unvis.3 @@ -1,4 +1,4 @@ -.\" $NetBSD: unvis.3,v 1.23 2011/03/17 14:06:29 wiz Exp $ +.\" $NetBSD: unvis.3,v 1.27 2012/12/15 07:34:36 wiz Exp $ .\" .\" Copyright (c) 1989, 1991, 1993 .\" The Regents of the University of California. All rights reserved. @@ -125,15 +125,17 @@ The function has several return codes that must be handled properly. They are: .Bl -tag -width UNVIS_VALIDPUSH -.It Li \&0 (zero) +.It Li \&0 No (zero) Another character is necessary; nothing has been recognized yet. .It Dv UNVIS_VALID A valid character has been recognized and is available at the location -pointed to by cp. +pointed to by +.Fa cp . .It Dv UNVIS_VALIDPUSH A valid character has been recognized and is available at the location -pointed to by cp; however, the character currently passed in should -be passed in again. +pointed to by +.Fa cp ; +however, the character currently passed in should be passed in again. .It Dv UNVIS_NOCHAR A valid sequence was detected, but no character was produced. This return code is necessary to indicate a logical break between characters. @@ -149,7 +151,7 @@ one more time with flag set to to extract any remaining character (the character passed in is ignored). .Pp The -.Ar flag +.Fa flag argument is also used to specify the encoding style of the source. If set to .Dv VIS_HTTPSTYLE @@ -160,7 +162,8 @@ will decode URI strings as specified in RFC 1808. If set to .Dv VIS_HTTP1866 , .Fn unvis -will decode URI strings as specified in RFC 1866. +will decode entity references and numeric character references +as specified in RFC 1866. If set to .Dv VIS_MIMESTYLE , .Fn unvis @@ -168,7 +171,9 @@ will decode MIME Quoted-Printable strings as specified in RFC 2045. If set to .Dv VIS_NOESCAPE , .Fn unvis -will not decode \e quoted characters. +will not decode +.Ql \e +quoted characters. .Pp The following code fragment illustrates a proper use of .Fn unvis . @@ -203,7 +208,7 @@ The functions and .Fn strnunvisx will return \-1 on error and set -.Va errno +.Va errno to: .Bl -tag -width Er .It Bq Er EINVAL @@ -211,7 +216,7 @@ An invalid escape sequence was detected, or the decoder is in an unknown state. .El .Pp In addition the functions -.Fn strnunvis +.Fn strnunvis and .Fn strnunvisx will can also set @@ -242,3 +247,13 @@ and .Fn strnunvisx functions appeared in .Nx 6.0 . +.Sh BUGS +The names +.Dv VIS_HTTP1808 +and +.Dv VIS_HTTP1866 +are wrong. +Percent-encoding was defined in RFC 1738, the original RFC for URL. +RFC 1866 defines HTML 2.0, an application of SGML, from which it +inherits concepts of numeric character references and entity +references. diff --git a/unvis.c b/unvis.c index 6ca4e7376dc..cf0273dfc8c 100644 --- a/unvis.c +++ b/unvis.c @@ -1,4 +1,4 @@ -/* $NetBSD: unvis.c,v 1.40 2012/12/14 21:31:01 christos Exp $ */ +/* $NetBSD: unvis.c,v 1.41 2012/12/15 04:29:53 matt Exp $ */ /*- * Copyright (c) 1989, 1993 @@ -34,7 +34,7 @@ #if 0 static char sccsid[] = "@(#)unvis.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: unvis.c,v 1.40 2012/12/14 21:31:01 christos Exp $"); +__RCSID("$NetBSD: unvis.c,v 1.41 2012/12/15 04:29:53 matt Exp $"); #endif #endif /* LIBC_SCCS and not lint */ @@ -81,7 +81,7 @@ __weak_alias(strnunvisx,_strnunvisx) * RFC 1866 */ static const struct nv { - const char name[7]; + char name[7]; uint8_t value; } nv[] = { { "AElig", 198 }, /* capital AE diphthong (ligature) */ diff --git a/vis.3 b/vis.3 index ea1a84dad64..166316d1f9a 100644 --- a/vis.3 +++ b/vis.3 @@ -1,4 +1,4 @@ -.\" $NetBSD: vis.3,v 1.29 2012/12/14 22:55:59 christos Exp $ +.\" $NetBSD: vis.3,v 1.39 2013/02/20 20:05:26 christos Exp $ .\" .\" Copyright (c) 1989, 1991, 1993 .\" The Regents of the University of California. All rights reserved. @@ -29,7 +29,7 @@ .\" .\" @(#)vis.3 8.1 (Berkeley) 6/9/93 .\" -.Dd December 14, 2012 +.Dd February 19, 2013 .Dt VIS 3 .Os .Sh NAME @@ -39,12 +39,14 @@ .Nm strnvis , .Nm strvisx , .Nm strnvisx , +.Nm strenvisx , .Nm svis , .Nm snvis , .Nm strsvis , .Nm strsnvis , -.Nm strsvisx -.Nm strsnvisx +.Nm strsvisx , +.Nm strsnvisx , +.Nm strsenvisx .Nd visually encode characters .Sh LIBRARY .Lb libc @@ -62,6 +64,8 @@ .Fn strvisx "char *dst" "const char *src" "size_t len" "int flag" .Ft int .Fn strnvisx "char *dst" "size_t dlen" "const char *src" "size_t len" "int flag" +.Ft int +.Fn strenvisx "char *dst" "size_t dlen" "const char *src" "size_t len" "int flag" "int *cerr_ptr" .Ft char * .Fn svis "char *dst" "int c" "int flag" "int nextc" "const char *extra" .Ft char * @@ -74,6 +78,8 @@ .Fn strsvisx "char *dst" "const char *src" "size_t len" "int flag" "const char *extra" .Ft int .Fn strsnvisx "char *dst" "size_t dlen" "const char *src" "size_t len" "int flag" "const char *extra" +.Ft int +.Fn strsenvisx "char *dst" "size_t dlen" "const char *src" "size_t len" "int flag" "const char *extra" "int *cerr_ptr" .Sh DESCRIPTION The .Fn vis @@ -88,11 +94,11 @@ needs no encoding, it is copied in unaltered. The string is null terminated, and a pointer to the end of the string is returned. The maximum length of any encoding is four -characters (not including the trailing +bytes (not including the trailing .Dv NUL ) ; thus, when encoding a set of characters into a buffer, the size of the buffer should -be four times the number of characters encoded, plus one for the trailing +be four times the number of bytes encoded, plus one for the trailing .Dv NUL . The flag parameter is used for altering the default range of characters considered for encoding and for altering the visual @@ -141,16 +147,17 @@ terminate The size of .Fa dst must be four times the number -of characters encoded from +of bytes encoded from .Fa src (plus one for the .Dv NUL ) . Both -forms return the number of characters in dst (not including -the trailing +forms return the number of characters in +.Fa dst +(not including the trailing .Dv NUL ) . The -.Dq n +.Dq Nm n versions of the functions also take an additional argument .Fa dlen that indicates the length of the @@ -158,7 +165,7 @@ that indicates the length of the buffer. If .Fa dlen -is not large enough to fix the converted string then the +is not large enough to fit the converted string then the .Fn strnvis and .Fn strnvisx @@ -166,6 +173,14 @@ functions return \-1 and set .Va errno to .Dv ENOSPC . +The +.Fn strenvisx +function takes an additional argument, +.Fa cerr_ptr , +that is used to pass in and out a multibyte conversion error flag. +This is useful when processing single characters at a time when +it is possible that the locale may be set to something other +than the locale of the characters in the input data. .Pp The functions .Fn svis , @@ -173,16 +188,18 @@ The functions .Fn strsvis , .Fn strsnvis , .Fn strsvisx , +.Fn strsnvisx , and -.Fn strsnvisx +.Fn strsenvisx correspond to .Fn vis , .Fn nvis , .Fn strvis , .Fn strnvis , .Fn strvisx , +.Fn strnvisx , and -.Fn strnvisx +.Fn strenvisx but have an additional argument .Fa extra , pointing to a @@ -213,14 +230,13 @@ and .Fn strnvisx ) , and the type of representation used. By default, all non-graphic characters, -except space, tab, and newline are encoded. -(See -.Xr isgraph 3 . ) +except space, tab, and newline are encoded (see +.Xr isgraph 3 ) . The following flags alter this: .Bl -tag -width VIS_WHITEX .It Dv VIS_GLOB -Also encode magic characters +Also encode the magic characters .Ql ( * , .Ql \&? , .Ql \&[ @@ -242,11 +258,13 @@ Synonym for \&| .Dv VIS_NL . .It Dv VIS_SAFE -Only encode "unsafe" characters. +Only encode +.Dq unsafe +characters. Unsafe means control characters which may cause common terminals to perform unexpected functions. Currently this form allows space, tab, newline, backspace, bell, and -return - in addition to all graphic characters - unencoded. +return \(em in addition to all graphic characters \(em unencoded. .El .Pp (The above flags have no effect for @@ -286,8 +304,8 @@ Use an to represent meta characters (characters with the 8th bit set), and use caret .Ql ^ -to represent control characters see -.Pf ( Xr iscntrl 3 ) . +to represent control characters (see +.Xr iscntrl 3 ) . The following formats are used: .Bl -tag -width xxxxx .It Dv \e^C @@ -334,19 +352,20 @@ Use C-style backslash sequences to represent standard non-printable characters. The following sequences are used to represent the indicated characters: .Bd -unfilled -offset indent -.Li \ea Tn - BEL No (007) -.Li \eb Tn - BS No (010) -.Li \ef Tn - NP No (014) -.Li \en Tn - NL No (012) -.Li \er Tn - CR No (015) -.Li \es Tn - SP No (040) -.Li \et Tn - HT No (011) -.Li \ev Tn - VT No (013) -.Li \e0 Tn - NUL No (000) +.Li \ea Tn \(em BEL No (007) +.Li \eb Tn \(em BS No (010) +.Li \ef Tn \(em NP No (014) +.Li \en Tn \(em NL No (012) +.Li \er Tn \(em CR No (015) +.Li \es Tn \(em SP No (040) +.Li \et Tn \(em HT No (011) +.Li \ev Tn \(em VT No (013) +.Li \e0 Tn \(em NUL No (000) .Ed .Pp -When using this format, the nextc parameter is looked at to determine -if a +When using this format, the +.Fa nextc +parameter is looked at to determine if a .Dv NUL character can be encoded as .Ql \e0 @@ -373,8 +392,8 @@ represents a lower case hexadecimal digit. .It Dv VIS_MIMESTYLE Use MIME Quoted-Printable encoding as described in RFC 2045, only don't break lines and don't handle CRLF. -The form is: -.Ql %XX +The form is +.Ql =XX where .Em X represents an upper case hexadecimal digit. @@ -391,6 +410,41 @@ meta characters as .Ql M-C ) . With this flag set, the encoding is ambiguous and non-invertible. +.Sh MULTIBYTE CHARACTER SUPPORT +These functions support multibyte character input. +The encoding conversion is influenced by the setting of the +.Ev LC_CTYPE +environment variable which defines the set of characters +that can be copied without encoding. +.Pp +When 8-bit data is present in the input, +.Ev LC_CTYPE +must be set to the correct locale or to the C locale. +If the locales of the data and the conversion are mismatched, +multibyte character recognition may fail and encoding will be performed +byte-by-byte instead. +.Pp +As noted above, +.Fa dst +must be four times the number of bytes processed from +.Fa src . +But note that each multibyte character can be up to +.Dv MB_LEN_MAX +bytes +.\" (see +.\" .Xr multibyte 3 ) +so in terms of multibyte characters, +.Fa dst +must be four times +.Dv MB_LEN_MAX +times the number of characters processed from +.Fa src . +.Sh ENVIRONMENT +.Bl -tag -width ".Ev LC_CTYPE" +.It Ev LC_CTYPE +Specify the locale of the input data. +Set to C if the input data locale is unknown. +.El .Sh ERRORS The functions .Fn nvis @@ -406,11 +460,11 @@ and .Fn strsnvisx , will return \-1 when the .Fa dlen -destination buffer length size is not enough to perform the conversion while +destination buffer size is not enough to perform the conversion while setting .Va errno to: -.Bl -tag -width Er +.Bl -tag -width ".Bq Er ENOSPC" .It Bq Er ENOSPC The destination buffer size is not large enough to perform the conversion. .El @@ -418,18 +472,23 @@ The destination buffer size is not large enough to perform the conversion. .Xr unvis 1 , .Xr vis 1 , .Xr glob 3 , +.\" .Xr multibyte 3 , .Xr unvis 3 .Rs .%A T. Berners-Lee .%T Uniform Resource Locators (URL) -.%O RFC1738 +.%O "RFC 1738" +.Re +.Rs +.%T "Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies" +.%O "RFC 2045" .Re .Sh HISTORY The .Fn vis , .Fn strvis , and -.Fa strvisx +.Fn strvisx functions first appeared in .Bx 4.4 . The @@ -448,4 +507,10 @@ The buffer size limited versions of the functions and .Fn strsnvisx Pc appeared in -.Nx 6.0 . +.Nx 6.0 +and +.Fx 9.2 . +Myltibyte character support was added in +.Nx 7.0 +and +.Fx 9.2 . diff --git a/vis.c b/vis.c index 0afc6eaa613..2ba6b5b23d7 100644 --- a/vis.c +++ b/vis.c @@ -1,4 +1,4 @@ -/* $NetBSD: vis.c,v 1.45 2012/12/14 21:38:18 christos Exp $ */ +/* $NetBSD: vis.c,v 1.60 2013/02/21 16:21:20 joerg Exp $ */ /*- * Copyright (c) 1989, 1993 @@ -57,16 +57,23 @@ #include #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: vis.c,v 1.45 2012/12/14 21:38:18 christos Exp $"); +__RCSID("$NetBSD: vis.c,v 1.60 2013/02/21 16:21:20 joerg Exp $"); #endif /* LIBC_SCCS and not lint */ +#ifdef __FBSDID +__FBSDID("$FreeBSD$"); +#define _DIAGASSERT(x) assert(x) +#endif #include "namespace.h" #include +#include #include #include #include #include +#include +#include #ifdef __weak_alias __weak_alias(strvisx,_strvisx) @@ -78,65 +85,66 @@ __weak_alias(strvisx,_strvisx) #include #include -static char *do_svis(char *, size_t *, int, int, int, const char *); +/* + * The reason for going through the trouble to deal with character encodings + * in vis(3), is that we use this to safe encode output of commands. This + * safe encoding varies depending on the character set. For example if we + * display ps output in French, we don't want to display French characters + * as M-foo. + */ + +static wchar_t *do_svis(wchar_t *, wint_t, int, wint_t, const wchar_t *); #undef BELL -#define BELL '\a' +#define BELL L'\a' -#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7') -#define iswhite(c) (c == ' ' || c == '\t' || c == '\n') -#define issafe(c) (c == '\b' || c == BELL || c == '\r') -#define xtoa(c) "0123456789abcdef"[c] -#define XTOA(c) "0123456789ABCDEF"[c] +#define iswoctal(c) (((u_char)(c)) >= L'0' && ((u_char)(c)) <= L'7') +#define iswwhite(c) (c == L' ' || c == L'\t' || c == L'\n') +#define iswsafe(c) (c == L'\b' || c == BELL || c == L'\r') +#define xtoa(c) L"0123456789abcdef"[c] +#define XTOA(c) L"0123456789ABCDEF"[c] -#define MAXEXTRAS 9 +#define MAXEXTRAS 10 -#define MAKEEXTRALIST(flag, extra, orig_str) \ -do { \ - const char *orig = orig_str; \ - const char *o = orig; \ - char *e; \ - while (*o++) \ - continue; \ - extra = malloc((size_t)((o - orig) + MAXEXTRAS)); \ - if (!extra) break; \ - for (o = orig, e = extra; (*e++ = *o++) != '\0';) \ - continue; \ - e--; \ - if (flag & VIS_GLOB) { \ - *e++ = '*'; \ - *e++ = '?'; \ - *e++ = '['; \ - *e++ = '#'; \ - } \ - if (flag & VIS_SP) *e++ = ' '; \ - if (flag & VIS_TAB) *e++ = '\t'; \ - if (flag & VIS_NL) *e++ = '\n'; \ - if ((flag & VIS_NOSLASH) == 0) *e++ = '\\'; \ - *e = '\0'; \ -} while (/*CONSTCOND*/0) +#if !HAVE_NBTOOL_CONFIG_H +#ifndef __NetBSD__ +/* + * On NetBSD MB_LEN_MAX is currently 32 which does not fit on any integer + * integral type and it is probably wrong, since currently the maximum + * number of bytes and character needs is 6. Until this is fixed, the + * loops below are using sizeof(uint64_t) - 1 instead of MB_LEN_MAX, and + * the assertion is commented out. + */ +#ifdef __FreeBSD__ +/* + * On FreeBSD including for CTASSERT only works in kernel + * mode. + */ +#ifndef CTASSERT +#define CTASSERT(x) _CTASSERT(x, __LINE__) +#define _CTASSERT(x, y) __CTASSERT(x, y) +#define __CTASSERT(x, y) typedef char __assert ## y[(x) ? 1 : -1] +#endif +#endif /* __FreeBSD__ */ +CTASSERT(MB_LEN_MAX <= sizeof(uint64_t)); +#endif /* !__NetBSD__ */ +#endif /* * This is do_hvis, for HTTP style (RFC 1808) */ -static char * -do_hvis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra) +static wchar_t * +do_hvis(wchar_t *dst, wint_t c, int flags, wint_t nextc, const wchar_t *extra) { - - if ((isascii(c) && isalnum(c)) + if (iswalnum(c) /* safe */ - || c == '$' || c == '-' || c == '_' || c == '.' || c == '+' + || c == L'$' || c == L'-' || c == L'_' || c == L'.' || c == L'+' /* extra */ - || c == '!' || c == '*' || c == '\'' || c == '(' || c == ')' - || c == ',') { - dst = do_svis(dst, dlen, c, flag, nextc, extra); - } else { - if (dlen) { - if (*dlen < 3) - return NULL; - *dlen -= 3; - } - *dst++ = '%'; + || c == L'!' || c == L'*' || c == L'\'' || c == L'(' || c == L')' + || c == L',') + dst = do_svis(dst, c, flags, nextc, extra); + else { + *dst++ = L'%'; *dst++ = xtoa(((unsigned int)c >> 4) & 0xf); *dst++ = xtoa((unsigned int)c & 0xf); } @@ -148,27 +156,97 @@ do_hvis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra) * This is do_mvis, for Quoted-Printable MIME (RFC 2045) * NB: No handling of long lines or CRLF. */ -static char * -do_mvis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra) +static wchar_t * +do_mvis(wchar_t *dst, wint_t c, int flags, wint_t nextc, const wchar_t *extra) { - if ((c != '\n') && + if ((c != L'\n') && /* Space at the end of the line */ - ((isspace(c) && (nextc == '\r' || nextc == '\n')) || + ((iswspace(c) && (nextc == L'\r' || nextc == L'\n')) || /* Out of range */ - (!isspace(c) && (c < 33 || (c > 60 && c < 62) || c > 126)) || - /* Specific char to be escaped */ - strchr("#$@[\\]^`{|}~", c) != NULL)) { - if (dlen) { - if (*dlen < 3) - return NULL; - *dlen -= 3; - } - *dst++ = '='; + (!iswspace(c) && (c < 33 || (c > 60 && c < 62) || c > 126)) || + /* Specific char to be escaped */ + wcschr(L"#$@[\\]^`{|}~", c) != NULL)) { + *dst++ = L'='; *dst++ = XTOA(((unsigned int)c >> 4) & 0xf); *dst++ = XTOA((unsigned int)c & 0xf); - } else { - dst = do_svis(dst, dlen, c, flag, nextc, extra); + } else + dst = do_svis(dst, c, flags, nextc, extra); + return dst; +} + +/* + * Output single byte of multibyte character. + */ +static wchar_t * +do_mbyte(wchar_t *dst, wint_t c, int flags, wint_t nextc, int iswextra) +{ + if (flags & VIS_CSTYLE) { + switch (c) { + case L'\n': + *dst++ = L'\\'; *dst++ = L'n'; + return dst; + case L'\r': + *dst++ = L'\\'; *dst++ = L'r'; + return dst; + case L'\b': + *dst++ = L'\\'; *dst++ = L'b'; + return dst; + case BELL: + *dst++ = L'\\'; *dst++ = L'a'; + return dst; + case L'\v': + *dst++ = L'\\'; *dst++ = L'v'; + return dst; + case L'\t': + *dst++ = L'\\'; *dst++ = L't'; + return dst; + case L'\f': + *dst++ = L'\\'; *dst++ = L'f'; + return dst; + case L' ': + *dst++ = L'\\'; *dst++ = L's'; + return dst; + case L'\0': + *dst++ = L'\\'; *dst++ = L'0'; + if (iswoctal(nextc)) { + *dst++ = L'0'; + *dst++ = L'0'; + } + return dst; + default: + if (iswgraph(c)) { + *dst++ = L'\\'; + *dst++ = c; + return dst; + } + } } + if (iswextra || ((c & 0177) == L' ') || (flags & VIS_OCTAL)) { + *dst++ = L'\\'; + *dst++ = (u_char)(((u_int32_t)(u_char)c >> 6) & 03) + L'0'; + *dst++ = (u_char)(((u_int32_t)(u_char)c >> 3) & 07) + L'0'; + *dst++ = (c & 07) + L'0'; + } else { + if ((flags & VIS_NOSLASH) == 0) + *dst++ = L'\\'; + + if (c & 0200) { + c &= 0177; + *dst++ = L'M'; + } + + if (iswcntrl(c)) { + *dst++ = L'^'; + if (c == 0177) + *dst++ = L'?'; + else + *dst++ = c + L'@'; + } else { + *dst++ = L'-'; + *dst++ = c; + } + } + return dst; } @@ -176,284 +254,350 @@ do_mvis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra) * This is do_vis, the central code of vis. * dst: Pointer to the destination buffer * c: Character to encode - * flag: Flag word + * flags: Flags word * nextc: The character following 'c' * extra: Pointer to the list of extra characters to be * backslash-protected. */ -static char * -do_svis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra) +static wchar_t * +do_svis(wchar_t *dst, wint_t c, int flags, wint_t nextc, const wchar_t *extra) { - int isextra; - size_t odlen = dlen ? *dlen : 0; + int iswextra, i, shft; + uint64_t bmsk, wmsk; - isextra = strchr(extra, c) != NULL; -#define HAVE(x) \ - do { \ - if (dlen) { \ - if (*dlen < (x)) \ - goto out; \ - *dlen -= (x); \ - } \ - } while (/*CONSTCOND*/0) - if (!isextra && isascii(c) && (isgraph(c) || iswhite(c) || - ((flag & VIS_SAFE) && issafe(c)))) { - HAVE(1); + iswextra = wcschr(extra, c) != NULL; + if (!iswextra && (iswgraph(c) || iswwhite(c) || + ((flags & VIS_SAFE) && iswsafe(c)))) { *dst++ = c; return dst; } - if (flag & VIS_CSTYLE) { - HAVE(2); - switch (c) { - case '\n': - *dst++ = '\\'; *dst++ = 'n'; - return dst; - case '\r': - *dst++ = '\\'; *dst++ = 'r'; - return dst; - case '\b': - *dst++ = '\\'; *dst++ = 'b'; - return dst; - case BELL: - *dst++ = '\\'; *dst++ = 'a'; - return dst; - case '\v': - *dst++ = '\\'; *dst++ = 'v'; - return dst; - case '\t': - *dst++ = '\\'; *dst++ = 't'; - return dst; - case '\f': - *dst++ = '\\'; *dst++ = 'f'; - return dst; - case ' ': - *dst++ = '\\'; *dst++ = 's'; - return dst; - case '\0': - *dst++ = '\\'; *dst++ = '0'; - if (isoctal(nextc)) { - HAVE(2); - *dst++ = '0'; - *dst++ = '0'; - } - return dst; - default: - if (isgraph(c)) { - *dst++ = '\\'; *dst++ = c; - return dst; - } - if (dlen) - *dlen = odlen; - } - } - if (isextra || ((c & 0177) == ' ') || (flag & VIS_OCTAL)) { - HAVE(4); - *dst++ = '\\'; - *dst++ = (u_char)(((u_int32_t)(u_char)c >> 6) & 03) + '0'; - *dst++ = (u_char)(((u_int32_t)(u_char)c >> 3) & 07) + '0'; - *dst++ = (c & 07) + '0'; - } else { - if ((flag & VIS_NOSLASH) == 0) { - HAVE(1); - *dst++ = '\\'; - } - if (c & 0200) { - HAVE(1); - c &= 0177; *dst++ = 'M'; - } - - if (iscntrl(c)) { - HAVE(2); - *dst++ = '^'; - if (c == 0177) - *dst++ = '?'; - else - *dst++ = c + '@'; - } else { - HAVE(2); - *dst++ = '-'; *dst++ = c; - } + /* See comment in istrsenvisx() output loop, below. */ + wmsk = 0; + for (i = sizeof(wmsk) - 1; i >= 0; i--) { + shft = i * NBBY; + bmsk = (uint64_t)0xffLL << shft; + wmsk |= bmsk; + if ((c & wmsk) || i == 0) + dst = do_mbyte(dst, (wint_t)( + (uint64_t)(c & bmsk) >> shft), + flags, nextc, iswextra); } + return dst; -out: - *dlen = odlen; - return NULL; } -typedef char *(*visfun_t)(char *, size_t *, int, int, int, const char *); +typedef wchar_t *(*visfun_t)(wchar_t *, wint_t, int, wint_t, const wchar_t *); /* * Return the appropriate encoding function depending on the flags given. */ static visfun_t -getvisfun(int flag) +getvisfun(int flags) { - if (flag & VIS_HTTPSTYLE) + if (flags & VIS_HTTPSTYLE) return do_hvis; - if (flag & VIS_MIMESTYLE) + if (flags & VIS_MIMESTYLE) return do_mvis; return do_svis; } /* - * isnvis - visually encode characters, also encoding the characters - * pointed to by `extra' + * Expand list of extra characters to not visually encode. */ -static char * -isnvis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra) +static wchar_t * +makeextralist(int flags, const char *src) { - char *nextra = NULL; - visfun_t f; + wchar_t *dst, *d; + size_t len; - _DIAGASSERT(dst != NULL); - _DIAGASSERT(extra != NULL); - MAKEEXTRALIST(flag, nextra, extra); - if (!nextra) { - if (dlen && *dlen == 0) { - errno = ENOSPC; - return NULL; - } - *dst = '\0'; /* can't create nextra, return "" */ - return dst; - } - f = getvisfun(flag); - dst = (*f)(dst, dlen, c, flag, nextc, nextra); - free(nextra); - if (dst == NULL || (dlen && *dlen == 0)) { - errno = ENOSPC; + len = strlen(src); + if ((dst = calloc(len + MAXEXTRAS, sizeof(*dst))) == NULL) return NULL; + + if (mbstowcs(dst, src, len) == (size_t)-1) { + size_t i; + for (i = 0; i < len; i++) + dst[i] = (wint_t)(u_char)src[i]; + d = dst + len; + } else + d = dst + wcslen(dst); + + if (flags & VIS_GLOB) { + *d++ = L'*'; + *d++ = L'?'; + *d++ = L'['; + *d++ = L'#'; } - *dst = '\0'; + + if (flags & VIS_SP) *d++ = L' '; + if (flags & VIS_TAB) *d++ = L'\t'; + if (flags & VIS_NL) *d++ = L'\n'; + if ((flags & VIS_NOSLASH) == 0) *d++ = L'\\'; + *d = L'\0'; + return dst; } -char * -svis(char *dst, int c, int flag, int nextc, const char *extra) -{ - return isnvis(dst, NULL, c, flag, nextc, extra); -} - -char * -snvis(char *dst, size_t dlen, int c, int flag, int nextc, const char *extra) -{ - return isnvis(dst, &dlen, c, flag, nextc, extra); -} - - /* - * strsvis, strsvisx - visually encode characters from src into dst - * - * Extra is a pointer to a \0-terminated list of characters to - * be encoded, too. These functions are useful e. g. to - * encode strings in such a way so that they are not interpreted - * by a shell. - * - * Dst must be 4 times the size of src to account for possible - * expansion. The length of dst, not including the trailing NULL, - * is returned. - * - * Strsvisx encodes exactly len bytes from src into dst. - * This is useful for encoding a block of data. + * istrsenvisx() + * The main internal function. + * All user-visible functions call this one. */ static int -istrsnvis(char *dst, size_t *dlen, const char *csrc, int flag, const char *extra) +istrsenvisx(char *mbdst, size_t *dlen, const char *mbsrc, size_t mblength, + int flags, const char *mbextra, int *cerr_ptr) { - int c; - char *start; - char *nextra = NULL; - const unsigned char *src = (const unsigned char *)csrc; + wchar_t *dst, *src, *pdst, *psrc, *start, *extra; + size_t len, olen; + uint64_t bmsk, wmsk; + wint_t c; visfun_t f; + int clen = 0, cerr = 0, error = -1, i, shft; + ssize_t mbslength, maxolen; - _DIAGASSERT(dst != NULL); - _DIAGASSERT(src != NULL); - _DIAGASSERT(extra != NULL); - MAKEEXTRALIST(flag, nextra, extra); - if (!nextra) { - *dst = '\0'; /* can't create nextra, return "" */ - return 0; - } - f = getvisfun(flag); - for (start = dst; (c = *src++) != '\0'; /* empty */) { - dst = (*f)(dst, dlen, c, flag, *src, nextra); - if (dst == NULL) { - errno = ENOSPC; - return -1; - } - } - free(nextra); - if (dlen && *dlen == 0) { - errno = ENOSPC; + _DIAGASSERT(mbdst != NULL); + _DIAGASSERT(mbsrc != NULL); + _DIAGASSERT(mbextra != NULL); + + /* + * Input (mbsrc) is a char string considered to be multibyte + * characters. The input loop will read this string pulling + * one character, possibly multiple bytes, from mbsrc and + * converting each to wchar_t in src. + * + * The vis conversion will be done using the wide char + * wchar_t string. + * + * This will then be converted back to a multibyte string to + * return to the caller. + */ + + /* Allocate space for the wide char strings */ + psrc = pdst = extra = NULL; + if (!mblength) + mblength = strlen(mbsrc); + if ((psrc = calloc(mblength + 1, sizeof(*psrc))) == NULL) return -1; + if ((pdst = calloc((4 * mblength) + 1, sizeof(*pdst))) == NULL) + goto out; + dst = pdst; + src = psrc; + + /* Use caller's multibyte conversion error flag. */ + if (cerr_ptr) + cerr = *cerr_ptr; + + /* + * Input loop. + * Handle up to mblength characters (not bytes). We do not + * stop at NULs because we may be processing a block of data + * that includes NULs. + */ + mbslength = (ssize_t)mblength; + /* + * When inputing a single character, must also read in the + * next character for nextc, the look-ahead character. + */ + if (mbslength == 1) + mbslength++; + while (mbslength > 0) { + /* Convert one multibyte character to wchar_t. */ + if (!cerr) + clen = mbtowc(src, mbsrc, MB_LEN_MAX); + if (cerr || clen < 0) { + /* Conversion error, process as a byte instead. */ + *src = (wint_t)(u_char)*mbsrc; + clen = 1; + cerr = 1; + } + if (clen == 0) + /* + * NUL in input gives 0 return value. process + * as single NUL byte and keep going. + */ + clen = 1; + /* Advance buffer character pointer. */ + src++; + /* Advance input pointer by number of bytes read. */ + mbsrc += clen; + /* Decrement input byte count. */ + mbslength -= clen; } - *dst = '\0'; - return (int)(dst - start); -} + len = src - psrc; + src = psrc; + /* + * In the single character input case, we will have actually + * processed two characters, c and nextc. Reset len back to + * just a single character. + */ + if (mblength < len) + len = mblength; -int -strsvis(char *dst, const char *csrc, int flag, const char *extra) -{ - return istrsnvis(dst, NULL, csrc, flag, extra); -} - -int -strsnvis(char *dst, size_t dlen, const char *csrc, int flag, const char *extra) -{ - return istrsnvis(dst, &dlen, csrc, flag, extra); -} - -static int -istrsnvisx(char *dst, size_t *dlen, const char *csrc, size_t len, int flag, - const char *extra) -{ - unsigned char c; - char *start; - char *nextra = NULL; - const unsigned char *src = (const unsigned char *)csrc; - visfun_t f; - - _DIAGASSERT(dst != NULL); - _DIAGASSERT(src != NULL); - _DIAGASSERT(extra != NULL); - MAKEEXTRALIST(flag, nextra, extra); - if (! nextra) { + /* Convert extra argument to list of characters for this mode. */ + extra = makeextralist(flags, mbextra); + if (!extra) { if (dlen && *dlen == 0) { errno = ENOSPC; - return -1; + goto out; } - *dst = '\0'; /* can't create nextra, return "" */ - return 0; + *mbdst = '\0'; /* can't create extra, return "" */ + error = 0; + goto out; } - f = getvisfun(flag); + /* Look up which processing function to call. */ + f = getvisfun(flags); + + /* + * Main processing loop. + * Call do_Xvis processing function one character at a time + * with next character available for look-ahead. + */ for (start = dst; len > 0; len--) { c = *src++; - dst = (*f)(dst, dlen, c, flag, len > 1 ? *src : '\0', nextra); + dst = (*f)(dst, c, flags, len >= 1 ? *src : L'\0', extra); if (dst == NULL) { errno = ENOSPC; - return -1; + goto out; } } - free(nextra); - if (dlen && *dlen == 0) { - errno = ENOSPC; - return -1; + + /* Terminate the string in the buffer. */ + *dst = L'\0'; + + /* + * Output loop. + * Convert wchar_t string back to multibyte output string. + * If we have hit a multi-byte conversion error on input, + * output byte-by-byte here. Else use wctomb(). + */ + len = wcslen(start); + maxolen = dlen ? *dlen : (wcslen(start) * MB_LEN_MAX + 1); + olen = 0; + for (dst = start; len > 0; len--) { + if (!cerr) + clen = wctomb(mbdst, *dst); + if (cerr || clen < 0) { + /* + * Conversion error, process as a byte(s) instead. + * Examine each byte and higher-order bytes for + * data. E.g., + * 0x000000000000a264 -> a2 64 + * 0x000000001f00a264 -> 1f 00 a2 64 + */ + clen = 0; + wmsk = 0; + for (i = sizeof(wmsk) - 1; i >= 0; i--) { + shft = i * NBBY; + bmsk = (uint64_t)0xffLL << shft; + wmsk |= bmsk; + if ((*dst & wmsk) || i == 0) + mbdst[clen++] = (char)( + (uint64_t)(*dst & bmsk) >> + shft); + } + cerr = 1; + } + /* If this character would exceed our output limit, stop. */ + if (olen + clen > (size_t)maxolen) + break; + /* Advance output pointer by number of bytes written. */ + mbdst += clen; + /* Advance buffer character pointer. */ + dst++; + /* Incrment output character count. */ + olen += clen; } - *dst = '\0'; - return (int)(dst - start); + + /* Terminate the output string. */ + *mbdst = '\0'; + + /* Pass conversion error flag out. */ + if (cerr_ptr) + *cerr_ptr = cerr; + + free(extra); + free(pdst); + free(psrc); + + return (int)olen; +out: + free(extra); + free(pdst); + free(psrc); + return error; +} +#endif + +#if !HAVE_SVIS +/* + * The "svis" variants all take an "extra" arg that is a pointer + * to a NUL-terminated list of characters to be encoded, too. + * These functions are useful e. g. to encode strings in such a + * way so that they are not interpreted by a shell. + */ + +char * +svis(char *mbdst, int c, int flags, int nextc, const char *mbextra) +{ + char cc[2]; + int ret; + + cc[0] = c; + cc[1] = nextc; + + ret = istrsenvisx(mbdst, NULL, cc, 1, flags, mbextra, NULL); + if (ret < 0) + return NULL; + return mbdst + ret; +} + +char * +snvis(char *mbdst, size_t dlen, int c, int flags, int nextc, const char *mbextra) +{ + char cc[2]; + int ret; + + cc[0] = c; + cc[1] = nextc; + + ret = istrsenvisx(mbdst, &dlen, cc, 1, flags, mbextra, NULL); + if (ret < 0) + return NULL; + return mbdst + ret; } int -strsvisx(char *dst, const char *csrc, size_t len, int flag, const char *extra) +strsvis(char *mbdst, const char *mbsrc, int flags, const char *mbextra) { - return istrsnvisx(dst, NULL, csrc, len, flag, extra); + return istrsenvisx(mbdst, NULL, mbsrc, 0, flags, mbextra, NULL); } int -strsnvisx(char *dst, size_t dlen, const char *csrc, size_t len, int flag, - const char *extra) +strsnvis(char *mbdst, size_t dlen, const char *mbsrc, int flags, const char *mbextra) { - return istrsnvisx(dst, &dlen, csrc, len, flag, extra); + return istrsenvisx(mbdst, &dlen, mbsrc, 0, flags, mbextra, NULL); +} + +int +strsvisx(char *mbdst, const char *mbsrc, size_t len, int flags, const char *mbextra) +{ + return istrsenvisx(mbdst, NULL, mbsrc, len, flags, mbextra, NULL); +} + +int +strsnvisx(char *mbdst, size_t dlen, const char *mbsrc, size_t len, int flags, + const char *mbextra) +{ + return istrsenvisx(mbdst, &dlen, mbsrc, len, flags, mbextra, NULL); +} + +int +strsenvisx(char *mbdst, size_t dlen, const char *mbsrc, size_t len, int flags, + const char *mbextra, int *cerr_ptr) +{ + return istrsenvisx(mbdst, &dlen, mbsrc, len, flags, mbextra, cerr_ptr); } #endif @@ -461,120 +605,83 @@ strsnvisx(char *dst, size_t dlen, const char *csrc, size_t len, int flag, /* * vis - visually encode characters */ -static char * -invis(char *dst, size_t *dlen, int c, int flag, int nextc) +char * +vis(char *mbdst, int c, int flags, int nextc) { - char *extra = NULL; - unsigned char uc = (unsigned char)c; - visfun_t f; + char cc[2]; + int ret; - _DIAGASSERT(dst != NULL); + cc[0] = c; + cc[1] = nextc; - MAKEEXTRALIST(flag, extra, ""); - if (! extra) { - if (dlen && *dlen == 0) { - errno = ENOSPC; - return NULL; - } - *dst = '\0'; /* can't create extra, return "" */ - return dst; - } - f = getvisfun(flag); - dst = (*f)(dst, dlen, uc, flag, nextc, extra); - free(extra); - if (dst == NULL || (dlen && *dlen == 0)) { - errno = ENOSPC; + ret = istrsenvisx(mbdst, NULL, cc, 1, flags, "", NULL); + if (ret < 0) return NULL; - } - *dst = '\0'; - return dst; + return mbdst + ret; } char * -vis(char *dst, int c, int flag, int nextc) +nvis(char *mbdst, size_t dlen, int c, int flags, int nextc) { - return invis(dst, NULL, c, flag, nextc); -} + char cc[2]; + int ret; -char * -nvis(char *dst, size_t dlen, int c, int flag, int nextc) -{ - return invis(dst, &dlen, c, flag, nextc); -} + cc[0] = c; + cc[1] = nextc; + ret = istrsenvisx(mbdst, &dlen, cc, 1, flags, "", NULL); + if (ret < 0) + return NULL; + return mbdst + ret; +} /* - * strvis, strvisx - visually encode characters from src into dst + * strvis - visually encode characters from src into dst + * + * Dst must be 4 times the size of src to account for possible + * expansion. The length of dst, not including the trailing NULL, + * is returned. + */ + +int +strvis(char *mbdst, const char *mbsrc, int flags) +{ + return istrsenvisx(mbdst, NULL, mbsrc, 0, flags, "", NULL); +} + +int +strnvis(char *mbdst, size_t dlen, const char *mbsrc, int flags) +{ + return istrsenvisx(mbdst, &dlen, mbsrc, 0, flags, "", NULL); +} + +/* + * strvisx - visually encode characters from src into dst * * Dst must be 4 times the size of src to account for possible * expansion. The length of dst, not including the trailing NULL, * is returned. * - * Strvisx encodes exactly len bytes from src into dst. + * Strvisx encodes exactly len characters from src into dst. * This is useful for encoding a block of data. */ -static int -istrnvis(char *dst, size_t *dlen, const char *src, int flag) -{ - char *extra = NULL; - int rv; - MAKEEXTRALIST(flag, extra, ""); - if (!extra) { - if (dlen && *dlen == 0) { - errno = ENOSPC; - return -1; - } - *dst = '\0'; /* can't create extra, return "" */ - return 0; - } - rv = istrsnvis(dst, dlen, src, flag, extra); - free(extra); - return rv; +int +strvisx(char *mbdst, const char *mbsrc, size_t len, int flags) +{ + return istrsenvisx(mbdst, NULL, mbsrc, len, flags, "", NULL); } int -strvis(char *dst, const char *src, int flag) +strnvisx(char *mbdst, size_t dlen, const char *mbsrc, size_t len, int flags) { - return istrnvis(dst, NULL, src, flag); + return istrsenvisx(mbdst, &dlen, mbsrc, len, flags, "", NULL); } int -strnvis(char *dst, size_t dlen, const char *src, int flag) +strenvisx(char *mbdst, size_t dlen, const char *mbsrc, size_t len, int flags, + int *cerr_ptr) { - return istrnvis(dst, &dlen, src, flag); + return istrsenvisx(mbdst, &dlen, mbsrc, len, flags, "", cerr_ptr); } - -static int -istrnvisx(char *dst, size_t *dlen, const char *src, size_t len, int flag) -{ - char *extra = NULL; - int rv; - - MAKEEXTRALIST(flag, extra, ""); - if (!extra) { - if (dlen && *dlen == 0) { - errno = ENOSPC; - return -1; - } - *dst = '\0'; /* can't create extra, return "" */ - return 0; - } - rv = istrsnvisx(dst, dlen, src, len, flag, extra); - free(extra); - return rv; -} - -int -strvisx(char *dst, const char *src, size_t len, int flag) -{ - return istrnvisx(dst, NULL, src, len, flag); -} - -int -strnvisx(char *dst, size_t dlen, const char *src, size_t len, int flag) -{ - return istrnvisx(dst, &dlen, src, len, flag); -} - #endif diff --git a/vis.h b/vis.h index dbdb2c4de1f..b4c6b5e1c6d 100644 --- a/vis.h +++ b/vis.h @@ -1,4 +1,4 @@ -/* $NetBSD: vis.h,v 1.20 2012/12/14 21:36:59 christos Exp $ */ +/* $NetBSD: vis.h,v 1.21 2013/02/20 17:01:15 christos Exp $ */ /*- * Copyright (c) 1990, 1993 @@ -95,9 +95,12 @@ int strsnvis(char *, size_t, const char *, int, const char *); int strvisx(char *, const char *, size_t, int); int strnvisx(char *, size_t, const char *, size_t, int); +int strenvisx(char *, size_t, const char *, size_t, int, int *); int strsvisx(char *, const char *, size_t, int, const char *); int strsnvisx(char *, size_t, const char *, size_t, int, const char *); +int strsenvisx(char *, size_t, const char *, size_t , int, const char *, + int *); int strunvis(char *, const char *); int strnunvis(char *, size_t, const char *); From 664b97eff580cca7aa435161b8aa7fa8a6f667f2 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 21 Feb 2013 17:40:59 +0000 Subject: [PATCH 0338/1476] Remove splsoftclock() since it is now gone. --- sys/sys/systm.h | 1 - 1 file changed, 1 deletion(-) diff --git a/sys/sys/systm.h b/sys/sys/systm.h index d9fdef00925..5dc237e5c81 100644 --- a/sys/sys/systm.h +++ b/sys/sys/systm.h @@ -330,7 +330,6 @@ static __inline intrmask_t splclock(void) { return 0; } static __inline intrmask_t splhigh(void) { return 0; } static __inline intrmask_t splimp(void) { return 0; } static __inline intrmask_t splnet(void) { return 0; } -static __inline intrmask_t splsoftclock(void) { return 0; } static __inline intrmask_t splsoftvm(void) { return 0; } static __inline intrmask_t spltty(void) { return 0; } static __inline intrmask_t splvm(void) { return 0; } From e7599006fa4d05813faabe5323af376ca23fdfff Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 21 Feb 2013 17:50:21 +0000 Subject: [PATCH 0339/1476] bus_dmamap_load_ccb doesn't exist on earlier versions of FreeBSD or DragonFlyBSD, so it certainly doesn't need splsoftvm(). Remove it. # I doubt this driver will now compile on older FreeBSD versions or DFBSD # We should consider unifdefing it since that code seems unmaintained. --- sys/dev/firewire/sbp.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sys/dev/firewire/sbp.c b/sys/dev/firewire/sbp.c index 8089d99fa03..5efc5eb377b 100644 --- a/sys/dev/firewire/sbp.c +++ b/sys/dev/firewire/sbp.c @@ -2488,16 +2488,14 @@ printf("ORB %08x %08x %08x %08x\n", ntohl(ocb->orb[0]), ntohl(ocb->orb[1]), ntoh printf("ORB %08x %08x %08x %08x\n", ntohl(ocb->orb[4]), ntohl(ocb->orb[5]), ntohl(ocb->orb[6]), ntohl(ocb->orb[7])); */ if (ccb->csio.dxfer_len > 0) { - int s, error; + int error; - s = splsoftvm(); error = bus_dmamap_load_ccb(/*dma tag*/sbp->dmat, /*dma map*/ocb->dmamap, ccb, sbp_execute_ocb, ocb, /*flags*/0); - splx(s); if (error) printf("sbp: bus_dmamap_load error %d\n", error); } else From ae40be8cf0ea07df25b46f95e47fb17a992edf4a Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 21 Feb 2013 17:54:14 +0000 Subject: [PATCH 0340/1476] splsoftvm() is no longer in the tree. gc. --- sys/sys/systm.h | 1 - 1 file changed, 1 deletion(-) diff --git a/sys/sys/systm.h b/sys/sys/systm.h index 5dc237e5c81..611d014831c 100644 --- a/sys/sys/systm.h +++ b/sys/sys/systm.h @@ -330,7 +330,6 @@ static __inline intrmask_t splclock(void) { return 0; } static __inline intrmask_t splhigh(void) { return 0; } static __inline intrmask_t splimp(void) { return 0; } static __inline intrmask_t splnet(void) { return 0; } -static __inline intrmask_t splsoftvm(void) { return 0; } static __inline intrmask_t spltty(void) { return 0; } static __inline intrmask_t splvm(void) { return 0; } static __inline void splx(intrmask_t ipl __unused) { return; } From 593efaf9f7ff8b4a961e61f55c333e63ee36495c Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Thu, 21 Feb 2013 19:02:50 +0000 Subject: [PATCH 0341/1476] Further refine the handling of stop signals in the NFS client. The changes in r246417 were incomplete as they did not add explicit calls to sigdeferstop() around all the places that previously passed SBDRY to _sleep(). In addition, nfs_getcacheblk() could trigger a write RPC from getblk() resulting in sigdeferstop() recursing. Rather than manually deferring stop signals in specific places, change the VFS_*() and VOP_*() methods to defer stop signals for filesystems which request this behavior via a new VFCF_SBDRY flag. Note that this has to be a VFC flag rather than a MNTK flag so that it works properly with VFS_MOUNT() when the mount is not yet fully constructed. For now, only the NFS clients are set this new flag in VFS_SET(). A few other related changes: - Add an assertion to ensure that TDF_SBDRY doesn't leak to userland. - When a lookup request uses VOP_READLINK() to follow a symlink, mark the request as being on behalf of the thread performing the lookup (cnp_thread) rather than using a NULL thread pointer. This causes NFS to properly handle signals during this VOP on an interruptible mount. PR: kern/176179 Reported by: Russell Cattelan (sigdeferstop() recursion) Reviewed by: kib MFC after: 1 month --- sys/fs/nfs/nfs_commonkrpc.c | 2 - sys/fs/nfsclient/nfs_clvfsops.c | 2 +- sys/kern/kern_sig.c | 22 +++-- sys/kern/subr_trap.c | 2 + sys/kern/vfs_export.c | 1 + sys/kern/vfs_lookup.c | 2 +- sys/nfsclient/nfs_krpc.c | 2 - sys/nfsclient/nfs_vfsops.c | 2 +- sys/sys/mount.h | 140 ++++++++++++++++++++++++++------ sys/sys/signalvar.h | 4 +- sys/tools/vnode_if.awk | 3 + 11 files changed, 141 insertions(+), 41 deletions(-) diff --git a/sys/fs/nfs/nfs_commonkrpc.c b/sys/fs/nfs/nfs_commonkrpc.c index f08ba854ea6..86b6987a138 100644 --- a/sys/fs/nfs/nfs_commonkrpc.c +++ b/sys/fs/nfs/nfs_commonkrpc.c @@ -1080,7 +1080,6 @@ newnfs_set_sigmask(struct thread *td, sigset_t *oldset) SIGDELSET(newset, newnfs_sig_set[i]); } mtx_unlock(&p->p_sigacts->ps_mtx); - sigdeferstop(td); kern_sigprocmask(td, SIG_SETMASK, &newset, oldset, SIGPROCMASK_PROC_LOCKED); PROC_UNLOCK(p); @@ -1092,7 +1091,6 @@ newnfs_restore_sigmask(struct thread *td, sigset_t *set) if (td == NULL) td = curthread; /* XXX */ kern_sigprocmask(td, SIG_SETMASK, set, NULL, 0); - sigallowstop(td); } /* diff --git a/sys/fs/nfsclient/nfs_clvfsops.c b/sys/fs/nfsclient/nfs_clvfsops.c index 83ce3cbd7d5..281ce4464a8 100644 --- a/sys/fs/nfsclient/nfs_clvfsops.c +++ b/sys/fs/nfsclient/nfs_clvfsops.c @@ -132,7 +132,7 @@ static struct vfsops nfs_vfsops = { .vfs_unmount = nfs_unmount, .vfs_sysctl = nfs_sysctl, }; -VFS_SET(nfs_vfsops, nfs, VFCF_NETWORK); +VFS_SET(nfs_vfsops, nfs, VFCF_NETWORK | VFCF_SBDRY); /* So that loader and kldload(2) can find us, wherever we are.. */ MODULE_VERSION(nfs, 1); diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 7d3634d337d..e1dbedc7947 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -2537,16 +2537,22 @@ tdsigcleanup(struct thread *td) } -/* Defer the delivery of SIGSTOP for the current thread. */ -void -sigdeferstop(struct thread *td) +/* + * Defer the delivery of SIGSTOP for the current thread. Returns true + * if stops were deferred and false if they were already deferred. + */ +int +sigdeferstop(void) { + struct thread *td; - KASSERT(!(td->td_flags & TDF_SBDRY), - ("attempt to set TDF_SBDRY recursively")); + td = curthread; + if (td->td_flags & TDF_SBDRY) + return (0); thread_lock(td); td->td_flags |= TDF_SBDRY; thread_unlock(td); + return (1); } /* @@ -2555,11 +2561,11 @@ sigdeferstop(struct thread *td) * will suspend either via ast() or a subsequent interruptible sleep. */ void -sigallowstop(struct thread *td) +sigallowstop() { + struct thread *td; - KASSERT(td->td_flags & TDF_SBDRY, - ("attempt to clear already-cleared TDF_SBDRY")); + td = curthread; thread_lock(td); td->td_flags &= ~TDF_SBDRY; thread_unlock(td); diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c index 22cabcb3b44..bd06f201d11 100644 --- a/sys/kern/subr_trap.c +++ b/sys/kern/subr_trap.c @@ -164,6 +164,8 @@ userret(struct thread *td, struct trapframe *frame) ("userret: Returning with with pinned thread")); KASSERT(td->td_vp_reserv == 0, ("userret: Returning while holding vnode reservation")); + KASSERT((td->td_flags & TDF_SBDRY) == 0, + ("userret: Returning with stop signals deferred")); #ifdef VIMAGE /* Unfortunately td_vnet_lpush needs VNET_DEBUG. */ VNET_ASSERT(curvnet == NULL, diff --git a/sys/kern/vfs_export.c b/sys/kern/vfs_export.c index 114c23ed5d0..6a3f2916cd3 100644 --- a/sys/kern/vfs_export.c +++ b/sys/kern/vfs_export.c @@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index e5ee4f63879..fbde152d6a6 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -339,7 +339,7 @@ namei(struct nameidata *ndp) auio.uio_offset = 0; auio.uio_rw = UIO_READ; auio.uio_segflg = UIO_SYSSPACE; - auio.uio_td = (struct thread *)0; + auio.uio_td = td; auio.uio_resid = MAXPATHLEN; error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred); if (error) { diff --git a/sys/nfsclient/nfs_krpc.c b/sys/nfsclient/nfs_krpc.c index 851b0b61838..d3082d8d914 100644 --- a/sys/nfsclient/nfs_krpc.c +++ b/sys/nfsclient/nfs_krpc.c @@ -748,7 +748,6 @@ nfs_set_sigmask(struct thread *td, sigset_t *oldset) SIGDELSET(newset, nfs_sig_set[i]); } mtx_unlock(&p->p_sigacts->ps_mtx); - sigdeferstop(td); kern_sigprocmask(td, SIG_SETMASK, &newset, oldset, SIGPROCMASK_PROC_LOCKED); PROC_UNLOCK(p); @@ -760,7 +759,6 @@ nfs_restore_sigmask(struct thread *td, sigset_t *set) if (td == NULL) td = curthread; /* XXX */ kern_sigprocmask(td, SIG_SETMASK, set, NULL, 0); - sigallowstop(td); } /* diff --git a/sys/nfsclient/nfs_vfsops.c b/sys/nfsclient/nfs_vfsops.c index 63b5772f35e..9cec3077fbc 100644 --- a/sys/nfsclient/nfs_vfsops.c +++ b/sys/nfsclient/nfs_vfsops.c @@ -146,7 +146,7 @@ static struct vfsops nfs_vfsops = { .vfs_unmount = nfs_unmount, .vfs_sysctl = nfs_sysctl, }; -VFS_SET(nfs_vfsops, oldnfs, VFCF_NETWORK); +VFS_SET(nfs_vfsops, oldnfs, VFCF_NETWORK | VFCF_SBDRY); /* So that loader and kldload(2) can find us, wherever we are.. */ MODULE_VERSION(oldnfs, 1); diff --git a/sys/sys/mount.h b/sys/sys/mount.h index bbbc569de70..f73d5d7443f 100644 --- a/sys/sys/mount.h +++ b/sys/sys/mount.h @@ -493,6 +493,7 @@ struct ovfsconf { #define VFCF_UNICODE 0x00200000 /* stores file names as Unicode */ #define VFCF_JAIL 0x00400000 /* can be mounted from within a jail */ #define VFCF_DELEGADMIN 0x00800000 /* supports delegated administration */ +#define VFCF_SBDRY 0x01000000 /* defer stop requests */ typedef uint32_t fsctlop_t; @@ -629,30 +630,121 @@ struct vfsops { vfs_statfs_t __vfs_statfs; -#define VFS_MOUNT(MP) (*(MP)->mnt_op->vfs_mount)(MP) -#define VFS_UNMOUNT(MP, FORCE) (*(MP)->mnt_op->vfs_unmount)(MP, FORCE) -#define VFS_ROOT(MP, FLAGS, VPP) \ - (*(MP)->mnt_op->vfs_root)(MP, FLAGS, VPP) -#define VFS_QUOTACTL(MP, C, U, A) \ - (*(MP)->mnt_op->vfs_quotactl)(MP, C, U, A) -#define VFS_STATFS(MP, SBP) __vfs_statfs((MP), (SBP)) -#define VFS_SYNC(MP, WAIT) (*(MP)->mnt_op->vfs_sync)(MP, WAIT) -#define VFS_VGET(MP, INO, FLAGS, VPP) \ - (*(MP)->mnt_op->vfs_vget)(MP, INO, FLAGS, VPP) -#define VFS_FHTOVP(MP, FIDP, FLAGS, VPP) \ - (*(MP)->mnt_op->vfs_fhtovp)(MP, FIDP, FLAGS, VPP) -#define VFS_CHECKEXP(MP, NAM, EXFLG, CRED, NUMSEC, SEC) \ - (*(MP)->mnt_op->vfs_checkexp)(MP, NAM, EXFLG, CRED, NUMSEC, SEC) -#define VFS_EXTATTRCTL(MP, C, FN, NS, N) \ - (*(MP)->mnt_op->vfs_extattrctl)(MP, C, FN, NS, N) -#define VFS_SYSCTL(MP, OP, REQ) \ - (*(MP)->mnt_op->vfs_sysctl)(MP, OP, REQ) -#define VFS_SUSP_CLEAN(MP) \ - ({if (*(MP)->mnt_op->vfs_susp_clean != NULL) \ - (*(MP)->mnt_op->vfs_susp_clean)(MP); }) -#define VFS_RECLAIM_LOWERVP(MP, VP) \ - ({if (*(MP)->mnt_op->vfs_reclaim_lowervp != NULL) \ - (*(MP)->mnt_op->vfs_reclaim_lowervp)((MP), (VP)); }) +#define VFS_PROLOGUE(MP) do { \ + int _enable_stops; \ + \ + _enable_stops = ((MP) != NULL && \ + ((MP)->mnt_vfc->vfc_flags & VFCF_SBDRY) && sigdeferstop()) + +#define VFS_EPILOGUE(MP) \ + if (_enable_stops) \ + sigallowstop(); \ +} while (0) + +#define VFS_MOUNT(MP) ({ \ + int _rc; \ + \ + VFS_PROLOGUE(MP); \ + _rc = (*(MP)->mnt_op->vfs_mount)(MP); \ + VFS_EPILOGUE(MP); \ + _rc; }) + +#define VFS_UNMOUNT(MP, FORCE) ({ \ + int _rc; \ + \ + VFS_PROLOGUE(MP); \ + _rc = (*(MP)->mnt_op->vfs_unmount)(MP, FORCE); \ + VFS_EPILOGUE(MP); \ + _rc; }) + +#define VFS_ROOT(MP, FLAGS, VPP) ({ \ + int _rc; \ + \ + VFS_PROLOGUE(MP); \ + _rc = (*(MP)->mnt_op->vfs_root)(MP, FLAGS, VPP); \ + VFS_EPILOGUE(MP); \ + _rc; }) + +#define VFS_QUOTACTL(MP, C, U, A) ({ \ + int _rc; \ + \ + VFS_PROLOGUE(MP); \ + _rc = (*(MP)->mnt_op->vfs_quotactl)(MP, C, U, A); \ + VFS_EPILOGUE(MP); \ + _rc; }) + +#define VFS_STATFS(MP, SBP) ({ \ + int _rc; \ + \ + VFS_PROLOGUE(MP); \ + _rc = __vfs_statfs((MP), (SBP)); \ + VFS_EPILOGUE(MP); \ + _rc; }) + +#define VFS_SYNC(MP, WAIT) ({ \ + int _rc; \ + \ + VFS_PROLOGUE(MP); \ + _rc = (*(MP)->mnt_op->vfs_sync)(MP, WAIT); \ + VFS_EPILOGUE(MP); \ + _rc; }) + +#define VFS_VGET(MP, INO, FLAGS, VPP) ({ \ + int _rc; \ + \ + VFS_PROLOGUE(MP); \ + _rc = (*(MP)->mnt_op->vfs_vget)(MP, INO, FLAGS, VPP); \ + VFS_EPILOGUE(MP); \ + _rc; }) + +#define VFS_FHTOVP(MP, FIDP, FLAGS, VPP) ({ \ + int _rc; \ + \ + VFS_PROLOGUE(MP); \ + _rc = (*(MP)->mnt_op->vfs_fhtovp)(MP, FIDP, FLAGS, VPP); \ + VFS_EPILOGUE(MP); \ + _rc; }) + +#define VFS_CHECKEXP(MP, NAM, EXFLG, CRED, NUMSEC, SEC) ({ \ + int _rc; \ + \ + VFS_PROLOGUE(MP); \ + _rc = (*(MP)->mnt_op->vfs_checkexp)(MP, NAM, EXFLG, CRED, NUMSEC,\ + SEC); \ + VFS_EPILOGUE(MP); \ + _rc; }) + +#define VFS_EXTATTRCTL(MP, C, FN, NS, N) ({ \ + int _rc; \ + \ + VFS_PROLOGUE(MP); \ + _rc = (*(MP)->mnt_op->vfs_extattrctl)(MP, C, FN, NS, N); \ + VFS_EPILOGUE(MP); \ + _rc; }) + +#define VFS_SYSCTL(MP, OP, REQ) ({ \ + int _rc; \ + \ + VFS_PROLOGUE(MP); \ + _rc = (*(MP)->mnt_op->vfs_sysctl)(MP, OP, REQ); \ + VFS_EPILOGUE(MP); \ + _rc; }) + +#define VFS_SUSP_CLEAN(MP) do { \ + if (*(MP)->mnt_op->vfs_susp_clean != NULL) { \ + VFS_PROLOGUE(MP); \ + (*(MP)->mnt_op->vfs_susp_clean)(MP); \ + VFS_EPILOGUE(MP); \ + } \ +} while (0) + +#define VFS_RECLAIM_LOWERVP(MP, VP) do { \ + if (*(MP)->mnt_op->vfs_reclaim_lowervp != NULL) { \ + VFS_PROLOGUE(MP); \ + (*(MP)->mnt_op->vfs_reclaim_lowervp)((MP), (VP)); \ + VFS_EPILOGUE(MP); \ + } \ +} while (0) #define VFS_KNOTE_LOCKED(vp, hint) do \ { \ diff --git a/sys/sys/signalvar.h b/sys/sys/signalvar.h index 91655b25a5d..fcf25adfb56 100644 --- a/sys/sys/signalvar.h +++ b/sys/sys/signalvar.h @@ -328,8 +328,8 @@ extern struct mtx sigio_lock; #define SIGPROCMASK_PS_LOCKED 0x0004 int cursig(struct thread *td, int stop_allowed); -void sigdeferstop(struct thread *td); -void sigallowstop(struct thread *td); +int sigdeferstop(void); +void sigallowstop(void); void execsigs(struct proc *p); void gsignal(int pgid, int sig, ksiginfo_t *ksi); void killproc(struct proc *p, char *why); diff --git a/sys/tools/vnode_if.awk b/sys/tools/vnode_if.awk index c9914582e23..2347004beb6 100644 --- a/sys/tools/vnode_if.awk +++ b/sys/tools/vnode_if.awk @@ -172,6 +172,7 @@ if (cfile) { "#include \n" \ "#include \n" \ "#include \n" \ + "#include \n" \ "#include \n" \ "#include \n" \ "\n" \ @@ -365,10 +366,12 @@ while ((getline < srcfile) > 0) { add_debug_code(name, args[i], "Entry", "\t"); printc("\tKTR_START" ctrstr); add_pre(name); + printc("\tVFS_PROLOGUE(a->a_" args[0]"->v_mount);") printc("\tif (vop->"name" != NULL)") printc("\t\trc = vop->"name"(a);") printc("\telse") printc("\t\trc = vop->vop_bypass(&a->a_gen);") + printc("\tVFS_EPILOGUE(a->a_" args[0]"->v_mount);") printc("\tSDT_PROBE(vfs, vop, " name ", return, a->a_" args[0] ", a, rc, 0, 0);\n"); printc("\tif (rc == 0) {"); for (i = 0; i < numargs; ++i) From ed7ce02c2c2420890d862493e83b33f9596b7d5d Mon Sep 17 00:00:00 2001 From: John-Mark Gurney Date: Thu, 21 Feb 2013 19:13:19 +0000 Subject: [PATCH 0342/1476] reorder so all the flags are together and make the PCLMUL flag unique.. This fixes the problem on amd64 miscompiling mpboot.s causing boot issues... We are still using gas for a few files in the kernel... Submitted by: kib MFC after: 1 month --- contrib/binutils/opcodes/i386-opc.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/contrib/binutils/opcodes/i386-opc.h b/contrib/binutils/opcodes/i386-opc.h index 45589d8b355..27c1dab2aae 100644 --- a/contrib/binutils/opcodes/i386-opc.h +++ b/contrib/binutils/opcodes/i386-opc.h @@ -73,15 +73,16 @@ typedef struct template #define CpuSSE4_2 0x800000 /* SSE4.2 Instructions required */ #define CpuXSAVE 0x1000000 /* XSAVE Instructions required */ #define CpuAES 0x2000000 /* AES Instructions required */ -#define CpuPCLMUL 0x4000000 /* Carry-less Multiplication extensions */ - -/* SSE4.1/4.2 Instructions required */ -#define CpuSSE4 (CpuSSE4_1|CpuSSE4_2) /* These flags are set by gas depending on the flag_code. */ #define Cpu64 0x4000000 /* 64bit support required */ #define CpuNo64 0x8000000 /* Not supported in the 64bit mode */ +#define CpuPCLMUL 0x10000000 /* Carry-less Multiplication extensions */ + +/* SSE4.1/4.2 Instructions required */ +#define CpuSSE4 (CpuSSE4_1|CpuSSE4_2) + /* The default value for unknown CPUs - enable all features to avoid problems. */ #define CpuUnknownFlags (Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686 \ |CpuP4|CpuSledgehammer|CpuMMX|CpuMMX2|CpuSSE|CpuSSE2|CpuSSE3|CpuVMX \ From c1508f2bad8d60cb487b7b74f07b376ebf3eafb2 Mon Sep 17 00:00:00 2001 From: Navdeep Parhar Date: Thu, 21 Feb 2013 20:13:15 +0000 Subject: [PATCH 0343/1476] cxgbe(4): Add sysctls to extract debug information from the chip: dev.t4nex.X.misc.cim_la logic analyzer dump dev.t4nex.X.misc.cim_qcfg queue configuration dev.t4nex.X.misc.cim_ibq_xxx inbound queues dev.t4nex.X.misc.cim_obq_xxx outbound queues Obtained from: Chelsio MFC after: 1 week --- sys/dev/cxgbe/common/t4_hw.h | 1 + sys/dev/cxgbe/t4_main.c | 229 +++++++++++++++++++++++++++++++++++ 2 files changed, 230 insertions(+) diff --git a/sys/dev/cxgbe/common/t4_hw.h b/sys/dev/cxgbe/common/t4_hw.h index 256a7d5e988..acc383aaf62 100644 --- a/sys/dev/cxgbe/common/t4_hw.h +++ b/sys/dev/cxgbe/common/t4_hw.h @@ -58,6 +58,7 @@ enum { CIM_PIFLA_SIZE = 64, /* # of 192-bit words in CIM PIF LA */ CIM_MALA_SIZE = 64, /* # of 160-bit words in CIM MA LA */ CIM_IBQ_SIZE = 128, /* # of 128-bit words in a CIM IBQ */ + CIM_OBQ_SIZE = 128, /* # of 128-bit words in a CIM OBQ */ TPLA_SIZE = 128, /* # of 64-bit words in TP LA */ ULPRX_LA_SIZE = 512, /* # of 256-bit words in ULP_RX LA */ }; diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c index 96246a60c74..0e24c7c8527 100644 --- a/sys/dev/cxgbe/t4_main.c +++ b/sys/dev/cxgbe/t4_main.c @@ -317,6 +317,9 @@ static int sysctl_qsize_txq(SYSCTL_HANDLER_ARGS); static int sysctl_handle_t4_reg64(SYSCTL_HANDLER_ARGS); #ifdef SBUF_DRAIN static int sysctl_cctrl(SYSCTL_HANDLER_ARGS); +static int sysctl_cim_ibq_obq(SYSCTL_HANDLER_ARGS); +static int sysctl_cim_la(SYSCTL_HANDLER_ARGS); +static int sysctl_cim_qcfg(SYSCTL_HANDLER_ARGS); static int sysctl_cpl_stats(SYSCTL_HANDLER_ARGS); static int sysctl_ddp_stats(SYSCTL_HANDLER_ARGS); static int sysctl_devlog(SYSCTL_HANDLER_ARGS); @@ -3171,6 +3174,62 @@ t4_sysctls(struct adapter *sc) CTLTYPE_STRING | CTLFLAG_RD, sc, 0, sysctl_cctrl, "A", "congestion control"); + SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cim_ibq_tp0", + CTLTYPE_STRING | CTLFLAG_RD, sc, 0, + sysctl_cim_ibq_obq, "A", "CIM IBQ 0 (TP0)"); + + SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cim_ibq_tp1", + CTLTYPE_STRING | CTLFLAG_RD, sc, 1, + sysctl_cim_ibq_obq, "A", "CIM IBQ 1 (TP1)"); + + SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cim_ibq_ulp", + CTLTYPE_STRING | CTLFLAG_RD, sc, 2, + sysctl_cim_ibq_obq, "A", "CIM IBQ 2 (ULP)"); + + SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cim_ibq_sge0", + CTLTYPE_STRING | CTLFLAG_RD, sc, 3, + sysctl_cim_ibq_obq, "A", "CIM IBQ 3 (SGE0)"); + + SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cim_ibq_sge1", + CTLTYPE_STRING | CTLFLAG_RD, sc, 4, + sysctl_cim_ibq_obq, "A", "CIM IBQ 4 (SGE1)"); + + SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cim_ibq_ncsi", + CTLTYPE_STRING | CTLFLAG_RD, sc, 5, + sysctl_cim_ibq_obq, "A", "CIM IBQ 5 (NCSI)"); + + SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cim_la", + CTLTYPE_STRING | CTLFLAG_RD, sc, 0, + sysctl_cim_la, "A", "CIM logic analyzer"); + + SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cim_obq_ulp0", + CTLTYPE_STRING | CTLFLAG_RD, sc, 0 + CIM_NUM_IBQ, + sysctl_cim_ibq_obq, "A", "CIM OBQ 0 (ULP0)"); + + SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cim_obq_ulp1", + CTLTYPE_STRING | CTLFLAG_RD, sc, 1 + CIM_NUM_IBQ, + sysctl_cim_ibq_obq, "A", "CIM OBQ 1 (ULP1)"); + + SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cim_obq_ulp2", + CTLTYPE_STRING | CTLFLAG_RD, sc, 2 + CIM_NUM_IBQ, + sysctl_cim_ibq_obq, "A", "CIM OBQ 2 (ULP2)"); + + SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cim_obq_ulp3", + CTLTYPE_STRING | CTLFLAG_RD, sc, 3 + CIM_NUM_IBQ, + sysctl_cim_ibq_obq, "A", "CIM OBQ 3 (ULP3)"); + + SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cim_obq_sge", + CTLTYPE_STRING | CTLFLAG_RD, sc, 4 + CIM_NUM_IBQ, + sysctl_cim_ibq_obq, "A", "CIM OBQ 4 (SGE)"); + + SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cim_obq_ncsi", + CTLTYPE_STRING | CTLFLAG_RD, sc, 5 + CIM_NUM_IBQ, + sysctl_cim_ibq_obq, "A", "CIM OBQ 5 (NCSI)"); + + SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cim_qcfg", + CTLTYPE_STRING | CTLFLAG_RD, sc, 0, + sysctl_cim_qcfg, "A", "CIM queue configuration"); + SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cpl_stats", CTLTYPE_STRING | CTLFLAG_RD, sc, 0, sysctl_cpl_stats, "A", "CPL statistics"); @@ -3694,6 +3753,176 @@ sysctl_cctrl(SYSCTL_HANDLER_ARGS) return (rc); } +static const char *qname[CIM_NUM_IBQ + CIM_NUM_OBQ] = { + "TP0", "TP1", "ULP", "SGE0", "SGE1", "NC-SI", /* ibq's */ + "ULP0", "ULP1", "ULP2", "ULP3", "SGE", "NC-SI" /* obq's */ +}; + +static int +sysctl_cim_ibq_obq(SYSCTL_HANDLER_ARGS) +{ + struct adapter *sc = arg1; + struct sbuf *sb; + int rc, i, n, qid = arg2; + uint32_t *buf, *p; + char *qtype; + + KASSERT(qid >= 0 && qid < nitems(qname), + ("%s: bad qid %d\n", __func__, qid)); + + if (qid < CIM_NUM_IBQ) { + /* inbound queue */ + qtype = "IBQ"; + n = 4 * CIM_IBQ_SIZE; + buf = malloc(n * sizeof(uint32_t), M_CXGBE, M_ZERO | M_WAITOK); + rc = t4_read_cim_ibq(sc, qid, buf, n); + } else { + /* outbound queue */ + qtype = "OBQ"; + qid -= CIM_NUM_IBQ; + n = 4 * 6 * CIM_OBQ_SIZE; + buf = malloc(n * sizeof(uint32_t), M_CXGBE, M_ZERO | M_WAITOK); + rc = t4_read_cim_obq(sc, qid, buf, n); + } + + if (rc < 0) { + rc = -rc; + goto done; + } + n = rc * sizeof(uint32_t); /* rc has # of words actually read */ + + rc = sysctl_wire_old_buffer(req, 0); + if (rc != 0) + goto done; + + sb = sbuf_new_for_sysctl(NULL, NULL, 4096, req); + if (sb == NULL) { + rc = ENOMEM; + goto done; + } + + sbuf_printf(sb, "%s%d %s", qtype , qid, qname[arg2]); + for (i = 0, p = buf; i < n; i += 16, p += 4) + sbuf_printf(sb, "\n%#06x: %08x %08x %08x %08x", i, p[0], p[1], + p[2], p[3]); + + rc = sbuf_finish(sb); + sbuf_delete(sb); +done: + free(buf, M_CXGBE); + return (rc); +} + +static int +sysctl_cim_la(SYSCTL_HANDLER_ARGS) +{ + struct adapter *sc = arg1; + u_int cfg; + struct sbuf *sb; + uint32_t *buf, *p; + int rc; + + rc = -t4_cim_read(sc, A_UP_UP_DBG_LA_CFG, 1, &cfg); + if (rc != 0) + return (rc); + + rc = sysctl_wire_old_buffer(req, 0); + if (rc != 0) + return (rc); + + sb = sbuf_new_for_sysctl(NULL, NULL, 4096, req); + if (sb == NULL) + return (ENOMEM); + + buf = malloc(sc->params.cim_la_size * sizeof(uint32_t), M_CXGBE, + M_ZERO | M_WAITOK); + + rc = -t4_cim_read_la(sc, buf, NULL); + if (rc != 0) + goto done; + + sbuf_printf(sb, "Status Data PC%s", + cfg & F_UPDBGLACAPTPCONLY ? "" : + " LS0Stat LS0Addr LS0Data"); + + KASSERT((sc->params.cim_la_size & 7) == 0, + ("%s: p will walk off the end of buf", __func__)); + + for (p = buf; p < &buf[sc->params.cim_la_size]; p += 8) { + if (cfg & F_UPDBGLACAPTPCONLY) { + sbuf_printf(sb, "\n %02x %08x %08x", p[5] & 0xff, + p[6], p[7]); + sbuf_printf(sb, "\n %02x %02x%06x %02x%06x", + (p[3] >> 8) & 0xff, p[3] & 0xff, p[4] >> 8, + p[4] & 0xff, p[5] >> 8); + sbuf_printf(sb, "\n %02x %x%07x %x%07x", + (p[0] >> 4) & 0xff, p[0] & 0xf, p[1] >> 4, + p[1] & 0xf, p[2] >> 4); + } else { + sbuf_printf(sb, + "\n %02x %x%07x %x%07x %08x %08x " + "%08x%08x%08x%08x", + (p[0] >> 4) & 0xff, p[0] & 0xf, p[1] >> 4, + p[1] & 0xf, p[2] >> 4, p[2] & 0xf, p[3], p[4], p[5], + p[6], p[7]); + } + } + + rc = sbuf_finish(sb); + sbuf_delete(sb); +done: + free(buf, M_CXGBE); + return (rc); +} + +static int +sysctl_cim_qcfg(SYSCTL_HANDLER_ARGS) +{ + struct adapter *sc = arg1; + struct sbuf *sb; + int rc, i; + uint16_t base[CIM_NUM_IBQ + CIM_NUM_OBQ]; + uint16_t size[CIM_NUM_IBQ + CIM_NUM_OBQ]; + uint16_t thres[CIM_NUM_IBQ]; + uint32_t obq_wr[2 * CIM_NUM_OBQ], *wr = obq_wr; + uint32_t stat[4 * (CIM_NUM_IBQ + CIM_NUM_OBQ)], *p = stat; + + rc = -t4_cim_read(sc, A_UP_IBQ_0_RDADDR, nitems(stat), stat); + if (rc == 0) + rc = -t4_cim_read(sc, A_UP_OBQ_0_REALADDR, nitems(obq_wr), + obq_wr); + if (rc != 0) + return (rc); + + t4_read_cimq_cfg(sc, base, size, thres); + + rc = sysctl_wire_old_buffer(req, 0); + if (rc != 0) + return (rc); + + sb = sbuf_new_for_sysctl(NULL, NULL, 4096, req); + if (sb == NULL) + return (ENOMEM); + + sbuf_printf(sb, "Queue Base Size Thres RdPtr WrPtr SOP EOP Avail"); + + for (i = 0; i < CIM_NUM_IBQ; i++, p += 4) + sbuf_printf(sb, "\n%5s %5x %5u %4u %6x %4x %4u %4u %5u", + qname[i], base[i], size[i], thres[i], G_IBQRDADDR(p[0]), + G_IBQWRADDR(p[1]), G_QUESOPCNT(p[3]), G_QUEEOPCNT(p[3]), + G_QUEREMFLITS(p[2]) * 16); + for ( ; i < CIM_NUM_IBQ + CIM_NUM_OBQ; i++, p += 4, wr += 2) + sbuf_printf(sb, "\n%5s %5x %5u %11x %4x %4u %4u %5u", qname[i], + base[i], size[i], G_QUERDADDR(p[0]) & 0x3fff, + wr[0] - base[i], G_QUESOPCNT(p[3]), G_QUEEOPCNT(p[3]), + G_QUEREMFLITS(p[2]) * 16); + + rc = sbuf_finish(sb); + sbuf_delete(sb); + + return (rc); +} + static int sysctl_cpl_stats(SYSCTL_HANDLER_ARGS) { From 7fc1dbca014cf0618ae440757472665d3b86c547 Mon Sep 17 00:00:00 2001 From: Brooks Davis Date: Thu, 21 Feb 2013 20:44:53 +0000 Subject: [PATCH 0344/1476] Vendor import of NetBSD's vis(1) at 2013-02-21 --- Makefile | 7 ++ extern.h | 39 ++++++++ foldit.c | 78 ++++++++++++++++ vis.1 | 169 ++++++++++++++++++++++++++++++++++ vis.c | 276 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 569 insertions(+) create mode 100644 Makefile create mode 100644 extern.h create mode 100644 foldit.c create mode 100644 vis.1 create mode 100644 vis.c diff --git a/Makefile b/Makefile new file mode 100644 index 00000000000..696b62a73db --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +# $NetBSD: Makefile,v 1.3 1994/11/17 07:55:57 jtc Exp $ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +PROG= vis +SRCS= vis.c foldit.c + +.include diff --git a/extern.h b/extern.h new file mode 100644 index 00000000000..49b6f15b3ba --- /dev/null +++ b/extern.h @@ -0,0 +1,39 @@ +/* $NetBSD: extern.h,v 1.1 2009/02/10 23:06:31 christos Exp $ */ + +/*- + * Copyright (c) 2009 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +int foldit(const char *, int, int, int); diff --git a/foldit.c b/foldit.c new file mode 100644 index 00000000000..789b14cb67c --- /dev/null +++ b/foldit.c @@ -0,0 +1,78 @@ +/* $NetBSD: foldit.c,v 1.7 2009/02/10 23:06:31 christos Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)foldit.c 8.1 (Berkeley) 6/6/93"; +#endif +__RCSID("$NetBSD: foldit.c,v 1.7 2009/02/10 23:06:31 christos Exp $"); +#endif /* not lint */ + +#include +#include +#include "extern.h" + +int +foldit(const char *chunk, int col, int max, int flags) +{ + const char *cp; + + /* + * Keep track of column position. Insert hidden newline + * if this chunk puts us over the limit. + */ +again: + cp = chunk; + while (*cp) { + switch(*cp) { + case '\n': + case '\r': + col = 0; + break; + case '\t': + col = (col + 8) &~ 07; + break; + case '\b': + col = col ? col - 1 : 0; + break; + default: + col++; + } + if (col > (max - 2)) { + printf(flags & VIS_MIMESTYLE ? "=\n" : "\\\n"); + col = 0; + goto again; + } + cp++; + } + return (col); +} diff --git a/vis.1 b/vis.1 new file mode 100644 index 00000000000..1b0b5edf4a8 --- /dev/null +++ b/vis.1 @@ -0,0 +1,169 @@ +.\" $NetBSD: vis.1,v 1.17 2013/02/14 14:00:00 christos Exp $ +.\" +.\" Copyright (c) 1989, 1991, 1993, 1994 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)vis.1 8.4 (Berkeley) 4/19/94 +.\" +.Dd February 13, 2013 +.Dt VIS 1 +.Os +.Sh NAME +.Nm vis +.Nd display non-printable characters in a visual format +.Sh SYNOPSIS +.Nm +.Op Fl bcfhlmnostw +.Op Fl e Ar extra +.Op Fl F Ar foldwidth +.Op Ar file ... +.Sh DESCRIPTION +.Nm +is a filter for converting non-printable characters +into a visual representation. +It differs from +.Ql cat -v +in that +the form is unique and invertible. +By default, all non-graphic +characters except space, tab, and newline are encoded. +A detailed description of the +various visual formats is given in +.Xr vis 3 . +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl b +Turns off prepending of backslash before up-arrow control sequences +and meta characters, and disables the doubling of backslashes. +This +produces output which is neither invertible or precise, but does +represent a minimum of change to the input. +It is similar to +.Dq Li cat -v . +.Pq Dv VIS_NOSLASH +.It Fl c +Request a format which displays a small subset of the +non-printable characters using C-style backslash sequences. +.Pq Dv VIS_CSTYLE +.It Fl e Ar extra +Also encode characters in +.Ar extra , +per +.Xr svis 3 . +.It Fl F Ar foldwidth +Causes +.Nm +to fold output lines to foldwidth columns (default 80), like +.Xr fold 1 , +except +that a hidden newline sequence is used, (which is removed +when inverting the file back to its original form with +.Xr unvis 1 ) . +If the last character in the encoded file does not end in a newline, +a hidden newline sequence is appended to the output. +This makes +the output usable with various editors and other utilities which +typically don't work with partial lines. +.It Fl f +Same as +.Fl F . +.It Fl h +Encode using the URI encoding from RFC 1808. +.Pq Dv VIS_HTTPSTYLE +.It Fl l +Mark newlines with the visible sequence +.Ql \e$ , +followed by the newline. +.It Fl m +Encode using the MIME Quoted-Printable encoding from RFC 2045. +.Pq Dv VIS_MIMESTYLE +.It Fl n +Turns off any encoding, except for the fact that backslashes are +still doubled and hidden newline sequences inserted if +.Fl f +or +.Fl F +is selected. +When combined with the +.Fl f +flag, +.Nm +becomes like +an invertible version of the +.Xr fold 1 +utility. +That is, the output can be unfolded by running the output through +.Xr unvis 1 . +.It Fl o +Request a format which displays non-printable characters as +an octal number, \eddd. +.Pq Dv VIS_OCTAL +.It Fl s +Only characters considered unsafe to send to a terminal are encoded. +This flag allows backspace, bell, and carriage return in addition +to the default space, tab and newline. +.Pq Dv VIS_SAFE +.It Fl t +Tabs are also encoded. +.Pq Dv VIS_TAB +.It Fl w +White space (space-tab-newline) is also encoded. +.Pq Dv VIS_WHITE +.El +.Sh MULTIBYTE CHARACTER SUPPORT +.Nm +supports multibyte character input. +The encoding conversion is influenced by the setting of the +.Ev LC_CTYPE +environment variable which defines the set of characters that can be +copied without encoding. +.Pp +When 8-bit data is present in the input, +.Ev LC_CTYPE +must be set to the correct locale or to the C locale. +If the locales of the data and the conversion are mismatched, multibyte +character recognition may fail and encoding will be performed byte-by-byte +instead. +.Sh ENVIRONMENT +.Bl -tag -width ".Ev LC_CTYPE" +.It Ev LC_CTYPE +Specify the locale of the input data. +Set to C if the input data locale is unknown. +.Sh SEE ALSO +.Xr unvis 1 , +.Xr svis 3 , +.Xr vis 3 +.Sh HISTORY +The +.Nm +command appears in +.Bx 4.4 . +Myltibyte character support was added in +.Nx 6.1 +and +.Fx 9.2 . diff --git a/vis.c b/vis.c new file mode 100644 index 00000000000..1509c81c412 --- /dev/null +++ b/vis.c @@ -0,0 +1,276 @@ +/* $NetBSD: vis.c,v 1.22 2013/02/20 17:04:45 christos Exp $ */ + +/*- + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#ifndef lint +__COPYRIGHT("@(#) Copyright (c) 1989, 1993\ + The Regents of the University of California. All rights reserved."); +#endif /* not lint */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)vis.c 8.1 (Berkeley) 6/6/93"; +#endif +__RCSID("$NetBSD: vis.c,v 1.22 2013/02/20 17:04:45 christos Exp $"); +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "extern.h" + +static int eflags, fold, foldwidth = 80, none, markeol; +#ifdef DEBUG +int debug; +#endif +static const char *extra = ""; + +static void process(FILE *); + +int +main(int argc, char *argv[]) +{ + FILE *fp; + int ch; + int rval; + + while ((ch = getopt(argc, argv, "bcde:F:fhlmnostw")) != -1) + switch((char)ch) { + case 'b': + eflags |= VIS_NOSLASH; + break; + case 'c': + eflags |= VIS_CSTYLE; + break; +#ifdef DEBUG + case 'd': + debug++; + break; +#endif + case 'e': + extra = optarg; + break; + case 'F': + if ((foldwidth = atoi(optarg)) < 5) { + errx(1, "can't fold lines to less than 5 cols"); + /* NOTREACHED */ + } + markeol++; + break; + case 'f': + fold++; /* fold output lines to 80 cols */ + break; /* using hidden newline */ + case 'h': + eflags |= VIS_HTTPSTYLE; + break; + case 'l': + markeol++; /* mark end of line with \$ */ + break; + case 'm': + eflags |= VIS_MIMESTYLE; + if (foldwidth == 80) + foldwidth = 76; + break; + case 'n': + none++; + break; + case 'o': + eflags |= VIS_OCTAL; + break; + case 's': + eflags |= VIS_SAFE; + break; + case 't': + eflags |= VIS_TAB; + break; + case 'w': + eflags |= VIS_WHITE; + break; + case '?': + default: + (void)fprintf(stderr, + "Usage: %s [-bcfhlmnostw] [-e extra]" + " [-F foldwidth] [file ...]\n", getprogname()); + return 1; + } + + if ((eflags & (VIS_HTTPSTYLE|VIS_MIMESTYLE)) == + (VIS_HTTPSTYLE|VIS_MIMESTYLE)) + errx(1, "Can't specify -m and -h at the same time"); + + argc -= optind; + argv += optind; + + rval = 0; + + if (*argv) + while (*argv) { + if ((fp = fopen(*argv, "r")) != NULL) { + process(fp); + (void)fclose(fp); + } else { + warn("%s", *argv); + rval = 1; + } + argv++; + } + else + process(stdin); + return rval; +} + +static void +process(FILE *fp) +{ + static int col = 0; + static char nul[] = "\0"; + char *cp = nul + 1; /* so *(cp-1) starts out != '\n' */ + wint_t c, c1, rachar; + char mbibuff[2 * MB_LEN_MAX + 1]; /* max space for 2 wchars */ + char buff[4 * MB_LEN_MAX + 1]; /* max encoding length for one char */ + int mbilen, cerr = 0, raerr = 0; + + /* + * The input stream is considered to be multibyte characters. + * The input loop will read this data inputing one character, + * possibly multiple bytes, at a time and converting each to + * a wide character wchar_t. + * + * The vis(3) functions, however, require single either bytes + * or a multibyte string as their arguments. So we convert + * our input wchar_t and the following look-ahead wchar_t to + * a multibyte string for processing by vis(3). + */ + + /* Read one multibyte character, store as wchar_t */ + c = getwc(fp); + if (c == WEOF && errno == EILSEQ) { + /* Error in multibyte data. Read one byte. */ + c = (wint_t)getc(fp); + cerr = 1; + } + while (c != WEOF) { + /* Clear multibyte input buffer. */ + memset(mbibuff, 0, sizeof(mbibuff)); + /* Read-ahead next multibyte character. */ + if (!cerr) + rachar = getwc(fp); + if (cerr || (rachar == WEOF && errno == EILSEQ)) { + /* Error in multibyte data. Read one byte. */ + rachar = (wint_t)getc(fp); + raerr = 1; + } + if (none) { + /* Handle -n flag. */ + cp = buff; + *cp++ = c; + if (c == '\\') + *cp++ = '\\'; + *cp = '\0'; + } else if (markeol && c == '\n') { + /* Handle -l flag. */ + cp = buff; + if ((eflags & VIS_NOSLASH) == 0) + *cp++ = '\\'; + *cp++ = '$'; + *cp++ = '\n'; + *cp = '\0'; + } else { + /* + * Convert character using vis(3) library. + * At this point we will process one character. + * But we must pass the vis(3) library this + * character plus the next one because the next + * one is used as a look-ahead to decide how to + * encode this one under certain circumstances. + * + * Since our characters may be multibyte, e.g., + * in the UTF-8 locale, we cannot use vis() and + * svis() which require byte input, so we must + * create a multibyte string and use strvisx(). + */ + /* Treat EOF as a NUL char. */ + c1 = rachar; + if (c1 == WEOF) + c1 = L'\0'; + /* + * If we hit a multibyte conversion error above, + * insert byte directly into string buff because + * wctomb() will fail. Else convert wchar_t to + * multibyte using wctomb(). + */ + if (cerr) { + *mbibuff = (char)c; + mbilen = 1; + } else + mbilen = wctomb(mbibuff, c); + /* Same for look-ahead character. */ + if (raerr) + mbibuff[mbilen] = (char)c1; + else + wctomb(mbibuff + mbilen, c1); + /* Perform encoding on just first character. */ + (void) strsenvisx(buff, 4 * MB_LEN_MAX, mbibuff, + 1, eflags, extra, &cerr); + } + + cp = buff; + if (fold) { +#ifdef DEBUG + if (debug) + (void)printf("<%02d,", col); +#endif + col = foldit(cp, col, foldwidth, eflags); +#ifdef DEBUG + if (debug) + (void)printf("%02d>", col); +#endif + } + do { + (void)putchar(*cp); + } while (*++cp); + c = rachar; + cerr = raerr; + } + /* + * terminate partial line with a hidden newline + */ + if (fold && *(cp - 1) != '\n') + (void)printf(eflags & VIS_MIMESTYLE ? "=\n" : "\\\n"); +} From fe9a760737d4905e72a36b1e605fc92d0eee5833 Mon Sep 17 00:00:00 2001 From: Sergey Kandaurov Date: Thu, 21 Feb 2013 20:45:19 +0000 Subject: [PATCH 0345/1476] Separate items in the list of System values with .Pp to ease readability. --- sbin/devd/devd.conf.5 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sbin/devd/devd.conf.5 b/sbin/devd/devd.conf.5 index 4c1893d366f..8ae8bf48133 100644 --- a/sbin/devd/devd.conf.5 +++ b/sbin/devd/devd.conf.5 @@ -350,6 +350,7 @@ The network interface is attached to the system. The network interface is detached from the system. .El .El +.Pp .It Li DEVFS Events related to the .Xr devfs 5 @@ -369,6 +370,7 @@ The node is destroyed. .El .El +.Pp .It Li USB Events related to the USB subsystem. .Bl -tag -width ".Sy Subsystem" -compact @@ -390,6 +392,7 @@ USB interface is attached to a device. USB interface is detached from a device. .El .El +.Pp .It Li coretemp Events related to the .Xr coretemp 4 @@ -404,6 +407,7 @@ Notification that the CPU core has reached critical temperature. String containing the temperature of the core that has become too hot. .El .El +.Pp .It Li kern Events related to the kernel. .Bl -tag -width ".Sy Subsystem" -compact From e95bfcdd038fc110fa63e283763638d6893568ce Mon Sep 17 00:00:00 2001 From: Brooks Davis Date: Thu, 21 Feb 2013 21:09:55 +0000 Subject: [PATCH 0346/1476] Vendor import of NetBSD's unvis(1) at 2013-02-21 --- Makefile | 6 +++ unvis.1 | 80 ++++++++++++++++++++++++++++++++ unvis.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 224 insertions(+) create mode 100644 Makefile create mode 100644 unvis.1 create mode 100644 unvis.c diff --git a/Makefile b/Makefile new file mode 100644 index 00000000000..677e61d94d8 --- /dev/null +++ b/Makefile @@ -0,0 +1,6 @@ +# $NetBSD: Makefile,v 1.3 1994/12/06 07:36:07 jtc Exp $ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +PROG= unvis + +.include diff --git a/unvis.1 b/unvis.1 new file mode 100644 index 00000000000..5c84671552e --- /dev/null +++ b/unvis.1 @@ -0,0 +1,80 @@ +.\" $NetBSD: unvis.1,v 1.10 2012/12/15 02:08:13 uwe Exp $ +.\" +.\" Copyright (c) 1989, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)unvis.1 8.1 (Berkeley) 6/6/93 +.\" +.Dd November 27, 2010 +.Dt UNVIS 1 +.Os +.Sh NAME +.Nm unvis +.Nd "revert a visual representation of data back to original form" +.Sh SYNOPSIS +.Nm +.Op Fl e +.Op Fl Hh | Fl m +.Op Ar file ... +.Sh DESCRIPTION +.Nm +is the inverse function of +.Xr vis 1 . +It reverts +a visual representation of data back to its original form on standard output. +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl e +Don't decode \e escaped sequences. +.It Fl H +Decode entity references and numeric character references from RFC 1866. +.Pq Dv VIS_HTTP1866 +.It Fl h +Decode using the URI encoding from RFC 1808. +.Pq Dv VIS_HTTP1808 +.It Fl m +Decode using mime style. +.Pq Dv VIS_MIMESTYLE +.El +.Pp +Mixing +.Fl h +or +.Fl H +with +.Fl m +is not supported. +.Sh SEE ALSO +.Xr vis 1 , +.Xr unvis 3 , +.Xr vis 3 +.Sh HISTORY +The +.Nm +command appears in +.Bx 4.4 . diff --git a/unvis.c b/unvis.c new file mode 100644 index 00000000000..d854a373117 --- /dev/null +++ b/unvis.c @@ -0,0 +1,138 @@ +/* $NetBSD: unvis.c,v 1.13 2010/11/27 19:46:25 christos Exp $ */ + +/*- + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#ifndef lint +__COPYRIGHT("@(#) Copyright (c) 1989, 1993\ + The Regents of the University of California. All rights reserved."); +#endif /* not lint */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)unvis.c 8.1 (Berkeley) 6/6/93"; +#endif +__RCSID("$NetBSD: unvis.c,v 1.13 2010/11/27 19:46:25 christos Exp $"); +#endif /* not lint */ + +#include +#include +#include +#include +#include + +static void process(FILE *, const char *, int); + +int +main(int argc, char *argv[]) +{ + FILE *fp; + int ch, eflags = 0; + + setprogname(argv[0]); + while ((ch = getopt(argc, argv, "eHhm")) != -1) + switch((char)ch) { + case 'e': + eflags |= VIS_NOESCAPE; + break; + case 'H': + eflags |= VIS_HTTP1866; + break; + case 'h': + eflags |= VIS_HTTP1808; + break; + case 'm': + eflags |= VIS_MIMESTYLE; + break; + case '?': + default: + (void)fprintf(stderr, + "Usage: %s [-e] [-Hh | -m] [file...]\n", + getprogname()); + return EXIT_FAILURE; + } + argc -= optind; + argv += optind; + + switch (eflags & (VIS_HTTP1808|VIS_HTTP1866|VIS_MIMESTYLE)) { + case VIS_HTTP1808|VIS_MIMESTYLE: + case VIS_HTTP1866|VIS_MIMESTYLE: + case VIS_HTTP1808|VIS_HTTP1866|VIS_MIMESTYLE: + errx(EXIT_FAILURE, "Can't mix -m with -h and/or -H"); + /*NOTREACHED*/ + default: + break; + } + + if (*argv) + while (*argv) { + if ((fp = fopen(*argv, "r")) != NULL) + process(fp, *argv, eflags); + else + warn("%s", *argv); + argv++; + } + else + process(stdin, "", eflags); + return EXIT_SUCCESS; +} + +static void +process(FILE *fp, const char *filename, int eflags) +{ + int offset = 0, c, ret; + int state = 0; + char outc; + + while ((c = getc(fp)) != EOF) { + offset++; + again: + switch(ret = unvis(&outc, (char)c, &state, eflags)) { + case UNVIS_VALID: + (void)putchar(outc); + break; + case UNVIS_VALIDPUSH: + (void)putchar(outc); + goto again; + case UNVIS_SYNBAD: + warnx("%s: offset: %d: can't decode", filename, offset); + state = 0; + break; + case 0: + case UNVIS_NOCHAR: + break; + default: + errx(1, "bad return value (%d), can't happen", ret); + /* NOTREACHED */ + } + } + if (unvis(&outc, (char)0, &state, eflags | UNVIS_END) == UNVIS_VALID) + (void)putchar(outc); +} From 26dd49c61d6c54d760571d04f558d08303e45e5a Mon Sep 17 00:00:00 2001 From: Andrew Gallatin Date: Thu, 21 Feb 2013 21:28:33 +0000 Subject: [PATCH 0347/1476] Improve mxge's receive performance for IPv6: - Add support for IPv6 rx csum offload - Finally switch mxge from using its own driver lro, to using tcp_lro MFC after: 7 days Sponsored by: Myricom Inc. --- sys/conf/files | 1 - sys/dev/mxge/if_mxge.c | 289 +++++++++++++------------- sys/dev/mxge/if_mxge_var.h | 32 +-- sys/dev/mxge/mxge_lro.c | 357 --------------------------------- sys/modules/mxge/mxge/Makefile | 2 +- 5 files changed, 149 insertions(+), 532 deletions(-) delete mode 100644 sys/dev/mxge/mxge_lro.c diff --git a/sys/conf/files b/sys/conf/files index c315254cca3..eee46bb5cbe 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1742,7 +1742,6 @@ mwlboot.fw optional mwlfw \ no-obj no-implicit-rule \ clean "mwlboot.fw" dev/mxge/if_mxge.c optional mxge pci -dev/mxge/mxge_lro.c optional mxge pci dev/mxge/mxge_eth_z8e.c optional mxge pci dev/mxge/mxge_ethp_z8e.c optional mxge pci dev/mxge/mxge_rss_eth_z8e.c optional mxge pci diff --git a/sys/dev/mxge/if_mxge.c b/sys/dev/mxge/if_mxge.c index 68afbf9a850..fcc08255e90 100644 --- a/sys/dev/mxge/if_mxge.c +++ b/sys/dev/mxge/if_mxge.c @@ -64,6 +64,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -102,7 +103,6 @@ static int mxge_intr_coal_delay = 30; static int mxge_deassert_wait = 1; static int mxge_flow_control = 1; static int mxge_verbose = 0; -static int mxge_lro_cnt = 8; static int mxge_ticks; static int mxge_max_slices = 1; static int mxge_rss_hash_type = MXGEFW_RSS_HASH_TYPE_SRC_DST_PORT; @@ -1311,9 +1311,9 @@ mxge_reset(mxge_softc_t *sc, int interrupts_setup) ss->tx.stall = 0; ss->rx_big.cnt = 0; ss->rx_small.cnt = 0; - ss->lro_bad_csum = 0; - ss->lro_queued = 0; - ss->lro_flushed = 0; + ss->lc.lro_bad_csum = 0; + ss->lc.lro_queued = 0; + ss->lc.lro_flushed = 0; if (ss->fw_stats != NULL) { bzero(ss->fw_stats, sizeof *ss->fw_stats); } @@ -1413,50 +1413,6 @@ mxge_change_flow_control(SYSCTL_HANDLER_ARGS) return err; } -static int -mxge_change_lro_locked(mxge_softc_t *sc, int lro_cnt) -{ - struct ifnet *ifp; - int err = 0; - - ifp = sc->ifp; - if (lro_cnt == 0) - ifp->if_capenable &= ~IFCAP_LRO; - else - ifp->if_capenable |= IFCAP_LRO; - sc->lro_cnt = lro_cnt; - if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - mxge_close(sc, 0); - err = mxge_open(sc); - } - return err; -} - -static int -mxge_change_lro(SYSCTL_HANDLER_ARGS) -{ - mxge_softc_t *sc; - unsigned int lro_cnt; - int err; - - sc = arg1; - lro_cnt = sc->lro_cnt; - err = sysctl_handle_int(oidp, &lro_cnt, arg2, req); - if (err != 0) - return err; - - if (lro_cnt == sc->lro_cnt) - return 0; - - if (lro_cnt > 128) - return EINVAL; - - mtx_lock(&sc->driver_mtx); - err = mxge_change_lro_locked(sc, lro_cnt); - mtx_unlock(&sc->driver_mtx); - return err; -} - static int mxge_handle_be32(SYSCTL_HANDLER_ARGS) { @@ -1653,14 +1609,6 @@ mxge_add_sysctls(mxge_softc_t *sc) CTLFLAG_RW, &mxge_verbose, 0, "verbose printing"); - /* lro */ - SYSCTL_ADD_PROC(ctx, children, OID_AUTO, - "lro_cnt", - CTLTYPE_INT|CTLFLAG_RW, sc, - 0, mxge_change_lro, - "I", "number of lro merge queues"); - - /* add counters exported for debugging from all slices */ sysctl_ctx_init(&sc->slice_sysctl_ctx); sc->slice_sysctl_tree = @@ -1686,11 +1634,15 @@ mxge_add_sysctls(mxge_softc_t *sc) CTLFLAG_RD, &ss->rx_big.cnt, 0, "rx_small_cnt"); SYSCTL_ADD_INT(ctx, children, OID_AUTO, - "lro_flushed", CTLFLAG_RD, &ss->lro_flushed, + "lro_flushed", CTLFLAG_RD, &ss->lc.lro_flushed, 0, "number of lro merge queues flushed"); SYSCTL_ADD_INT(ctx, children, OID_AUTO, - "lro_queued", CTLFLAG_RD, &ss->lro_queued, + "lro_bad_csum", CTLFLAG_RD, &ss->lc.lro_bad_csum, + 0, "number of bad csums preventing LRO"); + + SYSCTL_ADD_INT(ctx, children, OID_AUTO, + "lro_queued", CTLFLAG_RD, &ss->lc.lro_queued, 0, "number of frames appended to lro merge" "queues"); @@ -2534,6 +2486,64 @@ done: return err; } +#ifdef INET6 + +static uint16_t +mxge_csum_generic(uint16_t *raw, int len) +{ + uint32_t csum; + + + csum = 0; + while (len > 0) { + csum += *raw; + raw++; + len -= 2; + } + csum = (csum >> 16) + (csum & 0xffff); + csum = (csum >> 16) + (csum & 0xffff); + return (uint16_t)csum; +} + +static inline uint16_t +mxge_rx_csum6(void *p, struct mbuf *m, uint32_t csum) +{ + uint32_t partial; + int nxt, cksum_offset; + struct ip6_hdr *ip6 = p; + uint16_t c; + + nxt = ip6->ip6_nxt; + cksum_offset = sizeof (*ip6) + ETHER_HDR_LEN; + if (nxt != IPPROTO_TCP && nxt != IPPROTO_UDP) { + cksum_offset = ip6_lasthdr(m, ETHER_HDR_LEN, + IPPROTO_IPV6, &nxt); + if (nxt != IPPROTO_TCP && nxt != IPPROTO_UDP) + return (1); + } + + /* + * IPv6 headers do not contain a checksum, and hence + * do not checksum to zero, so they don't "fall out" + * of the partial checksum calculation like IPv4 + * headers do. We need to fix the partial checksum by + * subtracting the checksum of the IPv6 header. + */ + + partial = mxge_csum_generic((uint16_t *)ip6, cksum_offset - + ETHER_HDR_LEN); + csum += ~partial; + csum += (csum < ~partial); + csum = (csum >> 16) + (csum & 0xFFFF); + csum = (csum >> 16) + (csum & 0xFFFF); + c = in6_cksum_pseudo(ip6, m->m_pkthdr.len - cksum_offset, nxt, + csum); + +// printf("%d %d %x %x %x %x %x\n", m->m_pkthdr.len, cksum_offset, c, csum, ocsum, partial, d); + c ^= 0xffff; + return (c); +} +#endif /* INET6 */ /* * Myri10GE hardware checksums are not valid if the sender * padded the frame with non-zero padding. This is because @@ -2547,26 +2557,39 @@ static inline uint16_t mxge_rx_csum(struct mbuf *m, int csum) { struct ether_header *eh; +#ifdef INET struct ip *ip; - uint16_t c; +#endif + int cap = m->m_pkthdr.rcvif->if_capenable; + uint16_t c, etype; + eh = mtod(m, struct ether_header *); - - /* only deal with IPv4 TCP & UDP for now */ - if (__predict_false(eh->ether_type != htons(ETHERTYPE_IP))) - return 1; - ip = (struct ip *)(eh + 1); - if (__predict_false(ip->ip_p != IPPROTO_TCP && - ip->ip_p != IPPROTO_UDP)) - return 1; + etype = ntohs(eh->ether_type); + switch (etype) { #ifdef INET - c = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, - htonl(ntohs(csum) + ntohs(ip->ip_len) + - - (ip->ip_hl << 2) + ip->ip_p)); -#else - c = 1; + case ETHERTYPE_IP: + if ((cap & IFCAP_RXCSUM) == 0) + return (1); + ip = (struct ip *)(eh + 1); + if (ip->ip_p != IPPROTO_TCP && ip->ip_p != IPPROTO_UDP) + return (1); + c = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, + htonl(ntohs(csum) + ntohs(ip->ip_len) - + (ip->ip_hl << 2) + ip->ip_p)); + c ^= 0xffff; + break; #endif - c ^= 0xffff; +#ifdef INET6 + case ETHERTYPE_IPV6: + if ((cap & IFCAP_RXCSUM_IPV6) == 0) + return (1); + c = mxge_rx_csum6((eh + 1), m, csum); + break; +#endif + default: + c = 1; + } return (c); } @@ -2628,7 +2651,8 @@ mxge_vlan_tag_remove(struct mbuf *m, uint32_t *csum) static inline void -mxge_rx_done_big(struct mxge_slice_state *ss, uint32_t len, uint32_t csum) +mxge_rx_done_big(struct mxge_slice_state *ss, uint32_t len, + uint32_t csum, int lro) { mxge_softc_t *sc; struct ifnet *ifp; @@ -2637,7 +2661,6 @@ mxge_rx_done_big(struct mxge_slice_state *ss, uint32_t len, uint32_t csum) mxge_rx_ring_t *rx; bus_dmamap_t old_map; int idx; - uint16_t tcpudp_csum; sc = ss->sc; ifp = sc->ifp; @@ -2674,14 +2697,18 @@ mxge_rx_done_big(struct mxge_slice_state *ss, uint32_t len, uint32_t csum) mxge_vlan_tag_remove(m, &csum); } /* if the checksum is valid, mark it in the mbuf header */ - if (sc->csum_flag && (0 == (tcpudp_csum = mxge_rx_csum(m, csum)))) { - if (sc->lro_cnt && (0 == mxge_lro_rx(ss, m, csum))) - return; - /* otherwise, it was a UDP frame, or a TCP frame which - we could not do LRO on. Tell the stack that the - checksum is good */ + + if ((ifp->if_capenable & (IFCAP_RXCSUM_IPV6 | IFCAP_RXCSUM)) && + (0 == mxge_rx_csum(m, csum))) { + /* Tell the stack that the checksum is good */ m->m_pkthdr.csum_data = 0xffff; - m->m_pkthdr.csum_flags = CSUM_PSEUDO_HDR | CSUM_DATA_VALID; + m->m_pkthdr.csum_flags = CSUM_PSEUDO_HDR | + CSUM_DATA_VALID; + +#if defined(INET) || defined (INET6) + if (lro && (0 == tcp_lro_rx(&ss->lc, m, 0))) + return; +#endif } /* flowid only valid if RSS hashing is enabled */ if (sc->num_slices > 1) { @@ -2693,7 +2720,8 @@ mxge_rx_done_big(struct mxge_slice_state *ss, uint32_t len, uint32_t csum) } static inline void -mxge_rx_done_small(struct mxge_slice_state *ss, uint32_t len, uint32_t csum) +mxge_rx_done_small(struct mxge_slice_state *ss, uint32_t len, + uint32_t csum, int lro) { mxge_softc_t *sc; struct ifnet *ifp; @@ -2702,7 +2730,6 @@ mxge_rx_done_small(struct mxge_slice_state *ss, uint32_t len, uint32_t csum) mxge_rx_ring_t *rx; bus_dmamap_t old_map; int idx; - uint16_t tcpudp_csum; sc = ss->sc; ifp = sc->ifp; @@ -2739,14 +2766,17 @@ mxge_rx_done_small(struct mxge_slice_state *ss, uint32_t len, uint32_t csum) mxge_vlan_tag_remove(m, &csum); } /* if the checksum is valid, mark it in the mbuf header */ - if (sc->csum_flag && (0 == (tcpudp_csum = mxge_rx_csum(m, csum)))) { - if (sc->lro_cnt && (0 == mxge_lro_rx(ss, m, csum))) - return; - /* otherwise, it was a UDP frame, or a TCP frame which - we could not do LRO on. Tell the stack that the - checksum is good */ + if ((ifp->if_capenable & (IFCAP_RXCSUM_IPV6 | IFCAP_RXCSUM)) && + (0 == mxge_rx_csum(m, csum))) { + /* Tell the stack that the checksum is good */ m->m_pkthdr.csum_data = 0xffff; - m->m_pkthdr.csum_flags = CSUM_PSEUDO_HDR | CSUM_DATA_VALID; + m->m_pkthdr.csum_flags = CSUM_PSEUDO_HDR | + CSUM_DATA_VALID; + +#if defined(INET) || defined (INET6) + if (lro && (0 == tcp_lro_rx(&ss->lc, m, csum))) + return; +#endif } /* flowid only valid if RSS hashing is enabled */ if (sc->num_slices > 1) { @@ -2764,16 +2794,17 @@ mxge_clean_rx_done(struct mxge_slice_state *ss) int limit = 0; uint16_t length; uint16_t checksum; + int lro; - + lro = ss->sc->ifp->if_capenable & IFCAP_LRO; while (rx_done->entry[rx_done->idx].length != 0) { length = ntohs(rx_done->entry[rx_done->idx].length); rx_done->entry[rx_done->idx].length = 0; checksum = rx_done->entry[rx_done->idx].checksum; if (length <= (MHLEN - MXGEFW_PAD)) - mxge_rx_done_small(ss, length, checksum); + mxge_rx_done_small(ss, length, checksum, lro); else - mxge_rx_done_big(ss, length, checksum); + mxge_rx_done_big(ss, length, checksum, lro); rx_done->cnt++; rx_done->idx = rx_done->cnt & rx_done->mask; @@ -2781,11 +2812,11 @@ mxge_clean_rx_done(struct mxge_slice_state *ss) if (__predict_false(++limit > rx_done->mask / 2)) break; } -#ifdef INET - while (!SLIST_EMPTY(&ss->lro_active)) { - struct lro_entry *lro = SLIST_FIRST(&ss->lro_active); - SLIST_REMOVE_HEAD(&ss->lro_active, next); - mxge_lro_flush(ss, lro); +#if defined(INET) || defined (INET6) + while (!SLIST_EMPTY(&ss->lc.lro_active)) { + struct lro_entry *lro = SLIST_FIRST(&ss->lc.lro_active); + SLIST_REMOVE_HEAD(&ss->lc.lro_active, next); + tcp_lro_flush(&ss->lc, lro); } #endif } @@ -3153,15 +3184,11 @@ mxge_init(void *arg) static void mxge_free_slice_mbufs(struct mxge_slice_state *ss) { - struct lro_entry *lro_entry; int i; - while (!SLIST_EMPTY(&ss->lro_free)) { - lro_entry = SLIST_FIRST(&ss->lro_free); - SLIST_REMOVE_HEAD(&ss->lro_free, next); - free(lro_entry, M_DEVBUF); - } - +#if defined(INET) || defined(INET6) + tcp_lro_free(&ss->lc); +#endif for (i = 0; i <= ss->rx_big.mask; i++) { if (ss->rx_big.info[i].m == NULL) continue; @@ -3545,26 +3572,17 @@ mxge_slice_open(struct mxge_slice_state *ss, int nbufs, int cl_size) mxge_softc_t *sc; mxge_cmd_t cmd; bus_dmamap_t map; - struct lro_entry *lro_entry; int err, i, slice; sc = ss->sc; slice = ss - sc->ss; - SLIST_INIT(&ss->lro_free); - SLIST_INIT(&ss->lro_active); - - for (i = 0; i < sc->lro_cnt; i++) { - lro_entry = (struct lro_entry *) - malloc(sizeof (*lro_entry), M_DEVBUF, - M_NOWAIT | M_ZERO); - if (lro_entry == NULL) { - sc->lro_cnt = i; - break; - } - SLIST_INSERT_HEAD(&ss->lro_free, lro_entry, next); - } +#if defined(INET) || defined(INET6) + (void)tcp_lro_init(&ss->lc); +#endif + ss->lc.ifp = sc->ifp; + /* get the lanai pointers to the send and receive rings */ err = 0; @@ -4219,10 +4237,8 @@ mxge_ioctl(struct ifnet *ifp, u_long command, caddr_t data) } else if (mask & IFCAP_RXCSUM) { if (IFCAP_RXCSUM & ifp->if_capenable) { ifp->if_capenable &= ~IFCAP_RXCSUM; - sc->csum_flag = 0; } else { ifp->if_capenable |= IFCAP_RXCSUM; - sc->csum_flag = 1; } } if (mask & IFCAP_TSO4) { @@ -4249,16 +4265,12 @@ mxge_ioctl(struct ifnet *ifp, u_long command, caddr_t data) ifp->if_hwassist |= (CSUM_TCP_IPV6 | CSUM_UDP_IPV6); } -#ifdef NOTYET - } else if (mask & IFCAP_RXCSUM6) { - if (IFCAP_RXCSUM6 & ifp->if_capenable) { - ifp->if_capenable &= ~IFCAP_RXCSUM6; - sc->csum_flag = 0; + } else if (mask & IFCAP_RXCSUM_IPV6) { + if (IFCAP_RXCSUM_IPV6 & ifp->if_capenable) { + ifp->if_capenable &= ~IFCAP_RXCSUM_IPV6; } else { - ifp->if_capenable |= IFCAP_RXCSUM6; - sc->csum_flag = 1; + ifp->if_capenable |= IFCAP_RXCSUM_IPV6; } -#endif } if (mask & IFCAP_TSO6) { if (IFCAP_TSO6 & ifp->if_capenable) { @@ -4274,12 +4286,8 @@ mxge_ioctl(struct ifnet *ifp, u_long command, caddr_t data) } #endif /*IFCAP_TSO6 */ - if (mask & IFCAP_LRO) { - if (IFCAP_LRO & ifp->if_capenable) - err = mxge_change_lro_locked(sc, 0); - else - err = mxge_change_lro_locked(sc, mxge_lro_cnt); - } + if (mask & IFCAP_LRO) + ifp->if_capenable ^= IFCAP_LRO; if (mask & IFCAP_VLAN_HWTAGGING) ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING; if (mask & IFCAP_VLAN_HWTSO) @@ -4326,14 +4334,11 @@ mxge_fetch_tunables(mxge_softc_t *sc) TUNABLE_INT_FETCH("hw.mxge.verbose", &mxge_verbose); TUNABLE_INT_FETCH("hw.mxge.ticks", &mxge_ticks); - TUNABLE_INT_FETCH("hw.mxge.lro_cnt", &sc->lro_cnt); TUNABLE_INT_FETCH("hw.mxge.always_promisc", &mxge_always_promisc); TUNABLE_INT_FETCH("hw.mxge.rss_hash_type", &mxge_rss_hash_type); TUNABLE_INT_FETCH("hw.mxge.rss_hashtype", &mxge_rss_hash_type); TUNABLE_INT_FETCH("hw.mxge.initial_mtu", &mxge_initial_mtu); TUNABLE_INT_FETCH("hw.mxge.throttle", &mxge_throttle); - if (sc->lro_cnt != 0) - mxge_lro_cnt = sc->lro_cnt; if (bootverbose) mxge_verbose = 1; @@ -4897,8 +4902,9 @@ mxge_attach(device_t dev) if_initbaudrate(ifp, IF_Gbps(10)); ifp->if_capabilities = IFCAP_RXCSUM | IFCAP_TXCSUM | IFCAP_TSO4 | - IFCAP_VLAN_MTU | IFCAP_LINKSTATE | IFCAP_TXCSUM_IPV6; -#ifdef INET + IFCAP_VLAN_MTU | IFCAP_LINKSTATE | IFCAP_TXCSUM_IPV6 | + IFCAP_RXCSUM_IPV6; +#if defined(INET) || defined(INET6) ifp->if_capabilities |= IFCAP_LRO; #endif @@ -4929,7 +4935,6 @@ mxge_attach(device_t dev) ifp->if_capenable = ifp->if_capabilities; if (sc->lro_cnt == 0) ifp->if_capenable &= ~IFCAP_LRO; - sc->csum_flag = 1; ifp->if_init = mxge_init; ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; diff --git a/sys/dev/mxge/if_mxge_var.h b/sys/dev/mxge/if_mxge_var.h index 9393577106f..7ca1f3977aa 100644 --- a/sys/dev/mxge/if_mxge_var.h +++ b/sys/dev/mxge/if_mxge_var.h @@ -194,31 +194,6 @@ typedef struct char mtx_name[16]; } mxge_tx_ring_t; -struct lro_entry; -struct lro_entry -{ - SLIST_ENTRY(lro_entry) next; - struct mbuf *m_head; - struct mbuf *m_tail; - int timestamp; - struct ip *ip; - uint32_t tsval; - uint32_t tsecr; - uint32_t source_ip; - uint32_t dest_ip; - uint32_t next_seq; - uint32_t ack_seq; - uint32_t len; - uint32_t data_csum; - uint16_t window; - uint16_t source_port; - uint16_t dest_port; - uint16_t append_cnt; - uint16_t mss; - -}; -SLIST_HEAD(lro_head, lro_entry); - struct mxge_softc; typedef struct mxge_softc mxge_softc_t; @@ -236,11 +211,7 @@ struct mxge_slice_state { u_long omcasts; u_long oerrors; int if_drv_flags; - struct lro_head lro_active; - struct lro_head lro_free; - int lro_queued; - int lro_flushed; - int lro_bad_csum; + struct lro_ctrl lc; mxge_dma_t fw_stats_dma; struct sysctl_oid *sysctl_tree; struct sysctl_ctx_list sysctl_ctx; @@ -250,7 +221,6 @@ struct mxge_slice_state { struct mxge_softc { struct ifnet* ifp; struct mxge_slice_state *ss; - int csum_flag; /* rx_csums? */ int tx_boundary; /* boundary transmits cannot cross*/ int lro_cnt; bus_dma_tag_t parent_dmat; diff --git a/sys/dev/mxge/mxge_lro.c b/sys/dev/mxge/mxge_lro.c deleted file mode 100644 index b3130592f7a..00000000000 --- a/sys/dev/mxge/mxge_lro.c +++ /dev/null @@ -1,357 +0,0 @@ -/****************************************************************************** - -Copyright (c) 2007-2008, Myricom Inc. -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. Neither the name of the Myricom Inc, 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 -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include "opt_inet.h" - -#ifdef INET - -/* Assume len is a multiple of 4 */ -static uint16_t -mxge_csum_generic(uint16_t *raw, int len) -{ - uint32_t csum; - csum = 0; - while (len > 0) { - csum += *raw; - raw++; - csum += *raw; - raw++; - len -= 4; - } - csum = (csum >> 16) + (csum & 0xffff); - csum = (csum >> 16) + (csum & 0xffff); - return (uint16_t)csum; -} - - -void -mxge_lro_flush(struct mxge_slice_state *ss, struct lro_entry *lro) -{ - mxge_softc_t *mgp = ss->sc; - struct ifnet *ifp; - struct ip *ip; - struct tcphdr *tcp; - uint32_t *ts_ptr; - uint32_t tcplen, tcp_csum; - - if (lro->append_cnt) { - /* incorporate the new len into the ip header and - * re-calculate the checksum */ - ip = lro->ip; - ip->ip_len = htons(lro->len - ETHER_HDR_LEN); - ip->ip_sum = 0; - ip->ip_sum = 0xffff ^ - mxge_csum_generic((uint16_t*)ip, - sizeof (*ip)); - - lro->m_head->m_pkthdr.csum_flags = CSUM_IP_CHECKED | - CSUM_IP_VALID | CSUM_DATA_VALID | CSUM_PSEUDO_HDR; - lro->m_head->m_pkthdr.csum_data = 0xffff; - lro->m_head->m_pkthdr.len = lro->len; - - /* incorporate the latest ack into the tcp header */ - tcp = (struct tcphdr *) (ip + 1); - tcp->th_ack = lro->ack_seq; - tcp->th_win = lro->window; - /* incorporate latest timestamp into the tcp header */ - if (lro->timestamp) { - ts_ptr = (uint32_t *)(tcp + 1); - ts_ptr[1] = htonl(lro->tsval); - ts_ptr[2] = lro->tsecr; - } - /* - * update checksum in tcp header by re-calculating the - * tcp pseudoheader checksum, and adding it to the checksum - * of the tcp payload data - */ - tcp->th_sum = 0; - tcplen = lro->len - sizeof(*ip) - ETHER_HDR_LEN; - tcp_csum = lro->data_csum; - tcp_csum += in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, - htons(tcplen + IPPROTO_TCP)); - tcp_csum += mxge_csum_generic((uint16_t*)tcp, - tcp->th_off << 2); - tcp_csum = (tcp_csum & 0xffff) + (tcp_csum >> 16); - tcp_csum = (tcp_csum & 0xffff) + (tcp_csum >> 16); -#if 0 - IOLog("pseudo = 0x%x, generic = 0x%x, sum = %x\n", - in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, - htons(tcplen + IPPROTO_TCP)), - mxge_csum_generic((uint16_t*)tcp, - tcp->th_off << 2), - htons(0xffff ^ tcp_csum)); -#endif - tcp->th_sum = 0xffff ^ tcp_csum; - } - ifp = mgp->ifp; - (*ifp->if_input)(mgp->ifp, lro->m_head); - ss->lro_queued += lro->append_cnt + 1; - ss->lro_flushed++; - lro->m_head = NULL; - lro->timestamp = 0; - lro->append_cnt = 0; - SLIST_INSERT_HEAD(&ss->lro_free, lro, next); -} - -int -mxge_lro_rx(struct mxge_slice_state *ss, struct mbuf *m_head, uint32_t csum) -{ - struct ether_header *eh; - struct ip *ip; - struct tcphdr *tcp; - uint32_t *ts_ptr; - struct mbuf *m_nxt, *m_tail; - struct lro_entry *lro; - int hlen, ip_len, tcp_hdr_len, tcp_data_len, tot_len; - int opt_bytes, trim; - uint32_t seq, tmp_csum, device_mtu; - - eh = mtod(m_head, struct ether_header *); - if (eh->ether_type != htons(ETHERTYPE_IP)) - return 1; - ip = (struct ip *) (eh + 1); - if (ip->ip_p != IPPROTO_TCP) - return 1; - - /* ensure there are no options */ - if ((ip->ip_hl << 2) != sizeof (*ip)) - return -1; - - /* .. and the packet is not fragmented */ - if (ip->ip_off & htons(IP_MF|IP_OFFMASK)) - return -1; - - /* verify that the IP header checksum is correct */ - tmp_csum = mxge_csum_generic((uint16_t *)ip, sizeof (*ip)); - if (__predict_false((tmp_csum ^ 0xffff) != 0)) { - ss->lro_bad_csum++; - return -1; - } - - /* find the TCP header */ - tcp = (struct tcphdr *) (ip + 1); - - /* ensure no bits set besides ack or psh */ - if ((tcp->th_flags & ~(TH_ACK | TH_PUSH)) != 0) - return -1; - - /* check for timestamps. Since the only option we handle are - timestamps, we only have to handle the simple case of - aligned timestamps */ - - opt_bytes = (tcp->th_off << 2) - sizeof (*tcp); - tcp_hdr_len = sizeof (*tcp) + opt_bytes; - ts_ptr = (uint32_t *)(tcp + 1); - if (opt_bytes != 0) { - if (__predict_false(opt_bytes != TCPOLEN_TSTAMP_APPA) || - (*ts_ptr != ntohl(TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP))) - return -1; - } - - ip_len = ntohs(ip->ip_len); - tcp_data_len = ip_len - (tcp->th_off << 2) - sizeof (*ip); - - - /* - * If frame is padded beyond the end of the IP packet, - * then we must trim the extra bytes off the end. - */ - tot_len = m_head->m_pkthdr.len; - trim = tot_len - (ip_len + ETHER_HDR_LEN); - if (trim != 0) { - if (trim < 0) { - /* truncated packet */ - return -1; - } - m_adj(m_head, -trim); - tot_len = m_head->m_pkthdr.len; - } - - m_nxt = m_head; - m_tail = NULL; /* -Wuninitialized */ - while (m_nxt != NULL) { - m_tail = m_nxt; - m_nxt = m_tail->m_next; - } - - hlen = ip_len + ETHER_HDR_LEN - tcp_data_len; - seq = ntohl(tcp->th_seq); - - SLIST_FOREACH(lro, &ss->lro_active, next) { - if (lro->source_port == tcp->th_sport && - lro->dest_port == tcp->th_dport && - lro->source_ip == ip->ip_src.s_addr && - lro->dest_ip == ip->ip_dst.s_addr) { - /* Try to append it */ - - if (__predict_false(seq != lro->next_seq || - (tcp_data_len == 0 && - lro->ack_seq == tcp->th_ack))) { - /* out of order packet or dup ack */ - SLIST_REMOVE(&ss->lro_active, lro, - lro_entry, next); - mxge_lro_flush(ss, lro); - return -1; - } - - if (opt_bytes) { - uint32_t tsval = ntohl(*(ts_ptr + 1)); - /* make sure timestamp values are increasing */ - if (__predict_false(lro->tsval > tsval || - *(ts_ptr + 2) == 0)) { - return -1; - } - lro->tsval = tsval; - lro->tsecr = *(ts_ptr + 2); - } - - lro->next_seq += tcp_data_len; - lro->ack_seq = tcp->th_ack; - lro->window = tcp->th_win; - lro->append_cnt++; - if (tcp_data_len == 0) { - m_freem(m_head); - return 0; - } - /* subtract off the checksum of the tcp header - * from the hardware checksum, and add it to the - * stored tcp data checksum. Byteswap the checksum - * if the total length so far is odd - */ - tmp_csum = mxge_csum_generic((uint16_t*)tcp, - tcp_hdr_len); - csum = csum + (tmp_csum ^ 0xffff); - csum = (csum & 0xffff) + (csum >> 16); - csum = (csum & 0xffff) + (csum >> 16); - if (lro->len & 0x1) { - /* Odd number of bytes so far, flip bytes */ - csum = ((csum << 8) | (csum >> 8)) & 0xffff; - } - csum = csum + lro->data_csum; - csum = (csum & 0xffff) + (csum >> 16); - csum = (csum & 0xffff) + (csum >> 16); - lro->data_csum = csum; - - lro->len += tcp_data_len; - - /* adjust mbuf so that m->m_data points to - the first byte of the payload */ - m_adj(m_head, hlen); - /* append mbuf chain */ - lro->m_tail->m_next = m_head; - /* advance the last pointer */ - lro->m_tail = m_tail; - /* flush packet if required */ - device_mtu = ss->sc->ifp->if_mtu; - if (lro->len > (65535 - device_mtu)) { - SLIST_REMOVE(&ss->lro_active, lro, - lro_entry, next); - mxge_lro_flush(ss, lro); - } - return 0; - } - } - - if (SLIST_EMPTY(&ss->lro_free)) - return -1; - - /* start a new chain */ - lro = SLIST_FIRST(&ss->lro_free); - SLIST_REMOVE_HEAD(&ss->lro_free, next); - SLIST_INSERT_HEAD(&ss->lro_active, lro, next); - lro->source_port = tcp->th_sport; - lro->dest_port = tcp->th_dport; - lro->source_ip = ip->ip_src.s_addr; - lro->dest_ip = ip->ip_dst.s_addr; - lro->next_seq = seq + tcp_data_len; - lro->mss = tcp_data_len; - lro->ack_seq = tcp->th_ack; - lro->window = tcp->th_win; - - /* save the checksum of just the TCP payload by - * subtracting off the checksum of the TCP header from - * the entire hardware checksum - * Since IP header checksum is correct, checksum over - * the IP header is -0. Substracting -0 is unnecessary. - */ - tmp_csum = mxge_csum_generic((uint16_t*)tcp, tcp_hdr_len); - csum = csum + (tmp_csum ^ 0xffff); - csum = (csum & 0xffff) + (csum >> 16); - csum = (csum & 0xffff) + (csum >> 16); - lro->data_csum = csum; - - lro->ip = ip; - /* record timestamp if it is present */ - if (opt_bytes) { - lro->timestamp = 1; - lro->tsval = ntohl(*(ts_ptr + 1)); - lro->tsecr = *(ts_ptr + 2); - } - lro->len = tot_len; - lro->m_head = m_head; - lro->m_tail = m_tail; - return 0; -} - -#endif /* INET */ -/* - This file uses Myri10GE driver indentation. - - Local Variables: - c-file-style:"linux" - tab-width:8 - End: -*/ diff --git a/sys/modules/mxge/mxge/Makefile b/sys/modules/mxge/mxge/Makefile index 90c30eb84b8..3f1f80f4ef5 100644 --- a/sys/modules/mxge/mxge/Makefile +++ b/sys/modules/mxge/mxge/Makefile @@ -3,6 +3,6 @@ .PATH: ${.CURDIR}/../../../dev/mxge KMOD= if_mxge -SRCS= if_mxge.c mxge_lro.c device_if.h bus_if.h pci_if.h opt_inet.h opt_inet6.h +SRCS= if_mxge.c device_if.h bus_if.h pci_if.h opt_inet.h opt_inet6.h .include From 75dbe5f2b6ecf472c93c42fa2fc690662c6b7b81 Mon Sep 17 00:00:00 2001 From: Sergey Kandaurov Date: Thu, 21 Feb 2013 21:35:09 +0000 Subject: [PATCH 0348/1476] Reflect CARP media-type departure. X-MFC after: never --- sbin/devd/devd.conf.5 | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sbin/devd/devd.conf.5 b/sbin/devd/devd.conf.5 index 8ae8bf48133..311228ec28e 100644 --- a/sbin/devd/devd.conf.5 +++ b/sbin/devd/devd.conf.5 @@ -41,7 +41,7 @@ .\" ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS .\" SOFTWARE. .\" -.Dd December 16, 2011 +.Dd February 22, 2013 .Dt DEVD.CONF 5 .Os .Sh NAME @@ -181,9 +181,8 @@ Valid media types are: .Dq Li Tokenring , .Dq Li FDDI , .Dq Li 802.11 , -.Dq Li ATM , and -.Dq Li CARP . +.Dq Li ATM . .It Ic subdevice Qq Ar string ; This is shorthand for .Dq Ic match Qo Li subdevice Qc Qq Ar string . From ce597531f2c7c6bdd50812f3a4399bb50d8427df Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Thu, 21 Feb 2013 21:47:35 +0000 Subject: [PATCH 0349/1476] Disable debugging entries about BAW issues. I haven't seen any issues to do with BAW tracking in the last 9 months or so. --- sys/dev/ath/if_ath.c | 2 ++ sys/dev/ath/if_ath_tx.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 98c219bb76c..2ea3909fb59 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -3631,12 +3631,14 @@ ath_tx_default_comp(struct ath_softc *sc, struct ath_buf *bf, int fail) st = ((bf->bf_state.bfs_txflags & HAL_TXDESC_NOACK) == 0) ? ts->ts_status : HAL_TXERR_XRETRY; +#if 0 if (bf->bf_state.bfs_dobaw) device_printf(sc->sc_dev, "%s: bf %p: seqno %d: dobaw should've been cleared!\n", __func__, bf, SEQNO(bf->bf_state.bfs_seqno)); +#endif if (bf->bf_next != NULL) device_printf(sc->sc_dev, "%s: bf %p: seqno %d: bf_next not NULL!\n", diff --git a/sys/dev/ath/if_ath_tx.c b/sys/dev/ath/if_ath_tx.c index f3ce0e754dc..92b28c60e53 100644 --- a/sys/dev/ath/if_ath_tx.c +++ b/sys/dev/ath/if_ath_tx.c @@ -3373,6 +3373,7 @@ ath_tx_tid_drain_pkt(struct ath_softc *sc, struct ath_node *an, ath_tx_update_baw(sc, an, tid, bf); bf->bf_state.bfs_dobaw = 0; } +#if 0 /* * This has become a non-fatal error now */ @@ -3380,6 +3381,7 @@ ath_tx_tid_drain_pkt(struct ath_softc *sc, struct ath_node *an, device_printf(sc->sc_dev, "%s: wasn't added: seqno %d\n", __func__, SEQNO(bf->bf_state.bfs_seqno)); +#endif } TAILQ_INSERT_TAIL(bf_cq, bf, bf_list); } From 5e0fb0052bdc180c9685a7038f575340e85522ef Mon Sep 17 00:00:00 2001 From: Sergey Kandaurov Date: Thu, 21 Feb 2013 22:21:45 +0000 Subject: [PATCH 0350/1476] Document VFCF_SBDRY. Reviewed by: jhb X-MFC with: r247116 --- share/man/man9/VFS_SET.9 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/share/man/man9/VFS_SET.9 b/share/man/man9/VFS_SET.9 index cc2e037a229..25acc86bd6c 100644 --- a/share/man/man9/VFS_SET.9 +++ b/share/man/man9/VFS_SET.9 @@ -26,7 +26,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 28, 2013 +.Dd February 21, 2013 .Dt VFS_SET 9 .Os .Sh NAME @@ -80,6 +80,9 @@ Supports delegated administration if .Va vfs.usermount sysctl is set to .Dv 1 . +.It Dv VFCF_SBDRY +When in VFS method, the thread suspension is deferred to the user +boundary upon arrival of stop action. .El .Sh PSEUDOCODE .Bd -literal From 0ab13648f57a3c8bb56f256bf2d000da4416be7a Mon Sep 17 00:00:00 2001 From: Peter Grehan Date: Fri, 22 Feb 2013 00:46:32 +0000 Subject: [PATCH 0351/1476] Add the ability to have a 'fallback' search for memory ranges. These set of ranges will be looked at if a standard memory range isn't found, and won't be installed in the cache. Use this to implement the memory behaviour of the PCI hole on x86 systems, where writes are ignored and reads always return -1. This allows breakpoints to be set when issuing a 'boot -d', which has the side effect of accessing the PCI hole when changing the PTE protection on kernel code, since the pmap layer hasn't been initialized (a bug, but present in existing FreeBSD releases so has to be handled). Reviewed by: neel Obtained from: NetApp --- usr.sbin/bhyve/mem.c | 50 ++++++++++++++++++++++++++------------- usr.sbin/bhyve/mem.h | 1 + usr.sbin/bhyve/pci_emul.c | 31 ++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 17 deletions(-) diff --git a/usr.sbin/bhyve/mem.c b/usr.sbin/bhyve/mem.c index 27f47827e80..c2b5ab4f401 100644 --- a/usr.sbin/bhyve/mem.c +++ b/usr.sbin/bhyve/mem.c @@ -62,7 +62,7 @@ struct mmio_rb_range { struct mmio_rb_tree; RB_PROTOTYPE(mmio_rb_tree, mmio_rb_range, mr_link, mmio_rb_range_compare); -RB_HEAD(mmio_rb_tree, mmio_rb_range) mmio_rbroot; +RB_HEAD(mmio_rb_tree, mmio_rb_range) mmio_rb_root, mmio_rb_fallback; /* * Per-vCPU cache. Since most accesses from a vCPU will be to @@ -82,13 +82,14 @@ mmio_rb_range_compare(struct mmio_rb_range *a, struct mmio_rb_range *b) } static int -mmio_rb_lookup(uint64_t addr, struct mmio_rb_range **entry) +mmio_rb_lookup(struct mmio_rb_tree *rbt, uint64_t addr, + struct mmio_rb_range **entry) { struct mmio_rb_range find, *res; find.mr_base = find.mr_end = addr; - res = RB_FIND(mmio_rb_tree, &mmio_rbroot, &find); + res = RB_FIND(mmio_rb_tree, rbt, &find); if (res != NULL) { *entry = res; @@ -99,11 +100,11 @@ mmio_rb_lookup(uint64_t addr, struct mmio_rb_range **entry) } static int -mmio_rb_add(struct mmio_rb_range *new) +mmio_rb_add(struct mmio_rb_tree *rbt, struct mmio_rb_range *new) { struct mmio_rb_range *overlap; - overlap = RB_INSERT(mmio_rb_tree, &mmio_rbroot, new); + overlap = RB_INSERT(mmio_rb_tree, rbt, new); if (overlap != NULL) { #ifdef RB_DEBUG @@ -120,11 +121,11 @@ mmio_rb_add(struct mmio_rb_range *new) #if 0 static void -mmio_rb_dump(void) +mmio_rb_dump(struct mmio_rb_tree *rbt) { struct mmio_rb_range *np; - RB_FOREACH(np, mmio_rb_tree, &mmio_rbroot) { + RB_FOREACH(np, mmio_rb_tree, rbt) { printf(" %lx:%lx, %s\n", np->mr_base, np->mr_end, np->mr_param.name); } @@ -172,22 +173,22 @@ emulate_mem(struct vmctx *ctx, int vcpu, uint64_t paddr, struct vie *vie) entry = NULL; if (entry == NULL) { - if (mmio_rb_lookup(paddr, &entry)) + if (!mmio_rb_lookup(&mmio_rb_root, paddr, &entry)) { + /* Update the per-vCPU cache */ + mmio_hint[vcpu] = entry; + } else if (mmio_rb_lookup(&mmio_rb_fallback, paddr, &entry)) { return (ESRCH); - - /* Update the per-vCPU cache */ - mmio_hint[vcpu] = entry; + } } - assert(entry != NULL && entry == mmio_hint[vcpu]); - + assert(entry != NULL); err = vmm_emulate_instruction(ctx, vcpu, paddr, vie, mem_read, mem_write, &entry->mr_param); return (err); } -int -register_mem(struct mem_range *memp) +static int +register_mem_int(struct mmio_rb_tree *rbt, struct mem_range *memp) { struct mmio_rb_range *mrp; int err; @@ -201,7 +202,7 @@ register_mem(struct mem_range *memp) mrp->mr_base = memp->base; mrp->mr_end = memp->base + memp->size - 1; - err = mmio_rb_add(mrp); + err = mmio_rb_add(rbt, mrp); if (err) free(mrp); } else @@ -210,9 +211,24 @@ register_mem(struct mem_range *memp) return (err); } +int +register_mem(struct mem_range *memp) +{ + + return (register_mem_int(&mmio_rb_root, memp)); +} + +int +register_mem_fallback(struct mem_range *memp) +{ + + return (register_mem_int(&mmio_rb_fallback, memp)); +} + void init_mem(void) { - RB_INIT(&mmio_rbroot); + RB_INIT(&mmio_rb_root); + RB_INIT(&mmio_rb_fallback); } diff --git a/usr.sbin/bhyve/mem.h b/usr.sbin/bhyve/mem.h index 88fafe18005..05e7508f312 100644 --- a/usr.sbin/bhyve/mem.h +++ b/usr.sbin/bhyve/mem.h @@ -53,5 +53,6 @@ void init_mem(void); int emulate_mem(struct vmctx *, int vcpu, uint64_t paddr, struct vie *vie); int register_mem(struct mem_range *memp); +int register_mem_fallback(struct mem_range *memp); #endif /* _MEM_H_ */ diff --git a/usr.sbin/bhyve/pci_emul.c b/usr.sbin/bhyve/pci_emul.c index d883a540fc6..cb09b7c4586 100644 --- a/usr.sbin/bhyve/pci_emul.c +++ b/usr.sbin/bhyve/pci_emul.c @@ -846,12 +846,29 @@ pci_emul_iscap(struct pci_devinst *pi, int offset) return (found); } +static int +pci_emul_fallback_handler(struct vmctx *ctx, int vcpu, int dir, uint64_t addr, + int size, uint64_t *val, void *arg1, long arg2) +{ + /* + * Ignore writes; return 0xff's for reads. The mem read code + * will take care of truncating to the correct size. + */ + if (dir == MEM_F_READ) { + *val = 0xffffffffffffffff; + } + + return (0); +} + void init_pci(struct vmctx *ctx) { + struct mem_range memp; struct pci_devemu *pde; struct slotinfo *si; int slot, func; + int error; pci_emul_iobase = PCI_EMUL_IOBASE; pci_emul_membase32 = PCI_EMUL_MEMBASE32; @@ -879,6 +896,20 @@ init_pci(struct vmctx *ctx) lirq[11].li_generic = 1; lirq[12].li_generic = 1; lirq[15].li_generic = 1; + + /* + * Setup the PCI hole to return 0xff's when accessed in a region + * with no devices + */ + memset(&memp, 0, sizeof(struct mem_range)); + memp.name = "PCI hole"; + memp.flags = MEM_F_RW; + memp.base = lomem_sz; + memp.size = (4ULL * 1024 * 1024 * 1024) - lomem_sz; + memp.handler = pci_emul_fallback_handler; + + error = register_mem_fallback(&memp); + assert(error == 0); } int From ffdc8f48dd00ed4936e0dd46f37c0874c51b8db4 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Fri, 22 Feb 2013 07:07:11 +0000 Subject: [PATCH 0352/1476] Add a workaround for AR5416, AR9130 and AR9160 chipsets - work around an incorrectly calculated RTS duration value when transmitting aggregates. These earlier 802.11n NICs incorrectly used the ACK duration time when calculating what to put in the RTS of an aggregate frame. Instead it should have used the block-ack time. The result is that other stations may not reserve enough time and start transmitting _over_ the top of the in-progress blockack field. Tsk. This workaround is to popuate the burst duration field with the delta between the ACK duration the hardware is using and the required duration for the block-ack. The result is that the RTS field should now contain the correct duration for the subsequent block-ack. This doesn't apply for AR9280 and later NICs. Obtained from: Qualcomm Atheros --- sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c | 71 +++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c b/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c index 36f968fc7d7..945c766c2df 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c @@ -669,6 +669,26 @@ ar5416GetGlobalTxTimeout(struct ath_hal *ah) return MS(OS_REG_READ(ah, AR_GTXTO), AR_GTXTO_TIMEOUT_LIMIT); } +#define HT_RC_2_MCS(_rc) ((_rc) & 0x0f) +static const u_int8_t baDurationDelta[] = { + 24, // 0: BPSK + 12, // 1: QPSK 1/2 + 12, // 2: QPSK 3/4 + 4, // 3: 16-QAM 1/2 + 4, // 4: 16-QAM 3/4 + 4, // 5: 64-QAM 2/3 + 4, // 6: 64-QAM 3/4 + 4, // 7: 64-QAM 5/6 + 24, // 8: BPSK + 12, // 9: QPSK 1/2 + 12, // 10: QPSK 3/4 + 4, // 11: 16-QAM 1/2 + 4, // 12: 16-QAM 3/4 + 4, // 13: 64-QAM 2/3 + 4, // 14: 64-QAM 3/4 + 4, // 15: 64-QAM 5/6 +}; + void ar5416Set11nRateScenario(struct ath_hal *ah, struct ath_desc *ds, u_int durUpdateEn, u_int rtsctsRate, @@ -740,17 +760,44 @@ ar5416Set11nRateScenario(struct ath_hal *ah, struct ath_desc *ds, | SM(rtsctsRate, AR_RTSCTSRate); } +/* + * Note: this should be called before calling ar5416SetBurstDuration() + * (if it is indeed called) in order to ensure that the burst duration + * is correctly updated with the BA delta workaround. + */ void ar5416Set11nAggrFirst(struct ath_hal *ah, struct ath_desc *ds, u_int aggrLen, u_int numDelims) { struct ar5416_desc *ads = AR5416DESC(ds); + uint32_t flags; + uint32_t burstDur; + uint8_t rate; ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr); ads->ds_ctl6 &= ~(AR_AggrLen | AR_PadDelim); ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen); ads->ds_ctl6 |= SM(numDelims, AR_PadDelim); + + if (! AR_SREV_MERLIN_10_OR_LATER(ah)) { + /* + * XXX It'd be nice if I were passed in the rate scenario + * at this point.. + */ + rate = MS(ads->ds_ctl3, AR_XmitRate0); + flags = ads->ds_ctl0 & (AR_CTSEnable | AR_RTSEnable); + /* + * WAR - MAC assumes normal ACK time instead of + * block ACK while computing packet duration. + * Add this delta to the burst duration in the descriptor. + */ + if (flags && (ads->ds_ctl1 & AR_IsAggr)) { + burstDur = baDurationDelta[HT_RC_2_MCS(rate)]; + ads->ds_ctl2 &= ~(AR_BurstDur); + ads->ds_ctl2 |= SM(burstDur, AR_BurstDur); + } + } } void @@ -792,14 +839,36 @@ ar5416Clr11nAggr(struct ath_hal *ah, struct ath_desc *ds) ads->ds_ctl6 &= ~AR_AggrLen; } +/* + * Program the burst duration, with the included BA delta if it's + * applicable. + */ void ar5416Set11nBurstDuration(struct ath_hal *ah, struct ath_desc *ds, u_int burstDuration) { struct ar5416_desc *ads = AR5416DESC(ds); + uint32_t burstDur = 0; + uint8_t rate; + + if (! AR_SREV_MERLIN_10_OR_LATER(ah)) { + /* + * XXX It'd be nice if I were passed in the rate scenario + * at this point.. + */ + rate = MS(ads->ds_ctl3, AR_XmitDataTries0); + /* + * WAR - MAC assumes normal ACK time instead of + * block ACK while computing packet duration. + * Add this delta to the burst duration in the descriptor. + */ + if (ads->ds_ctl1 & AR_IsAggr) { + burstDur = baDurationDelta[HT_RC_2_MCS(rate)]; + } + } ads->ds_ctl2 &= ~AR_BurstDur; - ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur); + ads->ds_ctl2 |= SM(burstDur + burstDuration, AR_BurstDur); } /* From 60f27516705885214a40c70b268c94f6159784e9 Mon Sep 17 00:00:00 2001 From: Gleb Smirnoff Date: Fri, 22 Feb 2013 12:41:24 +0000 Subject: [PATCH 0353/1476] Fix build. --- sys/dev/mxge/if_mxge.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sys/dev/mxge/if_mxge.c b/sys/dev/mxge/if_mxge.c index fcc08255e90..afa27ffe8bc 100644 --- a/sys/dev/mxge/if_mxge.c +++ b/sys/dev/mxge/if_mxge.c @@ -2560,7 +2560,6 @@ mxge_rx_csum(struct mbuf *m, int csum) #ifdef INET struct ip *ip; #endif - int cap = m->m_pkthdr.rcvif->if_capenable; uint16_t c, etype; From abc5b96b991d3326b1f97c02115109ef495149e3 Mon Sep 17 00:00:00 2001 From: Andrew Gallatin Date: Fri, 22 Feb 2013 16:46:28 +0000 Subject: [PATCH 0354/1476] Try harder to make mxge safe for all combinations of INET and INET6 - Re-fix build by restoring local removed in r247151, but protected by #if defined(INET) || defined(INET6) so that the compile succeeds in the !(INET||INET6) case. - Protect call to in_pseudo() with an #ifdef INET, to allow a kernel to link with mxge when INET is not compiled in. - Also remove an errant (improperly commented) obsolete debugging printf Thanks to Glebius for pointing out the !(INET||INET6) build issue. Sponsored by: Myricom MFC After: 7 days --- sys/dev/mxge/if_mxge.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sys/dev/mxge/if_mxge.c b/sys/dev/mxge/if_mxge.c index afa27ffe8bc..ee2ca2fb3ad 100644 --- a/sys/dev/mxge/if_mxge.c +++ b/sys/dev/mxge/if_mxge.c @@ -1887,11 +1887,13 @@ mxge_encap_tso(struct mxge_slice_state *ss, struct mbuf *m, IPPROTO_TCP, 0); #endif } else { +#ifdef INET m->m_pkthdr.csum_flags |= CSUM_TCP; sum = in_pseudo(pi->ip->ip_src.s_addr, pi->ip->ip_dst.s_addr, htons(IPPROTO_TCP + (m->m_pkthdr.len - cksum_offset))); +#endif } m_copyback(m, offsetof(struct tcphdr, th_sum) + cksum_offset, sizeof(sum), (caddr_t)&sum); @@ -2538,8 +2540,6 @@ mxge_rx_csum6(void *p, struct mbuf *m, uint32_t csum) csum = (csum >> 16) + (csum & 0xFFFF); c = in6_cksum_pseudo(ip6, m->m_pkthdr.len - cksum_offset, nxt, csum); - -// printf("%d %d %x %x %x %x %x\n", m->m_pkthdr.len, cksum_offset, c, csum, ocsum, partial, d); c ^= 0xffff; return (c); } @@ -2559,6 +2559,9 @@ mxge_rx_csum(struct mbuf *m, int csum) struct ether_header *eh; #ifdef INET struct ip *ip; +#endif +#if defined(INET) || defined(INET6) + int cap = m->m_pkthdr.rcvif->if_capenable; #endif uint16_t c, etype; From 07ad25d4884af33f5b06ed42c6d1aaf3d070a324 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 22 Feb 2013 16:59:52 +0000 Subject: [PATCH 0355/1476] Eliminate an unused #define. --- sys/powerpc/include/vmparam.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sys/powerpc/include/vmparam.h b/sys/powerpc/include/vmparam.h index 8368a4179dc..4b36d9d5949 100644 --- a/sys/powerpc/include/vmparam.h +++ b/sys/powerpc/include/vmparam.h @@ -121,11 +121,6 @@ #endif /* AIM/E500 */ -/* XXX max. amount of KVM to be used by buffers. */ -#ifndef VM_MAX_KERNEL_BUF -#define VM_MAX_KERNEL_BUF (SEGMENT_LENGTH * 7 / 10) -#endif - #if !defined(LOCORE) struct pmap_physseg { struct pv_entry *pvent; From 3cd4155386e48d783af0cde911ae9416c5f47f8f Mon Sep 17 00:00:00 2001 From: Alexander Motin Date: Fri, 22 Feb 2013 17:45:32 +0000 Subject: [PATCH 0356/1476] Add DA_Q_NO_PREVENT quirk for Kingston DataTraveler G3 1.00 USB flash. PREVENT ALLOW MEDIUM REMOVAL commands return errors on these devices without returning sense data. In some cases unrelated following commands start to return errors too, that makes device to be dropped by CAM. --- sys/cam/scsi/scsi_da.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c index 7854215354e..00779977e5b 100644 --- a/sys/cam/scsi/scsi_da.c +++ b/sys/cam/scsi/scsi_da.c @@ -607,6 +607,10 @@ static struct da_quirk_entry da_quirk_table[] = {T_DIRECT, SIP_MEDIA_REMOVABLE, "Sony", "Sony DSC", "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE | DA_Q_NO_PREVENT }, + { + {T_DIRECT, SIP_MEDIA_REMOVABLE, "Kingston", "DataTraveler G3", + "1.00"}, /*quirks*/ DA_Q_NO_PREVENT + }, /* ATA/SATA devices over SAS/USB/... */ { /* Hitachi Advanced Format (4k) drives */ From a4b233dd068cda269db3fa9f8fe8479234a91730 Mon Sep 17 00:00:00 2001 From: Andrew Gallatin Date: Fri, 22 Feb 2013 19:21:29 +0000 Subject: [PATCH 0357/1476] Improvements for newer mxge nics: - Some mxge nics may store the serial number in the SN2 field of the EEPROM. These will also have an SN=0 field, so parse the SN2 field, and give it precedence. - Skip MXGEFW_CMD_UNALIGNED_TEST on mxge nics which do not require it. This saves roughly 10ms per port at device attach time. Sponsored by: Myricom MFC After: 7 days --- sys/dev/mxge/if_mxge.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/sys/dev/mxge/if_mxge.c b/sys/dev/mxge/if_mxge.c index ee2ca2fb3ad..e8a794335c8 100644 --- a/sys/dev/mxge/if_mxge.c +++ b/sys/dev/mxge/if_mxge.c @@ -291,11 +291,12 @@ mxge_parse_strings(mxge_softc_t *sc) #define MXGE_NEXT_STRING(p) while(ptr < limit && *ptr++) char *ptr, *limit; - int i, found_mac; + int i, found_mac, found_sn2; ptr = sc->eeprom_strings; limit = sc->eeprom_strings + MXGE_EEPROM_STRINGS_SIZE; found_mac = 0; + found_sn2 = 0; while (ptr < limit && *ptr != '\0') { if (memcmp(ptr, "MAC=", 4) == 0) { ptr += 1; @@ -311,10 +312,16 @@ mxge_parse_strings(mxge_softc_t *sc) ptr += 3; strncpy(sc->product_code_string, ptr, sizeof (sc->product_code_string) - 1); - } else if (memcmp(ptr, "SN=", 3) == 0) { + } else if (!found_sn2 && (memcmp(ptr, "SN=", 3) == 0)) { ptr += 3; strncpy(sc->serial_number_string, ptr, sizeof (sc->serial_number_string) - 1); + } else if (memcmp(ptr, "SN2=", 4) == 0) { + /* SN2 takes precedence over SN */ + ptr += 4; + found_sn2 = 1; + strncpy(sc->serial_number_string, ptr, + sizeof (sc->serial_number_string) - 1); } MXGE_NEXT_STRING(ptr); } @@ -581,9 +588,10 @@ mxge_firmware_probe(mxge_softc_t *sc) /* * Run a DMA test which watches for unaligned completions and - * aborts on the first one seen. + * aborts on the first one seen. Not required on Z8ES or newer. */ - + if (pci_get_revid(sc->dev) >= MXGE_PCI_REV_Z8ES) + return 0; status = mxge_dma_test(sc, MXGEFW_CMD_UNALIGNED_TEST); if (status == 0) return 0; /* keep the aligned firmware */ From cabc512fe4b1c162457bedc4937f1abe1d779f3d Mon Sep 17 00:00:00 2001 From: Andrew Gallatin Date: Fri, 22 Feb 2013 19:23:33 +0000 Subject: [PATCH 0358/1476] Bump mxge copyright. Sponsored by: Myricom MFC After: 7 days --- sys/dev/mxge/if_mxge.c | 2 +- sys/dev/mxge/if_mxge_var.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/dev/mxge/if_mxge.c b/sys/dev/mxge/if_mxge.c index e8a794335c8..245c1391345 100644 --- a/sys/dev/mxge/if_mxge.c +++ b/sys/dev/mxge/if_mxge.c @@ -1,6 +1,6 @@ /****************************************************************************** -Copyright (c) 2006-2009, Myricom Inc. +Copyright (c) 2006-2013, Myricom Inc. All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/sys/dev/mxge/if_mxge_var.h b/sys/dev/mxge/if_mxge_var.h index 7ca1f3977aa..a182a205af8 100644 --- a/sys/dev/mxge/if_mxge_var.h +++ b/sys/dev/mxge/if_mxge_var.h @@ -1,6 +1,6 @@ /******************************************************************************* -Copyright (c) 2006-2009, Myricom Inc. +Copyright (c) 2006-2013, Myricom Inc. All rights reserved. Redistribution and use in source and binary forms, with or without From 6efe203d7cf8df65a97ea0ac6cb9335b3a63443c Mon Sep 17 00:00:00 2001 From: Alexander Motin Date: Fri, 22 Feb 2013 19:53:12 +0000 Subject: [PATCH 0359/1476] Hide SEMB port of the SiI3826 Port Multiplier by default to avoid extra errors while it tries to talk via I2C to usually missing external SEP. There is tunable to enable it back when needed. --- sys/cam/ata/ata_pmp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sys/cam/ata/ata_pmp.c b/sys/cam/ata/ata_pmp.c index b2acdee6292..3c8bb51d95a 100644 --- a/sys/cam/ata/ata_pmp.c +++ b/sys/cam/ata/ata_pmp.c @@ -595,7 +595,9 @@ pmpdone(struct cam_periph *periph, union ccb *done_ccb) * causes timeouts if external SEP is not connected * to PMP over I2C. */ - if (softc->pm_pid == 0x37261095 && softc->pm_ports == 6) + if ((softc->pm_pid == 0x37261095 || + softc->pm_pid == 0x38261095) && + softc->pm_ports == 6) softc->pm_ports = 5; /* From 69b23515b5406136d049a4afa223a42b32ff755d Mon Sep 17 00:00:00 2001 From: "Andrey A. Chernov" Date: Fri, 22 Feb 2013 19:57:18 +0000 Subject: [PATCH 0360/1476] Back out prev. change preventing /sys/sys symlink. It appears my install was not very recent and not acts like 'ln -h' --- etc/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/Makefile b/etc/Makefile index 7c4cea51cff..81ef45a09f1 100644 --- a/etc/Makefile +++ b/etc/Makefile @@ -354,7 +354,7 @@ distrib-dirs: ${METALOG.add} ; \ done; true .endif - ${INSTALL_SYMLINK} usr/src/sys ${DESTDIR}/ + ${INSTALL_SYMLINK} usr/src/sys ${DESTDIR}/sys cd ${DESTDIR}/usr/share/man; \ for mandir in man*; do \ ${INSTALL_SYMLINK} ../$$mandir \ From 081b42f93c0e3bccf4cb446dc65b898a14f300b9 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Fri, 22 Feb 2013 20:49:50 +0000 Subject: [PATCH 0361/1476] Don't print an empty line for files with no attributes when -q is given for lsextattr(8). --- usr.sbin/extattr/rmextattr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/usr.sbin/extattr/rmextattr.c b/usr.sbin/extattr/rmextattr.c index db7df1a321c..cab6c7f3755 100644 --- a/usr.sbin/extattr/rmextattr.c +++ b/usr.sbin/extattr/rmextattr.c @@ -237,7 +237,8 @@ main(int argc, char *argv[]) printf("%s%*.*s", i ? "\t" : "", ch, ch, buf + i + 1); } - printf("\n"); + if (!flag_quiet || error > 0) + printf("\n"); continue; case EAGET: if (flag_nofollow) From 512a3aa0058fbd81e59e26e3de5450ff79f00d58 Mon Sep 17 00:00:00 2001 From: Alexander Motin Date: Fri, 22 Feb 2013 21:43:21 +0000 Subject: [PATCH 0362/1476] Fix command timeout caused by data underrun during fetching ATAPI sense data, introduced by r246713. There are two places where ata_request is filled in ATA_CAM: ata_cam_begin_transaction() and ata_cam_request_sense(). In the first case DMA should be done for addresses from the CCB. In second case, DMA should be done to the different address, the address of the sense buffer inside the CCB structure itself. --- sys/dev/ata/ata-all.c | 1 + sys/dev/ata/ata-all.h | 1 + sys/dev/ata/ata-dma.c | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c index 440db714342..bfd49c78e6c 100644 --- a/sys/dev/ata/ata-all.c +++ b/sys/dev/ata/ata-all.c @@ -1532,6 +1532,7 @@ ata_cam_begin_transaction(device_t dev, union ccb *ccb) request->timeout = (ccb->ccb_h.timeout + 999) / 1000; callout_init_mtx(&request->callout, &ch->state_mtx, CALLOUT_RETURNUNLOCKED); request->ccb = ccb; + request->flags |= ATA_R_DATA_IN_CCB; ch->running = request; ch->state = ATA_ACTIVE; diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h index 28c93f9240c..be166df97c0 100644 --- a/sys/dev/ata/ata-all.h +++ b/sys/dev/ata/ata-all.h @@ -398,6 +398,7 @@ struct ata_request { #define ATA_R_THREAD 0x00000800 #define ATA_R_DIRECT 0x00001000 #define ATA_R_NEEDRESULT 0x00002000 +#define ATA_R_DATA_IN_CCB 0x00004000 #define ATA_R_ATAPI16 0x00010000 #define ATA_R_ATAPI_INTR 0x00020000 diff --git a/sys/dev/ata/ata-dma.c b/sys/dev/ata/ata-dma.c index 9aea8458d68..5695bc8de3f 100644 --- a/sys/dev/ata/ata-dma.c +++ b/sys/dev/ata/ata-dma.c @@ -305,7 +305,7 @@ ata_dmaload(struct ata_request *request, void *addr, int *entries) dspa.dmatab = request->dma->sg; #ifdef ATA_CAM - if (request->ccb) + if (request->flags & ATA_R_DATA_IN_CCB) error = bus_dmamap_load_ccb(request->dma->data_tag, request->dma->data_map, request->ccb, ch->dma.setprd, &dspa, BUS_DMA_NOWAIT); From 2d97b320fb53e10732f1d38c45c24625cdb9276a Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Fri, 22 Feb 2013 22:40:10 +0000 Subject: [PATCH 0363/1476] Pull in r172354 from upstream clang trunk: Refactor the x86 CPU name logic in the driver and pass -march and -mcpu flag information down from the Clang driver into the Gold linker plugin for LTO. This allows specifying -march on the linker commandline and should hopefully have it pass all the way through to the LTO optimizer. Fixes PR14697. Pull in r175919 from upstream clang trunk: Driver: Pass down the -march setting down to -cc1as on x86 too. The assembler historically didn't make use of any target features, but this has changed when support for old CPUs that don't support long nops was added. This should fix the long nops that still occurred in crt*.o, and possibly other object files, if the system was compiled for a CPU that does not support those, such as Geode. Note that gcc on i386 also does not pass through any -march, -mcpu or -mtune setting to gas, but this has not caused any trouble yet, because gas defaults to i386. Reported by: lev MFC after: 1 week --- contrib/llvm/tools/clang/lib/Driver/Tools.cpp | 146 ++++++++++-------- contrib/llvm/tools/clang/lib/Driver/Tools.h | 1 + 2 files changed, 86 insertions(+), 61 deletions(-) diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp index 1dff3185348..4976b45b632 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp @@ -1114,10 +1114,59 @@ void Clang::AddSparcTargetArgs(const ArgList &Args, } } +static const char *getX86TargetCPU(const ArgList &Args, + const llvm::Triple &Triple) { + if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { + if (StringRef(A->getValue()) != "native") + return A->getValue(); + + // FIXME: Reject attempts to use -march=native unless the target matches + // the host. + // + // FIXME: We should also incorporate the detected target features for use + // with -native. + std::string CPU = llvm::sys::getHostCPUName(); + if (!CPU.empty() && CPU != "generic") + return Args.MakeArgString(CPU); + } + + // Select the default CPU if none was given (or detection failed). + + if (Triple.getArch() != llvm::Triple::x86_64 && + Triple.getArch() != llvm::Triple::x86) + return 0; // This routine is only handling x86 targets. + + bool Is64Bit = Triple.getArch() == llvm::Triple::x86_64; + + // FIXME: Need target hooks. + if (Triple.isOSDarwin()) + return Is64Bit ? "core2" : "yonah"; + + // Everything else goes to x86-64 in 64-bit mode. + if (Is64Bit) + return "x86-64"; + + if (Triple.getOSName().startswith("haiku")) + return "i586"; + if (Triple.getOSName().startswith("openbsd")) + return "i486"; + if (Triple.getOSName().startswith("bitrig")) + return "i686"; + if (Triple.getOSName().startswith("freebsd")) + return "i486"; + if (Triple.getOSName().startswith("netbsd")) + return "i486"; + // All x86 devices running Android have core2 as their common + // denominator. This makes a better choice than pentium4. + if (Triple.getEnvironment() == llvm::Triple::Android) + return "core2"; + + // Fallback to p4. + return "pentium4"; +} + void Clang::AddX86TargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const { - const bool isAndroid = - getToolChain().getTriple().getEnvironment() == llvm::Triple::Android; if (!Args.hasFlag(options::OPT_mred_zone, options::OPT_mno_red_zone, true) || @@ -1130,65 +1179,7 @@ void Clang::AddX86TargetArgs(const ArgList &Args, false)) CmdArgs.push_back("-no-implicit-float"); - const char *CPUName = 0; - if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { - if (StringRef(A->getValue()) == "native") { - // FIXME: Reject attempts to use -march=native unless the target matches - // the host. - // - // FIXME: We should also incorporate the detected target features for use - // with -native. - std::string CPU = llvm::sys::getHostCPUName(); - if (!CPU.empty() && CPU != "generic") - CPUName = Args.MakeArgString(CPU); - } else - CPUName = A->getValue(); - } - - // Select the default CPU if none was given (or detection failed). - if (!CPUName) { - // FIXME: Need target hooks. - if (getToolChain().getTriple().isOSDarwin()) { - if (getToolChain().getArch() == llvm::Triple::x86_64) - CPUName = "core2"; - else if (getToolChain().getArch() == llvm::Triple::x86) - CPUName = "yonah"; - } else if (getToolChain().getOS().startswith("haiku")) { - if (getToolChain().getArch() == llvm::Triple::x86_64) - CPUName = "x86-64"; - else if (getToolChain().getArch() == llvm::Triple::x86) - CPUName = "i586"; - } else if (getToolChain().getOS().startswith("openbsd")) { - if (getToolChain().getArch() == llvm::Triple::x86_64) - CPUName = "x86-64"; - else if (getToolChain().getArch() == llvm::Triple::x86) - CPUName = "i486"; - } else if (getToolChain().getOS().startswith("bitrig")) { - if (getToolChain().getArch() == llvm::Triple::x86_64) - CPUName = "x86-64"; - else if (getToolChain().getArch() == llvm::Triple::x86) - CPUName = "i686"; - } else if (getToolChain().getOS().startswith("freebsd")) { - if (getToolChain().getArch() == llvm::Triple::x86_64) - CPUName = "x86-64"; - else if (getToolChain().getArch() == llvm::Triple::x86) - CPUName = "i486"; - } else if (getToolChain().getOS().startswith("netbsd")) { - if (getToolChain().getArch() == llvm::Triple::x86_64) - CPUName = "x86-64"; - else if (getToolChain().getArch() == llvm::Triple::x86) - CPUName = "i486"; - } else { - if (getToolChain().getArch() == llvm::Triple::x86_64) - CPUName = "x86-64"; - else if (getToolChain().getArch() == llvm::Triple::x86) - // All x86 devices running Android have core2 as their common - // denominator. This makes a better choice than pentium4. - CPUName = isAndroid ? "core2" : "pentium4"; - } - } - - if (CPUName) { + if (const char *CPUName = getX86TargetCPU(Args, getToolChain().getTriple())) { CmdArgs.push_back("-target-cpu"); CmdArgs.push_back(CPUName); } @@ -3091,6 +3082,15 @@ void ClangAs::AddARMTargetArgs(const ArgList &Args, addFPMathArgs(D, A, Args, CmdArgs, getARMTargetCPU(Args, Triple)); } +void ClangAs::AddX86TargetArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + // Set the CPU based on -march=. + if (const char *CPUName = getX86TargetCPU(Args, getToolChain().getTriple())) { + CmdArgs.push_back("-target-cpu"); + CmdArgs.push_back(CPUName); + } +} + /// Add options related to the Objective-C runtime/ABI. /// /// Returns true if the runtime is non-fragile. @@ -3261,6 +3261,11 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, case llvm::Triple::thumb: AddARMTargetArgs(Args, CmdArgs); break; + + case llvm::Triple::x86: + case llvm::Triple::x86_64: + AddX86TargetArgs(Args, CmdArgs); + break; } // Ignore explicit -force_cpusubtype_ALL option. @@ -6068,8 +6073,27 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-plugin"); std::string Plugin = ToolChain.getDriver().Dir + "/../lib/LLVMgold.so"; CmdArgs.push_back(Args.MakeArgString(Plugin)); + + // Try to pass driver level flags relevant to LTO code generation down to + // the plugin. + + // Handle architecture-specific flags for selecting CPU variants. + if (ToolChain.getArch() == llvm::Triple::x86 || + ToolChain.getArch() == llvm::Triple::x86_64) + CmdArgs.push_back( + Args.MakeArgString(Twine("-plugin-opt=mcpu=") + + getX86TargetCPU(Args, ToolChain.getTriple()))); + else if (ToolChain.getArch() == llvm::Triple::arm || + ToolChain.getArch() == llvm::Triple::thumb) + CmdArgs.push_back( + Args.MakeArgString(Twine("-plugin-opt=mcpu=") + + getARMTargetCPU(Args, ToolChain.getTriple()))); + + // FIXME: Factor out logic for MIPS, PPC, and other targets to support this + // as well. } + if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) CmdArgs.push_back("--no-demangle"); diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.h b/contrib/llvm/tools/clang/lib/Driver/Tools.h index 5898c660a49..7ac43ec9b69 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Tools.h +++ b/contrib/llvm/tools/clang/lib/Driver/Tools.h @@ -68,6 +68,7 @@ namespace tools { /// \brief Clang integrated assembler tool. class LLVM_LIBRARY_VISIBILITY ClangAs : public Tool { void AddARMTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const; + void AddX86TargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const; public: ClangAs(const ToolChain &TC) : Tool("clang::as", "clang integrated assembler", TC) {} From b41b004f8768d731aa63e9fe454e873f26421fa5 Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Sat, 23 Feb 2013 08:57:47 +0000 Subject: [PATCH 0364/1476] Update vendor-sys/illumos/dist to illumos-gate 13958:1fd91513472c Illumos ZFS issues: 3561 arc_meta_limit should be exposed via kstats 3116 zpool reguid may log negative guids to internal SPA history --- uts/common/fs/zfs/arc.c | 18 ++++++++++++------ uts/common/fs/zfs/spa.c | 2 +- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/uts/common/fs/zfs/arc.c b/uts/common/fs/zfs/arc.c index 258a89ff3ff..ca3baeaeebb 100644 --- a/uts/common/fs/zfs/arc.c +++ b/uts/common/fs/zfs/arc.c @@ -294,6 +294,9 @@ typedef struct arc_stats { kstat_named_t arcstat_duplicate_buffers; kstat_named_t arcstat_duplicate_buffers_size; kstat_named_t arcstat_duplicate_reads; + kstat_named_t arcstat_meta_used; + kstat_named_t arcstat_meta_limit; + kstat_named_t arcstat_meta_max; } arc_stats_t; static arc_stats_t arc_stats = { @@ -352,7 +355,10 @@ static arc_stats_t arc_stats = { { "memory_throttle_count", KSTAT_DATA_UINT64 }, { "duplicate_buffers", KSTAT_DATA_UINT64 }, { "duplicate_buffers_size", KSTAT_DATA_UINT64 }, - { "duplicate_reads", KSTAT_DATA_UINT64 } + { "duplicate_reads", KSTAT_DATA_UINT64 }, + { "arc_meta_used", KSTAT_DATA_UINT64 }, + { "arc_meta_limit", KSTAT_DATA_UINT64 }, + { "arc_meta_max", KSTAT_DATA_UINT64 } }; #define ARCSTAT(stat) (arc_stats.stat.value.ui64) @@ -414,13 +420,13 @@ static arc_state_t *arc_l2c_only; #define arc_c ARCSTAT(arcstat_c) /* target size of cache */ #define arc_c_min ARCSTAT(arcstat_c_min) /* min target cache size */ #define arc_c_max ARCSTAT(arcstat_c_max) /* max target cache size */ +#define arc_meta_limit ARCSTAT(arcstat_meta_limit) /* max size for metadata */ +#define arc_meta_used ARCSTAT(arcstat_meta_used) /* size of metadata */ +#define arc_meta_max ARCSTAT(arcstat_meta_max) /* max size of metadata */ static int arc_no_grow; /* Don't try to grow cache size */ static uint64_t arc_tempreserve; static uint64_t arc_loaned_bytes; -static uint64_t arc_meta_used; -static uint64_t arc_meta_limit; -static uint64_t arc_meta_max = 0; typedef struct l2arc_buf_hdr l2arc_buf_hdr_t; @@ -1218,7 +1224,7 @@ arc_space_consume(uint64_t space, arc_space_type_t type) break; } - atomic_add_64(&arc_meta_used, space); + ARCSTAT_INCR(arcstat_meta_used, space); atomic_add_64(&arc_size, space); } @@ -1245,7 +1251,7 @@ arc_space_return(uint64_t space, arc_space_type_t type) ASSERT(arc_meta_used >= space); if (arc_meta_max < arc_meta_used) arc_meta_max = arc_meta_used; - atomic_add_64(&arc_meta_used, -space); + ARCSTAT_INCR(arcstat_meta_used, -space); ASSERT(arc_size >= space); atomic_add_64(&arc_size, -space); } diff --git a/uts/common/fs/zfs/spa.c b/uts/common/fs/zfs/spa.c index 09a322bad6b..fb68e91eed1 100644 --- a/uts/common/fs/zfs/spa.c +++ b/uts/common/fs/zfs/spa.c @@ -715,7 +715,7 @@ spa_change_guid_sync(void *arg1, void *arg2, dmu_tx_t *tx) vdev_config_dirty(rvd); spa_config_exit(spa, SCL_STATE, FTAG); - spa_history_log_internal(spa, "guid change", tx, "old=%lld new=%lld", + spa_history_log_internal(spa, "guid change", tx, "old=%llu new=%llu", oldguid, *newguid); } From de1744ec7cbd92d6f4cd12058a9682fb01717851 Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Sat, 23 Feb 2013 09:00:35 +0000 Subject: [PATCH 0365/1476] Update vendor/illumos/dist and vendor-sys/illumos/dist to illumos-gate 13959:e03e14ddfb4c Illumos ZFS issues: 3552 condensing one space map burns 3 seconds of CPU in spa_sync() thread 3564 spa_sync() spends 5-10% of its time in metaslab_sync() (when not condensing) --- cmd/zdb/zdb.c | 12 +- uts/common/fs/zfs/metaslab.c | 352 +++++++++++++++++++------- uts/common/fs/zfs/space_map.c | 33 ++- uts/common/fs/zfs/sys/metaslab_impl.h | 32 ++- uts/common/fs/zfs/sys/space_map.h | 7 +- uts/common/fs/zfs/vdev.c | 1 + 6 files changed, 326 insertions(+), 111 deletions(-) diff --git a/cmd/zdb/zdb.c b/cmd/zdb/zdb.c index 9075c47ad1a..2234a71528b 100644 --- a/cmd/zdb/zdb.c +++ b/cmd/zdb/zdb.c @@ -571,7 +571,7 @@ static void dump_metaslab_stats(metaslab_t *msp) { char maxbuf[32]; - space_map_t *sm = &msp->ms_map; + space_map_t *sm = msp->ms_map; avl_tree_t *t = sm->sm_pp_root; int free_pct = sm->sm_space * 100 / sm->sm_size; @@ -587,7 +587,7 @@ dump_metaslab(metaslab_t *msp) { vdev_t *vd = msp->ms_group->mg_vd; spa_t *spa = vd->vdev_spa; - space_map_t *sm = &msp->ms_map; + space_map_t *sm = msp->ms_map; space_map_obj_t *smo = &msp->ms_smo; char freebuf[32]; @@ -2216,11 +2216,11 @@ zdb_leak_init(spa_t *spa, zdb_cb_t *zcb) for (int m = 0; m < vd->vdev_ms_count; m++) { metaslab_t *msp = vd->vdev_ms[m]; mutex_enter(&msp->ms_lock); - space_map_unload(&msp->ms_map); - VERIFY(space_map_load(&msp->ms_map, + space_map_unload(msp->ms_map); + VERIFY(space_map_load(msp->ms_map, &zdb_space_map_ops, SM_ALLOC, &msp->ms_smo, spa->spa_meta_objset) == 0); - msp->ms_map.sm_ppd = vd; + msp->ms_map->sm_ppd = vd; mutex_exit(&msp->ms_lock); } } @@ -2243,7 +2243,7 @@ zdb_leak_fini(spa_t *spa) for (int m = 0; m < vd->vdev_ms_count; m++) { metaslab_t *msp = vd->vdev_ms[m]; mutex_enter(&msp->ms_lock); - space_map_unload(&msp->ms_map); + space_map_unload(msp->ms_map); mutex_exit(&msp->ms_lock); } } diff --git a/uts/common/fs/zfs/metaslab.c b/uts/common/fs/zfs/metaslab.c index ceb7c6fa573..9c4f97a3131 100644 --- a/uts/common/fs/zfs/metaslab.c +++ b/uts/common/fs/zfs/metaslab.c @@ -47,6 +47,14 @@ uint64_t metaslab_aliquot = 512ULL << 10; uint64_t metaslab_gang_bang = SPA_MAXBLOCKSIZE + 1; /* force gang blocks */ +/* + * The in-core space map representation is more compact than its on-disk form. + * The zfs_condense_pct determines how much more compact the in-core + * space_map representation must be before we compact it on-disk. + * Values should be greater than or equal to 100. + */ +int zfs_condense_pct = 200; + /* * This value defines the number of allowed allocation failures per vdev. * If a device reaches this threshold in a given txg then we consider skipping @@ -206,9 +214,9 @@ metaslab_compare(const void *x1, const void *x2) /* * If the weights are identical, use the offset to force uniqueness. */ - if (m1->ms_map.sm_start < m2->ms_map.sm_start) + if (m1->ms_map->sm_start < m2->ms_map->sm_start) return (-1); - if (m1->ms_map.sm_start > m2->ms_map.sm_start) + if (m1->ms_map->sm_start > m2->ms_map->sm_start) return (1); ASSERT3P(m1, ==, m2); @@ -723,14 +731,15 @@ metaslab_init(metaslab_group_t *mg, space_map_obj_t *smo, * addition of new space; and for debugging, it ensures that we'd * data fault on any attempt to use this metaslab before it's ready. */ - space_map_create(&msp->ms_map, start, size, + msp->ms_map = kmem_zalloc(sizeof (space_map_t), KM_SLEEP); + space_map_create(msp->ms_map, start, size, vd->vdev_ashift, &msp->ms_lock); metaslab_group_add(mg, msp); if (metaslab_debug && smo->smo_object != 0) { mutex_enter(&msp->ms_lock); - VERIFY(space_map_load(&msp->ms_map, mg->mg_class->mc_ops, + VERIFY(space_map_load(msp->ms_map, mg->mg_class->mc_ops, SM_FREE, smo, spa_meta_objset(vd->vdev_spa)) == 0); mutex_exit(&msp->ms_lock); } @@ -758,22 +767,27 @@ metaslab_fini(metaslab_t *msp) metaslab_group_t *mg = msp->ms_group; vdev_space_update(mg->mg_vd, - -msp->ms_smo.smo_alloc, 0, -msp->ms_map.sm_size); + -msp->ms_smo.smo_alloc, 0, -msp->ms_map->sm_size); metaslab_group_remove(mg, msp); mutex_enter(&msp->ms_lock); - space_map_unload(&msp->ms_map); - space_map_destroy(&msp->ms_map); + space_map_unload(msp->ms_map); + space_map_destroy(msp->ms_map); + kmem_free(msp->ms_map, sizeof (*msp->ms_map)); for (int t = 0; t < TXG_SIZE; t++) { - space_map_destroy(&msp->ms_allocmap[t]); - space_map_destroy(&msp->ms_freemap[t]); + space_map_destroy(msp->ms_allocmap[t]); + space_map_destroy(msp->ms_freemap[t]); + kmem_free(msp->ms_allocmap[t], sizeof (*msp->ms_allocmap[t])); + kmem_free(msp->ms_freemap[t], sizeof (*msp->ms_freemap[t])); } - for (int t = 0; t < TXG_DEFER_SIZE; t++) - space_map_destroy(&msp->ms_defermap[t]); + for (int t = 0; t < TXG_DEFER_SIZE; t++) { + space_map_destroy(msp->ms_defermap[t]); + kmem_free(msp->ms_defermap[t], sizeof (*msp->ms_defermap[t])); + } ASSERT0(msp->ms_deferspace); @@ -792,7 +806,7 @@ static uint64_t metaslab_weight(metaslab_t *msp) { metaslab_group_t *mg = msp->ms_group; - space_map_t *sm = &msp->ms_map; + space_map_t *sm = msp->ms_map; space_map_obj_t *smo = &msp->ms_smo; vdev_t *vd = mg->mg_vd; uint64_t weight, space; @@ -852,7 +866,7 @@ metaslab_prefetch(metaslab_group_t *mg) * Prefetch the next potential metaslabs */ for (msp = avl_first(t), m = 0; msp; msp = AVL_NEXT(t, msp), m++) { - space_map_t *sm = &msp->ms_map; + space_map_t *sm = msp->ms_map; space_map_obj_t *smo = &msp->ms_smo; /* If we have reached our prefetch limit then we're done */ @@ -873,7 +887,7 @@ static int metaslab_activate(metaslab_t *msp, uint64_t activation_weight) { metaslab_group_t *mg = msp->ms_group; - space_map_t *sm = &msp->ms_map; + space_map_t *sm = msp->ms_map; space_map_ops_t *sm_ops = msp->ms_group->mg_class->mc_ops; ASSERT(MUTEX_HELD(&msp->ms_lock)); @@ -890,7 +904,7 @@ metaslab_activate(metaslab_t *msp, uint64_t activation_weight) return (error); } for (int t = 0; t < TXG_DEFER_SIZE; t++) - space_map_walk(&msp->ms_defermap[t], + space_map_walk(msp->ms_defermap[t], space_map_claim, sm); } @@ -921,11 +935,157 @@ metaslab_passivate(metaslab_t *msp, uint64_t size) * this metaslab again. In that case, it had better be empty, * or we would be leaving space on the table. */ - ASSERT(size >= SPA_MINBLOCKSIZE || msp->ms_map.sm_space == 0); + ASSERT(size >= SPA_MINBLOCKSIZE || msp->ms_map->sm_space == 0); metaslab_group_sort(msp->ms_group, msp, MIN(msp->ms_weight, size)); ASSERT((msp->ms_weight & METASLAB_ACTIVE_MASK) == 0); } +/* + * Determine if the in-core space map representation can be condensed on-disk. + * We would like to use the following criteria to make our decision: + * + * 1. The size of the space map object should not dramatically increase as a + * result of writing out our in-core free map. + * + * 2. The minimal on-disk space map representation is zfs_condense_pct/100 + * times the size than the in-core representation (i.e. zfs_condense_pct = 110 + * and in-core = 1MB, minimal = 1.1.MB). + * + * Checking the first condition is tricky since we don't want to walk + * the entire AVL tree calculating the estimated on-disk size. Instead we + * use the size-ordered AVL tree in the space map and calculate the + * size required for the largest segment in our in-core free map. If the + * size required to represent that segment on disk is larger than the space + * map object then we avoid condensing this map. + * + * To determine the second criterion we use a best-case estimate and assume + * each segment can be represented on-disk as a single 64-bit entry. We refer + * to this best-case estimate as the space map's minimal form. + */ +static boolean_t +metaslab_should_condense(metaslab_t *msp) +{ + space_map_t *sm = msp->ms_map; + space_map_obj_t *smo = &msp->ms_smo_syncing; + space_seg_t *ss; + uint64_t size, entries, segsz; + + ASSERT(MUTEX_HELD(&msp->ms_lock)); + ASSERT(sm->sm_loaded); + + /* + * Use the sm_pp_root AVL tree, which is ordered by size, to obtain + * the largest segment in the in-core free map. If the tree is + * empty then we should condense the map. + */ + ss = avl_last(sm->sm_pp_root); + if (ss == NULL) + return (B_TRUE); + + /* + * Calculate the number of 64-bit entries this segment would + * require when written to disk. If this single segment would be + * larger on-disk than the entire current on-disk structure, then + * clearly condensing will increase the on-disk structure size. + */ + size = (ss->ss_end - ss->ss_start) >> sm->sm_shift; + entries = size / (MIN(size, SM_RUN_MAX)); + segsz = entries * sizeof (uint64_t); + + return (segsz <= smo->smo_objsize && + smo->smo_objsize >= (zfs_condense_pct * + sizeof (uint64_t) * avl_numnodes(&sm->sm_root)) / 100); +} + +/* + * Condense the on-disk space map representation to its minimized form. + * The minimized form consists of a small number of allocations followed by + * the in-core free map. + */ +static void +metaslab_condense(metaslab_t *msp, uint64_t txg, dmu_tx_t *tx) +{ + spa_t *spa = msp->ms_group->mg_vd->vdev_spa; + space_map_t *freemap = msp->ms_freemap[txg & TXG_MASK]; + space_map_t condense_map; + space_map_t *sm = msp->ms_map; + objset_t *mos = spa_meta_objset(spa); + space_map_obj_t *smo = &msp->ms_smo_syncing; + + ASSERT(MUTEX_HELD(&msp->ms_lock)); + ASSERT3U(spa_sync_pass(spa), ==, 1); + ASSERT(sm->sm_loaded); + + spa_dbgmsg(spa, "condensing: txg %llu, msp[%llu] %p, " + "smo size %llu, segments %lu", txg, + (msp->ms_map->sm_start / msp->ms_map->sm_size), msp, + smo->smo_objsize, avl_numnodes(&sm->sm_root)); + + /* + * Create an map that is a 100% allocated map. We remove segments + * that have been freed in this txg, any deferred frees that exist, + * and any allocation in the future. Removing segments should be + * a relatively inexpensive operation since we expect these maps to + * a small number of nodes. + */ + space_map_create(&condense_map, sm->sm_start, sm->sm_size, + sm->sm_shift, sm->sm_lock); + space_map_add(&condense_map, condense_map.sm_start, + condense_map.sm_size); + + /* + * Remove what's been freed in this txg from the condense_map. + * Since we're in sync_pass 1, we know that all the frees from + * this txg are in the freemap. + */ + space_map_walk(freemap, space_map_remove, &condense_map); + + for (int t = 0; t < TXG_DEFER_SIZE; t++) + space_map_walk(msp->ms_defermap[t], + space_map_remove, &condense_map); + + for (int t = 1; t < TXG_CONCURRENT_STATES; t++) + space_map_walk(msp->ms_allocmap[(txg + t) & TXG_MASK], + space_map_remove, &condense_map); + + /* + * We're about to drop the metaslab's lock thus allowing + * other consumers to change it's content. Set the + * space_map's sm_condensing flag to ensure that + * allocations on this metaslab do not occur while we're + * in the middle of committing it to disk. This is only critical + * for the ms_map as all other space_maps use per txg + * views of their content. + */ + sm->sm_condensing = B_TRUE; + + mutex_exit(&msp->ms_lock); + space_map_truncate(smo, mos, tx); + mutex_enter(&msp->ms_lock); + + /* + * While we would ideally like to create a space_map representation + * that consists only of allocation records, doing so can be + * prohibitively expensive because the in-core free map can be + * large, and therefore computationally expensive to subtract + * from the condense_map. Instead we sync out two maps, a cheap + * allocation only map followed by the in-core free map. While not + * optimal, this is typically close to optimal, and much cheaper to + * compute. + */ + space_map_sync(&condense_map, SM_ALLOC, smo, mos, tx); + space_map_vacate(&condense_map, NULL, NULL); + space_map_destroy(&condense_map); + + space_map_sync(sm, SM_FREE, smo, mos, tx); + sm->sm_condensing = B_FALSE; + + spa_dbgmsg(spa, "condensed: txg %llu, msp[%llu] %p, " + "smo size %llu", txg, + (msp->ms_map->sm_start / msp->ms_map->sm_size), msp, + smo->smo_objsize); +} + /* * Write a metaslab to disk in the context of the specified transaction group. */ @@ -935,17 +1095,29 @@ metaslab_sync(metaslab_t *msp, uint64_t txg) vdev_t *vd = msp->ms_group->mg_vd; spa_t *spa = vd->vdev_spa; objset_t *mos = spa_meta_objset(spa); - space_map_t *allocmap = &msp->ms_allocmap[txg & TXG_MASK]; - space_map_t *freemap = &msp->ms_freemap[txg & TXG_MASK]; - space_map_t *freed_map = &msp->ms_freemap[TXG_CLEAN(txg) & TXG_MASK]; - space_map_t *sm = &msp->ms_map; + space_map_t *allocmap = msp->ms_allocmap[txg & TXG_MASK]; + space_map_t **freemap = &msp->ms_freemap[txg & TXG_MASK]; + space_map_t **freed_map = &msp->ms_freemap[TXG_CLEAN(txg) & TXG_MASK]; + space_map_t *sm = msp->ms_map; space_map_obj_t *smo = &msp->ms_smo_syncing; dmu_buf_t *db; dmu_tx_t *tx; ASSERT(!vd->vdev_ishole); - if (allocmap->sm_space == 0 && freemap->sm_space == 0) + /* + * This metaslab has just been added so there's no work to do now. + */ + if (*freemap == NULL) { + ASSERT3P(allocmap, ==, NULL); + return; + } + + ASSERT3P(allocmap, !=, NULL); + ASSERT3P(*freemap, !=, NULL); + ASSERT3P(*freed_map, !=, NULL); + + if (allocmap->sm_space == 0 && (*freemap)->sm_space == 0) return; /* @@ -973,49 +1145,36 @@ metaslab_sync(metaslab_t *msp, uint64_t txg) mutex_enter(&msp->ms_lock); - space_map_walk(freemap, space_map_add, freed_map); - - if (sm->sm_loaded && spa_sync_pass(spa) == 1 && smo->smo_objsize >= - 2 * sizeof (uint64_t) * avl_numnodes(&sm->sm_root)) { - /* - * The in-core space map representation is twice as compact - * as the on-disk one, so it's time to condense the latter - * by generating a pure allocmap from first principles. - * - * This metaslab is 100% allocated, - * minus the content of the in-core map (sm), - * minus what's been freed this txg (freed_map), - * minus deferred frees (ms_defermap[]), - * minus allocations from txgs in the future - * (because they haven't been committed yet). - */ - space_map_vacate(allocmap, NULL, NULL); - space_map_vacate(freemap, NULL, NULL); - - space_map_add(allocmap, allocmap->sm_start, allocmap->sm_size); - - space_map_walk(sm, space_map_remove, allocmap); - space_map_walk(freed_map, space_map_remove, allocmap); - - for (int t = 0; t < TXG_DEFER_SIZE; t++) - space_map_walk(&msp->ms_defermap[t], - space_map_remove, allocmap); - - for (int t = 1; t < TXG_CONCURRENT_STATES; t++) - space_map_walk(&msp->ms_allocmap[(txg + t) & TXG_MASK], - space_map_remove, allocmap); - - mutex_exit(&msp->ms_lock); - space_map_truncate(smo, mos, tx); - mutex_enter(&msp->ms_lock); + if (sm->sm_loaded && spa_sync_pass(spa) == 1 && + metaslab_should_condense(msp)) { + metaslab_condense(msp, txg, tx); + } else { + space_map_sync(allocmap, SM_ALLOC, smo, mos, tx); + space_map_sync(*freemap, SM_FREE, smo, mos, tx); } - space_map_sync(allocmap, SM_ALLOC, smo, mos, tx); - space_map_sync(freemap, SM_FREE, smo, mos, tx); + space_map_vacate(allocmap, NULL, NULL); + + /* + * For sync pass 1, we avoid walking the entire space map and + * instead will just swap the pointers for freemap and + * freed_map. We can safely do this since the freed_map is + * guaranteed to be empty on the initial pass. + */ + if (spa_sync_pass(spa) == 1) { + ASSERT0((*freed_map)->sm_space); + ASSERT0(avl_numnodes(&(*freed_map)->sm_root)); + space_map_swap(freemap, freed_map); + } else { + space_map_vacate(*freemap, space_map_add, *freed_map); + } + + ASSERT0(msp->ms_allocmap[txg & TXG_MASK]->sm_space); + ASSERT0(msp->ms_freemap[txg & TXG_MASK]->sm_space); mutex_exit(&msp->ms_lock); - VERIFY(0 == dmu_bonus_hold(mos, smo->smo_object, FTAG, &db)); + VERIFY0(dmu_bonus_hold(mos, smo->smo_object, FTAG, &db)); dmu_buf_will_dirty(db, tx); ASSERT3U(db->db_size, >=, sizeof (*smo)); bcopy(smo, db->db_data, sizeof (*smo)); @@ -1033,9 +1192,9 @@ metaslab_sync_done(metaslab_t *msp, uint64_t txg) { space_map_obj_t *smo = &msp->ms_smo; space_map_obj_t *smosync = &msp->ms_smo_syncing; - space_map_t *sm = &msp->ms_map; - space_map_t *freed_map = &msp->ms_freemap[TXG_CLEAN(txg) & TXG_MASK]; - space_map_t *defer_map = &msp->ms_defermap[txg % TXG_DEFER_SIZE]; + space_map_t *sm = msp->ms_map; + space_map_t *freed_map = msp->ms_freemap[TXG_CLEAN(txg) & TXG_MASK]; + space_map_t *defer_map = msp->ms_defermap[txg % TXG_DEFER_SIZE]; metaslab_group_t *mg = msp->ms_group; vdev_t *vd = mg->mg_vd; int64_t alloc_delta, defer_delta; @@ -1046,19 +1205,30 @@ metaslab_sync_done(metaslab_t *msp, uint64_t txg) /* * If this metaslab is just becoming available, initialize its - * allocmaps and freemaps and add its capacity to the vdev. + * allocmaps, freemaps, and defermap and add its capacity to the vdev. */ - if (freed_map->sm_size == 0) { + if (freed_map == NULL) { + ASSERT(defer_map == NULL); for (int t = 0; t < TXG_SIZE; t++) { - space_map_create(&msp->ms_allocmap[t], sm->sm_start, + msp->ms_allocmap[t] = kmem_zalloc(sizeof (space_map_t), + KM_SLEEP); + space_map_create(msp->ms_allocmap[t], sm->sm_start, sm->sm_size, sm->sm_shift, sm->sm_lock); - space_map_create(&msp->ms_freemap[t], sm->sm_start, + msp->ms_freemap[t] = kmem_zalloc(sizeof (space_map_t), + KM_SLEEP); + space_map_create(msp->ms_freemap[t], sm->sm_start, sm->sm_size, sm->sm_shift, sm->sm_lock); } - for (int t = 0; t < TXG_DEFER_SIZE; t++) - space_map_create(&msp->ms_defermap[t], sm->sm_start, + for (int t = 0; t < TXG_DEFER_SIZE; t++) { + msp->ms_defermap[t] = kmem_zalloc(sizeof (space_map_t), + KM_SLEEP); + space_map_create(msp->ms_defermap[t], sm->sm_start, sm->sm_size, sm->sm_shift, sm->sm_lock); + } + + freed_map = msp->ms_freemap[TXG_CLEAN(txg) & TXG_MASK]; + defer_map = msp->ms_defermap[txg % TXG_DEFER_SIZE]; vdev_space_update(vd, 0, 0, sm->sm_size); } @@ -1068,8 +1238,8 @@ metaslab_sync_done(metaslab_t *msp, uint64_t txg) vdev_space_update(vd, alloc_delta + defer_delta, defer_delta, 0); - ASSERT(msp->ms_allocmap[txg & TXG_MASK].sm_space == 0); - ASSERT(msp->ms_freemap[txg & TXG_MASK].sm_space == 0); + ASSERT(msp->ms_allocmap[txg & TXG_MASK]->sm_space == 0); + ASSERT(msp->ms_freemap[txg & TXG_MASK]->sm_space == 0); /* * If there's a space_map_load() in progress, wait for it to complete @@ -1103,7 +1273,7 @@ metaslab_sync_done(metaslab_t *msp, uint64_t txg) int evictable = 1; for (int t = 1; t < TXG_CONCURRENT_STATES; t++) - if (msp->ms_allocmap[(txg + t) & TXG_MASK].sm_space) + if (msp->ms_allocmap[(txg + t) & TXG_MASK]->sm_space) evictable = 0; if (evictable && !metaslab_debug) @@ -1128,7 +1298,7 @@ metaslab_sync_reassess(metaslab_group_t *mg) for (int m = 0; m < vd->vdev_ms_count; m++) { metaslab_t *msp = vd->vdev_ms[m]; - if (msp->ms_map.sm_start > mg->mg_bonus_area) + if (msp->ms_map->sm_start > mg->mg_bonus_area) break; mutex_enter(&msp->ms_lock); @@ -1149,7 +1319,7 @@ metaslab_distance(metaslab_t *msp, dva_t *dva) { uint64_t ms_shift = msp->ms_group->mg_vd->vdev_ms_shift; uint64_t offset = DVA_GET_OFFSET(dva) >> ms_shift; - uint64_t start = msp->ms_map.sm_start >> ms_shift; + uint64_t start = msp->ms_map->sm_start >> ms_shift; if (msp->ms_group->mg_vd->vdev_id != DVA_GET_VDEV(dva)) return (1ULL << 63); @@ -1236,6 +1406,16 @@ metaslab_group_alloc(metaslab_group_t *mg, uint64_t psize, uint64_t asize, mutex_enter(&msp->ms_lock); + /* + * If this metaslab is currently condensing then pick again as + * we can't manipulate this metaslab until it's committed + * to disk. + */ + if (msp->ms_map->sm_condensing) { + mutex_exit(&msp->ms_lock); + continue; + } + /* * Ensure that the metaslab we have selected is still * capable of handling our request. It's possible that @@ -1262,20 +1442,20 @@ metaslab_group_alloc(metaslab_group_t *mg, uint64_t psize, uint64_t asize, continue; } - if ((offset = space_map_alloc(&msp->ms_map, asize)) != -1ULL) + if ((offset = space_map_alloc(msp->ms_map, asize)) != -1ULL) break; atomic_inc_64(&mg->mg_alloc_failures); - metaslab_passivate(msp, space_map_maxsize(&msp->ms_map)); + metaslab_passivate(msp, space_map_maxsize(msp->ms_map)); mutex_exit(&msp->ms_lock); } - if (msp->ms_allocmap[txg & TXG_MASK].sm_space == 0) + if (msp->ms_allocmap[txg & TXG_MASK]->sm_space == 0) vdev_dirty(mg->mg_vd, VDD_METASLAB, msp, txg); - space_map_add(&msp->ms_allocmap[txg & TXG_MASK], offset, asize); + space_map_add(msp->ms_allocmap[txg & TXG_MASK], offset, asize); mutex_exit(&msp->ms_lock); @@ -1507,13 +1687,13 @@ metaslab_free_dva(spa_t *spa, const dva_t *dva, uint64_t txg, boolean_t now) mutex_enter(&msp->ms_lock); if (now) { - space_map_remove(&msp->ms_allocmap[txg & TXG_MASK], + space_map_remove(msp->ms_allocmap[txg & TXG_MASK], offset, size); - space_map_free(&msp->ms_map, offset, size); + space_map_free(msp->ms_map, offset, size); } else { - if (msp->ms_freemap[txg & TXG_MASK].sm_space == 0) + if (msp->ms_freemap[txg & TXG_MASK]->sm_space == 0) vdev_dirty(vd, VDD_METASLAB, msp, txg); - space_map_add(&msp->ms_freemap[txg & TXG_MASK], offset, size); + space_map_add(msp->ms_freemap[txg & TXG_MASK], offset, size); } mutex_exit(&msp->ms_lock); @@ -1548,10 +1728,10 @@ metaslab_claim_dva(spa_t *spa, const dva_t *dva, uint64_t txg) mutex_enter(&msp->ms_lock); - if ((txg != 0 && spa_writeable(spa)) || !msp->ms_map.sm_loaded) + if ((txg != 0 && spa_writeable(spa)) || !msp->ms_map->sm_loaded) error = metaslab_activate(msp, METASLAB_WEIGHT_SECONDARY); - if (error == 0 && !space_map_contains(&msp->ms_map, offset, size)) + if (error == 0 && !space_map_contains(msp->ms_map, offset, size)) error = ENOENT; if (error || txg == 0) { /* txg == 0 indicates dry run */ @@ -1559,12 +1739,12 @@ metaslab_claim_dva(spa_t *spa, const dva_t *dva, uint64_t txg) return (error); } - space_map_claim(&msp->ms_map, offset, size); + space_map_claim(msp->ms_map, offset, size); if (spa_writeable(spa)) { /* don't dirty if we're zdb(1M) */ - if (msp->ms_allocmap[txg & TXG_MASK].sm_space == 0) + if (msp->ms_allocmap[txg & TXG_MASK]->sm_space == 0) vdev_dirty(vd, VDD_METASLAB, msp, txg); - space_map_add(&msp->ms_allocmap[txg & TXG_MASK], offset, size); + space_map_add(msp->ms_allocmap[txg & TXG_MASK], offset, size); } mutex_exit(&msp->ms_lock); diff --git a/uts/common/fs/zfs/space_map.c b/uts/common/fs/zfs/space_map.c index 17dd860eacf..30a35c85dab 100644 --- a/uts/common/fs/zfs/space_map.c +++ b/uts/common/fs/zfs/space_map.c @@ -107,6 +107,7 @@ space_map_add(space_map_t *sm, uint64_t start, uint64_t size) int merge_before, merge_after; ASSERT(MUTEX_HELD(sm->sm_lock)); + VERIFY(!sm->sm_condensing); VERIFY(size != 0); VERIFY3U(start, >=, sm->sm_start); VERIFY3U(end, <=, sm->sm_start + sm->sm_size); @@ -175,6 +176,7 @@ space_map_remove(space_map_t *sm, uint64_t start, uint64_t size) int left_over, right_over; ASSERT(MUTEX_HELD(sm->sm_lock)); + VERIFY(!sm->sm_condensing); VERIFY(size != 0); VERIFY(P2PHASE(start, 1ULL << sm->sm_shift) == 0); VERIFY(P2PHASE(size, 1ULL << sm->sm_shift) == 0); @@ -243,6 +245,20 @@ space_map_contains(space_map_t *sm, uint64_t start, uint64_t size) return (ss != NULL && ss->ss_start <= start && ss->ss_end >= end); } +void +space_map_swap(space_map_t **msrc, space_map_t **mdst) +{ + space_map_t *sm; + + ASSERT(MUTEX_HELD((*msrc)->sm_lock)); + ASSERT0((*mdst)->sm_space); + ASSERT0(avl_numnodes(&(*mdst)->sm_root)); + + sm = *msrc; + *msrc = *mdst; + *mdst = sm; +} + void space_map_vacate(space_map_t *sm, space_map_func_t *func, space_map_t *mdest) { @@ -424,9 +440,9 @@ space_map_sync(space_map_t *sm, uint8_t maptype, space_map_obj_t *smo, objset_t *os, dmu_tx_t *tx) { spa_t *spa = dmu_objset_spa(os); - void *cookie = NULL; + avl_tree_t *t = &sm->sm_root; space_seg_t *ss; - uint64_t bufsize, start, size, run_len, delta, sm_space; + uint64_t bufsize, start, size, run_len, total, sm_space, nodes; uint64_t *entry, *entry_map, *entry_map_end; ASSERT(MUTEX_HELD(sm->sm_lock)); @@ -455,13 +471,14 @@ space_map_sync(space_map_t *sm, uint8_t maptype, SM_DEBUG_SYNCPASS_ENCODE(spa_sync_pass(spa)) | SM_DEBUG_TXG_ENCODE(dmu_tx_get_txg(tx)); - delta = 0; + total = 0; + nodes = avl_numnodes(&sm->sm_root); sm_space = sm->sm_space; - while ((ss = avl_destroy_nodes(&sm->sm_root, &cookie)) != NULL) { + for (ss = avl_first(t); ss != NULL; ss = AVL_NEXT(t, ss)) { size = ss->ss_end - ss->ss_start; start = (ss->ss_start - sm->sm_start) >> sm->sm_shift; - delta += size; + total += size; size >>= sm->sm_shift; while (size) { @@ -483,7 +500,6 @@ space_map_sync(space_map_t *sm, uint8_t maptype, start += run_len; size -= run_len; } - kmem_cache_free(space_seg_cache, ss); } if (entry != entry_map) { @@ -499,12 +515,11 @@ space_map_sync(space_map_t *sm, uint8_t maptype, * Ensure that the space_map's accounting wasn't changed * while we were in the middle of writing it out. */ + VERIFY3U(nodes, ==, avl_numnodes(&sm->sm_root)); VERIFY3U(sm->sm_space, ==, sm_space); + VERIFY3U(sm->sm_space, ==, total); zio_buf_free(entry_map, bufsize); - - sm->sm_space -= delta; - VERIFY0(sm->sm_space); } void diff --git a/uts/common/fs/zfs/sys/metaslab_impl.h b/uts/common/fs/zfs/sys/metaslab_impl.h index f1f1b38eeed..138e14ef59f 100644 --- a/uts/common/fs/zfs/sys/metaslab_impl.h +++ b/uts/common/fs/zfs/sys/metaslab_impl.h @@ -66,20 +66,38 @@ struct metaslab_group { }; /* - * Each metaslab's free space is tracked in space map object in the MOS, - * which is only updated in syncing context. Each time we sync a txg, + * Each metaslab maintains an in-core free map (ms_map) that contains the + * current list of free segments. As blocks are allocated, the allocated + * segment is removed from the ms_map and added to a per txg allocation map. + * As blocks are freed, they are added to the per txg free map. These per + * txg maps allow us to process all allocations and frees in syncing context + * where it is safe to update the on-disk space maps. + * + * Each metaslab's free space is tracked in a space map object in the MOS, + * which is only updated in syncing context. Each time we sync a txg, * we append the allocs and frees from that txg to the space map object. * When the txg is done syncing, metaslab_sync_done() updates ms_smo - * to ms_smo_syncing. Everything in ms_smo is always safe to allocate. + * to ms_smo_syncing. Everything in ms_smo is always safe to allocate. + * + * To load the in-core free map we read the space map object from disk. + * This object contains a series of alloc and free records that are + * combined to make up the list of all free segments in this metaslab. These + * segments are represented in-core by the ms_map and are stored in an + * AVL tree. + * + * As the space map objects grows (as a result of the appends) it will + * eventually become space-inefficient. When the space map object is + * zfs_condense_pct/100 times the size of the minimal on-disk representation, + * we rewrite it in its minimized form. */ struct metaslab { kmutex_t ms_lock; /* metaslab lock */ space_map_obj_t ms_smo; /* synced space map object */ space_map_obj_t ms_smo_syncing; /* syncing space map object */ - space_map_t ms_allocmap[TXG_SIZE]; /* allocated this txg */ - space_map_t ms_freemap[TXG_SIZE]; /* freed this txg */ - space_map_t ms_defermap[TXG_DEFER_SIZE]; /* deferred frees */ - space_map_t ms_map; /* in-core free space map */ + space_map_t *ms_allocmap[TXG_SIZE]; /* allocated this txg */ + space_map_t *ms_freemap[TXG_SIZE]; /* freed this txg */ + space_map_t *ms_defermap[TXG_DEFER_SIZE]; /* deferred frees */ + space_map_t *ms_map; /* in-core free space map */ int64_t ms_deferspace; /* sum of ms_defermap[] space */ uint64_t ms_weight; /* weight vs. others in group */ metaslab_group_t *ms_group; /* metaslab group */ diff --git a/uts/common/fs/zfs/sys/space_map.h b/uts/common/fs/zfs/sys/space_map.h index 463b6bb4f2a..2da50fb7b3b 100644 --- a/uts/common/fs/zfs/sys/space_map.h +++ b/uts/common/fs/zfs/sys/space_map.h @@ -40,17 +40,17 @@ extern "C" { typedef struct space_map_ops space_map_ops_t; typedef struct space_map { - avl_tree_t sm_root; /* AVL tree of map segments */ + avl_tree_t sm_root; /* offset-ordered segment AVL tree */ uint64_t sm_space; /* sum of all segments in the map */ uint64_t sm_start; /* start of map */ uint64_t sm_size; /* size of map */ uint8_t sm_shift; /* unit shift */ - uint8_t sm_pad[3]; /* unused */ uint8_t sm_loaded; /* map loaded? */ uint8_t sm_loading; /* map loading? */ + uint8_t sm_condensing; /* map condensing? */ kcondvar_t sm_load_cv; /* map load completion */ space_map_ops_t *sm_ops; /* space map block picker ops vector */ - avl_tree_t *sm_pp_root; /* picker-private AVL tree */ + avl_tree_t *sm_pp_root; /* size-ordered, picker-private tree */ void *sm_ppd; /* picker-private data */ kmutex_t *sm_lock; /* pointer to lock that protects map */ } space_map_t; @@ -149,6 +149,7 @@ extern void space_map_add(space_map_t *sm, uint64_t start, uint64_t size); extern void space_map_remove(space_map_t *sm, uint64_t start, uint64_t size); extern boolean_t space_map_contains(space_map_t *sm, uint64_t start, uint64_t size); +extern void space_map_swap(space_map_t **msrc, space_map_t **mdest); extern void space_map_vacate(space_map_t *sm, space_map_func_t *func, space_map_t *mdest); extern void space_map_walk(space_map_t *sm, diff --git a/uts/common/fs/zfs/vdev.c b/uts/common/fs/zfs/vdev.c index 4f5c4e9c4df..41f9a07524d 100644 --- a/uts/common/fs/zfs/vdev.c +++ b/uts/common/fs/zfs/vdev.c @@ -1836,6 +1836,7 @@ vdev_dtl_sync(vdev_t *vd, uint64_t txg) space_map_truncate(smo, mos, tx); space_map_sync(&smsync, SM_ALLOC, smo, mos, tx); + space_map_vacate(&smsync, NULL, NULL); space_map_destroy(&smsync); From cca1f5d90df9f1566556598bfd6afc12ff929e68 Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Sat, 23 Feb 2013 09:02:46 +0000 Subject: [PATCH 0366/1476] Update vendor-sys/illumos/dist to illumos-gate 13966:0e1d84ebb004 Illumos ZFS issues: 3578 transferring the freed map to the defer map should be constant time 3579 ztest trips assertion in metaslab_weight() --- uts/common/fs/zfs/metaslab.c | 38 +++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/uts/common/fs/zfs/metaslab.c b/uts/common/fs/zfs/metaslab.c index 9c4f97a3131..76c66a00a33 100644 --- a/uts/common/fs/zfs/metaslab.c +++ b/uts/common/fs/zfs/metaslab.c @@ -813,6 +813,16 @@ metaslab_weight(metaslab_t *msp) ASSERT(MUTEX_HELD(&msp->ms_lock)); + /* + * This vdev is in the process of being removed so there is nothing + * for us to do here. + */ + if (vd->vdev_removing) { + ASSERT0(smo->smo_alloc); + ASSERT0(vd->vdev_ms_shift); + return (0); + } + /* * The baseline weight is the metaslab's free space. */ @@ -1193,8 +1203,8 @@ metaslab_sync_done(metaslab_t *msp, uint64_t txg) space_map_obj_t *smo = &msp->ms_smo; space_map_obj_t *smosync = &msp->ms_smo_syncing; space_map_t *sm = msp->ms_map; - space_map_t *freed_map = msp->ms_freemap[TXG_CLEAN(txg) & TXG_MASK]; - space_map_t *defer_map = msp->ms_defermap[txg % TXG_DEFER_SIZE]; + space_map_t **freed_map = &msp->ms_freemap[TXG_CLEAN(txg) & TXG_MASK]; + space_map_t **defer_map = &msp->ms_defermap[txg % TXG_DEFER_SIZE]; metaslab_group_t *mg = msp->ms_group; vdev_t *vd = mg->mg_vd; int64_t alloc_delta, defer_delta; @@ -1207,8 +1217,8 @@ metaslab_sync_done(metaslab_t *msp, uint64_t txg) * If this metaslab is just becoming available, initialize its * allocmaps, freemaps, and defermap and add its capacity to the vdev. */ - if (freed_map == NULL) { - ASSERT(defer_map == NULL); + if (*freed_map == NULL) { + ASSERT(*defer_map == NULL); for (int t = 0; t < TXG_SIZE; t++) { msp->ms_allocmap[t] = kmem_zalloc(sizeof (space_map_t), KM_SLEEP); @@ -1227,14 +1237,14 @@ metaslab_sync_done(metaslab_t *msp, uint64_t txg) sm->sm_size, sm->sm_shift, sm->sm_lock); } - freed_map = msp->ms_freemap[TXG_CLEAN(txg) & TXG_MASK]; - defer_map = msp->ms_defermap[txg % TXG_DEFER_SIZE]; + freed_map = &msp->ms_freemap[TXG_CLEAN(txg) & TXG_MASK]; + defer_map = &msp->ms_defermap[txg % TXG_DEFER_SIZE]; vdev_space_update(vd, 0, 0, sm->sm_size); } alloc_delta = smosync->smo_alloc - smo->smo_alloc; - defer_delta = freed_map->sm_space - defer_map->sm_space; + defer_delta = (*freed_map)->sm_space - (*defer_map)->sm_space; vdev_space_update(vd, alloc_delta + defer_delta, defer_delta, 0); @@ -1244,12 +1254,18 @@ metaslab_sync_done(metaslab_t *msp, uint64_t txg) /* * If there's a space_map_load() in progress, wait for it to complete * so that we have a consistent view of the in-core space map. - * Then, add defer_map (oldest deferred frees) to this map and - * transfer freed_map (this txg's frees) to defer_map. */ space_map_load_wait(sm); - space_map_vacate(defer_map, sm->sm_loaded ? space_map_free : NULL, sm); - space_map_vacate(freed_map, space_map_add, defer_map); + + /* + * Move the frees from the defer_map to this map (if it's loaded). + * Swap the freed_map and the defer_map -- this is safe to do + * because we've just emptied out the defer_map. + */ + space_map_vacate(*defer_map, sm->sm_loaded ? space_map_free : NULL, sm); + ASSERT0((*defer_map)->sm_space); + ASSERT0(avl_numnodes(&(*defer_map)->sm_root)); + space_map_swap(freed_map, defer_map); *smo = *smosync; From 3e63c757553472a19bdb02b0b85c61c927326975 Mon Sep 17 00:00:00 2001 From: Martin Matuska Date: Sat, 23 Feb 2013 09:06:36 +0000 Subject: [PATCH 0367/1476] Update vendor/illumos/dist and vendor-sys/illumos/dist to illumos-gate 13967:92bec6d87f59 Illumos ZFS issues: 3557 dumpvp_size is not updated correctly when a dump zvol's size is changed 3558 setting the volsize on a dump device does not return back ENOSPC 3559 setting a volsize larger than the space available sometimes succeeds --- cmd/zfs/zfs_main.c | 12 +++- lib/libzfs/common/libzfs_dataset.c | 22 +++++-- uts/common/fs/zfs/sys/zvol.h | 2 +- uts/common/fs/zfs/zfs_ioctl.c | 3 +- uts/common/fs/zfs/zvol.c | 97 +++++++++++++++++------------- 5 files changed, 83 insertions(+), 53 deletions(-) diff --git a/cmd/zfs/zfs_main.c b/cmd/zfs/zfs_main.c index ee9d289a11a..e5e35e6f166 100644 --- a/cmd/zfs/zfs_main.c +++ b/cmd/zfs/zfs_main.c @@ -775,10 +775,12 @@ zfs_do_create(int argc, char **argv) if (type == ZFS_TYPE_VOLUME && !noreserve) { zpool_handle_t *zpool_handle; + nvlist_t *real_props; uint64_t spa_version; char *p; zfs_prop_t resv_prop; char *strval; + char msg[1024]; if (p = strchr(argv[0], '/')) *p = '\0'; @@ -794,7 +796,15 @@ zfs_do_create(int argc, char **argv) resv_prop = ZFS_PROP_REFRESERVATION; else resv_prop = ZFS_PROP_RESERVATION; - volsize = zvol_volsize_to_reservation(volsize, props); + + (void) snprintf(msg, sizeof (msg), + gettext("cannot create '%s'"), argv[0]); + if (props && (real_props = zfs_valid_proplist(g_zfs, type, + props, 0, NULL, msg)) == NULL) + goto error; + + volsize = zvol_volsize_to_reservation(volsize, real_props); + nvlist_free(real_props); if (nvlist_lookup_string(props, zfs_prop_to_name(resv_prop), &strval) != 0) { diff --git a/lib/libzfs/common/libzfs_dataset.c b/lib/libzfs/common/libzfs_dataset.c index 35d27d9d1ff..3ad1ed69d57 100644 --- a/lib/libzfs/common/libzfs_dataset.c +++ b/lib/libzfs/common/libzfs_dataset.c @@ -1283,6 +1283,7 @@ zfs_add_synthetic_resv(zfs_handle_t *zhp, nvlist_t *nvl) uint64_t old_reservation; uint64_t new_reservation; zfs_prop_t resv_prop; + nvlist_t *props; /* * If this is an existing volume, and someone is setting the volsize, @@ -1292,16 +1293,25 @@ zfs_add_synthetic_resv(zfs_handle_t *zhp, nvlist_t *nvl) if (zfs_which_resv_prop(zhp, &resv_prop) < 0) return (-1); old_reservation = zfs_prop_get_int(zhp, resv_prop); - if ((zvol_volsize_to_reservation(old_volsize, zhp->zfs_props) != - old_reservation) || nvlist_lookup_uint64(nvl, - zfs_prop_to_name(resv_prop), &new_reservation) != ENOENT) { + + props = fnvlist_alloc(); + fnvlist_add_uint64(props, zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), + zfs_prop_get_int(zhp, ZFS_PROP_VOLBLOCKSIZE)); + + if ((zvol_volsize_to_reservation(old_volsize, props) != + old_reservation) || nvlist_exists(nvl, + zfs_prop_to_name(resv_prop))) { + fnvlist_free(props); return (0); } if (nvlist_lookup_uint64(nvl, zfs_prop_to_name(ZFS_PROP_VOLSIZE), - &new_volsize) != 0) + &new_volsize) != 0) { + fnvlist_free(props); return (-1); - new_reservation = zvol_volsize_to_reservation(new_volsize, - zhp->zfs_props); + } + new_reservation = zvol_volsize_to_reservation(new_volsize, props); + fnvlist_free(props); + if (nvlist_add_uint64(nvl, zfs_prop_to_name(resv_prop), new_reservation) != 0) { (void) no_memory(zhp->zfs_hdl); diff --git a/uts/common/fs/zfs/sys/zvol.h b/uts/common/fs/zfs/sys/zvol.h index 0059bf51026..db1f05ae9ca 100644 --- a/uts/common/fs/zfs/sys/zvol.h +++ b/uts/common/fs/zfs/sys/zvol.h @@ -43,7 +43,7 @@ extern void zvol_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx); extern int zvol_create_minor(const char *); extern int zvol_remove_minor(const char *); extern void zvol_remove_minors(const char *); -extern int zvol_set_volsize(const char *, major_t, uint64_t); +extern int zvol_set_volsize(const char *, uint64_t); extern int zvol_open(dev_t *devp, int flag, int otyp, cred_t *cr); extern int zvol_dump(dev_t dev, caddr_t addr, daddr_t offset, int nblocks); diff --git a/uts/common/fs/zfs/zfs_ioctl.c b/uts/common/fs/zfs/zfs_ioctl.c index 090d6c9417a..38adc1940ff 100644 --- a/uts/common/fs/zfs/zfs_ioctl.c +++ b/uts/common/fs/zfs/zfs_ioctl.c @@ -2368,8 +2368,7 @@ zfs_prop_set_special(const char *dsname, zprop_source_t source, err = dsl_dataset_set_reservation(dsname, source, intval); break; case ZFS_PROP_VOLSIZE: - err = zvol_set_volsize(dsname, ddi_driver_major(zfs_dip), - intval); + err = zvol_set_volsize(dsname, intval); break; case ZFS_PROP_VERSION: { diff --git a/uts/common/fs/zfs/zvol.c b/uts/common/fs/zfs/zvol.c index da1b0efda5b..b413f5ed8b0 100644 --- a/uts/common/fs/zfs/zvol.c +++ b/uts/common/fs/zfs/zvol.c @@ -145,10 +145,11 @@ static int zvol_dump_fini(zvol_state_t *zv); static int zvol_dump_init(zvol_state_t *zv, boolean_t resize); static void -zvol_size_changed(uint64_t volsize, major_t maj, minor_t min) +zvol_size_changed(zvol_state_t *zv, uint64_t volsize) { - dev_t dev = makedevice(maj, min); + dev_t dev = makedevice(ddi_driver_major(zfs_dip), zv->zv_minor); + zv->zv_volsize = volsize; VERIFY(ddi_prop_update_int64(dev, zfs_dip, "Size", volsize) == DDI_SUCCESS); VERIFY(ddi_prop_update_int64(dev, zfs_dip, @@ -610,22 +611,22 @@ zvol_first_open(zvol_state_t *zv) if (error) return (error); + zv->zv_objset = os; error = zap_lookup(os, ZVOL_ZAP_OBJ, "size", 8, 1, &volsize); if (error) { ASSERT(error == 0); dmu_objset_disown(os, zvol_tag); return (error); } - zv->zv_objset = os; + error = dmu_bonus_hold(os, ZVOL_OBJ, zvol_tag, &zv->zv_dbuf); if (error) { dmu_objset_disown(os, zvol_tag); return (error); } - zv->zv_volsize = volsize; + + zvol_size_changed(zv, volsize); zv->zv_zilog = zil_open(os, zvol_get_data); - zvol_size_changed(zv->zv_volsize, ddi_driver_major(zfs_dip), - zv->zv_minor); VERIFY(dsl_prop_get_integer(zv->zv_name, "readonly", &readonly, NULL) == 0); @@ -747,56 +748,37 @@ zvol_remove_minors(const char *name) mutex_exit(&zfsdev_state_lock); } -int -zvol_set_volsize(const char *name, major_t maj, uint64_t volsize) +static int +zvol_set_volsize_impl(objset_t *os, zvol_state_t *zv, uint64_t volsize) { - zvol_state_t *zv = NULL; - objset_t *os; - int error; - dmu_object_info_t doi; uint64_t old_volsize = 0ULL; - uint64_t readonly; - - mutex_enter(&zfsdev_state_lock); - zv = zvol_minor_lookup(name); - if ((error = dmu_objset_hold(name, FTAG, &os)) != 0) { - mutex_exit(&zfsdev_state_lock); - return (error); - } - - if ((error = dmu_object_info(os, ZVOL_OBJ, &doi)) != 0 || - (error = zvol_check_volsize(volsize, - doi.doi_data_block_size)) != 0) - goto out; - - VERIFY(dsl_prop_get_integer(name, "readonly", &readonly, - NULL) == 0); - if (readonly) { - error = EROFS; - goto out; - } + int error; + ASSERT(MUTEX_HELD(&zfsdev_state_lock)); error = zvol_update_volsize(os, volsize); + /* * Reinitialize the dump area to the new size. If we * failed to resize the dump area then restore it back to - * its original size. + * its original size. We must set the new volsize prior + * to calling dumpvp_resize() to ensure that the devices' + * size(9P) is not visible by the dump subsystem. */ if (zv && error == 0) { + old_volsize = zv->zv_volsize; + zvol_size_changed(zv, volsize); + if (zv->zv_flags & ZVOL_DUMPIFIED) { - old_volsize = zv->zv_volsize; - zv->zv_volsize = volsize; if ((error = zvol_dumpify(zv)) != 0 || (error = dumpvp_resize()) != 0) { + int dumpify_error; + (void) zvol_update_volsize(os, old_volsize); - zv->zv_volsize = old_volsize; - error = zvol_dumpify(zv); + zvol_size_changed(zv, old_volsize); + dumpify_error = zvol_dumpify(zv); + error = dumpify_error ? dumpify_error : error; } } - if (error == 0) { - zv->zv_volsize = volsize; - zvol_size_changed(volsize, maj, zv->zv_minor); - } } /* @@ -819,12 +801,41 @@ zvol_set_volsize(const char *name, major_t maj, uint64_t volsize) nvlist_free(attr); kmem_free(physpath, MAXPATHLEN); } + return (error); +} +int +zvol_set_volsize(const char *name, uint64_t volsize) +{ + zvol_state_t *zv = NULL; + objset_t *os; + int error; + dmu_object_info_t doi; + uint64_t readonly; + + mutex_enter(&zfsdev_state_lock); + zv = zvol_minor_lookup(name); + if ((error = dmu_objset_hold(name, FTAG, &os)) != 0) { + mutex_exit(&zfsdev_state_lock); + return (error); + } + + if ((error = dmu_object_info(os, ZVOL_OBJ, &doi)) != 0 || + (error = zvol_check_volsize(volsize, + doi.doi_data_block_size)) != 0) + goto out; + + VERIFY3U(dsl_prop_get_integer(name, + zfs_prop_to_name(ZFS_PROP_READONLY), &readonly, NULL), ==, 0); + if (readonly) { + error = EROFS; + goto out; + } + + error = zvol_set_volsize_impl(os, zv, volsize); out: dmu_objset_rele(os, FTAG); - mutex_exit(&zfsdev_state_lock); - return (error); } From b3d4294f3a6ed7ec475f26eeefc24f0dbddd0a6c Mon Sep 17 00:00:00 2001 From: Giorgos Keramidas Date: Sat, 23 Feb 2013 12:31:52 +0000 Subject: [PATCH 0368/1476] Now that qsort(3) has a sample comparison function, point to that example from bsearch(3) too, so that we don't have to duplicate the example code in both places. PR: docs/176197 Reviewed by: stefanf Approved by: remko (mentor), gjb (mentor) MFC after: 1 week --- lib/libc/stdlib/bsearch.3 | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/libc/stdlib/bsearch.3 b/lib/libc/stdlib/bsearch.3 index b3591f8e998..25be8420687 100644 --- a/lib/libc/stdlib/bsearch.3 +++ b/lib/libc/stdlib/bsearch.3 @@ -32,7 +32,7 @@ .\" @(#)bsearch.3 8.3 (Berkeley) 4/19/94 .\" $FreeBSD$ .\" -.Dd April 19, 1994 +.Dd February 22, 2013 .Dt BSEARCH 3 .Os .Sh NAME @@ -71,6 +71,12 @@ less than, equal to, or greater than zero if the .Fa key object is found, respectively, to be less than, to match, or be greater than the array member. +See the +.Fa int_compare +sample function in +.Xr qsort 3 +for a comparison function that is also compatible with +.Fn bsearch . .Sh RETURN VALUES The .Fn bsearch From 57f00aa510f666d2820972a8a310defe77844294 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Sat, 23 Feb 2013 15:15:41 +0000 Subject: [PATCH 0369/1476] sh: Test that the exit status is 1 if read encounters EOF. --- tools/regression/bin/sh/builtins/read6.0 | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 tools/regression/bin/sh/builtins/read6.0 diff --git a/tools/regression/bin/sh/builtins/read6.0 b/tools/regression/bin/sh/builtins/read6.0 new file mode 100644 index 00000000000..2168e10c841 --- /dev/null +++ b/tools/regression/bin/sh/builtins/read6.0 @@ -0,0 +1,5 @@ +# $FreeBSD$ + +: | read x +r=$? +[ "$r" = 1 ] From 504266d60afd54186bb3c47beeb2db08d98137e3 Mon Sep 17 00:00:00 2001 From: Alexander Motin Date: Sat, 23 Feb 2013 18:32:42 +0000 Subject: [PATCH 0370/1476] Add basic and not very reliable protection against going to sleep with thread scheduled by interrupt fired after we entered critical section. None of cpu_sleep() implementations on ARM check sched_runnable() now, so put the first line of defence here. This mostly fixes unexpectedly long sleeps in synthetic tests of calloutng code and probably other situations. --- sys/arm/arm/machdep.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sys/arm/arm/machdep.c b/sys/arm/arm/machdep.c index ec65c04b18b..5262e71b2d5 100644 --- a/sys/arm/arm/machdep.c +++ b/sys/arm/arm/machdep.c @@ -45,6 +45,7 @@ #include "opt_compat.h" #include "opt_ddb.h" #include "opt_platform.h" +#include "opt_sched.h" #include "opt_timer.h" #include @@ -70,6 +71,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -433,19 +435,24 @@ void cpu_idle(int busy) { + CTR2(KTR_SPARE2, "cpu_idle(%d) at %d", + busy, curcpu); #ifndef NO_EVENTTIMERS if (!busy) { critical_enter(); cpu_idleclock(); } #endif - cpu_sleep(0); + if (!sched_runnable()) + cpu_sleep(0); #ifndef NO_EVENTTIMERS if (!busy) { cpu_activeclock(); critical_exit(); } #endif + CTR2(KTR_SPARE2, "cpu_idle(%d) at %d done", + busy, curcpu); } int From 1736d28c44758ae88747543f85a7dbbfb30449e9 Mon Sep 17 00:00:00 2001 From: Marcel Moolenaar Date: Sat, 23 Feb 2013 19:27:53 +0000 Subject: [PATCH 0371/1476] Enable PREEMPTION by default now that PR 147501 has been fixed. --- sys/ia64/conf/GENERIC | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/ia64/conf/GENERIC b/sys/ia64/conf/GENERIC index 196e5becc81..810578f3809 100644 --- a/sys/ia64/conf/GENERIC +++ b/sys/ia64/conf/GENERIC @@ -44,7 +44,7 @@ options NFSLOCKD # Network Lock Manager options NFSD # New Network Filesystem Server options NFS_ROOT # NFS usable as root device options P1003_1B_SEMAPHORES # POSIX-style semaphores -#options PREEMPTION # Enable kernel thread preemption +options PREEMPTION # Enable kernel thread preemption options PRINTF_BUFR_SIZE=128 # Printf buffering to limit interspersion options PROCFS # Process filesystem (/proc) options PSEUDOFS # Pseudo-filesystem framework From 7beaf3ae9b60bb8cd14dcf0eec1300956f535018 Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Sat, 23 Feb 2013 20:27:03 +0000 Subject: [PATCH 0372/1476] Print kernel args as late as possible before jumping into kernel. --- sys/boot/uboot/lib/elf_freebsd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/boot/uboot/lib/elf_freebsd.c b/sys/boot/uboot/lib/elf_freebsd.c index 81407708858..6b828d32c2c 100644 --- a/sys/boot/uboot/lib/elf_freebsd.c +++ b/sys/boot/uboot/lib/elf_freebsd.c @@ -82,9 +82,9 @@ __elfN(uboot_exec)(struct preloaded_file *fp) entry = uboot_vm_translate(e->e_entry); printf("Kernel entry at 0x%x...\n", (unsigned)entry); - printf("Kernel args: %s\n", fp->f_args); dev_cleanup(); + printf("Kernel args: %s\n", fp->f_args); (*entry)((void *)mdp); panic("exec returned"); From 3bb97cef0705acbb8951321e5a550cc06bb6c62d Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Sat, 23 Feb 2013 20:34:47 +0000 Subject: [PATCH 0373/1476] "fdt addr" gets run from loader.rc before the kernel is loaded. This was broken by r247045 which tried to copy the FDT into the module directory immediately. Instead, store the address and arrange for the FDT to get copied into the module directory later when the usual FDT initialization runs. --- sys/boot/fdt/fdt_loader_cmd.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/sys/boot/fdt/fdt_loader_cmd.c b/sys/boot/fdt/fdt_loader_cmd.c index 37cf75dfcca..0417c52e01e 100644 --- a/sys/boot/fdt/fdt_loader_cmd.c +++ b/sys/boot/fdt/fdt_loader_cmd.c @@ -62,7 +62,9 @@ __FBSDID("$FreeBSD$"); #define CMD_REQUIRES_BLOB 0x01 -/* Local copy of FDT */ +/* Location of FDT yet to be loaded. */ +static struct fdt_header *fdt_to_load = NULL; +/* Local copy of FDT on heap. */ static struct fdt_header *fdtp = NULL; /* Size of FDT blob */ static size_t fdtp_size = 0; @@ -252,13 +254,20 @@ fdt_setup_fdtp() { struct preloaded_file *bfp; struct fdt_header *hdr; - const char *s, *p; + const char *s; + char *p; vm_offset_t va; if ((bfp = file_findfile(NULL, "dtb")) != NULL) { printf("Using DTB from loaded file.\n"); return fdt_load_dtb(bfp->f_addr); - } + } + + if (fdt_to_load != NULL) { + printf("Using DTB from memory address 0x%08X.\n", + (unsigned int)fdt_to_load); + return fdt_load_dtb_addr(fdt_to_load); + } s = ub_env_get("fdtaddr"); if (s != NULL && *s != '\0') { @@ -810,8 +819,12 @@ command_fdt_internal(int argc, char *argv[]) static int fdt_cmd_addr(int argc, char *argv[]) { + struct preloaded_file *fp; struct fdt_header *hdr; - const char *addr, *cp; + const char *addr; + char *cp; + + fdt_to_load = NULL; if (argc > 2) addr = argv[2]; @@ -820,15 +833,17 @@ fdt_cmd_addr(int argc, char *argv[]) return (CMD_ERROR); } - hdr = (struct fdt_header *)strtoul(addr, &cp, 0); + hdr = (struct fdt_header *)strtoul(addr, &cp, 16); if (cp == addr) { sprintf(command_errbuf, "Invalid address: %s", addr); return (CMD_ERROR); } - if (fdt_load_dtb_addr(hdr) != 0) - return (CMD_ERROR); + while ((fp = file_findfile(NULL, "dtb")) != NULL) { + file_discard(fp); + } + fdt_to_load = hdr; return (CMD_OK); } From e5b6b345cf754cba67929f5bd483b140d7cb4071 Mon Sep 17 00:00:00 2001 From: Oleksandr Tymoshenko Date: Sat, 23 Feb 2013 22:46:26 +0000 Subject: [PATCH 0374/1476] Add macroses to properly map IO peripherals memory window from ARM physical memory address space to VideoCore address space --- sys/arm/broadcom/bcm2835/bcm2835_vcbus.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sys/arm/broadcom/bcm2835/bcm2835_vcbus.h b/sys/arm/broadcom/bcm2835/bcm2835_vcbus.h index 1d91046eb88..cb871f23bf9 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_vcbus.h +++ b/sys/arm/broadcom/bcm2835/bcm2835_vcbus.h @@ -34,14 +34,28 @@ #define _BCM2835_VCBUS_H_ #define BCM2835_VCBUS_SDRAM_CACHED 0x40000000 +#define BCM2835_VCBUS_IO_BASE 0x7E000000 #define BCM2835_VCBUS_SDRAM_UNCACHED 0xC0000000 +#define BCM2835_ARM_IO_BASE 0x20000000 +#define BCM2835_ARM_IO_SIZE 0x02000000 + /* * Convert physical address to VC bus address. Should be used * when submitting address over mailbox interface */ #define PHYS_TO_VCBUS(pa) ((pa) + BCM2835_VCBUS_SDRAM_CACHED) +/* Check whether pa bellong top IO window */ +#define BCM2835_ARM_IS_IO(pa) (((pa) >= BCM2835_ARM_IO_BASE) && \ + ((pa) < BCM2835_ARM_IO_BASE + BCM2835_ARM_IO_SIZE)) + +/* + * Convert physical address in IO space to VC bus address. + */ +#define IO_TO_VCBUS(pa) ((pa - BCM2835_ARM_IO_BASE) + \ + BCM2835_VCBUS_IO_BASE) + /* * Convert address from VC bus space to physical. Should be used * when address is returned by VC over mailbox interface. e.g. From b2a67e7b16deb1f765b335afde59f44aa785ff01 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sat, 23 Feb 2013 22:48:12 +0000 Subject: [PATCH 0375/1476] Pull in r175962 from upstream llvm trunk: X86: Disable cmov-memory patterns on subtargets without cmov. Fixes PR15115. For the i386 arch, this should enable cmov instructions only on -march=pentiumpro and higher. Since our default CPU is i486, cmov instructions will now be disabled by default. MFC after: 1 week --- contrib/llvm/lib/Target/X86/X86InstrCompiler.td | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/contrib/llvm/lib/Target/X86/X86InstrCompiler.td b/contrib/llvm/lib/Target/X86/X86InstrCompiler.td index 9e6f27988f7..0d9c81e81c6 100644 --- a/contrib/llvm/lib/Target/X86/X86InstrCompiler.td +++ b/contrib/llvm/lib/Target/X86/X86InstrCompiler.td @@ -1076,12 +1076,14 @@ def : Pat<(X86cmp GR64:$src1, 0), // inverted. multiclass CMOVmr { - def : Pat<(X86cmov (loadi16 addr:$src1), GR16:$src2, InvertedCond, EFLAGS), - (Inst16 GR16:$src2, addr:$src1)>; - def : Pat<(X86cmov (loadi32 addr:$src1), GR32:$src2, InvertedCond, EFLAGS), - (Inst32 GR32:$src2, addr:$src1)>; - def : Pat<(X86cmov (loadi64 addr:$src1), GR64:$src2, InvertedCond, EFLAGS), - (Inst64 GR64:$src2, addr:$src1)>; + let Predicates = [HasCMov] in { + def : Pat<(X86cmov (loadi16 addr:$src1), GR16:$src2, InvertedCond, EFLAGS), + (Inst16 GR16:$src2, addr:$src1)>; + def : Pat<(X86cmov (loadi32 addr:$src1), GR32:$src2, InvertedCond, EFLAGS), + (Inst32 GR32:$src2, addr:$src1)>; + def : Pat<(X86cmov (loadi64 addr:$src1), GR64:$src2, InvertedCond, EFLAGS), + (Inst64 GR64:$src2, addr:$src1)>; + } } defm : CMOVmr; From 25e0f0f577987046d53a63ab7122775bbc344285 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Sat, 23 Feb 2013 22:50:57 +0000 Subject: [PATCH 0376/1476] sh: If a SIGINT or SIGQUIT interrupts "wait", return status 128+sig. --- bin/sh/eval.c | 2 +- bin/sh/jobs.c | 2 +- bin/sh/main.c | 2 +- bin/sh/trap.c | 35 +++++++++++++----------- bin/sh/trap.h | 2 +- tools/regression/bin/sh/builtins/wait4.0 | 12 ++++++++ tools/regression/bin/sh/builtins/wait5.0 | 12 ++++++++ 7 files changed, 47 insertions(+), 20 deletions(-) create mode 100644 tools/regression/bin/sh/builtins/wait4.0 create mode 100644 tools/regression/bin/sh/builtins/wait5.0 diff --git a/bin/sh/eval.c b/bin/sh/eval.c index b40fffde85a..0972b105a2e 100644 --- a/bin/sh/eval.c +++ b/bin/sh/eval.c @@ -301,7 +301,7 @@ evaltree(union node *n, int flags) } while (n != NULL); out: popstackmark(&smark); - if (pendingsigs) + if (pendingsig) dotrap(); if (eflag && exitstatus != 0 && do_etest) exitshell(exitstatus); diff --git a/bin/sh/jobs.c b/bin/sh/jobs.c index c86394f0d46..5a2790b4ade 100644 --- a/bin/sh/jobs.c +++ b/bin/sh/jobs.c @@ -521,7 +521,7 @@ waitcmd(int argc, char **argv) } while (dowait(DOWAIT_BLOCK | DOWAIT_SIG, (struct job *)NULL) != -1); in_waitcmd--; - return 0; + return pendingsig + 128; } diff --git a/bin/sh/main.c b/bin/sh/main.c index 66e13353295..5dc050ffb70 100644 --- a/bin/sh/main.c +++ b/bin/sh/main.c @@ -196,7 +196,7 @@ cmdloop(int top) TRACE(("cmdloop(%d) called\n", top)); setstackmark(&smark); for (;;) { - if (pendingsigs) + if (pendingsig) dotrap(); inter = 0; if (iflag && top) { diff --git a/bin/sh/trap.c b/bin/sh/trap.c index 521c5110cb3..0a9eb60f5fb 100644 --- a/bin/sh/trap.c +++ b/bin/sh/trap.c @@ -73,7 +73,7 @@ __FBSDID("$FreeBSD$"); MKINIT char sigmode[NSIG]; /* current value of signal */ -int pendingsigs; /* indicates some signal received */ +volatile sig_atomic_t pendingsig; /* indicates some signal received */ int in_dotrap; /* do we execute in a trap handler? */ static char *volatile trap[NSIG]; /* trap handler commands */ static volatile sig_atomic_t gotsig[NSIG]; @@ -388,22 +388,25 @@ onsig(int signo) return; } - if (signo != SIGCHLD || !ignore_sigchld) - gotsig[signo] = 1; - pendingsigs++; - /* If we are currently in a wait builtin, prepare to break it */ - if ((signo == SIGINT || signo == SIGQUIT) && in_waitcmd != 0) - breakwaitcmd = 1; - /* - * If a trap is set, not ignored and not the null command, we need - * to make sure traps are executed even when a child blocks signals. - */ - if (Tflag && - trap[signo] != NULL && - ! (trap[signo][0] == '\0') && - ! (trap[signo][0] == ':' && trap[signo][1] == '\0')) + if ((signo == SIGINT || signo == SIGQUIT) && in_waitcmd != 0) { breakwaitcmd = 1; + pendingsig = signo; + } + + if (trap[signo] != NULL && trap[signo][0] != '\0' && + (signo != SIGCHLD || !ignore_sigchld)) { + gotsig[signo] = 1; + pendingsig = signo; + + /* + * If a trap is set, not ignored and not the null command, we + * need to make sure traps are executed even when a child + * blocks signals. + */ + if (Tflag && !(trap[signo][0] == ':' && trap[signo][1] == '\0')) + breakwaitcmd = 1; + } #ifndef NO_HISTORY if (signo == SIGWINCH) @@ -424,7 +427,7 @@ dotrap(void) in_dotrap++; for (;;) { - pendingsigs = 0; + pendingsig = 0; for (i = 1; i < NSIG; i++) { if (gotsig[i]) { gotsig[i] = 0; diff --git a/bin/sh/trap.h b/bin/sh/trap.h index 61a17ec0517..0a05d8d0ad2 100644 --- a/bin/sh/trap.h +++ b/bin/sh/trap.h @@ -33,7 +33,7 @@ * $FreeBSD$ */ -extern int pendingsigs; +extern volatile sig_atomic_t pendingsig; extern int in_dotrap; extern volatile sig_atomic_t gotwinch; diff --git a/tools/regression/bin/sh/builtins/wait4.0 b/tools/regression/bin/sh/builtins/wait4.0 new file mode 100644 index 00000000000..79351315d38 --- /dev/null +++ b/tools/regression/bin/sh/builtins/wait4.0 @@ -0,0 +1,12 @@ +# $FreeBSD$ + +T=`mktemp -d ${TMPDIR:-/tmp}/sh-test.XXXXXX` +trap 'rm -rf $T' 0 +cd $T || exit 3 +mkfifo fifo1 +trapped= +trap trapped=1 QUIT +{ kill -QUIT $$; sleep 1; exit 4; } >fifo1 & +wait $! fifo1 & +wait Date: Sat, 23 Feb 2013 22:58:04 +0000 Subject: [PATCH 0377/1476] Bump per-device interrupt limit to more reasonable default. Some hardware like DMA and GPIO controllers might require more then 8 interrupts per device instance. Submitted by: Daisuke Aoyama Discussed with: gber@, raj@ --- sys/dev/fdt/fdt_common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/fdt/fdt_common.h b/sys/dev/fdt/fdt_common.h index 68e370830d2..d244a17963b 100644 --- a/sys/dev/fdt/fdt_common.h +++ b/sys/dev/fdt/fdt_common.h @@ -39,7 +39,7 @@ #define FDT_MEM_REGIONS 8 -#define DI_MAX_INTR_NUM 8 +#define DI_MAX_INTR_NUM 32 struct fdt_pci_range { u_long base_pci; From c84251eb7eb6fb1b8092566efa3062f02d7e1657 Mon Sep 17 00:00:00 2001 From: Oleksandr Tymoshenko Date: Sat, 23 Feb 2013 23:22:48 +0000 Subject: [PATCH 0378/1476] - Move dma, sdhci and mbox nodes down in dts in order to get them initialized after FPIO controller since they might rely on GPIO functionality - Update interrupts property of dma node to contain all allocated interrupts --- sys/boot/fdt/dts/bcm2835-rpi-b.dts | 73 ++++++++++++++---------------- 1 file changed, 35 insertions(+), 38 deletions(-) diff --git a/sys/boot/fdt/dts/bcm2835-rpi-b.dts b/sys/boot/fdt/dts/bcm2835-rpi-b.dts index d9357af65d6..80bbef04fbe 100644 --- a/sys/boot/fdt/dts/bcm2835-rpi-b.dts +++ b/sys/boot/fdt/dts/bcm2835-rpi-b.dts @@ -95,27 +95,6 @@ clock-frequency = <1000000>; }; - dma: dma { - compatible = "broadcom,bcm2835-dma", "broadcom,bcm2708-dma"; - reg = <0x7000 0x1000>, <0xE05000 0x1000>; - interrupts = < - 26 /* 2 */ - 27 /* 3 */ - >; - interrupt-parent = <&intc>; - - broadcom,channels = <0>; /* Set by VideoCore */ - }; - - sdhci { - compatible = "broadcom,bcm2835-sdhci", "broadcom,bcm2708-sdhci"; - reg = <0x300000 0x100>; - interrupts = <70>; - interrupt-parent = <&intc>; - - clock-frequency = <50000000>; /* Set by VideoCore */ - }; - armtimer { /* Not AMBA compatible */ compatible = "broadcom,bcm2835-sp804", "arm,sp804"; @@ -124,23 +103,6 @@ interrupt-parent = <&intc>; }; - vc_mbox: mbox { - compatible = "broadcom,bcm2835-mbox", "broadcom,bcm2708-mbox"; - reg = <0xB880 0x40>; - interrupts = <1>; - interrupt-parent = <&intc>; - - /* Channels - * 0: Power - * 1: Frame buffer - * 2: Virtual UART - * 3: VCHIQ - * 4: LEDs - * 5: Buttons - * 6: Touch screen - */ - }; - watchdog0 { compatible = "broadcom,bcm2835-wdt", "broadcom,bcm2708-wdt"; reg = <0x10001c 0x0c>; /* 0x1c, 0x20, 0x24 */ @@ -461,6 +423,41 @@ }; }; + dma: dma { + compatible = "broadcom,bcm2835-dma", "broadcom,bcm2708-dma"; + reg = <0x7000 0x1000>, <0xE05000 0x1000>; + interrupts = <24 25 26 27 28 29 30 31 32 33 34 35 36>; + interrupt-parent = <&intc>; + + broadcom,channels = <0>; /* Set by VideoCore */ + }; + + vc_mbox: mbox { + compatible = "broadcom,bcm2835-mbox", "broadcom,bcm2708-mbox"; + reg = <0xB880 0x40>; + interrupts = <1>; + interrupt-parent = <&intc>; + + /* Channels + * 0: Power + * 1: Frame buffer + * 2: Virtual UART + * 3: VCHIQ + * 4: LEDs + * 5: Buttons + * 6: Touch screen + */ + }; + + sdhci { + compatible = "broadcom,bcm2835-sdhci", "broadcom,bcm2708-sdhci"; + reg = <0x300000 0x100>; + interrupts = <70>; + interrupt-parent = <&intc>; + + clock-frequency = <50000000>; /* Set by VideoCore */ + }; + uart0: uart0 { compatible = "broadcom,bcm2835-uart", "broadcom,bcm2708-uart", "arm,pl011", "arm,primecell"; reg = <0x201000 0x1000>; From ed75b5a156ff71286323bfe9695733d5479d91dc Mon Sep 17 00:00:00 2001 From: Kirk McKusick Date: Sun, 24 Feb 2013 06:44:29 +0000 Subject: [PATCH 0379/1476] When running with the -d option, instrument fsck_ffs to track the number, data type, and running time of its I/O operations. No functional changes. --- sbin/fsck_ffs/dir.c | 2 +- sbin/fsck_ffs/ea.c | 2 +- sbin/fsck_ffs/fsck.h | 38 ++++++++++- sbin/fsck_ffs/fsutil.c | 141 ++++++++++++++++++++++++++++++++++++++--- sbin/fsck_ffs/inode.c | 45 ++++++------- sbin/fsck_ffs/main.c | 8 +++ sbin/fsck_ffs/setup.c | 7 +- 7 files changed, 206 insertions(+), 37 deletions(-) diff --git a/sbin/fsck_ffs/dir.c b/sbin/fsck_ffs/dir.c index 7815fe6f3f5..965e3e39821 100644 --- a/sbin/fsck_ffs/dir.c +++ b/sbin/fsck_ffs/dir.c @@ -708,6 +708,6 @@ getdirblk(ufs2_daddr_t blkno, long size) if (pdirbp != 0) pdirbp->b_flags &= ~B_INUSE; - pdirbp = getdatablk(blkno, size); + pdirbp = getdatablk(blkno, size, BT_DIRDATA); return (pdirbp); } diff --git a/sbin/fsck_ffs/ea.c b/sbin/fsck_ffs/ea.c index c1cf59dd667..35170117a2f 100644 --- a/sbin/fsck_ffs/ea.c +++ b/sbin/fsck_ffs/ea.c @@ -73,7 +73,7 @@ eascan(struct inodesc *idesc, struct ufs2_dinode *dp) else blksiz = sblock.fs_bsize; printf("blksiz = %ju\n", (intmax_t)blksiz); - bp = getdatablk(dp->di_extb[0], blksiz); + bp = getdatablk(dp->di_extb[0], blksiz, BT_EXTATTR); cp = (u_char *)bp->b_un.b_buf; for (n = 0; n < blksiz; n++) { printf("%02x", cp[n]); diff --git a/sbin/fsck_ffs/fsck.h b/sbin/fsck_ffs/fsck.h index dfb2ade37d5..ef98fa24489 100644 --- a/sbin/fsck_ffs/fsck.h +++ b/sbin/fsck_ffs/fsck.h @@ -138,6 +138,7 @@ struct bufarea { int b_size; int b_errs; int b_flags; + int b_type; union { char *b_buf; /* buffer space */ ufs1_daddr_t *b_indir1; /* UFS1 indirect block */ @@ -165,6 +166,36 @@ struct bufarea { * Buffer flags */ #define B_INUSE 0x00000001 /* Buffer is in use */ +/* + * Type of data in buffer + */ +#define BT_UNKNOWN 0 /* Buffer holds a superblock */ +#define BT_SUPERBLK 1 /* Buffer holds a superblock */ +#define BT_CYLGRP 2 /* Buffer holds a cylinder group map */ +#define BT_LEVEL1 3 /* Buffer holds single level indirect */ +#define BT_LEVEL2 4 /* Buffer holds double level indirect */ +#define BT_LEVEL3 5 /* Buffer holds triple level indirect */ +#define BT_EXTATTR 6 /* Buffer holds external attribute data */ +#define BT_INODES 7 /* Buffer holds external attribute data */ +#define BT_DIRDATA 8 /* Buffer holds directory data */ +#define BT_DATA 9 /* Buffer holds user data */ +#define BT_NUMBUFTYPES 10 +#define BT_NAMES { \ + "unknown", \ + "Superblock", \ + "Cylinder Group", \ + "Single Level Indirect", \ + "Double Level Indirect", \ + "Triple Level Indirect", \ + "External Attribute", \ + "Inode Block", \ + "Directory Contents", \ + "User Data" } +long readcnt[BT_NUMBUFTYPES]; +long totalreadcnt[BT_NUMBUFTYPES]; +struct timespec readtime[BT_NUMBUFTYPES]; +struct timespec totalreadtime[BT_NUMBUFTYPES]; +struct timespec startprog; struct bufarea sblk; /* file system superblock */ struct bufarea cgblk; /* cylinder group blocks */ @@ -177,10 +208,11 @@ struct bufarea *pbp; /* current inode block */ else \ (bp)->b_dirty = 1; \ } while (0) -#define initbarea(bp) do { \ +#define initbarea(bp, type) do { \ (bp)->b_dirty = 0; \ (bp)->b_bno = (ufs2_daddr_t)-1; \ (bp)->b_flags = 0; \ + (bp)->b_type = type; \ } while (0) #define sbdirty() dirty(&sblk) @@ -357,6 +389,7 @@ int dirscan(struct inodesc *); int dofix(struct inodesc *, const char *msg); int eascan(struct inodesc *, struct ufs2_dinode *dp); void fileerror(ino_t cwd, ino_t ino, const char *errmesg); +void finalIOstats(void); int findino(struct inodesc *); int findname(struct inodesc *); void flush(int fd, struct bufarea *bp); @@ -365,7 +398,7 @@ void freeino(ino_t ino); void freeinodebuf(void); int ftypeok(union dinode *dp); void getblk(struct bufarea *bp, ufs2_daddr_t blk, long size); -struct bufarea *getdatablk(ufs2_daddr_t blkno, long size); +struct bufarea *getdatablk(ufs2_daddr_t blkno, long size, int type); struct inoinfo *getinoinfo(ino_t inumber); union dinode *getnextinode(ino_t inumber, int rebuildcg); void getpathname(char *namebuf, ino_t curdir, ino_t ino); @@ -375,6 +408,7 @@ void alarmhandler(int sig); void inocleanup(void); void inodirty(void); struct inostat *inoinfo(ino_t inum); +void IOstats(char *what); int linkup(ino_t orphan, ino_t parentdir, char *name); int makeentry(ino_t parent, ino_t ino, const char *name); void panic(const char *fmt, ...) __printflike(1, 2); diff --git a/sbin/fsck_ffs/fsutil.c b/sbin/fsck_ffs/fsutil.c index f3a640af8ee..eef9bdcba80 100644 --- a/sbin/fsck_ffs/fsutil.c +++ b/sbin/fsck_ffs/fsutil.c @@ -56,19 +56,23 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include "fsck.h" static void slowio_start(void); static void slowio_end(void); +static void printIOstats(void); -long diskreads, totalreads; /* Disk cache statistics */ +static long diskreads, totaldiskreads, totalreads; /* Disk cache statistics */ +static struct timespec startpass, finishpass; struct timeval slowio_starttime; int slowio_delay_usec = 10000; /* Initial IO delay for background fsck */ int slowio_pollcnt; static TAILQ_HEAD(buflist, bufarea) bufhead; /* head of buffer cache list */ static int numbufs; /* size of buffer cache */ +static char *buftype[BT_NUMBUFTYPES] = BT_NAMES; int ftypeok(union dinode *dp) @@ -163,7 +167,7 @@ bufinit(void) if (bufp == 0) errx(EEXIT, "cannot allocate buffer pool"); cgblk.b_un.b_buf = bufp; - initbarea(&cgblk); + initbarea(&cgblk, BT_CYLGRP); TAILQ_INIT(&bufhead); bufcnt = MAXBUFS; if (bufcnt < MINBUFS) @@ -178,16 +182,21 @@ bufinit(void) } bp->b_un.b_buf = bufp; TAILQ_INSERT_HEAD(&bufhead, bp, b_list); - initbarea(bp); + initbarea(bp, BT_UNKNOWN); } numbufs = i; /* save number of buffers */ + for (i = 0; i < BT_NUMBUFTYPES; i++) { + readtime[i].tv_sec = totalreadtime[i].tv_sec = 0; + readtime[i].tv_nsec = totalreadtime[i].tv_nsec = 0; + readcnt[i] = totalreadcnt[i] = 0; + } } /* * Manage a cache of directory blocks. */ struct bufarea * -getdatablk(ufs2_daddr_t blkno, long size) +getdatablk(ufs2_daddr_t blkno, long size, int type) { struct bufarea *bp; @@ -199,26 +208,62 @@ getdatablk(ufs2_daddr_t blkno, long size) break; if (bp == NULL) errx(EEXIT, "deadlocked buffer pool"); + bp->b_type = type; getblk(bp, blkno, size); /* fall through */ foundit: + if (debug && bp->b_type != type) + printf("Buffer type changed from %s to %s\n", + buftype[bp->b_type], buftype[type]); TAILQ_REMOVE(&bufhead, bp, b_list); TAILQ_INSERT_HEAD(&bufhead, bp, b_list); bp->b_flags |= B_INUSE; return (bp); } +/* + * Timespec operations (from ). + */ +#define timespecsub(vvp, uvp) \ + do { \ + (vvp)->tv_sec -= (uvp)->tv_sec; \ + (vvp)->tv_nsec -= (uvp)->tv_nsec; \ + if ((vvp)->tv_nsec < 0) { \ + (vvp)->tv_sec--; \ + (vvp)->tv_nsec += 1000000000; \ + } \ + } while (0) +#define timespecadd(vvp, uvp) \ + do { \ + (vvp)->tv_sec += (uvp)->tv_sec; \ + (vvp)->tv_nsec += (uvp)->tv_nsec; \ + if ((vvp)->tv_nsec >= 1000000000) { \ + (vvp)->tv_sec++; \ + (vvp)->tv_nsec -= 1000000000; \ + } \ + } while (0) + void getblk(struct bufarea *bp, ufs2_daddr_t blk, long size) { ufs2_daddr_t dblk; + struct timespec start, finish; - totalreads++; dblk = fsbtodb(&sblock, blk); - if (bp->b_bno != dblk) { + if (bp->b_bno == dblk) { + totalreads++; + } else { flush(fswritefd, bp); - diskreads++; + if (debug) { + readcnt[bp->b_type]++; + clock_gettime(CLOCK_REALTIME_PRECISE, &start); + } bp->b_errs = blread(fsreadfd, bp->b_un.b_buf, dblk, size); + if (debug) { + clock_gettime(CLOCK_REALTIME_PRECISE, &finish); + timespecsub(&finish, &start); + timespecadd(&readtime[bp->b_type], &finish); + } bp->b_bno = dblk; bp->b_size = size; } @@ -292,8 +337,8 @@ ckfini(int markclean) } if (debug && totalreads > 0) printf("cache with %d buffers missed %ld of %ld (%d%%)\n", - numbufs, diskreads, totalreads, - (int)(diskreads * 100 / totalreads)); + numbufs, totaldiskreads, totalreads, + (int)(totaldiskreads * 100 / totalreads)); if (fswritefd < 0) { (void)close(fsreadfd); return; @@ -347,6 +392,82 @@ ckfini(int markclean) (void)close(fswritefd); } +/* + * Print out I/O statistics. + */ +void +IOstats(char *what) +{ + int i; + + if (debug == 0) + return; + if (diskreads == 0) { + printf("%s: no I/O\n\n", what); + return; + } + if (startpass.tv_sec == 0) + startpass = startprog; + printf("%s: I/O statistics\n", what); + printIOstats(); + totaldiskreads += diskreads; + diskreads = 0; + for (i = 0; i < BT_NUMBUFTYPES; i++) { + timespecadd(&totalreadtime[i], &readtime[i]); + totalreadcnt[i] += readcnt[i]; + readtime[i].tv_sec = readtime[i].tv_nsec = 0; + readcnt[i] = 0; + } + clock_gettime(CLOCK_REALTIME_PRECISE, &startpass); +} + +void +finalIOstats(void) +{ + int i; + + if (debug == 0) + return; + printf("Final I/O statistics\n"); + totaldiskreads += diskreads; + diskreads = totaldiskreads; + startpass = startprog; + for (i = 0; i < BT_NUMBUFTYPES; i++) { + timespecadd(&totalreadtime[i], &readtime[i]); + totalreadcnt[i] += readcnt[i]; + readtime[i] = totalreadtime[i]; + readcnt[i] = totalreadcnt[i]; + } + printIOstats(); +} + +static void printIOstats(void) +{ + long long msec, totalmsec; + int i; + + clock_gettime(CLOCK_REALTIME_PRECISE, &finishpass); + timespecsub(&finishpass, &startpass); + printf("Running time: %ld msec\n", + finishpass.tv_sec * 1000 + finishpass.tv_nsec / 1000000); + printf("buffer reads by type:\n"); + for (totalmsec = 0, i = 0; i < BT_NUMBUFTYPES; i++) + totalmsec += readtime[i].tv_sec * 1000 + + readtime[i].tv_nsec / 1000000; + if (totalmsec == 0) + totalmsec = 1; + for (i = 0; i < BT_NUMBUFTYPES; i++) { + if (readcnt[i] == 0) + continue; + msec = readtime[i].tv_sec * 1000 + readtime[i].tv_nsec / 1000000; + printf("%21s:%8ld %2ld.%ld%% %8lld msec %2lld.%lld%%\n", + buftype[i], readcnt[i], readcnt[i] * 100 / diskreads, + (readcnt[i] * 1000 / diskreads) % 10, msec, + msec * 100 / totalmsec, (msec * 1000 / totalmsec) % 10); + } + printf("\n"); +} + int blread(int fd, char *buf, ufs2_daddr_t blk, long size) { @@ -358,6 +479,8 @@ blread(int fd, char *buf, ufs2_daddr_t blk, long size) offset *= dev_bsize; if (bkgrdflag) slowio_start(); + totalreads++; + diskreads++; if (lseek(fd, offset, 0) < 0) rwerror("SEEK BLK", blk); else if (read(fd, buf, (int)size) == size) { diff --git a/sbin/fsck_ffs/inode.c b/sbin/fsck_ffs/inode.c index 389150a3d5f..fd98575f228 100644 --- a/sbin/fsck_ffs/inode.c +++ b/sbin/fsck_ffs/inode.c @@ -52,7 +52,7 @@ __FBSDID("$FreeBSD$"); static ino_t startinum; -static int iblock(struct inodesc *, long ilevel, off_t isize); +static int iblock(struct inodesc *, long ilevel, off_t isize, int type); int ckinode(union dinode *dp, struct inodesc *idesc) @@ -121,7 +121,7 @@ ckinode(union dinode *dp, struct inodesc *idesc) sizepb *= NINDIR(&sblock); if (DIP(&dino, di_ib[i])) { idesc->id_blkno = DIP(&dino, di_ib[i]); - ret = iblock(idesc, i + 1, remsize); + ret = iblock(idesc, i + 1, remsize, BT_LEVEL1 + i); if (ret & STOP) return (ret); } else { @@ -151,7 +151,7 @@ ckinode(union dinode *dp, struct inodesc *idesc) } static int -iblock(struct inodesc *idesc, long ilevel, off_t isize) +iblock(struct inodesc *idesc, long ilevel, off_t isize, int type) { struct bufarea *bp; int i, n, (*func)(struct inodesc *), nif; @@ -168,7 +168,7 @@ iblock(struct inodesc *idesc, long ilevel, off_t isize) func = dirscan; if (chkrange(idesc->id_blkno, idesc->id_numfrags)) return (SKIP); - bp = getdatablk(idesc->id_blkno, sblock.fs_bsize); + bp = getdatablk(idesc->id_blkno, sblock.fs_bsize, type); ilevel--; for (sizepb = sblock.fs_bsize, i = 0; i < ilevel; i++) sizepb *= NINDIR(&sblock); @@ -199,7 +199,7 @@ iblock(struct inodesc *idesc, long ilevel, off_t isize) if (ilevel == 0) n = (*func)(idesc); else - n = iblock(idesc, ilevel, isize); + n = iblock(idesc, ilevel, isize, type); if (n & STOP) { bp->b_flags &= ~B_INUSE; return (n); @@ -292,7 +292,7 @@ ginode(ino_t inumber) iblk = ino_to_fsba(&sblock, inumber); if (pbp != 0) pbp->b_flags &= ~B_INUSE; - pbp = getdatablk(iblk, sblock.fs_bsize); + pbp = getdatablk(iblk, sblock.fs_bsize, BT_INODES); startinum = (inumber / INOPB(&sblock)) * INOPB(&sblock); } if (sblock.fs_magic == FS_UFS1_MAGIC) @@ -306,8 +306,8 @@ ginode(ino_t inumber) * over all the inodes in numerical order. */ static ino_t nextino, lastinum, lastvalidinum; -static long readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize; -static caddr_t inodebuf; +static long readcount, readpercg, fullcnt, inobufsize, partialcnt, partialsize; +static struct bufarea inobuf; union dinode * getnextinode(ino_t inumber, int rebuildcg) @@ -315,7 +315,7 @@ getnextinode(ino_t inumber, int rebuildcg) int j; long size; mode_t mode; - ufs2_daddr_t ndb, dblk; + ufs2_daddr_t ndb, blk; union dinode *dp; static caddr_t nextinop; @@ -323,9 +323,9 @@ getnextinode(ino_t inumber, int rebuildcg) errx(EEXIT, "bad inode number %ju to nextinode", (uintmax_t)inumber); if (inumber >= lastinum) { - readcnt++; - dblk = fsbtodb(&sblock, ino_to_fsba(&sblock, lastinum)); - if (readcnt % readpercg == 0) { + readcount++; + blk = ino_to_fsba(&sblock, lastinum); + if (readcount % readpercg == 0) { size = partialsize; lastinum += partialcnt; } else { @@ -333,14 +333,14 @@ getnextinode(ino_t inumber, int rebuildcg) lastinum += fullcnt; } /* - * If blread returns an error, it will already have zeroed + * If getblk encounters an error, it will already have zeroed * out the buffer, so we do not need to do so here. */ - (void)blread(fsreadfd, inodebuf, dblk, size); - nextinop = inodebuf; + getblk(&inobuf, blk, size); + nextinop = inobuf.b_un.b_buf; } dp = (union dinode *)nextinop; - if (rebuildcg && nextinop == inodebuf) { + if (rebuildcg && nextinop == inobuf.b_un.b_buf) { /* * Try to determine if we have reached the end of the * allocated inodes. @@ -406,8 +406,8 @@ setinodebuf(ino_t inum) startinum = 0; nextino = inum; lastinum = inum; - readcnt = 0; - if (inodebuf != NULL) + readcount = 0; + if (inobuf.b_un.b_buf != NULL) return; inobufsize = blkroundup(&sblock, INOBUFSIZE); fullcnt = inobufsize / ((sblock.fs_magic == FS_UFS1_MAGIC) ? @@ -422,7 +422,8 @@ setinodebuf(ino_t inum) partialcnt = fullcnt; partialsize = inobufsize; } - if ((inodebuf = malloc((unsigned)inobufsize)) == NULL) + initbarea(&inobuf, BT_INODES); + if ((inobuf.b_un.b_buf = malloc((unsigned)inobufsize)) == NULL) errx(EEXIT, "cannot allocate space for inode buffer"); } @@ -430,9 +431,9 @@ void freeinodebuf(void) { - if (inodebuf != NULL) - free((char *)inodebuf); - inodebuf = NULL; + if (inobuf.b_un.b_buf != NULL) + free((char *)inobuf.b_un.b_buf); + inobuf.b_un.b_buf = NULL; } /* diff --git a/sbin/fsck_ffs/main.c b/sbin/fsck_ffs/main.c index 69f157ab195..27f17dbba05 100644 --- a/sbin/fsck_ffs/main.c +++ b/sbin/fsck_ffs/main.c @@ -424,7 +424,9 @@ checkfilesys(char *filesys) printf("** Root file system\n"); printf("** Phase 1 - Check Blocks and Sizes\n"); } + clock_gettime(CLOCK_REALTIME_PRECISE, &startprog); pass1(); + IOstats("Pass1"); /* * 1b: locate first references to duplicates, if any @@ -437,6 +439,7 @@ checkfilesys(char *filesys) usedsoftdep ? "softupdates" : ""); printf("** Phase 1b - Rescan For More DUPS\n"); pass1b(); + IOstats("Pass1b"); } /* @@ -445,6 +448,7 @@ checkfilesys(char *filesys) if (preen == 0) printf("** Phase 2 - Check Pathnames\n"); pass2(); + IOstats("Pass2"); /* * 3: scan inodes looking for disconnected directories @@ -452,6 +456,7 @@ checkfilesys(char *filesys) if (preen == 0) printf("** Phase 3 - Check Connectivity\n"); pass3(); + IOstats("Pass3"); /* * 4: scan inodes looking for disconnected files; check reference counts @@ -459,6 +464,7 @@ checkfilesys(char *filesys) if (preen == 0) printf("** Phase 4 - Check Reference Counts\n"); pass4(); + IOstats("Pass4"); /* * 5: check and repair resource counts in cylinder groups @@ -466,6 +472,7 @@ checkfilesys(char *filesys) if (preen == 0) printf("** Phase 5 - Check Cyl groups\n"); pass5(); + IOstats("Pass5"); /* * print out summary statistics @@ -519,6 +526,7 @@ checkfilesys(char *filesys) } if (rerun) resolved = 0; + finalIOstats(); /* * Check to see if the file system is mounted read-write. diff --git a/sbin/fsck_ffs/setup.c b/sbin/fsck_ffs/setup.c index ae0ea0519e4..32abeed0c53 100644 --- a/sbin/fsck_ffs/setup.c +++ b/sbin/fsck_ffs/setup.c @@ -249,6 +249,7 @@ setup(char *dev) for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { size = sblock.fs_cssize - i < sblock.fs_bsize ? sblock.fs_cssize - i : sblock.fs_bsize; + readcnt[sblk.b_type]++; if (blread(fsreadfd, (char *)sblock.fs_csp + i, fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag), size) != 0 && !asked) { @@ -322,6 +323,7 @@ readsb(int listerr) if (bflag) { super = bflag; + readcnt[sblk.b_type]++; if ((blread(fsreadfd, (char *)&sblock, super, (long)SBLOCKSIZE))) return (0); if (sblock.fs_magic == FS_BAD_MAGIC) { @@ -337,6 +339,7 @@ readsb(int listerr) } else { for (i = 0; sblock_try[i] != -1; i++) { super = sblock_try[i] / dev_bsize; + readcnt[sblk.b_type]++; if ((blread(fsreadfd, (char *)&sblock, super, (long)SBLOCKSIZE))) return (0); @@ -439,8 +442,8 @@ sblock_init(void) fswritefd = -1; fsmodified = 0; lfdir = 0; - initbarea(&sblk); - initbarea(&asblk); + initbarea(&sblk, BT_SUPERBLK); + initbarea(&asblk, BT_SUPERBLK); sblk.b_un.b_buf = malloc(SBLOCKSIZE); asblk.b_un.b_buf = malloc(SBLOCKSIZE); if (sblk.b_un.b_buf == NULL || asblk.b_un.b_buf == NULL) From a25349736dac12e2b5e36bf4bbe46df16ccb1c1a Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Sun, 24 Feb 2013 15:15:50 +0000 Subject: [PATCH 0380/1476] Merge part of r1712 from elftoolchain, making it possible to resize ELF sections and indirectly change the layout of an ELF file when ELF_F_LAYOUT is not set. PR: bin/167103 Approved by: rstone (co-mentor) Obtained from: elftoolchain MFC after: 2 weeks --- lib/libelf/elf_update.c | 314 +++++++++++++++++++++++----------------- 1 file changed, 184 insertions(+), 130 deletions(-) diff --git a/lib/libelf/elf_update.c b/lib/libelf/elf_update.c index 5880c07aadd..813d2bcbfd6 100644 --- a/lib/libelf/elf_update.c +++ b/lib/libelf/elf_update.c @@ -41,89 +41,79 @@ __FBSDID("$FreeBSD$"); #include "_libelf.h" /* - * Update the internal data structures associated with an ELF object. - * Returns the size in bytes the ELF object would occupy in its file - * representation. + * Layout strategy: * - * After a successful call to this function, the following structures - * are updated: + * - Case 1: ELF_F_LAYOUT is asserted + * In this case the application has full control over where the + * section header table, program header table, and section data + * will reside. The library only perform error checks. * - * - The ELF header is updated. - * - All sections are sorted in order of ascending addresses and their - * section header table entries updated. An error is signalled - * if an overlap was detected among sections. - * - All data descriptors associated with a section are sorted in order - * of ascending addresses. Overlaps, if detected, are signalled as - * errors. Other sanity checks for alignments, section types etc. are - * made. + * - Case 2: ELF_F_LAYOUT is not asserted * - * After a resync_elf() successfully returns, the ELF descriptor is - * ready for being handed over to _libelf_write_elf(). + * The library will do the object layout using the following + * ordering: + * - The executable header is placed first, are required by the + * ELF specification. + * - The program header table is placed immediately following the + * executable header. + * - Section data, if any, is placed after the program header + * table, aligned appropriately. + * - The section header table, if needed, is placed last. * - * File alignments: - * PHDR - Addr - * SHDR - Addr + * There are two sub-cases to be taken care of: * - * XXX: how do we handle 'flags'. + * - Case 2a: e->e_cmd == ELF_C_READ or ELF_C_RDWR + * + * In this sub-case, the underlying ELF object may already have + * content in it, which the application may have modified. The + * library will retrieve content from the existing object as + * needed. + * + * - Case 2b: e->e_cmd == ELF_C_WRITE + * + * The ELF object is being created afresh in this sub-case; + * there is no pre-existing content in the underlying ELF + * object. */ /* * Compute the extents of a section, by looking at the data - * descriptors associated with it. The function returns zero if an - * error was detected. `*rc' holds the maximum file extent seen so - * far. + * descriptors associated with it. The function returns 1 if + * successful, or zero if an error was detected. */ static int -_libelf_compute_section_extents(Elf *e, Elf_Scn *s, off_t *rc) +_libelf_compute_section_extents(Elf *e, Elf_Scn *s, off_t rc) { int ec; - Elf_Data *d, *td; + size_t fsz, msz; + Elf_Data *d; + Elf32_Shdr *shdr32; + Elf64_Shdr *shdr64; unsigned int elftype; uint32_t sh_type; uint64_t d_align; uint64_t sh_align, sh_entsize, sh_offset, sh_size; uint64_t scn_size, scn_alignment; - /* - * We need to recompute library private data structures if one - * or more of the following is true: - * - The underlying Shdr structure has been marked `dirty'. Significant - * fields include: `sh_offset', `sh_type', `sh_size', `sh_addralign'. - * - The Elf_Data structures part of this section have been marked - * `dirty'. Affected members include `d_align', `d_offset', `d_type', - * and `d_size'. - * - The section as a whole is `dirty', e.g., it has been allocated - * using elf_newscn(), or if a new Elf_Data structure was added using - * elf_newdata(). - * - * Each of these conditions would result in the ELF_F_DIRTY bit being - * set on the section descriptor's `s_flags' field. - */ - ec = e->e_class; + shdr32 = &s->s_shdr.s_shdr32; + shdr64 = &s->s_shdr.s_shdr64; if (ec == ELFCLASS32) { - sh_type = s->s_shdr.s_shdr32.sh_type; - sh_align = (uint64_t) s->s_shdr.s_shdr32.sh_addralign; - sh_entsize = (uint64_t) s->s_shdr.s_shdr32.sh_entsize; - sh_offset = (uint64_t) s->s_shdr.s_shdr32.sh_offset; - sh_size = (uint64_t) s->s_shdr.s_shdr32.sh_size; + sh_type = shdr32->sh_type; + sh_align = (uint64_t) shdr32->sh_addralign; + sh_entsize = (uint64_t) shdr32->sh_entsize; + sh_offset = (uint64_t) shdr32->sh_offset; + sh_size = (uint64_t) shdr32->sh_size; } else { - sh_type = s->s_shdr.s_shdr64.sh_type; - sh_align = s->s_shdr.s_shdr64.sh_addralign; - sh_entsize = s->s_shdr.s_shdr64.sh_entsize; - sh_offset = s->s_shdr.s_shdr64.sh_offset; - sh_size = s->s_shdr.s_shdr64.sh_size; + sh_type = shdr64->sh_type; + sh_align = shdr64->sh_addralign; + sh_entsize = shdr64->sh_entsize; + sh_offset = shdr64->sh_offset; + sh_size = shdr64->sh_size; } - if (sh_type == SHT_NULL || sh_type == SHT_NOBITS) - return (1); - - if ((s->s_flags & ELF_F_DIRTY) == 0) { - if ((size_t) *rc < sh_offset + sh_size) - *rc = sh_offset + sh_size; - return (1); - } + assert(sh_type != SHT_NULL && sh_type != SHT_NOBITS); elftype = _libelf_xlate_shtype(sh_type); if (elftype > ELF_T_LAST) { @@ -131,15 +121,52 @@ _libelf_compute_section_extents(Elf *e, Elf_Scn *s, off_t *rc) return (0); } - /* - * Compute the extent of the data descriptors associated with - * this section. - */ - scn_alignment = 0; if (sh_align == 0) sh_align = _libelf_falign(elftype, ec); - /* Compute the section alignment. */ + /* + * Check the section's data buffers for sanity and compute the + * section's alignment. + * Compute the section's size and alignment using the data + * descriptors associated with the section. + */ + if (STAILQ_EMPTY(&s->s_data)) { + /* + * The section's content (if any) has not been read in + * yet. If section is not dirty marked dirty, we can + * reuse the values in the 'sh_size' and 'sh_offset' + * fields of the section header. + */ + if ((s->s_flags & ELF_F_DIRTY) == 0) { + /* + * If the library is doing the layout, then we + * compute the new start offset for the + * section based on the current offset and the + * section's alignment needs. + * + * If the application is doing the layout, we + * can use the value in the 'sh_offset' field + * in the section header directly. + */ + if (e->e_flags & ELF_F_LAYOUT) + goto updatedescriptor; + else + goto computeoffset; + } + + /* + * Otherwise, we need to bring in the section's data + * from the underlying ELF object. + */ + if (e->e_cmd != ELF_C_WRITE && elf_getdata(s, NULL) == NULL) + return (0); + } + + /* + * Loop through the section's data descriptors. + */ + scn_size = 0L; + scn_alignment = 0L; STAILQ_FOREACH(d, &s->s_data, d_next) { if (d->d_type > ELF_T_LAST) { LIBELF_SET_ERROR(DATA, 0); @@ -153,23 +180,40 @@ _libelf_compute_section_extents(Elf *e, Elf_Scn *s, off_t *rc) LIBELF_SET_ERROR(DATA, 0); return (0); } - if (d_align > scn_alignment) - scn_alignment = d_align; - } - scn_size = 0L; + /* + * The buffer's size should be a multiple of the + * memory size of the underlying type. + */ + msz = _libelf_msize(d->d_type, ec, e->e_version); + if (d->d_size % msz) { + LIBELF_SET_ERROR(DATA, 0); + return (0); + } - STAILQ_FOREACH_SAFE(d, &s->s_data, d_next, td) { + /* + * Compute the section's size. + */ if (e->e_flags & ELF_F_LAYOUT) { if ((uint64_t) d->d_off + d->d_size > scn_size) scn_size = d->d_off + d->d_size; } else { scn_size = roundup2(scn_size, d->d_align); d->d_off = scn_size; - scn_size += d->d_size; + fsz = _libelf_fsize(d->d_type, ec, d->d_version, + d->d_size / msz); + scn_size += fsz; } + + /* + * The section's alignment is the maximum alignment + * needed for its data buffers. + */ + if (d_align > scn_alignment) + scn_alignment = d_align; } + /* * If the application is requesting full control over the layout * of the section, check its values for sanity. @@ -180,46 +224,60 @@ _libelf_compute_section_extents(Elf *e, Elf_Scn *s, off_t *rc) LIBELF_SET_ERROR(LAYOUT, 0); return (0); } - } else { - /* - * Otherwise compute the values in the section header. - */ - - if (scn_alignment > sh_align) - sh_align = scn_alignment; - - /* - * If the section entry size is zero, try and fill in an - * appropriate entry size. Per the elf(5) manual page - * sections without fixed-size entries should have their - * 'sh_entsize' field set to zero. - */ - if (sh_entsize == 0 && - (sh_entsize = _libelf_fsize(elftype, ec, e->e_version, - (size_t) 1)) == 1) - sh_entsize = 0; - - sh_size = scn_size; - sh_offset = roundup(*rc, sh_align); - - if (ec == ELFCLASS32) { - s->s_shdr.s_shdr32.sh_addralign = (uint32_t) sh_align; - s->s_shdr.s_shdr32.sh_entsize = (uint32_t) sh_entsize; - s->s_shdr.s_shdr32.sh_offset = (uint32_t) sh_offset; - s->s_shdr.s_shdr32.sh_size = (uint32_t) sh_size; - } else { - s->s_shdr.s_shdr64.sh_addralign = sh_align; - s->s_shdr.s_shdr64.sh_entsize = sh_entsize; - s->s_shdr.s_shdr64.sh_offset = sh_offset; - s->s_shdr.s_shdr64.sh_size = sh_size; - } + goto updatedescriptor; } - if ((size_t) *rc < sh_offset + sh_size) - *rc = sh_offset + sh_size; + /* + * Otherwise compute the values in the section header. + * + * The section alignment is the maximum alignment for any of + * its contained data descriptors. + */ + if (scn_alignment > sh_align) + sh_align = scn_alignment; + /* + * If the section entry size is zero, try and fill in an + * appropriate entry size. Per the elf(5) manual page + * sections without fixed-size entries should have their + * 'sh_entsize' field set to zero. + */ + if (sh_entsize == 0 && + (sh_entsize = _libelf_fsize(elftype, ec, e->e_version, + (size_t) 1)) == 1) + sh_entsize = 0; + + sh_size = scn_size; + +computeoffset: + /* + * Compute the new offset for the section based on + * the section's alignment needs. + */ + sh_offset = roundup(rc, sh_align); + + /* + * Update the section header. + */ + if (ec == ELFCLASS32) { + shdr32->sh_addralign = (uint32_t) sh_align; + shdr32->sh_entsize = (uint32_t) sh_entsize; + shdr32->sh_offset = (uint32_t) sh_offset; + shdr32->sh_size = (uint32_t) sh_size; + } else { + shdr64->sh_addralign = sh_align; + shdr64->sh_entsize = sh_entsize; + shdr64->sh_offset = sh_offset; + shdr64->sh_size = sh_size; + } + +updatedescriptor: + /* + * Update the section descriptor. + */ s->s_size = sh_size; s->s_offset = sh_offset; + return (1); } @@ -267,13 +325,16 @@ _libelf_insert_section(Elf *e, Elf_Scn *s) return (1); } +/* + * Recompute section layout. + */ + static off_t _libelf_resync_sections(Elf *e, off_t rc) { int ec; - off_t nrc; + Elf_Scn *s; size_t sh_type, shdr_start, shdr_end; - Elf_Scn *s, *ts; ec = e->e_class; @@ -281,13 +342,7 @@ _libelf_resync_sections(Elf *e, off_t rc) * Make a pass through sections, computing the extent of each * section. Order in increasing order of addresses. */ - - nrc = rc; - STAILQ_FOREACH(s, &e->e_u.e_elf.e_scn, s_next) - if (_libelf_compute_section_extents(e, s, &nrc) == 0) - return ((off_t) -1); - - STAILQ_FOREACH_SAFE(s, &e->e_u.e_elf.e_scn, s_next, ts) { + STAILQ_FOREACH(s, &e->e_u.e_elf.e_scn, s_next) { if (ec == ELFCLASS32) sh_type = s->s_shdr.s_shdr32.sh_type; else @@ -296,21 +351,22 @@ _libelf_resync_sections(Elf *e, off_t rc) if (sh_type == SHT_NOBITS || sh_type == SHT_NULL) continue; - if (s->s_offset < (uint64_t) rc) { - if (s->s_offset + s->s_size < (uint64_t) rc) { - /* - * Try insert this section in the - * correct place in the list, - * detecting overlaps if any. - */ - STAILQ_REMOVE(&e->e_u.e_elf.e_scn, s, _Elf_Scn, - s_next); - if (_libelf_insert_section(e, s) == 0) - return ((off_t) -1); - } else { - LIBELF_SET_ERROR(LAYOUT, 0); + if (_libelf_compute_section_extents(e, s, rc) == 0) + return ((off_t) -1); + + if (s->s_size == 0) + continue; + + if (s->s_offset + s->s_size < (size_t) rc) { + /* + * Try insert this section in the + * correct place in the list, + * detecting overlaps if any. + */ + STAILQ_REMOVE(&e->e_u.e_elf.e_scn, s, _Elf_Scn, + s_next); + if (_libelf_insert_section(e, s) == 0) return ((off_t) -1); - } } else rc = s->s_offset + s->s_size; } @@ -338,8 +394,6 @@ _libelf_resync_sections(Elf *e, off_t rc) } } - assert(nrc == rc); - return (rc); } From 3dfcb0da4b00ce7410a53670da8816b7353398ee Mon Sep 17 00:00:00 2001 From: Sergey Kandaurov Date: Sun, 24 Feb 2013 19:32:43 +0000 Subject: [PATCH 0381/1476] Catch up with internal API changes for initbarea() and getdatablk() of fsck_ffs introduced with r247212. Submitted by: David Wolfskill --- sbin/fsdb/fsdbutil.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sbin/fsdb/fsdbutil.c b/sbin/fsdb/fsdbutil.c index 91153d77f20..ba0b64e7280 100644 --- a/sbin/fsdb/fsdbutil.c +++ b/sbin/fsdb/fsdbutil.c @@ -239,11 +239,11 @@ printindir(ufs2_daddr_t blk, int level, char *bufp) /* for the final indirect level, don't use the cache */ bp = &buf; bp->b_un.b_buf = bufp; - initbarea(bp); + initbarea(bp, BT_UNKNOWN); getblk(bp, blk, sblock.fs_bsize); } else - bp = getdatablk(blk, sblock.fs_bsize); + bp = getdatablk(blk, sblock.fs_bsize, BT_UNKNOWN); cpl = charsperline(); for (i = charssofar = 0; i < NINDIR(&sblock); i++) { From c6344d08bb53304e1a495237ada5fdc1e0800d71 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Sun, 24 Feb 2013 20:53:32 +0000 Subject: [PATCH 0382/1476] libc/opendir: Improve behaviour of union uniquifier: * Reopen the directory using openat(fd, ".", ...) instead of opening the pathname again. This fixes a race condition where the meaning of the pathname changes and allows a reopen with fdopendir(). * Always reopen the directory for union stacks, not only when DTF_REWIND is passed. Applications should be able to fchdir(dirfd(dir)) and *at(dirfd(dir), ...). DTF_REWIND now does nothing. --- lib/libc/gen/opendir.c | 51 +++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/lib/libc/gen/opendir.c b/lib/libc/gen/opendir.c index 2d505fc4789..a9eb0af1ba4 100644 --- a/lib/libc/gen/opendir.c +++ b/lib/libc/gen/opendir.c @@ -49,7 +49,7 @@ __FBSDID("$FreeBSD$"); #include "gen-private.h" #include "telldir.h" -static DIR * __opendir_common(int, const char *, int); +static DIR * __opendir_common(int, int); /* * Open a directory. @@ -78,7 +78,7 @@ fdopendir(int fd) } if (_fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) return (NULL); - return (__opendir_common(fd, NULL, DTF_HIDEW|DTF_NODUP)); + return (__opendir_common(fd, DTF_HIDEW|DTF_NODUP)); } DIR * @@ -92,7 +92,7 @@ __opendir2(const char *name, int flags) O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC)) == -1) return (NULL); - dir = __opendir_common(fd, name, flags); + dir = __opendir_common(fd, flags); if (dir == NULL) { saved_errno = errno; _close(fd); @@ -113,7 +113,7 @@ opendir_compar(const void *p1, const void *p2) * Common routine for opendir(3), __opendir2(3) and fdopendir(3). */ static DIR * -__opendir_common(int fd, const char *name, int flags) +__opendir_common(int fd, int flags) { DIR *dirp; int incr; @@ -121,6 +121,8 @@ __opendir_common(int fd, const char *name, int flags) int unionstack; int fd2; + fd2 = -1; + if ((dirp = malloc(sizeof(DIR) + sizeof(struct _telldir))) == NULL) return (NULL); @@ -165,7 +167,22 @@ __opendir_common(int fd, const char *name, int flags) * entries into a buffer, sort the buffer, and * remove duplicate entries by setting the inode * number to zero. + * + * We reopen the directory because _getdirentries() + * on a MNT_UNION mount modifies the open directory, + * making it refer to the lower directory after the + * upper directory's entries are exhausted. + * This would otherwise break software that uses + * the directory descriptor for fchdir or *at + * functions, such as fts.c. */ + if ((fd2 = _openat(fd, ".", O_RDONLY | O_CLOEXEC)) == -1) { + saved_errno = errno; + free(buf); + free(dirp); + errno = saved_errno; + return (NULL); + } do { /* @@ -181,7 +198,7 @@ __opendir_common(int fd, const char *name, int flags) ddptr = buf + (len - space); } - n = _getdirentries(fd, ddptr, space, &dirp->dd_seek); + n = _getdirentries(fd2, ddptr, space, &dirp->dd_seek); if (n > 0) { ddptr += n; space -= n; @@ -191,25 +208,8 @@ __opendir_common(int fd, const char *name, int flags) ddeptr = ddptr; flags |= __DTF_READALL; - /* - * Re-open the directory. - * This has the effect of rewinding back to the - * top of the union stack and is needed by - * programs which plan to fchdir to a descriptor - * which has also been read -- see fts.c. - */ - if (flags & DTF_REWIND) { - if ((fd2 = _open(name, O_RDONLY | O_DIRECTORY | - O_CLOEXEC)) == -1) { - saved_errno = errno; - free(buf); - free(dirp); - errno = saved_errno; - return (NULL); - } - (void)_dup2(fd2, fd); - _close(fd2); - } + _close(fd2); + fd2 = -1; /* * There is now a buffer full of (possibly) duplicate @@ -293,7 +293,6 @@ __opendir_common(int fd, const char *name, int flags) if (dirp->dd_buf == NULL) goto fail; dirp->dd_seek = 0; - flags &= ~DTF_REWIND; } dirp->dd_loc = 0; @@ -310,6 +309,8 @@ __opendir_common(int fd, const char *name, int flags) fail: saved_errno = errno; + if (fd2 != -1) + _close(fd2); free(dirp); errno = saved_errno; return (NULL); From 6d4a620ebafd7e013a14fc0189399d0b6ae7a901 Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Mon, 25 Feb 2013 01:50:04 +0000 Subject: [PATCH 0383/1476] Fix the bug I introduced in r247045. After digging through more carefully, it looks like there's no real need to have the DTB in the module directory. So we can simplify a lot: Just copy DTB into local heap for "fdt addr" and U-Boot integration, drop all the extra COPYIN() calls. I've left one final COPYIN() to update the in-kernel DTB for consistency with how this code used to work, but I'm no longer convinced it's appropriate here. I've also remove the mem_load_raw() utility that I added to boot/common/module.c with r247045 since it's no longer necessary. --- sys/boot/common/bootstrap.h | 2 -- sys/boot/common/module.c | 36 ---------------------- sys/boot/fdt/fdt_loader_cmd.c | 58 ++++++++++++++++++----------------- 3 files changed, 30 insertions(+), 66 deletions(-) diff --git a/sys/boot/common/bootstrap.h b/sys/boot/common/bootstrap.h index 78b3895b71c..516b8a58646 100644 --- a/sys/boot/common/bootstrap.h +++ b/sys/boot/common/bootstrap.h @@ -237,8 +237,6 @@ void file_discard(struct preloaded_file *fp); void file_addmetadata(struct preloaded_file *fp, int type, size_t size, void *p); int file_addmodule(struct preloaded_file *fp, char *modname, int version, struct kernel_module **newmp); -/* Load from a buffer in memory. */ -struct preloaded_file *mem_load_raw(char *type, char *name, const void *p, size_t len); /* MI module loaders */ #ifdef __elfN diff --git a/sys/boot/common/module.c b/sys/boot/common/module.c index 3b74ab7856e..58085875a29 100644 --- a/sys/boot/common/module.c +++ b/sys/boot/common/module.c @@ -421,42 +421,6 @@ file_loadraw(char *type, char *name) return(CMD_OK); } -/* - * Load a chunk of data as if it had been read from a file. - */ -struct preloaded_file * -mem_load_raw(char *type, char *name, const void *p, size_t len) -{ - struct preloaded_file *fp; - - /* We can't load first */ - if ((file_findfile(NULL, NULL)) == NULL) { - command_errmsg = "can't load file before kernel"; - return(NULL); - } - - if (archsw.arch_loadaddr != NULL) - loadaddr = archsw.arch_loadaddr(LOAD_RAW, name, loadaddr); - archsw.arch_copyin(p, loadaddr, len); - - /* Looks OK so far; create & populate control structure */ - fp = file_alloc(); - fp->f_name = strdup(name); - fp->f_type = strdup(type); - fp->f_args = NULL; - fp->f_metadata = NULL; - fp->f_loader = -1; - fp->f_addr = loadaddr; - fp->f_size = len; - - /* recognise space consumption */ - loadaddr += len; - - /* Add to the list of loaded files */ - file_insert_tail(fp); - return fp; -} - /* * Load the module (name), pass it (argc),(argv), add container file * to the list of loaded files. diff --git a/sys/boot/fdt/fdt_loader_cmd.c b/sys/boot/fdt/fdt_loader_cmd.c index 0417c52e01e..1d65fe74221 100644 --- a/sys/boot/fdt/fdt_loader_cmd.c +++ b/sys/boot/fdt/fdt_loader_cmd.c @@ -63,12 +63,16 @@ __FBSDID("$FreeBSD$"); #define CMD_REQUIRES_BLOB 0x01 /* Location of FDT yet to be loaded. */ +/* This may be in read-only memory, so can't be manipulated directly. */ static struct fdt_header *fdt_to_load = NULL; -/* Local copy of FDT on heap. */ +/* Location of FDT on heap. */ +/* This is the copy we actually manipulate. */ static struct fdt_header *fdtp = NULL; /* Size of FDT blob */ static size_t fdtp_size = 0; -/* Location of FDT in kernel or module */ +/* Location of FDT in kernel or module. */ +/* This won't be set if FDT is loaded from disk or memory. */ +/* If it is set, we'll update it when fdt_copy() gets called. */ static vm_offset_t fdtp_va = 0; static int fdt_load_dtb(vm_offset_t va); @@ -191,7 +195,6 @@ fdt_find_static_dtb() fdt_start = (vm_offset_t)sym.st_value + offs; free(strp); } - printf("fdt_start: 0x%08jX\n", (intmax_t)fdt_start); return (fdt_start); } @@ -239,14 +242,19 @@ fdt_load_dtb(vm_offset_t va) static int fdt_load_dtb_addr(struct fdt_header *header) { - struct preloaded_file *bfp; - bfp = mem_load_raw("dtb", "memory.dtb", header, fdt_totalsize(header)); - if (bfp == NULL) { - command_errmsg = "unable to copy DTB into module directory"; + // TODO: Verify that there really is an FDT at + // the specified location. + fdtp_size = fdt_totalsize(header); + free(fdtp); + if ((fdtp = malloc(fdtp_size)) == NULL) { + command_errmsg = "can't allocate memory for device tree copy"; return (1); } - return fdt_load_dtb(bfp->f_addr); + + fdtp_va = 0; // Don't write this back into module or kernel. + bcopy(header, fdtp, fdtp_size); + return (0); } static int @@ -339,7 +347,7 @@ _fdt_strtovect(char *str, void *cellbuf, int lim, unsigned char cellsize, #define TMP_MAX_ETH 8 -void +static void fixup_ethernet(const char *env, char *ethstr, int *eth_no, int len) { char *end, *str; @@ -376,7 +384,7 @@ fixup_ethernet(const char *env, char *ethstr, int *eth_no, int len) *eth_no = n + 1; } -void +static void fixup_cpubusfreqs(unsigned long cpufreq, unsigned long busfreq) { int lo, o = 0, o2, maxo = 0, depth; @@ -424,7 +432,7 @@ fixup_cpubusfreqs(unsigned long cpufreq, unsigned long busfreq) } } -int +static int fdt_reg_valid(uint32_t *reg, int len, int addr_cells, int size_cells) { int cells_in_tuple, i, tuples, tuple_size; @@ -456,7 +464,7 @@ fdt_reg_valid(uint32_t *reg, int len, int addr_cells, int size_cells) return (0); } -void +static void fixup_memory(struct sys_info *si) { struct mem_region *curmr; @@ -611,7 +619,7 @@ fixup_memory(struct sys_info *si) free(sb); } -void +static void fixup_stdout(const char *env) { const char *str; @@ -664,7 +672,7 @@ fixup_stdout(const char *env) /* * Locate the blob, fix it up and return its location. */ -static vm_offset_t +static int fdt_fixup(void) { const char *env; @@ -692,7 +700,7 @@ fdt_fixup(void) /* Value assigned to fixup-applied does not matter. */ if (fdt_getprop(fdtp, chosen, "fixup-applied", NULL)) - goto success; + return (1); /* Acquire sys_info */ si = ub_get_sys_info(); @@ -735,15 +743,11 @@ fdt_fixup(void) fixup_memory(si); fdt_setprop(fdtp, chosen, "fixup-applied", NULL, 0); - -success: - /* Overwrite the FDT with the fixed version. */ - COPYIN(fdtp, fdtp_va, fdtp_size); - return (fdtp_va); + return (1); } /* - * Copy DTB blob to specified location and its return size + * Copy DTB blob to specified location and return size */ int fdt_copy(vm_offset_t va) @@ -761,6 +765,11 @@ fdt_copy(vm_offset_t va) if (fdt_fixup() == 0) return (0); + if (fdtp_va != 0) { + /* Overwrite the FDT with the fixed version. */ + /* XXX Is this really appropriate? */ + COPYIN(fdtp, fdtp_va, fdtp_size); + } COPYIN(fdtp, va, fdtp_size); return (fdtp_size); } @@ -1334,8 +1343,6 @@ fdt_modprop(int nodeoff, char *propname, void *value, char mode) else sprintf(command_errbuf, "Could not add/modify property!\n"); - } else { - COPYIN(fdtp, fdtp_va, fdtp_size); } return (rv); } @@ -1520,7 +1527,6 @@ fdt_cmd_mkprop(int argc, char *argv[]) if (fdt_modprop(o, propname, value, 1)) return (CMD_ERROR); - COPYIN(fdtp, fdtp_va, fdtp_size); return (CMD_OK); } @@ -1557,8 +1563,6 @@ fdt_cmd_rm(int argc, char *argv[]) if (rv) { sprintf(command_errbuf, "could not delete node"); return (CMD_ERROR); - } else { - COPYIN(fdtp, fdtp_va, fdtp_size); } return (CMD_OK); } @@ -1589,8 +1593,6 @@ fdt_cmd_mknode(int argc, char *argv[]) sprintf(command_errbuf, "Could not add node!\n"); return (CMD_ERROR); - } else { - COPYIN(fdtp, fdtp_va, fdtp_size); } return (CMD_OK); } From c78a079c40e478c6cd498e80769c309c68357e6e Mon Sep 17 00:00:00 2001 From: Marcel Moolenaar Date: Mon, 25 Feb 2013 02:41:38 +0000 Subject: [PATCH 0384/1476] kernacc() expects all KVAs to be covered in the kernel map. With the introduction of the PBVM, this stopped being the case. Redefine the VM parameters so that the PBVM is included in the kernel map. In particular this introduces VM_INIT_KERNEL_ADDRESS to point to the base of region 5 now that VM_MIN_KERNEL_ADDRESS points to the base of region 4 to include the PBVM. While here define KERNBASE to the actual link address of the kernel as is intended. PR: 169926 --- sys/ia64/ia64/pmap.c | 8 ++++---- sys/ia64/include/vmparam.h | 9 +++++---- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/sys/ia64/ia64/pmap.c b/sys/ia64/ia64/pmap.c index 594f8c6830d..fcc00f435cc 100644 --- a/sys/ia64/ia64/pmap.c +++ b/sys/ia64/ia64/pmap.c @@ -387,7 +387,7 @@ pmap_bootstrap() */ ia64_kptdir = ia64_physmem_alloc(PAGE_SIZE, PAGE_SIZE); nkpt = 0; - kernel_vm_end = VM_MIN_KERNEL_ADDRESS; + kernel_vm_end = VM_INIT_KERNEL_ADDRESS; /* * Determine a valid (mappable) VHPT size. @@ -425,7 +425,7 @@ pmap_bootstrap() ia64_set_pta(base + (1 << 8) + (pmap_vhpt_log2size << 2) + 1); ia64_srlz_i(); - virtual_avail = VM_MIN_KERNEL_ADDRESS; + virtual_avail = VM_INIT_KERNEL_ADDRESS; virtual_end = VM_MAX_KERNEL_ADDRESS; /* @@ -1383,7 +1383,7 @@ pmap_kextract(vm_offset_t va) /* Region 5 is our KVA. Bail out if the VA is beyond our limits. */ if (va >= kernel_vm_end) goto err_out; - if (va >= VM_MIN_KERNEL_ADDRESS) { + if (va >= VM_INIT_KERNEL_ADDRESS) { pte = pmap_find_kpte(va); pa = pmap_present(pte) ? pmap_ppn(pte) | (va & PAGE_MASK) : 0; goto out; @@ -2746,7 +2746,7 @@ DB_COMMAND(kpte, db_kpte) db_printf("usage: kpte \n"); return; } - if (addr < VM_MIN_KERNEL_ADDRESS) { + if (addr < VM_INIT_KERNEL_ADDRESS) { db_printf("kpte: error: invalid \n"); return; } diff --git a/sys/ia64/include/vmparam.h b/sys/ia64/include/vmparam.h index 16c5e7dda7a..10125db65ad 100644 --- a/sys/ia64/include/vmparam.h +++ b/sys/ia64/include/vmparam.h @@ -181,12 +181,13 @@ /* user/kernel map constants */ #define VM_MIN_ADDRESS 0 #define VM_MAXUSER_ADDRESS IA64_RR_BASE(IA64_VM_MINKERN_REGION) -#define VM_MIN_KERNEL_ADDRESS IA64_RR_BASE(IA64_VM_MINKERN_REGION + 1) -#define VM_MAX_KERNEL_ADDRESS \ - (VM_MIN_KERNEL_ADDRESS + IA64_REGION_GAP_START - 1) +#define VM_MIN_KERNEL_ADDRESS VM_MAXUSER_ADDRESS +#define VM_INIT_KERNEL_ADDRESS IA64_RR_BASE(IA64_VM_MINKERN_REGION + 1) +#define VM_MAX_KERNEL_ADDRESS (IA64_RR_BASE(IA64_VM_MINKERN_REGION + 2) - 1) #define VM_MAX_ADDRESS ~0UL -#define KERNBASE VM_MAXUSER_ADDRESS +/* We link the kernel at IA64_PBVM_BASE. */ +#define KERNBASE IA64_PBVM_BASE /* * USRSTACK is the top (end) of the user stack. Immediately above the user From 97b405f18f32c94958770f46866ff4a6ac45eea4 Mon Sep 17 00:00:00 2001 From: Oleksandr Tymoshenko Date: Mon, 25 Feb 2013 08:04:47 +0000 Subject: [PATCH 0385/1476] - Fix off-by-one error when returning max pin number - Fix GPIOGET for output pins. Requesting state for output pin is valid operation, get the state from TI_GPIO_DATAOUTX register --- sys/arm/ti/ti_gpio.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/sys/arm/ti/ti_gpio.c b/sys/arm/ti/ti_gpio.c index 979326faf8a..6747647fba2 100644 --- a/sys/arm/ti/ti_gpio.c +++ b/sys/arm/ti/ti_gpio.c @@ -281,7 +281,7 @@ ti_gpio_pin_max(device_t dev, int *maxpin) banks++; } - *maxpin = (banks * PINS_PER_BANK); + *maxpin = (banks * PINS_PER_BANK) - 1; TI_GPIO_UNLOCK(sc); @@ -541,13 +541,11 @@ ti_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *value) /* Sanity check the pin is not configured as an output */ val = ti_gpio_read_4(sc, bank, TI_GPIO_OE); - if ((val & mask) == mask) { - TI_GPIO_UNLOCK(sc); - return (EINVAL); - } - /* Read the value on the pin */ - *value = (ti_gpio_read_4(sc, bank, TI_GPIO_DATAIN) & mask) ? 1 : 0; + if (val & mask) + *value = (ti_gpio_read_4(sc, bank, TI_GPIO_DATAOUT) & mask) ? 1 : 0; + else + *value = (ti_gpio_read_4(sc, bank, TI_GPIO_DATAIN) & mask) ? 1 : 0; TI_GPIO_UNLOCK(sc); @@ -728,6 +726,7 @@ ti_gpio_attach(device_t dev) /* Finish of the probe call */ device_add_child(dev, "gpioc", device_get_unit(dev)); device_add_child(dev, "gpiobus", device_get_unit(dev)); + return (bus_generic_attach(dev)); } From 8cb536dd39990c76c977cfd4a9475d2dc11fd6e9 Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Mon, 25 Feb 2013 08:24:21 +0000 Subject: [PATCH 0386/1476] Add new USB ID. Submitted by: Dmitry Luhtionov --- sys/dev/usb/usbdevs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs index 62420478a8a..958745eefef 100644 --- a/sys/dev/usb/usbdevs +++ b/sys/dev/usb/usbdevs @@ -650,6 +650,7 @@ vendor OWEN 0x1555 Owen vendor OQO 0x1557 OQO vendor UMEDIA 0x157e U-MEDIA Communications vendor FIBERLINE 0x1582 Fiberline +vendor AFATECH 0x15a4 Afatech Technologies, Inc. vendor SPARKLAN 0x15a9 SparkLAN vendor OLIMEX 0x15ba Olimex vendor SOUNDGRAPH 0x15c2 Soundgraph, Inc. @@ -916,6 +917,9 @@ product ADS UBS10BTX 0x0009 UBS-10BT Ethernet /* AEI products */ product AEI FASTETHERNET 0x1701 Fast Ethernet +/* Afatech Technologies, Inc. */ +product AFATECH AFATECH1336 0x1336 Flash Card Reader + /* Agate Technologies products */ product AGATE QDRIVE 0x0378 Q-Drive From 8f80e4e13485c983c6b9235ad7674322a266cd30 Mon Sep 17 00:00:00 2001 From: Oleksandr Tymoshenko Date: Mon, 25 Feb 2013 09:33:48 +0000 Subject: [PATCH 0387/1476] Fix off-by-one error in sanity checks --- sys/arm/ti/ti_gpio.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sys/arm/ti/ti_gpio.c b/sys/arm/ti/ti_gpio.c index 6747647fba2..58de5165a02 100644 --- a/sys/arm/ti/ti_gpio.c +++ b/sys/arm/ti/ti_gpio.c @@ -315,7 +315,7 @@ ti_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps) TI_GPIO_LOCK(sc); /* Sanity check the pin number is valid */ - if ((bank > MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) { + if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) { TI_GPIO_UNLOCK(sc); return (EINVAL); } @@ -353,7 +353,7 @@ ti_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) TI_GPIO_LOCK(sc); /* Sanity check the pin number is valid */ - if ((bank > MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) { + if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) { TI_GPIO_UNLOCK(sc); return (EINVAL); } @@ -390,7 +390,7 @@ ti_gpio_pin_getname(device_t dev, uint32_t pin, char *name) TI_GPIO_LOCK(sc); /* Sanity check the pin number is valid */ - if ((bank > MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) { + if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) { TI_GPIO_UNLOCK(sc); return (EINVAL); } @@ -445,7 +445,7 @@ ti_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) TI_GPIO_LOCK(sc); /* Sanity check the pin number is valid */ - if ((bank > MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) { + if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) { TI_GPIO_UNLOCK(sc); return (EINVAL); } @@ -494,7 +494,7 @@ ti_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value) TI_GPIO_LOCK(sc); /* Sanity check the pin number is valid */ - if ((bank > MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) { + if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) { TI_GPIO_UNLOCK(sc); return (EINVAL); } @@ -533,7 +533,7 @@ ti_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *value) TI_GPIO_LOCK(sc); /* Sanity check the pin number is valid */ - if ((bank > MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) { + if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) { TI_GPIO_UNLOCK(sc); return (EINVAL); } @@ -575,7 +575,7 @@ ti_gpio_pin_toggle(device_t dev, uint32_t pin) TI_GPIO_LOCK(sc); /* Sanity check the pin number is valid */ - if ((bank > MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) { + if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) { TI_GPIO_UNLOCK(sc); return (EINVAL); } From 2e39e9ee7187fdd2e8b8388827c94a91b17256df Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Mon, 25 Feb 2013 10:57:35 +0000 Subject: [PATCH 0388/1476] Fix init/uninit function type. --- sys/dev/usb/usb_pf.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sys/dev/usb/usb_pf.c b/sys/dev/usb/usb_pf.c index 98705ebcdcd..d849a133e82 100644 --- a/sys/dev/usb/usb_pf.c +++ b/sys/dev/usb/usb_pf.c @@ -63,8 +63,8 @@ #include #endif /* USB_GLOBAL_INCLUDE_FILE */ -static void usbpf_init(void); -static void usbpf_uninit(void); +static void usbpf_init(void *); +static void usbpf_uninit(void *); static int usbpf_ioctl(struct ifnet *, u_long, caddr_t); static int usbpf_clone_match(struct if_clone *, const char *); static int usbpf_clone_create(struct if_clone *, char *, size_t, caddr_t); @@ -82,7 +82,7 @@ SYSINIT(usbpf_init, SI_SUB_PSEUDO, SI_ORDER_MIDDLE, usbpf_init, NULL); SYSUNINIT(usbpf_uninit, SI_SUB_PSEUDO, SI_ORDER_MIDDLE, usbpf_uninit, NULL); static void -usbpf_init(void) +usbpf_init(void *arg) { usbpf_cloner = if_clone_advanced(usbusname, 0, usbpf_clone_match, @@ -90,7 +90,7 @@ usbpf_init(void) } static void -usbpf_uninit(void) +usbpf_uninit(void *arg) { int devlcnt; device_t *devlp; From 5bba9b9f69b48242be303e2e15b57b9bae9f6191 Mon Sep 17 00:00:00 2001 From: Matt Jacob Date: Mon, 25 Feb 2013 11:22:54 +0000 Subject: [PATCH 0389/1476] Turn off fast posting for the ISP2100- I'd forgotten that it actually might have been enabled for them- now that we use all 32 bits of handle. Fast Posting doesn't pass the full 32 bits. Noticed by: Bugs in NetBSD. Only a NetBSD user might actually still use such old hardware. MFC after: 1 week --- sys/dev/isp/isp.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c index c4747e732c7..d3e5bdbd7c6 100644 --- a/sys/dev/isp/isp.c +++ b/sys/dev/isp/isp.c @@ -1709,7 +1709,13 @@ isp_fibre_init(ispsoftc_t *isp) * * NB: for the 2300, ICBOPT_EXTENDED is required. */ - if (IS_2200(isp) || IS_23XX(isp)) { + if (IS_2100(isp)) { + /* + * We can't have Fast Posting any more- we now + * have 32 bit handles. + */ + icbp->icb_fwoptions &= ~ICBOPT_FAST_POST; + } else if (IS_2200(isp) || IS_23XX(isp)) { icbp->icb_fwoptions |= ICBOPT_EXTENDED; icbp->icb_xfwoptions = fcp->isp_xfwoptions; From 9cdcf100c10c175ac4b8c1a0a711c27642fbaf8b Mon Sep 17 00:00:00 2001 From: Matt Jacob Date: Mon, 25 Feb 2013 14:06:24 +0000 Subject: [PATCH 0390/1476] Don't try and negotiate sync mode if either period or offset are zero. PR: kern/163064 Partially Submitted by: Peter MFC after: 1 month --- sys/dev/sym/sym_hipd.c | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/sys/dev/sym/sym_hipd.c b/sys/dev/sym/sym_hipd.c index 68ad77f68f9..7eebfd3ffc2 100644 --- a/sys/dev/sym/sym_hipd.c +++ b/sys/dev/sym/sym_hipd.c @@ -8211,8 +8211,13 @@ static void sym_update_trans(hcb_p np, tcb_p tp, struct sym_trans *tip, * Scale against driver configuration limits. */ if (tip->width > SYM_SETUP_MAX_WIDE) tip->width = SYM_SETUP_MAX_WIDE; - if (tip->offset > SYM_SETUP_MAX_OFFS) tip->offset = SYM_SETUP_MAX_OFFS; - if (tip->period < SYM_SETUP_MIN_SYNC) tip->period = SYM_SETUP_MIN_SYNC; + if (tip->period && tip->offset) { + if (tip->offset > SYM_SETUP_MAX_OFFS) tip->offset = SYM_SETUP_MAX_OFFS; + if (tip->period < SYM_SETUP_MIN_SYNC) tip->period = SYM_SETUP_MIN_SYNC; + } else { + tip->offset = 0; + tip->period = 0; + } /* * Scale against actual controller BUS width. @@ -8231,21 +8236,23 @@ static void sym_update_trans(hcb_p np, tcb_p tp, struct sym_trans *tip, /* * Scale period factor and offset against controller limits. */ - if (tip->options & PPR_OPT_DT) { - if (tip->period < np->minsync_dt) - tip->period = np->minsync_dt; - if (tip->period > np->maxsync_dt) - tip->period = np->maxsync_dt; - if (tip->offset > np->maxoffs_dt) - tip->offset = np->maxoffs_dt; - } - else { - if (tip->period < np->minsync) - tip->period = np->minsync; - if (tip->period > np->maxsync) - tip->period = np->maxsync; - if (tip->offset > np->maxoffs) - tip->offset = np->maxoffs; + if (tip->offset && tip->period) { + if (tip->options & PPR_OPT_DT) { + if (tip->period < np->minsync_dt) + tip->period = np->minsync_dt; + if (tip->period > np->maxsync_dt) + tip->period = np->maxsync_dt; + if (tip->offset > np->maxoffs_dt) + tip->offset = np->maxoffs_dt; + } + else { + if (tip->period < np->minsync) + tip->period = np->minsync; + if (tip->period > np->maxsync) + tip->period = np->maxsync; + if (tip->offset > np->maxoffs) + tip->offset = np->maxoffs; + } } } From dedbe8362f4173d7fd1b6d9de1ef678d8f9d5bb5 Mon Sep 17 00:00:00 2001 From: Andrew Gallatin Date: Mon, 25 Feb 2013 16:22:40 +0000 Subject: [PATCH 0391/1476] Several cleanups and fixes to mxge: - Remove vestigial null pointer tests after malloc(..., M_WAITOK). - Remove vestigal qualhack union - Use strlcpy() instead of the error-prone strncpy() when parsing EEPROM and copying strings - Check the MAC address in the EEPROM strings more strictly. - Expand the macro MXGE_NEXT_STRING() at its only user. Due to a typo, the macro was very confusing. - Remove unnecessary buffer limit check. The buffer is double-NUL terminated per construction. PR: kern/176369 Submitted by: Christoph Mallon --- sys/dev/mxge/if_mxge.c | 71 +++++++++++++++--------------------------- 1 file changed, 25 insertions(+), 46 deletions(-) diff --git a/sys/dev/mxge/if_mxge.c b/sys/dev/mxge/if_mxge.c index 245c1391345..68624adcc08 100644 --- a/sys/dev/mxge/if_mxge.c +++ b/sys/dev/mxge/if_mxge.c @@ -288,42 +288,43 @@ mxge_dma_free(mxge_dma_t *dma) static int mxge_parse_strings(mxge_softc_t *sc) { -#define MXGE_NEXT_STRING(p) while(ptr < limit && *ptr++) - - char *ptr, *limit; + char *ptr; int i, found_mac, found_sn2; + char *endptr; ptr = sc->eeprom_strings; - limit = sc->eeprom_strings + MXGE_EEPROM_STRINGS_SIZE; found_mac = 0; found_sn2 = 0; - while (ptr < limit && *ptr != '\0') { - if (memcmp(ptr, "MAC=", 4) == 0) { - ptr += 1; - sc->mac_addr_string = ptr; - for (i = 0; i < 6; i++) { - ptr += 3; - if ((ptr + 2) > limit) + while (*ptr != '\0') { + if (strncmp(ptr, "MAC=", 4) == 0) { + ptr += 4; + for (i = 0;;) { + sc->mac_addr[i] = strtoul(ptr, &endptr, 16); + if (endptr - ptr != 2) + goto abort; + ptr = endptr; + if (++i == 6) + break; + if (*ptr++ != ':') goto abort; - sc->mac_addr[i] = strtoul(ptr, NULL, 16); - found_mac = 1; } - } else if (memcmp(ptr, "PC=", 3) == 0) { + found_mac = 1; + } else if (strncmp(ptr, "PC=", 3) == 0) { ptr += 3; - strncpy(sc->product_code_string, ptr, - sizeof (sc->product_code_string) - 1); - } else if (!found_sn2 && (memcmp(ptr, "SN=", 3) == 0)) { + strlcpy(sc->product_code_string, ptr, + sizeof(sc->product_code_string)); + } else if (!found_sn2 && (strncmp(ptr, "SN=", 3) == 0)) { ptr += 3; - strncpy(sc->serial_number_string, ptr, - sizeof (sc->serial_number_string) - 1); - } else if (memcmp(ptr, "SN2=", 4) == 0) { + strlcpy(sc->serial_number_string, ptr, + sizeof(sc->serial_number_string)); + } else if (strncmp(ptr, "SN2=", 4) == 0) { /* SN2 takes precedence over SN */ ptr += 4; found_sn2 = 1; - strncpy(sc->serial_number_string, ptr, - sizeof (sc->serial_number_string) - 1); + strlcpy(sc->serial_number_string, ptr, + sizeof(sc->serial_number_string)); } - MXGE_NEXT_STRING(ptr); + while (*ptr++ != '\0') {} } if (found_mac) @@ -649,12 +650,6 @@ abort: return (mxge_load_firmware(sc, 0)); } -union qualhack -{ - const char *ro_char; - char *rw_char; -}; - static int mxge_validate_firmware(mxge_softc_t *sc, const mcp_gen_header_t *hdr) { @@ -667,7 +662,7 @@ mxge_validate_firmware(mxge_softc_t *sc, const mcp_gen_header_t *hdr) } /* save firmware version for sysctl */ - strncpy(sc->fw_version, hdr->version, sizeof (sc->fw_version)); + strlcpy(sc->fw_version, hdr->version, sizeof(sc->fw_version)); if (mxge_verbose) device_printf(sc->dev, "firmware id: %s\n", hdr->version); @@ -3325,8 +3320,6 @@ mxge_alloc_slice_rings(struct mxge_slice_state *ss, int rx_ring_entries, size_t bytes; int err, i; - err = ENOMEM; - /* allocate per-slice receive resources */ ss->rx_small.mask = ss->rx_big.mask = rx_ring_entries - 1; @@ -3335,24 +3328,16 @@ mxge_alloc_slice_rings(struct mxge_slice_state *ss, int rx_ring_entries, /* allocate the rx shadow rings */ bytes = rx_ring_entries * sizeof (*ss->rx_small.shadow); ss->rx_small.shadow = malloc(bytes, M_DEVBUF, M_ZERO|M_WAITOK); - if (ss->rx_small.shadow == NULL) - return err; bytes = rx_ring_entries * sizeof (*ss->rx_big.shadow); ss->rx_big.shadow = malloc(bytes, M_DEVBUF, M_ZERO|M_WAITOK); - if (ss->rx_big.shadow == NULL) - return err; /* allocate the rx host info rings */ bytes = rx_ring_entries * sizeof (*ss->rx_small.info); ss->rx_small.info = malloc(bytes, M_DEVBUF, M_ZERO|M_WAITOK); - if (ss->rx_small.info == NULL) - return err; bytes = rx_ring_entries * sizeof (*ss->rx_big.info); ss->rx_big.info = malloc(bytes, M_DEVBUF, M_ZERO|M_WAITOK); - if (ss->rx_big.info == NULL) - return err; /* allocate the rx busdma resources */ err = bus_dma_tag_create(sc->parent_dmat, /* parent */ @@ -3449,8 +3434,6 @@ mxge_alloc_slice_rings(struct mxge_slice_state *ss, int rx_ring_entries, bytes = 8 + sizeof (*ss->tx.req_list) * (ss->tx.max_desc + 4); ss->tx.req_bytes = malloc(bytes, M_DEVBUF, M_WAITOK); - if (ss->tx.req_bytes == NULL) - return err; /* ensure req_list entries are aligned to 8 bytes */ ss->tx.req_list = (mcp_kreq_ether_send_t *) ((unsigned long)(ss->tx.req_bytes + 7) & ~7UL); @@ -3459,14 +3442,10 @@ mxge_alloc_slice_rings(struct mxge_slice_state *ss, int rx_ring_entries, bytes = sizeof (*ss->tx.seg_list) * ss->tx.max_desc; ss->tx.seg_list = (bus_dma_segment_t *) malloc(bytes, M_DEVBUF, M_WAITOK); - if (ss->tx.seg_list == NULL) - return err; /* allocate the tx host info ring */ bytes = tx_ring_entries * sizeof (*ss->tx.info); ss->tx.info = malloc(bytes, M_DEVBUF, M_ZERO|M_WAITOK); - if (ss->tx.info == NULL) - return err; /* allocate the tx busdma resources */ err = bus_dma_tag_create(sc->parent_dmat, /* parent */ From f2e472dcf4951b615381ca630b8347313e63fab9 Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Mon, 25 Feb 2013 16:25:38 +0000 Subject: [PATCH 0392/1476] Fix ARM build by assigning the computed time here to a variable of the right type for printf. --- sbin/fsck_ffs/fsutil.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sbin/fsck_ffs/fsutil.c b/sbin/fsck_ffs/fsutil.c index eef9bdcba80..34cc29f972d 100644 --- a/sbin/fsck_ffs/fsutil.c +++ b/sbin/fsck_ffs/fsutil.c @@ -448,8 +448,8 @@ static void printIOstats(void) clock_gettime(CLOCK_REALTIME_PRECISE, &finishpass); timespecsub(&finishpass, &startpass); - printf("Running time: %ld msec\n", - finishpass.tv_sec * 1000 + finishpass.tv_nsec / 1000000); + msec = finishpass.tv_sec * 1000 + finishpass.tv_nsec / 1000000; + printf("Running time: %lld msec\n", msec); printf("buffer reads by type:\n"); for (totalmsec = 0, i = 0; i < BT_NUMBUFTYPES; i++) totalmsec += readtime[i].tv_sec * 1000 + From c1803a93a47ad6e5f9d6651859524d053f4defbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Mon, 25 Feb 2013 16:47:09 +0000 Subject: [PATCH 0393/1476] - Implement and use usage(). - Document the -C option. - Allow rtadvd to be invoked without any interfaces on the command line, and document that possibility. MFC after: 1 week --- usr.sbin/rtadvd/rtadvd.8 | 16 ++++++++++++++-- usr.sbin/rtadvd/rtadvd.c | 20 ++++++++++++-------- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/usr.sbin/rtadvd/rtadvd.8 b/usr.sbin/rtadvd/rtadvd.8 index ad39887dbc7..fcb46feebef 100644 --- a/usr.sbin/rtadvd/rtadvd.8 +++ b/usr.sbin/rtadvd/rtadvd.8 @@ -29,7 +29,7 @@ .\" .\" $FreeBSD$ .\" -.Dd July 14, 2011 +.Dd February 25, 2013 .Dt RTADVD 8 .Os .Sh NAME @@ -39,13 +39,19 @@ .Nm .Op Fl dDfRs .Op Fl c Ar configfile +.Op Fl C Ar ctlsock .Op Fl M Ar ifname .Op Fl p Ar pidfile -.Ar interface ... +.Op Ar interface ... .Sh DESCRIPTION .Nm sends router advertisement packets to the specified .Ar interfaces . +If no interfaces are specified, +.Nm +will still run, but will not advertise any routes until interfaces are +added using +.Xr rtadvctl 8 . .Pp The program will daemonize itself on invocation. It will then send router advertisement packets periodically, as well @@ -121,6 +127,11 @@ for the configuration file. By default, .Pa /etc/rtadvd.conf is used. +.It Fl C +Specify an alternate location for the control socket used by +.Xr rtadvctl 8 . +The default is +.Pa /var/run/rtadvd.sock . .It Fl d Print debugging information. .It Fl D @@ -185,6 +196,7 @@ The default process ID file. .Ex -std .Sh SEE ALSO .Xr rtadvd.conf 5 , +.Xr rtadvctl 8 , .Xr rtsol 8 .Rs .%A Thomas Narten diff --git a/usr.sbin/rtadvd/rtadvd.c b/usr.sbin/rtadvd/rtadvd.c index a5f306de260..4d2a5273f1c 100644 --- a/usr.sbin/rtadvd/rtadvd.c +++ b/usr.sbin/rtadvd/rtadvd.c @@ -166,6 +166,15 @@ static void rtmsg_input(struct sockinfo *); static void set_short_delay(struct ifinfo *); static int check_accept_rtadv(int); +static void +usage(void) +{ + + fprintf(stderr, "usage: rtadvd [-dDfRs] " + "[-c configfile] [-C ctlsock] [-M ifname] [-p pidfile]\n"); + exit(1); +} + int main(int argc, char *argv[]) { @@ -177,7 +186,7 @@ main(int argc, char *argv[]) pid_t pid, otherpid; /* get command line options and arguments */ - while ((ch = getopt(argc, argv, "c:C:dDfM:p:Rs")) != -1) { + while ((ch = getopt(argc, argv, "c:C:dDfhM:p:Rs")) != -1) { switch (ch) { case 'c': conffile = optarg; @@ -209,17 +218,12 @@ main(int argc, char *argv[]) case 'p': pidfilename = optarg; break; + default: + usage(); } } argc -= optind; argv += optind; - if (argc == 0) { - fprintf(stderr, - "usage: rtadvd [-dDfRs] [-c conffile] " - "[-C ctrlsockname] [-M ifname] " - "[-p pidfile] interfaces...\n"); - exit(1); - } logopt = LOG_NDELAY | LOG_PID; if (fflag) From 55de4cd6fe248b45618f9bc72a895310e80c41c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Mon, 25 Feb 2013 17:07:42 +0000 Subject: [PATCH 0394/1476] If rtadvd_interfaces is set to "none", start rtadvd without listing any interfaces on the command line. MFC after: 1 week --- etc/rc.d/rtadvd | 2 ++ 1 file changed, 2 insertions(+) diff --git a/etc/rc.d/rtadvd b/etc/rc.d/rtadvd index 1ad40b86168..562498c3c36 100755 --- a/etc/rc.d/rtadvd +++ b/etc/rc.d/rtadvd @@ -46,6 +46,8 @@ rtadvd_precmd() fi done ;; + [Nn][Oo][Nn][Ee]) + ;; *) command_args="${rtadvd_interfaces}" ;; From ed88bcd300eb5de7059342dac5352b37d82f3a3e Mon Sep 17 00:00:00 2001 From: Joel Dahl Date: Mon, 25 Feb 2013 17:32:10 +0000 Subject: [PATCH 0395/1476] Remove EOL whitespace. --- usr.bin/systat/systat.1 | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/usr.bin/systat/systat.1 b/usr.bin/systat/systat.1 index fa8f789365b..4916b9c839a 100644 --- a/usr.bin/systat/systat.1 +++ b/usr.bin/systat/systat.1 @@ -513,12 +513,12 @@ The following units are recognised: kbit, kbyte, mbit, mbyte, gbit, gbyte and auto. .It Cm pps Show statistics in packets per second instead of bytes/bits per second. -A subsequent call of -.Ic pps +A subsequent call of +.Ic pps switches this mode off. .It Cm match Op Ar patterns -Display only interfaces that match pattern provided as an argument. -Patterns should be in shell syntax separated by whitespaces or commas. +Display only interfaces that match pattern provided as an argument. +Patterns should be in shell syntax separated by whitespaces or commas. If this command is called without arguments then all interfaces are displayed. For example: .Pp @@ -528,8 +528,8 @@ This will display em0 and bge1 interfaces. .Pp .Dl match em*, bge*, lo0 .Pp -This will display all -.Ic em +This will display all +.Ic em interfaces, all .Ic bge interfaces and the loopback interface. From 293beebc463697485b14136f4b2a5b1d154a3da9 Mon Sep 17 00:00:00 2001 From: Peter Jeremy Date: Mon, 25 Feb 2013 19:05:40 +0000 Subject: [PATCH 0396/1476] Enhance test(1) by adding provision to compare any combination of the access, birth, change and modify times of two files, instead of only being able to compare modify times. The builtin test in sh(1) will automagically acquire the same expansion. Approved by: grog MFC after: 2 weeks --- bin/test/test.1 | 58 ++++++++- bin/test/test.c | 184 +++++++++++++++++++++++---- tools/regression/bin/test/regress.sh | 65 +++++++++- 3 files changed, 279 insertions(+), 28 deletions(-) diff --git a/bin/test/test.1 b/bin/test/test.1 index 885374e2e5c..76a4a9cb260 100644 --- a/bin/test/test.1 +++ b/bin/test/test.1 @@ -169,15 +169,65 @@ True if .Ar file exists and is a socket. .It Ar file1 Fl nt Ar file2 -True if +True if both .Ar file1 -exists and is newer than +and +.Ar file2 +exist and +.Ar file1 +is newer than .Ar file2 . +.It Ar file1 Fl nt Ns Ar X Ns Ar Y Ar file2 +True if both +.Ar file1 +and +.Ar file2 +exist and +.Ar file1 +has a more recent last access time +.Pq Ar X Ns = Ns Cm a , +inode creation time +.Pq Ar X Ns = Ns Cm b , +change time +.Pq Ar X Ns = Ns Cm c , +or modification time +.Pq Ar X Ns = Ns Cm m +than the last access time +.Pq Ar Y Ns = Ns Cm a , +inode creation time +.Pq Ar Y Ns = Ns Cm b , +change time +.Pq Ar Y Ns = Ns Cm c , +or modification time +.Pq Ar Y Ns = Ns Cm m +of +.Ar file2 . +Note that +.Ic -ntmm +is equivalent to +.Ic -nt . .It Ar file1 Fl ot Ar file2 -True if +True if both .Ar file1 -exists and is older than +and +.Ar file2 +exist and +.Ar file1 +is older than .Ar file2 . +Note that +.Ar file1 +.Ic -ot +.Ar file2 +is equivalent to +.Ar file2 +.Ic -nt +.Ar file1 +.It Ar file1 Fl ot Ns Ar X Ns Ar Y Ar file2 +Equivalent to +.Ar file2 +.Ic -nt Ns Ar Y Ns Ar X +.Ar file1 . .It Ar file1 Fl ef Ar file2 True if .Ar file1 diff --git a/bin/test/test.c b/bin/test/test.c index 96aa9f54970..eaa2f403444 100644 --- a/bin/test/test.c +++ b/bin/test/test.c @@ -63,7 +63,7 @@ error(const char *msg, ...) "-u"|"-g"|"-k"|"-s"|"-t"|"-z"|"-n"|"-o"|"-O"|"-G"|"-L"|"-S"; binary-operator ::= "="|"!="|"-eq"|"-ne"|"-ge"|"-gt"|"-le"|"-lt"| - "-nt"|"-ot"|"-ef"; + "-nt"|"-nt[abcm][abcm]"|"-ot"|"-ot[abcm][abcm])"|"-ef"; operand ::= */ @@ -85,8 +85,38 @@ enum token { FILSUID, FILSGID, FILSTCK, - FILNT, - FILOT, + FILNTAA, + FILNTAB, + FILNTAC, + FILNTAM, + FILNTBA, + FILNTBB, + FILNTBC, + FILNTBM, + FILNTCA, + FILNTCB, + FILNTCC, + FILNTCM, + FILNTMA, + FILNTMB, + FILNTMC, + FILNTMM, + FILOTAA, + FILOTAB, + FILOTAC, + FILOTAM, + FILOTBA, + FILOTBB, + FILOTBC, + FILOTBM, + FILOTCA, + FILOTCB, + FILOTCC, + FILOTCM, + FILOTMA, + FILOTMB, + FILOTMC, + FILOTMM, FILEQ, FILUID, FILGID, @@ -118,9 +148,16 @@ enum token_types { PAREN }; +enum time_types { + ATIME, + BTIME, + CTIME, + MTIME +}; + static struct t_op { - char op_text[4]; - short op_num, op_type; + char op_text[6]; + char op_num, op_type; } const ops [] = { {"-r", FILRD, UNOP}, {"-w", FILWR, UNOP}, @@ -154,8 +191,40 @@ static struct t_op { {"-gt", INTGT, BINOP}, {"-le", INTLE, BINOP}, {"-lt", INTLT, BINOP}, - {"-nt", FILNT, BINOP}, - {"-ot", FILOT, BINOP}, + {"-nt", FILNTMM, BINOP}, + {"-ntaa", FILNTAA, BINOP}, + {"-ntab", FILNTAB, BINOP}, + {"-ntac", FILNTAC, BINOP}, + {"-ntam", FILNTAM, BINOP}, + {"-ntba", FILNTBA, BINOP}, + {"-ntbb", FILNTBB, BINOP}, + {"-ntbc", FILNTBC, BINOP}, + {"-ntbm", FILNTBM, BINOP}, + {"-ntca", FILNTCA, BINOP}, + {"-ntcb", FILNTCB, BINOP}, + {"-ntcc", FILNTCC, BINOP}, + {"-ntcm", FILNTCM, BINOP}, + {"-ntma", FILNTMA, BINOP}, + {"-ntmb", FILNTMB, BINOP}, + {"-ntmc", FILNTMC, BINOP}, + {"-ntmm", FILNTMM, BINOP}, + {"-ot", FILOTMM, BINOP}, + {"-otaa", FILOTAA, BINOP}, + {"-otab", FILOTBB, BINOP}, + {"-otac", FILOTAC, BINOP}, + {"-otam", FILOTAM, BINOP}, + {"-otba", FILOTBA, BINOP}, + {"-otbb", FILOTBB, BINOP}, + {"-otbc", FILOTBC, BINOP}, + {"-otbm", FILOTBM, BINOP}, + {"-otca", FILOTCA, BINOP}, + {"-otcb", FILOTCB, BINOP}, + {"-otcc", FILOTCC, BINOP}, + {"-otcm", FILOTCM, BINOP}, + {"-otma", FILOTMA, BINOP}, + {"-otmb", FILOTMB, BINOP}, + {"-otmc", FILOTMC, BINOP}, + {"-otmm", FILOTMM, BINOP}, {"-ef", FILEQ, BINOP}, {"!", UNOT, BUNOP}, {"-a", BAND, BBINOP}, @@ -180,10 +249,10 @@ static int intcmp(const char *, const char *); static int isunopoperand(void); static int islparenoperand(void); static int isrparenoperand(void); -static int newerf(const char *, const char *); +static int newerf(const char *, const char *, enum time_types, + enum time_types); static int nexpr(enum token); static int oexpr(enum token); -static int olderf(const char *, const char *); static int primary(enum token); static void syntax(const char *, const char *); static enum token t_lex(char *); @@ -353,10 +422,70 @@ binop(void) return intcmp(opnd1, opnd2) <= 0; case INTLT: return intcmp(opnd1, opnd2) < 0; - case FILNT: - return newerf (opnd1, opnd2); - case FILOT: - return olderf (opnd1, opnd2); + case FILNTAA: + return newerf(opnd1, opnd2, ATIME, ATIME); + case FILNTAB: + return newerf(opnd1, opnd2, ATIME, BTIME); + case FILNTAC: + return newerf(opnd1, opnd2, ATIME, CTIME); + case FILNTAM: + return newerf(opnd1, opnd2, ATIME, MTIME); + case FILNTBA: + return newerf(opnd1, opnd2, BTIME, ATIME); + case FILNTBB: + return newerf(opnd1, opnd2, BTIME, BTIME); + case FILNTBC: + return newerf(opnd1, opnd2, BTIME, CTIME); + case FILNTBM: + return newerf(opnd1, opnd2, BTIME, MTIME); + case FILNTCA: + return newerf(opnd1, opnd2, CTIME, ATIME); + case FILNTCB: + return newerf(opnd1, opnd2, CTIME, BTIME); + case FILNTCC: + return newerf(opnd1, opnd2, CTIME, CTIME); + case FILNTCM: + return newerf(opnd1, opnd2, CTIME, MTIME); + case FILNTMA: + return newerf(opnd1, opnd2, MTIME, ATIME); + case FILNTMB: + return newerf(opnd1, opnd2, MTIME, BTIME); + case FILNTMC: + return newerf(opnd1, opnd2, MTIME, CTIME); + case FILNTMM: + return newerf(opnd1, opnd2, MTIME, MTIME); + case FILOTAA: + return newerf(opnd2, opnd1, ATIME, ATIME); + case FILOTAB: + return newerf(opnd2, opnd1, BTIME, ATIME); + case FILOTAC: + return newerf(opnd2, opnd1, CTIME, ATIME); + case FILOTAM: + return newerf(opnd2, opnd1, MTIME, ATIME); + case FILOTBA: + return newerf(opnd2, opnd1, ATIME, BTIME); + case FILOTBB: + return newerf(opnd2, opnd1, BTIME, BTIME); + case FILOTBC: + return newerf(opnd2, opnd1, CTIME, BTIME); + case FILOTBM: + return newerf(opnd2, opnd1, MTIME, BTIME); + case FILOTCA: + return newerf(opnd2, opnd1, ATIME, CTIME); + case FILOTCB: + return newerf(opnd2, opnd1, BTIME, CTIME); + case FILOTCC: + return newerf(opnd2, opnd1, CTIME, CTIME); + case FILOTCM: + return newerf(opnd2, opnd1, MTIME, CTIME); + case FILOTMA: + return newerf(opnd2, opnd1, ATIME, MTIME); + case FILOTMB: + return newerf(opnd2, opnd1, BTIME, MTIME); + case FILOTMC: + return newerf(opnd2, opnd1, CTIME, MTIME); + case FILOTMM: + return newerf(opnd2, opnd1, MTIME, MTIME); case FILEQ: return equalf (opnd1, opnd2); default: @@ -570,25 +699,34 @@ intcmp (const char *s1, const char *s2) } static int -newerf (const char *f1, const char *f2) +newerf (const char *f1, const char *f2, enum time_types t1, enum time_types t2) { struct stat b1, b2; + struct timespec *ts1, *ts2; if (stat(f1, &b1) != 0 || stat(f2, &b2) != 0) return 0; - if (b1.st_mtim.tv_sec > b2.st_mtim.tv_sec) + switch (t1) { + case ATIME: ts1 = &b1.st_atim; break; + case BTIME: ts1 = &b1.st_birthtim; break; + case CTIME: ts1 = &b1.st_ctim; break; + default: ts1 = &b1.st_mtim; break; + } + + switch (t2) { + case ATIME: ts2 = &b2.st_atim; break; + case BTIME: ts2 = &b2.st_birthtim; break; + case CTIME: ts2 = &b2.st_ctim; break; + default: ts2 = &b2.st_mtim; break; + } + + if (ts1->tv_sec > ts2->tv_sec) return 1; - if (b1.st_mtim.tv_sec < b2.st_mtim.tv_sec) + if (ts1->tv_sec < ts2->tv_sec) return 0; - return (b1.st_mtim.tv_nsec > b2.st_mtim.tv_nsec); -} - -static int -olderf (const char *f1, const char *f2) -{ - return (newerf(f2, f1)); + return (ts1->tv_nsec > ts2->tv_nsec); } static int diff --git a/tools/regression/bin/test/regress.sh b/tools/regression/bin/test/regress.sh index 922955129d9..117a7e27b64 100644 --- a/tools/regression/bin/test/regress.sh +++ b/tools/regression/bin/test/regress.sh @@ -52,7 +52,7 @@ t () } count=0 -echo "1..130" +echo "1..266" t 0 'b = b' t 0 'b == b' @@ -194,3 +194,66 @@ t 1 '\( ! -a \)' t 0 '\( -n -o \)' t 1 '\( -z -o \)' t 1 '\( ! -o \)' + +# Test all file timestamp comparison operators +s() { + t ${1} "${35} -nt ${36}" + t ${2} "${35} -ntaa ${36}" + t ${3} "${35} -ntab ${36}" + t ${4} "${35} -ntac ${36}" + t ${5} "${35} -ntam ${36}" + t ${6} "${35} -ntba ${36}" + t ${7} "${35} -ntbb ${36}" + t ${8} "${35} -ntbc ${36}" + t ${9} "${35} -ntbm ${36}" + t ${10} "${35} -ntca ${36}" + t ${11} "${35} -ntcb ${36}" + t ${12} "${35} -ntcc ${36}" + t ${13} "${35} -ntcm ${36}" + t ${14} "${35} -ntma ${36}" + t ${15} "${35} -ntmb ${36}" + t ${16} "${35} -ntmc ${36}" + t ${17} "${35} -ntmm ${36}" + t ${18} "${35} -ot ${36}" + t ${19} "${35} -otaa ${36}" + t ${20} "${35} -otab ${36}" + t ${21} "${35} -otac ${36}" + t ${22} "${35} -otam ${36}" + t ${23} "${35} -otba ${36}" + t ${24} "${35} -otbb ${36}" + t ${25} "${35} -otbc ${36}" + t ${26} "${35} -otbm ${36}" + t ${27} "${35} -otca ${36}" + t ${28} "${35} -otcb ${36}" + t ${29} "${35} -otcc ${36}" + t ${30} "${35} -otcm ${36}" + t ${31} "${35} -otma ${36}" + t ${32} "${35} -otmb ${36}" + t ${33} "${35} -otmc ${36}" + t ${34} "${35} -otmm ${36}" +} + +a=/tmp/test$$.1 +b=/tmp/test$$.2 +trap "rm -f $a $b" EXIT + +# Tests 131-164 +s 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 $a $b + +touch $a +# Tests 165-198 +s 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 $a $b + +sleep 2 # Ensure $b is newer than $a +touch $b +# Tests 199-232 +s 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 $a $b + +sleep 2 +echo >$b # Updates mtime & ctime +sleep 2 +touch -A 01 -a $b + +# $b now has ctime > mtime > atime > btime +# Tests 233-266 +s 1 1 0 1 1 1 1 1 1 0 0 1 0 0 0 1 1 1 1 1 0 0 0 1 0 0 1 1 1 1 1 1 0 1 $b $b From 11c5cac53f6cc9a2d94cb6f58728b2655e92d3a5 Mon Sep 17 00:00:00 2001 From: Devin Teske Date: Mon, 25 Feb 2013 19:14:06 +0000 Subject: [PATCH 0397/1476] Fix typo and update copyright. --- usr.sbin/bsdconfig/startup/rcvar | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usr.sbin/bsdconfig/startup/rcvar b/usr.sbin/bsdconfig/startup/rcvar index d7ced9e87b2..d655e613c09 100755 --- a/usr.sbin/bsdconfig/startup/rcvar +++ b/usr.sbin/bsdconfig/startup/rcvar @@ -1,6 +1,6 @@ #!/bin/sh #- -# Copyright (c) 2012 Devin Teske +# Copyright (c) 2012-2013 Devin Teske # All Rights Reserved. # # Redistribution and use in source and binary forms, with or without @@ -75,7 +75,7 @@ dialog_menu_main() " # END-QUOTE if [ ! "$_RCVAR_MAP" ]; then - # Genreate RCVAR_MAP of `rcvar dflt script desc ...' per-line + # Generate RCVAR_MAP of `rcvar dflt script desc ...' per-line f_dialog_info "$msg_creating_rcvar_map" RCVAR_MAP=$( f_startup_rcvar_map ) export RCVAR_MAP From ee4827b20d1454a12acd094baa16a72cb2298bba Mon Sep 17 00:00:00 2001 From: Sean Bruno Date: Mon, 25 Feb 2013 19:22:56 +0000 Subject: [PATCH 0398/1476] The 5300 series ciss(4) board does not work in performant mode with our currnet initialization sequence. Set it to simple mode only so that systems can be updated from stable/7 to newer installations. At some point, we should figure out why we cannot initialize performant mode on this board. PR: kern/153361 Reviewed by: scottl Obtained from: Yahoo! Inc. MFC after: 2 weeks --- sys/dev/ciss/ciss.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/sys/dev/ciss/ciss.c b/sys/dev/ciss/ciss.c index 9aef998fbde..5895d7f4643 100644 --- a/sys/dev/ciss/ciss.c +++ b/sys/dev/ciss/ciss.c @@ -282,6 +282,7 @@ TUNABLE_INT("hw.ciss.force_interrupt", &ciss_force_interrupt); #define CISS_BOARD_SA5 1 #define CISS_BOARD_SA5B 2 #define CISS_BOARD_NOMSI (1<<4) +#define CISS_BOARD_SIMPLE (1<<5) static struct { @@ -290,7 +291,8 @@ static struct int flags; char *desc; } ciss_vendor_data[] = { - { 0x0e11, 0x4070, CISS_BOARD_SA5|CISS_BOARD_NOMSI, "Compaq Smart Array 5300" }, + { 0x0e11, 0x4070, CISS_BOARD_SA5|CISS_BOARD_NOMSI|CISS_BOARD_SIMPLE, + "Compaq Smart Array 5300" }, { 0x0e11, 0x4080, CISS_BOARD_SA5B|CISS_BOARD_NOMSI, "Compaq Smart Array 5i" }, { 0x0e11, 0x4082, CISS_BOARD_SA5B|CISS_BOARD_NOMSI, "Compaq Smart Array 532" }, { 0x0e11, 0x4083, CISS_BOARD_SA5B|CISS_BOARD_NOMSI, "HP Smart Array 5312" }, @@ -682,8 +684,15 @@ ciss_init_pci(struct ciss_softc *sc) supported_methods = CISS_TRANSPORT_METHOD_PERF; break; default: - supported_methods = sc->ciss_cfg->supported_methods; - break; + /* + * Override the capabilities of the BOARD and specify SIMPLE + * MODE + */ + if (ciss_vendor_data[i].flags & CISS_BOARD_SIMPLE) + supported_methods = CISS_TRANSPORT_METHOD_SIMPLE; + else + supported_methods = sc->ciss_cfg->supported_methods; + break; } setup: From 7323adac99d399e58bdec71236a0db9ee6bfb6d2 Mon Sep 17 00:00:00 2001 From: Devin Teske Date: Mon, 25 Feb 2013 19:55:32 +0000 Subject: [PATCH 0399/1476] Import media selection/preparation framework (sysinstall inspired). Makes accessing files from various types of media nice and abstracted away from the wet-work involved in preparing, validating, and initializing those types of media. This will be used for the package management system module and other modules that need access to files and want to allow the user to decide where those files come from (either in a scripted fashion, prompted fashion, or any combination thereof). Heavily inspired by sysinstall and even uses the same reserved words so that scripts are portable. Coded over months, tested continuously through- out, and reviewed several times. Some notes about the changes: - Move network-setting acquisition/validation routines to media/tcpip.subr - The options screen from sysinstall has been converted to a dialog menu - The "UFS" media choice is renamed to "Directory" to reflect how sysinstall treats the choice and a new [true] "UFS" media choice has been added that acts on real UFS partitions (such as external disks with disklabels). - Many more help files have been resurrected from sysinstall (I noticed that some of the content seems a bit dated; I gave them a once-over but they could really use an update). - A total of 10 media choices are presented (via mediaGetType) including: CD/DVD, FTP, FTP Passive, HTTP Proxy, Directory, NFS, DOS, UFS, Floppy, USB - Novel struct/device management layer for managing the issue of passing more information than can comfortably fit in an argument list. --- usr.sbin/bsdconfig/include/Makefile | 3 +- usr.sbin/bsdconfig/include/media.hlp | 48 + usr.sbin/bsdconfig/include/messages.subr | 214 ++- usr.sbin/bsdconfig/include/network_device.hlp | 58 + usr.sbin/bsdconfig/include/options.hlp | 98 + .../{networking => }/include/tcp.hlp | 0 usr.sbin/bsdconfig/networking/devices | 3 +- .../bsdconfig/networking/include/Makefile | 2 +- .../bsdconfig/networking/share/common.subr | 13 +- .../bsdconfig/networking/share/device.subr | 133 +- .../bsdconfig/networking/share/hostname.subr | 59 +- .../bsdconfig/networking/share/ipaddr.subr | 204 +- .../bsdconfig/networking/share/netmask.subr | 83 +- .../bsdconfig/networking/share/resolv.subr | 27 +- .../bsdconfig/networking/share/routing.subr | 22 +- usr.sbin/bsdconfig/share/Makefile | 6 +- usr.sbin/bsdconfig/share/common.subr | 42 +- usr.sbin/bsdconfig/share/device.subr | 799 ++++++++ usr.sbin/bsdconfig/share/media/Makefile | 13 + usr.sbin/bsdconfig/share/media/any.subr | 152 ++ usr.sbin/bsdconfig/share/media/cdrom.subr | 210 ++ usr.sbin/bsdconfig/share/media/common.subr | 109 ++ usr.sbin/bsdconfig/share/media/directory.subr | 146 ++ usr.sbin/bsdconfig/share/media/dos.subr | 164 ++ usr.sbin/bsdconfig/share/media/floppy.subr | 214 +++ usr.sbin/bsdconfig/share/media/ftp.subr | 893 +++++++++ usr.sbin/bsdconfig/share/media/httpproxy.subr | 433 +++++ usr.sbin/bsdconfig/share/media/network.subr | 182 ++ usr.sbin/bsdconfig/share/media/nfs.subr | 251 +++ usr.sbin/bsdconfig/share/media/options.subr | 308 +++ usr.sbin/bsdconfig/share/media/tcpip.subr | 1688 +++++++++++++++++ usr.sbin/bsdconfig/share/media/ufs.subr | 193 ++ usr.sbin/bsdconfig/share/media/usb.subr | 174 ++ usr.sbin/bsdconfig/share/script.subr | 33 +- usr.sbin/bsdconfig/share/strings.subr | 68 +- usr.sbin/bsdconfig/share/struct.subr | 206 ++ usr.sbin/bsdconfig/share/variable.subr | 68 +- 37 files changed, 6766 insertions(+), 553 deletions(-) create mode 100644 usr.sbin/bsdconfig/include/media.hlp create mode 100644 usr.sbin/bsdconfig/include/network_device.hlp create mode 100644 usr.sbin/bsdconfig/include/options.hlp rename usr.sbin/bsdconfig/{networking => }/include/tcp.hlp (100%) create mode 100644 usr.sbin/bsdconfig/share/device.subr create mode 100644 usr.sbin/bsdconfig/share/media/Makefile create mode 100644 usr.sbin/bsdconfig/share/media/any.subr create mode 100644 usr.sbin/bsdconfig/share/media/cdrom.subr create mode 100644 usr.sbin/bsdconfig/share/media/common.subr create mode 100644 usr.sbin/bsdconfig/share/media/directory.subr create mode 100644 usr.sbin/bsdconfig/share/media/dos.subr create mode 100644 usr.sbin/bsdconfig/share/media/floppy.subr create mode 100644 usr.sbin/bsdconfig/share/media/ftp.subr create mode 100644 usr.sbin/bsdconfig/share/media/httpproxy.subr create mode 100644 usr.sbin/bsdconfig/share/media/network.subr create mode 100644 usr.sbin/bsdconfig/share/media/nfs.subr create mode 100644 usr.sbin/bsdconfig/share/media/options.subr create mode 100644 usr.sbin/bsdconfig/share/media/tcpip.subr create mode 100644 usr.sbin/bsdconfig/share/media/ufs.subr create mode 100644 usr.sbin/bsdconfig/share/media/usb.subr create mode 100644 usr.sbin/bsdconfig/share/struct.subr diff --git a/usr.sbin/bsdconfig/include/Makefile b/usr.sbin/bsdconfig/include/Makefile index cb4b1b6ccc4..ee21cec562b 100644 --- a/usr.sbin/bsdconfig/include/Makefile +++ b/usr.sbin/bsdconfig/include/Makefile @@ -3,7 +3,8 @@ NO_OBJ= FILESDIR= ${LIBEXECDIR}/bsdconfig/include -FILES= bsdconfig.hlp messages.subr usage.hlp +FILES= bsdconfig.hlp media.hlp messages.subr network_device.hlp \ + options.hlp tcp.hlp usage.hlp beforeinstall: mkdir -p ${DESTDIR}${FILESDIR} diff --git a/usr.sbin/bsdconfig/include/media.hlp b/usr.sbin/bsdconfig/include/media.hlp new file mode 100644 index 00000000000..6df5b03dae7 --- /dev/null +++ b/usr.sbin/bsdconfig/include/media.hlp @@ -0,0 +1,48 @@ +You can install from the following types of media: + + CDROM requires one of the following supported CDROM drives: + ATAPI - Any standard ATAPI CDROM drive hooked to + a supported controller (see Hardware Guide). + SCSI - Any standard SCSI CDROM drive hooked to + a supported controller (see Hardware Guide). + + + DOS A DOS primary partition with the required FreeBSD + distribution files copied onto it (e.g. C:\FREEBSD\) + + + UFS Assuming a disk or partition with an existing + FreeBSD file system and distribution set on it, + get the distribution files from there. + + + Floppy Get distribution files from one or more DOS or UFS + formatted floppies. Such floppies are assumed to + contain the appropriate distribution pieces - see + ABOUT.TXT for more information about making floppy + distribution media. + + + FTP Get the distribution files from an anonymous ftp server + (you will be presented with a list). Please note that + you may invoke FTP in "Active" mode, "Passive" mode, or + via an HTTP proxy. + + Active mode is the standard way of fetching files and + Passive mode is for use when you're behind a firewall or + some other security mechanism that blocks active FTP + connections. Using an HTTP proxy is sometimes necessary + for firewalls which block all FTP connections. + + If you chose to enter your own URL in the FTP menu, please + note that all paths are *relative* to the home directory + of the user being logged in as. By default, this is the + user "ftp" (anonymous ftp) but you may change this in the + Options screen. + + + NFS Get the distribution files from an NFS server somewhere + (make sure that permissions on the server allow this!). + If this install method hangs on you or refuses to work + properly, you may need to set some special options for + your NFS server. See the Options screen for more details. diff --git a/usr.sbin/bsdconfig/include/messages.subr b/usr.sbin/bsdconfig/include/messages.subr index dc7c246a05d..82afb6daa1e 100644 --- a/usr.sbin/bsdconfig/include/messages.subr +++ b/usr.sbin/bsdconfig/include/messages.subr @@ -1,5 +1,5 @@ # Copyright (c) 2012 Ron McDowell -# Copyright (c) 2012 Devin Teske +# Copyright (c) 2012-2013 Devin Teske # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -27,39 +27,251 @@ field_username="Username:" field_password="Password:" +hline_alnum_arrows_punc_tab_enter="Use alnum, arrows, punctuation, TAB or ENTER" hline_alnum_punc_tab_enter="Use alpha-numeric, punctuation, TAB or ENTER" hline_arrows_tab_enter="Press arrows, TAB or ENTER" +hline_choose_help_for_more_information_on_media_types="Choose Help for more information on the various media types" +msg_accept_continue="Accept/Continue" msg_always_try_sudo_when_run_as="Always try sudo(8) when run as %s" +msg_argentina="Argentina" +msg_assume_network_is_already_configured="Running multi-user, assume that the network is already configured?" +msg_attempt_automatic_dhcp_configuration="Attempt automatic DHCP configuration of interfaces" +msg_attempt_ipv6_configuration_of_interfaces="Attempt IPv6 configuration of interfaces" +msg_australia="Australia" +msg_austria="Austria" msg_becoming_root_via_sudo="Becoming root via sudo(8)..." +msg_brazil="Brazil" +msg_canada="Canada" msg_cancel="Cancel" msg_cancel_exit="Cancel/Exit" msg_cannot_create_permission_denied="%s: cannot create %s: Permission denied" +msg_cannot_resolve_hostname="Cannot resolve \`%s'! Are you sure that your\nname server, gateway and network interface are correctly configured?" +msg_cant_find_distribution="Warning: Can't find the \`%s' distribution on this\nFTP server. You may need to visit a different server for\nthe release you are trying to fetch or go to the Options\nmenu and set the release name to explicitly match what's\navailable on %s (or set to \"any\").\n\nWould you like to select another FTP server?" +msg_cant_seem_to_write_out_resolv_conf="Can't seem to write out %s. Net cannot be used." +msg_cd_dvd="CD/DVD" +msg_cdrom="CDROM" +msg_checking_access_to="Checking access to\n %s" +msg_china="China" +msg_choose_a_cd_dvd_type="Choose a CD/DVD type" +msg_choose_a_dos_partition="Choose a DOS partition" +msg_choose_a_floppy_drive="Choose a Floppy drive" +msg_choose_a_ufs_partition="Choose a UFS partition" +msg_choose_a_usb_partition="Choose a USB drive" +msg_choose_installation_media="Choose Installation Media" +msg_choose_installation_media_description="FreeBSD can be installed from a variety of different installation\nmedia, ranging from floppies to an Internet FTP server. If you're\ninstalling FreeBSD from a supported CD/DVD drive then this is generally\nthe best media to use if you have no overriding reason for using other\nmedia." +msg_client_error="Client error, you could try an other server" msg_command_failed_rest_of_script_aborted="Command \`%s' failed - rest of script aborted." +msg_configuration_for_interface="Configuration for Interface" +msg_could_not_unmount_the_cdrom_dvd="Could not unmount the CDROM/DVD from %s: %s" +msg_could_not_unmount_the_dos_partition="Could not unmount the DOS partition from %s: %s" +msg_could_not_unmount_the_nfs_partition="Could not unmount the NFS partition from %s: %s" +msg_could_not_unmount_the_ufs_partition="Could not unmount the UFS partition from %s: %s" +msg_couldnt_connect_to_proxy="Couldn't connect to proxy" +msg_couldnt_connect_to_ftp_server="Couldn't connect to FTP server" +msg_couldnt_open_ftp_connection="Couldn't open FTP connection to %s:\n %s." msg_created_path="Created %s" +msg_croatia="Croatia" +msg_czech_republic="Czech Republic" +msg_debugging="Debugging" +msg_denmark="Denmark" +msg_device_is_not_configured="The %s device is not configured. You will need to do so\nin the Networking configuration menu before proceeding." +msg_dhcp="DHCP" +msg_dialog_mixedform_navigation_help="Use / arrows to navigate between fields, TAB to focus buttons, and Enter for OK/Cancel." +msg_directory="Directory" msg_directory_not_found="%s: Directory not found." +msg_done="Done" +msg_dos="DOS" +msg_editor="Editor" +msg_emit_extra_debugging_output="Emit extra debugging output" +msg_enter_a_fully_qualified_pathname_for_the_directory="Enter a fully qualified pathname for the directory\ncontaining the FreeBSD distribution files:" +msg_enter_the_device_name_of_a_ufs_formatted_partition="Enter the device-name of a UFS formatted partition" +msg_error="Error" +msg_error_mounting_device="Error mounting %s on %s: %s" +msg_error_mounting_floppy_device="Error mounting floppy %s (%s) on %s: %s" +msg_error_mounting_usb_drive="Error mounting USB drive %s on %s: %s" +msg_error_when_requesting_url="Error when requesting %s, you could try an other server" +msg_estonia="Estonia" msg_exit="Exit" msg_exit_bsdconfig="Exit bsdconfig" +msg_extra_options_to_ifconfig="Extra options to ifconfig (usually empty):" +msg_failed_to_add_default_route="Failed to add a default route; please check your network configuration" +msg_file_system="File System" +msg_finland="Finland" +msg_floppy="Floppy" +msg_france="France" +msg_ftp="FTP" +msg_ftp_passive="FTP Passive" +msg_ftp_username="FTP username" +msg_germany="Germany" +msg_greece="Greece" +msg_help="Help" +msg_host_name_including_domain="Host name (including domain)" +msg_hostname_variable_not_set="WARNING: hostname variable not set and is a non-optional\nparameter. Please add this to your installation script\nor set the netInteractive variable (see bsdconfig man page)" +msg_http="HTTP" +msg_http_proxy="HTTP Proxy" +msg_hungary="Hungary" +msg_iceland="Iceland" +msg_install_from_a_dos_partition="Install from a DOS partition" +msg_install_from_a_floppy_disk_set="Install from a floppy disk set" +msg_install_from_a_freebsd_cd_dvd="Install from a FreeBSD CD/DVD" +msg_install_from_a_usb_drive="Install from a USB drive" +msg_install_from_a_ufs_partition="Install from a UFS partition" +msg_install_from_an_ftp_server="Install from an FTP server" +msg_install_from_an_ftp_server_thru_firewall="Install from an FTP server through a firewall" +msg_install_from_an_ftp_server_thru_proxy="Install from an FTP server through an HTTP proxy" +msg_install_from_the_existing_filesystem="Install from the existing filesystem" +msg_install_over_nfs="Install over NFS" +msg_invalid_gateway_ipv4_address_specified="Invalid gateway IPv4 address specified" +msg_invalid_hostname_value="Invalid hostname value" +msg_invalid_ipv4_address="Invalid IPv4 address" +msg_invalid_name_server_ip_address_specified="Invalid name server IP address specified" +msg_invalid_netmask_value="Invalid netmask value" +msg_invalid_nfs_path_specification="Invalid NFS path specification. Must be of the form:\nhost:/full/pathname/to/FreeBSD/distdir" +msg_ipv4_address="IPv4 Address" +msg_ipv4_gateway="IPv4 Gateway" +msg_ipv6="IPv6" +msg_ipv6_ready="IPv6 ready" +msg_ireland="Ireland" +msg_israel="Israel" +msg_italy="Italy" +msg_japan="Japan" +msg_korea="Korea" +msg_lithuania="Lithuania" +msg_length_of_specified_url_is_too_long="Length of specified URL is %u characters. Allowable maximum is %u." +msg_logging_in_to_user_at_host="Logging in to %s@%s.." +msg_looking_up_host="Looking up host %s" msg_main_menu="Main Menu" +msg_main_site="Main Site" +msg_media_timeout="Media Timeout" +msg_media_type="Media Type" msg_menu_text="If you've already installed FreeBSD, you may use\nthis menu to customize it somewhat to suit your\nparticular configuration. Most importantly, you\ncan use the Packages utility to load extra '3rd\nparty' software not provided in the base\ndistributions." +msg_missing_ftp_host_or_directory="Missing FTP host or directory specification. FTP media not initialized." msg_must_be_root_to_execute="%s: must be root to execute" +msg_must_specify_a_host_name_of_some_sort="Must specify a host name of some sort!" +msg_name_server="Name server" +msg_net_device_init_failed="Net device init failed." +msg_netmask="Netmask" +msg_netherlands="Netherlands" +msg_network_configuration="Network Configuration" +msg_network_interface_information_required="Network interface information required" msg_nfailed_attempts="%u incorrect password attempts" +msg_nfs="NFS" +msg_nfs_secure="NFS Secure" +msg_nfs_server_talks_only_on_a_secure_port="NFS server talks only on a secure port" +msg_nfs_slow="NFS Slow" +msg_nfs_tcp="NFS TCP" +msg_nfs_version_3="NFS version 3" msg_no="No" +msg_no_cd_dvd_devices_found="No CD/DVD devices found! Please check that your system's\nconfiguration is correct and that the CD/DVD drive is of a\nsupported type. For more information, consult the hardware\nguide in the Doc menu." +msg_no_dos_primary_partitions_found="No DOS primary partitions found! This installation method is unavailable" +msg_no_floppy_devices_found="No floppy devices found! Please check that your system's configuration\nis correct. For more information, consult the hardware guide in the Doc\nmenu." +msg_no_gateway_has_been_set="No gateway has been set. You will be unable to access hosts\nnot on your local network" +msg_no_network_devices="No network devices available!" msg_no_such_file_or_directory="%s: %s: No such file or directory" +msg_no_usb_devices_found="No USB devices found (try Options/Re-scan Devices)" msg_no_username="No username provided!" +msg_norway="Norway" +msg_not_a_directory="%s: %s: Not a directory" msg_not_found="not found" +msg_not_yet_set="not yet set" msg_ok="OK" +msg_options="Options" +msg_options_editor="Options Editor" +msg_other="other" msg_permission_denied="%s: %s: Permission denied" +msg_please_check_the_url_and_try_again="No such directory: %s\nplease check the URL and try again." msg_please_enter_password="Please enter your password for sudo(8):" msg_please_enter_username_password="Please enter a username and password for sudo(8):" +msg_please_enter_the_address_of_the_http_proxy="Please enter the address of the HTTP proxy in this format:\n hostname:port (the ':port' is optional, default is 3128)" +msg_please_enter_the_full_nfs_file_specification="Please enter the full NFS file specification for the remote\nhost and directory containing the FreeBSD distribution files.\nThis should be in the format: hostname:/some/freebsd/dir" +msg_please_enter_the_password_for_this_user="Please enter the password for this user:" +msg_please_enter_the_username_you_wish_to_login_as="Please enter the username you wish to login as:" +msg_please_insert_floppy_in_drive="Please insert floppy in %s" +msg_please_insert_floppy_containing="Please insert floppy containing %s in %s" +msg_please_select_a_cd_dvd_drive="FreeBSD can be installed directly from a CD/DVD containing a valid\nFreeBSD distribution. If you are seeing this menu it is because\nmore than one CD/DVD drive was found on your system. Please select\none of the following CD/DVD drives as your installation drive." +msg_please_select_a_floppy_drive="You have more than one floppy drive. Please choose which drive\nyou would like to use." +msg_please_select_a_freebsd_ftp_distribution_site="Please select a FreeBSD FTP distribution site" +msg_please_select_dos_partition="FreeBSD can be installed directly from a DOS partition assuming,\nof course, that you have copied the relevant distributions into\nyour DOS partition before starting this installation. If this is\nnot the case then you should reboot DOS at this time and copy the\ndistributions you wish to install into a \"FREEBSD\" subdirectory\non one of your DOS partitions. Otherwise, please select the DOS\npartition containing the FreeBSD distribution files." +msg_please_select_ufs_partition="FreeBSD can be installed directly from another FreeBSD partition\nthat is UFS formatted assuming, of course, that you have copied\nthe relevant distributions into said partition before starting\ninstallation." +msg_please_select_a_usb_drive="You have more than one USB drive. Please choose which drive\nyou would like to use." +msg_please_select_ethernet_device_to_configure="Please select the ethernet or PLIP device to configure." +msg_please_select_the_site_closest_to_you_or_other="Please select the site closest to you or \"other\" if you'd like to\nspecify a different choice. Also note that not every site listed here\ncarries more than the base distribution kits. Only Primary sites are\nguaranteed to carry the full range of possible distributions." +msg_please_specify_the_name_of_the_text_editor="Please specify the name of the text editor you wish to use:" +msg_please_specify_the_number_of_seconds_to_wait="Please specify the number of seconds to wait for slow media:" +msg_please_specify_the_release_you_wish_to_load="Please specify the release you wish to load or\n\"any\" for a generic release install:" +msg_please_specify_url_of_a_freebsd_distribution="Please specify the URL of a FreeBSD distribution on a\nremote ftp site. This site must accept either anonymous\nftp or you should have set an ftp username and password\nin the Options screen.\n\nA URL looks like this: ftp:///\nWhere is relative to the anonymous ftp directory or the\nhome directory of the user being logged in as." +msg_poland="Poland" +msg_portugal="Portugal" msg_previous_syntax_errors="%s: Not overwriting \`%s' due to previous syntax errors" +msg_primary="Primary" +msg_probing_devices_please_wait_this_can_take_a_while="Probing devices, please wait (this can take a while)..." msg_quick_start_how_to_use_this_menu_system="Quick start - How to use this menu system" +msg_release_name="Release Name" +msg_rerun_bsdconfig_initial_device_probe="Re-run bsdconfig initial device probe" +msg_rescan_devices="Re-scan Devices" +msg_reset="RESET!" +msg_reset_all_values_to_startup_defaults="Reset all values to startup defaults" +msg_reuse_old_ftp_site_selection_values="Re-use old FTP site selection values?" +msg_romania="Romania" +msg_russia="Russia" +msg_scanning_for_dhcp_servers="Scanning for DHCP servers..." +msg_scanning_for_ra_servers="Scanning for RA servers..." msg_secure_mode_requires_x11="Secure-mode requires X11 (use \`-X')!" msg_secure_mode_requires_root="Secure-mode requires root-access!" +msg_select_a_site_thats_close="Select a site that's close!" +msg_server_error_when_requesting_url="Server error when requesting %s, you could try an other server" +msg_singapore="Singapore" +msg_slovak_republic="Slovak Republic" +msg_slovenia="Slovenia" +msg_snapshots_server_japan="Snapshots Server Japan" +msg_snapshots_server_sweden="Snapshots Server Sweden" +msg_sorry_invalid_url="Sorry, %s is an invalid URL!" msg_sorry_try_again="Sorry, try again." +msg_south_africa="South Africa" +msg_spain="Spain" +msg_specify_some_other_ftp_site="Specify some other ftp site by URL" +msg_sweden="Sweden" +msg_switzerland="Switzerland" +msg_taiwan="Taiwan" +msg_the_current_installation_media_type="The current installation media type." +msg_timeout_value_in_seconds_for_slow_media="Timeout value in seconds for slow media." +msg_try_dhcp_configuration="Do you want to try DHCP configuration of the interface?" +msg_try_ipv6_configuration="Do you want to try IPv6 configuration of the interface?" msg_try_sudo_only_this_once="Try sudo(8) only this once" +msg_turkey="Turkey" +msg_ufs="UFS" +msg_uk="UK" +msg_ukraine="Ukraine" +msg_unable_to_configure_device="Unable to configure the %s interface!\nThis installation method cannot be used." +msg_unable_to_get_proper_ftp_path="Unable to get proper FTP path. FTP media not initialized." +msg_unable_to_make_directory_mountpoint="Unable to make %s directory mountpoint for %s!" msg_unable_to_open="Unable to open %s" +msg_unknown="unknown" msg_unknown_user="Unknown user: %s" +msg_url_was_not_found="%s was not found, maybe directory or release-version are wrong?" +msg_usa="USA" msg_usage="Usage" +msg_usb="USB" +msg_use_defaults="Use Defaults" +msg_use_nfs_version_3="Use NFS version 3" +msg_use_tcp_protocol_for_nfs="Use TCP protocol for NFS" msg_user_disallowed="User disallowed: %s" +msg_user_is_using_a_slow_pc_or_ethernet_card="User is using a slow PC or Ethernet card" +msg_username_and_password_to_use="Username and password to use instead of anonymous" +msg_using_interface="Using interface %s" +msg_using_usb_device="Using USB device: %s" +msg_view_set_various_media_options="View/Set various media options" +msg_which_release_to_attempt_to_load="Which release to attempt to load from installation media" +msg_which_text_editor_to_use="Which text editor to use during installation" +msg_would_you_like_to_bring_interface_up="Would you like to bring the %s interface up right now?" msg_yes="Yes" msg_you_are_not_root_but="You are not root but %s can use sudo(8).\nWhat would you like to do?" +msg_you_may_remove_the_floppy="You may remove the floppy from %s" +msg_youve_already_done_the_network_configuration="You've already done the network configuration once,\nwould you like to skip over it now?" +tcplayout_extras_help="Any interface-specific options to ifconfig you would like to add" +tcplayout_extras_help_for_plip="For PLIP configuration, you must enter the peer's IP address here." +tcplayout_gateway_help="IPv4 address of host forwarding packets to non-local destinations" +tcplayout_hostname_help="Your fully-qualified hostname, e.g. foo.example.com" +tcplayout_ipaddr_help="The IPv4 address to be used for this interface" +tcplayout_nameserver_help="IPv4 or IPv6 address of your local DNS server" +tcplayout_netmask_help="The netmask for this interface, e.g. 255.255.255.0 for a class C network" diff --git a/usr.sbin/bsdconfig/include/network_device.hlp b/usr.sbin/bsdconfig/include/network_device.hlp new file mode 100644 index 00000000000..affa86a91ec --- /dev/null +++ b/usr.sbin/bsdconfig/include/network_device.hlp @@ -0,0 +1,58 @@ +You can do network installations over 3 types of communications links: + + Serial port: SLIP / PPP + Parallel port: PLIP (laplink cable) + Ethernet: A standard Ethernet controller (includes some + PCMCIA networking cards). + +SLIP support is rather primitive and limited primarily to directly +connected links, such as a serial cable running between a laptop +computer and another PC. The link must be hard-wired as the SLIP +installation doesn't currently offer a dialing capability (that +facility is offered by the PPP utility, which should be used in +preference to SLIP whenever possible). When you choose the SLIP +option, you'll be given the option of later editing the slattach +command before it's run on the serial line. It is expected that +you'll run slattach (or some equivalent command) on the other end of +the link at that time and bring up the line. FreeBSD will then +install itself at serial speeds of up to 115.2K/baud (the recommended +speed for a hardwired cable). + +If you're using a modem then PPP is almost certainly your only choice. +Make sure that you have your service provider's information handy as +you'll need to know it fairly early in the installation process. You +will need to know your service provider's IP address, the IP address +of your provider's DNS server, and possibly your own IP address unless +your ISP supports dynamic negotiation, most do. If you do not choose +a PAP or CHAP login you will also need to know how to use the various +"AT commands" to dial the ISP with your particular brand of modem as +the PPP dialer provides only a very simple terminal emulator and has no +"modem capabilities database". If you choose a PAP or CHAP login you +can simply enter `dial' (without the quotes) at the ppp prompt if your +modem uses the Hayes compatible AT command set. + +If a hard-wired connection to another FreeBSD (2.0R or later) machine +is available, you might also consider installing over a "laplink" +parallel port cable. The data rate over the parallel port is much +higher than what is typically possible over a serial line, and speeds +of over 50KB/sec are not uncommon. + +Finally, for the fastest possible network installation, an Ethernet +adaptor is always a good choice! FreeBSD supports most common PC +Ethernet cards, a table of which is provided in the FreeBSD Hardware +Guide (see the `Documentation' entry in the main menu). If you are +using one of the supported PCMCIA Ethernet cards, also be sure that +it's plugged in BEFORE the laptop is powered on! Sysinstall does not, +unfortunately, currently support "hot insertion" of PCMCIA cards. + +You will also need to know your IP address on the network, the +"netmask" value for your address class, and the name of your machine. +Your system administrator can tell you which values to use for your +particular network setup. If you will be referring to other hosts by +name rather than IP address, you'll also need a name server and +possibly the address of a gateway (if you're using PPP, it's your +provider's IP address) to use in talking to it. If you do not know +the answers to all or most of these questions then you should really +probably talk to your system administrator FIRST before trying this +type of installation! Choosing the wrong IP address on a busy network +will NOT make you popular with your systems administrator! :-) diff --git a/usr.sbin/bsdconfig/include/options.hlp b/usr.sbin/bsdconfig/include/options.hlp new file mode 100644 index 00000000000..674e48d4ba7 --- /dev/null +++ b/usr.sbin/bsdconfig/include/options.hlp @@ -0,0 +1,98 @@ +The following options may be set from this screen. + +NFS Secure: NFS server talks only on a secure port + + This is most commonly used when talking to Sun workstations, which + will not talk NFS over "non privileged" ports. + + +NFS Slow: User is using a slow PC or Ethernet card + + Use this option if you have a slow PC (386) or an Ethernet card + with poor performance being "fed" by NFS on a higher-performance + workstation. This will throttle the workstation back to prevent + the PC from becoming swamped with data. + + +NFS TCP: Use TCP for the NFS mount + + This option can be used if your NFS server supports TCP + connections; not all do! This may be useful if your NFS server + is at a remote site in which case it may offer some additional + stability. + + +NFS version 3: Use NFS version 3 + + This option forces the use of NFS version 3 and is on by default. + If your NFS server only supports NFS version 2, disable this option. + + +Debugging: Turn on the extra debugging flag + + This turns on a lot of extra noise in between dialogs (unless + debugFile has been set, sending the data to a logfile instead). + Optionally, if debugFile begins with a plus sign (`+'), output will + occur both on standard output and to debugFile (minus leading plus). + If your installation should fail for any reason, PLEASE turn this + flag on when attempting to reproduce the problem. It will provide a + lot of extra debugging at the failure point and may be very helpful + to the developers in tracking such problems down! + + +DHCP: Enable DHCP configuration of interfaces + + This option specifies whether DHCP configuration of interfaces + may be attempted. The default setting is to interactively ask + the user. + + +IPv6: Enable IPv6 router solicitation configuration + + This option specifies whether automatic configuration of IPv6 + interfaces may be attempted. This uses the router solicitation + method of automatic configuration. The default setting is to + interactively ask the user. + + +FTP username: Specify username and password instead of anonymous. + + By default, the installation attempts to log in as the + anonymous user. If you wish to log in as someone else, + specify the username and password with this option. + + +Editor: Specify which screen editor to use. + + At various points during the installation it may be necessary + to customize some text file, at which point the user will be + thrown unceremoniously into a screen editor. A relatively + simplistic editor which shows its command set on-screen is + selected by default, but UNIX purists may wish to change this + setting to `/usr/bin/vi'. + + +Release Name: Which release to attempt to load from installation media. + + You should only change this option if you're really sure you know + what you are doing! This will change the release name used by + bsdconfig when fetching components of any distributions, and + is a useful way of using a more recent installation boot floppy + with an older release (say, on CDROM). + + +Media Type: Which media type is being used. + + This is mostly informational and indicates which media type (if any) + was last selected in the Media menu. It's also a convenient short-cut + to the media menu itself. + + +Re-scan Devices: + + Reprobe the system for devices. + + +Use Defaults: Use default values. + + Reset all options back to their default values. diff --git a/usr.sbin/bsdconfig/networking/include/tcp.hlp b/usr.sbin/bsdconfig/include/tcp.hlp similarity index 100% rename from usr.sbin/bsdconfig/networking/include/tcp.hlp rename to usr.sbin/bsdconfig/include/tcp.hlp diff --git a/usr.sbin/bsdconfig/networking/devices b/usr.sbin/bsdconfig/networking/devices index 443294f2f8e..f9c27b497e6 100755 --- a/usr.sbin/bsdconfig/networking/devices +++ b/usr.sbin/bsdconfig/networking/devices @@ -1,6 +1,6 @@ #!/bin/sh #- -# Copyright (c) 2006-2012 Devin Teske +# Copyright (c) 2006-2013 Devin Teske # All Rights Reserved. # # Redistribution and use in source and binary forms, with or without @@ -34,6 +34,7 @@ f_dprintf "%s: loading includes..." "$0" f_include $BSDCFG_SHARE/dialog.subr f_include $BSDCFG_SHARE/mustberoot.subr f_include $BSDCFG_SHARE/sysrc.subr +f_include $BSDCFG_SHARE/media/tcpip.subr f_include $BSDCFG_SHARE/networking/device.subr f_include $BSDCFG_SHARE/networking/ipaddr.subr f_include $BSDCFG_SHARE/networking/media.subr diff --git a/usr.sbin/bsdconfig/networking/include/Makefile b/usr.sbin/bsdconfig/networking/include/Makefile index be6cacb5b2f..c93d4866fe9 100644 --- a/usr.sbin/bsdconfig/networking/include/Makefile +++ b/usr.sbin/bsdconfig/networking/include/Makefile @@ -3,7 +3,7 @@ NO_OBJ= FILESDIR= ${LIBEXECDIR}/bsdconfig/120.networking/include -FILES= messages.subr tcp.hlp +FILES= messages.subr beforeinstall: mkdir -p ${DESTDIR}${FILESDIR} diff --git a/usr.sbin/bsdconfig/networking/share/common.subr b/usr.sbin/bsdconfig/networking/share/common.subr index e501a9c7561..1a37a9c3536 100644 --- a/usr.sbin/bsdconfig/networking/share/common.subr +++ b/usr.sbin/bsdconfig/networking/share/common.subr @@ -1,6 +1,6 @@ if [ ! "$_NETWORKING_COMMON_SUBR" ]; then _NETWORKING_COMMON_SUBR=1 # -# Copyright (c) 2006-2012 Devin Teske +# Copyright (c) 2006-2013 Devin Teske # All Rights Reserved. # # Redistribution and use in source and binary forms, with or without @@ -33,17 +33,6 @@ BSDCFG_SHARE="/usr/share/bsdconfig" ############################################################ FUNCTIONS -# f_mounted $local_directory -# -# Return success if a filesystem is mounted on a particular directory. -# -f_mounted() -{ - local dir="$1" - [ -d "$dir" ] || return $FAILURE - mount | grep -Eq " on $dir \([^)]+\)$" -} - # f_jailed # # Returns true if the current process is jail(8)ed. diff --git a/usr.sbin/bsdconfig/networking/share/device.subr b/usr.sbin/bsdconfig/networking/share/device.subr index 23ac83b3f23..cac8ef54753 100644 --- a/usr.sbin/bsdconfig/networking/share/device.subr +++ b/usr.sbin/bsdconfig/networking/share/device.subr @@ -1,6 +1,6 @@ if [ ! "$_NETWORKING_DEVICE_SUBR" ]; then _NETWORKING_DEVICE_SUBR=1 # -# Copyright (c) 2006-2012 Devin Teske +# Copyright (c) 2006-2013 Devin Teske # All Rights Reserved. # # Redistribution and use in source and binary forms, with or without @@ -31,8 +31,10 @@ if [ ! "$_NETWORKING_DEVICE_SUBR" ]; then _NETWORKING_DEVICE_SUBR=1 BSDCFG_SHARE="/usr/share/bsdconfig" . $BSDCFG_SHARE/common.subr || exit 1 f_dprintf "%s: loading includes..." networking/device.subr +f_include $BSDCFG_SHARE/device.subr f_include $BSDCFG_SHARE/dialog.subr f_include $BSDCFG_SHARE/sysrc.subr +f_include $BSDCFG_SHARE/media/tcpip.subr f_include $BSDCFG_SHARE/networking/common.subr f_include $BSDCFG_SHARE/networking/ipaddr.subr f_include $BSDCFG_SHARE/networking/media.subr @@ -43,8 +45,6 @@ f_include $BSDCFG_SHARE/networking/routing.subr BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="120.networking" f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr -TCP_HELPFILE=$BSDCFG_LIBE/$APP_DIR/include/tcp.hlp - ############################################################ GLOBALS # @@ -55,133 +55,6 @@ TCP_HELPFILE=$BSDCFG_LIBE/$APP_DIR/include/tcp.hlp ############################################################ FUNCTIONS -# f_device_desc $device_name -# -# Print a description for a device name (eg., `fxp0'). -# -f_device_desc() -{ - local device="$1" d="[1234567890]" desc="" - - # Check variables - [ "$device" ] || return $SUCCESS - - # - # Return sysctl MIB dev.NAME.UNIT.%desc if it exists, - # otherwise fall through to below static list. - # - if f_have sysctl; then - local devname devunit - devname="${device%%$d*}" - devunit="${device#$devname}" - devunit="${devunit%%[a-zA-Z_]*}" - sysctl -n "dev.$devname.$devunit.%desc" 2> /dev/null && - return $SUCCESS - fi - - case "$device" in - # Network devices - ae$d) desc="Attansic/Atheros L2 Fast Ethernet";; - age$d) desc="Attansic/Atheros L1 Gigabit Ethernet";; - alc$d) desc="Atheros AR8131/AR8132 PCIe Ethernet";; - ale$d) desc="Atheros AR8121/AR8113/AR8114 PCIe Ethernet";; - an$d) desc="Aironet 4500/4800 802.11 wireless adapter";; - ath$d) desc="Atheros IEEE 802.11 wireless adapter";; - aue$d) desc="ADMtek USB Ethernet adapter";; - axe$d) desc="ASIX Electronics USB Ethernet adapter";; - bce$d) desc="Broadcom NetXtreme II Gigabit Ethernet card";; - bfe$d) desc="Broadcom BCM440x PCI Ethernet card";; - bge$d) desc="Broadcom BCM570x PCI Gigabit Ethernet card";; - bm$d) desc="Apple BMAC Built-in Ethernet";; - bwn$d) desc="Broadcom BCM43xx IEEE 802.11 wireless adapter";; - cas$d) desc="Sun Cassini/Cassini+ or NS DP83065 Saturn Ethernet";; - cc3i$d) desc="SDL HSSI sync serial PCI card";; - cue$d) desc="CATC USB Ethernet adapter";; - cxgb$d) desc="Chelsio T3 10Gb Ethernet card";; - dc$d) desc="DEC/Intel 21143 (and clones) PCI Fast Ethernet card";; - de$d) desc="DEC DE435 PCI NIC or other DC21040-AA based card";; - disc$d) desc="Software discard network interface";; - ed$d) desc="Novell NE1000/2000; 3C503; NE2000-compatible PCMCIA";; - el$d) desc="3Com 3C501 Ethernet card";; - em$d) desc="Intel(R) PRO/1000 Ethernet card";; - en$d) desc="Efficient Networks ATM PCI card";; - ep$d) desc="3Com 3C509 Ethernet card/3C589 PCMCIA";; - et$d) desc="Agere ET1310 based PCI Express Gigabit Ethernet card";; - ex$d) desc="Intel EtherExpress Pro/10 Ethernet card";; - fe$d) desc="Fujitsu MB86960A/MB86965A Ethernet card";; - fpa$d) desc="DEC DEFPA PCI FDDI card";; - fwe$d) desc="FireWire Ethernet emulation";; - fwip$d) desc="IP over FireWire";; - fxp$d) desc="Intel EtherExpress Pro/100B PCI Fast Ethernet card";; - gem$d) desc="Apple GMAC or Sun ERI/GEM Ethernet adapter";; - hme$d) desc="Sun HME (Happy Meal Ethernet) Ethernet adapter";; - ie$d) desc="AT&T StarLAN 10 and EN100; 3Com 3C507; NI5210";; - igb$d) desc="Intel(R) PRO/1000 PCI Express Gigabit Ethernet card";; - ipw$d) desc="Intel PRO/Wireless 2100 IEEE 802.11 adapter";; - iwi$d) desc="Intel PRO/Wireless 2200BG/2225BG/2915ABG adapter";; - iwn$d) desc="Intel Wireless WiFi Link 4965AGN IEEE 802.11n adapter";; - ix$d) desc="Intel Etherexpress Ethernet card";; - ixgb$d) desc="Intel(R) PRO/10Gb Ethernet card";; - ixgbe$d) desc="Intel(R) PRO/10Gb Ethernet card";; - jme$d) desc="JMicron JMC250 Gigabit/JMC260 Fast Ethernet";; - kue$d) desc="Kawasaki LSI USB Ethernet adapter";; - le$d) desc="AMD Am7900 LANCE or Am79C9xx PCnet Ethernet adapter";; - lge$d) desc="Level 1 LXT1001 Gigabit Ethernet card";; - lnc$d) desc="Lance/PCnet (Isolan/Novell NE2100/NE32-VL) Ethernet";; - lp$d) desc="Parallel Port IP (PLIP) peer connection";; - lo$d) desc="Loop-back (local) network interface";; - malo$d) desc="Marvell Libertas 88W8335 802.11 wireless adapter";; - msk$d) desc="Marvell/SysKonnect Yukon II Gigabit Ethernet";; - mxge$d) desc="Myricom Myri10GE 10Gb Ethernet card";; - nfe$d) desc="NVIDIA nForce MCP Ethernet";; - ng${d}_*|ng$d${d}_*|ng$d$d${d}_*|ng$d$d$d${d}_*|ng$d$d$d$d${d}_*) - desc="Vimage netgraph(4) bridged Ethernet device";; - nge$d) desc="NatSemi PCI Gigabit Ethernet card";; - nve$d) desc="NVIDIA nForce MCP Ethernet";; - nxge$d) desc="Neterion Xframe 10GbE Server/Storage adapter";; - pcn$d) desc="AMD Am79c79x PCI Ethernet card";; - plip$d) desc="Parallel Port IP (PLIP) peer connection";; - ral$d) desc="Ralink Technology IEEE 802.11 wireless adapter";; - ray$d) desc="Raytheon Raylink 802.11 wireless adapter";; - re$d) desc="RealTek 8139C+/8169/8169S/8110S PCI Ethernet adapter";; - rl$d) desc="RealTek 8129/8139 PCI Ethernet card";; - rue$d) desc="RealTek USB Ethernet card";; - rum$d) desc="Ralink Technology USB IEEE 802.11 wireless adapter";; - sf$d) desc="Adaptec AIC-6915 PCI Ethernet card";; - sge$d) desc="Silicon Integrated Systems SiS190/191 Ethernet";; - sis$d) desc="SiS 900/SiS 7016 PCI Ethernet card";; - sk$d) desc="SysKonnect PCI Gigabit Ethernet card";; - sn$d) desc="SMC/Megahertz Ethernet card";; - snc$d) desc="SONIC Ethernet card";; - sr$d) desc="SDL T1/E1 sync serial PCI card";; - ste$d) desc="Sundance ST201 PCI Ethernet card";; - stge$d) desc="Sundance/Tamarack TC9021 Gigabit Ethernet";; - ti$d) desc="Alteon Networks PCI Gigabit Ethernet card";; - tl$d) desc="Texas Instruments ThunderLAN PCI Ethernet card";; - tx$d) desc="SMC 9432TX Ethernet card";; - txp$d) desc="3Com 3cR990 Ethernet card";; - uath$d) desc="Atheros AR5005UG and AR5005UX USB wireless adapter";; - upgt$d) desc="Conexant/Intersil PrismGT USB wireless adapter";; - ural$d) desc="Ralink Technology RT2500USB 802.11 wireless adapter";; - urtw$d) desc="Realtek 8187L USB wireless adapter";; - vge$d) desc="VIA VT612x PCI Gigabit Ethernet card";; - vlan$d|vlan$d$d|vlan$d$d$d|vlan$d$d$d$d|vlan$d$d$d$d$d) - desc="IEEE 802.1Q VLAN network interface";; - vr$d) desc="VIA VT3043/VT86C100A Rhine PCI Ethernet card";; - vx$d) desc="3COM 3c590 / 3c595 Ethernet card";; - wb$d) desc="Winbond W89C840F PCI Ethernet card";; - wi$d) desc="Lucent WaveLAN/IEEE 802.11 wireless adapter";; - wpi$d) desc="Intel 3945ABG IEEE 802.11 wireless adapter";; - wx$d) desc="Intel Gigabit Ethernet (82452) card";; - xe$d) desc="Xircom/Intel EtherExpress Pro100/16 Ethernet card";; - xl$d) desc="3COM 3c90x / 3c90xB PCI Ethernet card";; - zyd$d) desc="ZyDAS ZD1211/ZD1211B USB 802.11 wireless adapter";; - # Unknown device - *) desc="";; - esac - printf "%s\n" "$desc" -} - # f_dialog_menu_netdev # # Display a list of network devices with descriptions. diff --git a/usr.sbin/bsdconfig/networking/share/hostname.subr b/usr.sbin/bsdconfig/networking/share/hostname.subr index b2760597e2c..61df2b4b0e7 100644 --- a/usr.sbin/bsdconfig/networking/share/hostname.subr +++ b/usr.sbin/bsdconfig/networking/share/hostname.subr @@ -1,6 +1,6 @@ if [ ! "$_NETWORKING_HOSTNAME_SUBR" ]; then _NETWORKING_HOSTNAME_SUBR=1 # -# Copyright (c) 2006-2012 Devin Teske +# Copyright (c) 2006-2013 Devin Teske # All Rights Reserved. # # Redistribution and use in source and binary forms, with or without @@ -41,63 +41,6 @@ f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr ############################################################ FUNCTIONS -# f_validate_hostname $hostname -# -# Returns zero if the given argument (a fully-qualified hostname) is compliant -# with standards set-forth in RFC's 952 and 1123 of the Network Working Group: -# -# RFC 952 - DoD Internet host table specification -# http://tools.ietf.org/html/rfc952 -# -# RFC 1123 - Requirements for Internet Hosts - Application and Support -# http://tools.ietf.org/html/rfc1123 -# -# See http://en.wikipedia.org/wiki/Hostname for a brief overview. -# -# The return status for invalid hostnames is one of: -# 255 Entire hostname exceeds the maximum length of 255 characters. -# 63 One or more individual labels within the hostname (separated by -# dots) exceeds the maximum of 63 characters. -# 1 One or more individual labels within the hostname contains one -# or more invalid characters. -# 2 One or more individual labels within the hostname starts or -# ends with a hyphen (hyphens are allowed, but a label cannot -# begin or end with a hyphen). -# 3 One or more individual labels within the hostname are null. -# -# If the hostname is determined to be invalid, the appropriate error will be -# displayed using the f_show_msg function. -# -f_validate_hostname() -{ - local fqhn="$1" - - ( # Operate within a sub-shell to protect the parent environment - - # Return error if the hostname exceeds 255 characters - [ ${#fqhn} -gt 255 ] && exit 255 - - IFS="." # Split on `dot' - for label in $fqhn; do - - # Return error if the label exceeds 63 characters - [ ${#label} -gt 63 ] && exit 63 - - # Return error if the label is null - [ "$label" ] || exit 3 - - # Return error if label begins/ends with dash - case "$label" in - -*|*-) exit 2 - esac - - # Return error if the label contains any invalid chars - echo "$label" | grep -q '^[[:alnum:]-]*$' || exit 1 - - done - ) -} - # f_dialog_hnerror $error $hostname # # Display a msgbox with the appropriate error message for an error returned by diff --git a/usr.sbin/bsdconfig/networking/share/ipaddr.subr b/usr.sbin/bsdconfig/networking/share/ipaddr.subr index d5398e54cc4..4b39dd23be3 100644 --- a/usr.sbin/bsdconfig/networking/share/ipaddr.subr +++ b/usr.sbin/bsdconfig/networking/share/ipaddr.subr @@ -1,6 +1,6 @@ if [ ! "$_NETWORKING_IPADDR_SUBR" ]; then _NETWORKING_IPADDR_SUBR=1 # -# Copyright (c) 2006-2012 Devin Teske +# Copyright (c) 2006-2013 Devin Teske # All Rights Reserved. # # Redistribution and use in source and binary forms, with or without @@ -40,75 +40,10 @@ f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr ############################################################ FUNCTIONS -# f_ifconfig_inet $interface -# -# Returns the IPv4 address associated with $interface. -# -f_ifconfig_inet() -{ - local interface="$1" - ifconfig "$interface" 2> /dev/null | awk \ - ' - BEGIN { found = 0 } - ( $1 == "inet" ) \ - { - print $2 - found = 1 - exit - } - END { exit ! found } - ' -} - -# f_validate_ipaddr $ipaddr -# -# Returns zero if the given argument (an IP address) is of the proper format. -# -# The return status for invalid IP address is one of: -# 1 One or more individual octets within the IP address (separated -# by dots) contains one or more invalid characters. -# 2 One or more individual octets within the IP address are null -# and/or missing. -# 3 One or more individual octets within the IP address exceeds the -# maximum of 255 (or 2^8, being an octet comprised of 8 bits). -# 4 The IP address has either too few or too many octets. -# -f_validate_ipaddr() -{ - local ip="$1" - - ( # Operate within a sub-shell to protect the parent environment - - # Track number of octets for error checking - noctets=0 - - IFS="." # Split on `dot' - for octet in $ip; do - - # Return error if the octet is null - [ "$octet" ] || exit 2 - - # Return error if not a whole integer - f_isinteger "$octet" || exit 1 - - # Return error if not a positive integer - [ $octet -ge 0 ] || exit 1 - - # Return error if the octet exceeds 255 - [ $octet -gt 255 ] && exit 3 - - noctets=$(( $noctets + 1 )) - - done - - [ $noctets -eq 4 ] || exit 4 - ) -} - # f_dialog_iperror $error $ipaddr # # Display a msgbox with the appropriate error message for an error returned by -# the f_validate_ipaddr function above. +# the f_validate_ipaddr function. # f_dialog_iperror() { @@ -144,141 +79,6 @@ f_dialog_validate_ipaddr() return $retval } -# f_validate_ipaddr6 $ipv6_addr -# -# Returns zero if the given argument (an IPv6 address) is of the proper format. -# -# The return status for invalid IP address is one of: -# 1 One or more individual segments within the IP address -# (separated by colons) contains one or more invalid characters. -# Segments must contain only combinations of the characters 0-9, -# A-F, or a-f. -# 2 Too many/incorrect null segments. A single null segment is -# allowed within the IP address (separated by colons) but not -# allowed at the beginning or end (unless a double-null segment; -# i.e., "::*" or "*::"). -# 3 One or more individual segments within the IP address -# (separated by colons) exceeds the length of 4 hex-digits. -# 4 The IP address entered has either too few (less than 3), too -# many (more than 8), or not enough segments, separated by -# colons. -# 5* The IPv4 address at the end of the IPv6 address is invalid. -# * When there is an error with the dotted-quad IPv4 address at the -# end of the IPv6 address, the return value of 5 is OR'd with a -# bit-shifted (<< 4) return of f_validate_ipaddr. -# -f_validate_ipaddr6() -{ - local ip="$1" - - ( # Operate within a sub-shell to protect the parent environment - - IFS=":" # Split on `colon' - set -- $ip: - - # Return error if too many or too few segments - # Using 9 as max in case of leading or trailing null spanner - [ $# -gt 9 -o $# -lt 3 ] && exit 4 - - h="[0-9A-Fa-f]" - nulls=0 - nsegments=$# - contains_ipv4_segment= - - while [ $# -gt 0 ]; do - - segment="${1%:}" - shift - - # - # Return error if this segment makes one null too-many. - # A single null segment is allowed anywhere in the - # middle as well as double null segments are allowed at - # the beginning or end (but not both). - # - if [ ! "$segment" ]; then - nulls=$(( $nulls + 1 )) - if [ $nulls -eq 3 ]; then - # Only valid syntax for 3 nulls is `::' - [ "$ip" = "::" ] || exit 2 - elif [ $nulls -eq 2 ]; then - # Only valid if begins/ends with `::' - case "$ip" in - ::*|*::) : fall thru ;; - *) exit 2 - esac - fi - continue - fi - - # - # Return error if not a valid hexadecimal short - # - case "$segment" in - $h|$h$h|$h$h$h|$h$h$h$h) - : valid segment of 1-4 hexadecimal digits - ;; - *[!0-9A-Fa-f]*) - # Segment contains at least one invalid char - - # Return error immediately if not last segment - [ $# -eq 0 ] || exit 1 - - # Otherwise, check for legacy IPv4 notation - case "$segment" in - *[!0-9.]*) - # Segment contains at least one invalid - # character even for an IPv4 address - exit 1 - esac - - # Return error if not enough segments - if [ $nulls -eq 0 ]; then - [ $nsegments -eq 7 ] || exit 4 - fi - - contains_ipv4_segment=1 - - # Validate the IPv4 address - f_validate_ipaddr "$segment" || - exit $(( 5 | $? << 4 )) - ;; - *) - # Segment characters are all valid but too many - exit 3 - esac - - done - - if [ $nulls -eq 1 ]; then - # Single null segment cannot be at beginning/end - case "$ip" in - :*|*:) exit 2 - esac - fi - - # - # A legacy IPv4 address can span the last two 16-bit segments, - # reducing the amount of maximum allowable segments by-one. - # - maxsegments=8 - if [ "$contains_ipv4_segment" ]; then - maxsegments=7 - fi - - case $nulls in - # Return error if missing segments with no null spanner - 0) [ $nsegments -eq $maxsegments ] || exit 4 ;; - # Return error if null spanner with too many segments - 1) [ $nsegments -le $maxsegments ] || exit 4 ;; - # Return error if leading/trailing `::' with too many segments - 2) [ $nsegments -le $(( $maxsegments + 1 )) ] || exit 4 ;; - esac - - exit $SUCCESS - ) -} - # f_dialog_ip6error $error $ipv6_addr # # Display a msgbox with the appropriate error message for an error returned by diff --git a/usr.sbin/bsdconfig/networking/share/netmask.subr b/usr.sbin/bsdconfig/networking/share/netmask.subr index 3a8665de59b..e6838e52c0f 100644 --- a/usr.sbin/bsdconfig/networking/share/netmask.subr +++ b/usr.sbin/bsdconfig/networking/share/netmask.subr @@ -1,6 +1,6 @@ if [ ! "$_NETWORKING_NETMASK_SUBR" ]; then _NETWORKING_NETMASK_SUBR=1 # -# Copyright (c) 2006-2012 Devin Teske +# Copyright (c) 2006-2013 Devin Teske # All Rights Reserved. # # Redistribution and use in source and binary forms, with or without @@ -40,87 +40,6 @@ f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr ############################################################ FUNCTIONS -# f_ifconfig_netmask $interface -# -# Returns the IPv4 subnet mask associated with $interface. -# -f_ifconfig_netmask() -{ - local interface="$1" octets - octets=$( ifconfig "$interface" 2> /dev/null | awk \ - ' - BEGIN { found = 0 } - ( $1 == "inet" ) \ - { - printf "%s %s %s %s\n", - substr($4,3,2), - substr($4,5,2), - substr($4,7,2), - substr($4,9,2) - found = 1 - exit - } - END { exit ! found } - ' ) || return $FAILURE - - local octet netmask= - for octet in $octets; do - netmask="$netmask${netmask:+.}$( printf "%u" "0x$octet" )" - done - echo $netmask -} - -# f_validate_netmask $netmask -# -# Returns zero if the given argument (a subnet mask) is of the proper format. -# -# The return status for invalid IP address is one of: -# 1 One or more individual fields within the subnet mask (separated -# by dots) contains one or more invalid characters. -# 2 One or more individual fields within the subnet mask are null -# and/or missing. -# 3 One or more individual fields within the subnet mask exceeds -# the maximum of 255 (a full 8-bit register). -# 4 The subnet mask has either too few or too many fields. -# 5 One or more individual fields within the subnet mask is an -# invalid integer (only 0,128,192,224,240,248,252,254,255 are -# valid integers). -# -f_validate_netmask() -{ - local mask="$1" - - ( # Operate within a sub-shell to protect the parent environment - - # Track number of fields for error checking - nfields=0 - - IFS="." # Split on `dot' - for field in $mask; do - - # Return error if the field is null - [ "$field" ] || exit 2 - - # Return error if not a whole positive integer - f_isinteger "$field" || exit 1 - - # Return error if the field exceeds 255 - [ $field -gt 255 ] && exit 3 - - # Return error if the field is an invalid integer - case "$field" in - 0|128|192|224|240|248|252|254|255) :;; - *) exit 5;; - esac - - nfields=$(( $nfields + 1 )) - - done - - [ $nfields -eq 4 ] || exit 4 - ) -} - # f_dialog_maskerror $error $netmask # # Display a msgbox with the appropriate error message for an error returned by diff --git a/usr.sbin/bsdconfig/networking/share/resolv.subr b/usr.sbin/bsdconfig/networking/share/resolv.subr index 7d9af3b9545..b525a4d80f6 100644 --- a/usr.sbin/bsdconfig/networking/share/resolv.subr +++ b/usr.sbin/bsdconfig/networking/share/resolv.subr @@ -1,6 +1,6 @@ if [ ! "$_NETWORKING_RESOLV_SUBR" ]; then _NETWORKING_RESOLV_SUBR=1 # -# Copyright (c) 2006-2012 Devin Teske +# Copyright (c) 2006-2013 Devin Teske # All Rights Reserved. # # Redistribution and use in source and binary forms, with or without @@ -33,6 +33,7 @@ BSDCFG_SHARE="/usr/share/bsdconfig" f_dprintf "%s: loading includes..." networking/resolv.subr f_include $BSDCFG_SHARE/dialog.subr f_include $BSDCFG_SHARE/strings.subr +f_include $BSDCFG_SHARE/media/tcpip.subr f_include $BSDCFG_SHARE/networking/common.subr f_include $BSDCFG_SHARE/networking/ipaddr.subr @@ -41,11 +42,6 @@ f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr ############################################################ CONFIGURATION -# -# Path to resolv.conf(5). -# -: ${RESOLV_CONF:="/etc/resolv.conf"} - # # When updating resolv.conf(5), should we populate the `search' directive with # all possible sub-domains? In example, if the domain is "sub.domain.com", when @@ -103,25 +99,6 @@ f_resolv_conf_search() ' } -# f_resolv_conf_nameservers -# -# Returns nameserver(s) configured in resolv.conf(5). -# -f_resolv_conf_nameservers() -{ - awk \ - ' - BEGIN { found = 0 } - ( $1 == "nameserver" ) \ - { - print $2 - found = 1 - } - END { exit ! found } - ' \ - "$RESOLV_CONF" 2> /dev/null -} - # f_dialog_resolv_conf_update $hostname # # Updates the search/domain directives in resolv.conf(5) given a valid fully- diff --git a/usr.sbin/bsdconfig/networking/share/routing.subr b/usr.sbin/bsdconfig/networking/share/routing.subr index 4207ab204c9..2d8cafcf6e1 100644 --- a/usr.sbin/bsdconfig/networking/share/routing.subr +++ b/usr.sbin/bsdconfig/networking/share/routing.subr @@ -1,6 +1,6 @@ if [ ! "$_NETWORKING_ROUTING_SUBR" ]; then _NETWORKING_ROUTING_SUBR=1 # -# Copyright (c) 2006-2012 Devin Teske +# Copyright (c) 2006-2013 Devin Teske # All Rights Reserved. # # Redistribution and use in source and binary forms, with or without @@ -33,6 +33,7 @@ BSDCFG_SHARE="/usr/share/bsdconfig" f_dprintf "%s: loading includes..." networking/routing.subr f_include $BSDCFG_SHARE/sysrc.subr f_include $BSDCFG_SHARE/dialog.subr +f_include $BSDCFG_SHARE/media/tcpip.subr f_include $BSDCFG_SHARE/networking/common.subr f_include $BSDCFG_SHARE/networking/ipaddr.subr @@ -41,25 +42,6 @@ f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr ############################################################ FUNCTIONS -# f_route_get_default -# -# Returns the IP address of the currently active default router. -# -f_route_get_default() -{ - route -n get default 2> /dev/null | awk \ - ' - BEGIN { found = 0 } - ( $1 == "gateway:" ) \ - { - print $2 - found = 1 - exit - } - END { exit ! found } - ' -} - # f_dialog_input_defaultrouter # # Edits the default router. diff --git a/usr.sbin/bsdconfig/share/Makefile b/usr.sbin/bsdconfig/share/Makefile index cd56dfc5443..4c20c2b835a 100644 --- a/usr.sbin/bsdconfig/share/Makefile +++ b/usr.sbin/bsdconfig/share/Makefile @@ -2,9 +2,11 @@ NO_OBJ= +SUBDIR= media + FILESDIR= ${SHAREDIR}/bsdconfig -FILES= common.subr dialog.subr mustberoot.subr script.subr \ - strings.subr sysrc.subr variable.subr +FILES= common.subr device.subr dialog.subr mustberoot.subr \ + script.subr strings.subr struct.subr sysrc.subr variable.subr beforeinstall: mkdir -p ${DESTDIR}${FILESDIR} diff --git a/usr.sbin/bsdconfig/share/common.subr b/usr.sbin/bsdconfig/share/common.subr index c66a54f1df2..cb9096fc3ce 100644 --- a/usr.sbin/bsdconfig/share/common.subr +++ b/usr.sbin/bsdconfig/share/common.subr @@ -1,7 +1,7 @@ if [ ! "$_COMMON_SUBR" ]; then _COMMON_SUBR=1 # # Copyright (c) 2012 Ron McDowell -# Copyright (c) 2012 Devin Teske +# Copyright (c) 2012-2013 Devin Teske # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -127,15 +127,15 @@ f_have() # f_getvar() { - local var_to_get="$1" var_to_set="$2" - [ "$var_to_set" ] || local value - eval ${var_to_set:-value}=\"\${$var_to_get}\" - eval [ \"\${$var_to_get+set}\" ] - local retval=$? + local __var_to_get="$1" __var_to_set="$2" + [ "$__var_to_set" ] || local value + eval ${__var_to_set:-value}=\"\${$__var_to_get}\" + eval [ \"\${$__var_to_get+set}\" ] + local __retval=$? eval f_dprintf '"f_getvar: var=[%s] value=[%s] r=%u"' \ - \"\$var_to_get\" \"\$${var_to_set:-value}\" \$retval - [ "$var_to_set" ] || { [ "$value" ] && echo "$value"; } - return $retval + \"\$__var_to_get\" \"\$${__var_to_set:-value}\" \$__retval + [ "$__var_to_set" ] || { [ "$value" ] && echo "$value"; } + return $__retval } # f_die [ $status [ $fmt [ $opts ... ]]] @@ -574,6 +574,30 @@ f_index_menusel_command() echo "$command" } +# f_running_as_init +# +# Returns true if running as init(1). +# +f_running_as_init() +{ + # + # When a custom init(8) performs an exec(3) to invoke a shell script, + # PID 1 becomes sh(1) and $PPID is set to 1 in the executed script. + # + [ ${PPID:-0} -eq 1 ] # Return status +} + +# f_mounted $local_directory +# +# Return success if a filesystem is mounted on a particular directory. +# +f_mounted() +{ + local dir="$1" + [ -d "$dir" ] || return $FAILURE + mount | grep -Eq " on $dir \([^)]+\)$" +} + ############################################################ MAIN # diff --git a/usr.sbin/bsdconfig/share/device.subr b/usr.sbin/bsdconfig/share/device.subr new file mode 100644 index 00000000000..473838b8a77 --- /dev/null +++ b/usr.sbin/bsdconfig/share/device.subr @@ -0,0 +1,799 @@ +if [ ! "$_DEVICE_SUBR" ]; then _DEVICE_SUBR=1 +# +# Copyright (c) 2012-2013 Devin Teske +# 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 (INLUDING, 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$ +# +############################################################ INCLUDES + +BSDCFG_SHARE="/usr/share/bsdconfig" +. $BSDCFG_SHARE/common.subr || exit 1 +f_dprintf "%s: loading includes..." device.subr +f_include $BSDCFG_SHARE/dialog.subr +f_include $BSDCFG_SHARE/strings.subr +f_include $BSDCFG_SHARE/struct.subr + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +f_include_lang $BSDCFG_LIBE/include/messages.subr + +############################################################ GLOBALS + +DEVICES= +DEVICE_NAMES= + +# A "device" from sysinstall's point of view +f_struct_define DEVICE \ + name \ + desc \ + devname \ + type \ + enabled \ + init \ + get \ + shutdown \ + flags \ + private \ + volume + +# Network devices have their `private' property set to this +f_struct_define DEVICE_INFO \ + use_rtsol use_dhcp ipaddr ipv6addr netmask extras + +setvar DEVICE_TYPE_NONE 1 +setvar DEVICE_TYPE_DISK 2 +setvar DEVICE_TYPE_FLOPPY 3 +setvar DEVICE_TYPE_FTP 4 +setvar DEVICE_TYPE_NETWORK 5 +setvar DEVICE_TYPE_CDROM 6 +setvar DEVICE_TYPE_USB 7 +setvar DEVICE_TYPE_DOS 8 +setvar DEVICE_TYPE_UFS 9 +setvar DEVICE_TYPE_NFS 10 +setvar DEVICE_TYPE_ANY 11 +setvar DEVICE_TYPE_HTTP_PROXY 12 + +# +# Default behavior is to call f_device_get_all() automatically when loaded. +# +: ${DEVICE_SELF_SCAN_ALL=1} + +############################################################ FUNCTIONS + +# f_device_try $name [$i [$var_path]] +# +# Test a particular device. If $i is given, then $name is expected to contain a +# single "%d" where $i will be inserted using printf. If $var_path is given, +# it is used as a variable name to provide the caller the device pathname. +# +# Returns success if the device path exists and is a cdev. +# +f_device_try() +{ + local name="$1" i="$2" var_path="$3" unit + if [ "$i" ]; then + unit=$( printf "$name" "$i" ) + else + unit="$name" + fi + case "$unit" in + /dev/*) : good ;; # already qualified + *) unit="/dev/$unit" ;; + esac + [ "$var_path" ] && setvar "$var_path" "$unit" + f_dprintf "f_device_try: making sure %s is a device node" "$unit" + if [ -c "$unit" ]; then + f_dprintf "f_device_try: %s is a cdev [good]" "$unit" + return $SUCCESS + else + f_dprintf "f_device_try: %s is not a cdev [skip]" "$unit" + return $FAILURE + fi +} + +# f_device_register $name $desc $devname $type $enabled $init_function \ +# $get_function $shutdown_function $private +# +# Register a device. A `structure' (see struct.subr) is created with the name +# device_$name (so make sure $name contains only alpha-numeric characters or +# the underscore, `_'). The remaining arguments after $name correspond to the +# properties of the `DEVICE' structure-type (defined above). +# +# If not already registered, the device is then appended to the DEVICES +# environment variable, a space-separated list of all registered devices. +# +f_device_register() +{ + local name="$1" desc="$2" devname="$3" type="$4" enabled="$5" + local init_func="$6" get_func="$7" shutdown_func="$8" private="$9" + + f_struct_new DEVICE "device_$name" || return $FAILURE + device_$name set name "$name" + device_$name set desc "$desc" + device_$name set devname "$devname" + device_$name set type "$type" + device_$name set enabled "$enabled" + device_$name set init "$init_func" + device_$name set get "$get_func" + device_$name set shutdown "$shutdown_func" + device_$name set private "$private" + + # Scan our global register to see if it needs ammending + local dev found= + for dev in $DEVICES; do + [ "$dev" = "$name" ] || continue + found=1 && break + done + [ "$found" ] || DEVICES="$DEVICES $name" + + return $SUCCESS +} + +# f_device_reset +# +# Reset the registered device chain. +# +f_device_reset() +{ + local dev + for dev in $DEVICES; do + f_device_shutdown $dev + + # + # XXX this potentially leaks $dev->private if it's being + # used to point to something dynamic, but you're not supposed + # to call this routine at such times that some open instance + # has its private member pointing somewhere anyway. XXX + # + f_struct_free device_$dev + done + DEVICES= +} + +# f_device_get_all +# +# Get all device information for devices we have attached. +# +f_device_get_all() +{ + local devname desc + + f_dprintf "f_device_get_all: Probing devices..." + f_dialog_info "$msg_probing_devices_please_wait_this_can_take_a_while" + + # First go for the network interfaces + for devname in $( ifconfig -l ); do + # Eliminate network devices that don't make sense + case "$devname" in + lo*) continue ;; + esac + + # Try and find its description + f_device_desc "$devname" $DEVICE_TYPE_NETWORK desc + + f_dprintf "Found a network device named %s" "$devname" + f_device_register $devname \ + "$desc" "$devname" $DEVICE_TYPE_NETWORK 1 \ + f_media_init_network "" f_media_shutdown_network "" + done + + # Next, try to find all the types of devices one might use + # as a media source for content + # + + local dev desc type max n=0 + for dev in $DEVICE_NAMES; do + n=$(( $n + 1 )) + # Get the desc, type, and max (with debugging disabled) + # NOTE: Bypassing f_device_name_get() for efficiency + debug= f_getvar _device_desc$n desc + debug= f_getvar _device_type$n type + debug= f_getvar _device_max$n max + + local k=0 + while [ $k -lt ${max:-0} ]; do + i=$k k=$(( $k + 1 )) + devname="" + case "$type" in + $DEVICE_TYPE_CDROM) + f_device_try "$dev" "$i" devname || continue + f_device_register "${devname##*/}" "$desc" \ + "$devname" $DEVICE_TYPE_CDROM 1 \ + f_media_init_cdrom f_media_get_cdrom \ + f_media_shutdown_cdrom "" + f_dprintf "Found a CDROM device for %s" \ + "$devname" + ;; + $DEVICE_TYPE_FLOPPY) + f_device_try "$dev" "$i" devname || continue + f_device_register "${devname##*/}" "$desc" \ + "$devname" $DEVICE_TYPE_FLOPPY 1 \ + f_media_init_floppy \ + f_media_get_floppy \ + f_media_shutdown_floppy "" + f_dprintf "Found a floppy device for %s" \ + "$devname" + ;; + $DEVICE_TYPE_USB) + f_device_try "$dev" "$i" devname || continue + f_device_register "${devname##*/}" "$desc" \ + "$devname" $DEVICE_TYPE_USB 1 \ + f_media_init_usb f_media_get_usb \ + f_media_shutdown_usb "" + f_dprintf "Found a USB disk for %s" "$devname" + ;; + esac + done + done + + # Register ISO9660 providers as CDROM devices + for devname in /dev/iso9660/*; do + f_device_try "$devname" || continue + f_device_register "${devname##*/}" "ISO9660 file system" \ + "$devname" $DEVICE_TYPE_CDROM 1 \ + f_media_init_cdrom f_media_get_cdrom \ + f_media_shutdown_cdrom "" + f_dprintf "Found a CDROM device for %s" "$devname" + done + + # Scan for mdconfig(8)-created md(4) devices + local filename + for devname in /dev/md[0-9] /dev/md[0-9][0-9]; do + f_device_try "$devname" || continue + + # See if the md(4) device is a vnode type backed by a file + filename=$( sysctl kern.geom.conftxt | + awk -v devname="${devname##*/}" \ + ' + ( $2 == "MD" ) && \ + ( $3 == devname ) && \ + ( $(NF-2) == "vnode" ) && \ + ( $(NF-1) == "file" ) \ + { + print $NF + } + ' ) + case "$filename" in + *.iso) # Register the device as an ISO9660 provider + f_device_register "${devname##*/}" \ + "md(4) vnode file system" \ + "$devname" $DEVICE_TYPE_CDROM 1 \ + f_media_init_cdrom f_media_get_cdrom \ + f_media_shutdown_cdrom "" + f_dprintf "Found a CDROM device for %s" "$devname" + ;; + esac + done + + # Finally go get the disks and look for partitions to register + local diskname slices index type rest slice part + for diskname in $( sysctl -n kern.disks ); do + + case "$diskname" in + cd*) + # XXX + # Due to unknown reasons, kern.disks returns SCSI + # CDROM as a valid disk. This will prevent bsdconfig + # from presenting SCSI CDROMs as available disks in + # various menus. Why GEOM treats SCSI CDROM as a disk + # is beyond me and that should be investigated. + # For temporary workaround, ignore SCSI CDROM device. + # + continue ;; + esac + + # Try to create a list of partitions and their types, + # consisting of "N,typeN ..." (e.g., "1,0xa5 2,0x06"). + if ! slices=$( fdisk -p "$diskname" 2> /dev/null | + awk '( $1 == "p" ) { print $2","$3 }' ) + then + f_dprintf "Unable to open disk %s" "$diskname" + continue + fi + + f_device_register "$diskname" "" \ + "/dev/$diskname" $DEVICE_TYPE_DISK 0 + f_dprintf "Found a disk device named %s" "$diskname" + + # Look for existing partitions to register + for slice in $slices; do + index="${slice%%,*}" type="${slice#*,}" + slice=${diskname}s$index + case "$type" in + 0x01|0x04|0x06|0x0b|0x0c|0x0e|0xef) + # DOS partitions to add as "DOS media devices" + f_device_register "$slice" "" \ + "/dev/$slice" $DEVICE_TYPE_DOS 1 \ + f_media_init_dos f_media_get_dos \ + f_media_shutdown_dos "" + f_dprintf "Found a DOS partition %s" "$slice" + ;; + 0xa5) # FreeBSD partition + for part in $( + bsdlabel -r $slice 2> /dev/null | + awk -v slice="$slice" ' + ( $1 ~ /[abdefgh]:/ ) { + printf "%s%s\n", + slice, + substr($1,1,1) + }' + ); do + f_quietly dumpfs -m /dev/$part || + continue + f_device_register \ + "$part" "" "/dev/$part" \ + $DEVICE_TYPE_UFS 1 \ + f_media_init_ufs \ + f_media_get_ufs \ + f_media_shutdown_ufs "" + f_dprintf "Found a UFS partition %s" \ + "$part" + done # parts + ;; + esac + done # slices + + done # disks +} + +# f_device_name_get $type $name type|desc|max [$var_to_set] +# +# Fetch the device type (type), description (desc), or maximum number of +# devices to scan for (max) associated with device $name and $type. If $type is +# either NULL, missing, or set to $DEVICE_TYPE_ANY then only $name is used. +# Returns success if a match was found, otherwise failure. +# +# If $var_to_set is missing or NULL, the device name is printed to standard out +# for capturing in a sub-shell (which is less-recommended because of +# performance degredation; for example, when called in a loop). +# +f_device_name_get() +{ + local __type="$1" __name="$2" __prop="$3" __var_to_set="$4" + local __dev __devtype __n=0 + + # Return failure if no $name or $prop is an unknown property + [ "$__name" ] || return $FAILURE + case "$__prop" in type|desc|max) : good ;; + *) return $FAILURE; esac + + [ "$__type" = "$DEVICE_TYPE_ANY" ] && __type= + for __dev in $DEVICE_NAMES; do + __n=$(( $__n + 1 )) + [ "$__dev" = "$__name" ] || continue + f_getvar _device_type$__n __devtype + [ "${__type:-$__devtype}" = "$__devtype" ] || continue + f_getvar _device_$__prop$__n $__var_to_set + return $? + done + return $FAILURE +} + +# f_device_name_set $type $name $desc [$max] +# +# Store a description (desc) and [optionally] maximum number of devices to scan +# for (max) in-association with device $type and $name. Returns success. Use +# the f_device_name_get() routine with the same $name and [optionally] $type to +# retrieve one of type, desc, or max properties. +# +f_device_name_set() +{ + local type="$1" name="$2" desc="$3" max="$4" + local dev devtype n=0 found= + [ "$name" ] || return $FAILURE + for dev in $DEVICE_NAMES; do + n=$(( $n + 1 )) + [ "$dev" = "$name" ] || continue + if f_getvar _device_type$n devtype; then + # Allow multiple entries with same name but diff type + [ "$devtype" = "$type" ] || continue + fi + found=1 && break + done + if [ ! "$found" ]; then + DEVICE_NAMES="$DEVICE_NAMES $name" + n=$(( $n + 1 )) + fi + setvar _device_type$n "$type" + setvar _device_desc$n "$desc" + [ "${4+set}" ] && setvar _device_max$n "$max" + return $SUCCESS +} + +# f_device_desc $device_name $device_type [$var_to_set] +# +# Print a description for a device name (eg., `fxp0') given a specific device +# type/class. +# +# If $var_to_set is missing or NULL, the device description is printed to +# standard out for capturing in a sub-shell (which is less-recommended because +# of performance degredation; for example, when called in a loop). +# +f_device_desc() +{ + local __name="$1" __type="$2" __var_to_set="$3" + local __devname __devunit __cp + + # Check variables + [ "$__name" ] || return $SUCCESS + [ "$__type" = "$DEVICE_TYPE_ANY" ] && type= + [ "$__var_to_set" ] && { setvar "$__var_to_set" "" || return; } + + # + # Return sysctl MIB dev.NAME.UNIT.%desc if it exists, + # otherwise fall through to below static list. + # + if f_have sysctl; then + __devname="${__name%%[0-9]*}" + __devunit="${__name#$__devname}" + __devunit="${__devunit%%[!0-9]*}" + if [ "$__var_to_set" ]; then + if __cp=$( + sysctl -n "dev.$__devname.$__devunit.%desc" \ + 2> /dev/null + ); then + setvar "$__var_to_set" "$__cp" && + return $SUCCESS + fi + else + sysctl -n "dev.$__devname.$__devunit.%desc" \ + 2> /dev/null && return $SUCCESS + fi + fi + + local __dev __devtype __n=0 + for __dev in $DEVICE_NAMES; do + __n=$(( $__n + 1 )) + debug= f_getvar _device_type$__n __devtype + [ "${__type:-$__devtype}" = "$__devtype" ] || continue + if [ "$__devtype" = "$DEVICE_TYPE_NETWORK" ]; then + __devname=$( f_substr "$__name" 0 ${#__dev} ) + [ "$__devname" = "$__dev" ] || continue + else + __devname="${__name%%[0-9]*}" + __devunit="${__name#$__devname}" + __devunit="${__devunit%%[!0-9]*}" + __devname=$( printf "$__dev" $__devunit ) + [ "$__devname" = "$__name" ] || continue + fi + debug= f_getvar _device_desc$__n $__var_to_set + return $? + done + + # + # Sensible fall-backs for specific types + # + case "$__type" in + $DEVICE_TYPE_CDROM) __cp="";; + $DEVICE_TYPE_DISK) __cp="";; + $DEVICE_TYPE_FLOPPY) __cp="";; + $DEVICE_TYPE_USB) __cp="";; + $DEVICE_TYPE_NETWORK) __cp="";; + *) + __cp="" + esac + + if [ "$__var_to_set" ]; then + setvar "$__var_to_set" "$__cp" + else + echo "$__cp" + fi + + return $FAILURE +} + +# f_device_rescan +# +# Rescan all devices, after closing previous set - convenience function. +# +f_device_rescan() +{ + f_device_reset + f_device_get_all +} + +# f_device_find $name [$type [$var_to_set]] +# +# Find one or more registered devices by name, type, or both. Returns a space- +# separated list of devices matching the search criterion. +# +# If $var_to_set is missing or NULL, the device name(s) are printed to standard +# out for capturing in a sub-shell (which is less-recommended because of +# performance degredation; for example, when called in a loop). +# +f_device_find() +{ + local __name="$1" __type="${2:-$DEVICE_TYPE_ANY}" __var_to_set="$3" + local __dev __devname __devtype __found= + for __dev in $DEVICES; do + device_$__dev get name __devname + device_$__dev get type __devtype + if [ "$__name" = "$__devname" -o ! "$__name" ] && + [ "$__type" = "$DEVICE_TYPE_ANY" -o \ + "$__type" = "$__devtype" ] + then + __found="$__found $__dev" + fi + done + if [ "$__var_to_set" ]; then + setvar "$__var_to_set" "${__found# }" + else + echo $__found + fi + [ "$__found" ] # Return status +} + +# f_device_init $name +# +# Initialize a device by evaluating its `init' function. +# +f_device_init() +{ + local name="$1" init_func + device_$name get init init_func || return + ${init_func:-:} $name +} + +# f_device_get $name $file [$probe] +# +# Read $file by evaluating the device's `get' function. The file is commonly +# produced on standard output (but it truly depends on the function called). +# +f_device_get() +{ + local name="$1" file="$2" probe="$3" get_func + device_$name get get get_func || return + ${get_func:-:} $name "$file" ${3+"$probe"} +} + +# f_device_shutdown $name +# +# Shutdown a device by evaluating its `shutdown' function. +# +f_device_shutdown() +{ + local name="$1" shutdown_func + device_$name get shutdown shutdown_func || return + ${shutdown_func:-:} $name +} + +# f_device_menu $title $prompt $hline $device_type [$helpfile] +# +# Display a menu listing all the devices of a certain type in the system. +# +f_device_menu() +{ + f_dialog_title "$1" + local title="$DIALOG_TITLE" btitle="$DIALOG_BACKTITLE" + f_dialog_title_restore + + local prompt="$2" hline="$3" type="$4" helpfile="$5" + + local dev devtype devs= + for dev in $DEVICES; do + device_$dev get type devtype || continue + [ "$devtype" = "$type" ] || continue + devs="$devs $dev" + done + [ "$devs" ] || return $FAILURE + + local sanitize_awk="{ gsub(/'/, \"'\\\\''\"); print }" + + local desc menu_list= + for dev in $devs; do + device_$dev get desc desc + desc=$( echo "$desc" | awk "$sanitize_awk" ) + menu_list="$menu_list '$dev' '$desc'" + done + + local size mtag + size=$( eval f_dialog_menu_size \ + \"\$title\" \ + \"\$btitle\" \ + \"\$prompt\" \ + \"\$hline\" \ + $menu_list ) + + local errexit= + case $- in *e*) errexit=1; esac + set +e + + while :; do + mtag=$( eval $DIALOG \ + --title \"\$title\" \ + --backtitle \"\$btitle\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + ${helpfile:+ \ + --help-button \ + --help-label \"\$msg_help\" \ + ${USE_XDIALOG:+--help \"\"} \ + } \ + --menu \"\$prompt\" $size \ + $menu_list \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD + ) + local retval=$? + + [ $retval -ne 2 ] && break + # Otherwise, the Help button was pressed + f_show_help "$helpfile" + # Loop back to menu + done + f_dprintf "retval=%u mtag=[%s]" $retval "$mtag" + + [ "$errexit" ] && set -e + + [ $retval -eq 0 ] && echo "$mtag" >&2 + + return $retval +} + +# +# Short-hand +# +f_cdrom() { f_device_name_set $DEVICE_TYPE_CDROM "$1" "$2" "$3"; } +f_disk() { f_device_name_set $DEVICE_TYPE_DISK "$1" "$2" "$3"; } +f_floppy() { f_device_name_set $DEVICE_TYPE_FLOPPY "$1" "$2" "$3"; } +f_serial() { f_device_name_set $DEVICE_TYPE_NETWORK "$1" "$2" "$3"; } +f_usb() { f_device_name_set $DEVICE_TYPE_USB "$1" "$2" "$3"; } +f_network() { f_device_name_set $DEVICE_TYPE_NETWORK "$1" "$2"; } + +############################################################ MAIN + +# CDROM, Disk, Floppy, Serial, and USB devices/names +f_cdrom "acd%d" "ATAPI/IDE CDROM" 4 +f_cdrom "cd%d" "SCSI CDROM drive" 4 +f_cdrom "mcd%d" "Mitsumi (old model) CDROM drive" 4 +f_cdrom "scd%d" "Sony CDROM drive - CDU31/33A type" 4 +f_disk "aacd%d" "Adaptec FSA RAID array" 4 +f_disk "ad%d" "ATA/IDE disk device" 16 +f_disk "ada%d" "SATA disk device" 16 +f_disk "afd%d" "ATAPI/IDE floppy device" 4 +f_disk "amrd%d" "AMI MegaRAID drive" 4 +f_disk "ar%d" "ATA/IDE RAID device" 16 +f_disk "da%d" "SCSI disk device" 16 +f_disk "idad%d" "Compaq RAID array" 4 +f_disk "ipsd%d" "IBM ServeRAID RAID array" 4 +f_disk "mfid%d" "LSI MegaRAID SAS array" 4 +f_disk "mlxd%d" "Mylex RAID disk" 4 +f_disk "twed%d" "3ware ATA RAID array" 4 +f_floppy "fd%d" "Floppy Drive unit A" 4 +f_serial "cuau%d" "%s on device %s (COM%d)" 16 +f_usb "da%da" "USB Mass Storage Device" 16 + +# Network interfaces/names +f_network "ae" "Attansic/Atheros L2 Fast Ethernet" +f_network "age" "Attansic/Atheros L1 Gigabit Ethernet" +f_network "alc" "Atheros AR8131/AR8132 PCIe Ethernet" +f_network "ale" "Atheros AR8121/AR8113/AR8114 PCIe Ethernet" +f_network "an" "Aironet 4500/4800 802.11 wireless adapter" +f_network "ath" "Atheros IEEE 802.11 wireless adapter" +f_network "aue" "ADMtek USB Ethernet adapter" +f_network "axe" "ASIX Electronics USB Ethernet adapter" +f_network "bce" "Broadcom NetXtreme II Gigabit Ethernet card" +f_network "bfe" "Broadcom BCM440x PCI Ethernet card" +f_network "bge" "Broadcom BCM570x PCI Gigabit Ethernet card" +f_network "bm" "Apple BMAC Built-in Ethernet" +f_network "bwn" "Broadcom BCM43xx IEEE 802.11 wireless adapter" +f_network "cas" "Sun Cassini/Cassini+ or NS DP83065 Saturn Ethernet" +f_network "cc3i" "SDL HSSI sync serial PCI card" +f_network "cue" "CATC USB Ethernet adapter" +f_network "cxgb" "Chelsio T3 10Gb Ethernet card" +f_network "dc" "DEC/Intel 21143 (and clones) PCI Fast Ethernet card" +f_network "de" "DEC DE435 PCI NIC or other DC21040-AA based card" +f_network "disc" "Software discard network interface" +f_network "ed" "Novell NE1000/2000; 3C503; NE2000-compatible PCMCIA" +f_network "el" "3Com 3C501 Ethernet card" +f_network "em" "Intel(R) PRO/1000 Ethernet card" +f_network "en" "Efficient Networks ATM PCI card" +f_network "ep" "3Com 3C509 Ethernet card/3C589 PCMCIA" +f_network "et" "Agere ET1310 based PCI Express Gigabit Ethernet card" +f_network "ex" "Intel EtherExpress Pro/10 Ethernet card" +f_network "fe" "Fujitsu MB86960A/MB86965A Ethernet card" +f_network "fpa" "DEC DEFPA PCI FDDI card" +f_network "fwe" "FireWire Ethernet emulation" +f_network "fwip" "IP over FireWire" +f_network "fxp" "Intel EtherExpress Pro/100B PCI Fast Ethernet card" +f_network "gem" "Apple GMAC or Sun ERI/GEM Ethernet adapter" +f_network "hme" "Sun HME (Happy Meal Ethernet) Ethernet adapter" +f_network "ie" "AT&T StarLAN 10 and EN100; 3Com 3C507; NI5210" +f_network "igb" "Intel(R) PRO/1000 PCI Express Gigabit Ethernet card" +f_network "ipw" "Intel PRO/Wireless 2100 IEEE 802.11 adapter" +f_network "iwi" "Intel PRO/Wireless 2200BG/2225BG/2915ABG adapter" +f_network "iwn" "Intel Wireless WiFi Link 4965AGN IEEE 802.11n adapter" +f_network "ixgbe" "Intel(R) PRO/10Gb Ethernet card" +f_network "ixgb" "Intel(R) PRO/10Gb Ethernet card" +f_network "ix" "Intel Etherexpress Ethernet card" + # Maintain sequential order of above(3): ixgbe ixgb ix +f_network "jme" "JMicron JMC250 Gigabit/JMC260 Fast Ethernet" +f_network "kue" "Kawasaki LSI USB Ethernet adapter" +f_network "le" "AMD Am7900 LANCE or Am79C9xx PCnet Ethernet adapter" +f_network "lge" "Level 1 LXT1001 Gigabit Ethernet card" +f_network "lnc" "Lance/PCnet (Isolan/Novell NE2100/NE32-VL) Ethernet" +f_network "lo" "Loop-back (local) network interface" +f_network "lp" "Parallel Port IP (PLIP) peer connection" +f_network "malo" "Marvell Libertas 88W8335 802.11 wireless adapter" +f_network "msk" "Marvell/SysKonnect Yukon II Gigabit Ethernet" +f_network "mxge" "Myricom Myri10GE 10Gb Ethernet card" +f_network "nfe" "NVIDIA nForce MCP Ethernet" +f_network "nge" "NatSemi PCI Gigabit Ethernet card" +f_network "ng" "Vimage netgraph(4) bridged Ethernet device" + # Maintain sequential order of above(2): nge ng +f_network "nve" "NVIDIA nForce MCP Ethernet" +f_network "nxge" "Neterion Xframe 10GbE Server/Storage adapter" +f_network "pcn" "AMD Am79c79x PCI Ethernet card" +f_network "plip" "Parallel Port IP (PLIP) peer connection" +f_network "ral" "Ralink Technology IEEE 802.11 wireless adapter" +f_network "ray" "Raytheon Raylink 802.11 wireless adapter" +f_network "re" "RealTek 8139C+/8169/8169S/8110S PCI Ethernet adapter" +f_network "rl" "RealTek 8129/8139 PCI Ethernet card" +f_network "rue" "RealTek USB Ethernet card" +f_network "rum" "Ralink Technology USB IEEE 802.11 wireless adapter" +f_network "sf" "Adaptec AIC-6915 PCI Ethernet card" +f_network "sge" "Silicon Integrated Systems SiS190/191 Ethernet" +f_network "sis" "SiS 900/SiS 7016 PCI Ethernet card" +f_network "sk" "SysKonnect PCI Gigabit Ethernet card" +f_network "snc" "SONIC Ethernet card" +f_network "sn" "SMC/Megahertz Ethernet card" + # Maintain sequential order of above(2): snc sn +f_network "sr" "SDL T1/E1 sync serial PCI card" +f_network "ste" "Sundance ST201 PCI Ethernet card" +f_network "stge" "Sundance/Tamarack TC9021 Gigabit Ethernet" +f_network "ti" "Alteon Networks PCI Gigabit Ethernet card" +f_network "tl" "Texas Instruments ThunderLAN PCI Ethernet card" +f_network "txp" "3Com 3cR990 Ethernet card" +f_network "tx" "SMC 9432TX Ethernet card" + # Maintain sequential order of above(2): txp tx +f_network "uath" "Atheros AR5005UG and AR5005UX USB wireless adapter" +f_network "upgt" "Conexant/Intersil PrismGT USB wireless adapter" +f_network "ural" "Ralink Technology RT2500USB 802.11 wireless adapter" +f_network "urtw" "Realtek 8187L USB wireless adapter" +f_network "vge" "VIA VT612x PCI Gigabit Ethernet card" +f_network "vlan" "IEEE 802.1Q VLAN network interface" +f_network "vr" "VIA VT3043/VT86C100A Rhine PCI Ethernet card" +f_network "vx" "3COM 3c590 / 3c595 Ethernet card" +f_network "wb" "Winbond W89C840F PCI Ethernet card" +f_network "wi" "Lucent WaveLAN/IEEE 802.11 wireless adapter" +f_network "wpi" "Intel 3945ABG IEEE 802.11 wireless adapter" +f_network "wx" "Intel Gigabit Ethernet (82452) card" +f_network "xe" "Xircom/Intel EtherExpress Pro100/16 Ethernet card" +f_network "xl" "3COM 3c90x / 3c90xB PCI Ethernet card" +f_network "zyd" "ZyDAS ZD1211/ZD1211B USB 802.11 wireless adapter" + +f_dprintf "%s: Initialized %u known device names/descriptions." device.subr \ + "$( set -- $DEVICE_NAMES; echo $# )" + +# +# Scan for the above devices unless requeted otherwise +# +f_dprintf "%s: DEVICE_SELF_SCAN_ALL=[%s]" device.subr "$DEVICE_SELF_SCAN_ALL" +case "$DEVICE_SELF_SCAN_ALL" in +""|0|[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee]) : do nothing ;; +*) f_device_get_all +esac + +f_dprintf "%s: Successfully loaded." device.subr + +fi # ! $_DEVICE_SUBR diff --git a/usr.sbin/bsdconfig/share/media/Makefile b/usr.sbin/bsdconfig/share/media/Makefile new file mode 100644 index 00000000000..ebd7c968270 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/Makefile @@ -0,0 +1,13 @@ +# $FreeBSD$ + +NO_OBJ= + +FILESDIR= ${SHAREDIR}/bsdconfig/media +FILES= any.subr cdrom.subr common.subr directory.subr dos.subr \ + floppy.subr ftp.subr httpproxy.subr network.subr nfs.subr \ + options.subr tcpip.subr ufs.subr usb.subr + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/share/media/any.subr b/usr.sbin/bsdconfig/share/media/any.subr new file mode 100644 index 00000000000..f64710fc259 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/any.subr @@ -0,0 +1,152 @@ +if [ ! "$_MEDIA_ANY_SUBR" ]; then _MEDIA_ANY_SUBR=1 +# +# Copyright (c) 2012-2013 Devin Teske +# 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 (INLUDING, 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$ +# +############################################################ INCLUDES + +BSDCFG_SHARE="/usr/share/bsdconfig" +. $BSDCFG_SHARE/common.subr || exit 1 +f_dprintf "%s: loading includes..." media/any.subr +f_include $BSDCFG_SHARE/dialog.subr +f_include $BSDCFG_SHARE/struct.subr +f_include $BSDCFG_SHARE/media/cdrom.subr +f_include $BSDCFG_SHARE/media/directory.subr +f_include $BSDCFG_SHARE/media/dos.subr +f_include $BSDCFG_SHARE/media/floppy.subr +f_include $BSDCFG_SHARE/media/ftp.subr +f_include $BSDCFG_SHARE/media/httpproxy.subr +f_include $BSDCFG_SHARE/media/nfs.subr +f_include $BSDCFG_SHARE/media/options.subr +f_include $BSDCFG_SHARE/media/ufs.subr +f_include $BSDCFG_SHARE/media/usb.subr + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +f_include_lang $BSDCFG_LIBE/include/messages.subr + +MEDIA_HELPFILE=$BSDCFG_LIBE/include/media.hlp + +############################################################ FUNCTIONS + +# f_media_get_type +# +# Prompt the user to select amongst the known media types (included above). +# +# If the user does not cancel or press Esc, invokes the f_media_set_* function +# associated with the chosen media type. If after all that we have a struct +# named `device_media' then success is returned, otherwise failure. +# +# NOTE: The f_media_set_* function should create the `device_media' struct. +# See `struct.subr' and the above `media/*.subr' includes for more details. +# +f_media_get_type() +{ + f_dialog_title "$msg_choose_installation_media" + local title="$DIALOG_TITLE" btitle="$DIALOG_BACKTITLE" + f_dialog_title_restore + local prompt="$msg_choose_installation_media_description" + local hline="$hline_choose_help_for_more_information_on_media_types" + local menu_list size + + menu_list=" + '1 $msg_cd_dvd' '$msg_install_from_a_freebsd_cd_dvd' + '2 $msg_ftp' '$msg_install_from_an_ftp_server' + '3 $msg_ftp_passive' + '$msg_install_from_an_ftp_server_thru_firewall' + '4 $msg_http' '$msg_install_from_an_ftp_server_thru_proxy' + '5 $msg_directory' '$msg_install_from_the_existing_filesystem' + '6 $msg_nfs' '$msg_install_over_nfs' + '7 $msg_dos' '$msg_install_from_a_dos_partition' + '8 $msg_ufs' '$msg_install_from_a_ufs_partition' + '9 $msg_floppy' '$msg_install_from_a_floppy_disk_set' + 'A $msg_usb' '$msg_install_from_a_usb_drive' + 'X $msg_options' '$msg_view_set_various_media_options' + " # END-QUOTE + + size=$( eval f_dialog_menu_size \ + \"\$title\" \ + \"\$btitle\" \ + \"\$prompt\" \ + \"\$hline\" \ + $menu_list ) + + local dialog_menu + + while :; do + dialog_menu=$( eval $DIALOG \ + --title \"\$title\" \ + --backtitle \"\$btitle\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --help-button \ + --help-label \"\$msg_help\" \ + ${USE_XDIALOG:+--help \"\"} \ + --menu \"\$prompt\" $size $menu_list \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD + ) + local retval=$? + setvar DIALOG_MENU_$$ "$dialog_menu" + + local mtag + mtag=$( f_dialog_menutag ) + f_dprintf "retval=%s mtag=[%s]" $retval "$mtag" + + if [ $retval -eq 2 ]; then + # The Help button was pressed + f_show_help "$MEDIA_HELPFILE" + continue + elif [ $retval -ne 0 ]; then + return $FAILURE + fi + + case "$mtag" in + ?" $msg_cd_dvd") f_media_set_cdrom ;; + ?" $msg_ftp") f_media_set_ftp_active ;; + ?" $msg_ftp_passive") f_media_set_ftp_passive ;; + ?" $msg_http") f_media_set_http_proxy ;; + ?" $msg_directory") f_media_set_directory ;; + ?" $msg_dos") f_media_set_dos ;; + ?" $msg_nfs") f_media_set_nfs ;; + ?" $msg_ufs") f_media_set_ufs ;; + ?" $msg_floppy") f_media_set_floppy ;; + ?" $msg_usb") f_media_set_usb ;; + ?" $msg_options") + f_media_options_menu + continue + ;; + esac + break + done + + f_struct device_media || return $FAILURE +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." media/any.subr + +fi # ! $_MEDIA_ANY_SUBR diff --git a/usr.sbin/bsdconfig/share/media/cdrom.subr b/usr.sbin/bsdconfig/share/media/cdrom.subr new file mode 100644 index 00000000000..f22ebd254f5 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/cdrom.subr @@ -0,0 +1,210 @@ +if [ ! "$_MEDIA_CDROM_SUBR" ]; then _MEDIA_CDROM_SUBR=1 +# +# Copyright (c) 2012-2013 Devin Teske +# 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 (INLUDING, 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$ +# +############################################################ INCLUDES + +BSDCFG_SHARE="/usr/share/bsdconfig" +. $BSDCFG_SHARE/common.subr || exit 1 +f_dprintf "%s: loading includes..." media/cdrom.subr +f_include $BSDCFG_SHARE/struct.subr +f_include $BSDCFG_SHARE/device.subr +f_include $BSDCFG_SHARE/dialog.subr +f_include $BSDCFG_SHARE/variable.subr +f_include $BSDCFG_SHARE/media/common.subr + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +f_include_lang $BSDCFG_LIBE/include/messages.subr + +############################################################ GLOBALS + +CDROM_MOUNTED= +CDROM_PREVIOUSLY_MOUNTED= +CDROM_INIT_QUIET= + +############################################################ FUNCTIONS + +# f_media_set_cdrom +# +# Return success if we both found and set the media type to be a CD. +# +f_media_set_cdrom() +{ + f_media_close + + local devs ndevs + f_device_find "" $DEVICE_TYPE_CDROM devs + ndevs=$( set -- $devs; echo $# ) + + if [ ${ndevs:=0} -eq 0 ]; then + f_interactive && f_dialog_msgbox "$msg_no_cd_dvd_devices_found" + return $FAILURE + elif [ $ndevs -gt 1 ]; then + local title="$msg_choose_a_cd_dvd_type" + local prompt="$msg_please_select_a_cd_dvd_drive" + local hline="" + + local dev retval + dev=$( f_device_menu \ + "$title" "$prompt" "$hline" $DEVICE_TYPE_CDROM \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) + retval=$? + [ "$dev" ] || return $FAILURE + + f_device_find "$dev" $DEVICE_TYPE_CDROM devs + [ "$devs" ] || return $FAILURE + dev="${devs%%[$IFS]*}" + + f_struct_copy device_$dev device_media + [ $retval -eq $SUCCESS ] || return $FAILURE + else + f_struct_copy device_$devs device_media + fi + + f_struct device_media || return $FAILURE +} + +# f_media_init_cdrom $device +# +# Initializes the CDROM media device. Returns success if able to mount the CD +# device using mount_cd9660(8). +# +f_media_init_cdrom() +{ + local dev="$1" devname err + + device_$dev get devname devname || return $FAILURE + f_dprintf "Init routine called for CDROM device. devname=[%s]" \ + "$devname" + + if [ "$CDROM_MOUNTED" ]; then + f_dprintf "CDROM device already mounted." + return $SUCCESS + fi + + if [ ! -e "$MOUNTPOINT" ] && + ! err=$( mkdir -p "$MOUNTPOINT" 2>&1 ) + then + f_dialog_msgbox "$err" + return $FAILURE + fi + + if ! err=$( mount_cd9660 "$devname" "$MOUNTPOINT" 2>&1 ) + then + err="${err#mount_cd9660: }"; err="${err#$devname: }" + case "$err" in + "Device busy") + # Perhaps the CDROM drive is already mounted as /cdrom + if f_mounted /cdrom; then + CDROM_PREVIOUSLY_MOUNTED=1 + MOUNTPOINT=/cdrom + err= + fi + ;; + esac + case "$err" in + "") : good ;; # no error + *) + [ "$CDROM_INIT_QUIET" ] || + f_show_msg "$msg_error_mounting_device" \ + "$devname" "$MOUNTPOINT" "$err" + return $FAILURE + esac + fi + CDROM_MOUNTED=1 + + : xxx # /cdrom.inf has been deprecated since 9.0-R + + # No other CDROM media validation at this time + + return $SUCCESS +} + +# f_media_get_cdrom $device $file [$probe_only] +# +# Returns data from $file on a mounted CDROM device. Similar to cat(1). +# $probe_only is currently unused by this media type. +# +f_media_get_cdrom() +{ + local dev="$1" file="$2" probe_only="$3" + + f_dprintf "f_media_get_cdrom: dev=[%s] file=[%s] probe_only=%s" \ + "$dev" "$file" "$probe_only" + + f_media_generic_get "$MOUNTPOINT" "$file" +} + +# f_media_shutdown_cdrom $device +# +# Shuts down the CDROM device and ejects the media using f_media_eject_cdrom(), +# below. Return status should be ignored. +# +f_media_shutdown_cdrom() +{ + local dev="$1" err + + [ "$CDROM_MOUNTED" ] || return + + if [ "$CDROM_PREVIOUSLY_MOUNTED" ]; then + CDROM_MOUNTED= + return $SUCCESS + fi + + if ! err=$( umount -f "$MOUNTPOINT" 2>&1 ); then + err="${err#umount: }"; err="${err#*: }" + f_show_msg "$msg_could_not_unmount_the_cdrom_dvd" \ + "$MOUNTPOINT" "$err" + else + CDROM_MOUNTED= + fi + + f_media_eject_cdrom "$dev" +} + +# f_media_eject_cdrom $device +# +# Eject the media from the CDROM device. Returns success. +# +f_media_eject_cdrom() +{ + local dev="$1" devname err + device_$dev get name devname || return $SUCCESS + case "$devname" in /dev/iso9660/*) return $SUCCESS; esac + f_dprintf "Ejecting CDROM/DVD at %s" "$devname" + if ! err=$( cdcontrol -f "$devname" eject 2>&1 ); then + f_dprintf "Could not eject the CDROM/DVD from %s: %s" \ + "$devname" "${err#cdcontrol: }" + fi + return $SUCCESS +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." media/cdrom.subr + +fi # ! $_MEDIA_CDROM_SUBR diff --git a/usr.sbin/bsdconfig/share/media/common.subr b/usr.sbin/bsdconfig/share/media/common.subr new file mode 100644 index 00000000000..589bbdc84fc --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/common.subr @@ -0,0 +1,109 @@ +if [ ! "$_MEDIA_COMMON_SUBR" ]; then _MEDIA_COMMON_SUBR=1 +# +# Copyright (c) 2012-2013 Devin Teske +# 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 (INLUDING, 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$ +# +############################################################ INCLUDES + +BSDCFG_SHARE="/usr/share/bsdconfig" +. $BSDCFG_SHARE/common.subr || exit 1 +f_dprintf "%s: loading includes..." media/common.subr +f_include $BSDCFG_SHARE/struct.subr +f_include $BSDCFG_SHARE/device.subr + +############################################################ GLOBALS + +# +# Where to mount media +# +MOUNTPOINT=/dist + +############################################################ FUNCTIONS + +# f_media_open +# +# Returms success if able to initialize the media device. +# +f_media_open() +{ + { # Verify and initialize device media if-defined + f_struct device_media && + f_media_verify && + f_device_init media + } || return $FAILURE +} + +# f_media_close +# +# Shuts down the media device, see f_device_shutdown() from device.subr for +# more details. +# +f_media_close() +{ + f_struct device_media && + f_device_shutdown media + f_struct_free device_media +} + +# f_media_verify +# +# Returns success if the media device is available, and if not, prompts the +# user to select a media type. See f_media_get_type() from media/any.subr for +# more details. +# +f_media_verify() +{ + f_struct device_media || f_media_get_type +} + +# f_media_generic_get $base $file +# +# A generic open which follows a well-known "path" of places to look. +# +f_media_generic_get() +{ + local base="$1" file="$2" rel path + + f_getvar $VAR_RELNAME rel + for path in \ + "$base/$file" \ + "$base/FreeBSD/$file" \ + "$base/releases/$file" \ + "$base/$rel/$file" \ + ; do + if [ -f "$path" -a -r "$path" ]; then + cat "$path" + return + fi + done + cat "$base/releases/$rel/$file" # Final path to try +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." media/common.subr + +fi # ! $_MEDIA_COMMON_SUBR diff --git a/usr.sbin/bsdconfig/share/media/directory.subr b/usr.sbin/bsdconfig/share/media/directory.subr new file mode 100644 index 00000000000..38311405a73 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/directory.subr @@ -0,0 +1,146 @@ +if [ ! "$_MEDIA_DIRECTORY_SUBR" ]; then _MEDIA_DIRECTORY_SUBR=1 +# +# Copyright (c) 2012-2013 Devin Teske +# 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 (INLUDING, 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$ +# +############################################################ INCLUDES + +BSDCFG_SHARE="/usr/share/bsdconfig" +. $BSDCFG_SHARE/common.subr || exit 1 +f_dprintf "%s: loading includes..." media/directory.subr +f_include $BSDCFG_SHARE/struct.subr +f_include $BSDCFG_SHARE/device.subr +f_include $BSDCFG_SHARE/dialog.subr +f_include $BSDCFG_SHARE/variable.subr +f_include $BSDCFG_SHARE/media/common.subr + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +f_include_lang $BSDCFG_LIBE/include/messages.subr + +############################################################ GLOBALS + +DIRECTORY_CHECKED= + +############################################################ FUNCTIONS + +# f_media_set_directory +# +# Return success if we both found and set the media type to be a local +# directory. +# +# Variables from variable.subr that can be used to script user input: +# +# VAR_DIRECTORY_PATH +# Path to an existing directory containing the FreeBSD +# distribution files. +# +f_media_set_directory() +{ + local path + + f_media_close + + f_variable_get_value $VAR_DIRECTORY_PATH \ + "$msg_enter_a_fully_qualified_pathname_for_the_directory" + f_getvar $VAR_DIRECTORY_PATH path + [ "$path" ] || return $FAILURE + + f_struct_new DEVICE device_directory + device_directory set get f_media_get_directory + device_directory set init f_media_init_directory + device_directory set shutdown f_media_shutdown_directory + device_directory set private "$path" + + f_struct_copy device_directory device_media + f_struct_free device_directory + + f_struct device_media || return $FAILURE +} + +# f_media_init_directory $device +# +# Initializes the Directory media device. Returns success if the directory path +# both exists and is a directory. +# +f_media_init_directory() +{ + local dev="$1" path + + device_$dev get private path || return $FAILURE + f_dprintf "Init routine called for Directory device. path=[%s]" \ + "$path" + + # Track whether we've been through here before (for remote filesystems + # mounted in the directory path, not repeating these queries saves us + # valuable time for slow/uncooperative links). + if [ "$DIRECTORY_CHECKED" ]; then + f_dprintf "Directory device already checked." + return $SUCCESS + fi + + if [ ! -e "$path" ]; then + f_show_msg "$msg_no_such_file_or_directory" \ + "f_media_init_directory" "$path" + return $FAILURE + elif [ ! -d "$path" ]; then + f_show_msg "$msg_not_a_directory" \ + "f_media_init_directory" "$path" + return $FAILURE + fi + DIRECTORY_CHECKED=1 + return $SUCCESS +} + +# f_media_get_directory $device $file [$probe_only] +# +# Returns data from $file in the existing/current filesystem. Similar to +# cat(1). $probe_only is currently unused by this media type. +# +f_media_get_directory() +{ + local dev="$1" file="$2" probe_only="$3" path + + f_dprintf "f_media_get_directory: dev=[%s] file=[%s] probe_only=%s" \ + "$dev" "$file" "$probe_only" + + device_$dev get private path + f_media_generic_get "$path" "$file" +} + +# f_media_shutdown_directory $device +# +# Shuts down the Directory device. Return status should be ignored. +# +f_media_shutdown_directory() +{ + DIRECTORY_CHECKED= +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." media/directory.subr + +fi # ! $_MEDIA_DIRECTORY_SUBR diff --git a/usr.sbin/bsdconfig/share/media/dos.subr b/usr.sbin/bsdconfig/share/media/dos.subr new file mode 100644 index 00000000000..3e59fb671c1 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/dos.subr @@ -0,0 +1,164 @@ +if [ ! "$_MEDIA_DOS_SUBR" ]; then _MEDIA_DOS_SUBR=1 +# +# Copyright (c) 2012-2013 Devin Teske +# 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 (INLUDING, 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$ +# +############################################################ INCLUDES + +BSDCFG_SHARE="/usr/share/bsdconfig" +. $BSDCFG_SHARE/common.subr || exit 1 +f_dprintf "%s: loading includes..." media/dos.subr +f_include $BSDCFG_SHARE/struct.subr +f_include $BSDCFG_SHARE/device.subr +f_include $BSDCFG_SHARE/dialog.subr +f_include $BSDCFG_SHARE/variable.subr +f_include $BSDCFG_SHARE/media/common.subr + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +f_include_lang $BSDCFG_LIBE/include/messages.subr + +############################################################ GLOBALS + +DOS_MOUNTED= + +############################################################ FUNCTIONS + +# f_media_set_dos +# +# Return success if we both found and set the media type to be a DOS partition. +# +f_media_set_dos() +{ + f_media_close + + local devs ndevs + f_device_find "" $DEVICE_TYPE_DOS devs + ndevs=$( set -- $devs; echo $# ) + + if [ ${ndevs:=0} -eq 0 ]; then + f_dialog_msgbox "$msg_no_dos_primary_partitions_found" + return $FAILURE + elif [ $ndevs -gt 1 ]; then + local title="$msg_choose_a_dos_partition" + local prompt="$msg_please_select_dos_partition" + local hline="" + + local dev retval + dev=$( f_device_menu \ + "$title" "$prompt" "$hline" $DEVICE_TYPE_DOS \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) + retval=$? + [ "$dev" ] || return $FAILURE + + f_device_find "$dev" $DEVICE_TYPE_DOS devs + [ "$devs" ] || return $FAILURE + dev="${devs%%[$IFS]*}" + + f_struct_copy device_$dev device_media + [ $retval -eq $SUCCESS ] || return $FAILURE + else + f_struct_copy device_$devs device_media + fi + + f_struct device_media || return $FAILURE +} + +# f_media_init_dos $device +# +# Initializes the DOS media device. Returns success if able to mount the DOS +# partition device using mount_msdosfs(8). +# +f_media_init_dos() +{ + local dev="$1" devname err + + device_$dev get devname devname || return $FAILURE + f_dprintf "Init routine called for DOS device. devname=[%s]" \ + "$devname" + + if [ "$DOS_MOUNTED" ]; then + f_dprintf "DOS device already mounted." + return $SUCCESS + fi + + if [ ! -e "$MOUNTPOINT" ] && + ! err=$( mkdir -p "$MOUNTPOINT" 2>&1 ) + then + f_dialog_msgbox "$err" + return $FAILURE + fi + + if ! err=$( mount_msdosfs "$devname" "$MOUNTPOINT" 2>&1 ) + then + err="${err#mount_msdosfs: }"; err="${err#$devname: }" + f_show_msg "$msg_error_mounting_device" \ + "$devname" "$MOUNTPOINT" "$err" + return $FAILURE + fi + DOS_MOUNTED=1 + return $SUCCESS +} + +# f_media_get_dos $device $file [$probe_only] +# +# Returns data from $file on a mounted DOS partition device. Similar to cat(1). +# $probe_only is currently unused by this media type. +# +f_media_get_dos() +{ + local dev="$1" file="$2" probe_only="$3" + + f_dprintf "f_media_get_dos: dev=[%s] file=[%s] probe_only=%s" \ + "$dev" "$file" "$probe_only" + + f_media_generic_get "$MOUNTPOINT" "$file" +} + +# f_media_shutdown_dos $device +# +# Shuts down the DOS partition device using umount(8). Return status should be +# ignored. +# +f_media_shutdown_dos() +{ + local dev="$1" err + + [ "$DOS_MOUNTED" ] || return + + if ! err=$( umount -f "$MOUNTPOINT" 2>&1 ); then + err="${err#umount: }"; err="${err#*: }" + f_show_msg "$msg_could_not_unmount_the_dos_partition" \ + "$MOUNTPOINT" "$err" + else + DOS_MOUNTED= + fi +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." media/dos.subr + +fi # ! $_MEDIA_DOS_SUBR diff --git a/usr.sbin/bsdconfig/share/media/floppy.subr b/usr.sbin/bsdconfig/share/media/floppy.subr new file mode 100644 index 00000000000..c874c6128f7 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/floppy.subr @@ -0,0 +1,214 @@ +if [ ! "$_MEDIA_FLOPPY_SUBR" ]; then _MEDIA_FLOPPY_SUBR=1 +# +# Copyright (c) 2012-2013 Devin Teske +# 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 (INLUDING, 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$ +# +############################################################ INCLUDES + +BSDCFG_SHARE="/usr/share/bsdconfig" +. $BSDCFG_SHARE/common.subr || exit 1 +f_dprintf "%s: loading includes..." media/floppy.subr +f_include $BSDCFG_SHARE/struct.subr +f_include $BSDCFG_SHARE/device.subr +f_include $BSDCFG_SHARE/dialog.subr +f_include $BSDCFG_SHARE/variable.subr +f_include $BSDCFG_SHARE/media/common.subr + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +f_include_lang $BSDCFG_LIBE/include/messages.subr + +############################################################ GLOBALS + +FLOPPY_MOUNTED= +FLOPPY_DISTWANTED= + +############################################################ FUNCTIONS + +# f_media_set_floppy +# +# Return success if we both found and set the media type to be a floppy. +# +f_media_set_floppy() +{ + f_media_close + + local devs ndevs + f_device_find "" $DEVICE_TYPE_FLOPPY devs + ndevs=$( set -- $devs; echo $# ) + + if [ ${ndevs:=0} -eq 0 ]; then + f_interactive && f_dialog_msgbox "$msg_no_floppy_devices_found" + return $FAILURE + elif [ $ndevs -gt 1 ]; then + local title="$msg_choose_a_floppy_drive" + local prompt="$msg_please_select_a_floppy_drive" + local hline="" + + local dev retval + dev=$( f_device_menu \ + "$title" "$prompt" "$hline" $DEVICE_TYPE_FLOPPY \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) + retval=$? + [ "$dev" ] || return $FAILURE + + f_device_find "$dev" $DEVICE_TYPE_FLOPPY devs + [ "$devs" ] || return $FAILURE + dev="${devs%%[$IFS]*}" + + f_struct_copy device_$dev device_media + [ $retval -eq $SUCCESS ] || return $FAILURE + else + f_struct_copy device_$devs device_media + fi + + f_struct device_media && + device_media unset private + + f_struct device_media || return $FAILURE +} + +# f_media_init_floppy $device +# +# Initializes the Floppy media device. Returns success if able to mount the +# Floppy disk device using either mount_msdosfs(8) or mount(8) (tried in that +# order). +# +f_media_init_floppy() +{ + local dev="$1" devname err + + device_$dev get devname devname || return $FAILURE + f_dprintf "Init floppy called for %s distribution. devname=[%s]" \ + "${FLOPPY_DISTWANTED:-some}" "$devname" + + if [ "$FLOPPY_MOUNTED" ]; then + f_dprintf "Floppy device already mounted." + return $SUCCESS + fi + + local mp + device_$dev get private mp + if [ ! -e "${mp:=$MOUNTPOINT}" ] && ! f_quietly mkdir -p "$mp"; then + f_show_msg "$msg_unable_to_make_directory_mountpoint" \ + "$mp" "$devname" + return $FAILURE + fi + + if f_interactive; then + local desc + device_$dev get desc desc + if [ "$FLOPPY_DISTWANTED" ]; then + f_show_msg "$msg_please_insert_floppy_in_drive" "$desc" + else + f_show_msg "$msg_please_insert_floppy_containing" \ + "$FLOPPY_DISTWANTED" "$desc" + fi + fi + + if ! { + f_quietly mount_msdosfs -o ro -m 0777 -u 0 -g 0 "$devname" "$mp" || + err=$( mount -o ro "$devname" "$mp" 2>&1 ) + }; then + err="${err#mount: }"; err="${err#*: }" + local name + device_$dev get name name + f_show_msg "$msg_error_mounting_floppy_device" \ + "$name" "$devname" "$mp" "$err" + return $FAILURE + fi + FLOPPY_MOUNTED=1 + FLOPPY_DISTWANTED= + return $SUCCESS +} + +# f_media_get_floppy $device $file [$probe_only] +# +# Returns data from $file on a mounted Floppy disk device. Similar to cat(1). +# If $probe_only is present and non-null, limits retries to zero. +# +f_media_get_floppy() +{ + local dev="$1" file="$2" probe_only="$3" + + f_dprintf "f_media_get_floppy: dev=[%s] file=[%s] probe_only=%s" \ + "$dev" "$file" "$probe_only" + + # + # floppies don't use f_media_generic_get() because it's too expensive + # to speculatively open files on a floppy disk. Make user get it + # right or give up with floppies. + # + local mp + device_$dev get private mp + local fp="${mp:=$MOUNTPOINT}/$file" + if ! [ -f "$fp" -a -r "$fp" ]; then + local nretries=4 + [ "$probe_only" ] && return $FAILURE + while ! [ -f "$fp" -a -r "$fp" ]; do + if [ $nretries -eq 0 ]; then + f_show_msg "$msg_failed_to_get_floppy_file" \ + "$fp" + return $FAILURE + fi + FLOPPY_DISTWANTED="$fp" + f_media_shutdown_floppy "$dev" + f_media_init_floppy "$dev" || return $FAILURE + nretries=$(( $nretries - 1 )) + done + fi + cat "$fp" +} + +# f_media_shutdown_floppy $device +# +# Shuts down the Floppy disk device using umount(8). Return status should be +# ignored. +# +f_media_shutdown_floppy() +{ + local dev="$1" err mp + + [ "$FLOPPY_MOUNTED" ] || return + + device_$dev get private mp + if ! err=$( umount -f "${mp:=$MOUNTPOINT}" 2>&1 ); then + err="${err#umount: }"; err="${err#*:}" + f_dprintf "Umount of floppy on %s failed: %s" "$mp" "$err" + else + FLOPPY_MOUNTED= + if f_interactive && [ "$_systemState" != "fixit" ]; then + local desc + device_$dev get desc desc + f_show_msg "$msg_you_may_remove_the_floppy" "$desc" + fi + fi +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." media/floppy.subr + +fi # ! $_MEDIA_FLOPPY_SUBR diff --git a/usr.sbin/bsdconfig/share/media/ftp.subr b/usr.sbin/bsdconfig/share/media/ftp.subr new file mode 100644 index 00000000000..ecc7724ebe6 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/ftp.subr @@ -0,0 +1,893 @@ +if [ ! "$_MEDIA_FTP_SUBR" ]; then _MEDIA_FTP_SUBR=1 +# +# Copyright (c) 2012-2013 Devin Teske +# 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 (INLUDING, 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$ +# +############################################################ INCLUDES + +BSDCFG_SHARE="/usr/share/bsdconfig" +. $BSDCFG_SHARE/common.subr || exit 1 +f_dprintf "%s: loading includes..." media/ftp.subr +f_include $BSDCFG_SHARE/struct.subr +f_include $BSDCFG_SHARE/device.subr +f_include $BSDCFG_SHARE/dialog.subr +f_include $BSDCFG_SHARE/strings.subr +f_include $BSDCFG_SHARE/variable.subr +f_include $BSDCFG_SHARE/media/common.subr +f_include $BSDCFG_SHARE/media/tcpip.subr +f_include $BSDCFG_SHARE/media/network.subr + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +f_include_lang $BSDCFG_LIBE/include/messages.subr + +############################################################ GLOBALS + +FTP_SKIP_RESOLV= + +URL_MAX=261261 # according to actual fetch(1) test-results + +FTP_DIRS=" + . + releases/$UNAME_P + snapshots/$UNAME_P + pub/FreeBSD + pub/FreeBSD/releases/$UNAME_P + pub/FreeBSD/snapshots/$UNAME_P + pub/FreeBSD-Archive/old-releases/$UNAME_P +" # END-QUOTE + +############################################################ FUNCTIONS + +# f_dialog_menu_media_ftp +# +# Prompt the user to select from a range of ``built-in'' FTP servers or specify +# their own. If the user makes a choice and doesn't cancel or press Esc, stores +# the user's choice in VAR_FTP_PATH (see variables.subr) and returns success. +# +f_dialog_menu_media_ftp() +{ + f_dialog_title "$msg_please_select_a_freebsd_ftp_distribution_site" + local title="$DIALOG_TITLE" btitle="$DIALOG_BACKTITLE" + f_dialog_title_restore + + local prompt="$msg_please_select_the_site_closest_to_you_or_other" + local hline="$msg_select_a_site_thats_close" + local menu_list=" + '$msg_main_site' 'ftp.freebsd.org' + 'URL' '$msg_specify_some_other_ftp_site' + '$msg_snapshots_server_japan' + 'snapshots.jp.freebsd.org' + '$msg_snapshots_server_sweden' + 'snapshots.se.freebsd.org' + 'IPv6 $msg_main_site' 'ftp.freebsd.org' + ' IPv6 $msg_ireland' 'ftp3.ie.freebsd.org' + ' IPv6 $msg_israel' 'ftp.il.freebsd.org' + ' IPv6 $msg_japan' 'ftp2.jp.freebsd.org' + ' IPv6 $msg_usa' 'ftp4.us.freebsd.org' + ' IPv6 $msg_turkey' 'ftp2.tr.freebsd.org' + '$msg_primary' 'ftp1.freebsd.org' + ' $msg_primary #2' 'ftp2.freebsd.org' + ' $msg_primary #3' 'ftp3.freebsd.org' + ' $msg_primary #4' 'ftp4.freebsd.org' + ' $msg_primary #5' 'ftp5.freebsd.org' + ' $msg_primary #6' 'ftp6.freebsd.org' + ' $msg_primary #7' 'ftp7.freebsd.org' + ' $msg_primary #8' 'ftp8.freebsd.org' + ' $msg_primary #9' 'ftp9.freebsd.org' + ' $msg_primary #10' 'ftp10.freebsd.org' + ' $msg_primary #11' 'ftp11.freebsd.org' + ' $msg_primary #12' 'ftp12.freebsd.org' + ' $msg_primary #13' 'ftp13.freebsd.org' + ' $msg_primary #14' 'ftp14.freebsd.org' + '$msg_argentina' 'ftp.ar.freebsd.org' + '$msg_australia' 'ftp.au.freebsd.org' + ' $msg_australia #2' 'ftp2.au.freebsd.org' + ' $msg_australia #3' 'ftp3.au.freebsd.org' + '$msg_austria' 'ftp.at.freebsd.org' + ' $msg_austria #2' 'ftp2.at.freebsd.org' + '$msg_brazil' 'ftp.br.freebsd.org' + ' $msg_brazil #2' 'ftp2.br.freebsd.org' + ' $msg_brazil #3' 'ftp3.br.freebsd.org' + ' $msg_brazil #4' 'ftp4.br.freebsd.org' + ' $msg_brazil #5' 'ftp5.br.freebsd.org' + ' $msg_brazil #6' 'ftp6.br.freebsd.org' + ' $msg_brazil #7' 'ftp7.br.freebsd.org' + '$msg_canada' 'ftp.ca.freebsd.org' + '$msg_china' 'ftp.cn.freebsd.org' + ' $msg_china #2' 'ftp2.cn.freebsd.org' + '$msg_croatia' 'ftp.hr.freebsd.org' + '$msg_czech_republic' 'ftp.cz.freebsd.org' + '$msg_denmark' 'ftp.dk.freebsd.org' + ' $msg_denmark #2' 'ftp2.dk.freebsd.org' + '$msg_estonia' 'ftp.ee.freebsd.org' + '$msg_finland' 'ftp.fi.freebsd.org' + '$msg_france' 'ftp.fr.freebsd.org' + ' $msg_france #2' 'ftp2.fr.freebsd.org' + ' $msg_france #3' 'ftp3.fr.freebsd.org' + ' $msg_france #5' 'ftp5.fr.freebsd.org' + ' $msg_france #6' 'ftp6.fr.freebsd.org' + ' $msg_france #8' 'ftp8.fr.freebsd.org' + '$msg_germany' 'ftp.de.freebsd.org' + ' $msg_germany #2' 'ftp2.de.freebsd.org' + ' $msg_germany #3' 'ftp3.de.freebsd.org' + ' $msg_germany #4' 'ftp4.de.freebsd.org' + ' $msg_germany #5' 'ftp5.de.freebsd.org' + ' $msg_germany #6' 'ftp6.de.freebsd.org' + ' $msg_germany #7' 'ftp7.de.freebsd.org' + ' $msg_germany #8' 'ftp8.de.freebsd.org' + '$msg_greece' 'ftp.gr.freebsd.org' + ' $msg_greece #2' 'ftp2.gr.freebsd.org' + '$msg_hungary' 'ftp.hu.freebsd.org' + '$msg_iceland' 'ftp.is.freebsd.org' + '$msg_ireland' 'ftp.ie.freebsd.org' + ' $msg_ireland #2' 'ftp2.ie.freebsd.org' + ' $msg_ireland #3' 'ftp3.ie.freebsd.org' + '$msg_israel' 'ftp.il.freebsd.org' + '$msg_italy' 'ftp.it.freebsd.org' + '$msg_japan' 'ftp.jp.freebsd.org' + ' $msg_japan #2' 'ftp2.jp.freebsd.org' + ' $msg_japan #3' 'ftp3.jp.freebsd.org' + ' $msg_japan #4' 'ftp4.jp.freebsd.org' + ' $msg_japan #5' 'ftp5.jp.freebsd.org' + ' $msg_japan #6' 'ftp6.jp.freebsd.org' + ' $msg_japan #7' 'ftp7.jp.freebsd.org' + ' $msg_japan #8' 'ftp8.jp.freebsd.org' + ' $msg_japan #9' 'ftp9.jp.freebsd.org' + '$msg_korea' 'ftp.kr.freebsd.org' + ' $msg_korea #2' 'ftp2.kr.freebsd.org' + '$msg_lithuania' 'ftp.lt.freebsd.org' + '$msg_netherlands' 'ftp.nl.freebsd.org' + ' $msg_netherlands #2' 'ftp2.nl.freebsd.org' + '$msg_norway' 'ftp.no.freebsd.org' + ' $msg_norway #3' 'ftp3.no.freebsd.org' + '$msg_poland' 'ftp.pl.freebsd.org' + ' $msg_poland #2' 'ftp2.pl.freebsd.org' + ' $msg_poland #5' 'ftp5.pl.freebsd.org' + '$msg_portugal' 'ftp.pt.freebsd.org' + ' $msg_portugal #2' 'ftp2.pt.freebsd.org' + ' $msg_portugal #4' 'ftp4.pt.freebsd.org' + '$msg_romania' 'ftp.ro.freebsd.org' + '$msg_russia' 'ftp.ru.freebsd.org' + ' $msg_russia #2' 'ftp2.ru.freebsd.org' + ' $msg_russia #3' 'ftp3.ru.freebsd.org' + ' $msg_russia #4' 'ftp4.ru.freebsd.org' + '$msg_singapore' 'ftp.sg.freebsd.org' + '$msg_slovak_republic' 'ftp.sk.freebsd.org' + '$msg_slovenia' 'ftp.si.freebsd.org' + ' $msg_slovenia #2' 'ftp2.si.freebsd.org' + '$msg_south_africa' 'ftp.za.freebsd.org' + ' $msg_south_africa #2' 'ftp2.za.freebsd.org' + ' $msg_south_africa #3' 'ftp3.za.freebsd.org' + ' $msg_south_africa #4' 'ftp4.za.freebsd.org' + '$msg_spain' 'ftp.es.freebsd.org' + ' $msg_spain #2' 'ftp2.es.freebsd.org' + ' $msg_spain #3' 'ftp3.es.freebsd.org' + '$msg_sweden' 'ftp.se.freebsd.org' + ' $msg_sweden #2' 'ftp2.se.freebsd.org' + ' $msg_sweden #3' 'ftp3.se.freebsd.org' + ' $msg_sweden #4' 'ftp4.se.freebsd.org' + ' $msg_sweden #5' 'ftp5.se.freebsd.org' + '$msg_switzerland' 'ftp.ch.freebsd.org' + ' $msg_switzerland #2' 'ftp2.ch.freebsd.org' + '$msg_taiwan' 'ftp.tw.freebsd.org' + ' $msg_taiwan #2' 'ftp2.tw.freebsd.org' + ' $msg_taiwan #3' 'ftp3.tw.freebsd.org' + ' $msg_taiwan #4' 'ftp4.tw.freebsd.org' + ' $msg_taiwan #6' 'ftp6.tw.freebsd.org' + ' $msg_taiwan #11' 'ftp11.tw.freebsd.org' + '$msg_turkey' 'ftp.tr.freebsd.org' + ' $msg_turkey #2' 'ftp2.tr.freebsd.org' + '$msg_uk' 'ftp.uk.freebsd.org' + ' $msg_uk #2' 'ftp2.uk.freebsd.org' + ' $msg_uk #3' 'ftp3.uk.freebsd.org' + ' $msg_uk #4' 'ftp4.uk.freebsd.org' + ' $msg_uk #5' 'ftp5.uk.freebsd.org' + ' $msg_uk #6' 'ftp6.uk.freebsd.org' + '$msg_ukraine' 'ftp.ua.freebsd.org' + ' $msg_ukraine #2' 'ftp2.ua.freebsd.org' + ' $msg_ukraine #5' 'ftp5.ua.freebsd.org' + ' $msg_ukraine #6' 'ftp6.ua.freebsd.org' + ' $msg_ukraine #7' 'ftp7.ua.freebsd.org' + ' $msg_ukraine #8' 'ftp8.ua.freebsd.org' + '$msg_usa #1' 'ftp1.us.freebsd.org' + ' $msg_usa #2' 'ftp2.us.freebsd.org' + ' $msg_usa #3' 'ftp3.us.freebsd.org' + ' $msg_usa #4' 'ftp4.us.freebsd.org' + ' $msg_usa #5' 'ftp5.us.freebsd.org' + ' $msg_usa #6' 'ftp6.us.freebsd.org' + ' $msg_usa #7' 'ftp7.us.freebsd.org' + ' $msg_usa #8' 'ftp8.us.freebsd.org' + ' $msg_usa #9' 'ftp9.us.freebsd.org' + ' $msg_usa #10' 'ftp10.us.freebsd.org' + ' $msg_usa #11' 'ftp11.us.freebsd.org' + ' $msg_usa #12' 'ftp12.us.freebsd.org' + ' $msg_usa #13' 'ftp13.us.freebsd.org' + ' $msg_usa #14' 'ftp14.us.freebsd.org' + ' $msg_usa #15' 'ftp15.us.freebsd.org' + " # END-QUOTE + + local size + size=$( eval f_dialog_menu_size \ + \"\$title\" \ + \"\$btitle\" \ + \"\$prompt\" \ + \"\$hline\" \ + $menu_list ) + + local dialog_menu retval mtag value + dialog_menu=$( eval $DIALOG \ + --title \"\$title\" \ + --backtitle \"\$btitle\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --menu \"\$prompt\" $size \ + $menu_list \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD + ) + retval=$? + setvar DIALOG_MENU_$$ "$dialog_menu" + mtag=$( f_dialog_menutag ) + + [ $retval -eq 0 ] || return $FAILURE + + case "$mtag" in + URL) setvar $VAR_FTP_PATH "other" ;; + *) + value=$( eval f_dialog_menutag2item \"\$mtag\" $menu_list ) + setvar $VAR_FTP_PATH "ftp://$value" + esac + + return $SUCCESS +} + +# f_media_set_ftp +# +# Return success if we both found and set the media type to be an FTP server. +# Variables from variable.subr that can be used to script user input: +# +# VAR_FTP_PATH +# Can be a URL (including "ftp://" protocol-prefix) or "other" +# (user is prompted to enter FTP URL). If a URL, can optionally +# contain directory prefix after hostname/port. Valid examples +# include: +# ftp://myhost +# ftp://somename:21/pub/ +# ftp://192.168.2.3/pub/ +# ftp://[::1]:21/ +# The default port if not specified is 21. +# VAR_NAMESERVER [Optional] +# If set, overrides resolv.conf(5) and sets the nameserver that +# is used to convert names into addresses (when a name converts +# into multiple addresses, the first address to successfully +# connect is used). +# +# Meanwhile, the following variables from variable.subr are set after +# successful execution: +# +# VAR_FTP_HOST +# The FTP host to connect to, parsed from VAR_FTP_PATH. In the +# example case of IPv6 where VAR_FTP_PATH is a "ftp://[::1]" this +# variable will be set to "::1" (the outer brackets are removed). +# VAR_FTP_PORT +# The TCP port to connect to, parsed from VAR_FTP_PATH. Usually +# 21 unless VAR_FTP_PATH was of one of the following forms: +# ftp://hostname:OTHER_PORT +# ftp://hostname:OTHER_PORT/* +# ftp://ip:OTHER_PORT +# ftp://ip:OTHER_PORT/* +# ftp://[ip6]:OTHER_PORT +# ftp://[ip6]:OTHER_PORT/* +# VAR_FTP_DIR +# If VAR_FTP_PATH contained a directory element (e.g., +# "ftp://localhost/pub") this variable contains only the +# directory element (e.g., "/pub"). +# +f_media_set_ftp() +{ + f_media_close + + local url + f_getvar $VAR_FTP_PATH url + + # If we've been through here before ... + if f_struct device_network && [ "${url#$msg_other}" ]; then + f_dialog_yesno "$msg_reuse_old_ftp_site_selection_values" || + url= + fi + + if [ ! "$url" ]; then + f_dialog_menu_media_ftp || return $FAILURE + f_getvar $VAR_FTP_PATH url + fi + [ "$url" ] || return $FAILURE + + case "$url" in + other) + setvar $VAR_FTP_PATH "ftp://" + f_variable_get_value $VAR_FTP_PATH \ + "$msg_please_specify_url_of_a_freebsd_distribution" + f_getvar $VAR_FTP_PATH url + if [ ! "${url#ftp://}" ]; then + unset $VAR_FTP_PATH + return $FAILURE + fi + if [ ${#url} -gt ${URL_MAX:-261261} ]; then + f_show_msg "$msg_length_of_specified_url_is_too_long" \ + ${#url} ${URL_MAX:-261261} + unset $VAR_FTP_PATH + return $FAILURE + fi + case "$url" in + ftp://*) : valid URL ;; + *) + f_show_msg "$msg_sorry_invalid_url" "$url" + unset $VAR_FTP_PATH + return $FAILURE + esac + esac + case "$url" in + ftp://*) : valid URL ;; + *) + f_show_msg "$msg_sorry_invalid_url" "$url" + unset $VAR_FTP_PATH + return $FAILURE + esac + + # Set the name of the FTP device to the URL + f_struct_new DEVICE device_ftp + device_ftp set name "$url" + + if ! f_struct device_network || + ! f_dialog_yesno "$msg_youve_already_done_the_network_configuration" + then + f_struct device_network && + f_device_shutdown network + if ! f_device_select_tcp; then + unset $VAR_FTP_PATH + return $FAILURE + fi + local dev + f_getvar $VAR_NETWORK_DEVICE dev + f_struct_copy "device_$dev" device_network + fi + if ! f_device_init network; then + f_dprintf "f_media_set_ftp: %s" "$msg_net_device_init_failed" + unset $VAR_FTP_PATH + return $FAILURE + fi + + local hostname="${url#*://}" port=21 dir=/ + case "$hostname" in + "["*"]") + hostname="${hostname#\[}" + hostname="${hostname%%\]*}" + ;; + "["*"]/"*) + hostname="${hostname#\[}" + dir="/${hostname#*/}" + hostname="${hostname%%\]*}" + ;; + *"/"*) + dir="/${hostname#*/}" + hostname="${hostname%%/*}" + ;; + "["*"]:"*) + hostname="${hostname#\[}" + port="${hostname#*\]:}" + port="${port%%[!0-9]*}" + hostname="${hostname%%\]:*}" + ;; + *) + hostname="${hostname%%/*}" + esac + + f_dprintf "hostname = \`%s'" "$hostname" + f_dprintf "dir = \`%s'" "$dir" + f_dprintf "port \# = \`%d'" "$port" + + local ns + f_getvar $VAR_NAMESERVER ns + [ "$ns" ] || f_resolv_conf_nameservers ns + if [ "$ns" -a ! "$FTP_SKIP_RESOLV" ] && ! { + f_validate_ipaddr "$hostname" || + f_validate_ipaddr6 "$hostname" + }; then + f_show_info "$msg_looking_up_host" "$hostname" + f_dprintf "%s: Looking up hostname, %s, using host(1)" \ + "f_media_set_ftp" "$hostname" + if ! f_quietly f_host_lookup "$hostname"; then + f_show_msg "$msg_cannot_resolve_hostname" "$hostname" + f_struct device_network && + f_device_shutdown network + f_struct_free device_network + unset $VAR_FTP_PATH + return $FAILURE + fi + f_dprintf "Found DNS entry for %s successfully." "$hostname" + fi + + setvar $VAR_FTP_HOST "$hostname" + setvar $VAR_FTP_PORT "$port" + setvar $VAR_FTP_DIR "$dir" + + device_ftp set type $DEVICE_TYPE_FTP + device_ftp set init f_media_init_ftp + device_ftp set get f_media_get_ftp + device_ftp set shutdown f_media_shutdown_ftp + device_ftp set private network + f_struct_copy device_ftp device_media + f_struct_free device_ftp + + return $SUCCESS +} + +# f_media_set_ftp_active +# +# Wrapper to f_media_set_ftp to access FTP servers actively. +# +f_media_set_ftp_active() +{ + setvar $VAR_FTP_STATE "active" + f_media_set_ftp +} + +# f_media_set_ftp_passive +# +# Wrapper to f_media_set_ftp to access FTP servers passively. +# +f_media_set_ftp_passive() +{ + setvar $VAR_FTP_STATE "passive" + f_media_set_ftp +} + +# f_media_set_ftp_userpass +# +# Prompt the user to enter/confirm the username/password variables that will +# be used to communicate with the FTP servers. Returns success if the user does +# not cancel or press Esc to either username or password. +# +# Variables from variable.subr that can be used to script user input: +# +# VAR_FTP_USER +# The username to send via ftp(1) when connecting to an FTP +# server. +# VAR_FTP_PASS +# The password to send with the above username. +# +# Does not prompt for confirmation of values if VAR_NONINTERACTIVE is set (see +# variable.subr for more information). +# +f_media_set_ftp_userpass() +{ + local user pass + f_variable_get_value $VAR_FTP_USER \ + "$msg_please_enter_the_username_you_wish_to_login_as" + f_getvar $VAR_FTP_USER user + if [ "$user" ]; then + f_variable_get_value $VAR_FTP_PASS \ + "$msg_please_enter_the_password_for_this_user" + f_getvar $VAR_FTP_PASS pass + else + pass= + fi + [ "$pass" ] # Return status +} + +# f_device_network_up $device +# +# Brings up attached network device, if any - takes FTP device as arg. +# +f_device_network_up() +{ + local dev="$1" netDev + device_$dev get private netDev || return $SUCCESS # No net == happy net + f_device_init $netDev +} + +# f_device_network_down $device +# +# Brings down attached network device, if any - takes FTP device as arg. +# +f_device_network_down() +{ + local dev="$1" netDev + device_$dev get private netDev || return $SUCCESS + f_device_shutdown $netDev +} + +# f_media_init_ftp $device +# +# Initializes the FTP media device. Returns success if both able to log into +# the FTP server and confirm the existence of at least one known release path +# using ftp(1). +# +# Variables from variable.subr used to initialize the connection are as follows +# (all of which are configured by f_media_set_ftp above): +# +# VAR_FTP_PATH +# The unparsed FTP URL representing the server to contact. +# Usually "ftp://server" for example. Can contain TCP port number +# and/or directory path (but should not contain username/password +# info). +# VAR_FTP_HOST +# The FTP host to connect to. Can be an IPv4 address (e.g., +# 127.0.0.1), IPv6 address (e.g., ::1), or DNS hostname. Usually +# set automatically in f_media_set_ftp() by parsing VAR_FTP_PATH. +# VAR_FTP_PORT +# The TCP port to connect to. Usually set automatically in +# f_media_set_ftp() by parsing VAR_FTP_PATH. +# VAR_FTP_DIR +# The base FTP directory to use when downloading files from the +# FTP server. Usually set automatically in f_media_set_ftp() by +# parsing VAR_FTP_PATH. +# VAR_FTP_USER [Optional] +# If unset, defaults to using anonymous access. +# VAR_FTP_PASS [Optional] +# If unset, defaults to a sensible value. +# +# In addition, the following (managed either manually or by f_media_set_ftp_*): +# +# VAR_FTP_STATE +# Sets FTPMODE for ftp(1) and can be one of: +# active active mode FTP only +# auto automatic determination of passive or active +# (this is the default) +# gate gate-ftp mode +# passive passive mode FTP only +# See ftp(1) for additional information. +# +# And last, but not least (managed automatically or manually): +# +# VAR_RELNAME +# Defaults to being set to $(uname -r) but can be overridden. +# This sets the name of a release to look for as part of a well +# known set of paths to search for release data once connected +# via FTP. If set to "__RELEASE" or "any" then the VAR_FTP_DIR is +# taken as the absolute path to the release and no further +# searching is done (see FTP_DIRS above in the GLOBALS section +# for a list of well known paths that are used when searching for +# a VAR_RELNAME sub-directory). +# +f_media_init_ftp() +{ + local dev="$1" + + local url + device_$dev get name url + f_dprintf "Init routine called for FTP device. url=[%s]" "$url" + + if [ "$FTP_INITIALIZED" ]; then + f_dprintf "FTP device already initialized." + return $SUCCESS + fi + + # If we can't initialize the network, bag it! + f_device_network_up $dev || return $FAILURE + + local cp + while :; do + f_getvar $VAR_FTP_PATH cp + if [ ! "$cp" ]; then + if ! f_media_set_ftp || + ! f_getvar $VAR_FTP_PATH cp || + [ ! "$cp" ] + then + f_dialog_msgbox \ + "$msg_unable_to_get_proper_ftp_path" + f_device_network_down $dev + return $FAILURE + fi + fi + + local ftp_host ftp_dir + if ! { + f_getvar $VAR_FTP_HOST ftp_host && + f_getvar $VAR_FTP_DIR ftp_dir + }; then + f_dialog_msgbox "$msg_missing_ftp_host_or_directory" + f_device_network_down $dev + return $FAILURE + fi + + local ftp_port + f_getvar $VAR_FTP_PORT ftp_port + local host="$ftp_host" port="${ftp_port:+:$ftp_port}" + case "$host" in *:*) host="[$host]"; esac + + local user pass use_anon="" + f_getvar $VAR_FTP_USER user + if [ ! "$user" ]; then + user="anonymous" + use_anon=1 + fi + if ! f_getvar $VAR_FTP_PASS pass; then + f_getvar $VAR_HOSTNAME cp + if f_running_as_init; then + pass="installer@$cp" + else + local name="$( id -un 2> /dev/null )" + pass="${name:-ftp}@$cp" + fi + fi + + f_show_info "$msg_logging_in_to_user_at_host" \ + "$user" "$ftp_host" + + local userpass="" + if [ ! "$use_anon" ] && [ "$user" -o "$pass" ]; then + userpass="$user${pass:+:$( f_uriencode "$pass" )}" + userpass="$userpass${userpass:+@}" + fi + + local mode rx + f_getvar $VAR_FTP_STATE mode + + if [ "$ftp_dir" ]; then + if ! rx=$( + printf 'cd "%s"\npwd\n' "$ftp_dir" | eval \ + FTPMODE=\"\$mode\" \ + ${use_anon:+FTPANONPASS=\"\$pass\"} \ + ftp -V ${use_anon:+-a} \ + \"ftp://\$userpass\$host\$port\" \ + 2>&1 + ); then + f_show_msg "$msg_couldnt_open_ftp_connection" \ + "$ftp_host" "$rx" + break # to failure + fi + if echo "$rx" | awk -v dir="/${ftp_dir#/}" ' + BEGIN { found = 0 } + /^Remote directory: / { + sub(/^[^:]*:[[:space:]]*/, "") + if ($0 != dir) next + found = 1; exit + } + END { exit ! found } + '; then + setvar $VAR_FTP_DIR "$ftp_dir" + setvar $VAR_FTP_PATH \ + "ftp://$ftp_host/${ftp_dir#/}" + else + f_show_msg \ + "$msg_please_check_the_url_and_try_again" \ + "ftp://$ftp_host/${ftp_dir#/}" + break # to failure + fi + fi + + # + # Now that we've verified that the path we're given is ok, + # let's try to be a bit intelligent in locating the release we + # are looking for. First off, if the release is specified as + # "__RELEASE" or "any", then just assume that the current + # directory is the one we want and give up. + # + local rel + f_getvar $VAR_RELNAME rel + f_dprintf "f_media_init_ftp: rel=[%s]" "$rel" + + case "$rel" in + __RELEASE|any) + FTP_INITIALIZED=YES + return $SUCCESS + ;; + *) + # + # Ok, since we have a release variable, let's walk + # through the list of directories looking for a release + # directory. First successful CWD wins. + # + if ! rx=$( + for dir in $FTP_DIRS; do + # Avoid confusing some servers + [ "$dir" = "." ] && continue + printf 'cd "/%s/%s"\npwd\n' \ + "$dir" "$rel" + done | eval \ + FTPMODE=\"\$mode\" \ + ${use_anon:+FTPANONPASS=\"\$pass\"} \ + ftp -V ${use_anon:+-a} \ + \"ftp://\$userpass\$host\$port\" \ + 2>&1 + ); then + f_show_msg "$msg_couldnt_open_ftp_connection" \ + "$ftp_host" "$rx" + break # to failure + fi + + local fdir + if fdir=$( echo "$rx" | awk ' + BEGIN { found = 0 } + /^Remote directory: / { + sub(/^[^:]*:[[:space:]]*/, "") + if ($0 == "/") next + # Exit after the first dir + found++; print; exit + } + END { exit ! found } + ' ); then + setvar $VAR_FTP_DIR "$fdir" + setvar $VAR_FTP_PATH "ftp://$ftp_host$fdir" + FTP_INITIALIZED=YES + return $SUCCESS + else + f_yesno "$msg_cant_find_distribution" \ + "$rel" "$ftp_host" + if [ $? -eq $SUCCESS ]; then + unset $VAR_FTP_PATH + f_media_set_ftp && continue + fi + fi + esac + break # to failure + done + + unset FTP_INITIALIZED $VAR_FTP_PATH + f_device_network_down $dev + return $FAILURE +} + +# f_media_get_ftp $device $file [$probe_only] +# +# Returns data from $file on an FTP server using ftp(1). Please note that +# $device is unused but must be present (even if null). Information is instead +# gathered from the environment. $probe_only is currently unused by this media +# type. +# +# Variables from variable.subr used to configure the connection are as follows +# (all of which are configured by f_media_set_ftp above): +# +# VAR_FTP_HOST +# FTP host to connect to. Can be an IPv4 address, IPv6 address, +# or DNS hostname of your choice. +# VAR_FTP_PORT +# TCP port to connect on; see f_media_set_ftp() above. +# VAR_FTP_USER [Optional] +# If unset, defaults to using anonymous access. +# VAR_FTP_PASS [Optional] +# If unset, defaults to a sensible value. +# +# In addition, the following (managed either manually or by f_media_set_ftp_*): +# +# VAR_FTP_STATE +# Sets FTPMODE for ftp(1) and can be one of: +# active active mode FTP only +# auto automatic determination of passive or active +# (this is the default) +# gate gate-ftp mode +# passive passive mode FTP only +# See ftp(1) for additional information. +# +# See variable.subr for additional information. +# +# Example usage: +# f_media_set_ftp +# f_media_get_ftp media $file +# +f_media_get_ftp() +{ + local dev="$1" file="$2" probe_only="$3" + + f_dprintf "f_media_get_ftp: dev=[%s] file=[%s] probe_only=%s" \ + "$dev" "$file" "$probe_only" + + local ftp_host ftp_port + f_getvar $VAR_FTP_HOST ftp_host + f_getvar $VAR_FTP_PORT ftp_port + + if [ ! "$FTP_INITIALIZED" ]; then + f_dprintf "No FTP connection open, can't get file %s" "$file" + return $FAILURE + fi + + if ! { + f_validate_ipaddr "$ftp_host" || + f_validate_ipaddr6 "$ftp_host" || + { + f_dprintf "%s: Looking up hostname, %s, using host(1)" \ + "f_media_get_ftp" "$ftp_host" + f_host_lookup "$ftp_host" hosts + } + }; then + # All the above validations failed + [ "$hosts" ] && f_dialog_msgbox "$hosts" + return $FAILURE + elif [ ! "$hosts" ]; then + # One of the first two validations passed + hosts="$ftp_host" + fi + + local host connected= + for host in $hosts; do + f_quietly nc -nz "$host" "$ftp_port" || continue + connected=1; break + done + if [ ! "$connected" ]; then + f_show_msg "$msg_couldnt_connect_to_ftp_server %s:%s" \ + "$ftp_host" "$ftp_port" + return $FAILURE + fi + + local user pass use_anon="" + f_getvar $VAR_FTP_USER user + if [ ! "$user" ]; then + user="anonymous" + use_anon=1 + fi + if ! f_getvar $VAR_FTP_PASS pass; then + f_getvar $VAR_HOSTNAME cp + if f_running_as_init; then + pass="installer@$cp" + else + local name="$( id -un 2> /dev/null )" + pass="${name:-ftp}@$cp" + fi + fi + + local userpass="" + if [ ! "$use_anon" ] && [ "$user" -o "$pass" ]; then + userpass="$user${pass:+:$( f_uriencode "$pass" )}" + userpass="$userpass${userpass:+@}" + fi + + local ftp_dir mode rx + f_getvar $VAR_FTP_DIR ftp_dir + f_getvar $VAR_FTP_STATE mode + + local dir="${ftp_dir#/}" + local port="${ftp_port:+:$ftp_port}" + case "$host" in *:*) host="[$host]"; esac + + f_dprintf "sending ftp request for: %s" "ftp://$host$port/$dir/$file" + + eval FTPMODE=\"\$mode\" ${use_anon:+FTPANONPASS=\"\$pass\"} \ + ftp -V ${use_anon:+-a} -o - \ + \"ftp://\$userpass\$host\$port/\$dir/\$file\" 2> /dev/null + local retval=$? + + [ $retval -eq $SUCCESS ] || f_dprintf "request failed!" + return $retval +} + +# f_media_shutdown_ftp $device +# +# Shuts down the FTP device. Return status should be ignored. Note that since +# we don't maintain an open connection to the FTP server there's nothing to do. +# +f_media_shutdown_ftp() +{ + [ "$FTP_INITIALIZED" ] || return $SUCCESS + + unset FTP_INITIALIZED +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." media/ftp.subr + +fi # ! $_MEDIA_FTP_SUBR diff --git a/usr.sbin/bsdconfig/share/media/httpproxy.subr b/usr.sbin/bsdconfig/share/media/httpproxy.subr new file mode 100644 index 00000000000..fad10077949 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/httpproxy.subr @@ -0,0 +1,433 @@ +if [ ! "$_MEDIA_HTTPPROXY_SUBR" ]; then _MEDIA_HTTPPROXY_SUBR=1 +# +# Copyright (c) 2012-2013 Devin Teske +# 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 (INLUDING, 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$ +# +############################################################ INCLUDES + +BSDCFG_SHARE="/usr/share/bsdconfig" +. $BSDCFG_SHARE/common.subr || exit 1 +f_dprintf "%s: loading includes..." media/httpproxy.subr +f_include $BSDCFG_SHARE/dialog.subr +f_include $BSDCFG_SHARE/variable.subr +f_include $BSDCFG_SHARE/media/ftp.subr +f_include $BSDCFG_SHARE/media/tcpip.subr + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +f_include_lang $BSDCFG_LIBE/include/messages.subr + +############################################################ FUNCTIONS + +# f_media_set_http_proxy +# +# Return success if we both found and set the media type to be an ftp server, +# accessed via http proxy. +# +# Variables from variable.subr that can be used to script user input: +# +# VAR_HTTP_PROXY +# HTTP Proxy server to use. Valid examples include: +# myhost +# somename:3128 +# 192.168.2.3 +# [::1]:8080 +# The default port if not specified is 3128. +# +# Variables from variable.subr that are set after successful execution include +# the following: +# +# VAR_HTTP_PROXY_HOST The host portion of VAR_HTTP_PROXY. +# VAR_HTTP_PROXY_PORT The TCP port parsed from VAR_HTTP_PROXY. +# +# See also f_media_set_ftp() for additional variables. +# +f_media_set_http_proxy() +{ + FTP_SKIP_RESOLV=1 f_media_set_ftp || return $FAILURE + + f_variable_get_value $VAR_HTTP_PROXY \ + "$msg_please_enter_the_address_of_the_http_proxy" + + local proxy + f_getvar $VAR_HTTP_PROXY proxy + [ "$proxy" ] || return $FAILURE + + local hostname="$proxy" port=3128 + case "$hostname" in + "["*"]") + hostname="${hostname#\[}" + hostname="${hostname%\]}" + ;; + "["*"]:") + hostname="${hostname#\[}" + port="${hostname#*\]:}" + port="${port%%[!0-9]*}" + hostname="${hostname%%\]:*}" + ;; + *":"*) + port="${hostname#*:}" + hostname="${hostname%%:*}" + esac + + setvar $VAR_HTTP_PROXY_HOST "$hostname" + setvar $VAR_HTTP_PROXY_PORT "$port" + + if f_debugging; then + f_dprintf "VAR_FTP_PATH : %s" "$( f_getvar $VAR_FTP_PATH )" + f_dprintf "VAR_HTTP_PROXY_HOST, _PORT: %s:%s" \ + "$( f_getvar $VAR_HTTP_PROXY_HOST )" \ + "$( f_getvar $VAR_HTTP_PROXY_PORT )" + fi + + # media device has been set by f_media_set_ftp(), overwrite partly: + device_media set type $DEVICE_TYPE_HTTP_PROXY + device_media set init f_media_init_http_proxy + device_media set get f_media_get_http_proxy + device_media unset shutdown + + return $SUCCESS +} + +# f_http_proxy_check_access [$connect_only] +# +# Return success if able list a remote FTP directory via HTTP proxy. If +# $connect_only is present and non-null, then returns success if a connection +# can be made. Variables from variable.subr that can be used to script user +# input: +# +# VAR_HTTP_PROXY_HOST +# The HTTP proxy server host name, IPv4 address or IPv6 address. +# Valid examples include: +# myhost +# 192.168.2.3 +# ::1 +# VAR_HTTP_PROXY_PORT +# The TCP port to connect to when communicating with the HTTP +# proxy server. +# VAR_HTTP_PROXY_PATH +# The FTP URL sent to the HTTP proxy server. Unused if +# $connect_only is present and non-NULL. +# +f_http_proxy_check_access() +{ + local connect_only="$1" hosts="" + + local proxy_host proxy_port + f_getvar $VAR_HTTP_PROXY_HOST proxy_host + f_getvar $VAR_HTTP_PROXY_PORT proxy_port + + if ! { + f_validate_ipaddr "$proxy_host" || + f_validate_ipaddr6 "$proxy_host" || + { + f_dprintf "%s: Looking up hostname, %s, using host(1)" \ + "f_http_proxy_check_access" "$proxy_host" + f_host_lookup "$proxy_host" hosts + } + }; then + # All the above validations failed + [ "$hosts" ] && f_dialog_msgbox "$hosts" + unset $VAR_HTTP_PROXY_HOST + return $FAILURE + elif [ ! "$hosts" ]; then + # One of the first two validations passed + hosts="$proxy_host" + fi + + local host connected= + for host in $hosts; do + f_quietly nc -nz "$host" "$proxy_port" || continue + connected=1; break + done + if [ ! "$connected" ]; then + f_show_msg "$msg_couldnt_connect_to_proxy %s:%s" \ + "$proxy_host" "$proxy_port" + unset $VAR_HTTP_PROXY_HOST + return $FAILURE + fi + [ "$connect_only" ] && return $SUCCESS + + # + # Some proxies fetch files with certain extensions in "ascii mode" + # instead of "binary mode" for FTP. The FTP server then translates all + # LF to CRLF. + # + # You can force Squid to use binary mode by appending ";type=i" to the + # URL, which is what sysinstall(8) has traditionally done. + # + + local proxy_path + f_getvar $VAR_HTTP_PROXY_PATH proxy_path + f_show_info "$msg_checking_access_to" "$proxy_path" + + local rx + if ! rx=$( + printf "GET %s/ HTTP/1.0\r\n\r\n" "${proxy_path%/}" | + nc -n "$host" "$proxy_port" + ); then + f_show_msg "$msg_couldnt_connect_to_proxy %s:%s" \ + "$proxy_host" "$proxy_port" + unset $VAR_HTTP_PROXY_HOST + return $FAILURE + fi + + local hdr + hdr=$( echo "$rx" | awk '/^\r$/{exit}{print}' ) + + local http_found=$FAILURE + if echo "$hdr" | awk ' + BEGIN { found = 0 } + /^HTTP.... 200 / { + found = 1 + exit + } + END { exit ! found } + '; then + http_found=$SUCCESS + fi + + # + # Scan the headers of the response + # this is extremely quick'n dity + # + + unset $VAR_HTTP_FTP_MODE + if echo "$hdr" | awk ' + BEGIN { found = 0 } + { + if (!match($0, /^Server: /)) next + found = ( substr($0, 9, 5) ~ /[Ss]quid/ ) + } + END { exit ! found } + '; then + setvar $VAR_HTTP_FTP_MODE ";type=i" + else + setvar $VAR_HTTP_FTP_MODE "" + fi + + return $http_found +} + +# f_media_init_http_proxy $device +# +# Initializes the HTTP Proxy media device. Returns success if able to confirm +# the existence of at least one known FTP server release path via HTTP proxy +# using f_http_proxy_check_access(), above. +# +# Variables from variable.subr that can be used to script user input: +# +# VAR_HTTP_PROXY_HOST +# The HTTP proxy server to connect to. Usually set by having +# f_media_set_http_proxy() parse VAR_HTTP_PROXY. Must be set. +# Also see f_http_proxy_check_access() for additional variables. +# VAR_RELNAME +# Usually set to `uname -r' but can be overridden. +# VAR_FTP_PATH +# The FTP URL to send to the HTTP proxy server. Usually set by +# calling f_media_set_ftp(). +# +# Meanwhile, after successful execution, the following variables (also from +# variable.subr) are set: +# +# VAR_HTTP_PROXY_PATH +# The [possibly] adjusted VAR_FTP_PATH that was found to contain +# a valid FreeBSD repository. +# +f_media_init_http_proxy() +{ + local dev="$1" + f_dprintf "Init routine called for HTTP Proxy device. dev=[%s]" "$dev" + + # + # First verify access + # + local connect_only=1 + f_http_proxy_check_access $connect_only + + local proxy_host + f_getvar $VAR_HTTP_PROXY_HOST proxy_host + while [ ! "$proxy_host" ]; do + f_media_set_http_proxy || return $FAILURE + f_http_proxy_check_access $connect_only + f_getvar $VAR_HTTP_PROXY_HOST proxy_host + done + + local rel proxy_path http_found=$FAILURE + while :; do + # + # If the release is specified as "__RELEASE" or "any", then + # just assume that the path the user gave is ok. + # + f_getvar $VAR_RELNAME rel + f_dprintf "f_media_init_http_proxy: rel=[%s]" "$rel" + + case "$rel" in + __RELEASE|any) + f_getvar $VAR_FTP_PATH $VAR_HTTP_PROXY_PATH + f_http_proxy_check_access + http_found=$? + ;; + *) + local fdir fp + f_getvar $VAR_FTP_PATH fp + for fdir in $FTP_DIRS; do + setvar $VAR_HTTP_PROXY_PATH "$fp/$fdir/$rel" + if f_http_proxy_check_access; then + http_found=$SUCCESS + break + fi + done + esac + + [ $http_found -eq $SUCCESS ] && break + + f_getvar $VAR_HTTP_PROXY_PATH proxy_path + f_show_msg "$msg_please_check_the_url_and_try_again" \ + "$proxy_path" + + unset $VAR_HTTP_PROXY_PATH + f_media_set_http_proxy || break + done + + return $http_found +} + +# f_media_get_http_proxy $device $file [$probe_only] +# +# Returns data from $file on an FTP server via HTTP proxy using nc(1). Please +# note that $device is unused but must be present (even if null). Information +# is instead gathered from the environment. $probe_only is currently unused by +# this media type. +# +# The variables used to configure the connection are as follows (all of which +# are configured by f_media_set_http_proxy above): +# +# VAR_HTTP_PROXY_HOST +# HTTP proxy host to connect. Can be an IPv4 address, IPv6 +# address, or DNS hostname of your choice. +# VAR_HTTP_PROXY_PORT +# TCP port to connect on; see f_media_set_http_proxy above. +# VAR_HTTP_PROXY_PATH +# URL (including "ftp://" protocol-prefix) of FTP directory to +# use as a prefix when requesting $file via HTTP proxy. +# +# See variable.subr for additional information. +# +# Example usage: +# f_media_set_http_proxy +# f_media_get_http_proxy media $file +# +f_media_get_http_proxy() +{ + local dev="$1" file="$2" probe_only="$3" hosts= + + f_dprintf "f_media_get_http_proxy: dev=[%s] file=[%s] probe_only=%s" \ + "$dev" "$file" "$probe_only" + + local proxy_host proxy_port + f_getvar $VAR_HTTP_PROXY_HOST proxy_host + f_getvar $VAR_HTTP_PROXY_PORT proxy_port + + if ! { + f_validate_ipaddr "$proxy_host" || + f_validate_ipaddr6 "$proxy_host" || + { + f_dprintf "%s: Looking up hostname, %s, using host(1)" \ + "f_media_get_http_proxy" "$proxy_host" + f_host_lookup "$proxy_host" hosts + } + }; then + # All the above validations failed + [ "$hosts" ] && f_dialog_msgbox "$hosts" + return $FAILURE + elif [ ! "$hosts" ]; then + # One of the first two validations passed + hosts="$proxy_host" + fi + + local host connected= + for host in $hosts; do + f_quietly nc -nz "$host" "$proxy_port" || continue + connected=1; break + done + if [ ! "$connected" ]; then + f_show_msg "$msg_couldnt_connect_to_proxy %s:%s" \ + "$proxy_host" "$proxy_port" + return $FAILURE + fi + + local proxy_path mode + f_getvar $VAR_HTTP_PROXY_PATH proxy_path + f_getvar $VAR_HTTP_FTP_MODE mode + local url="${proxy_path%/}/$file$mode" rx + + f_dprintf "sending http request for: %s" "$url" + printf "GET %s HTTP/1.0\r\n\r\n" "$url" | nc -n "$host" "$proxy_port" | + ( + # + # scan the headers of the response + # this is extremely quick'n dirty + # + + rv=0 + while read LINE; do + case "$LINE" in + HTTP*) + f_dprintf "received response: %s" "$LINE" + set -- $LINE; rv=$2 + f_isinteger "$rv" || rv=0 + ;; + *) + [ "${LINE% }" ] || break # End of headers + esac + done + + [ $rv -ge 500 ] && exit 5 + [ $rv -eq 404 ] && exit 44 + [ $rv -ge 400 ] && exit 4 + [ $rv -ge 300 ] && exit 3 + [ $rv -eq 200 ] || exit $FAILURE + + cat # output the rest ``as-is'' + exit 200 + ) + local retval=$? + [ $retval -eq 200 ] && return $SUCCESS + + case "$retval" in + 5) f_show_msg "$msg_server_error_when_requesting_url" "$url" ;; + 44) f_show_msg "$msg_url_was_not_found" "$url" ;; + 4) f_show_msg "$msg_client_error" ;; + *) f_show_msg "$msg_error_when_requesting_url" "$url" ;; + esac + return $FAILURE +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." media/httpproxy.subr + +fi # ! $_MEDIA_HTTPPROXY_SUBR diff --git a/usr.sbin/bsdconfig/share/media/network.subr b/usr.sbin/bsdconfig/share/media/network.subr new file mode 100644 index 00000000000..d9fe8e69889 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/network.subr @@ -0,0 +1,182 @@ +if [ ! "$_MEDIA_NETWORK_SUBR" ]; then _MEDIA_NETWORK_SUBR=1 +# +# Copyright (c) 2012-2013 Devin Teske +# 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 (INLUDING, 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$ +# +############################################################ INCLUDES + +BSDCFG_SHARE="/usr/share/bsdconfig" +. $BSDCFG_SHARE/common.subr || exit 1 +f_dprintf "%s: loading includes..." media/network.subr +f_include $BSDCFG_SHARE/dialog.subr +f_include $BSDCFG_SHARE/media/tcpip.subr + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +f_include_lang $BSDCFG_LIBE/include/messages.subr + +############################################################ GLOBALS + +NETWORK_INITIALIZED= + +############################################################ FUNCTIONS + +# f_media_init_network $device +# +# Initialize a network device (such as `fxp0', `em0', etc.). Returns success if +# able to successfully initialize the device. If not running as init (basically +# from the FreeBSD install media) then assume that the network has already been +# initialized and returns success. +# +# The variables (from variable.subr) used to initialize the network are as +# follows (all of which are configured either automatically or manaully): +# +# VAR_IFCONFIG + device_name (e.g., `ifconfig_em0') +# Automatically populated but can be overridden in a script. This +# defines the ifconfig(8) properties specific to a chosen network +# interface device. Optional if VAR_IPV6ADDR is set. +# VAR_IPV6ADDR [Optional] +# If not running as init (and setting up RTSOL connections for +# the interface), then must be set manually. If set, used as the +# IPv6 configuration for the given network interface device. +# VAR_GATEWAY [Optional] +# If not running as init (and setting up a static connection for +# the interface) then must be set (usually via rc.conf(5), but +# can be set manually to override). If unset, the user is warned +# but not prevented from proceeding (as most connections need a +# default route but not everyone). +# +f_media_init_network() +{ + local dev="$1" + + f_dprintf "Init routine called for network device \`%s'." "$dev" + if [ "$NETWORK_INITIALIZED" ]; then + f_dprintf "Network already initialized." + return $SUCCESS + elif ! f_running_as_init; then + f_dprintf "Not running as init -- calling the deed done." + NETWORK_INITIALIZED=1 + return $SUCCESS + fi + + if [ ! -e "$RESOLV_CONF" ]; then + if ! f_config_resolv; then + f_show_msg "$msg_cant_seem_to_write_out_resolv_conf" \ + "$RESOLV_CONF" + return $FAILURE + fi + fi + + local cp + if f_getvar $VAR_IFCONFIG$dev cp; then + # + # If this interface isn't a DHCP one, bring it up. + # If it is, then it's already up. + # + case "$cp" in + *DHCP*) + f_dprintf "A DHCP interface. Should already be up." + ;; + *) + f_dprintf "Not a DHCP interface." + if ! f_quietly ifconfig "$dev" $cp; then + f_show_msg "$msg_unable_to_configure_device" \ + "$dev" + return $FAILURE + fi + local rp + f_getvar $VAR_GATEWAY rp + if [ ! "$rp" ]; then + f_dialog_msgbox "$msg_no_gateway_has_been_set" + else + # + # Explicitly flush all routes to get back to a + # known sane state. We don't need to check this + # exit code because if anything fails it will + # show up in the route add below. + # + f_quietly route -n flush + f_dprintf "Adding default route to %s." "$rp" + if ! f_quietly route -n add default "$rp"; then + f_dialog_msgbox \ + "$msg_failed_to_add_default_route" + return $FAILURE + fi + fi + esac + elif ! { f_getvar $VAR_IPV6ADDR cp && [ "$cp" ]; }; then + f_show_msg "$msg_device_is_not_configured" "$dev" + return $FAILURE + fi + + f_dprintf "Network initialized successfully." + NETWORK_INITIALIZED=1 + return $SUCCESS +} + +# f_media_shutdown_network $device +# +# Shuts down the configured network device (e.g., `fxp0', `em0', etc.) and +# deletes the default route (if configured). Returns failure if the device +# passed has not been configured. If not running as init (basically from the +# FreeBSD install media) then does nothing and returns success. +# +f_media_shutdown_network() +{ + local dev="$1" cp + + f_dprintf "Shutdown called for network device %s" "$dev" + if [ ! "$NETWORK_INITIALIZED" ]; then + f_dprintf "Network not initialized -- nothing to do." + return $SUCCESS + fi + + unset NETWORK_INITIALIZED + unset $VAR_NETWORK_DEVICE + + if ! f_running_as_init; then + f_dprintf "Not running as init -- calling the deed done." + return $SUCCESS + fi + + f_getvar $VAR_IFCONFIG$dev cp || return $FAILURE + f_dprintf "ifconfig %s down" "$dev" + f_quietly ifconfig $dev down || + f_show_msg "$msg_unable_to_down_the_interface_properly" "$dev" + + if f_getvar $VAR_GATEWAY cp; then + f_dprintf "Deleting default route." + f_quietly route -n delete default + fi + + return $SUCCESS +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." media/network.subr + +fi # ! $_MEDIA_NETWORK_SUBR diff --git a/usr.sbin/bsdconfig/share/media/nfs.subr b/usr.sbin/bsdconfig/share/media/nfs.subr new file mode 100644 index 00000000000..461db1ce5f0 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/nfs.subr @@ -0,0 +1,251 @@ +if [ ! "$_MEDIA_NFS_SUBR" ]; then _MEDIA_NFS_SUBR=1 +# +# Copyright (c) 2012-2013 Devin Teske +# 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 (INLUDING, 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$ +# +############################################################ INCLUDES + +BSDCFG_SHARE="/usr/share/bsdconfig" +. $BSDCFG_SHARE/common.subr || exit 1 +f_dprintf "%s: loading includes..." media/nfs.subr +f_include $BSDCFG_SHARE/struct.subr +f_include $BSDCFG_SHARE/device.subr +f_include $BSDCFG_SHARE/dialog.subr +f_include $BSDCFG_SHARE/variable.subr +f_include $BSDCFG_SHARE/media/common.subr +f_include $BSDCFG_SHARE/media/tcpip.subr +f_include $BSDCFG_SHARE/media/network.subr + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +f_include_lang $BSDCFG_LIBE/include/messages.subr + +############################################################ GLOBALS + +NFS_MOUNTED= + +############################################################ FUNCTIONS + +# f_media_set_nfs +# +# Return success if we both found and set the media type to be an NFS server. +# Variables from variable.subr that can be used to script user input: +# +# VAR_NFS_PATH +# The NFS path specification (host:path) to use when mounting the +# remote repository. +# VAR_NAMESERVER [Optional] +# Automatically populated from resolv.conf(5) but can be +# overridden. If set, the host portion of VAR_NFS_PATH is +# looked up using f_host_lookup() from `tcpip.subr'. +# +# Meanwhile, the following variables from variable.subr are set after +# successful execution: +# +# VAR_NFS_HOST +# The host portion of the NFS path specification, parsed from +# VAR_NFS_PATH. +# +f_media_set_nfs() +{ + local nfs + + f_media_close + + f_variable_get_value $VAR_NFS_PATH \ + "$msg_please_enter_the_full_nfs_file_specification" + f_getvar $VAR_NFS_PATH nfs + [ "$nfs" ] || return $FAILURE + + case "$nfs" in + *:*) : valid NFS path ;; + *) + f_dialog_msgbox "$msg_invalid_nfs_path_specification" + return $FAILURE + esac + + f_struct_new DEVICE device_nfs + device_nfs set name "$nfs" + + if ! f_struct device_network || + ! f_dialog_yesno "$msg_youve_already_done_the_network_configuration" + then + f_struct device_network && + f_device_shutdown network + f_device_select_tcp || return $FAILURE + local dev + f_getvar $VAR_NETWORK_DEVICE dev + f_struct_copy "device_$dev" device_network + fi + f_device_init network || + f_dprintf "%s: $msg_net_device_init_failed\n" f_media_set_nfs + + local hostname="${nfs%%:*}" + if f_quietly f_getvar $VAR_NAMESERVER && ! { + f_validate_ipaddr "$hostname" || + f_validate_ipaddr6 "$hostname" + }; then + f_show_info "$msg_looking_up_host" "$hostname" + f_dprintf "%s Looking up hostname, %s, using host(1)" \ + "f_media_set_nfs" "$hostname" + if ! f_quietly f_host_lookup "$hostname"; then + f_show_msg "$msg_cannot_resolve_hostname" "$hostname" + f_struct device_network && + f_device_shutdown network + f_struct_free device_network + unset $VAR_NFS_PATH + return $FAILURE + fi + f_dprintf "Found DNS entry for %s successfully." "$hostname" + fi + + setvar $VAR_NFS_HOST "$hostname" + + device_nfs set type $DEVICE_TYPE_NFS + device_nfs set init f_media_init_nfs + device_nfs set get f_media_get_nfs + device_nfs set shutdown f_media_shutdown_nfs + device_nfs set private device_network # in name only (deref'd later) + + f_struct_copy device_nfs device_media + f_struct_free device_nfs + + return $SUCCESS +} + +# f_media_init_nfs $device +# +# Initializes the NFS media device. Returns success if able to mount the NFS +# device using mount_nfs(1). +# +# The variables (from variable.subr) used to initialize the NFS mount are as +# follows (all of which are configured manually/optionally from the options +# menu): +# +# VAR_NFS_TCP [Optional] +# If non-NULL, adds the "tcp" option via `-o' to mount_nfs(8). +# VAR_NFS_V3 [Optional] +# If non-NULL, adds the "nfsv3" option via `-o' to mount_nfs(8). +# VAR_NFS_SECURE [Optional] +# If non-NULL, adds the "-P" flag to mount_nfs(8). +# VAR_SLOW_ETHER [Optional] +# If non-NULL, adjusts the read/write size to avoid timeouts. +# +f_media_init_nfs() +{ + local dev="$1" name err + + device_$dev get name name || return $FAILURE + f_dprintf "Init routine called for NFS device. name=[%s]" \ + "$name" + + if [ "$NFS_MOUNTED" ]; then + f_dprintf "NFS device already mounted." + return $SUCCESS + fi + + if ! f_device_init network; then + f_dprintf "f_media_init_nfs: %s" "$msg_net_device_init_failed" + return $FAILURE + fi + + if [ ! -e "$MOUNTPOINT" ] && + ! err=$( mkdir -p "$MOUNTPOINT" 2>&1 ) + then + f_dialog_msgbox "$err" + return $FAILURE + fi + + local cp tcp="" use3="" secure="" readsize=4096 writesize=4096 + f_getvar $VAR_NFS_TCP cp + [ "$cp" = "YES" ] && tcp=1 + f_getvar $VAR_NFS_V3 cp + [ "$cp" = "YES" ] && use3=1 + f_getvar $VAR_NFS_SECURE cp + [ "$cp" = "YES" ] && secure=1 + f_getvar $VAR_SLOW_ETHER cp + [ "$cp" = "YES" ] && readsize=1024 writesize=1024 + + local options="rsize=$readsize,wsize=$writesize" + [ "$use3" ] && options="$options,nfsv3" + [ "$tcp" ] && options="$options,tcp" + + if ! err=$( mount_nfs \ + ${secure:+-P} -o "$options" "$name" "$MOUNTPOINT" 2>&1 ) + then + err="${err#mount_nfs: }" + f_show_msg "$msg_error_mounting_device" \ + "$name" "$MOUNTPOINT" "$err" + f_struct device_network && + f_device_shutdown network + return $FAILURE + fi + NFS_MOUNTED=1 + + f_dprintf "Mounted NFS device %s onto %s" "$name" "$MOUNTPOINT" + + return $SUCCESS +} + +# f_media_get_nfs $device $file [$probe_only] +# +# Returns data from $file on a mounted NFS device. Similar to cat(1). +# $probe_only is currently unused by this media type. +# +f_media_get_nfs() +{ + local dev="$1" file="$2" probe_only="$3" + + f_dprintf "f_media_get_nfs: dev=[%s] file=[%s] probe_only=%s" \ + "$dev" "$file" "$probe_only" + + f_media_generic_get "$MOUNTPOINT" "$file" +} + +# f_media_shutdown_nfs $device +# +# Shuts down the NFS device using umount(8). Return status should be ignored. +# +f_media_shutdown_nfs() +{ + local dev="$1" err + + [ "$NFS_MOUNTED" ] || return + + f_dprintf "Unmounting NFS partition on %s" "$MOUNTPOINT" + if ! err=$( umount -f "$MOUNTPOINT" 2>&1 ); then + err="${err#umount: }"; err="${err#*: }" + f_show_msg "$msg_could_not_unmount_the_nfs_partition" \ + "$MOUNTPOINT" "$err" + else + NFS_MOUNTED= + fi +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." media/nfs.subr + +fi # ! $_MEDIA_NFS_SUBR diff --git a/usr.sbin/bsdconfig/share/media/options.subr b/usr.sbin/bsdconfig/share/media/options.subr new file mode 100644 index 00000000000..c32bec511d7 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/options.subr @@ -0,0 +1,308 @@ +if [ ! "$_MEDIA_OPTIONS_SUBR" ]; then _MEDIA_OPTIONS_SUBR=1 +# +# Copyright (c) 2012-2013 Devin Teske +# 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 (INLUDING, 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$ +# +############################################################ INCLUDES + +BSDCFG_SHARE="/usr/share/bsdconfig" +. $BSDCFG_SHARE/common.subr || exit 1 +f_dprintf "%s: loading includes..." media/options.subr +f_include $BSDCFG_SHARE/dialog.subr +f_include $BSDCFG_SHARE/struct.subr +f_include $BSDCFG_SHARE/variable.subr +f_include $BSDCFG_SHARE/media/any.subr +f_include $BSDCFG_SHARE/media/ftp.subr + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +f_include_lang $BSDCFG_LIBE/include/messages.subr + +OPTIONS_HELPFILE=$BSDCFG_LIBE/include/options.hlp + +############################################################ FUNCTIONS + +# f_media_options_menu +# +# Prompt the user to confirm/edit various media settings. Returns success. +# +f_media_options_menu() +{ + f_dialog_title "$msg_options_editor" + local title="$DIALOG_TITLE" btitle="$DIALOG_BACKTITLE" + f_dialog_title_restore + local prompt="" + local hline="$hline_arrows_tab_enter" + local menu_list size cp + + # + # A hack so that the dialogs below are always interactive in a script + # + local old_interactive= + if ! f_interactive; then + f_getvar $VAR_NONINTERACTIVE old_interactive + unset $VAR_NONINTERACTIVE + fi + + while :; do + menu_list="" + + f_getvar $VAR_NFS_SECURE cp + if [ "$cp" = "YES" ]; then menu_list="$menu_list + ' $msg_nfs_secure' 'YES' + '$msg_nfs_server_talks_only_on_a_secure_port'" + else menu_list="$menu_list + ' $msg_nfs_secure' 'NO' + '$msg_nfs_server_talks_only_on_a_secure_port'" + fi + + f_getvar $VAR_SLOW_ETHER cp + if [ "$cp" = "YES" ]; then menu_list="$menu_list + ' $msg_nfs_slow' 'YES' + '$msg_user_is_using_a_slow_pc_or_ethernet_card'" + else menu_list="$menu_list + ' $msg_nfs_slow' 'NO' + '$msg_user_is_using_a_slow_pc_or_ethernet_card'" + fi + + f_getvar $VAR_NFS_TCP cp + if [ "$cp" = "YES" ]; then menu_list="$menu_list + ' $msg_nfs_tcp' 'YES' '$msg_use_tcp_protocol_for_nfs'" + else menu_list="$menu_list + ' $msg_nfs_tcp' 'NO' '$msg_use_tcp_protocol_for_nfs'" + fi + + f_getvar $VAR_NFS_V3 cp + if [ "$cp" = "YES" ]; then menu_list="$menu_list + ' $msg_nfs_version_3' 'YES' '$msg_use_nfs_version_3'" + else menu_list="$menu_list + ' $msg_nfs_version_3' 'NO' '$msg_use_nfs_version_3'" + fi + + f_getvar $VAR_DEBUG cp + if [ "$cp" ]; then menu_list="$menu_list + ' $msg_debugging' 'YES' + '$msg_emit_extra_debugging_output'" + else menu_list="$menu_list + ' $msg_debugging' 'NO' + '$msg_emit_extra_debugging_output'" + fi + + f_getvar $VAR_TRY_DHCP cp + if [ "$cp" = "YES" ]; then menu_list="$menu_list + ' $msg_dhcp' 'YES' + '$msg_attempt_automatic_dhcp_configuration'" + else menu_list="$menu_list + ' $msg_dhcp' 'NO' + '$msg_attempt_automatic_dhcp_configuration'" + fi + + f_getvar $VAR_TRY_RTSOL cp + if [ "$cp" = "YES" ]; then menu_list="$menu_list + ' $msg_ipv6' 'YES' + '$msg_attempt_ipv6_configuration_of_interfaces'" + else menu_list="$menu_list + ' $msg_ipv6' 'NO' + '$msg_attempt_ipv6_configuration_of_interfaces'" + fi + + f_getvar $VAR_FTP_USER cp + menu_list="$menu_list + ' $msg_ftp_username' '$cp' + '$msg_username_and_password_to_use'" + + f_getvar $VAR_EDITOR cp + menu_list="$menu_list + ' $msg_editor' '$cp' '$msg_which_text_editor_to_use'" + + f_getvar $VAR_RELNAME cp + menu_list="$menu_list + ' $msg_release_name' '$cp' + '$msg_which_release_to_attempt_to_load'" + + if f_struct device_media; then + device_media get type cp + case "$cp" in + $DEVICE_TYPE_UFS|$DEVICE_TYPE_DISK) + cp="$msg_file_system";; + $DEVICE_TYPE_DIRECTORY) + cp="$msg_directory";; + $DEVICE_TYPE_FLOPPY) + cp="$msg_floppy";; + $DEVICE_TYPE_FTP) + cp="$msg_ftp";; + $DEVICE_TYPE_HTTP_PROXY) + cp="$msg_http_proxy";; + $DEVICE_TYPE_CDROM) + cp="$msg_cdrom";; + $DEVICE_TYPE_USB) + cp="$msg_usb";; + $DEVICE_TYPE_DOS) + cp="$msg_dos";; + $DEVICE_TYPE_NFS) + cp="$msg_nfs";; + *) + cp="<$msg_unknown>" + esac + else + cp="<$msg_not_yet_set>" + fi + menu_list="$menu_list + ' $msg_media_type' '$cp' + '$msg_the_current_installation_media_type'" + + f_getvar $VAR_MEDIA_TIMEOUT cp + menu_list="$menu_list + ' $msg_media_timeout' '$cp' + '$msg_timeout_value_in_seconds_for_slow_media'" + + menu_list="$menu_list + ' $msg_rescan_devices' '<*>' + '$msg_rerun_bsdconfig_initial_device_probe' + ' $msg_use_defaults' '[${msg_reset}]' + '$msg_reset_all_values_to_startup_defaults' + " # END-QUOTE + + size=$( eval f_dialog_menu_with_help_size \ + \"\$title\" \ + \"\$btitle\" \ + \"\$prompt\" \ + \"\$hline\" \ + $menu_list ) + + local dialog_menu + + dialog_menu=$( eval $DIALOG \ + --title \"\$title\" \ + --backtitle \"\$btitle\" \ + --hline \"\$hline\" \ + --item-help \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_done\" \ + --help-button \ + --help-label \"\$msg_help\" \ + ${USE_XDIALOG:+--help \"\"} \ + --menu \"\$prompt\" $size $menu_list \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD + ) + local retval=$? + setvar DIALOG_MENU_$$ "$dialog_menu" + + local mtag + mtag=$( f_dialog_menutag ) + f_dprintf "retval=%s mtag=[%s]" $retval "$mtag" + + if [ $retval -eq 2 ]; then + # The Help button was pressed + f_show_help "$OPTIONS_HELPFILE" + continue + elif [ $retval -ne 0 ]; then + break # to success + fi + + case "$mtag" in + " $msg_nfs_secure") + f_getvar $VAR_NFS_SECURE cp + if [ "$cp" = "YES" ]; then + export $VAR_NFS_SECURE="NO" + else + export $VAR_NFS_SECURE="YES" + fi ;; + " $msg_nfs_slow") + f_getvar $VAR_SLOW_ETHER cp + if [ "$cp" = "YES" ]; then + export $VAR_SLOW_ETHER="NO" + else + export $VAR_SLOW_ETHER="YES" + fi ;; + " $msg_nfs_tcp") + f_getvar $VAR_NFS_TCP cp + if [ "$cp" = "YES" ]; then + export $VAR_NFS_TCP="NO" + else + export $VAR_NFS_TCP="YES" + fi ;; + " $msg_nfs_version_3") + f_getvar $VAR_NFS_V3 cp + if [ "$cp" = "YES" ]; then + export $VAR_NFS_V3="NO" + else + export $VAR_NFS_V3="YES" + fi ;; + " $msg_debugging") + if f_getvar $VAR_DEBUG cp && [ "$cp" ]; then + unset $VAR_DEBUG + else + export $VAR_DEBUG=1 + fi ;; + " $msg_dhcp") + f_getvar $VAR_TRY_DHCP cp + if [ "$cp" = "YES" ]; then + export $VAR_TRY_DHCP="NO" + else + export $VAR_TRY_DHCP="YES" + fi ;; + " $msg_ipv6") + f_getvar $VAR_TRY_RTSOL cp + if [ "$cp" = "YES" ]; then + export $VAR_TRY_RTSOL="NO" + else + export $VAR_TRY_RTSOL="YES" + fi ;; + " $msg_ftp_username") + f_media_set_ftp_userpass ;; + " $msg_editor") + f_variable_get_value $VAR_EDITOR \ + "$msg_please_specify_the_name_of_the_text_editor" + ;; + " $msg_release_name") + f_variable_get_value $VAR_RELNAME \ + "$msg_please_specify_the_release_you_wish_to_load" + ;; + " $msg_media_type") + f_media_get_type ;; + " $msg_media_timeout") + f_variable_get_value $VAR_MEDIA_TIMEOUT \ + "$msg_please_specify_the_number_of_seconds_to_wait" + ;; + " $msg_rescan_devices") + f_device_rescan ;; + " $msg_use_defaults") + f_variable_set_defaults ;; + esac + done + + # Restore old VAR_NONINTERACTIVE if needed. + [ "$old_interactive" ] && + setvar $VAR_NONINTERACTIVE "$old_interactive" + + return $SUCCESS +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." media/options.subr + +fi # ! $_MEDIA_OPTIONS_SUBR diff --git a/usr.sbin/bsdconfig/share/media/tcpip.subr b/usr.sbin/bsdconfig/share/media/tcpip.subr new file mode 100644 index 00000000000..0bf04870198 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/tcpip.subr @@ -0,0 +1,1688 @@ +if [ ! "$_MEDIA_TCPIP_SUBR" ]; then _MEDIA_TCPIP_SUBR=1 +# +# Copyright (c) 2012-2013 Devin Teske +# 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 (INLUDING, 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$ +# +############################################################ INCLUDES + +BSDCFG_SHARE="/usr/share/bsdconfig" +. $BSDCFG_SHARE/common.subr || exit 1 +f_dprintf "%s: loading includes..." media/tcpip.subr +f_include $BSDCFG_SHARE/struct.subr +f_include $BSDCFG_SHARE/device.subr +f_include $BSDCFG_SHARE/dialog.subr +f_include $BSDCFG_SHARE/variable.subr + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +f_include_lang $BSDCFG_LIBE/include/messages.subr + +TCP_HELPFILE=$BSDCFG_LIBE/include/tcp.hlp +NETWORK_DEVICE_HELPFILE=$BSDCFG_LIBE/include/network_device.hlp + +############################################################ GLOBALS + +# +# Path to resolv.conf(5). +# +: ${RESOLV_CONF:="/etc/resolv.conf"} + +# +# Path to nsswitch.conf(5). +# +: ${NSSWITCH_CONF:="/etc/nsswitch.conf"} + +# +# Path to hosts(5) +# +: ${ETC_HOSTS:="/etc/hosts"} + +# +# Structure of dhclient.leases(5) lease { ... } entry +# +f_struct_define DHCP_LEASE \ + interface \ + fixed_address \ + filename \ + server_name \ + script \ + medium \ + host_name \ + subnet_mask \ + routers \ + domain_name_servers \ + domain_name \ + broadcast_address \ + dhcp_lease_time \ + dhcp_message_type \ + dhcp_server_identifier \ + dhcp_renewal_time \ + dhcp_rebinding_time \ + renew \ + rebind \ + expire + +############################################################ FUNCTIONS + +# f_validate_hostname $hostname +# +# Returns zero if the given argument (a fully-qualified hostname) is compliant +# with standards set-forth in RFC's 952 and 1123 of the Network Working Group: +# +# RFC 952 - DoD Internet host table specification +# http://tools.ietf.org/html/rfc952 +# +# RFC 1123 - Requirements for Internet Hosts - Application and Support +# http://tools.ietf.org/html/rfc1123 +# +# See http://en.wikipedia.org/wiki/Hostname for a brief overview. +# +# The return status for invalid hostnames is one of: +# 255 Entire hostname exceeds the maximum length of 255 characters. +# 63 One or more individual labels within the hostname (separated by +# dots) exceeds the maximum of 63 characters. +# 1 One or more individual labels within the hostname contains one +# or more invalid characters. +# 2 One or more individual labels within the hostname starts or +# ends with a hyphen (hyphens are allowed, but a label cannot +# begin or end with a hyphen). +# 3 One or more individual labels within the hostname are null. +# +# f_dialog_validate_hostname $hostname +# +# If the hostname is determined to be invalid, the appropriate error will be +# displayed using the f_show_msg function. +# +f_validate_hostname() +{ + local fqhn="$1" + + # Return error if the hostname exceeds 255 characters + [ ${#fqhn} -gt 255 ] && return 255 + + local IFS="." # Split on `dot' + for label in $fqhn; do + # Return error if the label exceeds 63 characters + [ ${#label} -gt 63 ] && return 63 + + # Return error if the label is null + [ "$label" ] || return 3 + + # Return error if label begins/ends with dash + case "$label" in -*|*-) return 2; esac + + # Return error if the label contains any invalid chars + case "$label" in *[!0-9a-zA-Z-]*) return 1; esac + done + + return $SUCCESS +} + +# f_inet_atoi $ipv4_address [$var_to_set] +# +# Convert an IPv4 address or mask from dotted-quad notation (e.g., `127.0.0.1' +# or `255.255.255.0') to a 32-bit unsigned integer for the purpose of network +# and broadcast calculations. For example, one can validate that two addresses +# are on the same network: +# +# f_inet_atoi 1.2.3.4 ip1num +# f_inet_atoi 1.2.4.5 ip2num +# f_inet_atoi 255.255.0.0 masknum +# if [ $(( $ip1num & $masknum )) -eq \ +# $(( $ip2num & $masknum )) ] +# then +# : IP addresses are on same network +# fi +# +# See f_validate_ipaddr() below for an additional example usage, on calculating +# network and broadcast addresses. +# +# If $var_to_set is missing or NULL, the converted IP address is printed to +# standard output for capturing in a sub-shell (which is less-recommended +# because of performance degredation; for example, when called in a loop). +# +f_inet_atoi() +{ + local __addr="$1" __var_to_set="$2" __num=0 + if f_validate_ipaddr "$__addr"; then + __num=$( IFS=.; set -- $__addr; \ + echo $(( ($1 << 24) + ($2 << 16) + ($3 << 8) + $4 )) ) + fi + if [ "$__var_to_set" ]; then + setvar "$__var_to_set" $__num + else + echo $__num + fi +} + +# f_validate_ipaddr $ipaddr [$netmask] +# +# Returns zero if the given argument (an IP address) is of the proper format. +# +# The return status for invalid IP address is one of: +# 1 One or more individual octets within the IP address (separated +# by dots) contains one or more invalid characters. +# 2 One or more individual octets within the IP address are null +# and/or missing. +# 3 One or more individual octets within the IP address exceeds the +# maximum of 255 (or 2^8, being an octet comprised of 8 bits). +# 4 The IP address has either too few or too many octets. +# +# If a netmask is provided, the IP address is checked further: +# +# 5 The IP address must not be the network or broadcast address. +# +f_validate_ipaddr() +{ + local ip="$1" mask="$2" + + # Track number of octets for error checking + local noctets=0 + + local oldIFS="$IFS" + local IFS="." # Split on `dot' + for octet in $ip; do + # Return error if the octet is null + [ "$octet" ] || return 2 + + # Return error if not a whole integer + f_isinteger "$octet" || return 1 + + # Return error if not a positive integer + [ $octet -ge 0 ] || return 1 + + # Return error if the octet exceeds 255 + [ $octet -gt 255 ] && return 3 + + noctets=$(( $noctets + 1 )) + done + IFS="$oldIFS" + + [ $noctets -eq 4 ] || return 4 + + # + # The IP address must not be network or broadcast address. + # + if [ "$mask" ]; then + local ipnum masknum netnum bcastnum + local max_addr=4294967295 # 255.255.255.255 + + f_inet_atoi $ip ipnum + f_inet_atoi $mask masknum + + netnum=$(( $ipnum & $masknum )) + bcastnum=$(( ($ipnum & $masknum)+$max_addr-$masknum )) + + if [ "$masknum" ] && + [ $ipnum -eq $netnum -o $ipnum -eq $bcastnum ] + then + return 5 + fi + fi + + return $SUCCESS +} + +# f_validate_ipaddr6 $ipv6_addr +# +# Returns zero if the given argument (an IPv6 address) is of the proper format. +# +# The return status for invalid IP address is one of: +# 1 One or more individual segments within the IP address +# (separated by colons) contains one or more invalid characters. +# Segments must contain only combinations of the characters 0-9, +# A-F, or a-f. +# 2 Too many/incorrect null segments. A single null segment is +# allowed within the IP address (separated by colons) but not +# allowed at the beginning or end (unless a double-null segment; +# i.e., "::*" or "*::"). +# 3 One or more individual segments within the IP address +# (separated by colons) exceeds the length of 4 hex-digits. +# 4 The IP address entered has either too few (less than 3), too +# many (more than 8), or not enough segments, separated by +# colons. +# 5* The IPv4 address at the end of the IPv6 address is invalid. +# * When there is an error with the dotted-quad IPv4 address at the +# end of the IPv6 address, the return value of 5 is OR'd with a +# bit-shifted (<< 4) return of f_validate_ipaddr. +# +f_validate_ipaddr6() +{ + local ip="${1%\%*}" # removing the interface specification if-present + + local IFS=":" # Split on `colon' + set -- $ip: + + # Return error if too many or too few segments + # Using 9 as max in case of leading or trailing null spanner + [ $# -gt 9 -o $# -lt 3 ] && return 4 + + local h="[0-9A-Fa-f]" + local nulls=0 nsegments=$# contains_ipv4_segment= + + while [ $# -gt 0 ]; do + + segment="${1%:}" + shift + + # + # Return error if this segment makes one null too-many. A + # single null segment is allowed anywhere in the middle as well + # as double null segments are allowed at the beginning or end + # (but not both). + # + if [ ! "$segment" ]; then + nulls=$(( $nulls + 1 )) + if [ $nulls -eq 3 ]; then + # Only valid syntax for 3 nulls is `::' + [ "$ip" = "::" ] || return 2 + elif [ $nulls -eq 2 ]; then + # Only valid if begins/ends with `::' + case "$ip" in + ::*|*::) : fall thru ;; + *) return 2 + esac + fi + continue + fi + + # + # Return error if not a valid hexadecimal short + # + case "$segment" in + $h|$h$h|$h$h$h|$h$h$h$h) + : valid segment of 1-4 hexadecimal digits + ;; + *[!0-9A-Fa-f]*) + # Segment contains at least one invalid char + + # Return error immediately if not last segment + [ $# -eq 0 ] || return 1 + + # Otherwise, check for legacy IPv4 notation + case "$segment" in + *[!0-9.]*) + # Segment contains at least one invalid + # character even for an IPv4 address + return 1 + esac + + # Return error if not enough segments + if [ $nulls -eq 0 ]; then + [ $nsegments -eq 7 ] || return 4 + fi + + contains_ipv4_segment=1 + + # Validate the IPv4 address + f_validate_ipaddr "$segment" || + return $(( 5 | $? << 4 )) + ;; + *) + # Segment characters are all valid but too many + return 3 + esac + + done + + if [ $nulls -eq 1 ]; then + # Single null segment cannot be at beginning/end + case "$ip" in + :*|*:) return 2 + esac + fi + + # + # A legacy IPv4 address can span the last two 16-bit segments, + # reducing the amount of maximum allowable segments by-one. + # + maxsegments=8 + if [ "$contains_ipv4_segment" ]; then + maxsegments=7 + fi + + case $nulls in + # Return error if missing segments with no null spanner + 0) [ $nsegments -eq $maxsegments ] || return 4 ;; + # Return error if null spanner with too many segments + 1) [ $nsegments -le $maxsegments ] || return 4 ;; + # Return error if leading/trailing `::' with too many segments + 2) [ $nsegments -le $(( $maxsegments + 1 )) ] || return 4 ;; + esac + + return $SUCCESS +} + +# f_validate_netmask $netmask +# +# Returns zero if the given argument (a subnet mask) is of the proper format. +# +# The return status for invalid netmask is one of: +# 1 One or more individual fields within the subnet mask (separated +# by dots) contains one or more invalid characters. +# 2 One or more individual fields within the subnet mask are null +# and/or missing. +# 3 One or more individual fields within the subnet mask exceeds +# the maximum of 255 (a full 8-bit register). +# 4 The subnet mask has either too few or too many fields. +# 5 One or more individual fields within the subnet mask is an +# invalid integer (only 0,128,192,224,240,248,252,254,255 are +# valid integers). +# +f_validate_netmask() +{ + local mask="$1" + + # Track number of fields for error checking + local nfields=0 + + local IFS="." # Split on `dot' + for field in $mask; do + # Return error if the field is null + [ "$field" ] || return 2 + + # Return error if not a whole positive integer + f_isinteger "$field" || return 1 + + # Return error if the field exceeds 255 + [ $field -gt 255 ] && return 3 + + # Return error if the field is an invalid integer + case "$field" in + 0|128|192|224|240|248|252|254|255) :;; + *) return 5;; + esac + + nfields=$(( $nfields + 1 )) + done + + [ $nfields -eq 4 ] || return 4 +} + +# f_validate_gateway $gateway $ipaddr $netmask +# +# Validate an IPv4 default gateway (aka router) address for a given IP address +# making sure the two are in the same network (able to ``talk'' to each other). +# Returns success if $ipaddr and $gateway are in the same network given subnet +# mask $netmask. +# +f_validate_gateway() +{ + local gateway="$1" ipaddr="$2" netmask="$3" + local gwnum ipnum masknum + + f_validate_ipaddr "$gateway" "$netmask" || return $FAILURE + + f_inet_atoi "$netmask" masknum + f_inet_atoi "$ipaddr" ipnum + f_inet_atoi "$gateway" gwnum + + # Gateway must be within set of IPs reachable through interface + [ $(( $ipnum & $masknum )) -eq \ + $(( $gwnum & $masknum )) ] # Return status +} + +# f_dialog_validate_tcpip $hostname $gateway $nameserver $ipaddr $netmask +# +# Returns success if the arguments provided are valid for accessing a TCP/IP +# network, otherwise returns failure. +# +f_dialog_validate_tcpip() +{ + local hostname="$1" gateway="$2" nameserver="$3" + local ipaddr="$4" netmask="$5" + local ipnum masknum + + if [ ! "$hostname" ]; then + f_dialog_msgbox "$msg_must_specify_a_host_name_of_some_sort" + elif ! f_validate_hostname "$hostname"; then + f_dialog_msgbox "$msg_invalid_hostname_value" + elif [ "$netmask" ] && ! f_validate_netmask "$netmask"; then + f_dialog_msgbox "$msg_invalid_netmask_value" + elif [ "$nameserver" ] && + ! f_validate_ipaddr "$nameserver" && + ! f_validate_ipaddr6 "$nameserver"; then + f_dialog_msgbox "$msg_invalid_name_server_ip_address_specified" + elif [ "$ipaddr" ] && ! f_validate_ipaddr "$ipaddr" "$netmask"; then + f_dialog_msgbox "$msg_invalid_ipv4_address" + elif [ "$gateway" -a "$gateway" != "NO" ] && + ! f_validate_gateway "$gateway" "$ipaddr" "$netmask"; then + f_dialog_msgbox "$msg_invalid_gateway_ipv4_address_specified" + else + return $SUCCESS + fi + + return $FAILURE +} + +# f_ifconfig_inet $interface [$var_to_set] +# +# Returns the IPv4 address associated with $interface. If $var_to_set is +# missing or NULL, the IP address is printed to standard output for capturing +# in a sub-shell (which is less-recommended because of performance degredation; +# for example, when called in a loop). +# +# This function is a two-parter. Below is the awk(1) portion of the function, +# afterward is the sh(1) function which utilizes the below awk script. +# +f_ifconfig_inet_awk=' +BEGIN { found = 0 } +( $1 == "inet" ) \ +{ + print $2 + found = 1 + exit +} +END { exit ! found } +' +f_ifconfig_inet() +{ + local __interface="$1" __var_to_set="$2" + if [ "$__var_to_set" ]; then + local __ip + __ip=$( ifconfig "$__interface" 2> /dev/null | + awk "$f_ifconfig_inet_awk" ) + setvar "$__var_to_set" "$__ip" + else + ifconfig "$__interface" 2> /dev/null | + awk "$f_ifconfig_inet_awk" + fi +} + +# f_ifconfig_inet6 $interface [$var_to_set] +# +# Returns the IPv6 address associated with $interface. If $var_to_set is +# missing or NULL, the IP address is printed to standard output for capturing +# in a sub-shell (which is less-recommended because of performance degredation; +# for example, when called in a loop). +# +# This function is a two-parter. Below is the awk(1) portion of the function, +# afterward is the sh(1) function which utilizes the below awk script. +# +f_ifconfig_inet6_awk=' +BEGIN { found = 0 } +( $1 == "inet6" ) \ +{ + print $2 + found = 1 + exit +} +END { exit ! found } +' +f_ifconfig_inet6() +{ + local __interface="$1" __var_to_set="$2" + if [ "$__var_to_set" ]; then + local __ip6 + __ip6=$( ifconfig "$__interface" 2> /dev/null | + awk "$f_ifconfig_inet6_awk" ) + setvar "$__var_to_set" "$__ip6" + else + ifconfig "$__interface" 2> /dev/null | + awk "$f_ifconfig_inet6_awk" + fi +} + +# f_ifconfig_netmask $interface [$var_to_set] +# +# Returns the IPv4 subnet mask associated with $interface. If $var_to_set is +# missing or NULL, the netmask is printed to standard output for capturing in a +# sub-shell (which is less-recommended because of performance degredation; for +# example, when called in a loop). +# +f_ifconfig_netmask() +{ + local __interface="$1" __var_to_set="$2" __octets + __octets=$( ifconfig "$__interface" 2> /dev/null | awk \ + ' + BEGIN { found = 0 } + ( $1 == "inet" ) \ + { + printf "%s %s %s %s\n", + substr($4,3,2), + substr($4,5,2), + substr($4,7,2), + substr($4,9,2) + found = 1 + exit + } + END { exit ! found } + ' ) || return $FAILURE + + local __octet __netmask= + for __octet in $__octets; do + __netmask="$__netmask.$( printf "%u" "0x$__octet" )" + done + __netmask="${__netmask#.}" + if [ "$__var_to_set" ]; then + setvar "$__var_to_set" "$__netmask" + else + echo $__netmask + fi +} + +# f_route_get_default [$var_to_set] +# +# Returns the IP address of the currently active default router. If $var_to_set +# is missing or NULL, the IP address is printed to standard output for +# capturing in a sub-shell (which is less-recommended because of performance +# degredation; for example, when called in a loop). +# +# This function is a two-parter. Below is the awk(1) portion of the function, +# afterward is the sh(1) function which utilizes the below awk script. +# +f_route_get_default=' +BEGIN { found = 0 } +( $1 == "gateway:" ) \ +{ + print $2 + found = 1 + exit +} +END { exit ! found } +' +f_route_get_default() +{ + local __var_to_set="$1" + if [ "$__var_to_set" ]; then + local __ip + __ip=$( route -n get default 2> /dev/null | + awk "$f_route_get_default_awk" ) + setvar "$__var_to_set" "$__ip" + else + route -n get default 2> /dev/null | + awk "$f_route_get_default_awk" + fi +} + +# f_resolv_conf_nameservers [$var_to_set] +# +# Returns nameserver(s) configured in resolv.conf(5). If $var_to_set is missing +# or NULL, the list of nameservers is printed to standard output for capturing +# in a sub-shell (which is less-recommended because of performance degredation; +# for example, when called in a loop). +# +# This function is a two-parter. Below is the awk(1) portion of the function, +# afterward is the sh(1) function which utilizes the below awk script. +# +f_resolv_conf_nameservers_awk=' +BEGIN { found = 0 } +( $1 == "nameserver" ) \ +{ + print $2 + found = 1 +} +END { exit ! found } +' +f_resolv_conf_nameservers() +{ + local __var_to_set="$1" + if [ "$__var_to_set" ]; then + local __ns + __ns=$( awk "$f_resolv_conf_nameservers_awk" "$RESOLV_CONF" \ + 2> /dev/null ) + setvar "$__var_to_set" "$__ns" + else + awk "$f_resolv_conf_nameservers_awk" "$RESOLV_CONF" \ + 2> /dev/null + fi +} + +# f_config_resolv +# +# Attempts to configure resolv.conf(5) and ilk. Returns success if able to +# write the file(s), otherwise returns error status. +# +# Variables from variable.subr that are used in configuring resolv.conf(5) are +# as follows (all of which can be configured automatically through functions +# like f_dhcp_get_info() or manually): +# +# VAR_NAMESERVER +# The nameserver to add in resolv.conf(5). +# VAR_DOMAINNAME +# The domain to configure in resolv.conf(5). Also used in the +# configuration of hosts(5). +# VAR_IPADDR +# The IPv4 address to configure in hosts(5). +# VAR_IPV6ADDR +# The IPv6 address to configure in hosts(5). +# VAR_HOSTNAME +# The hostname to associate with the IPv4 and/or IPv6 address in +# hosts(5). +# +f_config_resolv() +{ + local cp c6p dp hp + + f_getvar $VAR_NAMESERVER cp + if [ "$cp" ]; then + case "$RESOLV_CONF" in + */*) f_quietly mkdir -p "${RESOLV_CONF%/*}" ;; + esac + + # Attempt to create/truncate the file + ( :> "$RESOLV_CONF" ) 2> /dev/null || return $FAILURE + + f_getvar $VAR_DOMAINNAME dp && + printf "domain\t%s\n" "$dp" >> "$RESOLV_CONF" + printf "nameserver\t%s\n" "$cp" >> "$RESOLV_CONF" + + f_dprintf "Wrote out %s" "$RESOLV_CONF" + fi + + f_getvar $VAR_DOMAINNAME dp + f_getvar $VAR_IPADDR cp + f_getvar $VAR_IPV6ADDR c6p + f_getvar $VAR_HOSTNAME hp + + # Attempt to create the file if it doesn't already exist + if [ ! -e "$ETC_HOSTS" ]; then + case "$ETC_HOSTS" in + */*) f_quietly mkdir -p "${ETC_HOSTS%/*}" ;; + esac + + ( :> "$ETC_HOSTS" ) 2> /dev/null || return $FAILURE + fi + + # Scan the file and add ourselves if not already configured + awk -v dn="$dp" -v ip4="$cp" -v ip6="$c6p" -v hn="$hp" ' + BEGIN { + local4found = local6found = 0 + hn4found = hn6found = h4found = h6found = 0 + h = ( match(hn, /\./) ? substr(hn, 0, RSTART-1) : "" ) + } + ($1 == "127.0.0.1") { local4found = 1 } + ($1 == "::1") { local6found = 1 } + { + for (n = 2; n <= NF; n++) + { + if ( $1 == ip4 ) { + if ( $n == h ) h4found = 1 + if ( $n == hn ) hn4found = 1 + if ( $n == hn "." ) hn4found = 1 + } + if ( $1 == ip6 ) { + if ( $n == h ) h6found = 1 + if ( $n == hn ) hn6found = 1 + if ( $n == hn "." ) hn6found = 1 + } + } + } + END { + hosts = FILENAME + + if ( ! local6found ) + printf "::1\t\t\tlocalhost%s\n", + ( dn ? " localhost." dn : "" ) >> hosts + if ( ! local4found ) + printf "127.0.0.1\t\tlocalhost%s\n", + ( dn ? " localhost." dn : "" ) >> hosts + + if ( ip6 && ! (h6found && hn6found)) + { + printf "%s\t%s %s\n", ip6, hn, h >> hosts + printf "%s\t%s.\n", ip6, hn >> hosts + } + else if ( ip6 ) + { + if ( ! h6found ) + printf "%s\t%s.\n", ip6, h >> hosts + if ( ! hn6found ) + printf "%s\t%s\n", ip6, hn >> hosts + } + + if ( ip4 && ! (h4found && hn4found)) + { + printf "%s\t\t%s %s\n", ip4, hn, h >> hosts + printf "%s\t\t%s.\n", ip4, hn >> hosts + } + else if ( ip4 ) + { + if ( ! h4found ) + printf "%s\t\t%s.\n", ip4, h >> hosts + if ( ! hn4found ) + printf "%s\t\t%s\n", ip4, hn >> hosts + } + } + ' "$ETC_HOSTS" 2> /dev/null || return $FAILURE + + f_dprintf "Wrote out %s" "$ETC_HOSTS" + return $SUCCESS +} + +# f_dhcp_parse_leases $leasefile struct_name +# +# Parse $leasefile and store the information for the most recent lease in a +# struct (see struct.subr for additional details) named `struct_name'. See +# DHCP_LEASE struct definition in the GLOBALS section above. +# +f_dhcp_parse_leases() +{ + local leasefile="$1" struct_name="$2" + + [ "$struct_name" ] || return $FAILURE + + if [ ! -e "$leasefile" ]; then + f_dprintf "%s: No such file or directory" "$leasefile" + return $FAILURE + fi + + f_struct "$struct_name" && f_struct_free "$struct_name" + f_struct_new DHCP_LEASE "$struct_name" + + eval "$( awk -v struct="$struct_name" ' + BEGIN { + lease_found = 0 + keyword_list = " \ + interface \ + fixed-address \ + filename \ + server-name \ + script \ + medium \ + " + split(keyword_list, keywords, FS) + + time_list = "renew rebind expire" + split(time_list, times, FS) + + option_list = " \ + host-name \ + subnet-mask \ + routers \ + domain-name-servers \ + domain-name \ + broadcast-address \ + dhcp-lease-time \ + dhcp-message-type \ + dhcp-server-identifier \ + dhcp-renewal-time \ + dhcp-rebinding-time \ + " + split(option_list, options, FS) + } + function set_value(prop,value) + { + lease_found = 1 + gsub(/[^[:alnum:]_]/, "_", prop) + sub(/;$/, "", value) + sub(/^"/, "", value) + sub(/"$/, "", value) + sub(/,.*/, "", value) + printf "%s set %s \"%s\"\n", struct, prop, value + } + /^lease {$/, /^}$/ \ + { + if ( $0 ~ /^lease {$/ ) next + if ( $0 ~ /^}$/ ) exit + + for (k in keywords) + { + keyword = keywords[k] + if ( $1 == keyword ) + { + set_value(keyword, $2) + next + } + } + + for (t in times) + { + time = times[t] + if ( $1 == time ) + { + set_value(time, $2 " " $3 " " $4) + next + } + } + + if ( $1 != "option" ) next + for (o in options) + { + option = options[o] + if ( $2 == option ) + { + set_value(option, $3) + next + } + } + } + EXIT { + if ( ! lease_found ) + { + printf "f_struct_free \"%s\"\n", struct + print "return $FAILURE" + } + } + ' "$leasefile" )" +} + +# f_dhcp_get_info $interface +# +# Parse the dhclient(8) lease database for $interface to obtain all the +# necessary IPv4 details necessary to communicate on the network. The retrieved +# information is stored in VAR_IPADDR, VAR_NETMASK, VAR_GATEWAY, and +# VAR_NAMESERVER. +# +# If reading the lease database fails, values are obtained from ifconfig(8) and +# route(8). If the DHCP lease did not provide a nameserver (or likewise, we +# were unable to parse the lease database), fall-back to resolv.conf(5) for +# obtaining the nameserver. Always returns success. +# +f_dhcp_get_info() +{ + local interface="$1" cp + local leasefile="/var/db/dhclient.leases.$interface" + + # If it fails, do it the old-fashioned way + if f_dhcp_parse_leases "$leasefile" lease; then + lease get fixed_address $VAR_IPADDR + lease get subnet_mask $VAR_NETMASK + lease get routers cp + setvar $VAR_GATEWAY "${cp%%,*}" + lease get domain_name_servers cp + setvar $VAR_NAMESERVER "${cp%%,*}" + lease get host_name cp && + setvar $VAR_HOSTNAME "$cp" + f_struct_free lease + else + # Bah, now we have to get the information from ifconfig + if f_debugging; then + f_dprintf "DHCP configured interface returns %s" \ + "$( ifconfig "$interface" )" + fi + f_ifconfig_inet "$interface" $VAR_IPADDR + f_ifconfig_netmask "$interface" $VAR_NETMASK + f_route_get_default $VAR_GATEWAY + fi + + # If we didn't get a name server value, hunt for it in resolv.conf + local ns + if [ -r "$RESOLV_CONF" ] && ! { + f_getvar $VAR_NAMESERVER ns || [ "$ns" ] + }; then + f_resolv_conf_nameservers cp && + setvar $VAR_NAMESERVER ${cp%%[$IFS]*} + fi + + return $SUCCESS +} + +# f_rtsol_get_info $interface +# +# Returns the rtsol-provided IPv6 address associated with $interface. The +# retrieved IP address is stored in VAR_IPV6ADDR. Always returns success. +# +f_rtsol_get_info() +{ + local interface="$1" cp + cp=$( ifconfig "$interface" 2> /dev/null | awk \ + ' + BEGIN { found = 0 } + ( $1 == "inet6" ) && ( $2 ~ /^fe80:/ ) \ + { + print $2 + found = 1 + exit + } + END { exit ! found } + ' ) && setvar $VAR_IPV6ADDR "$cp" +} + +# f_host_lookup $host [$var_to_set] +# +# Use host(1) to lookup (or reverse) an Internet number from (or to) a name. +# Multiple answers are returned separated by a single space. If host(1) does +# not exit cleanly, its full output is provided and the return status is 1. +# +# If nsswitch.conf(5) has been configured to query local access first for the +# `hosts' database, we'll manually check hosts(5) first (preventing host(1) +# from hanging in the event that DNS goes awry). +# +# If $var_to_set is missing or NULL, the list of IP addresses is printed to +# standard output for capturing in a sub-shell (which is less-recommended +# because of performance degredation; for example, when called in a loop). +# +# The variables from variable.subr used in looking up the host are as follows +# (which are set manually): +# +# VAR_IPV6_ENABLE [Optional] +# If set to "YES", enables the lookup of IPv6 addresses and IPv4 +# address. IPv6 addresses, if any, will come before IPv4. Note +# that if nsswitch.conf(5) shows an affinity for "files" for the +# "host" database and there is a valid entry in hosts(5) for +# $host, this setting currently has no effect (an IPv4 address +# can supersede an IPv6 address). By design, hosts(5) overrides +# any preferential treatment. Otherwise, if this variable is not +# set, IPv6 addresses will not be used (IPv4 addresses will +# specifically be requested from DNS). +# +# This function is a two-parter. Below is the awk(1) portion of the function, +# afterward is the sh(1) function which utilizes the below awk script. +# +f_host_lookup_awk=' +BEGIN{ addrs = "" } +!/^[[:space:]]*(#|$)/ \ +{ + for (n=1; n++ < NF;) if ($n == name) + addrs = addrs (addrs ? " " : "") $1 +} +END { + if (addrs) print addrs + exit !addrs +} +' +f_host_lookup() +{ + local __host="$1" __var_to_set="$2" + f_dprintf "f_host_lookup: host=[%s]" "$__host" + + # If we're configured to look at local files first, do that + if awk '/^hosts:/{exit !($2=="files")}' "$NSSWITCH_CONF"; then + if [ "$__var_to_set" ]; then + local __cp + if __cp=$( awk -v name="$__host" \ + "$f_host_lookup_awk" "$ETC_HOSTS" ) + then + setvar "$__var_to_set" "$__cp" + return $SUCCESS + fi + else + awk -v name="$__host" \ + "$f_host_lookup_awk" "$ETC_HOSTS" && + return $SUCCESS + fi + fi + + # + # Fall back to host(1) -- which is further governed by nsswitch.conf(5) + # + + local __output __ip6 __addrs="" __wait="" + f_getvar $VAR_MEDIA_TIMEOUT __wait + [ "$__wait" ] && __wait="-W $(( $__wait / 2 ))" + f_getvar $VAR_IPV6_ENABLE __ip6 + if [ "$__ip6" = "YES" ]; then + if ! __output=$( host -t AAAA $__wait -- "$__host" 2>&1 ); then + # An error occurred, display in-full and return error + [ "$__var_to_set" ] && + setvar "$__var_to_set" "$__output" + return $FAILURE + fi + __addrs=$( echo "$__output" | awk '/ address /{print $NF}' ) + fi + if ! __output=$( host -t A $__wait -- "$__host" 2>&1 ); then + # An error occurred, display it in-full and return error + [ "$__var_to_set" ] && setvar "$__var_to_set" "$__output" + return $FAILURE + fi + __addrs="$__addrs${__addrs:+ }$( + echo "$__output" | awk '/ address /{print $NF}' )" + if [ "$__var_to_set" ]; then + setvar "$__var_to_set" "$__addrs" + else + echo $__addrs + fi +} + +# f_device_dialog_tcp $device +# +# This is it - how to get TCP setup values. Prompt the user to edit/confirm the +# interface, gateway, nameserver, and hostname settings -- all required for +# general TCP/IP access. +# +# Variables from variable.subr that can be used to sript user input: +# +# VAR_NO_INET6 +# If set, prevents asking the user if they would like to use +# rtsol(8) to check for an IPv6 router. +# VAR_TRY_RTSOL +# If set to "YES" (and VAR_NONINTERACTIVE is unset), asks the +# user if they would like to try the IPv6 RouTer SOLicitation +# utility (rtsol(8)) to get IPv6 information. Ignored if +# VAR_NO_INET6 is set. +# VAR_TRY_DHCP +# If set to "YES" (and VAR_NONINTERACTIVE is unset), asks the +# user if they would like to try to acquire IPv4 connection +# settings from a DHCP server using dhclient(8). +# +# VAR_GATEWAY Default gateway to use. +# VAR_IPADDR Interface address to assign. +# VAR_NETMASK Interface subnet mask. +# VAR_EXTRAS Extra interface options to ifconfig(8). +# VAR_HOSTNAME Hostname to set. +# VAR_DOMAINNAME Domain name to use. +# VAR_NAMESERVER DNS nameserver to use when making lookups. +# VAR_IPV6ADDR IPv6 interface address. +# +# In addition, the following variables are used in acquiring network settings +# from the user: +# +# VAR_NONINTERACTIVE +# If set (such as when running in a script), prevents asking the +# user questions or displaying the usual prompts, etc. +# VAR_NETINTERACTIVE +# The one exception to VAR_NONINTERACTIVE is VAR_NETINTERACTIVE, +# which if set will prompt the user to try RTSOL (unless +# VAR_TRY_RTSOL has been set), try DHCP (unless VAR_TRY_DHCP has +# been set), and display the network verification dialog. This +# allows you to have a mostly non-interactive script that still +# prompts for network setup/confirmation. +# +# After successfull execution, the following variables are set: +# +# VAR_IFCONFIG + $device (e.g., `ifconfig_em0') +# Defines the ifconfig(8) properties specific to $device. +# +f_device_dialog_tcp() +{ + local dev="$1" cp n + local use_dhcp="" use_rtsol="" + local _ipaddr _netmask _extras + + [ "$dev" ] || return $FAILURE + + # Initialize vars from previous device values + local private + device_$dev get private private + if [ "$private" ] && f_struct "$private"; then + $private get ipaddr _ipaddr + $private get netmask _netmask + $private get extras _extras + $private get use_dhcp use_dhcp + $private get use_rtsol use_rtsol + else # See if there are any defaults + + # + # This is a hack so that the dialogs below are interactive in a + # script if we have requested interactive behavior. + # + local old_interactive= + if ! f_interactive && f_netinteractive; then + f_getvar $VAR_NONINTERACTIVE old_interactive + unset $VAR_NONINTERACTIVE + fi + + + # + # Try a RTSOL scan if such behavior is desired. + # If the variable was configured and is YES, do it. + # If it was configured to anything else, treat it as NO. + # Otherwise, ask the question interactively. + # + local try6 + if ! f_quietly f_getvar $VAR_NO_INET6 && { + { f_getvar $VAR_TRY_RTSOL try6 && [ "$try6" = "YES" ]; } || + { + ! f_quietly f_getvar $VAR_TRY_RTSOL && + f_dialog_noyes "$msg_try_ipv6_configuration" + } + }; then + local i + + f_quietly sysctl net.inet6.ip6.forwarding=0 + f_quietly sysctl net.inet6.ip6.accept_rtadv=1 + f_quietly ifconfig $dev up + + i=$( sysctl -n net.inet6.ip6.dad_count ) + sleep $(( $i + 1 )) + + f_quietly mkdir -p /var/run + f_dialog_info "$msg_scanning_for_ra_servers" + if f_quietly rtsol $dev; then + i=$( sysctl -n net.inet6.ip6.dad_count ) + sleep $(( $i + 1 )) + f_rtsol_get_info $dev + use_rtsol=1 + else + use_rtsol= + fi + fi + + # + # Try a DHCP scan if such behavior is desired. + # If the variable was configured and is YES, do it. + # If it was configured to anything else, treat it as NO. + # Otherwise, ask the question interactively. + # + local try4 + if { f_getvar $VAR_TRY_DHCP try4 && [ "$try4" = "YES" ]; } || { + ! f_quietly f_getvar $VAR_TRY_DHCP && + f_dialog_noyes "$msg_try_dhcp_configuration" + }; then + f_quietly ifconfig $dev delete + f_quietly mkdir -p /var/db + f_quietly mkdir -p /var/run + f_quietly mkdir -p /tmp + + local msg="$msg_scanning_for_dhcp_servers" + trap - SIGINT + ( # Execute in sub-shell to allow/catch Ctrl-C + trap 'exit $FAILURE' SIGINT + if [ "$USE_XDIALOG" ]; then + f_quietly dhclient $dev | + f_xdialog_info "$msg" + else + f_dialog_info "$msg" + f_quietly dhclient $dev + fi + ) + local retval=$? + trap 'f_interrupt' SIGINT + if [ $retval -eq $SUCCESS ]; then + f_dhcp_get_info $dev + use_dhcp=1 + else + use_dhcp= + fi + fi + + # Restore old VAR_NONINTERACTIVE if needed. + [ "$old_interactive" ] && + setvar $VAR_NONINTERACTIVE "$old_interactive" + + # Special hack so it doesn't show up oddly in the menu + local gw + if f_getvar $VAR_GATEWAY gw && [ "$gw" = "NO" ]; then + setvar $VAR_GATEWAY "" + fi + + # Get old IP address from variable space, if available + if [ ! "$_ipaddr" ]; then + if f_getvar $VAR_IPADDR cp; then + _ipaddr="$cp" + elif f_getvar ${dev}_$VAR_IPADDR cp; then + _ipaddr="$cp" + fi + fi + + # Get old netmask from variable space, if available + if [ ! "$_netmask" ]; then + if f_getvar $VAR_NETMASK cp; then + _netmask="$cp" + elif f_getvar ${dev}_$VAR_NETMASK cp; then + _netmask="$cp" + fi + fi + + # Get old extras string from variable space, if available + if [ ! "$_extras" ]; then + if f_getvar $VAR_EXTRAS cp; then + _extras="$cp" + elif f_getvar ${dev}_$VAR_EXTRAS cp; then + _extras="$cp" + fi + fi + fi + + # Look up values already recorded with the system, or blank the string + # variables ready to accept some new data + local _hostname _gateway _nameserver + f_getvar $VAR_HOSTNAME _hostname + case "$_hostname" in + *.*) : do nothing ;; # Already fully-qualified + *) + f_getvar $VAR_DOMAINNAME cp + [ "$cp" ] && _hostname="$_hostname.$cp" + esac + f_getvar $VAR_GATEWAY _gateway + f_getvar $VAR_NAMESERVER _nameserver + + # Re-check variables for initial inheritance before heading into dialog + [ "$_hostname" ] || _hostname="${HOSTNAME:-$( hostname )}" + [ "$_gateway" ] || f_route_get_default _gateway + [ ! "$_nameserver" ] && + f_resolv_conf_nameservers cp && _nameserver=${cp%%[$IFS]*} + [ "$_ipaddr" ] || f_ifconfig_inet $dev _ipaddr + [ "$_netmask" ] || f_ifconfig_netmask $dev _netmask + + # If non-interactive, jump over dialog section and into config section + if f_netinteractive || f_interactive || [ ! "$_hostname" ] + then + [ ! "$_hostname" ] && f_interactive && + f_dialog_msgbox "$msg_hostname_variable_not_set" + + local title=" $msg_network_configuration " + local hline="$hline_alnum_arrows_punc_tab_enter" + local extras_help="$tcplayout_extras_help" + + # Modify the help line for PLIP config + [ "${dev#plip}" != "$dev" ] && + extras_help="$tcplayout_extras_help_for_plip" + + f_getvar $VAR_IPV6ADDR cp && [ "$cp" ] && + title="$title($msg_ipv6_ready) " + + if [ ! "$USE_XDIALOG" ]; then + local prompt="$msg_dialog_mixedform_navigation_help" + # Calculate center position for displaying device label + local devlabel="$msg_configuration_for_interface $dev" + local width=54 + local n=$(( $width/2 - (${#devlabel} + 4)/2 - 2 )) + + while :; do + cp=$( $DIALOG \ + --title "$title" \ + --backtitle "$DIALOG_BACKTITLE" \ + --hline "$hline" \ + --item-help \ + --ok-label "$msg_ok" \ + --cancel-label "$msg_cancel" \ + --help-button \ + --help-label "$msg_help" \ + --mixedform "$prompt" 16 $width 9 \ + "$msg_host_name_including_domain:" 1 2 \ + "$_hostname" 2 3 45 255 0 \ + "$tcplayout_hostname_help" \ + "$msg_ipv4_gateway:" 3 2 \ + "$_gateway" 4 3 16 15 0 \ + "$tcplayout_gateway_help" \ + "$msg_name_server:" 3 31 \ + "$_nameserver" 4 32 16 15 0 \ + "$tcplayout_nameserver_help" \ + "- $devlabel -" 5 $n "" 0 0 0 0 3 "" \ + "$msg_ipv4_address:" 6 6 \ + "$_ipaddr" 7 7 16 15 0 \ + "$tcplayout_ipaddr_help" \ + "$msg_netmask:" 6 31 \ + "$_netmask" 7 32 16 15 0 \ + "$tcplayout_netmask_help" \ + "$msg_extra_options_to_ifconfig" 8 6 \ + "$_extras" 9 7 41 2048 0 \ + "$extras_help" \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) + + # --mixed-form always returns 0, we have to + # use the returned data to determine button + if [ ! "$cp" ]; then + # User either chose "Cancel", pressed + # ESC, or blanked every form field + return $FAILURE + else + n=$( echo "$cp" | f_number_of_lines ) + [ $n -eq 1 ] && case "$cp" in HELP*) + # User chose "Help" + f_show_help "$TCP_HELPFILE" + continue + esac + fi + + # Turn mixed-form results into env variables + eval "$( echo "$cp" | awk ' + BEGIN { + n = 0 + field[++n] = "_hostname" + field[++n] = "_gateway" + field[++n] = "_nameserver" + field[++n] = "_ipaddr" + field[++n] = "_netmask" + field[++n] = "_extras" + nfields = n + n = 0 + } + { + gsub(/'\''/, "'\'\\\\\'\''") + sub(/[[:space:]]*$/, "") + value[field[++n]] = $0 + } + END { + for ( n = 1; n <= nfields; n++ ) + { + printf "%s='\''%s'\'';\n", + field[n], + value[field[n]] + } + }' )" + + f_dialog_validate_tcpip \ + "$_hostname" \ + "$_gateway" \ + "$_nameserver" \ + "$_ipaddr" \ + "$_netmask" \ + && break + done + else + # Xdialog(1) does not support --mixed-form + # Create a persistent menu instead + + f_dialog_title "$msg_network_configuration" + local prompt="" + + while :; do + cp=$( $DIALOG \ + --title "$DIALOG_TITLE" \ + --backtitle "$DIALOG_BACKTITLE" \ + --hline "$hline" \ + --item-help \ + --ok-label "$msg_ok" \ + --cancel-label "$msg_cancel" \ + --help "" \ + --menu "$prompt" 21 60 8 \ + "$msg_accept_continue" "" \ + "$tcplayout_accept_cont_help" \ + "$msg_host_name_including_domain:" \ + "$_hostname" \ + "$tcplayout_hostname_help" \ + "$msg_ipv4_gateway:" "$_gateway" \ + "$tcplayout_gateway_help" \ + "$msg_name_server:" "$_nameserver" \ + "$tcplayout_nameserver_help" \ + "$msg_ipv4_address:" "$_ipaddr" \ + "$tcplayout_ipaddr_help" \ + "$msg_netmask:" "$_netmask" \ + "$tcplayout_netmask_help" \ + "$msg_extra_options_to_ifconfig" \ + "$_extras" "$extras_help" \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD + ) + local retval=$? + f_dprintf "retval=%u mtag=[%s]" $retval "$cp" + + if [ $retval -eq 2 ]; then + # The Help button was pressed + f_show_help "$TCP_HELPFILE" + continue + elif [ $retval -ne 0 ]; then + # User chose "Cancel" or pressed ESC + f_dialog_title_restore + return $FAILURE + fi + + case "$cp" in + "$msg_accept_continue") + f_dialog_validate_tcpip \ + "$_hostname" \ + "$_gateway" \ + "$_nameserver" \ + "$_ipaddr" \ + "$_netmask" \ + && break ;; + "$msg_host_name_including_domain:") + cp=$( f_dialog_input "$cp" \ + "$_hostname" + ) && _hostname="$cp" ;; + "$msg_ipv4_gateway:") + cp=$( f_dialog_input "$cp" \ + "$_gateway" + ) && _gateway="$cp" ;; + "$msg_name_server:") + cp=$( f_dialog_input "$cp" \ + "$_nameserver" + ) && _nameserver="$cp" ;; + "$msg_ipv4_address:") + cp=$( f_dialog_input "$cp" \ + "$_ipaddr" + ) && _ipaddr="$cp" ;; + "$msg_netmask:") + cp=$( f_dialog_input "$cp" \ + "$_netmask" + ) && _netmask="$cp" ;; + "$msg_extra_options_to_ifconfig") + cp=$( f_dialog_input "$cp" \ + "$_extras" + ) && _extras="$cp" ;; + esac + done + + f_dialog_title_restore + + fi # XDIALOG + + fi # interactive + + # We actually need to inform the rest of bsdconfig about this + # data now if the user hasn't selected cancel. + + if [ "$_hostname" ]; then + setvar $VAR_HOSTNAME "$_hostname" + f_quietly hostname "$_hostname" + case "$_hostname" in + *.*) setvar $VAR_DOMAINNAME "${_hostname#*.}" ;; + esac + fi + [ "$_gateway" ] && setvar $VAR_GATEWAY "$_gateway" + [ "$_nameserver" ] && setvar $VAR_NAMESERVER "$_nameserver" + [ "$_ipaddr" ] && setvar $VAR_IPADDR "$_ipaddr" + [ "$_netmask" ] && setvar $VAR_NETMASK "$_netmask" + [ "$_extras" ] && setvar $VAR_EXTRAS "$_extras" + + f_dprintf "Creating struct DEVICE_INFO devinfo_%s" "$dev" + f_struct_new DEVICE_INFO devinfo_$dev + device_$dev set private devinfo_$dev + + devinfo_$dev set ipaddr $_ipaddr + devinfo_$dev set netmask $_netmask + devinfo_$dev set extras $_extras + devinfo_$dev set use_rtsol $use_rtsol + devinfo_$dev set use_dhcp $use_dhcp + + if [ "$use_dhcp" -o "$_ipaddr" ]; then + if [ "$use_dhcp" ]; then + cp="DHCP${extras:+ $extras}" + else + cp="inet $_ipaddr netmask $_netmask${extras:+ $extras}" + fi + setvar $VAR_IFCONFIG$dev "$cp" + fi + [ "$use_rtsol" ] && + setvar $VAR_IPV6_ENABLE "YES" + + [ "$use_dhcp" ] || + f_config_resolv # XXX this will do it on the MFS copy + + return $SUCCESS +} + +# f_device_scan_tcp [$var_to_set] +# +# Scan for the first active/configured TCP/IP device. The name of the interface +# is printed to stderr like other dialog(1)-based functions (stdout is reserved +# for dialog(1) interaction) if $var_to_set is missing or NULL. Returns failure +# if no active/configured interface +# +f_device_scan_tcp() +{ + local __var_to_set="$1" __iface + for __iface in $( ifconfig -l ); do + if ifconfig $__iface | awk ' + BEGIN { + has_inet = has_inet6 = is_ethernet = 0 + is_usable = 1 + } + ( $1 == "status:" && $2 != "active" ) { is_usable = 0; exit } + ( $1 == "inet" ) { + if ($2 == "0.0.0.0") { is_usable = 0; exit } + has_inet++ + } + ( $1 == "inet6") { has_inet6++ } + ( $1 == "media:" ) { + if ($2 != "Ethernet") { is_usable = 0; exit } + is_ethernet = 1 + } + END { + if (!(is_ethernet && (has_inet || has_inet6))) + is_usable = 0 + exit ! is_usable + }'; then + f_interactive && + f_show_msg "$msg_using_interface" "$__iface" + f_dprintf "f_device_scan_tcp found %s" "$__iface" + if [ "$__var_to_set" ]; then + setvar "$__var_to_set" "$__iface" + else + echo "$__iface" >&2 + fi + return $SUCCESS + fi + done + + return $FAILURE +} + +# f_device_select_tcp +# +# Prompt the user to select network interface to use for TCP/IP access. +# Variables from variable.subr that can be used to script user input: +# +# VAR_NETWORK_DEVICE [Optional] +# Either a comma-separated list of network interfaces to try when +# setting up network access (e.g., "fxp0,em0") or "ANY" (case- +# sensitive) to indicate that the first active and configured +# interface is acceptable. If unset, the user is presented with a +# menu of all available network interfaces. +# +# Returns success if a valid network interface has been selected. +# +f_device_select_tcp() +{ + local devs dev cnt network_dev + f_getvar $VAR_NETWORK_DEVICE network_dev + + f_dprintf "f_device_select_tcp: %s=[%s]" \ + VAR_NETWORK_DEVICE "$network_dev" + + if [ "$network_dev" ]; then + # + # This can be set to several types of values. If set to ANY, + # scan all network devices looking for a valid link, and go + # with the first device found. Can also be specified as a + # comma delimited list, with each network device tried in + # order. Can also be set to a single network device. + # + [ "$network_dev" = "ANY" ] && f_device_scan_tcp network_dev + + while [ "$network_dev" ]; do + case "$network_dev" in + *,*) dev="${network_dev%%,*}" + network_dev="${network_dev#*,}" + ;; + *) dev="$network_dev" + network_dev= + esac + + f_device_find "$dev" $DEVICE_TYPE_NETWORK devs + cnt=$( set -- $devs; echo $# ) + + if [ ${cnt:=0} -gt 0 ]; then + dev="${devs%%[$IFS]*}" + f_device_dialog_tcp $dev + if [ $? -eq $SUCCESS ]; then + setvar $VAR_NETWORK_DEVICE $dev + return $SUCCESS + fi + fi + done + + f_interactive && f_dialog_msgbox "$msg_no_network_devices" + return $FAILURE + + fi # $network_dev + + f_device_find "" $DEVICE_TYPE_NETWORK devs + cnt=$( set -- $devs; echo $# ) + dev="${devs%%[$IFS]*}" + + f_quietly f_getvar NETWORK_CONFIGURED # for debugging info + if ! f_running_as_init && + ! [ "${NETWORK_CONFIGURED+set}" -a "$NETWORK_CONFIGURED" = "NO" ] + then + trap 'f_interrupt' SIGINT + if f_dialog_yesno "$msg_assume_network_is_already_configured" + then + setvar $VAR_NETWORK_DEVICE $dev + return $SUCCESS + fi + fi + + local retval=$SUCCESS + if [ ${cnt:=0} -eq 0 ]; then + f_dialog_msgbox "$msg_no_network_devices" + retval=$FAILURE + elif [ $cnt -eq 1 ]; then + f_device_dialog_tcp $dev + retval=$? + [ $retval -eq $SUCCESS ] && setvar $VAR_NETWORK_DEVICE $dev + else + local title="$msg_network_interface_information_required" + local prompt="$msg_please_select_ethernet_device_to_configure" + local hline="$hline_arrows_tab_enter" + + dev=$( f_device_menu \ + "$title" "$prompt" "$hline" $DEVICE_TYPE_NETWORK \ + "$NETWORK_DEVICE_HELPFILE" \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) + retval=$? + [ "$dev" ] || return $FAILURE + + f_device_find "$dev" $DEVICE_TYPE_NETWORK devs + [ "$devs" ] || return $FAILURE + dev="${devs%%[$IFS]*}" + + f_device_dialog_tcp $dev + retval=$? + if [ $retval -eq $SUCCESS ]; then + f_struct_copy device_$dev device_network + setvar $VAR_NETWORK_DEVICE network + else + f_struct_free device_network + fi + fi + + return $retval +} + +# f_dialog_menu_select_tcp +# +# Like f_dialog_select_tcp() above, but do it from a menu that doesn't care +# about status. In other words, where f_dialog_select_tcp() will not display a +# menu if scripted, this function will always display the menu of available +# network interfaces. +# +f_dialog_menu_select_tcp() +{ + local private use_dhcp name + NETWORK_CONFIGURED=NO f_device_select_tcp + if f_struct device_network && + device_network get private private && + f_struct_copy "$private" di && + di get use_dhcp use_dhcp && + [ ! "$use_dhcp" ] && + device_network get name name && + f_yesno "$msg_would_you_like_to_bring_interface_up" "$name" + then + if ! f_device_init network; then + f_show_msg "$msg_initialization_of_device_failed" \ + "$name" + fi + fi + return $SUCCESS +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." media/tcpip.subr + +fi # ! $_MEDIA_TCPIP_SUBR diff --git a/usr.sbin/bsdconfig/share/media/ufs.subr b/usr.sbin/bsdconfig/share/media/ufs.subr new file mode 100644 index 00000000000..0b70f093c52 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/ufs.subr @@ -0,0 +1,193 @@ +if [ ! "$_MEDIA_UFS_SUBR" ]; then _MEDIA_UFS_SUBR=1 +# +# Copyright (c) 2012-2013 Devin Teske +# 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 (INLUDING, 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$ +# +############################################################ INCLUDES + +BSDCFG_SHARE="/usr/share/bsdconfig" +. $BSDCFG_SHARE/common.subr || exit 1 +f_dprintf "%s: loading includes..." media/ufs.subr +f_include $BSDCFG_SHARE/struct.subr +f_include $BSDCFG_SHARE/device.subr +f_include $BSDCFG_SHARE/dialog.subr +f_include $BSDCFG_SHARE/variable.subr +f_include $BSDCFG_SHARE/media/common.subr + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +f_include_lang $BSDCFG_LIBE/include/messages.subr + +############################################################ GLOBALS + +UFS_MOUNTED= + +############################################################ FUNCTIONS + +# f_media_set_ufs +# +# Return success if we both found and set the media type to be a UFS partition. +# Variables from variable.subr that can be used to script user input: +# +# VAR_UFS_PATH +# Path to a UFS character device node to be used with mount(8) in +# mounting a UFS formatted partition. Valid examples include: +# /dev/da0s1a +# /dev/ad4s1e +# However, other forms may be valid (see mount(8) for additional +# information). +# +f_media_set_ufs() +{ + local ufs + + f_media_close + + local devs ndevs + f_device_find "" $DEVICE_TYPE_UFS devs + ndevs=$( set -- $devs; echo $# ) + + if [ ${ndevs:=0} -eq 0 ]; then + f_variable_get_value $VAR_UFS_PATH \ + "$msg_enter_the_device_name_of_a_ufs_formatted_partition" + f_getvar $VAR_UFS_PATH ufs + [ "$ufs" ] || return $FAILURE + + local fstype + fstype=$( df -nT $ufs 2> /dev/null | + awk '!/Type/{print $2;exit}' ) + + f_struct_new DEVICE device_ufs + device_ufs set name ${fstype:-ufs} + device_ufs set devname "$ufs" + device_ufs set get f_media_get_ufs + device_ufs set init f_media_init_ufs + device_ufs set shutdown f_media_shutdown_ufs + device_ufs unset private + + f_struct_copy device_ufs device_media + f_struct_free device_ufs + elif [ $ndevs -gt 1 ]; then + local title="$msg_choose_a_ufs_partition" + local prompt="$msg_please_select_ufs_partition" + local hline="" + + local dev retval + dev=$( f_device_menu \ + "$title" "$prompt" "$hline" $DEVICE_TYPE_UFS \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) + retval=$? + [ "$dev" ] || return $FAILURE + + f_struct_copy device_$dev device_media + [ $retval -eq $SUCCESS ] || return $FAILURE + else + f_struct_copy device_$devs device_media + fi + + f_struct device_media || return $FAILURE +} + +# f_media_init_ufs $device +# +# Initializes the UFS media device. Returns success if able to mount the UFS +# partition device using mount(1). +# +f_media_init_ufs() +{ + local dev="$1" devname err + + device_$dev get devname devname || return $FAILURE + f_dprintf "Init routine called for UFS device. devname=[%s]" \ + "$devname" + + if [ "$UFS_MOUNTED" ]; then + f_dprintf "UFS device already mounted." + return $SUCCESS + fi + + if [ ! -e "$devname" ]; then + f_show_msg "$msg_no_such_file_or_directory" \ + "f_media_init_ufs" "$devname" + return $FAILURE + fi + + if [ ! -e "$MOUNTPOINT" ] && + ! err=$( mkdir -p "$MOUNTPOINT" 2>&1 ) + then + f_dialog_msgbox "$err" + return $FAILURE + fi + + if ! err=$( mount "$devname" "$MOUNTPOINT" 2>&1 ) + then + err="${err#mount: }"; err="${err#$devname : }" + f_show_msg "$msg_error_mounting_device" \ + "$devname" "$MOUNTPOINT" "$err" + return $FAILURE + fi + UFS_MOUNTED=1 + return $SUCCESS +} + +# f_media_get_ufs $device $file [$probe_only] +# +# Returns data from $file on a mounted UFS partition device. Similar to cat(1). +# $probe_only is currently unused by this media type. +# +f_media_get_ufs() +{ + local dev="$1" file="$2" probe_only="$3" + + f_dprintf "f_media_get_ufs: dev=[%s] file=[%s] probe_only=%s" \ + "$dev" "$file" "$probe_only" + + f_media_generic_get "$MOUNTPOINT" "$file" +} + +# f_media_shutdown_ufs $device +# +# Shuts down the UFS device using umount(8). Return status should be ignored. +# +f_media_shutdown_ufs() +{ + local dev="$1" err + + [ "$UFS_MOUNTED" ] || return + + if ! err=$( umount -f "$MOUNTPOINT" 2>&1 ); then + err="${err#umount: }"; err="${err#*: }" + f_show_msg "$msg_could_not_unmount_the_ufs_partition" \ + "$MOUNTPOINT" "$err" + else + UFS_MOUNTED= + fi +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." media/ufs.subr + +fi # ! $_MEDIA_UFS_SUBR diff --git a/usr.sbin/bsdconfig/share/media/usb.subr b/usr.sbin/bsdconfig/share/media/usb.subr new file mode 100644 index 00000000000..c7fc97317f8 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/usb.subr @@ -0,0 +1,174 @@ +if [ ! "$_MEDIA_USB_SUBR" ]; then _MEDIA_USB_SUBR=1 +# +# Copyright (c) 2012-2013 Devin Teske +# 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 (INLUDING, 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$ +# +############################################################ INCLUDES + +BSDCFG_SHARE="/usr/share/bsdconfig" +. $BSDCFG_SHARE/common.subr || exit 1 +f_dprintf "%s: loading includes..." media/usb.subr +f_include $BSDCFG_SHARE/struct.subr +f_include $BSDCFG_SHARE/device.subr +f_include $BSDCFG_SHARE/dialog.subr +f_include $BSDCFG_SHARE/variable.subr +f_include $BSDCFG_SHARE/media/common.subr + +BSDCFG_LIBE="/usr/libexec/bsdconfig" +f_include_lang $BSDCFG_LIBE/include/messages.subr + +############################################################ GLOBALS + +USB_MOUNTED= + +############################################################ FUNCTIONS + +# f_media_set_usb +# +# Attempt to use USB as the media type. Return success if we both found and set +# the media type to be a USB drive. +# +f_media_set_usb() +{ + f_media_close + + local devs ndevs + f_device_find "" $DEVICE_TYPE_USB devs + ndevs=$( set -- $devs; echo $# ) + + if [ ${ndevs:=0} -eq 0 ]; then + f_dialog_msgbox "$msg_no_usb_devices_found" + return $FAILURE + elif [ $ndevs -gt 1 ]; then + local title="$msg_choose_a_usb_drive" + local prompt="$msg_please_select_a_usb_drive" + local hline="" + + local dev retval + dev=$( f_device_menu \ + "$title" "$prompt" "$hline" $DEVICE_TYPE_USB \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) + retval=$? + [ "$dev" ] || return $FAILURE + + f_device_find "$dev" $DEVICE_TYPE_USB devs + [ "$devs" ] || return $FAILURE + dev="${devs%%[$IFS]*}" + + f_struct_copy device_$dev device_media + [ $retval -eq $SUCCESS ] || return $FAILURE + else + f_struct_copy device_$devs device_media + fi + + f_struct device_media && + device_media unset private + + if f_interactive; then + local name + f_struct device_media get name name + f_show_msg "$msg_using_usb_device" "$name" + fi + + f_struct device_media || return $FAILURE +} + +# f_media_init_usb $device +# +# Initializes the USB media device. Returns success if able to mount the USB +# disk device using mount(8). +# +f_media_init_usb() +{ + local dev="$1" devname err + + device_$dev get devname devname || return $FAILURE + f_dprintf "Init routine called for USB device. devname=[%s]" \ + "$devname" + + if [ "$USB_MOUNTED" ]; then + f_dprintf "USB device already mounted." + return $SUCCESS + fi + + if [ ! -e "$MOUNTPOINT" ] && + ! err=$( mkdir -p "$MOUNTPOINT" 2>&1 ) + then + f_dialog_msgbox "$err" + return $FAILURE + fi + + if err=$( mount "$devname" "$MOUNTPOINT" 2>&1 ); then + USB_MOUNTED=1 + return $SUCCESS + fi + + err="${err#mount: }"; err="${err#$devname: }" + f_show_msg "$msg_error_mounting_usb_drive" \ + "$devname" "$MOUNTPOINT" "$err" + return $FAILURE +} + +# f_media_get_usb $device $file [$probe_only] +# +# Returns data from $file on a mounted USB disk device. Similar to cat(1). +# $probe_only is currently unused by this media type. +# +f_media_get_usb() +{ + local dev="$1" file="$2" probe_only="$3" + + f_dprintf "f_media_get_usb: dev=[%s] file=[%s] probe_only=%s" \ + "$dev" "$file" "$probe_only" + + f_media_generic_get "$MOUNTPOINT" "$file" +} + +# f_media_shutdown_usb $device +# +# Shuts down the USB disk device using umount(8). Return status should be +# ignored. +# +f_media_shutdown_usb() +{ + local dev="$1" err + + [ "$USB_MOUNTED" ] || return + + if ! err=$( umount -f "$MOUNTPOINT" 2>&1 ); then + err="${err#umount: }"; err="${err#*: }" + f_show_msg "$msg_could_not_unmount_the_ufs_partition" \ + "$MOUNTPOINT" "$err" + else + USB_MOUNTED= + fi +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." media/usb.subr + +fi # ! $_MEDIA_USB_SUBR diff --git a/usr.sbin/bsdconfig/share/script.subr b/usr.sbin/bsdconfig/share/script.subr index 84d1cab4c20..3ea5dd54ad6 100644 --- a/usr.sbin/bsdconfig/share/script.subr +++ b/usr.sbin/bsdconfig/share/script.subr @@ -1,6 +1,6 @@ if [ ! "$_SCRIPT_SUBR" ]; then _SCRIPT_SUBR=1 # -# Copyright (c) 2012 Devin Teske +# Copyright (c) 2012-2013 Devin Teske # All Rights Reserved. # # Redistribution and use in source and binary forms, with or without @@ -31,7 +31,10 @@ if [ ! "$_SCRIPT_SUBR" ]; then _SCRIPT_SUBR=1 BSDCFG_SHARE="/usr/share/bsdconfig" . $BSDCFG_SHARE/common.subr || exit 1 f_dprintf "%s: loading includes..." script.subr +f_include $BSDCFG_SHARE/device.subr f_include $BSDCFG_SHARE/variable.subr +f_include $BSDCFG_SHARE/media/any.subr +f_include $BSDCFG_SHARE/media/tcpip.subr ############################################################ GLOBALS @@ -75,11 +78,13 @@ f_dispatch() local func="$1" resword="${2:-$1}" f_dprintf "f_dispatch: calling resword \`%s'" "$resword" eval $func - local retval=$? _ignore_this_error - f_getvar $VAR_NO_ERROR _ignore_this_error - [ $retval -eq $SUCCESS ] || + local retval=$? + if [ $retval -ne $SUCCESS ]; then + local _ignore_this_error + f_getvar $VAR_NO_ERROR _ignore_this_error [ "$_ignore_this_error" ] || f_die $retval \ - "$msg_command_failed_rest_of_script_aborted" "$resword" + "$msg_command_failed_rest_of_script_aborted" "$resword" + fi unset $VAR_NO_ERROR } @@ -146,8 +151,26 @@ f_script_load() # # Reserved words meant for scripting # +f_resword_new deviceRescan f_device_rescan f_resword_new dumpVariables f_dump_variables f_resword_new loadConfig f_script_load +f_resword_new mediaClose f_media_close +f_resword_new mediaGetType f_media_get_type +f_resword_new mediaOpen f_media_open +f_resword_new mediaSetCDROM f_media_set_cdrom +f_resword_new mediaSetDOS f_media_set_dos +f_resword_new mediaSetFTP f_media_set_ftp +f_resword_new mediaSetFTPActive f_media_set_ftp_active +f_resword_new mediaSetFTPPassive f_media_set_ftp_passive +f_resword_new mediaSetFTPUserPass f_media_set_ftp_userpass +f_resword_new mediaSetFloppy f_media_set_floppy +f_resword_new mediaSetHTTP f_media_set_http_proxy +f_resword_new mediaSetHTTPProxy f_media_set_http_proxy +f_resword_new mediaSetNFS f_media_set_nfs +f_resword_new mediaSetUFS f_media_set_ufs +f_resword_new mediaSetUSB f_media_set_usb +f_resword_new optionsEditor f_media_options_menu +f_resword_new tcpMenuSelect f_dialog_menu_select_tcp f_dprintf "%s: Successfully loaded." script.subr diff --git a/usr.sbin/bsdconfig/share/strings.subr b/usr.sbin/bsdconfig/share/strings.subr index 6fe0f3254a0..5b9f51e37ab 100644 --- a/usr.sbin/bsdconfig/share/strings.subr +++ b/usr.sbin/bsdconfig/share/strings.subr @@ -1,6 +1,6 @@ if [ ! "$_STRINGS_SUBR" ]; then _STRINGS_SUBR=1 # -# Copyright (c) 2006-2012 Devin Teske +# Copyright (c) 2006-2013 Devin Teske # All Rights Reserved. # # Redistribution and use in source and binary forms, with or without @@ -101,6 +101,72 @@ f_isinteger() ( : $((0/$arg)) ) > /dev/null 2>&1 } +# f_uriencode [$text] +# +# Encode $text for the purpose of embedding safely into a URL. Non-alphanumeric +# characters are converted to `%XX' sequence where XX represents the hexa- +# decimal ordinal of the non-alphanumeric character. If $text is missing, data +# is instead read from standard input. +# +f_uriencode_awk=' +BEGIN { + output = "" + for (n = 0; n < 256; n++) pack[sprintf("%c", n)] = sprintf("%%%02x", n) +} +{ + sline = "" + slen = length($0) + for (n = 1; n <= slen; n++) { + char = substr($0, n, 1) + if ( char !~ /^[[:alnum:]_]$/ ) char = pack[char] + sline = sline char + } + output = output ( output ? "%0a" : "" ) sline +} +END { print output } +' +f_uriencode() +{ + if [ $# -gt 0 ]; then + echo "$1" | awk "$f_uriencode_awk" + else + awk "$f_uriencode_awk" + fi +} + +# f_uridecode [$text] +# +# Decode $text from a URI. Encoded characters are converted from their `%XX' +# sequence into original unencoded ASCII sequences. If $text is missing, data +# is instead read from standard input. +# +f_uridecode_awk=' +BEGIN { for (n = 0; n < 256; n++) chr[n] = sprintf("%c", n) } +{ + sline = "" + slen = length($0) + for (n = 1; n <= slen; n++) + { + seq = substr($0, n, 3) + if ( seq ~ /^%[[:xdigit:]][[:xdigit:]]$/ ) { + hex = substr(seq, 2, 2) + sline = sline chr[sprintf("%u", "0x"hex)] + n += 2 + } else + sline = sline substr(seq, 1, 1) + } + print sline +} +' +f_uridecode() +{ + if [ $# -gt 0 ]; then + echo "$1" | awk "$f_uridecode_awk" + else + awk "$f_uridecode_awk" + fi +} + f_dprintf "%s: Successfully loaded." strings.subr fi # ! $_STRINGS_SUBR diff --git a/usr.sbin/bsdconfig/share/struct.subr b/usr.sbin/bsdconfig/share/struct.subr new file mode 100644 index 00000000000..3c6f90f1bf0 --- /dev/null +++ b/usr.sbin/bsdconfig/share/struct.subr @@ -0,0 +1,206 @@ +if [ ! "$_STRUCT_SUBR" ]; then _STRUCT_SUBR=1 +# +# Copyright (c) 2012-2013 Devin Teske +# 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 (INLUDING, 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$ +# +############################################################ INCLUDES + +BSDCFG_SHARE="/usr/share/bsdconfig" +. $BSDCFG_SHARE/common.subr || exit 1 + +############################################################ FUNCTIONS + +# f_struct_define $type $member_name1 ... +# +# Define a new `structure' type $type made up of the properties $member_name1 +# $member_name2 and so-on. Properties are not typed and can hold any type of +# data (including names of other structs). +# +# Before creating instances of a struct (using f_struct_new $type $name) you +# should use this function to define $type. +# +# Both $type and member names should consist only of alpha-numeric letters or +# the underscore. +# +f_struct_define() +{ + local type="$1" + [ "$type" ] || return $FAILURE + shift + setvar "_struct_typedef_$type" "$*" +} + +# f_struct_new $type $name +# +# Create a new `structure' named $name of type $type. There are two ways to +# access properties of a struct, but they are not equal (each method has its +# own unique benefits, discussed below). +# +# The primary method of accessing (both setting and getting) properties of any +# struct is through the f_struct() function below. +# +# The secondary method of accessing data is by using $name as a function. +# +# Both access methods are cross-platform compatible with any version of sh(1). +# Below is an example of the primary access method: +# +# f_struct_new MY_STRUCT_TYPE my_struct +# f_struct my_struct set abc 123 +# f_struct my_struct get abc # prints 123 to stdout +# f_struct my_struct get abc abc # sets local variable $abc to 123 +# +# Alternatively, the secondary access method (details below): +# +# f_struct_new MY_STRUCT_TYPE my_struct +# my_struct set abc 123 +# my_struct get abc # prints 123 to stdout +# my_struct get abc abc # sets local variable $abc to 123 +# +# The secondary form should only be used if/when: +# + You are certain that the structure already exists +# + You want a syntax error if/when the struct does not exist +# +# The primary benefit to the secondary form is syntax cleanliness and read- +# ability. If you are unsure if a given struct exists (which would cause a +# syntax error when using this form), you can use the primary access method to +# first test for the existence of the struct. For example: +# +# if f_struct my_struct; then +# my_struct get abc # only executed if my_struct exists +# fi +# +# For more information, see the f_struct() function. +# +f_struct_new() +{ + local type="$1" name="$2" + f_dprintf "f_struct_new: type=[%s] name=[%s]" "$type" "$name" + [ "$name" ] || return $FAILURE + setvar "_struct_type_$name" "$type" || return $FAILURE + # OK to use bare $name at this point + eval $name\(\){ f_struct $name \"\$@\"\; } +} + +# f_struct $name +# f_struct $name get $property [$var_to_set] +# f_struct $name set $property $new_value +# f_struct $name unset $property +# +# Access routine for getting, setting, unsetting, and testing properties of +# `structures'. +# +# If only given $name, returns success if struct $name has been created (using +# the f_struct_new() function above). +# +# For getting properties of a struct (versus setting) there are two methods of +# access. If $var_to_set is missing or NULL, the value of the property is +# printed to standard output for capturing in a sub-shell (which is less- +# recommended because of performance degredation; for example, when called in a +# loop). Returns success unless the property is unset. +# +# For setting properties of a struct, sets the value of $property to $new_value +# and returns success. +# +# For unsetting, the underlying environment variable associated with the given +# $property is unset. +# +f_struct() +{ + local __name="$1" __action="$2" __property="$3" + case $# in + 0) return $FAILURE ;; + 1) f_have $__name ;; + *) case "$__action" in + get) local __var_to_set="$4" + f_getvar "_struct_value_${__name}_$__property" "$__var_to_set" + ;; + set) local new_value="$4" + setvar "_struct_value_${__name}_$__property" "$new_value" ;; + unset) unset "_struct_value_${__name}_$__property" ;; + esac + esac + # Return the status of the last command above +} + +# f_struct_free $name +# +# Unset the collection of environment variables and accessor-function +# associated with struct $name. +# +f_struct_free() +{ + local name="$1" type member members + f_getvar "_struct_type_$name" type + f_dprintf "f_struct_free: name=[%s] type=[%s]" "$name" "$type" + [ "$name" ] || return $FAILURE + f_getvar "_struct_typedef_$type" members + for member in $members; do + f_struct "$name" unset $member + done + unset -f "$name" + unset "_struct_type_$name" +} + +# f_struct_copy $from_name $to_name +# +# Copy the properties of one struct to another. If struct $to_name does not +# exist, it is created. If struct $from_name does not exist, nothing is done +# and struct $to_name remains unmodified. +# +# Returns success unless struct $to_name did not exist and f_struct_new() was +# unable to create it. +# +f_struct_copy() +{ + local from_name="$1" to_name="$2" type + f_dprintf "f_struct_copy: from_name=[%s] to_name=[%s]" \ + "$from_name" "$to_name" + f_getvar "_struct_type_$from_name" type + f_struct "$to_name" || + f_struct_new "$type" "$to_name" || return $FAILURE + f_struct "$from_name" || return $SUCCESS + f_dprintf "f_struct_copy: copying properties from %s to %s" \ + "$from_name" "$to_name" + local property properties from_value n=0 k=0 + f_getvar "_struct_typedef_$type" properties + for property in $properties; do + k=$(( $k + 1 )) + if f_struct "$from_name" get $property from_value; then + f_struct "$to_name" set $property "$from_value" + n=$(( $n + 1 )) + else + f_struct "$to_name" unset $property + fi + done + f_dprintf "f_struct_copy: copied %u of %u properties from %s to %s" \ + "$n" "$k" "$from_name" "$to_name" +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." struct.subr + +fi # ! $_STRUCT_SUBR diff --git a/usr.sbin/bsdconfig/share/variable.subr b/usr.sbin/bsdconfig/share/variable.subr index 235f6dcb46b..7a066421f10 100644 --- a/usr.sbin/bsdconfig/share/variable.subr +++ b/usr.sbin/bsdconfig/share/variable.subr @@ -1,6 +1,6 @@ if [ ! "$_VARIABLE_SUBR" ]; then _VARIABLE_SUBR=1 # -# Copyright (c) 2012 Devin Teske +# Copyright (c) 2012-2013 Devin Teske # All Rights Reserved. # # Redistribution and use in source and binary forms, with or without @@ -109,7 +109,15 @@ f_variable_set_defaults() # # Initialize various user-edittable values to their defaults # - setvar $VAR_RELNAME "$UNAME_R" + setvar $VAR_EDITOR "${EDITOR:-/usr/bin/ee}" + setvar $VAR_FTP_STATE "passive" + setvar $VAR_FTP_USER "ftp" + setvar $VAR_HOSTNAME "$( hostname )" + setvar $VAR_MEDIA_TIMEOUT "300" + setvar $VAR_NFS_SECURE "NO" + setvar $VAR_NFS_TCP "NO" + setvar $VAR_NFS_V3 "YES" + setvar $VAR_RELNAME "$UNAME_R" f_dprintf "f_variable_set_defaults: Defaults initialized." } @@ -158,17 +166,71 @@ f_interactive() ! f_getvar $VAR_NONINTERACTIVE value || [ ! "$value" ] } +# f_netinteractive() +# +# Has the user specifically requested the network-portion of configuration and +# setup to be performed interactively? Returns success if the user has asked +# for the network configuration to be done interactively even if perhaps over- +# all non-interactive mode has been requested (by setting nonInteractive). +# +# Returns success if $netInteractive is set and non-NULL. +# +f_netinteractive() +{ + local value + f_getvar $VAR_NETINTERACTIVE value && [ "$value" ] +} + ############################################################ MAIN # # Variables that can be tweaked from config files # +# Handle Variable Name f_variable_new VAR_CONFIG_FILE configFile f_variable_new VAR_DEBUG debug f_variable_new VAR_DEBUG_FILE debugFile -f_variable_new VAR_NO_ERROR noError +f_variable_new VAR_DIRECTORY_PATH _directoryPath +f_variable_new VAR_DOMAINNAME domainname +f_variable_new VAR_EDITOR editor +f_variable_new VAR_EXTRAS ifconfig_ +f_variable_new VAR_FTP_DIR ftpDirectory +f_variable_new VAR_FTP_HOST ftpHost +f_variable_new VAR_FTP_PASS ftpPass +f_variable_new VAR_FTP_PATH _ftpPath +f_variable_new VAR_FTP_PORT ftpPort +f_variable_new VAR_FTP_STATE ftpState +f_variable_new VAR_FTP_USER ftpUser +f_variable_new VAR_GATEWAY defaultrouter +f_variable_new VAR_HOSTNAME hostname +f_variable_new VAR_HTTP_FTP_MODE httpFtpMode +f_variable_new VAR_HTTP_PROXY httpProxy +f_variable_new VAR_HTTP_PROXY_HOST httpProxyHost +f_variable_new VAR_HTTP_PROXY_PATH _httpProxyPath +f_variable_new VAR_HTTP_PROXY_PORT httpProxyPort +f_variable_new VAR_IFCONFIG ifconfig_ +f_variable_new VAR_IPADDR ipaddr +f_variable_new VAR_IPV6ADDR ipv6addr +f_variable_new VAR_IPV6_ENABLE ipv6_activate_all_interfaces +f_variable_new VAR_MEDIA_TIMEOUT MEDIA_TIMEOUT +f_variable_new VAR_MEDIA_TYPE mediaType +f_variable_new VAR_NAMESERVER nameserver +f_variable_new VAR_NETINTERACTIVE netInteractive +f_variable_new VAR_NETMASK netmask +f_variable_new VAR_NETWORK_DEVICE netDev +f_variable_new VAR_NFS_HOST nfsHost +f_variable_new VAR_NFS_PATH nfsPath +f_variable_new VAR_NFS_SECURE nfs_reserved_port_only +f_variable_new VAR_NFS_TCP nfs_use_tcp +f_variable_new VAR_NFS_V3 nfs_use_v3 f_variable_new VAR_NONINTERACTIVE nonInteractive +f_variable_new VAR_NO_ERROR noError +f_variable_new VAR_NO_INET6 noInet6 f_variable_new VAR_RELNAME releaseName +f_variable_new VAR_SLOW_ETHER slowEthernetCard +f_variable_new VAR_TRY_DHCP tryDHCP +f_variable_new VAR_TRY_RTSOL tryRTSOL +f_variable_new VAR_UFS_PATH ufs # # Self-initialize unless requested otherwise From 2adbba660d8dd25130ba17825fbf83888b70429a Mon Sep 17 00:00:00 2001 From: Mikolaj Golub Date: Mon, 25 Feb 2013 20:09:07 +0000 Subject: [PATCH 0400/1476] Add i/o error counters to hastd(8) and make hastctl(8) display them. This may be useful for detecting problems with HAST disks. Discussed with and reviewed by: pjd MFC after: 1 week --- sbin/hastctl/hastctl.c | 6 ++++++ sbin/hastd/control.c | 18 ++++++++++++++++++ sbin/hastd/hast.h | 12 ++++++++++++ sbin/hastd/primary.c | 18 ++++++++++++++++++ sbin/hastd/secondary.c | 18 +++++++++++++++++- 5 files changed, 71 insertions(+), 1 deletion(-) diff --git a/sbin/hastctl/hastctl.c b/sbin/hastctl/hastctl.c index 0bd47f275ef..503072c8199 100644 --- a/sbin/hastctl/hastctl.c +++ b/sbin/hastctl/hastctl.c @@ -351,6 +351,12 @@ control_status(struct nv *nv) (uint64_t)nv_get_uint64(nv, "stat_flush%u", ii)); printf(" activemap updates: %ju\n", (uint64_t)nv_get_uint64(nv, "stat_activemap_update%u", ii)); + printf(" local errors: " + "read: %ju, write: %ju, delete: %ju, flush: %ju\n", + (uintmax_t)nv_get_uint64(nv, "stat_read_error%u", ii), + (uintmax_t)nv_get_uint64(nv, "stat_write_error%u", ii), + (uintmax_t)nv_get_uint64(nv, "stat_delete_error%u", ii), + (uintmax_t)nv_get_uint64(nv, "stat_flush_error%u", ii)); } return (ret); } diff --git a/sbin/hastd/control.c b/sbin/hastd/control.c index 925fd32645c..3619fc61ff0 100644 --- a/sbin/hastd/control.c +++ b/sbin/hastd/control.c @@ -207,6 +207,14 @@ control_status_worker(struct hast_resource *res, struct nv *nvout, "stat_flush%u", no); nv_add_uint64(nvout, nv_get_uint64(cnvin, "stat_activemap_update"), "stat_activemap_update%u", no); + nv_add_uint64(nvout, nv_get_uint64(cnvin, "stat_read_error"), + "stat_read_error%u", no); + nv_add_uint64(nvout, nv_get_uint64(cnvin, "stat_write_error"), + "stat_write_error%u", no); + nv_add_uint64(nvout, nv_get_uint64(cnvin, "stat_delete_error"), + "stat_delete_error%u", no); + nv_add_uint64(nvout, nv_get_uint64(cnvin, "stat_flush_error"), + "stat_flush_error%u", no); end: if (cnvin != NULL) nv_free(cnvin); @@ -459,6 +467,16 @@ ctrl_thread(void *arg) nv_add_uint64(nvout, res->hr_stat_flush, "stat_flush"); nv_add_uint64(nvout, res->hr_stat_activemap_update, "stat_activemap_update"); + nv_add_uint64(nvout, res->hr_stat_read_error, + "stat_read_error"); + nv_add_uint64(nvout, res->hr_stat_write_error + + res->hr_stat_activemap_write_error, + "stat_write_error"); + nv_add_uint64(nvout, res->hr_stat_delete_error, + "stat_delete_error"); + nv_add_uint64(nvout, res->hr_stat_flush_error + + res->hr_stat_activemap_flush_error, + "stat_flush_error"); nv_add_int16(nvout, 0, "error"); break; case CONTROL_RELOAD: diff --git a/sbin/hastd/hast.h b/sbin/hastd/hast.h index c7a6b49b292..b757994a19b 100644 --- a/sbin/hastd/hast.h +++ b/sbin/hastd/hast.h @@ -239,6 +239,18 @@ struct hast_resource { uint64_t hr_stat_flush; /* Number of activemap updates. */ uint64_t hr_stat_activemap_update; + /* Number of local read errors. */ + uint64_t hr_stat_read_error; + /* Number of local write errors. */ + uint64_t hr_stat_write_error; + /* Number of local delete errors. */ + uint64_t hr_stat_delete_error; + /* Number of flush errors. */ + uint64_t hr_stat_flush_error; + /* Number of activemap write errors. */ + uint64_t hr_stat_activemap_write_error; + /* Number of activemap flush errors. */ + uint64_t hr_stat_activemap_flush_error; /* Next resource. */ TAILQ_ENTRY(hast_resource) hr_next; diff --git a/sbin/hastd/primary.c b/sbin/hastd/primary.c index fb49ef61f05..a9dfa2b1cc4 100644 --- a/sbin/hastd/primary.c +++ b/sbin/hastd/primary.c @@ -303,6 +303,7 @@ hast_activemap_flush(struct hast_resource *res) if (pwrite(res->hr_localfd, buf, size, METADATA_SIZE) != (ssize_t)size) { pjdlog_errno(LOG_ERR, "Unable to flush activemap to disk"); + res->hr_stat_activemap_write_error++; return (-1); } if (res->hr_metaflush == 1 && g_flush(res->hr_localfd) == -1) { @@ -313,6 +314,7 @@ hast_activemap_flush(struct hast_resource *res) } else { pjdlog_errno(LOG_ERR, "Unable to flush disk cache on activemap update"); + res->hr_stat_activemap_flush_error++; return (-1); } } @@ -1936,6 +1938,22 @@ ggate_send_thread(void *arg) "G_GATE_CMD_DONE failed"); } } + if (hio->hio_errors[0]) { + switch (ggio->gctl_cmd) { + case BIO_READ: + res->hr_stat_read_error++; + break; + case BIO_WRITE: + res->hr_stat_write_error++; + break; + case BIO_DELETE: + res->hr_stat_delete_error++; + break; + case BIO_FLUSH: + res->hr_stat_flush_error++; + break; + } + } pjdlog_debug(2, "ggate_send: (%p) Moving request to the free queue.", hio); QUEUE_INSERT2(hio, free); diff --git a/sbin/hastd/secondary.c b/sbin/hastd/secondary.c index 71524e90a26..febdc05b42e 100644 --- a/sbin/hastd/secondary.c +++ b/sbin/hastd/secondary.c @@ -765,6 +765,7 @@ disk_thread(void *arg) pjdlog_errno(LOG_WARNING, "Unable to store cleared activemap"); free(map); + res->hr_stat_activemap_write_error++; break; } free(map); @@ -883,8 +884,23 @@ send_thread(void *arg) PJDLOG_ABORT("Unexpected command (cmd=%hhu).", hio->hio_cmd); } - if (hio->hio_error != 0) + if (hio->hio_error != 0) { + switch (hio->hio_cmd) { + case HIO_READ: + res->hr_stat_read_error++; + break; + case HIO_WRITE: + res->hr_stat_write_error++; + break; + case HIO_DELETE: + res->hr_stat_delete_error++; + break; + case HIO_FLUSH: + res->hr_stat_flush_error++; + break; + } nv_add_int16(nvout, hio->hio_error, "error"); + } if (hast_proto_send(res, res->hr_remoteout, nvout, data, length) == -1) { secondary_exit(EX_TEMPFAIL, "Unable to send reply"); From 42b4049c3422c58c7af6bfcb0ea1c611dc0d8a99 Mon Sep 17 00:00:00 2001 From: Neel Natu Date: Mon, 25 Feb 2013 20:31:47 +0000 Subject: [PATCH 0401/1476] Get rid of unused struct member. Pointed out by: Gopakumar T Obtained from: NetApp --- usr.sbin/bhyve/pci_emul.h | 1 - 1 file changed, 1 deletion(-) diff --git a/usr.sbin/bhyve/pci_emul.h b/usr.sbin/bhyve/pci_emul.h index 079d5f2460a..db218bbbb32 100644 --- a/usr.sbin/bhyve/pci_emul.h +++ b/usr.sbin/bhyve/pci_emul.h @@ -105,7 +105,6 @@ struct pci_devinst { uint8_t pi_bus, pi_slot, pi_func; uint8_t pi_lintr_pin; char pi_name[PI_NAMESZ]; - uint16_t pi_iobase; int pi_bar_getsize; struct { From 893365e42dbc86b4b141c75184861f8fce624b0d Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Mon, 25 Feb 2013 20:50:08 +0000 Subject: [PATCH 0402/1476] After r237012, the fdgrowtable() doesn't drop the filedesc lock anymore, so update a stale comment. Reviewed by: kib, keramida --- sys/kern/kern_descrip.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index 9de55e82443..fafd95caf7c 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -855,9 +855,7 @@ do_dup(struct thread *td, int flags, int old, int new, /* * If the caller specified a file descriptor, make sure the file * table is large enough to hold it, and grab it. Otherwise, just - * allocate a new descriptor the usual way. Since the filedesc - * lock may be temporarily dropped in the process, we have to look - * out for a race. + * allocate a new descriptor the usual way. */ if (flags & DUP_FIXED) { if (new >= fdp->fd_nfiles) { From 1d59211b2eced9c1765364e83c7c7dfc506e16c8 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Mon, 25 Feb 2013 20:51:29 +0000 Subject: [PATCH 0403/1476] Style. Suggested by: kib --- sys/kern/kern_descrip.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index fafd95caf7c..acdea406eda 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -1425,8 +1425,7 @@ fdgrowtable(struct filedesc *fdp, int nfd) FILEDESC_XLOCK_ASSERT(fdp); - KASSERT(fdp->fd_nfiles > 0, - ("zero-length file table")); + KASSERT(fdp->fd_nfiles > 0, ("zero-length file table")); /* save old values */ onfiles = fdp->fd_nfiles; @@ -1447,13 +1446,11 @@ fdgrowtable(struct filedesc *fdp, int nfd) * it on the freelist. We place the struct freetable in the * middle so we don't have to worry about padding. */ - ntable = malloc(nnfiles * sizeof(*ntable) + - sizeof(struct freetable) + - nnfiles * sizeof(*nfileflags), - M_FILEDESC, M_ZERO | M_WAITOK); + ntable = malloc(nnfiles * sizeof(*ntable) + sizeof(struct freetable) + + nnfiles * sizeof(*nfileflags), M_FILEDESC, M_ZERO | M_WAITOK); nfileflags = (char *)&ntable[nnfiles] + sizeof(struct freetable); - nmap = malloc(NDSLOTS(nnfiles) * NDSLOTSIZE, - M_FILEDESC, M_ZERO | M_WAITOK); + nmap = malloc(NDSLOTS(nnfiles) * NDSLOTSIZE, M_FILEDESC, + M_ZERO | M_WAITOK); /* copy the old data over and point at the new tables */ memcpy(ntable, otable, onfiles * sizeof(*otable)); From 776a9ddc8c80b07a43c9d436bceae3b6d020ddee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Mon, 25 Feb 2013 22:25:56 +0000 Subject: [PATCH 0404/1476] In all situations where we need to bootstrap yacc, we also need to bootstrap liby. This was not readily apparent, because a normal 'make buildworld' or 'make toolchain' builds liby before building anything that uses yacc. However, 'make kernel-toolchain' does not build headers or libraries, so it was not possible to build a kernel from head on, say, stable/9 without first building the complete toolchain. MFC after: 1 week --- Makefile.inc1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile.inc1 b/Makefile.inc1 index 8a8f8cd3102..f404eaaf243 100644 --- a/Makefile.inc1 +++ b/Makefile.inc1 @@ -1132,7 +1132,8 @@ _lex= usr.bin/lex .endif .if ${BOOTSTRAPPING} < 1000013 -_yacc= usr.bin/yacc +_yacc= lib/liby \ + usr.bin/yacc .endif .if ${BOOTSTRAPPING} < 1000026 From d2a72d673fd835f7d8032f6801447d57ee50e53c Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Mon, 25 Feb 2013 22:42:43 +0000 Subject: [PATCH 0405/1476] Begin adding support to explicitly set the current chainmask. Right now the only way to set the chainmask is to set the hardware configured chainmask through capabilities. This is fine for forcing the chainmask to be something other than what the hardware is capable of (eg to reduce TX/RX to one connected antenna) but it does change what the HAL hardware chainmask configuration is. For operational mode changes, it (may?) make sense to separately control the TX/RX chainmask. Right now it's done as part of ar5416_reset.c - ar5416UpdateChainMasks() calculates which TX/RX chainmasks to enable based on the operating mode. (1 for legacy and whatever is supported for 11n operation.) But doing this in the HAL is suboptimal - the driver needs to know the currently configured chainmask in order to correctly enable things for each TX descriptor. This is currently done by overriding the chainmask config in the ar5416 TX routines but this has to disappear - the AR9300 HAL support requires the driver to dynamically set the TX chainmask based on the TX power and TX rate in order to meet mini-PCIe slot power requirements. So: * Introduce a new HAL method to set the operational chainmask variables; * Introduce null methods for the previous generation chipsets; * Add new driver state to record the current chainmask separate from the hardware configured chainmask. Part #2 of this will involve disabling ar5416UpdateChainMasks() and moving it into the driver; as well as properly programming the TX chainmask based on the currently configured HAL chainmask. Tested: * AR5416, STA mode - both legacy (11a/11bg) and 11n rates - verified that AR_SELFGEN_MASK (the chainmask used for self-generated frames like ACKs and RTSes) is correct, as well as the TX descriptor contents is correct. --- sys/dev/ath/ath_hal/ah.h | 2 ++ sys/dev/ath/ath_hal/ar5210/ar5210.h | 1 + sys/dev/ath/ath_hal/ar5210/ar5210_attach.c | 1 + sys/dev/ath/ath_hal/ar5210/ar5210_misc.c | 6 ++++++ sys/dev/ath/ath_hal/ar5211/ar5211.h | 2 ++ sys/dev/ath/ath_hal/ar5211/ar5211_attach.c | 1 + sys/dev/ath/ath_hal/ar5211/ar5211_misc.c | 6 ++++++ sys/dev/ath/ath_hal/ar5212/ar5212.h | 1 + sys/dev/ath/ath_hal/ar5212/ar5212_attach.c | 1 + sys/dev/ath/ath_hal/ar5212/ar5212_misc.c | 6 ++++++ sys/dev/ath/ath_hal/ar5416/ar5416.h | 1 + sys/dev/ath/ath_hal/ar5416/ar5416_attach.c | 1 + sys/dev/ath/ath_hal/ar5416/ar5416_misc.c | 14 ++++++++++++++ sys/dev/ath/if_athvar.h | 8 ++++++-- 14 files changed, 49 insertions(+), 2 deletions(-) diff --git a/sys/dev/ath/ath_hal/ah.h b/sys/dev/ath/ath_hal/ah.h index ddc4b6a057c..0e3d5abc8cf 100644 --- a/sys/dev/ath/ath_hal/ah.h +++ b/sys/dev/ath/ath_hal/ah.h @@ -1437,6 +1437,8 @@ struct ath_hal { HAL_STATUS __ahdecl(*ah_setQuiet)(struct ath_hal *ah, uint32_t period, uint32_t duration, uint32_t nextStart, HAL_QUIET_FLAG flag); + void __ahdecl(*ah_setChainMasks)(struct ath_hal *, + uint32_t, uint32_t); /* DFS functions */ void __ahdecl(*ah_enableDfs)(struct ath_hal *ah, diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210.h b/sys/dev/ath/ath_hal/ar5210/ar5210.h index 2dad1240d60..48ccc208513 100644 --- a/sys/dev/ath/ath_hal/ar5210/ar5210.h +++ b/sys/dev/ath/ath_hal/ar5210/ar5210.h @@ -259,6 +259,7 @@ extern HAL_BOOL ar5210GetDiagState(struct ath_hal *ah, int request, extern uint32_t ar5210Get11nExtBusy(struct ath_hal *); extern HAL_BOOL ar5210GetMibCycleCounts(struct ath_hal *, HAL_SURVEY_SAMPLE *); +extern void ar5210SetChainMasks(struct ath_hal *, uint32_t, uint32_t); extern void ar5210EnableDfs(struct ath_hal *, HAL_PHYERR_PARAM *); extern void ar5210GetDfsThresh(struct ath_hal *, HAL_PHYERR_PARAM *); extern void ar5210UpdateDiagReg(struct ath_hal *ah, uint32_t val); diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210_attach.c b/sys/dev/ath/ath_hal/ar5210/ar5210_attach.c index 495a3d0f5bb..3c0ed71ba8c 100644 --- a/sys/dev/ath/ath_hal/ar5210/ar5210_attach.c +++ b/sys/dev/ath/ath_hal/ar5210/ar5210_attach.c @@ -137,6 +137,7 @@ static const struct ath_hal_private ar5210hal = {{ .ah_setCoverageClass = ar5210SetCoverageClass, .ah_get11nExtBusy = ar5210Get11nExtBusy, .ah_getMibCycleCounts = ar5210GetMibCycleCounts, + .ah_setChainMasks = ar5210SetChainMasks, .ah_enableDfs = ar5210EnableDfs, .ah_getDfsThresh = ar5210GetDfsThresh, /* XXX procRadarEvent */ diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210_misc.c b/sys/dev/ath/ath_hal/ar5210/ar5210_misc.c index bf4b8d031db..81708800fe3 100644 --- a/sys/dev/ath/ath_hal/ar5210/ar5210_misc.c +++ b/sys/dev/ath/ath_hal/ar5210/ar5210_misc.c @@ -670,6 +670,12 @@ ar5210GetMibCycleCounts(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hsample) return (AH_FALSE); } +void +ar5210SetChainMasks(struct ath_hal *ah, uint32_t txchainmask, + uint32_t rxchainmask) +{ +} + void ar5210EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) { diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211.h b/sys/dev/ath/ath_hal/ar5211/ar5211.h index 6f813fba331..c50531e33ea 100644 --- a/sys/dev/ath/ath_hal/ar5211/ar5211.h +++ b/sys/dev/ath/ath_hal/ar5211/ar5211.h @@ -286,6 +286,8 @@ extern HAL_BOOL ar5211GetDiagState(struct ath_hal *ah, int request, extern uint32_t ar5211Get11nExtBusy(struct ath_hal *); extern HAL_BOOL ar5211GetMibCycleCounts(struct ath_hal *, HAL_SURVEY_SAMPLE *); +extern void ar5211SetChainMasks(struct ath_hal *ah, uint32_t, uint32_t); + extern void ar5211EnableDfs(struct ath_hal *, HAL_PHYERR_PARAM *); extern void ar5211GetDfsThresh(struct ath_hal *, HAL_PHYERR_PARAM *); diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211_attach.c b/sys/dev/ath/ath_hal/ar5211/ar5211_attach.c index 6f0379b2e92..454929523d5 100644 --- a/sys/dev/ath/ath_hal/ar5211/ar5211_attach.c +++ b/sys/dev/ath/ath_hal/ar5211/ar5211_attach.c @@ -137,6 +137,7 @@ static const struct ath_hal_private ar5211hal = {{ .ah_setCoverageClass = ar5211SetCoverageClass, .ah_get11nExtBusy = ar5211Get11nExtBusy, .ah_getMibCycleCounts = ar5211GetMibCycleCounts, + .ah_setChainMasks = ar5211SetChainMasks, .ah_enableDfs = ar5211EnableDfs, .ah_getDfsThresh = ar5211GetDfsThresh, /* XXX procRadarEvent */ diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211_misc.c b/sys/dev/ath/ath_hal/ar5211/ar5211_misc.c index 55f39e98da3..a1a59676341 100644 --- a/sys/dev/ath/ath_hal/ar5211/ar5211_misc.c +++ b/sys/dev/ath/ath_hal/ar5211/ar5211_misc.c @@ -710,6 +710,12 @@ ar5211GetMibCycleCounts(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hsample) return (AH_FALSE); } +void +ar5211SetChainMasks(struct ath_hal *ah, uint32_t txchainmask, + uint32_t rxchainmask) +{ +} + void ar5211EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) { diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212.h b/sys/dev/ath/ath_hal/ar5212/ar5212.h index d7063c4017b..0631432fdbe 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar5212.h +++ b/sys/dev/ath/ath_hal/ar5212/ar5212.h @@ -513,6 +513,7 @@ extern HAL_STATUS ar5212SetQuiet(struct ath_hal *ah, uint32_t period, uint32_t duration, uint32_t nextStart, HAL_QUIET_FLAG flag); extern HAL_BOOL ar5212GetMibCycleCounts(struct ath_hal *, HAL_SURVEY_SAMPLE *); +extern void ar5212SetChainMasks(struct ath_hal *, uint32_t, uint32_t); extern HAL_BOOL ar5212SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode, int setChip); diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c b/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c index 1870f94a7b4..e0af27c4b42 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c +++ b/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c @@ -134,6 +134,7 @@ static const struct ath_hal_private ar5212hal = {{ .ah_setCoverageClass = ar5212SetCoverageClass, .ah_setQuiet = ar5212SetQuiet, .ah_getMibCycleCounts = ar5212GetMibCycleCounts, + .ah_setChainMasks = ar5212SetChainMasks, /* DFS Functions */ .ah_enableDfs = ar5212EnableDfs, diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c b/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c index 143090fd935..486de30a372 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c +++ b/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c @@ -1413,3 +1413,9 @@ ar5212GetMibCycleCounts(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hsample) return (AH_FALSE); } + +void +ar5212SetChainMasks(struct ath_hal *ah, uint32_t tx_chainmask, + uint32_t rx_chainmask) +{ +} diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416.h b/sys/dev/ath/ath_hal/ar5416/ar5416.h index d5705889e3d..98dcf5e0854 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416.h +++ b/sys/dev/ath/ath_hal/ar5416/ar5416.h @@ -239,6 +239,7 @@ extern HAL_BOOL ar5416SetDecompMask(struct ath_hal *, uint16_t, int); extern void ar5416SetCoverageClass(struct ath_hal *, uint8_t, int); extern HAL_BOOL ar5416GetMibCycleCounts(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hsample); +extern void ar5416SetChainMasks(struct ath_hal *ah, uint32_t, uint32_t); extern uint32_t ar5416Get11nExtBusy(struct ath_hal *ah); extern void ar5416Set11nMac2040(struct ath_hal *ah, HAL_HT_MACMODE mode); extern HAL_HT_RXCLEAR ar5416Get11nRxClear(struct ath_hal *ah); diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c b/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c index c26ca4bb783..9a0a4794ecd 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c @@ -150,6 +150,7 @@ ar5416InitState(struct ath_hal_5416 *ahp5416, uint16_t devid, HAL_SOFTC sc, ah->ah_setCoverageClass = ar5416SetCoverageClass; ah->ah_setQuiet = ar5416SetQuiet; ah->ah_getMibCycleCounts = ar5416GetMibCycleCounts; + ah->ah_setChainMasks = ar5416SetChainMasks; ah->ah_resetKeyCacheEntry = ar5416ResetKeyCacheEntry; ah->ah_setKeyCacheEntry = ar5416SetKeyCacheEntry; diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_misc.c b/sys/dev/ath/ath_hal/ar5416/ar5416_misc.c index 7b0e92b47fe..6f47c5c8b8a 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_misc.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_misc.c @@ -255,6 +255,20 @@ ar5416GetMibCycleCounts(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hsample) return (good); } +/* + * Setup the TX/RX chainmasks - this needs to be done before a call + * to the reset method as it doesn't update the hardware. + */ +void +ar5416SetChainMasks(struct ath_hal *ah, uint32_t tx_chainmask, + uint32_t rx_chainmask) +{ + HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; + + AH5416(ah)->ah_tx_chainmask = tx_chainmask & pCap->halTxChainMask; + AH5416(ah)->ah_rx_chainmask = rx_chainmask & pCap->halRxChainMask; +} + /* * Return approximation of extension channel busy over an time interval * 0% (clear) -> 100% (busy) diff --git a/sys/dev/ath/if_athvar.h b/sys/dev/ath/if_athvar.h index 1b6e160dc10..e8fdeff6748 100644 --- a/sys/dev/ath/if_athvar.h +++ b/sys/dev/ath/if_athvar.h @@ -715,8 +715,10 @@ struct ath_softc { u_int32_t sc_avgtsfdeltap;/* TDMA slot adjust (+) */ u_int32_t sc_avgtsfdeltam;/* TDMA slot adjust (-) */ uint16_t *sc_eepromdata; /* Local eeprom data, if AR9100 */ - int sc_txchainmask; /* currently configured TX chainmask */ - int sc_rxchainmask; /* currently configured RX chainmask */ + int sc_txchainmask; /* hardware TX chainmask */ + int sc_rxchainmask; /* hardware RX chainmask */ + int sc_cur_txchainmask; /* currently configured TX chainmask */ + int sc_cur_rxchainmask; /* currently configured RX chainmask */ int sc_rts_aggr_limit; /* TX limit on RTS aggregates */ int sc_aggr_limit; /* TX limit on all aggregates */ int sc_delim_min_pad; /* Minimum delimiter count */ @@ -1334,6 +1336,8 @@ void ath_intr(void *); ((*(_ah)->ah_getMibCycleCounts)((_ah), (_sample))) #define ath_hal_get_chan_ext_busy(_ah) \ ((*(_ah)->ah_get11nExtBusy)((_ah))) +#define ath_hal_setchainmasks(_ah, _txchainmask, _rxchainmask) \ + ((*(_ah)->ah_setChainMasks)((_ah), (_txchainmask), (_rxchainmask))) #define ath_hal_spectral_supported(_ah) \ (ath_hal_getcapability(_ah, HAL_CAP_SPECTRAL_SCAN, 0, NULL) == HAL_OK) From 6322256b83ed63e1806d3a91bf3529d0f525ab5b Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Mon, 25 Feb 2013 22:45:02 +0000 Subject: [PATCH 0406/1476] Part #2 of the TX chainmask changes: * Remove ar5416UpdateChainmasks(); * Remove the TX chainmask override code from the ar5416 TX descriptor setup routines; * Write a driver method to calculate the current chainmask based on the operating mode and update the driver state; * Call the HAL chainmask method before calling ath_hal_reset(); * Use the currently configured chainmask in the TX descriptors rather than the hardware TX chainmasks. Tested: * AR5416, STA/AP mode - legacy and 11n modes --- sys/dev/ath/ath_hal/ar5416/ar5416_reset.c | 31 --------------------- sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c | 14 ---------- sys/dev/ath/if_ath.c | 33 +++++++++++++++++++++++ sys/dev/ath/if_ath_tx_ht.c | 17 ++++++------ 4 files changed, 42 insertions(+), 53 deletions(-) diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c b/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c index 75df5e995b4..5f8f2ad5b65 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c @@ -44,7 +44,6 @@ static void ar5416InitBB(struct ath_hal *ah, const struct ieee80211_channel *); static void ar5416InitIMR(struct ath_hal *ah, HAL_OPMODE opmode); static void ar5416InitQoS(struct ath_hal *ah); static void ar5416InitUserSettings(struct ath_hal *ah); -static void ar5416UpdateChainMasks(struct ath_hal *ah, HAL_BOOL is_ht); static void ar5416OverrideIni(struct ath_hal *ah, const struct ieee80211_channel *); #if 0 @@ -209,11 +208,6 @@ ar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode, HALDEBUG(ah, HAL_DEBUG_RESET, ">>>2 %s: AR_PHY_ADC_CTL=0x%x\n", __func__, OS_REG_READ(ah,AR_PHY_ADC_CTL)); - /* - * Setup ah_tx_chainmask / ah_rx_chainmask before we fiddle - * with enabling the TX/RX radio chains. - */ - ar5416UpdateChainMasks(ah, IEEE80211_IS_CHAN_HT(chan)); /* * This routine swaps the analog chains - it should be done * before any radio register twiddling is done. @@ -1464,31 +1458,6 @@ ar5416RestoreChainMask(struct ath_hal *ah) } } -/* - * Update the chainmask based on the current channel configuration. - * - * XXX ath9k checks bluetooth co-existence here - * XXX ath9k checks whether the current state is "off-channel". - * XXX ath9k sticks the hardware into 1x1 mode for legacy; - * we're going to leave multi-RX on for multi-path cancellation. - */ -static void -ar5416UpdateChainMasks(struct ath_hal *ah, HAL_BOOL is_ht) -{ - struct ath_hal_private *ahpriv = AH_PRIVATE(ah); - HAL_CAPABILITIES *pCap = &ahpriv->ah_caps; - - if (is_ht) { - AH5416(ah)->ah_tx_chainmask = pCap->halTxChainMask; - } else { - AH5416(ah)->ah_tx_chainmask = 1; - } - AH5416(ah)->ah_rx_chainmask = pCap->halRxChainMask; - HALDEBUG(ah, HAL_DEBUG_RESET, "TX chainmask: 0x%x; RX chainmask: 0x%x\n", - AH5416(ah)->ah_tx_chainmask, - AH5416(ah)->ah_rx_chainmask); -} - void ar5416InitPLL(struct ath_hal *ah, const struct ieee80211_channel *chan) { diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c b/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c index 945c766c2df..118a43bcc49 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c @@ -700,20 +700,6 @@ ar5416Set11nRateScenario(struct ath_hal *ah, struct ath_desc *ds, HALASSERT(nseries == 4); (void)nseries; - /* - * XXX since the upper layers doesn't know the current chainmask - * XXX setup, just override its decisions here. - * XXX The upper layers need to be taught this! - */ - if (series[0].Tries != 0) - series[0].ChSel = AH5416(ah)->ah_tx_chainmask; - if (series[1].Tries != 0) - series[1].ChSel = AH5416(ah)->ah_tx_chainmask; - if (series[2].Tries != 0) - series[2].ChSel = AH5416(ah)->ah_tx_chainmask; - if (series[3].Tries != 0) - series[3].ChSel = AH5416(ah)->ah_tx_chainmask; - /* * Only one of RTS and CTS enable must be set. * If a frame has both set, just do RTS protection - diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 2ea3909fb59..a614d6f0113 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -1476,6 +1476,26 @@ ath_reset_keycache(struct ath_softc *sc) ieee80211_crypto_reload_keys(ic); } +/* + * Fetch the current chainmask configuration based on the current + * operating channel and options. + */ +static void +ath_update_chainmasks(struct ath_softc *sc, struct ieee80211_channel *chan) +{ + + /* + * Set TX chainmask to the currently configured chainmask; + * the TX chainmask depends upon the current operating mode. + */ + sc->sc_cur_rxchainmask = sc->sc_rxchainmask; + if (IEEE80211_IS_CHAN_HT(chan)) { + sc->sc_cur_txchainmask = sc->sc_txchainmask; + } else { + sc->sc_cur_txchainmask = 1; + } +} + void ath_resume(struct ath_softc *sc) { @@ -1494,6 +1514,10 @@ ath_resume(struct ath_softc *sc) * Must reset the chip before we reload the * keycache as we were powered down on suspend. */ + ath_update_chainmasks(sc, + sc->sc_curchan != NULL ? sc->sc_curchan : ic->ic_curchan); + ath_hal_setchainmasks(sc->sc_ah, sc->sc_cur_txchainmask, + sc->sc_cur_rxchainmask); ath_hal_reset(ah, sc->sc_opmode, sc->sc_curchan != NULL ? sc->sc_curchan : ic->ic_curchan, AH_FALSE, &status); @@ -1935,6 +1959,9 @@ ath_init(void *arg) * and then setup of the interrupt mask. */ ath_settkipmic(sc); + ath_update_chainmasks(sc, ic->ic_curchan); + ath_hal_setchainmasks(sc->sc_ah, sc->sc_cur_txchainmask, + sc->sc_cur_rxchainmask); if (!ath_hal_reset(ah, sc->sc_opmode, ic->ic_curchan, AH_FALSE, &status)) { if_printf(ifp, "unable to reset hardware; hal status %u\n", status); @@ -2250,6 +2277,9 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type) ath_settkipmic(sc); /* configure TKIP MIC handling */ /* NB: indicate channel change so we do a full reset */ + ath_update_chainmasks(sc, ic->ic_curchan); + ath_hal_setchainmasks(sc->sc_ah, sc->sc_cur_txchainmask, + sc->sc_cur_rxchainmask); if (!ath_hal_reset(ah, sc->sc_opmode, ic->ic_curchan, AH_TRUE, &status)) if_printf(ifp, "%s: unable to reset hardware; hal status %u\n", __func__, status); @@ -4440,6 +4470,9 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan) */ ath_draintxq(sc, ATH_RESET_FULL); /* clear pending tx frames */ + ath_update_chainmasks(sc, chan); + ath_hal_setchainmasks(sc->sc_ah, sc->sc_cur_txchainmask, + sc->sc_cur_rxchainmask); if (!ath_hal_reset(ah, sc->sc_opmode, chan, AH_TRUE, &status)) { if_printf(ifp, "%s: unable to reset " "channel %u (%u MHz, flags 0x%x), hal status %u\n", diff --git a/sys/dev/ath/if_ath_tx_ht.c b/sys/dev/ath/if_ath_tx_ht.c index 7245d060fbc..c0e72ac84cd 100644 --- a/sys/dev/ath/if_ath_tx_ht.c +++ b/sys/dev/ath/if_ath_tx_ht.c @@ -498,13 +498,6 @@ ath_rateseries_setup(struct ath_softc *sc, struct ieee80211_node *ni, series[i].Tries = rc[i].tries; - /* - * XXX this isn't strictly correct - sc_txchainmask - * XXX isn't the currently active chainmask; - * XXX it's the interface chainmask at startup. - * XXX It's overridden in the HAL rate scenario function - * XXX for now. - */ /* * XXX TODO: When the NIC is capable of three stream TX, * transmit 1/2 stream rates on two streams. @@ -512,7 +505,7 @@ ath_rateseries_setup(struct ath_softc *sc, struct ieee80211_node *ni, * This reduces the power consumption of the NIC and * keeps it within the PCIe slot power limits. */ - series[i].ChSel = sc->sc_txchainmask; + series[i].ChSel = sc->sc_cur_txchainmask; if (flags & (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA)) series[i].RateFlags |= HAL_RATESERIES_RTS_CTS; @@ -542,6 +535,14 @@ ath_rateseries_setup(struct ath_softc *sc, struct ieee80211_node *ni, ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20) series[i].RateFlags |= HAL_RATESERIES_HALFGI; + /* + * XXX TODO: STBC if it's possible + */ + + /* + * XXX TODO: LDPC if it's possible + */ + series[i].Rate = rt->info[rc[i].rix].rateCode; series[i].RateIndex = rc[i].rix; series[i].tx_power_cap = 0x3f; /* XXX for now */ From d938ff1d15bdf214e948f8325b2deef94aca1570 Mon Sep 17 00:00:00 2001 From: Navdeep Parhar Date: Tue, 26 Feb 2013 00:10:28 +0000 Subject: [PATCH 0407/1476] cxgbe(4): Update firmware to 1.8.4.0. MFC after: 5 days --- sys/conf/files | 2 +- sys/dev/cxgbe/common/common.h | 8 +- sys/dev/cxgbe/common/t4_hw.c | 50 +- sys/dev/cxgbe/firmware/t4fw-1.6.2.0.bin.uu | 7600 ------------------ sys/dev/cxgbe/firmware/t4fw-1.8.4.0.bin.uu | 8237 ++++++++++++++++++++ sys/dev/cxgbe/firmware/t4fw_interface.h | 184 +- sys/modules/cxgbe/firmware/Makefile | 2 +- 7 files changed, 8384 insertions(+), 7699 deletions(-) delete mode 100644 sys/dev/cxgbe/firmware/t4fw-1.6.2.0.bin.uu create mode 100644 sys/dev/cxgbe/firmware/t4fw-1.8.4.0.bin.uu diff --git a/sys/conf/files b/sys/conf/files index eee46bb5cbe..55729ba114a 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1123,7 +1123,7 @@ t4fw.fwo optional cxgbe \ no-implicit-rule \ clean "t4fw.fwo" t4fw.fw optional cxgbe \ - dependency "$S/dev/cxgbe/firmware/t4fw-1.6.2.0.bin.uu" \ + dependency "$S/dev/cxgbe/firmware/t4fw-1.8.4.0.bin.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "t4fw.fw" diff --git a/sys/dev/cxgbe/common/common.h b/sys/dev/cxgbe/common/common.h index 54647eaeaf1..abc94224384 100644 --- a/sys/dev/cxgbe/common/common.h +++ b/sys/dev/cxgbe/common/common.h @@ -64,8 +64,9 @@ enum { }; #define FW_VERSION_MAJOR 1 -#define FW_VERSION_MINOR 6 -#define FW_VERSION_MICRO 2 +#define FW_VERSION_MINOR 8 +#define FW_VERSION_MICRO 4 +#define FW_VERSION_BUILD 0 struct port_stats { u64 tx_octets; /* total # of octets in good frames */ @@ -546,7 +547,4 @@ int t4_sge_ctxt_rd_bd(struct adapter *adap, unsigned int cid, enum ctxt_type cty int t4_sge_ctxt_flush(struct adapter *adap, unsigned int mbox); int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl); int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox, u32 addr, u32 val); -int t4_config_scheduler(struct adapter *adapter, int mode, int level, int pktsize, - int sched_class, int port, int rate, int unit, - int weight, int minrate, int maxrate); #endif /* __CHELSIO_COMMON_H */ diff --git a/sys/dev/cxgbe/common/t4_hw.c b/sys/dev/cxgbe/common/t4_hw.c index 099f5a9005f..3aea091347e 100644 --- a/sys/dev/cxgbe/common/t4_hw.c +++ b/sys/dev/cxgbe/common/t4_hw.c @@ -3909,13 +3909,13 @@ int t4_i2c_rd(struct adapter *adap, unsigned int mbox, unsigned int port_id, F_FW_CMD_READ | V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_FUNC_I2C)); c.cycles_to_len16 = htonl(FW_LEN16(c)); - c.u.i2c.pid_pkd = V_FW_LDST_CMD_PID(port_id); - c.u.i2c.base = dev_addr; - c.u.i2c.boffset = offset; + c.u.i2c_deprecated.pid_pkd = V_FW_LDST_CMD_PID(port_id); + c.u.i2c_deprecated.base = dev_addr; + c.u.i2c_deprecated.boffset = offset; ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c); if (ret == 0) - *valp = c.u.i2c.data; + *valp = c.u.i2c_deprecated.data; return ret; } @@ -4593,7 +4593,7 @@ int t4_alloc_vi_func(struct adapter *adap, unsigned int mbox, } } if (rss_size) - *rss_size = G_FW_VI_CMD_RSSSIZE(ntohs(c.rsssize_pkd)); + *rss_size = G_FW_VI_CMD_RSSSIZE(ntohs(c.norss_rsssize)); return G_FW_VI_CMD_VIID(htons(c.type_to_viid)); } @@ -5304,43 +5304,3 @@ int __devinit t4_port_init(struct port_info *p, int mbox, int pf, int vf) return 0; } - -int t4_config_scheduler(struct adapter *adapter, int mode, int level, - int pktsize, int sched_class, int port, int unit, - int rate, int weight, int minrate, int maxrate) -{ - struct fw_sched_cmd cmd, rpl; - - if (rate < 0 || unit < 0) - return -EINVAL; - - memset(&cmd, 0, sizeof(cmd)); - cmd.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_SCHED_CMD) | - F_FW_CMD_REQUEST | F_FW_CMD_WRITE); - cmd.retval_len16 = cpu_to_be32(V_FW_CMD_LEN16(sizeof(cmd)/16)); - - cmd.u.params.sc = 1; - cmd.u.params.level = level; - cmd.u.params.mode = mode; - cmd.u.params.ch = port; - cmd.u.params.cl = sched_class; - cmd.u.params.rate = rate; - cmd.u.params.unit = unit; - - switch (level) { - case FW_SCHED_PARAMS_LEVEL_CH_WRR: - case FW_SCHED_PARAMS_LEVEL_CL_WRR: - cmd.u.params.weight = cpu_to_be16(weight); - break; - case FW_SCHED_PARAMS_LEVEL_CH_RL: - case FW_SCHED_PARAMS_LEVEL_CL_RL: - cmd.u.params.max = cpu_to_be32(maxrate); - cmd.u.params.min = cpu_to_be32(minrate); - cmd.u.params.pktsize = cpu_to_be16(pktsize); - break; - default: - return -EINVAL; - } - - return t4_wr_mbox_meat(adapter, adapter->mbox, &cmd, sizeof(cmd), &rpl, 1); -} diff --git a/sys/dev/cxgbe/firmware/t4fw-1.6.2.0.bin.uu b/sys/dev/cxgbe/firmware/t4fw-1.6.2.0.bin.uu deleted file mode 100644 index fe4f03501d0..00000000000 --- a/sys/dev/cxgbe/firmware/t4fw-1.6.2.0.bin.uu +++ /dev/null @@ -1,7600 +0,0 @@ -/*- - * Copyright (c) 2012 Chelsio Communications, Inc. - * 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. - */ -begin-base64 644 t4fw -AAADSwEGAgAAAQkBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAzADPwNGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAENoZWxzaW8gRlcgUlVOTUVNIERFQlVHPTAgKEJ1aWx0IE1vbiBBdWcgMTMgMTM6 -MjU6MDYgUERUIDIwMTIgb24gY2xlb3BhdHJhLmFzaWNkZXNpZ25lcnMuY29tOi9ob21lL2ZlbGl4 -L3cvdDRmdy1yZWxlYXNlKSwgVmVyc2lvbiBUNHh4IDAxLjA2LjAyLjAwAAAAAAAAAAAAAGp9qktg -ALwAH/zhQIAAAAHhAHtwAAAQAB//9fjhAGAQ4QGUcCAAAADhAZwE4QB5AAACAEDhAHmAAAYAQAAC -AAoABgAK4QB5BAAKAACAAAEA4QB7POEAe0ThAHvk4gAAAAABAADhAHuQIAAAAAAAgADhAHsAAABA -AeEAe5wAAEAAREREQuAAAADjAARjREREQOMACAAgAAJcAAAAAB//ixAAAAAAH/+LFAAAAAAf/4sY -AAAAAB//ixwf/8AAAAAAAAAAAADAABH/0BL/0JIQEf/QEv/QkhAR/9AB9DER/9CQEBH/zyIK/5IQ -AOQxAAUxAQIAEv/MAucxAhYAEf/LgRABAV/AIQIRAckREf/IEv/IkhAR/8gS/8iSEGAADxH/wxL/ -x5IQEf/DEv/GkhCBEBH/xcAgkhES/8SSEsAgkhMS/8OSEIIQAvJQZS/3Ef/Bxy+SEBH/wJIQEv/A -E//AkyDAMpMhE/+/kyKCIhL/vhP/vpMgIyIhFP+9BDMByTgT/7yDMAODFAgzERT/uqQzkyET/66T -ImAACMIwkyET/6uTIhL/tZAgkCGQIpAjkCSQJZAmkCeQKJApkCqQK5AskC2QLpAvICYQICYRgiIS -/6jAMC03MC03NC03OC03PCM9AXIz7QACABL/pSMKAC83AC83EC83IC83MCM9AXIz7QACABL/msAw -KDcwKDc0KDc4KDc8Iz0BcjPtAwIAEv+YwDAnNwAnNxAnNyAnNzAjPQFyM+0DAgAS/5IV/5MW/5PA -MNcgBWYBYAAeAAAAAAAAAAAAAAAABDYFAAIA0w/TDwUzDG47FAdHFAcEQ3Yx5gQ2BQUzDG877QAC -ABL/hBX/giMKAAInAgcEQwQ+BQUzDAdHFG878AMCABL/fskugyCEIYUivCJ0Ow6GULRVljC0M3Qz -9GP/5gBlP+JlX98S/3LAMgMuBQMCABL/acAwKDdAKDdEKDdIKDdMIz0BcjPtAwIAAAIAEv9sLScA -wBEBSTEASDEBAgDAABT/aATSMRX/Z5RQFP9nBNMxFf9nlFAU/2YE1DEV/2aUUBT/ZgTVMRX/ZZRQ -EP9lAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf/AAA -H/wAAOMACfgf/AAAH/wAAOMACfgf/AAAH/wAAOMACfgf/4AAH/+F4OMACfgf/4XgH/+F4OMAD9gf -/4XgH/+F4OMAD9gf/4XgH/+HFOMAD9gf/4cUH/+LEOMAEQwf/4sQH/+gNOMAFQgf/6A0H/+gNOMA -Kiwf/8AAH//29eMAKiwgAAAAIAABauMAYSQgAAF4IAABfOMAYpAgAAF8IAABheMAYpQgAAGYIAAB -nOMAYqAgAAGcIAABpeMAYqQgAAG4IAABvOMAYrAgAAG8IAABxeMAYrQgAAHYIAAB2OMAYsAgAAHc -IAAB4uMAYsAgAAH4IAAB+OMAYsggAAH8IAAB/OMAYsggAAIYIAACGOMAYsggAAIcIAACHOMAYsgg -AAI4IAACOOMAYsggAAI8IAACPOMAYsggAAJYIAACWOMAYsggAAJcIAACYuMAYsggAAJ4IAACeOMA -YtAgAAJ8IAACguMAYtAgAAKYIAEewOMAYtggAoAAIAKTUOMBfwAgApNQIAKTUOMBklAgApNQIAYW -sOMBklAgBhawIAYbIOMFFbAgBoAAIAaNQOMFGiAgBo1AIAdScOMFJ2AgB1JwIAdTPOMF7JAgCMAA -IAjAAOMF7VwgCMAAIAjAAOMF7VwgCMAAIAkyJeMF7VwAAAAAAAAAAAAAAAAgAA8nIAAPGCAAEz0g -AA8YIAASqCAADxggAA/RIAASQiAAEcIgAA8YIAARbSAAERwgABCxIAAPBSAAEFwgAA8YIAAPGCAA -DxggAA/yAAAAACAAHk4gACCkIAAglSAAIIUgACB1IAAfpyAAH5ggAB47IAAeOyAAHjsgAB47IAAe -OyAAHjsgAB47IAAeOyAAHjsgAB47IAAe+CAAHukgAB47IAAeOyAAHjsgAB47IAAeOyAAHjsgAB47 -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 -H//ziB//84gf//OIH//ziB//7zAf//G0H//wYB//8GAf//BgIAXwAAAAAAAAAAAAAAAAAAAAAAAg -BfJoIAXyaAAAAAAAAAAAAAAAAAAAAAAgAQdgIAXwAB//8rQf//K0H//ytB//8rQf//K0H//ytAAA -AAAf/+84AAAAAAAAAAAAAAAAAAAAAAIBAAAAAAAAAAAAAAAAAAAEAAAAAAAAAIGAAAAAAAAQBQAA -AAAAAAQAAAAAAAAAAAAAAAAAAAAAgQAAAAAAABgFAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAQAAAAAAAACgQAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgCgAR8XcT8XfTDwPmMQECABbxdRfxdndrBpBgtGZ3Y/hU -DRVVlXsPFABj//kAAABsEAYpIAUqIAf4YKQVoBtFAPsgCt1hqgEAiyIuIBQc8WjxcjwN4AeVAAym -EaxmLWKe96AKW+IAnQAtYp3r1AAGilGAACnCrmSRFS3CrWTRD6TuDg5HLiQU9cALpdIAnQAf8Vku -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 -+kBoHaALRQBb/6VlrwGPEI/zLiEJDw9D5O4RD/7CgAD/xgAPcB8FAA/uAv7ABhWv+9YAK3wY6iQA -CWAEgABb/xRj/2NsEAgbm3ObEPhACBWgCQUAmRKZE5MU5BYFKVAEgAD0IMYV4AwlAOYWByxGAoAA -/QYADDANJQDoFgEo2ASAAFv/lNEPAGwQBMAg0Q8AbBAGlRCWESwgO4Yn4xYCI9kBAAD6IEgVr8gF -APTEABXj7AEA6FUBD3cCgAD/QABFMA0VAPtFABWgAKIALCA7sd2xzCwkO45r5egIBXhBAADojEAv -0ASAAPngBuKiAJ0AiaHpTzYE/tmAAO9EDA1IBIAA6SYADeAEgAAMBIoJAIgMAIqfsY6jiaEjogIO -/ggPmQwppgHupgMl2EEAAO/rB3ngBIAALDwB7KYCIg5DAACOEC8hIoURGps0JCEHiRIjIQn6QPAV -6kQBAOmSACojAoAABDMCJCEk+yAEBLC7EQDqmood2oKAAPsmAAzzhQEA65p3HEICgAAIRAIYmyQK -mQKZcIwgnnWTcxKagJR0lXbi/wIOZgKAAO92AiaQEQAADCwCnHHrABUDqMEAAAUAigjYAph+0Q8A -/+8ADT/8kgAgAzGmIAMxyCADMp0gAzNRIAMz0SADNE4gAzS7IAM1XSADVIIgA1RyIANUeiADVIIg -A1RyIANUciADVHIgA1R6IANUgiADVIIgA1RyIANUciADVNQgA1U0IANU1CADVNQgA1U0IANVNCAD -VTQgA1TUIANU1CADVNQgA1U0IANVNCADVeEgA1bbIANW5SADVeEgA1bbIANW2yADVtsgA1blIANV -4SADVeEgA1bbIANW2wMPCBKDjpOSAAAAAAAAAAAgA4RZIAOFdCADhFkgA4RZIAOFdCADhXQgA4V0 -IAOEWSADhFkgA4RZIAOFdCADhXQgA4ZFIAOGxSADhz4gA4d5IAOHjSADiE0gA4jLIAOI3iADiUog -A4l5IAOJngAAAAAgA5ETIAOSYCADj+QgA5AHIAOQ+yADj8QgA4/cIAOSfSADktggA5ZNIAOVDSAD -lUcgA5NpIAOT2yADlEkgA5SIIAOUwCADlb0gA5W1IAOVrSADlXEgA5VpAAAAAAAAAAABEBgBAAEA -AAAAAAAAAAAAIAPaSCAD2kggA9hbIAPaSCAD2FsgA9okIAPZ/SAD2FsgA9kxIAPYWyAD2FsgA9ko -IAPYWyAD2kggA9hbIAPYWyAD2kggA9hkAAAAAAAAAAADAQACAAAAAAAAAAAAAAAAIAReXSAEXSgg -BF0tIAReXSAEXSggBF0oIARdKCAEXS0gBF5dIAReXSAEXSggBF0oIARliiAEZbggBGc/IARliiAE -ZzcgBGcdIARliiAEZYogBGWKIARliiAEZYogBGWKIARliiAEZYogBGWKIARliiAEZwggBGbzIARl -iiAEZYogBGWKIARliiAEZYogBGWKIARliiAEZYogBGWKIARliiAEZYogBGWKIARliiAEZYogBGbI -IARliiAEZq0gBGatIARliiAEZYogBGaNIARliiAEZq0gBGWKIARliiAEZYogBGWKIARliiAEZYog -BGWKIARliiAEZYogBGWKIARliiAEZYogBGWKIARliiAEZYogBGWKIARliiAEZYogBGWKIARliiAE -ZYogBGWKIARliiAEZm0AAAAAAAAAAAAAAAAgBKxIIASsSCAEq1ogBKxIIASlpCAErD4gBKwYIASl -pCAEpaQgBKWkIASlpCAEpaQgBKs6IASsSCAEpaQgBKs6IASsSAAAAAAAAAAAAAAAACAEviQgBLtB -IAS/QCAEvuwgBL6eIAS+diAEvmsgBL4kIAS74gAAAAAAAAAAAAAAAAEQGAEAAgAAARAYAQACAAAg -BQU2IAUFCyAFA3MgBQTTIAUE0yAFBNMgBQNzIAUE0yAFA3MgBQS0IAUDcyAFA3MgBQS0IAUE0wAA -AAAAAAAAIAUo0CAFJKQgBSikIAUoeCAFKEwgBSTLIAUkyyAFJOIgBSgzIAUlFyAFJQMgBSTLIAUl -FyAFJMsgBSTLIAUkyyAFKNAAAAAAAAAAAAAAAAAAAAAAIAWECCAFfGAgBXwQIAV4yAAAAAAAAAAA -AAAAACAFfEogBXxGIAV8RiAFfEYgBXxKIAV8RiAFfEYgBXxGIAV8RiAFfEYgBXxGIAV8RiAFfEYg -BXxGIAV8RiAFfEYgBXxGIAV8RiAFfEYgBXxGIAV8RiAFfEYgBXxGIAV8RiAFfEYgBXxGIAV8RiAF -fEYgBXxGIAV8RiAFfEYgBXxGIAV8RiAFfEYgBXxGIAV8RiAFfEYgBXxGIAV8RiAFfEYgBXxGIAV8 -RiAFfEYgBXxGIAV8RiAFfEYgBXxGIAV8RiAFfEYgBXxGIAV8RiAFfEYgBXxGIAV8RiAFfEYgBXxG -IAV8RiAFfEYgBXxGIAV8RiAFfEogBXxGIAV8RiAFfEYgBXxKIAV8RiAFfEYgBXxGIAV8SiAFfEYg -BXxGIAV8RiAFfEogBXxGIAV8RiAFfEYgBXxKIAV8RiAFfEYgBXxGIAV8SiAFfEYgBXxGIAV8RiAF -fEogBXxGIAV8RiAFfEYgBXxKIAV8RiAFfEYgBXxGIAV8SiAFfEYgBXxGIAV8RiAFfEogBXxGIAV8 -RiAFfEYgBXxKIAV8RiAFfEYgBXxGIAV8SiAFfEYgBXxGIAV8RiAFfEogBXxGIAV8RiAFfEYgBXxK -IAV8RiAFfEYgBXxGIAV8SiAFfEYgBXxGIAV8RiAFfEogBXxGIAV8RiAFfEYgBXxGIAV8RiAFfEYg -BXxGIAV8RiAFfEYgBXxGIAV8RiAFfEYgBXxGIAV8RiAFfEYgBXxGIAV8RiAFfEYgBXxGIAV8SiAF -fEYgBXxGIAV8RiAFfEYgBXxGIAV8RiAFfEYgBXxGIAV8RiAFfEYgBXxGIAV8SiAFfEYgBXxGIAV8 -RiAFfEYgBXxGIAV8RiAFfEYgBXxGIAV8RiAFfEYgBXxGIAV8RiAFfEYgBXxGIAV8RiAFfEYgBXxG -IAV8RiAFfEYgBXxGIAV8RiAFfEYgBXxGIAV8SiAFfEYgBXxGIAV8RiAFfEogBXxGIAV8RiAFfEYg -BXxKAAAAAAAAAAAAAAAAIAV8niAFfYsgBX84IAV/KiAFfxUgBX8HIAV+8iAFfuQgBX7PIAV+wiAF -fq8gBX6iIAV+jyAFfoIgBX5vIAV8kCAFflwgBX5PIAV+PCAFfi8gBX4bIAV+ESAFfgAgBX32IAV9 -5SAFfJAgBXyQIAV8kCAFfJAgBXyQIAV8kCAFfdggBXy3IAV8kCAFfJAgBXyQIAV9uyAFfaIgBX2Z -IAV9fCAFfJAgBX1pIAV9TyAFfTwgBX0iIAV9DyAFfPcgBXzkIAV80QAAAAAAAAAAAAAAACAFhGEg -BYS2IAWF0iAFhaogBYWjIAWFnCAFhZUgBYWOIAWFhyAFhYAgBYV5IAWFbyAFhWUgBYVHIAWEySAF -hE4gBYTAIAWEawAAAAAAAAAAIAXawCAF2CQgBdaQIAXU3CAF0cwgBc8sIAXRsAAAAABSVgAAAAAA -AEG9zWUAAAAAY29uZmlndXJhdGlvbiBmaWxlIHBhcnNlciBmb3VuZCBhZGRpdGlvbmFsIGNvbmZp -Z3VyYXRpb24gYWZ0ZXIgW2ZpbmldCgAAZmNvZQAAAAB2bmljX2lkAHZsYW4AAAAAdG9zAGV0aGVy -dHlwZQAAAG1hY21hdGNoAAAAAG1wc2hpdHR5cGUAAGZyYWdtZW50YXRpb24AAABiYXNpY3ZpcnR1 -YWwAAAAAc3lubWFwZW4AAAAAc3luNHR1cGVuaXB2NgAAAHN5bjJ0dXBlbmlwdjYAAABzeW40dHVw -ZW5pcHY0AAAAc3luMnR1cGVuaXB2NAAAAG9mZG1hcGVuAAAAAHRubG1hcGVuAAAAAHRubGFsbGxr -cAAAAGhhc2h0b2VwbGl0egAAAAB0cF9waW8AAHRwX3RtX3BpbwAAADAAAABuaWNfdm0AAG5pY191 -bQAAbmljX3VtX2lzZ2wAb2ZsZAAAAAByZGRwAAAAAHJkbWFjAAAAaXNjc2lfaW5pdGlhdG9yX3Bk -dQBpc2NzaV90YXJnZXRfcGR1AAAAAGlzY3NpX2luaXRpYXRvcl9mb2ZsZAAAAGlzY3NpX3Rhcmdl -dF9mb2ZsZAAAZmNvZV9pbml0aWF0b3IAAGZjb2VfdGFyZ2V0AHBwcABkY2J4AAAAACACkHBuc3Rh -Y2tfbmwydCBbJXVdLCBmb2lzY3NpX250Y2IgWyV1XSwgcmMgWyV1XQoAAAAABAAAAAQAADB4AAAw -WAAAMEIAACAGAfAgBegwIAYB4CAF6EAgBehUIAXnZCAF6PwgBecAAAECAwAAAAAgA65sIAOt8CAE -uEgAAAAAIAOt6CADreAgA63YAAAAAGOCU2MAAAAAAAAAAAAAAABBQkNERUZHSElKS0xNTk9QUVJT -VFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSsvPQAAAAAAAAAAAAAA -AAAAAAsAAAAgApCwCAAAACACkLwIAAAAIAKQyAoAAAAgApDUDAAAACACkOASAAAAIAKQ8A0AAAAg -ApEEDgAAACACkRQTAAAAIAKRJAoAAAAgApE4DgAAACACkUQYAAAAIAKRVA0AAAAgApFwDgAAACAC -kYAQAAAAIAKRkBIAAAAgApGkDgAAACACkbgQAAAAIAKRyBEAAAAgApHcCgAAACACkfALAAAAIAKR -/A0AAAAgApIIFAAAACACkhgKAAAAIAKSMA8AAAAgApI8BgAAACACkkwGAAAAIAKSVAYAAAAgApJc -BgAAACACkmQGAAAAIAKSbAkAAAAgApJ0BgAAACACkoAEAAAAIAKSiAYAAAAgApKQCwAAACACkpgL -AAAAIAKSpAQAAAAgApKIBAAAACACkrAJAAAAIAKSuAkAAAAgApLEAAAAAAAAAAANAAAAIAKS0AoA -AAAgApLgBgAAACACkuwCAAAAIAKS9AMAAAAgApCsAQAAACACkvgAAAAAAAAAAP///////wAAAAdD -AAAAAAD/////////////////////AAAAgAAAAQAAAAIAAAAEAAAACAAAABAAAAAAAAAAAAADAgEA -AAAAAAAAAAAAAAAAAAAABQAAAAMAAAABAAAAAiAF3swgBd6EIAXdfCAF3DwgBdv8IAXb0CAF3CQA -AAAAAAACAAAABAAAAAgATkEAAFYwAABWMQAAVjIAAFYzAABWNAAAVjUAAFY2AABWNwAAVjgAAFY5 -AABWQQAAVkIAAFZDAABWRAAAVkUAAFZGAABhbGwAKgAAAG5vbmUAAAAAMHgAAHBvcnQAAAAAcHJv -dG9jb2wAAAAAZ2xvYmFsAABmdW5jdGlvbgAAAABmaW5pAAAAAHJlZwBmaWx0ZXJNb2RlAAByc3Nf -Z2xiX2NvbmZpZ19tb2RlAHJzc19nbGJfY29uZmlnX29wdGlvbnMAAHNnZV90aW1lcl92YWx1ZQB0 -cF9wbXJ4AHRwX3BtcnhfcGFnZXNpemUAAAAAdHBfcG10eAB0cF9wbXR4X3BhZ2VzaXplAAAAAG10 -dXMAAAAAbnZmAHd4X2NhcHMAcl9jYXBzAABuaXFmbGludAAAAABuZXEAbmV0aGN0cmwAAAAAbnZp -AG5leGFjdGYAY21hc2sAAABwbWFzawAAAG5ldGhvZmxkAAAAAG5yb3V0ZQAAbmNsaXAAAABuZmls -dGVyAG5zZXJ2ZXIAbmhhc2gAAAB0cF9sMnQAAHRwX2RkcAAAdHBfZGRwX2lzY3NpAAAAAHRwX3N0 -YWcAdHBfcGJsAAB0cF9ycQAAAGlzY3NpX250YXNrAGlzY3NpX25zZXNzAGlzY3NpX25jb25uX3Bl -cl9zZXNzaW9uAGlzY3NpX25pbml0aWF0b3JfaW5zdGFuY2UAAABpc2NzaV9tYXhfc2dlAAAAcHBt -X21heF96b25lcwAAAHBwbV96b25lX3JhbmdlMABwcG1fem9uZV9yYW5nZTEAcHBtX3pvbmVfcmFu -Z2UyAHBwbV96b25lX3JhbmdlMwBmY29lX25mY2YAAABmY29lX252bnAAAABmY29lX25zc24AAABk -Y2IAYmdfbWVtAABscGJrX21lbQAAAABod20AbHdtAGR3bQB2ZXJzaW9uAGNoZWNrc3VtAAAAAENo -ZWxzaW9fRk9pU0NTSQAwMTIzNDU2Nzg5YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoAAAAAMGIA -AFllcwBTZXNzaW9uVHlwZQBPRk1hcmtlcgAAAABJRk1hcmtlcgAAAABEYXRhRGlnZXN0AABIZWFk -ZXJEaWdlc3QAAAAARXJyb3JSZWNvdmVyeUxldmVsAABJbW1lZGlhdGVEYXRhAAAARGF0YVBEVUlu -T3JkZXIAAERhdGFTZXF1ZW5jZUluT3JkZXIASW5pdGlhbFIyVAAATWF4Q29ubmVjdGlvbnMAAE1h -eFJlY3ZEYXRhU2VnbWVudExlbmd0aAAAAABJbml0aWF0b3JOYW1lAAAASW5pdGlhdG9yQWxpYXMA -AERlZmF1bHRUaW1lMldhaXQAAAAARGVmYXVsdFRpbWUyUmV0YWluAABNYXhCdXJzdExlbmd0aAAA -Rmlyc3RCdXJzdExlbmd0aAAAAABNYXhPdXRzdGFuZGluZ1IyVAAAAFRhcmdldE5hbWUAAFRhcmdl -dEFsaWFzAFRhcmdldEFkZHJlc3MAAABUYXJnZXRQb3J0YWxHcm91cFRhZwAAAABBdXRoTWV0aG9k -AABTZW5kVGFyZ2V0cz1BbGwAQ0hBUF9BAABDSEFQX0kAAENIQVBfQwAAQ0hBUF9OAABDSEFQX1IA -AERpc2NvdmVyeQAAAE5vcm1hbAAATm9uZQAAAABDUkMzMkMAAENSQzMyQyxOb25lAE5vbmUsQ1JD -MzJDAENIQVAAAAAAQ0hBUCxOb25lAAAATm9uZSxDSEFQAAAATm90VW5kZXJzdG9vZAAAAElycmVs -ZXZhbnQAAFJlamVjdAAATm8AADUAAAAAAAAMAAAAAAEAAXwADAEAAAAAEAAAABQgBhHgAAADFQ5A -AAAf/AAAH/wAAB//oDgf/6A4IAYbICAGH1AgB1NAIAdTQCAHwAAgCBBAIAhAACAIwAAgCQMAH/+P -rB//kWABAAAAKAAAAOAAAAAgCQLAAAD//wD///8AIAAAIAjAkCAIwPAgBhsgH/zeAB//kfAIAAAA -BAAACIEAAAAqAAAAIAKmnCAJBLAgCMGQH/+PnCAJBhAgCMIgIAjCgCAJBmAAmJaAAACAACACtHD/ -//f/AAQAACAJByAgCQawH/+PDCAJBwAgBhtgA//QAAAQAgAAQAAAAFAH/wDAAAAgCQeg//9AACAJ -A8AAAA//IAKNEAAACAYAAAgAIAkH4CACrpQAD//wAAAf/iAIwvAgCMMwIAjDcNdqpHjox7dWJCBw -28G9zu71fA+vR4fGKqgwRhP9RpUBaYCY2ItE96///1uxiVzXvmuQESL9mHGTpnlDjkm0CCH2HiVi -wECzQCZeWlHptseq1i8QXQJEFFPYoeaB59P7yCHhzebDNwfW9NUNh0VaFO2p4+kF/O+j+GdvAtmN -KkyK//o5Qodx9oFtnWEi/eU4DKS+6kRL3s+p9rtLYL6/vHAom37G6qEn+tTvMIUEiB0F2dTQOebb -meUfonz4xKxWZfQpIkRDKv+Xq5Qjp/yToDllW1nDjwzMkv/v9H2FhF3Rb6h+T/4s5uCjAUMUTggR -ofdTfoK9OvI1KtfSu+uG05EgAotwIAKIoCACjHAgAowAIAKQgCACi1AgCMPQIAjEED/////P//// -IAKLfCAJCVBnRSMB782riZi63P4QMlR2IAkJcCAJCZAgCQmwIAkJ0CAJCfAgApCoIAKKwCACjCwg -AotsIAjEUCAJChDAAAAAIAkKUAAAIAAgCQqgH/+PECAJCsAgCQtAIAkK8CAJC6AgCQvQIAjEgCAI -xOAgCMSwIALVfCACq3wgAqisAADAACAJCIAgCQjgIAkIQCAIxSAf/4+oIAjFQCAGF7QgCQxAIAkM -sCAIxWDhAAAAIAjGUCACixAgCMbAIAjG4CAIx3AgCMcQIAjHQCAJBRAgCQVwIAkM4BoAAAAgCQQA -IAkEUCAFWmQAD0JAIAKkECAIyIAgAotoIAKQgCACikQgCMkQIAjI4B//jxQgCMlAIAjJsCAIymAE -AQAIIAjKICAIytAgCMqgIAjLACAJDXAgCQ2gIAjJ4FMAAAAgCMtAIAjLsCACi9AgCMvgIAkNQCAI -zCAgCMxgIAjMwCAIzPAgCMyQIAjNICAIzWAgCM2wIAjN8CAGGygKAAAAIAMW8B//jfQgBhkwAA/8 -ACAIzxBVAAAAIAjPoCAI0EAAADAAAAAP/h//j6QAAAwg8AAAACAI0HAgAzjEAABAAB//kBAf/4tg -IAKLMCAI0MAgCNEQH/+PACAI0dAgCQ5wIAjRcCADJdggCNIwIAjSoCAI0vAgCQ8AIAjTMCAI06Ag -CQ9AIAkQgCAI1AAf/4+YIAjUcCAGHlAgCNTwIAYeECAJENAXkAAAIAYWwH////8gAoAAH/+PuCYA -AADAAAABIAjWkCAI1sAgCNbgIAjXEIAAAAAgCNVQFLAAAAAAUACAAAAEIAM2uB//jSggCNYQFaAA -AAAAj/4gCNZAFqAAACMoFQAgoAAAP/AAACOgAAAD/wAfIAAAACAGHhogCNWAIAjVwCAI11D//wAA -EAAAACAI16AgCNgADgAAACAI2CAgAzcwIAjYQCAI2JAgCNrQH/+P2CAI2iAgCNqAIAjY8CAI2WAg -AoncIAjZwOEBjgAAAMggIAkREAABkQwgCRFgIAkRkOECFgDhAhoA///I////F////x//AAAQAAAC -GRwAAhl8AAIZnB//j7T///H/AAIZAAACGqQAAhooAAIaqAACGjQAAhq0AAIaMAACGrAgCNswAADE -AP//8//hAg4AAAAThyACgCAgAoBQIAKAgCAI24AAAMRFAADIAAAAJxAgCNtQQAAAAB3///9iAAAA -AADoACAI2+AgCNwgIAjbsAAADAAAABgAAAIQNCAEhgAAAMQwIAkR4CAJEbDhAF4AAAJJ7wAAzAAg -AoCwH/+LgCAI3FAgCNzgIAjcgCAI3LD//7//IAjdUB//kFgf/4v0AB6EgAABhqD/4XuAAAST4P/7 -bCAgCN2AIAjd8CAI3iAgCN5QIAjegCAI3rAgCN8QIAje4OD//gAAAhAIIAjfYCAJEuAgCRMQIAkT -QCAJE3AAABAQAABQEOECGAAAAH/9AAAQEeECFwThAhcAAAAMCf8AAP8AAAwOAAAMDAAADAvf//// -AAAMCgAAwBAAAmJaAADDMCACgMAQEAAAIBAAAAAQB2D/7/ifHv4AAOECGAzwAMNwH/+L8AAIAAAg -AoDwAAIQ4OECEgAAgAAAAAASAAACFQAAABOIAAAgAR//jmAdzWUA7////yACgSAAAMNQ9////yAC -gUCAf////4B//7//////P///AAehIP/AAD8gCN+QAAAXcCAJE8AgCROgIAOYeCAJE/AgCRQQIAYZ -FB//j6AgCN/AH/+PLCAI3+AgCOAAIAjgMB//jhThAH4AH/+PPAAA8/8EAAAAH/+SABQAAAAgA5+0 -H/+cACAI4NCD/7cAg/+2ICAJFIAf/5AYH/+dKDAAABAgCRTAIAkVIB//jRwgCRVQ4QH+ACIiIiIf -/56kIAjhIAAADLwAAIkGIAjhUOAACSQAnAAAIAjhcCAI4cAgCOHgAAIEwOEAjgAAAJaAAACWQCAG -GzAAAJagAACWYOECACwAAgAA4QB6AAAB4ADhAZIAAAHjAB//j7wgCOIwIAjiYAAAE9wf/51AH/+d -5AAP//8gBh3QAABgACAGHdoAABPKAACD/yACgYAIUAEAAMAABB//nqggBfCwIAPDmOEBlgAf/40s -H/+PsCAF8HTerb7/GsAAACAGHNgAAP/qIAYd4AAACBQAAIgAABAAAB//jjwgA9gYOAAAADAAAHQf -/4PwIAKBkCAI4pAwAAAIMAAADDQAAAjQAAAAAACJFDsAAAg0kAAAADAAAP8H//8FXUqAIAPdwAAY -AAAAOAAAIAkVoAYAAAAgA+pw+AAAAAH//+cAAcAAIAAAgAQAEAAf/46EH/+NYB//jqThAZoA4QGa -QOEBmjzhAZo44QGaNOEBmjAf/46cIAkV8CAI44AgCOOwIAkWgAMAAACDAAAAIAkXACAJF3CAAAAD -gAAAAv/8//8AAQAA4QEOAAAAEHAf/OIEH/+MwB//jUAgBAKQIAkaYCAJGBAgCRhQIAkaACAJGjAg -CRiAIAkYwCAJGPAgCRkwIAkZYCAJGaAgCRfg//AAAB//j2wf/51QIAQR4CAJG2AgCRuQIAkbACAJ -GqAAACMoH/+OHAAA/4AgCOPw//v//+EB4sAAAPgAAAIBDAACAQiP////AADwAOEBmAAgCORAIAjk -kCAI5MAgCOUA4QDeAAACAwgAAgIA///wAOEA7gAf/4/E//9//wAA4AAAAPwAAAIDBAABERwAAREY -ABAIAIAACAAAAgEEH/+PIP//wAAAAP/+AAAlgAACAwD8/4Dv4P/iwCAJG+AgCRwQIAkcMCAJG8AA -AP/zIAjlUCAJHFAgCOVwIAkckAAAKjAAAP/4AAD/8QAA/48AAFK1AABICgAAj4IAAI+GAAA4AAAA -j4oAAOM/AACDriAJHHAgCOWQ///PvwAAEEAgAoHgIAjlwCAJHLAAAP/7IAKB8B3/8O/+AAAAAF/2 -pwCyN8cAAAoAIAjmAP//3///9///IAkUMCAJFFAAABkAIAKCICAI5qAgCOZwIAkc4AACFgh/P/// -AAD5/wAA/z8AAP7/AAD/wCAJHTAgCOYwIAkd4CAJHZAf/5HU4AAGAAAAgMIAAP4AIARuzCAI5xAA -ACEAIAR3CCAGF9AgBhfgIAYX8CAGGAAgBhgQIAYYICAJEgAgCRJAAAGQ+CAJErAgBhawIAjnQOEC -FiQBMPhAGwAAAAADAAIgCR5AIAjnwCAI5/AAJiWgAmJaAAX14QAgCR7AIAkegCAI53AgCOgQH/+f -PCAI6GAgCOigIAjo0CAI6RAgCOlAIAjpcCAJHwAgCR9AIAkfgCAI6cAgCR/gIAjpkB//nOwgCSAQ -IAKDMCAI6vAQAAUN7gAAAAHAgAAJAAAAAACCACAI6gAAAIMAIAjqUCAI6qAQAAcCqqqqqszMzMz/ -AP8A8PDw8CAI7DAABQACIAjskCAI7LAAAPz/IAjs0CACg4AgA6xUIAOpoCADq8ggCSDwAP/AABIA -AAAgBMjAIAkhkCAJIVAgCO0AIAjtYCAJIdAA///8AAAQNv//7/8gAoOwH/+dNCAD5ygAAAhQIAKD -uDIAAAAAAAhAAP//+gAAgAXerb7vgYAAAAAAg/0wAAAcMAAABDAAABQAAP/v//3////+//8gAoPA -AP/wAAAoAAAgCO2wMAAAADAAADQAAIABIAKEAAAAgAIf/OB0EAAFEJkAAAA0AAAAIAkjsCAI7fAA -GQAAIAjuQCACjRgAABshfwAAAP8AAAAgCO5wIAjvcCAI76AgCO9AIAju0CAI7/AgCPBgIAkjACAC -irAgCSMgIAkjYCAJIjAgCSKQAACABzOQAAAgCPCwIAjxAAABkawgCPFgIAYbUAsAAAAgBV8wIAjy -ACAI8jAgCPJgIAkkACAJJKAgCSTwIAklYCAD7wQf/454IAKNIAAPAAAgA+/UH/+QeCAETbR8AP8P -H/+Q4OEALgDhAJYA4QCaAAAACf8AALAAIAKEUOEADgARAAAAH/+PHOEAEgAgCPMAIAkmYAABlI8A -AZTP///v+CAChHAf/42wIAKHYB//jzgAAknwH/+NgB//jBAgAogwIAj0EB//j2AgCPVAAD///x// -jBgAAP/3AAD//QAA/9UAAOqXwgAADgXcAQAD/wAAIAj1oCAI9eAgCPYwIAj2cCAI9sAgCPcAH/zi -CAPoAADgAAkc/f//0OECAAQf/42Y4QICAOECggAABAXu4QIBBOEB4gAf/49UH/+OkB//ktgAAJxA -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 -KYAA8uFSDaC5lQAYST5yixgUST0WST6kJHlLCQZGCoZgCmAAyVPGKtEPGEZvqCiIgPhgJhWgAgUA -0Q/HL9EPAGwQBOYkAAIBaYAAizAZSTH8kmAFoP31APrwAAVwOBUA+UGSDaACBQAJqQqJkAqQAMYq -0Q9lX9PHL9EPAAAAZELLK2AhKmAgCLsRC6oC+mAmFaACBQDRD2RC2ypgdv1AG/xiAJ0A2aD4YCYV -4AIFANEPZE+7LGANZMMC8mAmFaACBQDRD2RPqC1gDWTTBfJgJhWgAgUA0Q9kT5UuYA1k4q/yYCYV -oAIFANEPAAAAAABkT30vYA1k8rHyYCYVoAIFANEPZE9qKGAN6WIOJBa5gACwmvpgJhWgAgUA0Q9k -T1ArYA1kss3yYCYVoAIFANEPZE89LGAN6WESJhY5gACwnfxgJhXgAgUA0Q9kTyMuYA1k4r7yYCYV -oAIFANEPZE8QiMePxqj/sP+fMdEPZE8BiWeJnimRIpkx0Q9kTvOKxpox0Q9kQdssYGArYGEIzBEM -uwL6YCYV4AIFANEPZE7RLWBUC4tH/WAMK+IAnQDH7/5gJhWgAgUA0Q9kTrSPZ4/+j/2fMdEPZE6n -KcKOKMKNqYiwiJgx0Q9kTpYqwo2aMdEPZE6MLcKMK8KLrbuwu5sx0Q9kTnsuwoueMdEPZE5xj2eP -/ijyEI//qP+w/58x0Q9kTl2IZ4iOiI+YMdEPZE5QiWeJnoqciZuqmbCZmTHRD2ROPYpniq6Kq5ox -0Q9kTjCLZ4u+jL6Lvay7sLubMdEPZE4djGeMzo3KjMmtzLDMnDHRD2ROCo1njd6N2Z0x0Q9kTf2O -Z47uj+iO56/usO6eMdEPZE3qj2eP/o/3nzHRD2RN3YhniI6JhoiFqYiwiJgx0Q9kTcqJZ4meiZWZ -MdEPZE29imeKriuhKSqhKKuqsKqaMdEPZE2oi2eLviuxKJsx0Q9kTZqMZ4zOLcEnLMEmrcywzJwx -0Q9kTYWNZ43eLdEmnTHRD2RNd45nju4v4SUu4SSv7rDunjHRD2RNYo9nj/4v8SSfMdEPZE1UiGeI -jimBIyiBIqmIsIiYMdEP2mBYDoYpYAwImRH5RgAM8IoFAAqZAvhgJhXgAgUA0Q+KMfrEBh2oqh0A -+sQmHaACBQDRD4sx+swmHei7HQD6zAYd4AIFANEPAIkxDwIAaJAB3ZDtZHYrUASAAFreVcAg0Q8A -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 -8tUSmAAAAAAAAAAAAAAAAP//AAUABgAHAAgACQAKAAsADAANAA4ADwAQ////////AAoAFACMAIIA -ZABaAKAAlgB4AG4AUABGADwAMgAoAB4ACgTOBJIJzgmSArIEVgTiBKYDtgQaB7IJVgZeAnYJ4gmm -B04COgi2CRoIFgYiAsYEagCWA3oBcgd2AL4D3gT2BLoEQgOiAmIHOgYOAIIDygQuAG4AWgMqATYB -6gM+B8YJagFKBxIFlgh6BsIB/gZyAooDUgXmBb4I3gGaB9oJ9gm6CX4HnglCCKIJBgFeB2ICTgcm -AxYBIgWCCGYFqgjKCS4IjgEOBW4FWgVGBtYIKgY2AhIBwgbqCD4A5gaGAtoEfgKeBAYGSgImCAID -ZgCqA44F+gBGAdYG/gauBdIBhgeKCPIDAghSAPoFMgGuANID8gfuADIGmgLuBR4AHgUKAAAJxAmI -BNgEnAeoCUwJ2AmcCKwJEAK8BGABaAdsBOwEsAJYBzADwAQkAyABLAe8CWAFjAhwBmgCgAW0CNQJ -7AmwCTgImAdYAkQBGAV4CMAJJAVkBVAIIAYsBuAINALQBHQGQAIcAKADhAHMBvQBfAeACEgA8ADI -A+gGkALkBQAExASIAqgETAOsBBAGVAJsB0QCMAgMBhgAjANwALQD1AQ4A5gGBAB4AGQAUAHgAzQB -QAcIBrgB9ANIBdwBkAfQCXQHlAj8AVQHHAMMCFwFoAiEAQQFPAbMAggBuADcBnwClAP8B/gDXAXw -ADwGpAXICOgC+AUoAaQH5AAoBRQAFAAABMkEjQnJCY0CrQRRBN0EoQOxBBUHrQlRBlkCcQndCaEH -SQI1CLEJFQgRBh0CwQRlAJEDdQFtB3EAuQPZBPEEtQQ9A50CXQc1BgkAfQPFBCkAaQBVAyUBMQHl -AzkHwQllAUUHDQWRCHUGvQH5Bm0ChQNNBeEFuQjZAZUH1QnxCbUJeQeZCT0InQkBAVkHXQJJByED -EQEdBX0IYQWlCMUJKQiJAQkFaQVVBUEG0QglBjECDQG9BuUIOQDhBoEC1QR5ApkEAQZFAiEH/QNh -AKUDiQX1AEEB0Qb5BqkFzQGBB4UI7QL9CE0A9QUtAakAzQPtB+kALQaVAukFGQAZBQUAAAm/CYME -0wSXB6MJRwnTCZcIpwkLArcEWwFjB2cE5wSrAlMHKwO7BB8DGwEnB7cJWwWHCGsGYwJ7Ba8Izwnn -CasJMwiTB1MCPwETBXMIuwkfBV8FSwgbBicG2wgvAssEbwY7AhcAmwN/AccG7wF3B3sIQwDrAMMD -4waLAt8E+wS/BIMCowRHA6cECwZPAmcHPwIrCAcGEwCHA2sArwPPBDMDkwX/AHMAXwBLAdsDLwE7 -BwMGswHvA0MF1wGLB8sJbwePCPcBTwcXAwcIVwWbCH8A/wU3BscCAwGzANcGdwKPA/cH8wNXBesA -NwafBcMI4wLzBSMBnwffACMFDwAAAAoAjABuAJYAeAA8AFAAoACCAGQAMgBGAFoAKAAeABQAAACH -AGkAkQBzADcASwCbAH0AXwAtAEEAVQAjABkAACACjiQgBwz4IAKOKCAHErggAo40IAcSaCACjkgg -BxG8IAKOYCAHEHwgAo5wIAcQVCACjnggBxAsIAKOjCAHEAQgAo6UIAcP3CACjqggBxNsIAKOsCAH -DLggAo60IAcMgCACjrwgBwxIIAKOxCAHDBAgAo7QIAcL2CACjtQgBwugIAKO4CAHC2ggAo7kIAcL -MCACjuwgBwr4IAKO9CAHCQwgAo78IAcKwCACjwggBwqIIAKPECAHClAgAo8YIAcKGCACjyAgBwng -IAKPKCAHCaggAo38IAcHMCACjzAgBwb4IAKPOCAHBsAgAo9AIAcGiCACj1AgBwZQIAKPWCAHBhgg -Ao9gIAcF4CACj2ggBwW4IAKPdCAHBZAgAo+AIAcFYCACj5ggBwU4IAKPtCAHBRAgAo/EIAcE6CAC -j9QgBwTAIAKP5CAHBJggAo/0IAcEcCACkAQgBwRIIAKQFCAHBCAgApAgIAcD+CACkCwgBwPQIAKQ -OCAHArggApA8IAcCiCACkEQgBwJYIAKQUCAHAiggApBUIAcB+CACkFggBwHIIAKQXCAHAaAgApBk -IAcBeCACjgggBxWwIAKOECAHFNwgAo30IAcUJCACjhwgBxN0AAAQISBCMGNAhFClYMZw54EIkSmh -SrFrwYzRreHO8e8SMQIQMnMiUlK1QpRy92LWkzmDGLN7o1rTvcOc8//j3iRiNEMEIBQBZOZ0x0Sk -VIWlarVLhSiVCeXu9c/FrNWNNlMmchYRBjB212b2VpVGtLdbp3qXGYc499/n/tedx7xIxFjlaIZ4 -pwhAGGEoAjgjyczZ7emO+a+JSJlpqQq5K1r1StR6t2qWGnEKUDozKhLb/cvc+7/rnpt5i1i7O6sa -bKZ8h0zkXMUsIjwDDGAcQe2u/Y/N7N3NrSq9C41onUl+l262XtVO9D4TLjIeUQ5w/5/vvt/dz/y/ -G686n1mPeJGIgamxyqHr0QzBLfFO4W8QgAChMMIg41AEQCVwRmBng7mTmKP7s9rDPdMc43/zXgKx -EpAi8zLSQjVSFGJ3cla16qXLlaiFifVu5U/VLMUNNOIkwxSgBIF0ZmRHVCREBafbt/qHmZe451/3 -fscd1zwm0zbyBpEWsGZXdnZGFVY02UzJbfkO6S+ZyInpuYqpq1hESGV4BmgnGMAI4TiCKKPLfdtc -6z/7Hov5m9iru7uaSnVaVGo3ehYK8RrQKrM6kv0u7Q/dbM1Nvaqti53ojcl8JmwHXGRMRTyiLIMc -4AzB7x//Ps9d33yvm7+6j9mf+G4XfjZOVV50LpM+sg7RHvAAADAEAAAwEAAAWQgAAFmkAAGUMAAA -ECQAABAwAAAQPAAAENwAAHssAAB7NAAB4owAAeaMAAHqjAAB7owAAfKMAAH2jAAB+owAAf6MAACN -zAAAfnQAAI/cAAGRWAAAj/wAAHUcAAB1GAAAdRAAAHfgAAB35AAAd/QAAZw8AAEQdAABEIQAAJQI -AACYXAAAlgwAAJYUAACWIAAAliwAANAoAACQCAACENwAAjDcAAJQ3AACcNwAAZBUAABgHAABoNgA -AZCQAAB34AAAd+QAAHf0AAB5eAAAefgAAZQEAAHjwAAB58AAAevAAAHvwAAB88AAAffAAAH7wAAB -/8AAAZQMACEACQCBAEEAIQAJACEACQCBAEEAgQBBAIEAQQCBAEEAIQAJAIEAQQAhAAkAIQARAIEA -QQCBAEEAIQAJAIEAQQAhAAkAIQAJAQEAQQCBACEAgQAhABAQYQAAAAAAAAAAAAAwAD////8AADAI -P////wAAWRCsgAAAAABZrH4lAAAAAZQQH////wABlDQAAAARAAGUCB////8AAZQ4AAAAEQAAECh/ -////AAAQLH////8AABA0f////wAAEDh/////AAAQQA9EAAAAAHsoAB//4gAAezA//+7/AAB7OAAA -AAEAAHtAP//u/wAAfCQAH//iAAHiiAAIAAAAAeaIAAgAAAAB6ogACAAAAAHuiAAIAAAAAfKIAAgA -AAAB9ogACAAAAAH6iAAIAAAAAf6IAAgAAAAAjcj/////AACN0P////8AAH5wf7///wAAfnh/v/// -AAB+AADAAAAAAZFUAf///wABkZwB////AACP2AB///0AAI/4/////QAAdRQAAAAHAAB1DAAAAAsA -AHfcAAAAAwAAd/D/////AAGcOAABgEAAAZz4AAAAAwAAkAQAAAA+AAEQeAD///8AARB8AP///wAB -EIgAAAAAAACUBAAA//8AAJQQAAD//wAAmFQAAAH/AACYWAAAAf8AAJYIAAAAAAAAlhAAH///AACW -GAAf//8AAJYcAA///wAAliQAD///AACWKAD///8AAJYwAP///wAA0CAAAAAHAADQJAAAAAcAAhDY -AAAAAwACMNgAAAADAAJQ2AAAAAMAAnDYAAAAAwABkFAAAAAvAAGg1AAAAYMAAZCMADgAAAABkJgA -OAAAAAB5dAAAAC8AAHlwAAAABQAAefQAAAAvAAB58AAAAAXhAg4AAABAAOEAXgAACAAIAAAw1AAA -5AAAAMQwAADEMSAI80AACYloAADEUCAI83AgCPOQIAjzsAAAIAAAAMRRAADAAQAAxFIgT/+AIFAA -ACAGhrQgCScAIAknYCAJJrAAAMAGAACAAAAIAAIgCSegAACA1wAAQIIAAMSCAACEAyAJKZAgCSiQ -AACApgAAgD0gCSfwAACAQCAJKPAgCSlAIAkoQB//jcgf/46IIAkqMCAI89DhAZoAH/+OYB//i/QA -AAgA/8D//wAQAAAgCSngAAYIACAI9DAgCPSQIAkrcCAJKyAgCSqAIAkq0OEALgAgAo0wAACQAB// -jTwALBQAgAAAgOEAWgCB8OCA4QAuCCAAAADhAFYADAAAAP/zgAAADDgARgAAAD8///+AgAAA8/// -///g//8AAQAAIAaAACAGhZQgBoEAH/+L8OEBkgDhAIoA4QAOAOEAfgDhAHoAAAIAAAB/AEAAAwAA -AIAAgADBAMD//yP/AADIABAgASDhAI4APAAAAP//v/9QaOhH+P///wQAAACSAAAA8ADwAJ+/+/sg -AAQEf/f//4AAAgD//+////+A///3/38AAH6wAAYAAAAAD/8AAH60AP///wBJJJIAAH4YCAEIARAB -EAEQAQgBAAB+QCABIAEVFRUVhCGEIRAQEBDhAY4AAAD+fwQEAYAf/40c4QDOABEREREiIiIiMzMz -Mx//kBThAI4E4QCOCOEAjgwgBoi04QB2ACACjVD///AA4P/+AIAAAQAgBoe0AACQCAAACMCAAcQR -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 -+iAIFaAMBQBbzLiJEuKWACGAOYAAJzQAyFEkVABmrvIS+JUoapCoIqJi0Q+JEhL4kf8gBhXmmAUA -qCKiYtEPAGwQBCsyACawAMBw6Gl+bcgEgABkYHYLuQL4IAIdoAoFAPwBIh2gLTUAbQhdaGwVfGES -fWEi6Iz/JVAFAADmJAAhEAUAALF3q3kmkABoaVVkgGjPYmAATQAkkAD8iEAE0AUFAKt75rAALbgE -gABtCBTkYDFiqAUAACZwAbF36Gkia8gEgABj/+TTD2P/m8CA6CQAJNAFAAD6YAYVoAIFANEPq3ur -WcmCwLDrJAAk4AUAAOw2AC0QBIAA0Q/GKtEPAGwQCFv+0e/4WB0+QgAAEvheFvhc/fC2BaAKFQD3 -8K4F4AlFAP/wrAWgBAUA8/CwBe/19QAY+Fco5qUv5qQk5qcd+FUt5qYb+FQr5qkY+FQo5qgv5qsd -+FIt5qovYoIb+FEY+FEL/wEI/wIvZoIe+E8uZoYqZoctSkUtZqUrwvAJuwIrxvAY+Eof+EufgC0y -wB74Sg7dAS02wCsy0CzqwP1gBAWxHFUADLsCKzbQGPhDKDbRLTLYH/hCHvhCD90BDt0CLTbYKzLb -HPhADLsCKzbbGPg+KCY1LTLSH/g9Hvg9D90BDt0CLTbSKzLSKHCALPr+DLsB6zbSLBBwAAArMtMd -+DYc+DYNuwEMuwIrNtMlNvQlNvUuMt4f+DLTDw/uAS423isywx34L/1gBAX1DAUADLsCKzbDKDLB -Gvgr+wAEBDCJBQAJiAIoNsEuMsIf+Cga+CYb+CgP7gL+eEYVpBwFAFvU1Br4JBv4JRz4JVvU0Rr4 -JP3wSgWgC1UAW80gGvgh/fBCBaALZQBbzR0a+B398DwFoAt1AFvNGRr4Gv3wNAWgC4UAW80WGvgW -/fAwBaALlQBbzRIa+BP98CoFoAulAFvNDxr4D/3wIAWgC6UAW80LGvgM/fAYBaALtQBbzQga+Awc -+A4Y+Az4QcYVoCsFAA8CAFvNAvvwDgWiS0UA/ABCHaANJQBby+/78AQFoUsVAPwAAh3g/PUAW8vr -++/6BaFLFQD8AAId4Pz1AFvL5hr3+P3v9gWg6UUA+EFGFeArNQBbzO4a9/P97+oFoCtFAFvM6xr3 -7/3v5AWgK1UAW8znH/fwFvfwnywvJgsvJg0sYtQe9+4d9+4OzAH9hgAOcCrlAPzahhWgCxUAW7Xr -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 -Y3NrX2ZjLT5mbG93Y19zdGF0ZSwgWzB4JXhdLCBjb25uX2ZjLT5mbG93Y19zdGF0ZSBbMHgleF0s -IGZsYWdzIFsweCV4XQoAAAAAAHNlbmRfY2xvc2VfcmVxOiBjc2tfZmMtPmZsb3djX3R5cGUgWzB4 -JXhdLCBjc2tfZmMtPmZsb3djX2lkIFsweCV4XSwgY3NrX2ZjLT50Y2Jfc3RhdGUgWzB4JXhdCgAA -AHNlbmRfY2xvc2VfcmVxOiBjc2tfZmMtPmZsb3djX3R5cGUgWzB4JXhdLCBjc2tfZmMtPmZsb3dj -X2lkIFsweCV4XSwgY3NrX2ZjLT5mbG93Y19jc29ja190aWQgWzB4JXhdLCB1bHB0eGNoIFsldV0s -IGltbWRsZW4gWyV1XSwgYnVmZmVyZWQgWyV1XSwgbGVuMTYgWyV1XQoAAAAAAABjc29ja19mYWls -ZWQ6IGNza19mYy0+Zmxvd2NfaWQgWzB4JXhdLCBjc2tfZmMtPmZsb3djX3N0YXRlIFsweCV4XSwg -c2Vzc19mYy0+Zmxvd2NfaWQgWzB4JXhdLCBzZXNzX2ZjLT5mbG93Y19zdGF0ZSBbMHgleF0sIGV2 -dCBbMHgleF0KAAAAAAAAAAAAAABmb2lzY3NpX2Nzb2NrX2Nsb3NlOiBzZXNzLT5mbG93Y19pZCBb -MHgleF0sIGNza19mYy0+Zmxvd2NfaWQgWzB4JXhdLCB0Y2JfZmMtPmZsb3djX2lkIFsweCV4XQoA -AABmb2lzY3NpX2Nzb2NrX2Nsb3NlOiBpc2Vzcy0+Zmxvd2Nfc3RhdGUgWzB4JXhdLCBjc2tfZmMt -PmZsb3djX3N0YXRlIFsweCV4XSwgdGNiX2ZjLT5mbG93Y19zdGF0ZSBbMHgleF0KAAAAAAAAAAAA -cmVjb3ZlcnlfdGltZW91dDogUmVjb3ZlcnkgZmFpbGVkIGluIFsldV0gcmV0cnkKAAAAAAAAAAAA -AAAAAAAAAHJlY292ZXJ5X3RpbWVvdXQ6IHNlc3NfZmMtPmZsb3djX2lkIFsweCV4XSwgcmV0cnkg -Y291bnQgWyVkXQoAAAByZWNvdmVyeV90aW1lcjogc2Vzc19mYy0+Zmxvd2NfaWQgWzB4JXhdLCBz -ZXNzX2ZjLT5mbG93Y19zdGF0ZSBbMHgleF0gc2Vzc19mYy0+ZmxhZ3MgWzB4JXhdCgAAAABsb2dp -bl9wYXJhbXM6IGNvbm5fZmMtPmZsb3djX2ZvaXNjc2lfY29ubl9kaWdlc3RfdG9fdWxwIFsweCV4 -XQoAbG9naW5fcGFyYW1zOiBjb25uX2ZjLT5mbG93Y19mb2lzY3NpX2Nvbm5fZGlnZXN0X3RvX3Vs -cCBbMHgleF0KAFRDUCBjb25uIGVzdGFibGlzaG1lbnQgZmFpbGVkICVkCgAAAAAAAAAAAAAAAAAA -AHdyaF9mb2lzY3NpX25vZGU6IG5vZGVfd3ItPmZsb3dpZF9sZW4xNiBbJXhdCgAAAHdyaF9mb2lz -Y3NpX2NoYXA6IGlkX2xlbiBbJXhdLCBzZWNfbGVuIFsleF0KAAAAAHdyaF9mb2lzY3NpX2NoYXA6 -IHRndF9pZF9sZW4gWyV4XSwgdGd0X3NlY19sZW4gWyV4XQoAAAAAAAAAAAAAAAB3cmhfZm9pc2Nz -aV9jcnRsLTEKAAAAAAAAAAAAAAAAAHdyaF9mb2lzY3NpX2NydGw6IDEgY29va2llICVwCgAAd3Jo -X2ZvaXNjc2lfY3J0bDogc2Vzc2lvbiB0eXBlICV1CgAAAAAAAAAAAAAAAAAAY2xlYXJfZGRwX21h -cDogaXN0YXNrX2ZjLT5mbG93Y19pZCBbJXVdLCB3ci0+b3BfaW1tZGxlbiBbMHgleF0gYWxyZWFk -eSBzY2hlZHVsZWQKAAAAAAAAAAAAAAAAAAAAcHJjb2VzX2RhdGFfaW5fcmVzcG9uc2U6IGNvbm4t -PmZsb3djX2lkIFsweCV4XSwgZGRwX3N0YXR1cyBbMHgleF0sIGlzdGFza19mYy0+Zmxvd2NfaWQg -WzB4JXhdCgAAaW4gbG9vcAoAAAAAAAAAAGZvaXNjc2lfc2V0X2RpZ2VzdDogY3NrX2ZjLT5mbG93 -Y19pZCBbMHgleF0sIHRjYl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBpbiBkZWxheV9wcm9jZXNzaW5n -CgAAAAAAAHVzZXJuYW1lIG1pc21hdGNoCgAAAAAAAAAAAAAAAAAAUmVjdmQgYW5kIENvbXB1dGVk -IGRpZ2VzdCBtaXNtYXRjaAoAAAAAAAAAAAAAAAAAYmFzZTY0IEVSUiwgJWQgbGVmdCwgd2l0aCAl -ZCBwYWQuCgAAAAAAAAAAAAAAAAAAYmFzZTY0IEVSUiwgJWQgbGVmdCwgd2l0aCAlZCBwYWQuCgAA -AAAAAAAAAAAAAAAAYmFzZTY0IEVSUiwgJWQgbGVmdCwgd2l0aCAlZCBwYWQuCgAAAAAAAAAAAAAA -AAAAUmVjaWV2ZWQgQXV0aE1ldGhvZCB2YWx1ZQoAAAAAAAB2YWxpZGF0ZV9rZXl2YWw6IGZsb3dj -X2ZvaXNjc2lfY29ubl9kaWdlc3RfdG9fdWxwIFsweCV4XQoAAAAAAAAAdmFsaWRhdGVfa2V5dmFs -OiBmbG93Y19mb2lzY3NpX2Nvbm5fZGlnZXN0X3RvX3VscCBbMHgleF0KAAAAAAAAAEtFWV9NQVhS -Q1ZEU0wgWyV1XQoAAAAAAAAAAAAAAAAARHVwbGljYXRlIGlzY3NpIGtleQoAAAAAAAAAAAAAAABz -ZW5kX2xvZ2luX3JlcXVlc3Q6IHNlc3NfZmMtPmZsb3djX2lkIFsweCV4XSwgc2Vzc2lvbl90eXBl -IFslZF0sIGNvbm5fZmMtPmZsb3djX2lkIFsweCV4XQoAAAAAAABmb2lzY3NpX3BhcnNlX3JjdmRf -cGFyYW1zOiBlcnJvcgoAAAAAAAAAAAAAAAAAAABmb2lzY3NpX3BhcnNlX3JjdmRfcGFyYW1zOiBy -bGVuICVkCgAAAAAAAAAAAAAAAABwcm9jZXNzX3RtZl9yZXNwb25zZTogaXN0YXNrX2ZjLT5mbG93 -Y19idWYtPnNjaGVkX25vZGUubmV4dCBbMHgleF0sIGlzdGFza19mYyBbMHgleF0sIGlzdGFza19m -Yy0+Zmxvd2NfaWQgWyV1XQoAcHJvY2Vzc190bWZfcmVzcG9uc2U6IHVscHR4cGxlbjE2IFsldV0K -AAAAAAAAAAAAcHJvY2Vzc190bWZfcmVzcG9uc2U6IGRlbGF5X3Byb2Nlc3NpbmcsIG9wIFsleF0K -AAAAAAAAAAAAAAAAAAAAAHByb2Nlc3NfdG1mX3Jlc3BvbnNlOjogcHJvY2Vzc2luZyBBQlJUIHJl -c3BvbnNlCgAAAAAAAAAAAAAAAAAAAABwcm9jZXNzX3RtZl9yZXNwb25zZTo6IHByb2Nlc3Npbmcg -TFJFUyByZXNwb25zZQoAAAAAAAAAAAAAAAAAAAAAcHJvY2Vzc190bWZfcmVzcG9uc2U6OiBBQk9S -VF9SRVNQT05TRQoAAAAAAAAAAAAAcHJvY2Vzc190bWZfcmVzcG9uc2U6OiBMVU5fUkVTRVRfUkVT -UE9OU0UKAAAAAAAAY2FsbGluZyBkcm9wX3Rhc2ssIGlzdGFza19mYy0+Zmxvd2NfZm9pc2NzaV90 -YXNrX2xpZHggMHgleAoAAAAAAGFzeW5jX3BkdTogYXN5bmMgbXNnIHJlY3ZkIHNlc3NfZmMtPmZs -b3djX2lkIFsweCV4XSwgY3NrX2ZjLT5mbG93Y19pZCBbMHgleF0sIGNvbm5fZmMtPmZsb3djX2lk -IFsweCV4XQoAAAAAAAAAAABTZXEgIyBtaXNtYXRjaCBzdGF0c24gPSAweCV4IGV4cHN0YXRzbiA9 -IDB4JXgKAABsb2dpbl9yZXNwOiBmbG93Y19mb2lzY3NpX2Nvbm5fZGlnZXN0X3RvX3VscCBbMHgl -eF0KAAAAAAAAAAAAAAAAbG9naW5fcmVzcDogZmxvd2NfZm9pc2NzaV9jb25uX2RpZ2VzdF90b191 -bHAgWzB4JXhdCgAAAAAAAAAAAAAAAGlTQ1NJIFNlYy1wYXJhbXMgcmVjZWl2ZWRoYXZlIGVycm9y -cyEhCgAAAAAAAAAAAFRhcmdldCBtb3ZlZCB0ZW1wLiBjb25uICV4LCBzZXNzICV4CgAAAAAAAAAA -AAAAAExvZ2luIEZhaWxlZCEhLiBjb25uICVkLCBzZXNzICVkCgAAAAAAAAAAAAAAAAAAAFByb3Rv -Y29sIEVycm9yIGNiaXQgJWQgdGJpdCAlZCBjc2cgJWQgbnNnICVkCgAAAHJlY3ZfdG1mX3Jlc3Bv -bnNlOiByZWNlaXZlZCB0bWYgcmVzcG9uc2UgcnNwLT5yZXNwb25zZSBbMHgleF0KAAByZWN2X3Rt -Zl9yZXNwb25zZTogdGFza19pZHggWyV1XSwgdGFnIFsweCV4XQoAAABJbnZhbGlkIG9wY29kZSAw -eCV4CgAAAAAAAAAAAAAAAHdyaF9vZmxkX3J4X2RhdGE6IGFpZWUsIGNvbm4gWzB4JXhdIHRyYW5z -aXRlZCBpbiB0b2UgbW9kZQoAAAAAAABzZW5kX2Fib3J0X3JlcTogY3NrX2ZjLT5mbG93Y190eXBl -IFsweCV4XSwgY3NrX2ZjLT5mbG93Y19pZCBbMHgleF0sIGNza19mYy0+Zmxvd2NfY3NvY2tfdGlk -IFsweCV4XSwgdWxwdHhjaCBbJXVdLCBpbW1kbGVuIFsldV0sIGJ1ZmZlcmVkIFsldV0sIGxlbjE2 -IFsldV0KAAAAAAAAaXNjc2lfaGRyOiBiYWQgY3NrX2ZjIHN0YXRlIHRvIHJ4IGRhdGEsIGNza19m -Yy0+Zmxvd2NfaWQgWzB4JXhdLCB0Y2JfZmMtPmZsb3djX2lkIFsweCV4XSwgY3NrX2ZjLT5mbG93 -Y19zdGF0ZSBbMHgleF0KAAAAAAAAAAAAAABhY3RfZXN0YWI6IHRjYl9mYy0+Zmxvd2NfYnVmIFsw -eCV4XSwgdGNiX2ZjLT5mbG93Y190eXBlIFsweCV4XSB0Y2JfZmMtPmZsb3djX3N0YXRlIFsweCV4 -XSwgbnBhZ2VzIFsweCV4XSwgZmxvd2NfdHBfc25kX21heCBbMHgleF0KAAAAAAAAAAAAAAAAAABh -Y3RfZXN0YWI6IGF0aWQgWzB4JXhdLCB0aWQgWzB4JXhdLCBvcCBbMHgleF0sIHJjdl9pc24gWzB4 -JXhdLCBzbmRfaXNuIFsweCV4XSwgY3NvY2stPmZsb3djX3N0YXRlIFsweCV4XSwgdGNwX29wdCBb -MHgleF0sIHRjYl9mYy0+Zmxvd2NfaWQgWzB4JXhdIAoAAAAAAAAAAAAAAAAAY3NrX2ZjLT5mbG93 -Y19jc29ja19jb29raWUgWzB4JXhdIAoAAAAAAAAAAAAAAAAAbmV0aWZfZG9fZGhjcDogd3ItPnBh -cmFtLnZsYW5pZCBbJXVdLCBsMmRldl9mYy0+Zmxvd2NfbmV0X2wyZGV2X3ZsYW5kZXYgWzB4JXhd -CgBuZXRpZl9kb19kaGNwOiBybDJkZXZfZmMtPmZsb3djX2lkIFsweCV4XSwgZGhjcF9jdHh0IGlu -aXRpYWxpemF0aW9uIGVycm9yCgAAAAAAAGwzaW40X2Rldl9jb25maWc6IHdyLT5wYXJhbS52bGFu -aWQgWyV1XSwgbDJkZXZfZmMtPmZsb3djX25ldF9sMmRldl92bGFuZGV2IFsweCV4XQoAAAAAAAAA -AAAAAAAAAG5ldF9sM2luNF9kZXZfY29uZmlnOiBsMmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBh -ZGRyZXNzIGFscmVhZHkgdXNlZCBieSBwb3J0ICVkCgAAAAAAAAAAAAAAAAAAAG5ldF9sM2luNF9k -ZXZfY29uZmlnOiAgYWRkciBbMHgleF0sIG1hc2sgWzB4JXhdLCBndyBbMHgleF0sIHJlZl9jbnQg -WzB4JXhdIGluIHVzZQoAAAAAAAAAAAAAAAAAAHdyaF9jaG5ldF9pZmNvbmY6IGwyZGV2X2ZjLT5m -bG93Y19pZCBbMHgleF0sIGwyZGV2X2ZjLT5mbG93Y190eXBlIFslMHhdLCBpZmNvbmZfd3ItPnN1 -Ym9wIFsweCV4XQoAAAAAAAAAAAAAAAAAAAB3cmhfY2huZXRfaWZjb25mOiBsMmRldl9mYy0+Zmxv -d2NfaWQgWzB4JXhdLCB1bmtub3duIHN1Ym9wIFsweCV4XQoAAAAAAAAAAAAAAAAAAHdyaF9jaG5l -dF9pZmNvbmY6IGwyZGV2X2ZjLT5mbG93Y19pZCBbMHgleF0sIHJjICVkCgAAAAAAAAAAAAAAAABu -ZXRpZl9pcF9jb25mbGljdF90aW1lcl9jYjogbDJkZXZfZmMtPmZsb3djX2lkIFsweCV4XSwgaW5k -ZXZjdHh0LT5zdGF0ZSBbJWRdLCBpbmRldmN0eHQtPnJldHJ5X2NudCBbJWRdCgAAAAAAAAAAbmV0 -aWZfaXBfY29uZmxpY3RfdGltZXJfY2I6IGwyZGV2X2ZjLT5mbG93Y19pZCBbMHgleF0sIGluZGV2 -Y3R4dCBbMHgleF0sIGluIGZyZWUgc3RhdGUKAAAAAAAAAAAAaWZhY2VfY21kX2hhbmRsZXI6IGZj -IFsweCV4XSwgZmMtPmZsb3djX2lkIFsweCV4XSwgZmMtPmZsb3djX3R5cGUgWzB4JXhdLCBwIFsw -eCV4XSwgbGVuMTYgWyV1XSwgbG9jIFsweCV4XQoAAAAAAGlmYWNlX2NtZF9oYW5kbGVyOmwyZGV2 -X2ZjIFsweCV4XSwgbDJkZXZfZmMtPmZsb3djX2lkIFsweCV4XSwgbDJkZXYtPmZsb3djX3R5cGUg -WyV1XSwgbDJkZXZfZmMtPmZsb3djX25ldF9sMmRldl9mbGFncyBbJTB4XQoAAAAAZm9pc2NzaV9p -ZmFjZV9jbWRfaGFuZGxlcjogbDJkZXZfZmMtPmZsb3djX25ldF9sMmRldl9mbGFncyBjaGFuZ2Vk -IGZyb20gWyUweF0gdG8gWyUweF0KAAAAAAAAAAAAY2huZXRfbDJkZXZfdXA6IG1iIFsweCV4XSwg -ZGVmZXJyZWQKAAAAAAAAAAAAAAAAdmlpZCAldSwgbWFjLWlkIFslMDJ4OiUwMng6JTAyeDolMDJ4 -OiUwMng6JTAyeF0gcnNzX3NpemUgJXUKAAAAAHZpIHR5cGUgJXUgZmxvd2Nfc2dlX2VxaWQgJXUg -Zmxvd2Nfc2dlX2VxaWQgJXUgZmxvd2Nfc2dlX2VxY3IgJXUKAAAAAAAAAAAAAAAAAAAAbmV0aWZf -c2V0X21hYzogbWJfc2NyYXRjaCBbMHgleF0KAAAAAAAAAAAAAAAAAAAAbmV0aWZfc2V0X3J4bW9k -ZTogbDJkZXZfZmMtPmZsb3djX25ldF9sMmRldl9tdHUgWyV1XSwgbWJfc2NyYXRjaCBbMHgleF0K -AAAAAAAAAABjaG5ldF9sMmRldl91cDogY21kLT5tYWMgWyV4OiV4OiV4OiV4OiV4OiV4XQoAAABs -MmRldl9tYyBbJXg6JXg6JXg6JXg6JXg6JXhdCgAAAGNobmV0X2wyZGV2X3VwOiBmbG93Y19uZXRf -bDJkZXZfZmxhZ3MgWzB4JXhdCgAAAGNobmV0X2wyZGV2X3VwOiBtYl9sb2MgWzB4JXhdLCBtYl9v -cmlnIFsweCV4XSwgcmMgWyVkXQoAAAAAAAAAAABjaG5ldF9sMmRldl91cF9tYl9jYjogcmMgWyVk -XSwgcG9ydCBbJXVdLCBzdGF0ZSBbJXVdLCBjb29raWUgWyV1XQoAAAAAAAAAAAAAAAAAAGNobmV0 -X3htaXQ6IGwyZGV2X2ZjLT5mbG93Y19pZCBbMHgleF0sIHZsYW5pZCBbJXVdLCBMNENoa0Rpc2Fi -bGVfdG9faVZsYW5UYWcgWzB4JXhdCgAAAAAAAAAAAAAAAGNobmV0X3htaXQ6IHR4X2RsZW4gWyV1 -XQoAAAAAAAAAY2huZXRfeG1pdDogYWxyZWFkeSBzY2hlZHVsZWQKAABjaG5ldF94bWl0OiBsMmRl -dl9mYy0+Zmxvd2NpZCBbMHgleF0sIG5idWYgWzB4JXhdIGluIGRlbGF5ZWRfcHJvY2Vzc2luZwoA -AAAAAAAAAGRoY3BfcHJvY2Vzc19jYjogbDJkZXZfZmMtPmZsb3djX2lkIFsweCV4XSwgZGhjdHh0 -LT5zdGF0ZSBbJTB4XSwgZGhjdHh0LT5ydHJ5X2NudCBbJXVdCgAAAAAAAAAAAGRoY3BfdGltZXJf -Y2I6IERIQ1BESVNDT1ZFUiBzZW50LCBidXQgbm8gcmVwbHkgZnJvbSBhbnkgcG9zc2libGUgc2Vy -dmVyIG9uIHRoZSBuZXR3b3JrLiBSZXRyeWluZyBhZ2FpbgoAAAAAAAAAAABkaGNwX3RpbWVyX2Ni -OiBsMmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBzZW5kaW5nIERIQ1BESVNDT1ZFUiBmb3IgZGhj -dHh0IFsweCV4XSBvbiBwaWQgWyVkXQoAAABkaGNwX3RpbWVyX2NiOiBsMmRldl9mYy0+Zmxvd2Nf -aWQgWzB4JXhdLCBESENQT0ZGRVIgcmVjZWl2ZWQgZm9yIGRoY3R4dCBbJXhdIHBpZCBbJWRdCgAA -AAAAAAAAAABkaGNwX3RpbWVyX2NiOiBsMmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCAgREhDUEFD -SyByZWNlaXZlZCBmb3IgZGhjdHh0IFsleF0sIHBpZCBbJWRdCgAAAAAAAAAAAABkaGNwX3RpbWVy -X2NiOiBsMmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBkaGN0eHQtPmlwYWRkciBbMHgleF0KAAAA -AAAAAAAAAAAAAAAAAGRoY3BfdGltZXJfY2I6IGwyZGV2X2ZjLT5mbG93Y19pZCBbMHgleF0sIG5v -IHJlcGx5IGZyb20gZGhjcCBzZXJ2ZXIsIHRpbWluZyBvdXQKAAAAAAAAAAAAAAAAAAAAAGh3X2Ns -NDVfdXBkX3NwZF9hZHYgJSN4CgAAAAAAAAAAcFsldV0gY2hhbmdpbmcgc3BlZWQgZnJvbSAlI3gg -dG8gJSN4CgAAAAAAAAAAAAAAcFsldV0gY2FsaWJyYXRpbmcgUEhZIFNFUkRFUyBmb3IgbmV3IHNw -ZWVkCgAAAAAAcFsldV0gYXExMjAyIGxpbmsgc3RhdHVzIGNoYW5nZSBVUAoAAAAAAAAAAAAAAAAA -cFsldV0gUEhZIE9WRVJIRUFURUQgLSBmb3JjZWQgcG93ZXIgZG93biAodGVtcD0lZCkKAAAAAAAA -AAAAAAAAAHBbJXVdIGFxMTIwMiBsaW5rIHN0YXR1cyBjaGFuZ2UgRE9XTgoAAAAAAAAAAAAAAG1v -ZHVsZVsldV06IHBvcnQgbW9kdWxlIGluc2VydGVkIGFuZCByZWFkeQoAAAAAAG1vZHVsZVsldV06 -IHBvcnQgbW9kdWxlIHJlbW92ZWQKAAAAAAAAAAAAAAAAAAAAAG1vZHVsZVsldV06IHVua25vd24g -bW9kdWxlIGlkZW50aWZpZXIgMHglMDJ4CgAAAG1vZHVsZVsldV06IGdwaW8gJXUgdHJhbnMgMTBH -IDB4JTAyeCAxRyAweCUwMnggKGxlbmd0aCAldSkgY2FibGUgMHglMDJ4IChsZW5ndGggJXUpIG1v -ZHVsZV90eXBlIDB4JTAyeAoAAAAAAAAAAABjeDRfY3JfcGRvd25bJXVdOiBlbiAldSB2aV9lbl9j -bnQgJXUKAAAAAAAAAAAAAABpbml0X3BvcnRbJXVdOiAgbGluayBzdGF0dXMgMHgleCBtb2RfdHlw -ZSAweCV4IHZpX2VuX2NudCAldSByeF9sb3MgJXUgaHNzX3NpZ2RldCAldSBwb3J0X2NmZy5zaWdk -ZXQgJXUKAAAAAAAAAAAAaW5pdF9wb3J0WyV1XTogIGxpbmsgc3RhdHVzIDB4JXgKAAAAAAAAAAAA -AAAAAAAAaW5pdF9wb3J0WyV1XTogIGxpbmsgc3RhdHVzIDB4JXgKAAAAAAAAAAAAAAAAAAAAaW5p -dF9wb3J0WyV1XTogIGxpbmsgc3RhdHVzIDB4JXgKAAAAAAAAAAAAAAAAAAAAaW5pdF9wb3J0WyV1 -XTogIGxpbmsgc3RhdHVzIDB4JXgKAAAAAAAAAAAAAAAAAAAAaW5pdF9wb3J0WyV1XTogIGxpbmsg -c3RhdHVzIDB4JXgKAAAAAAAAAAAAAAAAAAAAbmV3IG1vZHVsZSBuZXcgc3BlZWQgKHRlY2hfdHlw -ZT0lI3gpCgAAAAAAAAAAAAAAY3JfbW9kdWxlX3N0YXR1c1sldV06IHR5cGUgY2hhbmdlZCBmcm9t -IDB4JTAyeCB0byB0eXBlIDB4JTAyeCBzdHlwZSAweCUwMngKAAAAAABjeDRfY3JbJXVdOiByZXQg -JWQgc3RhdHVzICV1IHhnbV9scyAweCUwOHgKAAAAAAB3YXRjaGRvZyBjbWQgaGFuZGxlciAodGlt -ZSAldSBhY3Rpb24gJXUpCgAAAAAAAABXQVRDSERPRzogQWRhcHRlciBzaHV0ZG93bi4KAAAAAFdB -VENIRE9HOiBCeXBhc3MgdGltZW91dC4KAAAAAAAAV0FUQ0hET0c6IEZMUiAtIG5vdCBpbXBsZW1l -bnRlZCB5ZXQKAAAAAAAAAAAAAAAAV0FUQ0hET0c6IE1vbml0b3JpbmcgdGVtcGVyYXR1cmUuCgAA -AAAAAAAAAAAAAAAAZmlsdGVyOiBwb3JncmFtbWluZyB0aWQgJXUgKGxlIHRjYW0gaW5kZXggJXUp -Li4uCgAAAAAAAAAAAAAAAAAAAGZpbHRlcjogcmVxdWVzdGluZyBjb21wbGV0aW9uLi4uCgAAAAAA -AAAAAAAAAAAAAEZDT0UgRnJlZTogc3RpbGwgeWllbGRlZCB3aGVuIGZyZWVpbmcuLi5mbG93Y19p -ZCAleCBmbG93Y19mbGFncyAleCAKAAAAAAAAAAAAAAAAcG9ydCAlZCBwcmlvciAlZCBzZWxlY3Qg -JWQgcHJvdG9jb2xJRCAweCUwNHgKAAAAcG9ydCAlZCBzZXQgcGZjX2VuID0gMHgleAoAAAAAAABw -b3J0ICVkIHNldCBwZ2lkXzBfNyA9IDB4JTA4eCBwZ19wZXJjZW50YWdlIDB4JTA4eF8lMDh4IG51 -bV90Y3Nfc3VwcG9ydGVkICVkCgAAAHBvcnQgJWQgc2V0IHBmY19lbiA9IDB4JXgKAAAAAAAAcG9y -dCAlZCBzZXQgcGdpZF8wXzcgPSAweCUwOHggcGdfcGVyY2VudGFnZSAweCUwOHhfJTA4eCBudW1f -dGNzX3N1cHBvcnRlZCAlZAoAAABGQ29FIEREUCBmYWlsZWQgOiBveF9pZCAweCV4IHJ4X2lkIDB4 -JXgKAAAAAAAAAABGQ29FIEREUCBmYWlsZWQgOiBEZHBSZXBvcnQgMHgleCBEZHBWYWxpZCAweCV4 -CgBQUkxJIFJzcCB0aW1lZG91dCA6IGZsb3djX2lkIDB4JXggb3hfaWQgMHgleCByeF9pZCAweCV4 -IAoAAAAAAAAAY29yZV9wcm9ncmFtX3RjYjogdGlkICUjeCB0X3N0YXRlICUjeCByY3ZfYWR2IDB4 -JTA4eCByY3Zfc2NhbGUgJSN4IHR4X21heCAlI3ggcmN2X254dCAlI3ggYXRpZCAlI3gKAAAAAAAA -AAAAAAAAAAlvcHQwICUjeCV4IG9wdDIgJSN4IGlwdjYgJSN4IGZsYWdzX3RpbWVyIDB4JTA4eAoA -AAAAAAAAAAAAAAAAAABjYW5ub3QgYWxsb2NhdGUgb2ZmbG9hZGVkIGZpbHRlciBjb25uZWN0aW9u -CgAAAABjYW5ub3QgYWxsb2NhdGUgb2ZmbG9hZGVkIGZpbHRlciBJUHY2IGNvbm5lY3Rpb24KAAAA -AAAAAAAAAAAAAAAAaW52YWxpZCBidWZmZXIgZ3JvdXBbJXVdIGNvbmZpZ3VyYXRpb246IG10dSAl -dSBsd20gJXUgaHdtICV1IGR3bSAldQoAAAAAAAAAAAAAAABwZm4gJXUgdmZuICV1IHdpdGggcG9y -dCBtYXNrIDB4JXggY2Fubm90IGFjY2VzcyBwb3J0ICV1LCByZXQgJWQKAAAAAAAAAAAAAAAAAAAA -AHBmbiAldSB2Zm4gJXUgY291bGQgbm90IGFsbG9jYXRlIHZpaWQsIHJldCAlZAoAAHBmbiAldSB2 -Zm4gJXUgY291bGQgbWFwIHZpaWQgIDB4JXggdG8gZmxvd2MsIHJldCAlZAoAAAAAAAAAAAAAAABw -Zm4gJXUgdmZuICV1IGNvdWxkIG5vdCBhbGxvY2F0ZSB1d2lyZSBmdW5jICVkIG1hYyBhZGRyLCBy -ZXQgJWQKAAAAAAAAAAAAAAAAAAAAAG1paV9hZHZfZmNbJXVdOiByY2FwcyAweCV4CgAAAAAAbWlp -X2FucmVzdGFydFsldV06IGFjYXBzIDB4JXgKAABtaWlfZm9yY2Vfc3BlZWRbJXVdOiByY2FwcyAw -eCV4CgAAAAAAAAAAAAAAAAAAAABtaWlfbGlua19zdGF0dXNbJXVdOiBibXNyIDB4JTA4eCBzdGF0 -dXMgJXUgeGdtX2xzIDB4JTA4eAoAAAAAAAAAcG9ydF9jbWRfaGFuZGxlcjogdW5rbm93biB1LmRj -Yi50eXBlIDB4JXgKAAAAAAAAcG9ydFsldToweCUwMng6MHglMDJ4XTogcGh5IHJlc2V0IG5vdCBh -dmFpbGFibGUKAAAAAAAAAAAAAAAAAAAAAHBvcnRbJXU6MHglMDJ4OjB4JTAyeF06IHVua25vd24g -YWN0aW9uIDB4JXgKAAAAAHBvcnRbJXU6MHglMDJ4OjB4JTAyeF06IHVua25vd24gcmVhZCBhY3Rp -b24gMHgleAoAAAAAAAAAAAAAAAAAAABwa3RzY2hlZCBjaGFubmVsICV1IHNldHMgc3BlZWQgdG8g -JXUga2JwcwoAAAAAAABwb3J0X2NtZF9oYW5kbGVyOiB1bmtub3duIHUuZGNiLnR5cGUgMHgleAoA -AAAAAABpMmMgZXJyb3IgY2F1c2VkIGJ5IG1vZHVsZSB1bnBsdWcKAAAAAAAAAAAAAAAAAABzZW5k -dG8gcGVuZGluZzogd3JfcGVuZCAlcCBmb3IgcG9ydCAldSwgIHdhbnQgdG8gc2VuZCB0byBwb3J0 -ICV1CgAAAAAAAAAAAAAAAAAAAGZjX3BmdmYgJXUsIGxzdGF0dXMgJXUsIGZjX3BvcnQgJXUKAAAA -AAAAAAAAAAAAAHNlbmR0bzpmbG93Y2lkICV1CgAAAAAAAAAAAAAAAAAARkNPRSBGcmVlOiBzdGls -bCB5aWVsZGVkIHdoZW4gZnJlZWluZy4uLmZsb3djX2lkICV4IGZsb3djX2ZsYWdzICV4IAoAAAAA -AAAAAAAAAABGQ09FIEJQIFdSIEVSUjogV1Igd2l0aCBjb29raWUgJXgleCBlcnJvcmVkIGJhY2sg -CgAAAAAAAAAAAAAAAAAAc2NzaV9hYm9ydDogRW50ZXJpbmcgQWJvcnRfdGFzawoAAAAAAAAAAAAA -AAAAAAAAc2NzaV9hYm9ydDo6IHdyLT5pcWlkIFsweCV4XSwgaXN0YXNrX2ZjLT5mbG93Y19zZ2Vf -aXFpZCBbMHgleF0KAHNjc2lfYWJvcnQ6IHNyZXEtPm9wY29kZSBbMHgleF0gZmxhZ3MgWzB4JXhd -CgAAAHNjc2lfYWJvcnQ6IHRhc2tfaWR4IFsldV0sIGl0dCBbMHgleF0KAAAAAAAAAAAAAHNjc2lf -YWJvcnQ6OiBsdW5faWR4IFsweCV4XQoAAAAAc2NzaV9hYm9ydDogcmVmIHRhc2sgbm90IG91dHN0 -YW5kaW5nCgAAAAAAAAAAAAAAc2NzaV9hYm9ydDogcmVmIHRhc2sgZm91bmQgaXR0IFsweCV4XSBj -b29raWUgWzB4JXBdCgAAAAAAAAAAAAAAAGFib3J0L2Nsb3NlIFdSIHdpdGggY29va2llIDB4JWx4 -IHdhcyBpc3N1ZWQgb24gc3NuIDB4JXggaW4gd3Jvbmcgc3RhdGUgMHgleAoAAAAAYWJvcnQgV1Ig -d2l0aCBjb29raWUgMHglbHggb24gc3NuIDB4JXg7ZGlkIG5vdCBmaW5kIFdSIHdpdGggY29va2ll -IDB4JWx4CgAAAAAAAABjbG9zZSBXUiB3aXRoIGNvb2tpZSAweCVseCBvbiBzc24gMHgleDtkaWQg -bm90IGZpbmQgV1Igd2l0aCBjb29raWUgMHglbHgKAAAAAAAAAGFib3J0IFdSIG9uIHNzbiAweCV4 -IHdhcyBpc3N1ZWQgb24geGNoZyAweCV4IHdpdGggcnhfaWQgMHgleCBpbiB3cm9uZyBzdGF0ZSAw -eCV4CgAAAAAAAAAAAAAAAAAAAHhtaXRfaW1tZF9kYXRhOiBjc2tfZmMtPmZsb3djX2lkIFsweCV4 -XSwgY29ubl9mYy0+Zmxvd2NfaWQgWzB4JXhdIGNza19mYy0+Zmxvd2Nfc3RhdGUsIFsweCV4XSwg -Y29ubl9mYy0+Zmxvd2Nfc3RhdGUgWzB4JXhdLCBmbGFncyBbMHgleF0KAAAAAAAAAHhtaXRfaW1t -ZF9kYXRhOiBjb25uX2ZjLT5mbG93Y19pZCBbJWRdIGFscmVhZHkgc2NoZWR1bGVkLCBjb25uX2Zj -LT5mbG93Y19mbGFncwoAbmV0X2wyZGV2X25vdGlmeTogRENCWCBldmVudCBvbiBwb3J0IFslZF0s -IHVscHR4Y2ggWyV1XSwgY2xhc3MgWzB4JXhdLCBwcmlvcml0eSBbMHgleF0KAAAAAAAAAAAAc2Vu -ZCBkY2J4IGluZm86Zmxvd2NpZCAldQoAAAAAAABzZW5kIGRjYnggY29tcGxldGUKAAAAAAAAAAAA -AAAAAHBvcnQgJWQgYXBwbElEIDB4JTA0eCBvdWkgMHglMDZ4IHVzZXJfcHJpb3IgJWQKAGNobmV0 -X2wydF91cGRhdGU6IGwydF91cGRhdGUgcmVxdWVzdCBzZW50IGwydGVudCBbJTA4eF0sIGwydGVu -dC0+aWR4IFslZF0sIGwydGVudC0+dmxhbiBbJWRdCgAAAG5ldGlmX3Byb2Nlc3NfZGhjcDogbDJk -ZXZfZmMtPmZsb3djX2lkIFsweCV4XSwgcHJvY2Vzc2luZywgb3B0X2xlbiAldQoAAAAAAAAAAAAA -Tl9QT1JUIDB4JXgleCV4IHJlamVjdGVkIFBMT0dJIHdpdGggcmVhc29uIGNvZGUgJXgKAAAAAAAA -AAAAAAAAAEFCVFMgd2hpbGUgYXdhaXRpbmcgUFJMSSBSc3A6IGZsb3djX2lkIDB4JXggb3hfaWQg -MHgleCByeF9pZCAweCV4IAoAAAAAAAAAAAAAAAAAQUJUUyBmYWtlIFJzcDogbG9jIDB4JXggb3hf -aWQgMHgleCByeF9pZCAweCV4CgAAY2huZXRfYXJwX3JlY3Y6IHBpZCBbJXVdLCBwa3QtPmFoZHIu -c2lwIFsweCV4XSwgcGt0LT5haGRyLnJpcCBbMHgleF0sIHBrdC0+YWhkci5vcGNvZCBbMHgleF0K -AAAAY2huZXRfYXJwX3JlY3Y6IHZsYW4gZXh0cmFjdGVkLCB2bGFuaWQgWyV1XSwgbDJkZXZfZmMt -PmZsb3djX25ldF9sMmRldl92bGFuZGV2IFsweCV4XSwgbDJkZXZfZmMgWzB4JXhdCgAAAAAAAAAA -AGNobmV0X2FycF9yZWN2OiBpcCBjb25mbGljdCBkZXRlY3RlZAoAAAAAAAAAAAAAAGNobmV0X2Fy -cF9yZWN2OiB2bGFuaWQgWyUweF0sIHBpZCBbJXVdCgAAAAAAAAAAAGNobmV0X2FycF9yZWN2OiBs -MmRldl9mYyBbJXhdLCBwa3QtPmFoZHIucmlwIFsweCV4XSwgcGt0LT5haGRyLnNpcCBbMHgleF0K -AAAAAAAAY2huZXRfaXBfcmVjdjogdmxhbiBleHRyYWN0ZWQsIHZsYW5pZCBbJXVdLCBsMmRldl9m -Yy0+Zmxvd2NfbmV0X2wyZGV2X3ZsYW5kZXYgWzB4JXhdLCBsMmRldl9mYyBbMHgleF0KAAAAAAAA -AAAAAGNobmV0X2lwX3JlY3Y6IGwyZGV2X2ZjLT5mbG93Y19pZCBbMHgleF0sIHBpZCBbMHgleF0s -IGlwIHByb3RvIFsweCV4XQoAAAAAAAAAAAAAYWN0X29wZW5fcnBsOiBhdGlkIFsweCV4XSwgdGlk -IFsweCV4XSwgb3AgWzB4JXhdLCBzdGF0dXMgWzB4JXhdCgAAAAAAAAAAAAAAAAAAAABhY3Rfb3Bl -bl9ycGw6IGNza19mYy0+dGNiX3N0YXRlIFsweCV4XSwgY3NrX2ZjLT5mbGFncyBbMHgleF0sIHRj -Yl9mYy0+Zmxvd2Nfc3RhdGUgWzB4JXhdCgAAAAAAAABzZW5kX2Fib3J0X3JwbDogY3NrX2ZjLT5m -bG93Y190eXBlIFsweCV4XSwgY3NrX2ZjLT5mbG93Y19pZCBbMHgleF0sIGNza19mYy0+Zmxvd2Nf -Y3NvY2tfdGlkIFsweCV4XSwgdWxwdHhjaCBbJXVdLCBpbW1kbGVuIFsldV0sIGJ1ZmZlcmVkIFsl -dV0sIGxlbjE2IFsldV0KAAAAAAAAdGNwX2Fib3J0X3JwbF9yc3M6IHRpZCBbMHgleF0sIHN0YXR1 -cyBbMHgleF0KAAAAdGNwX2Fib3J0X3JlcV9yc3M6IHRpZCBbMHgleF0sIHN0YXR1cyBbMHgleF0K -AAAAdGNiX2ZjLT5mbG93Y19pZCBbMHglMDZ4XSwgdGNiX2ZjLT5mbG93Y190eXBlIFsweCV4XSwg -Y3Bsb3AgWzB4JXhdIAoAAAAAAAAAAAAAAABwa3RzY2hlZF9jbF9ybFsldToldV06IG1vZGUgfCB1 -bml0IHwgcmF0ZSAweCUwNnggbWluICV1IG1heCAldSBwa3RzaXplICV1CgAAAAAAAHBhcmFtX2Rt -YXFbMHgleDoweCV4XTogZG1hcSAweCV4IHJlYWQgJXUgcGYgJXUgcmV0ICVkCgAAAAAAAAAAAABG -TEFTSCBub3QgcmVhZHk6IGkgJXUgbnZyUmVnICUjeAoAAAAAAAAAAAAAAAAAAABBUV9GTEFTSF9S -ZWFkeSAtIFRpbWVvdXQgKDEpCgAAAEFRX0ZMQVNIX1JlYWR5IC0gVGltZW91dCAoMikKAAAACUFR -X1JldHVybkNvbnRyb2xPZkZMQVNICgAAAAAAAABwaHk6IGZhaWxlZCB0byBhbGxvY2F0ZWQgbWVt -b3J5IGZvciBwaHkgZncgZmlsZSwgcmV0ICVkCgAAAAAAAAAAcGh5IGZ3dmVyICUjeCByZXQgJWQK -AAAAAAAAAAAAAABsZSBjb25maWd1cmF0aW9uOiBuZW50cmllcyAldSByb3V0ZSAldSBjbGlwICV1 -IGZpbHRlciAldSBhY3RpdmUgJXUgc2VydmVyICV1IGhhc2ggJXUKAAAAAAAAAAAAAABsZSBjb25m -aWd1cmF0aW9uOiBuZW50cmllcyAldSByb3V0ZSAldSBjbGlwICV1IGZpbHRlciAldSBzZXJ2ZXIg -JXUgYWN0aXZlICV1IGhhc2ggJXUgbnNlcnZlcnNyYW0gJXUKAAAAAAAAAAAAAAAAY2ZfcGFyc2U6 -IGZpbGUgbWVtdHlwZSAweCV4IG1lbWFkZHIgMHgleCBtYXBwZWQgQCAlcDoKAAAAAAAAAAAAAGNv -bmZpZ3VyZWQgd2l0aCBjYXBzIG5ibXxsaW5rIDB4JTA4eCBzd2l0Y2h8bmljIDB4JTA4eCB0b2V8 -cmRtYSAweCUwOHggaXNjc2l8ZmNvZSAweCUwOHgKAAAAAAAAAG5ldCBWSSBhbGxvY2F0aW9uIGZh -aWxlZCBmb3IgZmNfaWQgJXUgd2l0aCBlcnJvciAlZAoAAAAAAAAAAAAAAABuZXQgVkkgbWFjIGFk -ZHJlc3MgcHJvZ3JhbW1pbmcgZmFpbGVkIGZvciBmY19pZCAldSB3aXRoIGVycm9yICVkCgAAAAAA -AAAAAAAAAAAAAG5ldCBWSSByeG1vZGUgcHJvZ3JhbW1pbmcgZmFpbGVkIGZvciBmY19pZCAldSB3 -aXRoIGVycm9yICVkCgAAAABuZXQgVkkgcnNzIGluZGlyZWN0aW9uIHRhYmxlIHByb2dyYW1taW5n -IGZvciBmY19pZCAldSBmYWlsZWQgd2l0aCBlcnJvciAlZAoAAAAAAG5ldCBWSSByc3MgY29uZmln -IGNvbW1hbmQgZmFpbGVkIGZvciBmY19pZCAldSB3aXRoIGVycm9yICVkCgAAAABuZXQgVkkgY29t -bWFuZCBmYWlsZWQgZm9yIGZjX2lkICV1IHdpdGggZXJyb3IgJWQKAAAAAAAAAAAAAAAAAAAAbGUg -aW5pdGlhbGl6YXRpb246IG5lbnRyaWVzICV1IHJvdXRlICV1IGNsaXAgJXUgZmlsdGVyICV1IGFj -dGl2ZSAldSBzZXJ2ZXIgJXUgaGFzaCAldQoAAAAAAAAAAAAAbGUgaW5pdGlhbGl6YXRpb246IG5l -bnRyaWVzICV1IHJvdXRlICV1IGNsaXAgJXUgZmlsdGVyICV1IHNlcnZlciAldSBhY3RpdmUgJXUg -aGFzaCAldSBuc2VydmVyc3JhbSAldQoAAAAAAAAAAAAAAHRwIG1lbSBkaXN0cmlidXRpb25bJSVd -IHBtdHggJXUgcG1yeCAldSBkZHAgJXUgZGRwX2lzY3NpICV1IHN0YWcgJXUgcGJsICV1IHJxICV1 -IHJxdWRwICV1CgAAAAAAAFRQX1BNTV9SWF9QQUdFX1NJWkUgJXUgaXMgbm90IHN1cHBvcnRlZAoA -AAAAAAAAAFRQX1BNTV9UWF9QQUdFX1NJWkUgJXUgaXMgbm90IHN1cHBvcnRlZAoAAAAAAAAAAHBw -bWF4IFsldV0sIGJpdHMgWyV1XSwgRldfSVNDU0lfUEFHRVBPRF9UQUdfSURYX01BWF9TSVpFIFsl -dV0KAABkZWZhdWx0IHRhZ21hc2sgWzB4JTB4XQoAAAAAAAAAAGN4Y25pYy0+ZGRwX2luZm8ubGxp -bWl0IFsweCUweF0sIGN4Y25pYy0+ZGRwX2luZm8udWxpbWl0IFsweCUweF0sIGN4Y25pYy0+ZGRw -X2luZm8uc2l6ZSBbMHglMHhdCgAAAAAAAAAAAAAAAAAAAABjeGNuaWMtPmRkcF9pbmZvLm1heF90 -eHN6IFsweCUweF0gY3hjbmljLT5kZHBfaW5mby5tYXhfcnhzeiBbMHglMHhdIGlvc2l6ZSBbMHgl -MHhdCgAAAAAAAAAAAAAAAABwcG1heCBbJXVdLCBpZHhfYml0cyBbJXVdLCBpZHhfbWFzayBbMHgl -MHhdLCByZXN2ZF90YWdfbWFzayBbMHglMHhdLCB0YWdtYXNrIFsweCUweF0KAAAAAAAAAAAAAAB0 -YWcgaXR0IDB4JTB4LCBiaXRzICV1LCBhZ2UgMHglMHgsIGJpdHMgJXUKAAAAAABjeGNuaWMtPmlz -Y3NpX3BwbSBbMHglMHhdCgAAAAAAAHNjc2lfcGxkX3NpemUgWyV1XSwgQUxJR04oc2NzaV9wbGRf -c2l6ZSwgMTYpIFsldV0KAAAAAAAAAAAAAAAAAABtYXhfcHBvZF96b25lcyBbJXVdCgAAAAAAAAAA -AAAAAGwyZGV2X2ZjLT5mbG93Y19pZCBbJXVdLCBsMmRjLT5wZm4gWyV1XSwgbDJkYy0+dmZuIFsl -dV0sIGwyZGMtPmxwb3J0IFsldV0sIGwyZGV2X2ZjLT5mbG93aWQgWyV1XSBsMmRjLT50eF9jaCBb -JXVdLCBkZXYudnBkLnBvcnR2ZWMgWyV4XQoAAAAAAAAAAHBvcnR2ZWMgWyV1XQoAAABjeGNuaWNf -ZGV2aWNlX2luaXQ6IGRldi5yZXMuZm9pc2NzaV9udGFza3MgWyV1XSwgZGV2LnJlcy5mb2lzY3Np -X25zZXNzIFsldV0sIGRldi5yZXMubmNzb2NrIFsldV0sIGRldi5yZXMuZm9pc2NzaV9uaW5pdCBb -JXVdCgAAAGFycF90YWJsZV9zaXplIFsldV0sIGFycF90YmxfYm1fc2l6ZSBbJXVdLCBuc3RhY2tf -bmwydF9ibV9zaXplIFsldV0sIG9mbGRfc3BvcnRfYm1fc2l6ZSBbJXVdCgAAAGlzY3NpX25zZXNz -X2JtX3NpemUgWyV1XSwgY3NvY2tfYm1fc2l6ZSBbJXVdLCBpc2NzaV9zY3NpX250YXNrc19ibV9z -aXplIFsldV0KAAAAY3hjbmljX2RldmljZV9pbml0OiBjeGNuaWMgWzB4JTB4XSwgY3hjbmljLT5m -aWx0ZXIgWyUweF0sIGN4Y25pYy0+b2ZsZF90Y3Bfc3BvcnRfYm0gWyV4XSBzaXplb2Yoc3RydWN0 -IGZsb3djKSBbJXVdLCB0b3RhbF9pc2NzaV9ibV9zaXplIFsldV0sIHRvdGFsX21lbV9zaXplIFsl -dV0KAAAAAAAAAAAAAAAAAABjeGNuaWNfZGV2aWNlX2luaXQ6IGRldi50cC5udW1fdHhfcGFnZXMg -WyV1XSwgZGV2Lm1jLnNpemUgWyV1XSwgZGV2LnRwLnR4X3BhZ2Vfc3ogWyV1XSAAAAAAAAAAAABw -b3J0X2luaXRbJXVdOiBwb3J0IHR5cGUgMHgleCBpcyBub3Qgc3VwcG9ydGVkCgBFUSBwZm4gJXUg -dmZuICV1OiBkZXN0cm95aW5nIGVxaWQgJXUgd2l0aCBwZW5kaW5nIFdSKHMpIChudW1fYnl0ZXMg -JXUgYW5kIGZsYWdzIDB4JTA4eAoAAAAAAAAAAABBaCBoYS4uLmRvdWJsZSBmcmVlIG94X2lkIDB4 -JXgsIHJ4X2lkIDB4JXgKAAAAAABIb3N0IFBSTEkgUmVzcG9uc2UgdGltZWRvdXQ6IG94X2lkIDB4 -JXggcnhfaWQgMHgleAoAAAAAAAAAAAAAAAAAbDJkZXZfZmMtPmZsb3djX2lkIFsldV0sIGwyZGV2 -X2ZjLT5mbG93Y19uZXRfbDJkZXZfcGZuIFsldV0sIGwyZGV2X2ZjLT5mbG93Y19uZXRfbDJkZXZf -dmZuIFsldV0sIG5ldF9sMmRjLT5scG9ydCBbJXVdCgAAAAAAAAAAAABwZm4gJXUgdmZuICV1IHZp -YSBjb21tYW5kCgAAAAAAAGh3X2xlX2NsaXBfaGFuZGxlcjogcmVtb3ZlZCBwb3M9JXUgKD1pZHgg -JXUpCgAAAGh3X2xlX2NsaXBfaGFuZGxlcjogYWRkaW5nIHRvIHBvcz0ldSAoPWlkeCAldSkKAHBm -biAldSB2Zm4gJXUKAABodyBwZiBiaXRtYXAgMHglMDJ4IHZmaWQgYml0bWFwIDB4JTA4eDoweCUw -OHg6MHglMDh4OjB4JTA4eAoAAAAAYWZ0ZXIgdmZpZCBmaXh1cCwgdmZpZCBiaXRtYXAgMHglMDh4 -OjB4JTA4eDoweCUwOHg6MHglMDh4CgAAAAAAAHRpbWVyIHF1ZXVlICV1IGxvc3QgYSB0aWNrISBu -ZXh0ICVwIGxhc3QgJXAgbnVtZSAldQoAAAAAAAAAAAAAAABmbHJfdGltZXJfc3RhcnQ6IGZsb3dj -X2lkICV1ICVwIGJ1ZiAlcAoAAAAAAAAAAABzZXR0aW5nL3Vuc2V0dGluZyBoc3MgcmVzeW5jIGJp -dAoAAAAAAAAAAAAAAAAAAABNQyBpbml0aWFsaXphdGlvbiBub3QgY29tcGxldGluZywgTUMgY3Vy -cmVudCBpbml0IHN0YXRlIGlzIDB4JTAyeAoAAAAAAAAAAAAAAAAAAHBjaWU6IG5wZiAldSAocGZi -aXRtYXAgMHglMDJ4KSBudmYgJXUgKHBmIDAuLjMgMHglMDJ4IDB4JTAyeCAweCUwMnggMHglMDJ4 -KQoAAAAAZmFpbGVkIHRvIGZpbmQgdGhlICVjJWMgVlBEIHBhcmFtZXRlcgoAAAAAAAAAAAAAZmFp -bGVkIHRvIHBhcnNlIHRoZSAlYyVjIFZQRCBwYXJhbWV0ZXIKAAAAAAAAAAAAY2Y6IGZhaWxlZCB0 -byBhbGxvY2F0ZWQgbWVtb3J5IGZvciBjb25maWd1cmF0aW9uIGZpbGUsIHJldCAlZAoAAGZhaWxl -ZCB0byBzdWNjZXNzZnVsbHkgZmluZCBDaGVsc2lvIFZQRAoAAAAAAAAAAGxvZyBpbml0aWFsaXpl -ZCBAIDB4JTA4eCBzaXplICV1ICgldSBlbnRyaWVzKQoAAHNlbmRfbm9wb3V0OiBjb25uIFsweCV4 -XSwgc2VzcyBbMHgleF0sIGNza19mYyBbMHgleF0KAAAAAAAAAAAAAABzZXNzaW9uX2Jsb2NrOiBz -ZXNzX2ZjLT5mbG93Y19pZCBbMHgleF0sIHNlc3NfZmMtPmZsb3djX3N0YXRlIFsweCV4XSwgY29u -bl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBjb25uX2ZjLT5mbG93Y19zdGF0ZSBbMHgleF0sIGNza19m -Yy0+Zmxvd2NfaWQgWzB4JXhdLCBjc2tfZmMtPmZsb3djX3N0YXRlIFsweCV4XQoAAAAAAAAAAAAA -AAAAAABjc29ja19mcmVlOiBzaXplb2YoY3NrX2ZjLT51LmNzb2NrKSBbJXVdLCBieXRlcwoAAAAA -AAAAAAAAAAAAAAAAY3NvY2tfY2xvc2VkOiBzaXplb2YodGNiX2ZjLT51Lm9mbGQuby5mb2lzY3Np -X2Nvbm4pIFsldV0sIGJ5dGVzCgAAAAAAAAAAAAAAAAAAAABvZmxkX3RjcF9yZWxlYXNlX3RpZDog -Y3NrX2ZjLT5mbG93Y19pZCBbMHgleF0sIHRjYl9mYy0+Zmxvd2NfaWQgWzB4JXhdIGluIGRlbGF5 -X3Byb2Nlc3NpbmcKAAAAAABxdWV1ZV9jc29ja193cjogY3NrX2ZjLT5mbG93Y19pZCBbMHgleF0s -IGNza19mYy0+Zmxvd2NfY3NvY2tfdGlkIFsweCV4XSwgY2JfZnVuYyBbMHgleF0KAAAAAAAAAABv -ZmxkX3RjcF9kb19hY3RpdmVfY2xvc2U6IGNza19mYyBbMHgleF0sIGNza19mYy0+Zmxvd2NfaWQg -WzB4JXhdLCBjc2tfZmMtPnRjYl9zdGF0ZSBbMHgleF0KAAAAAABvZmxkX3RjcF9kb19hY3RpdmVf -Y2xvc2U6IGNza19mYyBbMHgleF0sIGNza19mYy0+Zmxvd2NfaWQgWzB4JXhdLCBjc2tfZmMtPnRj -Yl9zdGF0ZSBbMHgleF0KAAAAAABmb2lzY3NpX2ZyZWVfc2Vzc2lvbjogc2VzcyBbJXVdLCBzZXNz -X2ZjIFsweCUweF0KAAAAAAAAAAAAAAAAAAAAaXNjc2lfZnJlZV9zZXNzaW9uOiBzaXplb2Yoc2Vz -c19mYy0+dS5mb2lzY3NpX3Nlc3Npb24pIFsldV0sIGJ5dGVzCgAAAAAAAAAAAAAAAABzZXNzaW9u -X3JlY292ZXJ5OiBzZXNzLT5mbG93Y19pZCBbMHgleF0sIHNlc3NfZmMtPmZsb3djX3N0YXRlIFsw -eCV4XQoAAAAAAAAAAAAAAGNobmV0X2ZpbmRfbDJ0X2VudHJ5OiBkYWRkciBbJTA4eF0sIFsweCUw -OHhdLCBsb2NhbCBuZXR3b3JrIFslZF0KAAAAAAAAAAAAAAAAAAAAbDJ0ZW50IFslMHhdLCBsMnRl -bnQtPmlkeCBbJWRdCgB0Y3Bfc2VuZF9hb3Blbl9yZXE6IGNza19mYy0+Zmxvd2NfaWQgWzB4JXhd -LCBjc2tfZmMtPmZsb3djX3N0YXRlIFsweCV4XSwgYnVmZmVyZWQgWyV1XSwgcmVzX2NudCBbMHgl -eF0sIHNjaGVkX25vZGUubmV4dCBbMHgleF0KAG9mbGRfdGNwX3NlbmRfYW9wZW5fcmVxOiBjcGxf -cmVxLT5GaWx0ZXIgWzB4JTB4XQoAAAAAAAAAAAAAAAAAAABvZmxkX3RjcF9zZW5kX2FvcGVuX3Jl -cTogY3NrX2ZjLT5mbG93Y19pZCBbMHgleF0sIGluIGRlbGF5X3Byb2Nlc3NpbmcgIHBhdGhfcmVx -X2NudCBbJXVdCgAAAAAAAAByYyBbJWRdLCBjc2tfZmMgWzB4JXhdLCBjc2tfZmMtPmZsb3djX2lk -IFsweCV4XQoAAAAAAAAAAAAAAAAAAAAAY3NvY2tfYWxsb2M6IHR4X2NoIFsweCV4XSwgbHBvcnQg -WzB4JXhdLCBzbWFjX2lkeCBbJXVdLCBtc3NfaWR4IFsldV0gY29va2llIFslMDh4XQoAAAAAAAAA -AAAAAAAAY3NvY2tfYWxsb2M6IGF2YWlsYWJsZSBbJXVdLCBuY3NvY2sgWyV1XSwgcG9zOmF0aWQg -WzB4JXhdLCBjc2tfZmMgWzB4JXhdLCBjc2tfZmMtPmZsb3djX2lkIFsweCV4XSwgc3BvcnQgWyV1 -XQoAAGNoYXBfY2FsY19kaWdlc3RfbWQ1IC0xCgAAAAAAAAAAY2hhcF9jYWxjX2RpZ2VzdF9tZDUg -LTIKAAAAAAAAAABjaGFwX2NhbGNfZGlnZXN0X21kNSAtMwoAAAAAAAAAAGNoYXBfY2FsY19kaWdl -c3RfbWQ1IC00CgAAAAAAAAAAY2hhcF9jYWxjX2RpZ2VzdF9tZDUgLTUKAAAAAAAAAABjaGFwX2Nh -bGNfZGlnZXN0X21kNSAtNgoAAAAAAAAAAGZvaXNjc2lfcGVlcl9pbml0OiBjb25uX2F0dHItPmhk -aWdlc3RfdG9fZGRwX3Bnc3ogWzB4JXhdCgAAAAAAAABmb2lzY3NpX3BlZXJfaW5pdDogY29ubl9m -Yy0+Zmxvd2NfZm9pc2NzaV9jb25uX2RpZ2VzdF90b191bHAgWzB4JXhdCgAAAAAAAAAAAAAAAGZv -aXNjc2lfcGVlcl9pbml0IGNvbm4gMHgleAoAAAAAd3JoX2ZvaXNjc2lfbm9kZTogbm9kZV93ci0+ -Zmxvd2lkX2xlbjE2IFsleF0KAAAAZm9pc2NzaV9pbm9kZV9tb2Q6IG5vZGVfZmMgWzB4JXhdLCBu -b2RlX2ZjLT5mbG93Y19pZCBbJXVdIG5vZGVfd3ItPm5vZGVpZAoAAAAAAABmb2lzY3NpX2lub2Rl -X2ZyZWU6IG5vZGVfZmMgWzB4JXhdLCBub2RlX2ZjLT5mbG93Y19pZCBbJXVdLCBub2RlX2ZjLT5u -b2RlaWQgWyVkXQoAAAAAAAAAAAAAAAAAAABpbm9kZV9hbGxvYzogbm9kZV93ci0+bm9kZWlkIFsw -eCV4XQoAAAAAAAAAAAAAAABmb2lzY3NpX2lub2RlX2FsbG9jOiBub2RlX2ZjIFsweCV4XSwgbm9k -ZV9mYy0+Zmxvd2NfaWQgWyV1XSBub2RlX2ZjLT5mbG93Y19mb2lzY3NpX2lub2RlX2lkIFslZF0K -AAAAAAAAAAAAAAAAAAAAZm9pc2NzaV9hbGxvY19zZXNzaW9uOiBmbG93aWQgMHgleCwgc2Vzcy5t -YXhfY29ubiAlZCwgc2Vzcy5tYXhfcjJ0ICVkLCBzZXNzLm1heF9idXJzdCAlZCwgc2Vzcy5maXJz -dF9idXJzdCAlZAoAAHdyaF9mb2lzY3NpX2NydGw6Y3RybF93ci0+Y3RybF9pZCAldQoAAAAAAAAA -AAAAAG9mbGRfdGNwX2Rpc2Nvbm5lY3Q6IHRjYl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBjc2tfZmMt -PmZsb3djX2lkIFsweCV4XSwgY3NrLT50Y2Jfc3RhdGUgWzB4JXhdCgAAAGZvaXNjc2lfdmFsaWRh -dGVfbG9naW5fc3RhZ2U6IC0gMQoAAAAAAAAAAAAAAAAAAGRyb3BfYWxsX3Rhc2s6IHJlcXVlc3Rl -ZCBsaWR4IFsldV0KAAAAAAAAAAAAAAAAAGdldF9yZWZfdGFzazogaXN0YXNrLT5mbG93Y19pZCBb -MHgleF0sIGlzdGFza19mYy0+Zmxvd2Nfc3RhdGUgWyV1XSwgaXN0YXNrX2ZjLT5mbG93Y19mb2lz -Y3NpX3Rhc2tfbGlkeCBbJXVdLCBsaWR4IFsldV0sIGlzdGN0eC0+cjJ0cCBbMHgleF0KAAAAAHJl -Y3Zfbm9waW46IGNvbm4gWzB4JXhdLCBzZXNzIFsweCV4XSwgY3NrX2ZjIFsweCV4XQoAAAAAAAAA -AAAAAABuZXRfbDJkZXZfZmluZF9ieV9hZGRyOiBsMmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBs -MmRjLT5scG9ydCBbJXVdLCBsMmRfZmMtPmZsb3djX2lkIFsweCV4XSwgbDJkYy0+aW40X2Rldi5p -bl9hZGRyLmFkZHIgWzB4JXhdLCBhZGRyIFsweCV4XQoAAABuZXRfbDJkZXZfbXR1X2NvbmZpZzog -bDJkZXZfZmMtPmZsb3djX2lkIFsweCV4XSwgbXR1ICV1CgAAAAAAAAAAc2Vzc2lvbl91bmJsb2Nr -OiBzZXNzX2ZjLT5mbG93Y19pZCBbMHgleF0sIHNlc3NfZmMtPmZsb3djX3N0YXRlIFsweCV4XSwg -Y29ubl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBjb25uX2ZjLT5mbG93Y19zdGF0ZSBbMHgleF0sIGNz -a19mYy0+Zmxvd2NfaWQgWzB4JXhdLCBjc2tfZmMtPmZsb3djX3N0YXRlIFsweCV4XQoAAAAAAAAA -AAAAAAAAc2Vzc2lvbl9saW5rX25vdGlmeTogcG9ydCBbMHgleF0gbGluayBkb3duIHBpbmcgcmVj -b3ZlcnkgZGlzYWJsZWQsIHRyeWluZyB0byByZWNvdmVyIHNlc3Npb24gWzB4JXhdIGNvbm4gWzB4 -JXhdCgAAAAAAAAAAAAAAAAAAAABzZXNzaW9uX2xpbmtfbm90aWZ5OiBwb3J0IFsweCV4XSBsaW5r -IHVwIHNlc3Npb24gWzB4JXhdIGNvbm4gWzB4JXhdCgAAAAAAAAAAAAAAAGNobmV0X3ZpX2VuYWJs -ZTogdmlpZCBbJWRdLCB2aV9mYy0+Zmxvd2NfdmlfZmxhZ3MgWzB4JXhdCgAAAAAAAABodyByZWdp -c3RlciBvcGVyYXRpb24gbm90IGNvbXBsZXRpbmcsIHJlZyAweCUwOHggbWFzayAweCUwOHggdmFs -dWUgMHglMDh4CgAAAAAAAE1ESU8gQ0w0NTogZmFpbGVkIHRvIHNldCB1cCBNTUQgYWRkcgoAAAAA -AAAAAAAAAE1ESU86IGZhaWxlZCB0byByZWFkCgAAAAAAAAAAAAAATURJTyBDTDQ1OiBmYWlsZWQg -dG8gc2V0IHVwIE1NRCBhZGRyCgAAAAAAAAAAAAAATURJTzogZmFpbGVkIHRvIHdyaXRlCgAAAAAA -AAAAAABod19pMmNfdHJhbnNhY3Rpb246IG5kYXRhICV1IGRhdGFbMF0gMHgleCBkYXRhWzFdIDB4 -JXggZGlmZiAldQoAaHdfaTJjX3RyYW5zYWN0aW9uOiBuZGF0YSAldSBkYXRhWzBdIDB4JXggZGF0 -YVsxXSAweCV4IGRpZmYgJXUgZHBvcyAldSBjb250ICV1IGZhaWxlZCB3aXRoIGVyciAlZAoAAAAA -AAAAAAAAAAAAAGkyYyB0cmFuc2FjdGlvbiBmYWlsZWQgdG8gY29tcGxldGUKAAAAAAAAAAAAAAAA -AGh3X3hnbV9sZWRfbGlua191cCBsZWQwIGNvbmZpZzogJXUKAAAAAAAAAAAAAAAAAGh3X3hnbV9s -ZWRfbGlua191cCBsZWQxIGNvbmZpZzogJXUKAAAAAAAAAAAAAAAAAGhzc19zaWdkZXRbJXVdOiBo -c3Nfc2lnZGV0IGNoYW5nZWQgdG8gMHgleAoAAAAAAGNyX21vZHVsZV9yeF9sb3NbJXVdOiByeF9s -b3MgY2hhbmdlZCB0byAldQoAAAAAAFdBVENIRE9HOiBBY3RpdmF0aW5nCgAAAAAAAAAAAAAAV0FU -Q0hET0cgLSBFbmFibGUgYWN0aW9uICV1IHRpbWUgJXUKAAAAAAAAAAAAAAAAV0FUQ0hET0cgLSBE -aXNhYmxlIGFjdGlvbiAldQoAAABXQVRDSERPRzogRGUtYWN0aXZhdGluZwoAAAAAAAAAAGh3X3hn -bV9wb3dlcnVwIHBvcnQgJXUgZW4gJXUKAAAAaHdfeGdtX3Bvd2VydXAgb25seSBwb3J0IChwICV1 -IGVuICV1KQoAAAAAAAAAAAAARkNvRSBGQ0IgbGlua2Rvd246IGlvX3JlcSAweCV4JXggaXFpZCAw -eCV4IGZsb3dpZCAweCV4IG9wIDB4JXgKAGZjb2Ugbm90aWZ5IDogVXBkYXRlIG5ldyBEQ0JYIHZh -bHVlcyBWSSBzdGF0ZSAweCV4IHByaSAweCV4IHNjaGVkY2wgMHgleCBkY2J4X2RvbmUgMHgleAoA -AAAAAAAAAGZjb2Ugbm90aWZ5IDogRkNGIGZsb3dpZCAweCV4LCB1bHBjaCAweCV4IAoAAAAAAGZj -b2Ugbm90aWZ5IDogRENCWCA6IHBvcnQgMHgleCwgcHJpb3JpdHkgMHgleCB1bHB0eGNoIDB4JXgg -Y2xhc3MgMHgleAoAAAAAAAAAAAAARkNvRSBGQ0YgdGltZXI6IGZsb3djIHN0YXRlIDB4JXgsIHBv -cnQgMHgleCAsZmNmIDB4JXgsIGZsb3djX2lkIDB4JXgKAAAAAAAAAAAAAABvZmxkX2Nvbm5lY3Rp -b25fd3I6IGNvbm5lY3Rpb24gd2l0aCA1LXR1cGxlIGxwIDB4JTA0eCBmcCAweCUwNHggbGlwIDB4 -JTA4eCUwOHggcGlwIDB4JTA4eCUwOHggZmlsdGVyIDB4JTA4eCBleGlzdHMgQCBMRSBpbmRleCAl -dQoAAAAAAAAAAAAAAAAAAABvZmxkX2Nvbm5lY3Rpb25fd3I6IGNvbm5lY3Rpb24gd2l0aCA1LXR1 -cGxlIGxwIDB4JTA0eCBmcCAweCUwNHggbGlwIDB4JTA4eCBwaXAgMHglMDh4IGZpbHRlciAweCUw -OHggZXhpc3RzIEAgTEUgaW5kZXggJXUKAAAAAAAAAG9mbGRfY29ubmVjdGlvbl93cjogY29ubmVj -dGlvbiB3aXRoIDUtdHVwbGUgbHAgMHglMDR4IGZwIDB4JTA0eCBsaXAgMHglMDh4JTA4eCBwaXAg -MHglMDh4JTA4eCBmaWx0ZXIgMHglMDh4CgAAAABvZmxkX2Nvbm5lY3Rpb25fd3I6IGNvbm5lY3Rp -b24gd2l0aCA1LXR1cGxlIGxwIDB4JTA0eCBmcCAweCUwNHggbGlwIDB4JTA4eCBwaXAgMHglMDh4 -IGZpbHRlciAweCUwOHgKAAAAAAAAAAAAAAAASVFGTElOVCBwZm4gJXUgdmZuICV1OiBpcWVzaXpl -ICV1IHRvbyBzbWFsbAoAAAAASVFGTElOVCBwZm4gJXUgdmZuICV1OiBpcWlkICV1IHRvbyBsYXJn -ZSAobWF4ICV1KQoAAAAAAAAAAAAAAAAAAElRRkxJTlQgcGZuICV1IHZmbiAldTogaXFpZCAldSBu -b3QgYWxsb2NhdGVkCgAAAElRRkxJTlQgcGZuICV1IHZmbiAldTogZmwwaWQgJXUgdG9vIGxhcmdl -IChtYXggJXUpCgAAAAAAAAAAAAAAAABJUUZMSU5UIHBmbiAldSB2Zm4gJXU6IGZsMGlkICV1IG5v -dCBhbGxvY2F0ZWQKAABJUUZMSU5UIHBmbiAldSB2Zm4gJXU6IGZsMWlkICV1IHRvbyBsYXJnZSAo -bWF4ICV1KQoAAAAAAAAAAAAAAAAASVFGTElOVCBwZm4gJXUgdmZuICV1OiBmbDFpZCAldSBub3Qg -YWxsb2NhdGVkCgAASVFGTElOVCBwZm4gJXUgdmZuICV1OiBmbDFpZCAldSBpcyB2YWxpZCBidXQg -bm90IGZsMGlkICV1CgAAAAAAAElRRkxJTlQgcGZuICV1IHZmbiAldTogZmwxaWQgJXUgaXMgdmFs -aWQgYnV0IGhlYWRlciBzcGxpdCBmZWF0dXJlIGlzIG5vdCBlbmFibGVkCgAAAAAAAAAAAAAAAAAA -AElRIHBmbiAldSB2Zm4gJXU6IGlxaWQgJXUgdG9vIGxhcmdlIChtYXggJXUpCgAAAElRIHBmbiAl -dSB2Zm4gJXU6IGlxaWQgJXUgbm90IGFsbG9jYXRlZAoAAAAAAAAAAElRIHBmbiAldSB2Zm4gJXU6 -IGZsMGlkICV1IGZsMWlkICV1IGJ1dCBub3Qgc3VwcG9ydGVkCgAAAAAAAAAAAABFUSBwZm4gJXUg -dmZuICV1OiBjcmVhdGluZyBFVEggZXFpZCAldSB3aXRoIHBlbmRpbmcgV1IocykgKG51bV9ieXRl -cyAldSBhbmQgZmxhZ3MgMHglMDh4CgAAAAAAAABFUSBwZm4gJXUgdmZuICV1OiBjcmVhdGluZyBD -VFJMIGVxaWQgJXUgd2l0aCBwZW5kaW5nIFdSKHMpIChudW1fYnl0ZXMgJXUgYW5kIGZsYWdzIDB4 -JTA4eAoAAAAAAABFUSBwZm4gJXUgdmZuICV1OiBlcWlkICV1IHRvbyBsYXJnZSAobWF4ICV1KQoA -AABFUSBwZm4gJXUgdmZuICV1OiBlcWlkICV1IG5vdCBhbGxvY2F0ZWQKAAAAAAAAAABwb3J0X2Js -aW5rX2xlZF9yZXN0b3JlCgAAAAAAAAAAAHBvcnRfYmxpbms6IGJsaW5rZHVyPTB4JXggYmxpbmtf -cmVmY250CgAAAAAAAAAAAHBvcnRfYmxpbms6IAlibGlua19yZWZjbnQ9MHgleAoAcG9ydF9ibGlu -azogCWJsaW5rX3JlZmNudD0weCV4CgBtaWlfYWR2X3NwZWVkWyV1XTogcmNhcHMgMHgleAoAAG1p -aV9pbml0WyV1XTogYWNhcHMgMHgleAoAAAAAAAAAbWlpX3Bkb3duWyV1XTogcG93ZXJkb3duIGVu -ICV1CgBwb3J0WyV1XTogZ2F2ZSB1cCBmaXhpbmcgZXJyb3JzISEhCgAAAAAAAAAAAAAAAABwb3J0 -WyV1OjB4JTAyeDoweCUwMnhdOiBsMWNmZywgcGNhcHMgMHgleCBhY2FwcyAweCV4IHJjYXBzIDB4 -JXgKAAAAAAAAAAAAAAAAAAAAAHBvcnRbJXU6MHglMDJ4OjB4JTAyeF06IGwxY2ZnLCBpbnZhbGlk -IHJlcXVlc3QsIHBjYXBzIDB4JXggYWNhcHMgMHgleCByY2FwcyAweCV4CgAAAAAAAAAAAAAAAAAA -AHBvcnRbJXU6MHglMDJ4OjB4JTAyeF06IGwxY2ZnLCBtZGkgbi9hIHBjYXBzIDB4JXggYWNhcHMg -MHgleCByY2FwcyAweCV4CgAAAAAAAAAAcG9ydFsldToweCUwMng6MHglMDJ4XTogbDFjZmcsIGNh -bm5vdCBmb3JjZSBtdWx0aXBsZSBzcGVlZHMsIHBjYXBzIDB4JXggYWNhcHMgMHgleCByY2FwcyAw -eCV4CgAAUVNGUCBtb2R1bGUgdW5wbHVnIC0gcmVpbml0aWFsaXppbmcgcnhfbG9zICB0byAweGZm -CgAAAAAAAAAAAAAAAGdwaW9fcXNmcF9tb2R1bGVfdXBkYXRlOiBjaGFuZ2VkIHJ4X2xvcyBmcm9t -IDB4JXggdG8gMHgleAoAAAAAAABncGlvX3FzZnBfbW9kdWxlX3VwZGF0ZTogY2hhbmdlZCB0eF9k -aXMgZnJvbSAweCV4IHRvIDB4JXgKAAAAAAAAZ2V0X3JlZl90YXNrOiByZXF1ZXN0ZWQgY29va2ll -OiBoaWdoIFsweCUwOHhdLCBsb3cgWzB4JTA4eF0KAAAAAGdldF9yZWZfdGFzazogdGFzayBjb29r -aWU6IGhpZ2ggWzB4JTA4eF0sIGxvdyBbMHglMDh4XQoAAAAAAAAAAABnZXRfcmVmX3Rhc2s6IGlz -dGFzay0+Zmxvd2NfaWQgWzB4JXhdLCBpc3Rhc2tfZmMtPmZsb3djX3N0YXRlIFsldV0sIGlzdGN0 -eC0+cjJ0cCBbMHgleF0KAAAAAAAAAABnZXRfcmVmX3Rhc2s6IHRhc2sgbm90IGZvciBjb29raWUg -JWx4CgAAAAAAAAAAAABGQyBYQ0hHIEZJTkQ6IE5vIFhDSEcgYWxsb2NhdGVkIGZvciBXUiB3aXRo -IGNvb2tpZSAleCAleCAKAAAAAAAAd3JoX2lzY3NpX3Njc2lfcmVhZDogaXN0YXNrX2ZjLT5mbG93 -Y19pZCBbJXVdIGFscmVhZHkgc2NoZWR1bGVkCgAAAAAAAAAAAAAAAAAAAAB3cmhfaXNjc2lfc2Nz -aV9yZWFkOiBpc3Rhc2tfZmMtPmZsb3djX2lkIFsldV0gYWxyZWFkeSBzY2hlZHVsZWQKAAAAAAAA -AAAAAAAAAAAAAGNobmV0X2wydF91cGRhdGU6IGwyZGV2X2ZjIFsweCV4XSwgbDJkZXZfZmMtPmZs -b3djX2lkIFsldV0gbDJkZXZfZmMtPmZsb3djX2ZsYWdzIFsweCV4XQoAAAAAAAAAAGNobmV0X2wy -dF91cGRhdGU6IGwyZGV2X2ZjLT5mbG93Y19pZCBbJXVdIGFscmVhZHkgc2NoZWR1bGVkCgAAAABj -aG5ldF9sMnRfdXBkYXRlOiBpbiBkZWxheWVkX3Byb2Nlc3NpbmcsIGwydGVudCBbJTA4eF0KAAAA -AAAAAAAAbmV0aWZfcHJvY2Vzc19kaGNwX29wdHM6IGwyZGV2X2ZjLT5mbG93Y19pZCBbMHgleF0s -IE1TR19UWVBFIFslZF0sIGRoY3R4dC0+c3RhdGUgWyVkXQoAAAAAAAAAAAAAY2huZXRfZGhjcF9y -ZWN2OiB2bGFuaWQgWyV1XSwgbDJkZXZfcGlkX2ZjLT5mbG93Y19uZXRfbDJkZXZfdmxhbmRldiBb -MHgleF0sIGwyZGV2X2ZjIFsweCV4XQoAAAAAY2huZXRfZGhjcF9yZWN2OiBsMmRldl9mYy0+Zmxv -d2NfaWQgWzB4JXhdLCBkaGN0eHQtPnN0YXRlIFslZF0sIG1hbGFjaW91cyBkaGNwIHJlY3YgZm9y -IG5vIHJlcXVlc3QKAAAAAAAAAAAAAAAAAGRoY3R4dC0+c3RhdGUgOiAlZAAAAAAAAAAAAAAAAAAA -bDJkZXZfZmMtPmZsb3djX2lkIFsweCV4XSwgQmFkIERIQ1AgY29va2llIHJlY2lldmVkLCBhYm9y -dGluZwoAAGljbXBfcmVjdjogbDJkZXZfZmMtPmZsb3djX2lkIFsweCV4XSwgcGlkIFsweCV4XSwg -aWNtcCB0eXBlIFsweCV4XQoAAAAAAAAAAAAAAAAAQUJUUyBBQ0MgYXdhaXRpbmcgUFJMSSBSc3A6 -IGZsb3djX2lkIDB4JXggb3hfaWQgMHgleCByeF9pZCAweCV4IGlxaWQgMHgleAoAAAAAAABjc29j -a19wZWVyX2Nsb3NlOiBjc2tfZmMtPmZsb3djX2lkIFsweCV4XSwgY3NrX2ZjLT50Y2JfZmMtPmZs -b3djX2lkIFsweCV4XSwgY3NrX2ZjLT5mbG93Y19zdGF0ZSBbMHgleF0sIGNza19mYy0+Zmxvd2Nf -Y3NvY2tfdGNiX2ZjLT5mbG93Y19zdGF0ZSBbMHgleF0KAAAAAAAAAAAAY3NvY2tfcGVlcl9jbG9z -ZTogY3NrX2ZjLT5mbG93Y19pZCBbMHgleF0sIGNza19mYy0+Zmxvd2Nfc3RhdGUgIFsweCV4XQoA -AAAAAAAAAAB3cmhfb2ZsZF90Y3BfY2xvc2VfY29uX3JlcGx5OiB0Y2JfZmMtPmZsb3djX2lkIFsw -eCV4XSwgdGNiX2ZjLT5mbG93Y190eXBlIFsweCV4XSwgbGVuMTYgWyV1XSwgbG9jIFsldV0KAAAA -AAAAAAAAd3JoX29mbGRfdGNwX2Nsb3NlX2Nvbl9yZXBseTogcnBsLT5vcF9UaWQgWzB4JXhdLCBy -cGw+c3RhdHVzIFsweCV4XSwgcnBsLT5zbmRfbnh0IFsweCV4XSwgcnBsLT5yY3Zfbnh0IFsweCV4 -XQoAAHBrdHNjaGVkX2NoX3JsWyV1XTogd2VpZ2h0ICV1JQoAcGt0c2NoZWRfY2hfcmxbJXVdOiBy -YXRlICV1IG1heCAldQoAAAAAAAAAAAAAAAAAcGt0c2NoZWRfY2xfd3JyWyV1OiV1XTogd2VpZ2h0 -ICV1IHdlaWdodGVkX21hc2sgMHgleAoAAAAAAAAAAAAAAGVxX3BhcmFtc1sweCV4OjB4JXhdOiBk -bWFxIDB4JXggcmVhZCAldSBwZiAldSBlcWlkX2FwaSAldSByZXQgJWQKAAAAAAAAAAAAAAAAAAAA -CUFRX1Rha2VDb250cm9sT2ZGTEFTSDogMWUuYzAwMT0lI3ggMWUuYzQ1MD0lI3ggMWUuYzQ1MT0l -I3ggMWUuMTAwPSUjeAoAAAAAAAAAAABBUV9BUElfV3JpdGVBbmRWZXJpZnlGbGFzaEltYWdlIC0g -SW1hZ2UgaW50ZWdyaXR5IGNoZWNrIGZhaWxlZCAoY2FsYyAlI3ggdmFsICUjeCkKAAAAAAAAAAAA -AAAAAABBUV9BUElfV3JpdGVBbmRWZXJpZnlGbGFzaEltYWdlIC0gSW1hZ2UgaW50ZWdyaXR5IGNo -ZWNrIHBhc3NlZAoAQVFfQVBJX1dyaXRlQW5kVmVyaWZ5Rmxhc2hJbWFnZSAtIFRpbWVvdXQgd2Fp -dGluZyBmb3IgZmxhc2ggaW50ZXJmYWNlICgldSkKAAAAAABBUV9BUElfV3JpdGVBbmRWZXJpZnlG -bGFzaEltYWdlIC0gVGltZW91dCB3YWl0aW5nIGZvciBmbGFzaCBpbnRlcmZhY2UgKCV1KQoAAAAA -AEFRX0FQSV9Xcml0ZUFuZFZlcmlmeUZsYXNoSW1hZ2UgLSBUaW1lb3V0IHdhaXRpbmcgZm9yIGZs -YXNoIGludGVyZmFjZSAoJXUpCgAAAAAAQVFfQVBJX1dyaXRlQW5kVmVyaWZ5Rmxhc2hJbWFnZSAt -IFRpbWVvdXQgd2FpdGluZyBmb3IgZmxhc2ggaW50ZXJmYWNlICgldSkgKHBwICUjeCBhcCAlI3gp -CgAAAAAAQVFfQVBJX1dyaXRlQW5kVmVyaWZ5Rmxhc2hJbWFnZSAtIFRpbWVvdXQgd2FpdGluZyBm -b3IgZmxhc2ggaW50ZXJmYWNlICgldSkKAAAAAABBUV9BUElfV3JpdGVBbmRWZXJpZnlGbGFzaElt -YWdlIC0gVGltZW91dCB3YWl0aW5nIGZvciBmbGFzaCBpbnRlcmZhY2UgKCV1KQoAAAAAAEFRX0FQ -SV9Xcml0ZUFuZFZlcmlmeUZsYXNoSW1hZ2UgLSBFcnJvciBvbiBidXJuaW5nIEZMQVNIIChjcmMx -NiBtaXNtYXRjaCkKAAAAAAAAbWFsbG9jX2RlY1sldV06IHN0YXJ0ICVwIGVuZCAlcCBuZXh0ICVw -IHNpemUgMHgleCBhbGlnbWVudCAweCV4IHAgJXAKAAAAAAAAAAAAAABtYWxsb2NfaW5jWyV1XTog -c3RhcnQgJXAgZW5kICVwIG5leHQgJXAgc2l6ZSAweCV4IGFsaWdtZW50IDB4JXggcCAlcAoAAAAA -AAAAAAAAAGxlIGNvbmZpZ3VyYXRpb246IGhhc2ggbW9kZSByZXF1aXJlcyBhdCBsZWFzdCAxNiBl -bnRyaWVzLCBuaGFzaCAldQoAAAAAAAAAAAAAAAAAbGUgY29uZmlndXJhdGlvbjogaGFzaCBtb2Rl -IHJlcXVpcmVzIGF0IGVudHJpZXMgdG8gYmUgYSBwb3dlciBvZiAyLCBuaGFzaCAldQoAAABsZSBj -b25maWd1cmF0aW9uOiByZXF1ZXN0ZWQgJXUgdGNhbSBlbnRyaWVzIGJ1dCBvbmx5ICV1IGF2YWls -YWJsZQoAAAAAAAAAAAAAAAAAAGxlIGNvbmZpZ3VyYXRpb246IHRjYW0gcmVnaW9ucyBtdXN0IGhh -dmUgbXVsdGlwbGUgb2YgMzIgZW50cmllcywgbnJvdXRlICV1IG5jbGlwICV1IG5maWx0ZXIgJXUg -bnNlcnZlciAldQoAAAAAAABvZmxkIHRwIHRpbWVyIHNldHRpbmdzIFRQX01TTCAweCUwOHggVFBf -UlhUX01JTiAweCUwOHggVFBfUlhUX01BWCAweCUwOHggVFBfUEVSU19NSU4gMHglMDh4IFRQX1BF -UlNfTUFYIDB4JTA4eAoAICAgICAgICAgICAgICAgICAgICAgICBUUF9LRUVQX0lETEUgMHglMDh4 -IFRQX0tFRVBfSU5UVkwgMHglMDh4IFRQX0lOSVRfU1JUVC5pbml0X3NydHRfbWF4cnR0IDB4JTA0 -eCBUUF9JTklUX1NSVFQuaW5pdF9zcnR0X2luaXRzcnR0IDB4JTA0eCBUUF9GSU5XQUlUMl9USU1F -UiAweCUwOHgKAAAAAAAAAAAAAABjb25maWd1cmF0aW9uIGZpbGUgcGFyc2VyIGVuY291bnRlcmVk -IGVycm9yIEAgbGluZSAldToKAAAAAAAAAAAAaHdfaTJjX3cgcG9ydCAldSBkZXYgJXggcmVnICV1 -IGRhdGEgMHgleAoAAAAAAAAASE9TVCBQQUdFX1NJWkUgWzB4JTBseF0gdG9vIHNtYWxsLCBtaW4g -WzB4JTBseF0gcmVxdWlyZWQKAAAAAAAAAHBhZ2Ugc2l6ZSBbJWx1XSBtaXNtYXRjaAoAAAAAAAAA -UEFHRSBzaXplICVsdSB1bnN1cHBvcnRlZCwgZGRwIGRpc2FibGVkCgAAAAAAAAAASG9zdCBwYWdl -X3NpemUgJWx1LCBkZHBfaWR4ICV1CgBGQ29FIEREUCBpbml0OiBmY29lIGxsaW1pdCAweCV4LCBm -Y29lIHVsaW1pdCAweCV4IGdibCBsbGltaXQgMHgleCBnYmwgdWxpbWl0IDB4JXgKAAAAAAAAAAAA -AAAAAABGQ29FIEREUCBpbml0OiBmY29lIHBwb2Qgb2ZmIDB4JXgsIGZjb2Ugc3QgcHBvZCBhZGRy -IDB4JXggZmNvZSBudW0gcHBvZHMgMHgleAoAAGZjb2UgeGNoZyBtZ3IgaW5pdDogTnVtYmVyIG9m -IGV4Y2hhbmdlcyBmb3IgRkNvRSBpcyAleAoAAAAAAAAAAABDYWxjdWxhdGlvbiBvdXQgb2YgYm91 -bmRzIGZ1cmluZyBpbml0OiAlI3ggJSN4ICUjeAoAAAAAAAAAAAAAAAAAcGZuICV1IHZmbiAldSBo -YXMgcG5kdHhucyAldSBhZnRlciAxMDBtcwoAAAAAAAAAYmFkIG1haWxib3ggY21kOiBwZm4gMHgl -eCB2Zm4gMHgleDsgb3Bjb2RlIDB4JXggPiBMQVNUQzJFIDB4JXgKAG1haWxib3ggY21kIG5vdCB5 -ZXQgc3VwcG9ydGVkOiBwZm4gMHgleCB2Zm4gMHgleDsgb3Bjb2RlIDB4JXgKAABiYWQgbWFpbGJv -eCBjbWQ6IHBmbiAweCV4IHZmbiAweCV4OyBvcGNvZGUgMHgleCBpcyB2YWxpZCBwb3N0IGRldmlj -ZSBpbml0IG9ubHkKAGJhZCBtYWlsYm94IGNtZDogcGZuIDB4JXggdmZuIDB4JXg7IHJhbWFzayAw -eCV4IGNtZCByYW1hc2sgMHgleAoAAAAAAAAAAAAAAAAAAAAAYmFkIG1haWxib3ggY21kOiBwZm4g -MHgleCB2Zm4gMHgleDsgbGVuMTYgMHgleCB2ZXJzdXMgZXhwZWN0ZWQgbGVuMTYgMHgleAoAAAAA -AABpbnN1ZmZpY2llbnQgY2FwcyB0byBwcm9jZXNzIG1haWxib3ggY21kOiBwZm4gMHgleCB2Zm4g -MHgleDsgcl9jYXBzIDB4JXggd3hfY2FwcyAweCV4IHJlcXVpcmVkIHJfY2FwcyAweCV4IHdfY2Fw -cyAweCV4CgAAAAAAAAAAAGluc3VmZmljaWVudCBjYXBzIHRvIHByb2Nlc3MgbWFpbGJveCBjbWQ6 -IHBmbiAweCV4IHZmbiAweCV4OyByX2NhcHMgMHgleCB3eF9jYXBzIDB4JXggcmVxdWlyZWQgcl9j -YXBzIDB4JXggd19jYXBzIDB4JXgKAAAAAAAAAAAAVlBEIHJlZ2lvbiBpcyB0b28gc21hbGwgKFNF -UkNGR19TUl9QRk5WUERTSVpFIDB4JXgpCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAggAAASAAAAAAAAAAggAA -AQAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABoCAAAAAAAAAAAAAAAAA -gAAAAAAAAAAAAoAAAAAAAAAAAAACAAMAAAAAAWAIAAAAAAMAAAAAAAAAAAAAAAMAAAAAAAAAAAAA -AAIAAAAAAAAAAAAgAAAAAAAAAAAAAAABAAOAAAAAAAAAAAAAAAIAAAAAAAAAAAAgA4AAAAAAAAAA -AAAQAoAAgAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAKAAAAAAAAAAAAAAAIAAAAA -AAAAAAAAAAKAAAAAAAAAAAABAAMAAAAAAAAAAAAAAoMAAAAAAAAAAAAQAoAAAAAAAAAAAAAwAAMA -AAAAAAAIAAAwAAMAAAAAAAAAAAAwBYMAAAAAAAAIAAAwBYMAAAAAAAAAAAAwBIMAAAAAAAAIAAAw -BIMAAAAAAAAAAAAwAwMAAAAAAAAIAAAwAwMAAAAAAAAAAAA4AwMAAAAAAAAAAAA4BYMAAAAAAAAA -AAA4BIMAAAAAAAAAAAA4AAMAAAAAAAAAAAA0BoIAAAAAAAAAAAA8A4IAAAAAAAAAAAA8AAMAAAAA -AAAIAAA8AAMAAAAAAAAAAAA8BIMAAAAAAAAAAAA8BQMAAAAAAAAAAAA9BAMAAAAAAAAAAAA8A4MA -AAAAAAAAAAAsAAIAAAAAAAAAAAAsBYIAAAAAAAAAAAAsBQIAAAAAAAAAAAAQBoAAAAAAAAAAAAAQ -BoLAAAAAAAAAAAAQBoKAAAAAAAAAAAAADoIAAAAAAAAAAAAQB4KAAAAAIAAAAAAAB4IAAAAAIAAA -AAAQBwKAAAAAAAAAAAAQBwKAAAAAAAAAAAAQBwKAAAAAAAAAAAAABwIAAAAAIAAAAAAQF4MAAAAA -AAAIAAAQF4MAAAAAAAAIAAAQAAAAAAAAAAAAAAAQBgOAAAAAAAAAAAAADgMAAAAAAAAAAAAQBgNA -AAAAAAAAAAAQBgMAAAAAAAAAAAAQBgAAAAAAAAAAAAAABgOAAAAAAAAAAAAABgMAAAAAAAAAAAAA -DgIAAAAAAAAAAAAADgIAAAAAAAAAAAAQBgIAAAAAAAAAAAAQBgIAAAAAAAAAAAAQBgKAAAAAAAAA -AAAQBgKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAEAMAAAAA -AAAIAAAAAAAAAAAAAAAAAAD///////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////8AAAAgAAAAAMAAAAAAAAAgAAAAAOAA -AAAAAAAAAgAAAAAAAABAAAAAAAAAAAAAAAAAAAEhAAAAAAAAAAAAAQEgAAAAAAAAAAAAAAIAAAAE -AAQAAAAABQAAAAQAAAAAAAAAAACgAAAAAIAAAAAAgABAAAAAAAACAAAAgAAgAAAAAAACAAABAEAA -AAAAAAAAAAABAEIAAAAAAAAAAAAAACAAAAAAAAAAAAACECAAAAAAAAAAAAACDAIAAAAAAAAAAAAA -hQIAAAAEAAAAAAAAgEIAAAAAAAAAAAACACIAAAAAAAAAAAAAgEEAAAAAAAAAAAAAgEGAAAAAAAAA -AAACACEAAAAAAAAAAAAAECCAAAAAAAAAAAACJQCAAAAAAAAAAAAABQAAAAAAAAAAAAAIiASAAAAA -AAAAAAAIiASAAAAAAAAAAAAIogCAAAAAAAAAAAAIogCAAAAAAAAAAAAIowCAAAAAAAAAAAAIowCA -AAAAAAAAAAAIpICAAAAAAAAAAAAIpICAAAAAAAAAAAAEpIDAAAAAAAAAAAAEogDAAAAAAAAAAAAE -owDAAAAAAAAAAAAEiATAAAAAAAAAAAAACQGAAAAAAAAAAAACDACAAAAAAAAAAAAAiATAAAAAAAAA -AAAAiASAAAAAAAAAAAACCwCAAAAAAAAAAAAAioCAAAAAAAAAAAAAC4CAAAAAAAAAAAAAjACAAAAA -AAAAAAACIBCAAAAAAAAAAAACCgCAAAAAAAAAAAACCoCAAAAAAAAAAAAACQKAAAAAAAAAAAAAAQEA -AAAAAAAAAAAAAQFAAAAAAAAAAAAAAQCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAA -AIEQAAAAAAAAAAAAAIEIAAAAAAAAAAAAAIEEAAAAAAAAAAAAAIGAAAAAAAAAAAAAgADAAAAAAAAA -AAAAgACgAAAAAAAAAAAAAAgAAAAAAAAAAAAAgYAAAAAAAAAAAAAAgYCAAAAAAAAAAAAAiYCAAAAA -AAAAAAAAiYDAAAAAAAAAAAAAAYIAAAAAAAAAAAACAYAAAAAAAAAAAAACAYCAAAAAAAAAAAAAQYGA -AAAAAAAAAAACAYGAAAAAAAAAAAAASYGAAAAAAAAAAAACCYGAAAAAAAAAAAACAYEAAAAAAAAAAAAA -QYEAAAAAAAAAAAAgAAAAAAAAAAAAAAAQAAACAAAAAAAAAAAQAAAAAAAAAAAAAAAAgADAAAAAAAAA -AAAAAAAAAAAAAAAAAAD///////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA -kgAAAAAAAAADZgAgAEAAAAAACACSAAAAAAAAAANyASUEQAAAAAAAAAAAAAAAAAAAA5YAIABAAAAA -AAgAAAACAIgDhwAAVgAgAEAAAAAAAAAAAAAAAAAAAAOWACAAQAAAAAAAAAAAAAAAAAAAA5YAIABA -AAAAAAAAAAAAAAAAAAADlgAgAEAAAAAAAAAAAAAAAAAAAAOWACAAQAAAAAAIAAAAAgCIA4UAAJYB -IABAAAAAAAAAAAAAAAAAAAADlgAgAEAAAAAAAAAAAAAAAAAAAAOWACAAQAAAAAAIAAAAAgCIA4UA -AJYBIABAAAAAAAAAAAAAAAAAAAADlgAgAEAAAAAAAAAAAAAAAAAAAAOWACAAQAAAAAAIAAAAAgCI -A4UAAJYBIABAAAAAAAAAAAAAAAAAAAADlgAgAEAAAAAAAAAAAAAAAAACAAOWACYEQAAAAAAIRyAB -BAAAArIAAtIFICRAAAAAAAAAAAAAAAAAAAADlgAgAEAAAAAAAEcgAQYMoYKwQAGSBCAkQAAAAAAA -RyABBAygQrOAAhIFICRAAAAAAAgAAAACAIgDhQAAlgEgAEAAAAAACAAAAAIAiAOFAACWASAAQAAA -AAAIAAAAAgCIA4UAAJYBIABAAAAAAAAAAAAAAAAAAAADlgAgAEAAAAAADcUSugKwgNMUVIviSkYk -QAAAAAAFxRK6AreA0xRUi2JJpiRAAAAAAAXFEqIGsIDTFFSL4kpGJEAAAAAADcUSoga3gNMUVIti -SaYkQAAAAAAFxRKiBrCA0xRUi+JKRiRAAAAAAA3FEqIGt4DTFFSLYkmmJEAAAAAABcUSogawgNMU -VIviSkYkQAAAAAANxRKiBreA0xRUi2JJpiRAAAAAAAnEEKACAICQAACLYmnGJEAAAAAAAcQQoAaw -gJMGVItiacYkQAAAAAABxBCgBrCAkwZUi2JpxiRAAAAAAAHFELgGsICTFlSLYkjGJEAAAAAACKEQ -iAIAgVgSAAtSAKYkQAAAAAAJwBCQArCAAxZUipIBxiRAAAAAAAnAELgGsIADEJSL4gJGJEAAAAAA -CcAQuAK0gAMQlItiAaYkQAAAAAAJwBC4ArSAAxCUi2IBpiRAAAAAAAnAELgCtIADEJSLYgGmJEAA -AAAACcAQuAK0gAMQlItiAaYkQAAAAAABoBCQBrSAAxCUi2IBpiRAAAAAAAHAEIACsIADFFSKUgDG -JEAAAAAAAcAQgAKwgAMUVIpSAMYkQAAAAAABwBCAArCAAxRUilIAxiRAAAAAAAhHIAEEAAACsgAC -0gUgJEAAAAAAAIEAAAIAhVgHQAtSAKYkQAAAAAAAgQAAAgCFWAdAC1IApiRAAAAAAAAAAAAEAKBA -AYAB1gAgAEAAAAAAAAAAAAYAoYAAQAFWACAAQAAAAAAAAAAABACgQAGAAdYAIABAAAAAAAiBAAAC -AIVZgAQLUgCmJEAAAAAACWFAAAAAABgAAANCASakQAAAAAAIQAAAAAAAAAAAA1IBJiRAAAAAAAAA -AAAEAKBAAYAB1gAgAEAAAAAACAAAAAIAiAOHAAPWACYEQAAAAAAIAAAAAgCIA4cAA9YAJgRAAAAA -AAAAAAAAAAAAAAADlgAgAEAAAAAAAAAAAAAAAAAAAAOWACAAQAAAAAAAAAAABACgQAGAAdYAIABA -AAAAAAnAELgCtIADEJSLYgGmJEAAAAAAAAAAAAAAAAACAAOWACYEQAAAAAAAAAAAAAAAAAAAA5YA -IABAAAAAAAgAAAACAIgDhQAAlgEgAEAAAAAAAAAAAAQAoEABgAHWACAAQAAAAAAAAAAABACgQAGA -AdYAIABAAAAAAAAAAAAEAKBAAYAB1gAgAEAAAAAACKEQiAIAgVgQAAkSAaYkQAAAAAAAAAAABACg -QAGAAdYAIABAAAAAAAAAAAAGAKGAAEABVgAgAEAAAAAACAAAAAIAiAOFQAjSAkYkQAAAAAAJxRKi -ApSI0hCAiyJIpiRAAAAAAAnAEIACpIgAh1SLUgGmJEAAAAAACcAQgAa0iAMBFItSAaYkQAAAAAAN -wAAAArCAwxZUi+IDRiRAAAAAAAAAAAAAAAAAAAADlgAgAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIADAABAAA -AAIAAAIAJiRAAAAAAABHMAAGAyACtwAIAgHAJEAAAAAACAMAAAIGoAq1AAgCAMYkQAAAAAAAAAAA -AAAAAAIAAAIAJiRAAAAAAAAgUAAEAAAAAgAAAgAmJEAAAAAACGAgAIQAAAAAAAAGACAAQAAAAAAI -YCAAhAAAAAIBMAIAJiVAAAAAAAhgAAAEAIQBgAQEAgHGJMAAAAAAAcAAAAJDgAMCDIgCAaYkQAAA -AAAIAGAABAAAAAIAAAIAJiRAAAAAAAgAYAAEAAAAAAAABAEgAEAAAAAAAAAAAAAAAAAAAAAEASAA -QAAAAAAECBSABgoAAAcBTAIgpiZAAAAAAAiAAAAGAIQBgAQIAgGmJkAAAAAAAEAAAAIAoAACQAgC -AaYkQAAAAAAAAAAAAAAAAAIAAAIAJiRAAAAAAAQAAAAChAADAooIAgSmJEAAAAAAAAAAAAAAAAAC -AAAGASBIQAAAAAAAIFAABAAAAAIAAAIAJiRAAAAAAAhgIACEAAAAAgAABgAmBEAAAAAACGAgAIQA -AAACAAACASYlQAAAAAAIYAAABACEAYAEBAIBxiTAAAAAAAgAYAAEAAAAAAAABAEgAEAAAAAAAAAA -AAAAAAAAAAACACZMcAAAAAAAAAAAAAAAAAAAAAYBIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAcAAAAi0kAQJFgQCBMYkQAAAAAABwAAACLSQBAkWBAIExiRAAAAAAAQIdIBMCQAAUABc -AmHmJEAAAAAADAh0gEQAAABSAEACYSYkQAAAAAAIAhCgBAAAAAABAAIAJiRAAAAAAAgCEKAEAAAA -AAEAAgAmJEAAAAAABAh0AEIBAAAHAIgCYMYkQAAAAAANyBQAAgkAAARAnAJg5iRAAAAAAAnIEIAG -tJAEApSIAmXGJEAAAAAADch0AEi0kAMAlIgCYKYkwAAAAAANyHQASLSQAwCUiAJgpiTAAAAAAAhH -AAAEAAAAAAAAAgEgJEAAAAAACEcAAAQAAAACAAACBSAkQAAAAAAARyABDAchwrcACAIBwCRAAAAA -AABHIAEMByHCtwAIAgHAJEAAAAAAAEcgAQwHIcK3AAgCAcAkQAAAAAAAACABCACEAAVAiAIBxiTA -AAAAAAAAIAEIAIQABUCIAgHGJMAAAAAAAAAgAQgAhAAFQIgCAcYkwAAAAAAAACABhoIAAQLAiAID -xiTAAAAAAAAAIAGCggAAAsCIAgPGJMAAAAAACcAgAYKkgAEFQIgCAcYkwAAAAAAIAAAADACEAAVA -iAIBxiTAAAAAAAAAIAGGggABAsCIAgPGJMAAAAAAAAAgAYKCAAAAwIgCAqYkwAAAAAAJwCABgqSA -AQVAiAIBxiTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAQABCQEAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAABbZ2xvYmFsXQpyc3NfZ2xiX2NvbmZpZ19tb2RlPWJhc2lj -dmlydHVhbApyc3NfZ2xiX2NvbmZpZ19vcHRpb25zPXRubG1hcGVuLGhhc2h0b2VwbGl0eix0bmxh -bGxsa3AKcmVnWzB4MTAwOF09MHg0MDgxMC8weDIxYzcwCnJlZ1sweDEwMGNdPTB4MjIyMjIyMjIK -cmVnWzB4MTBhMF09MHgwMTA0MDgxMApyZWdbMHgxMDQ0XT00MDk2CnJlZ1sweDEwNDhdPTY1NTM2 -CnJlZ1sweDEwNGNdPTE1MzYKcmVnWzB4MTA1MF09OTAyNApyZWdbMHgxMDU0XT05MjE2CnJlZ1sw -eDEwNThdPTIwNDgKcmVnWzB4MTA1Y109MTI4CnJlZ1sweDEwNjBdPTgxOTIKcmVnWzB4MTA2NF09 -MTYzODQKcmVnWzB4MTBhNF09MHhhMDAwYTAwMC8weGYwMDBmMDAwCnJlZ1sweDEwYThdPTB4MjAw -MC8weDIwMDAKc2dlX3RpbWVyX3ZhbHVlPTUsMTAsMjAsNTAsMTAwLDIwMApyZWdbMHg3ZGMwXT0w -eDY0Zjg4NDkKZmlsdGVyTW9kZT1mcmFnbWVudGF0aW9uLG1wc2hpdHR5cGUscHJvdG9jb2wsdmxh -bixwb3J0LGZjb2UKdHBfcG1yeD0zMAp0cF9wbXJ4X3BhZ2VzaXplPTY0Swp0cF9wbXR4PTUwCnRw -X3BtdHhfcGFnZXNpemU9NjRLCltmdW5jdGlvbiIwIl0KbnZmPTE2Cnd4X2NhcHM9YWxsCnJfY2Fw -cz1hbGwKbnZpPTEKbmlxZmxpbnQ9OApuZXRoY3RybD04Cm5lcT0xNgpuZXhhY3RmPTgKY21hc2s9 -YWxsCnBtYXNrPTB4MQpbZnVuY3Rpb24iMSJdCm52Zj0xNgp3eF9jYXBzPWFsbApyX2NhcHM9YWxs -Cm52aT0xCm5pcWZsaW50PTgKbmV0aGN0cmw9OApuZXE9MTYKbmV4YWN0Zj04CmNtYXNrPWFsbApw -bWFzaz0weDIKW2Z1bmN0aW9uIjIiXQpudmY9MTYKd3hfY2Fwcz1hbGwKcl9jYXBzPWFsbApudmk9 -MQpuaXFmbGludD04Cm5ldGhjdHJsPTgKbmVxPTE2Cm5leGFjdGY9OApjbWFzaz1hbGwKcG1hc2s9 -MHg0CltmdW5jdGlvbiIzIl0KbnZmPTE2Cnd4X2NhcHM9YWxsCnJfY2Fwcz1hbGwKbnZpPTEKbmlx -ZmxpbnQ9OApuZXRoY3RybD04Cm5lcT0xNgpuZXhhY3RmPTgKY21hc2s9YWxsCnBtYXNrPTB4OApb -ZnVuY3Rpb24iNCJdCnd4X2NhcHM9YWxsCnJfY2Fwcz1hbGwKbnZpPTI4Cm5pcWZsaW50PTE3MApu -ZXRoY3RybD0xMDAKbmVxPTI1NgpuZXhhY3RmPTQwCmNtYXNrPWFsbApwbWFzaz1hbGwKbmV0aG9m -bGQ9MTAyNApucm91dGU9MzIKbmNsaXA9MzIKbmZpbHRlcj00OTYKbnNlcnZlcj00OTYKbmhhc2g9 -MTIyODgKcHJvdG9jb2w9bmljX3ZtLG9mbGQscmRkcCxyZG1hYyxpc2NzaV9pbml0aWF0b3JfcGR1 -LGlzY3NpX3RhcmdldF9wZHUKdHBfbDJ0PTMwNzIKdHBfZGRwPTIKdHBfZGRwX2lzY3NpPTIKdHBf -c3RhZz0yCnRwX3BibD01CnRwX3JxPTcKW2Z1bmN0aW9uIjUiXQp3eF9jYXBzPWFsbApyX2NhcHM9 -YWxsCm52aT00Cm5pcWZsaW50PTM0Cm5ldGhjdHJsPTMyCm5lcT02NApuZXhhY3RmPTQKY21hc2s9 -YWxsCnBtYXNrPWFsbApuc2VydmVyPTE2Cm5oYXNoPTIwNDgKdHBfbDJ0PTEwMjQKcHJvdG9jb2w9 -aXNjc2lfaW5pdGlhdG9yX2ZvZmxkCnRwX2RkcF9pc2NzaT0yCmlzY3NpX250YXNrPTIwNDgKaXNj -c2lfbnNlc3M9MjA0OAppc2NzaV9uY29ubl9wZXJfc2Vzc2lvbj0xCmlzY3NpX25pbml0aWF0b3Jf -aW5zdGFuY2U9NjQKW2Z1bmN0aW9uIjYiXQp3eF9jYXBzPWFsbApyX2NhcHM9YWxsCm52aT00Cm5p -cWZsaW50PTM0Cm5ldGhjdHJsPTMyCm5lcT02NgpuZXhhY3RmPTMyCmNtYXNrPWFsbApwbWFzaz1h -bGwKbmhhc2g9MjA0OApwcm90b2NvbD1mY29lX2luaXRpYXRvcgp0cF9kZHA9MgpmY29lX25mY2Y9 -MTYKZmNvZV9udm5wPTMyCmZjb2VfbnNzbj0xMDI0CltmdW5jdGlvbiIxMDIzIl0Kd3hfY2Fwcz1h -bGwKcl9jYXBzPWFsbApudmk9NApjbWFzaz1hbGwKcG1hc2s9YWxsCm5leGFjdGY9OApuZmlsdGVy -PTE2CltmdW5jdGlvbiIwLyoiXQp3eF9jYXBzPTB4ODIKcl9jYXBzPTB4ODYKbnZpPTEKbmlxZmxp -bnQ9NApuZXRoY3RybD0yCm5lcT00Cm5leGFjdGY9NApjbWFzaz1hbGwKcG1hc2s9MHgxCltmdW5j -dGlvbiIxLyoiXQp3eF9jYXBzPTB4ODIKcl9jYXBzPTB4ODYKbnZpPTEKbmlxZmxpbnQ9NApuZXRo -Y3RybD0yCm5lcT00Cm5leGFjdGY9NApjbWFzaz1hbGwKcG1hc2s9MHgyCltmdW5jdGlvbiIyLyoi -XQp3eF9jYXBzPTB4ODIKcl9jYXBzPTB4ODYKbnZpPTEKbmlxZmxpbnQ9NApuZXRoY3RybD0yCm5l -cT00Cm5leGFjdGY9NApjbWFzaz1hbGwKcG1hc2s9MHg0CltmdW5jdGlvbiIzLyoiXQp3eF9jYXBz -PTB4ODIKcl9jYXBzPTB4ODYKbnZpPTEKbmlxZmxpbnQ9NApuZXRoY3RybD0yCm5lcT00Cm5leGFj -dGY9NApjbWFzaz1hbGwKcG1hc2s9MHg4Cltwb3J0IjAiXQpkY2I9cHBwLGRjYngKYmdfbWVtPTI1 -CmxwYmtfbWVtPTI1Cmh3bT0zMApsd209MTUKZHdtPTMwCltwb3J0IjEiXQpkY2I9cHBwLGRjYngK -YmdfbWVtPTI1CmxwYmtfbWVtPTI1Cmh3bT0zMApsd209MTUKZHdtPTMwCltwb3J0IjIiXQpkY2I9 -cHBwLGRjYngKYmdfbWVtPTI1CmxwYmtfbWVtPTI1Cmh3bT0zMApsd209MTUKZHdtPTMwCltwb3J0 -IjMiXQpkY2I9cHBwLGRjYngKYmdfbWVtPTI1CmxwYmtfbWVtPTI1Cmh3bT0zMApsd209MTUKZHdt -PTMwCltmaW5pXQp2ZXJzaW9uPTB4MTQyNTAwMGIKY2hlY2tzdW09MHg3NjkwZjdhNQoAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAFtnbG9iYWxdCnJzc19nbGJfY29uZmlnX21vZGU9YmFzaWN2aXJ0dWFs -CnJzc19nbGJfY29uZmlnX29wdGlvbnM9dG5sbWFwZW4saGFzaHRvZXBsaXR6LHRubGFsbGxrcApy -ZWdbMHgxMDA4XT0weDQwODEwLzB4MjFjNzAKcmVnWzB4MTAwY109MHgyMjIyMjIyMgpyZWdbMHgx -MGEwXT0weDAxMDQwODEwCnJlZ1sweDEwNDRdPTQwOTYKcmVnWzB4MTA0OF09NjU1MzYKcmVnWzB4 -MTA0Y109MTUzNgpyZWdbMHgxMDUwXT05MDI0CnJlZ1sweDEwNTRdPTkyMTYKcmVnWzB4MTA1OF09 -MjA0OApyZWdbMHgxMDVjXT0xMjgKcmVnWzB4MTA2MF09ODE5MgpyZWdbMHgxMDY0XT0xNjM4NApy -ZWdbMHgxMGE0XT0weGEwMDBhMDAwLzB4ZjAwMGYwMDAKcmVnWzB4MTBhOF09MHgyMDAwLzB4MjAw -MApzZ2VfdGltZXJfdmFsdWU9NSwxMCwyMCw1MCwxMDAsMjAwCnJlZ1sweDdkYzBdPTB4NjRmODg0 -OQpmaWx0ZXJNb2RlPWZyYWdtZW50YXRpb24sbXBzaGl0dHlwZSxwcm90b2NvbCx2bGFuLHBvcnQs -ZmNvZQp0cF9wbXJ4PTMwCnRwX3BtcnhfcGFnZXNpemU9NjRLCnRwX3BtdHg9NTAKdHBfcG10eF9w -YWdlc2l6ZT02NEsKW2Z1bmN0aW9uIjAiXQp3eF9jYXBzPWFsbApyX2NhcHM9YWxsCm52aT0yOApu -aXFmbGludD0xNzAKbmV0aGN0cmw9OTYKbmVxPTI1MgpuZXhhY3RmPTQwCmNtYXNrPWFsbApwbWFz -az1hbGwKbnJvdXRlPTMyCm5jbGlwPTMyCm5maWx0ZXI9NDgKbnNlcnZlcj0zMgpuaGFzaD0wCnBy -b3RvY29sPW5pY192bSxvZmxkLHJkZHAscmRtYWMsaXNjc2lfaW5pdGlhdG9yX3BkdSxpc2NzaV90 -YXJnZXRfcGR1CnRwX2wydD0zMDcyCnRwX2RkcD0yCnRwX2RkcF9pc2NzaT0yCnRwX3N0YWc9Mgp0 -cF9wYmw9NQp0cF9ycT03CltmdW5jdGlvbiIxIl0Kd3hfY2Fwcz1hbGwKcl9jYXBzPWFsbApudmk9 -NApuaXFmbGludD0zNApuZXRoY3RybD0zMgpuZXE9NjYKbmV4YWN0Zj0zMgpjbWFzaz1hbGwKcG1h -c2s9YWxsCm5oYXNoPTAKcHJvdG9jb2w9ZmNvZV9pbml0aWF0b3IKdHBfZGRwPTIKZmNvZV9uZmNm -PTE2CmZjb2VfbnZucD0zMgpmY29lX25zc249MTAyNApbZnVuY3Rpb24iMTAyMyJdCnd4X2NhcHM9 -YWxsCnJfY2Fwcz1hbGwKbnZpPTQKY21hc2s9YWxsCnBtYXNrPWFsbApuZXhhY3RmPTgKbmZpbHRl -cj0xNgpbZnVuY3Rpb24iMC8qIl0Kd3hfY2Fwcz0weDgyCnJfY2Fwcz0weDg2Cm52aT0xCm5pcWZs -aW50PTQKbmV0aGN0cmw9MgpuZXE9NApuZXhhY3RmPTQKY21hc2s9YWxsCnBtYXNrPTB4MQpbZnVu -Y3Rpb24iMS8qIl0Kd3hfY2Fwcz0weDgyCnJfY2Fwcz0weDg2Cm52aT0xCm5pcWZsaW50PTQKbmV0 -aGN0cmw9MgpuZXE9NApuZXhhY3RmPTQKY21hc2s9YWxsCnBtYXNrPTB4MgpbcG9ydCIwIl0KZGNi -PXBwcCxkY2J4CmJnX21lbT0yNQpscGJrX21lbT0yNQpod209MzAKbHdtPTE1CmR3bT0zMApbcG9y -dCIxIl0KZGNiPXBwcCxkY2J4CmJnX21lbT0yNQpscGJrX21lbT0yNQpod209MzAKbHdtPTE1CmR3 -bT0zMApbcG9ydCIyIl0KZGNiPXBwcCxkY2J4CmJnX21lbT0yNQpscGJrX21lbT0yNQpod209MzAK -bHdtPTE1CmR3bT0zMApbcG9ydCIzIl0KZGNiPXBwcCxkY2J4CmJnX21lbT0yNQpscGJrX21lbT0y -NQpod209MzAKbHdtPTE1CmR3bT0zMApbZmluaV0KdmVyc2lvbj0weDE0MjUwMDBhCmNoZWNrc3Vt -PTB4NGU1NjY2MzkKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAA -==== diff --git a/sys/dev/cxgbe/firmware/t4fw-1.8.4.0.bin.uu b/sys/dev/cxgbe/firmware/t4fw-1.8.4.0.bin.uu new file mode 100644 index 00000000000..129a69fb8c7 --- /dev/null +++ b/sys/dev/cxgbe/firmware/t4fw-1.8.4.0.bin.uu @@ -0,0 +1,8237 @@ +/*- + * Copyright (c) 2013 Chelsio Communications, Inc. + * 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. + */ +begin-base64 644 t4fw +AAADkgEIBAAAAQkBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAA3cDhgONAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAENoZWxzaW8gRlcgUlVOTUVNIERFQlVHPTAgKEJ1aWx0IFRodSBGZWIgIDcgMTU6 +Mzg6MjYgUFNUIDIwMTMgb24gY2xlb3BhdHJhLmFzaWNkZXNpZ25lcnMuY29tOi9ob21lL2Zpcm13 +YXJlL2N2cy9mdy1yZWxlYXNlKSwgVmVyc2lvbiBUNHh4IDAxLjA4LjA0LjAwAAAAAAAAAJ/jNKZg +AMQA4QAwuHj///8f/OFAgAAAAeEAe3AAABAAH//7gOEAYBDhAZRwIAAAAOEBnAThAHkAAAIAQOEA +eYAABgBAAAIACgAGAArhAHkEAAoAAIAAAQDhAHs84QB7ROEAe+TiAAAAAAEAAOEAe5AgAAAAAACA +AOEAewAAAEAB4QB7nAAAQABERERC4AAAAOMABHNERERA4wAIACAAAlwAAAAAH/+NIAAAAAAf/40k +AAAAAB//jSgAAAAAH/+NLB//wAAAAAAAAAAAAMAAEv/OE//OhCAEMwGTIBH/zRL/zZIQEf/NEv/N +khAR/80B9DER/8yQEBH/zCIK/5IQAOQxAAUxAQIAEv/JAucxAhYAEf/IgRABAV/AIQIRAckUEf/F +Ev/FkhAR/8US/8WSEGAAEgAAABH/vxL/w5IQEf+/Ev/CkhCBEBH/wcAgkhES/8CSEsAgkhMS/7+S +EIIQAvJQZS/3Ef+9xy+SEBH/vJIQEv+8E/+8kyDAMpMhE/+7kyKCIhL/uhP/upMgIyIhFP+5BDMB +yTgT/7iDMAODFAgzERT/tqQzkyET/6qTImAACMIwkyET/6eTIhL/sZAgkCGQIpAjkCSQJZAmkCeQ +KJApkCqQK5AskC2QLpAvICYQICYRgiIS/6TAMC03MC03NC03OC03PCM9AXIz7QACABL/oSMKAC83 +AC83EC83IC83MCM9AXIz7QACABL/lsAwKDcwKDc0KDc4KDc8Iz0BcjPtAwIAEv+UwDAnNwAnNxAn +NyAnNzAjPQFyM+0DAgAS/44V/48W/4/AMNcgBWYBYAAWAAAAAAQ2BQACANMP0w8FMwxuOxQHRxQH +BEN2MeYENgUFMwxvO+0AAgAS/4IV/4AjCgACJwIHBEMEPgUFMwwHRxRvO/ADAgAS/3zJLoMghCGF +IrwidDsOhlC0VZYwtDN0M/Rj/+YAZT/iZV/fEv9wwDIDLgUDAgAS/2fAMCg3QCg3RCg3SCg3TCM9 +AXIz7QMCAAACABL/ai0nAMARAUkxAEgxAQIAwAAU/2YE0jEV/2WUUBT/ZQTTMRX/ZZRQFP9kBNQx +Ff9klFAU/2QE1TEV/2OUUBD/YwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf/AAA +H/wAAOMACfgf/AAAH/wAAOMACfgf/AAAH/wAAOMACfgf/4AAH/+GAOMACfgf/4YAH/+GAOMAD/gf +/4YAH/+GAOMAD/gf/4YAH/+HdOMAD/gf/4d0H/+NIOMAEWwf/40gH/+nhOMAFxgf/6eEH/+nhOMA +MXwf/8AAH//8ZeMAMXwgAAAAIAABauMAbeQgAAF4IAABfOMAb1AgAAF8IAABheMAb1QgAAGYIAAB +nOMAb2AgAAGcIAABpeMAb2QgAAG4IAABvOMAb3AgAAG8IAABxeMAb3QgAAHYIAAB2OMAb4AgAAHc +IAAB4uMAb4AgAAH4IAAB+OMAb4ggAAH8IAAB/OMAb4ggAAIYIAACGOMAb4ggAAIcIAACHOMAb4gg +AAI4IAACOOMAb4ggAAI8IAACPOMAb4ggAAJYIAACWOMAb4ggAAJcIAACYuMAb4ggAAJ4IAACeOMA +b5AgAAJ8IAACguMAb5AgAAKYIAGaouMAb5ggAoAAIAKTYOMCB6QgApNgIAKTYOMCGwQgApNgIAYP +KOMCGwQgBg8wIAYT8OMFltQgBoAAIAaNUOMFm5QgBo1QIAdgsuMFqOQgB2DAIAdhjOMGfFQgCMAA +IAjAAOMGfSAgCMAAIAjAAOMGfSAgCMAAIAkvL+MGfSAAAAAAAAAAAAAAAAAgAAYvIAAGICAACjkg +AAYgIAAJpSAABiAgAAbZIAAJPSAACMIgAAYgIAAIcSAACCQgAAe5IAAGDSAAB2QgAAYgIAAGICAA +BiAgAAb6AAAAAP///////w/8///w////APwgAItrIACMqyAAjNsgAIyhIACMYSAAjFcgAIwcIACM +EiAAjAggAIu4IACM2SAAi64gAIuUAAAAAAAAAAAAAAAAAAAACgAAAAoAAAAUAAAACgAAAAoAAAAK +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 +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAgCgAR8X8T8X/TDwPmMQECABbxfRfxfndrBpBgtGZ3Y/hUDoBVk5kPFABj +//kAAABsEAQY8Xsd8XYrIAcc8XYqIQj6AgAHcbsBAO7cOQ3cAoAAC6oCnDDj8XAZsASAAAiqAhzx +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 +IANNtCADTmEgA09bIANPZSADTmEgA09bIANPWyADT1sgA09lIANOYSADTmEgA09bIANPWwMPCBKD +jpOSAAAAAAAAAAAgA4eRIAOIrCADh5EgA4eRIAOIrCADiKwgA4isIAOHkSADh5EgA4eRIAOIrCAD +iKwgA4l9IAOJ/SADinYgA4qwIAOKwyADi4UgA4wAIAOMEyADjH0gA4ytIAOM0gAAAAAgA5RBIAOV +jSADkxQgA5M3IAOUKSADkvQgA5MMIAOVqiADlgggA5l9IAOYPSADmHcgA5aZIAOXCyADl3kgA5e4 +IAOX8CADmO0gA5jlIAOY3SADmKEgA5iZARAYAQABAAAgA+OoIAPjqCAD4bsgA+OoIAPhuyAD44Qg +A+NdIAPhuyAD4pEgA+G7IAPhuyAD4oggA+G7IAPjqCAD4bsgA+G7IAPjqCAD4cQAAAAAAAAAAAMB +AAIAAAAAAAAAAAAAAAAgBGA9IARe8SAEXvYgBGA9IARe8SAEXvEgBF7xIARe9iAEYD0gBGA9IARe +8SAEXvEgBGVqIARlmCAEZx8gBGVqIARnFyAEZv0gBGVqIARlaiAEZWogBGVqIARlaiAEZWogBGVq +IARlaiAEZWogBGVqIARm6CAEZtMgBGVqIARlaiAEZWogBGVqIARlaiAEZWogBGVqIARlaiAEZWog +BGVqIARlaiAEZWogBGVqIARlaiAEZqggBGVqIARmjSAEZo0gBGVqIARlaiAEZm0gBGVqIARmjSAE +ZWogBGVqIARlaiAEZWogBGVqIARlaiAEZWogBGVqIARlaiAEZWogBGVqIARlaiAEZWogBGVqIARl +aiAEZWogBGVqIARlaiAEZWogBGVqIARlaiAEZWogBGVqIARmTQAAAAAAAAAAAAAAACAEqrYgBKq2 +IASpiSAEqrYgBKSmIASqrCAEqoggBKSmIASkpiAEpKYgBKSmIASkpiAEqWwgBKq2IASkpiAEqWwg +BKq2AAAAAAAAAAAAAAAAIAS5vCAEuhEgBLxjIAS8EiAEu8sgBLugIAS7jSAEu4cgBLrdAAAAAAAA +AAAAAAAAARAYAQACAAABEBgBAAIAACAFCAYgBQfbIAUGQyAFB6MgBQejIAUHoyAFBkMgBQejIAUG +QyAFB4QgBQZDIAUGQyAFB4QgBQejAAAAAAAAAAAgBSuwIAUnfCAFK4QgBStYIAUrLCAFJ6MgBSej +IAUnuiAFKxMgBSfvIAUn2yAFJ6MgBSfvIAUnoyAFJ6MgBSejIAUrsAAAAAAAAAAAAAAAAAAAAAAg +BX9kIAV12CAFdYggBXGIAAAAAAAAAAAAAAAAIAV1wiAFdb4gBXW+IAV1viAFdcIgBXW+IAV1viAF +db4gBXW+IAV1viAFdb4gBXW+IAV1viAFdb4gBXW+IAV1viAFdb4gBXW+IAV1viAFdb4gBXW+IAV1 +viAFdb4gBXW+IAV1viAFdb4gBXW+IAV1viAFdb4gBXW+IAV1viAFdb4gBXW+IAV1viAFdb4gBXW+ +IAV1viAFdb4gBXW+IAV1viAFdb4gBXW+IAV1viAFdb4gBXW+IAV1viAFdb4gBXW+IAV1viAFdb4g +BXW+IAV1viAFdb4gBXW+IAV1viAFdb4gBXW+IAV1viAFdb4gBXW+IAV1wiAFdb4gBXW+IAV1viAF +dcIgBXW+IAV1viAFdb4gBXXCIAV1viAFdb4gBXW+IAV1wiAFdb4gBXW+IAV1viAFdcIgBXW+IAV1 +viAFdb4gBXXCIAV1viAFdb4gBXW+IAV1wiAFdb4gBXW+IAV1viAFdcIgBXW+IAV1viAFdb4gBXXC +IAV1viAFdb4gBXW+IAV1wiAFdb4gBXW+IAV1viAFdcIgBXW+IAV1viAFdb4gBXXCIAV1viAFdb4g +BXW+IAV1wiAFdb4gBXW+IAV1viAFdcIgBXW+IAV1viAFdb4gBXXCIAV1viAFdb4gBXW+IAV1wiAF +db4gBXW+IAV1viAFdb4gBXW+IAV1viAFdb4gBXW+IAV1viAFdb4gBXW+IAV1viAFdb4gBXW+IAV1 +viAFdb4gBXW+IAV1viAFdb4gBXXCIAV1viAFdb4gBXW+IAV1viAFdb4gBXW+IAV1viAFdb4gBXW+ +IAV1viAFdb4gBXXCIAV1viAFdb4gBXW+IAV1viAFdb4gBXW+IAV1viAFdb4gBXW+IAV1viAFdb4g +BXW+IAV1viAFdb4gBXW+IAV1viAFdb4gBXW+IAV1viAFdb4gBXW+IAV1viAFdb4gBXXCIAV1viAF +db4gBXW+IAV1wiAFdb4gBXW+IAV1viAFdcIAAAAAAAAAAAAAAAAgBXYeIAV3HSAFeMsgBXi9IAV4 +qCAFeJogBXiFIAV4dyAFeGIgBXhVIAV4QiAFeDUgBXgiIAV4FSAFeAIgBXYLIAV37yAFd+IgBXfP +IAV3wiAFd64gBXekIAV3kyAFd4kgBXd4IAV2CyAFdgsgBXYLIAV2CyAFdgsgBXYLIAV3ayAFdjcg +BXYLIAV2CyAFdgsgBXdOIAV3NSAFdysgBXcMIAV2CyAFdvkgBXbfIAV2zCAFdrIgBXafIAV2hyAF +dnQgBXZhIAV2UQAAAAAAAAAAIAV/uiAFf98gBYECIAWA2iAFgNMgBYDMIAWAxSAFgL4gBYC3IAWA +sCAFgKkgBYCfIAWAlSAFgHcgBX/1IAV/lyAFf+wgBX/EAAAAAAAAAAAgBdCAIAXN5CAFzHggBcrE +IAXHrCAFwcwgBcUIIAXFuFJWAAAAAAAAQb3NZQAAAABjb25maWd1cmF0aW9uIGZpbGUgcGFyc2Vy +IGZvdW5kIGFkZGl0aW9uYWwgY29uZmlndXJhdGlvbiBhZnRlciBbZmluaV0KAABmY29lAAAAAHZu +aWNfaWQAdmxhbgAAAAB0b3MAZXRoZXJ0eXBlAAAAbWFjbWF0Y2gAAAAAbXBzaGl0dHlwZQAAZnJh +Z21lbnRhdGlvbgAAAGJhc2ljdmlydHVhbAAAAABzeW5tYXBlbgAAAABzeW40dHVwZW5pcHY2AAAA +c3luMnR1cGVuaXB2NgAAAHN5bjR0dXBlbmlwdjQAAABzeW4ydHVwZW5pcHY0AAAAb2ZkbWFwZW4A +AAAAdG5sbWFwZW4AAAAAdG5sYWxsbGtwAAAAaGFzaHRvZXBsaXR6AAAAAHRwX3BpbwAAdHBfdG1f +cGlvAAAAMAAAAG5pY192bQAAbmljX3VtAABuaWNfdW1faXNnbABvZmxkAAAAAHJkZHAAAAAAcmRt +YWMAAABpc2NzaV9pbml0aWF0b3JfcGR1AGlzY3NpX3RhcmdldF9wZHUAAAAAaXNjc2lfaW5pdGlh +dG9yX2ZvZmxkAAAAaXNjc2lfdGFyZ2V0X2ZvZmxkAABmY29lX2luaXRpYXRvcgAAZmNvZV90YXJn +ZXQAcG9mY29lX2luaXRpYXRvcgAAAABwb2Zjb2VfdGFyZ2V0AAAAcHBwAGRjYngAAAAAIAKQgAAE +AAAAAAQAAAQAADB4AAAwWAAAMEIAACAF+SQgBd3wIAX5FCAF3gAgBd4UIAXdICAF3rwgBdy4AAEC +AwAAAAAAAAAAAAAAACADsxwgA7KwIASzrAAAAAAgA7KoIAOyoCADspgAAAAAY4JTYwAAAAAAAAAA +AAAAAAAAAAAAAAAEAAAABAAAAAhBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWpr +bG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSsvPQAAAAAAAAAAAAAAAAAAAAsAAAAgApDACAAAACAC +kMwIAAAAIAKQ2AoAAAAgApDkDAAAACACkPASAAAAIAKRAA0AAAAgApEUDgAAACACkSQTAAAAIAKR +NAoAAAAgApFIDgAAACACkVQYAAAAIAKRZA0AAAAgApGADgAAACACkZAQAAAAIAKRoBIAAAAgApG0 +DgAAACACkcgQAAAAIAKR2BEAAAAgApHsCgAAACACkgALAAAAIAKSDA0AAAAgApIYFAAAACACkigK +AAAAIAKSQA8AAAAgApJMBgAAACACklwGAAAAIAKSZAYAAAAgApJsBgAAACACknQGAAAAIAKSfAkA +AAAgApKEBgAAACACkpAEAAAAIAKSmAYAAAAgApKgCwAAACACkqgLAAAAIAKStAQAAAAgApKYBAAA +ACACksAJAAAAIAKSyAkAAAAgApLUAAAAAAAAAAANAAAAIAKS4AoAAAAgApLwBgAAACACkvwCAAAA +IAKTBAMAAAAgApC8AQAAACACkwgAAAAAAAAAAP///////wAAAAdDAAAAAAD///////////////// +////AAAAgAAAAQAAAAIAAAAEAAAACAAAABAAAAAAAAAAAAADAgEAAAAAAAAAAAAAAAAAAAAABQAA +AAMAAAABAAAAAiAF1IwgBdREIAXTPCAF0fwgBdG8IAXRkCAF0eQAAAAAAAACAAAABAAAAAgAAAAA +AAAEBAhOQQAAVjAAAFYxAABWMgAAVjMAAFY0AABWNQAAVjYAAFY3AABWOAAAVjkAAFZBAABWQgAA +VkMAAFZEAABWRQAAVkYAAGFsbAAqAAAAbm9uZQAAAAAweAAAcG9ydAAAAABwcm90b2NvbAAAAABn +bG9iYWwAAGZ1bmN0aW9uAAAAAGZpbmkAAAAAcmVnAGZpbHRlck1vZGUAAHJzc19nbGJfY29uZmln +X21vZGUAcnNzX2dsYl9jb25maWdfb3B0aW9ucwAAc2dlX3RpbWVyX3ZhbHVlAHRwX3BtcngAdHBf +cG1yeF9wYWdlc2l6ZQAAAAB0cF9wbXR4AHRwX3BtdHhfcGFnZXNpemUAAAAAbXR1cwAAAABudmYA +d3hfY2FwcwByX2NhcHMAAG5pcWZsaW50AAAAAG5lcQBuZXRoY3RybAAAAABudmkAcnNzbnZpAABu +ZXhhY3RmAGNtYXNrAAAAcG1hc2sAAABuZXRob2ZsZAAAAABucm91dGUAAG5jbGlwAAAAbmZpbHRl +cgBuc2VydmVyAG5oYXNoAAAAdHBfbDJ0AAB0cF9kZHAAAHRwX2RkcF9pc2NzaQAAAAB0cF9zdGFn +AHRwX3BibAAAdHBfcnEAAABpc2NzaV9udGFzawBpc2NzaV9uc2VzcwBpc2NzaV9uY29ubl9wZXJf +c2Vzc2lvbgBpc2NzaV9uaW5pdGlhdG9yX2luc3RhbmNlAAAAaXNjc2lfbWF4X3NnZQAAAHBwbV9t +YXhfem9uZXMAAABwcG1fem9uZV9yYW5nZTAAcHBtX3pvbmVfcmFuZ2UxAHBwbV96b25lX3Jhbmdl +MgBwcG1fem9uZV9yYW5nZTMAZmNvZV9uZmNmAAAAZmNvZV9udm5wAAAAZmNvZV9uc3NuAAAAZGNi +AGJnX21lbQAAbHBia19tZW0AAAAAaHdtAGx3bQBkd20AdmVyc2lvbgBjaGVja3N1bQAAAABDaGVs +c2lvX0ZPaVNDU0kAMDEyMzQ1Njc4OWFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6AAAAADBiAABZ +ZXMAU2Vzc2lvblR5cGUAT0ZNYXJrZXIAAAAASUZNYXJrZXIAAAAARGF0YURpZ2VzdAAASGVhZGVy +RGlnZXN0AAAAAEVycm9yUmVjb3ZlcnlMZXZlbAAASW1tZWRpYXRlRGF0YQAAAERhdGFQRFVJbk9y +ZGVyAABEYXRhU2VxdWVuY2VJbk9yZGVyAEluaXRpYWxSMlQAAE1heENvbm5lY3Rpb25zAABNYXhS +ZWN2RGF0YVNlZ21lbnRMZW5ndGgAAAAASW5pdGlhdG9yTmFtZQAAAEluaXRpYXRvckFsaWFzAABE +ZWZhdWx0VGltZTJXYWl0AAAAAERlZmF1bHRUaW1lMlJldGFpbgAATWF4QnVyc3RMZW5ndGgAAEZp +cnN0QnVyc3RMZW5ndGgAAAAATWF4T3V0c3RhbmRpbmdSMlQAAABUYXJnZXROYW1lAABUYXJnZXRB +bGlhcwBUYXJnZXRBZGRyZXNzAAAAVGFyZ2V0UG9ydGFsR3JvdXBUYWcAAAAAQXV0aE1ldGhvZAAA +U2VuZFRhcmdldHM9QWxsAENIQVBfQQAAQ0hBUF9JAABDSEFQX0MAAENIQVBfTgAAQ0hBUF9SAABE +aXNjb3ZlcnkAAABOb3JtYWwAAE5vbmUAAAAAQ1JDMzJDAABDUkMzMkMsTm9uZQBOb25lLENSQzMy +QwBDSEFQAAAAAENIQVAsTm9uZQAAAE5vbmUsQ0hBUAAAAE5vdFVuZGVyc3Rvb2QAAABJcnJlbGV2 +YW50AABSZWplY3QAAE5vAAA1AAAAAAAADAAAAAABAAF8AAwBAAAAABAAAAAUIAYKWAAAAxUOQAAA +H/wAAB/8AAAf/6eIH/+niCAGE/AgBhiwIAdhkCAHYZAgB8AAIAgQQCAIQAAgCMAAIAjAACAJBvAg +AqRsIAkHUCAGFEAIAAAAH/zgdCAIwFAoAAAAAQAAAOAAAAAf/44EAAgAAB//l3Af/5YoH/+WNP/9 +//8AmJaAAACAACACszwgCMDgH/+WRCAIwTAgAo0QAAAIBgAACAAABAAAAAD//yAJCJAD/9AAABAA +AABAAAAf/5ZgAFAH/yAJCRAgAqyQAAAQAADAAAAAAA//ACAAAAAP//AgCMFQ//9AAB//lZAgCMGQ +AAAf/h//ljjXaqR46Me3ViQgcNvBvc7u9XwPr0eHxiqoMEYT/UaVAWmAmNiLRPev//9bsYlc175r +kBEi/Zhxk6Z5Q45JtAgh9h4lYsBAs0AmXlpR6bbHqtYvEF0CRBRT2KHmgefT+8gh4c3mwzcH1vTV +DYdFWhTtqePpBfzvo/hnbwLZjSpMiv/6OUKHcfaBbZ1hIv3lOAykvupES97Pqfa7S2C+v7xwKJt+ +xuqhJ/rU7zCFBIgdBdnU0Dnm25nlH6J8+MSsVmX0KSJEQyr/l6uUI6f8k6A5ZVtZw48MzJL/7/R9 +hYRd0W+ofk/+LObgowFDFE4IEaH3U36CvTryNSrX0rvrhtORIAKLcCACiJAgAoxwIAKMACACkJAf +/5iAIAkKICACi1AgCMHQIAjCED/////P////IAKLfCAJCkBnRSMB782riZi63P4QMlR2IAkKYCAJ +CoAgCQqgIAkKwCAJCuAgApC4IAKKwCACjCwgAotsIAjCUCAJCwDAAAAAIAkLQAAAIAAgCMKA4QAA +ACACixAgCMLQIAjC8CAIw4AgCMMgIAjDUB/83gAgCQfQIAkIMCAJC4AgBVgAGgAAACAJDDAAD0JA +IAACmAACAAAgAovQIAkL4AD///8gAuVoIAjEoAQAAAiBAAAAAABIAAwAAAAgCMVAIAKLaAAAQAAg +AueYIAKKRCAIxaAgCMVwIAjGACAIxdAgAwYEIAjGMCAJDGAgCMZgIAjGoCAIxwAgCMeAIAjG0CAI +xzAgAAAAIAMC9CAIymAgBhP0CgAAACAC1ewgAqg8IAKlgAAAwAAgCQlQIAkJsCAIy/ACAAAAIAjM +gCAIzUAf/5RwIAYSAAAP/AAAADAAIAjNcCAIzgAgCM6gVQAAAAAAD/4f/5YwAAAMIPAAAAAgCM7Q +IAMvtB//lqAf/41wIAKLICAIzyAgCM9wH/+VhCAI0DAgCQ0AIAjP0CADGnAgCNCQIAjRACAI0VAg +CQ2QIAjRkCAI0gD/9///H/+VmCAJDdAmAAAAIAjSYB//liQgCNLQIAYXMCAI01AgBhbwIAkOUBeQ +AAAgBg9Af////yACgADAAAABIAjVMCAI1ZCAAAAAIAjTsCAGFkAAAFAAFLAAAIAAAAQgAy0YH/+P +OCAI1KAVoAAAAACP/iAI1NAWoAAAIygVACCgAAA/8AAAI6AAAAP/AB8gBhb6IAjT8CAI1EAgCNXQ +//8AABAAAAAgCNYgIAjWgA4AAAAgCNagKgAAACADLZQgCNbAIAjXECAI2VAf/5ZoIAjYoCAI2QAg +CNdwIAjX4CACieQgCNhA4QGOACAJDpAAAZEMIAkO4CAJDxD///P/4QIWAOECGgD//8j///8X//// +H/8AAhkcAAIZfAACGZwf/5ZA///x/wACGqQAAhooAAIaqAACGjQAAhq0AAIaMAACGrD///f/AAD/ +6eECDgAAABOHIAKAICACgFAgAoCAAABADQAA//cAAA9CAAD/9QAA//AgCNoQIAjZsCAI2eAAAAwA +AAAYAAACEDQAACBAAADEEAAAwAEAAMggIAjaQAAAxAD+AAAAAF/2pwCyN8dAAAAAHf///2IAAAAA +AMQwIAkPYAAAxDEgCQ8wAADoACAI2pAgCNrQIAjaYAAAyAAgCQ+AAAAnECAJD7AAAMRFIASK0AAA +yBAAABABAAAgfAAAMgDhAF4AAAJJ7wAAzAAgBhCMIAKAsCAI2wAgCNuQIAjbMCAI22D//7//IAjc +AB//luAAHoSAAAGGoP/he4AABJPg//tsICAI3DAgCNygIAjc0CAI3QAgCN0wIAjdYCAI3cAgCN2Q +AAIQCOD//gAgCN4QIAkP4CAJEBAgCRBAIAkQcAAAEBAAAFAQ4QIYAAAAf/0AABAR4QIXBOECFwAA +AAwJ/wAA/wAADA4AAAwMAAAMC9////8AAAwKAADAEAACYloAAMMwIAKAwBAQAAAgEAAAABAHYP/v ++J8e/gAA4QIYDPAAw3Af/44AIAKA8AACEODhAhIAAIAAAAAAEgAAAhUAAAATiAAAIAEf/5VwHc1l +AO////8gAoEgAADDUPf///8gAoFAgH////+Af/+//////z///wAHoSD/wAA/IAjeQAAAF3AgCRDw +IAkQoCAJENAgA5voIAkRICAJEUAgBhHkH/+WLOEAegAgCN5wIAjekCAI3rAf/5SU4QB+AB//lcQA +APP/BAAAAB//mJAUAAAAIAOjRB//o1AgCN9Qg/+3AIP/tiAgCRFgH/+keDAAABAgCRGgIAkSAB// +jywgCRIw4QH+AB//kfwiIiIiH/+l9CAI36AAAAy8AACJBiAI39DgAAkkAJwAACAI3/AgCOBAAAIE +wOEAjgAAAJaAAACWQCAGFAAAAJagAACWYOECACwAAeAA4QGSAAAB4wAf/5ZIIAjgYCAI4JAAABkc +H/+kkAAP//8f/6REH/+PPOEBlgAf/5WsIAYWsAAAYAAgBha6AAAZCgAAg/8gAoF4CFABAADAAAQf +/6X4IAXniCADy8QgBedM3q2+/xrAAAAgBhW4AAD/6iAGFsAAAAgUAACIAB//lLwgA+F4OAAAADAA +AHQf/4QQIAKBgCAI4MAwAAAIMAAADDQAAAjQAAAAAACJFDsAAAg0kAAAADAAAP8H//8FXUqAIAPn +oAAYAAAAOAAAIAkS4AYAAAAgA/V0+AAAAAH//+cAAcAAIAAAgAQAEAAf/5Sk4QGaAOEBmkDhAZo8 +4QGaOOEBmjThAZowgAAAA4AAAAIAAIbd//z//wABAADhAQ4AAAAVsB//ljwf/47QH/+PUCAEA1Ag +CRhQIAkWACAJFkAgCRfwIAkYICAJFnAgCRawIAkW4CAJFyAgCRdQIAkXkCAJFdAP///w//AAAB// +pKAgBBKgIAkZUCAJGYAgCRjwIAkYkB//lJwAACMoH/+ShAAA/4AgCOIw//v//+EB4sCQAADw/P+A +7yAI4oAgCOLAAAD4AAACAQwAAgEIj////wAA8AAf/5W44QGYACAI4xAgCONgIAjjkCAI49DhAN4A +AAIDCAACAgD///AA4QDuAB//llD//3//AADgAAAA/AAAAgMEAAERHAABERgAEAgAgAAIAB//laAA +AgEE///AAAAA//4AACWAAAIDAB//lbDg/+LAIAkZsCAJGkAgCRpwIAkakCAJGiAAAP/zIAjkICAJ +GrAgCORAIAka8AAAKjAAAP/4AAD/8QAA/48AAFK1AABICgAAj4IAAI+GAAA4AAAAj4oAAOM/AACD +riAJGtAgCORg///PvwAAEEAgAoHQIAjkkCAJGxAAAP/7IAKB4B3/8O8AAAoAIAjk0P//3/8gAoIQ +IAjlcCAI5UAgCRtAAAIWCH8///8AAPn/AAD+/wAA/8AAAP8/IAkbkCAI5QAgCRxAIAkb8OAABgAf +/5NwH/+PBAAC//8AAJxAIAkSgCAI5bAgCOYQAACAwgAA/gAgBG8kIAjm0AAAIQAgBHf8IAYQmCAG +EKggBhC4IAYQyCAGENggBhDoIAYQ+CAGFCAgCOcAAAGQ+CAI50AgCOewIAjn4OECFiQBMPhAIAjo +ECAJHRAgCOiQIAjoUOECAAQbAAAAAAMAAiAI6SAAJiWgAmJaAAX14QAgCOjQIAjpsCAI6XAgCOlA +IAjp0B//powgCOogBAEACAAAGRQAAN6tH/+kPCACgyAAAIMAIAjsoBAABQ3uAAAAAcCAAAkAAAAA +AIIAIAjrwCAI7BAgCOxQEAAHAiAI7WAAAPz/IAjt4AAFAAIgCO4QIAjuMCACg3AgCO5QIAOxCCAD +rjAgA7BUIAjucCAGFCgA/8AAEgAAACAEx6ggCO8QIAju0CAI71AgCO+wIAkeQCAI8NAgAoqgIAjw +8CAI8AAgCPBgAP///AAAEDb//+//IAKDoB//pIQgA/GcAAAIUCACg6gyAAAAAAAIQAD///oAAIAF +3q2+74GAAAAAAIP9MAAAHDAAAAQwAAAUAAD/7//+//8f/6U0IAKDsAD/8AAAKAAAIAjxMDAAAAAw +AAA0AACAASACg/AAAIACEAAFEJkAAAA0AAAAIAke8CAI8XAAGQAAIAjxwCACjRgAABshAACABzOQ +AAAf/5QMAxUAAAUAAACD/wAbIAjyMCAI8oAAAZGsIAVbjCAI8uAgBhQsCwAAACAI83AgCPPgIAj0 +UCAI9IAgCSDAIAkhYB//lwAgBE9E4QAOAOEAEgAf/5QYAAE4gAACJxAgCRygf///Dx//l2jhAC4A +/AD//+EAlgDhAJoAAAAJ/wAAsAAf/5aYIAKEQB//lfThABIE4QASCOEAEgzhABIQ4QASFBEAAAAf +/AAAIAj1ACAJIsAAAZSPAAGUz///7/ggAoRgH/+VECACh1Af/5XAAAJJ8B//lbQf/5UwIAKIIB// +jhQgCPbAH/+WcCAI+BAf/5RkAD///wAA//0AAP/VAADql8IAAA4F3AEAA/8AACAI+HAgCPiwIAj5 +ACAI+UAgCPmQIAj50B//onAADwP/AxEAAB//l1T9///QAAAZAOECAgDhAoIAAAQF7uECAQThAeIA +H/+V3OAACQgD6AAAH/+WpAAAeQQf/5XgACf//wAAdgAf/5SIH/+WgB//lewgBoAAAAAUACAGgRAg +Bq6gIAbu8CAGhmAgBoVQIAaEQCAGgzAgBoIgH///8B//o3AgAopwH/+kiAAAGdQf/6aESQAAACAJ +K4AgCSrQIAkrMB//lQwf/5XQH/+V2OEAdgDhAHIA///wDx//laQgCQHwIAkCUB//lYggBhY4QAAA +BBSQAAAf/6Q4/+gP/wAQgAAgCQOAIAW+bCACiHAByEAG4QGZ4AAAflAAAH5AAAB+GCAFzeQf/5WA +IAKN6CACjewgAo3wIAKN+ABQIAbhAZoMH/+VPABwIAb/4AAAAAIgBiAJA6DhAZoE4QGaCAAEIAYg +CQPQH/+UUOAAAQDf//4AH/zAAMAAAAXhAd4AIAXg5B//lbwgCQQAH/+WyOEAVgAgCSwA/+///+EB +lNAgCQQQH/+PNCAJBFAgCQSQH/+WnCAGEiQgAot0IAktACAJLbAgCSwwIAkscCAJLjAgCS1QIAks +sCAGEBQf/5X8IAkFMCAF4hwf/5ggH/+nPB//p1Qf/6dsH/+Z4B//p0Af/6dYH/+ncB//lrQf/5iw +4QAxAAQAAAEAACHBIAkFYB//jvz//H//IAkFkB/84YAgB8AAH/+OgJ////8f/5Q0AwAAAL//8P8g +CS7wH/+WACAGFDAf/494/w///x//jhB/8AAAAB///2wQBIMoKCIQ6yISKdAEgAALgACKMsunwLD9 +/gId7wwFAG0IDXrADQqKFOSgHWXYIQAAY//retAMtLvwABwNpKodAACxuwoaFGWv99owW7dxijfx +QiAN4AQFAPtEABWgCxUA/IBoHaANFQBbtimKN8efmaCUN1uygiQ2DiQ2DyQ2ECQ2ESQ2EiQ2EyQ2 +FCQ2FSQ2FiQ2FyQ2GCQ2Gf33mgWgClUA+gYCHeA9BQBY1eYkNAQkNAUkNgIkNCAkNCEkNCIkNCOU +OZQ6lDuUPCQ1GuQ1GylQBIAAWANe0Q9sEAiEKBz7vC0gBCRCES4iAP5AsBXgClUA9IoQFaA7BQBY +1dIpIAX6QEgVoHglAPkABWrnNQEAya38Y2CBUAsVACU8/gW1Odog7PusGtgEgABbqOjAINEPHPuq +LSAEjiCPLvR/wBXgCBUABYU59CAGFaAKVQD0ICYV4DsFAFjVuxb7oSpiF2Sgb/pAaB2gC4UA7RwQ +KmAEgABbqPzv+5sVAkGAAI4uwNCdoQ/uAp6gHPuXLWYX6RIEKl8CgACsu+m2ACGUhQAAiif6ACId +4AwFAPtEABWgDRUAW7XW0qDRD8Ag0Q/AINEPK0wY6iQACWAEgABbu3hj/02xq+wkAAlQBIAA62YX +IlhhAABbu3Jj/zUAAABsEBYc+36NIC4gBY8wKDAF9CAmFaAKVQD4IAYVoDsFAFjVjRf7dxb7dxX7 +dxr7ePpg6BXgDzUA/fbsBeGOBQD8EkIdoJgFAOuyDiIMeQAA/IIgElACBQBuQgmKOigwBYqofIEj +0Q8AAAAkMAX4gAjkIgCdACoyCiqiCHxBVSoiCFgPBcAg0Q8AKaIYrr4NmQIpphgv5JIoMAV8icf7 +9rgFr5xVACw0BRz7Wxn7WyqgfSzCLSmSh8CA6OSRLmZCgADsmQgFfVSAAC0KgP0gAETwAT4AKaIY +rr4NmQIpphgv5JIoMAV8iZUs+pUsNAUc+0kZ+0oa+0Yswi0pkocqoH0JzBGsmfFACe/SAJ0ALQqA +/SAARPAE3gAAAC8qgK+ZjTCWFvYghhXgD0UA5RYKLu4CgAAP3QKdFSyQByqRLgwMQQDMEQyqAgWq +ApoYCeowmBvpFgklyAsAAOlmAADQwQAACgyKCUCICgiKCSCICgSKCQCICgCK6xwQKdAEgAD8AIId +oA0lAFuapsAg0Q8d+yKMPxj7ISnSLS3SJSiChy+gfe3KCAzOQoAA6YkIDVZCgADqiggH/DyAAC8K +gP8gAETwACYAKCqAqJn/YABGsGxVACzUkYigJRYa9iKGFeAMRQDmFhYsRgKAAAyIAigWFS+QBy2R +Lg8PQQD/EQ/dAgXdAi0WGAzqMPwjJhWgCQUA6RYbJcgLAADp5gAA2cEAAAscignAiAsYigmgiAsU +igmAiAsQiiscUPwAgh2gDSUAW5p4wCDRDy8qgK+ZwIAo5JGNMJYW9iCGFeAPRQDlFgou7gKAAA/d +Ap0VLJAHKpEuDAxBAMwRDKoCBaoCmhgJ6jAoFgspFgnpvQIg0MEAAAlgiAoMiglAiAoIigkgiAoE +igkAiAoAiuscECnQBIAA/ACCHaANJQBbmlpj/cEAbBAEKzAF9/WsBeAEBQD38gIdoJwlAP1gBcQg +lVUA9WAFhGCYBQD5YAZlIgCdAIk4InKK6jIJJIBxgACZoIs4mrGUOJQ5iTzIliySErDMLJYSKHJ1 +ijclMgD7QcgVoAsFAPivAAq13IUAWNERlDiUOZQ6lDuUPJQ9lD6UPyQ2ECQ2ESQ2EiQ2EyQ2FCQ2 +FSQ2FiQ2FyQ2GCQ2GSQ2GiQ2GyQ2HCQ2HSQ2HuQ2HyrYBIAA9mCmHaAMBQD6QWgVoA0VAFu0kost +sLv6QaYV4AIFANEPjj4tIhjH/Q/uAe42Dia4aoAAfLEulDp1uQmIPvEABn/QBRUAwCDRD9ogW1RC +HPqZKiIYKzAFDKoB+kMGFaCZJQB5udCJOCJyiu0yCSSAcYAAmdCOOJ3hlDiUOYk8yJYvkhKw/y+W +EihydYo3JTIA+0HIFaALBQD4rwAKtdyFAFjQ15Q4lDmUOpQ7lDyUPZQ+lD8kNhAkNhEkNhIkNhMk +NhQkNhUkNhYkNhckNhgkNhkkNhokNhskNhwkNh0kNh7kNh8q2ASAAPZgph2gDAUA+kFoFaANFQBb +tFiLLbC7+kGmFeACBQDRDwAAAAAAAAAb+mkc+mrt+moZ0ASAAFtULtowW1QQgjeCLiQ2EiQ2FvRi +ZhXgCwUA9GKmFeAMJQD8YoYVo2pFAPpAAEUwjAUAWNCr+nyCHaALBQD6QABFMIwFAFjQpiwqgPxA +AEY0bUUArS0k1AAk1AEk1AIk1AMk1AQk1AUk1AYk1Ack1Agk1Akk1Aok1Ask1Awk1A0k1A4k1A8k +xNwkxN0kxN6LPgW7AvphxhXgAgUA0Q9sEAgmIgcPAgAmYg4rYngDuAEEugHooQd5KASAACNifuz6 +OhpwBIAA+AAiHaAPBQDjuQEJ6ASAAPlPAAzwOwUA+QIAD/AKVQBY1Dnq+iYRhDmAABz6Jhv6LSqg +fSzCLSmygP2IABYwBxUA7JkIBXxQgAApkieJnimSEPk/4BXgADoAKZKniZ4pkhCwmeKyhiSAiYAA +gi9tmQeIInOBKSIsKMDQ4tQABoHJgADKKS4hBvoAoh2gOwUA7PoWGWgEgABY1BvRDwAAAPxAaB3v +/14AAAAAAAAAwCD//1ANr/71AB/6DS1iYO0WBCLY6QAA+iBGFeYa5QCq2i7xAi4VAo/w/iAGFeAp +pQD5oKYV4AxlAFjQQIYU+iBoHeYahQD6wABFMAxlAFjQOx/5/fnz9gXlrYUArW2dEyfUfyfUhfmv +ph3gDGUALNSC/7AmHeAOhQD/sAYdoAiFAPmvhh2opx0AKtR++7CGHaALRQAr1IP6IEgV5irlAKpq +WNAmiBMvajj+wABH+JQdAOmEjirQBIAA9RHmHaiZHQD5EaYd6JkdAPkRhh3gDgUA7vUCK1gEgAD/ +4AYVqNMdAPMTJh3onR0A+RLmHej5HQD/EsYd4AwlAP0TBh3gDjUA/sDGHaANJQBYIEJj/sQAAGwQ +CIQqG/nMGvnN8gACHeAM1QBtCA+xM+PCDnmBCoAAAKgae4oDY//pABz5xS4gBY0gJiBQ/kNIFeAL +FQD+IAYV53UBAOkiByP7+QAAD785nxX5IEgV4ApVAPggJhXgOwUAWNO5KyIV7CIXKlAEgABb/2nl +pAANAs4AACoiGsGE+wAMYqIAnQDAwOwmGiOUTQAAiifAsftEABWgDRUAW7PcLSIRZNANAioC+kJI +FeAMFQAL0AAsIhBkwAr6QkgV4AoFAAvAANogWAEhwCDRDwAc+YQqwhhkoU76QGgdoCsFAO0cECtg +BIAAW6bfZKEAH/mVji0oITAopQIsISwP7gKeoC0iF52iLKUDKFEGKyIVm6OLLC0gU/JKEBXnkwEA +7yBSLMuCgADsiBEO8QKAAP5wABGyu8EA6xYGL/kCgAD55gAP/5ONAPkGAAx03R0A6P8CBYdpgAD9 +8vgFoAsFAAvYAgzpAgk7AokW6PgCDM4CgAAJuwIZ+XWbpRv5dQmIApikK7J/GPlzmKcrslwoOif5 +YAW8IgCdACk6K/lgByRiAJ0AwND9QMYV4DsFAP3y1AWgClUAWNNkLQpyLSQFHPlK6hIEK18CgACs +u+q2ACOUdQAAiif6ACId4AwFAPtEABWgDRUAW7OK0qDRD8Ag0Q8rbBjqJAAJYASAAFu5LYsV7PlX +GVAEgABbpnHAINEPALGr7CQACVAEgADrJhojWGEAAFu5I2P/1bGt6iQAA1hhAADtxhgpYASAAFu5 +HWP/vRz5SP/8YA2gCwUAiEv8onAV4Pg5APjAAAcyiEEA7O4RDEPCgADo7gIP+wKAAO/uAg7vwoAA +Dt0CHvk7/6YADr/8mgAZ+TkrUQd5sSMe+TgMvREO3QIvUBMe+TMP/xEP3QL/pgAOv/wCAAAAAAAA +AAD98mAF7/+GAGwQCIQqG/keGvkf+A4iHaADBQD4QKYdoAzVAG0ID7Ez48INeYEKgAAAqRp7mgJj +/+mNICYgUCkiGpkQiCfApf3yJAWgOwUA+QBIFaB+FQD4ICYVoA8FAFjTDisiFewiFypQBIAAW/6+ +5aQADQJGAAAqIhrBtPtgD9KiAJ0ALSIRwMDsJhomgJGAAAIqAvpCSBXgDBUAC9AALCIQyMn6QkgV +4AoFAAvAANogWAB7YAD8AAAAABv43SqyGGShEPpAaB2gKwUA7RwQK2AEgABbpjhkoY4X+O6PLSgh +MCilAi0hLAf/Ap+gLiIXnqItpQMoUQYsIhWcoy8gUvxKcBXnswEA4yBQLduCgADnIgwsRwKAAPOg +ABc03R0A7jMRD/kCgAD75gAP/7ONAPsGAAxyd8EA6P8CA4XxgAD98aoFoAsFAAvYAgzpAgj4Auk7 +AgvOAoAACbsCGfjPm6Ub+M8JiAKYpCuyfxj4zZinK7JcKTon+WAEVGIAnQApOiv5YAXMYgCdAMDQ +/UDGFeA7BQD98YgFoApVAFjSvi0Kci0kBRz4pOoSBCtfAoAArLuasO8iAClwBIAA/fGCBaAKVQD6 +BgId4A0FAFjSssAg0Q8AALGu7CQACVAEgADuthgjWGEAAFu4hdog/fFeBaALBQBbpcpj/7kc+K3/ +/RwNoAsFAIhL/KJwFeD4OQD4wAAHMohBAOzuEQxDwoAA6O4CD/sCgADv7gIO78KAAA7dAh74oP+m +AA6//U4AAAAZ+J4rUQd5sU4e+JwMvREO3QIvUBMe+JcP/xEP3QL/pgAOv/yuAAAAAAArbBjqJAAJ +YASAAFu4YmP/bytsGOisASlgBIAA6CYaKVAEgABbuFxj/1YAAAAA/fEUBe/+2gBsEASFIBv4iB34 +iSQhMIosKNKc87ZoFeAGBQD6gABCd5oBAOhVDASB4YAAyySMJy/6wPZA5hWv+PUA6MYAJnCBAAAP +7gHmxgoncQEAAJ7Jnsj1IAZYkgCdAPUgBwkSAJ0Amiwr0kzuIhclgeGAAP/wogXgCgUAbQgpKPIj +LNKtqKgJiBGozIzHjM4pwnfumQ91UAUAACnCerCZKcZ6K9JMe6sCY//PliiWKZYqliuWLJYtli6W +LyYmECYmESYmEiYmEyYmFCYmFSYmFiYmFyYmGCYmGSYmGiYmGyYmHP3wqAWgClUA+gYCHeBdRQBY +0kL6oGgd4HoFAPpAph2gDAUA+mEIFaANFQBbshfqMgkqWASAAPwAAh2gDRUAW7IT0Q+ONuoiDCZY +IQAAm+HuxgIh+GEAAJ/D+mDGFe/8ngCJNOoiDCZAIQAAmJHpxgIh2EEAAJvD+GCGFa/8JgBsEAwr +ITeDJxj4NMBS8mHIFeAMFQD7CBYN4AQFACogBSgKkvlACOwgmVUAeaEFwCDRDwAAJSYULCYTLCYV +JCYSii7kJhYl6AUAAC0lN/FABx+SAJ0A0kDRD9ogW1GrHff5GfgeG/f9jy7/7/IFoYoFAPpgAEU/ ++OUACP8Bny4f9/MlpJIu4H0rsi0pkoMkpJHqIgAt3kKAAPsgAETyjAUA/iDGFeCLBQDtFgAnfDCA +APsgAETwABoArJn978YFoAtFAOwWAi1WAoAAC6oCmhEokAcukS4PAgAICEEAiBEI7gIP7gKeFA3q +MC0WBeQWByHICwAA6WYAANCBAAAKDIoJQIgKCIoJIIgKBIoJAIgKAIrqJAAI2ASAAPwAgh2gDSUA +W5dQ9EbkHaACBQDRDwAAAAAAAOokAAnYBIAAWBSqwCDRDwDaIFtRcMAg0Q8AAABsEASKIIQihyOF +IY4wBHsDC1sBC3sDq+urqhv33YgxBUkD+0AARXyAPQAKqhiqWgmpAQlJA6mIqHcY99YKVgOJMvjg +AEO6AD0AB3cYp6cGdgEGVgOmlqZEFvfQB6gD9oAAQjeAPQAERBiGM6R0CEgBCKgDqGamVRb3yYs0 +B0wD9qAAQrUAPQAFVRilRQxcAQx8A6y7HPfDiDWsu/tAAEV8gD0ACqoYBFsDqloLqwELSwOriBv3 +vIY2q4j44ABDugA9AAd3GAWoA6enCHgBCFgDqGYY97WNN4s4qGYY97SmRPdXAAt3gD0ABEQYpHQH +TAMGRgEGpgOm1qhm9qAAQrUAPQAFVRilRQxcAQx8A6y7HPeohjkEWAOsu/tAAEV8gD0ACqoYG/ek +qloIqAEISAOoaKuIBasD+OAAQ7oAPQAHdxinp4g6C3sBC1sDq4gb95oc95uriIs7qET3VwAMd4A9 +AAREGKR0B08DCEgBCKgDqLisiKhV/GGIFaUAPQAFVRilRQ9fAQ9/A6/MH/eNiD2vzP1AAEU8gD0A +CqoYBFwDqloMrAEMTAOsiBz3hh/3h6yIjD744ABDugA9AAd3GAWoA6enCHgBCFgDqMiviAevA/iA +AEI3gD0ABEQYiD+kdA9PAQ+vA6+IH/d5r4ioVf5gKBXlAD0ABVUYpUUEWAMIeAEISAOo/xj3cqj/ +r6r4YMgVrYA9AAqqGKpaBa8DD08BD18Dr4gf92uviKh3/+7WBeuAPQAHdxinpweoAwhYAQioA6i4 +r4gf92X4gABCOQA9AAREGKR0B0gDCKgBCHgDqOiviKhV/mCoFeYAPQAFVRilRQRYAwh4AQhIA6j/ +GPdYqP+vqvhhSBWtgD0ACqoYqloFrwMPTwEPXwOviB/3Uq+I+OAAQ7uAPQAHdxiIP6enB68DD18B +D68Dr4gf90uviPiAAEI5AD0ABEQYiDSkdAdPAw+vAQ9/A6+IH/dEr4ioVfnuhgWmAD0ABVUYpUUE +XwMPfwEPTwOvb6j/r6r/7noF7YA9AAqqGKpaBagDCEgBCFgDqMiviPjgAEO7gD0AB3cYiDOnpwev +Aw9fAQ+vA6+IH/cxr4j4gABCOQA9AAREGIg4pHQHTwMPrwEPfwOviB/3K6+IqFX+YagV5gA9AAVV +GKVFBFgDCHgBCEgDqP8Y9ySo//9AAEV9gD0ACqoYH/chqloFqAMISAEIWAOomK+IH/cd+OAAQ7uA +PQAHdxinpweoAwhYAQioA6jYr4j4gABCOQA9AAREGIg8pHQHTwMPrwEPfwOviB/3Ea+IqFX+YKgV +5gA9AAVVGKVFBFgDCHgDqP8Y9wuo/6+q+GEIFa4APQAKqhiqWgWvAw9PA6+IH/cFr4iod//uCAXq +gD0AB3cYp6cHqAMIWAOouK+IH/b/+IAAQjgAPQAERBikdAdIAwioA6jIr4ioVf5gKBXkgD0ABVUY +pUUEWAMIeAOo/xj29Kj//0AARX4APQAKqhiINKpaBa8DD08Dr4gf9u6viB/27vjgAEO6gD0AB3cY +p6cHqAMIWAOo2K+I+IAAQjgAPQAERBiIOqR0B08DD68Dr4gf9uKviKhV/mGoFeSAPQAFVRilRQRY +Awh4A6j/GPbcqP+vqv/tuAXuAD0ACqoYqloFqAMISAOo6K+I+OAAQ7qAPQAHdxiIM6enB68DD18D +r4gf9tGviPiAAEI4AD0ABEQYiDakdAdPAw+vA6+IH/bLr4ioVfntlAWkgD0ABVUYpUUEXwMPfwOv +b6j/r6r4YYgVrgA9AAqqGKpaBa8DD08Dr4gf9sCviPjgAEO6gD0AB3cYp6eIPwevAw9fA6+IH/a6 +r4gf9rr4gABCOAA9AAREGKR0B0gDCKgDqJiviPigAEK0gD0A9KsACv/49QAIfwOlRQ9fAg9PA6/u +H/atr+7/QABFPQA9AAqqGAhOA6paDq4CDl4Drt0e9qeu3fzgAEP7AD0AB3cYCF0Dp6cNfQINrQOt +zB32oK3MCK0D/IAAQjiAPQAERBikdIw1DU0CDX0Drcwd9pqtzAh9A/ygAEK1gD0ABVUYpUWMPA1d +Ag1NA63MHfaTrcwITQP9QABFPQA9AAqqGKpajDMNrQINXQOtzB32jK3MCF0D/OAAQ7sAPQAHdxin +p4w6DX0CDa0Drcwd9oWtzAitA/yAAEI4gD0ABEQYpHSMMQ1NAg19A63MHfZ/rcwIfQP8oABCtYA9 +AAVVGKVFjDgNXQINTQOtzB32eK3MCE0D/UAART0APQAKqhiqWow/Da0CDV0Drcwd9nGtzAhdA/zg +AEO7AD0AB3cYp6eMNg19Ag2tA63MHfZqrcwIrQP8gABCOIA9AAREGKR0jD0NTQINfQOtzB32ZK3M +CH0D/KAAQrWAPQAFVRilRYw0DV0CDU0Drcwd9l2tzI0g/UAART0APQAKqhgITAOqWgysAgxcA6y7 +HPZWqt2su6t3+kBoFesAPQAHdxinp6e7myMIWwMIqAMLewILqgOqmRr2TY8hnSCqmfiAAEJ4gD0A +BEQYiSKkdAhIAgh3A6dmF/ZGpJmZIqdm9qAAQrWAPQAFVRilRKT/nyHRDwAAbBAGiiCIISMWAApJ +CykmAOqbCnoYBIAAKIwBKCYBA9tS+wAARfVKGQDrJgEiBLmAAPKAAEUwTAUA5MwMBVBhAAD8YAe7 +ogCdAIsQWMwVJSwY+KBoHaAZBQBtmikpgAEqgAMrgALpgAAs5gKAAAiqEQq6AuyZAg1UAoAACpkC +6YYAJEARAADrVAABUCEAAFv9+C0SAOTeDAJ7AQAA7zMIB2kBAADtFgAh6JOAAMBgixAKbBGry+w8 +DArQBIAAWMv40Q8AAOUsGCnrkAAA9mBoHeAGBQDiEgAhICEAANpQ+kBoHeBMBQBYy+74oGgdoBkF +AG2aKSmAASqAAyuAAumAACzmAoAACKoRCroC7JkCDVQCgAAKmQLphgAkQBEAAOpEAArYBIAAW/3S +53zAIzAFAADiLEAj6p+AAGP/cesSACngBIAAWMvW0Q8AAABsEAyjRhX16yciECkiESkWBShwcytS +FSxQUPwhBhWgiAkA6BYOK1AEgABYy8od9eOKGCwSDhv14PrAAEUwMtUA4qQALmdCgAALywjtzAgF +2BMAACuyGSzAgOwWDyVQBQAAWMu8jxiOHytSFyxQWK/u98AAQzAPBQAvZAItcHPsFgkncAkAAK5E +8oAAQ3DdEQDtFg4rUASAAFjLrooZHPXHix6qaiKkAAy7CyywgJwf67IhJVAFAABYy6ePGY4fK1IZ +LFBgr+73wABDMA8FAC9kAi1wc+wWCidwCQAArkTygABDcN0ZAO0WDitQBIAAWMuZihoc9bKLHqpq +IqQADLsLLLCAnB/rsiElUAUAAFjLkY8ajh8rUhuv7vfAAEMwDwUAL2QCLXBzLFBo7BYLJ3AJAAD+ +gABCMN0BAONGCAboOQAA7RYGK1AEgABYy4Id9ZyKGxv1mYwWqmoipAALywvrsv0uZ0KAAA3MCCzA +gOwWByVQBQAAWMt3jRuMFytSHa3Mps72rhAVoA0FAO3kAiZgCQAArETjSggLYASAAFjLbRX1iaZE +GPWImByjRiJkAOtxNijoBIAA6AAFCPgEgAD+AKgd4A6lAP4ghhXv/GUAwJBtCB7asA67LQy/KK+q +qloqoADq1AAu0ASAAOSwDmboBQAAY//YAAAAAAAAACmkAXobLNsQbQgi7LAAJvP/AAAp4P/s5P8l +U/0AAOm0ACXYBQAA6rsJduv9AABj/9YAAC8QAPHhwA3gAgUA2RBtCAwokAGxIuSACmTIBQAAY//s +AAAAsWrrFAAJYASAAFjLPffqqgWgClUA/eqyBaA7BQDsFg0paASAAFjO/eJgeCFYBQAAq0QrYh+j +SuwkAAVQBQAAWMswjhzpEgUhWAUAAKtE8oAAQ3A61QAqZADpkhko6ASAAO4EBQjgBIAA/ASoHa/7 +ZQD8IIYVoA6lAMDwbQge3JAOmS0LmCiozKxcLMAA7NQALtAEgADkkAlm6AUAAGP/2AAAL6QBehss +2xBtCCLusAAm+/8AACzw/+70/yVT/QAA7LQAJdgFAADquwl26/0AAGP/1gAAKBAA8QHADeACBQDZ +EG0IDCqQAbEi5KAKZMgFAABj/+wAAACxausUAAlgBIAAWMr/+gCiHaA7BQDsEg0paASAAFjOwSss +AQtECBv1ECKwoANKCCqsAeuyKSlgBIAAWMrz7hIMITAFAACmRPKAAENwP9UAL2QA6XIZKOgEgADu +CAUI4ASAAPwIqB2v+2UA/CCGFaAOpQBtCB7YkA6ZLQuaKKqIqFgogADo1AAu0ASAAOSQCGboBQAA +Y//aAMDALKQBehss2xBtCCLvsAAmw/8AAC6A/++E/yVT/QAA7rQAJdgFAADquwl26/0AAGP/1gAA +KRAA8SHADeACBQDZEG0IDCqQAbEi5KAKZMgFAABj/+wAAACxausUAAlgBIAAWMrD+gCiHaA7BQDs +Eg0paASAAFjOhSssAQtECBv01CKwqANKCCqsAeuyKylgBIAAWMq37hIMITAFAACmRPKAAENwP9UA +L2QA6XIYKOgEgADuDAUI4ASAAPwMqB2v+2UA/CCGFaAOpQDA8G0IHtiQDpktC5ooqoioWCiAAOjU +AC7QBIAA5JAIZugFAABj/9gAL6QBehss2xBtCCLusAAm+/8AACzw/+70/yVT/QAA7LQAJdgFAADq +uwl26/0AAGP/1gAAKBAA8QGQDeACBQDZEG0IDCqQAbEi5KAHZMgFAABj/+yxausUAAlgBIAAWMqI +FvSf+gCiHaA7BQDsEg0paASAAFjOSeJgsCFYBQAAq0QrYi2jSuwkAAVQBQAAWMp87hIMIRAFAACi +RPKAAENwP9UAL2QA6XIXKOgEgADuEAUI4ASAAPwQqB2gAqUA/CCGFa//ZQD6IGgd4AoFAG0IHtiQ +ApktD5worIioWCiAAOjUAC7wBIAA5JAIZugFAABj/9IAKuQBfrs56uQACNgEgAAPAgDTD9MPbQgi +77AAJsP/AAAugP/vhP8lU/0AAO60ACXYBQAA6rsJduv9AABj/88AACkQAPEhkA3gAgUA2RBtCAwq +kAGxIuSgB2TIBQAAY//s4xINI1AFAADrFAAJYASAAFjKRvxgaB2gClUA/EBoHeA7BQBYzgmkIrIi +0Q9sEA4V9F4kIhCUHiZQSCdCByRAcytSE+dyDinQBIAA/MBoHaBEMQBYyjaXFRv0Thj0TuY6CAon +QoAAC0sICEQI9JAQFaA81QAspADrvQQlUAUAAOuyGSpgBIAAWMoppkorUhWEHvNAAENwBwUA52QC +JVAJAACaGCZQUCRAc6Oqmh/8wGgdoEQ5AFjKHRv0N4ofC0sLJLCA90AARTA81QDspAAlUAUAAOuy +ISpgBIAAWMoUpkiEGCkSDxz0MQSECPkAAERwClUA9wBGHeA7BQDtIhgiIAkAAFjN0YgeKIBy7SIY +JBppgADApf3oTAWgOwUAWM3KKSIYK1IXo0b8qxAVoZnhAOwWECTICQAA6RYJK1AEgABYyfod9BUq +EhAb9BGMGfrAAEUwPtUALqQAC8sL67L9LmdCgACtzCzAgOwWCiVQBQAAWMnuLxIQjhorUhmv7qbv +J/QCLSIYLFBg7BYRJ3AJAAD+gABCMd3xAONGCAboCQAA7RYLK1AEgABYyeAd8/sqEhEb8/eMG/rA +AEUwMtUAIqQAC8sLK7L9DcwLLMCA7BYMJVAFAABYydUtEhGMHCtSG63Mps0mUGjn1AImYAkAAKxE +40oIC2AEgABYycwY8+imRKNGImQA6AAFCKgEgAAFAmGVFBXz4i9QAJgd9iAmHeACBQDvFAAngNmA +ANkQbQgMKJABsSLkgAlkyAUAAGP/7AAAsWrrFAAJYASAAFjJtxbz1foAoh2gOwUA7SQAC2AEgABY +zXmxK6tEG/PPIrCwA0oI5hYGJVAFAADrsi0pYASAAFjJqo4d6RIFIVAFAACqRPKAAENwOtUAKmQA +7gQFBMgHAADpFgco6ASAAOmRlCjgBIAA/ASoHa/7ZQD8IIYVoA6lAG0IHtyQDpktC58or8ysXCzA +AOzUAC7QBIAA5JAKZugFAABj/9oAAAAnpAF6GyzbEG0IIuywACbz/wAAKeD/7OT/JVP9AADptAAl +2AUAAOq7CXbr/QAAY//WAAAvEADx4ZAN4AIFANkQbQgMKJABsSLkgAdkyAUAAGP/7LFq6xQACWAE +gABYyXgW85b6AKIdoDsFAOwSBiloBIAAWM054mC4IVgFAACrRCtiLwNKCOwkAAVQBQAAWMlsjh3p +EgchWAUAAKtE8oAAQ3A61QAqZADpkZUo6ASAAO4IBQjgBIAA/AioHa/7ZQD8IIYVoA6lAG0IHtyQ +DpktC58or8ysXCzAAOzUAC7QBIAA5JAKZugFAABj/9oAAAAnpAF6GyzbEG0IIuywACbz/wAAKeD/ +7OT/JVP9AADptAAl2AUAAOq7CXbr/QAAY//WAAAvEADx4ZAN4AIFANkQbQgMKJABsSLkgAdkyAUA +AGP/7OMSBiNQBQAA6xQACWAEgABYyTr8YGgdoApVAPxAaB3gOwUAWMz9pCKyItEPH/NWHvNWD90B +Dt0B/EMGFe/yngBsECaHN+MWQilQBIAA6hY/KcAEgADncg4qkASAAPRANOCQBQUA2lAZ8tuGjxPy +2ymSJSMyh6lmCWYRpjODN/JhyBXgGYUAeSED0qDRDxvzPyaw9NpA67I+K2AEgABYyRf2gABFMcuF +APpgAEXwPNUALKQA7DACJVAFAABYyRApMAKmmegSPyTIBQAAKRZBpJkpFkAllAAoghAZ8r4W8r+C +hymSJYiPgi4mYof5AABEdG1FAO0tCAxGQoAAqGb2wOgVoogFAAgrCCqw3CZiDiXUDyXUDiXUDSXU +DCXUCyXUCiXUCSXUCCXUByXUBiXUBSXUBCXUAyXUAiXUASXUACyw5PGBcA3gAwUAbQgMLLDlsTPk +wAdl2AUAAGP/7BzzDeoUACDoEQAAldCV0ZXSldOV1JXVldaV15XYldmV2pXbldyV3ZXeld8l1hAl +1hEl1hIl1hMl1hT1oqYV4DsFAPwmxhWgClUAWMycGPL7HvL9H/L7GfL4HPL77BY3INARAACVoJWh +laKVo5WklaWVppWnlaiVqZWqlauVrJWtla6VryWmECWmESWmEiWmEyWmFCWmFSkWAy8WBf4gxhWg +OwUA+CCGFaAKVQBYzIO0GvogaB3gDBUAW/yR/eXIBaAKVQD8JwYVoDsFAFjMeyoqgKpoK4Ao0w/x +YZAN4AwFAG0IDC2AKbHM5NAJZEAFAABj/+wAACsqqOtrCADQEQAAW/x//eWmBaAKVQD8JyYVoDsF +AFjMafxgaB2ja0UA6ysIANARAABb/HYiFjX95ZIFoApVAPwnRhWgOwUAWMxfKBIBIhwc+KMABDA8 +9QDozAwA0BEAAPsAAEU/iwUA66QYIJgxAADqrBkmQdeAACsKAFjIl/hAaB2gGQUA0w9tmikpgAEq +gAMrgALpgAAs5gKAAAiqEQq6AuyZAg1UAoAACpkC6YYAJEARAADqNAAJWASAAFv6byocHJWglaGV +opWjlaSVpZWmlaeVqJWplaqVq5Ws9UGmFeAAVgAAAAAAw8f5jwAOMAsFAFjIefhAaB2gCeUA0w9t +mikpgAEqgAMrgALpgAAs5gKAAAiqEQq6AuyZAg1UAoAACpkC6YYAJEARAAAtEgIuEgHuFhUpWASA +AO0WFinQBIAAW/pN+GBoHaAJRQDTD22aKSmAASqAAyuAAumAACzmAoAACKoRCroC7JkCDVQCgAAK +mQLphgAkQBEAACoSNfpgaB3kbEUADwIA/UAARTAcBQBYyEX95OYFoApVAPwnZhWgOwUAWMwHG/Jk +KhJADwIAI7D8KqwB67JAKeAEgABYyDoqEkHr8mgR4AUAAKyqKhZB9UAARTA91QD6KAYVoAwlAO2k +ACVQBQAAWMgv9+S+BaudxQD84DmkYgCdACvKHPrgOUxiAJ0AIjqAAnsILrDk/XyQFeXuEQAObggu +4IAutGT/fLAVoD8FAOsWPi7vAoAAD90B/XywFaPuIQAO3QINbQgt0IAttGUtsOb/kAAWMD7FAA7M +Aft80BWh3TEADcwC/MAARjAINQD9kBAVoAlFAOy0ZiXYEQAAbZpi6HkIBdgRAACziPMgAES1qgEA +qmoqoIAqtF8qkOQKKkWqaiqggCq0YCqQ5CyQ5QyqEf9ABAVzzCEADKoCqmoqoIAqtGEqkOUskOYO +qhH/QAQFMcwxAAyqAqpqKqCAKrRiKpDmIhI+++QqBaXKAQCsbCzAgCy0Yygg8yqgBCokevpPZh2l +mBEACWkI6ZCALEcCgADTD/hPBh3gOQUACYgBqG8v8ID+TyYd4BKFACoSQCs65Ot7CAlgBIAA6xY9 +JVANAABYx9otEkGzLq7epO8l9AAsco79wCAV4As1APwoJhXozLkA/WAKBiIAnQD8JsgVpGhFAPjg +AEQyiQUA+OAARPOCBQCiciIWPiaQ3yIg7CKU3CWEACWEASWEAiWEAyWEBCWEBSWEBiWEByWECCWE +CSWECiWECyWEDCWEDSWEDuWEDyD5gQAAlfCV8ZXylfOV9JX1lfaV95X4lfmV+pX7lfyV/ZX+JfYP +JfYQJfYRJfYSJfYTJfYU9eKmFeAKVQDyK4YdoDsFAFjLcBvx0Brx0Bzxzu3xzBDxgQAAleCV4ZXi +leOV5JXlleaV55XolemV6pXrleyV7ZXuJeYPJeYQJeYRJeYSJeYTJeYUJeYVLRYaLBYbKhYd+iOG +FeAKVQD8JugVoDsFAFjLWCocYPorgBXgDBUAW/tlwKX8JwgVoDsFAFjLUShKgKh4L4DU8eZADeAM +BQBtCAwpgNWxzOSQVGRABQAAY//s0tDRDwAT8bAmMCzaQOsyDCtgBIAAWMd7pkryepAV4DvVACuk +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 +AgAAAAAAAAcSAAAAAAAACAMAAAAAAAAPEwAAAAAAABAEAAAAAAAAHxQAAAAAAAAgBQAAAAAAAD8V +AAAAAAAAQAYAAAAAAACABwAAAAAAAMAWAAAAAAABAAgAAAAAAAIACQAAAAAAAwAXAAAAAAAEAAoA +AAAAAAgACwAAAAAADAAYAAAAAAAQAAwAAAAAABgAGgAAAAAAIAANAAAAAABAAA4AAAAAAIAADwAA +AAAAwAAaAAAAAADgABsAAAAAAQAAEAAAAAABgAAcAAAAAAHAAB0AAAAAAeAAHgAAAAACAAARAAAA +8tUSmPLVEpjy1RKY8tUSmPLVEpjy1RKY8tUSmPLVEpjy1RKY8tUSmPLVEpgDhRsYA4UbmPLVEpjy +1RKY8tUSmPLVEpjy1RKY8tUSmPLVEpjy1RKYAAAAAAAAAAAAAAAA//8ABQAGAAcACAAJAAoACwAM +AA0ADgAPABD///////8ACgAUAIwAggBkAFoAoACWAHgAbgBQAEYAPAAyACgAHgAKBM4EkgnOCZIC +sgRWBOIEpgO2BBoHsglWBl4CdgniCaYHTgI6CLYJGggWBiICxgRqAJYDegFyB3YAvgPeBPYEugRC +A6ICYgc6Bg4AggPKBC4AbgBaAyoBNgHqAz4HxglqAUoHEgWWCHoGwgH+BnICigNSBeYFvgjeAZoH +2gn2CboJfgeeCUIIogkGAV4HYgJOByYDFgEiBYIIZgWqCMoJLgiOAQ4FbgVaBUYG1ggqBjYCEgHC +BuoIPgDmBoYC2gR+Ap4EBgZKAiYIAgNmAKoDjgX6AEYB1gb+Bq4F0gGGB4oI8gMCCFIA+gUyAa4A +0gPyB+4AMgaaAu4FHgAeBQoAAAnECYgE2AScB6gJTAnYCZwIrAkQArwEYAFoB2wE7ASwAlgHMAPA +BCQDIAEsB7wJYAWMCHAGaAKABbQI1AnsCbAJOAiYB1gCRAEYBXgIwAkkBWQFUAggBiwG4Ag0AtAE +dAZAAhwAoAOEAcwG9AF8B4AISADwAMgD6AaQAuQFAATEBIgCqARMA6wEEAZUAmwHRAIwCAwGGACM +A3AAtAPUBDgDmAYEAHgAZABQAeADNAFABwgGuAH0A0gF3AGQB9AJdAeUCPwBVAccAwwIXAWgCIQB +BAU8BswCCAG4ANwGfAKUA/wH+ANcBfAAPAakBcgI6AL4BSgBpAfkACgFFAAUAAAEyQSNCckJjQKt +BFEE3QShA7EEFQetCVEGWQJxCd0JoQdJAjUIsQkVCBEGHQLBBGUAkQN1AW0HcQC5A9kE8QS1BD0D +nQJdBzUGCQB9A8UEKQBpAFUDJQExAeUDOQfBCWUBRQcNBZEIdQa9AfkGbQKFA00F4QW5CNkBlQfV +CfEJtQl5B5kJPQidCQEBWQddAkkHIQMRAR0FfQhhBaUIxQkpCIkBCQVpBVUFQQbRCCUGMQINAb0G +5Qg5AOEGgQLVBHkCmQQBBkUCIQf9A2EApQOJBfUAQQHRBvkGqQXNAYEHhQjtAv0ITQD1BS0BqQDN +A+0H6QAtBpUC6QUZABkFBQAACb8JgwTTBJcHowlHCdMJlwinCQsCtwRbAWMHZwTnBKsCUwcrA7sE +HwMbAScHtwlbBYcIawZjAnsFrwjPCecJqwkzCJMHUwI/ARMFcwi7CR8FXwVLCBsGJwbbCC8CywRv +BjsCFwCbA38BxwbvAXcHewhDAOsAwwPjBosC3wT7BL8EgwKjBEcDpwQLBk8CZwc/AisIBwYTAIcD +awCvA88EMwOTBf8AcwBfAEsB2wMvATsHAwazAe8DQwXXAYsHywlvB48I9wFPBxcDBwhXBZsIfwD/ +BTcGxwIDAbMA1wZ3Ao8D9wfzA1cF6wA3Bp8FwwjjAvMFIwGfB98AIwUPAAAACgCMAG4AlgB4ADwA +UACgAIIAZAAyAEYAWgAoAB4AFAAAAIcAaQCRAHMANwBLAJsAfQBfAC0AQQBVACMAGQAAIAKOLCAH +GqwgAo4wIAcgaCACjjwgByAYIAKOUCAHH2wgAo5oIAceLCACjnggBx4EIAKOgCAHHdwgAo6UIAcd +tCACjpwgBx2MIAKOsCAHIRwgAo64IAcabCACjrwgBxnwIAKOxCAHGbggAo7MIAcZgCACjtggBxlI +IAKO3CAHGRAgAo7oIAcY2CACjuwgBxooIAKO9CAHGKAgAo78IAcYaCACjwQgBxZ4IAKPDCAHGDAg +Ao8YIAcX+CACjyAgBxfAIAKPKCAHF4ggAo8wIAcXUCACjzggBxcYIAKOBCAHFIAgAo9AIAcUSCAC +j0ggBxQQIAKPUCAHE9ggAo9gIAcToCACj2ggBxNoIAKPcCAHEzAgAo94IAcTCCACj4QgBxLgIAKP +kCAHErAgAo+oIAcSiCACj8QgBxJgIAKP1CAHEjggAo/kIAcSECACj/QgBxHoIAKQBCAHEcAgApAU +IAcRmCACkCQgBxFwIAKQMCAHEUggApA8IAcRIAAAAAAAAAAAIAKQSCAHEAggApBMIAcP2CACkFQg +Bw+oIAKQYCAHD3ggApBkIAcPSCACkGggBw8YIAKQbCAHDvAgApB0IAcOyCACjhAgByNgIAKOGCAH +IowgAo38IAch1CACjiQgByEkAAAQISBCMGNAhFClYMZw54EIkSmhSrFrwYzRreHO8e8SMQIQMnMi +UlK1QpRy92LWkzmDGLN7o1rTvcOc8//j3iRiNEMEIBQBZOZ0x0SkVIWlarVLhSiVCeXu9c/FrNWN +NlMmchYRBjB212b2VpVGtLdbp3qXGYc499/n/tedx7xIxFjlaIZ4pwhAGGEoAjgjyczZ7emO+a+J +SJlpqQq5K1r1StR6t2qWGnEKUDozKhLb/cvc+7/rnpt5i1i7O6sabKZ8h0zkXMUsIjwDDGAcQe2u +/Y/N7N3NrSq9C41onUl+l262XtVO9D4TLjIeUQ5w/5/vvt/dz/y/G686n1mPeJGIgamxyqHr0QzB +LfFO4W8QgAChMMIg41AEQCVwRmBng7mTmKP7s9rDPdMc43/zXgKxEpAi8zLSQjVSFGJ3cla16qXL +laiFifVu5U/VLMUNNOIkwxSgBIF0ZmRHVCREBafbt/qHmZe451/3fscd1zwm0zbyBpEWsGZXdnZG +FVY02UzJbfkO6S+ZyInpuYqpq1hESGV4BmgnGMAI4TiCKKPLfdtc6z/7Hov5m9iru7uaSnVaVGo3 +ehYK8RrQKrM6kv0u7Q/dbM1Nvaqti53ojcl8JmwHXGRMRTyiLIMc4AzB7x//Ps9d33yvm7+6j9mf ++G4XfjZOVV50LpM+sg7RHvAAADAEAAAwEAAAWQgAAFmkAAGUMAAAECQAABAwAAAQPAAAENwAAHss +AAB7NAAB4owAAeaMAAHqjAAB7owAAfKMAAH2jAAB+owAAf6MAACNzAAAfnQAAI/cAAGRWAAAj/wA +AHUcAAB1GAAAdRAAAHfgAAB35AAAd/QAAZw8AAEQdAABEIQAAJQIAACYXAAAlgwAAJYUAACWIAAA +liwAANAoAACQCAACENwAAjDcAAJQ3AACcNwAAZBUAABgHAABoNgAAZCQAAB34AAAd+QAAHf0AAB5 +eAAAefgAAZQEAAHjwAAB58AAAevAAAHvwAAB88AAAffAAAH7wAAB/8AAAZQMACEACQCBAEEAIQAJ +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 +4ogIAzAFAAB9awJj/6oikllkIJsVz+yMEPX/4h2gCgUA8AEQDaAGBQAAwMEk1Aws1A0m1CIv1HaY +35fc86FoFe+CBQAi1CAi1CGC3qN3I5JZ4ogIBVP9AADr1S4jMAUAAONrS3ZgBQAAIpKfLZKmomIJ +IxED3QjzoAYVoAPVAPOghh3gA4UA49QFLX0OAAAqUH4kTAHlr5FiqAUAAG0IDCpQfrFE5a+BYqgF +AABj/+woklrLivWbigXgBgUA+ADiHaAH5QBtCCUskqArkqasbAnNEa27nLAutA0otAwntAQqklrl +tS8jMAUAAHprAmP/08Ag0Q/Y4P/8TA2gBwUAAGwQBsCgW5AtEs5P0w+iqSiSgGeAC20IBSqSgGeg +AmP/88ChW5AmoqkrkoBnsA1tCAUskoBnwARj//MAAPud5AXgChUA/Z3iBaANBQD/nz4F4A4VAFum +jR/OVxPOLhjO6R7NuSkykioykSsykC420S420y421S421ywyjyg20Cg20i82zy821C0yji023i8y +lCgyk63MLjKYLTKXLDbfrLsrNuCrqiwylSo24aqZKzKWKTbiqYgqMqAoNuOo/ykyoS825ygyoq3/ +Lzbor+4uNuSuzCw25i8ypq3MLjKnLTKoLDblrLsrNumrqiwyqSo26qqZKzKqKTbrqYgqMqwoNuyo +/ykyrS827a/uKDKwLjburt0tNu8fzcGtzCw28C82zh7OJ6y7Kzbx/nrGFaANBQAtNt2rqio28qqZ +KTbzqYgoNvRbpk4rMtcvMtYPAgDzb+AVr4gFAOgiAQ1uQoAAotp680gpMtQPAgDLn+o21y1YBIAA +HM2RLjLV8iBmFaAKVQD6IAYV4IgFAPwgJhXgCwUA+CBGFaANFQBbqNjiNvUhAKGAAMAg0Q8AAAAA +//8MDaACBQDHJNEPbBAEE881+5piBaAEBQD3noIFoAcVACSmgSSmgySmgCSmghvN1ygwdf2bxAXg +3lUA/MsIFaAZBQDppookfKKAAA7MKB7N3Q3MLC+ywA7/AQ/PAi+2wC2y4A7dAQ3MAiy24Cuy4MCg +W4+nFc3IEs3JGc54Ba8IKfaBGM8oKPaCJPaD8/AGFaAKFQBbj56lqiSmgRvN2iumgiSmgyKmgFv+ +Quah1W0QBIAAHc19LgoIL9KPDw9DLzR0LNKKG85S/4YADjAIBQD9sUYVoImFAG2aDQuJCySWQOSW +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 +7/+SAKWb92AEHe//agClnPeABhXv/0IApZ0n1ADRD6WeJ+UA0Q8AAAAAAAAAAAAAAAAAACACjaQM +wAACIAXtfCACjagIwAAIIAXtfCACjawgwAAMIAXtBCACjbAGwAA0IAXu2CACjbQIwAA4IAXtfCAC +jbgCwAA8IAXu2CACjbwIwABAIAXtfCACjcAIgABEIAXuBCACjcQYgABYIAXuBCACjcgYgABkIAXu +BCACjcwYgABwIAXuBCACjdAYgAB8IAXuBCACjdQYgAC4IAXuBCACjdgYgADEIAXuBCACjdwYgADQ +IAXuBCACjeAYgADcIAXuBCACjeQIgAEYIAXuBGNzb2NrX2Nsb3NlZDogc2l6ZW9mKHRjYl9mYy0+ +dS5vZmxkLm8uZm9pc2NzaV9jb25uKSBbJXVdLCBieXRlcwoAAAAAAAAAAAAAAAAAAAAAY3NvY2tf +ZmFpbGVkOiBjc2tfZmMtPmZsb3djX2lkIFsweCV4XSwgY3NrX2ZjLT5mbG93Y19zdGF0ZSBbMHgl +eF0sIHNlc3NfZmMtPmZsb3djX2lkIFsweCV4XSwgc2Vzc19mYy0+Zmxvd2Nfc3RhdGUgWzB4JXhd +LCBldnQgWzB4JXhdCgAAAAAAAAAAAAAAY2huZXRfZmluZF9sMnRfZW50cnk6IGRhZGRyIFslMDh4 +XSwgWzB4JTA4eF0sIGxvY2FsIG5ldHdvcmsgWyVkXQoAAAAAAAAAAAAAAAAAAABsMnRlbnQgWyUw +eF0sIGwydGVudC0+aWR4IFslZF0KAHJjIFslZF0sIGNza19mYyBbMHgleF0sIGNza19mYy0+Zmxv +d2NfaWQgWzB4JXhdCgAAAAAAAAAAAAAAAAAAAABjc29ja19mcmVlOiBzaXplb2YoY3NrX2ZjLT51 +LmNzb2NrKSBbJXVdLCBieXRlcwoAAAAAAAAAAAAAAAAAAAAAbG9naW5fcGFyYW1zOiBjb25uX2Zj +LT5mbG93Y19mb2lzY3NpX2Nvbm5fZmxhZ3MgWzB4JXhdCgAAAAAAAAAAAGxvZ2luX3BhcmFtczog +Y29ubl9mYy0+Zmxvd2NfZm9pc2NzaV9jb25uX2ZsYWdzIFsweCV4XQoAAAAAAAAAAABUQ1AgY29u +biBlc3RhYmxpc2htZW50IGZhaWxlZCAlZAoAAAAAAAAAAAAAAAAAAABpbm9kZV9mYy0+Zmxvd2Nf +ZmxhZ3MgWzB4JXhdLCBpbm9kZV9mYy0+Zmxvd2NfYnVmLT5maWZvLm51bV9ieXRlcyBbJXVdCgAA +AAAAAAAAAHVzZXJuYW1lIG1pc21hdGNoCgAAAAAAAAAAAAAAAAAAUmVjdmQgYW5kIENvbXB1dGVk +IGRpZ2VzdCBtaXNtYXRjaAoAAAAAAAAAAAAAAAAAYmFzZTY0IEVSUiwgJWQgbGVmdCwgd2l0aCAl +ZCBwYWQuCgAAAAAAAAAAAAAAAAAAYmFzZTY0IEVSUiwgJWQgbGVmdCwgd2l0aCAlZCBwYWQuCgAA +AAAAAAAAAAAAAAAAYmFzZTY0IEVSUiwgJWQgbGVmdCwgd2l0aCAlZCBwYWQuCgAAAAAAAAAAAAAA +AAAAUmVjaWV2ZWQgQXV0aE1ldGhvZCB2YWx1ZQoAAAAAAAB2YWxpZGF0ZV9rZXl2YWw6IGZsb3dj +X2ZvaXNjc2lfY29ubl9mbGFncyBbMHgleF0KAAAAAAAAAAAAAAAAAAAAdmFsaWRhdGVfa2V5dmFs +OiBmbG93Y19mb2lzY3NpX2Nvbm5fZmxhZ3MgWzB4JXhdCgAAAAAAAAAAAAAAAAAAAE5lZ28gRkJM +IFsldV0KAABLRVlfTUFYUkNWRFNMIFsldV0KAAAAAAAAAAAAAAAAAER1cGxpY2F0ZSBpc2NzaSBr +ZXkKAAAAAAAAAAAAAAAAc2VuZF9sb2dpbl9yZXF1ZXN0OmNvbm5fZmMtPmZsb3djX2lkIFsweCV4 +XSwgc2Vzc19mYy0+Zmxvd2NfaWQgWzB4JXhdLCBwYXJhbSBbMHgleF0sIHBhcmFtLT5zZXNzX3R5 +cGUgWzB4JXhdLCBzZXNzX2ZjLT5mbG93Y19mb2lzY3NpX3Nlc3NfdHlwZSBbMHgleF0KAAAAAAAA +AAAAAHNlbmRfbG9naW5fcmVxdWVzdDogdHhfbGVuIFsldV0KAAAAAAAAAAAAAAAAAAAAAGZvaXNj +c2lfcGFyc2VfcmN2ZF9wYXJhbXM6IGVycm9yCgAAAAAAAAAAAAAAAAAAAGZvaXNjc2lfcGFyc2Vf +cmN2ZF9wYXJhbXM6IHJsZW4gJWQKAAAAAAAAAAAAAAAAAFNlcSAjIG1pc21hdGNoIHN0YXRzbiA9 +IDB4JXggZXhwc3RhdHNuID0gMHgleAoAAHRleHRfcmVzcDogY19iaXQgWzB4JXhdLCBmX2JpdCBb +MHgleF0KAAAAAAAAAAAAAGxvZ2luX3Jlc3A6IGZsb3djX2ZvaXNjc2lfY29ubl9mbGFncyBbMHgl +eF0KAAAAAGxvZ2luX3Jlc3A6IGZsb3djX2ZvaXNjc2lfY29ubl9mbGFncyBbMHgleF0sIHJjIFsw +eCV4XQoAAAAAAAAAAABpU0NTSSBTZWMtcGFyYW1zIHJlY2VpdmVkaGF2ZSBlcnJvcnMhIQoAAAAA +AAAAAABUYXJnZXQgbW92ZWQgdGVtcC4gY29ubiAleCwgc2VzcyAleAoAAAAAAAAAAAAAAABMb2dp +biBGYWlsZWQhIS4gY29ubiAlZCwgc2VzcyAlZAoAAAAAAAAAAAAAAAAAAABsb2dpbl9yZXNwOiBz +ZXNzX2ZjLT5mbG93Y19pZCBbJXVdLCBjb25uX2ZjLT5mbG93Y19pZCBbJXVdIGxvZ2dlZCBpbgoA +AAAAAAAAAAAAAFByb3RvY29sIEVycm9yIGNiaXQgJWQgdGJpdCAlZCBjc2cgJWQgbnNnICVkCgAA +AGRyb3BfYWxsX3Rhc2s6IHJlcXVlc3RlZCBsaWR4IFsldV0KAAAAAAAAAAAAAAAAAGdldF9yZWZf +dGFzazogaXN0YXNrLT5mbG93Y19pZCBbMHgleF0sIGlzdGFza19mYy0+Zmxvd2Nfc3RhdGUgWyV1 +XSwgaXN0YXNrX2ZjLT5mbG93Y19mb2lzY3NpX3Rhc2tfbGlkeCBbJXVdLCBsaWR4IFsldV0KAAAA +AAAAAAAAcHJvY2Vzc190bWZfcmVzcG9uc2U6IGlzdGFza19mYy0+Zmxvd2NfYnVmLT5zY2hlZF9u +b2RlLm5leHQgWzB4JXhdLCBpc3Rhc2tfZmMgWzB4JXhdLCBpc3Rhc2tfZmMtPmZsb3djX2lkIFsl +dV0KAHByb2Nlc3NfdG1mX3Jlc3BvbnNlOiB1bHB0eHBsZW4xNiBbJXVdCgAAAAAAAAAAAHByb2Nl +c3NfdG1mX3Jlc3BvbnNlOiBkZWxheV9wcm9jZXNzaW5nLCBvcCBbJXhdCgAAAAAAAAAAAAAAAAAA +AABwcm9jZXNzX3RtZl9yZXNwb25zZTo6IHdyIG9wY29kZSBbMHgleF0KAAAAAAAAAABwcm9jZXNz +X3RtZl9yZXNwb25zZTo6IHRhc2sgZnVuY3Rpb24gWzB4JXhdCgAAAABjYWxsaW5nIGRyb3BfdGFz +aywgaXN0YXNrX2ZjLT5mbG93Y19mb2lzY3NpX3Rhc2tfbGlkeCAweCV4CgAAAAAAcHJjb2VzX2Rh +dGFfaW5fcmVzcG9uc2U6IGNvbm4tPmZsb3djX2lkIFsweCV4XSwgaXN0YXNrX2ZjLT5mbG93Y19p +ZCBbMHgleF0KAAAAAABERFAgZXJyb3IgZm9yIGNvbm4gWzB4JXhdLCBtYXNrIFsweCV4XQoAAAAA +AAAAAABzZW5kX2Fib3J0X3JlcTogY3NrX2ZjLT5mbG93Y190eXBlIFsweCV4XSwgY3NrX2ZjLT5m +bG93Y19pZCBbMHgleF0sIGNza19mYy0+Zmxvd2NfY3NvY2tfdGlkIFsweCV4XSwgdWxwdHhjaCBb +JXVdLCBidWZmZXJlZCBbJXVdCgAAAAAAAAAAAAAAAAAAAABpc2NzaV9oZHI6IGJhZCB0Y2Igc3Rh +dGUgdG8gcnggZGF0YSwgdGNiX2ZjLT5mbG93Y19pZCBbMHgleF0sIHRjYl9mYy0+Zmxvd2Nfc3Rh +dGUgWzB4JXhdCgAAAAAAAAB3cmhfZm9pc2NzaV9ub2RlOiBub2RlX3dyLT5mbG93aWRfbGVuMTYg +MiBbJXhdCgB3cmhfZm9pc2NzaV9jaGFwOiBpZF9sZW4gWyV4XSwgc2VjX2xlbiBbJXhdCgAAAAB3 +cmhfZm9pc2NzaV9jaGFwOiB0Z3RfaWRfbGVuIFsleF0sIHRndF9zZWNfbGVuIFsleF0KAAAAAAAA +AAAAAAAAcGVlcl9jb246IGNza19mYyA9PiBmbG93aWQgWzB4JXhdLCBmbG93Y19idWYgWzB4JXhd +CgAAAAAAAAAAAAAAAGZvaXNjc2lfY3RybDogc3Vib3AgWzB4JXhdLCBzZXNzX3R5cGVfdG9fZXJs +IFsweCV4XSwgc2Vzc190eXBlIFsweCV4XQoAAAAAAAAAAAAASW52YWxpZCBvcGNvZGUgMHgleCBp +biBjdHJsIHBhdGgKAAAAAAAAAAAAAAAAAAAAcnhfZGF0YS0+c2VxIFsweCV4XSwgcnhfZGF0YS0+ +bGVuIFsweCV4XSwgcnhfZGF0YS0+c3RhdHVzIFsweCV4XQoAAAAAAAAAAAAAAAAAAABjc2tfZmMt +PmZsb3djX2Nzb2NrX29mZnNldCBbMHgleF0sIGRsZW4xNiBbMHgleF0KAAAAAAAAAAAAAAAAAAAA +YWN0X2VzdDogZmxvd2NfZm9pc2NzaV9jb25uX2ZsYWdzIFsweCV4XQoAAAAAAAAAYWN0X2VzdGFi +OiB0Y2JfZmMtPmZsb3djX2J1ZiBbMHgleF0sIHRjYl9mYy0+Zmxvd2NfdHlwZSBbMHgleF0gdGNi +X2ZjLT5mbG93Y19zdGF0ZSBbMHgleF0sIG5wYWdlcyBbMHgleF0sIGZsb3djX3RwX3NuZF9tYXgg +WzB4JXhdCgAAAAAAAAAAAAAAAAAAYWN0X2VzdGFiOiBhdGlkIFsweCV4XSwgdGlkIFsweCV4XSwg +b3AgWzB4JXhdLCByY3ZfaXNuIFsweCV4XSwgc25kX2lzbiBbMHgleF0sIGNzb2NrLT5mbG93Y19z +dGF0ZSBbMHgleF0sIHRjcF9vcHQgWzB4JXhdLCB0Y2JfZmMtPmZsb3djX2lkIFsweCV4XSAKAAAA +AAAAAAAAAAAAAGNza19mYy0+Zmxvd2NfY3NvY2tfY29va2llIFsweCV4XSAKAAAAAAAAAAAAAAAA +AG5ldGlmX2RvX2RoY3A6IHdyLT5wYXJhbS52bGFuaWQgWyV1XSwgbDJkZXZfZmMtPmZsb3djX25l +dF9sMmRldl92bGFuZGV2IFsweCV4XQoAbmV0aWZfZG9fZGhjcDogcmwyZGV2X2ZjLT5mbG93Y19p +ZCBbMHgleF0sIGRoY3BfY3R4dCBpbml0aWFsaXphdGlvbiBlcnJvcgoAAAAAAABsM2luNF9kZXZf +Y29uZmlnOiB3ci0+cGFyYW0udmxhbmlkIFsldV0sIGwyZGV2X2ZjLT5mbG93Y19uZXRfbDJkZXZf +dmxhbmRldiBbMHgleF0KAAAAAAAAAAAAAAAAAABuZXRfbDNpbjRfZGV2X2NvbmZpZzogbDJkZXZf +ZmMtPmZsb3djX2lkIFsweCV4XSwgYWRkcmVzcyBhbHJlYWR5IHVzZWQgYnkgcG9ydCAlZAoAAAAA +AAAAAAAAAAAAAABuZXRfbDNpbjRfZGV2X2NvbmZpZzogIGFkZHIgWzB4JXhdLCBtYXNrIFsweCV4 +XSwgZ3cgWzB4JXhdLCByZWZfY250IFsweCV4XSBpbiB1c2UKAAAAAAAAAAAAAAAAAAB3cmhfY2hu +ZXRfaWZjb25mOiBsMmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBsMmRldl9mYy0+Zmxvd2NfdHlw +ZSBbJTB4XSwgaWZjb25mX3dyLT5zdWJvcCBbMHgleF0KAAAAAAAAAAAAAAAAAAAAd3JoX2NobmV0 +X2lmY29uZjogbDJkZXZfZmMtPmZsb3djX2lkIFsweCV4XSwgdW5rbm93biBzdWJvcCBbMHgleF0K +AAAAAAAAAAAAAAAAAAB3cmhfY2huZXRfaWZjb25mOiBsMmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhd +LCByYyAlZAoAAAAAAAAAAAAAAAAAbmV0aWZfaXBfY29uZmxpY3RfdGltZXJfY2I6IGwyZGV2X2Zj +LT5mbG93Y19pZCBbMHgleF0sIGluZGV2Y3R4dC0+c3RhdGUgWyVkXSwgaW5kZXZjdHh0LT5yZXRy +eV9jbnQgWyVkXQoAAAAAAAAAAG5ldGlmX2lwX2NvbmZsaWN0X3RpbWVyX2NiOiBsMmRldl9mYy0+ +Zmxvd2NfaWQgWzB4JXhdLCBpbmRldmN0eHQgWzB4JXhdLCBpbiBmcmVlIHN0YXRlCgAAAAAAAAAA +AGlmYWNlX2NtZF9oYW5kbGVyOiBmYyBbMHgleF0sIGZjLT5mbG93Y19pZCBbMHgleF0sIGZjLT5m +bG93Y190eXBlIFsweCV4XSwgcCBbMHgleF0sIGxlbjE2IFsldV0sIGxvYyBbMHgleF0KAAAAAABp +ZmFjZV9jbWRfaGFuZGxlcjpsMmRldl9mYyBbMHgleF0sIGwyZGV2X2ZjLT5mbG93Y19pZCBbMHgl +eF0sIGwyZGV2LT5mbG93Y190eXBlIFsldV0sIGwyZGV2X2ZjLT5mbG93Y19uZXRfbDJkZXZfZmxh +Z3MgWyUweF0KAAAAAGZvaXNjc2lfaWZhY2VfY21kX2hhbmRsZXI6IGwyZGV2X2ZjLT5mbG93Y19u +ZXRfbDJkZXZfZmxhZ3MgY2hhbmdlZCBmcm9tIFslMHhdIHRvIFslMHhdCgAAAAAAAAAAAGNobmV0 +X2wyZGV2X3VwOiBtYiBbMHgleF0sIGRlZmVycmVkLCBzdGF0ZSBbMHgleF0sIHBvcnQgWzB4JXhd +CgB2aWlkIFsweCV4XSBwb3J0IFsweCV4XSwgbWFjLWlkIFslMDJ4OiUwMng6JTAyeDolMDJ4OiUw +Mng6JTAyeF0gcnNzX3NpemUgJXUKAAAAAHZpIHR5cGUgWzB4JXhdLCBwb3J0IFsweCV4XSwgZmxv +d2Nfc2dlX2VxaWQgWzB4JXhdLCBmbG93Y19zZ2VfZXFpZCBbMHgleF0sIGZsb3djX3NnZV9lcWNy +ICV1CgAAAG5ldGlmX3NldF9tYWM6IG1iX3NjcmF0Y2ggWzB4JXhdLCBwb3J0IFsweCV4XQoAAG5l +dGlmX3NldF9yeG1vZGU6IGwyZGV2X2ZjLT5mbG93Y19uZXRfbDJkZXZfbXR1IFsldV0sIG1iX3Nj +cmF0Y2ggWzB4JXhdLCBwb3J0IFsweCV4XQoAAAAAAAAAAAAAAGNobmV0X2wyZGV2X3VwOiBsMmRl +dl9tYWMgWyUwMng6JTAyeDolMDJ4OiUwMng6JTAyeDolMDJ4XSwgZmxvd2NfbmV0X2wyZGV2X2Zs +YWdzIFsweCV4XQoAAAAAAAAAAGNobmV0X2wyZGV2X3VwOiBtYl9sb2MgWzB4JXhdLCBtYl9vcmln +IFsweCV4XSwgcmMgWyVkXQoAAAAAAAAAAABjaG5ldF9sMmRldl91cF9tYl9jYjogcmMgWyVkXSwg +cG9ydCBbJXVdLCBzdGF0ZSBbJXVdLCBjb29raWUgWyV1XQoAAAAAAAAAAAAAAAAAAGNobmV0X3ht +aXQ6IGwyZGV2X2ZjLT5mbG93Y19pZCBbMHgleF0sIHZsYW5pZCBbJXVdLCBMNENoa0Rpc2FibGVf +dG9faVZsYW5UYWcgWzB4JXhdCgAAAAAAAAAAAAAAAGNobmV0X3htaXQ6IHR4X2RsZW4gWyV1XQoA +AAAAAAAAY2huZXRfeG1pdDogYWxyZWFkeSBzY2hlZHVsZWQKAABjaG5ldF94bWl0OiBsMmRldl9m +Yy0+Zmxvd2NpZCBbMHgleF0sIG5idWYgWzB4JXhdIGluIGRlbGF5ZWRfcHJvY2Vzc2luZwoAAAAA +AAAAAGRoY3BfcHJvY2Vzc19jYjogbDJkZXZfZmMtPmZsb3djX2lkIFsweCV4XSwgZGhjdHh0LT5z +dGF0ZSBbJTB4XSwgZGhjdHh0LT5ydHJ5X2NudCBbJXVdCgAAAAAAAAAAAGRoY3BfdGltZXJfY2I6 +IERIQ1BESVNDT1ZFUiBzZW50LCBidXQgbm8gcmVwbHkgZnJvbSBhbnkgcG9zc2libGUgc2VydmVy +IG9uIHRoZSBuZXR3b3JrLiBSZXRyeWluZyBhZ2FpbgoAAAAAAAAAAABkaGNwX3RpbWVyX2NiOiBs +MmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBzZW5kaW5nIERIQ1BESVNDT1ZFUiBmb3IgZGhjdHh0 +IFsweCV4XSBvbiBwaWQgWyVkXQoAAABkaGNwX3RpbWVyX2NiOiBsMmRldl9mYy0+Zmxvd2NfaWQg +WzB4JXhdLCBESENQT0ZGRVIgcmVjZWl2ZWQgZm9yIGRoY3R4dCBbJXhdIHBpZCBbJWRdCgAAAAAA +AAAAAABkaGNwX3RpbWVyX2NiOiBsMmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCAgREhDUEFDSyBy +ZWNlaXZlZCBmb3IgZGhjdHh0IFsleF0sIHBpZCBbJWRdCgAAAAAAAAAAAABkaGNwX3RpbWVyX2Ni +OiBsMmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBkaGN0eHQtPmlwYWRkciBbMHgleF0KAAAAAAAA +AAAAAAAAAAAAAGRoY3BfdGltZXJfY2I6IGwyZGV2X2ZjLT5mbG93Y19pZCBbMHgleF0sIG5vIHJl +cGx5IGZyb20gZGhjcCBzZXJ2ZXIsIHRpbWluZyBvdXQKAAAAAAAAAAAAAAAAAAAAAHBbJXVdIGNo +YW5naW5nIHNwZWVkIGZyb20gJSN4IHRvICUjeAoAAAAAAAAAAAAAAHBbJXVdIGJjbTg0ODM0IGxp +bmsgc3RhdHVzIGNoYW5nZSBVUAoAAAAAAAAAAAAAAHBbJXVdIGJjbTg0ODM0IGxpbmsgc3RhdHVz +IGNoYW5nZSBET1dOCgAAAAAAAAAAAGh3X2NsNDVfdXBkX3NwZF9hZHYgJSN4CgAAAAAAAAAAcFsl +dV0gYXExMjAyIGxpbmsgc3RhdHVzIGNoYW5nZSBVUAoAAAAAAAAAAAAAAAAAcFsldV0gUEhZIE9W +RVJIRUFURUQgLSBmb3JjZWQgcG93ZXIgZG93biAodGVtcD0lZCkKAAAAAAAAAAAAAAAAAHBbJXVd +IGFxMTIwMiBsaW5rIHN0YXR1cyBjaGFuZ2UgRE9XTgoAAAAAAAAAAAAAAG1vZHVsZVsldV06IHBv +cnQgbW9kdWxlIGluc2VydGVkIGFuZCByZWFkeQoAAAAAAG1vZHVsZVsldV06IHBvcnQgbW9kdWxl +IHJlbW92ZWQKAAAAAAAAAAAAAAAAAAAAAG1vZHVsZVsldV06IHVua25vd24gbW9kdWxlIGlkZW50 +aWZpZXIgMHglMDJ4CgAAAG1vZHVsZVsldV06IGdwaW8gJXUgdHJhbnMgMTBHIDB4JTAyeCAxRyAw +eCUwMnggKGxlbmd0aCAldSkgY2FibGUgMHglMDJ4IChsZW5ndGggJXUpIG1vZHVsZV90eXBlIDB4 +JTAyeAoAAAAAAAAAAABjeDRfY3JfcGRvd25bJXVdOiBlbiAldSB2aV9lbl9jbnQgJXUKAAAAAAAA +AAAAAABpbml0X3BvcnRbJXVdOiAgbGluayBzdGF0dXMgMHgleCBtb2RfdHlwZSAweCV4IHZpX2Vu +X2NudCAldSByeF9sb3MgJXUgaHNzX3NpZ2RldCAldSBwb3J0X2NmZy5zaWdkZXQgJXUKAAAAAAAA +AAAAaW5pdF9wb3J0WyV1XTogIGxpbmsgc3RhdHVzIDB4JXgKAAAAAAAAAAAAAAAAAAAAaW5pdF9w +b3J0WyV1XTogIGxpbmsgc3RhdHVzIDB4JXgKAAAAAAAAAAAAAAAAAAAAaW5pdF9wb3J0WyV1XTog +IGxpbmsgc3RhdHVzIDB4JXgKAAAAAAAAAAAAAAAAAAAAaW5pdF9wb3J0WyV1XTogIGxpbmsgc3Rh +dHVzIDB4JXgKAAAAAAAAAAAAAAAAAAAAaW5pdF9wb3J0WyV1XTogIGxpbmsgc3RhdHVzIDB4JXgK +AAAAAAAAAAAAAAAAAAAAbmV3IG1vZHVsZSBuZXcgc3BlZWQgKHRlY2hfdHlwZT0lI3gpCgAAAAAA +AAAAAAAAY3JfbW9kdWxlX3N0YXR1c1sldV06IHR5cGUgY2hhbmdlZCBmcm9tIDB4JTAyeCB0byB0 +eXBlIDB4JTAyeCBzdHlwZSAweCUwMngKAAAAAABjeDRfY3JbJXVdOiByZXQgJWQgc3RhdHVzICV1 +IHhnbV9scyAweCUwOHgKAAAAAAB3YXRjaGRvZyBjbWQgaGFuZGxlciAodGltZSAldSBhY3Rpb24g +JXUpCgAAAAAAAABXQVRDSERPRzogZGV2aWNlIHNodXRkb3duCgAAAAAAAFdBVENIRE9HOiBieXBh +c3MgdGltZW91dAoAAAAAAAAAV0FUQ0hET0c6IEZMUiAtIG5vdCBpbXBsZW1lbnRlZCB5ZXQKAAAA +AAAAAAAAAAAAZmlsdGVyOiBwb3JncmFtbWluZyB0aWQgJXUgKGxlIHRjYW0gaW5kZXggJXUpLi4u +CgAAAAAAAAAAAAAAAAAAAGZpbHRlcjogcmVxdWVzdGluZyBjb21wbGV0aW9uLi4uCgAAAAAAAAAA +AAAAAAAAAEZDT0UgRnJlZTogc3RpbGwgeWllbGRlZCB3aGVuIGZyZWVpbmcuLi5mbG93Y19pZCAl +eCBmbG93Y19mbGFncyAleCAKAAAAAAAAAAAAAAAAcG9ydCAlZCBwcmlvciAlZCBzZWxlY3QgJWQg +cHJvdG9jb2xJRCAweCUwNHgKAAAAcG9ydCAlZCBzZXQgcGZjX2VuID0gMHgleAoAAAAAAABwb3J0 +ICVkIHNldCBwZ2lkXzBfNyA9IDB4JTA4eCBwZ19wZXJjZW50YWdlIDB4JTA4eF8lMDh4IG51bV90 +Y3Nfc3VwcG9ydGVkICVkCgAAAHBvcnQgJWQgc2V0IHBmY19lbiA9IDB4JXgKAAAAAAAARkNvRSBE +RFAgZmFpbGVkIDogb3hfaWQgMHgleCByeF9pZCAweCV4CgAAAAAAAAAARkNvRSBERFAgZmFpbGVk +IDogRGRwUmVwb3J0IDB4JXggRGRwVmFsaWQgMHgleAoAUFJMSSBSc3AgdGltZWRvdXQgOiBmbG93 +Y19pZCAweCV4IG94X2lkIDB4JXggcnhfaWQgMHgleCAKAAAAAAAAAGNhbm5vdCBhbGxvY2F0ZSBv +ZmZsb2FkZWQgZmlsdGVyIGNvbm5lY3Rpb24KAAAAAGNhbm5vdCBhbGxvY2F0ZSBvZmZsb2FkZWQg +ZmlsdGVyIElQdjYgY29ubmVjdGlvbgoAAAAAAAAAAAAAAAAAAAB1b1sldV06IHdyICVwIHdyLT5s +ZW5ndGggJXUgbXNzICV1CgAAAAAAAAAAAAAAAAB1b1sldV06IGYgMHglMDh4IGRzdF9jcGwgMHgl +MDh4IHNyY19jcGwgMHglMDh4IGltbWRsZW4xNiAldQoAAAAAdW9bJXVdOiBsYXN0IG1zcyAldQoA +AAAAAAAAAAAAAAB1b1sldV06ICFsYXN0IHdyLT5zY2hlZHBrdHNpemUgJXUKAAAAAAAAAAAAAAAA +AABpbnZhbGlkIGJ1ZmZlciBncm91cFsldV0gY29uZmlndXJhdGlvbjogbXR1ICV1IGx3bSAldSBo +d20gJXUgZHdtICV1CgAAAAAAAAAAAAAAAGZjICV1IHZmICV1IGdvdCBpdmY9MHgleCxyYW5nZTog +JSN4LSUjeCAoJXUvJXUgdXNlZCkKAAAAAAAAAAAAAABWSSAldSBjYW5ub3QgZ2V0IFJTUyBzbGlj +ZTogTm8gbW9yZSBzbGljZXMgYXZhaWxhYmxlICh1c2VkICV1LyV1KQoAAAAAAAAAAAAAAAAAAHBm +biAldSB2Zm4gJXUgd2l0aCBwb3J0IG1hc2sgMHgleCBjYW5ub3QgYWNjZXNzIHBvcnQgJXUsIHJl +dCAlZAoAAAAAAAAAAAAAAAAAAAAAcGZuICV1IHZmbiAldSBjb3VsZCBub3QgYWxsb2NhdGUgdmlp +ZCwgcmV0ICVkCgAAcGZuICV1IHZmbiAldSBjb3VsZCBtYXAgdmlpZCAgMHgleCB0byBmbG93Yywg +cmV0ICVkCgAAAAAAAAAAAAAAAHBmbiAldSB2Zm4gJXUgY291bGQgbm90IGFsbG9jYXRlIHV3aXJl +IGZ1bmMgJWQgbWFjIGFkZHIsIHJldCAlZAoAAAAAAAAAAAAAAAAAAAAAbWlpX2Fkdl9mY1sldV06 +IHJjYXBzIDB4JXgKAAAAAABtaWlfYW5yZXN0YXJ0WyV1XTogYWNhcHMgMHgleAoAAG1paV9mb3Jj +ZV9zcGVlZFsldV06IHJjYXBzIDB4JXgKAAAAAAAAAAAAAAAAAAAAAG1paV9saW5rX3N0YXR1c1sl +dV06IGJtc3IgMHglMDh4IHN0YXR1cyAldSB4Z21fbHMgMHglMDh4CgAAAAAAAABwb3J0X2NtZF9o +YW5kbGVyOiB1bmtub3duIHUuZGNiLnR5cGUgMHgleAoAAAAAAABwb3J0WyV1OjB4JTAyeDoweCUw +MnhdOiBwaHkgcmVzZXQgbm90IGF2YWlsYWJsZQoAAAAAAAAAAAAAAAAAAAAAcG9ydFsldToweCUw +Mng6MHglMDJ4XTogdW5rbm93biBhY3Rpb24gMHgleAoAAAAAcG9ydFsldToweCUwMng6MHglMDJ4 +XTogdW5rbm93biByZWFkIGFjdGlvbiAweCV4CgAAAAAAAAAAAAAAAAAAAGNoX2NsX3JhdGVbJXUv +JXVdOiBjYXBwZWQgY2xhc3MgcmF0ZSBmcm9tIHJlcXVlc3RlZCAldSB0byBjb25maWd1cmVkIGNo +YW5uZWwgcmF0ZSAldQoAAAAAAAAAAAAAAGNoX2NsX3JhdGVbJXUvJXVdOiBpbmNyZWFzZWQgZGVm +aWNpdF9pbmNyIGZyb20gcmVxdWVzdGVkICV1IHRvIHJlcXVpcmVkIG1pbiBvZiAldTsgcmF0ZSAl +dSAoZWZmICV1KSBkZWZpY2l0X21heCAldQoAAAAAAAAAAAAAAAAAcGt0c2NoZWQgY2hhbm5lbCAl +dSBzZXRzIHNwZWVkIChmcm9tICV1KSB0byAldSBrYnBzCgAAAAAAAAAAAAAAAHBvcnRfY21kX2hh +bmRsZXI6IHVua25vd24gdS5kY2IudHlwZSAweCV4CgAAAAAAAGh3X2kyY190cmFuc2FjdGlvbjog +bmRhdGEgJXUgYWRkcl9vcCAweCV4IGRhdGFbMF0gMHgleCBkaWZmICV1CgBod19pMmNfdHJhbnNh +Y3Rpb246IG5kYXRhICV1IGFkZHJfb3AgMHgleCBkYXRhWzBdIDB4JXggZGlmZiAldSBkcG9zICV1 +IGNvbnQgJXUgZmFpbGVkIHdpdGggZXJyICVkCgAAAAAAAAAAAAAAAAAAaTJjIHRyYW5zYWN0aW9u +IGZhaWxlZCB0byBjb21wbGV0ZQoAAAAAAAAAAAAAAAAAaTJjIGVycm9yIGNhdXNlZCBieSBtb2R1 +bGUgdW5wbHVnCgAAAAAAAAAAAAAAAAAAUVNGUCBtb2R1bGUgdW5wbHVnIC0gcmVpbml0aWFsaXpp +bmcgcnhfbG9zICB0byAweGZmCgAAAAAAAAAAAAAAAGdwaW9fcXNmcF9tb2R1bGVfdXBkYXRlOiBj +aGFuZ2VkIHJ4X2xvcyBmcm9tIDB4JXggdG8gMHgleAoAAAAAAABncGlvX3FzZnBfbW9kdWxlX3Vw +ZGF0ZTogY2hhbmdlZCB0eF9kaXMgZnJvbSAweCV4IHRvIDB4JXgKAAAAAAAAc2VuZHRvIHBlbmRp +bmc6IHdyX3BlbmQgJXAgZm9yIHBvcnQgJXUsICB3YW50IHRvIHNlbmQgdG8gcG9ydCAldQoAAAAA +AAAAAAAAAAAAAABzZW5kdG86Zmxvd2NpZCAldQoAAAAAAAAAAAAAAAAAAGNwbF9lcnJfbm90aWZ5 +OiB0aWQgJXUgY3BsIDB4JTA4eCUwOHgKAAAAAAAAAAAAAGNwbF9lcnJfbm90aWZ5OiB0aWQgJXUg +Y3BsIDB4JTA4eCUwOHggMHglMDh4JTA4eAoAAAAAAAAAAAAAAAAAAABjcGxfZXJyX25vdGlmeTog +dGlkICV1IGxlbiAldQoAAEZDT0UgRnJlZTogc3RpbGwgeWllbGRlZCB3aGVuIGZyZWVpbmcuLi5m +bG93Y19pZCAleCBmbG93Y19mbGFncyAleCAKAAAAAAAAAAAAAAAARkNPRSBCUCBXUiBFUlI6IFdS +IHdpdGggY29va2llICV4JXggZXJyb3JlZCBiYWNrIAoAAAAAAAAAAAAAAAAAAHNjc2lfYWJvcnQ6 +IEVudGVyaW5nIEFib3J0X3Rhc2sKAAAAAAAAAAAAAAAAAAAAAHNjc2lfYWJvcnQ6OiB3ci0+aXFp +ZCBbMHgleF0sIGlzdGFza19mYy0+Zmxvd2Nfc2dlX2lxaWQgWzB4JXhdCgBzY3NpX2Fib3J0Ojog +bHVuX2lkeCBbMHgleF0KAAAAAHNjc2lfYWJvcnQ6IHJlZiB0YXNrIG5vdCBvdXRzdGFuZGluZwoA +AAAAAAAAAAAAAHNjc2lfYWJvcnQ6IHJlZiB0YXNrIGZvdW5kIGl0dCBbMHgleF0gY29va2llIFsw +eCVwXQoAAAAAAAAAAAAAAABzY3NpX2Fib3J0OiBzcmVxLT5vcGNvZGUgWzB4JXhdIGZsYWdzIFsw +eCV4XQoAAABzY3NpX2Fib3J0OiB0YXNrX2lkeCBbJXVdLCBpdHQgWzB4JXhdCgAAAAAAAAAAAABh +Ym9ydC9jbG9zZSBXUiB3aXRoIGNvb2tpZSAweCVseCB3YXMgaXNzdWVkIG9uIHNzbiAweCV4IGlu +IHdyb25nIHN0YXRlIDB4JXgKAAAAAGFib3J0IFdSIG9uIHNzbiAweCV4IGRpZCBub3QgZmluZCBX +UiB3aXRoIGNvb2tpZSAweCV4JXgKAAAAAAAAAABjbG9zZSBXUiB3aXRoIGNvb2tpZSAweCVseCBv +biBzc24gMHgleDtkaWQgbm90IGZpbmQgV1Igd2l0aCBjb29raWUgMHglbHgKAAAAAAAAAGFib3J0 +IFdSIG9uIHNzbiAweCV4IHdhcyBpc3N1ZWQgb24geGNoZyAweCV4IHdpdGggcnhfaWQgMHgleCBp +biB3cm9uZyBzdGF0ZSAweCV4CgAAAAAAAAAAAAAAAAAAAHdyaF9mb2lzY3NpX3Njc2lfZXJyOiB3 +ciBbMHgleF0sIHF1ZXVlZCBvbiBmbG93YyBbMHgleF0sIGZpZm8gWzB4JXhdIGJ5dGVzX2F2YWls +YWJsZQoAAAAAAAAAAAAAAG5ldF9sMmRldl9ub3RpZnk6IEV2ZW50IG9uIGwyZGV2X2ZjLT5mbG93 +Y19pZCBbMHgleF0sIHBvcnQgWyVkXSwgZXZlbnQgWzB4JXhdLCB1bHB0eGNoIFsldV0sIGNsYXNz +IFsweCV4XSwgcHJpb3JpdHkgWzB4JXhdCgAAAAAAcG9ydCAlZCBhcHBsSUQgMHglMDR4IG91aSAw +eCUwNnggdXNlcl9wcmlvciAlZAoAc2VuZCBkY2J4IGluZm86Zmxvd2NpZCAldQoAAAAAAABzZW5k +IGRjYnggY29tcGxldGUKAAAAAAAAAAAAAAAAAERDQlggcG9ydCAldSBhbGxfc3luY2QgPSAldQoA +AAAAY2huZXRfbDJ0X3VwZGF0ZTogbDJkZXZfZmMgWzB4JXhdLCBsMmRldl9mYy0+Zmxvd2NfaWQg +WyV1XSBsMmRldl9mYy0+Zmxvd2NfZmxhZ3MgWzB4JXhdCgAAAAAAAAAAY2huZXRfbDJ0X3VwZGF0 +ZTogbDJkZXZfZmMtPmZsb3djX2lkIFsldV0gYWxyZWFkeSBzY2hlZHVsZWQKAAAAAGNobmV0X2wy +dF91cGRhdGU6IGluIGRlbGF5ZWRfcHJvY2Vzc2luZywgbDJ0ZW50IFslMDh4XQoAAAAAAAAAAABj +aG5ldF9sMnRfdXBkYXRlOiBsMnRfdXBkYXRlIHJlcXVlc3Qgc2VudCBsMnRlbnQgWyUwOHhdLCBs +MnRlbnQtPmlkeCBbJWRdLCBsMnRlbnQtPnZsYW4gWyVkXQoAAABuZXRpZl9wcm9jZXNzX2RoY3A6 +IGwyZGV2X2ZjLT5mbG93Y19pZCBbMHgleF0sIHByb2Nlc3NpbmcsIG9wdF9sZW4gJXUKAAAAAAAA +AAAAAGNobmV0X2RoY3BfcmVjdjogdmxhbmlkIFsldV0sIGwyZGV2X3BpZF9mYy0+Zmxvd2NfbmV0 +X2wyZGV2X3ZsYW5kZXYgWzB4JXhdLCBsMmRldl9mYyBbMHgleF0KAAAAAGNobmV0X2RoY3BfcmVj +djogbDJkZXZfZmMtPmZsb3djX2lkIFsweCV4XSwgZGhjdHh0LT5zdGF0ZSBbJWRdLCBtYWxhY2lv +dXMgZGhjcCByZWN2IGZvciBubyByZXF1ZXN0CgAAAAAAAAAAAAAAAABkaGN0eHQtPnN0YXRlIDog +JWQAAAAAAAAAAAAAAAAAAGwyZGV2X2ZjLT5mbG93Y19pZCBbMHgleF0sIEJhZCBESENQIGNvb2tp +ZSByZWNpZXZlZCwgYWJvcnRpbmcKAABOX1BPUlQgMHgleCV4JXggcmVqZWN0ZWQgUExPR0kgd2l0 +aCByZWFzb24gY29kZSAleAoAAAAAAAAAAAAAAAAAQUJUUyB3aGlsZSBhd2FpdGluZyBQUkxJIFJz +cDogZmxvd2NfaWQgMHgleCBveF9pZCAweCV4IHJ4X2lkIDB4JXggCgAAAAAAAAAAAAAAAABBQlRT +IGZha2UgUnNwOiBsb2MgMHgleCBveF9pZCAweCV4IHJ4X2lkIDB4JXgKAABjYW5ub3QgYWxsb2Nh +dGUgUE9GQ09FIGZpbHRlciBjb25uZWN0aW9uIGZvciB4X2lkICV4IAoAAAAAAAAAAAAAYWN0X29w +ZW5fcnBsOiBhdGlkIFsweCV4XSwgdGlkIFsweCV4XSwgb3AgWzB4JXhdLCBzdGF0dXMgWzB4JXhd +CgAAAAAAAAAAAAAAAAAAAABhY3Rfb3Blbl9ycGw6IGNza19mYy0+dGNiX3N0YXRlIFsweCV4XSwg +Y3NrX2ZjLT5mbGFncyBbMHgleF0sIHRjYl9mYy0+Zmxvd2Nfc3RhdGUgWzB4JXhdCgAAAAAAAABz +ZW5kX2Fib3J0X3JwbDogY3NrX2ZjLT5mbG93Y190eXBlIFsweCV4XSwgY3NrX2ZjLT5mbG93Y19p +ZCBbMHgleF0sIGNza19mYy0+Zmxvd2NfY3NvY2tfdGlkIFsweCV4XSwgdWxwdHhjaCBbJXVdLCBi +dWZmZXJlZCBbJXVdCgAAAAAAAAAAAAAAAAAAAAB3cmhfb2ZsZF90Y3BfY2xvc2VfY29uX3JlcGx5 +OiB0Y2JfZmMtPmZsb3djX2lkIFsweCV4XSwgdGNiX2ZjLT5mbG93Y190eXBlIFsweCV4XSwgbGVu +MTYgWyV1XSwgbG9jIFsldV0KAAAAAAAAAAAAd3JoX29mbGRfdGNwX2Nsb3NlX2Nvbl9yZXBseTog +cnBsLT5vcF9UaWQgWzB4JXhdLCBycGw+c3RhdHVzIFsweCV4XSwgcnBsLT5zbmRfbnh0IFsweCV4 +XSwgcnBsLT5yY3Zfbnh0IFsweCV4XQoAAHRjcF9hYm9ydF9ycGxfcnNzOiB0aWQgWzB4JXhdLCBz +dGF0dXMgWzB4JXhdCgAAAHRjcF9hYm9ydF9yZXFfcnNzOiB0aWQgWzB4JXhdLCBzdGF0dXMgWzB4 +JXhdCgAAAHBrdHNjaGVkX2NsX3JsWyV1OiV1XTogbW9kZSB8IHVuaXQgfCByYXRlIDB4JTA2eCBt +aW4gJXUgbWF4ICV1IHBrdHNpemUgJXUKAAAAAAAAcGFyYW1fZG1hcVsweCV4OjB4JXhdOiBkbWFx +IDB4JXggcmVhZCAldSBwZiAldSByZXQgJWQKAAAAAAAAAAAAAGh3X2JjbTg0ODM0X2xvYWRzZXF1 +ZW5jZTogU3RhcnRlZAoAAAAAAAAAAAAAAAAAAGh3X2JjbTg0ODM0X2xvYWRzZXF1ZW5jZTogVXBs +b2FkIGltYWdlIHRvIFBIWSBvbi1jaGlwIG1lbW9yCgAAAABod19iY204NDgzNF9sb2Fkc2VxdWVu +Y2U6IGRvbmUgbG9hZGluZyBpbWFnZSAoaSA9ICV1KQoAAAAAAAAAAAAARkxBU0ggbm90IHJlYWR5 +OiBpICV1IG52clJlZyAlI3gKAAAAAAAAAAAAAAAAAAAAQVFfRkxBU0hfUmVhZHkgLSBUaW1lb3V0 +ICgxKQoAAABBUV9GTEFTSF9SZWFkeSAtIFRpbWVvdXQgKDIpCgAAAAlBUV9SZXR1cm5Db250cm9s +T2ZGTEFTSAoAAAAAAAAAcGh5OiBmYWlsZWQgdG8gYWxsb2NhdGVkIG1lbW9yeSBmb3IgcGh5IGZ3 +IGZpbGUsIHJldCAlZAoAAAAAAAAAAFBIWSBGVyB2ZXJzaW9uIGluZm9ybWF0aW9uIG5vdCBhdmFp +bGFibGUgZm9yIHRoaXMgdGVjaG5vbG9neQoAAABsZSBjb25maWd1cmF0aW9uOiBuZW50cmllcyAl +dSByb3V0ZSAldSBjbGlwICV1IGZpbHRlciAldSBhY3RpdmUgJXUgc2VydmVyICV1IGhhc2ggJXUK +AAAAAAAAAAAAAABsZSBjb25maWd1cmF0aW9uOiBuZW50cmllcyAldSByb3V0ZSAldSBjbGlwICV1 +IGZpbHRlciAldSBzZXJ2ZXIgJXUgYWN0aXZlICV1IGhhc2ggJXUgbnNlcnZlcnNyYW0gJXUKAAAA +AAAAAAAAAAAAY2ZfcGFyc2U6IGZpbGUgbWVtdHlwZSAweCV4IG1lbWFkZHIgMHgleCBtYXBwZWQg +QCAlcDoKAAAAAAAAAAAAAGNvbmZpZ3VyZWQgd2l0aCBjYXBzIG5ibXxsaW5rIDB4JTA4eCBzd2l0 +Y2h8bmljIDB4JTA4eCB0b2V8cmRtYSAweCUwOHggaXNjc2l8ZmNvZSAweCUwOHgKAAAAAAAAAG5l +dCBWSSBhbGxvY2F0aW9uIGZhaWxlZCBmb3IgZmNfaWQgJXUgd2l0aCBlcnJvciAlZAoAAAAAAAAA +AAAAAABuZXQgVkkgbWFjIGFkZHJlc3MgcHJvZ3JhbW1pbmcgZmFpbGVkIGZvciBmY19pZCAldSB3 +aXRoIGVycm9yICVkCgAAAAAAAAAAAAAAAAAAAG5ldCBWSSByeG1vZGUgcHJvZ3JhbW1pbmcgZmFp +bGVkIGZvciBmY19pZCAldSB3aXRoIGVycm9yICVkCgAAAABuZXQgVkkgcnNzIGluZGlyZWN0aW9u +IHRhYmxlIHByb2dyYW1taW5nIGZvciBmY19pZCAldSBmYWlsZWQgd2l0aCBlcnJvciAlZAoAAAAA +AG5ldCBWSSByc3MgY29uZmlnIGNvbW1hbmQgZmFpbGVkIGZvciBmY19pZCAldSB3aXRoIGVycm9y +ICVkCgAAAABuZXQgVkkgY29tbWFuZCBmYWlsZWQgZm9yIGZjX2lkICV1IHdpdGggZXJyb3IgJWQK +AAAAAAAAAAAAAAAAAAAAbGUgaW5pdGlhbGl6YXRpb246IG5lbnRyaWVzICV1IHJvdXRlICV1IGNs +aXAgJXUgZmlsdGVyICV1IGFjdGl2ZSAldSBzZXJ2ZXIgJXUgaGFzaCAldQoAAAAAAAAAAAAAbGUg +aW5pdGlhbGl6YXRpb246IG5lbnRyaWVzICV1IHJvdXRlICV1IGNsaXAgJXUgZmlsdGVyICV1IHNl +cnZlciAldSBhY3RpdmUgJXUgaGFzaCAldSBuc2VydmVyc3JhbSAldQoAAAAAAAAAAAAAAHRwIG1l +bSBkaXN0cmlidXRpb25bJSVdIHBtdHggJXUgcG1yeCAldSBkZHAgJXUgZGRwX2lzY3NpICV1IHN0 +YWcgJXUgcGJsICV1IHJxICV1IHJxdWRwICV1CgAAAAAAAFRQX1BNTV9SWF9QQUdFX1NJWkUgJXUg +aXMgbm90IHN1cHBvcnRlZAoAAAAAAAAAAFRQX1BNTV9UWF9QQUdFX1NJWkUgJXUgaXMgbm90IHN1 +cHBvcnRlZAoAAAAAAAAAAHBwbWF4IFsldV0sIGJpdHMgWyV1XSwgRldfSVNDU0lfUEFHRVBPRF9U +QUdfSURYX01BWF9TSVpFIFsldV0KAABkZWZhdWx0IHRhZ21hc2sgWzB4JTB4XQoAAAAAAAAAAHBy +b2dyYW1tZWQgdGFnbWFzayBbMHglMHhdCgAAAAAAY3hjbmljLT5kZHBfaW5mby5sbGltaXQgWzB4 +JTB4XSwgY3hjbmljLT5kZHBfaW5mby51bGltaXQgWzB4JTB4XSwgY3hjbmljLT5kZHBfaW5mby5z +aXplIFsweCUweF0KAAAAAAAAAAAAAAAAAAAAAGN4Y25pYy0+ZGRwX2luZm8ubWF4X3R4c3ogWzB4 +JTB4XSBjeGNuaWMtPmRkcF9pbmZvLm1heF9yeHN6IFsweCUweF0gaW9zaXplIFsweCUweF0KAAAA +AAAAAAAAAAAAAHBwbWF4IFsldV0sIGlkeF9iaXRzIFsldV0sIGlkeF9tYXNrIFsweCUweF0sIHJl +c3ZkX3RhZ19tYXNrIFsweCUweF0sIHRhZ21hc2sgWzB4JTB4XQoAAAAAAAAAAAAAAHRhZyBpdHQg +MHglMHgsIGJpdHMgJXUsIGFnZSAweCUweCwgYml0cyAldQoAAAAAAGN4Y25pYy0+aXNjc2lfcHBt +IFsweCUweF0KAAAAAAAAc2NzaV9wbGRfc2l6ZSBbJXVdLCBBTElHTihzY3NpX3BsZF9zaXplLCAx +NikgWyV1XQoAAAAAAAAAAAAAAAAAAG1heF9wcG9kX3pvbmVzIFsldV0KAAAAAAAAAAAAAAAAbDJk +ZXZfZmMtPmZsb3djX2lkIFsldV0sIGwyZGMtPnBmbiBbJXVdLCBsMmRjLT52Zm4gWyV1XSwgbDJk +Yy0+bHBvcnQgWyV1XSwgbDJkZXZfZmMtPmZsb3dpZCBbJXVdIGwyZGMtPnR4X2NoIFsldV0sIGRl +di52cGQucG9ydHZlYyBbJXhdCgAAAAAAAAAAcG9ydHZlYyBbJXVdCgAAAGN4Y25pY19kZXZpY2Vf +aW5pdDogY3hjbmljX2RldmljZV9pbml0X2RvbmUgWyV1XSwgZGV2LnJlcy5mb2lzY3NpX250YXNr +cyBbJXVdLCBkZXYucmVzLmZvaXNjc2lfbnNlc3MgWyV1XSwgZGV2LnJlcy5uY3NvY2sgWyV1XSwg +ZGV2LnJlcy5mb2lzY3NpX25pbml0IFsldV0KAAAAAABhcnBfdGFibGVfc2l6ZSBbJXVdLCBhcnBf +dGJsX2JtX3NpemUgWyV1XSwgbnN0YWNrX25sMnRfYm1fc2l6ZSBbJXVdLCBvZmxkX3Nwb3J0X2Jt +X3NpemUgWyV1XQoAAABpc2NzaV9uc2Vzc19ibV9zaXplIFsldV0sIGNzb2NrX2JtX3NpemUgWyV1 +XSwgaXNjc2lfc2NzaV9udGFza3NfYm1fc2l6ZSBbJXVdCgAAAGN4Y25pY19kZXZpY2VfaW5pdDog +Y3hjbmljIFsweCUweF0sIGN4Y25pYy0+ZmlsdGVyIFslMHhdLCBjeGNuaWMtPm9mbGRfdGNwX3Nw +b3J0X2JtIFsleF0gc2l6ZW9mKHN0cnVjdCBmbG93YykgWyV1XSwgdG90YWxfaXNjc2lfYm1fc2l6 +ZSBbJXVdLCB0b3RhbF9tZW1fc2l6ZSBbJXVdCgAAAAAAAAAAAAAAAAAAY3hjbmljX2RldmljZV9p +bml0OiBkZXYudHAubnVtX3R4X3BhZ2VzIFsldV0sIGRldi5tYy5zaXplIFsldV0sIGRldi50cC50 +eF9wYWdlX3N6IFsldV0gbnN0YWNrX25sMnQgWyV1XSwgZm9pc2NzaV9udGNiIFsldV0sIHJjIFsl +dV0KAAAAAAAAAAAAAAAAUG9ydFsldV06IFVua25vd24gU0dNSUkgc3ViLXR5cGUgJSN4CgAAAAAA +AAAAAAAAUG9ydFsldV06IFVua25vd24gQlRfWEZJIHN1Yi10eXBlICUjeAoAAAAAAAAAAAAAUG9y +dFsldV06IFVua25vd24gQlRfWEFVSSBzdWItdHlwZSAlI3gKAAAAAAAAAAAAcG9ydF9pbml0WyV1 +XTogcG9ydCB0eXBlIDB4JXggaXMgbm90IHN1cHBvcnRlZAoARVEgcGZuICV1IHZmbiAldTogZGVz +dHJveWluZyBlcWlkICV1IHdpdGggcGVuZGluZyBXUihzKSAobnVtX2J5dGVzICV1IGFuZCBmbGFn +cyAweCUwOHgKAAAAAAAAAAAAbmV0X2wyZGV2X2ZyZWU6IGwyZGV2X2ZjLT5mbG93Y19pZCBbMHgl +eF0sIHBvcyBbJXVdCgAAAAAAAAAAAAAAAEFoIGhhLi4uZG91YmxlIGZyZWUgb3hfaWQgMHgleCwg +cnhfaWQgMHgleAoAAAAAAEhvc3QgUFJMSSBSZXNwb25zZSB0aW1lZG91dDogb3hfaWQgMHgleCBy +eF9pZCAweCV4CgAAAAAAAAAAAAAAAABsMmRldl9mYy0+Zmxvd2NfaWQgWyV1XSwgbDJkZXZfZmMt +PmZsb3djX25ldF9sMmRldl9wZm4gWyV1XSwgbDJkZXZfZmMtPmZsb3djX25ldF9sMmRldl92Zm4g +WyV1XSwgbmV0X2wyZGMtPmxwb3J0IFsldV0KAAAAAAAAAAAAAHBmbiAldSB2Zm4gJXUgdmlhIGNv +bW1hbmQKAAAAAAAAaHdfbGVfY2xpcF9oYW5kbGVyOiByZW1vdmVkIHBvcz0ldSAoPWlkeCAldSkK +AAAAaHdfbGVfY2xpcF9oYW5kbGVyOiBhZGRpbmcgdG8gcG9zPSV1ICg9aWR4ICV1KQoAcGZuICV1 +IHZmbiAldQoAAGh3IHBmIGJpdG1hcCAweCUwMnggdmZpZCBiaXRtYXAgMHglMDh4OjB4JTA4eDow +eCUwOHg6MHglMDh4CgAAAABhZnRlciB2ZmlkIGZpeHVwLCB2ZmlkIGJpdG1hcCAweCUwOHg6MHgl +MDh4OjB4JTA4eDoweCUwOHgKAAAAAAAAd29ya2Fyb3VuZDEzNzIzOiBkZXRlY3RlZCBXUiBAIDB4 +JTA4eCBvZiBzaXplICV1IGJ5dGVzLCBkcmliYmxpbmcgaXQgaW4gJXUgYnl0ZXMgYXQgYSB0aW1l +CgAAAAAAdGltZXIgcXVldWUgJXUgbG9zdCBhIHRpY2shIG5leHQgJXAgbGFzdCAlcCBudW1lICV1 +CgAAAAAAAAAAAAAAAGZscl90aW1lcl9zdGFydDogZmxvd2NfaWQgJXUgJXAgYnVmICVwCgAAAAAA +AAAAAHNldHRpbmcvdW5zZXR0aW5nIGhzcyByZXN5bmMgYml0CgAAAAAAAAAAAAAAAAAAAE1DIGlu +aXRpYWxpemF0aW9uIG5vdCBjb21wbGV0aW5nLCBNQyBjdXJyZW50IGluaXQgc3RhdGUgaXMgMHgl +MDJ4CgAAAAAAAAAAAAAAAAAAcGNpZTogbnBmICV1IChwZmJpdG1hcCAweCUwMngpIG52ZiAldSAo +cGYgMC4uMyAweCUwMnggMHglMDJ4IDB4JTAyeCAweCUwMngpCgAAAABmYWlsZWQgdG8gZmluZCB0 +aGUgJWMlYyBWUEQgcGFyYW1ldGVyCgAAAAAAAAAAAABmYWlsZWQgdG8gcGFyc2UgdGhlICVjJWMg +VlBEIHBhcmFtZXRlcgoAAAAAAAAAAABmYWlsZWQgdG8gc3VjY2Vzc2Z1bGx5IGZpbmQgQ2hlbHNp +byBWUEQKAAAAAAAAAABsb2cgaW5pdGlhbGl6ZWQgQCAweCUwOHggc2l6ZSAldSAoJXUgZW50cmll +cykKAABzZW5kX2Nsb3NlX3JlcTogY3NrX2ZjLT5mbG93Y190eXBlIFsweCV4XSwgY3NrX2ZjLT5m +bG93Y19pZCBbMHgleF0sIGNza19mYy0+dGNiX3N0YXRlIFsweCV4XQoAAABzZW5kX2Nsb3NlX3Jl +cTogY3NrX2ZjLT5mbG93Y190eXBlIFsweCV4XSwgY3NrX2ZjLT5mbG93Y19pZCBbMHgleF0sIGNz +a19mYy0+Zmxvd2NfY3NvY2tfdGlkIFsweCV4XSwgdWxwdHhjaCBbJXVdLGJ1ZmZlcmVkIFsldV0K +AG9mbGRfdGNwX2RvX2FjdGl2ZV9jbG9zZTogY3NrX2ZjIFsweCV4XSwgY3NrX2ZjLT5mbG93Y19p +ZCBbMHgleF0sIGNza19mYy0+dGNiX3N0YXRlIFsweCV4XQoAAAAAAG9mbGRfdGNwX2RvX2FjdGl2 +ZV9jbG9zZTogY3NrX2ZjIFsweCV4XSwgY3NrX2ZjLT5mbG93Y19pZCBbMHgleF0sIGNza19mYy0+ +dGNiX3N0YXRlIFsweCV4XQoAAAAAAHRjcF9zZW5kX2FvcGVuX3JlcTogY3NrX2ZjLT5mbG93Y19p +ZCBbMHgleF0sIGNza19mYy0+Zmxvd2Nfc3RhdGUgWzB4JXhdLCBidWZmZXJlZCBbJXVdLCByZXNf +Y250IFsweCV4XSwgc2NoZWRfbm9kZS5uZXh0IFsweCV4XQoAb2ZsZF90Y3Bfc2VuZF9hb3Blbl9y +ZXE6IGNwbF9yZXEtPkZpbHRlciBbMHglMHhdCgAAAAAAAAAAAAAAAAAAAGNzb2NrX2FsbG9jOiB0 +eF9jaCBbMHgleF0sIGxwb3J0IFsweCV4XSwgc21hY19pZHggWyV1XSwgbXNzX2lkeCBbJXVdIGNv +b2tpZSBbJTA4eF0KAAAAAAAAAAAAAAAAAGNzb2NrX2FsbG9jOiBhdmFpbGFibGUgWyV1XSwgbmNz +b2NrIFsldV0sIHBvczphdGlkIFsweCV4XSwgY3NrX2ZjIFsweCV4XSwgY3NrX2ZjLT5mbG93Y19p +ZCBbMHgleF0sIHNwb3J0IFsldV0KAABlbmNvZGVfbnVtYmVyOiBhbGVuIFsldV0KAAAAAAAAAGNo +YXBfY2FsY19kaWdlc3RfbWQ1IC0xCgAAAAAAAAAAY2hhcF9jYWxjX2RpZ2VzdF9tZDUgLTIKAAAA +AAAAAABjaGFwX2NhbGNfZGlnZXN0X21kNSAtMwoAAAAAAAAAAGNoYXBfY2FsY19kaWdlc3RfbWQ1 +IC00CgAAAAAAAAAAY2hhcF9jYWxjX2RpZ2VzdF9tZDUgLTUKAAAAAAAAAABjaGFwX2NhbGNfZGln +ZXN0X21kNSAtNgoAAAAAAAAAAGZvaXNjc2lfcGVlcl9pbml0OiBjb25uX2F0dHItPmhkaWdlc3Rf +dG9fZGRwX3Bnc3ogWzB4JXhdCgAAAAAAAABmb2lzY3NpX3BlZXJfaW5pdDogY29ubl9mYy0+Zmxv +d2NfZm9pc2NzaV9jb25uX2ZsYWdzIFsweCV4XQoAAAAAb2ZsZF90Y3BfZGlzY29ubmVjdDogdGNi +X2ZjLT5mbG93Y19pZCBbMHgleF0sIGNza19mYy0+Zmxvd2NfaWQgWzB4JXhdLCBjc2stPnRjYl9z +dGF0ZSBbMHgleF0KAAAAeG1pdF9zZW5kdGFyZ2V0czogcGFyYW0tPnR0dCBbMHgleF0sIGRhdGFf +bGVuIFsldV0sIHBhZF9sZW4gWyV1XQoAAAAAAAAAAAAAAAAAAABsb2dnZWRfaW46IGZsb3djX2Zv +aXNjc2lfY29ubl9mbGFncyBbMHgleF0KAAAAAABmb2lzY3NpX3ZhbGlkYXRlX2xvZ2luX3N0YWdl +OiAtIDEKAAAAAAAAAAAAAAAAAAB0YXNrX2ZyZWU6IHRyeWluZyB0byBmcmVlIHF1ZXVlZCB0YXNr +IFsweCV4XSEhIQoAAAAAAAAAAAAAAAAAAAAASW52YWxpZCBvcGNvZGUgMHgleCBpbiBkYXRhIHBh +dGgKAAAAAAAAAAAAAAAAAAAAbmV0X2wyZGV2X2ZpbmRfYnlfYWRkcjogbDJkZXZfZmMtPmZsb3dj +X2lkIFsweCV4XSwgbDJkYy0+bHBvcnQgWyV1XSwgbDJkX2ZjLT5mbG93Y19pZCBbMHgleF0sIGwy +ZGMtPmluNF9kZXYuaW5fYWRkci5hZGRyIFsweCV4XSwgYWRkciBbMHgleF0KAAAAbmV0X2wyZGV2 +X210dV9jb25maWc6IGwyZGV2X2ZjLT5mbG93Y19pZCBbMHgleF0sIG10dSAldQoAAAAAAAAAAGZv +aXNjc2kgY29ubl9mYyBbMHgleF0sIGZsb3djX3NjaGVkY2wgWzB4JXhdLCBpbmdfY2ggWzB4JXhd +LCBlZ3JfY2ggWzB4JXhdCgAAAAAAbDJkZXZfbm90aWZ5IHdpdGggdW5rbm93biBmbGFnIFsweCV4 +XQoAAAAAAAAAAAAAY2huZXRfdmlfZW5hYmxlOiB2aWlkIFslZF0sIHZpX2ZjLT5mbG93Y192aV9m +bGFncyBbMHgleF0KAAAAAAAAAGh3IHJlZ2lzdGVyIG9wZXJhdGlvbiBub3QgY29tcGxldGluZywg +cmVnIDB4JTA4eCBtYXNrIDB4JTA4eCB2YWx1ZSAweCUwOHgKAAAAAAAATURJTyBDTDQ1OiBmYWls +ZWQgdG8gc2V0IHVwIE1NRCBhZGRyCgAAAAAAAAAAAAAATURJTzogZmFpbGVkIHRvIHJlYWQKAAAA +AAAAAAAAAABNRElPIENMNDU6IGZhaWxlZCB0byBzZXQgdXAgTU1EIGFkZHIKAAAAAAAAAAAAAABN +RElPOiBmYWlsZWQgdG8gd3JpdGUKAAAAAAAAAAAAAHBbJXVdIGNoYW5naW5nIHNwZWVkIGZyb20g +JSN4IHRvICUjeAoAAAAAAAAAAAAAAHBbJXVdIGNhbGlicmF0aW5nIFBIWSBTRVJERVMgZm9yIG5l +dyBzcGVlZAoAAAAAAGh3X3hnbV9sZWRfbGlua191cCBsZWQwIGNvbmZpZzogJXUKAAAAAAAAAAAA +AAAAAGh3X3hnbV9sZWRfbGlua191cCBsZWQxIGNvbmZpZzogJXUKAAAAAAAAAAAAAAAAAGhzc19z +aWdkZXRbJXVdOiBoc3Nfc2lnZGV0IGNoYW5nZWQgdG8gMHgleAoAAAAAAGNyX21vZHVsZV9yeF9s +b3NbJXVdOiByeF9sb3MgY2hhbmdlZCB0byAldQoAAAAAAFdBVENIRE9HOiBObyB0ZW1wZXJhdHVy +ZSBzZW5zb3IgYXZhaWxhYmxlLgoAAAAAAFdBVENIRE9HOiBBY3RpdmF0aW5nCgAAAAAAAAAAAAAA +V0FUQ0hET0cgLSBFbmFibGUgYWN0aW9uICV1IHRpbWUgJXUKAAAAAAAAAAAAAAAAV0FUQ0hET0cg +LSBEaXNhYmxlIGFjdGlvbiAldQoAAABXQVRDSERPRzogRGUtYWN0aXZhdGluZwoAAAAAAAAAAEZD +b0UgRkNCIGxpbmtkb3duOiBpb19yZXEgMHgleCV4IGlxaWQgMHgleCBmbG93aWQgMHgleCBvcCAw +eCV4CgBmY29lIG5vdGlmeSA6IFVwZGF0ZSBuZXcgRENCWCB2YWx1ZXMgVkkgc3RhdGUgMHgleCBw +cmkgMHgleCBzY2hlZGNsIDB4JXggZGNieF9kb25lIDB4JXgKAAAAAAAAAABmY29lIG5vdGlmeSA6 +IEZDRiBmbG93aWQgMHgleCwgdWxwY2ggMHgleCAKAAAAAABmY29lIG5vdGlmeSA6IERDQlggOiBw +b3J0IDB4JXgsIHByaW9yaXR5IDB4JXggdWxwdHhjaCAweCV4IGNsYXNzIDB4JXgKAAAAAAAAAAAA +AGNoX2NsX3JhdGVbJXUvJXVdOiBjYXBwZWQgZGVmaWNpdF9pbmNyIGZyb20gcmVxdWlyZWQgJXUg +dG8gJXU7IHJhdGUgJXUgKGVmZiAldSkgZGVmaWNpdF9tYXggJXUKAEZDb0UgRkNGIHRpbWVyOiBm +bG93YyBzdGF0ZSAweCV4LCBwb3J0IDB4JXggLGZjZiAweCV4LCBmbG93Y19pZCAweCV4CgAAAAAA +AAAAAAAAY29yZV9wcm9ncmFtX3RjYjogdGlkICUjeCB0X3N0YXRlICUjeCByY3ZfYWR2IDB4JTA4 +eCByY3Zfc2NhbGUgJSN4IHR4X21heCAlI3ggcmN2X254dCAlI3ggYXRpZCAlI3gKAAAAAAAAAAAA +AAAAAAlvcHQwICUjeCV4IG9wdDIgJSN4IGlwdjYgJSN4IGZsYWdzX3RpbWVyIDB4JTA4eAoAAAAA +AAAAAAAAAAAAAABvZmxkX2Nvbm5lY3Rpb25fd3I6IGNvbm5lY3Rpb24gd2l0aCA1LXR1cGxlIGxw +IDB4JTA0eCBmcCAweCUwNHggbGlwIDB4JTA4eCUwOHggcGlwIDB4JTA4eCUwOHggZmlsdGVyIDB4 +JTA4eCBleGlzdHMgQCBMRSBpbmRleCAldQoAAAAAAAAAAAAAAAAAAABvZmxkX2Nvbm5lY3Rpb25f +d3I6IGNvbm5lY3Rpb24gd2l0aCA1LXR1cGxlIGxwIDB4JTA0eCBmcCAweCUwNHggbGlwIDB4JTA4 +eCBwaXAgMHglMDh4IGZpbHRlciAweCUwOHggZXhpc3RzIEAgTEUgaW5kZXggJXUKAAAAAAAAAG9m +bGRfY29ubmVjdGlvbl93cjogY29ubmVjdGlvbiB3aXRoIDUtdHVwbGUgbHAgMHglMDR4IGZwIDB4 +JTA0eCBsaXAgMHglMDh4JTA4eCBwaXAgMHglMDh4JTA4eCBmaWx0ZXIgMHglMDh4CgAAAABvZmxk +X2Nvbm5lY3Rpb25fd3I6IGNvbm5lY3Rpb24gd2l0aCA1LXR1cGxlIGxwIDB4JTA0eCBmcCAweCUw +NHggbGlwIDB4JTA4eCBwaXAgMHglMDh4IGZpbHRlciAweCUwOHgKAAAAAAAAAAAAAAAASVFGTElO +VCBwZm4gJXUgdmZuICV1OiBpcWVzaXplICV1IHRvbyBzbWFsbAoAAAAASVFGTElOVCBwZm4gJXUg +dmZuICV1OiBpcWlkICV1IHRvbyBsYXJnZSAobWF4ICV1KQoAAAAAAAAAAAAAAAAAAElRRkxJTlQg +cGZuICV1IHZmbiAldTogaXFpZCAldSBub3QgYWxsb2NhdGVkCgAAAElRRkxJTlQgcGZuICV1IHZm +biAldTogZmwwaWQgJXUgdG9vIGxhcmdlIChtYXggJXUpCgAAAAAAAAAAAAAAAABJUUZMSU5UIHBm +biAldSB2Zm4gJXU6IGZsMGlkICV1IG5vdCBhbGxvY2F0ZWQKAABJUUZMSU5UIHBmbiAldSB2Zm4g +JXU6IGZsMWlkICV1IHRvbyBsYXJnZSAobWF4ICV1KQoAAAAAAAAAAAAAAAAASVFGTElOVCBwZm4g +JXUgdmZuICV1OiBmbDFpZCAldSBub3QgYWxsb2NhdGVkCgAASVFGTElOVCBwZm4gJXUgdmZuICV1 +OiBmbDFpZCAldSBpcyB2YWxpZCBidXQgbm90IGZsMGlkICV1CgAAAAAAAElRRkxJTlQgcGZuICV1 +IHZmbiAldTogZmwxaWQgJXUgaXMgdmFsaWQgYnV0IGhlYWRlciBzcGxpdCBmZWF0dXJlIGlzIG5v +dCBlbmFibGVkCgAAAAAAAAAAAAAAAAAAAElRIHBmbiAldSB2Zm4gJXU6IGlxaWQgJXUgdG9vIGxh +cmdlIChtYXggJXUpCgAAAElRIHBmbiAldSB2Zm4gJXU6IGlxaWQgJXUgbm90IGFsbG9jYXRlZAoA +AAAAAAAAAElRIHBmbiAldSB2Zm4gJXU6IGZsMGlkICV1IGZsMWlkICV1IGJ1dCBub3Qgc3VwcG9y +dGVkCgAAAAAAAAAAAABFUSBwZm4gJXUgdmZuICV1OiBjcmVhdGluZyBFVEggZXFpZCAldSB3aXRo +IHBlbmRpbmcgV1IocykgKG51bV9ieXRlcyAldSBhbmQgZmxhZ3MgMHglMDh4CgAAAAAAAABFUSBw +Zm4gJXUgdmZuICV1OiBjcmVhdGluZyBDVFJMIGVxaWQgJXUgd2l0aCBwZW5kaW5nIFdSKHMpIChu +dW1fYnl0ZXMgJXUgYW5kIGZsYWdzIDB4JTA4eAoAAAAAAABFUSBwZm4gJXUgdmZuICV1OiBlcWlk +ICV1IHRvbyBsYXJnZSAobWF4ICV1KQoAAABFUSBwZm4gJXUgdmZuICV1OiBlcWlkICV1IG5vdCBh +bGxvY2F0ZWQKAAAAAAAAAABod19jaW1fdHBfd29ya2Fyb3VuZDEzNzIzX2VuYWJsZTogcG9ydCAl +dSBwcm90b2NvbCAweCV4IGVuICV1IGN1cnJlbnQgMHgleCB3b3JrYXJvdW5kX3ByMTM3MjMgMHgl +eAoAAAAAAAAAAAAAAAAAcG9ydF9ibGlua19sZWRfcmVzdG9yZQoAAAAAAAAAAABwb3J0X2JsaW5r +OiBibGlua2R1cj0weCV4IGJsaW5rX3JlZmNudAoAAAAAAAAAAABwb3J0X2JsaW5rOiAJYmxpbmtf +cmVmY250PTB4JXgKAHBvcnRfYmxpbms6IAlibGlua19yZWZjbnQ9MHgleAoAbWlpX2Fkdl9zcGVl +ZFsldV06IHJjYXBzIDB4JXgKAABtaWlfaW5pdFsldV06IGFjYXBzIDB4JXgKAAAAAAAAAG1paV9w +ZG93blsldV06IHBvd2VyZG93biBlbiAldQoAcG9ydFsldV06IGdhdmUgdXAgZml4aW5nIGVycm9y +cyEhIQoAAAAAAAAAAAAAAAAAcG9ydFsldToweCUwMng6MHglMDJ4XTogbDFjZmcsIHBjYXBzIDB4 +JXggYWNhcHMgMHgleCByY2FwcyAweCV4CgAAAAAAAAAAAAAAAAAAAABwb3J0WyV1OjB4JTAyeDow +eCUwMnhdOiBsMWNmZywgaW52YWxpZCByZXF1ZXN0LCBwY2FwcyAweCV4IGFjYXBzIDB4JXggcmNh +cHMgMHgleAoAAAAAAAAAAAAAAAAAAABwb3J0WyV1OjB4JTAyeDoweCUwMnhdOiBsMWNmZywgbWRp +IG4vYSBwY2FwcyAweCV4IGFjYXBzIDB4JXggcmNhcHMgMHgleAoAAAAAAAAAAHBvcnRbJXU6MHgl +MDJ4OjB4JTAyeF06IGwxY2ZnLCBjYW5ub3QgZm9yY2UgbXVsdGlwbGUgc3BlZWRzLCBwY2FwcyAw +eCV4IGFjYXBzIDB4JXggcmNhcHMgMHgleAoAAGNoX3JhdGVbJXVdOiBjYXBwZWQgdGljayBmcm9t +IHJlcXVpcmVkICV1IHRvIHN1cHBvcnRlZCAldTsgcmF0ZSAldSAoZWZmICV1KSBkZWZpY2l0X2lu +Y3IgJXUgdGljayAldQoAAAAAAAAAAAAAAABod19pMmNfdyBwb3J0ICV1IGRldiAleCByZWcgJXUg +ZGF0YSAweCV4CgAAAAAAAABnZXRfcmVmX3Rhc2s6IHJlcXVlc3RlZCBjb29raWU6IGhpZ2ggWzB4 +JTA4eF0sIGxvdyBbMHglMDh4XQoAAAAAZ2V0X3JlZl90YXNrOiB0YXNrIGNvb2tpZTogaGlnaCBb +MHglMDh4XSwgbG93IFsweCUwOHhdCgAAAAAAAAAAAGdldF9yZWZfdGFzazogaXN0YXNrLT5mbG93 +Y19pZCBbMHgleF0sIGlzdGFza19mYy0+Zmxvd2Nfc3RhdGUgWyV1XQoAAAAAAAAAAAAAAAAAZ2V0 +X3JlZl90YXNrOiB0YXNrIG5vdCBmb3IgY29va2llICVseAoAAAAAAAAAAAAAbmV0aWZfcHJvY2Vz +c19kaGNwX29wdHM6IGwyZGV2X2ZjLT5mbG93Y19pZCBbMHgleF0sIE1TR19UWVBFIFslZF0sIGRo +Y3R4dC0+c3RhdGUgWyVkXQoAAAAAAAAAAAAAaWNtcF9yZWN2OiBsMmRldl9mYy0+Zmxvd2NfaWQg +WzB4JXhdLCBwaWQgWzB4JXhdLCBpY21wIHR5cGUgWzB4JXhdCgAAAAAAAAAAAAAAAABBQlRTIEFD +QyBhd2FpdGluZyBQUkxJIFJzcDogZmxvd2NfaWQgMHgleCBveF9pZCAweCV4IHJ4X2lkIDB4JXgg +aXFpZCAweCV4CgAAAAAAAGNobmV0X2FycF9yZWN2OiBwaWQgWyV1XSwgcGt0LT5haGRyLnNpcCBb +MHgleF0sIHBrdC0+YWhkci5yaXAgWzB4JXhdLCBwa3QtPmFoZHIub3Bjb2QgWzB4JXhdCgAAAGNo +bmV0X2FycF9yZWN2OiB2bGFuIGV4dHJhY3RlZCwgdmxhbmlkIFsldV0sIGwyZGV2X2ZjLT5mbG93 +Y19uZXRfbDJkZXZfdmxhbmRldiBbMHgleF0sIGwyZGV2X2ZjIFsweCV4XQoAAAAAAAAAAABjaG5l +dF9hcnBfcmVjdjogaXAgY29uZmxpY3QgZGV0ZWN0ZWQKAAAAAAAAAAAAAABjaG5ldF9hcnBfcmVj +djogdmxhbmlkIFslMHhdLCBwaWQgWyV1XQoAAAAAAAAAAABjaG5ldF9hcnBfcmVjdjogbDJkZXZf +ZmMgWyV4XSwgcGt0LT5haGRyLnJpcCBbMHgleF0sIHBrdC0+YWhkci5zaXAgWzB4JXhdCgAAAAAA +AGNzb2NrX3BlZXJfY2xvc2U6IGNza19mYy0+Zmxvd2NfaWQgWzB4JXhdLCBjc2tfZmMtPnRjYl9m +Yy0+Zmxvd2NfaWQgWzB4JXhdLCBjc2tfZmMtPmZsb3djX3N0YXRlIFsweCV4XSwgY3NrX2ZjLT5m +bG93Y19jc29ja190Y2JfZmMtPmZsb3djX3N0YXRlIFsweCV4XQoAAAAAAAAAAABjc29ja19wZWVy +X2Nsb3NlOiBjc2tfZmMtPmZsb3djX2lkIFsweCV4XSwgY3NrX2ZjLT5mbG93Y19zdGF0ZSAgWzB4 +JXhdCgAAAAAAAAAAAHRjYl9mYy0+Zmxvd2NfaWQgWzB4JTA2eF0sIHRjYl9mYy0+Zmxvd2NfdHlw +ZSBbMHgleF0sIGNwbG9wIFsweCV4XSAKAAAAAAAAAAAAAAAAcGt0c2NoZWRfY2hfcmxbJXVdOiBj +aGFubmVsIHJsIG5vdCBhdmFpbGFibGUgaW4gY29uanVuY3Rpb24gd2l0aCBmbG93IHNoYXBpbmcK +AABwa3RzY2hlZF9jaF9ybFsldV06IHJhdGUgJXUgbWF4ICV1CgAAAAAAAAAAAAAAAABwa3RzY2hl +ZF9jbF93cnJbJXU6JXVdOiB3ZWlnaHQgJXUgd2VpZ2h0ZWRfbWFzayAweCV4CgAAAAAAAAAAAAAA +ZXFfcGFyYW1zWzB4JXg6MHgleF06IGRtYXEgMHgleCByZWFkICV1IHBmICV1IGVxaWRfYXBpICV1 +IHJldCAlZAoAAAAAAAAAAAAAAAAAAABod19iY204NDM0X2NoZWNrcmFtOiBTdGFydAoAAAAAAFBI +WVsldV0gcHJvY2Vzc29yIG5vdCBydW5uaW5nCgAAUEhZWyV1XSBGVyBoYXMgYmFkIENSQwoAAAAA +AAAAAABQSFkgZmlybXdhcmUgbG9hZCBzdWNjZXNzZnVsIQoAAAlBUV9UYWtlQ29udHJvbE9mRkxB +U0g6IDFlLmMwMDE9JSN4IDFlLmM0NTA9JSN4IDFlLmM0NTE9JSN4IDFlLjEwMD0lI3gKAAAAAAAA +AAAAQVFfQVBJX1dyaXRlQW5kVmVyaWZ5Rmxhc2hJbWFnZSAtIEltYWdlIGludGVncml0eSBjaGVj +ayBmYWlsZWQgKGNhbGMgJSN4IHZhbCAlI3gpCgAAAAAAAAAAAAAAAAAAQVFfQVBJX1dyaXRlQW5k +VmVyaWZ5Rmxhc2hJbWFnZSAtIEltYWdlIGludGVncml0eSBjaGVjayBwYXNzZWQKAEFRX0FQSV9X +cml0ZUFuZFZlcmlmeUZsYXNoSW1hZ2UgLSBUaW1lb3V0IHdhaXRpbmcgZm9yIGZsYXNoIGludGVy +ZmFjZSAoJXUpCgAAAAAAQVFfQVBJX1dyaXRlQW5kVmVyaWZ5Rmxhc2hJbWFnZSAtIFRpbWVvdXQg +d2FpdGluZyBmb3IgZmxhc2ggaW50ZXJmYWNlICgldSkKAAAAAABBUV9BUElfV3JpdGVBbmRWZXJp +ZnlGbGFzaEltYWdlIC0gVGltZW91dCB3YWl0aW5nIGZvciBmbGFzaCBpbnRlcmZhY2UgKCV1KQoA +AAAAAEFRX0FQSV9Xcml0ZUFuZFZlcmlmeUZsYXNoSW1hZ2UgLSBUaW1lb3V0IHdhaXRpbmcgZm9y +IGZsYXNoIGludGVyZmFjZSAoJXUpIChwcCAlI3ggYXAgJSN4KQoAAAAAAEFRX0FQSV9Xcml0ZUFu +ZFZlcmlmeUZsYXNoSW1hZ2UgLSBUaW1lb3V0IHdhaXRpbmcgZm9yIGZsYXNoIGludGVyZmFjZSAo +JXUpCgAAAAAAQVFfQVBJX1dyaXRlQW5kVmVyaWZ5Rmxhc2hJbWFnZSAtIFRpbWVvdXQgd2FpdGlu +ZyBmb3IgZmxhc2ggaW50ZXJmYWNlICgldSkKAAAAAABBUV9BUElfV3JpdGVBbmRWZXJpZnlGbGFz +aEltYWdlIC0gRXJyb3Igb24gYnVybmluZyBGTEFTSCAoY3JjMTYgbWlzbWF0Y2gpCgAAAAAAAG1h +bGxvY19kZWNbJXVdOiBzdGFydCAlcCBlbmQgJXAgbmV4dCAlcCBzaXplIDB4JXggYWxpZ21lbnQg +MHgleCBwICVwCgAAAAAAAAAAAAAAbWFsbG9jX2luY1sldV06IHN0YXJ0ICVwIGVuZCAlcCBuZXh0 +ICVwIHNpemUgMHgleCBhbGlnbWVudCAweCV4IHAgJXAKAAAAAAAAAAAAAABsZSBjb25maWd1cmF0 +aW9uOiBoYXNoIG1vZGUgcmVxdWlyZXMgYXQgbGVhc3QgMTYgZW50cmllcywgbmhhc2ggJXUKAAAA +AAAAAAAAAAAAAGxlIGNvbmZpZ3VyYXRpb246IGhhc2ggbW9kZSByZXF1aXJlcyBhdCBlbnRyaWVz +IHRvIGJlIGEgcG93ZXIgb2YgMiwgbmhhc2ggJXUKAAAAbGUgY29uZmlndXJhdGlvbjogcmVxdWVz +dGVkICV1IHRjYW0gZW50cmllcyBidXQgb25seSAldSBhdmFpbGFibGUKAAAAAAAAAAAAAAAAAABs +ZSBjb25maWd1cmF0aW9uOiB0Y2FtIHJlZ2lvbnMgbXVzdCBoYXZlIG11bHRpcGxlIG9mIDMyIGVu +dHJpZXMsIG5yb3V0ZSAldSBuY2xpcCAldSBuZmlsdGVyICV1IG5zZXJ2ZXIgJXUKAAAAAAAAb2Zs +ZCB0cCB0aW1lciBzZXR0aW5ncyBUUF9NU0wgMHglMDh4IFRQX1JYVF9NSU4gMHglMDh4IFRQX1JY +VF9NQVggMHglMDh4IFRQX1BFUlNfTUlOIDB4JTA4eCBUUF9QRVJTX01BWCAweCUwOHgKACAgICAg +ICAgICAgICAgICAgICAgICAgVFBfS0VFUF9JRExFIDB4JTA4eCBUUF9LRUVQX0lOVFZMIDB4JTA4 +eCBUUF9JTklUX1NSVFQuaW5pdF9zcnR0X21heHJ0dCAweCUwNHggVFBfSU5JVF9TUlRULmluaXRf +c3J0dF9pbml0c3J0dCAweCUwNHggVFBfRklOV0FJVDJfVElNRVIgMHglMDh4CgAAAAAAAAAAAAAA +Y29uZmlndXJhdGlvbiBmaWxlIHBhcnNlciBlbmNvdW50ZXJlZCBlcnJvciBAIGxpbmUgJXU6CgAA +AAAAAAAAAEhPU1QgUEFHRV9TSVpFIFsweCUwbHhdIHRvbyBzbWFsbCwgbWluIFsweCUwbHhdIHJl +cXVpcmVkCgAAAAAAAABwYWdlIHNpemUgWyVsdV0gbWlzbWF0Y2gKAAAAAAAAAFBBR0Ugc2l6ZSAl +bHUgdW5zdXBwb3J0ZWQsIGRkcCBkaXNhYmxlZAoAAAAAAAAAAEhvc3QgcGFnZV9zaXplICVsdSwg +ZGRwX2lkeCAldQoARkNvRSBERFAgaW5pdDogZmNvZSBsbGltaXQgMHgleCwgZmNvZSB1bGltaXQg +MHgleCBnYmwgbGxpbWl0IDB4JXggZ2JsIHVsaW1pdCAweCV4CgAAAAAAAAAAAAAAAAAARkNvRSBE +RFAgaW5pdDogZmNvZSBwcG9kIG9mZiAweCV4LCBmY29lIHN0IHBwb2QgYWRkciAweCV4IGZjb2Ug +bnVtIHBwb2RzIDB4JXgKAABmY29lIHhjaGcgbWdyIGluaXQ6IE51bWJlciBvZiBleGNoYW5nZXMg +Zm9yIEZDb0UgaXMgJXgKAAAAAAAAAAAAQ2FsY3VsYXRpb24gb3V0IG9mIGJvdW5kcyBmdXJpbmcg +aW5pdDogJSN4ICUjeCAlI3gKAAAAAAAAAAAAAAAAAHBmbiAldSB2Zm4gJXUgaGFzIHBuZHR4bnMg +JXUgYWZ0ZXIgMTAwbXMKAAAAAAAAAGJhZCBtYWlsYm94IGNtZDogcGZuIDB4JXggdmZuIDB4JXg7 +IG9wY29kZSAweCV4ID4gTEFTVEMyRSAweCV4CgBtYWlsYm94IGNtZCBub3QgeWV0IHN1cHBvcnRl +ZDogcGZuIDB4JXggdmZuIDB4JXg7IG9wY29kZSAweCV4CgAAYmFkIG1haWxib3ggY21kOiBwZm4g +MHgleCB2Zm4gMHgleDsgb3Bjb2RlIDB4JXggaXMgdmFsaWQgcG9zdCBkZXZpY2UgaW5pdCBvbmx5 +CgBiYWQgbWFpbGJveCBjbWQ6IHBmbiAweCV4IHZmbiAweCV4OyBvcGNvZGUgMHglMDJ4IHJhbWFz +ayAweCV4IGNtZCByYW1hc2sgMHgleAoAAGJhZCBtYWlsYm94IGNtZDogcGZuIDB4JXggdmZuIDB4 +JXg7IG9wY29kZSAweCUwMnggbGVuMTYgMHgleCB2ZXJzdXMgZXhwZWN0ZWQgbGVuMTYgMHgleAoA +AAAAAAAAAGluc3VmZmljaWVudCBjYXBzIHRvIHByb2Nlc3MgbWFpbGJveCBjbWQ6IHBmbiAweCV4 +IHZmbiAweCV4OyByX2NhcHMgMHgleCB3eF9jYXBzIDB4JXggcmVxdWlyZWQgcl9jYXBzIDB4JXgg +d19jYXBzIDB4JXgKAAAAAAAAAAAAaW5zdWZmaWNpZW50IGNhcHMgdG8gcHJvY2VzcyBtYWlsYm94 +IGNtZDogcGZuIDB4JXggdmZuIDB4JXg7IHJfY2FwcyAweCV4IHd4X2NhcHMgMHgleCByZXF1aXJl +ZCByX2NhcHMgMHgleCB3X2NhcHMgMHgleAoAAAAAAAAAAABWUEQgcmVnaW9uIGlzIHRvbyBzbWFs +bCAoU0VSQ0ZHX1NSX1BGTlZQRFNJWkUgMHgleCkKAAAAAAAAAAAAAAAAY2Y6IGZhaWxlZCB0byBh +bGxvY2F0ZWQgbWVtb3J5IGZvciBjb25maWd1cmF0aW9uIGZpbGUsIHJldCAlZAoAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIIAAAEgAAAAAAAAAIIAAAEAAAAAAAAAAIAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAgAAAAAAAAAAAAAAAAIAAAAAAAAAAAAKAAAAA +AAAAAAAAAgADAAAAAAFgCAAAAAADAAAAAAAAAAAAAAADAAAAAAAAAAAAAAACAAAAAAAAAAAAIAAA +AAAAAAAAAAAAAQADgAAAAAAAAAAAAAACAAAAAAAAAAAAIAOAAAAAAAAAAAAAEAKAAIAAAAAAAAAA +AAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAACAAAAAAAAAAAAAAACgAAAAAAA +AAAAAQADAAAAAAAAAAAAAAKDAAAAAAAAAAAAEAKAAAAAAAAAAAAAMAADAAAAAAAACAAAMAADAAAA +AAAAAAAAMAWDAAAAAAAACAAAMAWDAAAAAAAAAAAAMASDAAAAAAAACAAAMASDAAAAAAAAAAAAMAMD +AAAAAAAACAAAMAMDAAAAAAAAAAAAOAMDAAAAAAAAAAAAOAWDAAAAAAAAAAAAOASDAAAAAAAAAAAA +OAADAAAAAAAAAAAANAaCAAAAAAAAAAAAPAOCAAAAAAAAAAAAPAADAAAAAAAACAAAPAADAAAAAAAA +AAAAPASDAAAAAAAAAAAAPAUDAAAAAAAAAAAAPQQDAAAAAAAAAAAAPAODAAAAAAAAAAAALAACAAAA +AAAAAAAALAWCAAAAAAAAAAAALAUCAAAAAAAAAAAAEAaAAAAAAAAAAAAAEAaCwAAAAAAAAAAAEAaC +gAAAAAAAAAAAAA6CAAAAAAAAAAAAEAeCgAAAACAAAAAAAAeCAAAAACAAAAAAEAcCgAAAAAAAAAAA +EAcCgAAAAAAAAAAAEAcCgAAAAAAAAAAAAAcCAAAAACAAAAAAEBeDAAAAAAAACAAAEBeDAAAAAAAA +CAAAEAAAAAAAAAAAAAAAEAYDgAAAAAAAAAAAAA4DAAAAAAAAAAAAEAYDQAAAAAAAAAAAEAYDAAAA +AAAAAAAAEAYAAAAAAAAAAAAAAAYDgAAAAAAAAAAAAAYDAAAAAAAAAAAAAA4CAAAAAAAAAAAAAA4C +AAAAAAAAAAAAEAYCAAAAAAAAAAAAEAYCAAAAAAAAAAAAEAYCgAAAAAAAAAAAEAYCgAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAABADAAAAAAAACAAAAAAAAAAAAAAA +AAAA//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +////////////////////////////AAAAIAAAAADAAAAAAAAAIAAAAADgAAAAAAAAAAIAAAAAAAAA +QAAAAAAAAAAAAAAAAAABIQAAAAAAAAAAAAEBIAAAAAAAAAAAAAACAAAABAAEAAAAAAUAAAAEAAAA +AAAAAAAAoAAAAACAAAAAAIAAQAAAAAAAAgAAAIAAIAAAAAAAAgAAAQBAAAAAAAAAAAAAAQBCAAAA +AAAAAAAAAAAgAAAAAAAAAAAAAhAgAAAAAAAAAAAAAgwCAAAAAAAAAAAAAIUCAAAABAAAAAAAAIBC +AAAAAAAAAAAAAgAiAAAAAAAAAAAAAIBBAAAAAAAAAAAAAIBBgAAAAAAAAAAAAgAhAAAAAAAAAAAA +ABAggAAAAAAAAAAAAiUAgAAAAAAAAAAAAAUAAAAAAAAAAAAACIgEgAAAAAAAAAAACIgEgAAAAAAA +AAAACKIAgAAAAAAAAAAACKIAgAAAAAAAAAAACKMAgAAAAAAAAAAACKMAgAAAAAAAAAAACKSAgAAA +AAAAAAAACKSAgAAAAAAAAAAABKSAwAAAAAAAAAAABKIAwAAAAAAAAAAABKMAwAAAAAAAAAAABIgE +wAAAAAAAAAAAAAkBgAAAAAAAAAAAAgwAgAAAAAAAAAAAAIgEwAAAAAAAAAAAAIgEgAAAAAAAAAAA +AgsAgAAAAAAAAAAAAIqAgAAAAAAAAAAAAAuAgAAAAAAAAAAAAIwAgAAAAAAAAAAAAiAQgAAAAAAA +AAAAAgoAgAAAAAAAAAAAAgqAgAAAAAAAAAAAAAkCgAAAAAAAAAAAAAEBAAAAAAAAAAAAAAEBQAAA +AAAAAAAAAAEAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAACBEAAAAAAAAAAAAACB +CAAAAAAAAAAAAACBBAAAAAAAAAAAAACBgAAAAAAAAAAAAIAAwAAAAAAAAAAAAIAAoAAAAAAAAAAA +AAAIAAAAAAAAAAAAAIGAAAAAAAAAAAAAAIGAgAAAAAAAAAAAAImAgAAAAAAAAAAAAImAwAAAAAAA +AAAAAAGCAAAAAAAAAAAAAgGAAAAAAAAAAAAAAgGAgAAAAAAAAAAAAEGBgAAAAAAAAAAAAgGBgAAA +AAAAAAAAAEmBgAAAAAAAAAAAAgmBgAAAAAAAAAAAAgGBAAAAAAAAAAAAAEGBAAAAAAAAAAAAIAAA +AAAAAAAAAAAAEAAAAgAAAAAAAAAAEAAAAAAAAAAAAAAAAIAAwAAAAAAAAAAAAAAAAAAAAAAAAAAA +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +////////////////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAJIAAAAAAAAAA2YAIABA +AAAAAAgAkgAAAAAAAAADcgElBEAAAAAAAAAAAAAAAAAAAAOWACAAQAAAAAAIAAAAAgCIA4cAAFYA +IABAAAAAAAAAAAAAAAAAAAADlgAgAEAAAAAAAAAAAAAAAAAAAAOWACAAQAAAAAAAAAAAAAAAAAAA +A5YAIABAAAAAAAAAAAAAAAAAAAADlgAgAEAAAAAACAAAAAIAiAOFAACWASAAQAAAAAAAAAAAAAAA +AAAAA5YAIABAAAAAAAAAAAAAAAAAAAADlgAgAEAAAAAACAAAAAIAiAOFAACWASAAQAAAAAAAAAAA +AAAAAAAAA5YAIABAAAAAAAAAAAAAAAAAAAADlgAgAEAAAAAACAAAAAIAiAOFAACWASAAQAAAAAAA +AAAAAAAAAAAAA5YAIABAAAAAAAAAAAAAAAAAAgADlgAmBEAAAAAACEcgAQQAAAKyAALSBSAkQAAA +AAAAAAAAAAAAAAAAA5YAIABAAAAAAABHIAEGDKGCsEABkgQgJEAAAAAAAEcgAQQMoEKzgAISBSAk +QAAAAAAIAAAAAgCIA4UAAJYBIABAAAAAAAgAAAACAIgDhQAAlgEgAEAAAAAACAAAAAIAiAOFAACW +ASAAQAAAAAAAAAAAAAAAAAAAA5YAIABAAAAAAA3FEroCsIDTFFSL4kpGJEAAAAAABcUSugK3gNMU +VItiSaYkQAAAAAAFxRKiBrCA0xRUi+JKRiRAAAAAAA3FEqIGt4DTFFSLYkmmJEAAAAAABcUSogaw +gNMUVIviSkYkQAAAAAANxRKiBreA0xRUi2JJpiRAAAAAAAXFEqIGsIDTFFSL4kpGJEAAAAAADcUS +oga3gNMUVItiSaYkQAAAAAAJxBCgAgCAkAAAi2JpxiRAAAAAAAHEEKAGsICTBlSLYmnGJEAAAAAA +AcQQoAawgJMGVItiacYkQAAAAAABxRC4BrCAkxZUi2JIxiRAAAAAAAihEIgCAIFYEgALUgCmJEAA +AAAACcAQkAKwgAMWVIqSAcYkQAAAAAAJwBC4BrCAAxCUi+ICRiRAAAAAAAnAELgCtIADEJSLYgGm +JEAAAAAACcAQuAK0gAMQlItiAaYkQAAAAAAJwBC4ArSAAxCUi2IBpiRAAAAAAAnAELgCtIADEJSL +YgGmJEAAAAAAAaAQkAa0gAMQlItiAaYkQAAAAAABwBCAArCAAxRUilIAxiRAAAAAAAHAEIACsIAD +FFSKUgDGJEAAAAAAAcAQgAKwgAMUVIpSAMYkQAAAAAAIRyABBAAAArIAAtIFICRAAAAAAACBAAAC +AIVYB0ALUgCmJEAAAAAAAIEAAAIAhVgHQAtSAKYkQAAAAAAAAAAABACgQAGAAdYAIABAAAAAAAAA +AAAGAKGAAEABVgAgAEAAAAAAAAAAAAQAoEABgAHWACAAQAAAAAAIgQAAAgCFWYAEC1IApiRAAAAA +AAlhQAAAAAAYAAADQgEmpEAAAAAACEAAAAAAAAAAAANSASYkQAAAAAAAAAAABACgQAGAAdYAIABA +AAAAAAgAAAACAIgDhwAD1gAmBEAAAAAACAAAAAIAiAOHAAPWACYEQAAAAAAAAAAAAAAAAAAAA5YA +IABAAAAAAAAAAAAAAAAAAAADlgAgAEAAAAAAAAAAAAQAoEABgAHWACAAQAAAAAAJwBC4ArSAAxCU +i2IBpiRAAAAAAAAAAAAAAAAAAgADlgAmBEAAAAAAAAAAAAAAAAAAAAOWACAAQAAAAAAIAAAAAgCI +A4UAAJYBIABAAAAAAAAAAAAEAKBAAYAB1gAgAEAAAAAAAAAAAAQAoEABgAHWACAAQAAAAAAAAAAA +BACgQAGAAdYAIABAAAAAAAihEIgCAIFYEAAJEgGmJEAAAAAAAAAAAAQAoEABgAHWACAAQAAAAAAA +AAAABgChgABAAVYAIABAAAAAAAgAAAACAIgDhUAI0gJGJEAAAAAACcUSogKUiNIQgIsiSKYkQAAA +AAAJwBCAAqSIAIdUi1IBpiRAAAAAAAnAEIAGtIgDARSLUgGmJEAAAAAADcAAAAKwgMMWVIviA0Yk +QAAAAAAAAAAAAAAAAAAAA5YAIABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAwAAQAAAACAAACACYkQAAAAAAA +RzAABgMgArcACAIBwCRAAAAAAAgDAAACBqAKtQAIAgDGJEAAAAAAAAAAAAAAAAACAAACACYkQAAA +AAAAIFAABAAAAAIAAAIAJiRAAAAAAAhgIACEAAAAAAAABgAgAEAAAAAACGAgAIQAAAACATACACYl +QAAAAAAIYAAABACEAYAEBAIBxiTAAAAAAAHAAAACQ4ADAgyIAgGmJEAAAAAACABgAAQAAAACAAAC +ACYkQAAAAAAIAGAABAAAAAAAAAQBIABAAAAAAAAAAAAAAAAAAAAABAEgAEAAAAAABAgUgAYKAAAH +AUwCIKYmQAAAAAAIgAAABgCEAYAECAIBpiZAAAAAAABAAAACAKAAAkAIAgGmJEAAAAAAAAAAAAAA +AAACAAACACYkQAAAAAAEAAAAAoQAAwKKCAIEpiRAAAAAAAAAAAAAAAAAAgAABgEgSEAAAAAAACBQ +AAQAAAACAAACACYkQAAAAAAIYCAAhAAAAAIAAAYAJgRAAAAAAAhgIACEAAAAAgAAAgEmJUAAAAAA +CGAAAAQAhAGABAQCAcYkwAAAAAAIAGAABAAAAAAAAAQBIABAAAAAAAAAAAAAAAAAAAAAAgAmTHAA +AAAAAAAAAAAAAAAAAAAGASAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAItJAE +CRYEAgTGJEAAAAAAAcAAAAi0kAQJFgQCBMYkQAAAAAAECHSATAkAAFAAXAJh5iRAAAAAAAwIdIBE +AAAAUgBAAmEmJEAAAAAACAIQoAQAAAAAAQACACYkQAAAAAAIAhCgBAAAAAABAAIAJiRAAAAAAAQI +dABCAQAABwCIAmDGJEAAAAAADcgUAAIJAAAEQJwCYOYkQAAAAAAJyBCABrSQBAKUiAJlxiRAAAAA +AA3IdABItJADAJSIAmCmJMAAAAAADch0AEi0kAMAlIgCYKYkwAAAAAAIRwAABAAAAAAAAAIBICRA +AAAAAAhHAAAEAAAAAgAAAgUgJEAAAAAAAEcgAQwHIcK3AAgCAcAkQAAAAAAARyABDAchwrcACAIB +wCRAAAAAAABHIAEMByHCtwAIAgHAJEAAAAAAAAAgAQgAhAAFQIgCAcYkwAAAAAAAACABCACEAAVA +iAIBxiTAAAAAAAAAIAEIAIQABUCIAgHGJMAAAAAAAAAgAYaCAAECwIgCA8YkwAAAAAAAACABgoIA +AALAiAIDxiTAAAAAAAnAIAGCpIABBUCIAgHGJMAAAAAACAAAAAwAhAAFQIgCAcYkwAAAAAAAACAB +hoIAAQLAiAIDxiTAAAAAAAAAIAGCggAAAMCIAgKmJMAAAAAACcAgAYKkgAEFQIgCAcYkwAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAEAAQkBAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAW2dsb2JhbF0KcnNzX2dsYl9jb25maWdfbW9kZT1iYXNpY3ZpcnR1YWwKcnNzX2ds +Yl9jb25maWdfb3B0aW9ucz10bmxtYXBlbixoYXNodG9lcGxpdHosdG5sYWxsbGtwCnJlZ1sweDEw +MDhdPTB4NDA4MTAvMHgyMWM3MApyZWdbMHgxMDBjXT0weDIyMjIyMjIyCnJlZ1sweDEwYTBdPTB4 +MDEwNDA4MTAKcmVnWzB4MTA0NF09NDA5NgpyZWdbMHgxMDQ4XT02NTUzNgpyZWdbMHgxMDRjXT0x +NTM2CnJlZ1sweDEwNTBdPTkwMjQKcmVnWzB4MTA1NF09OTIxNgpyZWdbMHgxMDU4XT0yMDQ4CnJl +Z1sweDEwNWNdPTEyOApyZWdbMHgxMDYwXT04MTkyCnJlZ1sweDEwNjRdPTE2Mzg0CnJlZ1sweDEw +YTRdPTB4YTAwMGEwMDAvMHhmMDAwZjAwMApyZWdbMHgxMGE4XT0weDIwMDAvMHgyMDAwCnNnZV90 +aW1lcl92YWx1ZT01LDEwLDIwLDUwLDEwMCwyMDAKcmVnWzB4N2RjMF09MHg2MmY4ODQ5CmZpbHRl +ck1vZGU9ZnJhZ21lbnRhdGlvbixtcHNoaXR0eXBlLHByb3RvY29sLHZsYW4scG9ydCxmY29lCnRw +X3Btcng9MzAKdHBfcG1yeF9wYWdlc2l6ZT02NEsKdHBfcG10eD01MAp0cF9wbXR4X3BhZ2VzaXpl +PTY0SwpbZnVuY3Rpb24iMCJdCm52Zj0xNgp3eF9jYXBzPWFsbApyX2NhcHM9YWxsCm52aT0xCm5p +cWZsaW50PTgKbmV0aGN0cmw9OApuZXE9MTYKbmV4YWN0Zj04CmNtYXNrPWFsbApwbWFzaz0weDEK +W2Z1bmN0aW9uIjEiXQpudmY9MTYKd3hfY2Fwcz1hbGwKcl9jYXBzPWFsbApudmk9MQpuaXFmbGlu +dD04Cm5ldGhjdHJsPTgKbmVxPTE2Cm5leGFjdGY9OApjbWFzaz1hbGwKcG1hc2s9MHgyCltmdW5j +dGlvbiIyIl0KbnZmPTE2Cnd4X2NhcHM9YWxsCnJfY2Fwcz1hbGwKbnZpPTEKbmlxZmxpbnQ9OApu +ZXRoY3RybD04Cm5lcT0xNgpuZXhhY3RmPTgKY21hc2s9YWxsCnBtYXNrPTB4NApbZnVuY3Rpb24i +MyJdCm52Zj0xNgp3eF9jYXBzPWFsbApyX2NhcHM9YWxsCm52aT0xCm5pcWZsaW50PTgKbmV0aGN0 +cmw9OApuZXE9MTYKbmV4YWN0Zj04CmNtYXNrPWFsbApwbWFzaz0weDgKW2Z1bmN0aW9uIjQiXQp3 +eF9jYXBzPWFsbApyX2NhcHM9YWxsCm52aT0yOApuaXFmbGludD0xNzAKbmV0aGN0cmw9MTAwCm5l +cT0yNTYKbmV4YWN0Zj00MApjbWFzaz1hbGwKcG1hc2s9YWxsCm5ldGhvZmxkPTEwMjQKbnJvdXRl +PTMyCm5jbGlwPTMyCm5maWx0ZXI9NDk2Cm5zZXJ2ZXI9NDk2Cm5oYXNoPTEyMjg4CnByb3RvY29s +PW5pY192bSxvZmxkLHJkZHAscmRtYWMsaXNjc2lfaW5pdGlhdG9yX3BkdSxpc2NzaV90YXJnZXRf +cGR1CnRwX2wydD0zMDcyCnRwX2RkcD0yCnRwX2RkcF9pc2NzaT0yCnRwX3N0YWc9Mgp0cF9wYmw9 +NQp0cF9ycT03CltmdW5jdGlvbiI1Il0Kd3hfY2Fwcz1hbGwKcl9jYXBzPWFsbApudmk9NApuaXFm +bGludD0zNApuZXRoY3RybD0zMgpuZXE9NjQKbmV4YWN0Zj00CmNtYXNrPWFsbApwbWFzaz1hbGwK +bnNlcnZlcj0xNgpuaGFzaD0yMDQ4CnRwX2wydD0xMDI0CnByb3RvY29sPWlzY3NpX2luaXRpYXRv +cl9mb2ZsZAp0cF9kZHBfaXNjc2k9Mgppc2NzaV9udGFzaz0yMDQ4CmlzY3NpX25zZXNzPTIwNDgK +aXNjc2lfbmNvbm5fcGVyX3Nlc3Npb249MQppc2NzaV9uaW5pdGlhdG9yX2luc3RhbmNlPTY0Cltm +dW5jdGlvbiI2Il0Kd3hfY2Fwcz1hbGwKcl9jYXBzPWFsbApudmk9NApuaXFmbGludD0zNApuZXRo +Y3RybD0zMgpuZXE9NjYKbmV4YWN0Zj0zMgpjbWFzaz1hbGwKcG1hc2s9YWxsCm5oYXNoPTIwNDgK +cHJvdG9jb2w9ZmNvZV9pbml0aWF0b3IKdHBfZGRwPTIKZmNvZV9uZmNmPTE2CmZjb2VfbnZucD0z +MgpmY29lX25zc249MTAyNApbZnVuY3Rpb24iMTAyMyJdCnd4X2NhcHM9YWxsCnJfY2Fwcz1hbGwK +bnZpPTQKY21hc2s9YWxsCnBtYXNrPWFsbApuZXhhY3RmPTgKbmZpbHRlcj0xNgpbZnVuY3Rpb24i +MC8qIl0Kd3hfY2Fwcz0weDgyCnJfY2Fwcz0weDg2Cm52aT0xCm5pcWZsaW50PTQKbmV0aGN0cmw9 +MgpuZXE9NApuZXhhY3RmPTQKY21hc2s9YWxsCnBtYXNrPTB4MQpbZnVuY3Rpb24iMS8qIl0Kd3hf +Y2Fwcz0weDgyCnJfY2Fwcz0weDg2Cm52aT0xCm5pcWZsaW50PTQKbmV0aGN0cmw9MgpuZXE9NApu +ZXhhY3RmPTQKY21hc2s9YWxsCnBtYXNrPTB4MgpbZnVuY3Rpb24iMi8qIl0Kd3hfY2Fwcz0weDgy +CnJfY2Fwcz0weDg2Cm52aT0xCm5pcWZsaW50PTQKbmV0aGN0cmw9MgpuZXE9NApuZXhhY3RmPTQK +Y21hc2s9YWxsCnBtYXNrPTB4NApbZnVuY3Rpb24iMy8qIl0Kd3hfY2Fwcz0weDgyCnJfY2Fwcz0w +eDg2Cm52aT0xCm5pcWZsaW50PTQKbmV0aGN0cmw9MgpuZXE9NApuZXhhY3RmPTQKY21hc2s9YWxs +CnBtYXNrPTB4OApbcG9ydCIwIl0KZGNiPXBwcCxkY2J4CmJnX21lbT0yNQpscGJrX21lbT0yNQpo +d209MzAKbHdtPTE1CmR3bT0zMApbcG9ydCIxIl0KZGNiPXBwcCxkY2J4CmJnX21lbT0yNQpscGJr +X21lbT0yNQpod209MzAKbHdtPTE1CmR3bT0zMApbcG9ydCIyIl0KZGNiPXBwcCxkY2J4CmJnX21l +bT0yNQpscGJrX21lbT0yNQpod209MzAKbHdtPTE1CmR3bT0zMApbcG9ydCIzIl0KZGNiPXBwcCxk +Y2J4CmJnX21lbT0yNQpscGJrX21lbT0yNQpod209MzAKbHdtPTE1CmR3bT0zMApbZmluaV0KdmVy +c2lvbj0weDE0MjUwMDBjCmNoZWNrc3VtPTB4NzY4ZWY3YTUKAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AABbZ2xvYmFsXQpyc3NfZ2xiX2NvbmZpZ19tb2RlPWJhc2ljdmlydHVhbApyc3NfZ2xiX2NvbmZp +Z19vcHRpb25zPXRubG1hcGVuLGhhc2h0b2VwbGl0eix0bmxhbGxsa3AKcmVnWzB4MTAwOF09MHg0 +MDgxMC8weDIxYzcwCnJlZ1sweDEwMGNdPTB4MjIyMjIyMjIKcmVnWzB4MTBhMF09MHgwMTA0MDgx +MApyZWdbMHgxMDQ0XT00MDk2CnJlZ1sweDEwNDhdPTY1NTM2CnJlZ1sweDEwNGNdPTE1MzYKcmVn +WzB4MTA1MF09OTAyNApyZWdbMHgxMDU0XT05MjE2CnJlZ1sweDEwNThdPTIwNDgKcmVnWzB4MTA1 +Y109MTI4CnJlZ1sweDEwNjBdPTgxOTIKcmVnWzB4MTA2NF09MTYzODQKcmVnWzB4MTBhNF09MHhh +MDAwYTAwMC8weGYwMDBmMDAwCnJlZ1sweDEwYThdPTB4MjAwMC8weDIwMDAKc2dlX3RpbWVyX3Zh +bHVlPTUsMTAsMjAsNTAsMTAwLDIwMApyZWdbMHg3ZGMwXT0weDYyZjg4NDkKZmlsdGVyTW9kZT1m +cmFnbWVudGF0aW9uLG1wc2hpdHR5cGUscHJvdG9jb2wsdmxhbixwb3J0LGZjb2UKdHBfcG1yeD0z +MAp0cF9wbXJ4X3BhZ2VzaXplPTY0Swp0cF9wbXR4PTUwCnRwX3BtdHhfcGFnZXNpemU9NjRLCltm +dW5jdGlvbiIwIl0Kd3hfY2Fwcz1hbGwKcl9jYXBzPWFsbApudmk9MjgKbmlxZmxpbnQ9MTcwCm5l +dGhjdHJsPTk2Cm5lcT0yNTIKbmV4YWN0Zj00MApjbWFzaz1hbGwKcG1hc2s9YWxsCm5yb3V0ZT0z +MgpuY2xpcD0zMgpuZmlsdGVyPTQ4Cm5zZXJ2ZXI9MzIKbmhhc2g9MApwcm90b2NvbD1uaWNfdm0s +b2ZsZCxyZGRwLHJkbWFjLGlzY3NpX2luaXRpYXRvcl9wZHUsaXNjc2lfdGFyZ2V0X3BkdQp0cF9s +MnQ9MzA3Mgp0cF9kZHA9Mgp0cF9kZHBfaXNjc2k9Mgp0cF9zdGFnPTIKdHBfcGJsPTUKdHBfcnE9 +NwpbZnVuY3Rpb24iMSJdCnd4X2NhcHM9YWxsCnJfY2Fwcz1hbGwKbnZpPTQKbmlxZmxpbnQ9MzQK +bmV0aGN0cmw9MzIKbmVxPTY2Cm5leGFjdGY9MzIKY21hc2s9YWxsCnBtYXNrPWFsbApuaGFzaD0w +CnByb3RvY29sPWZjb2VfaW5pdGlhdG9yCnRwX2RkcD0yCmZjb2VfbmZjZj0xNgpmY29lX252bnA9 +MzIKZmNvZV9uc3NuPTEwMjQKW2Z1bmN0aW9uIjEwMjMiXQp3eF9jYXBzPWFsbApyX2NhcHM9YWxs +Cm52aT00CmNtYXNrPWFsbApwbWFzaz1hbGwKbmV4YWN0Zj04Cm5maWx0ZXI9MTYKW2Z1bmN0aW9u +IjAvKiJdCnd4X2NhcHM9MHg4MgpyX2NhcHM9MHg4Ngpudmk9MQpuaXFmbGludD00Cm5ldGhjdHJs +PTIKbmVxPTQKbmV4YWN0Zj00CmNtYXNrPWFsbApwbWFzaz0weDEKW2Z1bmN0aW9uIjEvKiJdCnd4 +X2NhcHM9MHg4MgpyX2NhcHM9MHg4Ngpudmk9MQpuaXFmbGludD00Cm5ldGhjdHJsPTIKbmVxPTQK +bmV4YWN0Zj00CmNtYXNrPWFsbApwbWFzaz0weDIKW3BvcnQiMCJdCmRjYj1wcHAsZGNieApiZ19t +ZW09MjUKbHBia19tZW09MjUKaHdtPTMwCmx3bT0xNQpkd209MzAKW3BvcnQiMSJdCmRjYj1wcHAs +ZGNieApiZ19tZW09MjUKbHBia19tZW09MjUKaHdtPTMwCmx3bT0xNQpkd209MzAKW3BvcnQiMiJd +CmRjYj1wcHAsZGNieApiZ19tZW09MjUKbHBia19tZW09MjUKaHdtPTMwCmx3bT0xNQpkd209MzAK +W3BvcnQiMyJdCmRjYj1wcHAsZGNieApiZ19tZW09MjUKbHBia19tZW09MjUKaHdtPTMwCmx3bT0x +NQpkd209MzAKW2ZpbmldCnZlcnNpb249MHgxNDI1MDAwYwpjaGVja3N1bT0weDRjNTY2NjM5CgAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== +==== diff --git a/sys/dev/cxgbe/firmware/t4fw_interface.h b/sys/dev/cxgbe/firmware/t4fw_interface.h index 804d09ff291..cd0381626da 100644 --- a/sys/dev/cxgbe/firmware/t4fw_interface.h +++ b/sys/dev/cxgbe/firmware/t4fw_interface.h @@ -45,9 +45,11 @@ enum fw_retval { FW_EFAULT = 14, /* bad address; fw bad */ FW_EBUSY = 16, /* resource busy */ FW_EEXIST = 17, /* file exists */ + FW_ENODEV = 19, /* no such device */ FW_EINVAL = 22, /* invalid argument */ FW_ENOSPC = 28, /* no space left on device */ FW_ENOSYS = 38, /* functionality not implemented */ + FW_ENODATA = 61, /* no data available */ FW_EPROTO = 71, /* protocol error */ FW_EADDRINUSE = 98, /* address already in use */ FW_EADDRNOTAVAIL = 99, /* cannot assigned requested address */ @@ -114,6 +116,8 @@ enum fw_wr_opcodes { FW_SCSI_TGT_ACC_WR = 0x35, FW_SCSI_TGT_XMIT_WR = 0x36, FW_SCSI_TGT_RSP_WR = 0x37, + FW_POFCOE_TCB_WR = 0x42, + FW_POFCOE_ULPTX_WR = 0x43, FW_LASTC2E_WR = 0x70 }; @@ -556,12 +560,15 @@ struct fw_eth_tx_uo_wr { __be32 op_immdlen; __be32 equiq_to_len16; __be64 r3; - __be16 ethlen; + __u8 r4; + __u8 ethlen; __be16 iplen; - __be16 udplen; + __u8 udplen; + __u8 rtplen; + __be16 r5; __be16 mss; + __be16 schedpktsize; __be32 length; - __be32 r4; }; struct fw_eq_flush_wr { @@ -708,19 +715,19 @@ enum fw_flowc_mnem_uostate { }; enum fw_flowc_mnem { - FW_FLOWC_MNEM_PFNVFN, /* PFN [15:8] VFN [7:0] */ - FW_FLOWC_MNEM_CH, - FW_FLOWC_MNEM_PORT, - FW_FLOWC_MNEM_IQID, - FW_FLOWC_MNEM_SNDNXT, - FW_FLOWC_MNEM_RCVNXT, - FW_FLOWC_MNEM_SNDBUF, - FW_FLOWC_MNEM_MSS, - FW_FLOWC_MNEM_TXDATAPLEN_MAX, - FW_FLOWC_MNEM_TCPSTATE, - FW_FLOWC_MNEM_UOSTATE, - FW_FLOWC_MNEM_SCHEDCLASS, - FW_FLOWC_MNEM_DCBPRIO, + FW_FLOWC_MNEM_PFNVFN = 0, /* PFN [15:8] VFN [7:0] */ + FW_FLOWC_MNEM_CH = 1, + FW_FLOWC_MNEM_PORT = 2, + FW_FLOWC_MNEM_IQID = 3, + FW_FLOWC_MNEM_SNDNXT = 4, + FW_FLOWC_MNEM_RCVNXT = 5, + FW_FLOWC_MNEM_SNDBUF = 6, + FW_FLOWC_MNEM_MSS = 7, + FW_FLOWC_MNEM_TXDATAPLEN_MAX = 8, + FW_FLOWC_MNEM_TCPSTATE = 9, + FW_FLOWC_MNEM_UOSTATE = 10, + FW_FLOWC_MNEM_SCHEDCLASS = 11, + FW_FLOWC_MNEM_DCBPRIO = 12, }; struct fw_flowc_mnemval { @@ -2789,6 +2796,55 @@ struct fw_scsi_tgt_rsp_wr { #define G_FW_SCSI_TGT_RSP_WR_CLASS(x) \ (((x) >> S_FW_SCSI_TGT_RSP_WR_CLASS) & M_FW_SCSI_TGT_RSP_WR_CLASS) +struct fw_pofcoe_tcb_wr { + __be32 op_compl; + __be32 equiq_to_len16; + __be64 cookie; + __be32 tid_to_port; + __be16 x_id; + __be16 vlan_id; + __be32 s_id; + __be32 d_id; + __be32 tag; + __be32 xfer_len; + __be32 r4; + __be16 r5; + __be16 iqid; +}; + +#define S_FW_POFCOE_TCB_WR_TID 12 +#define M_FW_POFCOE_TCB_WR_TID 0xfffff +#define V_FW_POFCOE_TCB_WR_TID(x) ((x) << S_FW_POFCOE_TCB_WR_TID) +#define G_FW_POFCOE_TCB_WR_TID(x) \ + (((x) >> S_FW_POFCOE_TCB_WR_TID) & M_FW_POFCOE_TCB_WR_TID) + +#define S_FW_POFCOE_TCB_WR_ALLOC 4 +#define M_FW_POFCOE_TCB_WR_ALLOC 0x1 +#define V_FW_POFCOE_TCB_WR_ALLOC(x) ((x) << S_FW_POFCOE_TCB_WR_ALLOC) +#define G_FW_POFCOE_TCB_WR_ALLOC(x) \ + (((x) >> S_FW_POFCOE_TCB_WR_ALLOC) & M_FW_POFCOE_TCB_WR_ALLOC) +#define F_FW_POFCOE_TCB_WR_ALLOC V_FW_POFCOE_TCB_WR_ALLOC(1U) + +#define S_FW_POFCOE_TCB_WR_FREE 3 +#define M_FW_POFCOE_TCB_WR_FREE 0x1 +#define V_FW_POFCOE_TCB_WR_FREE(x) ((x) << S_FW_POFCOE_TCB_WR_FREE) +#define G_FW_POFCOE_TCB_WR_FREE(x) \ + (((x) >> S_FW_POFCOE_TCB_WR_FREE) & M_FW_POFCOE_TCB_WR_FREE) +#define F_FW_POFCOE_TCB_WR_FREE V_FW_POFCOE_TCB_WR_FREE(1U) + +#define S_FW_POFCOE_TCB_WR_PORT 0 +#define M_FW_POFCOE_TCB_WR_PORT 0x7 +#define V_FW_POFCOE_TCB_WR_PORT(x) ((x) << S_FW_POFCOE_TCB_WR_PORT) +#define G_FW_POFCOE_TCB_WR_PORT(x) \ + (((x) >> S_FW_POFCOE_TCB_WR_PORT) & M_FW_POFCOE_TCB_WR_PORT) + +struct fw_pofcoe_ulptx_wr { + __be32 op_pkd; + __be32 equiq_to_len16; + __u64 cookie; +}; + + /****************************************************************************** * C O M M A N D s *********************/ @@ -2937,8 +2993,9 @@ enum fw_ldst_addrspc { FW_LDST_ADDRSPC_MPS = 0x0020, FW_LDST_ADDRSPC_FUNC = 0x0028, FW_LDST_ADDRSPC_FUNC_PCIE = 0x0029, - FW_LDST_ADDRSPC_FUNC_I2C = 0x002A, + FW_LDST_ADDRSPC_FUNC_I2C = 0x002A, /* legacy */ FW_LDST_ADDRSPC_LE = 0x0030, + FW_LDST_ADDRSPC_I2C = 0x0038, }; /* @@ -3018,17 +3075,26 @@ struct fw_ldst_cmd { __be16 nset_pkd; __be32 data[12]; } pcie; - struct fw_ldst_i2c { + struct fw_ldst_i2c_deprecated { __u8 pid_pkd; __u8 base; __u8 boffset; __u8 data; __be32 r9; + } i2c_deprecated; + struct fw_ldst_i2c { + __u8 pid; + __u8 did; + __u8 boffset; + __u8 blen; + __be32 r9; + __u8 data[48]; } i2c; struct fw_ldst_le { - __be16 region; - __be16 nval; - __u32 val[12]; + __be32 index; + __be32 r9; + __u8 val[33]; + __u8 r11[7]; } le; } u; }; @@ -3332,6 +3398,8 @@ enum fw_caps_config_fcoe { FW_CAPS_CONFIG_FCOE_INITIATOR = 0x00000001, FW_CAPS_CONFIG_FCOE_TARGET = 0x00000002, FW_CAPS_CONFIG_FCOE_CTRL_OFLD = 0x00000004, + FW_CAPS_CONFIG_POFCOE_INITIATOR = 0x00000008, + FW_CAPS_CONFIG_POFCOE_TARGET = 0x00000010, }; enum fw_memtype_cf { @@ -3465,7 +3533,8 @@ enum fw_params_param_pfvf { FW_PARAMS_PARAM_PFVF_ACTIVE_FILTER_START = 0x2D, FW_PARAMS_PARAM_PFVF_ACTIVE_FILTER_END = 0x2E, FW_PARAMS_PARAM_PFVF_ETHOFLD_START = 0x2F, - FW_PARAMS_PARAM_PFVF_ETHOFLD_END = 0x30 + FW_PARAMS_PARAM_PFVF_ETHOFLD_END = 0x30, + FW_PARAMS_PARAM_PFVF_CPLFW4MSG_CPLSGEEGRUPDATE = 0x31 }; /* @@ -3474,6 +3543,7 @@ enum fw_params_param_pfvf { enum fw_params_param_dmaq { FW_PARAMS_PARAM_DMAQ_IQ_DCAEN_DCACPU = 0x00, FW_PARAMS_PARAM_DMAQ_IQ_INTCNTTHRESH = 0x01, + FW_PARAMS_PARAM_DMAQ_IQ_INTIDX = 0x02, FW_PARAMS_PARAM_DMAQ_EQ_CMPLIQID_MNGT = 0x10, FW_PARAMS_PARAM_DMAQ_EQ_CMPLIQID_CTRL = 0x11, FW_PARAMS_PARAM_DMAQ_EQ_SCHEDCLASS_ETH = 0x12, @@ -4943,7 +5013,7 @@ struct fw_vi_cmd { __u8 portid_pkd; __u8 nmac; __u8 nmac0[6]; - __be16 rsssize_pkd; + __be16 norss_rsssize; __u8 nmac1[6]; __be16 idsiiq_pkd; __u8 nmac2[6]; @@ -4998,6 +5068,13 @@ struct fw_vi_cmd { #define G_FW_VI_CMD_PORTID(x) \ (((x) >> S_FW_VI_CMD_PORTID) & M_FW_VI_CMD_PORTID) +#define S_FW_VI_CMD_NORSS 11 +#define M_FW_VI_CMD_NORSS 0x1 +#define V_FW_VI_CMD_NORSS(x) ((x) << S_FW_VI_CMD_NORSS) +#define G_FW_VI_CMD_NORSS(x) \ + (((x) >> S_FW_VI_CMD_NORSS) & M_FW_VI_CMD_NORSS) +#define F_FW_VI_CMD_NORSS V_FW_VI_CMD_NORSS(1U) + #define S_FW_VI_CMD_RSSSIZE 0 #define M_FW_VI_CMD_RSSSIZE 0x7ff #define V_FW_VI_CMD_RSSSIZE(x) ((x) << S_FW_VI_CMD_RSSSIZE) @@ -5524,6 +5601,8 @@ enum fw_port_dcb_type { enum fw_port_diag_ops { FW_PORT_DIAGS_TEMP = 0x00, + FW_PORT_DIAGS_TX_POWER = 0x01, + FW_PORT_DIAGS_RX_POWER = 0x02, }; struct fw_port_cmd { @@ -5560,8 +5639,9 @@ struct fw_port_cmd { __be64 r9; } info; struct fw_port_diags { - __be32 diagop_diagval; - __be32 r; + __u8 diagop; + __u8 r[3]; + __be32 diagval; } diags; union fw_port_dcb { struct fw_port_dcb_pgid { @@ -5602,7 +5682,7 @@ struct fw_port_cmd { struct fw_port_dcb_control { __u8 type; __u8 all_syncd_pkd; - __be16 r10_lo[3]; + __be16 r10_lo[3]; __be64 r11; } control; } dcb; @@ -5748,18 +5828,6 @@ struct fw_port_cmd { #define G_FW_PORT_CMD_MODTYPE(x) \ (((x) >> S_FW_PORT_CMD_MODTYPE) & M_FW_PORT_CMD_MODTYPE) -#define S_FW_PORT_CMD_DIAGOP 24 -#define M_FW_PORT_CMD_DIAGOP 0xff -#define V_FW_PORT_CMD_DIAGOP(x) ((x) << S_FW_PORT_CMD_DIAGOP) -#define G_FW_PORT_CMD_DIAGOP(x) \ - (((x) >> S_FW_PORT_CMD_DIAGOP) & M_FW_PORT_CMD_DIAGOP) - -#define S_FW_PORT_CMD_DIAGVAL 0 -#define M_FW_PORT_CMD_DIAGVAL 0xffffff -#define V_FW_PORT_CMD_DIAGVAL(x) ((x) << S_FW_PORT_CMD_DIAGVAL) -#define G_FW_PORT_CMD_DIAGVAL(x) \ - (((x) >> S_FW_PORT_CMD_DIAGVAL) & M_FW_PORT_CMD_DIAGVAL) - #define S_FW_PORT_CMD_APPLY 7 #define M_FW_PORT_CMD_APPLY 0x1 #define V_FW_PORT_CMD_APPLY(x) ((x) << S_FW_PORT_CMD_APPLY) @@ -5816,6 +5884,10 @@ enum fw_port_module_type { enum fw_port_mod_sub_type { FW_PORT_MOD_SUB_TYPE_NA, FW_PORT_MOD_SUB_TYPE_MV88E114X=0x1, + FW_PORT_MOD_SUB_TYPE_TN8022=0x2, + FW_PORT_MOD_SUB_TYPE_AQ1202=0x3, + FW_PORT_MOD_SUB_TYPE_88x3120=0x4, + FW_PORT_MOD_SUB_TYPE_BCM84834=0x5, FW_PORT_MOD_SUB_TYPE_BT_VSC8634=0x8, /* @@ -5832,11 +5904,13 @@ enum fw_port_mod_sub_type { /* link down reason codes (3b) */ enum fw_port_link_dn_rc { FW_PORT_LINK_DN_RC_NONE, - FW_PORT_LINK_DN_RC_REMFLT, - FW_PORT_LINK_DN_ANEG_F, - FW_PORT_LINK_DN_MS_RES_F, - FW_PORT_LINK_DN_OVERHEAT, - FW_PORT_LINK_DN_UNKNOWN + FW_PORT_LINK_DN_RC_REMFLT, /* Remote fault detected */ + FW_PORT_LINK_DN_ANEG_F, /* Auto-negotiation fault */ + FW_PORT_LINK_DN_RESERVED3, + FW_PORT_LINK_DN_OVERHEAT, /* Port overheated */ + FW_PORT_LINK_DN_UNKNOWN, /* Unable to determine reason */ + FW_PORT_LINK_DN_RX_LOS, /* No RX signal detected */ + FW_PORT_LINK_DN_RESERVED7 }; /* port stats */ @@ -6635,7 +6709,6 @@ enum fw_sched_params_level { FW_SCHED_PARAMS_LEVEL_CL_RL = 0, FW_SCHED_PARAMS_LEVEL_CL_WRR = 1, FW_SCHED_PARAMS_LEVEL_CH_RL = 2, - FW_SCHED_PARAMS_LEVEL_CH_WRR = 3, }; enum fw_sched_params_mode { @@ -6676,7 +6749,8 @@ struct fw_sched_cmd { __be32 max; __be16 weight; __be16 pktsize; - __be32 r4; + __be16 burstsize; + __be16 r4; } params; } u; }; @@ -7353,6 +7427,16 @@ struct fw_debug_cmd { * P C I E F W R E G I S T E R **************************************/ +enum pcie_fw_eval { + PCIE_FW_EVAL_CRASH = 0, + PCIE_FW_EVAL_PREP = 1, + PCIE_FW_EVAL_CONF = 2, + PCIE_FW_EVAL_INIT = 3, + PCIE_FW_EVAL_UNEXPECTEDEVENT = 4, + PCIE_FW_EVAL_OVERHEAT = 5, + PCIE_FW_EVAL_DEVICESHUTDOWN = 6, +}; + /** * Register definitions for the PCIE_FW register which the firmware uses * to retain status across RESETs. This register should be considered @@ -7377,6 +7461,11 @@ struct fw_debug_cmd { #define G_PCIE_FW_HALT(x) (((x) >> S_PCIE_FW_HALT) & M_PCIE_FW_HALT) #define F_PCIE_FW_HALT V_PCIE_FW_HALT(1U) +#define S_PCIE_FW_EVAL 24 +#define M_PCIE_FW_EVAL 0x7 +#define V_PCIE_FW_EVAL(x) ((x) << S_PCIE_FW_EVAL) +#define G_PCIE_FW_EVAL(x) (((x) >> S_PCIE_FW_EVAL) & M_PCIE_FW_EVAL) + #define S_PCIE_FW_STAGE 21 #define M_PCIE_FW_STAGE 0x7 #define V_PCIE_FW_STAGE(x) ((x) << S_PCIE_FW_STAGE) @@ -7455,11 +7544,11 @@ struct fw_hdr { __u8 intfver_ri; __u8 intfver_iscsipdu; __u8 intfver_iscsi; + __u8 intfver_fcoepdu; __u8 intfver_fcoe; - __u8 reserved2; + __u32 reserved2; __u32 reserved3; __u32 reserved4; - __u32 reserved5; __be32 flags; __be32 reserved6[23]; }; @@ -7504,6 +7593,7 @@ enum { FW_HDR_INTFVER_RI = 0x00, FW_HDR_INTFVER_ISCSIPDU = 0x00, FW_HDR_INTFVER_ISCSI = 0x00, + FW_HDR_INTFVER_FCOEPDU = 0x00, FW_HDR_INTFVER_FCOE = 0x00, }; diff --git a/sys/modules/cxgbe/firmware/Makefile b/sys/modules/cxgbe/firmware/Makefile index b6a87299d1b..fea29a5c166 100644 --- a/sys/modules/cxgbe/firmware/Makefile +++ b/sys/modules/cxgbe/firmware/Makefile @@ -17,7 +17,7 @@ FIRMWS += ${F}:${F:C/.txt//}:1.0.0.0 .endif .endfor -T4FW_VER = 1.6.2.0 +T4FW_VER = 1.8.4.0 FIRMWS += t4fw.fw:t4fw:${T4FW_VER} CLEANFILES += t4fw.fw From 0abd31e2f72f9ec4ee855c9220dfd1115d09182c Mon Sep 17 00:00:00 2001 From: Navdeep Parhar Date: Tue, 26 Feb 2013 00:27:27 +0000 Subject: [PATCH 0408/1476] cxgbe(4): Ask the card's firmware to pad up tiny CPLs by encapsulating them in a firmware message if it is able to do so. This works out better for one of the FIFOs in the chip. MFC after: 5 days --- sys/dev/cxgbe/adapter.h | 2 +- sys/dev/cxgbe/common/t4_msg.h | 18 ++++++++--- sys/dev/cxgbe/firmware/t4fw_interface.h | 2 +- sys/dev/cxgbe/t4_main.c | 40 +++++++++++++++++++++++++ sys/dev/cxgbe/t4_sge.c | 11 +++++++ 5 files changed, 67 insertions(+), 6 deletions(-) diff --git a/sys/dev/cxgbe/adapter.h b/sys/dev/cxgbe/adapter.h index 55cfa52cc2e..eee9e1a07ff 100644 --- a/sys/dev/cxgbe/adapter.h +++ b/sys/dev/cxgbe/adapter.h @@ -600,7 +600,7 @@ struct adapter { struct callout sfl_callout; an_handler_t an_handler __aligned(CACHE_LINE_SIZE); - fw_msg_handler_t fw_msg_handler[4]; /* NUM_FW6_TYPES */ + fw_msg_handler_t fw_msg_handler[5]; /* NUM_FW6_TYPES */ cpl_handler_t cpl_handler[0xef]; /* NUM_CPL_CMDS */ #ifdef INVARIANTS diff --git a/sys/dev/cxgbe/common/t4_msg.h b/sys/dev/cxgbe/common/t4_msg.h index 92f760b7304..2111d30ffb5 100644 --- a/sys/dev/cxgbe/common/t4_msg.h +++ b/sys/dev/cxgbe/common/t4_msg.h @@ -2224,6 +2224,15 @@ struct cpl_sge_egr_update { #define V_EGR_QID(x) ((x) << S_EGR_QID) #define G_EGR_QID(x) (((x) >> S_EGR_QID) & M_EGR_QID) +/* cpl_fw*.type values */ +enum { + FW_TYPE_CMD_RPL = 0, + FW_TYPE_WR_RPL = 1, + FW_TYPE_CQE = 2, + FW_TYPE_OFLD_CONNECTION_WR_RPL = 3, + FW_TYPE_RSSCPL = 4, +}; + struct cpl_fw2_pld { RSS_HDR u8 opcode; @@ -2292,10 +2301,11 @@ struct cpl_fw6_msg { /* cpl_fw6_msg.type values */ enum { - FW6_TYPE_CMD_RPL = 0, - FW6_TYPE_WR_RPL = 1, - FW6_TYPE_CQE = 2, - FW6_TYPE_OFLD_CONNECTION_WR_RPL = 3, + FW6_TYPE_CMD_RPL = FW_TYPE_CMD_RPL, + FW6_TYPE_WR_RPL = FW_TYPE_WR_RPL, + FW6_TYPE_CQE = FW_TYPE_CQE, + FW6_TYPE_OFLD_CONNECTION_WR_RPL = FW_TYPE_OFLD_CONNECTION_WR_RPL, + FW6_TYPE_RSSCPL = FW_TYPE_RSSCPL, NUM_FW6_TYPES }; diff --git a/sys/dev/cxgbe/firmware/t4fw_interface.h b/sys/dev/cxgbe/firmware/t4fw_interface.h index cd0381626da..4b1fbff326d 100644 --- a/sys/dev/cxgbe/firmware/t4fw_interface.h +++ b/sys/dev/cxgbe/firmware/t4fw_interface.h @@ -3534,7 +3534,7 @@ enum fw_params_param_pfvf { FW_PARAMS_PARAM_PFVF_ACTIVE_FILTER_END = 0x2E, FW_PARAMS_PARAM_PFVF_ETHOFLD_START = 0x2F, FW_PARAMS_PARAM_PFVF_ETHOFLD_END = 0x30, - FW_PARAMS_PARAM_PFVF_CPLFW4MSG_CPLSGEEGRUPDATE = 0x31 + FW_PARAMS_PARAM_PFVF_CPLFW4MSG_ENCAP = 0x31 }; /* diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c index 0e24c7c8527..da3accd3d46 100644 --- a/sys/dev/cxgbe/t4_main.c +++ b/sys/dev/cxgbe/t4_main.c @@ -281,6 +281,7 @@ static int upload_config_file(struct adapter *, const struct firmware *, static int partition_resources(struct adapter *, const struct firmware *); static int get_params__pre_init(struct adapter *); static int get_params__post_init(struct adapter *); +static int set_params__post_init(struct adapter *); static void t4_set_desc(struct adapter *); static void build_medialist(struct port_info *); static int update_mac_settings(struct port_info *, int); @@ -519,6 +520,10 @@ t4_attach(device_t dev) if (rc != 0) goto done; /* error message displayed already */ + rc = set_params__post_init(sc); + if (rc != 0) + goto done; /* error message displayed already */ + if (sc->flags & MASTER_PF) { uint16_t indsz = min(RX_COPY_THRESHOLD - 1, M_INDICATESIZE); @@ -1991,6 +1996,33 @@ get_params__post_init(struct adapter *sc) return (rc); } +static int +set_params__post_init(struct adapter *sc) +{ + uint32_t param, val; + int rc; + + param = FW_PARAM_PFVF(CPLFW4MSG_ENCAP); + rc = -t4_query_params(sc, sc->mbox, sc->pf, 0, 1, ¶m, &val); + if (rc == 0) { + /* ask for encapsulated CPLs */ + param = FW_PARAM_PFVF(CPLFW4MSG_ENCAP); + val = 1; + rc = -t4_set_params(sc, sc->mbox, sc->pf, 0, 1, ¶m, &val); + if (rc != 0) { + device_printf(sc->dev, + "failed to set parameter (post_init): %d.\n", rc); + return (rc); + } + } else if (rc != FW_EINVAL) { + device_printf(sc->dev, + "failed to check for encapsulated CPLs: %d.\n", rc); + } else + rc = 0; /* the firmware doesn't support the param, no worries */ + + return (rc); +} + #undef FW_PARAM_PFVF #undef FW_PARAM_DEV @@ -3077,6 +3109,14 @@ t4_register_fw_msg_handler(struct adapter *sc, int type, fw_msg_handler_t h) if (type >= nitems(sc->fw_msg_handler)) return (EINVAL); + /* + * These are dispatched by the handler for FW{4|6}_CPL_MSG using the CPL + * handler dispatch table. Reject any attempt to install a handler for + * this subtype. + */ + if (type == FW_TYPE_RSSCPL || type == FW6_TYPE_RSSCPL) + return (EINVAL); + new = h ? (uintptr_t)h : (uintptr_t)fw_msg_not_handled; loc = (uintptr_t *) &sc->fw_msg_handler[type]; atomic_store_rel_ptr(loc, new); diff --git a/sys/dev/cxgbe/t4_sge.c b/sys/dev/cxgbe/t4_sge.c index 94dca53289c..578f06f7f8c 100644 --- a/sys/dev/cxgbe/t4_sge.c +++ b/sys/dev/cxgbe/t4_sge.c @@ -3509,6 +3509,10 @@ handle_sge_egr_update(struct sge_iq *iq, const struct rss_header *rss, return (0); } +/* handle_fw_msg works for both fw4_msg and fw6_msg because this is valid */ +CTASSERT(offsetof(struct cpl_fw4_msg, data) == \ + offsetof(struct cpl_fw6_msg, data)); + static int handle_fw_msg(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) { @@ -3518,6 +3522,13 @@ handle_fw_msg(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) KASSERT(m == NULL, ("%s: payload with opcode %02x", __func__, rss->opcode)); + if (cpl->type == FW_TYPE_RSSCPL || cpl->type == FW6_TYPE_RSSCPL) { + const struct rss_header *rss2; + + rss2 = (const struct rss_header *)&cpl->data[0]; + return (sc->cpl_handler[rss2->opcode](iq, rss2, m)); + } + return (sc->fw_msg_handler[cpl->type](sc, &cpl->data[0])); } From 36e3acbc34f6b954a1142555e58a3f1690829677 Mon Sep 17 00:00:00 2001 From: Xin LI Date: Tue, 26 Feb 2013 00:43:01 +0000 Subject: [PATCH 0409/1476] Vendor import of expat 2.1.0 (trimmed). --- Changes | 80 +- FREEBSD-Xlist | 19 + FREEBSD-upgrade | 16 - MANIFEST | 25 +- Makefile.in | 90 +- README | 14 +- configure | 22017 -------------------------------- configure.in | 17 +- doc/reference.html | 61 +- doc/valid-xhtml10.png | Bin 2368 -> 0 bytes doc/xmlwf.sgml | 5 - expat_config.h.in | 14 +- lib/expat.h | 39 +- lib/winconfig.h | 30 - lib/xmlparse.c | 367 +- lib/xmlrole.c | 2 +- lib/xmltok.c | 6 +- lib/xmltok_impl.c | 2 +- tests/README.txt | 5 +- tests/benchmark/benchmark.dsp | 88 - tests/benchmark/benchmark.dsw | 44 - tests/minicheck.h | 9 +- tests/runtests.c | 3 +- tests/xmltest.sh | 7 +- xmlwf/readfilemap.c | 2 + xmlwf/xmlwf.c | 4 +- 26 files changed, 533 insertions(+), 22433 deletions(-) create mode 100644 FREEBSD-Xlist delete mode 100644 FREEBSD-upgrade delete mode 100755 configure delete mode 100755 doc/valid-xhtml10.png delete mode 100644 lib/winconfig.h delete mode 100755 tests/benchmark/benchmark.dsp delete mode 100755 tests/benchmark/benchmark.dsw diff --git a/Changes b/Changes index 1e885ab75c9..08897b9f9ed 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,41 @@ +Release 2.1.0 Sat March 24 2012 + - Bug Fixes: + #1742315: Harmful XML_ParserCreateNS suggestion. + #2895533: CVE-2012-1147 - Resource leak in readfilemap.c. + #1785430: Expat build fails on linux-amd64 with gcc version>=4.1 -O3. + #1983953, 2517952, 2517962, 2649838: + Build modifications using autoreconf instead of buildconf.sh. + #2815947, #2884086: OBJEXT and EXEEXT support while building. + #1990430: CVE-2009-3720 - Parser crash with special UTF-8 sequences. + #2517938: xmlwf should return non-zero exit status if not well-formed. + #2517946: Wrong statement about XMLDecl in xmlwf.1 and xmlwf.sgml. + #2855609: Dangling positionPtr after error. + #2894085: CVE-2009-3560 - Buffer over-read and crash in big2_toUtf8(). + #2958794: CVE-2012-1148 - Memory leak in poolGrow. + #2990652: CMake support. + #3010819: UNEXPECTED_STATE with a trailing "%" in entity value. + #3206497: Unitialized memory returned from XML_Parse. + #3287849: make check fails on mingw-w64. + #3496608: CVE-2012-0876 - Hash DOS attack. + - Patches: + #1749198: pkg-config support. + #3010222: Fix for bug #3010819. + #3312568: CMake support. + #3446384: Report byte offsets for attr names and values. + - New Features / API changes: + Added new API member XML_SetHashSalt() that allows setting an intial + value (salt) for hash calculations. This is part of the fix for + bug #3496608 to randomize hash parameters. + When compiled with XML_ATTR_INFO defined, adds new API member + XML_GetAttributeInfo() that allows retrieving the byte + offsets for attribute names and values (patch #3446384). + Added CMake build system. + See bug #2990652 and patch #3312568. + Added run-benchmark target to Makefile.in - relies on testdata module + present in the same relative location as in the repository. + Release 2.0.1 Tue June 5 2007 - - Fixed bugs #1515266, 1515600: The character data handler's calling + - Fixed bugs #1515266, #1515600: The character data handler's calling of XML_StopParser() was not handled properly; if the parser was stopped and the handler set to NULL, the parser would segfault. - Fixed bug #1690883: Expat failed on EBCDIC systems as it assumed @@ -8,7 +44,7 @@ Release 2.0.1 Tue June 5 2007 - Fixed xmlwf bug #1513566: "out of memory" error on file size zero. - Fixed outline.c bug #1543233: missing a final XML_ParserFree() call. - Fixes and improvements for Windows platform: - bugs #1409451, #1476160, 1548182, 1602769, 1717322. + bugs #1409451, #1476160, #1548182, #1602769, #1717322. - Build fixes for various platforms: HP-UX, Tru64, Solaris 9: patch #1437840, bug #1196180. All Unix: #1554618 (refreshed config.sub/config.guess). @@ -30,8 +66,8 @@ Release 2.0.0 Wed Jan 11 2006 byte indexes and line/column numbers. - Updated to use libtool 1.5.22 (the most recent). - Added support for AmigaOS. - - Some mostly minor bug fixes. SF issues include: 1006708, - 1021776, 1023646, 1114960, 1156398, 1221160, 1271642. + - Some mostly minor bug fixes. SF issues include: #1006708, + #1021776, #1023646, #1114960, #1156398, #1221160, #1271642. Release 1.95.8 Fri Jul 23 2004 - Major new feature: suspend/resume. Handlers can now request @@ -40,8 +76,8 @@ Release 1.95.8 Fri Jul 23 2004 documentation for more details. - Some mostly minor bug fixes, but compilation should no longer generate warnings on most platforms. SF issues - include: 827319, 840173, 846309, 888329, 896188, 923913, - 928113, 961698, 985192. + include: #827319, #840173, #846309, #888329, #896188, #923913, + #928113, #961698, #985192. Release 1.95.7 Mon Oct 20 2003 - Fixed enum XML_Status issue (reported on SourceForge many @@ -54,19 +90,19 @@ Release 1.95.7 Mon Oct 20 2003 - Improved ability to build without the configure-generated expat_config.h header. This is useful for applications which embed Expat rather than linking in the library. - - Fixed a variety of bugs: see SF issues 458907, 609603, - 676844, 679754, 692878, 692964, 695401, 699323, 699487, - 820946. + - Fixed a variety of bugs: see SF issues #458907, #609603, + #676844, #679754, #692878, #692964, #695401, #699323, #699487, + #820946. - Improved hash table lookups. - Added more regression tests and improved documentation. Release 1.95.6 Tue Jan 28 2003 - Added XML_FreeContentModel(). - Added XML_MemMalloc(), XML_MemRealloc(), XML_MemFree(). - - Fixed a variety of bugs: see SF issues 615606, 616863, - 618199, 653180, 673791. + - Fixed a variety of bugs: see SF issues #615606, #616863, + #618199, #653180, #673791. - Enhanced the regression test suite. - - Man page improvements: includes SF issue 632146. + - Man page improvements: includes SF issue #632146. Release 1.95.5 Fri Sep 6 2002 - Added XML_UseForeignDTD() for improved SAX2 support. @@ -84,9 +120,9 @@ Release 1.95.5 Fri Sep 6 2002 - Reduced line-length for all source code and headers to be no longer than 80 characters, to help with AS/400 support. - Reduced memory copying during parsing (SF patch #600964). - - Fixed a variety of bugs: see SF issues 580793, 434664, - 483514, 580503, 581069, 584041, 584183, 584832, 585537, - 596555, 596678, 598352, 598944, 599715, 600479, 600971. + - Fixed a variety of bugs: see SF issues #580793, #434664, + #483514, #580503, #581069, #584041, #584183, #584832, #585537, + #596555, #596678, #598352, #598944, #599715, #600479, #600971. Release 1.95.4 Fri Jul 12 2002 - Added support for VMS, contributed by Craig Berry. See @@ -95,14 +131,14 @@ Release 1.95.4 Fri Jul 12 2002 contributed by Thomas Wegner and Daryle Walker. - Added Borland C++ Builder 5 / BCC 5.5 support, contributed by Patrick McConnell (SF patch #538032). - - Fixed a variety of bugs: see SF issues 441449, 563184, - 564342, 566334, 566901, 569461, 570263, 575168, 579196. + - Fixed a variety of bugs: see SF issues #441449, #563184, + #564342, #566334, #566901, #569461, #570263, #575168, #579196. - Made skippedEntityHandler conform to SAX2 (see source comment) - Re-implemented WFC: Entity Declared from XML 1.0 spec and added a new error "entity declared in parameter entity": - see SF bug report 569461 and SF patch 578161 + see SF bug report #569461 and SF patch #578161 - Re-implemented section 5.1 from XML 1.0 spec: - see SF bug report 570263 and SF patch 578161 + see SF bug report #570263 and SF patch #578161 Release 1.95.3 Mon Jun 3 2002 - Added a project to the MSVC workspace to create a wchar_t @@ -114,9 +150,9 @@ Release 1.95.3 Mon Jun 3 2002 - Made the XML_UNICODE builds usable (thanks, Karl!). - Allow xmlwf to read from standard input. - Install a man page for xmlwf on Unix systems. - - Fixed many bugs; see SF bug reports 231864, 461380, 464837, - 466885, 469226, 477667, 484419, 487840, 494749, 496505, - 547350. Other bugs which we can't test as easily may also + - Fixed many bugs; see SF bug reports #231864, #461380, #464837, + #466885, #469226, #477667, #484419, #487840, #494749, #496505, + #547350. Other bugs which we can't test as easily may also have been fixed, especially in the area of build support. Release 1.95.2 Fri Jul 27 2001 diff --git a/FREEBSD-Xlist b/FREEBSD-Xlist new file mode 100644 index 00000000000..26bed47ba54 --- /dev/null +++ b/FREEBSD-Xlist @@ -0,0 +1,19 @@ +# $FreeBSD$ +*.MPW +*.cmake +*.def +*.dsp +*.dsw +*.m4 +*.pc.in +*config.h +CMake* +Configure* +amiga +bcb5 +configure +conftools +doc/valid-xhtml10.png +m4 +vms +win32 diff --git a/FREEBSD-upgrade b/FREEBSD-upgrade deleted file mode 100644 index 8fd9a57804f..00000000000 --- a/FREEBSD-upgrade +++ /dev/null @@ -1,16 +0,0 @@ -$FreeBSD$ - -eXpat from www.libexpat.org - -Imported by: - - tar zxvf expat-1.95.5.tar.gz - cd expat-1.95.5 - rm -rf bcb5 win32 vms conftools doc/valid-xhtml10.png - vi FREEBSD-upgrade - cvs import -m "Virgin import (trimmed) of eXpat version 1.95.5" \ - src/contrib/expat EXPAT v1_95_5 - -phk@FreeBSD.org - - diff --git a/MANIFEST b/MANIFEST index aa83d5bf16f..7a020dc05b0 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1,5 +1,8 @@ -amiga/stdlib.c amiga/launch.c +amiga/expat_68k.c +amiga/expat_68k.h +amiga/expat_68k_handler_stubs.c +amiga/expat_base.h amiga/expat_vectors.c amiga/expat_lib.c amiga/expat.xml @@ -42,25 +45,35 @@ doc/style.css doc/valid-xhtml10.png doc/xmlwf.1 doc/xmlwf.sgml +CMakeLists.txt +CMake.README COPYING Changes +ConfigureChecks.cmake MANIFEST Makefile.in README configure configure.in expat_config.h.in +expat_config.h.cmake +expat.pc.in expat.dsw +aclocal.m4 conftools/PrintPath conftools/ac_c_bigendian_cross.m4 -conftools/config.guess -conftools/config.sub conftools/expat.m4 conftools/get-version.sh -conftools/install-sh -conftools/libtool.m4 -conftools/ltmain.sh conftools/mkinstalldirs +conftools/config.guess +conftools/config.sub +conftools/install-sh +conftools/ltmain.sh +m4/libtool.m4 +m4/ltversion.m4 +m4/ltoptions.m4 +m4/ltsugar.m4 +m4/lt~obsolete.m4 examples/elements.c examples/elements.dsp examples/outline.c diff --git a/Makefile.in b/Makefile.in index 0e2cc959dce..9c0f5d49f0f 100644 --- a/Makefile.in +++ b/Makefile.in @@ -31,6 +31,7 @@ bindir = @bindir@ libdir = @libdir@ includedir = @includedir@ man1dir = @mandir@/man1 +pkgconfigdir = $(libdir)/pkgconfig top_builddir = . @@ -46,18 +47,18 @@ LIBRARY = libexpat.la DESTDIR = $(INSTALL_ROOT) -default: buildlib xmlwf/xmlwf +default: buildlib xmlwf/xmlwf@EXEEXT@ -buildlib: $(LIBRARY) +buildlib: $(LIBRARY) expat.pc -all: $(LIBRARY) xmlwf/xmlwf examples/elements examples/outline +all: $(LIBRARY) expat.pc xmlwf/xmlwf@EXEEXT@ examples/elements examples/outline clean: - cd lib && rm -f $(LIBRARY) *.o *.lo && rm -rf .libs _libs - cd xmlwf && rm -f xmlwf *.o *.lo && rm -rf .libs _libs - cd examples && rm -f elements outline *.o *.lo && rm -rf .libs _libs - cd tests && rm -rf .libs runtests runtests.o runtestspp runtestspp.o - cd tests && rm -f chardata.o minicheck.o + cd lib && rm -f $(LIBRARY) *.@OBJEXT@ *.lo && rm -rf .libs _libs + cd xmlwf && rm -f xmlwf *.@OBJEXT@ *.lo && rm -rf .libs _libs + cd examples && rm -f elements outline *.@OBJEXT@ *.lo && rm -rf .libs _libs + cd tests && rm -rf .libs runtests runtests.@OBJEXT@ runtestspp runtestspp.@OBJEXT@ + cd tests && rm -f chardata.@OBJEXT@ minicheck.@OBJEXT@ rm -rf .libs libexpat.la rm -f examples/core tests/core xmlwf/core @@ -65,34 +66,37 @@ clobber: clean distclean: clean rm -f expat_config.h config.status config.log config.cache libtool - rm -f Makefile + rm -f Makefile expat.pc extraclean: distclean rm -f expat_config.h.in configure - rm -f conftools/ltconfig conftools/ltmain.sh conftools/libtool.m4 + rm -f aclocal.m4 m4/* + rm -f conftools/ltmain.sh conftools/install-sh conftools/config.guess conftools/config.sub check: tests/runtests tests/runtestspp tests/runtests tests/runtestspp -install: xmlwf/xmlwf installlib +install: xmlwf/xmlwf@EXEEXT@ installlib $(mkinstalldirs) $(DESTDIR)$(bindir) $(DESTDIR)$(man1dir) - $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) xmlwf/xmlwf $(DESTDIR)$(bindir)/xmlwf + $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) xmlwf/xmlwf@EXEEXT@ $(DESTDIR)$(bindir)/xmlwf $(INSTALL_DATA) $(MANFILE) $(DESTDIR)$(man1dir) -installlib: $(LIBRARY) $(APIHEADER) - $(mkinstalldirs) $(DESTDIR)$(libdir) $(DESTDIR)$(includedir) +installlib: $(LIBRARY) $(APIHEADER) expat.pc + $(mkinstalldirs) $(DESTDIR)$(libdir) $(DESTDIR)$(includedir) $(DESTDIR)$(pkgconfigdir) $(LIBTOOL) --mode=install $(INSTALL) $(LIBRARY) $(DESTDIR)$(libdir)/$(LIBRARY) for FN in $(APIHEADER) ; do $(INSTALL_DATA) $$FN $(DESTDIR)$(includedir) ; done + $(INSTALL_DATA) expat.pc $(DESTDIR)$(pkgconfigdir)/expat.pc uninstall: uninstalllib - $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(bindir)/xmlwf + $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(bindir)/xmlwf@EXEEXT@ rm -f $(DESTDIR)$(man1dir)/xmlwf.1 uninstalllib: $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$(LIBRARY) rm -f $(DESTDIR)$(includedir)/expat.h rm -f $(DESTDIR)$(includedir)/expat_external.h + rm -f $(DESTDIR)$(pkgconfigdir)/expat.pc # for VPATH builds (invoked by configure) mkdir-init: @@ -125,6 +129,9 @@ LIB_OBJS = lib/xmlparse.lo lib/xmltok.lo lib/xmlrole.lo $(LIBRARY): $(LIB_OBJS) $(LINK_LIB) $(LIB_OBJS) +expat.pc: $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $@ + lib/xmlparse.lo: lib/xmlparse.c lib/expat.h lib/xmlrole.h lib/xmltok.h \ $(top_builddir)/expat_config.h lib/expat_external.h lib/internal.h @@ -137,46 +144,53 @@ lib/xmltok.lo: lib/xmltok.c lib/xmltok_impl.c lib/xmltok_ns.c \ $(top_builddir)/expat_config.h lib/expat_external.h lib/internal.h -XMLWF_OBJS = xmlwf/xmlwf.o xmlwf/xmlfile.o xmlwf/codepage.o xmlwf/@FILEMAP@.o -xmlwf/xmlwf.o: xmlwf/xmlwf.c -xmlwf/xmlfile.o: xmlwf/xmlfile.c -xmlwf/codepage.o: xmlwf/codepage.c -xmlwf/@FILEMAP@.o: xmlwf/@FILEMAP@.c -xmlwf/xmlwf: $(XMLWF_OBJS) $(LIBRARY) +XMLWF_OBJS = xmlwf/xmlwf.@OBJEXT@ xmlwf/xmlfile.@OBJEXT@ xmlwf/codepage.@OBJEXT@ xmlwf/@FILEMAP@.@OBJEXT@ +xmlwf/xmlwf.@OBJEXT@: xmlwf/xmlwf.c +xmlwf/xmlfile.@OBJEXT@: xmlwf/xmlfile.c +xmlwf/codepage.@OBJEXT@: xmlwf/codepage.c +xmlwf/@FILEMAP@.@OBJEXT@: xmlwf/@FILEMAP@.c +xmlwf/xmlwf@EXEEXT@: $(XMLWF_OBJS) $(LIBRARY) $(LINK_EXE) $(XMLWF_OBJS) $(LIBRARY) -examples/elements.o: examples/elements.c -examples/elements: examples/elements.o $(LIBRARY) +examples/elements.@OBJEXT@: examples/elements.c +examples/elements: examples/elements.@OBJEXT@ $(LIBRARY) $(LINK_EXE) $< $(LIBRARY) -examples/outline.o: examples/outline.c -examples/outline: examples/outline.o $(LIBRARY) +examples/outline.@OBJEXT@: examples/outline.c +examples/outline: examples/outline.@OBJEXT@ $(LIBRARY) $(LINK_EXE) $< $(LIBRARY) -tests/chardata.o: tests/chardata.c tests/chardata.h -tests/minicheck.o: tests/minicheck.c tests/minicheck.h -tests/runtests.o: tests/runtests.c tests/chardata.h -tests/runtests: tests/runtests.o tests/chardata.o tests/minicheck.o $(LIBRARY) - $(LINK_EXE) tests/runtests.o tests/chardata.o tests/minicheck.o $(LIBRARY) -tests/runtestspp.o: tests/runtestspp.cpp tests/runtests.c tests/chardata.h -tests/runtestspp: tests/runtestspp.o tests/chardata.o tests/minicheck.o $(LIBRARY) - $(LINK_CXX_EXE) tests/runtestspp.o tests/chardata.o tests/minicheck.o $(LIBRARY) +tests/chardata.@OBJEXT@: tests/chardata.c tests/chardata.h +tests/minicheck.@OBJEXT@: tests/minicheck.c tests/minicheck.h +tests/runtests.@OBJEXT@: tests/runtests.c tests/chardata.h +tests/runtests: tests/runtests.@OBJEXT@ tests/chardata.@OBJEXT@ tests/minicheck.@OBJEXT@ $(LIBRARY) + $(LINK_EXE) tests/runtests.@OBJEXT@ tests/chardata.@OBJEXT@ tests/minicheck.@OBJEXT@ $(LIBRARY) +tests/runtestspp.@OBJEXT@: tests/runtestspp.cpp tests/runtests.c tests/chardata.h +tests/runtestspp: tests/runtestspp.@OBJEXT@ tests/chardata.@OBJEXT@ tests/minicheck.@OBJEXT@ $(LIBRARY) + $(LINK_CXX_EXE) tests/runtestspp.@OBJEXT@ tests/chardata.@OBJEXT@ tests/minicheck.@OBJEXT@ $(LIBRARY) + +tests/benchmark/benchmark.@OBJEXT@: tests/benchmark/benchmark.c +tests/benchmark/benchmark: tests/benchmark/benchmark.@OBJEXT@ $(LIBRARY) + $(LINK_EXE) tests/benchmark/benchmark.@OBJEXT@ $(LIBRARY) + +run-benchmark: tests/benchmark/benchmark + tests/benchmark/benchmark@EXEEXT@ -n $(top_srcdir)/../testdata/largefiles/recset.xml 65535 3 tests/xmlts.zip: wget --output-document=tests/xmlts.zip \ - http://www.w3.org/XML/Test/xmlts20020606.zip + http://www.w3.org/XML/Test/xmlts20080827.zip tests/XML-Test-Suite: tests/xmlts.zip cd tests && unzip -q xmlts.zip -run-xmltest: xmlwf/xmlwf tests/XML-Test-Suite +run-xmltest: xmlwf/xmlwf@EXEEXT@ tests/XML-Test-Suite tests/xmltest.sh -.SUFFIXES: .c .cpp .lo .o +.SUFFIXES: .c .cpp .lo .@OBJEXT@ -.cpp.o: +.cpp.@OBJEXT@: $(CXXCOMPILE) -o $@ -c $< -.c.o: +.c.@OBJEXT@: $(COMPILE) -o $@ -c $< .c.lo: $(LTCOMPILE) -o $@ -c $< diff --git a/README b/README index fda282a8f54..1f88467d1b0 100644 --- a/README +++ b/README @@ -1,5 +1,5 @@ - Expat, Release 2.0.1 + Expat, Release 2.1.0 This is Expat, a C library for parsing XML, written by James Clark. Expat is a stream-oriented XML parser. This means that you register @@ -25,8 +25,7 @@ intended to be production grade software. If you are building Expat from a check-out from the CVS repository, you need to run a script that generates the configure script using the GNU autoconf and libtool tools. To do this, you need to have -autoconf 2.52 or newer and libtool 1.4 or newer (1.5 or newer preferred). -Run the script like this: +autoconf 2.58 or newer. Run the script like this: ./buildconf.sh @@ -65,8 +64,8 @@ location. Have a look at the "Makefile" to learn about additional the directories into which things will be installed. If you are interested in building Expat to provide document -information in UTF-16 rather than the default UTF-8, follow these -instructions (after having run "make distclean"): +information in UTF-16 encoding rather than the default UTF-8, follow +these instructions (after having run "make distclean"): 1. For UTF-16 output as unsigned short (and version/error strings as char), run: @@ -106,7 +105,10 @@ use DESTDIR=$(INSTALL_ROOT), even if DESTDIR eventually is defined in the environment, because variable-setting priority is 1) commandline 2) in-makefile -3) environment +3) environment + +Note: This only applies to the Expat library itself, building UTF-16 versions +of xmlwf and the tests is currently not supported. Note for Solaris users: The "ar" command is usually located in "/usr/ccs/bin", which is not in the default PATH. You will need to diff --git a/configure b/configure deleted file mode 100755 index 01ba7a99280..00000000000 --- a/configure +++ /dev/null @@ -1,22017 +0,0 @@ -#! /bin/sh -# Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.59 for expat 2.0.1. -# -# Report bugs to . -# -# Copyright (C) 2003 Free Software Foundation, Inc. -# This configure script is free software; the Free Software Foundation -# gives unlimited permission to copy, distribute and modify it. -## --------------------- ## -## M4sh Initialization. ## -## --------------------- ## - -# Be Bourne compatible -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' -elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then - set -o posix -fi -DUALCASE=1; export DUALCASE # for MKS sh - -# Support unset when possible. -if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then - as_unset=unset -else - as_unset=false -fi - - -# Work around bugs in pre-3.0 UWIN ksh. -$as_unset ENV MAIL MAILPATH -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -for as_var in \ - LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ - LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ - LC_TELEPHONE LC_TIME -do - if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then - eval $as_var=C; export $as_var - else - $as_unset $as_var - fi -done - -# Required to use basename. -if expr a : '\(a\)' >/dev/null 2>&1; then - as_expr=expr -else - as_expr=false -fi - -if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - - -# Name of the executable. -as_me=`$as_basename "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)$' \| \ - . : '\(.\)' 2>/dev/null || -echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } - /^X\/\(\/\/\)$/{ s//\1/; q; } - /^X\/\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - - -# PATH needs CR, and LINENO needs CR and PATH. -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - echo "#! /bin/sh" >conf$$.sh - echo "exit 0" >>conf$$.sh - chmod +x conf$$.sh - if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then - PATH_SEPARATOR=';' - else - PATH_SEPARATOR=: - fi - rm -f conf$$.sh -fi - - - as_lineno_1=$LINENO - as_lineno_2=$LINENO - as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x$as_lineno_3" = "x$as_lineno_2" || { - # Find who we are. Look in the path if we contain no path at all - # relative or not. - case $0 in - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break -done - - ;; - esac - # We did not find ourselves, most probably we were run as `sh COMMAND' - # in which case we are not to be found in the path. - if test "x$as_myself" = x; then - as_myself=$0 - fi - if test ! -f "$as_myself"; then - { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 - { (exit 1); exit 1; }; } - fi - case $CONFIG_SHELL in - '') - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for as_base in sh bash ksh sh5; do - case $as_dir in - /*) - if ("$as_dir/$as_base" -c ' - as_lineno_1=$LINENO - as_lineno_2=$LINENO - as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then - $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } - $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } - CONFIG_SHELL=$as_dir/$as_base - export CONFIG_SHELL - exec "$CONFIG_SHELL" "$0" ${1+"$@"} - fi;; - esac - done -done -;; - esac - - # Create $as_me.lineno as a copy of $as_myself, but with $LINENO - # uniformly replaced by the line number. The first 'sed' inserts a - # line-number line before each line; the second 'sed' does the real - # work. The second script uses 'N' to pair each line-number line - # with the numbered line, and appends trailing '-' during - # substitution so that $LINENO is not a special case at line end. - # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the - # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) - sed '=' <$as_myself | - sed ' - N - s,$,-, - : loop - s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, - t loop - s,-$,, - s,^['$as_cr_digits']*\n,, - ' >$as_me.lineno && - chmod +x $as_me.lineno || - { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 - { (exit 1); exit 1; }; } - - # Don't try to exec as it changes $[0], causing all sort of problems - # (the dirname of $[0] is not the place where we might find the - # original and so on. Autoconf is especially sensible to this). - . ./$as_me.lineno - # Exit status is that of the last command. - exit -} - - -case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in - *c*,-n*) ECHO_N= ECHO_C=' -' ECHO_T=' ' ;; - *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; - *) ECHO_N= ECHO_C='\c' ECHO_T= ;; -esac - -if expr a : '\(a\)' >/dev/null 2>&1; then - as_expr=expr -else - as_expr=false -fi - -rm -f conf$$ conf$$.exe conf$$.file -echo >conf$$.file -if ln -s conf$$.file conf$$ 2>/dev/null; then - # We could just check for DJGPP; but this test a) works b) is more generic - # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). - if test -f conf$$.exe; then - # Don't use ln at all; we don't have any links - as_ln_s='cp -p' - else - as_ln_s='ln -s' - fi -elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln -else - as_ln_s='cp -p' -fi -rm -f conf$$ conf$$.exe conf$$.file - -if mkdir -p . 2>/dev/null; then - as_mkdir_p=: -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - -as_executable_p="test -f" - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - - -# IFS -# We need space, tab and new line, in precisely that order. -as_nl=' -' -IFS=" $as_nl" - -# CDPATH. -$as_unset CDPATH - - - -# Check that we are running under the correct shell. -SHELL=${CONFIG_SHELL-/bin/sh} - -case X$ECHO in -X*--fallback-echo) - # Remove one level of quotation (which was required for Make). - ECHO=`echo "$ECHO" | sed 's,\\\\\$\\$0,'$0','` - ;; -esac - -echo=${ECHO-echo} -if test "X$1" = X--no-reexec; then - # Discard the --no-reexec flag, and continue. - shift -elif test "X$1" = X--fallback-echo; then - # Avoid inline document here, it may be left over - : -elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then - # Yippee, $echo works! - : -else - # Restart under the correct shell. - exec $SHELL "$0" --no-reexec ${1+"$@"} -fi - -if test "X$1" = X--fallback-echo; then - # used as fallback echo - shift - cat </dev/null 2>&1 && unset CDPATH - -if test -z "$ECHO"; then -if test "X${echo_test_string+set}" != Xset; then -# find a string as large as possible, as long as the shell can cope with it - for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do - # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... - if (echo_test_string=`eval $cmd`) 2>/dev/null && - echo_test_string=`eval $cmd` && - (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null - then - break - fi - done -fi - -if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && - echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - : -else - # The Solaris, AIX, and Digital Unix default echo programs unquote - # backslashes. This makes it impossible to quote backslashes using - # echo "$something" | sed 's/\\/\\\\/g' - # - # So, first we look for a working echo in the user's PATH. - - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for dir in $PATH /usr/ucb; do - IFS="$lt_save_ifs" - if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && - test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && - echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - echo="$dir/echo" - break - fi - done - IFS="$lt_save_ifs" - - if test "X$echo" = Xecho; then - # We didn't find a better echo, so look for alternatives. - if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && - echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - # This shell has a builtin print -r that does the trick. - echo='print -r' - elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && - test "X$CONFIG_SHELL" != X/bin/ksh; then - # If we have ksh, try running configure again with it. - ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} - export ORIGINAL_CONFIG_SHELL - CONFIG_SHELL=/bin/ksh - export CONFIG_SHELL - exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"} - else - # Try using printf. - echo='printf %s\n' - if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && - echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - # Cool, printf works - : - elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && - test "X$echo_testing_string" = 'X\t' && - echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL - export CONFIG_SHELL - SHELL="$CONFIG_SHELL" - export SHELL - echo="$CONFIG_SHELL $0 --fallback-echo" - elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && - test "X$echo_testing_string" = 'X\t' && - echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - echo="$CONFIG_SHELL $0 --fallback-echo" - else - # maybe with a smaller string... - prev=: - - for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do - if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null - then - break - fi - prev="$cmd" - done - - if test "$prev" != 'sed 50q "$0"'; then - echo_test_string=`eval $prev` - export echo_test_string - exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"} - else - # Oops. We lost completely, so just stick with echo. - echo=echo - fi - fi - fi - fi -fi -fi - -# Copy echo and quote the copy suitably for passing to libtool from -# the Makefile, instead of quoting the original, which is used later. -ECHO=$echo -if test "X$ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then - ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo" -fi - - - - -tagnames=${tagnames+${tagnames},}CXX - -tagnames=${tagnames+${tagnames},}F77 - -# Name of the host. -# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, -# so uname gets run too. -ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` - -exec 6>&1 - -# -# Initializations. -# -ac_default_prefix=/usr/local -ac_config_libobj_dir=. -cross_compiling=no -subdirs= -MFLAGS= -MAKEFLAGS= -SHELL=${CONFIG_SHELL-/bin/sh} - -# Maximum number of lines to put in a shell here document. -# This variable seems obsolete. It should probably be removed, and -# only ac_max_sed_lines should be used. -: ${ac_max_here_lines=38} - -# Identity of this package. -PACKAGE_NAME='expat' -PACKAGE_TARNAME='expat' -PACKAGE_VERSION='2.0.1' -PACKAGE_STRING='expat 2.0.1' -PACKAGE_BUGREPORT='expat-bugs@libexpat.org' - -ac_unique_file="Makefile.in" -# Factoring default headers for most tests. -ac_includes_default="\ -#include -#if HAVE_SYS_TYPES_H -# include -#endif -#if HAVE_SYS_STAT_H -# include -#endif -#if STDC_HEADERS -# include -# include -#else -# if HAVE_STDLIB_H -# include -# endif -#endif -#if HAVE_STRING_H -# if !STDC_HEADERS && HAVE_MEMORY_H -# include -# endif -# include -#endif -#if HAVE_STRINGS_H -# include -#endif -#if HAVE_INTTYPES_H -# include -#else -# if HAVE_STDINT_H -# include -# endif -#endif -#if HAVE_UNISTD_H -# include -#endif" - -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT EGREP LN_S ECHO AR ac_ct_AR RANLIB ac_ct_RANLIB STRIP ac_ct_STRIP DLLTOOL ac_ct_DLLTOOL AS ac_ct_AS OBJDUMP ac_ct_OBJDUMP CPP CXX CXXFLAGS ac_ct_CXX CXXCPP F77 FFLAGS ac_ct_F77 LIBTOOL LIBCURRENT LIBREVISION LIBAGE INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA FILEMAP LIBOBJS LTLIBOBJS' -ac_subst_files='' - -# Initialize some variables set by options. -ac_init_help= -ac_init_version=false -# The variables have the same names as the options, with -# dashes changed to underlines. -cache_file=/dev/null -exec_prefix=NONE -no_create= -no_recursion= -prefix=NONE -program_prefix=NONE -program_suffix=NONE -program_transform_name=s,x,x, -silent= -site= -srcdir= -verbose= -x_includes=NONE -x_libraries=NONE - -# Installation directory options. -# These are left unexpanded so users can "make install exec_prefix=/foo" -# and all the variables that are supposed to be based on exec_prefix -# by default will actually change. -# Use braces instead of parens because sh, perl, etc. also accept them. -bindir='${exec_prefix}/bin' -sbindir='${exec_prefix}/sbin' -libexecdir='${exec_prefix}/libexec' -datadir='${prefix}/share' -sysconfdir='${prefix}/etc' -sharedstatedir='${prefix}/com' -localstatedir='${prefix}/var' -libdir='${exec_prefix}/lib' -includedir='${prefix}/include' -oldincludedir='/usr/include' -infodir='${prefix}/info' -mandir='${prefix}/man' - -ac_prev= -for ac_option -do - # If the previous option needs an argument, assign it. - if test -n "$ac_prev"; then - eval "$ac_prev=\$ac_option" - ac_prev= - continue - fi - - ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` - - # Accept the important Cygnus configure options, so we can diagnose typos. - - case $ac_option in - - -bindir | --bindir | --bindi | --bind | --bin | --bi) - ac_prev=bindir ;; - -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) - bindir=$ac_optarg ;; - - -build | --build | --buil | --bui | --bu) - ac_prev=build_alias ;; - -build=* | --build=* | --buil=* | --bui=* | --bu=*) - build_alias=$ac_optarg ;; - - -cache-file | --cache-file | --cache-fil | --cache-fi \ - | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) - ac_prev=cache_file ;; - -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ - | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) - cache_file=$ac_optarg ;; - - --config-cache | -C) - cache_file=config.cache ;; - - -datadir | --datadir | --datadi | --datad | --data | --dat | --da) - ac_prev=datadir ;; - -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ - | --da=*) - datadir=$ac_optarg ;; - - -disable-* | --disable-*) - ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid feature name: $ac_feature" >&2 - { (exit 1); exit 1; }; } - ac_feature=`echo $ac_feature | sed 's/-/_/g'` - eval "enable_$ac_feature=no" ;; - - -enable-* | --enable-*) - ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid feature name: $ac_feature" >&2 - { (exit 1); exit 1; }; } - ac_feature=`echo $ac_feature | sed 's/-/_/g'` - case $ac_option in - *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; - *) ac_optarg=yes ;; - esac - eval "enable_$ac_feature='$ac_optarg'" ;; - - -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ - | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ - | --exec | --exe | --ex) - ac_prev=exec_prefix ;; - -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ - | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ - | --exec=* | --exe=* | --ex=*) - exec_prefix=$ac_optarg ;; - - -gas | --gas | --ga | --g) - # Obsolete; use --with-gas. - with_gas=yes ;; - - -help | --help | --hel | --he | -h) - ac_init_help=long ;; - -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) - ac_init_help=recursive ;; - -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) - ac_init_help=short ;; - - -host | --host | --hos | --ho) - ac_prev=host_alias ;; - -host=* | --host=* | --hos=* | --ho=*) - host_alias=$ac_optarg ;; - - -includedir | --includedir | --includedi | --included | --include \ - | --includ | --inclu | --incl | --inc) - ac_prev=includedir ;; - -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ - | --includ=* | --inclu=* | --incl=* | --inc=*) - includedir=$ac_optarg ;; - - -infodir | --infodir | --infodi | --infod | --info | --inf) - ac_prev=infodir ;; - -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) - infodir=$ac_optarg ;; - - -libdir | --libdir | --libdi | --libd) - ac_prev=libdir ;; - -libdir=* | --libdir=* | --libdi=* | --libd=*) - libdir=$ac_optarg ;; - - -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ - | --libexe | --libex | --libe) - ac_prev=libexecdir ;; - -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ - | --libexe=* | --libex=* | --libe=*) - libexecdir=$ac_optarg ;; - - -localstatedir | --localstatedir | --localstatedi | --localstated \ - | --localstate | --localstat | --localsta | --localst \ - | --locals | --local | --loca | --loc | --lo) - ac_prev=localstatedir ;; - -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ - | --localstate=* | --localstat=* | --localsta=* | --localst=* \ - | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) - localstatedir=$ac_optarg ;; - - -mandir | --mandir | --mandi | --mand | --man | --ma | --m) - ac_prev=mandir ;; - -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) - mandir=$ac_optarg ;; - - -nfp | --nfp | --nf) - # Obsolete; use --without-fp. - with_fp=no ;; - - -no-create | --no-create | --no-creat | --no-crea | --no-cre \ - | --no-cr | --no-c | -n) - no_create=yes ;; - - -no-recursion | --no-recursion | --no-recursio | --no-recursi \ - | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) - no_recursion=yes ;; - - -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ - | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ - | --oldin | --oldi | --old | --ol | --o) - ac_prev=oldincludedir ;; - -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ - | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ - | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) - oldincludedir=$ac_optarg ;; - - -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) - ac_prev=prefix ;; - -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) - prefix=$ac_optarg ;; - - -program-prefix | --program-prefix | --program-prefi | --program-pref \ - | --program-pre | --program-pr | --program-p) - ac_prev=program_prefix ;; - -program-prefix=* | --program-prefix=* | --program-prefi=* \ - | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) - program_prefix=$ac_optarg ;; - - -program-suffix | --program-suffix | --program-suffi | --program-suff \ - | --program-suf | --program-su | --program-s) - ac_prev=program_suffix ;; - -program-suffix=* | --program-suffix=* | --program-suffi=* \ - | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) - program_suffix=$ac_optarg ;; - - -program-transform-name | --program-transform-name \ - | --program-transform-nam | --program-transform-na \ - | --program-transform-n | --program-transform- \ - | --program-transform | --program-transfor \ - | --program-transfo | --program-transf \ - | --program-trans | --program-tran \ - | --progr-tra | --program-tr | --program-t) - ac_prev=program_transform_name ;; - -program-transform-name=* | --program-transform-name=* \ - | --program-transform-nam=* | --program-transform-na=* \ - | --program-transform-n=* | --program-transform-=* \ - | --program-transform=* | --program-transfor=* \ - | --program-transfo=* | --program-transf=* \ - | --program-trans=* | --program-tran=* \ - | --progr-tra=* | --program-tr=* | --program-t=*) - program_transform_name=$ac_optarg ;; - - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - silent=yes ;; - - -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) - ac_prev=sbindir ;; - -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ - | --sbi=* | --sb=*) - sbindir=$ac_optarg ;; - - -sharedstatedir | --sharedstatedir | --sharedstatedi \ - | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ - | --sharedst | --shareds | --shared | --share | --shar \ - | --sha | --sh) - ac_prev=sharedstatedir ;; - -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ - | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ - | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ - | --sha=* | --sh=*) - sharedstatedir=$ac_optarg ;; - - -site | --site | --sit) - ac_prev=site ;; - -site=* | --site=* | --sit=*) - site=$ac_optarg ;; - - -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) - ac_prev=srcdir ;; - -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) - srcdir=$ac_optarg ;; - - -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ - | --syscon | --sysco | --sysc | --sys | --sy) - ac_prev=sysconfdir ;; - -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ - | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) - sysconfdir=$ac_optarg ;; - - -target | --target | --targe | --targ | --tar | --ta | --t) - ac_prev=target_alias ;; - -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) - target_alias=$ac_optarg ;; - - -v | -verbose | --verbose | --verbos | --verbo | --verb) - verbose=yes ;; - - -version | --version | --versio | --versi | --vers | -V) - ac_init_version=: ;; - - -with-* | --with-*) - ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid package name: $ac_package" >&2 - { (exit 1); exit 1; }; } - ac_package=`echo $ac_package| sed 's/-/_/g'` - case $ac_option in - *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; - *) ac_optarg=yes ;; - esac - eval "with_$ac_package='$ac_optarg'" ;; - - -without-* | --without-*) - ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid package name: $ac_package" >&2 - { (exit 1); exit 1; }; } - ac_package=`echo $ac_package | sed 's/-/_/g'` - eval "with_$ac_package=no" ;; - - --x) - # Obsolete; use --with-x. - with_x=yes ;; - - -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ - | --x-incl | --x-inc | --x-in | --x-i) - ac_prev=x_includes ;; - -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ - | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) - x_includes=$ac_optarg ;; - - -x-libraries | --x-libraries | --x-librarie | --x-librari \ - | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) - ac_prev=x_libraries ;; - -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ - | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) - x_libraries=$ac_optarg ;; - - -*) { echo "$as_me: error: unrecognized option: $ac_option -Try \`$0 --help' for more information." >&2 - { (exit 1); exit 1; }; } - ;; - - *=*) - ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` - # Reject names that are not valid shell variable names. - expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 - { (exit 1); exit 1; }; } - ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` - eval "$ac_envvar='$ac_optarg'" - export $ac_envvar ;; - - *) - # FIXME: should be removed in autoconf 3.0. - echo "$as_me: WARNING: you should use --build, --host, --target" >&2 - expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && - echo "$as_me: WARNING: invalid host type: $ac_option" >&2 - : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} - ;; - - esac -done - -if test -n "$ac_prev"; then - ac_option=--`echo $ac_prev | sed 's/_/-/g'` - { echo "$as_me: error: missing argument to $ac_option" >&2 - { (exit 1); exit 1; }; } -fi - -# Be sure to have absolute paths. -for ac_var in exec_prefix prefix -do - eval ac_val=$`echo $ac_var` - case $ac_val in - [\\/$]* | ?:[\\/]* | NONE | '' ) ;; - *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 - { (exit 1); exit 1; }; };; - esac -done - -# Be sure to have absolute paths. -for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ - localstatedir libdir includedir oldincludedir infodir mandir -do - eval ac_val=$`echo $ac_var` - case $ac_val in - [\\/$]* | ?:[\\/]* ) ;; - *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 - { (exit 1); exit 1; }; };; - esac -done - -# There might be people who depend on the old broken behavior: `$host' -# used to hold the argument of --host etc. -# FIXME: To remove some day. -build=$build_alias -host=$host_alias -target=$target_alias - -# FIXME: To remove some day. -if test "x$host_alias" != x; then - if test "x$build_alias" = x; then - cross_compiling=maybe - echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. - If a cross compiler is detected then cross compile mode will be used." >&2 - elif test "x$build_alias" != "x$host_alias"; then - cross_compiling=yes - fi -fi - -ac_tool_prefix= -test -n "$host_alias" && ac_tool_prefix=$host_alias- - -test "$silent" = yes && exec 6>/dev/null - - -# Find the source files, if location was not specified. -if test -z "$srcdir"; then - ac_srcdir_defaulted=yes - # Try the directory containing this script, then its parent. - ac_confdir=`(dirname "$0") 2>/dev/null || -$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$0" : 'X\(//\)[^/]' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$0" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - srcdir=$ac_confdir - if test ! -r $srcdir/$ac_unique_file; then - srcdir=.. - fi -else - ac_srcdir_defaulted=no -fi -if test ! -r $srcdir/$ac_unique_file; then - if test "$ac_srcdir_defaulted" = yes; then - { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 - { (exit 1); exit 1; }; } - else - { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 - { (exit 1); exit 1; }; } - fi -fi -(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || - { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 - { (exit 1); exit 1; }; } -srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` -ac_env_build_alias_set=${build_alias+set} -ac_env_build_alias_value=$build_alias -ac_cv_env_build_alias_set=${build_alias+set} -ac_cv_env_build_alias_value=$build_alias -ac_env_host_alias_set=${host_alias+set} -ac_env_host_alias_value=$host_alias -ac_cv_env_host_alias_set=${host_alias+set} -ac_cv_env_host_alias_value=$host_alias -ac_env_target_alias_set=${target_alias+set} -ac_env_target_alias_value=$target_alias -ac_cv_env_target_alias_set=${target_alias+set} -ac_cv_env_target_alias_value=$target_alias -ac_env_CC_set=${CC+set} -ac_env_CC_value=$CC -ac_cv_env_CC_set=${CC+set} -ac_cv_env_CC_value=$CC -ac_env_CFLAGS_set=${CFLAGS+set} -ac_env_CFLAGS_value=$CFLAGS -ac_cv_env_CFLAGS_set=${CFLAGS+set} -ac_cv_env_CFLAGS_value=$CFLAGS -ac_env_LDFLAGS_set=${LDFLAGS+set} -ac_env_LDFLAGS_value=$LDFLAGS -ac_cv_env_LDFLAGS_set=${LDFLAGS+set} -ac_cv_env_LDFLAGS_value=$LDFLAGS -ac_env_CPPFLAGS_set=${CPPFLAGS+set} -ac_env_CPPFLAGS_value=$CPPFLAGS -ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} -ac_cv_env_CPPFLAGS_value=$CPPFLAGS -ac_env_CPP_set=${CPP+set} -ac_env_CPP_value=$CPP -ac_cv_env_CPP_set=${CPP+set} -ac_cv_env_CPP_value=$CPP -ac_env_CXX_set=${CXX+set} -ac_env_CXX_value=$CXX -ac_cv_env_CXX_set=${CXX+set} -ac_cv_env_CXX_value=$CXX -ac_env_CXXFLAGS_set=${CXXFLAGS+set} -ac_env_CXXFLAGS_value=$CXXFLAGS -ac_cv_env_CXXFLAGS_set=${CXXFLAGS+set} -ac_cv_env_CXXFLAGS_value=$CXXFLAGS -ac_env_CXXCPP_set=${CXXCPP+set} -ac_env_CXXCPP_value=$CXXCPP -ac_cv_env_CXXCPP_set=${CXXCPP+set} -ac_cv_env_CXXCPP_value=$CXXCPP -ac_env_F77_set=${F77+set} -ac_env_F77_value=$F77 -ac_cv_env_F77_set=${F77+set} -ac_cv_env_F77_value=$F77 -ac_env_FFLAGS_set=${FFLAGS+set} -ac_env_FFLAGS_value=$FFLAGS -ac_cv_env_FFLAGS_set=${FFLAGS+set} -ac_cv_env_FFLAGS_value=$FFLAGS - -# -# Report the --help message. -# -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 expat 2.0.1 to adapt to many kinds of systems. - -Usage: $0 [OPTION]... [VAR=VALUE]... - -To assign environment variables (e.g., CC, CFLAGS...), specify them as -VAR=VALUE. See below for descriptions of some of the useful variables. - -Defaults for the options are specified in brackets. - -Configuration: - -h, --help display this help and exit - --help=short display options specific to this package - --help=recursive display the short help of all the included packages - -V, --version display version information and exit - -q, --quiet, --silent do not print \`checking...' messages - --cache-file=FILE cache test results in FILE [disabled] - -C, --config-cache alias for \`--cache-file=config.cache' - -n, --no-create do not create output files - --srcdir=DIR find the sources in DIR [configure dir or \`..'] - -_ACEOF - - cat <<_ACEOF -Installation directories: - --prefix=PREFIX install architecture-independent files in PREFIX - [$ac_default_prefix] - --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX - [PREFIX] - -By default, \`make install' will install all the files in -\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify -an installation prefix other than \`$ac_default_prefix' using \`--prefix', -for instance \`--prefix=\$HOME'. - -For better control, use the options below. - -Fine tuning of the installation directories: - --bindir=DIR user executables [EPREFIX/bin] - --sbindir=DIR system admin executables [EPREFIX/sbin] - --libexecdir=DIR program executables [EPREFIX/libexec] - --datadir=DIR read-only architecture-independent data [PREFIX/share] - --sysconfdir=DIR read-only single-machine data [PREFIX/etc] - --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] - --localstatedir=DIR modifiable single-machine data [PREFIX/var] - --libdir=DIR object code libraries [EPREFIX/lib] - --includedir=DIR C header files [PREFIX/include] - --oldincludedir=DIR C header files for non-gcc [/usr/include] - --infodir=DIR info documentation [PREFIX/info] - --mandir=DIR man documentation [PREFIX/man] -_ACEOF - - cat <<\_ACEOF - -System types: - --build=BUILD configure for building on BUILD [guessed] - --host=HOST cross-compile to build programs to run on HOST [BUILD] -_ACEOF -fi - -if test -n "$ac_init_help"; then - case $ac_init_help in - short | recursive ) echo "Configuration of expat 2.0.1:";; - esac - cat <<\_ACEOF - -Optional Features: - --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) - --enable-FEATURE[=ARG] include FEATURE [ARG=yes] - --enable-shared[=PKGS] - build shared libraries [default=yes] - --enable-static[=PKGS] - build static libraries [default=yes] - --enable-fast-install[=PKGS] - optimize for fast installation [default=yes] - --disable-libtool-lock avoid locking (might break parallel builds) - -Optional Packages: - --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] - --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) - --with-gnu-ld assume the C compiler uses GNU ld [default=no] - --with-pic try to use only PIC/non-PIC objects [default=use - both] - --with-tags[=TAGS] - include additional configurations [automatic] - -Some influential environment variables: - CC C compiler command - CFLAGS C compiler flags - LDFLAGS linker flags, e.g. -L if you have libraries in a - nonstandard directory - CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have - headers in a nonstandard directory - CPP C preprocessor - CXX C++ compiler command - CXXFLAGS C++ compiler flags - CXXCPP C++ preprocessor - F77 Fortran 77 compiler command - FFLAGS Fortran 77 compiler flags - -Use these variables to override the choices made by `configure' or to help -it to find libraries and programs with nonstandard names/locations. - -Report bugs to . -_ACEOF -fi - -if test "$ac_init_help" = "recursive"; then - # If there are subdirs, report their specific --help. - ac_popdir=`pwd` - for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue - test -d $ac_dir || continue - ac_builddir=. - -if test "$ac_dir" != .; then - ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` - # A "../" for each directory in $ac_dir_suffix. - ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` -else - ac_dir_suffix= ac_top_builddir= -fi - -case $srcdir in - .) # No --srcdir option. We are building in place. - ac_srcdir=. - if test -z "$ac_top_builddir"; then - ac_top_srcdir=. - else - ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` - fi ;; - [\\/]* | ?:[\\/]* ) # Absolute path. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir ;; - *) # Relative path. - ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_builddir$srcdir ;; -esac - -# Do not use `cd foo && pwd` to compute absolute paths, because -# the directories may not exist. -case `pwd` in -.) ac_abs_builddir="$ac_dir";; -*) - case "$ac_dir" in - .) ac_abs_builddir=`pwd`;; - [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; - *) ac_abs_builddir=`pwd`/"$ac_dir";; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_top_builddir=${ac_top_builddir}.;; -*) - case ${ac_top_builddir}. in - .) ac_abs_top_builddir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; - *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_srcdir=$ac_srcdir;; -*) - case $ac_srcdir in - .) ac_abs_srcdir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; - *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_top_srcdir=$ac_top_srcdir;; -*) - case $ac_top_srcdir in - .) ac_abs_top_srcdir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; - *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; - esac;; -esac - - cd $ac_dir - # Check for guested configure; otherwise get Cygnus style configure. - if test -f $ac_srcdir/configure.gnu; then - echo - $SHELL $ac_srcdir/configure.gnu --help=recursive - elif test -f $ac_srcdir/configure; then - echo - $SHELL $ac_srcdir/configure --help=recursive - elif test -f $ac_srcdir/configure.ac || - test -f $ac_srcdir/configure.in; then - echo - $ac_configure --help - else - echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 - fi - cd $ac_popdir - done -fi - -test -n "$ac_init_help" && exit 0 -if $ac_init_version; then - cat <<\_ACEOF -expat configure 2.0.1 -generated by GNU Autoconf 2.59 - -Copyright (C) 2003 Free Software Foundation, Inc. -This configure script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it. -_ACEOF - exit 0 -fi -exec 5>config.log -cat >&5 <<_ACEOF -This file contains any messages produced by compilers while -running configure, to aid debugging if configure makes a mistake. - -It was created by expat $as_me 2.0.1, which was -generated by GNU Autoconf 2.59. Invocation command line was - - $ $0 $@ - -_ACEOF -{ -cat <<_ASUNAME -## --------- ## -## Platform. ## -## --------- ## - -hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` - -/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` -hostinfo = `(hostinfo) 2>/dev/null || echo unknown` -/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` -/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` - -_ASUNAME - -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - echo "PATH: $as_dir" -done - -} >&5 - -cat >&5 <<_ACEOF - - -## ----------- ## -## Core tests. ## -## ----------- ## - -_ACEOF - - -# Keep a trace of the command line. -# Strip out --no-create and --no-recursion so they do not pile up. -# Strip out --silent because we don't want to record it for future runs. -# Also quote any args containing shell meta-characters. -# Make two passes to allow for proper duplicate-argument suppression. -ac_configure_args= -ac_configure_args0= -ac_configure_args1= -ac_sep= -ac_must_keep_next=false -for ac_pass in 1 2 -do - for ac_arg - do - case $ac_arg in - -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - continue ;; - *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) - ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; - esac - case $ac_pass in - 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; - 2) - ac_configure_args1="$ac_configure_args1 '$ac_arg'" - if test $ac_must_keep_next = true; then - ac_must_keep_next=false # Got value, back to normal. - else - case $ac_arg in - *=* | --config-cache | -C | -disable-* | --disable-* \ - | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ - | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ - | -with-* | --with-* | -without-* | --without-* | --x) - case "$ac_configure_args0 " in - "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; - esac - ;; - -* ) ac_must_keep_next=true ;; - esac - fi - ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" - # Get rid of the leading space. - ac_sep=" " - ;; - esac - done -done -$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } -$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } - -# When interrupted or exit'd, cleanup temporary files, and complete -# config.log. We remove comments because anyway the quotes in there -# would cause problems or look ugly. -# WARNING: Be sure not to use single quotes in there, as some shells, -# such as our DU 5.0 friend, will then `close' the trap. -trap 'exit_status=$? - # Save into config.log some information that might help in debugging. - { - echo - - cat <<\_ASBOX -## ---------------- ## -## Cache variables. ## -## ---------------- ## -_ASBOX - echo - # The following way of writing the cache mishandles newlines in values, -{ - (set) 2>&1 | - case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in - *ac_space=\ *) - sed -n \ - "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" - ;; - *) - sed -n \ - "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" - ;; - esac; -} - echo - - cat <<\_ASBOX -## ----------------- ## -## Output variables. ## -## ----------------- ## -_ASBOX - echo - for ac_var in $ac_subst_vars - do - eval ac_val=$`echo $ac_var` - echo "$ac_var='"'"'$ac_val'"'"'" - done | sort - echo - - if test -n "$ac_subst_files"; then - cat <<\_ASBOX -## ------------- ## -## Output files. ## -## ------------- ## -_ASBOX - echo - for ac_var in $ac_subst_files - do - eval ac_val=$`echo $ac_var` - echo "$ac_var='"'"'$ac_val'"'"'" - done | sort - echo - fi - - if test -s confdefs.h; then - cat <<\_ASBOX -## ----------- ## -## confdefs.h. ## -## ----------- ## -_ASBOX - echo - sed "/^$/d" confdefs.h | sort - echo - fi - test "$ac_signal" != 0 && - echo "$as_me: caught signal $ac_signal" - echo "$as_me: exit $exit_status" - } >&5 - rm -f core *.core && - rm -rf conftest* confdefs* conf$$* $ac_clean_files && - exit $exit_status - ' 0 -for ac_signal in 1 2 13 15; do - trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal -done -ac_signal=0 - -# confdefs.h avoids OS command line length limits that DEFS can exceed. -rm -rf conftest* confdefs.h -# AIX cpp loses on an empty file, so make sure it contains at least a newline. -echo >confdefs.h - -# Predefined preprocessor variables. - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_NAME "$PACKAGE_NAME" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_TARNAME "$PACKAGE_TARNAME" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_VERSION "$PACKAGE_VERSION" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_STRING "$PACKAGE_STRING" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" -_ACEOF - - -# Let the site file select an alternate cache file if it wants to. -# Prefer explicitly selected file to automatically selected ones. -if test -z "$CONFIG_SITE"; then - if test "x$prefix" != xNONE; then - CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" - else - CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" - fi -fi -for ac_site_file in $CONFIG_SITE; do - if test -r "$ac_site_file"; then - { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 -echo "$as_me: loading site script $ac_site_file" >&6;} - sed 's/^/| /' "$ac_site_file" >&5 - . "$ac_site_file" - fi -done - -if test -r "$cache_file"; then - # Some versions of bash will fail to source /dev/null (special - # files actually), so we avoid doing that. - if test -f "$cache_file"; then - { echo "$as_me:$LINENO: loading cache $cache_file" >&5 -echo "$as_me: loading cache $cache_file" >&6;} - case $cache_file in - [\\/]* | ?:[\\/]* ) . $cache_file;; - *) . ./$cache_file;; - esac - fi -else - { echo "$as_me:$LINENO: creating cache $cache_file" >&5 -echo "$as_me: creating cache $cache_file" >&6;} - >$cache_file -fi - -# Check that the precious variables saved in the cache have kept the same -# value. -ac_cache_corrupted=false -for ac_var in `(set) 2>&1 | - sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do - eval ac_old_set=\$ac_cv_env_${ac_var}_set - eval ac_new_set=\$ac_env_${ac_var}_set - eval ac_old_val="\$ac_cv_env_${ac_var}_value" - eval ac_new_val="\$ac_env_${ac_var}_value" - case $ac_old_set,$ac_new_set in - set,) - { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 -echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,set) - { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 -echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,);; - *) - if test "x$ac_old_val" != "x$ac_new_val"; then - { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 -echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} - { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 -echo "$as_me: former value: $ac_old_val" >&2;} - { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 -echo "$as_me: current value: $ac_new_val" >&2;} - ac_cache_corrupted=: - fi;; - esac - # Pass precious variables to config.status. - if test "$ac_new_set" = set; then - case $ac_new_val in - *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) - ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; - *) ac_arg=$ac_var=$ac_new_val ;; - esac - case " $ac_configure_args " in - *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. - *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; - esac - fi -done -if $ac_cache_corrupted; then - { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 -echo "$as_me: error: changes in the environment can compromise the build" >&2;} - { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 -echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} - { (exit 1); exit 1; }; } -fi - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -ac_aux_dir= -for ac_dir in conftools $srcdir/conftools; do - if test -f $ac_dir/install-sh; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install-sh -c" - break - elif test -f $ac_dir/install.sh; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install.sh -c" - break - elif test -f $ac_dir/shtool; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/shtool install -c" - break - fi -done -if test -z "$ac_aux_dir"; then - { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in conftools $srcdir/conftools" >&5 -echo "$as_me: error: cannot find install-sh or install.sh in conftools $srcdir/conftools" >&2;} - { (exit 1); exit 1; }; } -fi -ac_config_guess="$SHELL $ac_aux_dir/config.guess" -ac_config_sub="$SHELL $ac_aux_dir/config.sub" -ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. - - - - -LIBCURRENT=6 -LIBREVISION=2 -LIBAGE=5 - - ac_config_headers="$ac_config_headers expat_config.h" - - -# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- -## Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005 -## Free Software Foundation, Inc. -## Originally by Gordon Matzigkeit , 1996 -## -## This file is free software; the Free Software Foundation gives -## unlimited permission to copy and/or distribute it, with or without -## modifications, as long as this notice is preserved. - -# serial 48 AC_PROG_LIBTOOL - - -# AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED) -# ----------------------------------------------------------- -# If this macro is not defined by Autoconf, define it here. - - - -# AC_PROG_LIBTOOL -# --------------- -# AC_PROG_LIBTOOL - - -# _AC_PROG_LIBTOOL -# ---------------- -# _AC_PROG_LIBTOOL - - -# AC_LIBTOOL_SETUP -# ---------------- -# AC_LIBTOOL_SETUP - - -# _LT_AC_SYS_COMPILER -# ------------------- -# _LT_AC_SYS_COMPILER - - -# _LT_CC_BASENAME(CC) -# ------------------- -# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. - - - -# _LT_COMPILER_BOILERPLATE -# ------------------------ -# Check for compiler boilerplate output or warnings with -# the simple compiler test code. -# _LT_COMPILER_BOILERPLATE - - -# _LT_LINKER_BOILERPLATE -# ---------------------- -# Check for linker boilerplate output or warnings with -# the simple link test code. -# _LT_LINKER_BOILERPLATE - - -# _LT_AC_SYS_LIBPATH_AIX -# ---------------------- -# Links a minimal program and checks the executable -# for the system default hardcoded library path. In most cases, -# this is /usr/lib:/lib, but when the MPI compilers are used -# the location of the communication and MPI libs are included too. -# If we don't find anything, use the default library path according -# to the aix ld manual. -# _LT_AC_SYS_LIBPATH_AIX - - -# _LT_AC_SHELL_INIT(ARG) -# ---------------------- -# _LT_AC_SHELL_INIT - - -# _LT_AC_PROG_ECHO_BACKSLASH -# -------------------------- -# Add some code to the start of the generated configure script which -# will find an echo command which doesn't interpret backslashes. -# _LT_AC_PROG_ECHO_BACKSLASH - - -# _LT_AC_LOCK -# ----------- -# _LT_AC_LOCK - - -# AC_LIBTOOL_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, -# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) -# ---------------------------------------------------------------- -# Check whether the given compiler option works -# AC_LIBTOOL_COMPILER_OPTION - - -# AC_LIBTOOL_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, -# [ACTION-SUCCESS], [ACTION-FAILURE]) -# ------------------------------------------------------------ -# Check whether the given compiler option works -# AC_LIBTOOL_LINKER_OPTION - - -# AC_LIBTOOL_SYS_MAX_CMD_LEN -# -------------------------- -# AC_LIBTOOL_SYS_MAX_CMD_LEN - - -# _LT_AC_CHECK_DLFCN -# ------------------ -# _LT_AC_CHECK_DLFCN - - -# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, -# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) -# --------------------------------------------------------------------- -# _LT_AC_TRY_DLOPEN_SELF - - -# AC_LIBTOOL_DLOPEN_SELF -# ---------------------- -# AC_LIBTOOL_DLOPEN_SELF - - -# AC_LIBTOOL_PROG_CC_C_O([TAGNAME]) -# --------------------------------- -# Check to see if options -c and -o are simultaneously supported by compiler -# AC_LIBTOOL_PROG_CC_C_O - - -# AC_LIBTOOL_SYS_HARD_LINK_LOCKS([TAGNAME]) -# ----------------------------------------- -# Check to see if we can do hard links to lock some files if needed -# AC_LIBTOOL_SYS_HARD_LINK_LOCKS - - -# AC_LIBTOOL_OBJDIR -# ----------------- -# AC_LIBTOOL_OBJDIR - - -# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH([TAGNAME]) -# ---------------------------------------------- -# Check hardcoding attributes. -# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH - - -# AC_LIBTOOL_SYS_LIB_STRIP -# ------------------------ -# AC_LIBTOOL_SYS_LIB_STRIP - - -# AC_LIBTOOL_SYS_DYNAMIC_LINKER -# ----------------------------- -# PORTME Fill in your ld.so characteristics -# AC_LIBTOOL_SYS_DYNAMIC_LINKER - - -# _LT_AC_TAGCONFIG -# ---------------- -# _LT_AC_TAGCONFIG - - -# AC_LIBTOOL_DLOPEN -# ----------------- -# enable checks for dlopen support -# AC_LIBTOOL_DLOPEN - - -# AC_LIBTOOL_WIN32_DLL -# -------------------- -# declare package support for building win32 DLLs -# AC_LIBTOOL_WIN32_DLL - - -# AC_ENABLE_SHARED([DEFAULT]) -# --------------------------- -# implement the --enable-shared flag -# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. -# AC_ENABLE_SHARED - - -# AC_DISABLE_SHARED -# ----------------- -# set the default shared flag to --disable-shared -# AC_DISABLE_SHARED - - -# AC_ENABLE_STATIC([DEFAULT]) -# --------------------------- -# implement the --enable-static flag -# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. -# AC_ENABLE_STATIC - - -# AC_DISABLE_STATIC -# ----------------- -# set the default static flag to --disable-static -# AC_DISABLE_STATIC - - -# AC_ENABLE_FAST_INSTALL([DEFAULT]) -# --------------------------------- -# implement the --enable-fast-install flag -# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. -# AC_ENABLE_FAST_INSTALL - - -# AC_DISABLE_FAST_INSTALL -# ----------------------- -# set the default to --disable-fast-install -# AC_DISABLE_FAST_INSTALL - - -# AC_LIBTOOL_PICMODE([MODE]) -# -------------------------- -# implement the --with-pic flag -# MODE is either `yes' or `no'. If omitted, it defaults to `both'. -# AC_LIBTOOL_PICMODE - - -# AC_PROG_EGREP -# ------------- -# This is predefined starting with Autoconf 2.54, so this conditional -# definition can be removed once we require Autoconf 2.54 or later. - - - -# AC_PATH_TOOL_PREFIX -# ------------------- -# find a file program which can recognise shared library -# AC_PATH_TOOL_PREFIX - - -# AC_PATH_MAGIC -# ------------- -# find a file program which can recognise a shared library -# AC_PATH_MAGIC - - -# AC_PROG_LD -# ---------- -# find the pathname to the GNU or non-GNU linker -# AC_PROG_LD - - -# AC_PROG_LD_GNU -# -------------- -# AC_PROG_LD_GNU - - -# AC_PROG_LD_RELOAD_FLAG -# ---------------------- -# find reload flag for linker -# -- PORTME Some linkers may need a different reload flag. -# AC_PROG_LD_RELOAD_FLAG - - -# AC_DEPLIBS_CHECK_METHOD -# ----------------------- -# how to check for library dependencies -# -- PORTME fill in with the dynamic library characteristics -# AC_DEPLIBS_CHECK_METHOD - - -# AC_PROG_NM -# ---------- -# find the pathname to a BSD-compatible name lister -# AC_PROG_NM - - -# AC_CHECK_LIBM -# ------------- -# check for math library -# AC_CHECK_LIBM - - -# AC_LIBLTDL_CONVENIENCE([DIRECTORY]) -# ----------------------------------- -# sets LIBLTDL to the link flags for the libltdl convenience library and -# LTDLINCL to the include flags for the libltdl header and adds -# --enable-ltdl-convenience to the configure arguments. Note that -# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided, -# it is assumed to be `libltdl'. LIBLTDL will be prefixed with -# '${top_builddir}/' and LTDLINCL will be prefixed with '${top_srcdir}/' -# (note the single quotes!). If your package is not flat and you're not -# using automake, define top_builddir and top_srcdir appropriately in -# the Makefiles. -# AC_LIBLTDL_CONVENIENCE - - -# AC_LIBLTDL_INSTALLABLE([DIRECTORY]) -# ----------------------------------- -# sets LIBLTDL to the link flags for the libltdl installable library and -# LTDLINCL to the include flags for the libltdl header and adds -# --enable-ltdl-install to the configure arguments. Note that -# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided, -# and an installed libltdl is not found, it is assumed to be `libltdl'. -# LIBLTDL will be prefixed with '${top_builddir}/'# and LTDLINCL with -# '${top_srcdir}/' (note the single quotes!). If your package is not -# flat and you're not using automake, define top_builddir and top_srcdir -# appropriately in the Makefiles. -# In the future, this macro may have to be called after AC_PROG_LIBTOOL. -# AC_LIBLTDL_INSTALLABLE - - -# AC_LIBTOOL_CXX -# -------------- -# enable support for C++ libraries -# AC_LIBTOOL_CXX - - -# _LT_AC_LANG_CXX -# --------------- -# _LT_AC_LANG_CXX - -# _LT_AC_PROG_CXXCPP -# ------------------ -# _LT_AC_PROG_CXXCPP - -# AC_LIBTOOL_F77 -# -------------- -# enable support for Fortran 77 libraries -# AC_LIBTOOL_F77 - - -# _LT_AC_LANG_F77 -# --------------- -# _LT_AC_LANG_F77 - - -# AC_LIBTOOL_GCJ -# -------------- -# enable support for GCJ libraries -# AC_LIBTOOL_GCJ - - -# _LT_AC_LANG_GCJ -# --------------- -# _LT_AC_LANG_GCJ - - -# AC_LIBTOOL_RC -# ------------- -# enable support for Windows resource files -# AC_LIBTOOL_RC - - -# AC_LIBTOOL_LANG_C_CONFIG -# ------------------------ -# Ensure that the configuration vars for the C compiler are -# suitably defined. Those variables are subsequently used by -# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. - -# AC_LIBTOOL_LANG_C_CONFIG - - -# AC_LIBTOOL_LANG_CXX_CONFIG -# -------------------------- -# Ensure that the configuration vars for the C compiler are -# suitably defined. Those variables are subsequently used by -# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. - -# AC_LIBTOOL_LANG_CXX_CONFIG - -# AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME]) -# ------------------------------------ -# Figure out "hidden" library dependencies from verbose -# compiler output when linking a shared library. -# Parse the compiler output and extract the necessary -# objects, libraries and library flags. -# AC_LIBTOOL_POSTDEP_PREDEP - -# AC_LIBTOOL_LANG_F77_CONFIG -# -------------------------- -# Ensure that the configuration vars for the C compiler are -# suitably defined. Those variables are subsequently used by -# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. - -# AC_LIBTOOL_LANG_F77_CONFIG - - -# AC_LIBTOOL_LANG_GCJ_CONFIG -# -------------------------- -# Ensure that the configuration vars for the C compiler are -# suitably defined. Those variables are subsequently used by -# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. - -# AC_LIBTOOL_LANG_GCJ_CONFIG - - -# AC_LIBTOOL_LANG_RC_CONFIG -# ------------------------- -# Ensure that the configuration vars for the Windows resource compiler are -# suitably defined. Those variables are subsequently used by -# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. - -# AC_LIBTOOL_LANG_RC_CONFIG - - -# AC_LIBTOOL_CONFIG([TAGNAME]) -# ---------------------------- -# If TAGNAME is not passed, then create an initial libtool script -# with a default configuration from the untagged config vars. Otherwise -# add code to config.status for appending the configuration named by -# TAGNAME from the matching tagged config vars. -# AC_LIBTOOL_CONFIG - - -# AC_LIBTOOL_PROG_COMPILER_NO_RTTI([TAGNAME]) -# ------------------------------------------- -# AC_LIBTOOL_PROG_COMPILER_NO_RTTI - - -# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE -# --------------------------------- - # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE - - -# AC_LIBTOOL_PROG_COMPILER_PIC([TAGNAME]) -# --------------------------------------- - - - -# AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME]) -# ------------------------------------ -# See if the linker supports building shared libraries. -# AC_LIBTOOL_PROG_LD_SHLIBS - - -# _LT_AC_FILE_LTDLL_C -# ------------------- -# Be careful that the start marker always follows a newline. -# _LT_AC_FILE_LTDLL_C - - -# _LT_AC_TAGVAR(VARNAME, [TAGNAME]) -# --------------------------------- - - - -# old names - - - - - - - - -# This is just to silence aclocal about the macro not being used - - - - - - -############################################################ -# NOTE: This macro has been submitted for inclusion into # -# GNU Autoconf as AC_PROG_SED. When it is available in # -# a released version of Autoconf we should remove this # -# macro and use it instead. # -############################################################ -# LT_AC_PROG_SED -# -------------- -# Check for a fully-functional sed program, that truncates -# as few characters as possible. Prefer GNU sed if found. - - - - - - - -# Check whether --enable-shared or --disable-shared was given. -if test "${enable_shared+set}" = set; then - enableval="$enable_shared" - p=${PACKAGE-default} - case $enableval in - yes) enable_shared=yes ;; - no) enable_shared=no ;; - *) - enable_shared=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for pkg in $enableval; do - IFS="$lt_save_ifs" - if test "X$pkg" = "X$p"; then - enable_shared=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac -else - enable_shared=yes -fi; - -# Check whether --enable-static or --disable-static was given. -if test "${enable_static+set}" = set; then - enableval="$enable_static" - p=${PACKAGE-default} - case $enableval in - yes) enable_static=yes ;; - no) enable_static=no ;; - *) - enable_static=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for pkg in $enableval; do - IFS="$lt_save_ifs" - if test "X$pkg" = "X$p"; then - enable_static=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac -else - enable_static=yes -fi; - -# Check whether --enable-fast-install or --disable-fast-install was given. -if test "${enable_fast_install+set}" = set; then - enableval="$enable_fast_install" - p=${PACKAGE-default} - case $enableval in - yes) enable_fast_install=yes ;; - no) enable_fast_install=no ;; - *) - enable_fast_install=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for pkg in $enableval; do - IFS="$lt_save_ifs" - if test "X$pkg" = "X$p"; then - enable_fast_install=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac -else - enable_fast_install=yes -fi; - -# Make sure we can run config.sub. -$ac_config_sub sun4 >/dev/null 2>&1 || - { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5 -echo "$as_me: error: cannot run $ac_config_sub" >&2;} - { (exit 1); exit 1; }; } - -echo "$as_me:$LINENO: checking build system type" >&5 -echo $ECHO_N "checking build system type... $ECHO_C" >&6 -if test "${ac_cv_build+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_build_alias=$build_alias -test -z "$ac_cv_build_alias" && - ac_cv_build_alias=`$ac_config_guess` -test -z "$ac_cv_build_alias" && - { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 -echo "$as_me: error: cannot guess build type; you must specify one" >&2;} - { (exit 1); exit 1; }; } -ac_cv_build=`$ac_config_sub $ac_cv_build_alias` || - { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5 -echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;} - { (exit 1); exit 1; }; } - -fi -echo "$as_me:$LINENO: result: $ac_cv_build" >&5 -echo "${ECHO_T}$ac_cv_build" >&6 -build=$ac_cv_build -build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` -build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` -build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` - - -echo "$as_me:$LINENO: checking host system type" >&5 -echo $ECHO_N "checking host system type... $ECHO_C" >&6 -if test "${ac_cv_host+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_host_alias=$host_alias -test -z "$ac_cv_host_alias" && - ac_cv_host_alias=$ac_cv_build_alias -ac_cv_host=`$ac_config_sub $ac_cv_host_alias` || - { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5 -echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;} - { (exit 1); exit 1; }; } - -fi -echo "$as_me:$LINENO: result: $ac_cv_host" >&5 -echo "${ECHO_T}$ac_cv_host" >&6 -host=$ac_cv_host -host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` -host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` -host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` - - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. -set dummy ${ac_tool_prefix}gcc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}gcc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$ac_cv_prog_CC"; then - ac_ct_CC=$CC - # Extract the first word of "gcc", so it can be a program name with args. -set dummy gcc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="gcc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 -echo "${ECHO_T}$ac_ct_CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - CC=$ac_ct_CC -else - CC="$ac_cv_prog_CC" -fi - -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. -set dummy ${ac_tool_prefix}cc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}cc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$ac_cv_prog_CC"; then - ac_ct_CC=$CC - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="cc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 -echo "${ECHO_T}$ac_ct_CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - CC=$ac_ct_CC -else - CC="$ac_cv_prog_CC" -fi - -fi -if test -z "$CC"; then - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else - ac_prog_rejected=no -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then - ac_prog_rejected=yes - continue - fi - ac_cv_prog_CC="cc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -if test $ac_prog_rejected = yes; then - # We found a bogon in the path, so make sure we never use it. - set dummy $ac_cv_prog_CC - shift - if test $# != 0; then - # We chose a different compiler from the bogus one. - # However, it has the same basename, so the bogon will be chosen - # first if we set CC to just the basename; use the full file name. - shift - ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" - fi -fi -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - for ac_prog in cl - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="$ac_tool_prefix$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - test -n "$CC" && break - done -fi -if test -z "$CC"; then - ac_ct_CC=$CC - for ac_prog in cl -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 -echo "${ECHO_T}$ac_ct_CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - test -n "$ac_ct_CC" && break -done - - CC=$ac_ct_CC -fi - -fi - - -test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH -See \`config.log' for more details." >&5 -echo "$as_me: error: no acceptable C compiler found in \$PATH -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } - -# Provide some information about the compiler. -echo "$as_me:$LINENO:" \ - "checking for C compiler version" >&5 -ac_compiler=`set X $ac_compile; echo $2` -{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 - (eval $ac_compiler --version &5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 - (eval $ac_compiler -v &5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 - (eval $ac_compiler -V &5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } - -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files a.out a.exe b.out" -# Try to create an executable without -o first, disregard a.out. -# It will help us diagnose broken compilers, and finding out an intuition -# of exeext. -echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 -echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6 -ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` -if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 - (eval $ac_link_default) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - # Find the output, starting from the most likely. This scheme is -# not robust to junk in `.', hence go to wildcards (a.*) only as a last -# resort. - -# Be careful to initialize this variable, since it used to be cached. -# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. -ac_cv_exeext= -# b.out is created by i960 compilers. -for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out -do - test -f "$ac_file" || continue - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) - ;; - conftest.$ac_ext ) - # This is the source file. - ;; - [ab].out ) - # We found the default executable, but exeext='' is most - # certainly right. - break;; - *.* ) - ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - # FIXME: I believe we export ac_cv_exeext for Libtool, - # but it would be cool to find out if it's true. Does anybody - # maintain Libtool? --akim. - export ac_cv_exeext - break;; - * ) - break;; - esac -done -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -{ { echo "$as_me:$LINENO: error: C compiler cannot create executables -See \`config.log' for more details." >&5 -echo "$as_me: error: C compiler cannot create executables -See \`config.log' for more details." >&2;} - { (exit 77); exit 77; }; } -fi - -ac_exeext=$ac_cv_exeext -echo "$as_me:$LINENO: result: $ac_file" >&5 -echo "${ECHO_T}$ac_file" >&6 - -# Check the compiler produces executables we can run. If not, either -# the compiler is broken, or we cross compile. -echo "$as_me:$LINENO: checking whether the C compiler works" >&5 -echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 -# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 -# If not cross compiling, check that we can run a simple program. -if test "$cross_compiling" != yes; then - if { ac_try='./$ac_file' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - cross_compiling=no - else - if test "$cross_compiling" = maybe; then - cross_compiling=yes - else - { { echo "$as_me:$LINENO: error: cannot run C compiled programs. -If you meant to cross compile, use \`--host'. -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot run C compiled programs. -If you meant to cross compile, use \`--host'. -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } - fi - fi -fi -echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 - -rm -f a.out a.exe conftest$ac_cv_exeext b.out -ac_clean_files=$ac_clean_files_save -# Check the compiler produces executables we can run. If not, either -# the compiler is broken, or we cross compile. -echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 -echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 -echo "$as_me:$LINENO: result: $cross_compiling" >&5 -echo "${ECHO_T}$cross_compiling" >&6 - -echo "$as_me:$LINENO: checking for suffix of executables" >&5 -echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - # If both `conftest.exe' and `conftest' are `present' (well, observable) -# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will -# work properly (i.e., refer to `conftest.exe'), while it won't with -# `rm'. -for ac_file in conftest.exe conftest conftest.*; do - test -f "$ac_file" || continue - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; - *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - export ac_cv_exeext - break;; - * ) break;; - esac -done -else - { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -fi - -rm -f conftest$ac_cv_exeext -echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 -echo "${ECHO_T}$ac_cv_exeext" >&6 - -rm -f conftest.$ac_ext -EXEEXT=$ac_cv_exeext -ac_exeext=$EXEEXT -echo "$as_me:$LINENO: checking for suffix of object files" >&5 -echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 -if test "${ac_cv_objext+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.o conftest.obj -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; - *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` - break;; - esac -done -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot compute suffix of object files: cannot compile -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -fi - -rm -f conftest.$ac_cv_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 -echo "${ECHO_T}$ac_cv_objext" >&6 -OBJEXT=$ac_cv_objext -ac_objext=$OBJEXT -echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 -echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 -if test "${ac_cv_c_compiler_gnu+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ -#ifndef __GNUC__ - choke me -#endif - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_compiler_gnu=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_compiler_gnu=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -ac_cv_c_compiler_gnu=$ac_compiler_gnu - -fi -echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 -echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 -GCC=`test $ac_compiler_gnu = yes && echo yes` -ac_test_CFLAGS=${CFLAGS+set} -ac_save_CFLAGS=$CFLAGS -CFLAGS="-g" -echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 -echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 -if test "${ac_cv_prog_cc_g+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_prog_cc_g=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_prog_cc_g=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 -echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 -if test "$ac_test_CFLAGS" = set; then - CFLAGS=$ac_save_CFLAGS -elif test $ac_cv_prog_cc_g = yes; then - if test "$GCC" = yes; then - CFLAGS="-g -O2" - else - CFLAGS="-g" - fi -else - if test "$GCC" = yes; then - CFLAGS="-O2" - else - CFLAGS= - fi -fi -echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 -echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 -if test "${ac_cv_prog_cc_stdc+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_prog_cc_stdc=no -ac_save_CC=$CC -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -#include -#include -#include -/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ -struct buf { int x; }; -FILE * (*rcsopen) (struct buf *, struct stat *, int); -static char *e (p, i) - char **p; - int i; -{ - return p[i]; -} -static char *f (char * (*g) (char **, int), char **p, ...) -{ - char *s; - va_list v; - va_start (v,p); - s = g (p, va_arg (v,int)); - va_end (v); - return s; -} - -/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has - function prototypes and stuff, but not '\xHH' hex character constants. - These don't provoke an error unfortunately, instead are silently treated - as 'x'. The following induces an error, until -std1 is added to get - proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an - array size at least. It's necessary to write '\x00'==0 to get something - that's true only with -std1. */ -int osf4_cc_array ['\x00' == 0 ? 1 : -1]; - -int test (int i, double x); -struct s1 {int (*f) (int a);}; -struct s2 {int (*f) (double a);}; -int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); -int argc; -char **argv; -int -main () -{ -return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; - ; - return 0; -} -_ACEOF -# Don't try gcc -ansi; that turns off useful extensions and -# breaks some systems' header files. -# AIX -qlanglvl=ansi -# Ultrix and OSF/1 -std1 -# HP-UX 10.20 and later -Ae -# HP-UX older versions -Aa -D_HPUX_SOURCE -# SVR4 -Xc -D__EXTENSIONS__ -for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" -do - CC="$ac_save_CC $ac_arg" - rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_prog_cc_stdc=$ac_arg -break -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext -done -rm -f conftest.$ac_ext conftest.$ac_objext -CC=$ac_save_CC - -fi - -case "x$ac_cv_prog_cc_stdc" in - x|xno) - echo "$as_me:$LINENO: result: none needed" >&5 -echo "${ECHO_T}none needed" >&6 ;; - *) - echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 -echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 - CC="$CC $ac_cv_prog_cc_stdc" ;; -esac - -# Some people use a C++ compiler to compile C. Since we use `exit', -# in C++ we need to declare it. In case someone uses the same compiler -# for both compiling C and C++ we need to have the C++ compiler decide -# the declaration of exit, since it's the most demanding environment. -cat >conftest.$ac_ext <<_ACEOF -#ifndef __cplusplus - choke me -#endif -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - for ac_declaration in \ - '' \ - 'extern "C" void std::exit (int) throw (); using std::exit;' \ - 'extern "C" void std::exit (int); using std::exit;' \ - 'extern "C" void exit (int) throw ();' \ - 'extern "C" void exit (int);' \ - 'void exit (int);' -do - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_declaration -#include -int -main () -{ -exit (42); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -continue -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_declaration -int -main () -{ -exit (42); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - break -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -done -rm -f conftest* -if test -n "$ac_declaration"; then - echo '#ifdef __cplusplus' >>confdefs.h - echo $ac_declaration >>confdefs.h - echo '#endif' >>confdefs.h -fi - -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -echo "$as_me:$LINENO: checking for a sed that does not truncate output" >&5 -echo $ECHO_N "checking for a sed that does not truncate output... $ECHO_C" >&6 -if test "${lt_cv_path_SED+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - # Loop through the user's path and test for sed and gsed. -# Then use that list of sed's as ones to test for truncation. -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for lt_ac_prog in sed gsed; do - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then - lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" - fi - done - done -done -lt_ac_max=0 -lt_ac_count=0 -# Add /usr/xpg4/bin/sed as it is typically found on Solaris -# along with /bin/sed that truncates output. -for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do - test ! -f $lt_ac_sed && continue - cat /dev/null > conftest.in - lt_ac_count=0 - echo $ECHO_N "0123456789$ECHO_C" >conftest.in - # Check for GNU sed and select it if it is found. - if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then - lt_cv_path_SED=$lt_ac_sed - break - fi - while true; do - cat conftest.in conftest.in >conftest.tmp - mv conftest.tmp conftest.in - cp conftest.in conftest.nl - echo >>conftest.nl - $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break - cmp -s conftest.out conftest.nl || break - # 10000 chars as input seems more than enough - test $lt_ac_count -gt 10 && break - lt_ac_count=`expr $lt_ac_count + 1` - if test $lt_ac_count -gt $lt_ac_max; then - lt_ac_max=$lt_ac_count - lt_cv_path_SED=$lt_ac_sed - fi - done -done - -fi - -SED=$lt_cv_path_SED -echo "$as_me:$LINENO: result: $SED" >&5 -echo "${ECHO_T}$SED" >&6 - -echo "$as_me:$LINENO: checking for egrep" >&5 -echo $ECHO_N "checking for egrep... $ECHO_C" >&6 -if test "${ac_cv_prog_egrep+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if echo a | (grep -E '(a|b)') >/dev/null 2>&1 - then ac_cv_prog_egrep='grep -E' - else ac_cv_prog_egrep='egrep' - fi -fi -echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 -echo "${ECHO_T}$ac_cv_prog_egrep" >&6 - EGREP=$ac_cv_prog_egrep - - - -# Check whether --with-gnu-ld or --without-gnu-ld was given. -if test "${with_gnu_ld+set}" = set; then - withval="$with_gnu_ld" - test "$withval" = no || with_gnu_ld=yes -else - with_gnu_ld=no -fi; -ac_prog=ld -if test "$GCC" = yes; then - # Check if gcc -print-prog-name=ld gives a path. - echo "$as_me:$LINENO: checking for ld used by $CC" >&5 -echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6 - case $host in - *-*-mingw*) - # gcc leaves a trailing carriage return which upsets mingw - ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; - *) - ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; - esac - case $ac_prog in - # Accept absolute paths. - [\\/]* | ?:[\\/]*) - re_direlt='/[^/][^/]*/\.\./' - # Canonicalize the pathname of ld - ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` - while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do - ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` - done - test -z "$LD" && LD="$ac_prog" - ;; - "") - # If it fails, then pretend we aren't using GCC. - ac_prog=ld - ;; - *) - # If it is relative, then search for the first ld in PATH. - with_gnu_ld=unknown - ;; - esac -elif test "$with_gnu_ld" = yes; then - echo "$as_me:$LINENO: checking for GNU ld" >&5 -echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6 -else - echo "$as_me:$LINENO: checking for non-GNU ld" >&5 -echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6 -fi -if test "${lt_cv_path_LD+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -z "$LD"; then - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for ac_dir in $PATH; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - lt_cv_path_LD="$ac_dir/$ac_prog" - # Check to see if the program is GNU ld. I'd rather use --version, - # but apparently some variants of GNU ld only accept -v. - # Break only if it was the GNU/non-GNU ld that we prefer. - case `"$lt_cv_path_LD" -v 2>&1 &5 -echo "${ECHO_T}$LD" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi -test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5 -echo "$as_me: error: no acceptable ld found in \$PATH" >&2;} - { (exit 1); exit 1; }; } -echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5 -echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6 -if test "${lt_cv_prog_gnu_ld+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - # I'd rather use --version here, but apparently some GNU lds only accept -v. -case `$LD -v 2>&1 &5 -echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6 -with_gnu_ld=$lt_cv_prog_gnu_ld - - -echo "$as_me:$LINENO: checking for $LD option to reload object files" >&5 -echo $ECHO_N "checking for $LD option to reload object files... $ECHO_C" >&6 -if test "${lt_cv_ld_reload_flag+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_cv_ld_reload_flag='-r' -fi -echo "$as_me:$LINENO: result: $lt_cv_ld_reload_flag" >&5 -echo "${ECHO_T}$lt_cv_ld_reload_flag" >&6 -reload_flag=$lt_cv_ld_reload_flag -case $reload_flag in -"" | " "*) ;; -*) reload_flag=" $reload_flag" ;; -esac -reload_cmds='$LD$reload_flag -o $output$reload_objs' -case $host_os in - darwin*) - if test "$GCC" = yes; then - reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' - else - reload_cmds='$LD$reload_flag -o $output$reload_objs' - fi - ;; -esac - -echo "$as_me:$LINENO: checking for BSD-compatible nm" >&5 -echo $ECHO_N "checking for BSD-compatible nm... $ECHO_C" >&6 -if test "${lt_cv_path_NM+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$NM"; then - # Let the user override the test. - lt_cv_path_NM="$NM" -else - lt_nm_to_check="${ac_tool_prefix}nm" - if test -n "$ac_tool_prefix" && test "$build" = "$host"; then - lt_nm_to_check="$lt_nm_to_check nm" - fi - for lt_tmp_nm in $lt_nm_to_check; do - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - tmp_nm="$ac_dir/$lt_tmp_nm" - if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then - # Check to see if the nm accepts a BSD-compat flag. - # Adding the `sed 1q' prevents false positives on HP-UX, which says: - # nm: unknown option "B" ignored - # Tru64's nm complains that /dev/null is an invalid object file - case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in - */dev/null* | *'Invalid file or object type'*) - lt_cv_path_NM="$tmp_nm -B" - break - ;; - *) - case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in - */dev/null*) - lt_cv_path_NM="$tmp_nm -p" - break - ;; - *) - lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but - continue # so that we can try to find one that supports BSD flags - ;; - esac - ;; - esac - fi - done - IFS="$lt_save_ifs" - done - test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm -fi -fi -echo "$as_me:$LINENO: result: $lt_cv_path_NM" >&5 -echo "${ECHO_T}$lt_cv_path_NM" >&6 -NM="$lt_cv_path_NM" - -echo "$as_me:$LINENO: checking whether ln -s works" >&5 -echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6 -LN_S=$as_ln_s -if test "$LN_S" = "ln -s"; then - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 -else - echo "$as_me:$LINENO: result: no, using $LN_S" >&5 -echo "${ECHO_T}no, using $LN_S" >&6 -fi - -echo "$as_me:$LINENO: checking how to recognise dependent libraries" >&5 -echo $ECHO_N "checking how to recognise dependent libraries... $ECHO_C" >&6 -if test "${lt_cv_deplibs_check_method+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_cv_file_magic_cmd='$MAGIC_CMD' -lt_cv_file_magic_test_file= -lt_cv_deplibs_check_method='unknown' -# Need to set the preceding variable on all platforms that support -# interlibrary dependencies. -# 'none' -- dependencies not supported. -# `unknown' -- same as none, but documents that we really don't know. -# 'pass_all' -- all dependencies passed with no checks. -# 'test_compile' -- check by making test program. -# 'file_magic [[regex]]' -- check by looking for files in library path -# which responds to the $file_magic_cmd with a given extended regex. -# If you have `file' or equivalent on your system and you're not sure -# whether `pass_all' will *always* work, you probably want this one. - -case $host_os in -aix4* | aix5*) - lt_cv_deplibs_check_method=pass_all - ;; - -beos*) - lt_cv_deplibs_check_method=pass_all - ;; - -bsdi[45]*) - lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' - lt_cv_file_magic_cmd='/usr/bin/file -L' - lt_cv_file_magic_test_file=/shlib/libc.so - ;; - -cygwin*) - # func_win32_libid is a shell function defined in ltmain.sh - lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' - lt_cv_file_magic_cmd='func_win32_libid' - ;; - -mingw* | pw32*) - # Base MSYS/MinGW do not provide the 'file' command needed by - # func_win32_libid shell function, so use a weaker test based on 'objdump'. - lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' - lt_cv_file_magic_cmd='$OBJDUMP -f' - ;; - -darwin* | rhapsody*) - lt_cv_deplibs_check_method=pass_all - ;; - -freebsd* | kfreebsd*-gnu | dragonfly*) - if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then - case $host_cpu in - i*86 ) - # Not sure whether the presence of OpenBSD here was a mistake. - # Let's accept both of them until this is cleared up. - lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' - lt_cv_file_magic_cmd=/usr/bin/file - lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` - ;; - esac - else - lt_cv_deplibs_check_method=pass_all - fi - ;; - -gnu*) - lt_cv_deplibs_check_method=pass_all - ;; - -hpux10.20* | hpux11*) - lt_cv_file_magic_cmd=/usr/bin/file - case $host_cpu in - ia64*) - lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' - lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so - ;; - hppa*64*) - lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]' - lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl - ;; - *) - lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library' - lt_cv_file_magic_test_file=/usr/lib/libc.sl - ;; - esac - ;; - -interix3*) - # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here - lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' - ;; - -irix5* | irix6* | nonstopux*) - case $LD in - *-32|*"-32 ") libmagic=32-bit;; - *-n32|*"-n32 ") libmagic=N32;; - *-64|*"-64 ") libmagic=64-bit;; - *) libmagic=never-match;; - esac - lt_cv_deplibs_check_method=pass_all - ;; - -# This must be Linux ELF. -linux*) - lt_cv_deplibs_check_method=pass_all - ;; - -netbsd*) - if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then - lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' - else - lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' - fi - ;; - -newos6*) - lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' - lt_cv_file_magic_cmd=/usr/bin/file - lt_cv_file_magic_test_file=/usr/lib/libnls.so - ;; - -nto-qnx*) - lt_cv_deplibs_check_method=unknown - ;; - -openbsd*) - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' - else - lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' - fi - ;; - -osf3* | osf4* | osf5*) - lt_cv_deplibs_check_method=pass_all - ;; - -solaris*) - lt_cv_deplibs_check_method=pass_all - ;; - -sysv4 | sysv4.3*) - case $host_vendor in - motorola) - lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' - lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` - ;; - ncr) - lt_cv_deplibs_check_method=pass_all - ;; - sequent) - lt_cv_file_magic_cmd='/bin/file' - lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' - ;; - sni) - lt_cv_file_magic_cmd='/bin/file' - lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" - lt_cv_file_magic_test_file=/lib/libc.so - ;; - siemens) - lt_cv_deplibs_check_method=pass_all - ;; - pc) - lt_cv_deplibs_check_method=pass_all - ;; - esac - ;; - -sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - lt_cv_deplibs_check_method=pass_all - ;; -esac - -fi -echo "$as_me:$LINENO: result: $lt_cv_deplibs_check_method" >&5 -echo "${ECHO_T}$lt_cv_deplibs_check_method" >&6 -file_magic_cmd=$lt_cv_file_magic_cmd -deplibs_check_method=$lt_cv_deplibs_check_method -test -z "$deplibs_check_method" && deplibs_check_method=unknown - - - - -# If no C compiler was specified, use CC. -LTCC=${LTCC-"$CC"} - -# If no C compiler flags were specified, use CFLAGS. -LTCFLAGS=${LTCFLAGS-"$CFLAGS"} - -# Allow CC to be a program name with arguments. -compiler=$CC - - -# Check whether --enable-libtool-lock or --disable-libtool-lock was given. -if test "${enable_libtool_lock+set}" = set; then - enableval="$enable_libtool_lock" - -fi; -test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes - -# Some flags need to be propagated to the compiler or linker for good -# libtool support. -case $host in -ia64-*-hpux*) - # Find out which ABI we are using. - echo 'int i;' > conftest.$ac_ext - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - case `/usr/bin/file conftest.$ac_objext` in - *ELF-32*) - HPUX_IA64_MODE="32" - ;; - *ELF-64*) - HPUX_IA64_MODE="64" - ;; - esac - fi - rm -rf conftest* - ;; -*-*-irix6*) - # Find out which ABI we are using. - echo '#line 3564 "configure"' > conftest.$ac_ext - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - if test "$lt_cv_prog_gnu_ld" = yes; then - case `/usr/bin/file conftest.$ac_objext` in - *32-bit*) - LD="${LD-ld} -melf32bsmip" - ;; - *N32*) - LD="${LD-ld} -melf32bmipn32" - ;; - *64-bit*) - LD="${LD-ld} -melf64bmip" - ;; - esac - else - case `/usr/bin/file conftest.$ac_objext` in - *32-bit*) - LD="${LD-ld} -32" - ;; - *N32*) - LD="${LD-ld} -n32" - ;; - *64-bit*) - LD="${LD-ld} -64" - ;; - esac - fi - fi - rm -rf conftest* - ;; - -x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) - # Find out which ABI we are using. - echo 'int i;' > conftest.$ac_ext - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - case `/usr/bin/file conftest.o` in - *32-bit*) - case $host in - x86_64-*linux*) - LD="${LD-ld} -m elf_i386" - ;; - ppc64-*linux*|powerpc64-*linux*) - LD="${LD-ld} -m elf32ppclinux" - ;; - s390x-*linux*) - LD="${LD-ld} -m elf_s390" - ;; - sparc64-*linux*) - LD="${LD-ld} -m elf32_sparc" - ;; - esac - ;; - *64-bit*) - case $host in - x86_64-*linux*) - LD="${LD-ld} -m elf_x86_64" - ;; - ppc*-*linux*|powerpc*-*linux*) - LD="${LD-ld} -m elf64ppc" - ;; - s390*-*linux*) - LD="${LD-ld} -m elf64_s390" - ;; - sparc*-*linux*) - LD="${LD-ld} -m elf64_sparc" - ;; - esac - ;; - esac - fi - rm -rf conftest* - ;; - -*-*-sco3.2v5*) - # On SCO OpenServer 5, we need -belf to get full-featured binaries. - SAVE_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -belf" - echo "$as_me:$LINENO: checking whether the C compiler needs -belf" >&5 -echo $ECHO_N "checking whether the C compiler needs -belf... $ECHO_C" >&6 -if test "${lt_cv_cc_needs_belf+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - lt_cv_cc_needs_belf=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -lt_cv_cc_needs_belf=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -fi -echo "$as_me:$LINENO: result: $lt_cv_cc_needs_belf" >&5 -echo "${ECHO_T}$lt_cv_cc_needs_belf" >&6 - if test x"$lt_cv_cc_needs_belf" != x"yes"; then - # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf - CFLAGS="$SAVE_CFLAGS" - fi - ;; -sparc*-*solaris*) - # Find out which ABI we are using. - echo 'int i;' > conftest.$ac_ext - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - case `/usr/bin/file conftest.o` in - *64-bit*) - case $lt_cv_prog_gnu_ld in - yes*) LD="${LD-ld} -m elf64_sparc" ;; - *) LD="${LD-ld} -64" ;; - esac - ;; - esac - fi - rm -rf conftest* - ;; - -*-*-cygwin* | *-*-mingw* | *-*-pw32*) - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. -set dummy ${ac_tool_prefix}dlltool; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_DLLTOOL+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$DLLTOOL"; then - ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -DLLTOOL=$ac_cv_prog_DLLTOOL -if test -n "$DLLTOOL"; then - echo "$as_me:$LINENO: result: $DLLTOOL" >&5 -echo "${ECHO_T}$DLLTOOL" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$ac_cv_prog_DLLTOOL"; then - ac_ct_DLLTOOL=$DLLTOOL - # Extract the first word of "dlltool", so it can be a program name with args. -set dummy dlltool; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_DLLTOOL+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_DLLTOOL"; then - ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_DLLTOOL="dlltool" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - - test -z "$ac_cv_prog_ac_ct_DLLTOOL" && ac_cv_prog_ac_ct_DLLTOOL="false" -fi -fi -ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL -if test -n "$ac_ct_DLLTOOL"; then - echo "$as_me:$LINENO: result: $ac_ct_DLLTOOL" >&5 -echo "${ECHO_T}$ac_ct_DLLTOOL" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - DLLTOOL=$ac_ct_DLLTOOL -else - DLLTOOL="$ac_cv_prog_DLLTOOL" -fi - - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args. -set dummy ${ac_tool_prefix}as; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_AS+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$AS"; then - ac_cv_prog_AS="$AS" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_AS="${ac_tool_prefix}as" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -AS=$ac_cv_prog_AS -if test -n "$AS"; then - echo "$as_me:$LINENO: result: $AS" >&5 -echo "${ECHO_T}$AS" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$ac_cv_prog_AS"; then - ac_ct_AS=$AS - # Extract the first word of "as", so it can be a program name with args. -set dummy as; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_AS+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_AS"; then - ac_cv_prog_ac_ct_AS="$ac_ct_AS" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_AS="as" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - - test -z "$ac_cv_prog_ac_ct_AS" && ac_cv_prog_ac_ct_AS="false" -fi -fi -ac_ct_AS=$ac_cv_prog_ac_ct_AS -if test -n "$ac_ct_AS"; then - echo "$as_me:$LINENO: result: $ac_ct_AS" >&5 -echo "${ECHO_T}$ac_ct_AS" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - AS=$ac_ct_AS -else - AS="$ac_cv_prog_AS" -fi - - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. -set dummy ${ac_tool_prefix}objdump; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_OBJDUMP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$OBJDUMP"; then - ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -OBJDUMP=$ac_cv_prog_OBJDUMP -if test -n "$OBJDUMP"; then - echo "$as_me:$LINENO: result: $OBJDUMP" >&5 -echo "${ECHO_T}$OBJDUMP" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$ac_cv_prog_OBJDUMP"; then - ac_ct_OBJDUMP=$OBJDUMP - # Extract the first word of "objdump", so it can be a program name with args. -set dummy objdump; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_OBJDUMP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_OBJDUMP"; then - ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_OBJDUMP="objdump" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - - test -z "$ac_cv_prog_ac_ct_OBJDUMP" && ac_cv_prog_ac_ct_OBJDUMP="false" -fi -fi -ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP -if test -n "$ac_ct_OBJDUMP"; then - echo "$as_me:$LINENO: result: $ac_ct_OBJDUMP" >&5 -echo "${ECHO_T}$ac_ct_OBJDUMP" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - OBJDUMP=$ac_ct_OBJDUMP -else - OBJDUMP="$ac_cv_prog_OBJDUMP" -fi - - ;; - -esac - -need_locks="$enable_libtool_lock" - - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 -echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 -# On Suns, sometimes $CPP names a directory. -if test -n "$CPP" && test -d "$CPP"; then - CPP= -fi -if test -z "$CPP"; then - if test "${ac_cv_prog_CPP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - # Double quotes because CPP needs to be expanded - for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" - do - ac_preproc_ok=false -for ac_c_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.$ac_ext - - # OK, works on sane cases. Now check whether non-existent headers - # can be detected and how. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - # Broken: success on invalid input. -continue -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext -if $ac_preproc_ok; then - break -fi - - done - ac_cv_prog_CPP=$CPP - -fi - CPP=$ac_cv_prog_CPP -else - ac_cv_prog_CPP=$CPP -fi -echo "$as_me:$LINENO: result: $CPP" >&5 -echo "${ECHO_T}$CPP" >&6 -ac_preproc_ok=false -for ac_c_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.$ac_ext - - # OK, works on sane cases. Now check whether non-existent headers - # can be detected and how. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - # Broken: success on invalid input. -continue -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext -if $ac_preproc_ok; then - : -else - { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details." >&5 -echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -fi - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - -echo "$as_me:$LINENO: checking for ANSI C header files" >&5 -echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 -if test "${ac_cv_header_stdc+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -#include -#include -#include - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_header_stdc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_header_stdc=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext - -if test $ac_cv_header_stdc = yes; then - # SunOS 4.x string.h does not declare mem*, contrary to ANSI. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "memchr" >/dev/null 2>&1; then - : -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "free" >/dev/null 2>&1; then - : -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. - if test "$cross_compiling" = yes; then - : -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -#if ((' ' & 0x0FF) == 0x020) -# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') -# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) -#else -# define ISLOWER(c) \ - (('a' <= (c) && (c) <= 'i') \ - || ('j' <= (c) && (c) <= 'r') \ - || ('s' <= (c) && (c) <= 'z')) -# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) -#endif - -#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) -int -main () -{ - int i; - for (i = 0; i < 256; i++) - if (XOR (islower (i), ISLOWER (i)) - || toupper (i) != TOUPPER (i)) - exit(2); - exit (0); -} -_ACEOF -rm -f conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { ac_try='./conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - : -else - echo "$as_me: program exited with status $ac_status" >&5 -echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -( exit $ac_status ) -ac_cv_header_stdc=no -fi -rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext -fi -fi -fi -echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 -echo "${ECHO_T}$ac_cv_header_stdc" >&6 -if test $ac_cv_header_stdc = yes; then - -cat >>confdefs.h <<\_ACEOF -#define STDC_HEADERS 1 -_ACEOF - -fi - -# On IRIX 5.3, sys/types and inttypes.h are conflicting. - - - - - - - - - -for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ - inttypes.h stdint.h unistd.h -do -as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` -echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default - -#include <$ac_header> -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - eval "$as_ac_Header=yes" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -eval "$as_ac_Header=no" -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 -if test `eval echo '${'$as_ac_Header'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - -fi - -done - - - -for ac_header in dlfcn.h -do -as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 -else - # Is the header compilable? -echo "$as_me:$LINENO: checking $ac_header usability" >&5 -echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include <$ac_header> -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_header_compiler=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_header_compiler=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6 - -# Is the header present? -echo "$as_me:$LINENO: checking $ac_header presence" >&5 -echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <$ac_header> -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - ac_header_preproc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no -fi -rm -f conftest.err conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6 - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in - yes:no: ) - { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} - ac_header_preproc=yes - ;; - no:yes:* ) - { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 -echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 -echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 -echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 -echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} - ( - cat <<\_ASBOX -## -------------------------------------- ## -## Report this to expat-bugs@libexpat.org ## -## -------------------------------------- ## -_ASBOX - ) | - sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac -echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - eval "$as_ac_Header=\$ac_header_preproc" -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 - -fi -if test `eval echo '${'$as_ac_Header'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - -fi - -done - -ac_ext=cc -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu -if test -n "$ac_tool_prefix"; then - for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CXX+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CXX"; then - ac_cv_prog_CXX="$CXX" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -CXX=$ac_cv_prog_CXX -if test -n "$CXX"; then - echo "$as_me:$LINENO: result: $CXX" >&5 -echo "${ECHO_T}$CXX" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - test -n "$CXX" && break - done -fi -if test -z "$CXX"; then - ac_ct_CXX=$CXX - for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_CXX"; then - ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CXX="$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -ac_ct_CXX=$ac_cv_prog_ac_ct_CXX -if test -n "$ac_ct_CXX"; then - echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 -echo "${ECHO_T}$ac_ct_CXX" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - test -n "$ac_ct_CXX" && break -done -test -n "$ac_ct_CXX" || ac_ct_CXX="g++" - - CXX=$ac_ct_CXX -fi - - -# Provide some information about the compiler. -echo "$as_me:$LINENO:" \ - "checking for C++ compiler version" >&5 -ac_compiler=`set X $ac_compile; echo $2` -{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 - (eval $ac_compiler --version &5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 - (eval $ac_compiler -v &5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 - (eval $ac_compiler -V &5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } - -echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 -echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6 -if test "${ac_cv_cxx_compiler_gnu+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ -#ifndef __GNUC__ - choke me -#endif - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_compiler_gnu=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_compiler_gnu=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -ac_cv_cxx_compiler_gnu=$ac_compiler_gnu - -fi -echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 -echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6 -GXX=`test $ac_compiler_gnu = yes && echo yes` -ac_test_CXXFLAGS=${CXXFLAGS+set} -ac_save_CXXFLAGS=$CXXFLAGS -CXXFLAGS="-g" -echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 -echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6 -if test "${ac_cv_prog_cxx_g+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_prog_cxx_g=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_prog_cxx_g=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 -echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6 -if test "$ac_test_CXXFLAGS" = set; then - CXXFLAGS=$ac_save_CXXFLAGS -elif test $ac_cv_prog_cxx_g = yes; then - if test "$GXX" = yes; then - CXXFLAGS="-g -O2" - else - CXXFLAGS="-g" - fi -else - if test "$GXX" = yes; then - CXXFLAGS="-O2" - else - CXXFLAGS= - fi -fi -for ac_declaration in \ - '' \ - 'extern "C" void std::exit (int) throw (); using std::exit;' \ - 'extern "C" void std::exit (int); using std::exit;' \ - 'extern "C" void exit (int) throw ();' \ - 'extern "C" void exit (int);' \ - 'void exit (int);' -do - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_declaration -#include -int -main () -{ -exit (42); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -continue -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_declaration -int -main () -{ -exit (42); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - break -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -done -rm -f conftest* -if test -n "$ac_declaration"; then - echo '#ifdef __cplusplus' >>confdefs.h - echo $ac_declaration >>confdefs.h - echo '#endif' >>confdefs.h -fi - -ac_ext=cc -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - - - -if test -n "$CXX" && ( test "X$CXX" != "Xno" && - ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || - (test "X$CXX" != "Xg++"))) ; then - ac_ext=cc -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu -echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5 -echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6 -if test -z "$CXXCPP"; then - if test "${ac_cv_prog_CXXCPP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - # Double quotes because CXXCPP needs to be expanded - for CXXCPP in "$CXX -E" "/lib/cpp" - do - ac_preproc_ok=false -for ac_cxx_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_cxx_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.$ac_ext - - # OK, works on sane cases. Now check whether non-existent headers - # can be detected and how. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_cxx_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - # Broken: success on invalid input. -continue -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext -if $ac_preproc_ok; then - break -fi - - done - ac_cv_prog_CXXCPP=$CXXCPP - -fi - CXXCPP=$ac_cv_prog_CXXCPP -else - ac_cv_prog_CXXCPP=$CXXCPP -fi -echo "$as_me:$LINENO: result: $CXXCPP" >&5 -echo "${ECHO_T}$CXXCPP" >&6 -ac_preproc_ok=false -for ac_cxx_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_cxx_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.$ac_ext - - # OK, works on sane cases. Now check whether non-existent headers - # can be detected and how. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_cxx_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - # Broken: success on invalid input. -continue -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext -if $ac_preproc_ok; then - : -else - { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check -See \`config.log' for more details." >&5 -echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -fi - -ac_ext=cc -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - -fi - - -ac_ext=f -ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5' -ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_f77_compiler_gnu -if test -n "$ac_tool_prefix"; then - for ac_prog in g77 f77 xlf frt pgf77 fort77 fl32 af77 f90 xlf90 pgf90 epcf90 f95 fort xlf95 ifc efc pgf95 lf95 gfortran - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_F77+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$F77"; then - ac_cv_prog_F77="$F77" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_F77="$ac_tool_prefix$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -F77=$ac_cv_prog_F77 -if test -n "$F77"; then - echo "$as_me:$LINENO: result: $F77" >&5 -echo "${ECHO_T}$F77" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - test -n "$F77" && break - done -fi -if test -z "$F77"; then - ac_ct_F77=$F77 - for ac_prog in g77 f77 xlf frt pgf77 fort77 fl32 af77 f90 xlf90 pgf90 epcf90 f95 fort xlf95 ifc efc pgf95 lf95 gfortran -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_F77+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_F77"; then - ac_cv_prog_ac_ct_F77="$ac_ct_F77" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_F77="$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -ac_ct_F77=$ac_cv_prog_ac_ct_F77 -if test -n "$ac_ct_F77"; then - echo "$as_me:$LINENO: result: $ac_ct_F77" >&5 -echo "${ECHO_T}$ac_ct_F77" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - test -n "$ac_ct_F77" && break -done - - F77=$ac_ct_F77 -fi - - -# Provide some information about the compiler. -echo "$as_me:5296:" \ - "checking for Fortran 77 compiler version" >&5 -ac_compiler=`set X $ac_compile; echo $2` -{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 - (eval $ac_compiler --version &5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 - (eval $ac_compiler -v &5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 - (eval $ac_compiler -V &5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -rm -f a.out - -# If we don't use `.F' as extension, the preprocessor is not run on the -# input file. (Note that this only needs to work for GNU compilers.) -ac_save_ext=$ac_ext -ac_ext=F -echo "$as_me:$LINENO: checking whether we are using the GNU Fortran 77 compiler" >&5 -echo $ECHO_N "checking whether we are using the GNU Fortran 77 compiler... $ECHO_C" >&6 -if test "${ac_cv_f77_compiler_gnu+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF - program main -#ifndef __GNUC__ - choke me -#endif - - end -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_f77_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_compiler_gnu=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_compiler_gnu=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -ac_cv_f77_compiler_gnu=$ac_compiler_gnu - -fi -echo "$as_me:$LINENO: result: $ac_cv_f77_compiler_gnu" >&5 -echo "${ECHO_T}$ac_cv_f77_compiler_gnu" >&6 -ac_ext=$ac_save_ext -ac_test_FFLAGS=${FFLAGS+set} -ac_save_FFLAGS=$FFLAGS -FFLAGS= -echo "$as_me:$LINENO: checking whether $F77 accepts -g" >&5 -echo $ECHO_N "checking whether $F77 accepts -g... $ECHO_C" >&6 -if test "${ac_cv_prog_f77_g+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - FFLAGS=-g -cat >conftest.$ac_ext <<_ACEOF - program main - - end -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_f77_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_prog_f77_g=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_prog_f77_g=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext - -fi -echo "$as_me:$LINENO: result: $ac_cv_prog_f77_g" >&5 -echo "${ECHO_T}$ac_cv_prog_f77_g" >&6 -if test "$ac_test_FFLAGS" = set; then - FFLAGS=$ac_save_FFLAGS -elif test $ac_cv_prog_f77_g = yes; then - if test "x$ac_cv_f77_compiler_gnu" = xyes; then - FFLAGS="-g -O2" - else - FFLAGS="-g" - fi -else - if test "x$ac_cv_f77_compiler_gnu" = xyes; then - FFLAGS="-O2" - else - FFLAGS= - fi -fi - -G77=`test $ac_compiler_gnu = yes && echo yes` -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - - -# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! - -# find the maximum length of command line arguments -echo "$as_me:$LINENO: checking the maximum length of command line arguments" >&5 -echo $ECHO_N "checking the maximum length of command line arguments... $ECHO_C" >&6 -if test "${lt_cv_sys_max_cmd_len+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - i=0 - teststring="ABCD" - - case $build_os in - msdosdjgpp*) - # On DJGPP, this test can blow up pretty badly due to problems in libc - # (any single argument exceeding 2000 bytes causes a buffer overrun - # during glob expansion). Even if it were fixed, the result of this - # check would be larger than it should be. - lt_cv_sys_max_cmd_len=12288; # 12K is about right - ;; - - gnu*) - # Under GNU Hurd, this test is not required because there is - # no limit to the length of command line arguments. - # Libtool will interpret -1 as no limit whatsoever - lt_cv_sys_max_cmd_len=-1; - ;; - - cygwin* | mingw*) - # On Win9x/ME, this test blows up -- it succeeds, but takes - # about 5 minutes as the teststring grows exponentially. - # Worse, since 9x/ME are not pre-emptively multitasking, - # you end up with a "frozen" computer, even though with patience - # the test eventually succeeds (with a max line length of 256k). - # Instead, let's just punt: use the minimum linelength reported by - # all of the supported platforms: 8192 (on NT/2K/XP). - lt_cv_sys_max_cmd_len=8192; - ;; - - amigaos*) - # On AmigaOS with pdksh, this test takes hours, literally. - # So we just punt and use a minimum line length of 8192. - lt_cv_sys_max_cmd_len=8192; - ;; - - netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) - # This has been around since 386BSD, at least. Likely further. - if test -x /sbin/sysctl; then - lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` - elif test -x /usr/sbin/sysctl; then - lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` - else - lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs - fi - # And add a safety zone - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` - ;; - - interix*) - # We know the value 262144 and hardcode it with a safety zone (like BSD) - lt_cv_sys_max_cmd_len=196608 - ;; - - osf*) - # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure - # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not - # nice to cause kernel panics so lets avoid the loop below. - # First set a reasonable default. - lt_cv_sys_max_cmd_len=16384 - # - if test -x /sbin/sysconfig; then - case `/sbin/sysconfig -q proc exec_disable_arg_limit` in - *1*) lt_cv_sys_max_cmd_len=-1 ;; - esac - fi - ;; - sco3.2v5*) - lt_cv_sys_max_cmd_len=102400 - ;; - sysv5* | sco5v6* | sysv4.2uw2*) - kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` - if test -n "$kargmax"; then - lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` - else - lt_cv_sys_max_cmd_len=32768 - fi - ;; - *) - # If test is not a shell built-in, we'll probably end up computing a - # maximum length that is only half of the actual maximum length, but - # we can't tell. - SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} - while (test "X"`$SHELL $0 --fallback-echo "X$teststring" 2>/dev/null` \ - = "XX$teststring") >/dev/null 2>&1 && - new_result=`expr "X$teststring" : ".*" 2>&1` && - lt_cv_sys_max_cmd_len=$new_result && - test $i != 17 # 1/2 MB should be enough - do - i=`expr $i + 1` - teststring=$teststring$teststring - done - teststring= - # Add a significant safety factor because C++ compilers can tack on massive - # amounts of additional arguments before passing them to the linker. - # It appears as though 1/2 is a usable value. - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` - ;; - esac - -fi - -if test -n $lt_cv_sys_max_cmd_len ; then - echo "$as_me:$LINENO: result: $lt_cv_sys_max_cmd_len" >&5 -echo "${ECHO_T}$lt_cv_sys_max_cmd_len" >&6 -else - echo "$as_me:$LINENO: result: none" >&5 -echo "${ECHO_T}none" >&6 -fi - - - - -# Check for command to grab the raw symbol name followed by C symbol from nm. -echo "$as_me:$LINENO: checking command to parse $NM output from $compiler object" >&5 -echo $ECHO_N "checking command to parse $NM output from $compiler object... $ECHO_C" >&6 -if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - -# These are sane defaults that work on at least a few old systems. -# [They come from Ultrix. What could be older than Ultrix?!! ;)] - -# Character class describing NM global symbol codes. -symcode='[BCDEGRST]' - -# Regexp to match symbols that can be accessed directly from C. -sympat='\([_A-Za-z][_A-Za-z0-9]*\)' - -# Transform an extracted symbol line into a proper C declaration -lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" - -# Transform an extracted symbol line into symbol name and symbol address -lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" - -# Define system-specific variables. -case $host_os in -aix*) - symcode='[BCDT]' - ;; -cygwin* | mingw* | pw32*) - symcode='[ABCDGISTW]' - ;; -hpux*) # Its linker distinguishes data from code symbols - if test "$host_cpu" = ia64; then - symcode='[ABCDEGRST]' - fi - lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" - lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" - ;; -linux*) - if test "$host_cpu" = ia64; then - symcode='[ABCDGIRSTW]' - lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" - lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" - fi - ;; -irix* | nonstopux*) - symcode='[BCDEGRST]' - ;; -osf*) - symcode='[BCDEGQRST]' - ;; -solaris*) - symcode='[BDRT]' - ;; -sco3.2v5*) - symcode='[DT]' - ;; -sysv4.2uw2*) - symcode='[DT]' - ;; -sysv5* | sco5v6* | unixware* | OpenUNIX*) - symcode='[ABDT]' - ;; -sysv4) - symcode='[DFNSTU]' - ;; -esac - -# Handle CRLF in mingw tool chain -opt_cr= -case $build_os in -mingw*) - opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp - ;; -esac - -# If we're using GNU nm, then use its standard symbol codes. -case `$NM -V 2>&1` in -*GNU* | *'with BFD'*) - symcode='[ABCDGIRSTW]' ;; -esac - -# Try without a prefix undercore, then with it. -for ac_symprfx in "" "_"; do - - # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. - symxfrm="\\1 $ac_symprfx\\2 \\2" - - # Write the raw and C identifiers. - lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" - - # Check to see that the pipe works correctly. - pipe_works=no - - rm -f conftest* - cat > conftest.$ac_ext <&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - # Now try to grab the symbols. - nlist=conftest.nm - if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\"") >&5 - (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && test -s "$nlist"; then - # Try sorting and uniquifying the output. - if sort "$nlist" | uniq > "$nlist"T; then - mv -f "$nlist"T "$nlist" - else - rm -f "$nlist"T - fi - - # Make sure that we snagged all the symbols we need. - if grep ' nm_test_var$' "$nlist" >/dev/null; then - if grep ' nm_test_func$' "$nlist" >/dev/null; then - cat < conftest.$ac_ext -#ifdef __cplusplus -extern "C" { -#endif - -EOF - # Now generate the symbol file. - eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' - - cat <> conftest.$ac_ext -#if defined (__STDC__) && __STDC__ -# define lt_ptr_t void * -#else -# define lt_ptr_t char * -# define const -#endif - -/* The mapping between symbol names and symbols. */ -const struct { - const char *name; - lt_ptr_t address; -} -lt_preloaded_symbols[] = -{ -EOF - $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext - cat <<\EOF >> conftest.$ac_ext - {0, (lt_ptr_t) 0} -}; - -#ifdef __cplusplus -} -#endif -EOF - # Now try linking the two files. - mv conftest.$ac_objext conftstm.$ac_objext - lt_save_LIBS="$LIBS" - lt_save_CFLAGS="$CFLAGS" - LIBS="conftstm.$ac_objext" - CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" - if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && test -s conftest${ac_exeext}; then - pipe_works=yes - fi - LIBS="$lt_save_LIBS" - CFLAGS="$lt_save_CFLAGS" - else - echo "cannot find nm_test_func in $nlist" >&5 - fi - else - echo "cannot find nm_test_var in $nlist" >&5 - fi - else - echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 - fi - else - echo "$progname: failed program was:" >&5 - cat conftest.$ac_ext >&5 - fi - rm -f conftest* conftst* - - # Do not use the global_symbol_pipe unless it works. - if test "$pipe_works" = yes; then - break - else - lt_cv_sys_global_symbol_pipe= - fi -done - -fi - -if test -z "$lt_cv_sys_global_symbol_pipe"; then - lt_cv_sys_global_symbol_to_cdecl= -fi -if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then - echo "$as_me:$LINENO: result: failed" >&5 -echo "${ECHO_T}failed" >&6 -else - echo "$as_me:$LINENO: result: ok" >&5 -echo "${ECHO_T}ok" >&6 -fi - -echo "$as_me:$LINENO: checking for objdir" >&5 -echo $ECHO_N "checking for objdir... $ECHO_C" >&6 -if test "${lt_cv_objdir+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - rm -f .libs 2>/dev/null -mkdir .libs 2>/dev/null -if test -d .libs; then - lt_cv_objdir=.libs -else - # MS-DOS does not allow filenames that begin with a dot. - lt_cv_objdir=_libs -fi -rmdir .libs 2>/dev/null -fi -echo "$as_me:$LINENO: result: $lt_cv_objdir" >&5 -echo "${ECHO_T}$lt_cv_objdir" >&6 -objdir=$lt_cv_objdir - - - - - -case $host_os in -aix3*) - # AIX sometimes has problems with the GCC collect2 program. For some - # reason, if we set the COLLECT_NAMES environment variable, the problems - # vanish in a puff of smoke. - if test "X${COLLECT_NAMES+set}" != Xset; then - COLLECT_NAMES= - export COLLECT_NAMES - fi - ;; -esac - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -Xsed='sed -e 1s/^X//' -sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g' - -# Same as above, but do not quote variable references. -double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g' - -# Sed substitution to delay expansion of an escaped shell variable in a -# double_quote_subst'ed string. -delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' - -# Sed substitution to avoid accidental globbing in evaled expressions -no_glob_subst='s/\*/\\\*/g' - -# Constants: -rm="rm -f" - -# Global variables: -default_ofile=libtool -can_build_shared=yes - -# All known linkers require a `.a' archive for static linking (except MSVC, -# which needs '.lib'). -libext=a -ltmain="$ac_aux_dir/ltmain.sh" -ofile="$default_ofile" -with_gnu_ld="$lt_cv_prog_gnu_ld" - -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. -set dummy ${ac_tool_prefix}ar; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_AR+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$AR"; then - ac_cv_prog_AR="$AR" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_AR="${ac_tool_prefix}ar" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -AR=$ac_cv_prog_AR -if test -n "$AR"; then - echo "$as_me:$LINENO: result: $AR" >&5 -echo "${ECHO_T}$AR" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$ac_cv_prog_AR"; then - ac_ct_AR=$AR - # Extract the first word of "ar", so it can be a program name with args. -set dummy ar; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_AR+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_AR"; then - ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_AR="ar" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - - test -z "$ac_cv_prog_ac_ct_AR" && ac_cv_prog_ac_ct_AR="false" -fi -fi -ac_ct_AR=$ac_cv_prog_ac_ct_AR -if test -n "$ac_ct_AR"; then - echo "$as_me:$LINENO: result: $ac_ct_AR" >&5 -echo "${ECHO_T}$ac_ct_AR" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - AR=$ac_ct_AR -else - AR="$ac_cv_prog_AR" -fi - -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. -set dummy ${ac_tool_prefix}ranlib; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_RANLIB+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$RANLIB"; then - ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -RANLIB=$ac_cv_prog_RANLIB -if test -n "$RANLIB"; then - echo "$as_me:$LINENO: result: $RANLIB" >&5 -echo "${ECHO_T}$RANLIB" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$ac_cv_prog_RANLIB"; then - ac_ct_RANLIB=$RANLIB - # Extract the first word of "ranlib", so it can be a program name with args. -set dummy ranlib; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_RANLIB"; then - ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_RANLIB="ranlib" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - - test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":" -fi -fi -ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB -if test -n "$ac_ct_RANLIB"; then - echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 -echo "${ECHO_T}$ac_ct_RANLIB" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - RANLIB=$ac_ct_RANLIB -else - RANLIB="$ac_cv_prog_RANLIB" -fi - -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. -set dummy ${ac_tool_prefix}strip; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_STRIP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$STRIP"; then - ac_cv_prog_STRIP="$STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_STRIP="${ac_tool_prefix}strip" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -STRIP=$ac_cv_prog_STRIP -if test -n "$STRIP"; then - echo "$as_me:$LINENO: result: $STRIP" >&5 -echo "${ECHO_T}$STRIP" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$ac_cv_prog_STRIP"; then - ac_ct_STRIP=$STRIP - # Extract the first word of "strip", so it can be a program name with args. -set dummy strip; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_STRIP"; then - ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_STRIP="strip" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - - test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":" -fi -fi -ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP -if test -n "$ac_ct_STRIP"; then - echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 -echo "${ECHO_T}$ac_ct_STRIP" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - STRIP=$ac_ct_STRIP -else - STRIP="$ac_cv_prog_STRIP" -fi - - -old_CC="$CC" -old_CFLAGS="$CFLAGS" - -# Set sane defaults for various variables -test -z "$AR" && AR=ar -test -z "$AR_FLAGS" && AR_FLAGS=cru -test -z "$AS" && AS=as -test -z "$CC" && CC=cc -test -z "$LTCC" && LTCC=$CC -test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS -test -z "$DLLTOOL" && DLLTOOL=dlltool -test -z "$LD" && LD=ld -test -z "$LN_S" && LN_S="ln -s" -test -z "$MAGIC_CMD" && MAGIC_CMD=file -test -z "$NM" && NM=nm -test -z "$SED" && SED=sed -test -z "$OBJDUMP" && OBJDUMP=objdump -test -z "$RANLIB" && RANLIB=: -test -z "$STRIP" && STRIP=: -test -z "$ac_objext" && ac_objext=o - -# Determine commands to create old-style static archives. -old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' -old_postinstall_cmds='chmod 644 $oldlib' -old_postuninstall_cmds= - -if test -n "$RANLIB"; then - case $host_os in - openbsd*) - old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" - ;; - *) - old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" - ;; - esac - old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" -fi - -for cc_temp in $compiler""; do - case $cc_temp in - compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; - distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; - \-*) ;; - *) break;; - esac -done -cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` - - -# Only perform the check for file, if the check method requires it -case $deplibs_check_method in -file_magic*) - if test "$file_magic_cmd" = '$MAGIC_CMD'; then - echo "$as_me:$LINENO: checking for ${ac_tool_prefix}file" >&5 -echo $ECHO_N "checking for ${ac_tool_prefix}file... $ECHO_C" >&6 -if test "${lt_cv_path_MAGIC_CMD+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - case $MAGIC_CMD in -[\\/*] | ?:[\\/]*) - lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. - ;; -*) - lt_save_MAGIC_CMD="$MAGIC_CMD" - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" - for ac_dir in $ac_dummy; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/${ac_tool_prefix}file; then - lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" - if test -n "$file_magic_test_file"; then - case $deplibs_check_method in - "file_magic "*) - file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` - MAGIC_CMD="$lt_cv_path_MAGIC_CMD" - if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | - $EGREP "$file_magic_regex" > /dev/null; then - : - else - cat <&2 - -*** Warning: the command libtool uses to detect shared libraries, -*** $file_magic_cmd, produces output that libtool cannot recognize. -*** The result is that libtool may fail to recognize shared libraries -*** as such. This will affect the creation of libtool libraries that -*** depend on shared libraries, but programs linked with such libtool -*** libraries will work regardless of this problem. Nevertheless, you -*** may want to report the problem to your system manager and/or to -*** bug-libtool@gnu.org - -EOF - fi ;; - esac - fi - break - fi - done - IFS="$lt_save_ifs" - MAGIC_CMD="$lt_save_MAGIC_CMD" - ;; -esac -fi - -MAGIC_CMD="$lt_cv_path_MAGIC_CMD" -if test -n "$MAGIC_CMD"; then - echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5 -echo "${ECHO_T}$MAGIC_CMD" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -if test -z "$lt_cv_path_MAGIC_CMD"; then - if test -n "$ac_tool_prefix"; then - echo "$as_me:$LINENO: checking for file" >&5 -echo $ECHO_N "checking for file... $ECHO_C" >&6 -if test "${lt_cv_path_MAGIC_CMD+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - case $MAGIC_CMD in -[\\/*] | ?:[\\/]*) - lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. - ;; -*) - lt_save_MAGIC_CMD="$MAGIC_CMD" - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" - for ac_dir in $ac_dummy; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/file; then - lt_cv_path_MAGIC_CMD="$ac_dir/file" - if test -n "$file_magic_test_file"; then - case $deplibs_check_method in - "file_magic "*) - file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` - MAGIC_CMD="$lt_cv_path_MAGIC_CMD" - if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | - $EGREP "$file_magic_regex" > /dev/null; then - : - else - cat <&2 - -*** Warning: the command libtool uses to detect shared libraries, -*** $file_magic_cmd, produces output that libtool cannot recognize. -*** The result is that libtool may fail to recognize shared libraries -*** as such. This will affect the creation of libtool libraries that -*** depend on shared libraries, but programs linked with such libtool -*** libraries will work regardless of this problem. Nevertheless, you -*** may want to report the problem to your system manager and/or to -*** bug-libtool@gnu.org - -EOF - fi ;; - esac - fi - break - fi - done - IFS="$lt_save_ifs" - MAGIC_CMD="$lt_save_MAGIC_CMD" - ;; -esac -fi - -MAGIC_CMD="$lt_cv_path_MAGIC_CMD" -if test -n "$MAGIC_CMD"; then - echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5 -echo "${ECHO_T}$MAGIC_CMD" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - else - MAGIC_CMD=: - fi -fi - - fi - ;; -esac - -enable_dlopen=no -enable_win32_dll=yes - -# Check whether --enable-libtool-lock or --disable-libtool-lock was given. -if test "${enable_libtool_lock+set}" = set; then - enableval="$enable_libtool_lock" - -fi; -test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes - - -# Check whether --with-pic or --without-pic was given. -if test "${with_pic+set}" = set; then - withval="$with_pic" - pic_mode="$withval" -else - pic_mode=default -fi; -test -z "$pic_mode" && pic_mode=default - -# Use C for the default configuration in the libtool script -tagname= -lt_save_CC="$CC" -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - -# Source file extension for C test sources. -ac_ext=c - -# Object file extension for compiled C test sources. -objext=o -objext=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code="int some_variable = 0;\n" - -# Code to be used in simple link tests -lt_simple_link_test_code='int main(){return(0);}\n' - - -# If no C compiler was specified, use CC. -LTCC=${LTCC-"$CC"} - -# If no C compiler flags were specified, use CFLAGS. -LTCFLAGS=${LTCFLAGS-"$CFLAGS"} - -# Allow CC to be a program name with arguments. -compiler=$CC - - -# save warnings/boilerplate of simple test code -ac_outfile=conftest.$ac_objext -printf "$lt_simple_compile_test_code" >conftest.$ac_ext -eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_compiler_boilerplate=`cat conftest.err` -$rm conftest* - -ac_outfile=conftest.$ac_objext -printf "$lt_simple_link_test_code" >conftest.$ac_ext -eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_linker_boilerplate=`cat conftest.err` -$rm conftest* - - -## CAVEAT EMPTOR: -## There is no encapsulation within the following macros, do not change -## the running order or otherwise move them around unless you know exactly -## what you are doing... - -lt_prog_compiler_no_builtin_flag= - -if test "$GCC" = yes; then - lt_prog_compiler_no_builtin_flag=' -fno-builtin' - - -echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 -echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6 -if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_cv_prog_compiler_rtti_exceptions=no - ac_outfile=conftest.$ac_objext - printf "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="-fno-rtti -fno-exceptions" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - # The option is referenced via a variable to avoid confusing sed. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:6363: $lt_compile\"" >&5) - (eval "$lt_compile" 2>conftest.err) - ac_status=$? - cat conftest.err >&5 - echo "$as_me:6367: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s "$ac_outfile"; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings other than the usual output. - $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then - lt_cv_prog_compiler_rtti_exceptions=yes - fi - fi - $rm conftest* - -fi -echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 -echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6 - -if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then - lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" -else - : -fi - -fi - -lt_prog_compiler_wl= -lt_prog_compiler_pic= -lt_prog_compiler_static= - -echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 -echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 - - if test "$GCC" = yes; then - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_static='-static' - - case $host_os in - aix*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static='-Bstatic' - fi - ;; - - amigaos*) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. - lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' - ;; - - beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - - mingw* | pw32* | os2*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - lt_prog_compiler_pic='-DDLL_EXPORT' - ;; - - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - lt_prog_compiler_pic='-fno-common' - ;; - - interix3*) - # Interix 3.x gcc -fpic/-fPIC options generate broken code. - # Instead, we relocate shared libraries at runtime. - ;; - - msdosdjgpp*) - # Just because we use GCC doesn't mean we suddenly get shared libraries - # on systems that don't support them. - lt_prog_compiler_can_build_shared=no - enable_shared=no - ;; - - sysv4*MP*) - if test -d /usr/nec; then - lt_prog_compiler_pic=-Kconform_pic - fi - ;; - - hpux*) - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case $host_cpu in - hppa*64*|ia64*) - # +Z the default - ;; - *) - lt_prog_compiler_pic='-fPIC' - ;; - esac - ;; - - *) - lt_prog_compiler_pic='-fPIC' - ;; - esac - else - # PORTME Check for flag to pass linker flags through the system compiler. - case $host_os in - aix*) - lt_prog_compiler_wl='-Wl,' - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static='-Bstatic' - else - lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' - fi - ;; - darwin*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - case $cc_basename in - xlc*) - lt_prog_compiler_pic='-qnocommon' - lt_prog_compiler_wl='-Wl,' - ;; - esac - ;; - - mingw* | pw32* | os2*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - lt_prog_compiler_pic='-DDLL_EXPORT' - ;; - - hpux9* | hpux10* | hpux11*) - lt_prog_compiler_wl='-Wl,' - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case $host_cpu in - hppa*64*|ia64*) - # +Z the default - ;; - *) - lt_prog_compiler_pic='+Z' - ;; - esac - # Is there a better lt_prog_compiler_static that works with the bundled CC? - lt_prog_compiler_static='${wl}-a ${wl}archive' - ;; - - irix5* | irix6* | nonstopux*) - lt_prog_compiler_wl='-Wl,' - # PIC (with -KPIC) is the default. - lt_prog_compiler_static='-non_shared' - ;; - - newsos6) - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-Bstatic' - ;; - - linux*) - case $cc_basename in - icc* | ecc*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-static' - ;; - pgcc* | pgf77* | pgf90* | pgf95*) - # Portland Group compilers (*not* the Pentium gcc compiler, - # which looks to be a dead project) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-fpic' - lt_prog_compiler_static='-Bstatic' - ;; - ccc*) - lt_prog_compiler_wl='-Wl,' - # All Alpha code is PIC. - lt_prog_compiler_static='-non_shared' - ;; - esac - ;; - - osf3* | osf4* | osf5*) - lt_prog_compiler_wl='-Wl,' - # All OSF/1 code is PIC. - lt_prog_compiler_static='-non_shared' - ;; - - solaris*) - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-Bstatic' - case $cc_basename in - f77* | f90* | f95*) - lt_prog_compiler_wl='-Qoption ld ';; - *) - lt_prog_compiler_wl='-Wl,';; - esac - ;; - - sunos4*) - lt_prog_compiler_wl='-Qoption ld ' - lt_prog_compiler_pic='-PIC' - lt_prog_compiler_static='-Bstatic' - ;; - - sysv4 | sysv4.2uw2* | sysv4.3*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-Bstatic' - ;; - - sysv4*MP*) - if test -d /usr/nec ;then - lt_prog_compiler_pic='-Kconform_pic' - lt_prog_compiler_static='-Bstatic' - fi - ;; - - sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-Bstatic' - ;; - - unicos*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_can_build_shared=no - ;; - - uts4*) - lt_prog_compiler_pic='-pic' - lt_prog_compiler_static='-Bstatic' - ;; - - *) - lt_prog_compiler_can_build_shared=no - ;; - esac - fi - -echo "$as_me:$LINENO: result: $lt_prog_compiler_pic" >&5 -echo "${ECHO_T}$lt_prog_compiler_pic" >&6 - -# -# Check to make sure the PIC flag actually works. -# -if test -n "$lt_prog_compiler_pic"; then - -echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 -echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic works... $ECHO_C" >&6 -if test "${lt_prog_compiler_pic_works+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_prog_compiler_pic_works=no - ac_outfile=conftest.$ac_objext - printf "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$lt_prog_compiler_pic -DPIC" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - # The option is referenced via a variable to avoid confusing sed. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:6631: $lt_compile\"" >&5) - (eval "$lt_compile" 2>conftest.err) - ac_status=$? - cat conftest.err >&5 - echo "$as_me:6635: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s "$ac_outfile"; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings other than the usual output. - $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then - lt_prog_compiler_pic_works=yes - fi - fi - $rm conftest* - -fi -echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works" >&5 -echo "${ECHO_T}$lt_prog_compiler_pic_works" >&6 - -if test x"$lt_prog_compiler_pic_works" = xyes; then - case $lt_prog_compiler_pic in - "" | " "*) ;; - *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; - esac -else - lt_prog_compiler_pic= - lt_prog_compiler_can_build_shared=no -fi - -fi -case $host_os in - # For platforms which do not support PIC, -DPIC is meaningless: - *djgpp*) - lt_prog_compiler_pic= - ;; - *) - lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" - ;; -esac - -# -# Check to make sure the static flag actually works. -# -wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" -echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 -echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6 -if test "${lt_prog_compiler_static_works+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_prog_compiler_static_works=no - save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS $lt_tmp_static_flag" - printf "$lt_simple_link_test_code" > conftest.$ac_ext - if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then - # The linker can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s conftest.err; then - # Append any errors to the config.log. - cat conftest.err 1>&5 - $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if diff conftest.exp conftest.er2 >/dev/null; then - lt_prog_compiler_static_works=yes - fi - else - lt_prog_compiler_static_works=yes - fi - fi - $rm conftest* - LDFLAGS="$save_LDFLAGS" - -fi -echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works" >&5 -echo "${ECHO_T}$lt_prog_compiler_static_works" >&6 - -if test x"$lt_prog_compiler_static_works" = xyes; then - : -else - lt_prog_compiler_static= -fi - - -echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 -echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6 -if test "${lt_cv_prog_compiler_c_o+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_cv_prog_compiler_c_o=no - $rm -r conftest 2>/dev/null - mkdir conftest - cd conftest - mkdir out - printf "$lt_simple_compile_test_code" > conftest.$ac_ext - - lt_compiler_flag="-o out/conftest2.$ac_objext" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:6735: $lt_compile\"" >&5) - (eval "$lt_compile" 2>out/conftest.err) - ac_status=$? - cat out/conftest.err >&5 - echo "$as_me:6739: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s out/conftest2.$ac_objext - then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp - $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 - if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then - lt_cv_prog_compiler_c_o=yes - fi - fi - chmod u+w . 2>&5 - $rm conftest* - # SGI C++ compiler will create directory out/ii_files/ for - # template instantiation - test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files - $rm out/* && rmdir out - cd .. - rmdir conftest - $rm conftest* - -fi -echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o" >&5 -echo "${ECHO_T}$lt_cv_prog_compiler_c_o" >&6 - - -hard_links="nottested" -if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then - # do not overwrite the value of need_locks provided by the user - echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 -echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6 - hard_links=yes - $rm conftest* - ln conftest.a conftest.b 2>/dev/null && hard_links=no - touch conftest.a - ln conftest.a conftest.b 2>&5 || hard_links=no - ln conftest.a conftest.b 2>/dev/null && hard_links=no - echo "$as_me:$LINENO: result: $hard_links" >&5 -echo "${ECHO_T}$hard_links" >&6 - if test "$hard_links" = no; then - { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 -echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} - need_locks=warn - fi -else - need_locks=no -fi - -echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 -echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6 - - runpath_var= - allow_undefined_flag= - enable_shared_with_static_runtimes=no - archive_cmds= - archive_expsym_cmds= - old_archive_From_new_cmds= - old_archive_from_expsyms_cmds= - export_dynamic_flag_spec= - whole_archive_flag_spec= - thread_safe_flag_spec= - hardcode_libdir_flag_spec= - hardcode_libdir_flag_spec_ld= - hardcode_libdir_separator= - hardcode_direct=no - hardcode_minus_L=no - hardcode_shlibpath_var=unsupported - link_all_deplibs=unknown - hardcode_automatic=no - module_cmds= - module_expsym_cmds= - always_export_symbols=no - export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - # include_expsyms should be a list of space-separated symbols to be *always* - # included in the symbol list - include_expsyms= - # exclude_expsyms can be an extended regexp of symbols to exclude - # it will be wrapped by ` (' and `)$', so one must not match beginning or - # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', - # as well as any symbol that contains `d'. - exclude_expsyms="_GLOBAL_OFFSET_TABLE_" - # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out - # platforms (ab)use it in PIC code, but their linkers get confused if - # the symbol is explicitly referenced. Since portable code cannot - # rely on this symbol name, it's probably fine to never include it in - # preloaded symbol tables. - extract_expsyms_cmds= - # Just being paranoid about ensuring that cc_basename is set. - for cc_temp in $compiler""; do - case $cc_temp in - compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; - distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; - \-*) ;; - *) break;; - esac -done -cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` - - case $host_os in - cygwin* | mingw* | pw32*) - # FIXME: the MSVC++ port hasn't been tested in a loooong time - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - if test "$GCC" != yes; then - with_gnu_ld=no - fi - ;; - interix*) - # we just hope/assume this is gcc and not c89 (= MSVC++) - with_gnu_ld=yes - ;; - openbsd*) - with_gnu_ld=no - ;; - esac - - ld_shlibs=yes - if test "$with_gnu_ld" = yes; then - # If archive_cmds runs LD, not CC, wlarc should be empty - wlarc='${wl}' - - # Set some defaults for GNU ld with shared library support. These - # are reset later if shared libraries are not supported. Putting them - # here allows them to be overridden if necessary. - runpath_var=LD_RUN_PATH - hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir' - export_dynamic_flag_spec='${wl}--export-dynamic' - # ancient GNU ld didn't support --whole-archive et. al. - if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then - whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - else - whole_archive_flag_spec= - fi - supports_anon_versioning=no - case `$LD -v 2>/dev/null` in - *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 - *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... - *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... - *\ 2.11.*) ;; # other 2.11 versions - *) supports_anon_versioning=yes ;; - esac - - # See if GNU ld supports shared libraries. - case $host_os in - aix3* | aix4* | aix5*) - # On AIX/PPC, the GNU linker is very broken - if test "$host_cpu" != ia64; then - ld_shlibs=no - cat <&2 - -*** Warning: the GNU linker, at least up to release 2.9.1, is reported -*** to be unable to reliably create shared libraries on AIX. -*** Therefore, libtool is disabling shared libraries support. If you -*** really care for shared libraries, you may want to modify your PATH -*** so that a non-GNU linker is found, and then restart. - -EOF - fi - ;; - - amigaos*) - archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - - # Samuel A. Falvo II reports - # that the semantics of dynamic libraries on AmigaOS, at least up - # to version 4, is to share data among multiple programs linked - # with the same dynamic library. Since this doesn't match the - # behavior of shared libraries on other platforms, we can't use - # them. - ld_shlibs=no - ;; - - beos*) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - allow_undefined_flag=unsupported - # Joseph Beckenbach says some releases of gcc - # support --undefined. This deserves some investigation. FIXME - archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - else - ld_shlibs=no - fi - ;; - - cygwin* | mingw* | pw32*) - # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, - # as there is no search path for DLLs. - hardcode_libdir_flag_spec='-L$libdir' - allow_undefined_flag=unsupported - always_export_symbols=no - enable_shared_with_static_runtimes=yes - export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' - - if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - else - ld_shlibs=no - fi - ;; - - interix3*) - hardcode_direct=no - hardcode_shlibpath_var=no - hardcode_libdir_flag_spec='${wl}-rpath,$libdir' - export_dynamic_flag_spec='${wl}-E' - # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. - # Instead, shared libraries are loaded at an image base (0x10000000 by - # default) and relocated if they conflict, which is a slow very memory - # consuming and fragmenting process. To avoid this, we pick a random, - # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link - # time. Moving up from 0x10000000 also allows more sbrk(2) space. - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - ;; - - linux*) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - tmp_addflag= - case $cc_basename,$host_cpu in - pgcc*) # Portland Group C compiler - whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' - tmp_addflag=' $pic_flag' - ;; - pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers - whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' - tmp_addflag=' $pic_flag -Mnomain' ;; - ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 - tmp_addflag=' -i_dynamic' ;; - efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 - tmp_addflag=' -i_dynamic -nofor_main' ;; - ifc* | ifort*) # Intel Fortran compiler - tmp_addflag=' -nofor_main' ;; - esac - archive_cmds='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - - if test $supports_anon_versioning = yes; then - archive_expsym_cmds='$echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - $echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' - fi - else - ld_shlibs=no - fi - ;; - - netbsd*) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' - wlarc= - else - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - fi - ;; - - solaris*) - if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then - ld_shlibs=no - cat <&2 - -*** Warning: The releases 2.8.* of the GNU linker cannot reliably -*** create shared libraries on Solaris systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.9.1 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -EOF - elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - ld_shlibs=no - fi - ;; - - sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) - case `$LD -v 2>&1` in - *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) - ld_shlibs=no - cat <<_LT_EOF 1>&2 - -*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not -*** reliably create shared libraries on SCO systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.16.91.0.3 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -_LT_EOF - ;; - *) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' - else - ld_shlibs=no - fi - ;; - esac - ;; - - sunos4*) - archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' - wlarc= - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - *) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - ld_shlibs=no - fi - ;; - esac - - if test "$ld_shlibs" = no; then - runpath_var= - hardcode_libdir_flag_spec= - export_dynamic_flag_spec= - whole_archive_flag_spec= - fi - else - # PORTME fill in a description of your system's linker (not GNU ld) - case $host_os in - aix3*) - allow_undefined_flag=unsupported - always_export_symbols=yes - archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' - # Note: this linker hardcodes the directories in LIBPATH if there - # are no directories specified by -L. - hardcode_minus_L=yes - if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then - # Neither direct hardcoding nor static linking is supported with a - # broken collect2. - hardcode_direct=unsupported - fi - ;; - - aix4* | aix5*) - if test "$host_cpu" = ia64; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag="" - else - # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - if $NM -V 2>&1 | grep 'GNU' > /dev/null; then - export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' - else - export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' - fi - aix_use_runtimelinking=no - - # Test if we are trying to use run time linking or normal - # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. - case $host_os in aix4.[23]|aix4.[23].*|aix5*) - for ld_flag in $LDFLAGS; do - if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then - aix_use_runtimelinking=yes - break - fi - done - ;; - esac - - exp_sym_flag='-bexport' - no_entry_flag='-bnoentry' - fi - - # When large executables or shared objects are built, AIX ld can - # have problems creating the table of contents. If linking a library - # or program results in "error TOC overflow" add -mminimal-toc to - # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not - # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. - - archive_cmds='' - hardcode_direct=yes - hardcode_libdir_separator=':' - link_all_deplibs=yes - - if test "$GCC" = yes; then - case $host_os in aix4.[012]|aix4.[012].*) - # We only want to do this on AIX 4.2 and lower, the check - # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` - if test -f "$collect2name" && \ - strings "$collect2name" | grep resolve_lib_name >/dev/null - then - # We have reworked collect2 - hardcode_direct=yes - else - # We have old collect2 - hardcode_direct=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - hardcode_minus_L=yes - hardcode_libdir_flag_spec='-L$libdir' - hardcode_libdir_separator= - fi - ;; - esac - shared_flag='-shared' - if test "$aix_use_runtimelinking" = yes; then - shared_flag="$shared_flag "'${wl}-G' - fi - else - # not using gcc - if test "$host_cpu" = ia64; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' - else - shared_flag='${wl}-bM:SRE' - fi - fi - fi - - # It seems that -bexpall does not export symbols beginning with - # underscore (_), so it is better to generate a list of symbols to export. - always_export_symbols=yes - if test "$aix_use_runtimelinking" = yes; then - # Warning - without using the other runtime loading flags (-brtl), - # -berok will link without error, but may produce a broken library. - allow_undefined_flag='-berok' - # Determine the default libpath from the value encoded in an empty executable. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'`; fi -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi - - hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" - archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" - else - if test "$host_cpu" = ia64; then - hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' - allow_undefined_flag="-z nodefs" - archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" - else - # Determine the default libpath from the value encoded in an empty executable. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'`; fi -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi - - hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" - # Warning - without using the other run time loading flags, - # -berok will link without error, but may produce a broken library. - no_undefined_flag=' ${wl}-bernotok' - allow_undefined_flag=' ${wl}-berok' - # Exported symbols can be pulled into shared objects from archives - whole_archive_flag_spec='$convenience' - archive_cmds_need_lc=yes - # This is similar to how AIX traditionally builds its shared libraries. - archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' - fi - fi - ;; - - amigaos*) - archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - # see comment about different semantics on the GNU ld section - ld_shlibs=no - ;; - - bsdi[45]*) - export_dynamic_flag_spec=-rdynamic - ;; - - cygwin* | mingw* | pw32*) - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - # hardcode_libdir_flag_spec is actually meaningless, as there is - # no search path for DLLs. - hardcode_libdir_flag_spec=' ' - allow_undefined_flag=unsupported - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" - # FIXME: Setting linknames here is a bad hack. - archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' - # The linker will automatically build a .lib file if we build a DLL. - old_archive_From_new_cmds='true' - # FIXME: Should let the user specify the lib program. - old_archive_cmds='lib /OUT:$oldlib$oldobjs$old_deplibs' - fix_srcfile_path='`cygpath -w "$srcfile"`' - enable_shared_with_static_runtimes=yes - ;; - - darwin* | rhapsody*) - case $host_os in - rhapsody* | darwin1.[012]) - allow_undefined_flag='${wl}-undefined ${wl}suppress' - ;; - *) # Darwin 1.3 on - if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then - allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' - else - case ${MACOSX_DEPLOYMENT_TARGET} in - 10.[012]) - allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' - ;; - 10.*) - allow_undefined_flag='${wl}-undefined ${wl}dynamic_lookup' - ;; - esac - fi - ;; - esac - archive_cmds_need_lc=no - hardcode_direct=no - hardcode_automatic=yes - hardcode_shlibpath_var=unsupported - whole_archive_flag_spec='' - link_all_deplibs=yes - if test "$GCC" = yes ; then - output_verbose_link_cmd='echo' - archive_cmds='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds - archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - else - case $cc_basename in - xlc*) - output_verbose_link_cmd='echo' - archive_cmds='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' - module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds - archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - ;; - *) - ld_shlibs=no - ;; - esac - fi - ;; - - dgux*) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_shlibpath_var=no - ;; - - freebsd1*) - ld_shlibs=no - ;; - - # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor - # support. Future versions do this automatically, but an explicit c++rt0.o - # does not break anything, and helps significantly (at the cost of a little - # extra space). - freebsd2.2*) - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' - hardcode_libdir_flag_spec='-R$libdir' - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - # Unfortunately, older versions of FreeBSD 2 do not have this feature. - freebsd2*) - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct=yes - hardcode_minus_L=yes - hardcode_shlibpath_var=no - ;; - - # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd* | kfreebsd*-gnu | dragonfly*) - archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec='-R$libdir' - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - hpux9*) - if test "$GCC" = yes; then - archive_cmds='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - else - archive_cmds='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - fi - hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' - hardcode_libdir_separator=: - hardcode_direct=yes - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L=yes - export_dynamic_flag_spec='${wl}-E' - ;; - - hpux10*) - if test "$GCC" = yes -a "$with_gnu_ld" = no; then - archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' - fi - if test "$with_gnu_ld" = no; then - hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' - hardcode_libdir_separator=: - - hardcode_direct=yes - export_dynamic_flag_spec='${wl}-E' - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L=yes - fi - ;; - - hpux11*) - if test "$GCC" = yes -a "$with_gnu_ld" = no; then - case $host_cpu in - hppa*64*) - archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - ia64*) - archive_cmds='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - else - case $host_cpu in - hppa*64*) - archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - ia64*) - archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - fi - if test "$with_gnu_ld" = no; then - hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' - hardcode_libdir_separator=: - - case $host_cpu in - hppa*64*|ia64*) - hardcode_libdir_flag_spec_ld='+b $libdir' - hardcode_direct=no - hardcode_shlibpath_var=no - ;; - *) - hardcode_direct=yes - export_dynamic_flag_spec='${wl}-E' - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L=yes - ;; - esac - fi - ;; - - irix5* | irix6* | nonstopux*) - if test "$GCC" = yes; then - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - hardcode_libdir_flag_spec_ld='-rpath $libdir' - fi - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator=: - link_all_deplibs=yes - ;; - - netbsd*) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out - else - archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF - fi - hardcode_libdir_flag_spec='-R$libdir' - hardcode_direct=yes - hardcode_shlibpath_var=no - ;; - - newsos6) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct=yes - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator=: - hardcode_shlibpath_var=no - ;; - - openbsd*) - hardcode_direct=yes - hardcode_shlibpath_var=no - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' - hardcode_libdir_flag_spec='${wl}-rpath,$libdir' - export_dynamic_flag_spec='${wl}-E' - else - case $host_os in - openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec='-R$libdir' - ;; - *) - archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec='${wl}-rpath,$libdir' - ;; - esac - fi - ;; - - os2*) - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - allow_undefined_flag=unsupported - archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' - old_archive_From_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' - ;; - - osf3*) - if test "$GCC" = yes; then - allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - allow_undefined_flag=' -expect_unresolved \*' - archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - fi - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator=: - ;; - - osf4* | osf5*) # as osf3* with the addition of -msym flag - if test "$GCC" = yes; then - allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - else - allow_undefined_flag=' -expect_unresolved \*' - archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ - $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' - - # Both c and cxx compiler support -rpath directly - hardcode_libdir_flag_spec='-rpath $libdir' - fi - hardcode_libdir_separator=: - ;; - - solaris*) - no_undefined_flag=' -z text' - if test "$GCC" = yes; then - wlarc='${wl}' - archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' - else - wlarc='' - archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' - archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' - fi - hardcode_libdir_flag_spec='-R$libdir' - hardcode_shlibpath_var=no - case $host_os in - solaris2.[0-5] | solaris2.[0-5].*) ;; - *) - # The compiler driver will combine linker options so we - # cannot just pass the convience library names through - # without $wl, iff we do not link with $LD. - # Luckily, gcc supports the same syntax we need for Sun Studio. - # Supported since Solaris 2.6 (maybe 2.5.1?) - case $wlarc in - '') - whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;; - *) - whole_archive_flag_spec='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; - esac ;; - esac - link_all_deplibs=yes - ;; - - sunos4*) - if test "x$host_vendor" = xsequent; then - # Use $CC to link under sequent, because it throws in some extra .o - # files that make .init and .fini sections work. - archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' - fi - hardcode_libdir_flag_spec='-L$libdir' - hardcode_direct=yes - hardcode_minus_L=yes - hardcode_shlibpath_var=no - ;; - - sysv4) - case $host_vendor in - sni) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct=yes # is this really true??? - ;; - siemens) - ## LD is ld it makes a PLAMLIB - ## CC just makes a GrossModule. - archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' - reload_cmds='$CC -r -o $output$reload_objs' - hardcode_direct=no - ;; - motorola) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct=no #Motorola manual says yes, but my tests say they lie - ;; - esac - runpath_var='LD_RUN_PATH' - hardcode_shlibpath_var=no - ;; - - sysv4.3*) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_shlibpath_var=no - export_dynamic_flag_spec='-Bexport' - ;; - - sysv4*MP*) - if test -d /usr/nec; then - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_shlibpath_var=no - runpath_var=LD_RUN_PATH - hardcode_runpath_var=yes - ld_shlibs=yes - fi - ;; - - sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) - no_undefined_flag='${wl}-z,text' - archive_cmds_need_lc=no - hardcode_shlibpath_var=no - runpath_var='LD_RUN_PATH' - - if test "$GCC" = yes; then - archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - fi - ;; - - sysv5* | sco3.2v5* | sco5v6*) - # Note: We can NOT use -z defs as we might desire, because we do not - # link with -lc, and that would cause any symbols used from libc to - # always be unresolved, which means just about no library would - # ever link correctly. If we're not using GNU ld we use -z text - # though, which does catch some bad symbols but isn't as heavy-handed - # as -z defs. - no_undefined_flag='${wl}-z,text' - allow_undefined_flag='${wl}-z,nodefs' - archive_cmds_need_lc=no - hardcode_shlibpath_var=no - hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' - hardcode_libdir_separator=':' - link_all_deplibs=yes - export_dynamic_flag_spec='${wl}-Bexport' - runpath_var='LD_RUN_PATH' - - if test "$GCC" = yes; then - archive_cmds='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - fi - ;; - - uts4*) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec='-L$libdir' - hardcode_shlibpath_var=no - ;; - - *) - ld_shlibs=no - ;; - esac - fi - -echo "$as_me:$LINENO: result: $ld_shlibs" >&5 -echo "${ECHO_T}$ld_shlibs" >&6 -test "$ld_shlibs" = no && can_build_shared=no - -# -# Do we need to explicitly link libc? -# -case "x$archive_cmds_need_lc" in -x|xyes) - # Assume -lc should be added - archive_cmds_need_lc=yes - - if test "$enable_shared" = yes && test "$GCC" = yes; then - case $archive_cmds in - *'~'*) - # FIXME: we may have to deal with multi-command sequences. - ;; - '$CC '*) - # Test whether the compiler implicitly links with -lc since on some - # systems, -lgcc has to come before -lc. If gcc already passes -lc - # to ld, don't add -lc before -lgcc. - echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 -echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6 - $rm conftest* - printf "$lt_simple_compile_test_code" > conftest.$ac_ext - - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } 2>conftest.err; then - soname=conftest - lib=conftest - libobjs=conftest.$ac_objext - deplibs= - wl=$lt_prog_compiler_wl - pic_flag=$lt_prog_compiler_pic - compiler_flags=-v - linker_flags=-v - verstring= - output_objdir=. - libname=conftest - lt_save_allow_undefined_flag=$allow_undefined_flag - allow_undefined_flag= - if { (eval echo "$as_me:$LINENO: \"$archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 - (eval $archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } - then - archive_cmds_need_lc=no - else - archive_cmds_need_lc=yes - fi - allow_undefined_flag=$lt_save_allow_undefined_flag - else - cat conftest.err 1>&5 - fi - $rm conftest* - echo "$as_me:$LINENO: result: $archive_cmds_need_lc" >&5 -echo "${ECHO_T}$archive_cmds_need_lc" >&6 - ;; - esac - fi - ;; -esac - -echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 -echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6 -library_names_spec= -libname_spec='lib$name' -soname_spec= -shrext_cmds=".so" -postinstall_cmds= -postuninstall_cmds= -finish_cmds= -finish_eval= -shlibpath_var= -shlibpath_overrides_runpath=unknown -version_type=none -dynamic_linker="$host_os ld.so" -sys_lib_dlsearch_path_spec="/lib /usr/lib" -if test "$GCC" = yes; then - sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then - # if the path contains ";" then we assume it to be the separator - # otherwise default to the standard path separator (i.e. ":") - it is - # assumed that no part of a normal pathname contains ";" but that should - # okay in the real world where ";" in dirpaths is itself problematic. - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi -else - sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" -fi -need_lib_prefix=unknown -hardcode_into_libs=no - -# when you set need_version to no, make sure it does not cause -set_version -# flags to be left without arguments -need_version=unknown - -case $host_os in -aix3*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' - shlibpath_var=LIBPATH - - # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='${libname}${release}${shared_ext}$major' - ;; - -aix4* | aix5*) - version_type=linux - need_lib_prefix=no - need_version=no - hardcode_into_libs=yes - if test "$host_cpu" = ia64; then - # AIX 5 supports IA64 - library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - else - # With GCC up to 2.95.x, collect2 would create an import file - # for dependence libraries. The import file would start with - # the line `#! .'. This would cause the generated library to - # depend on `.', always an invalid library. This was fixed in - # development snapshots of GCC prior to 3.0. - case $host_os in - aix4 | aix4.[01] | aix4.[01].*) - if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' - echo ' yes ' - echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then - : - else - can_build_shared=no - fi - ;; - esac - # AIX (on Power*) has no versioning support, so currently we can not hardcode correct - # soname into executable. Probably we can add versioning support to - # collect2, so additional links can be useful in future. - if test "$aix_use_runtimelinking" = yes; then - # If using run time linking (on AIX 4.2 or later) use lib.so - # instead of lib.a to let people know that these are not - # typical AIX shared libraries. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - else - # We preserve .a as extension for shared libraries through AIX4.2 - # and later when we are not doing run time linking. - library_names_spec='${libname}${release}.a $libname.a' - soname_spec='${libname}${release}${shared_ext}$major' - fi - shlibpath_var=LIBPATH - fi - ;; - -amigaos*) - library_names_spec='$libname.ixlibrary $libname.a' - # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' - ;; - -beos*) - library_names_spec='${libname}${shared_ext}' - dynamic_linker="$host_os ld.so" - shlibpath_var=LIBRARY_PATH - ;; - -bsdi[45]*) - version_type=linux - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" - sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" - # the default ld.so.conf also contains /usr/contrib/lib and - # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow - # libtool to hard-code these into programs - ;; - -cygwin* | mingw* | pw32*) - version_type=windows - shrext_cmds=".dll" - need_version=no - need_lib_prefix=no - - case $GCC,$host_os in - yes,cygwin* | yes,mingw* | yes,pw32*) - library_names_spec='$libname.dll.a' - # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname~ - chmod a+x \$dldir/$dlname' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $rm \$dlpath' - shlibpath_overrides_runpath=yes - - case $host_os in - cygwin*) - # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" - ;; - mingw*) - # MinGW DLLs use traditional 'lib' prefix - soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then - # It is most probably a Windows format PATH printed by - # mingw gcc, but we are running on Cygwin. Gcc prints its search - # path with ; separators, and with drive letters. We can handle the - # drive letters (cygwin fileutils understands them), so leave them, - # especially as we might pass files found there to a mingw objdump, - # which wouldn't understand a cygwinified path. Ahh. - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi - ;; - pw32*) - # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - ;; - esac - ;; - - *) - library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' - ;; - esac - dynamic_linker='Win32 ld.exe' - # FIXME: first we should search . and the directory the executable is in - shlibpath_var=PATH - ;; - -darwin* | rhapsody*) - dynamic_linker="$host_os dyld" - version_type=darwin - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' - soname_spec='${libname}${release}${major}$shared_ext' - shlibpath_overrides_runpath=yes - shlibpath_var=DYLD_LIBRARY_PATH - shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' - # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. - if test "$GCC" = yes; then - sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` - else - sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' - fi - sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' - ;; - -dgux*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -freebsd1*) - dynamic_linker=no - ;; - -kfreebsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='GNU ld.so' - ;; - -freebsd* | dragonfly*) - # DragonFly does not have aout. When/if they implement a new - # versioning mechanism, adjust this. - if test -x /usr/bin/objformat; then - objformat=`/usr/bin/objformat` - else - case $host_os in - freebsd[123]*) objformat=aout ;; - *) objformat=elf ;; - esac - fi - version_type=freebsd-$objformat - case $version_type in - freebsd-elf*) - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - need_version=no - need_lib_prefix=no - ;; - freebsd-*) - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' - need_version=yes - ;; - esac - shlibpath_var=LD_LIBRARY_PATH - case $host_os in - freebsd2*) - shlibpath_overrides_runpath=yes - ;; - freebsd3.[01]* | freebsdelf3.[01]*) - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ - freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - freebsd*) # from 4.6 on - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - esac - ;; - -gnu*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - hardcode_into_libs=yes - ;; - -hpux9* | hpux10* | hpux11*) - # Give a soname corresponding to the major version so that dld.sl refuses to - # link against other versions. - version_type=sunos - need_lib_prefix=no - need_version=no - case $host_cpu in - ia64*) - shrext_cmds='.so' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.so" - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - if test "X$HPUX_IA64_MODE" = X32; then - sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" - else - sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" - fi - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - hppa*64*) - shrext_cmds='.sl' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.sl" - shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - *) - shrext_cmds='.sl' - dynamic_linker="$host_os dld.sl" - shlibpath_var=SHLIB_PATH - shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - ;; - esac - # HP-UX runs *really* slowly unless shared libraries are mode 555. - postinstall_cmds='chmod 555 $lib' - ;; - -interix3*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - -irix5* | irix6* | nonstopux*) - case $host_os in - nonstopux*) version_type=nonstopux ;; - *) - if test "$lt_cv_prog_gnu_ld" = yes; then - version_type=linux - else - version_type=irix - fi ;; - esac - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' - case $host_os in - irix5* | nonstopux*) - libsuff= shlibsuff= - ;; - *) - case $LD in # libtool.m4 will add one of these switches to LD - *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") - libsuff= shlibsuff= libmagic=32-bit;; - *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") - libsuff=32 shlibsuff=N32 libmagic=N32;; - *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") - libsuff=64 shlibsuff=64 libmagic=64-bit;; - *) libsuff= shlibsuff= libmagic=never-match;; - esac - ;; - esac - shlibpath_var=LD_LIBRARY${shlibsuff}_PATH - shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" - sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" - hardcode_into_libs=yes - ;; - -# No shared lib support for Linux oldld, aout, or coff. -linux*oldld* | linux*aout* | linux*coff*) - dynamic_linker=no - ;; - -# This must be Linux ELF. -linux*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. - hardcode_into_libs=yes - - # Append ld.so.conf contents to the search path - if test -f /etc/ld.so.conf; then - lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` - sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" - fi - - # We used to test for /lib/ld.so.1 and disable shared libraries on - # powerpc, because MkLinux only supported shared libraries with the - # GNU dynamic linker. Since this was broken with cross compilers, - # most powerpc-linux boxes support dynamic linking these days and - # people can always --disable-shared, the test was removed, and we - # assume the GNU/Linux dynamic linker is in use. - dynamic_linker='GNU/Linux ld.so' - ;; - -knetbsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='GNU ld.so' - ;; - -netbsd*) - version_type=sunos - need_lib_prefix=no - need_version=no - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - dynamic_linker='NetBSD (a.out) ld.so' - else - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='NetBSD ld.elf_so' - fi - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - -newsos6) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -nto-qnx*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -openbsd*) - version_type=sunos - sys_lib_dlsearch_path_spec="/usr/lib" - need_lib_prefix=no - # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. - case $host_os in - openbsd3.3 | openbsd3.3.*) need_version=yes ;; - *) need_version=no ;; - esac - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - shlibpath_var=LD_LIBRARY_PATH - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - case $host_os in - openbsd2.[89] | openbsd2.[89].*) - shlibpath_overrides_runpath=no - ;; - *) - shlibpath_overrides_runpath=yes - ;; - esac - else - shlibpath_overrides_runpath=yes - fi - ;; - -os2*) - libname_spec='$name' - shrext_cmds=".dll" - need_lib_prefix=no - library_names_spec='$libname${shared_ext} $libname.a' - dynamic_linker='OS/2 ld.exe' - shlibpath_var=LIBPATH - ;; - -osf3* | osf4* | osf5*) - version_type=osf - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" - ;; - -solaris*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - # ldd complains unless libraries are executable - postinstall_cmds='chmod +x $lib' - ;; - -sunos4*) - version_type=sunos - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - if test "$with_gnu_ld" = yes; then - need_lib_prefix=no - fi - need_version=yes - ;; - -sysv4 | sysv4.3*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - case $host_vendor in - sni) - shlibpath_overrides_runpath=no - need_lib_prefix=no - export_dynamic_flag_spec='${wl}-Blargedynsym' - runpath_var=LD_RUN_PATH - ;; - siemens) - need_lib_prefix=no - ;; - motorola) - need_lib_prefix=no - need_version=no - shlibpath_overrides_runpath=no - sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' - ;; - esac - ;; - -sysv4*MP*) - if test -d /usr/nec ;then - version_type=linux - library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' - soname_spec='$libname${shared_ext}.$major' - shlibpath_var=LD_LIBRARY_PATH - fi - ;; - -sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - version_type=freebsd-elf - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - hardcode_into_libs=yes - if test "$with_gnu_ld" = yes; then - sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' - shlibpath_overrides_runpath=no - else - sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' - shlibpath_overrides_runpath=yes - case $host_os in - sco3.2v5*) - sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" - ;; - esac - fi - sys_lib_dlsearch_path_spec='/usr/lib' - ;; - -uts4*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -*) - dynamic_linker=no - ;; -esac -echo "$as_me:$LINENO: result: $dynamic_linker" >&5 -echo "${ECHO_T}$dynamic_linker" >&6 -test "$dynamic_linker" = no && can_build_shared=no - -variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test "$GCC" = yes; then - variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" -fi - -echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 -echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6 -hardcode_action= -if test -n "$hardcode_libdir_flag_spec" || \ - test -n "$runpath_var" || \ - test "X$hardcode_automatic" = "Xyes" ; then - - # We can hardcode non-existant directories. - if test "$hardcode_direct" != no && - # If the only mechanism to avoid hardcoding is shlibpath_var, we - # have to relink, otherwise we might link with an installed library - # when we should be linking with a yet-to-be-installed one - ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, )" != no && - test "$hardcode_minus_L" != no; then - # Linking always hardcodes the temporary library directory. - hardcode_action=relink - else - # We can link without hardcoding, and we can hardcode nonexisting dirs. - hardcode_action=immediate - fi -else - # We cannot hardcode anything, or else we can only hardcode existing - # directories. - hardcode_action=unsupported -fi -echo "$as_me:$LINENO: result: $hardcode_action" >&5 -echo "${ECHO_T}$hardcode_action" >&6 - -if test "$hardcode_action" = relink; then - # Fast installation is not supported - enable_fast_install=no -elif test "$shlibpath_overrides_runpath" = yes || - test "$enable_shared" = no; then - # Fast installation is not necessary - enable_fast_install=needless -fi - -striplib= -old_striplib= -echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5 -echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6 -if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then - test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" - test -z "$striplib" && striplib="$STRIP --strip-unneeded" - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 -else -# FIXME - insert some real tests, host_os isn't really good enough - case $host_os in - darwin*) - if test -n "$STRIP" ; then - striplib="$STRIP -x" - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 - else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - ;; - *) - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 - ;; - esac -fi - -if test "x$enable_dlopen" != xyes; then - enable_dlopen=unknown - enable_dlopen_self=unknown - enable_dlopen_self_static=unknown -else - lt_cv_dlopen=no - lt_cv_dlopen_libs= - - case $host_os in - beos*) - lt_cv_dlopen="load_add_on" - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - ;; - - mingw* | pw32*) - lt_cv_dlopen="LoadLibrary" - lt_cv_dlopen_libs= - ;; - - cygwin*) - lt_cv_dlopen="dlopen" - lt_cv_dlopen_libs= - ;; - - darwin*) - # if libdl is installed we need to link against it - echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 -echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6 -if test "${ac_cv_lib_dl_dlopen+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldl $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char dlopen (); -int -main () -{ -dlopen (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_dl_dlopen=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_dl_dlopen=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 -echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6 -if test $ac_cv_lib_dl_dlopen = yes; then - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" -else - - lt_cv_dlopen="dyld" - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - -fi - - ;; - - *) - echo "$as_me:$LINENO: checking for shl_load" >&5 -echo $ECHO_N "checking for shl_load... $ECHO_C" >&6 -if test "${ac_cv_func_shl_load+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define shl_load to an innocuous variant, in case declares shl_load. - For example, HP-UX 11i declares gettimeofday. */ -#define shl_load innocuous_shl_load - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char shl_load (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef shl_load - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -{ -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char shl_load (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_shl_load) || defined (__stub___shl_load) -choke me -#else -char (*f) () = shl_load; -#endif -#ifdef __cplusplus -} -#endif - -int -main () -{ -return f != shl_load; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_func_shl_load=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_func_shl_load=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5 -echo "${ECHO_T}$ac_cv_func_shl_load" >&6 -if test $ac_cv_func_shl_load = yes; then - lt_cv_dlopen="shl_load" -else - echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 -echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6 -if test "${ac_cv_lib_dld_shl_load+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldld $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char shl_load (); -int -main () -{ -shl_load (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_dld_shl_load=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_dld_shl_load=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 -echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6 -if test $ac_cv_lib_dld_shl_load = yes; then - lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld" -else - echo "$as_me:$LINENO: checking for dlopen" >&5 -echo $ECHO_N "checking for dlopen... $ECHO_C" >&6 -if test "${ac_cv_func_dlopen+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define dlopen to an innocuous variant, in case declares dlopen. - For example, HP-UX 11i declares gettimeofday. */ -#define dlopen innocuous_dlopen - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char dlopen (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef dlopen - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -{ -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char dlopen (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_dlopen) || defined (__stub___dlopen) -choke me -#else -char (*f) () = dlopen; -#endif -#ifdef __cplusplus -} -#endif - -int -main () -{ -return f != dlopen; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_func_dlopen=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_func_dlopen=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5 -echo "${ECHO_T}$ac_cv_func_dlopen" >&6 -if test $ac_cv_func_dlopen = yes; then - lt_cv_dlopen="dlopen" -else - echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 -echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6 -if test "${ac_cv_lib_dl_dlopen+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldl $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char dlopen (); -int -main () -{ -dlopen (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_dl_dlopen=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_dl_dlopen=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 -echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6 -if test $ac_cv_lib_dl_dlopen = yes; then - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" -else - echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5 -echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6 -if test "${ac_cv_lib_svld_dlopen+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lsvld $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char dlopen (); -int -main () -{ -dlopen (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_svld_dlopen=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_svld_dlopen=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5 -echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6 -if test $ac_cv_lib_svld_dlopen = yes; then - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" -else - echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5 -echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6 -if test "${ac_cv_lib_dld_dld_link+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldld $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char dld_link (); -int -main () -{ -dld_link (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_dld_dld_link=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_dld_dld_link=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5 -echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6 -if test $ac_cv_lib_dld_dld_link = yes; then - lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld" -fi - - -fi - - -fi - - -fi - - -fi - - -fi - - ;; - esac - - if test "x$lt_cv_dlopen" != xno; then - enable_dlopen=yes - else - enable_dlopen=no - fi - - case $lt_cv_dlopen in - dlopen) - save_CPPFLAGS="$CPPFLAGS" - test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" - - save_LDFLAGS="$LDFLAGS" - wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" - - save_LIBS="$LIBS" - LIBS="$lt_cv_dlopen_libs $LIBS" - - echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5 -echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6 -if test "${lt_cv_dlopen_self+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test "$cross_compiling" = yes; then : - lt_cv_dlopen_self=cross -else - lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 - lt_status=$lt_dlunknown - cat > conftest.$ac_ext < -#endif - -#include - -#ifdef RTLD_GLOBAL -# define LT_DLGLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LT_DLGLOBAL DL_GLOBAL -# else -# define LT_DLGLOBAL 0 -# endif -#endif - -/* We may have to define LT_DLLAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LT_DLLAZY_OR_NOW -# ifdef RTLD_LAZY -# define LT_DLLAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LT_DLLAZY_OR_NOW DL_LAZY -# else -# ifdef RTLD_NOW -# define LT_DLLAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LT_DLLAZY_OR_NOW DL_NOW -# else -# define LT_DLLAZY_OR_NOW 0 -# endif -# endif -# endif -# endif -#endif - -#ifdef __cplusplus -extern "C" void exit (int); -#endif - -void fnord() { int i=42;} -int main () -{ - void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); - int status = $lt_dlunknown; - - if (self) - { - if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; - /* dlclose (self); */ - } - else - puts (dlerror ()); - - exit (status); -} -EOF - if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then - (./conftest; exit; ) >&5 2>/dev/null - lt_status=$? - case x$lt_status in - x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; - x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; - x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; - esac - else : - # compilation failed - lt_cv_dlopen_self=no - fi -fi -rm -fr conftest* - - -fi -echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5 -echo "${ECHO_T}$lt_cv_dlopen_self" >&6 - - if test "x$lt_cv_dlopen_self" = xyes; then - wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" - echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5 -echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6 -if test "${lt_cv_dlopen_self_static+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test "$cross_compiling" = yes; then : - lt_cv_dlopen_self_static=cross -else - lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 - lt_status=$lt_dlunknown - cat > conftest.$ac_ext < -#endif - -#include - -#ifdef RTLD_GLOBAL -# define LT_DLGLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LT_DLGLOBAL DL_GLOBAL -# else -# define LT_DLGLOBAL 0 -# endif -#endif - -/* We may have to define LT_DLLAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LT_DLLAZY_OR_NOW -# ifdef RTLD_LAZY -# define LT_DLLAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LT_DLLAZY_OR_NOW DL_LAZY -# else -# ifdef RTLD_NOW -# define LT_DLLAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LT_DLLAZY_OR_NOW DL_NOW -# else -# define LT_DLLAZY_OR_NOW 0 -# endif -# endif -# endif -# endif -#endif - -#ifdef __cplusplus -extern "C" void exit (int); -#endif - -void fnord() { int i=42;} -int main () -{ - void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); - int status = $lt_dlunknown; - - if (self) - { - if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; - /* dlclose (self); */ - } - else - puts (dlerror ()); - - exit (status); -} -EOF - if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then - (./conftest; exit; ) >&5 2>/dev/null - lt_status=$? - case x$lt_status in - x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; - x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; - x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; - esac - else : - # compilation failed - lt_cv_dlopen_self_static=no - fi -fi -rm -fr conftest* - - -fi -echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5 -echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6 - fi - - CPPFLAGS="$save_CPPFLAGS" - LDFLAGS="$save_LDFLAGS" - LIBS="$save_LIBS" - ;; - esac - - case $lt_cv_dlopen_self in - yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; - *) enable_dlopen_self=unknown ;; - esac - - case $lt_cv_dlopen_self_static in - yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; - *) enable_dlopen_self_static=unknown ;; - esac -fi - - -# Report which library types will actually be built -echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5 -echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6 -echo "$as_me:$LINENO: result: $can_build_shared" >&5 -echo "${ECHO_T}$can_build_shared" >&6 - -echo "$as_me:$LINENO: checking whether to build shared libraries" >&5 -echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6 -test "$can_build_shared" = "no" && enable_shared=no - -# On AIX, shared libraries and static libraries use the same namespace, and -# are all built from PIC. -case $host_os in -aix3*) - test "$enable_shared" = yes && enable_static=no - if test -n "$RANLIB"; then - archive_cmds="$archive_cmds~\$RANLIB \$lib" - postinstall_cmds='$RANLIB $lib' - fi - ;; - -aix4* | aix5*) - if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then - test "$enable_shared" = yes && enable_static=no - fi - ;; -esac -echo "$as_me:$LINENO: result: $enable_shared" >&5 -echo "${ECHO_T}$enable_shared" >&6 - -echo "$as_me:$LINENO: checking whether to build static libraries" >&5 -echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6 -# Make sure either enable_shared or enable_static is yes. -test "$enable_shared" = yes || enable_static=yes -echo "$as_me:$LINENO: result: $enable_static" >&5 -echo "${ECHO_T}$enable_static" >&6 - -# The else clause should only fire when bootstrapping the -# libtool distribution, otherwise you forgot to ship ltmain.sh -# with your package, and you will get complaints that there are -# no rules to generate ltmain.sh. -if test -f "$ltmain"; then - # See if we are running on zsh, and set the options which allow our commands through - # without removal of \ escapes. - if test -n "${ZSH_VERSION+set}" ; then - setopt NO_GLOB_SUBST - fi - # Now quote all the things that may contain metacharacters while being - # careful not to overquote the AC_SUBSTed values. We take copies of the - # variables and quote the copies for generation of the libtool script. - for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ - SED SHELL STRIP \ - libname_spec library_names_spec soname_spec extract_expsyms_cmds \ - old_striplib striplib file_magic_cmd finish_cmds finish_eval \ - deplibs_check_method reload_flag reload_cmds need_locks \ - lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ - lt_cv_sys_global_symbol_to_c_name_address \ - sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ - old_postinstall_cmds old_postuninstall_cmds \ - compiler \ - CC \ - LD \ - lt_prog_compiler_wl \ - lt_prog_compiler_pic \ - lt_prog_compiler_static \ - lt_prog_compiler_no_builtin_flag \ - export_dynamic_flag_spec \ - thread_safe_flag_spec \ - whole_archive_flag_spec \ - enable_shared_with_static_runtimes \ - old_archive_cmds \ - old_archive_from_new_cmds \ - predep_objects \ - postdep_objects \ - predeps \ - postdeps \ - compiler_lib_search_path \ - archive_cmds \ - archive_expsym_cmds \ - postinstall_cmds \ - postuninstall_cmds \ - old_archive_from_expsyms_cmds \ - allow_undefined_flag \ - no_undefined_flag \ - export_symbols_cmds \ - hardcode_libdir_flag_spec \ - hardcode_libdir_flag_spec_ld \ - hardcode_libdir_separator \ - hardcode_automatic \ - module_cmds \ - module_expsym_cmds \ - lt_cv_prog_compiler_c_o \ - exclude_expsyms \ - include_expsyms; do - - case $var in - old_archive_cmds | \ - old_archive_from_new_cmds | \ - archive_cmds | \ - archive_expsym_cmds | \ - module_cmds | \ - module_expsym_cmds | \ - old_archive_from_expsyms_cmds | \ - export_symbols_cmds | \ - extract_expsyms_cmds | reload_cmds | finish_cmds | \ - postinstall_cmds | postuninstall_cmds | \ - old_postinstall_cmds | old_postuninstall_cmds | \ - sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) - # Double-quote double-evaled strings. - eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" - ;; - *) - eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" - ;; - esac - done - - case $lt_echo in - *'\$0 --fallback-echo"') - lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` - ;; - esac - -cfgfile="${ofile}T" - trap "$rm \"$cfgfile\"; exit 1" 1 2 15 - $rm -f "$cfgfile" - { echo "$as_me:$LINENO: creating $ofile" >&5 -echo "$as_me: creating $ofile" >&6;} - - cat <<__EOF__ >> "$cfgfile" -#! $SHELL - -# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. -# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) -# NOTE: Changes made to this file will be lost: look at ltmain.sh. -# -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 -# Free Software Foundation, Inc. -# -# This file is part of GNU Libtool: -# Originally by Gordon Matzigkeit , 1996 -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# A sed program that does not truncate output. -SED=$lt_SED - -# Sed that helps us avoid accidentally triggering echo(1) options like -n. -Xsed="$SED -e 1s/^X//" - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -# The names of the tagged configurations supported by this script. -available_tags= - -# ### BEGIN LIBTOOL CONFIG - -# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: - -# Shell to use when invoking shell scripts. -SHELL=$lt_SHELL - -# Whether or not to build shared libraries. -build_libtool_libs=$enable_shared - -# Whether or not to build static libraries. -build_old_libs=$enable_static - -# Whether or not to add -lc for building shared libraries. -build_libtool_need_lc=$archive_cmds_need_lc - -# Whether or not to disallow shared libs when runtime libs are static -allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes - -# Whether or not to optimize for fast installation. -fast_install=$enable_fast_install - -# The host system. -host_alias=$host_alias -host=$host -host_os=$host_os - -# The build system. -build_alias=$build_alias -build=$build -build_os=$build_os - -# An echo program that does not interpret backslashes. -echo=$lt_echo - -# The archiver. -AR=$lt_AR -AR_FLAGS=$lt_AR_FLAGS - -# A C compiler. -LTCC=$lt_LTCC - -# LTCC compiler flags. -LTCFLAGS=$lt_LTCFLAGS - -# A language-specific compiler. -CC=$lt_compiler - -# Is the compiler the GNU C compiler? -with_gcc=$GCC - -# An ERE matcher. -EGREP=$lt_EGREP - -# The linker used to build libraries. -LD=$lt_LD - -# Whether we need hard or soft links. -LN_S=$lt_LN_S - -# A BSD-compatible nm program. -NM=$lt_NM - -# A symbol stripping program -STRIP=$lt_STRIP - -# Used to examine libraries when file_magic_cmd begins "file" -MAGIC_CMD=$MAGIC_CMD - -# Used on cygwin: DLL creation program. -DLLTOOL="$DLLTOOL" - -# Used on cygwin: object dumper. -OBJDUMP="$OBJDUMP" - -# Used on cygwin: assembler. -AS="$AS" - -# The name of the directory that contains temporary libtool files. -objdir=$objdir - -# How to create reloadable object files. -reload_flag=$lt_reload_flag -reload_cmds=$lt_reload_cmds - -# How to pass a linker flag through the compiler. -wl=$lt_lt_prog_compiler_wl - -# Object file suffix (normally "o"). -objext="$ac_objext" - -# Old archive suffix (normally "a"). -libext="$libext" - -# Shared library suffix (normally ".so"). -shrext_cmds='$shrext_cmds' - -# Executable file suffix (normally ""). -exeext="$exeext" - -# Additional compiler flags for building library objects. -pic_flag=$lt_lt_prog_compiler_pic -pic_mode=$pic_mode - -# What is the maximum length of a command? -max_cmd_len=$lt_cv_sys_max_cmd_len - -# Does compiler simultaneously support -c and -o options? -compiler_c_o=$lt_lt_cv_prog_compiler_c_o - -# Must we lock files when doing compilation? -need_locks=$lt_need_locks - -# Do we need the lib prefix for modules? -need_lib_prefix=$need_lib_prefix - -# Do we need a version for libraries? -need_version=$need_version - -# Whether dlopen is supported. -dlopen_support=$enable_dlopen - -# Whether dlopen of programs is supported. -dlopen_self=$enable_dlopen_self - -# Whether dlopen of statically linked programs is supported. -dlopen_self_static=$enable_dlopen_self_static - -# Compiler flag to prevent dynamic linking. -link_static_flag=$lt_lt_prog_compiler_static - -# Compiler flag to turn off builtin functions. -no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag - -# Compiler flag to allow reflexive dlopens. -export_dynamic_flag_spec=$lt_export_dynamic_flag_spec - -# Compiler flag to generate shared objects directly from archives. -whole_archive_flag_spec=$lt_whole_archive_flag_spec - -# Compiler flag to generate thread-safe objects. -thread_safe_flag_spec=$lt_thread_safe_flag_spec - -# Library versioning type. -version_type=$version_type - -# Format of library name prefix. -libname_spec=$lt_libname_spec - -# List of archive names. First name is the real one, the rest are links. -# The last name is the one that the linker finds with -lNAME. -library_names_spec=$lt_library_names_spec - -# The coded name of the library, if different from the real name. -soname_spec=$lt_soname_spec - -# Commands used to build and install an old-style archive. -RANLIB=$lt_RANLIB -old_archive_cmds=$lt_old_archive_cmds -old_postinstall_cmds=$lt_old_postinstall_cmds -old_postuninstall_cmds=$lt_old_postuninstall_cmds - -# Create an old-style archive from a shared archive. -old_archive_from_new_cmds=$lt_old_archive_from_new_cmds - -# Create a temporary old-style archive to link instead of a shared archive. -old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds - -# Commands used to build and install a shared archive. -archive_cmds=$lt_archive_cmds -archive_expsym_cmds=$lt_archive_expsym_cmds -postinstall_cmds=$lt_postinstall_cmds -postuninstall_cmds=$lt_postuninstall_cmds - -# Commands used to build a loadable module (assumed same as above if empty) -module_cmds=$lt_module_cmds -module_expsym_cmds=$lt_module_expsym_cmds - -# Commands to strip libraries. -old_striplib=$lt_old_striplib -striplib=$lt_striplib - -# Dependencies to place before the objects being linked to create a -# shared library. -predep_objects=$lt_predep_objects - -# Dependencies to place after the objects being linked to create a -# shared library. -postdep_objects=$lt_postdep_objects - -# Dependencies to place before the objects being linked to create a -# shared library. -predeps=$lt_predeps - -# Dependencies to place after the objects being linked to create a -# shared library. -postdeps=$lt_postdeps - -# The library search path used internally by the compiler when linking -# a shared library. -compiler_lib_search_path=$lt_compiler_lib_search_path - -# Method to check whether dependent libraries are shared objects. -deplibs_check_method=$lt_deplibs_check_method - -# Command to use when deplibs_check_method == file_magic. -file_magic_cmd=$lt_file_magic_cmd - -# Flag that allows shared libraries with undefined symbols to be built. -allow_undefined_flag=$lt_allow_undefined_flag - -# Flag that forces no undefined symbols. -no_undefined_flag=$lt_no_undefined_flag - -# Commands used to finish a libtool library installation in a directory. -finish_cmds=$lt_finish_cmds - -# Same as above, but a single script fragment to be evaled but not shown. -finish_eval=$lt_finish_eval - -# Take the output of nm and produce a listing of raw symbols and C names. -global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe - -# Transform the output of nm in a proper C declaration -global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl - -# Transform the output of nm in a C name address pair -global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address - -# This is the shared library runtime path variable. -runpath_var=$runpath_var - -# This is the shared library path variable. -shlibpath_var=$shlibpath_var - -# Is shlibpath searched before the hard-coded library search path? -shlibpath_overrides_runpath=$shlibpath_overrides_runpath - -# How to hardcode a shared library path into an executable. -hardcode_action=$hardcode_action - -# Whether we should hardcode library paths into libraries. -hardcode_into_libs=$hardcode_into_libs - -# Flag to hardcode \$libdir into a binary during linking. -# This must work even if \$libdir does not exist. -hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec - -# If ld is used when linking, flag to hardcode \$libdir into -# a binary during linking. This must work even if \$libdir does -# not exist. -hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld - -# Whether we need a single -rpath flag with a separated argument. -hardcode_libdir_separator=$lt_hardcode_libdir_separator - -# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the -# resulting binary. -hardcode_direct=$hardcode_direct - -# Set to yes if using the -LDIR flag during linking hardcodes DIR into the -# resulting binary. -hardcode_minus_L=$hardcode_minus_L - -# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into -# the resulting binary. -hardcode_shlibpath_var=$hardcode_shlibpath_var - -# Set to yes if building a shared library automatically hardcodes DIR into the library -# and all subsequent libraries and executables linked against it. -hardcode_automatic=$hardcode_automatic - -# Variables whose values should be saved in libtool wrapper scripts and -# restored at relink time. -variables_saved_for_relink="$variables_saved_for_relink" - -# Whether libtool must link a program against all its dependency libraries. -link_all_deplibs=$link_all_deplibs - -# Compile-time system search path for libraries -sys_lib_search_path_spec=$lt_sys_lib_search_path_spec - -# Run-time system search path for libraries -sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec - -# Fix the shell variable \$srcfile for the compiler. -fix_srcfile_path="$fix_srcfile_path" - -# Set to yes if exported symbols are required. -always_export_symbols=$always_export_symbols - -# The commands to list exported symbols. -export_symbols_cmds=$lt_export_symbols_cmds - -# The commands to extract the exported symbol list from a shared archive. -extract_expsyms_cmds=$lt_extract_expsyms_cmds - -# Symbols that should not be listed in the preloaded symbols. -exclude_expsyms=$lt_exclude_expsyms - -# Symbols that must always be exported. -include_expsyms=$lt_include_expsyms - -# ### END LIBTOOL CONFIG - -__EOF__ - - - case $host_os in - aix3*) - cat <<\EOF >> "$cfgfile" - -# AIX sometimes has problems with the GCC collect2 program. For some -# reason, if we set the COLLECT_NAMES environment variable, the problems -# vanish in a puff of smoke. -if test "X${COLLECT_NAMES+set}" != Xset; then - COLLECT_NAMES= - export COLLECT_NAMES -fi -EOF - ;; - esac - - # We use sed instead of cat because bash on DJGPP gets confused if - # if finds mixed CR/LF and LF-only lines. Since sed operates in - # text mode, it properly converts lines to CR/LF. This bash problem - # is reportedly fixed, but why not run on old versions too? - sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1) - - mv -f "$cfgfile" "$ofile" || \ - (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") - chmod +x "$ofile" - -else - # If there is no Makefile yet, we rely on a make rule to execute - # `config.status --recheck' to rerun these tests and create the - # libtool script then. - ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` - if test -f "$ltmain_in"; then - test -f Makefile && make "$ltmain" - fi -fi - - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -CC="$lt_save_CC" - - -# Check whether --with-tags or --without-tags was given. -if test "${with_tags+set}" = set; then - withval="$with_tags" - tagnames="$withval" -fi; - -if test -f "$ltmain" && test -n "$tagnames"; then - if test ! -f "${ofile}"; then - { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not exist" >&5 -echo "$as_me: WARNING: output file \`$ofile' does not exist" >&2;} - fi - - if test -z "$LTCC"; then - eval "`$SHELL ${ofile} --config | grep '^LTCC='`" - if test -z "$LTCC"; then - { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not look like a libtool script" >&5 -echo "$as_me: WARNING: output file \`$ofile' does not look like a libtool script" >&2;} - else - { echo "$as_me:$LINENO: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&5 -echo "$as_me: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&2;} - fi - fi - if test -z "$LTCFLAGS"; then - eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`" - fi - - # Extract list of available tagged configurations in $ofile. - # Note that this assumes the entire list is on one line. - available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` - - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for tagname in $tagnames; do - IFS="$lt_save_ifs" - # Check whether tagname contains only valid characters - case `$echo "X$tagname" | $Xsed -e 's:[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]::g'` in - "") ;; - *) { { echo "$as_me:$LINENO: error: invalid tag name: $tagname" >&5 -echo "$as_me: error: invalid tag name: $tagname" >&2;} - { (exit 1); exit 1; }; } - ;; - esac - - if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null - then - { { echo "$as_me:$LINENO: error: tag name \"$tagname\" already exists" >&5 -echo "$as_me: error: tag name \"$tagname\" already exists" >&2;} - { (exit 1); exit 1; }; } - fi - - # Update the list of available tags. - if test -n "$tagname"; then - echo appending configuration tag \"$tagname\" to $ofile - - case $tagname in - CXX) - if test -n "$CXX" && ( test "X$CXX" != "Xno" && - ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || - (test "X$CXX" != "Xg++"))) ; then - ac_ext=cc -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - - - - -archive_cmds_need_lc_CXX=no -allow_undefined_flag_CXX= -always_export_symbols_CXX=no -archive_expsym_cmds_CXX= -export_dynamic_flag_spec_CXX= -hardcode_direct_CXX=no -hardcode_libdir_flag_spec_CXX= -hardcode_libdir_flag_spec_ld_CXX= -hardcode_libdir_separator_CXX= -hardcode_minus_L_CXX=no -hardcode_shlibpath_var_CXX=unsupported -hardcode_automatic_CXX=no -module_cmds_CXX= -module_expsym_cmds_CXX= -link_all_deplibs_CXX=unknown -old_archive_cmds_CXX=$old_archive_cmds -no_undefined_flag_CXX= -whole_archive_flag_spec_CXX= -enable_shared_with_static_runtimes_CXX=no - -# Dependencies to place before and after the object being linked: -predep_objects_CXX= -postdep_objects_CXX= -predeps_CXX= -postdeps_CXX= -compiler_lib_search_path_CXX= - -# Source file extension for C++ test sources. -ac_ext=cpp - -# Object file extension for compiled C++ test sources. -objext=o -objext_CXX=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code="int some_variable = 0;\n" - -# Code to be used in simple link tests -lt_simple_link_test_code='int main(int, char *[]) { return(0); }\n' - -# ltmain only uses $CC for tagged configurations so make sure $CC is set. - -# If no C compiler was specified, use CC. -LTCC=${LTCC-"$CC"} - -# If no C compiler flags were specified, use CFLAGS. -LTCFLAGS=${LTCFLAGS-"$CFLAGS"} - -# Allow CC to be a program name with arguments. -compiler=$CC - - -# save warnings/boilerplate of simple test code -ac_outfile=conftest.$ac_objext -printf "$lt_simple_compile_test_code" >conftest.$ac_ext -eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_compiler_boilerplate=`cat conftest.err` -$rm conftest* - -ac_outfile=conftest.$ac_objext -printf "$lt_simple_link_test_code" >conftest.$ac_ext -eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_linker_boilerplate=`cat conftest.err` -$rm conftest* - - -# Allow CC to be a program name with arguments. -lt_save_CC=$CC -lt_save_LD=$LD -lt_save_GCC=$GCC -GCC=$GXX -lt_save_with_gnu_ld=$with_gnu_ld -lt_save_path_LD=$lt_cv_path_LD -if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then - lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx -else - $as_unset lt_cv_prog_gnu_ld -fi -if test -n "${lt_cv_path_LDCXX+set}"; then - lt_cv_path_LD=$lt_cv_path_LDCXX -else - $as_unset lt_cv_path_LD -fi -test -z "${LDCXX+set}" || LD=$LDCXX -CC=${CXX-"c++"} -compiler=$CC -compiler_CXX=$CC -for cc_temp in $compiler""; do - case $cc_temp in - compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; - distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; - \-*) ;; - *) break;; - esac -done -cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` - - -# We don't want -fno-exception wen compiling C++ code, so set the -# no_builtin_flag separately -if test "$GXX" = yes; then - lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' -else - lt_prog_compiler_no_builtin_flag_CXX= -fi - -if test "$GXX" = yes; then - # Set up default GNU C++ configuration - - -# Check whether --with-gnu-ld or --without-gnu-ld was given. -if test "${with_gnu_ld+set}" = set; then - withval="$with_gnu_ld" - test "$withval" = no || with_gnu_ld=yes -else - with_gnu_ld=no -fi; -ac_prog=ld -if test "$GCC" = yes; then - # Check if gcc -print-prog-name=ld gives a path. - echo "$as_me:$LINENO: checking for ld used by $CC" >&5 -echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6 - case $host in - *-*-mingw*) - # gcc leaves a trailing carriage return which upsets mingw - ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; - *) - ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; - esac - case $ac_prog in - # Accept absolute paths. - [\\/]* | ?:[\\/]*) - re_direlt='/[^/][^/]*/\.\./' - # Canonicalize the pathname of ld - ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` - while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do - ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` - done - test -z "$LD" && LD="$ac_prog" - ;; - "") - # If it fails, then pretend we aren't using GCC. - ac_prog=ld - ;; - *) - # If it is relative, then search for the first ld in PATH. - with_gnu_ld=unknown - ;; - esac -elif test "$with_gnu_ld" = yes; then - echo "$as_me:$LINENO: checking for GNU ld" >&5 -echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6 -else - echo "$as_me:$LINENO: checking for non-GNU ld" >&5 -echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6 -fi -if test "${lt_cv_path_LD+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -z "$LD"; then - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for ac_dir in $PATH; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - lt_cv_path_LD="$ac_dir/$ac_prog" - # Check to see if the program is GNU ld. I'd rather use --version, - # but apparently some variants of GNU ld only accept -v. - # Break only if it was the GNU/non-GNU ld that we prefer. - case `"$lt_cv_path_LD" -v 2>&1 &5 -echo "${ECHO_T}$LD" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi -test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5 -echo "$as_me: error: no acceptable ld found in \$PATH" >&2;} - { (exit 1); exit 1; }; } -echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5 -echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6 -if test "${lt_cv_prog_gnu_ld+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - # I'd rather use --version here, but apparently some GNU lds only accept -v. -case `$LD -v 2>&1 &5 -echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6 -with_gnu_ld=$lt_cv_prog_gnu_ld - - - - # Check if GNU C++ uses GNU ld as the underlying linker, since the - # archiving commands below assume that GNU ld is being used. - if test "$with_gnu_ld" = yes; then - archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - - hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' - export_dynamic_flag_spec_CXX='${wl}--export-dynamic' - - # If archive_cmds runs LD, not CC, wlarc should be empty - # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to - # investigate it a little bit more. (MM) - wlarc='${wl}' - - # ancient GNU ld didn't support --whole-archive et. al. - if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ - grep 'no-whole-archive' > /dev/null; then - whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - else - whole_archive_flag_spec_CXX= - fi - else - with_gnu_ld=no - wlarc= - - # A generic and very simple default shared library creation - # command for GNU C++ for the case where it uses the native - # linker, instead of GNU ld. If possible, this setting should - # overridden to take advantage of the native linker features on - # the platform it is being used on. - archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' - fi - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' - -else - GXX=no - with_gnu_ld=no - wlarc= -fi - -# PORTME: fill in a description of your system's C++ link characteristics -echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 -echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6 -ld_shlibs_CXX=yes -case $host_os in - aix3*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - aix4* | aix5*) - if test "$host_cpu" = ia64; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag="" - else - aix_use_runtimelinking=no - - # Test if we are trying to use run time linking or normal - # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. - case $host_os in aix4.[23]|aix4.[23].*|aix5*) - for ld_flag in $LDFLAGS; do - case $ld_flag in - *-brtl*) - aix_use_runtimelinking=yes - break - ;; - esac - done - ;; - esac - - exp_sym_flag='-bexport' - no_entry_flag='-bnoentry' - fi - - # When large executables or shared objects are built, AIX ld can - # have problems creating the table of contents. If linking a library - # or program results in "error TOC overflow" add -mminimal-toc to - # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not - # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. - - archive_cmds_CXX='' - hardcode_direct_CXX=yes - hardcode_libdir_separator_CXX=':' - link_all_deplibs_CXX=yes - - if test "$GXX" = yes; then - case $host_os in aix4.[012]|aix4.[012].*) - # We only want to do this on AIX 4.2 and lower, the check - # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` - if test -f "$collect2name" && \ - strings "$collect2name" | grep resolve_lib_name >/dev/null - then - # We have reworked collect2 - hardcode_direct_CXX=yes - else - # We have old collect2 - hardcode_direct_CXX=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - hardcode_minus_L_CXX=yes - hardcode_libdir_flag_spec_CXX='-L$libdir' - hardcode_libdir_separator_CXX= - fi - ;; - esac - shared_flag='-shared' - if test "$aix_use_runtimelinking" = yes; then - shared_flag="$shared_flag "'${wl}-G' - fi - else - # not using gcc - if test "$host_cpu" = ia64; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' - else - shared_flag='${wl}-bM:SRE' - fi - fi - fi - - # It seems that -bexpall does not export symbols beginning with - # underscore (_), so it is better to generate a list of symbols to export. - always_export_symbols_CXX=yes - if test "$aix_use_runtimelinking" = yes; then - # Warning - without using the other runtime loading flags (-brtl), - # -berok will link without error, but may produce a broken library. - allow_undefined_flag_CXX='-berok' - # Determine the default libpath from the value encoded in an empty executable. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'`; fi -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi - - hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" - - archive_expsym_cmds_CXX="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" - else - if test "$host_cpu" = ia64; then - hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib' - allow_undefined_flag_CXX="-z nodefs" - archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" - else - # Determine the default libpath from the value encoded in an empty executable. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'`; fi -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi - - hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" - # Warning - without using the other run time loading flags, - # -berok will link without error, but may produce a broken library. - no_undefined_flag_CXX=' ${wl}-bernotok' - allow_undefined_flag_CXX=' ${wl}-berok' - # Exported symbols can be pulled into shared objects from archives - whole_archive_flag_spec_CXX='$convenience' - archive_cmds_need_lc_CXX=yes - # This is similar to how AIX traditionally builds its shared libraries. - archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' - fi - fi - ;; - - beos*) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - allow_undefined_flag_CXX=unsupported - # Joseph Beckenbach says some releases of gcc - # support --undefined. This deserves some investigation. FIXME - archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - else - ld_shlibs_CXX=no - fi - ;; - - chorus*) - case $cc_basename in - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - esac - ;; - - cygwin* | mingw* | pw32*) - # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, - # as there is no search path for DLLs. - hardcode_libdir_flag_spec_CXX='-L$libdir' - allow_undefined_flag_CXX=unsupported - always_export_symbols_CXX=no - enable_shared_with_static_runtimes_CXX=yes - - if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then - archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - else - ld_shlibs_CXX=no - fi - ;; - darwin* | rhapsody*) - case $host_os in - rhapsody* | darwin1.[012]) - allow_undefined_flag_CXX='${wl}-undefined ${wl}suppress' - ;; - *) # Darwin 1.3 on - if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then - allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' - else - case ${MACOSX_DEPLOYMENT_TARGET} in - 10.[012]) - allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' - ;; - 10.*) - allow_undefined_flag_CXX='${wl}-undefined ${wl}dynamic_lookup' - ;; - esac - fi - ;; - esac - archive_cmds_need_lc_CXX=no - hardcode_direct_CXX=no - hardcode_automatic_CXX=yes - hardcode_shlibpath_var_CXX=unsupported - whole_archive_flag_spec_CXX='' - link_all_deplibs_CXX=yes - - if test "$GXX" = yes ; then - lt_int_apple_cc_single_mod=no - output_verbose_link_cmd='echo' - if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then - lt_int_apple_cc_single_mod=yes - fi - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - archive_cmds_CXX='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - else - archive_cmds_CXX='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - fi - module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - else - archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - fi - module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - else - case $cc_basename in - xlc*) - output_verbose_link_cmd='echo' - archive_cmds_CXX='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' - module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds - archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - ;; - *) - ld_shlibs_CXX=no - ;; - esac - fi - ;; - - dgux*) - case $cc_basename in - ec++*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - ghcx*) - # Green Hills C++ Compiler - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - esac - ;; - freebsd[12]*) - # C++ shared libraries reported to be fairly broken before switch to ELF - ld_shlibs_CXX=no - ;; - freebsd-elf*) - archive_cmds_need_lc_CXX=no - ;; - freebsd* | kfreebsd*-gnu | dragonfly*) - # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF - # conventions - ld_shlibs_CXX=yes - ;; - gnu*) - ;; - hpux9*) - hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' - hardcode_libdir_separator_CXX=: - export_dynamic_flag_spec_CXX='${wl}-E' - hardcode_direct_CXX=yes - hardcode_minus_L_CXX=yes # Not in the search PATH, - # but as the default - # location of the library. - - case $cc_basename in - CC*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - aCC*) - archive_cmds_CXX='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[-]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - ;; - *) - if test "$GXX" = yes; then - archive_cmds_CXX='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - else - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - fi - ;; - esac - ;; - hpux10*|hpux11*) - if test $with_gnu_ld = no; then - hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' - hardcode_libdir_separator_CXX=: - - case $host_cpu in - hppa*64*|ia64*) - hardcode_libdir_flag_spec_ld_CXX='+b $libdir' - ;; - *) - export_dynamic_flag_spec_CXX='${wl}-E' - ;; - esac - fi - case $host_cpu in - hppa*64*|ia64*) - hardcode_direct_CXX=no - hardcode_shlibpath_var_CXX=no - ;; - *) - hardcode_direct_CXX=yes - hardcode_minus_L_CXX=yes # Not in the search PATH, - # but as the default - # location of the library. - ;; - esac - - case $cc_basename in - CC*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - aCC*) - case $host_cpu in - hppa*64*) - archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - ia64*) - archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - *) - archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - esac - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - ;; - *) - if test "$GXX" = yes; then - if test $with_gnu_ld = no; then - case $host_cpu in - hppa*64*) - archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - ia64*) - archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - *) - archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - esac - fi - else - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - fi - ;; - esac - ;; - interix3*) - hardcode_direct_CXX=no - hardcode_shlibpath_var_CXX=no - hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' - export_dynamic_flag_spec_CXX='${wl}-E' - # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. - # Instead, shared libraries are loaded at an image base (0x10000000 by - # default) and relocated if they conflict, which is a slow very memory - # consuming and fragmenting process. To avoid this, we pick a random, - # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link - # time. Moving up from 0x10000000 also allows more sbrk(2) space. - archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - archive_expsym_cmds_CXX='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - ;; - irix5* | irix6*) - case $cc_basename in - CC*) - # SGI C++ - archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - - # Archives containing C++ object files must be created using - # "CC -ar", where "CC" is the IRIX C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' - ;; - *) - if test "$GXX" = yes; then - if test "$with_gnu_ld" = no; then - archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' - fi - fi - link_all_deplibs_CXX=yes - ;; - esac - hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator_CXX=: - ;; - linux*) - case $cc_basename in - KCC*) - # Kuck and Associates, Inc. (KAI) C++ Compiler - - # KCC will only create a shared library if the output file - # ends with ".so" (or ".sl" for HP-UX), so rename the library - # to its proper name (with version) after linking. - archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - - hardcode_libdir_flag_spec_CXX='${wl}--rpath,$libdir' - export_dynamic_flag_spec_CXX='${wl}--export-dynamic' - - # Archives containing C++ object files must be created using - # "CC -Bstatic", where "CC" is the KAI C++ compiler. - old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' - ;; - icpc*) - # Intel C++ - with_gnu_ld=yes - # version 8.0 and above of icpc choke on multiply defined symbols - # if we add $predep_objects and $postdep_objects, however 7.1 and - # earlier do not add the objects themselves. - case `$CC -V 2>&1` in - *"Version 7."*) - archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - ;; - *) # Version 8.0 or newer - tmp_idyn= - case $host_cpu in - ia64*) tmp_idyn=' -i_dynamic';; - esac - archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - ;; - esac - archive_cmds_need_lc_CXX=no - hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' - export_dynamic_flag_spec_CXX='${wl}--export-dynamic' - whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' - ;; - pgCC*) - # Portland Group C++ compiler - archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' - archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' - - hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' - export_dynamic_flag_spec_CXX='${wl}--export-dynamic' - whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' - ;; - cxx*) - # Compaq C++ - archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' - - runpath_var=LD_RUN_PATH - hardcode_libdir_flag_spec_CXX='-rpath $libdir' - hardcode_libdir_separator_CXX=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - ;; - esac - ;; - lynxos*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - m88k*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - mvs*) - case $cc_basename in - cxx*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - esac - ;; - netbsd*) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' - wlarc= - hardcode_libdir_flag_spec_CXX='-R$libdir' - hardcode_direct_CXX=yes - hardcode_shlibpath_var_CXX=no - fi - # Workaround some broken pre-1.5 toolchains - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' - ;; - openbsd2*) - # C++ shared libraries are fairly broken - ld_shlibs_CXX=no - ;; - openbsd*) - hardcode_direct_CXX=yes - hardcode_shlibpath_var_CXX=no - archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' - hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' - export_dynamic_flag_spec_CXX='${wl}-E' - whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - fi - output_verbose_link_cmd='echo' - ;; - osf3*) - case $cc_basename in - KCC*) - # Kuck and Associates, Inc. (KAI) C++ Compiler - - # KCC will only create a shared library if the output file - # ends with ".so" (or ".sl" for HP-UX), so rename the library - # to its proper name (with version) after linking. - archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - - hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' - hardcode_libdir_separator_CXX=: - - # Archives containing C++ object files must be created using - # "CC -Bstatic", where "CC" is the KAI C++ compiler. - old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' - - ;; - RCC*) - # Rational C++ 2.4.1 - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - cxx*) - allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - - hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator_CXX=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - ;; - *) - if test "$GXX" = yes && test "$with_gnu_ld" = no; then - allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - - hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator_CXX=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' - - else - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - fi - ;; - esac - ;; - osf4* | osf5*) - case $cc_basename in - KCC*) - # Kuck and Associates, Inc. (KAI) C++ Compiler - - # KCC will only create a shared library if the output file - # ends with ".so" (or ".sl" for HP-UX), so rename the library - # to its proper name (with version) after linking. - archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - - hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' - hardcode_libdir_separator_CXX=: - - # Archives containing C++ object files must be created using - # the KAI C++ compiler. - old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' - ;; - RCC*) - # Rational C++ 2.4.1 - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - cxx*) - allow_undefined_flag_CXX=' -expect_unresolved \*' - archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ - echo "-hidden">> $lib.exp~ - $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~ - $rm $lib.exp' - - hardcode_libdir_flag_spec_CXX='-rpath $libdir' - hardcode_libdir_separator_CXX=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' - ;; - *) - if test "$GXX" = yes && test "$with_gnu_ld" = no; then - allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - - hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator_CXX=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' - - else - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - fi - ;; - esac - ;; - psos*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - sunos4*) - case $cc_basename in - CC*) - # Sun C++ 4.x - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - lcc*) - # Lucid - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - esac - ;; - solaris*) - case $cc_basename in - CC*) - # Sun C++ 4.2, 5.x and Centerline C++ - archive_cmds_need_lc_CXX=yes - no_undefined_flag_CXX=' -zdefs' - archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' - - hardcode_libdir_flag_spec_CXX='-R$libdir' - hardcode_shlibpath_var_CXX=no - case $host_os in - solaris2.[0-5] | solaris2.[0-5].*) ;; - *) - # The C++ compiler is used as linker so we must use $wl - # flag to pass the commands to the underlying system - # linker. We must also pass each convience library through - # to the system linker between allextract/defaultextract. - # The C++ compiler will combine linker options so we - # cannot just pass the convience library names through - # without $wl. - # Supported since Solaris 2.6 (maybe 2.5.1?) - whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' - ;; - esac - link_all_deplibs_CXX=yes - - output_verbose_link_cmd='echo' - - # Archives containing C++ object files must be created using - # "CC -xar", where "CC" is the Sun C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' - ;; - gcx*) - # Green Hills C++ Compiler - archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' - - # The C++ compiler must be used to create the archive. - old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' - ;; - *) - # GNU C++ compiler with Solaris linker - if test "$GXX" = yes && test "$with_gnu_ld" = no; then - no_undefined_flag_CXX=' ${wl}-z ${wl}defs' - if $CC --version | grep -v '^2\.7' > /dev/null; then - archive_cmds_CXX='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' - archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" - else - # g++ 2.7 appears to require `-G' NOT `-shared' on this - # platform. - archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' - archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" - fi - - hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir' - fi - ;; - esac - ;; - sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) - no_undefined_flag_CXX='${wl}-z,text' - archive_cmds_need_lc_CXX=no - hardcode_shlibpath_var_CXX=no - runpath_var='LD_RUN_PATH' - - case $cc_basename in - CC*) - archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - ;; - sysv5* | sco3.2v5* | sco5v6*) - # Note: We can NOT use -z defs as we might desire, because we do not - # link with -lc, and that would cause any symbols used from libc to - # always be unresolved, which means just about no library would - # ever link correctly. If we're not using GNU ld we use -z text - # though, which does catch some bad symbols but isn't as heavy-handed - # as -z defs. - # For security reasons, it is highly recommended that you always - # use absolute paths for naming shared libraries, and exclude the - # DT_RUNPATH tag from executables and libraries. But doing so - # requires that you compile everything twice, which is a pain. - # So that behaviour is only enabled if SCOABSPATH is set to a - # non-empty value in the environment. Most likely only useful for - # creating official distributions of packages. - # This is a hack until libtool officially supports absolute path - # names for shared libraries. - no_undefined_flag_CXX='${wl}-z,text' - allow_undefined_flag_CXX='${wl}-z,nodefs' - archive_cmds_need_lc_CXX=no - hardcode_shlibpath_var_CXX=no - hardcode_libdir_flag_spec_CXX='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' - hardcode_libdir_separator_CXX=':' - link_all_deplibs_CXX=yes - export_dynamic_flag_spec_CXX='${wl}-Bexport' - runpath_var='LD_RUN_PATH' - - case $cc_basename in - CC*) - archive_cmds_CXX='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - archive_cmds_CXX='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - ;; - tandem*) - case $cc_basename in - NCC*) - # NonStop-UX NCC 3.20 - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - esac - ;; - vxworks*) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; -esac -echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5 -echo "${ECHO_T}$ld_shlibs_CXX" >&6 -test "$ld_shlibs_CXX" = no && can_build_shared=no - -GCC_CXX="$GXX" -LD_CXX="$LD" - -## CAVEAT EMPTOR: -## There is no encapsulation within the following macros, do not change -## the running order or otherwise move them around unless you know exactly -## what you are doing... - -cat > conftest.$ac_ext <&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - # Parse the compiler output and extract the necessary - # objects, libraries and library flags. - - # Sentinel used to keep track of whether or not we are before - # the conftest object file. - pre_test_object_deps_done=no - - # The `*' in the case matches for architectures that use `case' in - # $output_verbose_cmd can trigger glob expansion during the loop - # eval without this substitution. - output_verbose_link_cmd=`$echo "X$output_verbose_link_cmd" | $Xsed -e "$no_glob_subst"` - - for p in `eval $output_verbose_link_cmd`; do - case $p in - - -L* | -R* | -l*) - # Some compilers place space between "-{L,R}" and the path. - # Remove the space. - if test $p = "-L" \ - || test $p = "-R"; then - prev=$p - continue - else - prev= - fi - - if test "$pre_test_object_deps_done" = no; then - case $p in - -L* | -R*) - # Internal compiler library paths should come after those - # provided the user. The postdeps already come after the - # user supplied libs so there is no need to process them. - if test -z "$compiler_lib_search_path_CXX"; then - compiler_lib_search_path_CXX="${prev}${p}" - else - compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}" - fi - ;; - # The "-l" case would never come before the object being - # linked, so don't bother handling this case. - esac - else - if test -z "$postdeps_CXX"; then - postdeps_CXX="${prev}${p}" - else - postdeps_CXX="${postdeps_CXX} ${prev}${p}" - fi - fi - ;; - - *.$objext) - # This assumes that the test object file only shows up - # once in the compiler output. - if test "$p" = "conftest.$objext"; then - pre_test_object_deps_done=yes - continue - fi - - if test "$pre_test_object_deps_done" = no; then - if test -z "$predep_objects_CXX"; then - predep_objects_CXX="$p" - else - predep_objects_CXX="$predep_objects_CXX $p" - fi - else - if test -z "$postdep_objects_CXX"; then - postdep_objects_CXX="$p" - else - postdep_objects_CXX="$postdep_objects_CXX $p" - fi - fi - ;; - - *) ;; # Ignore the rest. - - esac - done - - # Clean up. - rm -f a.out a.exe -else - echo "libtool.m4: error: problem compiling CXX test program" -fi - -$rm -f confest.$objext - -# PORTME: override above test on systems where it is broken -case $host_os in -interix3*) - # Interix 3.5 installs completely hosed .la files for C++, so rather than - # hack all around it, let's just trust "g++" to DTRT. - predep_objects_CXX= - postdep_objects_CXX= - postdeps_CXX= - ;; - -solaris*) - case $cc_basename in - CC*) - # Adding this requires a known-good setup of shared libraries for - # Sun compiler versions before 5.6, else PIC objects from an old - # archive will be linked into the output, leading to subtle bugs. - postdeps_CXX='-lCstd -lCrun' - ;; - esac - ;; -esac - - -case " $postdeps_CXX " in -*" -lc "*) archive_cmds_need_lc_CXX=no ;; -esac - -lt_prog_compiler_wl_CXX= -lt_prog_compiler_pic_CXX= -lt_prog_compiler_static_CXX= - -echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 -echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 - - # C++ specific cases for pic, static, wl, etc. - if test "$GXX" = yes; then - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_static_CXX='-static' - - case $host_os in - aix*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static_CXX='-Bstatic' - fi - ;; - amigaos*) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. - lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' - ;; - beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - mingw* | os2* | pw32*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - lt_prog_compiler_pic_CXX='-DDLL_EXPORT' - ;; - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - lt_prog_compiler_pic_CXX='-fno-common' - ;; - *djgpp*) - # DJGPP does not support shared libraries at all - lt_prog_compiler_pic_CXX= - ;; - interix3*) - # Interix 3.x gcc -fpic/-fPIC options generate broken code. - # Instead, we relocate shared libraries at runtime. - ;; - sysv4*MP*) - if test -d /usr/nec; then - lt_prog_compiler_pic_CXX=-Kconform_pic - fi - ;; - hpux*) - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case $host_cpu in - hppa*64*|ia64*) - ;; - *) - lt_prog_compiler_pic_CXX='-fPIC' - ;; - esac - ;; - *) - lt_prog_compiler_pic_CXX='-fPIC' - ;; - esac - else - case $host_os in - aix4* | aix5*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static_CXX='-Bstatic' - else - lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' - fi - ;; - chorus*) - case $cc_basename in - cxch68*) - # Green Hills C++ Compiler - # _LT_AC_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" - ;; - esac - ;; - darwin*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - case $cc_basename in - xlc*) - lt_prog_compiler_pic_CXX='-qnocommon' - lt_prog_compiler_wl_CXX='-Wl,' - ;; - esac - ;; - dgux*) - case $cc_basename in - ec++*) - lt_prog_compiler_pic_CXX='-KPIC' - ;; - ghcx*) - # Green Hills C++ Compiler - lt_prog_compiler_pic_CXX='-pic' - ;; - *) - ;; - esac - ;; - freebsd* | kfreebsd*-gnu | dragonfly*) - # FreeBSD uses GNU C++ - ;; - hpux9* | hpux10* | hpux11*) - case $cc_basename in - CC*) - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' - if test "$host_cpu" != ia64; then - lt_prog_compiler_pic_CXX='+Z' - fi - ;; - aCC*) - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' - case $host_cpu in - hppa*64*|ia64*) - # +Z the default - ;; - *) - lt_prog_compiler_pic_CXX='+Z' - ;; - esac - ;; - *) - ;; - esac - ;; - interix*) - # This is c89, which is MS Visual C++ (no shared libs) - # Anyone wants to do a port? - ;; - irix5* | irix6* | nonstopux*) - case $cc_basename in - CC*) - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_static_CXX='-non_shared' - # CC pic flag -KPIC is the default. - ;; - *) - ;; - esac - ;; - linux*) - case $cc_basename in - KCC*) - # KAI C++ Compiler - lt_prog_compiler_wl_CXX='--backend -Wl,' - lt_prog_compiler_pic_CXX='-fPIC' - ;; - icpc* | ecpc*) - # Intel C++ - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_pic_CXX='-KPIC' - lt_prog_compiler_static_CXX='-static' - ;; - pgCC*) - # Portland Group C++ compiler. - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_pic_CXX='-fpic' - lt_prog_compiler_static_CXX='-Bstatic' - ;; - cxx*) - # Compaq C++ - # Make sure the PIC flag is empty. It appears that all Alpha - # Linux and Compaq Tru64 Unix objects are PIC. - lt_prog_compiler_pic_CXX= - lt_prog_compiler_static_CXX='-non_shared' - ;; - *) - ;; - esac - ;; - lynxos*) - ;; - m88k*) - ;; - mvs*) - case $cc_basename in - cxx*) - lt_prog_compiler_pic_CXX='-W c,exportall' - ;; - *) - ;; - esac - ;; - netbsd*) - ;; - osf3* | osf4* | osf5*) - case $cc_basename in - KCC*) - lt_prog_compiler_wl_CXX='--backend -Wl,' - ;; - RCC*) - # Rational C++ 2.4.1 - lt_prog_compiler_pic_CXX='-pic' - ;; - cxx*) - # Digital/Compaq C++ - lt_prog_compiler_wl_CXX='-Wl,' - # Make sure the PIC flag is empty. It appears that all Alpha - # Linux and Compaq Tru64 Unix objects are PIC. - lt_prog_compiler_pic_CXX= - lt_prog_compiler_static_CXX='-non_shared' - ;; - *) - ;; - esac - ;; - psos*) - ;; - solaris*) - case $cc_basename in - CC*) - # Sun C++ 4.2, 5.x and Centerline C++ - lt_prog_compiler_pic_CXX='-KPIC' - lt_prog_compiler_static_CXX='-Bstatic' - lt_prog_compiler_wl_CXX='-Qoption ld ' - ;; - gcx*) - # Green Hills C++ Compiler - lt_prog_compiler_pic_CXX='-PIC' - ;; - *) - ;; - esac - ;; - sunos4*) - case $cc_basename in - CC*) - # Sun C++ 4.x - lt_prog_compiler_pic_CXX='-pic' - lt_prog_compiler_static_CXX='-Bstatic' - ;; - lcc*) - # Lucid - lt_prog_compiler_pic_CXX='-pic' - ;; - *) - ;; - esac - ;; - tandem*) - case $cc_basename in - NCC*) - # NonStop-UX NCC 3.20 - lt_prog_compiler_pic_CXX='-KPIC' - ;; - *) - ;; - esac - ;; - sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) - case $cc_basename in - CC*) - lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_pic_CXX='-KPIC' - lt_prog_compiler_static_CXX='-Bstatic' - ;; - esac - ;; - vxworks*) - ;; - *) - lt_prog_compiler_can_build_shared_CXX=no - ;; - esac - fi - -echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_CXX" >&5 -echo "${ECHO_T}$lt_prog_compiler_pic_CXX" >&6 - -# -# Check to make sure the PIC flag actually works. -# -if test -n "$lt_prog_compiler_pic_CXX"; then - -echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 -echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... $ECHO_C" >&6 -if test "${lt_prog_compiler_pic_works_CXX+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_prog_compiler_pic_works_CXX=no - ac_outfile=conftest.$ac_objext - printf "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - # The option is referenced via a variable to avoid confusing sed. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:11524: $lt_compile\"" >&5) - (eval "$lt_compile" 2>conftest.err) - ac_status=$? - cat conftest.err >&5 - echo "$as_me:11528: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s "$ac_outfile"; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings other than the usual output. - $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then - lt_prog_compiler_pic_works_CXX=yes - fi - fi - $rm conftest* - -fi -echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_CXX" >&5 -echo "${ECHO_T}$lt_prog_compiler_pic_works_CXX" >&6 - -if test x"$lt_prog_compiler_pic_works_CXX" = xyes; then - case $lt_prog_compiler_pic_CXX in - "" | " "*) ;; - *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; - esac -else - lt_prog_compiler_pic_CXX= - lt_prog_compiler_can_build_shared_CXX=no -fi - -fi -case $host_os in - # For platforms which do not support PIC, -DPIC is meaningless: - *djgpp*) - lt_prog_compiler_pic_CXX= - ;; - *) - lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" - ;; -esac - -# -# Check to make sure the static flag actually works. -# -wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\" -echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 -echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6 -if test "${lt_prog_compiler_static_works_CXX+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_prog_compiler_static_works_CXX=no - save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS $lt_tmp_static_flag" - printf "$lt_simple_link_test_code" > conftest.$ac_ext - if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then - # The linker can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s conftest.err; then - # Append any errors to the config.log. - cat conftest.err 1>&5 - $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if diff conftest.exp conftest.er2 >/dev/null; then - lt_prog_compiler_static_works_CXX=yes - fi - else - lt_prog_compiler_static_works_CXX=yes - fi - fi - $rm conftest* - LDFLAGS="$save_LDFLAGS" - -fi -echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_CXX" >&5 -echo "${ECHO_T}$lt_prog_compiler_static_works_CXX" >&6 - -if test x"$lt_prog_compiler_static_works_CXX" = xyes; then - : -else - lt_prog_compiler_static_CXX= -fi - - -echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 -echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6 -if test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_cv_prog_compiler_c_o_CXX=no - $rm -r conftest 2>/dev/null - mkdir conftest - cd conftest - mkdir out - printf "$lt_simple_compile_test_code" > conftest.$ac_ext - - lt_compiler_flag="-o out/conftest2.$ac_objext" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:11628: $lt_compile\"" >&5) - (eval "$lt_compile" 2>out/conftest.err) - ac_status=$? - cat out/conftest.err >&5 - echo "$as_me:11632: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s out/conftest2.$ac_objext - then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp - $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 - if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then - lt_cv_prog_compiler_c_o_CXX=yes - fi - fi - chmod u+w . 2>&5 - $rm conftest* - # SGI C++ compiler will create directory out/ii_files/ for - # template instantiation - test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files - $rm out/* && rmdir out - cd .. - rmdir conftest - $rm conftest* - -fi -echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_CXX" >&5 -echo "${ECHO_T}$lt_cv_prog_compiler_c_o_CXX" >&6 - - -hard_links="nottested" -if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then - # do not overwrite the value of need_locks provided by the user - echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 -echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6 - hard_links=yes - $rm conftest* - ln conftest.a conftest.b 2>/dev/null && hard_links=no - touch conftest.a - ln conftest.a conftest.b 2>&5 || hard_links=no - ln conftest.a conftest.b 2>/dev/null && hard_links=no - echo "$as_me:$LINENO: result: $hard_links" >&5 -echo "${ECHO_T}$hard_links" >&6 - if test "$hard_links" = no; then - { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 -echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} - need_locks=warn - fi -else - need_locks=no -fi - -echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 -echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6 - - export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - case $host_os in - aix4* | aix5*) - # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - if $NM -V 2>&1 | grep 'GNU' > /dev/null; then - export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' - else - export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' - fi - ;; - pw32*) - export_symbols_cmds_CXX="$ltdll_cmds" - ;; - cygwin* | mingw*) - export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/;/^.* __nm__/s/^.* __nm__\([^ ]*\) [^ ]*/\1 DATA/;/^I /d;/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' - ;; - *) - export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - ;; - esac - -echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5 -echo "${ECHO_T}$ld_shlibs_CXX" >&6 -test "$ld_shlibs_CXX" = no && can_build_shared=no - -# -# Do we need to explicitly link libc? -# -case "x$archive_cmds_need_lc_CXX" in -x|xyes) - # Assume -lc should be added - archive_cmds_need_lc_CXX=yes - - if test "$enable_shared" = yes && test "$GCC" = yes; then - case $archive_cmds_CXX in - *'~'*) - # FIXME: we may have to deal with multi-command sequences. - ;; - '$CC '*) - # Test whether the compiler implicitly links with -lc since on some - # systems, -lgcc has to come before -lc. If gcc already passes -lc - # to ld, don't add -lc before -lgcc. - echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 -echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6 - $rm conftest* - printf "$lt_simple_compile_test_code" > conftest.$ac_ext - - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } 2>conftest.err; then - soname=conftest - lib=conftest - libobjs=conftest.$ac_objext - deplibs= - wl=$lt_prog_compiler_wl_CXX - pic_flag=$lt_prog_compiler_pic_CXX - compiler_flags=-v - linker_flags=-v - verstring= - output_objdir=. - libname=conftest - lt_save_allow_undefined_flag=$allow_undefined_flag_CXX - allow_undefined_flag_CXX= - if { (eval echo "$as_me:$LINENO: \"$archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 - (eval $archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } - then - archive_cmds_need_lc_CXX=no - else - archive_cmds_need_lc_CXX=yes - fi - allow_undefined_flag_CXX=$lt_save_allow_undefined_flag - else - cat conftest.err 1>&5 - fi - $rm conftest* - echo "$as_me:$LINENO: result: $archive_cmds_need_lc_CXX" >&5 -echo "${ECHO_T}$archive_cmds_need_lc_CXX" >&6 - ;; - esac - fi - ;; -esac - -echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 -echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6 -library_names_spec= -libname_spec='lib$name' -soname_spec= -shrext_cmds=".so" -postinstall_cmds= -postuninstall_cmds= -finish_cmds= -finish_eval= -shlibpath_var= -shlibpath_overrides_runpath=unknown -version_type=none -dynamic_linker="$host_os ld.so" -sys_lib_dlsearch_path_spec="/lib /usr/lib" -if test "$GCC" = yes; then - sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then - # if the path contains ";" then we assume it to be the separator - # otherwise default to the standard path separator (i.e. ":") - it is - # assumed that no part of a normal pathname contains ";" but that should - # okay in the real world where ";" in dirpaths is itself problematic. - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi -else - sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" -fi -need_lib_prefix=unknown -hardcode_into_libs=no - -# when you set need_version to no, make sure it does not cause -set_version -# flags to be left without arguments -need_version=unknown - -case $host_os in -aix3*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' - shlibpath_var=LIBPATH - - # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='${libname}${release}${shared_ext}$major' - ;; - -aix4* | aix5*) - version_type=linux - need_lib_prefix=no - need_version=no - hardcode_into_libs=yes - if test "$host_cpu" = ia64; then - # AIX 5 supports IA64 - library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - else - # With GCC up to 2.95.x, collect2 would create an import file - # for dependence libraries. The import file would start with - # the line `#! .'. This would cause the generated library to - # depend on `.', always an invalid library. This was fixed in - # development snapshots of GCC prior to 3.0. - case $host_os in - aix4 | aix4.[01] | aix4.[01].*) - if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' - echo ' yes ' - echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then - : - else - can_build_shared=no - fi - ;; - esac - # AIX (on Power*) has no versioning support, so currently we can not hardcode correct - # soname into executable. Probably we can add versioning support to - # collect2, so additional links can be useful in future. - if test "$aix_use_runtimelinking" = yes; then - # If using run time linking (on AIX 4.2 or later) use lib.so - # instead of lib.a to let people know that these are not - # typical AIX shared libraries. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - else - # We preserve .a as extension for shared libraries through AIX4.2 - # and later when we are not doing run time linking. - library_names_spec='${libname}${release}.a $libname.a' - soname_spec='${libname}${release}${shared_ext}$major' - fi - shlibpath_var=LIBPATH - fi - ;; - -amigaos*) - library_names_spec='$libname.ixlibrary $libname.a' - # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' - ;; - -beos*) - library_names_spec='${libname}${shared_ext}' - dynamic_linker="$host_os ld.so" - shlibpath_var=LIBRARY_PATH - ;; - -bsdi[45]*) - version_type=linux - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" - sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" - # the default ld.so.conf also contains /usr/contrib/lib and - # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow - # libtool to hard-code these into programs - ;; - -cygwin* | mingw* | pw32*) - version_type=windows - shrext_cmds=".dll" - need_version=no - need_lib_prefix=no - - case $GCC,$host_os in - yes,cygwin* | yes,mingw* | yes,pw32*) - library_names_spec='$libname.dll.a' - # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname~ - chmod a+x \$dldir/$dlname' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $rm \$dlpath' - shlibpath_overrides_runpath=yes - - case $host_os in - cygwin*) - # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" - ;; - mingw*) - # MinGW DLLs use traditional 'lib' prefix - soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then - # It is most probably a Windows format PATH printed by - # mingw gcc, but we are running on Cygwin. Gcc prints its search - # path with ; separators, and with drive letters. We can handle the - # drive letters (cygwin fileutils understands them), so leave them, - # especially as we might pass files found there to a mingw objdump, - # which wouldn't understand a cygwinified path. Ahh. - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi - ;; - pw32*) - # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - ;; - esac - ;; - - *) - library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' - ;; - esac - dynamic_linker='Win32 ld.exe' - # FIXME: first we should search . and the directory the executable is in - shlibpath_var=PATH - ;; - -darwin* | rhapsody*) - dynamic_linker="$host_os dyld" - version_type=darwin - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' - soname_spec='${libname}${release}${major}$shared_ext' - shlibpath_overrides_runpath=yes - shlibpath_var=DYLD_LIBRARY_PATH - shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' - # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. - if test "$GCC" = yes; then - sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` - else - sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' - fi - sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' - ;; - -dgux*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -freebsd1*) - dynamic_linker=no - ;; - -kfreebsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='GNU ld.so' - ;; - -freebsd* | dragonfly*) - # DragonFly does not have aout. When/if they implement a new - # versioning mechanism, adjust this. - if test -x /usr/bin/objformat; then - objformat=`/usr/bin/objformat` - else - case $host_os in - freebsd[123]*) objformat=aout ;; - *) objformat=elf ;; - esac - fi - version_type=freebsd-$objformat - case $version_type in - freebsd-elf*) - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - need_version=no - need_lib_prefix=no - ;; - freebsd-*) - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' - need_version=yes - ;; - esac - shlibpath_var=LD_LIBRARY_PATH - case $host_os in - freebsd2*) - shlibpath_overrides_runpath=yes - ;; - freebsd3.[01]* | freebsdelf3.[01]*) - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ - freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - freebsd*) # from 4.6 on - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - esac - ;; - -gnu*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - hardcode_into_libs=yes - ;; - -hpux9* | hpux10* | hpux11*) - # Give a soname corresponding to the major version so that dld.sl refuses to - # link against other versions. - version_type=sunos - need_lib_prefix=no - need_version=no - case $host_cpu in - ia64*) - shrext_cmds='.so' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.so" - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - if test "X$HPUX_IA64_MODE" = X32; then - sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" - else - sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" - fi - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - hppa*64*) - shrext_cmds='.sl' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.sl" - shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - *) - shrext_cmds='.sl' - dynamic_linker="$host_os dld.sl" - shlibpath_var=SHLIB_PATH - shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - ;; - esac - # HP-UX runs *really* slowly unless shared libraries are mode 555. - postinstall_cmds='chmod 555 $lib' - ;; - -interix3*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - -irix5* | irix6* | nonstopux*) - case $host_os in - nonstopux*) version_type=nonstopux ;; - *) - if test "$lt_cv_prog_gnu_ld" = yes; then - version_type=linux - else - version_type=irix - fi ;; - esac - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' - case $host_os in - irix5* | nonstopux*) - libsuff= shlibsuff= - ;; - *) - case $LD in # libtool.m4 will add one of these switches to LD - *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") - libsuff= shlibsuff= libmagic=32-bit;; - *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") - libsuff=32 shlibsuff=N32 libmagic=N32;; - *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") - libsuff=64 shlibsuff=64 libmagic=64-bit;; - *) libsuff= shlibsuff= libmagic=never-match;; - esac - ;; - esac - shlibpath_var=LD_LIBRARY${shlibsuff}_PATH - shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" - sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" - hardcode_into_libs=yes - ;; - -# No shared lib support for Linux oldld, aout, or coff. -linux*oldld* | linux*aout* | linux*coff*) - dynamic_linker=no - ;; - -# This must be Linux ELF. -linux*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. - hardcode_into_libs=yes - - # Append ld.so.conf contents to the search path - if test -f /etc/ld.so.conf; then - lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` - sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" - fi - - # We used to test for /lib/ld.so.1 and disable shared libraries on - # powerpc, because MkLinux only supported shared libraries with the - # GNU dynamic linker. Since this was broken with cross compilers, - # most powerpc-linux boxes support dynamic linking these days and - # people can always --disable-shared, the test was removed, and we - # assume the GNU/Linux dynamic linker is in use. - dynamic_linker='GNU/Linux ld.so' - ;; - -knetbsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='GNU ld.so' - ;; - -netbsd*) - version_type=sunos - need_lib_prefix=no - need_version=no - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - dynamic_linker='NetBSD (a.out) ld.so' - else - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='NetBSD ld.elf_so' - fi - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - -newsos6) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -nto-qnx*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -openbsd*) - version_type=sunos - sys_lib_dlsearch_path_spec="/usr/lib" - need_lib_prefix=no - # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. - case $host_os in - openbsd3.3 | openbsd3.3.*) need_version=yes ;; - *) need_version=no ;; - esac - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - shlibpath_var=LD_LIBRARY_PATH - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - case $host_os in - openbsd2.[89] | openbsd2.[89].*) - shlibpath_overrides_runpath=no - ;; - *) - shlibpath_overrides_runpath=yes - ;; - esac - else - shlibpath_overrides_runpath=yes - fi - ;; - -os2*) - libname_spec='$name' - shrext_cmds=".dll" - need_lib_prefix=no - library_names_spec='$libname${shared_ext} $libname.a' - dynamic_linker='OS/2 ld.exe' - shlibpath_var=LIBPATH - ;; - -osf3* | osf4* | osf5*) - version_type=osf - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" - ;; - -solaris*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - # ldd complains unless libraries are executable - postinstall_cmds='chmod +x $lib' - ;; - -sunos4*) - version_type=sunos - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - if test "$with_gnu_ld" = yes; then - need_lib_prefix=no - fi - need_version=yes - ;; - -sysv4 | sysv4.3*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - case $host_vendor in - sni) - shlibpath_overrides_runpath=no - need_lib_prefix=no - export_dynamic_flag_spec='${wl}-Blargedynsym' - runpath_var=LD_RUN_PATH - ;; - siemens) - need_lib_prefix=no - ;; - motorola) - need_lib_prefix=no - need_version=no - shlibpath_overrides_runpath=no - sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' - ;; - esac - ;; - -sysv4*MP*) - if test -d /usr/nec ;then - version_type=linux - library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' - soname_spec='$libname${shared_ext}.$major' - shlibpath_var=LD_LIBRARY_PATH - fi - ;; - -sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - version_type=freebsd-elf - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - hardcode_into_libs=yes - if test "$with_gnu_ld" = yes; then - sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' - shlibpath_overrides_runpath=no - else - sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' - shlibpath_overrides_runpath=yes - case $host_os in - sco3.2v5*) - sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" - ;; - esac - fi - sys_lib_dlsearch_path_spec='/usr/lib' - ;; - -uts4*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -*) - dynamic_linker=no - ;; -esac -echo "$as_me:$LINENO: result: $dynamic_linker" >&5 -echo "${ECHO_T}$dynamic_linker" >&6 -test "$dynamic_linker" = no && can_build_shared=no - -variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test "$GCC" = yes; then - variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" -fi - -echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 -echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6 -hardcode_action_CXX= -if test -n "$hardcode_libdir_flag_spec_CXX" || \ - test -n "$runpath_var_CXX" || \ - test "X$hardcode_automatic_CXX" = "Xyes" ; then - - # We can hardcode non-existant directories. - if test "$hardcode_direct_CXX" != no && - # If the only mechanism to avoid hardcoding is shlibpath_var, we - # have to relink, otherwise we might link with an installed library - # when we should be linking with a yet-to-be-installed one - ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, CXX)" != no && - test "$hardcode_minus_L_CXX" != no; then - # Linking always hardcodes the temporary library directory. - hardcode_action_CXX=relink - else - # We can link without hardcoding, and we can hardcode nonexisting dirs. - hardcode_action_CXX=immediate - fi -else - # We cannot hardcode anything, or else we can only hardcode existing - # directories. - hardcode_action_CXX=unsupported -fi -echo "$as_me:$LINENO: result: $hardcode_action_CXX" >&5 -echo "${ECHO_T}$hardcode_action_CXX" >&6 - -if test "$hardcode_action_CXX" = relink; then - # Fast installation is not supported - enable_fast_install=no -elif test "$shlibpath_overrides_runpath" = yes || - test "$enable_shared" = no; then - # Fast installation is not necessary - enable_fast_install=needless -fi - - -# The else clause should only fire when bootstrapping the -# libtool distribution, otherwise you forgot to ship ltmain.sh -# with your package, and you will get complaints that there are -# no rules to generate ltmain.sh. -if test -f "$ltmain"; then - # See if we are running on zsh, and set the options which allow our commands through - # without removal of \ escapes. - if test -n "${ZSH_VERSION+set}" ; then - setopt NO_GLOB_SUBST - fi - # Now quote all the things that may contain metacharacters while being - # careful not to overquote the AC_SUBSTed values. We take copies of the - # variables and quote the copies for generation of the libtool script. - for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ - SED SHELL STRIP \ - libname_spec library_names_spec soname_spec extract_expsyms_cmds \ - old_striplib striplib file_magic_cmd finish_cmds finish_eval \ - deplibs_check_method reload_flag reload_cmds need_locks \ - lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ - lt_cv_sys_global_symbol_to_c_name_address \ - sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ - old_postinstall_cmds old_postuninstall_cmds \ - compiler_CXX \ - CC_CXX \ - LD_CXX \ - lt_prog_compiler_wl_CXX \ - lt_prog_compiler_pic_CXX \ - lt_prog_compiler_static_CXX \ - lt_prog_compiler_no_builtin_flag_CXX \ - export_dynamic_flag_spec_CXX \ - thread_safe_flag_spec_CXX \ - whole_archive_flag_spec_CXX \ - enable_shared_with_static_runtimes_CXX \ - old_archive_cmds_CXX \ - old_archive_from_new_cmds_CXX \ - predep_objects_CXX \ - postdep_objects_CXX \ - predeps_CXX \ - postdeps_CXX \ - compiler_lib_search_path_CXX \ - archive_cmds_CXX \ - archive_expsym_cmds_CXX \ - postinstall_cmds_CXX \ - postuninstall_cmds_CXX \ - old_archive_from_expsyms_cmds_CXX \ - allow_undefined_flag_CXX \ - no_undefined_flag_CXX \ - export_symbols_cmds_CXX \ - hardcode_libdir_flag_spec_CXX \ - hardcode_libdir_flag_spec_ld_CXX \ - hardcode_libdir_separator_CXX \ - hardcode_automatic_CXX \ - module_cmds_CXX \ - module_expsym_cmds_CXX \ - lt_cv_prog_compiler_c_o_CXX \ - exclude_expsyms_CXX \ - include_expsyms_CXX; do - - case $var in - old_archive_cmds_CXX | \ - old_archive_from_new_cmds_CXX | \ - archive_cmds_CXX | \ - archive_expsym_cmds_CXX | \ - module_cmds_CXX | \ - module_expsym_cmds_CXX | \ - old_archive_from_expsyms_cmds_CXX | \ - export_symbols_cmds_CXX | \ - extract_expsyms_cmds | reload_cmds | finish_cmds | \ - postinstall_cmds | postuninstall_cmds | \ - old_postinstall_cmds | old_postuninstall_cmds | \ - sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) - # Double-quote double-evaled strings. - eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" - ;; - *) - eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" - ;; - esac - done - - case $lt_echo in - *'\$0 --fallback-echo"') - lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` - ;; - esac - -cfgfile="$ofile" - - cat <<__EOF__ >> "$cfgfile" -# ### BEGIN LIBTOOL TAG CONFIG: $tagname - -# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: - -# Shell to use when invoking shell scripts. -SHELL=$lt_SHELL - -# Whether or not to build shared libraries. -build_libtool_libs=$enable_shared - -# Whether or not to build static libraries. -build_old_libs=$enable_static - -# Whether or not to add -lc for building shared libraries. -build_libtool_need_lc=$archive_cmds_need_lc_CXX - -# Whether or not to disallow shared libs when runtime libs are static -allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX - -# Whether or not to optimize for fast installation. -fast_install=$enable_fast_install - -# The host system. -host_alias=$host_alias -host=$host -host_os=$host_os - -# The build system. -build_alias=$build_alias -build=$build -build_os=$build_os - -# An echo program that does not interpret backslashes. -echo=$lt_echo - -# The archiver. -AR=$lt_AR -AR_FLAGS=$lt_AR_FLAGS - -# A C compiler. -LTCC=$lt_LTCC - -# LTCC compiler flags. -LTCFLAGS=$lt_LTCFLAGS - -# A language-specific compiler. -CC=$lt_compiler_CXX - -# Is the compiler the GNU C compiler? -with_gcc=$GCC_CXX - -# An ERE matcher. -EGREP=$lt_EGREP - -# The linker used to build libraries. -LD=$lt_LD_CXX - -# Whether we need hard or soft links. -LN_S=$lt_LN_S - -# A BSD-compatible nm program. -NM=$lt_NM - -# A symbol stripping program -STRIP=$lt_STRIP - -# Used to examine libraries when file_magic_cmd begins "file" -MAGIC_CMD=$MAGIC_CMD - -# Used on cygwin: DLL creation program. -DLLTOOL="$DLLTOOL" - -# Used on cygwin: object dumper. -OBJDUMP="$OBJDUMP" - -# Used on cygwin: assembler. -AS="$AS" - -# The name of the directory that contains temporary libtool files. -objdir=$objdir - -# How to create reloadable object files. -reload_flag=$lt_reload_flag -reload_cmds=$lt_reload_cmds - -# How to pass a linker flag through the compiler. -wl=$lt_lt_prog_compiler_wl_CXX - -# Object file suffix (normally "o"). -objext="$ac_objext" - -# Old archive suffix (normally "a"). -libext="$libext" - -# Shared library suffix (normally ".so"). -shrext_cmds='$shrext_cmds' - -# Executable file suffix (normally ""). -exeext="$exeext" - -# Additional compiler flags for building library objects. -pic_flag=$lt_lt_prog_compiler_pic_CXX -pic_mode=$pic_mode - -# What is the maximum length of a command? -max_cmd_len=$lt_cv_sys_max_cmd_len - -# Does compiler simultaneously support -c and -o options? -compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX - -# Must we lock files when doing compilation? -need_locks=$lt_need_locks - -# Do we need the lib prefix for modules? -need_lib_prefix=$need_lib_prefix - -# Do we need a version for libraries? -need_version=$need_version - -# Whether dlopen is supported. -dlopen_support=$enable_dlopen - -# Whether dlopen of programs is supported. -dlopen_self=$enable_dlopen_self - -# Whether dlopen of statically linked programs is supported. -dlopen_self_static=$enable_dlopen_self_static - -# Compiler flag to prevent dynamic linking. -link_static_flag=$lt_lt_prog_compiler_static_CXX - -# Compiler flag to turn off builtin functions. -no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX - -# Compiler flag to allow reflexive dlopens. -export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX - -# Compiler flag to generate shared objects directly from archives. -whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX - -# Compiler flag to generate thread-safe objects. -thread_safe_flag_spec=$lt_thread_safe_flag_spec_CXX - -# Library versioning type. -version_type=$version_type - -# Format of library name prefix. -libname_spec=$lt_libname_spec - -# List of archive names. First name is the real one, the rest are links. -# The last name is the one that the linker finds with -lNAME. -library_names_spec=$lt_library_names_spec - -# The coded name of the library, if different from the real name. -soname_spec=$lt_soname_spec - -# Commands used to build and install an old-style archive. -RANLIB=$lt_RANLIB -old_archive_cmds=$lt_old_archive_cmds_CXX -old_postinstall_cmds=$lt_old_postinstall_cmds -old_postuninstall_cmds=$lt_old_postuninstall_cmds - -# Create an old-style archive from a shared archive. -old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX - -# Create a temporary old-style archive to link instead of a shared archive. -old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX - -# Commands used to build and install a shared archive. -archive_cmds=$lt_archive_cmds_CXX -archive_expsym_cmds=$lt_archive_expsym_cmds_CXX -postinstall_cmds=$lt_postinstall_cmds -postuninstall_cmds=$lt_postuninstall_cmds - -# Commands used to build a loadable module (assumed same as above if empty) -module_cmds=$lt_module_cmds_CXX -module_expsym_cmds=$lt_module_expsym_cmds_CXX - -# Commands to strip libraries. -old_striplib=$lt_old_striplib -striplib=$lt_striplib - -# Dependencies to place before the objects being linked to create a -# shared library. -predep_objects=$lt_predep_objects_CXX - -# Dependencies to place after the objects being linked to create a -# shared library. -postdep_objects=$lt_postdep_objects_CXX - -# Dependencies to place before the objects being linked to create a -# shared library. -predeps=$lt_predeps_CXX - -# Dependencies to place after the objects being linked to create a -# shared library. -postdeps=$lt_postdeps_CXX - -# The library search path used internally by the compiler when linking -# a shared library. -compiler_lib_search_path=$lt_compiler_lib_search_path_CXX - -# Method to check whether dependent libraries are shared objects. -deplibs_check_method=$lt_deplibs_check_method - -# Command to use when deplibs_check_method == file_magic. -file_magic_cmd=$lt_file_magic_cmd - -# Flag that allows shared libraries with undefined symbols to be built. -allow_undefined_flag=$lt_allow_undefined_flag_CXX - -# Flag that forces no undefined symbols. -no_undefined_flag=$lt_no_undefined_flag_CXX - -# Commands used to finish a libtool library installation in a directory. -finish_cmds=$lt_finish_cmds - -# Same as above, but a single script fragment to be evaled but not shown. -finish_eval=$lt_finish_eval - -# Take the output of nm and produce a listing of raw symbols and C names. -global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe - -# Transform the output of nm in a proper C declaration -global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl - -# Transform the output of nm in a C name address pair -global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address - -# This is the shared library runtime path variable. -runpath_var=$runpath_var - -# This is the shared library path variable. -shlibpath_var=$shlibpath_var - -# Is shlibpath searched before the hard-coded library search path? -shlibpath_overrides_runpath=$shlibpath_overrides_runpath - -# How to hardcode a shared library path into an executable. -hardcode_action=$hardcode_action_CXX - -# Whether we should hardcode library paths into libraries. -hardcode_into_libs=$hardcode_into_libs - -# Flag to hardcode \$libdir into a binary during linking. -# This must work even if \$libdir does not exist. -hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX - -# If ld is used when linking, flag to hardcode \$libdir into -# a binary during linking. This must work even if \$libdir does -# not exist. -hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_CXX - -# Whether we need a single -rpath flag with a separated argument. -hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX - -# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the -# resulting binary. -hardcode_direct=$hardcode_direct_CXX - -# Set to yes if using the -LDIR flag during linking hardcodes DIR into the -# resulting binary. -hardcode_minus_L=$hardcode_minus_L_CXX - -# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into -# the resulting binary. -hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX - -# Set to yes if building a shared library automatically hardcodes DIR into the library -# and all subsequent libraries and executables linked against it. -hardcode_automatic=$hardcode_automatic_CXX - -# Variables whose values should be saved in libtool wrapper scripts and -# restored at relink time. -variables_saved_for_relink="$variables_saved_for_relink" - -# Whether libtool must link a program against all its dependency libraries. -link_all_deplibs=$link_all_deplibs_CXX - -# Compile-time system search path for libraries -sys_lib_search_path_spec=$lt_sys_lib_search_path_spec - -# Run-time system search path for libraries -sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec - -# Fix the shell variable \$srcfile for the compiler. -fix_srcfile_path="$fix_srcfile_path_CXX" - -# Set to yes if exported symbols are required. -always_export_symbols=$always_export_symbols_CXX - -# The commands to list exported symbols. -export_symbols_cmds=$lt_export_symbols_cmds_CXX - -# The commands to extract the exported symbol list from a shared archive. -extract_expsyms_cmds=$lt_extract_expsyms_cmds - -# Symbols that should not be listed in the preloaded symbols. -exclude_expsyms=$lt_exclude_expsyms_CXX - -# Symbols that must always be exported. -include_expsyms=$lt_include_expsyms_CXX - -# ### END LIBTOOL TAG CONFIG: $tagname - -__EOF__ - - -else - # If there is no Makefile yet, we rely on a make rule to execute - # `config.status --recheck' to rerun these tests and create the - # libtool script then. - ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` - if test -f "$ltmain_in"; then - test -f Makefile && make "$ltmain" - fi -fi - - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -CC=$lt_save_CC -LDCXX=$LD -LD=$lt_save_LD -GCC=$lt_save_GCC -with_gnu_ldcxx=$with_gnu_ld -with_gnu_ld=$lt_save_with_gnu_ld -lt_cv_path_LDCXX=$lt_cv_path_LD -lt_cv_path_LD=$lt_save_path_LD -lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld -lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld - - else - tagname="" - fi - ;; - - F77) - if test -n "$F77" && test "X$F77" != "Xno"; then - -ac_ext=f -ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5' -ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_f77_compiler_gnu - - -archive_cmds_need_lc_F77=no -allow_undefined_flag_F77= -always_export_symbols_F77=no -archive_expsym_cmds_F77= -export_dynamic_flag_spec_F77= -hardcode_direct_F77=no -hardcode_libdir_flag_spec_F77= -hardcode_libdir_flag_spec_ld_F77= -hardcode_libdir_separator_F77= -hardcode_minus_L_F77=no -hardcode_automatic_F77=no -module_cmds_F77= -module_expsym_cmds_F77= -link_all_deplibs_F77=unknown -old_archive_cmds_F77=$old_archive_cmds -no_undefined_flag_F77= -whole_archive_flag_spec_F77= -enable_shared_with_static_runtimes_F77=no - -# Source file extension for f77 test sources. -ac_ext=f - -# Object file extension for compiled f77 test sources. -objext=o -objext_F77=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code=" subroutine t\n return\n end\n" - -# Code to be used in simple link tests -lt_simple_link_test_code=" program t\n end\n" - -# ltmain only uses $CC for tagged configurations so make sure $CC is set. - -# If no C compiler was specified, use CC. -LTCC=${LTCC-"$CC"} - -# If no C compiler flags were specified, use CFLAGS. -LTCFLAGS=${LTCFLAGS-"$CFLAGS"} - -# Allow CC to be a program name with arguments. -compiler=$CC - - -# save warnings/boilerplate of simple test code -ac_outfile=conftest.$ac_objext -printf "$lt_simple_compile_test_code" >conftest.$ac_ext -eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_compiler_boilerplate=`cat conftest.err` -$rm conftest* - -ac_outfile=conftest.$ac_objext -printf "$lt_simple_link_test_code" >conftest.$ac_ext -eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_linker_boilerplate=`cat conftest.err` -$rm conftest* - - -# Allow CC to be a program name with arguments. -lt_save_CC="$CC" -CC=${F77-"f77"} -compiler=$CC -compiler_F77=$CC -for cc_temp in $compiler""; do - case $cc_temp in - compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; - distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; - \-*) ;; - *) break;; - esac -done -cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` - - -echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5 -echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6 -echo "$as_me:$LINENO: result: $can_build_shared" >&5 -echo "${ECHO_T}$can_build_shared" >&6 - -echo "$as_me:$LINENO: checking whether to build shared libraries" >&5 -echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6 -test "$can_build_shared" = "no" && enable_shared=no - -# On AIX, shared libraries and static libraries use the same namespace, and -# are all built from PIC. -case $host_os in -aix3*) - test "$enable_shared" = yes && enable_static=no - if test -n "$RANLIB"; then - archive_cmds="$archive_cmds~\$RANLIB \$lib" - postinstall_cmds='$RANLIB $lib' - fi - ;; -aix4* | aix5*) - if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then - test "$enable_shared" = yes && enable_static=no - fi - ;; -esac -echo "$as_me:$LINENO: result: $enable_shared" >&5 -echo "${ECHO_T}$enable_shared" >&6 - -echo "$as_me:$LINENO: checking whether to build static libraries" >&5 -echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6 -# Make sure either enable_shared or enable_static is yes. -test "$enable_shared" = yes || enable_static=yes -echo "$as_me:$LINENO: result: $enable_static" >&5 -echo "${ECHO_T}$enable_static" >&6 - -GCC_F77="$G77" -LD_F77="$LD" - -lt_prog_compiler_wl_F77= -lt_prog_compiler_pic_F77= -lt_prog_compiler_static_F77= - -echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 -echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 - - if test "$GCC" = yes; then - lt_prog_compiler_wl_F77='-Wl,' - lt_prog_compiler_static_F77='-static' - - case $host_os in - aix*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static_F77='-Bstatic' - fi - ;; - - amigaos*) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. - lt_prog_compiler_pic_F77='-m68020 -resident32 -malways-restore-a4' - ;; - - beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - - mingw* | pw32* | os2*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - lt_prog_compiler_pic_F77='-DDLL_EXPORT' - ;; - - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - lt_prog_compiler_pic_F77='-fno-common' - ;; - - interix3*) - # Interix 3.x gcc -fpic/-fPIC options generate broken code. - # Instead, we relocate shared libraries at runtime. - ;; - - msdosdjgpp*) - # Just because we use GCC doesn't mean we suddenly get shared libraries - # on systems that don't support them. - lt_prog_compiler_can_build_shared_F77=no - enable_shared=no - ;; - - sysv4*MP*) - if test -d /usr/nec; then - lt_prog_compiler_pic_F77=-Kconform_pic - fi - ;; - - hpux*) - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case $host_cpu in - hppa*64*|ia64*) - # +Z the default - ;; - *) - lt_prog_compiler_pic_F77='-fPIC' - ;; - esac - ;; - - *) - lt_prog_compiler_pic_F77='-fPIC' - ;; - esac - else - # PORTME Check for flag to pass linker flags through the system compiler. - case $host_os in - aix*) - lt_prog_compiler_wl_F77='-Wl,' - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static_F77='-Bstatic' - else - lt_prog_compiler_static_F77='-bnso -bI:/lib/syscalls.exp' - fi - ;; - darwin*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - case $cc_basename in - xlc*) - lt_prog_compiler_pic_F77='-qnocommon' - lt_prog_compiler_wl_F77='-Wl,' - ;; - esac - ;; - - mingw* | pw32* | os2*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - lt_prog_compiler_pic_F77='-DDLL_EXPORT' - ;; - - hpux9* | hpux10* | hpux11*) - lt_prog_compiler_wl_F77='-Wl,' - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case $host_cpu in - hppa*64*|ia64*) - # +Z the default - ;; - *) - lt_prog_compiler_pic_F77='+Z' - ;; - esac - # Is there a better lt_prog_compiler_static that works with the bundled CC? - lt_prog_compiler_static_F77='${wl}-a ${wl}archive' - ;; - - irix5* | irix6* | nonstopux*) - lt_prog_compiler_wl_F77='-Wl,' - # PIC (with -KPIC) is the default. - lt_prog_compiler_static_F77='-non_shared' - ;; - - newsos6) - lt_prog_compiler_pic_F77='-KPIC' - lt_prog_compiler_static_F77='-Bstatic' - ;; - - linux*) - case $cc_basename in - icc* | ecc*) - lt_prog_compiler_wl_F77='-Wl,' - lt_prog_compiler_pic_F77='-KPIC' - lt_prog_compiler_static_F77='-static' - ;; - pgcc* | pgf77* | pgf90* | pgf95*) - # Portland Group compilers (*not* the Pentium gcc compiler, - # which looks to be a dead project) - lt_prog_compiler_wl_F77='-Wl,' - lt_prog_compiler_pic_F77='-fpic' - lt_prog_compiler_static_F77='-Bstatic' - ;; - ccc*) - lt_prog_compiler_wl_F77='-Wl,' - # All Alpha code is PIC. - lt_prog_compiler_static_F77='-non_shared' - ;; - esac - ;; - - osf3* | osf4* | osf5*) - lt_prog_compiler_wl_F77='-Wl,' - # All OSF/1 code is PIC. - lt_prog_compiler_static_F77='-non_shared' - ;; - - solaris*) - lt_prog_compiler_pic_F77='-KPIC' - lt_prog_compiler_static_F77='-Bstatic' - case $cc_basename in - f77* | f90* | f95*) - lt_prog_compiler_wl_F77='-Qoption ld ';; - *) - lt_prog_compiler_wl_F77='-Wl,';; - esac - ;; - - sunos4*) - lt_prog_compiler_wl_F77='-Qoption ld ' - lt_prog_compiler_pic_F77='-PIC' - lt_prog_compiler_static_F77='-Bstatic' - ;; - - sysv4 | sysv4.2uw2* | sysv4.3*) - lt_prog_compiler_wl_F77='-Wl,' - lt_prog_compiler_pic_F77='-KPIC' - lt_prog_compiler_static_F77='-Bstatic' - ;; - - sysv4*MP*) - if test -d /usr/nec ;then - lt_prog_compiler_pic_F77='-Kconform_pic' - lt_prog_compiler_static_F77='-Bstatic' - fi - ;; - - sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) - lt_prog_compiler_wl_F77='-Wl,' - lt_prog_compiler_pic_F77='-KPIC' - lt_prog_compiler_static_F77='-Bstatic' - ;; - - unicos*) - lt_prog_compiler_wl_F77='-Wl,' - lt_prog_compiler_can_build_shared_F77=no - ;; - - uts4*) - lt_prog_compiler_pic_F77='-pic' - lt_prog_compiler_static_F77='-Bstatic' - ;; - - *) - lt_prog_compiler_can_build_shared_F77=no - ;; - esac - fi - -echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_F77" >&5 -echo "${ECHO_T}$lt_prog_compiler_pic_F77" >&6 - -# -# Check to make sure the PIC flag actually works. -# -if test -n "$lt_prog_compiler_pic_F77"; then - -echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works" >&5 -echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works... $ECHO_C" >&6 -if test "${lt_prog_compiler_pic_works_F77+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_prog_compiler_pic_works_F77=no - ac_outfile=conftest.$ac_objext - printf "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$lt_prog_compiler_pic_F77" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - # The option is referenced via a variable to avoid confusing sed. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:13198: $lt_compile\"" >&5) - (eval "$lt_compile" 2>conftest.err) - ac_status=$? - cat conftest.err >&5 - echo "$as_me:13202: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s "$ac_outfile"; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings other than the usual output. - $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then - lt_prog_compiler_pic_works_F77=yes - fi - fi - $rm conftest* - -fi -echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_F77" >&5 -echo "${ECHO_T}$lt_prog_compiler_pic_works_F77" >&6 - -if test x"$lt_prog_compiler_pic_works_F77" = xyes; then - case $lt_prog_compiler_pic_F77 in - "" | " "*) ;; - *) lt_prog_compiler_pic_F77=" $lt_prog_compiler_pic_F77" ;; - esac -else - lt_prog_compiler_pic_F77= - lt_prog_compiler_can_build_shared_F77=no -fi - -fi -case $host_os in - # For platforms which do not support PIC, -DPIC is meaningless: - *djgpp*) - lt_prog_compiler_pic_F77= - ;; - *) - lt_prog_compiler_pic_F77="$lt_prog_compiler_pic_F77" - ;; -esac - -# -# Check to make sure the static flag actually works. -# -wl=$lt_prog_compiler_wl_F77 eval lt_tmp_static_flag=\"$lt_prog_compiler_static_F77\" -echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 -echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6 -if test "${lt_prog_compiler_static_works_F77+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_prog_compiler_static_works_F77=no - save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS $lt_tmp_static_flag" - printf "$lt_simple_link_test_code" > conftest.$ac_ext - if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then - # The linker can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s conftest.err; then - # Append any errors to the config.log. - cat conftest.err 1>&5 - $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if diff conftest.exp conftest.er2 >/dev/null; then - lt_prog_compiler_static_works_F77=yes - fi - else - lt_prog_compiler_static_works_F77=yes - fi - fi - $rm conftest* - LDFLAGS="$save_LDFLAGS" - -fi -echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_F77" >&5 -echo "${ECHO_T}$lt_prog_compiler_static_works_F77" >&6 - -if test x"$lt_prog_compiler_static_works_F77" = xyes; then - : -else - lt_prog_compiler_static_F77= -fi - - -echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 -echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6 -if test "${lt_cv_prog_compiler_c_o_F77+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_cv_prog_compiler_c_o_F77=no - $rm -r conftest 2>/dev/null - mkdir conftest - cd conftest - mkdir out - printf "$lt_simple_compile_test_code" > conftest.$ac_ext - - lt_compiler_flag="-o out/conftest2.$ac_objext" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:13302: $lt_compile\"" >&5) - (eval "$lt_compile" 2>out/conftest.err) - ac_status=$? - cat out/conftest.err >&5 - echo "$as_me:13306: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s out/conftest2.$ac_objext - then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp - $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 - if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then - lt_cv_prog_compiler_c_o_F77=yes - fi - fi - chmod u+w . 2>&5 - $rm conftest* - # SGI C++ compiler will create directory out/ii_files/ for - # template instantiation - test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files - $rm out/* && rmdir out - cd .. - rmdir conftest - $rm conftest* - -fi -echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_F77" >&5 -echo "${ECHO_T}$lt_cv_prog_compiler_c_o_F77" >&6 - - -hard_links="nottested" -if test "$lt_cv_prog_compiler_c_o_F77" = no && test "$need_locks" != no; then - # do not overwrite the value of need_locks provided by the user - echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 -echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6 - hard_links=yes - $rm conftest* - ln conftest.a conftest.b 2>/dev/null && hard_links=no - touch conftest.a - ln conftest.a conftest.b 2>&5 || hard_links=no - ln conftest.a conftest.b 2>/dev/null && hard_links=no - echo "$as_me:$LINENO: result: $hard_links" >&5 -echo "${ECHO_T}$hard_links" >&6 - if test "$hard_links" = no; then - { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 -echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} - need_locks=warn - fi -else - need_locks=no -fi - -echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 -echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6 - - runpath_var= - allow_undefined_flag_F77= - enable_shared_with_static_runtimes_F77=no - archive_cmds_F77= - archive_expsym_cmds_F77= - old_archive_From_new_cmds_F77= - old_archive_from_expsyms_cmds_F77= - export_dynamic_flag_spec_F77= - whole_archive_flag_spec_F77= - thread_safe_flag_spec_F77= - hardcode_libdir_flag_spec_F77= - hardcode_libdir_flag_spec_ld_F77= - hardcode_libdir_separator_F77= - hardcode_direct_F77=no - hardcode_minus_L_F77=no - hardcode_shlibpath_var_F77=unsupported - link_all_deplibs_F77=unknown - hardcode_automatic_F77=no - module_cmds_F77= - module_expsym_cmds_F77= - always_export_symbols_F77=no - export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - # include_expsyms should be a list of space-separated symbols to be *always* - # included in the symbol list - include_expsyms_F77= - # exclude_expsyms can be an extended regexp of symbols to exclude - # it will be wrapped by ` (' and `)$', so one must not match beginning or - # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', - # as well as any symbol that contains `d'. - exclude_expsyms_F77="_GLOBAL_OFFSET_TABLE_" - # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out - # platforms (ab)use it in PIC code, but their linkers get confused if - # the symbol is explicitly referenced. Since portable code cannot - # rely on this symbol name, it's probably fine to never include it in - # preloaded symbol tables. - extract_expsyms_cmds= - # Just being paranoid about ensuring that cc_basename is set. - for cc_temp in $compiler""; do - case $cc_temp in - compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; - distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; - \-*) ;; - *) break;; - esac -done -cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` - - case $host_os in - cygwin* | mingw* | pw32*) - # FIXME: the MSVC++ port hasn't been tested in a loooong time - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - if test "$GCC" != yes; then - with_gnu_ld=no - fi - ;; - interix*) - # we just hope/assume this is gcc and not c89 (= MSVC++) - with_gnu_ld=yes - ;; - openbsd*) - with_gnu_ld=no - ;; - esac - - ld_shlibs_F77=yes - if test "$with_gnu_ld" = yes; then - # If archive_cmds runs LD, not CC, wlarc should be empty - wlarc='${wl}' - - # Set some defaults for GNU ld with shared library support. These - # are reset later if shared libraries are not supported. Putting them - # here allows them to be overridden if necessary. - runpath_var=LD_RUN_PATH - hardcode_libdir_flag_spec_F77='${wl}--rpath ${wl}$libdir' - export_dynamic_flag_spec_F77='${wl}--export-dynamic' - # ancient GNU ld didn't support --whole-archive et. al. - if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then - whole_archive_flag_spec_F77="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - else - whole_archive_flag_spec_F77= - fi - supports_anon_versioning=no - case `$LD -v 2>/dev/null` in - *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 - *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... - *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... - *\ 2.11.*) ;; # other 2.11 versions - *) supports_anon_versioning=yes ;; - esac - - # See if GNU ld supports shared libraries. - case $host_os in - aix3* | aix4* | aix5*) - # On AIX/PPC, the GNU linker is very broken - if test "$host_cpu" != ia64; then - ld_shlibs_F77=no - cat <&2 - -*** Warning: the GNU linker, at least up to release 2.9.1, is reported -*** to be unable to reliably create shared libraries on AIX. -*** Therefore, libtool is disabling shared libraries support. If you -*** really care for shared libraries, you may want to modify your PATH -*** so that a non-GNU linker is found, and then restart. - -EOF - fi - ;; - - amigaos*) - archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - hardcode_libdir_flag_spec_F77='-L$libdir' - hardcode_minus_L_F77=yes - - # Samuel A. Falvo II reports - # that the semantics of dynamic libraries on AmigaOS, at least up - # to version 4, is to share data among multiple programs linked - # with the same dynamic library. Since this doesn't match the - # behavior of shared libraries on other platforms, we can't use - # them. - ld_shlibs_F77=no - ;; - - beos*) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - allow_undefined_flag_F77=unsupported - # Joseph Beckenbach says some releases of gcc - # support --undefined. This deserves some investigation. FIXME - archive_cmds_F77='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - else - ld_shlibs_F77=no - fi - ;; - - cygwin* | mingw* | pw32*) - # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, F77) is actually meaningless, - # as there is no search path for DLLs. - hardcode_libdir_flag_spec_F77='-L$libdir' - allow_undefined_flag_F77=unsupported - always_export_symbols_F77=no - enable_shared_with_static_runtimes_F77=yes - export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' - - if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then - archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - archive_expsym_cmds_F77='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - else - ld_shlibs_F77=no - fi - ;; - - interix3*) - hardcode_direct_F77=no - hardcode_shlibpath_var_F77=no - hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' - export_dynamic_flag_spec_F77='${wl}-E' - # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. - # Instead, shared libraries are loaded at an image base (0x10000000 by - # default) and relocated if they conflict, which is a slow very memory - # consuming and fragmenting process. To avoid this, we pick a random, - # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link - # time. Moving up from 0x10000000 also allows more sbrk(2) space. - archive_cmds_F77='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - archive_expsym_cmds_F77='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - ;; - - linux*) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - tmp_addflag= - case $cc_basename,$host_cpu in - pgcc*) # Portland Group C compiler - whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' - tmp_addflag=' $pic_flag' - ;; - pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers - whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' - tmp_addflag=' $pic_flag -Mnomain' ;; - ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 - tmp_addflag=' -i_dynamic' ;; - efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 - tmp_addflag=' -i_dynamic -nofor_main' ;; - ifc* | ifort*) # Intel Fortran compiler - tmp_addflag=' -nofor_main' ;; - esac - archive_cmds_F77='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - - if test $supports_anon_versioning = yes; then - archive_expsym_cmds_F77='$echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - $echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' - fi - else - ld_shlibs_F77=no - fi - ;; - - netbsd*) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - archive_cmds_F77='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' - wlarc= - else - archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - fi - ;; - - solaris*) - if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then - ld_shlibs_F77=no - cat <&2 - -*** Warning: The releases 2.8.* of the GNU linker cannot reliably -*** create shared libraries on Solaris systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.9.1 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -EOF - elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - ld_shlibs_F77=no - fi - ;; - - sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) - case `$LD -v 2>&1` in - *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) - ld_shlibs_F77=no - cat <<_LT_EOF 1>&2 - -*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not -*** reliably create shared libraries on SCO systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.16.91.0.3 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -_LT_EOF - ;; - *) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' - archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' - archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' - else - ld_shlibs_F77=no - fi - ;; - esac - ;; - - sunos4*) - archive_cmds_F77='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' - wlarc= - hardcode_direct_F77=yes - hardcode_shlibpath_var_F77=no - ;; - - *) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - ld_shlibs_F77=no - fi - ;; - esac - - if test "$ld_shlibs_F77" = no; then - runpath_var= - hardcode_libdir_flag_spec_F77= - export_dynamic_flag_spec_F77= - whole_archive_flag_spec_F77= - fi - else - # PORTME fill in a description of your system's linker (not GNU ld) - case $host_os in - aix3*) - allow_undefined_flag_F77=unsupported - always_export_symbols_F77=yes - archive_expsym_cmds_F77='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' - # Note: this linker hardcodes the directories in LIBPATH if there - # are no directories specified by -L. - hardcode_minus_L_F77=yes - if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then - # Neither direct hardcoding nor static linking is supported with a - # broken collect2. - hardcode_direct_F77=unsupported - fi - ;; - - aix4* | aix5*) - if test "$host_cpu" = ia64; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag="" - else - # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - if $NM -V 2>&1 | grep 'GNU' > /dev/null; then - export_symbols_cmds_F77='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' - else - export_symbols_cmds_F77='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' - fi - aix_use_runtimelinking=no - - # Test if we are trying to use run time linking or normal - # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. - case $host_os in aix4.[23]|aix4.[23].*|aix5*) - for ld_flag in $LDFLAGS; do - if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then - aix_use_runtimelinking=yes - break - fi - done - ;; - esac - - exp_sym_flag='-bexport' - no_entry_flag='-bnoentry' - fi - - # When large executables or shared objects are built, AIX ld can - # have problems creating the table of contents. If linking a library - # or program results in "error TOC overflow" add -mminimal-toc to - # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not - # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. - - archive_cmds_F77='' - hardcode_direct_F77=yes - hardcode_libdir_separator_F77=':' - link_all_deplibs_F77=yes - - if test "$GCC" = yes; then - case $host_os in aix4.[012]|aix4.[012].*) - # We only want to do this on AIX 4.2 and lower, the check - # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` - if test -f "$collect2name" && \ - strings "$collect2name" | grep resolve_lib_name >/dev/null - then - # We have reworked collect2 - hardcode_direct_F77=yes - else - # We have old collect2 - hardcode_direct_F77=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - hardcode_minus_L_F77=yes - hardcode_libdir_flag_spec_F77='-L$libdir' - hardcode_libdir_separator_F77= - fi - ;; - esac - shared_flag='-shared' - if test "$aix_use_runtimelinking" = yes; then - shared_flag="$shared_flag "'${wl}-G' - fi - else - # not using gcc - if test "$host_cpu" = ia64; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' - else - shared_flag='${wl}-bM:SRE' - fi - fi - fi - - # It seems that -bexpall does not export symbols beginning with - # underscore (_), so it is better to generate a list of symbols to export. - always_export_symbols_F77=yes - if test "$aix_use_runtimelinking" = yes; then - # Warning - without using the other runtime loading flags (-brtl), - # -berok will link without error, but may produce a broken library. - allow_undefined_flag_F77='-berok' - # Determine the default libpath from the value encoded in an empty executable. - cat >conftest.$ac_ext <<_ACEOF - program main - - end -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_f77_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'`; fi -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi - - hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath" - archive_expsym_cmds_F77="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" - else - if test "$host_cpu" = ia64; then - hardcode_libdir_flag_spec_F77='${wl}-R $libdir:/usr/lib:/lib' - allow_undefined_flag_F77="-z nodefs" - archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" - else - # Determine the default libpath from the value encoded in an empty executable. - cat >conftest.$ac_ext <<_ACEOF - program main - - end -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_f77_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'`; fi -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi - - hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath" - # Warning - without using the other run time loading flags, - # -berok will link without error, but may produce a broken library. - no_undefined_flag_F77=' ${wl}-bernotok' - allow_undefined_flag_F77=' ${wl}-berok' - # Exported symbols can be pulled into shared objects from archives - whole_archive_flag_spec_F77='$convenience' - archive_cmds_need_lc_F77=yes - # This is similar to how AIX traditionally builds its shared libraries. - archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' - fi - fi - ;; - - amigaos*) - archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - hardcode_libdir_flag_spec_F77='-L$libdir' - hardcode_minus_L_F77=yes - # see comment about different semantics on the GNU ld section - ld_shlibs_F77=no - ;; - - bsdi[45]*) - export_dynamic_flag_spec_F77=-rdynamic - ;; - - cygwin* | mingw* | pw32*) - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - # hardcode_libdir_flag_spec is actually meaningless, as there is - # no search path for DLLs. - hardcode_libdir_flag_spec_F77=' ' - allow_undefined_flag_F77=unsupported - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" - # FIXME: Setting linknames here is a bad hack. - archive_cmds_F77='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' - # The linker will automatically build a .lib file if we build a DLL. - old_archive_From_new_cmds_F77='true' - # FIXME: Should let the user specify the lib program. - old_archive_cmds_F77='lib /OUT:$oldlib$oldobjs$old_deplibs' - fix_srcfile_path_F77='`cygpath -w "$srcfile"`' - enable_shared_with_static_runtimes_F77=yes - ;; - - darwin* | rhapsody*) - case $host_os in - rhapsody* | darwin1.[012]) - allow_undefined_flag_F77='${wl}-undefined ${wl}suppress' - ;; - *) # Darwin 1.3 on - if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then - allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' - else - case ${MACOSX_DEPLOYMENT_TARGET} in - 10.[012]) - allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' - ;; - 10.*) - allow_undefined_flag_F77='${wl}-undefined ${wl}dynamic_lookup' - ;; - esac - fi - ;; - esac - archive_cmds_need_lc_F77=no - hardcode_direct_F77=no - hardcode_automatic_F77=yes - hardcode_shlibpath_var_F77=unsupported - whole_archive_flag_spec_F77='' - link_all_deplibs_F77=yes - if test "$GCC" = yes ; then - output_verbose_link_cmd='echo' - archive_cmds_F77='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds - archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - else - case $cc_basename in - xlc*) - output_verbose_link_cmd='echo' - archive_cmds_F77='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' - module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds - archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - ;; - *) - ld_shlibs_F77=no - ;; - esac - fi - ;; - - dgux*) - archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec_F77='-L$libdir' - hardcode_shlibpath_var_F77=no - ;; - - freebsd1*) - ld_shlibs_F77=no - ;; - - # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor - # support. Future versions do this automatically, but an explicit c++rt0.o - # does not break anything, and helps significantly (at the cost of a little - # extra space). - freebsd2.2*) - archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' - hardcode_libdir_flag_spec_F77='-R$libdir' - hardcode_direct_F77=yes - hardcode_shlibpath_var_F77=no - ;; - - # Unfortunately, older versions of FreeBSD 2 do not have this feature. - freebsd2*) - archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct_F77=yes - hardcode_minus_L_F77=yes - hardcode_shlibpath_var_F77=no - ;; - - # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd* | kfreebsd*-gnu | dragonfly*) - archive_cmds_F77='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec_F77='-R$libdir' - hardcode_direct_F77=yes - hardcode_shlibpath_var_F77=no - ;; - - hpux9*) - if test "$GCC" = yes; then - archive_cmds_F77='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - else - archive_cmds_F77='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - fi - hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' - hardcode_libdir_separator_F77=: - hardcode_direct_F77=yes - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L_F77=yes - export_dynamic_flag_spec_F77='${wl}-E' - ;; - - hpux10*) - if test "$GCC" = yes -a "$with_gnu_ld" = no; then - archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds_F77='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' - fi - if test "$with_gnu_ld" = no; then - hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' - hardcode_libdir_separator_F77=: - - hardcode_direct_F77=yes - export_dynamic_flag_spec_F77='${wl}-E' - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L_F77=yes - fi - ;; - - hpux11*) - if test "$GCC" = yes -a "$with_gnu_ld" = no; then - case $host_cpu in - hppa*64*) - archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - ia64*) - archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - else - case $host_cpu in - hppa*64*) - archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - ia64*) - archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - fi - if test "$with_gnu_ld" = no; then - hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' - hardcode_libdir_separator_F77=: - - case $host_cpu in - hppa*64*|ia64*) - hardcode_libdir_flag_spec_ld_F77='+b $libdir' - hardcode_direct_F77=no - hardcode_shlibpath_var_F77=no - ;; - *) - hardcode_direct_F77=yes - export_dynamic_flag_spec_F77='${wl}-E' - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L_F77=yes - ;; - esac - fi - ;; - - irix5* | irix6* | nonstopux*) - if test "$GCC" = yes; then - archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - archive_cmds_F77='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - hardcode_libdir_flag_spec_ld_F77='-rpath $libdir' - fi - hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator_F77=: - link_all_deplibs_F77=yes - ;; - - netbsd*) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out - else - archive_cmds_F77='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF - fi - hardcode_libdir_flag_spec_F77='-R$libdir' - hardcode_direct_F77=yes - hardcode_shlibpath_var_F77=no - ;; - - newsos6) - archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct_F77=yes - hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator_F77=: - hardcode_shlibpath_var_F77=no - ;; - - openbsd*) - hardcode_direct_F77=yes - hardcode_shlibpath_var_F77=no - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' - hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' - export_dynamic_flag_spec_F77='${wl}-E' - else - case $host_os in - openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) - archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec_F77='-R$libdir' - ;; - *) - archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' - ;; - esac - fi - ;; - - os2*) - hardcode_libdir_flag_spec_F77='-L$libdir' - hardcode_minus_L_F77=yes - allow_undefined_flag_F77=unsupported - archive_cmds_F77='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' - old_archive_From_new_cmds_F77='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' - ;; - - osf3*) - if test "$GCC" = yes; then - allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - allow_undefined_flag_F77=' -expect_unresolved \*' - archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - fi - hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator_F77=: - ;; - - osf4* | osf5*) # as osf3* with the addition of -msym flag - if test "$GCC" = yes; then - allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' - else - allow_undefined_flag_F77=' -expect_unresolved \*' - archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - archive_expsym_cmds_F77='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ - $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' - - # Both c and cxx compiler support -rpath directly - hardcode_libdir_flag_spec_F77='-rpath $libdir' - fi - hardcode_libdir_separator_F77=: - ;; - - solaris*) - no_undefined_flag_F77=' -z text' - if test "$GCC" = yes; then - wlarc='${wl}' - archive_cmds_F77='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' - else - wlarc='' - archive_cmds_F77='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' - archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' - fi - hardcode_libdir_flag_spec_F77='-R$libdir' - hardcode_shlibpath_var_F77=no - case $host_os in - solaris2.[0-5] | solaris2.[0-5].*) ;; - *) - # The compiler driver will combine linker options so we - # cannot just pass the convience library names through - # without $wl, iff we do not link with $LD. - # Luckily, gcc supports the same syntax we need for Sun Studio. - # Supported since Solaris 2.6 (maybe 2.5.1?) - case $wlarc in - '') - whole_archive_flag_spec_F77='-z allextract$convenience -z defaultextract' ;; - *) - whole_archive_flag_spec_F77='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; - esac ;; - esac - link_all_deplibs_F77=yes - ;; - - sunos4*) - if test "x$host_vendor" = xsequent; then - # Use $CC to link under sequent, because it throws in some extra .o - # files that make .init and .fini sections work. - archive_cmds_F77='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds_F77='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' - fi - hardcode_libdir_flag_spec_F77='-L$libdir' - hardcode_direct_F77=yes - hardcode_minus_L_F77=yes - hardcode_shlibpath_var_F77=no - ;; - - sysv4) - case $host_vendor in - sni) - archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct_F77=yes # is this really true??? - ;; - siemens) - ## LD is ld it makes a PLAMLIB - ## CC just makes a GrossModule. - archive_cmds_F77='$LD -G -o $lib $libobjs $deplibs $linker_flags' - reload_cmds_F77='$CC -r -o $output$reload_objs' - hardcode_direct_F77=no - ;; - motorola) - archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct_F77=no #Motorola manual says yes, but my tests say they lie - ;; - esac - runpath_var='LD_RUN_PATH' - hardcode_shlibpath_var_F77=no - ;; - - sysv4.3*) - archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_shlibpath_var_F77=no - export_dynamic_flag_spec_F77='-Bexport' - ;; - - sysv4*MP*) - if test -d /usr/nec; then - archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_shlibpath_var_F77=no - runpath_var=LD_RUN_PATH - hardcode_runpath_var=yes - ld_shlibs_F77=yes - fi - ;; - - sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) - no_undefined_flag_F77='${wl}-z,text' - archive_cmds_need_lc_F77=no - hardcode_shlibpath_var_F77=no - runpath_var='LD_RUN_PATH' - - if test "$GCC" = yes; then - archive_cmds_F77='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds_F77='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - fi - ;; - - sysv5* | sco3.2v5* | sco5v6*) - # Note: We can NOT use -z defs as we might desire, because we do not - # link with -lc, and that would cause any symbols used from libc to - # always be unresolved, which means just about no library would - # ever link correctly. If we're not using GNU ld we use -z text - # though, which does catch some bad symbols but isn't as heavy-handed - # as -z defs. - no_undefined_flag_F77='${wl}-z,text' - allow_undefined_flag_F77='${wl}-z,nodefs' - archive_cmds_need_lc_F77=no - hardcode_shlibpath_var_F77=no - hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' - hardcode_libdir_separator_F77=':' - link_all_deplibs_F77=yes - export_dynamic_flag_spec_F77='${wl}-Bexport' - runpath_var='LD_RUN_PATH' - - if test "$GCC" = yes; then - archive_cmds_F77='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds_F77='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - fi - ;; - - uts4*) - archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec_F77='-L$libdir' - hardcode_shlibpath_var_F77=no - ;; - - *) - ld_shlibs_F77=no - ;; - esac - fi - -echo "$as_me:$LINENO: result: $ld_shlibs_F77" >&5 -echo "${ECHO_T}$ld_shlibs_F77" >&6 -test "$ld_shlibs_F77" = no && can_build_shared=no - -# -# Do we need to explicitly link libc? -# -case "x$archive_cmds_need_lc_F77" in -x|xyes) - # Assume -lc should be added - archive_cmds_need_lc_F77=yes - - if test "$enable_shared" = yes && test "$GCC" = yes; then - case $archive_cmds_F77 in - *'~'*) - # FIXME: we may have to deal with multi-command sequences. - ;; - '$CC '*) - # Test whether the compiler implicitly links with -lc since on some - # systems, -lgcc has to come before -lc. If gcc already passes -lc - # to ld, don't add -lc before -lgcc. - echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 -echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6 - $rm conftest* - printf "$lt_simple_compile_test_code" > conftest.$ac_ext - - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } 2>conftest.err; then - soname=conftest - lib=conftest - libobjs=conftest.$ac_objext - deplibs= - wl=$lt_prog_compiler_wl_F77 - pic_flag=$lt_prog_compiler_pic_F77 - compiler_flags=-v - linker_flags=-v - verstring= - output_objdir=. - libname=conftest - lt_save_allow_undefined_flag=$allow_undefined_flag_F77 - allow_undefined_flag_F77= - if { (eval echo "$as_me:$LINENO: \"$archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 - (eval $archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } - then - archive_cmds_need_lc_F77=no - else - archive_cmds_need_lc_F77=yes - fi - allow_undefined_flag_F77=$lt_save_allow_undefined_flag - else - cat conftest.err 1>&5 - fi - $rm conftest* - echo "$as_me:$LINENO: result: $archive_cmds_need_lc_F77" >&5 -echo "${ECHO_T}$archive_cmds_need_lc_F77" >&6 - ;; - esac - fi - ;; -esac - -echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 -echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6 -library_names_spec= -libname_spec='lib$name' -soname_spec= -shrext_cmds=".so" -postinstall_cmds= -postuninstall_cmds= -finish_cmds= -finish_eval= -shlibpath_var= -shlibpath_overrides_runpath=unknown -version_type=none -dynamic_linker="$host_os ld.so" -sys_lib_dlsearch_path_spec="/lib /usr/lib" -if test "$GCC" = yes; then - sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then - # if the path contains ";" then we assume it to be the separator - # otherwise default to the standard path separator (i.e. ":") - it is - # assumed that no part of a normal pathname contains ";" but that should - # okay in the real world where ";" in dirpaths is itself problematic. - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi -else - sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" -fi -need_lib_prefix=unknown -hardcode_into_libs=no - -# when you set need_version to no, make sure it does not cause -set_version -# flags to be left without arguments -need_version=unknown - -case $host_os in -aix3*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' - shlibpath_var=LIBPATH - - # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='${libname}${release}${shared_ext}$major' - ;; - -aix4* | aix5*) - version_type=linux - need_lib_prefix=no - need_version=no - hardcode_into_libs=yes - if test "$host_cpu" = ia64; then - # AIX 5 supports IA64 - library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - else - # With GCC up to 2.95.x, collect2 would create an import file - # for dependence libraries. The import file would start with - # the line `#! .'. This would cause the generated library to - # depend on `.', always an invalid library. This was fixed in - # development snapshots of GCC prior to 3.0. - case $host_os in - aix4 | aix4.[01] | aix4.[01].*) - if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' - echo ' yes ' - echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then - : - else - can_build_shared=no - fi - ;; - esac - # AIX (on Power*) has no versioning support, so currently we can not hardcode correct - # soname into executable. Probably we can add versioning support to - # collect2, so additional links can be useful in future. - if test "$aix_use_runtimelinking" = yes; then - # If using run time linking (on AIX 4.2 or later) use lib.so - # instead of lib.a to let people know that these are not - # typical AIX shared libraries. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - else - # We preserve .a as extension for shared libraries through AIX4.2 - # and later when we are not doing run time linking. - library_names_spec='${libname}${release}.a $libname.a' - soname_spec='${libname}${release}${shared_ext}$major' - fi - shlibpath_var=LIBPATH - fi - ;; - -amigaos*) - library_names_spec='$libname.ixlibrary $libname.a' - # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' - ;; - -beos*) - library_names_spec='${libname}${shared_ext}' - dynamic_linker="$host_os ld.so" - shlibpath_var=LIBRARY_PATH - ;; - -bsdi[45]*) - version_type=linux - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" - sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" - # the default ld.so.conf also contains /usr/contrib/lib and - # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow - # libtool to hard-code these into programs - ;; - -cygwin* | mingw* | pw32*) - version_type=windows - shrext_cmds=".dll" - need_version=no - need_lib_prefix=no - - case $GCC,$host_os in - yes,cygwin* | yes,mingw* | yes,pw32*) - library_names_spec='$libname.dll.a' - # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname~ - chmod a+x \$dldir/$dlname' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $rm \$dlpath' - shlibpath_overrides_runpath=yes - - case $host_os in - cygwin*) - # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" - ;; - mingw*) - # MinGW DLLs use traditional 'lib' prefix - soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then - # It is most probably a Windows format PATH printed by - # mingw gcc, but we are running on Cygwin. Gcc prints its search - # path with ; separators, and with drive letters. We can handle the - # drive letters (cygwin fileutils understands them), so leave them, - # especially as we might pass files found there to a mingw objdump, - # which wouldn't understand a cygwinified path. Ahh. - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi - ;; - pw32*) - # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - ;; - esac - ;; - - *) - library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' - ;; - esac - dynamic_linker='Win32 ld.exe' - # FIXME: first we should search . and the directory the executable is in - shlibpath_var=PATH - ;; - -darwin* | rhapsody*) - dynamic_linker="$host_os dyld" - version_type=darwin - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' - soname_spec='${libname}${release}${major}$shared_ext' - shlibpath_overrides_runpath=yes - shlibpath_var=DYLD_LIBRARY_PATH - shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' - # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. - if test "$GCC" = yes; then - sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` - else - sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' - fi - sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' - ;; - -dgux*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -freebsd1*) - dynamic_linker=no - ;; - -kfreebsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='GNU ld.so' - ;; - -freebsd* | dragonfly*) - # DragonFly does not have aout. When/if they implement a new - # versioning mechanism, adjust this. - if test -x /usr/bin/objformat; then - objformat=`/usr/bin/objformat` - else - case $host_os in - freebsd[123]*) objformat=aout ;; - *) objformat=elf ;; - esac - fi - version_type=freebsd-$objformat - case $version_type in - freebsd-elf*) - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - need_version=no - need_lib_prefix=no - ;; - freebsd-*) - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' - need_version=yes - ;; - esac - shlibpath_var=LD_LIBRARY_PATH - case $host_os in - freebsd2*) - shlibpath_overrides_runpath=yes - ;; - freebsd3.[01]* | freebsdelf3.[01]*) - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ - freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - freebsd*) # from 4.6 on - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - esac - ;; - -gnu*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - hardcode_into_libs=yes - ;; - -hpux9* | hpux10* | hpux11*) - # Give a soname corresponding to the major version so that dld.sl refuses to - # link against other versions. - version_type=sunos - need_lib_prefix=no - need_version=no - case $host_cpu in - ia64*) - shrext_cmds='.so' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.so" - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - if test "X$HPUX_IA64_MODE" = X32; then - sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" - else - sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" - fi - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - hppa*64*) - shrext_cmds='.sl' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.sl" - shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - *) - shrext_cmds='.sl' - dynamic_linker="$host_os dld.sl" - shlibpath_var=SHLIB_PATH - shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - ;; - esac - # HP-UX runs *really* slowly unless shared libraries are mode 555. - postinstall_cmds='chmod 555 $lib' - ;; - -interix3*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - -irix5* | irix6* | nonstopux*) - case $host_os in - nonstopux*) version_type=nonstopux ;; - *) - if test "$lt_cv_prog_gnu_ld" = yes; then - version_type=linux - else - version_type=irix - fi ;; - esac - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' - case $host_os in - irix5* | nonstopux*) - libsuff= shlibsuff= - ;; - *) - case $LD in # libtool.m4 will add one of these switches to LD - *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") - libsuff= shlibsuff= libmagic=32-bit;; - *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") - libsuff=32 shlibsuff=N32 libmagic=N32;; - *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") - libsuff=64 shlibsuff=64 libmagic=64-bit;; - *) libsuff= shlibsuff= libmagic=never-match;; - esac - ;; - esac - shlibpath_var=LD_LIBRARY${shlibsuff}_PATH - shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" - sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" - hardcode_into_libs=yes - ;; - -# No shared lib support for Linux oldld, aout, or coff. -linux*oldld* | linux*aout* | linux*coff*) - dynamic_linker=no - ;; - -# This must be Linux ELF. -linux*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. - hardcode_into_libs=yes - - # Append ld.so.conf contents to the search path - if test -f /etc/ld.so.conf; then - lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` - sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" - fi - - # We used to test for /lib/ld.so.1 and disable shared libraries on - # powerpc, because MkLinux only supported shared libraries with the - # GNU dynamic linker. Since this was broken with cross compilers, - # most powerpc-linux boxes support dynamic linking these days and - # people can always --disable-shared, the test was removed, and we - # assume the GNU/Linux dynamic linker is in use. - dynamic_linker='GNU/Linux ld.so' - ;; - -knetbsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='GNU ld.so' - ;; - -netbsd*) - version_type=sunos - need_lib_prefix=no - need_version=no - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - dynamic_linker='NetBSD (a.out) ld.so' - else - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='NetBSD ld.elf_so' - fi - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - -newsos6) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -nto-qnx*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -openbsd*) - version_type=sunos - sys_lib_dlsearch_path_spec="/usr/lib" - need_lib_prefix=no - # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. - case $host_os in - openbsd3.3 | openbsd3.3.*) need_version=yes ;; - *) need_version=no ;; - esac - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - shlibpath_var=LD_LIBRARY_PATH - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - case $host_os in - openbsd2.[89] | openbsd2.[89].*) - shlibpath_overrides_runpath=no - ;; - *) - shlibpath_overrides_runpath=yes - ;; - esac - else - shlibpath_overrides_runpath=yes - fi - ;; - -os2*) - libname_spec='$name' - shrext_cmds=".dll" - need_lib_prefix=no - library_names_spec='$libname${shared_ext} $libname.a' - dynamic_linker='OS/2 ld.exe' - shlibpath_var=LIBPATH - ;; - -osf3* | osf4* | osf5*) - version_type=osf - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" - ;; - -solaris*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - # ldd complains unless libraries are executable - postinstall_cmds='chmod +x $lib' - ;; - -sunos4*) - version_type=sunos - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - if test "$with_gnu_ld" = yes; then - need_lib_prefix=no - fi - need_version=yes - ;; - -sysv4 | sysv4.3*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - case $host_vendor in - sni) - shlibpath_overrides_runpath=no - need_lib_prefix=no - export_dynamic_flag_spec='${wl}-Blargedynsym' - runpath_var=LD_RUN_PATH - ;; - siemens) - need_lib_prefix=no - ;; - motorola) - need_lib_prefix=no - need_version=no - shlibpath_overrides_runpath=no - sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' - ;; - esac - ;; - -sysv4*MP*) - if test -d /usr/nec ;then - version_type=linux - library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' - soname_spec='$libname${shared_ext}.$major' - shlibpath_var=LD_LIBRARY_PATH - fi - ;; - -sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - version_type=freebsd-elf - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - hardcode_into_libs=yes - if test "$with_gnu_ld" = yes; then - sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' - shlibpath_overrides_runpath=no - else - sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' - shlibpath_overrides_runpath=yes - case $host_os in - sco3.2v5*) - sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" - ;; - esac - fi - sys_lib_dlsearch_path_spec='/usr/lib' - ;; - -uts4*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -*) - dynamic_linker=no - ;; -esac -echo "$as_me:$LINENO: result: $dynamic_linker" >&5 -echo "${ECHO_T}$dynamic_linker" >&6 -test "$dynamic_linker" = no && can_build_shared=no - -variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test "$GCC" = yes; then - variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" -fi - -echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 -echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6 -hardcode_action_F77= -if test -n "$hardcode_libdir_flag_spec_F77" || \ - test -n "$runpath_var_F77" || \ - test "X$hardcode_automatic_F77" = "Xyes" ; then - - # We can hardcode non-existant directories. - if test "$hardcode_direct_F77" != no && - # If the only mechanism to avoid hardcoding is shlibpath_var, we - # have to relink, otherwise we might link with an installed library - # when we should be linking with a yet-to-be-installed one - ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, F77)" != no && - test "$hardcode_minus_L_F77" != no; then - # Linking always hardcodes the temporary library directory. - hardcode_action_F77=relink - else - # We can link without hardcoding, and we can hardcode nonexisting dirs. - hardcode_action_F77=immediate - fi -else - # We cannot hardcode anything, or else we can only hardcode existing - # directories. - hardcode_action_F77=unsupported -fi -echo "$as_me:$LINENO: result: $hardcode_action_F77" >&5 -echo "${ECHO_T}$hardcode_action_F77" >&6 - -if test "$hardcode_action_F77" = relink; then - # Fast installation is not supported - enable_fast_install=no -elif test "$shlibpath_overrides_runpath" = yes || - test "$enable_shared" = no; then - # Fast installation is not necessary - enable_fast_install=needless -fi - - -# The else clause should only fire when bootstrapping the -# libtool distribution, otherwise you forgot to ship ltmain.sh -# with your package, and you will get complaints that there are -# no rules to generate ltmain.sh. -if test -f "$ltmain"; then - # See if we are running on zsh, and set the options which allow our commands through - # without removal of \ escapes. - if test -n "${ZSH_VERSION+set}" ; then - setopt NO_GLOB_SUBST - fi - # Now quote all the things that may contain metacharacters while being - # careful not to overquote the AC_SUBSTed values. We take copies of the - # variables and quote the copies for generation of the libtool script. - for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ - SED SHELL STRIP \ - libname_spec library_names_spec soname_spec extract_expsyms_cmds \ - old_striplib striplib file_magic_cmd finish_cmds finish_eval \ - deplibs_check_method reload_flag reload_cmds need_locks \ - lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ - lt_cv_sys_global_symbol_to_c_name_address \ - sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ - old_postinstall_cmds old_postuninstall_cmds \ - compiler_F77 \ - CC_F77 \ - LD_F77 \ - lt_prog_compiler_wl_F77 \ - lt_prog_compiler_pic_F77 \ - lt_prog_compiler_static_F77 \ - lt_prog_compiler_no_builtin_flag_F77 \ - export_dynamic_flag_spec_F77 \ - thread_safe_flag_spec_F77 \ - whole_archive_flag_spec_F77 \ - enable_shared_with_static_runtimes_F77 \ - old_archive_cmds_F77 \ - old_archive_from_new_cmds_F77 \ - predep_objects_F77 \ - postdep_objects_F77 \ - predeps_F77 \ - postdeps_F77 \ - compiler_lib_search_path_F77 \ - archive_cmds_F77 \ - archive_expsym_cmds_F77 \ - postinstall_cmds_F77 \ - postuninstall_cmds_F77 \ - old_archive_from_expsyms_cmds_F77 \ - allow_undefined_flag_F77 \ - no_undefined_flag_F77 \ - export_symbols_cmds_F77 \ - hardcode_libdir_flag_spec_F77 \ - hardcode_libdir_flag_spec_ld_F77 \ - hardcode_libdir_separator_F77 \ - hardcode_automatic_F77 \ - module_cmds_F77 \ - module_expsym_cmds_F77 \ - lt_cv_prog_compiler_c_o_F77 \ - exclude_expsyms_F77 \ - include_expsyms_F77; do - - case $var in - old_archive_cmds_F77 | \ - old_archive_from_new_cmds_F77 | \ - archive_cmds_F77 | \ - archive_expsym_cmds_F77 | \ - module_cmds_F77 | \ - module_expsym_cmds_F77 | \ - old_archive_from_expsyms_cmds_F77 | \ - export_symbols_cmds_F77 | \ - extract_expsyms_cmds | reload_cmds | finish_cmds | \ - postinstall_cmds | postuninstall_cmds | \ - old_postinstall_cmds | old_postuninstall_cmds | \ - sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) - # Double-quote double-evaled strings. - eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" - ;; - *) - eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" - ;; - esac - done - - case $lt_echo in - *'\$0 --fallback-echo"') - lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` - ;; - esac - -cfgfile="$ofile" - - cat <<__EOF__ >> "$cfgfile" -# ### BEGIN LIBTOOL TAG CONFIG: $tagname - -# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: - -# Shell to use when invoking shell scripts. -SHELL=$lt_SHELL - -# Whether or not to build shared libraries. -build_libtool_libs=$enable_shared - -# Whether or not to build static libraries. -build_old_libs=$enable_static - -# Whether or not to add -lc for building shared libraries. -build_libtool_need_lc=$archive_cmds_need_lc_F77 - -# Whether or not to disallow shared libs when runtime libs are static -allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_F77 - -# Whether or not to optimize for fast installation. -fast_install=$enable_fast_install - -# The host system. -host_alias=$host_alias -host=$host -host_os=$host_os - -# The build system. -build_alias=$build_alias -build=$build -build_os=$build_os - -# An echo program that does not interpret backslashes. -echo=$lt_echo - -# The archiver. -AR=$lt_AR -AR_FLAGS=$lt_AR_FLAGS - -# A C compiler. -LTCC=$lt_LTCC - -# LTCC compiler flags. -LTCFLAGS=$lt_LTCFLAGS - -# A language-specific compiler. -CC=$lt_compiler_F77 - -# Is the compiler the GNU C compiler? -with_gcc=$GCC_F77 - -# An ERE matcher. -EGREP=$lt_EGREP - -# The linker used to build libraries. -LD=$lt_LD_F77 - -# Whether we need hard or soft links. -LN_S=$lt_LN_S - -# A BSD-compatible nm program. -NM=$lt_NM - -# A symbol stripping program -STRIP=$lt_STRIP - -# Used to examine libraries when file_magic_cmd begins "file" -MAGIC_CMD=$MAGIC_CMD - -# Used on cygwin: DLL creation program. -DLLTOOL="$DLLTOOL" - -# Used on cygwin: object dumper. -OBJDUMP="$OBJDUMP" - -# Used on cygwin: assembler. -AS="$AS" - -# The name of the directory that contains temporary libtool files. -objdir=$objdir - -# How to create reloadable object files. -reload_flag=$lt_reload_flag -reload_cmds=$lt_reload_cmds - -# How to pass a linker flag through the compiler. -wl=$lt_lt_prog_compiler_wl_F77 - -# Object file suffix (normally "o"). -objext="$ac_objext" - -# Old archive suffix (normally "a"). -libext="$libext" - -# Shared library suffix (normally ".so"). -shrext_cmds='$shrext_cmds' - -# Executable file suffix (normally ""). -exeext="$exeext" - -# Additional compiler flags for building library objects. -pic_flag=$lt_lt_prog_compiler_pic_F77 -pic_mode=$pic_mode - -# What is the maximum length of a command? -max_cmd_len=$lt_cv_sys_max_cmd_len - -# Does compiler simultaneously support -c and -o options? -compiler_c_o=$lt_lt_cv_prog_compiler_c_o_F77 - -# Must we lock files when doing compilation? -need_locks=$lt_need_locks - -# Do we need the lib prefix for modules? -need_lib_prefix=$need_lib_prefix - -# Do we need a version for libraries? -need_version=$need_version - -# Whether dlopen is supported. -dlopen_support=$enable_dlopen - -# Whether dlopen of programs is supported. -dlopen_self=$enable_dlopen_self - -# Whether dlopen of statically linked programs is supported. -dlopen_self_static=$enable_dlopen_self_static - -# Compiler flag to prevent dynamic linking. -link_static_flag=$lt_lt_prog_compiler_static_F77 - -# Compiler flag to turn off builtin functions. -no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_F77 - -# Compiler flag to allow reflexive dlopens. -export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_F77 - -# Compiler flag to generate shared objects directly from archives. -whole_archive_flag_spec=$lt_whole_archive_flag_spec_F77 - -# Compiler flag to generate thread-safe objects. -thread_safe_flag_spec=$lt_thread_safe_flag_spec_F77 - -# Library versioning type. -version_type=$version_type - -# Format of library name prefix. -libname_spec=$lt_libname_spec - -# List of archive names. First name is the real one, the rest are links. -# The last name is the one that the linker finds with -lNAME. -library_names_spec=$lt_library_names_spec - -# The coded name of the library, if different from the real name. -soname_spec=$lt_soname_spec - -# Commands used to build and install an old-style archive. -RANLIB=$lt_RANLIB -old_archive_cmds=$lt_old_archive_cmds_F77 -old_postinstall_cmds=$lt_old_postinstall_cmds -old_postuninstall_cmds=$lt_old_postuninstall_cmds - -# Create an old-style archive from a shared archive. -old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_F77 - -# Create a temporary old-style archive to link instead of a shared archive. -old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_F77 - -# Commands used to build and install a shared archive. -archive_cmds=$lt_archive_cmds_F77 -archive_expsym_cmds=$lt_archive_expsym_cmds_F77 -postinstall_cmds=$lt_postinstall_cmds -postuninstall_cmds=$lt_postuninstall_cmds - -# Commands used to build a loadable module (assumed same as above if empty) -module_cmds=$lt_module_cmds_F77 -module_expsym_cmds=$lt_module_expsym_cmds_F77 - -# Commands to strip libraries. -old_striplib=$lt_old_striplib -striplib=$lt_striplib - -# Dependencies to place before the objects being linked to create a -# shared library. -predep_objects=$lt_predep_objects_F77 - -# Dependencies to place after the objects being linked to create a -# shared library. -postdep_objects=$lt_postdep_objects_F77 - -# Dependencies to place before the objects being linked to create a -# shared library. -predeps=$lt_predeps_F77 - -# Dependencies to place after the objects being linked to create a -# shared library. -postdeps=$lt_postdeps_F77 - -# The library search path used internally by the compiler when linking -# a shared library. -compiler_lib_search_path=$lt_compiler_lib_search_path_F77 - -# Method to check whether dependent libraries are shared objects. -deplibs_check_method=$lt_deplibs_check_method - -# Command to use when deplibs_check_method == file_magic. -file_magic_cmd=$lt_file_magic_cmd - -# Flag that allows shared libraries with undefined symbols to be built. -allow_undefined_flag=$lt_allow_undefined_flag_F77 - -# Flag that forces no undefined symbols. -no_undefined_flag=$lt_no_undefined_flag_F77 - -# Commands used to finish a libtool library installation in a directory. -finish_cmds=$lt_finish_cmds - -# Same as above, but a single script fragment to be evaled but not shown. -finish_eval=$lt_finish_eval - -# Take the output of nm and produce a listing of raw symbols and C names. -global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe - -# Transform the output of nm in a proper C declaration -global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl - -# Transform the output of nm in a C name address pair -global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address - -# This is the shared library runtime path variable. -runpath_var=$runpath_var - -# This is the shared library path variable. -shlibpath_var=$shlibpath_var - -# Is shlibpath searched before the hard-coded library search path? -shlibpath_overrides_runpath=$shlibpath_overrides_runpath - -# How to hardcode a shared library path into an executable. -hardcode_action=$hardcode_action_F77 - -# Whether we should hardcode library paths into libraries. -hardcode_into_libs=$hardcode_into_libs - -# Flag to hardcode \$libdir into a binary during linking. -# This must work even if \$libdir does not exist. -hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_F77 - -# If ld is used when linking, flag to hardcode \$libdir into -# a binary during linking. This must work even if \$libdir does -# not exist. -hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_F77 - -# Whether we need a single -rpath flag with a separated argument. -hardcode_libdir_separator=$lt_hardcode_libdir_separator_F77 - -# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the -# resulting binary. -hardcode_direct=$hardcode_direct_F77 - -# Set to yes if using the -LDIR flag during linking hardcodes DIR into the -# resulting binary. -hardcode_minus_L=$hardcode_minus_L_F77 - -# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into -# the resulting binary. -hardcode_shlibpath_var=$hardcode_shlibpath_var_F77 - -# Set to yes if building a shared library automatically hardcodes DIR into the library -# and all subsequent libraries and executables linked against it. -hardcode_automatic=$hardcode_automatic_F77 - -# Variables whose values should be saved in libtool wrapper scripts and -# restored at relink time. -variables_saved_for_relink="$variables_saved_for_relink" - -# Whether libtool must link a program against all its dependency libraries. -link_all_deplibs=$link_all_deplibs_F77 - -# Compile-time system search path for libraries -sys_lib_search_path_spec=$lt_sys_lib_search_path_spec - -# Run-time system search path for libraries -sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec - -# Fix the shell variable \$srcfile for the compiler. -fix_srcfile_path="$fix_srcfile_path_F77" - -# Set to yes if exported symbols are required. -always_export_symbols=$always_export_symbols_F77 - -# The commands to list exported symbols. -export_symbols_cmds=$lt_export_symbols_cmds_F77 - -# The commands to extract the exported symbol list from a shared archive. -extract_expsyms_cmds=$lt_extract_expsyms_cmds - -# Symbols that should not be listed in the preloaded symbols. -exclude_expsyms=$lt_exclude_expsyms_F77 - -# Symbols that must always be exported. -include_expsyms=$lt_include_expsyms_F77 - -# ### END LIBTOOL TAG CONFIG: $tagname - -__EOF__ - - -else - # If there is no Makefile yet, we rely on a make rule to execute - # `config.status --recheck' to rerun these tests and create the - # libtool script then. - ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` - if test -f "$ltmain_in"; then - test -f Makefile && make "$ltmain" - fi -fi - - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -CC="$lt_save_CC" - - else - tagname="" - fi - ;; - - GCJ) - if test -n "$GCJ" && test "X$GCJ" != "Xno"; then - - - -# Source file extension for Java test sources. -ac_ext=java - -# Object file extension for compiled Java test sources. -objext=o -objext_GCJ=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code="class foo {}\n" - -# Code to be used in simple link tests -lt_simple_link_test_code='public class conftest { public static void main(String[] argv) {}; }\n' - -# ltmain only uses $CC for tagged configurations so make sure $CC is set. - -# If no C compiler was specified, use CC. -LTCC=${LTCC-"$CC"} - -# If no C compiler flags were specified, use CFLAGS. -LTCFLAGS=${LTCFLAGS-"$CFLAGS"} - -# Allow CC to be a program name with arguments. -compiler=$CC - - -# save warnings/boilerplate of simple test code -ac_outfile=conftest.$ac_objext -printf "$lt_simple_compile_test_code" >conftest.$ac_ext -eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_compiler_boilerplate=`cat conftest.err` -$rm conftest* - -ac_outfile=conftest.$ac_objext -printf "$lt_simple_link_test_code" >conftest.$ac_ext -eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_linker_boilerplate=`cat conftest.err` -$rm conftest* - - -# Allow CC to be a program name with arguments. -lt_save_CC="$CC" -CC=${GCJ-"gcj"} -compiler=$CC -compiler_GCJ=$CC -for cc_temp in $compiler""; do - case $cc_temp in - compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; - distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; - \-*) ;; - *) break;; - esac -done -cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` - - -# GCJ did not exist at the time GCC didn't implicitly link libc in. -archive_cmds_need_lc_GCJ=no - -old_archive_cmds_GCJ=$old_archive_cmds - -## CAVEAT EMPTOR: -## There is no encapsulation within the following macros, do not change -## the running order or otherwise move them around unless you know exactly -## what you are doing... - -lt_prog_compiler_no_builtin_flag_GCJ= - -if test "$GCC" = yes; then - lt_prog_compiler_no_builtin_flag_GCJ=' -fno-builtin' - - -echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 -echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6 -if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_cv_prog_compiler_rtti_exceptions=no - ac_outfile=conftest.$ac_objext - printf "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="-fno-rtti -fno-exceptions" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - # The option is referenced via a variable to avoid confusing sed. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:15509: $lt_compile\"" >&5) - (eval "$lt_compile" 2>conftest.err) - ac_status=$? - cat conftest.err >&5 - echo "$as_me:15513: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s "$ac_outfile"; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings other than the usual output. - $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then - lt_cv_prog_compiler_rtti_exceptions=yes - fi - fi - $rm conftest* - -fi -echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 -echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6 - -if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then - lt_prog_compiler_no_builtin_flag_GCJ="$lt_prog_compiler_no_builtin_flag_GCJ -fno-rtti -fno-exceptions" -else - : -fi - -fi - -lt_prog_compiler_wl_GCJ= -lt_prog_compiler_pic_GCJ= -lt_prog_compiler_static_GCJ= - -echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 -echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 - - if test "$GCC" = yes; then - lt_prog_compiler_wl_GCJ='-Wl,' - lt_prog_compiler_static_GCJ='-static' - - case $host_os in - aix*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static_GCJ='-Bstatic' - fi - ;; - - amigaos*) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. - lt_prog_compiler_pic_GCJ='-m68020 -resident32 -malways-restore-a4' - ;; - - beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - - mingw* | pw32* | os2*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - lt_prog_compiler_pic_GCJ='-DDLL_EXPORT' - ;; - - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - lt_prog_compiler_pic_GCJ='-fno-common' - ;; - - interix3*) - # Interix 3.x gcc -fpic/-fPIC options generate broken code. - # Instead, we relocate shared libraries at runtime. - ;; - - msdosdjgpp*) - # Just because we use GCC doesn't mean we suddenly get shared libraries - # on systems that don't support them. - lt_prog_compiler_can_build_shared_GCJ=no - enable_shared=no - ;; - - sysv4*MP*) - if test -d /usr/nec; then - lt_prog_compiler_pic_GCJ=-Kconform_pic - fi - ;; - - hpux*) - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case $host_cpu in - hppa*64*|ia64*) - # +Z the default - ;; - *) - lt_prog_compiler_pic_GCJ='-fPIC' - ;; - esac - ;; - - *) - lt_prog_compiler_pic_GCJ='-fPIC' - ;; - esac - else - # PORTME Check for flag to pass linker flags through the system compiler. - case $host_os in - aix*) - lt_prog_compiler_wl_GCJ='-Wl,' - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - lt_prog_compiler_static_GCJ='-Bstatic' - else - lt_prog_compiler_static_GCJ='-bnso -bI:/lib/syscalls.exp' - fi - ;; - darwin*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - case $cc_basename in - xlc*) - lt_prog_compiler_pic_GCJ='-qnocommon' - lt_prog_compiler_wl_GCJ='-Wl,' - ;; - esac - ;; - - mingw* | pw32* | os2*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - lt_prog_compiler_pic_GCJ='-DDLL_EXPORT' - ;; - - hpux9* | hpux10* | hpux11*) - lt_prog_compiler_wl_GCJ='-Wl,' - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case $host_cpu in - hppa*64*|ia64*) - # +Z the default - ;; - *) - lt_prog_compiler_pic_GCJ='+Z' - ;; - esac - # Is there a better lt_prog_compiler_static that works with the bundled CC? - lt_prog_compiler_static_GCJ='${wl}-a ${wl}archive' - ;; - - irix5* | irix6* | nonstopux*) - lt_prog_compiler_wl_GCJ='-Wl,' - # PIC (with -KPIC) is the default. - lt_prog_compiler_static_GCJ='-non_shared' - ;; - - newsos6) - lt_prog_compiler_pic_GCJ='-KPIC' - lt_prog_compiler_static_GCJ='-Bstatic' - ;; - - linux*) - case $cc_basename in - icc* | ecc*) - lt_prog_compiler_wl_GCJ='-Wl,' - lt_prog_compiler_pic_GCJ='-KPIC' - lt_prog_compiler_static_GCJ='-static' - ;; - pgcc* | pgf77* | pgf90* | pgf95*) - # Portland Group compilers (*not* the Pentium gcc compiler, - # which looks to be a dead project) - lt_prog_compiler_wl_GCJ='-Wl,' - lt_prog_compiler_pic_GCJ='-fpic' - lt_prog_compiler_static_GCJ='-Bstatic' - ;; - ccc*) - lt_prog_compiler_wl_GCJ='-Wl,' - # All Alpha code is PIC. - lt_prog_compiler_static_GCJ='-non_shared' - ;; - esac - ;; - - osf3* | osf4* | osf5*) - lt_prog_compiler_wl_GCJ='-Wl,' - # All OSF/1 code is PIC. - lt_prog_compiler_static_GCJ='-non_shared' - ;; - - solaris*) - lt_prog_compiler_pic_GCJ='-KPIC' - lt_prog_compiler_static_GCJ='-Bstatic' - case $cc_basename in - f77* | f90* | f95*) - lt_prog_compiler_wl_GCJ='-Qoption ld ';; - *) - lt_prog_compiler_wl_GCJ='-Wl,';; - esac - ;; - - sunos4*) - lt_prog_compiler_wl_GCJ='-Qoption ld ' - lt_prog_compiler_pic_GCJ='-PIC' - lt_prog_compiler_static_GCJ='-Bstatic' - ;; - - sysv4 | sysv4.2uw2* | sysv4.3*) - lt_prog_compiler_wl_GCJ='-Wl,' - lt_prog_compiler_pic_GCJ='-KPIC' - lt_prog_compiler_static_GCJ='-Bstatic' - ;; - - sysv4*MP*) - if test -d /usr/nec ;then - lt_prog_compiler_pic_GCJ='-Kconform_pic' - lt_prog_compiler_static_GCJ='-Bstatic' - fi - ;; - - sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) - lt_prog_compiler_wl_GCJ='-Wl,' - lt_prog_compiler_pic_GCJ='-KPIC' - lt_prog_compiler_static_GCJ='-Bstatic' - ;; - - unicos*) - lt_prog_compiler_wl_GCJ='-Wl,' - lt_prog_compiler_can_build_shared_GCJ=no - ;; - - uts4*) - lt_prog_compiler_pic_GCJ='-pic' - lt_prog_compiler_static_GCJ='-Bstatic' - ;; - - *) - lt_prog_compiler_can_build_shared_GCJ=no - ;; - esac - fi - -echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_GCJ" >&5 -echo "${ECHO_T}$lt_prog_compiler_pic_GCJ" >&6 - -# -# Check to make sure the PIC flag actually works. -# -if test -n "$lt_prog_compiler_pic_GCJ"; then - -echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works" >&5 -echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works... $ECHO_C" >&6 -if test "${lt_prog_compiler_pic_works_GCJ+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_prog_compiler_pic_works_GCJ=no - ac_outfile=conftest.$ac_objext - printf "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$lt_prog_compiler_pic_GCJ" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - # The option is referenced via a variable to avoid confusing sed. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:15777: $lt_compile\"" >&5) - (eval "$lt_compile" 2>conftest.err) - ac_status=$? - cat conftest.err >&5 - echo "$as_me:15781: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s "$ac_outfile"; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings other than the usual output. - $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then - lt_prog_compiler_pic_works_GCJ=yes - fi - fi - $rm conftest* - -fi -echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_GCJ" >&5 -echo "${ECHO_T}$lt_prog_compiler_pic_works_GCJ" >&6 - -if test x"$lt_prog_compiler_pic_works_GCJ" = xyes; then - case $lt_prog_compiler_pic_GCJ in - "" | " "*) ;; - *) lt_prog_compiler_pic_GCJ=" $lt_prog_compiler_pic_GCJ" ;; - esac -else - lt_prog_compiler_pic_GCJ= - lt_prog_compiler_can_build_shared_GCJ=no -fi - -fi -case $host_os in - # For platforms which do not support PIC, -DPIC is meaningless: - *djgpp*) - lt_prog_compiler_pic_GCJ= - ;; - *) - lt_prog_compiler_pic_GCJ="$lt_prog_compiler_pic_GCJ" - ;; -esac - -# -# Check to make sure the static flag actually works. -# -wl=$lt_prog_compiler_wl_GCJ eval lt_tmp_static_flag=\"$lt_prog_compiler_static_GCJ\" -echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 -echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6 -if test "${lt_prog_compiler_static_works_GCJ+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_prog_compiler_static_works_GCJ=no - save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS $lt_tmp_static_flag" - printf "$lt_simple_link_test_code" > conftest.$ac_ext - if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then - # The linker can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s conftest.err; then - # Append any errors to the config.log. - cat conftest.err 1>&5 - $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if diff conftest.exp conftest.er2 >/dev/null; then - lt_prog_compiler_static_works_GCJ=yes - fi - else - lt_prog_compiler_static_works_GCJ=yes - fi - fi - $rm conftest* - LDFLAGS="$save_LDFLAGS" - -fi -echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_GCJ" >&5 -echo "${ECHO_T}$lt_prog_compiler_static_works_GCJ" >&6 - -if test x"$lt_prog_compiler_static_works_GCJ" = xyes; then - : -else - lt_prog_compiler_static_GCJ= -fi - - -echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 -echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6 -if test "${lt_cv_prog_compiler_c_o_GCJ+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_cv_prog_compiler_c_o_GCJ=no - $rm -r conftest 2>/dev/null - mkdir conftest - cd conftest - mkdir out - printf "$lt_simple_compile_test_code" > conftest.$ac_ext - - lt_compiler_flag="-o out/conftest2.$ac_objext" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:15881: $lt_compile\"" >&5) - (eval "$lt_compile" 2>out/conftest.err) - ac_status=$? - cat out/conftest.err >&5 - echo "$as_me:15885: \$? = $ac_status" >&5 - if (exit $ac_status) && test -s out/conftest2.$ac_objext - then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp - $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 - if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then - lt_cv_prog_compiler_c_o_GCJ=yes - fi - fi - chmod u+w . 2>&5 - $rm conftest* - # SGI C++ compiler will create directory out/ii_files/ for - # template instantiation - test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files - $rm out/* && rmdir out - cd .. - rmdir conftest - $rm conftest* - -fi -echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_GCJ" >&5 -echo "${ECHO_T}$lt_cv_prog_compiler_c_o_GCJ" >&6 - - -hard_links="nottested" -if test "$lt_cv_prog_compiler_c_o_GCJ" = no && test "$need_locks" != no; then - # do not overwrite the value of need_locks provided by the user - echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 -echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6 - hard_links=yes - $rm conftest* - ln conftest.a conftest.b 2>/dev/null && hard_links=no - touch conftest.a - ln conftest.a conftest.b 2>&5 || hard_links=no - ln conftest.a conftest.b 2>/dev/null && hard_links=no - echo "$as_me:$LINENO: result: $hard_links" >&5 -echo "${ECHO_T}$hard_links" >&6 - if test "$hard_links" = no; then - { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 -echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} - need_locks=warn - fi -else - need_locks=no -fi - -echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 -echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6 - - runpath_var= - allow_undefined_flag_GCJ= - enable_shared_with_static_runtimes_GCJ=no - archive_cmds_GCJ= - archive_expsym_cmds_GCJ= - old_archive_From_new_cmds_GCJ= - old_archive_from_expsyms_cmds_GCJ= - export_dynamic_flag_spec_GCJ= - whole_archive_flag_spec_GCJ= - thread_safe_flag_spec_GCJ= - hardcode_libdir_flag_spec_GCJ= - hardcode_libdir_flag_spec_ld_GCJ= - hardcode_libdir_separator_GCJ= - hardcode_direct_GCJ=no - hardcode_minus_L_GCJ=no - hardcode_shlibpath_var_GCJ=unsupported - link_all_deplibs_GCJ=unknown - hardcode_automatic_GCJ=no - module_cmds_GCJ= - module_expsym_cmds_GCJ= - always_export_symbols_GCJ=no - export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - # include_expsyms should be a list of space-separated symbols to be *always* - # included in the symbol list - include_expsyms_GCJ= - # exclude_expsyms can be an extended regexp of symbols to exclude - # it will be wrapped by ` (' and `)$', so one must not match beginning or - # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', - # as well as any symbol that contains `d'. - exclude_expsyms_GCJ="_GLOBAL_OFFSET_TABLE_" - # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out - # platforms (ab)use it in PIC code, but their linkers get confused if - # the symbol is explicitly referenced. Since portable code cannot - # rely on this symbol name, it's probably fine to never include it in - # preloaded symbol tables. - extract_expsyms_cmds= - # Just being paranoid about ensuring that cc_basename is set. - for cc_temp in $compiler""; do - case $cc_temp in - compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; - distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; - \-*) ;; - *) break;; - esac -done -cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` - - case $host_os in - cygwin* | mingw* | pw32*) - # FIXME: the MSVC++ port hasn't been tested in a loooong time - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - if test "$GCC" != yes; then - with_gnu_ld=no - fi - ;; - interix*) - # we just hope/assume this is gcc and not c89 (= MSVC++) - with_gnu_ld=yes - ;; - openbsd*) - with_gnu_ld=no - ;; - esac - - ld_shlibs_GCJ=yes - if test "$with_gnu_ld" = yes; then - # If archive_cmds runs LD, not CC, wlarc should be empty - wlarc='${wl}' - - # Set some defaults for GNU ld with shared library support. These - # are reset later if shared libraries are not supported. Putting them - # here allows them to be overridden if necessary. - runpath_var=LD_RUN_PATH - hardcode_libdir_flag_spec_GCJ='${wl}--rpath ${wl}$libdir' - export_dynamic_flag_spec_GCJ='${wl}--export-dynamic' - # ancient GNU ld didn't support --whole-archive et. al. - if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then - whole_archive_flag_spec_GCJ="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - else - whole_archive_flag_spec_GCJ= - fi - supports_anon_versioning=no - case `$LD -v 2>/dev/null` in - *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 - *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... - *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... - *\ 2.11.*) ;; # other 2.11 versions - *) supports_anon_versioning=yes ;; - esac - - # See if GNU ld supports shared libraries. - case $host_os in - aix3* | aix4* | aix5*) - # On AIX/PPC, the GNU linker is very broken - if test "$host_cpu" != ia64; then - ld_shlibs_GCJ=no - cat <&2 - -*** Warning: the GNU linker, at least up to release 2.9.1, is reported -*** to be unable to reliably create shared libraries on AIX. -*** Therefore, libtool is disabling shared libraries support. If you -*** really care for shared libraries, you may want to modify your PATH -*** so that a non-GNU linker is found, and then restart. - -EOF - fi - ;; - - amigaos*) - archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - hardcode_libdir_flag_spec_GCJ='-L$libdir' - hardcode_minus_L_GCJ=yes - - # Samuel A. Falvo II reports - # that the semantics of dynamic libraries on AmigaOS, at least up - # to version 4, is to share data among multiple programs linked - # with the same dynamic library. Since this doesn't match the - # behavior of shared libraries on other platforms, we can't use - # them. - ld_shlibs_GCJ=no - ;; - - beos*) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - allow_undefined_flag_GCJ=unsupported - # Joseph Beckenbach says some releases of gcc - # support --undefined. This deserves some investigation. FIXME - archive_cmds_GCJ='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - else - ld_shlibs_GCJ=no - fi - ;; - - cygwin* | mingw* | pw32*) - # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, GCJ) is actually meaningless, - # as there is no search path for DLLs. - hardcode_libdir_flag_spec_GCJ='-L$libdir' - allow_undefined_flag_GCJ=unsupported - always_export_symbols_GCJ=no - enable_shared_with_static_runtimes_GCJ=yes - export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' - - if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then - archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - archive_expsym_cmds_GCJ='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - else - ld_shlibs_GCJ=no - fi - ;; - - interix3*) - hardcode_direct_GCJ=no - hardcode_shlibpath_var_GCJ=no - hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' - export_dynamic_flag_spec_GCJ='${wl}-E' - # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. - # Instead, shared libraries are loaded at an image base (0x10000000 by - # default) and relocated if they conflict, which is a slow very memory - # consuming and fragmenting process. To avoid this, we pick a random, - # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link - # time. Moving up from 0x10000000 also allows more sbrk(2) space. - archive_cmds_GCJ='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - archive_expsym_cmds_GCJ='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - ;; - - linux*) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - tmp_addflag= - case $cc_basename,$host_cpu in - pgcc*) # Portland Group C compiler - whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' - tmp_addflag=' $pic_flag' - ;; - pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers - whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' - tmp_addflag=' $pic_flag -Mnomain' ;; - ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 - tmp_addflag=' -i_dynamic' ;; - efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 - tmp_addflag=' -i_dynamic -nofor_main' ;; - ifc* | ifort*) # Intel Fortran compiler - tmp_addflag=' -nofor_main' ;; - esac - archive_cmds_GCJ='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - - if test $supports_anon_versioning = yes; then - archive_expsym_cmds_GCJ='$echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - $echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' - fi - else - ld_shlibs_GCJ=no - fi - ;; - - netbsd*) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - archive_cmds_GCJ='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' - wlarc= - else - archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - fi - ;; - - solaris*) - if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then - ld_shlibs_GCJ=no - cat <&2 - -*** Warning: The releases 2.8.* of the GNU linker cannot reliably -*** create shared libraries on Solaris systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.9.1 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -EOF - elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - ld_shlibs_GCJ=no - fi - ;; - - sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) - case `$LD -v 2>&1` in - *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) - ld_shlibs_GCJ=no - cat <<_LT_EOF 1>&2 - -*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not -*** reliably create shared libraries on SCO systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.16.91.0.3 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -_LT_EOF - ;; - *) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' - archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' - archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' - else - ld_shlibs_GCJ=no - fi - ;; - esac - ;; - - sunos4*) - archive_cmds_GCJ='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' - wlarc= - hardcode_direct_GCJ=yes - hardcode_shlibpath_var_GCJ=no - ;; - - *) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - ld_shlibs_GCJ=no - fi - ;; - esac - - if test "$ld_shlibs_GCJ" = no; then - runpath_var= - hardcode_libdir_flag_spec_GCJ= - export_dynamic_flag_spec_GCJ= - whole_archive_flag_spec_GCJ= - fi - else - # PORTME fill in a description of your system's linker (not GNU ld) - case $host_os in - aix3*) - allow_undefined_flag_GCJ=unsupported - always_export_symbols_GCJ=yes - archive_expsym_cmds_GCJ='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' - # Note: this linker hardcodes the directories in LIBPATH if there - # are no directories specified by -L. - hardcode_minus_L_GCJ=yes - if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then - # Neither direct hardcoding nor static linking is supported with a - # broken collect2. - hardcode_direct_GCJ=unsupported - fi - ;; - - aix4* | aix5*) - if test "$host_cpu" = ia64; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag="" - else - # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - if $NM -V 2>&1 | grep 'GNU' > /dev/null; then - export_symbols_cmds_GCJ='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' - else - export_symbols_cmds_GCJ='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' - fi - aix_use_runtimelinking=no - - # Test if we are trying to use run time linking or normal - # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. - case $host_os in aix4.[23]|aix4.[23].*|aix5*) - for ld_flag in $LDFLAGS; do - if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then - aix_use_runtimelinking=yes - break - fi - done - ;; - esac - - exp_sym_flag='-bexport' - no_entry_flag='-bnoentry' - fi - - # When large executables or shared objects are built, AIX ld can - # have problems creating the table of contents. If linking a library - # or program results in "error TOC overflow" add -mminimal-toc to - # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not - # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. - - archive_cmds_GCJ='' - hardcode_direct_GCJ=yes - hardcode_libdir_separator_GCJ=':' - link_all_deplibs_GCJ=yes - - if test "$GCC" = yes; then - case $host_os in aix4.[012]|aix4.[012].*) - # We only want to do this on AIX 4.2 and lower, the check - # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` - if test -f "$collect2name" && \ - strings "$collect2name" | grep resolve_lib_name >/dev/null - then - # We have reworked collect2 - hardcode_direct_GCJ=yes - else - # We have old collect2 - hardcode_direct_GCJ=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - hardcode_minus_L_GCJ=yes - hardcode_libdir_flag_spec_GCJ='-L$libdir' - hardcode_libdir_separator_GCJ= - fi - ;; - esac - shared_flag='-shared' - if test "$aix_use_runtimelinking" = yes; then - shared_flag="$shared_flag "'${wl}-G' - fi - else - # not using gcc - if test "$host_cpu" = ia64; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' - else - shared_flag='${wl}-bM:SRE' - fi - fi - fi - - # It seems that -bexpall does not export symbols beginning with - # underscore (_), so it is better to generate a list of symbols to export. - always_export_symbols_GCJ=yes - if test "$aix_use_runtimelinking" = yes; then - # Warning - without using the other runtime loading flags (-brtl), - # -berok will link without error, but may produce a broken library. - allow_undefined_flag_GCJ='-berok' - # Determine the default libpath from the value encoded in an empty executable. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'`; fi -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi - - hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath" - archive_expsym_cmds_GCJ="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" - else - if test "$host_cpu" = ia64; then - hardcode_libdir_flag_spec_GCJ='${wl}-R $libdir:/usr/lib:/lib' - allow_undefined_flag_GCJ="-z nodefs" - archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" - else - # Determine the default libpath from the value encoded in an empty executable. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'`; fi -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi - - hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath" - # Warning - without using the other run time loading flags, - # -berok will link without error, but may produce a broken library. - no_undefined_flag_GCJ=' ${wl}-bernotok' - allow_undefined_flag_GCJ=' ${wl}-berok' - # Exported symbols can be pulled into shared objects from archives - whole_archive_flag_spec_GCJ='$convenience' - archive_cmds_need_lc_GCJ=yes - # This is similar to how AIX traditionally builds its shared libraries. - archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' - fi - fi - ;; - - amigaos*) - archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - hardcode_libdir_flag_spec_GCJ='-L$libdir' - hardcode_minus_L_GCJ=yes - # see comment about different semantics on the GNU ld section - ld_shlibs_GCJ=no - ;; - - bsdi[45]*) - export_dynamic_flag_spec_GCJ=-rdynamic - ;; - - cygwin* | mingw* | pw32*) - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - # hardcode_libdir_flag_spec is actually meaningless, as there is - # no search path for DLLs. - hardcode_libdir_flag_spec_GCJ=' ' - allow_undefined_flag_GCJ=unsupported - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" - # FIXME: Setting linknames here is a bad hack. - archive_cmds_GCJ='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' - # The linker will automatically build a .lib file if we build a DLL. - old_archive_From_new_cmds_GCJ='true' - # FIXME: Should let the user specify the lib program. - old_archive_cmds_GCJ='lib /OUT:$oldlib$oldobjs$old_deplibs' - fix_srcfile_path_GCJ='`cygpath -w "$srcfile"`' - enable_shared_with_static_runtimes_GCJ=yes - ;; - - darwin* | rhapsody*) - case $host_os in - rhapsody* | darwin1.[012]) - allow_undefined_flag_GCJ='${wl}-undefined ${wl}suppress' - ;; - *) # Darwin 1.3 on - if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then - allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' - else - case ${MACOSX_DEPLOYMENT_TARGET} in - 10.[012]) - allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' - ;; - 10.*) - allow_undefined_flag_GCJ='${wl}-undefined ${wl}dynamic_lookup' - ;; - esac - fi - ;; - esac - archive_cmds_need_lc_GCJ=no - hardcode_direct_GCJ=no - hardcode_automatic_GCJ=yes - hardcode_shlibpath_var_GCJ=unsupported - whole_archive_flag_spec_GCJ='' - link_all_deplibs_GCJ=yes - if test "$GCC" = yes ; then - output_verbose_link_cmd='echo' - archive_cmds_GCJ='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds - archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - else - case $cc_basename in - xlc*) - output_verbose_link_cmd='echo' - archive_cmds_GCJ='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' - module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds - archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - ;; - *) - ld_shlibs_GCJ=no - ;; - esac - fi - ;; - - dgux*) - archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec_GCJ='-L$libdir' - hardcode_shlibpath_var_GCJ=no - ;; - - freebsd1*) - ld_shlibs_GCJ=no - ;; - - # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor - # support. Future versions do this automatically, but an explicit c++rt0.o - # does not break anything, and helps significantly (at the cost of a little - # extra space). - freebsd2.2*) - archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' - hardcode_libdir_flag_spec_GCJ='-R$libdir' - hardcode_direct_GCJ=yes - hardcode_shlibpath_var_GCJ=no - ;; - - # Unfortunately, older versions of FreeBSD 2 do not have this feature. - freebsd2*) - archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct_GCJ=yes - hardcode_minus_L_GCJ=yes - hardcode_shlibpath_var_GCJ=no - ;; - - # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd* | kfreebsd*-gnu | dragonfly*) - archive_cmds_GCJ='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec_GCJ='-R$libdir' - hardcode_direct_GCJ=yes - hardcode_shlibpath_var_GCJ=no - ;; - - hpux9*) - if test "$GCC" = yes; then - archive_cmds_GCJ='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - else - archive_cmds_GCJ='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - fi - hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' - hardcode_libdir_separator_GCJ=: - hardcode_direct_GCJ=yes - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L_GCJ=yes - export_dynamic_flag_spec_GCJ='${wl}-E' - ;; - - hpux10*) - if test "$GCC" = yes -a "$with_gnu_ld" = no; then - archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds_GCJ='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' - fi - if test "$with_gnu_ld" = no; then - hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' - hardcode_libdir_separator_GCJ=: - - hardcode_direct_GCJ=yes - export_dynamic_flag_spec_GCJ='${wl}-E' - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L_GCJ=yes - fi - ;; - - hpux11*) - if test "$GCC" = yes -a "$with_gnu_ld" = no; then - case $host_cpu in - hppa*64*) - archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - ia64*) - archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - else - case $host_cpu in - hppa*64*) - archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - ia64*) - archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - fi - if test "$with_gnu_ld" = no; then - hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' - hardcode_libdir_separator_GCJ=: - - case $host_cpu in - hppa*64*|ia64*) - hardcode_libdir_flag_spec_ld_GCJ='+b $libdir' - hardcode_direct_GCJ=no - hardcode_shlibpath_var_GCJ=no - ;; - *) - hardcode_direct_GCJ=yes - export_dynamic_flag_spec_GCJ='${wl}-E' - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L_GCJ=yes - ;; - esac - fi - ;; - - irix5* | irix6* | nonstopux*) - if test "$GCC" = yes; then - archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - archive_cmds_GCJ='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - hardcode_libdir_flag_spec_ld_GCJ='-rpath $libdir' - fi - hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator_GCJ=: - link_all_deplibs_GCJ=yes - ;; - - netbsd*) - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out - else - archive_cmds_GCJ='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF - fi - hardcode_libdir_flag_spec_GCJ='-R$libdir' - hardcode_direct_GCJ=yes - hardcode_shlibpath_var_GCJ=no - ;; - - newsos6) - archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct_GCJ=yes - hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator_GCJ=: - hardcode_shlibpath_var_GCJ=no - ;; - - openbsd*) - hardcode_direct_GCJ=yes - hardcode_shlibpath_var_GCJ=no - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' - hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' - export_dynamic_flag_spec_GCJ='${wl}-E' - else - case $host_os in - openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) - archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec_GCJ='-R$libdir' - ;; - *) - archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' - ;; - esac - fi - ;; - - os2*) - hardcode_libdir_flag_spec_GCJ='-L$libdir' - hardcode_minus_L_GCJ=yes - allow_undefined_flag_GCJ=unsupported - archive_cmds_GCJ='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' - old_archive_From_new_cmds_GCJ='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' - ;; - - osf3*) - if test "$GCC" = yes; then - allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - allow_undefined_flag_GCJ=' -expect_unresolved \*' - archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - fi - hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator_GCJ=: - ;; - - osf4* | osf5*) # as osf3* with the addition of -msym flag - if test "$GCC" = yes; then - allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' - else - allow_undefined_flag_GCJ=' -expect_unresolved \*' - archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' - archive_expsym_cmds_GCJ='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ - $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' - - # Both c and cxx compiler support -rpath directly - hardcode_libdir_flag_spec_GCJ='-rpath $libdir' - fi - hardcode_libdir_separator_GCJ=: - ;; - - solaris*) - no_undefined_flag_GCJ=' -z text' - if test "$GCC" = yes; then - wlarc='${wl}' - archive_cmds_GCJ='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' - else - wlarc='' - archive_cmds_GCJ='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' - archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' - fi - hardcode_libdir_flag_spec_GCJ='-R$libdir' - hardcode_shlibpath_var_GCJ=no - case $host_os in - solaris2.[0-5] | solaris2.[0-5].*) ;; - *) - # The compiler driver will combine linker options so we - # cannot just pass the convience library names through - # without $wl, iff we do not link with $LD. - # Luckily, gcc supports the same syntax we need for Sun Studio. - # Supported since Solaris 2.6 (maybe 2.5.1?) - case $wlarc in - '') - whole_archive_flag_spec_GCJ='-z allextract$convenience -z defaultextract' ;; - *) - whole_archive_flag_spec_GCJ='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; - esac ;; - esac - link_all_deplibs_GCJ=yes - ;; - - sunos4*) - if test "x$host_vendor" = xsequent; then - # Use $CC to link under sequent, because it throws in some extra .o - # files that make .init and .fini sections work. - archive_cmds_GCJ='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds_GCJ='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' - fi - hardcode_libdir_flag_spec_GCJ='-L$libdir' - hardcode_direct_GCJ=yes - hardcode_minus_L_GCJ=yes - hardcode_shlibpath_var_GCJ=no - ;; - - sysv4) - case $host_vendor in - sni) - archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct_GCJ=yes # is this really true??? - ;; - siemens) - ## LD is ld it makes a PLAMLIB - ## CC just makes a GrossModule. - archive_cmds_GCJ='$LD -G -o $lib $libobjs $deplibs $linker_flags' - reload_cmds_GCJ='$CC -r -o $output$reload_objs' - hardcode_direct_GCJ=no - ;; - motorola) - archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct_GCJ=no #Motorola manual says yes, but my tests say they lie - ;; - esac - runpath_var='LD_RUN_PATH' - hardcode_shlibpath_var_GCJ=no - ;; - - sysv4.3*) - archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_shlibpath_var_GCJ=no - export_dynamic_flag_spec_GCJ='-Bexport' - ;; - - sysv4*MP*) - if test -d /usr/nec; then - archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_shlibpath_var_GCJ=no - runpath_var=LD_RUN_PATH - hardcode_runpath_var=yes - ld_shlibs_GCJ=yes - fi - ;; - - sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) - no_undefined_flag_GCJ='${wl}-z,text' - archive_cmds_need_lc_GCJ=no - hardcode_shlibpath_var_GCJ=no - runpath_var='LD_RUN_PATH' - - if test "$GCC" = yes; then - archive_cmds_GCJ='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds_GCJ='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - fi - ;; - - sysv5* | sco3.2v5* | sco5v6*) - # Note: We can NOT use -z defs as we might desire, because we do not - # link with -lc, and that would cause any symbols used from libc to - # always be unresolved, which means just about no library would - # ever link correctly. If we're not using GNU ld we use -z text - # though, which does catch some bad symbols but isn't as heavy-handed - # as -z defs. - no_undefined_flag_GCJ='${wl}-z,text' - allow_undefined_flag_GCJ='${wl}-z,nodefs' - archive_cmds_need_lc_GCJ=no - hardcode_shlibpath_var_GCJ=no - hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' - hardcode_libdir_separator_GCJ=':' - link_all_deplibs_GCJ=yes - export_dynamic_flag_spec_GCJ='${wl}-Bexport' - runpath_var='LD_RUN_PATH' - - if test "$GCC" = yes; then - archive_cmds_GCJ='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - else - archive_cmds_GCJ='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' - fi - ;; - - uts4*) - archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec_GCJ='-L$libdir' - hardcode_shlibpath_var_GCJ=no - ;; - - *) - ld_shlibs_GCJ=no - ;; - esac - fi - -echo "$as_me:$LINENO: result: $ld_shlibs_GCJ" >&5 -echo "${ECHO_T}$ld_shlibs_GCJ" >&6 -test "$ld_shlibs_GCJ" = no && can_build_shared=no - -# -# Do we need to explicitly link libc? -# -case "x$archive_cmds_need_lc_GCJ" in -x|xyes) - # Assume -lc should be added - archive_cmds_need_lc_GCJ=yes - - if test "$enable_shared" = yes && test "$GCC" = yes; then - case $archive_cmds_GCJ in - *'~'*) - # FIXME: we may have to deal with multi-command sequences. - ;; - '$CC '*) - # Test whether the compiler implicitly links with -lc since on some - # systems, -lgcc has to come before -lc. If gcc already passes -lc - # to ld, don't add -lc before -lgcc. - echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 -echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6 - $rm conftest* - printf "$lt_simple_compile_test_code" > conftest.$ac_ext - - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } 2>conftest.err; then - soname=conftest - lib=conftest - libobjs=conftest.$ac_objext - deplibs= - wl=$lt_prog_compiler_wl_GCJ - pic_flag=$lt_prog_compiler_pic_GCJ - compiler_flags=-v - linker_flags=-v - verstring= - output_objdir=. - libname=conftest - lt_save_allow_undefined_flag=$allow_undefined_flag_GCJ - allow_undefined_flag_GCJ= - if { (eval echo "$as_me:$LINENO: \"$archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 - (eval $archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } - then - archive_cmds_need_lc_GCJ=no - else - archive_cmds_need_lc_GCJ=yes - fi - allow_undefined_flag_GCJ=$lt_save_allow_undefined_flag - else - cat conftest.err 1>&5 - fi - $rm conftest* - echo "$as_me:$LINENO: result: $archive_cmds_need_lc_GCJ" >&5 -echo "${ECHO_T}$archive_cmds_need_lc_GCJ" >&6 - ;; - esac - fi - ;; -esac - -echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 -echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6 -library_names_spec= -libname_spec='lib$name' -soname_spec= -shrext_cmds=".so" -postinstall_cmds= -postuninstall_cmds= -finish_cmds= -finish_eval= -shlibpath_var= -shlibpath_overrides_runpath=unknown -version_type=none -dynamic_linker="$host_os ld.so" -sys_lib_dlsearch_path_spec="/lib /usr/lib" -if test "$GCC" = yes; then - sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then - # if the path contains ";" then we assume it to be the separator - # otherwise default to the standard path separator (i.e. ":") - it is - # assumed that no part of a normal pathname contains ";" but that should - # okay in the real world where ";" in dirpaths is itself problematic. - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi -else - sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" -fi -need_lib_prefix=unknown -hardcode_into_libs=no - -# when you set need_version to no, make sure it does not cause -set_version -# flags to be left without arguments -need_version=unknown - -case $host_os in -aix3*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' - shlibpath_var=LIBPATH - - # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='${libname}${release}${shared_ext}$major' - ;; - -aix4* | aix5*) - version_type=linux - need_lib_prefix=no - need_version=no - hardcode_into_libs=yes - if test "$host_cpu" = ia64; then - # AIX 5 supports IA64 - library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - else - # With GCC up to 2.95.x, collect2 would create an import file - # for dependence libraries. The import file would start with - # the line `#! .'. This would cause the generated library to - # depend on `.', always an invalid library. This was fixed in - # development snapshots of GCC prior to 3.0. - case $host_os in - aix4 | aix4.[01] | aix4.[01].*) - if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' - echo ' yes ' - echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then - : - else - can_build_shared=no - fi - ;; - esac - # AIX (on Power*) has no versioning support, so currently we can not hardcode correct - # soname into executable. Probably we can add versioning support to - # collect2, so additional links can be useful in future. - if test "$aix_use_runtimelinking" = yes; then - # If using run time linking (on AIX 4.2 or later) use lib.so - # instead of lib.a to let people know that these are not - # typical AIX shared libraries. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - else - # We preserve .a as extension for shared libraries through AIX4.2 - # and later when we are not doing run time linking. - library_names_spec='${libname}${release}.a $libname.a' - soname_spec='${libname}${release}${shared_ext}$major' - fi - shlibpath_var=LIBPATH - fi - ;; - -amigaos*) - library_names_spec='$libname.ixlibrary $libname.a' - # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' - ;; - -beos*) - library_names_spec='${libname}${shared_ext}' - dynamic_linker="$host_os ld.so" - shlibpath_var=LIBRARY_PATH - ;; - -bsdi[45]*) - version_type=linux - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" - sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" - # the default ld.so.conf also contains /usr/contrib/lib and - # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow - # libtool to hard-code these into programs - ;; - -cygwin* | mingw* | pw32*) - version_type=windows - shrext_cmds=".dll" - need_version=no - need_lib_prefix=no - - case $GCC,$host_os in - yes,cygwin* | yes,mingw* | yes,pw32*) - library_names_spec='$libname.dll.a' - # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname~ - chmod a+x \$dldir/$dlname' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $rm \$dlpath' - shlibpath_overrides_runpath=yes - - case $host_os in - cygwin*) - # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" - ;; - mingw*) - # MinGW DLLs use traditional 'lib' prefix - soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then - # It is most probably a Windows format PATH printed by - # mingw gcc, but we are running on Cygwin. Gcc prints its search - # path with ; separators, and with drive letters. We can handle the - # drive letters (cygwin fileutils understands them), so leave them, - # especially as we might pass files found there to a mingw objdump, - # which wouldn't understand a cygwinified path. Ahh. - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi - ;; - pw32*) - # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - ;; - esac - ;; - - *) - library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' - ;; - esac - dynamic_linker='Win32 ld.exe' - # FIXME: first we should search . and the directory the executable is in - shlibpath_var=PATH - ;; - -darwin* | rhapsody*) - dynamic_linker="$host_os dyld" - version_type=darwin - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' - soname_spec='${libname}${release}${major}$shared_ext' - shlibpath_overrides_runpath=yes - shlibpath_var=DYLD_LIBRARY_PATH - shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' - # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. - if test "$GCC" = yes; then - sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` - else - sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' - fi - sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' - ;; - -dgux*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -freebsd1*) - dynamic_linker=no - ;; - -kfreebsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='GNU ld.so' - ;; - -freebsd* | dragonfly*) - # DragonFly does not have aout. When/if they implement a new - # versioning mechanism, adjust this. - if test -x /usr/bin/objformat; then - objformat=`/usr/bin/objformat` - else - case $host_os in - freebsd[123]*) objformat=aout ;; - *) objformat=elf ;; - esac - fi - version_type=freebsd-$objformat - case $version_type in - freebsd-elf*) - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - need_version=no - need_lib_prefix=no - ;; - freebsd-*) - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' - need_version=yes - ;; - esac - shlibpath_var=LD_LIBRARY_PATH - case $host_os in - freebsd2*) - shlibpath_overrides_runpath=yes - ;; - freebsd3.[01]* | freebsdelf3.[01]*) - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ - freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - freebsd*) # from 4.6 on - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - esac - ;; - -gnu*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - hardcode_into_libs=yes - ;; - -hpux9* | hpux10* | hpux11*) - # Give a soname corresponding to the major version so that dld.sl refuses to - # link against other versions. - version_type=sunos - need_lib_prefix=no - need_version=no - case $host_cpu in - ia64*) - shrext_cmds='.so' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.so" - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - if test "X$HPUX_IA64_MODE" = X32; then - sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" - else - sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" - fi - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - hppa*64*) - shrext_cmds='.sl' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.sl" - shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - *) - shrext_cmds='.sl' - dynamic_linker="$host_os dld.sl" - shlibpath_var=SHLIB_PATH - shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - ;; - esac - # HP-UX runs *really* slowly unless shared libraries are mode 555. - postinstall_cmds='chmod 555 $lib' - ;; - -interix3*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - -irix5* | irix6* | nonstopux*) - case $host_os in - nonstopux*) version_type=nonstopux ;; - *) - if test "$lt_cv_prog_gnu_ld" = yes; then - version_type=linux - else - version_type=irix - fi ;; - esac - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' - case $host_os in - irix5* | nonstopux*) - libsuff= shlibsuff= - ;; - *) - case $LD in # libtool.m4 will add one of these switches to LD - *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") - libsuff= shlibsuff= libmagic=32-bit;; - *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") - libsuff=32 shlibsuff=N32 libmagic=N32;; - *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") - libsuff=64 shlibsuff=64 libmagic=64-bit;; - *) libsuff= shlibsuff= libmagic=never-match;; - esac - ;; - esac - shlibpath_var=LD_LIBRARY${shlibsuff}_PATH - shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" - sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" - hardcode_into_libs=yes - ;; - -# No shared lib support for Linux oldld, aout, or coff. -linux*oldld* | linux*aout* | linux*coff*) - dynamic_linker=no - ;; - -# This must be Linux ELF. -linux*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. - hardcode_into_libs=yes - - # Append ld.so.conf contents to the search path - if test -f /etc/ld.so.conf; then - lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` - sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" - fi - - # We used to test for /lib/ld.so.1 and disable shared libraries on - # powerpc, because MkLinux only supported shared libraries with the - # GNU dynamic linker. Since this was broken with cross compilers, - # most powerpc-linux boxes support dynamic linking these days and - # people can always --disable-shared, the test was removed, and we - # assume the GNU/Linux dynamic linker is in use. - dynamic_linker='GNU/Linux ld.so' - ;; - -knetbsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='GNU ld.so' - ;; - -netbsd*) - version_type=sunos - need_lib_prefix=no - need_version=no - if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - dynamic_linker='NetBSD (a.out) ld.so' - else - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='NetBSD ld.elf_so' - fi - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - -newsos6) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -nto-qnx*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -openbsd*) - version_type=sunos - sys_lib_dlsearch_path_spec="/usr/lib" - need_lib_prefix=no - # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. - case $host_os in - openbsd3.3 | openbsd3.3.*) need_version=yes ;; - *) need_version=no ;; - esac - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - shlibpath_var=LD_LIBRARY_PATH - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - case $host_os in - openbsd2.[89] | openbsd2.[89].*) - shlibpath_overrides_runpath=no - ;; - *) - shlibpath_overrides_runpath=yes - ;; - esac - else - shlibpath_overrides_runpath=yes - fi - ;; - -os2*) - libname_spec='$name' - shrext_cmds=".dll" - need_lib_prefix=no - library_names_spec='$libname${shared_ext} $libname.a' - dynamic_linker='OS/2 ld.exe' - shlibpath_var=LIBPATH - ;; - -osf3* | osf4* | osf5*) - version_type=osf - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" - ;; - -solaris*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - # ldd complains unless libraries are executable - postinstall_cmds='chmod +x $lib' - ;; - -sunos4*) - version_type=sunos - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - if test "$with_gnu_ld" = yes; then - need_lib_prefix=no - fi - need_version=yes - ;; - -sysv4 | sysv4.3*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - case $host_vendor in - sni) - shlibpath_overrides_runpath=no - need_lib_prefix=no - export_dynamic_flag_spec='${wl}-Blargedynsym' - runpath_var=LD_RUN_PATH - ;; - siemens) - need_lib_prefix=no - ;; - motorola) - need_lib_prefix=no - need_version=no - shlibpath_overrides_runpath=no - sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' - ;; - esac - ;; - -sysv4*MP*) - if test -d /usr/nec ;then - version_type=linux - library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' - soname_spec='$libname${shared_ext}.$major' - shlibpath_var=LD_LIBRARY_PATH - fi - ;; - -sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - version_type=freebsd-elf - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - hardcode_into_libs=yes - if test "$with_gnu_ld" = yes; then - sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' - shlibpath_overrides_runpath=no - else - sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' - shlibpath_overrides_runpath=yes - case $host_os in - sco3.2v5*) - sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" - ;; - esac - fi - sys_lib_dlsearch_path_spec='/usr/lib' - ;; - -uts4*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -*) - dynamic_linker=no - ;; -esac -echo "$as_me:$LINENO: result: $dynamic_linker" >&5 -echo "${ECHO_T}$dynamic_linker" >&6 -test "$dynamic_linker" = no && can_build_shared=no - -variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test "$GCC" = yes; then - variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" -fi - -echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 -echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6 -hardcode_action_GCJ= -if test -n "$hardcode_libdir_flag_spec_GCJ" || \ - test -n "$runpath_var_GCJ" || \ - test "X$hardcode_automatic_GCJ" = "Xyes" ; then - - # We can hardcode non-existant directories. - if test "$hardcode_direct_GCJ" != no && - # If the only mechanism to avoid hardcoding is shlibpath_var, we - # have to relink, otherwise we might link with an installed library - # when we should be linking with a yet-to-be-installed one - ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, GCJ)" != no && - test "$hardcode_minus_L_GCJ" != no; then - # Linking always hardcodes the temporary library directory. - hardcode_action_GCJ=relink - else - # We can link without hardcoding, and we can hardcode nonexisting dirs. - hardcode_action_GCJ=immediate - fi -else - # We cannot hardcode anything, or else we can only hardcode existing - # directories. - hardcode_action_GCJ=unsupported -fi -echo "$as_me:$LINENO: result: $hardcode_action_GCJ" >&5 -echo "${ECHO_T}$hardcode_action_GCJ" >&6 - -if test "$hardcode_action_GCJ" = relink; then - # Fast installation is not supported - enable_fast_install=no -elif test "$shlibpath_overrides_runpath" = yes || - test "$enable_shared" = no; then - # Fast installation is not necessary - enable_fast_install=needless -fi - - -# The else clause should only fire when bootstrapping the -# libtool distribution, otherwise you forgot to ship ltmain.sh -# with your package, and you will get complaints that there are -# no rules to generate ltmain.sh. -if test -f "$ltmain"; then - # See if we are running on zsh, and set the options which allow our commands through - # without removal of \ escapes. - if test -n "${ZSH_VERSION+set}" ; then - setopt NO_GLOB_SUBST - fi - # Now quote all the things that may contain metacharacters while being - # careful not to overquote the AC_SUBSTed values. We take copies of the - # variables and quote the copies for generation of the libtool script. - for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ - SED SHELL STRIP \ - libname_spec library_names_spec soname_spec extract_expsyms_cmds \ - old_striplib striplib file_magic_cmd finish_cmds finish_eval \ - deplibs_check_method reload_flag reload_cmds need_locks \ - lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ - lt_cv_sys_global_symbol_to_c_name_address \ - sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ - old_postinstall_cmds old_postuninstall_cmds \ - compiler_GCJ \ - CC_GCJ \ - LD_GCJ \ - lt_prog_compiler_wl_GCJ \ - lt_prog_compiler_pic_GCJ \ - lt_prog_compiler_static_GCJ \ - lt_prog_compiler_no_builtin_flag_GCJ \ - export_dynamic_flag_spec_GCJ \ - thread_safe_flag_spec_GCJ \ - whole_archive_flag_spec_GCJ \ - enable_shared_with_static_runtimes_GCJ \ - old_archive_cmds_GCJ \ - old_archive_from_new_cmds_GCJ \ - predep_objects_GCJ \ - postdep_objects_GCJ \ - predeps_GCJ \ - postdeps_GCJ \ - compiler_lib_search_path_GCJ \ - archive_cmds_GCJ \ - archive_expsym_cmds_GCJ \ - postinstall_cmds_GCJ \ - postuninstall_cmds_GCJ \ - old_archive_from_expsyms_cmds_GCJ \ - allow_undefined_flag_GCJ \ - no_undefined_flag_GCJ \ - export_symbols_cmds_GCJ \ - hardcode_libdir_flag_spec_GCJ \ - hardcode_libdir_flag_spec_ld_GCJ \ - hardcode_libdir_separator_GCJ \ - hardcode_automatic_GCJ \ - module_cmds_GCJ \ - module_expsym_cmds_GCJ \ - lt_cv_prog_compiler_c_o_GCJ \ - exclude_expsyms_GCJ \ - include_expsyms_GCJ; do - - case $var in - old_archive_cmds_GCJ | \ - old_archive_from_new_cmds_GCJ | \ - archive_cmds_GCJ | \ - archive_expsym_cmds_GCJ | \ - module_cmds_GCJ | \ - module_expsym_cmds_GCJ | \ - old_archive_from_expsyms_cmds_GCJ | \ - export_symbols_cmds_GCJ | \ - extract_expsyms_cmds | reload_cmds | finish_cmds | \ - postinstall_cmds | postuninstall_cmds | \ - old_postinstall_cmds | old_postuninstall_cmds | \ - sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) - # Double-quote double-evaled strings. - eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" - ;; - *) - eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" - ;; - esac - done - - case $lt_echo in - *'\$0 --fallback-echo"') - lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` - ;; - esac - -cfgfile="$ofile" - - cat <<__EOF__ >> "$cfgfile" -# ### BEGIN LIBTOOL TAG CONFIG: $tagname - -# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: - -# Shell to use when invoking shell scripts. -SHELL=$lt_SHELL - -# Whether or not to build shared libraries. -build_libtool_libs=$enable_shared - -# Whether or not to build static libraries. -build_old_libs=$enable_static - -# Whether or not to add -lc for building shared libraries. -build_libtool_need_lc=$archive_cmds_need_lc_GCJ - -# Whether or not to disallow shared libs when runtime libs are static -allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_GCJ - -# Whether or not to optimize for fast installation. -fast_install=$enable_fast_install - -# The host system. -host_alias=$host_alias -host=$host -host_os=$host_os - -# The build system. -build_alias=$build_alias -build=$build -build_os=$build_os - -# An echo program that does not interpret backslashes. -echo=$lt_echo - -# The archiver. -AR=$lt_AR -AR_FLAGS=$lt_AR_FLAGS - -# A C compiler. -LTCC=$lt_LTCC - -# LTCC compiler flags. -LTCFLAGS=$lt_LTCFLAGS - -# A language-specific compiler. -CC=$lt_compiler_GCJ - -# Is the compiler the GNU C compiler? -with_gcc=$GCC_GCJ - -# An ERE matcher. -EGREP=$lt_EGREP - -# The linker used to build libraries. -LD=$lt_LD_GCJ - -# Whether we need hard or soft links. -LN_S=$lt_LN_S - -# A BSD-compatible nm program. -NM=$lt_NM - -# A symbol stripping program -STRIP=$lt_STRIP - -# Used to examine libraries when file_magic_cmd begins "file" -MAGIC_CMD=$MAGIC_CMD - -# Used on cygwin: DLL creation program. -DLLTOOL="$DLLTOOL" - -# Used on cygwin: object dumper. -OBJDUMP="$OBJDUMP" - -# Used on cygwin: assembler. -AS="$AS" - -# The name of the directory that contains temporary libtool files. -objdir=$objdir - -# How to create reloadable object files. -reload_flag=$lt_reload_flag -reload_cmds=$lt_reload_cmds - -# How to pass a linker flag through the compiler. -wl=$lt_lt_prog_compiler_wl_GCJ - -# Object file suffix (normally "o"). -objext="$ac_objext" - -# Old archive suffix (normally "a"). -libext="$libext" - -# Shared library suffix (normally ".so"). -shrext_cmds='$shrext_cmds' - -# Executable file suffix (normally ""). -exeext="$exeext" - -# Additional compiler flags for building library objects. -pic_flag=$lt_lt_prog_compiler_pic_GCJ -pic_mode=$pic_mode - -# What is the maximum length of a command? -max_cmd_len=$lt_cv_sys_max_cmd_len - -# Does compiler simultaneously support -c and -o options? -compiler_c_o=$lt_lt_cv_prog_compiler_c_o_GCJ - -# Must we lock files when doing compilation? -need_locks=$lt_need_locks - -# Do we need the lib prefix for modules? -need_lib_prefix=$need_lib_prefix - -# Do we need a version for libraries? -need_version=$need_version - -# Whether dlopen is supported. -dlopen_support=$enable_dlopen - -# Whether dlopen of programs is supported. -dlopen_self=$enable_dlopen_self - -# Whether dlopen of statically linked programs is supported. -dlopen_self_static=$enable_dlopen_self_static - -# Compiler flag to prevent dynamic linking. -link_static_flag=$lt_lt_prog_compiler_static_GCJ - -# Compiler flag to turn off builtin functions. -no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_GCJ - -# Compiler flag to allow reflexive dlopens. -export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_GCJ - -# Compiler flag to generate shared objects directly from archives. -whole_archive_flag_spec=$lt_whole_archive_flag_spec_GCJ - -# Compiler flag to generate thread-safe objects. -thread_safe_flag_spec=$lt_thread_safe_flag_spec_GCJ - -# Library versioning type. -version_type=$version_type - -# Format of library name prefix. -libname_spec=$lt_libname_spec - -# List of archive names. First name is the real one, the rest are links. -# The last name is the one that the linker finds with -lNAME. -library_names_spec=$lt_library_names_spec - -# The coded name of the library, if different from the real name. -soname_spec=$lt_soname_spec - -# Commands used to build and install an old-style archive. -RANLIB=$lt_RANLIB -old_archive_cmds=$lt_old_archive_cmds_GCJ -old_postinstall_cmds=$lt_old_postinstall_cmds -old_postuninstall_cmds=$lt_old_postuninstall_cmds - -# Create an old-style archive from a shared archive. -old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_GCJ - -# Create a temporary old-style archive to link instead of a shared archive. -old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_GCJ - -# Commands used to build and install a shared archive. -archive_cmds=$lt_archive_cmds_GCJ -archive_expsym_cmds=$lt_archive_expsym_cmds_GCJ -postinstall_cmds=$lt_postinstall_cmds -postuninstall_cmds=$lt_postuninstall_cmds - -# Commands used to build a loadable module (assumed same as above if empty) -module_cmds=$lt_module_cmds_GCJ -module_expsym_cmds=$lt_module_expsym_cmds_GCJ - -# Commands to strip libraries. -old_striplib=$lt_old_striplib -striplib=$lt_striplib - -# Dependencies to place before the objects being linked to create a -# shared library. -predep_objects=$lt_predep_objects_GCJ - -# Dependencies to place after the objects being linked to create a -# shared library. -postdep_objects=$lt_postdep_objects_GCJ - -# Dependencies to place before the objects being linked to create a -# shared library. -predeps=$lt_predeps_GCJ - -# Dependencies to place after the objects being linked to create a -# shared library. -postdeps=$lt_postdeps_GCJ - -# The library search path used internally by the compiler when linking -# a shared library. -compiler_lib_search_path=$lt_compiler_lib_search_path_GCJ - -# Method to check whether dependent libraries are shared objects. -deplibs_check_method=$lt_deplibs_check_method - -# Command to use when deplibs_check_method == file_magic. -file_magic_cmd=$lt_file_magic_cmd - -# Flag that allows shared libraries with undefined symbols to be built. -allow_undefined_flag=$lt_allow_undefined_flag_GCJ - -# Flag that forces no undefined symbols. -no_undefined_flag=$lt_no_undefined_flag_GCJ - -# Commands used to finish a libtool library installation in a directory. -finish_cmds=$lt_finish_cmds - -# Same as above, but a single script fragment to be evaled but not shown. -finish_eval=$lt_finish_eval - -# Take the output of nm and produce a listing of raw symbols and C names. -global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe - -# Transform the output of nm in a proper C declaration -global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl - -# Transform the output of nm in a C name address pair -global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address - -# This is the shared library runtime path variable. -runpath_var=$runpath_var - -# This is the shared library path variable. -shlibpath_var=$shlibpath_var - -# Is shlibpath searched before the hard-coded library search path? -shlibpath_overrides_runpath=$shlibpath_overrides_runpath - -# How to hardcode a shared library path into an executable. -hardcode_action=$hardcode_action_GCJ - -# Whether we should hardcode library paths into libraries. -hardcode_into_libs=$hardcode_into_libs - -# Flag to hardcode \$libdir into a binary during linking. -# This must work even if \$libdir does not exist. -hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_GCJ - -# If ld is used when linking, flag to hardcode \$libdir into -# a binary during linking. This must work even if \$libdir does -# not exist. -hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_GCJ - -# Whether we need a single -rpath flag with a separated argument. -hardcode_libdir_separator=$lt_hardcode_libdir_separator_GCJ - -# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the -# resulting binary. -hardcode_direct=$hardcode_direct_GCJ - -# Set to yes if using the -LDIR flag during linking hardcodes DIR into the -# resulting binary. -hardcode_minus_L=$hardcode_minus_L_GCJ - -# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into -# the resulting binary. -hardcode_shlibpath_var=$hardcode_shlibpath_var_GCJ - -# Set to yes if building a shared library automatically hardcodes DIR into the library -# and all subsequent libraries and executables linked against it. -hardcode_automatic=$hardcode_automatic_GCJ - -# Variables whose values should be saved in libtool wrapper scripts and -# restored at relink time. -variables_saved_for_relink="$variables_saved_for_relink" - -# Whether libtool must link a program against all its dependency libraries. -link_all_deplibs=$link_all_deplibs_GCJ - -# Compile-time system search path for libraries -sys_lib_search_path_spec=$lt_sys_lib_search_path_spec - -# Run-time system search path for libraries -sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec - -# Fix the shell variable \$srcfile for the compiler. -fix_srcfile_path="$fix_srcfile_path_GCJ" - -# Set to yes if exported symbols are required. -always_export_symbols=$always_export_symbols_GCJ - -# The commands to list exported symbols. -export_symbols_cmds=$lt_export_symbols_cmds_GCJ - -# The commands to extract the exported symbol list from a shared archive. -extract_expsyms_cmds=$lt_extract_expsyms_cmds - -# Symbols that should not be listed in the preloaded symbols. -exclude_expsyms=$lt_exclude_expsyms_GCJ - -# Symbols that must always be exported. -include_expsyms=$lt_include_expsyms_GCJ - -# ### END LIBTOOL TAG CONFIG: $tagname - -__EOF__ - - -else - # If there is no Makefile yet, we rely on a make rule to execute - # `config.status --recheck' to rerun these tests and create the - # libtool script then. - ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` - if test -f "$ltmain_in"; then - test -f Makefile && make "$ltmain" - fi -fi - - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -CC="$lt_save_CC" - - else - tagname="" - fi - ;; - - RC) - - - -# Source file extension for RC test sources. -ac_ext=rc - -# Object file extension for compiled RC test sources. -objext=o -objext_RC=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }\n' - -# Code to be used in simple link tests -lt_simple_link_test_code="$lt_simple_compile_test_code" - -# ltmain only uses $CC for tagged configurations so make sure $CC is set. - -# If no C compiler was specified, use CC. -LTCC=${LTCC-"$CC"} - -# If no C compiler flags were specified, use CFLAGS. -LTCFLAGS=${LTCFLAGS-"$CFLAGS"} - -# Allow CC to be a program name with arguments. -compiler=$CC - - -# save warnings/boilerplate of simple test code -ac_outfile=conftest.$ac_objext -printf "$lt_simple_compile_test_code" >conftest.$ac_ext -eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_compiler_boilerplate=`cat conftest.err` -$rm conftest* - -ac_outfile=conftest.$ac_objext -printf "$lt_simple_link_test_code" >conftest.$ac_ext -eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_linker_boilerplate=`cat conftest.err` -$rm conftest* - - -# Allow CC to be a program name with arguments. -lt_save_CC="$CC" -CC=${RC-"windres"} -compiler=$CC -compiler_RC=$CC -for cc_temp in $compiler""; do - case $cc_temp in - compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; - distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; - \-*) ;; - *) break;; - esac -done -cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` - -lt_cv_prog_compiler_c_o_RC=yes - -# The else clause should only fire when bootstrapping the -# libtool distribution, otherwise you forgot to ship ltmain.sh -# with your package, and you will get complaints that there are -# no rules to generate ltmain.sh. -if test -f "$ltmain"; then - # See if we are running on zsh, and set the options which allow our commands through - # without removal of \ escapes. - if test -n "${ZSH_VERSION+set}" ; then - setopt NO_GLOB_SUBST - fi - # Now quote all the things that may contain metacharacters while being - # careful not to overquote the AC_SUBSTed values. We take copies of the - # variables and quote the copies for generation of the libtool script. - for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ - SED SHELL STRIP \ - libname_spec library_names_spec soname_spec extract_expsyms_cmds \ - old_striplib striplib file_magic_cmd finish_cmds finish_eval \ - deplibs_check_method reload_flag reload_cmds need_locks \ - lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ - lt_cv_sys_global_symbol_to_c_name_address \ - sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ - old_postinstall_cmds old_postuninstall_cmds \ - compiler_RC \ - CC_RC \ - LD_RC \ - lt_prog_compiler_wl_RC \ - lt_prog_compiler_pic_RC \ - lt_prog_compiler_static_RC \ - lt_prog_compiler_no_builtin_flag_RC \ - export_dynamic_flag_spec_RC \ - thread_safe_flag_spec_RC \ - whole_archive_flag_spec_RC \ - enable_shared_with_static_runtimes_RC \ - old_archive_cmds_RC \ - old_archive_from_new_cmds_RC \ - predep_objects_RC \ - postdep_objects_RC \ - predeps_RC \ - postdeps_RC \ - compiler_lib_search_path_RC \ - archive_cmds_RC \ - archive_expsym_cmds_RC \ - postinstall_cmds_RC \ - postuninstall_cmds_RC \ - old_archive_from_expsyms_cmds_RC \ - allow_undefined_flag_RC \ - no_undefined_flag_RC \ - export_symbols_cmds_RC \ - hardcode_libdir_flag_spec_RC \ - hardcode_libdir_flag_spec_ld_RC \ - hardcode_libdir_separator_RC \ - hardcode_automatic_RC \ - module_cmds_RC \ - module_expsym_cmds_RC \ - lt_cv_prog_compiler_c_o_RC \ - exclude_expsyms_RC \ - include_expsyms_RC; do - - case $var in - old_archive_cmds_RC | \ - old_archive_from_new_cmds_RC | \ - archive_cmds_RC | \ - archive_expsym_cmds_RC | \ - module_cmds_RC | \ - module_expsym_cmds_RC | \ - old_archive_from_expsyms_cmds_RC | \ - export_symbols_cmds_RC | \ - extract_expsyms_cmds | reload_cmds | finish_cmds | \ - postinstall_cmds | postuninstall_cmds | \ - old_postinstall_cmds | old_postuninstall_cmds | \ - sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) - # Double-quote double-evaled strings. - eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" - ;; - *) - eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" - ;; - esac - done - - case $lt_echo in - *'\$0 --fallback-echo"') - lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` - ;; - esac - -cfgfile="$ofile" - - cat <<__EOF__ >> "$cfgfile" -# ### BEGIN LIBTOOL TAG CONFIG: $tagname - -# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: - -# Shell to use when invoking shell scripts. -SHELL=$lt_SHELL - -# Whether or not to build shared libraries. -build_libtool_libs=$enable_shared - -# Whether or not to build static libraries. -build_old_libs=$enable_static - -# Whether or not to add -lc for building shared libraries. -build_libtool_need_lc=$archive_cmds_need_lc_RC - -# Whether or not to disallow shared libs when runtime libs are static -allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_RC - -# Whether or not to optimize for fast installation. -fast_install=$enable_fast_install - -# The host system. -host_alias=$host_alias -host=$host -host_os=$host_os - -# The build system. -build_alias=$build_alias -build=$build -build_os=$build_os - -# An echo program that does not interpret backslashes. -echo=$lt_echo - -# The archiver. -AR=$lt_AR -AR_FLAGS=$lt_AR_FLAGS - -# A C compiler. -LTCC=$lt_LTCC - -# LTCC compiler flags. -LTCFLAGS=$lt_LTCFLAGS - -# A language-specific compiler. -CC=$lt_compiler_RC - -# Is the compiler the GNU C compiler? -with_gcc=$GCC_RC - -# An ERE matcher. -EGREP=$lt_EGREP - -# The linker used to build libraries. -LD=$lt_LD_RC - -# Whether we need hard or soft links. -LN_S=$lt_LN_S - -# A BSD-compatible nm program. -NM=$lt_NM - -# A symbol stripping program -STRIP=$lt_STRIP - -# Used to examine libraries when file_magic_cmd begins "file" -MAGIC_CMD=$MAGIC_CMD - -# Used on cygwin: DLL creation program. -DLLTOOL="$DLLTOOL" - -# Used on cygwin: object dumper. -OBJDUMP="$OBJDUMP" - -# Used on cygwin: assembler. -AS="$AS" - -# The name of the directory that contains temporary libtool files. -objdir=$objdir - -# How to create reloadable object files. -reload_flag=$lt_reload_flag -reload_cmds=$lt_reload_cmds - -# How to pass a linker flag through the compiler. -wl=$lt_lt_prog_compiler_wl_RC - -# Object file suffix (normally "o"). -objext="$ac_objext" - -# Old archive suffix (normally "a"). -libext="$libext" - -# Shared library suffix (normally ".so"). -shrext_cmds='$shrext_cmds' - -# Executable file suffix (normally ""). -exeext="$exeext" - -# Additional compiler flags for building library objects. -pic_flag=$lt_lt_prog_compiler_pic_RC -pic_mode=$pic_mode - -# What is the maximum length of a command? -max_cmd_len=$lt_cv_sys_max_cmd_len - -# Does compiler simultaneously support -c and -o options? -compiler_c_o=$lt_lt_cv_prog_compiler_c_o_RC - -# Must we lock files when doing compilation? -need_locks=$lt_need_locks - -# Do we need the lib prefix for modules? -need_lib_prefix=$need_lib_prefix - -# Do we need a version for libraries? -need_version=$need_version - -# Whether dlopen is supported. -dlopen_support=$enable_dlopen - -# Whether dlopen of programs is supported. -dlopen_self=$enable_dlopen_self - -# Whether dlopen of statically linked programs is supported. -dlopen_self_static=$enable_dlopen_self_static - -# Compiler flag to prevent dynamic linking. -link_static_flag=$lt_lt_prog_compiler_static_RC - -# Compiler flag to turn off builtin functions. -no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_RC - -# Compiler flag to allow reflexive dlopens. -export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_RC - -# Compiler flag to generate shared objects directly from archives. -whole_archive_flag_spec=$lt_whole_archive_flag_spec_RC - -# Compiler flag to generate thread-safe objects. -thread_safe_flag_spec=$lt_thread_safe_flag_spec_RC - -# Library versioning type. -version_type=$version_type - -# Format of library name prefix. -libname_spec=$lt_libname_spec - -# List of archive names. First name is the real one, the rest are links. -# The last name is the one that the linker finds with -lNAME. -library_names_spec=$lt_library_names_spec - -# The coded name of the library, if different from the real name. -soname_spec=$lt_soname_spec - -# Commands used to build and install an old-style archive. -RANLIB=$lt_RANLIB -old_archive_cmds=$lt_old_archive_cmds_RC -old_postinstall_cmds=$lt_old_postinstall_cmds -old_postuninstall_cmds=$lt_old_postuninstall_cmds - -# Create an old-style archive from a shared archive. -old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_RC - -# Create a temporary old-style archive to link instead of a shared archive. -old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_RC - -# Commands used to build and install a shared archive. -archive_cmds=$lt_archive_cmds_RC -archive_expsym_cmds=$lt_archive_expsym_cmds_RC -postinstall_cmds=$lt_postinstall_cmds -postuninstall_cmds=$lt_postuninstall_cmds - -# Commands used to build a loadable module (assumed same as above if empty) -module_cmds=$lt_module_cmds_RC -module_expsym_cmds=$lt_module_expsym_cmds_RC - -# Commands to strip libraries. -old_striplib=$lt_old_striplib -striplib=$lt_striplib - -# Dependencies to place before the objects being linked to create a -# shared library. -predep_objects=$lt_predep_objects_RC - -# Dependencies to place after the objects being linked to create a -# shared library. -postdep_objects=$lt_postdep_objects_RC - -# Dependencies to place before the objects being linked to create a -# shared library. -predeps=$lt_predeps_RC - -# Dependencies to place after the objects being linked to create a -# shared library. -postdeps=$lt_postdeps_RC - -# The library search path used internally by the compiler when linking -# a shared library. -compiler_lib_search_path=$lt_compiler_lib_search_path_RC - -# Method to check whether dependent libraries are shared objects. -deplibs_check_method=$lt_deplibs_check_method - -# Command to use when deplibs_check_method == file_magic. -file_magic_cmd=$lt_file_magic_cmd - -# Flag that allows shared libraries with undefined symbols to be built. -allow_undefined_flag=$lt_allow_undefined_flag_RC - -# Flag that forces no undefined symbols. -no_undefined_flag=$lt_no_undefined_flag_RC - -# Commands used to finish a libtool library installation in a directory. -finish_cmds=$lt_finish_cmds - -# Same as above, but a single script fragment to be evaled but not shown. -finish_eval=$lt_finish_eval - -# Take the output of nm and produce a listing of raw symbols and C names. -global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe - -# Transform the output of nm in a proper C declaration -global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl - -# Transform the output of nm in a C name address pair -global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address - -# This is the shared library runtime path variable. -runpath_var=$runpath_var - -# This is the shared library path variable. -shlibpath_var=$shlibpath_var - -# Is shlibpath searched before the hard-coded library search path? -shlibpath_overrides_runpath=$shlibpath_overrides_runpath - -# How to hardcode a shared library path into an executable. -hardcode_action=$hardcode_action_RC - -# Whether we should hardcode library paths into libraries. -hardcode_into_libs=$hardcode_into_libs - -# Flag to hardcode \$libdir into a binary during linking. -# This must work even if \$libdir does not exist. -hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_RC - -# If ld is used when linking, flag to hardcode \$libdir into -# a binary during linking. This must work even if \$libdir does -# not exist. -hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_RC - -# Whether we need a single -rpath flag with a separated argument. -hardcode_libdir_separator=$lt_hardcode_libdir_separator_RC - -# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the -# resulting binary. -hardcode_direct=$hardcode_direct_RC - -# Set to yes if using the -LDIR flag during linking hardcodes DIR into the -# resulting binary. -hardcode_minus_L=$hardcode_minus_L_RC - -# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into -# the resulting binary. -hardcode_shlibpath_var=$hardcode_shlibpath_var_RC - -# Set to yes if building a shared library automatically hardcodes DIR into the library -# and all subsequent libraries and executables linked against it. -hardcode_automatic=$hardcode_automatic_RC - -# Variables whose values should be saved in libtool wrapper scripts and -# restored at relink time. -variables_saved_for_relink="$variables_saved_for_relink" - -# Whether libtool must link a program against all its dependency libraries. -link_all_deplibs=$link_all_deplibs_RC - -# Compile-time system search path for libraries -sys_lib_search_path_spec=$lt_sys_lib_search_path_spec - -# Run-time system search path for libraries -sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec - -# Fix the shell variable \$srcfile for the compiler. -fix_srcfile_path="$fix_srcfile_path_RC" - -# Set to yes if exported symbols are required. -always_export_symbols=$always_export_symbols_RC - -# The commands to list exported symbols. -export_symbols_cmds=$lt_export_symbols_cmds_RC - -# The commands to extract the exported symbol list from a shared archive. -extract_expsyms_cmds=$lt_extract_expsyms_cmds - -# Symbols that should not be listed in the preloaded symbols. -exclude_expsyms=$lt_exclude_expsyms_RC - -# Symbols that must always be exported. -include_expsyms=$lt_include_expsyms_RC - -# ### END LIBTOOL TAG CONFIG: $tagname - -__EOF__ - - -else - # If there is no Makefile yet, we rely on a make rule to execute - # `config.status --recheck' to rerun these tests and create the - # libtool script then. - ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` - if test -f "$ltmain_in"; then - test -f Makefile && make "$ltmain" - fi -fi - - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -CC="$lt_save_CC" - - ;; - - *) - { { echo "$as_me:$LINENO: error: Unsupported tag name: $tagname" >&5 -echo "$as_me: error: Unsupported tag name: $tagname" >&2;} - { (exit 1); exit 1; }; } - ;; - esac - - # Append the new tag name to the list of available tags. - if test -n "$tagname" ; then - available_tags="$available_tags $tagname" - fi - fi - done - IFS="$lt_save_ifs" - - # Now substitute the updated list of available tags. - if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then - mv "${ofile}T" "$ofile" - chmod +x "$ofile" - else - rm -f "${ofile}T" - { { echo "$as_me:$LINENO: error: unable to update list of available tagged configurations." >&5 -echo "$as_me: error: unable to update list of available tagged configurations." >&2;} - { (exit 1); exit 1; }; } - fi -fi - - - -# This can be used to rebuild libtool when needed -LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" - -# Always use our own libtool. -LIBTOOL='$(SHELL) $(top_builddir)/libtool' - -# Prevent multiple expansion - - - - - - - - - - - - - - - - - - - - - - - - - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. -set dummy ${ac_tool_prefix}gcc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}gcc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$ac_cv_prog_CC"; then - ac_ct_CC=$CC - # Extract the first word of "gcc", so it can be a program name with args. -set dummy gcc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="gcc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 -echo "${ECHO_T}$ac_ct_CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - CC=$ac_ct_CC -else - CC="$ac_cv_prog_CC" -fi - -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. -set dummy ${ac_tool_prefix}cc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}cc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$ac_cv_prog_CC"; then - ac_ct_CC=$CC - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="cc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 -echo "${ECHO_T}$ac_ct_CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - CC=$ac_ct_CC -else - CC="$ac_cv_prog_CC" -fi - -fi -if test -z "$CC"; then - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else - ac_prog_rejected=no -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then - ac_prog_rejected=yes - continue - fi - ac_cv_prog_CC="cc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -if test $ac_prog_rejected = yes; then - # We found a bogon in the path, so make sure we never use it. - set dummy $ac_cv_prog_CC - shift - if test $# != 0; then - # We chose a different compiler from the bogus one. - # However, it has the same basename, so the bogon will be chosen - # first if we set CC to just the basename; use the full file name. - shift - ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" - fi -fi -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - for ac_prog in cl - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="$ac_tool_prefix$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - test -n "$CC" && break - done -fi -if test -z "$CC"; then - ac_ct_CC=$CC - for ac_prog in cl -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 -echo "${ECHO_T}$ac_ct_CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - test -n "$ac_ct_CC" && break -done - - CC=$ac_ct_CC -fi - -fi - - -test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH -See \`config.log' for more details." >&5 -echo "$as_me: error: no acceptable C compiler found in \$PATH -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } - -# Provide some information about the compiler. -echo "$as_me:$LINENO:" \ - "checking for C compiler version" >&5 -ac_compiler=`set X $ac_compile; echo $2` -{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 - (eval $ac_compiler --version &5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 - (eval $ac_compiler -v &5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 - (eval $ac_compiler -V &5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } - -echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 -echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 -if test "${ac_cv_c_compiler_gnu+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ -#ifndef __GNUC__ - choke me -#endif - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_compiler_gnu=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_compiler_gnu=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -ac_cv_c_compiler_gnu=$ac_compiler_gnu - -fi -echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 -echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 -GCC=`test $ac_compiler_gnu = yes && echo yes` -ac_test_CFLAGS=${CFLAGS+set} -ac_save_CFLAGS=$CFLAGS -CFLAGS="-g" -echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 -echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 -if test "${ac_cv_prog_cc_g+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_prog_cc_g=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_prog_cc_g=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 -echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 -if test "$ac_test_CFLAGS" = set; then - CFLAGS=$ac_save_CFLAGS -elif test $ac_cv_prog_cc_g = yes; then - if test "$GCC" = yes; then - CFLAGS="-g -O2" - else - CFLAGS="-g" - fi -else - if test "$GCC" = yes; then - CFLAGS="-O2" - else - CFLAGS= - fi -fi -echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 -echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 -if test "${ac_cv_prog_cc_stdc+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_prog_cc_stdc=no -ac_save_CC=$CC -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -#include -#include -#include -/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ -struct buf { int x; }; -FILE * (*rcsopen) (struct buf *, struct stat *, int); -static char *e (p, i) - char **p; - int i; -{ - return p[i]; -} -static char *f (char * (*g) (char **, int), char **p, ...) -{ - char *s; - va_list v; - va_start (v,p); - s = g (p, va_arg (v,int)); - va_end (v); - return s; -} - -/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has - function prototypes and stuff, but not '\xHH' hex character constants. - These don't provoke an error unfortunately, instead are silently treated - as 'x'. The following induces an error, until -std1 is added to get - proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an - array size at least. It's necessary to write '\x00'==0 to get something - that's true only with -std1. */ -int osf4_cc_array ['\x00' == 0 ? 1 : -1]; - -int test (int i, double x); -struct s1 {int (*f) (int a);}; -struct s2 {int (*f) (double a);}; -int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); -int argc; -char **argv; -int -main () -{ -return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; - ; - return 0; -} -_ACEOF -# Don't try gcc -ansi; that turns off useful extensions and -# breaks some systems' header files. -# AIX -qlanglvl=ansi -# Ultrix and OSF/1 -std1 -# HP-UX 10.20 and later -Ae -# HP-UX older versions -Aa -D_HPUX_SOURCE -# SVR4 -Xc -D__EXTENSIONS__ -for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" -do - CC="$ac_save_CC $ac_arg" - rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_prog_cc_stdc=$ac_arg -break -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext -done -rm -f conftest.$ac_ext conftest.$ac_objext -CC=$ac_save_CC - -fi - -case "x$ac_cv_prog_cc_stdc" in - x|xno) - echo "$as_me:$LINENO: result: none needed" >&5 -echo "${ECHO_T}none needed" >&6 ;; - *) - echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 -echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 - CC="$CC $ac_cv_prog_cc_stdc" ;; -esac - -# Some people use a C++ compiler to compile C. Since we use `exit', -# in C++ we need to declare it. In case someone uses the same compiler -# for both compiling C and C++ we need to have the C++ compiler decide -# the declaration of exit, since it's the most demanding environment. -cat >conftest.$ac_ext <<_ACEOF -#ifndef __cplusplus - choke me -#endif -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - for ac_declaration in \ - '' \ - 'extern "C" void std::exit (int) throw (); using std::exit;' \ - 'extern "C" void std::exit (int); using std::exit;' \ - 'extern "C" void exit (int) throw ();' \ - 'extern "C" void exit (int);' \ - 'void exit (int);' -do - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_declaration -#include -int -main () -{ -exit (42); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -continue -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_declaration -int -main () -{ -exit (42); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - break -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -done -rm -f conftest* -if test -n "$ac_declaration"; then - echo '#ifdef __cplusplus' >>confdefs.h - echo $ac_declaration >>confdefs.h - echo '#endif' >>confdefs.h -fi - -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -# Find a good install program. We prefer a C program (faster), -# so one script is as good as another. But avoid the broken or -# incompatible versions: -# SysV /etc/install, /usr/sbin/install -# SunOS /usr/etc/install -# IRIX /sbin/install -# AIX /bin/install -# AmigaOS /C/install, which installs bootblocks on floppy discs -# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag -# AFS /usr/afsws/bin/install, which mishandles nonexistent args -# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" -# OS/2's system install, which has a completely different semantic -# ./install, which can be erroneously created by make from ./install.sh. -echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 -echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 -if test -z "$INSTALL"; then -if test "${ac_cv_path_install+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - # Account for people who put trailing slashes in PATH elements. -case $as_dir/ in - ./ | .// | /cC/* | \ - /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ - ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ - /usr/ucb/* ) ;; - *) - # OSF1 and SCO ODT 3.0 have their own names for install. - # Don't use installbsd from OSF since it installs stuff as root - # by default. - for ac_prog in ginstall scoinst install; do - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then - if test $ac_prog = install && - grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then - # AIX install. It has an incompatible calling convention. - : - elif test $ac_prog = install && - grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then - # program-specific install script used by HP pwplus--don't use. - : - else - ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" - break 3 - fi - fi - done - done - ;; -esac -done - - -fi - if test "${ac_cv_path_install+set}" = set; then - INSTALL=$ac_cv_path_install - else - # As a last resort, use the slow shell script. We don't cache a - # path for INSTALL within a source directory, because that will - # break other packages using the cache if that directory is - # removed, or if the path is relative. - INSTALL=$ac_install_sh - fi -fi -echo "$as_me:$LINENO: result: $INSTALL" >&5 -echo "${ECHO_T}$INSTALL" >&6 - -# Use test -z because SunOS4 sh mishandles braces in ${var-val}. -# It thinks the first close brace ends the variable substitution. -test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' - -test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' - -test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' - - -if test "$GCC" = yes ; then - OLDCFLAGS="$CFLAGS -Wall -Wmissing-prototypes -Wstrict-prototypes" - CFLAGS="$OLDCFLAGS -fexceptions" - echo "$as_me:$LINENO: checking whether $CC accepts -fexceptions" >&5 -echo $ECHO_N "checking whether $CC accepts -fexceptions... $ECHO_C" >&6 - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; CFLAGS="$OLDCFLAGS" -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - CXXFLAGS=`echo "$CFLAGS" | sed 's/ -Wmissing-prototypes -Wstrict-prototypes//'` -fi - -echo "$as_me:$LINENO: checking for ANSI C header files" >&5 -echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 -if test "${ac_cv_header_stdc+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -#include -#include -#include - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_header_stdc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_header_stdc=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext - -if test $ac_cv_header_stdc = yes; then - # SunOS 4.x string.h does not declare mem*, contrary to ANSI. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "memchr" >/dev/null 2>&1; then - : -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "free" >/dev/null 2>&1; then - : -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. - if test "$cross_compiling" = yes; then - : -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -#if ((' ' & 0x0FF) == 0x020) -# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') -# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) -#else -# define ISLOWER(c) \ - (('a' <= (c) && (c) <= 'i') \ - || ('j' <= (c) && (c) <= 'r') \ - || ('s' <= (c) && (c) <= 'z')) -# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) -#endif - -#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) -int -main () -{ - int i; - for (i = 0; i < 256; i++) - if (XOR (islower (i), ISLOWER (i)) - || toupper (i) != TOUPPER (i)) - exit(2); - exit (0); -} -_ACEOF -rm -f conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { ac_try='./conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - : -else - echo "$as_me: program exited with status $ac_status" >&5 -echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -( exit $ac_status ) -ac_cv_header_stdc=no -fi -rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext -fi -fi -fi -echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 -echo "${ECHO_T}$ac_cv_header_stdc" >&6 -if test $ac_cv_header_stdc = yes; then - -cat >>confdefs.h <<\_ACEOF -#define STDC_HEADERS 1 -_ACEOF - -fi - - - -echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5 -echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6 -if test "${ac_cv_c_bigendian+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_c_bigendian=unknown -# See if sys/param.h defines the BYTE_ORDER macro. -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -#include -int -main () -{ - -#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN - bogus endian macros -#endif - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - # It does; now see whether it defined to BIG_ENDIAN or not. -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -#include -int -main () -{ - -#if BYTE_ORDER != BIG_ENDIAN - not big endian -#endif - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_c_bigendian=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_c_bigendian=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -if test $ac_cv_c_bigendian = unknown; then -if test "$cross_compiling" = yes; then - echo $ac_n "cross-compiling... " 2>&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -main () { - /* Are we little or big endian? From Harbison&Steele. */ - union - { - long l; - char c[sizeof (long)]; - } u; - u.l = 1; - exit (u.c[sizeof (long) - 1] == 1); -} -_ACEOF -rm -f conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { ac_try='./conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_c_bigendian=no -else - echo "$as_me: program exited with status $ac_status" >&5 -echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -( exit $ac_status ) -ac_cv_c_bigendian=yes -fi -rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext -fi -fi -fi -echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5 -echo "${ECHO_T}$ac_cv_c_bigendian" >&6 -if test $ac_cv_c_bigendian = unknown; then -echo "$as_me:$LINENO: checking to probe for byte ordering" >&5 -echo $ECHO_N "checking to probe for byte ordering... $ECHO_C" >&6 - -cat >conftest.c <&6 - ac_cv_c_bigendian=yes - fi - if test `grep -l LiTTleEnDian conftest.o` ; then - echo $ac_n ' little endian probe OK, ' 1>&6 - if test $ac_cv_c_bigendian = yes ; then - ac_cv_c_bigendian=unknown; - else - ac_cv_c_bigendian=no - fi - fi - echo $ac_n 'guessing bigendian ... ' >&6 - fi - fi -echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5 -echo "${ECHO_T}$ac_cv_c_bigendian" >&6 -fi -if test $ac_cv_c_bigendian = yes; then - -cat >>confdefs.h <<\_ACEOF -#define WORDS_BIGENDIAN 1 -_ACEOF - - BYTEORDER=4321 -else - BYTEORDER=1234 -fi - -cat >>confdefs.h <<_ACEOF -#define BYTEORDER $BYTEORDER -_ACEOF - -if test $ac_cv_c_bigendian = unknown; then - { { echo "$as_me:$LINENO: error: unknown endianess - sorry" >&5 -echo "$as_me: error: unknown endianess - sorry" >&2;} - { (exit please pre-set ac_cv_c_bigendian); exit please pre-set ac_cv_c_bigendian; }; } -fi - - -echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5 -echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6 -if test "${ac_cv_c_const+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ -/* FIXME: Include the comments suggested by Paul. */ -#ifndef __cplusplus - /* Ultrix mips cc rejects this. */ - typedef int charset[2]; - const charset x; - /* SunOS 4.1.1 cc rejects this. */ - char const *const *ccp; - char **p; - /* NEC SVR4.0.2 mips cc rejects this. */ - struct point {int x, y;}; - static struct point const zero = {0,0}; - /* AIX XL C 1.02.0.0 rejects this. - It does not let you subtract one const X* pointer from another in - an arm of an if-expression whose if-part is not a constant - expression */ - const char *g = "string"; - ccp = &g + (g ? g-g : 0); - /* HPUX 7.0 cc rejects these. */ - ++ccp; - p = (char**) ccp; - ccp = (char const *const *) p; - { /* SCO 3.2v4 cc rejects this. */ - char *t; - char const *s = 0 ? (char *) 0 : (char const *) 0; - - *t++ = 0; - } - { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ - int x[] = {25, 17}; - const int *foo = &x[0]; - ++foo; - } - { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ - typedef const int *iptr; - iptr p = 0; - ++p; - } - { /* AIX XL C 1.02.0.0 rejects this saying - "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ - struct s { int j; const int *ap[3]; }; - struct s *b; b->j = 5; - } - { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ - const int foo = 10; - } -#endif - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_c_const=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_c_const=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5 -echo "${ECHO_T}$ac_cv_c_const" >&6 -if test $ac_cv_c_const = no; then - -cat >>confdefs.h <<\_ACEOF -#define const -_ACEOF - -fi - -echo "$as_me:$LINENO: checking for size_t" >&5 -echo $ECHO_N "checking for size_t... $ECHO_C" >&6 -if test "${ac_cv_type_size_t+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -if ((size_t *) 0) - return 0; -if (sizeof (size_t)) - return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_type_size_t=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_type_size_t=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5 -echo "${ECHO_T}$ac_cv_type_size_t" >&6 -if test $ac_cv_type_size_t = yes; then - : -else - -cat >>confdefs.h <<_ACEOF -#define size_t unsigned -_ACEOF - -fi - - - -for ac_func in memmove bcopy -do -as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` -echo "$as_me:$LINENO: checking for $ac_func" >&5 -echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 -if eval "test \"\${$as_ac_var+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define $ac_func to an innocuous variant, in case declares $ac_func. - For example, HP-UX 11i declares gettimeofday. */ -#define $ac_func innocuous_$ac_func - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char $ac_func (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef $ac_func - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -{ -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char $ac_func (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_$ac_func) || defined (__stub___$ac_func) -choke me -#else -char (*f) () = $ac_func; -#endif -#ifdef __cplusplus -} -#endif - -int -main () -{ -return f != $ac_func; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - eval "$as_ac_var=yes" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -eval "$as_ac_var=no" -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 -if test `eval echo '${'$as_ac_var'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF - -fi -done - - - - -for ac_header in fcntl.h unistd.h -do -as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 -else - # Is the header compilable? -echo "$as_me:$LINENO: checking $ac_header usability" >&5 -echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include <$ac_header> -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_header_compiler=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_header_compiler=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6 - -# Is the header present? -echo "$as_me:$LINENO: checking $ac_header presence" >&5 -echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <$ac_header> -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - ac_header_preproc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no -fi -rm -f conftest.err conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6 - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in - yes:no: ) - { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} - ac_header_preproc=yes - ;; - no:yes:* ) - { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 -echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 -echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 -echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 -echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} - ( - cat <<\_ASBOX -## -------------------------------------- ## -## Report this to expat-bugs@libexpat.org ## -## -------------------------------------- ## -_ASBOX - ) | - sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac -echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - eval "$as_ac_Header=\$ac_header_preproc" -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 - -fi -if test `eval echo '${'$as_ac_Header'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - -fi - -done - -echo "$as_me:$LINENO: checking for off_t" >&5 -echo $ECHO_N "checking for off_t... $ECHO_C" >&6 -if test "${ac_cv_type_off_t+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -if ((off_t *) 0) - return 0; -if (sizeof (off_t)) - return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_type_off_t=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_type_off_t=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_type_off_t" >&5 -echo "${ECHO_T}$ac_cv_type_off_t" >&6 -if test $ac_cv_type_off_t = yes; then - : -else - -cat >>confdefs.h <<_ACEOF -#define off_t long -_ACEOF - -fi - - - -for ac_header in stdlib.h unistd.h -do -as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 -else - # Is the header compilable? -echo "$as_me:$LINENO: checking $ac_header usability" >&5 -echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include <$ac_header> -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_header_compiler=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_header_compiler=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6 - -# Is the header present? -echo "$as_me:$LINENO: checking $ac_header presence" >&5 -echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <$ac_header> -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - ac_header_preproc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no -fi -rm -f conftest.err conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6 - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in - yes:no: ) - { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} - ac_header_preproc=yes - ;; - no:yes:* ) - { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 -echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 -echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 -echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 -echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} - ( - cat <<\_ASBOX -## -------------------------------------- ## -## Report this to expat-bugs@libexpat.org ## -## -------------------------------------- ## -_ASBOX - ) | - sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac -echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - eval "$as_ac_Header=\$ac_header_preproc" -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 - -fi -if test `eval echo '${'$as_ac_Header'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - -fi - -done - - -for ac_func in getpagesize -do -as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` -echo "$as_me:$LINENO: checking for $ac_func" >&5 -echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 -if eval "test \"\${$as_ac_var+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define $ac_func to an innocuous variant, in case declares $ac_func. - For example, HP-UX 11i declares gettimeofday. */ -#define $ac_func innocuous_$ac_func - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char $ac_func (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef $ac_func - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -{ -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char $ac_func (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_$ac_func) || defined (__stub___$ac_func) -choke me -#else -char (*f) () = $ac_func; -#endif -#ifdef __cplusplus -} -#endif - -int -main () -{ -return f != $ac_func; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - eval "$as_ac_var=yes" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -eval "$as_ac_var=no" -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 -if test `eval echo '${'$as_ac_var'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF - -fi -done - -echo "$as_me:$LINENO: checking for working mmap" >&5 -echo $ECHO_N "checking for working mmap... $ECHO_C" >&6 -if test "${ac_cv_func_mmap_fixed_mapped+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test "$cross_compiling" = yes; then - ac_cv_func_mmap_fixed_mapped=no -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -/* malloc might have been renamed as rpl_malloc. */ -#undef malloc - -/* Thanks to Mike Haertel and Jim Avera for this test. - Here is a matrix of mmap possibilities: - mmap private not fixed - mmap private fixed at somewhere currently unmapped - mmap private fixed at somewhere already mapped - mmap shared not fixed - mmap shared fixed at somewhere currently unmapped - mmap shared fixed at somewhere already mapped - For private mappings, we should verify that changes cannot be read() - back from the file, nor mmap's back from the file at a different - address. (There have been systems where private was not correctly - implemented like the infamous i386 svr4.0, and systems where the - VM page cache was not coherent with the file system buffer cache - like early versions of FreeBSD and possibly contemporary NetBSD.) - For shared mappings, we should conversely verify that changes get - propagated back to all the places they're supposed to be. - - Grep wants private fixed already mapped. - The main things grep needs to know about mmap are: - * does it exist and is it safe to write into the mmap'd area - * how to use it (BSD variants) */ - -#include -#include - -#if !STDC_HEADERS && !HAVE_STDLIB_H -char *malloc (); -#endif - -/* This mess was copied from the GNU getpagesize.h. */ -#if !HAVE_GETPAGESIZE -/* Assume that all systems that can run configure have sys/param.h. */ -# if !HAVE_SYS_PARAM_H -# define HAVE_SYS_PARAM_H 1 -# endif - -# ifdef _SC_PAGESIZE -# define getpagesize() sysconf(_SC_PAGESIZE) -# else /* no _SC_PAGESIZE */ -# if HAVE_SYS_PARAM_H -# include -# ifdef EXEC_PAGESIZE -# define getpagesize() EXEC_PAGESIZE -# else /* no EXEC_PAGESIZE */ -# ifdef NBPG -# define getpagesize() NBPG * CLSIZE -# ifndef CLSIZE -# define CLSIZE 1 -# endif /* no CLSIZE */ -# else /* no NBPG */ -# ifdef NBPC -# define getpagesize() NBPC -# else /* no NBPC */ -# ifdef PAGESIZE -# define getpagesize() PAGESIZE -# endif /* PAGESIZE */ -# endif /* no NBPC */ -# endif /* no NBPG */ -# endif /* no EXEC_PAGESIZE */ -# else /* no HAVE_SYS_PARAM_H */ -# define getpagesize() 8192 /* punt totally */ -# endif /* no HAVE_SYS_PARAM_H */ -# endif /* no _SC_PAGESIZE */ - -#endif /* no HAVE_GETPAGESIZE */ - -int -main () -{ - char *data, *data2, *data3; - int i, pagesize; - int fd; - - pagesize = getpagesize (); - - /* First, make a file with some known garbage in it. */ - data = (char *) malloc (pagesize); - if (!data) - exit (1); - for (i = 0; i < pagesize; ++i) - *(data + i) = rand (); - umask (0); - fd = creat ("conftest.mmap", 0600); - if (fd < 0) - exit (1); - if (write (fd, data, pagesize) != pagesize) - exit (1); - close (fd); - - /* Next, try to mmap the file at a fixed address which already has - something else allocated at it. If we can, also make sure that - we see the same garbage. */ - fd = open ("conftest.mmap", O_RDWR); - if (fd < 0) - exit (1); - data2 = (char *) malloc (2 * pagesize); - if (!data2) - exit (1); - data2 += (pagesize - ((long) data2 & (pagesize - 1))) & (pagesize - 1); - if (data2 != mmap (data2, pagesize, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_FIXED, fd, 0L)) - exit (1); - for (i = 0; i < pagesize; ++i) - if (*(data + i) != *(data2 + i)) - exit (1); - - /* Finally, make sure that changes to the mapped area do not - percolate back to the file as seen by read(). (This is a bug on - some variants of i386 svr4.0.) */ - for (i = 0; i < pagesize; ++i) - *(data2 + i) = *(data2 + i) + 1; - data3 = (char *) malloc (pagesize); - if (!data3) - exit (1); - if (read (fd, data3, pagesize) != pagesize) - exit (1); - for (i = 0; i < pagesize; ++i) - if (*(data + i) != *(data3 + i)) - exit (1); - close (fd); - exit (0); -} -_ACEOF -rm -f conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { ac_try='./conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_func_mmap_fixed_mapped=yes -else - echo "$as_me: program exited with status $ac_status" >&5 -echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -( exit $ac_status ) -ac_cv_func_mmap_fixed_mapped=no -fi -rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext -fi -fi -echo "$as_me:$LINENO: result: $ac_cv_func_mmap_fixed_mapped" >&5 -echo "${ECHO_T}$ac_cv_func_mmap_fixed_mapped" >&6 -if test $ac_cv_func_mmap_fixed_mapped = yes; then - -cat >>confdefs.h <<\_ACEOF -#define HAVE_MMAP 1 -_ACEOF - -fi -rm -f conftest.mmap - - -if test "$ac_cv_func_mmap_fixed_mapped" = "yes"; then - FILEMAP=unixfilemap -else - FILEMAP=readfilemap -fi - - - -# AC_CPP_FUNC -# ------------------ # -# Checks to see if ANSI C99 CPP variable __func__ works. -# If not, perhaps __FUNCTION__ works instead. -# If not, we'll just define __func__ to "". -# AC_CPP_FUNC - - -echo "$as_me:$LINENO: checking for an ANSI C99-conforming __func__" >&5 -echo $ECHO_N "checking for an ANSI C99-conforming __func__... $ECHO_C" >&6 -if test "${ac_cv_cpp_func+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ -char *foo = __func__; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_cpp_func=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ -char *foo = __FUNCTION__; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_cpp_func=__FUNCTION__ -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_cpp_func=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_cpp_func" >&5 -echo "${ECHO_T}$ac_cv_cpp_func" >&6 -if test $ac_cv_cpp_func = __FUNCTION__; then - -cat >>confdefs.h <<\_ACEOF -#define __func__ __FUNCTION__ -_ACEOF - -elif test $ac_cv_cpp_func = no; then - -cat >>confdefs.h <<\_ACEOF -#define __func__ "" -_ACEOF - -fi - - - - -cat >>confdefs.h <<\_ACEOF -#define XML_NS 1 -_ACEOF - - -cat >>confdefs.h <<\_ACEOF -#define XML_DTD 1 -_ACEOF - - -cat >>confdefs.h <<\_ACEOF -#define XML_CONTEXT_BYTES 1024 -_ACEOF - - - ac_config_files="$ac_config_files Makefile" - -cat >confcache <<\_ACEOF -# This file is a shell script that caches the results of configure -# tests run on this system so they can be shared between configure -# scripts and configure runs, see configure's option --config-cache. -# It is not useful on other systems. If it contains results you don't -# want to keep, you may remove or edit it. -# -# config.status only pays attention to the cache file if you give it -# the --recheck option to rerun configure. -# -# `ac_cv_env_foo' variables (set or unset) will be overridden when -# loading this file, other *unset* `ac_cv_foo' will be assigned the -# following values. - -_ACEOF - -# The following way of writing the cache mishandles newlines in values, -# but we know of no workaround that is simple, portable, and efficient. -# So, don't put newlines in cache variables' values. -# Ultrix sh set writes to stderr and can't be redirected directly, -# and sets the high bit in the cache file unless we assign to the vars. -{ - (set) 2>&1 | - case `(ac_space=' '; set | grep ac_space) 2>&1` in - *ac_space=\ *) - # `set' does not quote correctly, so add quotes (double-quote - # substitution turns \\\\ into \\, and sed turns \\ into \). - sed -n \ - "s/'/'\\\\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" - ;; - *) - # `set' quotes correctly as required by POSIX, so do not add quotes. - sed -n \ - "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" - ;; - esac; -} | - sed ' - t clear - : clear - s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ - t end - /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ - : end' >>confcache -if diff $cache_file confcache >/dev/null 2>&1; then :; else - if test -w $cache_file; then - test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" - cat confcache >$cache_file - else - echo "not updating unwritable cache $cache_file" - fi -fi -rm -f confcache - -test "x$prefix" = xNONE && prefix=$ac_default_prefix -# Let make expand exec_prefix. -test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' - -# VPATH may cause trouble with some makes, so we remove $(srcdir), -# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and -# trailing colons and then remove the whole line if VPATH becomes empty -# (actually we leave an empty line to preserve line numbers). -if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=/{ -s/:*\$(srcdir):*/:/; -s/:*\${srcdir}:*/:/; -s/:*@srcdir@:*/:/; -s/^\([^=]*=[ ]*\):*/\1/; -s/:*$//; -s/^[^=]*=[ ]*$//; -}' -fi - -DEFS=-DHAVE_CONFIG_H - -ac_libobjs= -ac_ltlibobjs= -for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue - # 1. Remove the extension, and $U if already installed. - ac_i=`echo "$ac_i" | - sed 's/\$U\././;s/\.o$//;s/\.obj$//'` - # 2. Add them. - ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" - ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' -done -LIBOBJS=$ac_libobjs - -LTLIBOBJS=$ac_ltlibobjs - - - -: ${CONFIG_STATUS=./config.status} -ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files $CONFIG_STATUS" -{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 -echo "$as_me: creating $CONFIG_STATUS" >&6;} -cat >$CONFIG_STATUS <<_ACEOF -#! $SHELL -# Generated by $as_me. -# Run this file to recreate the current configuration. -# Compiler output produced by configure, useful for debugging -# configure, is in config.log if it exists. - -debug=false -ac_cs_recheck=false -ac_cs_silent=false -SHELL=\${CONFIG_SHELL-$SHELL} -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF -## --------------------- ## -## M4sh Initialization. ## -## --------------------- ## - -# Be Bourne compatible -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' -elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then - set -o posix -fi -DUALCASE=1; export DUALCASE # for MKS sh - -# Support unset when possible. -if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then - as_unset=unset -else - as_unset=false -fi - - -# Work around bugs in pre-3.0 UWIN ksh. -$as_unset ENV MAIL MAILPATH -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -for as_var in \ - LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ - LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ - LC_TELEPHONE LC_TIME -do - if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then - eval $as_var=C; export $as_var - else - $as_unset $as_var - fi -done - -# Required to use basename. -if expr a : '\(a\)' >/dev/null 2>&1; then - as_expr=expr -else - as_expr=false -fi - -if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - - -# Name of the executable. -as_me=`$as_basename "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)$' \| \ - . : '\(.\)' 2>/dev/null || -echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } - /^X\/\(\/\/\)$/{ s//\1/; q; } - /^X\/\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - - -# PATH needs CR, and LINENO needs CR and PATH. -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - echo "#! /bin/sh" >conf$$.sh - echo "exit 0" >>conf$$.sh - chmod +x conf$$.sh - if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then - PATH_SEPARATOR=';' - else - PATH_SEPARATOR=: - fi - rm -f conf$$.sh -fi - - - as_lineno_1=$LINENO - as_lineno_2=$LINENO - as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x$as_lineno_3" = "x$as_lineno_2" || { - # Find who we are. Look in the path if we contain no path at all - # relative or not. - case $0 in - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break -done - - ;; - esac - # We did not find ourselves, most probably we were run as `sh COMMAND' - # in which case we are not to be found in the path. - if test "x$as_myself" = x; then - as_myself=$0 - fi - if test ! -f "$as_myself"; then - { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 -echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} - { (exit 1); exit 1; }; } - fi - case $CONFIG_SHELL in - '') - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for as_base in sh bash ksh sh5; do - case $as_dir in - /*) - if ("$as_dir/$as_base" -c ' - as_lineno_1=$LINENO - as_lineno_2=$LINENO - as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then - $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } - $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } - CONFIG_SHELL=$as_dir/$as_base - export CONFIG_SHELL - exec "$CONFIG_SHELL" "$0" ${1+"$@"} - fi;; - esac - done -done -;; - esac - - # Create $as_me.lineno as a copy of $as_myself, but with $LINENO - # uniformly replaced by the line number. The first 'sed' inserts a - # line-number line before each line; the second 'sed' does the real - # work. The second script uses 'N' to pair each line-number line - # with the numbered line, and appends trailing '-' during - # substitution so that $LINENO is not a special case at line end. - # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the - # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) - sed '=' <$as_myself | - sed ' - N - s,$,-, - : loop - s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, - t loop - s,-$,, - s,^['$as_cr_digits']*\n,, - ' >$as_me.lineno && - chmod +x $as_me.lineno || - { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 -echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} - { (exit 1); exit 1; }; } - - # Don't try to exec as it changes $[0], causing all sort of problems - # (the dirname of $[0] is not the place where we might find the - # original and so on. Autoconf is especially sensible to this). - . ./$as_me.lineno - # Exit status is that of the last command. - exit -} - - -case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in - *c*,-n*) ECHO_N= ECHO_C=' -' ECHO_T=' ' ;; - *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; - *) ECHO_N= ECHO_C='\c' ECHO_T= ;; -esac - -if expr a : '\(a\)' >/dev/null 2>&1; then - as_expr=expr -else - as_expr=false -fi - -rm -f conf$$ conf$$.exe conf$$.file -echo >conf$$.file -if ln -s conf$$.file conf$$ 2>/dev/null; then - # We could just check for DJGPP; but this test a) works b) is more generic - # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). - if test -f conf$$.exe; then - # Don't use ln at all; we don't have any links - as_ln_s='cp -p' - else - as_ln_s='ln -s' - fi -elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln -else - as_ln_s='cp -p' -fi -rm -f conf$$ conf$$.exe conf$$.file - -if mkdir -p . 2>/dev/null; then - as_mkdir_p=: -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - -as_executable_p="test -f" - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - - -# IFS -# We need space, tab and new line, in precisely that order. -as_nl=' -' -IFS=" $as_nl" - -# CDPATH. -$as_unset CDPATH - -exec 6>&1 - -# Open the log real soon, to keep \$[0] and so on meaningful, and to -# report actual input values of CONFIG_FILES etc. instead of their -# values after options handling. Logging --version etc. is OK. -exec 5>>config.log -{ - echo - sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX -## Running $as_me. ## -_ASBOX -} >&5 -cat >&5 <<_CSEOF - -This file was extended by expat $as_me 2.0.1, which was -generated by GNU Autoconf 2.59. Invocation command line was - - CONFIG_FILES = $CONFIG_FILES - CONFIG_HEADERS = $CONFIG_HEADERS - CONFIG_LINKS = $CONFIG_LINKS - CONFIG_COMMANDS = $CONFIG_COMMANDS - $ $0 $@ - -_CSEOF -echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 -echo >&5 -_ACEOF - -# Files that config.status was made for. -if test -n "$ac_config_files"; then - echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS -fi - -if test -n "$ac_config_headers"; then - echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS -fi - -if test -n "$ac_config_links"; then - echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS -fi - -if test -n "$ac_config_commands"; then - echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS -fi - -cat >>$CONFIG_STATUS <<\_ACEOF - -ac_cs_usage="\ -\`$as_me' instantiates files from templates according to the -current configuration. - -Usage: $0 [OPTIONS] [FILE]... - - -h, --help print this help, then exit - -V, --version print version number, then exit - -q, --quiet do not print progress messages - -d, --debug don't remove temporary files - --recheck update $as_me by reconfiguring in the same conditions - --file=FILE[:TEMPLATE] - instantiate the configuration file FILE - --header=FILE[:TEMPLATE] - instantiate the configuration header FILE - -Configuration files: -$config_files - -Configuration headers: -$config_headers - -Report bugs to ." -_ACEOF - -cat >>$CONFIG_STATUS <<_ACEOF -ac_cs_version="\\ -expat config.status 2.0.1 -configured by $0, generated by GNU Autoconf 2.59, - with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" - -Copyright (C) 2003 Free Software Foundation, Inc. -This config.status script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it." -srcdir=$srcdir -INSTALL="$INSTALL" -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF -# If no file are specified by the user, then we need to provide default -# value. By we need to know if files were specified by the user. -ac_need_defaults=: -while test $# != 0 -do - case $1 in - --*=*) - ac_option=`expr "x$1" : 'x\([^=]*\)='` - ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` - ac_shift=: - ;; - -*) - ac_option=$1 - ac_optarg=$2 - ac_shift=shift - ;; - *) # This is not an option, so the user has probably given explicit - # arguments. - ac_option=$1 - ac_need_defaults=false;; - esac - - case $ac_option in - # Handling of the options. -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF - -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) - ac_cs_recheck=: ;; - --version | --vers* | -V ) - echo "$ac_cs_version"; exit 0 ;; - --he | --h) - # Conflict between --help and --header - { { echo "$as_me:$LINENO: error: ambiguous option: $1 -Try \`$0 --help' for more information." >&5 -echo "$as_me: error: ambiguous option: $1 -Try \`$0 --help' for more information." >&2;} - { (exit 1); exit 1; }; };; - --help | --hel | -h ) - echo "$ac_cs_usage"; exit 0 ;; - --debug | --d* | -d ) - debug=: ;; - --file | --fil | --fi | --f ) - $ac_shift - CONFIG_FILES="$CONFIG_FILES $ac_optarg" - ac_need_defaults=false;; - --header | --heade | --head | --hea ) - $ac_shift - CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" - ac_need_defaults=false;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil | --si | --s) - ac_cs_silent=: ;; - - # This is an error. - -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 -Try \`$0 --help' for more information." >&5 -echo "$as_me: error: unrecognized option: $1 -Try \`$0 --help' for more information." >&2;} - { (exit 1); exit 1; }; } ;; - - *) ac_config_targets="$ac_config_targets $1" ;; - - esac - shift -done - -ac_configure_extra_args= - -if $ac_cs_silent; then - exec 6>/dev/null - ac_configure_extra_args="$ac_configure_extra_args --silent" -fi - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF -if \$ac_cs_recheck; then - echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 - exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion -fi - -_ACEOF - - - - - -cat >>$CONFIG_STATUS <<\_ACEOF -for ac_config_target in $ac_config_targets -do - case "$ac_config_target" in - # Handling of arguments. - "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; - "expat_config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS expat_config.h" ;; - *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 -echo "$as_me: error: invalid argument: $ac_config_target" >&2;} - { (exit 1); exit 1; }; };; - esac -done - -# If the user did not use the arguments to specify the items to instantiate, -# then the envvar interface is used. Set only those that are not. -# We use the long form for the default assignment because of an extremely -# bizarre bug on SunOS 4.1.3. -if $ac_need_defaults; then - test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files - test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers -fi - -# Have a temporary directory for convenience. Make it in the build tree -# simply because there is no reason to put it here, and in addition, -# creating and moving files from /tmp can sometimes cause problems. -# Create a temporary directory, and hook for its removal unless debugging. -$debug || -{ - trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 - trap '{ (exit 1); exit 1; }' 1 2 13 15 -} - -# Create a (secure) tmp directory for tmp files. - -{ - tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && - test -n "$tmp" && test -d "$tmp" -} || -{ - tmp=./confstat$$-$RANDOM - (umask 077 && mkdir $tmp) -} || -{ - echo "$me: cannot create a temporary directory in ." >&2 - { (exit 1); exit 1; } -} - -_ACEOF - -cat >>$CONFIG_STATUS <<_ACEOF - -# -# CONFIG_FILES section. -# - -# No need to generate the scripts if there are no CONFIG_FILES. -# This happens for instance when ./config.status config.h -if test -n "\$CONFIG_FILES"; then - # Protect against being on the right side of a sed subst in config.status. - sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; - s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF -s,@SHELL@,$SHELL,;t t -s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t -s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t -s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t -s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t -s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t -s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t -s,@exec_prefix@,$exec_prefix,;t t -s,@prefix@,$prefix,;t t -s,@program_transform_name@,$program_transform_name,;t t -s,@bindir@,$bindir,;t t -s,@sbindir@,$sbindir,;t t -s,@libexecdir@,$libexecdir,;t t -s,@datadir@,$datadir,;t t -s,@sysconfdir@,$sysconfdir,;t t -s,@sharedstatedir@,$sharedstatedir,;t t -s,@localstatedir@,$localstatedir,;t t -s,@libdir@,$libdir,;t t -s,@includedir@,$includedir,;t t -s,@oldincludedir@,$oldincludedir,;t t -s,@infodir@,$infodir,;t t -s,@mandir@,$mandir,;t t -s,@build_alias@,$build_alias,;t t -s,@host_alias@,$host_alias,;t t -s,@target_alias@,$target_alias,;t t -s,@DEFS@,$DEFS,;t t -s,@ECHO_C@,$ECHO_C,;t t -s,@ECHO_N@,$ECHO_N,;t t -s,@ECHO_T@,$ECHO_T,;t t -s,@LIBS@,$LIBS,;t t -s,@build@,$build,;t t -s,@build_cpu@,$build_cpu,;t t -s,@build_vendor@,$build_vendor,;t t -s,@build_os@,$build_os,;t t -s,@host@,$host,;t t -s,@host_cpu@,$host_cpu,;t t -s,@host_vendor@,$host_vendor,;t t -s,@host_os@,$host_os,;t t -s,@CC@,$CC,;t t -s,@CFLAGS@,$CFLAGS,;t t -s,@LDFLAGS@,$LDFLAGS,;t t -s,@CPPFLAGS@,$CPPFLAGS,;t t -s,@ac_ct_CC@,$ac_ct_CC,;t t -s,@EXEEXT@,$EXEEXT,;t t -s,@OBJEXT@,$OBJEXT,;t t -s,@EGREP@,$EGREP,;t t -s,@LN_S@,$LN_S,;t t -s,@ECHO@,$ECHO,;t t -s,@AR@,$AR,;t t -s,@ac_ct_AR@,$ac_ct_AR,;t t -s,@RANLIB@,$RANLIB,;t t -s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t -s,@STRIP@,$STRIP,;t t -s,@ac_ct_STRIP@,$ac_ct_STRIP,;t t -s,@DLLTOOL@,$DLLTOOL,;t t -s,@ac_ct_DLLTOOL@,$ac_ct_DLLTOOL,;t t -s,@AS@,$AS,;t t -s,@ac_ct_AS@,$ac_ct_AS,;t t -s,@OBJDUMP@,$OBJDUMP,;t t -s,@ac_ct_OBJDUMP@,$ac_ct_OBJDUMP,;t t -s,@CPP@,$CPP,;t t -s,@CXX@,$CXX,;t t -s,@CXXFLAGS@,$CXXFLAGS,;t t -s,@ac_ct_CXX@,$ac_ct_CXX,;t t -s,@CXXCPP@,$CXXCPP,;t t -s,@F77@,$F77,;t t -s,@FFLAGS@,$FFLAGS,;t t -s,@ac_ct_F77@,$ac_ct_F77,;t t -s,@LIBTOOL@,$LIBTOOL,;t t -s,@LIBCURRENT@,$LIBCURRENT,;t t -s,@LIBREVISION@,$LIBREVISION,;t t -s,@LIBAGE@,$LIBAGE,;t t -s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t -s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t -s,@INSTALL_DATA@,$INSTALL_DATA,;t t -s,@FILEMAP@,$FILEMAP,;t t -s,@LIBOBJS@,$LIBOBJS,;t t -s,@LTLIBOBJS@,$LTLIBOBJS,;t t -CEOF - -_ACEOF - - cat >>$CONFIG_STATUS <<\_ACEOF - # Split the substitutions into bite-sized pieces for seds with - # small command number limits, like on Digital OSF/1 and HP-UX. - ac_max_sed_lines=48 - ac_sed_frag=1 # Number of current file. - ac_beg=1 # First line for current file. - ac_end=$ac_max_sed_lines # Line after last line for current file. - ac_more_lines=: - ac_sed_cmds= - while $ac_more_lines; do - if test $ac_beg -gt 1; then - sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag - else - sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag - fi - if test ! -s $tmp/subs.frag; then - ac_more_lines=false - else - # The purpose of the label and of the branching condition is to - # speed up the sed processing (if there are no `@' at all, there - # is no need to browse any of the substitutions). - # These are the two extra sed commands mentioned above. - (echo ':t - /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed - if test -z "$ac_sed_cmds"; then - ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" - else - ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" - fi - ac_sed_frag=`expr $ac_sed_frag + 1` - ac_beg=$ac_end - ac_end=`expr $ac_end + $ac_max_sed_lines` - fi - done - if test -z "$ac_sed_cmds"; then - ac_sed_cmds=cat - fi -fi # test -n "$CONFIG_FILES" - -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF -for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue - # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". - case $ac_file in - - | *:- | *:-:* ) # input from stdin - cat >$tmp/stdin - ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` - ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; - *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` - ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; - * ) ac_file_in=$ac_file.in ;; - esac - - # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. - ac_dir=`(dirname "$ac_file") 2>/dev/null || -$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$ac_file" : 'X\(//\)[^/]' \| \ - X"$ac_file" : 'X\(//\)$' \| \ - X"$ac_file" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$ac_file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - { if $as_mkdir_p; then - mkdir -p "$ac_dir" - else - as_dir="$ac_dir" - as_dirs= - while test ! -d "$as_dir"; do - as_dirs="$as_dir $as_dirs" - as_dir=`(dirname "$as_dir") 2>/dev/null || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - done - test ! -n "$as_dirs" || mkdir $as_dirs - fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 -echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} - { (exit 1); exit 1; }; }; } - - ac_builddir=. - -if test "$ac_dir" != .; then - ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` - # A "../" for each directory in $ac_dir_suffix. - ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` -else - ac_dir_suffix= ac_top_builddir= -fi - -case $srcdir in - .) # No --srcdir option. We are building in place. - ac_srcdir=. - if test -z "$ac_top_builddir"; then - ac_top_srcdir=. - else - ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` - fi ;; - [\\/]* | ?:[\\/]* ) # Absolute path. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir ;; - *) # Relative path. - ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_builddir$srcdir ;; -esac - -# Do not use `cd foo && pwd` to compute absolute paths, because -# the directories may not exist. -case `pwd` in -.) ac_abs_builddir="$ac_dir";; -*) - case "$ac_dir" in - .) ac_abs_builddir=`pwd`;; - [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; - *) ac_abs_builddir=`pwd`/"$ac_dir";; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_top_builddir=${ac_top_builddir}.;; -*) - case ${ac_top_builddir}. in - .) ac_abs_top_builddir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; - *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_srcdir=$ac_srcdir;; -*) - case $ac_srcdir in - .) ac_abs_srcdir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; - *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_top_srcdir=$ac_top_srcdir;; -*) - case $ac_top_srcdir in - .) ac_abs_top_srcdir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; - *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; - esac;; -esac - - - case $INSTALL in - [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; - *) ac_INSTALL=$ac_top_builddir$INSTALL ;; - esac - - if test x"$ac_file" != x-; then - { echo "$as_me:$LINENO: creating $ac_file" >&5 -echo "$as_me: creating $ac_file" >&6;} - rm -f "$ac_file" - fi - # Let's still pretend it is `configure' which instantiates (i.e., don't - # use $as_me), people would be surprised to read: - # /* config.h. Generated by config.status. */ - if test x"$ac_file" = x-; then - configure_input= - else - configure_input="$ac_file. " - fi - configure_input=$configure_input"Generated from `echo $ac_file_in | - sed 's,.*/,,'` by configure." - - # First look for the input files in the build tree, otherwise in the - # src tree. - ac_file_inputs=`IFS=: - for f in $ac_file_in; do - case $f in - -) echo $tmp/stdin ;; - [\\/$]*) - # Absolute (can't be DOS-style, as IFS=:) - test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 -echo "$as_me: error: cannot find input file: $f" >&2;} - { (exit 1); exit 1; }; } - echo "$f";; - *) # Relative - if test -f "$f"; then - # Build tree - echo "$f" - elif test -f "$srcdir/$f"; then - # Source tree - echo "$srcdir/$f" - else - # /dev/null tree - { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 -echo "$as_me: error: cannot find input file: $f" >&2;} - { (exit 1); exit 1; }; } - fi;; - esac - done` || { (exit 1); exit 1; } -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF - sed "$ac_vpsub -$extrasub -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF -:t -/@[a-zA-Z_][a-zA-Z_0-9]*@/!b -s,@configure_input@,$configure_input,;t t -s,@srcdir@,$ac_srcdir,;t t -s,@abs_srcdir@,$ac_abs_srcdir,;t t -s,@top_srcdir@,$ac_top_srcdir,;t t -s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t -s,@builddir@,$ac_builddir,;t t -s,@abs_builddir@,$ac_abs_builddir,;t t -s,@top_builddir@,$ac_top_builddir,;t t -s,@abs_top_builddir@,$ac_abs_top_builddir,;t t -s,@INSTALL@,$ac_INSTALL,;t t -" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out - rm -f $tmp/stdin - if test x"$ac_file" != x-; then - mv $tmp/out $ac_file - else - cat $tmp/out - rm -f $tmp/out - fi - -done -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF - -# -# CONFIG_HEADER section. -# - -# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where -# NAME is the cpp macro being defined and VALUE is the value it is being given. -# -# ac_d sets the value in "#define NAME VALUE" lines. -ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)' -ac_dB='[ ].*$,\1#\2' -ac_dC=' ' -ac_dD=',;t' -# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE". -ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' -ac_uB='$,\1#\2define\3' -ac_uC=' ' -ac_uD=',;t' - -for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue - # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". - case $ac_file in - - | *:- | *:-:* ) # input from stdin - cat >$tmp/stdin - ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` - ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; - *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` - ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; - * ) ac_file_in=$ac_file.in ;; - esac - - test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5 -echo "$as_me: creating $ac_file" >&6;} - - # First look for the input files in the build tree, otherwise in the - # src tree. - ac_file_inputs=`IFS=: - for f in $ac_file_in; do - case $f in - -) echo $tmp/stdin ;; - [\\/$]*) - # Absolute (can't be DOS-style, as IFS=:) - test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 -echo "$as_me: error: cannot find input file: $f" >&2;} - { (exit 1); exit 1; }; } - # Do quote $f, to prevent DOS paths from being IFS'd. - echo "$f";; - *) # Relative - if test -f "$f"; then - # Build tree - echo "$f" - elif test -f "$srcdir/$f"; then - # Source tree - echo "$srcdir/$f" - else - # /dev/null tree - { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 -echo "$as_me: error: cannot find input file: $f" >&2;} - { (exit 1); exit 1; }; } - fi;; - esac - done` || { (exit 1); exit 1; } - # Remove the trailing spaces. - sed 's/[ ]*$//' $ac_file_inputs >$tmp/in - -_ACEOF - -# Transform confdefs.h into two sed scripts, `conftest.defines' and -# `conftest.undefs', that substitutes the proper values into -# config.h.in to produce config.h. The first handles `#define' -# templates, and the second `#undef' templates. -# And first: Protect against being on the right side of a sed subst in -# config.status. Protect against being in an unquoted here document -# in config.status. -rm -f conftest.defines conftest.undefs -# Using a here document instead of a string reduces the quoting nightmare. -# Putting comments in sed scripts is not portable. -# -# `end' is used to avoid that the second main sed command (meant for -# 0-ary CPP macros) applies to n-ary macro definitions. -# See the Autoconf documentation for `clear'. -cat >confdef2sed.sed <<\_ACEOF -s/[\\&,]/\\&/g -s,[\\$`],\\&,g -t clear -: clear -s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp -t end -s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp -: end -_ACEOF -# If some macros were called several times there might be several times -# the same #defines, which is useless. Nevertheless, we may not want to -# sort them, since we want the *last* AC-DEFINE to be honored. -uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines -sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs -rm -f confdef2sed.sed - -# This sed command replaces #undef with comments. This is necessary, for -# example, in the case of _POSIX_SOURCE, which is predefined and required -# on some systems where configure will not decide to define it. -cat >>conftest.undefs <<\_ACEOF -s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, -_ACEOF - -# Break up conftest.defines because some shells have a limit on the size -# of here documents, and old seds have small limits too (100 cmds). -echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS -echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS -echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS -echo ' :' >>$CONFIG_STATUS -rm -f conftest.tail -while grep . conftest.defines >/dev/null -do - # Write a limited-size here document to $tmp/defines.sed. - echo ' cat >$tmp/defines.sed <>$CONFIG_STATUS - # Speed up: don't consider the non `#define' lines. - echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS - # Work around the forget-to-reset-the-flag bug. - echo 't clr' >>$CONFIG_STATUS - echo ': clr' >>$CONFIG_STATUS - sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS - echo 'CEOF - sed -f $tmp/defines.sed $tmp/in >$tmp/out - rm -f $tmp/in - mv $tmp/out $tmp/in -' >>$CONFIG_STATUS - sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail - rm -f conftest.defines - mv conftest.tail conftest.defines -done -rm -f conftest.defines -echo ' fi # grep' >>$CONFIG_STATUS -echo >>$CONFIG_STATUS - -# Break up conftest.undefs because some shells have a limit on the size -# of here documents, and old seds have small limits too (100 cmds). -echo ' # Handle all the #undef templates' >>$CONFIG_STATUS -rm -f conftest.tail -while grep . conftest.undefs >/dev/null -do - # Write a limited-size here document to $tmp/undefs.sed. - echo ' cat >$tmp/undefs.sed <>$CONFIG_STATUS - # Speed up: don't consider the non `#undef' - echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS - # Work around the forget-to-reset-the-flag bug. - echo 't clr' >>$CONFIG_STATUS - echo ': clr' >>$CONFIG_STATUS - sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS - echo 'CEOF - sed -f $tmp/undefs.sed $tmp/in >$tmp/out - rm -f $tmp/in - mv $tmp/out $tmp/in -' >>$CONFIG_STATUS - sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail - rm -f conftest.undefs - mv conftest.tail conftest.undefs -done -rm -f conftest.undefs - -cat >>$CONFIG_STATUS <<\_ACEOF - # Let's still pretend it is `configure' which instantiates (i.e., don't - # use $as_me), people would be surprised to read: - # /* config.h. Generated by config.status. */ - if test x"$ac_file" = x-; then - echo "/* Generated by configure. */" >$tmp/config.h - else - echo "/* $ac_file. Generated by configure. */" >$tmp/config.h - fi - cat $tmp/in >>$tmp/config.h - rm -f $tmp/in - if test x"$ac_file" != x-; then - if diff $ac_file $tmp/config.h >/dev/null 2>&1; then - { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 -echo "$as_me: $ac_file is unchanged" >&6;} - else - ac_dir=`(dirname "$ac_file") 2>/dev/null || -$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$ac_file" : 'X\(//\)[^/]' \| \ - X"$ac_file" : 'X\(//\)$' \| \ - X"$ac_file" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$ac_file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - { if $as_mkdir_p; then - mkdir -p "$ac_dir" - else - as_dir="$ac_dir" - as_dirs= - while test ! -d "$as_dir"; do - as_dirs="$as_dir $as_dirs" - as_dir=`(dirname "$as_dir") 2>/dev/null || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - done - test ! -n "$as_dirs" || mkdir $as_dirs - fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 -echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} - { (exit 1); exit 1; }; }; } - - rm -f $ac_file - mv $tmp/config.h $ac_file - fi - else - cat $tmp/config.h - rm -f $tmp/config.h - fi -done -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF - -{ (exit 0); exit 0; } -_ACEOF -chmod +x $CONFIG_STATUS -ac_clean_files=$ac_clean_files_save - - -# configure is writing to config.log, and then calls config.status. -# config.status does its own redirection, appending to config.log. -# Unfortunately, on DOS this fails, as config.log is still kept open -# by configure, so config.status won't be able to write to it; its -# output is simply discarded. So we exec the FD to /dev/null, -# effectively closing config.log, so it can be properly (re)opened and -# appended to by config.status. When coming back to configure, we -# need to make the FD available again. -if test "$no_create" != yes; then - ac_cs_success=: - ac_config_status_args= - test "$silent" = yes && - ac_config_status_args="$ac_config_status_args --quiet" - exec 5>/dev/null - $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false - exec 5>>config.log - # Use ||, not &&, to avoid exiting from the if with $? = 1, which - # would make configure fail if this is the last instruction. - $ac_cs_success || { (exit 1); exit 1; } -fi - - -abs_srcdir="`cd $srcdir && pwd`" -abs_builddir="`pwd`" -if test "$abs_srcdir" != "$abs_builddir"; then - make mkdir-init -fi diff --git a/configure.in b/configure.in index 24bcb407e0d..7e968c46de3 100644 --- a/configure.in +++ b/configure.in @@ -10,8 +10,8 @@ dnl under the terms of the License (based on the MIT/X license) contained dnl in the file COPYING that comes with this distribution. dnl -dnl Ensure that Expat is configured with autoconf 2.52 or newer -AC_PREREQ(2.52) +dnl Ensure that Expat is configured with autoconf 2.58 or newer +AC_PREREQ(2.58) dnl Get the version number of Expat, using m4's esyscmd() command to run dnl the command at m4-generation time. This allows us to create an m4 @@ -25,12 +25,13 @@ dnl test. I believe this test will work, but I don't have a place with non- dnl GNU M4 to test it right now. define([expat_version], ifdef([__gnu__], [esyscmd(conftools/get-version.sh lib/expat.h)], - [2.0.x])) + [2.1.x])) AC_INIT(expat, expat_version, expat-bugs@libexpat.org) undefine([expat_version]) AC_CONFIG_SRCDIR(Makefile.in) AC_CONFIG_AUX_DIR(conftools) +AC_CONFIG_MACRO_DIR([m4]) dnl @@ -44,13 +45,12 @@ dnl dnl If the API changes incompatibly set LIBAGE back to 0 dnl -LIBCURRENT=6 -LIBREVISION=2 -LIBAGE=5 +LIBCURRENT=7 +LIBREVISION=0 +LIBAGE=6 AC_CONFIG_HEADER(expat_config.h) -sinclude(conftools/libtool.m4) sinclude(conftools/ac_c_bigendian_cross.m4) AC_LIBTOOL_WIN32_DLL @@ -62,6 +62,7 @@ AC_SUBST(LIBAGE) dnl Checks for programs. AC_PROG_CC +AC_PROG_CXX AC_PROG_INSTALL if test "$GCC" = yes ; then @@ -144,7 +145,7 @@ AC_DEFINE([XML_DTD], 1, AC_DEFINE([XML_CONTEXT_BYTES], 1024, [Define to specify how much context to retain around the current parse point.]) -AC_CONFIG_FILES(Makefile) +AC_CONFIG_FILES([Makefile expat.pc]) AC_OUTPUT abs_srcdir="`cd $srcdir && pwd`" diff --git a/doc/reference.html b/doc/reference.html index a315870dd7c..8811a3397c7 100644 --- a/doc/reference.html +++ b/doc/reference.html @@ -129,8 +129,10 @@ interface.

  1. XML_GetBase
  2. XML_GetSpecifiedAttributeCount
  3. XML_GetIdAttributeIndex
  4. +
  5. XML_GetAttributeInfo
  6. XML_SetEncoding
  7. XML_SetParamEntityParsing
  8. +
  9. XML_SetHashSalt
  10. XML_UseForeignDTD
  11. XML_SetReturnNSTriplet
  12. XML_DefaultCurrent
  13. @@ -369,6 +371,11 @@ footprint and can be faster. statically with the code that calls it; this is required to get all the right MSVC magic annotations correct. This is ignored on other platforms. + +
    XML_ATTR_INFO
    +
    If defined, makes the the additional function XML_GetAttributeInfo available +for reporting attribute byte offsets.

    @@ -917,12 +924,15 @@ XML_ParserCreateNS(const XML_Char *encoding, Constructs a new parser that has namespace processing in effect. Namespace expanded element names and attribute names are returned as a concatenation of the namespace URI, sep, and the local part of the name. This -means that you should pick a character for sep that can't be -part of a legal URI. There is a special case when sep is the null -character '\0': the namespace URI and the local part will be -concatenated without any separator - this is intended to support RDF processors. -It is a programming error to use the null separator with -namespace triplets. +means that you should pick a character for sep that can't be part +of an URI. Since Expat does not check namespace URIs for conformance, the +only safe choice for a namespace separator is a character that is illegal +in XML. For instance, '\xFF' is not legal in UTF-8, and +'\xFFFF' is not legal in UTF-16. There is a special case when +sep is the null character '\0': the namespace URI and +the local part will be concatenated without any separator - this is intended +to support RDF processors. It is a programming error to use the null separator +with namespace triplets.
     XML_Parser XMLCALL
    @@ -2074,6 +2084,27 @@ attribute. If called inside a start handler, then that means the
     current call.
     
     
    +
    +const XML_AttrInfo * XMLCALL
    +XML_GetAttributeInfo(XML_Parser parser);
    +
    +
    +typedef struct {
    +  XML_Index  nameStart;  /* Offset to beginning of the attribute name. */
    +  XML_Index  nameEnd;    /* Offset after the attribute name's last byte. */
    +  XML_Index  valueStart; /* Offset to beginning of the attribute value. */
    +  XML_Index  valueEnd;   /* Offset after the attribute value's last byte. */
    +} XML_AttrInfo;
    +
    +
    +Returns an array of XML_AttrInfo structures for the +attribute/value pairs passed in the last call to the +XML_StartElementHandler that were specified +in the start-tag rather than defaulted. Each attribute/value pair counts +as 1; thus the number of entries in the array is +XML_GetSpecifiedAttributeCount(parser) / 2. +
    +
     enum XML_Status XMLCALL
     XML_SetEncoding(XML_Parser p,
    @@ -2104,6 +2135,24 @@ The choices for code are:
     
  14. XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE
  15. XML_PARAM_ENTITY_PARSING_ALWAYS
  16. +Note: If XML_SetParamEntityParsing is called after +XML_Parse or XML_ParseBuffer, then it has +no effect and will always return 0. + + +
    +int XMLCALL
    +XML_SetHashSalt(XML_Parser p,
    +                unsigned long hash_salt);
    +
    +
    +Sets the hash salt to use for internal hash calculations. +Helps in preventing DoS attacks based on predicting hash +function behavior. In order to have an effect this must be called +before parsing has started. Returns 1 if successful, 0 when called +after XML_Parse or XML_ParseBuffer. +

    Note: This call is optional, as the parser will auto-generate a new +random salt value if no value has been set at the start of parsing.

    diff --git a/doc/valid-xhtml10.png b/doc/valid-xhtml10.png
    deleted file mode 100755
    index 4c23f48fe02a58fbb3d1088e6a7d372568830b53..0000000000000000000000000000000000000000
    GIT binary patch
    literal 0
    HcmV?d00001
    
    literal 2368
    zcmbVNX;2f{7H-8QAWIODU~n{oVqipj2Gj;zXrn-jfGsLCqYzsnPDF&p1zT|;Y|_rS
    zG$U$6T%rydH;kg#qJRP9(E@6_VH9x;sL%+GanDQ5do}fb&5w6(-TKbG-???Zuj*9Y
    zyvXoiJDXuP007v9hR9G0MqBm>ffWGsad*5W1AxA{kzr9YEtdwPktHFmR%@VOjSA)&
    zoWU@I3T8>tpwXyl(x5~21YyvkYJtGSU^GS0B#P4v2q8Gd&;Y=2MoP=_T2#YuoPk$q
    z^sK?iaz>G*Rw`f+2}zO|h6sfMihzU&g`o&R5IPzW2mqB5l!z<{sBloJRB9=hBOtvR
    zG4ni*7aZszoQI$?fGZ2KRb(~rN=#@$}0O&Ostz&hN2!bFDDiw(YGzpP7C=v>2
    z0s=vhQ6pN3&|okCAj!~(PykR$5Rj5msZ>K@9LMP>m}OZbZ_?}aj0RIdQYo$`)C{9j
    zV=5i1!OSMk(%j5*I4Z>vDFCT>Jq~~>H3_Lz7)^j$8Y2mdY>cL9t=?cVn@uJ&Oln~S
    zVf1=Jt>=t9OlT>Jf?=WC}BuMC{d|INMN9uQ^KH#u(V^9Mg~J+
    z39CUZq)~^NSX@P*COwW}m_-@{BYI4#qcH(OqbRCl4H8TZAe8y90F@eADFt8(A+-pC
    zkQNO(++gH!3^n}~oEC>+*r3%K8Jy>N2oxDD1v-ln6qE{SnnWNGsYF4Ekfulsk#Jgz
    zLIHtEdCO$L5;KQ$8k8a}I&rfeSE3S?mKBLaW}dLP6=Jm6NHA(lh|)SlA`}W4*1#|f
    zL}&yEg`x4lr}-7+3wMlqyF={n!T4V9EeMwS$Ii;hQ-5s#b|B-&
    z^0k*l@0<7rwu{X$l~;V6qOf-+-Z)Obd4U}D_8z_2@7au-G3OHKvyQVoL<7(6Uzppk
    z&GDM}&q#-oZcXiiH?z__HO>^+cSHCYkr=Oj&KaDoWCQW3U`x!sK~)9g$gdf2c4&Ni
    z?6=WkP3)S+*n-#grETtop`{*2LPpDF8)Qz_c*KyCEn~xuQKh&4dZx!4%?5Owj^wrHZNb`-KoZWZr0n-NbZyfPpZP1Pz?!j)p
    zA#oS|y0+~LvYk?~u6l_hboP3aXoT0Hw7?UOS4@4m`
    zla;1?MUFD#{O8zftHeEci3}{h+c~lNmhggf`n3v&y@|`E=jTjwLd9e9YqP9EV)CU)
    zn@SJ+9>=t`+i@5$X&
    zOBeezmLz^$vA#foB1=_E@Ao0R%F|+I8Gov(yZ3Q&SW#lM(4RXnpD#9yYOsxaJxM$y
    z!78@1s^M0))$*){Wwl6sfVzb#J$3rbsg#S$j!*Irnj5h`wOj1E^@G#F_+K+86-CPL
    z%Uc~9oW5ksb3cT&ZZGOL?COAJw|(2MPM^B7%KG!lfXg}Od>zV$*0=3@{poe$n^>oZ
    zH7nwKpNQl2p5eCpI?G<#NJPyiteboLKe@fVcwt0+AknetuD;JtT+6%#w>HfU{m$*$7tbeM1BWUc?BhDKavT?o_Xm$VDzO{fhUl-g4+v}5J?CesCp7o}6bHRC@XBLld<~&;{
    zY{J|{xm6nB^Wdszc1HftOZyrR(@Pf>h7I=V*!!$-#`B8rd*^lCZw{ypv>cHaiN!w>szMg{>z%h_f_Id>mx^<^GRN#Xz
    zCqC>xeER9jv|qL-R{9b4JLfIx#IJOt(M<|J`QG|Uz9BR{&|p2tcDuvG#-?KT)_rZa
    zgRl!rLYIhNJ)ip0)hqc{Q&z$L;7##mN4{QF@IUf40qL1fh9Zpi|Xcd6q+U5hJ@_A^g(aNKfk|iGsv=R1`YZs
    oi4;OEvV%bfcgjD_ar)+RxUQtjXTTPP<@*6bXNJp8!|_}H4I+HVz5oCK
    
    diff --git a/doc/xmlwf.sgml b/doc/xmlwf.sgml
    index 139c95e1f11..313cfbcb210 100644
    --- a/doc/xmlwf.sgml
    +++ b/doc/xmlwf.sgml
    @@ -388,11 +388,6 @@ supports both.
       
       
         BUGS
    -	
    -	According to the W3C standard, an XML file without a
    -	declaration at the beginning is not considered well-formed.
    -	However, &dhpackage; allows this to pass.
    -	
     	
     	&dhpackage; returns a 0 - noerr result,
     	even if the file is not well-formed.  There is no good way for
    diff --git a/expat_config.h.in b/expat_config.h.in
    index 8c3698afd93..8c6e51409e0 100644
    --- a/expat_config.h.in
    +++ b/expat_config.h.in
    @@ -39,6 +39,9 @@
     /* Define to 1 if you have the  header file. */
     #undef HAVE_STRING_H
     
    +/* Define to 1 if you have the  header file. */
    +#undef HAVE_SYS_PARAM_H
    +
     /* Define to 1 if you have the  header file. */
     #undef HAVE_SYS_STAT_H
     
    @@ -48,6 +51,10 @@
     /* Define to 1 if you have the  header file. */
     #undef HAVE_UNISTD_H
     
    +/* Define to the sub-directory in which libtool stores uninstalled libraries.
    +   */
    +#undef LT_OBJDIR
    +
     /* Define to the address where bug reports for this package should be sent. */
     #undef PACKAGE_BUGREPORT
     
    @@ -60,6 +67,9 @@
     /* Define to the one symbol short name of this package. */
     #undef PACKAGE_TARNAME
     
    +/* Define to the home page for this package. */
    +#undef PACKAGE_URL
    +
     /* Define to the version of this package. */
     #undef PACKAGE_VERSION
     
    @@ -85,8 +95,8 @@
     /* Define to empty if `const' does not conform to ANSI C. */
     #undef const
     
    -/* Define to `long' if  does not define. */
    +/* Define to `long int' if  does not define. */
     #undef off_t
     
    -/* Define to `unsigned' if  does not define. */
    +/* Define to `unsigned int' if  does not define. */
     #undef size_t
    diff --git a/lib/expat.h b/lib/expat.h
    index 20a8278f78d..9a21680be46 100644
    --- a/lib/expat.h
    +++ b/lib/expat.h
    @@ -742,6 +742,29 @@ XML_GetSpecifiedAttributeCount(XML_Parser parser);
     XMLPARSEAPI(int)
     XML_GetIdAttributeIndex(XML_Parser parser);
     
    +#ifdef XML_ATTR_INFO
    +/* Source file byte offsets for the start and end of attribute names and values.
    +   The value indices are exclusive of surrounding quotes; thus in a UTF-8 source
    +   file an attribute value of "blah" will yield:
    +   info->valueEnd - info->valueStart = 4 bytes.
    +*/
    +typedef struct {
    +  XML_Index  nameStart;  /* Offset to beginning of the attribute name. */
    +  XML_Index  nameEnd;    /* Offset after the attribute name's last byte. */
    +  XML_Index  valueStart; /* Offset to beginning of the attribute value. */
    +  XML_Index  valueEnd;   /* Offset after the attribute value's last byte. */
    +} XML_AttrInfo;
    +
    +/* Returns an array of XML_AttrInfo structures for the attribute/value pairs
    +   passed in last call to the XML_StartElementHandler that were specified
    +   in the start-tag rather than defaulted. Each attribute/value pair counts
    +   as 1; thus the number of entries in the array is
    +   XML_GetSpecifiedAttributeCount(parser) / 2.
    +*/
    +XMLPARSEAPI(const XML_AttrInfo *)
    +XML_GetAttributeInfo(XML_Parser parser);
    +#endif
    +
     /* Parses some input. Returns XML_STATUS_ERROR if a fatal error is
        detected.  The last call to XML_Parse must have isFinal true; len
        may be zero for this call (or any other).
    @@ -883,6 +906,15 @@ XMLPARSEAPI(int)
     XML_SetParamEntityParsing(XML_Parser parser,
                               enum XML_ParamEntityParsing parsing);
     
    +/* Sets the hash salt to use for internal hash calculations.
    +   Helps in preventing DoS attacks based on predicting hash
    +   function behavior. This must be called before parsing is started.
    +   Returns 1 if successful, 0 when called after parsing has started.
    +*/
    +XMLPARSEAPI(int)
    +XML_SetHashSalt(XML_Parser parser,
    +                unsigned long hash_salt);
    +
     /* If XML_Parse or XML_ParseBuffer have returned XML_STATUS_ERROR, then
        XML_GetErrorCode returns information about the error.
     */
    @@ -984,7 +1016,8 @@ enum XML_FeatureEnum {
       XML_FEATURE_SIZEOF_XML_CHAR,
       XML_FEATURE_SIZEOF_XML_LCHAR,
       XML_FEATURE_NS,
    -  XML_FEATURE_LARGE_SIZE
    +  XML_FEATURE_LARGE_SIZE,
    +  XML_FEATURE_ATTR_INFO
       /* Additional features must be added to the end of this enum. */
     };
     
    @@ -1004,8 +1037,8 @@ XML_GetFeatureList(void);
        change to major or minor version.
     */
     #define XML_MAJOR_VERSION 2
    -#define XML_MINOR_VERSION 0
    -#define XML_MICRO_VERSION 1
    +#define XML_MINOR_VERSION 1
    +#define XML_MICRO_VERSION 0
     
     #ifdef __cplusplus
     }
    diff --git a/lib/winconfig.h b/lib/winconfig.h
    deleted file mode 100644
    index c1b791d62d0..00000000000
    --- a/lib/winconfig.h
    +++ /dev/null
    @@ -1,30 +0,0 @@
    -/*================================================================
    -** Copyright 2000, Clark Cooper
    -** All rights reserved.
    -**
    -** This is free software. You are permitted to copy, distribute, or modify
    -** it under the terms of the MIT/X license (contained in the COPYING file
    -** with this distribution.)
    -*/
    -
    -#ifndef WINCONFIG_H
    -#define WINCONFIG_H
    -
    -#define WIN32_LEAN_AND_MEAN
    -#include 
    -#undef WIN32_LEAN_AND_MEAN
    -
    -#include 
    -#include 
    -
    -#define XML_NS 1
    -#define XML_DTD 1
    -#define XML_CONTEXT_BYTES 1024
    -
    -/* we will assume all Windows platforms are little endian */
    -#define BYTEORDER 1234
    -
    -/* Windows has memmove() available. */
    -#define HAVE_MEMMOVE
    -
    -#endif /* ndef WINCONFIG_H */
    diff --git a/lib/xmlparse.c b/lib/xmlparse.c
    index e111460d0a3..f35aa36ba8a 100644
    --- a/lib/xmlparse.c
    +++ b/lib/xmlparse.c
    @@ -5,6 +5,8 @@
     #include 
     #include                      /* memset(), memcpy() */
     #include 
    +#include                      /* UINT_MAX */
    +#include                        /* time() */
     
     #define XML_BUILDING_EXPAT 1
     
    @@ -12,7 +14,7 @@
     #include "winconfig.h"
     #elif defined(MACOS_CLASSIC)
     #include "macconfig.h"
    -#elif defined(__amigaos4__)
    +#elif defined(__amigaos__)
     #include "amigaconfig.h"
     #elif defined(__WATCOMC__)
     #include "watcomconfig.h"
    @@ -327,15 +329,15 @@ processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
     static enum XML_Error
     initializeEncoding(XML_Parser parser);
     static enum XML_Error
    -doProlog(XML_Parser parser, const ENCODING *enc, const char *s, 
    -         const char *end, int tok, const char *next, const char **nextPtr, 
    +doProlog(XML_Parser parser, const ENCODING *enc, const char *s,
    +         const char *end, int tok, const char *next, const char **nextPtr,
              XML_Bool haveMore);
     static enum XML_Error
    -processInternalEntity(XML_Parser parser, ENTITY *entity, 
    +processInternalEntity(XML_Parser parser, ENTITY *entity,
                           XML_Bool betweenDecl);
     static enum XML_Error
     doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
    -          const char *start, const char *end, const char **endPtr, 
    +          const char *start, const char *end, const char **endPtr,
               XML_Bool haveMore);
     static enum XML_Error
     doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr,
    @@ -353,7 +355,7 @@ static enum XML_Error
     addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
                const XML_Char *uri, BINDING **bindingsPtr);
     static int
    -defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, XML_Bool isCdata, 
    +defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, XML_Bool isCdata,
                     XML_Bool isId, const XML_Char *dfltValue, XML_Parser parser);
     static enum XML_Error
     storeAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
    @@ -391,12 +393,13 @@ static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms);
     static void
     dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms);
     static int
    -dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms);
    +dtdCopy(XML_Parser oldParser,
    +        DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms);
     static int
    -copyEntityTable(HASH_TABLE *, STRING_POOL *, const HASH_TABLE *);
    -
    +copyEntityTable(XML_Parser oldParser,
    +                HASH_TABLE *, STRING_POOL *, const HASH_TABLE *);
     static NAMED *
    -lookup(HASH_TABLE *table, KEY name, size_t createSize);
    +lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize);
     static void FASTCALL
     hashTableInit(HASH_TABLE *, const XML_Memory_Handling_Suite *ms);
     static void FASTCALL hashTableClear(HASH_TABLE *);
    @@ -429,11 +432,15 @@ static ELEMENT_TYPE *
     getElementType(XML_Parser parser, const ENCODING *enc,
                    const char *ptr, const char *end);
     
    +static unsigned long generate_hash_secret_salt(void);
    +static XML_Bool startParsing(XML_Parser parser);
    +
     static XML_Parser
     parserCreate(const XML_Char *encodingName,
                  const XML_Memory_Handling_Suite *memsuite,
                  const XML_Char *nameSep,
                  DTD *dtd);
    +
     static void
     parserInit(XML_Parser parser, const XML_Char *encodingName);
     
    @@ -533,6 +540,9 @@ struct XML_ParserStruct {
       NS_ATT *m_nsAtts;
       unsigned long m_nsAttsVersion;
       unsigned char m_nsAttsPower;
    +#ifdef XML_ATTR_INFO
    +  XML_AttrInfo *m_attInfo;
    +#endif
       POSITION m_position;
       STRING_POOL m_tempPool;
       STRING_POOL m_temp2Pool;
    @@ -546,6 +556,7 @@ struct XML_ParserStruct {
       XML_Bool m_useForeignDTD;
       enum XML_ParamEntityParsing m_paramEntityParsing;
     #endif
    +  unsigned long m_hash_secret_salt;
     };
     
     #define MALLOC(s) (parser->m_mem.malloc_fcn((s)))
    @@ -640,6 +651,7 @@ struct XML_ParserStruct {
     #define nsAtts (parser->m_nsAtts)
     #define nsAttsVersion (parser->m_nsAttsVersion)
     #define nsAttsPower (parser->m_nsAttsPower)
    +#define attInfo (parser->m_attInfo)
     #define tempPool (parser->m_tempPool)
     #define temp2Pool (parser->m_temp2Pool)
     #define groupConnector (parser->m_groupConnector)
    @@ -653,6 +665,7 @@ struct XML_ParserStruct {
     #define useForeignDTD (parser->m_useForeignDTD)
     #define paramEntityParsing (parser->m_paramEntityParsing)
     #endif /* XML_DTD */
    +#define hash_secret_salt (parser->m_hash_secret_salt)
     
     XML_Parser XMLCALL
     XML_ParserCreate(const XML_Char *encodingName)
    @@ -670,29 +683,42 @@ XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep)
     
     static const XML_Char implicitContext[] = {
       ASCII_x, ASCII_m, ASCII_l, ASCII_EQUALS, ASCII_h, ASCII_t, ASCII_t, ASCII_p,
    -  ASCII_COLON, ASCII_SLASH, ASCII_SLASH, ASCII_w, ASCII_w, ASCII_w, 
    +  ASCII_COLON, ASCII_SLASH, ASCII_SLASH, ASCII_w, ASCII_w, ASCII_w,
       ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD, ASCII_o, ASCII_r, ASCII_g,
       ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L, ASCII_SLASH, ASCII_1, ASCII_9,
       ASCII_9, ASCII_8, ASCII_SLASH, ASCII_n, ASCII_a, ASCII_m, ASCII_e,
       ASCII_s, ASCII_p, ASCII_a, ASCII_c, ASCII_e, '\0'
     };
     
    +static unsigned long
    +generate_hash_secret_salt(void)
    +{
    +  unsigned int seed = time(NULL) % UINT_MAX;
    +  srand(seed);
    +  return rand();
    +}
    +
    +static XML_Bool  /* only valid for root parser */
    +startParsing(XML_Parser parser)
    +{
    +    /* hash functions must be initialized before setContext() is called */
    +    if (hash_secret_salt == 0)
    +      hash_secret_salt = generate_hash_secret_salt();
    +    if (ns) {
    +      /* implicit context only set for root parser, since child
    +         parsers (i.e. external entity parsers) will inherit it
    +      */
    +      return setContext(parser, implicitContext);
    +    }
    +    return XML_TRUE;
    +}
    +
     XML_Parser XMLCALL
     XML_ParserCreate_MM(const XML_Char *encodingName,
                         const XML_Memory_Handling_Suite *memsuite,
                         const XML_Char *nameSep)
     {
    -  XML_Parser parser = parserCreate(encodingName, memsuite, nameSep, NULL);
    -  if (parser != NULL && ns) {
    -    /* implicit context only set for root parser, since child
    -       parsers (i.e. external entity parsers) will inherit it
    -    */
    -    if (!setContext(parser, implicitContext)) {
    -      XML_ParserFree(parser);
    -      return NULL;
    -    }
    -  }
    -  return parser;
    +  return parserCreate(encodingName, memsuite, nameSep, NULL);
     }
     
     static XML_Parser
    @@ -737,9 +763,20 @@ parserCreate(const XML_Char *encodingName,
         FREE(parser);
         return NULL;
       }
    +#ifdef XML_ATTR_INFO
    +  attInfo = (XML_AttrInfo*)MALLOC(attsSize * sizeof(XML_AttrInfo));
    +  if (attInfo == NULL) {
    +    FREE(atts);
    +    FREE(parser);
    +    return NULL;
    +  }
    +#endif
       dataBuf = (XML_Char *)MALLOC(INIT_DATA_BUF_SIZE * sizeof(XML_Char));
       if (dataBuf == NULL) {
         FREE(atts);
    +#ifdef XML_ATTR_INFO
    +    FREE(attInfo);
    +#endif
         FREE(parser);
         return NULL;
       }
    @@ -752,6 +789,9 @@ parserCreate(const XML_Char *encodingName,
         if (_dtd == NULL) {
           FREE(dataBuf);
           FREE(atts);
    +#ifdef XML_ATTR_INFO
    +      FREE(attInfo);
    +#endif
           FREE(parser);
           return NULL;
         }
    @@ -866,6 +906,7 @@ parserInit(XML_Parser parser, const XML_Char *encodingName)
       useForeignDTD = XML_FALSE;
       paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
     #endif
    +  hash_secret_salt = 0;
     }
     
     /* moves list of bindings to freeBindingList */
    @@ -913,7 +954,7 @@ XML_ParserReset(XML_Parser parser, const XML_Char *encodingName)
       poolClear(&temp2Pool);
       parserInit(parser, encodingName);
       dtdReset(_dtd, &parser->m_mem);
    -  return setContext(parser, implicitContext);
    +  return XML_TRUE;
     }
     
     enum XML_Status XMLCALL
    @@ -982,6 +1023,12 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser,
       int oldInEntityValue = prologState.inEntityValue;
     #endif
       XML_Bool oldns_triplets = ns_triplets;
    +  /* Note that the new parser shares the same hash secret as the old
    +     parser, so that dtdCopy and copyEntityTable can lookup values
    +     from hash tables associated with either parser without us having
    +     to worry which hash secrets each table has.
    +  */
    +  unsigned long oldhash_secret_salt = hash_secret_salt;
     
     #ifdef XML_DTD
       if (!context)
    @@ -1035,13 +1082,14 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser,
         externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
       defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
       ns_triplets = oldns_triplets;
    +  hash_secret_salt = oldhash_secret_salt;
       parentParser = oldParser;
     #ifdef XML_DTD
       paramEntityParsing = oldParamEntityParsing;
       prologState.inEntityValue = oldInEntityValue;
       if (context) {
     #endif /* XML_DTD */
    -    if (!dtdCopy(_dtd, oldDtd, &parser->m_mem)
    +    if (!dtdCopy(oldParser, _dtd, oldDtd, &parser->m_mem)
           || !setContext(parser, context)) {
           XML_ParserFree(parser);
           return NULL;
    @@ -1130,6 +1178,9 @@ XML_ParserFree(XML_Parser parser)
     #endif /* XML_DTD */
         dtdDestroy(_dtd, (XML_Bool)!parentParser, &parser->m_mem);
       FREE((void *)atts);
    +#ifdef XML_ATTR_INFO
    +  FREE((void *)attInfo);
    +#endif
       FREE(groupConnector);
       FREE(buffer);
       FREE(dataBuf);
    @@ -1210,6 +1261,14 @@ XML_GetIdAttributeIndex(XML_Parser parser)
       return idAttIndex;
     }
     
    +#ifdef XML_ATTR_INFO
    +const XML_AttrInfo * XMLCALL
    +XML_GetAttributeInfo(XML_Parser parser)
    +{
    +  return attInfo;
    +}
    +#endif
    +
     void XMLCALL
     XML_SetElementHandler(XML_Parser parser,
                           XML_StartElementHandler start,
    @@ -1426,6 +1485,17 @@ XML_SetParamEntityParsing(XML_Parser parser,
     #endif
     }
     
    +int XMLCALL
    +XML_SetHashSalt(XML_Parser parser,
    +                unsigned long hash_salt)
    +{
    +  /* block after XML_Parse()/XML_ParseBuffer() has been called */
    +  if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
    +    return 0;
    +  hash_secret_salt = hash_salt;
    +  return 1;
    +}
    +
     enum XML_Status XMLCALL
     XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
     {
    @@ -1436,6 +1506,11 @@ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
       case XML_FINISHED:
         errorCode = XML_ERROR_FINISHED;
         return XML_STATUS_ERROR;
    +  case XML_INITIALIZED:
    +    if (parentParser == NULL && !startParsing(parser)) {
    +      errorCode = XML_ERROR_NO_MEMORY;
    +      return XML_STATUS_ERROR;
    +    }
       default:
         ps_parsing = XML_PARSING;
       }
    @@ -1459,7 +1534,7 @@ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
             XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
             positionPtr = bufferPtr;
             return XML_STATUS_SUSPENDED;
    -      case XML_INITIALIZED: 
    +      case XML_INITIALIZED:
           case XML_PARSING:
             ps_parsing = XML_FINISHED;
             /* fall through */
    @@ -1494,11 +1569,13 @@ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
             break;
           case XML_INITIALIZED:
           case XML_PARSING:
    -        result = XML_STATUS_OK;
             if (isFinal) {
               ps_parsing = XML_FINISHED;
    -          return result;
    +          return XML_STATUS_OK;
             }
    +      /* fall through */
    +      default:
    +        result = XML_STATUS_OK;
           }
         }
     
    @@ -1512,16 +1589,12 @@ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
                     ? (char *)MALLOC(len * 2)
                     : (char *)REALLOC(buffer, len * 2));
             if (temp == NULL) {
    -          errorCode = XML_ERROR_NO_MEMORY;
    -          return XML_STATUS_ERROR;
    -        }
    -        buffer = temp;
    -        if (!buffer) {
               errorCode = XML_ERROR_NO_MEMORY;
               eventPtr = eventEndPtr = NULL;
               processor = errorProcessor;
               return XML_STATUS_ERROR;
             }
    +        buffer = temp;
             bufferLim = buffer + len * 2;
           }
           memcpy(buffer, end, nLeftOver);
    @@ -1559,6 +1632,11 @@ XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
       case XML_FINISHED:
         errorCode = XML_ERROR_FINISHED;
         return XML_STATUS_ERROR;
    +  case XML_INITIALIZED:
    +    if (parentParser == NULL && !startParsing(parser)) {
    +      errorCode = XML_ERROR_NO_MEMORY;
    +      return XML_STATUS_ERROR;
    +    }
       default:
         ps_parsing = XML_PARSING;
       }
    @@ -1582,7 +1660,7 @@ XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
         case XML_SUSPENDED:
           result = XML_STATUS_SUSPENDED;
           break;
    -    case XML_INITIALIZED: 
    +    case XML_INITIALIZED:
         case XML_PARSING:
           if (isFinal) {
             ps_parsing = XML_FINISHED;
    @@ -1672,6 +1750,8 @@ XML_GetBuffer(XML_Parser parser, int len)
           bufferPtr = buffer = newBuf;
     #endif  /* not defined XML_CONTEXT_BYTES */
         }
    +    eventPtr = eventEndPtr = NULL;
    +    positionPtr = NULL;
       }
       return bufferEnd;
     }
    @@ -1729,7 +1809,7 @@ XML_ResumeParser(XML_Parser parser)
         case XML_SUSPENDED:
           result = XML_STATUS_SUSPENDED;
           break;
    -    case XML_INITIALIZED: 
    +    case XML_INITIALIZED:
         case XML_PARSING:
           if (ps_finalBuffer) {
             ps_parsing = XML_FINISHED;
    @@ -1956,7 +2036,10 @@ XML_GetFeatureList(void)
     #endif
     #ifdef XML_LARGE_SIZE
         {XML_FEATURE_LARGE_SIZE,       XML_L("XML_LARGE_SIZE"), 0},
    -#endif    
    +#endif
    +#ifdef XML_ATTR_INFO
    +    {XML_FEATURE_ATTR_INFO,        XML_L("XML_ATTR_INFO"), 0},
    +#endif
         {XML_FEATURE_END,              NULL, 0}
       };
     
    @@ -2019,7 +2102,7 @@ contentProcessor(XML_Parser parser,
                      const char *end,
                      const char **endPtr)
     {
    -  enum XML_Error result = doContent(parser, 0, encoding, start, end, 
    +  enum XML_Error result = doContent(parser, 0, encoding, start, end,
                                         endPtr, (XML_Bool)!ps_finalBuffer);
       if (result == XML_ERROR_NONE) {
         if (!storeRawNames(parser))
    @@ -2101,7 +2184,7 @@ externalEntityInitProcessor3(XML_Parser parser,
           if (result != XML_ERROR_NONE)
             return result;
           switch (ps_parsing) {
    -      case XML_SUSPENDED: 
    +      case XML_SUSPENDED:
             *endPtr = next;
             return XML_ERROR_NONE;
           case XML_FINISHED:
    @@ -2135,7 +2218,7 @@ externalEntityContentProcessor(XML_Parser parser,
                                    const char *end,
                                    const char **endPtr)
     {
    -  enum XML_Error result = doContent(parser, 1, encoding, start, end, 
    +  enum XML_Error result = doContent(parser, 1, encoding, start, end,
                                         endPtr, (XML_Bool)!ps_finalBuffer);
       if (result == XML_ERROR_NONE) {
         if (!storeRawNames(parser))
    @@ -2154,7 +2237,7 @@ doContent(XML_Parser parser,
               XML_Bool haveMore)
     {
       /* save one level of indirection */
    -  DTD * const dtd = _dtd;  
    +  DTD * const dtd = _dtd;
     
       const char **eventPP;
       const char **eventEndPP;
    @@ -2185,8 +2268,8 @@ doContent(XML_Parser parser,
           }
           else if (defaultHandler)
             reportDefault(parser, enc, s, end);
    -      /* We are at the end of the final buffer, should we check for 
    -         XML_SUSPENDED, XML_FINISHED? 
    +      /* We are at the end of the final buffer, should we check for
    +         XML_SUSPENDED, XML_FINISHED?
           */
           if (startTagLevel == 0)
             return XML_ERROR_NO_ELEMENTS;
    @@ -2240,7 +2323,7 @@ doContent(XML_Parser parser,
                                     next - enc->minBytesPerChar);
             if (!name)
               return XML_ERROR_NO_MEMORY;
    -        entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0);
    +        entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
             poolDiscard(&dtd->pool);
             /* First, determine if a check for an existing declaration is needed;
                if yes, check that the entity exists, and that it is internal,
    @@ -2537,8 +2620,8 @@ doContent(XML_Parser parser,
           }
           else if (defaultHandler)
             reportDefault(parser, enc, s, end);
    -      /* We are at the end of the final buffer, should we check for 
    -         XML_SUSPENDED, XML_FINISHED? 
    +      /* We are at the end of the final buffer, should we check for
    +         XML_SUSPENDED, XML_FINISHED?
           */
           if (startTagLevel == 0) {
             *eventPP = end;
    @@ -2550,7 +2633,7 @@ doContent(XML_Parser parser,
           }
           *nextPtr = end;
           return XML_ERROR_NONE;
    -    case XML_TOK_DATA_CHARS: 
    +    case XML_TOK_DATA_CHARS:
           {
             XML_CharacterDataHandler charDataHandler = characterDataHandler;
             if (charDataHandler) {
    @@ -2590,7 +2673,7 @@ doContent(XML_Parser parser,
         }
         *eventPP = s = next;
         switch (ps_parsing) {
    -    case XML_SUSPENDED: 
    +    case XML_SUSPENDED:
           *nextPtr = next;
           return XML_ERROR_NONE;
         case XML_FINISHED:
    @@ -2630,12 +2713,12 @@ storeAtts(XML_Parser parser, const ENCODING *enc,
       const XML_Char *localPart;
     
       /* lookup the element type name */
    -  elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, tagNamePtr->str,0);
    +  elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, tagNamePtr->str,0);
       if (!elementType) {
         const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str);
         if (!name)
           return XML_ERROR_NO_MEMORY;
    -    elementType = (ELEMENT_TYPE *)lookup(&dtd->elementTypes, name,
    +    elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, name,
                                              sizeof(ELEMENT_TYPE));
         if (!elementType)
           return XML_ERROR_NO_MEMORY;
    @@ -2649,23 +2732,44 @@ storeAtts(XML_Parser parser, const ENCODING *enc,
       if (n + nDefaultAtts > attsSize) {
         int oldAttsSize = attsSize;
         ATTRIBUTE *temp;
    +#ifdef XML_ATTR_INFO
    +    XML_AttrInfo *temp2;
    +#endif
         attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
         temp = (ATTRIBUTE *)REALLOC((void *)atts, attsSize * sizeof(ATTRIBUTE));
         if (temp == NULL)
           return XML_ERROR_NO_MEMORY;
         atts = temp;
    +#ifdef XML_ATTR_INFO
    +    temp2 = (XML_AttrInfo *)REALLOC((void *)attInfo, attsSize * sizeof(XML_AttrInfo));
    +    if (temp2 == NULL)
    +      return XML_ERROR_NO_MEMORY;
    +    attInfo = temp2;
    +#endif
         if (n > oldAttsSize)
           XmlGetAttributes(enc, attStr, n, atts);
       }
     
       appAtts = (const XML_Char **)atts;
       for (i = 0; i < n; i++) {
    +    ATTRIBUTE *currAtt = &atts[i];
    +#ifdef XML_ATTR_INFO
    +    XML_AttrInfo *currAttInfo = &attInfo[i];
    +#endif
         /* add the name and value to the attribute list */
    -    ATTRIBUTE_ID *attId = getAttributeId(parser, enc, atts[i].name,
    -                                         atts[i].name
    -                                         + XmlNameLength(enc, atts[i].name));
    +    ATTRIBUTE_ID *attId = getAttributeId(parser, enc, currAtt->name,
    +                                         currAtt->name
    +                                         + XmlNameLength(enc, currAtt->name));
         if (!attId)
           return XML_ERROR_NO_MEMORY;
    +#ifdef XML_ATTR_INFO
    +    currAttInfo->nameStart = parseEndByteIndex - (parseEndPtr - currAtt->name);
    +    currAttInfo->nameEnd = currAttInfo->nameStart +
    +                           XmlNameLength(enc, currAtt->name);
    +    currAttInfo->valueStart = parseEndByteIndex -
    +                            (parseEndPtr - currAtt->valuePtr);
    +    currAttInfo->valueEnd = parseEndByteIndex - (parseEndPtr - currAtt->valueEnd);
    +#endif
         /* Detect duplicate attributes by their QNames. This does not work when
            namespace processing is turned on and different prefixes for the same
            namespace are used. For this case we have a check further down.
    @@ -2804,9 +2908,9 @@ storeAtts(XML_Parser parser, const ENCODING *enc,
           if (s[-1] == 2) {  /* prefixed */
             ATTRIBUTE_ID *id;
             const BINDING *b;
    -        unsigned long uriHash = 0;
    +        unsigned long uriHash = hash_secret_salt;
             ((XML_Char *)s)[-1] = 0;  /* clear flag */
    -        id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, s, 0);
    +        id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, s, 0);
             b = id->prefix->binding;
             if (!b)
               return XML_ERROR_UNBOUND_PREFIX;
    @@ -2828,7 +2932,7 @@ storeAtts(XML_Parser parser, const ENCODING *enc,
             } while (*s++);
     
             { /* Check hash table for duplicate of expanded name (uriName).
    -             Derived from code in lookup(HASH_TABLE *table, ...).
    +             Derived from code in lookup(parser, HASH_TABLE *table, ...).
               */
               unsigned char step = 0;
               unsigned long mask = nsAttsSize - 1;
    @@ -2949,27 +3053,27 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
       static const XML_Char xmlNamespace[] = {
         ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH,
         ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD,
    -    ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L, 
    +    ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L,
         ASCII_SLASH, ASCII_1, ASCII_9, ASCII_9, ASCII_8, ASCII_SLASH,
         ASCII_n, ASCII_a, ASCII_m, ASCII_e, ASCII_s, ASCII_p, ASCII_a, ASCII_c,
         ASCII_e, '\0'
       };
    -  static const int xmlLen = 
    +  static const int xmlLen =
         (int)sizeof(xmlNamespace)/sizeof(XML_Char) - 1;
       static const XML_Char xmlnsNamespace[] = {
         ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH,
         ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD,
    -    ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_2, ASCII_0, ASCII_0, 
    -    ASCII_0, ASCII_SLASH, ASCII_x, ASCII_m, ASCII_l, ASCII_n, ASCII_s, 
    +    ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_2, ASCII_0, ASCII_0,
    +    ASCII_0, ASCII_SLASH, ASCII_x, ASCII_m, ASCII_l, ASCII_n, ASCII_s,
         ASCII_SLASH, '\0'
       };
    -  static const int xmlnsLen = 
    +  static const int xmlnsLen =
         (int)sizeof(xmlnsNamespace)/sizeof(XML_Char) - 1;
     
       XML_Bool mustBeXML = XML_FALSE;
       XML_Bool isXML = XML_TRUE;
       XML_Bool isXMLNS = XML_TRUE;
    -  
    +
       BINDING *b;
       int len;
     
    @@ -2996,7 +3100,7 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
         if (isXML && (len > xmlLen || uri[len] != xmlNamespace[len]))
           isXML = XML_FALSE;
     
    -    if (!mustBeXML && isXMLNS 
    +    if (!mustBeXML && isXMLNS
             && (len > xmlnsLen || uri[len] != xmlnsNamespace[len]))
           isXMLNS = XML_FALSE;
       }
    @@ -3207,7 +3311,7 @@ ignoreSectionProcessor(XML_Parser parser,
                            const char *end,
                            const char **endPtr)
     {
    -  enum XML_Error result = doIgnoreSection(parser, encoding, &start, end, 
    +  enum XML_Error result = doIgnoreSection(parser, encoding, &start, end,
                                               endPtr, (XML_Bool)!ps_finalBuffer);
       if (result != XML_ERROR_NONE)
         return result;
    @@ -3489,7 +3593,7 @@ entityValueInitProcessor(XML_Parser parser,
       const char *next = start;
       eventPtr = start;
     
    -  for (;;) {  
    +  for (;;) {
         tok = XmlPrologTok(encoding, start, end, &next);
         eventEndPtr = next;
         if (tok <= 0) {
    @@ -3517,7 +3621,7 @@ entityValueInitProcessor(XML_Parser parser,
           if (result != XML_ERROR_NONE)
             return result;
           switch (ps_parsing) {
    -      case XML_SUSPENDED: 
    +      case XML_SUSPENDED:
             *nextPtr = next;
             return XML_ERROR_NONE;
           case XML_FINISHED:
    @@ -3582,7 +3686,7 @@ externalParEntProcessor(XML_Parser parser,
       }
     
       processor = prologProcessor;
    -  return doProlog(parser, encoding, s, end, tok, next, 
    +  return doProlog(parser, encoding, s, end, tok, next,
                       nextPtr, (XML_Bool)!ps_finalBuffer);
     }
     
    @@ -3632,7 +3736,7 @@ prologProcessor(XML_Parser parser,
     {
       const char *next = s;
       int tok = XmlPrologTok(encoding, s, end, &next);
    -  return doProlog(parser, encoding, s, end, tok, next, 
    +  return doProlog(parser, encoding, s, end, tok, next,
                       nextPtr, (XML_Bool)!ps_finalBuffer);
     }
     
    @@ -3649,7 +3753,7 @@ doProlog(XML_Parser parser,
     #ifdef XML_DTD
       static const XML_Char externalSubsetName[] = { ASCII_HASH , '\0' };
     #endif /* XML_DTD */
    -  static const XML_Char atypeCDATA[] = 
    +  static const XML_Char atypeCDATA[] =
           { ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' };
       static const XML_Char atypeID[] = { ASCII_I, ASCII_D, '\0' };
       static const XML_Char atypeIDREF[] =
    @@ -3670,7 +3774,7 @@ doProlog(XML_Parser parser,
       static const XML_Char enumValueStart[] = { ASCII_LPAREN, '\0' };
     
       /* save one level of indirection */
    -  DTD * const dtd = _dtd; 
    +  DTD * const dtd = _dtd;
     
       const char **eventPP;
       const char **eventEndPP;
    @@ -3703,6 +3807,9 @@ doProlog(XML_Parser parser,
             return XML_ERROR_UNCLOSED_TOKEN;
           case XML_TOK_PARTIAL_CHAR:
             return XML_ERROR_PARTIAL_CHAR;
    +      case -XML_TOK_PROLOG_S:
    +        tok = -tok;
    +        break;
           case XML_TOK_NONE:
     #ifdef XML_DTD
             /* for internal PE NOT referenced between declarations */
    @@ -3725,6 +3832,7 @@ doProlog(XML_Parser parser,
             return XML_ERROR_NO_ELEMENTS;
           default:
             tok = -tok;
    +        next = end;
             break;
           }
         }
    @@ -3773,7 +3881,8 @@ doProlog(XML_Parser parser,
         case XML_ROLE_DOCTYPE_PUBLIC_ID:
     #ifdef XML_DTD
           useForeignDTD = XML_FALSE;
    -      declEntity = (ENTITY *)lookup(&dtd->paramEntities,
    +      declEntity = (ENTITY *)lookup(parser,
    +                                    &dtd->paramEntities,
                                         externalSubsetName,
                                         sizeof(ENTITY));
           if (!declEntity)
    @@ -3781,15 +3890,17 @@ doProlog(XML_Parser parser,
     #endif /* XML_DTD */
           dtd->hasParamEntityRefs = XML_TRUE;
           if (startDoctypeDeclHandler) {
    +        XML_Char *pubId;
             if (!XmlIsPublicId(enc, s, next, eventPP))
               return XML_ERROR_PUBLICID;
    -        doctypePubid = poolStoreString(&tempPool, enc,
    -                                       s + enc->minBytesPerChar,
    -                                       next - enc->minBytesPerChar);
    -        if (!doctypePubid)
    +        pubId = poolStoreString(&tempPool, enc,
    +                                s + enc->minBytesPerChar,
    +                                next - enc->minBytesPerChar);
    +        if (!pubId)
               return XML_ERROR_NO_MEMORY;
    -        normalizePublicId((XML_Char *)doctypePubid);
    +        normalizePublicId(pubId);
             poolFinish(&tempPool);
    +        doctypePubid = pubId;
             handleDefault = XML_FALSE;
             goto alreadyChecked;
           }
    @@ -3828,7 +3939,8 @@ doProlog(XML_Parser parser,
             XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
             dtd->hasParamEntityRefs = XML_TRUE;
             if (paramEntityParsing && externalEntityRefHandler) {
    -          ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities,
    +          ENTITY *entity = (ENTITY *)lookup(parser,
    +                                            &dtd->paramEntities,
                                                 externalSubsetName,
                                                 sizeof(ENTITY));
               if (!entity)
    @@ -3843,8 +3955,8 @@ doProlog(XML_Parser parser,
                                             entity->publicId))
                 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
               if (dtd->paramEntityRead) {
    -            if (!dtd->standalone && 
    -                notStandaloneHandler && 
    +            if (!dtd->standalone &&
    +                notStandaloneHandler &&
                     !notStandaloneHandler(handlerArg))
                   return XML_ERROR_NOT_STANDALONE;
               }
    @@ -3872,7 +3984,7 @@ doProlog(XML_Parser parser,
             XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
             dtd->hasParamEntityRefs = XML_TRUE;
             if (paramEntityParsing && externalEntityRefHandler) {
    -          ENTITY *entity = (ENTITY *)lookup(&dtd->paramEntities,
    +          ENTITY *entity = (ENTITY *)lookup(parser, &dtd->paramEntities,
                                                 externalSubsetName,
                                                 sizeof(ENTITY));
               if (!entity)
    @@ -4086,7 +4198,8 @@ doProlog(XML_Parser parser,
           break;
     #else /* XML_DTD */
           if (!declEntity) {
    -        declEntity = (ENTITY *)lookup(&dtd->paramEntities,
    +        declEntity = (ENTITY *)lookup(parser,
    +                                      &dtd->paramEntities,
                                           externalSubsetName,
                                           sizeof(ENTITY));
             if (!declEntity)
    @@ -4161,7 +4274,7 @@ doProlog(XML_Parser parser,
               const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
               if (!name)
                 return XML_ERROR_NO_MEMORY;
    -          declEntity = (ENTITY *)lookup(&dtd->generalEntities, name,
    +          declEntity = (ENTITY *)lookup(parser, &dtd->generalEntities, name,
                                             sizeof(ENTITY));
               if (!declEntity)
                 return XML_ERROR_NO_MEMORY;
    @@ -4193,7 +4306,7 @@ doProlog(XML_Parser parser,
             const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
             if (!name)
               return XML_ERROR_NO_MEMORY;
    -        declEntity = (ENTITY *)lookup(&dtd->paramEntities,
    +        declEntity = (ENTITY *)lookup(parser, &dtd->paramEntities,
                                                name, sizeof(ENTITY));
             if (!declEntity)
               return XML_ERROR_NO_MEMORY;
    @@ -4282,7 +4395,7 @@ doProlog(XML_Parser parser,
           switch (tok) {
           case XML_TOK_PARAM_ENTITY_REF:
             /* PE references in internal subset are
    -           not allowed within declarations. */  
    +           not allowed within declarations. */
             return XML_ERROR_PARAM_ENTITY_REF;
           case XML_TOK_XML_DECL:
             return XML_ERROR_MISPLACED_XML_PI;
    @@ -4375,7 +4488,7 @@ doProlog(XML_Parser parser,
                                     next - enc->minBytesPerChar);
             if (!name)
               return XML_ERROR_NO_MEMORY;
    -        entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0);
    +        entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
             poolDiscard(&dtd->pool);
             /* first, determine if a check for an existing declaration is needed;
                if yes, check that the entity exists, and that it is internal,
    @@ -4403,7 +4516,7 @@ doProlog(XML_Parser parser,
               return XML_ERROR_RECURSIVE_ENTITY_REF;
             if (entity->textPtr) {
               enum XML_Error result;
    -          XML_Bool betweenDecl = 
    +          XML_Bool betweenDecl =
                 (role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE);
               result = processInternalEntity(parser, entity, betweenDecl);
               if (result != XML_ERROR_NONE)
    @@ -4598,7 +4711,7 @@ doProlog(XML_Parser parser,
           reportDefault(parser, enc, s, next);
     
         switch (ps_parsing) {
    -    case XML_SUSPENDED: 
    +    case XML_SUSPENDED:
           *nextPtr = next;
           return XML_ERROR_NONE;
         case XML_FINISHED:
    @@ -4668,7 +4781,7 @@ epilogProcessor(XML_Parser parser,
         }
         eventPtr = s = next;
         switch (ps_parsing) {
    -    case XML_SUSPENDED: 
    +    case XML_SUSPENDED:
           *nextPtr = next;
           return XML_ERROR_NONE;
         case XML_FINISHED:
    @@ -4711,12 +4824,12 @@ processInternalEntity(XML_Parser parser, ENTITY *entity,
     #ifdef XML_DTD
       if (entity->is_param) {
         int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next);
    -    result = doProlog(parser, internalEncoding, textStart, textEnd, tok, 
    +    result = doProlog(parser, internalEncoding, textStart, textEnd, tok,
                           next, &next, XML_FALSE);
       }
    -  else 
    +  else
     #endif /* XML_DTD */
    -    result = doContent(parser, tagLevel, internalEncoding, textStart, 
    +    result = doContent(parser, tagLevel, internalEncoding, textStart,
                            textEnd, &next, XML_FALSE);
     
       if (result == XML_ERROR_NONE) {
    @@ -4756,13 +4869,13 @@ internalEntityProcessor(XML_Parser parser,
     #ifdef XML_DTD
       if (entity->is_param) {
         int tok = XmlPrologTok(internalEncoding, textStart, textEnd, &next);
    -    result = doProlog(parser, internalEncoding, textStart, textEnd, tok, 
    +    result = doProlog(parser, internalEncoding, textStart, textEnd, tok,
                           next, &next, XML_FALSE);
       }
       else
     #endif /* XML_DTD */
    -    result = doContent(parser, openEntity->startTagLevel, internalEncoding, 
    -                       textStart, textEnd, &next, XML_FALSE);  
    +    result = doContent(parser, openEntity->startTagLevel, internalEncoding,
    +                       textStart, textEnd, &next, XML_FALSE);
     
       if (result != XML_ERROR_NONE)
         return result;
    @@ -4783,7 +4896,7 @@ internalEntityProcessor(XML_Parser parser,
         int tok;
         processor = prologProcessor;
         tok = XmlPrologTok(encoding, s, end, &next);
    -    return doProlog(parser, encoding, s, end, tok, next, nextPtr, 
    +    return doProlog(parser, encoding, s, end, tok, next, nextPtr,
                         (XML_Bool)!ps_finalBuffer);
       }
       else
    @@ -4792,8 +4905,8 @@ internalEntityProcessor(XML_Parser parser,
         processor = contentProcessor;
         /* see externalEntityContentProcessor vs contentProcessor */
         return doContent(parser, parentParser ? 1 : 0, encoding, s, end,
    -                     nextPtr, (XML_Bool)!ps_finalBuffer); 
    -  }  
    +                     nextPtr, (XML_Bool)!ps_finalBuffer);
    +  }
     }
     
     static enum XML_Error PTRCALL
    @@ -4899,7 +5012,7 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
                                    next - enc->minBytesPerChar);
             if (!name)
               return XML_ERROR_NO_MEMORY;
    -        entity = (ENTITY *)lookup(&dtd->generalEntities, name, 0);
    +        entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
             poolDiscard(&temp2Pool);
             /* First, determine if a check for an existing declaration is needed;
                if yes, check that the entity exists, and that it is internal.
    @@ -4946,7 +5059,7 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
             if (!entity->textPtr) {
               if (enc == encoding)
                 eventPtr = ptr;
    -              return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
    +          return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
             }
             else {
               enum XML_Error result;
    @@ -5008,7 +5121,7 @@ storeEntityValue(XML_Parser parser,
               result = XML_ERROR_NO_MEMORY;
               goto endEntityValue;
             }
    -        entity = (ENTITY *)lookup(&dtd->paramEntities, name, 0);
    +        entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
             poolDiscard(&tempPool);
             if (!entity) {
               /* not a well-formedness error - see XML 1.0: WFC Entity Declared */
    @@ -5298,7 +5411,7 @@ setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)
           }
           if (!poolAppendChar(&dtd->pool, XML_T('\0')))
             return 0;
    -      prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool),
    +      prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),
                                     sizeof(PREFIX));
           if (!prefix)
             return 0;
    @@ -5327,7 +5440,7 @@ getAttributeId(XML_Parser parser, const ENCODING *enc,
         return NULL;
       /* skip quotation mark - its storage will be re-used (like in name[-1]) */
       ++name;
    -  id = (ATTRIBUTE_ID *)lookup(&dtd->attributeIds, name, sizeof(ATTRIBUTE_ID));
    +  id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, name, sizeof(ATTRIBUTE_ID));
       if (!id)
         return NULL;
       if (id->name != name)
    @@ -5345,7 +5458,7 @@ getAttributeId(XML_Parser parser, const ENCODING *enc,
           if (name[5] == XML_T('\0'))
             id->prefix = &dtd->defaultPrefix;
           else
    -        id->prefix = (PREFIX *)lookup(&dtd->prefixes, name + 6, sizeof(PREFIX));
    +        id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, name + 6, sizeof(PREFIX));
           id->xmlns = XML_TRUE;
         }
         else {
    @@ -5360,7 +5473,7 @@ getAttributeId(XML_Parser parser, const ENCODING *enc,
               }
               if (!poolAppendChar(&dtd->pool, XML_T('\0')))
                 return NULL;
    -          id->prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&dtd->pool),
    +          id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),
                                             sizeof(PREFIX));
               if (id->prefix->name == poolStart(&dtd->pool))
                 poolFinish(&dtd->pool);
    @@ -5456,7 +5569,7 @@ setContext(XML_Parser parser, const XML_Char *context)
           ENTITY *e;
           if (!poolAppendChar(&tempPool, XML_T('\0')))
             return XML_FALSE;
    -      e = (ENTITY *)lookup(&dtd->generalEntities, poolStart(&tempPool), 0);
    +      e = (ENTITY *)lookup(parser, &dtd->generalEntities, poolStart(&tempPool), 0);
           if (e)
             e->open = XML_TRUE;
           if (*s != XML_T('\0'))
    @@ -5471,7 +5584,7 @@ setContext(XML_Parser parser, const XML_Char *context)
           else {
             if (!poolAppendChar(&tempPool, XML_T('\0')))
               return XML_FALSE;
    -        prefix = (PREFIX *)lookup(&dtd->prefixes, poolStart(&tempPool),
    +        prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&tempPool),
                                       sizeof(PREFIX));
             if (!prefix)
               return XML_FALSE;
    @@ -5635,7 +5748,7 @@ dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms)
        The new DTD has already been initialized.
     */
     static int
    -dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
    +dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
     {
       HASH_TABLE_ITER iter;
     
    @@ -5650,7 +5763,7 @@ dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
         name = poolCopyString(&(newDtd->pool), oldP->name);
         if (!name)
           return 0;
    -    if (!lookup(&(newDtd->prefixes), name, sizeof(PREFIX)))
    +    if (!lookup(oldParser, &(newDtd->prefixes), name, sizeof(PREFIX)))
           return 0;
       }
     
    @@ -5672,7 +5785,7 @@ dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
         if (!name)
           return 0;
         ++name;
    -    newA = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), name,
    +    newA = (ATTRIBUTE_ID *)lookup(oldParser, &(newDtd->attributeIds), name,
                                       sizeof(ATTRIBUTE_ID));
         if (!newA)
           return 0;
    @@ -5682,7 +5795,7 @@ dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
           if (oldA->prefix == &oldDtd->defaultPrefix)
             newA->prefix = &newDtd->defaultPrefix;
           else
    -        newA->prefix = (PREFIX *)lookup(&(newDtd->prefixes),
    +        newA->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
                                             oldA->prefix->name, 0);
         }
       }
    @@ -5701,7 +5814,7 @@ dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
         name = poolCopyString(&(newDtd->pool), oldE->name);
         if (!name)
           return 0;
    -    newE = (ELEMENT_TYPE *)lookup(&(newDtd->elementTypes), name,
    +    newE = (ELEMENT_TYPE *)lookup(oldParser, &(newDtd->elementTypes), name,
                                       sizeof(ELEMENT_TYPE));
         if (!newE)
           return 0;
    @@ -5715,14 +5828,14 @@ dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
         }
         if (oldE->idAtt)
           newE->idAtt = (ATTRIBUTE_ID *)
    -          lookup(&(newDtd->attributeIds), oldE->idAtt->name, 0);
    +          lookup(oldParser, &(newDtd->attributeIds), oldE->idAtt->name, 0);
         newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
         if (oldE->prefix)
    -      newE->prefix = (PREFIX *)lookup(&(newDtd->prefixes),
    +      newE->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
                                           oldE->prefix->name, 0);
         for (i = 0; i < newE->nDefaultAtts; i++) {
           newE->defaultAtts[i].id = (ATTRIBUTE_ID *)
    -          lookup(&(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
    +          lookup(oldParser, &(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
           newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
           if (oldE->defaultAtts[i].value) {
             newE->defaultAtts[i].value
    @@ -5736,13 +5849,15 @@ dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
       }
     
       /* Copy the entity tables. */
    -  if (!copyEntityTable(&(newDtd->generalEntities),
    +  if (!copyEntityTable(oldParser,
    +                       &(newDtd->generalEntities),
                            &(newDtd->pool),
                            &(oldDtd->generalEntities)))
           return 0;
     
     #ifdef XML_DTD
    -  if (!copyEntityTable(&(newDtd->paramEntities),
    +  if (!copyEntityTable(oldParser,
    +                       &(newDtd->paramEntities),
                            &(newDtd->pool),
                            &(oldDtd->paramEntities)))
           return 0;
    @@ -5765,7 +5880,8 @@ dtdCopy(DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
     }  /* End dtdCopy */
     
     static int
    -copyEntityTable(HASH_TABLE *newTable,
    +copyEntityTable(XML_Parser oldParser,
    +                HASH_TABLE *newTable,
                     STRING_POOL *newPool,
                     const HASH_TABLE *oldTable)
     {
    @@ -5784,7 +5900,7 @@ copyEntityTable(HASH_TABLE *newTable,
         name = poolCopyString(newPool, oldE->name);
         if (!name)
           return 0;
    -    newE = (ENTITY *)lookup(newTable, name, sizeof(ENTITY));
    +    newE = (ENTITY *)lookup(oldParser, newTable, name, sizeof(ENTITY));
         if (!newE)
           return 0;
         if (oldE->systemId) {
    @@ -5842,16 +5958,16 @@ keyeq(KEY s1, KEY s2)
     }
     
     static unsigned long FASTCALL
    -hash(KEY s)
    +hash(XML_Parser parser, KEY s)
     {
    -  unsigned long h = 0;
    +  unsigned long h = hash_secret_salt;
       while (*s)
         h = CHAR_HASH(h, *s++);
       return h;
     }
     
     static NAMED *
    -lookup(HASH_TABLE *table, KEY name, size_t createSize)
    +lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize)
     {
       size_t i;
       if (table->size == 0) {
    @@ -5868,10 +5984,10 @@ lookup(HASH_TABLE *table, KEY name, size_t createSize)
           return NULL;
         }
         memset(table->v, 0, tsize);
    -    i = hash(name) & ((unsigned long)table->size - 1);
    +    i = hash(parser, name) & ((unsigned long)table->size - 1);
       }
       else {
    -    unsigned long h = hash(name);
    +    unsigned long h = hash(parser, name);
         unsigned long mask = (unsigned long)table->size - 1;
         unsigned char step = 0;
         i = h & mask;
    @@ -5897,7 +6013,7 @@ lookup(HASH_TABLE *table, KEY name, size_t createSize)
           memset(newV, 0, tsize);
           for (i = 0; i < table->size; i++)
             if (table->v[i]) {
    -          unsigned long newHash = hash(table->v[i]->name);
    +          unsigned long newHash = hash(parser, table->v[i]->name);
               size_t j = newHash & newMask;
               step = 0;
               while (newV[j]) {
    @@ -6118,12 +6234,13 @@ poolGrow(STRING_POOL *pool)
       }
       if (pool->blocks && pool->start == pool->blocks->s) {
         int blockSize = (int)(pool->end - pool->start)*2;
    -    pool->blocks = (BLOCK *)
    +    BLOCK *temp = (BLOCK *)
           pool->mem->realloc_fcn(pool->blocks,
                                  (offsetof(BLOCK, s)
                                   + blockSize * sizeof(XML_Char)));
    -    if (pool->blocks == NULL)
    +    if (temp == NULL)
           return XML_FALSE;
    +    pool->blocks = temp;
         pool->blocks->size = blockSize;
         pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
         pool->start = pool->blocks->s;
    @@ -6272,7 +6389,7 @@ getElementType(XML_Parser parser,
     
       if (!name)
         return NULL;
    -  ret = (ELEMENT_TYPE *) lookup(&dtd->elementTypes, name, sizeof(ELEMENT_TYPE));
    +  ret = (ELEMENT_TYPE *) lookup(parser, &dtd->elementTypes, name, sizeof(ELEMENT_TYPE));
       if (!ret)
         return NULL;
       if (ret->name != name)
    diff --git a/lib/xmlrole.c b/lib/xmlrole.c
    index 9c5e25b179f..44772e21dd3 100644
    --- a/lib/xmlrole.c
    +++ b/lib/xmlrole.c
    @@ -8,7 +8,7 @@
     #include "winconfig.h"
     #elif defined(MACOS_CLASSIC)
     #include "macconfig.h"
    -#elif defined(__amigaos4__)
    +#elif defined(__amigaos__)
     #include "amigaconfig.h"
     #elif defined(__WATCOMC__)
     #include "watcomconfig.h"
    diff --git a/lib/xmltok.c b/lib/xmltok.c
    index 068afdec6e1..bf09dfc72b9 100644
    --- a/lib/xmltok.c
    +++ b/lib/xmltok.c
    @@ -8,7 +8,7 @@
     #include "winconfig.h"
     #elif defined(MACOS_CLASSIC)
     #include "macconfig.h"
    -#elif defined(__amigaos4__)
    +#elif defined(__amigaos__)
     #include "amigaconfig.h"
     #elif defined(__WATCOMC__)
     #include "watcomconfig.h"
    @@ -1345,7 +1345,7 @@ unknown_toUtf16(const ENCODING *enc,
     ENCODING *
     XmlInitUnknownEncoding(void *mem,
                            int *table,
    -                       CONVERTER convert, 
    +                       CONVERTER convert,
                            void *userData)
     {
       int i;
    @@ -1639,7 +1639,7 @@ initScan(const ENCODING * const *encodingTable,
     ENCODING *
     XmlInitUnknownEncodingNS(void *mem,
                              int *table,
    -                         CONVERTER convert, 
    +                         CONVERTER convert,
                              void *userData)
     {
       ENCODING *enc = XmlInitUnknownEncoding(mem, table, convert, userData);
    diff --git a/lib/xmltok_impl.c b/lib/xmltok_impl.c
    index 16dfb85f031..9c2895b8773 100644
    --- a/lib/xmltok_impl.c
    +++ b/lib/xmltok_impl.c
    @@ -885,7 +885,7 @@ PREFIX(scanPercent)(const ENCODING *enc, const char *ptr, const char *end,
                         const char **nextTokPtr)
     {
       if (ptr == end)
    -    return -XML_TOK_PERCENT;
    +    return XML_TOK_PARTIAL;
       switch (BYTE_TYPE(enc, ptr)) {
       CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
       case BT_S: case BT_LF: case BT_CR: case BT_PERCNT:
    diff --git a/tests/README.txt b/tests/README.txt
    index 33a47c34abc..30e1d4dabe8 100644
    --- a/tests/README.txt
    +++ b/tests/README.txt
    @@ -8,7 +8,6 @@ unit testing framework for C. More information on Check can be found at:
     
             http://check.sourceforge.net/
     
    -Expat must be built and installed before "make check" can be executed.
    +Expat must be built and, depending on platform, must be installed, before "make check" can be executed.
     
    -Since both Check and this test suite are young, it can all change in a
    -later version.
    +This test suite can all change in a later version.
    diff --git a/tests/benchmark/benchmark.dsp b/tests/benchmark/benchmark.dsp
    deleted file mode 100755
    index 6f310d0a931..00000000000
    --- a/tests/benchmark/benchmark.dsp
    +++ /dev/null
    @@ -1,88 +0,0 @@
    -# Microsoft Developer Studio Project File - Name="benchmark" - Package Owner=<4>
    -# Microsoft Developer Studio Generated Build File, Format Version 6.00
    -# ** DO NOT EDIT **
    -
    -# TARGTYPE "Win32 (x86) Console Application" 0x0103
    -
    -CFG=benchmark - Win32 Debug
    -!MESSAGE This is not a valid makefile. To build this project using NMAKE,
    -!MESSAGE use the Export Makefile command and run
    -!MESSAGE 
    -!MESSAGE NMAKE /f "benchmark.mak".
    -!MESSAGE 
    -!MESSAGE You can specify a configuration when running NMAKE
    -!MESSAGE by defining the macro CFG on the command line. For example:
    -!MESSAGE 
    -!MESSAGE NMAKE /f "benchmark.mak" CFG="benchmark - Win32 Debug"
    -!MESSAGE 
    -!MESSAGE Possible choices for configuration are:
    -!MESSAGE 
    -!MESSAGE "benchmark - Win32 Release" (based on "Win32 (x86) Console Application")
    -!MESSAGE "benchmark - Win32 Debug" (based on "Win32 (x86) Console Application")
    -!MESSAGE 
    -
    -# Begin Project
    -# PROP AllowPerConfigDependencies 0
    -# PROP Scc_ProjName ""
    -# PROP Scc_LocalPath ""
    -CPP=cl.exe
    -RSC=rc.exe
    -
    -!IF  "$(CFG)" == "benchmark - Win32 Release"
    -
    -# PROP BASE Use_MFC 0
    -# PROP BASE Use_Debug_Libraries 0
    -# PROP BASE Output_Dir "Release"
    -# PROP BASE Intermediate_Dir "Release"
    -# PROP BASE Target_Dir ""
    -# PROP Use_MFC 0
    -# PROP Use_Debug_Libraries 0
    -# PROP Output_Dir "Release"
    -# PROP Intermediate_Dir "Release"
    -# PROP Target_Dir ""
    -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
    -# ADD CPP /nologo /W3 /GX /O2 /I "..\..\lib" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
    -# ADD BASE RSC /l 0x1009 /d "NDEBUG"
    -# ADD RSC /l 0x1009 /d "NDEBUG"
    -BSC32=bscmake.exe
    -# ADD BASE BSC32 /nologo
    -# ADD BSC32 /nologo
    -LINK32=link.exe
    -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
    -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
    -
    -!ELSEIF  "$(CFG)" == "benchmark - Win32 Debug"
    -
    -# PROP BASE Use_MFC 0
    -# PROP BASE Use_Debug_Libraries 1
    -# PROP BASE Output_Dir "Debug"
    -# PROP BASE Intermediate_Dir "Debug"
    -# PROP BASE Target_Dir ""
    -# PROP Use_MFC 0
    -# PROP Use_Debug_Libraries 1
    -# PROP Output_Dir "Debug"
    -# PROP Intermediate_Dir "Debug"
    -# PROP Target_Dir ""
    -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
    -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\lib" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
    -# ADD BASE RSC /l 0x1009 /d "_DEBUG"
    -# ADD RSC /l 0x1009 /d "_DEBUG"
    -BSC32=bscmake.exe
    -# ADD BASE BSC32 /nologo
    -# ADD BSC32 /nologo
    -LINK32=link.exe
    -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
    -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
    -
    -!ENDIF 
    -
    -# Begin Target
    -
    -# Name "benchmark - Win32 Release"
    -# Name "benchmark - Win32 Debug"
    -# Begin Source File
    -
    -SOURCE=.\benchmark.c
    -# End Source File
    -# End Target
    -# End Project
    diff --git a/tests/benchmark/benchmark.dsw b/tests/benchmark/benchmark.dsw
    deleted file mode 100755
    index 3346a9ad986..00000000000
    --- a/tests/benchmark/benchmark.dsw
    +++ /dev/null
    @@ -1,44 +0,0 @@
    -Microsoft Developer Studio Workspace File, Format Version 6.00
    -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
    -
    -###############################################################################
    -
    -Project: "benchmark"=.\benchmark.dsp - Package Owner=<4>
    -
    -Package=<5>
    -{{{
    -}}}
    -
    -Package=<4>
    -{{{
    -    Begin Project Dependency
    -    Project_Dep_Name expat
    -    End Project Dependency
    -}}}
    -
    -###############################################################################
    -
    -Project: "expat"=..\..\lib\expat.dsp - Package Owner=<4>
    -
    -Package=<5>
    -{{{
    -}}}
    -
    -Package=<4>
    -{{{
    -}}}
    -
    -###############################################################################
    -
    -Global:
    -
    -Package=<5>
    -{{{
    -}}}
    -
    -Package=<3>
    -{{{
    -}}}
    -
    -###############################################################################
    -
    diff --git a/tests/minicheck.h b/tests/minicheck.h
    index f846bead1a8..c917c026971 100755
    --- a/tests/minicheck.h
    +++ b/tests/minicheck.h
    @@ -18,10 +18,11 @@ extern "C" {
     #define CK_NORMAL  1
     #define CK_VERBOSE 2
     
    -/* Workaround for Tru64 Unix systems where the C compiler has a working
    -   __func__, but the C++ compiler only has a working __FUNCTION__.  This
    -   could be fixed in configure.in, but it's not worth it right now. */
    -#if defined(__osf__) && defined(__cplusplus)
    +/* Workaround for Microsoft's compiler and Tru64 Unix systems where the
    +   C compiler has a working __func__, but the C++ compiler only has a 
    +   working __FUNCTION__.  This could be fixed in configure.in, but it's
    +   not worth it right now. */
    +#if defined (_MSC_VER) || (defined(__osf__) && defined(__cplusplus))
     #define __func__ __FUNCTION__
     #endif
     
    diff --git a/tests/runtests.c b/tests/runtests.c
    index 3521c086bbb..614d6b24873 100644
    --- a/tests/runtests.c
    +++ b/tests/runtests.c
    @@ -12,6 +12,7 @@
     #include 
     #include 
     #include 
    +#include 
     
     #include "expat.h"
     #include "chardata.h"
    @@ -1254,7 +1255,7 @@ external_entity_handler(XML_Parser parser,
                             const XML_Char *systemId,
                             const XML_Char *publicId) 
     {
    -    long callno = 1 + (long)XML_GetUserData(parser);
    +    intptr_t callno = 1 + (intptr_t)XML_GetUserData(parser);
         char *text;
         XML_Parser p2;
     
    diff --git a/tests/xmltest.sh b/tests/xmltest.sh
    index 725441edb69..793a5cc2819 100755
    --- a/tests/xmltest.sh
    +++ b/tests/xmltest.sh
    @@ -6,7 +6,7 @@
     # w3c.org xml test suite, available from
     # http://www.w3.org/XML/Test/xmlts20020606.zip.
     
    -# To run this script, first set XMLWF so that xmlwf can be
    +# To run this script, first set XMLWF below so that xmlwf can be
     # found, then set the output directory with OUTPUT.
     
     # The script lists all test cases where Expat shows a discrepancy
    @@ -39,7 +39,7 @@ RunXmlwfNotWF() {
       $XMLWF -p "$file" > outfile || return $?
       read outdata < outfile
       if test "$outdata" = "" ; then
    -      echo "Expected well-formed: $reldir$file"
    +      echo "Expected not well-formed: $reldir$file"
           return 1
       else
           return 0
    @@ -55,7 +55,7 @@ RunXmlwfWF() {
       read outdata < outfile 
       if test "$outdata" = "" ; then 
           if [ -f "out/$file" ] ; then 
    -          diff "$OUTPUT$reldir$file" "out/$file" > outfile 
    +          diff -u "$OUTPUT$reldir$file" "out/$file" > outfile 
               if [ -s outfile ] ; then 
                   cp outfile "$OUTPUT$reldir$file.diff"
                   echo "Output differs: $reldir$file"
    @@ -117,6 +117,7 @@ rm outfile
     
     cd "$TS/xmlconf"
     for xmldir in ibm/not-wf/P* \
    +              ibm/not-wf/p28a \
                   ibm/not-wf/misc \
                   xmltest/not-wf/ext-sa \
                   xmltest/not-wf/not-sa \
    diff --git a/xmlwf/readfilemap.c b/xmlwf/readfilemap.c
    index 088dda5c23d..bd32b934147 100755
    --- a/xmlwf/readfilemap.c
    +++ b/xmlwf/readfilemap.c
    @@ -58,10 +58,12 @@ filemap(const char *name,
       }
       if (fstat(fd, &sb) < 0) {
         perror(name);
    +    close(fd);
         return 0;
       }
       if (!S_ISREG(sb.st_mode)) {
         fprintf(stderr, "%s: not a regular file\n", name);
    +    close(fd);
         return 0;
       }
       nbytes = sb.st_size;
    diff --git a/xmlwf/xmlwf.c b/xmlwf/xmlwf.c
    index 41a433d3ced..4fc77da9441 100755
    --- a/xmlwf/xmlwf.c
    +++ b/xmlwf/xmlwf.c
    @@ -849,8 +849,10 @@ tmain(int argc, XML_Char **argv)
           if (outputType == 'm')
             metaEndDocument(parser);
           fclose(fp);
    -      if (!result)
    +      if (!result) {
             tremove(outName);
    +        exit(2);
    +      }
           free(outName);
         }
         XML_ParserFree(parser);
    
    From 590f9303e563b588032bfeb69d99f8c91cd75d72 Mon Sep 17 00:00:00 2001
    From: Attilio Rao 
    Date: Tue, 26 Feb 2013 01:00:11 +0000
    Subject: [PATCH 0410/1476] Merge from vmobj-rwlock branch: Remove unused
     inclusion of vm/vm_pager.h and vm/vnode_pager.h.
    
    Sponsored by:	EMC / Isilon storage division
    Tested by:	pho
    Reviewed by:	alc
    ---
     sys/arm/at91/at91_machdep.c        | 1 -
     sys/arm/sa11x0/assabet_machdep.c   | 1 -
     sys/fs/fuse/fuse_io.c              | 2 --
     sys/kern/sys_process.c             | 1 -
     sys/mips/adm5120/adm5120_machdep.c | 1 -
     sys/mips/alchemy/alchemy_machdep.c | 1 -
     sys/mips/beri/beri_machdep.c       | 1 -
     sys/mips/cavium/octeon_machdep.c   | 1 -
     sys/mips/gxemul/gxemul_machdep.c   | 1 -
     sys/mips/idt/idt_machdep.c         | 1 -
     sys/mips/malta/malta_machdep.c     | 1 -
     sys/mips/rt305x/rt305x_machdep.c   | 1 -
     sys/mips/sentry5/s5_machdep.c      | 1 -
     sys/mips/sibyte/sb_machdep.c       | 1 -
     sys/powerpc/aim/mmu_oea.c          | 1 -
     sys/powerpc/aim/mmu_oea64.c        | 1 -
     sys/powerpc/aim/moea64_native.c    | 1 -
     sys/powerpc/ps3/mmu_ps3.c          | 1 -
     sys/sparc64/sparc64/tsb.c          | 1 -
     19 files changed, 20 deletions(-)
    
    diff --git a/sys/arm/at91/at91_machdep.c b/sys/arm/at91/at91_machdep.c
    index 3df922ef336..27e88447d44 100644
    --- a/sys/arm/at91/at91_machdep.c
    +++ b/sys/arm/at91/at91_machdep.c
    @@ -76,7 +76,6 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     #include 
     #include 
     #include 
    diff --git a/sys/arm/sa11x0/assabet_machdep.c b/sys/arm/sa11x0/assabet_machdep.c
    index 9266939bbdf..986395340d3 100644
    --- a/sys/arm/sa11x0/assabet_machdep.c
    +++ b/sys/arm/sa11x0/assabet_machdep.c
    @@ -79,7 +79,6 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     #include 
     #include 
     #include 
    diff --git a/sys/fs/fuse/fuse_io.c b/sys/fs/fuse/fuse_io.c
    index e5765687145..06ad6346adb 100644
    --- a/sys/fs/fuse/fuse_io.c
    +++ b/sys/fs/fuse/fuse_io.c
    @@ -87,8 +87,6 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
    -#include 
     #include 
     
     #include "fuse.h"
    diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
    index 63de37a27de..e70e60e1997 100644
    --- a/sys/kern/sys_process.c
    +++ b/sys/kern/sys_process.c
    @@ -59,7 +59,6 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     #include 
     
     #ifdef COMPAT_FREEBSD32
    diff --git a/sys/mips/adm5120/adm5120_machdep.c b/sys/mips/adm5120/adm5120_machdep.c
    index 29079c804cb..2713618607e 100644
    --- a/sys/mips/adm5120/adm5120_machdep.c
    +++ b/sys/mips/adm5120/adm5120_machdep.c
    @@ -53,7 +53,6 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     
     #include 
     #include 
    diff --git a/sys/mips/alchemy/alchemy_machdep.c b/sys/mips/alchemy/alchemy_machdep.c
    index 0593f83cddd..d7f242ae0ad 100644
    --- a/sys/mips/alchemy/alchemy_machdep.c
    +++ b/sys/mips/alchemy/alchemy_machdep.c
    @@ -53,7 +53,6 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     
     #include 
     #include 
    diff --git a/sys/mips/beri/beri_machdep.c b/sys/mips/beri/beri_machdep.c
    index 98fcb85aa3a..f36b0ea1bb1 100644
    --- a/sys/mips/beri/beri_machdep.c
    +++ b/sys/mips/beri/beri_machdep.c
    @@ -64,7 +64,6 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     
     #include 
     #include 
    diff --git a/sys/mips/cavium/octeon_machdep.c b/sys/mips/cavium/octeon_machdep.c
    index fcf3ab66da1..53a84427a0a 100644
    --- a/sys/mips/cavium/octeon_machdep.c
    +++ b/sys/mips/cavium/octeon_machdep.c
    @@ -55,7 +55,6 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     
     #include 
     #include 
    diff --git a/sys/mips/gxemul/gxemul_machdep.c b/sys/mips/gxemul/gxemul_machdep.c
    index 8996919d3e6..a068efc7b4e 100644
    --- a/sys/mips/gxemul/gxemul_machdep.c
    +++ b/sys/mips/gxemul/gxemul_machdep.c
    @@ -52,7 +52,6 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     
     #include 
     #include 
    diff --git a/sys/mips/idt/idt_machdep.c b/sys/mips/idt/idt_machdep.c
    index ac18748f567..b48931987d2 100644
    --- a/sys/mips/idt/idt_machdep.c
    +++ b/sys/mips/idt/idt_machdep.c
    @@ -55,7 +55,6 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     
     #include 
     #include 
    diff --git a/sys/mips/malta/malta_machdep.c b/sys/mips/malta/malta_machdep.c
    index 8efb98778b6..27cfa9f664c 100644
    --- a/sys/mips/malta/malta_machdep.c
    +++ b/sys/mips/malta/malta_machdep.c
    @@ -54,7 +54,6 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     
     #include 
     #include 
    diff --git a/sys/mips/rt305x/rt305x_machdep.c b/sys/mips/rt305x/rt305x_machdep.c
    index 33c131cb066..07342bde9ed 100644
    --- a/sys/mips/rt305x/rt305x_machdep.c
    +++ b/sys/mips/rt305x/rt305x_machdep.c
    @@ -54,7 +54,6 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     
     #include 
     #include 
    diff --git a/sys/mips/sentry5/s5_machdep.c b/sys/mips/sentry5/s5_machdep.c
    index cde081bc92d..a10b48d2bf9 100644
    --- a/sys/mips/sentry5/s5_machdep.c
    +++ b/sys/mips/sentry5/s5_machdep.c
    @@ -53,7 +53,6 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     
     #include 
     #include 
    diff --git a/sys/mips/sibyte/sb_machdep.c b/sys/mips/sibyte/sb_machdep.c
    index 452eea6fa63..5e7c2fded87 100644
    --- a/sys/mips/sibyte/sb_machdep.c
    +++ b/sys/mips/sibyte/sb_machdep.c
    @@ -55,7 +55,6 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     
     #include 
     #include 
    diff --git a/sys/powerpc/aim/mmu_oea.c b/sys/powerpc/aim/mmu_oea.c
    index b17376039eb..24350c44f95 100644
    --- a/sys/powerpc/aim/mmu_oea.c
    +++ b/sys/powerpc/aim/mmu_oea.c
    @@ -136,7 +136,6 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     #include 
     
     #include 
    diff --git a/sys/powerpc/aim/mmu_oea64.c b/sys/powerpc/aim/mmu_oea64.c
    index 00dab9bd883..0d77b576cff 100644
    --- a/sys/powerpc/aim/mmu_oea64.c
    +++ b/sys/powerpc/aim/mmu_oea64.c
    @@ -140,7 +140,6 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     #include 
     
     #include 
    diff --git a/sys/powerpc/aim/moea64_native.c b/sys/powerpc/aim/moea64_native.c
    index 3da2f5ad3f9..de0d4ba250f 100644
    --- a/sys/powerpc/aim/moea64_native.c
    +++ b/sys/powerpc/aim/moea64_native.c
    @@ -117,7 +117,6 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     
     #include 
     #include 
    diff --git a/sys/powerpc/ps3/mmu_ps3.c b/sys/powerpc/ps3/mmu_ps3.c
    index 5a7fe93af3b..dfca9a7d772 100644
    --- a/sys/powerpc/ps3/mmu_ps3.c
    +++ b/sys/powerpc/ps3/mmu_ps3.c
    @@ -45,7 +45,6 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     #include 
     
     #include 
    diff --git a/sys/sparc64/sparc64/tsb.c b/sys/sparc64/sparc64/tsb.c
    index 403043c6403..c38d50e2b6b 100644
    --- a/sys/sparc64/sparc64/tsb.c
    +++ b/sys/sparc64/sparc64/tsb.c
    @@ -53,7 +53,6 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     
     #include 
     #include 
    
    From 285a4c7c59d4e4c1509bcd0128dd53298b4b40b5 Mon Sep 17 00:00:00 2001
    From: Xin LI 
    Date: Tue, 26 Feb 2013 02:13:02 +0000
    Subject: [PATCH 0411/1476] Expose timespec and timeval macros when
     __BSD_VISIBLE is defined.  This allows userland application to use the
     following macros:
    
    	timespecclear, timespecisset, timespeccmp, timespecadd,
    	timespecsub;
    
    	timevalclear, timevalisset, timevalcmp.
    
    MFC after:	1 month
    ---
     sys/sys/time.h           |  5 +----
     usr.bin/truss/main.c     |  8 ++++----
     usr.bin/truss/syscalls.c | 10 +++++-----
     usr.bin/truss/truss.h    |  4 ++--
     4 files changed, 12 insertions(+), 15 deletions(-)
    
    diff --git a/sys/sys/time.h b/sys/sys/time.h
    index 80878c0e9f8..14b80e37aec 100644
    --- a/sys/sys/time.h
    +++ b/sys/sys/time.h
    @@ -156,9 +156,6 @@ timeval2bintime(const struct timeval *tv, struct bintime *bt)
     	/* 18446744073709 = int(2^64 / 1000000) */
     	bt->frac = tv->tv_usec * (uint64_t)18446744073709LL;
     }
    -#endif /* __BSD_VISIBLE */
    -
    -#ifdef _KERNEL
     
     /* Operations on timespecs */
     #define	timespecclear(tvp)	((tvp)->tv_sec = (tvp)->tv_nsec = 0)
    @@ -197,7 +194,7 @@ timeval2bintime(const struct timeval *tv, struct bintime *bt)
     
     /* timevaladd and timevalsub are not inlined */
     
    -#endif /* _KERNEL */
    +#endif /* __BSD_VISIBLE */
     
     #ifndef _KERNEL			/* NetBSD/OpenBSD compatible interfaces */
     
    diff --git a/usr.bin/truss/main.c b/usr.bin/truss/main.c
    index 4e9f74b8a3c..7b8242bb32f 100644
    --- a/usr.bin/truss/main.c
    +++ b/usr.bin/truss/main.c
    @@ -323,14 +323,14 @@ START_TRACE:
     				fprintf(trussinfo->outfile, "%5d: ",
     				    trussinfo->pid);
     			if (trussinfo->flags & ABSOLUTETIMESTAMPS) {
    -				timespecsubt(&trussinfo->curthread->after,
    +				timespecsubt_to(&trussinfo->curthread->after,
     				    &trussinfo->start_time, &timediff);
     				fprintf(trussinfo->outfile, "%ld.%09ld ",
     				    (long)timediff.tv_sec,
     				    timediff.tv_nsec);
     			}
     			if (trussinfo->flags & RELATIVETIMESTAMPS) {
    -				timespecsubt(&trussinfo->curthread->after,
    +				timespecsubt_to(&trussinfo->curthread->after,
     				    &trussinfo->curthread->before, &timediff);
     				fprintf(trussinfo->outfile, "%ld.%09ld ",
     				    (long)timediff.tv_sec,
    @@ -349,14 +349,14 @@ START_TRACE:
     				fprintf(trussinfo->outfile, "%5d: ",
     				    trussinfo->pid);
     			if (trussinfo->flags & ABSOLUTETIMESTAMPS) {
    -				timespecsubt(&trussinfo->curthread->after,
    +				timespecsubt_to(&trussinfo->curthread->after,
     				    &trussinfo->start_time, &timediff);
     				fprintf(trussinfo->outfile, "%ld.%09ld ",
     				    (long)timediff.tv_sec,
     				    timediff.tv_nsec);
     			}
     			if (trussinfo->flags & RELATIVETIMESTAMPS) {
    -				timespecsubt(&trussinfo->curthread->after,
    +				timespecsubt_to(&trussinfo->curthread->after,
     				    &trussinfo->curthread->before, &timediff);
     				fprintf(trussinfo->outfile, "%ld.%09ld ",
     				    (long)timediff.tv_sec, timediff.tv_nsec);
    diff --git a/usr.bin/truss/syscalls.c b/usr.bin/truss/syscalls.c
    index 0afd083d845..c926af2515f 100644
    --- a/usr.bin/truss/syscalls.c
    +++ b/usr.bin/truss/syscalls.c
    @@ -1126,14 +1126,14 @@ print_syscall(struct trussinfo *trussinfo, const char *name, int nargs,
     	}
     
     	if (trussinfo->flags & ABSOLUTETIMESTAMPS) {
    -		timespecsubt(&trussinfo->curthread->after,
    +		timespecsubt_to(&trussinfo->curthread->after,
     		    &trussinfo->start_time, &timediff);
     		len += fprintf(trussinfo->outfile, "%ld.%09ld ",
     		    (long)timediff.tv_sec, timediff.tv_nsec);
     	}
     
     	if (trussinfo->flags & RELATIVETIMESTAMPS) {
    -		timespecsubt(&trussinfo->curthread->after,
    +		timespecsubt_to(&trussinfo->curthread->after,
     		    &trussinfo->curthread->before, &timediff);
     		len += fprintf(trussinfo->outfile, "%ld.%09ld ",
     		    (long)timediff.tv_sec, timediff.tv_nsec);
    @@ -1165,9 +1165,9 @@ print_syscall_ret(struct trussinfo *trussinfo, const char *name, int nargs,
     		if (!sc)
     			return;
     		clock_gettime(CLOCK_REALTIME, &trussinfo->curthread->after);
    -		timespecsubt(&trussinfo->curthread->after,
    +		timespecsubt_to(&trussinfo->curthread->after,
     		    &trussinfo->curthread->before, &timediff);
    -		timespecadd(&sc->time, &timediff, &sc->time);
    +		timespecadd_to(&sc->time, &timediff, &sc->time);
     		sc->ncalls++;
     		if (errorp)
     			sc->nerror++;
    @@ -1205,7 +1205,7 @@ print_summary(struct trussinfo *trussinfo)
     			fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
     			    sc->name, (intmax_t)sc->time.tv_sec,
     			    sc->time.tv_nsec, sc->ncalls, sc->nerror);
    -			timespecadd(&total, &sc->time, &total);
    +			timespecadd_to(&total, &sc->time, &total);
     			ncall += sc->ncalls;
     			nerror += sc->nerror;
     		}
    diff --git a/usr.bin/truss/truss.h b/usr.bin/truss/truss.h
    index dcc86a57136..ea954e85ab5 100644
    --- a/usr.bin/truss/truss.h
    +++ b/usr.bin/truss/truss.h
    @@ -62,7 +62,7 @@ struct trussinfo
     	SLIST_HEAD(, threadinfo) threadlist;
     };
     
    -#define	timespecsubt(tvp, uvp, vvp)					\
    +#define	timespecsubt_to(tvp, uvp, vvp)					\
     	do {								\
     		(vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec;		\
     		(vvp)->tv_nsec = (tvp)->tv_nsec - (uvp)->tv_nsec;	\
    @@ -72,7 +72,7 @@ struct trussinfo
     		}							\
     	} while (0)
     
    -#define	timespecadd(tvp, uvp, vvp)					\
    +#define	timespecadd_to(tvp, uvp, vvp)					\
     	do {								\
     		(vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec;		\
     		(vvp)->tv_nsec = (tvp)->tv_nsec + (uvp)->tv_nsec;	\
    
    From c6f9cfb723403a00b233b0a4b48ce28a79b7396d Mon Sep 17 00:00:00 2001
    From: Ian Lepore 
    Date: Tue, 26 Feb 2013 03:24:45 +0000
    Subject: [PATCH 0412/1476] Adjust the arm kernel entry point address properly
     regardless of whether the e_entry field holds a physical or a virtual
     address.  Add a comment block that explains the assumptions being made by the
     adjustment code.
    
    ---
     sys/boot/common/load_elf.c | 23 +++++++++++++++++------
     1 file changed, 17 insertions(+), 6 deletions(-)
    
    diff --git a/sys/boot/common/load_elf.c b/sys/boot/common/load_elf.c
    index e1e6de74b16..d712b3d3004 100644
    --- a/sys/boot/common/load_elf.c
    +++ b/sys/boot/common/load_elf.c
    @@ -290,14 +290,25 @@ __elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, u_int64_t off)
     	} else
     	    off = 0;
     #elif defined(__arm__)
    -	if (off & 0xf0000000u) {
    -	    off = -(off & 0xf0000000u);
    -	    ehdr->e_entry += off;
    +	/*
    +	 * The elf headers in some kernels specify virtual addresses in all
    +	 * header fields.  More recently, the e_entry and p_paddr fields are the
    +	 * proper physical addresses.  Even when the p_paddr fields are correct,
    +	 * the MI code below uses the p_vaddr fields with an offset added for
    +	 * loading (doing so is arguably wrong).  To make loading work, we need
    +	 * an offset that represents the difference between physical and virtual
    +	 * addressing.  ARM kernels are always linked at 0xC0000000.  Depending
    +	 * on the headers, the offset value passed in may be physical or virtual
    +	 * (because it typically comes from e_entry), but we always replace
    +	 * whatever is passed in with the va<->pa offset.  On the other hand, we
    +	 * only adjust the entry point if it's a virtual address to begin with.
    +	 */
    +	off = -0xc0000000u;
    +	if ((ehdr->e_entry & 0xc0000000u) == 0xc000000u)
    +		ehdr->e_entry += off;
     #ifdef ELF_VERBOSE
    -	    printf("Converted entry 0x%08x\n", ehdr->e_entry);
    +	printf("ehdr->e_entry 0x%08x, va<->pa off %llx\n", ehdr->e_entry, off);
     #endif
    -	} else
    -	    off = 0;
     #else
     	off = 0;		/* other archs use direct mapped kernels */
     #endif
    
    From 245e65e713f419db3635a18ad1ef7cf885897830 Mon Sep 17 00:00:00 2001
    From: Tim Kientzle 
    Date: Tue, 26 Feb 2013 04:59:02 +0000
    Subject: [PATCH 0413/1476] RPi users might want to touch the boot partition,
     which is always FAT formatted on this board, so compile-in MSDOSFS.
    
    Comment out the compiled-in FDT and explain why.
    ---
     sys/arm/conf/RPI-B | 7 +++++--
     1 file changed, 5 insertions(+), 2 deletions(-)
    
    diff --git a/sys/arm/conf/RPI-B b/sys/arm/conf/RPI-B
    index c7b9a5f6628..d9e8d38f086 100644
    --- a/sys/arm/conf/RPI-B
    +++ b/sys/arm/conf/RPI-B
    @@ -42,6 +42,7 @@ options 	FFS			#Berkeley Fast Filesystem
     options 	SOFTUPDATES		#Enable FFS soft updates support
     options 	UFS_ACL			#Support for access control lists
     options 	UFS_DIRHASH		#Improve performance on big directories
    +options 	MSDOSFS			#MSDOS Filesystem
     device		snp
     
     options 	NFSCL			#Network Filesystem Client
    @@ -113,5 +114,7 @@ device		smsc
     
     # Flattened Device Tree
     options         FDT
    -options         FDT_DTB_STATIC
    -makeoptions     FDT_DTS_FILE=bcm2835-rpi-b.dts
    +# Note:  DTB is normally loaded and modified by RPi boot loader, then
    +# handed to kernel via U-Boot and ubldr.
    +#options         FDT_DTB_STATIC
    +#makeoptions     FDT_DTS_FILE=bcm2835-rpi-b.dts
    
    From 2c8472682c46958f0a11db9b6eaee7589f4541fc Mon Sep 17 00:00:00 2001
    From: Alan Cox 
    Date: Tue, 26 Feb 2013 07:00:24 +0000
    Subject: [PATCH 0414/1476] Eliminate a duplicate #include.
    
    Sponsored by:	EMC / Isilon Storage Division
    ---
     sys/fs/fuse/fuse_io.c | 1 -
     1 file changed, 1 deletion(-)
    
    diff --git a/sys/fs/fuse/fuse_io.c b/sys/fs/fuse/fuse_io.c
    index 06ad6346adb..5feec1efe49 100644
    --- a/sys/fs/fuse/fuse_io.c
    +++ b/sys/fs/fuse/fuse_io.c
    @@ -87,7 +87,6 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     
     #include "fuse.h"
     #include "fuse_file.h"
    
    From 6147fb3cff0ede8fd7545a8438a52ca8583482d9 Mon Sep 17 00:00:00 2001
    From: Alan Cox 
    Date: Tue, 26 Feb 2013 07:41:34 +0000
    Subject: [PATCH 0415/1476] Eliminate a redundant #include: machine/pmap.h is
     already included through vm/pmap.h.
    
    ---
     sys/arm/at91/at91_machdep.c      | 1 -
     sys/arm/sa11x0/assabet_machdep.c | 1 -
     2 files changed, 2 deletions(-)
    
    diff --git a/sys/arm/at91/at91_machdep.c b/sys/arm/at91/at91_machdep.c
    index 27e88447d44..3837cbde06a 100644
    --- a/sys/arm/at91/at91_machdep.c
    +++ b/sys/arm/at91/at91_machdep.c
    @@ -77,7 +77,6 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     #include 
     #include 
     #include 
    diff --git a/sys/arm/sa11x0/assabet_machdep.c b/sys/arm/sa11x0/assabet_machdep.c
    index 986395340d3..0808798106a 100644
    --- a/sys/arm/sa11x0/assabet_machdep.c
    +++ b/sys/arm/sa11x0/assabet_machdep.c
    @@ -80,7 +80,6 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     #include 
     #include 
     #include 
    
    From 219d95655054afe0cd8a9551708b5902ef880fa8 Mon Sep 17 00:00:00 2001
    From: Alan Cox 
    Date: Tue, 26 Feb 2013 08:17:34 +0000
    Subject: [PATCH 0416/1476] Be more conservative in auto-sizing and capping the
     kmem submap.  In fact, use the same values here that we use on 32-bit x86 and
     MIPS.  Some machines were reported to have problems with the more aggressive
     values.
    
    Reported and tested by:	andrew
    ---
     sys/arm/include/vmparam.h | 6 +++---
     1 file changed, 3 insertions(+), 3 deletions(-)
    
    diff --git a/sys/arm/include/vmparam.h b/sys/arm/include/vmparam.h
    index 94caeefddf6..09bf62ce3c4 100644
    --- a/sys/arm/include/vmparam.h
    +++ b/sys/arm/include/vmparam.h
    @@ -142,15 +142,15 @@
     #define VM_KMEM_SIZE		(12*1024*1024)
     #endif
     #ifndef VM_KMEM_SIZE_SCALE
    -#define VM_KMEM_SIZE_SCALE	(2)
    +#define VM_KMEM_SIZE_SCALE	(3)
     #endif
     
     /*
    - * Ceiling on the size of the kmem submap: 60% of the kernel map.
    + * Ceiling on the size of the kmem submap: 40% of the kernel map.
      */
     #ifndef VM_KMEM_SIZE_MAX
     #define	VM_KMEM_SIZE_MAX	((vm_max_kernel_address - \
    -    VM_MIN_KERNEL_ADDRESS + 1) * 3 / 5)
    +    VM_MIN_KERNEL_ADDRESS + 1) * 2 / 5)
     #endif
     
     #define MAXTSIZ 	(16*1024*1024)
    
    From 0f857eb26863fa7eb17f1246ecae17cc81890101 Mon Sep 17 00:00:00 2001
    From: Martin Matuska 
    Date: Tue, 26 Feb 2013 08:51:39 +0000
    Subject: [PATCH 0417/1476] Update vendor-sys/illumos/dist to illumos-gate
     13968:e4988c7d0403
    
    Illumos ZFS issues:
      3552 condensing one space map burns 3 seconds of CPU in spa_sync() thread
           (fix race condition)
    ---
     uts/common/fs/zfs/metaslab.c | 27 +++++++++++++++++----------
     1 file changed, 17 insertions(+), 10 deletions(-)
    
    diff --git a/uts/common/fs/zfs/metaslab.c b/uts/common/fs/zfs/metaslab.c
    index 76c66a00a33..bf9889e183d 100644
    --- a/uts/common/fs/zfs/metaslab.c
    +++ b/uts/common/fs/zfs/metaslab.c
    @@ -1383,6 +1383,13 @@ metaslab_group_alloc(metaslab_group_t *mg, uint64_t psize, uint64_t asize,
     				mutex_exit(&mg->mg_lock);
     				return (-1ULL);
     			}
    +
    +			/*
    +			 * If the selected metaslab is condensing, skip it.
    +			 */
    +			if (msp->ms_map->sm_condensing)
    +				continue;
    +
     			was_active = msp->ms_weight & METASLAB_ACTIVE_MASK;
     			if (activation_weight == METASLAB_WEIGHT_PRIMARY)
     				break;
    @@ -1422,16 +1429,6 @@ metaslab_group_alloc(metaslab_group_t *mg, uint64_t psize, uint64_t asize,
     
     		mutex_enter(&msp->ms_lock);
     
    -		/*
    -		 * If this metaslab is currently condensing then pick again as
    -		 * we can't manipulate this metaslab until it's committed
    -		 * to disk.
    -		 */
    -		if (msp->ms_map->sm_condensing) {
    -			mutex_exit(&msp->ms_lock);
    -			continue;
    -		}
    -
     		/*
     		 * Ensure that the metaslab we have selected is still
     		 * capable of handling our request. It's possible that
    @@ -1458,6 +1455,16 @@ metaslab_group_alloc(metaslab_group_t *mg, uint64_t psize, uint64_t asize,
     			continue;
     		}
     
    +		/*
    +		 * If this metaslab is currently condensing then pick again as
    +		 * we can't manipulate this metaslab until it's committed
    +		 * to disk.
    +		 */
    +		if (msp->ms_map->sm_condensing) {
    +			mutex_exit(&msp->ms_lock);
    +			continue;
    +		}
    +
     		if ((offset = space_map_alloc(msp->ms_map, asize)) != -1ULL)
     			break;
     
    
    From 1f06ad3c96e5ce038e57c10b8155583d20307f98 Mon Sep 17 00:00:00 2001
    From: Martin Matuska 
    Date: Tue, 26 Feb 2013 08:53:33 +0000
    Subject: [PATCH 0418/1476] Update vendor/illumos/dist and
     vendor-sys/illumos/dist to illumos-gate 13969:b2c7608044b7
    
    Illumos ZFS issues:
      3588 provide zfs properties for logical (uncompressed) space used and
           referenced
    ---
     common/zfs/zfs_prop.c           |  6 +++++-
     man/man1m/zfs.1m                | 34 +++++++++++++++++++++++++++++++++
     uts/common/fs/zfs/dsl_dataset.c |  2 ++
     uts/common/fs/zfs/dsl_dir.c     |  2 ++
     uts/common/sys/fs/zfs.h         |  2 ++
     5 files changed, 45 insertions(+), 1 deletion(-)
    
    diff --git a/common/zfs/zfs_prop.c b/common/zfs/zfs_prop.c
    index 9d8365528c3..ebb267965a3 100644
    --- a/common/zfs/zfs_prop.c
    +++ b/common/zfs/zfs_prop.c
    @@ -20,7 +20,7 @@
      */
     /*
      * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
    - * Copyright (c) 2011 by Delphix. All rights reserved.
    + * Copyright (c) 2012 by Delphix. All rights reserved.
      * Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
      */
     
    @@ -350,6 +350,10 @@ zfs_prop_init(void)
     	    ZFS_TYPE_SNAPSHOT, "", "USERREFS");
     	zprop_register_number(ZFS_PROP_WRITTEN, "written", 0, PROP_READONLY,
     	    ZFS_TYPE_DATASET, "", "WRITTEN");
    +	zprop_register_number(ZFS_PROP_LOGICALUSED, "logicalused", 0,
    +	    PROP_READONLY, ZFS_TYPE_DATASET, "", "LUSED");
    +	zprop_register_number(ZFS_PROP_LOGICALREFERENCED, "logicalreferenced",
    +	    0, PROP_READONLY, ZFS_TYPE_DATASET, "", "LREFER");
     
     	/* default number properties */
     	zprop_register_number(ZFS_PROP_QUOTA, "quota", 0, PROP_DEFAULT,
    diff --git a/man/man1m/zfs.1m b/man/man1m/zfs.1m
    index 10382efa785..18441dad6ef 100644
    --- a/man/man1m/zfs.1m
    +++ b/man/man1m/zfs.1m
    @@ -532,6 +532,40 @@ by using the \fBzfs destroy\fR \fB-d\fR command. Otherwise, the property is
     \fBoff\fR.
     .RE
     
    +.sp
    +.ne 2
    +.na
    +\fB\fBlogicalreferenced\fR\fR
    +.ad
    +.sp .6
    +.RS 4n
    +The amount of space that is "logically" accessible by this dataset.  See
    +the \fBreferenced\fR property.  The logical space ignores the effect of
    +the \fBcompression\fR and \fBcopies\fR properties, giving a quantity
    +closer to the amount of data that applications see.  However, it does
    +include space consumed by metadata.
    +.sp
    +This property can also be referred to by its shortened column name,
    +\fBlrefer\fR.
    +.RE
    +
    +.sp
    +.ne 2
    +.na
    +\fB\fBlogicalused\fR\fR
    +.ad
    +.sp .6
    +.RS 4n
    +The amount of space that is "logically" consumed by this dataset and all
    +its descendents.  See the \fBused\fR property.  The logical space
    +ignores the effect of the \fBcompression\fR and \fBcopies\fR properties,
    +giving a quantity closer to the amount of data that applications see.
    +However, it does include space consumed by metadata.
    +.sp
    +This property can also be referred to by its shortened column name,
    +\fBlused\fR.
    +.RE
    +
     .sp
     .ne 2
     .na
    diff --git a/uts/common/fs/zfs/dsl_dataset.c b/uts/common/fs/zfs/dsl_dataset.c
    index cf888d2017a..0a5ef837ccf 100644
    --- a/uts/common/fs/zfs/dsl_dataset.c
    +++ b/uts/common/fs/zfs/dsl_dataset.c
    @@ -2247,6 +2247,8 @@ dsl_dataset_stats(dsl_dataset_t *ds, nvlist_t *nv)
     	    ds->ds_phys->ds_compressed_bytes);
     
     	dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_REFRATIO, ratio);
    +	dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_LOGICALREFERENCED,
    +	    ds->ds_phys->ds_uncompressed_bytes);
     
     	if (dsl_dataset_is_snapshot(ds)) {
     		dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_COMPRESSRATIO, ratio);
    diff --git a/uts/common/fs/zfs/dsl_dir.c b/uts/common/fs/zfs/dsl_dir.c
    index df3f02b1df3..5ccb6862e9d 100644
    --- a/uts/common/fs/zfs/dsl_dir.c
    +++ b/uts/common/fs/zfs/dsl_dir.c
    @@ -530,6 +530,8 @@ dsl_dir_stats(dsl_dir_t *dd, nvlist_t *nv)
     	    dd->dd_phys->dd_compressed_bytes == 0 ? 100 :
     	    (dd->dd_phys->dd_uncompressed_bytes * 100 /
     	    dd->dd_phys->dd_compressed_bytes));
    +	dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_LOGICALUSED,
    +	    dd->dd_phys->dd_uncompressed_bytes);
     	if (dd->dd_phys->dd_flags & DD_FLAG_USED_BREAKDOWN) {
     		dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_USEDSNAP,
     		    dd->dd_phys->dd_used_breakdown[DD_USED_SNAP]);
    diff --git a/uts/common/sys/fs/zfs.h b/uts/common/sys/fs/zfs.h
    index 8639a2b8db4..286b35b9d6c 100644
    --- a/uts/common/sys/fs/zfs.h
    +++ b/uts/common/sys/fs/zfs.h
    @@ -138,6 +138,8 @@ typedef enum {
     	ZFS_PROP_REFRATIO,
     	ZFS_PROP_WRITTEN,
     	ZFS_PROP_CLONES,
    +	ZFS_PROP_LOGICALUSED,
    +	ZFS_PROP_LOGICALREFERENCED,
     	ZFS_NUM_PROPS
     } zfs_prop_t;
     
    
    From 38fda92679e6b688e18d12435e82b97f699a8549 Mon Sep 17 00:00:00 2001
    From: Adrian Chadd 
    Date: Tue, 26 Feb 2013 10:24:49 +0000
    Subject: [PATCH 0419/1476] Update the EWMA statistics for each intermediary
     rate as well as the final rate.
    
    This fixes two things:
    
    * The intermediary rates now also have their EWMA values changed;
    * The existing code was using the wrong value for longtries - so the
      EWMA stats were only adjusted for the first rate and not subsequent
      rates in a MRR setup.
    
    TODO:
    
    * Merge the EWMA updates into update_stats() now..
    ---
     sys/dev/ath/ath_rate/sample/sample.c | 43 +++++++++++++++++++++-------
     1 file changed, 33 insertions(+), 10 deletions(-)
    
    diff --git a/sys/dev/ath/ath_rate/sample/sample.c b/sys/dev/ath/ath_rate/sample/sample.c
    index 54360f510cd..a7d6af6b20f 100644
    --- a/sys/dev/ath/ath_rate/sample/sample.c
    +++ b/sys/dev/ath/ath_rate/sample/sample.c
    @@ -1008,6 +1008,15 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
     				     short_tries, long_tries,
     				     long_tries > rc[0].tries,
     				     nframes, nbad);
    +			update_ewma_stats(sc, an, frame_size,
    +				     rc[0].rix, rc[0].tries,
    +				     rc[1].rix, rc[1].tries,
    +				     rc[2].rix, rc[2].tries,
    +				     rc[3].rix, rc[3].tries,
    +				     short_tries, long_tries,
    +				     long_tries > rc[0].tries,
    +				     nframes, nbad);
    +
     			long_tries -= rc[0].tries;
     		}
     		
    @@ -1020,6 +1029,14 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
     				     short_tries, long_tries,
     				     status,
     				     nframes, nbad);
    +			update_ewma_stats(sc, an, frame_size,
    +				     rc[1].rix, rc[1].tries,
    +				     rc[2].rix, rc[2].tries,
    +				     rc[3].rix, rc[3].tries,
    +				     0, 0,
    +				     short_tries, long_tries,
    +				     status,
    +				     nframes, nbad);
     			long_tries -= rc[1].tries;
     		}
     
    @@ -1032,6 +1049,14 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
     				     short_tries, long_tries,
     				     status,
     				     nframes, nbad);
    +			update_ewma_stats(sc, an, frame_size,
    +				     rc[2].rix, rc[2].tries,
    +				     rc[3].rix, rc[3].tries,
    +				     0, 0,
    +				     0, 0,
    +				     short_tries, long_tries,
    +				     status,
    +				     nframes, nbad);
     			long_tries -= rc[2].tries;
     		}
     
    @@ -1044,17 +1069,15 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
     				     short_tries, long_tries,
     				     status,
     				     nframes, nbad);
    +			update_ewma_stats(sc, an, frame_size,
    +				     rc[3].rix, rc[3].tries,
    +				     0, 0,
    +				     0, 0,
    +				     0, 0,
    +				     short_tries, long_tries,
    +				     status,
    +				     nframes, nbad);
     		}
    -
    -		update_ewma_stats(sc, an, frame_size,
    -			     rc[0].rix, rc[0].tries,
    -			     rc[1].rix, rc[1].tries,
    -			     rc[2].rix, rc[2].tries,
    -			     rc[3].rix, rc[3].tries,
    -			     short_tries, long_tries,
    -			     long_tries > rc[0].tries,
    -			     nframes, nbad);
    -
     	}
     }
     
    
    From 8a4f65bc335d44b791fd71803ea39e7085720eff Mon Sep 17 00:00:00 2001
    From: Alexander Motin 
    Date: Tue, 26 Feb 2013 13:59:39 +0000
    Subject: [PATCH 0420/1476] Change the way how software PMC updates counters.
     This at least fixes -n option of pmcstat.
    
    Reviewed by:	fabient
    ---
     sys/dev/hwpmc/hwpmc_soft.c | 8 ++++++--
     1 file changed, 6 insertions(+), 2 deletions(-)
    
    diff --git a/sys/dev/hwpmc/hwpmc_soft.c b/sys/dev/hwpmc/hwpmc_soft.c
    index dac36127916..0ed22623e35 100644
    --- a/sys/dev/hwpmc/hwpmc_soft.c
    +++ b/sys/dev/hwpmc/hwpmc_soft.c
    @@ -408,8 +408,11 @@ pmc_soft_intr(struct pmckern_soft *ks)
     		}
     
     		processed = 1;
    -		pc->soft_values[ri]++;
     		if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) {
    +			if ((pc->soft_values[ri]--) <= 0)
    +				pc->soft_values[ri] += pm->pm_sc.pm_reloadcount;
    +			else
    +				continue;
     			user_mode = TRAPF_USERMODE(ks->pm_tf);
     			error = pmc_process_interrupt(ks->pm_cpu, PMC_SR, pm,
     			    ks->pm_tf, user_mode);
    @@ -424,7 +427,8 @@ pmc_soft_intr(struct pmckern_soft *ks)
     				 */
     				curthread->td_flags |= TDF_ASTPENDING;
     			}
    -		}
    +		} else
    +			pc->soft_values[ri]++;
     	}
     
     	atomic_add_int(processed ? &pmc_stats.pm_intr_processed :
    
    From 0dde287b2038fcffb6aec4f64cbd3ffed3f8adcb Mon Sep 17 00:00:00 2001
    From: Attilio Rao 
    Date: Tue, 26 Feb 2013 17:22:08 +0000
    Subject: [PATCH 0421/1476] Wrap the sleeps synchronized by the vm_object lock
     into the specific macro VM_OBJECT_SLEEP(). This hides some implementation
     details like the usage of the msleep() primitive and the necessity to access
     to the lock address directly. For this reason VM_OBJECT_MTX() macro is now
     retired.
    
    Sponsored by:	EMC / Isilon storage division
    Reviewed by:	alc
    Tested by:	pho
    ---
     sys/vm/swap_pager.c  |  2 +-
     sys/vm/vm_object.c   | 12 +++++-------
     sys/vm/vm_object.h   |  4 +++-
     sys/vm/vm_page.c     |  2 +-
     sys/vm/vnode_pager.c |  4 ++--
     5 files changed, 12 insertions(+), 12 deletions(-)
    
    diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c
    index 44bff250706..2659b67cbd1 100644
    --- a/sys/vm/swap_pager.c
    +++ b/sys/vm/swap_pager.c
    @@ -1213,7 +1213,7 @@ swap_pager_getpages(vm_object_t object, vm_page_t *m, int count, int reqpage)
     	while ((mreq->oflags & VPO_SWAPINPROG) != 0) {
     		mreq->oflags |= VPO_WANTED;
     		PCPU_INC(cnt.v_intrans);
    -		if (msleep(mreq, VM_OBJECT_MTX(object), PSWP, "swread", hz*20)) {
    +		if (VM_OBJECT_SLEEP(object, mreq, PSWP, "swread", hz * 20)) {
     			printf(
     "swap_pager: indefinite wait buffer: bufobj: %p, blkno: %jd, size: %ld\n",
     			    bp->b_bufobj, (intmax_t)bp->b_blkno, bp->b_bcount);
    diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c
    index 32b07796a14..fbfd24e30b0 100644
    --- a/sys/vm/vm_object.c
    +++ b/sys/vm/vm_object.c
    @@ -387,7 +387,7 @@ vm_object_pip_wait(vm_object_t object, char *waitid)
     	VM_OBJECT_LOCK_ASSERT(object, MA_OWNED);
     	while (object->paging_in_progress) {
     		object->flags |= OBJ_PIPWNT;
    -		msleep(object, VM_OBJECT_MTX(object), PVM, waitid, 0);
    +		VM_OBJECT_SLEEP(object, object, PVM, waitid, 0);
     	}
     }
     
    @@ -579,8 +579,7 @@ retry:
     					} else if (object->paging_in_progress) {
     						VM_OBJECT_UNLOCK(robject);
     						object->flags |= OBJ_PIPWNT;
    -						msleep(object,
    -						    VM_OBJECT_MTX(object),
    +						VM_OBJECT_SLEEP(object, object,
     						    PDROP | PVM, "objde2", 0);
     						VM_OBJECT_LOCK(robject);
     						temp = robject->backing_object;
    @@ -1139,8 +1138,7 @@ shadowlookup:
     			if (object != tobject)
     				VM_OBJECT_UNLOCK(object);
     			m->oflags |= VPO_WANTED;
    -			msleep(m, VM_OBJECT_MTX(tobject), PDROP | PVM, "madvpo",
    -			    0);
    +			VM_OBJECT_SLEEP(tobject, m, PDROP | PVM, "madvpo" , 0);
     			VM_OBJECT_LOCK(object);
       			goto relookup;
     		}
    @@ -1338,7 +1336,7 @@ retry:
     		if ((m->oflags & VPO_BUSY) || m->busy) {
     			VM_OBJECT_UNLOCK(new_object);
     			m->oflags |= VPO_WANTED;
    -			msleep(m, VM_OBJECT_MTX(orig_object), PVM, "spltwt", 0);
    +			VM_OBJECT_SLEEP(orig_object, m, PVM, "spltwt" , 0);
     			VM_OBJECT_LOCK(new_object);
     			goto retry;
     		}
    @@ -1496,7 +1494,7 @@ vm_object_backing_scan(vm_object_t object, int op)
     				if ((p->oflags & VPO_BUSY) || p->busy) {
     					VM_OBJECT_UNLOCK(object);
     					p->oflags |= VPO_WANTED;
    -					msleep(p, VM_OBJECT_MTX(backing_object),
    +					VM_OBJECT_SLEEP(backing_object, p,
     					    PDROP | PVM, "vmocol", 0);
     					VM_OBJECT_LOCK(object);
     					VM_OBJECT_LOCK(backing_object);
    diff --git a/sys/vm/vm_object.h b/sys/vm/vm_object.h
    index 813475237af..0cb63e99c3b 100644
    --- a/sys/vm/vm_object.h
    +++ b/sys/vm/vm_object.h
    @@ -210,7 +210,9 @@ extern struct vm_object kmem_object_store;
     					mtx_init(&(object)->mtx, "vm object", \
     					    (type), MTX_DEF | MTX_DUPOK)
     #define	VM_OBJECT_LOCKED(object)	mtx_owned(&(object)->mtx)
    -#define	VM_OBJECT_MTX(object)		(&(object)->mtx)
    +#define	VM_OBJECT_SLEEP(object, wchan, pri, wmesg, timo) \
    +					msleep((wchan), &(object)->mtx, (pri), \
    +					    (wmesg), (timo))
     #define	VM_OBJECT_TRYLOCK(object)	mtx_trylock(&(object)->mtx)
     #define	VM_OBJECT_UNLOCK(object)	mtx_unlock(&(object)->mtx)
     
    diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
    index c952c0541cc..44f7193ace1 100644
    --- a/sys/vm/vm_page.c
    +++ b/sys/vm/vm_page.c
    @@ -763,7 +763,7 @@ vm_page_sleep(vm_page_t m, const char *msg)
     	 * it.
     	 */
     	m->oflags |= VPO_WANTED;
    -	msleep(m, VM_OBJECT_MTX(m->object), PVM, msg, 0);
    +	VM_OBJECT_SLEEP(m->object, m, PVM, msg, 0);
     }
     
     /*
    diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c
    index a6d78f4065c..40f9497d69d 100644
    --- a/sys/vm/vnode_pager.c
    +++ b/sys/vm/vnode_pager.c
    @@ -116,7 +116,7 @@ vnode_create_vobject(struct vnode *vp, off_t isize, struct thread *td)
     		}
     		VOP_UNLOCK(vp, 0);
     		vm_object_set_flag(object, OBJ_DISCONNECTWNT);
    -		msleep(object, VM_OBJECT_MTX(object), PDROP | PVM, "vodead", 0);
    +		VM_OBJECT_SLEEP(object, object, PDROP | PVM, "vodead" , 0);
     		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
     	}
     
    @@ -210,7 +210,7 @@ retry:
     		if ((object->flags & OBJ_DEAD) == 0)
     			break;
     		vm_object_set_flag(object, OBJ_DISCONNECTWNT);
    -		msleep(object, VM_OBJECT_MTX(object), PDROP | PVM, "vadead", 0);
    +		VM_OBJECT_SLEEP(object, object, PDROP | PVM, "vadead" , 0);
     	}
     
     	if (vp->v_usecount == 0)
    
    From 1af19ee4a2929303426ae4f532bb533f275afce1 Mon Sep 17 00:00:00 2001
    From: Alexander Motin 
    Date: Tue, 26 Feb 2013 18:13:42 +0000
    Subject: [PATCH 0422/1476] Add support for good old 8192Hz profiling clock to
     software PMC.
    
    Reviewed by:	fabient
    ---
     lib/libpmc/pmc.soft.3       |  4 +++-
     sys/dev/hwpmc/hwpmc_soft.c  |  9 ++++++---
     sys/kern/kern_clock.c       |  5 +++++
     sys/kern/kern_clocksource.c | 24 +++++++++++++++---------
     4 files changed, 29 insertions(+), 13 deletions(-)
    
    diff --git a/lib/libpmc/pmc.soft.3 b/lib/libpmc/pmc.soft.3
    index a8674ba8b6f..a6919aef0ca 100644
    --- a/lib/libpmc/pmc.soft.3
    +++ b/lib/libpmc/pmc.soft.3
    @@ -23,7 +23,7 @@
     .\"
     .\" $FreeBSD$
     .\"
    -.Dd March 28, 2012
    +.Dd February 26, 2013
     .Dt PMC.SOFT 3
     .Os
     .Sh NAME
    @@ -61,6 +61,8 @@ The event specifiers supported by software are:
     Hard clock ticks.
     .It Li CLOCK.STAT
     Stat clock ticks.
    +.It Li CLOCK.PROF
    +Profiling clock ticks.
     .It Li LOCK.FAILED
     Lock acquisition failed.
     .It Li PAGE_FAULT.ALL
    diff --git a/sys/dev/hwpmc/hwpmc_soft.c b/sys/dev/hwpmc/hwpmc_soft.c
    index 0ed22623e35..48e297e769c 100644
    --- a/sys/dev/hwpmc/hwpmc_soft.c
    +++ b/sys/dev/hwpmc/hwpmc_soft.c
    @@ -45,6 +45,8 @@ __FBSDID("$FreeBSD$");
     #define	SOFT_CAPS (PMC_CAP_READ | PMC_CAP_WRITE | PMC_CAP_INTERRUPT | \
         PMC_CAP_USER | PMC_CAP_SYSTEM)
     
    +PMC_SOFT_DECLARE( , , clock, prof);
    +
     struct soft_descr {
     	struct pmc_descr pm_descr;  /* "base class" */
     };
    @@ -125,6 +127,8 @@ soft_allocate_pmc(int cpu, int ri, struct pmc *pm,
     		return (EINVAL);
     	pmc_soft_ev_release(ps);
     
    +	if (ev == pmc___clock_prof.ps_ev.pm_ev_code)
    +		cpu_startprofclock();
     	return (0);
     }
     
    @@ -324,9 +328,8 @@ soft_release_pmc(int cpu, int ri, struct pmc *pmc)
     	KASSERT(phw->phw_pmc == NULL,
     	    ("[soft,%d] PHW pmc %p non-NULL", __LINE__, phw->phw_pmc));
     
    -	/*
    -	 * Nothing to do.
    -	 */
    +	if (pmc->pm_event == pmc___clock_prof.ps_ev.pm_ev_code)
    +		cpu_stopprofclock();
     	return (0);
     }
     
    diff --git a/sys/kern/kern_clock.c b/sys/kern/kern_clock.c
    index 9d62c58524a..55a2bff57f8 100644
    --- a/sys/kern/kern_clock.c
    +++ b/sys/kern/kern_clock.c
    @@ -78,6 +78,7 @@ __FBSDID("$FreeBSD$");
     #include 
     PMC_SOFT_DEFINE( , , clock, hard);
     PMC_SOFT_DEFINE( , , clock, stat);
    +PMC_SOFT_DEFINE( , , clock, prof);
     #endif
     
     #ifdef DEVICE_POLLING
    @@ -817,6 +818,10 @@ profclock_cnt(int cnt, int usermode, uintfptr_t pc)
     		}
     	}
     #endif
    +#ifdef HWPMC_HOOKS
    +	if (td->td_intr_frame != NULL)
    +		PMC_SOFT_CALL_TF( , , clock, prof, td->td_intr_frame);
    +#endif
     }
     
     /*
    diff --git a/sys/kern/kern_clocksource.c b/sys/kern/kern_clocksource.c
    index 6fd40a87051..33f21e97be2 100644
    --- a/sys/kern/kern_clocksource.c
    +++ b/sys/kern/kern_clocksource.c
    @@ -732,12 +732,15 @@ cpu_startprofclock(void)
     {
     
     	ET_LOCK();
    -	if (periodic) {
    -		configtimer(0);
    -		profiling = 1;
    -		configtimer(1);
    +	if (profiling == 0) {
    +		if (periodic) {
    +			configtimer(0);
    +			profiling = 1;
    +			configtimer(1);
    +		} else
    +			profiling = 1;
     	} else
    -		profiling = 1;
    +		profiling++;
     	ET_UNLOCK();
     }
     
    @@ -749,12 +752,15 @@ cpu_stopprofclock(void)
     {
     
     	ET_LOCK();
    -	if (periodic) {
    -		configtimer(0);
    +	if (profiling == 1) {
    +		if (periodic) {
    +			configtimer(0);
    +			profiling = 0;
    +			configtimer(1);
    +		} else
     		profiling = 0;
    -		configtimer(1);
     	} else
    -		profiling = 0;
    +		profiling--;
     	ET_UNLOCK();
     }
     
    
    From 7ad65edee343f79be93a1ec098d38a7881609e02 Mon Sep 17 00:00:00 2001
    From: John Baldwin 
    Date: Tue, 26 Feb 2013 18:30:47 +0000
    Subject: [PATCH 0423/1476] Add a quirk to disable this driver for certain
     older laptops with an ICH2 southbridge and an Intel 82815_MC host bridge
     where the host bridge's revision is less than 5.
    
    Tested by:	mi
    MFC after:	1 week
    ---
     sys/dev/cpufreq/ichss.c | 21 +++++++++++++++++----
     1 file changed, 17 insertions(+), 4 deletions(-)
    
    diff --git a/sys/dev/cpufreq/ichss.c b/sys/dev/cpufreq/ichss.c
    index 0eae0c99618..101b5765800 100644
    --- a/sys/dev/cpufreq/ichss.c
    +++ b/sys/dev/cpufreq/ichss.c
    @@ -67,7 +67,7 @@ struct ichss_softc {
     #define PCI_DEV_82801BA		0x244c /* ICH2M */
     #define PCI_DEV_82801CA		0x248c /* ICH3M */
     #define PCI_DEV_82801DB		0x24cc /* ICH4M */
    -#define PCI_DEV_82815BA		0x1130 /* Unsupported/buggy part */
    +#define PCI_DEV_82815_MC	0x1130 /* Unsupported/buggy part */
     
     /* PCI config registers for finding PMBASE and enabling SpeedStep. */
     #define ICHSS_PMBASE_OFFSET	0x40
    @@ -155,9 +155,6 @@ ichss_identify(driver_t *driver, device_t parent)
     	 * E.g. see Section 6.1 "PCI Devices and Functions" and table 6.1 of
     	 * Intel(r) 82801BA I/O Controller Hub 2 (ICH2) and Intel(r) 82801BAM
     	 * I/O Controller Hub 2 Mobile (ICH2-M).
    -	 *
    -	 * TODO: add a quirk to disable if we see the 82815_MC along
    -	 * with the 82801BA and revision < 5.
     	 */
     	ich_device = pci_find_bsf(0, 0x1f, 0);
     	if (ich_device == NULL ||
    @@ -167,6 +164,22 @@ ichss_identify(driver_t *driver, device_t parent)
     	    pci_get_device(ich_device) != PCI_DEV_82801DB))
     		return;
     
    +	/*
    +	 * Certain systems with ICH2 and an Intel 82815_MC host bridge
    +	 * where the host bridge's revision is < 5 lockup if SpeedStep
    +	 * is used.
    +	 */
    +	if (pci_get_device(ich_device) == PCI_DEV_82801BA) {
    +		device_t hostb;
    +
    +		hostb = pci_find_bsf(0, 0, 0);
    +		if (hostb != NULL &&
    +		    pci_get_vendor(hostb) == PCI_VENDOR_INTEL &&
    +		    pci_get_device(hostb) == PCI_DEV_82815_MC &&
    +		    pci_get_revid(hostb) < 5)
    +			return;
    +	}
    +
     	/* Find the PMBASE register from our PCI config header. */
     	pmbase = pci_read_config(ich_device, ICHSS_PMBASE_OFFSET,
     	    sizeof(pmbase));
    
    From 498b4407b9dbd8eac29cdbe337dea668e27eb671 Mon Sep 17 00:00:00 2001
    From: Xin LI 
    Date: Tue, 26 Feb 2013 18:33:23 +0000
    Subject: [PATCH 0424/1476] Correct a typo introduced in r153575, which gives
     inverted logic when handling blocking semantics when seeding.
    
    PR:		kern/143298
    Submitted by:	James Juran 
    Reviewed by:	markm
    MFC after:	3 days
    ---
     sys/dev/random/randomdev_soft.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/sys/dev/random/randomdev_soft.c b/sys/dev/random/randomdev_soft.c
    index c720902c633..420a82a6793 100644
    --- a/sys/dev/random/randomdev_soft.c
    +++ b/sys/dev/random/randomdev_soft.c
    @@ -391,7 +391,7 @@ random_yarrow_block(int flag)
     	mtx_lock(&random_reseed_mtx);
     
     	/* Blocking logic */
    -	while (random_systat.seeded && !error) {
    +	while (!random_systat.seeded && !error) {
     		if (flag & O_NONBLOCK)
     			error = EWOULDBLOCK;
     		else {
    
    From c928b49e6379e118b4aa6511f7829b578d609cc1 Mon Sep 17 00:00:00 2001
    From: John-Mark Gurney 
    Date: Tue, 26 Feb 2013 19:46:02 +0000
    Subject: [PATCH 0425/1476] no one bothered to write the iconv.9 man page... 
     If it appears we can readd the xref...
    
    MFC:	1 week
    ---
     lib/libkiconv/kiconv.3 | 3 +--
     1 file changed, 1 insertion(+), 2 deletions(-)
    
    diff --git a/lib/libkiconv/kiconv.3 b/lib/libkiconv/kiconv.3
    index affacf1687c..ed250a1420c 100644
    --- a/lib/libkiconv/kiconv.3
    +++ b/lib/libkiconv/kiconv.3
    @@ -126,5 +126,4 @@ not using
     .Sh SEE ALSO
     .Xr iconv 3 ,
     .Xr tolower 3 ,
    -.Xr toupper 3 ,
    -.Xr iconv 9
    +.Xr toupper 3
    
    From d9dcc46365cf52a5902fde488e57e662ce715786 Mon Sep 17 00:00:00 2001
    From: Xin LI 
    Date: Tue, 26 Feb 2013 19:46:59 +0000
    Subject: [PATCH 0426/1476] Revert r247300 for now.  I'll post a new changeset
     for review.
    
    ---
     sys/sys/time.h           |  5 ++++-
     usr.bin/truss/main.c     |  8 ++++----
     usr.bin/truss/syscalls.c | 10 +++++-----
     usr.bin/truss/truss.h    |  4 ++--
     4 files changed, 15 insertions(+), 12 deletions(-)
    
    diff --git a/sys/sys/time.h b/sys/sys/time.h
    index 14b80e37aec..80878c0e9f8 100644
    --- a/sys/sys/time.h
    +++ b/sys/sys/time.h
    @@ -156,6 +156,9 @@ timeval2bintime(const struct timeval *tv, struct bintime *bt)
     	/* 18446744073709 = int(2^64 / 1000000) */
     	bt->frac = tv->tv_usec * (uint64_t)18446744073709LL;
     }
    +#endif /* __BSD_VISIBLE */
    +
    +#ifdef _KERNEL
     
     /* Operations on timespecs */
     #define	timespecclear(tvp)	((tvp)->tv_sec = (tvp)->tv_nsec = 0)
    @@ -194,7 +197,7 @@ timeval2bintime(const struct timeval *tv, struct bintime *bt)
     
     /* timevaladd and timevalsub are not inlined */
     
    -#endif /* __BSD_VISIBLE */
    +#endif /* _KERNEL */
     
     #ifndef _KERNEL			/* NetBSD/OpenBSD compatible interfaces */
     
    diff --git a/usr.bin/truss/main.c b/usr.bin/truss/main.c
    index 7b8242bb32f..4e9f74b8a3c 100644
    --- a/usr.bin/truss/main.c
    +++ b/usr.bin/truss/main.c
    @@ -323,14 +323,14 @@ START_TRACE:
     				fprintf(trussinfo->outfile, "%5d: ",
     				    trussinfo->pid);
     			if (trussinfo->flags & ABSOLUTETIMESTAMPS) {
    -				timespecsubt_to(&trussinfo->curthread->after,
    +				timespecsubt(&trussinfo->curthread->after,
     				    &trussinfo->start_time, &timediff);
     				fprintf(trussinfo->outfile, "%ld.%09ld ",
     				    (long)timediff.tv_sec,
     				    timediff.tv_nsec);
     			}
     			if (trussinfo->flags & RELATIVETIMESTAMPS) {
    -				timespecsubt_to(&trussinfo->curthread->after,
    +				timespecsubt(&trussinfo->curthread->after,
     				    &trussinfo->curthread->before, &timediff);
     				fprintf(trussinfo->outfile, "%ld.%09ld ",
     				    (long)timediff.tv_sec,
    @@ -349,14 +349,14 @@ START_TRACE:
     				fprintf(trussinfo->outfile, "%5d: ",
     				    trussinfo->pid);
     			if (trussinfo->flags & ABSOLUTETIMESTAMPS) {
    -				timespecsubt_to(&trussinfo->curthread->after,
    +				timespecsubt(&trussinfo->curthread->after,
     				    &trussinfo->start_time, &timediff);
     				fprintf(trussinfo->outfile, "%ld.%09ld ",
     				    (long)timediff.tv_sec,
     				    timediff.tv_nsec);
     			}
     			if (trussinfo->flags & RELATIVETIMESTAMPS) {
    -				timespecsubt_to(&trussinfo->curthread->after,
    +				timespecsubt(&trussinfo->curthread->after,
     				    &trussinfo->curthread->before, &timediff);
     				fprintf(trussinfo->outfile, "%ld.%09ld ",
     				    (long)timediff.tv_sec, timediff.tv_nsec);
    diff --git a/usr.bin/truss/syscalls.c b/usr.bin/truss/syscalls.c
    index c926af2515f..0afd083d845 100644
    --- a/usr.bin/truss/syscalls.c
    +++ b/usr.bin/truss/syscalls.c
    @@ -1126,14 +1126,14 @@ print_syscall(struct trussinfo *trussinfo, const char *name, int nargs,
     	}
     
     	if (trussinfo->flags & ABSOLUTETIMESTAMPS) {
    -		timespecsubt_to(&trussinfo->curthread->after,
    +		timespecsubt(&trussinfo->curthread->after,
     		    &trussinfo->start_time, &timediff);
     		len += fprintf(trussinfo->outfile, "%ld.%09ld ",
     		    (long)timediff.tv_sec, timediff.tv_nsec);
     	}
     
     	if (trussinfo->flags & RELATIVETIMESTAMPS) {
    -		timespecsubt_to(&trussinfo->curthread->after,
    +		timespecsubt(&trussinfo->curthread->after,
     		    &trussinfo->curthread->before, &timediff);
     		len += fprintf(trussinfo->outfile, "%ld.%09ld ",
     		    (long)timediff.tv_sec, timediff.tv_nsec);
    @@ -1165,9 +1165,9 @@ print_syscall_ret(struct trussinfo *trussinfo, const char *name, int nargs,
     		if (!sc)
     			return;
     		clock_gettime(CLOCK_REALTIME, &trussinfo->curthread->after);
    -		timespecsubt_to(&trussinfo->curthread->after,
    +		timespecsubt(&trussinfo->curthread->after,
     		    &trussinfo->curthread->before, &timediff);
    -		timespecadd_to(&sc->time, &timediff, &sc->time);
    +		timespecadd(&sc->time, &timediff, &sc->time);
     		sc->ncalls++;
     		if (errorp)
     			sc->nerror++;
    @@ -1205,7 +1205,7 @@ print_summary(struct trussinfo *trussinfo)
     			fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n",
     			    sc->name, (intmax_t)sc->time.tv_sec,
     			    sc->time.tv_nsec, sc->ncalls, sc->nerror);
    -			timespecadd_to(&total, &sc->time, &total);
    +			timespecadd(&total, &sc->time, &total);
     			ncall += sc->ncalls;
     			nerror += sc->nerror;
     		}
    diff --git a/usr.bin/truss/truss.h b/usr.bin/truss/truss.h
    index ea954e85ab5..dcc86a57136 100644
    --- a/usr.bin/truss/truss.h
    +++ b/usr.bin/truss/truss.h
    @@ -62,7 +62,7 @@ struct trussinfo
     	SLIST_HEAD(, threadinfo) threadlist;
     };
     
    -#define	timespecsubt_to(tvp, uvp, vvp)					\
    +#define	timespecsubt(tvp, uvp, vvp)					\
     	do {								\
     		(vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec;		\
     		(vvp)->tv_nsec = (tvp)->tv_nsec - (uvp)->tv_nsec;	\
    @@ -72,7 +72,7 @@ struct trussinfo
     		}							\
     	} while (0)
     
    -#define	timespecadd_to(tvp, uvp, vvp)					\
    +#define	timespecadd(tvp, uvp, vvp)					\
     	do {								\
     		(vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec;		\
     		(vvp)->tv_nsec = (tvp)->tv_nsec + (uvp)->tv_nsec;	\
    
    From f4e091106b94f517771af858fca924f2b816e4ca Mon Sep 17 00:00:00 2001
    From: Olivier Houchard 
    Date: Tue, 26 Feb 2013 19:58:49 +0000
    Subject: [PATCH 0427/1476] Don't forget to init the VFP stuff for all cores.
    
    ---
     sys/arm/arm/mp_machdep.c | 8 ++++++++
     1 file changed, 8 insertions(+)
    
    diff --git a/sys/arm/arm/mp_machdep.c b/sys/arm/arm/mp_machdep.c
    index 30e6b63eb2b..6337b9c59be 100644
    --- a/sys/arm/arm/mp_machdep.c
    +++ b/sys/arm/arm/mp_machdep.c
    @@ -49,6 +49,9 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    +#ifdef ARM_VFP_SUPPORT
    +#include 
    +#endif
     
     #include "opt_smp.h"
     
    @@ -181,6 +184,11 @@ init_secondary(int cpu)
     	KASSERT(PCPU_GET(idlethread) != NULL, ("no idle thread"));
     	pc->pc_curthread = pc->pc_idlethread;
     	pc->pc_curpcb = pc->pc_idlethread->td_pcb;
    +#ifdef ARM_VFP_SUPPORT
    +	pc->pc_cpu = cpu;
    +
    +	vfp_init();
    +#endif
     
     	mtx_lock_spin(&ap_boot_mtx);
     
    
    From 486179737a9b4f9bab89e695f23e593f2df5b850 Mon Sep 17 00:00:00 2001
    From: Olivier Houchard 
    Date: Tue, 26 Feb 2013 19:59:52 +0000
    Subject: [PATCH 0428/1476] Fix SMP build.
    
    ---
     sys/arm/arm/vfp.c | 7 +++----
     1 file changed, 3 insertions(+), 4 deletions(-)
    
    diff --git a/sys/arm/arm/vfp.c b/sys/arm/arm/vfp.c
    index bde566ca43c..c163af03045 100644
    --- a/sys/arm/arm/vfp.c
    +++ b/sys/arm/arm/vfp.c
    @@ -43,7 +43,6 @@ unsigned int get_coprocessorACR(void);
     int	vfp_bounce(u_int, u_int, struct trapframe *, int);
     void	vfp_discard(void);
     void	vfp_enable(void);
    -void	vfp_init(void);
     void	vfp_restore(struct vfp_state *);
     void	vfp_store(struct vfp_state *);
     void	set_coprocessorACR(u_int);
    @@ -74,8 +73,8 @@ void
     set_coprocessorACR(u_int val)
     {
     	__asm __volatile("mcr p15, 0, %0, c1, c0, 2\n\t"
    -			 "isb\n\t"
     	 : : "r" (val) : "cc");
    +	isb();
     }
     
     
    @@ -140,7 +139,7 @@ vfp_bounce(u_int addr, u_int insn, struct trapframe *frame, int code)
     #ifdef SMP
     		/* don't save if newer registers are on another processor */
     		if (vfptd /* && (vfptd == curthread) */ &&
    -		   (vfptd->td_pcb->pcb_vfpcpu == PCPU_GET(vfpcpu))
    +		   (vfptd->td_pcb->pcb_vfpcpu == PCPU_GET(cpu)))
     #else
     		/* someone did not save their registers, */
     		if (vfptd /* && (vfptd == curthread) */)
    @@ -168,7 +167,7 @@ vfp_bounce(u_int addr, u_int insn, struct trapframe *frame, int code)
     	 */
     	vfp_restore(&curpcb->pcb_vfpstate);
     #ifdef SMP
    -	curpcb->pcb_cpu = PCPU_GET(cpu);
    +	curpcb->pcb_vfpcpu = PCPU_GET(cpu);
     #endif
     	PCPU_SET(vfpcthread, PCPU_GET(curthread));
     	return 0;
    
    From d99fd701439f5a89bf69660b8e88f65134ad3a96 Mon Sep 17 00:00:00 2001
    From: Olivier Houchard 
    Date: Tue, 26 Feb 2013 20:01:05 +0000
    Subject: [PATCH 0429/1476] Export vfp_init() prototype, for use in the MP
     code.
    
    ---
     sys/arm/include/vfp.h | 1 +
     1 file changed, 1 insertion(+)
    
    diff --git a/sys/arm/include/vfp.h b/sys/arm/include/vfp.h
    index 618f49105dc..94c24a965f4 100644
    --- a/sys/arm/include/vfp.h
    +++ b/sys/arm/include/vfp.h
    @@ -124,5 +124,6 @@
     #define COPROC10		(0x3 << 20)
     #define COPROC11		(0x3 << 22)
     
    +void    vfp_init(void);
     
     #endif
    
    From 58a6b0338ad64e39968f08764759d7f8fd2a9cf2 Mon Sep 17 00:00:00 2001
    From: Neel Natu 
    Date: Tue, 26 Feb 2013 20:02:17 +0000
    Subject: [PATCH 0430/1476] Ignore the BARRIER flag in the virtio block header.
    
    This capability is not advertised by the host so ignore it even if the guest
    insists on setting the flag.
    
    Reviewed by:	grehan
    Obtained from:	NetApp
    ---
     usr.sbin/bhyve/pci_virtio_block.c | 15 +++++++++++----
     1 file changed, 11 insertions(+), 4 deletions(-)
    
    diff --git a/usr.sbin/bhyve/pci_virtio_block.c b/usr.sbin/bhyve/pci_virtio_block.c
    index c8fc914dfb7..62bf801bdcc 100644
    --- a/usr.sbin/bhyve/pci_virtio_block.c
    +++ b/usr.sbin/bhyve/pci_virtio_block.c
    @@ -110,8 +110,9 @@ CTASSERT(sizeof(struct vtblk_config) == VTBLK_CFGSZ);
      * Fixed-size block header
      */
     struct virtio_blk_hdr {
    -#define VBH_OP_READ	0
    -#define VBH_OP_WRITE	1
    +#define	VBH_OP_READ		0
    +#define	VBH_OP_WRITE		1
    +#define	VBH_FLAG_BARRIER	0x80000000	/* OR'ed into vbh_type */
     	uint32_t       	vbh_type;
     	uint32_t	vbh_ioprio;
     	uint64_t	vbh_sector;
    @@ -198,7 +199,7 @@ pci_vtblk_proc(struct pci_vtblk_softc *sc, struct vring_hqueue *hq)
     	int iolen;
     	int nsegs;
     	int uidx, aidx, didx;
    -	int writeop;
    +	int writeop, type;
     	off_t offset;
     
     	uidx = *hq->hq_used_idx;
    @@ -232,7 +233,13 @@ pci_vtblk_proc(struct pci_vtblk_softc *sc, struct vring_hqueue *hq)
     	assert(vid[0].vd_flags & VRING_DESC_F_NEXT);
     	assert((vid[0].vd_flags & VRING_DESC_F_WRITE) == 0);
     
    -	writeop = (vbh->vbh_type == VBH_OP_WRITE);
    +	/*
    +	 * XXX
    +	 * The guest should not be setting the BARRIER flag because
    +	 * we don't advertise the capability.
    +	 */
    +	type = vbh->vbh_type & ~VBH_FLAG_BARRIER;
    +	writeop = (type == VBH_OP_WRITE);
     
     	offset = vbh->vbh_sector * DEV_BSIZE;
     
    
    From 6559a21f71cd6f4532939540aae2ef5f41985ecf Mon Sep 17 00:00:00 2001
    From: Mikolaj Golub 
    Date: Tue, 26 Feb 2013 20:19:45 +0000
    Subject: [PATCH 0431/1476] Fix casting.
    
    MFC after:	3 days
    ---
     sbin/hastctl/hastctl.c | 10 +++++-----
     1 file changed, 5 insertions(+), 5 deletions(-)
    
    diff --git a/sbin/hastctl/hastctl.c b/sbin/hastctl/hastctl.c
    index 503072c8199..3dfde03add7 100644
    --- a/sbin/hastctl/hastctl.c
    +++ b/sbin/hastctl/hastctl.c
    @@ -342,15 +342,15 @@ control_status(struct nv *nv)
     		    (intmax_t)nv_get_uint64(nv, "dirty%u", ii));
     		printf("  statistics:\n");
     		printf("    reads: %ju\n",
    -		    (uint64_t)nv_get_uint64(nv, "stat_read%u", ii));
    +		    (uintmax_t)nv_get_uint64(nv, "stat_read%u", ii));
     		printf("    writes: %ju\n",
    -		    (uint64_t)nv_get_uint64(nv, "stat_write%u", ii));
    +		    (uintmax_t)nv_get_uint64(nv, "stat_write%u", ii));
     		printf("    deletes: %ju\n",
    -		    (uint64_t)nv_get_uint64(nv, "stat_delete%u", ii));
    +		    (uintmax_t)nv_get_uint64(nv, "stat_delete%u", ii));
     		printf("    flushes: %ju\n",
    -		    (uint64_t)nv_get_uint64(nv, "stat_flush%u", ii));
    +		    (uintmax_t)nv_get_uint64(nv, "stat_flush%u", ii));
     		printf("    activemap updates: %ju\n",
    -		    (uint64_t)nv_get_uint64(nv, "stat_activemap_update%u", ii));
    +		    (uintmax_t)nv_get_uint64(nv, "stat_activemap_update%u", ii));
     		printf("    local errors: "
     		    "read: %ju, write: %ju, delete: %ju, flush: %ju\n",
     		    (uintmax_t)nv_get_uint64(nv, "stat_read_error%u", ii),
    
    From 64a3476f0cc1690fbf055b1539913908651f1c78 Mon Sep 17 00:00:00 2001
    From: Attilio Rao 
    Date: Tue, 26 Feb 2013 20:35:40 +0000
    Subject: [PATCH 0432/1476] Remove white spaces.
    
    Sponsored by:	EMC / Isilon storage division
    ---
     sys/vm/vm_object.c   | 4 ++--
     sys/vm/vnode_pager.c | 4 ++--
     2 files changed, 4 insertions(+), 4 deletions(-)
    
    diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c
    index fbfd24e30b0..810707ee236 100644
    --- a/sys/vm/vm_object.c
    +++ b/sys/vm/vm_object.c
    @@ -1138,7 +1138,7 @@ shadowlookup:
     			if (object != tobject)
     				VM_OBJECT_UNLOCK(object);
     			m->oflags |= VPO_WANTED;
    -			VM_OBJECT_SLEEP(tobject, m, PDROP | PVM, "madvpo" , 0);
    +			VM_OBJECT_SLEEP(tobject, m, PDROP | PVM, "madvpo", 0);
     			VM_OBJECT_LOCK(object);
       			goto relookup;
     		}
    @@ -1336,7 +1336,7 @@ retry:
     		if ((m->oflags & VPO_BUSY) || m->busy) {
     			VM_OBJECT_UNLOCK(new_object);
     			m->oflags |= VPO_WANTED;
    -			VM_OBJECT_SLEEP(orig_object, m, PVM, "spltwt" , 0);
    +			VM_OBJECT_SLEEP(orig_object, m, PVM, "spltwt", 0);
     			VM_OBJECT_LOCK(new_object);
     			goto retry;
     		}
    diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c
    index 40f9497d69d..4c678f4458d 100644
    --- a/sys/vm/vnode_pager.c
    +++ b/sys/vm/vnode_pager.c
    @@ -116,7 +116,7 @@ vnode_create_vobject(struct vnode *vp, off_t isize, struct thread *td)
     		}
     		VOP_UNLOCK(vp, 0);
     		vm_object_set_flag(object, OBJ_DISCONNECTWNT);
    -		VM_OBJECT_SLEEP(object, object, PDROP | PVM, "vodead" , 0);
    +		VM_OBJECT_SLEEP(object, object, PDROP | PVM, "vodead", 0);
     		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
     	}
     
    @@ -210,7 +210,7 @@ retry:
     		if ((object->flags & OBJ_DEAD) == 0)
     			break;
     		vm_object_set_flag(object, OBJ_DISCONNECTWNT);
    -		VM_OBJECT_SLEEP(object, object, PDROP | PVM, "vadead" , 0);
    +		VM_OBJECT_SLEEP(object, object, PDROP | PVM, "vadead", 0);
     	}
     
     	if (vp->v_usecount == 0)
    
    From d78bd33facb7c34d3597790c2e0f310fe9720492 Mon Sep 17 00:00:00 2001
    From: Navdeep Parhar 
    Date: Tue, 26 Feb 2013 20:35:54 +0000
    Subject: [PATCH 0433/1476] cxgbe(4): Consider all the API versions of the
     interfaces exported by the firmware (instead of just the main firmware
     version) when evaluating firmware compatibility.  Document the new
     "hw.cxgbe.fw_install" knob being introduced here.
    
    This should fix kern/173584 too.  Setting hw.cxgbe.fw_install=2 will
    mostly do what was requested in the PR but it's a bit more intelligent
    in that it won't reinstall the same firmware repeatedly if the knob is
    left set.
    
    PR:		kern/173584
    MFC after:	5 days
    ---
     share/man/man4/cxgbe.4        |   9 ++
     sys/dev/cxgbe/common/common.h |   5 +
     sys/dev/cxgbe/t4_main.c       | 186 +++++++++++++++++++++-------------
     3 files changed, 132 insertions(+), 68 deletions(-)
    
    diff --git a/share/man/man4/cxgbe.4 b/share/man/man4/cxgbe.4
    index 882bcf7072b..25cc148ca92 100644
    --- a/share/man/man4/cxgbe.4
    +++ b/share/man/man4/cxgbe.4
    @@ -178,6 +178,15 @@ Bit 0 represents INTx (line interrupts), bit 1 MSI, bit 2 MSI-X.
     The default is 7 (all allowed).
     The driver will select the best possible type out of the allowed types by
     itself.
    +.It Va hw.cxgbe.fw_install
    +0 prohibits the driver from installing a firmware on the card.
    +1 allows the driver to install a new firmware if internal driver
    +heuristics indicate that the new firmware is preferable to the one
    +already on the card.
    +2 instructs the driver to always install the new firmware on the card as
    +long as it is compatible with the driver and is a different version than
    +the one already on the card.
    +The default is 1.
     .It Va hw.cxgbe.config_file
     Select a pre-packaged device configuration file.
     A configuration file contains a recipe for partitioning and configuring the
    diff --git a/sys/dev/cxgbe/common/common.h b/sys/dev/cxgbe/common/common.h
    index abc94224384..ccd1195aa05 100644
    --- a/sys/dev/cxgbe/common/common.h
    +++ b/sys/dev/cxgbe/common/common.h
    @@ -68,6 +68,11 @@ enum {
     #define FW_VERSION_MICRO 4
     #define FW_VERSION_BUILD 0
     
    +#define FW_VERSION (V_FW_HDR_FW_VER_MAJOR(FW_VERSION_MAJOR) | \
    +    V_FW_HDR_FW_VER_MINOR(FW_VERSION_MINOR) | \
    +    V_FW_HDR_FW_VER_MICRO(FW_VERSION_MICRO) | \
    +    V_FW_HDR_FW_VER_BUILD(FW_VERSION_BUILD))
    +
     struct port_stats {
     	u64 tx_octets;            /* total # of octets in good frames */
     	u64 tx_frames;            /* all good frames */
    diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c
    index da3accd3d46..fcea547f63e 100644
    --- a/sys/dev/cxgbe/t4_main.c
    +++ b/sys/dev/cxgbe/t4_main.c
    @@ -212,6 +212,13 @@ TUNABLE_INT("hw.cxgbe.interrupt_types", &t4_intr_types);
     static char t4_cfg_file[32] = "default";
     TUNABLE_STR("hw.cxgbe.config_file", t4_cfg_file, sizeof(t4_cfg_file));
     
    +/*
    + * Firmware auto-install by driver during attach (0, 1, 2 = prohibited, allowed,
    + * encouraged respectively).
    + */
    +static unsigned int t4_fw_install = 1;
    +TUNABLE_INT("hw.cxgbe.fw_install", &t4_fw_install);
    +
     /*
      * ASIC features that will be used.  Disable the ones you don't want so that the
      * chip resources aren't wasted on features that will not be used.
    @@ -1502,6 +1509,33 @@ allocate:
     	return (ENXIO);
     }
     
    +/*
    + * Is the given firmware compatible with the one the driver was compiled with?
    + */
    +static int
    +fw_compatible(const struct fw_hdr *hdr)
    +{
    +
    +	if (hdr->fw_ver == htonl(FW_VERSION))
    +		return (1);
    +
    +	/*
    +	 * XXX: Is this too conservative?  Perhaps I should limit this to the
    +	 * features that are supported in the driver.
    +	 */
    +	if (hdr->intfver_nic == FW_HDR_INTFVER_NIC &&
    +	    hdr->intfver_vnic == FW_HDR_INTFVER_VNIC &&
    +	    hdr->intfver_ofld == FW_HDR_INTFVER_OFLD &&
    +	    hdr->intfver_ri == FW_HDR_INTFVER_RI &&
    +	    hdr->intfver_iscsipdu == FW_HDR_INTFVER_ISCSIPDU &&
    +	    hdr->intfver_iscsi == FW_HDR_INTFVER_ISCSI &&
    +	    hdr->intfver_fcoepdu == FW_HDR_INTFVER_FCOEPDU &&
    +	    hdr->intfver_fcoe == FW_HDR_INTFVER_FCOEPDU)
    +		return (1);
    +
    +	return (0);
    +}
    +
     /*
      * Install a compatible firmware (if required), establish contact with it (by
      * saying hello), and reset the device.  If we end up as the master driver,
    @@ -1512,83 +1546,98 @@ static int
     prep_firmware(struct adapter *sc)
     {
     	const struct firmware *fw = NULL, *cfg = NULL, *default_cfg;
    -	int rc;
    +	int rc, card_fw_usable, kld_fw_usable;
     	enum dev_state state;
    +	struct fw_hdr *card_fw;
    +	const struct fw_hdr *kld_fw;
     
     	default_cfg = firmware_get(T4_CFGNAME);
     
    -	/* Check firmware version and install a different one if necessary */
    -	rc = t4_check_fw_version(sc);
    +	/* Read the header of the firmware on the card */
    +	card_fw = malloc(sizeof(*card_fw), M_CXGBE, M_ZERO | M_WAITOK);
    +	rc = -t4_read_flash(sc, FLASH_FW_START,
    +	    sizeof (*card_fw) / sizeof (uint32_t), (uint32_t *)card_fw, 1);
    +	if (rc == 0)
    +		card_fw_usable = fw_compatible((const void*)card_fw);
    +	else {
    +		device_printf(sc->dev,
    +		    "Unable to read card's firmware header: %d\n", rc);
    +		card_fw_usable = 0;
    +	}
    +
    +	/* This is the firmware in the KLD */
    +	fw = firmware_get(T4_FWNAME);
    +	if (fw != NULL) {
    +		kld_fw = (const void *)fw->data;
    +		kld_fw_usable = fw_compatible(kld_fw);
    +	} else {
    +		kld_fw = NULL;
    +		kld_fw_usable = 0;
    +	}
    +
    +	/*
    +	 * Short circuit for the common case: the firmware on the card is an
    +	 * exact match and the KLD is an exact match too, or it's
    +	 * absent/incompatible, or we're prohibited from using it.  Note that
    +	 * t4_fw_install = 2 is ignored here -- use cxgbetool loadfw if you want
    +	 * to reinstall the same firmware as the one on the card.
    +	 */
    +	if (card_fw_usable && card_fw->fw_ver == htonl(FW_VERSION) &&
    +	    (!kld_fw_usable || kld_fw->fw_ver == htonl(FW_VERSION) ||
    +	    t4_fw_install == 0))
    +		goto hello;
    +
    +	if (kld_fw_usable && (!card_fw_usable ||
    +	    ntohl(kld_fw->fw_ver) > ntohl(card_fw->fw_ver) ||
    +	    (t4_fw_install == 2 && kld_fw->fw_ver != card_fw->fw_ver))) {
    +		uint32_t v = ntohl(kld_fw->fw_ver);
    +
    +		device_printf(sc->dev,
    +		    "installing firmware %d.%d.%d.%d on card.\n",
    +		    G_FW_HDR_FW_VER_MAJOR(v), G_FW_HDR_FW_VER_MINOR(v),
    +		    G_FW_HDR_FW_VER_MICRO(v), G_FW_HDR_FW_VER_BUILD(v));
    +
    +		rc = -t4_load_fw(sc, fw->data, fw->datasize);
    +		if (rc != 0) {
    +			device_printf(sc->dev,
    +			    "failed to install firmware: %d\n", rc);
    +			goto done;
    +		}
    +
    +		/* Installed successfully, update the cached header too. */
    +		memcpy(card_fw, kld_fw, sizeof(*card_fw));
    +		card_fw_usable = 1;
    +	}
    +
    +	if (!card_fw_usable) {
    +		uint32_t c, k;
    +
    +		c = ntohl(card_fw->fw_ver);
    +		k = kld_fw ? ntohl(kld_fw->fw_ver) : 0;
    +
    +		device_printf(sc->dev, "Cannot find a usable firmware: "
    +		    "fw_install %d, driver compiled with %d.%d.%d.%d, "
    +		    "card has %d.%d.%d.%d, KLD has %d.%d.%d.%d\n",
    +		    t4_fw_install,
    +		    G_FW_HDR_FW_VER_MAJOR(FW_VERSION),
    +		    G_FW_HDR_FW_VER_MINOR(FW_VERSION),
    +		    G_FW_HDR_FW_VER_MICRO(FW_VERSION),
    +		    G_FW_HDR_FW_VER_BUILD(FW_VERSION),
    +		    G_FW_HDR_FW_VER_MAJOR(c), G_FW_HDR_FW_VER_MINOR(c),
    +		    G_FW_HDR_FW_VER_MICRO(c), G_FW_HDR_FW_VER_BUILD(c),
    +		    G_FW_HDR_FW_VER_MAJOR(k), G_FW_HDR_FW_VER_MINOR(k),
    +		    G_FW_HDR_FW_VER_MICRO(k), G_FW_HDR_FW_VER_BUILD(k));
    +		goto done;
    +	}
    +
    +hello:
    +	/* We're using whatever's on the card and it's known to be good. */
    +	sc->params.fw_vers = ntohl(card_fw->fw_ver);
     	snprintf(sc->fw_version, sizeof(sc->fw_version), "%u.%u.%u.%u",
     	    G_FW_HDR_FW_VER_MAJOR(sc->params.fw_vers),
     	    G_FW_HDR_FW_VER_MINOR(sc->params.fw_vers),
     	    G_FW_HDR_FW_VER_MICRO(sc->params.fw_vers),
     	    G_FW_HDR_FW_VER_BUILD(sc->params.fw_vers));
    -	if (rc != 0) {
    -		uint32_t v = 0;
    -
    -		fw = firmware_get(T4_FWNAME);
    -		if (fw != NULL) {
    -			const struct fw_hdr *hdr = (const void *)fw->data;
    -
    -			v = ntohl(hdr->fw_ver);
    -
    -			/*
    -			 * The firmware module will not be used if it isn't the
    -			 * same major version as what the driver was compiled
    -			 * with.
    -			 */
    -			if (G_FW_HDR_FW_VER_MAJOR(v) != FW_VERSION_MAJOR) {
    -				device_printf(sc->dev,
    -				    "Found firmware image but version %d "
    -				    "can not be used with this driver (%d)\n",
    -				    G_FW_HDR_FW_VER_MAJOR(v), FW_VERSION_MAJOR);
    -
    -				firmware_put(fw, FIRMWARE_UNLOAD);
    -				fw = NULL;
    -			}
    -		}
    -
    -		if (fw == NULL && rc < 0) {
    -			device_printf(sc->dev, "No usable firmware. "
    -			    "card has %d.%d.%d, driver compiled with %d.%d.%d",
    -			    G_FW_HDR_FW_VER_MAJOR(sc->params.fw_vers),
    -			    G_FW_HDR_FW_VER_MINOR(sc->params.fw_vers),
    -			    G_FW_HDR_FW_VER_MICRO(sc->params.fw_vers),
    -			    FW_VERSION_MAJOR, FW_VERSION_MINOR,
    -			    FW_VERSION_MICRO);
    -			rc = EAGAIN;
    -			goto done;
    -		}
    -
    -		/*
    -		 * Always upgrade, even for minor/micro/build mismatches.
    -		 * Downgrade only for a major version mismatch or if
    -		 * force_firmware_install was specified.
    -		 */
    -		if (fw != NULL && (rc < 0 || v > sc->params.fw_vers)) {
    -			device_printf(sc->dev,
    -			    "installing firmware %d.%d.%d.%d on card.\n",
    -			    G_FW_HDR_FW_VER_MAJOR(v), G_FW_HDR_FW_VER_MINOR(v),
    -			    G_FW_HDR_FW_VER_MICRO(v), G_FW_HDR_FW_VER_BUILD(v));
    -
    -			rc = -t4_load_fw(sc, fw->data, fw->datasize);
    -			if (rc != 0) {
    -				device_printf(sc->dev,
    -				    "failed to install firmware: %d\n", rc);
    -				goto done;
    -			} else {
    -				/* refresh */
    -				(void) t4_check_fw_version(sc);
    -				snprintf(sc->fw_version,
    -				    sizeof(sc->fw_version), "%u.%u.%u.%u",
    -				    G_FW_HDR_FW_VER_MAJOR(sc->params.fw_vers),
    -				    G_FW_HDR_FW_VER_MINOR(sc->params.fw_vers),
    -				    G_FW_HDR_FW_VER_MICRO(sc->params.fw_vers),
    -				    G_FW_HDR_FW_VER_BUILD(sc->params.fw_vers));
    -			}
    -		}
    -	}
     
     	/* Contact firmware.  */
     	rc = t4_fw_hello(sc, sc->mbox, sc->mbox, MASTER_MAY, &state);
    @@ -1639,6 +1688,7 @@ prep_firmware(struct adapter *sc)
     	sc->flags |= FW_OK;
     
     done:
    +	free(card_fw, M_CXGBE);
     	if (fw != NULL)
     		firmware_put(fw, FIRMWARE_UNLOAD);
     	if (cfg != NULL)
    
    From e4428d63a81181ebb454b3c6525cc0b1bb12a9f8 Mon Sep 17 00:00:00 2001
    From: Martin Matuska 
    Date: Tue, 26 Feb 2013 20:41:27 +0000
    Subject: [PATCH 0434/1476] Be more verbose on ZFS deadman I/O panic Patch
     suggested upstream.
    
    Suggested by:	Olivier Cinquin
    MFC after:	12 days
    ---
     sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c | 6 +++++-
     1 file changed, 5 insertions(+), 1 deletion(-)
    
    diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c
    index 17cb6c1e78e..59b461bf56b 100644
    --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c
    +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c
    @@ -23,6 +23,7 @@
      * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
      * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
      * Copyright (c) 2012 by Delphix. All rights reserved.
    + * Copyright 2013 Martin Matuska . All rights reserved.
      */
     
     #include 
    @@ -3205,7 +3206,10 @@ vdev_deadman(vdev_t *vd)
     				    fio->io_timestamp, delta,
     				    vq->vq_io_complete_ts);
     				fm_panic("I/O to pool '%s' appears to be "
    -				    "hung.", spa_name(spa));
    +				    "hung on vdev guid %llu at '%s'.",
    +				    spa_name(spa),
    +				    (long long unsigned int) vd->vdev_guid,
    +				    vd->vdev_path);
     			}
     		}
     		mutex_exit(&vq->vq_lock);
    
    From cc66a2c789def28cfba2488eb4691654fc6222d9 Mon Sep 17 00:00:00 2001
    From: Navdeep Parhar 
    Date: Tue, 26 Feb 2013 21:25:17 +0000
    Subject: [PATCH 0435/1476] cxgbe(4): Report unusual out of band errors from
     the firmware.
    
    Obtained from:	Chelsio
    MFC after:	5 days
    ---
     sys/dev/cxgbe/common/t4_hw.c | 47 ++++++++++++++++++++++++++++++++++--
     1 file changed, 45 insertions(+), 2 deletions(-)
    
    diff --git a/sys/dev/cxgbe/common/t4_hw.c b/sys/dev/cxgbe/common/t4_hw.c
    index 3aea091347e..e00e779c421 100644
    --- a/sys/dev/cxgbe/common/t4_hw.c
    +++ b/sys/dev/cxgbe/common/t4_hw.c
    @@ -153,6 +153,36 @@ u32 t4_hw_pci_read_cfg4(adapter_t *adap, int reg)
     	return t4_read_reg(adap, A_PCIE_CFG_SPACE_DATA);
     }
     
    +/*
    + *	t4_report_fw_error - report firmware error
    + *	@adap: the adapter
    + *
    + *	The adapter firmware can indicate error conditions to the host.
    + *	This routine prints out the reason for the firmware error (as
    + *	reported by the firmware).
    + */
    +static void t4_report_fw_error(struct adapter *adap)
    +{
    +	static const char *reason[] = {
    +		"Crash",			/* PCIE_FW_EVAL_CRASH */
    +		"During Device Preparation",	/* PCIE_FW_EVAL_PREP */
    +		"During Device Configuration",	/* PCIE_FW_EVAL_CONF */
    +		"During Device Initialization",	/* PCIE_FW_EVAL_INIT */
    +		"Unexpected Event",		/* PCIE_FW_EVAL_UNEXPECTEDEVENT */
    +		"Insufficient Airflow",		/* PCIE_FW_EVAL_OVERHEAT */
    +		"Device Shutdown",		/* PCIE_FW_EVAL_DEVICESHUTDOWN */
    +		"Reserved",			/* reserved */
    +	};
    +	u32 pcie_fw;
    +
    +	pcie_fw = t4_read_reg(adap, A_PCIE_FW);
    +	if (!(pcie_fw & F_PCIE_FW_ERR))
    +		CH_ERR(adap, "Firmware error report called with no error\n");
    +	else
    +		CH_ERR(adap, "Firmware reports adapter error: %s\n",
    +		       reason[G_PCIE_FW_EVAL(pcie_fw)]);
    +}
    +
     /*
      * Get the reply to a mailbox command and store it in @rpl in big-endian order.
      */
    @@ -267,8 +297,15 @@ int t4_wr_mbox_meat(struct adapter *adap, int mbox, const void *cmd, int size,
     		}
     	}
     
    +	/*
    +	 * We timed out waiting for a reply to our mailbox command.  Report
    +	 * the error and also check to see if the firmware reported any
    +	 * errors ...
    +	 */
     	CH_ERR(adap, "command %#x in mailbox %d timed out\n",
     	       *(const u8 *)cmd, mbox);
    +	if (t4_read_reg(adap, A_PCIE_FW) & F_PCIE_FW_ERR)
    +		t4_report_fw_error(adap);
     	return -ETIMEDOUT;
     }
     
    @@ -2033,9 +2070,11 @@ static void cim_intr_handler(struct adapter *adapter)
     		{ F_TIMEOUTMAINT , "CIM PIF MA timeout", -1, 1 },
     		{ 0 }
     	};
    -
     	int fat;
     
    +	if (t4_read_reg(adapter, A_PCIE_FW) & F_PCIE_FW_ERR)
    +		t4_report_fw_error(adapter);
    +
     	fat = t4_handle_intr_status(adapter, A_CIM_HOST_INT_CAUSE,
     				    cim_intr_info) +
     	      t4_handle_intr_status(adapter, A_CIM_HOST_UPACC_INT_CAUSE,
    @@ -4103,12 +4142,16 @@ retry:
     	/*
     	 * Issue the HELLO command to the firmware.  If it's not successful
     	 * but indicates that we got a "busy" or "timeout" condition, retry
    -	 * the HELLO until we exhaust our retry limit.
    +	 * the HELLO until we exhaust our retry limit.  If we do exceed our
    +	 * retry limit, check to see if the firmware left us any error
    +	 * information and report that if so ...
     	 */
     	ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
     	if (ret != FW_SUCCESS) {
     		if ((ret == -EBUSY || ret == -ETIMEDOUT) && retries-- > 0)
     			goto retry;
    +		if (t4_read_reg(adap, A_PCIE_FW) & F_PCIE_FW_ERR)
    +			t4_report_fw_error(adap);
     		return ret;
     	}
     
    
    From 3e0e2e20266426ea16064e6686be26af52c1db4d Mon Sep 17 00:00:00 2001
    From: Matt Jacob 
    Date: Tue, 26 Feb 2013 21:37:12 +0000
    Subject: [PATCH 0436/1476] Remove redundant xpt_alloc_ccb in isp_target_thread
     that was causing leakage.
    
    Pointed out by:	Sascha Wildner of DragonFly BSD
    MFC after:	1 week
    ---
     sys/dev/isp/isp_freebsd.c | 2 --
     1 file changed, 2 deletions(-)
    
    diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c
    index 328244a51c3..8b1ca9c4683 100644
    --- a/sys/dev/isp/isp_freebsd.c
    +++ b/sys/dev/isp/isp_freebsd.c
    @@ -4140,8 +4140,6 @@ isp_target_thread(ispsoftc_t *isp, int chan)
     		return;
     	}
     
    -	ccb = xpt_alloc_ccb();
    -
     	ISP_LOCK(isp);
     	status = cam_periph_alloc(isptargctor, NULL, isptargdtor, isptargstart, "isptarg", CAM_PERIPH_BIO, wpath, NULL, 0, softc);
     	if (status != CAM_REQ_CMP) {
    
    From 0e52eb5ac55aab07eae9bc091561a528e28bb5c3 Mon Sep 17 00:00:00 2001
    From: Nick Hibma 
    Date: Tue, 26 Feb 2013 23:18:35 +0000
    Subject: [PATCH 0437/1476] Clarify that overriding the -h/-D flags through
     flags in device.hints only works for sio(4) but not for uart(4) which no
     longer has this flag.
    
    ---
     sbin/reboot/boot_i386.8 | 7 +++----
     1 file changed, 3 insertions(+), 4 deletions(-)
    
    diff --git a/sbin/reboot/boot_i386.8 b/sbin/reboot/boot_i386.8
    index 3b58cc5dfc6..33ad8febe4a 100644
    --- a/sbin/reboot/boot_i386.8
    +++ b/sbin/reboot/boot_i386.8
    @@ -220,15 +220,14 @@ you can use the
     option to force the kernel to use the serial port as its
     console device.
     The serial port driver
    -.Xr uart 4
    +.Xr sio 4
    +(but not
    +.Xr uart 4 )
     has a flag (0x20) to override this option.
     If that flag is set, the serial port will always be used as the console,
     regardless of the
     .Fl h
     option described here.
    -See the man page for
    -.Xr uart 4
    -for more details.
     .It Fl m
     mute the console to suppress all console input and output during the
     boot.
    
    From a4915c21d9d06823579d21fdf68c041c49eb67ac Mon Sep 17 00:00:00 2001
    From: Attilio Rao 
    Date: Tue, 26 Feb 2013 23:35:27 +0000
    Subject: [PATCH 0438/1476] Merge from vmc-playground branch: Replace the
     sub-optimal uma_zone_set_obj() primitive with more modern
     uma_zone_reserve_kva().  The new primitive reserves before hand the necessary
     KVA space to cater the zone allocations and allocates pages with ALLOC_NOOBJ.
      More specifically: - uma_zone_reserve_kva() does not need an object to cater
     the backend   allocator. - uma_zone_reserve_kva() can cater M_WAITOK
     requests, in order to   serve zones which need to do uma_prealloc() too. -
     When possible, uma_zone_reserve_kva() uses directly the direct-mapping   by
     uma_small_alloc() rather than relying on the KVA / offset   combination.
    
    The removal of the object attribute allows 2 further changes:
    1) _vm_object_allocate() becomes static within vm_object.c
    2) VM_OBJECT_LOCK_INIT() is removed.  This function is replaced by
       direct calls to mtx_init() as there is no need to export it anymore
       and the calls aren't either homogeneous anymore: there are now small
       differences between arguments passed to mtx_init().
    
    Sponsored by:	EMC / Isilon storage division
    Reviewed by:	alc (which also offered almost all the comments)
    Tested by:	pho, jhb, davide
    ---
     sys/arm/arm/pmap-v6.c    |   3 +-
     sys/arm/arm/pmap.c       |   3 +-
     sys/powerpc/booke/pmap.c |   3 +-
     sys/vm/swap_pager.c      |   3 +-
     sys/vm/uma.h             |  19 ++++---
     sys/vm/uma_core.c        | 106 +++++++++++++++++++++------------------
     sys/vm/uma_int.h         |   4 +-
     sys/vm/vm_map.c          |   3 +-
     sys/vm/vm_object.c       |   8 +--
     sys/vm/vm_object.h       |   4 --
     10 files changed, 77 insertions(+), 79 deletions(-)
    
    diff --git a/sys/arm/arm/pmap-v6.c b/sys/arm/arm/pmap-v6.c
    index 72ef310d918..a4f3db1ae74 100644
    --- a/sys/arm/arm/pmap-v6.c
    +++ b/sys/arm/arm/pmap-v6.c
    @@ -392,7 +392,6 @@ static uma_zone_t l2table_zone;
     static vm_offset_t pmap_kernel_l2dtable_kva;
     static vm_offset_t pmap_kernel_l2ptp_kva;
     static vm_paddr_t pmap_kernel_l2ptp_phys;
    -static struct vm_object pvzone_obj;
     static int pv_entry_count=0, pv_entry_max=0, pv_entry_high_water=0;
     static struct rwlock pvh_global_lock;
     
    @@ -1164,7 +1163,7 @@ pmap_init(void)
     	    NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_VM | UMA_ZONE_NOFREE);
     	TUNABLE_INT_FETCH("vm.pmap.shpgperproc", &shpgperproc);
     	pv_entry_max = shpgperproc * maxproc + cnt.v_page_count;
    -	uma_zone_set_obj(pvzone, &pvzone_obj, pv_entry_max);
    +	uma_zone_reserve_kva(pvzone, pv_entry_max);
     	pv_entry_high_water = 9 * (pv_entry_max / 10);
     
     	/*
    diff --git a/sys/arm/arm/pmap.c b/sys/arm/arm/pmap.c
    index 28b4912d6e0..313e6fa4290 100644
    --- a/sys/arm/arm/pmap.c
    +++ b/sys/arm/arm/pmap.c
    @@ -397,7 +397,6 @@ static uma_zone_t l2table_zone;
     static vm_offset_t pmap_kernel_l2dtable_kva;
     static vm_offset_t pmap_kernel_l2ptp_kva;
     static vm_paddr_t pmap_kernel_l2ptp_phys;
    -static struct vm_object pvzone_obj;
     static int pv_entry_count=0, pv_entry_max=0, pv_entry_high_water=0;
     static struct rwlock pvh_global_lock;
     
    @@ -1828,7 +1827,7 @@ pmap_init(void)
     	    NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_VM | UMA_ZONE_NOFREE);
     	TUNABLE_INT_FETCH("vm.pmap.shpgperproc", &shpgperproc);
     	pv_entry_max = shpgperproc * maxproc + cnt.v_page_count;
    -	uma_zone_set_obj(pvzone, &pvzone_obj, pv_entry_max);
    +	uma_zone_reserve_kva(pvzone, pv_entry_max);
     	pv_entry_high_water = 9 * (pv_entry_max / 10);
     
     	/*
    diff --git a/sys/powerpc/booke/pmap.c b/sys/powerpc/booke/pmap.c
    index f6e5f9c2d53..5172009360f 100644
    --- a/sys/powerpc/booke/pmap.c
    +++ b/sys/powerpc/booke/pmap.c
    @@ -217,7 +217,6 @@ static struct rwlock_padalign pvh_global_lock;
     
     /* Data for the pv entry allocation mechanism */
     static uma_zone_t pvzone;
    -static struct vm_object pvzone_obj;
     static int pv_entry_count = 0, pv_entry_max = 0, pv_entry_high_water = 0;
     
     #define PV_ENTRY_ZONE_MIN	2048	/* min pv entries in uma zone */
    @@ -1343,7 +1342,7 @@ mmu_booke_init(mmu_t mmu)
     	TUNABLE_INT_FETCH("vm.pmap.pv_entries", &pv_entry_max);
     	pv_entry_high_water = 9 * (pv_entry_max / 10);
     
    -	uma_zone_set_obj(pvzone, &pvzone_obj, pv_entry_max);
    +	uma_zone_reserve_kva(pvzone, pv_entry_max);
     
     	/* Pre-fill pvzone with initial number of pv entries. */
     	uma_prealloc(pvzone, PV_ENTRY_ZONE_MIN);
    diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c
    index 2659b67cbd1..712fd832034 100644
    --- a/sys/vm/swap_pager.c
    +++ b/sys/vm/swap_pager.c
    @@ -343,7 +343,6 @@ SYSCTL_INT(_vm, OID_AUTO, swap_async_max,
     static struct mtx sw_alloc_mtx;	/* protect list manipulation */
     static struct pagerlst	swap_pager_object_list[NOBJLISTS];
     static uma_zone_t	swap_zone;
    -static struct vm_object	swap_zone_obj;
     
     /*
      * pagerops for OBJT_SWAP - "swap pager".  Some ops are also global procedure
    @@ -554,7 +553,7 @@ swap_pager_swap_init(void)
     	if (swap_zone == NULL)
     		panic("failed to create swap_zone.");
     	do {
    -		if (uma_zone_set_obj(swap_zone, &swap_zone_obj, n))
    +		if (uma_zone_reserve_kva(swap_zone, n))
     			break;
     		/*
     		 * if the allocation failed, try a zone two thirds the
    diff --git a/sys/vm/uma.h b/sys/vm/uma.h
    index 3abfd3e2157..2569b88f9a3 100644
    --- a/sys/vm/uma.h
    +++ b/sys/vm/uma.h
    @@ -432,24 +432,23 @@ void uma_reclaim(void);
     void uma_set_align(int align);
     
     /*
    - * Switches the backing object of a zone
    + * Reserves the maximum KVA space required by the zone and configures the zone
    + * to use a VM_ALLOC_NOOBJ-based backend allocator.
      *
      * Arguments:
      *	zone  The zone to update.
    - *	obj   The VM object to use for future allocations.
    - *	size  The size of the object to allocate.
    + *	nitems  The upper limit on the number of items that can be allocated.
      *
      * Returns:
    - *	0  if kva space can not be allocated
    + *	0  if KVA space can not be allocated
      *	1  if successful
      *
      * Discussion:
    - *	A NULL object can be used and uma will allocate one for you.  Setting
    - *	the size will limit the amount of memory allocated to this zone.
    - *
    + *	When the machine supports a direct map and the zone's items are smaller
    + *	than a page, the zone will use the direct map instead of allocating KVA
    + *	space.
      */
    -struct vm_object;
    -int uma_zone_set_obj(uma_zone_t zone, struct vm_object *obj, int size);
    +int uma_zone_reserve_kva(uma_zone_t zone, int nitems);
     
     /*
      * Sets a high limit on the number of items allowed in a zone
    @@ -521,7 +520,7 @@ void uma_zone_set_zinit(uma_zone_t zone, uma_init zinit);
     void uma_zone_set_zfini(uma_zone_t zone, uma_fini zfini);
     
     /*
    - * Replaces the standard page_alloc or obj_alloc functions for this zone
    + * Replaces the standard backend allocator for this zone.
      *
      * Arguments:
      *	zone   The zone whose backend allocator is being changed.
    diff --git a/sys/vm/uma_core.c b/sys/vm/uma_core.c
    index 2d5b555c60b..d2980644ff3 100644
    --- a/sys/vm/uma_core.c
    +++ b/sys/vm/uma_core.c
    @@ -79,6 +79,7 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    +#include 
     #include 
     #include 
     #include 
    @@ -213,7 +214,7 @@ enum zfreeskip { SKIP_NONE, SKIP_DTOR, SKIP_FINI };
     
     /* Prototypes.. */
     
    -static void *obj_alloc(uma_zone_t, int, u_int8_t *, int);
    +static void *noobj_alloc(uma_zone_t, int, u_int8_t *, int);
     static void *page_alloc(uma_zone_t, int, u_int8_t *, int);
     static void *startup_alloc(uma_zone_t, int, u_int8_t *, int);
     static void page_free(void *, int, u_int8_t);
    @@ -1030,50 +1031,53 @@ page_alloc(uma_zone_t zone, int bytes, u_int8_t *pflag, int wait)
      *	NULL if M_NOWAIT is set.
      */
     static void *
    -obj_alloc(uma_zone_t zone, int bytes, u_int8_t *flags, int wait)
    +noobj_alloc(uma_zone_t zone, int bytes, u_int8_t *flags, int wait)
     {
    -	vm_object_t object;
    +	TAILQ_HEAD(, vm_page) alloctail;
    +	u_long npages;
     	vm_offset_t retkva, zkva;
    -	vm_page_t p;
    -	int pages, startpages;
    +	vm_page_t p, p_next;
     	uma_keg_t keg;
     
    +	TAILQ_INIT(&alloctail);
     	keg = zone_first_keg(zone);
    -	object = keg->uk_obj;
    -	retkva = 0;
     
    -	/*
    -	 * This looks a little weird since we're getting one page at a time.
    -	 */
    -	VM_OBJECT_LOCK(object);
    -	p = TAILQ_LAST(&object->memq, pglist);
    -	pages = p != NULL ? p->pindex + 1 : 0;
    -	startpages = pages;
    -	zkva = keg->uk_kva + pages * PAGE_SIZE;
    -	for (; bytes > 0; bytes -= PAGE_SIZE) {
    -		p = vm_page_alloc(object, pages,
    -		    VM_ALLOC_INTERRUPT | VM_ALLOC_WIRED);
    -		if (p == NULL) {
    -			if (pages != startpages)
    -				pmap_qremove(retkva, pages - startpages);
    -			while (pages != startpages) {
    -				pages--;
    -				p = TAILQ_LAST(&object->memq, pglist);
    -				vm_page_unwire(p, 0);
    -				vm_page_free(p);
    -			}
    -			retkva = 0;
    -			goto done;
    +	npages = howmany(bytes, PAGE_SIZE);
    +	while (npages > 0) {
    +		p = vm_page_alloc(NULL, 0, VM_ALLOC_INTERRUPT |
    +		    VM_ALLOC_WIRED | VM_ALLOC_NOOBJ);
    +		if (p != NULL) {
    +			/*
    +			 * Since the page does not belong to an object, its
    +			 * listq is unused.
    +			 */
    +			TAILQ_INSERT_TAIL(&alloctail, p, listq);
    +			npages--;
    +			continue;
     		}
    -		pmap_qenter(zkva, &p, 1);
    -		if (retkva == 0)
    -			retkva = zkva;
    -		zkva += PAGE_SIZE;
    -		pages += 1;
    +		if (wait & M_WAITOK) {
    +			VM_WAIT;
    +			continue;
    +		}
    +
    +		/*
    +		 * Page allocation failed, free intermediate pages and
    +		 * exit.
    +		 */
    +		TAILQ_FOREACH_SAFE(p, &alloctail, listq, p_next) {
    +			vm_page_unwire(p, 0);
    +			vm_page_free(p); 
    +		}
    +		return (NULL);
     	}
    -done:
    -	VM_OBJECT_UNLOCK(object);
     	*flags = UMA_SLAB_PRIV;
    +	zkva = keg->uk_kva +
    +	    atomic_fetchadd_long(&keg->uk_offset, round_page(bytes));
    +	retkva = zkva;
    +	TAILQ_FOREACH(p, &alloctail, listq) {
    +		pmap_qenter(zkva, &p, 1);
    +		zkva += PAGE_SIZE;
    +	}
     
     	return ((void *)retkva);
     }
    @@ -3012,7 +3016,7 @@ uma_zone_set_allocf(uma_zone_t zone, uma_alloc allocf)
     
     /* See uma.h */
     int
    -uma_zone_set_obj(uma_zone_t zone, struct vm_object *obj, int count)
    +uma_zone_reserve_kva(uma_zone_t zone, int count)
     {
     	uma_keg_t keg;
     	vm_offset_t kva;
    @@ -3024,21 +3028,25 @@ uma_zone_set_obj(uma_zone_t zone, struct vm_object *obj, int count)
     	if (pages * keg->uk_ipers < count)
     		pages++;
     
    -	kva = kmem_alloc_nofault(kernel_map, pages * UMA_SLAB_SIZE);
    -
    -	if (kva == 0)
    -		return (0);
    -	if (obj == NULL)
    -		obj = vm_object_allocate(OBJT_PHYS, pages);
    -	else {
    -		VM_OBJECT_LOCK_INIT(obj, "uma object");
    -		_vm_object_allocate(OBJT_PHYS, pages, obj);
    -	}
    +#ifdef UMA_MD_SMALL_ALLOC
    +	if (keg->uk_ppera > 1) {
    +#else
    +	if (1) {
    +#endif
    +		kva = kmem_alloc_nofault(kernel_map, pages * UMA_SLAB_SIZE);
    +		if (kva == 0)
    +			return (0);
    +	} else
    +		kva = 0;
     	ZONE_LOCK(zone);
     	keg->uk_kva = kva;
    -	keg->uk_obj = obj;
    +	keg->uk_offset = 0;
     	keg->uk_maxpages = pages;
    -	keg->uk_allocf = obj_alloc;
    +#ifdef UMA_MD_SMALL_ALLOC
    +	keg->uk_allocf = (keg->uk_ppera > 1) ? noobj_alloc : uma_small_alloc;
    +#else
    +	keg->uk_allocf = noobj_alloc;
    +#endif
     	keg->uk_flags |= UMA_ZONE_NOFREE | UMA_ZFLAG_PRIVALLOC;
     	ZONE_UNLOCK(zone);
     	return (1);
    diff --git a/sys/vm/uma_int.h b/sys/vm/uma_int.h
    index aaec92642db..b8c2be0ea25 100644
    --- a/sys/vm/uma_int.h
    +++ b/sys/vm/uma_int.h
    @@ -221,8 +221,8 @@ struct uma_keg {
     	uma_alloc	uk_allocf;	/* Allocation function */
     	uma_free	uk_freef;	/* Free routine */
     
    -	struct vm_object	*uk_obj;	/* Zone specific object */
    -	vm_offset_t	uk_kva;		/* Base kva for zones with objs */
    +	u_long		uk_offset;	/* Next free offset from base KVA */
    +	vm_offset_t	uk_kva;		/* Zone base KVA */
     	uma_zone_t	uk_slabzone;	/* Slab zone backing us, if OFFPAGE */
     
     	u_int16_t	uk_pgoff;	/* Offset to uma_slab struct */
    diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
    index 26de82692a7..35ac4689588 100644
    --- a/sys/vm/vm_map.c
    +++ b/sys/vm/vm_map.c
    @@ -125,7 +125,6 @@ static uma_zone_t mapentzone;
     static uma_zone_t kmapentzone;
     static uma_zone_t mapzone;
     static uma_zone_t vmspace_zone;
    -static struct vm_object kmapentobj;
     static int vmspace_zinit(void *mem, int size, int flags);
     static void vmspace_zfini(void *mem, int size);
     static int vm_map_zinit(void *mem, int ize, int flags);
    @@ -303,7 +302,7 @@ vmspace_alloc(min, max)
     void
     vm_init2(void)
     {
    -	uma_zone_set_obj(kmapentzone, &kmapentobj, lmin(cnt.v_page_count,
    +	uma_zone_reserve_kva(kmapentzone, lmin(cnt.v_page_count,
     	    (VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS) / PAGE_SIZE) / 8 +
     	     maxproc * 2 + maxfiles);
     	vmspace_zone = uma_zcreate("VMSPACE", sizeof(struct vmspace), NULL,
    diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c
    index 810707ee236..28d6d0c9e8c 100644
    --- a/sys/vm/vm_object.c
    +++ b/sys/vm/vm_object.c
    @@ -194,7 +194,7 @@ vm_object_zinit(void *mem, int size, int flags)
     
     	object = (vm_object_t)mem;
     	bzero(&object->mtx, sizeof(object->mtx));
    -	VM_OBJECT_LOCK_INIT(object, "standard object");
    +	mtx_init(&object->mtx, "vm object", NULL, MTX_DEF | MTX_DUPOK);
     
     	/* These are true for any object that has been freed */
     	object->paging_in_progress = 0;
    @@ -203,7 +203,7 @@ vm_object_zinit(void *mem, int size, int flags)
     	return (0);
     }
     
    -void
    +static void
     _vm_object_allocate(objtype_t type, vm_pindex_t size, vm_object_t object)
     {
     
    @@ -266,7 +266,7 @@ vm_object_init(void)
     	TAILQ_INIT(&vm_object_list);
     	mtx_init(&vm_object_list_mtx, "vm object_list", NULL, MTX_DEF);
     	
    -	VM_OBJECT_LOCK_INIT(kernel_object, "kernel object");
    +	mtx_init(&kernel_object->mtx, "vm object", "kernel object", MTX_DEF);
     	_vm_object_allocate(OBJT_PHYS, OFF_TO_IDX(VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS),
     	    kernel_object);
     #if VM_NRESERVLEVEL > 0
    @@ -274,7 +274,7 @@ vm_object_init(void)
     	kernel_object->pg_color = (u_short)atop(VM_MIN_KERNEL_ADDRESS);
     #endif
     
    -	VM_OBJECT_LOCK_INIT(kmem_object, "kmem object");
    +	mtx_init(&kmem_object->mtx, "vm object", "kmem object", MTX_DEF);
     	_vm_object_allocate(OBJT_PHYS, OFF_TO_IDX(VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS),
     	    kmem_object);
     #if VM_NRESERVLEVEL > 0
    diff --git a/sys/vm/vm_object.h b/sys/vm/vm_object.h
    index 0cb63e99c3b..e085929cd41 100644
    --- a/sys/vm/vm_object.h
    +++ b/sys/vm/vm_object.h
    @@ -206,9 +206,6 @@ extern struct vm_object kmem_object_store;
     #define	VM_OBJECT_LOCK(object)		mtx_lock(&(object)->mtx)
     #define	VM_OBJECT_LOCK_ASSERT(object, type) \
     					mtx_assert(&(object)->mtx, (type))
    -#define	VM_OBJECT_LOCK_INIT(object, type) \
    -					mtx_init(&(object)->mtx, "vm object", \
    -					    (type), MTX_DEF | MTX_DUPOK)
     #define	VM_OBJECT_LOCKED(object)	mtx_owned(&(object)->mtx)
     #define	VM_OBJECT_SLEEP(object, wchan, pri, wmesg, timo) \
     					msleep((wchan), &(object)->mtx, (pri), \
    @@ -234,7 +231,6 @@ void vm_object_pip_wakeupn(vm_object_t object, short i);
     void vm_object_pip_wait(vm_object_t object, char *waitid);
     
     vm_object_t vm_object_allocate (objtype_t, vm_pindex_t);
    -void _vm_object_allocate (objtype_t, vm_pindex_t, vm_object_t);
     boolean_t vm_object_coalesce(vm_object_t, vm_ooffset_t, vm_size_t, vm_size_t,
        boolean_t);
     void vm_object_collapse (vm_object_t);
    
    From 6606ba811c9aa06a8283d8e0c57d757d11b8b32b Mon Sep 17 00:00:00 2001
    From: Adrian Chadd 
    Date: Wed, 27 Feb 2013 00:25:44 +0000
    Subject: [PATCH 0439/1476] Add in the STBC TX/RX capability support into the
     HAL and driver.
    
    The HAL already included the STBC fields; it just needed to be exposed
    to the driver and net80211 stack.
    
    This should allow single-stream STBC TX and RX to be negotiated; however
    the driver and rate control code currently don't do anything with it.
    ---
     sys/dev/ath/ath_hal/ah.c |  4 ++++
     sys/dev/ath/ath_hal/ah.h |  3 +++
     sys/dev/ath/if_ath.c     | 22 ++++++++++++++++++++++
     sys/dev/ath/if_athvar.h  |  4 +++-
     4 files changed, 32 insertions(+), 1 deletion(-)
    
    diff --git a/sys/dev/ath/ath_hal/ah.c b/sys/dev/ath/ath_hal/ah.c
    index d1ce7a82b3c..551c225ef88 100644
    --- a/sys/dev/ath/ath_hal/ah.c
    +++ b/sys/dev/ath/ath_hal/ah.c
    @@ -692,6 +692,10 @@ ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
     		return pCap->hal4AddrAggrSupport ? HAL_OK : HAL_ENOTSUPP;
     	case HAL_CAP_EXT_CHAN_DFS:
     		return pCap->halExtChanDfsSupport ? HAL_OK : HAL_ENOTSUPP;
    +	case HAL_CAP_RX_STBC:
    +		return pCap->halRxStbcSupport ? HAL_OK : HAL_ENOTSUPP;
    +	case HAL_CAP_TX_STBC:
    +		return pCap->halTxStbcSupport ? HAL_OK : HAL_ENOTSUPP;
     	case HAL_CAP_COMBINED_RADAR_RSSI:
     		return pCap->halUseCombinedRadarRssi ? HAL_OK : HAL_ENOTSUPP;
     	case HAL_CAP_AUTO_SLEEP:
    diff --git a/sys/dev/ath/ath_hal/ah.h b/sys/dev/ath/ath_hal/ah.h
    index 0e3d5abc8cf..ca2e7ca172a 100644
    --- a/sys/dev/ath/ath_hal/ah.h
    +++ b/sys/dev/ath/ath_hal/ah.h
    @@ -137,6 +137,9 @@ typedef enum {
     	HAL_CAP_RIFS_RX_ENABLED	= 53,
     	HAL_CAP_BB_DFS_HANG	= 54,
     
    +	HAL_CAP_RX_STBC		= 58,
    +	HAL_CAP_TX_STBC		= 59,
    +
     	HAL_CAP_BT_COEX		= 60,	/* hardware is capable of bluetooth coexistence */
     	HAL_CAP_DYNAMIC_SMPS	= 61,	/* Dynamic MIMO Power Save hardware support */
     
    diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c
    index a614d6f0113..fd1a7c34f2b 100644
    --- a/sys/dev/ath/if_ath.c
    +++ b/sys/dev/ath/if_ath.c
    @@ -781,6 +781,28 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
     		ic->ic_txstream = txs;
     		ic->ic_rxstream = rxs;
     
    +		/*
    +		 * Setup TX and RX STBC based on what the HAL allows and
    +		 * the currently configured chainmask set.
    +		 * Ie - don't enable STBC TX if only one chain is enabled.
    +		 * STBC RX is fine on a single RX chain; it just won't
    +		 * provide any real benefit.
    +		 */
    +		if (ath_hal_getcapability(ah, HAL_CAP_RX_STBC, 0,
    +		    NULL) == HAL_OK) {
    +			sc->sc_rx_stbc = 1;
    +			device_printf(sc->sc_dev,
    +			    "[HT] 1 stream STBC receive enabled\n");
    +			ic->ic_htcaps |= IEEE80211_HTCAP_RXSTBC_1STREAM;
    +		}
    +		if (txs > 1 && ath_hal_getcapability(ah, HAL_CAP_TX_STBC, 0,
    +		    NULL) == HAL_OK) {
    +			sc->sc_tx_stbc = 1;
    +			device_printf(sc->sc_dev,
    +			    "[HT] 1 stream STBC transmit enabled\n");
    +			ic->ic_htcaps |= IEEE80211_HTCAP_TXSTBC;
    +		}
    +
     		(void) ath_hal_getcapability(ah, HAL_CAP_RTS_AGGR_LIMIT, 1,
     		    &sc->sc_rts_aggr_limit);
     		if (sc->sc_rts_aggr_limit != (64 * 1024))
    diff --git a/sys/dev/ath/if_athvar.h b/sys/dev/ath/if_athvar.h
    index e8fdeff6748..42442de7a60 100644
    --- a/sys/dev/ath/if_athvar.h
    +++ b/sys/dev/ath/if_athvar.h
    @@ -567,7 +567,9 @@ struct ath_softc {
     	/*
     	 * Second set of flags.
     	 */
    -	u_int32_t		sc_use_ent  : 1;
    +	u_int32_t		sc_use_ent  : 1,
    +				sc_rx_stbc  : 1,
    +				sc_tx_stbc  : 1;
     
     	/*
     	 * Enterprise mode configuration for AR9380 and later chipsets.
    
    From 5df4935e7ae4a2d732cfcab433bfd846fe0971b6 Mon Sep 17 00:00:00 2001
    From: Steven Hartland 
    Date: Wed, 27 Feb 2013 00:35:40 +0000
    Subject: [PATCH 0440/1476] Fixes mfi panic on recused on non-recusive mutex
     MFI I/O lock
    
    Removes a mtx_unlock call for mfi_io_lock which is never aquired
    
    While I'm here fix a braceing style issue.
    
    Reviewed by:	Doug Ambrisko
    Approved by:	pjd (mentor)
    MFC after:	1 month
    ---
     sys/dev/mfi/mfi.c       | 4 +---
     sys/dev/mfi/mfi_tbolt.c | 4 +++-
     2 files changed, 4 insertions(+), 4 deletions(-)
    
    diff --git a/sys/dev/mfi/mfi.c b/sys/dev/mfi/mfi.c
    index ed759fc729b..c74370b3c9b 100644
    --- a/sys/dev/mfi/mfi.c
    +++ b/sys/dev/mfi/mfi.c
    @@ -723,10 +723,8 @@ mfi_attach(struct mfi_softc *sc)
     		    "hook\n");
     		return (EINVAL);
     	}
    -	if ((error = mfi_aen_setup(sc, 0), 0) != 0) {
    -		mtx_unlock(&sc->mfi_io_lock);
    +	if ((error = mfi_aen_setup(sc, 0), 0) != 0)
     		return (error);
    -	}
     
     	/*
     	 * Register a shutdown handler.
    diff --git a/sys/dev/mfi/mfi_tbolt.c b/sys/dev/mfi/mfi_tbolt.c
    index cce63c057ce..af83392bb18 100644
    --- a/sys/dev/mfi/mfi_tbolt.c
    +++ b/sys/dev/mfi/mfi_tbolt.c
    @@ -1194,6 +1194,7 @@ mfi_process_fw_state_chg_isr(void *arg)
     			sc->hw_crit_error= 1;
     			return ;
     		}
    +		mtx_unlock(&sc->mfi_io_lock);
     		if ((error = mfi_tbolt_init_MFI_queue(sc)) != 0)
     				return;
     
    @@ -1225,7 +1226,9 @@ mfi_process_fw_state_chg_isr(void *arg)
     			/*
     			 * Initiate AEN (Asynchronous Event Notification)
     			 */
    +			mtx_unlock(&sc->mfi_io_lock);
     			mfi_aen_setup(sc, sc->last_seq_num);
    +			mtx_lock(&sc->mfi_io_lock);
     			sc->issuepend_done = 1;
     			device_printf(sc->mfi_dev, "second stage of reset "
     			    "complete, FW is ready now.\n");
    @@ -1237,7 +1240,6 @@ mfi_process_fw_state_chg_isr(void *arg)
     		device_printf(sc->mfi_dev, "mfi_process_fw_state_chg_isr "
     		    "called with unhandled value:%d\n", sc->adpreset);
     	}
    -	mtx_unlock(&sc->mfi_io_lock);
     }
     
     /*
    
    From 1a3a560767329f041ac725ab95462c02d7978fb4 Mon Sep 17 00:00:00 2001
    From: Adrian Chadd 
    Date: Wed, 27 Feb 2013 00:49:32 +0000
    Subject: [PATCH 0441/1476] Enable STBC for the given rate series if it's
     negotiated:
    
    * If both ends have negotiated (at least) one stream;
    * Only if it's a single stream rate (MCS0-7);
    * Only if there's more than one TX chain enabled.
    
    Tested:
    
    * AR9280 STA mode -> Atheros AP; tested both MCS2 (STBC) and MCS12 (no STBC.)
      Verified using athalq to inspect the TX descriptors.
    
    TODO:
    
    * Test AR5416 - no STBC should be enabled;
    * Test AR9280 with one TX chain enabled - no STBC should be enabled.
    ---
     sys/dev/ath/if_ath_tx_ht.c | 23 ++++++++++++++++++-----
     1 file changed, 18 insertions(+), 5 deletions(-)
    
    diff --git a/sys/dev/ath/if_ath_tx_ht.c b/sys/dev/ath/if_ath_tx_ht.c
    index c0e72ac84cd..d382f8f620e 100644
    --- a/sys/dev/ath/if_ath_tx_ht.c
    +++ b/sys/dev/ath/if_ath_tx_ht.c
    @@ -536,17 +536,30 @@ ath_rateseries_setup(struct ath_softc *sc, struct ieee80211_node *ni,
     			series[i].RateFlags |= HAL_RATESERIES_HALFGI;
     
     		/*
    -		 * XXX TODO: STBC if it's possible
    +		 * Setup rate and TX power cap for this series.
     		 */
    +		series[i].Rate = rt->info[rc[i].rix].rateCode;
    +		series[i].RateIndex = rc[i].rix;
    +		series[i].tx_power_cap = 0x3f;	/* XXX for now */
    +
    +
    +		/*
    +		 * If we have STBC TX enabled and the receiver
    +		 * can receive (at least) 1 stream STBC, AND it's
    +		 * MCS 0-7, AND we have at least two chains enabled,
    +		 * enable STBC.
    +		 */
    +		if (ic->ic_htcaps & IEEE80211_HTCAP_TXSTBC &&
    +		    ni->ni_htcap & IEEE80211_HTCAP_RXSTBC_1STREAM &&
    +		    (sc->sc_cur_txchainmask > 1) &&
    +		    HT_RC_2_STREAMS(series[i].Rate) == 1) {
    +			series[i].RateFlags |= HAL_RATESERIES_STBC;
    +		}
     
     		/*
     		 * XXX TODO: LDPC if it's possible
     		 */
     
    -		series[i].Rate = rt->info[rc[i].rix].rateCode;
    -		series[i].RateIndex = rc[i].rix;
    -		series[i].tx_power_cap = 0x3f;	/* XXX for now */
    -
     		/*
     		 * PktDuration doesn't include slot, ACK, RTS, etc timing -
     		 * it's just the packet duration
    
    From 08c89430bd9b1871c26eac1a01e87d6b0cb4cbad Mon Sep 17 00:00:00 2001
    From: Steven Hartland 
    Date: Wed, 27 Feb 2013 02:21:10 +0000
    Subject: [PATCH 0442/1476] Fixes queuing issues where mfi_release_command
     blindly sets the cm_flags = 0 without first removing the command from the
     relavent queue.
    
    This was causing panics in the queue functions which check to ensure a command
    is not on another queue.
    
    Fixed some cases where the error from mfi_mapcmd was lost and where the command
    was never released / dequeued in error cases.
    
    Ensure that all failures to mfi_mapcmd are logged.
    
    Fixed possible null pointer exception in mfi_aen_setup if mfi_get_log_state
    failed.
    
    Fixed mfi_parse_entries & mfi_aen_setup not returning possible errors.
    
    Corrected MFI_DUMP_CMDS calls with invalid vars SC vs sc.
    
    Commands which have timed out now set cm_error to ETIMEDOUT and call
    mfi_complete which prevents them getting stuck in the busy queue forever.
    
    Fixed possible use of NULL pointer in mfi_tbolt_get_cmd.
    
    Changed output formats to be more easily recognisable when debugging.
    
    Optimised mfi_cmd_pool_tbolt cleanup.
    
    Made information about driver limiting commands always display as for modern
    cards this can be severe.
    
    Fixed mfi_tbolt_alloc_cmd out of memory case which previously didnt return an
    error.
    
    Added malloc checks for request_desc_pool including free when subsiquent errors
    are detected.
    
    Fixed overflow error in SIMD reply descriptor check.
    
    Fixed tbolt_cmd leak in mfi_build_and_issue_cmd if there's an error during IO
    build.
    
    Elimintated double checks on sc->mfi_aen_cm & sc->mfi_map_sync_cm in
    mfi_shutdown.
    
    Move local hdr calculation after error check in mfi_aen_complete.
    
    Fixed wakeup on NULL in mfi_aen_complete.
    
    Fixed mfi_aen_cm cleanup in mfi_process_fw_state_chg_isr not checking if it was
    NULL.
    
    Changed mfi_alloc_commands to error if bus_dmamap_create fails. Previously we
    would try to continue with the number of allocated commands but lots of places
    in the driver assume sc->mfi_max_fw_cmds is whats available so its unsafe to do
    this without lots of changes.
    
    Removed mfi_total_cmds as its no longer used due the above change.
    
    Corrected mfi_tbolt_alloc_cmd to return ENOMEM where appropriate.
    
    Fixed timeouts actually firing at double what they should.
    
    Setting hw.mfi.max_cmds=-1 now configures to use the controller max.
    
    A few style (9) fixes e.g. braced single line conditions and double blank lines
    
    Cleaned up queuing macros
    
    Removed invalid queuing tests for multiple queues
    
    Trap and deal with errors when doing sends in mfi_data_cb
    
    Refactored frame sending into one method with error checking of the return
    code so we can ensure commands aren't left on the queue after error. This
    ensures that mfi_mapcmd & mfi_data_cb leave the queue in a valid state.
    
    Refactored how commands are cleaned up, mfi_release_command now ensures
    that all queues and command state is maintained in a consistent state.
    
    Prevent NULL pointer use in mfi_tbolt_complete_cmd
    
    Fixed use of NULL sc->mfi_map_sync_cm in wakeup
    
    Added defines to help with output of mfi_cmd and header flags.
    
    Fixed mfi_tbolt_init_MFI_queue invalidating cm_index of the acquired mfi_cmd.
    
    Reset now reinitialises sync map as well as AEN.
    
    Fixed possible use of NULL pointer in mfi_build_and_issue_cmd
    
    Fixed mfi_tbolt_init_MFI_queue call to mfi_process_fw_state_chg_isr causing
    panic on failure.
    
    Ensure that tbolt cards always initialise next_host_reply_index and
    free_host_reply_index (based off mfi_max_fw_cmds) on both startup and
    reset as per the linux driver.
    
    Fixed mfi_tbolt_complete_cmd not acknowledging unknown commands so
    it didn't clear the controller.
    
    Prevent locks from being dropped and re-acquired in the following functions
    which was allowing multiple threads to enter critical methods such as
    mfi_tbolt_complete_cmd & mfi_process_fw_state_chg_isr:-
    * mfi_tbolt_init_MFI_queue
    * mfi_aen_complete / mfi_aen_register
    * mfi_tbolt_sync_map_info
    * mfi_get_log_state
    * mfi_parse_entries
    
    The locking for these functions was promoting to higher level methods. This
    also fixed MFI_LINUX_SET_AEN_2 which was already acquiring the lock, so would
    have paniced for recursive lock.
    
    This also required changing malloc of ld_sync in mfi_tbolt_sync_map_info to
    M_NOWAIT which can hence now fail but this was already expected as its return
    was being tested.
    
    Removed the assignment of cm_index in mfi_tbolt_init_MFI_queue which breaks
    the world if the cmd returned by mfi_dequeue_free isn't the first cmd.
    
    Fixed locking in mfi_data_cb, this is an async callback from bus_dmamap_load
    which could hence be called after the caller has dropped the lock. If we
    don't have the lock we aquire it and ensure we unlock before returning.
    
    Fixed locking mfi_comms_init when mfi_dequeue_free fails.
    
    Fixed mfi_build_and_issue_cmd not returning tbolt cmds aquired to the pool
    on error.
    
    Fixed mfi_abort not dropping the io lock when mfi_dequeue_free fails.
    
    Added hw.mfi.polled_cmd_timeout sysctl that enables tuning of polled
    timeouts. This shouldn't be reduced below 50 seconds as its used for
    firmware patching which can take quite some time.
    
    Added hw.mfi.fw_reset_test sysctl which is avaliable when compiled with
    MFI_DEBUG and allows the testing of controller reset that was provoking a
    large number of the issues encountered here.
    
    Reviewed by:	Doug Ambrisko
    Approved by:	pjd (mentor)
    MFC after:	1 month
    ---
     sys/dev/mfi/mfi.c       | 320 +++++++++++++++++++++------------
     sys/dev/mfi/mfi_cam.c   |   8 +-
     sys/dev/mfi/mfi_debug.c |  22 +--
     sys/dev/mfi/mfi_tbolt.c | 389 +++++++++++++++++++++++-----------------
     sys/dev/mfi/mfireg.h    |  12 +-
     sys/dev/mfi/mfivar.h    |  48 ++---
     6 files changed, 477 insertions(+), 322 deletions(-)
    
    diff --git a/sys/dev/mfi/mfi.c b/sys/dev/mfi/mfi.c
    index c74370b3c9b..e799b9dc967 100644
    --- a/sys/dev/mfi/mfi.c
    +++ b/sys/dev/mfi/mfi.c
    @@ -108,6 +108,7 @@ static void	mfi_bio_complete(struct mfi_command *);
     static struct mfi_command *mfi_build_ldio(struct mfi_softc *,struct bio*);
     static struct mfi_command *mfi_build_syspdio(struct mfi_softc *,struct bio*);
     static int	mfi_send_frame(struct mfi_softc *, struct mfi_command *);
    +static int	mfi_std_send_frame(struct mfi_softc *, struct mfi_command *);
     static int	mfi_abort(struct mfi_softc *, struct mfi_command **);
     static int	mfi_linux_ioctl_int(struct cdev *, u_long, caddr_t, int, struct thread *);
     static void	mfi_timeout(void *);
    @@ -132,24 +133,30 @@ static int mfi_check_for_sscd(struct mfi_softc *sc, struct mfi_command *cm);
     SYSCTL_NODE(_hw, OID_AUTO, mfi, CTLFLAG_RD, 0, "MFI driver parameters");
     static int	mfi_event_locale = MFI_EVT_LOCALE_ALL;
     TUNABLE_INT("hw.mfi.event_locale", &mfi_event_locale);
    -SYSCTL_INT(_hw_mfi, OID_AUTO, event_locale, CTLFLAG_RW, &mfi_event_locale,
    -            0, "event message locale");
    +SYSCTL_INT(_hw_mfi, OID_AUTO, event_locale, CTLFLAG_RWTUN, &mfi_event_locale,
    +           0, "event message locale");
     
     static int	mfi_event_class = MFI_EVT_CLASS_INFO;
     TUNABLE_INT("hw.mfi.event_class", &mfi_event_class);
    -SYSCTL_INT(_hw_mfi, OID_AUTO, event_class, CTLFLAG_RW, &mfi_event_class,
    -          0, "event message class");
    +SYSCTL_INT(_hw_mfi, OID_AUTO, event_class, CTLFLAG_RWTUN, &mfi_event_class,
    +           0, "event message class");
     
     static int	mfi_max_cmds = 128;
     TUNABLE_INT("hw.mfi.max_cmds", &mfi_max_cmds);
    -SYSCTL_INT(_hw_mfi, OID_AUTO, max_cmds, CTLFLAG_RD, &mfi_max_cmds,
    -	   0, "Max commands");
    +SYSCTL_INT(_hw_mfi, OID_AUTO, max_cmds, CTLFLAG_RDTUN, &mfi_max_cmds,
    +	   0, "Max commands limit (-1 = controller limit)");
     
     static int	mfi_detect_jbod_change = 1;
     TUNABLE_INT("hw.mfi.detect_jbod_change", &mfi_detect_jbod_change);
    -SYSCTL_INT(_hw_mfi, OID_AUTO, detect_jbod_change, CTLFLAG_RW,
    +SYSCTL_INT(_hw_mfi, OID_AUTO, detect_jbod_change, CTLFLAG_RWTUN,
     	   &mfi_detect_jbod_change, 0, "Detect a change to a JBOD");
     
    +int		mfi_polled_cmd_timeout = MFI_POLL_TIMEOUT_SECS;
    +TUNABLE_INT("hw.mfi.polled_cmd_timeout", &mfi_polled_cmd_timeout);
    +SYSCTL_INT(_hw_mfi, OID_AUTO, polled_cmd_timeout, CTLFLAG_RWTUN,
    +	   &mfi_polled_cmd_timeout, 0,
    +	   "Polled command timeout - used for firmware flash etc (in seconds)");
    +
     /* Management interface */
     static d_open_t		mfi_open;
     static d_close_t	mfi_close;
    @@ -361,7 +368,7 @@ mfi_attach(struct mfi_softc *sc)
     {
     	uint32_t status;
     	int error, commsz, framessz, sensesz;
    -	int frames, unit, max_fw_sge;
    +	int frames, unit, max_fw_sge, max_fw_cmds;
     	uint32_t tb_mem_size = 0;
     
     	if (sc == NULL)
    @@ -456,7 +463,14 @@ mfi_attach(struct mfi_softc *sc)
     	 * instead of compile time.
     	 */
     	status = sc->mfi_read_fw_status(sc);
    -	sc->mfi_max_fw_cmds = status & MFI_FWSTATE_MAXCMD_MASK;
    +	max_fw_cmds = status & MFI_FWSTATE_MAXCMD_MASK;
    +	if (mfi_max_cmds > 0 && mfi_max_cmds < max_fw_cmds) {
    +		device_printf(sc->mfi_dev, "FW MaxCmds = %d, limiting to %d\n",
    +		    max_fw_cmds, mfi_max_cmds);
    +		sc->mfi_max_fw_cmds = mfi_max_cmds;
    +	} else {
    +		sc->mfi_max_fw_cmds = max_fw_cmds;
    +	}
     	max_fw_sge = (status & MFI_FWSTATE_MAXSGL_MASK) >> 16;
     	sc->mfi_max_sge = min(max_fw_sge, ((MFI_MAXPHYS / PAGE_SIZE) + 1));
     
    @@ -464,7 +478,8 @@ mfi_attach(struct mfi_softc *sc)
     
     	if (sc->mfi_flags & MFI_FLAGS_TBOLT) {
     		mfi_tbolt_init_globals(sc);
    -		device_printf(sc->mfi_dev, "MaxCmd = %x MaxSgl = %x state = %x \n",
    +		device_printf(sc->mfi_dev, "MaxCmd = %d, Drv MaxCmd = %d, "
    +		    "MaxSgl = %d, state = %#x\n", max_fw_cmds,
     		    sc->mfi_max_fw_cmds, sc->mfi_max_sge, status);
     		tb_mem_size = mfi_tbolt_get_memory_requirement(sc);
     
    @@ -503,8 +518,8 @@ mfi_attach(struct mfi_softc *sc)
     				0,			/* flags */
     				NULL, NULL,		/* lockfunc, lockarg */
     				&sc->mfi_tb_init_dmat)) {
    -		device_printf(sc->mfi_dev, "Cannot allocate init DMA tag\n");
    -		return (ENOMEM);
    +			device_printf(sc->mfi_dev, "Cannot allocate init DMA tag\n");
    +			return (ENOMEM);
     		}
     		if (bus_dmamem_alloc(sc->mfi_tb_init_dmat, (void **)&sc->mfi_tb_init,
     		    BUS_DMA_NOWAIT, &sc->mfi_tb_init_dmamap)) {
    @@ -683,11 +698,14 @@ mfi_attach(struct mfi_softc *sc)
     	/* ThunderBolt MFI_IOC2 INIT */
     	if (sc->mfi_flags & MFI_FLAGS_TBOLT) {
     		sc->mfi_disable_intr(sc);
    +		mtx_lock(&sc->mfi_io_lock);
     		if ((error = mfi_tbolt_init_MFI_queue(sc)) != 0) {
     			device_printf(sc->mfi_dev,
     			    "TB Init has failed with error %d\n",error);
    +			mtx_unlock(&sc->mfi_io_lock);
     			return error;
     		}
    +		mtx_unlock(&sc->mfi_io_lock);
     
     		if ((error = mfi_tbolt_alloc_cmd(sc)) != 0)
     			return error;
    @@ -723,8 +741,12 @@ mfi_attach(struct mfi_softc *sc)
     		    "hook\n");
     		return (EINVAL);
     	}
    -	if ((error = mfi_aen_setup(sc, 0), 0) != 0)
    +	mtx_lock(&sc->mfi_io_lock);
    +	if ((error = mfi_aen_setup(sc, 0), 0) != 0) {
    +		mtx_unlock(&sc->mfi_io_lock);
     		return (error);
    +	}
    +	mtx_unlock(&sc->mfi_io_lock);
     
     	/*
     	 * Register a shutdown handler.
    @@ -764,7 +786,9 @@ mfi_attach(struct mfi_softc *sc)
     	    mfi_timeout, sc);
     
     	if (sc->mfi_flags & MFI_FLAGS_TBOLT) {
    +		mtx_lock(&sc->mfi_io_lock);
     		mfi_tbolt_sync_map_info(sc);
    +		mtx_unlock(&sc->mfi_io_lock);
     	}
     
     	return (0);
    @@ -774,21 +798,16 @@ static int
     mfi_alloc_commands(struct mfi_softc *sc)
     {
     	struct mfi_command *cm;
    -	int i, ncmds;
    +	int i, j;
     
     	/*
     	 * XXX Should we allocate all the commands up front, or allocate on
     	 * demand later like 'aac' does?
     	 */
    -	ncmds = MIN(mfi_max_cmds, sc->mfi_max_fw_cmds);
    -	if (bootverbose)
    -		device_printf(sc->mfi_dev, "Max fw cmds= %d, sizing driver "
    -		   "pool to %d\n", sc->mfi_max_fw_cmds, ncmds);
    +	sc->mfi_commands = malloc(sizeof(sc->mfi_commands[0]) *
    +	    sc->mfi_max_fw_cmds, M_MFIBUF, M_WAITOK | M_ZERO);
     
    -	sc->mfi_commands = malloc(sizeof(struct mfi_command) * ncmds, M_MFIBUF,
    -	    M_WAITOK | M_ZERO);
    -
    -	for (i = 0; i < ncmds; i++) {
    +	for (i = 0; i < sc->mfi_max_fw_cmds; i++) {
     		cm = &sc->mfi_commands[i];
     		cm->cm_frame = (union mfi_frame *)((uintptr_t)sc->mfi_frames +
     		    sc->mfi_cmd_size * i);
    @@ -804,10 +823,20 @@ mfi_alloc_commands(struct mfi_softc *sc)
     			mtx_lock(&sc->mfi_io_lock);
     			mfi_release_command(cm);
     			mtx_unlock(&sc->mfi_io_lock);
    +		} else {
    +			device_printf(sc->mfi_dev, "Failed to allocate %d "
    +			   "command blocks, only allocated %d\n",
    +			    sc->mfi_max_fw_cmds, i - 1);
    +			for (j = 0; j < i; j++) {
    +				cm = &sc->mfi_commands[i];
    +				bus_dmamap_destroy(sc->mfi_buffer_dmat,
    +				    cm->cm_dmamap);
    +			}
    +			free(sc->mfi_commands, M_MFIBUF);
    +			sc->mfi_commands = NULL;
    +
    +			return (ENOMEM);
     		}
    -		else
    -			break;
    -		sc->mfi_total_cmds++;
     	}
     
     	return (0);
    @@ -832,6 +861,29 @@ mfi_release_command(struct mfi_command *cm)
     		cm->cm_sg->sg32[0].addr = 0;
     	}
     
    +	/*
    +	 * Command may be on other queues e.g. busy queue depending on the
    +	 * flow of a previous call to mfi_mapcmd, so ensure its dequeued
    +	 * properly
    +	 */
    +	if ((cm->cm_flags & MFI_ON_MFIQ_BUSY) != 0)
    +		mfi_remove_busy(cm);
    +	if ((cm->cm_flags & MFI_ON_MFIQ_READY) != 0)
    +		mfi_remove_ready(cm);
    +
    +	/* We're not expecting it to be on any other queue but check */
    +	if ((cm->cm_flags & MFI_ON_MFIQ_MASK) != 0) {
    +		panic("Command %p is still on another queue, flags = %#x",
    +		    cm, cm->cm_flags);
    +	}
    +
    +	/* tbolt cleanup */
    +	if ((cm->cm_flags & MFI_CMD_TBOLT) != 0) {
    +		mfi_tbolt_return_cmd(cm->cm_sc,
    +		    cm->cm_sc->mfi_cmd_pool_tbolt[cm->cm_extra_frames - 1],
    +		    cm);
    +	}
    +
     	hdr_data = (uint32_t *)cm->cm_frame;
     	hdr_data[0] = 0;	/* cmd, sense_len, cmd_status, scsi_status */
     	hdr_data[1] = 0;	/* target_id, lun_id, cdb_len, sg_count */
    @@ -914,8 +966,10 @@ mfi_comms_init(struct mfi_softc *sc)
     	uint32_t context = 0;
     
     	mtx_lock(&sc->mfi_io_lock);
    -	if ((cm = mfi_dequeue_free(sc)) == NULL)
    +	if ((cm = mfi_dequeue_free(sc)) == NULL) {
    +		mtx_unlock(&sc->mfi_io_lock);
     		return (EBUSY);
    +	}
     
     	/* Zero out the MFI frame */
     	context = cm->cm_frame->header.context;
    @@ -944,15 +998,12 @@ mfi_comms_init(struct mfi_softc *sc)
     	cm->cm_data = NULL;
     	cm->cm_flags = MFI_CMD_POLLED;
     
    -	if ((error = mfi_mapcmd(sc, cm)) != 0) {
    +	if ((error = mfi_mapcmd(sc, cm)) != 0)
     		device_printf(sc->mfi_dev, "failed to send init command\n");
    -		mtx_unlock(&sc->mfi_io_lock);
    -		return (error);
    -	}
     	mfi_release_command(cm);
     	mtx_unlock(&sc->mfi_io_lock);
     
    -	return (0);
    +	return (error);
     }
     
     static int
    @@ -1003,7 +1054,7 @@ mfi_get_log_state(struct mfi_softc *sc, struct mfi_evt_log_state **log_state)
     	struct mfi_command *cm = NULL;
     	int error;
     
    -	mtx_lock(&sc->mfi_io_lock);
    +	mtx_assert(&sc->mfi_io_lock, MA_OWNED);
     	error = mfi_dcmd_command(sc, &cm, MFI_DCMD_CTRL_EVENT_GETINFO,
     	    (void **)log_state, sizeof(**log_state));
     	if (error)
    @@ -1022,7 +1073,6 @@ mfi_get_log_state(struct mfi_softc *sc, struct mfi_evt_log_state **log_state)
     out:
     	if (cm)
     		mfi_release_command(cm);
    -	mtx_unlock(&sc->mfi_io_lock);
     
     	return (error);
     }
    @@ -1035,32 +1085,32 @@ mfi_aen_setup(struct mfi_softc *sc, uint32_t seq_start)
     	int error = 0;
     	uint32_t seq;
     
    +	mtx_assert(&sc->mfi_io_lock, MA_OWNED);
    +
     	class_locale.members.reserved = 0;
     	class_locale.members.locale = mfi_event_locale;
     	class_locale.members.evt_class  = mfi_event_class;
     
     	if (seq_start == 0) {
    -		error = mfi_get_log_state(sc, &log_state);
    +		if ((error = mfi_get_log_state(sc, &log_state)) != 0)
    +			goto out;
     		sc->mfi_boot_seq_num = log_state->boot_seq_num;
    -		if (error) {
    -			if (log_state)
    -				free(log_state, M_MFIBUF);
    -			return (error);
    -		}
     
     		/*
     		 * Walk through any events that fired since the last
     		 * shutdown.
     		 */
    -		mfi_parse_entries(sc, log_state->shutdown_seq_num,
    -		    log_state->newest_seq_num);
    +		if ((error = mfi_parse_entries(sc, log_state->shutdown_seq_num,
    +		    log_state->newest_seq_num)) != 0)
    +			goto out;
     		seq = log_state->newest_seq_num;
     	} else
     		seq = seq_start;
    -	mfi_aen_register(sc, seq, class_locale.word);
    +	error = mfi_aen_register(sc, seq, class_locale.word);
    +out:
     	free(log_state, M_MFIBUF);
     
    -	return 0;
    +	return (error);
     }
     
     int
    @@ -1070,7 +1120,6 @@ mfi_wait_command(struct mfi_softc *sc, struct mfi_command *cm)
     	mtx_assert(&sc->mfi_io_lock, MA_OWNED);
     	cm->cm_complete = NULL;
     
    -
     	/*
     	 * MegaCli can issue a DCMD of 0.  In this case do nothing
     	 * and return 0 to it as status
    @@ -1098,12 +1147,13 @@ mfi_free(struct mfi_softc *sc)
     	if (sc->mfi_cdev != NULL)
     		destroy_dev(sc->mfi_cdev);
     
    -	if (sc->mfi_total_cmds != 0) {
    -		for (i = 0; i < sc->mfi_total_cmds; i++) {
    +	if (sc->mfi_commands != NULL) {
    +		for (i = 0; i < sc->mfi_max_fw_cmds; i++) {
     			cm = &sc->mfi_commands[i];
     			bus_dmamap_destroy(sc->mfi_buffer_dmat, cm->cm_dmamap);
     		}
     		free(sc->mfi_commands, M_MFIBUF);
    +		sc->mfi_commands = NULL;
     	}
     
     	if (sc->mfi_intr)
    @@ -1159,7 +1209,8 @@ mfi_free(struct mfi_softc *sc)
     		/* End LSIP200113393 */
     		/* ThunderBolt INIT packet memory Free */
     		if (sc->mfi_tb_init_busaddr != 0)
    -			bus_dmamap_unload(sc->mfi_tb_init_dmat, sc->mfi_tb_init_dmamap);
    +			bus_dmamap_unload(sc->mfi_tb_init_dmat,
    +			    sc->mfi_tb_init_dmamap);
     		if (sc->mfi_tb_init != NULL)
     			bus_dmamem_free(sc->mfi_tb_init_dmat, sc->mfi_tb_init,
     			    sc->mfi_tb_init_dmamap);
    @@ -1176,16 +1227,14 @@ mfi_free(struct mfi_softc *sc)
     			    sc->mfi_tb_ioc_init_dmamap);
     		if (sc->mfi_tb_ioc_init_dmat != NULL)
     			bus_dma_tag_destroy(sc->mfi_tb_ioc_init_dmat);
    -		for (int i = 0; i < sc->mfi_max_fw_cmds; i++) {
    -			if (sc->mfi_cmd_pool_tbolt != NULL) {
    +		if (sc->mfi_cmd_pool_tbolt != NULL) {
    +			for (int i = 0; i < sc->mfi_max_fw_cmds; i++) {
     				if (sc->mfi_cmd_pool_tbolt[i] != NULL) {
     					free(sc->mfi_cmd_pool_tbolt[i],
     					    M_MFIBUF);
     					sc->mfi_cmd_pool_tbolt[i] = NULL;
     				}
     			}
    -		}
    -		if (sc->mfi_cmd_pool_tbolt != NULL) {
     			free(sc->mfi_cmd_pool_tbolt, M_MFIBUF);
     			sc->mfi_cmd_pool_tbolt = NULL;
     		}
    @@ -1250,16 +1299,14 @@ restart:
     			cm->cm_error = 0;
     			mfi_complete(sc, cm);
     		}
    -		if (++ci == (sc->mfi_max_fw_cmds + 1)) {
    +		if (++ci == (sc->mfi_max_fw_cmds + 1))
     			ci = 0;
    -		}
     	}
     
     	sc->mfi_comms->hw_ci = ci;
     
     	/* Give defered I/O a chance to run */
    -	if (sc->mfi_flags & MFI_FLAGS_QFRZN)
    -		sc->mfi_flags &= ~MFI_FLAGS_QFRZN;
    +	sc->mfi_flags &= ~MFI_FLAGS_QFRZN;
     	mfi_startio(sc);
     	mtx_unlock(&sc->mfi_io_lock);
     
    @@ -1282,15 +1329,15 @@ mfi_shutdown(struct mfi_softc *sc)
     	int error;
     
     
    -	if (sc->mfi_aen_cm)
    +	if (sc->mfi_aen_cm != NULL) {
     		sc->cm_aen_abort = 1;
    -	if (sc->mfi_aen_cm != NULL)
     		mfi_abort(sc, &sc->mfi_aen_cm);
    +	}
     
    -	if (sc->mfi_map_sync_cm)
    +	if (sc->mfi_map_sync_cm != NULL) {
     		sc->cm_map_abort = 1;
    -	if (sc->mfi_map_sync_cm != NULL)
     		mfi_abort(sc, &sc->mfi_map_sync_cm);
    +	}
     
     	mtx_lock(&sc->mfi_io_lock);
     	error = mfi_dcmd_command(sc, &cm, MFI_DCMD_CTRL_SHUTDOWN, NULL, 0);
    @@ -1304,9 +1351,8 @@ mfi_shutdown(struct mfi_softc *sc)
     	cm->cm_flags = MFI_CMD_POLLED;
     	cm->cm_data = NULL;
     
    -	if ((error = mfi_mapcmd(sc, cm)) != 0) {
    +	if ((error = mfi_mapcmd(sc, cm)) != 0)
     		device_printf(sc->mfi_dev, "Failed to shutdown controller\n");
    -	}
     
     	mfi_release_command(cm);
     	mtx_unlock(&sc->mfi_io_lock);
    @@ -1372,8 +1418,10 @@ mfi_syspdprobe(struct mfi_softc *sc)
     	TAILQ_FOREACH_SAFE(syspd, &sc->mfi_syspd_tqh, pd_link, tmp) {
     		found = 0;
     		for (i = 0; i < pdlist->count; i++) {
    -			if (syspd->pd_id == pdlist->addr[i].device_id)
    +			if (syspd->pd_id == pdlist->addr[i].device_id) {
     				found = 1;
    +				break;
    +			}
     		}
     		if (found == 0) {
     			printf("DELETE\n");
    @@ -1626,6 +1674,8 @@ mfi_aen_register(struct mfi_softc *sc, int seq, int locale)
     	struct mfi_evt_detail *ed = NULL;
     	int error = 0;
     
    +	mtx_assert(&sc->mfi_io_lock, MA_OWNED);
    +
     	current_aen.word = locale;
     	if (sc->mfi_aen_cm != NULL) {
     		prior_aen.word =
    @@ -1644,13 +1694,10 @@ mfi_aen_register(struct mfi_softc *sc, int seq, int locale)
     		}
     	}
     
    -	mtx_lock(&sc->mfi_io_lock);
     	error = mfi_dcmd_command(sc, &cm, MFI_DCMD_CTRL_EVENT_WAIT,
     	    (void **)&ed, sizeof(*ed));
    -	mtx_unlock(&sc->mfi_io_lock);
    -	if (error) {
    +	if (error)
     		goto out;
    -	}
     
     	dcmd = &cm->cm_frame->dcmd;
     	((uint32_t *)&dcmd->mbox)[0] = seq;
    @@ -1661,10 +1708,8 @@ mfi_aen_register(struct mfi_softc *sc, int seq, int locale)
     	sc->last_seq_num = seq;
     	sc->mfi_aen_cm = cm;
     
    -	mtx_lock(&sc->mfi_io_lock);
     	mfi_enqueue_ready(cm);
     	mfi_startio(sc);
    -	mtx_unlock(&sc->mfi_io_lock);
     
     out:
     	return (error);
    @@ -1682,11 +1727,11 @@ mfi_aen_complete(struct mfi_command *cm)
     	sc = cm->cm_sc;
     	mtx_assert(&sc->mfi_io_lock, MA_OWNED);
     
    -	hdr = &cm->cm_frame->header;
    -
     	if (sc->mfi_aen_cm == NULL)
     		return;
     
    +	hdr = &cm->cm_frame->header;
    +
     	if (sc->cm_aen_abort ||
     	    hdr->cmd_status == MFI_STAT_INVALID_STATUS) {
     		sc->cm_aen_abort = 0;
    @@ -1712,16 +1757,13 @@ mfi_aen_complete(struct mfi_command *cm)
     	}
     
     	free(cm->cm_data, M_MFIBUF);
    -	sc->mfi_aen_cm = NULL;
     	wakeup(&sc->mfi_aen_cm);
    +	sc->mfi_aen_cm = NULL;
     	mfi_release_command(cm);
     
     	/* set it up again so the driver can catch more events */
    -	if (!aborted) {
    -		mtx_unlock(&sc->mfi_io_lock);
    +	if (!aborted)
     		mfi_aen_setup(sc, seq);
    -		mtx_lock(&sc->mfi_io_lock);
    -	}
     }
     
     #define MAX_EVENTS 15
    @@ -1735,6 +1777,8 @@ mfi_parse_entries(struct mfi_softc *sc, int start_seq, int stop_seq)
     	union mfi_evt class_locale;
     	int error, i, seq, size;
     
    +	mtx_assert(&sc->mfi_io_lock, MA_OWNED);
    +
     	class_locale.members.reserved = 0;
     	class_locale.members.locale = mfi_event_locale;
     	class_locale.members.evt_class  = mfi_event_class;
    @@ -1746,13 +1790,10 @@ mfi_parse_entries(struct mfi_softc *sc, int start_seq, int stop_seq)
     		return (ENOMEM);
     
     	for (seq = start_seq;;) {
    -		mtx_lock(&sc->mfi_io_lock);
     		if ((cm = mfi_dequeue_free(sc)) == NULL) {
     			free(el, M_MFIBUF);
    -			mtx_unlock(&sc->mfi_io_lock);
     			return (EBUSY);
     		}
    -		mtx_unlock(&sc->mfi_io_lock);
     
     		dcmd = &cm->cm_frame->dcmd;
     		bzero(dcmd->mbox, MFI_MBOX_SIZE);
    @@ -1768,38 +1809,30 @@ mfi_parse_entries(struct mfi_softc *sc, int start_seq, int stop_seq)
     		cm->cm_data = el;
     		cm->cm_len = size;
     
    -		mtx_lock(&sc->mfi_io_lock);
     		if ((error = mfi_mapcmd(sc, cm)) != 0) {
     			device_printf(sc->mfi_dev,
     			    "Failed to get controller entries\n");
     			mfi_release_command(cm);
    -			mtx_unlock(&sc->mfi_io_lock);
     			break;
     		}
     
    -		mtx_unlock(&sc->mfi_io_lock);
     		bus_dmamap_sync(sc->mfi_buffer_dmat, cm->cm_dmamap,
     		    BUS_DMASYNC_POSTREAD);
     		bus_dmamap_unload(sc->mfi_buffer_dmat, cm->cm_dmamap);
     
     		if (dcmd->header.cmd_status == MFI_STAT_NOT_FOUND) {
    -			mtx_lock(&sc->mfi_io_lock);
     			mfi_release_command(cm);
    -			mtx_unlock(&sc->mfi_io_lock);
     			break;
     		}
     		if (dcmd->header.cmd_status != MFI_STAT_OK) {
     			device_printf(sc->mfi_dev,
     			    "Error %d fetching controller entries\n",
     			    dcmd->header.cmd_status);
    -			mtx_lock(&sc->mfi_io_lock);
     			mfi_release_command(cm);
    -			mtx_unlock(&sc->mfi_io_lock);
    +			error = EIO;
     			break;
     		}
    -		mtx_lock(&sc->mfi_io_lock);
     		mfi_release_command(cm);
    -		mtx_unlock(&sc->mfi_io_lock);
     
     		for (i = 0; i < el->count; i++) {
     			/*
    @@ -1815,15 +1848,13 @@ mfi_parse_entries(struct mfi_softc *sc, int start_seq, int stop_seq)
     				else if (el->event[i].seq < start_seq)
     					break;
     			}
    -			mtx_lock(&sc->mfi_io_lock);
     			mfi_queue_evt(sc, &el->event[i]);
    -			mtx_unlock(&sc->mfi_io_lock);
     		}
     		seq = el->event[el->count - 1].seq + 1;
     	}
     
     	free(el, M_MFIBUF);
    -	return (0);
    +	return (error);
     }
     
     static int
    @@ -1940,11 +1971,12 @@ static int mfi_add_sys_pd(struct mfi_softc *sc, int id)
     	dcmd->mbox[0]=id;
     	dcmd->header.scsi_status = 0;
     	dcmd->header.pad0 = 0;
    -	if (mfi_mapcmd(sc, cm) != 0) {
    +	if ((error = mfi_mapcmd(sc, cm)) != 0) {
     		device_printf(sc->mfi_dev,
     		    "Failed to get physical drive info %d\n", id);
     		free(pd_info, M_MFIBUF);
    -		return (0);
    +		mfi_release_command(cm);
    +		return (error);
     	}
     	bus_dmamap_sync(sc->mfi_buffer_dmat, cm->cm_dmamap,
     	    BUS_DMASYNC_POSTREAD);
    @@ -2094,6 +2126,8 @@ mfi_build_syspdio(struct mfi_softc *sc, struct bio *bio)
     	int flags = 0, blkcount = 0, readop;
     	uint8_t cdb_len;
     
    +	mtx_assert(&sc->mfi_io_lock, MA_OWNED);
    +
     	if ((cm = mfi_dequeue_free(sc)) == NULL)
     	    return (NULL);
     
    @@ -2140,6 +2174,7 @@ mfi_build_syspdio(struct mfi_softc *sc, struct bio *bio)
     	cm->cm_sg = &pass->sgl;
     	cm->cm_total_frame_size = MFI_PASS_FRAME_SIZE;
     	cm->cm_flags = flags;
    +
     	return (cm);
     }
     
    @@ -2152,6 +2187,8 @@ mfi_build_ldio(struct mfi_softc *sc, struct bio *bio)
     	uint32_t blkcount;
     	uint32_t context = 0;
     
    +	mtx_assert(&sc->mfi_io_lock, MA_OWNED);
    +
     	if ((cm = mfi_dequeue_free(sc)) == NULL)
     	    return (NULL);
     
    @@ -2193,6 +2230,7 @@ mfi_build_ldio(struct mfi_softc *sc, struct bio *bio)
     	cm->cm_sg = &io->sgl;
     	cm->cm_total_frame_size = MFI_IO_FRAME_SIZE;
     	cm->cm_flags = flags;
    +
     	return (cm);
     }
     
    @@ -2210,11 +2248,14 @@ mfi_bio_complete(struct mfi_command *cm)
     	if ((hdr->cmd_status != MFI_STAT_OK) || (hdr->scsi_status != 0)) {
     		bio->bio_flags |= BIO_ERROR;
     		bio->bio_error = EIO;
    -		device_printf(sc->mfi_dev, "I/O error, status= %d "
    -		    "scsi_status= %d\n", hdr->cmd_status, hdr->scsi_status);
    +		device_printf(sc->mfi_dev, "I/O error, cmd=%p, status=%#x, "
    +		    "scsi_status=%#x\n", cm, hdr->cmd_status, hdr->scsi_status);
     		mfi_print_sense(cm->cm_sc, cm->cm_sense);
     	} else if (cm->cm_error != 0) {
     		bio->bio_flags |= BIO_ERROR;
    +		bio->bio_error = cm->cm_error;
    +		device_printf(sc->mfi_dev, "I/O error, cmd=%p, error=%#x\n",
    +		    cm, cm->cm_error);
     	}
     
     	mfi_release_command(cm);
    @@ -2250,6 +2291,7 @@ mfi_startio(struct mfi_softc *sc)
     
     		/* Send the command to the controller */
     		if (mfi_mapcmd(sc, cm) != 0) {
    +			device_printf(sc->mfi_dev, "Failed to startio\n");
     			mfi_requeue_ready(cm);
     			break;
     		}
    @@ -2278,10 +2320,7 @@ mfi_mapcmd(struct mfi_softc *sc, struct mfi_command *cm)
     			return (0);
     		}
     	} else {
    -		if (sc->MFA_enabled)
    -			error = mfi_tbolt_send_frame(sc, cm);
    -		else
    -			error = mfi_send_frame(sc, cm);
    +		error = mfi_send_frame(sc, cm);
     	}
     
     	return (error);
    @@ -2295,18 +2334,28 @@ mfi_data_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
     	union mfi_sgl *sgl;
     	struct mfi_softc *sc;
     	int i, j, first, dir;
    -	int sge_size;
    +	int sge_size, locked;
     
     	cm = (struct mfi_command *)arg;
     	sc = cm->cm_sc;
     	hdr = &cm->cm_frame->header;
     	sgl = cm->cm_sg;
     
    +	/*
    +	 * We need to check if we have the lock as this is async
    +	 * callback so even though our caller mfi_mapcmd asserts
    +	 * it has the lock, there is no garantee that hasn't been
    +	 * dropped if bus_dmamap_load returned prior to our
    +	 * completion.
    +	 */
    +	if ((locked = mtx_owned(&sc->mfi_io_lock)) == 0)
    +		mtx_lock(&sc->mfi_io_lock);
    +
     	if (error) {
     		printf("error %d in callback\n", error);
     		cm->cm_error = error;
     		mfi_complete(sc, cm);
    -		return;
    +		goto out;
     	}
     	/* Use IEEE sgl only for IO's on a SKINNY controller
     	 * For other commands on a SKINNY controller use either
    @@ -2378,19 +2427,44 @@ mfi_data_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
     	cm->cm_total_frame_size += (sc->mfi_sge_size * nsegs);
     	cm->cm_extra_frames = (cm->cm_total_frame_size - 1) / MFI_FRAME_SIZE;
     
    -	if (sc->MFA_enabled)
    -			mfi_tbolt_send_frame(sc, cm);
    -	else
    -		mfi_send_frame(sc, cm);
    +	if ((error = mfi_send_frame(sc, cm)) != 0) {
    +		printf("error %d in callback from mfi_send_frame\n", error);
    +		cm->cm_error = error;
    +		mfi_complete(sc, cm);
    +		goto out;
    +	}
    +
    +out:
    +	/* leave the lock in the state we found it */
    +	if (locked == 0)
    +		mtx_unlock(&sc->mfi_io_lock);
     
     	return;
     }
     
     static int
     mfi_send_frame(struct mfi_softc *sc, struct mfi_command *cm)
    +{
    +	int error;
    +
    +	mtx_assert(&sc->mfi_io_lock, MA_OWNED);
    +
    +	if (sc->MFA_enabled)
    +		error = mfi_tbolt_send_frame(sc, cm);
    +	else
    +		error = mfi_std_send_frame(sc, cm);
    +
    +	if (error != 0 && (cm->cm_flags & MFI_ON_MFIQ_BUSY) != 0)
    +		mfi_remove_busy(cm);
    +
    +	return (error);
    +}
    +
    +static int
    +mfi_std_send_frame(struct mfi_softc *sc, struct mfi_command *cm)
     {
     	struct mfi_frame_header *hdr;
    -	int tm = MFI_POLL_TIMEOUT_SECS * 1000;
    +	int tm = mfi_polled_cmd_timeout * 1000;
     
     	hdr = &cm->cm_frame->header;
     
    @@ -2444,6 +2518,7 @@ void
     mfi_complete(struct mfi_softc *sc, struct mfi_command *cm)
     {
     	int dir;
    +	mtx_assert(&sc->mfi_io_lock, MA_OWNED);
     
     	if ((cm->cm_flags & MFI_CMD_MAPPED) != 0) {
     		dir = 0;
    @@ -2471,11 +2546,12 @@ mfi_abort(struct mfi_softc *sc, struct mfi_command **cm_abort)
     {
     	struct mfi_command *cm;
     	struct mfi_abort_frame *abort;
    -	int i = 0;
    +	int i = 0, error;
     	uint32_t context = 0;
     
     	mtx_lock(&sc->mfi_io_lock);
     	if ((cm = mfi_dequeue_free(sc)) == NULL) {
    +		mtx_unlock(&sc->mfi_io_lock);
     		return (EBUSY);
     	}
     
    @@ -2495,7 +2571,8 @@ mfi_abort(struct mfi_softc *sc, struct mfi_command **cm_abort)
     	cm->cm_data = NULL;
     	cm->cm_flags = MFI_CMD_POLLED;
     
    -	mfi_mapcmd(sc, cm);
    +	if ((error = mfi_mapcmd(sc, cm)) != 0)
    +		device_printf(sc->mfi_dev, "failed to abort command\n");
     	mfi_release_command(cm);
     
     	mtx_unlock(&sc->mfi_io_lock);
    @@ -2511,7 +2588,7 @@ mfi_abort(struct mfi_softc *sc, struct mfi_command **cm_abort)
     		mtx_unlock(&sc->mfi_io_lock);
     	}
     
    -	return (0);
    +	return (error);
     }
     
     int
    @@ -2549,7 +2626,8 @@ mfi_dump_blocks(struct mfi_softc *sc, int id, uint64_t lba, void *virt,
     	cm->cm_total_frame_size = MFI_IO_FRAME_SIZE;
     	cm->cm_flags = MFI_CMD_POLLED | MFI_CMD_DATAOUT;
     
    -	error = mfi_mapcmd(sc, cm);
    +	if ((error = mfi_mapcmd(sc, cm)) != 0)
    +		device_printf(sc->mfi_dev, "failed dump blocks\n");
     	bus_dmamap_sync(sc->mfi_buffer_dmat, cm->cm_dmamap,
     	    BUS_DMASYNC_POSTWRITE);
     	bus_dmamap_unload(sc->mfi_buffer_dmat, cm->cm_dmamap);
    @@ -2592,7 +2670,8 @@ mfi_dump_syspd_blocks(struct mfi_softc *sc, int id, uint64_t lba, void *virt,
     	cm->cm_total_frame_size = MFI_PASS_FRAME_SIZE;
     	cm->cm_flags = MFI_CMD_POLLED | MFI_CMD_DATAOUT | MFI_CMD_SCSI;
     
    -	error = mfi_mapcmd(sc, cm);
    +	if ((error = mfi_mapcmd(sc, cm)) != 0)
    +		device_printf(sc->mfi_dev, "failed dump blocks\n");
     	bus_dmamap_sync(sc->mfi_buffer_dmat, cm->cm_dmamap,
     	    BUS_DMASYNC_POSTWRITE);
     	bus_dmamap_unload(sc->mfi_buffer_dmat, cm->cm_dmamap);
    @@ -3306,8 +3385,10 @@ out:
     		}
     	case MFI_SET_AEN:
     		aen = (struct mfi_ioc_aen *)arg;
    +		mtx_lock(&sc->mfi_io_lock);
     		error = mfi_aen_register(sc, aen->aen_seq_num,
     		    aen->aen_class_locale);
    +		mtx_unlock(&sc->mfi_io_lock);
     
     		break;
     	case MFI_LINUX_CMD_2: /* Firmware Linux ioctl shim */
    @@ -3636,7 +3717,7 @@ mfi_dump_all(void)
     		deadline = time_uptime - MFI_CMD_TIMEOUT;
     		mtx_lock(&sc->mfi_io_lock);
     		TAILQ_FOREACH(cm, &sc->mfi_busy, cm_link) {
    -			if (cm->cm_timestamp < deadline) {
    +			if (cm->cm_timestamp <= deadline) {
     				device_printf(sc->mfi_dev,
     				    "COMMAND %p TIMEOUT AFTER %d SECONDS\n",
     				    cm, (int)(time_uptime - cm->cm_timestamp));
    @@ -3647,7 +3728,7 @@ mfi_dump_all(void)
     
     #if 0
     		if (timedout)
    -			MFI_DUMP_CMDS(SC);
    +			MFI_DUMP_CMDS(sc);
     #endif
     
     		mtx_unlock(&sc->mfi_io_lock);
    @@ -3660,7 +3741,7 @@ static void
     mfi_timeout(void *data)
     {
     	struct mfi_softc *sc = (struct mfi_softc *)data;
    -	struct mfi_command *cm;
    +	struct mfi_command *cm, *tmp;
     	time_t deadline;
     	int timedout = 0;
     
    @@ -3672,10 +3753,10 @@ mfi_timeout(void *data)
     		}
     	}
     	mtx_lock(&sc->mfi_io_lock);
    -	TAILQ_FOREACH(cm, &sc->mfi_busy, cm_link) {
    +	TAILQ_FOREACH_SAFE(cm, &sc->mfi_busy, cm_link, tmp) {
     		if (sc->mfi_aen_cm == cm || sc->mfi_map_sync_cm == cm)
     			continue;
    -		if (cm->cm_timestamp < deadline) {
    +		if (cm->cm_timestamp <= deadline) {
     			if (sc->adpreset != 0 && sc->issuepend_done == 0) {
     				cm->cm_timestamp = time_uptime;
     			} else {
    @@ -3685,6 +3766,13 @@ mfi_timeout(void *data)
     				     );
     				MFI_PRINT_CMD(cm);
     				MFI_VALIDATE_CMD(sc, cm);
    +				/*
    +				 * Fail the command instead of leaving it on
    +				 * the queue where it could remain stuck forever
    +				 */
    +				mfi_remove_busy(cm);
    +				cm->cm_error = ETIMEDOUT;
    +				mfi_complete(sc, cm);
     				timedout++;
     			}
     		}
    @@ -3692,7 +3780,7 @@ mfi_timeout(void *data)
     
     #if 0
     	if (timedout)
    -		MFI_DUMP_CMDS(SC);
    +		MFI_DUMP_CMDS(sc);
     #endif
     
     	mtx_unlock(&sc->mfi_io_lock);
    diff --git a/sys/dev/mfi/mfi_cam.c b/sys/dev/mfi/mfi_cam.c
    index 325b064cde9..0ea232669c9 100644
    --- a/sys/dev/mfi/mfi_cam.c
    +++ b/sys/dev/mfi/mfi_cam.c
    @@ -145,6 +145,7 @@ mfip_attach(device_t dev)
     				MFI_SCSI_MAX_CMDS, sc->devq);
     	if (sc->sim == NULL) {
     		cam_simq_free(sc->devq);
    +		sc->devq = NULL;
     		device_printf(dev, "CAM SIM attach failed\n");
     		return (EINVAL);
     	}
    @@ -155,7 +156,9 @@ mfip_attach(device_t dev)
     	if (xpt_bus_register(sc->sim, dev, 0) != 0) {
     		device_printf(dev, "XPT bus registration failed\n");
     		cam_sim_free(sc->sim, FALSE);
    +		sc->sim = NULL;
     		cam_simq_free(sc->devq);
    +		sc->devq = NULL;
     		mtx_unlock(&mfisc->mfi_io_lock);
     		return (EINVAL);
     	}
    @@ -187,11 +190,14 @@ mfip_detach(device_t dev)
     		mtx_lock(&sc->mfi_sc->mfi_io_lock);
     		xpt_bus_deregister(cam_sim_path(sc->sim));
     		cam_sim_free(sc->sim, FALSE);
    +		sc->sim = NULL;
     		mtx_unlock(&sc->mfi_sc->mfi_io_lock);
     	}
     
    -	if (sc->devq != NULL)
    +	if (sc->devq != NULL) {
     		cam_simq_free(sc->devq);
    +		sc->devq = NULL;
    +	}
     
     	return (0);
     }
    diff --git a/sys/dev/mfi/mfi_debug.c b/sys/dev/mfi/mfi_debug.c
    index 2e66e19d1fd..4aec4f7dbf5 100644
    --- a/sys/dev/mfi/mfi_debug.c
    +++ b/sys/dev/mfi/mfi_debug.c
    @@ -57,14 +57,7 @@ __FBSDID("$FreeBSD$");
     static void
     mfi_print_frame_flags(device_t dev, uint32_t flags)
     {
    -	device_printf(dev, "flags=%b\n", flags,
    -	    "\20"
    -	    "\1NOPOST"
    -	    "\2SGL64"
    -	    "\3SENSE64"
    -	    "\4WRITE"
    -	    "\5READ"
    -	    "\6IEEESGL");
    +	device_printf(dev, "flags=%b\n", flags, MFI_FRAME_FMT);
     }
     
     static void
    @@ -205,16 +198,7 @@ mfi_print_cmd(struct mfi_command *cm)
     	device_printf(dev, "cm=%p index=%d total_frame_size=%d "
     	    "extra_frames=%d\n", cm, cm->cm_index, cm->cm_total_frame_size,
     	    cm->cm_extra_frames);
    -	device_printf(dev, "flags=%b\n", cm->cm_flags,
    -	    "\20"
    -	    "\1MAPPED"
    -	    "\2DATAIN"
    -	    "\3DATAOUT"
    -	    "\4COMPLETED"
    -	    "\5POLLED"
    -	    "\6Q_FREE"
    -	    "\7Q_READY"
    -	    "\10Q_BUSY");
    +	device_printf(dev, "flags=%b\n", cm->cm_flags, MFI_CMD_FLAGS_FMT);
     
     	switch (cm->cm_frame->header.cmd) {
     	case MFI_CMD_DCMD:
    @@ -237,7 +221,7 @@ mfi_dump_cmds(struct mfi_softc *sc)
     {
     	int i;
     
    -	for (i = 0; i < sc->mfi_total_cmds; i++)
    +	for (i = 0; i < sc->mfi_max_fw_cmds; i++)
     		mfi_print_generic_frame(sc, &sc->mfi_commands[i]);
     }
     
    diff --git a/sys/dev/mfi/mfi_tbolt.c b/sys/dev/mfi/mfi_tbolt.c
    index af83392bb18..9d29ea0a413 100644
    --- a/sys/dev/mfi/mfi_tbolt.c
    +++ b/sys/dev/mfi/mfi_tbolt.c
    @@ -55,14 +55,12 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     
    -struct mfi_cmd_tbolt *mfi_tbolt_get_cmd(struct mfi_softc *sc);
    +struct mfi_cmd_tbolt *mfi_tbolt_get_cmd(struct mfi_softc *sc, struct mfi_command *);
     union mfi_mpi2_request_descriptor *
     mfi_tbolt_get_request_descriptor(struct mfi_softc *sc, uint16_t index);
     void mfi_tbolt_complete_cmd(struct mfi_softc *sc);
     int mfi_tbolt_build_io(struct mfi_softc *sc, struct mfi_command *mfi_cmd,
         struct mfi_cmd_tbolt *cmd);
    -static inline void mfi_tbolt_return_cmd(struct mfi_softc *sc,
    -    struct mfi_cmd_tbolt *cmd);
     union mfi_mpi2_request_descriptor *mfi_tbolt_build_mpt_cmd(struct mfi_softc
         *sc, struct mfi_command *cmd);
     uint8_t
    @@ -84,6 +82,15 @@ static void mfi_queue_map_sync(struct mfi_softc *sc);
     
     #define MFI_FUSION_ENABLE_INTERRUPT_MASK	(0x00000008)
     
    +
    +extern int	mfi_polled_cmd_timeout;
    +static int	mfi_fw_reset_test = 0;
    +#ifdef MFI_DEBUG
    +TUNABLE_INT("hw.mfi.fw_reset_test", &mfi_fw_reset_test);
    +SYSCTL_INT(_hw_mfi, OID_AUTO, fw_reset_test, CTLFLAG_RWTUN, &mfi_fw_reset_test,
    +           0, "Force a firmware reset condition");
    +#endif
    +
     void
     mfi_tbolt_enable_intr_ppc(struct mfi_softc *sc)
     {
    @@ -162,14 +169,14 @@ mfi_tbolt_adp_reset(struct mfi_softc *sc)
     	while (!( HostDiag & DIAG_WRITE_ENABLE)) {
     		for (i = 0; i < 1000; i++);
     		HostDiag = (uint32_t)MFI_READ4(sc, MFI_HDR);
    -		device_printf(sc->mfi_dev, "ADP_RESET_TBOLT: retry time=%x, "
    -		    "hostdiag=%x\n", retry, HostDiag);
    +		device_printf(sc->mfi_dev, "ADP_RESET_TBOLT: retry time=%d, "
    +		    "hostdiag=%#x\n", retry, HostDiag);
     
     		if (retry++ >= 100)
     			return 1;
     	}
     
    -	device_printf(sc->mfi_dev, "ADP_RESET_TBOLT: HostDiag=%x\n", HostDiag);
    +	device_printf(sc->mfi_dev, "ADP_RESET_TBOLT: HostDiag=%#x\n", HostDiag);
     
     	MFI_WRITE4(sc, MFI_HDR, (HostDiag | DIAG_RESET_ADAPTER));
     
    @@ -181,8 +188,8 @@ mfi_tbolt_adp_reset(struct mfi_softc *sc)
     	while (HostDiag & DIAG_RESET_ADAPTER) {
     		for (i = 0; i < 1000; i++) ;
     		HostDiag = (uint32_t)MFI_READ4(sc, MFI_RSR);
    -		device_printf(sc->mfi_dev, "ADP_RESET_TBOLT: retry time=%x, "
    -		    "hostdiag=%x\n", retry, HostDiag);
    +		device_printf(sc->mfi_dev, "ADP_RESET_TBOLT: retry time=%d, "
    +		    "hostdiag=%#x\n", retry, HostDiag);
     
     		if (retry++ >= 1000)
     			return 1;
    @@ -311,6 +318,8 @@ mfi_tbolt_init_desc_pool(struct mfi_softc *sc, uint8_t* mem_location,
     	sc->sg_frame_busaddr = sc->reply_frame_busaddr + offset;
     	/* initialize the last_reply_idx to 0 */
     	sc->last_reply_idx = 0;
    +	MFI_WRITE4(sc, MFI_RFPI, sc->mfi_max_fw_cmds - 1);
    +	MFI_WRITE4(sc, MFI_RPI, sc->last_reply_idx);
     	offset = (sc->sg_frame_busaddr + (MEGASAS_MAX_SZ_CHAIN_FRAME *
     	    sc->mfi_max_fw_cmds)) - sc->mfi_tb_busaddr;
     	if (offset > tbolt_contg_length)
    @@ -327,30 +336,35 @@ int
     mfi_tbolt_init_MFI_queue(struct mfi_softc *sc)
     {
     	struct MPI2_IOC_INIT_REQUEST   *mpi2IocInit;
    -	struct mfi_init_frame	*mfi_init;
    +	struct mfi_init_frame		*mfi_init;
     	uintptr_t			offset = 0;
     	bus_addr_t			phyAddress;
     	MFI_ADDRESS			*mfiAddressTemp;
    -	struct mfi_command *cm;
    +	struct mfi_command		*cm, cmd_tmp;
     	int error;
     
    -	mpi2IocInit = (struct MPI2_IOC_INIT_REQUEST *)sc->mfi_tb_ioc_init_desc;
    +	mtx_assert(&sc->mfi_io_lock, MA_OWNED);
    +
     	/* Check if initialization is already completed */
     	if (sc->MFA_enabled) {
    +		device_printf(sc->mfi_dev, "tbolt_init already initialised!\n");
     		return 1;
     	}
     
    -	mtx_lock(&sc->mfi_io_lock);
     	if ((cm = mfi_dequeue_free(sc)) == NULL) {
    -		mtx_unlock(&sc->mfi_io_lock);
    +		device_printf(sc->mfi_dev, "tbolt_init failed to get command "
    +		    " entry!\n");
     		return (EBUSY);
     	}
    +
    +	cmd_tmp.cm_frame = cm->cm_frame;
    +	cmd_tmp.cm_frame_busaddr = cm->cm_frame_busaddr;
    +	cmd_tmp.cm_dmamap = cm->cm_dmamap;
    +
     	cm->cm_frame = (union mfi_frame *)((uintptr_t)sc->mfi_tb_init);
     	cm->cm_frame_busaddr = sc->mfi_tb_init_busaddr;
     	cm->cm_dmamap = sc->mfi_tb_init_dmamap;
     	cm->cm_frame->header.context = 0;
    -	cm->cm_sc = sc;
    -	cm->cm_index = 0;
     
     	/*
     	 * Abuse the SG list area of the frame to hold the init_qinfo
    @@ -358,6 +372,7 @@ mfi_tbolt_init_MFI_queue(struct mfi_softc *sc)
     	 */
     	mfi_init = &cm->cm_frame->init;
     
    +	mpi2IocInit = (struct MPI2_IOC_INIT_REQUEST *)sc->mfi_tb_ioc_init_desc;
     	bzero(mpi2IocInit, sizeof(struct MPI2_IOC_INIT_REQUEST));
     	mpi2IocInit->Function  = MPI2_FUNCTION_IOC_INIT;
     	mpi2IocInit->WhoInit   = MPI2_WHOINIT_HOST_DRIVER;
    @@ -411,23 +426,25 @@ mfi_tbolt_init_MFI_queue(struct mfi_softc *sc)
     	if ((error = mfi_mapcmd(sc, cm)) != 0) {
     		device_printf(sc->mfi_dev, "failed to send IOC init2 "
     		    "command %d at %lx\n", error, (long)cm->cm_frame_busaddr);
    -		mfi_release_command(cm);
    -		mtx_unlock(&sc->mfi_io_lock);
    -		return (error);
    +		goto out;
     	}
    -	mfi_release_command(cm);
    -	mtx_unlock(&sc->mfi_io_lock);
     
    -	if (mfi_init->header.cmd_status == 0) {
    +	if (mfi_init->header.cmd_status == MFI_STAT_OK) {
     		sc->MFA_enabled = 1;
    -	}
    -	else {
    -		device_printf(sc->mfi_dev, "Init command Failed %x\n",
    +	} else {
    +		device_printf(sc->mfi_dev, "Init command Failed %#x\n",
     		    mfi_init->header.cmd_status);
    -		return 1;
    +		error = mfi_init->header.cmd_status;
    +		goto out;
     	}
     
    -	return 0;
    +out:
    +	cm->cm_frame = cmd_tmp.cm_frame;
    +	cm->cm_frame_busaddr = cmd_tmp.cm_frame_busaddr;
    +	cm->cm_dmamap = cmd_tmp.cm_dmamap;
    +	mfi_release_command(cm);
    +
    +	return (error);
     
     }
     
    @@ -447,13 +464,21 @@ mfi_tbolt_alloc_cmd(struct mfi_softc *sc)
     	sc->request_desc_pool = malloc(sizeof(
     	    union mfi_mpi2_request_descriptor) * sc->mfi_max_fw_cmds,
     	    M_MFIBUF, M_NOWAIT|M_ZERO);
    +
    +	if (sc->request_desc_pool == NULL) {
    +		device_printf(sc->mfi_dev, "Could not alloc "
    +		    "memory for request_desc_pool\n");
    +		return (ENOMEM);
    +	}
    +
     	sc->mfi_cmd_pool_tbolt = malloc(sizeof(struct mfi_cmd_tbolt*)
     	    * sc->mfi_max_fw_cmds, M_MFIBUF, M_NOWAIT|M_ZERO);
     
    -	if (!sc->mfi_cmd_pool_tbolt) {
    -		device_printf(sc->mfi_dev, "out of memory. Could not alloc "
    -		    "memory for cmd_list_fusion\n");
    -		return 1;
    +	if (sc->mfi_cmd_pool_tbolt == NULL) {
    +		free(sc->request_desc_pool, M_MFIBUF);
    +		device_printf(sc->mfi_dev, "Could not alloc "
    +		    "memory for cmd_pool_tbolt\n");
    +		return (ENOMEM);
     	}
     
     	for (i = 0; i < sc->mfi_max_fw_cmds; i++) {
    @@ -461,20 +486,24 @@ mfi_tbolt_alloc_cmd(struct mfi_softc *sc)
     		    struct mfi_cmd_tbolt),M_MFIBUF, M_NOWAIT|M_ZERO);
     
     		if (!sc->mfi_cmd_pool_tbolt[i]) {
    -			device_printf(sc->mfi_dev, "Could not alloc cmd list "
    -			    "fusion\n");
    +			device_printf(sc->mfi_dev, "Could not alloc "
    +			    "cmd_pool_tbolt entry\n");
     
     			for (j = 0; j < i; j++)
     				free(sc->mfi_cmd_pool_tbolt[j], M_MFIBUF);
     
    +			free(sc->request_desc_pool, M_MFIBUF);
    +			sc->request_desc_pool = NULL;
     			free(sc->mfi_cmd_pool_tbolt, M_MFIBUF);
     			sc->mfi_cmd_pool_tbolt = NULL;
    +
    +			return (ENOMEM);
     		}
     	}
     
     	/*
     	 * The first 256 bytes (SMID 0) is not used. Don't add to the cmd
    -	 *list
    +	 * list
     	 */
     	io_req_base = sc->request_message_pool_align
     		+ MEGASAS_THUNDERBOLT_NEW_MSG_SIZE;
    @@ -520,7 +549,8 @@ mfi_tbolt_reset(struct mfi_softc *sc)
     
     	if (sc->mfi_flags & MFI_FLAGS_TBOLT) {
     		fw_state = sc->mfi_read_fw_status(sc);
    -		if ((fw_state & MFI_FWSTATE_FAULT) == MFI_FWSTATE_FAULT) {
    +		if ((fw_state & MFI_FWSTATE_FAULT) == MFI_FWSTATE_FAULT ||
    +		    mfi_fw_reset_test) {
     			if ((sc->disableOnlineCtrlReset == 0)
     			    && (sc->adpreset == 0)) {
     				device_printf(sc->mfi_dev, "Adapter RESET "
    @@ -554,8 +584,7 @@ mfi_intr_tbolt(void *arg)
     		return;
     	mtx_lock(&sc->mfi_io_lock);
     	mfi_tbolt_complete_cmd(sc);
    -	if (sc->mfi_flags & MFI_FLAGS_QFRZN)
    -		sc->mfi_flags &= ~MFI_FLAGS_QFRZN;
    +	sc->mfi_flags &= ~MFI_FLAGS_QFRZN;
     	mfi_startio(sc);
     	mtx_unlock(&sc->mfi_io_lock);
     	return;
    @@ -573,58 +602,63 @@ map_tbolt_cmd_status(struct mfi_command *mfi_cmd, uint8_t status,
         uint8_t ext_status)
     {
     	switch (status) {
    -		case MFI_STAT_OK:
    -			mfi_cmd->cm_frame->header.cmd_status = MFI_STAT_OK;
    -			mfi_cmd->cm_frame->dcmd.header.cmd_status = MFI_STAT_OK;
    -			mfi_cmd->cm_error = MFI_STAT_OK;
    -			break;
    +	case MFI_STAT_OK:
    +		mfi_cmd->cm_frame->header.cmd_status = MFI_STAT_OK;
    +		mfi_cmd->cm_frame->dcmd.header.cmd_status = MFI_STAT_OK;
    +		mfi_cmd->cm_error = MFI_STAT_OK;
    +		break;
     
    -		case MFI_STAT_SCSI_IO_FAILED:
    -		case MFI_STAT_LD_INIT_IN_PROGRESS:
    -			mfi_cmd->cm_frame->header.cmd_status = status;
    -			mfi_cmd->cm_frame->header.scsi_status = ext_status;
    -			mfi_cmd->cm_frame->dcmd.header.cmd_status = status;
    -			mfi_cmd->cm_frame->dcmd.header.scsi_status
    -			    = ext_status;
    -			break;
    +	case MFI_STAT_SCSI_IO_FAILED:
    +	case MFI_STAT_LD_INIT_IN_PROGRESS:
    +		mfi_cmd->cm_frame->header.cmd_status = status;
    +		mfi_cmd->cm_frame->header.scsi_status = ext_status;
    +		mfi_cmd->cm_frame->dcmd.header.cmd_status = status;
    +		mfi_cmd->cm_frame->dcmd.header.scsi_status
    +		    = ext_status;
    +		break;
     
    -		case MFI_STAT_SCSI_DONE_WITH_ERROR:
    -			mfi_cmd->cm_frame->header.cmd_status = ext_status;
    -			mfi_cmd->cm_frame->dcmd.header.cmd_status = ext_status;
    -			break;
    +	case MFI_STAT_SCSI_DONE_WITH_ERROR:
    +		mfi_cmd->cm_frame->header.cmd_status = ext_status;
    +		mfi_cmd->cm_frame->dcmd.header.cmd_status = ext_status;
    +		break;
     
    -		case MFI_STAT_LD_OFFLINE:
    -		case MFI_STAT_DEVICE_NOT_FOUND:
    -			mfi_cmd->cm_frame->header.cmd_status = status;
    -			mfi_cmd->cm_frame->dcmd.header.cmd_status = status;
    -			break;
    +	case MFI_STAT_LD_OFFLINE:
    +	case MFI_STAT_DEVICE_NOT_FOUND:
    +		mfi_cmd->cm_frame->header.cmd_status = status;
    +		mfi_cmd->cm_frame->dcmd.header.cmd_status = status;
    +		break;
     
    -		default:
    -			mfi_cmd->cm_frame->header.cmd_status = status;
    -			mfi_cmd->cm_frame->dcmd.header.cmd_status = status;
    -			break;
    -		}
    +	default:
    +		mfi_cmd->cm_frame->header.cmd_status = status;
    +		mfi_cmd->cm_frame->dcmd.header.cmd_status = status;
    +		break;
    +	}
     }
     
     /*
      * mfi_tbolt_return_cmd -	Return a cmd to free command pool
      * @instance:		Adapter soft state
    - * @cmd:		Command packet to be returned to free command pool
    + * @tbolt_cmd:		Tbolt command packet to be returned to free command pool
    + * @mfi_cmd:		Oning MFI command packe
      */
    -static inline void
    -mfi_tbolt_return_cmd(struct mfi_softc *sc, struct mfi_cmd_tbolt *cmd)
    +void
    +mfi_tbolt_return_cmd(struct mfi_softc *sc, struct mfi_cmd_tbolt *tbolt_cmd,
    +    struct mfi_command *mfi_cmd)
     {
     	mtx_assert(&sc->mfi_io_lock, MA_OWNED);
     
    -	cmd->sync_cmd_idx = sc->mfi_max_fw_cmds;
    -	TAILQ_INSERT_TAIL(&sc->mfi_cmd_tbolt_tqh, cmd, next);
    +	mfi_cmd->cm_flags &= ~MFI_CMD_TBOLT;
    +	mfi_cmd->cm_extra_frames = 0;
    +	tbolt_cmd->sync_cmd_idx = sc->mfi_max_fw_cmds;
    +
    +	TAILQ_INSERT_TAIL(&sc->mfi_cmd_tbolt_tqh, tbolt_cmd, next);
     }
     
     void
     mfi_tbolt_complete_cmd(struct mfi_softc *sc)
     {
     	struct mfi_mpi2_reply_header *desc, *reply_desc;
    -	struct mfi_command *cmd_mfi, *cmd_mfi_check;	/* For MFA Cmds */
    +	struct mfi_command *cmd_mfi;	/* For MFA Cmds */
     	struct mfi_cmd_tbolt *cmd_tbolt;
     	uint16_t smid;
     	uint8_t reply_descript_type;
    @@ -632,14 +666,17 @@ mfi_tbolt_complete_cmd(struct mfi_softc *sc)
     	uint32_t status, extStatus;
     	uint16_t num_completed;
     	union desc_value val;
    +	mtx_assert(&sc->mfi_io_lock, MA_OWNED);
     
     	desc = (struct mfi_mpi2_reply_header *)
     		((uintptr_t)sc->reply_frame_pool_align
     		+ sc->last_reply_idx * sc->reply_size);
     	reply_desc = desc;
     
    -	if (!reply_desc)
    +	if (reply_desc == NULL) {
     		device_printf(sc->mfi_dev, "reply desc is NULL!!\n");
    +		return;
    +	}
     
     	reply_descript_type = reply_desc->ReplyFlags
     	     & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
    @@ -652,13 +689,18 @@ mfi_tbolt_complete_cmd(struct mfi_softc *sc)
     	/* Read Reply descriptor */
     	while ((val.u.low != 0xFFFFFFFF) && (val.u.high != 0xFFFFFFFF)) {
     		smid = reply_desc->SMID;
    -		if (!smid || smid > sc->mfi_max_fw_cmds + 1) {
    -			device_printf(sc->mfi_dev, "smid is %x. Cannot "
    -			    "proceed. Returning \n", smid);
    -			return;
    +		if (smid == 0 || smid > sc->mfi_max_fw_cmds) {
    +			device_printf(sc->mfi_dev, "smid is %d cannot "
    +			    "proceed - skipping\n", smid);
    +			goto next;
     		}
    -
     		cmd_tbolt = sc->mfi_cmd_pool_tbolt[smid - 1];
    +		if (cmd_tbolt->sync_cmd_idx == sc->mfi_max_fw_cmds) {
    +			device_printf(sc->mfi_dev, "cmd_tbolt %p "
    +			    "has invalid sync_cmd_idx=%d - skipping\n",
    +			    cmd_tbolt, cmd_tbolt->sync_cmd_idx);
    +			goto next;
    +		}
     		cmd_mfi = &sc->mfi_commands[cmd_tbolt->sync_cmd_idx];
     		scsi_io_req = cmd_tbolt->io_request;
     
    @@ -666,33 +708,30 @@ mfi_tbolt_complete_cmd(struct mfi_softc *sc)
     		extStatus = cmd_mfi->cm_frame->dcmd.header.scsi_status;
     		map_tbolt_cmd_status(cmd_mfi, status, extStatus);
     
    -		if (cmd_mfi->cm_flags & MFI_CMD_SCSI &&
    +		/* mfi_tbolt_return_cmd is handled by mfi complete / return */
    +		if ((cmd_mfi->cm_flags & MFI_CMD_SCSI) != 0 &&
     		    (cmd_mfi->cm_flags & MFI_CMD_POLLED) != 0) {
     			/* polled LD/SYSPD IO command */
    -			mfi_tbolt_return_cmd(sc, cmd_tbolt);
     			/* XXX mark okay for now DJA */
     			cmd_mfi->cm_frame->header.cmd_status = MFI_STAT_OK;
    -		} else {
     
    +		} else {
     			/* remove command from busy queue if not polled */
    -			TAILQ_FOREACH(cmd_mfi_check, &sc->mfi_busy, cm_link) {
    -				if (cmd_mfi_check == cmd_mfi) {
    -					mfi_remove_busy(cmd_mfi);
    -					break;
    -				}
    -			}
    +			if ((cmd_mfi->cm_flags & MFI_ON_MFIQ_BUSY) != 0)
    +				mfi_remove_busy(cmd_mfi);
     
     			/* complete the command */
     			mfi_complete(sc, cmd_mfi);
    -			mfi_tbolt_return_cmd(sc, cmd_tbolt);
     		}
     
    +next:
     		sc->last_reply_idx++;
     		if (sc->last_reply_idx >= sc->mfi_max_fw_cmds) {
     			MFI_WRITE4(sc, MFI_RPI, sc->last_reply_idx);
     			sc->last_reply_idx = 0;
     		}
    -		/*set it back to all 0xfff.*/
    +
    +		/* Set it back to all 0xfff */
     		((union mfi_mpi2_reply_descriptor*)desc)->words =
     			~((uint64_t)0x00);
     
    @@ -728,17 +767,23 @@ mfi_tbolt_complete_cmd(struct mfi_softc *sc)
      */
     
     struct mfi_cmd_tbolt *
    -mfi_tbolt_get_cmd(struct mfi_softc *sc)
    +mfi_tbolt_get_cmd(struct mfi_softc *sc, struct mfi_command *mfi_cmd)
     {
     	struct mfi_cmd_tbolt *cmd = NULL;
     
     	mtx_assert(&sc->mfi_io_lock, MA_OWNED);
     
    -	cmd = TAILQ_FIRST(&sc->mfi_cmd_tbolt_tqh);
    +	if ((cmd = TAILQ_FIRST(&sc->mfi_cmd_tbolt_tqh)) == NULL)
    +		return (NULL);
     	TAILQ_REMOVE(&sc->mfi_cmd_tbolt_tqh, cmd, next);
     	memset((uint8_t *)cmd->sg_frame, 0, MEGASAS_MAX_SZ_CHAIN_FRAME);
     	memset((uint8_t *)cmd->io_request, 0,
     	    MEGASAS_THUNDERBOLT_NEW_MSG_SIZE);
    +
    +	cmd->sync_cmd_idx = mfi_cmd->cm_index;
    +	mfi_cmd->cm_extra_frames = cmd->index; /* Frame count used as SMID */
    +	mfi_cmd->cm_flags |= MFI_CMD_TBOLT;
    +
     	return cmd;
     }
     
    @@ -767,11 +812,9 @@ mfi_build_mpt_pass_thru(struct mfi_softc *sc, struct mfi_command *mfi_cmd)
     	struct mfi_mpi2_request_raid_scsi_io *io_req;
     	struct mfi_cmd_tbolt *cmd;
     
    -	cmd = mfi_tbolt_get_cmd(sc);
    +	cmd = mfi_tbolt_get_cmd(sc, mfi_cmd);
     	if (!cmd)
     		return EBUSY;
    -	mfi_cmd->cm_extra_frames = cmd->index; /* Frame count used as SMID */
    -	cmd->sync_cmd_idx = mfi_cmd->cm_index;
     	io_req = cmd->io_request;
     	mpi25_ieee_chain = (MPI25_IEEE_SGE_CHAIN64 *)&io_req->SGL.IeeeChain;
     
    @@ -980,16 +1023,21 @@ mfi_build_and_issue_cmd(struct mfi_softc *sc, struct mfi_command *mfi_cmd)
     	struct mfi_cmd_tbolt *cmd;
     	union mfi_mpi2_request_descriptor *req_desc = NULL;
     	uint16_t index;
    -	cmd = mfi_tbolt_get_cmd(sc);
    -	if (!cmd)
    -		return NULL;
    -	mfi_cmd->cm_extra_frames = cmd->index;
    -	cmd->sync_cmd_idx = mfi_cmd->cm_index;
    +	cmd = mfi_tbolt_get_cmd(sc, mfi_cmd);
    +	if (cmd == NULL)
    +		return (NULL);
     
     	index = cmd->index;
     	req_desc = mfi_tbolt_get_request_descriptor(sc, index-1);
    -	if (mfi_tbolt_build_io(sc, mfi_cmd, cmd))
    -		return NULL;
    +	if (req_desc == NULL) {
    +		mfi_tbolt_return_cmd(sc, cmd, mfi_cmd);
    +		return (NULL);
    +	}
    +
    +	if (mfi_tbolt_build_io(sc, mfi_cmd, cmd) != 0) {
    +		mfi_tbolt_return_cmd(sc, cmd, mfi_cmd);
    +		return (NULL);
    +	}
     	req_desc->header.SMID = index;
     	return req_desc;
     }
    @@ -1008,7 +1056,7 @@ mfi_tbolt_build_mpt_cmd(struct mfi_softc *sc, struct mfi_command *cmd)
     	index = cmd->cm_extra_frames;
     
     	req_desc = mfi_tbolt_get_request_descriptor(sc, index - 1);
    -	if (!req_desc)
    +	if (req_desc == NULL)
     		return NULL;
     
     	bzero(req_desc, sizeof(*req_desc));
    @@ -1024,7 +1072,7 @@ mfi_tbolt_send_frame(struct mfi_softc *sc, struct mfi_command *cm)
     	struct mfi_frame_header *hdr;
     	uint8_t *cdb;
     	union mfi_mpi2_request_descriptor *req_desc = NULL;
    -	int tm = MFI_POLL_TIMEOUT_SECS * 1000;
    +	int tm = mfi_polled_cmd_timeout * 1000;
     
     	hdr = &cm->cm_frame->header;
     	cdb = cm->cm_frame->pass.cdb;
    @@ -1058,9 +1106,8 @@ mfi_tbolt_send_frame(struct mfi_softc *sc, struct mfi_command *cm)
     			return 1;
     		}
     	} else if ((req_desc = mfi_tbolt_build_mpt_cmd(sc, cm)) == NULL) {
    -			device_printf(sc->mfi_dev, "Mapping from MFI to MPT "
    -			    "Failed\n");
    -			return 1;
    +		device_printf(sc->mfi_dev, "Mapping from MFI to MPT Failed\n");
    +		return (1);
     	}
     
     	if (cm->cm_flags & MFI_CMD_SCSI) {
    @@ -1078,23 +1125,30 @@ mfi_tbolt_send_frame(struct mfi_softc *sc, struct mfi_command *cm)
     	if ((cm->cm_flags & MFI_CMD_POLLED) == 0)
     		return 0;
     
    -	if (cm->cm_flags & MFI_CMD_SCSI) {
    -		/* check reply queue */
    -		mfi_tbolt_complete_cmd(sc);
    -	}
    -
    -	/* This is a polled command, so busy-wait for it to complete. */
    +	/*
    +	 * This is a polled command, so busy-wait for it to complete.
    +	 *
    +	 * The value of hdr->cmd_status is updated directly by the hardware
    +	 * so there is no garantee that mfi_tbolt_complete_cmd is called
    +	 * prior to this value changing.
    +	 */
     	while (hdr->cmd_status == MFI_STAT_INVALID_STATUS) {
     		DELAY(1000);
     		tm -= 1;
     		if (tm <= 0)
     			break;
     		if (cm->cm_flags & MFI_CMD_SCSI) {
    -			/* check reply queue */
    +			/*
    +			 * Force check reply queue.
    +			 * This ensures that dump works correctly
    +			 */
     			mfi_tbolt_complete_cmd(sc);
     		}
     	}
     
    +	/* ensure the command cleanup has been processed before returning */
    +	mfi_tbolt_complete_cmd(sc);
    +
     	if (hdr->cmd_status == MFI_STAT_INVALID_STATUS) {
     		device_printf(sc->mfi_dev, "Frame %p timed out "
     		    "command 0x%X\n", hdr, cm->cm_frame->dcmd.opcode);
    @@ -1104,9 +1158,10 @@ mfi_tbolt_send_frame(struct mfi_softc *sc, struct mfi_command *cm)
     }
     
     static void
    -mfi_issue_pending_cmds_again (struct mfi_softc *sc)
    +mfi_issue_pending_cmds_again(struct mfi_softc *sc)
     {
     	struct mfi_command *cm, *tmp;
    +	struct mfi_cmd_tbolt *cmd;
     
     	mtx_assert(&sc->mfi_io_lock, MA_OWNED);
     	TAILQ_FOREACH_REVERSE_SAFE(cm, &sc->mfi_busy, BUSYQ, cm_link, tmp) {
    @@ -1119,50 +1174,51 @@ mfi_issue_pending_cmds_again (struct mfi_softc *sc)
     		 * should be performed on the controller
     		 */
     		if (cm->retry_for_fw_reset == 3) {
    -			device_printf(sc->mfi_dev, "megaraid_sas: command %d "
    -			    "was tried multiple times during adapter reset"
    -			    "Shutting down the HBA\n", cm->cm_index);
    +			device_printf(sc->mfi_dev, "megaraid_sas: command %p "
    +			    "index=%d was tried multiple times during adapter "
    +			    "reset - Shutting down the HBA\n", cm, cm->cm_index);
     			mfi_kill_hba(sc);
     			sc->hw_crit_error = 1;
     			return;
     		}
     
    -		if ((cm->cm_flags & MFI_ON_MFIQ_BUSY) != 0) {
    -			struct mfi_cmd_tbolt *cmd;
    -			mfi_remove_busy(cm);
    -			cmd = sc->mfi_cmd_pool_tbolt[cm->cm_extra_frames -
    -			    1 ];
    -			mfi_tbolt_return_cmd(sc, cmd);
    -			if ((cm->cm_flags & MFI_ON_MFIQ_MASK) == 0) {
    -				if (cm->cm_frame->dcmd.opcode !=
    -				    MFI_DCMD_CTRL_EVENT_WAIT) {
    -					device_printf(sc->mfi_dev,
    -					    "APJ ****requeue command %d \n",
    -					    cm->cm_index);
    -					mfi_requeue_ready(cm);
    -				}
    +		mfi_remove_busy(cm);
    +		if ((cm->cm_flags & MFI_CMD_TBOLT) != 0) {
    +			if (cm->cm_extra_frames != 0 && cm->cm_extra_frames <=
    +			    sc->mfi_max_fw_cmds) {
    +				cmd = sc->mfi_cmd_pool_tbolt[cm->cm_extra_frames - 1];
    +				mfi_tbolt_return_cmd(sc, cmd, cm);
    +			} else {
    +				device_printf(sc->mfi_dev,
    +				    "Invalid extra_frames: %d detected\n",
    +				    cm->cm_extra_frames);
     			}
    -			else
    -				mfi_release_command(cm);
     		}
    +
    +		if (cm->cm_frame->dcmd.opcode != MFI_DCMD_CTRL_EVENT_WAIT) {
    +			device_printf(sc->mfi_dev,
    +			    "APJ ****requeue command %p index=%d\n",
    +			    cm, cm->cm_index);
    +			mfi_requeue_ready(cm);
    +		} else
    +			mfi_release_command(cm);
     	}
     	mfi_startio(sc);
     }
     
     static void
    -mfi_kill_hba (struct mfi_softc *sc)
    +mfi_kill_hba(struct mfi_softc *sc)
     {
     	if (sc->mfi_flags & MFI_FLAGS_TBOLT)
    -		MFI_WRITE4 (sc, 0x00,MFI_STOP_ADP);
    +		MFI_WRITE4(sc, 0x00, MFI_STOP_ADP);
     	else
    -		MFI_WRITE4 (sc, MFI_IDB,MFI_STOP_ADP);
    +		MFI_WRITE4(sc, MFI_IDB, MFI_STOP_ADP);
     }
     
     static void
     mfi_process_fw_state_chg_isr(void *arg)
     {
     	struct mfi_softc *sc= (struct mfi_softc *)arg;
    -	struct mfi_cmd_tbolt *cmd;
     	int error, status;
     
     	if (sc->adpreset == 1) {
    @@ -1191,27 +1247,32 @@ mfi_process_fw_state_chg_isr(void *arg)
     			device_printf(sc->mfi_dev, "controller is not in "
     			    "ready state\n");
     			mfi_kill_hba(sc);
    -			sc->hw_crit_error= 1;
    -			return ;
    +			sc->hw_crit_error = 1;
    +			return;
    +		}
    +		if ((error = mfi_tbolt_init_MFI_queue(sc)) != 0) {
    +			device_printf(sc->mfi_dev, "Failed to initialise MFI "
    +			    "queue\n");
    +			mfi_kill_hba(sc);
    +			sc->hw_crit_error = 1;
    +			return;
     		}
    -		mtx_unlock(&sc->mfi_io_lock);
    -		if ((error = mfi_tbolt_init_MFI_queue(sc)) != 0)
    -				return;
     
    -		mtx_lock(&sc->mfi_io_lock);
    +		/* Init last reply index and max */
    +		MFI_WRITE4(sc, MFI_RFPI, sc->mfi_max_fw_cmds - 1);
    +		MFI_WRITE4(sc, MFI_RPI, sc->last_reply_idx);
     
     		sc->mfi_enable_intr(sc);
     		sc->adpreset = 0;
    -		free(sc->mfi_aen_cm->cm_data, M_MFIBUF);
    -		mfi_remove_busy(sc->mfi_aen_cm);
    -		cmd = sc->mfi_cmd_pool_tbolt[sc->mfi_aen_cm->cm_extra_frames
    -		    - 1];
    -		mfi_tbolt_return_cmd(sc, cmd);
    -		if (sc->mfi_aen_cm) {
    +		if (sc->mfi_aen_cm != NULL) {
    +			free(sc->mfi_aen_cm->cm_data, M_MFIBUF);
    +			mfi_remove_busy(sc->mfi_aen_cm);
     			mfi_release_command(sc->mfi_aen_cm);
     			sc->mfi_aen_cm = NULL;
     		}
    -		if (sc->mfi_map_sync_cm) {
    +
    +		if (sc->mfi_map_sync_cm != NULL) {
    +			mfi_remove_busy(sc->mfi_map_sync_cm);
     			mfi_release_command(sc->mfi_map_sync_cm);
     			sc->mfi_map_sync_cm = NULL;
     		}
    @@ -1224,11 +1285,12 @@ mfi_process_fw_state_chg_isr(void *arg)
     		 */
     		if (!sc->hw_crit_error) {
     			/*
    -			 * Initiate AEN (Asynchronous Event Notification)
    +			 * Initiate AEN (Asynchronous Event Notification) &
    +			 * Sync Map
     			 */
    -			mtx_unlock(&sc->mfi_io_lock);
     			mfi_aen_setup(sc, sc->last_seq_num);
    -			mtx_lock(&sc->mfi_io_lock);
    +			mfi_tbolt_sync_map_info(sc);
    +
     			sc->issuepend_done = 1;
     			device_printf(sc->mfi_dev, "second stage of reset "
     			    "complete, FW is ready now.\n");
    @@ -1278,25 +1340,27 @@ void
     mfi_tbolt_sync_map_info(struct mfi_softc *sc)
     {
     	int error = 0, i;
    -	struct mfi_command *cmd;
    -	struct mfi_dcmd_frame *dcmd;
    +	struct mfi_command *cmd = NULL;
    +	struct mfi_dcmd_frame *dcmd = NULL;
     	uint32_t context = 0;
    -	union mfi_ld_ref *ld_sync;
    +	union mfi_ld_ref *ld_sync = NULL;
     	size_t ld_size;
     	struct mfi_frame_header *hdr;
     	struct mfi_command *cm = NULL;
     	struct mfi_ld_list *list = NULL;
     
    +	mtx_assert(&sc->mfi_io_lock, MA_OWNED);
    +
     	if (sc->mfi_map_sync_cm != NULL || sc->cm_map_abort)
     		return;
     
    -	mtx_lock(&sc->mfi_io_lock);
     	error = mfi_dcmd_command(sc, &cm, MFI_DCMD_LD_GET_LIST,
     	    (void **)&list, sizeof(*list));
     	if (error)
     		goto out;
     
     	cm->cm_flags = MFI_CMD_POLLED | MFI_CMD_DATAIN;
    +
     	if (mfi_wait_command(sc, cm) != 0) {
     		device_printf(sc->mfi_dev, "Failed to get device listing\n");
     		goto out;
    @@ -1310,18 +1374,15 @@ mfi_tbolt_sync_map_info(struct mfi_softc *sc)
     	}
     
     	ld_size = sizeof(*ld_sync) * list->ld_count;
    -	mtx_unlock(&sc->mfi_io_lock);
     	ld_sync = (union mfi_ld_ref *) malloc(ld_size, M_MFIBUF,
    -	     M_WAITOK | M_ZERO);
    +	     M_NOWAIT | M_ZERO);
     	if (ld_sync == NULL) {
     		device_printf(sc->mfi_dev, "Failed to allocate sync\n");
     		goto out;
     	}
    -	for (i = 0; i < list->ld_count; i++) {
    +	for (i = 0; i < list->ld_count; i++)
     		ld_sync[i].ref = list->ld_list[i].ld.ref;
    -	}
     
    -	mtx_lock(&sc->mfi_io_lock);
     	if ((cmd = mfi_dequeue_free(sc)) == NULL) {
     		device_printf(sc->mfi_dev, "Failed to get command\n");
     		free(ld_sync, M_MFIBUF);
    @@ -1357,7 +1418,7 @@ mfi_tbolt_sync_map_info(struct mfi_softc *sc)
     		device_printf(sc->mfi_dev, "failed to send map sync\n");
     		free(ld_sync, M_MFIBUF);
     		sc->mfi_map_sync_cm = NULL;
    -		mfi_requeue_ready(cmd);
    +		mfi_release_command(cmd);
     		goto out;
     	}
     
    @@ -1366,7 +1427,6 @@ out:
     		free(list, M_MFIBUF);
     	if (cm)
     		mfi_release_command(cm);
    -	mtx_unlock(&sc->mfi_io_lock);
     }
     
     static void
    @@ -1391,14 +1451,13 @@ mfi_sync_map_complete(struct mfi_command *cm)
     	}
     
     	free(cm->cm_data, M_MFIBUF);
    -	sc->mfi_map_sync_cm = NULL;
     	wakeup(&sc->mfi_map_sync_cm);
    +	sc->mfi_map_sync_cm = NULL;
     	mfi_release_command(cm);
     
     	/* set it up again so the driver can catch more events */
    -	if (!aborted) {
    +	if (!aborted)
     		mfi_queue_map_sync(sc);
    -	}
     }
     
     static void
    @@ -1414,5 +1473,7 @@ mfi_handle_map_sync(void *context, int pending)
     	struct mfi_softc *sc;
     
     	sc = context;
    +	mtx_lock(&sc->mfi_io_lock);
     	mfi_tbolt_sync_map_info(sc);
    +	mtx_unlock(&sc->mfi_io_lock);
     }
    diff --git a/sys/dev/mfi/mfireg.h b/sys/dev/mfi/mfireg.h
    index dab9cf7baa1..52ddafead09 100644
    --- a/sys/dev/mfi/mfireg.h
    +++ b/sys/dev/mfi/mfireg.h
    @@ -86,6 +86,7 @@ __FBSDID("$FreeBSD$");
     *  ThunderBolt specific Register
     */
     
    +#define MFI_RFPI	0x48 		/* reply_free_post_host_index */
     #define MFI_RPI		0x6c 		/* reply_post_host_index */
     #define MFI_ILQP 	0xc0		/* inbound_low_queue_port */
     #define MFI_IHQP 	0xc4		/* inbound_high_queue_port */
    @@ -259,6 +260,13 @@ typedef enum {
     #define MFI_FRAME_DIR_READ			0x0010
     #define MFI_FRAME_DIR_BOTH			0x0018
     #define MFI_FRAME_IEEE_SGL			0x0020
    +#define MFI_FRAME_FMT "\20" \
    +    "\1NOPOST" \
    +    "\2SGL64" \
    +    "\3SENSE64" \
    +    "\4WRITE" \
    +    "\5READ" \
    +    "\6IEEESGL"
     
     /* ThunderBolt Specific */
     
    @@ -456,8 +464,8 @@ typedef enum {
     #define MFI_FRAME_SIZE		64
     #define MFI_MBOX_SIZE		12
     
    -/* Firmware flashing can take 40s */
    -#define MFI_POLL_TIMEOUT_SECS	50
    +/* Firmware flashing can take 50+ seconds */
    +#define MFI_POLL_TIMEOUT_SECS	60
     
     /* Allow for speedier math calculations */
     #define MFI_SECTOR_LEN		512
    diff --git a/sys/dev/mfi/mfivar.h b/sys/dev/mfi/mfivar.h
    index bb2a324b514..664ede96ad7 100644
    --- a/sys/dev/mfi/mfivar.h
    +++ b/sys/dev/mfi/mfivar.h
    @@ -102,12 +102,25 @@ struct mfi_command {
     #define MFI_CMD_DATAOUT		(1<<2)
     #define MFI_CMD_COMPLETED	(1<<3)
     #define MFI_CMD_POLLED		(1<<4)
    -#define MFI_ON_MFIQ_FREE	(1<<5)
    -#define MFI_ON_MFIQ_READY	(1<<6)
    -#define MFI_ON_MFIQ_BUSY	(1<<7)
    -#define MFI_ON_MFIQ_MASK	((1<<5)|(1<<6)|(1<<7))
    -#define MFI_CMD_SCSI		(1<<8)
    -#define MFI_CMD_CCB		(1<<9)
    +#define MFI_CMD_SCSI		(1<<5)
    +#define MFI_CMD_CCB		(1<<6)
    +#define MFI_CMD_TBOLT		(1<<7)
    +#define MFI_ON_MFIQ_FREE	(1<<8)
    +#define MFI_ON_MFIQ_READY	(1<<9)
    +#define MFI_ON_MFIQ_BUSY	(1<<10)
    +#define MFI_ON_MFIQ_MASK	(MFI_ON_MFIQ_FREE | MFI_ON_MFIQ_READY| \
    +    MFI_ON_MFIQ_BUSY)
    +#define MFI_CMD_FLAGS_FMT	"\20" \
    +    "\1MAPPED" \
    +    "\2DATAIN" \
    +    "\3DATAOUT" \
    +    "\4COMPLETED" \
    +    "\5POLLED" \
    +    "\6SCSI" \
    +    "\7TBOLT" \
    +    "\10Q_FREE" \
    +    "\11Q_READY" \
    +    "\12Q_BUSY"
     	uint8_t			retry_for_fw_reset;
     	void			(* cm_complete)(struct mfi_command *cm);
     	void			*cm_private;
    @@ -267,10 +280,6 @@ struct mfi_softc {
     	 * recover completed commands.
     	 */
     	struct mfi_command		*mfi_commands;
    -	/*
    -	 * How many commands were actually allocated
    -	 */
    -	int				mfi_total_cmds;
     	/*
     	 * How many commands the firmware can handle.  Also how big the reply
     	 * queue is, minus 1.
    @@ -470,9 +479,8 @@ extern int mfi_build_cdb(int, uint8_t, u_int64_t, u_int32_t, uint8_t *);
     	mfi_enqueue_ ## name (struct mfi_command *cm)			\
     	{								\
     		if ((cm->cm_flags & MFI_ON_MFIQ_MASK) != 0) {		\
    -			printf("command %p is on another queue, "	\
    +			panic("command %p is on another queue, "	\
     			    "flags = %#x\n", cm, cm->cm_flags);		\
    -			panic("command is on another queue");		\
     		}							\
     		TAILQ_INSERT_TAIL(&cm->cm_sc->mfi_ ## name, cm, cm_link); \
     		cm->cm_flags |= MFI_ON_ ## index;			\
    @@ -482,9 +490,8 @@ extern int mfi_build_cdb(int, uint8_t, u_int64_t, u_int32_t, uint8_t *);
     	mfi_requeue_ ## name (struct mfi_command *cm)			\
     	{								\
     		if ((cm->cm_flags & MFI_ON_MFIQ_MASK) != 0) {		\
    -			printf("command %p is on another queue, "	\
    +			panic("command %p is on another queue, "	\
     			    "flags = %#x\n", cm, cm->cm_flags);		\
    -			panic("command is on another queue");		\
     		}							\
     		TAILQ_INSERT_HEAD(&cm->cm_sc->mfi_ ## name, cm, cm_link); \
     		cm->cm_flags |= MFI_ON_ ## index;			\
    @@ -497,10 +504,9 @@ extern int mfi_build_cdb(int, uint8_t, u_int64_t, u_int32_t, uint8_t *);
     									\
     		if ((cm = TAILQ_FIRST(&sc->mfi_ ## name)) != NULL) {	\
     			if ((cm->cm_flags & MFI_ON_ ## index) == 0) {	\
    -				printf("command %p not in queue, "	\
    +				panic("command %p not in queue, "	\
     				    "flags = %#x, bit = %#x\n", cm,	\
     				    cm->cm_flags, MFI_ON_ ## index);	\
    -				panic("command not in queue");		\
     			}						\
     			TAILQ_REMOVE(&sc->mfi_ ## name, cm, cm_link);	\
     			cm->cm_flags &= ~MFI_ON_ ## index;		\
    @@ -512,10 +518,9 @@ extern int mfi_build_cdb(int, uint8_t, u_int64_t, u_int32_t, uint8_t *);
     	mfi_remove_ ## name (struct mfi_command *cm)			\
     	{								\
     		if ((cm->cm_flags & MFI_ON_ ## index) == 0) {		\
    -			printf("command %p not in queue, flags = %#x, " \
    +			panic("command %p not in queue, flags = %#x, " \
     			    "bit = %#x\n", cm, cm->cm_flags,		\
     			    MFI_ON_ ## index);				\
    -			panic("command not in queue");			\
     		}							\
     		TAILQ_REMOVE(&cm->cm_sc->mfi_ ## name, cm, cm_link);	\
     		cm->cm_flags &= ~MFI_ON_ ## index;			\
    @@ -608,7 +613,8 @@ SYSCTL_DECL(_hw_mfi);
     #ifdef MFI_DEBUG
     extern void mfi_print_cmd(struct mfi_command *cm);
     extern void mfi_dump_cmds(struct mfi_softc *sc);
    -extern void mfi_validate_sg(struct mfi_softc *, struct mfi_command *, const char *, int );
    +extern void mfi_validate_sg(struct mfi_softc *, struct mfi_command *,
    +    const char *, int);
     #define MFI_PRINT_CMD(cm)	mfi_print_cmd(cm)
     #define MFI_DUMP_CMDS(sc)	mfi_dump_cmds(sc)
     #define MFI_VALIDATE_CMD(sc, cm) mfi_validate_sg(sc, cm, __FUNCTION__, __LINE__)
    @@ -618,6 +624,8 @@ extern void mfi_validate_sg(struct mfi_softc *, struct mfi_command *, const char
     #define MFI_VALIDATE_CMD(sc, cm)
     #endif
     
    -extern void mfi_release_command(struct mfi_command *cm);
    +extern void mfi_release_command(struct mfi_command *);
    +extern void mfi_tbolt_return_cmd(struct mfi_softc *,
    +    struct mfi_cmd_tbolt *, struct mfi_command *);
     
     #endif /* _MFIVAR_H */
    
    From 085c63842092befa6b3c3e3fdc8102ca74bac466 Mon Sep 17 00:00:00 2001
    From: Benno Rice 
    Date: Wed, 27 Feb 2013 03:43:16 +0000
    Subject: [PATCH 0443/1476] Fix typo in EFI GPT GUID.
    
    ---
     sbin/geom/class/part/gpart.8 | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/sbin/geom/class/part/gpart.8 b/sbin/geom/class/part/gpart.8
    index 8843e532495..ef83daa78b5 100644
    --- a/sbin/geom/class/part/gpart.8
    +++ b/sbin/geom/class/part/gpart.8
    @@ -583,7 +583,7 @@ The system partition for computers that use the Extensible Firmware
     Interface (EFI).
     In such cases, the GPT partitioning scheme is used and the
     actual partition type for the system partition can also be specified as
    -.Qq Li "!c12a7328-f81f-11d2-ba4b-00a0c93ec93ab" .
    +.Qq Li "!c12a7328-f81f-11d2-ba4b-00a0c93ec93b" .
     .It Cm freebsd
     A
     .Fx
    
    From ee563d630b65f71d2d1a2dd7c084040c945d1be0 Mon Sep 17 00:00:00 2001
    From: Adrian Chadd 
    Date: Wed, 27 Feb 2013 04:33:06 +0000
    Subject: [PATCH 0444/1476] I give up - just throw the EWMA update into the
     normal update_stats() routine.
    
    There were still corner cases where the EWMA update stats are being
    called on a rix which didn't have an intermediary stats update; thus
    no packets were counted against it.  Sigh.
    
    This should fix the crashes I've been seeing on recent -HEAD.
    ---
     sys/dev/ath/ath_rate/sample/sample.c | 132 ++++++---------------------
     1 file changed, 27 insertions(+), 105 deletions(-)
    
    diff --git a/sys/dev/ath/ath_rate/sample/sample.c b/sys/dev/ath/ath_rate/sample/sample.c
    index a7d6af6b20f..b3f82fa9509 100644
    --- a/sys/dev/ath/ath_rate/sample/sample.c
    +++ b/sys/dev/ath/ath_rate/sample/sample.c
    @@ -708,71 +708,6 @@ ath_rate_setupxtxdesc(struct ath_softc *sc, struct ath_node *an,
     	    s3code, sched->t3);		/* series 3 */
     }
     
    -/*
    - * Update the EWMA percentage.
    - *
    - * This is a simple hack to track an EWMA based on the current
    - * rate scenario. For the rate codes which failed, this will
    - * record a 0% against it. For the rate code which succeeded,
    - * EWMA will record the nbad*100/nframes percentage against it.
    - */
    -static void
    -update_ewma_stats(struct ath_softc *sc, struct ath_node *an,
    -    int frame_size,
    -    int rix0, int tries0,
    -    int rix1, int tries1,
    -    int rix2, int tries2,
    -    int rix3, int tries3,
    -    int short_tries, int tries, int status,
    -    int nframes, int nbad)
    -{
    -	struct sample_node *sn = ATH_NODE_SAMPLE(an);
    -	struct sample_softc *ssc = ATH_SOFTC_SAMPLE(sc);
    -	const int size_bin = size_to_bin(frame_size);
    -	int tries_so_far;
    -	int pct;
    -	int rix = rix0;
    -
    -	/* Calculate percentage based on current rate */
    -	if (nframes == 0)
    -		nframes = nbad = 1;
    -	pct = ((nframes - nbad) * 1000) / nframes;
    -
    -	/* Figure out which rate index succeeded */
    -	tries_so_far = tries0;
    -
    -	if (tries1 && tries_so_far < tries) {
    -		tries_so_far += tries1;
    -		rix = rix1;
    -		/* XXX bump ewma pct */
    -	}
    -
    -	if (tries2 && tries_so_far < tries) {
    -		tries_so_far += tries2;
    -		rix = rix2;
    -		/* XXX bump ewma pct */
    -	}
    -
    -	if (tries3 && tries_so_far < tries) {
    -		rix = rix3;
    -		/* XXX bump ewma pct */
    -	}
    -
    -	/* rix is the successful rate, update EWMA for final rix */
    -	if (sn->stats[size_bin][rix].total_packets <
    -	    ssc->smoothing_minpackets) {
    -		/* just average the first few packets */
    -		int a_pct = (sn->stats[size_bin][rix].packets_acked * 1000) /
    -		    (sn->stats[size_bin][rix].total_packets);
    -		sn->stats[size_bin][rix].ewma_pct = a_pct;
    -	} else {
    -		/* use a ewma */
    -		sn->stats[size_bin][rix].ewma_pct =
    -			((sn->stats[size_bin][rix].ewma_pct * ssc->smoothing_rate) +
    -			 (pct * (100 - ssc->smoothing_rate))) / 100;
    -	}
    -}
    -
     static void
     update_stats(struct ath_softc *sc, struct ath_node *an, 
     		  int frame_size,
    @@ -792,6 +727,7 @@ update_stats(struct ath_softc *sc, struct ath_node *an,
     	const int size = bin_to_size(size_bin);
     	int tt, tries_so_far;
     	int is_ht40 = (an->an_node.ni_chw == 40);
    +	int pct;
     
     	if (!IS_RATE_DEFINED(sn, rix0))
     		return;
    @@ -865,6 +801,27 @@ update_stats(struct ath_softc *sc, struct ath_node *an,
     	sn->stats[size_bin][rix0].last_tx = ticks;
     	sn->stats[size_bin][rix0].total_packets += nframes;
     
    +	/* update EWMA for this rix */
    +
    +	/* Calculate percentage based on current rate */
    +	if (nframes == 0)
    +		nframes = nbad = 1;
    +	pct = ((nframes - nbad) * 1000) / nframes;
    +
    +	if (sn->stats[size_bin][rix0].total_packets <
    +	    ssc->smoothing_minpackets) {
    +		/* just average the first few packets */
    +		int a_pct = (sn->stats[size_bin][rix0].packets_acked * 1000) /
    +		    (sn->stats[size_bin][rix0].total_packets);
    +		sn->stats[size_bin][rix0].ewma_pct = a_pct;
    +	} else {
    +		/* use a ewma */
    +		sn->stats[size_bin][rix0].ewma_pct =
    +			((sn->stats[size_bin][rix0].ewma_pct * ssc->smoothing_rate) +
    +			 (pct * (100 - ssc->smoothing_rate))) / 100;
    +	}
    +
    +
     	if (rix0 == sn->current_sample_rix[size_bin]) {
     		IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL,
     		   &an->an_node,
    @@ -907,6 +864,11 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
     	short_tries = ts->ts_shortretry;
     	long_tries = ts->ts_longretry + 1;
     
    +	if (nframes == 0) {
    +		device_printf(sc->sc_dev, "%s: nframes=0?\n", __func__);
    +		return;
    +	}
    +
     	if (frame_size == 0)		    /* NB: should not happen */
     		frame_size = 1500;
     
    @@ -950,13 +912,6 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
     			     0, 0,
     			     short_tries, long_tries, status,
     			     nframes, nbad);
    -		update_ewma_stats(sc, an, frame_size, 
    -			     final_rix, long_tries,
    -			     0, 0,
    -			     0, 0,
    -			     0, 0,
    -			     short_tries, long_tries, status,
    -			     nframes, nbad);
     
     	} else {
     		int finalTSIdx = ts->ts_finaltsi;
    @@ -1008,15 +963,6 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
     				     short_tries, long_tries,
     				     long_tries > rc[0].tries,
     				     nframes, nbad);
    -			update_ewma_stats(sc, an, frame_size,
    -				     rc[0].rix, rc[0].tries,
    -				     rc[1].rix, rc[1].tries,
    -				     rc[2].rix, rc[2].tries,
    -				     rc[3].rix, rc[3].tries,
    -				     short_tries, long_tries,
    -				     long_tries > rc[0].tries,
    -				     nframes, nbad);
    -
     			long_tries -= rc[0].tries;
     		}
     		
    @@ -1029,14 +975,6 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
     				     short_tries, long_tries,
     				     status,
     				     nframes, nbad);
    -			update_ewma_stats(sc, an, frame_size,
    -				     rc[1].rix, rc[1].tries,
    -				     rc[2].rix, rc[2].tries,
    -				     rc[3].rix, rc[3].tries,
    -				     0, 0,
    -				     short_tries, long_tries,
    -				     status,
    -				     nframes, nbad);
     			long_tries -= rc[1].tries;
     		}
     
    @@ -1049,14 +987,6 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
     				     short_tries, long_tries,
     				     status,
     				     nframes, nbad);
    -			update_ewma_stats(sc, an, frame_size,
    -				     rc[2].rix, rc[2].tries,
    -				     rc[3].rix, rc[3].tries,
    -				     0, 0,
    -				     0, 0,
    -				     short_tries, long_tries,
    -				     status,
    -				     nframes, nbad);
     			long_tries -= rc[2].tries;
     		}
     
    @@ -1069,14 +999,6 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
     				     short_tries, long_tries,
     				     status,
     				     nframes, nbad);
    -			update_ewma_stats(sc, an, frame_size,
    -				     rc[3].rix, rc[3].tries,
    -				     0, 0,
    -				     0, 0,
    -				     0, 0,
    -				     short_tries, long_tries,
    -				     status,
    -				     nframes, nbad);
     		}
     	}
     }
    
    From 1c3515d2d514b1d8f8e13a5f4142e1bffacae051 Mon Sep 17 00:00:00 2001
    From: Pyun YongHyeon 
    Date: Wed, 27 Feb 2013 05:03:35 +0000
    Subject: [PATCH 0445/1476] RX checksum offloading on old Yukon controllers
     seem to cause more problems.  Disable RX checksum offloading on controllers
     that don't use new descriptor format but give chance to enable it with
     ifconfig(8).
    
    ---
     sys/dev/msk/if_msk.c | 6 ++++++
     1 file changed, 6 insertions(+)
    
    diff --git a/sys/dev/msk/if_msk.c b/sys/dev/msk/if_msk.c
    index d0ca808c8ef..664575c77c6 100644
    --- a/sys/dev/msk/if_msk.c
    +++ b/sys/dev/msk/if_msk.c
    @@ -1695,6 +1695,12 @@ msk_attach(device_t dev)
     			ifp->if_capabilities |= IFCAP_VLAN_HWCSUM;
     	}
     	ifp->if_capenable = ifp->if_capabilities;
    +	/*
    +	 * Disable RX checksum offloading on controllers that don't use
    +	 * new descriptor format but give chance to enable it.
    +	 */
    +	if ((sc_if->msk_flags & MSK_FLAG_DESCV2) == 0)
    +		ifp->if_capenable &= ~IFCAP_RXCSUM;
     
     	/*
     	 * Tell the upper layer(s) we support long frames.
    
    From e63b9309086dfda4acbf3d51f293164e271ce12f Mon Sep 17 00:00:00 2001
    From: Andrew Turner 
    Date: Wed, 27 Feb 2013 06:53:15 +0000
    Subject: [PATCH 0446/1476] Clear the memory allocated to build the unwind
     tables. This fixes C++ exceptions on ARM EABI with static binaries.
    
    ---
     contrib/binutils/gas/config/tc-arm.c | 2 ++
     1 file changed, 2 insertions(+)
    
    diff --git a/contrib/binutils/gas/config/tc-arm.c b/contrib/binutils/gas/config/tc-arm.c
    index 0b18b5b0fa3..daaae003510 100644
    --- a/contrib/binutils/gas/config/tc-arm.c
    +++ b/contrib/binutils/gas/config/tc-arm.c
    @@ -3079,6 +3079,7 @@ s_arm_unwind_fnend (int ignored ATTRIBUTE_UNUSED)
       record_alignment (now_seg, 2);
     
       ptr = frag_more (8);
    +  memset(ptr, 0, 8);
       where = frag_now_fix () - 8;
     
       /* Self relative offset of the function start.  */
    @@ -17350,6 +17351,7 @@ create_unwind_entry (int have_data)
     
       /* Allocate the table entry.	*/
       ptr = frag_more ((size << 2) + 4);
    +  memset(ptr, 0, (size << 2) + 4);
       where = frag_now_fix () - ((size << 2) + 4);
     
       switch (unwind.personality_index)
    
    From 94f4ac214c403b99cbc44dd6e9cdf4db2cc9b297 Mon Sep 17 00:00:00 2001
    From: Konstantin Belousov 
    Date: Wed, 27 Feb 2013 07:31:23 +0000
    Subject: [PATCH 0447/1476] An inode block must not be blockingly read while cg
     block is owned. The order is inode buffer lock -> snaplk -> cg buffer lock,
     reversing the order causes deadlocks.
    
    Inode block must not be written while cg block buffer is owned. The
    FFS copy on write needs to allocate a block to copy the content of the
    inode block, and the cylinder group selected for the allocation might
    be the same as the owned cg block.  The reserved block detection code
    in the ffs_copyonwrite() and ffs_bp_snapblk() is unable to detect the
    situation, because the locked cg buffer is not exposed to it.
    
    In order to maintain the dependency between initialized inode block
    and the cg_initediblk pointer, look up the inode buffer in
    non-blocking mode. If succeeded, brelse cg block, initialize the inode
    block and write it.  After the write is finished, reread cg block and
    update the cg_initediblk.
    
    If inode block is already locked by another thread, let the another
    thread initialize it.  If another thread raced with us after we
    started writing inode block, the situation is detected by an update of
    cg_initediblk.  Note that double-initialization of the inode block is
    harmless, the block cannot be used until cg_initediblk is incremented.
    
    Sponsored by:	The FreeBSD Foundation
    In collaboration with:	pho
    Reviewed by:	mckusick
    MFC after:	1 month
    X-MFC-note:	after r246877
    ---
     sys/ufs/ffs/ffs_alloc.c | 73 +++++++++++++++++++++++++++++++++++++----
     1 file changed, 67 insertions(+), 6 deletions(-)
    
    diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c
    index abe4073f16b..789a7cf53e3 100644
    --- a/sys/ufs/ffs/ffs_alloc.c
    +++ b/sys/ufs/ffs/ffs_alloc.c
    @@ -1790,6 +1790,17 @@ fail:
     	return (0);
     }
     
    +static inline struct buf *
    +getinobuf(struct inode *ip, u_int cg, u_int32_t cginoblk, int gbflags)
    +{
    +	struct fs *fs;
    +
    +	fs = ip->i_fs;
    +	return (getblk(ip->i_devvp, fsbtodb(fs, ino_to_fsba(fs,
    +	    cg * fs->fs_ipg + cginoblk)), (int)fs->fs_bsize, 0, 0,
    +	    gbflags));
    +}
    +
     /*
      * Determine whether an inode can be allocated.
      *
    @@ -1814,9 +1825,11 @@ ffs_nodealloccg(ip, cg, ipref, mode, unused)
     	u_int8_t *inosused, *loc;
     	struct ufs2_dinode *dp2;
     	int error, start, len, i;
    +	u_int32_t old_initediblk;
     
     	fs = ip->i_fs;
     	ump = ip->i_ump;
    +check_nifree:
     	if (fs->fs_cs(fs, cg).cs_nifree == 0)
     		return (0);
     	UFS_UNLOCK(ump);
    @@ -1828,13 +1841,13 @@ ffs_nodealloccg(ip, cg, ipref, mode, unused)
     		return (0);
     	}
     	cgp = (struct cg *)bp->b_data;
    +restart:
     	if (!cg_chkmagic(cgp) || cgp->cg_cs.cs_nifree == 0) {
     		brelse(bp);
     		UFS_LOCK(ump);
     		return (0);
     	}
     	bp->b_xflags |= BX_BKGRDWRITE;
    -	cgp->cg_old_time = cgp->cg_time = time_second;
     	inosused = cg_inosused(cgp);
     	if (ipref) {
     		ipref %= fs->fs_ipg;
    @@ -1856,7 +1869,6 @@ ffs_nodealloccg(ip, cg, ipref, mode, unused)
     		}
     	}
     	ipref = (loc - inosused) * NBBY + ffs(~*loc) - 1;
    -	cgp->cg_irotor = ipref;
     gotit:
     	/*
     	 * Check to see if we need to initialize more inodes.
    @@ -1864,9 +1876,37 @@ gotit:
     	if (fs->fs_magic == FS_UFS2_MAGIC &&
     	    ipref + INOPB(fs) > cgp->cg_initediblk &&
     	    cgp->cg_initediblk < cgp->cg_niblk) {
    -		ibp = getblk(ip->i_devvp, fsbtodb(fs,
    -		    ino_to_fsba(fs, cg * fs->fs_ipg + cgp->cg_initediblk)),
    -		    (int)fs->fs_bsize, 0, 0, 0);
    +		old_initediblk = cgp->cg_initediblk;
    +
    +		/*
    +		 * Free the cylinder group lock before writing the
    +		 * initialized inode block.  Entering the
    +		 * babarrierwrite() with the cylinder group lock
    +		 * causes lock order violation between the lock and
    +		 * snaplk.
    +		 *
    +		 * Another thread can decide to initialize the same
    +		 * inode block, but whichever thread first gets the
    +		 * cylinder group lock after writing the newly
    +		 * allocated inode block will update it and the other
    +		 * will realize that it has lost and leave the
    +		 * cylinder group unchanged.
    +		 */
    +		ibp = getinobuf(ip, cg, old_initediblk, GB_LOCK_NOWAIT);
    +		brelse(bp);
    +		if (ibp == NULL) {
    +			/*
    +			 * The inode block buffer is already owned by
    +			 * another thread, which must initialize it.
    +			 * Wait on the buffer to allow another thread
    +			 * to finish the updates, with dropped cg
    +			 * buffer lock, then retry.
    +			 */
    +			ibp = getinobuf(ip, cg, old_initediblk, 0);
    +			brelse(ibp);
    +			UFS_LOCK(ump);
    +			goto check_nifree;
    +		}
     		bzero(ibp->b_data, (int)fs->fs_bsize);
     		dp2 = (struct ufs2_dinode *)(ibp->b_data);
     		for (i = 0; i < INOPB(fs); i++) {
    @@ -1883,8 +1923,29 @@ gotit:
     		 * loading of newly created filesystems.
     		 */
     		babarrierwrite(ibp);
    -		cgp->cg_initediblk += INOPB(fs);
    +
    +		/*
    +		 * After the inode block is written, try to update the
    +		 * cg initediblk pointer.  If another thread beat us
    +		 * to it, then leave it unchanged as the other thread
    +		 * has already set it correctly.
    +		 */
    +		error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)),
    +		    (int)fs->fs_cgsize, NOCRED, &bp);
    +		UFS_LOCK(ump);
    +		ACTIVECLEAR(fs, cg);
    +		UFS_UNLOCK(ump);
    +		if (error != 0) {
    +			brelse(bp);
    +			return (error);
    +		}
    +		cgp = (struct cg *)bp->b_data;
    +		if (cgp->cg_initediblk == old_initediblk)
    +			cgp->cg_initediblk += INOPB(fs);
    +		goto restart;
     	}
    +	cgp->cg_old_time = cgp->cg_time = time_second;
    +	cgp->cg_irotor = ipref;
     	UFS_LOCK(ump);
     	ACTIVECLEAR(fs, cg);
     	setbit(inosused, ipref);
    
    From ba05dec5a4ba7b724dbcf40a0b3319c4705c6148 Mon Sep 17 00:00:00 2001
    From: Konstantin Belousov 
    Date: Wed, 27 Feb 2013 07:32:39 +0000
    Subject: [PATCH 0448/1476] The softdep freeblks workitem might hold a
     reference on the dquot. Current dqflush() panics when a dquot with with
     non-zero refcount is encountered.  The situation is possible, because quotas
     are turned off before softdep workitem queue if flushed, due to the quota
     file writes might create softdep workitems.
    
    Make the encountering an active dquot in dqflush() not fatal, return
    the error from quotaoff() instead.  Ignore the quotaoff() failures
    when ffs_flushfiles() is called in the course of softdep_flushfiles()
    loop, until the last iteration.  At the last loop, the quotas must be
    closed, and because SU workitems should be already flushed, the
    references to dquot are gone.
    
    Sponsored by:	The FreeBSD Foundation
    Reported and tested by:	pho
    Reviewed by:	mckusick
    MFC after:	2 weeks
    ---
     sys/sys/vnode.h           |  1 +
     sys/ufs/ffs/ffs_softdep.c | 23 ++++++++++++++++++++---
     sys/ufs/ffs/ffs_vfsops.c  | 33 ++++++++++++++++++++++++++-------
     sys/ufs/ufs/ufs_quota.c   | 23 ++++++++++++++++-------
     4 files changed, 63 insertions(+), 17 deletions(-)
    
    diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
    index b54dc04d430..0696eddb598 100644
    --- a/sys/sys/vnode.h
    +++ b/sys/sys/vnode.h
    @@ -385,6 +385,7 @@ extern int		vttoif_tab[];
     #define	SKIPSYSTEM	0x0001	/* vflush: skip vnodes marked VSYSTEM */
     #define	FORCECLOSE	0x0002	/* vflush: force file closure */
     #define	WRITECLOSE	0x0004	/* vflush: only close writable files */
    +#define	EARLYFLUSH	0x0008	/* vflush: early call for ffs_flushfiles */
     #define	V_SAVE		0x0001	/* vinvalbuf: sync file first */
     #define	V_ALT		0x0002	/* vinvalbuf: invalidate only alternate bufs */
     #define	V_NORMAL	0x0004	/* vinvalbuf: invalidate only regular bufs */
    diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
    index 16fe134fe73..e39fd465529 100644
    --- a/sys/ufs/ffs/ffs_softdep.c
    +++ b/sys/ufs/ffs/ffs_softdep.c
    @@ -1908,7 +1908,12 @@ softdep_flushfiles(oldmnt, flags, td)
     	int flags;
     	struct thread *td;
     {
    -	int error, depcount, loopcnt, retry_flush_count, retry;
    +#ifdef QUOTA
    +	struct ufsmount *ump;
    +	int i;
    +#endif
    +	int error, early, depcount, loopcnt, retry_flush_count, retry;
    +	int morework;
     
     	loopcnt = 10;
     	retry_flush_count = 3;
    @@ -1926,7 +1931,9 @@ retry_flush:
     		 * Do another flush in case any vnodes were brought in
     		 * as part of the cleanup operations.
     		 */
    -		if ((error = ffs_flushfiles(oldmnt, flags, td)) != 0)
    +		early = retry_flush_count == 1 || (oldmnt->mnt_kern_flag &
    +		    MNTK_UNMOUNT) == 0 ? 0 : EARLYFLUSH;
    +		if ((error = ffs_flushfiles(oldmnt, flags | early, td)) != 0)
     			break;
     		if ((error = softdep_flushworklist(oldmnt, &depcount, td)) != 0 ||
     		    depcount == 0)
    @@ -1950,7 +1957,17 @@ retry_flush:
     			MNT_ILOCK(oldmnt);
     			KASSERT((oldmnt->mnt_kern_flag & MNTK_NOINSMNTQ) != 0,
     			    ("softdep_flushfiles: !MNTK_NOINSMNTQ"));
    -			if (oldmnt->mnt_nvnodelistsize > 0) {
    +			morework = oldmnt->mnt_nvnodelistsize > 0;
    +#ifdef QUOTA
    +			ump = VFSTOUFS(oldmnt);
    +			UFS_LOCK(ump);
    +			for (i = 0; i < MAXQUOTAS; i++) {
    +				if (ump->um_quotas[i] != NULLVP)
    +					morework = 1;
    +			}
    +			UFS_UNLOCK(ump);
    +#endif
    +			if (morework) {
     				if (--retry_flush_count > 0) {
     					retry = 1;
     					loopcnt = 3;
    diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
    index 0204613a6a1..b3292d0e536 100644
    --- a/sys/ufs/ffs/ffs_vfsops.c
    +++ b/sys/ufs/ffs/ffs_vfsops.c
    @@ -1351,9 +1351,10 @@ ffs_flushfiles(mp, flags, td)
     	struct thread *td;
     {
     	struct ufsmount *ump;
    -	int error;
    +	int qerror, error;
     
     	ump = VFSTOUFS(mp);
    +	qerror = 0;
     #ifdef QUOTA
     	if (mp->mnt_flag & MNT_QUOTA) {
     		int i;
    @@ -1361,11 +1362,19 @@ ffs_flushfiles(mp, flags, td)
     		if (error)
     			return (error);
     		for (i = 0; i < MAXQUOTAS; i++) {
    -			quotaoff(td, mp, i);
    +			error = quotaoff(td, mp, i);
    +			if (error != 0) {
    +				if ((flags & EARLYFLUSH) == 0)
    +					return (error);
    +				else
    +					qerror = error;
    +			}
     		}
    +
     		/*
    -		 * Here we fall through to vflush again to ensure
    -		 * that we have gotten rid of all the system vnodes.
    +		 * Here we fall through to vflush again to ensure that
    +		 * we have gotten rid of all the system vnodes, unless
    +		 * quotas must not be closed.
     		 */
     	}
     #endif
    @@ -1380,11 +1389,21 @@ ffs_flushfiles(mp, flags, td)
     		 * that we have gotten rid of all the system vnodes.
     		 */
     	}
    -        /*
    -	 * Flush all the files.
    +
    +	/*
    +	 * Do not close system files if quotas were not closed, to be
    +	 * able to sync the remaining dquots.  The freeblks softupdate
    +	 * workitems might hold a reference on a dquot, preventing
    +	 * quotaoff() from completing.  Next round of
    +	 * softdep_flushworklist() iteration should process the
    +	 * blockers, allowing the next run of quotaoff() to finally
    +	 * flush held dquots.
    +	 *
    +	 * Otherwise, flush all the files.
     	 */
    -	if ((error = vflush(mp, 0, flags, td)) != 0)
    +	if (qerror == 0 && (error = vflush(mp, 0, flags, td)) != 0)
     		return (error);
    +
     	/*
     	 * Flush filesystem metadata.
     	 */
    diff --git a/sys/ufs/ufs/ufs_quota.c b/sys/ufs/ufs/ufs_quota.c
    index 87ac9a197e6..a9498982432 100644
    --- a/sys/ufs/ufs/ufs_quota.c
    +++ b/sys/ufs/ufs/ufs_quota.c
    @@ -80,7 +80,7 @@ static int dqopen(struct vnode *, struct ufsmount *, int);
     static int dqget(struct vnode *,
     	u_long, struct ufsmount *, int, struct dquot **);
     static int dqsync(struct vnode *, struct dquot *);
    -static void dqflush(struct vnode *);
    +static int dqflush(struct vnode *);
     static int quotaoff1(struct thread *td, struct mount *mp, int type);
     static int quotaoff_inchange(struct thread *td, struct mount *mp, int type);
     
    @@ -674,8 +674,12 @@ again:
     		vrele(vp);
     	}
     
    -	dqflush(qvp);
    -	/* Clear um_quotas before closing the quota vnode to prevent
    +	error = dqflush(qvp);
    +	if (error != 0)
    +		return (error);
    +
    +	/*
    +	 * Clear um_quotas before closing the quota vnode to prevent
     	 * access to the closed vnode from dqget/dqsync
     	 */
     	UFS_LOCK(ump);
    @@ -1594,17 +1598,19 @@ out:
     /*
      * Flush all entries from the cache for a particular vnode.
      */
    -static void
    +static int
     dqflush(struct vnode *vp)
     {
     	struct dquot *dq, *nextdq;
     	struct dqhash *dqh;
    +	int error;
     
     	/*
     	 * Move all dquot's that used to refer to this quota
     	 * file off their hash chains (they will eventually
     	 * fall off the head of the free list and be re-used).
     	 */
    +	error = 0;
     	DQH_LOCK();
     	for (dqh = &dqhashtbl[dqhash]; dqh >= dqhashtbl; dqh--) {
     		for (dq = LIST_FIRST(dqh); dq; dq = nextdq) {
    @@ -1612,12 +1618,15 @@ dqflush(struct vnode *vp)
     			if (dq->dq_ump->um_quotas[dq->dq_type] != vp)
     				continue;
     			if (dq->dq_cnt)
    -				panic("dqflush: stray dquot");
    -			LIST_REMOVE(dq, dq_hash);
    -			dq->dq_ump = (struct ufsmount *)0;
    +				error = EBUSY;
    +			else {
    +				LIST_REMOVE(dq, dq_hash);
    +				dq->dq_ump = NULL;
    +			}
     		}
     	}
     	DQH_UNLOCK();
    +	return (error);
     }
     
     /*
    
    From 20f4e3e158cc6b25a280d11ef83d7a5acc49f043 Mon Sep 17 00:00:00 2001
    From: Konstantin Belousov 
    Date: Wed, 27 Feb 2013 07:34:09 +0000
    Subject: [PATCH 0449/1476] Make recursive getblk() slightly more useful.  Keep
     the buffer state intact if getblk() is done on the already owned buffer. 
     Exit from brelse() early when the lock recursion is detected, otherwise
     brelse() might prematurely destroy the buffer under some circumstances.
    
    Sponsored by:	The FreeBSD Foundation
    Noted by:	mckusick
    Tested by:	pho
    MFC after:	2 weeks
    ---
     sys/kern/vfs_bio.c | 19 +++++++++++++------
     1 file changed, 13 insertions(+), 6 deletions(-)
    
    diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
    index 63933991e18..f9b4dbbf1ab 100644
    --- a/sys/kern/vfs_bio.c
    +++ b/sys/kern/vfs_bio.c
    @@ -1268,6 +1268,15 @@ brelse(struct buf *bp)
     	KASSERT(!(bp->b_flags & (B_CLUSTER|B_PAGING)),
     	    ("brelse: inappropriate B_PAGING or B_CLUSTER bp %p", bp));
     
    +	if (BUF_LOCKRECURSED(bp)) {
    +		/*
    +		 * Do not process, in particular, do not handle the
    +		 * B_INVAL/B_RELBUF and do not release to free list.
    +		 */
    +		BUF_UNLOCK(bp);
    +		return;
    +	}
    +
     	if (bp->b_flags & B_MANAGED) {
     		bqrelse(bp);
     		return;
    @@ -1444,12 +1453,6 @@ brelse(struct buf *bp)
     			brelvp(bp);
     	}
     			
    -	if (BUF_LOCKRECURSED(bp)) {
    -		/* do not release to free list */
    -		BUF_UNLOCK(bp);
    -		return;
    -	}
    -
     	/* enqueue */
     	mtx_lock(&bqlock);
     	/* Handle delayed bremfree() processing. */
    @@ -2681,6 +2684,9 @@ loop:
     		/* We timed out or were interrupted. */
     		else if (error)
     			return (NULL);
    +		/* If recursed, assume caller knows the rules. */
    +		else if (BUF_LOCKRECURSED(bp))
    +			goto end;
     
     		/*
     		 * The buffer is locked.  B_CACHE is cleared if the buffer is 
    @@ -2864,6 +2870,7 @@ loop:
     	}
     	CTR4(KTR_BUF, "getblk(%p, %ld, %d) = %p", vp, (long)blkno, size, bp);
     	BUF_ASSERT_HELD(bp);
    +end:
     	KASSERT(bp->b_bufobj == bo,
     	    ("bp %p wrong b_bufobj %p should be %p", bp, bp->b_bufobj, bo));
     	return (bp);
    
    From 5c7269aca44a0d42797649d9fd55125272776ac7 Mon Sep 17 00:00:00 2001
    From: Oleksandr Tymoshenko 
    Date: Wed, 27 Feb 2013 08:32:34 +0000
    Subject: [PATCH 0450/1476] - Initialize GPIO_OE register based on pinmux
     configuration
    
    Although AM335x TRM states that GPIO_OE register is not used and just
    reflects pads configuration in practice it does control pin behavior
    and shoiuld be set in addition to pinmux setup
    ---
     sys/arm/ti/ti_gpio.c | 14 ++++++++++++++
     1 file changed, 14 insertions(+)
    
    diff --git a/sys/arm/ti/ti_gpio.c b/sys/arm/ti/ti_gpio.c
    index 58de5165a02..aa9bb8ee226 100644
    --- a/sys/arm/ti/ti_gpio.c
    +++ b/sys/arm/ti/ti_gpio.c
    @@ -653,6 +653,9 @@ ti_gpio_attach(device_t dev)
     	struct ti_gpio_softc *sc = device_get_softc(dev);
     	unsigned int i;
     	int err = 0;
    +	int pin;
    +	uint32_t flags;
    +	uint32_t reg_oe;
     
     	sc->sc_dev = dev;
     
    @@ -720,6 +723,17 @@ ti_gpio_attach(device_t dev)
     			/* Disable interrupts for all pins */
     			ti_gpio_write_4(sc, i, TI_GPIO_CLEARIRQENABLE1, 0xffffffff);
     			ti_gpio_write_4(sc, i, TI_GPIO_CLEARIRQENABLE2, 0xffffffff);
    +
    +			/* Init OE registger based on pads configuration */
    +			reg_oe = 0xffffffff;
    +			for (pin = 0; pin < 32; pin++) {
    +				ti_scm_padconf_get_gpioflags(
    +				    PINS_PER_BANK*i + pin, &flags);
    +				if (flags & GPIO_PIN_OUTPUT)
    +					reg_oe &= ~(1U << pin);
    +			}
    +
    +			ti_gpio_write_4(sc, i, TI_GPIO_OE, reg_oe);
     		}
     	}
     
    
    From 8e02f209f93c144edb6a0ecd80d5bf2ec4228d81 Mon Sep 17 00:00:00 2001
    From: Oleksandr Tymoshenko 
    Date: Wed, 27 Feb 2013 08:34:32 +0000
    Subject: [PATCH 0451/1476] Fix typo
    
    ---
     sys/arm/ti/ti_gpio.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/sys/arm/ti/ti_gpio.c b/sys/arm/ti/ti_gpio.c
    index aa9bb8ee226..4edb10e8f51 100644
    --- a/sys/arm/ti/ti_gpio.c
    +++ b/sys/arm/ti/ti_gpio.c
    @@ -724,7 +724,7 @@ ti_gpio_attach(device_t dev)
     			ti_gpio_write_4(sc, i, TI_GPIO_CLEARIRQENABLE1, 0xffffffff);
     			ti_gpio_write_4(sc, i, TI_GPIO_CLEARIRQENABLE2, 0xffffffff);
     
    -			/* Init OE registger based on pads configuration */
    +			/* Init OE register based on pads configuration */
     			reg_oe = 0xffffffff;
     			for (pin = 0; pin < 32; pin++) {
     				ti_scm_padconf_get_gpioflags(
    
    From 157895135a201b7ab10bca1ea20f6785989e890f Mon Sep 17 00:00:00 2001
    From: Tijl Coosemans 
    Date: Wed, 27 Feb 2013 09:34:09 +0000
    Subject: [PATCH 0452/1476] Map libraries linked with -Ttext-segment=base_addr
     at base_addr. Normal libraries have base address 0 and are unaffected by this
     change.
    
    PR:		176216
    Submitted by:	Damjan Jovanovic 
    Reviewed by:	kib
    MFC after:	1 week
    ---
     libexec/rtld-elf/map_object.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/libexec/rtld-elf/map_object.c b/libexec/rtld-elf/map_object.c
    index 79e4132298b..0f75cca31cc 100644
    --- a/libexec/rtld-elf/map_object.c
    +++ b/libexec/rtld-elf/map_object.c
    @@ -175,7 +175,7 @@ map_object(int fd, const char *path, const struct stat *sb)
         base_vaddr = trunc_page(segs[0]->p_vaddr);
         base_vlimit = round_page(segs[nsegs]->p_vaddr + segs[nsegs]->p_memsz);
         mapsize = base_vlimit - base_vaddr;
    -    base_addr = hdr->e_type == ET_EXEC ? (caddr_t) base_vaddr : NULL;
    +    base_addr = (caddr_t) base_vaddr;
     
         mapbase = mmap(base_addr, mapsize, PROT_NONE, MAP_ANON | MAP_PRIVATE |
           MAP_NOCORE, -1, 0);
    
    From 14951d42342055e20e135415d68c44ec966ec3d3 Mon Sep 17 00:00:00 2001
    From: Peter Holm 
    Date: Wed, 27 Feb 2013 18:12:04 +0000
    Subject: [PATCH 0453/1476] The .journal file needs to reside on the ROOTINO
     which must not extend beyond direct blocks. A typo caused this check to fail.
    
    ---
     sbin/tunefs/tunefs.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/sbin/tunefs/tunefs.c b/sbin/tunefs/tunefs.c
    index 688952fc790..39e08f76090 100644
    --- a/sbin/tunefs/tunefs.c
    +++ b/sbin/tunefs/tunefs.c
    @@ -671,7 +671,7 @@ journal_findfile(void)
     				return (ino);
     		}
     	} else {
    -		if ((off_t)dp1->di_size >= lblktosize(&sblock, NDADDR)) {
    +		if ((off_t)dp2->di_size >= lblktosize(&sblock, NDADDR)) {
     			warnx("ROOTINO extends beyond direct blocks.");
     			return (-1);
     		}
    
    From dc1558d1cd79a8244a37aaee3d50c97b0657b5ff Mon Sep 17 00:00:00 2001
    From: Attilio Rao 
    Date: Wed, 27 Feb 2013 18:12:13 +0000
    Subject: [PATCH 0454/1476] Merge from vmobj-rwlock: VM_OBJECT_LOCKED() macro
     is only used to implement a custom version of lock assertions right now
     (which likely spread out thanks to copy and paste). Remove it and implement
     actual assertions.
    
    Sponsored by:	EMC / Isilon storage division
    Reviewed by:	alc
    Tested by:	pho
    ---
     sys/amd64/amd64/pmap.c      | 5 ++---
     sys/i386/i386/pmap.c        | 5 ++---
     sys/i386/xen/pmap.c         | 5 ++---
     sys/powerpc/aim/mmu_oea.c   | 5 ++---
     sys/powerpc/aim/mmu_oea64.c | 5 ++---
     sys/powerpc/booke/pmap.c    | 5 ++---
     sys/sparc64/sparc64/pmap.c  | 5 ++---
     sys/vm/vm_object.h          | 1 -
     8 files changed, 14 insertions(+), 22 deletions(-)
    
    diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
    index c6c62ae8636..f2d8967f6fb 100644
    --- a/sys/amd64/amd64/pmap.c
    +++ b/sys/amd64/amd64/pmap.c
    @@ -3492,9 +3492,8 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_prot_t access, vm_page_t m,
     	KASSERT((m->oflags & VPO_UNMANAGED) != 0 || va < kmi.clean_sva ||
     	    va >= kmi.clean_eva,
     	    ("pmap_enter: managed mapping within the clean submap"));
    -	KASSERT((m->oflags & (VPO_UNMANAGED | VPO_BUSY)) != 0 ||
    -	    VM_OBJECT_LOCKED(m->object),
    -	    ("pmap_enter: page %p is not busy", m));
    +	if ((m->oflags & (VPO_UNMANAGED | VPO_BUSY)) == 0)
    +		VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
     	pa = VM_PAGE_TO_PHYS(m);
     	newpte = (pt_entry_t)(pa | PG_A | PG_V);
     	if ((access & VM_PROT_WRITE) != 0)
    diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c
    index 5fee565962c..3c47a456785 100644
    --- a/sys/i386/i386/pmap.c
    +++ b/sys/i386/i386/pmap.c
    @@ -3456,9 +3456,8 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_prot_t access, vm_page_t m,
     	KASSERT(va < UPT_MIN_ADDRESS || va >= UPT_MAX_ADDRESS,
     	    ("pmap_enter: invalid to pmap_enter page table pages (va: 0x%x)",
     	    va));
    -	KASSERT((m->oflags & (VPO_UNMANAGED | VPO_BUSY)) != 0 ||
    -	    VM_OBJECT_LOCKED(m->object),
    -	    ("pmap_enter: page %p is not busy", m));
    +	if ((m->oflags & (VPO_UNMANAGED | VPO_BUSY)) == 0)
    +		VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
     
     	mpte = NULL;
     
    diff --git a/sys/i386/xen/pmap.c b/sys/i386/xen/pmap.c
    index a8f11a46d13..4989e07e7ef 100644
    --- a/sys/i386/xen/pmap.c
    +++ b/sys/i386/xen/pmap.c
    @@ -2666,9 +2666,8 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_prot_t access, vm_page_t m,
     	KASSERT(va < UPT_MIN_ADDRESS || va >= UPT_MAX_ADDRESS,
     	    ("pmap_enter: invalid to pmap_enter page table pages (va: 0x%x)",
     	    va));
    -	KASSERT((m->oflags & (VPO_UNMANAGED | VPO_BUSY)) != 0 ||
    -	    VM_OBJECT_LOCKED(m->object),
    -	    ("pmap_enter: page %p is not busy", m));
    +	if ((m->oflags & (VPO_UNMANAGED | VPO_BUSY)) == 0)
    +		VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
     
     	mpte = NULL;
     
    diff --git a/sys/powerpc/aim/mmu_oea.c b/sys/powerpc/aim/mmu_oea.c
    index 24350c44f95..e0af4e5fa9b 100644
    --- a/sys/powerpc/aim/mmu_oea.c
    +++ b/sys/powerpc/aim/mmu_oea.c
    @@ -1121,9 +1121,8 @@ moea_enter_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
     	if (pmap_bootstrapped)
     		rw_assert(&pvh_global_lock, RA_WLOCKED);
     	PMAP_LOCK_ASSERT(pmap, MA_OWNED);
    -	KASSERT((m->oflags & (VPO_UNMANAGED | VPO_BUSY)) != 0 ||
    -	    VM_OBJECT_LOCKED(m->object),
    -	    ("moea_enter_locked: page %p is not busy", m));
    +	if ((m->oflags & (VPO_UNMANAGED | VPO_BUSY)) == 0)
    +		VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
     
     	/* XXX change the pvo head for fake pages */
     	if ((m->oflags & VPO_UNMANAGED) != 0) {
    diff --git a/sys/powerpc/aim/mmu_oea64.c b/sys/powerpc/aim/mmu_oea64.c
    index 0d77b576cff..296b5462b9e 100644
    --- a/sys/powerpc/aim/mmu_oea64.c
    +++ b/sys/powerpc/aim/mmu_oea64.c
    @@ -1183,9 +1183,8 @@ moea64_enter(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_page_t m,
     		pvo_flags = PVO_MANAGED;
     	}
     
    -	KASSERT((m->oflags & (VPO_UNMANAGED | VPO_BUSY)) != 0 ||
    -	    VM_OBJECT_LOCKED(m->object),
    -	    ("moea64_enter: page %p is not busy", m));
    +	if ((m->oflags & (VPO_UNMANAGED | VPO_BUSY)) == 0)
    +		VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
     
     	/* XXX change the pvo head for fake pages */
     	if ((m->oflags & VPO_UNMANAGED) != 0) {
    diff --git a/sys/powerpc/booke/pmap.c b/sys/powerpc/booke/pmap.c
    index 5172009360f..8e0b76fc312 100644
    --- a/sys/powerpc/booke/pmap.c
    +++ b/sys/powerpc/booke/pmap.c
    @@ -1560,9 +1560,8 @@ mmu_booke_enter_locked(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_page_t m,
     		KASSERT((va <= VM_MAXUSER_ADDRESS),
     		    ("mmu_booke_enter_locked: user pmap, non user va"));
     	}
    -	KASSERT((m->oflags & (VPO_UNMANAGED | VPO_BUSY)) != 0 ||
    -	    VM_OBJECT_LOCKED(m->object),
    -	    ("mmu_booke_enter_locked: page %p is not busy", m));
    +	if ((m->oflags & (VPO_UNMANAGED | VPO_BUSY)) == 0)
    +		VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
     
     	PMAP_LOCK_ASSERT(pmap, MA_OWNED);
     
    diff --git a/sys/sparc64/sparc64/pmap.c b/sys/sparc64/sparc64/pmap.c
    index 08f008c8916..f689b179c92 100644
    --- a/sys/sparc64/sparc64/pmap.c
    +++ b/sys/sparc64/sparc64/pmap.c
    @@ -1494,9 +1494,8 @@ pmap_enter_locked(pmap_t pm, vm_offset_t va, vm_page_t m, vm_prot_t prot,
     
     	rw_assert(&tte_list_global_lock, RA_WLOCKED);
     	PMAP_LOCK_ASSERT(pm, MA_OWNED);
    -	KASSERT((m->oflags & (VPO_UNMANAGED | VPO_BUSY)) != 0 ||
    -	    VM_OBJECT_LOCKED(m->object),
    -	    ("pmap_enter_locked: page %p is not busy", m));
    +	if ((m->oflags & (VPO_UNMANAGED | VPO_BUSY)) == 0)
    +		VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
     	PMAP_STATS_INC(pmap_nenter);
     	pa = VM_PAGE_TO_PHYS(m);
     
    diff --git a/sys/vm/vm_object.h b/sys/vm/vm_object.h
    index e085929cd41..76caa75166e 100644
    --- a/sys/vm/vm_object.h
    +++ b/sys/vm/vm_object.h
    @@ -206,7 +206,6 @@ extern struct vm_object kmem_object_store;
     #define	VM_OBJECT_LOCK(object)		mtx_lock(&(object)->mtx)
     #define	VM_OBJECT_LOCK_ASSERT(object, type) \
     					mtx_assert(&(object)->mtx, (type))
    -#define	VM_OBJECT_LOCKED(object)	mtx_owned(&(object)->mtx)
     #define	VM_OBJECT_SLEEP(object, wchan, pri, wmesg, timo) \
     					msleep((wchan), &(object)->mtx, (pri), \
     					    (wmesg), (timo))
    
    From 4b9b732ac0023efb10c6f3f61d804cfe1fb785e6 Mon Sep 17 00:00:00 2001
    From: Alfred Perlstein 
    Date: Wed, 27 Feb 2013 19:03:31 +0000
    Subject: [PATCH 0455/1476] watchdogd(8) and watchdog(4) enhancements.
    
    The following support was added to watchdog(4):
    - Support to query the outstanding timeout.
    - Support to set a software pre-timeout function watchdog with an 'action'
    - Support to set a software only watchdog with a configurable 'action'
    
    'action' can be a mask specifying a single operation or a combination of:
     log(9), printf(9), panic(9) and/or kdb_enter(9).
    
    Support the following in watchdogged:
    - Support to utilize the new additions to watchdog(4).
    - Support to warn if a watchdog script runs for too long.
    - Support for "dry run" where we do not actually arm the watchdog,
      but only report on our timing.
    
    Sponsored by:   iXsystems, Inc.
    MFC after:      1 month
    ---
     sys/dev/watchdog/watchdog.c    | 248 +++++++++++++++++++++---
     sys/sys/watchdog.h             |  25 ++-
     usr.sbin/watchdogd/watchdogd.8 | 104 ++++++++++-
     usr.sbin/watchdogd/watchdogd.c | 331 +++++++++++++++++++++++++++++++--
     4 files changed, 668 insertions(+), 40 deletions(-)
    
    diff --git a/sys/dev/watchdog/watchdog.c b/sys/dev/watchdog/watchdog.c
    index e7edf31c4b7..71d8ecdb6ec 100644
    --- a/sys/dev/watchdog/watchdog.c
    +++ b/sys/dev/watchdog/watchdog.c
    @@ -1,5 +1,8 @@
     /*-
      * Copyright (c) 2004 Poul-Henning Kamp
    + * Copyright (c) 2013 iXsystems.com,
    + *               author: Alfred Perlstein 
    + *
      * All rights reserved.
      *
      * Redistribution and use in source and binary forms, with or without
    @@ -29,21 +32,40 @@
     __FBSDID("$FreeBSD$");
     
     #include 
    +#include 
     #include 
     #include 
     #include 
     #include 
     #include 
     #include 
    +#include 
     #include 
     #include 
     #include 
     
    -static struct cdev *wd_dev;
    -static volatile u_int wd_last_u;
    +#include  /* kern_clock_gettime() */
     
    -static int
    -kern_do_pat(u_int utim)
    +static int wd_set_pretimeout(int newtimeout, int disableiftoolong);
    +static void wd_timeout_cb(void *arg);
    +
    +static struct callout wd_pretimeo_handle;
    +static int wd_pretimeout;
    +static int wd_pretimeout_act = WD_SOFT_LOG;
    +
    +static struct callout wd_softtimeo_handle;
    +static int wd_softtimer;	/* true = use softtimer instead of hardware
    +				   watchdog */
    +static int wd_softtimeout_act = WD_SOFT_LOG;	/* action for the software timeout */
    +
    +static struct cdev *wd_dev;
    +static volatile u_int wd_last_u;    /* last timeout value set by kern_do_pat */
    +
    +static int wd_lastpat_valid = 0;
    +static time_t wd_lastpat = 0;	/* when the watchdog was last patted */
    +
    +int
    +wdog_kern_pat(u_int utim)
     {
     	int error;
     
    @@ -51,11 +73,20 @@ kern_do_pat(u_int utim)
     		return (EINVAL);
     
     	if ((utim & WD_LASTVAL) != 0) {
    +		/*
    +		 * if WD_LASTVAL is set, fill in the bits for timeout
    +		 * from the saved value in wd_last_u.
    +		 */
     		MPASS((wd_last_u & ~WD_INTERVAL) == 0);
     		utim &= ~WD_LASTVAL;
     		utim |= wd_last_u;
    -	} else
    +	} else {
    +		/*
    +		 * Otherwise save the new interval.
    +		 * This can be zero (to disable the watchdog)
    +		 */
     		wd_last_u = (utim & WD_INTERVAL);
    +	}
     	if ((utim & WD_INTERVAL) == WD_TO_NEVER) {
     		utim = 0;
     
    @@ -65,18 +96,49 @@ kern_do_pat(u_int utim)
     		/* Assume no watchdog available; watchdog flags success */
     		error = EOPNOTSUPP;
     	}
    -	EVENTHANDLER_INVOKE(watchdog_list, utim, &error);
    +	if (wd_softtimer) {
    +		if (utim == 0) {
    +			callout_stop(&wd_softtimeo_handle);
    +		} else {
    +			(void) callout_reset(&wd_softtimeo_handle,
    +			    hz*utim, wd_timeout_cb, "soft");
    +		}
    +		error = 0;
    +	} else {
    +		EVENTHANDLER_INVOKE(watchdog_list, utim, &error);
    +	}
    +	wd_set_pretimeout(wd_pretimeout, true);
    +	/*
    +	 * If we were able to arm/strobe the watchdog, then
    +	 * update the last time it was strobed for WDIOC_GETTIMELEFT
    +	 */
    +	if (!error) {
    +		struct timespec ts;
    +
    +		error = kern_clock_gettime(curthread /* XXX */,
    +		    CLOCK_MONOTONIC_FAST, &ts);
    +		if (!error) {
    +			wd_lastpat = ts.tv_sec;
    +			wd_lastpat_valid = 1;
    +		}
    +	}
     	return (error);
     }
     
     static int
    -wd_ioctl(struct cdev *dev __unused, u_long cmd, caddr_t data,
    -    int flags __unused, struct thread *td)
    +wd_valid_act(int act)
    +{
    +
    +	if ((act & ~(WD_SOFT_MASK)) != 0)
    +		return false;
    +	return true;
    +}
    +
    +static int
    +wd_ioctl_patpat(caddr_t data)
     {
     	u_int u;
     
    -	if (cmd != WDIOCPATPAT)
    -		return (ENOIOCTL);
     	u = *(u_int *)data;
     	if (u & ~(WD_ACTIVE | WD_PASSIVE | WD_LASTVAL | WD_INTERVAL))
     		return (EINVAL);
    @@ -89,9 +151,157 @@ wd_ioctl(struct cdev *dev __unused, u_long cmd, caddr_t data,
     		return (ENOSYS);	/* XXX Not implemented yet */
     	u &= ~(WD_ACTIVE | WD_PASSIVE);
     
    -	return (kern_do_pat(u));
    +	return (wdog_kern_pat(u));
     }
     
    +static int
    +wd_get_time_left(struct thread *td, time_t *remainp)
    +{
    +	struct timespec ts;
    +	int error;
    +
    +	error = kern_clock_gettime(td, CLOCK_MONOTONIC_FAST, &ts);
    +	if (error)
    +		return (error);
    +	if (!wd_lastpat_valid)
    +		return (ENOENT);
    +	*remainp = ts.tv_sec - wd_lastpat;
    +	return (0);
    +}
    +
    +static void
    +wd_timeout_cb(void *arg)
    +{
    +	const char *type = arg;
    +
    +#ifdef DDB
    +	if ((wd_pretimeout_act & WD_SOFT_DDB)) {
    +		char kdb_why[80];
    +		snprintf(kdb_why, sizeof(buf), "watchdog %s timeout", type);
    +		kdb_backtrace();
    +		kdb_enter(KDB_WHY_WATCHDOG, kdb_why);
    +	}
    +#endif
    +	if ((wd_pretimeout_act & WD_SOFT_LOG))
    +		log(LOG_EMERG, "watchdog %s-timeout, WD_SOFT_LOG", type);
    +	if ((wd_pretimeout_act & WD_SOFT_PRINTF))
    +		printf("watchdog %s-timeout, WD_SOFT_PRINTF\n", type);
    +	if ((wd_pretimeout_act & WD_SOFT_PANIC))
    +		panic("watchdog %s-timeout, WD_SOFT_PANIC set", type);
    +}
    +
    +/*
    + * Called to manage timeouts.
    + * newtimeout needs to be in the range of 0 to actual watchdog timeout.
    + * if 0, we disable the pre-timeout.
    + * otherwise we set the pre-timeout provided it's not greater than the
    + * current actual watchdog timeout.
    + */
    +static int
    +wd_set_pretimeout(int newtimeout, int disableiftoolong)
    +{
    +	u_int utime;
    +
    +	utime = wdog_kern_last_timeout();
    +	/* do not permit a pre-timeout >= than the timeout. */
    +	if (newtimeout >= utime) {
    +		/*
    +		 * If 'disableiftoolong' then just fall through
    +		 * so as to disable the pre-watchdog
    +		 */
    +		if (disableiftoolong)
    +			newtimeout = 0;
    +		else
    +			return EINVAL;
    +	}
    +
    +	/* disable the pre-timeout */
    +	if (newtimeout == 0) {
    +		wd_pretimeout = 0;
    +		callout_stop(&wd_pretimeo_handle);
    +		return 0;
    +	}
    +
    +	/* We determined the value is sane, so reset the callout */
    +	(void) callout_reset(&wd_pretimeo_handle, hz*(utime - newtimeout),
    +	    wd_timeout_cb, "pre-timeout");
    +	wd_pretimeout = newtimeout;
    +	return 0;
    +}
    +
    +static int
    +wd_ioctl(struct cdev *dev __unused, u_long cmd, caddr_t data,
    +    int flags __unused, struct thread *td)
    +{
    +	u_int u;
    +	time_t timeleft;
    +	int error;
    +
    +	error = 0;
    +
    +	switch (cmd) {
    +	case WDIOC_SETSOFT:
    +		u = *(int *)data;
    +		/* do nothing? */
    +		if (u == wd_softtimer)
    +			break;
    +		/* If there is a pending timeout disallow this ioctl */
    +		if (wd_last_u != 0) {
    +			error = EINVAL;
    +			break;
    +		}
    +		wd_softtimer = u;
    +		break;
    +	case WDIOC_SETSOFTTIMEOUTACT:
    +		u = *(int *)data;
    +		if (wd_valid_act(u)) {
    +			wd_softtimeout_act = u;
    +		} else {
    +			error = EINVAL;
    +		}
    +		break;
    +	case WDIOC_SETPRETIMEOUTACT:
    +		u = *(int *)data;
    +		if (wd_valid_act(u)) {
    +			wd_pretimeout_act = u;
    +		} else {
    +			error = EINVAL;
    +		}
    +		break;
    +	case WDIOC_GETPRETIMEOUT:
    +		*(int *)data = (int)wd_pretimeout;
    +		break;
    +	case WDIOC_SETPRETIMEOUT:
    +		error = wd_set_pretimeout(*(int *)data, false);
    +		break;
    +	case WDIOC_GETTIMELEFT:
    +		error = wd_get_time_left(td, &timeleft);
    +		if (error)
    +			break;
    +		*(int *)data = (int)timeleft;
    +		break;
    +	case WDIOC_SETTIMEOUT:
    +		u = *(u_int *)data;
    +		error = wdog_kern_pat(u);
    +		break;
    +	case WDIOC_GETTIMEOUT:
    +		u = wdog_kern_last_timeout();
    +		*(u_int *)data = u;
    +		break;
    +	case WDIOCPATPAT:
    +		error = wd_ioctl_patpat(data);
    +		break;
    +	default:
    +		error = ENOIOCTL;
    +		break;
    +	}
    +	return (error);
    +}
    +
    +/*
    + * Return the last timeout set, this is NOT the seconds from NOW until timeout,
    + * rather it is the amount of seconds passed to WDIOCPATPAT/WDIOC_SETTIMEOUT.
    + */
     u_int
     wdog_kern_last_timeout(void)
     {
    @@ -99,16 +309,6 @@ wdog_kern_last_timeout(void)
     	return (wd_last_u);
     }
     
    -int
    -wdog_kern_pat(u_int utim)
    -{
    -
    -	if (utim & ~(WD_LASTVAL | WD_INTERVAL))
    -		return (EINVAL);
    -
    -	return (kern_do_pat(utim));
    -}
    -
     static struct cdevsw wd_cdevsw = {
     	.d_version =	D_VERSION,
     	.d_ioctl =	wd_ioctl,
    @@ -120,10 +320,16 @@ watchdog_modevent(module_t mod __unused, int type, void *data __unused)
     {
     	switch(type) {
     	case MOD_LOAD:
    +		callout_init(&wd_pretimeo_handle, true);
    +		callout_init(&wd_softtimeo_handle, true);
     		wd_dev = make_dev(&wd_cdevsw, 0,
     		    UID_ROOT, GID_WHEEL, 0600, _PATH_WATCHDOG);
     		return 0;
     	case MOD_UNLOAD:
    +		callout_stop(&wd_pretimeo_handle);
    +		callout_stop(&wd_softtimeo_handle);
    +		callout_drain(&wd_pretimeo_handle);
    +		callout_drain(&wd_softtimeo_handle);
     		destroy_dev(wd_dev);
     		return 0;
     	case MOD_SHUTDOWN:
    diff --git a/sys/sys/watchdog.h b/sys/sys/watchdog.h
    index ba58a7c69a5..92c47dee75f 100644
    --- a/sys/sys/watchdog.h
    +++ b/sys/sys/watchdog.h
    @@ -1,5 +1,8 @@
     /*-
      * Copyright (c) 2003 Poul-Henning Kamp
    + * Copyright (c) 2013 iXsystems.com,
    + *                    author: Alfred Perlstein 
    + *
      * All rights reserved.
      *
      * Redistribution and use in source and binary forms, with or without
    @@ -32,7 +35,18 @@
     
     #define	_PATH_WATCHDOG	"fido"
     
    -#define WDIOCPATPAT	_IOW('W', 42, u_int)
    +#define WDIOCPATPAT	_IOW('W', 42, u_int)	/* pat the watchdog */
    +#define WDIOC_SETTIMEOUT    _IOW('W', 43, int)	/* set/reset the timer */
    +#define WDIOC_GETTIMEOUT    _IOR('W', 44, int)	/* get total timeout */
    +#define WDIOC_GETTIMELEFT   _IOR('W', 45, int)	/* get time left */
    +#define WDIOC_GETPRETIMEOUT _IOR('W', 46, int)	/* get the pre-timeout */
    +#define WDIOC_SETPRETIMEOUT _IOW('W', 47, int)	/* set the pre-timeout */
    +/* set the action when a pre-timeout occurs see: WD_SOFT_* */
    +#define WDIOC_SETPRETIMEOUTACT _IOW('W', 48, int)
    +
    +/* use software watchdog instead of hardware */
    +#define WDIOC_SETSOFT	_IOW('W', 49, int)
    +#define WDIOC_SETSOFTTIMEOUTACT	_IOW('W', 50, int)
     
     #define WD_ACTIVE	0x8000000
     	/* 
    @@ -76,6 +90,15 @@
     #define WD_TO_8SEC	33
     #define WD_TO_16SEC	34
     #define WD_TO_32SEC	35
    +#define WD_TO_64SEC	36
    +#define WD_TO_128SEC	37
    +
    +/* action on pre-timeout trigger */
    +#define	WD_SOFT_PANIC	0x01	/* panic */
    +#define	WD_SOFT_DDB	0x02	/* enter debugger */
    +#define	WD_SOFT_LOG	0x04	/* log(9) */
    +#define	WD_SOFT_PRINTF	0x08	/* printf(9) */
    +#define WD_SOFT_MASK	0x0f	/* all of the above */
     
     #ifdef _KERNEL
     
    diff --git a/usr.sbin/watchdogd/watchdogd.8 b/usr.sbin/watchdogd/watchdogd.8
    index b00fef17cdb..096eb9d55b7 100644
    --- a/usr.sbin/watchdogd/watchdogd.8
    +++ b/usr.sbin/watchdogd/watchdogd.8
    @@ -1,3 +1,5 @@
    +.\" Copyright (c) 2013  iXsystems.com,
    +.\"                     author: Alfred Perlstein 
     .\" Copyright (c) 2004  Poul-Henning Kamp 
     .\" Copyright (c) 2003  Sean M. Kelly 
     .\" All rights reserved.
    @@ -25,7 +27,7 @@
     .\"
     .\" $FreeBSD$
     .\"
    -.Dd September 2, 2006
    +.Dd September 2, 2013
     .Dt WATCHDOGD 8
     .Os
     .Sh NAME
    @@ -33,11 +35,17 @@
     .Nd watchdog daemon
     .Sh SYNOPSIS
     .Nm
    -.Op Fl d
    +.Op Fl dnw
    +.Op Fl -debug
    +.Op Fl -softtimeout
    +.Op Fl -softtimeout-action Ar action
    +.Op Fl -pretimeout Ar timeout
    +.Op Fl -pretimeout-action Ar action
     .Op Fl e Ar cmd
     .Op Fl I Ar file
     .Op Fl s Ar sleep
     .Op Fl t Ar timeout
    +.Op Fl T Ar script_timeout
     .Sh DESCRIPTION
     The
     .Nm
    @@ -62,6 +70,13 @@ is not specified, the daemon will perform a trivial file system
     check instead.
     .Pp
     The
    +.Fl n
    +argument 'dry-run' will cause watchdog not to arm the system watchdog and
    +instead only run the watchdog function and report on failures.
    +This is useful for developing new watchdogd scripts as the system will not
    +reboot if there are problems with the script.
    +.Pp
    +The
     .Fl s Ar sleep
     argument can be used to control the sleep period between each execution
     of the check and defaults to one second.
    @@ -78,6 +93,16 @@ If this occurs,
     will no longer execute and thus the kernel's watchdog routines will take
     action after a configurable timeout.
     .Pp
    +The
    +.Fl T Ar script_timeout
    +specifies the threshold (in seconds) at which the watchdogd will complain
    +that its script has run for too long.
    +If unset
    +.Ar script_timeout
    +defaults to the value specified by the
    +.Fl s Ar sleep 
    +option.
    +.Pp
     Upon receiving the
     .Dv SIGTERM
     or
    @@ -90,17 +115,85 @@ will terminate.
     The
     .Nm
     utility recognizes the following runtime options:
    -.Bl -tag -width ".Fl I Ar file"
    +.Bl -tag -width ".Fl -softtimeout-action Ar action  "
     .It Fl I Ar file
     Write the process ID of the
     .Nm
     utility in the specified file.
    -.It Fl d
    +.It Fl d Fl -debug
     Do not fork.
     When this option is specified,
     .Nm
     will not fork into the background at startup.
    +.Pp
    +.It Fl w
    +Complain when the watchdog script takes too long.
    +This flag will cause watchdogd to complain when the amount of time to
    +execute the watchdog script exceeds the threshold of 'sleep' option.
    +.Pp
    +.It Fl -pretimeout Ar timeout
    +Set a "pretimeout" watchdog.  At "timeout" seconds before the watchdog
    +will fire attempt an action.  The action is set by the --pretimeout-action
    +flag.  The default is just to log a message (WD_SOFT_LOG) via
    +.Xr log 9 .
    +.Pp
    +.It Fl -pretimeout-action Ar action
    +Set the timeout action for the pretimeout.  See the section 
    +.Sx Timeout Actions .
    +.Pp
    +.It Fl -softtimeout
    +Instead of arming the various hardware watchdogs, only use a basic software
    +watchdog.  The default action is just to
    +.Xr log 9
    +a message (WD_SOFT_LOG).
    +.Pp
    +.It Fl -softtimeout-action Ar action
    +Set the timeout action for the softtimeout.  See the section 
    +.Sx Timeout Actions .
    +.Pp
     .El
    +.Sh Timeout Actions
    +The following timeout actions are available via the
    +.Fl -pretimeout-action
    +and
    +.Fl -softtimeout-action
    +flags:
    +.Bl -tag -width ".Ar printf  "
    +.It Ar panic
    +Call
    +.Xr panic 9
    +when the timeout is reached.
    +.Pp
    +.It Ar ddb
    +Enter the kernel debugger via
    +.Xr kdb_enter 9
    +when the timeout is reached.
    +.Pp
    +.It Ar log
    +Log a message using
    +.Xr log 9
    +when the timeout is reached.
    +.Pp
    +.It Ar printf
    +call the kernel 
    +.Xr printf 9
    +to display a message to the console and
    +.Xr dmesg 8
    +buffer.
    +.Pp
    +.El
    +Actions can be combined in a comma separated list as so:
    +.Ar log,printf
    +which would both
    +.Xr printf 9
    +and
    +.Xr log 9
    +which will send messages both to
    +.Xr dmesg 8
    +and the kernel
    +.Xr log 4
    +device for
    +.Xr syslog 8 .
     .Sh FILES
     .Bl -tag -width ".Pa /var/run/watchdogd.pid" -compact
     .It Pa /var/run/watchdogd.pid
    @@ -125,3 +218,6 @@ and
     .Pp
     Some contributions made by
     .An Jeff Roberson Aq jeff@FreeBSD.org .
    +.Pp
    +The pretimeout and softtimeout action system was added by
    +.An Alfred Perlstein Aq alfred@freebsd.org .
    diff --git a/usr.sbin/watchdogd/watchdogd.c b/usr.sbin/watchdogd/watchdogd.c
    index 50bdd91fa79..bb923875a69 100644
    --- a/usr.sbin/watchdogd/watchdogd.c
    +++ b/usr.sbin/watchdogd/watchdogd.c
    @@ -1,5 +1,8 @@
     /*-
      * Copyright (c) 2003-2004  Sean M. Kelly 
    + * Copyright (c) 2013 iXsystems.com,
    + *                    author: Alfred Perlstein 
    + *
      * All rights reserved.
      *
      * Redistribution and use in source and binary forms, with or without
    @@ -50,8 +53,11 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    +#include 
     #include 
     
    +#include 
    +
     static void	parseargs(int, char *[]);
     static void	sighandler(int);
     static void	watchdog_loop(void);
    @@ -63,13 +69,39 @@ static void	usage(void);
     static int debugging = 0;
     static int end_program = 0;
     static const char *pidfile = _PATH_VARRUN "watchdogd.pid";
    -static u_int timeout = WD_TO_16SEC;
    +static u_int timeout = WD_TO_128SEC;
    +static u_int pretimeout = 0;
     static u_int passive = 0;
     static int is_daemon = 0;
    +static int is_dry_run = 0;  /* do not arm the watchdog, only
    +			       report on timing of the watch
    +			       program */
    +static int do_timedog = 0;
    +static int do_syslog = 0;
     static int fd = -1;
     static int nap = 1;
    +static int carp_thresh_seconds = -1;
     static char *test_cmd = NULL;
     
    +static const char *getopt_shortopts;
    +
    +static int pretimeout_set;
    +static int pretimeout_act;
    +static int pretimeout_act_set;
    +
    +static int softtimeout_set;
    +static int softtimeout_act;
    +static int softtimeout_act_set;
    +
    +static struct option longopts[] = {
    +	{ "debug", no_argument, &debugging, 1 },
    +	{ "pretimeout", required_argument, &pretimeout_set, 1 },
    +	{ "pretimeout-action", required_argument, &pretimeout_act_set, 1 },
    +	{ "softtimeout", no_argument, &softtimeout_set, 1 },
    +	{ "softtimeout-action", required_argument, &softtimeout_act_set, 1 },
    +	{ NULL, 0, NULL, 0}
    +};
    +
     /*
      * Ask malloc() to map minimum-sized chunks of virtual address space at a time,
      * so that mlockall() won't needlessly wire megabytes of unused memory into the
    @@ -93,12 +125,18 @@ main(int argc, char *argv[])
     		
     	parseargs(argc, argv);
     
    +	if (do_syslog) {
    +		openlog("watchdogd", LOG_CONS|LOG_NDELAY|LOG_PERROR,
    +		    LOG_DAEMON);
    +
    +	}
    +
     	rtp.type = RTP_PRIO_REALTIME;
     	rtp.prio = 0;
     	if (rtprio(RTP_SET, 0, &rtp) == -1)
     		err(EX_OSERR, "rtprio");
     
    -	if (watchdog_init() == -1)
    +	if (!is_dry_run && watchdog_init() == -1)
     		errx(EX_SOFTWARE, "unable to initialize watchdog");
     
     	if (is_daemon) {
    @@ -108,6 +146,7 @@ main(int argc, char *argv[])
     		pfh = pidfile_open(pidfile, 0600, &otherpid);
     		if (pfh == NULL) {
     			if (errno == EEXIST) {
    +				watchdog_onoff(0);
     				errx(EX_SOFTWARE, "%s already running, pid: %d",
     				    getprogname(), otherpid);
     			}
    @@ -164,6 +203,9 @@ static int
     watchdog_init(void)
     {
     
    +	if (is_dry_run)
    +		return 0;
    +
     	fd = open("/dev/" _PATH_WATCHDOG, O_RDWR);
     	if (fd >= 0)
     		return (0);
    @@ -171,27 +213,99 @@ watchdog_init(void)
     	return (-1);
     }
     
    +/*
    + * If we are doing timing, then get the time.
    + */
    +static int
    +watchdog_getuptime(struct timespec *tp)
    +{
    +	int error;
    +
    +	if (!do_timedog)
    +		return 0;
    +
    +	error = clock_gettime(CLOCK_UPTIME_FAST, tp);
    +	if (error)
    +		warn("clock_gettime");
    +	return (error);
    +}
    +
    +static long
    +watchdog_check_dogfunction_time(struct timespec *tp_start,
    +    struct timespec *tp_end)
    +{
    +	struct timeval tv_start, tv_end, tv;
    +	const char *cmd_prefix, *cmd;
    +	int sec;
    +
    +	if (!do_timedog)
    +		return (0);
    +
    +	TIMESPEC_TO_TIMEVAL(&tv_start, tp_start);
    +	TIMESPEC_TO_TIMEVAL(&tv_end, tp_end);
    +	timersub(&tv_end, &tv_start, &tv);
    +	sec = tv.tv_sec;
    +	if (sec < carp_thresh_seconds)
    +		return (sec);
    +
    +	if (test_cmd) {
    +		cmd_prefix = "Watchdog program";
    +		cmd = test_cmd;
    +	} else {
    +		cmd_prefix = "Watchdog operation";
    +		cmd = "stat(\"/etc\", &sb)";
    +	}
    +	if (do_syslog)
    +		syslog(LOG_CRIT, "%s: '%s' took too long: "
    +		    "%d.%06ld seconds >= %d seconds threshhold",
    +		    cmd_prefix, cmd, sec, (long)tv.tv_usec,
    +		    carp_thresh_seconds);
    +	warnx("%s: '%s' took too long: "
    +	    "%d.%06ld seconds >= %d seconds threshhold",
    +	    cmd_prefix, cmd, sec, (long)tv.tv_usec, carp_thresh_seconds);
    +	return (sec);
    +}
    +
    +
     /*
      * Main program loop which is iterated every second.
      */
     static void
     watchdog_loop(void)
     {
    +	struct timespec ts_start, ts_end;
     	struct stat sb;
    -	int failed;
    +	long waited;
    +	int error, failed;
     
     	while (end_program != 2) {
     		failed = 0;
     
    +		error = watchdog_getuptime(&ts_start);
    +		if (error) {
    +			end_program = 1;
    +			goto try_end;
    +		}
    +
     		if (test_cmd != NULL)
     			failed = system(test_cmd);
     		else
     			failed = stat("/etc", &sb);
     
    +		error = watchdog_getuptime(&ts_end);
    +		if (error) {
    +			end_program = 1;
    +			goto try_end;
    +		}
    +
    +		waited = watchdog_check_dogfunction_time(&ts_start, &ts_end);
    +
     		if (failed == 0)
     			watchdog_patpat(timeout|WD_ACTIVE);
    -		sleep(nap);
    +		if (nap - waited > 0)
    +			sleep(nap - waited);
     
    +try_end:
     		if (end_program != 0) {
     			if (watchdog_onoff(0) == 0) {
     				end_program = 2;
    @@ -211,6 +325,9 @@ static int
     watchdog_patpat(u_int t)
     {
     
    +	if (is_dry_run)
    +		return 0;
    +
     	return ioctl(fd, WDIOCPATPAT, &t);
     }
     
    @@ -221,11 +338,62 @@ watchdog_patpat(u_int t)
     static int
     watchdog_onoff(int onoff)
     {
    +	int error;
     
    -	if (onoff)
    +	/* fake successful watchdog op if a dry run */
    +	if (is_dry_run)
    +		return 0;
    +
    +	if (onoff) {
    +		/*
    +		 * Call the WDIOC_SETSOFT regardless of softtimeout_set
    +		 * because we'll need to turn it off if someone had turned
    +		 * it on.
    +		 */
    +		error = ioctl(fd, WDIOC_SETSOFT, &softtimeout_set);
    +		if (error) {
    +			warn("setting WDIOC_SETSOFT %d", softtimeout_set);
    +			return (error);
    +		}
    +		error = watchdog_patpat((timeout|WD_ACTIVE));
    +		if (error) {
    +			warn("watchdog_patpat failed");
    +			goto failsafe;
    +		}
    +		if (softtimeout_act_set) {
    +			error = ioctl(fd, WDIOC_SETSOFTTIMEOUTACT,
    +			    &softtimeout_act);
    +			if (error) {
    +				warn("setting WDIOC_SETSOFTTIMEOUTACT %d",
    +				    softtimeout_act);
    +				goto failsafe;
    +			}
    +		}
    +		if (pretimeout_set) {
    +			error = ioctl(fd, WDIOC_SETPRETIMEOUT, &pretimeout);
    +			if (error) {
    +				warn("setting WDIOC_SETPRETIMEOUT %d",
    +				    pretimeout);
    +				goto failsafe;
    +			}
    +		}
    +		if (pretimeout_act_set) {
    +			error = ioctl(fd, WDIOC_SETPRETIMEOUTACT,
    +			    &pretimeout_act);
    +			if (error) {
    +				warn("setting WDIOC_SETPRETIMEOUTACT %d",
    +				    pretimeout_act);
    +				goto failsafe;
    +			}
    +		}
    +		/* pat one more time for good measure */
     		return watchdog_patpat((timeout|WD_ACTIVE));
    -	else
    +	 } else {
     		return watchdog_patpat(0);
    +	 }
    +failsafe:
    +	watchdog_patpat(0);
    +	return (error);
     }
     
     /*
    @@ -235,27 +403,132 @@ static void
     usage(void)
     {
     	if (is_daemon)
    -		fprintf(stderr, "usage: watchdogd [-d] [-e cmd] [-I file] [-s sleep] [-t timeout]\n");
    +		fprintf(stderr, "usage:\n"
    +"  watchdogd [-dnw] [-e cmd] [-I file] [-s sleep] [-t timeout]\n"
    +"            [-T script_timeout]\n"
    +"            [--debug]\n"
    +"            [--pretimeout seconds] [-pretimeout-action action]\n"
    +"            [--softtimeout] [-softtimeout-action action]\n"
    +);
     	else
     		fprintf(stderr, "usage: watchdog [-d] [-t timeout]\n");
     	exit(EX_USAGE);
     }
     
    +static long
    +fetchtimeout(int opt, const char *longopt, const char *myoptarg)
    +{
    +	const char *errstr;
    +	char *p;
    +	long rv;
    +
    +	errstr = NULL;
    +	p = NULL;
    +	errno = 0;
    +	rv = strtol(myoptarg, &p, 0);
    +	if ((p != NULL && *p != '\0') || errno != 0)
    +		errstr = "is not a number";
    +	if (rv <= 0)
    +		errstr = "must be greater than zero";
    +	if (errstr) {
    +		if (longopt) 
    +			errx(EX_USAGE, "--%s argument %s", longopt, errstr);
    +		else 
    +			errx(EX_USAGE, "-%c argument %s", opt, errstr);
    +	}
    +	return (rv);
    +}
    +
    +struct act_tbl {
    +	const char *at_act;
    +	int at_value;
    +};
    +
    +struct act_tbl act_tbl[] = {
    +	{ "panic", WD_SOFT_PANIC },
    +	{ "ddb", WD_SOFT_DDB },
    +	{ "log", WD_SOFT_LOG },
    +	{ "printf", WD_SOFT_PRINTF },
    +	{ NULL, 0 }
    +};
    +
    +static void
    +timeout_act_error(const char *lopt, const char *badact)
    +{
    +	char *opts, *oldopts;
    +	int i;
    +
    +	opts = NULL;
    +	for (i = 0; act_tbl[i].at_act != NULL; i++) {
    +		oldopts = opts;
    +		if (asprintf(&opts, "%s%s%s",
    +		    oldopts == NULL ? "" : oldopts,
    +		    oldopts == NULL ? "" : ", ",
    +		    act_tbl[i].at_act) == -1)
    +			err(EX_OSERR, "malloc");
    +		free(oldopts);
    +	}
    +	warnx("bad --%s argument '%s' must be one of (%s).",
    +	    lopt, badact, opts);
    +	usage();
    +}
    +
    +/*
    + * Take a comma separated list of actions and or the flags
    + * together for the ioctl.
    + */
    +static int
    +timeout_act_str2int(const char *lopt, const char *acts)
    +{
    +	int i;
    +	char *dupacts, *tofree;
    +	char *o;
    +	int rv = 0;
    +
    +	tofree = dupacts = strdup(acts);
    +	if (!tofree)
    +		err(EX_OSERR, "malloc");
    +	while ((o = strsep(&dupacts, ",")) != NULL) {
    +		for (i = 0; act_tbl[i].at_act != NULL; i++) {
    +			if (!strcmp(o, act_tbl[i].at_act)) {
    +				rv |= act_tbl[i].at_value;
    +				break;
    +			}
    +		}
    +		if (act_tbl[i].at_act == NULL)
    +			timeout_act_error(lopt, o);
    +	}
    +	free(tofree);
    +	return rv;
    +}
    +
     /*
      * Handle the few command line arguments supported.
      */
     static void
     parseargs(int argc, char *argv[])
     {
    +	int longindex;
     	int c;
     	char *p;
    +	const char *lopt;
     	double a;
     
    +	/*
    +	 * if we end with a 'd' aka 'watchdogd' then we are the daemon program,
    +	 * otherwise run as a command line utility.
    +	 */
     	c = strlen(argv[0]);
     	if (argv[0][c - 1] == 'd')
     		is_daemon = 1;
    -	while ((c = getopt(argc, argv,
    -	    is_daemon ? "I:de:s:t:?" : "dt:?")) != -1) {
    +
    +	if (is_daemon)
    +		getopt_shortopts = "I:de:ns:t:ST:w?";
    +	else
    +		getopt_shortopts = "dt:?";
    +
    +	while ((c = getopt_long(argc, argv, getopt_shortopts, longopts,
    +		    &longindex)) != -1) {
     		switch (c) {
     		case 'I':
     			pidfile = optarg;
    @@ -266,17 +539,19 @@ parseargs(int argc, char *argv[])
     		case 'e':
     			test_cmd = strdup(optarg);
     			break;
    +		case 'n':
    +			is_dry_run = 1;
    +			break;
     #ifdef notyet
     		case 'p':
     			passive = 1;
     			break;
     #endif
     		case 's':
    -			p = NULL;
    -			errno = 0;
    -			nap = strtol(optarg, &p, 0);
    -			if ((p != NULL && *p != '\0') || errno != 0)
    -				errx(EX_USAGE, "-s argument is not a number");
    +			nap = fetchtimeout(c, NULL, optarg);
    +			break;
    +		case 'S':
    +			do_syslog = 1;
     			break;
     		case 't':
     			p = NULL;
    @@ -286,6 +561,7 @@ parseargs(int argc, char *argv[])
     				errx(EX_USAGE, "-t argument is not a number");
     			if (a < 0)
     				errx(EX_USAGE, "-t argument must be positive");
    +
     			if (a == 0)
     				timeout = WD_TO_NEVER;
     			else
    @@ -294,12 +570,39 @@ parseargs(int argc, char *argv[])
     				printf("Timeout is 2^%d nanoseconds\n",
     				    timeout);
     			break;
    +		case 'T':
    +			carp_thresh_seconds = fetchtimeout(c, "NULL", optarg);
    +			break;
    +		case 'w':
    +			do_timedog = 1;
    +			break;
    +		case 0:
    +			lopt = longopts[longindex].name;
    +			if (!strcmp(lopt, "pretimeout")) {
    +				pretimeout = fetchtimeout(0, lopt, optarg);
    +			} else if (!strcmp(lopt, "pretimeout-action")) {
    +				pretimeout_act = timeout_act_str2int(lopt,
    +				    optarg);
    +			} else if (!strcmp(lopt, "softtimeout-action")) {
    +				softtimeout_act = timeout_act_str2int(lopt,
    +				    optarg);
    +			} else {
    +		/*		warnx("bad option at index %d: %s", optind,
    +				    argv[optind]);
    +				usage();
    +				*/
    +			}
    +			break;
     		case '?':
     		default:
     			usage();
     			/* NOTREACHED */
     		}
     	}
    +
    +	if (carp_thresh_seconds == -1)
    +		carp_thresh_seconds = nap;
    +
     	if (argc != optind)
     		errx(EX_USAGE, "extra arguments.");
     	if (is_daemon && timeout < WD_TO_1SEC)
    
    From 9240031ac655f4e3cd4bcf840f2efc5222d6fdbc Mon Sep 17 00:00:00 2001
    From: John Baldwin 
    Date: Wed, 27 Feb 2013 19:50:46 +0000
    Subject: [PATCH 0456/1476] Add an implementation of open_memstream() and
     open_wmemstream().  These routines provide write-only stdio FILE objects that
     store their data in a dynamically allocated buffer.  They are a string
     builder interface somewhat akin to a completely dynamic sbuf.
    
    Reviewed by:	bde, jilles (earlier versions)
    MFC after:	1 month
    ---
     include/stdio.h                               |   1 +
     include/wchar.h                               |   1 +
     lib/libc/stdio/Makefile.inc                   |   4 +-
     lib/libc/stdio/Symbol.map                     |   2 +
     lib/libc/stdio/open_memstream.3               | 154 ++++++++++
     lib/libc/stdio/open_memstream.c               | 209 ++++++++++++++
     lib/libc/stdio/open_wmemstream.c              | 271 ++++++++++++++++++
     tools/regression/lib/libc/stdio/Makefile      |   4 +-
     .../lib/libc/stdio/test-open_memstream.c      | 203 +++++++++++++
     .../lib/libc/stdio/test-open_memstream.t      |  10 +
     .../lib/libc/stdio/test-open_wmemstream.c     | 203 +++++++++++++
     .../lib/libc/stdio/test-open_wmemstream.t     |  10 +
     12 files changed, 1070 insertions(+), 2 deletions(-)
     create mode 100644 lib/libc/stdio/open_memstream.3
     create mode 100644 lib/libc/stdio/open_memstream.c
     create mode 100644 lib/libc/stdio/open_wmemstream.c
     create mode 100644 tools/regression/lib/libc/stdio/test-open_memstream.c
     create mode 100644 tools/regression/lib/libc/stdio/test-open_memstream.t
     create mode 100644 tools/regression/lib/libc/stdio/test-open_wmemstream.c
     create mode 100644 tools/regression/lib/libc/stdio/test-open_wmemstream.t
    
    diff --git a/include/stdio.h b/include/stdio.h
    index 4fc78b833ab..19b1e20f66b 100644
    --- a/include/stdio.h
    +++ b/include/stdio.h
    @@ -346,6 +346,7 @@ char	*tempnam(const char *, const char *);
     FILE	*fmemopen(void * __restrict, size_t, const char * __restrict);
     ssize_t	 getdelim(char ** __restrict, size_t * __restrict, int,
     	    FILE * __restrict);
    +FILE	*open_memstream(char **, size_t *);
     int	 renameat(int, const char *, int, const char *);
     int	 vdprintf(int, const char * __restrict, __va_list);
     
    diff --git a/include/wchar.h b/include/wchar.h
    index 9e8d807c5f2..4a3fe538554 100644
    --- a/include/wchar.h
    +++ b/include/wchar.h
    @@ -207,6 +207,7 @@ int	wcwidth(wchar_t);
     #if __POSIX_VISIBLE >= 200809 || __BSD_VISIBLE
     size_t	mbsnrtowcs(wchar_t * __restrict, const char ** __restrict, size_t,
     	    size_t, mbstate_t * __restrict);
    +FILE	*open_wmemstream(wchar_t **, size_t *);
     wchar_t	*wcpcpy(wchar_t * __restrict, const wchar_t * __restrict);
     wchar_t	*wcpncpy(wchar_t * __restrict, const wchar_t * __restrict, size_t);
     wchar_t	*wcsdup(const wchar_t *) __malloc_like;
    diff --git a/lib/libc/stdio/Makefile.inc b/lib/libc/stdio/Makefile.inc
    index bc3b9e54801..0062d3dd8dd 100644
    --- a/lib/libc/stdio/Makefile.inc
    +++ b/lib/libc/stdio/Makefile.inc
    @@ -14,6 +14,7 @@ SRCS+=	_flock_stub.c asprintf.c clrerr.c dprintf.c \
     	ftell.c funopen.c fvwrite.c fwalk.c fwide.c fwprintf.c fwscanf.c \
     	fwrite.c getc.c getchar.c getdelim.c getline.c \
     	gets.c getw.c getwc.c getwchar.c makebuf.c mktemp.c \
    +	open_memstream.c open_wmemstream.c \
     	perror.c printf.c printf-pos.c putc.c putchar.c \
     	puts.c putw.c putwc.c putwchar.c \
     	refill.c remove.c rewind.c rget.c scanf.c setbuf.c setbuffer.c \
    @@ -36,7 +37,7 @@ MAN+=	fclose.3 ferror.3 fflush.3 fgetln.3 fgets.3 fgetwln.3 fgetws.3 \
     	flockfile.3 \
     	fopen.3 fputs.3 \
     	fputws.3 fread.3 fseek.3 funopen.3 fwide.3 getc.3 \
    -	getline.3 getwc.3 mktemp.3 \
    +	getline.3 getwc.3 mktemp.3 open_memstream.3 \
     	printf.3 printf_l.3 putc.3 putwc.3 remove.3 scanf.3 scanf_l.3 setbuf.3 \
     	stdio.3 tmpnam.3 \
     	ungetc.3 ungetwc.3 wprintf.3 wscanf.3
    @@ -60,6 +61,7 @@ MLINKS+=getc.3 fgetc.3 getc.3 getc_unlocked.3 getc.3 getchar.3 \
     MLINKS+=getline.3 getdelim.3
     MLINKS+=getwc.3 fgetwc.3 getwc.3 getwchar.3
     MLINKS+=mktemp.3 mkdtemp.3 mktemp.3 mkstemp.3 mktemp.3 mkstemps.3
    +MLINKS+=open_memstream.3 open_wmemstream.3
     MLINKS+=printf.3 asprintf.3 printf.3 dprintf.3 printf.3 fprintf.3 \
     	printf.3 snprintf.3 printf.3 sprintf.3 \
     	printf.3 vasprintf.3 printf.3 vdprintf.3 \
    diff --git a/lib/libc/stdio/Symbol.map b/lib/libc/stdio/Symbol.map
    index b78de5a4d81..538b29aac4c 100644
    --- a/lib/libc/stdio/Symbol.map
    +++ b/lib/libc/stdio/Symbol.map
    @@ -156,6 +156,8 @@ FBSD_1.3 {
     	putwc_l;
     	putwchar_l;
     	fmemopen;
    +	open_memstream;
    +	open_wmemstream;
     };
     
     FBSDprivate_1.0 {
    diff --git a/lib/libc/stdio/open_memstream.3 b/lib/libc/stdio/open_memstream.3
    new file mode 100644
    index 00000000000..d03ed1fc7b5
    --- /dev/null
    +++ b/lib/libc/stdio/open_memstream.3
    @@ -0,0 +1,154 @@
    +.\" Copyright (c) 2013 Advanced Computing Technologies LLC
    +.\" Written by: John H. Baldwin 
    +.\" All rights reserved.
    +.\"
    +.\" Redistribution and use in source and binary forms, with or without
    +.\" modification, are permitted provided that the following conditions
    +.\" are met:
    +.\" 1. Redistributions of source code must retain the above copyright
    +.\"    notice, this list of conditions and the following disclaimer.
    +.\" 2. Redistributions in binary form must reproduce the above copyright
    +.\"    notice, this list of conditions and the following disclaimer in the
    +.\"    documentation and/or other materials provided with the distribution.
    +.\"
    +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
    +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    +.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
    +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    +.\" SUCH DAMAGE.
    +.\"
    +.\" $FreeBSD$
    +.\"
    +.Dd February 27, 2013
    +.Dt OPEN_MEMSTREAM 3
    +.Os
    +.Sh NAME
    +.Nm open_memstream ,
    +.Nm open_wmemstream
    +.Nd dynamic memory buffer stream open functions
    +.Sh LIBRARY
    +.Lb libc
    +.Sh SYNOPSIS
    +.In stdio.h
    +.Ft FILE *
    +.Fn open_memstream "char **bufp" "size_t **sizep"
    +.In wchar.h
    +.Ft FILE *
    +.Fn open_wmemstream "wchar_t **bufp" "size_t **sizep"
    +.Sh DESCRIPTION
    +The
    +.Fn open_memstream
    +and
    +.Fn open_wmemstream
    +functions create a write-only, seekable stream backed by a dynamically
    +allocated memory buffer.
    +The
    +.Fn open_memstream
    +function creates a byte-oriented stream,
    +while the
    +.Fn open_wmemstream
    +function creates a wide-oriented stream.
    +.Pp
    +Each stream maintains a current position and size.
    +Initially,
    +the position and size are set to zero.
    +Each write begins at the current position and advances it the number of
    +successfully written bytes for
    +.Fn open_memstream
    +or wide characters for
    +.Fn open_wmemstream .
    +If a write moves the current position beyond the length of the buffer,
    +the length of the buffer is extended and a null character is appended to the
    +buffer.
    +.Pp
    +A stream's buffer always contains a null character at the end of the buffer
    +that is not included in the current length.
    +.Pp
    +If a stream's current position is moved beyond the current length via a
    +seek operation and a write is performed,
    +the characters between the current length and the current position are filled
    +with null characters before the write is performed.
    +.Pp
    +After a successful call to
    +.Xr fclose 3
    +or
    +.Xr fflush 3 ,
    +the pointer referenced by
    +.Fa bufp
    +will contain the start of the memory buffer and the variable referenced by
    +.Fa sizep
    +will contain the smaller of the current position and the current buffer length.
    +.Pp
    +After a successful call to
    +.Xr fflush 3,
    +the pointer referenced by
    +.Fa bufp
    +and the variable referenced by
    +.Fa sizep
    +are only valid until the next write operation or a call to
    +.Xr fclose 3.
    +.Pp
    +Once a stream is closed,
    +the allocated buffer referenced by
    +.Fa bufp
    +should be released via a call to
    +.Xr free 3
    +when it is no longer needed.
    +.Sh IMPLEMENTATION NOTES
    +Internally all I/O streams are effectively byte-oriented,
    +so using wide-oriented operations to write to a stream opened via
    +.Fn open_wmemstream
    +results in wide characters being expanded to a stream of multibyte characters
    +in stdio's internal buffers.
    +These multibyte characters are then converted back to wide characters when
    +written into the stream.
    +As a result,
    +the wide-oriented streams maintain an internal multibyte character conversion
    +state that is cleared on any seek opertion that changes the current position.
    +This should have no effect as long as wide-oriented output operations are used
    +on a wide-oriented stream.
    +.Sh RETURN VALUES
    +Upon successful completion,
    +.Fn open_memstream
    +and
    +.Fn open_wmemstream
    +return a
    +.Tn FILE
    +pointer.
    +Otherwise,
    +.Dv NULL
    +is returned and the global variable
    +.Va errno
    +is set to indicate the error.
    +.Sh ERRORS
    +.Bl -tag -width Er
    +.It Bq Er EINVAL
    +The
    +.Fa bufp
    +or
    +.Fa sizep
    +argument was
    +.Dv NULL .
    +.It Bq Er ENOMEM
    +Memory for the stream or buffer could not be allocated.
    +.Sh SEE ALSO
    +.Xr fclose 3 ,
    +.Xr fflush 3 ,
    +.Xr fopen 3 ,
    +.Xr free 3 ,
    +.Xr fseek 3 ,
    +.Xr sbuf 3 ,
    +.Xr stdio 3
    +.Sh STANDARDS
    +The
    +.Fn open_memstream
    +and
    +.Fn open_wmemstream
    +functions conform to
    +.St -p1003.1-2008 .
    diff --git a/lib/libc/stdio/open_memstream.c b/lib/libc/stdio/open_memstream.c
    new file mode 100644
    index 00000000000..aa50822b152
    --- /dev/null
    +++ b/lib/libc/stdio/open_memstream.c
    @@ -0,0 +1,209 @@
    +/*-
    + * Copyright (c) 2013 Advanced Computing Technologies LLC
    + * Written by: John H. Baldwin 
    + * All rights reserved.
    + *
    + * Redistribution and use in source and binary forms, with or without
    + * modification, are permitted provided that the following conditions
    + * are met:
    + * 1. Redistributions of source code must retain the above copyright
    + *    notice, this list of conditions and the following disclaimer.
    + * 2. Redistributions in binary form must reproduce the above copyright
    + *    notice, this list of conditions and the following disclaimer in the
    + *    documentation and/or other materials provided with the distribution.
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
    + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
    + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    + * SUCH DAMAGE.
    + */
    +
    +#include 
    +__FBSDID("$FreeBSD$");
    +
    +#include "namespace.h"
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include "un-namespace.h"
    +
    +/* XXX: There is no FPOS_MAX.  This assumes fpos_t is an off_t. */
    +#define	FPOS_MAX	OFF_MAX
    +
    +struct memstream {
    +	char **bufp;
    +	size_t *sizep;
    +	ssize_t len;
    +	fpos_t offset;
    +};
    +
    +static int
    +memstream_grow(struct memstream *ms, fpos_t newoff)
    +{
    +	char *buf;
    +	ssize_t newsize;
    +
    +	if (newoff < 0 || newoff >= SSIZE_MAX)
    +		newsize = SSIZE_MAX - 1;
    +	else
    +		newsize = newoff;
    +	if (newsize > ms->len) {
    +		buf = realloc(*ms->bufp, newsize + 1);
    +		if (buf != NULL) {
    +#ifdef DEBUG
    +			fprintf(stderr, "MS: %p growing from %zd to %zd\n",
    +			    ms, ms->len, newsize);
    +#endif
    +			memset(buf + ms->len + 1, 0, newsize - ms->len);
    +			*ms->bufp = buf;
    +			ms->len = newsize;
    +			return (1);
    +		}
    +		return (0);
    +	}
    +	return (1);
    +}
    +
    +static void
    +memstream_update(struct memstream *ms)
    +{
    +
    +	assert(ms->len >= 0 && ms->offset >= 0);
    +	*ms->sizep = ms->len < ms->offset ? ms->len : ms->offset;
    +}
    +
    +static int
    +memstream_write(void *cookie, const char *buf, int len)
    +{
    +	struct memstream *ms;
    +	ssize_t tocopy;
    +
    +	ms = cookie;
    +	if (!memstream_grow(ms, ms->offset + len))
    +		return (-1);
    +	tocopy = ms->len - ms->offset;
    +	if (len < tocopy)
    +		tocopy = len;
    +	memcpy(*ms->bufp + ms->offset, buf, tocopy);
    +	ms->offset += tocopy;
    +	memstream_update(ms);
    +#ifdef DEBUG
    +	fprintf(stderr, "MS: write(%p, %d) = %zd\n", ms, len, tocopy);
    +#endif
    +	return (tocopy);
    +}
    +
    +static fpos_t
    +memstream_seek(void *cookie, fpos_t pos, int whence)
    +{
    +	struct memstream *ms;
    +#ifdef DEBUG
    +	fpos_t old;
    +#endif
    +
    +	ms = cookie;
    +#ifdef DEBUG
    +	old = ms->offset;
    +#endif
    +	switch (whence) {
    +	case SEEK_SET:
    +		/* _fseeko() checks for negative offsets. */
    +		assert(pos >= 0);
    +		ms->offset = pos;
    +		break;
    +	case SEEK_CUR:
    +		/* This is only called by _ftello(). */
    +		assert(pos == 0);
    +		break;
    +	case SEEK_END:
    +		if (pos < 0) {
    +			if (pos + ms->len < 0) {
    +#ifdef DEBUG
    +				fprintf(stderr,
    +				    "MS: bad SEEK_END: pos %jd, len %zd\n",
    +				    (intmax_t)pos, ms->len);
    +#endif
    +				errno = EINVAL;
    +				return (-1);
    +			}
    +		} else {
    +			if (FPOS_MAX - ms->len < pos) {
    +#ifdef DEBUG
    +				fprintf(stderr,
    +				    "MS: bad SEEK_END: pos %jd, len %zd\n",
    +				    (intmax_t)pos, ms->len);
    +#endif
    +				errno = EOVERFLOW;
    +				return (-1);
    +			}
    +		}
    +		ms->offset = ms->len + pos;
    +		break;
    +	}
    +	memstream_update(ms);
    +#ifdef DEBUG
    +	fprintf(stderr, "MS: seek(%p, %jd, %d) %jd -> %jd\n", ms, (intmax_t)pos,
    +	    whence, (intmax_t)old, (intmax_t)ms->offset);
    +#endif
    +	return (ms->offset);
    +}
    +
    +static int
    +memstream_close(void *cookie)
    +{
    +
    +	free(cookie);
    +	return (0);
    +}
    +
    +FILE *
    +open_memstream(char **bufp, size_t *sizep)
    +{
    +	struct memstream *ms;
    +	int save_errno;
    +	FILE *fp;
    +
    +	if (bufp == NULL || sizep == NULL) {
    +		errno = EINVAL;
    +		return (NULL);
    +	}
    +	*bufp = calloc(1, 1);
    +	if (*bufp == NULL)
    +		return (NULL);
    +	ms = malloc(sizeof(*ms));
    +	if (ms == NULL) {
    +		save_errno = errno;
    +		free(*bufp);
    +		*bufp = NULL;
    +		errno = save_errno;
    +		return (NULL);
    +	}
    +	ms->bufp = bufp;
    +	ms->sizep = sizep;
    +	ms->len = 0;
    +	ms->offset = 0;
    +	memstream_update(ms);
    +	fp = funopen(ms, NULL, memstream_write, memstream_seek,
    +	    memstream_close);
    +	if (fp == NULL) {
    +		save_errno = errno;
    +		free(ms);
    +		free(*bufp);
    +		*bufp = NULL;
    +		errno = save_errno;
    +		return (NULL);
    +	}
    +	fwide(fp, -1);
    +	return (fp);
    +}
    diff --git a/lib/libc/stdio/open_wmemstream.c b/lib/libc/stdio/open_wmemstream.c
    new file mode 100644
    index 00000000000..cf2968ae626
    --- /dev/null
    +++ b/lib/libc/stdio/open_wmemstream.c
    @@ -0,0 +1,271 @@
    +/*-
    + * Copyright (c) 2013 Advanced Computing Technologies LLC
    + * Written by: John H. Baldwin 
    + * All rights reserved.
    + *
    + * Redistribution and use in source and binary forms, with or without
    + * modification, are permitted provided that the following conditions
    + * are met:
    + * 1. Redistributions of source code must retain the above copyright
    + *    notice, this list of conditions and the following disclaimer.
    + * 2. Redistributions in binary form must reproduce the above copyright
    + *    notice, this list of conditions and the following disclaimer in the
    + *    documentation and/or other materials provided with the distribution.
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
    + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
    + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    + * SUCH DAMAGE.
    + */
    +
    +#include 
    +__FBSDID("$FreeBSD$");
    +
    +#include "namespace.h"
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include "un-namespace.h"
    +
    +/* XXX: There is no FPOS_MAX.  This assumes fpos_t is an off_t. */
    +#define	FPOS_MAX	OFF_MAX
    +
    +struct wmemstream {
    +	wchar_t **bufp;
    +	size_t *sizep;
    +	ssize_t len;
    +	fpos_t offset;
    +	mbstate_t mbstate;
    +};
    +
    +static int
    +wmemstream_grow(struct wmemstream *ms, fpos_t newoff)
    +{
    +	wchar_t *buf;
    +	ssize_t newsize;
    +
    +	if (newoff < 0 || newoff >= SSIZE_MAX / sizeof(wchar_t))
    +		newsize = SSIZE_MAX / sizeof(wchar_t) - 1;
    +	else
    +		newsize = newoff;
    +	if (newsize > ms->len) {
    +		buf = realloc(*ms->bufp, (newsize + 1) * sizeof(wchar_t));
    +		if (buf != NULL) {
    +#ifdef DEBUG
    +			fprintf(stderr, "WMS: %p growing from %zd to %zd\n",
    +			    ms, ms->len, newsize);
    +#endif
    +			wmemset(buf + ms->len + 1, 0, newsize - ms->len);
    +			*ms->bufp = buf;
    +			ms->len = newsize;
    +			return (1);
    +		}
    +		return (0);
    +	}
    +	return (1);
    +}
    +
    +static void
    +wmemstream_update(struct wmemstream *ms)
    +{
    +
    +	assert(ms->len >= 0 && ms->offset >= 0);
    +	*ms->sizep = ms->len < ms->offset ? ms->len : ms->offset;
    +}
    +
    +/*
    + * Based on a starting multibyte state and an input buffer, determine
    + * how many wchar_t's would be output.  This doesn't use mbsnrtowcs()
    + * so that it can handle embedded null characters.
    + */
    +static size_t
    +wbuflen(const mbstate_t *state, const char *buf, int len)
    +{
    +	mbstate_t lenstate;
    +	size_t charlen, count;
    +
    +	count = 0;
    +	lenstate = *state;
    +	while (len > 0) {
    +		charlen = mbrlen(buf, len, &lenstate);
    +		if (charlen == (size_t)-1)
    +			return (-1);
    +		if (charlen == (size_t)-2)
    +			break;
    +		if (charlen == 0)
    +			/* XXX: Not sure how else to handle this. */
    +			charlen = 1;
    +		len -= charlen;
    +		buf += charlen;
    +		count++;
    +	}
    +	return (count);
    +}
    +
    +static int
    +wmemstream_write(void *cookie, const char *buf, int len)
    +{
    +	struct wmemstream *ms;
    +	ssize_t consumed, wlen;
    +	size_t charlen;
    +
    +	ms = cookie;
    +	wlen = wbuflen(&ms->mbstate, buf, len);
    +	if (wlen < 0) {
    +		errno = EILSEQ;
    +		return (-1);
    +	}
    +	if (!wmemstream_grow(ms, ms->offset + wlen))
    +		return (-1);
    +
    +	/*
    +	 * This copies characters one at a time rather than using
    +	 * mbsnrtowcs() so it can properly handle embedded null
    +	 * characters.
    +	 */
    +	consumed = 0;
    +	while (len > 0 && ms->offset < ms->len) {
    +		charlen = mbrtowc(*ms->bufp + ms->offset, buf, len,
    +		    &ms->mbstate);
    +		if (charlen == (size_t)-1) {
    +			if (consumed == 0) {
    +				errno = EILSEQ;
    +				return (-1);
    +			}
    +			/* Treat it as a successful short write. */
    +			break;
    +		}
    +		if (charlen == 0)
    +			/* XXX: Not sure how else to handle this. */
    +			charlen = 1;
    +		if (charlen == (size_t)-2) {
    +			consumed += len;
    +			len = 0;
    +		} else {
    +			consumed += charlen;
    +			buf += charlen;
    +			len -= charlen;
    +			ms->offset++;
    +		}
    +	}
    +	wmemstream_update(ms);
    +#ifdef DEBUG
    +	fprintf(stderr, "WMS: write(%p, %d) = %zd\n", ms, len, consumed);
    +#endif
    +	return (consumed);
    +}
    +
    +static fpos_t
    +wmemstream_seek(void *cookie, fpos_t pos, int whence)
    +{
    +	struct wmemstream *ms;
    +	fpos_t old;
    +
    +	ms = cookie;
    +	old = ms->offset;
    +	switch (whence) {
    +	case SEEK_SET:
    +		/* _fseeko() checks for negative offsets. */
    +		assert(pos >= 0);
    +		ms->offset = pos;
    +		break;
    +	case SEEK_CUR:
    +		/* This is only called by _ftello(). */
    +		assert(pos == 0);
    +		break;
    +	case SEEK_END:
    +		if (pos < 0) {
    +			if (pos + ms->len < 0) {
    +#ifdef DEBUG
    +				fprintf(stderr,
    +				    "WMS: bad SEEK_END: pos %jd, len %zd\n",
    +				    (intmax_t)pos, ms->len);
    +#endif
    +				errno = EINVAL;
    +				return (-1);
    +			}
    +		} else {
    +			if (FPOS_MAX - ms->len < pos) {
    +#ifdef DEBUG
    +				fprintf(stderr,
    +				    "WMS: bad SEEK_END: pos %jd, len %zd\n",
    +				    (intmax_t)pos, ms->len);
    +#endif
    +				errno = EOVERFLOW;
    +				return (-1);
    +			}
    +		}
    +		ms->offset = ms->len + pos;
    +		break;
    +	}
    +	/* Reset the multibyte state if a seek changes the position. */
    +	if (ms->offset != old)
    +		memset(&ms->mbstate, 0, sizeof(ms->mbstate));
    +	wmemstream_update(ms);
    +#ifdef DEBUG
    +	fprintf(stderr, "WMS: seek(%p, %jd, %d) %jd -> %jd\n", ms,
    +	    (intmax_t)pos, whence, (intmax_t)old, (intmax_t)ms->offset);
    +#endif
    +	return (ms->offset);
    +}
    +
    +static int
    +wmemstream_close(void *cookie)
    +{
    +
    +	free(cookie);
    +	return (0);
    +}
    +
    +FILE *
    +open_wmemstream(wchar_t **bufp, size_t *sizep)
    +{
    +	struct wmemstream *ms;
    +	int save_errno;
    +	FILE *fp;
    +
    +	if (bufp == NULL || sizep == NULL) {
    +		errno = EINVAL;
    +		return (NULL);
    +	}
    +	*bufp = calloc(1, sizeof(wchar_t));
    +	if (*bufp == NULL)
    +		return (NULL);
    +	ms = malloc(sizeof(*ms));
    +	if (ms == NULL) {
    +		save_errno = errno;
    +		free(*bufp);
    +		*bufp = NULL;
    +		errno = save_errno;
    +		return (NULL);
    +	}
    +	ms->bufp = bufp;
    +	ms->sizep = sizep;
    +	ms->len = 0;
    +	ms->offset = 0;
    +	memset(&ms->mbstate, 0, sizeof(mbstate_t));
    +	wmemstream_update(ms);
    +	fp = funopen(ms, NULL, wmemstream_write, wmemstream_seek,
    +	    wmemstream_close);
    +	if (fp == NULL) {
    +		save_errno = errno;
    +		free(ms);
    +		free(*bufp);
    +		*bufp = NULL;
    +		errno = save_errno;
    +		return (NULL);
    +	}
    +	fwide(fp, 1);
    +	return (fp);
    +}
    diff --git a/tools/regression/lib/libc/stdio/Makefile b/tools/regression/lib/libc/stdio/Makefile
    index d62ac84bf6e..f496f73f86e 100644
    --- a/tools/regression/lib/libc/stdio/Makefile
    +++ b/tools/regression/lib/libc/stdio/Makefile
    @@ -1,6 +1,8 @@
     # $FreeBSD$
     
    -TESTS=	test-getdelim test-perror test-print-positional test-printbasic test-printfloat test-scanfloat
    +TESTS=	test-fmemopen test-getdelim test-open_memstream test-open_wmemstream \
    +	test-perror test-print-positional test-printbasic test-printfloat \
    +	test-scanfloat 
     CFLAGS+= -lm
     
     .PHONY: tests
    diff --git a/tools/regression/lib/libc/stdio/test-open_memstream.c b/tools/regression/lib/libc/stdio/test-open_memstream.c
    new file mode 100644
    index 00000000000..1a168c65828
    --- /dev/null
    +++ b/tools/regression/lib/libc/stdio/test-open_memstream.c
    @@ -0,0 +1,203 @@
    +/*-
    + * Copyright (c) 2013 Advanced Computing Technologies LLC
    + * Written by: John H. Baldwin 
    + * All rights reserved.
    + *
    + * Redistribution and use in source and binary forms, with or without
    + * modification, are permitted provided that the following conditions
    + * are met:
    + * 1. Redistributions of source code must retain the above copyright
    + *    notice, this list of conditions and the following disclaimer.
    + * 2. Redistributions in binary form must reproduce the above copyright
    + *    notice, this list of conditions and the following disclaimer in the
    + *    documentation and/or other materials provided with the distribution.
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
    + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
    + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    + * SUCH DAMAGE.
    + */
    +
    +#include 
    +__FBSDID("$FreeBSD$");
    +
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +
    +static char *buf;
    +static size_t len;
    +
    +static void
    +assert_stream(const char *contents)
    +{
    +	if (strlen(contents) != len)
    +		printf("bad length %zd for \"%s\"\n", len, contents);
    +	else if (strncmp(buf, contents, strlen(contents)) != 0)
    +		printf("bad buffer \"%s\" for \"%s\"\n", buf, contents);
    +}
    +
    +static void
    +open_group_test(void)
    +{
    +	FILE *fp;
    +	off_t eob;
    +
    +	fp = open_memstream(&buf, &len);
    +	if (fp == NULL)
    +		err(1, "failed to open stream");
    +
    +	fprintf(fp, "hello my world");
    +	fflush(fp);
    +	assert_stream("hello my world");
    +	eob = ftello(fp);
    +	rewind(fp);
    +	fprintf(fp, "good-bye");
    +	fseeko(fp, eob, SEEK_SET);
    +	fclose(fp);
    +	assert_stream("good-bye world");
    +	free(buf);
    +}
    +
    +static void
    +simple_tests(void)
    +{
    +	static const char zerobuf[] =
    +	    { 'f', 'o', 'o', 0, 0, 0, 0, 'b', 'a', 'r', 0 };
    +	char c;
    +	FILE *fp;
    +
    +	fp = open_memstream(&buf, NULL);
    +	if (fp != NULL)
    +		errx(1, "did not fail to open stream");
    +	else if (errno != EINVAL)
    +		err(1, "incorrect error for bad length pointer");
    +	fp = open_memstream(NULL, &len);
    +	if (fp != NULL)
    +		errx(1, "did not fail to open stream");
    +	else if (errno != EINVAL)
    +		err(1, "incorrect error for bad buffer pointer");
    +	fp = open_memstream(&buf, &len);
    +	if (fp == NULL)
    +		err(1, "failed to open stream");
    +	fflush(fp);
    +	assert_stream("");
    +	if (fwide(fp, 0) >= 0)
    +		printf("stream is not byte-oriented\n");
    +
    +	fprintf(fp, "fo");
    +	fflush(fp);
    +	assert_stream("fo");
    +	fputc('o', fp);
    +	fflush(fp);
    +	assert_stream("foo");
    +	rewind(fp);
    +	fflush(fp);
    +	assert_stream("");
    +	fseek(fp, 0, SEEK_END);
    +	fflush(fp);
    +	assert_stream("foo");
    +
    +	/*
    +	 * Test seeking out past the current end.  Should zero-fill the
    +	 * intermediate area.
    +	 */
    +	fseek(fp, 4, SEEK_END);
    +	fprintf(fp, "bar");
    +	fflush(fp);
    +
    +	/*
    +	 * Can't use assert_stream() here since this should contain
    +	 * embedded null characters.
    +	 */
    +	if (len != 10)
    +		printf("bad length %zd for zero-fill test\n", len);
    +	else if (memcmp(buf, zerobuf, sizeof(zerobuf)) != 0)
    +		printf("bad buffer for zero-fill test\n");
    +
    +	fseek(fp, 3, SEEK_SET);
    +	fprintf(fp, " in ");
    +	fflush(fp);
    +	assert_stream("foo in ");
    +	fseek(fp, 0, SEEK_END);
    +	fflush(fp);
    +	assert_stream("foo in bar");
    +
    +	rewind(fp);
    +	if (fread(&c, sizeof(c), 1, fp) != 0)
    +		printf("fread did not fail\n");
    +	else if (!ferror(fp))
    +		printf("error indicator not set after fread\n");
    +	else
    +		clearerr(fp);
    +
    +	fseek(fp, 4, SEEK_SET);
    +	fprintf(fp, "bar baz");
    +	fclose(fp);
    +	assert_stream("foo bar baz");
    +	free(buf);
    +}
    +
    +static void
    +seek_tests(void)
    +{
    +	FILE *fp;
    +
    +	fp = open_memstream(&buf, &len);
    +	if (fp == NULL)
    +		err(1, "failed to open stream");
    +#define SEEK_FAIL(offset, whence, error) do {				\
    +	errno = 0;							\
    +	if (fseeko(fp, (offset), (whence)) == 0)			\
    +		printf("fseeko(%s, %s) did not fail, set pos to %jd\n",	\
    +		    __STRING(offset), __STRING(whence),			\
    +		    (intmax_t)ftello(fp));				\
    +	else if (errno != (error))					\
    +		printf("fseeko(%s, %s) failed with %d rather than %s\n",\
    +		    __STRING(offset), __STRING(whence),	errno,		\
    +		    __STRING(error));					\
    +} while (0)
    +
    +#define SEEK_OK(offset, whence, result) do {				\
    +	if (fseeko(fp, (offset), (whence)) != 0)			\
    +		printf("fseeko(%s, %s) failed: %s\n",			\
    +		    __STRING(offset), __STRING(whence),	strerror(errno)); \
    +	else if (ftello(fp) != (result))				\
    +		printf("fseeko(%s, %s) seeked to %jd rather than %s\n",	\
    +		    __STRING(offset), __STRING(whence),			\
    +		    (intmax_t)ftello(fp), __STRING(result));		\
    +} while (0)
    +
    +	SEEK_FAIL(-1, SEEK_SET, EINVAL);
    +	SEEK_FAIL(-1, SEEK_CUR, EINVAL);
    +	SEEK_FAIL(-1, SEEK_END, EINVAL);
    +	fprintf(fp, "foo");
    +	SEEK_OK(-1, SEEK_CUR, 2);
    +	SEEK_OK(0, SEEK_SET, 0);
    +	SEEK_OK(-1, SEEK_END, 2);
    +	SEEK_OK(OFF_MAX - 1, SEEK_SET, OFF_MAX - 1);
    +	SEEK_FAIL(2, SEEK_CUR, EOVERFLOW);
    +	fclose(fp);
    +}
    +
    +int
    +main(int ac, char **av)
    +{
    +
    +	open_group_test();
    +	simple_tests();
    +	seek_tests();
    +	return (0);
    +}
    diff --git a/tools/regression/lib/libc/stdio/test-open_memstream.t b/tools/regression/lib/libc/stdio/test-open_memstream.t
    new file mode 100644
    index 00000000000..8bdfd03be81
    --- /dev/null
    +++ b/tools/regression/lib/libc/stdio/test-open_memstream.t
    @@ -0,0 +1,10 @@
    +#!/bin/sh
    +# $FreeBSD$
    +
    +cd `dirname $0`
    +
    +executable=`basename $0 .t`
    +
    +make $executable 2>&1 > /dev/null
    +
    +exec ./$executable
    diff --git a/tools/regression/lib/libc/stdio/test-open_wmemstream.c b/tools/regression/lib/libc/stdio/test-open_wmemstream.c
    new file mode 100644
    index 00000000000..4cd0ab9544d
    --- /dev/null
    +++ b/tools/regression/lib/libc/stdio/test-open_wmemstream.c
    @@ -0,0 +1,203 @@
    +/*-
    + * Copyright (c) 2013 Advanced Computing Technologies LLC
    + * Written by: John H. Baldwin 
    + * All rights reserved.
    + *
    + * Redistribution and use in source and binary forms, with or without
    + * modification, are permitted provided that the following conditions
    + * are met:
    + * 1. Redistributions of source code must retain the above copyright
    + *    notice, this list of conditions and the following disclaimer.
    + * 2. Redistributions in binary form must reproduce the above copyright
    + *    notice, this list of conditions and the following disclaimer in the
    + *    documentation and/or other materials provided with the distribution.
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
    + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
    + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    + * SUCH DAMAGE.
    + */
    +
    +#include 
    +__FBSDID("$FreeBSD$");
    +
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +
    +static wchar_t *buf;
    +static size_t len;
    +
    +static void
    +assert_stream(const wchar_t *contents)
    +{
    +	if (wcslen(contents) != len)
    +		printf("bad length %zd for \"%ls\"\n", len, contents);
    +	else if (wcsncmp(buf, contents, wcslen(contents)) != 0)
    +		printf("bad buffer \"%ls\" for \"%ls\"\n", buf, contents);
    +}
    +
    +static void
    +open_group_test(void)
    +{
    +	FILE *fp;
    +	off_t eob;
    +
    +	fp = open_wmemstream(&buf, &len);
    +	if (fp == NULL)
    +		err(1, "failed to open stream");
    +
    +	fwprintf(fp, L"hello my world");
    +	fflush(fp);
    +	assert_stream(L"hello my world");
    +	eob = ftello(fp);
    +	rewind(fp);
    +	fwprintf(fp, L"good-bye");
    +	fseeko(fp, eob, SEEK_SET);
    +	fclose(fp);
    +	assert_stream(L"good-bye world");
    +	free(buf);
    +}
    +
    +static void
    +simple_tests(void)
    +{
    +	static const wchar_t zerobuf[] =
    +	    { L'f', L'o', L'o', 0, 0, 0, 0, L'b', L'a', L'r', 0 };
    +	wchar_t c;
    +	FILE *fp;
    +
    +	fp = open_wmemstream(&buf, NULL);
    +	if (fp != NULL)
    +		errx(1, "did not fail to open stream");
    +	else if (errno != EINVAL)
    +		err(1, "incorrect error for bad length pointer");
    +	fp = open_wmemstream(NULL, &len);
    +	if (fp != NULL)
    +		errx(1, "did not fail to open stream");
    +	else if (errno != EINVAL)
    +		err(1, "incorrect error for bad buffer pointer");
    +	fp = open_wmemstream(&buf, &len);
    +	if (fp == NULL)
    +		err(1, "failed to open stream");
    +	fflush(fp);
    +	assert_stream(L"");
    +	if (fwide(fp, 0) <= 0)
    +		printf("stream is not wide-oriented\n");
    +
    +	fwprintf(fp, L"fo");
    +	fflush(fp);
    +	assert_stream(L"fo");
    +	fputwc(L'o', fp);
    +	fflush(fp);
    +	assert_stream(L"foo");
    +	rewind(fp);
    +	fflush(fp);
    +	assert_stream(L"");
    +	fseek(fp, 0, SEEK_END);
    +	fflush(fp);
    +	assert_stream(L"foo");
    +
    +	/*
    +	 * Test seeking out past the current end.  Should zero-fill the
    +	 * intermediate area.
    +	 */
    +	fseek(fp, 4, SEEK_END);
    +	fwprintf(fp, L"bar");
    +	fflush(fp);
    +
    +	/*
    +	 * Can't use assert_stream() here since this should contain
    +	 * embedded null characters.
    +	 */
    +	if (len != 10)
    +		printf("bad length %zd for zero-fill test\n", len);
    +	else if (memcmp(buf, zerobuf, sizeof(zerobuf)) != 0)
    +		printf("bad buffer for zero-fill test\n");
    +
    +	fseek(fp, 3, SEEK_SET);
    +	fwprintf(fp, L" in ");
    +	fflush(fp);
    +	assert_stream(L"foo in ");
    +	fseek(fp, 0, SEEK_END);
    +	fflush(fp);
    +	assert_stream(L"foo in bar");
    +
    +	rewind(fp);
    +	if (fread(&c, sizeof(c), 1, fp) != 0)
    +		printf("fread did not fail\n");
    +	else if (!ferror(fp))
    +		printf("error indicator not set after fread\n");
    +	else
    +		clearerr(fp);
    +
    +	fseek(fp, 4, SEEK_SET);
    +	fwprintf(fp, L"bar baz");
    +	fclose(fp);
    +	assert_stream(L"foo bar baz");
    +	free(buf);
    +}
    +
    +static void
    +seek_tests(void)
    +{
    +	FILE *fp;
    +
    +	fp = open_wmemstream(&buf, &len);
    +	if (fp == NULL)
    +		err(1, "failed to open stream");
    +#define SEEK_FAIL(offset, whence, error) do {				\
    +	errno = 0;							\
    +	if (fseeko(fp, (offset), (whence)) == 0)			\
    +		printf("fseeko(%s, %s) did not fail, set pos to %jd\n",	\
    +		    __STRING(offset), __STRING(whence),			\
    +		    (intmax_t)ftello(fp));				\
    +	else if (errno != (error))					\
    +		printf("fseeko(%s, %s) failed with %d rather than %s\n",\
    +		    __STRING(offset), __STRING(whence),	errno,		\
    +		    __STRING(error));					\
    +} while (0)
    +
    +#define SEEK_OK(offset, whence, result) do {				\
    +	if (fseeko(fp, (offset), (whence)) != 0)			\
    +		printf("fseeko(%s, %s) failed: %s\n",			\
    +		    __STRING(offset), __STRING(whence),	strerror(errno)); \
    +	else if (ftello(fp) != (result))				\
    +		printf("fseeko(%s, %s) seeked to %jd rather than %s\n",	\
    +		    __STRING(offset), __STRING(whence),			\
    +		    (intmax_t)ftello(fp), __STRING(result));		\
    +} while (0)
    +
    +	SEEK_FAIL(-1, SEEK_SET, EINVAL);
    +	SEEK_FAIL(-1, SEEK_CUR, EINVAL);
    +	SEEK_FAIL(-1, SEEK_END, EINVAL);
    +	fwprintf(fp, L"foo");
    +	SEEK_OK(-1, SEEK_CUR, 2);
    +	SEEK_OK(0, SEEK_SET, 0);
    +	SEEK_OK(-1, SEEK_END, 2);
    +	SEEK_OK(OFF_MAX - 1, SEEK_SET, OFF_MAX - 1);
    +	SEEK_FAIL(2, SEEK_CUR, EOVERFLOW);
    +	fclose(fp);
    +}
    +
    +int
    +main(int ac, char **av)
    +{
    +
    +	open_group_test();
    +	simple_tests();
    +	seek_tests();
    +	return (0);
    +}
    diff --git a/tools/regression/lib/libc/stdio/test-open_wmemstream.t b/tools/regression/lib/libc/stdio/test-open_wmemstream.t
    new file mode 100644
    index 00000000000..8bdfd03be81
    --- /dev/null
    +++ b/tools/regression/lib/libc/stdio/test-open_wmemstream.t
    @@ -0,0 +1,10 @@
    +#!/bin/sh
    +# $FreeBSD$
    +
    +cd `dirname $0`
    +
    +executable=`basename $0 .t`
    +
    +make $executable 2>&1 > /dev/null
    +
    +exec ./$executable
    
    From e045904fdc942fb55c4b8004aad40dfcec946fcb Mon Sep 17 00:00:00 2001
    From: Michael Tuexen 
    Date: Wed, 27 Feb 2013 19:51:47 +0000
    Subject: [PATCH 0457/1476] Fix a potential race in returning setting errno
     when an association goes down. Reported by Mozilla in
     https://bugzilla.mozilla.org/show_bug.cgi?id=845513
    
    MFC after: 3 days
    ---
     sys/netinet/sctputil.c | 3 ++-
     1 file changed, 2 insertions(+), 1 deletion(-)
    
    diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
    index fe2b9459a40..7bd8c7a9bd8 100644
    --- a/sys/netinet/sctputil.c
    +++ b/sys/netinet/sctputil.c
    @@ -2678,6 +2678,7 @@ set_error:
     	if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
     	    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
     	    ((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC))) {
    +		SOCK_LOCK(stcb->sctp_socket);
     		if (from_peer) {
     			if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) {
     				SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ECONNREFUSED);
    @@ -2709,7 +2710,7 @@ set_error:
     	if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
     	    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
     	    ((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC))) {
    -		socantrcvmore(stcb->sctp_socket);
    +		socantrcvmore_locked(stcb->sctp_socket);
     	}
     	sorwakeup(stcb->sctp_socket);
     	sowwakeup(stcb->sctp_socket);
    
    From 62e939ea178844b69446527f350a647c49699cc0 Mon Sep 17 00:00:00 2001
    From: Ian Lepore 
    Date: Wed, 27 Feb 2013 19:59:41 +0000
    Subject: [PATCH 0458/1476] Fix a typo that prevented booting a kernel that had
     virtual addresses in the elf headers.
    
    ---
     sys/boot/common/load_elf.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/sys/boot/common/load_elf.c b/sys/boot/common/load_elf.c
    index d712b3d3004..3a4152e7afb 100644
    --- a/sys/boot/common/load_elf.c
    +++ b/sys/boot/common/load_elf.c
    @@ -304,7 +304,7 @@ __elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, u_int64_t off)
     	 * only adjust the entry point if it's a virtual address to begin with.
     	 */
     	off = -0xc0000000u;
    -	if ((ehdr->e_entry & 0xc0000000u) == 0xc000000u)
    +	if ((ehdr->e_entry & 0xc0000000u) == 0xc0000000u)
     		ehdr->e_entry += off;
     #ifdef ELF_VERBOSE
     	printf("ehdr->e_entry 0x%08x, va<->pa off %llx\n", ehdr->e_entry, off);
    
    From 80ff58b89dcacfe07fe20b045890df9db5ca0af0 Mon Sep 17 00:00:00 2001
    From: John-Mark Gurney 
    Date: Wed, 27 Feb 2013 19:59:58 +0000
    Subject: [PATCH 0459/1476] fix this script so we don't expand the second
     $FreeBSD since svn thinks the $ in $1 ends the keyword, and expands it...
    
    ---
     tools/test/iconv/tablegen/cmp.sh | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/tools/test/iconv/tablegen/cmp.sh b/tools/test/iconv/tablegen/cmp.sh
    index 50664c422e9..349c08f6e03 100755
    --- a/tools/test/iconv/tablegen/cmp.sh
    +++ b/tools/test/iconv/tablegen/cmp.sh
    @@ -1,4 +1,4 @@
     #!/bin/sh
     # $FreeBSD$
     
    -diff -I\$FreeBSD$1 $2 | grep '^-' >/dev/null && printf "\tDIFFER: $1 $2\n" && exit 0 || exit 0
    +diff -I\$\FreeBSD $1 $2 | grep '^-' >/dev/null && printf "\tDIFFER: $1 $2\n" && exit 0 || exit 0
    
    From 1046c6427e0c3f8bc989fa6a1816fe1b26b0eafb Mon Sep 17 00:00:00 2001
    From: Joel Dahl 
    Date: Wed, 27 Feb 2013 20:09:25 +0000
    Subject: [PATCH 0460/1476] mdoc: add missing El.
    
    ---
     lib/libc/stdio/open_memstream.3 | 1 +
     1 file changed, 1 insertion(+)
    
    diff --git a/lib/libc/stdio/open_memstream.3 b/lib/libc/stdio/open_memstream.3
    index d03ed1fc7b5..939683036b5 100644
    --- a/lib/libc/stdio/open_memstream.3
    +++ b/lib/libc/stdio/open_memstream.3
    @@ -137,6 +137,7 @@ argument was
     .Dv NULL .
     .It Bq Er ENOMEM
     Memory for the stream or buffer could not be allocated.
    +.El
     .Sh SEE ALSO
     .Xr fclose 3 ,
     .Xr fflush 3 ,
    
    From 42e7fa7e098a659161b9261a0de31000e1c46d62 Mon Sep 17 00:00:00 2001
    From: Joel Dahl 
    Date: Wed, 27 Feb 2013 20:15:06 +0000
    Subject: [PATCH 0461/1476] mdoc: begin sentence on new line.
    
    ---
     usr.sbin/watchdogd/watchdogd.8 | 16 ++++++++++------
     1 file changed, 10 insertions(+), 6 deletions(-)
    
    diff --git a/usr.sbin/watchdogd/watchdogd.8 b/usr.sbin/watchdogd/watchdogd.8
    index 096eb9d55b7..3666a5ae3c2 100644
    --- a/usr.sbin/watchdogd/watchdogd.8
    +++ b/usr.sbin/watchdogd/watchdogd.8
    @@ -132,23 +132,27 @@ This flag will cause watchdogd to complain when the amount of time to
     execute the watchdog script exceeds the threshold of 'sleep' option.
     .Pp
     .It Fl -pretimeout Ar timeout
    -Set a "pretimeout" watchdog.  At "timeout" seconds before the watchdog
    -will fire attempt an action.  The action is set by the --pretimeout-action
    -flag.  The default is just to log a message (WD_SOFT_LOG) via
    +Set a "pretimeout" watchdog.
    +At "timeout" seconds before the watchdog will fire attempt an action.
    +The action is set by the --pretimeout-action flag.
    +The default is just to log a message (WD_SOFT_LOG) via
     .Xr log 9 .
     .Pp
     .It Fl -pretimeout-action Ar action
    -Set the timeout action for the pretimeout.  See the section 
    +Set the timeout action for the pretimeout.
    +See the section 
     .Sx Timeout Actions .
     .Pp
     .It Fl -softtimeout
     Instead of arming the various hardware watchdogs, only use a basic software
    -watchdog.  The default action is just to
    +watchdog.
    +The default action is just to
     .Xr log 9
     a message (WD_SOFT_LOG).
     .Pp
     .It Fl -softtimeout-action Ar action
    -Set the timeout action for the softtimeout.  See the section 
    +Set the timeout action for the softtimeout.
    +See the section 
     .Sx Timeout Actions .
     .Pp
     .El
    
    From 06db73ec2b89430bcb2a812cbf4ad6b99333ebe0 Mon Sep 17 00:00:00 2001
    From: Joel Dahl 
    Date: Wed, 27 Feb 2013 20:16:30 +0000
    Subject: [PATCH 0462/1476] Remove EOL whitespace.
    
    ---
     usr.sbin/watchdogd/watchdogd.8 | 8 ++++----
     1 file changed, 4 insertions(+), 4 deletions(-)
    
    diff --git a/usr.sbin/watchdogd/watchdogd.8 b/usr.sbin/watchdogd/watchdogd.8
    index 3666a5ae3c2..3fb61f6c877 100644
    --- a/usr.sbin/watchdogd/watchdogd.8
    +++ b/usr.sbin/watchdogd/watchdogd.8
    @@ -100,7 +100,7 @@ that its script has run for too long.
     If unset
     .Ar script_timeout
     defaults to the value specified by the
    -.Fl s Ar sleep 
    +.Fl s Ar sleep
     option.
     .Pp
     Upon receiving the
    @@ -140,7 +140,7 @@ The default is just to log a message (WD_SOFT_LOG) via
     .Pp
     .It Fl -pretimeout-action Ar action
     Set the timeout action for the pretimeout.
    -See the section 
    +See the section
     .Sx Timeout Actions .
     .Pp
     .It Fl -softtimeout
    @@ -152,7 +152,7 @@ a message (WD_SOFT_LOG).
     .Pp
     .It Fl -softtimeout-action Ar action
     Set the timeout action for the softtimeout.
    -See the section 
    +See the section
     .Sx Timeout Actions .
     .Pp
     .El
    @@ -179,7 +179,7 @@ Log a message using
     when the timeout is reached.
     .Pp
     .It Ar printf
    -call the kernel 
    +call the kernel
     .Xr printf 9
     to display a message to the console and
     .Xr dmesg 8
    
    From 20a011d5b3a78a3d4943eefecb57f4b3bb61ece1 Mon Sep 17 00:00:00 2001
    From: Xin LI 
    Date: Wed, 27 Feb 2013 21:58:06 +0000
    Subject: [PATCH 0463/1476] Add a reminder that the user should update boot
     block if they are upgrading their existing system and use LZ4 compression for
     ZFS.
    
    Suggested by:	mm
    MFC after:	3 days
    ---
     UPDATING | 7 +++++++
     1 file changed, 7 insertions(+)
    
    diff --git a/UPDATING b/UPDATING
    index 20e375ccbce..8be2f464462 100644
    --- a/UPDATING
    +++ b/UPDATING
    @@ -26,6 +26,13 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 10.x IS SLOW:
     	disable the most expensive debugging functionality run
     	"ln -s 'abort:false,junk:false' /etc/malloc.conf".)
     
    +20130208:
    +	A new compression method (lz4) has been merged to -HEAD.  Please
    +	refer to zpool-features(7) for more information.
    +
    +	Please refer to the "ZFS notes" section of this file for information
    +	on upgrading boot ZFS pools.
    +
     20130129:
     	A BSD-licensed patch(1) variant has been added and is installed
     	as bsdpatch, being the GNU version the default patch.
    
    From f108bdaa19164e3e85ce171cd57176cc02a36ba1 Mon Sep 17 00:00:00 2001
    From: Steven Hartland 
    Date: Wed, 27 Feb 2013 23:17:45 +0000
    Subject: [PATCH 0464/1476] Adds hw.mfi.cmd_timeout loader / sysctl tuneable
     which controls the default timeout used in the mfi driver. This is useful for
     long running commands such as secure erase.
    
    Reviewed by:	John Baldwin
    Approved by:	pjd (mentor)
    ---
     sys/dev/mfi/mfi.c | 16 +++++++++++-----
     1 file changed, 11 insertions(+), 5 deletions(-)
    
    diff --git a/sys/dev/mfi/mfi.c b/sys/dev/mfi/mfi.c
    index e799b9dc967..e2401f6ee51 100644
    --- a/sys/dev/mfi/mfi.c
    +++ b/sys/dev/mfi/mfi.c
    @@ -157,6 +157,11 @@ SYSCTL_INT(_hw_mfi, OID_AUTO, polled_cmd_timeout, CTLFLAG_RWTUN,
     	   &mfi_polled_cmd_timeout, 0,
     	   "Polled command timeout - used for firmware flash etc (in seconds)");
     
    +static int	mfi_cmd_timeout = MFI_CMD_TIMEOUT;
    +TUNABLE_INT("hw.mfi.cmd_timeout", &mfi_cmd_timeout);
    +SYSCTL_INT(_hw_mfi, OID_AUTO, cmd_timeout, CTLFLAG_RWTUN, &mfi_cmd_timeout,
    +	   0, "Command timeout (in seconds)");
    +
     /* Management interface */
     static d_open_t		mfi_open;
     static d_close_t	mfi_close;
    @@ -782,7 +787,7 @@ mfi_attach(struct mfi_softc *sc)
     
     	/* Start the timeout watchdog */
     	callout_init(&sc->mfi_watchdog_callout, CALLOUT_MPSAFE);
    -	callout_reset(&sc->mfi_watchdog_callout, MFI_CMD_TIMEOUT * hz,
    +	callout_reset(&sc->mfi_watchdog_callout, mfi_cmd_timeout * hz,
     	    mfi_timeout, sc);
     
     	if (sc->mfi_flags & MFI_FLAGS_TBOLT) {
    @@ -3714,7 +3719,7 @@ mfi_dump_all(void)
     			break;
     		device_printf(sc->mfi_dev, "Dumping\n\n");
     		timedout = 0;
    -		deadline = time_uptime - MFI_CMD_TIMEOUT;
    +		deadline = time_uptime - mfi_cmd_timeout;
     		mtx_lock(&sc->mfi_io_lock);
     		TAILQ_FOREACH(cm, &sc->mfi_busy, cm_link) {
     			if (cm->cm_timestamp <= deadline) {
    @@ -3745,10 +3750,11 @@ mfi_timeout(void *data)
     	time_t deadline;
     	int timedout = 0;
     
    -	deadline = time_uptime - MFI_CMD_TIMEOUT;
    +	deadline = time_uptime - mfi_cmd_timeout;
     	if (sc->adpreset == 0) {
     		if (!mfi_tbolt_reset(sc)) {
    -			callout_reset(&sc->mfi_watchdog_callout, MFI_CMD_TIMEOUT * hz, mfi_timeout, sc);
    +			callout_reset(&sc->mfi_watchdog_callout,
    +			    mfi_cmd_timeout * hz, mfi_timeout, sc);
     			return;
     		}
     	}
    @@ -3785,7 +3791,7 @@ mfi_timeout(void *data)
     
     	mtx_unlock(&sc->mfi_io_lock);
     
    -	callout_reset(&sc->mfi_watchdog_callout, MFI_CMD_TIMEOUT * hz,
    +	callout_reset(&sc->mfi_watchdog_callout, mfi_cmd_timeout * hz,
     	    mfi_timeout, sc);
     
     	if (0)
    
    From ecf507c36b2785372c4b32085c0b7c87b0e6c8b8 Mon Sep 17 00:00:00 2001
    From: Attilio Rao 
    Date: Thu, 28 Feb 2013 00:18:56 +0000
    Subject: [PATCH 0465/1476] Complete r247297: Remove unused inclusions of
     vm/vm_pager.h and vm/vnode_pager.h.
    
    Sponsored by:	EMC / Isilon storage division
    ---
     sys/arm/econa/econa_machdep.c           | 2 --
     sys/arm/s3c2xx0/s3c24x0_machdep.c       | 2 --
     sys/arm/xscale/i80321/ep80219_machdep.c | 2 --
     sys/arm/xscale/i80321/iq31244_machdep.c | 2 --
     sys/arm/xscale/i8134x/crb_machdep.c     | 2 --
     sys/arm/xscale/ixp425/avila_machdep.c   | 2 --
     sys/arm/xscale/pxa/pxa_machdep.c        | 2 --
     7 files changed, 14 deletions(-)
    
    diff --git a/sys/arm/econa/econa_machdep.c b/sys/arm/econa/econa_machdep.c
    index 177d45b7789..d622860b964 100644
    --- a/sys/arm/econa/econa_machdep.c
    +++ b/sys/arm/econa/econa_machdep.c
    @@ -67,9 +67,7 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     #include 
    -#include 
     #include 
     #include 
     #include 
    diff --git a/sys/arm/s3c2xx0/s3c24x0_machdep.c b/sys/arm/s3c2xx0/s3c24x0_machdep.c
    index f19e3f295f7..e497bc4e2ed 100644
    --- a/sys/arm/s3c2xx0/s3c24x0_machdep.c
    +++ b/sys/arm/s3c2xx0/s3c24x0_machdep.c
    @@ -77,9 +77,7 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     #include 
    -#include 
     #include 
     #include 
     #include 
    diff --git a/sys/arm/xscale/i80321/ep80219_machdep.c b/sys/arm/xscale/i80321/ep80219_machdep.c
    index d3c65b2ac88..cb3d161d16c 100644
    --- a/sys/arm/xscale/i80321/ep80219_machdep.c
    +++ b/sys/arm/xscale/i80321/ep80219_machdep.c
    @@ -77,9 +77,7 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     #include 
    -#include 
     #include 
     #include 
     #include 
    diff --git a/sys/arm/xscale/i80321/iq31244_machdep.c b/sys/arm/xscale/i80321/iq31244_machdep.c
    index e7f34f5bebd..2375b6bc48d 100644
    --- a/sys/arm/xscale/i80321/iq31244_machdep.c
    +++ b/sys/arm/xscale/i80321/iq31244_machdep.c
    @@ -77,9 +77,7 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     #include 
    -#include 
     #include 
     #include 
     #include 
    diff --git a/sys/arm/xscale/i8134x/crb_machdep.c b/sys/arm/xscale/i8134x/crb_machdep.c
    index 7c62c725717..a1344afb3b0 100644
    --- a/sys/arm/xscale/i8134x/crb_machdep.c
    +++ b/sys/arm/xscale/i8134x/crb_machdep.c
    @@ -77,9 +77,7 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     #include 
    -#include 
     #include 
     #include 
     #include 
    diff --git a/sys/arm/xscale/ixp425/avila_machdep.c b/sys/arm/xscale/ixp425/avila_machdep.c
    index 82b0e0219cc..07026da89e7 100644
    --- a/sys/arm/xscale/ixp425/avila_machdep.c
    +++ b/sys/arm/xscale/ixp425/avila_machdep.c
    @@ -77,9 +77,7 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     #include 
    -#include 
     #include 
     #include 
     #include 
    diff --git a/sys/arm/xscale/pxa/pxa_machdep.c b/sys/arm/xscale/pxa/pxa_machdep.c
    index 440812f909a..706fb588797 100644
    --- a/sys/arm/xscale/pxa/pxa_machdep.c
    +++ b/sys/arm/xscale/pxa/pxa_machdep.c
    @@ -79,9 +79,7 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     #include 
    -#include 
     #include 
     #include 
     #include 
    
    From 5bf80db6764dbf466db64663504124c660cd6d0a Mon Sep 17 00:00:00 2001
    From: Neel Natu 
    Date: Thu, 28 Feb 2013 01:00:32 +0000
    Subject: [PATCH 0466/1476] Remove the quirk to allow use of MSI when the guest
     is running inside bhyve.
    
    This became redundant after the hostbridge presented to the guest started
    advertising the PCI-E capability (r246846).
    
    Obtained from:	NetApp
    ---
     sys/dev/pci/pci.c | 1 -
     1 file changed, 1 deletion(-)
    
    diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
    index 7632e7364c8..649a494bf4d 100644
    --- a/sys/dev/pci/pci.c
    +++ b/sys/dev/pci/pci.c
    @@ -244,7 +244,6 @@ static const struct pci_quirk pci_quirks[] = {
     	 * but support MSI just fine.  QEMU uses the Intel 82440.
     	 */
     	{ 0x12378086, PCI_QUIRK_ENABLE_MSI_VM,	0,	0 },
    -	{ 0x12751275, PCI_QUIRK_ENABLE_MSI_VM,	0, 	0 },	/* bhyve */
     
     	/*
     	 * HPET MMIO base address may appear in Bar1 for AMD SB600 SMBus
    
    From eff269ee18dc7dc7b465730e5d76830fe93b4256 Mon Sep 17 00:00:00 2001
    From: Glen Barber 
    Date: Thu, 28 Feb 2013 01:22:14 +0000
    Subject: [PATCH 0467/1476] Properly handle '-h' argument.
    
    PR:		176332
    Reviewed by:	scottl
    MFC after:	3 days
    ---
     usr.bin/dc/dc.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/usr.bin/dc/dc.c b/usr.bin/dc/dc.c
    index d5edadb7989..546b24706ee 100644
    --- a/usr.bin/dc/dc.c
    +++ b/usr.bin/dc/dc.c
    @@ -84,7 +84,7 @@ main(int argc, char *argv[])
     	bool extended_regs = false, preproc_done = false;
     
     	/* accept and ignore a single dash to be 4.4BSD dc(1) compatible */
    -	while ((ch = getopt_long(argc, argv, "e:f:Vx", long_options, NULL)) != -1) {
    +	while ((ch = getopt_long(argc, argv, "e:f:hVx", long_options, NULL)) != -1) {
     		switch (ch) {
     		case 'e':
     			if (!preproc_done)
    
    From a66ffea41d7ea4e39a49bc146e6f6decb4fbd02c Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Thu, 28 Feb 2013 01:24:24 +0000
    Subject: [PATCH 0468/1476] When we are waiting for new trail files we may have
     been disconnected and reconnected in the meantime. Check if reset is set
     before opening next trail file, as not doing so will result in sending OPEN
     message with the same file name twice and this is illegal - the second OPEN
     is send without first closing previous trail file.
    
    ---
     contrib/openbsm/bin/auditdistd/sender.c | 9 +++++++++
     1 file changed, 9 insertions(+)
    
    diff --git a/contrib/openbsm/bin/auditdistd/sender.c b/contrib/openbsm/bin/auditdistd/sender.c
    index 256fbb1f475..ab90e6ce03d 100644
    --- a/contrib/openbsm/bin/auditdistd/sender.c
    +++ b/contrib/openbsm/bin/auditdistd/sender.c
    @@ -394,6 +394,7 @@ read_thread_wait(void)
     
     	mtx_lock(&adist_remote_mtx);
     	if (adhost->adh_reset) {
    +reset:
     		adhost->adh_reset = false;
     		if (trail_filefd(adist_trail) != -1)
     			trail_close(adist_trail);
    @@ -408,6 +409,14 @@ read_thread_wait(void)
     	while (trail_filefd(adist_trail) == -1) {
     		newfile = true;
     		wait_for_dir();
    +		/*
    +		 * We may have been disconnected and reconnected in the
    +		 * meantime, check if reset is set.
    +		 */
    +		mtx_lock(&adist_remote_mtx);
    +		if (adhost->adh_reset)
    +			goto reset;
    +		mtx_unlock(&adist_remote_mtx);
     		if (trail_filefd(adist_trail) == -1)
     			trail_next(adist_trail);
     	}
    
    From 35689395b3d5478b3fab05080c71b13a7d57ca54 Mon Sep 17 00:00:00 2001
    From: Xin LI 
    Date: Thu, 28 Feb 2013 04:16:47 +0000
    Subject: [PATCH 0469/1476] Refresh vendor driver version which adds ARC-1224
     support.
    MIME-Version: 1.0
    Content-Type: text/plain; charset=UTF-8
    Content-Transfer-Encoding: 8bit
    
    Many thanks to Areca for continuing to support FreeBSD.
    
    Submitted by:	黃清隆 
    MFC after:	3 days
    ---
     share/man/man4/arcmsr.4 |   4 +-
     sys/dev/arcmsr/arcmsr.c | 135 +++++++++++++++++++++++++++++++++++-----
     sys/dev/arcmsr/arcmsr.h |  17 +++--
     3 files changed, 129 insertions(+), 27 deletions(-)
    
    diff --git a/share/man/man4/arcmsr.4 b/share/man/man4/arcmsr.4
    index 71b5faa0c6e..87c70509fec 100644
    --- a/share/man/man4/arcmsr.4
    +++ b/share/man/man4/arcmsr.4
    @@ -24,7 +24,7 @@
     .\"
     .\" $FreeBSD$
     .\"
    -.Dd December 18, 2012
    +.Dd February 27, 2013
     .Dt ARCMSR 4
     .Os
     .Sh NAME
    @@ -108,6 +108,8 @@ ARC-1222
     .It
     ARC-1223
     .It
    +ARC-1224
    +.It
     ARC-1230
     .It
     ARC-1231
    diff --git a/sys/dev/arcmsr/arcmsr.c b/sys/dev/arcmsr/arcmsr.c
    index c815d02202c..d80fcf2d64d 100644
    --- a/sys/dev/arcmsr/arcmsr.c
    +++ b/sys/dev/arcmsr/arcmsr.c
    @@ -1,16 +1,15 @@
     /*
    -*****************************************************************************************
    -**        O.S   : FreeBSD
    +********************************************************************************
    +**        OS    : FreeBSD
     **   FILE NAME  : arcmsr.c
     **        BY    : Erich Chen, Ching Huang
     **   Description: SCSI RAID Device Driver for 
    -**                ARECA (ARC11XX/ARC12XX/ARC13XX/ARC16XX/ARC188x) SATA/SAS RAID HOST Adapter
    -**                ARCMSR RAID Host adapter
    -**                [RAID controller:INTEL 331(PCI-X) 341(PCI-EXPRESS) chip set]
    -******************************************************************************************
    -************************************************************************
    +**                ARECA (ARC11XX/ARC12XX/ARC13XX/ARC16XX/ARC188x)
    +**                SATA/SAS RAID HOST Adapter
    +********************************************************************************
    +********************************************************************************
     **
    -** Copyright (C) 2002 - 2010, Areca Technology Corporation All rights reserved.
    +** Copyright (C) 2002 - 2012, Areca Technology Corporation All rights reserved.
     **
     ** Redistribution and use in source and binary forms, with or without
     ** modification, are permitted provided that the following conditions
    @@ -33,7 +32,7 @@
     ** 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.
    -**************************************************************************
    +********************************************************************************
     ** History
     **
     **        REV#         DATE             NAME             DESCRIPTION
    @@ -73,7 +72,7 @@
     **     1.20.00.23   01/30/2012      Ching Huang          Fixed Request requeued and Retrying command
     **     1.20.00.24   06/11/2012      Ching Huang          Fixed return sense data condition
     **     1.20.00.25   08/17/2012      Ching Huang          Fixed hotplug device no function on type A adapter
    -**     1.20.00.26   12/14/2012      Ching Huang          Added support ARC1214
    +**     1.20.00.26   12/14/2012      Ching Huang          Added support ARC1214,1224
     ******************************************************************************************
     */
     
    @@ -145,7 +144,7 @@ __FBSDID("$FreeBSD$");
     #define arcmsr_callout_init(a)	callout_init(a);
     #endif
     
    -#define ARCMSR_DRIVER_VERSION	"Driver Version 1.20.00.26 2012-12-14"
    +#define ARCMSR_DRIVER_VERSION	"Driver Version 1.20.00.26 2013-01-08"
     #include 
     /*
     **************************************************************************
    @@ -168,7 +167,7 @@ static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb);
     static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb);
     static void arcmsr_iop_init(struct AdapterControlBlock *acb);
     static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb);
    -static void	arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb, struct QBUFFER *prbuffer);
    +static u_int32_t arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb, struct QBUFFER *prbuffer);
     static void arcmsr_Write_data_2iop_wqbuffer(struct AdapterControlBlock *acb);
     static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb);
     static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag);
    @@ -212,7 +211,11 @@ static device_method_t arcmsr_methods[]={
     	DEVMETHOD(device_suspend,	arcmsr_suspend),
     	DEVMETHOD(device_resume,	arcmsr_resume),
     
    +#if __FreeBSD_version >= 803000
     	DEVMETHOD_END
    +#else
    +	{ 0, 0 }
    +#endif
     };
     	
     static driver_t arcmsr_driver={
    @@ -1381,13 +1384,61 @@ static void arcmsr_poll(struct cam_sim *psim)
     **************************************************************************
     **************************************************************************
     */
    -static void	arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb,
    +static u_int32_t arcmsr_Read_iop_rqbuffer_data_D(struct AdapterControlBlock *acb,
    +    struct QBUFFER *prbuffer) {
    +
    +	u_int8_t *pQbuffer;
    +	u_int8_t *buf1 = 0;
    +	u_int32_t *iop_data, *buf2 = 0;
    +	u_int32_t iop_len, data_len;
    +
    +	iop_data = (u_int32_t *)prbuffer->data;
    +	iop_len = (u_int32_t)prbuffer->data_len;
    +	if ( iop_len > 0 )
    +	{
    +		buf1 = malloc(128, M_DEVBUF, M_NOWAIT | M_ZERO);
    +		buf2 = (u_int32_t *)buf1;
    +		if( buf1 == NULL)
    +			return (0);
    +		data_len = iop_len;
    +		while(data_len >= 4)
    +		{
    +			*buf2++ = *iop_data++;
    +			data_len -= 4;
    +		}
    +		if(data_len)
    +			*buf2 = *iop_data;
    +		buf2 = (u_int32_t *)buf1;
    +	}
    +	while (iop_len > 0) {
    +		pQbuffer = &acb->rqbuffer[acb->rqbuf_lastindex];
    +		*pQbuffer = *buf1;
    +		acb->rqbuf_lastindex++;
    +		/* if last, index number set it to 0 */
    +		acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
    +		buf1++;
    +		iop_len--;
    +	}
    +	if(buf2)
    +		free( (u_int8_t *)buf2, M_DEVBUF);
    +	/* let IOP know data has been read */
    +	arcmsr_iop_message_read(acb);
    +	return (1);
    +}
    +/*
    +**************************************************************************
    +**************************************************************************
    +*/
    +static u_int32_t arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb,
         struct QBUFFER *prbuffer) {
     
     	u_int8_t *pQbuffer;
     	u_int8_t *iop_data;
     	u_int32_t iop_len;
     
    +	if(acb->adapter_type == ACB_ADAPTER_TYPE_D) {
    +		return(arcmsr_Read_iop_rqbuffer_data_D(acb, prbuffer));
    +	}
     	iop_data = (u_int8_t *)prbuffer->data;
     	iop_len = (u_int32_t)prbuffer->data_len;
     	while (iop_len > 0) {
    @@ -1401,6 +1452,7 @@ static void	arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb,
     	}
     	/* let IOP know data has been read */
     	arcmsr_iop_message_read(acb);
    +	return (1);
     }
     /*
     **************************************************************************
    @@ -1417,7 +1469,8 @@ static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb)
     	my_empty_len = (acb->rqbuf_lastindex - acb->rqbuf_firstindex - 1) &
     	    (ARCMSR_MAX_QBUFFER-1);
     	if(my_empty_len >= prbuffer->data_len) {
    -		arcmsr_Read_iop_rqbuffer_data(acb, prbuffer);
    +		if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0)
    +			acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
     	} else {
     		acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
     	}
    @@ -1427,6 +1480,50 @@ static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb)
     **********************************************************************
     **********************************************************************
     */
    +static void arcmsr_Write_data_2iop_wqbuffer_D(struct AdapterControlBlock *acb)
    +{
    +	u_int8_t *pQbuffer;
    +	struct QBUFFER *pwbuffer;
    +	u_int8_t *buf1 = 0;
    +	u_int32_t *iop_data, *buf2 = 0;
    +	u_int32_t allxfer_len = 0, data_len;
    +	
    +	if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READ) {
    +		buf1 = malloc(128, M_DEVBUF, M_NOWAIT | M_ZERO);
    +		buf2 = (u_int32_t *)buf1;
    +		if( buf1 == NULL)
    +			return;
    +
    +		acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ);
    +		pwbuffer = arcmsr_get_iop_wqbuffer(acb);
    +		iop_data = (u_int32_t *)pwbuffer->data;
    +		while((acb->wqbuf_firstindex != acb->wqbuf_lastindex) 
    +			&& (allxfer_len < 124)) {
    +			pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex];
    +			*buf1 = *pQbuffer;
    +			acb->wqbuf_firstindex++;
    +			acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
    +			buf1++;
    +			allxfer_len++;
    +		}
    +		pwbuffer->data_len = allxfer_len;
    +		data_len = allxfer_len;
    +		buf1 = (u_int8_t *)buf2;
    +		while(data_len >= 4)
    +		{
    +			*iop_data++ = *buf2++;
    +			data_len -= 4;
    +		}
    +		if(data_len)
    +			*iop_data = *buf2;
    +		free( buf1, M_DEVBUF);
    +		arcmsr_iop_message_wrote(acb);
    +	}
    +}
    +/*
    +**********************************************************************
    +**********************************************************************
    +*/
     static void arcmsr_Write_data_2iop_wqbuffer(struct AdapterControlBlock *acb)
     {
     	u_int8_t *pQbuffer;
    @@ -1434,6 +1531,10 @@ static void arcmsr_Write_data_2iop_wqbuffer(struct AdapterControlBlock *acb)
     	u_int8_t *iop_data;
     	int32_t allxfer_len=0;
     	
    +	if(acb->adapter_type == ACB_ADAPTER_TYPE_D) {
    +		arcmsr_Write_data_2iop_wqbuffer_D(acb);
    +		return;
    +	}
     	if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READ) {
     		acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ);
     		pwbuffer = arcmsr_get_iop_wqbuffer(acb);
    @@ -2153,7 +2254,8 @@ u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_c
     	
     				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
     				prbuffer = arcmsr_get_iop_rqbuffer(acb);
    -				arcmsr_Read_iop_rqbuffer_data(acb, prbuffer);
    +				if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0)
    +					acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
     			}
     			pcmdmessagefld->cmdmessage.Length = allxfer_len;
     			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
    @@ -2374,7 +2476,8 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb *p
     	
     				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
     				prbuffer = arcmsr_get_iop_rqbuffer(acb);
    -				arcmsr_Read_iop_rqbuffer_data(acb, prbuffer);
    +				if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0)
    +					acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
     			}
     			pcmdmessagefld->cmdmessage.Length = allxfer_len;
     			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
    diff --git a/sys/dev/arcmsr/arcmsr.h b/sys/dev/arcmsr/arcmsr.h
    index 219372e549d..95bb6a1583d 100644
    --- a/sys/dev/arcmsr/arcmsr.h
    +++ b/sys/dev/arcmsr/arcmsr.h
    @@ -1,17 +1,14 @@
     /*
    -***********************************************************************************************
    -**        O.S   : FreeBSD
    +********************************************************************************
    +**        OS    : FreeBSD
     **   FILE NAME  : arcmsr.h
     **        BY    : Erich Chen, Ching Huang
     **   Description: SCSI RAID Device Driver for 
    -**                ARECA SATA/SAS RAID HOST Adapter
    -**                [RAID controller:INTEL 331(PCI-X) 341(PCI-EXPRESS) chip set]
    -***********************************************************************************************
    -************************************************************************
    -** Copyright (C) 2002 - 2010, Areca Technology Corporation All rights reserved.
    -**
    -**     Web site: www.areca.com.tw
    -**       E-mail: erich@areca.com.tw; ching2048@areca.com.tw
    +**                ARECA (ARC11XX/ARC12XX/ARC13XX/ARC16XX/ARC188x)
    +**                SATA/SAS RAID HOST Adapter
    +********************************************************************************
    +********************************************************************************
    +** Copyright (C) 2002 - 2012, Areca Technology Corporation All rights reserved.
     **
     ** Redistribution and use in source and binary forms,with or without
     ** modification,are permitted provided that the following conditions
    
    From 0f4fc79e2fcc50b027e0fe63887f860cb913a670 Mon Sep 17 00:00:00 2001
    From: Alexander Motin 
    Date: Thu, 28 Feb 2013 10:21:04 +0000
    Subject: [PATCH 0470/1476] Introduce sbintime_t type -- the simplified version
     of struct bintime, using 32.32 fixed point in form of single int64_t.  It is
     much easier to use in cases where additional precision and range of struct
     bintime is not required.
    
    Reviewed by:	bde (previous version), davide
    ---
     sys/sys/time.h | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++
     1 file changed, 85 insertions(+)
    
    diff --git a/sys/sys/time.h b/sys/sys/time.h
    index 80878c0e9f8..927ceccf7c4 100644
    --- a/sys/sys/time.h
    +++ b/sys/sys/time.h
    @@ -109,6 +109,37 @@ bintime_mul(struct bintime *bt, u_int x)
     	    ((a)->frac cmp (b)->frac) :					\
     	    ((a)->sec cmp (b)->sec))
     
    +typedef int64_t sbintime_t;
    +#define	SBT_1S	((sbintime_t)1 << 32)
    +#define	SBT_1M	(SBT_1S * 60)
    +#define	SBT_1MS	(SBT_1S / 1000)
    +#define	SBT_1US	(SBT_1S / 1000000)
    +#define	SBT_1NS (SBT_1S / 1000000000)  
    +
    +static __inline int
    +sbintime_getsec(sbintime_t sbt)
    +{
    +
    +	return (sbt >> 32);
    +}
    +
    +static __inline sbintime_t
    +bttosbt(const struct bintime bt)
    +{
    +
    +	return (((sbintime_t)bt.sec << 32) + (bt.frac >> 32));
    +}
    +
    +static __inline struct bintime
    +sbttobt(sbintime_t sbt)
    +{
    +	struct bintime bt;
    +	
    +	bt.sec = sbt >> 32;
    +	bt.frac = sbt << 32;
    +	return (bt);
    +}
    +
     /*-
      * Background information:
      *
    @@ -156,6 +187,42 @@ timeval2bintime(const struct timeval *tv, struct bintime *bt)
     	/* 18446744073709 = int(2^64 / 1000000) */
     	bt->frac = tv->tv_usec * (uint64_t)18446744073709LL;
     }
    +
    +static __inline struct timespec
    +sbttots(sbintime_t sbt)
    +{
    +	struct timespec ts;
    +
    +	ts.tv_sec = sbt >> 32;
    +	ts.tv_nsec = ((uint64_t)1000000000 * (uint32_t)sbt) >> 32;
    +	return (ts);
    +}
    +
    +static __inline sbintime_t
    +tstosbt(struct timespec ts)
    +{
    +
    +	return (((sbintime_t)ts.tv_sec << 32) +
    +	    (ts.tv_nsec * (((uint64_t)1 << 63) / 500000000) >> 32));
    +}
    +
    +static __inline struct timeval
    +sbttotv(sbintime_t sbt)
    +{
    +	struct timeval tv;
    +
    +	tv.tv_sec = sbt >> 32;
    +	tv.tv_usec = ((uint64_t)1000000 * (uint32_t)sbt) >> 32;
    +	return (tv);
    +}
    +
    +static __inline sbintime_t
    +tvtosbt(struct timeval tv)
    +{
    +
    +	return (((sbintime_t)tv.tv_sec << 32) +
    +	    (tv.tv_usec * (((uint64_t)1 << 63) / 500000) >> 32));
    +}
     #endif /* __BSD_VISIBLE */
     
     #ifdef _KERNEL
    @@ -317,6 +384,15 @@ void	binuptime(struct bintime *bt);
     void	nanouptime(struct timespec *tsp);
     void	microuptime(struct timeval *tvp);
     
    +static __inline sbintime_t
    +sbinuptime(void)
    +{
    +	struct bintime bt;
    +
    +	binuptime(&bt);
    +	return (bttosbt(bt));
    +}
    +
     void	bintime(struct bintime *bt);
     void	nanotime(struct timespec *tsp);
     void	microtime(struct timeval *tvp);
    @@ -325,6 +401,15 @@ void	getbinuptime(struct bintime *bt);
     void	getnanouptime(struct timespec *tsp);
     void	getmicrouptime(struct timeval *tvp);
     
    +static __inline sbintime_t
    +getsbinuptime(void)
    +{
    +	struct bintime bt;
    +
    +	getbinuptime(&bt);
    +	return (bttosbt(bt));
    +}
    +
     void	getbintime(struct bintime *bt);
     void	getnanotime(struct timespec *tsp);
     void	getmicrotime(struct timeval *tvp);
    
    From acccf7d8b4896ba5a0f622d846bed66125f5c40a Mon Sep 17 00:00:00 2001
    From: Davide Italiano 
    Date: Thu, 28 Feb 2013 10:46:54 +0000
    Subject: [PATCH 0471/1476] MFcalloutng: When CPU becomes idle, cpu_idleclock()
     calculates time to the next timer event in order to reprogram hw timer.
     Return that time in sbintime_t to the caller and pass it to acpi_cpu_idle(),
     where it can be used as one more factor (quite precise) to extimate furter
     sleep time and choose optimal sleep state. This is a preparatory change for
     further callout improvements will be committed in the next days.
    
    The commmit is not targeted for MFC.
    ---
     sys/amd64/amd64/machdep.c      | 19 ++++++++++---------
     sys/dev/acpica/acpi_cpu.c      | 11 +++++++----
     sys/i386/i386/machdep.c        | 23 ++++++++++++-----------
     sys/ia64/ia64/machdep.c        |  7 ++++---
     sys/kern/kern_clocksource.c    |  6 ++++--
     sys/pc98/pc98/machdep.c        | 13 +++++++------
     sys/powerpc/powerpc/cpu.c      | 15 ++++++++-------
     sys/powerpc/ps3/platform_ps3.c |  4 ++--
     sys/powerpc/wii/platform_wii.c |  4 ++--
     sys/sys/proc.h                 |  2 +-
     sys/sys/systm.h                |  3 ++-
     11 files changed, 59 insertions(+), 48 deletions(-)
    
    diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
    index abce8267535..1d7178f9c7d 100644
    --- a/sys/amd64/amd64/machdep.c
    +++ b/sys/amd64/amd64/machdep.c
    @@ -658,7 +658,7 @@ cpu_halt(void)
     		halt();
     }
     
    -void (*cpu_idle_hook)(void) = NULL;	/* ACPI idle hook. */
    +void (*cpu_idle_hook)(sbintime_t) = NULL;	/* ACPI idle hook. */
     static int	cpu_ident_amdc1e = 0;	/* AMD C1E supported. */
     static int	idle_mwait = 1;		/* Use MONITOR/MWAIT for short idle. */
     TUNABLE_INT("machdep.idle_mwait", &idle_mwait);
    @@ -670,7 +670,7 @@ SYSCTL_INT(_machdep, OID_AUTO, idle_mwait, CTLFLAG_RW, &idle_mwait,
     #define	STATE_SLEEPING	0x2
     
     static void
    -cpu_idle_acpi(int busy)
    +cpu_idle_acpi(sbintime_t sbt)
     {
     	int *state;
     
    @@ -682,14 +682,14 @@ cpu_idle_acpi(int busy)
     	if (sched_runnable())
     		enable_intr();
     	else if (cpu_idle_hook)
    -		cpu_idle_hook();
    +		cpu_idle_hook(sbt);
     	else
     		__asm __volatile("sti; hlt");
     	*state = STATE_RUNNING;
     }
     
     static void
    -cpu_idle_hlt(int busy)
    +cpu_idle_hlt(sbintime_t sbt)
     {
     	int *state;
     
    @@ -730,7 +730,7 @@ cpu_idle_hlt(int busy)
     #define	MWAIT_C4	0x30
     
     static void
    -cpu_idle_mwait(int busy)
    +cpu_idle_mwait(sbintime_t sbt)
     {
     	int *state;
     
    @@ -753,7 +753,7 @@ cpu_idle_mwait(int busy)
     }
     
     static void
    -cpu_idle_spin(int busy)
    +cpu_idle_spin(sbintime_t sbt)
     {
     	int *state;
     	int i;
    @@ -802,12 +802,13 @@ cpu_probe_amdc1e(void)
     	}
     }
     
    -void (*cpu_idle_fn)(int) = cpu_idle_acpi;
    +void (*cpu_idle_fn)(sbintime_t) = cpu_idle_acpi;
     
     void
     cpu_idle(int busy)
     {
     	uint64_t msr;
    +	sbintime_t sbt = -1;
     
     	CTR2(KTR_SPARE2, "cpu_idle(%d) at %d",
     	    busy, curcpu);
    @@ -825,7 +826,7 @@ cpu_idle(int busy)
     	/* If we have time - switch timers into idle mode. */
     	if (!busy) {
     		critical_enter();
    -		cpu_idleclock();
    +		sbt = cpu_idleclock();
     	}
     
     	/* Apply AMD APIC timer C1E workaround. */
    @@ -836,7 +837,7 @@ cpu_idle(int busy)
     	}
     
     	/* Call main idle method. */
    -	cpu_idle_fn(busy);
    +	cpu_idle_fn(sbt);
     
     	/* Switch timers mack into active mode. */
     	if (!busy) {
    diff --git a/sys/dev/acpica/acpi_cpu.c b/sys/dev/acpica/acpi_cpu.c
    index 7f008f72df6..df4c4c2e292 100644
    --- a/sys/dev/acpica/acpi_cpu.c
    +++ b/sys/dev/acpica/acpi_cpu.c
    @@ -168,7 +168,7 @@ static int	acpi_cpu_cx_cst(struct acpi_cpu_softc *sc);
     static void	acpi_cpu_startup(void *arg);
     static void	acpi_cpu_startup_cx(struct acpi_cpu_softc *sc);
     static void	acpi_cpu_cx_list(struct acpi_cpu_softc *sc);
    -static void	acpi_cpu_idle(void);
    +static void	acpi_cpu_idle(sbintime_t sbt);
     static void	acpi_cpu_notify(ACPI_HANDLE h, UINT32 notify, void *context);
     static int	acpi_cpu_quirks(void);
     static int	acpi_cpu_usage_sysctl(SYSCTL_HANDLER_ARGS);
    @@ -954,13 +954,13 @@ acpi_cpu_startup_cx(struct acpi_cpu_softc *sc)
      * interrupts are re-enabled.
      */
     static void
    -acpi_cpu_idle()
    +acpi_cpu_idle(sbintime_t sbt)
     {
         struct	acpi_cpu_softc *sc;
         struct	acpi_cx *cx_next;
         uint64_t	cputicks;
         uint32_t	start_time, end_time;
    -    int		bm_active, cx_next_idx, i;
    +    int		bm_active, cx_next_idx, i, us;
     
         /*
          * Look up our CPU id to get our softc.  If it's NULL, we'll use C1
    @@ -980,13 +980,16 @@ acpi_cpu_idle()
         }
     
         /* Find the lowest state that has small enough latency. */
    +    us = sc->cpu_prev_sleep;
    +    if (sbt >= 0 && us > sbt / SBT_1US)
    +	us = sbt / SBT_1US;
         cx_next_idx = 0;
         if (cpu_disable_deep_sleep)
     	i = min(sc->cpu_cx_lowest, sc->cpu_non_c3);
         else
     	i = sc->cpu_cx_lowest;
         for (; i >= 0; i--) {
    -	if (sc->cpu_cx_states[i].trans_lat * 3 <= sc->cpu_prev_sleep) {
    +	if (sc->cpu_cx_states[i].trans_lat * 3 <= us) {
     	    cx_next_idx = i;
     	    break;
     	}
    diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c
    index 744c3cbbed0..3f15f082834 100644
    --- a/sys/i386/i386/machdep.c
    +++ b/sys/i386/i386/machdep.c
    @@ -1220,7 +1220,7 @@ cpu_halt(void)
     int scheduler_running;
     
     static void
    -cpu_idle_hlt(int busy)
    +cpu_idle_hlt(sbintime_t sbt)
     {
     
     	scheduler_running = 1;
    @@ -1241,7 +1241,7 @@ cpu_halt(void)
     
     #endif
     
    -void (*cpu_idle_hook)(void) = NULL;	/* ACPI idle hook. */
    +void (*cpu_idle_hook)(sbintime_t) = NULL;	/* ACPI idle hook. */
     static int	cpu_ident_amdc1e = 0;	/* AMD C1E supported. */
     static int	idle_mwait = 1;		/* Use MONITOR/MWAIT for short idle. */
     TUNABLE_INT("machdep.idle_mwait", &idle_mwait);
    @@ -1253,7 +1253,7 @@ SYSCTL_INT(_machdep, OID_AUTO, idle_mwait, CTLFLAG_RW, &idle_mwait,
     #define	STATE_SLEEPING	0x2
     
     static void
    -cpu_idle_acpi(int busy)
    +cpu_idle_acpi(sbintime_t sbt)
     {
     	int *state;
     
    @@ -1265,7 +1265,7 @@ cpu_idle_acpi(int busy)
     	if (sched_runnable())
     		enable_intr();
     	else if (cpu_idle_hook)
    -		cpu_idle_hook();
    +		cpu_idle_hook(sbt);
     	else
     		__asm __volatile("sti; hlt");
     	*state = STATE_RUNNING;
    @@ -1273,7 +1273,7 @@ cpu_idle_acpi(int busy)
     
     #ifndef XEN
     static void
    -cpu_idle_hlt(int busy)
    +cpu_idle_hlt(sbintime_t sbt)
     {
     	int *state;
     
    @@ -1315,7 +1315,7 @@ cpu_idle_hlt(int busy)
     #define	MWAIT_C4	0x30
     
     static void
    -cpu_idle_mwait(int busy)
    +cpu_idle_mwait(sbintime_t sbt)
     {
     	int *state;
     
    @@ -1338,7 +1338,7 @@ cpu_idle_mwait(int busy)
     }
     
     static void
    -cpu_idle_spin(int busy)
    +cpu_idle_spin(sbintime_t sbt)
     {
     	int *state;
     	int i;
    @@ -1388,9 +1388,9 @@ cpu_probe_amdc1e(void)
     }
     
     #ifdef XEN
    -void (*cpu_idle_fn)(int) = cpu_idle_hlt;
    +void (*cpu_idle_fn)(sbintime_t) = cpu_idle_hlt;
     #else
    -void (*cpu_idle_fn)(int) = cpu_idle_acpi;
    +void (*cpu_idle_fn)(sbintime_t) = cpu_idle_acpi;
     #endif
     
     void
    @@ -1399,6 +1399,7 @@ cpu_idle(int busy)
     #ifndef XEN
     	uint64_t msr;
     #endif
    +	sbintime_t sbt = -1;
     
     	CTR2(KTR_SPARE2, "cpu_idle(%d) at %d",
     	    busy, curcpu);
    @@ -1418,7 +1419,7 @@ cpu_idle(int busy)
     	/* If we have time - switch timers into idle mode. */
     	if (!busy) {
     		critical_enter();
    -		cpu_idleclock();
    +		sbt = cpu_idleclock();
     	}
     
     #ifndef XEN
    @@ -1431,7 +1432,7 @@ cpu_idle(int busy)
     #endif
     
     	/* Call main idle method. */
    -	cpu_idle_fn(busy);
    +	cpu_idle_fn(sbt);
     
     	/* Switch timers mack into active mode. */
     	if (!busy) {
    diff --git a/sys/ia64/ia64/machdep.c b/sys/ia64/ia64/machdep.c
    index 98bcf446d7a..ac6a8291c92 100644
    --- a/sys/ia64/ia64/machdep.c
    +++ b/sys/ia64/ia64/machdep.c
    @@ -171,7 +171,7 @@ extern vm_offset_t ksym_start, ksym_end;
     struct msgbuf *msgbufp = NULL;
     
     /* Other subsystems (e.g., ACPI) can hook this later. */
    -void (*cpu_idle_hook)(void) = NULL;
    +void (*cpu_idle_hook)(sbintime_t) = NULL;
     
     struct kva_md_info kmi;
     
    @@ -408,10 +408,11 @@ void
     cpu_idle(int busy)
     {
     	register_t ie;
    +	sbintime_t sbt = -1;
     
     	if (!busy) {
     		critical_enter();
    -		cpu_idleclock();
    +		sbt = cpu_idleclock();
     	}
     
     	ie = intr_disable();
    @@ -420,7 +421,7 @@ cpu_idle(int busy)
     	if (sched_runnable())
     		ia64_enable_intr();
     	else if (cpu_idle_hook != NULL) {
    -		(*cpu_idle_hook)();
    +		(*cpu_idle_hook)(sbt);
     		/* The hook must enable interrupts! */
     	} else {
     		ia64_call_pal_static(PAL_HALT_LIGHT, 0, 0, 0);
    diff --git a/sys/kern/kern_clocksource.c b/sys/kern/kern_clocksource.c
    index 33f21e97be2..ac7e2de77a3 100644
    --- a/sys/kern/kern_clocksource.c
    +++ b/sys/kern/kern_clocksource.c
    @@ -767,7 +767,7 @@ cpu_stopprofclock(void)
     /*
      * Switch to idle mode (all ticks handled).
      */
    -void
    +sbintime_t
     cpu_idleclock(void)
     {
     	struct bintime now, t;
    @@ -779,7 +779,7 @@ cpu_idleclock(void)
     	    || curcpu == CPU_FIRST()
     #endif
     	    )
    -		return;
    +		return (-1);
     	state = DPCPU_PTR(timerstate);
     	if (periodic)
     		now = state->now;
    @@ -795,6 +795,8 @@ cpu_idleclock(void)
     	if (!periodic)
     		loadtimer(&now, 0);
     	ET_HW_UNLOCK(state);
    +	bintime_sub(&t, &now);
    +	return (MAX(bttosbt(t), 0));
     }
     
     /*
    diff --git a/sys/pc98/pc98/machdep.c b/sys/pc98/pc98/machdep.c
    index 3133d1b41ee..b0d5acd7e38 100644
    --- a/sys/pc98/pc98/machdep.c
    +++ b/sys/pc98/pc98/machdep.c
    @@ -1145,7 +1145,7 @@ SYSCTL_INT(_machdep, OID_AUTO, idle_mwait, CTLFLAG_RW, &idle_mwait,
     #define	STATE_SLEEPING	0x2
     
     static void
    -cpu_idle_hlt(int busy)
    +cpu_idle_hlt(sbintime_t sbt)
     {
     	int *state;
     
    @@ -1186,7 +1186,7 @@ cpu_idle_hlt(int busy)
     #define	MWAIT_C4	0x30
     
     static void
    -cpu_idle_mwait(int busy)
    +cpu_idle_mwait(sbintime_t sbt)
     {
     	int *state;
     
    @@ -1209,7 +1209,7 @@ cpu_idle_mwait(int busy)
     }
     
     static void
    -cpu_idle_spin(int busy)
    +cpu_idle_spin(sbintime_t sbt)
     {
     	int *state;
     	int i;
    @@ -1229,11 +1229,12 @@ cpu_idle_spin(int busy)
     	}
     }
     
    -void (*cpu_idle_fn)(int) = cpu_idle_hlt;
    +void (*cpu_idle_fn)(sbintime_t) = cpu_idle_hlt;
     
     void
     cpu_idle(int busy)
     {
    +	sbintime_t sbt = -1;
     
     	CTR2(KTR_SPARE2, "cpu_idle(%d) at %d",
     	    busy, curcpu);
    @@ -1251,11 +1252,11 @@ cpu_idle(int busy)
     	/* If we have time - switch timers into idle mode. */
     	if (!busy) {
     		critical_enter();
    -		cpu_idleclock();
    +		sbt = cpu_idleclock();
     	}
     
     	/* Call main idle method. */
    -	cpu_idle_fn(busy);
    +	cpu_idle_fn(sbt);
     
     	/* Switch timers mack into active mode. */
     	if (!busy) {
    diff --git a/sys/powerpc/powerpc/cpu.c b/sys/powerpc/powerpc/cpu.c
    index d177c8b7aed..d67f359e41c 100644
    --- a/sys/powerpc/powerpc/cpu.c
    +++ b/sys/powerpc/powerpc/cpu.c
    @@ -79,9 +79,9 @@ static void	cpu_970_setup(int cpuid, uint16_t vers);
     static void	cpu_booke_setup(int cpuid, uint16_t vers);
     
     int powerpc_pow_enabled;
    -void (*cpu_idle_hook)(void) = NULL;
    -static void	cpu_idle_60x(void);
    -static void	cpu_idle_booke(void);
    +void (*cpu_idle_hook)(sbintime_t) = NULL;
    +static void	cpu_idle_60x(sbintime_t);
    +static void	cpu_idle_booke(sbintime_t);
     
     struct cputab {
     	const char	*name;
    @@ -516,6 +516,7 @@ cpu_feature_bit(SYSCTL_HANDLER_ARGS)
     void
     cpu_idle(int busy)
     {
    +	sbintime_t sbt = -1;
     
     #ifdef INVARIANTS
     	if ((mfmsr() & PSL_EE) != PSL_EE) {
    @@ -531,9 +532,9 @@ cpu_idle(int busy)
     	if (cpu_idle_hook != NULL) {
     		if (!busy) {
     			critical_enter();
    -			cpu_idleclock();
    +			sbt = cpu_idleclock();
     		}
    -		cpu_idle_hook();
    +		cpu_idle_hook(sbt);
     		if (!busy) {
     			cpu_activeclock();
     			critical_exit();
    @@ -551,7 +552,7 @@ cpu_idle_wakeup(int cpu)
     }
     
     static void
    -cpu_idle_60x(void)
    +cpu_idle_60x(sbintime_t sbt)
     {
     	register_t msr;
     	uint16_t vers;
    @@ -586,7 +587,7 @@ cpu_idle_60x(void)
     }
     
     static void
    -cpu_idle_booke(void)
    +cpu_idle_booke(sbintime_t sbt)
     {
     	register_t msr;
     
    diff --git a/sys/powerpc/ps3/platform_ps3.c b/sys/powerpc/ps3/platform_ps3.c
    index 61ce8737a4a..207382d86fd 100644
    --- a/sys/powerpc/ps3/platform_ps3.c
    +++ b/sys/powerpc/ps3/platform_ps3.c
    @@ -70,7 +70,7 @@ static int ps3_smp_start_cpu(platform_t, struct pcpu *cpu);
     static struct cpu_group *ps3_smp_topo(platform_t);
     #endif
     static void ps3_reset(platform_t);
    -static void ps3_cpu_idle(void);
    +static void ps3_cpu_idle(sbintime_t);
     
     static platform_method_t ps3_methods[] = {
     	PLATFORMMETHOD(platform_probe, 		ps3_probe),
    @@ -245,7 +245,7 @@ ps3_real_maxaddr(platform_t plat)
     }
     
     static void
    -ps3_cpu_idle(void)
    +ps3_cpu_idle(sbintime_t sbt)
     {
     	lv1_pause(0);
     }
    diff --git a/sys/powerpc/wii/platform_wii.c b/sys/powerpc/wii/platform_wii.c
    index 2bb6022ce9a..bc35105c0db 100644
    --- a/sys/powerpc/wii/platform_wii.c
    +++ b/sys/powerpc/wii/platform_wii.c
    @@ -60,7 +60,7 @@ static void		wii_mem_regions(platform_t, struct mem_region **,
     			    int *, struct mem_region **, int *);
     static unsigned long	wii_timebase_freq(platform_t, struct cpuref *cpuref);
     static void		wii_reset(platform_t);
    -static void		wii_cpu_idle(void);
    +static void		wii_cpu_idle(sbintime_t sbt);
     
     static platform_method_t wii_methods[] = {
     	PLATFORMMETHOD(platform_probe,		wii_probe),
    @@ -155,6 +155,6 @@ wii_reset(platform_t plat)
     }
     
     static void
    -wii_cpu_idle(void)
    +wii_cpu_idle(sbintime_t sbt)
     {
     }
    diff --git a/sys/sys/proc.h b/sys/sys/proc.h
    index ade28642cf0..46f5820e745 100644
    --- a/sys/sys/proc.h
    +++ b/sys/sys/proc.h
    @@ -908,7 +908,7 @@ void	tidhash_add(struct thread *);
     void	tidhash_remove(struct thread *);
     void	cpu_idle(int);
     int	cpu_idle_wakeup(int);
    -extern	void (*cpu_idle_hook)(void);	/* Hook to machdep CPU idler. */
    +extern	void (*cpu_idle_hook)(sbintime_t);	/* Hook to machdep CPU idler. */
     void	cpu_switch(struct thread *, struct thread *, struct mtx *);
     void	cpu_throw(struct thread *, struct thread *) __dead2;
     void	unsleep(struct thread *);
    diff --git a/sys/sys/systm.h b/sys/sys/systm.h
    index 611d014831c..2bf805605b3 100644
    --- a/sys/sys/systm.h
    +++ b/sys/sys/systm.h
    @@ -44,6 +44,7 @@
     #include 
     #include 
     #include 		/* for people using printf mainly */
    +#include 
     
     extern int cold;		/* nonzero if we are doing a cold boot */
     extern int rebooting;		/* kern_reboot() has been called. */
    @@ -267,7 +268,7 @@ void	startprofclock(struct proc *);
     void	stopprofclock(struct proc *);
     void	cpu_startprofclock(void);
     void	cpu_stopprofclock(void);
    -void	cpu_idleclock(void);
    +sbintime_t 	cpu_idleclock(void);
     void	cpu_activeclock(void);
     extern int	cpu_can_deep_sleep;
     extern int	cpu_disable_deep_sleep;
    
    From d9ddf0c057f436df4eb9ac8b8a60640a84394f08 Mon Sep 17 00:00:00 2001
    From: Davide Italiano 
    Date: Thu, 28 Feb 2013 11:27:01 +0000
    Subject: [PATCH 0472/1476] MFcalloutng (r247427 by mav): We don't need any
     precision here. Let it be fast and dirty shift then slow and excessively
     precise 64-bit division.
    
    ---
     sys/dev/acpica/acpi_cpu.c | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/sys/dev/acpica/acpi_cpu.c b/sys/dev/acpica/acpi_cpu.c
    index df4c4c2e292..e58d980d565 100644
    --- a/sys/dev/acpica/acpi_cpu.c
    +++ b/sys/dev/acpica/acpi_cpu.c
    @@ -981,8 +981,8 @@ acpi_cpu_idle(sbintime_t sbt)
     
         /* Find the lowest state that has small enough latency. */
         us = sc->cpu_prev_sleep;
    -    if (sbt >= 0 && us > sbt / SBT_1US)
    -	us = sbt / SBT_1US;
    +    if (sbt >= 0 && us > (sbt >> 12))
    +	us = (sbt >> 12);
         cx_next_idx = 0;
         if (cpu_disable_deep_sleep)
     	i = min(sc->cpu_cx_lowest, sc->cpu_non_c3);
    
    From fdc5dd2d2fedb812958cf7c835a5dce2dcd874c5 Mon Sep 17 00:00:00 2001
    From: Alexander Motin 
    Date: Thu, 28 Feb 2013 13:46:03 +0000
    Subject: [PATCH 0473/1476] MFcalloutng: Switch eventtimers(9) from using
     struct bintime to sbintime_t. Even before this not a single driver really
     supported full dynamic range of struct bintime even in theory, not speaking
     about practical inexpediency. This change legitimates the status quo and
     cleans up the code.
    
    ---
     share/man/man9/eventtimers.9                | 12 ++---
     sys/arm/allwinner/timer.c                   | 35 ++++++--------
     sys/arm/arm/mpcore_timer.c                  | 30 ++++--------
     sys/arm/broadcom/bcm2835/bcm2835_systimer.c | 19 +++-----
     sys/arm/lpc/lpc_timer.c                     | 32 +++++--------
     sys/arm/mv/timer.c                          | 31 +++++--------
     sys/arm/ti/am335x/am335x_dmtimer.c          | 28 ++++-------
     sys/arm/versatile/sp804.c                   | 19 +++-----
     sys/dev/acpica/acpi_hpet.c                  | 26 ++++-------
     sys/i386/xen/clock.c                        | 26 ++++-------
     sys/ia64/ia64/clock.c                       | 22 +++------
     sys/kern/kern_clocksource.c                 | 16 ++++---
     sys/kern/kern_et.c                          | 51 ++++++++-------------
     sys/mips/mips/tick.c                        | 24 ++++------
     sys/mips/nlm/tick.c                         | 26 ++++-------
     sys/mips/rmi/tick.c                         | 26 ++++-------
     sys/powerpc/aim/clock.c                     | 26 ++++-------
     sys/powerpc/booke/clock.c                   | 29 ++++--------
     sys/sparc64/sparc64/tick.c                  | 29 +++++-------
     sys/sys/timeet.h                            | 11 ++---
     sys/x86/isa/atrtc.c                         | 11 ++---
     sys/x86/isa/clock.c                         | 17 +++----
     sys/x86/x86/local_apic.c                    | 31 ++++---------
     23 files changed, 207 insertions(+), 370 deletions(-)
    
    diff --git a/share/man/man9/eventtimers.9 b/share/man/man9/eventtimers.9
    index 2f528bfd1ae..b43bc49bcc6 100644
    --- a/share/man/man9/eventtimers.9
    +++ b/share/man/man9/eventtimers.9
    @@ -1,5 +1,5 @@
     .\"
    -.\" Copyright (c) 2011 Alexander Motin 
    +.\" Copyright (c) 2011-2013 Alexander Motin 
     .\" All rights reserved.
     .\"
     .\" Redistribution and use in source and binary forms, with or without
    @@ -24,7 +24,7 @@
     .\"
     .\" $FreeBSD$
     .\"
    -.Dd December 14, 2011
    +.Dd February 25, 2013
     .Dt EVENTTIMERS 9
     .Os
     .Sh NAME
    @@ -36,7 +36,7 @@
     struct eventtimer;
     
     typedef int et_start_t(struct eventtimer *et,
    -    struct bintime *first, struct bintime *period);
    +    sbintime_t first, sbintime_t period);
     typedef int et_stop_t(struct eventtimer *et);
     typedef void et_event_cb_t(struct eventtimer *et, void *arg);
     typedef int et_deregister_cb_t(struct eventtimer *et, void *arg);
    @@ -53,8 +53,8 @@ struct eventtimer {
     	int			et_quality;
     	int			et_active;
     	uint64_t		et_frequency;
    -	struct bintime		et_min_period;
    -	struct bintime		et_max_period;
    +	sbintime_t		et_min_period;
    +	sbintime_t		et_max_period;
     	et_start_t		*et_start;
     	et_stop_t		*et_stop;
     	et_event_cb_t		*et_event_cb;
    @@ -75,7 +75,7 @@ struct eventtimer {
     .Ft int
     .Fn et_init "struct eventtimer *et" "et_event_cb_t *event" "et_deregister_cb_t *deregister" "void *arg"
     .Ft int
    -.Fn et_start "struct eventtimer *et" "struct bintime *first" "struct bintime *period"
    +.Fn et_start "struct eventtimer *et" "sbintime_t first" "sbintime_t period"
     .Ft int
     .Fn et_stop "struct eventtimer *et"
     .Ft int
    diff --git a/sys/arm/allwinner/timer.c b/sys/arm/allwinner/timer.c
    index 4da3517c1c3..49c5f18a063 100644
    --- a/sys/arm/allwinner/timer.c
    +++ b/sys/arm/allwinner/timer.c
    @@ -95,7 +95,7 @@ int a10_timer_get_timerfreq(struct a10_timer_softc *);
     
     static u_int	a10_timer_get_timecount(struct timecounter *);
     static int	a10_timer_timer_start(struct eventtimer *,
    -    struct bintime *, struct bintime *);
    +    sbintime_t first, sbintime_t period);
     static int	a10_timer_timer_stop(struct eventtimer *);
     
     static uint64_t timer_read_counter64(void);
    @@ -193,12 +193,8 @@ a10_timer_attach(device_t dev)
     	sc->et.et_name = "a10_timer Eventtimer";
     	sc->et.et_flags = ET_FLAGS_ONESHOT | ET_FLAGS_PERIODIC;
     	sc->et.et_quality = 1000;
    -	sc->et.et_min_period.sec = 0;
    -	sc->et.et_min_period.frac =
    -	    ((0x00000005LLU << 32) / sc->et.et_frequency) << 32;
    -	sc->et.et_max_period.sec = 0xfffffff0U / sc->et.et_frequency;
    -	sc->et.et_max_period.frac =
    -	    ((0xfffffffeLLU << 32) / sc->et.et_frequency) << 32;
    +	sc->et.et_min_period = (0x00000005LLU << 32) / sc->et.et_frequency;
    +	sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency;
     	sc->et.et_start = a10_timer_timer_start;
     	sc->et.et_stop = a10_timer_timer_stop;
     	sc->et.et_priv = sc;
    @@ -225,8 +221,8 @@ a10_timer_attach(device_t dev)
     }
     
     static int
    -a10_timer_timer_start(struct eventtimer *et, struct bintime *first,
    -    struct bintime *period)
    +a10_timer_timer_start(struct eventtimer *et, sbintime_t first,
    +    sbintime_t period)
     {
     	struct a10_timer_softc *sc;
     	uint32_t count;
    @@ -234,26 +230,21 @@ a10_timer_timer_start(struct eventtimer *et, struct bintime *first,
     
     	sc = (struct a10_timer_softc *)et->et_priv;
     
    -	sc->sc_period = 0;
    -
    -	if (period != NULL) {
    -		sc->sc_period = (sc->et.et_frequency * (period->frac >> 32)) >> 32;
    -		sc->sc_period += sc->et.et_frequency * period->sec;
    -	}
    -	if (first == NULL)
    +	if (period != 0)
    +		sc->sc_period = ((uint32_t)et->et_frequency * period) >> 32;
    +	else
    +		sc->sc_period = 0;
    +	if (first != 0)
    +		count = ((uint32_t)et->et_frequency * first) >> 32;
    +	else
     		count = sc->sc_period;
    -	else {
    -		count = (sc->et.et_frequency * (first->frac >> 32)) >> 32;
    -		if (first->sec != 0)
    -			count += sc->et.et_frequency * first->sec;
    -	}
     
     	/* Update timer values */
     	timer_write_4(sc, SW_TIMER0_INT_VALUE_REG, sc->sc_period);
     	timer_write_4(sc, SW_TIMER0_CUR_VALUE_REG, count);
     
     	val = timer_read_4(sc, SW_TIMER0_CTRL_REG);
    -	if (first == NULL) {
    +	if (period != 0) {
     		/* periodic */
     		val |= TIMER_AUTORELOAD;
     	} else {
    diff --git a/sys/arm/arm/mpcore_timer.c b/sys/arm/arm/mpcore_timer.c
    index 41a0b27382c..8445d3df40c 100644
    --- a/sys/arm/arm/mpcore_timer.c
    +++ b/sys/arm/arm/mpcore_timer.c
    @@ -167,31 +167,23 @@ arm_tmr_get_timecount(struct timecounter *tc)
      *	Always returns 0
      */
     static int
    -arm_tmr_start(struct eventtimer *et, struct bintime *first,
    -              struct bintime *period)
    +arm_tmr_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
     {
    -	struct arm_tmr_softc *sc = (struct arm_tmr_softc *)et->et_priv;
     	uint32_t load, count;
     	uint32_t ctrl;
     
     	ctrl = PRV_TIMER_CTRL_IRQ_ENABLE | PRV_TIMER_CTRL_TIMER_ENABLE;
     
    -	if (period != NULL) {
    -		load = (et->et_frequency * (period->frac >> 32)) >> 32;
    -		if (period->sec > 0)
    -			load += et->et_frequency * period->sec;
    +	if (period != 0) {
    +		load = ((uint32_t)et->et_frequency * period) >> 32;
     		ctrl |= PRV_TIMER_CTRL_AUTO_RELOAD;
    -	} else {
    +	} else
     		load = 0;
    -	}
     
    -	if (first != NULL) {
    -		count = (sc->et.et_frequency * (first->frac >> 32)) >> 32;
    -		if (first->sec != 0)
    -			count += sc->et.et_frequency * first->sec;
    -	} else {
    +	if (first != 0)
    +		count = ((uint32_t)et->et_frequency * first) >> 32;
    +	else
     		count = load;
    -	}
     
     	tmr_prv_write_4(PRV_TIMER_LOAD, load);
     	tmr_prv_write_4(PRV_TIMER_COUNT, count);
    @@ -330,12 +322,8 @@ arm_tmr_attach(device_t dev)
     	sc->et.et_quality = 1000;
     
     	sc->et.et_frequency = sc->clkfreq;
    -	sc->et.et_min_period.sec = 0;
    -	sc->et.et_min_period.frac =
    -            ((0x00000002LLU << 32) / sc->et.et_frequency) << 32;
    -	sc->et.et_max_period.sec = 0xfffffff0U / sc->et.et_frequency;
    -	sc->et.et_max_period.frac =
    -            ((0xfffffffeLLU << 32) / sc->et.et_frequency) << 32;
    +	sc->et.et_min_period = (0x00000002LLU << 32) / sc->et.et_frequency;
    +	sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency;
     	sc->et.et_start = arm_tmr_start;
     	sc->et.et_stop = arm_tmr_stop;
     	sc->et.et_priv = sc;
    diff --git a/sys/arm/broadcom/bcm2835/bcm2835_systimer.c b/sys/arm/broadcom/bcm2835/bcm2835_systimer.c
    index 97ec43aebcf..1d7fddaea8f 100644
    --- a/sys/arm/broadcom/bcm2835/bcm2835_systimer.c
    +++ b/sys/arm/broadcom/bcm2835/bcm2835_systimer.c
    @@ -118,19 +118,16 @@ bcm_systimer_tc_get_timecount(struct timecounter *tc)
     }
     
     static int
    -bcm_systimer_start(struct eventtimer *et, struct bintime *first,
    -              struct bintime *period)
    +bcm_systimer_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
     {
     	struct systimer *st = et->et_priv;
     	uint32_t clo;
     	uint32_t count;
     	register_t s;
     
    -	if (first != NULL) {
    +	if (first != 0) {
     
    -		count = (st->et.et_frequency * (first->frac >> 32)) >> 32;
    -		if (first->sec != 0)
    -			count += st->et.et_frequency * first->sec;
    +		count = ((uint32_t)et->et_frequency * first) >> 32;
     
     		s = intr_disable();
     		clo = bcm_systimer_tc_read_4(SYSTIMER_CLO);
    @@ -238,12 +235,10 @@ bcm_systimer_attach(device_t dev)
     	sc->st[DEFAULT_TIMER].et.et_flags = ET_FLAGS_ONESHOT;
     	sc->st[DEFAULT_TIMER].et.et_quality = 1000;
     	sc->st[DEFAULT_TIMER].et.et_frequency = sc->sysclk_freq;
    -	sc->st[DEFAULT_TIMER].et.et_min_period.sec = 0;
    -	sc->st[DEFAULT_TIMER].et.et_min_period.frac =
    -	    ((MIN_PERIOD << 32) / sc->st[DEFAULT_TIMER].et.et_frequency) << 32;
    -	sc->st[DEFAULT_TIMER].et.et_max_period.sec = 0xfffffff0U / sc->st[DEFAULT_TIMER].et.et_frequency;
    -	sc->st[DEFAULT_TIMER].et.et_max_period.frac =
    -	    ((0xfffffffeLLU << 32) / sc->st[DEFAULT_TIMER].et.et_frequency) << 32;
    +	sc->st[DEFAULT_TIMER].et.et_min_period =
    +	    (MIN_PERIOD << 32) / sc->st[DEFAULT_TIMER].et.et_frequency;
    +	sc->st[DEFAULT_TIMER].et.et_max_period =
    +	    (0xfffffffeLLU << 32) / sc->st[DEFAULT_TIMER].et.et_frequency;
     	sc->st[DEFAULT_TIMER].et.et_start = bcm_systimer_start;
     	sc->st[DEFAULT_TIMER].et.et_stop = bcm_systimer_stop;
     	sc->st[DEFAULT_TIMER].et.et_priv = &sc->st[DEFAULT_TIMER];
    diff --git a/sys/arm/lpc/lpc_timer.c b/sys/arm/lpc/lpc_timer.c
    index 87ed104740c..8572e1a09fe 100644
    --- a/sys/arm/lpc/lpc_timer.c
    +++ b/sys/arm/lpc/lpc_timer.c
    @@ -72,8 +72,8 @@ static struct lpc_timer_softc *timer_softc = NULL;
     static int lpc_timer_initialized = 0;
     static int lpc_timer_probe(device_t);
     static int lpc_timer_attach(device_t);
    -static int lpc_timer_start(struct eventtimer *, struct bintime *first,
    -    struct bintime *);
    +static int lpc_timer_start(struct eventtimer *,
    +    sbintime_t first, sbintime_t period);
     static int lpc_timer_stop(struct eventtimer *et);
     static unsigned lpc_get_timecount(struct timecounter *);
     static int lpc_hardclock(void *);
    @@ -173,12 +173,8 @@ lpc_timer_attach(device_t dev)
     	sc->lt_et.et_name = "LPC32x0 Timer0";
     	sc->lt_et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT;
     	sc->lt_et.et_quality = 1000;
    -	sc->lt_et.et_min_period.sec = 0;
    -	sc->lt_et.et_min_period.frac =
    -	    ((0x00000002LLU << 32) / sc->lt_et.et_frequency) << 32;
    -	sc->lt_et.et_max_period.sec = 0xfffffff0U / sc->lt_et.et_frequency;
    -	sc->lt_et.et_max_period.frac =
    -	    ((0xfffffffeLLU << 32) / sc->lt_et.et_frequency) << 32;
    +	sc->lt_et.et_min_period = (0x00000002LLU << 32) / sc->lt_et.et_frequency;
    +	sc->lt_et.et_max_period = (0xfffffffeLLU << 32) / sc->lt_et.et_frequency;
     	sc->lt_et.et_start = lpc_timer_start;
     	sc->lt_et.et_stop = lpc_timer_stop;
     	sc->lt_et.et_priv = sc;
    @@ -199,27 +195,23 @@ lpc_timer_attach(device_t dev)
     }
     
     static int
    -lpc_timer_start(struct eventtimer *et, struct bintime *first,
    -    struct bintime *period)
    +lpc_timer_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
     {
     	struct lpc_timer_softc *sc = (struct lpc_timer_softc *)et->et_priv;
     	uint32_t ticks;
     
    -	if (period == NULL)
    +	if (period == 0) {
     		sc->lt_oneshot = 1;
    -	else {
    +		sc->lt_period = 0;
    +	} else {
     		sc->lt_oneshot = 0;
    -		sc->lt_period = (sc->lt_et.et_frequency * (first->frac >> 32)) >> 32;
    -			sc->lt_period += sc->lt_et.et_frequency * first->sec;
    +		sc->lt_period = ((uint32_t)et->et_frequency * period) >> 32;
     	}
     
    -	if (first == NULL)
    +	if (first == 0)
     		ticks = sc->lt_period;
    -	else {
    -		ticks = (sc->lt_et.et_frequency * (first->frac >> 32)) >> 32;
    -		if (first->sec != 0)
    -			ticks += sc->lt_et.et_frequency * first->sec;
    -	}
    +	else
    +		ticks = ((uint32_t)et->et_frequency * first) >> 32;
     
     	/* Reset timer */
     	timer0_write_4(sc, LPC_TIMER_TCR, LPC_TIMER_TCR_RESET);
    diff --git a/sys/arm/mv/timer.c b/sys/arm/mv/timer.c
    index db6e4047724..51a6c17ca2a 100644
    --- a/sys/arm/mv/timer.c
    +++ b/sys/arm/mv/timer.c
    @@ -93,7 +93,7 @@ static void	mv_watchdog_enable(void);
     static void	mv_watchdog_disable(void);
     static void	mv_watchdog_event(void *, unsigned int, int *);
     static int	mv_timer_start(struct eventtimer *et,
    -    struct bintime *first, struct bintime *period);
    +    sbintime_t first, sbintime_t period);
     static int	mv_timer_stop(struct eventtimer *et);
     static void	mv_setup_timers(void);
     
    @@ -168,12 +168,8 @@ mv_timer_attach(device_t dev)
     	sc->et.et_quality = 1000;
     
     	sc->et.et_frequency = MV_CLOCK_SRC;
    -	sc->et.et_min_period.sec = 0;
    -	sc->et.et_min_period.frac =
    -	    ((0x00000002LLU << 32) / sc->et.et_frequency) << 32;
    -	sc->et.et_max_period.sec = 0xfffffff0U / sc->et.et_frequency;
    -	sc->et.et_max_period.frac =
    -	    ((0xfffffffeLLU << 32) / sc->et.et_frequency) << 32;
    +	sc->et.et_min_period = (0x00000002LLU << 32) / sc->et.et_frequency;
    +	sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency;
     	sc->et.et_start = mv_timer_start;
     	sc->et.et_stop = mv_timer_stop;
     	sc->et.et_priv = sc;
    @@ -394,25 +390,20 @@ mv_watchdog_event(void *arg, unsigned int cmd, int *error)
     }
     
     static int
    -mv_timer_start(struct eventtimer *et,
    -    struct bintime *first, struct bintime *period)
    +mv_timer_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
     {
     	struct	mv_timer_softc *sc;
     	uint32_t val, val1;
     
     	/* Calculate dividers. */
     	sc = (struct mv_timer_softc *)et->et_priv;
    -	if (period != NULL) {
    -		val = (sc->et.et_frequency * (period->frac >> 32)) >> 32;
    -		if (period->sec != 0)
    -			val += sc->et.et_frequency * period->sec;
    -	} else
    +	if (period != 0)
    +		val = ((uint32_t)sc->et.et_frequency * period) >> 32;
    +	else
     		val = 0;
    -	if (first != NULL) {
    -		val1 = (sc->et.et_frequency * (first->frac >> 32)) >> 32;
    -		if (first->sec != 0)
    -			val1 += sc->et.et_frequency * first->sec;
    -	} else
    +	if (first != 0)
    +		val1 = ((uint32_t)sc->et.et_frequency * first) >> 32;
    +	else
     		val1 = val;
     
     	/* Apply configuration. */
    @@ -420,7 +411,7 @@ mv_timer_start(struct eventtimer *et,
     	mv_set_timer(0, val1);
     	val = mv_get_timer_control();
     	val |= CPU_TIMER0_EN;
    -	if (period != NULL)
    +	if (period != 0)
     		val |= CPU_TIMER0_AUTO;
     	else
     		val &= ~CPU_TIMER0_AUTO;
    diff --git a/sys/arm/ti/am335x/am335x_dmtimer.c b/sys/arm/ti/am335x/am335x_dmtimer.c
    index be9832c6551..93911f24f18 100644
    --- a/sys/arm/ti/am335x/am335x_dmtimer.c
    +++ b/sys/arm/ti/am335x/am335x_dmtimer.c
    @@ -143,30 +143,24 @@ am335x_dmtimer_tc_get_timecount(struct timecounter *tc)
     }
     
     static int
    -am335x_dmtimer_start(struct eventtimer *et, struct bintime *first,
    -              struct bintime *period)
    +am335x_dmtimer_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
     {
     	struct am335x_dmtimer *tmr = (struct am335x_dmtimer *)et->et_priv;
     	uint32_t load, count;
     	uint32_t tclr = 0;
     
    -	if (period != NULL) {
    -		load = (et->et_frequency * (period->frac >> 32)) >> 32;
    -		if (period->sec > 0)
    -			load += et->et_frequency * period->sec;
    +	if (period != 0) {
    +		load = ((uint32_t)et->et_frequency * period) >> 32;
     		tclr |= 2; /* autoreload bit */
     		panic("periodic timer not implemented\n");
     	} else {
     		load = 0;
     	}
     
    -	if (first != NULL) {
    -		count = (tmr->et.et_frequency * (first->frac >> 32)) >> 32;
    -		if (first->sec != 0)
    -			count += tmr->et.et_frequency * first->sec;
    -	} else {
    +	if (first != 0)
    +		count = ((uint32_t)et->et_frequency * first) >> 32;
    +	else
     		count = load;
    -	}
     
     	/* Reset Timer */
     	am335x_dmtimer_et_write_4(DMTIMER_TSICR, 2);
    @@ -316,12 +310,10 @@ am335x_dmtimer_attach(device_t dev)
     	sc->t[3].et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT;
     	sc->t[3].et.et_quality = 1000;
     	sc->t[3].et.et_frequency = sc->sysclk_freq;
    -	sc->t[3].et.et_min_period.sec = 0;
    -	sc->t[3].et.et_min_period.frac =
    -	    ((0x00000002LLU << 32) / sc->t[3].et.et_frequency) << 32;
    -	sc->t[3].et.et_max_period.sec = 0xfffffff0U / sc->t[3].et.et_frequency;
    -	sc->t[3].et.et_max_period.frac =
    -	    ((0xfffffffeLLU << 32) / sc->t[3].et.et_frequency) << 32;
    +	sc->t[3].et.et_min_period =
    +	    (0x00000002LLU << 32) / sc->t[3].et.et_frequency;
    +	sc->t[3].et.et_max_period =
    +	    (0xfffffffeLLU << 32) / sc->t[3].et.et_frequency;
     	sc->t[3].et.et_start = am335x_dmtimer_start;
     	sc->t[3].et.et_stop = am335x_dmtimer_stop;
     	sc->t[3].et.et_priv = &sc->t[3];
    diff --git a/sys/arm/versatile/sp804.c b/sys/arm/versatile/sp804.c
    index 82a1889b260..000ccb64380 100644
    --- a/sys/arm/versatile/sp804.c
    +++ b/sys/arm/versatile/sp804.c
    @@ -120,18 +120,15 @@ sp804_timer_tc_get_timecount(struct timecounter *tc)
     }
     
     static int
    -sp804_timer_start(struct eventtimer *et, struct bintime *first,
    -              struct bintime *period)
    +sp804_timer_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
     {
     	struct sp804_timer_softc *sc = et->et_priv;
     	uint32_t count, reg;
     
    -	if (first != NULL) {
    +	if (first != 0) {
     		sc->et_enabled = 1;
     
    -		count = (sc->et.et_frequency * (first->frac >> 32)) >> 32;
    -		if (first->sec != 0)
    -			count += sc->et.et_frequency * first->sec;
    +		count = ((uint32_t)et->et_frequency * first) >> 32;
     
     		sp804_timer_tc_write_4(SP804_TIMER2_LOAD, count);
     		reg = TIMER_CONTROL_32BIT | TIMER_CONTROL_INTREN |
    @@ -142,7 +139,7 @@ sp804_timer_start(struct eventtimer *et, struct bintime *first,
     		return (0);
     	} 
     
    -	if (period != NULL) {
    +	if (period != 0) {
     		panic("period");
     	}
     
    @@ -264,12 +261,8 @@ sp804_timer_attach(device_t dev)
     	sc->et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT;
     	sc->et.et_quality = 1000;
     	sc->et.et_frequency = sc->sysclk_freq / DEFAULT_DIVISOR;
    -	sc->et.et_min_period.sec = 0;
    -	sc->et.et_min_period.frac =
    -	    ((0x00000002LLU << 32) / sc->et.et_frequency) << 32;
    -	sc->et.et_max_period.sec = 0xfffffff0U / sc->et.et_frequency;
    -	sc->et.et_max_period.frac =
    -	    ((0xfffffffeLLU << 32) / sc->et.et_frequency) << 32;
    +	sc->et.et_min_period = (0x00000002LLU << 32) / sc->et.et_frequency;
    +	sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency;
     	sc->et.et_start = sp804_timer_start;
     	sc->et.et_stop = sp804_timer_stop;
     	sc->et.et_priv = sc;
    diff --git a/sys/dev/acpica/acpi_hpet.c b/sys/dev/acpica/acpi_hpet.c
    index c00bda4cc36..9b9c966f837 100644
    --- a/sys/dev/acpica/acpi_hpet.c
    +++ b/sys/dev/acpica/acpi_hpet.c
    @@ -147,8 +147,7 @@ hpet_disable(struct hpet_softc *sc)
     }
     
     static int
    -hpet_start(struct eventtimer *et,
    -    struct bintime *first, struct bintime *period)
    +hpet_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
     {
     	struct hpet_timer *mt = (struct hpet_timer *)et->et_priv;
     	struct hpet_timer *t;
    @@ -156,20 +155,16 @@ hpet_start(struct eventtimer *et,
     	uint32_t fdiv, now;
     
     	t = (mt->pcpu_master < 0) ? mt : &sc->t[mt->pcpu_slaves[curcpu]];
    -	if (period != NULL) {
    +	if (period != 0) {
     		t->mode = 1;
    -		t->div = (sc->freq * (period->frac >> 32)) >> 32;
    -		if (period->sec != 0)
    -			t->div += sc->freq * period->sec;
    +		t->div = (sc->freq * period) >> 32;
     	} else {
     		t->mode = 2;
     		t->div = 0;
     	}
    -	if (first != NULL) {
    -		fdiv = (sc->freq * (first->frac >> 32)) >> 32;
    -		if (first->sec != 0)
    -			fdiv += sc->freq * first->sec;
    -	} else
    +	if (first != 0)
    +		fdiv = (sc->freq * first) >> 32;
    +	else
     		fdiv = t->div;
     	if (t->irq < 0)
     		bus_write_4(sc->mem_res, HPET_ISR, 1 << t->num);
    @@ -684,12 +679,9 @@ hpet_attach(device_t dev)
     		if ((t->caps & HPET_TCAP_PER_INT) == 0)
     			t->et.et_quality -= 10;
     		t->et.et_frequency = sc->freq;
    -		t->et.et_min_period.sec = 0;
    -		t->et.et_min_period.frac =
    -		    (((uint64_t)(HPET_MIN_CYCLES * 2) << 32) / sc->freq) << 32;
    -		t->et.et_max_period.sec = 0xfffffffeLLU / sc->freq;
    -		t->et.et_max_period.frac =
    -		    ((0xfffffffeLLU << 32) / sc->freq) << 32;
    +		t->et.et_min_period =
    +		    ((uint64_t)(HPET_MIN_CYCLES * 2) << 32) / sc->freq;
    +		t->et.et_max_period = (0xfffffffeLLU << 32) / sc->freq;
     		t->et.et_start = hpet_start;
     		t->et.et_stop = hpet_stop;
     		t->et.et_priv = &sc->t[i];
    diff --git a/sys/i386/xen/clock.c b/sys/i386/xen/clock.c
    index 4e43a12c03e..a10b5462b7a 100644
    --- a/sys/i386/xen/clock.c
    +++ b/sys/i386/xen/clock.c
    @@ -768,8 +768,7 @@ resettodr()
     #endif
     
     static int
    -xen_et_start(struct eventtimer *et,
    -    struct bintime *first, struct bintime *period)
    +xen_et_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
     {
     	struct xen_et_state *state = DPCPU_PTR(et_state);
     	struct shadow_time_info *shadow;
    @@ -777,21 +776,16 @@ xen_et_start(struct eventtimer *et,
     
     	__get_time_values_from_xen();
     
    -	if (period != NULL) {
    +	if (period != 0) {
     		state->mode = MODE_PERIODIC;
    -		state->period = (1000000000LL *
    -		    (uint32_t)(period->frac >> 32)) >> 32;
    -		if (period->sec != 0)
    -			state->period += 1000000000LL * period->sec;
    +		state->period = (1000000000LLU * period) >> 32;
     	} else {
     		state->mode = MODE_ONESHOT;
     		state->period = 0;
     	}
    -	if (first != NULL) {
    -		fperiod = (1000000000LL * (uint32_t)(first->frac >> 32)) >> 32;
    -		if (first->sec != 0)
    -			fperiod += 1000000000LL * first->sec;
    -	} else
    +	if (first != 0)
    +		fperiod = (1000000000LLU * first) >> 32;
    +	else
     		fperiod = state->period;
     
     	shadow = &per_cpu(shadow_time, smp_processor_id());
    @@ -832,11 +826,9 @@ cpu_initclocks(void)
     	xen_et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT |
     	    ET_FLAGS_PERCPU;
     	xen_et.et_quality = 600;
    -	xen_et.et_frequency = 0;
    -	xen_et.et_min_period.sec = 0;
    -	xen_et.et_min_period.frac = 0x00400000LL << 32;
    -	xen_et.et_max_period.sec = 2;
    -	xen_et.et_max_period.frac = 0;
    +	xen_et.et_frequency = 1000000000;
    +	xen_et.et_min_period = 0x00400000LL;
    +	xen_et.et_max_period = (0xfffffffeLLU << 32) / xen_et.et_frequency;
     	xen_et.et_start = xen_et_start;
     	xen_et.et_stop = xen_et_stop;
     	xen_et.et_priv = NULL;
    diff --git a/sys/ia64/ia64/clock.c b/sys/ia64/ia64/clock.c
    index 24623c5d1de..37a99a13830 100644
    --- a/sys/ia64/ia64/clock.c
    +++ b/sys/ia64/ia64/clock.c
    @@ -105,17 +105,14 @@ ia64_ih_clock(struct thread *td, u_int xiv, struct trapframe *tf)
      * Event timer start method.
      */
     static int
    -ia64_clock_start(struct eventtimer *et, struct bintime *first,
    -    struct bintime *period)
    +ia64_clock_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
     {
     	u_long itc, load;
     	register_t is;
     
    -	if (period != NULL) {
    +	if (period != 0) {
     		PCPU_SET(md.clock_mode, CLOCK_ET_PERIODIC);
    -		load = (et->et_frequency * (period->frac >> 32)) >> 32;
    -		if (period->sec > 0)
    -			load += et->et_frequency * period->sec;
    +		load = (et->et_frequency * period) >> 32;
     	} else {
     		PCPU_SET(md.clock_mode, CLOCK_ET_ONESHOT);
     		load = 0;
    @@ -123,11 +120,8 @@ ia64_clock_start(struct eventtimer *et, struct bintime *first,
     
     	PCPU_SET(md.clock_load, load);
     
    -	if (first != NULL) {
    -		load = (et->et_frequency * (first->frac >> 32)) >> 32;
    -		if (first->sec > 0)
    -			load += et->et_frequency * first->sec;
    -	}
    +	if (first != 0)
    +		load = (et->et_frequency * first) >> 32;
     
     	is = intr_disable();
     	itc = ia64_get_itc();
    @@ -185,10 +179,8 @@ clock_configure(void *dummy)
     	et->et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT | ET_FLAGS_PERCPU;
     	et->et_quality = 1000;
     	et->et_frequency = itc_freq;
    -	et->et_min_period.sec = 0;
    -	et->et_min_period.frac = (0x8000000000000000ul / (u_long)(10*hz)) << 1;
    -	et->et_max_period.sec = 0xffffffff;
    -	et->et_max_period.frac = ((0xfffffffeul << 32) / itc_freq) << 32;
    +	et->et_min_period = SBT_1S / (10 * hz);
    +	et->et_max_period = (0xfffffffeul << 32) / itc_freq;
     	et->et_start = ia64_clock_start;
     	et->et_stop = ia64_clock_stop;
     	et->et_priv = NULL;
    diff --git a/sys/kern/kern_clocksource.c b/sys/kern/kern_clocksource.c
    index ac7e2de77a3..10732d991a3 100644
    --- a/sys/kern/kern_clocksource.c
    +++ b/sys/kern/kern_clocksource.c
    @@ -153,6 +153,8 @@ static DPCPU_DEFINE(struct pcpu_state, timerstate);
     	(((uint64_t)0x8000000000000000 + ((bt)->frac >> 2)) /		\
     	    ((bt)->frac >> 1))
     
    +#define	SBT2FREQ(sbt)	((SBT_1S + ((sbt) >> 1)) / (sbt))
    +
     /*
      * Timer broadcast IPI handler.
      */
    @@ -442,7 +444,7 @@ loadtimer(struct bintime *now, int start)
     			    new.sec, (u_int)(new.frac >> 32));
     			*next = new;
     			bintime_add(next, now);
    -			et_start(timer, &new, &timerperiod);
    +			et_start(timer, bttosbt(new), bttosbt(timerperiod));
     		}
     	} else {
     		getnextevent(&new);
    @@ -454,7 +456,7 @@ loadtimer(struct bintime *now, int start)
     		if (!eq) {
     			*next = new;
     			bintime_sub(&new, now);
    -			et_start(timer, &new, NULL);
    +			et_start(timer, bttosbt(new), 0);
     		}
     	}
     }
    @@ -603,13 +605,13 @@ round_freq(struct eventtimer *et, int freq)
     			div = 1 << (flsl(div + div / 2) - 1);
     		freq = (et->et_frequency + div / 2) / div;
     	}
    -	if (et->et_min_period.sec > 0)
    +	if (et->et_min_period > SBT_1S)
     		panic("Event timer \"%s\" doesn't support sub-second periods!",
     		    et->et_name);
    -	else if (et->et_min_period.frac != 0)
    -		freq = min(freq, BT2FREQ(&et->et_min_period));
    -	if (et->et_max_period.sec == 0 && et->et_max_period.frac != 0)
    -		freq = max(freq, BT2FREQ(&et->et_max_period));
    +	else if (et->et_min_period != 0)
    +		freq = min(freq, SBT2FREQ(et->et_min_period));
    +	if (et->et_max_period < SBT_1S && et->et_max_period != 0)
    +		freq = max(freq, SBT2FREQ(et->et_max_period));
     	return (freq);
     }
     
    diff --git a/sys/kern/kern_et.c b/sys/kern/kern_et.c
    index 3156c818655..472db79e9d5 100644
    --- a/sys/kern/kern_et.c
    +++ b/sys/kern/kern_et.c
    @@ -1,5 +1,5 @@
     /*-
    - * Copyright (c) 2010 Alexander Motin 
    + * Copyright (c) 2010-2013 Alexander Motin 
      * All rights reserved.
      *
      * Redistribution and use in source and binary forms, with or without
    @@ -62,6 +62,7 @@ et_register(struct eventtimer *et)
     			    et->et_quality);
     		}
     	}
    +	KASSERT(et->et_start, ("et_register: timer has no start function"));
     	et->et_sysctl = SYSCTL_ADD_NODE(NULL,
     	    SYSCTL_STATIC_CHILDREN(_kern_eventtimer_et), OID_AUTO, et->et_name,
     	    CTLFLAG_RW, 0, "event timer description");
    @@ -159,43 +160,29 @@ et_init(struct eventtimer *et, et_event_cb_t *event,
      * period - period of subsequent periodic ticks.
      */
     int
    -et_start(struct eventtimer *et,
    -    struct bintime *first, struct bintime *period)
    +et_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
     {
     
     	if (!et->et_active)
     		return (ENXIO);
    -	if (first == NULL && period == NULL)
    -		return (EINVAL);
    -	if ((et->et_flags & ET_FLAGS_PERIODIC) == 0 &&
    -	    period != NULL)
    -		return (ENODEV);
    -	if ((et->et_flags & ET_FLAGS_ONESHOT) == 0 &&
    -	    period == NULL)
    -		return (ENODEV);
    -	if (first != NULL) {
    -		if (first->sec < et->et_min_period.sec ||
    -		    (first->sec == et->et_min_period.sec &&
    -		     first->frac < et->et_min_period.frac))
    -		        first = &et->et_min_period;
    -		if (first->sec > et->et_max_period.sec ||
    -		    (first->sec == et->et_max_period.sec &&
    -		     first->frac > et->et_max_period.frac))
    -		        first = &et->et_max_period;
    +	KASSERT(period >= 0, ("et_start: negative period"));
    +	KASSERT((et->et_flags & ET_FLAGS_PERIODIC) || period == 0,
    +		("et_start: period specified for oneshot-only timer"));
    +	KASSERT((et->et_flags & ET_FLAGS_ONESHOT) && period == 0,
    +		("et_start: period not specified for periodic-only timer"));
    +	if (period != 0) {
    +		if (period < et->et_min_period)
    +		        period = et->et_min_period;
    +		else if (period > et->et_max_period)
    +		        period = et->et_max_period;
     	}
    -	if (period != NULL) {
    -		if (period->sec < et->et_min_period.sec ||
    -		    (period->sec == et->et_min_period.sec &&
    -		     period->frac < et->et_min_period.frac))
    -		        period = &et->et_min_period;
    -		if (period->sec > et->et_max_period.sec ||
    -		    (period->sec == et->et_max_period.sec &&
    -		     period->frac > et->et_max_period.frac))
    -		        period = &et->et_max_period;
    +	if (period == 0 || first != 0) {
    +		if (first < et->et_min_period)
    +		        first = et->et_min_period;
    +		else if (first > et->et_max_period)
    +		        first = et->et_max_period;
     	}
    -	if (et->et_start)
    -		return (et->et_start(et, first, period));
    -	return (0);
    +	return (et->et_start(et, first, period));
     }
     
     /* Stop event timer hardware. */
    diff --git a/sys/mips/mips/tick.c b/sys/mips/mips/tick.c
    index 50f4f24ead3..1dc3e7a8efb 100644
    --- a/sys/mips/mips/tick.c
    +++ b/sys/mips/mips/tick.c
    @@ -217,22 +217,17 @@ DELAY(int n)
     }
     
     static int
    -clock_start(struct eventtimer *et,
    -    struct bintime *first, struct bintime *period)
    +clock_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
     {
     	uint32_t fdiv, div, next;
     
    -	if (period != NULL) {
    -		div = (et->et_frequency * (period->frac >> 32)) >> 32;
    -		if (period->sec != 0)
    -			div += et->et_frequency * period->sec;
    +	if (period != 0) {
    +		div = (et->et_frequency * period) >> 32;
     	} else
     		div = 0;
    -	if (first != NULL) {
    -		fdiv = (et->et_frequency * (first->frac >> 32)) >> 32;
    -		if (first->sec != 0)
    -			fdiv += et->et_frequency * first->sec;
    -	} else 
    +	if (first != 0)
    +		fdiv = (et->et_frequency * first) >> 32;
    +	else 
     		fdiv = div;
     	DPCPU_SET(cycles_per_tick, div);
     	next = mips_rd_count() + fdiv;
    @@ -361,11 +356,8 @@ clock_attach(device_t dev)
     	    ET_FLAGS_PERCPU;
     	sc->et.et_quality = 800;
     	sc->et.et_frequency = counter_freq;
    -	sc->et.et_min_period.sec = 0;
    -	sc->et.et_min_period.frac = 0x00004000LLU << 32; /* To be safe. */
    -	sc->et.et_max_period.sec = 0xfffffffeU / sc->et.et_frequency;
    -	sc->et.et_max_period.frac =
    -	    ((0xfffffffeLLU << 32) / sc->et.et_frequency) << 32;
    +	sc->et.et_min_period = 0x00004000LLU; /* To be safe. */
    +	sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency;
     	sc->et.et_start = clock_start;
     	sc->et.et_stop = clock_stop;
     	sc->et.et_priv = sc;
    diff --git a/sys/mips/nlm/tick.c b/sys/mips/nlm/tick.c
    index 09f3bb67997..b5a8c368ea3 100644
    --- a/sys/mips/nlm/tick.c
    +++ b/sys/mips/nlm/tick.c
    @@ -222,22 +222,17 @@ DELAY(int n)
     }
     
     static int
    -clock_start(struct eventtimer *et,
    -    struct bintime *first, struct bintime *period)
    +clock_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
     {
     	uint32_t fdiv, div, next;
     
    -	if (period != NULL) {
    -		div = (et->et_frequency * (period->frac >> 32)) >> 32;
    -		if (period->sec != 0)
    -			div += et->et_frequency * period->sec;
    -	} else
    +	if (period != 0)
    +		div = (et->et_frequency * period) >> 32;
    +	else
     		div = 0;
    -	if (first != NULL) {
    -		fdiv = (et->et_frequency * (first->frac >> 32)) >> 32;
    -		if (first->sec != 0)
    -			fdiv += et->et_frequency * first->sec;
    -	} else 
    +	if (first != 0)
    +		fdiv = (et->et_frequency * first) >> 32;
    +	else
     		fdiv = div;
     	DPCPU_SET(cycles_per_tick, div);
     	next = mips_rd_count() + fdiv;
    @@ -357,11 +352,8 @@ clock_attach(device_t dev)
     	sc->et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_PERCPU;
     	sc->et.et_quality = 800;
     	sc->et.et_frequency = counter_freq;
    -	sc->et.et_min_period.sec = 0;
    -	sc->et.et_min_period.frac = 0x00004000LLU << 32; /* To be safe. */
    -	sc->et.et_max_period.sec = 0xfffffffeU / sc->et.et_frequency;
    -	sc->et.et_max_period.frac =
    -	    ((0xfffffffeLLU << 32) / sc->et.et_frequency) << 32;
    +	sc->et.et_min_period = 0x00004000LLU; /* To be safe. */
    +	sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency;
     	sc->et.et_start = clock_start;
     	sc->et.et_stop = clock_stop;
     	sc->et.et_priv = sc;
    diff --git a/sys/mips/rmi/tick.c b/sys/mips/rmi/tick.c
    index 39f0a04e49b..adc8c89fb42 100644
    --- a/sys/mips/rmi/tick.c
    +++ b/sys/mips/rmi/tick.c
    @@ -219,22 +219,17 @@ DELAY(int n)
     }
     
     static int
    -clock_start(struct eventtimer *et,
    -    struct bintime *first, struct bintime *period)
    +clock_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
     {
     	uint32_t fdiv, div, next;
     
    -	if (period != NULL) {
    -		div = (et->et_frequency * (period->frac >> 32)) >> 32;
    -		if (period->sec != 0)
    -			div += et->et_frequency * period->sec;
    -	} else
    +	if (period != 0)
    +		div = (et->et_frequency * period) >> 32;
    +	else
     		div = 0;
    -	if (first != NULL) {
    -		fdiv = (et->et_frequency * (first->frac >> 32)) >> 32;
    -		if (first->sec != 0)
    -			fdiv += et->et_frequency * first->sec;
    -	} else 
    +	if (first != 0)
    +		fdiv = (et->et_frequency * first) >> 32;
    +	else 
     		fdiv = div;
     	DPCPU_SET(cycles_per_tick, div);
     	next = mips_rd_count() + fdiv;
    @@ -351,11 +346,8 @@ clock_attach(device_t dev)
     	    ET_FLAGS_PERCPU;
     	sc->et.et_quality = 800;
     	sc->et.et_frequency = counter_freq;
    -	sc->et.et_min_period.sec = 0;
    -	sc->et.et_min_period.frac = 0x00004000LLU << 32; /* To be safe. */
    -	sc->et.et_max_period.sec = 0xfffffffeU / sc->et.et_frequency;
    -	sc->et.et_max_period.frac =
    -	    ((0xfffffffeLLU << 32) / sc->et.et_frequency) << 32;
    +	sc->et.et_min_period = 0x00004000LLU; /* To be safe. */
    +	sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency;
     	sc->et.et_start = clock_start;
     	sc->et.et_stop = clock_stop;
     	sc->et.et_priv = sc;
    diff --git a/sys/powerpc/aim/clock.c b/sys/powerpc/aim/clock.c
    index 0bf7cfa1169..ae98d26efda 100644
    --- a/sys/powerpc/aim/clock.c
    +++ b/sys/powerpc/aim/clock.c
    @@ -85,7 +85,7 @@ static u_long		ticks_per_sec = 12500000;
     static u_long		*decr_counts[MAXCPU];
     
     static int		decr_et_start(struct eventtimer *et,
    -    struct bintime *first, struct bintime *period);
    +    sbintime_t first, sbintime_t period);
     static int		decr_et_stop(struct eventtimer *et);
     static timecounter_get_t	decr_get_timecount;
     
    @@ -195,12 +195,8 @@ decr_tc_init(void)
     	    ET_FLAGS_PERCPU;
     	decr_et.et_quality = 1000;
     	decr_et.et_frequency = ticks_per_sec;
    -	decr_et.et_min_period.sec = 0;
    -	decr_et.et_min_period.frac =
    -	    ((0x00000002LLU << 32) / ticks_per_sec) << 32;
    -	decr_et.et_max_period.sec = 0x7fffffffLLU / ticks_per_sec;
    -	decr_et.et_max_period.frac =
    -	    ((0x7fffffffLLU << 32) / ticks_per_sec) << 32;
    +	decr_et.et_min_period = (0x00000002LLU << 32) / ticks_per_sec;
    +	decr_et.et_max_period = (0x7fffffffLLU << 32) / ticks_per_sec;
     	decr_et.et_start = decr_et_start;
     	decr_et.et_stop = decr_et_stop;
     	decr_et.et_priv = NULL;
    @@ -212,24 +208,20 @@ decr_tc_init(void)
      */
     static int
     decr_et_start(struct eventtimer *et,
    -    struct bintime *first, struct bintime *period)
    +    sbintime_t first, sbintime_t period)
     {
     	struct decr_state *s = DPCPU_PTR(decr_state);
     	uint32_t fdiv;
     
    -	if (period != NULL) {
    +	if (period != 0) {
     		s->mode = 1;
    -		s->div = (decr_et.et_frequency * (period->frac >> 32)) >> 32;
    -		if (period->sec != 0)
    -			s->div += decr_et.et_frequency * period->sec;
    +		s->div = (decr_et.et_frequency * period) >> 32;
     	} else {
     		s->mode = 2;
    -		s->div = 0x7fffffff;
    +		s->div = 0;
     	}
    -	if (first != NULL) {
    -		fdiv = (decr_et.et_frequency * (first->frac >> 32)) >> 32;
    -		if (first->sec != 0)
    -			fdiv += decr_et.et_frequency * first->sec;
    +	if (first != 0) {
    +		fdiv = (decr_et.et_frequency * first) >> 32;
     	} else
     		fdiv = s->div;
     
    diff --git a/sys/powerpc/booke/clock.c b/sys/powerpc/booke/clock.c
    index 9958160a1af..5827e73c25f 100644
    --- a/sys/powerpc/booke/clock.c
    +++ b/sys/powerpc/booke/clock.c
    @@ -88,7 +88,7 @@ static u_long		*decr_counts[MAXCPU];
     #define	DIFF19041970	2082844800
     
     static int		decr_et_start(struct eventtimer *et,
    -    struct bintime *first, struct bintime *period);
    +    sbintime_t first, sbintime_t period);
     static int		decr_et_stop(struct eventtimer *et);
     static timecounter_get_t decr_get_timecount;
     
    @@ -193,12 +193,8 @@ decr_tc_init(void)
     	    ET_FLAGS_PERCPU;
     	decr_et.et_quality = 1000;
     	decr_et.et_frequency = ticks_per_sec;
    -	decr_et.et_min_period.sec = 0;
    -	decr_et.et_min_period.frac =
    -	    ((0x00000002LLU << 32) / ticks_per_sec) << 32;
    -	decr_et.et_max_period.sec = 0xfffffffeLLU / ticks_per_sec;
    -	decr_et.et_max_period.frac =
    -	    ((0xfffffffeLLU << 32) / ticks_per_sec) << 32;
    +	decr_et.et_min_period = (0x00000002LLU << 32) / ticks_per_sec;
    +	decr_et.et_max_period = (0xfffffffeLLU << 32) / ticks_per_sec;
     	decr_et.et_start = decr_et_start;
     	decr_et.et_stop = decr_et_stop;
     	decr_et.et_priv = NULL;
    @@ -209,26 +205,21 @@ decr_tc_init(void)
      * Event timer start method.
      */
     static int
    -decr_et_start(struct eventtimer *et,
    -    struct bintime *first, struct bintime *period)
    +decr_et_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
     {
     	struct decr_state *s = DPCPU_PTR(decr_state);
     	uint32_t fdiv, tcr;
     
    -	if (period != NULL) {
    +	if (period != 0) {
     		s->mode = 1;
    -		s->div = (decr_et.et_frequency * (period->frac >> 32)) >> 32;
    -		if (period->sec != 0)
    -			s->div += decr_et.et_frequency * period->sec;
    +		s->div = (decr_et.et_frequency * period) >> 32;
     	} else {
     		s->mode = 2;
    -		s->div = 0xffffffff;
    +		s->div = 0;
     	}
    -	if (first != NULL) {
    -		fdiv = (decr_et.et_frequency * (first->frac >> 32)) >> 32;
    -		if (first->sec != 0)
    -			fdiv += decr_et.et_frequency * first->sec;
    -	} else
    +	if (first != 0)
    +		fdiv = (decr_et.et_frequency * first) >> 32;
    +	else
     		fdiv = s->div;
     
     	tcr = mfspr(SPR_TCR);
    diff --git a/sys/sparc64/sparc64/tick.c b/sys/sparc64/sparc64/tick.c
    index cfd5776e7c9..130efa691dc 100644
    --- a/sys/sparc64/sparc64/tick.c
    +++ b/sys/sparc64/sparc64/tick.c
    @@ -93,8 +93,8 @@ static timecounter_get_t stick_get_timecount_mp;
     static timecounter_get_t stick_get_timecount_up;
     static rd_tick_t stick_rd;
     static wr_tick_cmpr_t stick_wr_cmpr;
    -static int tick_et_start(struct eventtimer *et, struct bintime *first,
    -    struct bintime *period);
    +static int tick_et_start(struct eventtimer *et, sbintime_t first,
    +    sbintime_t period);
     static int tick_et_stop(struct eventtimer *et);
     #ifdef SMP
     static timecounter_get_t tick_get_timecount_mp;
    @@ -227,10 +227,8 @@ cpu_initclocks(void)
     	    ET_FLAGS_PERCPU;
     	tick_et.et_quality = 1000;
     	tick_et.et_frequency = tick_et_use_stick ? sclock : clock;
    -	tick_et.et_min_period.sec = 0;
    -	tick_et.et_min_period.frac = 0x00010000LLU << 32; /* To be safe. */
    -	tick_et.et_max_period.sec = 3600 * 24; /* No practical limit. */
    -	tick_et.et_max_period.frac = 0;
    +	tick_et.et_min_period = 0x00010000LLU; /* To be safe. */
    +	tick_et.et_max_period = (0xfffffffeLLU << 32) / tick_et.et_frequency;
     	tick_et.et_start = tick_et_start;
     	tick_et.et_stop = tick_et_stop;
     	tick_et.et_priv = NULL;
    @@ -355,23 +353,18 @@ tick_get_timecount_mp(struct timecounter *tc)
     #endif
     
     static int
    -tick_et_start(struct eventtimer *et, struct bintime *first,
    -    struct bintime *period)
    +tick_et_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
     {
     	u_long base, div, fdiv;
     	register_t s;
     
    -	if (period != NULL) {
    -		div = (tick_et.et_frequency * (period->frac >> 32)) >> 32;
    -		if (period->sec != 0)
    -			div += tick_et.et_frequency * period->sec;
    -	} else
    +	if (period != 0)
    +		div = (tick_et.et_frequency * period) >> 32;
    +	else
     		div = 0;
    -	if (first != NULL) {
    -		fdiv = (tick_et.et_frequency * (first->frac >> 32)) >> 32;
    -		if (first->sec != 0)
    -			fdiv += tick_et.et_frequency * first->sec;
    -	} else
    +	if (first != 0)
    +		fdiv = (tick_et.et_frequency * first) >> 32;
    +	else
     		fdiv = div;
     	PCPU_SET(tickincrement, div);
     
    diff --git a/sys/sys/timeet.h b/sys/sys/timeet.h
    index 87392a29a64..23a170c0174 100644
    --- a/sys/sys/timeet.h
    +++ b/sys/sys/timeet.h
    @@ -1,5 +1,5 @@
     /*-
    - * Copyright (c) 2010 Alexander Motin 
    + * Copyright (c) 2010-2013 Alexander Motin 
      * All rights reserved.
      *
      * Redistribution and use in source and binary forms, with or without
    @@ -45,7 +45,7 @@
     
     struct eventtimer;
     typedef int et_start_t(struct eventtimer *et,
    -    struct bintime *first, struct bintime *period);
    +    sbintime_t first, sbintime_t period);
     typedef int et_stop_t(struct eventtimer *et);
     typedef void et_event_cb_t(struct eventtimer *et, void *arg);
     typedef int et_deregister_cb_t(struct eventtimer *et, void *arg);
    @@ -70,8 +70,8 @@ struct eventtimer {
     	int			et_active;
     	u_int64_t		et_frequency;
     		/* Base frequency in Hz. */
    -	struct bintime		et_min_period;
    -	struct bintime		et_max_period;
    +	sbintime_t		et_min_period;
    +	sbintime_t		et_max_period;
     	et_start_t		*et_start;
     	et_stop_t		*et_stop;
     	et_event_cb_t		*et_event_cb;
    @@ -93,8 +93,7 @@ int	et_deregister(struct eventtimer *et);
     struct eventtimer *et_find(const char *name, int check, int want);
     int	et_init(struct eventtimer *et, et_event_cb_t *event,
         et_deregister_cb_t *deregister, void *arg);
    -int	et_start(struct eventtimer *et,
    -    struct bintime *first, struct bintime *period);
    +int	et_start(struct eventtimer *et, sbintime_t first, sbintime_t period);
     int	et_stop(struct eventtimer *et);
     int	et_ban(struct eventtimer *et);
     int	et_free(struct eventtimer *et);
    diff --git a/sys/x86/isa/atrtc.c b/sys/x86/isa/atrtc.c
    index c6a6f8c9a23..69c2157eee2 100644
    --- a/sys/x86/isa/atrtc.c
    +++ b/sys/x86/isa/atrtc.c
    @@ -164,11 +164,10 @@ struct atrtc_softc {
     };
     
     static int
    -rtc_start(struct eventtimer *et,
    -    struct bintime *first, struct bintime *period)
    +rtc_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
     {
     
    -	atrtc_rate(max(fls((period->frac + (period->frac >> 1)) >> 32) - 17, 1));
    +	atrtc_rate(max(fls(period + (period >> 1)) - 17, 1));
     	atrtc_enable_intr();
     	return (0);
     }
    @@ -277,10 +276,8 @@ atrtc_attach(device_t dev)
     		sc->et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_POW2DIV;
     		sc->et.et_quality = 0;
     		sc->et.et_frequency = 32768;
    -		sc->et.et_min_period.sec = 0;
    -		sc->et.et_min_period.frac = 0x0008LLU << 48;
    -		sc->et.et_max_period.sec = 0;
    -		sc->et.et_max_period.frac = 0x8000LLU << 48;
    +		sc->et.et_min_period = 0x00080000;
    +		sc->et.et_max_period = 0x80000000;
     		sc->et.et_start = rtc_start;
     		sc->et.et_stop = rtc_stop;
     		sc->et.et_priv = dev;
    diff --git a/sys/x86/isa/clock.c b/sys/x86/isa/clock.c
    index 232c913674f..29ec02d456e 100644
    --- a/sys/x86/isa/clock.c
    +++ b/sys/x86/isa/clock.c
    @@ -589,18 +589,17 @@ i8254_get_timecount(struct timecounter *tc)
     }
     
     static int
    -attimer_start(struct eventtimer *et,
    -    struct bintime *first, struct bintime *period)
    +attimer_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
     {
     	device_t dev = (device_t)et->et_priv;
     	struct attimer_softc *sc = device_get_softc(dev);
     
    -	if (period != NULL) {
    +	if (period != 0) {
     		sc->mode = MODE_PERIODIC;
    -		sc->period = period->frac >> 32;
    +		sc->period = period;
     	} else {
     		sc->mode = MODE_ONESHOT;
    -		sc->period = first->frac >> 32;
    +		sc->period = first;
     	}
     	if (!sc->intr_en) {
     		i8254_intsrc->is_pic->pic_enable_source(i8254_intsrc);
    @@ -755,12 +754,8 @@ attimer_attach(device_t dev)
     			sc->et.et_flags |= ET_FLAGS_ONESHOT;
     		sc->et.et_quality = 100;
     		sc->et.et_frequency = i8254_freq;
    -		sc->et.et_min_period.sec = 0;
    -		sc->et.et_min_period.frac =
    -		    ((0x0002LLU << 48) / i8254_freq) << 16;
    -		sc->et.et_max_period.sec = 0xffff / i8254_freq;
    -		sc->et.et_max_period.frac =
    -		    ((0xfffeLLU << 48) / i8254_freq) << 16;
    +		sc->et.et_min_period = (0x0002LLU << 32) / i8254_freq;
    +		sc->et.et_max_period = (0xfffeLLU << 32) / i8254_freq;
     		sc->et.et_start = attimer_start;
     		sc->et.et_stop = attimer_stop;
     		sc->et.et_priv = dev;
    diff --git a/sys/x86/x86/local_apic.c b/sys/x86/x86/local_apic.c
    index c60db22bb77..ac87ebd075f 100644
    --- a/sys/x86/x86/local_apic.c
    +++ b/sys/x86/x86/local_apic.c
    @@ -169,7 +169,7 @@ static void	lapic_timer_stop(struct lapic *);
     static void	lapic_timer_set_divisor(u_int divisor);
     static uint32_t	lvt_mode(struct lapic *la, u_int pin, uint32_t value);
     static int	lapic_et_start(struct eventtimer *et,
    -    struct bintime *first, struct bintime *period);
    +    sbintime_t first, sbintime_t period);
     static int	lapic_et_stop(struct eventtimer *et);
     
     struct pic lapic_pic = { .pic_resume = lapic_resume };
    @@ -268,10 +268,8 @@ lapic_init(vm_paddr_t addr)
     		}
     		lapic_et.et_frequency = 0;
     		/* We don't know frequency yet, so trying to guess. */
    -		lapic_et.et_min_period.sec = 0;
    -		lapic_et.et_min_period.frac = 0x00001000LL << 32;
    -		lapic_et.et_max_period.sec = 1;
    -		lapic_et.et_max_period.frac = 0;
    +		lapic_et.et_min_period = 0x00001000LL;
    +		lapic_et.et_max_period = SBT_1S;
     		lapic_et.et_start = lapic_et_start;
     		lapic_et.et_stop = lapic_et_stop;
     		lapic_et.et_priv = NULL;
    @@ -487,8 +485,7 @@ lapic_disable_pmc(void)
     }
     
     static int
    -lapic_et_start(struct eventtimer *et,
    -    struct bintime *first, struct bintime *period)
    +lapic_et_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
     {
     	struct lapic *la;
     	u_long value;
    @@ -513,28 +510,18 @@ lapic_et_start(struct eventtimer *et,
     			printf("lapic: Divisor %lu, Frequency %lu Hz\n",
     			    lapic_timer_divisor, value);
     		et->et_frequency = value;
    -		et->et_min_period.sec = 0;
    -		et->et_min_period.frac =
    -		    ((0x00000002LLU << 32) / et->et_frequency) << 32;
    -		et->et_max_period.sec = 0xfffffffeLLU / et->et_frequency;
    -		et->et_max_period.frac =
    -		    ((0xfffffffeLLU << 32) / et->et_frequency) << 32;
    +		et->et_min_period = (0x00000002LLU << 32) / et->et_frequency;
    +		et->et_max_period = (0xfffffffeLLU << 32) / et->et_frequency;
     	}
     	if (la->la_timer_mode == 0)
     		lapic_timer_set_divisor(lapic_timer_divisor);
    -	if (period != NULL) {
    +	if (period != 0) {
     		la->la_timer_mode = 1;
    -		la->la_timer_period =
    -		    (et->et_frequency * (period->frac >> 32)) >> 32;
    -		if (period->sec != 0)
    -			la->la_timer_period += et->et_frequency * period->sec;
    +		la->la_timer_period = ((uint32_t)et->et_frequency * period) >> 32;
     		lapic_timer_periodic(la, la->la_timer_period, 1);
     	} else {
     		la->la_timer_mode = 2;
    -		la->la_timer_period =
    -		    (et->et_frequency * (first->frac >> 32)) >> 32;
    -		if (first->sec != 0)
    -			la->la_timer_period += et->et_frequency * first->sec;
    +		la->la_timer_period = ((uint32_t)et->et_frequency * first) >> 32;
     		lapic_timer_oneshot(la, la->la_timer_period, 1);
     	}
     	return (0);
    
    From e234a588cb8a1fdfae05e1cc6708715889a6b6dc Mon Sep 17 00:00:00 2001
    From: Davide Italiano 
    Date: Thu, 28 Feb 2013 16:22:49 +0000
    Subject: [PATCH 0474/1476] MFcalloutng: Style fixes.
    
    ---
     sys/kern/kern_timeout.c | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/sys/kern/kern_timeout.c b/sys/kern/kern_timeout.c
    index 80933faf5f5..9cdc39b3809 100644
    --- a/sys/kern/kern_timeout.c
    +++ b/sys/kern/kern_timeout.c
    @@ -100,7 +100,7 @@ struct cc_mig_ent {
     	int	ce_migration_ticks;
     #endif
     };
    -	
    +
     /*
      * There is one struct callout_cpu per cpu, holding all relevant
      * state for the callout processing thread on the individual CPU.
    @@ -613,7 +613,7 @@ skip:
     }
     
     /*
    - * The callout mechanism is based on the work of Adam M. Costello and 
    + * The callout mechanism is based on the work of Adam M. Costello and
      * George Varghese, published in a technical report entitled "Redesigning
      * the BSD Callout and Timer Facilities" and modified slightly for inclusion
      * in FreeBSD by Justin T. Gibbs.  The original work on the data structures
    
    From aa97685d73e8ea9e497b2c8d1977fc98acbe56c8 Mon Sep 17 00:00:00 2001
    From: Davide Italiano 
    Date: Thu, 28 Feb 2013 17:10:30 +0000
    Subject: [PATCH 0475/1476] Move the definition of sbintime_t type from
      to . With this change we prevent gross namespace
     pollution.
    
    Reported by:	bde
    Suggested by:	attilio
    ---
     sys/sys/time.h  | 1 -
     sys/sys/types.h | 2 ++
     2 files changed, 2 insertions(+), 1 deletion(-)
    
    diff --git a/sys/sys/time.h b/sys/sys/time.h
    index 927ceccf7c4..555c37ef5cf 100644
    --- a/sys/sys/time.h
    +++ b/sys/sys/time.h
    @@ -109,7 +109,6 @@ bintime_mul(struct bintime *bt, u_int x)
     	    ((a)->frac cmp (b)->frac) :					\
     	    ((a)->sec cmp (b)->sec))
     
    -typedef int64_t sbintime_t;
     #define	SBT_1S	((sbintime_t)1 << 32)
     #define	SBT_1M	(SBT_1S * 60)
     #define	SBT_1MS	(SBT_1S / 1000)
    diff --git a/sys/sys/types.h b/sys/sys/types.h
    index 491e99daefc..cc0bca8f33b 100644
    --- a/sys/sys/types.h
    +++ b/sys/sys/types.h
    @@ -188,6 +188,8 @@ typedef	__rlim_t	rlim_t;		/* resource limit */
     #define	_RLIM_T_DECLARED
     #endif
     
    +typedef	__int64_t	sbintime_t;
    +
     typedef	__segsz_t	segsz_t;	/* segment size (in pages) */
     
     #ifndef _SIZE_T_DECLARED
    
    From c3a0f75a9f5ac514c85dcde4c23d7e7e14faf250 Mon Sep 17 00:00:00 2001
    From: Oleksandr Tymoshenko 
    Date: Thu, 28 Feb 2013 19:43:14 +0000
    Subject: [PATCH 0476/1476] Add hooks for plugging platform-provided transfer
     backend.
    
    In order to use platorm backend hardware driver should
    impement three methods:
    - platform_start_transfer and platform_finish_transfer
        to start and finish transfer
    - platform_will_handle - check whether transaction is
        suitable for backend. If not - driver will fall back
        to PIO mode.
    
    Submitted by:	Daisuke Aoyama 
    Approved by:	ian@
    ---
     sys/dev/sdhci/sdhci.c    | 34 ++++++++++++++++++++++++++++------
     sys/dev/sdhci/sdhci.h    |  6 +++++-
     sys/dev/sdhci/sdhci_if.m | 16 ++++++++++++++++
     3 files changed, 49 insertions(+), 7 deletions(-)
    
    diff --git a/sys/dev/sdhci/sdhci.c b/sys/dev/sdhci/sdhci.c
    index 1044bb64b3e..15199f01956 100644
    --- a/sys/dev/sdhci/sdhci.c
    +++ b/sys/dev/sdhci/sdhci.c
    @@ -573,6 +573,13 @@ sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num)
     	if (slot->quirks & SDHCI_QUIRK_FORCE_DMA)
     		slot->opt |= SDHCI_HAVE_DMA;
     
    +	/* 
    +	 * Use platform-provided transfer backend
    +	 * with PIO as a fallback mechanism
    +	 */
    +	if (slot->opt & SDHCI_PLATFORM_TRANSFER)
    +		slot->opt &= ~SDHCI_HAVE_DMA;
    +
     	if (bootverbose || sdhci_debug) {
     		slot_printf(slot, "%uMHz%s 4bits%s%s%s %s\n",
     		    slot->max_clk / 1000000,
    @@ -909,7 +916,7 @@ sdhci_start_data(struct sdhci_slot *slot, struct mmc_data *data)
     	WR2(slot, SDHCI_BLOCK_COUNT, (data->len + 511) / 512);
     }
     
    -static void
    +void
     sdhci_finish_data(struct sdhci_slot *slot)
     {
     	struct mmc_data *data = slot->curcmd->data;
    @@ -1102,13 +1109,23 @@ sdhci_data_irq(struct sdhci_slot *slot, uint32_t intmask)
     	}
     	if (slot->curcmd->error) {
     		/* No need to continue after any error. */
    -		sdhci_finish_data(slot);
    +		if (slot->flags & PLATFORM_DATA_STARTED) {
    +			slot->flags &= ~PLATFORM_DATA_STARTED;
    +			SDHCI_PLATFORM_FINISH_TRANSFER(slot->bus, slot);
    +		} else
    +			sdhci_finish_data(slot);
     		return;
     	}
     
     	/* Handle PIO interrupt. */
    -	if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL))
    -		sdhci_transfer_pio(slot);
    +	if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL)) {
    +		if ((slot->opt & SDHCI_PLATFORM_TRANSFER) && 
    +		    SDHCI_PLATFORM_WILL_HANDLE(slot->bus, slot)) {
    +			SDHCI_PLATFORM_START_TRANSFER(slot->bus, slot, &intmask);
    +			slot->flags |= PLATFORM_DATA_STARTED;
    +		} else
    +			sdhci_transfer_pio(slot);
    +	}
     	/* Handle DMA border. */
     	if (intmask & SDHCI_INT_DMA_END) {
     		struct mmc_data *data = slot->curcmd->data;
    @@ -1147,8 +1164,13 @@ sdhci_data_irq(struct sdhci_slot *slot, uint32_t intmask)
     		WR4(slot, SDHCI_DMA_ADDRESS, slot->paddr);
     	}
     	/* We have got all data. */
    -	if (intmask & SDHCI_INT_DATA_END)
    -		sdhci_finish_data(slot);
    +	if (intmask & SDHCI_INT_DATA_END) {
    +		if (slot->flags & PLATFORM_DATA_STARTED) {
    +			slot->flags &= ~PLATFORM_DATA_STARTED;
    +			SDHCI_PLATFORM_FINISH_TRANSFER(slot->bus, slot);
    +		} else
    +			sdhci_finish_data(slot);
    +	}
     }
     
     static void
    diff --git a/sys/dev/sdhci/sdhci.h b/sys/dev/sdhci/sdhci.h
    index 31fbe6889f1..5c467786ece 100644
    --- a/sys/dev/sdhci/sdhci.h
    +++ b/sys/dev/sdhci/sdhci.h
    @@ -224,8 +224,9 @@ struct sdhci_slot {
     	device_t	dev;		/* Slot device */
     	u_char		num;		/* Slot number */
     	u_char		opt;		/* Slot options */
    +#define SDHCI_HAVE_DMA			1
    +#define SDHCI_PLATFORM_TRANSFER		2
     	u_char		version;
    -#define SDHCI_HAVE_DMA		1
     	uint32_t	max_clk;	/* Max possible freq */
     	uint32_t	timeout_clk;	/* Timeout freq */
     	bus_dma_tag_t 	dmatag;
    @@ -250,6 +251,7 @@ struct sdhci_slot {
     #define CMD_STARTED		1
     #define STOP_STARTED		2
     #define SDHCI_USE_DMA		4	/* Use DMA for this req. */
    +#define PLATFORM_DATA_STARTED	8	/* Data transfer is handled by platform */
     	struct mtx	mtx;		/* Slot mutex */
     };
     
    @@ -257,6 +259,8 @@ int sdhci_generic_read_ivar(device_t bus, device_t child, int which, uintptr_t *
     int sdhci_generic_write_ivar(device_t bus, device_t child, int which, uintptr_t value);
     int sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num);
     void sdhci_start_slot(struct sdhci_slot *slot);
    +/* performs generic clean-up for platform transfers */
    +void sdhci_finish_data(struct sdhci_slot *slot);
     int sdhci_cleanup_slot(struct sdhci_slot *slot);
     int sdhci_generic_suspend(struct sdhci_slot *slot);
     int sdhci_generic_resume(struct sdhci_slot *slot);
    diff --git a/sys/dev/sdhci/sdhci_if.m b/sys/dev/sdhci/sdhci_if.m
    index b434fd29d94..f0b7567896e 100644
    --- a/sys/dev/sdhci/sdhci_if.m
    +++ b/sys/dev/sdhci/sdhci_if.m
    @@ -131,6 +131,22 @@ METHOD void write_multi_4 {
     	bus_size_t		count;
     }
     
    +METHOD int platform_will_handle {
    +	device_t		brdev;
    +	struct sdhci_slot	*slot;
    +}
    +
    +METHOD void platform_start_transfer {
    +	device_t		brdev;
    +	struct sdhci_slot	*slot;
    +	uint32_t		*intmask;
    +}
    +
    +METHOD void platform_finish_transfer {
    +	device_t		brdev;
    +	struct sdhci_slot	*slot;
    +}
    +
     METHOD uint32_t min_freq {
     	device_t		brdev;
     	struct sdhci_slot	*slot;
    
    From cdafe74e8473fb14a5a58777482a847cc3f5c860 Mon Sep 17 00:00:00 2001
    From: Oleksandr Tymoshenko 
    Date: Thu, 28 Feb 2013 19:48:19 +0000
    Subject: [PATCH 0477/1476] Add driver for BCM2835's DMA engine
    
    This is a version of code submitted by Daisuke Aoyama 
    with some architectural changes.
    ---
     sys/arm/broadcom/bcm2835/bcm2835_dma.c | 727 +++++++++++++++++++++++++
     sys/arm/broadcom/bcm2835/bcm2835_dma.h |  62 +++
     sys/arm/broadcom/bcm2835/files.bcm2835 |   1 +
     3 files changed, 790 insertions(+)
     create mode 100644 sys/arm/broadcom/bcm2835/bcm2835_dma.c
     create mode 100644 sys/arm/broadcom/bcm2835/bcm2835_dma.h
    
    diff --git a/sys/arm/broadcom/bcm2835/bcm2835_dma.c b/sys/arm/broadcom/bcm2835/bcm2835_dma.c
    new file mode 100644
    index 00000000000..5e1c9dc1e2f
    --- /dev/null
    +++ b/sys/arm/broadcom/bcm2835/bcm2835_dma.c
    @@ -0,0 +1,727 @@
    +/*
    + * Copyright (c) 2013 Daisuke Aoyama 
    + * Copyright (c) 2013 Oleksandr Tymoshenko 
    + *
    + * 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 
    +__FBSDID("$FreeBSD$");
    +
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +
    +#include 
    +#include 
    +#include 
    +#include 
    +
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +
    +#include "bcm2835_dma.h"
    +#include "bcm2835_vcbus.h"
    +
    +#define	MAX_REG			9
    +
    +/* private flags */
    +#define	BCM_DMA_CH_USED		0x00000001
    +#define	BCM_DMA_CH_FREE		0x40000000
    +#define	BCM_DMA_CH_UNMAP	0x80000000
    +
    +/* Register Map (4.2.1.2) */
    +#define	BCM_DMA_CS(n)		(0x100*(n) + 0x00)
    +#define		CS_ACTIVE		(1 <<  0)
    +#define		CS_END			(1 <<  1)
    +#define		CS_INT			(1 <<  2)
    +#define		CS_DREQ			(1 <<  3)
    +#define		CS_ISPAUSED		(1 <<  4)
    +#define		CS_ISHELD		(1 <<  5)
    +#define		CS_ISWAIT		(1 <<  6)
    +#define		CS_ERR			(1 <<  8)
    +#define		CS_WAITWRT		(1 << 28)
    +#define		CS_DISDBG		(1 << 29)
    +#define		CS_ABORT		(1 << 30)
    +#define		CS_RESET		(1 << 31)
    +#define	BCM_DMA_CBADDR(n)	(0x100*(n) + 0x04)
    +#define	BCM_DMA_INFO(n)		(0x100*(n) + 0x08)
    +#define		INFO_INT_EN		(1 << 0)
    +#define		INFO_TDMODE		(1 << 1)
    +#define		INFO_WAIT_RESP		(1 << 3)
    +#define		INFO_D_INC		(1 << 4)
    +#define		INFO_D_WIDTH		(1 << 5)
    +#define		INFO_D_DREQ		(1 << 6)
    +#define		INFO_S_INC		(1 << 8)
    +#define		INFO_S_WIDTH		(1 << 9)
    +#define		INFO_S_DREQ		(1 << 10)
    +#define		INFO_WAITS_SHIFT	(21)
    +#define		INFO_PERMAP_SHIFT	(16)
    +#define		INFO_PERMAP_MASK	(0x1f << INFO_PERMAP_SHIFT)
    +
    +#define	BCM_DMA_SRC(n)		(0x100*(n) + 0x0C)
    +#define	BCM_DMA_DST(n)		(0x100*(n) + 0x10)
    +#define	BCM_DMA_LEN(n)		(0x100*(n) + 0x14)
    +#define	BCM_DMA_STRIDE(n)	(0x100*(n) + 0x18)
    +#define	BCM_DMA_CBNEXT(n)	(0x100*(n) + 0x1C)
    +#define	BCM_DMA_DEBUG(n)	(0x100*(n) + 0x20)
    +#define		DEBUG_ERROR_MASK	(7)
    +
    +#define	BCM_DMA_INT_STATUS	0xfe0
    +#define	BCM_DMA_ENABLE		0xff0
    +
    +/* relative offset from BCM_VC_DMA0_BASE (p.39) */
    +#define	BCM_DMA_CH(n)		(0x100*(n))
    +
    +/* DMA Control Block - 256bit aligned (p.40) */
    +struct bcm_dma_cb {
    +	uint32_t info;		/* Transfer Information */
    +	uint32_t src;		/* Source Address */
    +	uint32_t dst;		/* Destination Address */
    +	uint32_t len;		/* Transfer Length */
    +	uint32_t stride;	/* 2D Mode Stride */
    +	uint32_t next;		/* Next Control Block Address */
    +	uint32_t rsvd1;		/* Reserved */
    +	uint32_t rsvd2;		/* Reserved */
    +};
    +
    +#ifdef DEBUG
    +static void bcm_dma_cb_dump(struct bcm_dma_cb *cb);
    +static void bcm_dma_reg_dump(int ch);
    +#endif
    +
    +/* DMA channel private info */
    +struct bcm_dma_ch {
    +	int			ch;
    +	uint32_t		flags;
    +	struct bcm_dma_cb *	cb;
    +	uint32_t		vc_cb;
    +	bus_dmamap_t		dma_map;
    +	void 			(*intr_func)(int, void *);
    +	void *			intr_arg;
    +};
    +
    +struct bcm_dma_softc {
    +	device_t		sc_dev;
    +	struct mtx		sc_mtx;
    +	struct resource *	sc_mem;
    +	struct resource *	sc_irq[BCM_DMA_CH_MAX];
    +	void *			sc_intrhand[BCM_DMA_CH_MAX];
    +	struct bcm_dma_ch	sc_dma_ch[BCM_DMA_CH_MAX];
    +	bus_dma_tag_t		sc_dma_tag;
    +};
    +
    +static struct bcm_dma_softc *bcm_dma_sc = NULL;
    +
    +static void
    +bcm_dmamap_cb(void *arg, bus_dma_segment_t *segs,
    +	int nseg, int err)
    +{
    +        bus_addr_t *addr;
    +
    +        if (err)
    +                return;
    +
    +        addr = (bus_addr_t*)arg;
    +        *addr = PHYS_TO_VCBUS(segs[0].ds_addr);
    +}
    +
    +static void
    +bcm_dma_reset(device_t dev, int ch)
    +{
    +	struct bcm_dma_softc *sc = device_get_softc(dev);
    +	struct bcm_dma_cb *cb;
    +	uint32_t cs;
    +	int count;
    +
    +	if (ch < 0 || ch >= BCM_DMA_CH_MAX)
    +		return;
    +
    +	cs = bus_read_4(sc->sc_mem, BCM_DMA_CS(ch));
    +
    +	if (cs & CS_ACTIVE) {
    +		/* pause current task */
    +		bus_write_4(sc->sc_mem, BCM_DMA_CS(ch), 0);
    +
    +		count = 1000;
    +		do {
    +			cs = bus_read_4(sc->sc_mem, BCM_DMA_CS(ch));
    +		} while (!(cs & CS_ISPAUSED) && (count-- > 0));
    +
    +		if (!(cs & CS_ISPAUSED)) {
    +			device_printf(dev,
    +			    "Can't abort DMA transfer at channel %d\n", ch);
    +		}
    +
    +		bus_write_4(sc->sc_mem, BCM_DMA_CBNEXT(ch), 0);
    +
    +		/* Complete everything, clear interrupt */
    +		bus_write_4(sc->sc_mem, BCM_DMA_CS(ch),
    +		    CS_ABORT | CS_INT | CS_END| CS_ACTIVE);
    +	}
    +
    +	/* clear control blocks */
    +	bus_write_4(sc->sc_mem, BCM_DMA_CBADDR(ch), 0);
    +	bus_write_4(sc->sc_mem, BCM_DMA_CBNEXT(ch), 0);
    +
    +	/* Reset control block */
    +	cb = sc->sc_dma_ch[ch].cb;
    +	bzero(cb, sizeof(cb));
    +}
    +
    +static int
    +bcm_dma_init(device_t dev)
    +{
    +	struct bcm_dma_softc *sc = device_get_softc(dev);
    +	uint32_t mask;
    +	struct bcm_dma_ch *ch;
    +	void *cb_virt;
    +	vm_paddr_t cb_phys;
    +	int err;
    +	int i;
    +
    +	/* disable and clear interrupt status */
    +	bus_write_4(sc->sc_mem, BCM_DMA_ENABLE, 0);
    +	bus_write_4(sc->sc_mem, BCM_DMA_INT_STATUS, 0);
    +
    +	/* Allocate DMA chunks control blocks */
    +	/* p.40 of spec - control block should be 32-bit aligned */
    +	err = bus_dma_tag_create(bus_get_dma_tag(dev),
    +	    1, 0, BUS_SPACE_MAXADDR_32BIT,
    +	    BUS_SPACE_MAXADDR, NULL, NULL,
    +	    sizeof(struct bcm_dma_cb), 1,
    +	    sizeof(struct bcm_dma_cb),
    +	    BUS_DMA_ALLOCNOW, NULL, NULL,
    +	    &sc->sc_dma_tag);
    +
    +	if (err) {
    +		device_printf(dev, "failed allocate DMA tag");
    +		return (err);
    +	}
    +
    +	/* setup initial settings */
    +	for (i = 0; i < BCM_DMA_CH_MAX; i++) {
    +		ch = &sc->sc_dma_ch[i];
    +
    +		err = bus_dmamem_alloc(sc->sc_dma_tag, &cb_virt,
    +		    BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO,
    +		    &ch->dma_map);
    +		if (err) {
    +			device_printf(dev, "cannot allocate DMA memory\n");
    +			break;
    +		}
    +
    +		/* 
    +		 * Least alignment for busdma-allocated stuff is cache 
    +		 * line size, so just make sure nothing stupid happend
    +		 * and we got properly aligned address
    +		 */
    +		if ((uintptr_t)cb_virt & 0x1f) {
    +			device_printf(dev,
    +			    "DMA address is not 32-bytes aligned: %p\n",
    +			    (void*)cb_virt);
    +			break;
    +		}
    +
    +		err = bus_dmamap_load(sc->sc_dma_tag, ch->dma_map, cb_virt,
    +		    sizeof(struct bcm_dma_cb), bcm_dmamap_cb, &cb_phys,
    +		    BUS_DMA_WAITOK);
    +		if (err) {
    +			device_printf(dev, "cannot load DMA memory\n");
    +			break;
    +		}
    +
    +		bzero(ch, sizeof(struct bcm_dma_ch));
    +		ch->ch = i;
    +		ch->cb = cb_virt;
    +		ch->vc_cb = cb_phys;
    +		ch->intr_func = NULL;
    +		ch->intr_arg = NULL;
    +		ch->flags = BCM_DMA_CH_UNMAP;
    +
    +		ch->cb->info = INFO_WAIT_RESP;
    +
    +		/* reset DMA engine */
    +		bcm_dma_reset(dev, i);
    +	}
    +
    +	/* now use DMA2/DMA3 only */
    +	sc->sc_dma_ch[2].flags = BCM_DMA_CH_FREE;
    +	sc->sc_dma_ch[3].flags = BCM_DMA_CH_FREE;
    +
    +	/* enable DMAs */
    +	mask = 0;
    +
    +	for (i = 0; i < BCM_DMA_CH_MAX; i++)
    +		if (sc->sc_dma_ch[i].flags & BCM_DMA_CH_FREE)
    +			mask |= (1 << i);
    +
    +	bus_write_4(sc->sc_mem, BCM_DMA_ENABLE, mask);
    +
    +	return (0);
    +}
    +
    +/*
    + * Allocate DMA channel for further use, returns channel # or
    + *     BCM_DMA_CH_INVALID
    + */
    +int
    +bcm_dma_allocate(int req_ch)
    +{
    +	struct bcm_dma_softc *sc = bcm_dma_sc;
    +	int ch = BCM_DMA_CH_INVALID;
    +	int i;
    +
    +	if (req_ch >= BCM_DMA_CH_MAX)
    +		return (BCM_DMA_CH_INVALID);
    +
    +	/* Auto(req_ch < 0) or CH specified */
    +	mtx_lock(&sc->sc_mtx);
    +
    +	if (req_ch < 0) {
    +		for (i = 0; i < BCM_DMA_CH_MAX; i++) {
    +			if (sc->sc_dma_ch[i].flags & BCM_DMA_CH_FREE) {
    +				ch = i;
    +				sc->sc_dma_ch[ch].flags &= ~BCM_DMA_CH_FREE;
    +				sc->sc_dma_ch[ch].flags |= BCM_DMA_CH_USED;
    +				break;
    +			}
    +		}
    +	}
    +	else {
    +		if (sc->sc_dma_ch[req_ch].flags & BCM_DMA_CH_FREE) {
    +			ch = req_ch;
    +			sc->sc_dma_ch[ch].flags &= ~BCM_DMA_CH_FREE;
    +			sc->sc_dma_ch[ch].flags |= BCM_DMA_CH_USED;
    +		}
    +	}
    +
    +	mtx_unlock(&sc->sc_mtx);
    +	return (ch);
    +}
    +
    +/*
    + * Frees allocated channel. Returns 0 on success, -1 otherwise
    + */
    +int
    +bcm_dma_free(int ch)
    +{
    +	struct bcm_dma_softc *sc = bcm_dma_sc;
    +
    +	if (ch < 0 || ch >= BCM_DMA_CH_MAX)
    +		return (-1);
    +
    +	mtx_lock(&sc->sc_mtx);
    +	if (sc->sc_dma_ch[ch].flags & BCM_DMA_CH_USED) {
    +		sc->sc_dma_ch[ch].flags |= BCM_DMA_CH_FREE;
    +		sc->sc_dma_ch[ch].flags &= ~BCM_DMA_CH_USED;
    +		sc->sc_dma_ch[ch].intr_func = NULL;
    +		sc->sc_dma_ch[ch].intr_arg = NULL;
    +
    +		/* reset DMA engine */
    +		bcm_dma_reset(sc->sc_dev, ch);
    +	}
    +
    +	mtx_unlock(&sc->sc_mtx);
    +	return (0);
    +}
    +
    +/*
    + * Assign handler function for channel interrupt
    + * Returns 0 on success, -1 otherwise
    + */
    +int
    +bcm_dma_setup_intr(int ch, void (*func)(int, void *), void *arg)
    +{
    +	struct bcm_dma_softc *sc = bcm_dma_sc;
    +	struct bcm_dma_cb *cb;
    +
    +	if (ch < 0 || ch >= BCM_DMA_CH_MAX)
    +		return (-1);
    +
    +	if (!(sc->sc_dma_ch[ch].flags & BCM_DMA_CH_USED))
    +		return (-1);
    +
    +	sc->sc_dma_ch[ch].intr_func = func;
    +	sc->sc_dma_ch[ch].intr_arg = arg;
    +	cb = sc->sc_dma_ch[ch].cb;
    +	cb->info |= INFO_INT_EN;
    +
    +	return (0);
    +}
    +
    +/*
    + * Setup DMA source parameters
    + *     ch - channel number
    + *     dreq - hardware DREQ # or BCM_DMA_DREQ_NONE if
    + *         source is physical memory
    + *     inc_addr - BCM_DMA_INC_ADDR if source address
    + *         should be increased after each access or 
    + *         BCM_DMA_SAME_ADDR if address should remain 
    + *         the same
    + *     width - size of read operation, BCM_DMA_32BIT
    + *         for 32bit bursts, BCM_DMA_128BIT for 128 bits
    + *	  
    + * Returns 0 on success, -1 otherwise
    + */
    +int
    +bcm_dma_setup_src(int ch, int dreq, int inc_addr, int width)
    +{
    +	struct bcm_dma_softc *sc = bcm_dma_sc;
    +	uint32_t info;
    +
    +	if (ch < 0 || ch >= BCM_DMA_CH_MAX)
    +		return (-1);
    +
    +	if (!(sc->sc_dma_ch[ch].flags & BCM_DMA_CH_USED))
    +		return (-1);
    +
    +	info = sc->sc_dma_ch[ch].cb->info;
    +	info &= ~INFO_PERMAP_MASK;
    +	info |= (dreq << INFO_PERMAP_SHIFT) & INFO_PERMAP_MASK;
    +
    +	if (dreq)
    +		info |= INFO_S_DREQ;
    +	else
    +		info &= ~INFO_S_DREQ;
    +
    +	if (width == BCM_DMA_128BIT)
    +		info |= INFO_S_WIDTH;
    +	else
    +		info &= ~INFO_S_WIDTH;
    +
    +	if (inc_addr == BCM_DMA_INC_ADDR)
    +		info |= INFO_S_INC;
    +	else
    +		info &= ~INFO_S_INC;
    +
    +	sc->sc_dma_ch[ch].cb->info = info;
    +
    +	return (0);
    +}
    +
    +/*
    + * Setup DMA destination parameters
    + *     ch - channel number
    + *     dreq - hardware DREQ # or BCM_DMA_DREQ_NONE if
    + *         destination is physical memory
    + *     inc_addr - BCM_DMA_INC_ADDR if source address
    + *         should be increased after each access or 
    + *         BCM_DMA_SAME_ADDR if address should remain 
    + *         the same
    + *     width - size of write operation, BCM_DMA_32BIT
    + *         for 32bit bursts, BCM_DMA_128BIT for 128 bits
    + *	  
    + * Returns 0 on success, -1 otherwise
    + */
    +int
    +bcm_dma_setup_dst(int ch, int dreq, int inc_addr, int width)
    +{
    +	struct bcm_dma_softc *sc = bcm_dma_sc;
    +	uint32_t info;
    +
    +	if (ch < 0 || ch >= BCM_DMA_CH_MAX)
    +		return (-1);
    +
    +	if (!(sc->sc_dma_ch[ch].flags & BCM_DMA_CH_USED))
    +		return (-1);
    +
    +	info = sc->sc_dma_ch[ch].cb->info;
    +	info &= ~INFO_PERMAP_MASK;
    +	info |= (dreq << INFO_PERMAP_SHIFT) & INFO_PERMAP_MASK;
    +
    +	if (dreq)
    +		info |= INFO_D_DREQ;
    +	else
    +		info &= ~INFO_D_DREQ;
    +
    +	if (width == BCM_DMA_128BIT)
    +		info |= INFO_D_WIDTH;
    +	else
    +		info &= ~INFO_D_WIDTH;
    +
    +	if (inc_addr == BCM_DMA_INC_ADDR)
    +		info |= INFO_D_INC;
    +	else
    +		info &= ~INFO_D_INC;
    +
    +	sc->sc_dma_ch[ch].cb->info = info;
    +
    +	return (0);
    +}
    +
    +#ifdef DEBUG
    +void
    +bcm_dma_cb_dump(struct bcm_dma_cb *cb)
    +{
    +
    +	printf("DMA CB ");
    +	printf("INFO: %8.8x ", cb->info);
    +	printf("SRC: %8.8x ", cb->src);
    +	printf("DST: %8.8x ", cb->dst);
    +	printf("LEN: %8.8x ", cb->len);
    +	printf("\n");
    +	printf("STRIDE: %8.8x ", cb->stride);
    +	printf("NEXT: %8.8x ", cb->next);
    +	printf("RSVD1: %8.8x ", cb->rsvd1);
    +	printf("RSVD2: %8.8x ", cb->rsvd2);
    +	printf("\n");
    +}
    +
    +void
    +bcm_dma_reg_dump(int ch)
    +{
    +	struct bcm_dma_softc *sc = bcm_dma_sc;
    +	int i;
    +	uint32_t reg;
    +
    +	if (ch < 0 || ch >= BCM_DMA_CH_MAX)
    +		return;
    +
    +	printf("DMA%d: ", ch);
    +	for (i = 0; i < MAX_REG; i++) {
    +		reg = bus_read_4(sc->sc_mem, BCM_DMA_CH(ch) + i*4);
    +		printf("%8.8x ", reg);
    +	}
    +	printf("\n");
    +}
    +#endif
    +
    +/*
    + * Start DMA transaction
    + *     ch - channel number
    + *     src, dst - source and destination address in
    + *         ARM physical memory address space. 
    + *     len - amount of bytes to be transfered
    + *	  
    + * Returns 0 on success, -1 otherwise
    + */
    +int
    +bcm_dma_start(int ch, vm_paddr_t src, vm_paddr_t dst, int len)
    +{
    +	struct bcm_dma_softc *sc = bcm_dma_sc;
    +	struct bcm_dma_cb *cb;
    +
    +	if (ch < 0 || ch >= BCM_DMA_CH_MAX)
    +		return (-1);
    +
    +	if (!(sc->sc_dma_ch[ch].flags & BCM_DMA_CH_USED))
    +		return (-1);
    +
    +	cb = sc->sc_dma_ch[ch].cb;
    +	if (BCM2835_ARM_IS_IO(src))
    +		cb->src = IO_TO_VCBUS(src);
    +	else
    +		cb->src = PHYS_TO_VCBUS(src);
    +	if (BCM2835_ARM_IS_IO(dst))
    +		cb->dst = IO_TO_VCBUS(dst);
    +	else
    +		cb->dst = PHYS_TO_VCBUS(dst);
    +	cb->len = len;
    +
    +	bus_dmamap_sync(sc->sc_dma_tag,
    +	    sc->sc_dma_ch[ch].dma_map, BUS_DMASYNC_PREWRITE);
    +
    +	bus_write_4(sc->sc_mem, BCM_DMA_CBADDR(ch),
    +	    sc->sc_dma_ch[ch].vc_cb);
    +	bus_write_4(sc->sc_mem, BCM_DMA_CS(ch), CS_ACTIVE);
    +
    +#ifdef DEBUG
    +	bcm_dma_cb_dump(sc->sc_dma_ch[ch].cb);
    +	bcm_dma_reg_dump(ch);
    +#endif
    +
    +	return (0);
    +}
    +
    +/*
    + * Get length requested for DMA transaction
    + *     ch - channel number
    + *	  
    + * Returns size of transaction, 0 if channel is invalid
    + */
    +uint32_t
    +bcm_dma_length(int ch)
    +{
    +	struct bcm_dma_softc *sc = bcm_dma_sc;
    +	struct bcm_dma_cb *cb;
    +
    +	if (ch < 0 || ch >= BCM_DMA_CH_MAX)
    +		return (0);
    +
    +	if (!(sc->sc_dma_ch[ch].flags & BCM_DMA_CH_USED))
    +		return (0);
    +
    +	cb = sc->sc_dma_ch[ch].cb;
    +
    +	return (cb->len);
    +}
    +
    +static void
    +bcm_dma_intr(void *arg)
    +{
    +	struct bcm_dma_softc *sc = bcm_dma_sc;
    +	struct bcm_dma_ch *ch = (struct bcm_dma_ch *)arg;
    +	uint32_t cs, debug;
    +
    +	/* my interrupt? */
    +	cs = bus_read_4(sc->sc_mem, BCM_DMA_CS(ch->ch));
    +
    +	if (!(cs & (CS_INT | CS_ERR)))
    +		return;
    +
    +	/* running? */
    +	if (!(ch->flags & BCM_DMA_CH_USED)) {
    +		device_printf(sc->sc_dev,
    +		    "unused DMA intr CH=%d, CS=%x\n", ch->ch, cs);
    +		return;
    +	}
    +
    +	if (cs & CS_ERR) {
    +		debug = bus_read_4(sc->sc_mem, BCM_DMA_DEBUG(ch->ch));
    +		device_printf(sc->sc_dev, "DMA error %d on CH%d\n",
    +			debug & DEBUG_ERROR_MASK, ch->ch);
    +		bus_write_4(sc->sc_mem, BCM_DMA_DEBUG(ch->ch), 
    +		    debug & DEBUG_ERROR_MASK);
    +	}
    +
    +	if (cs & CS_INT) {
    +		/* acknowledge interrupt */
    +		bus_write_4(sc->sc_mem, BCM_DMA_CS(ch->ch), 
    +		    CS_INT | CS_END);
    +
    +		/* Prepare for possible access to len field */
    +		bus_dmamap_sync(sc->sc_dma_tag, ch->dma_map,
    +		    BUS_DMASYNC_POSTWRITE);
    +
    +		/* save callback function and argument */
    +		if (ch->intr_func)
    +			ch->intr_func(ch->ch, ch->intr_arg);
    +	}
    +}
    +
    +static int
    +bcm_dma_probe(device_t dev)
    +{
    +
    +	if (!ofw_bus_is_compatible(dev, "broadcom,bcm2835-dma"))
    +		return (ENXIO);
    +
    +	device_set_desc(dev, "BCM2835 DMA Controller");
    +	return (BUS_PROBE_DEFAULT);
    +}
    +
    +static int
    +bcm_dma_attach(device_t dev)
    +{
    +	struct bcm_dma_softc *sc = device_get_softc(dev);
    +	int rid, err = 0;
    +	int i;
    +
    +	sc->sc_dev = dev;
    +
    +	if (bcm_dma_sc)
    +		return (ENXIO);
    +
    +	for (i = 0; i < BCM_DMA_CH_MAX; i++) {
    +		sc->sc_irq[i] = NULL;
    +		sc->sc_intrhand[i] = NULL;
    +	}
    +
    +	/* DMA0 - DMA14 */
    +	rid = 0;
    +	sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
    +	if (sc->sc_mem == NULL) {
    +		device_printf(dev, "could not allocate memory resource\n");
    +		return (ENXIO);
    +	}
    +
    +	/* IRQ DMA0 - DMA11 XXX NOT USE DMA12(spurious?) */
    +	for (rid = 0; rid < BCM_DMA_CH_MAX; rid++) {
    +		sc->sc_irq[rid] = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
    +						       RF_ACTIVE);
    +		if (sc->sc_irq[rid] == NULL) {
    +			device_printf(dev, "cannot allocate interrupt\n");
    +			err = ENXIO;
    +			goto fail;
    +		}
    +		if (bus_setup_intr(dev, sc->sc_irq[rid], INTR_TYPE_MISC | INTR_MPSAFE,
    +				   NULL, bcm_dma_intr, &sc->sc_dma_ch[rid],
    +				   &sc->sc_intrhand[rid])) {
    +			device_printf(dev, "cannot setup interrupt handler\n");
    +			err = ENXIO;
    +			goto fail;
    +		}
    +	}
    +
    +	mtx_init(&sc->sc_mtx, "bcmdma", "bcmdma", MTX_DEF);
    +	bcm_dma_sc = sc;
    +
    +	err = bcm_dma_init(dev);
    +	if (err)
    +		goto fail;
    +
    +	return (err);
    +
    +fail:
    +	if (sc->sc_mem)
    +		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem);
    +
    +	for (i = 0; i < BCM_DMA_CH_MAX; i++) {
    +		if (sc->sc_intrhand[i])
    +			bus_teardown_intr(dev, sc->sc_irq[i], sc->sc_intrhand[i]);
    +		if (sc->sc_irq[i])
    +			bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq[i]);
    +	}
    +
    +	return (err);
    +}
    +
    +static device_method_t bcm_dma_methods[] = {
    +	DEVMETHOD(device_probe,		bcm_dma_probe),
    +	DEVMETHOD(device_attach,	bcm_dma_attach),
    +	{ 0, 0 }
    +};
    +
    +static driver_t bcm_dma_driver = {
    +	"bcm_dma",
    +	bcm_dma_methods,
    +	sizeof(struct bcm_dma_softc),
    +};
    +
    +static devclass_t bcm_dma_devclass;
    +
    +DRIVER_MODULE(bcm_dma, simplebus, bcm_dma_driver, bcm_dma_devclass, 0, 0);
    +MODULE_VERSION(bcm_dma, 1);
    diff --git a/sys/arm/broadcom/bcm2835/bcm2835_dma.h b/sys/arm/broadcom/bcm2835/bcm2835_dma.h
    new file mode 100644
    index 00000000000..785cf2cf538
    --- /dev/null
    +++ b/sys/arm/broadcom/bcm2835/bcm2835_dma.h
    @@ -0,0 +1,62 @@
    +/*
    + * Copyright (c) 2013 Daisuke Aoyama 
    + * Copyright (c) 2013 Oleksandr Tymoshenko 
    + *
    + * 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	_BCM2835_DMA_H_
    +#define	_BCM2835_DMA_H_
    +
    +#define	BCM_DMA_BLOCK_SIZE	512
    +
    +/* DMA0-DMA15 but DMA15 is special */
    +#define	BCM_DMA_CH_MAX		12
    +
    +/* request CH for any nubmer */
    +#define	BCM_DMA_CH_INVALID	(-1)
    +#define	BCM_DMA_CH_ANY		(-1)
    +#define	BCM_DMA_CH_FAST1	(2)
    +#define	BCM_DMA_CH_FAST2	(3)
    +
    +/* Peripheral DREQ Signals (4.2.1.3) */
    +#define	BCM_DMA_DREQ_NONE	0
    +#define	BCM_DMA_DREQ_EMMC	11
    +#define	BCM_DMA_DREQ_SDHOST	13
    +
    +#define	BCM_DMA_SAME_ADDR	0
    +#define	BCM_DMA_INC_ADDR	1
    +
    +#define	BCM_DMA_32BIT		0
    +#define	BCM_DMA_128BIT		1
    +
    +int bcm_dma_allocate(int req_ch);
    +int bcm_dma_free(int ch);
    +int bcm_dma_setup_intr(int ch, void (*func)(int, void *), void *arg);
    +int bcm_dma_setup_src(int ch, int dreq, int inc_addr, int width);
    +int bcm_dma_setup_dst(int ch, int dreq, int inc_addr, int width);
    +int bcm_dma_start(int ch, vm_paddr_t src, vm_paddr_t dst, int len);
    +uint32_t bcm_dma_length(int ch);
    +
    +#endif	/* _BCM2835_DMA_H_ */
    diff --git a/sys/arm/broadcom/bcm2835/files.bcm2835 b/sys/arm/broadcom/bcm2835/files.bcm2835
    index 9885155d067..aa1af40ee5a 100644
    --- a/sys/arm/broadcom/bcm2835/files.bcm2835
    +++ b/sys/arm/broadcom/bcm2835/files.bcm2835
    @@ -1,5 +1,6 @@
     # $FreeBSD$
     
    +arm/broadcom/bcm2835/bcm2835_dma.c		standard
     arm/broadcom/bcm2835/bcm2835_fb.c		optional sc
     arm/broadcom/bcm2835/bcm2835_gpio.c		optional gpio
     arm/broadcom/bcm2835/bcm2835_intr.c		standard
    
    From adc99a8aa627f04abafd78ca21d7c8a63e6cbb54 Mon Sep 17 00:00:00 2001
    From: Oleksandr Tymoshenko 
    Date: Thu, 28 Feb 2013 19:51:30 +0000
    Subject: [PATCH 0478/1476] Add platform DMA support to SDHCI driver for
     BCM2835
    
    Submitted by:	Daisuke Aoyama 
    Reviewed by:	ian@
    ---
     sys/arm/broadcom/bcm2835/bcm2835_sdhci.c | 304 ++++++++++++++++++++++-
     1 file changed, 300 insertions(+), 4 deletions(-)
    
    diff --git a/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c b/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c
    index cfba2cd43f1..35129549e3f 100644
    --- a/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c
    +++ b/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c
    @@ -67,8 +67,13 @@ __FBSDID("$FreeBSD$");
     #include 
     #include "sdhci_if.h"
     
    +#include "bcm2835_dma.h"
    +#include "bcm2835_vcbus.h"
    +
     #define	BCM2835_DEFAULT_SDHCI_FREQ	50
     
    +#define	BCM_SDHCI_BUFFER_SIZE		512
    +
     #define	DEBUG
     
     #ifdef DEBUG
    @@ -85,9 +90,11 @@ __FBSDID("$FreeBSD$");
      */
     static int bcm2835_sdhci_min_freq = 400000;
     static int bcm2835_sdhci_hs = 1;
    +static int bcm2835_sdhci_pio_mode = 0;
     
     TUNABLE_INT("hw.bcm2835.sdhci.min_freq", &bcm2835_sdhci_min_freq);
     TUNABLE_INT("hw.bcm2835.sdhci.hs", &bcm2835_sdhci_hs);
    +TUNABLE_INT("hw.bcm2835.sdhci.pio_mode", &bcm2835_sdhci_pio_mode);
     
     struct bcm_sdhci_dmamap_arg {
     	bus_addr_t		sc_dma_busaddr;
    @@ -111,23 +118,41 @@ struct bcm_sdhci_softc {
     	int			sc_xfer_done;
     	int			sc_bus_busy;
     	struct sdhci_slot	sc_slot;
    +	int			sc_dma_inuse;
    +	int			sc_dma_ch;
    +	bus_dma_tag_t		sc_dma_tag;
    +	bus_dmamap_t		sc_dma_map;
    +	void			*sc_dma_buffer;
    +	vm_paddr_t		sc_dma_buffer_phys;
    +	vm_paddr_t		sc_sdhci_buffer_phys;;
     };
     
    -#define	SD_MAX_BLOCKSIZE	1024
    -/* XXX */
    -
     static int bcm_sdhci_probe(device_t);
     static int bcm_sdhci_attach(device_t);
     static int bcm_sdhci_detach(device_t);
     static void bcm_sdhci_intr(void *);
     
     static int bcm_sdhci_get_ro(device_t, device_t);
    +static void bcm_sdhci_dma_intr(int ch, void *arg);
     
     #define	bcm_sdhci_lock(_sc)						\
         mtx_lock(&_sc->sc_mtx);
     #define	bcm_sdhci_unlock(_sc)						\
         mtx_unlock(&_sc->sc_mtx);
     
    +static void
    +bcm_dmamap_cb(void *arg, bus_dma_segment_t *segs,
    +	int nseg, int err)
    +{
    +        bus_addr_t *addr;
    +
    +        if (err)
    +                return;
    +
    +        addr = (bus_addr_t*)arg;
    +        *addr = segs[0].ds_addr;
    +}
    +
     static int
     bcm_sdhci_probe(device_t dev)
     {
    @@ -146,9 +171,13 @@ bcm_sdhci_attach(device_t dev)
     	phandle_t node;
     	pcell_t cell;
     	int default_freq;
    +	void *buffer;
    +	vm_paddr_t buffer_phys;
    +	void *va;
     
     	sc->sc_dev = dev;
     	sc->sc_req = NULL;
    +	err = 0;
     
     	default_freq = BCM2835_DEFAULT_SDHCI_FREQ;
     	node = ofw_bus_get_node(sc->sc_dev);
    @@ -191,6 +220,9 @@ bcm_sdhci_attach(device_t dev)
     		goto fail;
     	}
     
    +	if (!bcm2835_sdhci_pio_mode)
    +		sc->sc_slot.opt = SDHCI_PLATFORM_TRANSFER;
    +
     	sc->sc_slot.caps = SDHCI_CAN_VDD_330 | SDHCI_CAN_VDD_180;
     	if (bcm2835_sdhci_hs)
     		sc->sc_slot.caps |= SDHCI_CAN_DO_HISPD;
    @@ -201,6 +233,61 @@ bcm_sdhci_attach(device_t dev)
      
     	sdhci_init_slot(dev, &sc->sc_slot, 0);
     
    +	sc->sc_dma_ch = bcm_dma_allocate(BCM_DMA_CH_FAST1);
    +	if (sc->sc_dma_ch == BCM_DMA_CH_INVALID)
    +		sc->sc_dma_ch = bcm_dma_allocate(BCM_DMA_CH_FAST2);
    +	if (sc->sc_dma_ch == BCM_DMA_CH_INVALID)
    +		sc->sc_dma_ch = bcm_dma_allocate(BCM_DMA_CH_ANY);
    +	if (sc->sc_dma_ch == BCM_DMA_CH_INVALID)
    +		goto fail;
    +
    +	bcm_dma_setup_intr(sc->sc_dma_ch, bcm_sdhci_dma_intr, sc);
    +
    +	/* Allocate DMA buffers */
    +	err = bus_dma_tag_create(bus_get_dma_tag(dev),
    +	    1, 0, BUS_SPACE_MAXADDR_32BIT,
    +	    BUS_SPACE_MAXADDR, NULL, NULL,
    +	    BCM_SDHCI_BUFFER_SIZE, 1, BCM_SDHCI_BUFFER_SIZE,
    +	    BUS_DMA_ALLOCNOW, NULL, NULL,
    +	    &sc->sc_dma_tag);
    +
    +	if (err) {
    +		device_printf(dev, "failed allocate DMA tag");
    +		goto fail;
    +	}
    +
    +	err = bus_dmamem_alloc(sc->sc_dma_tag, &buffer,
    +	    BUS_DMA_WAITOK | BUS_DMA_COHERENT| BUS_DMA_ZERO,
    +	    &sc->sc_dma_map);
    +
    +	if (err) {
    +		device_printf(dev, "cannot allocate DMA memory\n");
    +		goto fail;
    +	}
    +
    +	err = bus_dmamap_load(sc->sc_dma_tag, sc->sc_dma_map, buffer,
    +	    BCM_SDHCI_BUFFER_SIZE, bcm_dmamap_cb, &buffer_phys,
    +	    BUS_DMA_WAITOK);
    +	if (err) {
    +		device_printf(dev, "cannot load DMA memory\n");
    +		goto fail;
    +	}
    +
    +	/* 
    +	 * Sanity check: two least bits of address should be zero
    +	 */
    +	if ((uintptr_t)buffer & 3) {
    +		device_printf(dev,
    +		    "DMA address is not word-aligned\n");
    +		goto fail;
    +	}
    +
    +	sc->sc_dma_buffer = buffer;
    +	sc->sc_dma_buffer_phys = buffer_phys;
    +	va = (void*)rman_get_start(sc->sc_mem_res);
    +	sc->sc_sdhci_buffer_phys =
    +	    pmap_kextract((vm_offset_t)va) + SDHCI_BUFFER;
    +
     	bus_generic_probe(dev);
     	bus_generic_attach(dev);
     
    @@ -354,6 +441,211 @@ bcm_sdhci_min_freq(device_t dev, struct sdhci_slot *slot)
     	return bcm2835_sdhci_min_freq;
     }
     
    +static void
    +bcm_sdhci_dma_intr(int ch, void *arg)
    +{
    +	struct bcm_sdhci_softc *sc = (struct bcm_sdhci_softc *)arg;
    +	struct sdhci_slot *slot = &sc->sc_slot;
    +	uint32_t reg, mask;
    +	void *buffer;
    +	size_t len;
    +	int left;
    +
    +	mtx_lock(&slot->mtx);
    +
    +	/* copy DMA buffer to VA if READ */
    +	len = bcm_dma_length(sc->sc_dma_ch);
    +	if (slot->curcmd->data->flags & MMC_DATA_READ) {
    +		bus_dmamap_sync(sc->sc_dma_tag, sc->sc_dma_map,
    +		    BUS_DMASYNC_POSTREAD);
    +
    +		mask = SDHCI_INT_DATA_AVAIL;
    +		/* all dma data in single or contiguous page */
    +		buffer = (uint8_t*)(slot->curcmd->data->data) + slot->offset;
    +		memcpy(buffer, sc->sc_dma_buffer, len);
    +	} else {
    +		bus_dmamap_sync(sc->sc_dma_tag, sc->sc_dma_map,
    +		    BUS_DMASYNC_POSTWRITE);
    +		mask = SDHCI_INT_SPACE_AVAIL;
    +	}
    +
    +	slot->offset += len;
    +	sc->sc_dma_inuse = 0;
    +
    +	left = min(BCM_SDHCI_BUFFER_SIZE,
    +	    slot->curcmd->data->len - slot->offset);
    +
    +	/* DATA END? */
    +	reg = bcm_sdhci_read_4(slot->bus, slot, SDHCI_INT_STATUS);
    +
    +	if (reg & SDHCI_INT_DATA_END) {
    +		/* ACK for all outstanding interrupts */
    +		bcm_sdhci_write_4(slot->bus, slot, SDHCI_INT_STATUS, reg);
    +
    +		/* enable INT */
    +		slot->intmask |= SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL
    +		    | SDHCI_INT_DATA_END;
    +		bcm_sdhci_write_4(slot->bus, slot, SDHCI_SIGNAL_ENABLE,
    +		    slot->intmask);
    +
    +		/* finish this data */
    +		sdhci_finish_data(slot);
    +	} 
    +	else {
    +		/* already available? */
    +		if (reg & mask) {
    +			sc->sc_dma_inuse = 1;
    +
    +			/* ACK for DATA_AVAIL or SPACE_AVAIL */
    +			bcm_sdhci_write_4(slot->bus, slot,
    +			    SDHCI_INT_STATUS, mask);
    +
    +			/* continue next DMA transfer */
    +			if (slot->curcmd->data->flags & MMC_DATA_READ) {
    +				bus_dmamap_sync(sc->sc_dma_tag, sc->sc_dma_map,
    +				    BUS_DMASYNC_PREREAD);
    +
    +				/* DMA start */
    +				if (bcm_dma_start(sc->sc_dma_ch,
    +				    sc->sc_sdhci_buffer_phys,
    +				    sc->sc_dma_buffer_phys, left) != 0)
    +					device_printf(sc->sc_dev, "failed DMA start\n");
    +			} else {
    +				buffer = (char*)slot->curcmd->data->data + slot->offset;
    +				memcpy(sc->sc_dma_buffer, buffer, left);
    +
    +				bus_dmamap_sync(sc->sc_dma_tag,
    +				    sc->sc_dma_map, BUS_DMASYNC_PREWRITE);
    +
    +				/* DMA start */
    +				if (bcm_dma_start(sc->sc_dma_ch, 
    +				    sc->sc_dma_buffer_phys,
    +				    sc->sc_sdhci_buffer_phys, left) != 0)
    +					device_printf(sc->sc_dev, "failed DMA start\n");
    +			}
    +		} else {
    +			/* wait for next data by INT */
    +
    +			/* enable INT */
    +			slot->intmask |= SDHCI_INT_DATA_AVAIL |
    +			    SDHCI_INT_SPACE_AVAIL | SDHCI_INT_DATA_END;
    +			bcm_sdhci_write_4(slot->bus, slot, SDHCI_SIGNAL_ENABLE,
    +			    slot->intmask);
    +		}
    +	}
    +
    +	mtx_unlock(&slot->mtx);
    +}
    +
    +static void
    +bcm_sdhci_read_dma(struct sdhci_slot *slot)
    +{
    +	struct bcm_sdhci_softc *sc = device_get_softc(slot->bus);
    +	size_t left;
    +
    +	if (sc->sc_dma_inuse) {
    +		device_printf(sc->sc_dev, "DMA in use\n");
    +		return;
    +	}
    +
    +	sc->sc_dma_inuse = 1;
    +
    +	left = min(BCM_SDHCI_BUFFER_SIZE,
    +	    slot->curcmd->data->len - slot->offset);
    +
    +	KASSERT((left & 3) == 0,
    +	    ("%s: len = %d, not word-aligned", __func__, left));
    +
    +	bcm_dma_setup_src(sc->sc_dma_ch, BCM_DMA_DREQ_EMMC,
    +	    BCM_DMA_SAME_ADDR, BCM_DMA_32BIT); 
    +	bcm_dma_setup_dst(sc->sc_dma_ch, BCM_DMA_DREQ_NONE,
    +	    BCM_DMA_INC_ADDR,
    +	    (left & 0xf) ? BCM_DMA_32BIT : BCM_DMA_128BIT);
    +
    +	bus_dmamap_sync(sc->sc_dma_tag, sc->sc_dma_map,
    +	    BUS_DMASYNC_PREREAD);
    +
    +	/* DMA start */
    +	if (bcm_dma_start(sc->sc_dma_ch, sc->sc_sdhci_buffer_phys,
    +	    sc->sc_dma_buffer_phys, left) != 0)
    +		device_printf(sc->sc_dev, "failed DMA start\n");
    +}
    +
    +static void
    +bcm_sdhci_write_dma(struct sdhci_slot *slot)
    +{
    +	struct bcm_sdhci_softc *sc = device_get_softc(slot->bus);
    +	char *buffer;
    +	size_t left;
    +
    +	if (sc->sc_dma_inuse) {
    +		device_printf(sc->sc_dev, "DMA in use\n");
    +		return;
    +	}
    +
    +	sc->sc_dma_inuse = 1;
    +
    +	left = min(BCM_SDHCI_BUFFER_SIZE,
    +	    slot->curcmd->data->len - slot->offset);
    +
    +	KASSERT((left & 3) == 0,
    +	    ("%s: len = %d, not word-aligned", __func__, left));
    +
    +	buffer = (char*)slot->curcmd->data->data + slot->offset;
    +	memcpy(sc->sc_dma_buffer, buffer, left);
    +
    +	bcm_dma_setup_src(sc->sc_dma_ch, BCM_DMA_DREQ_NONE,
    +	    BCM_DMA_INC_ADDR,
    +	    (left & 0xf) ? BCM_DMA_32BIT : BCM_DMA_128BIT);
    +	bcm_dma_setup_dst(sc->sc_dma_ch, BCM_DMA_DREQ_EMMC,
    +	    BCM_DMA_SAME_ADDR, BCM_DMA_32BIT);
    +
    +	bus_dmamap_sync(sc->sc_dma_tag, sc->sc_dma_map,
    +	    BUS_DMASYNC_PREWRITE);
    +
    +	/* DMA start */
    +	if (bcm_dma_start(sc->sc_dma_ch, sc->sc_dma_buffer_phys,
    +	    sc->sc_sdhci_buffer_phys, left) != 0)
    +		device_printf(sc->sc_dev, "failed DMA start\n");
    +}
    +
    +static int
    +bcm_sdhci_will_handle_transfer(device_t dev, struct sdhci_slot *slot)
    +{
    +	size_t left;
    +
    +	/* Do not use DMA for transfers less then block size */
    +	left = min(BCM_DMA_BLOCK_SIZE,
    +	    slot->curcmd->data->len - slot->offset);
    +	if (left < BCM_DMA_BLOCK_SIZE)
    +		return (0);
    +
    +	return (1);
    +}
    +
    +static void
    +bcm_sdhci_start_transfer(device_t dev, struct sdhci_slot *slot,
    +    uint32_t *intmask)
    +{
    +
    +	/* Disable INT */
    +	slot->intmask &= ~(SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | SDHCI_INT_DATA_END);
    +	bcm_sdhci_write_4(dev, slot, SDHCI_SIGNAL_ENABLE, slot->intmask);
    +
    +	/* DMA transfer FIFO 1KB */
    +	if (slot->curcmd->data->flags & MMC_DATA_READ)
    +		bcm_sdhci_read_dma(slot);
    +	else
    +		bcm_sdhci_write_dma(slot);
    +}
    +
    +static void
    +bcm_sdhci_finish_transfer(device_t dev, struct sdhci_slot *slot)
    +{
    +
    +	sdhci_finish_data(slot);
    +}
    +
     static device_method_t bcm_sdhci_methods[] = {
     	/* Device interface */
     	DEVMETHOD(device_probe,		bcm_sdhci_probe),
    @@ -372,8 +664,12 @@ static device_method_t bcm_sdhci_methods[] = {
     	DEVMETHOD(mmcbr_acquire_host,	sdhci_generic_acquire_host),
     	DEVMETHOD(mmcbr_release_host,	sdhci_generic_release_host),
     
    -	/* SDHCI registers accessors */
     	DEVMETHOD(sdhci_min_freq,	bcm_sdhci_min_freq),
    +	/* Platform transfer methods */
    +	DEVMETHOD(sdhci_platform_will_handle,		bcm_sdhci_will_handle_transfer),
    +	DEVMETHOD(sdhci_platform_start_transfer,	bcm_sdhci_start_transfer),
    +	DEVMETHOD(sdhci_platform_finish_transfer,	bcm_sdhci_finish_transfer),
    +	/* SDHCI registers accessors */
     	DEVMETHOD(sdhci_read_1,		bcm_sdhci_read_1),
     	DEVMETHOD(sdhci_read_2,		bcm_sdhci_read_2),
     	DEVMETHOD(sdhci_read_4,		bcm_sdhci_read_4),
    
    From 5e59bc21380810608a6012e2729afccaf774ce8e Mon Sep 17 00:00:00 2001
    From: Jack F Vogel 
    Date: Thu, 28 Feb 2013 22:48:00 +0000
    Subject: [PATCH 0479/1476] Change the ixgbe module name to if_ixgbe to conform
     to the usual naming convention.
    
    ---
     sys/modules/ixgbe/Makefile | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/sys/modules/ixgbe/Makefile b/sys/modules/ixgbe/Makefile
    index 1bc64a0bcd4..6abdf7afe34 100644
    --- a/sys/modules/ixgbe/Makefile
    +++ b/sys/modules/ixgbe/Makefile
    @@ -4,7 +4,7 @@
     
     .PATH:  ${.CURDIR}/../../dev/ixgbe
     
    -KMOD    = ixgbe
    +KMOD    = if_ixgbe
     SRCS    = device_if.h bus_if.h pci_if.h
     SRCS	+= opt_inet.h opt_inet6.h
     SRCS    += ixgbe.c ixv.c
    
    From 56129906234d9d511c778a8fbd4161a2c02b4658 Mon Sep 17 00:00:00 2001
    From: Adrian Chadd 
    Date: Thu, 28 Feb 2013 23:31:23 +0000
    Subject: [PATCH 0480/1476] Don't enable the HT flags for legacy rates.
    
    I stumbled across this whilst trying to debug another weird hang reported
    on the freebsd-wireless list.
    
    Whilst here, add in the STBC check to ath_rateseries_setup().
    
    Whilst here, fix the short preamble flag to be set only for legacy rates.
    
    Whilst here, comment that we should be using the full set of decisions
    made by ath_rateseries_setup() rather than recalculating them!
    ---
     sys/dev/ath/if_ath_tx_ht.c | 108 ++++++++++++++++++++++---------------
     1 file changed, 64 insertions(+), 44 deletions(-)
    
    diff --git a/sys/dev/ath/if_ath_tx_ht.c b/sys/dev/ath/if_ath_tx_ht.c
    index d382f8f620e..dbd4a847361 100644
    --- a/sys/dev/ath/if_ath_tx_ht.c
    +++ b/sys/dev/ath/if_ath_tx_ht.c
    @@ -236,9 +236,9 @@ ath_tx_rate_fill_rcflags(struct ath_softc *sc, struct ath_buf *bf)
     		rate = rt->info[rc[i].rix].rateCode;
     
     		/*
    -		 * XXX only do this for legacy rates?
    +		 * Only enable short preamble for legacy rates
     		 */
    -		if (bf->bf_state.bfs_shpream)
    +		if (IS_HT_RATE(rate) && bf->bf_state.bfs_shpream)
     			rate |= rt->info[rc[i].rix].shortPreamble;
     
     		/*
    @@ -267,6 +267,19 @@ ath_tx_rate_fill_rcflags(struct ath_softc *sc, struct ath_buf *bf)
     			    ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20)
     				rc[i].flags |= ATH_RC_SGI_FLAG;
     
    +			/*
    +			 * If we have STBC TX enabled and the receiver
    +			 * can receive (at least) 1 stream STBC, AND it's
    +			 * MCS 0-7, AND we have at least two chains enabled,
    +			 * enable STBC.
    +			 */
    +			if (ic->ic_htcaps & IEEE80211_HTCAP_TXSTBC &&
    +			    ni->ni_htcap & IEEE80211_HTCAP_RXSTBC_1STREAM &&
    +			    (sc->sc_cur_txchainmask > 1) &&
    +			    HT_RC_2_STREAMS(rate) == 1) {
    +				rc[i].flags |= ATH_RC_STBC_FLAG;
    +			}
    +
     			/* XXX dual stream? and 3-stream? */
     		}
     
    @@ -459,6 +472,9 @@ ath_get_aggr_limit(struct ath_softc *sc, struct ath_buf *bf)
      *
      * It, along with ath_buf_set_rate, must be called -after- a burst
      * or aggregate is setup.
    + *
    + * XXX TODO: it should use the rate series information from the
    + * ath_buf, rather than recalculating it here!
      */
     static void
     ath_rateseries_setup(struct ath_softc *sc, struct ieee80211_node *ni,
    @@ -507,34 +523,6 @@ ath_rateseries_setup(struct ath_softc *sc, struct ieee80211_node *ni,
     		 */
     		series[i].ChSel = sc->sc_cur_txchainmask;
     
    -		if (flags & (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA))
    -			series[i].RateFlags |= HAL_RATESERIES_RTS_CTS;
    -
    -		/*
    -		 * Transmit 40MHz frames only if the node has negotiated
    -		 * it rather than whether the node is capable of it or not.
    -	 	 * It's subtly different in the hostap case.
    -	 	 */
    -		if (ni->ni_chw == 40)
    -			series[i].RateFlags |= HAL_RATESERIES_2040;
    -
    -		/*
    -		 * Set short-GI only if the node has advertised it
    -		 * the channel width is suitable, and we support it.
    -		 * We don't currently have a "negotiated" set of bits -
    -		 * ni_htcap is what the remote end sends, not what this
    -		 * node is capable of.
    -		 */
    -		if (ni->ni_chw == 40 &&
    -		    ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI40 &&
    -		    ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40)
    -			series[i].RateFlags |= HAL_RATESERIES_HALFGI;
    -
    -		if (ni->ni_chw == 20 &&
    -		    ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI20 &&
    -		    ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20)
    -			series[i].RateFlags |= HAL_RATESERIES_HALFGI;
    -
     		/*
     		 * Setup rate and TX power cap for this series.
     		 */
    @@ -542,24 +530,56 @@ ath_rateseries_setup(struct ath_softc *sc, struct ieee80211_node *ni,
     		series[i].RateIndex = rc[i].rix;
     		series[i].tx_power_cap = 0x3f;	/* XXX for now */
     
    -
     		/*
    -		 * If we have STBC TX enabled and the receiver
    -		 * can receive (at least) 1 stream STBC, AND it's
    -		 * MCS 0-7, AND we have at least two chains enabled,
    -		 * enable STBC.
    +		 * Enable RTS/CTS as appropriate.
     		 */
    -		if (ic->ic_htcaps & IEEE80211_HTCAP_TXSTBC &&
    -		    ni->ni_htcap & IEEE80211_HTCAP_RXSTBC_1STREAM &&
    -		    (sc->sc_cur_txchainmask > 1) &&
    -		    HT_RC_2_STREAMS(series[i].Rate) == 1) {
    -			series[i].RateFlags |= HAL_RATESERIES_STBC;
    +		if (flags & (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA))
    +			series[i].RateFlags |= HAL_RATESERIES_RTS_CTS;
    +
    +
    +		if (IS_HT_RATE(rt->info[rc[i].rix].rateCode)) {
    +			/*
    +			 * Transmit 40MHz frames only if the node has negotiated
    +			 * it rather than whether the node is capable of it or not.
    +			 * It's subtly different in the hostap case.
    +			 */
    +			if (ni->ni_chw == 40)
    +				series[i].RateFlags |= HAL_RATESERIES_2040;
    +
    +			/*
    +			 * Set short-GI only if the node has advertised it
    +			 * the channel width is suitable, and we support it.
    +			 * We don't currently have a "negotiated" set of bits -
    +			 * ni_htcap is what the remote end sends, not what this
    +			 * node is capable of.
    +			 */
    +			if (ni->ni_chw == 40 &&
    +			    ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI40 &&
    +			    ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40)
    +				series[i].RateFlags |= HAL_RATESERIES_HALFGI;
    +
    +			if (ni->ni_chw == 20 &&
    +			    ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI20 &&
    +			    ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20)
    +				series[i].RateFlags |= HAL_RATESERIES_HALFGI;
    +
    +			/*
    +			 * If we have STBC TX enabled and the receiver
    +			 * can receive (at least) 1 stream STBC, AND it's
    +			 * MCS 0-7, AND we have at least two chains enabled,
    +			 * enable STBC.
    +			 */
    +			if (ic->ic_htcaps & IEEE80211_HTCAP_TXSTBC &&
    +			    ni->ni_htcap & IEEE80211_HTCAP_RXSTBC_1STREAM &&
    +			    (sc->sc_cur_txchainmask > 1) &&
    +			    HT_RC_2_STREAMS(series[i].Rate) == 1) {
    +				series[i].RateFlags |= HAL_RATESERIES_STBC;
    +			}
    +			/*
    +			 * XXX TODO: LDPC if it's possible
    +			 */
     		}
     
    -		/*
    -		 * XXX TODO: LDPC if it's possible
    -		 */
    -
     		/*
     		 * PktDuration doesn't include slot, ACK, RTS, etc timing -
     		 * it's just the packet duration
    
    From 7a27f0a338aa8695ab9538ae6be139c98b9a51db Mon Sep 17 00:00:00 2001
    From: Adrian Chadd 
    Date: Thu, 28 Feb 2013 23:39:22 +0000
    Subject: [PATCH 0481/1476] Oops - fix an incorrect test.
    
    ---
     sys/dev/ath/if_ath_tx_ht.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/sys/dev/ath/if_ath_tx_ht.c b/sys/dev/ath/if_ath_tx_ht.c
    index dbd4a847361..9921ffaf305 100644
    --- a/sys/dev/ath/if_ath_tx_ht.c
    +++ b/sys/dev/ath/if_ath_tx_ht.c
    @@ -238,7 +238,7 @@ ath_tx_rate_fill_rcflags(struct ath_softc *sc, struct ath_buf *bf)
     		/*
     		 * Only enable short preamble for legacy rates
     		 */
    -		if (IS_HT_RATE(rate) && bf->bf_state.bfs_shpream)
    +		if ((! IS_HT_RATE(rate)) && bf->bf_state.bfs_shpream)
     			rate |= rt->info[rc[i].rix].shortPreamble;
     
     		/*
    
    From 87c176d272e4a02be43801841a8a03d4b46934dc Mon Sep 17 00:00:00 2001
    From: Adrian Chadd 
    Date: Thu, 28 Feb 2013 23:39:38 +0000
    Subject: [PATCH 0482/1476] Add missing flags.
    
    ---
     sys/dev/ath/if_athrate.h | 2 ++
     1 file changed, 2 insertions(+)
    
    diff --git a/sys/dev/ath/if_athrate.h b/sys/dev/ath/if_athrate.h
    index d07c9ca0b8b..918823ff4a8 100644
    --- a/sys/dev/ath/if_athrate.h
    +++ b/sys/dev/ath/if_athrate.h
    @@ -84,6 +84,8 @@ void	ath_rate_detach(struct ath_ratectrl *);
     #define	ATH_RC_SGI_FLAG		0x04	/* use short-GI */
     #define	ATH_RC_HT_FLAG		0x08	/* use HT */
     #define	ATH_RC_RTSCTS_FLAG	0x10	/* enable RTS/CTS protection */
    +#define	ATH_RC_STBC_FLAG	0x20	/* enable STBC */
    +#define	ATH_RC_LDPC_FLAG	0x40	/* enable STBC */
     
     struct ath_rc_series {
     	uint8_t rix;		/* ratetable index, not rate code */
    
    From 4cf5de800c0f43b48ee9fad19b2d88404f7fea74 Mon Sep 17 00:00:00 2001
    From: Glen Barber 
    Date: Thu, 28 Feb 2013 23:45:41 +0000
    Subject: [PATCH 0483/1476] Minor wordsmithing.
    
    X-MFC-Needs:	r245617
    ---
     UPDATING | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/UPDATING b/UPDATING
    index 8be2f464462..74da04d05b6 100644
    --- a/UPDATING
    +++ b/UPDATING
    @@ -46,8 +46,8 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 10.x IS SLOW:
     	unlikely event that -M was the last option on the command line
     	and the command line contained at least two files and a target
     	directory the first file will have logs appended to it.  The -M
    -	option served little practical purpose in the last decade so it's
    -	used expected to be extremely rare.
    +	option served little practical purpose in the last decade so its
    +	use is expected to be extremely rare.
     
     20121223:
     	After switching to Clang as the default compiler some users of ZFS
    
    From ac4adddf040f1010f08e284f71e1bb2f92b4d43a Mon Sep 17 00:00:00 2001
    From: Ganbold Tsagaankhuu 
    Date: Fri, 1 Mar 2013 01:42:31 +0000
    Subject: [PATCH 0484/1476] Add support for A10 uart. A10 uart is derived from
     Synopsys DesignWare uart and requires to read Uart Status Register when
     IIR_BUSY has detected. Also this change includes FDT check, where it checks
     device specific properties defined in dts and sets the busy_detect variable.
     broken_txfifo is also needed to be set in order to make it work for A10 uart
     case.
    
    Reviewed by: marcel@
    Approved by: gonzo@
    ---
     sys/dev/ic/ns16550.h           |  1 +
     sys/dev/uart/uart_dev_ns8250.c | 43 ++++++++++++++++++++++++++++++----
     2 files changed, 39 insertions(+), 5 deletions(-)
    
    diff --git a/sys/dev/ic/ns16550.h b/sys/dev/ic/ns16550.h
    index 635270c4a3d..659f5918497 100644
    --- a/sys/dev/ic/ns16550.h
    +++ b/sys/dev/ic/ns16550.h
    @@ -182,6 +182,7 @@
     #define	com_xoff1	6	/* XOFF 1 character (R/W) */
     #define	com_xoff2	7	/* XOFF 2 character (R/W) */
     
    +#define DW_REG_USR	31	/* DesignWare derived Uart Status Reg */
     #define com_usr		39	/* Octeon 16750/16550 Uart Status Reg */
     #define REG_USR		com_usr
     #define USR_TXFIFO_NOTFULL 2    /* Uart TX FIFO Not full */
    diff --git a/sys/dev/uart/uart_dev_ns8250.c b/sys/dev/uart/uart_dev_ns8250.c
    index eb36da1bf40..8eca8f0f4dd 100644
    --- a/sys/dev/uart/uart_dev_ns8250.c
    +++ b/sys/dev/uart/uart_dev_ns8250.c
    @@ -24,6 +24,8 @@
      * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      */
     
    +#include "opt_platform.h"
    +
     #include 
     __FBSDID("$FreeBSD$");
     
    @@ -35,6 +37,12 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     
    +#ifdef FDT
    +#include 
    +#include 
    +#include 
    +#endif
    +
     #include 
     #include 
     #include 
    @@ -45,6 +53,11 @@ __FBSDID("$FreeBSD$");
     
     #define	DEFAULT_RCLK	1843200
     
    +static int broken_txfifo = 0;
    +SYSCTL_INT(_hw, OID_AUTO, broken_txfifo, CTLFLAG_RW | CTLFLAG_TUN,
    +	&broken_txfifo, 0, "UART FIFO has QEMU emulation bug");
    +TUNABLE_INT("hw.broken_txfifo", &broken_txfifo);
    +
     /*
      * Clear pending interrupts. THRE is cleared by reading IIR. Data
      * that may have been received gets lost here.
    @@ -350,6 +363,7 @@ struct ns8250_softc {
     	
     	uint8_t		ier_mask;
     	uint8_t		ier_rxbits;
    +	uint8_t		busy_detect;
     };
     
     static int ns8250_bus_attach(struct uart_softc *);
    @@ -401,6 +415,24 @@ ns8250_bus_attach(struct uart_softc *sc)
     	struct ns8250_softc *ns8250 = (struct ns8250_softc*)sc;
     	struct uart_bas *bas;
     	unsigned int ivar;
    +#ifdef FDT
    +	phandle_t node;
    +	pcell_t cell;
    +#endif
    +
    +	ns8250->busy_detect = 0;
    +
    +#ifdef FDT
    +	/* 
    +	 * Check whether uart requires to read USR reg when IIR_BUSY and 
    +	 * has broken txfifo. 
    +	 */
    +	node = ofw_bus_get_node(sc->sc_dev);
    +	if ((OF_getprop(node, "busy-detect", &cell, sizeof(cell))) > 0)
    +		ns8250->busy_detect = 1;
    +	if ((OF_getprop(node, "broken-txfifo", &cell, sizeof(cell))) > 0)
    +		broken_txfifo = 1;
    +#endif
     
     	bas = &sc->sc_bas;
     
    @@ -592,6 +624,12 @@ ns8250_bus_ipend(struct uart_softc *sc)
     	bas = &sc->sc_bas;
     	uart_lock(sc->sc_hwmtx);
     	iir = uart_getreg(bas, REG_IIR);
    +
    +	if (ns8250->busy_detect && (iir & IIR_BUSY) == IIR_BUSY) {
    +		(void)uart_getreg(bas, DW_REG_USR);
    +		uart_unlock(sc->sc_hwmtx);
    +		return (0);
    +	}
     	if (iir & IIR_NOPEND) {
     		uart_unlock(sc->sc_hwmtx);
     		return (0);
    @@ -847,11 +885,6 @@ ns8250_bus_setsig(struct uart_softc *sc, int sig)
     	return (0);
     }
     
    -static int broken_txfifo = 0;
    -SYSCTL_INT(_hw, OID_AUTO, broken_txfifo, CTLFLAG_RW | CTLFLAG_TUN,
    -	&broken_txfifo, 0, "UART FIFO has QEMU emulation bug");
    -TUNABLE_INT("hw.broken_txfifo", &broken_txfifo);
    -
     static int
     ns8250_bus_transmit(struct uart_softc *sc)
     {
    
    From 341d7df3dacc74e8923c7f8c974e0e67cad8d1a7 Mon Sep 17 00:00:00 2001
    From: Ganbold Tsagaankhuu 
    Date: Fri, 1 Mar 2013 01:47:11 +0000
    Subject: [PATCH 0485/1476] Enable uart driver for A10.
    
    Approved by: gonzo@
    ---
     sys/arm/allwinner/files.a10     | 2 +-
     sys/arm/conf/CUBIEBOARD         | 4 ++--
     sys/boot/fdt/dts/cubieboard.dts | 2 ++
     3 files changed, 5 insertions(+), 3 deletions(-)
    
    diff --git a/sys/arm/allwinner/files.a10 b/sys/arm/allwinner/files.a10
    index 9e947dec9f7..c25682a86bc 100644
    --- a/sys/arm/allwinner/files.a10
    +++ b/sys/arm/allwinner/files.a10
    @@ -17,5 +17,5 @@ arm/allwinner/timer.c			standard
     arm/allwinner/aintc.c			standard
     arm/allwinner/bus_space.c		standard
     arm/allwinner/common.c			standard
    -arm/allwinner/console.c			standard
    +#arm/allwinner/console.c			standard
     arm/allwinner/a10_machdep.c		standard
    diff --git a/sys/arm/conf/CUBIEBOARD b/sys/arm/conf/CUBIEBOARD
    index fa5bfc8751d..1c0407bb158 100644
    --- a/sys/arm/conf/CUBIEBOARD
    +++ b/sys/arm/conf/CUBIEBOARD
    @@ -87,8 +87,8 @@ options		ROOTDEVNAME=\"ufs:/dev/da0s2\"
     #options	ATA_STATIC_ID	# Static device numbering
     
     # Console and misc
    -#device		uart
    -#device		uart_ns8250
    +device		uart
    +device		uart_ns8250
     device		pty
     device		snp
     device		md
    diff --git a/sys/boot/fdt/dts/cubieboard.dts b/sys/boot/fdt/dts/cubieboard.dts
    index abb3f454bea..181d5d43367 100644
    --- a/sys/boot/fdt/dts/cubieboard.dts
    +++ b/sys/boot/fdt/dts/cubieboard.dts
    @@ -121,6 +121,8 @@
     			interrupt-parent = <&AINTC>;
     			current-speed = <115200>;
     			clock-frequency = < 24000000 >;
    +			busy-detect = <1>;
    +			broken-txfifo = <1>;
     		};
     	};
     
    
    From 91039bb268df0130d07584031909665a198464ad Mon Sep 17 00:00:00 2001
    From: Neel Natu 
    Date: Fri, 1 Mar 2013 02:26:28 +0000
    Subject: [PATCH 0486/1476] Specify the length of the mapping requested from
     'paddr_guest2host()'.
    
    This seems prudent to do in its own right but it also opens up the possibility
    of not having to mmap the entire guest address space in the 'bhyve' process
    context.
    
    Discussed with:	grehan
    Obtained from:	NetApp
    ---
     usr.sbin/bhyve/acpi.c             |  9 ++++++---
     usr.sbin/bhyve/bhyverun.c         | 18 ++++++++++--------
     usr.sbin/bhyve/bhyverun.h         |  2 +-
     usr.sbin/bhyve/mptbl.c            |  9 ++++++---
     usr.sbin/bhyve/pci_virtio_block.c | 19 +++++++------------
     usr.sbin/bhyve/pci_virtio_net.c   | 14 ++++----------
     usr.sbin/bhyve/virtio.h           | 15 +++++++++++++++
     7 files changed, 49 insertions(+), 37 deletions(-)
    
    diff --git a/usr.sbin/bhyve/acpi.c b/usr.sbin/bhyve/acpi.c
    index 32effdc1e95..cabe75ef59f 100644
    --- a/usr.sbin/bhyve/acpi.c
    +++ b/usr.sbin/bhyve/acpi.c
    @@ -683,13 +683,16 @@ static int
     basl_load(int fd, uint64_t off)
     {
             struct stat sb;
    +	void *gaddr;
     	int err;
     
     	err = 0;
    -
    -	if (fstat(fd, &sb) < 0 ||
    -	    read(fd, paddr_guest2host(basl_acpi_base + off), sb.st_size) < 0)
    +	gaddr = paddr_guest2host(basl_acpi_base + off, sb.st_size);
    +	if (gaddr != NULL) {
    +		if (fstat(fd, &sb) < 0 || read(fd, gaddr, sb.st_size) < 0)
     			err = errno;
    +	} else
    +		err = EFAULT;
     
     	return (err);
     }
    diff --git a/usr.sbin/bhyve/bhyverun.c b/usr.sbin/bhyve/bhyverun.c
    index ea4b68c703c..17d60d6ef9f 100644
    --- a/usr.sbin/bhyve/bhyverun.c
    +++ b/usr.sbin/bhyve/bhyverun.c
    @@ -157,17 +157,19 @@ usage(int code)
     }
     
     void *
    -paddr_guest2host(uintptr_t gaddr)
    +paddr_guest2host(uintptr_t gaddr, size_t len)
     {
    -	if (lomem_sz == 0)
    -		return (NULL);
     
    -	if (gaddr < lomem_sz) {
    +	if (gaddr < lomem_sz && gaddr + len <= lomem_sz)
     		return ((void *)(lomem_addr + gaddr));
    -	} else if (gaddr >= 4*GB && gaddr < (4*GB + himem_sz)) {
    -		return ((void *)(himem_addr + gaddr - 4*GB));
    -	} else
    -		return (NULL);
    +
    +	if (gaddr >= 4*GB) {
    +		gaddr -= 4*GB;
    +		if (gaddr < himem_sz && gaddr + len <= himem_sz)
    +			return ((void *)(himem_addr + gaddr));
    +	}
    +
    +	return (NULL);
     }
     
     int
    diff --git a/usr.sbin/bhyve/bhyverun.h b/usr.sbin/bhyve/bhyverun.h
    index 45033b8a5e1..70455bf3ace 100644
    --- a/usr.sbin/bhyve/bhyverun.h
    +++ b/usr.sbin/bhyve/bhyverun.h
    @@ -43,7 +43,7 @@ extern char *vmname;
     
     extern u_long lomem_sz, himem_sz;
     
    -void *paddr_guest2host(uintptr_t);
    +void *paddr_guest2host(uintptr_t addr, size_t len);
     
     void fbsdrun_addcpu(struct vmctx *ctx, int cpu, uint64_t rip);
     int  fbsdrun_muxed(void);
    diff --git a/usr.sbin/bhyve/mptbl.c b/usr.sbin/bhyve/mptbl.c
    index 52790f38ab8..9c68b3d0258 100644
    --- a/usr.sbin/bhyve/mptbl.c
    +++ b/usr.sbin/bhyve/mptbl.c
    @@ -41,6 +41,9 @@ __FBSDID("$FreeBSD$");
     
     #define MPTABLE_BASE		0xF0000
     
    +/* floating pointer length + maximum length of configuration table */
    +#define	MPTABLE_MAX_LENGTH	(65536 + 16)
    +
     #define LAPIC_PADDR		0xFEE00000
     #define LAPIC_VERSION 		16
     
    @@ -346,13 +349,13 @@ mptable_build(struct vmctx *ctx, int ncpu, int ioapic)
     	char 			*curraddr;
     	char 			*startaddr;
     
    -	if (paddr_guest2host(0) == NULL) {
    +	startaddr = paddr_guest2host(MPTABLE_BASE, MPTABLE_MAX_LENGTH);
    +	if (startaddr == NULL) {
     		printf("mptable requires mapped mem\n");
     		return (ENOMEM);
     	}
     
    -	startaddr = curraddr = paddr_guest2host(MPTABLE_BASE);
    -
    +	curraddr = startaddr;
     	mpfp = (mpfps_t)curraddr;
     	mpt_build_mpfp(mpfp, MPTABLE_BASE);
     	curraddr += sizeof(*mpfp);
    diff --git a/usr.sbin/bhyve/pci_virtio_block.c b/usr.sbin/bhyve/pci_virtio_block.c
    index 62bf801bdcc..31ff2e62ac7 100644
    --- a/usr.sbin/bhyve/pci_virtio_block.c
    +++ b/usr.sbin/bhyve/pci_virtio_block.c
    @@ -222,13 +222,13 @@ pci_vtblk_proc(struct pci_vtblk_softc *sc, struct vring_hqueue *hq)
     	assert(nsegs >= 3);
     	assert(nsegs < VTBLK_MAXSEGS + 2);
     
    -	vid = paddr_guest2host(vd->vd_addr);
    +	vid = paddr_guest2host(vd->vd_addr, vd->vd_len);
     	assert((vid->vd_flags & VRING_DESC_F_INDIRECT) == 0);
     
     	/*
     	 * The first descriptor will be the read-only fixed header
     	 */
    -	vbh = paddr_guest2host(vid[0].vd_addr);
    +	vbh = paddr_guest2host(vid[0].vd_addr, sizeof(struct virtio_blk_hdr));
     	assert(vid[0].vd_len == sizeof(struct virtio_blk_hdr));
     	assert(vid[0].vd_flags & VRING_DESC_F_NEXT);
     	assert((vid[0].vd_flags & VRING_DESC_F_WRITE) == 0);
    @@ -247,7 +247,8 @@ pci_vtblk_proc(struct pci_vtblk_softc *sc, struct vring_hqueue *hq)
     	 * Build up the iovec based on the guest's data descriptors
     	 */
     	for (i = 1, iolen = 0; i < nsegs - 1; i++) {
    -		iov[i-1].iov_base = paddr_guest2host(vid[i].vd_addr);
    +		iov[i-1].iov_base = paddr_guest2host(vid[i].vd_addr,
    +						     vid[i].vd_len);
     		iov[i-1].iov_len = vid[i].vd_len;
     		iolen += vid[i].vd_len;
     
    @@ -265,7 +266,7 @@ pci_vtblk_proc(struct pci_vtblk_softc *sc, struct vring_hqueue *hq)
     	}
     
     	/* Lastly, get the address of the status byte */
    -	status = paddr_guest2host(vid[nsegs - 1].vd_addr);
    +	status = paddr_guest2host(vid[nsegs - 1].vd_addr, 1);
     	assert(vid[nsegs - 1].vd_len == 1);
     	assert((vid[nsegs - 1].vd_flags & VRING_DESC_F_NEXT) == 0);
     	assert(vid[nsegs - 1].vd_flags & VRING_DESC_F_WRITE);
    @@ -341,7 +342,8 @@ pci_vtblk_ring_init(struct pci_vtblk_softc *sc, uint64_t pfn)
     	hq = &sc->vbsc_q;
     	hq->hq_size = VTBLK_RINGSZ;
     
    -	hq->hq_dtable = paddr_guest2host(pfn << VRING_PFN);
    +	hq->hq_dtable = paddr_guest2host(pfn << VRING_PFN,
    +					 vring_size(VTBLK_RINGSZ));
     	hq->hq_avail_flags =  (uint16_t *)(hq->hq_dtable + hq->hq_size);
     	hq->hq_avail_idx = hq->hq_avail_flags + 1;
     	hq->hq_avail_ring = hq->hq_avail_flags + 2;
    @@ -371,13 +373,6 @@ pci_vtblk_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
     		return (1);
     	}
     
    -	/*
    -	 * Access to guest memory is required. Fail if
    -	 * memory not mapped
    -	 */
    -	if (paddr_guest2host(0) == NULL)
    -		return (1);
    -
     	/*
     	 * The supplied backing file has to exist
     	 */
    diff --git a/usr.sbin/bhyve/pci_virtio_net.c b/usr.sbin/bhyve/pci_virtio_net.c
    index 327ebf71441..a5cf8b3c85c 100644
    --- a/usr.sbin/bhyve/pci_virtio_net.c
    +++ b/usr.sbin/bhyve/pci_virtio_net.c
    @@ -326,7 +326,7 @@ pci_vtnet_tap_rx(struct pci_vtnet_softc *sc)
     		 * Get a pointer to the rx header, and use the
     		 * data immediately following it for the packet buffer.
     		 */
    -		vrx = (struct virtio_net_rxhdr *)paddr_guest2host(vd->vd_addr);
    +		vrx = paddr_guest2host(vd->vd_addr, vd->vd_len);
     		buf = (uint8_t *)(vrx + 1);
     
     		len = read(sc->vsc_tapfd, buf,
    @@ -434,7 +434,7 @@ pci_vtnet_proctx(struct pci_vtnet_softc *sc, struct vring_hqueue *hq)
     	for (i = 0, plen = 0;
     	     i < VTNET_MAXSEGS;
     	     i++, vd = &hq->hq_dtable[vd->vd_next]) {
    -		iov[i].iov_base = paddr_guest2host(vd->vd_addr);
    +		iov[i].iov_base = paddr_guest2host(vd->vd_addr, vd->vd_len);
     		iov[i].iov_len = vd->vd_len;
     		plen += vd->vd_len;
     		tlen += vd->vd_len;
    @@ -517,7 +517,8 @@ pci_vtnet_ring_init(struct pci_vtnet_softc *sc, uint64_t pfn)
     	hq = &sc->vsc_hq[qnum];
     	hq->hq_size = pci_vtnet_qsize(qnum);
     
    -	hq->hq_dtable = paddr_guest2host(pfn << VRING_PFN);
    +	hq->hq_dtable = paddr_guest2host(pfn << VRING_PFN,
    +					 vring_size(hq->hq_size));
     	hq->hq_avail_flags =  (uint16_t *)(hq->hq_dtable + hq->hq_size);
     	hq->hq_avail_idx = hq->hq_avail_flags + 1;
     	hq->hq_avail_ring = hq->hq_avail_flags + 2;
    @@ -541,13 +542,6 @@ pci_vtnet_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
     	struct pci_vtnet_softc *sc;
     	const char *env_msi;
     
    -	/*
    -	 * Access to guest memory is required. Fail if
    -	 * memory not mapped
    -	 */
    -	if (paddr_guest2host(0) == NULL)
    -		return (1);
    -
     	sc = malloc(sizeof(struct pci_vtnet_softc));
     	memset(sc, 0, sizeof(struct pci_vtnet_softc));
     
    diff --git a/usr.sbin/bhyve/virtio.h b/usr.sbin/bhyve/virtio.h
    index 04ef586afcd..fe6fb1af3e1 100644
    --- a/usr.sbin/bhyve/virtio.h
    +++ b/usr.sbin/bhyve/virtio.h
    @@ -85,4 +85,19 @@ struct virtio_used {
     #define VTCFG_R_CFG1		24	/* With MSI-X */
     #define VTCFG_R_MSIX		20
     
    +/* From section 2.3, "Virtqueue Configuration", of the virtio specification */
    +static inline u_int
    +vring_size(u_int qsz)
    +{
    +	u_int size;
    +
    +	size = sizeof(struct virtio_desc) * qsz + sizeof(uint16_t) * (3 + qsz);
    +	size = roundup2(size, VRING_ALIGN);
    +
    +	size += sizeof(uint16_t) * 3 + sizeof(struct virtio_used) * qsz;
    +	size = roundup2(size, VRING_ALIGN);
    +
    +	return (size);
    +}
    +
     #endif	/* _VIRTIO_H_ */
    
    From 0837595205131f2c1bdc3087cc0e5118243ee601 Mon Sep 17 00:00:00 2001
    From: Brooks Davis 
    Date: Fri, 1 Mar 2013 03:25:43 +0000
    Subject: [PATCH 0487/1476] Provide slightly more helpful feedback when we
     can't figure out what compiler the user is using.
    
    PR:		misc/173914
    ---
     share/mk/bsd.compiler.mk | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/share/mk/bsd.compiler.mk b/share/mk/bsd.compiler.mk
    index c38c76ea4b3..2d648de6c48 100644
    --- a/share/mk/bsd.compiler.mk
    +++ b/share/mk/bsd.compiler.mk
    @@ -14,7 +14,7 @@ COMPILER_TYPE:=	gcc
     .  elif ${_COMPILER_VERSION:Mclang}
     COMPILER_TYPE:=	clang
     .  else
    -.error Unable to determine compiler type for ${CC}
    +.error Unable to determine compiler type for ${CC}.  Consider setting COMPILER_TYPE.
     .  endif
     .  undef _COMPILER_VERSION
     . endif
    
    From d1a0cea48b0159af86b3d389592af910474b45ec Mon Sep 17 00:00:00 2001
    From: Ruslan Ermilov 
    Date: Fri, 1 Mar 2013 07:39:14 +0000
    Subject: [PATCH 0488/1476] Fixed documented prototype of kinfo_getproc(3).
    
    ---
     lib/libutil/kinfo_getproc.3 | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/lib/libutil/kinfo_getproc.3 b/lib/libutil/kinfo_getproc.3
    index 68b8819b556..804cb6c19b7 100644
    --- a/lib/libutil/kinfo_getproc.3
    +++ b/lib/libutil/kinfo_getproc.3
    @@ -25,7 +25,7 @@
     .\"
     .\" $FreeBSD$
     .\"
    -.Dd February 25, 2012
    +.Dd March 1, 2013
     .Dt KINFO_GETPROC 3
     .Os
     .Sh NAME
    @@ -37,7 +37,7 @@
     .In sys/types.h
     .In libutil.h
     .Ft struct kinfo_proc *
    -.Fn kinfo_getproc "pid_t pid" "int *cntp"
    +.Fn kinfo_getproc "pid_t pid"
     .Sh DESCRIPTION
     This function is used for obtaining process information from the kernel.
     .Pp
    
    From 99c899985653fe4b9bef31d01c2b6bc4a0a5995f Mon Sep 17 00:00:00 2001
    From: Alan Cox 
    Date: Fri, 1 Mar 2013 08:30:31 +0000
    Subject: [PATCH 0489/1476] Copy the definition of VM_MAX_AUTOTUNE_MAXUSERS
     from i386.  (See r242847.)
    
    Tested by:	andrew
    ---
     sys/arm/include/vmparam.h | 4 ++++
     1 file changed, 4 insertions(+)
    
    diff --git a/sys/arm/include/vmparam.h b/sys/arm/include/vmparam.h
    index 09bf62ce3c4..53c40d203f8 100644
    --- a/sys/arm/include/vmparam.h
    +++ b/sys/arm/include/vmparam.h
    @@ -178,4 +178,8 @@ extern vm_offset_t vm_max_kernel_address;
     
     #define	ZERO_REGION_SIZE	(64 * 1024)	/* 64KB */
     
    +#ifndef VM_MAX_AUTOTUNE_MAXUSERS
    +#define	VM_MAX_AUTOTUNE_MAXUSERS	384
    +#endif
    +
     #endif	/* _MACHINE_VMPARAM_H_ */
    
    From bb508e7732e285bcce70a43c900c58ee16e3c465 Mon Sep 17 00:00:00 2001
    From: Martin Matuska 
    Date: Fri, 1 Mar 2013 09:42:58 +0000
    Subject: [PATCH 0490/1476] Fix the zfs_ioctl compat layer to support zfs_cmd
     size change introduced in r247265 (ZFS deadman thread). Both new utilities
     now support the old kernel and new kernel properly detects old utilities.
    
    For future backwards compatibility, the vfs.zfs.version.ioctl read-only
    sysctl has been introduced. With this sysctl zfs utilities will be able
    to detect the ioctl interface version of the currently loaded zfs module.
    
    As a side effect, the zfs utilities between r247265 and this revision don't
    support the old kernel module. If you are using HEAD newer or equal than
    r247265, install the new kernel module (or whole kernel) first.
    
    MFC after:	10 days
    ---
     .../lib/libzfs/common/libzfs_impl.h           |  35 ++-
     .../opensolaris/common/zfs/zfs_ioctl_compat.c | 207 +++++++++++++++---
     .../opensolaris/common/zfs/zfs_ioctl_compat.h |  74 ++++++-
     .../opensolaris/uts/common/fs/zfs/zfs_ioctl.c |  17 +-
     4 files changed, 288 insertions(+), 45 deletions(-)
    
    diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h
    index 1c46d32f4ba..be07187f9d5 100644
    --- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h
    +++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h
    @@ -24,6 +24,7 @@
      * Copyright (c) 2011 Pawel Jakub Dawidek .
      * All rights reserved.
      * Copyright (c) 2011 by Delphix. All rights reserved.
    + * Copyright (c) 2013 Martin Matuska . All rights reserved.
      */
     
     #ifndef	_LIBFS_IMPL_H
    @@ -216,6 +217,7 @@ extern void libzfs_fru_clear(libzfs_handle_t *, boolean_t);
     
     #ifndef sun
     static int zfs_kernel_version = 0;
    +static int zfs_ioctl_version = 0;
     
     /*
      * This is FreeBSD version of ioctl, because Solaris' ioctl() updates
    @@ -225,19 +227,34 @@ static int zfs_kernel_version = 0;
     static __inline int
     zcmd_ioctl(int fd, unsigned long cmd, zfs_cmd_t *zc)
     {
    -	size_t oldsize, zfs_kernel_version_size;
    +	size_t oldsize, zfs_kernel_version_size, zfs_ioctl_version_size;
     	int version, ret, cflag = ZFS_CMD_COMPAT_NONE;
     
    -	zfs_kernel_version_size = sizeof(zfs_kernel_version);
    -	if (zfs_kernel_version == 0) {
    -		sysctlbyname("vfs.zfs.version.spa", &zfs_kernel_version,
    -		    &zfs_kernel_version_size, NULL, 0);
    +	zfs_ioctl_version_size = sizeof(zfs_ioctl_version);
    +	if (zfs_ioctl_version == 0) {
    +		sysctlbyname("vfs.zfs.version.ioctl", &zfs_ioctl_version,
    +		    &zfs_ioctl_version_size, NULL, 0);
     	}
     
    -	if (zfs_kernel_version == SPA_VERSION_15 ||
    -	    zfs_kernel_version == SPA_VERSION_14 ||
    -	    zfs_kernel_version == SPA_VERSION_13)
    -		cflag = ZFS_CMD_COMPAT_V15;
    +	/*
    +	 * If vfs.zfs.version.ioctl is not defined, assume we have v28
    +	 * compatible binaries and use vfs.zfs.version.spa to test for v15
    +	 */
    +	if (zfs_ioctl_version < ZFS_IOCVER_DEADMAN) {
    +		cflag = ZFS_CMD_COMPAT_V28;
    +		zfs_kernel_version_size = sizeof(zfs_kernel_version);
    +
    +		if (zfs_kernel_version == 0) {
    +			sysctlbyname("vfs.zfs.version.spa",
    +			    &zfs_kernel_version,
    +			    &zfs_kernel_version_size, NULL, 0);
    +		}
    +
    +		if (zfs_kernel_version == SPA_VERSION_15 ||
    +		    zfs_kernel_version == SPA_VERSION_14 ||
    +		    zfs_kernel_version == SPA_VERSION_13)
    +			cflag = ZFS_CMD_COMPAT_V15;
    +	}
     
     	oldsize = zc->zc_nvlist_dst_size;
     	ret = zcmd_ioctl_compat(fd, cmd, zc, cflag);
    diff --git a/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c b/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c
    index 0b43c7869e7..4959335409b 100644
    --- a/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c
    +++ b/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c
    @@ -19,7 +19,7 @@
      * CDDL HEADER END
      */
     /*
    - * Copyright 2010 Martin Matuska . All rights reserved.
    + * Copyright 2013 Martin Matuska . All rights reserved.
      * Portions Copyright 2005, 2010, Oracle and/or its affiliates.
      * All rights reserved.
      * Use is subject to license terms.
    @@ -35,22 +35,100 @@
     #include 
     #include "zfs_ioctl_compat.h"
     
    +static int zfs_version_ioctl = ZFS_IOCVER_CURRENT;
    +SYSCTL_DECL(_vfs_zfs_version);
    +SYSCTL_INT(_vfs_zfs_version, OID_AUTO, ioctl, CTLFLAG_RD, &zfs_version_ioctl,
    +    0, "ZFS_IOCTL_VERSION");
    +
     /*
    - * FreeBSD zfs_cmd compatibility with v15 and older binaries
    + * FreeBSD zfs_cmd compatibility with older binaries
      * appropriately remap/extend the zfs_cmd_t structure
      */
     void
     zfs_cmd_compat_get(zfs_cmd_t *zc, caddr_t addr, const int cflag)
     {
     	zfs_cmd_v15_t *zc_c;
    +	zfs_cmd_v28_t *zc28_c;
     
    -	if (cflag == ZFS_CMD_COMPAT_V15) {
    +	switch (cflag) {
    +	case ZFS_CMD_COMPAT_V28:
    +		zc28_c = (void *)addr;
    +
    +		/* zc */
    +		strlcpy(zc->zc_name, zc28_c->zc_name, MAXPATHLEN);
    +		strlcpy(zc->zc_value, zc28_c->zc_value, MAXPATHLEN * 2);
    +		strlcpy(zc->zc_string, zc28_c->zc_string, MAXPATHLEN);
    +		strlcpy(zc->zc_top_ds, zc28_c->zc_top_ds, MAXPATHLEN);
    +		zc->zc_guid = zc28_c->zc_guid;
    +		zc->zc_nvlist_conf = zc28_c->zc_nvlist_conf;
    +		zc->zc_nvlist_conf_size = zc28_c->zc_nvlist_conf_size;
    +		zc->zc_nvlist_src = zc28_c->zc_nvlist_src;
    +		zc->zc_nvlist_src_size = zc28_c->zc_nvlist_src_size;
    +		zc->zc_nvlist_dst = zc28_c->zc_nvlist_dst;
    +		zc->zc_nvlist_dst_size = zc28_c->zc_nvlist_dst_size;
    +		zc->zc_cookie = zc28_c->zc_cookie;
    +		zc->zc_objset_type = zc28_c->zc_objset_type;
    +		zc->zc_perm_action = zc28_c->zc_perm_action;
    +		zc->zc_history = zc28_c->zc_history;
    +		zc->zc_history_len = zc28_c->zc_history_len;
    +		zc->zc_history_offset = zc28_c->zc_history_offset;
    +		zc->zc_obj = zc28_c->zc_obj;
    +		zc->zc_iflags = zc28_c->zc_iflags;
    +		zc->zc_share = zc28_c->zc_share;
    +		zc->zc_jailid = zc28_c->zc_jailid;
    +		zc->zc_objset_stats = zc28_c->zc_objset_stats;
    +		zc->zc_begin_record = zc28_c->zc_begin_record;
    +		zc->zc_defer_destroy = zc28_c->zc_defer_destroy;
    +		zc->zc_temphold = zc28_c->zc_temphold;
    +		zc->zc_action_handle = zc28_c->zc_action_handle;
    +		zc->zc_cleanup_fd = zc28_c->zc_cleanup_fd;
    +		zc->zc_simple = zc28_c->zc_simple;
    +		bcopy(zc28_c->zc_pad, zc->zc_pad, sizeof(zc->zc_pad));
    +		zc->zc_sendobj = zc28_c->zc_sendobj;
    +		zc->zc_fromobj = zc28_c->zc_fromobj;
    +		zc->zc_createtxg = zc28_c->zc_createtxg;
    +		zc->zc_stat = zc28_c->zc_stat;
    +
    +		/* zc->zc_inject_record */
    +		zc->zc_inject_record.zi_objset =
    +		    zc28_c->zc_inject_record.zi_objset;
    +		zc->zc_inject_record.zi_object =
    +		    zc28_c->zc_inject_record.zi_object;
    +		zc->zc_inject_record.zi_start =
    +		    zc28_c->zc_inject_record.zi_start;
    +		zc->zc_inject_record.zi_end =
    +		    zc28_c->zc_inject_record.zi_end;
    +		zc->zc_inject_record.zi_guid =
    +		    zc28_c->zc_inject_record.zi_guid;
    +		zc->zc_inject_record.zi_level =
    +		    zc28_c->zc_inject_record.zi_level;
    +		zc->zc_inject_record.zi_error =
    +		    zc28_c->zc_inject_record.zi_error;
    +		zc->zc_inject_record.zi_type =
    +		    zc28_c->zc_inject_record.zi_type;
    +		zc->zc_inject_record.zi_freq =
    +		    zc28_c->zc_inject_record.zi_freq;
    +		zc->zc_inject_record.zi_failfast =
    +		    zc28_c->zc_inject_record.zi_failfast;
    +		strlcpy(zc->zc_inject_record.zi_func,
    +		    zc28_c->zc_inject_record.zi_func, MAXNAMELEN);
    +		zc->zc_inject_record.zi_iotype =
    +		    zc28_c->zc_inject_record.zi_iotype;
    +		zc->zc_inject_record.zi_duration =
    +		    zc28_c->zc_inject_record.zi_duration;
    +		zc->zc_inject_record.zi_timer =
    +		    zc28_c->zc_inject_record.zi_timer;
    +		zc->zc_inject_record.zi_cmd = ZINJECT_UNINITIALIZED;
    +		zc->zc_inject_record.zi_pad = 0;
    +		break;
    +
    +	case ZFS_CMD_COMPAT_V15:
     		zc_c = (void *)addr;
     
     		/* zc */
    -		strlcpy(zc->zc_name,zc_c->zc_name,MAXPATHLEN);
    -		strlcpy(zc->zc_value,zc_c->zc_value,MAXPATHLEN);
    -		strlcpy(zc->zc_string,zc_c->zc_string,MAXPATHLEN);
    +		strlcpy(zc->zc_name, zc_c->zc_name, MAXPATHLEN);
    +		strlcpy(zc->zc_value, zc_c->zc_value, MAXPATHLEN);
    +		strlcpy(zc->zc_string, zc_c->zc_string, MAXPATHLEN);
     		zc->zc_guid = zc_c->zc_guid;
     		zc->zc_nvlist_conf = zc_c->zc_nvlist_conf;
     		zc->zc_nvlist_conf_size = zc_c->zc_nvlist_conf_size;
    @@ -91,6 +169,7 @@ zfs_cmd_compat_get(zfs_cmd_t *zc, caddr_t addr, const int cflag)
     		    zc_c->zc_inject_record.zi_freq;
     		zc->zc_inject_record.zi_failfast =
     		    zc_c->zc_inject_record.zi_failfast;
    +		break;
     	}
     }
     
    @@ -98,15 +177,84 @@ void
     zfs_cmd_compat_put(zfs_cmd_t *zc, caddr_t addr, const int cflag)
     {
     	zfs_cmd_v15_t *zc_c;
    +	zfs_cmd_v28_t *zc28_c;
     
     	switch (cflag) {
    +	case ZFS_CMD_COMPAT_V28:
    +		zc28_c = (void *)addr;
    +
    +		strlcpy(zc28_c->zc_name, zc->zc_name, MAXPATHLEN);
    +		strlcpy(zc28_c->zc_value, zc->zc_value, MAXPATHLEN * 2);
    +		strlcpy(zc28_c->zc_string, zc->zc_string, MAXPATHLEN);
    +		strlcpy(zc28_c->zc_top_ds, zc->zc_top_ds, MAXPATHLEN);
    +		zc28_c->zc_guid = zc->zc_guid;
    +		zc28_c->zc_nvlist_conf = zc->zc_nvlist_conf;
    +		zc28_c->zc_nvlist_conf_size = zc->zc_nvlist_conf_size;
    +		zc28_c->zc_nvlist_src = zc->zc_nvlist_src;
    +		zc28_c->zc_nvlist_src_size = zc->zc_nvlist_src_size;
    +		zc28_c->zc_nvlist_dst = zc->zc_nvlist_dst;
    +		zc28_c->zc_nvlist_dst_size = zc->zc_nvlist_dst_size;
    +		zc28_c->zc_cookie = zc->zc_cookie;
    +		zc28_c->zc_objset_type = zc->zc_objset_type;
    +		zc28_c->zc_perm_action = zc->zc_perm_action;
    +		zc28_c->zc_history = zc->zc_history;
    +		zc28_c->zc_history_len = zc->zc_history_len;
    +		zc28_c->zc_history_offset = zc->zc_history_offset;
    +		zc28_c->zc_obj = zc->zc_obj;
    +		zc28_c->zc_iflags = zc->zc_iflags;
    +		zc28_c->zc_share = zc->zc_share;
    +		zc28_c->zc_jailid = zc->zc_jailid;
    +		zc28_c->zc_objset_stats = zc->zc_objset_stats;
    +		zc28_c->zc_begin_record = zc->zc_begin_record;
    +		zc28_c->zc_defer_destroy = zc->zc_defer_destroy;
    +		zc28_c->zc_temphold = zc->zc_temphold;
    +		zc28_c->zc_action_handle = zc->zc_action_handle;
    +		zc28_c->zc_cleanup_fd = zc->zc_cleanup_fd;
    +		zc28_c->zc_simple = zc->zc_simple;
    +		bcopy(zc->zc_pad, zc28_c->zc_pad, sizeof(zc28_c->zc_pad));
    +		zc28_c->zc_sendobj = zc->zc_sendobj;
    +		zc28_c->zc_fromobj = zc->zc_fromobj;
    +		zc28_c->zc_createtxg = zc->zc_createtxg;
    +		zc28_c->zc_stat = zc->zc_stat;
    +
    +		/* zc_inject_record */
    +		zc28_c->zc_inject_record.zi_objset =
    +		    zc->zc_inject_record.zi_objset;
    +		zc28_c->zc_inject_record.zi_object =
    +		    zc->zc_inject_record.zi_object;
    +		zc28_c->zc_inject_record.zi_start =
    +		    zc->zc_inject_record.zi_start;
    +		zc28_c->zc_inject_record.zi_end =
    +		    zc->zc_inject_record.zi_end;
    +		zc28_c->zc_inject_record.zi_guid =
    +		    zc->zc_inject_record.zi_guid;
    +		zc28_c->zc_inject_record.zi_level =
    +		    zc->zc_inject_record.zi_level;
    +		zc28_c->zc_inject_record.zi_error =
    +		    zc->zc_inject_record.zi_error;
    +		zc28_c->zc_inject_record.zi_type =
    +		    zc->zc_inject_record.zi_type;
    +		zc28_c->zc_inject_record.zi_freq =
    +		    zc->zc_inject_record.zi_freq;
    +		zc28_c->zc_inject_record.zi_failfast =
    +		    zc->zc_inject_record.zi_failfast;
    +		strlcpy(zc28_c->zc_inject_record.zi_func,
    +		    zc->zc_inject_record.zi_func, MAXNAMELEN);
    +		zc28_c->zc_inject_record.zi_iotype =
    +		    zc->zc_inject_record.zi_iotype;
    +		zc28_c->zc_inject_record.zi_duration =
    +		    zc->zc_inject_record.zi_duration;
    +		zc28_c->zc_inject_record.zi_timer =
    +		    zc->zc_inject_record.zi_timer;
    +		break;
    +
     	case ZFS_CMD_COMPAT_V15:
     		zc_c = (void *)addr;
     
     		/* zc */
    -		strlcpy(zc_c->zc_name,zc->zc_name,MAXPATHLEN);
    -		strlcpy(zc_c->zc_value,zc->zc_value,MAXPATHLEN);
    -		strlcpy(zc_c->zc_string,zc->zc_string,MAXPATHLEN);
    +		strlcpy(zc_c->zc_name, zc->zc_name, MAXPATHLEN);
    +		strlcpy(zc_c->zc_value, zc->zc_value, MAXPATHLEN);
    +		strlcpy(zc_c->zc_string, zc->zc_string, MAXPATHLEN);
     		zc_c->zc_guid = zc->zc_guid;
     		zc_c->zc_nvlist_conf = zc->zc_nvlist_conf;
     		zc_c->zc_nvlist_conf_size = zc->zc_nvlist_conf_size;
    @@ -260,7 +408,7 @@ zfs_ioctl_compat_fix_stats_nvlist(nvlist_t *nvl)
     }
     
     static int
    -zfs_ioctl_compat_fix_stats(zfs_cmd_t *zc, const int cflag)
    +zfs_ioctl_compat_fix_stats(zfs_cmd_t *zc, const int nc)
     {
     	nvlist_t *nv, *nvp = NULL;
     	nvpair_t *elem;
    @@ -270,7 +418,7 @@ zfs_ioctl_compat_fix_stats(zfs_cmd_t *zc, const int cflag)
     	    zc->zc_nvlist_dst_size, zc->zc_iflags, &nv)) != 0)
     		return (error);
     
    -	if (cflag == 5) { /* ZFS_IOC_POOL_STATS */
    +	if (nc == 5) { /* ZFS_IOC_POOL_STATS */
     		elem = NULL;
     		while ((elem = nvlist_next_nvpair(nv, elem)) != NULL) {
     			if (nvpair_value_nvlist(elem, &nvp) == 0)
    @@ -334,17 +482,22 @@ zcmd_ioctl_compat(int fd, unsigned long cmd, zfs_cmd_t *zc, const int cflag)
     	void *zc_c;
     	unsigned long ncmd;
     
    -	if (cflag == ZFS_CMD_COMPAT_NONE) {
    +	switch (cflag) {
    +	case ZFS_CMD_COMPAT_NONE:
     		ret = ioctl(fd, cmd, zc);
     		return (ret);
    -	}
    -
    -	if (cflag == ZFS_CMD_COMPAT_V15) {
    +	case ZFS_CMD_COMPAT_V28:
    +		zc_c = malloc(sizeof(zfs_cmd_v28_t));
    +		ncmd = _IOWR('Z', ZFS_IOC(cmd), struct zfs_cmd_v28);
    +		break;
    +	case ZFS_CMD_COMPAT_V15:
     		nc = zfs_ioctl_v28_to_v15[ZFS_IOC(cmd)];
     		zc_c = malloc(sizeof(zfs_cmd_v15_t));
     		ncmd = _IOWR('Z', nc, struct zfs_cmd_v15);
    -	} else
    +		break;
    +	default:
     		return (EINVAL);
    +	}
     
     	if (ZFS_IOC(ncmd) == ZFS_IOC_COMPAT_FAIL)
     		return (ENOTSUP);
    @@ -358,16 +511,18 @@ zcmd_ioctl_compat(int fd, unsigned long cmd, zfs_cmd_t *zc, const int cflag)
     	zfs_cmd_compat_get(zc, (caddr_t)zc_c, cflag);
     	free(zc_c);
     
    -	switch (nc) {
    -	case 2:	/* ZFS_IOC_POOL_IMPORT */
    -	case 4: /* ZFS_IOC_POOL_CONFIGS */
    -	case 5: /* ZFS_IOC_POOL_STATS */
    -	case 6: /* ZFS_IOC_POOL_TRYIMPORT */
    -		zfs_ioctl_compat_fix_stats(zc, nc);
    -		break;
    -	case 41: /* ZFS_IOC_POOL_GET_PROPS (v15) */
    -		zfs_ioctl_compat_pool_get_props(zc);
    -		break;
    +	if (cflag == ZFS_CMD_COMPAT_V15) {
    +		switch (nc) {
    +		case 2:	/* ZFS_IOC_POOL_IMPORT */
    +		case 4: /* ZFS_IOC_POOL_CONFIGS */
    +		case 5: /* ZFS_IOC_POOL_STATS */
    +		case 6: /* ZFS_IOC_POOL_TRYIMPORT */
    +			zfs_ioctl_compat_fix_stats(zc, nc);
    +			break;
    +		case 41: /* ZFS_IOC_POOL_GET_PROPS (v15) */
    +			zfs_ioctl_compat_pool_get_props(zc);
    +			break;
    +		}
     	}
     
     	return (ret);
    diff --git a/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.h b/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.h
    index 03d648c9ea1..b20cecafc74 100644
    --- a/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.h
    +++ b/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.h
    @@ -19,7 +19,7 @@
      * CDDL HEADER END
      */
     /*
    - * Copyright 2010 Martin Matuska .  All rights reserved.
    + * Copyright 2013 Martin Matuska .  All rights reserved.
      * Use is subject to license terms.
      */
     
    @@ -40,11 +40,21 @@
     extern "C" {
     #endif
     
    -#define ZFS_CMD_COMPAT_NONE	0
    -#define	ZFS_CMD_COMPAT_V15	1
    +/*
    + * Backwards ioctl compatibility
    + */
     
    -#define ZFS_IOC_COMPAT_PASS	254
    -#define ZFS_IOC_COMPAT_FAIL	255
    +/* ioctl versions for vfs.zfs.version.ioctl */
    +#define	ZFS_IOCVER_DEADMAN	1
    +#define	ZFS_IOCVER_CURRENT	ZFS_IOCVER_DEADMAN
    +
    +/* compatibility conversion flag */
    +#define	ZFS_CMD_COMPAT_NONE	0
    +#define	ZFS_CMD_COMPAT_V15	1
    +#define	ZFS_CMD_COMPAT_V28	2
    +
    +#define	ZFS_IOC_COMPAT_PASS	254
    +#define	ZFS_IOC_COMPAT_FAIL	255
     
     typedef struct zinject_record_v15 {
     	uint64_t	zi_objset;
    @@ -84,6 +94,60 @@ typedef struct zfs_cmd_v15 {
     	zinject_record_v15_t zc_inject_record;
     } zfs_cmd_v15_t;
     
    +typedef struct zinject_record_v28 {
    +	uint64_t	zi_objset;
    +	uint64_t	zi_object;
    +	uint64_t	zi_start;
    +	uint64_t	zi_end;
    +	uint64_t	zi_guid;
    +	uint32_t	zi_level;
    +	uint32_t	zi_error;
    +	uint64_t	zi_type;
    +	uint32_t	zi_freq;
    +	uint32_t	zi_failfast;
    +	char		zi_func[MAXNAMELEN];
    +	uint32_t	zi_iotype;
    +	int32_t		zi_duration;
    +	uint64_t	zi_timer;
    +} zinject_record_v28_t;
    +
    +typedef struct zfs_cmd_v28 {
    +	char		zc_name[MAXPATHLEN];
    +	char		zc_value[MAXPATHLEN * 2];
    +	char		zc_string[MAXNAMELEN];
    +	char		zc_top_ds[MAXPATHLEN];
    +	uint64_t	zc_guid;
    +	uint64_t	zc_nvlist_conf;		/* really (char *) */
    +	uint64_t	zc_nvlist_conf_size;
    +	uint64_t	zc_nvlist_src;		/* really (char *) */
    +	uint64_t	zc_nvlist_src_size;
    +	uint64_t	zc_nvlist_dst;		/* really (char *) */
    +	uint64_t	zc_nvlist_dst_size;
    +	uint64_t	zc_cookie;
    +	uint64_t	zc_objset_type;
    +	uint64_t	zc_perm_action;
    +	uint64_t 	zc_history;		/* really (char *) */
    +	uint64_t 	zc_history_len;
    +	uint64_t	zc_history_offset;
    +	uint64_t	zc_obj;
    +	uint64_t	zc_iflags;		/* internal to zfs(7fs) */
    +	zfs_share_t	zc_share;
    +	uint64_t	zc_jailid;
    +	dmu_objset_stats_t zc_objset_stats;
    +	struct drr_begin zc_begin_record;
    +	zinject_record_v28_t zc_inject_record;
    +	boolean_t	zc_defer_destroy;
    +	boolean_t	zc_temphold;
    +	uint64_t	zc_action_handle;
    +	int		zc_cleanup_fd;
    +	uint8_t		zc_simple;
    +	uint8_t		zc_pad[3];		/* alignment */
    +	uint64_t	zc_sendobj;
    +	uint64_t	zc_fromobj;
    +	uint64_t	zc_createtxg;
    +	zfs_stat_t	zc_stat;
    +} zfs_cmd_v28_t;
    +
     #ifdef _KERNEL
     unsigned static long zfs_ioctl_v15_to_v28[] = {
     	0,	/*  0 ZFS_IOC_POOL_CREATE */
    diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
    index 9925a3bb50c..af0c9f75d33 100644
    --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
    +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
    @@ -23,7 +23,7 @@
      * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
      * Copyright (c) 2011-2012 Pawel Jakub Dawidek .
      * All rights reserved.
    - * Portions Copyright 2011 Martin Matuska 
    + * Copyright 2013 Martin Matuska . All rights reserved.
      * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
      * Copyright (c) 2012 by Delphix. All rights reserved.
      * Copyright (c) 2012, Joyent, Inc. All rights reserved.
    @@ -5331,12 +5331,14 @@ zfsdev_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
     	len = IOCPARM_LEN(cmd);
     
     	/*
    -	 * Check if we have sufficient kernel memory allocated
    -	 * for the zfs_cmd_t request.  Bail out if not so we
    -	 * will not access undefined memory region.
    +	 * Check if we are talking to supported older binaries
    +	 * and translate zfs_cmd if necessary
     	 */
     	if (len < sizeof(zfs_cmd_t))
    -		if (len == sizeof(zfs_cmd_v15_t)) {
    +		if (len == sizeof(zfs_cmd_v28_t)) {
    +			cflag = ZFS_CMD_COMPAT_V28;
    +			vec = ZFS_IOC(cmd);
    +		} else if (len == sizeof(zfs_cmd_v15_t)) {
     			cflag = ZFS_CMD_COMPAT_V15;
     			vec = zfs_ioctl_v15_to_v28[ZFS_IOC(cmd)];
     		} else
    @@ -5351,6 +5353,11 @@ zfsdev_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
     			return (ENOTSUP);
     	}
     
    +	/*
    +	 * Check if we have sufficient kernel memory allocated
    +	 * for the zfs_cmd_t request.  Bail out if not so we
    +	 * will not access undefined memory region.
    +	 */
     	if (vec >= sizeof (zfs_ioc_vec) / sizeof (zfs_ioc_vec[0]))
     		return (EINVAL);
     
    
    From 5ee74037312107c15df0caf9ac8e636c0e348df3 Mon Sep 17 00:00:00 2001
    From: Kevin Lo 
    Date: Fri, 1 Mar 2013 15:45:57 +0000
    Subject: [PATCH 0491/1476] Assign the len field of the netbuf structure to the
     current length of a sockaddr.
    
    Obtained from:	NetBSD
    ---
     lib/libc/rpc/clnt_vc.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/lib/libc/rpc/clnt_vc.c b/lib/libc/rpc/clnt_vc.c
    index 881f84d181d..53e393eff75 100644
    --- a/lib/libc/rpc/clnt_vc.c
    +++ b/lib/libc/rpc/clnt_vc.c
    @@ -260,7 +260,7 @@ clnt_vc_create(fd, raddr, prog, vers, sendsz, recvsz)
     	if (ct->ct_addr.buf == NULL)
     		goto err;
     	memcpy(ct->ct_addr.buf, raddr->buf, raddr->len);
    -	ct->ct_addr.len = raddr->maxlen;
    +	ct->ct_addr.len = raddr->len;
     	ct->ct_addr.maxlen = raddr->maxlen;
     
     	/*
    
    From 130f254b211749d2540ee7d20fbaab9f313add6b Mon Sep 17 00:00:00 2001
    From: Kevin Lo 
    Date: Fri, 1 Mar 2013 15:48:31 +0000
    Subject: [PATCH 0492/1476] Fix typo.
    
    ---
     sys/dev/tws/tws_hdm.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/sys/dev/tws/tws_hdm.c b/sys/dev/tws/tws_hdm.c
    index 3f6bea0cba9..f5bb3f16a63 100644
    --- a/sys/dev/tws/tws_hdm.c
    +++ b/sys/dev/tws/tws_hdm.c
    @@ -99,7 +99,7 @@ tws_init_ctlr(struct tws_softc *sc)
             regh = tws_read_reg(sc, TWS_I2O0_IOPOBQPH, 4);
             regl = tws_read_reg(sc, TWS_I2O0_IOPOBQPL, 4);
             reg = (((u_int64_t)regh) << 32) | regl;
    -        TWS_TRACE_DEBUG(sc, "host outbound clenup",reg, regl);
    +        TWS_TRACE_DEBUG(sc, "host outbound cleanup",reg, regl);
             if ( regh == TWS_FIFO_EMPTY32 )
                 break;
         } 
    
    From 58248e57ab7ee2dcdd4c8da4d1c713dbb45e288e Mon Sep 17 00:00:00 2001
    From: Konstantin Belousov 
    Date: Fri, 1 Mar 2013 18:40:14 +0000
    Subject: [PATCH 0493/1476] Make the default implementation of the
     VOP_VPTOCNP() fail if the directory entry, matched by the inode number, is
     ".".
    
    NFSv4 client might instantiate the distinct vnodes which have the same
    inode number, since single v4 export can be combined from several
    filesystems on the server.  For instance, a case when the nested
    server mount point is exactly one directory below the top of the
    export, causes directory and its parent to have the same inode number
    2.  The vop_stdvptocnp() algorithm then returns "." as the name of the
    lower directory.
    
    Filtering out the "." entry with ENOENT works around this behaviour,
    the error forces getcwd(3) to fall back to usermode implementation,
    which compares both st_dev and st_ino.
    
    Based on the submission by:	rmacklem
    Tested by:	rmacklem
    MFC after:	1 week
    ---
     sys/kern/vfs_default.c | 8 ++++++--
     1 file changed, 6 insertions(+), 2 deletions(-)
    
    diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c
    index 00d064e3d14..1dd0185ce90 100644
    --- a/sys/kern/vfs_default.c
    +++ b/sys/kern/vfs_default.c
    @@ -856,8 +856,12 @@ vop_stdvptocnp(struct vop_vptocnp_args *ap)
     				error = ENOMEM;
     				goto out;
     			}
    -			bcopy(dp->d_name, buf + i, dp->d_namlen);
    -			error = 0;
    +			if (dp->d_namlen == 1 && dp->d_name[0] == '.') {
    +				error = ENOENT;
    +			} else {
    +				bcopy(dp->d_name, buf + i, dp->d_namlen);
    +				error = 0;
    +			}
     			goto out;
     		}
     	} while (len > 0 || !eofflag);
    
    From db9066f7981a4532c4054d5a2a24ff1032eb8a7d Mon Sep 17 00:00:00 2001
    From: Marius Strobl 
    Date: Fri, 1 Mar 2013 18:49:14 +0000
    Subject: [PATCH 0494/1476] - Use strdup(9) instead of reimplementing it. - Use
     __DECONST instead of strange casts. - Reduce code duplication and simplify
     name2oid().
    
    PR:		176373
    Submitted by:	Christoph Mallon
    MFC after:	1 week
    ---
     sys/kern/kern_sysctl.c | 70 +++++++++++-------------------------------
     1 file changed, 18 insertions(+), 52 deletions(-)
    
    diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c
    index 33296d3c077..68bf453f8c1 100644
    --- a/sys/kern/kern_sysctl.c
    +++ b/sys/kern/kern_sysctl.c
    @@ -444,9 +444,9 @@ sysctl_remove_oid_locked(struct sysctl_oid *oidp, int del, int recurse)
     				SYSCTL_SLEEP(&oidp->oid_running, "oidrm", 0);
     			}
     			if (oidp->oid_descr)
    -				free((void *)(uintptr_t)(const void *)oidp->oid_descr, M_SYSCTLOID);
    -			free((void *)(uintptr_t)(const void *)oidp->oid_name,
    -			     M_SYSCTLOID);
    +				free(__DECONST(char *, oidp->oid_descr),
    +				    M_SYSCTLOID);
    +			free(__DECONST(char *, oidp->oid_name), M_SYSCTLOID);
     			free(oidp, M_SYSCTLOID);
     		}
     	}
    @@ -462,8 +462,6 @@ sysctl_add_oid(struct sysctl_ctx_list *clist, struct sysctl_oid_list *parent,
     	int (*handler)(SYSCTL_HANDLER_ARGS), const char *fmt, const char *descr)
     {
     	struct sysctl_oid *oidp;
    -	ssize_t len;
    -	char *newname;
     
     	/* You have to hook up somewhere.. */
     	if (parent == NULL)
    @@ -490,11 +488,7 @@ sysctl_add_oid(struct sysctl_ctx_list *clist, struct sysctl_oid_list *parent,
     	SLIST_NEXT(oidp, oid_link) = NULL;
     	oidp->oid_number = number;
     	oidp->oid_refcnt = 1;
    -	len = strlen(name);
    -	newname = malloc(len + 1, M_SYSCTLOID, M_WAITOK);
    -	bcopy(name, newname, len + 1);
    -	newname[len] = '\0';
    -	oidp->oid_name = newname;
    +	oidp->oid_name = strdup(name, M_SYSCTLOID);
     	oidp->oid_handler = handler;
     	oidp->oid_kind = CTLFLAG_DYN | kind;
     	if ((kind & CTLTYPE) == CTLTYPE_NODE) {
    @@ -508,12 +502,8 @@ sysctl_add_oid(struct sysctl_ctx_list *clist, struct sysctl_oid_list *parent,
     		oidp->oid_arg2 = arg2;
     	}
     	oidp->oid_fmt = fmt;
    -	if (descr) {
    -		int len = strlen(descr) + 1;
    -		oidp->oid_descr = malloc(len, M_SYSCTLOID, M_WAITOK);
    -		if (oidp->oid_descr)
    -			strcpy((char *)(uintptr_t)(const void *)oidp->oid_descr, descr);
    -	}
    +	if (descr)
    +		oidp->oid_descr = strdup(descr, M_SYSCTLOID);
     	/* Update the context, if used */
     	if (clist != NULL)
     		sysctl_ctx_entry_add(clist, oidp);
    @@ -529,16 +519,12 @@ sysctl_add_oid(struct sysctl_ctx_list *clist, struct sysctl_oid_list *parent,
     void
     sysctl_rename_oid(struct sysctl_oid *oidp, const char *name)
     {
    -	ssize_t len;
     	char *newname;
    -	void *oldname;
    +	char *oldname;
     
    -	len = strlen(name);
    -	newname = malloc(len + 1, M_SYSCTLOID, M_WAITOK);
    -	bcopy(name, newname, len + 1);
    -	newname[len] = '\0';
    +	newname = strdup(name, M_SYSCTLOID);
     	SYSCTL_XLOCK();
    -	oldname = (void *)(uintptr_t)(const void *)oidp->oid_name;
    +	oldname = __DECONST(char *, oidp->oid_name);
     	oidp->oid_name = newname;
     	SYSCTL_XUNLOCK();
     	free(oldname, M_SYSCTLOID);
    @@ -823,39 +809,26 @@ static SYSCTL_NODE(_sysctl, 2, next, CTLFLAG_RD | CTLFLAG_CAPRD,
     static int
     name2oid(char *name, int *oid, int *len, struct sysctl_oid **oidpp)
     {
    -	int i;
     	struct sysctl_oid *oidp;
     	struct sysctl_oid_list *lsp = &sysctl__children;
     	char *p;
     
     	SYSCTL_ASSERT_XLOCKED();
     
    -	if (!*name)
    -		return (ENOENT);
    +	for (*len = 0; *len < CTL_MAXNAME;) {
    +		p = strsep(&name, ".");
     
    -	p = name + strlen(name) - 1 ;
    -	if (*p == '.')
    -		*p = '\0';
    -
    -	*len = 0;
    -
    -	for (p = name; *p && *p != '.'; p++) 
    -		;
    -	i = *p;
    -	if (i == '.')
    -		*p = '\0';
    -
    -	oidp = SLIST_FIRST(lsp);
    -
    -	while (oidp && *len < CTL_MAXNAME) {
    -		if (strcmp(name, oidp->oid_name)) {
    -			oidp = SLIST_NEXT(oidp, oid_link);
    -			continue;
    +		oidp = SLIST_FIRST(lsp);
    +		for (;; oidp = SLIST_NEXT(oidp, oid_link)) {
    +			if (oidp == NULL)
    +				return (ENOENT);
    +			if (strcmp(p, oidp->oid_name) == 0)
    +				break;
     		}
     		*oid++ = oidp->oid_number;
     		(*len)++;
     
    -		if (!i) {
    +		if (name == NULL || *name == '\0') {
     			if (oidpp)
     				*oidpp = oidp;
     			return (0);
    @@ -868,13 +841,6 @@ name2oid(char *name, int *oid, int *len, struct sysctl_oid **oidpp)
     			break;
     
     		lsp = SYSCTL_CHILDREN(oidp);
    -		oidp = SLIST_FIRST(lsp);
    -		name = p+1;
    -		for (p = name; *p && *p != '.'; p++) 
    -				;
    -		i = *p;
    -		if (i == '.')
    -			*p = '\0';
     	}
     	return (ENOENT);
     }
    
    From 1f9d53d89350873d962cc4c67a89d66d694c6418 Mon Sep 17 00:00:00 2001
    From: Alan Cox 
    Date: Fri, 1 Mar 2013 19:02:41 +0000
    Subject: [PATCH 0495/1476] Eliminate a redundant #include: machine/pmap.h is
     already included through vm/pmap.h.
    
    ---
     sys/arm/econa/econa_machdep.c           | 1 -
     sys/arm/s3c2xx0/s3c24x0_machdep.c       | 1 -
     sys/arm/xscale/i80321/ep80219_machdep.c | 1 -
     sys/arm/xscale/i80321/iq31244_machdep.c | 1 -
     sys/arm/xscale/i8134x/crb_machdep.c     | 1 -
     sys/arm/xscale/ixp425/avila_machdep.c   | 1 -
     sys/arm/xscale/pxa/pxa_machdep.c        | 1 -
     7 files changed, 7 deletions(-)
    
    diff --git a/sys/arm/econa/econa_machdep.c b/sys/arm/econa/econa_machdep.c
    index d622860b964..d64e826d1e7 100644
    --- a/sys/arm/econa/econa_machdep.c
    +++ b/sys/arm/econa/econa_machdep.c
    @@ -68,7 +68,6 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     #include 
     #include 
     #include 
    diff --git a/sys/arm/s3c2xx0/s3c24x0_machdep.c b/sys/arm/s3c2xx0/s3c24x0_machdep.c
    index e497bc4e2ed..1811b520189 100644
    --- a/sys/arm/s3c2xx0/s3c24x0_machdep.c
    +++ b/sys/arm/s3c2xx0/s3c24x0_machdep.c
    @@ -78,7 +78,6 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     #include 
     #include 
     #include 
    diff --git a/sys/arm/xscale/i80321/ep80219_machdep.c b/sys/arm/xscale/i80321/ep80219_machdep.c
    index cb3d161d16c..ff2f1c3151a 100644
    --- a/sys/arm/xscale/i80321/ep80219_machdep.c
    +++ b/sys/arm/xscale/i80321/ep80219_machdep.c
    @@ -78,7 +78,6 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     #include 
     #include 
     #include 
    diff --git a/sys/arm/xscale/i80321/iq31244_machdep.c b/sys/arm/xscale/i80321/iq31244_machdep.c
    index 2375b6bc48d..1412635c295 100644
    --- a/sys/arm/xscale/i80321/iq31244_machdep.c
    +++ b/sys/arm/xscale/i80321/iq31244_machdep.c
    @@ -78,7 +78,6 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     #include 
     #include 
     #include 
    diff --git a/sys/arm/xscale/i8134x/crb_machdep.c b/sys/arm/xscale/i8134x/crb_machdep.c
    index a1344afb3b0..4ae836bb80c 100644
    --- a/sys/arm/xscale/i8134x/crb_machdep.c
    +++ b/sys/arm/xscale/i8134x/crb_machdep.c
    @@ -78,7 +78,6 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     #include 
     #include 
     #include 
    diff --git a/sys/arm/xscale/ixp425/avila_machdep.c b/sys/arm/xscale/ixp425/avila_machdep.c
    index 07026da89e7..82e1aab004c 100644
    --- a/sys/arm/xscale/ixp425/avila_machdep.c
    +++ b/sys/arm/xscale/ixp425/avila_machdep.c
    @@ -78,7 +78,6 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     #include 
     #include 
     #include 
    diff --git a/sys/arm/xscale/pxa/pxa_machdep.c b/sys/arm/xscale/pxa/pxa_machdep.c
    index 706fb588797..5640622aef3 100644
    --- a/sys/arm/xscale/pxa/pxa_machdep.c
    +++ b/sys/arm/xscale/pxa/pxa_machdep.c
    @@ -80,7 +80,6 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    -#include 
     #include 
     #include 
     #include 
    
    From 499e58864ac54d3ac095604b7bce2aed354a38fd Mon Sep 17 00:00:00 2001
    From: Marius Strobl 
    Date: Fri, 1 Mar 2013 19:12:38 +0000
    Subject: [PATCH 0496/1476] - Make tables, device ID strings etc const. - Use
     NULL instead of 0 for pointers. - Remove redundant bzero(9)'ing of the softc.
     - Remove redundant/unused softc members. - Don't allocate MSI/MSI-X as
     RF_SHAREABLE. - Re-use bus accessor macros instead of duplicating them. - In
     bce_miibus_{read,write}_reg(), remove superfluous limiting of the PHY  
     address (missed in r213893).
    
    MFC after:	1 week
    ---
     sys/dev/bce/if_bce.c    | 71 +++++++++++++++--------------------------
     sys/dev/bce/if_bcereg.h | 22 ++++++-------
     2 files changed, 34 insertions(+), 59 deletions(-)
    
    diff --git a/sys/dev/bce/if_bce.c b/sys/dev/bce/if_bce.c
    index 2471f1926cc..8f6bc486d43 100644
    --- a/sys/dev/bce/if_bce.c
    +++ b/sys/dev/bce/if_bce.c
    @@ -95,7 +95,7 @@ __FBSDID("$FreeBSD$");
     /****************************************************************************/
     #define BCE_DEVDESC_MAX		64
     
    -static struct bce_type bce_devs[] = {
    +static const struct bce_type bce_devs[] = {
     	/* BCM5706C Controllers and OEM boards. */
     	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5706,  HP_VENDORID, 0x3101,
     		"HP NC370T Multifunction Gigabit Server Adapter" },
    @@ -161,7 +161,7 @@ static struct bce_type bce_devs[] = {
     /****************************************************************************/
     /* Supported Flash NVRAM device data.                                       */
     /****************************************************************************/
    -static struct flash_spec flash_table[] =
    +static const struct flash_spec flash_table[] =
     {
     #define BUFFERED_FLAGS		(BCE_NV_BUFFERED | BCE_NV_TRANSLATE)
     #define NONBUFFERED_FLAGS	(BCE_NV_WREN)
    @@ -258,7 +258,7 @@ static struct flash_spec flash_table[] =
      * logical-to-physical mapping is required in the
      * driver.
      */
    -static struct flash_spec flash_5709 = {
    +static const struct flash_spec flash_5709 = {
     	.flags		= BCE_NV_BUFFERED,
     	.page_bits	= BCM5709_FLASH_PAGE_BITS,
     	.page_size	= BCM5709_FLASH_PAGE_SIZE,
    @@ -481,8 +481,8 @@ MODULE_DEPEND(bce, pci, 1, 1, 1);
     MODULE_DEPEND(bce, ether, 1, 1, 1);
     MODULE_DEPEND(bce, miibus, 1, 1, 1);
     
    -DRIVER_MODULE(bce, pci, bce_driver, bce_devclass, 0, 0);
    -DRIVER_MODULE(miibus, bce, miibus_driver, miibus_devclass, 0, 0);
    +DRIVER_MODULE(bce, pci, bce_driver, bce_devclass, NULL, NULL);
    +DRIVER_MODULE(miibus, bce, miibus_driver, miibus_devclass, NULL, NULL);
     
     
     /****************************************************************************/
    @@ -647,7 +647,7 @@ SYSCTL_UINT(_hw_bce, OID_AUTO, rx_ticks, CTLFLAG_RDTUN,
     static int
     bce_probe(device_t dev)
     {
    -	struct bce_type *t;
    +	const struct bce_type *t;
     	struct bce_softc *sc;
     	char *descbuf;
     	u16 vid = 0, did = 0, svid = 0, sdid = 0;
    @@ -655,7 +655,6 @@ bce_probe(device_t dev)
     	t = bce_devs;
     
     	sc = device_get_softc(dev);
    -	bzero(sc, sizeof(struct bce_softc));
     	sc->bce_unit = device_get_unit(dev);
     	sc->bce_dev = dev;
     
    @@ -1040,7 +1039,7 @@ bce_attach(device_t dev)
     	struct bce_softc *sc;
     	struct ifnet *ifp;
     	u32 val;
    -	int error, rid, rc = 0;
    +	int count, error, rc = 0, rid;
     
     	sc = device_get_softc(dev);
     	sc->bce_dev = dev;
    @@ -1084,14 +1083,14 @@ bce_attach(device_t dev)
     		((sc->bce_res_irq = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
     		&rid, RF_ACTIVE)) != NULL)) {
     
    -		msi_needed = sc->bce_msi_count = 1;
    +		msi_needed = count = 1;
     
    -		if (((error = pci_alloc_msix(dev, &sc->bce_msi_count)) != 0) ||
    -			(sc->bce_msi_count != msi_needed)) {
    +		if (((error = pci_alloc_msix(dev, &count)) != 0) ||
    +			(count != msi_needed)) {
     			BCE_PRINTF("%s(%d): MSI-X allocation failed! Requested = %d,"
     				"Received = %d, error = %d\n", __FILE__, __LINE__,
    -				msi_needed, sc->bce_msi_count, error);
    -			sc->bce_msi_count = 0;
    +				msi_needed, count, error);
    +			count = 0;
     			pci_release_msi(dev);
     			bus_release_resource(dev, SYS_RES_MEMORY, rid,
     				sc->bce_res_irq);
    @@ -1100,19 +1099,18 @@ bce_attach(device_t dev)
     			DBPRINT(sc, BCE_INFO_LOAD, "%s(): Using MSI-X interrupt.\n",
     				__FUNCTION__);
     			sc->bce_flags |= BCE_USING_MSIX_FLAG;
    -			sc->bce_intr = bce_intr;
     		}
     	}
     #endif
     
     	/* Try allocating a MSI interrupt. */
     	if ((sc->bce_cap_flags & BCE_MSI_CAPABLE_FLAG) &&
    -		(bce_msi_enable >= 1) && (sc->bce_msi_count == 0)) {
    -		sc->bce_msi_count = 1;
    -		if ((error = pci_alloc_msi(dev, &sc->bce_msi_count)) != 0) {
    +		(bce_msi_enable >= 1) && (count == 0)) {
    +		count = 1;
    +		if ((error = pci_alloc_msi(dev, &count)) != 0) {
     			BCE_PRINTF("%s(%d): MSI allocation failed! "
     			    "error = %d\n", __FILE__, __LINE__, error);
    -			sc->bce_msi_count = 0;
    +			count = 0;
     			pci_release_msi(dev);
     		} else {
     			DBPRINT(sc, BCE_INFO_LOAD, "%s(): Using MSI "
    @@ -1120,23 +1118,19 @@ bce_attach(device_t dev)
     			sc->bce_flags |= BCE_USING_MSI_FLAG;
     			if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709)
     				sc->bce_flags |= BCE_ONE_SHOT_MSI_FLAG;
    -			sc->bce_irq_rid = 1;
    -			sc->bce_intr = bce_intr;
    +			rid = 1;
     		}
     	}
     
     	/* Try allocating a legacy interrupt. */
    -	if (sc->bce_msi_count == 0) {
    +	if (count == 0) {
     		DBPRINT(sc, BCE_INFO_LOAD, "%s(): Using INTx interrupt.\n",
     			__FUNCTION__);
     		rid = 0;
    -		sc->bce_intr = bce_intr;
     	}
     
     	sc->bce_res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
    -	    &rid, RF_SHAREABLE | RF_ACTIVE);
    -
    -	sc->bce_irq_rid = rid;
    +	    &rid, RF_ACTIVE | (count != 0 ? 0 : RF_SHAREABLE));
     
     	/* Report any IRQ allocation errors. */
     	if (sc->bce_res_irq == NULL) {
    @@ -1635,7 +1629,7 @@ bce_shutdown(device_t dev)
     static u32
     bce_reg_rd(struct bce_softc *sc, u32 offset)
     {
    -	u32 val = bus_space_read_4(sc->bce_btag, sc->bce_bhandle, offset);
    +	u32 val = REG_RD(sc, offset);
     	DBPRINT(sc, BCE_INSANE_REG, "%s(); offset = 0x%08X, val = 0x%08X\n",
     		__FUNCTION__, offset, val);
     	return val;
    @@ -1653,7 +1647,7 @@ bce_reg_wr16(struct bce_softc *sc, u32 offset, u16 val)
     {
     	DBPRINT(sc, BCE_INSANE_REG, "%s(); offset = 0x%08X, val = 0x%04X\n",
     		__FUNCTION__, offset, val);
    -	bus_space_write_2(sc->bce_btag, sc->bce_bhandle, offset, val);
    +	REG_WR16(sc, offset, val);
     }
     
     
    @@ -1668,7 +1662,7 @@ bce_reg_wr(struct bce_softc *sc, u32 offset, u32 val)
     {
     	DBPRINT(sc, BCE_INSANE_REG, "%s(); offset = 0x%08X, val = 0x%08X\n",
     		__FUNCTION__, offset, val);
    -	bus_space_write_4(sc->bce_btag, sc->bce_bhandle, offset, val);
    +	REG_WR(sc, offset, val);
     }
     #endif
     
    @@ -1879,13 +1873,6 @@ bce_miibus_read_reg(device_t dev, int phy, int reg)
     
     	sc = device_get_softc(dev);
     
    -	/* Make sure we are accessing the correct PHY address. */
    -	if (phy != sc->bce_phy_addr) {
    -		DBPRINT(sc, BCE_INSANE_PHY, "Invalid PHY address %d "
    -		    "for PHY read!\n", phy);
    -		return(0);
    -	}
    -
         /*
          * The 5709S PHY is an IEEE Clause 45 PHY
          * with special mappings to work with IEEE
    @@ -1968,13 +1955,6 @@ bce_miibus_write_reg(device_t dev, int phy, int reg, int val)
     
     	sc = device_get_softc(dev);
     
    -	/* Make sure we are accessing the correct PHY address. */
    -	if (phy != sc->bce_phy_addr) {
    -		DBPRINT(sc, BCE_INSANE_PHY, "Invalid PHY address %d "
    -		    "for PHY write!\n", phy);
    -		return(0);
    -	}
    -
     	DB_PRINT_PHY_REG(reg, val);
     
     	/*
    @@ -2535,7 +2515,7 @@ bce_init_nvram(struct bce_softc *sc)
     {
     	u32 val;
     	int j, entry_count, rc = 0;
    -	struct flash_spec *flash;
    +	const struct flash_spec *flash;
     
     	DBENTER(BCE_VERBOSE_NVRAM);
     
    @@ -3949,8 +3929,8 @@ bce_release_resources(struct bce_softc *sc)
     
     	if (sc->bce_res_irq != NULL) {
     		DBPRINT(sc, BCE_INFO_RESET, "Releasing IRQ.\n");
    -		bus_release_resource(dev, SYS_RES_IRQ, sc->bce_irq_rid,
    -		    sc->bce_res_irq);
    +		bus_release_resource(dev, SYS_RES_IRQ,
    +		    rman_get_rid(sc->bce_res_irq), sc->bce_res_irq);
     	}
     
     	if (sc->bce_flags & (BCE_USING_MSI_FLAG | BCE_USING_MSIX_FLAG)) {
    @@ -11650,4 +11630,3 @@ bce_breakpoint(struct bce_softc *sc)
     	return;
     }
     #endif
    -
    diff --git a/sys/dev/bce/if_bcereg.h b/sys/dev/bce/if_bcereg.h
    index fc37b2c75f9..37ff5ed8d3e 100644
    --- a/sys/dev/bce/if_bcereg.h
    +++ b/sys/dev/bce/if_bcereg.h
    @@ -622,7 +622,7 @@ struct bce_type {
     	u_int16_t bce_did;
     	u_int16_t bce_svid;
     	u_int16_t bce_sdid;
    -	char      *bce_name;
    +	const char *bce_name;
     };
     
     /****************************************************************************/
    @@ -716,7 +716,7 @@ struct flash_spec {
     	u32 page_size;
     	u32 addr_mask;
     	u32 total_size;
    -	u8  *name;
    +	const u8 *name;
     };
     
     
    @@ -2001,7 +2001,7 @@ struct l2_fhdr {
     #define BCE_MISC_ENABLE_CLR_BITS_UMP_ENABLE				(1L<<27)
     #define BCE_MISC_ENABLE_CLR_BITS_RV2P_CMD_SCHEDULER_ENABLE	(1L<<28)
     #define BCE_MISC_ENABLE_CLR_BITS_RSVD_FUTURE_ENABLE		(0x7L<<29)
    -
    +
     #define BCE_MISC_ENABLE_CLR_DEFAULT						0x17ffffff
     
     #define BCE_MISC_CLOCK_CONTROL_BITS			0x00000818
    @@ -6318,19 +6318,19 @@ struct fw_info {
     	u32 text_addr;
     	u32 text_len;
     	u32 text_index;
    -	u32 *text;
    +	const u32 *text;
     
     	/* Data section. */
     	u32 data_addr;
     	u32 data_len;
     	u32 data_index;
    -	u32 *data;
    +	const u32 *data;
     
     	/* SBSS section. */
     	u32 sbss_addr;
     	u32 sbss_len;
     	u32 sbss_index;
    -	u32 *sbss;
    +	const u32 *sbss;
     
     	/* BSS section. */
     	u32 bss_addr;
    @@ -6421,7 +6421,7 @@ struct fw_info {
     
     struct bce_softc
     {
    -	/* Interface info.  Must be first!! */
    +	/* Interface info */
     	struct ifnet		*bce_ifp;
     
     	/* Parent device handle */
    @@ -6451,10 +6451,7 @@ struct bce_softc
     	struct mtx		bce_mtx;
     
     	/* Interrupt handler. */
    -	driver_intr_t		*bce_intr;
     	void			*bce_intrhand;
    -	int			bce_irq_rid;
    -	int			bce_msi_count;
     
     	/* ASIC Chip ID. */
     	u32			bce_chipid;
    @@ -6509,7 +6506,7 @@ struct bce_softc
     	u16			link_speed;
     
     	/* Flash NVRAM settings */
    -	struct flash_spec	*bce_flash_info;
    +	const struct flash_spec	*bce_flash_info;
     
     	/* Flash NVRAM size */
     	u32			bce_flash_size;
    @@ -6518,7 +6515,7 @@ struct bce_softc
     	u32			bce_shmem_base;
     
     	/* Name string */
    -	char			*bce_name;
    +	const char		*bce_name;
     
     	/* Tracks the version of bootcode firmware. */
     	char			bce_bc_ver[32];
    @@ -6834,4 +6831,3 @@ struct bce_softc
     };
     
     #endif /* __BCEREG_H_DEFINED */
    -
    
    From da4882c200f116135d9bf2b32dce555ae50a193a Mon Sep 17 00:00:00 2001
    From: Marius Strobl 
    Date: Fri, 1 Mar 2013 19:55:10 +0000
    Subject: [PATCH 0497/1476] - Make tables, device ID strings etc const. This
     includes #ifdef'ing 0   aac_command_status_table, which is actually unused
     since r111532.   While at it, make aac_if a pointer to the now const
     interface tables   instead of copying them over to the softc (this alone
     already reduces the   size of aac.ko on amd64 by ~1 KiB). - Remove redundant
     softc members. - Use DEVMETHOD_END. - Use NULL instead of 0 for pointers. -
     Remove redundant bzero(9)'ing of the softc. - Use pci_enable_busmaster(9)
     instead of duplicating it. - Remove redundant checking for PCIM_CMD_MEMEN
     (resource allocation will   just fail). - Canonicalize the error messages in
     case of resource allocation failures. - Add support for using MSI instead of
     INTx, controllable via the tunable   hw.aac.enable_msi (defaulting to on).
    
    MFC after:	1 month
    ---
     sys/dev/aac/aac.c        | 59 ++++++++++--------------
     sys/dev/aac/aac_cam.c    |  5 +-
     sys/dev/aac/aac_disk.c   |  4 +-
     sys/dev/aac/aac_pci.c    | 98 ++++++++++++++++++++++------------------
     sys/dev/aac/aac_tables.h | 11 +++--
     sys/dev/aac/aacvar.h     | 43 +++++++++---------
     6 files changed, 109 insertions(+), 111 deletions(-)
    
    diff --git a/sys/dev/aac/aac.c b/sys/dev/aac/aac.c
    index 9f315b6307b..d4c73836eca 100644
    --- a/sys/dev/aac/aac.c
    +++ b/sys/dev/aac/aac.c
    @@ -117,7 +117,7 @@ static void	aac_sa_set_mailbox(struct aac_softc *sc, u_int32_t command,
     static int	aac_sa_get_mailbox(struct aac_softc *sc, int mb);
     static void	aac_sa_set_interrupts(struct aac_softc *sc, int enable);
     
    -struct aac_interface aac_sa_interface = {
    +const struct aac_interface aac_sa_interface = {
     	aac_sa_get_fwstatus,
     	aac_sa_qnotify,
     	aac_sa_get_istatus,
    @@ -142,7 +142,7 @@ static int aac_rx_send_command(struct aac_softc *sc, struct aac_command *cm);
     static int aac_rx_get_outb_queue(struct aac_softc *sc);
     static void aac_rx_set_outb_queue(struct aac_softc *sc, int index);
     
    -struct aac_interface aac_rx_interface = {
    +const struct aac_interface aac_rx_interface = {
     	aac_rx_get_fwstatus,
     	aac_rx_qnotify,
     	aac_rx_get_istatus,
    @@ -169,7 +169,7 @@ static int aac_rkt_send_command(struct aac_softc *sc, struct aac_command *cm);
     static int aac_rkt_get_outb_queue(struct aac_softc *sc);
     static void aac_rkt_set_outb_queue(struct aac_softc *sc, int index);
     
    -struct aac_interface aac_rkt_interface = {
    +const struct aac_interface aac_rkt_interface = {
     	aac_rkt_get_fwstatus,
     	aac_rkt_qnotify,
     	aac_rkt_get_istatus,
    @@ -183,8 +183,8 @@ struct aac_interface aac_rkt_interface = {
     };
     
     /* Debugging and Diagnostics */
    -static void	aac_describe_controller(struct aac_softc *sc);
    -static char	*aac_describe_code(struct aac_code_lookup *table,
    +static void		aac_describe_controller(struct aac_softc *sc);
    +static const char	*aac_describe_code(const struct aac_code_lookup *table,
     				   u_int32_t code);
     
     /* Management Interface */
    @@ -222,7 +222,7 @@ static struct cdevsw aac_cdevsw = {
     static MALLOC_DEFINE(M_AACBUF, "aacbuf", "Buffers for the AAC driver");
     
     /* sysctl node */
    -static SYSCTL_NODE(_hw, OID_AUTO, aac, CTLFLAG_RD, 0, "AAC driver parameters");
    +SYSCTL_NODE(_hw, OID_AUTO, aac, CTLFLAG_RD, 0, "AAC driver parameters");
     
     /*
      * Device Interface
    @@ -634,8 +634,8 @@ aac_free(struct aac_softc *sc)
     	if (sc->aac_intr)
     		bus_teardown_intr(sc->aac_dev, sc->aac_irq, sc->aac_intr);
     	if (sc->aac_irq != NULL)
    -		bus_release_resource(sc->aac_dev, SYS_RES_IRQ, sc->aac_irq_rid,
    -				     sc->aac_irq);
    +		bus_release_resource(sc->aac_dev, SYS_RES_IRQ,
    +		    rman_get_rid(sc->aac_irq), sc->aac_irq);
     
     	/* destroy data-transfer DMA tag */
     	if (sc->aac_buffer_dmat)
    @@ -648,10 +648,10 @@ aac_free(struct aac_softc *sc)
     	/* release the register window mapping */
     	if (sc->aac_regs_res0 != NULL)
     		bus_release_resource(sc->aac_dev, SYS_RES_MEMORY,
    -				     sc->aac_regs_rid0, sc->aac_regs_res0);
    +		    rman_get_rid(sc->aac_regs_res0), sc->aac_regs_res0);
     	if (sc->aac_hwif == AAC_HWIF_NARK && sc->aac_regs_res1 != NULL)
     		bus_release_resource(sc->aac_dev, SYS_RES_MEMORY,
    -				     sc->aac_regs_rid1, sc->aac_regs_res1);
    +		    rman_get_rid(sc->aac_regs_res1), sc->aac_regs_res1);
     }
     
     /*
    @@ -1333,9 +1333,6 @@ aac_bio_complete(struct aac_command *cm)
     	} else {
     		bp->bio_error = EIO;
     		bp->bio_flags |= BIO_ERROR;
    -		/* pass an error string out to the disk layer */
    -		bp->bio_driver1 = aac_describe_code(aac_command_status_table,
    -						    status);
     	}
     	aac_biodone(bp);
     }
    @@ -1687,7 +1684,7 @@ static int
     aac_check_firmware(struct aac_softc *sc)
     {
     	u_int32_t code, major, minor, options = 0, atu_size = 0;
    -	int status;
    +	int rid, status;
     	time_t then;
     
     	fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
    @@ -1765,7 +1762,7 @@ aac_check_firmware(struct aac_softc *sc)
     			sc->flags |= AAC_FLAGS_SG_64BIT;
     		}
     		if ((options & AAC_SUPPORTED_NEW_COMM)
    -		 && sc->aac_if.aif_send_command)
    +		 && sc->aac_if->aif_send_command)
     			sc->flags |= AAC_FLAGS_NEW_COMM;
     		if (options & AAC_SUPPORTED_64BIT_ARRAYSIZE)
     			sc->flags |= AAC_FLAGS_ARRAY_64BIT;
    @@ -1776,17 +1773,15 @@ aac_check_firmware(struct aac_softc *sc)
     
     	/* Remap mem. resource, if required */
     	if ((sc->flags & AAC_FLAGS_NEW_COMM) &&
    -		atu_size > rman_get_size(sc->aac_regs_res1)) {
    -		bus_release_resource(
    -			sc->aac_dev, SYS_RES_MEMORY,
    -			sc->aac_regs_rid1, sc->aac_regs_res1);
    -		sc->aac_regs_res1 = bus_alloc_resource(
    -			sc->aac_dev, SYS_RES_MEMORY, &sc->aac_regs_rid1,
    -			0ul, ~0ul, atu_size, RF_ACTIVE);
    +	    atu_size > rman_get_size(sc->aac_regs_res1)) {
    +		rid = rman_get_rid(sc->aac_regs_res1);
    +		bus_release_resource(sc->aac_dev, SYS_RES_MEMORY, rid,
    +		    sc->aac_regs_res1);
    +		sc->aac_regs_res1 = bus_alloc_resource(sc->aac_dev,
    +		    SYS_RES_MEMORY, &rid, 0ul, ~0ul, atu_size, RF_ACTIVE);
     		if (sc->aac_regs_res1 == NULL) {
     			sc->aac_regs_res1 = bus_alloc_resource_any(
    -				sc->aac_dev, SYS_RES_MEMORY,
    -				&sc->aac_regs_rid1, RF_ACTIVE);
    +			    sc->aac_dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
     			if (sc->aac_regs_res1 == NULL) {
     				device_printf(sc->aac_dev,
     				    "couldn't allocate register window\n");
    @@ -1799,7 +1794,6 @@ aac_check_firmware(struct aac_softc *sc)
     
     		if (sc->aac_hwif == AAC_HWIF_NARK) {
     			sc->aac_regs_res0 = sc->aac_regs_res1;
    -			sc->aac_regs_rid0 = sc->aac_regs_rid1;
     			sc->aac_btag0 = sc->aac_btag1;
     			sc->aac_bhandle0 = sc->aac_bhandle1;
     		}
    @@ -2003,14 +1997,7 @@ out:
     static int
     aac_setup_intr(struct aac_softc *sc)
     {
    -	sc->aac_irq_rid = 0;
    -	if ((sc->aac_irq = bus_alloc_resource_any(sc->aac_dev, SYS_RES_IRQ,
    -			   			  &sc->aac_irq_rid,
    -			   			  RF_SHAREABLE |
    -						  RF_ACTIVE)) == NULL) {
    -		device_printf(sc->aac_dev, "can't allocate interrupt\n");
    -		return (EINVAL);
    -	}
    +
     	if (sc->flags & AAC_FLAGS_NEW_COMM) {
     		if (bus_setup_intr(sc->aac_dev, sc->aac_irq,
     				   INTR_MPSAFE|INTR_TYPE_BIO, NULL,
    @@ -2119,7 +2106,7 @@ aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate,
      * Note that the queue implementation here is a little funky; neither the PI or
      * CI will ever be zero.  This behaviour is a controller feature.
      */
    -static struct {
    +static const struct {
     	int		size;
     	int		notify;
     } aac_qinfo[] = {
    @@ -2786,8 +2773,8 @@ aac_describe_controller(struct aac_softc *sc)
      * Look up a text description of a numeric error code and return a pointer to
      * same.
      */
    -static char *
    -aac_describe_code(struct aac_code_lookup *table, u_int32_t code)
    +static const char *
    +aac_describe_code(const struct aac_code_lookup *table, u_int32_t code)
     {
     	int i;
     
    diff --git a/sys/dev/aac/aac_cam.c b/sys/dev/aac/aac_cam.c
    index 7f0d7ee1cdc..60ead24c033 100644
    --- a/sys/dev/aac/aac_cam.c
    +++ b/sys/dev/aac/aac_cam.c
    @@ -92,7 +92,7 @@ static device_method_t	aac_pass_methods[] = {
     	DEVMETHOD(device_probe,		aac_cam_probe),
     	DEVMETHOD(device_attach,	aac_cam_attach),
     	DEVMETHOD(device_detach,	aac_cam_detach),
    -	{ 0, 0 }
    +	DEVMETHOD_END
     };
     
     static driver_t	aac_pass_driver = {
    @@ -101,7 +101,7 @@ static driver_t	aac_pass_driver = {
     	sizeof(struct aac_cam)
     };
     
    -DRIVER_MODULE(aacp, aac, aac_pass_driver, aac_pass_devclass, 0, 0);
    +DRIVER_MODULE(aacp, aac, aac_pass_driver, aac_pass_devclass, NULL, NULL);
     MODULE_DEPEND(aacp, cam, 1, 1, 1);
     
     static MALLOC_DEFINE(M_AACCAM, "aaccam", "AAC CAM info");
    @@ -685,4 +685,3 @@ aac_cam_term_io(struct cam_sim *sim, union ccb *ccb)
     {
     	return (CAM_UA_TERMIO);
     }
    -
    diff --git a/sys/dev/aac/aac_disk.c b/sys/dev/aac/aac_disk.c
    index f2f66361393..082be9b4ca7 100644
    --- a/sys/dev/aac/aac_disk.c
    +++ b/sys/dev/aac/aac_disk.c
    @@ -73,7 +73,7 @@ static device_method_t aac_disk_methods[] = {
     	DEVMETHOD(device_probe,	aac_disk_probe),
     	DEVMETHOD(device_attach,	aac_disk_attach),
     	DEVMETHOD(device_detach,	aac_disk_detach),
    -	{ 0, 0 }
    +	DEVMETHOD_END
     };
     
     static driver_t aac_disk_driver = {
    @@ -82,7 +82,7 @@ static driver_t aac_disk_driver = {
     	sizeof(struct aac_disk)
     };
     
    -DRIVER_MODULE(aacd, aac, aac_disk_driver, aac_disk_devclass, 0, 0);
    +DRIVER_MODULE(aacd, aac, aac_disk_driver, aac_disk_devclass, NULL, NULL);
     
     /*
      * Handle open from generic layer.
    diff --git a/sys/dev/aac/aac_pci.c b/sys/dev/aac/aac_pci.c
    index 163c5ea56c3..87ada1c1446 100644
    --- a/sys/dev/aac/aac_pci.c
    +++ b/sys/dev/aac/aac_pci.c
    @@ -60,6 +60,11 @@ __FBSDID("$FreeBSD$");
     static int	aac_pci_probe(device_t dev);
     static int	aac_pci_attach(device_t dev);
     
    +static int aac_enable_msi = 1;
    +TUNABLE_INT("hw.aac.enable_msi", &aac_enable_msi);
    +SYSCTL_INT(_hw_aac, OID_AUTO, enable_msi, CTLFLAG_RDTUN, &aac_enable_msi, 0,
    +    "Enable MSI interrupts");
    +
     static device_method_t aac_methods[] = {
     	/* Device interface */
     	DEVMETHOD(device_probe,		aac_pci_probe),
    @@ -79,11 +84,10 @@ static driver_t aac_pci_driver = {
     
     static devclass_t	aac_devclass;
     
    -DRIVER_MODULE(aac, pci, aac_pci_driver, aac_devclass, 0, 0);
    +DRIVER_MODULE(aac, pci, aac_pci_driver, aac_devclass, NULL, NULL);
     MODULE_DEPEND(aac, pci, 1, 1, 1);
     
    -
    -struct aac_ident
    +static const struct aac_ident
     {
     	u_int16_t		vendor;
     	u_int16_t		device;
    @@ -91,7 +95,7 @@ struct aac_ident
     	u_int16_t		subdevice;
     	int			hwif;
     	int			quirks;
    -	char			*desc;
    +	const char		*desc;
     } aac_identifiers[] = {
     	{0x1028, 0x0001, 0x1028, 0x0001, AAC_HWIF_I960RX, 0,
     	"Dell PERC 2/Si"},
    @@ -139,7 +143,6 @@ struct aac_ident
     	 "Adaptec SCSI RAID 2230S"},
     	{0x9005, 0x0286, 0x9005, 0x028d, AAC_HWIF_RKT, 0,
     	 "Adaptec SCSI RAID 2130S"},
    -
     	{0x9005, 0x0285, 0x9005, 0x0287, AAC_HWIF_I960RX, AAC_FLAGS_NO4GB |
     	 AAC_FLAGS_256FIBS, "Adaptec SCSI RAID 2200S"},
     	{0x9005, 0x0285, 0x17aa, 0x0286, AAC_HWIF_I960RX, AAC_FLAGS_NO4GB |
    @@ -276,7 +279,8 @@ struct aac_ident
     	 "AOC-USAS-S8iR-LP"},
     	{0, 0, 0, 0, 0, 0, 0}
     };
    -struct aac_ident
    +
    +static const struct aac_ident
     aac_family_identifiers[] = {
     	{0x9005, 0x0285, 0, 0, AAC_HWIF_I960RX, 0,
     	 "Adaptec RAID Controller"},
    @@ -285,10 +289,10 @@ aac_family_identifiers[] = {
     	{0, 0, 0, 0, 0, 0, 0}
     };
     
    -static struct aac_ident *
    +static const struct aac_ident *
     aac_find_ident(device_t dev)
     {
    -	struct aac_ident *m;
    +	const struct aac_ident *m;
     	u_int16_t vendid, devid, sub_vendid, sub_devid;
     
     	vendid = pci_get_vendor(dev);
    @@ -317,7 +321,7 @@ aac_find_ident(device_t dev)
     static int
     aac_pci_probe(device_t dev)
     {
    -	struct aac_ident *id;
    +	const struct aac_ident *id;
     
     	fwprintf(NULL, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
     
    @@ -335,9 +339,8 @@ static int
     aac_pci_attach(device_t dev)
     {
     	struct aac_softc *sc;
    -	struct aac_ident *id;
    -	int error;
    -	u_int32_t command;
    +	const struct aac_ident *id;
    +	int count, error, reg, rid;
     
     	fwprintf(NULL, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
     
    @@ -345,7 +348,6 @@ aac_pci_attach(device_t dev)
     	 * Initialise softc.
     	 */
     	sc = device_get_softc(dev);
    -	bzero(sc, sizeof(*sc));
     	sc->aac_dev = dev;
     
     	/* assume failure is 'not configured' */
    @@ -354,55 +356,65 @@ aac_pci_attach(device_t dev)
     	/*
     	 * Verify that the adapter is correctly set up in PCI space.
     	 */
    -	command = pci_read_config(sc->aac_dev, PCIR_COMMAND, 2);
    -	command |= PCIM_CMD_BUSMASTEREN;
    -	pci_write_config(dev, PCIR_COMMAND, command, 2);
    -	command = pci_read_config(sc->aac_dev, PCIR_COMMAND, 2);
    -	if (!(command & PCIM_CMD_BUSMASTEREN)) {
    -		device_printf(sc->aac_dev, "can't enable bus-master feature\n");
    -		goto out;
    -	}
    -	if ((command & PCIM_CMD_MEMEN) == 0) {
    -		device_printf(sc->aac_dev, "memory window not available\n");
    +	pci_enable_busmaster(dev);
    +	if (!(pci_read_config(dev, PCIR_COMMAND, 2) & PCIM_CMD_BUSMASTEREN)) {
    +		device_printf(dev, "can't enable bus-master feature\n");
     		goto out;
     	}
     
     	/*
    -	 * Allocate the PCI register window.
    +	 * Allocate the PCI register window(s).
     	 */
    -	sc->aac_regs_rid0 = PCIR_BAR(0);
    -	if ((sc->aac_regs_res0 = bus_alloc_resource_any(sc->aac_dev,
    -	    SYS_RES_MEMORY, &sc->aac_regs_rid0, RF_ACTIVE)) == NULL) {
    -		device_printf(sc->aac_dev,
    -		    "couldn't allocate register window 0\n");
    +	rid = PCIR_BAR(0);
    +	if ((sc->aac_regs_res0 = bus_alloc_resource_any(dev,
    +	    SYS_RES_MEMORY, &rid, RF_ACTIVE)) == NULL) {
    +		device_printf(dev, "can't allocate register window 0\n");
     		goto out;
     	}
     	sc->aac_btag0 = rman_get_bustag(sc->aac_regs_res0);
     	sc->aac_bhandle0 = rman_get_bushandle(sc->aac_regs_res0);
     
     	if (sc->aac_hwif == AAC_HWIF_NARK) {
    -		sc->aac_regs_rid1 = PCIR_BAR(1);
    -		if ((sc->aac_regs_res1 = bus_alloc_resource_any(sc->aac_dev,
    -		    SYS_RES_MEMORY, &sc->aac_regs_rid1, RF_ACTIVE)) == NULL) {
    -			device_printf(sc->aac_dev,
    -			    "couldn't allocate register window 1\n");
    +		rid = PCIR_BAR(1);
    +		if ((sc->aac_regs_res1 = bus_alloc_resource_any(dev,
    +		    SYS_RES_MEMORY, &rid, RF_ACTIVE)) == NULL) {
    +			device_printf(dev,
    +			    "can't allocate register window 1\n");
     			goto out;
     		}
     		sc->aac_btag1 = rman_get_bustag(sc->aac_regs_res1);
     		sc->aac_bhandle1 = rman_get_bushandle(sc->aac_regs_res1);
     	} else {
     		sc->aac_regs_res1 = sc->aac_regs_res0;
    -		sc->aac_regs_rid1 = sc->aac_regs_rid0;
     		sc->aac_btag1 = sc->aac_btag0;
     		sc->aac_bhandle1 = sc->aac_bhandle0;
     	}
     
    +	/*
    +	 * Allocate the interrupt.
    +	 */
    +	rid = 0;
    +	if (aac_enable_msi != 0 && pci_find_cap(dev, PCIY_MSI, ®) == 0) {
    +		count = pci_msi_count(dev);
    +		if (count > 1)
    +			count = 1;
    +		else
    +			count = 0;
    +		if (count == 1 && pci_alloc_msi(dev, &count) == 0)
    +			rid = 1;
    +	}
    +	if ((sc->aac_irq = bus_alloc_resource_any(sc->aac_dev, SYS_RES_IRQ,
    +	    &rid, RF_ACTIVE | (count != 0 ? 0 : RF_SHAREABLE))) == NULL) {
    +		device_printf(dev, "can't allocate interrupt\n");
    +		goto out;
    +	}
    +
     	/*
     	 * Allocate the parent bus DMA tag appropriate for our PCI interface.
     	 *
     	 * Note that some of these controllers are 64-bit capable.
     	 */
    -	if (bus_dma_tag_create(bus_get_dma_tag(sc->aac_dev), /* parent */
    +	if (bus_dma_tag_create(bus_get_dma_tag(dev),	/* parent */
     			       PAGE_SIZE, 0,		/* algnmnt, boundary */
     			       BUS_SPACE_MAXADDR,	/* lowaddr */
     			       BUS_SPACE_MAXADDR, 	/* highaddr */
    @@ -413,7 +425,7 @@ aac_pci_attach(device_t dev)
     			       0,			/* flags */
     			       NULL, NULL,		/* No locking needed */
     			       &sc->aac_parent_dmat)) {
    -		device_printf(sc->aac_dev, "can't allocate parent DMA tag\n");
    +		device_printf(dev, "can't allocate parent DMA tag\n");
     		goto out;
     	}
     
    @@ -427,19 +439,19 @@ aac_pci_attach(device_t dev)
     	case AAC_HWIF_I960RX:
     	case AAC_HWIF_NARK:
     		fwprintf(sc, HBA_FLAGS_DBG_INIT_B, "set hardware up for i960Rx/NARK");
    -		sc->aac_if = aac_rx_interface;
    +		sc->aac_if = &aac_rx_interface;
     		break;
     	case AAC_HWIF_STRONGARM:
     		fwprintf(sc, HBA_FLAGS_DBG_INIT_B, "set hardware up for StrongARM");
    -		sc->aac_if = aac_sa_interface;
    +		sc->aac_if = &aac_sa_interface;
     		break;
     	case AAC_HWIF_RKT:
     		fwprintf(sc, HBA_FLAGS_DBG_INIT_B, "set hardware up for Rocket/MIPS");
    -		sc->aac_if = aac_rkt_interface;
    +		sc->aac_if = &aac_rkt_interface;
     		break;
     	default:
     		sc->aac_hwif = AAC_HWIF_UNKNOWN;
    -		device_printf(sc->aac_dev, "unknown hardware type\n");
    +		device_printf(dev, "unknown hardware type\n");
     		error = ENXIO;
     		goto out;
     	}
    @@ -472,7 +484,7 @@ static device_method_t aacch_methods[] = {
     	DEVMETHOD(device_probe,		aacch_probe),
     	DEVMETHOD(device_attach,	aacch_attach),
     	DEVMETHOD(device_detach,	aacch_detach),
    -	{ 0, 0 }
    +	DEVMETHOD_END
     };
     
     struct aacch_softc {
    @@ -486,7 +498,7 @@ static driver_t aacch_driver = {
     };
     
     static devclass_t	aacch_devclass;
    -DRIVER_MODULE(aacch, pci, aacch_driver, aacch_devclass, 0, 0);
    +DRIVER_MODULE(aacch, pci, aacch_driver, aacch_devclass, NULL, NULL);
     
     static int
     aacch_probe(device_t dev)
    diff --git a/sys/dev/aac/aac_tables.h b/sys/dev/aac/aac_tables.h
    index fe687fb8477..6f52d5d41cd 100644
    --- a/sys/dev/aac/aac_tables.h
    +++ b/sys/dev/aac/aac_tables.h
    @@ -27,13 +27,14 @@
      *	$FreeBSD$
      */
     
    +#if 0
     /*
      * Status codes for block read/write commands, etc.
      *
      * XXX many of these would not normally be returned, as they are
      * relevant only to FSA operations.
      */
    -static struct aac_code_lookup aac_command_status_table[] = {
    +static const struct aac_code_lookup aac_command_status_table[] = {
     	{"OK",					ST_OK},
     	{"operation not permitted",		ST_PERM},
     	{"not found",				ST_NOENT},
    @@ -75,8 +76,9 @@ static struct aac_code_lookup aac_command_status_table[] = {
     };
     
     #define AAC_COMMAND_STATUS(x)	aac_describe_code(aac_command_status_table, x)
    +#endif
     
    -static struct aac_code_lookup aac_cpu_variant[] = {
    +static const struct aac_code_lookup aac_cpu_variant[] = {
     	{"i960JX",		CPUI960_JX},
     	{"i960CX",		CPUI960_CX},
     	{"i960HX",		CPUI960_HX},
    @@ -93,7 +95,7 @@ static struct aac_code_lookup aac_cpu_variant[] = {
     	{"Unknown processor",	0}
     };
     
    -static struct aac_code_lookup aac_battery_platform[] = {
    +static const struct aac_code_lookup aac_battery_platform[] = {
     	{"required battery present",		PLATFORM_BAT_REQ_PRESENT},
     	{"REQUIRED BATTERY NOT PRESENT",	PLATFORM_BAT_REQ_NOTPRESENT},
     	{"optional battery present",		PLATFORM_BAT_OPT_PRESENT},
    @@ -103,7 +105,7 @@ static struct aac_code_lookup aac_battery_platform[] = {
     	{"unknown battery platform",		0}
     };
     
    -static struct aac_code_lookup aac_container_types[] = {
    +static const struct aac_code_lookup aac_container_types[] = {
     	{"Volume",		CT_VOLUME},
     	{"RAID 1 (Mirror)",	CT_MIRROR},
     	{"RAID 0 (Stripe)",	CT_STRIPE},
    @@ -126,4 +128,3 @@ static struct aac_code_lookup aac_container_types[] = {
     	{NULL, 0},
     	{"unknown",		0}
     };
    -
    diff --git a/sys/dev/aac/aacvar.h b/sys/dev/aac/aacvar.h
    index d994acf559a..6dc779507d9 100644
    --- a/sys/dev/aac/aacvar.h
    +++ b/sys/dev/aac/aacvar.h
    @@ -33,10 +33,13 @@
     #include 
     #include 
     #include 
    -#include 
     #include 
    +#include 
    +#include 
     #include 
     
    +SYSCTL_DECL(_hw_aac);
    +
     #define	AAC_TYPE_DEVO			1
     #define	AAC_TYPE_ALPHA			2
     #define	AAC_TYPE_BETA			3
    @@ -242,28 +245,28 @@ struct aac_interface
     	int (*aif_get_outb_queue)(struct aac_softc *sc);
     	void (*aif_set_outb_queue)(struct aac_softc *sc, int index);
     };
    -extern struct aac_interface	aac_rx_interface;
    -extern struct aac_interface	aac_sa_interface;
    -extern struct aac_interface	aac_fa_interface;
    -extern struct aac_interface	aac_rkt_interface;
    +extern const struct aac_interface	aac_rx_interface;
    +extern const struct aac_interface	aac_sa_interface;
    +extern const struct aac_interface	aac_fa_interface;
    +extern const struct aac_interface	aac_rkt_interface;
     
    -#define AAC_GET_FWSTATUS(sc)		((sc)->aac_if.aif_get_fwstatus((sc)))
    -#define AAC_QNOTIFY(sc, qbit)		((sc)->aac_if.aif_qnotify((sc), (qbit)))
    -#define AAC_GET_ISTATUS(sc)		((sc)->aac_if.aif_get_istatus((sc)))
    -#define AAC_CLEAR_ISTATUS(sc, mask)	((sc)->aac_if.aif_clr_istatus((sc), \
    +#define AAC_GET_FWSTATUS(sc)		((sc)->aac_if->aif_get_fwstatus((sc)))
    +#define AAC_QNOTIFY(sc, qbit)		((sc)->aac_if->aif_qnotify((sc), (qbit)))
    +#define AAC_GET_ISTATUS(sc)		((sc)->aac_if->aif_get_istatus((sc)))
    +#define AAC_CLEAR_ISTATUS(sc, mask)	((sc)->aac_if->aif_clr_istatus((sc), \
     					(mask)))
     #define AAC_SET_MAILBOX(sc, command, arg0, arg1, arg2, arg3) \
    -	((sc)->aac_if.aif_set_mailbox((sc), (command), (arg0), (arg1), (arg2), \
    +	((sc)->aac_if->aif_set_mailbox((sc), (command), (arg0), (arg1), (arg2), \
     	(arg3)))
    -#define AAC_GET_MAILBOX(sc, mb)		((sc)->aac_if.aif_get_mailbox((sc), \
    +#define AAC_GET_MAILBOX(sc, mb)		((sc)->aac_if->aif_get_mailbox((sc), \
     					(mb)))
    -#define	AAC_MASK_INTERRUPTS(sc)		((sc)->aac_if.aif_set_interrupts((sc), \
    +#define	AAC_MASK_INTERRUPTS(sc)		((sc)->aac_if->aif_set_interrupts((sc), \
     					0))
    -#define AAC_UNMASK_INTERRUPTS(sc)	((sc)->aac_if.aif_set_interrupts((sc), \
    +#define AAC_UNMASK_INTERRUPTS(sc)	((sc)->aac_if->aif_set_interrupts((sc), \
     					1))
    -#define AAC_SEND_COMMAND(sc, cm)	((sc)->aac_if.aif_send_command((sc), (cm)))
    -#define AAC_GET_OUTB_QUEUE(sc)		((sc)->aac_if.aif_get_outb_queue((sc)))
    -#define AAC_SET_OUTB_QUEUE(sc, idx)	((sc)->aac_if.aif_set_outb_queue((sc), (idx)))
    +#define AAC_SEND_COMMAND(sc, cm)	((sc)->aac_if->aif_send_command((sc), (cm)))
    +#define AAC_GET_OUTB_QUEUE(sc)		((sc)->aac_if->aif_get_outb_queue((sc)))
    +#define AAC_SET_OUTB_QUEUE(sc, idx)	((sc)->aac_if->aif_set_outb_queue((sc), (idx)))
     
     #define AAC_MEM0_SETREG4(sc, reg, val)	bus_space_write_4(sc->aac_btag0, \
     					sc->aac_bhandle0, reg, val)
    @@ -307,14 +310,12 @@ struct aac_softc
     	/* bus connections */
     	device_t		aac_dev;
     	struct resource		*aac_regs_res0, *aac_regs_res1; /* reg. if. window */
    -	int			aac_regs_rid0, aac_regs_rid1;		/* resource ID */
     	bus_space_handle_t	aac_bhandle0, aac_bhandle1;		/* bus space handle */
     	bus_space_tag_t		aac_btag0, aac_btag1;		/* bus space tag */
     	bus_dma_tag_t		aac_parent_dmat;	/* parent DMA tag */
     	bus_dma_tag_t		aac_buffer_dmat;	/* data buffer/command
     							 * DMA tag */
     	struct resource		*aac_irq;		/* interrupt */
    -	int			aac_irq_rid;
     	void			*aac_intr;		/* interrupt handle */
     	eventhandler_tag	eh;
     
    @@ -339,7 +340,7 @@ struct aac_softc
     							 * DMA map */
     	struct aac_common	*aac_common;
     	u_int32_t		aac_common_busaddr;
    -	struct aac_interface	aac_if;
    +	const struct aac_interface	*aac_if;
     
     	/* command/fib resources */
     	bus_dma_tag_t		aac_fib_dmat;	/* DMA tag for allocing FIBs */
    @@ -499,7 +500,7 @@ extern void	aac_print_aif(struct aac_softc *sc,
     #endif
     
     struct aac_code_lookup {
    -	char	*string;
    +	const char	*string;
     	u_int32_t	code;
     };
     
    @@ -581,7 +582,6 @@ aac_remove_ ## name (struct aac_command *cm)				\
     	cm->cm_flags &= ~AAC_ON_ ## index;				\
     	AACQ_REMOVE(cm->cm_sc, index);					\
     }									\
    -struct hack
     
     AACQ_COMMAND_QUEUE(free, AACQ_FREE);
     AACQ_COMMAND_QUEUE(ready, AACQ_READY);
    @@ -644,4 +644,3 @@ aac_release_sync_fib(struct aac_softc *sc)
     
     	mtx_assert(&sc->aac_io_lock, MA_OWNED);
     }
    -
    
    From 00ff5de5858f84162396fb67b114b3f7dfd9511b Mon Sep 17 00:00:00 2001
    From: Marius Strobl 
    Date: Fri, 1 Mar 2013 20:16:06 +0000
    Subject: [PATCH 0498/1476] - Apparently, r186520 was just wrong and the clock
     of Oxford OX16PCI958 is   neither DEFAULT_RCLK * 2 nor DEFAULT_RCLK * 10 but
     plain DEFAULT_RCLK   and there's no (open) source indicating otherwise. This
     was tested with   an EXSYS EX-41098-2, whose clock is not configurable and
     identifies as:   puc0@pci0:5:1:0:        class=0x070200 card=0x06711415
     chip=0x95381415 rev=0x01 hdr=0x00       vendor     = 'Oxford Semiconductor
     Ltd'       class      = simple comms       subclass   = multiport serial
    
      Note that this exactly matches the card mentioned in PR 129665 so no
      sub-device/sub-vendor based quirking of the latter is possible. So maybe
      we should grow some sort of tunable, in case non-default cards such as
      the latter aren't configurable either (this also wouldn't be the first
      time an allegedly tested commit turns out to be wrong though).
    - Make the TiMedia tables const.
    
    MFC after:	1 week
    ---
     sys/dev/puc/pucdata.c | 15 ++++++++-------
     1 file changed, 8 insertions(+), 7 deletions(-)
    
    diff --git a/sys/dev/puc/pucdata.c b/sys/dev/puc/pucdata.c
    index 216a30be481..6d933e8039c 100644
    --- a/sys/dev/puc/pucdata.c
    +++ b/sys/dev/puc/pucdata.c
    @@ -769,7 +769,7 @@ const struct puc_cfg puc_pci_devices[] = {
     
     	{   0x1415, 0x9538, 0xffff, 0,
     	    "Oxford Semiconductor OX16PCI958 UARTs",
    -	    DEFAULT_RCLK * 10,
    +	    DEFAULT_RCLK,
     	    PUC_PORT_8S, 0x18, 0, 8,
     	},
     
    @@ -918,6 +918,7 @@ const struct puc_cfg puc_pci_devices[] = {
     	    DEFAULT_RCLK * 8,
     	    PUC_PORT_4S, 0x10, 0, 8,
     	},
    +
     	{   0x14d2, 0xa004, 0xffff, 0,
     	    "Titan PCI-800H",
     	    DEFAULT_RCLK * 8,
    @@ -1060,7 +1061,7 @@ const struct puc_cfg puc_pci_devices[] = {
     	{   0x9710, 0x9865, 0xa000, 0x3004,
     	    "NetMos NM9865 Quad UART",
     	    DEFAULT_RCLK,
    -	    PUC_PORT_4S, 0x10, 4, 0,0
    +	    PUC_PORT_4S, 0x10, 4, 0,
     	},
     
     	{   0x9710, 0x9865, 0xa000, 0x3011,
    @@ -1420,26 +1421,26 @@ static int
     puc_config_timedia(struct puc_softc *sc, enum puc_cfg_cmd cmd, int port,
         intptr_t *res)
     {
    -	static uint16_t dual[] = {
    +	static const uint16_t dual[] = {
     	    0x0002, 0x4036, 0x4037, 0x4038, 0x4078, 0x4079, 0x4085,
     	    0x4088, 0x4089, 0x5037, 0x5078, 0x5079, 0x5085, 0x6079, 
     	    0x7079, 0x8079, 0x8137, 0x8138, 0x8237, 0x8238, 0x9079, 
     	    0x9137, 0x9138, 0x9237, 0x9238, 0xA079, 0xB079, 0xC079,
     	    0xD079, 0
     	};
    -	static uint16_t quad[] = {
    +	static const uint16_t quad[] = {
     	    0x4055, 0x4056, 0x4095, 0x4096, 0x5056, 0x8156, 0x8157, 
     	    0x8256, 0x8257, 0x9056, 0x9156, 0x9157, 0x9158, 0x9159, 
     	    0x9256, 0x9257, 0xA056, 0xA157, 0xA158, 0xA159, 0xB056,
     	    0xB157, 0
     	};
    -	static uint16_t octa[] = {
    +	static const uint16_t octa[] = {
     	    0x4065, 0x4066, 0x5065, 0x5066, 0x8166, 0x9066, 0x9166, 
     	    0x9167, 0x9168, 0xA066, 0xA167, 0xA168, 0
     	};
    -	static struct {
    +	static const struct {
     		int ports;
    -		uint16_t *ids;
    +		const uint16_t *ids;
     	} subdevs[] = {
     	    { 2, dual },
     	    { 4, quad },
    
    From 1a5a52f1f97eb950718e7abf60716dce5b98619c Mon Sep 17 00:00:00 2001
    From: Marius Strobl 
    Date: Fri, 1 Mar 2013 20:34:02 +0000
    Subject: [PATCH 0499/1476] - Remove an unused header. - Use NULL instead of 0
     for pointers. - Let ofw_pcib_probe() return BUS_PROBE_DEFAULT instead of 0 so
     specialized   PCI-PCI-bridge drivers may attach instead. - Add WARs for PLX
     Technology PEX 8114 bridges and PEX 8532 switches.   Ideally, these should
     live in MI code but at least for the latter we're   missing the necessary
     infrastructure there.
    
    MFC after:	1 week
    ---
     sys/sparc64/pci/ofw_pcib.c | 47 +++++++++++++++++++++++++++++++++-----
     1 file changed, 41 insertions(+), 6 deletions(-)
    
    diff --git a/sys/sparc64/pci/ofw_pcib.c b/sys/sparc64/pci/ofw_pcib.c
    index 69bdb7254fe..7944237b048 100644
    --- a/sys/sparc64/pci/ofw_pcib.c
    +++ b/sys/sparc64/pci/ofw_pcib.c
    @@ -47,8 +47,6 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     
    -#include 
    -
     #include 
     #include 
     #include 
    @@ -58,8 +56,12 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     
    +#define	PCI_DEVID_ALI_M5249	0x524910b9
    +#define	PCI_VENDOR_PLX		0x10b5
    +
     static device_probe_t ofw_pcib_probe;
     static device_attach_t ofw_pcib_attach;
    +static ofw_pci_setup_device_t ofw_pcib_setup_device;
     
     static device_method_t ofw_pcib_methods[] = {
     	/* Device interface */
    @@ -73,6 +75,7 @@ static device_method_t ofw_pcib_methods[] = {
     
     	/* ofw_bus interface */
     	DEVMETHOD(ofw_bus_get_node,	ofw_pcib_gen_get_node),
    +	DEVMETHOD(ofw_pci_setup_device, ofw_pcib_setup_device),
     
     	DEVMETHOD_END
     };
    @@ -81,7 +84,7 @@ static devclass_t pcib_devclass;
     
     DEFINE_CLASS_1(pcib, ofw_pcib_driver, ofw_pcib_methods,
         sizeof(struct ofw_pcib_gen_softc), pcib_driver);
    -EARLY_DRIVER_MODULE(ofw_pcib, pci, ofw_pcib_driver, pcib_devclass, 0, 0,
    +EARLY_DRIVER_MODULE(ofw_pcib, pci, ofw_pcib_driver, pcib_devclass, NULL, NULL,
         BUS_PASS_BUS);
     MODULE_DEPEND(ofw_pcib, pci, 1, 1, 1);
     
    @@ -104,7 +107,7 @@ ofw_pcib_probe(device_t dev)
     		    ISDTYPE(pbdtype, OFW_TYPE_PCIE) ? "e" : "",
     		    ISDTYPE(dtype, OFW_TYPE_PCIE) ? "e" : "");
     		device_set_desc_copy(dev, desc);
    -		return (0);
    +		return (BUS_PROBE_DEFAULT);
     	}
     
     #undef ISDTYPE
    @@ -119,7 +122,6 @@ ofw_pcib_attach(device_t dev)
     
     	sc = device_get_softc(dev);
     
    -	/* Quirk handling */
     	switch (pci_get_devid(dev)) {
     	/*
     	 * The ALi M5249 found in Fire-based machines by definition must me
    @@ -127,13 +129,46 @@ ofw_pcib_attach(device_t dev)
     	 * don't indicate this in the class code although the ISA I/O range
     	 * isn't included in their bridge decode.
     	 */
    -	case 0x524910b9:
    +	case PCI_DEVID_ALI_M5249:
     		sc->ops_pcib_sc.flags |= PCIB_SUBTRACTIVE;
     		break;
     	}
     
    +	switch (pci_get_vendor(dev)) {
    +	/*
    +	 * Concurrently write the primary and secondary bus numbers in order
    +	 * to work around a bug in PLX PEX 8114 causing the internal shadow
    +	 * copies of these not to be updated when setting them bytewise.
    +	 */
    +	case PCI_VENDOR_PLX:
    +		pci_write_config(dev, PCIR_PRIBUS_1,
    +		    pci_read_config(dev, PCIR_SECBUS_1, 1) << 8 |
    +		    pci_read_config(dev, PCIR_PRIBUS_1, 1), 2);
    +		break;
    +	}
    +
     	ofw_pcib_gen_setup(dev);
     	pcib_attach_common(dev);
     	device_add_child(dev, "pci", -1);
     	return (bus_generic_attach(dev));
     }
    +
    +static void
    +ofw_pcib_setup_device(device_t bus, device_t child)
    +{
    +	int i;
    +	uint16_t reg;
    +
    +	switch (pci_get_vendor(bus)) {
    +	/*
    +	 * For PLX PEX 8532 issue 64 TLPs to the child from the downstream
    +	 * port to the child device in order to work around a hardware bug.
    +	 */
    +	case PCI_VENDOR_PLX:
    +		for (i = 0, reg = 0; i < 64; i++)
    +			reg |= pci_get_devid(child);
    +		break;
    +	}
    +
    +	OFW_PCI_SETUP_DEVICE(device_get_parent(bus), child);
    +}
    
    From 22f19117ed237aa36e85e2ec1fdbc3783e9fe361 Mon Sep 17 00:00:00 2001
    From: Marius Strobl 
    Date: Fri, 1 Mar 2013 20:36:59 +0000
    Subject: [PATCH 0500/1476] - In sbbc_pci_attach() just pass the already
     obtained bus tag and handle   instead of acquiring these anew. - Use NULL
     instead of 0 for pointers.
    
    MFC after:	1 week
    ---
     sys/sparc64/pci/sbbc.c | 7 +++----
     1 file changed, 3 insertions(+), 4 deletions(-)
    
    diff --git a/sys/sparc64/pci/sbbc.c b/sys/sparc64/pci/sbbc.c
    index 491f653c227..218093fcbc6 100644
    --- a/sys/sparc64/pci/sbbc.c
    +++ b/sys/sparc64/pci/sbbc.c
    @@ -299,7 +299,7 @@ static device_method_t sbbc_pci_methods[] = {
     static devclass_t sbbc_devclass;
     
     DEFINE_CLASS_0(sbbc, sbbc_driver, sbbc_pci_methods, sizeof(struct sbbc_softc));
    -DRIVER_MODULE(sbbc, pci, sbbc_driver, sbbc_devclass, 0, 0);
    +DRIVER_MODULE(sbbc, pci, sbbc_driver, sbbc_devclass, NULL, NULL);
     
     static int
     sbbc_pci_probe(device_t dev)
    @@ -358,8 +358,7 @@ sbbc_pci_attach(device_t dev)
     		if (error != 0)
     			device_printf(dev, "failed to attach UART device\n");
     	} else {
    -		error = sbbc_parse_toc(rman_get_bustag(sc->sc_res),
    -		    rman_get_bushandle(sc->sc_res));
    +		error = sbbc_parse_toc(bst, bsh);
     		if (error != 0) {
     			device_printf(dev, "failed to parse TOC\n");
     			if (sbbc_console != 0) {
    @@ -609,7 +608,7 @@ static device_method_t sbbc_uart_sbbc_methods[] = {
     
     DEFINE_CLASS_0(uart, sbbc_uart_driver, sbbc_uart_sbbc_methods,
         sizeof(struct uart_softc));
    -DRIVER_MODULE(uart, sbbc, sbbc_uart_driver, uart_devclass, 0, 0);
    +DRIVER_MODULE(uart, sbbc, sbbc_uart_driver, uart_devclass, NULL, NULL);
     
     static int
     sbbc_uart_sbbc_probe(device_t dev)
    
    From 1dd7ebb604a81bc34a2de82fa19e23b311ffbcea Mon Sep 17 00:00:00 2001
    From: Martin Matuska 
    Date: Fri, 1 Mar 2013 20:48:07 +0000
    Subject: [PATCH 0501/1476] Update vendor-sys/illumos/dist to illumos-gate
     13970:c9a5683da38e
    
    Illumos ZFS issues:
      3543 Feature flags causes assertion in spa.c to miss certain cases
    ---
     uts/common/fs/zfs/spa.c | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/uts/common/fs/zfs/spa.c b/uts/common/fs/zfs/spa.c
    index fb68e91eed1..151b78091a8 100644
    --- a/uts/common/fs/zfs/spa.c
    +++ b/uts/common/fs/zfs/spa.c
    @@ -5747,7 +5747,7 @@ spa_sync_version(void *arg1, void *arg2, dmu_tx_t *tx)
     	 */
     	ASSERT(tx->tx_txg != TXG_INITIAL);
     
    -	ASSERT(version <= SPA_VERSION);
    +	ASSERT(SPA_VERSION_IS_SUPPORTED(version));
     	ASSERT(version >= spa_version(spa));
     
     	spa->spa_uberblock.ub_version = version;
    @@ -6276,7 +6276,7 @@ spa_upgrade(spa_t *spa, uint64_t version)
     	 * future version would result in an unopenable pool, this shouldn't be
     	 * possible.
     	 */
    -	ASSERT(spa->spa_uberblock.ub_version <= SPA_VERSION);
    +	ASSERT(SPA_VERSION_IS_SUPPORTED(spa->spa_uberblock.ub_version));
     	ASSERT(version >= spa->spa_uberblock.ub_version);
     
     	spa->spa_uberblock.ub_version = version;
    
    From b9192d31aabb73ffd7d70eb6dd383aa9f924dc0a Mon Sep 17 00:00:00 2001
    From: Martin Matuska 
    Date: Fri, 1 Mar 2013 20:49:56 +0000
    Subject: [PATCH 0502/1476] Update vendor-sys/illumos/dist to illumos-gate
     13971:d1648d817bd6
    
    Illumos ZFS issues:
      3581 spa_zio_taskq[ZIO_TYPE_FREE][ZIO_TASKQ_ISSUE]->tq_lock is piping hot
    ---
     uts/common/fs/zfs/spa.c          | 208 +++++++++++++++++++++----------
     uts/common/fs/zfs/sys/spa_impl.h |  16 ++-
     uts/common/fs/zfs/vdev_file.c    |   2 +-
     uts/common/fs/zfs/zio.c          |  31 +++--
     4 files changed, 173 insertions(+), 84 deletions(-)
    
    diff --git a/uts/common/fs/zfs/spa.c b/uts/common/fs/zfs/spa.c
    index 151b78091a8..fdc28700c82 100644
    --- a/uts/common/fs/zfs/spa.c
    +++ b/uts/common/fs/zfs/spa.c
    @@ -77,23 +77,25 @@
     #include "zfs_comutil.h"
     
     typedef enum zti_modes {
    -	zti_mode_fixed,			/* value is # of threads (min 1) */
    -	zti_mode_online_percent,	/* value is % of online CPUs */
    -	zti_mode_batch,			/* cpu-intensive; value is ignored */
    -	zti_mode_null,			/* don't create a taskq */
    -	zti_nmodes
    +	ZTI_MODE_FIXED,			/* value is # of threads (min 1) */
    +	ZTI_MODE_ONLINE_PERCENT,	/* value is % of online CPUs */
    +	ZTI_MODE_BATCH,			/* cpu-intensive; value is ignored */
    +	ZTI_MODE_NULL,			/* don't create a taskq */
    +	ZTI_NMODES
     } zti_modes_t;
     
    -#define	ZTI_FIX(n)	{ zti_mode_fixed, (n) }
    -#define	ZTI_PCT(n)	{ zti_mode_online_percent, (n) }
    -#define	ZTI_BATCH	{ zti_mode_batch, 0 }
    -#define	ZTI_NULL	{ zti_mode_null, 0 }
    +#define	ZTI_P(n, q)	{ ZTI_MODE_FIXED, (n), (q) }
    +#define	ZTI_PCT(n)	{ ZTI_MODE_ONLINE_PERCENT, (n), 1 }
    +#define	ZTI_BATCH	{ ZTI_MODE_BATCH, 0, 1 }
    +#define	ZTI_NULL	{ ZTI_MODE_NULL, 0, 0 }
     
    -#define	ZTI_ONE		ZTI_FIX(1)
    +#define	ZTI_N(n)	ZTI_P(n, 1)
    +#define	ZTI_ONE		ZTI_N(1)
     
     typedef struct zio_taskq_info {
    -	enum zti_modes zti_mode;
    +	zti_modes_t zti_mode;
     	uint_t zti_value;
    +	uint_t zti_count;
     } zio_taskq_info_t;
     
     static const char *const zio_taskq_types[ZIO_TASKQ_TYPES] = {
    @@ -101,17 +103,30 @@ static const char *const zio_taskq_types[ZIO_TASKQ_TYPES] = {
     };
     
     /*
    - * Define the taskq threads for the following I/O types:
    - * 	NULL, READ, WRITE, FREE, CLAIM, and IOCTL
    + * This table defines the taskq settings for each ZFS I/O type. When
    + * initializing a pool, we use this table to create an appropriately sized
    + * taskq. Some operations are low volume and therefore have a small, static
    + * number of threads assigned to their taskqs using the ZTI_N(#) or ZTI_ONE
    + * macros. Other operations process a large amount of data; the ZTI_BATCH
    + * macro causes us to create a taskq oriented for throughput. Some operations
    + * are so high frequency and short-lived that the taskq itself can become a a
    + * point of lock contention. The ZTI_P(#, #) macro indicates that we need an
    + * additional degree of parallelism specified by the number of threads per-
    + * taskq and the number of taskqs; when dispatching an event in this case, the
    + * particular taskq is chosen at random.
    + *
    + * The different taskq priorities are to handle the different contexts (issue
    + * and interrupt) and then to reserve threads for ZIO_PRIORITY_NOW I/Os that
    + * need to be handled with minimum delay.
      */
     const zio_taskq_info_t zio_taskqs[ZIO_TYPES][ZIO_TASKQ_TYPES] = {
     	/* ISSUE	ISSUE_HIGH	INTR		INTR_HIGH */
    -	{ ZTI_ONE,	ZTI_NULL,	ZTI_ONE,	ZTI_NULL },
    -	{ ZTI_FIX(8),	ZTI_NULL,	ZTI_BATCH,	ZTI_NULL },
    -	{ ZTI_BATCH,	ZTI_FIX(5),	ZTI_FIX(8),	ZTI_FIX(5) },
    -	{ ZTI_FIX(100),	ZTI_NULL,	ZTI_ONE,	ZTI_NULL },
    -	{ ZTI_ONE,	ZTI_NULL,	ZTI_ONE,	ZTI_NULL },
    -	{ ZTI_ONE,	ZTI_NULL,	ZTI_ONE,	ZTI_NULL },
    +	{ ZTI_ONE,	ZTI_NULL,	ZTI_ONE,	ZTI_NULL }, /* NULL */
    +	{ ZTI_N(8),	ZTI_NULL,	ZTI_BATCH,	ZTI_NULL }, /* READ */
    +	{ ZTI_BATCH,	ZTI_N(5),	ZTI_N(8),	ZTI_N(5) }, /* WRITE */
    +	{ ZTI_P(12, 8),	ZTI_NULL,	ZTI_ONE,	ZTI_NULL }, /* FREE */
    +	{ ZTI_ONE,	ZTI_NULL,	ZTI_ONE,	ZTI_NULL }, /* CLAIM */
    +	{ ZTI_ONE,	ZTI_NULL,	ZTI_ONE,	ZTI_NULL }, /* IOCTL */
     };
     
     static dsl_syncfunc_t spa_sync_version;
    @@ -794,48 +809,120 @@ spa_get_errlists(spa_t *spa, avl_tree_t *last, avl_tree_t *scrub)
     	    offsetof(spa_error_entry_t, se_avl));
     }
     
    -static taskq_t *
    -spa_taskq_create(spa_t *spa, const char *name, enum zti_modes mode,
    -    uint_t value)
    +static void
    +spa_taskqs_init(spa_t *spa, zio_type_t t, zio_taskq_type_t q)
     {
    +	const zio_taskq_info_t *ztip = &zio_taskqs[t][q];
    +	enum zti_modes mode = ztip->zti_mode;
    +	uint_t value = ztip->zti_value;
    +	uint_t count = ztip->zti_count;
    +	spa_taskqs_t *tqs = &spa->spa_zio_taskq[t][q];
    +	char name[32];
     	uint_t flags = 0;
     	boolean_t batch = B_FALSE;
     
    -	switch (mode) {
    -	case zti_mode_null:
    -		return (NULL);		/* no taskq needed */
    -
    -	case zti_mode_fixed:
    -		ASSERT3U(value, >=, 1);
    -		value = MAX(value, 1);
    -		break;
    -
    -	case zti_mode_batch:
    -		batch = B_TRUE;
    -		flags |= TASKQ_THREADS_CPU_PCT;
    -		value = zio_taskq_batch_pct;
    -		break;
    -
    -	case zti_mode_online_percent:
    -		flags |= TASKQ_THREADS_CPU_PCT;
    -		break;
    -
    -	default:
    -		panic("unrecognized mode for %s taskq (%u:%u) in "
    -		    "spa_activate()",
    -		    name, mode, value);
    -		break;
    +	if (mode == ZTI_MODE_NULL) {
    +		tqs->stqs_count = 0;
    +		tqs->stqs_taskq = NULL;
    +		return;
     	}
     
    -	if (zio_taskq_sysdc && spa->spa_proc != &p0) {
    -		if (batch)
    -			flags |= TASKQ_DC_BATCH;
    +	ASSERT3U(count, >, 0);
     
    -		return (taskq_create_sysdc(name, value, 50, INT_MAX,
    -		    spa->spa_proc, zio_taskq_basedc, flags));
    +	tqs->stqs_count = count;
    +	tqs->stqs_taskq = kmem_alloc(count * sizeof (taskq_t *), KM_SLEEP);
    +
    +	for (uint_t i = 0; i < count; i++) {
    +		taskq_t *tq;
    +
    +		switch (mode) {
    +		case ZTI_MODE_FIXED:
    +			ASSERT3U(value, >=, 1);
    +			value = MAX(value, 1);
    +			break;
    +
    +		case ZTI_MODE_BATCH:
    +			batch = B_TRUE;
    +			flags |= TASKQ_THREADS_CPU_PCT;
    +			value = zio_taskq_batch_pct;
    +			break;
    +
    +		case ZTI_MODE_ONLINE_PERCENT:
    +			flags |= TASKQ_THREADS_CPU_PCT;
    +			break;
    +
    +		default:
    +			panic("unrecognized mode for %s_%s taskq (%u:%u) in "
    +			    "spa_activate()",
    +			    zio_type_name[t], zio_taskq_types[q], mode, value);
    +			break;
    +		}
    +
    +		if (count > 1) {
    +			(void) snprintf(name, sizeof (name), "%s_%s_%u",
    +			    zio_type_name[t], zio_taskq_types[q], i);
    +		} else {
    +			(void) snprintf(name, sizeof (name), "%s_%s",
    +			    zio_type_name[t], zio_taskq_types[q]);
    +		}
    +
    +		if (zio_taskq_sysdc && spa->spa_proc != &p0) {
    +			if (batch)
    +				flags |= TASKQ_DC_BATCH;
    +
    +			tq = taskq_create_sysdc(name, value, 50, INT_MAX,
    +			    spa->spa_proc, zio_taskq_basedc, flags);
    +		} else {
    +			tq = taskq_create_proc(name, value, maxclsyspri, 50,
    +			    INT_MAX, spa->spa_proc, flags);
    +		}
    +
    +		tqs->stqs_taskq[i] = tq;
     	}
    -	return (taskq_create_proc(name, value, maxclsyspri, 50, INT_MAX,
    -	    spa->spa_proc, flags));
    +}
    +
    +static void
    +spa_taskqs_fini(spa_t *spa, zio_type_t t, zio_taskq_type_t q)
    +{
    +	spa_taskqs_t *tqs = &spa->spa_zio_taskq[t][q];
    +
    +	if (tqs->stqs_taskq == NULL) {
    +		ASSERT0(tqs->stqs_count);
    +		return;
    +	}
    +
    +	for (uint_t i = 0; i < tqs->stqs_count; i++) {
    +		ASSERT3P(tqs->stqs_taskq[i], !=, NULL);
    +		taskq_destroy(tqs->stqs_taskq[i]);
    +	}
    +
    +	kmem_free(tqs->stqs_taskq, tqs->stqs_count * sizeof (taskq_t *));
    +	tqs->stqs_taskq = NULL;
    +}
    +
    +/*
    + * Dispatch a task to the appropriate taskq for the ZFS I/O type and priority.
    + * Note that a type may have multiple discrete taskqs to avoid lock contention
    + * on the taskq itself. In that case we choose which taskq at random by using
    + * the low bits of gethrtime().
    + */
    +void
    +spa_taskq_dispatch_ent(spa_t *spa, zio_type_t t, zio_taskq_type_t q,
    +    task_func_t *func, void *arg, uint_t flags, taskq_ent_t *ent)
    +{
    +	spa_taskqs_t *tqs = &spa->spa_zio_taskq[t][q];
    +	taskq_t *tq;
    +
    +	ASSERT3P(tqs->stqs_taskq, !=, NULL);
    +	ASSERT3U(tqs->stqs_count, !=, 0);
    +
    +	if (tqs->stqs_count == 1) {
    +		tq = tqs->stqs_taskq[0];
    +	} else {
    +		tq = tqs->stqs_taskq[gethrtime() % tqs->stqs_count];
    +	}
    +
    +	taskq_dispatch_ent(tq, func, arg, flags, ent);
     }
     
     static void
    @@ -843,16 +930,7 @@ spa_create_zio_taskqs(spa_t *spa)
     {
     	for (int t = 0; t < ZIO_TYPES; t++) {
     		for (int q = 0; q < ZIO_TASKQ_TYPES; q++) {
    -			const zio_taskq_info_t *ztip = &zio_taskqs[t][q];
    -			enum zti_modes mode = ztip->zti_mode;
    -			uint_t value = ztip->zti_value;
    -			char name[32];
    -
    -			(void) snprintf(name, sizeof (name),
    -			    "%s_%s", zio_type_name[t], zio_taskq_types[q]);
    -
    -			spa->spa_zio_taskq[t][q] =
    -			    spa_taskq_create(spa, name, mode, value);
    +			spa_taskqs_init(spa, t, q);
     		}
     	}
     }
    @@ -1009,9 +1087,7 @@ spa_deactivate(spa_t *spa)
     
     	for (int t = 0; t < ZIO_TYPES; t++) {
     		for (int q = 0; q < ZIO_TASKQ_TYPES; q++) {
    -			if (spa->spa_zio_taskq[t][q] != NULL)
    -				taskq_destroy(spa->spa_zio_taskq[t][q]);
    -			spa->spa_zio_taskq[t][q] = NULL;
    +			spa_taskqs_fini(spa, t, q);
     		}
     	}
     
    diff --git a/uts/common/fs/zfs/sys/spa_impl.h b/uts/common/fs/zfs/sys/spa_impl.h
    index ffd676e2ed7..983103e3862 100644
    --- a/uts/common/fs/zfs/sys/spa_impl.h
    +++ b/uts/common/fs/zfs/sys/spa_impl.h
    @@ -80,16 +80,16 @@ typedef struct spa_config_dirent {
     	char		*scd_path;
     } spa_config_dirent_t;
     
    -enum zio_taskq_type {
    +typedef enum zio_taskq_type {
     	ZIO_TASKQ_ISSUE = 0,
     	ZIO_TASKQ_ISSUE_HIGH,
     	ZIO_TASKQ_INTERRUPT,
     	ZIO_TASKQ_INTERRUPT_HIGH,
     	ZIO_TASKQ_TYPES
    -};
    +} zio_taskq_type_t;
     
     /*
    - * State machine for the zpool-pooname process.  The states transitions
    + * State machine for the zpool-poolname process.  The states transitions
      * are done as follows:
      *
      *	From		   To			Routine
    @@ -107,6 +107,11 @@ typedef enum spa_proc_state {
     	SPA_PROC_GONE		/* spa_thread() is exiting, spa_proc = &p0 */
     } spa_proc_state_t;
     
    +typedef struct spa_taskqs {
    +	uint_t stqs_count;
    +	taskq_t **stqs_taskq;
    +} spa_taskqs_t;
    +
     struct spa {
     	/*
     	 * Fields protected by spa_namespace_lock.
    @@ -125,7 +130,7 @@ struct spa {
     	uint8_t		spa_sync_on;		/* sync threads are running */
     	spa_load_state_t spa_load_state;	/* current load operation */
     	uint64_t	spa_import_flags;	/* import specific flags */
    -	taskq_t		*spa_zio_taskq[ZIO_TYPES][ZIO_TASKQ_TYPES];
    +	spa_taskqs_t	spa_zio_taskq[ZIO_TYPES][ZIO_TASKQ_TYPES];
     	dsl_pool_t	*spa_dsl_pool;
     	boolean_t	spa_is_initializing;	/* true while opening pool */
     	metaslab_class_t *spa_normal_class;	/* normal data class */
    @@ -245,6 +250,9 @@ struct spa {
     
     extern const char *spa_config_path;
     
    +extern void spa_taskq_dispatch_ent(spa_t *spa, zio_type_t t, zio_taskq_type_t q,
    +    task_func_t *func, void *arg, uint_t flags, taskq_ent_t *ent);
    +
     #ifdef	__cplusplus
     }
     #endif
    diff --git a/uts/common/fs/zfs/vdev_file.c b/uts/common/fs/zfs/vdev_file.c
    index 1fbce5e5422..f7cfa9b095a 100644
    --- a/uts/common/fs/zfs/vdev_file.c
    +++ b/uts/common/fs/zfs/vdev_file.c
    @@ -224,7 +224,7 @@ vdev_file_io_start(zio_t *zio)
     	bp->b_private = vf->vf_vnode;
     	bp->b_iodone = (int (*)())vdev_file_io_intr;
     
    -	taskq_dispatch_ent(spa->spa_zio_taskq[ZIO_TYPE_FREE][ZIO_TASKQ_ISSUE],
    +	spa_taskq_dispatch_ent(spa, ZIO_TYPE_FREE, ZIO_TASKQ_ISSUE,
     	    vdev_file_io_strategy, bp, 0, &zio->io_tqent);
     
     	return (ZIO_PIPELINE_STOP);
    diff --git a/uts/common/fs/zfs/zio.c b/uts/common/fs/zfs/zio.c
    index 04b8ddfaf71..432a992b26f 100644
    --- a/uts/common/fs/zfs/zio.c
    +++ b/uts/common/fs/zfs/zio.c
    @@ -1107,7 +1107,7 @@ zio_free_bp_init(zio_t *zio)
      */
     
     static void
    -zio_taskq_dispatch(zio_t *zio, enum zio_taskq_type q, boolean_t cutinline)
    +zio_taskq_dispatch(zio_t *zio, zio_taskq_type_t q, boolean_t cutinline)
     {
     	spa_t *spa = zio->io_spa;
     	zio_type_t t = zio->io_type;
    @@ -1128,10 +1128,11 @@ zio_taskq_dispatch(zio_t *zio, enum zio_taskq_type q, boolean_t cutinline)
     		t = ZIO_TYPE_NULL;
     
     	/*
    -	 * If this is a high priority I/O, then use the high priority taskq.
    +	 * If this is a high priority I/O, then use the high priority taskq if
    +	 * available.
     	 */
     	if (zio->io_priority == ZIO_PRIORITY_NOW &&
    -	    spa->spa_zio_taskq[t][q + 1] != NULL)
    +	    spa->spa_zio_taskq[t][q + 1].stqs_count != 0)
     		q++;
     
     	ASSERT3U(q, <, ZIO_TASKQ_TYPES);
    @@ -1142,19 +1143,24 @@ zio_taskq_dispatch(zio_t *zio, enum zio_taskq_type q, boolean_t cutinline)
     	 * to dispatch the zio to another taskq at the same time.
     	 */
     	ASSERT(zio->io_tqent.tqent_next == NULL);
    -	taskq_dispatch_ent(spa->spa_zio_taskq[t][q],
    -	    (task_func_t *)zio_execute, zio, flags, &zio->io_tqent);
    +	spa_taskq_dispatch_ent(spa, t, q, (task_func_t *)zio_execute, zio,
    +	    flags, &zio->io_tqent);
     }
     
     static boolean_t
    -zio_taskq_member(zio_t *zio, enum zio_taskq_type q)
    +zio_taskq_member(zio_t *zio, zio_taskq_type_t q)
     {
     	kthread_t *executor = zio->io_executor;
     	spa_t *spa = zio->io_spa;
     
    -	for (zio_type_t t = 0; t < ZIO_TYPES; t++)
    -		if (taskq_member(spa->spa_zio_taskq[t][q], executor))
    -			return (B_TRUE);
    +	for (zio_type_t t = 0; t < ZIO_TYPES; t++) {
    +		spa_taskqs_t *tqs = &spa->spa_zio_taskq[t][q];
    +		uint_t i;
    +		for (i = 0; i < tqs->stqs_count; i++) {
    +			if (taskq_member(tqs->stqs_taskq[i], executor))
    +				return (B_TRUE);
    +		}
    +	}
     
     	return (B_FALSE);
     }
    @@ -3017,10 +3023,9 @@ zio_done(zio_t *zio)
     			 * Hand it off to the otherwise-unused claim taskq.
     			 */
     			ASSERT(zio->io_tqent.tqent_next == NULL);
    -			taskq_dispatch_ent(
    -			    spa->spa_zio_taskq[ZIO_TYPE_CLAIM][ZIO_TASKQ_ISSUE],
    -			    (task_func_t *)zio_reexecute, zio, 0,
    -			    &zio->io_tqent);
    +			spa_taskq_dispatch_ent(spa, ZIO_TYPE_CLAIM,
    +			    ZIO_TASKQ_ISSUE, (task_func_t *)zio_reexecute, zio,
    +			    0, &zio->io_tqent);
     		}
     		return (ZIO_PIPELINE_STOP);
     	}
    
    From a587c657efbc898b7937a9c14e10fdb8be346b18 Mon Sep 17 00:00:00 2001
    From: Marius Strobl 
    Date: Fri, 1 Mar 2013 20:51:53 +0000
    Subject: [PATCH 0503/1476] - Move reporting of failures to disable RX/TX MAC
     under bootverbose as at   least the Saturn chips of 501-6738 cards may fail
     to do so the first   time, which isn't fatal though.   Reported by: Paul
     Keusemann - Explain why we don't enable infinite bursts on sparc64. - Given
     that these chips support memory write invalidate, make sure that   it's
     enabled in the command register. Also make sure that PERR# and   SERR#
     assertion is enabled.
    
    MFC after:	1 week
    ---
     sys/dev/cas/if_cas.c | 14 ++++++++++----
     1 file changed, 10 insertions(+), 4 deletions(-)
    
    diff --git a/sys/dev/cas/if_cas.c b/sys/dev/cas/if_cas.c
    index f98d4f0b725..eec8fa44c34 100644
    --- a/sys/dev/cas/if_cas.c
    +++ b/sys/dev/cas/if_cas.c
    @@ -824,7 +824,8 @@ cas_disable_rx(struct cas_softc *sc)
     	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
     	if (cas_bitwait(sc, CAS_MAC_RX_CONF, CAS_MAC_RX_CONF_EN, 0))
     		return (1);
    -	device_printf(sc->sc_dev, "cannot disable RX MAC\n");
    +	if (bootverbose)
    +		device_printf(sc->sc_dev, "cannot disable RX MAC\n");
     	return (0);
     }
     
    @@ -838,7 +839,8 @@ cas_disable_tx(struct cas_softc *sc)
     	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
     	if (cas_bitwait(sc, CAS_MAC_TX_CONF, CAS_MAC_TX_CONF_EN, 0))
     		return (1);
    -	device_printf(sc->sc_dev, "cannot disable TX MAC\n");
    +	if (bootverbose)
    +		device_printf(sc->sc_dev, "cannot disable TX MAC\n");
     	return (0);
     }
     
    @@ -1041,7 +1043,8 @@ cas_init_locked(struct cas_softc *sc)
     	/*
     	 * Enable infinite bursts for revisions without PCI issues if
     	 * applicable.  Doing so greatly improves the TX performance on
    -	 * !__sparc64__.
    +	 * !__sparc64__ (on sparc64, setting CAS_INF_BURST improves TX
    +	 * performance only marginally but hurts RX throughput quite a bit).
     	 */
     	CAS_WRITE_4(sc, CAS_INF_BURST,
     #if !defined(__sparc64__)
    @@ -2691,7 +2694,10 @@ cas_pci_attach(device_t dev)
     		return (ENXIO);
     	}
     
    -	pci_enable_busmaster(dev);
    +	/* PCI configuration */
    +	pci_write_config(dev, PCIR_COMMAND,
    +	    pci_read_config(dev, PCIR_COMMAND, 2) | PCIM_CMD_BUSMASTEREN |
    +	    PCIM_CMD_MWRICEN | PCIM_CMD_PERRESPEN | PCIM_CMD_SERRESPEN, 2);
     
     	sc->sc_dev = dev;
     	if (sc->sc_variant == CAS_CAS && pci_get_devid(dev) < 0x02)
    
    From 577227be9d7e7e691365c6df7c2c70a0cd5c0d96 Mon Sep 17 00:00:00 2001
    From: Martin Matuska 
    Date: Fri, 1 Mar 2013 21:01:45 +0000
    Subject: [PATCH 0504/1476] Update vendor/illumos/dist and
     vendor-sys/illumos/dist to illumos-gate 13973:4972ab336f54
    
    Illumos ZFS issues:
      3464 zfs synctask code needs restructuring
    ---
     cmd/zdb/zdb.c                         |    9 +-
     cmd/zfs/zfs_main.c                    |  116 +-
     cmd/zhack/zhack.c                     |   27 +-
     cmd/ztest/ztest.c                     |  190 +-
     common/nvpair/fnvpair.c               |   13 +
     lib/libzfs/common/libzfs.h            |    6 +-
     lib/libzfs/common/libzfs_dataset.c    |  318 ++-
     lib/libzfs/common/libzfs_sendrecv.c   |   12 +-
     lib/libzfs_core/common/libzfs_core.c  |  102 +-
     lib/libzfs_core/common/libzfs_core.h  |    4 +
     lib/libzpool/common/kernel.c          |    5 +
     lib/libzpool/common/sys/zfs_context.h |   15 +-
     man/man1m/zfs.1m                      |    6 +-
     uts/common/Makefile.files             |    4 +-
     uts/common/fs/zfs/arc.c               |   10 +-
     uts/common/fs/zfs/bplist.c            |    8 +
     uts/common/fs/zfs/bpobj.c             |    4 +
     uts/common/fs/zfs/dbuf.c              |   87 +-
     uts/common/fs/zfs/dmu.c               |    2 +-
     uts/common/fs/zfs/dmu_diff.c          |   82 +-
     uts/common/fs/zfs/dmu_objset.c        |  889 +++---
     uts/common/fs/zfs/dmu_send.c          |  917 +++---
     uts/common/fs/zfs/dmu_traverse.c      |   42 +-
     uts/common/fs/zfs/dmu_tx.c            |   31 +-
     uts/common/fs/zfs/dnode.c             |    6 +-
     uts/common/fs/zfs/dnode_sync.c        |    1 +
     uts/common/fs/zfs/dsl_dataset.c       | 3718 ++++++++-----------------
     uts/common/fs/zfs/dsl_deleg.c         |  150 +-
     uts/common/fs/zfs/dsl_destroy.c       |  926 ++++++
     uts/common/fs/zfs/dsl_dir.c           |  587 ++--
     uts/common/fs/zfs/dsl_pool.c          |  216 +-
     uts/common/fs/zfs/dsl_prop.c          |  483 ++--
     uts/common/fs/zfs/dsl_scan.c          |  116 +-
     uts/common/fs/zfs/dsl_synctask.c      |  239 +-
     uts/common/fs/zfs/dsl_userhold.c      |  536 ++++
     uts/common/fs/zfs/metaslab.c          |   38 +
     uts/common/fs/zfs/refcount.c          |   21 +-
     uts/common/fs/zfs/rrwlock.c           |   41 +-
     uts/common/fs/zfs/sa.c                |    6 +-
     uts/common/fs/zfs/spa.c               |   81 +-
     uts/common/fs/zfs/spa_history.c       |   26 +-
     uts/common/fs/zfs/spa_misc.c          |   23 +-
     uts/common/fs/zfs/space_map.c         |   43 +-
     uts/common/fs/zfs/sys/arc.h           |    2 +-
     uts/common/fs/zfs/sys/dbuf.h          |    9 +-
     uts/common/fs/zfs/sys/dmu.h           |   52 +-
     uts/common/fs/zfs/sys/dmu_objset.h    |   11 +-
     uts/common/fs/zfs/sys/dmu_send.h      |   66 +
     uts/common/fs/zfs/sys/dmu_tx.h        |    6 +-
     uts/common/fs/zfs/sys/dsl_dataset.h   |  112 +-
     uts/common/fs/zfs/sys/dsl_destroy.h   |   52 +
     uts/common/fs/zfs/sys/dsl_dir.h       |   17 +-
     uts/common/fs/zfs/sys/dsl_pool.h      |   16 +-
     uts/common/fs/zfs/sys/dsl_prop.h      |   53 +-
     uts/common/fs/zfs/sys/dsl_synctask.h  |   46 +-
     uts/common/fs/zfs/sys/dsl_userhold.h  |   57 +
     uts/common/fs/zfs/sys/metaslab.h      |    3 +-
     uts/common/fs/zfs/sys/refcount.h      |    5 +-
     uts/common/fs/zfs/sys/rrwlock.h       |    7 +-
     uts/common/fs/zfs/sys/space_map.h     |    2 +
     uts/common/fs/zfs/sys/txg.h           |    9 +-
     uts/common/fs/zfs/sys/zfeature.h      |   17 +-
     uts/common/fs/zfs/sys/zfs_debug.h     |   12 +-
     uts/common/fs/zfs/sys/zfs_ioctl.h     |    4 +-
     uts/common/fs/zfs/sys/zfs_znode.h     |    3 +-
     uts/common/fs/zfs/sys/zil.h           |    4 +-
     uts/common/fs/zfs/txg.c               |   37 +-
     uts/common/fs/zfs/zfs_ctldir.c        |   33 +-
     uts/common/fs/zfs/zfs_ioctl.c         | 1139 ++++----
     uts/common/fs/zfs/zfs_vfsops.c        |   74 +-
     uts/common/fs/zfs/zil.c               |  137 +-
     uts/common/fs/zfs/zio.c               |    8 +-
     uts/common/fs/zfs/zvol.c              |   81 +-
     uts/common/sys/nvpair.h               |    1 +
     74 files changed, 6341 insertions(+), 5890 deletions(-)
     create mode 100644 uts/common/fs/zfs/dsl_destroy.c
     create mode 100644 uts/common/fs/zfs/dsl_userhold.c
     create mode 100644 uts/common/fs/zfs/sys/dmu_send.h
     create mode 100644 uts/common/fs/zfs/sys/dsl_destroy.h
     create mode 100644 uts/common/fs/zfs/sys/dsl_userhold.h
    
    diff --git a/cmd/zdb/zdb.c b/cmd/zdb/zdb.c
    index 2234a71528b..46a630fb423 100644
    --- a/cmd/zdb/zdb.c
    +++ b/cmd/zdb/zdb.c
    @@ -1658,7 +1658,9 @@ dump_dir(objset_t *os)
     	int print_header = 1;
     	int i, error;
     
    +	dsl_pool_config_enter(dmu_objset_pool(os), FTAG);
     	dmu_objset_fast_stat(os, &dds);
    +	dsl_pool_config_exit(dmu_objset_pool(os), FTAG);
     
     	if (dds.dds_type < DMU_OST_NUMTYPES)
     		type = objset_types[dds.dds_type];
    @@ -2109,7 +2111,6 @@ zdb_blkptr_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
     
     		zio_nowait(zio_read(NULL, spa, bp, data, size,
     		    zdb_blkptr_done, zcb, ZIO_PRIORITY_ASYNC_READ, flags, zb));
    -
     	}
     
     	zcb->zcb_readfails = 0;
    @@ -2297,8 +2298,10 @@ dump_block_stats(spa_t *spa)
     	 */
     	(void) bpobj_iterate_nofree(&spa->spa_deferred_bpobj,
     	    count_block_cb, &zcb, NULL);
    -	(void) bpobj_iterate_nofree(&spa->spa_dsl_pool->dp_free_bpobj,
    -	    count_block_cb, &zcb, NULL);
    +	if (spa_version(spa) >= SPA_VERSION_DEADLISTS) {
    +		(void) bpobj_iterate_nofree(&spa->spa_dsl_pool->dp_free_bpobj,
    +		    count_block_cb, &zcb, NULL);
    +	}
     	if (spa_feature_is_active(spa,
     	    &spa_feature_table[SPA_FEATURE_ASYNC_DESTROY])) {
     		VERIFY3U(0, ==, bptree_iterate(spa->spa_meta_objset,
    diff --git a/cmd/zfs/zfs_main.c b/cmd/zfs/zfs_main.c
    index e5e35e6f166..5e95aed88b4 100644
    --- a/cmd/zfs/zfs_main.c
    +++ b/cmd/zfs/zfs_main.c
    @@ -898,6 +898,7 @@ typedef struct destroy_cbdata {
     	boolean_t	cb_parsable;
     	boolean_t	cb_dryrun;
     	nvlist_t	*cb_nvl;
    +	nvlist_t	*cb_batchedsnaps;
     
     	/* first snap in contiguous run */
     	char		*cb_firstsnap;
    @@ -994,9 +995,27 @@ destroy_callback(zfs_handle_t *zhp, void *data)
     		zfs_close(zhp);
     		return (0);
     	}
    +	if (cb->cb_dryrun) {
    +		zfs_close(zhp);
    +		return (0);
    +	}
     
    -	if (!cb->cb_dryrun) {
    -		if (zfs_unmount(zhp, NULL, cb->cb_force ? MS_FORCE : 0) != 0 ||
    +	/*
    +	 * We batch up all contiguous snapshots (even of different
    +	 * filesystems) and destroy them with one ioctl.  We can't
    +	 * simply do all snap deletions and then all fs deletions,
    +	 * because we must delete a clone before its origin.
    +	 */
    +	if (zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT) {
    +		fnvlist_add_boolean(cb->cb_batchedsnaps, name);
    +	} else {
    +		int error = zfs_destroy_snaps_nvl(g_zfs,
    +		    cb->cb_batchedsnaps, B_FALSE);
    +		fnvlist_free(cb->cb_batchedsnaps);
    +		cb->cb_batchedsnaps = fnvlist_alloc();
    +
    +		if (error != 0 ||
    +		    zfs_unmount(zhp, NULL, cb->cb_force ? MS_FORCE : 0) != 0 ||
     		    zfs_destroy(zhp, cb->cb_defer_destroy) != 0) {
     			zfs_close(zhp);
     			return (-1);
    @@ -1152,8 +1171,10 @@ static int
     zfs_do_destroy(int argc, char **argv)
     {
     	destroy_cbdata_t cb = { 0 };
    +	int rv = 0;
    +	int err = 0;
     	int c;
    -	zfs_handle_t *zhp;
    +	zfs_handle_t *zhp = NULL;
     	char *at;
     	zfs_type_t type = ZFS_TYPE_DATASET;
     
    @@ -1207,11 +1228,9 @@ zfs_do_destroy(int argc, char **argv)
     
     	at = strchr(argv[0], '@');
     	if (at != NULL) {
    -		int err = 0;
     
     		/* Build the list of snaps to destroy in cb_nvl. */
    -		if (nvlist_alloc(&cb.cb_nvl, NV_UNIQUE_NAME, 0) != 0)
    -			nomem();
    +		cb.cb_nvl = fnvlist_alloc();
     
     		*at = '\0';
     		zhp = zfs_open(g_zfs, argv[0],
    @@ -1222,17 +1241,15 @@ zfs_do_destroy(int argc, char **argv)
     		cb.cb_snapspec = at + 1;
     		if (gather_snapshots(zfs_handle_dup(zhp), &cb) != 0 ||
     		    cb.cb_error) {
    -			zfs_close(zhp);
    -			nvlist_free(cb.cb_nvl);
    -			return (1);
    +			rv = 1;
    +			goto out;
     		}
     
     		if (nvlist_empty(cb.cb_nvl)) {
     			(void) fprintf(stderr, gettext("could not find any "
     			    "snapshots to destroy; check snapshot names.\n"));
    -			zfs_close(zhp);
    -			nvlist_free(cb.cb_nvl);
    -			return (1);
    +			rv = 1;
    +			goto out;
     		}
     
     		if (cb.cb_verbose) {
    @@ -1251,18 +1268,26 @@ zfs_do_destroy(int argc, char **argv)
     		}
     
     		if (!cb.cb_dryrun) {
    -			if (cb.cb_doclones)
    +			if (cb.cb_doclones) {
    +				cb.cb_batchedsnaps = fnvlist_alloc();
     				err = destroy_clones(&cb);
    +				if (err == 0) {
    +					err = zfs_destroy_snaps_nvl(g_zfs,
    +					    cb.cb_batchedsnaps, B_FALSE);
    +				}
    +				if (err != 0) {
    +					rv = 1;
    +					goto out;
    +				}
    +			}
     			if (err == 0) {
    -				err = zfs_destroy_snaps_nvl(zhp, cb.cb_nvl,
    +				err = zfs_destroy_snaps_nvl(g_zfs, cb.cb_nvl,
     				    cb.cb_defer_destroy);
     			}
     		}
     
    -		zfs_close(zhp);
    -		nvlist_free(cb.cb_nvl);
     		if (err != 0)
    -			return (1);
    +			rv = 1;
     	} else {
     		/* Open the given dataset */
     		if ((zhp = zfs_open(g_zfs, argv[0], type)) == NULL)
    @@ -1283,8 +1308,8 @@ zfs_do_destroy(int argc, char **argv)
     			    zfs_get_name(zhp));
     			(void) fprintf(stderr, gettext("use 'zpool destroy %s' "
     			    "to destroy the pool itself\n"), zfs_get_name(zhp));
    -			zfs_close(zhp);
    -			return (1);
    +			rv = 1;
    +			goto out;
     		}
     
     		/*
    @@ -1294,30 +1319,42 @@ zfs_do_destroy(int argc, char **argv)
     		if (!cb.cb_doclones &&
     		    zfs_iter_dependents(zhp, B_TRUE, destroy_check_dependent,
     		    &cb) != 0) {
    -			zfs_close(zhp);
    -			return (1);
    +			rv = 1;
    +			goto out;
     		}
     
     		if (cb.cb_error) {
    -			zfs_close(zhp);
    -			return (1);
    +			rv = 1;
    +			goto out;
     		}
     
    +		cb.cb_batchedsnaps = fnvlist_alloc();
     		if (zfs_iter_dependents(zhp, B_FALSE, destroy_callback,
     		    &cb) != 0) {
    -			zfs_close(zhp);
    -			return (1);
    +			rv = 1;
    +			goto out;
     		}
     
     		/*
     		 * Do the real thing.  The callback will close the
     		 * handle regardless of whether it succeeds or not.
     		 */
    -		if (destroy_callback(zhp, &cb) != 0)
    -			return (1);
    +		err = destroy_callback(zhp, &cb);
    +		zhp = NULL;
    +		if (err == 0) {
    +			err = zfs_destroy_snaps_nvl(g_zfs,
    +			    cb.cb_batchedsnaps, cb.cb_defer_destroy);
    +		}
    +		if (err != 0)
    +			rv = 1;
     	}
     
    -	return (0);
    +out:
    +	fnvlist_free(cb.cb_batchedsnaps);
    +	fnvlist_free(cb.cb_nvl);
    +	if (zhp != NULL)
    +		zfs_close(zhp);
    +	return (rv);
     }
     
     static boolean_t
    @@ -5052,28 +5089,12 @@ cleanup2:
     	return (error);
     }
     
    -/*
    - * zfs allow [-r] [-t]   ...
    - *
    - *	-r	Recursively hold
    - *	-t	Temporary hold (hidden option)
    - *
    - * Apply a user-hold with the given tag to the list of snapshots.
    - */
     static int
     zfs_do_allow(int argc, char **argv)
     {
     	return (zfs_do_allow_unallow_impl(argc, argv, B_FALSE));
     }
     
    -/*
    - * zfs unallow [-r] [-t]   ...
    - *
    - *	-r	Recursively hold
    - *	-t	Temporary hold (hidden option)
    - *
    - * Apply a user-hold with the given tag to the list of snapshots.
    - */
     static int
     zfs_do_unallow(int argc, char **argv)
     {
    @@ -5087,7 +5108,6 @@ zfs_do_hold_rele_impl(int argc, char **argv, boolean_t holding)
     	int i;
     	const char *tag;
     	boolean_t recursive = B_FALSE;
    -	boolean_t temphold = B_FALSE;
     	const char *opts = holding ? "rt" : "r";
     	int c;
     
    @@ -5097,9 +5117,6 @@ zfs_do_hold_rele_impl(int argc, char **argv, boolean_t holding)
     		case 'r':
     			recursive = B_TRUE;
     			break;
    -		case 't':
    -			temphold = B_TRUE;
    -			break;
     		case '?':
     			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
     			    optopt);
    @@ -5148,7 +5165,7 @@ zfs_do_hold_rele_impl(int argc, char **argv, boolean_t holding)
     		}
     		if (holding) {
     			if (zfs_hold(zhp, delim+1, tag, recursive,
    -			    temphold, B_FALSE, -1, 0, 0) != 0)
    +			    B_FALSE, -1) != 0)
     				++errors;
     		} else {
     			if (zfs_release(zhp, delim+1, tag, recursive) != 0)
    @@ -5164,7 +5181,6 @@ zfs_do_hold_rele_impl(int argc, char **argv, boolean_t holding)
      * zfs hold [-r] [-t]   ...
      *
      *	-r	Recursively hold
    - *	-t	Temporary hold (hidden option)
      *
      * Apply a user-hold with the given tag to the list of snapshots.
      */
    diff --git a/cmd/zhack/zhack.c b/cmd/zhack/zhack.c
    index 7cc83d2dc0b..d9ad36cccb3 100644
    --- a/cmd/zhack/zhack.c
    +++ b/cmd/zhack/zhack.c
    @@ -46,6 +46,7 @@
     #include 
     #include 
     #include 
    +#include 
     #undef ZFS_MAXNAMELEN
     #undef verify
     #include 
    @@ -273,10 +274,10 @@ zhack_do_feature_stat(int argc, char **argv)
     }
     
     static void
    -feature_enable_sync(void *arg1, void *arg2, dmu_tx_t *tx)
    +feature_enable_sync(void *arg, dmu_tx_t *tx)
     {
    -	spa_t *spa = arg1;
    -	zfeature_info_t *feature = arg2;
    +	spa_t *spa = dmu_tx_pool(tx)->dp_spa;
    +	zfeature_info_t *feature = arg;
     
     	spa_feature_enable(spa, feature, tx);
     	spa_history_log_internal(spa, "zhack enable feature", tx,
    @@ -344,8 +345,8 @@ zhack_do_feature_enable(int argc, char **argv)
     	if (0 == zap_contains(mos, spa->spa_feat_desc_obj, feature.fi_guid))
     		fatal("feature already enabled: %s", feature.fi_guid);
     
    -	VERIFY3U(0, ==, dsl_sync_task_do(spa->spa_dsl_pool, NULL,
    -	    feature_enable_sync, spa, &feature, 5));
    +	VERIFY0(dsl_sync_task(spa_name(spa), NULL,
    +	    feature_enable_sync, &feature, 5));
     
     	spa_close(spa, FTAG);
     
    @@ -353,10 +354,10 @@ zhack_do_feature_enable(int argc, char **argv)
     }
     
     static void
    -feature_incr_sync(void *arg1, void *arg2, dmu_tx_t *tx)
    +feature_incr_sync(void *arg, dmu_tx_t *tx)
     {
    -	spa_t *spa = arg1;
    -	zfeature_info_t *feature = arg2;
    +	spa_t *spa = dmu_tx_pool(tx)->dp_spa;
    +	zfeature_info_t *feature = arg;
     
     	spa_feature_incr(spa, feature, tx);
     	spa_history_log_internal(spa, "zhack feature incr", tx,
    @@ -364,10 +365,10 @@ feature_incr_sync(void *arg1, void *arg2, dmu_tx_t *tx)
     }
     
     static void
    -feature_decr_sync(void *arg1, void *arg2, dmu_tx_t *tx)
    +feature_decr_sync(void *arg, dmu_tx_t *tx)
     {
    -	spa_t *spa = arg1;
    -	zfeature_info_t *feature = arg2;
    +	spa_t *spa = dmu_tx_pool(tx)->dp_spa;
    +	zfeature_info_t *feature = arg;
     
     	spa_feature_decr(spa, feature, tx);
     	spa_history_log_internal(spa, "zhack feature decr", tx,
    @@ -442,8 +443,8 @@ zhack_do_feature_ref(int argc, char **argv)
     	if (decr && !spa_feature_is_active(spa, &feature))
     		fatal("feature refcount already 0: %s", feature.fi_guid);
     
    -	VERIFY3U(0, ==, dsl_sync_task_do(spa->spa_dsl_pool, NULL,
    -	    decr ? feature_decr_sync : feature_incr_sync, spa, &feature, 5));
    +	VERIFY0(dsl_sync_task(spa_name(spa), NULL,
    +	    decr ? feature_decr_sync : feature_incr_sync, &feature, 5));
     
     	spa_close(spa, FTAG);
     }
    diff --git a/cmd/ztest/ztest.c b/cmd/ztest/ztest.c
    index b51ab84bfc3..ed460551c69 100644
    --- a/cmd/ztest/ztest.c
    +++ b/cmd/ztest/ztest.c
    @@ -103,10 +103,12 @@
     #include 
     #include 
     #include 
    +#include 
     #include 
     #include 
     #include 
     #include 
    +#include 
     #include 
     #include 
     #include 
    @@ -365,7 +367,7 @@ ztest_info_t ztest_info[] = {
     	{ ztest_scrub,				1,	&zopt_rarely	},
     	{ ztest_spa_upgrade,			1,	&zopt_rarely	},
     	{ ztest_dsl_dataset_promote_busy,	1,	&zopt_rarely	},
    -	{ ztest_vdev_attach_detach,		1,	&zopt_rarely	},
    +	{ ztest_vdev_attach_detach,		1,	&zopt_sometimes	},
     	{ ztest_vdev_LUN_growth,		1,	&zopt_rarely	},
     	{ ztest_vdev_add_remove,		1,
     	    &ztest_opts.zo_vdevtime				},
    @@ -1006,9 +1008,8 @@ ztest_dsl_prop_set_uint64(char *osname, zfs_prop_t prop, uint64_t value,
     	uint64_t curval;
     	int error;
     
    -	error = dsl_prop_set(osname, propname,
    -	    (inherit ? ZPROP_SRC_NONE : ZPROP_SRC_LOCAL),
    -	    sizeof (value), 1, &value);
    +	error = dsl_prop_set_int(osname, propname,
    +	    (inherit ? ZPROP_SRC_NONE : ZPROP_SRC_LOCAL), value);
     
     	if (error == ENOSPC) {
     		ztest_record_enospc(FTAG);
    @@ -1016,8 +1017,7 @@ ztest_dsl_prop_set_uint64(char *osname, zfs_prop_t prop, uint64_t value,
     	}
     	ASSERT0(error);
     
    -	VERIFY3U(dsl_prop_get(osname, propname, sizeof (curval),
    -	    1, &curval, setpoint), ==, 0);
    +	VERIFY0(dsl_prop_get_integer(osname, propname, &curval, setpoint));
     
     	if (ztest_opts.zo_verbose >= 6) {
     		VERIFY(zfs_prop_index_to_string(prop, curval, &valname) == 0);
    @@ -2479,8 +2479,7 @@ ztest_vdev_add_remove(ztest_ds_t *zd, uint64_t id)
     	int error;
     
     	VERIFY(mutex_lock(&ztest_vdev_lock) == 0);
    -	leaves =
    -	    MAX(zs->zs_mirrors + zs->zs_splits, 1) * ztest_opts.zo_raidz;
    +	leaves = MAX(zs->zs_mirrors + zs->zs_splits, 1) * ztest_opts.zo_raidz;
     
     	spa_config_enter(spa, SCL_VDEV, FTAG, RW_READER);
     
    @@ -3180,7 +3179,7 @@ ztest_objset_destroy_cb(const char *name, void *arg)
     	/*
     	 * Verify that the dataset contains a directory object.
     	 */
    -	VERIFY3U(0, ==, dmu_objset_hold(name, FTAG, &os));
    +	VERIFY0(dmu_objset_own(name, DMU_OST_OTHER, B_TRUE, FTAG, &os));
     	error = dmu_object_info(os, ZTEST_DIROBJ, &doi);
     	if (error != ENOENT) {
     		/* We could have crashed in the middle of destroying it */
    @@ -3188,12 +3187,16 @@ ztest_objset_destroy_cb(const char *name, void *arg)
     		ASSERT3U(doi.doi_type, ==, DMU_OT_ZAP_OTHER);
     		ASSERT3S(doi.doi_physical_blocks_512, >=, 0);
     	}
    -	dmu_objset_rele(os, FTAG);
    +	dmu_objset_disown(os, FTAG);
     
     	/*
     	 * Destroy the dataset.
     	 */
    -	VERIFY3U(0, ==, dmu_objset_destroy(name, B_FALSE));
    +	if (strchr(name, '@') != NULL) {
    +		VERIFY0(dsl_destroy_snapshot(name, B_FALSE));
    +	} else {
    +		VERIFY0(dsl_destroy_head(name));
    +	}
     	return (0);
     }
     
    @@ -3203,16 +3206,17 @@ ztest_snapshot_create(char *osname, uint64_t id)
     	char snapname[MAXNAMELEN];
     	int error;
     
    -	(void) snprintf(snapname, MAXNAMELEN, "%s@%llu", osname,
    -	    (u_longlong_t)id);
    +	(void) snprintf(snapname, sizeof (snapname), "%llu", (u_longlong_t)id);
     
    -	error = dmu_objset_snapshot_one(osname, strchr(snapname, '@') + 1);
    +	error = dmu_objset_snapshot_one(osname, snapname);
     	if (error == ENOSPC) {
     		ztest_record_enospc(FTAG);
     		return (B_FALSE);
     	}
    -	if (error != 0 && error != EEXIST)
    -		fatal(0, "ztest_snapshot_create(%s) = %d", snapname, error);
    +	if (error != 0 && error != EEXIST) {
    +		fatal(0, "ztest_snapshot_create(%s@%s) = %d", osname,
    +		    snapname, error);
    +	}
     	return (B_TRUE);
     }
     
    @@ -3225,7 +3229,7 @@ ztest_snapshot_destroy(char *osname, uint64_t id)
     	(void) snprintf(snapname, MAXNAMELEN, "%s@%llu", osname,
     	    (u_longlong_t)id);
     
    -	error = dmu_objset_destroy(snapname, B_FALSE);
    +	error = dsl_destroy_snapshot(snapname, B_FALSE);
     	if (error != 0 && error != ENOENT)
     		fatal(0, "ztest_snapshot_destroy(%s) = %d", snapname, error);
     	return (B_TRUE);
    @@ -3271,7 +3275,8 @@ ztest_dmu_objset_create_destroy(ztest_ds_t *zd, uint64_t id)
     	/*
     	 * Verify that the destroyed dataset is no longer in the namespace.
     	 */
    -	VERIFY3U(ENOENT, ==, dmu_objset_hold(name, FTAG, &os));
    +	VERIFY3U(ENOENT, ==, dmu_objset_own(name, DMU_OST_OTHER, B_TRUE,
    +	    FTAG, &os));
     
     	/*
     	 * Verify that we can create a new dataset.
    @@ -3286,8 +3291,7 @@ ztest_dmu_objset_create_destroy(ztest_ds_t *zd, uint64_t id)
     		fatal(0, "dmu_objset_create(%s) = %d", name, error);
     	}
     
    -	VERIFY3U(0, ==,
    -	    dmu_objset_own(name, DMU_OST_OTHER, B_FALSE, FTAG, &os));
    +	VERIFY0(dmu_objset_own(name, DMU_OST_OTHER, B_FALSE, FTAG, &os));
     
     	ztest_zd_init(&zdtmp, NULL, os);
     
    @@ -3363,21 +3367,21 @@ ztest_dsl_dataset_cleanup(char *osname, uint64_t id)
     	(void) snprintf(clone2name, MAXNAMELEN, "%s/c2_%llu", osname, id);
     	(void) snprintf(snap3name, MAXNAMELEN, "%s@s3_%llu", clone1name, id);
     
    -	error = dmu_objset_destroy(clone2name, B_FALSE);
    +	error = dsl_destroy_head(clone2name);
     	if (error && error != ENOENT)
    -		fatal(0, "dmu_objset_destroy(%s) = %d", clone2name, error);
    -	error = dmu_objset_destroy(snap3name, B_FALSE);
    +		fatal(0, "dsl_destroy_head(%s) = %d", clone2name, error);
    +	error = dsl_destroy_snapshot(snap3name, B_FALSE);
     	if (error && error != ENOENT)
    -		fatal(0, "dmu_objset_destroy(%s) = %d", snap3name, error);
    -	error = dmu_objset_destroy(snap2name, B_FALSE);
    +		fatal(0, "dsl_destroy_snapshot(%s) = %d", snap3name, error);
    +	error = dsl_destroy_snapshot(snap2name, B_FALSE);
     	if (error && error != ENOENT)
    -		fatal(0, "dmu_objset_destroy(%s) = %d", snap2name, error);
    -	error = dmu_objset_destroy(clone1name, B_FALSE);
    +		fatal(0, "dsl_destroy_snapshot(%s) = %d", snap2name, error);
    +	error = dsl_destroy_head(clone1name);
     	if (error && error != ENOENT)
    -		fatal(0, "dmu_objset_destroy(%s) = %d", clone1name, error);
    -	error = dmu_objset_destroy(snap1name, B_FALSE);
    +		fatal(0, "dsl_destroy_head(%s) = %d", clone1name, error);
    +	error = dsl_destroy_snapshot(snap1name, B_FALSE);
     	if (error && error != ENOENT)
    -		fatal(0, "dmu_objset_destroy(%s) = %d", snap1name, error);
    +		fatal(0, "dsl_destroy_snapshot(%s) = %d", snap1name, error);
     }
     
     /*
    @@ -3386,8 +3390,7 @@ ztest_dsl_dataset_cleanup(char *osname, uint64_t id)
     void
     ztest_dsl_dataset_promote_busy(ztest_ds_t *zd, uint64_t id)
     {
    -	objset_t *clone;
    -	dsl_dataset_t *ds;
    +	objset_t *os;
     	char snap1name[MAXNAMELEN];
     	char clone1name[MAXNAMELEN];
     	char snap2name[MAXNAMELEN];
    @@ -3415,12 +3418,7 @@ ztest_dsl_dataset_promote_busy(ztest_ds_t *zd, uint64_t id)
     		fatal(0, "dmu_take_snapshot(%s) = %d", snap1name, error);
     	}
     
    -	error = dmu_objset_hold(snap1name, FTAG, &clone);
    -	if (error)
    -		fatal(0, "dmu_open_snapshot(%s) = %d", snap1name, error);
    -
    -	error = dmu_objset_clone(clone1name, dmu_objset_ds(clone), 0);
    -	dmu_objset_rele(clone, FTAG);
    +	error = dmu_objset_clone(clone1name, snap1name);
     	if (error) {
     		if (error == ENOSPC) {
     			ztest_record_enospc(FTAG);
    @@ -3447,12 +3445,7 @@ ztest_dsl_dataset_promote_busy(ztest_ds_t *zd, uint64_t id)
     		fatal(0, "dmu_open_snapshot(%s) = %d", snap3name, error);
     	}
     
    -	error = dmu_objset_hold(snap3name, FTAG, &clone);
    -	if (error)
    -		fatal(0, "dmu_open_snapshot(%s) = %d", snap3name, error);
    -
    -	error = dmu_objset_clone(clone2name, dmu_objset_ds(clone), 0);
    -	dmu_objset_rele(clone, FTAG);
    +	error = dmu_objset_clone(clone2name, snap3name);
     	if (error) {
     		if (error == ENOSPC) {
     			ztest_record_enospc(FTAG);
    @@ -3461,14 +3454,14 @@ ztest_dsl_dataset_promote_busy(ztest_ds_t *zd, uint64_t id)
     		fatal(0, "dmu_objset_create(%s) = %d", clone2name, error);
     	}
     
    -	error = dsl_dataset_own(snap2name, B_FALSE, FTAG, &ds);
    +	error = dmu_objset_own(snap2name, DMU_OST_ANY, B_TRUE, FTAG, &os);
     	if (error)
    -		fatal(0, "dsl_dataset_own(%s) = %d", snap2name, error);
    +		fatal(0, "dmu_objset_own(%s) = %d", snap2name, error);
     	error = dsl_dataset_promote(clone2name, NULL);
     	if (error != EBUSY)
     		fatal(0, "dsl_dataset_promote(%s), %d, not EBUSY", clone2name,
     		    error);
    -	dsl_dataset_disown(ds, FTAG);
    +	dmu_objset_disown(os, FTAG);
     
     out:
     	ztest_dsl_dataset_cleanup(osname, id);
    @@ -4280,7 +4273,7 @@ ztest_zap_parallel(ztest_ds_t *zd, uint64_t id)
     	}
     
     	count = -1ULL;
    -	VERIFY(zap_count(os, object, &count) == 0);
    +	VERIFY0(zap_count(os, object, &count));
     	ASSERT(count != -1ULL);
     
     	/*
    @@ -4591,6 +4584,22 @@ ztest_spa_prop_get_set(ztest_ds_t *zd, uint64_t id)
     	(void) rw_unlock(&ztest_name_lock);
     }
     
    +static int
    +user_release_one(const char *snapname, const char *holdname)
    +{
    +	nvlist_t *snaps, *holds;
    +	int error;
    +
    +	snaps = fnvlist_alloc();
    +	holds = fnvlist_alloc();
    +	fnvlist_add_boolean(holds, holdname);
    +	fnvlist_add_nvlist(snaps, snapname, holds);
    +	fnvlist_free(holds);
    +	error = dsl_dataset_user_release(snaps, NULL);
    +	fnvlist_free(snaps);
    +	return (error);
    +}
    +
     /*
      * Test snapshot hold/release and deferred destroy.
      */
    @@ -4605,22 +4614,30 @@ ztest_dmu_snapshot_hold(ztest_ds_t *zd, uint64_t id)
     	char clonename[100];
     	char tag[100];
     	char osname[MAXNAMELEN];
    +	nvlist_t *holds;
     
     	(void) rw_rdlock(&ztest_name_lock);
     
     	dmu_objset_name(os, osname);
     
    -	(void) snprintf(snapname, 100, "sh1_%llu", id);
    -	(void) snprintf(fullname, 100, "%s@%s", osname, snapname);
    -	(void) snprintf(clonename, 100, "%s/ch1_%llu", osname, id);
    -	(void) snprintf(tag, 100, "%tag_%llu", id);
    +	(void) snprintf(snapname, sizeof (snapname), "sh1_%llu", id);
    +	(void) snprintf(fullname, sizeof (fullname), "%s@%s", osname, snapname);
    +	(void) snprintf(clonename, sizeof (clonename),
    +	    "%s/ch1_%llu", osname, id);
    +	(void) snprintf(tag, sizeof (tag), "tag_%llu", id);
     
     	/*
     	 * Clean up from any previous run.
     	 */
    -	(void) dmu_objset_destroy(clonename, B_FALSE);
    -	(void) dsl_dataset_user_release(osname, snapname, tag, B_FALSE);
    -	(void) dmu_objset_destroy(fullname, B_FALSE);
    +	error = dsl_destroy_head(clonename);
    +	if (error != ENOENT)
    +		ASSERT0(error);
    +	error = user_release_one(fullname, tag);
    +	if (error != ESRCH && error != ENOENT)
    +		ASSERT0(error);
    +	error = dsl_destroy_snapshot(fullname, B_FALSE);
    +	if (error != ENOENT)
    +		ASSERT0(error);
     
     	/*
     	 * Create snapshot, clone it, mark snap for deferred destroy,
    @@ -4635,12 +4652,7 @@ ztest_dmu_snapshot_hold(ztest_ds_t *zd, uint64_t id)
     		fatal(0, "dmu_objset_snapshot(%s) = %d", fullname, error);
     	}
     
    -	error = dmu_objset_hold(fullname, FTAG, &origin);
    -	if (error)
    -		fatal(0, "dmu_objset_hold(%s) = %d", fullname, error);
    -
    -	error = dmu_objset_clone(clonename, dmu_objset_ds(origin), 0);
    -	dmu_objset_rele(origin, FTAG);
    +	error = dmu_objset_clone(clonename, fullname);
     	if (error) {
     		if (error == ENOSPC) {
     			ztest_record_enospc("dmu_objset_clone");
    @@ -4649,15 +4661,15 @@ ztest_dmu_snapshot_hold(ztest_ds_t *zd, uint64_t id)
     		fatal(0, "dmu_objset_clone(%s) = %d", clonename, error);
     	}
     
    -	error = dmu_objset_destroy(fullname, B_TRUE);
    +	error = dsl_destroy_snapshot(fullname, B_TRUE);
     	if (error) {
    -		fatal(0, "dmu_objset_destroy(%s, B_TRUE) = %d",
    +		fatal(0, "dsl_destroy_snapshot(%s, B_TRUE) = %d",
     		    fullname, error);
     	}
     
    -	error = dmu_objset_destroy(clonename, B_FALSE);
    +	error = dsl_destroy_head(clonename);
     	if (error)
    -		fatal(0, "dmu_objset_destroy(%s) = %d", clonename, error);
    +		fatal(0, "dsl_destroy_head(%s) = %d", clonename, error);
     
     	error = dmu_objset_hold(fullname, FTAG, &origin);
     	if (error != ENOENT)
    @@ -4677,28 +4689,31 @@ ztest_dmu_snapshot_hold(ztest_ds_t *zd, uint64_t id)
     		fatal(0, "dmu_objset_snapshot(%s) = %d", fullname, error);
     	}
     
    -	error = dsl_dataset_user_hold(osname, snapname, tag, B_FALSE,
    -	    B_TRUE, -1);
    +	holds = fnvlist_alloc();
    +	fnvlist_add_string(holds, fullname, tag);
    +	error = dsl_dataset_user_hold(holds, 0, NULL);
    +	fnvlist_free(holds);
    +
     	if (error)
     		fatal(0, "dsl_dataset_user_hold(%s)", fullname, tag);
     
    -	error = dmu_objset_destroy(fullname, B_FALSE);
    +	error = dsl_destroy_snapshot(fullname, B_FALSE);
     	if (error != EBUSY) {
    -		fatal(0, "dmu_objset_destroy(%s, B_FALSE) = %d",
    +		fatal(0, "dsl_destroy_snapshot(%s, B_FALSE) = %d",
     		    fullname, error);
     	}
     
    -	error = dmu_objset_destroy(fullname, B_TRUE);
    +	error = dsl_destroy_snapshot(fullname, B_TRUE);
     	if (error) {
    -		fatal(0, "dmu_objset_destroy(%s, B_TRUE) = %d",
    +		fatal(0, "dsl_destroy_snapshot(%s, B_TRUE) = %d",
     		    fullname, error);
     	}
     
    -	error = dsl_dataset_user_release(osname, snapname, tag, B_FALSE);
    +	error = user_release_one(fullname, tag);
     	if (error)
    -		fatal(0, "dsl_dataset_user_release(%s)", fullname, tag);
    +		fatal(0, "user_release_one(%s)", fullname, tag);
     
    -	VERIFY(dmu_objset_hold(fullname, FTAG, &origin) == ENOENT);
    +	VERIFY3U(dmu_objset_hold(fullname, FTAG, &origin), ==, ENOENT);
     
     out:
     	(void) rw_unlock(&ztest_name_lock);
    @@ -4952,8 +4967,12 @@ ztest_ddt_repair(ztest_ds_t *zd, uint64_t id)
     	 */
     	for (int i = 0; i < copies; i++) {
     		uint64_t offset = i * blocksize;
    -		VERIFY0(dmu_buf_hold(os, object, offset, FTAG, &db,
    -		    DMU_READ_NO_PREFETCH));
    +		int error = dmu_buf_hold(os, object, offset, FTAG, &db,
    +		    DMU_READ_NO_PREFETCH);
    +		if (error != 0) {
    +			fatal(B_FALSE, "dmu_buf_hold(%p, %llu, %llu) = %u",
    +			    os, (long long)object, (long long) offset, error);
    +		}
     		ASSERT(db->db_offset == offset);
     		ASSERT(db->db_size == blocksize);
     		ASSERT(ztest_pattern_match(db->db_data, db->db_size, pattern) ||
    @@ -5163,6 +5182,7 @@ ztest_spa_import_export(char *oldname, char *newname)
     	nvlist_t *config, *newconfig;
     	uint64_t pool_guid;
     	spa_t *spa;
    +	int error;
     
     	if (ztest_opts.zo_verbose >= 4) {
     		(void) printf("import/export: old = %s, new = %s\n",
    @@ -5207,7 +5227,12 @@ ztest_spa_import_export(char *oldname, char *newname)
     	/*
     	 * Import it under the new name.
     	 */
    -	VERIFY3U(0, ==, spa_import(newname, config, NULL, 0));
    +	error = spa_import(newname, config, NULL, 0);
    +	if (error != 0) {
    +		dump_nvlist(config, 0);
    +		fatal(B_FALSE, "couldn't import pool %s as %s: error %u",
    +		    oldname, newname, error);
    +	}
     
     	ztest_walk_pool_directory("pools after import");
     
    @@ -5414,7 +5439,7 @@ ztest_dataset_open(int d)
     	}
     	ASSERT(error == 0 || error == EEXIST);
     
    -	VERIFY0(dmu_objset_hold(name, zd, &os));
    +	VERIFY0(dmu_objset_own(name, DMU_OST_OTHER, B_FALSE, zd, &os));
     	(void) rw_unlock(&ztest_name_lock);
     
     	ztest_zd_init(zd, ZTEST_GET_SHARED_DS(d), os);
    @@ -5455,7 +5480,7 @@ ztest_dataset_close(int d)
     	ztest_ds_t *zd = &ztest_ds[d];
     
     	zil_close(zd->zd_zilog);
    -	dmu_objset_rele(zd->zd_os, zd);
    +	dmu_objset_disown(zd->zd_os, zd);
     
     	ztest_zd_fini(zd);
     }
    @@ -5499,13 +5524,14 @@ ztest_run(ztest_shared_t *zs)
     	 * Open our pool.
     	 */
     	kernel_init(FREAD | FWRITE);
    -	VERIFY(spa_open(ztest_opts.zo_pool, &spa, FTAG) == 0);
    +	VERIFY0(spa_open(ztest_opts.zo_pool, &spa, FTAG));
     	spa->spa_debug = B_TRUE;
     	ztest_spa = spa;
     
    -	VERIFY3U(0, ==, dmu_objset_hold(ztest_opts.zo_pool, FTAG, &os));
    +	VERIFY0(dmu_objset_own(ztest_opts.zo_pool,
    +	    DMU_OST_ANY, B_TRUE, FTAG, &os));
     	zs->zs_guid = dmu_objset_fsid_guid(os);
    -	dmu_objset_rele(os, FTAG);
    +	dmu_objset_disown(os, FTAG);
     
     	spa->spa_dedup_ditto = 2 * ZIO_DEDUPDITTO_MIN;
     
    diff --git a/common/nvpair/fnvpair.c b/common/nvpair/fnvpair.c
    index 8c5591c0b2f..b3cf173f649 100644
    --- a/common/nvpair/fnvpair.c
    +++ b/common/nvpair/fnvpair.c
    @@ -26,6 +26,7 @@
     #include 
     #include 
     #include 
    +#include 
     #ifndef _KERNEL
     #include 
     #endif
    @@ -114,6 +115,18 @@ fnvlist_merge(nvlist_t *dst, nvlist_t *src)
     	VERIFY0(nvlist_merge(dst, src, KM_SLEEP));
     }
     
    +size_t
    +fnvlist_num_pairs(nvlist_t *nvl)
    +{
    +	size_t count = 0;
    +	nvpair_t *pair;
    +
    +	for (pair = nvlist_next_nvpair(nvl, 0); pair != NULL;
    +	    pair = nvlist_next_nvpair(nvl, pair))
    +		count++;
    +	return (count);
    +}
    +
     void
     fnvlist_add_boolean(nvlist_t *nvl, const char *name)
     {
    diff --git a/lib/libzfs/common/libzfs.h b/lib/libzfs/common/libzfs.h
    index 49c86dd18f7..4d1e8186d28 100644
    --- a/lib/libzfs/common/libzfs.h
    +++ b/lib/libzfs/common/libzfs.h
    @@ -550,7 +550,7 @@ extern int zfs_create(libzfs_handle_t *, const char *, zfs_type_t,
     extern int zfs_create_ancestors(libzfs_handle_t *, const char *);
     extern int zfs_destroy(zfs_handle_t *, boolean_t);
     extern int zfs_destroy_snaps(zfs_handle_t *, char *, boolean_t);
    -extern int zfs_destroy_snaps_nvl(zfs_handle_t *, nvlist_t *, boolean_t);
    +extern int zfs_destroy_snaps_nvl(libzfs_handle_t *, nvlist_t *, boolean_t);
     extern int zfs_clone(zfs_handle_t *, const char *, nvlist_t *);
     extern int zfs_snapshot(libzfs_handle_t *, const char *, boolean_t, nvlist_t *);
     extern int zfs_snapshot_nvl(libzfs_handle_t *hdl, nvlist_t *snaps,
    @@ -593,8 +593,8 @@ extern int zfs_send(zfs_handle_t *, const char *, const char *,
         sendflags_t *, int, snapfilter_cb_t, void *, nvlist_t **);
     
     extern int zfs_promote(zfs_handle_t *);
    -extern int zfs_hold(zfs_handle_t *, const char *, const char *, boolean_t,
    -    boolean_t, boolean_t, int, uint64_t, uint64_t);
    +extern int zfs_hold(zfs_handle_t *, const char *, const char *,
    +    boolean_t, boolean_t, int);
     extern int zfs_release(zfs_handle_t *, const char *, const char *, boolean_t);
     extern int zfs_get_holds(zfs_handle_t *, nvlist_t **);
     extern uint64_t zvol_volsize_to_reservation(uint64_t, nvlist_t *);
    diff --git a/lib/libzfs/common/libzfs_dataset.c b/lib/libzfs/common/libzfs_dataset.c
    index 3ad1ed69d57..6121a0f1618 100644
    --- a/lib/libzfs/common/libzfs_dataset.c
    +++ b/lib/libzfs/common/libzfs_dataset.c
    @@ -1973,10 +1973,7 @@ get_clones_cb(zfs_handle_t *zhp, void *arg)
     	    NULL, NULL, 0, B_TRUE) != 0)
     		goto out;
     	if (strcmp(gca->buf, gca->origin) == 0) {
    -		if (nvlist_add_boolean(gca->value, zfs_get_name(zhp)) != 0) {
    -			zfs_close(zhp);
    -			return (no_memory(zhp->zfs_hdl));
    -		}
    +		fnvlist_add_boolean(gca->value, zfs_get_name(zhp));
     		gca->numclones--;
     	}
     
    @@ -3142,45 +3139,49 @@ zfs_destroy_snaps(zfs_handle_t *zhp, char *snapname, boolean_t defer)
     		    dgettext(TEXT_DOMAIN, "cannot destroy '%s@%s'"),
     		    zhp->zfs_name, snapname);
     	} else {
    -		ret = zfs_destroy_snaps_nvl(zhp, dd.nvl, defer);
    +		ret = zfs_destroy_snaps_nvl(zhp->zfs_hdl, dd.nvl, defer);
     	}
     	nvlist_free(dd.nvl);
     	return (ret);
     }
     
     /*
    - * Destroys all the snapshots named in the nvlist.  They must be underneath
    - * the zhp (either snapshots of it, or snapshots of its descendants).
    + * Destroys all the snapshots named in the nvlist.
      */
     int
    -zfs_destroy_snaps_nvl(zfs_handle_t *zhp, nvlist_t *snaps, boolean_t defer)
    +zfs_destroy_snaps_nvl(libzfs_handle_t *hdl, nvlist_t *snaps, boolean_t defer)
     {
     	int ret;
     	nvlist_t *errlist;
     
     	ret = lzc_destroy_snaps(snaps, defer, &errlist);
     
    -	if (ret != 0) {
    -		for (nvpair_t *pair = nvlist_next_nvpair(errlist, NULL);
    -		    pair != NULL; pair = nvlist_next_nvpair(errlist, pair)) {
    -			char errbuf[1024];
    -			(void) snprintf(errbuf, sizeof (errbuf),
    -			    dgettext(TEXT_DOMAIN, "cannot destroy snapshot %s"),
    -			    nvpair_name(pair));
    +	if (ret == 0)
    +		return (0);
     
    -			switch (fnvpair_value_int32(pair)) {
    -			case EEXIST:
    -				zfs_error_aux(zhp->zfs_hdl,
    -				    dgettext(TEXT_DOMAIN,
    -				    "snapshot is cloned"));
    -				ret = zfs_error(zhp->zfs_hdl, EZFS_EXISTS,
    -				    errbuf);
    -				break;
    -			default:
    -				ret = zfs_standard_error(zhp->zfs_hdl, errno,
    -				    errbuf);
    -				break;
    -			}
    +	if (nvlist_next_nvpair(errlist, NULL) == NULL) {
    +		char errbuf[1024];
    +		(void) snprintf(errbuf, sizeof (errbuf),
    +		    dgettext(TEXT_DOMAIN, "cannot destroy snapshots"));
    +
    +		ret = zfs_standard_error(hdl, ret, errbuf);
    +	}
    +	for (nvpair_t *pair = nvlist_next_nvpair(errlist, NULL);
    +	    pair != NULL; pair = nvlist_next_nvpair(errlist, pair)) {
    +		char errbuf[1024];
    +		(void) snprintf(errbuf, sizeof (errbuf),
    +		    dgettext(TEXT_DOMAIN, "cannot destroy snapshot %s"),
    +		    nvpair_name(pair));
    +
    +		switch (fnvpair_value_int32(pair)) {
    +		case EEXIST:
    +			zfs_error_aux(hdl,
    +			    dgettext(TEXT_DOMAIN, "snapshot is cloned"));
    +			ret = zfs_error(hdl, EZFS_EXISTS, errbuf);
    +			break;
    +		default:
    +			ret = zfs_standard_error(hdl, errno, errbuf);
    +			break;
     		}
     	}
     
    @@ -4047,7 +4048,7 @@ zfs_userspace(zfs_handle_t *zhp, zfs_userquota_prop_t type,
     
     		zc.zc_nvlist_dst_size = sizeof (buf);
     		if (zfs_ioctl(hdl, ZFS_IOC_USERSPACE_MANY, &zc) != 0) {
    -			char errbuf[ZFS_MAXNAMELEN + 32];
    +			char errbuf[1024];
     
     			(void) snprintf(errbuf, sizeof (errbuf),
     			    dgettext(TEXT_DOMAIN,
    @@ -4069,37 +4070,83 @@ zfs_userspace(zfs_handle_t *zhp, zfs_userquota_prop_t type,
     	return (0);
     }
     
    +struct holdarg {
    +	nvlist_t *nvl;
    +	const char *snapname;
    +	const char *tag;
    +	boolean_t recursive;
    +};
    +
    +static int
    +zfs_hold_one(zfs_handle_t *zhp, void *arg)
    +{
    +	struct holdarg *ha = arg;
    +	zfs_handle_t *szhp;
    +	char name[ZFS_MAXNAMELEN];
    +	int rv = 0;
    +
    +	(void) snprintf(name, sizeof (name),
    +	    "%s@%s", zhp->zfs_name, ha->snapname);
    +
    +	szhp = make_dataset_handle(zhp->zfs_hdl, name);
    +	if (szhp) {
    +		fnvlist_add_string(ha->nvl, name, ha->tag);
    +		zfs_close(szhp);
    +	}
    +
    +	if (ha->recursive)
    +		rv = zfs_iter_filesystems(zhp, zfs_hold_one, ha);
    +	zfs_close(zhp);
    +	return (rv);
    +}
    +
     int
     zfs_hold(zfs_handle_t *zhp, const char *snapname, const char *tag,
    -    boolean_t recursive, boolean_t temphold, boolean_t enoent_ok,
    -    int cleanup_fd, uint64_t dsobj, uint64_t createtxg)
    +    boolean_t recursive, boolean_t enoent_ok, int cleanup_fd)
     {
    -	zfs_cmd_t zc = { 0 };
    +	int ret;
    +	struct holdarg ha;
    +	nvlist_t *errors;
     	libzfs_handle_t *hdl = zhp->zfs_hdl;
    +	char errbuf[1024];
    +	nvpair_t *elem;
     
    -	ASSERT(!recursive || dsobj == 0);
    +	ha.nvl = fnvlist_alloc();
    +	ha.snapname = snapname;
    +	ha.tag = tag;
    +	ha.recursive = recursive;
    +	(void) zfs_hold_one(zfs_handle_dup(zhp), &ha);
    +	ret = lzc_hold(ha.nvl, cleanup_fd, &errors);
    +	fnvlist_free(ha.nvl);
     
    -	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
    -	(void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value));
    -	if (strlcpy(zc.zc_string, tag, sizeof (zc.zc_string))
    -	    >= sizeof (zc.zc_string))
    -		return (zfs_error(hdl, EZFS_TAGTOOLONG, tag));
    -	zc.zc_cookie = recursive;
    -	zc.zc_temphold = temphold;
    -	zc.zc_cleanup_fd = cleanup_fd;
    -	zc.zc_sendobj = dsobj;
    -	zc.zc_createtxg = createtxg;
    +	if (ret == 0)
    +		return (0);
     
    -	if (zfs_ioctl(hdl, ZFS_IOC_HOLD, &zc) != 0) {
    -		char errbuf[ZFS_MAXNAMELEN+32];
    +	if (nvlist_next_nvpair(errors, NULL) == NULL) {
    +		/* no hold-specific errors */
    +		(void) snprintf(errbuf, sizeof (errbuf),
    +		    dgettext(TEXT_DOMAIN, "cannot hold"));
    +		switch (ret) {
    +		case ENOTSUP:
    +			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
    +			    "pool must be upgraded"));
    +			(void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
    +			break;
    +		case EINVAL:
    +			(void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
    +			break;
    +		default:
    +			(void) zfs_standard_error(hdl, ret, errbuf);
    +		}
    +	}
     
    -		/*
    -		 * if it was recursive, the one that actually failed will be in
    -		 * zc.zc_name.
    -		 */
    -		(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
    -		    "cannot hold '%s@%s'"), zc.zc_name, snapname);
    -		switch (errno) {
    +	for (elem = nvlist_next_nvpair(errors, NULL);
    +	    elem != NULL;
    +	    elem = nvlist_next_nvpair(errors, elem)) {
    +		(void) snprintf(errbuf, sizeof (errbuf),
    +		    dgettext(TEXT_DOMAIN,
    +		    "cannot hold snapshot '%s'"), nvpair_name(elem));
    +		switch (fnvpair_value_int32(elem)) {
     		case E2BIG:
     			/*
     			 * Temporary tags wind up having the ds object id
    @@ -4107,66 +4154,122 @@ zfs_hold(zfs_handle_t *zhp, const char *snapname, const char *tag,
     			 * above, it's still possible for the tag to wind
     			 * up being slightly too long.
     			 */
    -			return (zfs_error(hdl, EZFS_TAGTOOLONG, errbuf));
    -		case ENOTSUP:
    -			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
    -			    "pool must be upgraded"));
    -			return (zfs_error(hdl, EZFS_BADVERSION, errbuf));
    +			(void) zfs_error(hdl, EZFS_TAGTOOLONG, errbuf);
    +			break;
     		case EINVAL:
    -			return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
    +			(void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
    +			break;
     		case EEXIST:
    -			return (zfs_error(hdl, EZFS_REFTAG_HOLD, errbuf));
    +			(void) zfs_error(hdl, EZFS_REFTAG_HOLD, errbuf);
    +			break;
     		case ENOENT:
     			if (enoent_ok)
     				return (ENOENT);
     			/* FALLTHROUGH */
     		default:
    -			return (zfs_standard_error_fmt(hdl, errno, errbuf));
    +			(void) zfs_standard_error(hdl,
    +			    fnvpair_value_int32(elem), errbuf);
     		}
     	}
     
    -	return (0);
    +	fnvlist_free(errors);
    +	return (ret);
    +}
    +
    +struct releasearg {
    +	nvlist_t *nvl;
    +	const char *snapname;
    +	const char *tag;
    +	boolean_t recursive;
    +};
    +
    +static int
    +zfs_release_one(zfs_handle_t *zhp, void *arg)
    +{
    +	struct holdarg *ha = arg;
    +	zfs_handle_t *szhp;
    +	char name[ZFS_MAXNAMELEN];
    +	int rv = 0;
    +
    +	(void) snprintf(name, sizeof (name),
    +	    "%s@%s", zhp->zfs_name, ha->snapname);
    +
    +	szhp = make_dataset_handle(zhp->zfs_hdl, name);
    +	if (szhp) {
    +		nvlist_t *holds = fnvlist_alloc();
    +		fnvlist_add_boolean(holds, ha->tag);
    +		fnvlist_add_nvlist(ha->nvl, name, holds);
    +		zfs_close(szhp);
    +	}
    +
    +	if (ha->recursive)
    +		rv = zfs_iter_filesystems(zhp, zfs_release_one, ha);
    +	zfs_close(zhp);
    +	return (rv);
     }
     
     int
     zfs_release(zfs_handle_t *zhp, const char *snapname, const char *tag,
         boolean_t recursive)
     {
    -	zfs_cmd_t zc = { 0 };
    +	int ret;
    +	struct holdarg ha;
    +	nvlist_t *errors;
    +	nvpair_t *elem;
     	libzfs_handle_t *hdl = zhp->zfs_hdl;
     
    -	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
    -	(void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value));
    -	if (strlcpy(zc.zc_string, tag, sizeof (zc.zc_string))
    -	    >= sizeof (zc.zc_string))
    -		return (zfs_error(hdl, EZFS_TAGTOOLONG, tag));
    -	zc.zc_cookie = recursive;
    +	ha.nvl = fnvlist_alloc();
    +	ha.snapname = snapname;
    +	ha.tag = tag;
    +	ha.recursive = recursive;
    +	(void) zfs_release_one(zfs_handle_dup(zhp), &ha);
    +	ret = lzc_release(ha.nvl, &errors);
    +	fnvlist_free(ha.nvl);
     
    -	if (zfs_ioctl(hdl, ZFS_IOC_RELEASE, &zc) != 0) {
    -		char errbuf[ZFS_MAXNAMELEN+32];
    +	if (ret == 0)
    +		return (0);
    +
    +	if (nvlist_next_nvpair(errors, NULL) == NULL) {
    +		/* no hold-specific errors */
    +		char errbuf[1024];
     
    -		/*
    -		 * if it was recursive, the one that actually failed will be in
    -		 * zc.zc_name.
    -		 */
     		(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
    -		    "cannot release '%s' from '%s@%s'"), tag, zc.zc_name,
    -		    snapname);
    +		    "cannot release"));
     		switch (errno) {
    -		case ESRCH:
    -			return (zfs_error(hdl, EZFS_REFTAG_RELE, errbuf));
     		case ENOTSUP:
     			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
     			    "pool must be upgraded"));
    -			return (zfs_error(hdl, EZFS_BADVERSION, errbuf));
    -		case EINVAL:
    -			return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
    +			(void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
    +			break;
     		default:
    -			return (zfs_standard_error_fmt(hdl, errno, errbuf));
    +			(void) zfs_standard_error_fmt(hdl, errno, errbuf);
     		}
     	}
     
    -	return (0);
    +	for (elem = nvlist_next_nvpair(errors, NULL);
    +	    elem != NULL;
    +	    elem = nvlist_next_nvpair(errors, elem)) {
    +		char errbuf[1024];
    +
    +		(void) snprintf(errbuf, sizeof (errbuf),
    +		    dgettext(TEXT_DOMAIN,
    +		    "cannot release hold from snapshot '%s'"),
    +		    nvpair_name(elem));
    +		switch (fnvpair_value_int32(elem)) {
    +		case ESRCH:
    +			(void) zfs_error(hdl, EZFS_REFTAG_RELE, errbuf);
    +			break;
    +		case EINVAL:
    +			(void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
    +			break;
    +		default:
    +			(void) zfs_standard_error_fmt(hdl,
    +			    fnvpair_value_int32(elem), errbuf);
    +		}
    +	}
    +
    +	fnvlist_free(errors);
    +	return (ret);
     }
     
     int
    @@ -4177,7 +4280,7 @@ zfs_get_fsacl(zfs_handle_t *zhp, nvlist_t **nvl)
     	int nvsz = 2048;
     	void *nvbuf;
     	int err = 0;
    -	char errbuf[ZFS_MAXNAMELEN+32];
    +	char errbuf[1024];
     
     	assert(zhp->zfs_type == ZFS_TYPE_VOLUME ||
     	    zhp->zfs_type == ZFS_TYPE_FILESYSTEM);
    @@ -4242,7 +4345,7 @@ zfs_set_fsacl(zfs_handle_t *zhp, boolean_t un, nvlist_t *nvl)
     	zfs_cmd_t zc = { 0 };
     	libzfs_handle_t *hdl = zhp->zfs_hdl;
     	char *nvbuf;
    -	char errbuf[ZFS_MAXNAMELEN+32];
    +	char errbuf[1024];
     	size_t nvsz;
     	int err;
     
    @@ -4293,38 +4396,18 @@ zfs_set_fsacl(zfs_handle_t *zhp, boolean_t un, nvlist_t *nvl)
     int
     zfs_get_holds(zfs_handle_t *zhp, nvlist_t **nvl)
     {
    -	zfs_cmd_t zc = { 0 };
    -	libzfs_handle_t *hdl = zhp->zfs_hdl;
    -	int nvsz = 2048;
    -	void *nvbuf;
    -	int err = 0;
    -	char errbuf[ZFS_MAXNAMELEN+32];
    +	int err;
    +	char errbuf[1024];
     
    -	assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT);
    +	err = lzc_get_holds(zhp->zfs_name, nvl);
     
    -tryagain:
    +	if (err != 0) {
    +		libzfs_handle_t *hdl = zhp->zfs_hdl;
     
    -	nvbuf = malloc(nvsz);
    -	if (nvbuf == NULL) {
    -		err = (zfs_error(hdl, EZFS_NOMEM, strerror(errno)));
    -		goto out;
    -	}
    -
    -	zc.zc_nvlist_dst_size = nvsz;
    -	zc.zc_nvlist_dst = (uintptr_t)nvbuf;
    -
    -	(void) strlcpy(zc.zc_name, zhp->zfs_name, ZFS_MAXNAMELEN);
    -
    -	if (zfs_ioctl(hdl, ZFS_IOC_GET_HOLDS, &zc) != 0) {
     		(void) snprintf(errbuf, sizeof (errbuf),
     		    dgettext(TEXT_DOMAIN, "cannot get holds for '%s'"),
    -		    zc.zc_name);
    -		switch (errno) {
    -		case ENOMEM:
    -			free(nvbuf);
    -			nvsz = zc.zc_nvlist_dst_size;
    -			goto tryagain;
    -
    +		    zhp->zfs_name);
    +		switch (err) {
     		case ENOTSUP:
     			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
     			    "pool must be upgraded"));
    @@ -4340,19 +4423,8 @@ tryagain:
     			err = zfs_standard_error_fmt(hdl, errno, errbuf);
     			break;
     		}
    -	} else {
    -		/* success */
    -		int rc = nvlist_unpack(nvbuf, zc.zc_nvlist_dst_size, nvl, 0);
    -		if (rc) {
    -			(void) snprintf(errbuf, sizeof (errbuf),
    -			    dgettext(TEXT_DOMAIN, "cannot get holds for '%s'"),
    -			    zc.zc_name);
    -			err = zfs_standard_error_fmt(hdl, rc, errbuf);
    -		}
     	}
     
    -	free(nvbuf);
    -out:
     	return (err);
     }
     
    diff --git a/lib/libzfs/common/libzfs_sendrecv.c b/lib/libzfs/common/libzfs_sendrecv.c
    index ee6e64319e4..ea0634ee70c 100644
    --- a/lib/libzfs/common/libzfs_sendrecv.c
    +++ b/lib/libzfs/common/libzfs_sendrecv.c
    @@ -972,9 +972,7 @@ hold_for_send(zfs_handle_t *zhp, send_dump_data_t *sdd)
     	 */
     	if (pzhp) {
     		error = zfs_hold(pzhp, thissnap, sdd->holdtag,
    -		    B_FALSE, B_TRUE, B_TRUE, sdd->cleanup_fd,
    -		    zfs_prop_get_int(zhp, ZFS_PROP_OBJSETID),
    -		    zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG));
    +		    B_FALSE, B_TRUE, sdd->cleanup_fd);
     		zfs_close(pzhp);
     	}
     
    @@ -1713,12 +1711,11 @@ recv_rename(libzfs_handle_t *hdl, const char *name, const char *tryname,
     		err = ENOENT;
     	}
     
    -	if (err != 0 && strncmp(name+baselen, "recv-", 5) != 0) {
    +	if (err != 0 && strncmp(name + baselen, "recv-", 5) != 0) {
     		seq++;
     
    -		(void) strncpy(newname, name, baselen);
    -		(void) snprintf(newname+baselen, ZFS_MAXNAMELEN-baselen,
    -		    "recv-%u-%u", getpid(), seq);
    +		(void) snprintf(newname, ZFS_MAXNAMELEN, "%.*srecv-%u-%u",
    +		    baselen, name, getpid(), seq);
     		(void) strlcpy(zc.zc_value, newname, sizeof (zc.zc_value));
     
     		if (flags->verbose) {
    @@ -2643,7 +2640,6 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
     	/*
     	 * Determine name of destination snapshot, store in zc_value.
     	 */
    -	(void) strcpy(zc.zc_top_ds, tosnap);
     	(void) strcpy(zc.zc_value, tosnap);
     	(void) strncat(zc.zc_value, chopprefix, sizeof (zc.zc_value));
     	free(cp);
    diff --git a/lib/libzfs_core/common/libzfs_core.c b/lib/libzfs_core/common/libzfs_core.c
    index 73afd50b8de..5e8ee077967 100644
    --- a/lib/libzfs_core/common/libzfs_core.c
    +++ b/lib/libzfs_core/common/libzfs_core.c
    @@ -132,6 +132,7 @@ lzc_ioctl(zfs_ioc_t ioc, const char *name,
     	zc.zc_nvlist_src_size = size;
     
     	if (resultp != NULL) {
    +		*resultp = NULL;
     		zc.zc_nvlist_dst_size = MAX(size * 2, 128 * 1024);
     		zc.zc_nvlist_dst = (uint64_t)(uintptr_t)
     		    malloc(zc.zc_nvlist_dst_size);
    @@ -159,8 +160,6 @@ lzc_ioctl(zfs_ioc_t ioc, const char *name,
     	if (zc.zc_nvlist_dst_filled) {
     		*resultp = fnvlist_unpack((void *)(uintptr_t)zc.zc_nvlist_dst,
     		    zc.zc_nvlist_dst_size);
    -	} else if (resultp != NULL) {
    -		*resultp = NULL;
     	}
     
     out:
    @@ -209,7 +208,7 @@ lzc_clone(const char *fsname, const char *origin,
      * The value will be the (int32) error code.
      *
      * The return value will be 0 if all snapshots were created, otherwise it will
    - * be the errno of a (undetermined) snapshot that failed.
    + * be the errno of a (unspecified) snapshot that failed.
      */
     int
     lzc_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t **errlist)
    @@ -258,7 +257,7 @@ lzc_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t **errlist)
      * The return value will be 0 if all snapshots were destroyed (or marked for
      * later destruction if 'defer' is set) or didn't exist to begin with.
      *
    - * Otherwise the return value will be the errno of a (undetermined) snapshot
    + * Otherwise the return value will be the errno of a (unspecified) snapshot
      * that failed, no snapshots will be destroyed, and the errlist will have an
      * entry for each snapshot that failed.  The value in the errlist will be
      * the (int32) error code.
    @@ -332,6 +331,101 @@ lzc_exists(const char *dataset)
     	return (ioctl(g_fd, ZFS_IOC_OBJSET_STATS, &zc) == 0);
     }
     
    +/*
    + * Create "user holds" on snapshots.  If there is a hold on a snapshot,
    + * the snapshot can not be destroyed.  (However, it can be marked for deletion
    + * by lzc_destroy_snaps(defer=B_TRUE).)
    + *
    + * The keys in the nvlist are snapshot names.
    + * The snapshots must all be in the same pool.
    + * The value is the name of the hold (string type).
    + *
    + * If cleanup_fd is not -1, it must be the result of open("/dev/zfs", O_EXCL).
    + * In this case, when the cleanup_fd is closed (including on process
    + * termination), the holds will be released.  If the system is shut down
    + * uncleanly, the holds will be released when the pool is next opened
    + * or imported.
    + *
    + * The return value will be 0 if all holds were created. Otherwise the return
    + * value will be the errno of a (unspecified) hold that failed, no holds will
    + * be created, and the errlist will have an entry for each hold that
    + * failed (name = snapshot).  The value in the errlist will be the error
    + * code (int32).
    + */
    +int
    +lzc_hold(nvlist_t *holds, int cleanup_fd, nvlist_t **errlist)
    +{
    +	char pool[MAXNAMELEN];
    +	nvlist_t *args;
    +	nvpair_t *elem;
    +	int error;
    +
    +	/* determine the pool name */
    +	elem = nvlist_next_nvpair(holds, NULL);
    +	if (elem == NULL)
    +		return (0);
    +	(void) strlcpy(pool, nvpair_name(elem), sizeof (pool));
    +	pool[strcspn(pool, "/@")] = '\0';
    +
    +	args = fnvlist_alloc();
    +	fnvlist_add_nvlist(args, "holds", holds);
    +	if (cleanup_fd != -1)
    +		fnvlist_add_int32(args, "cleanup_fd", cleanup_fd);
    +
    +	error = lzc_ioctl(ZFS_IOC_HOLD, pool, args, errlist);
    +	nvlist_free(args);
    +	return (error);
    +}
    +
    +/*
    + * Release "user holds" on snapshots.  If the snapshot has been marked for
    + * deferred destroy (by lzc_destroy_snaps(defer=B_TRUE)), it does not have
    + * any clones, and all the user holds are removed, then the snapshot will be
    + * destroyed.
    + *
    + * The keys in the nvlist are snapshot names.
    + * The snapshots must all be in the same pool.
    + * The value is a nvlist whose keys are the holds to remove.
    + *
    + * The return value will be 0 if all holds were removed.
    + * Otherwise the return value will be the errno of a (unspecified) release
    + * that failed, no holds will be released, and the errlist will have an
    + * entry for each snapshot that has failed releases (name = snapshot).
    + * The value in the errlist will be the error code (int32) of a failed release.
    + */
    +int
    +lzc_release(nvlist_t *holds, nvlist_t **errlist)
    +{
    +	char pool[MAXNAMELEN];
    +	nvpair_t *elem;
    +
    +	/* determine the pool name */
    +	elem = nvlist_next_nvpair(holds, NULL);
    +	if (elem == NULL)
    +		return (0);
    +	(void) strlcpy(pool, nvpair_name(elem), sizeof (pool));
    +	pool[strcspn(pool, "/@")] = '\0';
    +
    +	return (lzc_ioctl(ZFS_IOC_RELEASE, pool, holds, errlist));
    +}
    +
    +/*
    + * Retrieve list of user holds on the specified snapshot.
    + *
    + * On success, *holdsp will be set to a nvlist which the caller must free.
    + * The keys are the names of the holds, and the value is the creation time
    + * of the hold (uint64) in seconds since the epoch.
    + */
    +int
    +lzc_get_holds(const char *snapname, nvlist_t **holdsp)
    +{
    +	int error;
    +	nvlist_t *innvl = fnvlist_alloc();
    +	error = lzc_ioctl(ZFS_IOC_GET_HOLDS, snapname, innvl, holdsp);
    +	fnvlist_free(innvl);
    +	return (error);
    +}
    +
     /*
      * If fromsnap is NULL, a full (non-incremental) stream will be sent.
      */
    diff --git a/lib/libzfs_core/common/libzfs_core.h b/lib/libzfs_core/common/libzfs_core.h
    index 9edc884a14d..f5fd6cda9f0 100644
    --- a/lib/libzfs_core/common/libzfs_core.h
    +++ b/lib/libzfs_core/common/libzfs_core.h
    @@ -46,6 +46,10 @@ int lzc_destroy_snaps(nvlist_t *snaps, boolean_t defer, nvlist_t **errlist);
     int lzc_snaprange_space(const char *firstsnap, const char *lastsnap,
         uint64_t *usedp);
     
    +int lzc_hold(nvlist_t *holds, int cleanup_fd, nvlist_t **errlist);
    +int lzc_release(nvlist_t *holds, nvlist_t **errlist);
    +int lzc_get_holds(const char *snapname, nvlist_t **holdsp);
    +
     int lzc_send(const char *snapname, const char *fromsnap, int fd);
     int lzc_receive(const char *snapname, nvlist_t *props, const char *origin,
         boolean_t force, int fd);
    diff --git a/lib/libzpool/common/kernel.c b/lib/libzpool/common/kernel.c
    index cc0d5428bee..96280941a64 100644
    --- a/lib/libzpool/common/kernel.c
    +++ b/lib/libzpool/common/kernel.c
    @@ -34,6 +34,7 @@
     #include 
     #include 
     #include 
    +#include 
     #include 
     #include 
     #include 
    @@ -859,6 +860,8 @@ umem_out_of_memory(void)
     void
     kernel_init(int mode)
     {
    +	extern uint_t rrw_tsd_key;
    +
     	umem_nofail_callback(umem_out_of_memory);
     
     	physmem = sysconf(_SC_PHYS_PAGES);
    @@ -877,6 +880,8 @@ kernel_init(int mode)
     	mutex_init(&cpu_lock, NULL, MUTEX_DEFAULT, NULL);
     
     	spa_init(mode);
    +
    +	tsd_create(&rrw_tsd_key, rrw_tsd_destroy);
     }
     
     void
    diff --git a/lib/libzpool/common/sys/zfs_context.h b/lib/libzpool/common/sys/zfs_context.h
    index bcb27cf1a5c..7802da4e2b0 100644
    --- a/lib/libzpool/common/sys/zfs_context.h
    +++ b/lib/libzpool/common/sys/zfs_context.h
    @@ -61,6 +61,8 @@ extern "C" {
     #include 
     #include 
     #include 
    +#include 
    +#include 
     #include 
     #include 
     #include 
    @@ -224,6 +226,9 @@ typedef int krw_t;
     #undef RW_WRITE_HELD
     #define	RW_WRITE_HELD(x)	_rw_write_held(&(x)->rw_lock)
     
    +#undef RW_LOCK_HELD
    +#define	RW_LOCK_HELD(x)		(RW_READ_HELD(x) || RW_WRITE_HELD(x))
    +
     extern void rw_init(krwlock_t *rwlp, char *name, int type, void *arg);
     extern void rw_destroy(krwlock_t *rwlp);
     extern void rw_enter(krwlock_t *rwlp, krw_t rw);
    @@ -252,6 +257,14 @@ extern clock_t cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime);
     extern void cv_signal(kcondvar_t *cv);
     extern void cv_broadcast(kcondvar_t *cv);
     
    +/*
    + * Thread-specific data
    + */
    +#define	tsd_get(k) pthread_getspecific(k)
    +#define	tsd_set(k, v) pthread_setspecific(k, v)
    +#define	tsd_create(kp, d) pthread_key_create(kp, d)
    +#define	tsd_destroy(kp) /* nothing */
    +
     /*
      * kstat creation, installation and deletion
      */
    @@ -519,7 +532,7 @@ typedef struct callb_cpr {
     #define	INGLOBALZONE(z)			(1)
     
     extern char *kmem_asprintf(const char *fmt, ...);
    -#define	strfree(str) kmem_free((str), strlen(str)+1)
    +#define	strfree(str) kmem_free((str), strlen(str) + 1)
     
     /*
      * Hostname information
    diff --git a/man/man1m/zfs.1m b/man/man1m/zfs.1m
    index 18441dad6ef..c4d579d7cbe 100644
    --- a/man/man1m/zfs.1m
    +++ b/man/man1m/zfs.1m
    @@ -1868,7 +1868,9 @@ descendent file systems.
     .ad
     .sp .6
     .RS 4n
    -Recursively destroy all dependents.
    +Recursively destroy all clones of these snapshots, including the clones,
    +snapshots, and children.  If this flag is specified, the \fB-d\fR flag will
    +have no effect.
     .RE
     
     .sp
    @@ -1904,7 +1906,7 @@ Print verbose information about the deleted data.
     .RE
     
     .sp
    -Extreme care should be taken when applying either the \fB-r\fR or the \fB-f\fR
    +Extreme care should be taken when applying either the \fB-r\fR or the \fB-R\fR
     options, as they can destroy large portions of a pool and cause unexpected
     behavior for mounted file systems in use.
     .RE
    diff --git a/uts/common/Makefile.files b/uts/common/Makefile.files
    index 1eb0e3158a7..e0fa959279a 100644
    --- a/uts/common/Makefile.files
    +++ b/uts/common/Makefile.files
    @@ -1346,8 +1346,10 @@ ZFS_COMMON_OBJS +=		\
     	dsl_dir.o		\
     	dsl_dataset.o		\
     	dsl_deadlist.o		\
    +	dsl_destroy.o		\
     	dsl_pool.o		\
     	dsl_synctask.o		\
    +	dsl_userhold.o		\
     	dmu_zfetch.o		\
     	dsl_deleg.o		\
     	dsl_prop.o		\
    @@ -1358,6 +1360,7 @@ ZFS_COMMON_OBJS +=		\
     	lzjb.o			\
     	metaslab.o		\
     	refcount.o		\
    +	rrwlock.o		\
     	sa.o			\
     	sha256.o		\
     	spa.o			\
    @@ -1417,7 +1420,6 @@ ZFS_OBJS +=			\
     	zfs_onexit.o		\
     	zfs_replay.o		\
     	zfs_rlock.o		\
    -	rrwlock.o		\
     	zfs_vfsops.o		\
     	zfs_vnops.o		\
     	zvol.o
    diff --git a/uts/common/fs/zfs/arc.c b/uts/common/fs/zfs/arc.c
    index ca3baeaeebb..9588e404332 100644
    --- a/uts/common/fs/zfs/arc.c
    +++ b/uts/common/fs/zfs/arc.c
    @@ -1633,12 +1633,12 @@ arc_buf_free(arc_buf_t *buf, void *tag)
     	}
     }
     
    -int
    +boolean_t
     arc_buf_remove_ref(arc_buf_t *buf, void* tag)
     {
     	arc_buf_hdr_t *hdr = buf->b_hdr;
     	kmutex_t *hash_lock = HDR_LOCK(hdr);
    -	int no_callback = (buf->b_efunc == NULL);
    +	boolean_t no_callback = (buf->b_efunc == NULL);
     
     	if (hdr->b_state == arc_anon) {
     		ASSERT(hdr->b_datacnt == 1);
    @@ -1843,7 +1843,7 @@ arc_evict(arc_state_t *state, uint64_t spa, int64_t bytes, boolean_t recycle,
     		ARCSTAT_INCR(arcstat_mutex_miss, missed);
     
     	/*
    -	 * We have just evicted some date into the ghost state, make
    +	 * We have just evicted some data into the ghost state, make
     	 * sure we also adjust the ghost state size if necessary.
     	 */
     	if (arc_no_grow &&
    @@ -2622,7 +2622,7 @@ arc_bcopy_func(zio_t *zio, arc_buf_t *buf, void *arg)
     {
     	if (zio == NULL || zio->io_error == 0)
     		bcopy(buf->b_data, arg, buf->b_hdr->b_size);
    -	VERIFY(arc_buf_remove_ref(buf, arg) == 1);
    +	VERIFY(arc_buf_remove_ref(buf, arg));
     }
     
     /* a generic arc_done_func_t */
    @@ -2631,7 +2631,7 @@ arc_getbuf_func(zio_t *zio, arc_buf_t *buf, void *arg)
     {
     	arc_buf_t **bufp = arg;
     	if (zio && zio->io_error) {
    -		VERIFY(arc_buf_remove_ref(buf, arg) == 1);
    +		VERIFY(arc_buf_remove_ref(buf, arg));
     		*bufp = NULL;
     	} else {
     		*bufp = buf;
    diff --git a/uts/common/fs/zfs/bplist.c b/uts/common/fs/zfs/bplist.c
    index 066ccc6b1e0..ee12db3a266 100644
    --- a/uts/common/fs/zfs/bplist.c
    +++ b/uts/common/fs/zfs/bplist.c
    @@ -20,6 +20,7 @@
      */
     /*
      * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2012 by Delphix. All rights reserved.
      */
     
     #include 
    @@ -52,6 +53,12 @@ bplist_append(bplist_t *bpl, const blkptr_t *bp)
     	mutex_exit(&bpl->bpl_lock);
     }
     
    +/*
    + * To aid debugging, we keep the most recently removed entry.  This way if
    + * we are in the callback, we can easily locate the entry.
    + */
    +static bplist_entry_t *bplist_iterate_last_removed;
    +
     void
     bplist_iterate(bplist_t *bpl, bplist_itor_t *func, void *arg, dmu_tx_t *tx)
     {
    @@ -59,6 +66,7 @@ bplist_iterate(bplist_t *bpl, bplist_itor_t *func, void *arg, dmu_tx_t *tx)
     
     	mutex_enter(&bpl->bpl_lock);
     	while (bpe = list_head(&bpl->bpl_list)) {
    +		bplist_iterate_last_removed = bpe;
     		list_remove(&bpl->bpl_list, bpe);
     		mutex_exit(&bpl->bpl_lock);
     		func(arg, &bpe->bpe_blk, tx);
    diff --git a/uts/common/fs/zfs/bpobj.c b/uts/common/fs/zfs/bpobj.c
    index 1920da4408c..bcb5f331f0b 100644
    --- a/uts/common/fs/zfs/bpobj.c
    +++ b/uts/common/fs/zfs/bpobj.c
    @@ -392,6 +392,10 @@ bpobj_enqueue_subobj(bpobj_t *bpo, uint64_t subobj, dmu_tx_t *tx)
     		    DMU_OT_BPOBJ_SUBOBJ, SPA_MAXBLOCKSIZE, DMU_OT_NONE, 0, tx);
     	}
     
    +	dmu_object_info_t doi;
    +	ASSERT0(dmu_object_info(bpo->bpo_os, bpo->bpo_phys->bpo_subobjs, &doi));
    +	ASSERT3U(doi.doi_type, ==, DMU_OT_BPOBJ_SUBOBJ);
    +
     	mutex_enter(&bpo->bpo_lock);
     	dmu_write(bpo->bpo_os, bpo->bpo_phys->bpo_subobjs,
     	    bpo->bpo_phys->bpo_num_subobjs * sizeof (subobj),
    diff --git a/uts/common/fs/zfs/dbuf.c b/uts/common/fs/zfs/dbuf.c
    index 8bf3d099ef0..57abfa10034 100644
    --- a/uts/common/fs/zfs/dbuf.c
    +++ b/uts/common/fs/zfs/dbuf.c
    @@ -39,7 +39,7 @@
     #include 
     
     static void dbuf_destroy(dmu_buf_impl_t *db);
    -static int dbuf_undirty(dmu_buf_impl_t *db, dmu_tx_t *tx);
    +static boolean_t dbuf_undirty(dmu_buf_impl_t *db, dmu_tx_t *tx);
     static void dbuf_write(dbuf_dirty_record_t *dr, arc_buf_t *data, dmu_tx_t *tx);
     
     /*
    @@ -499,7 +499,7 @@ dbuf_read_done(zio_t *zio, arc_buf_t *buf, void *vdb)
     	} else {
     		ASSERT(db->db_blkid != DMU_BONUS_BLKID);
     		ASSERT3P(db->db_buf, ==, NULL);
    -		VERIFY(arc_buf_remove_ref(buf, db) == 1);
    +		VERIFY(arc_buf_remove_ref(buf, db));
     		db->db_state = DB_UNCACHED;
     	}
     	cv_broadcast(&db->db_changed);
    @@ -828,10 +828,12 @@ dbuf_free_range(dnode_t *dn, uint64_t start, uint64_t end, dmu_tx_t *tx)
     			continue;
     
     		/* found a level 0 buffer in the range */
    -		if (dbuf_undirty(db, tx))
    -			continue;
    -
     		mutex_enter(&db->db_mtx);
    +		if (dbuf_undirty(db, tx)) {
    +			/* mutex has been dropped and dbuf destroyed */
    +			continue;
    +		}
    +
     		if (db->db_state == DB_UNCACHED ||
     		    db->db_state == DB_NOFILL ||
     		    db->db_state == DB_EVICTING) {
    @@ -958,7 +960,7 @@ dbuf_new_size(dmu_buf_impl_t *db, int size, dmu_tx_t *tx)
     
     	mutex_enter(&db->db_mtx);
     	dbuf_set_data(db, buf);
    -	VERIFY(arc_buf_remove_ref(obuf, db) == 1);
    +	VERIFY(arc_buf_remove_ref(obuf, db));
     	db->db.db_size = size;
     
     	if (db->db_level == 0) {
    @@ -1258,7 +1260,10 @@ dbuf_dirty(dmu_buf_impl_t *db, dmu_tx_t *tx)
     	return (dr);
     }
     
    -static int
    +/*
    + * Return TRUE if this evicted the dbuf.
    + */
    +static boolean_t
     dbuf_undirty(dmu_buf_impl_t *db, dmu_tx_t *tx)
     {
     	dnode_t *dn;
    @@ -1267,18 +1272,17 @@ dbuf_undirty(dmu_buf_impl_t *db, dmu_tx_t *tx)
     
     	ASSERT(txg != 0);
     	ASSERT(db->db_blkid != DMU_BONUS_BLKID);
    +	ASSERT0(db->db_level);
    +	ASSERT(MUTEX_HELD(&db->db_mtx));
     
    -	mutex_enter(&db->db_mtx);
     	/*
     	 * If this buffer is not dirty, we're done.
     	 */
     	for (drp = &db->db_last_dirty; (dr = *drp) != NULL; drp = &dr->dr_next)
     		if (dr->dr_txg <= txg)
     			break;
    -	if (dr == NULL || dr->dr_txg < txg) {
    -		mutex_exit(&db->db_mtx);
    -		return (0);
    -	}
    +	if (dr == NULL || dr->dr_txg < txg)
    +		return (B_FALSE);
     	ASSERT(dr->dr_txg == txg);
     	ASSERT(dr->dr_dbuf == db);
     
    @@ -1286,24 +1290,12 @@ dbuf_undirty(dmu_buf_impl_t *db, dmu_tx_t *tx)
     	dn = DB_DNODE(db);
     
     	/*
    -	 * If this buffer is currently held, we cannot undirty
    -	 * it, since one of the current holders may be in the
    -	 * middle of an update.  Note that users of dbuf_undirty()
    -	 * should not place a hold on the dbuf before the call.
    -	 * Also note: we can get here with a spill block, so
    -	 * test for that similar to how dbuf_dirty does.
    +	 * Note:  This code will probably work even if there are concurrent
    +	 * holders, but it is untested in that scenerio, as the ZPL and
    +	 * ztest have additional locking (the range locks) that prevents
    +	 * that type of concurrent access.
     	 */
    -	if (refcount_count(&db->db_holds) > db->db_dirtycnt) {
    -		mutex_exit(&db->db_mtx);
    -		/* Make sure we don't toss this buffer at sync phase */
    -		if (db->db_blkid != DMU_SPILL_BLKID) {
    -			mutex_enter(&dn->dn_mtx);
    -			dnode_clear_range(dn, db->db_blkid, 1, tx);
    -			mutex_exit(&dn->dn_mtx);
    -		}
    -		DB_DNODE_EXIT(db);
    -		return (0);
    -	}
    +	ASSERT3U(refcount_count(&db->db_holds), ==, db->db_dirtycnt);
     
     	dprintf_dbuf(db, "size=%llx\n", (u_longlong_t)db->db.db_size);
     
    @@ -1332,21 +1324,13 @@ dbuf_undirty(dmu_buf_impl_t *db, dmu_tx_t *tx)
     	}
     	DB_DNODE_EXIT(db);
     
    -	if (db->db_level == 0) {
    -		if (db->db_state != DB_NOFILL) {
    -			dbuf_unoverride(dr);
    +	if (db->db_state != DB_NOFILL) {
    +		dbuf_unoverride(dr);
     
    -			ASSERT(db->db_buf != NULL);
    -			ASSERT(dr->dt.dl.dr_data != NULL);
    -			if (dr->dt.dl.dr_data != db->db_buf)
    -				VERIFY(arc_buf_remove_ref(dr->dt.dl.dr_data,
    -				    db) == 1);
    -		}
    -	} else {
     		ASSERT(db->db_buf != NULL);
    -		ASSERT(list_head(&dr->dt.di.dr_children) == NULL);
    -		mutex_destroy(&dr->dt.di.dr_mtx);
    -		list_destroy(&dr->dt.di.dr_children);
    +		ASSERT(dr->dt.dl.dr_data != NULL);
    +		if (dr->dt.dl.dr_data != db->db_buf)
    +			VERIFY(arc_buf_remove_ref(dr->dt.dl.dr_data, db));
     	}
     	kmem_free(dr, sizeof (dbuf_dirty_record_t));
     
    @@ -1358,13 +1342,12 @@ dbuf_undirty(dmu_buf_impl_t *db, dmu_tx_t *tx)
     
     		ASSERT(db->db_state == DB_NOFILL || arc_released(buf));
     		dbuf_set_data(db, NULL);
    -		VERIFY(arc_buf_remove_ref(buf, db) == 1);
    +		VERIFY(arc_buf_remove_ref(buf, db));
     		dbuf_evict(db);
    -		return (1);
    +		return (B_TRUE);
     	}
     
    -	mutex_exit(&db->db_mtx);
    -	return (0);
    +	return (B_FALSE);
     }
     
     #pragma weak dmu_buf_will_dirty = dbuf_will_dirty
    @@ -1463,7 +1446,7 @@ dbuf_assign_arcbuf(dmu_buf_impl_t *db, arc_buf_t *buf, dmu_tx_t *tx)
     		mutex_exit(&db->db_mtx);
     		(void) dbuf_dirty(db, tx);
     		bcopy(buf->b_data, db->db.db_data, db->db.db_size);
    -		VERIFY(arc_buf_remove_ref(buf, db) == 1);
    +		VERIFY(arc_buf_remove_ref(buf, db));
     		xuio_stat_wbuf_copied();
     		return;
     	}
    @@ -1481,10 +1464,10 @@ dbuf_assign_arcbuf(dmu_buf_impl_t *db, arc_buf_t *buf, dmu_tx_t *tx)
     				arc_release(db->db_buf, db);
     			}
     			dr->dt.dl.dr_data = buf;
    -			VERIFY(arc_buf_remove_ref(db->db_buf, db) == 1);
    +			VERIFY(arc_buf_remove_ref(db->db_buf, db));
     		} else if (dr == NULL || dr->dt.dl.dr_data != db->db_buf) {
     			arc_release(db->db_buf, db);
    -			VERIFY(arc_buf_remove_ref(db->db_buf, db) == 1);
    +			VERIFY(arc_buf_remove_ref(db->db_buf, db));
     		}
     		db->db_buf = NULL;
     	}
    @@ -2067,10 +2050,10 @@ dbuf_rele_and_unlock(dmu_buf_impl_t *db, void *tag)
     			 * This dbuf has anonymous data associated with it.
     			 */
     			dbuf_set_data(db, NULL);
    -			VERIFY(arc_buf_remove_ref(buf, db) == 1);
    +			VERIFY(arc_buf_remove_ref(buf, db));
     			dbuf_evict(db);
     		} else {
    -			VERIFY(arc_buf_remove_ref(db->db_buf, db) == 0);
    +			VERIFY(!arc_buf_remove_ref(db->db_buf, db));
     
     			/*
     			 * A dbuf will be eligible for eviction if either the
    @@ -2567,7 +2550,7 @@ dbuf_write_done(zio_t *zio, arc_buf_t *buf, void *vdb)
     		if (db->db_state != DB_NOFILL) {
     			if (dr->dt.dl.dr_data != db->db_buf)
     				VERIFY(arc_buf_remove_ref(dr->dt.dl.dr_data,
    -				    db) == 1);
    +				    db));
     			else if (!arc_released(db->db_buf))
     				arc_set_callback(db->db_buf, dbuf_do_evict, db);
     		}
    diff --git a/uts/common/fs/zfs/dmu.c b/uts/common/fs/zfs/dmu.c
    index 21cdd7c1eda..6ee37ac8b77 100644
    --- a/uts/common/fs/zfs/dmu.c
    +++ b/uts/common/fs/zfs/dmu.c
    @@ -1194,7 +1194,7 @@ void
     dmu_return_arcbuf(arc_buf_t *buf)
     {
     	arc_return_buf(buf, FTAG);
    -	VERIFY(arc_buf_remove_ref(buf, FTAG) == 1);
    +	VERIFY(arc_buf_remove_ref(buf, FTAG));
     }
     
     /*
    diff --git a/uts/common/fs/zfs/dmu_diff.c b/uts/common/fs/zfs/dmu_diff.c
    index dc237780c0b..2d1aaa4c449 100644
    --- a/uts/common/fs/zfs/dmu_diff.c
    +++ b/uts/common/fs/zfs/dmu_diff.c
    @@ -20,6 +20,7 @@
      */
     /*
      * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2012 by Delphix. All rights reserved.
      */
     
     #include 
    @@ -155,51 +156,49 @@ diff_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
     }
     
     int
    -dmu_diff(objset_t *tosnap, objset_t *fromsnap, struct vnode *vp, offset_t *offp)
    +dmu_diff(const char *tosnap_name, const char *fromsnap_name,
    +    struct vnode *vp, offset_t *offp)
     {
     	struct diffarg da;
    -	dsl_dataset_t *ds = tosnap->os_dsl_dataset;
    -	dsl_dataset_t *fromds = fromsnap->os_dsl_dataset;
    -	dsl_dataset_t *findds;
    -	dsl_dataset_t *relds;
    -	int err = 0;
    +	dsl_dataset_t *fromsnap;
    +	dsl_dataset_t *tosnap;
    +	dsl_pool_t *dp;
    +	int error;
    +	uint64_t fromtxg;
     
    -	/* make certain we are looking at snapshots */
    -	if (!dsl_dataset_is_snapshot(ds) || !dsl_dataset_is_snapshot(fromds))
    +	if (strchr(tosnap_name, '@') == NULL ||
    +	    strchr(fromsnap_name, '@') == NULL)
     		return (EINVAL);
     
    -	/* fromsnap must be earlier and from the same lineage as tosnap */
    -	if (fromds->ds_phys->ds_creation_txg >= ds->ds_phys->ds_creation_txg)
    -		return (EXDEV);
    +	error = dsl_pool_hold(tosnap_name, FTAG, &dp);
    +	if (error != 0)
    +		return (error);
     
    -	relds = NULL;
    -	findds = ds;
    -
    -	while (fromds->ds_dir != findds->ds_dir) {
    -		dsl_pool_t *dp = ds->ds_dir->dd_pool;
    -
    -		if (!dsl_dir_is_clone(findds->ds_dir)) {
    -			if (relds)
    -				dsl_dataset_rele(relds, FTAG);
    -			return (EXDEV);
    -		}
    -
    -		rw_enter(&dp->dp_config_rwlock, RW_READER);
    -		err = dsl_dataset_hold_obj(dp,
    -		    findds->ds_dir->dd_phys->dd_origin_obj, FTAG, &findds);
    -		rw_exit(&dp->dp_config_rwlock);
    -
    -		if (relds)
    -			dsl_dataset_rele(relds, FTAG);
    -
    -		if (err)
    -			return (EXDEV);
    -
    -		relds = findds;
    +	error = dsl_dataset_hold(dp, tosnap_name, FTAG, &tosnap);
    +	if (error != 0) {
    +		dsl_pool_rele(dp, FTAG);
    +		return (error);
     	}
     
    -	if (relds)
    -		dsl_dataset_rele(relds, FTAG);
    +	error = dsl_dataset_hold(dp, fromsnap_name, FTAG, &fromsnap);
    +	if (error != 0) {
    +		dsl_dataset_rele(tosnap, FTAG);
    +		dsl_pool_rele(dp, FTAG);
    +		return (error);
    +	}
    +
    +	if (!dsl_dataset_is_before(tosnap, fromsnap)) {
    +		dsl_dataset_rele(fromsnap, FTAG);
    +		dsl_dataset_rele(tosnap, FTAG);
    +		dsl_pool_rele(dp, FTAG);
    +		return (EXDEV);
    +	}
    +
    +	fromtxg = fromsnap->ds_phys->ds_creation_txg;
    +	dsl_dataset_rele(fromsnap, FTAG);
    +
    +	dsl_dataset_long_hold(tosnap, FTAG);
    +	dsl_pool_rele(dp, FTAG);
     
     	da.da_vp = vp;
     	da.da_offp = offp;
    @@ -207,15 +206,18 @@ dmu_diff(objset_t *tosnap, objset_t *fromsnap, struct vnode *vp, offset_t *offp)
     	da.da_ddr.ddr_first = da.da_ddr.ddr_last = 0;
     	da.da_err = 0;
     
    -	err = traverse_dataset(ds, fromds->ds_phys->ds_creation_txg,
    +	error = traverse_dataset(tosnap, fromtxg,
     	    TRAVERSE_PRE | TRAVERSE_PREFETCH_METADATA, diff_cb, &da);
     
    -	if (err) {
    -		da.da_err = err;
    +	if (error != 0) {
    +		da.da_err = error;
     	} else {
     		/* we set the da.da_err we return as side-effect */
     		(void) write_record(&da);
     	}
     
    +	dsl_dataset_long_rele(tosnap, FTAG);
    +	dsl_dataset_rele(tosnap, FTAG);
    +
     	return (da.da_err);
     }
    diff --git a/uts/common/fs/zfs/dmu_objset.c b/uts/common/fs/zfs/dmu_objset.c
    index 74c1192017b..a646f404506 100644
    --- a/uts/common/fs/zfs/dmu_objset.c
    +++ b/uts/common/fs/zfs/dmu_objset.c
    @@ -44,6 +44,7 @@
     #include 
     #include 
     #include 
    +#include 
     
     /*
      * Needed to close a window in dnode_move() that allows the objset to be freed
    @@ -280,7 +281,7 @@ dmu_objset_open_impl(spa_t *spa, dsl_dataset_t *ds, blkptr_t *bp,
     		err = arc_read(NULL, spa, os->os_rootbp,
     		    arc_getbuf_func, &os->os_phys_buf,
     		    ZIO_PRIORITY_SYNC_READ, ZIO_FLAG_CANFAIL, &aflags, &zb);
    -		if (err) {
    +		if (err != 0) {
     			kmem_free(os, sizeof (objset_t));
     			/* convert checksum errors into IO errors */
     			if (err == ECKSUM)
    @@ -320,34 +321,49 @@ dmu_objset_open_impl(spa_t *spa, dsl_dataset_t *ds, blkptr_t *bp,
     	 * checksum/compression/copies.
     	 */
     	if (ds) {
    -		err = dsl_prop_register(ds, "primarycache",
    +		err = dsl_prop_register(ds,
    +		    zfs_prop_to_name(ZFS_PROP_PRIMARYCACHE),
     		    primary_cache_changed_cb, os);
    -		if (err == 0)
    -			err = dsl_prop_register(ds, "secondarycache",
    +		if (err == 0) {
    +			err = dsl_prop_register(ds,
    +			    zfs_prop_to_name(ZFS_PROP_SECONDARYCACHE),
     			    secondary_cache_changed_cb, os);
    -		if (!dsl_dataset_is_snapshot(ds)) {
    -			if (err == 0)
    -				err = dsl_prop_register(ds, "checksum",
    -				    checksum_changed_cb, os);
    -			if (err == 0)
    -				err = dsl_prop_register(ds, "compression",
    -				    compression_changed_cb, os);
    -			if (err == 0)
    -				err = dsl_prop_register(ds, "copies",
    -				    copies_changed_cb, os);
    -			if (err == 0)
    -				err = dsl_prop_register(ds, "dedup",
    -				    dedup_changed_cb, os);
    -			if (err == 0)
    -				err = dsl_prop_register(ds, "logbias",
    -				    logbias_changed_cb, os);
    -			if (err == 0)
    -				err = dsl_prop_register(ds, "sync",
    -				    sync_changed_cb, os);
     		}
    -		if (err) {
    +		if (!dsl_dataset_is_snapshot(ds)) {
    +			if (err == 0) {
    +				err = dsl_prop_register(ds,
    +				    zfs_prop_to_name(ZFS_PROP_CHECKSUM),
    +				    checksum_changed_cb, os);
    +			}
    +			if (err == 0) {
    +				err = dsl_prop_register(ds,
    +				    zfs_prop_to_name(ZFS_PROP_COMPRESSION),
    +				    compression_changed_cb, os);
    +			}
    +			if (err == 0) {
    +				err = dsl_prop_register(ds,
    +				    zfs_prop_to_name(ZFS_PROP_COPIES),
    +				    copies_changed_cb, os);
    +			}
    +			if (err == 0) {
    +				err = dsl_prop_register(ds,
    +				    zfs_prop_to_name(ZFS_PROP_DEDUP),
    +				    dedup_changed_cb, os);
    +			}
    +			if (err == 0) {
    +				err = dsl_prop_register(ds,
    +				    zfs_prop_to_name(ZFS_PROP_LOGBIAS),
    +				    logbias_changed_cb, os);
    +			}
    +			if (err == 0) {
    +				err = dsl_prop_register(ds,
    +				    zfs_prop_to_name(ZFS_PROP_SYNC),
    +				    sync_changed_cb, os);
    +			}
    +		}
    +		if (err != 0) {
     			VERIFY(arc_buf_remove_ref(os->os_phys_buf,
    -			    &os->os_phys_buf) == 1);
    +			    &os->os_phys_buf));
     			kmem_free(os, sizeof (objset_t));
     			return (err);
     		}
    @@ -425,44 +441,66 @@ dmu_objset_from_ds(dsl_dataset_t *ds, objset_t **osp)
     	return (err);
     }
     
    -/* called from zpl */
    +/*
    + * Holds the pool while the objset is held.  Therefore only one objset
    + * can be held at a time.
    + */
     int
     dmu_objset_hold(const char *name, void *tag, objset_t **osp)
     {
    +	dsl_pool_t *dp;
     	dsl_dataset_t *ds;
     	int err;
     
    -	err = dsl_dataset_hold(name, tag, &ds);
    -	if (err)
    +	err = dsl_pool_hold(name, tag, &dp);
    +	if (err != 0)
     		return (err);
    +	err = dsl_dataset_hold(dp, name, tag, &ds);
    +	if (err != 0) {
    +		dsl_pool_rele(dp, tag);
    +		return (err);
    +	}
     
     	err = dmu_objset_from_ds(ds, osp);
    -	if (err)
    +	if (err != 0) {
     		dsl_dataset_rele(ds, tag);
    +		dsl_pool_rele(dp, tag);
    +	}
     
     	return (err);
     }
     
    -/* called from zpl */
    +/*
    + * dsl_pool must not be held when this is called.
    + * Upon successful return, there will be a longhold on the dataset,
    + * and the dsl_pool will not be held.
    + */
     int
     dmu_objset_own(const char *name, dmu_objset_type_t type,
         boolean_t readonly, void *tag, objset_t **osp)
     {
    +	dsl_pool_t *dp;
     	dsl_dataset_t *ds;
     	int err;
     
    -	err = dsl_dataset_own(name, B_FALSE, tag, &ds);
    -	if (err)
    +	err = dsl_pool_hold(name, FTAG, &dp);
    +	if (err != 0)
     		return (err);
    +	err = dsl_dataset_own(dp, name, tag, &ds);
    +	if (err != 0) {
    +		dsl_pool_rele(dp, FTAG);
    +		return (err);
    +	}
     
     	err = dmu_objset_from_ds(ds, osp);
    -	if (err) {
    +	dsl_pool_rele(dp, FTAG);
    +	if (err != 0) {
     		dsl_dataset_disown(ds, tag);
     	} else if (type != DMU_OST_ANY && type != (*osp)->os_phys->os_type) {
    -		dmu_objset_disown(*osp, tag);
    +		dsl_dataset_disown(ds, tag);
     		return (EINVAL);
     	} else if (!readonly && dsl_dataset_is_snapshot(ds)) {
    -		dmu_objset_disown(*osp, tag);
    +		dsl_dataset_disown(ds, tag);
     		return (EROFS);
     	}
     	return (err);
    @@ -471,7 +509,9 @@ dmu_objset_own(const char *name, dmu_objset_type_t type,
     void
     dmu_objset_rele(objset_t *os, void *tag)
     {
    +	dsl_pool_t *dp = dmu_objset_pool(os);
     	dsl_dataset_rele(os->os_dsl_dataset, tag);
    +	dsl_pool_rele(dp, tag);
     }
     
     void
    @@ -480,7 +520,7 @@ dmu_objset_disown(objset_t *os, void *tag)
     	dsl_dataset_disown(os->os_dsl_dataset, tag);
     }
     
    -int
    +void
     dmu_objset_evict_dbufs(objset_t *os)
     {
     	dnode_t *dn;
    @@ -515,9 +555,7 @@ dmu_objset_evict_dbufs(objset_t *os)
     		mutex_enter(&os->os_lock);
     		dn = next_dn;
     	}
    -	dn = list_head(&os->os_dnodes);
     	mutex_exit(&os->os_lock);
    -	return (dn != DMU_META_DNODE(os));
     }
     
     void
    @@ -530,33 +568,37 @@ dmu_objset_evict(objset_t *os)
     
     	if (ds) {
     		if (!dsl_dataset_is_snapshot(ds)) {
    -			VERIFY(0 == dsl_prop_unregister(ds, "checksum",
    +			VERIFY0(dsl_prop_unregister(ds,
    +			    zfs_prop_to_name(ZFS_PROP_CHECKSUM),
     			    checksum_changed_cb, os));
    -			VERIFY(0 == dsl_prop_unregister(ds, "compression",
    +			VERIFY0(dsl_prop_unregister(ds,
    +			    zfs_prop_to_name(ZFS_PROP_COMPRESSION),
     			    compression_changed_cb, os));
    -			VERIFY(0 == dsl_prop_unregister(ds, "copies",
    +			VERIFY0(dsl_prop_unregister(ds,
    +			    zfs_prop_to_name(ZFS_PROP_COPIES),
     			    copies_changed_cb, os));
    -			VERIFY(0 == dsl_prop_unregister(ds, "dedup",
    +			VERIFY0(dsl_prop_unregister(ds,
    +			    zfs_prop_to_name(ZFS_PROP_DEDUP),
     			    dedup_changed_cb, os));
    -			VERIFY(0 == dsl_prop_unregister(ds, "logbias",
    +			VERIFY0(dsl_prop_unregister(ds,
    +			    zfs_prop_to_name(ZFS_PROP_LOGBIAS),
     			    logbias_changed_cb, os));
    -			VERIFY(0 == dsl_prop_unregister(ds, "sync",
    +			VERIFY0(dsl_prop_unregister(ds,
    +			    zfs_prop_to_name(ZFS_PROP_SYNC),
     			    sync_changed_cb, os));
     		}
    -		VERIFY(0 == dsl_prop_unregister(ds, "primarycache",
    +		VERIFY0(dsl_prop_unregister(ds,
    +		    zfs_prop_to_name(ZFS_PROP_PRIMARYCACHE),
     		    primary_cache_changed_cb, os));
    -		VERIFY(0 == dsl_prop_unregister(ds, "secondarycache",
    +		VERIFY0(dsl_prop_unregister(ds,
    +		    zfs_prop_to_name(ZFS_PROP_SECONDARYCACHE),
     		    secondary_cache_changed_cb, os));
     	}
     
     	if (os->os_sa)
     		sa_tear_down(os);
     
    -	/*
    -	 * We should need only a single pass over the dnode list, since
    -	 * nothing can be added to the list at this point.
    -	 */
    -	(void) dmu_objset_evict_dbufs(os);
    +	dmu_objset_evict_dbufs(os);
     
     	dnode_special_close(&os->os_meta_dnode);
     	if (DMU_USERUSED_DNODE(os)) {
    @@ -567,7 +609,7 @@ dmu_objset_evict(objset_t *os)
     
     	ASSERT3P(list_head(&os->os_dnodes), ==, NULL);
     
    -	VERIFY(arc_buf_remove_ref(os->os_phys_buf, &os->os_phys_buf) == 1);
    +	VERIFY(arc_buf_remove_ref(os->os_phys_buf, &os->os_phys_buf));
     
     	/*
     	 * This is a barrier to prevent the objset from going away in
    @@ -599,10 +641,11 @@ dmu_objset_create_impl(spa_t *spa, dsl_dataset_t *ds, blkptr_t *bp,
     	dnode_t *mdn;
     
     	ASSERT(dmu_tx_is_syncing(tx));
    +
     	if (ds != NULL)
    -		VERIFY(0 == dmu_objset_from_ds(ds, &os));
    +		VERIFY0(dmu_objset_from_ds(ds, &os));
     	else
    -		VERIFY(0 == dmu_objset_open_impl(spa, NULL, bp, &os));
    +		VERIFY0(dmu_objset_open_impl(spa, NULL, bp, &os));
     
     	mdn = DMU_META_DNODE(os);
     
    @@ -650,359 +693,181 @@ dmu_objset_create_impl(spa_t *spa, dsl_dataset_t *ds, blkptr_t *bp,
     	return (os);
     }
     
    -struct oscarg {
    -	void (*userfunc)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx);
    -	void *userarg;
    -	dsl_dataset_t *clone_origin;
    -	const char *lastname;
    -	dmu_objset_type_t type;
    -	uint64_t flags;
    -	cred_t *cr;
    -};
    +typedef struct dmu_objset_create_arg {
    +	const char *doca_name;
    +	cred_t *doca_cred;
    +	void (*doca_userfunc)(objset_t *os, void *arg,
    +	    cred_t *cr, dmu_tx_t *tx);
    +	void *doca_userarg;
    +	dmu_objset_type_t doca_type;
    +	uint64_t doca_flags;
    +} dmu_objset_create_arg_t;
     
     /*ARGSUSED*/
     static int
    -dmu_objset_create_check(void *arg1, void *arg2, dmu_tx_t *tx)
    +dmu_objset_create_check(void *arg, dmu_tx_t *tx)
     {
    -	dsl_dir_t *dd = arg1;
    -	struct oscarg *oa = arg2;
    -	objset_t *mos = dd->dd_pool->dp_meta_objset;
    -	int err;
    -	uint64_t ddobj;
    +	dmu_objset_create_arg_t *doca = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	dsl_dir_t *pdd;
    +	const char *tail;
    +	int error;
     
    -	err = zap_lookup(mos, dd->dd_phys->dd_child_dir_zapobj,
    -	    oa->lastname, sizeof (uint64_t), 1, &ddobj);
    -	if (err != ENOENT)
    -		return (err ? err : EEXIST);
    +	if (strchr(doca->doca_name, '@') != NULL)
    +		return (EINVAL);
     
    -	if (oa->clone_origin != NULL) {
    -		/* You can't clone across pools. */
    -		if (oa->clone_origin->ds_dir->dd_pool != dd->dd_pool)
    -			return (EXDEV);
    -
    -		/* You can only clone snapshots, not the head datasets. */
    -		if (!dsl_dataset_is_snapshot(oa->clone_origin))
    -			return (EINVAL);
    +	error = dsl_dir_hold(dp, doca->doca_name, FTAG, &pdd, &tail);
    +	if (error != 0)
    +		return (error);
    +	if (tail == NULL) {
    +		dsl_dir_rele(pdd, FTAG);
    +		return (EEXIST);
     	}
    +	dsl_dir_rele(pdd, FTAG);
     
     	return (0);
     }
     
     static void
    -dmu_objset_create_sync(void *arg1, void *arg2, dmu_tx_t *tx)
    +dmu_objset_create_sync(void *arg, dmu_tx_t *tx)
     {
    -	dsl_dir_t *dd = arg1;
    -	spa_t *spa = dd->dd_pool->dp_spa;
    -	struct oscarg *oa = arg2;
    -	uint64_t obj;
    +	dmu_objset_create_arg_t *doca = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	dsl_dir_t *pdd;
    +	const char *tail;
     	dsl_dataset_t *ds;
    +	uint64_t obj;
     	blkptr_t *bp;
    +	objset_t *os;
     
    -	ASSERT(dmu_tx_is_syncing(tx));
    +	VERIFY0(dsl_dir_hold(dp, doca->doca_name, FTAG, &pdd, &tail));
     
    -	obj = dsl_dataset_create_sync(dd, oa->lastname,
    -	    oa->clone_origin, oa->flags, oa->cr, tx);
    +	obj = dsl_dataset_create_sync(pdd, tail, NULL, doca->doca_flags,
    +	    doca->doca_cred, tx);
     
    -	VERIFY3U(0, ==, dsl_dataset_hold_obj(dd->dd_pool, obj, FTAG, &ds));
    +	VERIFY0(dsl_dataset_hold_obj(pdd->dd_pool, obj, FTAG, &ds));
     	bp = dsl_dataset_get_blkptr(ds);
    -	if (BP_IS_HOLE(bp)) {
    -		objset_t *os =
    -		    dmu_objset_create_impl(spa, ds, bp, oa->type, tx);
    +	os = dmu_objset_create_impl(pdd->dd_pool->dp_spa,
    +	    ds, bp, doca->doca_type, tx);
     
    -		if (oa->userfunc)
    -			oa->userfunc(os, oa->userarg, oa->cr, tx);
    +	if (doca->doca_userfunc != NULL) {
    +		doca->doca_userfunc(os, doca->doca_userarg,
    +		    doca->doca_cred, tx);
     	}
     
    -	if (oa->clone_origin == NULL) {
    -		spa_history_log_internal_ds(ds, "create", tx, "");
    -	} else {
    -		char namebuf[MAXNAMELEN];
    -		dsl_dataset_name(oa->clone_origin, namebuf);
    -		spa_history_log_internal_ds(ds, "clone", tx,
    -		    "origin=%s (%llu)", namebuf, oa->clone_origin->ds_object);
    -	}
    +	spa_history_log_internal_ds(ds, "create", tx, "");
     	dsl_dataset_rele(ds, FTAG);
    +	dsl_dir_rele(pdd, FTAG);
     }
     
     int
     dmu_objset_create(const char *name, dmu_objset_type_t type, uint64_t flags,
         void (*func)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx), void *arg)
     {
    -	dsl_dir_t *pdd;
    -	const char *tail;
    -	int err = 0;
    -	struct oscarg oa = { 0 };
    +	dmu_objset_create_arg_t doca;
     
    -	ASSERT(strchr(name, '@') == NULL);
    -	err = dsl_dir_open(name, FTAG, &pdd, &tail);
    -	if (err)
    -		return (err);
    -	if (tail == NULL) {
    -		dsl_dir_close(pdd, FTAG);
    -		return (EEXIST);
    -	}
    +	doca.doca_name = name;
    +	doca.doca_cred = CRED();
    +	doca.doca_flags = flags;
    +	doca.doca_userfunc = func;
    +	doca.doca_userarg = arg;
    +	doca.doca_type = type;
     
    -	oa.userfunc = func;
    -	oa.userarg = arg;
    -	oa.lastname = tail;
    -	oa.type = type;
    -	oa.flags = flags;
    -	oa.cr = CRED();
    -
    -	err = dsl_sync_task_do(pdd->dd_pool, dmu_objset_create_check,
    -	    dmu_objset_create_sync, pdd, &oa, 5);
    -	dsl_dir_close(pdd, FTAG);
    -	return (err);
    +	return (dsl_sync_task(name,
    +	    dmu_objset_create_check, dmu_objset_create_sync, &doca, 5));
     }
     
    -int
    -dmu_objset_clone(const char *name, dsl_dataset_t *clone_origin, uint64_t flags)
    -{
    -	dsl_dir_t *pdd;
    -	const char *tail;
    -	int err = 0;
    -	struct oscarg oa = { 0 };
    -
    -	ASSERT(strchr(name, '@') == NULL);
    -	err = dsl_dir_open(name, FTAG, &pdd, &tail);
    -	if (err)
    -		return (err);
    -	if (tail == NULL) {
    -		dsl_dir_close(pdd, FTAG);
    -		return (EEXIST);
    -	}
    -
    -	oa.lastname = tail;
    -	oa.clone_origin = clone_origin;
    -	oa.flags = flags;
    -	oa.cr = CRED();
    -
    -	err = dsl_sync_task_do(pdd->dd_pool, dmu_objset_create_check,
    -	    dmu_objset_create_sync, pdd, &oa, 5);
    -	dsl_dir_close(pdd, FTAG);
    -	return (err);
    -}
    -
    -int
    -dmu_objset_destroy(const char *name, boolean_t defer)
    -{
    -	dsl_dataset_t *ds;
    -	int error;
    -
    -	error = dsl_dataset_own(name, B_TRUE, FTAG, &ds);
    -	if (error == 0) {
    -		error = dsl_dataset_destroy(ds, FTAG, defer);
    -		/* dsl_dataset_destroy() closes the ds. */
    -	}
    -
    -	return (error);
    -}
    -
    -typedef struct snapallarg {
    -	dsl_sync_task_group_t *saa_dstg;
    -	boolean_t saa_needsuspend;
    -	nvlist_t *saa_props;
    -
    -	/* the following are used only if 'temporary' is set: */
    -	boolean_t saa_temporary;
    -	const char *saa_htag;
    -	struct dsl_ds_holdarg *saa_ha;
    -	dsl_dataset_t *saa_newds;
    -} snapallarg_t;
    -
    -typedef struct snaponearg {
    -	const char *soa_longname; /* long snap name */
    -	const char *soa_snapname; /* short snap name */
    -	snapallarg_t *soa_saa;
    -} snaponearg_t;
    +typedef struct dmu_objset_clone_arg {
    +	const char *doca_clone;
    +	const char *doca_origin;
    +	cred_t *doca_cred;
    +} dmu_objset_clone_arg_t;
     
    +/*ARGSUSED*/
     static int
    -snapshot_check(void *arg1, void *arg2, dmu_tx_t *tx)
    +dmu_objset_clone_check(void *arg, dmu_tx_t *tx)
     {
    -	objset_t *os = arg1;
    -	snaponearg_t *soa = arg2;
    -	snapallarg_t *saa = soa->soa_saa;
    +	dmu_objset_clone_arg_t *doca = arg;
    +	dsl_dir_t *pdd;
    +	const char *tail;
     	int error;
    +	dsl_dataset_t *origin;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
     
    -	/* The props have already been checked by zfs_check_userprops(). */
    +	if (strchr(doca->doca_clone, '@') != NULL)
    +		return (EINVAL);
     
    -	error = dsl_dataset_snapshot_check(os->os_dsl_dataset,
    -	    soa->soa_snapname, tx);
    -	if (error)
    +	error = dsl_dir_hold(dp, doca->doca_clone, FTAG, &pdd, &tail);
    +	if (error != 0)
    +		return (error);
    +	if (tail == NULL) {
    +		dsl_dir_rele(pdd, FTAG);
    +		return (EEXIST);
    +	}
    +	/* You can't clone across pools. */
    +	if (pdd->dd_pool != dp) {
    +		dsl_dir_rele(pdd, FTAG);
    +		return (EXDEV);
    +	}
    +	dsl_dir_rele(pdd, FTAG);
    +
    +	error = dsl_dataset_hold(dp, doca->doca_origin, FTAG, &origin);
    +	if (error != 0)
     		return (error);
     
    -	if (saa->saa_temporary) {
    -		/*
    -		 * Ideally we would just call
    -		 * dsl_dataset_user_hold_check() and
    -		 * dsl_dataset_destroy_check() here.  However the
    -		 * dataset we want to hold and destroy is the snapshot
    -		 * that we just confirmed we can create, but it won't
    -		 * exist until after these checks are run.  Do any
    -		 * checks we can here and if more checks are added to
    -		 * those routines in the future, similar checks may be
    -		 * necessary here.
    -		 */
    -		if (spa_version(os->os_spa) < SPA_VERSION_USERREFS)
    -			return (ENOTSUP);
    -		/*
    -		 * Not checking number of tags because the tag will be
    -		 * unique, as it will be the only tag.
    -		 */
    -		if (strlen(saa->saa_htag) + MAX_TAG_PREFIX_LEN >= MAXNAMELEN)
    -			return (E2BIG);
    -
    -		saa->saa_ha = kmem_alloc(sizeof (struct dsl_ds_holdarg),
    -		    KM_SLEEP);
    -		saa->saa_ha->temphold = B_TRUE;
    -		saa->saa_ha->htag = saa->saa_htag;
    -	}
    -	return (error);
    -}
    -
    -static void
    -snapshot_sync(void *arg1, void *arg2, dmu_tx_t *tx)
    -{
    -	objset_t *os = arg1;
    -	dsl_dataset_t *ds = os->os_dsl_dataset;
    -	snaponearg_t *soa = arg2;
    -	snapallarg_t *saa = soa->soa_saa;
    -
    -	dsl_dataset_snapshot_sync(ds, soa->soa_snapname, tx);
    -
    -	if (saa->saa_props != NULL) {
    -		dsl_props_arg_t pa;
    -		pa.pa_props = saa->saa_props;
    -		pa.pa_source = ZPROP_SRC_LOCAL;
    -		dsl_props_set_sync(ds->ds_prev, &pa, tx);
    +	/* You can't clone across pools. */
    +	if (origin->ds_dir->dd_pool != dp) {
    +		dsl_dataset_rele(origin, FTAG);
    +		return (EXDEV);
     	}
     
    -	if (saa->saa_temporary) {
    -		struct dsl_ds_destroyarg da;
    -
    -		dsl_dataset_user_hold_sync(ds->ds_prev, saa->saa_ha, tx);
    -		kmem_free(saa->saa_ha, sizeof (struct dsl_ds_holdarg));
    -		saa->saa_ha = NULL;
    -		saa->saa_newds = ds->ds_prev;
    -
    -		da.ds = ds->ds_prev;
    -		da.defer = B_TRUE;
    -		dsl_dataset_destroy_sync(&da, FTAG, tx);
    +	/* You can only clone snapshots, not the head datasets. */
    +	if (!dsl_dataset_is_snapshot(origin)) {
    +		dsl_dataset_rele(origin, FTAG);
    +		return (EINVAL);
     	}
    -}
    -
    -static int
    -snapshot_one_impl(const char *snapname, void *arg)
    -{
    -	char fsname[MAXPATHLEN];
    -	snapallarg_t *saa = arg;
    -	snaponearg_t *soa;
    -	objset_t *os;
    -	int err;
    -
    -	(void) strlcpy(fsname, snapname, sizeof (fsname));
    -	strchr(fsname, '@')[0] = '\0';
    -
    -	err = dmu_objset_hold(fsname, saa, &os);
    -	if (err != 0)
    -		return (err);
    -
    -	/*
    -	 * If the objset is in an inconsistent state (eg, in the process
    -	 * of being destroyed), don't snapshot it.
    -	 */
    -	if (os->os_dsl_dataset->ds_phys->ds_flags & DS_FLAG_INCONSISTENT) {
    -		dmu_objset_rele(os, saa);
    -		return (EBUSY);
    -	}
    -
    -	if (saa->saa_needsuspend) {
    -		err = zil_suspend(dmu_objset_zil(os));
    -		if (err) {
    -			dmu_objset_rele(os, saa);
    -			return (err);
    -		}
    -	}
    -
    -	soa = kmem_zalloc(sizeof (*soa), KM_SLEEP);
    -	soa->soa_saa = saa;
    -	soa->soa_longname = snapname;
    -	soa->soa_snapname = strchr(snapname, '@') + 1;
    -
    -	dsl_sync_task_create(saa->saa_dstg, snapshot_check, snapshot_sync,
    -	    os, soa, 3);
    +	dsl_dataset_rele(origin, FTAG);
     
     	return (0);
     }
     
    -/*
    - * The snapshots must all be in the same pool.
    - */
    -int
    -dmu_objset_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t *errors)
    +static void
    +dmu_objset_clone_sync(void *arg, dmu_tx_t *tx)
     {
    -	dsl_sync_task_t *dst;
    -	snapallarg_t saa = { 0 };
    -	spa_t *spa;
    -	int rv = 0;
    -	int err;
    -	nvpair_t *pair;
    +	dmu_objset_clone_arg_t *doca = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	dsl_dir_t *pdd;
    +	const char *tail;
    +	dsl_dataset_t *origin, *ds;
    +	uint64_t obj;
    +	char namebuf[MAXNAMELEN];
     
    -	pair = nvlist_next_nvpair(snaps, NULL);
    -	if (pair == NULL)
    -		return (0);
    +	VERIFY0(dsl_dir_hold(dp, doca->doca_clone, FTAG, &pdd, &tail));
    +	VERIFY0(dsl_dataset_hold(dp, doca->doca_origin, FTAG, &origin));
     
    -	err = spa_open(nvpair_name(pair), &spa, FTAG);
    -	if (err)
    -		return (err);
    -	saa.saa_dstg = dsl_sync_task_group_create(spa_get_dsl(spa));
    -	saa.saa_props = props;
    -	saa.saa_needsuspend = (spa_version(spa) < SPA_VERSION_FAST_SNAP);
    +	obj = dsl_dataset_create_sync(pdd, tail, origin, 0,
    +	    doca->doca_cred, tx);
     
    -	for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL;
    -	    pair = nvlist_next_nvpair(snaps, pair)) {
    -		err = snapshot_one_impl(nvpair_name(pair), &saa);
    -		if (err != 0) {
    -			if (errors != NULL) {
    -				fnvlist_add_int32(errors,
    -				    nvpair_name(pair), err);
    -			}
    -			rv = err;
    -		}
    -	}
    +	VERIFY0(dsl_dataset_hold_obj(pdd->dd_pool, obj, FTAG, &ds));
    +	dsl_dataset_name(origin, namebuf);
    +	spa_history_log_internal_ds(ds, "clone", tx,
    +	    "origin=%s (%llu)", namebuf, origin->ds_object);
    +	dsl_dataset_rele(ds, FTAG);
    +	dsl_dataset_rele(origin, FTAG);
    +	dsl_dir_rele(pdd, FTAG);
    +}
     
    -	/*
    -	 * If any call to snapshot_one_impl() failed, don't execute the
    -	 * sync task.  The error handling code below will clean up the
    -	 * snaponearg_t from any successful calls to
    -	 * snapshot_one_impl().
    -	 */
    -	if (rv == 0)
    -		err = dsl_sync_task_group_wait(saa.saa_dstg);
    -	if (err != 0)
    -		rv = err;
    +int
    +dmu_objset_clone(const char *clone, const char *origin)
    +{
    +	dmu_objset_clone_arg_t doca;
     
    -	for (dst = list_head(&saa.saa_dstg->dstg_tasks); dst;
    -	    dst = list_next(&saa.saa_dstg->dstg_tasks, dst)) {
    -		objset_t *os = dst->dst_arg1;
    -		snaponearg_t *soa = dst->dst_arg2;
    -		if (dst->dst_err != 0) {
    -			if (errors != NULL) {
    -				fnvlist_add_int32(errors,
    -				    soa->soa_longname, dst->dst_err);
    -			}
    -			rv = dst->dst_err;
    -		}
    +	doca.doca_clone = clone;
    +	doca.doca_origin = origin;
    +	doca.doca_cred = CRED();
     
    -		if (saa.saa_needsuspend)
    -			zil_resume(dmu_objset_zil(os));
    -		dmu_objset_rele(os, &saa);
    -		kmem_free(soa, sizeof (*soa));
    -	}
    -
    -	dsl_sync_task_group_destroy(saa.saa_dstg);
    -	spa_close(spa, FTAG);
    -	return (rv);
    +	return (dsl_sync_task(clone,
    +	    dmu_objset_clone_check, dmu_objset_clone_sync, &doca, 5));
     }
     
     int
    @@ -1013,59 +878,12 @@ dmu_objset_snapshot_one(const char *fsname, const char *snapname)
     	nvlist_t *snaps = fnvlist_alloc();
     
     	fnvlist_add_boolean(snaps, longsnap);
    -	err = dmu_objset_snapshot(snaps, NULL, NULL);
    -	fnvlist_free(snaps);
     	strfree(longsnap);
    +	err = dsl_dataset_snapshot(snaps, NULL, NULL);
    +	fnvlist_free(snaps);
     	return (err);
     }
     
    -int
    -dmu_objset_snapshot_tmp(const char *snapname, const char *tag, int cleanup_fd)
    -{
    -	dsl_sync_task_t *dst;
    -	snapallarg_t saa = { 0 };
    -	spa_t *spa;
    -	minor_t minor;
    -	int err;
    -
    -	err = spa_open(snapname, &spa, FTAG);
    -	if (err)
    -		return (err);
    -	saa.saa_dstg = dsl_sync_task_group_create(spa_get_dsl(spa));
    -	saa.saa_htag = tag;
    -	saa.saa_needsuspend = (spa_version(spa) < SPA_VERSION_FAST_SNAP);
    -	saa.saa_temporary = B_TRUE;
    -
    -	if (cleanup_fd < 0) {
    -		spa_close(spa, FTAG);
    -		return (EINVAL);
    -	}
    -	if ((err = zfs_onexit_fd_hold(cleanup_fd, &minor)) != 0) {
    -		spa_close(spa, FTAG);
    -		return (err);
    -	}
    -
    -	err = snapshot_one_impl(snapname, &saa);
    -
    -	if (err == 0)
    -		err = dsl_sync_task_group_wait(saa.saa_dstg);
    -
    -	for (dst = list_head(&saa.saa_dstg->dstg_tasks); dst;
    -	    dst = list_next(&saa.saa_dstg->dstg_tasks, dst)) {
    -		objset_t *os = dst->dst_arg1;
    -		dsl_register_onexit_hold_cleanup(saa.saa_newds, tag, minor);
    -		if (saa.saa_needsuspend)
    -			zil_resume(dmu_objset_zil(os));
    -		dmu_objset_rele(os, &saa);
    -	}
    -
    -	zfs_onexit_fd_rele(cleanup_fd);
    -	dsl_sync_task_group_destroy(saa.saa_dstg);
    -	spa_close(spa, FTAG);
    -	return (err);
    -}
    -
    -
     static void
     dmu_objset_sync_dnodes(list_t *list, list_t *newlist, dmu_tx_t *tx)
     {
    @@ -1101,9 +919,9 @@ dmu_objset_write_ready(zio_t *zio, arc_buf_t *abuf, void *arg)
     	objset_t *os = arg;
     	dnode_phys_t *dnp = &os->os_phys->os_meta_dnode;
     
    -	ASSERT(bp == os->os_rootbp);
    -	ASSERT(BP_GET_TYPE(bp) == DMU_OT_OBJSET);
    -	ASSERT(BP_GET_LEVEL(bp) == 0);
    +	ASSERT3P(bp, ==, os->os_rootbp);
    +	ASSERT3U(BP_GET_TYPE(bp), ==, DMU_OT_OBJSET);
    +	ASSERT0(BP_GET_LEVEL(bp));
     
     	/*
     	 * Update rootbp fill count: it should be the number of objects
    @@ -1210,7 +1028,7 @@ dmu_objset_sync(objset_t *os, zio_t *pio, dmu_tx_t *tx)
     
     	list = &DMU_META_DNODE(os)->dn_dirty_records[txgoff];
     	while (dr = list_head(list)) {
    -		ASSERT(dr->dr_dbuf->db_level == 0);
    +		ASSERT0(dr->dr_dbuf->db_level);
     		list_remove(list, dr);
     		if (dr->dr_zio)
     			zio_nowait(dr->dr_zio);
    @@ -1505,12 +1323,12 @@ dmu_objset_userspace_upgrade(objset_t *os)
     			return (EINTR);
     
     		objerr = dmu_bonus_hold(os, obj, FTAG, &db);
    -		if (objerr)
    +		if (objerr != 0)
     			continue;
     		tx = dmu_tx_create(os);
     		dmu_tx_hold_bonus(tx, obj);
     		objerr = dmu_tx_assign(tx, TXG_WAIT);
    -		if (objerr) {
    +		if (objerr != 0) {
     			dmu_tx_abort(tx);
     			continue;
     		}
    @@ -1593,6 +1411,8 @@ dmu_snapshot_list_next(objset_t *os, int namelen, char *name,
     	zap_cursor_t cursor;
     	zap_attribute_t attr;
     
    +	ASSERT(dsl_pool_config_held(dmu_objset_pool(os)));
    +
     	if (ds->ds_phys->ds_snapnames_zapobj == 0)
     		return (ENOENT);
     
    @@ -1659,64 +1479,34 @@ dmu_dir_list_next(objset_t *os, int namelen, char *name,
     	return (0);
     }
     
    -struct findarg {
    -	int (*func)(const char *, void *);
    -	void *arg;
    -};
    -
    -/* ARGSUSED */
    -static int
    -findfunc(spa_t *spa, uint64_t dsobj, const char *dsname, void *arg)
    -{
    -	struct findarg *fa = arg;
    -	return (fa->func(dsname, fa->arg));
    -}
    -
     /*
    - * Find all objsets under name, and for each, call 'func(child_name, arg)'.
    - * Perhaps change all callers to use dmu_objset_find_spa()?
    + * Find objsets under and including ddobj, call func(ds) on each.
      */
     int
    -dmu_objset_find(char *name, int func(const char *, void *), void *arg,
    -    int flags)
    -{
    -	struct findarg fa;
    -	fa.func = func;
    -	fa.arg = arg;
    -	return (dmu_objset_find_spa(NULL, name, findfunc, &fa, flags));
    -}
    -
    -/*
    - * Find all objsets under name, call func on each
    - */
    -int
    -dmu_objset_find_spa(spa_t *spa, const char *name,
    -    int func(spa_t *, uint64_t, const char *, void *), void *arg, int flags)
    +dmu_objset_find_dp(dsl_pool_t *dp, uint64_t ddobj,
    +    int func(dsl_pool_t *, dsl_dataset_t *, void *), void *arg, int flags)
     {
     	dsl_dir_t *dd;
    -	dsl_pool_t *dp;
     	dsl_dataset_t *ds;
     	zap_cursor_t zc;
     	zap_attribute_t *attr;
    -	char *child;
     	uint64_t thisobj;
     	int err;
     
    -	if (name == NULL)
    -		name = spa_name(spa);
    -	err = dsl_dir_open_spa(spa, name, FTAG, &dd, NULL);
    -	if (err)
    +	ASSERT(dsl_pool_config_held(dp));
    +
    +	err = dsl_dir_hold_obj(dp, ddobj, NULL, FTAG, &dd);
    +	if (err != 0)
     		return (err);
     
     	/* Don't visit hidden ($MOS & $ORIGIN) objsets. */
     	if (dd->dd_myname[0] == '$') {
    -		dsl_dir_close(dd, FTAG);
    +		dsl_dir_rele(dd, FTAG);
     		return (0);
     	}
     
     	thisobj = dd->dd_phys->dd_head_dataset_obj;
     	attr = kmem_alloc(sizeof (zap_attribute_t), KM_SLEEP);
    -	dp = dd->dd_pool;
     
     	/*
     	 * Iterate over all children.
    @@ -1726,19 +1516,19 @@ dmu_objset_find_spa(spa_t *spa, const char *name,
     		    dd->dd_phys->dd_child_dir_zapobj);
     		    zap_cursor_retrieve(&zc, attr) == 0;
     		    (void) zap_cursor_advance(&zc)) {
    -			ASSERT(attr->za_integer_length == sizeof (uint64_t));
    -			ASSERT(attr->za_num_integers == 1);
    +			ASSERT3U(attr->za_integer_length, ==,
    +			    sizeof (uint64_t));
    +			ASSERT3U(attr->za_num_integers, ==, 1);
     
    -			child = kmem_asprintf("%s/%s", name, attr->za_name);
    -			err = dmu_objset_find_spa(spa, child, func, arg, flags);
    -			strfree(child);
    -			if (err)
    +			err = dmu_objset_find_dp(dp, attr->za_first_integer,
    +			    func, arg, flags);
    +			if (err != 0)
     				break;
     		}
     		zap_cursor_fini(&zc);
     
    -		if (err) {
    -			dsl_dir_close(dd, FTAG);
    +		if (err != 0) {
    +			dsl_dir_rele(dd, FTAG);
     			kmem_free(attr, sizeof (zap_attribute_t));
     			return (err);
     		}
    @@ -1748,11 +1538,8 @@ dmu_objset_find_spa(spa_t *spa, const char *name,
     	 * Iterate over all snapshots.
     	 */
     	if (flags & DS_FIND_SNAPSHOTS) {
    -		if (!dsl_pool_sync_context(dp))
    -			rw_enter(&dp->dp_config_rwlock, RW_READER);
    +		dsl_dataset_t *ds;
     		err = dsl_dataset_hold_obj(dp, thisobj, FTAG, &ds);
    -		if (!dsl_pool_sync_context(dp))
    -			rw_exit(&dp->dp_config_rwlock);
     
     		if (err == 0) {
     			uint64_t snapobj = ds->ds_phys->ds_snapnames_zapobj;
    @@ -1761,64 +1548,166 @@ dmu_objset_find_spa(spa_t *spa, const char *name,
     			for (zap_cursor_init(&zc, dp->dp_meta_objset, snapobj);
     			    zap_cursor_retrieve(&zc, attr) == 0;
     			    (void) zap_cursor_advance(&zc)) {
    -				ASSERT(attr->za_integer_length ==
    +				ASSERT3U(attr->za_integer_length, ==,
     				    sizeof (uint64_t));
    -				ASSERT(attr->za_num_integers == 1);
    +				ASSERT3U(attr->za_num_integers, ==, 1);
     
    -				child = kmem_asprintf("%s@%s",
    -				    name, attr->za_name);
    -				err = func(spa, attr->za_first_integer,
    -				    child, arg);
    -				strfree(child);
    -				if (err)
    +				err = dsl_dataset_hold_obj(dp,
    +				    attr->za_first_integer, FTAG, &ds);
    +				if (err != 0)
    +					break;
    +				err = func(dp, ds, arg);
    +				dsl_dataset_rele(ds, FTAG);
    +				if (err != 0)
     					break;
     			}
     			zap_cursor_fini(&zc);
     		}
     	}
     
    -	dsl_dir_close(dd, FTAG);
    +	dsl_dir_rele(dd, FTAG);
     	kmem_free(attr, sizeof (zap_attribute_t));
     
    -	if (err)
    +	if (err != 0)
     		return (err);
     
     	/*
    -	 * Apply to self if appropriate.
    +	 * Apply to self.
     	 */
    -	err = func(spa, thisobj, name, arg);
    +	err = dsl_dataset_hold_obj(dp, thisobj, FTAG, &ds);
    +	if (err != 0)
    +		return (err);
    +	err = func(dp, ds, arg);
    +	dsl_dataset_rele(ds, FTAG);
     	return (err);
     }
     
    -/* ARGSUSED */
    -int
    -dmu_objset_prefetch(const char *name, void *arg)
    +/*
    + * Find all objsets under name, and for each, call 'func(child_name, arg)'.
    + * The dp_config_rwlock must not be held when this is called, and it
    + * will not be held when the callback is called.
    + * Therefore this function should only be used when the pool is not changing
    + * (e.g. in syncing context), or the callback can deal with the possible races.
    + */
    +static int
    +dmu_objset_find_impl(spa_t *spa, const char *name,
    +    int func(const char *, void *), void *arg, int flags)
     {
    +	dsl_dir_t *dd;
    +	dsl_pool_t *dp = spa_get_dsl(spa);
     	dsl_dataset_t *ds;
    +	zap_cursor_t zc;
    +	zap_attribute_t *attr;
    +	char *child;
    +	uint64_t thisobj;
    +	int err;
     
    -	if (dsl_dataset_hold(name, FTAG, &ds))
    -		return (0);
    +	dsl_pool_config_enter(dp, FTAG);
     
    -	if (!BP_IS_HOLE(&ds->ds_phys->ds_bp)) {
    -		mutex_enter(&ds->ds_opening_lock);
    -		if (ds->ds_objset == NULL) {
    -			uint32_t aflags = ARC_NOWAIT | ARC_PREFETCH;
    -			zbookmark_t zb;
    -
    -			SET_BOOKMARK(&zb, ds->ds_object, ZB_ROOT_OBJECT,
    -			    ZB_ROOT_LEVEL, ZB_ROOT_BLKID);
    -
    -			(void) arc_read(NULL, dsl_dataset_get_spa(ds),
    -			    &ds->ds_phys->ds_bp, NULL, NULL,
    -			    ZIO_PRIORITY_ASYNC_READ,
    -			    ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE,
    -			    &aflags, &zb);
    -		}
    -		mutex_exit(&ds->ds_opening_lock);
    +	err = dsl_dir_hold(dp, name, FTAG, &dd, NULL);
    +	if (err != 0) {
    +		dsl_pool_config_exit(dp, FTAG);
    +		return (err);
     	}
     
    -	dsl_dataset_rele(ds, FTAG);
    -	return (0);
    +	/* Don't visit hidden ($MOS & $ORIGIN) objsets. */
    +	if (dd->dd_myname[0] == '$') {
    +		dsl_dir_rele(dd, FTAG);
    +		dsl_pool_config_exit(dp, FTAG);
    +		return (0);
    +	}
    +
    +	thisobj = dd->dd_phys->dd_head_dataset_obj;
    +	attr = kmem_alloc(sizeof (zap_attribute_t), KM_SLEEP);
    +
    +	/*
    +	 * Iterate over all children.
    +	 */
    +	if (flags & DS_FIND_CHILDREN) {
    +		for (zap_cursor_init(&zc, dp->dp_meta_objset,
    +		    dd->dd_phys->dd_child_dir_zapobj);
    +		    zap_cursor_retrieve(&zc, attr) == 0;
    +		    (void) zap_cursor_advance(&zc)) {
    +			ASSERT3U(attr->za_integer_length, ==,
    +			    sizeof (uint64_t));
    +			ASSERT3U(attr->za_num_integers, ==, 1);
    +
    +			child = kmem_asprintf("%s/%s", name, attr->za_name);
    +			dsl_pool_config_exit(dp, FTAG);
    +			err = dmu_objset_find_impl(spa, child,
    +			    func, arg, flags);
    +			dsl_pool_config_enter(dp, FTAG);
    +			strfree(child);
    +			if (err != 0)
    +				break;
    +		}
    +		zap_cursor_fini(&zc);
    +
    +		if (err != 0) {
    +			dsl_dir_rele(dd, FTAG);
    +			dsl_pool_config_exit(dp, FTAG);
    +			kmem_free(attr, sizeof (zap_attribute_t));
    +			return (err);
    +		}
    +	}
    +
    +	/*
    +	 * Iterate over all snapshots.
    +	 */
    +	if (flags & DS_FIND_SNAPSHOTS) {
    +		err = dsl_dataset_hold_obj(dp, thisobj, FTAG, &ds);
    +
    +		if (err == 0) {
    +			uint64_t snapobj = ds->ds_phys->ds_snapnames_zapobj;
    +			dsl_dataset_rele(ds, FTAG);
    +
    +			for (zap_cursor_init(&zc, dp->dp_meta_objset, snapobj);
    +			    zap_cursor_retrieve(&zc, attr) == 0;
    +			    (void) zap_cursor_advance(&zc)) {
    +				ASSERT3U(attr->za_integer_length, ==,
    +				    sizeof (uint64_t));
    +				ASSERT3U(attr->za_num_integers, ==, 1);
    +
    +				child = kmem_asprintf("%s@%s",
    +				    name, attr->za_name);
    +				dsl_pool_config_exit(dp, FTAG);
    +				err = func(child, arg);
    +				dsl_pool_config_enter(dp, FTAG);
    +				strfree(child);
    +				if (err != 0)
    +					break;
    +			}
    +			zap_cursor_fini(&zc);
    +		}
    +	}
    +
    +	dsl_dir_rele(dd, FTAG);
    +	kmem_free(attr, sizeof (zap_attribute_t));
    +	dsl_pool_config_exit(dp, FTAG);
    +
    +	if (err != 0)
    +		return (err);
    +
    +	/* Apply to self. */
    +	return (func(name, arg));
    +}
    +
    +/*
    + * See comment above dmu_objset_find_impl().
    + */
    +int
    +dmu_objset_find(char *name, int func(const char *, void *), void *arg,
    +    int flags)
    +{
    +	spa_t *spa;
    +	int error;
    +
    +	error = spa_open(name, &spa, FTAG);
    +	if (error != 0)
    +		return (error);
    +	error = dmu_objset_find_impl(spa, name, func, arg, flags);
    +	spa_close(spa, FTAG);
    +	return (error);
     }
     
     void
    @@ -1834,3 +1723,19 @@ dmu_objset_get_user(objset_t *os)
     	ASSERT(MUTEX_HELD(&os->os_user_ptr_lock));
     	return (os->os_user_ptr);
     }
    +
    +/*
    + * Determine name of filesystem, given name of snapshot.
    + * buf must be at least MAXNAMELEN bytes
    + */
    +int
    +dmu_fsname(const char *snapname, char *buf)
    +{
    +	char *atp = strchr(snapname, '@');
    +	if (atp == NULL)
    +		return (EINVAL);
    +	if (atp - snapname >= MAXNAMELEN)
    +		return (ENAMETOOLONG);
    +	(void) strlcpy(buf, snapname, atp - snapname + 1);
    +	return (0);
    +}
    diff --git a/uts/common/fs/zfs/dmu_send.c b/uts/common/fs/zfs/dmu_send.c
    index c2493357d6d..a2a3647b4b2 100644
    --- a/uts/common/fs/zfs/dmu_send.c
    +++ b/uts/common/fs/zfs/dmu_send.c
    @@ -46,11 +46,14 @@
     #include 
     #include 
     #include 
    +#include 
    +#include 
     
     /* Set this tunable to TRUE to replace corrupt data with 0x2f5baddb10c */
     int zfs_send_corrupt_data = B_FALSE;
     
     static char *dmu_recv_tag = "dmu_recv_tag";
    +static const char *recv_clone_name = "%recv";
     
     static int
     dump_bytes(dmu_sendarg_t *dsp, void *buf, int len)
    @@ -290,7 +293,7 @@ dump_dnode(dmu_sendarg_t *dsp, uint64_t object, dnode_phys_t *dnp)
     	if (dump_free(dsp, object, (dnp->dn_maxblkid + 1) *
     	    (dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT), -1ULL))
     		return (EINTR);
    -	if (dsp->dsa_err)
    +	if (dsp->dsa_err != 0)
     		return (EINTR);
     	return (0);
     }
    @@ -340,7 +343,7 @@ backup_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
     			uint64_t dnobj = (zb->zb_blkid <<
     			    (DNODE_BLOCK_SHIFT - DNODE_SHIFT)) + i;
     			err = dump_dnode(dsp, dnobj, blk+i);
    -			if (err)
    +			if (err != 0)
     				break;
     		}
     		(void) arc_buf_remove_ref(abuf, &abuf);
    @@ -388,65 +391,33 @@ backup_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
     }
     
     /*
    - * Return TRUE if 'earlier' is an earlier snapshot in 'later's timeline.
    - * For example, they could both be snapshots of the same filesystem, and
    - * 'earlier' is before 'later'.  Or 'earlier' could be the origin of
    - * 'later's filesystem.  Or 'earlier' could be an older snapshot in the origin's
    - * filesystem.  Or 'earlier' could be the origin's origin.
    + * Releases dp, ds, and fromds, using the specified tag.
      */
    -static boolean_t
    -is_before(dsl_dataset_t *later, dsl_dataset_t *earlier)
    +static int
    +dmu_send_impl(void *tag, dsl_pool_t *dp, dsl_dataset_t *ds,
    +    dsl_dataset_t *fromds, int outfd, vnode_t *vp, offset_t *off)
     {
    -	dsl_pool_t *dp = later->ds_dir->dd_pool;
    -	int error;
    -	boolean_t ret;
    -	dsl_dataset_t *origin;
    -
    -	if (earlier->ds_phys->ds_creation_txg >=
    -	    later->ds_phys->ds_creation_txg)
    -		return (B_FALSE);
    -
    -	if (later->ds_dir == earlier->ds_dir)
    -		return (B_TRUE);
    -	if (!dsl_dir_is_clone(later->ds_dir))
    -		return (B_FALSE);
    -
    -	rw_enter(&dp->dp_config_rwlock, RW_READER);
    -	if (later->ds_dir->dd_phys->dd_origin_obj == earlier->ds_object) {
    -		rw_exit(&dp->dp_config_rwlock);
    -		return (B_TRUE);
    -	}
    -	error = dsl_dataset_hold_obj(dp,
    -	    later->ds_dir->dd_phys->dd_origin_obj, FTAG, &origin);
    -	rw_exit(&dp->dp_config_rwlock);
    -	if (error != 0)
    -		return (B_FALSE);
    -	ret = is_before(origin, earlier);
    -	dsl_dataset_rele(origin, FTAG);
    -	return (ret);
    -}
    -
    -int
    -dmu_send(objset_t *tosnap, objset_t *fromsnap, int outfd, vnode_t *vp,
    -    offset_t *off)
    -{
    -	dsl_dataset_t *ds = tosnap->os_dsl_dataset;
    -	dsl_dataset_t *fromds = fromsnap ? fromsnap->os_dsl_dataset : NULL;
    +	objset_t *os;
     	dmu_replay_record_t *drr;
     	dmu_sendarg_t *dsp;
     	int err;
     	uint64_t fromtxg = 0;
     
    -	/* tosnap must be a snapshot */
    -	if (ds->ds_phys->ds_next_snap_obj == 0)
    -		return (EINVAL);
    -
    -	/*
    -	 * fromsnap must be an earlier snapshot from the same fs as tosnap,
    -	 * or the origin's fs.
    -	 */
    -	if (fromds != NULL && !is_before(ds, fromds))
    +	if (fromds != NULL && !dsl_dataset_is_before(ds, fromds)) {
    +		dsl_dataset_rele(fromds, tag);
    +		dsl_dataset_rele(ds, tag);
    +		dsl_pool_rele(dp, tag);
     		return (EXDEV);
    +	}
    +
    +	err = dmu_objset_from_ds(ds, &os);
    +	if (err != 0) {
    +		if (fromds != NULL)
    +			dsl_dataset_rele(fromds, tag);
    +		dsl_dataset_rele(ds, tag);
    +		dsl_pool_rele(dp, tag);
    +		return (err);
    +	}
     
     	drr = kmem_zalloc(sizeof (dmu_replay_record_t), KM_SLEEP);
     	drr->drr_type = DRR_BEGIN;
    @@ -455,13 +426,17 @@ dmu_send(objset_t *tosnap, objset_t *fromsnap, int outfd, vnode_t *vp,
     	    DMU_SUBSTREAM);
     
     #ifdef _KERNEL
    -	if (dmu_objset_type(tosnap) == DMU_OST_ZFS) {
    +	if (dmu_objset_type(os) == DMU_OST_ZFS) {
     		uint64_t version;
    -		if (zfs_get_zplprop(tosnap, ZFS_PROP_VERSION, &version) != 0) {
    +		if (zfs_get_zplprop(os, ZFS_PROP_VERSION, &version) != 0) {
     			kmem_free(drr, sizeof (dmu_replay_record_t));
    +			if (fromds != NULL)
    +				dsl_dataset_rele(fromds, tag);
    +			dsl_dataset_rele(ds, tag);
    +			dsl_pool_rele(dp, tag);
     			return (EINVAL);
     		}
    -		if (version == ZPL_VERSION_SA) {
    +		if (version >= ZPL_VERSION_SA) {
     			DMU_SET_FEATUREFLAGS(
     			    drr->drr_u.drr_begin.drr_versioninfo,
     			    DMU_BACKUP_FEATURE_SA_SPILL);
    @@ -471,19 +446,22 @@ dmu_send(objset_t *tosnap, objset_t *fromsnap, int outfd, vnode_t *vp,
     
     	drr->drr_u.drr_begin.drr_creation_time =
     	    ds->ds_phys->ds_creation_time;
    -	drr->drr_u.drr_begin.drr_type = tosnap->os_phys->os_type;
    +	drr->drr_u.drr_begin.drr_type = dmu_objset_type(os);
     	if (fromds != NULL && ds->ds_dir != fromds->ds_dir)
     		drr->drr_u.drr_begin.drr_flags |= DRR_FLAG_CLONE;
     	drr->drr_u.drr_begin.drr_toguid = ds->ds_phys->ds_guid;
     	if (ds->ds_phys->ds_flags & DS_FLAG_CI_DATASET)
     		drr->drr_u.drr_begin.drr_flags |= DRR_FLAG_CI_DATA;
     
    -	if (fromds)
    +	if (fromds != NULL)
     		drr->drr_u.drr_begin.drr_fromguid = fromds->ds_phys->ds_guid;
     	dsl_dataset_name(ds, drr->drr_u.drr_begin.drr_toname);
     
    -	if (fromds)
    +	if (fromds != NULL) {
     		fromtxg = fromds->ds_phys->ds_creation_txg;
    +		dsl_dataset_rele(fromds, tag);
    +		fromds = NULL;
    +	}
     
     	dsp = kmem_zalloc(sizeof (dmu_sendarg_t), KM_SLEEP);
     
    @@ -491,7 +469,7 @@ dmu_send(objset_t *tosnap, objset_t *fromsnap, int outfd, vnode_t *vp,
     	dsp->dsa_vp = vp;
     	dsp->dsa_outfd = outfd;
     	dsp->dsa_proc = curproc;
    -	dsp->dsa_os = tosnap;
    +	dsp->dsa_os = os;
     	dsp->dsa_off = off;
     	dsp->dsa_toguid = ds->ds_phys->ds_guid;
     	ZIO_SET_CHECKSUM(&dsp->dsa_zc, 0, 0, 0, 0);
    @@ -506,6 +484,9 @@ dmu_send(objset_t *tosnap, objset_t *fromsnap, int outfd, vnode_t *vp,
     		goto out;
     	}
     
    +	dsl_dataset_long_hold(ds, FTAG);
    +	dsl_pool_rele(dp, tag);
    +
     	err = traverse_dataset(ds, fromtxg, TRAVERSE_PRE | TRAVERSE_PREFETCH,
     	    backup_cb, dsp);
     
    @@ -513,8 +494,8 @@ dmu_send(objset_t *tosnap, objset_t *fromsnap, int outfd, vnode_t *vp,
     		if (dump_bytes(dsp, drr, sizeof (dmu_replay_record_t)) != 0)
     			err = EINTR;
     
    -	if (err) {
    -		if (err == EINTR && dsp->dsa_err)
    +	if (err != 0) {
    +		if (err == EINTR && dsp->dsa_err != 0)
     			err = dsp->dsa_err;
     		goto out;
     	}
    @@ -537,27 +518,96 @@ out:
     	kmem_free(drr, sizeof (dmu_replay_record_t));
     	kmem_free(dsp, sizeof (dmu_sendarg_t));
     
    +	dsl_dataset_long_rele(ds, FTAG);
    +	dsl_dataset_rele(ds, tag);
    +
     	return (err);
     }
     
     int
    -dmu_send_estimate(objset_t *tosnap, objset_t *fromsnap, uint64_t *sizep)
    +dmu_send_obj(const char *pool, uint64_t tosnap, uint64_t fromsnap,
    +    int outfd, vnode_t *vp, offset_t *off)
    +{
    +	dsl_pool_t *dp;
    +	dsl_dataset_t *ds;
    +	dsl_dataset_t *fromds = NULL;
    +	int err;
    +
    +	err = dsl_pool_hold(pool, FTAG, &dp);
    +	if (err != 0)
    +		return (err);
    +
    +	err = dsl_dataset_hold_obj(dp, tosnap, FTAG, &ds);
    +	if (err != 0) {
    +		dsl_pool_rele(dp, FTAG);
    +		return (err);
    +	}
    +
    +	if (fromsnap != 0) {
    +		err = dsl_dataset_hold_obj(dp, fromsnap, FTAG, &fromds);
    +		if (err != 0) {
    +			dsl_dataset_rele(ds, FTAG);
    +			dsl_pool_rele(dp, FTAG);
    +			return (err);
    +		}
    +	}
    +
    +	return (dmu_send_impl(FTAG, dp, ds, fromds, outfd, vp, off));
    +}
    +
    +int
    +dmu_send(const char *tosnap, const char *fromsnap,
    +    int outfd, vnode_t *vp, offset_t *off)
    +{
    +	dsl_pool_t *dp;
    +	dsl_dataset_t *ds;
    +	dsl_dataset_t *fromds = NULL;
    +	int err;
    +
    +	if (strchr(tosnap, '@') == NULL)
    +		return (EINVAL);
    +	if (fromsnap != NULL && strchr(fromsnap, '@') == NULL)
    +		return (EINVAL);
    +
    +	err = dsl_pool_hold(tosnap, FTAG, &dp);
    +	if (err != 0)
    +		return (err);
    +
    +	err = dsl_dataset_hold(dp, tosnap, FTAG, &ds);
    +	if (err != 0) {
    +		dsl_pool_rele(dp, FTAG);
    +		return (err);
    +	}
    +
    +	if (fromsnap != NULL) {
    +		err = dsl_dataset_hold(dp, fromsnap, FTAG, &fromds);
    +		if (err != 0) {
    +			dsl_dataset_rele(ds, FTAG);
    +			dsl_pool_rele(dp, FTAG);
    +			return (err);
    +		}
    +	}
    +	return (dmu_send_impl(FTAG, dp, ds, fromds, outfd, vp, off));
    +}
    +
    +int
    +dmu_send_estimate(dsl_dataset_t *ds, dsl_dataset_t *fromds, uint64_t *sizep)
     {
    -	dsl_dataset_t *ds = tosnap->os_dsl_dataset;
    -	dsl_dataset_t *fromds = fromsnap ? fromsnap->os_dsl_dataset : NULL;
     	dsl_pool_t *dp = ds->ds_dir->dd_pool;
     	int err;
     	uint64_t size;
     
    +	ASSERT(dsl_pool_config_held(dp));
    +
     	/* tosnap must be a snapshot */
    -	if (ds->ds_phys->ds_next_snap_obj == 0)
    +	if (!dsl_dataset_is_snapshot(ds))
     		return (EINVAL);
     
     	/*
     	 * fromsnap must be an earlier snapshot from the same fs as tosnap,
     	 * or the origin's fs.
     	 */
    -	if (fromds != NULL && !is_before(ds, fromds))
    +	if (fromds != NULL && !dsl_dataset_is_before(ds, fromds))
     		return (EXDEV);
     
     	/* Get uncompressed size estimate of changed data. */
    @@ -567,7 +617,7 @@ dmu_send_estimate(objset_t *tosnap, objset_t *fromsnap, uint64_t *sizep)
     		uint64_t used, comp;
     		err = dsl_dataset_space_written(fromds, ds,
     		    &used, &comp, &size);
    -		if (err)
    +		if (err != 0)
     			return (err);
     	}
     
    @@ -587,11 +637,8 @@ dmu_send_estimate(objset_t *tosnap, objset_t *fromsnap, uint64_t *sizep)
     	 * block, which we observe in practice.
     	 */
     	uint64_t recordsize;
    -	rw_enter(&dp->dp_config_rwlock, RW_READER);
    -	err = dsl_prop_get_ds(ds, "recordsize",
    -	    sizeof (recordsize), 1, &recordsize, NULL);
    -	rw_exit(&dp->dp_config_rwlock);
    -	if (err)
    +	err = dsl_prop_get_int_ds(ds, "recordsize", &recordsize);
    +	if (err != 0)
     		return (err);
     	size -= size / recordsize * sizeof (blkptr_t);
     
    @@ -603,93 +650,40 @@ dmu_send_estimate(objset_t *tosnap, objset_t *fromsnap, uint64_t *sizep)
     	return (0);
     }
     
    -struct recvbeginsyncarg {
    -	const char *tofs;
    -	const char *tosnap;
    -	dsl_dataset_t *origin;
    -	uint64_t fromguid;
    -	dmu_objset_type_t type;
    -	void *tag;
    -	boolean_t force;
    -	uint64_t dsflags;
    -	char clonelastname[MAXNAMELEN];
    -	dsl_dataset_t *ds; /* the ds to recv into; returned from the syncfunc */
    -	cred_t *cr;
    -};
    +typedef struct dmu_recv_begin_arg {
    +	const char *drba_origin;
    +	dmu_recv_cookie_t *drba_cookie;
    +	cred_t *drba_cred;
    +} dmu_recv_begin_arg_t;
     
    -/* ARGSUSED */
     static int
    -recv_new_check(void *arg1, void *arg2, dmu_tx_t *tx)
    +recv_begin_check_existing_impl(dmu_recv_begin_arg_t *drba, dsl_dataset_t *ds,
    +    uint64_t fromguid)
     {
    -	dsl_dir_t *dd = arg1;
    -	struct recvbeginsyncarg *rbsa = arg2;
    -	objset_t *mos = dd->dd_pool->dp_meta_objset;
    -	uint64_t val;
    -	int err;
    -
    -	err = zap_lookup(mos, dd->dd_phys->dd_child_dir_zapobj,
    -	    strrchr(rbsa->tofs, '/') + 1, sizeof (uint64_t), 1, &val);
    -
    -	if (err != ENOENT)
    -		return (err ? err : EEXIST);
    -
    -	if (rbsa->origin) {
    -		/* make sure it's a snap in the same pool */
    -		if (rbsa->origin->ds_dir->dd_pool != dd->dd_pool)
    -			return (EXDEV);
    -		if (!dsl_dataset_is_snapshot(rbsa->origin))
    -			return (EINVAL);
    -		if (rbsa->origin->ds_phys->ds_guid != rbsa->fromguid)
    -			return (ENODEV);
    -	}
    -
    -	return (0);
    -}
    -
    -static void
    -recv_new_sync(void *arg1, void *arg2, dmu_tx_t *tx)
    -{
    -	dsl_dir_t *dd = arg1;
    -	struct recvbeginsyncarg *rbsa = arg2;
    -	uint64_t flags = DS_FLAG_INCONSISTENT | rbsa->dsflags;
    -	uint64_t dsobj;
    -
    -	/* Create and open new dataset. */
    -	dsobj = dsl_dataset_create_sync(dd, strrchr(rbsa->tofs, '/') + 1,
    -	    rbsa->origin, flags, rbsa->cr, tx);
    -	VERIFY(0 == dsl_dataset_own_obj(dd->dd_pool, dsobj,
    -	    B_TRUE, dmu_recv_tag, &rbsa->ds));
    -
    -	if (rbsa->origin == NULL) {
    -		(void) dmu_objset_create_impl(dd->dd_pool->dp_spa,
    -		    rbsa->ds, &rbsa->ds->ds_phys->ds_bp, rbsa->type, tx);
    -	}
    -
    -	spa_history_log_internal_ds(rbsa->ds, "receive new", tx, "");
    -}
    -
    -/* ARGSUSED */
    -static int
    -recv_existing_check(void *arg1, void *arg2, dmu_tx_t *tx)
    -{
    -	dsl_dataset_t *ds = arg1;
    -	struct recvbeginsyncarg *rbsa = arg2;
    -	int err;
     	uint64_t val;
    +	int error;
    +	dsl_pool_t *dp = ds->ds_dir->dd_pool;
     
     	/* must not have any changes since most recent snapshot */
    -	if (!rbsa->force && dsl_dataset_modified_since_lastsnap(ds))
    +	if (!drba->drba_cookie->drc_force &&
    +	    dsl_dataset_modified_since_lastsnap(ds))
     		return (ETXTBSY);
     
    -	/* new snapshot name must not exist */
    -	err = zap_lookup(ds->ds_dir->dd_pool->dp_meta_objset,
    -	    ds->ds_phys->ds_snapnames_zapobj, rbsa->tosnap, 8, 1, &val);
    -	if (err == 0)
    -		return (EEXIST);
    -	if (err != ENOENT)
    -		return (err);
    +	/* temporary clone name must not exist */
    +	error = zap_lookup(dp->dp_meta_objset,
    +	    ds->ds_dir->dd_phys->dd_child_dir_zapobj, recv_clone_name,
    +	    8, 1, &val);
    +	if (error != ENOENT)
    +		return (error == 0 ? EBUSY : error);
     
    -	if (rbsa->fromguid) {
    +	/* new snapshot name must not exist */
    +	error = zap_lookup(dp->dp_meta_objset,
    +	    ds->ds_phys->ds_snapnames_zapobj, drba->drba_cookie->drc_tosnap,
    +	    8, 1, &val);
    +	if (error != ENOENT)
    +		return (error == 0 ? EEXIST : error);
    +
    +	if (fromguid != 0) {
     		/* if incremental, most recent snapshot must match fromguid */
     		if (ds->ds_prev == NULL)
     			return (ENODEV);
    @@ -698,20 +692,20 @@ recv_existing_check(void *arg1, void *arg2, dmu_tx_t *tx)
     		 * most recent snapshot must match fromguid, or there are no
     		 * changes since the fromguid one
     		 */
    -		if (ds->ds_prev->ds_phys->ds_guid != rbsa->fromguid) {
    +		if (ds->ds_prev->ds_phys->ds_guid != fromguid) {
     			uint64_t birth = ds->ds_prev->ds_phys->ds_bp.blk_birth;
     			uint64_t obj = ds->ds_prev->ds_phys->ds_prev_snap_obj;
     			while (obj != 0) {
     				dsl_dataset_t *snap;
    -				err = dsl_dataset_hold_obj(ds->ds_dir->dd_pool,
    -				    obj, FTAG, &snap);
    -				if (err)
    +				error = dsl_dataset_hold_obj(dp, obj, FTAG,
    +				    &snap);
    +				if (error != 0)
     					return (ENODEV);
     				if (snap->ds_phys->ds_creation_txg < birth) {
     					dsl_dataset_rele(snap, FTAG);
     					return (ENODEV);
     				}
    -				if (snap->ds_phys->ds_guid == rbsa->fromguid) {
    +				if (snap->ds_phys->ds_guid == fromguid) {
     					dsl_dataset_rele(snap, FTAG);
     					break; /* it's ok */
     				}
    @@ -727,58 +721,153 @@ recv_existing_check(void *arg1, void *arg2, dmu_tx_t *tx)
     			return (ENODEV);
     	}
     
    -	/* temporary clone name must not exist */
    -	err = zap_lookup(ds->ds_dir->dd_pool->dp_meta_objset,
    -	    ds->ds_dir->dd_phys->dd_child_dir_zapobj,
    -	    rbsa->clonelastname, 8, 1, &val);
    -	if (err == 0)
    -		return (EEXIST);
    -	if (err != ENOENT)
    -		return (err);
    -
     	return (0);
    +
     }
     
    -/* ARGSUSED */
    -static void
    -recv_existing_sync(void *arg1, void *arg2, dmu_tx_t *tx)
    +static int
    +dmu_recv_begin_check(void *arg, dmu_tx_t *tx)
     {
    -	dsl_dataset_t *ohds = arg1;
    -	struct recvbeginsyncarg *rbsa = arg2;
    -	dsl_pool_t *dp = ohds->ds_dir->dd_pool;
    -	dsl_dataset_t *cds;
    -	uint64_t flags = DS_FLAG_INCONSISTENT | rbsa->dsflags;
    -	uint64_t dsobj;
    +	dmu_recv_begin_arg_t *drba = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	struct drr_begin *drrb = drba->drba_cookie->drc_drrb;
    +	uint64_t fromguid = drrb->drr_fromguid;
    +	int flags = drrb->drr_flags;
    +	int error;
    +	dsl_dataset_t *ds;
    +	const char *tofs = drba->drba_cookie->drc_tofs;
     
    -	/* create and open the temporary clone */
    -	dsobj = dsl_dataset_create_sync(ohds->ds_dir, rbsa->clonelastname,
    -	    ohds->ds_prev, flags, rbsa->cr, tx);
    -	VERIFY(0 == dsl_dataset_own_obj(dp, dsobj, B_TRUE, dmu_recv_tag, &cds));
    +	/* already checked */
    +	ASSERT3U(drrb->drr_magic, ==, DMU_BACKUP_MAGIC);
    +
    +	if (DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo) ==
    +	    DMU_COMPOUNDSTREAM ||
    +	    drrb->drr_type >= DMU_OST_NUMTYPES ||
    +	    ((flags & DRR_FLAG_CLONE) && drba->drba_origin == NULL))
    +		return (EINVAL);
    +
    +	/* Verify pool version supports SA if SA_SPILL feature set */
    +	if ((DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo) &
    +	    DMU_BACKUP_FEATURE_SA_SPILL) &&
    +	    spa_version(dp->dp_spa) < SPA_VERSION_SA) {
    +		return (ENOTSUP);
    +	}
    +
    +	error = dsl_dataset_hold(dp, tofs, FTAG, &ds);
    +	if (error == 0) {
    +		/* target fs already exists; recv into temp clone */
    +
    +		/* Can't recv a clone into an existing fs */
    +		if (flags & DRR_FLAG_CLONE) {
    +			dsl_dataset_rele(ds, FTAG);
    +			return (EINVAL);
    +		}
    +
    +		error = recv_begin_check_existing_impl(drba, ds, fromguid);
    +		dsl_dataset_rele(ds, FTAG);
    +	} else if (error == ENOENT) {
    +		/* target fs does not exist; must be a full backup or clone */
    +		char buf[MAXNAMELEN];
    +
    +		/*
    +		 * If it's a non-clone incremental, we are missing the
    +		 * target fs, so fail the recv.
    +		 */
    +		if (fromguid != 0 && !(flags & DRR_FLAG_CLONE))
    +			return (ENOENT);
    +
    +		/* Open the parent of tofs */
    +		ASSERT3U(strlen(tofs), <, MAXNAMELEN);
    +		(void) strlcpy(buf, tofs, strrchr(tofs, '/') - tofs + 1);
    +		error = dsl_dataset_hold(dp, buf, FTAG, &ds);
    +		if (error != 0)
    +			return (error);
    +
    +		if (drba->drba_origin != NULL) {
    +			dsl_dataset_t *origin;
    +			error = dsl_dataset_hold(dp, drba->drba_origin,
    +			    FTAG, &origin);
    +			if (error != 0) {
    +				dsl_dataset_rele(ds, FTAG);
    +				return (error);
    +			}
    +			if (!dsl_dataset_is_snapshot(origin)) {
    +				dsl_dataset_rele(origin, FTAG);
    +				dsl_dataset_rele(ds, FTAG);
    +				return (EINVAL);
    +			}
    +			if (origin->ds_phys->ds_guid != fromguid) {
    +				dsl_dataset_rele(origin, FTAG);
    +				dsl_dataset_rele(ds, FTAG);
    +				return (ENODEV);
    +			}
    +			dsl_dataset_rele(origin, FTAG);
    +		}
    +		dsl_dataset_rele(ds, FTAG);
    +		error = 0;
    +	}
    +	return (error);
    +}
    +
    +static void
    +dmu_recv_begin_sync(void *arg, dmu_tx_t *tx)
    +{
    +	dmu_recv_begin_arg_t *drba = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	struct drr_begin *drrb = drba->drba_cookie->drc_drrb;
    +	const char *tofs = drba->drba_cookie->drc_tofs;
    +	dsl_dataset_t *ds, *newds;
    +	uint64_t dsobj;
    +	int error;
    +	uint64_t crflags;
    +
    +	crflags = (drrb->drr_flags & DRR_FLAG_CI_DATA) ?
    +	    DS_FLAG_CI_DATASET : 0;
    +
    +	error = dsl_dataset_hold(dp, tofs, FTAG, &ds);
    +	if (error == 0) {
    +		/* create temporary clone */
    +		dsobj = dsl_dataset_create_sync(ds->ds_dir, recv_clone_name,
    +		    ds->ds_prev, crflags, drba->drba_cred, tx);
    +		dsl_dataset_rele(ds, FTAG);
    +	} else {
    +		dsl_dir_t *dd;
    +		const char *tail;
    +		dsl_dataset_t *origin = NULL;
    +
    +		VERIFY0(dsl_dir_hold(dp, tofs, FTAG, &dd, &tail));
    +
    +		if (drba->drba_origin != NULL) {
    +			VERIFY0(dsl_dataset_hold(dp, drba->drba_origin,
    +			    FTAG, &origin));
    +		}
    +
    +		/* Create new dataset. */
    +		dsobj = dsl_dataset_create_sync(dd,
    +		    strrchr(tofs, '/') + 1,
    +		    origin, crflags, drba->drba_cred, tx);
    +		if (origin != NULL)
    +			dsl_dataset_rele(origin, FTAG);
    +		dsl_dir_rele(dd, FTAG);
    +		drba->drba_cookie->drc_newfs = B_TRUE;
    +	}
    +	VERIFY0(dsl_dataset_own_obj(dp, dsobj, dmu_recv_tag, &newds));
    +
    +	dmu_buf_will_dirty(newds->ds_dbuf, tx);
    +	newds->ds_phys->ds_flags |= DS_FLAG_INCONSISTENT;
     
     	/*
     	 * If we actually created a non-clone, we need to create the
     	 * objset in our new dataset.
     	 */
    -	if (BP_IS_HOLE(dsl_dataset_get_blkptr(cds))) {
    +	if (BP_IS_HOLE(dsl_dataset_get_blkptr(newds))) {
     		(void) dmu_objset_create_impl(dp->dp_spa,
    -		    cds, dsl_dataset_get_blkptr(cds), rbsa->type, tx);
    +		    newds, dsl_dataset_get_blkptr(newds), drrb->drr_type, tx);
     	}
     
    -	rbsa->ds = cds;
    +	drba->drba_cookie->drc_ds = newds;
     
    -	spa_history_log_internal_ds(cds, "receive over existing", tx, "");
    -}
    -
    -static boolean_t
    -dmu_recv_verify_features(dsl_dataset_t *ds, struct drr_begin *drrb)
    -{
    -	int featureflags;
    -
    -	featureflags = DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo);
    -
    -	/* Verify pool version supports SA if SA_SPILL feature set */
    -	return ((featureflags & DMU_BACKUP_FEATURE_SA_SPILL) &&
    -	    (spa_version(dsl_dataset_get_spa(ds)) < SPA_VERSION_SA));
    +	spa_history_log_internal_ds(newds, "receive", tx, "");
     }
     
     /*
    @@ -786,132 +875,55 @@ dmu_recv_verify_features(dsl_dataset_t *ds, struct drr_begin *drrb)
      * succeeds; otherwise we will leak the holds on the datasets.
      */
     int
    -dmu_recv_begin(char *tofs, char *tosnap, char *top_ds, struct drr_begin *drrb,
    -    boolean_t force, objset_t *origin, dmu_recv_cookie_t *drc)
    +dmu_recv_begin(char *tofs, char *tosnap, struct drr_begin *drrb,
    +    boolean_t force, char *origin, dmu_recv_cookie_t *drc)
     {
    -	int err = 0;
    -	boolean_t byteswap;
    -	struct recvbeginsyncarg rbsa = { 0 };
    -	uint64_t versioninfo;
    -	int flags;
    -	dsl_dataset_t *ds;
    -
    -	if (drrb->drr_magic == DMU_BACKUP_MAGIC)
    -		byteswap = FALSE;
    -	else if (drrb->drr_magic == BSWAP_64(DMU_BACKUP_MAGIC))
    -		byteswap = TRUE;
    -	else
    -		return (EINVAL);
    -
    -	rbsa.tofs = tofs;
    -	rbsa.tosnap = tosnap;
    -	rbsa.origin = origin ? origin->os_dsl_dataset : NULL;
    -	rbsa.fromguid = drrb->drr_fromguid;
    -	rbsa.type = drrb->drr_type;
    -	rbsa.tag = FTAG;
    -	rbsa.dsflags = 0;
    -	rbsa.cr = CRED();
    -	versioninfo = drrb->drr_versioninfo;
    -	flags = drrb->drr_flags;
    -
    -	if (byteswap) {
    -		rbsa.type = BSWAP_32(rbsa.type);
    -		rbsa.fromguid = BSWAP_64(rbsa.fromguid);
    -		versioninfo = BSWAP_64(versioninfo);
    -		flags = BSWAP_32(flags);
    -	}
    -
    -	if (DMU_GET_STREAM_HDRTYPE(versioninfo) == DMU_COMPOUNDSTREAM ||
    -	    rbsa.type >= DMU_OST_NUMTYPES ||
    -	    ((flags & DRR_FLAG_CLONE) && origin == NULL))
    -		return (EINVAL);
    -
    -	if (flags & DRR_FLAG_CI_DATA)
    -		rbsa.dsflags = DS_FLAG_CI_DATASET;
    +	dmu_recv_begin_arg_t drba = { 0 };
    +	dmu_replay_record_t *drr;
     
     	bzero(drc, sizeof (dmu_recv_cookie_t));
     	drc->drc_drrb = drrb;
     	drc->drc_tosnap = tosnap;
    -	drc->drc_top_ds = top_ds;
    +	drc->drc_tofs = tofs;
     	drc->drc_force = force;
     
    -	/*
    -	 * Process the begin in syncing context.
    -	 */
    +	if (drrb->drr_magic == BSWAP_64(DMU_BACKUP_MAGIC))
    +		drc->drc_byteswap = B_TRUE;
    +	else if (drrb->drr_magic != DMU_BACKUP_MAGIC)
    +		return (EINVAL);
     
    -	/* open the dataset we are logically receiving into */
    -	err = dsl_dataset_hold(tofs, dmu_recv_tag, &ds);
    -	if (err == 0) {
    -		if (dmu_recv_verify_features(ds, drrb)) {
    -			dsl_dataset_rele(ds, dmu_recv_tag);
    -			return (ENOTSUP);
    -		}
    -		/* target fs already exists; recv into temp clone */
    +	drr = kmem_zalloc(sizeof (dmu_replay_record_t), KM_SLEEP);
    +	drr->drr_type = DRR_BEGIN;
    +	drr->drr_u.drr_begin = *drc->drc_drrb;
    +	if (drc->drc_byteswap) {
    +		fletcher_4_incremental_byteswap(drr,
    +		    sizeof (dmu_replay_record_t), &drc->drc_cksum);
    +	} else {
    +		fletcher_4_incremental_native(drr,
    +		    sizeof (dmu_replay_record_t), &drc->drc_cksum);
    +	}
    +	kmem_free(drr, sizeof (dmu_replay_record_t));
     
    -		/* Can't recv a clone into an existing fs */
    -		if (flags & DRR_FLAG_CLONE) {
    -			dsl_dataset_rele(ds, dmu_recv_tag);
    -			return (EINVAL);
    -		}
    -
    -		/* must not have an incremental recv already in progress */
    -		if (!mutex_tryenter(&ds->ds_recvlock)) {
    -			dsl_dataset_rele(ds, dmu_recv_tag);
    -			return (EBUSY);
    -		}
    -
    -		/* tmp clone name is: tofs/%tosnap" */
    -		(void) snprintf(rbsa.clonelastname, sizeof (rbsa.clonelastname),
    -		    "%%%s", tosnap);
    -		rbsa.force = force;
    -		err = dsl_sync_task_do(ds->ds_dir->dd_pool,
    -		    recv_existing_check, recv_existing_sync, ds, &rbsa, 5);
    -		if (err) {
    -			mutex_exit(&ds->ds_recvlock);
    -			dsl_dataset_rele(ds, dmu_recv_tag);
    -			return (err);
    -		}
    -		drc->drc_logical_ds = ds;
    -		drc->drc_real_ds = rbsa.ds;
    -	} else if (err == ENOENT) {
    -		/* target fs does not exist; must be a full backup or clone */
    -		char *cp;
    -
    -		/*
    -		 * If it's a non-clone incremental, we are missing the
    -		 * target fs, so fail the recv.
    -		 */
    -		if (rbsa.fromguid && !(flags & DRR_FLAG_CLONE))
    -			return (ENOENT);
    -
    -		/* Open the parent of tofs */
    -		cp = strrchr(tofs, '/');
    -		*cp = '\0';
    -		err = dsl_dataset_hold(tofs, FTAG, &ds);
    -		*cp = '/';
    -		if (err)
    -			return (err);
    -
    -		if (dmu_recv_verify_features(ds, drrb)) {
    -			dsl_dataset_rele(ds, FTAG);
    -			return (ENOTSUP);
    -		}
    -
    -		err = dsl_sync_task_do(ds->ds_dir->dd_pool,
    -		    recv_new_check, recv_new_sync, ds->ds_dir, &rbsa, 5);
    -		dsl_dataset_rele(ds, FTAG);
    -		if (err)
    -			return (err);
    -		drc->drc_logical_ds = drc->drc_real_ds = rbsa.ds;
    -		drc->drc_newfs = B_TRUE;
    +	if (drc->drc_byteswap) {
    +		drrb->drr_magic = BSWAP_64(drrb->drr_magic);
    +		drrb->drr_versioninfo = BSWAP_64(drrb->drr_versioninfo);
    +		drrb->drr_creation_time = BSWAP_64(drrb->drr_creation_time);
    +		drrb->drr_type = BSWAP_32(drrb->drr_type);
    +		drrb->drr_toguid = BSWAP_64(drrb->drr_toguid);
    +		drrb->drr_fromguid = BSWAP_64(drrb->drr_fromguid);
     	}
     
    -	return (err);
    +	drba.drba_origin = origin;
    +	drba.drba_cookie = drc;
    +	drba.drba_cred = CRED();
    +
    +	return (dsl_sync_task(tofs, dmu_recv_begin_check, dmu_recv_begin_sync,
    +	    &drba, 5));
     }
     
     struct restorearg {
     	int err;
    -	int byteswap;
    +	boolean_t byteswap;
     	vnode_t *vp;
     	char *buf;
     	uint64_t voff;
    @@ -947,7 +959,7 @@ free_guid_map_onexit(void *arg)
     	guid_map_entry_t *gmep;
     
     	while ((gmep = avl_destroy_nodes(ca, &cookie)) != NULL) {
    -		dsl_dataset_rele(gmep->gme_ds, ca);
    +		dsl_dataset_long_rele(gmep->gme_ds, gmep);
     		kmem_free(gmep, sizeof (guid_map_entry_t));
     	}
     	avl_destroy(ca);
    @@ -975,7 +987,7 @@ restore_read(struct restorearg *ra, int len)
     			ra->err = EINVAL;
     		ra->voff += len - done - resid;
     		done = len - resid;
    -		if (ra->err)
    +		if (ra->err != 0)
     			return (NULL);
     	}
     
    @@ -1094,7 +1106,7 @@ restore_object(struct restorearg *ra, objset_t *os, struct drr_object *drro)
     
     	if (drro->drr_bonuslen) {
     		data = restore_read(ra, P2ROUNDUP(drro->drr_bonuslen, 8));
    -		if (ra->err)
    +		if (ra->err != 0)
     			return (ra->err);
     	}
     
    @@ -1103,7 +1115,7 @@ restore_object(struct restorearg *ra, objset_t *os, struct drr_object *drro)
     		tx = dmu_tx_create(os);
     		dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT);
     		err = dmu_tx_assign(tx, TXG_WAIT);
    -		if (err) {
    +		if (err != 0) {
     			dmu_tx_abort(tx);
     			return (err);
     		}
    @@ -1117,14 +1129,14 @@ restore_object(struct restorearg *ra, objset_t *os, struct drr_object *drro)
     		    drro->drr_type, drro->drr_blksz,
     		    drro->drr_bonustype, drro->drr_bonuslen);
     	}
    -	if (err) {
    +	if (err != 0) {
     		return (EINVAL);
     	}
     
     	tx = dmu_tx_create(os);
     	dmu_tx_hold_bonus(tx, drro->drr_object);
     	err = dmu_tx_assign(tx, TXG_WAIT);
    -	if (err) {
    +	if (err != 0) {
     		dmu_tx_abort(tx);
     		return (err);
     	}
    @@ -1172,7 +1184,7 @@ restore_freeobjects(struct restorearg *ra, objset_t *os,
     			continue;
     
     		err = dmu_free_object(os, obj);
    -		if (err)
    +		if (err != 0)
     			return (err);
     	}
     	return (0);
    @@ -1202,7 +1214,7 @@ restore_write(struct restorearg *ra, objset_t *os,
     	dmu_tx_hold_write(tx, drrw->drr_object,
     	    drrw->drr_offset, drrw->drr_length);
     	err = dmu_tx_assign(tx, TXG_WAIT);
    -	if (err) {
    +	if (err != 0) {
     		dmu_tx_abort(tx);
     		return (err);
     	}
    @@ -1264,7 +1276,7 @@ restore_write_byref(struct restorearg *ra, objset_t *os,
     	dmu_tx_hold_write(tx, drrwbr->drr_object,
     	    drrwbr->drr_offset, drrwbr->drr_length);
     	err = dmu_tx_assign(tx, TXG_WAIT);
    -	if (err) {
    +	if (err != 0) {
     		dmu_tx_abort(tx);
     		return (err);
     	}
    @@ -1305,7 +1317,7 @@ restore_spill(struct restorearg *ra, objset_t *os, struct drr_spill *drrs)
     	dmu_tx_hold_spill(tx, db->db_object);
     
     	err = dmu_tx_assign(tx, TXG_WAIT);
    -	if (err) {
    +	if (err != 0) {
     		dmu_buf_rele(db, FTAG);
     		dmu_buf_rele(db_spill, FTAG);
     		dmu_tx_abort(tx);
    @@ -1344,6 +1356,16 @@ restore_free(struct restorearg *ra, objset_t *os,
     	return (err);
     }
     
    +/* used to destroy the drc_ds on error */
    +static void
    +dmu_recv_cleanup_ds(dmu_recv_cookie_t *drc)
    +{
    +	char name[MAXNAMELEN];
    +	dsl_dataset_name(drc->drc_ds, name);
    +	dsl_dataset_disown(drc->drc_ds, dmu_recv_tag);
    +	(void) dsl_destroy_head(name);
    +}
    +
     /*
      * NB: callers *must* call dmu_recv_end() if this succeeds.
      */
    @@ -1357,52 +1379,24 @@ dmu_recv_stream(dmu_recv_cookie_t *drc, vnode_t *vp, offset_t *voffp,
     	zio_cksum_t pcksum;
     	int featureflags;
     
    -	if (drc->drc_drrb->drr_magic == BSWAP_64(DMU_BACKUP_MAGIC))
    -		ra.byteswap = TRUE;
    -
    -	{
    -		/* compute checksum of drr_begin record */
    -		dmu_replay_record_t *drr;
    -		drr = kmem_zalloc(sizeof (dmu_replay_record_t), KM_SLEEP);
    -
    -		drr->drr_type = DRR_BEGIN;
    -		drr->drr_u.drr_begin = *drc->drc_drrb;
    -		if (ra.byteswap) {
    -			fletcher_4_incremental_byteswap(drr,
    -			    sizeof (dmu_replay_record_t), &ra.cksum);
    -		} else {
    -			fletcher_4_incremental_native(drr,
    -			    sizeof (dmu_replay_record_t), &ra.cksum);
    -		}
    -		kmem_free(drr, sizeof (dmu_replay_record_t));
    -	}
    -
    -	if (ra.byteswap) {
    -		struct drr_begin *drrb = drc->drc_drrb;
    -		drrb->drr_magic = BSWAP_64(drrb->drr_magic);
    -		drrb->drr_versioninfo = BSWAP_64(drrb->drr_versioninfo);
    -		drrb->drr_creation_time = BSWAP_64(drrb->drr_creation_time);
    -		drrb->drr_type = BSWAP_32(drrb->drr_type);
    -		drrb->drr_toguid = BSWAP_64(drrb->drr_toguid);
    -		drrb->drr_fromguid = BSWAP_64(drrb->drr_fromguid);
    -	}
    -
    +	ra.byteswap = drc->drc_byteswap;
    +	ra.cksum = drc->drc_cksum;
     	ra.vp = vp;
     	ra.voff = *voffp;
     	ra.bufsize = 1<<20;
     	ra.buf = kmem_alloc(ra.bufsize, KM_SLEEP);
     
     	/* these were verified in dmu_recv_begin */
    -	ASSERT(DMU_GET_STREAM_HDRTYPE(drc->drc_drrb->drr_versioninfo) ==
    +	ASSERT3U(DMU_GET_STREAM_HDRTYPE(drc->drc_drrb->drr_versioninfo), ==,
     	    DMU_SUBSTREAM);
    -	ASSERT(drc->drc_drrb->drr_type < DMU_OST_NUMTYPES);
    +	ASSERT3U(drc->drc_drrb->drr_type, <, DMU_OST_NUMTYPES);
     
     	/*
     	 * Open the objset we are modifying.
     	 */
    -	VERIFY(dmu_objset_from_ds(drc->drc_real_ds, &os) == 0);
    +	VERIFY0(dmu_objset_from_ds(drc->drc_ds, &os));
     
    -	ASSERT(drc->drc_real_ds->ds_phys->ds_flags & DS_FLAG_INCONSISTENT);
    +	ASSERT(drc->drc_ds->ds_phys->ds_flags & DS_FLAG_INCONSISTENT);
     
     	featureflags = DMU_GET_FEATUREFLAGS(drc->drc_drrb->drr_versioninfo);
     
    @@ -1415,7 +1409,7 @@ dmu_recv_stream(dmu_recv_cookie_t *drc, vnode_t *vp, offset_t *voffp,
     			goto out;
     		}
     		ra.err = zfs_onexit_fd_hold(cleanup_fd, &minor);
    -		if (ra.err) {
    +		if (ra.err != 0) {
     			cleanup_fd = -1;
     			goto out;
     		}
    @@ -1429,12 +1423,12 @@ dmu_recv_stream(dmu_recv_cookie_t *drc, vnode_t *vp, offset_t *voffp,
     			ra.err = zfs_onexit_add_cb(minor,
     			    free_guid_map_onexit, ra.guid_to_ds_map,
     			    action_handlep);
    -			if (ra.err)
    +			if (ra.err != 0)
     				goto out;
     		} else {
     			ra.err = zfs_onexit_cb_data(minor, *action_handlep,
     			    (void **)&ra.guid_to_ds_map);
    -			if (ra.err)
    +			if (ra.err != 0)
     				goto out;
     		}
     
    @@ -1528,14 +1522,7 @@ out:
     		 * destroy what we created, so we don't leave it in the
     		 * inconsistent restoring state.
     		 */
    -		txg_wait_synced(drc->drc_real_ds->ds_dir->dd_pool, 0);
    -
    -		(void) dsl_dataset_destroy(drc->drc_real_ds, dmu_recv_tag,
    -		    B_FALSE);
    -		if (drc->drc_real_ds != drc->drc_logical_ds) {
    -			mutex_exit(&drc->drc_logical_ds->ds_recvlock);
    -			dsl_dataset_rele(drc->drc_logical_ds, dmu_recv_tag);
    -		}
    +		dmu_recv_cleanup_ds(drc);
     	}
     
     	kmem_free(ra.buf, ra.bufsize);
    @@ -1543,142 +1530,176 @@ out:
     	return (ra.err);
     }
     
    -struct recvendsyncarg {
    -	char *tosnap;
    -	uint64_t creation_time;
    -	uint64_t toguid;
    -};
    -
     static int
    -recv_end_check(void *arg1, void *arg2, dmu_tx_t *tx)
    +dmu_recv_end_check(void *arg, dmu_tx_t *tx)
     {
    -	dsl_dataset_t *ds = arg1;
    -	struct recvendsyncarg *resa = arg2;
    +	dmu_recv_cookie_t *drc = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	int error;
     
    -	return (dsl_dataset_snapshot_check(ds, resa->tosnap, tx));
    +	ASSERT3P(drc->drc_ds->ds_owner, ==, dmu_recv_tag);
    +
    +	if (!drc->drc_newfs) {
    +		dsl_dataset_t *origin_head;
    +
    +		error = dsl_dataset_hold(dp, drc->drc_tofs, FTAG, &origin_head);
    +		if (error != 0)
    +			return (error);
    +		error = dsl_dataset_clone_swap_check_impl(drc->drc_ds,
    +		    origin_head, drc->drc_force);
    +		if (error != 0) {
    +			dsl_dataset_rele(origin_head, FTAG);
    +			return (error);
    +		}
    +		error = dsl_dataset_snapshot_check_impl(origin_head,
    +		    drc->drc_tosnap, tx);
    +		dsl_dataset_rele(origin_head, FTAG);
    +		if (error != 0)
    +			return (error);
    +
    +		error = dsl_destroy_head_check_impl(drc->drc_ds, 1);
    +	} else {
    +		error = dsl_dataset_snapshot_check_impl(drc->drc_ds,
    +		    drc->drc_tosnap, tx);
    +	}
    +	return (error);
     }
     
     static void
    -recv_end_sync(void *arg1, void *arg2, dmu_tx_t *tx)
    +dmu_recv_end_sync(void *arg, dmu_tx_t *tx)
     {
    -	dsl_dataset_t *ds = arg1;
    -	struct recvendsyncarg *resa = arg2;
    +	dmu_recv_cookie_t *drc = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
     
    -	dsl_dataset_snapshot_sync(ds, resa->tosnap, tx);
    +	spa_history_log_internal_ds(drc->drc_ds, "finish receiving",
    +	    tx, "snap=%s", drc->drc_tosnap);
     
    -	/* set snapshot's creation time and guid */
    -	dmu_buf_will_dirty(ds->ds_prev->ds_dbuf, tx);
    -	ds->ds_prev->ds_phys->ds_creation_time = resa->creation_time;
    -	ds->ds_prev->ds_phys->ds_guid = resa->toguid;
    -	ds->ds_prev->ds_phys->ds_flags &= ~DS_FLAG_INCONSISTENT;
    +	if (!drc->drc_newfs) {
    +		dsl_dataset_t *origin_head;
     
    -	dmu_buf_will_dirty(ds->ds_dbuf, tx);
    -	ds->ds_phys->ds_flags &= ~DS_FLAG_INCONSISTENT;
    -	spa_history_log_internal_ds(ds, "finished receiving", tx, "");
    +		VERIFY0(dsl_dataset_hold(dp, drc->drc_tofs, FTAG,
    +		    &origin_head));
    +		dsl_dataset_clone_swap_sync_impl(drc->drc_ds,
    +		    origin_head, tx);
    +		dsl_dataset_snapshot_sync_impl(origin_head,
    +		    drc->drc_tosnap, tx);
    +
    +		/* set snapshot's creation time and guid */
    +		dmu_buf_will_dirty(origin_head->ds_prev->ds_dbuf, tx);
    +		origin_head->ds_prev->ds_phys->ds_creation_time =
    +		    drc->drc_drrb->drr_creation_time;
    +		origin_head->ds_prev->ds_phys->ds_guid =
    +		    drc->drc_drrb->drr_toguid;
    +		origin_head->ds_prev->ds_phys->ds_flags &=
    +		    ~DS_FLAG_INCONSISTENT;
    +
    +		dmu_buf_will_dirty(origin_head->ds_dbuf, tx);
    +		origin_head->ds_phys->ds_flags &= ~DS_FLAG_INCONSISTENT;
    +
    +		dsl_dataset_rele(origin_head, FTAG);
    +		dsl_destroy_head_sync_impl(drc->drc_ds, tx);
    +	} else {
    +		dsl_dataset_t *ds = drc->drc_ds;
    +
    +		dsl_dataset_snapshot_sync_impl(ds, drc->drc_tosnap, tx);
    +
    +		/* set snapshot's creation time and guid */
    +		dmu_buf_will_dirty(ds->ds_prev->ds_dbuf, tx);
    +		ds->ds_prev->ds_phys->ds_creation_time =
    +		    drc->drc_drrb->drr_creation_time;
    +		ds->ds_prev->ds_phys->ds_guid = drc->drc_drrb->drr_toguid;
    +		ds->ds_prev->ds_phys->ds_flags &= ~DS_FLAG_INCONSISTENT;
    +
    +		dmu_buf_will_dirty(ds->ds_dbuf, tx);
    +		ds->ds_phys->ds_flags &= ~DS_FLAG_INCONSISTENT;
    +	}
    +	drc->drc_newsnapobj = drc->drc_ds->ds_phys->ds_prev_snap_obj;
    +	/*
    +	 * Release the hold from dmu_recv_begin.  This must be done before
    +	 * we return to open context, so that when we free the dataset's dnode,
    +	 * we can evict its bonus buffer.
    +	 */
    +	dsl_dataset_disown(drc->drc_ds, dmu_recv_tag);
    +	drc->drc_ds = NULL;
     }
     
     static int
    -add_ds_to_guidmap(avl_tree_t *guid_map, dsl_dataset_t *ds)
    +add_ds_to_guidmap(const char *name, avl_tree_t *guid_map, uint64_t snapobj)
     {
    -	dsl_pool_t *dp = ds->ds_dir->dd_pool;
    -	uint64_t snapobj = ds->ds_phys->ds_prev_snap_obj;
    +	dsl_pool_t *dp;
     	dsl_dataset_t *snapds;
     	guid_map_entry_t *gmep;
     	int err;
     
     	ASSERT(guid_map != NULL);
     
    -	rw_enter(&dp->dp_config_rwlock, RW_READER);
    -	err = dsl_dataset_hold_obj(dp, snapobj, guid_map, &snapds);
    +	err = dsl_pool_hold(name, FTAG, &dp);
    +	if (err != 0)
    +		return (err);
    +	err = dsl_dataset_hold_obj(dp, snapobj, FTAG, &snapds);
     	if (err == 0) {
     		gmep = kmem_alloc(sizeof (guid_map_entry_t), KM_SLEEP);
     		gmep->guid = snapds->ds_phys->ds_guid;
     		gmep->gme_ds = snapds;
     		avl_add(guid_map, gmep);
    +		dsl_dataset_long_hold(snapds, gmep);
    +		dsl_dataset_rele(snapds, FTAG);
     	}
     
    -	rw_exit(&dp->dp_config_rwlock);
    +	dsl_pool_rele(dp, FTAG);
     	return (err);
     }
     
    +static int dmu_recv_end_modified_blocks = 3;
    +
     static int
     dmu_recv_existing_end(dmu_recv_cookie_t *drc)
     {
    -	struct recvendsyncarg resa;
    -	dsl_dataset_t *ds = drc->drc_logical_ds;
    -	int err, myerr;
    +	int error;
    +	char name[MAXNAMELEN];
     
    -	if (dsl_dataset_tryown(ds, FALSE, dmu_recv_tag)) {
    -		err = dsl_dataset_clone_swap(drc->drc_real_ds, ds,
    -		    drc->drc_force);
    -		if (err)
    -			goto out;
    -	} else {
    -		mutex_exit(&ds->ds_recvlock);
    -		dsl_dataset_rele(ds, dmu_recv_tag);
    -		(void) dsl_dataset_destroy(drc->drc_real_ds, dmu_recv_tag,
    -		    B_FALSE);
    -		return (EBUSY);
    -	}
    +#ifdef _KERNEL
    +	/*
    +	 * We will be destroying the ds; make sure its origin is unmounted if
    +	 * necessary.
    +	 */
    +	dsl_dataset_name(drc->drc_ds, name);
    +	zfs_destroy_unmount_origin(name);
    +#endif
     
    -	resa.creation_time = drc->drc_drrb->drr_creation_time;
    -	resa.toguid = drc->drc_drrb->drr_toguid;
    -	resa.tosnap = drc->drc_tosnap;
    +	error = dsl_sync_task(drc->drc_tofs,
    +	    dmu_recv_end_check, dmu_recv_end_sync, drc,
    +	    dmu_recv_end_modified_blocks);
     
    -	err = dsl_sync_task_do(ds->ds_dir->dd_pool,
    -	    recv_end_check, recv_end_sync, ds, &resa, 3);
    -	if (err) {
    -		/* swap back */
    -		(void) dsl_dataset_clone_swap(drc->drc_real_ds, ds, B_TRUE);
    -	}
    -
    -out:
    -	mutex_exit(&ds->ds_recvlock);
    -	if (err == 0 && drc->drc_guid_to_ds_map != NULL)
    -		(void) add_ds_to_guidmap(drc->drc_guid_to_ds_map, ds);
    -	dsl_dataset_disown(ds, dmu_recv_tag);
    -	myerr = dsl_dataset_destroy(drc->drc_real_ds, dmu_recv_tag, B_FALSE);
    -	ASSERT0(myerr);
    -	return (err);
    +	if (error != 0)
    +		dmu_recv_cleanup_ds(drc);
    +	return (error);
     }
     
     static int
     dmu_recv_new_end(dmu_recv_cookie_t *drc)
     {
    -	struct recvendsyncarg resa;
    -	dsl_dataset_t *ds = drc->drc_logical_ds;
    -	int err;
    +	int error;
     
    -	/*
    -	 * XXX hack; seems the ds is still dirty and dsl_pool_zil_clean()
    -	 * expects it to have a ds_user_ptr (and zil), but clone_swap()
    -	 * can close it.
    -	 */
    -	txg_wait_synced(ds->ds_dir->dd_pool, 0);
    +	error = dsl_sync_task(drc->drc_tofs,
    +	    dmu_recv_end_check, dmu_recv_end_sync, drc,
    +	    dmu_recv_end_modified_blocks);
     
    -	resa.creation_time = drc->drc_drrb->drr_creation_time;
    -	resa.toguid = drc->drc_drrb->drr_toguid;
    -	resa.tosnap = drc->drc_tosnap;
    -
    -	err = dsl_sync_task_do(ds->ds_dir->dd_pool,
    -	    recv_end_check, recv_end_sync, ds, &resa, 3);
    -	if (err) {
    -		/* clean up the fs we just recv'd into */
    -		(void) dsl_dataset_destroy(ds, dmu_recv_tag, B_FALSE);
    -	} else {
    -		if (drc->drc_guid_to_ds_map != NULL)
    -			(void) add_ds_to_guidmap(drc->drc_guid_to_ds_map, ds);
    -		/* release the hold from dmu_recv_begin */
    -		dsl_dataset_disown(ds, dmu_recv_tag);
    +	if (error != 0) {
    +		dmu_recv_cleanup_ds(drc);
    +	} else if (drc->drc_guid_to_ds_map != NULL) {
    +		(void) add_ds_to_guidmap(drc->drc_tofs,
    +		    drc->drc_guid_to_ds_map,
    +		    drc->drc_newsnapobj);
     	}
    -	return (err);
    +	return (error);
     }
     
     int
     dmu_recv_end(dmu_recv_cookie_t *drc)
     {
    -	if (drc->drc_logical_ds != drc->drc_real_ds)
    -		return (dmu_recv_existing_end(drc));
    -	else
    +	if (drc->drc_newfs)
     		return (dmu_recv_new_end(drc));
    +	else
    +		return (dmu_recv_existing_end(drc));
     }
    diff --git a/uts/common/fs/zfs/dmu_traverse.c b/uts/common/fs/zfs/dmu_traverse.c
    index f3d5069d476..e9765179972 100644
    --- a/uts/common/fs/zfs/dmu_traverse.c
    +++ b/uts/common/fs/zfs/dmu_traverse.c
    @@ -265,7 +265,7 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp,
     
     		err = arc_read(NULL, td->td_spa, bp, arc_getbuf_func, &buf,
     		    ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, &flags, zb);
    -		if (err)
    +		if (err != 0)
     			return (err);
     		cbp = buf->b_data;
     
    @@ -282,7 +282,7 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp,
     			    zb->zb_level - 1,
     			    zb->zb_blkid * epb + i);
     			err = traverse_visitbp(td, dnp, &cbp[i], &czb);
    -			if (err) {
    +			if (err != 0) {
     				if (!hard)
     					break;
     				lasterr = err;
    @@ -295,7 +295,7 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp,
     
     		err = arc_read(NULL, td->td_spa, bp, arc_getbuf_func, &buf,
     		    ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, &flags, zb);
    -		if (err)
    +		if (err != 0)
     			return (err);
     		dnp = buf->b_data;
     
    @@ -308,7 +308,7 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp,
     		for (i = 0; i < epb; i++) {
     			err = traverse_dnode(td, &dnp[i], zb->zb_objset,
     			    zb->zb_blkid * epb + i);
    -			if (err) {
    +			if (err != 0) {
     				if (!hard)
     					break;
     				lasterr = err;
    @@ -321,7 +321,7 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp,
     
     		err = arc_read(NULL, td->td_spa, bp, arc_getbuf_func, &buf,
     		    ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, &flags, zb);
    -		if (err)
    +		if (err != 0)
     			return (err);
     
     		osp = buf->b_data;
    @@ -405,7 +405,7 @@ traverse_dnode(traverse_data_t *td, const dnode_phys_t *dnp,
     	for (j = 0; j < dnp->dn_nblkptr; j++) {
     		SET_BOOKMARK(&czb, objset, object, dnp->dn_nlevels - 1, j);
     		err = traverse_visitbp(td, dnp, &dnp->dn_blkptr[j], &czb);
    -		if (err) {
    +		if (err != 0) {
     			if (!hard)
     				break;
     			lasterr = err;
    @@ -415,7 +415,7 @@ traverse_dnode(traverse_data_t *td, const dnode_phys_t *dnp,
     	if (dnp->dn_flags & DNODE_FLAG_SPILL_BLKPTR) {
     		SET_BOOKMARK(&czb, objset, object, 0, DMU_SPILL_BLKID);
     		err = traverse_visitbp(td, dnp, &dnp->dn_spill, &czb);
    -		if (err) {
    +		if (err != 0) {
     			if (!hard)
     				return (err);
     			lasterr = err;
    @@ -514,14 +514,20 @@ traverse_impl(spa_t *spa, dsl_dataset_t *ds, uint64_t objset, blkptr_t *rootbp,
     	cv_init(&pd.pd_cv, NULL, CV_DEFAULT, NULL);
     
     	/* See comment on ZIL traversal in dsl_scan_visitds. */
    -	if (ds != NULL && !dsl_dataset_is_snapshot(ds)) {
    -		objset_t *os;
    +	if (ds != NULL && !dsl_dataset_is_snapshot(ds) && !BP_IS_HOLE(rootbp)) {
    +		uint32_t flags = ARC_WAIT;
    +		objset_phys_t *osp;
    +		arc_buf_t *buf;
     
    -		err = dmu_objset_from_ds(ds, &os);
    -		if (err)
    +		err = arc_read(NULL, td.td_spa, rootbp,
    +		    arc_getbuf_func, &buf,
    +		    ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, &flags, NULL);
    +		if (err != 0)
     			return (err);
     
    -		traverse_zil(&td, &os->os_zil_header);
    +		osp = buf->b_data;
    +		traverse_zil(&td, &osp->os_zil_header);
    +		(void) arc_buf_remove_ref(buf, &buf);
     	}
     
     	if (!(flags & TRAVERSE_PREFETCH_DATA) ||
    @@ -583,7 +589,7 @@ traverse_pool(spa_t *spa, uint64_t txg_start, int flags,
     	/* visit the MOS */
     	err = traverse_impl(spa, NULL, 0, spa_get_rootblkptr(spa),
     	    txg_start, NULL, flags, func, arg);
    -	if (err)
    +	if (err != 0)
     		return (err);
     
     	/* visit each dataset */
    @@ -592,7 +598,7 @@ traverse_pool(spa_t *spa, uint64_t txg_start, int flags,
     		dmu_object_info_t doi;
     
     		err = dmu_object_info(mos, obj, &doi);
    -		if (err) {
    +		if (err != 0) {
     			if (!hard)
     				return (err);
     			lasterr = err;
    @@ -603,10 +609,10 @@ traverse_pool(spa_t *spa, uint64_t txg_start, int flags,
     			dsl_dataset_t *ds;
     			uint64_t txg = txg_start;
     
    -			rw_enter(&dp->dp_config_rwlock, RW_READER);
    +			dsl_pool_config_enter(dp, FTAG);
     			err = dsl_dataset_hold_obj(dp, obj, FTAG, &ds);
    -			rw_exit(&dp->dp_config_rwlock);
    -			if (err) {
    +			dsl_pool_config_exit(dp, FTAG);
    +			if (err != 0) {
     				if (!hard)
     					return (err);
     				lasterr = err;
    @@ -616,7 +622,7 @@ traverse_pool(spa_t *spa, uint64_t txg_start, int flags,
     				txg = ds->ds_phys->ds_prev_snap_txg;
     			err = traverse_dataset(ds, txg, flags, func, arg);
     			dsl_dataset_rele(ds, FTAG);
    -			if (err) {
    +			if (err != 0) {
     				if (!hard)
     					return (err);
     				lasterr = err;
    diff --git a/uts/common/fs/zfs/dmu_tx.c b/uts/common/fs/zfs/dmu_tx.c
    index 556ae6a83a5..8e6beec4f1b 100644
    --- a/uts/common/fs/zfs/dmu_tx.c
    +++ b/uts/common/fs/zfs/dmu_tx.c
    @@ -898,7 +898,7 @@ dmu_tx_dirty_buf(dmu_tx_t *tx, dmu_buf_impl_t *db)
     #endif
     
     static int
    -dmu_tx_try_assign(dmu_tx_t *tx, uint64_t txg_how)
    +dmu_tx_try_assign(dmu_tx_t *tx, txg_how_t txg_how)
     {
     	dmu_tx_hold_t *txh;
     	spa_t *spa = tx->tx_pool->dp_spa;
    @@ -961,13 +961,6 @@ dmu_tx_try_assign(dmu_tx_t *tx, uint64_t txg_how)
     		fudge += txh->txh_fudge;
     	}
     
    -	/*
    -	 * NB: This check must be after we've held the dnodes, so that
    -	 * the dmu_tx_unassign() logic will work properly
    -	 */
    -	if (txg_how >= TXG_INITIAL && txg_how != tx->tx_txg)
    -		return (ERESTART);
    -
     	/*
     	 * If a snapshot has been taken since we made our estimates,
     	 * assume that we won't be able to free or overwrite anything.
    @@ -1048,26 +1041,25 @@ dmu_tx_unassign(dmu_tx_t *tx)
      *
      * (1)	TXG_WAIT.  If the current open txg is full, waits until there's
      *	a new one.  This should be used when you're not holding locks.
    - *	If will only fail if we're truly out of space (or over quota).
    + *	It will only fail if we're truly out of space (or over quota).
      *
      * (2)	TXG_NOWAIT.  If we can't assign into the current open txg without
      *	blocking, returns immediately with ERESTART.  This should be used
      *	whenever you're holding locks.  On an ERESTART error, the caller
      *	should drop locks, do a dmu_tx_wait(tx), and try again.
    - *
    - * (3)	A specific txg.  Use this if you need to ensure that multiple
    - *	transactions all sync in the same txg.  Like TXG_NOWAIT, it
    - *	returns ERESTART if it can't assign you into the requested txg.
      */
     int
    -dmu_tx_assign(dmu_tx_t *tx, uint64_t txg_how)
    +dmu_tx_assign(dmu_tx_t *tx, txg_how_t txg_how)
     {
     	int err;
     
     	ASSERT(tx->tx_txg == 0);
    -	ASSERT(txg_how != 0);
    +	ASSERT(txg_how == TXG_WAIT || txg_how == TXG_NOWAIT);
     	ASSERT(!dsl_pool_sync_context(tx->tx_pool));
     
    +	/* If we might wait, we must not hold the config lock. */
    +	ASSERT(txg_how != TXG_WAIT || !dsl_pool_config_held(tx->tx_pool));
    +
     	while ((err = dmu_tx_try_assign(tx, txg_how)) != 0) {
     		dmu_tx_unassign(tx);
     
    @@ -1088,6 +1080,7 @@ dmu_tx_wait(dmu_tx_t *tx)
     	spa_t *spa = tx->tx_pool->dp_spa;
     
     	ASSERT(tx->tx_txg == 0);
    +	ASSERT(!dsl_pool_config_held(tx->tx_pool));
     
     	/*
     	 * It's possible that the pool has become active after this thread
    @@ -1214,6 +1207,14 @@ dmu_tx_get_txg(dmu_tx_t *tx)
     	return (tx->tx_txg);
     }
     
    +dsl_pool_t *
    +dmu_tx_pool(dmu_tx_t *tx)
    +{
    +	ASSERT(tx->tx_pool != NULL);
    +	return (tx->tx_pool);
    +}
    +
    +
     void
     dmu_tx_callback_register(dmu_tx_t *tx, dmu_tx_callback_func_t *func, void *data)
     {
    diff --git a/uts/common/fs/zfs/dnode.c b/uts/common/fs/zfs/dnode.c
    index 6838576dcf0..5b5ece424a4 100644
    --- a/uts/common/fs/zfs/dnode.c
    +++ b/uts/common/fs/zfs/dnode.c
    @@ -72,7 +72,11 @@ dnode_cons(void *arg, void *unused, int kmflag)
     	mutex_init(&dn->dn_dbufs_mtx, NULL, MUTEX_DEFAULT, NULL);
     	cv_init(&dn->dn_notxholds, NULL, CV_DEFAULT, NULL);
     
    -	refcount_create(&dn->dn_holds);
    +	/*
    +	 * Every dbuf has a reference, and dropping a tracked reference is
    +	 * O(number of references), so don't track dn_holds.
    +	 */
    +	refcount_create_untracked(&dn->dn_holds);
     	refcount_create(&dn->dn_tx_holds);
     	list_link_init(&dn->dn_link);
     
    diff --git a/uts/common/fs/zfs/dnode_sync.c b/uts/common/fs/zfs/dnode_sync.c
    index 38dab665fc6..7d47ce02b41 100644
    --- a/uts/common/fs/zfs/dnode_sync.c
    +++ b/uts/common/fs/zfs/dnode_sync.c
    @@ -477,6 +477,7 @@ dnode_sync_free(dnode_t *dn, dmu_tx_t *tx)
     	dnode_undirty_dbufs(&dn->dn_dirty_records[txgoff]);
     	dnode_evict_dbufs(dn);
     	ASSERT3P(list_head(&dn->dn_dbufs), ==, NULL);
    +	ASSERT3P(dn->dn_bonus, ==, NULL);
     
     	/*
     	 * XXX - It would be nice to assert this, but we may still
    diff --git a/uts/common/fs/zfs/dsl_dataset.c b/uts/common/fs/zfs/dsl_dataset.c
    index 0a5ef837ccf..5e0446d3513 100644
    --- a/uts/common/fs/zfs/dsl_dataset.c
    +++ b/uts/common/fs/zfs/dsl_dataset.c
    @@ -20,7 +20,7 @@
      */
     /*
      * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
    - * Copyright (c) 2012 by Delphix. All rights reserved.
    + * Copyright (c) 2013 by Delphix. All rights reserved.
      * Copyright (c) 2012, Joyent, Inc. All rights reserved.
      */
     
    @@ -45,12 +45,8 @@
     #include 
     #include 
     #include 
    -
    -static char *dsl_reaper = "the grim reaper";
    -
    -static dsl_checkfunc_t dsl_dataset_destroy_begin_check;
    -static dsl_syncfunc_t dsl_dataset_destroy_begin_sync;
    -static dsl_syncfunc_t dsl_dataset_set_reservation_sync;
    +#include 
    +#include 
     
     #define	SWITCH64(x, y) \
     	{ \
    @@ -63,9 +59,6 @@ static dsl_syncfunc_t dsl_dataset_set_reservation_sync;
     
     #define	DSL_DEADLIST_BLOCKSIZE	SPA_MAXBLOCKSIZE
     
    -#define	DSL_DATASET_IS_DESTROYED(ds)	((ds)->ds_owner == dsl_reaper)
    -
    -
     /*
      * Figure out how much of this delta should be propogated to the dsl_dir
      * layer.  If there's a refreservation, that space has already been
    @@ -252,7 +245,7 @@ dsl_dataset_evict(dmu_buf_t *db, void *dsv)
     {
     	dsl_dataset_t *ds = dsv;
     
    -	ASSERT(ds->ds_owner == NULL || DSL_DATASET_IS_DESTROYED(ds));
    +	ASSERT(ds->ds_owner == NULL);
     
     	unique_remove(ds->ds_fsid_guid);
     
    @@ -260,32 +253,26 @@ dsl_dataset_evict(dmu_buf_t *db, void *dsv)
     		dmu_objset_evict(ds->ds_objset);
     
     	if (ds->ds_prev) {
    -		dsl_dataset_drop_ref(ds->ds_prev, ds);
    +		dsl_dataset_rele(ds->ds_prev, ds);
     		ds->ds_prev = NULL;
     	}
     
     	bplist_destroy(&ds->ds_pending_deadlist);
    -	if (db != NULL) {
    +	if (ds->ds_phys->ds_deadlist_obj != 0)
     		dsl_deadlist_close(&ds->ds_deadlist);
    -	} else {
    -		ASSERT(ds->ds_deadlist.dl_dbuf == NULL);
    -		ASSERT(!ds->ds_deadlist.dl_oldfmt);
    -	}
     	if (ds->ds_dir)
    -		dsl_dir_close(ds->ds_dir, ds);
    +		dsl_dir_rele(ds->ds_dir, ds);
     
     	ASSERT(!list_link_active(&ds->ds_synced_link));
     
     	mutex_destroy(&ds->ds_lock);
    -	mutex_destroy(&ds->ds_recvlock);
     	mutex_destroy(&ds->ds_opening_lock);
    -	rw_destroy(&ds->ds_rwlock);
    -	cv_destroy(&ds->ds_exclusive_cv);
    +	refcount_destroy(&ds->ds_longholds);
     
     	kmem_free(ds, sizeof (dsl_dataset_t));
     }
     
    -static int
    +int
     dsl_dataset_get_snapname(dsl_dataset_t *ds)
     {
     	dsl_dataset_phys_t *headphys;
    @@ -301,7 +288,7 @@ dsl_dataset_get_snapname(dsl_dataset_t *ds)
     
     	err = dmu_bonus_hold(mos, ds->ds_dir->dd_phys->dd_head_dataset_obj,
     	    FTAG, &headdbuf);
    -	if (err)
    +	if (err != 0)
     		return (err);
     	headphys = headdbuf->db_data;
     	err = zap_value_search(dp->dp_meta_objset,
    @@ -310,7 +297,7 @@ dsl_dataset_get_snapname(dsl_dataset_t *ds)
     	return (err);
     }
     
    -static int
    +int
     dsl_dataset_snap_lookup(dsl_dataset_t *ds, const char *name, uint64_t *value)
     {
     	objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
    @@ -330,8 +317,8 @@ dsl_dataset_snap_lookup(dsl_dataset_t *ds, const char *name, uint64_t *value)
     	return (err);
     }
     
    -static int
    -dsl_dataset_snap_remove(dsl_dataset_t *ds, char *name, dmu_tx_t *tx)
    +int
    +dsl_dataset_snap_remove(dsl_dataset_t *ds, const char *name, dmu_tx_t *tx)
     {
     	objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
     	uint64_t snapobj = ds->ds_phys->ds_snapnames_zapobj;
    @@ -351,8 +338,8 @@ dsl_dataset_snap_remove(dsl_dataset_t *ds, char *name, dmu_tx_t *tx)
     	return (err);
     }
     
    -static int
    -dsl_dataset_get_ref(dsl_pool_t *dp, uint64_t dsobj, void *tag,
    +int
    +dsl_dataset_hold_obj(dsl_pool_t *dp, uint64_t dsobj, void *tag,
         dsl_dataset_t **dsp)
     {
     	objset_t *mos = dp->dp_meta_objset;
    @@ -361,11 +348,10 @@ dsl_dataset_get_ref(dsl_pool_t *dp, uint64_t dsobj, void *tag,
     	int err;
     	dmu_object_info_t doi;
     
    -	ASSERT(RW_LOCK_HELD(&dp->dp_config_rwlock) ||
    -	    dsl_pool_sync_context(dp));
    +	ASSERT(dsl_pool_config_held(dp));
     
     	err = dmu_bonus_hold(mos, dsobj, tag, &dbuf);
    -	if (err)
    +	if (err != 0)
     		return (err);
     
     	/* Make sure dsobj has the correct object type. */
    @@ -383,12 +369,9 @@ dsl_dataset_get_ref(dsl_pool_t *dp, uint64_t dsobj, void *tag,
     		ds->ds_phys = dbuf->db_data;
     
     		mutex_init(&ds->ds_lock, NULL, MUTEX_DEFAULT, NULL);
    -		mutex_init(&ds->ds_recvlock, NULL, MUTEX_DEFAULT, NULL);
     		mutex_init(&ds->ds_opening_lock, NULL, MUTEX_DEFAULT, NULL);
     		mutex_init(&ds->ds_sendstream_lock, NULL, MUTEX_DEFAULT, NULL);
    -
    -		rw_init(&ds->ds_rwlock, 0, 0, 0);
    -		cv_init(&ds->ds_exclusive_cv, NULL, CV_DEFAULT, NULL);
    +		refcount_create(&ds->ds_longholds);
     
     		bplist_create(&ds->ds_pending_deadlist);
     		dsl_deadlist_open(&ds->ds_deadlist,
    @@ -398,15 +381,13 @@ dsl_dataset_get_ref(dsl_pool_t *dp, uint64_t dsobj, void *tag,
     		    offsetof(dmu_sendarg_t, dsa_link));
     
     		if (err == 0) {
    -			err = dsl_dir_open_obj(dp,
    +			err = dsl_dir_hold_obj(dp,
     			    ds->ds_phys->ds_dir_obj, NULL, ds, &ds->ds_dir);
     		}
    -		if (err) {
    +		if (err != 0) {
     			mutex_destroy(&ds->ds_lock);
    -			mutex_destroy(&ds->ds_recvlock);
     			mutex_destroy(&ds->ds_opening_lock);
    -			rw_destroy(&ds->ds_rwlock);
    -			cv_destroy(&ds->ds_exclusive_cv);
    +			refcount_destroy(&ds->ds_longholds);
     			bplist_destroy(&ds->ds_pending_deadlist);
     			dsl_deadlist_close(&ds->ds_deadlist);
     			kmem_free(ds, sizeof (dsl_dataset_t));
    @@ -416,8 +397,8 @@ dsl_dataset_get_ref(dsl_pool_t *dp, uint64_t dsobj, void *tag,
     
     		if (!dsl_dataset_is_snapshot(ds)) {
     			ds->ds_snapname[0] = '\0';
    -			if (ds->ds_phys->ds_prev_snap_obj) {
    -				err = dsl_dataset_get_ref(dp,
    +			if (ds->ds_phys->ds_prev_snap_obj != 0) {
    +				err = dsl_dataset_hold_obj(dp,
     				    ds->ds_phys->ds_prev_snap_obj,
     				    ds, &ds->ds_prev);
     			}
    @@ -433,29 +414,14 @@ dsl_dataset_get_ref(dsl_pool_t *dp, uint64_t dsobj, void *tag,
     		}
     
     		if (err == 0 && !dsl_dataset_is_snapshot(ds)) {
    -			/*
    -			 * In sync context, we're called with either no lock
    -			 * or with the write lock.  If we're not syncing,
    -			 * we're always called with the read lock held.
    -			 */
    -			boolean_t need_lock =
    -			    !RW_WRITE_HELD(&dp->dp_config_rwlock) &&
    -			    dsl_pool_sync_context(dp);
    -
    -			if (need_lock)
    -				rw_enter(&dp->dp_config_rwlock, RW_READER);
    -
    -			err = dsl_prop_get_ds(ds,
    -			    "refreservation", sizeof (uint64_t), 1,
    -			    &ds->ds_reserved, NULL);
    +			err = dsl_prop_get_int_ds(ds,
    +			    zfs_prop_to_name(ZFS_PROP_REFRESERVATION),
    +			    &ds->ds_reserved);
     			if (err == 0) {
    -				err = dsl_prop_get_ds(ds,
    -				    "refquota", sizeof (uint64_t), 1,
    -				    &ds->ds_quota, NULL);
    +				err = dsl_prop_get_int_ds(ds,
    +				    zfs_prop_to_name(ZFS_PROP_REFQUOTA),
    +				    &ds->ds_quota);
     			}
    -
    -			if (need_lock)
    -				rw_exit(&dp->dp_config_rwlock);
     		} else {
     			ds->ds_reserved = ds->ds_quota = 0;
     		}
    @@ -465,15 +431,13 @@ dsl_dataset_get_ref(dsl_pool_t *dp, uint64_t dsobj, void *tag,
     			bplist_destroy(&ds->ds_pending_deadlist);
     			dsl_deadlist_close(&ds->ds_deadlist);
     			if (ds->ds_prev)
    -				dsl_dataset_drop_ref(ds->ds_prev, ds);
    -			dsl_dir_close(ds->ds_dir, ds);
    +				dsl_dataset_rele(ds->ds_prev, ds);
    +			dsl_dir_rele(ds->ds_dir, ds);
     			mutex_destroy(&ds->ds_lock);
    -			mutex_destroy(&ds->ds_recvlock);
     			mutex_destroy(&ds->ds_opening_lock);
    -			rw_destroy(&ds->ds_rwlock);
    -			cv_destroy(&ds->ds_exclusive_cv);
    +			refcount_destroy(&ds->ds_longholds);
     			kmem_free(ds, sizeof (dsl_dataset_t));
    -			if (err) {
    +			if (err != 0) {
     				dmu_buf_rele(dbuf, tag);
     				return (err);
     			}
    @@ -488,90 +452,68 @@ dsl_dataset_get_ref(dsl_pool_t *dp, uint64_t dsobj, void *tag,
     	ASSERT(ds->ds_phys->ds_prev_snap_obj != 0 ||
     	    spa_version(dp->dp_spa) < SPA_VERSION_ORIGIN ||
     	    dp->dp_origin_snap == NULL || ds == dp->dp_origin_snap);
    -	mutex_enter(&ds->ds_lock);
    -	if (!dsl_pool_sync_context(dp) && DSL_DATASET_IS_DESTROYED(ds)) {
    -		mutex_exit(&ds->ds_lock);
    -		dmu_buf_rele(ds->ds_dbuf, tag);
    -		return (ENOENT);
    -	}
    -	mutex_exit(&ds->ds_lock);
     	*dsp = ds;
     	return (0);
     }
     
    -static int
    -dsl_dataset_hold_ref(dsl_dataset_t *ds, void *tag)
    +int
    +dsl_dataset_hold(dsl_pool_t *dp, const char *name,
    +    void *tag, dsl_dataset_t **dsp)
     {
    -	dsl_pool_t *dp = ds->ds_dir->dd_pool;
    +	dsl_dir_t *dd;
    +	const char *snapname;
    +	uint64_t obj;
    +	int err = 0;
     
    -	/*
    -	 * In syncing context we don't want the rwlock lock: there
    -	 * may be an existing writer waiting for sync phase to
    -	 * finish.  We don't need to worry about such writers, since
    -	 * sync phase is single-threaded, so the writer can't be
    -	 * doing anything while we are active.
    -	 */
    -	if (dsl_pool_sync_context(dp)) {
    -		ASSERT(!DSL_DATASET_IS_DESTROYED(ds));
    -		return (0);
    -	}
    +	err = dsl_dir_hold(dp, name, FTAG, &dd, &snapname);
    +	if (err != 0)
    +		return (err);
     
    -	/*
    -	 * Normal users will hold the ds_rwlock as a READER until they
    -	 * are finished (i.e., call dsl_dataset_rele()).  "Owners" will
    -	 * drop their READER lock after they set the ds_owner field.
    -	 *
    -	 * If the dataset is being destroyed, the destroy thread will
    -	 * obtain a WRITER lock for exclusive access after it's done its
    -	 * open-context work and then change the ds_owner to
    -	 * dsl_reaper once destruction is assured.  So threads
    -	 * may block here temporarily, until the "destructability" of
    -	 * the dataset is determined.
    -	 */
    -	ASSERT(!RW_WRITE_HELD(&dp->dp_config_rwlock));
    -	mutex_enter(&ds->ds_lock);
    -	while (!rw_tryenter(&ds->ds_rwlock, RW_READER)) {
    -		rw_exit(&dp->dp_config_rwlock);
    -		cv_wait(&ds->ds_exclusive_cv, &ds->ds_lock);
    -		if (DSL_DATASET_IS_DESTROYED(ds)) {
    -			mutex_exit(&ds->ds_lock);
    -			dsl_dataset_drop_ref(ds, tag);
    -			rw_enter(&dp->dp_config_rwlock, RW_READER);
    +	ASSERT(dsl_pool_config_held(dp));
    +	obj = dd->dd_phys->dd_head_dataset_obj;
    +	if (obj != 0)
    +		err = dsl_dataset_hold_obj(dp, obj, tag, dsp);
    +	else
    +		err = ENOENT;
    +
    +	/* we may be looking for a snapshot */
    +	if (err == 0 && snapname != NULL) {
    +		dsl_dataset_t *ds;
    +
    +		if (*snapname++ != '@') {
    +			dsl_dataset_rele(*dsp, tag);
    +			dsl_dir_rele(dd, FTAG);
     			return (ENOENT);
     		}
    -		/*
    -		 * The dp_config_rwlock lives above the ds_lock. And
    -		 * we need to check DSL_DATASET_IS_DESTROYED() while
    -		 * holding the ds_lock, so we have to drop and reacquire
    -		 * the ds_lock here.
    -		 */
    -		mutex_exit(&ds->ds_lock);
    -		rw_enter(&dp->dp_config_rwlock, RW_READER);
    -		mutex_enter(&ds->ds_lock);
    +
    +		dprintf("looking for snapshot '%s'\n", snapname);
    +		err = dsl_dataset_snap_lookup(*dsp, snapname, &obj);
    +		if (err == 0)
    +			err = dsl_dataset_hold_obj(dp, obj, tag, &ds);
    +		dsl_dataset_rele(*dsp, tag);
    +
    +		if (err == 0) {
    +			mutex_enter(&ds->ds_lock);
    +			if (ds->ds_snapname[0] == 0)
    +				(void) strlcpy(ds->ds_snapname, snapname,
    +				    sizeof (ds->ds_snapname));
    +			mutex_exit(&ds->ds_lock);
    +			*dsp = ds;
    +		}
     	}
    -	mutex_exit(&ds->ds_lock);
    -	return (0);
    +
    +	dsl_dir_rele(dd, FTAG);
    +	return (err);
     }
     
     int
    -dsl_dataset_hold_obj(dsl_pool_t *dp, uint64_t dsobj, void *tag,
    -    dsl_dataset_t **dsp)
    -{
    -	int err = dsl_dataset_get_ref(dp, dsobj, tag, dsp);
    -
    -	if (err)
    -		return (err);
    -	return (dsl_dataset_hold_ref(*dsp, tag));
    -}
    -
    -int
    -dsl_dataset_own_obj(dsl_pool_t *dp, uint64_t dsobj, boolean_t inconsistentok,
    +dsl_dataset_own_obj(dsl_pool_t *dp, uint64_t dsobj,
         void *tag, dsl_dataset_t **dsp)
     {
     	int err = dsl_dataset_hold_obj(dp, dsobj, tag, dsp);
    -	if (err)
    +	if (err != 0)
     		return (err);
    -	if (!dsl_dataset_tryown(*dsp, inconsistentok, tag)) {
    +	if (!dsl_dataset_tryown(*dsp, tag)) {
     		dsl_dataset_rele(*dsp, tag);
     		*dsp = NULL;
     		return (EBUSY);
    @@ -580,78 +522,48 @@ dsl_dataset_own_obj(dsl_pool_t *dp, uint64_t dsobj, boolean_t inconsistentok,
     }
     
     int
    -dsl_dataset_hold(const char *name, void *tag, dsl_dataset_t **dsp)
    -{
    -	dsl_dir_t *dd;
    -	dsl_pool_t *dp;
    -	const char *snapname;
    -	uint64_t obj;
    -	int err = 0;
    -
    -	err = dsl_dir_open_spa(NULL, name, FTAG, &dd, &snapname);
    -	if (err)
    -		return (err);
    -
    -	dp = dd->dd_pool;
    -	obj = dd->dd_phys->dd_head_dataset_obj;
    -	rw_enter(&dp->dp_config_rwlock, RW_READER);
    -	if (obj)
    -		err = dsl_dataset_get_ref(dp, obj, tag, dsp);
    -	else
    -		err = ENOENT;
    -	if (err)
    -		goto out;
    -
    -	err = dsl_dataset_hold_ref(*dsp, tag);
    -
    -	/* we may be looking for a snapshot */
    -	if (err == 0 && snapname != NULL) {
    -		dsl_dataset_t *ds = NULL;
    -
    -		if (*snapname++ != '@') {
    -			dsl_dataset_rele(*dsp, tag);
    -			err = ENOENT;
    -			goto out;
    -		}
    -
    -		dprintf("looking for snapshot '%s'\n", snapname);
    -		err = dsl_dataset_snap_lookup(*dsp, snapname, &obj);
    -		if (err == 0)
    -			err = dsl_dataset_get_ref(dp, obj, tag, &ds);
    -		dsl_dataset_rele(*dsp, tag);
    -
    -		ASSERT3U((err == 0), ==, (ds != NULL));
    -
    -		if (ds) {
    -			mutex_enter(&ds->ds_lock);
    -			if (ds->ds_snapname[0] == 0)
    -				(void) strlcpy(ds->ds_snapname, snapname,
    -				    sizeof (ds->ds_snapname));
    -			mutex_exit(&ds->ds_lock);
    -			err = dsl_dataset_hold_ref(ds, tag);
    -			*dsp = err ? NULL : ds;
    -		}
    -	}
    -out:
    -	rw_exit(&dp->dp_config_rwlock);
    -	dsl_dir_close(dd, FTAG);
    -	return (err);
    -}
    -
    -int
    -dsl_dataset_own(const char *name, boolean_t inconsistentok,
    +dsl_dataset_own(dsl_pool_t *dp, const char *name,
         void *tag, dsl_dataset_t **dsp)
     {
    -	int err = dsl_dataset_hold(name, tag, dsp);
    -	if (err)
    +	int err = dsl_dataset_hold(dp, name, tag, dsp);
    +	if (err != 0)
     		return (err);
    -	if (!dsl_dataset_tryown(*dsp, inconsistentok, tag)) {
    +	if (!dsl_dataset_tryown(*dsp, tag)) {
     		dsl_dataset_rele(*dsp, tag);
     		return (EBUSY);
     	}
     	return (0);
     }
     
    +/*
    + * See the comment above dsl_pool_hold() for details.  In summary, a long
    + * hold is used to prevent destruction of a dataset while the pool hold
    + * is dropped, allowing other concurrent operations (e.g. spa_sync()).
    + *
    + * The dataset and pool must be held when this function is called.  After it
    + * is called, the pool hold may be released while the dataset is still held
    + * and accessed.
    + */
    +void
    +dsl_dataset_long_hold(dsl_dataset_t *ds, void *tag)
    +{
    +	ASSERT(dsl_pool_config_held(ds->ds_dir->dd_pool));
    +	(void) refcount_add(&ds->ds_longholds, tag);
    +}
    +
    +void
    +dsl_dataset_long_rele(dsl_dataset_t *ds, void *tag)
    +{
    +	(void) refcount_remove(&ds->ds_longholds, tag);
    +}
    +
    +/* Return B_TRUE if there are any long holds on this dataset. */
    +boolean_t
    +dsl_dataset_long_held(dsl_dataset_t *ds)
    +{
    +	return (!refcount_is_zero(&ds->ds_longholds));
    +}
    +
     void
     dsl_dataset_name(dsl_dataset_t *ds, char *name)
     {
    @@ -659,7 +571,7 @@ dsl_dataset_name(dsl_dataset_t *ds, char *name)
     		(void) strcpy(name, "mos");
     	} else {
     		dsl_dir_name(ds->ds_dir, name);
    -		VERIFY(0 == dsl_dataset_get_snapname(ds));
    +		VERIFY0(dsl_dataset_get_snapname(ds));
     		if (ds->ds_snapname[0]) {
     			(void) strcat(name, "@");
     			/*
    @@ -686,7 +598,7 @@ dsl_dataset_namelen(dsl_dataset_t *ds)
     		result = 3;	/* "mos" */
     	} else {
     		result = dsl_dir_namelen(ds->ds_dir);
    -		VERIFY(0 == dsl_dataset_get_snapname(ds));
    +		VERIFY0(dsl_dataset_get_snapname(ds));
     		if (ds->ds_snapname[0]) {
     			++result;	/* adding one for the @-sign */
     			if (!MUTEX_HELD(&ds->ds_lock)) {
    @@ -703,64 +615,41 @@ dsl_dataset_namelen(dsl_dataset_t *ds)
     }
     
     void
    -dsl_dataset_drop_ref(dsl_dataset_t *ds, void *tag)
    +dsl_dataset_rele(dsl_dataset_t *ds, void *tag)
     {
     	dmu_buf_rele(ds->ds_dbuf, tag);
     }
     
    -void
    -dsl_dataset_rele(dsl_dataset_t *ds, void *tag)
    -{
    -	if (!dsl_pool_sync_context(ds->ds_dir->dd_pool)) {
    -		rw_exit(&ds->ds_rwlock);
    -	}
    -	dsl_dataset_drop_ref(ds, tag);
    -}
    -
     void
     dsl_dataset_disown(dsl_dataset_t *ds, void *tag)
     {
    -	ASSERT((ds->ds_owner == tag && ds->ds_dbuf) ||
    -	    (DSL_DATASET_IS_DESTROYED(ds) && ds->ds_dbuf == NULL));
    +	ASSERT(ds->ds_owner == tag && ds->ds_dbuf != NULL);
     
     	mutex_enter(&ds->ds_lock);
     	ds->ds_owner = NULL;
    -	if (RW_WRITE_HELD(&ds->ds_rwlock)) {
    -		rw_exit(&ds->ds_rwlock);
    -		cv_broadcast(&ds->ds_exclusive_cv);
    -	}
     	mutex_exit(&ds->ds_lock);
    -	if (ds->ds_dbuf)
    -		dsl_dataset_drop_ref(ds, tag);
    +	dsl_dataset_long_rele(ds, tag);
    +	if (ds->ds_dbuf != NULL)
    +		dsl_dataset_rele(ds, tag);
     	else
     		dsl_dataset_evict(NULL, ds);
     }
     
     boolean_t
    -dsl_dataset_tryown(dsl_dataset_t *ds, boolean_t inconsistentok, void *tag)
    +dsl_dataset_tryown(dsl_dataset_t *ds, void *tag)
     {
     	boolean_t gotit = FALSE;
     
     	mutex_enter(&ds->ds_lock);
    -	if (ds->ds_owner == NULL &&
    -	    (!DS_IS_INCONSISTENT(ds) || inconsistentok)) {
    +	if (ds->ds_owner == NULL && !DS_IS_INCONSISTENT(ds)) {
     		ds->ds_owner = tag;
    -		if (!dsl_pool_sync_context(ds->ds_dir->dd_pool))
    -			rw_exit(&ds->ds_rwlock);
    +		dsl_dataset_long_hold(ds, tag);
     		gotit = TRUE;
     	}
     	mutex_exit(&ds->ds_lock);
     	return (gotit);
     }
     
    -void
    -dsl_dataset_make_exclusive(dsl_dataset_t *ds, void *owner)
    -{
    -	ASSERT3P(owner, ==, ds->ds_owner);
    -	if (!RW_WRITE_HELD(&ds->ds_rwlock))
    -		rw_enter(&ds->ds_rwlock, RW_WRITER);
    -}
    -
     uint64_t
     dsl_dataset_create_sync_dd(dsl_dir_t *dd, dsl_dataset_t *origin,
         uint64_t flags, dmu_tx_t *tx)
    @@ -781,7 +670,7 @@ dsl_dataset_create_sync_dd(dsl_dir_t *dd, dsl_dataset_t *origin,
     
     	dsobj = dmu_object_alloc(mos, DMU_OT_DSL_DATASET, 0,
     	    DMU_OT_DSL_DATASET, sizeof (dsl_dataset_phys_t), tx);
    -	VERIFY(0 == dmu_bonus_hold(mos, dsobj, FTAG, &dbuf));
    +	VERIFY0(dmu_bonus_hold(mos, dsobj, FTAG, &dbuf));
     	dmu_buf_will_dirty(dbuf, tx);
     	dsphys = dbuf->db_data;
     	bzero(dsphys, sizeof (dsl_dataset_phys_t));
    @@ -799,7 +688,7 @@ dsl_dataset_create_sync_dd(dsl_dir_t *dd, dsl_dataset_t *origin,
     	if (origin == NULL) {
     		dsphys->ds_deadlist_obj = dsl_deadlist_alloc(mos, tx);
     	} else {
    -		dsl_dataset_t *ohds;
    +		dsl_dataset_t *ohds; /* head of the origin snapshot */
     
     		dsphys->ds_prev_snap_obj = origin->ds_object;
     		dsphys->ds_prev_snap_txg =
    @@ -816,7 +705,7 @@ dsl_dataset_create_sync_dd(dsl_dir_t *dd, dsl_dataset_t *origin,
     		dmu_buf_will_dirty(origin->ds_dbuf, tx);
     		origin->ds_phys->ds_num_children++;
     
    -		VERIFY3U(0, ==, dsl_dataset_hold_obj(dp,
    +		VERIFY0(dsl_dataset_hold_obj(dp,
     		    origin->ds_dir->dd_phys->dd_head_dataset_obj, FTAG, &ohds));
     		dsphys->ds_deadlist_obj = dsl_deadlist_clone(&ohds->ds_deadlist,
     		    dsphys->ds_prev_snap_txg, dsphys->ds_prev_snap_obj, tx);
    @@ -828,9 +717,8 @@ dsl_dataset_create_sync_dd(dsl_dir_t *dd, dsl_dataset_t *origin,
     				    zap_create(mos,
     				    DMU_OT_NEXT_CLONES, DMU_OT_NONE, 0, tx);
     			}
    -			VERIFY(0 == zap_add_int(mos,
    -			    origin->ds_phys->ds_next_clones_obj,
    -			    dsobj, tx));
    +			VERIFY0(zap_add_int(mos,
    +			    origin->ds_phys->ds_next_clones_obj, dsobj, tx));
     		}
     
     		dmu_buf_will_dirty(dd->dd_dbuf, tx);
    @@ -842,7 +730,7 @@ dsl_dataset_create_sync_dd(dsl_dir_t *dd, dsl_dataset_t *origin,
     				    zap_create(mos,
     				    DMU_OT_DSL_CLONES, DMU_OT_NONE, 0, tx);
     			}
    -			VERIFY3U(0, ==, zap_add_int(mos,
    +			VERIFY0(zap_add_int(mos,
     			    origin->ds_dir->dd_phys->dd_clones, dsobj, tx));
     		}
     	}
    @@ -858,6 +746,16 @@ dsl_dataset_create_sync_dd(dsl_dir_t *dd, dsl_dataset_t *origin,
     	return (dsobj);
     }
     
    +static void
    +dsl_dataset_zero_zil(dsl_dataset_t *ds, dmu_tx_t *tx)
    +{
    +	objset_t *os;
    +
    +	VERIFY0(dmu_objset_from_ds(ds, &os));
    +	bzero(&os->os_zil_header, sizeof (os->os_zil_header));
    +	dsl_dataset_dirty(ds, tx);
    +}
    +
     uint64_t
     dsl_dataset_create_sync(dsl_dir_t *pdd, const char *lastname,
         dsl_dataset_t *origin, uint64_t flags, cred_t *cr, dmu_tx_t *tx)
    @@ -866,29 +764,28 @@ dsl_dataset_create_sync(dsl_dir_t *pdd, const char *lastname,
     	uint64_t dsobj, ddobj;
     	dsl_dir_t *dd;
     
    +	ASSERT(dmu_tx_is_syncing(tx));
     	ASSERT(lastname[0] != '@');
     
     	ddobj = dsl_dir_create_sync(dp, pdd, lastname, tx);
    -	VERIFY(0 == dsl_dir_open_obj(dp, ddobj, lastname, FTAG, &dd));
    +	VERIFY0(dsl_dir_hold_obj(dp, ddobj, lastname, FTAG, &dd));
     
    -	dsobj = dsl_dataset_create_sync_dd(dd, origin, flags, tx);
    +	dsobj = dsl_dataset_create_sync_dd(dd, origin,
    +	    flags & ~DS_CREATE_FLAG_NODIRTY, tx);
     
     	dsl_deleg_set_create_perms(dd, tx, cr);
     
    -	dsl_dir_close(dd, FTAG);
    +	dsl_dir_rele(dd, FTAG);
     
     	/*
     	 * If we are creating a clone, make sure we zero out any stale
     	 * data from the origin snapshots zil header.
     	 */
    -	if (origin != NULL) {
    +	if (origin != NULL && !(flags & DS_CREATE_FLAG_NODIRTY)) {
     		dsl_dataset_t *ds;
    -		objset_t *os;
     
    -		VERIFY3U(0, ==, dsl_dataset_hold_obj(dp, dsobj, FTAG, &ds));
    -		VERIFY3U(0, ==, dmu_objset_from_ds(ds, &os));
    -		bzero(&os->os_zil_header, sizeof (os->os_zil_header));
    -		dsl_dataset_dirty(ds, tx);
    +		VERIFY0(dsl_dataset_hold_obj(dp, dsobj, FTAG, &ds));
    +		dsl_dataset_zero_zil(ds, tx);
     		dsl_dataset_rele(ds, FTAG);
     	}
     
    @@ -896,271 +793,65 @@ dsl_dataset_create_sync(dsl_dir_t *pdd, const char *lastname,
     }
     
     /*
    - * The snapshots must all be in the same pool.
    + * The unique space in the head dataset can be calculated by subtracting
    + * the space used in the most recent snapshot, that is still being used
    + * in this file system, from the space currently in use.  To figure out
    + * the space in the most recent snapshot still in use, we need to take
    + * the total space used in the snapshot and subtract out the space that
    + * has been freed up since the snapshot was taken.
      */
    -int
    -dmu_snapshots_destroy_nvl(nvlist_t *snaps, boolean_t defer,
    -    nvlist_t *errlist)
    +void
    +dsl_dataset_recalc_head_uniq(dsl_dataset_t *ds)
     {
    +	uint64_t mrs_used;
    +	uint64_t dlused, dlcomp, dluncomp;
    +
    +	ASSERT(!dsl_dataset_is_snapshot(ds));
    +
    +	if (ds->ds_phys->ds_prev_snap_obj != 0)
    +		mrs_used = ds->ds_prev->ds_phys->ds_referenced_bytes;
    +	else
    +		mrs_used = 0;
    +
    +	dsl_deadlist_space(&ds->ds_deadlist, &dlused, &dlcomp, &dluncomp);
    +
    +	ASSERT3U(dlused, <=, mrs_used);
    +	ds->ds_phys->ds_unique_bytes =
    +	    ds->ds_phys->ds_referenced_bytes - (mrs_used - dlused);
    +
    +	if (spa_version(ds->ds_dir->dd_pool->dp_spa) >=
    +	    SPA_VERSION_UNIQUE_ACCURATE)
    +		ds->ds_phys->ds_flags |= DS_FLAG_UNIQUE_ACCURATE;
    +}
    +
    +void
    +dsl_dataset_remove_from_next_clones(dsl_dataset_t *ds, uint64_t obj,
    +    dmu_tx_t *tx)
    +{
    +	objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
    +	uint64_t count;
     	int err;
    -	dsl_sync_task_t *dst;
    -	spa_t *spa;
    -	nvpair_t *pair;
    -	dsl_sync_task_group_t *dstg;
    -
    -	pair = nvlist_next_nvpair(snaps, NULL);
    -	if (pair == NULL)
    -		return (0);
    -
    -	err = spa_open(nvpair_name(pair), &spa, FTAG);
    -	if (err)
    -		return (err);
    -	dstg = dsl_sync_task_group_create(spa_get_dsl(spa));
    -
    -	for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL;
    -	    pair = nvlist_next_nvpair(snaps, pair)) {
    -		dsl_dataset_t *ds;
    -
    -		err = dsl_dataset_own(nvpair_name(pair), B_TRUE, dstg, &ds);
    -		if (err == 0) {
    -			struct dsl_ds_destroyarg *dsda;
    -
    -			dsl_dataset_make_exclusive(ds, dstg);
    -			dsda = kmem_zalloc(sizeof (struct dsl_ds_destroyarg),
    -			    KM_SLEEP);
    -			dsda->ds = ds;
    -			dsda->defer = defer;
    -			dsl_sync_task_create(dstg, dsl_dataset_destroy_check,
    -			    dsl_dataset_destroy_sync, dsda, dstg, 0);
    -		} else if (err == ENOENT) {
    -			err = 0;
    -		} else {
    -			fnvlist_add_int32(errlist, nvpair_name(pair), err);
    -			break;
    -		}
    -	}
    -
    -	if (err == 0)
    -		err = dsl_sync_task_group_wait(dstg);
    -
    -	for (dst = list_head(&dstg->dstg_tasks); dst;
    -	    dst = list_next(&dstg->dstg_tasks, dst)) {
    -		struct dsl_ds_destroyarg *dsda = dst->dst_arg1;
    -		dsl_dataset_t *ds = dsda->ds;
    -
    -		/*
    -		 * Return the snapshots that triggered the error.
    -		 */
    -		if (dst->dst_err != 0) {
    -			char name[ZFS_MAXNAMELEN];
    -			dsl_dataset_name(ds, name);
    -			fnvlist_add_int32(errlist, name, dst->dst_err);
    -		}
    -		ASSERT3P(dsda->rm_origin, ==, NULL);
    -		dsl_dataset_disown(ds, dstg);
    -		kmem_free(dsda, sizeof (struct dsl_ds_destroyarg));
    -	}
    -
    -	dsl_sync_task_group_destroy(dstg);
    -	spa_close(spa, FTAG);
    -	return (err);
    -
    -}
    -
    -static boolean_t
    -dsl_dataset_might_destroy_origin(dsl_dataset_t *ds)
    -{
    -	boolean_t might_destroy = B_FALSE;
    -
    -	mutex_enter(&ds->ds_lock);
    -	if (ds->ds_phys->ds_num_children == 2 && ds->ds_userrefs == 0 &&
    -	    DS_IS_DEFER_DESTROY(ds))
    -		might_destroy = B_TRUE;
    -	mutex_exit(&ds->ds_lock);
    -
    -	return (might_destroy);
    -}
    -
    -/*
    - * If we're removing a clone, and these three conditions are true:
    - *	1) the clone's origin has no other children
    - *	2) the clone's origin has no user references
    - *	3) the clone's origin has been marked for deferred destruction
    - * Then, prepare to remove the origin as part of this sync task group.
    - */
    -static int
    -dsl_dataset_origin_rm_prep(struct dsl_ds_destroyarg *dsda, void *tag)
    -{
    -	dsl_dataset_t *ds = dsda->ds;
    -	dsl_dataset_t *origin = ds->ds_prev;
    -
    -	if (dsl_dataset_might_destroy_origin(origin)) {
    -		char *name;
    -		int namelen;
    -		int error;
    -
    -		namelen = dsl_dataset_namelen(origin) + 1;
    -		name = kmem_alloc(namelen, KM_SLEEP);
    -		dsl_dataset_name(origin, name);
    -#ifdef _KERNEL
    -		error = zfs_unmount_snap(name, NULL);
    -		if (error) {
    -			kmem_free(name, namelen);
    -			return (error);
    -		}
    -#endif
    -		error = dsl_dataset_own(name, B_TRUE, tag, &origin);
    -		kmem_free(name, namelen);
    -		if (error)
    -			return (error);
    -		dsda->rm_origin = origin;
    -		dsl_dataset_make_exclusive(origin, tag);
    -	}
    -
    -	return (0);
    -}
    -
    -/*
    - * ds must be opened as OWNER.  On return (whether successful or not),
    - * ds will be closed and caller can no longer dereference it.
    - */
    -int
    -dsl_dataset_destroy(dsl_dataset_t *ds, void *tag, boolean_t defer)
    -{
    -	int err;
    -	dsl_sync_task_group_t *dstg;
    -	objset_t *os;
    -	dsl_dir_t *dd;
    -	uint64_t obj;
    -	struct dsl_ds_destroyarg dsda = { 0 };
    -
    -	dsda.ds = ds;
    -
    -	if (dsl_dataset_is_snapshot(ds)) {
    -		/* Destroying a snapshot is simpler */
    -		dsl_dataset_make_exclusive(ds, tag);
    -
    -		dsda.defer = defer;
    -		err = dsl_sync_task_do(ds->ds_dir->dd_pool,
    -		    dsl_dataset_destroy_check, dsl_dataset_destroy_sync,
    -		    &dsda, tag, 0);
    -		ASSERT3P(dsda.rm_origin, ==, NULL);
    -		goto out;
    -	} else if (defer) {
    -		err = EINVAL;
    -		goto out;
    -	}
    -
    -	dd = ds->ds_dir;
    -
    -	if (!spa_feature_is_enabled(dsl_dataset_get_spa(ds),
    -	    &spa_feature_table[SPA_FEATURE_ASYNC_DESTROY])) {
    -		/*
    -		 * Check for errors and mark this ds as inconsistent, in
    -		 * case we crash while freeing the objects.
    -		 */
    -		err = dsl_sync_task_do(dd->dd_pool,
    -		    dsl_dataset_destroy_begin_check,
    -		    dsl_dataset_destroy_begin_sync, ds, NULL, 0);
    -		if (err)
    -			goto out;
    -
    -		err = dmu_objset_from_ds(ds, &os);
    -		if (err)
    -			goto out;
    -
    -		/*
    -		 * Remove all objects while in the open context so that
    -		 * there is less work to do in the syncing context.
    -		 */
    -		for (obj = 0; err == 0; err = dmu_object_next(os, &obj, FALSE,
    -		    ds->ds_phys->ds_prev_snap_txg)) {
    -			/*
    -			 * Ignore errors, if there is not enough disk space
    -			 * we will deal with it in dsl_dataset_destroy_sync().
    -			 */
    -			(void) dmu_free_object(os, obj);
    -		}
    -		if (err != ESRCH)
    -			goto out;
    -
    -		/*
    -		 * Sync out all in-flight IO.
    -		 */
    -		txg_wait_synced(dd->dd_pool, 0);
    -
    -		/*
    -		 * If we managed to free all the objects in open
    -		 * context, the user space accounting should be zero.
    -		 */
    -		if (ds->ds_phys->ds_bp.blk_fill == 0 &&
    -		    dmu_objset_userused_enabled(os)) {
    -			uint64_t count;
    -
    -			ASSERT(zap_count(os, DMU_USERUSED_OBJECT,
    -			    &count) != 0 || count == 0);
    -			ASSERT(zap_count(os, DMU_GROUPUSED_OBJECT,
    -			    &count) != 0 || count == 0);
    -		}
    -	}
    -
    -	rw_enter(&dd->dd_pool->dp_config_rwlock, RW_READER);
    -	err = dsl_dir_open_obj(dd->dd_pool, dd->dd_object, NULL, FTAG, &dd);
    -	rw_exit(&dd->dd_pool->dp_config_rwlock);
    -
    -	if (err)
    -		goto out;
     
    +	ASSERT(ds->ds_phys->ds_num_children >= 2);
    +	err = zap_remove_int(mos, ds->ds_phys->ds_next_clones_obj, obj, tx);
     	/*
    -	 * Blow away the dsl_dir + head dataset.
    +	 * The err should not be ENOENT, but a bug in a previous version
    +	 * of the code could cause upgrade_clones_cb() to not set
    +	 * ds_next_snap_obj when it should, leading to a missing entry.
    +	 * If we knew that the pool was created after
    +	 * SPA_VERSION_NEXT_CLONES, we could assert that it isn't
    +	 * ENOENT.  However, at least we can check that we don't have
    +	 * too many entries in the next_clones_obj even after failing to
    +	 * remove this one.
     	 */
    -	dsl_dataset_make_exclusive(ds, tag);
    -	/*
    -	 * If we're removing a clone, we might also need to remove its
    -	 * origin.
    -	 */
    -	do {
    -		dsda.need_prep = B_FALSE;
    -		if (dsl_dir_is_clone(dd)) {
    -			err = dsl_dataset_origin_rm_prep(&dsda, tag);
    -			if (err) {
    -				dsl_dir_close(dd, FTAG);
    -				goto out;
    -			}
    -		}
    -
    -		dstg = dsl_sync_task_group_create(ds->ds_dir->dd_pool);
    -		dsl_sync_task_create(dstg, dsl_dataset_destroy_check,
    -		    dsl_dataset_destroy_sync, &dsda, tag, 0);
    -		dsl_sync_task_create(dstg, dsl_dir_destroy_check,
    -		    dsl_dir_destroy_sync, dd, FTAG, 0);
    -		err = dsl_sync_task_group_wait(dstg);
    -		dsl_sync_task_group_destroy(dstg);
    -
    -		/*
    -		 * We could be racing against 'zfs release' or 'zfs destroy -d'
    -		 * on the origin snap, in which case we can get EBUSY if we
    -		 * needed to destroy the origin snap but were not ready to
    -		 * do so.
    -		 */
    -		if (dsda.need_prep) {
    -			ASSERT(err == EBUSY);
    -			ASSERT(dsl_dir_is_clone(dd));
    -			ASSERT(dsda.rm_origin == NULL);
    -		}
    -	} while (dsda.need_prep);
    -
    -	if (dsda.rm_origin != NULL)
    -		dsl_dataset_disown(dsda.rm_origin, tag);
    -
    -	/* if it is successful, dsl_dir_destroy_sync will close the dd */
    -	if (err)
    -		dsl_dir_close(dd, FTAG);
    -out:
    -	dsl_dataset_disown(ds, tag);
    -	return (err);
    +	if (err != ENOENT)
    +		VERIFY0(err);
    +	ASSERT0(zap_count(mos, ds->ds_phys->ds_next_clones_obj,
    +	    &count));
    +	ASSERT3U(count, <=, ds->ds_phys->ds_num_children - 2);
     }
     
    +
     blkptr_t *
     dsl_dataset_get_blkptr(dsl_dataset_t *ds)
     {
    @@ -1201,7 +892,7 @@ dsl_dataset_dirty(dsl_dataset_t *ds, dmu_tx_t *tx)
     
     	dp = ds->ds_dir->dd_pool;
     
    -	if (txg_list_add(&dp->dp_dirty_datasets, ds, tx->tx_txg) == 0) {
    +	if (txg_list_add(&dp->dp_dirty_datasets, ds, tx->tx_txg)) {
     		/* up the hold count until we can be written out */
     		dmu_buf_add_ref(ds->ds_dbuf, ds);
     	}
    @@ -1218,769 +909,6 @@ dsl_dataset_is_dirty(dsl_dataset_t *ds)
     	return (B_FALSE);
     }
     
    -/*
    - * The unique space in the head dataset can be calculated by subtracting
    - * the space used in the most recent snapshot, that is still being used
    - * in this file system, from the space currently in use.  To figure out
    - * the space in the most recent snapshot still in use, we need to take
    - * the total space used in the snapshot and subtract out the space that
    - * has been freed up since the snapshot was taken.
    - */
    -static void
    -dsl_dataset_recalc_head_uniq(dsl_dataset_t *ds)
    -{
    -	uint64_t mrs_used;
    -	uint64_t dlused, dlcomp, dluncomp;
    -
    -	ASSERT(!dsl_dataset_is_snapshot(ds));
    -
    -	if (ds->ds_phys->ds_prev_snap_obj != 0)
    -		mrs_used = ds->ds_prev->ds_phys->ds_referenced_bytes;
    -	else
    -		mrs_used = 0;
    -
    -	dsl_deadlist_space(&ds->ds_deadlist, &dlused, &dlcomp, &dluncomp);
    -
    -	ASSERT3U(dlused, <=, mrs_used);
    -	ds->ds_phys->ds_unique_bytes =
    -	    ds->ds_phys->ds_referenced_bytes - (mrs_used - dlused);
    -
    -	if (spa_version(ds->ds_dir->dd_pool->dp_spa) >=
    -	    SPA_VERSION_UNIQUE_ACCURATE)
    -		ds->ds_phys->ds_flags |= DS_FLAG_UNIQUE_ACCURATE;
    -}
    -
    -struct killarg {
    -	dsl_dataset_t *ds;
    -	dmu_tx_t *tx;
    -};
    -
    -/* ARGSUSED */
    -static int
    -kill_blkptr(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
    -    const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg)
    -{
    -	struct killarg *ka = arg;
    -	dmu_tx_t *tx = ka->tx;
    -
    -	if (bp == NULL)
    -		return (0);
    -
    -	if (zb->zb_level == ZB_ZIL_LEVEL) {
    -		ASSERT(zilog != NULL);
    -		/*
    -		 * It's a block in the intent log.  It has no
    -		 * accounting, so just free it.
    -		 */
    -		dsl_free(ka->tx->tx_pool, ka->tx->tx_txg, bp);
    -	} else {
    -		ASSERT(zilog == NULL);
    -		ASSERT3U(bp->blk_birth, >, ka->ds->ds_phys->ds_prev_snap_txg);
    -		(void) dsl_dataset_block_kill(ka->ds, bp, tx, B_FALSE);
    -	}
    -
    -	return (0);
    -}
    -
    -/* ARGSUSED */
    -static int
    -dsl_dataset_destroy_begin_check(void *arg1, void *arg2, dmu_tx_t *tx)
    -{
    -	dsl_dataset_t *ds = arg1;
    -	objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
    -	uint64_t count;
    -	int err;
    -
    -	/*
    -	 * Can't delete a head dataset if there are snapshots of it.
    -	 * (Except if the only snapshots are from the branch we cloned
    -	 * from.)
    -	 */
    -	if (ds->ds_prev != NULL &&
    -	    ds->ds_prev->ds_phys->ds_next_snap_obj == ds->ds_object)
    -		return (EBUSY);
    -
    -	/*
    -	 * This is really a dsl_dir thing, but check it here so that
    -	 * we'll be less likely to leave this dataset inconsistent &
    -	 * nearly destroyed.
    -	 */
    -	err = zap_count(mos, ds->ds_dir->dd_phys->dd_child_dir_zapobj, &count);
    -	if (err)
    -		return (err);
    -	if (count != 0)
    -		return (EEXIST);
    -
    -	return (0);
    -}
    -
    -/* ARGSUSED */
    -static void
    -dsl_dataset_destroy_begin_sync(void *arg1, void *arg2, dmu_tx_t *tx)
    -{
    -	dsl_dataset_t *ds = arg1;
    -
    -	/* Mark it as inconsistent on-disk, in case we crash */
    -	dmu_buf_will_dirty(ds->ds_dbuf, tx);
    -	ds->ds_phys->ds_flags |= DS_FLAG_INCONSISTENT;
    -
    -	spa_history_log_internal_ds(ds, "destroy begin", tx, "");
    -}
    -
    -static int
    -dsl_dataset_origin_check(struct dsl_ds_destroyarg *dsda, void *tag,
    -    dmu_tx_t *tx)
    -{
    -	dsl_dataset_t *ds = dsda->ds;
    -	dsl_dataset_t *ds_prev = ds->ds_prev;
    -
    -	if (dsl_dataset_might_destroy_origin(ds_prev)) {
    -		struct dsl_ds_destroyarg ndsda = {0};
    -
    -		/*
    -		 * If we're not prepared to remove the origin, don't remove
    -		 * the clone either.
    -		 */
    -		if (dsda->rm_origin == NULL) {
    -			dsda->need_prep = B_TRUE;
    -			return (EBUSY);
    -		}
    -
    -		ndsda.ds = ds_prev;
    -		ndsda.is_origin_rm = B_TRUE;
    -		return (dsl_dataset_destroy_check(&ndsda, tag, tx));
    -	}
    -
    -	/*
    -	 * If we're not going to remove the origin after all,
    -	 * undo the open context setup.
    -	 */
    -	if (dsda->rm_origin != NULL) {
    -		dsl_dataset_disown(dsda->rm_origin, tag);
    -		dsda->rm_origin = NULL;
    -	}
    -
    -	return (0);
    -}
    -
    -/*
    - * If you add new checks here, you may need to add
    - * additional checks to the "temporary" case in
    - * snapshot_check() in dmu_objset.c.
    - */
    -/* ARGSUSED */
    -int
    -dsl_dataset_destroy_check(void *arg1, void *arg2, dmu_tx_t *tx)
    -{
    -	struct dsl_ds_destroyarg *dsda = arg1;
    -	dsl_dataset_t *ds = dsda->ds;
    -
    -	/* we have an owner hold, so noone else can destroy us */
    -	ASSERT(!DSL_DATASET_IS_DESTROYED(ds));
    -
    -	/*
    -	 * Only allow deferred destroy on pools that support it.
    -	 * NOTE: deferred destroy is only supported on snapshots.
    -	 */
    -	if (dsda->defer) {
    -		if (spa_version(ds->ds_dir->dd_pool->dp_spa) <
    -		    SPA_VERSION_USERREFS)
    -			return (ENOTSUP);
    -		ASSERT(dsl_dataset_is_snapshot(ds));
    -		return (0);
    -	}
    -
    -	/*
    -	 * Can't delete a head dataset if there are snapshots of it.
    -	 * (Except if the only snapshots are from the branch we cloned
    -	 * from.)
    -	 */
    -	if (ds->ds_prev != NULL &&
    -	    ds->ds_prev->ds_phys->ds_next_snap_obj == ds->ds_object)
    -		return (EBUSY);
    -
    -	/*
    -	 * If we made changes this txg, traverse_dsl_dataset won't find
    -	 * them.  Try again.
    -	 */
    -	if (ds->ds_phys->ds_bp.blk_birth >= tx->tx_txg)
    -		return (EAGAIN);
    -
    -	if (dsl_dataset_is_snapshot(ds)) {
    -		/*
    -		 * If this snapshot has an elevated user reference count,
    -		 * we can't destroy it yet.
    -		 */
    -		if (ds->ds_userrefs > 0 && !dsda->releasing)
    -			return (EBUSY);
    -
    -		mutex_enter(&ds->ds_lock);
    -		/*
    -		 * Can't delete a branch point. However, if we're destroying
    -		 * a clone and removing its origin due to it having a user
    -		 * hold count of 0 and having been marked for deferred destroy,
    -		 * it's OK for the origin to have a single clone.
    -		 */
    -		if (ds->ds_phys->ds_num_children >
    -		    (dsda->is_origin_rm ? 2 : 1)) {
    -			mutex_exit(&ds->ds_lock);
    -			return (EEXIST);
    -		}
    -		mutex_exit(&ds->ds_lock);
    -	} else if (dsl_dir_is_clone(ds->ds_dir)) {
    -		return (dsl_dataset_origin_check(dsda, arg2, tx));
    -	}
    -
    -	/* XXX we should do some i/o error checking... */
    -	return (0);
    -}
    -
    -struct refsarg {
    -	kmutex_t lock;
    -	boolean_t gone;
    -	kcondvar_t cv;
    -};
    -
    -/* ARGSUSED */
    -static void
    -dsl_dataset_refs_gone(dmu_buf_t *db, void *argv)
    -{
    -	struct refsarg *arg = argv;
    -
    -	mutex_enter(&arg->lock);
    -	arg->gone = TRUE;
    -	cv_signal(&arg->cv);
    -	mutex_exit(&arg->lock);
    -}
    -
    -static void
    -dsl_dataset_drain_refs(dsl_dataset_t *ds, void *tag)
    -{
    -	struct refsarg arg;
    -
    -	mutex_init(&arg.lock, NULL, MUTEX_DEFAULT, NULL);
    -	cv_init(&arg.cv, NULL, CV_DEFAULT, NULL);
    -	arg.gone = FALSE;
    -	(void) dmu_buf_update_user(ds->ds_dbuf, ds, &arg, &ds->ds_phys,
    -	    dsl_dataset_refs_gone);
    -	dmu_buf_rele(ds->ds_dbuf, tag);
    -	mutex_enter(&arg.lock);
    -	while (!arg.gone)
    -		cv_wait(&arg.cv, &arg.lock);
    -	ASSERT(arg.gone);
    -	mutex_exit(&arg.lock);
    -	ds->ds_dbuf = NULL;
    -	ds->ds_phys = NULL;
    -	mutex_destroy(&arg.lock);
    -	cv_destroy(&arg.cv);
    -}
    -
    -static void
    -remove_from_next_clones(dsl_dataset_t *ds, uint64_t obj, dmu_tx_t *tx)
    -{
    -	objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
    -	uint64_t count;
    -	int err;
    -
    -	ASSERT(ds->ds_phys->ds_num_children >= 2);
    -	err = zap_remove_int(mos, ds->ds_phys->ds_next_clones_obj, obj, tx);
    -	/*
    -	 * The err should not be ENOENT, but a bug in a previous version
    -	 * of the code could cause upgrade_clones_cb() to not set
    -	 * ds_next_snap_obj when it should, leading to a missing entry.
    -	 * If we knew that the pool was created after
    -	 * SPA_VERSION_NEXT_CLONES, we could assert that it isn't
    -	 * ENOENT.  However, at least we can check that we don't have
    -	 * too many entries in the next_clones_obj even after failing to
    -	 * remove this one.
    -	 */
    -	if (err != ENOENT) {
    -		VERIFY0(err);
    -	}
    -	ASSERT3U(0, ==, zap_count(mos, ds->ds_phys->ds_next_clones_obj,
    -	    &count));
    -	ASSERT3U(count, <=, ds->ds_phys->ds_num_children - 2);
    -}
    -
    -static void
    -dsl_dataset_remove_clones_key(dsl_dataset_t *ds, uint64_t mintxg, dmu_tx_t *tx)
    -{
    -	objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
    -	zap_cursor_t zc;
    -	zap_attribute_t za;
    -
    -	/*
    -	 * If it is the old version, dd_clones doesn't exist so we can't
    -	 * find the clones, but deadlist_remove_key() is a no-op so it
    -	 * doesn't matter.
    -	 */
    -	if (ds->ds_dir->dd_phys->dd_clones == 0)
    -		return;
    -
    -	for (zap_cursor_init(&zc, mos, ds->ds_dir->dd_phys->dd_clones);
    -	    zap_cursor_retrieve(&zc, &za) == 0;
    -	    zap_cursor_advance(&zc)) {
    -		dsl_dataset_t *clone;
    -
    -		VERIFY3U(0, ==, dsl_dataset_hold_obj(ds->ds_dir->dd_pool,
    -		    za.za_first_integer, FTAG, &clone));
    -		if (clone->ds_dir->dd_origin_txg > mintxg) {
    -			dsl_deadlist_remove_key(&clone->ds_deadlist,
    -			    mintxg, tx);
    -			dsl_dataset_remove_clones_key(clone, mintxg, tx);
    -		}
    -		dsl_dataset_rele(clone, FTAG);
    -	}
    -	zap_cursor_fini(&zc);
    -}
    -
    -struct process_old_arg {
    -	dsl_dataset_t *ds;
    -	dsl_dataset_t *ds_prev;
    -	boolean_t after_branch_point;
    -	zio_t *pio;
    -	uint64_t used, comp, uncomp;
    -};
    -
    -static int
    -process_old_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx)
    -{
    -	struct process_old_arg *poa = arg;
    -	dsl_pool_t *dp = poa->ds->ds_dir->dd_pool;
    -
    -	if (bp->blk_birth <= poa->ds->ds_phys->ds_prev_snap_txg) {
    -		dsl_deadlist_insert(&poa->ds->ds_deadlist, bp, tx);
    -		if (poa->ds_prev && !poa->after_branch_point &&
    -		    bp->blk_birth >
    -		    poa->ds_prev->ds_phys->ds_prev_snap_txg) {
    -			poa->ds_prev->ds_phys->ds_unique_bytes +=
    -			    bp_get_dsize_sync(dp->dp_spa, bp);
    -		}
    -	} else {
    -		poa->used += bp_get_dsize_sync(dp->dp_spa, bp);
    -		poa->comp += BP_GET_PSIZE(bp);
    -		poa->uncomp += BP_GET_UCSIZE(bp);
    -		dsl_free_sync(poa->pio, dp, tx->tx_txg, bp);
    -	}
    -	return (0);
    -}
    -
    -static void
    -process_old_deadlist(dsl_dataset_t *ds, dsl_dataset_t *ds_prev,
    -    dsl_dataset_t *ds_next, boolean_t after_branch_point, dmu_tx_t *tx)
    -{
    -	struct process_old_arg poa = { 0 };
    -	dsl_pool_t *dp = ds->ds_dir->dd_pool;
    -	objset_t *mos = dp->dp_meta_objset;
    -
    -	ASSERT(ds->ds_deadlist.dl_oldfmt);
    -	ASSERT(ds_next->ds_deadlist.dl_oldfmt);
    -
    -	poa.ds = ds;
    -	poa.ds_prev = ds_prev;
    -	poa.after_branch_point = after_branch_point;
    -	poa.pio = zio_root(dp->dp_spa, NULL, NULL, ZIO_FLAG_MUSTSUCCEED);
    -	VERIFY3U(0, ==, bpobj_iterate(&ds_next->ds_deadlist.dl_bpobj,
    -	    process_old_cb, &poa, tx));
    -	VERIFY0(zio_wait(poa.pio));
    -	ASSERT3U(poa.used, ==, ds->ds_phys->ds_unique_bytes);
    -
    -	/* change snapused */
    -	dsl_dir_diduse_space(ds->ds_dir, DD_USED_SNAP,
    -	    -poa.used, -poa.comp, -poa.uncomp, tx);
    -
    -	/* swap next's deadlist to our deadlist */
    -	dsl_deadlist_close(&ds->ds_deadlist);
    -	dsl_deadlist_close(&ds_next->ds_deadlist);
    -	SWITCH64(ds_next->ds_phys->ds_deadlist_obj,
    -	    ds->ds_phys->ds_deadlist_obj);
    -	dsl_deadlist_open(&ds->ds_deadlist, mos, ds->ds_phys->ds_deadlist_obj);
    -	dsl_deadlist_open(&ds_next->ds_deadlist, mos,
    -	    ds_next->ds_phys->ds_deadlist_obj);
    -}
    -
    -static int
    -old_synchronous_dataset_destroy(dsl_dataset_t *ds, dmu_tx_t *tx)
    -{
    -	int err;
    -	struct killarg ka;
    -
    -	/*
    -	 * Free everything that we point to (that's born after
    -	 * the previous snapshot, if we are a clone)
    -	 *
    -	 * NB: this should be very quick, because we already
    -	 * freed all the objects in open context.
    -	 */
    -	ka.ds = ds;
    -	ka.tx = tx;
    -	err = traverse_dataset(ds,
    -	    ds->ds_phys->ds_prev_snap_txg, TRAVERSE_POST,
    -	    kill_blkptr, &ka);
    -	ASSERT0(err);
    -	ASSERT(!DS_UNIQUE_IS_ACCURATE(ds) || ds->ds_phys->ds_unique_bytes == 0);
    -
    -	return (err);
    -}
    -
    -void
    -dsl_dataset_destroy_sync(void *arg1, void *tag, dmu_tx_t *tx)
    -{
    -	struct dsl_ds_destroyarg *dsda = arg1;
    -	dsl_dataset_t *ds = dsda->ds;
    -	int err;
    -	int after_branch_point = FALSE;
    -	dsl_pool_t *dp = ds->ds_dir->dd_pool;
    -	objset_t *mos = dp->dp_meta_objset;
    -	dsl_dataset_t *ds_prev = NULL;
    -	boolean_t wont_destroy;
    -	uint64_t obj;
    -
    -	wont_destroy = (dsda->defer &&
    -	    (ds->ds_userrefs > 0 || ds->ds_phys->ds_num_children > 1));
    -
    -	ASSERT(ds->ds_owner || wont_destroy);
    -	ASSERT(dsda->defer || ds->ds_phys->ds_num_children <= 1);
    -	ASSERT(ds->ds_prev == NULL ||
    -	    ds->ds_prev->ds_phys->ds_next_snap_obj != ds->ds_object);
    -	ASSERT3U(ds->ds_phys->ds_bp.blk_birth, <=, tx->tx_txg);
    -
    -	if (wont_destroy) {
    -		ASSERT(spa_version(dp->dp_spa) >= SPA_VERSION_USERREFS);
    -		dmu_buf_will_dirty(ds->ds_dbuf, tx);
    -		ds->ds_phys->ds_flags |= DS_FLAG_DEFER_DESTROY;
    -		spa_history_log_internal_ds(ds, "defer_destroy", tx, "");
    -		return;
    -	}
    -
    -	/* We need to log before removing it from the namespace. */
    -	spa_history_log_internal_ds(ds, "destroy", tx, "");
    -
    -	/* signal any waiters that this dataset is going away */
    -	mutex_enter(&ds->ds_lock);
    -	ds->ds_owner = dsl_reaper;
    -	cv_broadcast(&ds->ds_exclusive_cv);
    -	mutex_exit(&ds->ds_lock);
    -
    -	/* Remove our reservation */
    -	if (ds->ds_reserved != 0) {
    -		dsl_prop_setarg_t psa;
    -		uint64_t value = 0;
    -
    -		dsl_prop_setarg_init_uint64(&psa, "refreservation",
    -		    (ZPROP_SRC_NONE | ZPROP_SRC_LOCAL | ZPROP_SRC_RECEIVED),
    -		    &value);
    -		psa.psa_effective_value = 0;	/* predict default value */
    -
    -		dsl_dataset_set_reservation_sync(ds, &psa, tx);
    -		ASSERT0(ds->ds_reserved);
    -	}
    -
    -	ASSERT(RW_WRITE_HELD(&dp->dp_config_rwlock));
    -
    -	dsl_scan_ds_destroyed(ds, tx);
    -
    -	obj = ds->ds_object;
    -
    -	if (ds->ds_phys->ds_prev_snap_obj != 0) {
    -		if (ds->ds_prev) {
    -			ds_prev = ds->ds_prev;
    -		} else {
    -			VERIFY(0 == dsl_dataset_hold_obj(dp,
    -			    ds->ds_phys->ds_prev_snap_obj, FTAG, &ds_prev));
    -		}
    -		after_branch_point =
    -		    (ds_prev->ds_phys->ds_next_snap_obj != obj);
    -
    -		dmu_buf_will_dirty(ds_prev->ds_dbuf, tx);
    -		if (after_branch_point &&
    -		    ds_prev->ds_phys->ds_next_clones_obj != 0) {
    -			remove_from_next_clones(ds_prev, obj, tx);
    -			if (ds->ds_phys->ds_next_snap_obj != 0) {
    -				VERIFY(0 == zap_add_int(mos,
    -				    ds_prev->ds_phys->ds_next_clones_obj,
    -				    ds->ds_phys->ds_next_snap_obj, tx));
    -			}
    -		}
    -		if (after_branch_point &&
    -		    ds->ds_phys->ds_next_snap_obj == 0) {
    -			/* This clone is toast. */
    -			ASSERT(ds_prev->ds_phys->ds_num_children > 1);
    -			ds_prev->ds_phys->ds_num_children--;
    -
    -			/*
    -			 * If the clone's origin has no other clones, no
    -			 * user holds, and has been marked for deferred
    -			 * deletion, then we should have done the necessary
    -			 * destroy setup for it.
    -			 */
    -			if (ds_prev->ds_phys->ds_num_children == 1 &&
    -			    ds_prev->ds_userrefs == 0 &&
    -			    DS_IS_DEFER_DESTROY(ds_prev)) {
    -				ASSERT3P(dsda->rm_origin, !=, NULL);
    -			} else {
    -				ASSERT3P(dsda->rm_origin, ==, NULL);
    -			}
    -		} else if (!after_branch_point) {
    -			ds_prev->ds_phys->ds_next_snap_obj =
    -			    ds->ds_phys->ds_next_snap_obj;
    -		}
    -	}
    -
    -	if (dsl_dataset_is_snapshot(ds)) {
    -		dsl_dataset_t *ds_next;
    -		uint64_t old_unique;
    -		uint64_t used = 0, comp = 0, uncomp = 0;
    -
    -		VERIFY(0 == dsl_dataset_hold_obj(dp,
    -		    ds->ds_phys->ds_next_snap_obj, FTAG, &ds_next));
    -		ASSERT3U(ds_next->ds_phys->ds_prev_snap_obj, ==, obj);
    -
    -		old_unique = ds_next->ds_phys->ds_unique_bytes;
    -
    -		dmu_buf_will_dirty(ds_next->ds_dbuf, tx);
    -		ds_next->ds_phys->ds_prev_snap_obj =
    -		    ds->ds_phys->ds_prev_snap_obj;
    -		ds_next->ds_phys->ds_prev_snap_txg =
    -		    ds->ds_phys->ds_prev_snap_txg;
    -		ASSERT3U(ds->ds_phys->ds_prev_snap_txg, ==,
    -		    ds_prev ? ds_prev->ds_phys->ds_creation_txg : 0);
    -
    -
    -		if (ds_next->ds_deadlist.dl_oldfmt) {
    -			process_old_deadlist(ds, ds_prev, ds_next,
    -			    after_branch_point, tx);
    -		} else {
    -			/* Adjust prev's unique space. */
    -			if (ds_prev && !after_branch_point) {
    -				dsl_deadlist_space_range(&ds_next->ds_deadlist,
    -				    ds_prev->ds_phys->ds_prev_snap_txg,
    -				    ds->ds_phys->ds_prev_snap_txg,
    -				    &used, &comp, &uncomp);
    -				ds_prev->ds_phys->ds_unique_bytes += used;
    -			}
    -
    -			/* Adjust snapused. */
    -			dsl_deadlist_space_range(&ds_next->ds_deadlist,
    -			    ds->ds_phys->ds_prev_snap_txg, UINT64_MAX,
    -			    &used, &comp, &uncomp);
    -			dsl_dir_diduse_space(ds->ds_dir, DD_USED_SNAP,
    -			    -used, -comp, -uncomp, tx);
    -
    -			/* Move blocks to be freed to pool's free list. */
    -			dsl_deadlist_move_bpobj(&ds_next->ds_deadlist,
    -			    &dp->dp_free_bpobj, ds->ds_phys->ds_prev_snap_txg,
    -			    tx);
    -			dsl_dir_diduse_space(tx->tx_pool->dp_free_dir,
    -			    DD_USED_HEAD, used, comp, uncomp, tx);
    -
    -			/* Merge our deadlist into next's and free it. */
    -			dsl_deadlist_merge(&ds_next->ds_deadlist,
    -			    ds->ds_phys->ds_deadlist_obj, tx);
    -		}
    -		dsl_deadlist_close(&ds->ds_deadlist);
    -		dsl_deadlist_free(mos, ds->ds_phys->ds_deadlist_obj, tx);
    -
    -		/* Collapse range in clone heads */
    -		dsl_dataset_remove_clones_key(ds,
    -		    ds->ds_phys->ds_creation_txg, tx);
    -
    -		if (dsl_dataset_is_snapshot(ds_next)) {
    -			dsl_dataset_t *ds_nextnext;
    -
    -			/*
    -			 * Update next's unique to include blocks which
    -			 * were previously shared by only this snapshot
    -			 * and it.  Those blocks will be born after the
    -			 * prev snap and before this snap, and will have
    -			 * died after the next snap and before the one
    -			 * after that (ie. be on the snap after next's
    -			 * deadlist).
    -			 */
    -			VERIFY(0 == dsl_dataset_hold_obj(dp,
    -			    ds_next->ds_phys->ds_next_snap_obj,
    -			    FTAG, &ds_nextnext));
    -			dsl_deadlist_space_range(&ds_nextnext->ds_deadlist,
    -			    ds->ds_phys->ds_prev_snap_txg,
    -			    ds->ds_phys->ds_creation_txg,
    -			    &used, &comp, &uncomp);
    -			ds_next->ds_phys->ds_unique_bytes += used;
    -			dsl_dataset_rele(ds_nextnext, FTAG);
    -			ASSERT3P(ds_next->ds_prev, ==, NULL);
    -
    -			/* Collapse range in this head. */
    -			dsl_dataset_t *hds;
    -			VERIFY3U(0, ==, dsl_dataset_hold_obj(dp,
    -			    ds->ds_dir->dd_phys->dd_head_dataset_obj,
    -			    FTAG, &hds));
    -			dsl_deadlist_remove_key(&hds->ds_deadlist,
    -			    ds->ds_phys->ds_creation_txg, tx);
    -			dsl_dataset_rele(hds, FTAG);
    -
    -		} else {
    -			ASSERT3P(ds_next->ds_prev, ==, ds);
    -			dsl_dataset_drop_ref(ds_next->ds_prev, ds_next);
    -			ds_next->ds_prev = NULL;
    -			if (ds_prev) {
    -				VERIFY(0 == dsl_dataset_get_ref(dp,
    -				    ds->ds_phys->ds_prev_snap_obj,
    -				    ds_next, &ds_next->ds_prev));
    -			}
    -
    -			dsl_dataset_recalc_head_uniq(ds_next);
    -
    -			/*
    -			 * Reduce the amount of our unconsmed refreservation
    -			 * being charged to our parent by the amount of
    -			 * new unique data we have gained.
    -			 */
    -			if (old_unique < ds_next->ds_reserved) {
    -				int64_t mrsdelta;
    -				uint64_t new_unique =
    -				    ds_next->ds_phys->ds_unique_bytes;
    -
    -				ASSERT(old_unique <= new_unique);
    -				mrsdelta = MIN(new_unique - old_unique,
    -				    ds_next->ds_reserved - old_unique);
    -				dsl_dir_diduse_space(ds->ds_dir,
    -				    DD_USED_REFRSRV, -mrsdelta, 0, 0, tx);
    -			}
    -		}
    -		dsl_dataset_rele(ds_next, FTAG);
    -	} else {
    -		zfeature_info_t *async_destroy =
    -		    &spa_feature_table[SPA_FEATURE_ASYNC_DESTROY];
    -		objset_t *os;
    -
    -		/*
    -		 * There's no next snapshot, so this is a head dataset.
    -		 * Destroy the deadlist.  Unless it's a clone, the
    -		 * deadlist should be empty.  (If it's a clone, it's
    -		 * safe to ignore the deadlist contents.)
    -		 */
    -		dsl_deadlist_close(&ds->ds_deadlist);
    -		dsl_deadlist_free(mos, ds->ds_phys->ds_deadlist_obj, tx);
    -		ds->ds_phys->ds_deadlist_obj = 0;
    -
    -		VERIFY3U(0, ==, dmu_objset_from_ds(ds, &os));
    -
    -		if (!spa_feature_is_enabled(dp->dp_spa, async_destroy)) {
    -			err = old_synchronous_dataset_destroy(ds, tx);
    -		} else {
    -			/*
    -			 * Move the bptree into the pool's list of trees to
    -			 * clean up and update space accounting information.
    -			 */
    -			uint64_t used, comp, uncomp;
    -
    -			zil_destroy_sync(dmu_objset_zil(os), tx);
    -
    -			if (!spa_feature_is_active(dp->dp_spa, async_destroy)) {
    -				spa_feature_incr(dp->dp_spa, async_destroy, tx);
    -				dp->dp_bptree_obj = bptree_alloc(mos, tx);
    -				VERIFY(zap_add(mos,
    -				    DMU_POOL_DIRECTORY_OBJECT,
    -				    DMU_POOL_BPTREE_OBJ, sizeof (uint64_t), 1,
    -				    &dp->dp_bptree_obj, tx) == 0);
    -			}
    -
    -			used = ds->ds_dir->dd_phys->dd_used_bytes;
    -			comp = ds->ds_dir->dd_phys->dd_compressed_bytes;
    -			uncomp = ds->ds_dir->dd_phys->dd_uncompressed_bytes;
    -
    -			ASSERT(!DS_UNIQUE_IS_ACCURATE(ds) ||
    -			    ds->ds_phys->ds_unique_bytes == used);
    -
    -			bptree_add(mos, dp->dp_bptree_obj,
    -			    &ds->ds_phys->ds_bp, ds->ds_phys->ds_prev_snap_txg,
    -			    used, comp, uncomp, tx);
    -			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,
    -			    used, comp, uncomp, tx);
    -		}
    -
    -		if (ds->ds_prev != NULL) {
    -			if (spa_version(dp->dp_spa) >= SPA_VERSION_DIR_CLONES) {
    -				VERIFY3U(0, ==, zap_remove_int(mos,
    -				    ds->ds_prev->ds_dir->dd_phys->dd_clones,
    -				    ds->ds_object, tx));
    -			}
    -			dsl_dataset_rele(ds->ds_prev, ds);
    -			ds->ds_prev = ds_prev = NULL;
    -		}
    -	}
    -
    -	/*
    -	 * This must be done after the dsl_traverse(), because it will
    -	 * re-open the objset.
    -	 */
    -	if (ds->ds_objset) {
    -		dmu_objset_evict(ds->ds_objset);
    -		ds->ds_objset = NULL;
    -	}
    -
    -	if (ds->ds_dir->dd_phys->dd_head_dataset_obj == ds->ds_object) {
    -		/* Erase the link in the dir */
    -		dmu_buf_will_dirty(ds->ds_dir->dd_dbuf, tx);
    -		ds->ds_dir->dd_phys->dd_head_dataset_obj = 0;
    -		ASSERT(ds->ds_phys->ds_snapnames_zapobj != 0);
    -		err = zap_destroy(mos, ds->ds_phys->ds_snapnames_zapobj, tx);
    -		ASSERT(err == 0);
    -	} else {
    -		/* remove from snapshot namespace */
    -		dsl_dataset_t *ds_head;
    -		ASSERT(ds->ds_phys->ds_snapnames_zapobj == 0);
    -		VERIFY(0 == dsl_dataset_hold_obj(dp,
    -		    ds->ds_dir->dd_phys->dd_head_dataset_obj, FTAG, &ds_head));
    -		VERIFY(0 == dsl_dataset_get_snapname(ds));
    -#ifdef ZFS_DEBUG
    -		{
    -			uint64_t val;
    -
    -			err = dsl_dataset_snap_lookup(ds_head,
    -			    ds->ds_snapname, &val);
    -			ASSERT0(err);
    -			ASSERT3U(val, ==, obj);
    -		}
    -#endif
    -		err = dsl_dataset_snap_remove(ds_head, ds->ds_snapname, tx);
    -		ASSERT(err == 0);
    -		dsl_dataset_rele(ds_head, FTAG);
    -	}
    -
    -	if (ds_prev && ds->ds_prev != ds_prev)
    -		dsl_dataset_rele(ds_prev, FTAG);
    -
    -	spa_prop_clear_bootfs(dp->dp_spa, ds->ds_object, tx);
    -
    -	if (ds->ds_phys->ds_next_clones_obj != 0) {
    -		uint64_t count;
    -		ASSERT(0 == zap_count(mos,
    -		    ds->ds_phys->ds_next_clones_obj, &count) && count == 0);
    -		VERIFY(0 == dmu_object_free(mos,
    -		    ds->ds_phys->ds_next_clones_obj, tx));
    -	}
    -	if (ds->ds_phys->ds_props_obj != 0)
    -		VERIFY(0 == zap_destroy(mos, ds->ds_phys->ds_props_obj, tx));
    -	if (ds->ds_phys->ds_userrefs_obj != 0)
    -		VERIFY(0 == zap_destroy(mos, ds->ds_phys->ds_userrefs_obj, tx));
    -	dsl_dir_close(ds->ds_dir, ds);
    -	ds->ds_dir = NULL;
    -	dsl_dataset_drain_refs(ds, tag);
    -	VERIFY(0 == dmu_object_free(mos, obj, tx));
    -
    -	if (dsda->rm_origin) {
    -		/*
    -		 * Remove the origin of the clone we just destroyed.
    -		 */
    -		struct dsl_ds_destroyarg ndsda = {0};
    -
    -		ndsda.ds = dsda->rm_origin;
    -		dsl_dataset_destroy_sync(&ndsda, tag, tx);
    -	}
    -}
    -
     static int
     dsl_dataset_snapshot_reserve_space(dsl_dataset_t *ds, dmu_tx_t *tx)
     {
    @@ -2009,13 +937,24 @@ dsl_dataset_snapshot_reserve_space(dsl_dataset_t *ds, dmu_tx_t *tx)
     	return (0);
     }
     
    +typedef struct dsl_dataset_snapshot_arg {
    +	nvlist_t *ddsa_snaps;
    +	nvlist_t *ddsa_props;
    +	nvlist_t *ddsa_errors;
    +} dsl_dataset_snapshot_arg_t;
    +
     int
    -dsl_dataset_snapshot_check(dsl_dataset_t *ds, const char *snapname,
    +dsl_dataset_snapshot_check_impl(dsl_dataset_t *ds, const char *snapname,
         dmu_tx_t *tx)
     {
    -	int err;
    +	int error;
     	uint64_t value;
     
    +	ds->ds_trysnap_txg = tx->tx_txg;
    +
    +	if (!dmu_tx_is_syncing(tx))
    +		return (0);
    +
     	/*
     	 * We don't allow multiple snapshots of the same txg.  If there
     	 * is already one, try again.
    @@ -2026,39 +965,87 @@ dsl_dataset_snapshot_check(dsl_dataset_t *ds, const char *snapname,
     	/*
     	 * Check for conflicting snapshot name.
     	 */
    -	err = dsl_dataset_snap_lookup(ds, snapname, &value);
    -	if (err == 0)
    +	error = dsl_dataset_snap_lookup(ds, snapname, &value);
    +	if (error == 0)
     		return (EEXIST);
    -	if (err != ENOENT)
    -		return (err);
    +	if (error != ENOENT)
    +		return (error);
     
    -	/*
    -	 * Check that the dataset's name is not too long.  Name consists
    -	 * of the dataset's length + 1 for the @-sign + snapshot name's length
    -	 */
    -	if (dsl_dataset_namelen(ds) + 1 + strlen(snapname) >= MAXNAMELEN)
    -		return (ENAMETOOLONG);
    +	error = dsl_dataset_snapshot_reserve_space(ds, tx);
    +	if (error != 0)
    +		return (error);
     
    -	err = dsl_dataset_snapshot_reserve_space(ds, tx);
    -	if (err)
    -		return (err);
    -
    -	ds->ds_trysnap_txg = tx->tx_txg;
     	return (0);
     }
     
    +static int
    +dsl_dataset_snapshot_check(void *arg, dmu_tx_t *tx)
    +{
    +	dsl_dataset_snapshot_arg_t *ddsa = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	nvpair_t *pair;
    +	int rv = 0;
    +
    +	for (pair = nvlist_next_nvpair(ddsa->ddsa_snaps, NULL);
    +	    pair != NULL; pair = nvlist_next_nvpair(ddsa->ddsa_snaps, pair)) {
    +		int error = 0;
    +		dsl_dataset_t *ds;
    +		char *name, *atp;
    +		char dsname[MAXNAMELEN];
    +
    +		name = nvpair_name(pair);
    +		if (strlen(name) >= MAXNAMELEN)
    +			error = ENAMETOOLONG;
    +		if (error == 0) {
    +			atp = strchr(name, '@');
    +			if (atp == NULL)
    +				error = EINVAL;
    +			if (error == 0)
    +				(void) strlcpy(dsname, name, atp - name + 1);
    +		}
    +		if (error == 0)
    +			error = dsl_dataset_hold(dp, dsname, FTAG, &ds);
    +		if (error == 0) {
    +			error = dsl_dataset_snapshot_check_impl(ds,
    +			    atp + 1, tx);
    +			dsl_dataset_rele(ds, FTAG);
    +		}
    +
    +		if (error != 0) {
    +			if (ddsa->ddsa_errors != NULL) {
    +				fnvlist_add_int32(ddsa->ddsa_errors,
    +				    name, error);
    +			}
    +			rv = error;
    +		}
    +	}
    +	return (rv);
    +}
    +
     void
    -dsl_dataset_snapshot_sync(dsl_dataset_t *ds, const char *snapname,
    +dsl_dataset_snapshot_sync_impl(dsl_dataset_t *ds, const char *snapname,
         dmu_tx_t *tx)
     {
    +	static zil_header_t zero_zil;
    +
     	dsl_pool_t *dp = ds->ds_dir->dd_pool;
     	dmu_buf_t *dbuf;
     	dsl_dataset_phys_t *dsphys;
     	uint64_t dsobj, crtxg;
     	objset_t *mos = dp->dp_meta_objset;
    -	int err;
    +	objset_t *os;
    +
    +	ASSERT(RRW_WRITE_HELD(&dp->dp_config_rwlock));
    +
    +	/*
    +	 * If we are on an old pool, the zil must not be active, in which
    +	 * case it will be zeroed.  Usually zil_suspend() accomplishes this.
    +	 */
    +	ASSERT(spa_version(dmu_tx_pool(tx)->dp_spa) >= SPA_VERSION_FAST_SNAP ||
    +	    dmu_objset_from_ds(ds, &os) != 0 ||
    +	    bcmp(&os->os_phys->os_zil_header, &zero_zil,
    +	    sizeof (zero_zil)) == 0);
     
    -	ASSERT(RW_WRITE_HELD(&dp->dp_config_rwlock));
     
     	/*
     	 * The origin's ds_creation_txg has to be < TXG_INITIAL
    @@ -2070,7 +1057,7 @@ dsl_dataset_snapshot_sync(dsl_dataset_t *ds, const char *snapname,
     
     	dsobj = dmu_object_alloc(mos, DMU_OT_DSL_DATASET, 0,
     	    DMU_OT_DSL_DATASET, sizeof (dsl_dataset_phys_t), tx);
    -	VERIFY(0 == dmu_bonus_hold(mos, dsobj, FTAG, &dbuf));
    +	VERIFY0(dmu_bonus_hold(mos, dsobj, FTAG, &dbuf));
     	dmu_buf_will_dirty(dbuf, tx);
     	dsphys = dbuf->db_data;
     	bzero(dsphys, sizeof (dsl_dataset_phys_t));
    @@ -2105,9 +1092,9 @@ dsl_dataset_snapshot_sync(dsl_dataset_t *ds, const char *snapname,
     			    ds->ds_prev->ds_phys->ds_creation_txg);
     			ds->ds_prev->ds_phys->ds_next_snap_obj = dsobj;
     		} else if (next_clones_obj != 0) {
    -			remove_from_next_clones(ds->ds_prev,
    +			dsl_dataset_remove_from_next_clones(ds->ds_prev,
     			    dsphys->ds_next_snap_obj, tx);
    -			VERIFY3U(0, ==, zap_add_int(mos,
    +			VERIFY0(zap_add_int(mos,
     			    next_clones_obj, dsobj, tx));
     		}
     	}
    @@ -2126,9 +1113,6 @@ dsl_dataset_snapshot_sync(dsl_dataset_t *ds, const char *snapname,
     	}
     
     	dmu_buf_will_dirty(ds->ds_dbuf, tx);
    -	zfs_dbgmsg("taking snapshot %s@%s/%llu; newkey=%llu",
    -	    ds->ds_dir->dd_myname, snapname, dsobj,
    -	    ds->ds_phys->ds_prev_snap_txg);
     	ds->ds_phys->ds_deadlist_obj = dsl_deadlist_clone(&ds->ds_deadlist,
     	    UINT64_MAX, ds->ds_phys->ds_prev_snap_obj, tx);
     	dsl_deadlist_close(&ds->ds_deadlist);
    @@ -2143,13 +1127,12 @@ dsl_dataset_snapshot_sync(dsl_dataset_t *ds, const char *snapname,
     	if (spa_version(dp->dp_spa) >= SPA_VERSION_UNIQUE_ACCURATE)
     		ds->ds_phys->ds_flags |= DS_FLAG_UNIQUE_ACCURATE;
     
    -	err = zap_add(mos, ds->ds_phys->ds_snapnames_zapobj,
    -	    snapname, 8, 1, &dsobj, tx);
    -	ASSERT(err == 0);
    +	VERIFY0(zap_add(mos, ds->ds_phys->ds_snapnames_zapobj,
    +	    snapname, 8, 1, &dsobj, tx));
     
     	if (ds->ds_prev)
    -		dsl_dataset_drop_ref(ds->ds_prev, ds);
    -	VERIFY(0 == dsl_dataset_get_ref(dp,
    +		dsl_dataset_rele(ds->ds_prev, ds);
    +	VERIFY0(dsl_dataset_hold_obj(dp,
     	    ds->ds_phys->ds_prev_snap_obj, ds, &ds->ds_prev));
     
     	dsl_scan_ds_snapshotted(ds, tx);
    @@ -2159,6 +1142,198 @@ dsl_dataset_snapshot_sync(dsl_dataset_t *ds, const char *snapname,
     	spa_history_log_internal_ds(ds->ds_prev, "snapshot", tx, "");
     }
     
    +static void
    +dsl_dataset_snapshot_sync(void *arg, dmu_tx_t *tx)
    +{
    +	dsl_dataset_snapshot_arg_t *ddsa = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	nvpair_t *pair;
    +
    +	for (pair = nvlist_next_nvpair(ddsa->ddsa_snaps, NULL);
    +	    pair != NULL; pair = nvlist_next_nvpair(ddsa->ddsa_snaps, pair)) {
    +		dsl_dataset_t *ds;
    +		char *name, *atp;
    +		char dsname[MAXNAMELEN];
    +
    +		name = nvpair_name(pair);
    +		atp = strchr(name, '@');
    +		(void) strlcpy(dsname, name, atp - name + 1);
    +		VERIFY0(dsl_dataset_hold(dp, dsname, FTAG, &ds));
    +
    +		dsl_dataset_snapshot_sync_impl(ds, atp + 1, tx);
    +		if (ddsa->ddsa_props != NULL) {
    +			dsl_props_set_sync_impl(ds->ds_prev,
    +			    ZPROP_SRC_LOCAL, ddsa->ddsa_props, tx);
    +		}
    +		dsl_dataset_rele(ds, FTAG);
    +	}
    +}
    +
    +/*
    + * The snapshots must all be in the same pool.
    + * All-or-nothing: if there are any failures, nothing will be modified.
    + */
    +int
    +dsl_dataset_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t *errors)
    +{
    +	dsl_dataset_snapshot_arg_t ddsa;
    +	nvpair_t *pair;
    +	boolean_t needsuspend;
    +	int error;
    +	spa_t *spa;
    +	char *firstname;
    +	nvlist_t *suspended = NULL;
    +
    +	pair = nvlist_next_nvpair(snaps, NULL);
    +	if (pair == NULL)
    +		return (0);
    +	firstname = nvpair_name(pair);
    +
    +	error = spa_open(firstname, &spa, FTAG);
    +	if (error != 0)
    +		return (error);
    +	needsuspend = (spa_version(spa) < SPA_VERSION_FAST_SNAP);
    +	spa_close(spa, FTAG);
    +
    +	if (needsuspend) {
    +		suspended = fnvlist_alloc();
    +		for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL;
    +		    pair = nvlist_next_nvpair(snaps, pair)) {
    +			char fsname[MAXNAMELEN];
    +			char *snapname = nvpair_name(pair);
    +			char *atp;
    +			void *cookie;
    +
    +			atp = strchr(snapname, '@');
    +			if (atp == NULL) {
    +				error = EINVAL;
    +				break;
    +			}
    +			(void) strlcpy(fsname, snapname, atp - snapname + 1);
    +
    +			error = zil_suspend(fsname, &cookie);
    +			if (error != 0)
    +				break;
    +			fnvlist_add_uint64(suspended, fsname,
    +			    (uintptr_t)cookie);
    +		}
    +	}
    +
    +	ddsa.ddsa_snaps = snaps;
    +	ddsa.ddsa_props = props;
    +	ddsa.ddsa_errors = errors;
    +
    +	if (error == 0) {
    +		error = dsl_sync_task(firstname, dsl_dataset_snapshot_check,
    +		    dsl_dataset_snapshot_sync, &ddsa,
    +		    fnvlist_num_pairs(snaps) * 3);
    +	}
    +
    +	if (suspended != NULL) {
    +		for (pair = nvlist_next_nvpair(suspended, NULL); pair != NULL;
    +		    pair = nvlist_next_nvpair(suspended, pair)) {
    +			zil_resume((void *)(uintptr_t)
    +			    fnvpair_value_uint64(pair));
    +		}
    +		fnvlist_free(suspended);
    +	}
    +
    +	return (error);
    +}
    +
    +typedef struct dsl_dataset_snapshot_tmp_arg {
    +	const char *ddsta_fsname;
    +	const char *ddsta_snapname;
    +	minor_t ddsta_cleanup_minor;
    +	const char *ddsta_htag;
    +} dsl_dataset_snapshot_tmp_arg_t;
    +
    +static int
    +dsl_dataset_snapshot_tmp_check(void *arg, dmu_tx_t *tx)
    +{
    +	dsl_dataset_snapshot_tmp_arg_t *ddsta = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	dsl_dataset_t *ds;
    +	int error;
    +
    +	error = dsl_dataset_hold(dp, ddsta->ddsta_fsname, FTAG, &ds);
    +	if (error != 0)
    +		return (error);
    +
    +	error = dsl_dataset_snapshot_check_impl(ds, ddsta->ddsta_snapname, tx);
    +	if (error != 0) {
    +		dsl_dataset_rele(ds, FTAG);
    +		return (error);
    +	}
    +
    +	if (spa_version(dp->dp_spa) < SPA_VERSION_USERREFS) {
    +		dsl_dataset_rele(ds, FTAG);
    +		return (ENOTSUP);
    +	}
    +	error = dsl_dataset_user_hold_check_one(NULL, ddsta->ddsta_htag,
    +	    B_TRUE, tx);
    +	if (error != 0) {
    +		dsl_dataset_rele(ds, FTAG);
    +		return (error);
    +	}
    +
    +	dsl_dataset_rele(ds, FTAG);
    +	return (0);
    +}
    +
    +static void
    +dsl_dataset_snapshot_tmp_sync(void *arg, dmu_tx_t *tx)
    +{
    +	dsl_dataset_snapshot_tmp_arg_t *ddsta = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	dsl_dataset_t *ds;
    +
    +	VERIFY0(dsl_dataset_hold(dp, ddsta->ddsta_fsname, FTAG, &ds));
    +
    +	dsl_dataset_snapshot_sync_impl(ds, ddsta->ddsta_snapname, tx);
    +	dsl_dataset_user_hold_sync_one(ds->ds_prev, ddsta->ddsta_htag,
    +	    ddsta->ddsta_cleanup_minor, gethrestime_sec(), tx);
    +	dsl_destroy_snapshot_sync_impl(ds->ds_prev, B_TRUE, tx);
    +
    +	dsl_dataset_rele(ds, FTAG);
    +}
    +
    +int
    +dsl_dataset_snapshot_tmp(const char *fsname, const char *snapname,
    +    minor_t cleanup_minor, const char *htag)
    +{
    +	dsl_dataset_snapshot_tmp_arg_t ddsta;
    +	int error;
    +	spa_t *spa;
    +	boolean_t needsuspend;
    +	void *cookie;
    +
    +	ddsta.ddsta_fsname = fsname;
    +	ddsta.ddsta_snapname = snapname;
    +	ddsta.ddsta_cleanup_minor = cleanup_minor;
    +	ddsta.ddsta_htag = htag;
    +
    +	error = spa_open(fsname, &spa, FTAG);
    +	if (error != 0)
    +		return (error);
    +	needsuspend = (spa_version(spa) < SPA_VERSION_FAST_SNAP);
    +	spa_close(spa, FTAG);
    +
    +	if (needsuspend) {
    +		error = zil_suspend(fsname, &cookie);
    +		if (error != 0)
    +			return (error);
    +	}
    +
    +	error = dsl_sync_task(fsname, dsl_dataset_snapshot_tmp_check,
    +	    dsl_dataset_snapshot_tmp_sync, &ddsta, 3);
    +
    +	if (needsuspend)
    +		zil_resume(cookie);
    +	return (error);
    +}
    +
    +
     void
     dsl_dataset_sync(dsl_dataset_t *ds, zio_t *zio, dmu_tx_t *tx)
     {
    @@ -2183,65 +1358,49 @@ get_clones_stat(dsl_dataset_t *ds, nvlist_t *nv)
     	objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
     	zap_cursor_t zc;
     	zap_attribute_t za;
    -	nvlist_t *propval;
    -	nvlist_t *val;
    +	nvlist_t *propval = fnvlist_alloc();
    +	nvlist_t *val = fnvlist_alloc();
     
    -	rw_enter(&ds->ds_dir->dd_pool->dp_config_rwlock, RW_READER);
    -	VERIFY(nvlist_alloc(&propval, NV_UNIQUE_NAME, KM_SLEEP) == 0);
    -	VERIFY(nvlist_alloc(&val, NV_UNIQUE_NAME, KM_SLEEP) == 0);
    +	ASSERT(dsl_pool_config_held(ds->ds_dir->dd_pool));
     
     	/*
    -	 * There may me missing entries in ds_next_clones_obj
    +	 * There may be missing entries in ds_next_clones_obj
     	 * due to a bug in a previous version of the code.
     	 * Only trust it if it has the right number of entries.
     	 */
     	if (ds->ds_phys->ds_next_clones_obj != 0) {
    -		ASSERT3U(0, ==, zap_count(mos, ds->ds_phys->ds_next_clones_obj,
    +		ASSERT0(zap_count(mos, ds->ds_phys->ds_next_clones_obj,
     		    &count));
     	}
    -	if (count != ds->ds_phys->ds_num_children - 1) {
    +	if (count != ds->ds_phys->ds_num_children - 1)
     		goto fail;
    -	}
     	for (zap_cursor_init(&zc, mos, ds->ds_phys->ds_next_clones_obj);
     	    zap_cursor_retrieve(&zc, &za) == 0;
     	    zap_cursor_advance(&zc)) {
     		dsl_dataset_t *clone;
     		char buf[ZFS_MAXNAMELEN];
    -		/*
    -		 * Even though we hold the dp_config_rwlock, the dataset
    -		 * may fail to open, returning ENOENT.  If there is a
    -		 * thread concurrently attempting to destroy this
    -		 * dataset, it will have the ds_rwlock held for
    -		 * RW_WRITER.  Our call to dsl_dataset_hold_obj() ->
    -		 * dsl_dataset_hold_ref() will fail its
    -		 * rw_tryenter(&ds->ds_rwlock, RW_READER), drop the
    -		 * dp_config_rwlock, and wait for the destroy progress
    -		 * and signal ds_exclusive_cv.  If the destroy was
    -		 * successful, we will see that
    -		 * DSL_DATASET_IS_DESTROYED(), and return ENOENT.
    -		 */
    -		if (dsl_dataset_hold_obj(ds->ds_dir->dd_pool,
    -		    za.za_first_integer, FTAG, &clone) != 0)
    -			continue;
    +		VERIFY0(dsl_dataset_hold_obj(ds->ds_dir->dd_pool,
    +		    za.za_first_integer, FTAG, &clone));
     		dsl_dir_name(clone->ds_dir, buf);
    -		VERIFY(nvlist_add_boolean(val, buf) == 0);
    +		fnvlist_add_boolean(val, buf);
     		dsl_dataset_rele(clone, FTAG);
     	}
     	zap_cursor_fini(&zc);
    -	VERIFY(nvlist_add_nvlist(propval, ZPROP_VALUE, val) == 0);
    -	VERIFY(nvlist_add_nvlist(nv, zfs_prop_to_name(ZFS_PROP_CLONES),
    -	    propval) == 0);
    +	fnvlist_add_nvlist(propval, ZPROP_VALUE, val);
    +	fnvlist_add_nvlist(nv, zfs_prop_to_name(ZFS_PROP_CLONES), propval);
     fail:
     	nvlist_free(val);
     	nvlist_free(propval);
    -	rw_exit(&ds->ds_dir->dd_pool->dp_config_rwlock);
     }
     
     void
     dsl_dataset_stats(dsl_dataset_t *ds, nvlist_t *nv)
     {
    +	dsl_pool_t *dp = ds->ds_dir->dd_pool;
     	uint64_t refd, avail, uobjs, aobjs, ratio;
     
    +	ASSERT(dsl_pool_config_held(dp));
    +
     	ratio = ds->ds_phys->ds_compressed_bytes == 0 ? 100 :
     	    (ds->ds_phys->ds_uncompressed_bytes * 100 /
     	    ds->ds_phys->ds_compressed_bytes);
    @@ -2287,10 +1446,8 @@ dsl_dataset_stats(dsl_dataset_t *ds, nvlist_t *nv)
     		dsl_pool_t *dp = ds->ds_dir->dd_pool;
     		dsl_dataset_t *prev;
     
    -		rw_enter(&dp->dp_config_rwlock, RW_READER);
     		int err = dsl_dataset_hold_obj(dp,
     		    ds->ds_phys->ds_prev_snap_obj, FTAG, &prev);
    -		rw_exit(&dp->dp_config_rwlock);
     		if (err == 0) {
     			err = dsl_dataset_space_written(prev, ds, &written,
     			    &comp, &uncomp);
    @@ -2306,6 +1463,9 @@ dsl_dataset_stats(dsl_dataset_t *ds, nvlist_t *nv)
     void
     dsl_dataset_fast_stat(dsl_dataset_t *ds, dmu_objset_stats_t *stat)
     {
    +	dsl_pool_t *dp = ds->ds_dir->dd_pool;
    +	ASSERT(dsl_pool_config_held(dp));
    +
     	stat->dds_creation_txg = ds->ds_phys->ds_creation_txg;
     	stat->dds_inconsistent = ds->ds_phys->ds_flags & DS_FLAG_INCONSISTENT;
     	stat->dds_guid = ds->ds_phys->ds_guid;
    @@ -2317,16 +1477,14 @@ dsl_dataset_fast_stat(dsl_dataset_t *ds, dmu_objset_stats_t *stat)
     		stat->dds_is_snapshot = B_FALSE;
     		stat->dds_num_clones = 0;
     
    -		rw_enter(&ds->ds_dir->dd_pool->dp_config_rwlock, RW_READER);
     		if (dsl_dir_is_clone(ds->ds_dir)) {
     			dsl_dataset_t *ods;
     
    -			VERIFY(0 == dsl_dataset_get_ref(ds->ds_dir->dd_pool,
    +			VERIFY0(dsl_dataset_hold_obj(dp,
     			    ds->ds_dir->dd_phys->dd_origin_obj, FTAG, &ods));
     			dsl_dataset_name(ods, stat->dds_origin);
    -			dsl_dataset_drop_ref(ods, FTAG);
    +			dsl_dataset_rele(ods, FTAG);
     		}
    -		rw_exit(&ds->ds_dir->dd_pool->dp_config_rwlock);
     	}
     }
     
    @@ -2364,8 +1522,7 @@ dsl_dataset_modified_since_lastsnap(dsl_dataset_t *ds)
     {
     	dsl_pool_t *dp = ds->ds_dir->dd_pool;
     
    -	ASSERT(RW_LOCK_HELD(&dp->dp_config_rwlock) ||
    -	    dsl_pool_sync_context(dp));
    +	ASSERT(dsl_pool_config_held(dp));
     	if (ds->ds_prev == NULL)
     		return (B_FALSE);
     	if (ds->ds_phys->ds_bp.blk_birth >
    @@ -2387,237 +1544,225 @@ dsl_dataset_modified_since_lastsnap(dsl_dataset_t *ds)
     	return (B_FALSE);
     }
     
    +typedef struct dsl_dataset_rename_snapshot_arg {
    +	const char *ddrsa_fsname;
    +	const char *ddrsa_oldsnapname;
    +	const char *ddrsa_newsnapname;
    +	boolean_t ddrsa_recursive;
    +	dmu_tx_t *ddrsa_tx;
    +} dsl_dataset_rename_snapshot_arg_t;
    +
     /* ARGSUSED */
     static int
    -dsl_dataset_snapshot_rename_check(void *arg1, void *arg2, dmu_tx_t *tx)
    +dsl_dataset_rename_snapshot_check_impl(dsl_pool_t *dp,
    +    dsl_dataset_t *hds, void *arg)
     {
    -	dsl_dataset_t *ds = arg1;
    -	char *newsnapname = arg2;
    -	dsl_dir_t *dd = ds->ds_dir;
    -	dsl_dataset_t *hds;
    +	dsl_dataset_rename_snapshot_arg_t *ddrsa = arg;
    +	int error;
     	uint64_t val;
    -	int err;
     
    -	err = dsl_dataset_hold_obj(dd->dd_pool,
    -	    dd->dd_phys->dd_head_dataset_obj, FTAG, &hds);
    -	if (err)
    -		return (err);
    +	error = dsl_dataset_snap_lookup(hds, ddrsa->ddrsa_oldsnapname, &val);
    +	if (error != 0) {
    +		/* ignore nonexistent snapshots */
    +		return (error == ENOENT ? 0 : error);
    +	}
     
    -	/* new name better not be in use */
    -	err = dsl_dataset_snap_lookup(hds, newsnapname, &val);
    -	dsl_dataset_rele(hds, FTAG);
    -
    -	if (err == 0)
    -		err = EEXIST;
    -	else if (err == ENOENT)
    -		err = 0;
    +	/* new name should not exist */
    +	error = dsl_dataset_snap_lookup(hds, ddrsa->ddrsa_newsnapname, &val);
    +	if (error == 0)
    +		error = EEXIST;
    +	else if (error == ENOENT)
    +		error = 0;
     
     	/* dataset name + 1 for the "@" + the new snapshot name must fit */
    -	if (dsl_dir_namelen(ds->ds_dir) + 1 + strlen(newsnapname) >= MAXNAMELEN)
    -		err = ENAMETOOLONG;
    +	if (dsl_dir_namelen(hds->ds_dir) + 1 +
    +	    strlen(ddrsa->ddrsa_newsnapname) >= MAXNAMELEN)
    +		error = ENAMETOOLONG;
     
    -	return (err);
    +	return (error);
    +}
    +
    +static int
    +dsl_dataset_rename_snapshot_check(void *arg, dmu_tx_t *tx)
    +{
    +	dsl_dataset_rename_snapshot_arg_t *ddrsa = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	dsl_dataset_t *hds;
    +	int error;
    +
    +	error = dsl_dataset_hold(dp, ddrsa->ddrsa_fsname, FTAG, &hds);
    +	if (error != 0)
    +		return (error);
    +
    +	if (ddrsa->ddrsa_recursive) {
    +		error = dmu_objset_find_dp(dp, hds->ds_dir->dd_object,
    +		    dsl_dataset_rename_snapshot_check_impl, ddrsa,
    +		    DS_FIND_CHILDREN);
    +	} else {
    +		error = dsl_dataset_rename_snapshot_check_impl(dp, hds, ddrsa);
    +	}
    +	dsl_dataset_rele(hds, FTAG);
    +	return (error);
    +}
    +
    +static int
    +dsl_dataset_rename_snapshot_sync_impl(dsl_pool_t *dp,
    +    dsl_dataset_t *hds, void *arg)
    +{
    +	dsl_dataset_rename_snapshot_arg_t *ddrsa = arg;
    +	dsl_dataset_t *ds;
    +	uint64_t val;
    +	dmu_tx_t *tx = ddrsa->ddrsa_tx;
    +	int error;
    +
    +	error = dsl_dataset_snap_lookup(hds, ddrsa->ddrsa_oldsnapname, &val);
    +	ASSERT(error == 0 || error == ENOENT);
    +	if (error == ENOENT) {
    +		/* ignore nonexistent snapshots */
    +		return (0);
    +	}
    +
    +	VERIFY0(dsl_dataset_hold_obj(dp, val, FTAG, &ds));
    +
    +	/* log before we change the name */
    +	spa_history_log_internal_ds(ds, "rename", tx,
    +	    "-> @%s", ddrsa->ddrsa_newsnapname);
    +
    +	VERIFY0(dsl_dataset_snap_remove(hds, ddrsa->ddrsa_oldsnapname, tx));
    +	mutex_enter(&ds->ds_lock);
    +	(void) strcpy(ds->ds_snapname, ddrsa->ddrsa_newsnapname);
    +	mutex_exit(&ds->ds_lock);
    +	VERIFY0(zap_add(dp->dp_meta_objset, hds->ds_phys->ds_snapnames_zapobj,
    +	    ds->ds_snapname, 8, 1, &ds->ds_object, tx));
    +
    +	dsl_dataset_rele(ds, FTAG);
    +	return (0);
     }
     
     static void
    -dsl_dataset_snapshot_rename_sync(void *arg1, void *arg2, dmu_tx_t *tx)
    +dsl_dataset_rename_snapshot_sync(void *arg, dmu_tx_t *tx)
     {
    -	dsl_dataset_t *ds = arg1;
    -	const char *newsnapname = arg2;
    -	dsl_dir_t *dd = ds->ds_dir;
    -	objset_t *mos = dd->dd_pool->dp_meta_objset;
    +	dsl_dataset_rename_snapshot_arg_t *ddrsa = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
     	dsl_dataset_t *hds;
    -	int err;
     
    -	ASSERT(ds->ds_phys->ds_next_snap_obj != 0);
    -
    -	VERIFY(0 == dsl_dataset_hold_obj(dd->dd_pool,
    -	    dd->dd_phys->dd_head_dataset_obj, FTAG, &hds));
    -
    -	VERIFY(0 == dsl_dataset_get_snapname(ds));
    -	err = dsl_dataset_snap_remove(hds, ds->ds_snapname, tx);
    -	ASSERT0(err);
    -	mutex_enter(&ds->ds_lock);
    -	(void) strcpy(ds->ds_snapname, newsnapname);
    -	mutex_exit(&ds->ds_lock);
    -	err = zap_add(mos, hds->ds_phys->ds_snapnames_zapobj,
    -	    ds->ds_snapname, 8, 1, &ds->ds_object, tx);
    -	ASSERT0(err);
    -
    -	spa_history_log_internal_ds(ds, "rename", tx,
    -	    "-> @%s", newsnapname);
    +	VERIFY0(dsl_dataset_hold(dp, ddrsa->ddrsa_fsname, FTAG, &hds));
    +	ddrsa->ddrsa_tx = tx;
    +	if (ddrsa->ddrsa_recursive) {
    +		VERIFY0(dmu_objset_find_dp(dp, hds->ds_dir->dd_object,
    +		    dsl_dataset_rename_snapshot_sync_impl, ddrsa,
    +		    DS_FIND_CHILDREN));
    +	} else {
    +		VERIFY0(dsl_dataset_rename_snapshot_sync_impl(dp, hds, ddrsa));
    +	}
     	dsl_dataset_rele(hds, FTAG);
     }
     
    -struct renamesnaparg {
    -	dsl_sync_task_group_t *dstg;
    -	char failed[MAXPATHLEN];
    -	char *oldsnap;
    -	char *newsnap;
    -};
    -
    -static int
    -dsl_snapshot_rename_one(const char *name, void *arg)
    -{
    -	struct renamesnaparg *ra = arg;
    -	dsl_dataset_t *ds = NULL;
    -	char *snapname;
    -	int err;
    -
    -	snapname = kmem_asprintf("%s@%s", name, ra->oldsnap);
    -	(void) strlcpy(ra->failed, snapname, sizeof (ra->failed));
    -
    -	/*
    -	 * For recursive snapshot renames the parent won't be changing
    -	 * so we just pass name for both the to/from argument.
    -	 */
    -	err = zfs_secpolicy_rename_perms(snapname, snapname, CRED());
    -	if (err != 0) {
    -		strfree(snapname);
    -		return (err == ENOENT ? 0 : err);
    -	}
    -
    -#ifdef _KERNEL
    -	/*
    -	 * For all filesystems undergoing rename, we'll need to unmount it.
    -	 */
    -	(void) zfs_unmount_snap(snapname, NULL);
    -#endif
    -	err = dsl_dataset_hold(snapname, ra->dstg, &ds);
    -	strfree(snapname);
    -	if (err != 0)
    -		return (err == ENOENT ? 0 : err);
    -
    -	dsl_sync_task_create(ra->dstg, dsl_dataset_snapshot_rename_check,
    -	    dsl_dataset_snapshot_rename_sync, ds, ra->newsnap, 0);
    -
    -	return (0);
    -}
    -
    -static int
    -dsl_recursive_rename(char *oldname, const char *newname)
    -{
    -	int err;
    -	struct renamesnaparg *ra;
    -	dsl_sync_task_t *dst;
    -	spa_t *spa;
    -	char *cp, *fsname = spa_strdup(oldname);
    -	int len = strlen(oldname) + 1;
    -
    -	/* truncate the snapshot name to get the fsname */
    -	cp = strchr(fsname, '@');
    -	*cp = '\0';
    -
    -	err = spa_open(fsname, &spa, FTAG);
    -	if (err) {
    -		kmem_free(fsname, len);
    -		return (err);
    -	}
    -	ra = kmem_alloc(sizeof (struct renamesnaparg), KM_SLEEP);
    -	ra->dstg = dsl_sync_task_group_create(spa_get_dsl(spa));
    -
    -	ra->oldsnap = strchr(oldname, '@') + 1;
    -	ra->newsnap = strchr(newname, '@') + 1;
    -	*ra->failed = '\0';
    -
    -	err = dmu_objset_find(fsname, dsl_snapshot_rename_one, ra,
    -	    DS_FIND_CHILDREN);
    -	kmem_free(fsname, len);
    -
    -	if (err == 0) {
    -		err = dsl_sync_task_group_wait(ra->dstg);
    -	}
    -
    -	for (dst = list_head(&ra->dstg->dstg_tasks); dst;
    -	    dst = list_next(&ra->dstg->dstg_tasks, dst)) {
    -		dsl_dataset_t *ds = dst->dst_arg1;
    -		if (dst->dst_err) {
    -			dsl_dir_name(ds->ds_dir, ra->failed);
    -			(void) strlcat(ra->failed, "@", sizeof (ra->failed));
    -			(void) strlcat(ra->failed, ra->newsnap,
    -			    sizeof (ra->failed));
    -		}
    -		dsl_dataset_rele(ds, ra->dstg);
    -	}
    -
    -	if (err)
    -		(void) strlcpy(oldname, ra->failed, sizeof (ra->failed));
    -
    -	dsl_sync_task_group_destroy(ra->dstg);
    -	kmem_free(ra, sizeof (struct renamesnaparg));
    -	spa_close(spa, FTAG);
    -	return (err);
    -}
    -
    -static int
    -dsl_valid_rename(const char *oldname, void *arg)
    -{
    -	int delta = *(int *)arg;
    -
    -	if (strlen(oldname) + delta >= MAXNAMELEN)
    -		return (ENAMETOOLONG);
    -
    -	return (0);
    -}
    -
    -#pragma weak dmu_objset_rename = dsl_dataset_rename
     int
    -dsl_dataset_rename(char *oldname, const char *newname, boolean_t recursive)
    +dsl_dataset_rename_snapshot(const char *fsname,
    +    const char *oldsnapname, const char *newsnapname, boolean_t recursive)
     {
    -	dsl_dir_t *dd;
    +	dsl_dataset_rename_snapshot_arg_t ddrsa;
    +
    +	ddrsa.ddrsa_fsname = fsname;
    +	ddrsa.ddrsa_oldsnapname = oldsnapname;
    +	ddrsa.ddrsa_newsnapname = newsnapname;
    +	ddrsa.ddrsa_recursive = recursive;
    +
    +	return (dsl_sync_task(fsname, dsl_dataset_rename_snapshot_check,
    +	    dsl_dataset_rename_snapshot_sync, &ddrsa, 1));
    +}
    +
    +static int
    +dsl_dataset_rollback_check(void *arg, dmu_tx_t *tx)
    +{
    +	const char *fsname = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
     	dsl_dataset_t *ds;
    -	const char *tail;
    -	int err;
    +	int64_t unused_refres_delta;
    +	int error;
     
    -	err = dsl_dir_open(oldname, FTAG, &dd, &tail);
    -	if (err)
    -		return (err);
    -
    -	if (tail == NULL) {
    -		int delta = strlen(newname) - strlen(oldname);
    -
    -		/* if we're growing, validate child name lengths */
    -		if (delta > 0)
    -			err = dmu_objset_find(oldname, dsl_valid_rename,
    -			    &delta, DS_FIND_CHILDREN | DS_FIND_SNAPSHOTS);
    -
    -		if (err == 0)
    -			err = dsl_dir_rename(dd, newname);
    -		dsl_dir_close(dd, FTAG);
    -		return (err);
    -	}
    -
    -	if (tail[0] != '@') {
    -		/* the name ended in a nonexistent component */
    -		dsl_dir_close(dd, FTAG);
    -		return (ENOENT);
    -	}
    -
    -	dsl_dir_close(dd, FTAG);
    -
    -	/* new name must be snapshot in same filesystem */
    -	tail = strchr(newname, '@');
    -	if (tail == NULL)
    -		return (EINVAL);
    -	tail++;
    -	if (strncmp(oldname, newname, tail - newname) != 0)
    -		return (EXDEV);
    -
    -	if (recursive) {
    -		err = dsl_recursive_rename(oldname, newname);
    -	} else {
    -		err = dsl_dataset_hold(oldname, FTAG, &ds);
    -		if (err)
    -			return (err);
    -
    -		err = dsl_sync_task_do(ds->ds_dir->dd_pool,
    -		    dsl_dataset_snapshot_rename_check,
    -		    dsl_dataset_snapshot_rename_sync, ds, (char *)tail, 1);
    +	error = dsl_dataset_hold(dp, fsname, FTAG, &ds);
    +	if (error != 0)
    +		return (error);
     
    +	/* must not be a snapshot */
    +	if (dsl_dataset_is_snapshot(ds)) {
     		dsl_dataset_rele(ds, FTAG);
    +		return (EINVAL);
     	}
     
    -	return (err);
    +	/* must have a most recent snapshot */
    +	if (ds->ds_phys->ds_prev_snap_txg < TXG_INITIAL) {
    +		dsl_dataset_rele(ds, FTAG);
    +		return (EINVAL);
    +	}
    +
    +	if (dsl_dataset_long_held(ds)) {
    +		dsl_dataset_rele(ds, FTAG);
    +		return (EBUSY);
    +	}
    +
    +	/*
    +	 * Check if the snap we are rolling back to uses more than
    +	 * the refquota.
    +	 */
    +	if (ds->ds_quota != 0 &&
    +	    ds->ds_prev->ds_phys->ds_referenced_bytes > ds->ds_quota) {
    +		dsl_dataset_rele(ds, FTAG);
    +		return (EDQUOT);
    +	}
    +
    +	/*
    +	 * When we do the clone swap, we will temporarily use more space
    +	 * due to the refreservation (the head will no longer have any
    +	 * unique space, so the entire amount of the refreservation will need
    +	 * to be free).  We will immediately destroy the clone, freeing
    +	 * this space, but the freeing happens over many txg's.
    +	 */
    +	unused_refres_delta = (int64_t)MIN(ds->ds_reserved,
    +	    ds->ds_phys->ds_unique_bytes);
    +
    +	if (unused_refres_delta > 0 &&
    +	    unused_refres_delta >
    +	    dsl_dir_space_available(ds->ds_dir, NULL, 0, TRUE)) {
    +		dsl_dataset_rele(ds, FTAG);
    +		return (ENOSPC);
    +	}
    +
    +	dsl_dataset_rele(ds, FTAG);
    +	return (0);
    +}
    +
    +static void
    +dsl_dataset_rollback_sync(void *arg, dmu_tx_t *tx)
    +{
    +	const char *fsname = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	dsl_dataset_t *ds, *clone;
    +	uint64_t cloneobj;
    +
    +	VERIFY0(dsl_dataset_hold(dp, fsname, FTAG, &ds));
    +
    +	cloneobj = dsl_dataset_create_sync(ds->ds_dir, "%rollback",
    +	    ds->ds_prev, DS_CREATE_FLAG_NODIRTY, kcred, tx);
    +
    +	VERIFY0(dsl_dataset_hold_obj(dp, cloneobj, FTAG, &clone));
    +
    +	dsl_dataset_clone_swap_sync_impl(clone, ds, tx);
    +	dsl_dataset_zero_zil(ds, tx);
    +
    +	dsl_destroy_head_sync_impl(clone, tx);
    +
    +	dsl_dataset_rele(clone, FTAG);
    +	dsl_dataset_rele(ds, FTAG);
    +}
    +
    +int
    +dsl_dataset_rollback(const char *fsname)
    +{
    +	return (dsl_sync_task(fsname, dsl_dataset_rollback_check,
    +	    dsl_dataset_rollback_sync, (void *)fsname, 1));
     }
     
     struct promotenode {
    @@ -2625,49 +1770,66 @@ struct promotenode {
     	dsl_dataset_t *ds;
     };
     
    -struct promotearg {
    +typedef struct dsl_dataset_promote_arg {
    +	const char *ddpa_clonename;
    +	dsl_dataset_t *ddpa_clone;
     	list_t shared_snaps, origin_snaps, clone_snaps;
    -	dsl_dataset_t *origin_origin;
    +	dsl_dataset_t *origin_origin; /* origin of the origin */
     	uint64_t used, comp, uncomp, unique, cloneusedsnap, originusedsnap;
     	char *err_ds;
    -};
    +} dsl_dataset_promote_arg_t;
     
     static int snaplist_space(list_t *l, uint64_t mintxg, uint64_t *spacep);
    -static boolean_t snaplist_unstable(list_t *l);
    +static int promote_hold(dsl_dataset_promote_arg_t *ddpa, dsl_pool_t *dp,
    +    void *tag);
    +static void promote_rele(dsl_dataset_promote_arg_t *ddpa, void *tag);
     
     static int
    -dsl_dataset_promote_check(void *arg1, void *arg2, dmu_tx_t *tx)
    +dsl_dataset_promote_check(void *arg, dmu_tx_t *tx)
     {
    -	dsl_dataset_t *hds = arg1;
    -	struct promotearg *pa = arg2;
    -	struct promotenode *snap = list_head(&pa->shared_snaps);
    -	dsl_dataset_t *origin_ds = snap->ds;
    +	dsl_dataset_promote_arg_t *ddpa = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	dsl_dataset_t *hds;
    +	struct promotenode *snap;
    +	dsl_dataset_t *origin_ds;
     	int err;
     	uint64_t unused;
     
    -	/* Check that it is a real clone */
    -	if (!dsl_dir_is_clone(hds->ds_dir))
    -		return (EINVAL);
    +	err = promote_hold(ddpa, dp, FTAG);
    +	if (err != 0)
    +		return (err);
     
    -	/* Since this is so expensive, don't do the preliminary check */
    -	if (!dmu_tx_is_syncing(tx))
    -		return (0);
    +	hds = ddpa->ddpa_clone;
     
    -	if (hds->ds_phys->ds_flags & DS_FLAG_NOPROMOTE)
    +	if (hds->ds_phys->ds_flags & DS_FLAG_NOPROMOTE) {
    +		promote_rele(ddpa, FTAG);
     		return (EXDEV);
    +	}
    +
    +	/*
    +	 * Compute and check the amount of space to transfer.  Since this is
    +	 * so expensive, don't do the preliminary check.
    +	 */
    +	if (!dmu_tx_is_syncing(tx)) {
    +		promote_rele(ddpa, FTAG);
    +		return (0);
    +	}
    +
    +	snap = list_head(&ddpa->shared_snaps);
    +	origin_ds = snap->ds;
     
     	/* compute origin's new unique space */
    -	snap = list_tail(&pa->clone_snaps);
    +	snap = list_tail(&ddpa->clone_snaps);
     	ASSERT3U(snap->ds->ds_phys->ds_prev_snap_obj, ==, origin_ds->ds_object);
     	dsl_deadlist_space_range(&snap->ds->ds_deadlist,
     	    origin_ds->ds_phys->ds_prev_snap_txg, UINT64_MAX,
    -	    &pa->unique, &unused, &unused);
    +	    &ddpa->unique, &unused, &unused);
     
     	/*
     	 * Walk the snapshots that we are moving
     	 *
     	 * Compute space to transfer.  Consider the incremental changes
    -	 * to used for each snapshot:
    +	 * to used by each snapshot:
     	 * (my used) = (prev's used) + (blocks born) - (blocks killed)
     	 * So each snapshot gave birth to:
     	 * (blocks born) = (my used) - (prev's used) + (blocks killed)
    @@ -2678,18 +1840,28 @@ dsl_dataset_promote_check(void *arg1, void *arg2, dmu_tx_t *tx)
     	 * Note however, if we stop before we reach the ORIGIN we get:
     	 * uN + kN + kN-1 + ... + kM - uM-1
     	 */
    -	pa->used = origin_ds->ds_phys->ds_referenced_bytes;
    -	pa->comp = origin_ds->ds_phys->ds_compressed_bytes;
    -	pa->uncomp = origin_ds->ds_phys->ds_uncompressed_bytes;
    -	for (snap = list_head(&pa->shared_snaps); snap;
    -	    snap = list_next(&pa->shared_snaps, snap)) {
    +	ddpa->used = origin_ds->ds_phys->ds_referenced_bytes;
    +	ddpa->comp = origin_ds->ds_phys->ds_compressed_bytes;
    +	ddpa->uncomp = origin_ds->ds_phys->ds_uncompressed_bytes;
    +	for (snap = list_head(&ddpa->shared_snaps); snap;
    +	    snap = list_next(&ddpa->shared_snaps, snap)) {
     		uint64_t val, dlused, dlcomp, dluncomp;
     		dsl_dataset_t *ds = snap->ds;
     
    +		/*
    +		 * If there are long holds, we won't be able to evict
    +		 * the objset.
    +		 */
    +		if (dsl_dataset_long_held(ds)) {
    +			err = EBUSY;
    +			goto out;
    +		}
    +
     		/* Check that the snapshot name does not conflict */
    -		VERIFY(0 == dsl_dataset_get_snapname(ds));
    +		VERIFY0(dsl_dataset_get_snapname(ds));
     		err = dsl_dataset_snap_lookup(hds, ds->ds_snapname, &val);
     		if (err == 0) {
    +			(void) strcpy(ddpa->err_ds, snap->ds->ds_snapname);
     			err = EEXIST;
     			goto out;
     		}
    @@ -2702,26 +1874,27 @@ dsl_dataset_promote_check(void *arg1, void *arg2, dmu_tx_t *tx)
     
     		dsl_deadlist_space(&ds->ds_deadlist,
     		    &dlused, &dlcomp, &dluncomp);
    -		pa->used += dlused;
    -		pa->comp += dlcomp;
    -		pa->uncomp += dluncomp;
    +		ddpa->used += dlused;
    +		ddpa->comp += dlcomp;
    +		ddpa->uncomp += dluncomp;
     	}
     
     	/*
     	 * If we are a clone of a clone then we never reached ORIGIN,
     	 * so we need to subtract out the clone origin's used space.
     	 */
    -	if (pa->origin_origin) {
    -		pa->used -= pa->origin_origin->ds_phys->ds_referenced_bytes;
    -		pa->comp -= pa->origin_origin->ds_phys->ds_compressed_bytes;
    -		pa->uncomp -= pa->origin_origin->ds_phys->ds_uncompressed_bytes;
    +	if (ddpa->origin_origin) {
    +		ddpa->used -= ddpa->origin_origin->ds_phys->ds_referenced_bytes;
    +		ddpa->comp -= ddpa->origin_origin->ds_phys->ds_compressed_bytes;
    +		ddpa->uncomp -=
    +		    ddpa->origin_origin->ds_phys->ds_uncompressed_bytes;
     	}
     
     	/* Check that there is enough space here */
     	err = dsl_dir_transfer_possible(origin_ds->ds_dir, hds->ds_dir,
    -	    pa->used);
    -	if (err)
    -		return (err);
    +	    ddpa->used);
    +	if (err != 0)
    +		goto out;
     
     	/*
     	 * Compute the amounts of space that will be used by snapshots
    @@ -2739,68 +1912,75 @@ dsl_dataset_promote_check(void *arg1, void *arg2, dmu_tx_t *tx)
     		 * calls will be fast because they do not have to
     		 * iterate over all bps.
     		 */
    -		snap = list_head(&pa->origin_snaps);
    -		err = snaplist_space(&pa->shared_snaps,
    -		    snap->ds->ds_dir->dd_origin_txg, &pa->cloneusedsnap);
    -		if (err)
    -			return (err);
    +		snap = list_head(&ddpa->origin_snaps);
    +		err = snaplist_space(&ddpa->shared_snaps,
    +		    snap->ds->ds_dir->dd_origin_txg, &ddpa->cloneusedsnap);
    +		if (err != 0)
    +			goto out;
     
    -		err = snaplist_space(&pa->clone_snaps,
    +		err = snaplist_space(&ddpa->clone_snaps,
     		    snap->ds->ds_dir->dd_origin_txg, &space);
    -		if (err)
    -			return (err);
    -		pa->cloneusedsnap += space;
    +		if (err != 0)
    +			goto out;
    +		ddpa->cloneusedsnap += space;
     	}
     	if (origin_ds->ds_dir->dd_phys->dd_flags & DD_FLAG_USED_BREAKDOWN) {
    -		err = snaplist_space(&pa->origin_snaps,
    -		    origin_ds->ds_phys->ds_creation_txg, &pa->originusedsnap);
    -		if (err)
    -			return (err);
    +		err = snaplist_space(&ddpa->origin_snaps,
    +		    origin_ds->ds_phys->ds_creation_txg, &ddpa->originusedsnap);
    +		if (err != 0)
    +			goto out;
     	}
     
    -	return (0);
     out:
    -	pa->err_ds =  snap->ds->ds_snapname;
    +	promote_rele(ddpa, FTAG);
     	return (err);
     }
     
     static void
    -dsl_dataset_promote_sync(void *arg1, void *arg2, dmu_tx_t *tx)
    +dsl_dataset_promote_sync(void *arg, dmu_tx_t *tx)
     {
    -	dsl_dataset_t *hds = arg1;
    -	struct promotearg *pa = arg2;
    -	struct promotenode *snap = list_head(&pa->shared_snaps);
    -	dsl_dataset_t *origin_ds = snap->ds;
    +	dsl_dataset_promote_arg_t *ddpa = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	dsl_dataset_t *hds;
    +	struct promotenode *snap;
    +	dsl_dataset_t *origin_ds;
     	dsl_dataset_t *origin_head;
    -	dsl_dir_t *dd = hds->ds_dir;
    -	dsl_pool_t *dp = hds->ds_dir->dd_pool;
    +	dsl_dir_t *dd;
     	dsl_dir_t *odd = NULL;
     	uint64_t oldnext_obj;
     	int64_t delta;
     
    -	ASSERT(0 == (hds->ds_phys->ds_flags & DS_FLAG_NOPROMOTE));
    +	VERIFY0(promote_hold(ddpa, dp, FTAG));
    +	hds = ddpa->ddpa_clone;
     
    -	snap = list_head(&pa->origin_snaps);
    +	ASSERT0(hds->ds_phys->ds_flags & DS_FLAG_NOPROMOTE);
    +
    +	snap = list_head(&ddpa->shared_snaps);
    +	origin_ds = snap->ds;
    +	dd = hds->ds_dir;
    +
    +	snap = list_head(&ddpa->origin_snaps);
     	origin_head = snap->ds;
     
     	/*
     	 * We need to explicitly open odd, since origin_ds's dd will be
     	 * changing.
     	 */
    -	VERIFY(0 == dsl_dir_open_obj(dp, origin_ds->ds_dir->dd_object,
    +	VERIFY0(dsl_dir_hold_obj(dp, origin_ds->ds_dir->dd_object,
     	    NULL, FTAG, &odd));
     
     	/* change origin's next snap */
     	dmu_buf_will_dirty(origin_ds->ds_dbuf, tx);
     	oldnext_obj = origin_ds->ds_phys->ds_next_snap_obj;
    -	snap = list_tail(&pa->clone_snaps);
    +	snap = list_tail(&ddpa->clone_snaps);
     	ASSERT3U(snap->ds->ds_phys->ds_prev_snap_obj, ==, origin_ds->ds_object);
     	origin_ds->ds_phys->ds_next_snap_obj = snap->ds->ds_object;
     
     	/* change the origin's next clone */
     	if (origin_ds->ds_phys->ds_next_clones_obj) {
    -		remove_from_next_clones(origin_ds, snap->ds->ds_object, tx);
    -		VERIFY3U(0, ==, zap_add_int(dp->dp_meta_objset,
    +		dsl_dataset_remove_from_next_clones(origin_ds,
    +		    snap->ds->ds_object, tx);
    +		VERIFY0(zap_add_int(dp->dp_meta_objset,
     		    origin_ds->ds_phys->ds_next_clones_obj,
     		    oldnext_obj, tx));
     	}
    @@ -2817,39 +1997,43 @@ dsl_dataset_promote_sync(void *arg1, void *arg2, dmu_tx_t *tx)
     
     	/* change dd_clone entries */
     	if (spa_version(dp->dp_spa) >= SPA_VERSION_DIR_CLONES) {
    -		VERIFY3U(0, ==, zap_remove_int(dp->dp_meta_objset,
    +		VERIFY0(zap_remove_int(dp->dp_meta_objset,
     		    odd->dd_phys->dd_clones, hds->ds_object, tx));
    -		VERIFY3U(0, ==, zap_add_int(dp->dp_meta_objset,
    -		    pa->origin_origin->ds_dir->dd_phys->dd_clones,
    +		VERIFY0(zap_add_int(dp->dp_meta_objset,
    +		    ddpa->origin_origin->ds_dir->dd_phys->dd_clones,
     		    hds->ds_object, tx));
     
    -		VERIFY3U(0, ==, zap_remove_int(dp->dp_meta_objset,
    -		    pa->origin_origin->ds_dir->dd_phys->dd_clones,
    +		VERIFY0(zap_remove_int(dp->dp_meta_objset,
    +		    ddpa->origin_origin->ds_dir->dd_phys->dd_clones,
     		    origin_head->ds_object, tx));
     		if (dd->dd_phys->dd_clones == 0) {
     			dd->dd_phys->dd_clones = zap_create(dp->dp_meta_objset,
     			    DMU_OT_DSL_CLONES, DMU_OT_NONE, 0, tx);
     		}
    -		VERIFY3U(0, ==, zap_add_int(dp->dp_meta_objset,
    +		VERIFY0(zap_add_int(dp->dp_meta_objset,
     		    dd->dd_phys->dd_clones, origin_head->ds_object, tx));
    -
     	}
     
     	/* move snapshots to this dir */
    -	for (snap = list_head(&pa->shared_snaps); snap;
    -	    snap = list_next(&pa->shared_snaps, snap)) {
    +	for (snap = list_head(&ddpa->shared_snaps); snap;
    +	    snap = list_next(&ddpa->shared_snaps, snap)) {
     		dsl_dataset_t *ds = snap->ds;
     
    -		/* unregister props as dsl_dir is changing */
    +		/*
    +		 * Property callbacks are registered to a particular
    +		 * dsl_dir.  Since ours is changing, evict the objset
    +		 * so that they will be unregistered from the old dsl_dir.
    +		 */
     		if (ds->ds_objset) {
     			dmu_objset_evict(ds->ds_objset);
     			ds->ds_objset = NULL;
     		}
    +
     		/* move snap name entry */
    -		VERIFY(0 == dsl_dataset_get_snapname(ds));
    -		VERIFY(0 == dsl_dataset_snap_remove(origin_head,
    +		VERIFY0(dsl_dataset_get_snapname(ds));
    +		VERIFY0(dsl_dataset_snap_remove(origin_head,
     		    ds->ds_snapname, tx));
    -		VERIFY(0 == zap_add(dp->dp_meta_objset,
    +		VERIFY0(zap_add(dp->dp_meta_objset,
     		    hds->ds_phys->ds_snapnames_zapobj, ds->ds_snapname,
     		    8, 1, &ds->ds_object, tx));
     
    @@ -2858,8 +2042,8 @@ dsl_dataset_promote_sync(void *arg1, void *arg2, dmu_tx_t *tx)
     		ASSERT3U(ds->ds_phys->ds_dir_obj, ==, odd->dd_object);
     		ds->ds_phys->ds_dir_obj = dd->dd_object;
     		ASSERT3P(ds->ds_dir, ==, odd);
    -		dsl_dir_close(ds->ds_dir, ds);
    -		VERIFY(0 == dsl_dir_open_obj(dp, dd->dd_object,
    +		dsl_dir_rele(ds->ds_dir, ds);
    +		VERIFY0(dsl_dir_hold_obj(dp, dd->dd_object,
     		    NULL, ds, &ds->ds_dir));
     
     		/* move any clone references */
    @@ -2883,20 +2067,20 @@ dsl_dataset_promote_sync(void *arg1, void *arg2, dmu_tx_t *tx)
     					continue;
     				}
     
    -				VERIFY3U(0, ==, dsl_dataset_hold_obj(dp,
    +				VERIFY0(dsl_dataset_hold_obj(dp,
     				    za.za_first_integer, FTAG, &cnds));
     				o = cnds->ds_dir->dd_phys->dd_head_dataset_obj;
     
    -				VERIFY3U(zap_remove_int(dp->dp_meta_objset,
    -				    odd->dd_phys->dd_clones, o, tx), ==, 0);
    -				VERIFY3U(zap_add_int(dp->dp_meta_objset,
    -				    dd->dd_phys->dd_clones, o, tx), ==, 0);
    +				VERIFY0(zap_remove_int(dp->dp_meta_objset,
    +				    odd->dd_phys->dd_clones, o, tx));
    +				VERIFY0(zap_add_int(dp->dp_meta_objset,
    +				    dd->dd_phys->dd_clones, o, tx));
     				dsl_dataset_rele(cnds, FTAG);
     			}
     			zap_cursor_fini(&zc);
     		}
     
    -		ASSERT0(dsl_prop_numcb(ds));
    +		ASSERT(!dsl_prop_hascb(ds));
     	}
     
     	/*
    @@ -2906,31 +2090,31 @@ dsl_dataset_promote_sync(void *arg1, void *arg2, dmu_tx_t *tx)
     	 * is true for each of {clone,origin} independently.
     	 */
     
    -	delta = pa->cloneusedsnap -
    +	delta = ddpa->cloneusedsnap -
     	    dd->dd_phys->dd_used_breakdown[DD_USED_SNAP];
     	ASSERT3S(delta, >=, 0);
    -	ASSERT3U(pa->used, >=, delta);
    +	ASSERT3U(ddpa->used, >=, delta);
     	dsl_dir_diduse_space(dd, DD_USED_SNAP, delta, 0, 0, tx);
     	dsl_dir_diduse_space(dd, DD_USED_HEAD,
    -	    pa->used - delta, pa->comp, pa->uncomp, tx);
    +	    ddpa->used - delta, ddpa->comp, ddpa->uncomp, tx);
     
    -	delta = pa->originusedsnap -
    +	delta = ddpa->originusedsnap -
     	    odd->dd_phys->dd_used_breakdown[DD_USED_SNAP];
     	ASSERT3S(delta, <=, 0);
    -	ASSERT3U(pa->used, >=, -delta);
    +	ASSERT3U(ddpa->used, >=, -delta);
     	dsl_dir_diduse_space(odd, DD_USED_SNAP, delta, 0, 0, tx);
     	dsl_dir_diduse_space(odd, DD_USED_HEAD,
    -	    -pa->used - delta, -pa->comp, -pa->uncomp, tx);
    +	    -ddpa->used - delta, -ddpa->comp, -ddpa->uncomp, tx);
     
    -	origin_ds->ds_phys->ds_unique_bytes = pa->unique;
    +	origin_ds->ds_phys->ds_unique_bytes = ddpa->unique;
     
     	/* log history record */
     	spa_history_log_internal_ds(hds, "promote", tx, "");
     
    -	dsl_dir_close(odd, FTAG);
    +	dsl_dir_rele(odd, FTAG);
    +	promote_rele(ddpa, FTAG);
     }
     
    -static char *snaplist_tag = "snaplist";
     /*
      * Make a list of dsl_dataset_t's for the snapshots between first_obj
      * (exclusive) and last_obj (inclusive).  The list will be in reverse
    @@ -2938,13 +2122,11 @@ static char *snaplist_tag = "snaplist";
      * snapshots back to this dataset's origin.
      */
     static int
    -snaplist_make(dsl_pool_t *dp, boolean_t own,
    -    uint64_t first_obj, uint64_t last_obj, list_t *l)
    +snaplist_make(dsl_pool_t *dp,
    +    uint64_t first_obj, uint64_t last_obj, list_t *l, void *tag)
     {
     	uint64_t obj = last_obj;
     
    -	ASSERT(RW_LOCK_HELD(&dp->dp_config_rwlock));
    -
     	list_create(l, sizeof (struct promotenode),
     	    offsetof(struct promotenode, link));
     
    @@ -2953,28 +2135,15 @@ snaplist_make(dsl_pool_t *dp, boolean_t own,
     		struct promotenode *snap;
     		int err;
     
    -		if (own) {
    -			err = dsl_dataset_own_obj(dp, obj,
    -			    0, snaplist_tag, &ds);
    -			if (err == 0)
    -				dsl_dataset_make_exclusive(ds, snaplist_tag);
    -		} else {
    -			err = dsl_dataset_hold_obj(dp, obj, snaplist_tag, &ds);
    -		}
    -		if (err == ENOENT) {
    -			/* lost race with snapshot destroy */
    -			struct promotenode *last = list_tail(l);
    -			ASSERT(obj != last->ds->ds_phys->ds_prev_snap_obj);
    -			obj = last->ds->ds_phys->ds_prev_snap_obj;
    -			continue;
    -		} else if (err) {
    +		err = dsl_dataset_hold_obj(dp, obj, tag, &ds);
    +		ASSERT(err != ENOENT);
    +		if (err != 0)
     			return (err);
    -		}
     
     		if (first_obj == 0)
     			first_obj = ds->ds_dir->dd_phys->dd_origin_obj;
     
    -		snap = kmem_alloc(sizeof (struct promotenode), KM_SLEEP);
    +		snap = kmem_alloc(sizeof (*snap), KM_SLEEP);
     		snap->ds = ds;
     		list_insert_tail(l, snap);
     		obj = ds->ds_phys->ds_prev_snap_obj;
    @@ -2999,208 +2168,209 @@ snaplist_space(list_t *l, uint64_t mintxg, uint64_t *spacep)
     }
     
     static void
    -snaplist_destroy(list_t *l, boolean_t own)
    +snaplist_destroy(list_t *l, void *tag)
     {
     	struct promotenode *snap;
     
    -	if (!l || !list_link_active(&l->list_head))
    +	if (l == NULL || !list_link_active(&l->list_head))
     		return;
     
     	while ((snap = list_tail(l)) != NULL) {
     		list_remove(l, snap);
    -		if (own)
    -			dsl_dataset_disown(snap->ds, snaplist_tag);
    -		else
    -			dsl_dataset_rele(snap->ds, snaplist_tag);
    -		kmem_free(snap, sizeof (struct promotenode));
    +		dsl_dataset_rele(snap->ds, tag);
    +		kmem_free(snap, sizeof (*snap));
     	}
     	list_destroy(l);
     }
     
    +static int
    +promote_hold(dsl_dataset_promote_arg_t *ddpa, dsl_pool_t *dp, void *tag)
    +{
    +	int error;
    +	dsl_dir_t *dd;
    +	struct promotenode *snap;
    +
    +	error = dsl_dataset_hold(dp, ddpa->ddpa_clonename, tag,
    +	    &ddpa->ddpa_clone);
    +	if (error != 0)
    +		return (error);
    +	dd = ddpa->ddpa_clone->ds_dir;
    +
    +	if (dsl_dataset_is_snapshot(ddpa->ddpa_clone) ||
    +	    !dsl_dir_is_clone(dd)) {
    +		dsl_dataset_rele(ddpa->ddpa_clone, tag);
    +		return (EINVAL);
    +	}
    +
    +	error = snaplist_make(dp, 0, dd->dd_phys->dd_origin_obj,
    +	    &ddpa->shared_snaps, tag);
    +	if (error != 0)
    +		goto out;
    +
    +	error = snaplist_make(dp, 0, ddpa->ddpa_clone->ds_object,
    +	    &ddpa->clone_snaps, tag);
    +	if (error != 0)
    +		goto out;
    +
    +	snap = list_head(&ddpa->shared_snaps);
    +	ASSERT3U(snap->ds->ds_object, ==, dd->dd_phys->dd_origin_obj);
    +	error = snaplist_make(dp, dd->dd_phys->dd_origin_obj,
    +	    snap->ds->ds_dir->dd_phys->dd_head_dataset_obj,
    +	    &ddpa->origin_snaps, tag);
    +	if (error != 0)
    +		goto out;
    +
    +	if (snap->ds->ds_dir->dd_phys->dd_origin_obj != 0) {
    +		error = dsl_dataset_hold_obj(dp,
    +		    snap->ds->ds_dir->dd_phys->dd_origin_obj,
    +		    tag, &ddpa->origin_origin);
    +		if (error != 0)
    +			goto out;
    +	}
    +out:
    +	if (error != 0)
    +		promote_rele(ddpa, tag);
    +	return (error);
    +}
    +
    +static void
    +promote_rele(dsl_dataset_promote_arg_t *ddpa, void *tag)
    +{
    +	snaplist_destroy(&ddpa->shared_snaps, tag);
    +	snaplist_destroy(&ddpa->clone_snaps, tag);
    +	snaplist_destroy(&ddpa->origin_snaps, tag);
    +	if (ddpa->origin_origin != NULL)
    +		dsl_dataset_rele(ddpa->origin_origin, tag);
    +	dsl_dataset_rele(ddpa->ddpa_clone, tag);
    +}
    +
     /*
    - * Promote a clone.  Nomenclature note:
    - * "clone" or "cds": the original clone which is being promoted
    - * "origin" or "ods": the snapshot which is originally clone's origin
    - * "origin head" or "ohds": the dataset which is the head
    - * (filesystem/volume) for the origin
    - * "origin origin": the origin of the origin's filesystem (typically
    - * NULL, indicating that the clone is not a clone of a clone).
    + * Promote a clone.
    + *
    + * If it fails due to a conflicting snapshot name, "conflsnap" will be filled
    + * in with the name.  (It must be at least MAXNAMELEN bytes long.)
      */
     int
     dsl_dataset_promote(const char *name, char *conflsnap)
     {
    -	dsl_dataset_t *ds;
    -	dsl_dir_t *dd;
    -	dsl_pool_t *dp;
    -	dmu_object_info_t doi;
    -	struct promotearg pa = { 0 };
    -	struct promotenode *snap;
    -	int err;
    -
    -	err = dsl_dataset_hold(name, FTAG, &ds);
    -	if (err)
    -		return (err);
    -	dd = ds->ds_dir;
    -	dp = dd->dd_pool;
    -
    -	err = dmu_object_info(dp->dp_meta_objset,
    -	    ds->ds_phys->ds_snapnames_zapobj, &doi);
    -	if (err) {
    -		dsl_dataset_rele(ds, FTAG);
    -		return (err);
    -	}
    -
    -	if (dsl_dataset_is_snapshot(ds) || dd->dd_phys->dd_origin_obj == 0) {
    -		dsl_dataset_rele(ds, FTAG);
    -		return (EINVAL);
    -	}
    +	dsl_dataset_promote_arg_t ddpa = { 0 };
    +	uint64_t numsnaps;
    +	int error;
    +	objset_t *os;
     
     	/*
    -	 * We are going to inherit all the snapshots taken before our
    -	 * origin (i.e., our new origin will be our parent's origin).
    -	 * Take ownership of them so that we can rename them into our
    -	 * namespace.
    +	 * We will modify space proportional to the number of
    +	 * snapshots.  Compute numsnaps.
     	 */
    -	rw_enter(&dp->dp_config_rwlock, RW_READER);
    +	error = dmu_objset_hold(name, FTAG, &os);
    +	if (error != 0)
    +		return (error);
    +	error = zap_count(dmu_objset_pool(os)->dp_meta_objset,
    +	    dmu_objset_ds(os)->ds_phys->ds_snapnames_zapobj, &numsnaps);
    +	dmu_objset_rele(os, FTAG);
    +	if (error != 0)
    +		return (error);
     
    -	err = snaplist_make(dp, B_TRUE, 0, dd->dd_phys->dd_origin_obj,
    -	    &pa.shared_snaps);
    -	if (err != 0)
    -		goto out;
    +	ddpa.ddpa_clonename = name;
    +	ddpa.err_ds = conflsnap;
     
    -	err = snaplist_make(dp, B_FALSE, 0, ds->ds_object, &pa.clone_snaps);
    -	if (err != 0)
    -		goto out;
    -
    -	snap = list_head(&pa.shared_snaps);
    -	ASSERT3U(snap->ds->ds_object, ==, dd->dd_phys->dd_origin_obj);
    -	err = snaplist_make(dp, B_FALSE, dd->dd_phys->dd_origin_obj,
    -	    snap->ds->ds_dir->dd_phys->dd_head_dataset_obj, &pa.origin_snaps);
    -	if (err != 0)
    -		goto out;
    -
    -	if (snap->ds->ds_dir->dd_phys->dd_origin_obj != 0) {
    -		err = dsl_dataset_hold_obj(dp,
    -		    snap->ds->ds_dir->dd_phys->dd_origin_obj,
    -		    FTAG, &pa.origin_origin);
    -		if (err != 0)
    -			goto out;
    -	}
    -
    -out:
    -	rw_exit(&dp->dp_config_rwlock);
    -
    -	/*
    -	 * Add in 128x the snapnames zapobj size, since we will be moving
    -	 * a bunch of snapnames to the promoted ds, and dirtying their
    -	 * bonus buffers.
    -	 */
    -	if (err == 0) {
    -		err = dsl_sync_task_do(dp, dsl_dataset_promote_check,
    -		    dsl_dataset_promote_sync, ds, &pa,
    -		    2 + 2 * doi.doi_physical_blocks_512);
    -		if (err && pa.err_ds && conflsnap)
    -			(void) strncpy(conflsnap, pa.err_ds, MAXNAMELEN);
    -	}
    -
    -	snaplist_destroy(&pa.shared_snaps, B_TRUE);
    -	snaplist_destroy(&pa.clone_snaps, B_FALSE);
    -	snaplist_destroy(&pa.origin_snaps, B_FALSE);
    -	if (pa.origin_origin)
    -		dsl_dataset_rele(pa.origin_origin, FTAG);
    -	dsl_dataset_rele(ds, FTAG);
    -	return (err);
    +	return (dsl_sync_task(name, dsl_dataset_promote_check,
    +	    dsl_dataset_promote_sync, &ddpa, 2 + numsnaps));
     }
     
    -struct cloneswaparg {
    -	dsl_dataset_t *cds; /* clone dataset */
    -	dsl_dataset_t *ohds; /* origin's head dataset */
    -	boolean_t force;
    -	int64_t unused_refres_delta; /* change in unconsumed refreservation */
    -};
    -
    -/* ARGSUSED */
    -static int
    -dsl_dataset_clone_swap_check(void *arg1, void *arg2, dmu_tx_t *tx)
    +int
    +dsl_dataset_clone_swap_check_impl(dsl_dataset_t *clone,
    +    dsl_dataset_t *origin_head, boolean_t force)
     {
    -	struct cloneswaparg *csa = arg1;
    +	int64_t unused_refres_delta;
     
     	/* they should both be heads */
    -	if (dsl_dataset_is_snapshot(csa->cds) ||
    -	    dsl_dataset_is_snapshot(csa->ohds))
    +	if (dsl_dataset_is_snapshot(clone) ||
    +	    dsl_dataset_is_snapshot(origin_head))
     		return (EINVAL);
     
     	/* the branch point should be just before them */
    -	if (csa->cds->ds_prev != csa->ohds->ds_prev)
    +	if (clone->ds_prev != origin_head->ds_prev)
     		return (EINVAL);
     
    -	/* cds should be the clone (unless they are unrelated) */
    -	if (csa->cds->ds_prev != NULL &&
    -	    csa->cds->ds_prev != csa->cds->ds_dir->dd_pool->dp_origin_snap &&
    -	    csa->ohds->ds_object !=
    -	    csa->cds->ds_prev->ds_phys->ds_next_snap_obj)
    +	/* clone should be the clone (unless they are unrelated) */
    +	if (clone->ds_prev != NULL &&
    +	    clone->ds_prev != clone->ds_dir->dd_pool->dp_origin_snap &&
    +	    origin_head->ds_object !=
    +	    clone->ds_prev->ds_phys->ds_next_snap_obj)
     		return (EINVAL);
     
     	/* the clone should be a child of the origin */
    -	if (csa->cds->ds_dir->dd_parent != csa->ohds->ds_dir)
    +	if (clone->ds_dir->dd_parent != origin_head->ds_dir)
     		return (EINVAL);
     
    -	/* ohds shouldn't be modified unless 'force' */
    -	if (!csa->force && dsl_dataset_modified_since_lastsnap(csa->ohds))
    +	/* origin_head shouldn't be modified unless 'force' */
    +	if (!force && dsl_dataset_modified_since_lastsnap(origin_head))
     		return (ETXTBSY);
     
    -	/* adjust amount of any unconsumed refreservation */
    -	csa->unused_refres_delta =
    -	    (int64_t)MIN(csa->ohds->ds_reserved,
    -	    csa->ohds->ds_phys->ds_unique_bytes) -
    -	    (int64_t)MIN(csa->ohds->ds_reserved,
    -	    csa->cds->ds_phys->ds_unique_bytes);
    +	/* origin_head should have no long holds (e.g. is not mounted) */
    +	if (dsl_dataset_long_held(origin_head))
    +		return (EBUSY);
     
    -	if (csa->unused_refres_delta > 0 &&
    -	    csa->unused_refres_delta >
    -	    dsl_dir_space_available(csa->ohds->ds_dir, NULL, 0, TRUE))
    +	/* check amount of any unconsumed refreservation */
    +	unused_refres_delta =
    +	    (int64_t)MIN(origin_head->ds_reserved,
    +	    origin_head->ds_phys->ds_unique_bytes) -
    +	    (int64_t)MIN(origin_head->ds_reserved,
    +	    clone->ds_phys->ds_unique_bytes);
    +
    +	if (unused_refres_delta > 0 &&
    +	    unused_refres_delta >
    +	    dsl_dir_space_available(origin_head->ds_dir, NULL, 0, TRUE))
     		return (ENOSPC);
     
    -	if (csa->ohds->ds_quota != 0 &&
    -	    csa->cds->ds_phys->ds_unique_bytes > csa->ohds->ds_quota)
    +	/* clone can't be over the head's refquota */
    +	if (origin_head->ds_quota != 0 &&
    +	    clone->ds_phys->ds_referenced_bytes > origin_head->ds_quota)
     		return (EDQUOT);
     
     	return (0);
     }
     
    -/* ARGSUSED */
    -static void
    -dsl_dataset_clone_swap_sync(void *arg1, void *arg2, dmu_tx_t *tx)
    +void
    +dsl_dataset_clone_swap_sync_impl(dsl_dataset_t *clone,
    +    dsl_dataset_t *origin_head, dmu_tx_t *tx)
     {
    -	struct cloneswaparg *csa = arg1;
    -	dsl_pool_t *dp = csa->cds->ds_dir->dd_pool;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	int64_t unused_refres_delta;
     
    -	ASSERT(csa->cds->ds_reserved == 0);
    -	ASSERT(csa->ohds->ds_quota == 0 ||
    -	    csa->cds->ds_phys->ds_unique_bytes <= csa->ohds->ds_quota);
    +	ASSERT(clone->ds_reserved == 0);
    +	ASSERT(origin_head->ds_quota == 0 ||
    +	    clone->ds_phys->ds_unique_bytes <= origin_head->ds_quota);
     
    -	dmu_buf_will_dirty(csa->cds->ds_dbuf, tx);
    -	dmu_buf_will_dirty(csa->ohds->ds_dbuf, tx);
    +	dmu_buf_will_dirty(clone->ds_dbuf, tx);
    +	dmu_buf_will_dirty(origin_head->ds_dbuf, tx);
     
    -	if (csa->cds->ds_objset != NULL) {
    -		dmu_objset_evict(csa->cds->ds_objset);
    -		csa->cds->ds_objset = NULL;
    +	if (clone->ds_objset != NULL) {
    +		dmu_objset_evict(clone->ds_objset);
    +		clone->ds_objset = NULL;
     	}
     
    -	if (csa->ohds->ds_objset != NULL) {
    -		dmu_objset_evict(csa->ohds->ds_objset);
    -		csa->ohds->ds_objset = NULL;
    +	if (origin_head->ds_objset != NULL) {
    +		dmu_objset_evict(origin_head->ds_objset);
    +		origin_head->ds_objset = NULL;
     	}
     
    +	unused_refres_delta =
    +	    (int64_t)MIN(origin_head->ds_reserved,
    +	    origin_head->ds_phys->ds_unique_bytes) -
    +	    (int64_t)MIN(origin_head->ds_reserved,
    +	    clone->ds_phys->ds_unique_bytes);
    +
     	/*
     	 * Reset origin's unique bytes, if it exists.
     	 */
    -	if (csa->cds->ds_prev) {
    -		dsl_dataset_t *origin = csa->cds->ds_prev;
    +	if (clone->ds_prev) {
    +		dsl_dataset_t *origin = clone->ds_prev;
     		uint64_t comp, uncomp;
     
     		dmu_buf_will_dirty(origin->ds_dbuf, tx);
    -		dsl_deadlist_space_range(&csa->cds->ds_deadlist,
    +		dsl_deadlist_space_range(&clone->ds_deadlist,
     		    origin->ds_phys->ds_prev_snap_txg, UINT64_MAX,
     		    &origin->ds_phys->ds_unique_bytes, &comp, &uncomp);
     	}
    @@ -3208,9 +2378,9 @@ dsl_dataset_clone_swap_sync(void *arg1, void *arg2, dmu_tx_t *tx)
     	/* swap blkptrs */
     	{
     		blkptr_t tmp;
    -		tmp = csa->ohds->ds_phys->ds_bp;
    -		csa->ohds->ds_phys->ds_bp = csa->cds->ds_phys->ds_bp;
    -		csa->cds->ds_phys->ds_bp = tmp;
    +		tmp = origin_head->ds_phys->ds_bp;
    +		origin_head->ds_phys->ds_bp = clone->ds_phys->ds_bp;
    +		clone->ds_phys->ds_bp = tmp;
     	}
     
     	/* set dd_*_bytes */
    @@ -3219,25 +2389,25 @@ dsl_dataset_clone_swap_sync(void *arg1, void *arg2, dmu_tx_t *tx)
     		uint64_t cdl_used, cdl_comp, cdl_uncomp;
     		uint64_t odl_used, odl_comp, odl_uncomp;
     
    -		ASSERT3U(csa->cds->ds_dir->dd_phys->
    +		ASSERT3U(clone->ds_dir->dd_phys->
     		    dd_used_breakdown[DD_USED_SNAP], ==, 0);
     
    -		dsl_deadlist_space(&csa->cds->ds_deadlist,
    +		dsl_deadlist_space(&clone->ds_deadlist,
     		    &cdl_used, &cdl_comp, &cdl_uncomp);
    -		dsl_deadlist_space(&csa->ohds->ds_deadlist,
    +		dsl_deadlist_space(&origin_head->ds_deadlist,
     		    &odl_used, &odl_comp, &odl_uncomp);
     
    -		dused = csa->cds->ds_phys->ds_referenced_bytes + cdl_used -
    -		    (csa->ohds->ds_phys->ds_referenced_bytes + odl_used);
    -		dcomp = csa->cds->ds_phys->ds_compressed_bytes + cdl_comp -
    -		    (csa->ohds->ds_phys->ds_compressed_bytes + odl_comp);
    -		duncomp = csa->cds->ds_phys->ds_uncompressed_bytes +
    +		dused = clone->ds_phys->ds_referenced_bytes + cdl_used -
    +		    (origin_head->ds_phys->ds_referenced_bytes + odl_used);
    +		dcomp = clone->ds_phys->ds_compressed_bytes + cdl_comp -
    +		    (origin_head->ds_phys->ds_compressed_bytes + odl_comp);
    +		duncomp = clone->ds_phys->ds_uncompressed_bytes +
     		    cdl_uncomp -
    -		    (csa->ohds->ds_phys->ds_uncompressed_bytes + odl_uncomp);
    +		    (origin_head->ds_phys->ds_uncompressed_bytes + odl_uncomp);
     
    -		dsl_dir_diduse_space(csa->ohds->ds_dir, DD_USED_HEAD,
    +		dsl_dir_diduse_space(origin_head->ds_dir, DD_USED_HEAD,
     		    dused, dcomp, duncomp, tx);
    -		dsl_dir_diduse_space(csa->cds->ds_dir, DD_USED_HEAD,
    +		dsl_dir_diduse_space(clone->ds_dir, DD_USED_HEAD,
     		    -dused, -dcomp, -duncomp, tx);
     
     		/*
    @@ -3246,86 +2416,46 @@ dsl_dataset_clone_swap_sync(void *arg1, void *arg2, dmu_tx_t *tx)
     		 * deadlist (since that's the only thing that's
     		 * changing that affects the snapused).
     		 */
    -		dsl_deadlist_space_range(&csa->cds->ds_deadlist,
    -		    csa->ohds->ds_dir->dd_origin_txg, UINT64_MAX,
    +		dsl_deadlist_space_range(&clone->ds_deadlist,
    +		    origin_head->ds_dir->dd_origin_txg, UINT64_MAX,
     		    &cdl_used, &cdl_comp, &cdl_uncomp);
    -		dsl_deadlist_space_range(&csa->ohds->ds_deadlist,
    -		    csa->ohds->ds_dir->dd_origin_txg, UINT64_MAX,
    +		dsl_deadlist_space_range(&origin_head->ds_deadlist,
    +		    origin_head->ds_dir->dd_origin_txg, UINT64_MAX,
     		    &odl_used, &odl_comp, &odl_uncomp);
    -		dsl_dir_transfer_space(csa->ohds->ds_dir, cdl_used - odl_used,
    +		dsl_dir_transfer_space(origin_head->ds_dir, cdl_used - odl_used,
     		    DD_USED_HEAD, DD_USED_SNAP, tx);
     	}
     
     	/* swap ds_*_bytes */
    -	SWITCH64(csa->ohds->ds_phys->ds_referenced_bytes,
    -	    csa->cds->ds_phys->ds_referenced_bytes);
    -	SWITCH64(csa->ohds->ds_phys->ds_compressed_bytes,
    -	    csa->cds->ds_phys->ds_compressed_bytes);
    -	SWITCH64(csa->ohds->ds_phys->ds_uncompressed_bytes,
    -	    csa->cds->ds_phys->ds_uncompressed_bytes);
    -	SWITCH64(csa->ohds->ds_phys->ds_unique_bytes,
    -	    csa->cds->ds_phys->ds_unique_bytes);
    +	SWITCH64(origin_head->ds_phys->ds_referenced_bytes,
    +	    clone->ds_phys->ds_referenced_bytes);
    +	SWITCH64(origin_head->ds_phys->ds_compressed_bytes,
    +	    clone->ds_phys->ds_compressed_bytes);
    +	SWITCH64(origin_head->ds_phys->ds_uncompressed_bytes,
    +	    clone->ds_phys->ds_uncompressed_bytes);
    +	SWITCH64(origin_head->ds_phys->ds_unique_bytes,
    +	    clone->ds_phys->ds_unique_bytes);
     
     	/* apply any parent delta for change in unconsumed refreservation */
    -	dsl_dir_diduse_space(csa->ohds->ds_dir, DD_USED_REFRSRV,
    -	    csa->unused_refres_delta, 0, 0, tx);
    +	dsl_dir_diduse_space(origin_head->ds_dir, DD_USED_REFRSRV,
    +	    unused_refres_delta, 0, 0, tx);
     
     	/*
     	 * Swap deadlists.
     	 */
    -	dsl_deadlist_close(&csa->cds->ds_deadlist);
    -	dsl_deadlist_close(&csa->ohds->ds_deadlist);
    -	SWITCH64(csa->ohds->ds_phys->ds_deadlist_obj,
    -	    csa->cds->ds_phys->ds_deadlist_obj);
    -	dsl_deadlist_open(&csa->cds->ds_deadlist, dp->dp_meta_objset,
    -	    csa->cds->ds_phys->ds_deadlist_obj);
    -	dsl_deadlist_open(&csa->ohds->ds_deadlist, dp->dp_meta_objset,
    -	    csa->ohds->ds_phys->ds_deadlist_obj);
    +	dsl_deadlist_close(&clone->ds_deadlist);
    +	dsl_deadlist_close(&origin_head->ds_deadlist);
    +	SWITCH64(origin_head->ds_phys->ds_deadlist_obj,
    +	    clone->ds_phys->ds_deadlist_obj);
    +	dsl_deadlist_open(&clone->ds_deadlist, dp->dp_meta_objset,
    +	    clone->ds_phys->ds_deadlist_obj);
    +	dsl_deadlist_open(&origin_head->ds_deadlist, dp->dp_meta_objset,
    +	    origin_head->ds_phys->ds_deadlist_obj);
     
    -	dsl_scan_ds_clone_swapped(csa->ohds, csa->cds, tx);
    +	dsl_scan_ds_clone_swapped(origin_head, clone, tx);
     
    -	spa_history_log_internal_ds(csa->cds, "clone swap", tx,
    -	    "parent=%s", csa->ohds->ds_dir->dd_myname);
    -}
    -
    -/*
    - * Swap 'clone' with its origin head datasets.  Used at the end of "zfs
    - * recv" into an existing fs to swizzle the file system to the new
    - * version, and by "zfs rollback".  Can also be used to swap two
    - * independent head datasets if neither has any snapshots.
    - */
    -int
    -dsl_dataset_clone_swap(dsl_dataset_t *clone, dsl_dataset_t *origin_head,
    -    boolean_t force)
    -{
    -	struct cloneswaparg csa;
    -	int error;
    -
    -	ASSERT(clone->ds_owner);
    -	ASSERT(origin_head->ds_owner);
    -retry:
    -	/*
    -	 * Need exclusive access for the swap. If we're swapping these
    -	 * datasets back after an error, we already hold the locks.
    -	 */
    -	if (!RW_WRITE_HELD(&clone->ds_rwlock))
    -		rw_enter(&clone->ds_rwlock, RW_WRITER);
    -	if (!RW_WRITE_HELD(&origin_head->ds_rwlock) &&
    -	    !rw_tryenter(&origin_head->ds_rwlock, RW_WRITER)) {
    -		rw_exit(&clone->ds_rwlock);
    -		rw_enter(&origin_head->ds_rwlock, RW_WRITER);
    -		if (!rw_tryenter(&clone->ds_rwlock, RW_WRITER)) {
    -			rw_exit(&origin_head->ds_rwlock);
    -			goto retry;
    -		}
    -	}
    -	csa.cds = clone;
    -	csa.ohds = origin_head;
    -	csa.force = force;
    -	error = dsl_sync_task_do(clone->ds_dir->dd_pool,
    -	    dsl_dataset_clone_swap_check,
    -	    dsl_dataset_clone_swap_sync, &csa, NULL, 9);
    -	return (error);
    +	spa_history_log_internal_ds(clone, "clone swap", tx,
    +	    "parent=%s", origin_head->ds_dir->dd_myname);
     }
     
     /*
    @@ -3335,21 +2465,20 @@ retry:
     int
     dsl_dsobj_to_dsname(char *pname, uint64_t obj, char *buf)
     {
    -	spa_t *spa;
     	dsl_pool_t *dp;
     	dsl_dataset_t *ds;
     	int error;
     
    -	if ((error = spa_open(pname, &spa, FTAG)) != 0)
    +	error = dsl_pool_hold(pname, FTAG, &dp);
    +	if (error != 0)
     		return (error);
    -	dp = spa_get_dsl(spa);
    -	rw_enter(&dp->dp_config_rwlock, RW_READER);
    -	if ((error = dsl_dataset_hold_obj(dp, obj, FTAG, &ds)) == 0) {
    +
    +	error = dsl_dataset_hold_obj(dp, obj, FTAG, &ds);
    +	if (error == 0) {
     		dsl_dataset_name(ds, buf);
     		dsl_dataset_rele(ds, FTAG);
     	}
    -	rw_exit(&dp->dp_config_rwlock);
    -	spa_close(spa, FTAG);
    +	dsl_pool_rele(dp, FTAG);
     
     	return (error);
     }
    @@ -3402,102 +2531,134 @@ dsl_dataset_check_quota(dsl_dataset_t *ds, boolean_t check_quota,
     	return (error);
     }
     
    +typedef struct dsl_dataset_set_qr_arg {
    +	const char *ddsqra_name;
    +	zprop_source_t ddsqra_source;
    +	uint64_t ddsqra_value;
    +} dsl_dataset_set_qr_arg_t;
    +
    +
     /* ARGSUSED */
     static int
    -dsl_dataset_set_quota_check(void *arg1, void *arg2, dmu_tx_t *tx)
    +dsl_dataset_set_refquota_check(void *arg, dmu_tx_t *tx)
     {
    -	dsl_dataset_t *ds = arg1;
    -	dsl_prop_setarg_t *psa = arg2;
    -	int err;
    +	dsl_dataset_set_qr_arg_t *ddsqra = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	dsl_dataset_t *ds;
    +	int error;
    +	uint64_t newval;
     
    -	if (spa_version(ds->ds_dir->dd_pool->dp_spa) < SPA_VERSION_REFQUOTA)
    +	if (spa_version(dp->dp_spa) < SPA_VERSION_REFQUOTA)
     		return (ENOTSUP);
     
    -	if ((err = dsl_prop_predict_sync(ds->ds_dir, psa)) != 0)
    -		return (err);
    +	error = dsl_dataset_hold(dp, ddsqra->ddsqra_name, FTAG, &ds);
    +	if (error != 0)
    +		return (error);
     
    -	if (psa->psa_effective_value == 0)
    +	if (dsl_dataset_is_snapshot(ds)) {
    +		dsl_dataset_rele(ds, FTAG);
    +		return (EINVAL);
    +	}
    +
    +	error = dsl_prop_predict(ds->ds_dir,
    +	    zfs_prop_to_name(ZFS_PROP_REFQUOTA),
    +	    ddsqra->ddsqra_source, ddsqra->ddsqra_value, &newval);
    +	if (error != 0) {
    +		dsl_dataset_rele(ds, FTAG);
    +		return (error);
    +	}
    +
    +	if (newval == 0) {
    +		dsl_dataset_rele(ds, FTAG);
     		return (0);
    +	}
     
    -	if (psa->psa_effective_value < ds->ds_phys->ds_referenced_bytes ||
    -	    psa->psa_effective_value < ds->ds_reserved)
    +	if (newval < ds->ds_phys->ds_referenced_bytes ||
    +	    newval < ds->ds_reserved) {
    +		dsl_dataset_rele(ds, FTAG);
     		return (ENOSPC);
    +	}
     
    +	dsl_dataset_rele(ds, FTAG);
     	return (0);
     }
     
    -extern void dsl_prop_set_sync(void *, void *, dmu_tx_t *);
    -
    -void
    -dsl_dataset_set_quota_sync(void *arg1, void *arg2, dmu_tx_t *tx)
    +static void
    +dsl_dataset_set_refquota_sync(void *arg, dmu_tx_t *tx)
     {
    -	dsl_dataset_t *ds = arg1;
    -	dsl_prop_setarg_t *psa = arg2;
    -	uint64_t effective_value = psa->psa_effective_value;
    +	dsl_dataset_set_qr_arg_t *ddsqra = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	dsl_dataset_t *ds;
    +	uint64_t newval;
     
    -	dsl_prop_set_sync(ds, psa, tx);
    -	DSL_PROP_CHECK_PREDICTION(ds->ds_dir, psa);
    +	VERIFY0(dsl_dataset_hold(dp, ddsqra->ddsqra_name, FTAG, &ds));
     
    -	if (ds->ds_quota != effective_value) {
    +	dsl_prop_set_sync_impl(ds,
    +	    zfs_prop_to_name(ZFS_PROP_REFQUOTA),
    +	    ddsqra->ddsqra_source, sizeof (ddsqra->ddsqra_value), 1,
    +	    &ddsqra->ddsqra_value, tx);
    +
    +	VERIFY0(dsl_prop_get_int_ds(ds,
    +	    zfs_prop_to_name(ZFS_PROP_REFQUOTA), &newval));
    +
    +	if (ds->ds_quota != newval) {
     		dmu_buf_will_dirty(ds->ds_dbuf, tx);
    -		ds->ds_quota = effective_value;
    +		ds->ds_quota = newval;
     	}
    +	dsl_dataset_rele(ds, FTAG);
     }
     
     int
    -dsl_dataset_set_quota(const char *dsname, zprop_source_t source, uint64_t quota)
    +dsl_dataset_set_refquota(const char *dsname, zprop_source_t source,
    +    uint64_t refquota)
     {
    -	dsl_dataset_t *ds;
    -	dsl_prop_setarg_t psa;
    -	int err;
    +	dsl_dataset_set_qr_arg_t ddsqra;
     
    -	dsl_prop_setarg_init_uint64(&psa, "refquota", source, "a);
    +	ddsqra.ddsqra_name = dsname;
    +	ddsqra.ddsqra_source = source;
    +	ddsqra.ddsqra_value = refquota;
     
    -	err = dsl_dataset_hold(dsname, FTAG, &ds);
    -	if (err)
    -		return (err);
    -
    -	/*
    -	 * If someone removes a file, then tries to set the quota, we
    -	 * want to make sure the file freeing takes effect.
    -	 */
    -	txg_wait_open(ds->ds_dir->dd_pool, 0);
    -
    -	err = dsl_sync_task_do(ds->ds_dir->dd_pool,
    -	    dsl_dataset_set_quota_check, dsl_dataset_set_quota_sync,
    -	    ds, &psa, 0);
    -
    -	dsl_dataset_rele(ds, FTAG);
    -	return (err);
    +	return (dsl_sync_task(dsname, dsl_dataset_set_refquota_check,
    +	    dsl_dataset_set_refquota_sync, &ddsqra, 0));
     }
     
     static int
    -dsl_dataset_set_reservation_check(void *arg1, void *arg2, dmu_tx_t *tx)
    +dsl_dataset_set_refreservation_check(void *arg, dmu_tx_t *tx)
     {
    -	dsl_dataset_t *ds = arg1;
    -	dsl_prop_setarg_t *psa = arg2;
    -	uint64_t effective_value;
    -	uint64_t unique;
    -	int err;
    +	dsl_dataset_set_qr_arg_t *ddsqra = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	dsl_dataset_t *ds;
    +	int error;
    +	uint64_t newval, unique;
     
    -	if (spa_version(ds->ds_dir->dd_pool->dp_spa) <
    -	    SPA_VERSION_REFRESERVATION)
    +	if (spa_version(dp->dp_spa) < SPA_VERSION_REFRESERVATION)
     		return (ENOTSUP);
     
    -	if (dsl_dataset_is_snapshot(ds))
    +	error = dsl_dataset_hold(dp, ddsqra->ddsqra_name, FTAG, &ds);
    +	if (error != 0)
    +		return (error);
    +
    +	if (dsl_dataset_is_snapshot(ds)) {
    +		dsl_dataset_rele(ds, FTAG);
     		return (EINVAL);
    +	}
     
    -	if ((err = dsl_prop_predict_sync(ds->ds_dir, psa)) != 0)
    -		return (err);
    -
    -	effective_value = psa->psa_effective_value;
    +	error = dsl_prop_predict(ds->ds_dir,
    +	    zfs_prop_to_name(ZFS_PROP_REFRESERVATION),
    +	    ddsqra->ddsqra_source, ddsqra->ddsqra_value, &newval);
    +	if (error != 0) {
    +		dsl_dataset_rele(ds, FTAG);
    +		return (error);
    +	}
     
     	/*
     	 * If we are doing the preliminary check in open context, the
     	 * space estimates may be inaccurate.
     	 */
    -	if (!dmu_tx_is_syncing(tx))
    +	if (!dmu_tx_is_syncing(tx)) {
    +		dsl_dataset_rele(ds, FTAG);
     		return (0);
    +	}
     
     	mutex_enter(&ds->ds_lock);
     	if (!DS_UNIQUE_IS_ACCURATE(ds))
    @@ -3505,637 +2666,75 @@ dsl_dataset_set_reservation_check(void *arg1, void *arg2, dmu_tx_t *tx)
     	unique = ds->ds_phys->ds_unique_bytes;
     	mutex_exit(&ds->ds_lock);
     
    -	if (MAX(unique, effective_value) > MAX(unique, ds->ds_reserved)) {
    -		uint64_t delta = MAX(unique, effective_value) -
    +	if (MAX(unique, newval) > MAX(unique, ds->ds_reserved)) {
    +		uint64_t delta = MAX(unique, newval) -
     		    MAX(unique, ds->ds_reserved);
     
    -		if (delta > dsl_dir_space_available(ds->ds_dir, NULL, 0, TRUE))
    -			return (ENOSPC);
    -		if (ds->ds_quota > 0 &&
    -		    effective_value > ds->ds_quota)
    +		if (delta >
    +		    dsl_dir_space_available(ds->ds_dir, NULL, 0, B_TRUE) ||
    +		    (ds->ds_quota > 0 && newval > ds->ds_quota)) {
    +			dsl_dataset_rele(ds, FTAG);
     			return (ENOSPC);
    +		}
     	}
     
    +	dsl_dataset_rele(ds, FTAG);
     	return (0);
     }
     
    -static void
    -dsl_dataset_set_reservation_sync(void *arg1, void *arg2, dmu_tx_t *tx)
    +void
    +dsl_dataset_set_refreservation_sync_impl(dsl_dataset_t *ds,
    +    zprop_source_t source, uint64_t value, dmu_tx_t *tx)
     {
    -	dsl_dataset_t *ds = arg1;
    -	dsl_prop_setarg_t *psa = arg2;
    -	uint64_t effective_value = psa->psa_effective_value;
    +	uint64_t newval;
     	uint64_t unique;
     	int64_t delta;
     
    -	dsl_prop_set_sync(ds, psa, tx);
    -	DSL_PROP_CHECK_PREDICTION(ds->ds_dir, psa);
    +	dsl_prop_set_sync_impl(ds, zfs_prop_to_name(ZFS_PROP_REFRESERVATION),
    +	    source, sizeof (value), 1, &value, tx);
    +
    +	VERIFY0(dsl_prop_get_int_ds(ds,
    +	    zfs_prop_to_name(ZFS_PROP_REFRESERVATION), &newval));
     
     	dmu_buf_will_dirty(ds->ds_dbuf, tx);
    -
     	mutex_enter(&ds->ds_dir->dd_lock);
     	mutex_enter(&ds->ds_lock);
     	ASSERT(DS_UNIQUE_IS_ACCURATE(ds));
     	unique = ds->ds_phys->ds_unique_bytes;
    -	delta = MAX(0, (int64_t)(effective_value - unique)) -
    +	delta = MAX(0, (int64_t)(newval - unique)) -
     	    MAX(0, (int64_t)(ds->ds_reserved - unique));
    -	ds->ds_reserved = effective_value;
    +	ds->ds_reserved = newval;
     	mutex_exit(&ds->ds_lock);
     
     	dsl_dir_diduse_space(ds->ds_dir, DD_USED_REFRSRV, delta, 0, 0, tx);
     	mutex_exit(&ds->ds_dir->dd_lock);
     }
     
    -int
    -dsl_dataset_set_reservation(const char *dsname, zprop_source_t source,
    -    uint64_t reservation)
    -{
    -	dsl_dataset_t *ds;
    -	dsl_prop_setarg_t psa;
    -	int err;
    -
    -	dsl_prop_setarg_init_uint64(&psa, "refreservation", source,
    -	    &reservation);
    -
    -	err = dsl_dataset_hold(dsname, FTAG, &ds);
    -	if (err)
    -		return (err);
    -
    -	err = dsl_sync_task_do(ds->ds_dir->dd_pool,
    -	    dsl_dataset_set_reservation_check,
    -	    dsl_dataset_set_reservation_sync, ds, &psa, 0);
    -
    -	dsl_dataset_rele(ds, FTAG);
    -	return (err);
    -}
    -
    -typedef struct zfs_hold_cleanup_arg {
    -	dsl_pool_t *dp;
    -	uint64_t dsobj;
    -	char htag[MAXNAMELEN];
    -} zfs_hold_cleanup_arg_t;
    -
     static void
    -dsl_dataset_user_release_onexit(void *arg)
    +dsl_dataset_set_refreservation_sync(void *arg, dmu_tx_t *tx)
     {
    -	zfs_hold_cleanup_arg_t *ca = arg;
    -
    -	(void) dsl_dataset_user_release_tmp(ca->dp, ca->dsobj, ca->htag,
    -	    B_TRUE);
    -	kmem_free(ca, sizeof (zfs_hold_cleanup_arg_t));
    -}
    -
    -void
    -dsl_register_onexit_hold_cleanup(dsl_dataset_t *ds, const char *htag,
    -    minor_t minor)
    -{
    -	zfs_hold_cleanup_arg_t *ca;
    -
    -	ca = kmem_alloc(sizeof (zfs_hold_cleanup_arg_t), KM_SLEEP);
    -	ca->dp = ds->ds_dir->dd_pool;
    -	ca->dsobj = ds->ds_object;
    -	(void) strlcpy(ca->htag, htag, sizeof (ca->htag));
    -	VERIFY3U(0, ==, zfs_onexit_add_cb(minor,
    -	    dsl_dataset_user_release_onexit, ca, NULL));
    -}
    -
    -/*
    - * If you add new checks here, you may need to add
    - * additional checks to the "temporary" case in
    - * snapshot_check() in dmu_objset.c.
    - */
    -static int
    -dsl_dataset_user_hold_check(void *arg1, void *arg2, dmu_tx_t *tx)
    -{
    -	dsl_dataset_t *ds = arg1;
    -	struct dsl_ds_holdarg *ha = arg2;
    -	const char *htag = ha->htag;
    -	objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
    -	int error = 0;
    -
    -	if (spa_version(ds->ds_dir->dd_pool->dp_spa) < SPA_VERSION_USERREFS)
    -		return (ENOTSUP);
    -
    -	if (!dsl_dataset_is_snapshot(ds))
    -		return (EINVAL);
    -
    -	/* tags must be unique */
    -	mutex_enter(&ds->ds_lock);
    -	if (ds->ds_phys->ds_userrefs_obj) {
    -		error = zap_lookup(mos, ds->ds_phys->ds_userrefs_obj, htag,
    -		    8, 1, tx);
    -		if (error == 0)
    -			error = EEXIST;
    -		else if (error == ENOENT)
    -			error = 0;
    -	}
    -	mutex_exit(&ds->ds_lock);
    -
    -	if (error == 0 && ha->temphold &&
    -	    strlen(htag) + MAX_TAG_PREFIX_LEN >= MAXNAMELEN)
    -		error = E2BIG;
    -
    -	return (error);
    -}
    -
    -void
    -dsl_dataset_user_hold_sync(void *arg1, void *arg2, dmu_tx_t *tx)
    -{
    -	dsl_dataset_t *ds = arg1;
    -	struct dsl_ds_holdarg *ha = arg2;
    -	const char *htag = ha->htag;
    -	dsl_pool_t *dp = ds->ds_dir->dd_pool;
    -	objset_t *mos = dp->dp_meta_objset;
    -	uint64_t now = gethrestime_sec();
    -	uint64_t zapobj;
    -
    -	mutex_enter(&ds->ds_lock);
    -	if (ds->ds_phys->ds_userrefs_obj == 0) {
    -		/*
    -		 * This is the first user hold for this dataset.  Create
    -		 * the userrefs zap object.
    -		 */
    -		dmu_buf_will_dirty(ds->ds_dbuf, tx);
    -		zapobj = ds->ds_phys->ds_userrefs_obj =
    -		    zap_create(mos, DMU_OT_USERREFS, DMU_OT_NONE, 0, tx);
    -	} else {
    -		zapobj = ds->ds_phys->ds_userrefs_obj;
    -	}
    -	ds->ds_userrefs++;
    -	mutex_exit(&ds->ds_lock);
    -
    -	VERIFY(0 == zap_add(mos, zapobj, htag, 8, 1, &now, tx));
    -
    -	if (ha->temphold) {
    -		VERIFY(0 == dsl_pool_user_hold(dp, ds->ds_object,
    -		    htag, &now, tx));
    -	}
    -
    -	spa_history_log_internal_ds(ds, "hold", tx,
    -	    "tag = %s temp = %d holds now = %llu",
    -	    htag, (int)ha->temphold, ds->ds_userrefs);
    -}
    -
    -static int
    -dsl_dataset_user_hold_one(const char *dsname, void *arg)
    -{
    -	struct dsl_ds_holdarg *ha = arg;
    +	dsl_dataset_set_qr_arg_t *ddsqra = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
     	dsl_dataset_t *ds;
    -	int error;
    -	char *name;
     
    -	/* alloc a buffer to hold dsname@snapname plus terminating NULL */
    -	name = kmem_asprintf("%s@%s", dsname, ha->snapname);
    -	error = dsl_dataset_hold(name, ha->dstg, &ds);
    -	strfree(name);
    -	if (error == 0) {
    -		ha->gotone = B_TRUE;
    -		dsl_sync_task_create(ha->dstg, dsl_dataset_user_hold_check,
    -		    dsl_dataset_user_hold_sync, ds, ha, 0);
    -	} else if (error == ENOENT && ha->recursive) {
    -		error = 0;
    -	} else {
    -		(void) strlcpy(ha->failed, dsname, sizeof (ha->failed));
    -	}
    -	return (error);
    -}
    -
    -int
    -dsl_dataset_user_hold_for_send(dsl_dataset_t *ds, char *htag,
    -    boolean_t temphold)
    -{
    -	struct dsl_ds_holdarg *ha;
    -	int error;
    -
    -	ha = kmem_zalloc(sizeof (struct dsl_ds_holdarg), KM_SLEEP);
    -	ha->htag = htag;
    -	ha->temphold = temphold;
    -	error = dsl_sync_task_do(ds->ds_dir->dd_pool,
    -	    dsl_dataset_user_hold_check, dsl_dataset_user_hold_sync,
    -	    ds, ha, 0);
    -	kmem_free(ha, sizeof (struct dsl_ds_holdarg));
    -
    -	return (error);
    -}
    -
    -int
    -dsl_dataset_user_hold(char *dsname, char *snapname, char *htag,
    -    boolean_t recursive, boolean_t temphold, int cleanup_fd)
    -{
    -	struct dsl_ds_holdarg *ha;
    -	dsl_sync_task_t *dst;
    -	spa_t *spa;
    -	int error;
    -	minor_t minor = 0;
    -
    -	if (cleanup_fd != -1) {
    -		/* Currently we only support cleanup-on-exit of tempholds. */
    -		if (!temphold)
    -			return (EINVAL);
    -		error = zfs_onexit_fd_hold(cleanup_fd, &minor);
    -		if (error)
    -			return (error);
    -	}
    -
    -	ha = kmem_zalloc(sizeof (struct dsl_ds_holdarg), KM_SLEEP);
    -
    -	(void) strlcpy(ha->failed, dsname, sizeof (ha->failed));
    -
    -	error = spa_open(dsname, &spa, FTAG);
    -	if (error) {
    -		kmem_free(ha, sizeof (struct dsl_ds_holdarg));
    -		if (cleanup_fd != -1)
    -			zfs_onexit_fd_rele(cleanup_fd);
    -		return (error);
    -	}
    -
    -	ha->dstg = dsl_sync_task_group_create(spa_get_dsl(spa));
    -	ha->htag = htag;
    -	ha->snapname = snapname;
    -	ha->recursive = recursive;
    -	ha->temphold = temphold;
    -
    -	if (recursive) {
    -		error = dmu_objset_find(dsname, dsl_dataset_user_hold_one,
    -		    ha, DS_FIND_CHILDREN);
    -	} else {
    -		error = dsl_dataset_user_hold_one(dsname, ha);
    -	}
    -	if (error == 0)
    -		error = dsl_sync_task_group_wait(ha->dstg);
    -
    -	for (dst = list_head(&ha->dstg->dstg_tasks); dst;
    -	    dst = list_next(&ha->dstg->dstg_tasks, dst)) {
    -		dsl_dataset_t *ds = dst->dst_arg1;
    -
    -		if (dst->dst_err) {
    -			dsl_dataset_name(ds, ha->failed);
    -			*strchr(ha->failed, '@') = '\0';
    -		} else if (error == 0 && minor != 0 && temphold) {
    -			/*
    -			 * If this hold is to be released upon process exit,
    -			 * register that action now.
    -			 */
    -			dsl_register_onexit_hold_cleanup(ds, htag, minor);
    -		}
    -		dsl_dataset_rele(ds, ha->dstg);
    -	}
    -
    -	if (error == 0 && recursive && !ha->gotone)
    -		error = ENOENT;
    -
    -	if (error)
    -		(void) strlcpy(dsname, ha->failed, sizeof (ha->failed));
    -
    -	dsl_sync_task_group_destroy(ha->dstg);
    -
    -	kmem_free(ha, sizeof (struct dsl_ds_holdarg));
    -	spa_close(spa, FTAG);
    -	if (cleanup_fd != -1)
    -		zfs_onexit_fd_rele(cleanup_fd);
    -	return (error);
    -}
    -
    -struct dsl_ds_releasearg {
    -	dsl_dataset_t *ds;
    -	const char *htag;
    -	boolean_t own;		/* do we own or just hold ds? */
    -};
    -
    -static int
    -dsl_dataset_release_might_destroy(dsl_dataset_t *ds, const char *htag,
    -    boolean_t *might_destroy)
    -{
    -	objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
    -	uint64_t zapobj;
    -	uint64_t tmp;
    -	int error;
    -
    -	*might_destroy = B_FALSE;
    -
    -	mutex_enter(&ds->ds_lock);
    -	zapobj = ds->ds_phys->ds_userrefs_obj;
    -	if (zapobj == 0) {
    -		/* The tag can't possibly exist */
    -		mutex_exit(&ds->ds_lock);
    -		return (ESRCH);
    -	}
    -
    -	/* Make sure the tag exists */
    -	error = zap_lookup(mos, zapobj, htag, 8, 1, &tmp);
    -	if (error) {
    -		mutex_exit(&ds->ds_lock);
    -		if (error == ENOENT)
    -			error = ESRCH;
    -		return (error);
    -	}
    -
    -	if (ds->ds_userrefs == 1 && ds->ds_phys->ds_num_children == 1 &&
    -	    DS_IS_DEFER_DESTROY(ds))
    -		*might_destroy = B_TRUE;
    -
    -	mutex_exit(&ds->ds_lock);
    -	return (0);
    -}
    -
    -static int
    -dsl_dataset_user_release_check(void *arg1, void *tag, dmu_tx_t *tx)
    -{
    -	struct dsl_ds_releasearg *ra = arg1;
    -	dsl_dataset_t *ds = ra->ds;
    -	boolean_t might_destroy;
    -	int error;
    -
    -	if (spa_version(ds->ds_dir->dd_pool->dp_spa) < SPA_VERSION_USERREFS)
    -		return (ENOTSUP);
    -
    -	error = dsl_dataset_release_might_destroy(ds, ra->htag, &might_destroy);
    -	if (error)
    -		return (error);
    -
    -	if (might_destroy) {
    -		struct dsl_ds_destroyarg dsda = {0};
    -
    -		if (dmu_tx_is_syncing(tx)) {
    -			/*
    -			 * If we're not prepared to remove the snapshot,
    -			 * we can't allow the release to happen right now.
    -			 */
    -			if (!ra->own)
    -				return (EBUSY);
    -		}
    -		dsda.ds = ds;
    -		dsda.releasing = B_TRUE;
    -		return (dsl_dataset_destroy_check(&dsda, tag, tx));
    -	}
    -
    -	return (0);
    -}
    -
    -static void
    -dsl_dataset_user_release_sync(void *arg1, void *tag, dmu_tx_t *tx)
    -{
    -	struct dsl_ds_releasearg *ra = arg1;
    -	dsl_dataset_t *ds = ra->ds;
    -	dsl_pool_t *dp = ds->ds_dir->dd_pool;
    -	objset_t *mos = dp->dp_meta_objset;
    -	uint64_t zapobj;
    -	uint64_t refs;
    -	int error;
    -
    -	mutex_enter(&ds->ds_lock);
    -	ds->ds_userrefs--;
    -	refs = ds->ds_userrefs;
    -	mutex_exit(&ds->ds_lock);
    -	error = dsl_pool_user_release(dp, ds->ds_object, ra->htag, tx);
    -	VERIFY(error == 0 || error == ENOENT);
    -	zapobj = ds->ds_phys->ds_userrefs_obj;
    -	VERIFY(0 == zap_remove(mos, zapobj, ra->htag, tx));
    -
    -	spa_history_log_internal_ds(ds, "release", tx,
    -	    "tag = %s refs now = %lld", ra->htag, (longlong_t)refs);
    -
    -	if (ds->ds_userrefs == 0 && ds->ds_phys->ds_num_children == 1 &&
    -	    DS_IS_DEFER_DESTROY(ds)) {
    -		struct dsl_ds_destroyarg dsda = {0};
    -
    -		ASSERT(ra->own);
    -		dsda.ds = ds;
    -		dsda.releasing = B_TRUE;
    -		/* We already did the destroy_check */
    -		dsl_dataset_destroy_sync(&dsda, tag, tx);
    -	}
    -}
    -
    -static int
    -dsl_dataset_user_release_one(const char *dsname, void *arg)
    -{
    -	struct dsl_ds_holdarg *ha = arg;
    -	struct dsl_ds_releasearg *ra;
    -	dsl_dataset_t *ds;
    -	int error;
    -	void *dtag = ha->dstg;
    -	char *name;
    -	boolean_t own = B_FALSE;
    -	boolean_t might_destroy;
    -
    -	/* alloc a buffer to hold dsname@snapname, plus the terminating NULL */
    -	name = kmem_asprintf("%s@%s", dsname, ha->snapname);
    -	error = dsl_dataset_hold(name, dtag, &ds);
    -	strfree(name);
    -	if (error == ENOENT && ha->recursive)
    -		return (0);
    -	(void) strlcpy(ha->failed, dsname, sizeof (ha->failed));
    -	if (error)
    -		return (error);
    -
    -	ha->gotone = B_TRUE;
    -
    -	ASSERT(dsl_dataset_is_snapshot(ds));
    -
    -	error = dsl_dataset_release_might_destroy(ds, ha->htag, &might_destroy);
    -	if (error) {
    -		dsl_dataset_rele(ds, dtag);
    -		return (error);
    -	}
    -
    -	if (might_destroy) {
    -#ifdef _KERNEL
    -		name = kmem_asprintf("%s@%s", dsname, ha->snapname);
    -		error = zfs_unmount_snap(name, NULL);
    -		strfree(name);
    -		if (error) {
    -			dsl_dataset_rele(ds, dtag);
    -			return (error);
    -		}
    -#endif
    -		if (!dsl_dataset_tryown(ds, B_TRUE, dtag)) {
    -			dsl_dataset_rele(ds, dtag);
    -			return (EBUSY);
    -		} else {
    -			own = B_TRUE;
    -			dsl_dataset_make_exclusive(ds, dtag);
    -		}
    -	}
    -
    -	ra = kmem_alloc(sizeof (struct dsl_ds_releasearg), KM_SLEEP);
    -	ra->ds = ds;
    -	ra->htag = ha->htag;
    -	ra->own = own;
    -	dsl_sync_task_create(ha->dstg, dsl_dataset_user_release_check,
    -	    dsl_dataset_user_release_sync, ra, dtag, 0);
    -
    -	return (0);
    -}
    -
    -int
    -dsl_dataset_user_release(char *dsname, char *snapname, char *htag,
    -    boolean_t recursive)
    -{
    -	struct dsl_ds_holdarg *ha;
    -	dsl_sync_task_t *dst;
    -	spa_t *spa;
    -	int error;
    -
    -top:
    -	ha = kmem_zalloc(sizeof (struct dsl_ds_holdarg), KM_SLEEP);
    -
    -	(void) strlcpy(ha->failed, dsname, sizeof (ha->failed));
    -
    -	error = spa_open(dsname, &spa, FTAG);
    -	if (error) {
    -		kmem_free(ha, sizeof (struct dsl_ds_holdarg));
    -		return (error);
    -	}
    -
    -	ha->dstg = dsl_sync_task_group_create(spa_get_dsl(spa));
    -	ha->htag = htag;
    -	ha->snapname = snapname;
    -	ha->recursive = recursive;
    -	if (recursive) {
    -		error = dmu_objset_find(dsname, dsl_dataset_user_release_one,
    -		    ha, DS_FIND_CHILDREN);
    -	} else {
    -		error = dsl_dataset_user_release_one(dsname, ha);
    -	}
    -	if (error == 0)
    -		error = dsl_sync_task_group_wait(ha->dstg);
    -
    -	for (dst = list_head(&ha->dstg->dstg_tasks); dst;
    -	    dst = list_next(&ha->dstg->dstg_tasks, dst)) {
    -		struct dsl_ds_releasearg *ra = dst->dst_arg1;
    -		dsl_dataset_t *ds = ra->ds;
    -
    -		if (dst->dst_err)
    -			dsl_dataset_name(ds, ha->failed);
    -
    -		if (ra->own)
    -			dsl_dataset_disown(ds, ha->dstg);
    -		else
    -			dsl_dataset_rele(ds, ha->dstg);
    -
    -		kmem_free(ra, sizeof (struct dsl_ds_releasearg));
    -	}
    -
    -	if (error == 0 && recursive && !ha->gotone)
    -		error = ENOENT;
    -
    -	if (error && error != EBUSY)
    -		(void) strlcpy(dsname, ha->failed, sizeof (ha->failed));
    -
    -	dsl_sync_task_group_destroy(ha->dstg);
    -	kmem_free(ha, sizeof (struct dsl_ds_holdarg));
    -	spa_close(spa, FTAG);
    -
    -	/*
    -	 * We can get EBUSY if we were racing with deferred destroy and
    -	 * dsl_dataset_user_release_check() hadn't done the necessary
    -	 * open context setup.  We can also get EBUSY if we're racing
    -	 * with destroy and that thread is the ds_owner.  Either way
    -	 * the busy condition should be transient, and we should retry
    -	 * the release operation.
    -	 */
    -	if (error == EBUSY)
    -		goto top;
    -
    -	return (error);
    -}
    -
    -/*
    - * Called at spa_load time (with retry == B_FALSE) to release a stale
    - * temporary user hold. Also called by the onexit code (with retry == B_TRUE).
    - */
    -int
    -dsl_dataset_user_release_tmp(dsl_pool_t *dp, uint64_t dsobj, char *htag,
    -    boolean_t retry)
    -{
    -	dsl_dataset_t *ds;
    -	char *snap;
    -	char *name;
    -	int namelen;
    -	int error;
    -
    -	do {
    -		rw_enter(&dp->dp_config_rwlock, RW_READER);
    -		error = dsl_dataset_hold_obj(dp, dsobj, FTAG, &ds);
    -		rw_exit(&dp->dp_config_rwlock);
    -		if (error)
    -			return (error);
    -		namelen = dsl_dataset_namelen(ds)+1;
    -		name = kmem_alloc(namelen, KM_SLEEP);
    -		dsl_dataset_name(ds, name);
    -		dsl_dataset_rele(ds, FTAG);
    -
    -		snap = strchr(name, '@');
    -		*snap = '\0';
    -		++snap;
    -		error = dsl_dataset_user_release(name, snap, htag, B_FALSE);
    -		kmem_free(name, namelen);
    -
    -		/*
    -		 * The object can't have been destroyed because we have a hold,
    -		 * but it might have been renamed, resulting in ENOENT.  Retry
    -		 * if we've been requested to do so.
    -		 *
    -		 * It would be nice if we could use the dsobj all the way
    -		 * through and avoid ENOENT entirely.  But we might need to
    -		 * unmount the snapshot, and there's currently no way to lookup
    -		 * a vfsp using a ZFS object id.
    -		 */
    -	} while ((error == ENOENT) && retry);
    -
    -	return (error);
    -}
    -
    -int
    -dsl_dataset_get_holds(const char *dsname, nvlist_t **nvp)
    -{
    -	dsl_dataset_t *ds;
    -	int err;
    -
    -	err = dsl_dataset_hold(dsname, FTAG, &ds);
    -	if (err)
    -		return (err);
    -
    -	VERIFY(0 == nvlist_alloc(nvp, NV_UNIQUE_NAME, KM_SLEEP));
    -	if (ds->ds_phys->ds_userrefs_obj != 0) {
    -		zap_attribute_t *za;
    -		zap_cursor_t zc;
    -
    -		za = kmem_alloc(sizeof (zap_attribute_t), KM_SLEEP);
    -		for (zap_cursor_init(&zc, ds->ds_dir->dd_pool->dp_meta_objset,
    -		    ds->ds_phys->ds_userrefs_obj);
    -		    zap_cursor_retrieve(&zc, za) == 0;
    -		    zap_cursor_advance(&zc)) {
    -			VERIFY(0 == nvlist_add_uint64(*nvp, za->za_name,
    -			    za->za_first_integer));
    -		}
    -		zap_cursor_fini(&zc);
    -		kmem_free(za, sizeof (zap_attribute_t));
    -	}
    +	VERIFY0(dsl_dataset_hold(dp, ddsqra->ddsqra_name, FTAG, &ds));
    +	dsl_dataset_set_refreservation_sync_impl(ds,
    +	    ddsqra->ddsqra_source, ddsqra->ddsqra_value, tx);
     	dsl_dataset_rele(ds, FTAG);
    -	return (0);
     }
     
    -/*
    - * Note, this function is used as the callback for dmu_objset_find().  We
    - * always return 0 so that we will continue to find and process
    - * inconsistent datasets, even if we encounter an error trying to
    - * process one of them.
    - */
    -/* ARGSUSED */
     int
    -dsl_destroy_inconsistent(const char *dsname, void *arg)
    +dsl_dataset_set_refreservation(const char *dsname, zprop_source_t source,
    +    uint64_t refreservation)
     {
    -	dsl_dataset_t *ds;
    +	dsl_dataset_set_qr_arg_t ddsqra;
     
    -	if (dsl_dataset_own(dsname, B_TRUE, FTAG, &ds) == 0) {
    -		if (DS_IS_INCONSISTENT(ds))
    -			(void) dsl_dataset_destroy(ds, FTAG, B_FALSE);
    -		else
    -			dsl_dataset_disown(ds, FTAG);
    -	}
    -	return (0);
    +	ddsqra.ddsqra_name = dsname;
    +	ddsqra.ddsqra_source = source;
    +	ddsqra.ddsqra_value = refreservation;
    +
    +	return (dsl_sync_task(dsname, dsl_dataset_set_refreservation_check,
    +	    dsl_dataset_set_refreservation_sync, &ddsqra, 0));
     }
     
     /*
    @@ -4163,6 +2762,8 @@ dsl_dataset_space_written(dsl_dataset_t *oldsnap, dsl_dataset_t *new,
     	uint64_t snapobj;
     	dsl_pool_t *dp = new->ds_dir->dd_pool;
     
    +	ASSERT(dsl_pool_config_held(dp));
    +
     	*usedp = 0;
     	*usedp += new->ds_phys->ds_referenced_bytes;
     	*usedp -= oldsnap->ds_phys->ds_referenced_bytes;
    @@ -4175,7 +2776,6 @@ dsl_dataset_space_written(dsl_dataset_t *oldsnap, dsl_dataset_t *new,
     	*uncompp += new->ds_phys->ds_uncompressed_bytes;
     	*uncompp -= oldsnap->ds_phys->ds_uncompressed_bytes;
     
    -	rw_enter(&dp->dp_config_rwlock, RW_READER);
     	snapobj = new->ds_object;
     	while (snapobj != oldsnap->ds_object) {
     		dsl_dataset_t *snap;
    @@ -4224,7 +2824,6 @@ dsl_dataset_space_written(dsl_dataset_t *oldsnap, dsl_dataset_t *new,
     		}
     
     	}
    -	rw_exit(&dp->dp_config_rwlock);
     	return (err);
     }
     
    @@ -4266,7 +2865,6 @@ dsl_dataset_space_wouldfree(dsl_dataset_t *firstsnap,
     
     	*usedp = *compp = *uncompp = 0;
     
    -	rw_enter(&dp->dp_config_rwlock, RW_READER);
     	snapobj = lastsnap->ds_phys->ds_next_snap_obj;
     	while (snapobj != firstsnap->ds_object) {
     		dsl_dataset_t *ds;
    @@ -4287,6 +2885,42 @@ dsl_dataset_space_wouldfree(dsl_dataset_t *firstsnap,
     		ASSERT3U(snapobj, !=, 0);
     		dsl_dataset_rele(ds, FTAG);
     	}
    -	rw_exit(&dp->dp_config_rwlock);
     	return (err);
     }
    +
    +/*
    + * Return TRUE if 'earlier' is an earlier snapshot in 'later's timeline.
    + * For example, they could both be snapshots of the same filesystem, and
    + * 'earlier' is before 'later'.  Or 'earlier' could be the origin of
    + * 'later's filesystem.  Or 'earlier' could be an older snapshot in the origin's
    + * filesystem.  Or 'earlier' could be the origin's origin.
    + */
    +boolean_t
    +dsl_dataset_is_before(dsl_dataset_t *later, dsl_dataset_t *earlier)
    +{
    +	dsl_pool_t *dp = later->ds_dir->dd_pool;
    +	int error;
    +	boolean_t ret;
    +
    +	ASSERT(dsl_pool_config_held(dp));
    +
    +	if (earlier->ds_phys->ds_creation_txg >=
    +	    later->ds_phys->ds_creation_txg)
    +		return (B_FALSE);
    +
    +	if (later->ds_dir == earlier->ds_dir)
    +		return (B_TRUE);
    +	if (!dsl_dir_is_clone(later->ds_dir))
    +		return (B_FALSE);
    +
    +	if (later->ds_dir->dd_phys->dd_origin_obj == earlier->ds_object)
    +		return (B_TRUE);
    +	dsl_dataset_t *origin;
    +	error = dsl_dataset_hold_obj(dp,
    +	    later->ds_dir->dd_phys->dd_origin_obj, FTAG, &origin);
    +	if (error != 0)
    +		return (B_FALSE);
    +	ret = dsl_dataset_is_before(origin, earlier);
    +	dsl_dataset_rele(origin, FTAG);
    +	return (ret);
    +}
    diff --git a/uts/common/fs/zfs/dsl_deleg.c b/uts/common/fs/zfs/dsl_deleg.c
    index ba620bd6fbe..f09cb2f2ac2 100644
    --- a/uts/common/fs/zfs/dsl_deleg.c
    +++ b/uts/common/fs/zfs/dsl_deleg.c
    @@ -147,28 +147,37 @@ dsl_deleg_can_unallow(char *ddname, nvlist_t *nvp, cred_t *cr)
     	return (0);
     }
     
    -static void
    -dsl_deleg_set_sync(void *arg1, void *arg2, dmu_tx_t *tx)
    -{
    -	dsl_dir_t *dd = arg1;
    -	nvlist_t *nvp = arg2;
    -	objset_t *mos = dd->dd_pool->dp_meta_objset;
    -	nvpair_t *whopair = NULL;
    -	uint64_t zapobj = dd->dd_phys->dd_deleg_zapobj;
    +typedef struct dsl_deleg_arg {
    +	const char *dda_name;
    +	nvlist_t *dda_nvlist;
    +} dsl_deleg_arg_t;
     
    +static void
    +dsl_deleg_set_sync(void *arg, dmu_tx_t *tx)
    +{
    +	dsl_deleg_arg_t *dda = arg;
    +	dsl_dir_t *dd;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	objset_t *mos = dp->dp_meta_objset;
    +	nvpair_t *whopair = NULL;
    +	uint64_t zapobj;
    +
    +	VERIFY0(dsl_dir_hold(dp, dda->dda_name, FTAG, &dd, NULL));
    +
    +	zapobj = dd->dd_phys->dd_deleg_zapobj;
     	if (zapobj == 0) {
     		dmu_buf_will_dirty(dd->dd_dbuf, tx);
     		zapobj = dd->dd_phys->dd_deleg_zapobj = zap_create(mos,
     		    DMU_OT_DSL_PERMS, DMU_OT_NONE, 0, tx);
     	}
     
    -	while (whopair = nvlist_next_nvpair(nvp, whopair)) {
    +	while (whopair = nvlist_next_nvpair(dda->dda_nvlist, whopair)) {
     		const char *whokey = nvpair_name(whopair);
     		nvlist_t *perms;
     		nvpair_t *permpair = NULL;
     		uint64_t jumpobj;
     
    -		VERIFY(nvpair_value_nvlist(whopair, &perms) == 0);
    +		perms = fnvpair_value_nvlist(whopair);
     
     		if (zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj) != 0) {
     			jumpobj = zap_create_link(mos, DMU_OT_DSL_PERMS,
    @@ -185,21 +194,27 @@ dsl_deleg_set_sync(void *arg1, void *arg2, dmu_tx_t *tx)
     			    "%s %s", whokey, perm);
     		}
     	}
    +	dsl_dir_rele(dd, FTAG);
     }
     
     static void
    -dsl_deleg_unset_sync(void *arg1, void *arg2, dmu_tx_t *tx)
    +dsl_deleg_unset_sync(void *arg, dmu_tx_t *tx)
     {
    -	dsl_dir_t *dd = arg1;
    -	nvlist_t *nvp = arg2;
    -	objset_t *mos = dd->dd_pool->dp_meta_objset;
    +	dsl_deleg_arg_t *dda = arg;
    +	dsl_dir_t *dd;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	objset_t *mos = dp->dp_meta_objset;
     	nvpair_t *whopair = NULL;
    -	uint64_t zapobj = dd->dd_phys->dd_deleg_zapobj;
    +	uint64_t zapobj;
     
    -	if (zapobj == 0)
    +	VERIFY0(dsl_dir_hold(dp, dda->dda_name, FTAG, &dd, NULL));
    +	zapobj = dd->dd_phys->dd_deleg_zapobj;
    +	if (zapobj == 0) {
    +		dsl_dir_rele(dd, FTAG);
     		return;
    +	}
     
    -	while (whopair = nvlist_next_nvpair(nvp, whopair)) {
    +	while (whopair = nvlist_next_nvpair(dda->dda_nvlist, whopair)) {
     		const char *whokey = nvpair_name(whopair);
     		nvlist_t *perms;
     		nvpair_t *permpair = NULL;
    @@ -234,35 +249,40 @@ dsl_deleg_unset_sync(void *arg1, void *arg2, dmu_tx_t *tx)
     			    "%s %s", whokey, perm);
     		}
     	}
    +	dsl_dir_rele(dd, FTAG);
    +}
    +
    +static int
    +dsl_deleg_check(void *arg, dmu_tx_t *tx)
    +{
    +	dsl_deleg_arg_t *dda = arg;
    +	dsl_dir_t *dd;
    +	int error;
    +
    +	if (spa_version(dmu_tx_pool(tx)->dp_spa) <
    +	    SPA_VERSION_DELEGATED_PERMS) {
    +		return (ENOTSUP);
    +	}
    +
    +	error = dsl_dir_hold(dmu_tx_pool(tx), dda->dda_name, FTAG, &dd, NULL);
    +	if (error == 0)
    +		dsl_dir_rele(dd, FTAG);
    +	return (error);
     }
     
     int
     dsl_deleg_set(const char *ddname, nvlist_t *nvp, boolean_t unset)
     {
    -	dsl_dir_t *dd;
    -	int error;
    -	nvpair_t *whopair = NULL;
    -	int blocks_modified = 0;
    +	dsl_deleg_arg_t dda;
     
    -	error = dsl_dir_open(ddname, FTAG, &dd, NULL);
    -	if (error)
    -		return (error);
    +	/* nvp must already have been verified to be valid */
     
    -	if (spa_version(dmu_objset_spa(dd->dd_pool->dp_meta_objset)) <
    -	    SPA_VERSION_DELEGATED_PERMS) {
    -		dsl_dir_close(dd, FTAG);
    -		return (ENOTSUP);
    -	}
    +	dda.dda_name = ddname;
    +	dda.dda_nvlist = nvp;
     
    -	while (whopair = nvlist_next_nvpair(nvp, whopair))
    -		blocks_modified++;
    -
    -	error = dsl_sync_task_do(dd->dd_pool, NULL,
    +	return (dsl_sync_task(ddname, dsl_deleg_check,
     	    unset ? dsl_deleg_unset_sync : dsl_deleg_set_sync,
    -	    dd, nvp, blocks_modified);
    -	dsl_dir_close(dd, FTAG);
    -
    -	return (error);
    +	    &dda, fnvlist_num_pairs(nvp)));
     }
     
     /*
    @@ -290,16 +310,21 @@ dsl_deleg_get(const char *ddname, nvlist_t **nvp)
     	int error;
     	objset_t *mos;
     
    -	error = dsl_dir_open(ddname, FTAG, &startdd, NULL);
    -	if (error)
    +	error = dsl_pool_hold(ddname, FTAG, &dp);
    +	if (error != 0)
     		return (error);
     
    +	error = dsl_dir_hold(dp, ddname, FTAG, &startdd, NULL);
    +	if (error != 0) {
    +		dsl_pool_rele(dp, FTAG);
    +		return (error);
    +	}
    +
     	dp = startdd->dd_pool;
     	mos = dp->dp_meta_objset;
     
     	VERIFY(nvlist_alloc(nvp, NV_UNIQUE_NAME, KM_SLEEP) == 0);
     
    -	rw_enter(&dp->dp_config_rwlock, RW_READER);
     	for (dd = startdd; dd != NULL; dd = dd->dd_parent) {
     		zap_cursor_t basezc;
     		zap_attribute_t baseza;
    @@ -307,15 +332,12 @@ dsl_deleg_get(const char *ddname, nvlist_t **nvp)
     		uint64_t n;
     		char source[MAXNAMELEN];
     
    -		if (dd->dd_phys->dd_deleg_zapobj &&
    -		    (zap_count(mos, dd->dd_phys->dd_deleg_zapobj,
    -		    &n) == 0) && n) {
    -			VERIFY(nvlist_alloc(&sp_nvp,
    -			    NV_UNIQUE_NAME, KM_SLEEP) == 0);
    -		} else {
    +		if (dd->dd_phys->dd_deleg_zapobj == 0 ||
    +		    zap_count(mos, dd->dd_phys->dd_deleg_zapobj, &n) != 0 ||
    +		    n == 0)
     			continue;
    -		}
     
    +		sp_nvp = fnvlist_alloc();
     		for (zap_cursor_init(&basezc, mos,
     		    dd->dd_phys->dd_deleg_zapobj);
     		    zap_cursor_retrieve(&basezc, &baseza) == 0;
    @@ -327,29 +349,26 @@ dsl_deleg_get(const char *ddname, nvlist_t **nvp)
     			ASSERT(baseza.za_integer_length == 8);
     			ASSERT(baseza.za_num_integers == 1);
     
    -			VERIFY(nvlist_alloc(&perms_nvp,
    -			    NV_UNIQUE_NAME, KM_SLEEP) == 0);
    +			perms_nvp = fnvlist_alloc();
     			for (zap_cursor_init(&zc, mos, baseza.za_first_integer);
     			    zap_cursor_retrieve(&zc, &za) == 0;
     			    zap_cursor_advance(&zc)) {
    -				VERIFY(nvlist_add_boolean(perms_nvp,
    -				    za.za_name) == 0);
    +				fnvlist_add_boolean(perms_nvp, za.za_name);
     			}
     			zap_cursor_fini(&zc);
    -			VERIFY(nvlist_add_nvlist(sp_nvp, baseza.za_name,
    -			    perms_nvp) == 0);
    -			nvlist_free(perms_nvp);
    +			fnvlist_add_nvlist(sp_nvp, baseza.za_name, perms_nvp);
    +			fnvlist_free(perms_nvp);
     		}
     
     		zap_cursor_fini(&basezc);
     
     		dsl_dir_name(dd, source);
    -		VERIFY(nvlist_add_nvlist(*nvp, source, sp_nvp) == 0);
    +		fnvlist_add_nvlist(*nvp, source, sp_nvp);
     		nvlist_free(sp_nvp);
     	}
    -	rw_exit(&dp->dp_config_rwlock);
     
    -	dsl_dir_close(startdd, FTAG);
    +	dsl_dir_rele(startdd, FTAG);
    +	dsl_pool_rele(dp, FTAG);
     	return (0);
     }
     
    @@ -555,7 +574,7 @@ dsl_deleg_access_impl(dsl_dataset_t *ds, const char *perm, cred_t *cr)
     	avl_create(&permsets, perm_set_compare, sizeof (perm_set_t),
     	    offsetof(perm_set_t, p_node));
     
    -	rw_enter(&dp->dp_config_rwlock, RW_READER);
    +	ASSERT(dsl_pool_config_held(dp));
     	for (dd = ds->ds_dir; dd != NULL; dd = dd->dd_parent,
     	    checkflag = ZFS_DELEG_DESCENDENT) {
     		uint64_t zapobj;
    @@ -616,7 +635,6 @@ again:
     	}
     	error = EPERM;
     success:
    -	rw_exit(&dp->dp_config_rwlock);
     
     	cookie = NULL;
     	while ((setnode = avl_destroy_nodes(&permsets, &cookie)) != NULL)
    @@ -628,15 +646,19 @@ success:
     int
     dsl_deleg_access(const char *dsname, const char *perm, cred_t *cr)
     {
    +	dsl_pool_t *dp;
     	dsl_dataset_t *ds;
     	int error;
     
    -	error = dsl_dataset_hold(dsname, FTAG, &ds);
    -	if (error)
    +	error = dsl_pool_hold(dsname, FTAG, &dp);
    +	if (error != 0)
     		return (error);
    -
    -	error = dsl_deleg_access_impl(ds, perm, cr);
    -	dsl_dataset_rele(ds, FTAG);
    +	error = dsl_dataset_hold(dp, dsname, FTAG, &ds);
    +	if (error == 0) {
    +		error = dsl_deleg_access_impl(ds, perm, cr);
    +		dsl_dataset_rele(ds, FTAG);
    +	}
    +	dsl_pool_rele(dp, FTAG);
     
     	return (error);
     }
    diff --git a/uts/common/fs/zfs/dsl_destroy.c b/uts/common/fs/zfs/dsl_destroy.c
    new file mode 100644
    index 00000000000..20d401f2590
    --- /dev/null
    +++ b/uts/common/fs/zfs/dsl_destroy.c
    @@ -0,0 +1,926 @@
    +/*
    + * CDDL HEADER START
    + *
    + * The contents of this file are subject to the terms of the
    + * Common Development and Distribution License (the "License").
    + * You may not use this file except in compliance with the License.
    + *
    + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
    + * or http://www.opensolaris.org/os/licensing.
    + * See the License for the specific language governing permissions
    + * and limitations under the License.
    + *
    + * When distributing Covered Code, include this CDDL HEADER in each
    + * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
    + * If applicable, add the following below this CDDL HEADER, with the
    + * fields enclosed by brackets "[]" replaced with your own identifying
    + * information: Portions Copyright [yyyy] [name of copyright owner]
    + *
    + * CDDL HEADER END
    + */
    +/*
    + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2012 by Delphix. All rights reserved.
    + */
    +
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +
    +typedef struct dmu_snapshots_destroy_arg {
    +	nvlist_t *dsda_snaps;
    +	nvlist_t *dsda_successful_snaps;
    +	boolean_t dsda_defer;
    +	nvlist_t *dsda_errlist;
    +} dmu_snapshots_destroy_arg_t;
    +
    +/*
    + * ds must be owned.
    + */
    +static int
    +dsl_destroy_snapshot_check_impl(dsl_dataset_t *ds, boolean_t defer)
    +{
    +	if (!dsl_dataset_is_snapshot(ds))
    +		return (EINVAL);
    +
    +	if (dsl_dataset_long_held(ds))
    +		return (EBUSY);
    +
    +	/*
    +	 * Only allow deferred destroy on pools that support it.
    +	 * NOTE: deferred destroy is only supported on snapshots.
    +	 */
    +	if (defer) {
    +		if (spa_version(ds->ds_dir->dd_pool->dp_spa) <
    +		    SPA_VERSION_USERREFS)
    +			return (ENOTSUP);
    +		return (0);
    +	}
    +
    +	/*
    +	 * If this snapshot has an elevated user reference count,
    +	 * we can't destroy it yet.
    +	 */
    +	if (ds->ds_userrefs > 0)
    +		return (EBUSY);
    +
    +	/*
    +	 * Can't delete a branch point.
    +	 */
    +	if (ds->ds_phys->ds_num_children > 1)
    +		return (EEXIST);
    +
    +	return (0);
    +}
    +
    +static int
    +dsl_destroy_snapshot_check(void *arg, dmu_tx_t *tx)
    +{
    +	dmu_snapshots_destroy_arg_t *dsda = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	nvpair_t *pair;
    +	int error = 0;
    +
    +	if (!dmu_tx_is_syncing(tx))
    +		return (0);
    +
    +	for (pair = nvlist_next_nvpair(dsda->dsda_snaps, NULL);
    +	    pair != NULL; pair = nvlist_next_nvpair(dsda->dsda_snaps, pair)) {
    +		dsl_dataset_t *ds;
    +
    +		error = dsl_dataset_hold(dp, nvpair_name(pair),
    +		    FTAG, &ds);
    +
    +		/*
    +		 * If the snapshot does not exist, silently ignore it
    +		 * (it's "already destroyed").
    +		 */
    +		if (error == ENOENT)
    +			continue;
    +
    +		if (error == 0) {
    +			error = dsl_destroy_snapshot_check_impl(ds,
    +			    dsda->dsda_defer);
    +			dsl_dataset_rele(ds, FTAG);
    +		}
    +
    +		if (error == 0) {
    +			fnvlist_add_boolean(dsda->dsda_successful_snaps,
    +			    nvpair_name(pair));
    +		} else {
    +			fnvlist_add_int32(dsda->dsda_errlist,
    +			    nvpair_name(pair), error);
    +		}
    +	}
    +
    +	pair = nvlist_next_nvpair(dsda->dsda_errlist, NULL);
    +	if (pair != NULL)
    +		return (fnvpair_value_int32(pair));
    +	return (0);
    +}
    +
    +struct process_old_arg {
    +	dsl_dataset_t *ds;
    +	dsl_dataset_t *ds_prev;
    +	boolean_t after_branch_point;
    +	zio_t *pio;
    +	uint64_t used, comp, uncomp;
    +};
    +
    +static int
    +process_old_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx)
    +{
    +	struct process_old_arg *poa = arg;
    +	dsl_pool_t *dp = poa->ds->ds_dir->dd_pool;
    +
    +	if (bp->blk_birth <= poa->ds->ds_phys->ds_prev_snap_txg) {
    +		dsl_deadlist_insert(&poa->ds->ds_deadlist, bp, tx);
    +		if (poa->ds_prev && !poa->after_branch_point &&
    +		    bp->blk_birth >
    +		    poa->ds_prev->ds_phys->ds_prev_snap_txg) {
    +			poa->ds_prev->ds_phys->ds_unique_bytes +=
    +			    bp_get_dsize_sync(dp->dp_spa, bp);
    +		}
    +	} else {
    +		poa->used += bp_get_dsize_sync(dp->dp_spa, bp);
    +		poa->comp += BP_GET_PSIZE(bp);
    +		poa->uncomp += BP_GET_UCSIZE(bp);
    +		dsl_free_sync(poa->pio, dp, tx->tx_txg, bp);
    +	}
    +	return (0);
    +}
    +
    +static void
    +process_old_deadlist(dsl_dataset_t *ds, dsl_dataset_t *ds_prev,
    +    dsl_dataset_t *ds_next, boolean_t after_branch_point, dmu_tx_t *tx)
    +{
    +	struct process_old_arg poa = { 0 };
    +	dsl_pool_t *dp = ds->ds_dir->dd_pool;
    +	objset_t *mos = dp->dp_meta_objset;
    +	uint64_t deadlist_obj;
    +
    +	ASSERT(ds->ds_deadlist.dl_oldfmt);
    +	ASSERT(ds_next->ds_deadlist.dl_oldfmt);
    +
    +	poa.ds = ds;
    +	poa.ds_prev = ds_prev;
    +	poa.after_branch_point = after_branch_point;
    +	poa.pio = zio_root(dp->dp_spa, NULL, NULL, ZIO_FLAG_MUSTSUCCEED);
    +	VERIFY0(bpobj_iterate(&ds_next->ds_deadlist.dl_bpobj,
    +	    process_old_cb, &poa, tx));
    +	VERIFY0(zio_wait(poa.pio));
    +	ASSERT3U(poa.used, ==, ds->ds_phys->ds_unique_bytes);
    +
    +	/* change snapused */
    +	dsl_dir_diduse_space(ds->ds_dir, DD_USED_SNAP,
    +	    -poa.used, -poa.comp, -poa.uncomp, tx);
    +
    +	/* swap next's deadlist to our deadlist */
    +	dsl_deadlist_close(&ds->ds_deadlist);
    +	dsl_deadlist_close(&ds_next->ds_deadlist);
    +	deadlist_obj = ds->ds_phys->ds_deadlist_obj;
    +	ds->ds_phys->ds_deadlist_obj = ds_next->ds_phys->ds_deadlist_obj;
    +	ds_next->ds_phys->ds_deadlist_obj = deadlist_obj;
    +	dsl_deadlist_open(&ds->ds_deadlist, mos, ds->ds_phys->ds_deadlist_obj);
    +	dsl_deadlist_open(&ds_next->ds_deadlist, mos,
    +	    ds_next->ds_phys->ds_deadlist_obj);
    +}
    +
    +static void
    +dsl_dataset_remove_clones_key(dsl_dataset_t *ds, uint64_t mintxg, dmu_tx_t *tx)
    +{
    +	objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
    +	zap_cursor_t zc;
    +	zap_attribute_t za;
    +
    +	/*
    +	 * If it is the old version, dd_clones doesn't exist so we can't
    +	 * find the clones, but dsl_deadlist_remove_key() is a no-op so it
    +	 * doesn't matter.
    +	 */
    +	if (ds->ds_dir->dd_phys->dd_clones == 0)
    +		return;
    +
    +	for (zap_cursor_init(&zc, mos, ds->ds_dir->dd_phys->dd_clones);
    +	    zap_cursor_retrieve(&zc, &za) == 0;
    +	    zap_cursor_advance(&zc)) {
    +		dsl_dataset_t *clone;
    +
    +		VERIFY0(dsl_dataset_hold_obj(ds->ds_dir->dd_pool,
    +		    za.za_first_integer, FTAG, &clone));
    +		if (clone->ds_dir->dd_origin_txg > mintxg) {
    +			dsl_deadlist_remove_key(&clone->ds_deadlist,
    +			    mintxg, tx);
    +			dsl_dataset_remove_clones_key(clone, mintxg, tx);
    +		}
    +		dsl_dataset_rele(clone, FTAG);
    +	}
    +	zap_cursor_fini(&zc);
    +}
    +
    +void
    +dsl_destroy_snapshot_sync_impl(dsl_dataset_t *ds, boolean_t defer, dmu_tx_t *tx)
    +{
    +	int err;
    +	int after_branch_point = FALSE;
    +	dsl_pool_t *dp = ds->ds_dir->dd_pool;
    +	objset_t *mos = dp->dp_meta_objset;
    +	dsl_dataset_t *ds_prev = NULL;
    +	uint64_t obj;
    +
    +	ASSERT(RRW_WRITE_HELD(&dp->dp_config_rwlock));
    +	ASSERT3U(ds->ds_phys->ds_bp.blk_birth, <=, tx->tx_txg);
    +	ASSERT(refcount_is_zero(&ds->ds_longholds));
    +
    +	if (defer &&
    +	    (ds->ds_userrefs > 0 || ds->ds_phys->ds_num_children > 1)) {
    +		ASSERT(spa_version(dp->dp_spa) >= SPA_VERSION_USERREFS);
    +		dmu_buf_will_dirty(ds->ds_dbuf, tx);
    +		ds->ds_phys->ds_flags |= DS_FLAG_DEFER_DESTROY;
    +		spa_history_log_internal_ds(ds, "defer_destroy", tx, "");
    +		return;
    +	}
    +
    +	ASSERT3U(ds->ds_phys->ds_num_children, <=, 1);
    +
    +	/* We need to log before removing it from the namespace. */
    +	spa_history_log_internal_ds(ds, "destroy", tx, "");
    +
    +	dsl_scan_ds_destroyed(ds, tx);
    +
    +	obj = ds->ds_object;
    +
    +	if (ds->ds_phys->ds_prev_snap_obj != 0) {
    +		ASSERT3P(ds->ds_prev, ==, NULL);
    +		VERIFY0(dsl_dataset_hold_obj(dp,
    +		    ds->ds_phys->ds_prev_snap_obj, FTAG, &ds_prev));
    +		after_branch_point =
    +		    (ds_prev->ds_phys->ds_next_snap_obj != obj);
    +
    +		dmu_buf_will_dirty(ds_prev->ds_dbuf, tx);
    +		if (after_branch_point &&
    +		    ds_prev->ds_phys->ds_next_clones_obj != 0) {
    +			dsl_dataset_remove_from_next_clones(ds_prev, obj, tx);
    +			if (ds->ds_phys->ds_next_snap_obj != 0) {
    +				VERIFY0(zap_add_int(mos,
    +				    ds_prev->ds_phys->ds_next_clones_obj,
    +				    ds->ds_phys->ds_next_snap_obj, tx));
    +			}
    +		}
    +		if (!after_branch_point) {
    +			ds_prev->ds_phys->ds_next_snap_obj =
    +			    ds->ds_phys->ds_next_snap_obj;
    +		}
    +	}
    +
    +	dsl_dataset_t *ds_next;
    +	uint64_t old_unique;
    +	uint64_t used = 0, comp = 0, uncomp = 0;
    +
    +	VERIFY0(dsl_dataset_hold_obj(dp,
    +	    ds->ds_phys->ds_next_snap_obj, FTAG, &ds_next));
    +	ASSERT3U(ds_next->ds_phys->ds_prev_snap_obj, ==, obj);
    +
    +	old_unique = ds_next->ds_phys->ds_unique_bytes;
    +
    +	dmu_buf_will_dirty(ds_next->ds_dbuf, tx);
    +	ds_next->ds_phys->ds_prev_snap_obj =
    +	    ds->ds_phys->ds_prev_snap_obj;
    +	ds_next->ds_phys->ds_prev_snap_txg =
    +	    ds->ds_phys->ds_prev_snap_txg;
    +	ASSERT3U(ds->ds_phys->ds_prev_snap_txg, ==,
    +	    ds_prev ? ds_prev->ds_phys->ds_creation_txg : 0);
    +
    +	if (ds_next->ds_deadlist.dl_oldfmt) {
    +		process_old_deadlist(ds, ds_prev, ds_next,
    +		    after_branch_point, tx);
    +	} else {
    +		/* Adjust prev's unique space. */
    +		if (ds_prev && !after_branch_point) {
    +			dsl_deadlist_space_range(&ds_next->ds_deadlist,
    +			    ds_prev->ds_phys->ds_prev_snap_txg,
    +			    ds->ds_phys->ds_prev_snap_txg,
    +			    &used, &comp, &uncomp);
    +			ds_prev->ds_phys->ds_unique_bytes += used;
    +		}
    +
    +		/* Adjust snapused. */
    +		dsl_deadlist_space_range(&ds_next->ds_deadlist,
    +		    ds->ds_phys->ds_prev_snap_txg, UINT64_MAX,
    +		    &used, &comp, &uncomp);
    +		dsl_dir_diduse_space(ds->ds_dir, DD_USED_SNAP,
    +		    -used, -comp, -uncomp, tx);
    +
    +		/* Move blocks to be freed to pool's free list. */
    +		dsl_deadlist_move_bpobj(&ds_next->ds_deadlist,
    +		    &dp->dp_free_bpobj, ds->ds_phys->ds_prev_snap_txg,
    +		    tx);
    +		dsl_dir_diduse_space(tx->tx_pool->dp_free_dir,
    +		    DD_USED_HEAD, used, comp, uncomp, tx);
    +
    +		/* Merge our deadlist into next's and free it. */
    +		dsl_deadlist_merge(&ds_next->ds_deadlist,
    +		    ds->ds_phys->ds_deadlist_obj, tx);
    +	}
    +	dsl_deadlist_close(&ds->ds_deadlist);
    +	dsl_deadlist_free(mos, ds->ds_phys->ds_deadlist_obj, tx);
    +	dmu_buf_will_dirty(ds->ds_dbuf, tx);
    +	ds->ds_phys->ds_deadlist_obj = 0;
    +
    +	/* Collapse range in clone heads */
    +	dsl_dataset_remove_clones_key(ds,
    +	    ds->ds_phys->ds_creation_txg, tx);
    +
    +	if (dsl_dataset_is_snapshot(ds_next)) {
    +		dsl_dataset_t *ds_nextnext;
    +
    +		/*
    +		 * Update next's unique to include blocks which
    +		 * were previously shared by only this snapshot
    +		 * and it.  Those blocks will be born after the
    +		 * prev snap and before this snap, and will have
    +		 * died after the next snap and before the one
    +		 * after that (ie. be on the snap after next's
    +		 * deadlist).
    +		 */
    +		VERIFY0(dsl_dataset_hold_obj(dp,
    +		    ds_next->ds_phys->ds_next_snap_obj, FTAG, &ds_nextnext));
    +		dsl_deadlist_space_range(&ds_nextnext->ds_deadlist,
    +		    ds->ds_phys->ds_prev_snap_txg,
    +		    ds->ds_phys->ds_creation_txg,
    +		    &used, &comp, &uncomp);
    +		ds_next->ds_phys->ds_unique_bytes += used;
    +		dsl_dataset_rele(ds_nextnext, FTAG);
    +		ASSERT3P(ds_next->ds_prev, ==, NULL);
    +
    +		/* Collapse range in this head. */
    +		dsl_dataset_t *hds;
    +		VERIFY0(dsl_dataset_hold_obj(dp,
    +		    ds->ds_dir->dd_phys->dd_head_dataset_obj, FTAG, &hds));
    +		dsl_deadlist_remove_key(&hds->ds_deadlist,
    +		    ds->ds_phys->ds_creation_txg, tx);
    +		dsl_dataset_rele(hds, FTAG);
    +
    +	} else {
    +		ASSERT3P(ds_next->ds_prev, ==, ds);
    +		dsl_dataset_rele(ds_next->ds_prev, ds_next);
    +		ds_next->ds_prev = NULL;
    +		if (ds_prev) {
    +			VERIFY0(dsl_dataset_hold_obj(dp,
    +			    ds->ds_phys->ds_prev_snap_obj,
    +			    ds_next, &ds_next->ds_prev));
    +		}
    +
    +		dsl_dataset_recalc_head_uniq(ds_next);
    +
    +		/*
    +		 * Reduce the amount of our unconsumed refreservation
    +		 * being charged to our parent by the amount of
    +		 * new unique data we have gained.
    +		 */
    +		if (old_unique < ds_next->ds_reserved) {
    +			int64_t mrsdelta;
    +			uint64_t new_unique =
    +			    ds_next->ds_phys->ds_unique_bytes;
    +
    +			ASSERT(old_unique <= new_unique);
    +			mrsdelta = MIN(new_unique - old_unique,
    +			    ds_next->ds_reserved - old_unique);
    +			dsl_dir_diduse_space(ds->ds_dir,
    +			    DD_USED_REFRSRV, -mrsdelta, 0, 0, tx);
    +		}
    +	}
    +	dsl_dataset_rele(ds_next, FTAG);
    +
    +	/*
    +	 * This must be done after the dsl_traverse(), because it will
    +	 * re-open the objset.
    +	 */
    +	if (ds->ds_objset) {
    +		dmu_objset_evict(ds->ds_objset);
    +		ds->ds_objset = NULL;
    +	}
    +
    +	/* remove from snapshot namespace */
    +	dsl_dataset_t *ds_head;
    +	ASSERT(ds->ds_phys->ds_snapnames_zapobj == 0);
    +	VERIFY0(dsl_dataset_hold_obj(dp,
    +	    ds->ds_dir->dd_phys->dd_head_dataset_obj, FTAG, &ds_head));
    +	VERIFY0(dsl_dataset_get_snapname(ds));
    +#ifdef ZFS_DEBUG
    +	{
    +		uint64_t val;
    +
    +		err = dsl_dataset_snap_lookup(ds_head,
    +		    ds->ds_snapname, &val);
    +		ASSERT0(err);
    +		ASSERT3U(val, ==, obj);
    +	}
    +#endif
    +	VERIFY0(dsl_dataset_snap_remove(ds_head, ds->ds_snapname, tx));
    +	dsl_dataset_rele(ds_head, FTAG);
    +
    +	if (ds_prev != NULL)
    +		dsl_dataset_rele(ds_prev, FTAG);
    +
    +	spa_prop_clear_bootfs(dp->dp_spa, ds->ds_object, tx);
    +
    +	if (ds->ds_phys->ds_next_clones_obj != 0) {
    +		uint64_t count;
    +		ASSERT0(zap_count(mos,
    +		    ds->ds_phys->ds_next_clones_obj, &count) && count == 0);
    +		VERIFY0(dmu_object_free(mos,
    +		    ds->ds_phys->ds_next_clones_obj, tx));
    +	}
    +	if (ds->ds_phys->ds_props_obj != 0)
    +		VERIFY0(zap_destroy(mos, ds->ds_phys->ds_props_obj, tx));
    +	if (ds->ds_phys->ds_userrefs_obj != 0)
    +		VERIFY0(zap_destroy(mos, ds->ds_phys->ds_userrefs_obj, tx));
    +	dsl_dir_rele(ds->ds_dir, ds);
    +	ds->ds_dir = NULL;
    +	VERIFY0(dmu_object_free(mos, obj, tx));
    +}
    +
    +static void
    +dsl_destroy_snapshot_sync(void *arg, dmu_tx_t *tx)
    +{
    +	dmu_snapshots_destroy_arg_t *dsda = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	nvpair_t *pair;
    +
    +	for (pair = nvlist_next_nvpair(dsda->dsda_successful_snaps, NULL);
    +	    pair != NULL;
    +	    pair = nvlist_next_nvpair(dsda->dsda_successful_snaps, pair)) {
    +		dsl_dataset_t *ds;
    +
    +		VERIFY0(dsl_dataset_hold(dp, nvpair_name(pair), FTAG, &ds));
    +
    +		dsl_destroy_snapshot_sync_impl(ds, dsda->dsda_defer, tx);
    +		dsl_dataset_rele(ds, FTAG);
    +	}
    +}
    +
    +/*
    + * The semantics of this function are described in the comment above
    + * lzc_destroy_snaps().  To summarize:
    + *
    + * The snapshots must all be in the same pool.
    + *
    + * Snapshots that don't exist will be silently ignored (considered to be
    + * "already deleted").
    + *
    + * On success, all snaps will be destroyed and this will return 0.
    + * On failure, no snaps will be destroyed, the errlist will be filled in,
    + * and this will return an errno.
    + */
    +int
    +dsl_destroy_snapshots_nvl(nvlist_t *snaps, boolean_t defer,
    +    nvlist_t *errlist)
    +{
    +	dmu_snapshots_destroy_arg_t dsda;
    +	int error;
    +	nvpair_t *pair;
    +
    +	pair = nvlist_next_nvpair(snaps, NULL);
    +	if (pair == NULL)
    +		return (0);
    +
    +	dsda.dsda_snaps = snaps;
    +	dsda.dsda_successful_snaps = fnvlist_alloc();
    +	dsda.dsda_defer = defer;
    +	dsda.dsda_errlist = errlist;
    +
    +	error = dsl_sync_task(nvpair_name(pair),
    +	    dsl_destroy_snapshot_check, dsl_destroy_snapshot_sync,
    +	    &dsda, 0);
    +	fnvlist_free(dsda.dsda_successful_snaps);
    +
    +	return (error);
    +}
    +
    +int
    +dsl_destroy_snapshot(const char *name, boolean_t defer)
    +{
    +	int error;
    +	nvlist_t *nvl = fnvlist_alloc();
    +	nvlist_t *errlist = fnvlist_alloc();
    +
    +	fnvlist_add_boolean(nvl, name);
    +	error = dsl_destroy_snapshots_nvl(nvl, defer, errlist);
    +	fnvlist_free(errlist);
    +	fnvlist_free(nvl);
    +	return (error);
    +}
    +
    +struct killarg {
    +	dsl_dataset_t *ds;
    +	dmu_tx_t *tx;
    +};
    +
    +/* ARGSUSED */
    +static int
    +kill_blkptr(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
    +    const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg)
    +{
    +	struct killarg *ka = arg;
    +	dmu_tx_t *tx = ka->tx;
    +
    +	if (bp == NULL)
    +		return (0);
    +
    +	if (zb->zb_level == ZB_ZIL_LEVEL) {
    +		ASSERT(zilog != NULL);
    +		/*
    +		 * It's a block in the intent log.  It has no
    +		 * accounting, so just free it.
    +		 */
    +		dsl_free(ka->tx->tx_pool, ka->tx->tx_txg, bp);
    +	} else {
    +		ASSERT(zilog == NULL);
    +		ASSERT3U(bp->blk_birth, >, ka->ds->ds_phys->ds_prev_snap_txg);
    +		(void) dsl_dataset_block_kill(ka->ds, bp, tx, B_FALSE);
    +	}
    +
    +	return (0);
    +}
    +
    +static void
    +old_synchronous_dataset_destroy(dsl_dataset_t *ds, dmu_tx_t *tx)
    +{
    +	struct killarg ka;
    +
    +	/*
    +	 * Free everything that we point to (that's born after
    +	 * the previous snapshot, if we are a clone)
    +	 *
    +	 * NB: this should be very quick, because we already
    +	 * freed all the objects in open context.
    +	 */
    +	ka.ds = ds;
    +	ka.tx = tx;
    +	VERIFY0(traverse_dataset(ds,
    +	    ds->ds_phys->ds_prev_snap_txg, TRAVERSE_POST,
    +	    kill_blkptr, &ka));
    +	ASSERT(!DS_UNIQUE_IS_ACCURATE(ds) || ds->ds_phys->ds_unique_bytes == 0);
    +}
    +
    +typedef struct dsl_destroy_head_arg {
    +	const char *ddha_name;
    +} dsl_destroy_head_arg_t;
    +
    +int
    +dsl_destroy_head_check_impl(dsl_dataset_t *ds, int expected_holds)
    +{
    +	int error;
    +	uint64_t count;
    +	objset_t *mos;
    +
    +	if (dsl_dataset_is_snapshot(ds))
    +		return (EINVAL);
    +
    +	if (refcount_count(&ds->ds_longholds) != expected_holds)
    +		return (EBUSY);
    +
    +	mos = ds->ds_dir->dd_pool->dp_meta_objset;
    +
    +	/*
    +	 * Can't delete a head dataset if there are snapshots of it.
    +	 * (Except if the only snapshots are from the branch we cloned
    +	 * from.)
    +	 */
    +	if (ds->ds_prev != NULL &&
    +	    ds->ds_prev->ds_phys->ds_next_snap_obj == ds->ds_object)
    +		return (EBUSY);
    +
    +	/*
    +	 * Can't delete if there are children of this fs.
    +	 */
    +	error = zap_count(mos,
    +	    ds->ds_dir->dd_phys->dd_child_dir_zapobj, &count);
    +	if (error != 0)
    +		return (error);
    +	if (count != 0)
    +		return (EEXIST);
    +
    +	if (dsl_dir_is_clone(ds->ds_dir) && DS_IS_DEFER_DESTROY(ds->ds_prev) &&
    +	    ds->ds_prev->ds_phys->ds_num_children == 2 &&
    +	    ds->ds_prev->ds_userrefs == 0) {
    +		/* We need to remove the origin snapshot as well. */
    +		if (!refcount_is_zero(&ds->ds_prev->ds_longholds))
    +			return (EBUSY);
    +	}
    +	return (0);
    +}
    +
    +static int
    +dsl_destroy_head_check(void *arg, dmu_tx_t *tx)
    +{
    +	dsl_destroy_head_arg_t *ddha = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	dsl_dataset_t *ds;
    +	int error;
    +
    +	error = dsl_dataset_hold(dp, ddha->ddha_name, FTAG, &ds);
    +	if (error != 0)
    +		return (error);
    +
    +	error = dsl_destroy_head_check_impl(ds, 0);
    +	dsl_dataset_rele(ds, FTAG);
    +	return (error);
    +}
    +
    +static void
    +dsl_dir_destroy_sync(uint64_t ddobj, dmu_tx_t *tx)
    +{
    +	dsl_dir_t *dd;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	objset_t *mos = dp->dp_meta_objset;
    +	dd_used_t t;
    +
    +	ASSERT(RRW_WRITE_HELD(&dmu_tx_pool(tx)->dp_config_rwlock));
    +
    +	VERIFY0(dsl_dir_hold_obj(dp, ddobj, NULL, FTAG, &dd));
    +
    +	ASSERT0(dd->dd_phys->dd_head_dataset_obj);
    +
    +	/*
    +	 * Remove our reservation. The impl() routine avoids setting the
    +	 * actual property, which would require the (already destroyed) ds.
    +	 */
    +	dsl_dir_set_reservation_sync_impl(dd, 0, tx);
    +
    +	ASSERT0(dd->dd_phys->dd_used_bytes);
    +	ASSERT0(dd->dd_phys->dd_reserved);
    +	for (t = 0; t < DD_USED_NUM; t++)
    +		ASSERT0(dd->dd_phys->dd_used_breakdown[t]);
    +
    +	VERIFY0(zap_destroy(mos, dd->dd_phys->dd_child_dir_zapobj, tx));
    +	VERIFY0(zap_destroy(mos, dd->dd_phys->dd_props_zapobj, tx));
    +	VERIFY0(dsl_deleg_destroy(mos, dd->dd_phys->dd_deleg_zapobj, tx));
    +	VERIFY0(zap_remove(mos,
    +	    dd->dd_parent->dd_phys->dd_child_dir_zapobj, dd->dd_myname, tx));
    +
    +	dsl_dir_rele(dd, FTAG);
    +	VERIFY0(dmu_object_free(mos, ddobj, tx));
    +}
    +
    +void
    +dsl_destroy_head_sync_impl(dsl_dataset_t *ds, dmu_tx_t *tx)
    +{
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	objset_t *mos = dp->dp_meta_objset;
    +	uint64_t obj, ddobj, prevobj = 0;
    +	boolean_t rmorigin;
    +
    +	ASSERT3U(ds->ds_phys->ds_num_children, <=, 1);
    +	ASSERT(ds->ds_prev == NULL ||
    +	    ds->ds_prev->ds_phys->ds_next_snap_obj != ds->ds_object);
    +	ASSERT3U(ds->ds_phys->ds_bp.blk_birth, <=, tx->tx_txg);
    +	ASSERT(RRW_WRITE_HELD(&dp->dp_config_rwlock));
    +
    +	/* We need to log before removing it from the namespace. */
    +	spa_history_log_internal_ds(ds, "destroy", tx, "");
    +
    +	rmorigin = (dsl_dir_is_clone(ds->ds_dir) &&
    +	    DS_IS_DEFER_DESTROY(ds->ds_prev) &&
    +	    ds->ds_prev->ds_phys->ds_num_children == 2 &&
    +	    ds->ds_prev->ds_userrefs == 0);
    +
    +	/* Remove our reservation */
    +	if (ds->ds_reserved != 0) {
    +		dsl_dataset_set_refreservation_sync_impl(ds,
    +		    (ZPROP_SRC_NONE | ZPROP_SRC_LOCAL | ZPROP_SRC_RECEIVED),
    +		    0, tx);
    +		ASSERT0(ds->ds_reserved);
    +	}
    +
    +	dsl_scan_ds_destroyed(ds, tx);
    +
    +	obj = ds->ds_object;
    +
    +	if (ds->ds_phys->ds_prev_snap_obj != 0) {
    +		/* This is a clone */
    +		ASSERT(ds->ds_prev != NULL);
    +		ASSERT3U(ds->ds_prev->ds_phys->ds_next_snap_obj, !=, obj);
    +		ASSERT0(ds->ds_phys->ds_next_snap_obj);
    +
    +		dmu_buf_will_dirty(ds->ds_prev->ds_dbuf, tx);
    +		if (ds->ds_prev->ds_phys->ds_next_clones_obj != 0) {
    +			dsl_dataset_remove_from_next_clones(ds->ds_prev,
    +			    obj, tx);
    +		}
    +
    +		ASSERT3U(ds->ds_prev->ds_phys->ds_num_children, >, 1);
    +		ds->ds_prev->ds_phys->ds_num_children--;
    +	}
    +
    +	zfeature_info_t *async_destroy =
    +	    &spa_feature_table[SPA_FEATURE_ASYNC_DESTROY];
    +	objset_t *os;
    +
    +	/*
    +	 * Destroy the deadlist.  Unless it's a clone, the
    +	 * deadlist should be empty.  (If it's a clone, it's
    +	 * safe to ignore the deadlist contents.)
    +	 */
    +	dsl_deadlist_close(&ds->ds_deadlist);
    +	dsl_deadlist_free(mos, ds->ds_phys->ds_deadlist_obj, tx);
    +	dmu_buf_will_dirty(ds->ds_dbuf, tx);
    +	ds->ds_phys->ds_deadlist_obj = 0;
    +
    +	VERIFY0(dmu_objset_from_ds(ds, &os));
    +
    +	if (!spa_feature_is_enabled(dp->dp_spa, async_destroy)) {
    +		old_synchronous_dataset_destroy(ds, tx);
    +	} else {
    +		/*
    +		 * Move the bptree into the pool's list of trees to
    +		 * clean up and update space accounting information.
    +		 */
    +		uint64_t used, comp, uncomp;
    +
    +		zil_destroy_sync(dmu_objset_zil(os), tx);
    +
    +		if (!spa_feature_is_active(dp->dp_spa, async_destroy)) {
    +			spa_feature_incr(dp->dp_spa, async_destroy, tx);
    +			dp->dp_bptree_obj = bptree_alloc(mos, tx);
    +			VERIFY0(zap_add(mos,
    +			    DMU_POOL_DIRECTORY_OBJECT,
    +			    DMU_POOL_BPTREE_OBJ, sizeof (uint64_t), 1,
    +			    &dp->dp_bptree_obj, tx));
    +		}
    +
    +		used = ds->ds_dir->dd_phys->dd_used_bytes;
    +		comp = ds->ds_dir->dd_phys->dd_compressed_bytes;
    +		uncomp = ds->ds_dir->dd_phys->dd_uncompressed_bytes;
    +
    +		ASSERT(!DS_UNIQUE_IS_ACCURATE(ds) ||
    +		    ds->ds_phys->ds_unique_bytes == used);
    +
    +		bptree_add(mos, dp->dp_bptree_obj,
    +		    &ds->ds_phys->ds_bp, ds->ds_phys->ds_prev_snap_txg,
    +		    used, comp, uncomp, tx);
    +		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,
    +		    used, comp, uncomp, tx);
    +	}
    +
    +	if (ds->ds_prev != NULL) {
    +		if (spa_version(dp->dp_spa) >= SPA_VERSION_DIR_CLONES) {
    +			VERIFY0(zap_remove_int(mos,
    +			    ds->ds_prev->ds_dir->dd_phys->dd_clones,
    +			    ds->ds_object, tx));
    +		}
    +		prevobj = ds->ds_prev->ds_object;
    +		dsl_dataset_rele(ds->ds_prev, ds);
    +		ds->ds_prev = NULL;
    +	}
    +
    +	/*
    +	 * This must be done after the dsl_traverse(), because it will
    +	 * re-open the objset.
    +	 */
    +	if (ds->ds_objset) {
    +		dmu_objset_evict(ds->ds_objset);
    +		ds->ds_objset = NULL;
    +	}
    +
    +	/* Erase the link in the dir */
    +	dmu_buf_will_dirty(ds->ds_dir->dd_dbuf, tx);
    +	ds->ds_dir->dd_phys->dd_head_dataset_obj = 0;
    +	ddobj = ds->ds_dir->dd_object;
    +	ASSERT(ds->ds_phys->ds_snapnames_zapobj != 0);
    +	VERIFY0(zap_destroy(mos, ds->ds_phys->ds_snapnames_zapobj, tx));
    +
    +	spa_prop_clear_bootfs(dp->dp_spa, ds->ds_object, tx);
    +
    +	ASSERT0(ds->ds_phys->ds_next_clones_obj);
    +	ASSERT0(ds->ds_phys->ds_props_obj);
    +	ASSERT0(ds->ds_phys->ds_userrefs_obj);
    +	dsl_dir_rele(ds->ds_dir, ds);
    +	ds->ds_dir = NULL;
    +	VERIFY0(dmu_object_free(mos, obj, tx));
    +
    +	dsl_dir_destroy_sync(ddobj, tx);
    +
    +	if (rmorigin) {
    +		dsl_dataset_t *prev;
    +		VERIFY0(dsl_dataset_hold_obj(dp, prevobj, FTAG, &prev));
    +		dsl_destroy_snapshot_sync_impl(prev, B_FALSE, tx);
    +		dsl_dataset_rele(prev, FTAG);
    +	}
    +}
    +
    +static void
    +dsl_destroy_head_sync(void *arg, dmu_tx_t *tx)
    +{
    +	dsl_destroy_head_arg_t *ddha = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	dsl_dataset_t *ds;
    +
    +	VERIFY0(dsl_dataset_hold(dp, ddha->ddha_name, FTAG, &ds));
    +	dsl_destroy_head_sync_impl(ds, tx);
    +	dsl_dataset_rele(ds, FTAG);
    +}
    +
    +static void
    +dsl_destroy_head_begin_sync(void *arg, dmu_tx_t *tx)
    +{
    +	dsl_destroy_head_arg_t *ddha = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	dsl_dataset_t *ds;
    +
    +	VERIFY0(dsl_dataset_hold(dp, ddha->ddha_name, FTAG, &ds));
    +
    +	/* Mark it as inconsistent on-disk, in case we crash */
    +	dmu_buf_will_dirty(ds->ds_dbuf, tx);
    +	ds->ds_phys->ds_flags |= DS_FLAG_INCONSISTENT;
    +
    +	spa_history_log_internal_ds(ds, "destroy begin", tx, "");
    +	dsl_dataset_rele(ds, FTAG);
    +}
    +
    +int
    +dsl_destroy_head(const char *name)
    +{
    +	dsl_destroy_head_arg_t ddha;
    +	int error;
    +	spa_t *spa;
    +	boolean_t isenabled;
    +
    +#ifdef _KERNEL
    +	zfs_destroy_unmount_origin(name);
    +#endif
    +
    +	error = spa_open(name, &spa, FTAG);
    +	if (error != 0)
    +		return (error);
    +	isenabled = spa_feature_is_enabled(spa,
    +	    &spa_feature_table[SPA_FEATURE_ASYNC_DESTROY]);
    +	spa_close(spa, FTAG);
    +
    +	ddha.ddha_name = name;
    +
    +	if (!isenabled) {
    +		objset_t *os;
    +
    +		error = dsl_sync_task(name, dsl_destroy_head_check,
    +		    dsl_destroy_head_begin_sync, &ddha, 0);
    +		if (error != 0)
    +			return (error);
    +
    +		/*
    +		 * Head deletion is processed in one txg on old pools;
    +		 * remove the objects from open context so that the txg sync
    +		 * is not too long.
    +		 */
    +		error = dmu_objset_own(name, DMU_OST_ANY, B_FALSE, FTAG, &os);
    +		if (error == 0) {
    +			uint64_t prev_snap_txg =
    +			    dmu_objset_ds(os)->ds_phys->ds_prev_snap_txg;
    +			for (uint64_t obj = 0; error == 0;
    +			    error = dmu_object_next(os, &obj, FALSE,
    +			    prev_snap_txg))
    +				(void) dmu_free_object(os, obj);
    +			/* sync out all frees */
    +			txg_wait_synced(dmu_objset_pool(os), 0);
    +			dmu_objset_disown(os, FTAG);
    +		}
    +	}
    +
    +	return (dsl_sync_task(name, dsl_destroy_head_check,
    +	    dsl_destroy_head_sync, &ddha, 0));
    +}
    +
    +/*
    + * Note, this function is used as the callback for dmu_objset_find().  We
    + * always return 0 so that we will continue to find and process
    + * inconsistent datasets, even if we encounter an error trying to
    + * process one of them.
    + */
    +/* ARGSUSED */
    +int
    +dsl_destroy_inconsistent(const char *dsname, void *arg)
    +{
    +	objset_t *os;
    +
    +	if (dmu_objset_hold(dsname, FTAG, &os) == 0) {
    +		boolean_t inconsistent = DS_IS_INCONSISTENT(dmu_objset_ds(os));
    +		dmu_objset_rele(os, FTAG);
    +		if (inconsistent)
    +			(void) dsl_destroy_head(dsname);
    +	}
    +	return (0);
    +}
    diff --git a/uts/common/fs/zfs/dsl_dir.c b/uts/common/fs/zfs/dsl_dir.c
    index 5ccb6862e9d..1e7ba6d6cbe 100644
    --- a/uts/common/fs/zfs/dsl_dir.c
    +++ b/uts/common/fs/zfs/dsl_dir.c
    @@ -40,8 +40,6 @@
     #include "zfs_namecheck.h"
     
     static uint64_t dsl_dir_space_towrite(dsl_dir_t *dd);
    -static void dsl_dir_set_reservation_sync_impl(dsl_dir_t *dd,
    -    uint64_t value, dmu_tx_t *tx);
     
     /* ARGSUSED */
     static void
    @@ -58,7 +56,7 @@ dsl_dir_evict(dmu_buf_t *db, void *arg)
     	}
     
     	if (dd->dd_parent)
    -		dsl_dir_close(dd->dd_parent, dd);
    +		dsl_dir_rele(dd->dd_parent, dd);
     
     	spa_close(dd->dd_pool->dp_spa, dd);
     
    @@ -72,18 +70,17 @@ dsl_dir_evict(dmu_buf_t *db, void *arg)
     }
     
     int
    -dsl_dir_open_obj(dsl_pool_t *dp, uint64_t ddobj,
    +dsl_dir_hold_obj(dsl_pool_t *dp, uint64_t ddobj,
         const char *tail, void *tag, dsl_dir_t **ddp)
     {
     	dmu_buf_t *dbuf;
     	dsl_dir_t *dd;
     	int err;
     
    -	ASSERT(RW_LOCK_HELD(&dp->dp_config_rwlock) ||
    -	    dsl_pool_sync_context(dp));
    +	ASSERT(dsl_pool_config_held(dp));
     
     	err = dmu_bonus_hold(dp->dp_meta_objset, ddobj, tag, &dbuf);
    -	if (err)
    +	if (err != 0)
     		return (err);
     	dd = dmu_buf_get_user(dbuf);
     #ifdef ZFS_DEBUG
    @@ -110,9 +107,9 @@ dsl_dir_open_obj(dsl_pool_t *dp, uint64_t ddobj,
     		dsl_dir_snap_cmtime_update(dd);
     
     		if (dd->dd_phys->dd_parent_obj) {
    -			err = dsl_dir_open_obj(dp, dd->dd_phys->dd_parent_obj,
    +			err = dsl_dir_hold_obj(dp, dd->dd_phys->dd_parent_obj,
     			    NULL, dd, &dd->dd_parent);
    -			if (err)
    +			if (err != 0)
     				goto errout;
     			if (tail) {
     #ifdef ZFS_DEBUG
    @@ -129,7 +126,7 @@ dsl_dir_open_obj(dsl_pool_t *dp, uint64_t ddobj,
     				    dd->dd_parent->dd_phys->dd_child_dir_zapobj,
     				    ddobj, 0, dd->dd_myname);
     			}
    -			if (err)
    +			if (err != 0)
     				goto errout;
     		} else {
     			(void) strcpy(dd->dd_myname, spa_name(dp->dp_spa));
    @@ -146,7 +143,7 @@ dsl_dir_open_obj(dsl_pool_t *dp, uint64_t ddobj,
     			 */
     			err = dmu_bonus_hold(dp->dp_meta_objset,
     			    dd->dd_phys->dd_origin_obj, FTAG, &origin_bonus);
    -			if (err)
    +			if (err != 0)
     				goto errout;
     			origin_phys = origin_bonus->db_data;
     			dd->dd_origin_txg =
    @@ -158,7 +155,7 @@ dsl_dir_open_obj(dsl_pool_t *dp, uint64_t ddobj,
     		    dsl_dir_evict);
     		if (winner) {
     			if (dd->dd_parent)
    -				dsl_dir_close(dd->dd_parent, dd);
    +				dsl_dir_rele(dd->dd_parent, dd);
     			mutex_destroy(&dd->dd_lock);
     			kmem_free(dd, sizeof (dsl_dir_t));
     			dd = winner;
    @@ -185,7 +182,7 @@ dsl_dir_open_obj(dsl_pool_t *dp, uint64_t ddobj,
     
     errout:
     	if (dd->dd_parent)
    -		dsl_dir_close(dd->dd_parent, dd);
    +		dsl_dir_rele(dd->dd_parent, dd);
     	mutex_destroy(&dd->dd_lock);
     	kmem_free(dd, sizeof (dsl_dir_t));
     	dmu_buf_rele(dbuf, tag);
    @@ -193,7 +190,7 @@ errout:
     }
     
     void
    -dsl_dir_close(dsl_dir_t *dd, void *tag)
    +dsl_dir_rele(dsl_dir_t *dd, void *tag)
     {
     	dprintf_dd(dd, "%s\n", "");
     	spa_close(dd->dd_pool->dp_spa, tag);
    @@ -250,6 +247,7 @@ static int
     getcomponent(const char *path, char *component, const char **nextp)
     {
     	char *p;
    +
     	if ((path == NULL) || (path[0] == '\0'))
     		return (ENOENT);
     	/* This would be a good place to reserve some namespace... */
    @@ -272,10 +270,10 @@ getcomponent(const char *path, char *component, const char **nextp)
     		(void) strcpy(component, path);
     		p = NULL;
     	} else if (p[0] == '/') {
    -		if (p-path >= MAXNAMELEN)
    +		if (p - path >= MAXNAMELEN)
     			return (ENAMETOOLONG);
     		(void) strncpy(component, path, p - path);
    -		component[p-path] = '\0';
    +		component[p - path] = '\0';
     		p++;
     	} else if (p[0] == '@') {
     		/*
    @@ -284,65 +282,54 @@ getcomponent(const char *path, char *component, const char **nextp)
     		 */
     		if (strchr(path, '/'))
     			return (EINVAL);
    -		if (p-path >= MAXNAMELEN)
    +		if (p - path >= MAXNAMELEN)
     			return (ENAMETOOLONG);
     		(void) strncpy(component, path, p - path);
    -		component[p-path] = '\0';
    +		component[p - path] = '\0';
     	} else {
    -		ASSERT(!"invalid p");
    +		panic("invalid p=%p", (void *)p);
     	}
     	*nextp = p;
     	return (0);
     }
     
     /*
    - * same as dsl_open_dir, ignore the first component of name and use the
    - * spa instead
    + * Return the dsl_dir_t, and possibly the last component which couldn't
    + * be found in *tail.  The name must be in the specified dsl_pool_t.  This
    + * thread must hold the dp_config_rwlock for the pool.  Returns NULL if the
    + * path is bogus, or if tail==NULL and we couldn't parse the whole name.
    + * (*tail)[0] == '@' means that the last component is a snapshot.
      */
     int
    -dsl_dir_open_spa(spa_t *spa, const char *name, void *tag,
    +dsl_dir_hold(dsl_pool_t *dp, const char *name, void *tag,
         dsl_dir_t **ddp, const char **tailp)
     {
     	char buf[MAXNAMELEN];
    -	const char *next, *nextnext = NULL;
    +	const char *spaname, *next, *nextnext = NULL;
     	int err;
     	dsl_dir_t *dd;
    -	dsl_pool_t *dp;
     	uint64_t ddobj;
    -	int openedspa = FALSE;
    -
    -	dprintf("%s\n", name);
     
     	err = getcomponent(name, buf, &next);
    -	if (err)
    +	if (err != 0)
     		return (err);
    -	if (spa == NULL) {
    -		err = spa_open(buf, &spa, FTAG);
    -		if (err) {
    -			dprintf("spa_open(%s) failed\n", buf);
    -			return (err);
    -		}
    -		openedspa = TRUE;
     
    -		/* XXX this assertion belongs in spa_open */
    -		ASSERT(!dsl_pool_sync_context(spa_get_dsl(spa)));
    -	}
    +	/* Make sure the name is in the specified pool. */
    +	spaname = spa_name(dp->dp_spa);
    +	if (strcmp(buf, spaname) != 0)
    +		return (EINVAL);
     
    -	dp = spa_get_dsl(spa);
    +	ASSERT(dsl_pool_config_held(dp));
     
    -	rw_enter(&dp->dp_config_rwlock, RW_READER);
    -	err = dsl_dir_open_obj(dp, dp->dp_root_dir_obj, NULL, tag, &dd);
    -	if (err) {
    -		rw_exit(&dp->dp_config_rwlock);
    -		if (openedspa)
    -			spa_close(spa, FTAG);
    +	err = dsl_dir_hold_obj(dp, dp->dp_root_dir_obj, NULL, tag, &dd);
    +	if (err != 0) {
     		return (err);
     	}
     
     	while (next != NULL) {
     		dsl_dir_t *child_ds;
     		err = getcomponent(next, buf, &nextnext);
    -		if (err)
    +		if (err != 0)
     			break;
     		ASSERT(next[0] != '\0');
     		if (next[0] == '@')
    @@ -353,25 +340,22 @@ dsl_dir_open_spa(spa_t *spa, const char *name, void *tag,
     		err = zap_lookup(dp->dp_meta_objset,
     		    dd->dd_phys->dd_child_dir_zapobj,
     		    buf, sizeof (ddobj), 1, &ddobj);
    -		if (err) {
    +		if (err != 0) {
     			if (err == ENOENT)
     				err = 0;
     			break;
     		}
     
    -		err = dsl_dir_open_obj(dp, ddobj, buf, tag, &child_ds);
    -		if (err)
    +		err = dsl_dir_hold_obj(dp, ddobj, buf, tag, &child_ds);
    +		if (err != 0)
     			break;
    -		dsl_dir_close(dd, tag);
    +		dsl_dir_rele(dd, tag);
     		dd = child_ds;
     		next = nextnext;
     	}
    -	rw_exit(&dp->dp_config_rwlock);
     
    -	if (err) {
    -		dsl_dir_close(dd, tag);
    -		if (openedspa)
    -			spa_close(spa, FTAG);
    +	if (err != 0) {
    +		dsl_dir_rele(dd, tag);
     		return (err);
     	}
     
    @@ -382,30 +366,16 @@ dsl_dir_open_spa(spa_t *spa, const char *name, void *tag,
     	if (next != NULL &&
     	    (tailp == NULL || (nextnext && nextnext[0] != '\0'))) {
     		/* bad path name */
    -		dsl_dir_close(dd, tag);
    +		dsl_dir_rele(dd, tag);
     		dprintf("next=%p (%s) tail=%p\n", next, next?next:"", tailp);
     		err = ENOENT;
     	}
    -	if (tailp)
    +	if (tailp != NULL)
     		*tailp = next;
    -	if (openedspa)
    -		spa_close(spa, FTAG);
     	*ddp = dd;
     	return (err);
     }
     
    -/*
    - * Return the dsl_dir_t, and possibly the last component which couldn't
    - * be found in *tail.  Return NULL if the path is bogus, or if
    - * tail==NULL and we couldn't parse the whole name.  (*tail)[0] == '@'
    - * means that the last component is a snapshot.
    - */
    -int
    -dsl_dir_open(const char *name, void *tag, dsl_dir_t **ddp, const char **tailp)
    -{
    -	return (dsl_dir_open_spa(NULL, name, tag, ddp, tailp));
    -}
    -
     uint64_t
     dsl_dir_create_sync(dsl_pool_t *dp, dsl_dir_t *pds, const char *name,
         dmu_tx_t *tx)
    @@ -443,71 +413,6 @@ dsl_dir_create_sync(dsl_pool_t *dp, dsl_dir_t *pds, const char *name,
     	return (ddobj);
     }
     
    -/* ARGSUSED */
    -int
    -dsl_dir_destroy_check(void *arg1, void *arg2, dmu_tx_t *tx)
    -{
    -	dsl_dir_t *dd = arg1;
    -	dsl_pool_t *dp = dd->dd_pool;
    -	objset_t *mos = dp->dp_meta_objset;
    -	int err;
    -	uint64_t count;
    -
    -	/*
    -	 * There should be exactly two holds, both from
    -	 * dsl_dataset_destroy: one on the dd directory, and one on its
    -	 * head ds.  If there are more holds, then a concurrent thread is
    -	 * performing a lookup inside this dir while we're trying to destroy
    -	 * it.  To minimize this possibility, we perform this check only
    -	 * in syncing context and fail the operation if we encounter
    -	 * additional holds.  The dp_config_rwlock ensures that nobody else
    -	 * opens it after we check.
    -	 */
    -	if (dmu_tx_is_syncing(tx) && dmu_buf_refcount(dd->dd_dbuf) > 2)
    -		return (EBUSY);
    -
    -	err = zap_count(mos, dd->dd_phys->dd_child_dir_zapobj, &count);
    -	if (err)
    -		return (err);
    -	if (count != 0)
    -		return (EEXIST);
    -
    -	return (0);
    -}
    -
    -void
    -dsl_dir_destroy_sync(void *arg1, void *tag, dmu_tx_t *tx)
    -{
    -	dsl_dir_t *dd = arg1;
    -	objset_t *mos = dd->dd_pool->dp_meta_objset;
    -	uint64_t obj;
    -	dd_used_t t;
    -
    -	ASSERT(RW_WRITE_HELD(&dd->dd_pool->dp_config_rwlock));
    -	ASSERT(dd->dd_phys->dd_head_dataset_obj == 0);
    -
    -	/*
    -	 * Remove our reservation. The impl() routine avoids setting the
    -	 * actual property, which would require the (already destroyed) ds.
    -	 */
    -	dsl_dir_set_reservation_sync_impl(dd, 0, tx);
    -
    -	ASSERT0(dd->dd_phys->dd_used_bytes);
    -	ASSERT0(dd->dd_phys->dd_reserved);
    -	for (t = 0; t < DD_USED_NUM; t++)
    -		ASSERT0(dd->dd_phys->dd_used_breakdown[t]);
    -
    -	VERIFY(0 == zap_destroy(mos, dd->dd_phys->dd_child_dir_zapobj, tx));
    -	VERIFY(0 == zap_destroy(mos, dd->dd_phys->dd_props_zapobj, tx));
    -	VERIFY(0 == dsl_deleg_destroy(mos, dd->dd_phys->dd_deleg_zapobj, tx));
    -	VERIFY(0 == zap_remove(mos,
    -	    dd->dd_parent->dd_phys->dd_child_dir_zapobj, dd->dd_myname, tx));
    -
    -	obj = dd->dd_object;
    -	dsl_dir_close(dd, tag);
    -	VERIFY(0 == dmu_object_free(mos, obj, tx));
    -}
    -
     boolean_t
     dsl_dir_is_clone(dsl_dir_t *dd)
     {
    @@ -545,18 +450,16 @@ dsl_dir_stats(dsl_dir_t *dd, nvlist_t *nv)
     	}
     	mutex_exit(&dd->dd_lock);
     
    -	rw_enter(&dd->dd_pool->dp_config_rwlock, RW_READER);
     	if (dsl_dir_is_clone(dd)) {
     		dsl_dataset_t *ds;
     		char buf[MAXNAMELEN];
     
    -		VERIFY(0 == dsl_dataset_hold_obj(dd->dd_pool,
    +		VERIFY0(dsl_dataset_hold_obj(dd->dd_pool,
     		    dd->dd_phys->dd_origin_obj, FTAG, &ds));
     		dsl_dataset_name(ds, buf);
     		dsl_dataset_rele(ds, FTAG);
     		dsl_prop_nvlist_add_string(nv, ZFS_PROP_ORIGIN, buf);
     	}
    -	rw_exit(&dd->dd_pool->dp_config_rwlock);
     }
     
     void
    @@ -566,7 +469,7 @@ dsl_dir_dirty(dsl_dir_t *dd, dmu_tx_t *tx)
     
     	ASSERT(dd->dd_phys);
     
    -	if (txg_list_add(&dp->dp_dirty_dirs, dd, tx->tx_txg) == 0) {
    +	if (txg_list_add(&dp->dp_dirty_dirs, dd, tx->tx_txg)) {
     		/* up the hold count until we can be written out */
     		dmu_buf_add_ref(dd->dd_dbuf, dd);
     	}
    @@ -853,7 +756,7 @@ dsl_dir_tempreserve_space(dsl_dir_t *dd, uint64_t lsize, uint64_t asize,
     		    FALSE, asize > usize, tr_list, tx, TRUE);
     	}
     
    -	if (err)
    +	if (err != 0)
     		dsl_dir_tempreserve_clear(tr_list, tx);
     	else
     		*tr_cookiep = tr_list;
    @@ -1004,115 +907,123 @@ dsl_dir_transfer_space(dsl_dir_t *dd, int64_t delta,
     		mutex_exit(&dd->dd_lock);
     }
     
    +typedef struct dsl_dir_set_qr_arg {
    +	const char *ddsqra_name;
    +	zprop_source_t ddsqra_source;
    +	uint64_t ddsqra_value;
    +} dsl_dir_set_qr_arg_t;
    +
     static int
    -dsl_dir_set_quota_check(void *arg1, void *arg2, dmu_tx_t *tx)
    +dsl_dir_set_quota_check(void *arg, dmu_tx_t *tx)
     {
    -	dsl_dataset_t *ds = arg1;
    -	dsl_dir_t *dd = ds->ds_dir;
    -	dsl_prop_setarg_t *psa = arg2;
    -	int err;
    -	uint64_t towrite;
    +	dsl_dir_set_qr_arg_t *ddsqra = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	dsl_dataset_t *ds;
    +	int error;
    +	uint64_t towrite, newval;
     
    -	if ((err = dsl_prop_predict_sync(ds->ds_dir, psa)) != 0)
    -		return (err);
    +	error = dsl_dataset_hold(dp, ddsqra->ddsqra_name, FTAG, &ds);
    +	if (error != 0)
    +		return (error);
     
    -	if (psa->psa_effective_value == 0)
    +	error = dsl_prop_predict(ds->ds_dir, "quota",
    +	    ddsqra->ddsqra_source, ddsqra->ddsqra_value, &newval);
    +	if (error != 0) {
    +		dsl_dataset_rele(ds, FTAG);
    +		return (error);
    +	}
    +
    +	if (newval == 0) {
    +		dsl_dataset_rele(ds, FTAG);
     		return (0);
    +	}
     
    -	mutex_enter(&dd->dd_lock);
    +	mutex_enter(&ds->ds_dir->dd_lock);
     	/*
     	 * If we are doing the preliminary check in open context, and
     	 * there are pending changes, then don't fail it, since the
     	 * pending changes could under-estimate the amount of space to be
     	 * freed up.
     	 */
    -	towrite = dsl_dir_space_towrite(dd);
    +	towrite = dsl_dir_space_towrite(ds->ds_dir);
     	if ((dmu_tx_is_syncing(tx) || towrite == 0) &&
    -	    (psa->psa_effective_value < dd->dd_phys->dd_reserved ||
    -	    psa->psa_effective_value < dd->dd_phys->dd_used_bytes + towrite)) {
    -		err = ENOSPC;
    +	    (newval < ds->ds_dir->dd_phys->dd_reserved ||
    +	    newval < ds->ds_dir->dd_phys->dd_used_bytes + towrite)) {
    +		error = ENOSPC;
     	}
    -	mutex_exit(&dd->dd_lock);
    -	return (err);
    +	mutex_exit(&ds->ds_dir->dd_lock);
    +	dsl_dataset_rele(ds, FTAG);
    +	return (error);
     }
     
    -extern dsl_syncfunc_t dsl_prop_set_sync;
    -
     static void
    -dsl_dir_set_quota_sync(void *arg1, void *arg2, dmu_tx_t *tx)
    +dsl_dir_set_quota_sync(void *arg, dmu_tx_t *tx)
     {
    -	dsl_dataset_t *ds = arg1;
    -	dsl_dir_t *dd = ds->ds_dir;
    -	dsl_prop_setarg_t *psa = arg2;
    -	uint64_t effective_value = psa->psa_effective_value;
    +	dsl_dir_set_qr_arg_t *ddsqra = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	dsl_dataset_t *ds;
    +	uint64_t newval;
     
    -	dsl_prop_set_sync(ds, psa, tx);
    -	DSL_PROP_CHECK_PREDICTION(dd, psa);
    +	VERIFY0(dsl_dataset_hold(dp, ddsqra->ddsqra_name, FTAG, &ds));
     
    -	dmu_buf_will_dirty(dd->dd_dbuf, tx);
    +	dsl_prop_set_sync_impl(ds, zfs_prop_to_name(ZFS_PROP_QUOTA),
    +	    ddsqra->ddsqra_source, sizeof (ddsqra->ddsqra_value), 1,
    +	    &ddsqra->ddsqra_value, tx);
     
    -	mutex_enter(&dd->dd_lock);
    -	dd->dd_phys->dd_quota = effective_value;
    -	mutex_exit(&dd->dd_lock);
    +	VERIFY0(dsl_prop_get_int_ds(ds,
    +	    zfs_prop_to_name(ZFS_PROP_QUOTA), &newval));
    +
    +	dmu_buf_will_dirty(ds->ds_dir->dd_dbuf, tx);
    +	mutex_enter(&ds->ds_dir->dd_lock);
    +	ds->ds_dir->dd_phys->dd_quota = newval;
    +	mutex_exit(&ds->ds_dir->dd_lock);
    +	dsl_dataset_rele(ds, FTAG);
     }
     
     int
     dsl_dir_set_quota(const char *ddname, zprop_source_t source, uint64_t quota)
     {
    -	dsl_dir_t *dd;
    -	dsl_dataset_t *ds;
    -	dsl_prop_setarg_t psa;
    -	int err;
    +	dsl_dir_set_qr_arg_t ddsqra;
     
    -	dsl_prop_setarg_init_uint64(&psa, "quota", source, "a);
    +	ddsqra.ddsqra_name = ddname;
    +	ddsqra.ddsqra_source = source;
    +	ddsqra.ddsqra_value = quota;
     
    -	err = dsl_dataset_hold(ddname, FTAG, &ds);
    -	if (err)
    -		return (err);
    -
    -	err = dsl_dir_open(ddname, FTAG, &dd, NULL);
    -	if (err) {
    -		dsl_dataset_rele(ds, FTAG);
    -		return (err);
    -	}
    -
    -	ASSERT(ds->ds_dir == dd);
    -
    -	/*
    -	 * If someone removes a file, then tries to set the quota, we want to
    -	 * make sure the file freeing takes effect.
    -	 */
    -	txg_wait_open(dd->dd_pool, 0);
    -
    -	err = dsl_sync_task_do(dd->dd_pool, dsl_dir_set_quota_check,
    -	    dsl_dir_set_quota_sync, ds, &psa, 0);
    -
    -	dsl_dir_close(dd, FTAG);
    -	dsl_dataset_rele(ds, FTAG);
    -	return (err);
    +	return (dsl_sync_task(ddname, dsl_dir_set_quota_check,
    +	    dsl_dir_set_quota_sync, &ddsqra, 0));
     }
     
     int
    -dsl_dir_set_reservation_check(void *arg1, void *arg2, dmu_tx_t *tx)
    +dsl_dir_set_reservation_check(void *arg, dmu_tx_t *tx)
     {
    -	dsl_dataset_t *ds = arg1;
    -	dsl_dir_t *dd = ds->ds_dir;
    -	dsl_prop_setarg_t *psa = arg2;
    -	uint64_t effective_value;
    -	uint64_t used, avail;
    -	int err;
    +	dsl_dir_set_qr_arg_t *ddsqra = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	dsl_dataset_t *ds;
    +	dsl_dir_t *dd;
    +	uint64_t newval, used, avail;
    +	int error;
     
    -	if ((err = dsl_prop_predict_sync(ds->ds_dir, psa)) != 0)
    -		return (err);
    -
    -	effective_value = psa->psa_effective_value;
    +	error = dsl_dataset_hold(dp, ddsqra->ddsqra_name, FTAG, &ds);
    +	if (error != 0)
    +		return (error);
    +	dd = ds->ds_dir;
     
     	/*
     	 * If we are doing the preliminary check in open context, the
     	 * space estimates may be inaccurate.
     	 */
    -	if (!dmu_tx_is_syncing(tx))
    +	if (!dmu_tx_is_syncing(tx)) {
    +		dsl_dataset_rele(ds, FTAG);
     		return (0);
    +	}
    +
    +	error = dsl_prop_predict(ds->ds_dir,
    +	    zfs_prop_to_name(ZFS_PROP_RESERVATION),
    +	    ddsqra->ddsqra_source, ddsqra->ddsqra_value, &newval);
    +	if (error != 0) {
    +		dsl_dataset_rele(ds, FTAG);
    +		return (error);
    +	}
     
     	mutex_enter(&dd->dd_lock);
     	used = dd->dd_phys->dd_used_bytes;
    @@ -1125,21 +1036,21 @@ dsl_dir_set_reservation_check(void *arg1, void *arg2, dmu_tx_t *tx)
     		avail = dsl_pool_adjustedsize(dd->dd_pool, B_FALSE) - used;
     	}
     
    -	if (MAX(used, effective_value) > MAX(used, dd->dd_phys->dd_reserved)) {
    -		uint64_t delta = MAX(used, effective_value) -
    +	if (MAX(used, newval) > MAX(used, dd->dd_phys->dd_reserved)) {
    +		uint64_t delta = MAX(used, newval) -
     		    MAX(used, dd->dd_phys->dd_reserved);
     
    -		if (delta > avail)
    -			return (ENOSPC);
    -		if (dd->dd_phys->dd_quota > 0 &&
    -		    effective_value > dd->dd_phys->dd_quota)
    -			return (ENOSPC);
    +		if (delta > avail ||
    +		    (dd->dd_phys->dd_quota > 0 &&
    +		    newval > dd->dd_phys->dd_quota))
    +			error = ENOSPC;
     	}
     
    -	return (0);
    +	dsl_dataset_rele(ds, FTAG);
    +	return (error);
     }
     
    -static void
    +void
     dsl_dir_set_reservation_sync_impl(dsl_dir_t *dd, uint64_t value, dmu_tx_t *tx)
     {
     	uint64_t used;
    @@ -1162,48 +1073,38 @@ dsl_dir_set_reservation_sync_impl(dsl_dir_t *dd, uint64_t value, dmu_tx_t *tx)
     
     
     static void
    -dsl_dir_set_reservation_sync(void *arg1, void *arg2, dmu_tx_t *tx)
    +dsl_dir_set_reservation_sync(void *arg, dmu_tx_t *tx)
     {
    -	dsl_dataset_t *ds = arg1;
    -	dsl_dir_t *dd = ds->ds_dir;
    -	dsl_prop_setarg_t *psa = arg2;
    -	uint64_t value = psa->psa_effective_value;
    +	dsl_dir_set_qr_arg_t *ddsqra = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	dsl_dataset_t *ds;
    +	uint64_t newval;
     
    -	dsl_prop_set_sync(ds, psa, tx);
    -	DSL_PROP_CHECK_PREDICTION(dd, psa);
    +	VERIFY0(dsl_dataset_hold(dp, ddsqra->ddsqra_name, FTAG, &ds));
     
    -	dsl_dir_set_reservation_sync_impl(dd, value, tx);
    +	dsl_prop_set_sync_impl(ds, zfs_prop_to_name(ZFS_PROP_RESERVATION),
    +	    ddsqra->ddsqra_source, sizeof (ddsqra->ddsqra_value), 1,
    +	    &ddsqra->ddsqra_value, tx);
    +
    +	VERIFY0(dsl_prop_get_int_ds(ds,
    +	    zfs_prop_to_name(ZFS_PROP_RESERVATION), &newval));
    +
    +	dsl_dir_set_reservation_sync_impl(ds->ds_dir, newval, tx);
    +	dsl_dataset_rele(ds, FTAG);
     }
     
     int
     dsl_dir_set_reservation(const char *ddname, zprop_source_t source,
         uint64_t reservation)
     {
    -	dsl_dir_t *dd;
    -	dsl_dataset_t *ds;
    -	dsl_prop_setarg_t psa;
    -	int err;
    +	dsl_dir_set_qr_arg_t ddsqra;
     
    -	dsl_prop_setarg_init_uint64(&psa, "reservation", source, &reservation);
    +	ddsqra.ddsqra_name = ddname;
    +	ddsqra.ddsqra_source = source;
    +	ddsqra.ddsqra_value = reservation;
     
    -	err = dsl_dataset_hold(ddname, FTAG, &ds);
    -	if (err)
    -		return (err);
    -
    -	err = dsl_dir_open(ddname, FTAG, &dd, NULL);
    -	if (err) {
    -		dsl_dataset_rele(ds, FTAG);
    -		return (err);
    -	}
    -
    -	ASSERT(ds->ds_dir == dd);
    -
    -	err = dsl_sync_task_do(dd->dd_pool, dsl_dir_set_reservation_check,
    -	    dsl_dir_set_reservation_sync, ds, &psa, 0);
    -
    -	dsl_dir_close(dd, FTAG);
    -	dsl_dataset_rele(ds, FTAG);
    -	return (err);
    +	return (dsl_sync_task(ddname, dsl_dir_set_reservation_check,
    +	    dsl_dir_set_reservation_sync, &ddsqra, 0));
     }
     
     static dsl_dir_t *
    @@ -1235,79 +1136,123 @@ would_change(dsl_dir_t *dd, int64_t delta, dsl_dir_t *ancestor)
     	return (would_change(dd->dd_parent, delta, ancestor));
     }
     
    -struct renamearg {
    -	dsl_dir_t *newparent;
    -	const char *mynewname;
    -};
    +typedef struct dsl_dir_rename_arg {
    +	const char *ddra_oldname;
    +	const char *ddra_newname;
    +} dsl_dir_rename_arg_t;
    +
    +/* ARGSUSED */
    +static int
    +dsl_valid_rename(dsl_pool_t *dp, dsl_dataset_t *ds, void *arg)
    +{
    +	int *deltap = arg;
    +	char namebuf[MAXNAMELEN];
    +
    +	dsl_dataset_name(ds, namebuf);
    +
    +	if (strlen(namebuf) + *deltap >= MAXNAMELEN)
    +		return (ENAMETOOLONG);
    +	return (0);
    +}
     
     static int
    -dsl_dir_rename_check(void *arg1, void *arg2, dmu_tx_t *tx)
    +dsl_dir_rename_check(void *arg, dmu_tx_t *tx)
     {
    -	dsl_dir_t *dd = arg1;
    -	struct renamearg *ra = arg2;
    -	dsl_pool_t *dp = dd->dd_pool;
    -	objset_t *mos = dp->dp_meta_objset;
    -	int err;
    -	uint64_t val;
    +	dsl_dir_rename_arg_t *ddra = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	dsl_dir_t *dd, *newparent;
    +	const char *mynewname;
    +	int error;
    +	int delta = strlen(ddra->ddra_newname) - strlen(ddra->ddra_oldname);
     
    -	/*
    -	 * There should only be one reference, from dmu_objset_rename().
    -	 * Fleeting holds are also possible (eg, from "zfs list" getting
    -	 * stats), but any that are present in open context will likely
    -	 * be gone by syncing context, so only fail from syncing
    -	 * context.
    -	 */
    -	if (dmu_tx_is_syncing(tx) && dmu_buf_refcount(dd->dd_dbuf) > 1)
    -		return (EBUSY);
    +	/* target dir should exist */
    +	error = dsl_dir_hold(dp, ddra->ddra_oldname, FTAG, &dd, NULL);
    +	if (error != 0)
    +		return (error);
     
    -	/* check for existing name */
    -	err = zap_lookup(mos, ra->newparent->dd_phys->dd_child_dir_zapobj,
    -	    ra->mynewname, 8, 1, &val);
    -	if (err == 0)
    +	/* new parent should exist */
    +	error = dsl_dir_hold(dp, ddra->ddra_newname, FTAG,
    +	    &newparent, &mynewname);
    +	if (error != 0) {
    +		dsl_dir_rele(dd, FTAG);
    +		return (error);
    +	}
    +
    +	/* can't rename to different pool */
    +	if (dd->dd_pool != newparent->dd_pool) {
    +		dsl_dir_rele(newparent, FTAG);
    +		dsl_dir_rele(dd, FTAG);
    +		return (ENXIO);
    +	}
    +
    +	/* new name should not already exist */
    +	if (mynewname == NULL) {
    +		dsl_dir_rele(newparent, FTAG);
    +		dsl_dir_rele(dd, FTAG);
     		return (EEXIST);
    -	if (err != ENOENT)
    -		return (err);
    +	}
     
    -	if (ra->newparent != dd->dd_parent) {
    +	/* if the name length is growing, validate child name lengths */
    +	if (delta > 0) {
    +		error = dmu_objset_find_dp(dp, dd->dd_object, dsl_valid_rename,
    +		    &delta, DS_FIND_CHILDREN | DS_FIND_SNAPSHOTS);
    +		if (error != 0) {
    +			dsl_dir_rele(newparent, FTAG);
    +			dsl_dir_rele(dd, FTAG);
    +			return (error);
    +		}
    +	}
    +
    +	if (newparent != dd->dd_parent) {
     		/* is there enough space? */
     		uint64_t myspace =
     		    MAX(dd->dd_phys->dd_used_bytes, dd->dd_phys->dd_reserved);
     
     		/* no rename into our descendant */
    -		if (closest_common_ancestor(dd, ra->newparent) == dd)
    +		if (closest_common_ancestor(dd, newparent) == dd) {
    +			dsl_dir_rele(newparent, FTAG);
    +			dsl_dir_rele(dd, FTAG);
     			return (EINVAL);
    +		}
     
    -		if (err = dsl_dir_transfer_possible(dd->dd_parent,
    -		    ra->newparent, myspace))
    -			return (err);
    +		error = dsl_dir_transfer_possible(dd->dd_parent,
    +		    newparent, myspace);
    +		if (error != 0) {
    +			dsl_dir_rele(newparent, FTAG);
    +			dsl_dir_rele(dd, FTAG);
    +			return (error);
    +		}
     	}
     
    +	dsl_dir_rele(newparent, FTAG);
    +	dsl_dir_rele(dd, FTAG);
     	return (0);
     }
     
     static void
    -dsl_dir_rename_sync(void *arg1, void *arg2, dmu_tx_t *tx)
    +dsl_dir_rename_sync(void *arg, dmu_tx_t *tx)
     {
    -	dsl_dir_t *dd = arg1;
    -	struct renamearg *ra = arg2;
    -	dsl_pool_t *dp = dd->dd_pool;
    +	dsl_dir_rename_arg_t *ddra = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	dsl_dir_t *dd, *newparent;
    +	const char *mynewname;
    +	int error;
     	objset_t *mos = dp->dp_meta_objset;
    -	int err;
    -	char namebuf[MAXNAMELEN];
     
    -	ASSERT(dmu_buf_refcount(dd->dd_dbuf) <= 2);
    +	VERIFY0(dsl_dir_hold(dp, ddra->ddra_oldname, FTAG, &dd, NULL));
    +	VERIFY0(dsl_dir_hold(dp, ddra->ddra_newname, FTAG, &newparent,
    +	    &mynewname));
     
     	/* Log this before we change the name. */
    -	dsl_dir_name(ra->newparent, namebuf);
     	spa_history_log_internal_dd(dd, "rename", tx,
    -	    "-> %s/%s", namebuf, ra->mynewname);
    +	    "-> %s", ddra->ddra_newname);
     
    -	if (ra->newparent != dd->dd_parent) {
    +	if (newparent != dd->dd_parent) {
     		dsl_dir_diduse_space(dd->dd_parent, DD_USED_CHILD,
     		    -dd->dd_phys->dd_used_bytes,
     		    -dd->dd_phys->dd_compressed_bytes,
     		    -dd->dd_phys->dd_uncompressed_bytes, tx);
    -		dsl_dir_diduse_space(ra->newparent, DD_USED_CHILD,
    +		dsl_dir_diduse_space(newparent, DD_USED_CHILD,
     		    dd->dd_phys->dd_used_bytes,
     		    dd->dd_phys->dd_compressed_bytes,
     		    dd->dd_phys->dd_uncompressed_bytes, tx);
    @@ -1318,7 +1263,7 @@ dsl_dir_rename_sync(void *arg1, void *arg2, dmu_tx_t *tx)
     
     			dsl_dir_diduse_space(dd->dd_parent, DD_USED_CHILD_RSRV,
     			    -unused_rsrv, 0, 0, tx);
    -			dsl_dir_diduse_space(ra->newparent, DD_USED_CHILD_RSRV,
    +			dsl_dir_diduse_space(newparent, DD_USED_CHILD_RSRV,
     			    unused_rsrv, 0, 0, tx);
     		}
     	}
    @@ -1326,52 +1271,36 @@ dsl_dir_rename_sync(void *arg1, void *arg2, dmu_tx_t *tx)
     	dmu_buf_will_dirty(dd->dd_dbuf, tx);
     
     	/* remove from old parent zapobj */
    -	err = zap_remove(mos, dd->dd_parent->dd_phys->dd_child_dir_zapobj,
    +	error = zap_remove(mos, dd->dd_parent->dd_phys->dd_child_dir_zapobj,
     	    dd->dd_myname, tx);
    -	ASSERT0(err);
    +	ASSERT0(error);
     
    -	(void) strcpy(dd->dd_myname, ra->mynewname);
    -	dsl_dir_close(dd->dd_parent, dd);
    -	dd->dd_phys->dd_parent_obj = ra->newparent->dd_object;
    -	VERIFY(0 == dsl_dir_open_obj(dd->dd_pool,
    -	    ra->newparent->dd_object, NULL, dd, &dd->dd_parent));
    +	(void) strcpy(dd->dd_myname, mynewname);
    +	dsl_dir_rele(dd->dd_parent, dd);
    +	dd->dd_phys->dd_parent_obj = newparent->dd_object;
    +	VERIFY0(dsl_dir_hold_obj(dp,
    +	    newparent->dd_object, NULL, dd, &dd->dd_parent));
     
     	/* add to new parent zapobj */
    -	err = zap_add(mos, ra->newparent->dd_phys->dd_child_dir_zapobj,
    -	    dd->dd_myname, 8, 1, &dd->dd_object, tx);
    -	ASSERT0(err);
    +	VERIFY0(zap_add(mos, newparent->dd_phys->dd_child_dir_zapobj,
    +	    dd->dd_myname, 8, 1, &dd->dd_object, tx));
     
    +	dsl_prop_notify_all(dd);
    +
    +	dsl_dir_rele(newparent, FTAG);
    +	dsl_dir_rele(dd, FTAG);
     }
     
     int
    -dsl_dir_rename(dsl_dir_t *dd, const char *newname)
    +dsl_dir_rename(const char *oldname, const char *newname)
     {
    -	struct renamearg ra;
    -	int err;
    +	dsl_dir_rename_arg_t ddra;
     
    -	/* new parent should exist */
    -	err = dsl_dir_open(newname, FTAG, &ra.newparent, &ra.mynewname);
    -	if (err)
    -		return (err);
    +	ddra.ddra_oldname = oldname;
    +	ddra.ddra_newname = newname;
     
    -	/* can't rename to different pool */
    -	if (dd->dd_pool != ra.newparent->dd_pool) {
    -		err = ENXIO;
    -		goto out;
    -	}
    -
    -	/* new name should not already exist */
    -	if (ra.mynewname == NULL) {
    -		err = EEXIST;
    -		goto out;
    -	}
    -
    -	err = dsl_sync_task_do(dd->dd_pool,
    -	    dsl_dir_rename_check, dsl_dir_rename_sync, dd, &ra, 3);
    -
    -out:
    -	dsl_dir_close(ra.newparent, FTAG);
    -	return (err);
    +	return (dsl_sync_task(oldname,
    +	    dsl_dir_rename_check, dsl_dir_rename_sync, &ddra, 3));
     }
     
     int
    diff --git a/uts/common/fs/zfs/dsl_pool.c b/uts/common/fs/zfs/dsl_pool.c
    index 38d656a43be..6af631679e9 100644
    --- a/uts/common/fs/zfs/dsl_pool.c
    +++ b/uts/common/fs/zfs/dsl_pool.c
    @@ -43,6 +43,7 @@
     #include 
     #include 
     #include 
    +#include 
     
     int zfs_no_write_throttle = 0;
     int zfs_write_limit_shift = 3;			/* 1/8th of physical memory */
    @@ -69,7 +70,7 @@ dsl_pool_open_special_dir(dsl_pool_t *dp, const char *name, dsl_dir_t **ddp)
     	if (err)
     		return (err);
     
    -	return (dsl_dir_open_obj(dp, obj, name, dp, ddp));
    +	return (dsl_dir_hold_obj(dp, obj, name, dp, ddp));
     }
     
     static dsl_pool_t *
    @@ -81,7 +82,7 @@ dsl_pool_open_impl(spa_t *spa, uint64_t txg)
     	dp = kmem_zalloc(sizeof (dsl_pool_t), KM_SLEEP);
     	dp->dp_spa = spa;
     	dp->dp_meta_rootbp = *bp;
    -	rw_init(&dp->dp_config_rwlock, NULL, RW_DEFAULT, NULL);
    +	rrw_init(&dp->dp_config_rwlock, B_TRUE);
     	dp->dp_write_limit = zfs_write_limit_min;
     	txg_init(dp, txg);
     
    @@ -92,7 +93,7 @@ dsl_pool_open_impl(spa_t *spa, uint64_t txg)
     	txg_list_create(&dp->dp_dirty_dirs,
     	    offsetof(dsl_dir_t, dd_dirty_link));
     	txg_list_create(&dp->dp_sync_tasks,
    -	    offsetof(dsl_sync_task_group_t, dstg_node));
    +	    offsetof(dsl_sync_task_t, dst_node));
     
     	mutex_init(&dp->dp_lock, NULL, MUTEX_DEFAULT, NULL);
     
    @@ -126,14 +127,14 @@ dsl_pool_open(dsl_pool_t *dp)
     	dsl_dataset_t *ds;
     	uint64_t obj;
     
    -	rw_enter(&dp->dp_config_rwlock, RW_WRITER);
    +	rrw_enter(&dp->dp_config_rwlock, RW_WRITER, FTAG);
     	err = zap_lookup(dp->dp_meta_objset, DMU_POOL_DIRECTORY_OBJECT,
     	    DMU_POOL_ROOT_DATASET, sizeof (uint64_t), 1,
     	    &dp->dp_root_dir_obj);
     	if (err)
     		goto out;
     
    -	err = dsl_dir_open_obj(dp, dp->dp_root_dir_obj,
    +	err = dsl_dir_hold_obj(dp, dp->dp_root_dir_obj,
     	    NULL, dp, &dp->dp_root_dir);
     	if (err)
     		goto out;
    @@ -154,7 +155,7 @@ dsl_pool_open(dsl_pool_t *dp)
     			    &dp->dp_origin_snap);
     			dsl_dataset_rele(ds, FTAG);
     		}
    -		dsl_dir_close(dd, dp);
    +		dsl_dir_rele(dd, dp);
     		if (err)
     			goto out;
     	}
    @@ -169,7 +170,7 @@ dsl_pool_open(dsl_pool_t *dp)
     		    DMU_POOL_FREE_BPOBJ, sizeof (uint64_t), 1, &obj);
     		if (err)
     			goto out;
    -		VERIFY3U(0, ==, bpobj_open(&dp->dp_free_bpobj,
    +		VERIFY0(bpobj_open(&dp->dp_free_bpobj,
     		    dp->dp_meta_objset, obj));
     	}
     
    @@ -202,7 +203,7 @@ dsl_pool_open(dsl_pool_t *dp)
     	err = dsl_scan_init(dp, dp->dp_tx.tx_open_txg);
     
     out:
    -	rw_exit(&dp->dp_config_rwlock);
    +	rrw_exit(&dp->dp_config_rwlock, FTAG);
     	return (err);
     }
     
    @@ -217,13 +218,13 @@ dsl_pool_close(dsl_pool_t *dp)
     	 * and not a hold, so just drop that here.
     	 */
     	if (dp->dp_origin_snap)
    -		dsl_dataset_drop_ref(dp->dp_origin_snap, dp);
    +		dsl_dataset_rele(dp->dp_origin_snap, dp);
     	if (dp->dp_mos_dir)
    -		dsl_dir_close(dp->dp_mos_dir, dp);
    +		dsl_dir_rele(dp->dp_mos_dir, dp);
     	if (dp->dp_free_dir)
    -		dsl_dir_close(dp->dp_free_dir, dp);
    +		dsl_dir_rele(dp->dp_free_dir, dp);
     	if (dp->dp_root_dir)
    -		dsl_dir_close(dp->dp_root_dir, dp);
    +		dsl_dir_rele(dp->dp_root_dir, dp);
     
     	bpobj_close(&dp->dp_free_bpobj);
     
    @@ -239,7 +240,7 @@ dsl_pool_close(dsl_pool_t *dp)
     	arc_flush(dp->dp_spa);
     	txg_fini(dp);
     	dsl_scan_fini(dp);
    -	rw_destroy(&dp->dp_config_rwlock);
    +	rrw_destroy(&dp->dp_config_rwlock);
     	mutex_destroy(&dp->dp_lock);
     	taskq_destroy(dp->dp_vnrele_taskq);
     	if (dp->dp_blkstats)
    @@ -257,6 +258,8 @@ dsl_pool_create(spa_t *spa, nvlist_t *zplprops, uint64_t txg)
     	dsl_dataset_t *ds;
     	uint64_t obj;
     
    +	rrw_enter(&dp->dp_config_rwlock, RW_WRITER, FTAG);
    +
     	/* create and open the MOS (meta-objset) */
     	dp->dp_meta_objset = dmu_objset_create_impl(spa,
     	    NULL, &dp->dp_meta_rootbp, DMU_OST_META, tx);
    @@ -267,30 +270,30 @@ dsl_pool_create(spa_t *spa, nvlist_t *zplprops, uint64_t txg)
     	ASSERT0(err);
     
     	/* Initialize scan structures */
    -	VERIFY3U(0, ==, dsl_scan_init(dp, txg));
    +	VERIFY0(dsl_scan_init(dp, txg));
     
     	/* create and open the root dir */
     	dp->dp_root_dir_obj = dsl_dir_create_sync(dp, NULL, NULL, tx);
    -	VERIFY(0 == dsl_dir_open_obj(dp, dp->dp_root_dir_obj,
    +	VERIFY0(dsl_dir_hold_obj(dp, dp->dp_root_dir_obj,
     	    NULL, dp, &dp->dp_root_dir));
     
     	/* create and open the meta-objset dir */
     	(void) dsl_dir_create_sync(dp, dp->dp_root_dir, MOS_DIR_NAME, tx);
    -	VERIFY(0 == dsl_pool_open_special_dir(dp,
    +	VERIFY0(dsl_pool_open_special_dir(dp,
     	    MOS_DIR_NAME, &dp->dp_mos_dir));
     
     	if (spa_version(spa) >= SPA_VERSION_DEADLISTS) {
     		/* create and open the free dir */
     		(void) dsl_dir_create_sync(dp, dp->dp_root_dir,
     		    FREE_DIR_NAME, tx);
    -		VERIFY(0 == dsl_pool_open_special_dir(dp,
    +		VERIFY0(dsl_pool_open_special_dir(dp,
     		    FREE_DIR_NAME, &dp->dp_free_dir));
     
     		/* create and open the free_bplist */
     		obj = bpobj_alloc(dp->dp_meta_objset, SPA_MAXBLOCKSIZE, tx);
     		VERIFY(zap_add(dp->dp_meta_objset, DMU_POOL_DIRECTORY_OBJECT,
     		    DMU_POOL_FREE_BPOBJ, sizeof (uint64_t), 1, &obj, tx) == 0);
    -		VERIFY3U(0, ==, bpobj_open(&dp->dp_free_bpobj,
    +		VERIFY0(bpobj_open(&dp->dp_free_bpobj,
     		    dp->dp_meta_objset, obj));
     	}
     
    @@ -301,7 +304,7 @@ dsl_pool_create(spa_t *spa, nvlist_t *zplprops, uint64_t txg)
     	obj = dsl_dataset_create_sync_dd(dp->dp_root_dir, NULL, 0, tx);
     
     	/* create the root objset */
    -	VERIFY(0 == dsl_dataset_hold_obj(dp, obj, FTAG, &ds));
    +	VERIFY0(dsl_dataset_hold_obj(dp, obj, FTAG, &ds));
     	os = dmu_objset_create_impl(dp->dp_spa, ds,
     	    dsl_dataset_get_blkptr(ds), DMU_OST_ZFS, tx);
     #ifdef _KERNEL
    @@ -311,6 +314,8 @@ dsl_pool_create(spa_t *spa, nvlist_t *zplprops, uint64_t txg)
     
     	dmu_tx_commit(tx);
     
    +	rrw_exit(&dp->dp_config_rwlock, FTAG);
    +
     	return (dp);
     }
     
    @@ -333,10 +338,7 @@ static int
     deadlist_enqueue_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx)
     {
     	dsl_deadlist_t *dl = arg;
    -	dsl_pool_t *dp = dmu_objset_pool(dl->dl_os);
    -	rw_enter(&dp->dp_config_rwlock, RW_READER);
     	dsl_deadlist_insert(dl, bp, tx);
    -	rw_exit(&dp->dp_config_rwlock);
     	return (0);
     }
     
    @@ -358,7 +360,7 @@ dsl_pool_sync(dsl_pool_t *dp, uint64_t txg)
     
     	/*
     	 * We need to copy dp_space_towrite() before doing
    -	 * dsl_sync_task_group_sync(), because
    +	 * dsl_sync_task_sync(), because
     	 * dsl_dataset_snapshot_reserve_space() will increase
     	 * dp_space_towrite but not actually write anything.
     	 */
    @@ -472,14 +474,14 @@ dsl_pool_sync(dsl_pool_t *dp, uint64_t txg)
     	 */
     	DTRACE_PROBE(pool_sync__3task);
     	if (!txg_list_empty(&dp->dp_sync_tasks, txg)) {
    -		dsl_sync_task_group_t *dstg;
    +		dsl_sync_task_t *dst;
     		/*
     		 * No more sync tasks should have been added while we
     		 * were syncing.
     		 */
     		ASSERT(spa_sync_pass(dp->dp_spa) == 1);
    -		while (dstg = txg_list_remove(&dp->dp_sync_tasks, txg))
    -			dsl_sync_task_group_sync(dstg, tx);
    +		while (dst = txg_list_remove(&dp->dp_sync_tasks, txg))
    +			dsl_sync_task_sync(dst, tx);
     	}
     
     	dmu_tx_commit(tx);
    @@ -654,14 +656,13 @@ dsl_pool_willuse_space(dsl_pool_t *dp, int64_t space, dmu_tx_t *tx)
     
     /* ARGSUSED */
     static int
    -upgrade_clones_cb(spa_t *spa, uint64_t dsobj, const char *dsname, void *arg)
    +upgrade_clones_cb(dsl_pool_t *dp, dsl_dataset_t *hds, void *arg)
     {
     	dmu_tx_t *tx = arg;
     	dsl_dataset_t *ds, *prev = NULL;
     	int err;
    -	dsl_pool_t *dp = spa_get_dsl(spa);
     
    -	err = dsl_dataset_hold_obj(dp, dsobj, FTAG, &ds);
    +	err = dsl_dataset_hold_obj(dp, hds->ds_object, FTAG, &ds);
     	if (err)
     		return (err);
     
    @@ -687,7 +688,7 @@ upgrade_clones_cb(spa_t *spa, uint64_t dsobj, const char *dsname, void *arg)
     		 * The $ORIGIN can't have any data, or the accounting
     		 * will be wrong.
     		 */
    -		ASSERT(prev->ds_phys->ds_bp.blk_birth == 0);
    +		ASSERT0(prev->ds_phys->ds_bp.blk_birth);
     
     		/* The origin doesn't get attached to itself */
     		if (ds->ds_object == prev->ds_object) {
    @@ -707,13 +708,13 @@ upgrade_clones_cb(spa_t *spa, uint64_t dsobj, const char *dsname, void *arg)
     
     		if (ds->ds_phys->ds_next_snap_obj == 0) {
     			ASSERT(ds->ds_prev == NULL);
    -			VERIFY(0 == dsl_dataset_hold_obj(dp,
    +			VERIFY0(dsl_dataset_hold_obj(dp,
     			    ds->ds_phys->ds_prev_snap_obj, ds, &ds->ds_prev));
     		}
     	}
     
    -	ASSERT(ds->ds_dir->dd_phys->dd_origin_obj == prev->ds_object);
    -	ASSERT(ds->ds_phys->ds_prev_snap_obj == prev->ds_object);
    +	ASSERT3U(ds->ds_dir->dd_phys->dd_origin_obj, ==, prev->ds_object);
    +	ASSERT3U(ds->ds_phys->ds_prev_snap_obj, ==, prev->ds_object);
     
     	if (prev->ds_phys->ds_next_clones_obj == 0) {
     		dmu_buf_will_dirty(prev->ds_dbuf, tx);
    @@ -721,7 +722,7 @@ upgrade_clones_cb(spa_t *spa, uint64_t dsobj, const char *dsname, void *arg)
     		    zap_create(dp->dp_meta_objset,
     		    DMU_OT_NEXT_CLONES, DMU_OT_NONE, 0, tx);
     	}
    -	VERIFY(0 == zap_add_int(dp->dp_meta_objset,
    +	VERIFY0(zap_add_int(dp->dp_meta_objset,
     	    prev->ds_phys->ds_next_clones_obj, ds->ds_object, tx));
     
     	dsl_dataset_rele(ds, FTAG);
    @@ -736,25 +737,21 @@ dsl_pool_upgrade_clones(dsl_pool_t *dp, dmu_tx_t *tx)
     	ASSERT(dmu_tx_is_syncing(tx));
     	ASSERT(dp->dp_origin_snap != NULL);
     
    -	VERIFY3U(0, ==, dmu_objset_find_spa(dp->dp_spa, NULL, upgrade_clones_cb,
    +	VERIFY0(dmu_objset_find_dp(dp, dp->dp_root_dir_obj, upgrade_clones_cb,
     	    tx, DS_FIND_CHILDREN));
     }
     
     /* ARGSUSED */
     static int
    -upgrade_dir_clones_cb(spa_t *spa, uint64_t dsobj, const char *dsname, void *arg)
    +upgrade_dir_clones_cb(dsl_pool_t *dp, dsl_dataset_t *ds, void *arg)
     {
     	dmu_tx_t *tx = arg;
    -	dsl_dataset_t *ds;
    -	dsl_pool_t *dp = spa_get_dsl(spa);
     	objset_t *mos = dp->dp_meta_objset;
     
    -	VERIFY3U(0, ==, dsl_dataset_hold_obj(dp, dsobj, FTAG, &ds));
    -
    -	if (ds->ds_dir->dd_phys->dd_origin_obj) {
    +	if (ds->ds_dir->dd_phys->dd_origin_obj != 0) {
     		dsl_dataset_t *origin;
     
    -		VERIFY3U(0, ==, dsl_dataset_hold_obj(dp,
    +		VERIFY0(dsl_dataset_hold_obj(dp,
     		    ds->ds_dir->dd_phys->dd_origin_obj, FTAG, &origin));
     
     		if (origin->ds_dir->dd_phys->dd_clones == 0) {
    @@ -763,13 +760,11 @@ upgrade_dir_clones_cb(spa_t *spa, uint64_t dsobj, const char *dsname, void *arg)
     			    DMU_OT_DSL_CLONES, DMU_OT_NONE, 0, tx);
     		}
     
    -		VERIFY3U(0, ==, zap_add_int(dp->dp_meta_objset,
    -		    origin->ds_dir->dd_phys->dd_clones, dsobj, tx));
    +		VERIFY0(zap_add_int(dp->dp_meta_objset,
    +		    origin->ds_dir->dd_phys->dd_clones, ds->ds_object, tx));
     
     		dsl_dataset_rele(origin, FTAG);
     	}
    -
    -	dsl_dataset_rele(ds, FTAG);
     	return (0);
     }
     
    @@ -780,7 +775,7 @@ dsl_pool_upgrade_dir_clones(dsl_pool_t *dp, dmu_tx_t *tx)
     	uint64_t obj;
     
     	(void) dsl_dir_create_sync(dp, dp->dp_root_dir, FREE_DIR_NAME, tx);
    -	VERIFY(0 == dsl_pool_open_special_dir(dp,
    +	VERIFY0(dsl_pool_open_special_dir(dp,
     	    FREE_DIR_NAME, &dp->dp_free_dir));
     
     	/*
    @@ -790,12 +785,11 @@ dsl_pool_upgrade_dir_clones(dsl_pool_t *dp, dmu_tx_t *tx)
     	 */
     	obj = dmu_object_alloc(dp->dp_meta_objset, DMU_OT_BPOBJ,
     	    SPA_MAXBLOCKSIZE, DMU_OT_BPOBJ_HDR, sizeof (bpobj_phys_t), tx);
    -	VERIFY3U(0, ==, zap_add(dp->dp_meta_objset, DMU_POOL_DIRECTORY_OBJECT,
    +	VERIFY0(zap_add(dp->dp_meta_objset, DMU_POOL_DIRECTORY_OBJECT,
     	    DMU_POOL_FREE_BPOBJ, sizeof (uint64_t), 1, &obj, tx));
    -	VERIFY3U(0, ==, bpobj_open(&dp->dp_free_bpobj,
    -	    dp->dp_meta_objset, obj));
    +	VERIFY0(bpobj_open(&dp->dp_free_bpobj, dp->dp_meta_objset, obj));
     
    -	VERIFY3U(0, ==, dmu_objset_find_spa(dp->dp_spa, NULL,
    +	VERIFY0(dmu_objset_find_dp(dp, dp->dp_root_dir_obj,
     	    upgrade_dir_clones_cb, tx, DS_FIND_CHILDREN));
     }
     
    @@ -807,17 +801,16 @@ dsl_pool_create_origin(dsl_pool_t *dp, dmu_tx_t *tx)
     
     	ASSERT(dmu_tx_is_syncing(tx));
     	ASSERT(dp->dp_origin_snap == NULL);
    +	ASSERT(rrw_held(&dp->dp_config_rwlock, RW_WRITER));
     
     	/* create the origin dir, ds, & snap-ds */
    -	rw_enter(&dp->dp_config_rwlock, RW_WRITER);
     	dsobj = dsl_dataset_create_sync(dp->dp_root_dir, ORIGIN_DIR_NAME,
     	    NULL, 0, kcred, tx);
    -	VERIFY(0 == dsl_dataset_hold_obj(dp, dsobj, FTAG, &ds));
    -	dsl_dataset_snapshot_sync(ds, ORIGIN_DIR_NAME, tx);
    -	VERIFY(0 == dsl_dataset_hold_obj(dp, ds->ds_phys->ds_prev_snap_obj,
    +	VERIFY0(dsl_dataset_hold_obj(dp, dsobj, FTAG, &ds));
    +	dsl_dataset_snapshot_sync_impl(ds, ORIGIN_DIR_NAME, tx);
    +	VERIFY0(dsl_dataset_hold_obj(dp, ds->ds_phys->ds_prev_snap_obj,
     	    dp, &dp->dp_origin_snap));
     	dsl_dataset_rele(ds, FTAG);
    -	rw_exit(&dp->dp_config_rwlock);
     }
     
     taskq_t *
    @@ -852,7 +845,7 @@ dsl_pool_clean_tmp_userrefs(dsl_pool_t *dp)
     		*htag = '\0';
     		++htag;
     		dsobj = strtonum(za.za_name, NULL);
    -		(void) dsl_dataset_user_release_tmp(dp, dsobj, htag, B_FALSE);
    +		dsl_dataset_user_release_tmp(dp, dsobj, htag);
     	}
     	zap_cursor_fini(&zc);
     }
    @@ -874,7 +867,7 @@ dsl_pool_user_hold_create_obj(dsl_pool_t *dp, dmu_tx_t *tx)
     
     static int
     dsl_pool_user_hold_rele_impl(dsl_pool_t *dp, uint64_t dsobj,
    -    const char *tag, uint64_t *now, dmu_tx_t *tx, boolean_t holding)
    +    const char *tag, uint64_t now, dmu_tx_t *tx, boolean_t holding)
     {
     	objset_t *mos = dp->dp_meta_objset;
     	uint64_t zapobj = dp->dp_tmp_userrefs_obj;
    @@ -899,7 +892,7 @@ dsl_pool_user_hold_rele_impl(dsl_pool_t *dp, uint64_t dsobj,
     
     	name = kmem_asprintf("%llx-%s", (u_longlong_t)dsobj, tag);
     	if (holding)
    -		error = zap_add(mos, zapobj, name, 8, 1, now, tx);
    +		error = zap_add(mos, zapobj, name, 8, 1, &now, tx);
     	else
     		error = zap_remove(mos, zapobj, name, tx);
     	strfree(name);
    @@ -912,7 +905,7 @@ dsl_pool_user_hold_rele_impl(dsl_pool_t *dp, uint64_t dsobj,
      */
     int
     dsl_pool_user_hold(dsl_pool_t *dp, uint64_t dsobj, const char *tag,
    -    uint64_t *now, dmu_tx_t *tx)
    +    uint64_t now, dmu_tx_t *tx)
     {
     	return (dsl_pool_user_hold_rele_impl(dp, dsobj, tag, now, tx, B_TRUE));
     }
    @@ -927,3 +920,106 @@ dsl_pool_user_release(dsl_pool_t *dp, uint64_t dsobj, const char *tag,
     	return (dsl_pool_user_hold_rele_impl(dp, dsobj, tag, NULL,
     	    tx, B_FALSE));
     }
    +
    +/*
    + * DSL Pool Configuration Lock
    + *
    + * The dp_config_rwlock protects against changes to DSL state (e.g. dataset
    + * creation / destruction / rename / property setting).  It must be held for
    + * read to hold a dataset or dsl_dir.  I.e. you must call
    + * dsl_pool_config_enter() or dsl_pool_hold() before calling
    + * dsl_{dataset,dir}_hold{_obj}.  In most circumstances, the dp_config_rwlock
    + * must be held continuously until all datasets and dsl_dirs are released.
    + *
    + * The only exception to this rule is that if a "long hold" is placed on
    + * a dataset, then the dp_config_rwlock may be dropped while the dataset
    + * is still held.  The long hold will prevent the dataset from being
    + * destroyed -- the destroy will fail with EBUSY.  A long hold can be
    + * obtained by calling dsl_dataset_long_hold(), or by "owning" a dataset
    + * (by calling dsl_{dataset,objset}_{try}own{_obj}).
    + *
    + * Legitimate long-holders (including owners) should be long-running, cancelable
    + * tasks that should cause "zfs destroy" to fail.  This includes DMU
    + * consumers (i.e. a ZPL filesystem being mounted or ZVOL being open),
    + * "zfs send", and "zfs diff".  There are several other long-holders whose
    + * uses are suboptimal (e.g. "zfs promote", and zil_suspend()).
    + *
    + * The usual formula for long-holding would be:
    + * dsl_pool_hold()
    + * dsl_dataset_hold()
    + * ... perform checks ...
    + * dsl_dataset_long_hold()
    + * dsl_pool_rele()
    + * ... perform long-running task ...
    + * dsl_dataset_long_rele()
    + * dsl_dataset_rele()
    + *
    + * Note that when the long hold is released, the dataset is still held but
    + * the pool is not held.  The dataset may change arbitrarily during this time
    + * (e.g. it could be destroyed).  Therefore you shouldn't do anything to the
    + * dataset except release it.
    + *
    + * User-initiated operations (e.g. ioctls, zfs_ioc_*()) are either read-only
    + * or modifying operations.
    + *
    + * Modifying operations should generally use dsl_sync_task().  The synctask
    + * infrastructure enforces proper locking strategy with respect to the
    + * dp_config_rwlock.  See the comment above dsl_sync_task() for details.
    + *
    + * Read-only operations will manually hold the pool, then the dataset, obtain
    + * information from the dataset, then release the pool and dataset.
    + * dmu_objset_{hold,rele}() are convenience routines that also do the pool
    + * hold/rele.
    + */
    +
    +int
    +dsl_pool_hold(const char *name, void *tag, dsl_pool_t **dp)
    +{
    +	spa_t *spa;
    +	int error;
    +
    +	error = spa_open(name, &spa, tag);
    +	if (error == 0) {
    +		*dp = spa_get_dsl(spa);
    +		dsl_pool_config_enter(*dp, tag);
    +	}
    +	return (error);
    +}
    +
    +void
    +dsl_pool_rele(dsl_pool_t *dp, void *tag)
    +{
    +	dsl_pool_config_exit(dp, tag);
    +	spa_close(dp->dp_spa, tag);
    +}
    +
    +void
    +dsl_pool_config_enter(dsl_pool_t *dp, void *tag)
    +{
    +	/*
    +	 * We use a "reentrant" reader-writer lock, but not reentrantly.
    +	 *
    +	 * The rrwlock can (with the track_all flag) track all reading threads,
    +	 * which is very useful for debugging which code path failed to release
    +	 * the lock, and for verifying that the *current* thread does hold
    +	 * the lock.
    +	 *
    +	 * (Unlike a rwlock, which knows that N threads hold it for
    +	 * read, but not *which* threads, so rw_held(RW_READER) returns TRUE
    +	 * if any thread holds it for read, even if this thread doesn't).
    +	 */
    +	ASSERT(!rrw_held(&dp->dp_config_rwlock, RW_READER));
    +	rrw_enter(&dp->dp_config_rwlock, RW_READER, tag);
    +}
    +
    +void
    +dsl_pool_config_exit(dsl_pool_t *dp, void *tag)
    +{
    +	rrw_exit(&dp->dp_config_rwlock, tag);
    +}
    +
    +boolean_t
    +dsl_pool_config_held(dsl_pool_t *dp)
    +{
    +	return (RRW_LOCK_HELD(&dp->dp_config_rwlock));
    +}
    diff --git a/uts/common/fs/zfs/dsl_prop.c b/uts/common/fs/zfs/dsl_prop.c
    index 5bbe14ff691..cd7c3ecb5f7 100644
    --- a/uts/common/fs/zfs/dsl_prop.c
    +++ b/uts/common/fs/zfs/dsl_prop.c
    @@ -82,7 +82,7 @@ dsl_prop_get_dd(dsl_dir_t *dd, const char *propname,
     	char *inheritstr;
     	char *recvdstr;
     
    -	ASSERT(RW_LOCK_HELD(&dd->dd_pool->dp_config_rwlock));
    +	ASSERT(dsl_pool_config_held(dd->dd_pool));
     
     	if (setpoint)
     		setpoint[0] = '\0';
    @@ -97,8 +97,6 @@ dsl_prop_get_dd(dsl_dir_t *dd, const char *propname,
     	 * after this loop.
     	 */
     	for (; dd != NULL; dd = dd->dd_parent) {
    -		ASSERT(RW_LOCK_HELD(&dd->dd_pool->dp_config_rwlock));
    -
     		if (dd != target || snapshot) {
     			if (!inheritable)
     				break;
    @@ -167,7 +165,7 @@ dsl_prop_get_ds(dsl_dataset_t *ds, const char *propname,
     	boolean_t snapshot;
     	uint64_t zapobj;
     
    -	ASSERT(RW_LOCK_HELD(&ds->ds_dir->dd_pool->dp_config_rwlock));
    +	ASSERT(dsl_pool_config_held(ds->ds_dir->dd_pool));
     	inheritable = (prop == ZPROP_INVAL || zfs_prop_inheritable(prop));
     	snapshot = (ds->ds_phys != NULL && dsl_dataset_is_snapshot(ds));
     	zapobj = (ds->ds_phys == NULL ? 0 : ds->ds_phys->ds_props_obj);
    @@ -235,18 +233,12 @@ dsl_prop_register(dsl_dataset_t *ds, const char *propname,
     	uint64_t value;
     	dsl_prop_cb_record_t *cbr;
     	int err;
    -	int need_rwlock;
     
    -	need_rwlock = !RW_WRITE_HELD(&dp->dp_config_rwlock);
    -	if (need_rwlock)
    -		rw_enter(&dp->dp_config_rwlock, RW_READER);
    +	ASSERT(dsl_pool_config_held(dp));
     
    -	err = dsl_prop_get_ds(ds, propname, 8, 1, &value, NULL);
    -	if (err != 0) {
    -		if (need_rwlock)
    -			rw_exit(&dp->dp_config_rwlock);
    +	err = dsl_prop_get_int_ds(ds, propname, &value);
    +	if (err != 0)
     		return (err);
    -	}
     
     	cbr = kmem_alloc(sizeof (dsl_prop_cb_record_t), KM_SLEEP);
     	cbr->cbr_ds = ds;
    @@ -259,9 +251,6 @@ dsl_prop_register(dsl_dataset_t *ds, const char *propname,
     	mutex_exit(&dd->dd_lock);
     
     	cbr->cbr_func(cbr->cbr_arg, value);
    -
    -	if (need_rwlock)
    -		rw_exit(&dp->dp_config_rwlock);
     	return (0);
     }
     
    @@ -269,19 +258,18 @@ int
     dsl_prop_get(const char *dsname, const char *propname,
         int intsz, int numints, void *buf, char *setpoint)
     {
    -	dsl_dataset_t *ds;
    -	int err;
    +	objset_t *os;
    +	int error;
     
    -	err = dsl_dataset_hold(dsname, FTAG, &ds);
    -	if (err)
    -		return (err);
    +	error = dmu_objset_hold(dsname, FTAG, &os);
    +	if (error != 0)
    +		return (error);
     
    -	rw_enter(&ds->ds_dir->dd_pool->dp_config_rwlock, RW_READER);
    -	err = dsl_prop_get_ds(ds, propname, intsz, numints, buf, setpoint);
    -	rw_exit(&ds->ds_dir->dd_pool->dp_config_rwlock);
    +	error = dsl_prop_get_ds(dmu_objset_ds(os), propname,
    +	    intsz, numints, buf, setpoint);
     
    -	dsl_dataset_rele(ds, FTAG);
    -	return (err);
    +	dmu_objset_rele(os, FTAG);
    +	return (error);
     }
     
     /*
    @@ -299,17 +287,11 @@ dsl_prop_get_integer(const char *ddname, const char *propname,
     	return (dsl_prop_get(ddname, propname, 8, 1, valuep, setpoint));
     }
     
    -void
    -dsl_prop_setarg_init_uint64(dsl_prop_setarg_t *psa, const char *propname,
    -    zprop_source_t source, uint64_t *value)
    +int
    +dsl_prop_get_int_ds(dsl_dataset_t *ds, const char *propname,
    +    uint64_t *valuep)
     {
    -	psa->psa_name = propname;
    -	psa->psa_source = source;
    -	psa->psa_intsz = 8;
    -	psa->psa_numints = 1;
    -	psa->psa_value = value;
    -
    -	psa->psa_effective_value = -1ULL;
    +	return (dsl_prop_get_ds(ds, propname, 8, 1, valuep, NULL));
     }
     
     /*
    @@ -323,11 +305,10 @@ dsl_prop_setarg_init_uint64(dsl_prop_setarg_t *psa, const char *propname,
      * a property not handled by this function.
      */
     int
    -dsl_prop_predict_sync(dsl_dir_t *dd, dsl_prop_setarg_t *psa)
    +dsl_prop_predict(dsl_dir_t *dd, const char *propname,
    +    zprop_source_t source, uint64_t value, uint64_t *newvalp)
     {
    -	const char *propname = psa->psa_name;
     	zfs_prop_t prop = zfs_name_to_prop(propname);
    -	zprop_source_t source = psa->psa_source;
     	objset_t *mos;
     	uint64_t zapobj;
     	uint64_t version;
    @@ -359,36 +340,33 @@ dsl_prop_predict_sync(dsl_dir_t *dd, dsl_prop_setarg_t *psa)
     	switch (source) {
     	case ZPROP_SRC_NONE:
     		/* Revert to the received value, if any. */
    -		err = zap_lookup(mos, zapobj, recvdstr, 8, 1,
    -		    &psa->psa_effective_value);
    +		err = zap_lookup(mos, zapobj, recvdstr, 8, 1, newvalp);
     		if (err == ENOENT)
    -			psa->psa_effective_value = 0;
    +			*newvalp = 0;
     		break;
     	case ZPROP_SRC_LOCAL:
    -		psa->psa_effective_value = *(uint64_t *)psa->psa_value;
    +		*newvalp = value;
     		break;
     	case ZPROP_SRC_RECEIVED:
     		/*
     		 * If there's no local setting, then the new received value will
     		 * be the effective value.
     		 */
    -		err = zap_lookup(mos, zapobj, propname, 8, 1,
    -		    &psa->psa_effective_value);
    +		err = zap_lookup(mos, zapobj, propname, 8, 1, newvalp);
     		if (err == ENOENT)
    -			psa->psa_effective_value = *(uint64_t *)psa->psa_value;
    +			*newvalp = value;
     		break;
     	case (ZPROP_SRC_NONE | ZPROP_SRC_RECEIVED):
     		/*
     		 * We're clearing the received value, so the local setting (if
     		 * it exists) remains the effective value.
     		 */
    -		err = zap_lookup(mos, zapobj, propname, 8, 1,
    -		    &psa->psa_effective_value);
    +		err = zap_lookup(mos, zapobj, propname, 8, 1, newvalp);
     		if (err == ENOENT)
    -			psa->psa_effective_value = 0;
    +			*newvalp = 0;
     		break;
     	default:
    -		cmn_err(CE_PANIC, "unexpected property source: %d", source);
    +		panic("unexpected property source: %d", source);
     	}
     
     	strfree(recvdstr);
    @@ -399,37 +377,6 @@ dsl_prop_predict_sync(dsl_dir_t *dd, dsl_prop_setarg_t *psa)
     	return (err);
     }
     
    -#ifdef	ZFS_DEBUG
    -void
    -dsl_prop_check_prediction(dsl_dir_t *dd, dsl_prop_setarg_t *psa)
    -{
    -	zfs_prop_t prop = zfs_name_to_prop(psa->psa_name);
    -	uint64_t intval;
    -	char setpoint[MAXNAMELEN];
    -	uint64_t version = spa_version(dd->dd_pool->dp_spa);
    -	int err;
    -
    -	if (version < SPA_VERSION_RECVD_PROPS) {
    -		switch (prop) {
    -		case ZFS_PROP_QUOTA:
    -		case ZFS_PROP_RESERVATION:
    -			return;
    -		}
    -	}
    -
    -	err = dsl_prop_get_dd(dd, psa->psa_name, 8, 1, &intval,
    -	    setpoint, B_FALSE);
    -	if (err == 0 && intval != psa->psa_effective_value) {
    -		cmn_err(CE_PANIC, "%s property, source: %x, "
    -		    "predicted effective value: %llu, "
    -		    "actual effective value: %llu (setpoint: %s)",
    -		    psa->psa_name, psa->psa_source,
    -		    (unsigned long long)psa->psa_effective_value,
    -		    (unsigned long long)intval, setpoint);
    -	}
    -}
    -#endif
    -
     /*
      * Unregister this callback.  Return 0 on success, ENOENT if ddname is
      * invalid, ENOMSG if no matching callback registered.
    @@ -464,25 +411,57 @@ dsl_prop_unregister(dsl_dataset_t *ds, const char *propname,
     	return (0);
     }
     
    -/*
    - * Return the number of callbacks that are registered for this dataset.
    - */
    -int
    -dsl_prop_numcb(dsl_dataset_t *ds)
    +boolean_t
    +dsl_prop_hascb(dsl_dataset_t *ds)
    +{
    +	dsl_dir_t *dd = ds->ds_dir;
    +	boolean_t rv = B_FALSE;
    +	dsl_prop_cb_record_t *cbr;
    +
    +	mutex_enter(&dd->dd_lock);
    +	for (cbr = list_head(&dd->dd_prop_cbs); cbr;
    +	    cbr = list_next(&dd->dd_prop_cbs, cbr)) {
    +		if (cbr->cbr_ds == ds) {
    +			rv = B_TRUE;
    +			break;
    +		}
    +	}
    +	mutex_exit(&dd->dd_lock);
    +	return (rv);
    +}
    +
    +/* ARGSUSED */
    +static int
    +dsl_prop_notify_all_cb(dsl_pool_t *dp, dsl_dataset_t *ds, void *arg)
     {
     	dsl_dir_t *dd = ds->ds_dir;
     	dsl_prop_cb_record_t *cbr;
    -	int num = 0;
     
     	mutex_enter(&dd->dd_lock);
    -	for (cbr = list_head(&dd->dd_prop_cbs);
    -	    cbr; cbr = list_next(&dd->dd_prop_cbs, cbr)) {
    -		if (cbr->cbr_ds == ds)
    -			num++;
    +	for (cbr = list_head(&dd->dd_prop_cbs); cbr;
    +	    cbr = list_next(&dd->dd_prop_cbs, cbr)) {
    +		uint64_t value;
    +
    +		if (dsl_prop_get_ds(cbr->cbr_ds, cbr->cbr_propname,
    +		    sizeof (value), 1, &value, NULL) == 0)
    +			cbr->cbr_func(cbr->cbr_arg, value);
     	}
     	mutex_exit(&dd->dd_lock);
     
    -	return (num);
    +	return (0);
    +}
    +
    +/*
    + * Update all property values for ddobj & its descendants.  This is used
    + * when renaming the dir.
    + */
    +void
    +dsl_prop_notify_all(dsl_dir_t *dd)
    +{
    +	dsl_pool_t *dp = dd->dd_pool;
    +	ASSERT(RRW_WRITE_HELD(&dp->dp_config_rwlock));
    +	(void) dmu_objset_find_dp(dp, dd->dd_object, dsl_prop_notify_all_cb,
    +	    NULL, DS_FIND_CHILDREN);
     }
     
     static void
    @@ -496,8 +475,8 @@ dsl_prop_changed_notify(dsl_pool_t *dp, uint64_t ddobj,
     	zap_attribute_t *za;
     	int err;
     
    -	ASSERT(RW_WRITE_HELD(&dp->dp_config_rwlock));
    -	err = dsl_dir_open_obj(dp, ddobj, NULL, FTAG, &dd);
    +	ASSERT(RRW_WRITE_HELD(&dp->dp_config_rwlock));
    +	err = dsl_dir_hold_obj(dp, ddobj, NULL, FTAG, &dd);
     	if (err)
     		return;
     
    @@ -508,7 +487,7 @@ dsl_prop_changed_notify(dsl_pool_t *dp, uint64_t ddobj,
     		 */
     		err = zap_contains(mos, dd->dd_phys->dd_props_zapobj, propname);
     		if (err == 0) {
    -			dsl_dir_close(dd, FTAG);
    +			dsl_dir_rele(dd, FTAG);
     			return;
     		}
     		ASSERT3U(err, ==, ENOENT);
    @@ -543,26 +522,24 @@ dsl_prop_changed_notify(dsl_pool_t *dp, uint64_t ddobj,
     	}
     	kmem_free(za, sizeof (zap_attribute_t));
     	zap_cursor_fini(&zc);
    -	dsl_dir_close(dd, FTAG);
    +	dsl_dir_rele(dd, FTAG);
     }
     
     void
    -dsl_prop_set_sync(void *arg1, void *arg2, dmu_tx_t *tx)
    +dsl_prop_set_sync_impl(dsl_dataset_t *ds, const char *propname,
    +    zprop_source_t source, int intsz, int numints, const void *value,
    +    dmu_tx_t *tx)
     {
    -	dsl_dataset_t *ds = arg1;
    -	dsl_prop_setarg_t *psa = arg2;
     	objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
     	uint64_t zapobj, intval, dummy;
     	int isint;
     	char valbuf[32];
    -	char *valstr = NULL;
    +	const char *valstr = NULL;
     	char *inheritstr;
     	char *recvdstr;
     	char *tbuf = NULL;
     	int err;
     	uint64_t version = spa_version(ds->ds_dir->dd_pool->dp_spa);
    -	const char *propname = psa->psa_name;
    -	zprop_source_t source = psa->psa_source;
     
     	isint = (dodefault(propname, 8, 1, &intval) == 0);
     
    @@ -612,8 +589,8 @@ dsl_prop_set_sync(void *arg1, void *arg2, dmu_tx_t *tx)
     		 */
     		err = zap_remove(mos, zapobj, inheritstr, tx);
     		ASSERT(err == 0 || err == ENOENT);
    -		VERIFY(0 == zap_update(mos, zapobj, propname,
    -		    psa->psa_intsz, psa->psa_numints, psa->psa_value, tx));
    +		VERIFY0(zap_update(mos, zapobj, propname,
    +		    intsz, numints, value, tx));
     		break;
     	case ZPROP_SRC_INHERITED:
     		/*
    @@ -624,12 +601,10 @@ dsl_prop_set_sync(void *arg1, void *arg2, dmu_tx_t *tx)
     		err = zap_remove(mos, zapobj, propname, tx);
     		ASSERT(err == 0 || err == ENOENT);
     		if (version >= SPA_VERSION_RECVD_PROPS &&
    -		    dsl_prop_get_ds(ds, ZPROP_HAS_RECVD, 8, 1, &dummy,
    -		    NULL) == 0) {
    +		    dsl_prop_get_int_ds(ds, ZPROP_HAS_RECVD, &dummy) == 0) {
     			dummy = 0;
    -			err = zap_update(mos, zapobj, inheritstr,
    -			    8, 1, &dummy, tx);
    -			ASSERT(err == 0);
    +			VERIFY0(zap_update(mos, zapobj, inheritstr,
    +			    8, 1, &dummy, tx));
     		}
     		break;
     	case ZPROP_SRC_RECEIVED:
    @@ -637,7 +612,7 @@ dsl_prop_set_sync(void *arg1, void *arg2, dmu_tx_t *tx)
     		 * set propname$recvd -> value
     		 */
     		err = zap_update(mos, zapobj, recvdstr,
    -		    psa->psa_intsz, psa->psa_numints, psa->psa_value, tx);
    +		    intsz, numints, value, tx);
     		ASSERT(err == 0);
     		break;
     	case (ZPROP_SRC_NONE | ZPROP_SRC_LOCAL | ZPROP_SRC_RECEIVED):
    @@ -667,7 +642,7 @@ dsl_prop_set_sync(void *arg1, void *arg2, dmu_tx_t *tx)
     	strfree(recvdstr);
     
     	if (isint) {
    -		VERIFY(0 == dsl_prop_get_ds(ds, propname, 8, 1, &intval, NULL));
    +		VERIFY0(dsl_prop_get_int_ds(ds, propname, &intval));
     
     		if (ds->ds_phys != NULL && dsl_dataset_is_snapshot(ds)) {
     			dsl_prop_cb_record_t *cbr;
    @@ -694,7 +669,7 @@ dsl_prop_set_sync(void *arg1, void *arg2, dmu_tx_t *tx)
     		valstr = valbuf;
     	} else {
     		if (source == ZPROP_SRC_LOCAL) {
    -			valstr = (char *)psa->psa_value;
    +			valstr = value;
     		} else {
     			tbuf = kmem_alloc(ZAP_MAXVALUELEN, KM_SLEEP);
     			if (dsl_prop_get_ds(ds, propname, 1,
    @@ -711,118 +686,73 @@ dsl_prop_set_sync(void *arg1, void *arg2, dmu_tx_t *tx)
     		kmem_free(tbuf, ZAP_MAXVALUELEN);
     }
     
    -void
    -dsl_props_set_sync(void *arg1, void *arg2, dmu_tx_t *tx)
    +int
    +dsl_prop_set_int(const char *dsname, const char *propname,
    +    zprop_source_t source, uint64_t value)
     {
    -	dsl_dataset_t *ds = arg1;
    -	dsl_props_arg_t *pa = arg2;
    -	nvlist_t *props = pa->pa_props;
    -	dsl_prop_setarg_t psa;
    -	nvpair_t *elem = NULL;
    +	nvlist_t *nvl = fnvlist_alloc();
    +	int error;
     
    -	psa.psa_source = pa->pa_source;
    -
    -	while ((elem = nvlist_next_nvpair(props, elem)) != NULL) {
    -		nvpair_t *pair = elem;
    -
    -		psa.psa_name = nvpair_name(pair);
    -
    -		if (nvpair_type(pair) == DATA_TYPE_NVLIST) {
    -			/*
    -			 * dsl_prop_get_all_impl() returns properties in this
    -			 * format.
    -			 */
    -			nvlist_t *attrs;
    -			VERIFY(nvpair_value_nvlist(pair, &attrs) == 0);
    -			VERIFY(nvlist_lookup_nvpair(attrs, ZPROP_VALUE,
    -			    &pair) == 0);
    -		}
    -
    -		if (nvpair_type(pair) == DATA_TYPE_STRING) {
    -			VERIFY(nvpair_value_string(pair,
    -			    (char **)&psa.psa_value) == 0);
    -			psa.psa_intsz = 1;
    -			psa.psa_numints = strlen(psa.psa_value) + 1;
    -		} else {
    -			uint64_t intval;
    -			VERIFY(nvpair_value_uint64(pair, &intval) == 0);
    -			psa.psa_intsz = sizeof (intval);
    -			psa.psa_numints = 1;
    -			psa.psa_value = &intval;
    -		}
    -		dsl_prop_set_sync(ds, &psa, tx);
    -	}
    +	fnvlist_add_uint64(nvl, propname, value);
    +	error = dsl_props_set(dsname, source, nvl);
    +	fnvlist_free(nvl);
    +	return (error);
     }
     
     int
    -dsl_prop_set(const char *dsname, const char *propname, zprop_source_t source,
    -    int intsz, int numints, const void *buf)
    +dsl_prop_set_string(const char *dsname, const char *propname,
    +    zprop_source_t source, const char *value)
     {
    -	dsl_dataset_t *ds;
    -	uint64_t version;
    -	int err;
    -	dsl_prop_setarg_t psa;
    +	nvlist_t *nvl = fnvlist_alloc();
    +	int error;
     
    -	/*
    -	 * We must do these checks before we get to the syncfunc, since
    -	 * it can't fail.
    -	 */
    -	if (strlen(propname) >= ZAP_MAXNAMELEN)
    -		return (ENAMETOOLONG);
    -
    -	err = dsl_dataset_hold(dsname, FTAG, &ds);
    -	if (err)
    -		return (err);
    -
    -	version = spa_version(ds->ds_dir->dd_pool->dp_spa);
    -	if (intsz * numints >= (version < SPA_VERSION_STMF_PROP ?
    -	    ZAP_OLDMAXVALUELEN : ZAP_MAXVALUELEN)) {
    -		dsl_dataset_rele(ds, FTAG);
    -		return (E2BIG);
    -	}
    -	if (dsl_dataset_is_snapshot(ds) &&
    -	    version < SPA_VERSION_SNAP_PROPS) {
    -		dsl_dataset_rele(ds, FTAG);
    -		return (ENOTSUP);
    -	}
    -
    -	psa.psa_name = propname;
    -	psa.psa_source = source;
    -	psa.psa_intsz = intsz;
    -	psa.psa_numints = numints;
    -	psa.psa_value = buf;
    -	psa.psa_effective_value = -1ULL;
    -
    -	err = dsl_sync_task_do(ds->ds_dir->dd_pool,
    -	    NULL, dsl_prop_set_sync, ds, &psa, 2);
    -
    -	dsl_dataset_rele(ds, FTAG);
    -	return (err);
    +	fnvlist_add_string(nvl, propname, value);
    +	error = dsl_props_set(dsname, source, nvl);
    +	fnvlist_free(nvl);
    +	return (error);
     }
     
     int
    -dsl_props_set(const char *dsname, zprop_source_t source, nvlist_t *props)
    +dsl_prop_inherit(const char *dsname, const char *propname,
    +    zprop_source_t source)
     {
    +	nvlist_t *nvl = fnvlist_alloc();
    +	int error;
    +
    +	fnvlist_add_boolean(nvl, propname);
    +	error = dsl_props_set(dsname, source, nvl);
    +	fnvlist_free(nvl);
    +	return (error);
    +}
    +
    +typedef struct dsl_props_set_arg {
    +	const char *dpsa_dsname;
    +	zprop_source_t dpsa_source;
    +	nvlist_t *dpsa_props;
    +} dsl_props_set_arg_t;
    +
    +static int
    +dsl_props_set_check(void *arg, dmu_tx_t *tx)
    +{
    +	dsl_props_set_arg_t *dpsa = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
     	dsl_dataset_t *ds;
     	uint64_t version;
     	nvpair_t *elem = NULL;
    -	dsl_props_arg_t pa;
     	int err;
     
    -	if (err = dsl_dataset_hold(dsname, FTAG, &ds))
    +	err = dsl_dataset_hold(dp, dpsa->dpsa_dsname, FTAG, &ds);
    +	if (err != 0)
     		return (err);
    -	/*
    -	 * Do these checks before the syncfunc, since it can't fail.
    -	 */
    +
     	version = spa_version(ds->ds_dir->dd_pool->dp_spa);
    -	while ((elem = nvlist_next_nvpair(props, elem)) != NULL) {
    +	while ((elem = nvlist_next_nvpair(dpsa->dpsa_props, elem)) != NULL) {
     		if (strlen(nvpair_name(elem)) >= ZAP_MAXNAMELEN) {
     			dsl_dataset_rele(ds, FTAG);
     			return (ENAMETOOLONG);
     		}
     		if (nvpair_type(elem) == DATA_TYPE_STRING) {
    -			char *valstr;
    -			VERIFY(nvpair_value_string(elem, &valstr) == 0);
    +			char *valstr = fnvpair_value_string(elem);
     			if (strlen(valstr) >= (version <
     			    SPA_VERSION_STMF_PROP ?
     			    ZAP_OLDMAXVALUELEN : ZAP_MAXVALUELEN)) {
    @@ -832,20 +762,83 @@ dsl_props_set(const char *dsname, zprop_source_t source, nvlist_t *props)
     		}
     	}
     
    -	if (dsl_dataset_is_snapshot(ds) &&
    -	    version < SPA_VERSION_SNAP_PROPS) {
    +	if (dsl_dataset_is_snapshot(ds) && version < SPA_VERSION_SNAP_PROPS) {
     		dsl_dataset_rele(ds, FTAG);
     		return (ENOTSUP);
     	}
    -
    -	pa.pa_props = props;
    -	pa.pa_source = source;
    -
    -	err = dsl_sync_task_do(ds->ds_dir->dd_pool,
    -	    NULL, dsl_props_set_sync, ds, &pa, 2);
    -
     	dsl_dataset_rele(ds, FTAG);
    -	return (err);
    +	return (0);
    +}
    +
    +void
    +dsl_props_set_sync_impl(dsl_dataset_t *ds, zprop_source_t source,
    +    nvlist_t *props, dmu_tx_t *tx)
    +{
    +	nvpair_t *elem = NULL;
    +
    +	while ((elem = nvlist_next_nvpair(props, elem)) != NULL) {
    +		nvpair_t *pair = elem;
    +
    +		if (nvpair_type(pair) == DATA_TYPE_NVLIST) {
    +			/*
    +			 * dsl_prop_get_all_impl() returns properties in this
    +			 * format.
    +			 */
    +			nvlist_t *attrs = fnvpair_value_nvlist(pair);
    +			pair = fnvlist_lookup_nvpair(attrs, ZPROP_VALUE);
    +		}
    +
    +		if (nvpair_type(pair) == DATA_TYPE_STRING) {
    +			const char *value = fnvpair_value_string(pair);
    +			dsl_prop_set_sync_impl(ds, nvpair_name(pair),
    +			    source, 1, strlen(value) + 1, value, tx);
    +		} else if (nvpair_type(pair) == DATA_TYPE_UINT64) {
    +			uint64_t intval = fnvpair_value_uint64(pair);
    +			dsl_prop_set_sync_impl(ds, nvpair_name(pair),
    +			    source, sizeof (intval), 1, &intval, tx);
    +		} else if (nvpair_type(pair) == DATA_TYPE_BOOLEAN) {
    +			dsl_prop_set_sync_impl(ds, nvpair_name(pair),
    +			    source, 0, 0, NULL, tx);
    +		} else {
    +			panic("invalid nvpair type");
    +		}
    +	}
    +}
    +
    +static void
    +dsl_props_set_sync(void *arg, dmu_tx_t *tx)
    +{
    +	dsl_props_set_arg_t *dpsa = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	dsl_dataset_t *ds;
    +
    +	VERIFY0(dsl_dataset_hold(dp, dpsa->dpsa_dsname, FTAG, &ds));
    +	dsl_props_set_sync_impl(ds, dpsa->dpsa_source, dpsa->dpsa_props, tx);
    +	dsl_dataset_rele(ds, FTAG);
    +}
    +
    +/*
    + * All-or-nothing; if any prop can't be set, nothing will be modified.
    + */
    +int
    +dsl_props_set(const char *dsname, zprop_source_t source, nvlist_t *props)
    +{
    +	dsl_props_set_arg_t dpsa;
    +	int nblks = 0;
    +
    +	dpsa.dpsa_dsname = dsname;
    +	dpsa.dpsa_source = source;
    +	dpsa.dpsa_props = props;
    +
    +	/*
    +	 * If the source includes NONE, then we will only be removing entries
    +	 * from the ZAP object.  In that case don't check for ENOSPC.
    +	 */
    +	if ((source & ZPROP_SRC_NONE) == 0)
    +		nblks = 2 * fnvlist_num_pairs(props);
    +
    +	return (dsl_sync_task(dsname, dsl_props_set_check, dsl_props_set_sync,
    +	    &dpsa, nblks));
     }
     
     typedef enum dsl_prop_getflags {
    @@ -995,7 +988,7 @@ dsl_prop_get_all_ds(dsl_dataset_t *ds, nvlist_t **nvp,
     	if (dsl_dataset_is_snapshot(ds))
     		flags |= DSL_PROP_GET_SNAPSHOT;
     
    -	rw_enter(&dp->dp_config_rwlock, RW_READER);
    +	ASSERT(dsl_pool_config_held(dp));
     
     	if (ds->ds_phys->ds_props_obj != 0) {
     		ASSERT(flags & DSL_PROP_GET_SNAPSHOT);
    @@ -1020,58 +1013,51 @@ dsl_prop_get_all_ds(dsl_dataset_t *ds, nvlist_t **nvp,
     			break;
     	}
     out:
    -	rw_exit(&dp->dp_config_rwlock);
     	return (err);
     }
     
     boolean_t
    -dsl_prop_get_hasrecvd(objset_t *os)
    +dsl_prop_get_hasrecvd(const char *dsname)
     {
    -	dsl_dataset_t *ds = os->os_dsl_dataset;
    -	int rc;
     	uint64_t dummy;
     
    -	rw_enter(&ds->ds_dir->dd_pool->dp_config_rwlock, RW_READER);
    -	rc = dsl_prop_get_ds(ds, ZPROP_HAS_RECVD, 8, 1, &dummy, NULL);
    -	rw_exit(&ds->ds_dir->dd_pool->dp_config_rwlock);
    -	ASSERT(rc != 0 || spa_version(os->os_spa) >= SPA_VERSION_RECVD_PROPS);
    -	return (rc == 0);
    +	return (0 ==
    +	    dsl_prop_get_integer(dsname, ZPROP_HAS_RECVD, &dummy, NULL));
     }
     
    -static void
    -dsl_prop_set_hasrecvd_impl(objset_t *os, zprop_source_t source)
    +static int
    +dsl_prop_set_hasrecvd_impl(const char *dsname, zprop_source_t source)
     {
    -	dsl_dataset_t *ds = os->os_dsl_dataset;
    -	uint64_t dummy = 0;
    -	dsl_prop_setarg_t psa;
    +	uint64_t version;
    +	spa_t *spa;
    +	int error = 0;
     
    -	if (spa_version(os->os_spa) < SPA_VERSION_RECVD_PROPS)
    -		return;
    +	VERIFY0(spa_open(dsname, &spa, FTAG));
    +	version = spa_version(spa);
    +	spa_close(spa, FTAG);
     
    -	dsl_prop_setarg_init_uint64(&psa, ZPROP_HAS_RECVD, source, &dummy);
    -
    -	(void) dsl_sync_task_do(ds->ds_dir->dd_pool, NULL,
    -	    dsl_prop_set_sync, ds, &psa, 2);
    +	if (version >= SPA_VERSION_RECVD_PROPS)
    +		error = dsl_prop_set_int(dsname, ZPROP_HAS_RECVD, source, 0);
    +	return (error);
     }
     
     /*
      * Call after successfully receiving properties to ensure that only the first
      * receive on or after SPA_VERSION_RECVD_PROPS blows away local properties.
      */
    -void
    -dsl_prop_set_hasrecvd(objset_t *os)
    +int
    +dsl_prop_set_hasrecvd(const char *dsname)
     {
    -	if (dsl_prop_get_hasrecvd(os)) {
    -		ASSERT(spa_version(os->os_spa) >= SPA_VERSION_RECVD_PROPS);
    -		return;
    -	}
    -	dsl_prop_set_hasrecvd_impl(os, ZPROP_SRC_LOCAL);
    +	int error = 0;
    +	if (!dsl_prop_get_hasrecvd(dsname))
    +		error = dsl_prop_set_hasrecvd_impl(dsname, ZPROP_SRC_LOCAL);
    +	return (error);
     }
     
     void
    -dsl_prop_unset_hasrecvd(objset_t *os)
    +dsl_prop_unset_hasrecvd(const char *dsname)
     {
    -	dsl_prop_set_hasrecvd_impl(os, ZPROP_SRC_NONE);
    +	VERIFY0(dsl_prop_set_hasrecvd_impl(dsname, ZPROP_SRC_NONE));
     }
     
     int
    @@ -1081,16 +1067,25 @@ dsl_prop_get_all(objset_t *os, nvlist_t **nvp)
     }
     
     int
    -dsl_prop_get_received(objset_t *os, nvlist_t **nvp)
    +dsl_prop_get_received(const char *dsname, nvlist_t **nvp)
     {
    +	objset_t *os;
    +	int error;
    +
     	/*
     	 * Received properties are not distinguishable from local properties
     	 * until the dataset has received properties on or after
     	 * SPA_VERSION_RECVD_PROPS.
     	 */
    -	dsl_prop_getflags_t flags = (dsl_prop_get_hasrecvd(os) ?
    +	dsl_prop_getflags_t flags = (dsl_prop_get_hasrecvd(dsname) ?
     	    DSL_PROP_GET_RECEIVED : DSL_PROP_GET_LOCAL);
    -	return (dsl_prop_get_all_ds(os->os_dsl_dataset, nvp, flags));
    +
    +	error = dmu_objset_hold(dsname, FTAG, &os);
    +	if (error != 0)
    +		return (error);
    +	error = dsl_prop_get_all_ds(os->os_dsl_dataset, nvp, flags);
    +	dmu_objset_rele(os, FTAG);
    +	return (error);
     }
     
     void
    diff --git a/uts/common/fs/zfs/dsl_scan.c b/uts/common/fs/zfs/dsl_scan.c
    index e1717257990..3de3c6e4d7f 100644
    --- a/uts/common/fs/zfs/dsl_scan.c
    +++ b/uts/common/fs/zfs/dsl_scan.c
    @@ -55,7 +55,7 @@ typedef int (scan_cb_t)(dsl_pool_t *, const blkptr_t *, const zbookmark_t *);
     static scan_cb_t dsl_scan_defrag_cb;
     static scan_cb_t dsl_scan_scrub_cb;
     static scan_cb_t dsl_scan_remove_cb;
    -static dsl_syncfunc_t dsl_scan_cancel_sync;
    +static void dsl_scan_cancel_sync(void *, dmu_tx_t *);
     static void dsl_scan_sync_state(dsl_scan_t *, dmu_tx_t *tx);
     
     int zfs_top_maxinflight = 32;		/* maximum I/Os per top-level */
    @@ -154,9 +154,9 @@ dsl_scan_fini(dsl_pool_t *dp)
     
     /* ARGSUSED */
     static int
    -dsl_scan_setup_check(void *arg1, void *arg2, dmu_tx_t *tx)
    +dsl_scan_setup_check(void *arg, dmu_tx_t *tx)
     {
    -	dsl_scan_t *scn = arg1;
    +	dsl_scan_t *scn = dmu_tx_pool(tx)->dp_scan;
     
     	if (scn->scn_phys.scn_state == DSS_SCANNING)
     		return (EBUSY);
    @@ -164,12 +164,11 @@ dsl_scan_setup_check(void *arg1, void *arg2, dmu_tx_t *tx)
     	return (0);
     }
     
    -/* ARGSUSED */
     static void
    -dsl_scan_setup_sync(void *arg1, void *arg2, dmu_tx_t *tx)
    +dsl_scan_setup_sync(void *arg, dmu_tx_t *tx)
     {
    -	dsl_scan_t *scn = arg1;
    -	pool_scan_func_t *funcp = arg2;
    +	dsl_scan_t *scn = dmu_tx_pool(tx)->dp_scan;
    +	pool_scan_func_t *funcp = arg;
     	dmu_object_type_t ot = 0;
     	dsl_pool_t *dp = scn->scn_dp;
     	spa_t *spa = dp->dp_spa;
    @@ -315,9 +314,9 @@ dsl_scan_done(dsl_scan_t *scn, boolean_t complete, dmu_tx_t *tx)
     
     /* ARGSUSED */
     static int
    -dsl_scan_cancel_check(void *arg1, void *arg2, dmu_tx_t *tx)
    +dsl_scan_cancel_check(void *arg, dmu_tx_t *tx)
     {
    -	dsl_scan_t *scn = arg1;
    +	dsl_scan_t *scn = dmu_tx_pool(tx)->dp_scan;
     
     	if (scn->scn_phys.scn_state != DSS_SCANNING)
     		return (ENOENT);
    @@ -326,9 +325,9 @@ dsl_scan_cancel_check(void *arg1, void *arg2, dmu_tx_t *tx)
     
     /* ARGSUSED */
     static void
    -dsl_scan_cancel_sync(void *arg1, void *arg2, dmu_tx_t *tx)
    +dsl_scan_cancel_sync(void *arg, dmu_tx_t *tx)
     {
    -	dsl_scan_t *scn = arg1;
    +	dsl_scan_t *scn = dmu_tx_pool(tx)->dp_scan;
     
     	dsl_scan_done(scn, B_FALSE, tx);
     	dsl_scan_sync_state(scn, tx);
    @@ -337,12 +336,8 @@ dsl_scan_cancel_sync(void *arg1, void *arg2, dmu_tx_t *tx)
     int
     dsl_scan_cancel(dsl_pool_t *dp)
     {
    -	boolean_t complete = B_FALSE;
    -	int err;
    -
    -	err = dsl_sync_task_do(dp, dsl_scan_cancel_check,
    -	    dsl_scan_cancel_sync, dp->dp_scan, &complete, 3);
    -	return (err);
    +	return (dsl_sync_task(spa_name(dp->dp_spa), dsl_scan_cancel_check,
    +	    dsl_scan_cancel_sync, NULL, 3));
     }
     
     static void dsl_scan_visitbp(blkptr_t *bp,
    @@ -378,7 +373,7 @@ dsl_scan_ds_maxtxg(dsl_dataset_t *ds)
     static void
     dsl_scan_sync_state(dsl_scan_t *scn, dmu_tx_t *tx)
     {
    -	VERIFY(0 == zap_update(scn->scn_dp->dp_meta_objset,
    +	VERIFY0(zap_update(scn->scn_dp->dp_meta_objset,
     	    DMU_POOL_DIRECTORY_OBJECT,
     	    DMU_POOL_SCAN, sizeof (uint64_t), SCAN_PHYS_NUMINTS,
     	    &scn->scn_phys, tx));
    @@ -950,33 +945,33 @@ struct enqueue_clones_arg {
     
     /* ARGSUSED */
     static int
    -enqueue_clones_cb(spa_t *spa, uint64_t dsobj, const char *dsname, void *arg)
    +enqueue_clones_cb(dsl_pool_t *dp, dsl_dataset_t *hds, void *arg)
     {
     	struct enqueue_clones_arg *eca = arg;
     	dsl_dataset_t *ds;
     	int err;
    -	dsl_pool_t *dp = spa->spa_dsl_pool;
     	dsl_scan_t *scn = dp->dp_scan;
     
    -	err = dsl_dataset_hold_obj(dp, dsobj, FTAG, &ds);
    +	if (hds->ds_dir->dd_phys->dd_origin_obj != eca->originobj)
    +		return (0);
    +
    +	err = dsl_dataset_hold_obj(dp, hds->ds_object, FTAG, &ds);
     	if (err)
     		return (err);
     
    -	if (ds->ds_dir->dd_phys->dd_origin_obj == eca->originobj) {
    -		while (ds->ds_phys->ds_prev_snap_obj != eca->originobj) {
    -			dsl_dataset_t *prev;
    -			err = dsl_dataset_hold_obj(dp,
    -			    ds->ds_phys->ds_prev_snap_obj, FTAG, &prev);
    +	while (ds->ds_phys->ds_prev_snap_obj != eca->originobj) {
    +		dsl_dataset_t *prev;
    +		err = dsl_dataset_hold_obj(dp,
    +		    ds->ds_phys->ds_prev_snap_obj, FTAG, &prev);
     
    -			dsl_dataset_rele(ds, FTAG);
    -			if (err)
    -				return (err);
    -			ds = prev;
    -		}
    -		VERIFY(zap_add_int_key(dp->dp_meta_objset,
    -		    scn->scn_phys.scn_queue_obj, ds->ds_object,
    -		    ds->ds_phys->ds_prev_snap_txg, eca->tx) == 0);
    +		dsl_dataset_rele(ds, FTAG);
    +		if (err)
    +			return (err);
    +		ds = prev;
     	}
    +	VERIFY(zap_add_int_key(dp->dp_meta_objset,
    +	    scn->scn_phys.scn_queue_obj, ds->ds_object,
    +	    ds->ds_phys->ds_prev_snap_txg, eca->tx) == 0);
     	dsl_dataset_rele(ds, FTAG);
     	return (0);
     }
    @@ -1065,17 +1060,17 @@ dsl_scan_visitds(dsl_scan_t *scn, uint64_t dsobj, dmu_tx_t *tx)
     		}
     
     		if (usenext) {
    -			VERIFY(zap_join_key(dp->dp_meta_objset,
    +			VERIFY0(zap_join_key(dp->dp_meta_objset,
     			    ds->ds_phys->ds_next_clones_obj,
     			    scn->scn_phys.scn_queue_obj,
    -			    ds->ds_phys->ds_creation_txg, tx) == 0);
    +			    ds->ds_phys->ds_creation_txg, tx));
     		} else {
     			struct enqueue_clones_arg eca;
     			eca.tx = tx;
     			eca.originobj = ds->ds_object;
     
    -			(void) dmu_objset_find_spa(ds->ds_dir->dd_pool->dp_spa,
    -			    NULL, enqueue_clones_cb, &eca, DS_FIND_CHILDREN);
    +			VERIFY0(dmu_objset_find_dp(dp, dp->dp_root_dir_obj,
    +			    enqueue_clones_cb, &eca, DS_FIND_CHILDREN));
     		}
     	}
     
    @@ -1085,15 +1080,14 @@ out:
     
     /* ARGSUSED */
     static int
    -enqueue_cb(spa_t *spa, uint64_t dsobj, const char *dsname, void *arg)
    +enqueue_cb(dsl_pool_t *dp, dsl_dataset_t *hds, void *arg)
     {
     	dmu_tx_t *tx = arg;
     	dsl_dataset_t *ds;
     	int err;
    -	dsl_pool_t *dp = spa->spa_dsl_pool;
     	dsl_scan_t *scn = dp->dp_scan;
     
    -	err = dsl_dataset_hold_obj(dp, dsobj, FTAG, &ds);
    +	err = dsl_dataset_hold_obj(dp, hds->ds_object, FTAG, &ds);
     	if (err)
     		return (err);
     
    @@ -1248,8 +1242,8 @@ dsl_scan_visit(dsl_scan_t *scn, dmu_tx_t *tx)
     			return;
     
     		if (spa_version(dp->dp_spa) < SPA_VERSION_DSL_SCRUB) {
    -			VERIFY(0 == dmu_objset_find_spa(dp->dp_spa,
    -			    NULL, enqueue_cb, tx, DS_FIND_CHILDREN));
    +			VERIFY0(dmu_objset_find_dp(dp, dp->dp_root_dir_obj,
    +			    enqueue_cb, tx, DS_FIND_CHILDREN));
     		} else {
     			dsl_scan_visitds(scn,
     			    dp->dp_origin_snap->ds_object, tx);
    @@ -1384,7 +1378,7 @@ dsl_scan_sync(dsl_pool_t *dp, dmu_tx_t *tx)
     			func = POOL_SCAN_RESILVER;
     		zfs_dbgmsg("restarting scan func=%u txg=%llu",
     		    func, tx->tx_txg);
    -		dsl_scan_setup_sync(scn, &func, tx);
    +		dsl_scan_setup_sync(&func, tx);
     	}
     
     	if (!dsl_scan_active(scn) ||
    @@ -1418,21 +1412,21 @@ dsl_scan_sync(dsl_pool_t *dp, dmu_tx_t *tx)
     			err = bptree_iterate(dp->dp_meta_objset,
     			    dp->dp_bptree_obj, B_TRUE, dsl_scan_free_block_cb,
     			    scn, tx);
    -			VERIFY3U(0, ==, zio_wait(scn->scn_zio_root));
    -			if (err != 0)
    -				return;
    +			VERIFY0(zio_wait(scn->scn_zio_root));
     
    -			/* disable async destroy feature */
    -			spa_feature_decr(spa,
    -			    &spa_feature_table[SPA_FEATURE_ASYNC_DESTROY], tx);
    -			ASSERT(!spa_feature_is_active(spa,
    -			    &spa_feature_table[SPA_FEATURE_ASYNC_DESTROY]));
    -			VERIFY3U(0, ==, zap_remove(dp->dp_meta_objset,
    -			    DMU_POOL_DIRECTORY_OBJECT,
    -			    DMU_POOL_BPTREE_OBJ, tx));
    -			VERIFY3U(0, ==, bptree_free(dp->dp_meta_objset,
    -			    dp->dp_bptree_obj, tx));
    -			dp->dp_bptree_obj = 0;
    +			if (err == 0) {
    +				zfeature_info_t *feat = &spa_feature_table
    +				    [SPA_FEATURE_ASYNC_DESTROY];
    +				/* finished; deactivate async destroy feature */
    +				spa_feature_decr(spa, feat, tx);
    +				ASSERT(!spa_feature_is_active(spa, feat));
    +				VERIFY0(zap_remove(dp->dp_meta_objset,
    +				    DMU_POOL_DIRECTORY_OBJECT,
    +				    DMU_POOL_BPTREE_OBJ, tx));
    +				VERIFY0(bptree_free(dp->dp_meta_objset,
    +				    dp->dp_bptree_obj, tx));
    +				dp->dp_bptree_obj = 0;
    +			}
     		}
     		if (scn->scn_visited_this_txg) {
     			zfs_dbgmsg("freed %llu blocks in %llums from "
    @@ -1479,7 +1473,9 @@ dsl_scan_sync(dsl_pool_t *dp, dmu_tx_t *tx)
     
     	scn->scn_zio_root = zio_root(dp->dp_spa, NULL,
     	    NULL, ZIO_FLAG_CANFAIL);
    +	dsl_pool_config_enter(dp, FTAG);
     	dsl_scan_visit(scn, tx);
    +	dsl_pool_config_exit(dp, FTAG);
     	(void) zio_wait(scn->scn_zio_root);
     	scn->scn_zio_root = NULL;
     
    @@ -1714,6 +1710,6 @@ dsl_scan(dsl_pool_t *dp, pool_scan_func_t func)
     	spa->spa_scrub_reopen = B_FALSE;
     	(void) spa_vdev_state_exit(spa, NULL, 0);
     
    -	return (dsl_sync_task_do(dp, dsl_scan_setup_check,
    -	    dsl_scan_setup_sync, dp->dp_scan, &func, 0));
    +	return (dsl_sync_task(spa_name(spa), dsl_scan_setup_check,
    +	    dsl_scan_setup_sync, &func, 0));
     }
    diff --git a/uts/common/fs/zfs/dsl_synctask.c b/uts/common/fs/zfs/dsl_synctask.c
    index e2481281e06..ecb45fbc38e 100644
    --- a/uts/common/fs/zfs/dsl_synctask.c
    +++ b/uts/common/fs/zfs/dsl_synctask.c
    @@ -34,136 +34,115 @@
     
     /* ARGSUSED */
     static int
    -dsl_null_checkfunc(void *arg1, void *arg2, dmu_tx_t *tx)
    +dsl_null_checkfunc(void *arg, dmu_tx_t *tx)
     {
     	return (0);
     }
     
    -dsl_sync_task_group_t *
    -dsl_sync_task_group_create(dsl_pool_t *dp)
    -{
    -	dsl_sync_task_group_t *dstg;
    -
    -	dstg = kmem_zalloc(sizeof (dsl_sync_task_group_t), KM_SLEEP);
    -	list_create(&dstg->dstg_tasks, sizeof (dsl_sync_task_t),
    -	    offsetof(dsl_sync_task_t, dst_node));
    -	dstg->dstg_pool = dp;
    -
    -	return (dstg);
    -}
    -
    -void
    -dsl_sync_task_create(dsl_sync_task_group_t *dstg,
    -    dsl_checkfunc_t *checkfunc, dsl_syncfunc_t *syncfunc,
    -    void *arg1, void *arg2, int blocks_modified)
    -{
    -	dsl_sync_task_t *dst;
    -
    -	if (checkfunc == NULL)
    -		checkfunc = dsl_null_checkfunc;
    -	dst = kmem_zalloc(sizeof (dsl_sync_task_t), KM_SLEEP);
    -	dst->dst_checkfunc = checkfunc;
    -	dst->dst_syncfunc = syncfunc;
    -	dst->dst_arg1 = arg1;
    -	dst->dst_arg2 = arg2;
    -	list_insert_tail(&dstg->dstg_tasks, dst);
    -
    -	dstg->dstg_space += blocks_modified << DST_AVG_BLKSHIFT;
    -}
    -
    +/*
    + * Called from open context to perform a callback in syncing context.  Waits
    + * for the operation to complete.
    + *
    + * The checkfunc will be called from open context as a preliminary check
    + * which can quickly fail.  If it succeeds, it will be called again from
    + * syncing context.  The checkfunc should generally be designed to work
    + * properly in either context, but if necessary it can check
    + * dmu_tx_is_syncing(tx).
    + *
    + * The synctask infrastructure enforces proper locking strategy with respect
    + * to the dp_config_rwlock -- the lock will always be held when the callbacks
    + * are called.  It will be held for read during the open-context (preliminary)
    + * call to the checkfunc, and then held for write from syncing context during
    + * the calls to the check and sync funcs.
    + *
    + * A dataset or pool name can be passed as the first argument.  Typically,
    + * the check func will hold, check the return value of the hold, and then
    + * release the dataset.  The sync func will VERIFYO(hold()) the dataset.
    + * This is safe because no changes can be made between the check and sync funcs,
    + * and the sync func will only be called if the check func successfully opened
    + * the dataset.
    + */
     int
    -dsl_sync_task_group_wait(dsl_sync_task_group_t *dstg)
    +dsl_sync_task(const char *pool, dsl_checkfunc_t *checkfunc,
    +    dsl_syncfunc_t *syncfunc, void *arg, int blocks_modified)
     {
    +	spa_t *spa;
     	dmu_tx_t *tx;
    -	uint64_t txg;
    -	dsl_sync_task_t *dst;
    +	int err;
    +	dsl_sync_task_t dst = { 0 };
    +	dsl_pool_t *dp;
    +
    +	err = spa_open(pool, &spa, FTAG);
    +	if (err != 0)
    +		return (err);
    +	dp = spa_get_dsl(spa);
     
     top:
    -	tx = dmu_tx_create_dd(dstg->dstg_pool->dp_mos_dir);
    -	VERIFY(0 == dmu_tx_assign(tx, TXG_WAIT));
    +	tx = dmu_tx_create_dd(dp->dp_mos_dir);
    +	VERIFY0(dmu_tx_assign(tx, TXG_WAIT));
     
    -	txg = dmu_tx_get_txg(tx);
    +	dst.dst_pool = dp;
    +	dst.dst_txg = dmu_tx_get_txg(tx);
    +	dst.dst_space = blocks_modified << DST_AVG_BLKSHIFT;
    +	dst.dst_checkfunc = checkfunc != NULL ? checkfunc : dsl_null_checkfunc;
    +	dst.dst_syncfunc = syncfunc;
    +	dst.dst_arg = arg;
    +	dst.dst_error = 0;
    +	dst.dst_nowaiter = B_FALSE;
     
    -	/* Do a preliminary error check. */
    -	dstg->dstg_err = 0;
    -#ifdef ZFS_DEBUG
    -	/*
    -	 * Only check half the time, otherwise, the sync-context
    -	 * check will almost never fail.
    -	 */
    -	if (spa_get_random(2) == 0)
    -		goto skip;
    -#endif
    -	rw_enter(&dstg->dstg_pool->dp_config_rwlock, RW_READER);
    -	for (dst = list_head(&dstg->dstg_tasks); dst;
    -	    dst = list_next(&dstg->dstg_tasks, dst)) {
    -		dst->dst_err =
    -		    dst->dst_checkfunc(dst->dst_arg1, dst->dst_arg2, tx);
    -		if (dst->dst_err)
    -			dstg->dstg_err = dst->dst_err;
    -	}
    -	rw_exit(&dstg->dstg_pool->dp_config_rwlock);
    +	dsl_pool_config_enter(dp, FTAG);
    +	err = dst.dst_checkfunc(arg, tx);
    +	dsl_pool_config_exit(dp, FTAG);
     
    -	if (dstg->dstg_err) {
    +	if (err != 0) {
     		dmu_tx_commit(tx);
    -		return (dstg->dstg_err);
    +		spa_close(spa, FTAG);
    +		return (err);
     	}
    -skip:
     
    -	/*
    -	 * We don't generally have many sync tasks, so pay the price of
    -	 * add_tail to get the tasks executed in the right order.
    -	 */
    -	VERIFY(0 == txg_list_add_tail(&dstg->dstg_pool->dp_sync_tasks,
    -	    dstg, txg));
    +	VERIFY(txg_list_add_tail(&dp->dp_sync_tasks, &dst, dst.dst_txg));
     
     	dmu_tx_commit(tx);
     
    -	txg_wait_synced(dstg->dstg_pool, txg);
    +	txg_wait_synced(dp, dst.dst_txg);
     
    -	if (dstg->dstg_err == EAGAIN) {
    -		txg_wait_synced(dstg->dstg_pool, txg + TXG_DEFER_SIZE);
    +	if (dst.dst_error == EAGAIN) {
    +		txg_wait_synced(dp, dst.dst_txg + TXG_DEFER_SIZE);
     		goto top;
     	}
     
    -	return (dstg->dstg_err);
    +	spa_close(spa, FTAG);
    +	return (dst.dst_error);
     }
     
     void
    -dsl_sync_task_group_nowait(dsl_sync_task_group_t *dstg, dmu_tx_t *tx)
    +dsl_sync_task_nowait(dsl_pool_t *dp, dsl_syncfunc_t *syncfunc, void *arg,
    +    int blocks_modified, dmu_tx_t *tx)
     {
    -	uint64_t txg;
    +	dsl_sync_task_t *dst = kmem_zalloc(sizeof (*dst), KM_SLEEP);
     
    -	dstg->dstg_nowaiter = B_TRUE;
    -	txg = dmu_tx_get_txg(tx);
    -	/*
    -	 * We don't generally have many sync tasks, so pay the price of
    -	 * add_tail to get the tasks executed in the right order.
    -	 */
    -	VERIFY(0 == txg_list_add_tail(&dstg->dstg_pool->dp_sync_tasks,
    -	    dstg, txg));
    +	dst->dst_pool = dp;
    +	dst->dst_txg = dmu_tx_get_txg(tx);
    +	dst->dst_space = blocks_modified << DST_AVG_BLKSHIFT;
    +	dst->dst_checkfunc = dsl_null_checkfunc;
    +	dst->dst_syncfunc = syncfunc;
    +	dst->dst_arg = arg;
    +	dst->dst_error = 0;
    +	dst->dst_nowaiter = B_TRUE;
    +
    +	VERIFY(txg_list_add_tail(&dp->dp_sync_tasks, dst, dst->dst_txg));
     }
     
    +/*
    + * Called in syncing context to execute the synctask.
    + */
     void
    -dsl_sync_task_group_destroy(dsl_sync_task_group_t *dstg)
    +dsl_sync_task_sync(dsl_sync_task_t *dst, dmu_tx_t *tx)
     {
    -	dsl_sync_task_t *dst;
    -
    -	while (dst = list_head(&dstg->dstg_tasks)) {
    -		list_remove(&dstg->dstg_tasks, dst);
    -		kmem_free(dst, sizeof (dsl_sync_task_t));
    -	}
    -	kmem_free(dstg, sizeof (dsl_sync_task_group_t));
    -}
    -
    -void
    -dsl_sync_task_group_sync(dsl_sync_task_group_t *dstg, dmu_tx_t *tx)
    -{
    -	dsl_sync_task_t *dst;
    -	dsl_pool_t *dp = dstg->dstg_pool;
    +	dsl_pool_t *dp = dst->dst_pool;
     	uint64_t quota, used;
     
    -	ASSERT0(dstg->dstg_err);
    +	ASSERT0(dst->dst_error);
     
     	/*
     	 * Check for sufficient space.  We just check against what's
    @@ -175,63 +154,21 @@ dsl_sync_task_group_sync(dsl_sync_task_group_t *dstg, dmu_tx_t *tx)
     	    metaslab_class_get_deferred(spa_normal_class(dp->dp_spa));
     	used = dp->dp_root_dir->dd_phys->dd_used_bytes;
     	/* MOS space is triple-dittoed, so we multiply by 3. */
    -	if (dstg->dstg_space > 0 && used + dstg->dstg_space * 3 > quota) {
    -		dstg->dstg_err = ENOSPC;
    +	if (dst->dst_space > 0 && used + dst->dst_space * 3 > quota) {
    +		dst->dst_error = ENOSPC;
    +		if (dst->dst_nowaiter)
    +			kmem_free(dst, sizeof (*dst));
     		return;
     	}
     
     	/*
    -	 * Check for errors by calling checkfuncs.
    +	 * Check for errors by calling checkfunc.
     	 */
    -	rw_enter(&dp->dp_config_rwlock, RW_WRITER);
    -	for (dst = list_head(&dstg->dstg_tasks); dst;
    -	    dst = list_next(&dstg->dstg_tasks, dst)) {
    -		dst->dst_err =
    -		    dst->dst_checkfunc(dst->dst_arg1, dst->dst_arg2, tx);
    -		if (dst->dst_err)
    -			dstg->dstg_err = dst->dst_err;
    -	}
    -
    -	if (dstg->dstg_err == 0) {
    -		/*
    -		 * Execute sync tasks.
    -		 */
    -		for (dst = list_head(&dstg->dstg_tasks); dst;
    -		    dst = list_next(&dstg->dstg_tasks, dst)) {
    -			dst->dst_syncfunc(dst->dst_arg1, dst->dst_arg2, tx);
    -		}
    -	}
    -	rw_exit(&dp->dp_config_rwlock);
    -
    -	if (dstg->dstg_nowaiter)
    -		dsl_sync_task_group_destroy(dstg);
    -}
    -
    -int
    -dsl_sync_task_do(dsl_pool_t *dp,
    -    dsl_checkfunc_t *checkfunc, dsl_syncfunc_t *syncfunc,
    -    void *arg1, void *arg2, int blocks_modified)
    -{
    -	dsl_sync_task_group_t *dstg;
    -	int err;
    -
    -	ASSERT(spa_writeable(dp->dp_spa));
    -
    -	dstg = dsl_sync_task_group_create(dp);
    -	dsl_sync_task_create(dstg, checkfunc, syncfunc,
    -	    arg1, arg2, blocks_modified);
    -	err = dsl_sync_task_group_wait(dstg);
    -	dsl_sync_task_group_destroy(dstg);
    -	return (err);
    -}
    -
    -void
    -dsl_sync_task_do_nowait(dsl_pool_t *dp,
    -    dsl_checkfunc_t *checkfunc, dsl_syncfunc_t *syncfunc,
    -    void *arg1, void *arg2, int blocks_modified, dmu_tx_t *tx)
    -{
    -	dsl_sync_task_group_t *dstg = dsl_sync_task_group_create(dp);
    -	dsl_sync_task_create(dstg, checkfunc, syncfunc,
    -	    arg1, arg2, blocks_modified);
    -	dsl_sync_task_group_nowait(dstg, tx);
    +	rrw_enter(&dp->dp_config_rwlock, RW_WRITER, FTAG);
    +	dst->dst_error = dst->dst_checkfunc(dst->dst_arg, tx);
    +	if (dst->dst_error == 0)
    +		dst->dst_syncfunc(dst->dst_arg, tx);
    +	rrw_exit(&dp->dp_config_rwlock, FTAG);
    +	if (dst->dst_nowaiter)
    +		kmem_free(dst, sizeof (*dst));
     }
    diff --git a/uts/common/fs/zfs/dsl_userhold.c b/uts/common/fs/zfs/dsl_userhold.c
    new file mode 100644
    index 00000000000..e30169eade4
    --- /dev/null
    +++ b/uts/common/fs/zfs/dsl_userhold.c
    @@ -0,0 +1,536 @@
    +/*
    + * CDDL HEADER START
    + *
    + * The contents of this file are subject to the terms of the
    + * Common Development and Distribution License (the "License").
    + * You may not use this file except in compliance with the License.
    + *
    + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
    + * or http://www.opensolaris.org/os/licensing.
    + * See the License for the specific language governing permissions
    + * and limitations under the License.
    + *
    + * When distributing Covered Code, include this CDDL HEADER in each
    + * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
    + * If applicable, add the following below this CDDL HEADER, with the
    + * fields enclosed by brackets "[]" replaced with your own identifying
    + * information: Portions Copyright [yyyy] [name of copyright owner]
    + *
    + * CDDL HEADER END
    + */
    +/*
    + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2012 by Delphix. All rights reserved.
    + */
    +
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +
    +typedef struct dsl_dataset_user_hold_arg {
    +	nvlist_t *dduha_holds;
    +	nvlist_t *dduha_errlist;
    +	minor_t dduha_minor;
    +} dsl_dataset_user_hold_arg_t;
    +
    +/*
    + * If you add new checks here, you may need to add additional checks to the
    + * "temporary" case in snapshot_check() in dmu_objset.c.
    + */
    +int
    +dsl_dataset_user_hold_check_one(dsl_dataset_t *ds, const char *htag,
    +    boolean_t temphold, dmu_tx_t *tx)
    +{
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	objset_t *mos = dp->dp_meta_objset;
    +	int error = 0;
    +
    +	if (strlen(htag) > MAXNAMELEN)
    +		return (E2BIG);
    +	/* Tempholds have a more restricted length */
    +	if (temphold && strlen(htag) + MAX_TAG_PREFIX_LEN >= MAXNAMELEN)
    +		return (E2BIG);
    +
    +	/* tags must be unique (if ds already exists) */
    +	if (ds != NULL) {
    +		mutex_enter(&ds->ds_lock);
    +		if (ds->ds_phys->ds_userrefs_obj != 0) {
    +			uint64_t value;
    +			error = zap_lookup(mos, ds->ds_phys->ds_userrefs_obj,
    +			    htag, 8, 1, &value);
    +			if (error == 0)
    +				error = EEXIST;
    +			else if (error == ENOENT)
    +				error = 0;
    +		}
    +		mutex_exit(&ds->ds_lock);
    +	}
    +
    +	return (error);
    +}
    +
    +static int
    +dsl_dataset_user_hold_check(void *arg, dmu_tx_t *tx)
    +{
    +	dsl_dataset_user_hold_arg_t *dduha = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	nvpair_t *pair;
    +	int rv = 0;
    +
    +	if (spa_version(dp->dp_spa) < SPA_VERSION_USERREFS)
    +		return (ENOTSUP);
    +
    +	for (pair = nvlist_next_nvpair(dduha->dduha_holds, NULL); pair != NULL;
    +	    pair = nvlist_next_nvpair(dduha->dduha_holds, pair)) {
    +		int error = 0;
    +		dsl_dataset_t *ds;
    +		char *htag;
    +
    +		/* must be a snapshot */
    +		if (strchr(nvpair_name(pair), '@') == NULL)
    +			error = EINVAL;
    +
    +		if (error == 0)
    +			error = nvpair_value_string(pair, &htag);
    +		if (error == 0) {
    +			error = dsl_dataset_hold(dp,
    +			    nvpair_name(pair), FTAG, &ds);
    +		}
    +		if (error == 0) {
    +			error = dsl_dataset_user_hold_check_one(ds, htag,
    +			    dduha->dduha_minor != 0, tx);
    +			dsl_dataset_rele(ds, FTAG);
    +		}
    +
    +		if (error != 0) {
    +			rv = error;
    +			fnvlist_add_int32(dduha->dduha_errlist,
    +			    nvpair_name(pair), error);
    +		}
    +	}
    +	return (rv);
    +}
    +
    +void
    +dsl_dataset_user_hold_sync_one(dsl_dataset_t *ds, const char *htag,
    +    minor_t minor, uint64_t now, dmu_tx_t *tx)
    +{
    +	dsl_pool_t *dp = ds->ds_dir->dd_pool;
    +	objset_t *mos = dp->dp_meta_objset;
    +	uint64_t zapobj;
    +
    +	mutex_enter(&ds->ds_lock);
    +	if (ds->ds_phys->ds_userrefs_obj == 0) {
    +		/*
    +		 * This is the first user hold for this dataset.  Create
    +		 * the userrefs zap object.
    +		 */
    +		dmu_buf_will_dirty(ds->ds_dbuf, tx);
    +		zapobj = ds->ds_phys->ds_userrefs_obj =
    +		    zap_create(mos, DMU_OT_USERREFS, DMU_OT_NONE, 0, tx);
    +	} else {
    +		zapobj = ds->ds_phys->ds_userrefs_obj;
    +	}
    +	ds->ds_userrefs++;
    +	mutex_exit(&ds->ds_lock);
    +
    +	VERIFY0(zap_add(mos, zapobj, htag, 8, 1, &now, tx));
    +
    +	if (minor != 0) {
    +		VERIFY0(dsl_pool_user_hold(dp, ds->ds_object,
    +		    htag, now, tx));
    +		dsl_register_onexit_hold_cleanup(ds, htag, minor);
    +	}
    +
    +	spa_history_log_internal_ds(ds, "hold", tx,
    +	    "tag=%s temp=%d refs=%llu",
    +	    htag, minor != 0, ds->ds_userrefs);
    +}
    +
    +static void
    +dsl_dataset_user_hold_sync(void *arg, dmu_tx_t *tx)
    +{
    +	dsl_dataset_user_hold_arg_t *dduha = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	nvpair_t *pair;
    +	uint64_t now = gethrestime_sec();
    +
    +	for (pair = nvlist_next_nvpair(dduha->dduha_holds, NULL); pair != NULL;
    +	    pair = nvlist_next_nvpair(dduha->dduha_holds, pair)) {
    +		dsl_dataset_t *ds;
    +		VERIFY0(dsl_dataset_hold(dp, nvpair_name(pair), FTAG, &ds));
    +		dsl_dataset_user_hold_sync_one(ds, fnvpair_value_string(pair),
    +		    dduha->dduha_minor, now, tx);
    +		dsl_dataset_rele(ds, FTAG);
    +	}
    +}
    +
    +/*
    + * holds is nvl of snapname -> holdname
    + * errlist will be filled in with snapname -> error
    + * if cleanup_minor is not 0, the holds will be temporary, cleaned up
    + * when the process exits.
    + *
    + * if any fails, all will fail.
    + */
    +int
    +dsl_dataset_user_hold(nvlist_t *holds, minor_t cleanup_minor, nvlist_t *errlist)
    +{
    +	dsl_dataset_user_hold_arg_t dduha;
    +	nvpair_t *pair;
    +
    +	pair = nvlist_next_nvpair(holds, NULL);
    +	if (pair == NULL)
    +		return (0);
    +
    +	dduha.dduha_holds = holds;
    +	dduha.dduha_errlist = errlist;
    +	dduha.dduha_minor = cleanup_minor;
    +
    +	return (dsl_sync_task(nvpair_name(pair), dsl_dataset_user_hold_check,
    +	    dsl_dataset_user_hold_sync, &dduha, fnvlist_num_pairs(holds)));
    +}
    +
    +typedef struct dsl_dataset_user_release_arg {
    +	nvlist_t *ddura_holds;
    +	nvlist_t *ddura_todelete;
    +	nvlist_t *ddura_errlist;
    +} dsl_dataset_user_release_arg_t;
    +
    +static int
    +dsl_dataset_user_release_check_one(dsl_dataset_t *ds,
    +    nvlist_t *holds, boolean_t *todelete)
    +{
    +	uint64_t zapobj;
    +	nvpair_t *pair;
    +	objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
    +	int error;
    +	int numholds = 0;
    +
    +	*todelete = B_FALSE;
    +
    +	if (!dsl_dataset_is_snapshot(ds))
    +		return (EINVAL);
    +
    +	zapobj = ds->ds_phys->ds_userrefs_obj;
    +	if (zapobj == 0)
    +		return (ESRCH);
    +
    +	for (pair = nvlist_next_nvpair(holds, NULL); pair != NULL;
    +	    pair = nvlist_next_nvpair(holds, pair)) {
    +		/* Make sure the hold exists */
    +		uint64_t tmp;
    +		error = zap_lookup(mos, zapobj, nvpair_name(pair), 8, 1, &tmp);
    +		if (error == ENOENT)
    +			error = ESRCH;
    +		if (error != 0)
    +			return (error);
    +		numholds++;
    +	}
    +
    +	if (DS_IS_DEFER_DESTROY(ds) && ds->ds_phys->ds_num_children == 1 &&
    +	    ds->ds_userrefs == numholds) {
    +		/* we need to destroy the snapshot as well */
    +
    +		if (dsl_dataset_long_held(ds))
    +			return (EBUSY);
    +		*todelete = B_TRUE;
    +	}
    +	return (0);
    +}
    +
    +static int
    +dsl_dataset_user_release_check(void *arg, dmu_tx_t *tx)
    +{
    +	dsl_dataset_user_release_arg_t *ddura = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	nvpair_t *pair;
    +	int rv = 0;
    +
    +	if (!dmu_tx_is_syncing(tx))
    +		return (0);
    +
    +	for (pair = nvlist_next_nvpair(ddura->ddura_holds, NULL); pair != NULL;
    +	    pair = nvlist_next_nvpair(ddura->ddura_holds, pair)) {
    +		const char *name = nvpair_name(pair);
    +		int error;
    +		dsl_dataset_t *ds;
    +		nvlist_t *holds;
    +
    +		error = nvpair_value_nvlist(pair, &holds);
    +		if (error != 0)
    +			return (EINVAL);
    +
    +		error = dsl_dataset_hold(dp, name, FTAG, &ds);
    +		if (error == 0) {
    +			boolean_t deleteme;
    +			error = dsl_dataset_user_release_check_one(ds,
    +			    holds, &deleteme);
    +			if (error == 0 && deleteme) {
    +				fnvlist_add_boolean(ddura->ddura_todelete,
    +				    name);
    +			}
    +			dsl_dataset_rele(ds, FTAG);
    +		}
    +		if (error != 0) {
    +			if (ddura->ddura_errlist != NULL) {
    +				fnvlist_add_int32(ddura->ddura_errlist,
    +				    name, error);
    +			}
    +			rv = error;
    +		}
    +	}
    +	return (rv);
    +}
    +
    +static void
    +dsl_dataset_user_release_sync_one(dsl_dataset_t *ds, nvlist_t *holds,
    +    dmu_tx_t *tx)
    +{
    +	dsl_pool_t *dp = ds->ds_dir->dd_pool;
    +	objset_t *mos = dp->dp_meta_objset;
    +	uint64_t zapobj;
    +	int error;
    +	nvpair_t *pair;
    +
    +	for (pair = nvlist_next_nvpair(holds, NULL); pair != NULL;
    +	    pair = nvlist_next_nvpair(holds, pair)) {
    +		ds->ds_userrefs--;
    +		error = dsl_pool_user_release(dp, ds->ds_object,
    +		    nvpair_name(pair), tx);
    +		VERIFY(error == 0 || error == ENOENT);
    +		zapobj = ds->ds_phys->ds_userrefs_obj;
    +		VERIFY0(zap_remove(mos, zapobj, nvpair_name(pair), tx));
    +
    +		spa_history_log_internal_ds(ds, "release", tx,
    +		    "tag=%s refs=%lld", nvpair_name(pair),
    +		    (longlong_t)ds->ds_userrefs);
    +	}
    +}
    +
    +static void
    +dsl_dataset_user_release_sync(void *arg, dmu_tx_t *tx)
    +{
    +	dsl_dataset_user_release_arg_t *ddura = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	nvpair_t *pair;
    +
    +	for (pair = nvlist_next_nvpair(ddura->ddura_holds, NULL); pair != NULL;
    +	    pair = nvlist_next_nvpair(ddura->ddura_holds, pair)) {
    +		dsl_dataset_t *ds;
    +
    +		VERIFY0(dsl_dataset_hold(dp, nvpair_name(pair), FTAG, &ds));
    +		dsl_dataset_user_release_sync_one(ds,
    +		    fnvpair_value_nvlist(pair), tx);
    +		if (nvlist_exists(ddura->ddura_todelete,
    +		    nvpair_name(pair))) {
    +			ASSERT(ds->ds_userrefs == 0 &&
    +			    ds->ds_phys->ds_num_children == 1 &&
    +			    DS_IS_DEFER_DESTROY(ds));
    +			dsl_destroy_snapshot_sync_impl(ds, B_FALSE, tx);
    +		}
    +		dsl_dataset_rele(ds, FTAG);
    +	}
    +}
    +
    +/*
    + * holds is nvl of snapname -> { holdname, ... }
    + * errlist will be filled in with snapname -> error
    + *
    + * if any fails, all will fail.
    + */
    +int
    +dsl_dataset_user_release(nvlist_t *holds, nvlist_t *errlist)
    +{
    +	dsl_dataset_user_release_arg_t ddura;
    +	nvpair_t *pair;
    +	int error;
    +
    +	pair = nvlist_next_nvpair(holds, NULL);
    +	if (pair == NULL)
    +		return (0);
    +
    +	ddura.ddura_holds = holds;
    +	ddura.ddura_errlist = errlist;
    +	ddura.ddura_todelete = fnvlist_alloc();
    +
    +	error = dsl_sync_task(nvpair_name(pair), dsl_dataset_user_release_check,
    +	    dsl_dataset_user_release_sync, &ddura, fnvlist_num_pairs(holds));
    +	fnvlist_free(ddura.ddura_todelete);
    +	return (error);
    +}
    +
    +typedef struct dsl_dataset_user_release_tmp_arg {
    +	uint64_t ddurta_dsobj;
    +	nvlist_t *ddurta_holds;
    +	boolean_t ddurta_deleteme;
    +} dsl_dataset_user_release_tmp_arg_t;
    +
    +static int
    +dsl_dataset_user_release_tmp_check(void *arg, dmu_tx_t *tx)
    +{
    +	dsl_dataset_user_release_tmp_arg_t *ddurta = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	dsl_dataset_t *ds;
    +	int error;
    +
    +	if (!dmu_tx_is_syncing(tx))
    +		return (0);
    +
    +	error = dsl_dataset_hold_obj(dp, ddurta->ddurta_dsobj, FTAG, &ds);
    +	if (error)
    +		return (error);
    +
    +	error = dsl_dataset_user_release_check_one(ds,
    +	    ddurta->ddurta_holds, &ddurta->ddurta_deleteme);
    +	dsl_dataset_rele(ds, FTAG);
    +	return (error);
    +}
    +
    +static void
    +dsl_dataset_user_release_tmp_sync(void *arg, dmu_tx_t *tx)
    +{
    +	dsl_dataset_user_release_tmp_arg_t *ddurta = arg;
    +	dsl_pool_t *dp = dmu_tx_pool(tx);
    +	dsl_dataset_t *ds;
    +
    +	VERIFY0(dsl_dataset_hold_obj(dp, ddurta->ddurta_dsobj, FTAG, &ds));
    +	dsl_dataset_user_release_sync_one(ds, ddurta->ddurta_holds, tx);
    +	if (ddurta->ddurta_deleteme) {
    +		ASSERT(ds->ds_userrefs == 0 &&
    +		    ds->ds_phys->ds_num_children == 1 &&
    +		    DS_IS_DEFER_DESTROY(ds));
    +		dsl_destroy_snapshot_sync_impl(ds, B_FALSE, tx);
    +	}
    +	dsl_dataset_rele(ds, FTAG);
    +}
    +
    +/*
    + * Called at spa_load time to release a stale temporary user hold.
    + * Also called by the onexit code.
    + */
    +void
    +dsl_dataset_user_release_tmp(dsl_pool_t *dp, uint64_t dsobj, const char *htag)
    +{
    +	dsl_dataset_user_release_tmp_arg_t ddurta;
    +	dsl_dataset_t *ds;
    +	int error;
    +
    +#ifdef _KERNEL
    +	/* Make sure it is not mounted. */
    +	dsl_pool_config_enter(dp, FTAG);
    +	error = dsl_dataset_hold_obj(dp, dsobj, FTAG, &ds);
    +	if (error == 0) {
    +		char name[MAXNAMELEN];
    +		dsl_dataset_name(ds, name);
    +		dsl_dataset_rele(ds, FTAG);
    +		dsl_pool_config_exit(dp, FTAG);
    +		zfs_unmount_snap(name);
    +	} else {
    +		dsl_pool_config_exit(dp, FTAG);
    +	}
    +#endif
    +
    +	ddurta.ddurta_dsobj = dsobj;
    +	ddurta.ddurta_holds = fnvlist_alloc();
    +	fnvlist_add_boolean(ddurta.ddurta_holds, htag);
    +
    +	(void) dsl_sync_task(spa_name(dp->dp_spa),
    +	    dsl_dataset_user_release_tmp_check,
    +	    dsl_dataset_user_release_tmp_sync, &ddurta, 1);
    +	fnvlist_free(ddurta.ddurta_holds);
    +}
    +
    +typedef struct zfs_hold_cleanup_arg {
    +	char zhca_spaname[MAXNAMELEN];
    +	uint64_t zhca_spa_load_guid;
    +	uint64_t zhca_dsobj;
    +	char zhca_htag[MAXNAMELEN];
    +} zfs_hold_cleanup_arg_t;
    +
    +static void
    +dsl_dataset_user_release_onexit(void *arg)
    +{
    +	zfs_hold_cleanup_arg_t *ca = arg;
    +	spa_t *spa;
    +	int error;
    +
    +	error = spa_open(ca->zhca_spaname, &spa, FTAG);
    +	if (error != 0) {
    +		zfs_dbgmsg("couldn't release hold on pool=%s ds=%llu tag=%s "
    +		    "because pool is no longer loaded",
    +		    ca->zhca_spaname, ca->zhca_dsobj, ca->zhca_htag);
    +		return;
    +	}
    +	if (spa_load_guid(spa) != ca->zhca_spa_load_guid) {
    +		zfs_dbgmsg("couldn't release hold on pool=%s ds=%llu tag=%s "
    +		    "because pool is no longer loaded (guid doesn't match)",
    +		    ca->zhca_spaname, ca->zhca_dsobj, ca->zhca_htag);
    +		spa_close(spa, FTAG);
    +		return;
    +	}
    +
    +	dsl_dataset_user_release_tmp(spa_get_dsl(spa),
    +	    ca->zhca_dsobj, ca->zhca_htag);
    +	kmem_free(ca, sizeof (zfs_hold_cleanup_arg_t));
    +	spa_close(spa, FTAG);
    +}
    +
    +void
    +dsl_register_onexit_hold_cleanup(dsl_dataset_t *ds, const char *htag,
    +    minor_t minor)
    +{
    +	zfs_hold_cleanup_arg_t *ca = kmem_alloc(sizeof (*ca), KM_SLEEP);
    +	spa_t *spa = dsl_dataset_get_spa(ds);
    +	(void) strlcpy(ca->zhca_spaname, spa_name(spa),
    +	    sizeof (ca->zhca_spaname));
    +	ca->zhca_spa_load_guid = spa_load_guid(spa);
    +	ca->zhca_dsobj = ds->ds_object;
    +	(void) strlcpy(ca->zhca_htag, htag, sizeof (ca->zhca_htag));
    +	VERIFY0(zfs_onexit_add_cb(minor,
    +	    dsl_dataset_user_release_onexit, ca, NULL));
    +}
    +
    +int
    +dsl_dataset_get_holds(const char *dsname, nvlist_t *nvl)
    +{
    +	dsl_pool_t *dp;
    +	dsl_dataset_t *ds;
    +	int err;
    +
    +	err = dsl_pool_hold(dsname, FTAG, &dp);
    +	if (err != 0)
    +		return (err);
    +	err = dsl_dataset_hold(dp, dsname, FTAG, &ds);
    +	if (err != 0) {
    +		dsl_pool_rele(dp, FTAG);
    +		return (err);
    +	}
    +
    +	if (ds->ds_phys->ds_userrefs_obj != 0) {
    +		zap_attribute_t *za;
    +		zap_cursor_t zc;
    +
    +		za = kmem_alloc(sizeof (zap_attribute_t), KM_SLEEP);
    +		for (zap_cursor_init(&zc, ds->ds_dir->dd_pool->dp_meta_objset,
    +		    ds->ds_phys->ds_userrefs_obj);
    +		    zap_cursor_retrieve(&zc, za) == 0;
    +		    zap_cursor_advance(&zc)) {
    +			fnvlist_add_uint64(nvl, za->za_name,
    +			    za->za_first_integer);
    +		}
    +		zap_cursor_fini(&zc);
    +		kmem_free(za, sizeof (zap_attribute_t));
    +	}
    +	dsl_dataset_rele(ds, FTAG);
    +	dsl_pool_rele(dp, FTAG);
    +	return (0);
    +}
    diff --git a/uts/common/fs/zfs/metaslab.c b/uts/common/fs/zfs/metaslab.c
    index bf9889e183d..aae2ccd5d9e 100644
    --- a/uts/common/fs/zfs/metaslab.c
    +++ b/uts/common/fs/zfs/metaslab.c
    @@ -1866,3 +1866,41 @@ metaslab_claim(spa_t *spa, const blkptr_t *bp, uint64_t txg)
     
     	return (error);
     }
    +
    +static void
    +checkmap(space_map_t *sm, uint64_t off, uint64_t size)
    +{
    +	space_seg_t *ss;
    +	avl_index_t where;
    +
    +	mutex_enter(sm->sm_lock);
    +	ss = space_map_find(sm, off, size, &where);
    +	if (ss != NULL)
    +		panic("freeing free block; ss=%p", (void *)ss);
    +	mutex_exit(sm->sm_lock);
    +}
    +
    +void
    +metaslab_check_free(spa_t *spa, const blkptr_t *bp)
    +{
    +	if ((zfs_flags & ZFS_DEBUG_ZIO_FREE) == 0)
    +		return;
    +
    +	spa_config_enter(spa, SCL_VDEV, FTAG, RW_READER);
    +	for (int i = 0; i < BP_GET_NDVAS(bp); i++) {
    +		uint64_t vdid = DVA_GET_VDEV(&bp->blk_dva[i]);
    +		vdev_t *vd = vdev_lookup_top(spa, vdid);
    +		uint64_t off = DVA_GET_OFFSET(&bp->blk_dva[i]);
    +		uint64_t size = DVA_GET_ASIZE(&bp->blk_dva[i]);
    +		metaslab_t *ms = vd->vdev_ms[off >> vd->vdev_ms_shift];
    +
    +		if (ms->ms_map->sm_loaded)
    +			checkmap(ms->ms_map, off, size);
    +
    +		for (int j = 0; j < TXG_SIZE; j++)
    +			checkmap(ms->ms_freemap[j], off, size);
    +		for (int j = 0; j < TXG_DEFER_SIZE; j++)
    +			checkmap(ms->ms_defermap[j], off, size);
    +	}
    +	spa_config_exit(spa, SCL_VDEV, FTAG);
    +}
    diff --git a/uts/common/fs/zfs/refcount.c b/uts/common/fs/zfs/refcount.c
    index 3a8e144e909..df0f2568495 100644
    --- a/uts/common/fs/zfs/refcount.c
    +++ b/uts/common/fs/zfs/refcount.c
    @@ -20,6 +20,7 @@
      */
     /*
      * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2012 by Delphix. All rights reserved.
      */
     
     #include 
    @@ -32,7 +33,7 @@ int reference_tracking_enable = FALSE; /* runs out of memory too easily */
     #else
     int reference_tracking_enable = TRUE;
     #endif
    -int reference_history = 4; /* tunable */
    +int reference_history = 3; /* tunable */
     
     static kmem_cache_t *reference_cache;
     static kmem_cache_t *reference_history_cache;
    @@ -64,6 +65,14 @@ refcount_create(refcount_t *rc)
     	    offsetof(reference_t, ref_link));
     	rc->rc_count = 0;
     	rc->rc_removed_count = 0;
    +	rc->rc_tracked = reference_tracking_enable;
    +}
    +
    +void
    +refcount_create_untracked(refcount_t *rc)
    +{
    +	refcount_create(rc);
    +	rc->rc_tracked = B_FALSE;
     }
     
     void
    @@ -96,14 +105,12 @@ refcount_destroy(refcount_t *rc)
     int
     refcount_is_zero(refcount_t *rc)
     {
    -	ASSERT(rc->rc_count >= 0);
     	return (rc->rc_count == 0);
     }
     
     int64_t
     refcount_count(refcount_t *rc)
     {
    -	ASSERT(rc->rc_count >= 0);
     	return (rc->rc_count);
     }
     
    @@ -113,14 +120,14 @@ refcount_add_many(refcount_t *rc, uint64_t number, void *holder)
     	reference_t *ref = NULL;
     	int64_t count;
     
    -	if (reference_tracking_enable) {
    +	if (rc->rc_tracked) {
     		ref = kmem_cache_alloc(reference_cache, KM_SLEEP);
     		ref->ref_holder = holder;
     		ref->ref_number = number;
     	}
     	mutex_enter(&rc->rc_mtx);
     	ASSERT(rc->rc_count >= 0);
    -	if (reference_tracking_enable)
    +	if (rc->rc_tracked)
     		list_insert_head(&rc->rc_list, ref);
     	rc->rc_count += number;
     	count = rc->rc_count;
    @@ -144,7 +151,7 @@ refcount_remove_many(refcount_t *rc, uint64_t number, void *holder)
     	mutex_enter(&rc->rc_mtx);
     	ASSERT(rc->rc_count >= number);
     
    -	if (!reference_tracking_enable) {
    +	if (!rc->rc_tracked) {
     		rc->rc_count -= number;
     		count = rc->rc_count;
     		mutex_exit(&rc->rc_mtx);
    @@ -161,7 +168,7 @@ refcount_remove_many(refcount_t *rc, uint64_t number, void *holder)
     				    KM_SLEEP);
     				list_insert_head(&rc->rc_removed, ref);
     				rc->rc_removed_count++;
    -				if (rc->rc_removed_count >= reference_history) {
    +				if (rc->rc_removed_count > reference_history) {
     					ref = list_tail(&rc->rc_removed);
     					list_remove(&rc->rc_removed, ref);
     					kmem_cache_free(reference_history_cache,
    diff --git a/uts/common/fs/zfs/rrwlock.c b/uts/common/fs/zfs/rrwlock.c
    index 7f9290bd44c..8e80166c7d1 100644
    --- a/uts/common/fs/zfs/rrwlock.c
    +++ b/uts/common/fs/zfs/rrwlock.c
    @@ -75,8 +75,9 @@
     uint_t rrw_tsd_key;
     
     typedef struct rrw_node {
    -	struct rrw_node	*rn_next;
    -	rrwlock_t	*rn_rrl;
    +	struct rrw_node *rn_next;
    +	rrwlock_t *rn_rrl;
    +	void *rn_tag;
     } rrw_node_t;
     
     static rrw_node_t *
    @@ -98,13 +99,14 @@ rrn_find(rrwlock_t *rrl)
      * Add a node to the head of the singly linked list.
      */
     static void
    -rrn_add(rrwlock_t *rrl)
    +rrn_add(rrwlock_t *rrl, void *tag)
     {
     	rrw_node_t *rn;
     
     	rn = kmem_alloc(sizeof (*rn), KM_SLEEP);
     	rn->rn_rrl = rrl;
     	rn->rn_next = tsd_get(rrw_tsd_key);
    +	rn->rn_tag = tag;
     	VERIFY(tsd_set(rrw_tsd_key, rn) == 0);
     }
     
    @@ -113,7 +115,7 @@ rrn_add(rrwlock_t *rrl)
      * thread's list and return TRUE; otherwise return FALSE.
      */
     static boolean_t
    -rrn_find_and_remove(rrwlock_t *rrl)
    +rrn_find_and_remove(rrwlock_t *rrl, void *tag)
     {
     	rrw_node_t *rn;
     	rrw_node_t *prev = NULL;
    @@ -122,7 +124,7 @@ rrn_find_and_remove(rrwlock_t *rrl)
     		return (B_FALSE);
     
     	for (rn = tsd_get(rrw_tsd_key); rn != NULL; rn = rn->rn_next) {
    -		if (rn->rn_rrl == rrl) {
    +		if (rn->rn_rrl == rrl && rn->rn_tag == tag) {
     			if (prev)
     				prev->rn_next = rn->rn_next;
     			else
    @@ -136,7 +138,7 @@ rrn_find_and_remove(rrwlock_t *rrl)
     }
     
     void
    -rrw_init(rrwlock_t *rrl)
    +rrw_init(rrwlock_t *rrl, boolean_t track_all)
     {
     	mutex_init(&rrl->rr_lock, NULL, MUTEX_DEFAULT, NULL);
     	cv_init(&rrl->rr_cv, NULL, CV_DEFAULT, NULL);
    @@ -144,6 +146,7 @@ rrw_init(rrwlock_t *rrl)
     	refcount_create(&rrl->rr_anon_rcount);
     	refcount_create(&rrl->rr_linked_rcount);
     	rrl->rr_writer_wanted = B_FALSE;
    +	rrl->rr_track_all = track_all;
     }
     
     void
    @@ -156,12 +159,13 @@ rrw_destroy(rrwlock_t *rrl)
     	refcount_destroy(&rrl->rr_linked_rcount);
     }
     
    -static void
    +void
     rrw_enter_read(rrwlock_t *rrl, void *tag)
     {
     	mutex_enter(&rrl->rr_lock);
     #if !defined(DEBUG) && defined(_KERNEL)
    -	if (!rrl->rr_writer && !rrl->rr_writer_wanted) {
    +	if (rrl->rr_writer == NULL && !rrl->rr_writer_wanted &&
    +	    !rrl->rr_track_all) {
     		rrl->rr_anon_rcount.rc_count++;
     		mutex_exit(&rrl->rr_lock);
     		return;
    @@ -171,14 +175,14 @@ rrw_enter_read(rrwlock_t *rrl, void *tag)
     	ASSERT(rrl->rr_writer != curthread);
     	ASSERT(refcount_count(&rrl->rr_anon_rcount) >= 0);
     
    -	while (rrl->rr_writer || (rrl->rr_writer_wanted &&
    +	while (rrl->rr_writer != NULL || (rrl->rr_writer_wanted &&
     	    refcount_is_zero(&rrl->rr_anon_rcount) &&
     	    rrn_find(rrl) == NULL))
     		cv_wait(&rrl->rr_cv, &rrl->rr_lock);
     
    -	if (rrl->rr_writer_wanted) {
    +	if (rrl->rr_writer_wanted || rrl->rr_track_all) {
     		/* may or may not be a re-entrant enter */
    -		rrn_add(rrl);
    +		rrn_add(rrl, tag);
     		(void) refcount_add(&rrl->rr_linked_rcount, tag);
     	} else {
     		(void) refcount_add(&rrl->rr_anon_rcount, tag);
    @@ -187,7 +191,7 @@ rrw_enter_read(rrwlock_t *rrl, void *tag)
     	mutex_exit(&rrl->rr_lock);
     }
     
    -static void
    +void
     rrw_enter_write(rrwlock_t *rrl)
     {
     	mutex_enter(&rrl->rr_lock);
    @@ -233,10 +237,12 @@ rrw_exit(rrwlock_t *rrl, void *tag)
     
     	if (rrl->rr_writer == NULL) {
     		int64_t count;
    -		if (rrn_find_and_remove(rrl))
    +		if (rrn_find_and_remove(rrl, tag)) {
     			count = refcount_remove(&rrl->rr_linked_rcount, tag);
    -		else
    +		} else {
    +			ASSERT(!rrl->rr_track_all);
     			count = refcount_remove(&rrl->rr_anon_rcount, tag);
    +		}
     		if (count == 0)
     			cv_broadcast(&rrl->rr_cv);
     	} else {
    @@ -249,6 +255,11 @@ rrw_exit(rrwlock_t *rrl, void *tag)
     	mutex_exit(&rrl->rr_lock);
     }
     
    +/*
    + * If the lock was created with track_all, rrw_held(RW_READER) will return
    + * B_TRUE iff the current thread has the lock for reader.  Otherwise it may
    + * return B_TRUE if any thread has the lock for reader.
    + */
     boolean_t
     rrw_held(rrwlock_t *rrl, krw_t rw)
     {
    @@ -259,7 +270,7 @@ rrw_held(rrwlock_t *rrl, krw_t rw)
     		held = (rrl->rr_writer == curthread);
     	} else {
     		held = (!refcount_is_zero(&rrl->rr_anon_rcount) ||
    -		    !refcount_is_zero(&rrl->rr_linked_rcount));
    +		    rrn_find(rrl) != NULL);
     	}
     	mutex_exit(&rrl->rr_lock);
     
    diff --git a/uts/common/fs/zfs/sa.c b/uts/common/fs/zfs/sa.c
    index cd3a58b5fa9..05f329c6474 100644
    --- a/uts/common/fs/zfs/sa.c
    +++ b/uts/common/fs/zfs/sa.c
    @@ -1001,10 +1001,10 @@ sa_setup(objset_t *os, uint64_t sa_obj, sa_attr_reg_t *reg_attrs, int count,
     	sa_attr_type_t *tb;
     	int error;
     
    -	mutex_enter(&os->os_lock);
    +	mutex_enter(&os->os_user_ptr_lock);
     	if (os->os_sa) {
     		mutex_enter(&os->os_sa->sa_lock);
    -		mutex_exit(&os->os_lock);
    +		mutex_exit(&os->os_user_ptr_lock);
     		tb = os->os_sa->sa_user_table;
     		mutex_exit(&os->os_sa->sa_lock);
     		*user_table = tb;
    @@ -1017,7 +1017,7 @@ sa_setup(objset_t *os, uint64_t sa_obj, sa_attr_reg_t *reg_attrs, int count,
     
     	os->os_sa = sa;
     	mutex_enter(&sa->sa_lock);
    -	mutex_exit(&os->os_lock);
    +	mutex_exit(&os->os_user_ptr_lock);
     	avl_create(&sa->sa_layout_num_tree, layout_num_compare,
     	    sizeof (sa_lot_t), offsetof(sa_lot_t, lot_num_node));
     	avl_create(&sa->sa_layout_hash_tree, layout_hash_compare,
    diff --git a/uts/common/fs/zfs/spa.c b/uts/common/fs/zfs/spa.c
    index fdc28700c82..544a0407c1b 100644
    --- a/uts/common/fs/zfs/spa.c
    +++ b/uts/common/fs/zfs/spa.c
    @@ -63,6 +63,7 @@
     #include 
     #include 
     #include 
    +#include 
     
     #ifdef	_KERNEL
     #include 
    @@ -129,10 +130,8 @@ const zio_taskq_info_t zio_taskqs[ZIO_TYPES][ZIO_TASKQ_TYPES] = {
     	{ ZTI_ONE,	ZTI_NULL,	ZTI_ONE,	ZTI_NULL }, /* IOCTL */
     };
     
    -static dsl_syncfunc_t spa_sync_version;
    -static dsl_syncfunc_t spa_sync_props;
    -static dsl_checkfunc_t spa_change_guid_check;
    -static dsl_syncfunc_t spa_change_guid_sync;
    +static void spa_sync_version(void *arg, dmu_tx_t *tx);
    +static void spa_sync_props(void *arg, dmu_tx_t *tx);
     static boolean_t spa_has_active_shared_spare(spa_t *spa);
     static int spa_load_impl(spa_t *spa, uint64_t, nvlist_t *config,
         spa_load_state_t state, spa_import_type_t type, boolean_t mosconfig,
    @@ -325,10 +324,10 @@ spa_prop_get(spa_t *spa, nvlist_t **nvp)
     				dsl_dataset_t *ds = NULL;
     
     				dp = spa_get_dsl(spa);
    -				rw_enter(&dp->dp_config_rwlock, RW_READER);
    +				dsl_pool_config_enter(dp, FTAG);
     				if (err = dsl_dataset_hold_obj(dp,
     				    za.za_first_integer, FTAG, &ds)) {
    -					rw_exit(&dp->dp_config_rwlock);
    +					dsl_pool_config_exit(dp, FTAG);
     					break;
     				}
     
    @@ -337,7 +336,7 @@ spa_prop_get(spa_t *spa, nvlist_t **nvp)
     				    KM_SLEEP);
     				dsl_dataset_name(ds, strval);
     				dsl_dataset_rele(ds, FTAG);
    -				rw_exit(&dp->dp_config_rwlock);
    +				dsl_pool_config_exit(dp, FTAG);
     			} else {
     				strval = NULL;
     				intval = za.za_first_integer;
    @@ -491,9 +490,10 @@ spa_prop_validate(spa_t *spa, nvlist_t *props)
     
     				if (dmu_objset_type(os) != DMU_OST_ZFS) {
     					error = ENOTSUP;
    -				} else if ((error = dsl_prop_get_integer(strval,
    +				} else if ((error =
    +				    dsl_prop_get_int_ds(dmu_objset_ds(os),
     				    zfs_prop_to_name(ZFS_PROP_COMPRESSION),
    -				    &compress, NULL)) == 0 &&
    +				    &compress)) == 0 &&
     				    !BOOTFS_COMPRESS_VALID(compress)) {
     					error = ENOTSUP;
     				} else {
    @@ -660,8 +660,8 @@ spa_prop_set(spa_t *spa, nvlist_t *nvp)
     			 * read object, the features for write object, or the
     			 * feature descriptions object.
     			 */
    -			error = dsl_sync_task_do(spa_get_dsl(spa), NULL,
    -			    spa_sync_version, spa, &ver, 6);
    +			error = dsl_sync_task(spa->spa_name, NULL,
    +			    spa_sync_version, &ver, 6);
     			if (error)
     				return (error);
     			continue;
    @@ -672,8 +672,8 @@ spa_prop_set(spa_t *spa, nvlist_t *nvp)
     	}
     
     	if (need_sync) {
    -		return (dsl_sync_task_do(spa_get_dsl(spa), NULL, spa_sync_props,
    -		    spa, nvp, 6));
    +		return (dsl_sync_task(spa->spa_name, NULL, spa_sync_props,
    +		    nvp, 6));
     	}
     
     	return (0);
    @@ -695,10 +695,10 @@ spa_prop_clear_bootfs(spa_t *spa, uint64_t dsobj, dmu_tx_t *tx)
     
     /*ARGSUSED*/
     static int
    -spa_change_guid_check(void *arg1, void *arg2, dmu_tx_t *tx)
    +spa_change_guid_check(void *arg, dmu_tx_t *tx)
     {
    -	spa_t *spa = arg1;
    -	uint64_t *newguid = arg2;
    +	uint64_t *newguid = arg;
    +	spa_t *spa = dmu_tx_pool(tx)->dp_spa;
     	vdev_t *rvd = spa->spa_root_vdev;
     	uint64_t vdev_state;
     
    @@ -715,10 +715,10 @@ spa_change_guid_check(void *arg1, void *arg2, dmu_tx_t *tx)
     }
     
     static void
    -spa_change_guid_sync(void *arg1, void *arg2, dmu_tx_t *tx)
    +spa_change_guid_sync(void *arg, dmu_tx_t *tx)
     {
    -	spa_t *spa = arg1;
    -	uint64_t *newguid = arg2;
    +	uint64_t *newguid = arg;
    +	spa_t *spa = dmu_tx_pool(tx)->dp_spa;
     	uint64_t oldguid;
     	vdev_t *rvd = spa->spa_root_vdev;
     
    @@ -752,8 +752,8 @@ spa_change_guid(spa_t *spa)
     	mutex_enter(&spa_namespace_lock);
     	guid = spa_generate_guid(NULL);
     
    -	error = dsl_sync_task_do(spa_get_dsl(spa), spa_change_guid_check,
    -	    spa_change_guid_sync, spa, &guid, 5);
    +	error = dsl_sync_task(spa->spa_name, spa_change_guid_check,
    +	    spa_change_guid_sync, &guid, 5);
     
     	if (error == 0) {
     		spa_config_sync(spa, B_FALSE, B_TRUE);
    @@ -1687,21 +1687,22 @@ spa_config_valid(spa_t *spa, nvlist_t *config)
     /*
      * Check for missing log devices
      */
    -static int
    +static boolean_t
     spa_check_logs(spa_t *spa)
     {
    +	boolean_t rv = B_FALSE;
    +
     	switch (spa->spa_log_state) {
     	case SPA_LOG_MISSING:
     		/* need to recheck in case slog has been restored */
     	case SPA_LOG_UNKNOWN:
    -		if (dmu_objset_find(spa->spa_name, zil_check_log_chain, NULL,
    -		    DS_FIND_CHILDREN)) {
    +		rv = (dmu_objset_find(spa->spa_name, zil_check_log_chain,
    +		    NULL, DS_FIND_CHILDREN) != 0);
    +		if (rv)
     			spa_set_log_state(spa, SPA_LOG_MISSING);
    -			return (1);
    -		}
     		break;
     	}
    -	return (0);
    +	return (rv);
     }
     
     static boolean_t
    @@ -1747,11 +1748,11 @@ spa_activate_log(spa_t *spa)
     int
     spa_offline_log(spa_t *spa)
     {
    -	int error = 0;
    -
    -	if ((error = dmu_objset_find(spa_name(spa), zil_vdev_offline,
    -	    NULL, DS_FIND_CHILDREN)) == 0) {
    +	int error;
     
    +	error = dmu_objset_find(spa_name(spa), zil_vdev_offline,
    +	    NULL, DS_FIND_CHILDREN);
    +	if (error == 0) {
     		/*
     		 * We successfully offlined the log device, sync out the
     		 * current txg so that the "stubby" block can be removed
    @@ -3549,7 +3550,7 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
     
     	if (props != NULL) {
     		spa_configfile_set(spa, props, B_FALSE);
    -		spa_sync_props(spa, props, tx);
    +		spa_sync_props(props, tx);
     	}
     
     	dmu_tx_commit(tx);
    @@ -5813,10 +5814,11 @@ spa_sync_config_object(spa_t *spa, dmu_tx_t *tx)
     }
     
     static void
    -spa_sync_version(void *arg1, void *arg2, dmu_tx_t *tx)
    +spa_sync_version(void *arg, dmu_tx_t *tx)
     {
    -	spa_t *spa = arg1;
    -	uint64_t version = *(uint64_t *)arg2;
    +	uint64_t *versionp = arg;
    +	uint64_t version = *versionp;
    +	spa_t *spa = dmu_tx_pool(tx)->dp_spa;
     
     	/*
     	 * Setting the version is special cased when first creating the pool.
    @@ -5835,11 +5837,11 @@ spa_sync_version(void *arg1, void *arg2, dmu_tx_t *tx)
      * Set zpool properties.
      */
     static void
    -spa_sync_props(void *arg1, void *arg2, dmu_tx_t *tx)
    +spa_sync_props(void *arg, dmu_tx_t *tx)
     {
    -	spa_t *spa = arg1;
    +	nvlist_t *nvp = arg;
    +	spa_t *spa = dmu_tx_pool(tx)->dp_spa;
     	objset_t *mos = spa->spa_meta_objset;
    -	nvlist_t *nvp = arg2;
     	nvpair_t *elem = NULL;
     
     	mutex_enter(&spa->spa_props_lock);
    @@ -5990,6 +5992,8 @@ spa_sync_upgrades(spa_t *spa, dmu_tx_t *tx)
     
     	ASSERT(spa->spa_sync_pass == 1);
     
    +	rrw_enter(&dp->dp_config_rwlock, RW_WRITER, FTAG);
    +
     	if (spa->spa_ubsync.ub_version < SPA_VERSION_ORIGIN &&
     	    spa->spa_uberblock.ub_version >= SPA_VERSION_ORIGIN) {
     		dsl_pool_create_origin(dp, tx);
    @@ -6015,6 +6019,7 @@ spa_sync_upgrades(spa_t *spa, dmu_tx_t *tx)
     	    spa->spa_uberblock.ub_version >= SPA_VERSION_FEATURES) {
     		spa_feature_create_zap_objects(spa, tx);
     	}
    +	rrw_exit(&dp->dp_config_rwlock, FTAG);
     }
     
     /*
    diff --git a/uts/common/fs/zfs/spa_history.c b/uts/common/fs/zfs/spa_history.c
    index 9ae28739f37..eef642aa132 100644
    --- a/uts/common/fs/zfs/spa_history.c
    +++ b/uts/common/fs/zfs/spa_history.c
    @@ -195,10 +195,10 @@ spa_history_zone(void)
      */
     /*ARGSUSED*/
     static void
    -spa_history_log_sync(void *arg1, void *arg2, dmu_tx_t *tx)
    +spa_history_log_sync(void *arg, dmu_tx_t *tx)
     {
    -	spa_t		*spa = arg1;
    -	nvlist_t	*nvl = arg2;
    +	nvlist_t	*nvl = arg;
    +	spa_t		*spa = dmu_tx_pool(tx)->dp_spa;
     	objset_t	*mos = spa->spa_meta_objset;
     	dmu_buf_t	*dbp;
     	spa_history_phys_t *shpp;
    @@ -220,7 +220,7 @@ spa_history_log_sync(void *arg1, void *arg2, dmu_tx_t *tx)
     	 * Get the offset of where we need to write via the bonus buffer.
     	 * Update the offset when the write completes.
     	 */
    -	VERIFY(0 == dmu_bonus_hold(mos, spa->spa_history, FTAG, &dbp));
    +	VERIFY0(dmu_bonus_hold(mos, spa->spa_history, FTAG, &dbp));
     	shpp = dbp->db_data;
     
     	dmu_buf_will_dirty(dbp, tx);
    @@ -321,8 +321,8 @@ spa_history_log_nvl(spa_t *spa, nvlist_t *nvl)
     	fnvlist_add_uint64(nvarg, ZPOOL_HIST_WHO, crgetruid(CRED()));
     
     	/* Kick this off asynchronously; errors are ignored. */
    -	dsl_sync_task_do_nowait(spa_get_dsl(spa), NULL,
    -	    spa_history_log_sync, spa, nvarg, 0, tx);
    +	dsl_sync_task_nowait(spa_get_dsl(spa), spa_history_log_sync,
    +	    nvarg, 0, tx);
     	dmu_tx_commit(tx);
     
     	/* spa_history_log_sync will free nvl */
    @@ -455,10 +455,10 @@ log_internal(nvlist_t *nvl, const char *operation, spa_t *spa,
     	fnvlist_add_uint64(nvl, ZPOOL_HIST_TXG, tx->tx_txg);
     
     	if (dmu_tx_is_syncing(tx)) {
    -		spa_history_log_sync(spa, nvl, tx);
    +		spa_history_log_sync(nvl, tx);
     	} else {
    -		dsl_sync_task_do_nowait(spa_get_dsl(spa), NULL,
    -		    spa_history_log_sync, spa, nvl, 0, tx);
    +		dsl_sync_task_nowait(spa_get_dsl(spa),
    +		    spa_history_log_sync, nvl, 0, tx);
     	}
     	/* spa_history_log_sync() will free nvl */
     }
    @@ -530,15 +530,9 @@ spa_history_log_internal_dd(dsl_dir_t *dd, const char *operation,
     void
     spa_history_log_version(spa_t *spa, const char *operation)
     {
    -#ifdef _KERNEL
    -	uint64_t current_vers = spa_version(spa);
    -
     	spa_history_log_internal(spa, operation, NULL,
     	    "pool version %llu; software version %llu/%d; uts %s %s %s %s",
    -	    (u_longlong_t)current_vers, SPA_VERSION, ZPL_VERSION,
    +	    (u_longlong_t)spa_version(spa), SPA_VERSION, ZPL_VERSION,
     	    utsname.nodename, utsname.release, utsname.version,
     	    utsname.machine);
    -	cmn_err(CE_CONT, "!%s version %llu pool %s using %llu", operation,
    -	    (u_longlong_t)current_vers, spa_name(spa), SPA_VERSION);
    -#endif
     }
    diff --git a/uts/common/fs/zfs/spa_misc.c b/uts/common/fs/zfs/spa_misc.c
    index 405d93c6ced..733d2609e55 100644
    --- a/uts/common/fs/zfs/spa_misc.c
    +++ b/uts/common/fs/zfs/spa_misc.c
    @@ -237,8 +237,8 @@ kmem_cache_t *spa_buffer_pool;
     int spa_mode_global;
     
     #ifdef ZFS_DEBUG
    -/* Everything except dprintf is on by default in debug builds */
    -int zfs_flags = ~ZFS_DEBUG_DPRINTF;
    +/* Everything except dprintf and spa is on by default in debug builds */
    +int zfs_flags = ~(ZFS_DEBUG_DPRINTF | ZFS_DEBUG_SPA);
     #else
     int zfs_flags = 0;
     #endif
    @@ -282,7 +282,7 @@ spa_config_lock_init(spa_t *spa)
     		spa_config_lock_t *scl = &spa->spa_config_lock[i];
     		mutex_init(&scl->scl_lock, NULL, MUTEX_DEFAULT, NULL);
     		cv_init(&scl->scl_cv, NULL, CV_DEFAULT, NULL);
    -		refcount_create(&scl->scl_count);
    +		refcount_create_untracked(&scl->scl_count);
     		scl->scl_writer = NULL;
     		scl->scl_write_wanted = 0;
     	}
    @@ -335,6 +335,8 @@ spa_config_enter(spa_t *spa, int locks, void *tag, krw_t rw)
     {
     	int wlocks_held = 0;
     
    +	ASSERT3U(SCL_LOCKS, <, sizeof (wlocks_held) * NBBY);
    +
     	for (int i = 0; i < SCL_LOCKS; i++) {
     		spa_config_lock_t *scl = &spa->spa_config_lock[i];
     		if (scl->scl_writer == curthread)
    @@ -413,27 +415,22 @@ spa_lookup(const char *name)
     	static spa_t search;	/* spa_t is large; don't allocate on stack */
     	spa_t *spa;
     	avl_index_t where;
    -	char c;
     	char *cp;
     
     	ASSERT(MUTEX_HELD(&spa_namespace_lock));
     
    +	(void) strlcpy(search.spa_name, name, sizeof (search.spa_name));
    +
     	/*
     	 * If it's a full dataset name, figure out the pool name and
     	 * just use that.
     	 */
    -	cp = strpbrk(name, "/@");
    -	if (cp) {
    -		c = *cp;
    +	cp = strpbrk(search.spa_name, "/@");
    +	if (cp != NULL)
     		*cp = '\0';
    -	}
     
    -	(void) strlcpy(search.spa_name, name, sizeof (search.spa_name));
     	spa = avl_find(&spa_namespace_avl, &search, &where);
     
    -	if (cp)
    -		*cp = c;
    -
     	return (spa);
     }
     
    @@ -567,6 +564,8 @@ spa_add(const char *name, nvlist_t *config, const char *altroot)
     		kstat_install(spa->spa_iokstat);
     	}
     
    +	spa->spa_debug = ((zfs_flags & ZFS_DEBUG_SPA) != 0);
    +
     	return (spa);
     }
     
    diff --git a/uts/common/fs/zfs/space_map.c b/uts/common/fs/zfs/space_map.c
    index 30a35c85dab..fb30b344704 100644
    --- a/uts/common/fs/zfs/space_map.c
    +++ b/uts/common/fs/zfs/space_map.c
    @@ -102,7 +102,7 @@ void
     space_map_add(space_map_t *sm, uint64_t start, uint64_t size)
     {
     	avl_index_t where;
    -	space_seg_t ssearch, *ss_before, *ss_after, *ss;
    +	space_seg_t *ss_before, *ss_after, *ss;
     	uint64_t end = start + size;
     	int merge_before, merge_after;
     
    @@ -115,11 +115,8 @@ space_map_add(space_map_t *sm, uint64_t start, uint64_t size)
     	VERIFY(P2PHASE(start, 1ULL << sm->sm_shift) == 0);
     	VERIFY(P2PHASE(size, 1ULL << sm->sm_shift) == 0);
     
    -	ssearch.ss_start = start;
    -	ssearch.ss_end = end;
    -	ss = avl_find(&sm->sm_root, &ssearch, &where);
    -
    -	if (ss != NULL && ss->ss_start <= start && ss->ss_end >= end) {
    +	ss = space_map_find(sm, start, size, &where);
    +	if (ss != NULL) {
     		zfs_panic_recover("zfs: allocating allocated segment"
     		    "(offset=%llu size=%llu)\n",
     		    (longlong_t)start, (longlong_t)size);
    @@ -171,19 +168,12 @@ void
     space_map_remove(space_map_t *sm, uint64_t start, uint64_t size)
     {
     	avl_index_t where;
    -	space_seg_t ssearch, *ss, *newseg;
    +	space_seg_t *ss, *newseg;
     	uint64_t end = start + size;
     	int left_over, right_over;
     
    -	ASSERT(MUTEX_HELD(sm->sm_lock));
     	VERIFY(!sm->sm_condensing);
    -	VERIFY(size != 0);
    -	VERIFY(P2PHASE(start, 1ULL << sm->sm_shift) == 0);
    -	VERIFY(P2PHASE(size, 1ULL << sm->sm_shift) == 0);
    -
    -	ssearch.ss_start = start;
    -	ssearch.ss_end = end;
    -	ss = avl_find(&sm->sm_root, &ssearch, &where);
    +	ss = space_map_find(sm, start, size, &where);
     
     	/* Make sure we completely overlap with someone */
     	if (ss == NULL) {
    @@ -226,12 +216,11 @@ space_map_remove(space_map_t *sm, uint64_t start, uint64_t size)
     	sm->sm_space -= size;
     }
     
    -boolean_t
    -space_map_contains(space_map_t *sm, uint64_t start, uint64_t size)
    +space_seg_t *
    +space_map_find(space_map_t *sm, uint64_t start, uint64_t size,
    +    avl_index_t *wherep)
     {
    -	avl_index_t where;
     	space_seg_t ssearch, *ss;
    -	uint64_t end = start + size;
     
     	ASSERT(MUTEX_HELD(sm->sm_lock));
     	VERIFY(size != 0);
    @@ -239,10 +228,20 @@ space_map_contains(space_map_t *sm, uint64_t start, uint64_t size)
     	VERIFY(P2PHASE(size, 1ULL << sm->sm_shift) == 0);
     
     	ssearch.ss_start = start;
    -	ssearch.ss_end = end;
    -	ss = avl_find(&sm->sm_root, &ssearch, &where);
    +	ssearch.ss_end = start + size;
    +	ss = avl_find(&sm->sm_root, &ssearch, wherep);
     
    -	return (ss != NULL && ss->ss_start <= start && ss->ss_end >= end);
    +	if (ss != NULL && ss->ss_start <= start && ss->ss_end >= start + size)
    +		return (ss);
    +	return (NULL);
    +}
    +
    +boolean_t
    +space_map_contains(space_map_t *sm, uint64_t start, uint64_t size)
    +{
    +	avl_index_t where;
    +
    +	return (space_map_find(sm, start, size, &where) != 0);
     }
     
     void
    diff --git a/uts/common/fs/zfs/sys/arc.h b/uts/common/fs/zfs/sys/arc.h
    index 916d2abf147..0e86290f2df 100644
    --- a/uts/common/fs/zfs/sys/arc.h
    +++ b/uts/common/fs/zfs/sys/arc.h
    @@ -89,7 +89,7 @@ arc_buf_t *arc_loan_buf(spa_t *spa, int size);
     void arc_return_buf(arc_buf_t *buf, void *tag);
     void arc_loan_inuse_buf(arc_buf_t *buf, void *tag);
     void arc_buf_add_ref(arc_buf_t *buf, void *tag);
    -int arc_buf_remove_ref(arc_buf_t *buf, void *tag);
    +boolean_t arc_buf_remove_ref(arc_buf_t *buf, void *tag);
     int arc_buf_size(arc_buf_t *buf);
     void arc_release(arc_buf_t *buf, void *tag);
     int arc_released(arc_buf_t *buf);
    diff --git a/uts/common/fs/zfs/sys/dbuf.h b/uts/common/fs/zfs/sys/dbuf.h
    index 8591f158512..a29f7b3ccf1 100644
    --- a/uts/common/fs/zfs/sys/dbuf.h
    +++ b/uts/common/fs/zfs/sys/dbuf.h
    @@ -311,20 +311,17 @@ void dbuf_fini(void);
     
     boolean_t dbuf_is_metadata(dmu_buf_impl_t *db);
     
    -#define	DBUF_IS_METADATA(_db)	\
    -	(dbuf_is_metadata(_db))
    -
     #define	DBUF_GET_BUFC_TYPE(_db)	\
    -	(DBUF_IS_METADATA(_db) ? ARC_BUFC_METADATA : ARC_BUFC_DATA)
    +	(dbuf_is_metadata(_db) ? ARC_BUFC_METADATA : ARC_BUFC_DATA)
     
     #define	DBUF_IS_CACHEABLE(_db)						\
     	((_db)->db_objset->os_primary_cache == ZFS_CACHE_ALL ||		\
    -	(DBUF_IS_METADATA(_db) &&					\
    +	(dbuf_is_metadata(_db) &&					\
     	((_db)->db_objset->os_primary_cache == ZFS_CACHE_METADATA)))
     
     #define	DBUF_IS_L2CACHEABLE(_db)					\
     	((_db)->db_objset->os_secondary_cache == ZFS_CACHE_ALL ||	\
    -	(DBUF_IS_METADATA(_db) &&					\
    +	(dbuf_is_metadata(_db) &&					\
     	((_db)->db_objset->os_secondary_cache == ZFS_CACHE_METADATA)))
     
     #ifdef ZFS_DEBUG
    diff --git a/uts/common/fs/zfs/sys/dmu.h b/uts/common/fs/zfs/sys/dmu.h
    index ef0a6a7c373..1366a998fd5 100644
    --- a/uts/common/fs/zfs/sys/dmu.h
    +++ b/uts/common/fs/zfs/sys/dmu.h
    @@ -217,6 +217,11 @@ typedef enum dmu_object_type {
     	DMU_OTN_ZAP_METADATA = DMU_OT(DMU_BSWAP_ZAP, B_TRUE),
     } dmu_object_type_t;
     
    +typedef enum txg_how {
    +	TXG_WAIT = 1,
    +	TXG_NOWAIT,
    +} txg_how_t;
    +
     void byteswap_uint64_array(void *buf, size_t size);
     void byteswap_uint32_array(void *buf, size_t size);
     void byteswap_uint16_array(void *buf, size_t size);
    @@ -255,22 +260,19 @@ void dmu_objset_rele(objset_t *os, void *tag);
     void dmu_objset_disown(objset_t *os, void *tag);
     int dmu_objset_open_ds(struct dsl_dataset *ds, objset_t **osp);
     
    -int dmu_objset_evict_dbufs(objset_t *os);
    +void dmu_objset_evict_dbufs(objset_t *os);
     int dmu_objset_create(const char *name, dmu_objset_type_t type, uint64_t flags,
         void (*func)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx), void *arg);
    -int dmu_objset_clone(const char *name, struct dsl_dataset *clone_origin,
    -    uint64_t flags);
    -int dmu_objset_destroy(const char *name, boolean_t defer);
    -int dmu_snapshots_destroy_nvl(struct nvlist *snaps, boolean_t defer,
    +int dmu_objset_clone(const char *name, const char *origin);
    +int dsl_destroy_snapshots_nvl(struct nvlist *snaps, boolean_t defer,
         struct nvlist *errlist);
    -int dmu_objset_snapshot(struct nvlist *snaps, struct nvlist *, struct nvlist *);
     int dmu_objset_snapshot_one(const char *fsname, const char *snapname);
     int dmu_objset_snapshot_tmp(const char *, const char *, int);
    -int dmu_objset_rename(const char *name, const char *newname,
    -    boolean_t recursive);
     int dmu_objset_find(char *name, int func(const char *, void *), void *arg,
         int flags);
     void dmu_objset_byteswap(void *buf, size_t size);
    +int dsl_dataset_rename_snapshot(const char *fsname,
    +    const char *oldsnapname, const char *newsnapname, boolean_t recursive);
     
     typedef struct dmu_buf {
     	uint64_t db_object;		/* object that this buffer is part of */
    @@ -545,7 +547,7 @@ void dmu_tx_hold_spill(dmu_tx_t *tx, uint64_t object);
     void dmu_tx_hold_sa(dmu_tx_t *tx, struct sa_handle *hdl, boolean_t may_grow);
     void dmu_tx_hold_sa_create(dmu_tx_t *tx, int total_size);
     void dmu_tx_abort(dmu_tx_t *tx);
    -int dmu_tx_assign(dmu_tx_t *tx, uint64_t txg_how);
    +int dmu_tx_assign(dmu_tx_t *tx, enum txg_how txg_how);
     void dmu_tx_wait(dmu_tx_t *tx);
     void dmu_tx_commit(dmu_tx_t *tx);
     
    @@ -788,36 +790,8 @@ typedef void (*dmu_traverse_cb_t)(objset_t *os, void *arg, struct blkptr *bp,
     void dmu_traverse_objset(objset_t *os, uint64_t txg_start,
         dmu_traverse_cb_t cb, void *arg);
     
    -int dmu_send(objset_t *tosnap, objset_t *fromsnap,
    -    int outfd, struct vnode *vp, offset_t *off);
    -int dmu_send_estimate(objset_t *tosnap, objset_t *fromsnap, uint64_t *sizep);
    -
    -typedef struct dmu_recv_cookie {
    -	/*
    -	 * This structure is opaque!
    -	 *
    -	 * If logical and real are different, we are recving the stream
    -	 * into the "real" temporary clone, and then switching it with
    -	 * the "logical" target.
    -	 */
    -	struct dsl_dataset *drc_logical_ds;
    -	struct dsl_dataset *drc_real_ds;
    -	struct drr_begin *drc_drrb;
    -	char *drc_tosnap;
    -	char *drc_top_ds;
    -	boolean_t drc_newfs;
    -	boolean_t drc_force;
    -	struct avl_tree *drc_guid_to_ds_map;
    -} dmu_recv_cookie_t;
    -
    -int dmu_recv_begin(char *tofs, char *tosnap, char *topds, struct drr_begin *,
    -    boolean_t force, objset_t *origin, dmu_recv_cookie_t *);
    -int dmu_recv_stream(dmu_recv_cookie_t *drc, struct vnode *vp, offset_t *voffp,
    -    int cleanup_fd, uint64_t *action_handlep);
    -int dmu_recv_end(dmu_recv_cookie_t *drc);
    -
    -int dmu_diff(objset_t *tosnap, objset_t *fromsnap, struct vnode *vp,
    -    offset_t *off);
    +int dmu_diff(const char *tosnap_name, const char *fromsnap_name,
    +    struct vnode *vp, offset_t *offp);
     
     /* CRC64 table */
     #define	ZFS_CRC64_POLY	0xC96C5795D7870F42ULL	/* ECMA-182, reflected form */
    diff --git a/uts/common/fs/zfs/sys/dmu_objset.h b/uts/common/fs/zfs/sys/dmu_objset.h
    index 578b94732ed..143e594d1d1 100644
    --- a/uts/common/fs/zfs/sys/dmu_objset.h
    +++ b/uts/common/fs/zfs/sys/dmu_objset.h
    @@ -43,6 +43,7 @@ extern "C" {
     
     extern krwlock_t os_lock;
     
    +struct dsl_pool;
     struct dsl_dataset;
     struct dmu_tx;
     
    @@ -114,8 +115,6 @@ struct objset {
     	/* stuff we store for the user */
     	kmutex_t os_user_ptr_lock;
     	void *os_user_ptr;
    -
    -	/* SA layout/attribute registration */
     	sa_os_t *os_sa;
     };
     
    @@ -143,10 +142,11 @@ void dmu_objset_fast_stat(objset_t *os, dmu_objset_stats_t *stat);
     void dmu_objset_space(objset_t *os, uint64_t *refdbytesp, uint64_t *availbytesp,
         uint64_t *usedobjsp, uint64_t *availobjsp);
     uint64_t dmu_objset_fsid_guid(objset_t *os);
    -int dmu_objset_find_spa(spa_t *spa, const char *name,
    -    int func(spa_t *, uint64_t, const char *, void *), void *arg, int flags);
    +int dmu_objset_find_dp(struct dsl_pool *dp, uint64_t ddobj,
    +    int func(struct dsl_pool *, struct dsl_dataset *, void *),
    +    void *arg, int flags);
     int dmu_objset_prefetch(const char *name, void *arg);
    -int dmu_objset_evict_dbufs(objset_t *os);
    +void dmu_objset_evict_dbufs(objset_t *os);
     timestruc_t dmu_objset_snap_cmtime(objset_t *os);
     
     /* called from dsl */
    @@ -162,6 +162,7 @@ void dmu_objset_userquota_get_ids(dnode_t *dn, boolean_t before, dmu_tx_t *tx);
     boolean_t dmu_objset_userused_enabled(objset_t *os);
     int dmu_objset_userspace_upgrade(objset_t *os);
     boolean_t dmu_objset_userspace_present(objset_t *os);
    +int dmu_fsname(const char *snapname, char *buf);
     
     void dmu_objset_init(void);
     void dmu_objset_fini(void);
    diff --git a/uts/common/fs/zfs/sys/dmu_send.h b/uts/common/fs/zfs/sys/dmu_send.h
    new file mode 100644
    index 00000000000..ee0885a60ff
    --- /dev/null
    +++ b/uts/common/fs/zfs/sys/dmu_send.h
    @@ -0,0 +1,66 @@
    +/*
    + * CDDL HEADER START
    + *
    + * The contents of this file are subject to the terms of the
    + * Common Development and Distribution License (the "License").
    + * You may not use this file except in compliance with the License.
    + *
    + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
    + * or http://www.opensolaris.org/os/licensing.
    + * See the License for the specific language governing permissions
    + * and limitations under the License.
    + *
    + * When distributing Covered Code, include this CDDL HEADER in each
    + * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
    + * If applicable, add the following below this CDDL HEADER, with the
    + * fields enclosed by brackets "[]" replaced with your own identifying
    + * information: Portions Copyright [yyyy] [name of copyright owner]
    + *
    + * CDDL HEADER END
    + */
    +
    +/*
    + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2012 by Delphix. All rights reserved.
    + * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
    + * Copyright (c) 2012, Joyent, Inc. All rights reserved.
    + */
    +
    +#ifndef _DMU_SEND_H
    +#define	_DMU_SEND_H
    +
    +#include 
    +#include 
    +
    +struct vnode;
    +struct dsl_dataset;
    +struct drr_begin;
    +struct avl_tree;
    +
    +int dmu_send(const char *tosnap, const char *fromsnap, int outfd,
    +    struct vnode *vp, offset_t *off);
    +int dmu_send_estimate(struct dsl_dataset *ds, struct dsl_dataset *fromds,
    +    uint64_t *sizep);
    +int dmu_send_obj(const char *pool, uint64_t tosnap, uint64_t fromsnap,
    +    int outfd, struct vnode *vp, offset_t *off);
    +
    +typedef struct dmu_recv_cookie {
    +	struct dsl_dataset *drc_ds;
    +	struct drr_begin *drc_drrb;
    +	const char *drc_tofs;
    +	const char *drc_tosnap;
    +	boolean_t drc_newfs;
    +	boolean_t drc_byteswap;
    +	boolean_t drc_force;
    +	struct avl_tree *drc_guid_to_ds_map;
    +	zio_cksum_t drc_cksum;
    +	uint64_t drc_newsnapobj;
    +} dmu_recv_cookie_t;
    +
    +int dmu_recv_begin(char *tofs, char *tosnap, struct drr_begin *drrb,
    +    boolean_t force, char *origin, dmu_recv_cookie_t *drc);
    +int dmu_recv_stream(dmu_recv_cookie_t *drc, struct vnode *vp, offset_t *voffp,
    +    int cleanup_fd, uint64_t *action_handlep);
    +int dmu_recv_end(dmu_recv_cookie_t *drc);
    +
    +#endif /* _DMU_SEND_H */
    diff --git a/uts/common/fs/zfs/sys/dmu_tx.h b/uts/common/fs/zfs/sys/dmu_tx.h
    index c5ea50fa8d8..dbd2242540e 100644
    --- a/uts/common/fs/zfs/sys/dmu_tx.h
    +++ b/uts/common/fs/zfs/sys/dmu_tx.h
    @@ -22,6 +22,9 @@
      * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
      * Use is subject to license terms.
      */
    +/*
    + * Copyright (c) 2012 by Delphix. All rights reserved.
    + */
     
     #ifndef	_SYS_DMU_TX_H
     #define	_SYS_DMU_TX_H
    @@ -108,10 +111,11 @@ typedef struct dmu_tx_callback {
      * These routines are defined in dmu.h, and are called by the user.
      */
     dmu_tx_t *dmu_tx_create(objset_t *dd);
    -int dmu_tx_assign(dmu_tx_t *tx, uint64_t txg_how);
    +int dmu_tx_assign(dmu_tx_t *tx, txg_how_t txg_how);
     void dmu_tx_commit(dmu_tx_t *tx);
     void dmu_tx_abort(dmu_tx_t *tx);
     uint64_t dmu_tx_get_txg(dmu_tx_t *tx);
    +struct dsl_pool *dmu_tx_pool(dmu_tx_t *tx);
     void dmu_tx_wait(dmu_tx_t *tx);
     
     void dmu_tx_callback_register(dmu_tx_t *tx, dmu_tx_callback_func_t *dcb_func,
    diff --git a/uts/common/fs/zfs/sys/dsl_dataset.h b/uts/common/fs/zfs/sys/dsl_dataset.h
    index 272c3ecde24..6729f9f05a9 100644
    --- a/uts/common/fs/zfs/sys/dsl_dataset.h
    +++ b/uts/common/fs/zfs/sys/dsl_dataset.h
    @@ -35,6 +35,7 @@
     #include 
     #include 
     #include 
    +#include 
     
     #ifdef	__cplusplus
     extern "C" {
    @@ -48,10 +49,8 @@ struct dsl_pool;
     #define	DS_IS_INCONSISTENT(ds)	\
     	((ds)->ds_phys->ds_flags & DS_FLAG_INCONSISTENT)
     /*
    - * NB: nopromote can not yet be set, but we want support for it in this
    - * on-disk version, so that we don't need to upgrade for it later.  It
    - * will be needed when we implement 'zfs split' (where the split off
    - * clone should not be promoted).
    + * Note: nopromote can not yet be set, but we want support for it in this
    + * on-disk version, so that we don't need to upgrade for it later.
      */
     #define	DS_FLAG_NOPROMOTE	(1ULL<<1)
     
    @@ -76,6 +75,8 @@ struct dsl_pool;
      */
     #define	DS_FLAG_CI_DATASET	(1ULL<<16)
     
    +#define	DS_CREATE_FLAG_NODIRTY	(1ULL<<24)
    +
     typedef struct dsl_dataset_phys {
     	uint64_t ds_dir_obj;		/* DMU_OT_DSL_DIR */
     	uint64_t ds_prev_snap_obj;	/* DMU_OT_DSL_DATASET */
    @@ -125,9 +126,6 @@ typedef struct dsl_dataset {
     	dsl_deadlist_t ds_deadlist;
     	bplist_t ds_pending_deadlist;
     
    -	/* to protect against multiple concurrent incremental recv */
    -	kmutex_t ds_recvlock;
    -
     	/* protected by lock on pool's dp_dirty_datasets list */
     	txg_node_t ds_dirty_link;
     	list_node_t ds_synced_link;
    @@ -139,13 +137,15 @@ typedef struct dsl_dataset {
     	kmutex_t ds_lock;
     	objset_t *ds_objset;
     	uint64_t ds_userrefs;
    +	void *ds_owner;
     
     	/*
    -	 * ds_owner is protected by the ds_rwlock and the ds_lock
    +	 * Long holds prevent the ds from being destroyed; they allow the
    +	 * ds to remain held even after dropping the dp_config_rwlock.
    +	 * Owning counts as a long hold.  See the comments above
    +	 * dsl_pool_hold() for details.
     	 */
    -	krwlock_t ds_rwlock;
    -	kcondvar_t ds_exclusive_cv;
    -	void *ds_owner;
    +	refcount_t ds_longholds;
     
     	/* no locking; only for making guesses */
     	uint64_t ds_trysnap_txg;
    @@ -163,76 +163,44 @@ typedef struct dsl_dataset {
     	char ds_snapname[MAXNAMELEN];
     } dsl_dataset_t;
     
    -struct dsl_ds_destroyarg {
    -	dsl_dataset_t *ds;		/* ds to destroy */
    -	dsl_dataset_t *rm_origin;	/* also remove our origin? */
    -	boolean_t is_origin_rm;		/* set if removing origin snap */
    -	boolean_t defer;		/* destroy -d requested? */
    -	boolean_t releasing;		/* destroying due to release? */
    -	boolean_t need_prep;		/* do we need to retry due to EBUSY? */
    -};
    -
     /*
      * The max length of a temporary tag prefix is the number of hex digits
      * required to express UINT64_MAX plus one for the hyphen.
      */
     #define	MAX_TAG_PREFIX_LEN	17
     
    -struct dsl_ds_holdarg {
    -	dsl_sync_task_group_t *dstg;
    -	const char *htag;
    -	char *snapname;
    -	boolean_t recursive;
    -	boolean_t gotone;
    -	boolean_t temphold;
    -	char failed[MAXPATHLEN];
    -};
    -
     #define	dsl_dataset_is_snapshot(ds) \
     	((ds)->ds_phys->ds_num_children != 0)
     
     #define	DS_UNIQUE_IS_ACCURATE(ds)	\
     	(((ds)->ds_phys->ds_flags & DS_FLAG_UNIQUE_ACCURATE) != 0)
     
    -int dsl_dataset_hold(const char *name, void *tag, dsl_dataset_t **dsp);
    -int dsl_dataset_hold_obj(struct dsl_pool *dp, uint64_t dsobj,
    -    void *tag, dsl_dataset_t **);
    -int dsl_dataset_own(const char *name, boolean_t inconsistentok,
    +int dsl_dataset_hold(struct dsl_pool *dp, const char *name, void *tag,
    +    dsl_dataset_t **dsp);
    +int dsl_dataset_hold_obj(struct dsl_pool *dp, uint64_t dsobj, void *tag,
    +    dsl_dataset_t **);
    +void dsl_dataset_rele(dsl_dataset_t *ds, void *tag);
    +int dsl_dataset_own(struct dsl_pool *dp, const char *name,
         void *tag, dsl_dataset_t **dsp);
     int dsl_dataset_own_obj(struct dsl_pool *dp, uint64_t dsobj,
    -    boolean_t inconsistentok, void *tag, dsl_dataset_t **dsp);
    -void dsl_dataset_name(dsl_dataset_t *ds, char *name);
    -void dsl_dataset_rele(dsl_dataset_t *ds, void *tag);
    +    void *tag, dsl_dataset_t **dsp);
     void dsl_dataset_disown(dsl_dataset_t *ds, void *tag);
    -void dsl_dataset_drop_ref(dsl_dataset_t *ds, void *tag);
    -boolean_t dsl_dataset_tryown(dsl_dataset_t *ds, boolean_t inconsistentok,
    -    void *tag);
    -void dsl_dataset_make_exclusive(dsl_dataset_t *ds, void *tag);
    +void dsl_dataset_name(dsl_dataset_t *ds, char *name);
    +boolean_t dsl_dataset_tryown(dsl_dataset_t *ds, void *tag);
     void dsl_register_onexit_hold_cleanup(dsl_dataset_t *ds, const char *htag,
         minor_t minor);
     uint64_t dsl_dataset_create_sync(dsl_dir_t *pds, const char *lastname,
         dsl_dataset_t *origin, uint64_t flags, cred_t *, dmu_tx_t *);
     uint64_t dsl_dataset_create_sync_dd(dsl_dir_t *dd, dsl_dataset_t *origin,
         uint64_t flags, dmu_tx_t *tx);
    -int dsl_dataset_destroy(dsl_dataset_t *ds, void *tag, boolean_t defer);
    -dsl_checkfunc_t dsl_dataset_destroy_check;
    -dsl_syncfunc_t dsl_dataset_destroy_sync;
    -dsl_syncfunc_t dsl_dataset_user_hold_sync;
    -int dsl_dataset_snapshot_check(dsl_dataset_t *ds, const char *, dmu_tx_t *tx);
    -void dsl_dataset_snapshot_sync(dsl_dataset_t *ds, const char *, dmu_tx_t *tx);
    -int dsl_dataset_rename(char *name, const char *newname, boolean_t recursive);
    +int dsl_dataset_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t *errors);
     int dsl_dataset_promote(const char *name, char *conflsnap);
     int dsl_dataset_clone_swap(dsl_dataset_t *clone, dsl_dataset_t *origin_head,
         boolean_t force);
    -int dsl_dataset_user_hold(char *dsname, char *snapname, char *htag,
    -    boolean_t recursive, boolean_t temphold, int cleanup_fd);
    -int dsl_dataset_user_hold_for_send(dsl_dataset_t *ds, char *htag,
    -    boolean_t temphold);
    -int dsl_dataset_user_release(char *dsname, char *snapname, char *htag,
    -    boolean_t recursive);
    -int dsl_dataset_user_release_tmp(struct dsl_pool *dp, uint64_t dsobj,
    -    char *htag, boolean_t retry);
    -int dsl_dataset_get_holds(const char *dsname, nvlist_t **nvp);
    +int dsl_dataset_rename_snapshot(const char *fsname,
    +    const char *oldsnapname, const char *newsnapname, boolean_t recursive);
    +int dsl_dataset_snapshot_tmp(const char *fsname, const char *snapname,
    +    minor_t cleanup_minor, const char *htag);
     
     blkptr_t *dsl_dataset_get_blkptr(dsl_dataset_t *ds);
     void dsl_dataset_set_blkptr(dsl_dataset_t *ds, blkptr_t *bp, dmu_tx_t *tx);
    @@ -269,13 +237,35 @@ int dsl_dsobj_to_dsname(char *pname, uint64_t obj, char *buf);
     int dsl_dataset_check_quota(dsl_dataset_t *ds, boolean_t check_quota,
         uint64_t asize, uint64_t inflight, uint64_t *used,
         uint64_t *ref_rsrv);
    -int dsl_dataset_set_quota(const char *dsname, zprop_source_t source,
    +int dsl_dataset_set_refquota(const char *dsname, zprop_source_t source,
         uint64_t quota);
    -dsl_syncfunc_t dsl_dataset_set_quota_sync;
    -int dsl_dataset_set_reservation(const char *dsname, zprop_source_t source,
    +int dsl_dataset_set_refreservation(const char *dsname, zprop_source_t source,
         uint64_t reservation);
     
    -int dsl_destroy_inconsistent(const char *dsname, void *arg);
    +boolean_t dsl_dataset_is_before(dsl_dataset_t *later, dsl_dataset_t *earlier);
    +void dsl_dataset_long_hold(dsl_dataset_t *ds, void *tag);
    +void dsl_dataset_long_rele(dsl_dataset_t *ds, void *tag);
    +boolean_t dsl_dataset_long_held(dsl_dataset_t *ds);
    +
    +int dsl_dataset_clone_swap_check_impl(dsl_dataset_t *clone,
    +    dsl_dataset_t *origin_head, boolean_t force);
    +void dsl_dataset_clone_swap_sync_impl(dsl_dataset_t *clone,
    +    dsl_dataset_t *origin_head, dmu_tx_t *tx);
    +int dsl_dataset_snapshot_check_impl(dsl_dataset_t *ds, const char *snapname,
    +    dmu_tx_t *tx);
    +void dsl_dataset_snapshot_sync_impl(dsl_dataset_t *ds, const char *snapname,
    +    dmu_tx_t *tx);
    +
    +void dsl_dataset_remove_from_next_clones(dsl_dataset_t *ds, uint64_t obj,
    +    dmu_tx_t *tx);
    +void dsl_dataset_recalc_head_uniq(dsl_dataset_t *ds);
    +int dsl_dataset_get_snapname(dsl_dataset_t *ds);
    +int dsl_dataset_snap_lookup(dsl_dataset_t *ds, const char *name,
    +    uint64_t *value);
    +int dsl_dataset_snap_remove(dsl_dataset_t *ds, const char *name, dmu_tx_t *tx);
    +void dsl_dataset_set_refreservation_sync_impl(dsl_dataset_t *ds,
    +    zprop_source_t source, uint64_t value, dmu_tx_t *tx);
    +int dsl_dataset_rollback(const char *fsname);
     
     #ifdef ZFS_DEBUG
     #define	dprintf_ds(ds, fmt, ...) do { \
    diff --git a/uts/common/fs/zfs/sys/dsl_destroy.h b/uts/common/fs/zfs/sys/dsl_destroy.h
    new file mode 100644
    index 00000000000..c5a70bb90e4
    --- /dev/null
    +++ b/uts/common/fs/zfs/sys/dsl_destroy.h
    @@ -0,0 +1,52 @@
    +/*
    + * CDDL HEADER START
    + *
    + * The contents of this file are subject to the terms of the
    + * Common Development and Distribution License (the "License").
    + * You may not use this file except in compliance with the License.
    + *
    + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
    + * or http://www.opensolaris.org/os/licensing.
    + * See the License for the specific language governing permissions
    + * and limitations under the License.
    + *
    + * When distributing Covered Code, include this CDDL HEADER in each
    + * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
    + * If applicable, add the following below this CDDL HEADER, with the
    + * fields enclosed by brackets "[]" replaced with your own identifying
    + * information: Portions Copyright [yyyy] [name of copyright owner]
    + *
    + * CDDL HEADER END
    + */
    +/*
    + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2012 by Delphix. All rights reserved.
    + * Copyright (c) 2012, Joyent, Inc. All rights reserved.
    + */
    +
    +#ifndef	_SYS_DSL_DESTROY_H
    +#define	_SYS_DSL_DESTROY_H
    +
    +#ifdef	__cplusplus
    +extern "C" {
    +#endif
    +
    +struct nvlist;
    +struct dsl_dataset;
    +struct dmu_tx;
    +
    +int dsl_destroy_snapshots_nvl(struct nvlist *snaps, boolean_t defer,
    +    struct nvlist *errlist);
    +int dsl_destroy_snapshot(const char *name, boolean_t defer);
    +int dsl_destroy_head(const char *name);
    +int dsl_destroy_head_check_impl(struct dsl_dataset *ds, int expected_holds);
    +void dsl_destroy_head_sync_impl(struct dsl_dataset *ds, struct dmu_tx *tx);
    +int dsl_destroy_inconsistent(const char *dsname, void *arg);
    +void dsl_destroy_snapshot_sync_impl(struct dsl_dataset *ds,
    +    boolean_t defer, struct dmu_tx *tx);
    +
    +#ifdef	__cplusplus
    +}
    +#endif
    +
    +#endif /* _SYS_DSL_DESTROY_H */
    diff --git a/uts/common/fs/zfs/sys/dsl_dir.h b/uts/common/fs/zfs/sys/dsl_dir.h
    index 2191635dd81..641bcfcdd30 100644
    --- a/uts/common/fs/zfs/sys/dsl_dir.h
    +++ b/uts/common/fs/zfs/sys/dsl_dir.h
    @@ -20,6 +20,7 @@
      */
     /*
      * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2012 by Delphix. All rights reserved.
      */
     
     #ifndef	_SYS_DSL_DIR_H
    @@ -101,18 +102,15 @@ struct dsl_dir {
     	char dd_myname[MAXNAMELEN];
     };
     
    -void dsl_dir_close(dsl_dir_t *dd, void *tag);
    -int dsl_dir_open(const char *name, void *tag, dsl_dir_t **, const char **tail);
    -int dsl_dir_open_spa(spa_t *spa, const char *name, void *tag, dsl_dir_t **,
    -    const char **tailp);
    -int dsl_dir_open_obj(dsl_pool_t *dp, uint64_t ddobj,
    +void dsl_dir_rele(dsl_dir_t *dd, void *tag);
    +int dsl_dir_hold(dsl_pool_t *dp, const char *name, void *tag,
    +    dsl_dir_t **, const char **tail);
    +int dsl_dir_hold_obj(dsl_pool_t *dp, uint64_t ddobj,
         const char *tail, void *tag, dsl_dir_t **);
     void dsl_dir_name(dsl_dir_t *dd, char *buf);
     int dsl_dir_namelen(dsl_dir_t *dd);
     uint64_t dsl_dir_create_sync(dsl_pool_t *dp, dsl_dir_t *pds,
         const char *name, dmu_tx_t *tx);
    -dsl_checkfunc_t dsl_dir_destroy_check;
    -dsl_syncfunc_t dsl_dir_destroy_sync;
     void dsl_dir_stats(dsl_dir_t *dd, nvlist_t *nv);
     uint64_t dsl_dir_space_available(dsl_dir_t *dd,
         dsl_dir_t *ancestor, int64_t delta, int ondiskonly);
    @@ -131,14 +129,15 @@ int dsl_dir_set_quota(const char *ddname, zprop_source_t source,
         uint64_t quota);
     int dsl_dir_set_reservation(const char *ddname, zprop_source_t source,
         uint64_t reservation);
    -int dsl_dir_rename(dsl_dir_t *dd, const char *newname);
    +int dsl_dir_rename(const char *oldname, const char *newname);
     int dsl_dir_transfer_possible(dsl_dir_t *sdd, dsl_dir_t *tdd, uint64_t space);
    -int dsl_dir_set_reservation_check(void *arg1, void *arg2, dmu_tx_t *tx);
     boolean_t dsl_dir_is_clone(dsl_dir_t *dd);
     void dsl_dir_new_refreservation(dsl_dir_t *dd, struct dsl_dataset *ds,
         uint64_t reservation, cred_t *cr, dmu_tx_t *tx);
     void dsl_dir_snap_cmtime_update(dsl_dir_t *dd);
     timestruc_t dsl_dir_snap_cmtime(dsl_dir_t *dd);
    +void dsl_dir_set_reservation_sync_impl(dsl_dir_t *dd, uint64_t value,
    +    dmu_tx_t *tx);
     
     /* internal reserved dir name */
     #define	MOS_DIR_NAME "$MOS"
    diff --git a/uts/common/fs/zfs/sys/dsl_pool.h b/uts/common/fs/zfs/sys/dsl_pool.h
    index ab1229a2e61..b0160edfb1f 100644
    --- a/uts/common/fs/zfs/sys/dsl_pool.h
    +++ b/uts/common/fs/zfs/sys/dsl_pool.h
    @@ -36,6 +36,7 @@
     #include 
     #include 
     #include 
    +#include 
     
     #ifdef	__cplusplus
     extern "C" {
    @@ -113,7 +114,7 @@ typedef struct dsl_pool {
     	 * syncing context does not need to ever have it for read, since
     	 * nobody else could possibly have it for write.
     	 */
    -	krwlock_t dp_config_rwlock;
    +	rrwlock_t dp_config_rwlock;
     
     	zfs_all_blkstats_t *dp_blkstats;
     } dsl_pool_t;
    @@ -139,15 +140,20 @@ void dsl_pool_upgrade_clones(dsl_pool_t *dp, dmu_tx_t *tx);
     void dsl_pool_upgrade_dir_clones(dsl_pool_t *dp, dmu_tx_t *tx);
     void dsl_pool_mos_diduse_space(dsl_pool_t *dp,
         int64_t used, int64_t comp, int64_t uncomp);
    +void dsl_pool_config_enter(dsl_pool_t *dp, void *tag);
    +void dsl_pool_config_exit(dsl_pool_t *dp, void *tag);
    +boolean_t dsl_pool_config_held(dsl_pool_t *dp);
     
     taskq_t *dsl_pool_vnrele_taskq(dsl_pool_t *dp);
     
    -extern int dsl_pool_user_hold(dsl_pool_t *dp, uint64_t dsobj,
    -    const char *tag, uint64_t *now, dmu_tx_t *tx);
    -extern int dsl_pool_user_release(dsl_pool_t *dp, uint64_t dsobj,
    +int dsl_pool_user_hold(dsl_pool_t *dp, uint64_t dsobj,
    +    const char *tag, uint64_t now, dmu_tx_t *tx);
    +int dsl_pool_user_release(dsl_pool_t *dp, uint64_t dsobj,
         const char *tag, dmu_tx_t *tx);
    -extern void dsl_pool_clean_tmp_userrefs(dsl_pool_t *dp);
    +void dsl_pool_clean_tmp_userrefs(dsl_pool_t *dp);
     int dsl_pool_open_special_dir(dsl_pool_t *dp, const char *name, dsl_dir_t **);
    +int dsl_pool_hold(const char *name, void *tag, dsl_pool_t **dp);
    +void dsl_pool_rele(dsl_pool_t *dp, void *tag);
     
     #ifdef	__cplusplus
     }
    diff --git a/uts/common/fs/zfs/sys/dsl_prop.h b/uts/common/fs/zfs/sys/dsl_prop.h
    index b0d9a52cdfd..5fe18d6a7c5 100644
    --- a/uts/common/fs/zfs/sys/dsl_prop.h
    +++ b/uts/common/fs/zfs/sys/dsl_prop.h
    @@ -54,58 +54,47 @@ typedef struct dsl_props_arg {
     	zprop_source_t pa_source;
     } dsl_props_arg_t;
     
    -typedef struct dsl_prop_set_arg {
    -	const char *psa_name;
    -	zprop_source_t psa_source;
    -	int psa_intsz;
    -	int psa_numints;
    -	const void *psa_value;
    -
    -	/*
    -	 * Used to handle the special requirements of the quota and reservation
    -	 * properties.
    -	 */
    -	uint64_t psa_effective_value;
    -} dsl_prop_setarg_t;
    -
     int dsl_prop_register(struct dsl_dataset *ds, const char *propname,
         dsl_prop_changed_cb_t *callback, void *cbarg);
     int dsl_prop_unregister(struct dsl_dataset *ds, const char *propname,
         dsl_prop_changed_cb_t *callback, void *cbarg);
    -int dsl_prop_numcb(struct dsl_dataset *ds);
    +void dsl_prop_notify_all(struct dsl_dir *dd);
    +boolean_t dsl_prop_hascb(struct dsl_dataset *ds);
     
     int dsl_prop_get(const char *ddname, const char *propname,
         int intsz, int numints, void *buf, char *setpoint);
     int dsl_prop_get_integer(const char *ddname, const char *propname,
         uint64_t *valuep, char *setpoint);
     int dsl_prop_get_all(objset_t *os, nvlist_t **nvp);
    -int dsl_prop_get_received(objset_t *os, nvlist_t **nvp);
    +int dsl_prop_get_received(const char *dsname, nvlist_t **nvp);
     int dsl_prop_get_ds(struct dsl_dataset *ds, const char *propname,
         int intsz, int numints, void *buf, char *setpoint);
    +int dsl_prop_get_int_ds(struct dsl_dataset *ds, const char *propname,
    +    uint64_t *valuep);
     int dsl_prop_get_dd(struct dsl_dir *dd, const char *propname,
         int intsz, int numints, void *buf, char *setpoint,
         boolean_t snapshot);
     
    -dsl_syncfunc_t dsl_props_set_sync;
    -int dsl_prop_set(const char *ddname, const char *propname,
    -    zprop_source_t source, int intsz, int numints, const void *buf);
    +void dsl_props_set_sync_impl(struct dsl_dataset *ds, zprop_source_t source,
    +    nvlist_t *props, dmu_tx_t *tx);
    +void dsl_prop_set_sync_impl(struct dsl_dataset *ds, const char *propname,
    +    zprop_source_t source, int intsz, int numints, const void *value,
    +    dmu_tx_t *tx);
     int dsl_props_set(const char *dsname, zprop_source_t source, nvlist_t *nvl);
    +int dsl_prop_set_int(const char *dsname, const char *propname,
    +    zprop_source_t source, uint64_t value);
    +int dsl_prop_set_string(const char *dsname, const char *propname,
    +    zprop_source_t source, const char *value);
    +int dsl_prop_inherit(const char *dsname, const char *propname,
    +    zprop_source_t source);
     
    -void dsl_prop_setarg_init_uint64(dsl_prop_setarg_t *psa, const char *propname,
    -    zprop_source_t source, uint64_t *value);
    -int dsl_prop_predict_sync(dsl_dir_t *dd, dsl_prop_setarg_t *psa);
    -#ifdef	ZFS_DEBUG
    -void dsl_prop_check_prediction(dsl_dir_t *dd, dsl_prop_setarg_t *psa);
    -#define	DSL_PROP_CHECK_PREDICTION(dd, psa)	\
    -	dsl_prop_check_prediction((dd), (psa))
    -#else
    -#define	DSL_PROP_CHECK_PREDICTION(dd, psa)	/* nothing */
    -#endif
    +int dsl_prop_predict(dsl_dir_t *dd, const char *propname,
    +    zprop_source_t source, uint64_t value, uint64_t *newvalp);
     
     /* flag first receive on or after SPA_VERSION_RECVD_PROPS */
    -boolean_t dsl_prop_get_hasrecvd(objset_t *os);
    -void dsl_prop_set_hasrecvd(objset_t *os);
    -void dsl_prop_unset_hasrecvd(objset_t *os);
    +boolean_t dsl_prop_get_hasrecvd(const char *dsname);
    +int dsl_prop_set_hasrecvd(const char *dsname);
    +void dsl_prop_unset_hasrecvd(const char *dsname);
     
     void dsl_prop_nvlist_add_uint64(nvlist_t *nv, zfs_prop_t prop, uint64_t value);
     void dsl_prop_nvlist_add_string(nvlist_t *nv,
    diff --git a/uts/common/fs/zfs/sys/dsl_synctask.h b/uts/common/fs/zfs/sys/dsl_synctask.h
    index 9126290cdb5..ef86fb64cf0 100644
    --- a/uts/common/fs/zfs/sys/dsl_synctask.h
    +++ b/uts/common/fs/zfs/sys/dsl_synctask.h
    @@ -20,6 +20,7 @@
      */
     /*
      * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2012 by Delphix. All rights reserved.
      */
     
     #ifndef	_SYS_DSL_SYNCTASK_H
    @@ -34,43 +35,26 @@ extern "C" {
     
     struct dsl_pool;
     
    -typedef int (dsl_checkfunc_t)(void *, void *, dmu_tx_t *);
    -typedef void (dsl_syncfunc_t)(void *, void *, dmu_tx_t *);
    +typedef int (dsl_checkfunc_t)(void *, dmu_tx_t *);
    +typedef void (dsl_syncfunc_t)(void *, dmu_tx_t *);
     
     typedef struct dsl_sync_task {
    -	list_node_t dst_node;
    +	txg_node_t dst_node;
    +	struct dsl_pool *dst_pool;
    +	uint64_t dst_txg;
    +	int dst_space;
     	dsl_checkfunc_t *dst_checkfunc;
     	dsl_syncfunc_t *dst_syncfunc;
    -	void *dst_arg1;
    -	void *dst_arg2;
    -	int dst_err;
    +	void *dst_arg;
    +	int dst_error;
    +	boolean_t dst_nowaiter;
     } dsl_sync_task_t;
     
    -typedef struct dsl_sync_task_group {
    -	txg_node_t dstg_node;
    -	list_t dstg_tasks;
    -	struct dsl_pool *dstg_pool;
    -	uint64_t dstg_txg;
    -	int dstg_err;
    -	int dstg_space;
    -	boolean_t dstg_nowaiter;
    -} dsl_sync_task_group_t;
    -
    -dsl_sync_task_group_t *dsl_sync_task_group_create(struct dsl_pool *dp);
    -void dsl_sync_task_create(dsl_sync_task_group_t *dstg,
    -    dsl_checkfunc_t *, dsl_syncfunc_t *,
    -    void *arg1, void *arg2, int blocks_modified);
    -int dsl_sync_task_group_wait(dsl_sync_task_group_t *dstg);
    -void dsl_sync_task_group_nowait(dsl_sync_task_group_t *dstg, dmu_tx_t *tx);
    -void dsl_sync_task_group_destroy(dsl_sync_task_group_t *dstg);
    -void dsl_sync_task_group_sync(dsl_sync_task_group_t *dstg, dmu_tx_t *tx);
    -
    -int dsl_sync_task_do(struct dsl_pool *dp,
    -    dsl_checkfunc_t *checkfunc, dsl_syncfunc_t *syncfunc,
    -    void *arg1, void *arg2, int blocks_modified);
    -void dsl_sync_task_do_nowait(struct dsl_pool *dp,
    -    dsl_checkfunc_t *checkfunc, dsl_syncfunc_t *syncfunc,
    -    void *arg1, void *arg2, int blocks_modified, dmu_tx_t *tx);
    +void dsl_sync_task_sync(dsl_sync_task_t *dst, dmu_tx_t *tx);
    +int dsl_sync_task(const char *pool, dsl_checkfunc_t *checkfunc,
    +    dsl_syncfunc_t *syncfunc, void *arg, int blocks_modified);
    +void dsl_sync_task_nowait(struct dsl_pool *dp, dsl_syncfunc_t *syncfunc,
    +    void *arg, int blocks_modified, dmu_tx_t *tx);
     
     #ifdef	__cplusplus
     }
    diff --git a/uts/common/fs/zfs/sys/dsl_userhold.h b/uts/common/fs/zfs/sys/dsl_userhold.h
    new file mode 100644
    index 00000000000..56c6c8f47a8
    --- /dev/null
    +++ b/uts/common/fs/zfs/sys/dsl_userhold.h
    @@ -0,0 +1,57 @@
    +
    +/*
    + * CDDL HEADER START
    + *
    + * The contents of this file are subject to the terms of the
    + * Common Development and Distribution License (the "License").
    + * You may not use this file except in compliance with the License.
    + *
    + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
    + * or http://www.opensolaris.org/os/licensing.
    + * See the License for the specific language governing permissions
    + * and limitations under the License.
    + *
    + * When distributing Covered Code, include this CDDL HEADER in each
    + * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
    + * If applicable, add the following below this CDDL HEADER, with the
    + * fields enclosed by brackets "[]" replaced with your own identifying
    + * information: Portions Copyright [yyyy] [name of copyright owner]
    + *
    + * CDDL HEADER END
    + */
    +/*
    + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2012 by Delphix. All rights reserved.
    + * Copyright (c) 2012, Joyent, Inc. All rights reserved.
    + */
    +
    +#ifndef	_SYS_DSL_USERHOLD_H
    +#define	_SYS_DSL_USERHOLD_H
    +
    +#include 
    +#include 
    +
    +#ifdef	__cplusplus
    +extern "C" {
    +#endif
    +
    +struct dsl_pool;
    +struct dsl_dataset;
    +struct dmu_tx;
    +
    +int dsl_dataset_user_hold(nvlist_t *holds, minor_t cleanup_minor,
    +    nvlist_t *errlist);
    +int dsl_dataset_user_release(nvlist_t *holds, nvlist_t *errlist);
    +int dsl_dataset_get_holds(const char *dsname, nvlist_t *nvl);
    +void dsl_dataset_user_release_tmp(struct dsl_pool *dp, uint64_t dsobj,
    +    const char *htag);
    +int dsl_dataset_user_hold_check_one(struct dsl_dataset *ds, const char *htag,
    +    boolean_t temphold, struct dmu_tx *tx);
    +void dsl_dataset_user_hold_sync_one(struct dsl_dataset *ds, const char *htag,
    +    minor_t minor, uint64_t now, struct dmu_tx *tx);
    +
    +#ifdef	__cplusplus
    +}
    +#endif
    +
    +#endif /* _SYS_DSL_USERHOLD_H */
    diff --git a/uts/common/fs/zfs/sys/metaslab.h b/uts/common/fs/zfs/sys/metaslab.h
    index 2cf4d2b489b..d6c0bf4c94c 100644
    --- a/uts/common/fs/zfs/sys/metaslab.h
    +++ b/uts/common/fs/zfs/sys/metaslab.h
    @@ -20,7 +20,7 @@
      */
     /*
      * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
    - * Copyright (c) 2011 by Delphix. All rights reserved.
    + * Copyright (c) 2012 by Delphix. All rights reserved.
      */
     
     #ifndef _SYS_METASLAB_H
    @@ -56,6 +56,7 @@ extern int metaslab_alloc(spa_t *spa, metaslab_class_t *mc, uint64_t psize,
     extern void metaslab_free(spa_t *spa, const blkptr_t *bp, uint64_t txg,
         boolean_t now);
     extern int metaslab_claim(spa_t *spa, const blkptr_t *bp, uint64_t txg);
    +extern void metaslab_check_free(spa_t *spa, const blkptr_t *bp);
     
     extern metaslab_class_t *metaslab_class_create(spa_t *spa,
         space_map_ops_t *ops);
    diff --git a/uts/common/fs/zfs/sys/refcount.h b/uts/common/fs/zfs/sys/refcount.h
    index 1dcd467f91a..9efc5f1e445 100644
    --- a/uts/common/fs/zfs/sys/refcount.h
    +++ b/uts/common/fs/zfs/sys/refcount.h
    @@ -51,15 +51,17 @@ typedef struct reference {
     
     typedef struct refcount {
     	kmutex_t rc_mtx;
    +	boolean_t rc_tracked;
     	list_t rc_list;
     	list_t rc_removed;
     	uint64_t rc_count;
     	uint64_t rc_removed_count;
     } refcount_t;
     
    -/* Note: refcount_t must be initialized with refcount_create() */
    +/* Note: refcount_t must be initialized with refcount_create[_untracked]() */
     
     void refcount_create(refcount_t *rc);
    +void refcount_create_untracked(refcount_t *rc);
     void refcount_destroy(refcount_t *rc);
     void refcount_destroy_many(refcount_t *rc, uint64_t number);
     int refcount_is_zero(refcount_t *rc);
    @@ -80,6 +82,7 @@ typedef struct refcount {
     } refcount_t;
     
     #define	refcount_create(rc) ((rc)->rc_count = 0)
    +#define	refcount_create_untracked(rc) ((rc)->rc_count = 0)
     #define	refcount_destroy(rc) ((rc)->rc_count = 0)
     #define	refcount_destroy_many(rc, number) ((rc)->rc_count = 0)
     #define	refcount_is_zero(rc) ((rc)->rc_count == 0)
    diff --git a/uts/common/fs/zfs/sys/rrwlock.h b/uts/common/fs/zfs/sys/rrwlock.h
    index 239268bd58e..e1e6d312237 100644
    --- a/uts/common/fs/zfs/sys/rrwlock.h
    +++ b/uts/common/fs/zfs/sys/rrwlock.h
    @@ -58,6 +58,7 @@ typedef struct rrwlock {
     	refcount_t	rr_anon_rcount;
     	refcount_t	rr_linked_rcount;
     	boolean_t	rr_writer_wanted;
    +	boolean_t	rr_track_all;
     } rrwlock_t;
     
     /*
    @@ -65,15 +66,19 @@ typedef struct rrwlock {
      * 'tag' must be the same in a rrw_enter() as in its
      * corresponding rrw_exit().
      */
    -void rrw_init(rrwlock_t *rrl);
    +void rrw_init(rrwlock_t *rrl, boolean_t track_all);
     void rrw_destroy(rrwlock_t *rrl);
     void rrw_enter(rrwlock_t *rrl, krw_t rw, void *tag);
    +void rrw_enter_read(rrwlock_t *rrl, void *tag);
    +void rrw_enter_write(rrwlock_t *rrl);
     void rrw_exit(rrwlock_t *rrl, void *tag);
     boolean_t rrw_held(rrwlock_t *rrl, krw_t rw);
     void rrw_tsd_destroy(void *arg);
     
     #define	RRW_READ_HELD(x)	rrw_held(x, RW_READER)
     #define	RRW_WRITE_HELD(x)	rrw_held(x, RW_WRITER)
    +#define	RRW_LOCK_HELD(x) \
    +	(rrw_held(x, RW_WRITER) || rrw_held(x, RW_READER))
     
     #ifdef	__cplusplus
     }
    diff --git a/uts/common/fs/zfs/sys/space_map.h b/uts/common/fs/zfs/sys/space_map.h
    index 2da50fb7b3b..64223daf620 100644
    --- a/uts/common/fs/zfs/sys/space_map.h
    +++ b/uts/common/fs/zfs/sys/space_map.h
    @@ -149,6 +149,8 @@ extern void space_map_add(space_map_t *sm, uint64_t start, uint64_t size);
     extern void space_map_remove(space_map_t *sm, uint64_t start, uint64_t size);
     extern boolean_t space_map_contains(space_map_t *sm,
         uint64_t start, uint64_t size);
    +extern space_seg_t *space_map_find(space_map_t *sm, uint64_t start,
    +    uint64_t size, avl_index_t *wherep);
     extern void space_map_swap(space_map_t **msrc, space_map_t **mdest);
     extern void space_map_vacate(space_map_t *sm,
         space_map_func_t *func, space_map_t *mdest);
    diff --git a/uts/common/fs/zfs/sys/txg.h b/uts/common/fs/zfs/sys/txg.h
    index 1287f09c7ee..2df33f0fb0a 100644
    --- a/uts/common/fs/zfs/sys/txg.h
    +++ b/uts/common/fs/zfs/sys/txg.h
    @@ -45,9 +45,6 @@ extern "C" {
     /* Number of txgs worth of frees we defer adding to in-core spacemaps */
     #define	TXG_DEFER_SIZE		2
     
    -#define	TXG_WAIT		1ULL
    -#define	TXG_NOWAIT		2ULL
    -
     typedef struct tx_cpu tx_cpu_t;
     
     typedef struct txg_handle {
    @@ -119,11 +116,11 @@ extern boolean_t txg_sync_waiting(struct dsl_pool *dp);
     extern void txg_list_create(txg_list_t *tl, size_t offset);
     extern void txg_list_destroy(txg_list_t *tl);
     extern boolean_t txg_list_empty(txg_list_t *tl, uint64_t txg);
    -extern int txg_list_add(txg_list_t *tl, void *p, uint64_t txg);
    -extern int txg_list_add_tail(txg_list_t *tl, void *p, uint64_t txg);
    +extern boolean_t txg_list_add(txg_list_t *tl, void *p, uint64_t txg);
    +extern boolean_t txg_list_add_tail(txg_list_t *tl, void *p, uint64_t txg);
     extern void *txg_list_remove(txg_list_t *tl, uint64_t txg);
     extern void *txg_list_remove_this(txg_list_t *tl, void *p, uint64_t txg);
    -extern int txg_list_member(txg_list_t *tl, void *p, uint64_t txg);
    +extern boolean_t txg_list_member(txg_list_t *tl, void *p, uint64_t txg);
     extern void *txg_list_head(txg_list_t *tl, uint64_t txg);
     extern void *txg_list_next(txg_list_t *tl, void *p, uint64_t txg);
     
    diff --git a/uts/common/fs/zfs/sys/zfeature.h b/uts/common/fs/zfs/sys/zfeature.h
    index 481e85b1bad..1a081e422d4 100644
    --- a/uts/common/fs/zfs/sys/zfeature.h
    +++ b/uts/common/fs/zfs/sys/zfeature.h
    @@ -26,7 +26,6 @@
     #ifndef _SYS_ZFEATURE_H
     #define	_SYS_ZFEATURE_H
     
    -#include 
     #include 
     #include "zfeature_common.h"
     
    @@ -34,14 +33,18 @@
     extern "C" {
     #endif
     
    -extern boolean_t feature_is_supported(objset_t *os, uint64_t obj,
    +struct spa;
    +struct dmu_tx;
    +struct objset;
    +
    +extern boolean_t feature_is_supported(struct objset *os, uint64_t obj,
         uint64_t desc_obj, nvlist_t *unsup_feat, nvlist_t *enabled_feat);
     
    -struct spa;
    -extern void spa_feature_create_zap_objects(struct spa *, dmu_tx_t *);
    -extern void spa_feature_enable(struct spa *, zfeature_info_t *, dmu_tx_t *);
    -extern void spa_feature_incr(struct spa *, zfeature_info_t *, dmu_tx_t *);
    -extern void spa_feature_decr(struct spa *, zfeature_info_t *, dmu_tx_t *);
    +extern void spa_feature_create_zap_objects(struct spa *, struct dmu_tx *);
    +extern void spa_feature_enable(struct spa *, zfeature_info_t *,
    +    struct dmu_tx *);
    +extern void spa_feature_incr(struct spa *, zfeature_info_t *, struct dmu_tx *);
    +extern void spa_feature_decr(struct spa *, zfeature_info_t *, struct dmu_tx *);
     extern boolean_t spa_feature_is_enabled(struct spa *, zfeature_info_t *);
     extern boolean_t spa_feature_is_active(struct spa *, zfeature_info_t *);
     
    diff --git a/uts/common/fs/zfs/sys/zfs_debug.h b/uts/common/fs/zfs/sys/zfs_debug.h
    index 94626229add..14eb2abdc1c 100644
    --- a/uts/common/fs/zfs/sys/zfs_debug.h
    +++ b/uts/common/fs/zfs/sys/zfs_debug.h
    @@ -48,11 +48,13 @@ extern "C" {
     
     extern int zfs_flags;
     
    -#define	ZFS_DEBUG_DPRINTF	0x0001
    -#define	ZFS_DEBUG_DBUF_VERIFY	0x0002
    -#define	ZFS_DEBUG_DNODE_VERIFY	0x0004
    -#define	ZFS_DEBUG_SNAPNAMES	0x0008
    -#define	ZFS_DEBUG_MODIFY	0x0010
    +#define	ZFS_DEBUG_DPRINTF	(1<<0)
    +#define	ZFS_DEBUG_DBUF_VERIFY	(1<<1)
    +#define	ZFS_DEBUG_DNODE_VERIFY	(1<<2)
    +#define	ZFS_DEBUG_SNAPNAMES	(1<<3)
    +#define	ZFS_DEBUG_MODIFY	(1<<4)
    +#define	ZFS_DEBUG_SPA		(1<<5)
    +#define	ZFS_DEBUG_ZIO_FREE	(1<<6)
     
     #ifdef ZFS_DEBUG
     extern void __dprintf(const char *file, const char *func,
    diff --git a/uts/common/fs/zfs/sys/zfs_ioctl.h b/uts/common/fs/zfs/sys/zfs_ioctl.h
    index 86e901be0d7..874d422568d 100644
    --- a/uts/common/fs/zfs/sys/zfs_ioctl.h
    +++ b/uts/common/fs/zfs/sys/zfs_ioctl.h
    @@ -293,7 +293,6 @@ typedef struct zfs_cmd {
     	uint64_t	zc_history;		/* really (char *) */
     	char		zc_value[MAXPATHLEN * 2];
     	char		zc_string[MAXNAMELEN];
    -	char		zc_top_ds[MAXPATHLEN];
     	uint64_t	zc_guid;
     	uint64_t	zc_nvlist_conf;		/* really (char *) */
     	uint64_t	zc_nvlist_conf_size;
    @@ -345,7 +344,8 @@ extern int zfs_secpolicy_rename_perms(const char *from,
         const char *to, cred_t *cr);
     extern int zfs_secpolicy_destroy_perms(const char *name, cred_t *cr);
     extern int zfs_busy(void);
    -extern int zfs_unmount_snap(const char *, void *);
    +extern void zfs_unmount_snap(const char *);
    +extern void zfs_destroy_unmount_origin(const char *);
     
     /*
      * ZFS minor numbers can refer to either a control device instance or
    diff --git a/uts/common/fs/zfs/sys/zfs_znode.h b/uts/common/fs/zfs/sys/zfs_znode.h
    index 3e9621a0ee2..cf0bbee2cab 100644
    --- a/uts/common/fs/zfs/sys/zfs_znode.h
    +++ b/uts/common/fs/zfs/sys/zfs_znode.h
    @@ -20,6 +20,7 @@
      */
     /*
      * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2012 by Delphix. All rights reserved.
      */
     
     #ifndef	_SYS_FS_ZFS_ZNODE_H
    @@ -240,7 +241,7 @@ typedef struct znode {
      */
     #define	ZFS_ENTER(zfsvfs) \
     	{ \
    -		rrw_enter(&(zfsvfs)->z_teardown_lock, RW_READER, FTAG); \
    +		rrw_enter_read(&(zfsvfs)->z_teardown_lock, FTAG); \
     		if ((zfsvfs)->z_unmounted) { \
     			ZFS_EXIT(zfsvfs); \
     			return (EIO); \
    diff --git a/uts/common/fs/zfs/sys/zil.h b/uts/common/fs/zfs/sys/zil.h
    index e52c65bb762..a212e4f0e11 100644
    --- a/uts/common/fs/zfs/sys/zil.h
    +++ b/uts/common/fs/zfs/sys/zil.h
    @@ -411,8 +411,8 @@ extern int	zil_check_log_chain(const char *osname, void *txarg);
     extern void	zil_sync(zilog_t *zilog, dmu_tx_t *tx);
     extern void	zil_clean(zilog_t *zilog, uint64_t synced_txg);
     
    -extern int	zil_suspend(zilog_t *zilog);
    -extern void	zil_resume(zilog_t *zilog);
    +extern int	zil_suspend(const char *osname, void **cookiep);
    +extern void	zil_resume(void *cookie);
     
     extern void	zil_add_block(zilog_t *zilog, const blkptr_t *bp);
     extern int	zil_bp_tree_add(zilog_t *zilog, const blkptr_t *bp);
    diff --git a/uts/common/fs/zfs/txg.c b/uts/common/fs/zfs/txg.c
    index 47603872afb..58690e325fe 100644
    --- a/uts/common/fs/zfs/txg.c
    +++ b/uts/common/fs/zfs/txg.c
    @@ -576,6 +576,8 @@ txg_wait_synced(dsl_pool_t *dp, uint64_t txg)
     {
     	tx_state_t *tx = &dp->dp_tx;
     
    +	ASSERT(!dsl_pool_config_held(dp));
    +
     	mutex_enter(&tx->tx_sync_lock);
     	ASSERT(tx->tx_threads == 2);
     	if (txg == 0)
    @@ -599,6 +601,8 @@ txg_wait_open(dsl_pool_t *dp, uint64_t txg)
     {
     	tx_state_t *tx = &dp->dp_tx;
     
    +	ASSERT(!dsl_pool_config_held(dp));
    +
     	mutex_enter(&tx->tx_sync_lock);
     	ASSERT(tx->tx_threads == 2);
     	if (txg == 0)
    @@ -664,42 +668,43 @@ txg_list_empty(txg_list_t *tl, uint64_t txg)
     }
     
     /*
    - * Add an entry to the list.
    - * Returns 0 if it's a new entry, 1 if it's already there.
    + * Add an entry to the list (unless it's already on the list).
    + * Returns B_TRUE if it was actually added.
      */
    -int
    +boolean_t
     txg_list_add(txg_list_t *tl, void *p, uint64_t txg)
     {
     	int t = txg & TXG_MASK;
     	txg_node_t *tn = (txg_node_t *)((char *)p + tl->tl_offset);
    -	int already_on_list;
    +	boolean_t add;
     
     	mutex_enter(&tl->tl_lock);
    -	already_on_list = tn->tn_member[t];
    -	if (!already_on_list) {
    +	add = (tn->tn_member[t] == 0);
    +	if (add) {
     		tn->tn_member[t] = 1;
     		tn->tn_next[t] = tl->tl_head[t];
     		tl->tl_head[t] = tn;
     	}
     	mutex_exit(&tl->tl_lock);
     
    -	return (already_on_list);
    +	return (add);
     }
     
     /*
    - * Add an entry to the end of the list (walks list to find end).
    - * Returns 0 if it's a new entry, 1 if it's already there.
    + * Add an entry to the end of the list, unless it's already on the list.
    + * (walks list to find end)
    + * Returns B_TRUE if it was actually added.
      */
    -int
    +boolean_t
     txg_list_add_tail(txg_list_t *tl, void *p, uint64_t txg)
     {
     	int t = txg & TXG_MASK;
     	txg_node_t *tn = (txg_node_t *)((char *)p + tl->tl_offset);
    -	int already_on_list;
    +	boolean_t add;
     
     	mutex_enter(&tl->tl_lock);
    -	already_on_list = tn->tn_member[t];
    -	if (!already_on_list) {
    +	add = (tn->tn_member[t] == 0);
    +	if (add) {
     		txg_node_t **tp;
     
     		for (tp = &tl->tl_head[t]; *tp != NULL; tp = &(*tp)->tn_next[t])
    @@ -711,7 +716,7 @@ txg_list_add_tail(txg_list_t *tl, void *p, uint64_t txg)
     	}
     	mutex_exit(&tl->tl_lock);
     
    -	return (already_on_list);
    +	return (add);
     }
     
     /*
    @@ -762,13 +767,13 @@ txg_list_remove_this(txg_list_t *tl, void *p, uint64_t txg)
     	return (NULL);
     }
     
    -int
    +boolean_t
     txg_list_member(txg_list_t *tl, void *p, uint64_t txg)
     {
     	int t = txg & TXG_MASK;
     	txg_node_t *tn = (txg_node_t *)((char *)p + tl->tl_offset);
     
    -	return (tn->tn_member[t]);
    +	return (tn->tn_member[t] != 0);
     }
     
     /*
    diff --git a/uts/common/fs/zfs/zfs_ctldir.c b/uts/common/fs/zfs/zfs_ctldir.c
    index d902ff637c3..ef9a5611a25 100644
    --- a/uts/common/fs/zfs/zfs_ctldir.c
    +++ b/uts/common/fs/zfs/zfs_ctldir.c
    @@ -72,6 +72,7 @@
     #include 
     #include 
     #include 
    +#include 
     #include 
     #include 
     #include 
    @@ -615,7 +616,7 @@ zfsctl_snapdir_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm,
     	zfsvfs_t *zfsvfs;
     	avl_index_t where;
     	char from[MAXNAMELEN], to[MAXNAMELEN];
    -	char real[MAXNAMELEN];
    +	char real[MAXNAMELEN], fsname[MAXNAMELEN];
     	int err;
     
     	zfsvfs = sdvp->v_vfsp->vfs_data;
    @@ -634,12 +635,14 @@ zfsctl_snapdir_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm,
     
     	ZFS_EXIT(zfsvfs);
     
    +	dmu_objset_name(zfsvfs->z_os, fsname);
    +
     	err = zfsctl_snapshot_zname(sdvp, snm, MAXNAMELEN, from);
    -	if (!err)
    +	if (err == 0)
     		err = zfsctl_snapshot_zname(tdvp, tnm, MAXNAMELEN, to);
    -	if (!err)
    +	if (err == 0)
     		err = zfs_secpolicy_rename_perms(from, to, cr);
    -	if (err)
    +	if (err != 0)
     		return (err);
     
     	/*
    @@ -659,7 +662,7 @@ zfsctl_snapdir_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm,
     		return (ENOENT);
     	}
     
    -	err = dmu_objset_rename(from, to, B_FALSE);
    +	err = dsl_dataset_rename_snapshot(fsname, snm, tnm, B_FALSE);
     	if (err == 0)
     		zfsctl_rename_snap(sdp, sep, tnm);
     
    @@ -699,9 +702,9 @@ zfsctl_snapdir_remove(vnode_t *dvp, char *name, vnode_t *cwd, cred_t *cr,
     	ZFS_EXIT(zfsvfs);
     
     	err = zfsctl_snapshot_zname(dvp, name, MAXNAMELEN, snapname);
    -	if (!err)
    +	if (err == 0)
     		err = zfs_secpolicy_destroy_perms(snapname, cr);
    -	if (err)
    +	if (err != 0)
     		return (err);
     
     	mutex_enter(&sdp->sd_lock);
    @@ -711,10 +714,10 @@ zfsctl_snapdir_remove(vnode_t *dvp, char *name, vnode_t *cwd, cred_t *cr,
     	if (sep) {
     		avl_remove(&sdp->sd_snaps, sep);
     		err = zfsctl_unmount_snap(sep, MS_FORCE, cr);
    -		if (err)
    +		if (err != 0)
     			avl_add(&sdp->sd_snaps, sep);
     		else
    -			err = dmu_objset_destroy(snapname, B_FALSE);
    +			err = dsl_destroy_snapshot(snapname, B_FALSE);
     	} else {
     		err = ENOENT;
     	}
    @@ -746,12 +749,12 @@ zfsctl_snapdir_mkdir(vnode_t *dvp, char *dirname, vattr_t *vap, vnode_t  **vpp,
     	*vpp = NULL;
     
     	err = zfs_secpolicy_snapshot_perms(name, cr);
    -	if (err)
    +	if (err != 0)
     		return (err);
     
     	if (err == 0) {
     		err = dmu_objset_snapshot_one(name, dirname);
    -		if (err)
    +		if (err != 0)
     			return (err);
     		err = lookupnameat(dirname, seg, follow, NULL, vpp, dvp);
     	}
    @@ -831,7 +834,7 @@ zfsctl_snapdir_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, pathname_t *pnp,
     		*vpp = sep->se_root;
     		VN_HOLD(*vpp);
     		err = traverse(vpp);
    -		if (err) {
    +		if (err != 0) {
     			VN_RELE(*vpp);
     			*vpp = NULL;
     		} else if (*vpp == sep->se_root) {
    @@ -857,7 +860,7 @@ zfsctl_snapdir_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, pathname_t *pnp,
     	 * The requested snapshot is not currently mounted, look it up.
     	 */
     	err = zfsctl_snapshot_zname(dvp, nm, MAXNAMELEN, snapname);
    -	if (err) {
    +	if (err != 0) {
     		mutex_exit(&sdp->sd_lock);
     		ZFS_EXIT(zfsvfs);
     		/*
    @@ -930,7 +933,7 @@ domount:
     	 * If we had an error, drop our hold on the vnode and
     	 * zfsctl_snapshot_inactive() will clean up.
     	 */
    -	if (err) {
    +	if (err != 0) {
     		VN_RELE(*vpp);
     		*vpp = NULL;
     	}
    @@ -982,8 +985,10 @@ zfsctl_snapdir_readdir_cb(vnode_t *vp, void *dp, int *eofp,
     	ZFS_ENTER(zfsvfs);
     
     	cookie = *offp;
    +	dsl_pool_config_enter(dmu_objset_pool(zfsvfs->z_os), FTAG);
     	error = dmu_snapshot_list_next(zfsvfs->z_os, MAXNAMELEN, snapname, &id,
     	    &cookie, &case_conflict);
    +	dsl_pool_config_exit(dmu_objset_pool(zfsvfs->z_os), FTAG);
     	if (error) {
     		ZFS_EXIT(zfsvfs);
     		if (error == ENOENT) {
    diff --git a/uts/common/fs/zfs/zfs_ioctl.c b/uts/common/fs/zfs/zfs_ioctl.c
    index 38adc1940ff..caad34c5a70 100644
    --- a/uts/common/fs/zfs/zfs_ioctl.c
    +++ b/uts/common/fs/zfs/zfs_ioctl.c
    @@ -156,6 +156,7 @@
     #include 
     #include 
     #include 
    +#include 
     #include 
     #include 
     #include 
    @@ -173,6 +174,9 @@
     #include 
     #include 
     #include 
    +#include 
    +#include 
    +#include 
     #include 
     
     #include "zfs_namecheck.h"
    @@ -237,11 +241,7 @@ static int zfs_fill_zplprops_root(uint64_t, nvlist_t *, nvlist_t *,
     int zfs_set_prop_nvlist(const char *, zprop_source_t, nvlist_t *, nvlist_t *);
     static int get_nvlist(uint64_t nvl, uint64_t size, int iflag, nvlist_t **nvp);
     
    -static int zfs_prop_activate_feature(dsl_pool_t *dp, zfeature_info_t *feature);
    -static int zfs_prop_activate_feature_check(void *arg1, void *arg2,
    -    dmu_tx_t *tx);
    -static void zfs_prop_activate_feature_sync(void *arg1, void *arg2,
    -    dmu_tx_t *tx);
    +static int zfs_prop_activate_feature(spa_t *spa, zfeature_info_t *feature);
     
     /* _NOTE(PRINTFLIKE(4)) - this is printf-like, but lint is too whiney */
     void
    @@ -461,37 +461,12 @@ zfs_dozonecheck_ds(const char *dataset, dsl_dataset_t *ds, cred_t *cr)
     {
     	uint64_t zoned;
     
    -	rw_enter(&ds->ds_dir->dd_pool->dp_config_rwlock, RW_READER);
    -	if (dsl_prop_get_ds(ds, "zoned", 8, 1, &zoned, NULL)) {
    -		rw_exit(&ds->ds_dir->dd_pool->dp_config_rwlock);
    +	if (dsl_prop_get_int_ds(ds, "zoned", &zoned))
     		return (ENOENT);
    -	}
    -	rw_exit(&ds->ds_dir->dd_pool->dp_config_rwlock);
     
     	return (zfs_dozonecheck_impl(dataset, zoned, cr));
     }
     
    -static int
    -zfs_secpolicy_write_perms(const char *name, const char *perm, cred_t *cr)
    -{
    -	int error;
    -	dsl_dataset_t *ds;
    -
    -	error = dsl_dataset_hold(name, FTAG, &ds);
    -	if (error != 0)
    -		return (error);
    -
    -	error = zfs_dozonecheck_ds(name, ds, cr);
    -	if (error == 0) {
    -		error = secpolicy_zfs(cr);
    -		if (error)
    -			error = dsl_deleg_access_impl(ds, perm, cr);
    -	}
    -
    -	dsl_dataset_rele(ds, FTAG);
    -	return (error);
    -}
    -
     static int
     zfs_secpolicy_write_perms_ds(const char *name, dsl_dataset_t *ds,
         const char *perm, cred_t *cr)
    @@ -501,12 +476,36 @@ zfs_secpolicy_write_perms_ds(const char *name, dsl_dataset_t *ds,
     	error = zfs_dozonecheck_ds(name, ds, cr);
     	if (error == 0) {
     		error = secpolicy_zfs(cr);
    -		if (error)
    +		if (error != 0)
     			error = dsl_deleg_access_impl(ds, perm, cr);
     	}
     	return (error);
     }
     
    +static int
    +zfs_secpolicy_write_perms(const char *name, const char *perm, cred_t *cr)
    +{
    +	int error;
    +	dsl_dataset_t *ds;
    +	dsl_pool_t *dp;
    +
    +	error = dsl_pool_hold(name, FTAG, &dp);
    +	if (error != 0)
    +		return (error);
    +
    +	error = dsl_dataset_hold(dp, name, FTAG, &ds);
    +	if (error != 0) {
    +		dsl_pool_rele(dp, FTAG);
    +		return (error);
    +	}
    +
    +	error = zfs_secpolicy_write_perms_ds(name, ds, perm, cr);
    +
    +	dsl_dataset_rele(ds, FTAG);
    +	dsl_pool_rele(dp, FTAG);
    +	return (error);
    +}
    +
     /*
      * Policy for setting the security label property.
      *
    @@ -525,7 +524,7 @@ zfs_set_slabel_policy(const char *name, char *strval, cred_t *cr)
     	/* First get the existing dataset label. */
     	error = dsl_prop_get(name, zfs_prop_to_name(ZFS_PROP_MLSLABEL),
     	    1, sizeof (ds_hexsl), &ds_hexsl, NULL);
    -	if (error)
    +	if (error != 0)
     		return (EPERM);
     
     	if (strcasecmp(strval, ZFS_MLSLABEL_DEFAULT) == 0)
    @@ -575,7 +574,7 @@ zfs_set_slabel_policy(const char *name, char *strval, cred_t *cr)
     		 */
     		error = dmu_objset_own(name, DMU_OST_ZFS, B_TRUE,
     		    setsl_tag, &os);
    -		if (error)
    +		if (error != 0)
     			return (EPERM);
     
     		dmu_objset_disown(os, setsl_tag);
    @@ -663,7 +662,7 @@ zfs_secpolicy_set_fsacl(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
     	int error;
     
     	error = zfs_dozonecheck(zc->zc_name, cr);
    -	if (error)
    +	if (error != 0)
     		return (error);
     
     	/*
    @@ -685,7 +684,6 @@ zfs_secpolicy_rollback(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
     static int
     zfs_secpolicy_send(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
     {
    -	spa_t *spa;
     	dsl_pool_t *dp;
     	dsl_dataset_t *ds;
     	char *cp;
    @@ -698,23 +696,22 @@ zfs_secpolicy_send(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
     	cp = strchr(zc->zc_name, '@');
     	if (cp == NULL)
     		return (EINVAL);
    -	error = spa_open(zc->zc_name, &spa, FTAG);
    -	if (error)
    +	error = dsl_pool_hold(zc->zc_name, FTAG, &dp);
    +	if (error != 0)
     		return (error);
     
    -	dp = spa_get_dsl(spa);
    -	rw_enter(&dp->dp_config_rwlock, RW_READER);
     	error = dsl_dataset_hold_obj(dp, zc->zc_sendobj, FTAG, &ds);
    -	rw_exit(&dp->dp_config_rwlock);
    -	spa_close(spa, FTAG);
    -	if (error)
    +	if (error != 0) {
    +		dsl_pool_rele(dp, FTAG);
     		return (error);
    +	}
     
     	dsl_dataset_name(ds, zc->zc_name);
     
     	error = zfs_secpolicy_write_perms_ds(zc->zc_name, ds,
     	    ZFS_DELEG_PERM_SEND, cr);
     	dsl_dataset_rele(ds, FTAG);
    +	dsl_pool_rele(dp, FTAG);
     
     	return (error);
     }
    @@ -835,12 +832,21 @@ zfs_secpolicy_destroy_snaps(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
     		return (EINVAL);
     	for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL;
     	    pair = nextpair) {
    +		dsl_pool_t *dp;
     		dsl_dataset_t *ds;
     
    +		error = dsl_pool_hold(nvpair_name(pair), FTAG, &dp);
    +		if (error != 0)
    +			break;
     		nextpair = nvlist_next_nvpair(snaps, pair);
    -		error = dsl_dataset_hold(nvpair_name(pair), FTAG, &ds);
    -		if (error == 0) {
    +		error = dsl_dataset_hold(dp, nvpair_name(pair), FTAG, &ds);
    +		if (error == 0)
     			dsl_dataset_rele(ds, FTAG);
    +		dsl_pool_rele(dp, FTAG);
    +
    +		if (error == 0) {
    +			error = zfs_secpolicy_destroy_perms(nvpair_name(pair),
    +			    cr);
     		} else if (error == ENOENT) {
     			/*
     			 * Ignore any snapshots that don't exist (we consider
    @@ -852,11 +858,7 @@ zfs_secpolicy_destroy_snaps(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
     			 */
     			fnvlist_remove_nvpair(snaps, pair);
     			error = 0;
    -			continue;
    -		} else {
    -			break;
     		}
    -		error = zfs_secpolicy_destroy_perms(nvpair_name(pair), cr);
     		if (error != 0)
     			break;
     	}
    @@ -904,41 +906,47 @@ zfs_secpolicy_rename(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
     static int
     zfs_secpolicy_promote(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
     {
    -	char	parentname[MAXNAMELEN];
    -	objset_t *clone;
    +	dsl_pool_t *dp;
    +	dsl_dataset_t *clone;
     	int error;
     
     	error = zfs_secpolicy_write_perms(zc->zc_name,
     	    ZFS_DELEG_PERM_PROMOTE, cr);
    -	if (error)
    +	if (error != 0)
     		return (error);
     
    -	error = dmu_objset_hold(zc->zc_name, FTAG, &clone);
    +	error = dsl_pool_hold(zc->zc_name, FTAG, &dp);
    +	if (error != 0)
    +		return (error);
    +
    +	error = dsl_dataset_hold(dp, zc->zc_name, FTAG, &clone);
     
     	if (error == 0) {
    -		dsl_dataset_t *pclone = NULL;
    +		char parentname[MAXNAMELEN];
    +		dsl_dataset_t *origin = NULL;
     		dsl_dir_t *dd;
    -		dd = clone->os_dsl_dataset->ds_dir;
    +		dd = clone->ds_dir;
     
    -		rw_enter(&dd->dd_pool->dp_config_rwlock, RW_READER);
     		error = dsl_dataset_hold_obj(dd->dd_pool,
    -		    dd->dd_phys->dd_origin_obj, FTAG, &pclone);
    -		rw_exit(&dd->dd_pool->dp_config_rwlock);
    -		if (error) {
    -			dmu_objset_rele(clone, FTAG);
    +		    dd->dd_phys->dd_origin_obj, FTAG, &origin);
    +		if (error != 0) {
    +			dsl_dataset_rele(clone, FTAG);
    +			dsl_pool_rele(dp, FTAG);
     			return (error);
     		}
     
    -		error = zfs_secpolicy_write_perms(zc->zc_name,
    +		error = zfs_secpolicy_write_perms_ds(zc->zc_name, clone,
     		    ZFS_DELEG_PERM_MOUNT, cr);
     
    -		dsl_dataset_name(pclone, parentname);
    -		dmu_objset_rele(clone, FTAG);
    -		dsl_dataset_rele(pclone, FTAG);
    -		if (error == 0)
    -			error = zfs_secpolicy_write_perms(parentname,
    +		dsl_dataset_name(origin, parentname);
    +		if (error == 0) {
    +			error = zfs_secpolicy_write_perms_ds(parentname, origin,
     			    ZFS_DELEG_PERM_PROMOTE, cr);
    +		}
    +		dsl_dataset_rele(clone, FTAG);
    +		dsl_dataset_rele(origin, FTAG);
     	}
    +	dsl_pool_rele(dp, FTAG);
     	return (error);
     }
     
    @@ -1147,16 +1155,47 @@ zfs_secpolicy_userspace_upgrade(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
     static int
     zfs_secpolicy_hold(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
     {
    -	return (zfs_secpolicy_write_perms(zc->zc_name,
    -	    ZFS_DELEG_PERM_HOLD, cr));
    +	nvpair_t *pair;
    +	nvlist_t *holds;
    +	int error;
    +
    +	error = nvlist_lookup_nvlist(innvl, "holds", &holds);
    +	if (error != 0)
    +		return (EINVAL);
    +
    +	for (pair = nvlist_next_nvpair(holds, NULL); pair != NULL;
    +	    pair = nvlist_next_nvpair(holds, pair)) {
    +		char fsname[MAXNAMELEN];
    +		error = dmu_fsname(nvpair_name(pair), fsname);
    +		if (error != 0)
    +			return (error);
    +		error = zfs_secpolicy_write_perms(fsname,
    +		    ZFS_DELEG_PERM_HOLD, cr);
    +		if (error != 0)
    +			return (error);
    +	}
    +	return (0);
     }
     
     /* ARGSUSED */
     static int
     zfs_secpolicy_release(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
     {
    -	return (zfs_secpolicy_write_perms(zc->zc_name,
    -	    ZFS_DELEG_PERM_RELEASE, cr));
    +	nvpair_t *pair;
    +	int error;
    +
    +	for (pair = nvlist_next_nvpair(innvl, NULL); pair != NULL;
    +	    pair = nvlist_next_nvpair(innvl, pair)) {
    +		char fsname[MAXNAMELEN];
    +		error = dmu_fsname(nvpair_name(pair), fsname);
    +		if (error != 0)
    +			return (error);
    +		error = zfs_secpolicy_write_perms(fsname,
    +		    ZFS_DELEG_PERM_RELEASE, cr);
    +		if (error != 0)
    +			return (error);
    +	}
    +	return (0);
     }
     
     /*
    @@ -1177,11 +1216,11 @@ zfs_secpolicy_tmp_snapshot(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
     		return (0);
     
     	error = zfs_secpolicy_snapshot_perms(zc->zc_name, cr);
    -	if (!error)
    +	if (error == 0)
     		error = zfs_secpolicy_hold(zc, innvl, cr);
    -	if (!error)
    +	if (error == 0)
     		error = zfs_secpolicy_release(zc, innvl, cr);
    -	if (!error)
    +	if (error == 0)
     		error = zfs_secpolicy_destroy(zc, innvl, cr);
     	return (error);
     }
    @@ -1291,7 +1330,7 @@ getzfsvfs(const char *dsname, zfsvfs_t **zfvp)
     	int error;
     
     	error = dmu_objset_hold(dsname, FTAG, &os);
    -	if (error)
    +	if (error != 0)
     		return (error);
     	if (dmu_objset_type(os) != DMU_OST_ZFS) {
     		dmu_objset_rele(os, FTAG);
    @@ -1394,7 +1433,7 @@ zfs_ioc_pool_create(zfs_cmd_t *zc)
     		VERIFY(nvlist_alloc(&zplprops, NV_UNIQUE_NAME, KM_SLEEP) == 0);
     		error = zfs_fill_zplprops_root(version, rootprops,
     		    zplprops, NULL);
    -		if (error)
    +		if (error != 0)
     			goto pool_props_bad;
     	}
     
    @@ -1667,12 +1706,7 @@ zfs_ioc_pool_reguid(zfs_cmd_t *zc)
     static int
     zfs_ioc_dsobj_to_dsname(zfs_cmd_t *zc)
     {
    -	int error;
    -
    -	if (error = dsl_dsobj_to_dsname(zc->zc_name, zc->zc_obj, zc->zc_value))
    -		return (error);
    -
    -	return (0);
    +	return (dsl_dsobj_to_dsname(zc->zc_name, zc->zc_obj, zc->zc_value));
     }
     
     /*
    @@ -1988,15 +2022,14 @@ zfs_ioc_objset_stats_impl(zfs_cmd_t *zc, objset_t *os)
     static int
     zfs_ioc_objset_stats(zfs_cmd_t *zc)
     {
    -	objset_t *os = NULL;
    +	objset_t *os;
     	int error;
     
    -	if (error = dmu_objset_hold(zc->zc_name, FTAG, &os))
    -		return (error);
    -
    -	error = zfs_ioc_objset_stats_impl(zc, os);
    -
    -	dmu_objset_rele(os, FTAG);
    +	error = dmu_objset_hold(zc->zc_name, FTAG, &os);
    +	if (error == 0) {
    +		error = zfs_ioc_objset_stats_impl(zc, os);
    +		dmu_objset_rele(os, FTAG);
    +	}
     
     	return (error);
     }
    @@ -2017,30 +2050,23 @@ zfs_ioc_objset_stats(zfs_cmd_t *zc)
     static int
     zfs_ioc_objset_recvd_props(zfs_cmd_t *zc)
     {
    -	objset_t *os = NULL;
    -	int error;
    +	int error = 0;
     	nvlist_t *nv;
     
    -	if (error = dmu_objset_hold(zc->zc_name, FTAG, &os))
    -		return (error);
    -
     	/*
     	 * Without this check, we would return local property values if the
     	 * caller has not already received properties on or after
     	 * SPA_VERSION_RECVD_PROPS.
     	 */
    -	if (!dsl_prop_get_hasrecvd(os)) {
    -		dmu_objset_rele(os, FTAG);
    +	if (!dsl_prop_get_hasrecvd(zc->zc_name))
     		return (ENOTSUP);
    -	}
     
     	if (zc->zc_nvlist_dst != 0 &&
    -	    (error = dsl_prop_get_received(os, &nv)) == 0) {
    +	    (error = dsl_prop_get_received(zc->zc_name, &nv)) == 0) {
     		error = put_nvlist(zc, nv);
     		nvlist_free(nv);
     	}
     
    -	dmu_objset_rele(os, FTAG);
     	return (error);
     }
     
    @@ -2155,20 +2181,6 @@ top:
     		(void) strlcat(zc->zc_name, "/", sizeof (zc->zc_name));
     	p = zc->zc_name + strlen(zc->zc_name);
     
    -	/*
    -	 * Pre-fetch the datasets.  dmu_objset_prefetch() always returns 0
    -	 * but is not declared void because its called by dmu_objset_find().
    -	 */
    -	if (zc->zc_cookie == 0) {
    -		uint64_t cookie = 0;
    -		int len = sizeof (zc->zc_name) - (p - zc->zc_name);
    -
    -		while (dmu_dir_list_next(os, len, p, NULL, &cookie) == 0) {
    -			if (!dataset_name_hidden(zc->zc_name))
    -				(void) dmu_objset_prefetch(zc->zc_name, NULL);
    -		}
    -	}
    -
     	do {
     		error = dmu_dir_list_next(os,
     		    sizeof (zc->zc_name) - (p - zc->zc_name), p,
    @@ -2211,14 +2223,10 @@ zfs_ioc_snapshot_list_next(zfs_cmd_t *zc)
     	objset_t *os;
     	int error;
     
    -top:
    -	if (zc->zc_cookie == 0)
    -		(void) dmu_objset_find(zc->zc_name, dmu_objset_prefetch,
    -		    NULL, DS_FIND_SNAPSHOTS);
    -
     	error = dmu_objset_hold(zc->zc_name, FTAG, &os);
    -	if (error)
    +	if (error != 0) {
     		return (error == ENOENT ? ESRCH : error);
    +	}
     
     	/*
     	 * A dataset name of maximum length cannot have any snapshots,
    @@ -2238,24 +2246,8 @@ top:
     		dsl_dataset_t *ds;
     		dsl_pool_t *dp = os->os_dsl_dataset->ds_dir->dd_pool;
     
    -		/*
    -		 * Since we probably don't have a hold on this snapshot,
    -		 * it's possible that the objsetid could have been destroyed
    -		 * and reused for a new objset. It's OK if this happens during
    -		 * a zfs send operation, since the new createtxg will be
    -		 * beyond the range we're interested in.
    -		 */
    -		rw_enter(&dp->dp_config_rwlock, RW_READER);
     		error = dsl_dataset_hold_obj(dp, zc->zc_obj, FTAG, &ds);
    -		rw_exit(&dp->dp_config_rwlock);
    -		if (error) {
    -			if (error == ENOENT) {
    -				/* Racing with destroy, get the next one. */
    -				*strchr(zc->zc_name, '@') = '\0';
    -				dmu_objset_rele(os, FTAG);
    -				goto top;
    -			}
    -		} else {
    +		if (error == 0) {
     			objset_t *ossnap;
     
     			error = dmu_objset_from_ds(ds, &ossnap);
    @@ -2269,7 +2261,7 @@ top:
     
     	dmu_objset_rele(os, FTAG);
     	/* if we failed, undo the @ that we tacked on to zc_name */
    -	if (error)
    +	if (error != 0)
     		*strchr(zc->zc_name, '@') = '\0';
     	return (error);
     }
    @@ -2359,13 +2351,13 @@ zfs_prop_set_special(const char *dsname, zprop_source_t source,
     		err = dsl_dir_set_quota(dsname, source, intval);
     		break;
     	case ZFS_PROP_REFQUOTA:
    -		err = dsl_dataset_set_quota(dsname, source, intval);
    +		err = dsl_dataset_set_refquota(dsname, source, intval);
     		break;
     	case ZFS_PROP_RESERVATION:
     		err = dsl_dir_set_reservation(dsname, source, intval);
     		break;
     	case ZFS_PROP_REFRESERVATION:
    -		err = dsl_dataset_set_reservation(dsname, source, intval);
    +		err = dsl_dataset_set_refreservation(dsname, source, intval);
     		break;
     	case ZFS_PROP_VOLSIZE:
     		err = zvol_set_volsize(dsname, intval);
    @@ -2396,19 +2388,16 @@ zfs_prop_set_special(const char *dsname, zprop_source_t source,
     			zfeature_info_t *feature =
     			    &spa_feature_table[SPA_FEATURE_LZ4_COMPRESS];
     			spa_t *spa;
    -			dsl_pool_t *dp;
     
     			if ((err = spa_open(dsname, &spa, FTAG)) != 0)
     				return (err);
     
    -			dp = spa->spa_dsl_pool;
    -
     			/*
     			 * Setting the LZ4 compression algorithm activates
     			 * the feature.
     			 */
     			if (!spa_feature_is_active(spa, feature)) {
    -				if ((err = zfs_prop_activate_feature(dp,
    +				if ((err = zfs_prop_activate_feature(spa,
     				    feature)) != 0) {
     					spa_close(spa, FTAG);
     					return (err);
    @@ -2567,12 +2556,12 @@ retry:
     
     			if (nvpair_type(propval) == DATA_TYPE_STRING) {
     				strval = fnvpair_value_string(propval);
    -				err = dsl_prop_set(dsname, propname, source, 1,
    -				    strlen(strval) + 1, strval);
    +				err = dsl_prop_set_string(dsname, propname,
    +				    source, strval);
     			} else {
     				intval = fnvpair_value_uint64(propval);
    -				err = dsl_prop_set(dsname, propname, source, 8,
    -				    1, &intval);
    +				err = dsl_prop_set_int(dsname, propname, source,
    +				    intval);
     			}
     
     			if (err != 0) {
    @@ -2638,7 +2627,7 @@ props_skip(nvlist_t *props, nvlist_t *skipped, nvlist_t **newprops)
     }
     
     static int
    -clear_received_props(objset_t *os, const char *fs, nvlist_t *props,
    +clear_received_props(const char *dsname, nvlist_t *props,
         nvlist_t *skipped)
     {
     	int err = 0;
    @@ -2650,8 +2639,8 @@ clear_received_props(objset_t *os, const char *fs, nvlist_t *props,
     		 * properties at least once on or after SPA_VERSION_RECVD_PROPS.
     		 */
     		zprop_source_t flags = (ZPROP_SRC_NONE |
    -		    (dsl_prop_get_hasrecvd(os) ? ZPROP_SRC_RECEIVED : 0));
    -		err = zfs_set_prop_nvlist(fs, flags, cleared_props, NULL);
    +		    (dsl_prop_get_hasrecvd(dsname) ? ZPROP_SRC_RECEIVED : 0));
    +		err = zfs_set_prop_nvlist(dsname, flags, cleared_props, NULL);
     	}
     	nvlist_free(cleared_props);
     	return (err);
    @@ -2683,22 +2672,19 @@ zfs_ioc_set_prop(zfs_cmd_t *zc)
     
     	if (received) {
     		nvlist_t *origprops;
    -		objset_t *os;
     
    -		if (dmu_objset_hold(zc->zc_name, FTAG, &os) == 0) {
    -			if (dsl_prop_get_received(os, &origprops) == 0) {
    -				(void) clear_received_props(os,
    -				    zc->zc_name, origprops, nvl);
    -				nvlist_free(origprops);
    -			}
    -
    -			dsl_prop_set_hasrecvd(os);
    -			dmu_objset_rele(os, FTAG);
    +		if (dsl_prop_get_received(zc->zc_name, &origprops) == 0) {
    +			(void) clear_received_props(zc->zc_name,
    +			    origprops, nvl);
    +			nvlist_free(origprops);
     		}
    +
    +		error = dsl_prop_set_hasrecvd(zc->zc_name);
     	}
     
     	errors = fnvlist_alloc();
    -	error = zfs_set_prop_nvlist(zc->zc_name, source, nvl, errors);
    +	if (error == 0)
    +		error = zfs_set_prop_nvlist(zc->zc_name, source, nvl, errors);
     
     	if (zc->zc_nvlist_dst != NULL && errors != NULL) {
     		(void) put_nvlist(zc, errors);
    @@ -2781,7 +2767,7 @@ zfs_ioc_inherit_prop(zfs_cmd_t *zc)
     	}
     
     	/* property name has been validated by zfs_secpolicy_inherit_prop() */
    -	return (dsl_prop_set(zc->zc_name, zc->zc_value, source, 0, 0, NULL));
    +	return (dsl_prop_inherit(zc->zc_name, zc->zc_value, source));
     }
     
     static int
    @@ -2893,7 +2879,7 @@ zfs_ioc_set_fsacl(zfs_cmd_t *zc)
     	 */
     
     	error = secpolicy_zfs(CRED());
    -	if (error) {
    +	if (error != 0) {
     		if (zc->zc_perm_action == B_FALSE) {
     			error = dsl_deleg_can_allow(zc->zc_name,
     			    fsaclnv, CRED());
    @@ -3221,7 +3207,7 @@ zfs_ioc_create(const char *fsname, nvlist_t *innvl, nvlist_t *outnvl)
     		error = zfs_set_prop_nvlist(fsname, ZPROP_SRC_LOCAL,
     		    nvprops, outnvl);
     		if (error != 0)
    -			(void) dmu_objset_destroy(fsname, B_FALSE);
    +			(void) dsl_destroy_head(fsname);
     	}
     	return (error);
     }
    @@ -3240,7 +3226,6 @@ zfs_ioc_clone(const char *fsname, nvlist_t *innvl, nvlist_t *outnvl)
     	int error = 0;
     	nvlist_t *nvprops = NULL;
     	char *origin_name;
    -	dsl_dataset_t *origin;
     
     	if (nvlist_lookup_string(innvl, "origin", &origin_name) != 0)
     		return (EINVAL);
    @@ -3252,14 +3237,8 @@ zfs_ioc_clone(const char *fsname, nvlist_t *innvl, nvlist_t *outnvl)
     
     	if (dataset_namecheck(origin_name, NULL, NULL) != 0)
     		return (EINVAL);
    -
    -	error = dsl_dataset_hold(origin_name, FTAG, &origin);
    -	if (error)
    -		return (error);
    -
    -	error = dmu_objset_clone(fsname, origin, 0);
    -	dsl_dataset_rele(origin, FTAG);
    -	if (error)
    +	error = dmu_objset_clone(fsname, origin_name);
    +	if (error != 0)
     		return (error);
     
     	/*
    @@ -3269,7 +3248,7 @@ zfs_ioc_clone(const char *fsname, nvlist_t *innvl, nvlist_t *outnvl)
     		error = zfs_set_prop_nvlist(fsname, ZPROP_SRC_LOCAL,
     		    nvprops, outnvl);
     		if (error != 0)
    -			(void) dmu_objset_destroy(fsname, B_FALSE);
    +			(void) dsl_destroy_head(fsname);
     	}
     	return (error);
     }
    @@ -3281,7 +3260,6 @@ zfs_ioc_clone(const char *fsname, nvlist_t *innvl, nvlist_t *outnvl)
      * }
      *
      * outnvl: snapshot -> error code (int32)
    - *
      */
     static int
     zfs_ioc_snapshot(const char *poolname, nvlist_t *innvl, nvlist_t *outnvl)
    @@ -3331,7 +3309,7 @@ zfs_ioc_snapshot(const char *poolname, nvlist_t *innvl, nvlist_t *outnvl)
     		}
     	}
     
    -	error = dmu_objset_snapshot(snaps, props, outnvl);
    +	error = dsl_dataset_snapshot(snaps, props, outnvl);
     	return (error);
     }
     
    @@ -3376,30 +3354,73 @@ zfs_ioc_log_history(const char *unused, nvlist_t *innvl, nvlist_t *outnvl)
     	return (error);
     }
     
    -/* ARGSUSED */
    -int
    -zfs_unmount_snap(const char *name, void *arg)
    +/*
    + * The dp_config_rwlock must not be held when calling this, because the
    + * unmount may need to write out data.
    + *
    + * This function is best-effort.  Callers must deal gracefully if it
    + * remains mounted (or is remounted after this call).
    + */
    +void
    +zfs_unmount_snap(const char *snapname)
     {
     	vfs_t *vfsp;
    -	int err;
    +	zfsvfs_t *zfsvfs;
     
    -	if (strchr(name, '@') == NULL)
    -		return (0);
    +	if (strchr(snapname, '@') == NULL)
    +		return;
     
    -	vfsp = zfs_get_vfs(name);
    +	vfsp = zfs_get_vfs(snapname);
     	if (vfsp == NULL)
    -		return (0);
    +		return;
     
    -	if ((err = vn_vfswlock(vfsp->vfs_vnodecovered)) != 0) {
    +	zfsvfs = vfsp->vfs_data;
    +	ASSERT(!dsl_pool_config_held(dmu_objset_pool(zfsvfs->z_os)));
    +
    +	if (vn_vfswlock(vfsp->vfs_vnodecovered) != 0) {
     		VFS_RELE(vfsp);
    -		return (err);
    +		return;
     	}
     	VFS_RELE(vfsp);
     
     	/*
     	 * Always force the unmount for snapshots.
     	 */
    -	return (dounmount(vfsp, MS_FORCE, kcred));
    +	(void) dounmount(vfsp, MS_FORCE, kcred);
    +}
    +
    +/* ARGSUSED */
    +static int
    +zfs_unmount_snap_cb(const char *snapname, void *arg)
    +{
    +	zfs_unmount_snap(snapname);
    +	return (0);
    +}
    +
    +/*
    + * When a clone is destroyed, its origin may also need to be destroyed,
    + * in which case it must be unmounted.  This routine will do that unmount
    + * if necessary.
    + */
    +void
    +zfs_destroy_unmount_origin(const char *fsname)
    +{
    +	int error;
    +	objset_t *os;
    +	dsl_dataset_t *ds;
    +
    +	error = dmu_objset_hold(fsname, FTAG, &os);
    +	if (error != 0)
    +		return;
    +	ds = dmu_objset_ds(os);
    +	if (dsl_dir_is_clone(ds->ds_dir) && DS_IS_DEFER_DESTROY(ds->ds_prev)) {
    +		char originname[MAXNAMELEN];
    +		dsl_dataset_name(ds->ds_prev, originname);
    +		dmu_objset_rele(os, FTAG);
    +		zfs_unmount_snap(originname);
    +	} else {
    +		dmu_objset_rele(os, FTAG);
    +	}
     }
     
     /*
    @@ -3435,14 +3456,10 @@ zfs_ioc_destroy_snaps(const char *poolname, nvlist_t *innvl, nvlist_t *outnvl)
     		    (name[poollen] != '/' && name[poollen] != '@'))
     			return (EXDEV);
     
    -		/*
    -		 * Ignore failures to unmount; dmu_snapshots_destroy_nvl()
    -		 * will deal with this gracefully (by filling in outnvl).
    -		 */
    -		(void) zfs_unmount_snap(name, NULL);
    +		zfs_unmount_snap(name);
     	}
     
    -	return (dmu_snapshots_destroy_nvl(snaps, defer, outnvl));
    +	return (dsl_destroy_snapshots_nvl(snaps, defer, outnvl));
     }
     
     /*
    @@ -3457,13 +3474,13 @@ static int
     zfs_ioc_destroy(zfs_cmd_t *zc)
     {
     	int err;
    -	if (strchr(zc->zc_name, '@') && zc->zc_objset_type == DMU_OST_ZFS) {
    -		err = zfs_unmount_snap(zc->zc_name, NULL);
    -		if (err)
    -			return (err);
    -	}
    +	if (strchr(zc->zc_name, '@') && zc->zc_objset_type == DMU_OST_ZFS)
    +		zfs_unmount_snap(zc->zc_name);
     
    -	err = dmu_objset_destroy(zc->zc_name, zc->zc_defer_destroy);
    +	if (strchr(zc->zc_name, '@'))
    +		err = dsl_destroy_snapshot(zc->zc_name, zc->zc_defer_destroy);
    +	else
    +		err = dsl_destroy_head(zc->zc_name);
     	if (zc->zc_objset_type == DMU_OST_ZVOL && err == 0)
     		(void) zvol_remove_minor(zc->zc_name);
     	return (err);
    @@ -3478,81 +3495,36 @@ zfs_ioc_destroy(zfs_cmd_t *zc)
     static int
     zfs_ioc_rollback(zfs_cmd_t *zc)
     {
    -	dsl_dataset_t *ds, *clone;
    -	int error;
     	zfsvfs_t *zfsvfs;
    -	char *clone_name;
    +	int error;
     
    -	error = dsl_dataset_hold(zc->zc_name, FTAG, &ds);
    -	if (error)
    -		return (error);
    -
    -	/* must not be a snapshot */
    -	if (dsl_dataset_is_snapshot(ds)) {
    -		dsl_dataset_rele(ds, FTAG);
    -		return (EINVAL);
    -	}
    -
    -	/* must have a most recent snapshot */
    -	if (ds->ds_phys->ds_prev_snap_txg < TXG_INITIAL) {
    -		dsl_dataset_rele(ds, FTAG);
    -		return (EINVAL);
    -	}
    -
    -	/*
    -	 * Create clone of most recent snapshot.
    -	 */
    -	clone_name = kmem_asprintf("%s/%%rollback", zc->zc_name);
    -	error = dmu_objset_clone(clone_name, ds->ds_prev, DS_FLAG_INCONSISTENT);
    -	if (error)
    -		goto out;
    -
    -	error = dsl_dataset_own(clone_name, B_TRUE, FTAG, &clone);
    -	if (error)
    -		goto out;
    -
    -	/*
    -	 * Do clone swap.
    -	 */
     	if (getzfsvfs(zc->zc_name, &zfsvfs) == 0) {
     		error = zfs_suspend_fs(zfsvfs);
     		if (error == 0) {
     			int resume_err;
     
    -			if (dsl_dataset_tryown(ds, B_FALSE, FTAG)) {
    -				error = dsl_dataset_clone_swap(clone, ds,
    -				    B_TRUE);
    -				dsl_dataset_disown(ds, FTAG);
    -				ds = NULL;
    -			} else {
    -				error = EBUSY;
    -			}
    +			error = dsl_dataset_rollback(zc->zc_name);
     			resume_err = zfs_resume_fs(zfsvfs, zc->zc_name);
     			error = error ? error : resume_err;
     		}
     		VFS_RELE(zfsvfs->z_vfs);
     	} else {
    -		if (dsl_dataset_tryown(ds, B_FALSE, FTAG)) {
    -			error = dsl_dataset_clone_swap(clone, ds, B_TRUE);
    -			dsl_dataset_disown(ds, FTAG);
    -			ds = NULL;
    -		} else {
    -			error = EBUSY;
    -		}
    +		error = dsl_dataset_rollback(zc->zc_name);
     	}
    -
    -	/*
    -	 * Destroy clone (which also closes it).
    -	 */
    -	(void) dsl_dataset_destroy(clone, FTAG, B_FALSE);
    -
    -out:
    -	strfree(clone_name);
    -	if (ds)
    -		dsl_dataset_rele(ds, FTAG);
     	return (error);
     }
     
    +static int
    +recursive_unmount(const char *fsname, void *arg)
    +{
    +	const char *snapname = arg;
    +	char fullname[MAXNAMELEN];
    +
    +	(void) snprintf(fullname, sizeof (fullname), "%s@%s", fsname, snapname);
    +	zfs_unmount_snap(fullname);
    +	return (0);
    +}
    +
     /*
      * inputs:
      * zc_name	old name of dataset
    @@ -3565,26 +3537,33 @@ static int
     zfs_ioc_rename(zfs_cmd_t *zc)
     {
     	boolean_t recursive = zc->zc_cookie & 1;
    +	char *at;
     
     	zc->zc_value[sizeof (zc->zc_value) - 1] = '\0';
     	if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 ||
     	    strchr(zc->zc_value, '%'))
     		return (EINVAL);
     
    -	/*
    -	 * Unmount snapshot unless we're doing a recursive rename,
    -	 * in which case the dataset code figures out which snapshots
    -	 * to unmount.
    -	 */
    -	if (!recursive && strchr(zc->zc_name, '@') != NULL &&
    -	    zc->zc_objset_type == DMU_OST_ZFS) {
    -		int err = zfs_unmount_snap(zc->zc_name, NULL);
    -		if (err)
    -			return (err);
    +	at = strchr(zc->zc_name, '@');
    +	if (at != NULL) {
    +		/* snaps must be in same fs */
    +		if (strncmp(zc->zc_name, zc->zc_value, at - zc->zc_name + 1))
    +			return (EXDEV);
    +		*at = '\0';
    +		if (zc->zc_objset_type == DMU_OST_ZFS) {
    +			int error = dmu_objset_find(zc->zc_name,
    +			    recursive_unmount, at + 1,
    +			    recursive ? DS_FIND_CHILDREN : 0);
    +			if (error != 0)
    +				return (error);
    +		}
    +		return (dsl_dataset_rename_snapshot(zc->zc_name,
    +		    at + 1, strchr(zc->zc_value, '@') + 1, recursive));
    +	} else {
    +		if (zc->zc_objset_type == DMU_OST_ZVOL)
    +			(void) zvol_remove_minor(zc->zc_name);
    +		return (dsl_dir_rename(zc->zc_name, zc->zc_value));
     	}
    -	if (zc->zc_objset_type == DMU_OST_ZVOL)
    -		(void) zvol_remove_minor(zc->zc_name);
    -	return (dmu_objset_rename(zc->zc_name, zc->zc_value, recursive));
     }
     
     static int
    @@ -3727,36 +3706,15 @@ zfs_check_settable(const char *dsname, nvpair_t *pair, cred_t *cr)
     	return (zfs_secpolicy_setprop(dsname, prop, pair, CRED()));
     }
     
    -/*
    - * Activates a feature on a pool in response to a property setting. This
    - * creates a new sync task which modifies the pool to reflect the feature
    - * as being active.
    - */
    -static int
    -zfs_prop_activate_feature(dsl_pool_t *dp, zfeature_info_t *feature)
    -{
    -	int err;
    -
    -	/* EBUSY here indicates that the feature is already active */
    -	err = dsl_sync_task_do(dp, zfs_prop_activate_feature_check,
    -	    zfs_prop_activate_feature_sync, dp->dp_spa, feature, 2);
    -
    -	if (err != 0 && err != EBUSY)
    -		return (err);
    -	else
    -		return (0);
    -}
    -
     /*
      * Checks for a race condition to make sure we don't increment a feature flag
      * multiple times.
      */
    -/*ARGSUSED*/
     static int
    -zfs_prop_activate_feature_check(void *arg1, void *arg2, dmu_tx_t *tx)
    +zfs_prop_activate_feature_check(void *arg, dmu_tx_t *tx)
     {
    -	spa_t *spa = arg1;
    -	zfeature_info_t *feature = arg2;
    +	spa_t *spa = dmu_tx_pool(tx)->dp_spa;
    +	zfeature_info_t *feature = arg;
     
     	if (!spa_feature_is_active(spa, feature))
     		return (0);
    @@ -3769,14 +3727,35 @@ zfs_prop_activate_feature_check(void *arg1, void *arg2, dmu_tx_t *tx)
      * zfs_prop_activate_feature.
      */
     static void
    -zfs_prop_activate_feature_sync(void *arg1, void *arg2, dmu_tx_t *tx)
    +zfs_prop_activate_feature_sync(void *arg, dmu_tx_t *tx)
     {
    -	spa_t *spa = arg1;
    -	zfeature_info_t *feature = arg2;
    +	spa_t *spa = dmu_tx_pool(tx)->dp_spa;
    +	zfeature_info_t *feature = arg;
     
     	spa_feature_incr(spa, feature, tx);
     }
     
    +/*
    + * Activates a feature on a pool in response to a property setting. This
    + * creates a new sync task which modifies the pool to reflect the feature
    + * as being active.
    + */
    +static int
    +zfs_prop_activate_feature(spa_t *spa, zfeature_info_t *feature)
    +{
    +	int err;
    +
    +	/* EBUSY here indicates that the feature is already active */
    +	err = dsl_sync_task(spa_name(spa),
    +	    zfs_prop_activate_feature_check, zfs_prop_activate_feature_sync,
    +	    feature, 2);
    +
    +	if (err != 0 && err != EBUSY)
    +		return (err);
    +	else
    +		return (0);
    +}
    +
     /*
      * Removes properties from the given props list that fail permission checks
      * needed to clear them and to restore them in case of a receive error. For each
    @@ -3931,7 +3910,6 @@ static int
     zfs_ioc_recv(zfs_cmd_t *zc)
     {
     	file_t *fp;
    -	objset_t *os;
     	dmu_recv_cookie_t drc;
     	boolean_t force = (boolean_t)zc->zc_guid;
     	int fd;
    @@ -3941,7 +3919,7 @@ zfs_ioc_recv(zfs_cmd_t *zc)
     	offset_t off;
     	nvlist_t *props = NULL; /* sent properties */
     	nvlist_t *origprops = NULL; /* existing properties */
    -	objset_t *origin = NULL;
    +	char *origin = NULL;
     	char *tosnap;
     	char tofs[ZFS_MAXNAMELEN];
     	boolean_t first_recvd_props = B_FALSE;
    @@ -3969,18 +3947,31 @@ zfs_ioc_recv(zfs_cmd_t *zc)
     
     	VERIFY(nvlist_alloc(&errors, NV_UNIQUE_NAME, KM_SLEEP) == 0);
     
    -	if (props && dmu_objset_hold(tofs, FTAG, &os) == 0) {
    -		if ((spa_version(os->os_spa) >= SPA_VERSION_RECVD_PROPS) &&
    -		    !dsl_prop_get_hasrecvd(os)) {
    +	if (zc->zc_string[0])
    +		origin = zc->zc_string;
    +
    +	error = dmu_recv_begin(tofs, tosnap,
    +	    &zc->zc_begin_record, force, origin, &drc);
    +	if (error != 0)
    +		goto out;
    +
    +	/*
    +	 * Set properties before we receive the stream so that they are applied
    +	 * to the new data. Note that we must call dmu_recv_stream() if
    +	 * dmu_recv_begin() succeeds.
    +	 */
    +	if (props != NULL && !drc.drc_newfs) {
    +		if (spa_version(dsl_dataset_get_spa(drc.drc_ds)) >=
    +		    SPA_VERSION_RECVD_PROPS &&
    +		    !dsl_prop_get_hasrecvd(tofs))
     			first_recvd_props = B_TRUE;
    -		}
     
     		/*
     		 * If new received properties are supplied, they are to
     		 * completely replace the existing received properties, so stash
     		 * away the existing ones.
     		 */
    -		if (dsl_prop_get_received(os, &origprops) == 0) {
    +		if (dsl_prop_get_received(tofs, &origprops) == 0) {
     			nvlist_t *errlist = NULL;
     			/*
     			 * Don't bother writing a property if its value won't
    @@ -3992,53 +3983,25 @@ zfs_ioc_recv(zfs_cmd_t *zc)
     			 */
     			if (!first_recvd_props)
     				props_reduce(props, origprops);
    -			if (zfs_check_clearable(tofs, origprops,
    -			    &errlist) != 0)
    +			if (zfs_check_clearable(tofs, origprops, &errlist) != 0)
     				(void) nvlist_merge(errors, errlist, 0);
     			nvlist_free(errlist);
    -		}
     
    -		dmu_objset_rele(os, FTAG);
    -	}
    -
    -	if (zc->zc_string[0]) {
    -		error = dmu_objset_hold(zc->zc_string, FTAG, &origin);
    -		if (error)
    -			goto out;
    -	}
    -
    -	error = dmu_recv_begin(tofs, tosnap, zc->zc_top_ds,
    -	    &zc->zc_begin_record, force, origin, &drc);
    -	if (origin)
    -		dmu_objset_rele(origin, FTAG);
    -	if (error)
    -		goto out;
    -
    -	/*
    -	 * Set properties before we receive the stream so that they are applied
    -	 * to the new data. Note that we must call dmu_recv_stream() if
    -	 * dmu_recv_begin() succeeds.
    -	 */
    -	if (props) {
    -		if (dmu_objset_from_ds(drc.drc_logical_ds, &os) == 0) {
    -			if (drc.drc_newfs) {
    -				if (spa_version(os->os_spa) >=
    -				    SPA_VERSION_RECVD_PROPS)
    -					first_recvd_props = B_TRUE;
    -			} else if (origprops != NULL) {
    -				if (clear_received_props(os, tofs, origprops,
    -				    first_recvd_props ? NULL : props) != 0)
    -					zc->zc_obj |= ZPROP_ERR_NOCLEAR;
    -			} else {
    +			if (clear_received_props(tofs, origprops,
    +			    first_recvd_props ? NULL : props) != 0)
     				zc->zc_obj |= ZPROP_ERR_NOCLEAR;
    -			}
    -			dsl_prop_set_hasrecvd(os);
    -		} else if (!drc.drc_newfs) {
    +		} else {
     			zc->zc_obj |= ZPROP_ERR_NOCLEAR;
     		}
    +	}
     
    -		(void) zfs_set_prop_nvlist(tofs, ZPROP_SRC_RECEIVED,
    -		    props, errors);
    +	if (props != NULL) {
    +		props_error = dsl_prop_set_hasrecvd(tofs);
    +
    +		if (props_error == 0) {
    +			(void) zfs_set_prop_nvlist(tofs, ZPROP_SRC_RECEIVED,
    +			    props, errors);
    +		}
     	}
     
     	if (zc->zc_nvlist_dst_size != 0 &&
    @@ -4090,22 +4053,16 @@ zfs_ioc_recv(zfs_cmd_t *zc)
     	/*
     	 * On error, restore the original props.
     	 */
    -	if (error && props) {
    -		if (dmu_objset_hold(tofs, FTAG, &os) == 0) {
    -			if (clear_received_props(os, tofs, props, NULL) != 0) {
    -				/*
    -				 * We failed to clear the received properties.
    -				 * Since we may have left a $recvd value on the
    -				 * system, we can't clear the $hasrecvd flag.
    -				 */
    -				zc->zc_obj |= ZPROP_ERR_NORESTORE;
    -			} else if (first_recvd_props) {
    -				dsl_prop_unset_hasrecvd(os);
    -			}
    -			dmu_objset_rele(os, FTAG);
    -		} else if (!drc.drc_newfs) {
    -			/* We failed to clear the received properties. */
    +	if (error != 0 && props != NULL && !drc.drc_newfs) {
    +		if (clear_received_props(tofs, props, NULL) != 0) {
    +			/*
    +			 * We failed to clear the received properties.
    +			 * Since we may have left a $recvd value on the
    +			 * system, we can't clear the $hasrecvd flag.
    +			 */
     			zc->zc_obj |= ZPROP_ERR_NORESTORE;
    +		} else if (first_recvd_props) {
    +			dsl_prop_unset_hasrecvd(tofs);
     		}
     
     		if (origprops == NULL && !drc.drc_newfs) {
    @@ -4157,100 +4114,75 @@ out:
     static int
     zfs_ioc_send(zfs_cmd_t *zc)
     {
    -	objset_t *fromsnap = NULL;
    -	objset_t *tosnap;
     	int error;
     	offset_t off;
    -	dsl_dataset_t *ds;
    -	dsl_dataset_t *dsfrom = NULL;
    -	spa_t *spa;
    -	dsl_pool_t *dp;
     	boolean_t estimate = (zc->zc_guid != 0);
     
    -	error = spa_open(zc->zc_name, &spa, FTAG);
    -	if (error)
    -		return (error);
    +	if (zc->zc_obj != 0) {
    +		dsl_pool_t *dp;
    +		dsl_dataset_t *tosnap;
     
    -	dp = spa_get_dsl(spa);
    -	rw_enter(&dp->dp_config_rwlock, RW_READER);
    -	error = dsl_dataset_hold_obj(dp, zc->zc_sendobj, FTAG, &ds);
    -	rw_exit(&dp->dp_config_rwlock);
    -	spa_close(spa, FTAG);
    -	if (error)
    -		return (error);
    +		error = dsl_pool_hold(zc->zc_name, FTAG, &dp);
    +		if (error != 0)
    +			return (error);
     
    -	error = dmu_objset_from_ds(ds, &tosnap);
    -	if (error) {
    -		dsl_dataset_rele(ds, FTAG);
    -		return (error);
    -	}
    -
    -	if (zc->zc_fromobj != 0) {
    -		rw_enter(&dp->dp_config_rwlock, RW_READER);
    -		error = dsl_dataset_hold_obj(dp, zc->zc_fromobj, FTAG, &dsfrom);
    -		rw_exit(&dp->dp_config_rwlock);
    -		if (error) {
    -			dsl_dataset_rele(ds, FTAG);
    +		error = dsl_dataset_hold_obj(dp, zc->zc_sendobj, FTAG, &tosnap);
    +		if (error != 0) {
    +			dsl_pool_rele(dp, FTAG);
     			return (error);
     		}
    -		error = dmu_objset_from_ds(dsfrom, &fromsnap);
    -		if (error) {
    -			dsl_dataset_rele(dsfrom, FTAG);
    -			dsl_dataset_rele(ds, FTAG);
    -			return (error);
    -		}
    -	}
     
    -	if (zc->zc_obj) {
    -		dsl_pool_t *dp = ds->ds_dir->dd_pool;
    -
    -		if (fromsnap != NULL) {
    -			dsl_dataset_rele(dsfrom, FTAG);
    -			dsl_dataset_rele(ds, FTAG);
    -			return (EINVAL);
    -		}
    -
    -		if (dsl_dir_is_clone(ds->ds_dir)) {
    -			rw_enter(&dp->dp_config_rwlock, RW_READER);
    -			error = dsl_dataset_hold_obj(dp,
    -			    ds->ds_dir->dd_phys->dd_origin_obj, FTAG, &dsfrom);
    -			rw_exit(&dp->dp_config_rwlock);
    -			if (error) {
    -				dsl_dataset_rele(ds, FTAG);
    -				return (error);
    -			}
    -			error = dmu_objset_from_ds(dsfrom, &fromsnap);
    -			if (error) {
    -				dsl_dataset_rele(dsfrom, FTAG);
    -				dsl_dataset_rele(ds, FTAG);
    -				return (error);
    -			}
    -		}
    +		if (dsl_dir_is_clone(tosnap->ds_dir))
    +			zc->zc_fromobj = tosnap->ds_dir->dd_phys->dd_origin_obj;
    +		dsl_dataset_rele(tosnap, FTAG);
    +		dsl_pool_rele(dp, FTAG);
     	}
     
     	if (estimate) {
    -		error = dmu_send_estimate(tosnap, fromsnap,
    -		    &zc->zc_objset_type);
    -	} else {
    -		file_t *fp = getf(zc->zc_cookie);
    -		if (fp == NULL) {
    -			dsl_dataset_rele(ds, FTAG);
    -			if (dsfrom)
    -				dsl_dataset_rele(dsfrom, FTAG);
    -			return (EBADF);
    +		dsl_pool_t *dp;
    +		dsl_dataset_t *tosnap;
    +		dsl_dataset_t *fromsnap = NULL;
    +
    +		error = dsl_pool_hold(zc->zc_name, FTAG, &dp);
    +		if (error != 0)
    +			return (error);
    +
    +		error = dsl_dataset_hold_obj(dp, zc->zc_sendobj, FTAG, &tosnap);
    +		if (error != 0) {
    +			dsl_pool_rele(dp, FTAG);
    +			return (error);
     		}
     
    +		if (zc->zc_fromobj != 0) {
    +			error = dsl_dataset_hold_obj(dp, zc->zc_fromobj,
    +			    FTAG, &fromsnap);
    +			if (error != 0) {
    +				dsl_dataset_rele(tosnap, FTAG);
    +				dsl_pool_rele(dp, FTAG);
    +				return (error);
    +			}
    +		}
    +
    +		error = dmu_send_estimate(tosnap, fromsnap,
    +		    &zc->zc_objset_type);
    +
    +		if (fromsnap != NULL)
    +			dsl_dataset_rele(fromsnap, FTAG);
    +		dsl_dataset_rele(tosnap, FTAG);
    +		dsl_pool_rele(dp, FTAG);
    +	} else {
    +		file_t *fp = getf(zc->zc_cookie);
    +		if (fp == NULL)
    +			return (EBADF);
    +
     		off = fp->f_offset;
    -		error = dmu_send(tosnap, fromsnap,
    -		    zc->zc_cookie, fp->f_vnode, &off);
    +		error = dmu_send_obj(zc->zc_name, zc->zc_sendobj,
    +		    zc->zc_fromobj, zc->zc_cookie, fp->f_vnode, &off);
     
     		if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0)
     			fp->f_offset = off;
     		releasef(zc->zc_cookie);
     	}
    -	if (dsfrom)
    -		dsl_dataset_rele(dsfrom, FTAG);
    -	dsl_dataset_rele(ds, FTAG);
     	return (error);
     }
     
    @@ -4265,13 +4197,21 @@ zfs_ioc_send(zfs_cmd_t *zc)
     static int
     zfs_ioc_send_progress(zfs_cmd_t *zc)
     {
    +	dsl_pool_t *dp;
     	dsl_dataset_t *ds;
     	dmu_sendarg_t *dsp = NULL;
     	int error;
     
    -	if ((error = dsl_dataset_hold(zc->zc_name, FTAG, &ds)) != 0)
    +	error = dsl_pool_hold(zc->zc_name, FTAG, &dp);
    +	if (error != 0)
     		return (error);
     
    +	error = dsl_dataset_hold(dp, zc->zc_name, FTAG, &ds);
    +	if (error != 0) {
    +		dsl_pool_rele(dp, FTAG);
    +		return (error);
    +	}
    +
     	mutex_enter(&ds->ds_sendstream_lock);
     
     	/*
    @@ -4294,6 +4234,7 @@ zfs_ioc_send_progress(zfs_cmd_t *zc)
     
     	mutex_exit(&ds->ds_sendstream_lock);
     	dsl_dataset_rele(ds, FTAG);
    +	dsl_pool_rele(dp, FTAG);
     	return (error);
     }
     
    @@ -4400,7 +4341,7 @@ zfs_ioc_clear(zfs_cmd_t *zc)
     		}
     	}
     
    -	if (error)
    +	if (error != 0)
     		return (error);
     
     	spa_vdev_state_enter(spa, SCL_NONE);
    @@ -4438,7 +4379,7 @@ zfs_ioc_pool_reopen(zfs_cmd_t *zc)
     	int error;
     
     	error = spa_open(zc->zc_name, &spa, FTAG);
    -	if (error)
    +	if (error != 0)
     		return (error);
     
     	spa_vdev_state_enter(spa, SCL_NONE);
    @@ -4478,7 +4419,7 @@ zfs_ioc_promote(zfs_cmd_t *zc)
     	if (cp)
     		*cp = '\0';
     	(void) dmu_objset_find(zc->zc_value,
    -	    zfs_unmount_snap, NULL, DS_FIND_SNAPSHOTS);
    +	    zfs_unmount_snap_cb, NULL, DS_FIND_SNAPSHOTS);
     	return (dsl_dataset_promote(zc->zc_name, zc->zc_string));
     }
     
    @@ -4504,7 +4445,7 @@ zfs_ioc_userspace_one(zfs_cmd_t *zc)
     		return (EINVAL);
     
     	error = zfsvfs_hold(zc->zc_name, FTAG, &zfsvfs, B_FALSE);
    -	if (error)
    +	if (error != 0)
     		return (error);
     
     	error = zfs_userspace_one(zfsvfs,
    @@ -4535,7 +4476,7 @@ zfs_ioc_userspace_many(zfs_cmd_t *zc)
     		return (ENOMEM);
     
     	int error = zfsvfs_hold(zc->zc_name, FTAG, &zfsvfs, B_FALSE);
    -	if (error)
    +	if (error != 0)
     		return (error);
     
     	void *buf = kmem_alloc(bufsize, KM_SLEEP);
    @@ -4585,7 +4526,7 @@ zfs_ioc_userspace_upgrade(zfs_cmd_t *zc)
     	} else {
     		/* XXX kind of reading contents without owning */
     		error = dmu_objset_hold(zc->zc_name, FTAG, &os);
    -		if (error)
    +		if (error != 0)
     			return (error);
     
     		error = dmu_objset_userspace_upgrade(os);
    @@ -4658,7 +4599,7 @@ zfs_ioc_share(zfs_cmd_t *zc)
     				return (ENOSYS);
     			}
     			error = zfs_init_sharefs();
    -			if (error) {
    +			if (error != 0) {
     				mutex_exit(&zfs_share_lock);
     				return (ENOSYS);
     			}
    @@ -4683,7 +4624,7 @@ zfs_ioc_share(zfs_cmd_t *zc)
     				return (ENOSYS);
     			}
     			error = zfs_init_sharefs();
    -			if (error) {
    +			if (error != 0) {
     				mutex_exit(&zfs_share_lock);
     				return (ENOSYS);
     			}
    @@ -4748,7 +4689,7 @@ zfs_ioc_next_obj(zfs_cmd_t *zc)
     	int error;
     
     	error = dmu_objset_hold(zc->zc_name, FTAG, &os);
    -	if (error)
    +	if (error != 0)
     		return (error);
     
     	error = dmu_object_next(os, &zc->zc_obj, B_FALSE,
    @@ -4771,25 +4712,26 @@ static int
     zfs_ioc_tmp_snapshot(zfs_cmd_t *zc)
     {
     	char *snap_name;
    +	char *hold_name;
     	int error;
    +	minor_t minor;
     
    -	snap_name = kmem_asprintf("%s@%s-%016llx", zc->zc_name, zc->zc_value,
    -	    (u_longlong_t)ddi_get_lbolt64());
    -
    -	if (strlen(snap_name) >= MAXPATHLEN) {
    -		strfree(snap_name);
    -		return (E2BIG);
    -	}
    -
    -	error = dmu_objset_snapshot_tmp(snap_name, "%temp", zc->zc_cleanup_fd);
    -	if (error != 0) {
    -		strfree(snap_name);
    +	error = zfs_onexit_fd_hold(zc->zc_cleanup_fd, &minor);
    +	if (error != 0)
     		return (error);
    -	}
     
    -	(void) strcpy(zc->zc_value, strchr(snap_name, '@') + 1);
    +	snap_name = kmem_asprintf("%s-%016llx", zc->zc_value,
    +	    (u_longlong_t)ddi_get_lbolt64());
    +	hold_name = kmem_asprintf("%%%s", zc->zc_value);
    +
    +	error = dsl_dataset_snapshot_tmp(zc->zc_name, snap_name, minor,
    +	    hold_name);
    +	if (error == 0)
    +		(void) strcpy(zc->zc_value, snap_name);
     	strfree(snap_name);
    -	return (0);
    +	strfree(hold_name);
    +	zfs_onexit_fd_rele(zc->zc_cleanup_fd);
    +	return (error);
     }
     
     /*
    @@ -4804,39 +4746,22 @@ zfs_ioc_tmp_snapshot(zfs_cmd_t *zc)
     static int
     zfs_ioc_diff(zfs_cmd_t *zc)
     {
    -	objset_t *fromsnap;
    -	objset_t *tosnap;
     	file_t *fp;
     	offset_t off;
     	int error;
     
    -	error = dmu_objset_hold(zc->zc_name, FTAG, &tosnap);
    -	if (error)
    -		return (error);
    -
    -	error = dmu_objset_hold(zc->zc_value, FTAG, &fromsnap);
    -	if (error) {
    -		dmu_objset_rele(tosnap, FTAG);
    -		return (error);
    -	}
    -
     	fp = getf(zc->zc_cookie);
    -	if (fp == NULL) {
    -		dmu_objset_rele(fromsnap, FTAG);
    -		dmu_objset_rele(tosnap, FTAG);
    +	if (fp == NULL)
     		return (EBADF);
    -	}
     
     	off = fp->f_offset;
     
    -	error = dmu_diff(tosnap, fromsnap, fp->f_vnode, &off);
    +	error = dmu_diff(zc->zc_name, zc->zc_value, fp->f_vnode, &off);
     
     	if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0)
     		fp->f_offset = off;
     	releasef(zc->zc_cookie);
     
    -	dmu_objset_rele(fromsnap, FTAG);
    -	dmu_objset_rele(tosnap, FTAG);
     	return (error);
     }
     
    @@ -4905,13 +4830,13 @@ zfs_ioc_smb_acl(zfs_cmd_t *zc)
     		    ZFS_SHARES_DIR);
     		dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, FALSE, NULL);
     		error = dmu_tx_assign(tx, TXG_WAIT);
    -		if (error) {
    +		if (error != 0) {
     			dmu_tx_abort(tx);
     		} else {
     			error = zfs_create_share_dir(zfsvfs, tx);
     			dmu_tx_commit(tx);
     		}
    -		if (error) {
    +		if (error != 0) {
     			mutex_exit(&zfsvfs->z_lock);
     			VN_RELE(vp);
     			ZFS_EXIT(zfsvfs);
    @@ -4990,124 +4915,82 @@ zfs_ioc_smb_acl(zfs_cmd_t *zc)
     }
     
     /*
    - * inputs:
    - * zc_name		name of filesystem
    - * zc_value		short name of snap
    - * zc_string		user-supplied tag for this hold
    - * zc_cookie		recursive flag
    - * zc_temphold		set if hold is temporary
    - * zc_cleanup_fd	cleanup-on-exit file descriptor for calling process
    - * zc_sendobj		if non-zero, the objid for zc_name@zc_value
    - * zc_createtxg		if zc_sendobj is non-zero, snap must have zc_createtxg
    + * innvl: {
    + *     "holds" -> { snapname -> holdname (string), ... }
    + *     (optional) "cleanup_fd" -> fd (int32)
    + * }
      *
    - * outputs:		none
    + * outnvl: {
    + *     snapname -> error value (int32)
    + *     ...
    + * }
      */
    +/* ARGSUSED */
     static int
    -zfs_ioc_hold(zfs_cmd_t *zc)
    +zfs_ioc_hold(const char *pool, nvlist_t *args, nvlist_t *errlist)
     {
    -	boolean_t recursive = zc->zc_cookie;
    -	spa_t *spa;
    -	dsl_pool_t *dp;
    -	dsl_dataset_t *ds;
    +	nvlist_t *holds;
    +	int cleanup_fd = -1;
     	int error;
     	minor_t minor = 0;
     
    -	if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0)
    +	error = nvlist_lookup_nvlist(args, "holds", &holds);
    +	if (error != 0)
     		return (EINVAL);
     
    -	if (zc->zc_sendobj == 0) {
    -		return (dsl_dataset_user_hold(zc->zc_name, zc->zc_value,
    -		    zc->zc_string, recursive, zc->zc_temphold,
    -		    zc->zc_cleanup_fd));
    +	if (nvlist_lookup_int32(args, "cleanup_fd", &cleanup_fd) == 0) {
    +		error = zfs_onexit_fd_hold(cleanup_fd, &minor);
    +		if (error != 0)
    +			return (error);
     	}
     
    -	if (recursive)
    -		return (EINVAL);
    +	error = dsl_dataset_user_hold(holds, minor, errlist);
    +	if (minor != 0)
    +		zfs_onexit_fd_rele(cleanup_fd);
    +	return (error);
    +}
     
    -	error = spa_open(zc->zc_name, &spa, FTAG);
    -	if (error)
    -		return (error);
    +/*
    + * innvl is not used.
    + *
    + * outnvl: {
    + *    holdname -> time added (uint64 seconds since epoch)
    + *    ...
    + * }
    + */
    +/* ARGSUSED */
    +static int
    +zfs_ioc_get_holds(const char *snapname, nvlist_t *args, nvlist_t *outnvl)
    +{
    +	return (dsl_dataset_get_holds(snapname, outnvl));
    +}
     
    -	dp = spa_get_dsl(spa);
    -	rw_enter(&dp->dp_config_rwlock, RW_READER);
    -	error = dsl_dataset_hold_obj(dp, zc->zc_sendobj, FTAG, &ds);
    -	rw_exit(&dp->dp_config_rwlock);
    -	spa_close(spa, FTAG);
    -	if (error)
    -		return (error);
    +/*
    + * innvl: {
    + *     snapname -> { holdname, ... }
    + *     ...
    + * }
    + *
    + * outnvl: {
    + *     snapname -> error value (int32)
    + *     ...
    + * }
    + */
    +/* ARGSUSED */
    +static int
    +zfs_ioc_release(const char *pool, nvlist_t *holds, nvlist_t *errlist)
    +{
    +	nvpair_t *pair;
     
     	/*
    -	 * Until we have a hold on this snapshot, it's possible that
    -	 * zc_sendobj could've been destroyed and reused as part
    -	 * of a later txg.  Make sure we're looking at the right object.
    +	 * The release may cause the snapshot to be destroyed; make sure it
    +	 * is not mounted.
     	 */
    -	if (zc->zc_createtxg != ds->ds_phys->ds_creation_txg) {
    -		dsl_dataset_rele(ds, FTAG);
    -		return (ENOENT);
    -	}
    +	for (pair = nvlist_next_nvpair(holds, NULL); pair != NULL;
    +	    pair = nvlist_next_nvpair(holds, pair))
    +		zfs_unmount_snap(nvpair_name(pair));
     
    -	if (zc->zc_cleanup_fd != -1 && zc->zc_temphold) {
    -		error = zfs_onexit_fd_hold(zc->zc_cleanup_fd, &minor);
    -		if (error) {
    -			dsl_dataset_rele(ds, FTAG);
    -			return (error);
    -		}
    -	}
    -
    -	error = dsl_dataset_user_hold_for_send(ds, zc->zc_string,
    -	    zc->zc_temphold);
    -	if (minor != 0) {
    -		if (error == 0) {
    -			dsl_register_onexit_hold_cleanup(ds, zc->zc_string,
    -			    minor);
    -		}
    -		zfs_onexit_fd_rele(zc->zc_cleanup_fd);
    -	}
    -	dsl_dataset_rele(ds, FTAG);
    -
    -	return (error);
    -}
    -
    -/*
    - * inputs:
    - * zc_name	name of dataset from which we're releasing a user hold
    - * zc_value	short name of snap
    - * zc_string	user-supplied tag for this hold
    - * zc_cookie	recursive flag
    - *
    - * outputs:	none
    - */
    -static int
    -zfs_ioc_release(zfs_cmd_t *zc)
    -{
    -	boolean_t recursive = zc->zc_cookie;
    -
    -	if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0)
    -		return (EINVAL);
    -
    -	return (dsl_dataset_user_release(zc->zc_name, zc->zc_value,
    -	    zc->zc_string, recursive));
    -}
    -
    -/*
    - * inputs:
    - * zc_name		name of filesystem
    - *
    - * outputs:
    - * zc_nvlist_src{_size}	nvlist of snapshot holds
    - */
    -static int
    -zfs_ioc_get_holds(zfs_cmd_t *zc)
    -{
    -	nvlist_t *nvp;
    -	int error;
    -
    -	if ((error = dsl_dataset_get_holds(zc->zc_name, &nvp)) == 0) {
    -		error = put_nvlist(zc, nvp);
    -		nvlist_free(nvp);
    -	}
    -
    -	return (error);
    +	return (dsl_dataset_user_release(holds, errlist));
     }
     
     /*
    @@ -5124,14 +5007,21 @@ static int
     zfs_ioc_space_written(zfs_cmd_t *zc)
     {
     	int error;
    +	dsl_pool_t *dp;
     	dsl_dataset_t *new, *old;
     
    -	error = dsl_dataset_hold(zc->zc_name, FTAG, &new);
    +	error = dsl_pool_hold(zc->zc_name, FTAG, &dp);
     	if (error != 0)
     		return (error);
    -	error = dsl_dataset_hold(zc->zc_value, FTAG, &old);
    +	error = dsl_dataset_hold(dp, zc->zc_name, FTAG, &new);
    +	if (error != 0) {
    +		dsl_pool_rele(dp, FTAG);
    +		return (error);
    +	}
    +	error = dsl_dataset_hold(dp, zc->zc_value, FTAG, &old);
     	if (error != 0) {
     		dsl_dataset_rele(new, FTAG);
    +		dsl_pool_rele(dp, FTAG);
     		return (error);
     	}
     
    @@ -5139,8 +5029,10 @@ zfs_ioc_space_written(zfs_cmd_t *zc)
     	    &zc->zc_objset_type, &zc->zc_perm_action);
     	dsl_dataset_rele(old, FTAG);
     	dsl_dataset_rele(new, FTAG);
    +	dsl_pool_rele(dp, FTAG);
     	return (error);
     }
    +
     /*
      * innvl: {
      *     "firstsnap" -> snapshot name
    @@ -5156,6 +5048,7 @@ static int
     zfs_ioc_space_snaps(const char *lastsnap, nvlist_t *innvl, nvlist_t *outnvl)
     {
     	int error;
    +	dsl_pool_t *dp;
     	dsl_dataset_t *new, *old;
     	char *firstsnap;
     	uint64_t used, comp, uncomp;
    @@ -5163,18 +5056,26 @@ zfs_ioc_space_snaps(const char *lastsnap, nvlist_t *innvl, nvlist_t *outnvl)
     	if (nvlist_lookup_string(innvl, "firstsnap", &firstsnap) != 0)
     		return (EINVAL);
     
    -	error = dsl_dataset_hold(lastsnap, FTAG, &new);
    +	error = dsl_pool_hold(lastsnap, FTAG, &dp);
     	if (error != 0)
     		return (error);
    -	error = dsl_dataset_hold(firstsnap, FTAG, &old);
    +
    +	error = dsl_dataset_hold(dp, lastsnap, FTAG, &new);
    +	if (error != 0) {
    +		dsl_pool_rele(dp, FTAG);
    +		return (error);
    +	}
    +	error = dsl_dataset_hold(dp, firstsnap, FTAG, &old);
     	if (error != 0) {
     		dsl_dataset_rele(new, FTAG);
    +		dsl_pool_rele(dp, FTAG);
     		return (error);
     	}
     
     	error = dsl_dataset_space_wouldfree(old, new, &used, &comp, &uncomp);
     	dsl_dataset_rele(old, FTAG);
     	dsl_dataset_rele(new, FTAG);
    +	dsl_pool_rele(dp, FTAG);
     	fnvlist_add_uint64(outnvl, "used", used);
     	fnvlist_add_uint64(outnvl, "compressed", comp);
     	fnvlist_add_uint64(outnvl, "uncompressed", uncomp);
    @@ -5193,47 +5094,27 @@ zfs_ioc_space_snaps(const char *lastsnap, nvlist_t *innvl, nvlist_t *outnvl)
     static int
     zfs_ioc_send_new(const char *snapname, nvlist_t *innvl, nvlist_t *outnvl)
     {
    -	objset_t *fromsnap = NULL;
    -	objset_t *tosnap;
     	int error;
     	offset_t off;
    -	char *fromname;
    +	char *fromname = NULL;
     	int fd;
     
     	error = nvlist_lookup_int32(innvl, "fd", &fd);
     	if (error != 0)
     		return (EINVAL);
     
    -	error = dmu_objset_hold(snapname, FTAG, &tosnap);
    -	if (error)
    -		return (error);
    -
    -	error = nvlist_lookup_string(innvl, "fromsnap", &fromname);
    -	if (error == 0) {
    -		error = dmu_objset_hold(fromname, FTAG, &fromsnap);
    -		if (error) {
    -			dmu_objset_rele(tosnap, FTAG);
    -			return (error);
    -		}
    -	}
    +	(void) nvlist_lookup_string(innvl, "fromsnap", &fromname);
     
     	file_t *fp = getf(fd);
    -	if (fp == NULL) {
    -		dmu_objset_rele(tosnap, FTAG);
    -		if (fromsnap != NULL)
    -			dmu_objset_rele(fromsnap, FTAG);
    +	if (fp == NULL)
     		return (EBADF);
    -	}
     
     	off = fp->f_offset;
    -	error = dmu_send(tosnap, fromsnap, fd, fp->f_vnode, &off);
    +	error = dmu_send(snapname, fromname, fd, fp->f_vnode, &off);
     
     	if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0)
     		fp->f_offset = off;
     	releasef(fd);
    -	if (fromsnap != NULL)
    -		dmu_objset_rele(fromsnap, FTAG);
    -	dmu_objset_rele(tosnap, FTAG);
     	return (error);
     }
     
    @@ -5252,21 +5133,29 @@ zfs_ioc_send_new(const char *snapname, nvlist_t *innvl, nvlist_t *outnvl)
     static int
     zfs_ioc_send_space(const char *snapname, nvlist_t *innvl, nvlist_t *outnvl)
     {
    -	objset_t *fromsnap = NULL;
    -	objset_t *tosnap;
    +	dsl_pool_t *dp;
    +	dsl_dataset_t *fromsnap = NULL;
    +	dsl_dataset_t *tosnap;
     	int error;
     	char *fromname;
     	uint64_t space;
     
    -	error = dmu_objset_hold(snapname, FTAG, &tosnap);
    -	if (error)
    +	error = dsl_pool_hold(snapname, FTAG, &dp);
    +	if (error != 0)
     		return (error);
     
    +	error = dsl_dataset_hold(dp, snapname, FTAG, &tosnap);
    +	if (error != 0) {
    +		dsl_pool_rele(dp, FTAG);
    +		return (error);
    +	}
    +
     	error = nvlist_lookup_string(innvl, "fromsnap", &fromname);
     	if (error == 0) {
    -		error = dmu_objset_hold(fromname, FTAG, &fromsnap);
    -		if (error) {
    -			dmu_objset_rele(tosnap, FTAG);
    +		error = dsl_dataset_hold(dp, fromname, FTAG, &fromsnap);
    +		if (error != 0) {
    +			dsl_dataset_rele(tosnap, FTAG);
    +			dsl_pool_rele(dp, FTAG);
     			return (error);
     		}
     	}
    @@ -5275,8 +5164,9 @@ zfs_ioc_send_space(const char *snapname, nvlist_t *innvl, nvlist_t *outnvl)
     	fnvlist_add_uint64(outnvl, "space", space);
     
     	if (fromsnap != NULL)
    -		dmu_objset_rele(fromsnap, FTAG);
    -	dmu_objset_rele(tosnap, FTAG);
    +		dsl_dataset_rele(fromsnap, FTAG);
    +	dsl_dataset_rele(tosnap, FTAG);
    +	dsl_pool_rele(dp, FTAG);
     	return (error);
     }
     
    @@ -5421,6 +5311,17 @@ zfs_ioctl_init(void)
     	    zfs_ioc_destroy_snaps, zfs_secpolicy_destroy_snaps, POOL_NAME,
     	    POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_TRUE, B_TRUE);
     
    +	zfs_ioctl_register("hold", ZFS_IOC_HOLD,
    +	    zfs_ioc_hold, zfs_secpolicy_hold, POOL_NAME,
    +	    POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_TRUE, B_TRUE);
    +	zfs_ioctl_register("release", ZFS_IOC_RELEASE,
    +	    zfs_ioc_release, zfs_secpolicy_release, POOL_NAME,
    +	    POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_TRUE, B_TRUE);
    +
    +	zfs_ioctl_register("get_holds", ZFS_IOC_GET_HOLDS,
    +	    zfs_ioc_get_holds, zfs_secpolicy_read, DATASET_NAME,
    +	    POOL_CHECK_SUSPENDED, B_FALSE, B_FALSE);
    +
     	/* IOCTLS that use the legacy function signature */
     
     	zfs_ioctl_register_legacy(ZFS_IOC_POOL_FREEZE, zfs_ioc_pool_freeze,
    @@ -5498,8 +5399,6 @@ zfs_ioctl_init(void)
     
     	zfs_ioctl_register_dataset_read(ZFS_IOC_SPACE_WRITTEN,
     	    zfs_ioc_space_written);
    -	zfs_ioctl_register_dataset_read(ZFS_IOC_GET_HOLDS,
    -	    zfs_ioc_get_holds);
     	zfs_ioctl_register_dataset_read(ZFS_IOC_OBJSET_RECVD_PROPS,
     	    zfs_ioc_objset_recvd_props);
     	zfs_ioctl_register_dataset_read(ZFS_IOC_NEXT_OBJ,
    @@ -5542,10 +5441,6 @@ zfs_ioctl_init(void)
     	    zfs_secpolicy_recv);
     	zfs_ioctl_register_dataset_modify(ZFS_IOC_PROMOTE, zfs_ioc_promote,
     	    zfs_secpolicy_promote);
    -	zfs_ioctl_register_dataset_modify(ZFS_IOC_HOLD, zfs_ioc_hold,
    -	    zfs_secpolicy_hold);
    -	zfs_ioctl_register_dataset_modify(ZFS_IOC_RELEASE, zfs_ioc_release,
    -	    zfs_secpolicy_release);
     	zfs_ioctl_register_dataset_modify(ZFS_IOC_INHERIT_PROP,
     	    zfs_ioc_inherit_prop, zfs_secpolicy_inherit_prop);
     	zfs_ioctl_register_dataset_modify(ZFS_IOC_SET_FSACL, zfs_ioc_set_fsacl,
    diff --git a/uts/common/fs/zfs/zfs_vfsops.c b/uts/common/fs/zfs/zfs_vfsops.c
    index 2a2501707b4..42486ea23c5 100644
    --- a/uts/common/fs/zfs/zfs_vfsops.c
    +++ b/uts/common/fs/zfs/zfs_vfsops.c
    @@ -513,27 +513,31 @@ zfs_register_callbacks(vfs_t *vfsp)
     	 * overboard...
     	 */
     	ds = dmu_objset_ds(os);
    -	error = dsl_prop_register(ds, "atime", atime_changed_cb, zfsvfs);
    +	dsl_pool_config_enter(dmu_objset_pool(os), FTAG);
    +	error = dsl_prop_register(ds,
    +	    zfs_prop_to_name(ZFS_PROP_ATIME), atime_changed_cb, zfsvfs);
     	error = error ? error : dsl_prop_register(ds,
    -	    "xattr", xattr_changed_cb, zfsvfs);
    +	    zfs_prop_to_name(ZFS_PROP_XATTR), xattr_changed_cb, zfsvfs);
     	error = error ? error : dsl_prop_register(ds,
    -	    "recordsize", blksz_changed_cb, zfsvfs);
    +	    zfs_prop_to_name(ZFS_PROP_RECORDSIZE), blksz_changed_cb, zfsvfs);
     	error = error ? error : dsl_prop_register(ds,
    -	    "readonly", readonly_changed_cb, zfsvfs);
    +	    zfs_prop_to_name(ZFS_PROP_READONLY), readonly_changed_cb, zfsvfs);
     	error = error ? error : dsl_prop_register(ds,
    -	    "devices", devices_changed_cb, zfsvfs);
    +	    zfs_prop_to_name(ZFS_PROP_DEVICES), devices_changed_cb, zfsvfs);
     	error = error ? error : dsl_prop_register(ds,
    -	    "setuid", setuid_changed_cb, zfsvfs);
    +	    zfs_prop_to_name(ZFS_PROP_SETUID), setuid_changed_cb, zfsvfs);
     	error = error ? error : dsl_prop_register(ds,
    -	    "exec", exec_changed_cb, zfsvfs);
    +	    zfs_prop_to_name(ZFS_PROP_EXEC), exec_changed_cb, zfsvfs);
     	error = error ? error : dsl_prop_register(ds,
    -	    "snapdir", snapdir_changed_cb, zfsvfs);
    +	    zfs_prop_to_name(ZFS_PROP_SNAPDIR), snapdir_changed_cb, zfsvfs);
     	error = error ? error : dsl_prop_register(ds,
    -	    "aclmode", acl_mode_changed_cb, zfsvfs);
    +	    zfs_prop_to_name(ZFS_PROP_ACLMODE), acl_mode_changed_cb, zfsvfs);
     	error = error ? error : dsl_prop_register(ds,
    -	    "aclinherit", acl_inherit_changed_cb, zfsvfs);
    +	    zfs_prop_to_name(ZFS_PROP_ACLINHERIT), acl_inherit_changed_cb,
    +	    zfsvfs);
     	error = error ? error : dsl_prop_register(ds,
    -	    "vscan", vscan_changed_cb, zfsvfs);
    +	    zfs_prop_to_name(ZFS_PROP_VSCAN), vscan_changed_cb, zfsvfs);
    +	dsl_pool_config_exit(dmu_objset_pool(os), FTAG);
     	if (error)
     		goto unregister;
     
    @@ -563,28 +567,35 @@ unregister:
     	 * registered, but this is OK; it will simply return ENOMSG,
     	 * which we will ignore.
     	 */
    -	(void) dsl_prop_unregister(ds, "atime", atime_changed_cb, zfsvfs);
    -	(void) dsl_prop_unregister(ds, "xattr", xattr_changed_cb, zfsvfs);
    -	(void) dsl_prop_unregister(ds, "recordsize", blksz_changed_cb, zfsvfs);
    -	(void) dsl_prop_unregister(ds, "readonly", readonly_changed_cb, zfsvfs);
    -	(void) dsl_prop_unregister(ds, "devices", devices_changed_cb, zfsvfs);
    -	(void) dsl_prop_unregister(ds, "setuid", setuid_changed_cb, zfsvfs);
    -	(void) dsl_prop_unregister(ds, "exec", exec_changed_cb, zfsvfs);
    -	(void) dsl_prop_unregister(ds, "snapdir", snapdir_changed_cb, zfsvfs);
    -	(void) dsl_prop_unregister(ds, "aclmode", acl_mode_changed_cb, zfsvfs);
    -	(void) dsl_prop_unregister(ds, "aclinherit", acl_inherit_changed_cb,
    -	    zfsvfs);
    -	(void) dsl_prop_unregister(ds, "vscan", vscan_changed_cb, zfsvfs);
    +	(void) dsl_prop_unregister(ds, zfs_prop_to_name(ZFS_PROP_ATIME),
    +	    atime_changed_cb, zfsvfs);
    +	(void) dsl_prop_unregister(ds, zfs_prop_to_name(ZFS_PROP_XATTR),
    +	    xattr_changed_cb, zfsvfs);
    +	(void) dsl_prop_unregister(ds, zfs_prop_to_name(ZFS_PROP_RECORDSIZE),
    +	    blksz_changed_cb, zfsvfs);
    +	(void) dsl_prop_unregister(ds, zfs_prop_to_name(ZFS_PROP_READONLY),
    +	    readonly_changed_cb, zfsvfs);
    +	(void) dsl_prop_unregister(ds, zfs_prop_to_name(ZFS_PROP_DEVICES),
    +	    devices_changed_cb, zfsvfs);
    +	(void) dsl_prop_unregister(ds, zfs_prop_to_name(ZFS_PROP_SETUID),
    +	    setuid_changed_cb, zfsvfs);
    +	(void) dsl_prop_unregister(ds, zfs_prop_to_name(ZFS_PROP_EXEC),
    +	    exec_changed_cb, zfsvfs);
    +	(void) dsl_prop_unregister(ds, zfs_prop_to_name(ZFS_PROP_SNAPDIR),
    +	    snapdir_changed_cb, zfsvfs);
    +	(void) dsl_prop_unregister(ds, zfs_prop_to_name(ZFS_PROP_ACLMODE),
    +	    acl_mode_changed_cb, zfsvfs);
    +	(void) dsl_prop_unregister(ds, zfs_prop_to_name(ZFS_PROP_ACLINHERIT),
    +	    acl_inherit_changed_cb, zfsvfs);
    +	(void) dsl_prop_unregister(ds, zfs_prop_to_name(ZFS_PROP_VSCAN),
    +	    vscan_changed_cb, zfsvfs);
     	return (error);
    -
     }
     
     static int
     zfs_space_delta_cb(dmu_object_type_t bonustype, void *data,
         uint64_t *userp, uint64_t *groupp)
     {
    -	int error = 0;
    -
     	/*
     	 * Is it a valid type of object to track?
     	 */
    @@ -641,7 +652,7 @@ zfs_space_delta_cb(dmu_object_type_t bonustype, void *data,
     			*groupp = BSWAP_64(*groupp);
     		}
     	}
    -	return (error);
    +	return (0);
     }
     
     static void
    @@ -993,7 +1004,7 @@ zfsvfs_create(const char *osname, zfsvfs_t **zfvp)
     	mutex_init(&zfsvfs->z_lock, NULL, MUTEX_DEFAULT, NULL);
     	list_create(&zfsvfs->z_all_znodes, sizeof (znode_t),
     	    offsetof(znode_t, z_link_node));
    -	rrw_init(&zfsvfs->z_teardown_lock);
    +	rrw_init(&zfsvfs->z_teardown_lock, B_FALSE);
     	rw_init(&zfsvfs->z_teardown_inactive_lock, NULL, RW_DEFAULT, NULL);
     	rw_init(&zfsvfs->z_fuid_lock, NULL, RW_DEFAULT, NULL);
     	for (i = 0; i != ZFS_OBJ_MTX_SZ; i++)
    @@ -1444,8 +1455,9 @@ zfs_mount_label_policy(vfs_t *vfsp, char *osname)
     		char *str = NULL;
     
     		if (l_to_str_internal(mnt_sl, &str) == 0 &&
    -		    dsl_prop_set(osname, zfs_prop_to_name(ZFS_PROP_MLSLABEL),
    -		    ZPROP_SRC_LOCAL, 1, strlen(str) + 1, str) == 0)
    +		    dsl_prop_set_string(osname,
    +		    zfs_prop_to_name(ZFS_PROP_MLSLABEL),
    +		    ZPROP_SRC_LOCAL, str) == 0)
     			retv = 0;
     		if (str != NULL)
     			kmem_free(str, strlen(str) + 1);
    @@ -1856,7 +1868,7 @@ zfsvfs_teardown(zfsvfs_t *zfsvfs, boolean_t unmounting)
     	if (dsl_dataset_is_dirty(dmu_objset_ds(zfsvfs->z_os)) &&
     	    !(zfsvfs->z_vfs->vfs_flag & VFS_RDONLY))
     		txg_wait_synced(dmu_objset_pool(zfsvfs->z_os), 0);
    -	(void) dmu_objset_evict_dbufs(zfsvfs->z_os);
    +	dmu_objset_evict_dbufs(zfsvfs->z_os);
     
     	return (0);
     }
    diff --git a/uts/common/fs/zfs/zil.c b/uts/common/fs/zfs/zil.c
    index 81d2bb5a975..e9616f8f65e 100644
    --- a/uts/common/fs/zfs/zil.c
    +++ b/uts/common/fs/zfs/zil.c
    @@ -235,7 +235,7 @@ zil_read_log_block(zilog_t *zilog, const blkptr_t *bp, blkptr_t *nbp, void *dst,
     			}
     		}
     
    -		VERIFY(arc_buf_remove_ref(abuf, &abuf) == 1);
    +		VERIFY(arc_buf_remove_ref(abuf, &abuf));
     	}
     
     	return (error);
    @@ -332,7 +332,7 @@ zil_parse(zilog_t *zilog, zil_parse_blk_func_t *parse_blk_func,
     			break;
     
     		error = zil_read_log_block(zilog, &blk, &next_blk, lrbuf, &end);
    -		if (error)
    +		if (error != 0)
     			break;
     
     		for (lrp = lrbuf; lrp < end; lrp += reclen) {
    @@ -467,7 +467,7 @@ zilog_dirty(zilog_t *zilog, uint64_t txg)
     	if (dsl_dataset_is_snapshot(ds))
     		panic("dirtying snapshot!");
     
    -	if (txg_list_add(&dp->dp_dirty_zilogs, zilog, txg) == 0) {
    +	if (txg_list_add(&dp->dp_dirty_zilogs, zilog, txg)) {
     		/* up the hold count until we can be written out */
     		dmu_buf_add_ref(ds->ds_dbuf, zilog);
     	}
    @@ -626,8 +626,8 @@ zil_claim(const char *osname, void *txarg)
     	objset_t *os;
     	int error;
     
    -	error = dmu_objset_hold(osname, FTAG, &os);
    -	if (error) {
    +	error = dmu_objset_own(osname, DMU_OST_ANY, B_FALSE, FTAG, &os);
    +	if (error != 0) {
     		cmn_err(CE_WARN, "can't open objset for %s", osname);
     		return (0);
     	}
    @@ -640,7 +640,7 @@ zil_claim(const char *osname, void *txarg)
     			zio_free_zil(zilog->zl_spa, first_txg, &zh->zh_log);
     		BP_ZERO(&zh->zh_log);
     		dsl_dataset_dirty(dmu_objset_ds(os), tx);
    -		dmu_objset_rele(os, FTAG);
    +		dmu_objset_disown(os, FTAG);
     		return (0);
     	}
     
    @@ -665,7 +665,7 @@ zil_claim(const char *osname, void *txarg)
     	}
     
     	ASSERT3U(first_txg, ==, (spa_last_synced_txg(zilog->zl_spa) + 1));
    -	dmu_objset_rele(os, FTAG);
    +	dmu_objset_disown(os, FTAG);
     	return (0);
     }
     
    @@ -685,7 +685,7 @@ zil_check_log_chain(const char *osname, void *tx)
     	ASSERT(tx == NULL);
     
     	error = dmu_objset_hold(osname, FTAG, &os);
    -	if (error) {
    +	if (error != 0) {
     		cmn_err(CE_WARN, "can't open objset for %s", osname);
     		return (0);
     	}
    @@ -973,7 +973,7 @@ zil_lwb_write_start(zilog_t *zilog, lwb_t *lwb)
     	/* pass the old blkptr in order to spread log blocks across devs */
     	error = zio_alloc_zil(spa, txg, bp, &lwb->lwb_blk, zil_blksz,
     	    USE_SLOG(zilog));
    -	if (!error) {
    +	if (error == 0) {
     		ASSERT3U(bp->blk_birth, ==, txg);
     		bp->blk_cksum = lwb->lwb_blk.blk_cksum;
     		bp->blk_cksum.zc_word[ZIL_ZC_SEQ]++;
    @@ -1084,7 +1084,7 @@ zil_lwb_commit(zilog_t *zilog, itx_t *itx, lwb_t *lwb)
     				txg_wait_synced(zilog->zl_dmu_pool, txg);
     				return (lwb);
     			}
    -			if (error) {
    +			if (error != 0) {
     				ASSERT(error == ENOENT || error == EEXIST ||
     				    error == EALREADY);
     				return (lwb);
    @@ -1708,6 +1708,9 @@ zil_free(zilog_t *zilog)
     {
     	zilog->zl_stop_sync = 1;
     
    +	ASSERT0(zilog->zl_suspend);
    +	ASSERT0(zilog->zl_suspending);
    +
     	ASSERT(list_is_empty(&zilog->zl_lwb_list));
     	list_destroy(&zilog->zl_lwb_list);
     
    @@ -1803,32 +1806,100 @@ zil_close(zilog_t *zilog)
     	mutex_exit(&zilog->zl_lock);
     }
     
    +static char *suspend_tag = "zil suspending";
    +
     /*
      * Suspend an intent log.  While in suspended mode, we still honor
      * synchronous semantics, but we rely on txg_wait_synced() to do it.
    - * We suspend the log briefly when taking a snapshot so that the snapshot
    - * contains all the data it's supposed to, and has an empty intent log.
    + * On old version pools, we suspend the log briefly when taking a
    + * snapshot so that it will have an empty intent log.
    + *
    + * Long holds are not really intended to be used the way we do here --
    + * held for such a short time.  A concurrent caller of dsl_dataset_long_held()
    + * could fail.  Therefore we take pains to only put a long hold if it is
    + * actually necessary.  Fortunately, it will only be necessary if the
    + * objset is currently mounted (or the ZVOL equivalent).  In that case it
    + * will already have a long hold, so we are not really making things any worse.
    + *
    + * Ideally, we would locate the existing long-holder (i.e. the zfsvfs_t or
    + * zvol_state_t), and use their mechanism to prevent their hold from being
    + * dropped (e.g. VFS_HOLD()).  However, that would be even more pain for
    + * very little gain.
    + *
    + * if cookiep == NULL, this does both the suspend & resume.
    + * Otherwise, it returns with the dataset "long held", and the cookie
    + * should be passed into zil_resume().
      */
     int
    -zil_suspend(zilog_t *zilog)
    +zil_suspend(const char *osname, void **cookiep)
     {
    -	const zil_header_t *zh = zilog->zl_header;
    +	objset_t *os;
    +	zilog_t *zilog;
    +	const zil_header_t *zh;
    +	int error;
    +
    +	error = dmu_objset_hold(osname, suspend_tag, &os);
    +	if (error != 0)
    +		return (error);
    +	zilog = dmu_objset_zil(os);
     
     	mutex_enter(&zilog->zl_lock);
    +	zh = zilog->zl_header;
    +
     	if (zh->zh_flags & ZIL_REPLAY_NEEDED) {		/* unplayed log */
     		mutex_exit(&zilog->zl_lock);
    +		dmu_objset_rele(os, suspend_tag);
     		return (EBUSY);
     	}
    -	if (zilog->zl_suspend++ != 0) {
    +
    +	/*
    +	 * Don't put a long hold in the cases where we can avoid it.  This
    +	 * is when there is no cookie so we are doing a suspend & resume
    +	 * (i.e. called from zil_vdev_offline()), and there's nothing to do
    +	 * for the suspend because it's already suspended, or there's no ZIL.
    +	 */
    +	if (cookiep == NULL && !zilog->zl_suspending &&
    +	    (zilog->zl_suspend > 0 || BP_IS_HOLE(&zh->zh_log))) {
    +		mutex_exit(&zilog->zl_lock);
    +		dmu_objset_rele(os, suspend_tag);
    +		return (0);
    +	}
    +
    +	dsl_dataset_long_hold(dmu_objset_ds(os), suspend_tag);
    +	dsl_pool_rele(dmu_objset_pool(os), suspend_tag);
    +
    +	zilog->zl_suspend++;
    +
    +	if (zilog->zl_suspend > 1) {
     		/*
    -		 * Someone else already began a suspend.
    +		 * Someone else is already suspending it.
     		 * Just wait for them to finish.
     		 */
    +
     		while (zilog->zl_suspending)
     			cv_wait(&zilog->zl_cv_suspend, &zilog->zl_lock);
     		mutex_exit(&zilog->zl_lock);
    +
    +		if (cookiep == NULL)
    +			zil_resume(os);
    +		else
    +			*cookiep = os;
     		return (0);
     	}
    +
    +	/*
    +	 * If there is no pointer to an on-disk block, this ZIL must not
    +	 * be active (e.g. filesystem not mounted), so there's nothing
    +	 * to clean up.
    +	 */
    +	if (BP_IS_HOLE(&zh->zh_log)) {
    +		ASSERT(cookiep != NULL); /* fast path already handled */
    +
    +		*cookiep = os;
    +		mutex_exit(&zilog->zl_lock);
    +		return (0);
    +	}
    +
     	zilog->zl_suspending = B_TRUE;
     	mutex_exit(&zilog->zl_lock);
     
    @@ -1841,16 +1912,25 @@ zil_suspend(zilog_t *zilog)
     	cv_broadcast(&zilog->zl_cv_suspend);
     	mutex_exit(&zilog->zl_lock);
     
    +	if (cookiep == NULL)
    +		zil_resume(os);
    +	else
    +		*cookiep = os;
     	return (0);
     }
     
     void
    -zil_resume(zilog_t *zilog)
    +zil_resume(void *cookie)
     {
    +	objset_t *os = cookie;
    +	zilog_t *zilog = dmu_objset_zil(os);
    +
     	mutex_enter(&zilog->zl_lock);
     	ASSERT(zilog->zl_suspend != 0);
     	zilog->zl_suspend--;
     	mutex_exit(&zilog->zl_lock);
    +	dsl_dataset_long_rele(dmu_objset_ds(os), suspend_tag);
    +	dsl_dataset_rele(dmu_objset_ds(os), suspend_tag);
     }
     
     typedef struct zil_replay_arg {
    @@ -1923,7 +2003,7 @@ zil_replay_log_record(zilog_t *zilog, lr_t *lr, void *zra, uint64_t claim_txg)
     	if (txtype == TX_WRITE && reclen == sizeof (lr_write_t)) {
     		error = zil_read_log_data(zilog, (lr_write_t *)lr,
     		    zr->zr_lr + reclen);
    -		if (error)
    +		if (error != 0)
     			return (zil_replay_error(zilog, lr, error));
     	}
     
    @@ -1944,7 +2024,7 @@ zil_replay_log_record(zilog_t *zilog, lr_t *lr, void *zra, uint64_t claim_txg)
     	 * is updated if we are in replay mode.
     	 */
     	error = zr->zr_replay[txtype](zr->zr_arg, zr->zr_lr, zr->zr_byteswap);
    -	if (error) {
    +	if (error != 0) {
     		/*
     		 * The DMU's dnode layer doesn't see removes until the txg
     		 * commits, so a subsequent claim can spuriously fail with
    @@ -1954,7 +2034,7 @@ zil_replay_log_record(zilog_t *zilog, lr_t *lr, void *zra, uint64_t claim_txg)
     		 */
     		txg_wait_synced(spa_get_dsl(zilog->zl_spa), 0);
     		error = zr->zr_replay[txtype](zr->zr_arg, zr->zr_lr, B_FALSE);
    -		if (error)
    +		if (error != 0)
     			return (zil_replay_error(zilog, lr, error));
     	}
     	return (0);
    @@ -2026,19 +2106,10 @@ zil_replaying(zilog_t *zilog, dmu_tx_t *tx)
     int
     zil_vdev_offline(const char *osname, void *arg)
     {
    -	objset_t *os;
    -	zilog_t *zilog;
     	int error;
     
    -	error = dmu_objset_hold(osname, FTAG, &os);
    -	if (error)
    -		return (error);
    -
    -	zilog = dmu_objset_zil(os);
    -	if (zil_suspend(zilog) != 0)
    -		error = EEXIST;
    -	else
    -		zil_resume(zilog);
    -	dmu_objset_rele(os, FTAG);
    -	return (error);
    +	error = zil_suspend(osname, NULL);
    +	if (error != 0)
    +		return (EEXIST);
    +	return (0);
     }
    diff --git a/uts/common/fs/zfs/zio.c b/uts/common/fs/zfs/zio.c
    index 432a992b26f..7940e201ef8 100644
    --- a/uts/common/fs/zfs/zio.c
    +++ b/uts/common/fs/zfs/zio.c
    @@ -697,6 +697,7 @@ zio_write_override(zio_t *zio, blkptr_t *bp, int copies, boolean_t nopwrite)
     void
     zio_free(spa_t *spa, uint64_t txg, const blkptr_t *bp)
     {
    +	metaslab_check_free(spa, bp);
     	bplist_append(&spa->spa_free_bplist[txg & TXG_MASK], bp);
     }
     
    @@ -713,6 +714,8 @@ zio_free_sync(zio_t *pio, spa_t *spa, uint64_t txg, const blkptr_t *bp,
     	ASSERT(spa_syncing_txg(spa) == txg);
     	ASSERT(spa_sync_pass(spa) < zfs_sync_pass_deferred_free);
     
    +	metaslab_check_free(spa, bp);
    +
     	zio = zio_create(pio, spa, txg, bp, NULL, BP_GET_PSIZE(bp),
     	    NULL, NULL, ZIO_TYPE_FREE, ZIO_PRIORITY_FREE, flags,
     	    NULL, 0, NULL, ZIO_STAGE_OPEN, ZIO_FREE_PIPELINE);
    @@ -2010,7 +2013,7 @@ zio_ddt_collision(zio_t *zio, ddt_t *ddt, ddt_entry_t *dde)
     				    bcmp(abuf->b_data, zio->io_orig_data,
     				    zio->io_orig_size) != 0)
     					error = EEXIST;
    -				VERIFY(arc_buf_remove_ref(abuf, &abuf) == 1);
    +				VERIFY(arc_buf_remove_ref(abuf, &abuf));
     			}
     
     			ddt_enter(ddt);
    @@ -2600,8 +2603,9 @@ zio_vdev_io_assess(zio_t *zio)
     	 * set vdev_cant_write so that we stop trying to allocate from it.
     	 */
     	if (zio->io_error == ENXIO && zio->io_type == ZIO_TYPE_WRITE &&
    -	    vd != NULL && !vd->vdev_ops->vdev_op_leaf)
    +	    vd != NULL && !vd->vdev_ops->vdev_op_leaf) {
     		vd->vdev_cant_write = B_TRUE;
    +	}
     
     	if (zio->io_error)
     		zio->io_pipeline = ZIO_INTERLOCK_PIPELINE;
    diff --git a/uts/common/fs/zfs/zvol.c b/uts/common/fs/zfs/zvol.c
    index b413f5ed8b0..5911fd3d2d0 100644
    --- a/uts/common/fs/zfs/zvol.c
    +++ b/uts/common/fs/zfs/zvol.c
    @@ -653,7 +653,7 @@ zvol_last_close(zvol_state_t *zv)
     	if (dsl_dataset_is_dirty(dmu_objset_ds(zv->zv_objset)) &&
     	    !(zv->zv_flags & ZVOL_RDONLY))
     		txg_wait_synced(dmu_objset_pool(zv->zv_objset), 0);
    -	(void) dmu_objset_evict_dbufs(zv->zv_objset);
    +	dmu_objset_evict_dbufs(zv->zv_objset);
     
     	dmu_objset_disown(zv->zv_objset, zvol_tag);
     	zv->zv_objset = NULL;
    @@ -698,7 +698,7 @@ zvol_prealloc(zvol_state_t *zv)
     	return (0);
     }
     
    -int
    +static int
     zvol_update_volsize(objset_t *os, uint64_t volsize)
     {
     	dmu_tx_t *tx;
    @@ -749,13 +749,12 @@ zvol_remove_minors(const char *name)
     }
     
     static int
    -zvol_set_volsize_impl(objset_t *os, zvol_state_t *zv, uint64_t volsize)
    +zvol_update_live_volsize(zvol_state_t *zv, uint64_t volsize)
     {
     	uint64_t old_volsize = 0ULL;
    -	int error;
    +	int error = 0;
     
     	ASSERT(MUTEX_HELD(&zfsdev_state_lock));
    -	error = zvol_update_volsize(os, volsize);
     
     	/*
     	 * Reinitialize the dump area to the new size. If we
    @@ -764,27 +763,25 @@ zvol_set_volsize_impl(objset_t *os, zvol_state_t *zv, uint64_t volsize)
     	 * to calling dumpvp_resize() to ensure that the devices'
     	 * size(9P) is not visible by the dump subsystem.
     	 */
    -	if (zv && error == 0) {
    -		old_volsize = zv->zv_volsize;
    -		zvol_size_changed(zv, volsize);
    +	old_volsize = zv->zv_volsize;
    +	zvol_size_changed(zv, volsize);
     
    -		if (zv->zv_flags & ZVOL_DUMPIFIED) {
    -			if ((error = zvol_dumpify(zv)) != 0 ||
    -			    (error = dumpvp_resize()) != 0) {
    -				int dumpify_error;
    +	if (zv->zv_flags & ZVOL_DUMPIFIED) {
    +		if ((error = zvol_dumpify(zv)) != 0 ||
    +		    (error = dumpvp_resize()) != 0) {
    +			int dumpify_error;
     
    -				(void) zvol_update_volsize(os, old_volsize);
    -				zvol_size_changed(zv, old_volsize);
    -				dumpify_error = zvol_dumpify(zv);
    -				error = dumpify_error ? dumpify_error : error;
    -			}
    +			(void) zvol_update_volsize(zv->zv_objset, old_volsize);
    +			zvol_size_changed(zv, old_volsize);
    +			dumpify_error = zvol_dumpify(zv);
    +			error = dumpify_error ? dumpify_error : error;
     		}
     	}
     
     	/*
     	 * Generate a LUN expansion event.
     	 */
    -	if (zv && error == 0) {
    +	if (error == 0) {
     		sysevent_id_t eid;
     		nvlist_t *attr;
     		char *physpath = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
    @@ -812,29 +809,45 @@ zvol_set_volsize(const char *name, uint64_t volsize)
     	int error;
     	dmu_object_info_t doi;
     	uint64_t readonly;
    +	boolean_t owned = B_FALSE;
    +
    +	error = dsl_prop_get_integer(name,
    +	    zfs_prop_to_name(ZFS_PROP_READONLY), &readonly, NULL);
    +	if (error != 0)
    +		return (error);
    +	if (readonly)
    +		return (EROFS);
     
     	mutex_enter(&zfsdev_state_lock);
     	zv = zvol_minor_lookup(name);
    -	if ((error = dmu_objset_hold(name, FTAG, &os)) != 0) {
    -		mutex_exit(&zfsdev_state_lock);
    -		return (error);
    +
    +	if (zv == NULL || zv->zv_objset == NULL) {
    +		if ((error = dmu_objset_own(name, DMU_OST_ZVOL, B_FALSE,
    +		    FTAG, &os)) != 0) {
    +			mutex_exit(&zfsdev_state_lock);
    +			return (error);
    +		}
    +		owned = B_TRUE;
    +		if (zv != NULL)
    +			zv->zv_objset = os;
    +	} else {
    +		os = zv->zv_objset;
     	}
     
     	if ((error = dmu_object_info(os, ZVOL_OBJ, &doi)) != 0 ||
    -	    (error = zvol_check_volsize(volsize,
    -	    doi.doi_data_block_size)) != 0)
    +	    (error = zvol_check_volsize(volsize, doi.doi_data_block_size)) != 0)
     		goto out;
     
    -	VERIFY3U(dsl_prop_get_integer(name,
    -	    zfs_prop_to_name(ZFS_PROP_READONLY), &readonly, NULL), ==, 0);
    -	if (readonly) {
    -		error = EROFS;
    -		goto out;
    -	}
    +	error = zvol_update_volsize(os, volsize);
     
    -	error = zvol_set_volsize_impl(os, zv, volsize);
    +	if (error == 0 && zv != NULL)
    +		error = zvol_update_live_volsize(zv, volsize);
     out:
    -	dmu_objset_rele(os, FTAG);
    +	if (owned) {
    +		dmu_objset_disown(os, FTAG);
    +		if (zv != NULL)
    +			zv->zv_objset = NULL;
    +	}
     	mutex_exit(&zfsdev_state_lock);
     	return (error);
     }
    @@ -1155,6 +1168,9 @@ zvol_dumpio(zvol_state_t *zv, void *addr, uint64_t offset, uint64_t size,
     		ze = list_next(&zv->zv_extents, ze);
     	}
     
    +	if (ze == NULL)
    +		return (EINVAL);
    +
     	if (!ddi_in_panic())
     		spa_config_enter(spa, SCL_STATE, FTAG, RW_READER);
     
    @@ -1308,6 +1324,9 @@ zvol_dump(dev_t dev, caddr_t addr, daddr_t blkno, int nblocks)
     	if (zv == NULL)
     		return (ENXIO);
     
    +	if ((zv->zv_flags & ZVOL_DUMPIFIED) == 0)
    +		return (EINVAL);
    +
     	boff = ldbtob(blkno);
     	resid = ldbtob(nblocks);
     
    diff --git a/uts/common/sys/nvpair.h b/uts/common/sys/nvpair.h
    index ad25effc299..e4d637b0073 100644
    --- a/uts/common/sys/nvpair.h
    +++ b/uts/common/sys/nvpair.h
    @@ -284,6 +284,7 @@ void fnvlist_pack_free(char *, size_t);
     nvlist_t *fnvlist_unpack(char *, size_t);
     nvlist_t *fnvlist_dup(nvlist_t *);
     void fnvlist_merge(nvlist_t *, nvlist_t *);
    +size_t fnvlist_num_pairs(nvlist_t *);
     
     void fnvlist_add_boolean(nvlist_t *, const char *);
     void fnvlist_add_boolean_value(nvlist_t *, const char *, boolean_t);
    
    From f4d0191b225727a871d5195bbb887efc50c86386 Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Fri, 1 Mar 2013 21:57:02 +0000
    Subject: [PATCH 0505/1476] Reduce lock scope a little.
    
    ---
     sys/kern/vfs_syscalls.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
    index bbda70d53be..bd44a3a180e 100644
    --- a/sys/kern/vfs_syscalls.c
    +++ b/sys/kern/vfs_syscalls.c
    @@ -2633,9 +2633,9 @@ setfflags(td, vp, flags)
     
     	if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
     		return (error);
    -	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
     	VATTR_NULL(&vattr);
     	vattr.va_flags = flags;
    +	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
     #ifdef MAC
     	error = mac_vnode_check_setflags(td->td_ucred, vp, vattr.va_flags);
     	if (error == 0)
    
    From 71ac38e8968b8b9e1980f05976836f33d4e0404f Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Fri, 1 Mar 2013 21:58:56 +0000
    Subject: [PATCH 0506/1476] Remove unnecessary variables.
    
    ---
     sys/kern/vfs_vnops.c | 8 ++------
     1 file changed, 2 insertions(+), 6 deletions(-)
    
    diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
    index 32c09781a1c..96ce9e2a73a 100644
    --- a/sys/kern/vfs_vnops.c
    +++ b/sys/kern/vfs_vnops.c
    @@ -1860,7 +1860,6 @@ vn_chmod(struct file *fp, mode_t mode, struct ucred *active_cred,
         struct thread *td)
     {
     	struct vnode *vp;
    -	int error;
     
     	vp = fp->f_vnode;
     #ifdef AUDIT
    @@ -1868,8 +1867,7 @@ vn_chmod(struct file *fp, mode_t mode, struct ucred *active_cred,
     	AUDIT_ARG_VNODE1(vp);
     	VOP_UNLOCK(vp, 0);
     #endif
    -	error = setfmode(td, active_cred, vp, mode);
    -	return (error);
    +	return (setfmode(td, active_cred, vp, mode));
     }
     
     int
    @@ -1877,7 +1875,6 @@ vn_chown(struct file *fp, uid_t uid, gid_t gid, struct ucred *active_cred,
         struct thread *td)
     {
     	struct vnode *vp;
    -	int error;
     
     	vp = fp->f_vnode;
     #ifdef AUDIT
    @@ -1885,8 +1882,7 @@ vn_chown(struct file *fp, uid_t uid, gid_t gid, struct ucred *active_cred,
     	AUDIT_ARG_VNODE1(vp);
     	VOP_UNLOCK(vp, 0);
     #endif
    -	error = setfown(td, active_cred, vp, uid, gid);
    -	return (error);
    +	return (setfown(td, active_cred, vp, uid, gid));
     }
     
     void
    
    From 5f61931668e0826d885e501456e11dae34c6732c Mon Sep 17 00:00:00 2001
    From: Andrew Turner 
    Date: Fri, 1 Mar 2013 21:59:23 +0000
    Subject: [PATCH 0507/1476] Increase the maximum text size on ARM to 64MiB.
     Without this clang would be sent a SIGABRT when it is loaded as it is too
     large. This is the smallest power of two MiB value that allows us to execute
     clang.
    
    While here wrap it in an #ifndef to be consistent with the other
    architectures.
    
    Submitted by:	Daisuke Aoyama 
    ---
     sys/arm/include/vmparam.h | 4 +++-
     1 file changed, 3 insertions(+), 1 deletion(-)
    
    diff --git a/sys/arm/include/vmparam.h b/sys/arm/include/vmparam.h
    index 53c40d203f8..aec94f82325 100644
    --- a/sys/arm/include/vmparam.h
    +++ b/sys/arm/include/vmparam.h
    @@ -153,7 +153,9 @@
         VM_MIN_KERNEL_ADDRESS + 1) * 2 / 5)
     #endif
     
    -#define MAXTSIZ 	(16*1024*1024)
    +#ifndef MAXTSIZ
    +#define MAXTSIZ 	(64*1024*1024)
    +#endif
     #ifndef DFLDSIZ
     #define DFLDSIZ         (128*1024*1024)
     #endif
    
    From f9379dc4118730b9fc82afb5ae62de6b0fd6dd3b Mon Sep 17 00:00:00 2001
    From: John Baldwin 
    Date: Fri, 1 Mar 2013 22:03:31 +0000
    Subject: [PATCH 0508/1476] Replace the TDP_NOSLEEPING flag with a counter so
     that the THREAD_NO_SLEEPING() and THREAD_SLEEPING_OK() macros can nest.
    
    Reviewed by:	attilio
    ---
     sys/dev/mps/mps.c          |  8 ++++----
     sys/kern/subr_sleepqueue.c |  4 ++--
     sys/kern/subr_trap.c       |  2 +-
     sys/sys/proc.h             | 15 ++++-----------
     sys/sys/rmlock.h           |  2 +-
     5 files changed, 12 insertions(+), 19 deletions(-)
    
    diff --git a/sys/dev/mps/mps.c b/sys/dev/mps/mps.c
    index 7a3e4f7637d..5e41b0ab218 100644
    --- a/sys/dev/mps/mps.c
    +++ b/sys/dev/mps/mps.c
    @@ -136,8 +136,8 @@ mps_diag_reset(struct mps_softc *sc,int sleep_flag)
     
     	/*Force NO_SLEEP for threads prohibited to sleep
      	* e.a Thread from interrupt handler are prohibited to sleep.
    - 	*/	
    -	if(curthread->td_pflags & TDP_NOSLEEPING)
    + 	*/
    +	if (curthread->td_no_sleeping != 0)
     		sleep_flag = NO_SLEEP;
      
     	/* Push the magic sequence */
    @@ -469,8 +469,8 @@ mps_request_sync(struct mps_softc *sc, void *req, MPI2_DEFAULT_REPLY *reply,
     	uint16_t *data16;
     	int i, count, ioc_sz, residual;
     	int sleep_flags = CAN_SLEEP;
    -	
    -	if(curthread->td_pflags & TDP_NOSLEEPING)
    +
    +	if (curthread->td_no_sleeping != 0)
     		sleep_flags = NO_SLEEP;
     
     	/* Step 1 */
    diff --git a/sys/kern/subr_sleepqueue.c b/sys/kern/subr_sleepqueue.c
    index b6bd8fcc884..f1875446ab8 100644
    --- a/sys/kern/subr_sleepqueue.c
    +++ b/sys/kern/subr_sleepqueue.c
    @@ -296,8 +296,8 @@ sleepq_add(void *wchan, struct lock_object *lock, const char *wmesg, int flags,
     	MPASS((queue >= 0) && (queue < NR_SLEEPQS));
     
     	/* If this thread is not allowed to sleep, die a horrible death. */
    -	KASSERT(!(td->td_pflags & TDP_NOSLEEPING),
    -	    ("%s: td %p to sleep on wchan %p with TDP_NOSLEEPING on",
    +	KASSERT(td->td_no_sleeping == 0,
    +	    ("%s: td %p to sleep on wchan %p with sleeping prohibited",
     	    __func__, td, wchan));
     
     	/* Look up the sleep queue associated with the wait channel 'wchan'. */
    diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c
    index bd06f201d11..1f24e8848cc 100644
    --- a/sys/kern/subr_trap.c
    +++ b/sys/kern/subr_trap.c
    @@ -158,7 +158,7 @@ userret(struct thread *td, struct trapframe *frame)
     	    ("userret: Returning with %d locks held", td->td_locks));
     	KASSERT((td->td_pflags & TDP_NOFAULTING) == 0,
     	    ("userret: Returning with pagefaults disabled"));
    -	KASSERT((td->td_pflags & TDP_NOSLEEPING) == 0,
    +	KASSERT(td->td_no_sleeping == 0,
     	    ("userret: Returning with sleep disabled"));
     	KASSERT(td->td_pinned == 0 || (td->td_pflags & TDP_CALLCHAIN) != 0,
     	    ("userret: Returning with with pinned thread"));
    diff --git a/sys/sys/proc.h b/sys/sys/proc.h
    index 46f5820e745..f6cf2e4d665 100644
    --- a/sys/sys/proc.h
    +++ b/sys/sys/proc.h
    @@ -273,6 +273,7 @@ struct thread {
     	struct vm_map_entry *td_map_def_user; /* (k) Deferred entries. */
     	pid_t		td_dbg_forked;	/* (c) Child pid for debugger. */
     	u_int		td_vp_reserv;	/* (k) Count of reserved vnodes. */
    +	int		td_no_sleeping;	/* (k) Sleeping disabled count. */
     #define	td_endzero td_sigmask
     
     /* Copied during fork1() or create_thread(). */
    @@ -404,7 +405,7 @@ do {									\
     #define	TDP_ALTSTACK	0x00000020 /* Have alternate signal stack. */
     #define	TDP_DEADLKTREAT	0x00000040 /* Lock aquisition - deadlock treatment. */
     #define	TDP_NOFAULTING	0x00000080 /* Do not handle page faults. */
    -#define	TDP_NOSLEEPING	0x00000100 /* Thread is not allowed to sleep on a sq. */
    +#define	TDP_UNUSED9	0x00000100 /* --available-- */
     #define	TDP_OWEUPC	0x00000200 /* Call addupc() at next AST. */
     #define	TDP_ITHREAD	0x00000400 /* Thread is an interrupt thread. */
     #define	TDP_SYNCIO	0x00000800 /* Local override, disable async i/o. */
    @@ -790,17 +791,9 @@ extern pid_t pid_max;
     #define	thread_safetoswapout(td)	((td)->td_flags & TDF_CANSWAP)
     
     /* Control whether or not it is safe for curthread to sleep. */
    -#define	THREAD_NO_SLEEPING() do {					\
    -	KASSERT(!(curthread->td_pflags & TDP_NOSLEEPING),		\
    -	    ("nested no sleeping"));					\
    -	curthread->td_pflags |= TDP_NOSLEEPING;				\
    -} while (0)
    +#define	THREAD_NO_SLEEPING()		((curthread)->td_no_sleeping++)
     
    -#define	THREAD_SLEEPING_OK() do {					\
    -	KASSERT((curthread->td_pflags & TDP_NOSLEEPING),		\
    -	    ("nested sleeping ok"));					\
    -	curthread->td_pflags &= ~TDP_NOSLEEPING;			\
    -} while (0)
    +#define	THREAD_SLEEPING_OK()		((curthread)->td_no_sleeping--)
     
     #define	PIDHASH(pid)	(&pidhashtbl[(pid) & pidhash])
     extern LIST_HEAD(pidhashhead, proc) *pidhashtbl;
    diff --git a/sys/sys/rmlock.h b/sys/sys/rmlock.h
    index 0ae20996427..5a0fa8af393 100644
    --- a/sys/sys/rmlock.h
    +++ b/sys/sys/rmlock.h
    @@ -40,7 +40,7 @@
     #ifdef _KERNEL
     
     /*
    - * Flags passed to rm_init(9).
    + * Flags passed to rm_init_flags(9).
      */
     #define	RM_NOWITNESS	0x00000001
     #define	RM_RECURSE	0x00000002
    
    From 9e2585bfed8f600050203e7277d4c6e72d073d8d Mon Sep 17 00:00:00 2001
    From: Marius Strobl 
    Date: Fri, 1 Mar 2013 22:05:20 +0000
    Subject: [PATCH 0509/1476] Initialize count in order to appease clang.
    
    Submitted by:	delphij
    ---
     sys/dev/bce/if_bce.c | 1 +
     1 file changed, 1 insertion(+)
    
    diff --git a/sys/dev/bce/if_bce.c b/sys/dev/bce/if_bce.c
    index 8f6bc486d43..032ca5fadb1 100644
    --- a/sys/dev/bce/if_bce.c
    +++ b/sys/dev/bce/if_bce.c
    @@ -1076,6 +1076,7 @@ bce_attach(device_t dev)
     	bce_probe_pci_caps(dev, sc);
     
     	rid = 1;
    +	count = 0;
     #if 0
     	/* Try allocating MSI-X interrupts. */
     	if ((sc->bce_cap_flags & BCE_MSIX_CAPABLE_FLAG) &&
    
    From 20132a22383f48c3134cde493d36bebf0c8b464c Mon Sep 17 00:00:00 2001
    From: Marius Strobl 
    Date: Fri, 1 Mar 2013 22:09:08 +0000
    Subject: [PATCH 0510/1476] Initialize count in order to appease clang.
    
    Submitted by:	delphij
    ---
     sys/dev/aac/aac_pci.c | 1 +
     1 file changed, 1 insertion(+)
    
    diff --git a/sys/dev/aac/aac_pci.c b/sys/dev/aac/aac_pci.c
    index 87ada1c1446..f768c8b2fd6 100644
    --- a/sys/dev/aac/aac_pci.c
    +++ b/sys/dev/aac/aac_pci.c
    @@ -394,6 +394,7 @@ aac_pci_attach(device_t dev)
     	 * Allocate the interrupt.
     	 */
     	rid = 0;
    +	count = 0;
     	if (aac_enable_msi != 0 && pci_find_cap(dev, PCIY_MSI, ®) == 0) {
     		count = pci_msi_count(dev);
     		if (count > 1)
    
    From 0e47e251a9f1c024cacce8f245384834059e542f Mon Sep 17 00:00:00 2001
    From: Xin LI 
    Date: Fri, 1 Mar 2013 23:18:20 +0000
    Subject: [PATCH 0511/1476] Fix a typo in mfi_stp_cmd() that would give wrong
     assignment.
    
    Submitted by:	Sascha Wildner 
    Obtained from:	DragonFly rev 0dc98fff2206d7bb78ce5e07ac34d6954e4bd96a
    MFC after:	3 days
    ---
     sys/dev/mfi/mfi.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/sys/dev/mfi/mfi.c b/sys/dev/mfi/mfi.c
    index e2401f6ee51..cf2d5053620 100644
    --- a/sys/dev/mfi/mfi.c
    +++ b/sys/dev/mfi/mfi.c
    @@ -2997,7 +2997,7 @@ mfi_stp_cmd(struct mfi_softc *sc, struct mfi_command *cm,caddr_t arg)
     			cm->cm_frame->stp.sgl.sg64[i].len =
     			    ioc->mfi_sgl[i].iov_len;
     		} else {
    -			cm->cm_frame->stp.sgl.sg32[i].len =
    +			cm->cm_frame->stp.sgl.sg32[i].addr =
     			    kern_sge[i].phys_addr;
     			cm->cm_frame->stp.sgl.sg32[i].len =
     			    ioc->mfi_sgl[i].iov_len;
    
    From 69136e792a724e44dbbcde16681ca590f76360ef Mon Sep 17 00:00:00 2001
    From: Xin LI 
    Date: Fri, 1 Mar 2013 23:21:18 +0000
    Subject: [PATCH 0512/1476] Fix wrong assignment.
    
    Submitted by:	Sascha Wildner 
    Obtained from:	DragonFly rev 9568dd07a22a136e380e6c19a8ea188eb92976d5
    MFC after:	2 weeks
    ---
     sys/compat/ndis/kern_ndis.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/sys/compat/ndis/kern_ndis.c b/sys/compat/ndis/kern_ndis.c
    index 23abaf130f2..e094997789d 100644
    --- a/sys/compat/ndis/kern_ndis.c
    +++ b/sys/compat/ndis/kern_ndis.c
    @@ -566,7 +566,7 @@ ndis_convert_res(arg)
     		return (ENOMEM);
     
     	rl->cprl_version = 5;
    -	rl->cprl_version = 1;
    +	rl->cprl_revision = 1;
     	rl->cprl_count = sc->ndis_rescnt;
     	prd = rl->cprl_partial_descs;
     
    
    From d0ebccde132655114ac9f6f0caa06d29d5ea20c9 Mon Sep 17 00:00:00 2001
    From: Xin LI 
    Date: Fri, 1 Mar 2013 23:26:13 +0000
    Subject: [PATCH 0513/1476] Fix assignment of maximum bounadary.
    
    Submitted by:	Sascha Wildner 
    Obtained from:	DragonFly rev fd39c81ba220f7ad6e4dc9b30d45e828cf58a1ad
    MFC after:	2 weeks
    ---
     lib/libc/regex/regcomp.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/lib/libc/regex/regcomp.c b/lib/libc/regex/regcomp.c
    index 68ffa66a1df..f3a41e90fb7 100644
    --- a/lib/libc/regex/regcomp.c
    +++ b/lib/libc/regex/regcomp.c
    @@ -1212,7 +1212,7 @@ CHaddrange(struct parse *p, cset *cs, wint_t min, wint_t max)
     	}
     	cs->ranges = newranges;
     	cs->ranges[cs->nranges].min = min;
    -	cs->ranges[cs->nranges].min = max;
    +	cs->ranges[cs->nranges].max = max;
     	cs->nranges++;
     }
     
    
    From d6f122f4fba359f6b54eebde65a98ac770f0c205 Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Sat, 2 Mar 2013 00:11:27 +0000
    Subject: [PATCH 0514/1476] Provide cap_sandboxed(3) function, which is a
     wrapper around cap_getmode(2) system call, which has a nice property - it
     never fails, so it is a bit easier to use. If there is no support for
     capability mode in the kernel the function will return false (not in a
     sandbox). If the kernel is compiled with the support for capability mode, the
     function will return true or false depending if the calling process is in the
     capability mode sandbox or not respectively.
    
    Sponsored by:	The FreeBSD Foundation
    ---
     lib/libc/gen/Makefile.inc    |  2 ++
     lib/libc/gen/cap_sandboxed.3 | 70 ++++++++++++++++++++++++++++++++++++
     lib/libc/gen/cap_sandboxed.c | 50 ++++++++++++++++++++++++++
     lib/libc/sys/Symbol.map      |  1 +
     lib/libc/sys/cap_enter.2     |  1 +
     5 files changed, 124 insertions(+)
     create mode 100644 lib/libc/gen/cap_sandboxed.3
     create mode 100644 lib/libc/gen/cap_sandboxed.c
    
    diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc
    index 711cbff9a7b..89689a03636 100644
    --- a/lib/libc/gen/Makefile.inc
    +++ b/lib/libc/gen/Makefile.inc
    @@ -16,6 +16,7 @@ SRCS+=	__getosreldate.c \
     	assert.c \
     	auxv.c \
     	basename.c \
    +	cap_sandboxed.c \
     	check_utility_compat.c \
     	clock.c \
     	clock_getcpuclockid.c \
    @@ -168,6 +169,7 @@ SYM_MAPS+=${.CURDIR}/gen/Symbol.map
     MAN+=	alarm.3 \
     	arc4random.3 \
     	basename.3 \
    +	cap_sandboxed.3 \
     	check_utility_compat.3 \
     	clock.3 \
     	clock_getcpuclockid.3 \
    diff --git a/lib/libc/gen/cap_sandboxed.3 b/lib/libc/gen/cap_sandboxed.3
    new file mode 100644
    index 00000000000..067d6d2d676
    --- /dev/null
    +++ b/lib/libc/gen/cap_sandboxed.3
    @@ -0,0 +1,70 @@
    +.\" Copyright (c) 2012 The FreeBSD Foundation
    +.\" All rights reserved.
    +.\"
    +.\" This documentation was written by Pawel Jakub Dawidek under sponsorship
    +.\" from the FreeBSD Foundation.
    +.\"
    +.\" Redistribution and use in source and binary forms, with or without
    +.\" modification, are permitted provided that the following conditions
    +.\" are met:
    +.\" 1. Redistributions of source code must retain the above copyright
    +.\"    notice, this list of conditions and the following disclaimer.
    +.\" 2. Redistributions in binary form must reproduce the above copyright
    +.\"    notice, this list of conditions and the following disclaimer in the
    +.\"    documentation and/or other materials provided with the distribution.
    +.\"
    +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
    +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    +.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
    +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    +.\" SUCH DAMAGE.
    +.\"
    +.\" $FreeBSD$
    +.\"
    +.Dd September 18, 2012
    +.Dt CAP_SANDBOXED 3
    +.Os
    +.Sh NAME
    +.Nm cap_sandboxed
    +.Nd Check if in a capability mode sandbox
    +.Sh LIBRARY
    +.Lb libc
    +.Sh SYNOPSIS
    +.In sys/capability.h
    +.In stdbool.h
    +.Ft bool
    +.Fn cap_sandboxed "void"
    +.Sh DESCRIPTION
    +.Fn cap_sandboxed
    +returns
    +.Va true
    +if the process is in a capability mode sandbox or
    +.Va false
    +if it is not.
    +This function is a more handy alternative to the
    +.Xr cap_getmode 2
    +system call as it always succeeds, so there is no need for error checking.
    +If the support for capability mode is not compiled into the kernel,
    +.Fn cap_sandboxed
    +will always return
    +.Va false .
    +.Sh RETURN VALUES
    +Function
    +.Fn cap_sandboxed
    +is always successful and will return either
    +.Va true
    +or
    +.Va false .
    +.Sh SEE ALSO
    +.Xr cap_enter 2 ,
    +.Xr capsicum 4
    +.Sh AUTHORS
    +This function was implemented and manual page was written by
    +.An Pawel Jakub Dawidek Aq pawel@dawidek.net
    +under sponsorship of the FreeBSD Foundation.
    diff --git a/lib/libc/gen/cap_sandboxed.c b/lib/libc/gen/cap_sandboxed.c
    new file mode 100644
    index 00000000000..baa9b3f7886
    --- /dev/null
    +++ b/lib/libc/gen/cap_sandboxed.c
    @@ -0,0 +1,50 @@
    +/*-
    + * Copyright (c) 2012 The FreeBSD Foundation
    + * All rights reserved.
    + *
    + * This software was developed by Pawel Jakub Dawidek under sponsorship from
    + * the FreeBSD Foundation.
    + *
    + * Redistribution and use in source and binary forms, with or without
    + * modification, are permitted provided that the following conditions
    + * are met:
    + * 1. Redistributions of source code must retain the above copyright
    + *    notice, this list of conditions and the following disclaimer.
    + * 2. Redistributions in binary form must reproduce the above copyright
    + *    notice, this list of conditions and the following disclaimer in the
    + *    documentation and/or other materials provided with the distribution.
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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 
    +__FBSDID("$FreeBSD$");
    +
    +#include 
    +
    +#include 
    +#include 
    +#include 
    +
    +bool
    +cap_sandboxed(void)
    +{
    +	u_int mode;
    +
    +	if (cap_getmode(&mode) != 0) {
    +		assert(errno == ENOSYS);
    +		return (false);
    +	}
    +	assert(mode == 0 || mode == 1);
    +	return (mode == 1);
    +}
    diff --git a/lib/libc/sys/Symbol.map b/lib/libc/sys/Symbol.map
    index babae3082d5..d1262557384 100644
    --- a/lib/libc/sys/Symbol.map
    +++ b/lib/libc/sys/Symbol.map
    @@ -379,6 +379,7 @@ FBSD_1.2 {
     };
     
     FBSD_1.3 {
    +	cap_sandboxed;
     	clock_getcpuclockid2;
     	ffclock_getcounter;
     	ffclock_getestimate;
    diff --git a/lib/libc/sys/cap_enter.2 b/lib/libc/sys/cap_enter.2
    index 5454ec94862..c3cefe887c8 100644
    --- a/lib/libc/sys/cap_enter.2
    +++ b/lib/libc/sys/cap_enter.2
    @@ -90,6 +90,7 @@ acquired rights as possible.
     .Sh SEE ALSO
     .Xr cap_new 2 ,
     .Xr fexecve 2 ,
    +.Xr cap_sandboxed 3 ,
     .Xr capsicum 4
     .Sh HISTORY
     Support for capabilities and capabilities mode was developed as part of the
    
    From 7e026d15d59ddca20d78ffc37212520fe196af66 Mon Sep 17 00:00:00 2001
    From: Marius Strobl 
    Date: Sat, 2 Mar 2013 00:37:31 +0000
    Subject: [PATCH 0515/1476] - While Netra X1 generally show no ill effects when
     registering a power   fail interrupt handler, there seems to be either a
     broken batch of them   or a tendency to develop a defect which causes this
     interrupt to fire   inadvertedly. Given that apart from this problem these
     machines work   just fine, add a tunable allowing the setup of the power fail
     interrupt   to be disabled.   While at it, remove the DEBUGGER_ON_POWERFAIL
     compile time option and   make that behavior also selectable via the newly
     added tunable. - Apparently, it's no longer a problem to call
     shutdown_nice(9) from within   an interrupt filter (some other drivers in the
     tree do the same). So   change the power fail interrupt from an handler in
     order to simplify the   code and get rid of a !INTR_MPSAFE handler. - Use
     NULL instead of 0 for pointers.
    
    MFC after:	1 week
    ---
     sys/conf/options.sparc64 |  1 -
     sys/sparc64/pci/psycho.c | 71 +++++++++++++++++++++++++---------------
     2 files changed, 44 insertions(+), 28 deletions(-)
    
    diff --git a/sys/conf/options.sparc64 b/sys/conf/options.sparc64
    index bc6af5a18a5..883db166927 100644
    --- a/sys/conf/options.sparc64
    +++ b/sys/conf/options.sparc64
    @@ -23,7 +23,6 @@ PSM_DEBUG		opt_psm.h
     PSM_HOOKRESUME		opt_psm.h
     PSM_RESETAFTERSUSPEND	opt_psm.h
     
    -DEBUGGER_ON_POWERFAIL	opt_psycho.h
     PSYCHO_DEBUG		opt_psycho.h
     
     SCHIZO_DEBUG		opt_schizo.h
    diff --git a/sys/sparc64/pci/psycho.c b/sys/sparc64/pci/psycho.c
    index a44af7ca8bf..8f4f23e5fb7 100644
    --- a/sys/sparc64/pci/psycho.c
    +++ b/sys/sparc64/pci/psycho.c
    @@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    +#include 
     
     #include 
     #include 
    @@ -80,7 +81,7 @@ static const struct psycho_desc *psycho_find_desc(const struct psycho_desc *,
         const char *);
     static const struct psycho_desc *psycho_get_desc(device_t);
     static void psycho_set_intr(struct psycho_softc *, u_int, bus_addr_t,
    -    driver_filter_t, driver_intr_t);
    +    driver_filter_t);
     static int psycho_find_intrmap(struct psycho_softc *, u_int, bus_addr_t *,
         bus_addr_t *, u_long *);
     static void sabre_dmamap_sync(bus_dma_tag_t dt, bus_dmamap_t map,
    @@ -94,8 +95,9 @@ static void psycho_intr_clear(void *);
     static driver_filter_t psycho_ue;
     static driver_filter_t psycho_ce;
     static driver_filter_t psycho_pci_bus;
    -static driver_filter_t psycho_powerfail;
    -static driver_intr_t psycho_overtemp;
    +static driver_filter_t psycho_powerdebug;
    +static driver_filter_t psycho_powerdown;
    +static driver_filter_t psycho_overtemp;
     #ifdef PSYCHO_MAP_WAKEUP
     static driver_filter_t psycho_wakeup;
     #endif
    @@ -159,9 +161,16 @@ static devclass_t psycho_devclass;
     
     DEFINE_CLASS_0(pcib, psycho_driver, psycho_methods,
         sizeof(struct psycho_softc));
    -EARLY_DRIVER_MODULE(psycho, nexus, psycho_driver, psycho_devclass, 0, 0,
    +EARLY_DRIVER_MODULE(psycho, nexus, psycho_driver, psycho_devclass, NULL, NULL,
         BUS_PASS_BUS);
     
    +static SYSCTL_NODE(_hw, OID_AUTO, psycho, CTLFLAG_RD, 0, "psycho parameters");
    +
    +static u_int psycho_powerfail = 1;
    +TUNABLE_INT("hw.psycho.powerfail", &psycho_powerfail);
    +SYSCTL_UINT(_hw_psycho, OID_AUTO, powerfail, CTLFLAG_RDTUN, &psycho_powerfail,
    +    0, "powerfail action (0: none, 1: shutdown (default), 2: debugger)");
    +
     static SLIST_HEAD(, psycho_softc) psycho_softcs =
         SLIST_HEAD_INITIALIZER(psycho_softcs);
     
    @@ -610,15 +619,20 @@ psycho_attach(device_t dev)
     		 * XXX Not all controllers have these, but installing them
     		 * is better than trying to sort through this mess.
     		 */
    -		psycho_set_intr(sc, 1, PSR_UE_INT_MAP, psycho_ue, NULL);
    -		psycho_set_intr(sc, 2, PSR_CE_INT_MAP, psycho_ce, NULL);
    -#ifdef DEBUGGER_ON_POWERFAIL
    -		psycho_set_intr(sc, 3, PSR_POWER_INT_MAP, psycho_powerfail,
    -		    NULL);
    -#else
    -		psycho_set_intr(sc, 3, PSR_POWER_INT_MAP, NULL,
    -		    (driver_intr_t *)psycho_powerfail);
    -#endif
    +		psycho_set_intr(sc, 1, PSR_UE_INT_MAP, psycho_ue);
    +		psycho_set_intr(sc, 2, PSR_CE_INT_MAP, psycho_ce);
    +		switch (psycho_powerfail) {
    +		case 0:
    +			break;
    +		case 2:
    +			psycho_set_intr(sc, 3, PSR_POWER_INT_MAP,
    +			    psycho_powerdebug);
    +			break;
    +		default:
    +			psycho_set_intr(sc, 3, PSR_POWER_INT_MAP,
    +			    psycho_powerdown);
    +			break;
    +		}
     		if (sc->sc_mode == PSYCHO_MODE_PSYCHO) {
     			/*
     			 * Hummingbirds/Sabres do not have the following two
    @@ -630,14 +644,14 @@ psycho_attach(device_t dev)
     			 * over-temperature interrupt.
     			 */
     			psycho_set_intr(sc, 4, PSR_SPARE_INT_MAP,
    -			    NULL, psycho_overtemp);
    +			    psycho_overtemp);
     #ifdef PSYCHO_MAP_WAKEUP
     			/*
     			 * psycho_wakeup() doesn't do anything useful right
     			 * now.
     			 */
     			psycho_set_intr(sc, 5, PSR_PWRMGT_INT_MAP,
    -			    psycho_wakeup, NULL);
    +			    psycho_wakeup);
     #endif /* PSYCHO_MAP_WAKEUP */
     		}
     	}
    @@ -647,7 +661,7 @@ psycho_attach(device_t dev)
     	 * interrupt but they are also only used for PCI bus A.
     	 */
     	psycho_set_intr(sc, 0, sc->sc_half == 0 ? PSR_PCIAERR_INT_MAP :
    -	    PSR_PCIBERR_INT_MAP, psycho_pci_bus, NULL);
    +	    PSR_PCIBERR_INT_MAP, psycho_pci_bus);
     
     	/*
     	 * Set the latency timer register as this isn't always done by the
    @@ -687,7 +701,7 @@ psycho_attach(device_t dev)
     
     static void
     psycho_set_intr(struct psycho_softc *sc, u_int index, bus_addr_t intrmap,
    -    driver_filter_t filt, driver_intr_t intr)
    +    driver_filter_t handler)
     {
     	u_long vec;
     	int rid;
    @@ -708,7 +722,7 @@ psycho_set_intr(struct psycho_softc *sc, u_int index, bus_addr_t intrmap,
     	    INTVEC(PSYCHO_READ8(sc, intrmap)) != vec ||
     	    intr_vectors[vec].iv_ic != &psycho_ic ||
     	    bus_setup_intr(sc->sc_dev, sc->sc_irq_res[index],
    -	    INTR_TYPE_MISC | INTR_BRIDGE, filt, intr, sc,
    +	    INTR_TYPE_MISC | INTR_BRIDGE, handler, NULL, sc,
     	    &sc->sc_ihand[index]) != 0)
     		panic("%s: failed to set up interrupt %d", __func__, index);
     }
    @@ -837,13 +851,16 @@ psycho_pci_bus(void *arg)
     }
     
     static int
    -psycho_powerfail(void *arg)
    +psycho_powerdebug(void *arg __unused)
     {
    -#ifdef DEBUGGER_ON_POWERFAIL
    -	struct psycho_softc *sc = arg;
     
     	kdb_enter(KDB_WHY_POWERFAIL, "powerfail");
    -#else
    +	return (FILTER_HANDLED);
    +}
    +
    +static int
    +psycho_powerdown(void *arg __unused)
    +{
     	static int shutdown;
     
     	/* As the interrupt is cleared we may be called multiple times. */
    @@ -851,22 +868,22 @@ psycho_powerfail(void *arg)
     		return (FILTER_HANDLED);
     	shutdown++;
     	printf("Power Failure Detected: Shutting down NOW.\n");
    -	shutdown_nice(0);
    -#endif
    +	shutdown_nice(RB_POWEROFF);
     	return (FILTER_HANDLED);
     }
     
    -static void
    -psycho_overtemp(void *arg)
    +static int
    +psycho_overtemp(void *arg __unused)
     {
     	static int shutdown;
     
     	/* As the interrupt is cleared we may be called multiple times. */
     	if (shutdown != 0)
    -		return;
    +		return (FILTER_HANDLED);
     	shutdown++;
     	printf("DANGER: OVER TEMPERATURE detected.\nShutting down NOW.\n");
     	shutdown_nice(RB_POWEROFF);
    +	return (FILTER_HANDLED);
     }
     
     #ifdef PSYCHO_MAP_WAKEUP
    
    From 11be09b05638547790aa4e97b80c0530427f5885 Mon Sep 17 00:00:00 2001
    From: Marius Strobl 
    Date: Sat, 2 Mar 2013 00:41:51 +0000
    Subject: [PATCH 0516/1476] - Apparently, it's no longer a problem to call
     shutdown_nice(9) from within   an interrupt filter (some other drivers in the
     tree do the same). So   change the overtemperature and power fail interrupts
     from handlers in order   to code and get rid of a !INTR_MPSAFE handlers. -
     Mark unused parameters as such. - Use NULL instead of 0 for pointers.
    
    MFC after:	1 week
    ---
     sys/sparc64/sbus/sbus.c | 26 ++++++++++++++------------
     1 file changed, 14 insertions(+), 12 deletions(-)
    
    diff --git a/sys/sparc64/sbus/sbus.c b/sys/sparc64/sbus/sbus.c
    index dbf1cccc813..6c69e2dcc5d 100644
    --- a/sys/sparc64/sbus/sbus.c
    +++ b/sys/sparc64/sbus/sbus.c
    @@ -152,8 +152,8 @@ static void sbus_intr_assign(void *);
     static void sbus_intr_clear(void *);
     static int sbus_find_intrmap(struct sbus_softc *, u_int, bus_addr_t *,
         bus_addr_t *);
    -static driver_intr_t sbus_overtemp;
    -static driver_intr_t sbus_pwrfail;
    +static driver_filter_t sbus_overtemp;
    +static driver_filter_t sbus_pwrfail;
     static int sbus_print_res(struct sbus_devinfo *);
     
     static device_method_t sbus_methods[] = {
    @@ -199,7 +199,7 @@ static driver_t sbus_driver = {
     
     static devclass_t sbus_devclass;
     
    -EARLY_DRIVER_MODULE(sbus, nexus, sbus_driver, sbus_devclass, 0, 0,
    +EARLY_DRIVER_MODULE(sbus, nexus, sbus_driver, sbus_devclass, NULL, NULL,
         BUS_PASS_BUS);
     MODULE_DEPEND(sbus, nexus, 1, 1, 1);
     MODULE_VERSION(sbus, 1);
    @@ -410,7 +410,7 @@ sbus_attach(device_t dev)
     	    INTVEC(SYSIO_READ8(sc, SBR_THERM_INT_MAP)) != vec ||
     	    intr_vectors[vec].iv_ic != &sbus_ic ||
     	    bus_setup_intr(dev, sc->sc_ot_ires, INTR_TYPE_MISC | INTR_BRIDGE,
    -	    NULL, sbus_overtemp, sc, &sc->sc_ot_ihand) != 0)
    +	    sbus_overtemp, NULL, sc, &sc->sc_ot_ihand) != 0)
     		panic("%s: failed to set up temperature interrupt", __func__);
     	i = 3;
     	sc->sc_pf_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &i,
    @@ -420,7 +420,7 @@ sbus_attach(device_t dev)
     	    INTVEC(SYSIO_READ8(sc, SBR_POWER_INT_MAP)) != vec ||
     	    intr_vectors[vec].iv_ic != &sbus_ic ||
     	    bus_setup_intr(dev, sc->sc_pf_ires, INTR_TYPE_MISC | INTR_BRIDGE,
    -	    NULL, sbus_pwrfail, sc, &sc->sc_pf_ihand) != 0)
    +	    sbus_pwrfail, NULL, sc, &sc->sc_pf_ihand) != 0)
     		panic("%s: failed to set up power fail interrupt", __func__);
     
     	/* Initialize the counter-timer. */
    @@ -897,31 +897,33 @@ sbus_get_devinfo(device_t bus, device_t child)
      * This handles the interrupt and powers off the machine.
      * The same needs to be done to PCI controller drivers.
      */
    -static void
    -sbus_overtemp(void *arg)
    +static int
    +sbus_overtemp(void *arg __unused)
     {
     	static int shutdown;
     
     	/* As the interrupt is cleared we may be called multiple times. */
     	if (shutdown != 0)
    -		return;
    +		return (FILTER_HANDLED);
     	shutdown++;
     	printf("DANGER: OVER TEMPERATURE detected\nShutting down NOW.\n");
     	shutdown_nice(RB_POWEROFF);
    +	return (FILTER_HANDLED);
     }
     
     /* Try to shut down in time in case of power failure. */
    -static void
    -sbus_pwrfail(void *arg)
    +static int
    +sbus_pwrfail(void *arg __unused)
     {
     	static int shutdown;
     
     	/* As the interrupt is cleared we may be called multiple times. */
     	if (shutdown != 0)
    -		return;
    +		return (FILTER_HANDLED);
     	shutdown++;
     	printf("Power failure detected\nShutting down NOW.\n");
    -	shutdown_nice(0);
    +	shutdown_nice(FILTER_HANDLED);
    +	return (FILTER_HANDLED);
     }
     
     static int
    
    From 2609222ab459852b4ae585584d2e68f40d525bb1 Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Sat, 2 Mar 2013 00:53:12 +0000
    Subject: [PATCH 0517/1476] Merge Capsicum overhaul:
    
    - Capability is no longer separate descriptor type. Now every descriptor
      has set of its own capability rights.
    
    - The cap_new(2) system call is left, but it is no longer documented and
      should not be used in new code.
    
    - The new syscall cap_rights_limit(2) should be used instead of
      cap_new(2), which limits capability rights of the given descriptor
      without creating a new one.
    
    - The cap_getrights(2) syscall is renamed to cap_rights_get(2).
    
    - If CAP_IOCTL capability right is present we can further reduce allowed
      ioctls list with the new cap_ioctls_limit(2) syscall. List of allowed
      ioctls can be retrived with cap_ioctls_get(2) syscall.
    
    - If CAP_FCNTL capability right is present we can further reduce fcntls
      that can be used with the new cap_fcntls_limit(2) syscall and retrive
      them with cap_fcntls_get(2).
    
    - To support ioctl and fcntl white-listing the filedesc structure was
      heavly modified.
    
    - The audit subsystem, kdump and procstat tools were updated to
      recognize new syscalls.
    
    - Capability rights were revised and eventhough I tried hard to provide
      backward API and ABI compatibility there are some incompatible changes
      that are described in detail below:
    
    	CAP_CREATE old behaviour:
    	- Allow for openat(2)+O_CREAT.
    	- Allow for linkat(2).
    	- Allow for symlinkat(2).
    	CAP_CREATE new behaviour:
    	- Allow for openat(2)+O_CREAT.
    
    	Added CAP_LINKAT:
    	- Allow for linkat(2). ABI: Reuses CAP_RMDIR bit.
    	- Allow to be target for renameat(2).
    
    	Added CAP_SYMLINKAT:
    	- Allow for symlinkat(2).
    
    	Removed CAP_DELETE. Old behaviour:
    	- Allow for unlinkat(2) when removing non-directory object.
    	- Allow to be source for renameat(2).
    
    	Removed CAP_RMDIR. Old behaviour:
    	- Allow for unlinkat(2) when removing directory.
    
    	Added CAP_RENAMEAT:
    	- Required for source directory for the renameat(2) syscall.
    
    	Added CAP_UNLINKAT (effectively it replaces CAP_DELETE and CAP_RMDIR):
    	- Allow for unlinkat(2) on any object.
    	- Required if target of renameat(2) exists and will be removed by this
    	  call.
    
    	Removed CAP_MAPEXEC.
    
    	CAP_MMAP old behaviour:
    	- Allow for mmap(2) with any combination of PROT_NONE, PROT_READ and
    	  PROT_WRITE.
    	CAP_MMAP new behaviour:
    	- Allow for mmap(2)+PROT_NONE.
    
    	Added CAP_MMAP_R:
    	- Allow for mmap(PROT_READ).
    	Added CAP_MMAP_W:
    	- Allow for mmap(PROT_WRITE).
    	Added CAP_MMAP_X:
    	- Allow for mmap(PROT_EXEC).
    	Added CAP_MMAP_RW:
    	- Allow for mmap(PROT_READ | PROT_WRITE).
    	Added CAP_MMAP_RX:
    	- Allow for mmap(PROT_READ | PROT_EXEC).
    	Added CAP_MMAP_WX:
    	- Allow for mmap(PROT_WRITE | PROT_EXEC).
    	Added CAP_MMAP_RWX:
    	- Allow for mmap(PROT_READ | PROT_WRITE | PROT_EXEC).
    
    	Renamed CAP_MKDIR to CAP_MKDIRAT.
    	Renamed CAP_MKFIFO to CAP_MKFIFOAT.
    	Renamed CAP_MKNODE to CAP_MKNODEAT.
    
    	CAP_READ old behaviour:
    	- Allow pread(2).
    	- Disallow read(2), readv(2) (if there is no CAP_SEEK).
    	CAP_READ new behaviour:
    	- Allow read(2), readv(2).
    	- Disallow pread(2) (CAP_SEEK was also required).
    
    	CAP_WRITE old behaviour:
    	- Allow pwrite(2).
    	- Disallow write(2), writev(2) (if there is no CAP_SEEK).
    	CAP_WRITE new behaviour:
    	- Allow write(2), writev(2).
    	- Disallow pwrite(2) (CAP_SEEK was also required).
    
    	Added convinient defines:
    
    	#define	CAP_PREAD		(CAP_SEEK | CAP_READ)
    	#define	CAP_PWRITE		(CAP_SEEK | CAP_WRITE)
    	#define	CAP_MMAP_R		(CAP_MMAP | CAP_SEEK | CAP_READ)
    	#define	CAP_MMAP_W		(CAP_MMAP | CAP_SEEK | CAP_WRITE)
    	#define	CAP_MMAP_X		(CAP_MMAP | CAP_SEEK | 0x0000000000000008ULL)
    	#define	CAP_MMAP_RW		(CAP_MMAP_R | CAP_MMAP_W)
    	#define	CAP_MMAP_RX		(CAP_MMAP_R | CAP_MMAP_X)
    	#define	CAP_MMAP_WX		(CAP_MMAP_W | CAP_MMAP_X)
    	#define	CAP_MMAP_RWX		(CAP_MMAP_R | CAP_MMAP_W | CAP_MMAP_X)
    	#define	CAP_RECV		CAP_READ
    	#define	CAP_SEND		CAP_WRITE
    
    	#define	CAP_SOCK_CLIENT \
    		(CAP_CONNECT | CAP_GETPEERNAME | CAP_GETSOCKNAME | CAP_GETSOCKOPT | \
    		 CAP_PEELOFF | CAP_RECV | CAP_SEND | CAP_SETSOCKOPT | CAP_SHUTDOWN)
    	#define	CAP_SOCK_SERVER \
    		(CAP_ACCEPT | CAP_BIND | CAP_GETPEERNAME | CAP_GETSOCKNAME | \
    		 CAP_GETSOCKOPT | CAP_LISTEN | CAP_PEELOFF | CAP_RECV | CAP_SEND | \
    		 CAP_SETSOCKOPT | CAP_SHUTDOWN)
    
    	Added defines for backward API compatibility:
    
    	#define	CAP_MAPEXEC		CAP_MMAP_X
    	#define	CAP_DELETE		CAP_UNLINKAT
    	#define	CAP_MKDIR		CAP_MKDIRAT
    	#define	CAP_RMDIR		CAP_UNLINKAT
    	#define	CAP_MKFIFO		CAP_MKFIFOAT
    	#define	CAP_MKNOD		CAP_MKNODAT
    	#define	CAP_SOCK_ALL		(CAP_SOCK_CLIENT | CAP_SOCK_SERVER)
    
    Sponsored by:	The FreeBSD Foundation
    Reviewed by:	Christoph Mallon 
    Many aspects discussed with:	rwatson, benl, jonathan
    ABI compatibility discussed with:	kib
    ---
     contrib/openbsm/etc/audit_event               |   7 +-
     lib/libc/include/compat.h                     |   2 +
     lib/libc/sys/Makefile.inc                     |   8 +-
     lib/libc/sys/Symbol.map                       |   7 +-
     lib/libc/sys/cap_enter.2                      |  38 +-
     lib/libc/sys/cap_fcntls_limit.2               | 127 +++
     lib/libc/sys/cap_ioctls_limit.2               | 158 ++++
     .../sys/{cap_new.2 => cap_rights_limit.2}     | 382 ++++++---
     lib/libc/sys/dup.2                            |   6 -
     lib/libprocstat/libprocstat.c                 |   1 -
     lib/libprocstat/libprocstat.h                 |   1 -
     sys/bsm/audit_kevents.h                       |   7 +-
     sys/cddl/compat/opensolaris/sys/file.h        |   8 +-
     .../opensolaris/uts/common/fs/zfs/zfs_ioctl.c |   6 +-
     .../uts/common/fs/zfs/zfs_onexit.c            |   2 +-
     sys/compat/freebsd32/syscalls.master          |  12 +-
     sys/compat/linux/linux_file.c                 |   9 +-
     sys/compat/svr4/svr4_fcntl.c                  |   6 +-
     sys/compat/svr4/svr4_filio.c                  |  10 +-
     sys/compat/svr4/svr4_misc.c                   |   7 +-
     sys/compat/svr4/svr4_stream.c                 |   4 +-
     sys/dev/iscsi/initiator/iscsi.c               |   4 +-
     sys/fs/fdescfs/fdesc_vfsops.c                 |   2 +-
     sys/fs/fdescfs/fdesc_vnops.c                  |   2 +-
     sys/fs/nfs/nfsdport.h                         |   2 -
     sys/fs/nfsclient/nfs_clport.c                 |   2 +-
     sys/fs/nfsserver/nfs_nfsdport.c               |   8 +-
     sys/i386/ibcs2/ibcs2_misc.c                   |   7 +-
     sys/kern/capabilities.conf                    |  18 +-
     sys/kern/kern_descrip.c                       | 663 ++++++++--------
     sys/kern/kern_exec.c                          |   3 -
     sys/kern/kern_exit.c                          |   2 +-
     sys/kern/kern_fork.c                          |   2 +-
     sys/kern/sys_capability.c                     | 735 ++++++++++--------
     sys/kern/sys_generic.c                        | 133 ++--
     sys/kern/syscalls.master                      |  12 +-
     sys/kern/tty.c                                |  16 +-
     sys/kern/uipc_mqueue.c                        |   9 +-
     sys/kern/uipc_sem.c                           |   4 +-
     sys/kern/uipc_shm.c                           |   4 +-
     sys/kern/uipc_syscalls.c                      |  46 +-
     sys/kern/uipc_usrreq.c                        |  89 +--
     sys/kern/vfs_aio.c                            |   6 +-
     sys/kern/vfs_lookup.c                         |  13 +-
     sys/kern/vfs_syscalls.c                       |  88 +--
     sys/netsmb/smb_dev.c                          |   4 +-
     sys/nfsserver/nfs_srvkrpc.c                   |   3 +-
     sys/ofed/include/linux/file.h                 |   9 +-
     sys/security/audit/audit.h                    |   7 +
     sys/security/audit/audit_arg.c                |  13 +
     sys/security/audit/audit_bsm.c                |  15 +-
     sys/security/audit/audit_private.h            |   2 +
     sys/sys/capability.h                          | 201 +++--
     sys/sys/file.h                                |   7 +-
     sys/sys/filedesc.h                            |  45 +-
     sys/sys/namei.h                               |   5 +-
     sys/sys/user.h                                |   4 +-
     sys/vm/vm_mmap.c                              |   6 +-
     usr.bin/kdump/kdump.c                         |   9 +
     usr.bin/kdump/mksubr                          |   1 +
     usr.bin/procstat/procstat_files.c             |  49 +-
     61 files changed, 1887 insertions(+), 1171 deletions(-)
     create mode 100644 lib/libc/sys/cap_fcntls_limit.2
     create mode 100644 lib/libc/sys/cap_ioctls_limit.2
     rename lib/libc/sys/{cap_new.2 => cap_rights_limit.2} (62%)
    
    diff --git a/contrib/openbsm/etc/audit_event b/contrib/openbsm/etc/audit_event
    index 0350389d63a..f82841ae773 100644
    --- a/contrib/openbsm/etc/audit_event
    +++ b/contrib/openbsm/etc/audit_event
    @@ -548,7 +548,7 @@
     43184:AUE_OPENAT:openat(2) - attr only:fa
     43185:AUE_POSIX_OPENPT:posix_openpt(2):ip
     43186:AUE_CAP_NEW:cap_new(2):fm
    -43187:AUE_CAP_GETRIGHTS:cap_getrights(2):fm
    +43187:AUE_CAP_RIGHTS_GET:cap_rights_get(2):fm
     43188:AUE_CAP_ENTER:cap_enter(2):pc
     43189:AUE_CAP_GETMODE:cap_getmode(2):pc
     43190:AUE_POSIX_SPAWN:posix_spawn(2):pc
    @@ -563,6 +563,11 @@
     43199:AUE_PDGETPID:pdgetpid(2):pc
     43200:AUE_PDWAIT:pdwait(2):pc
     43201:AUE_WAIT6:wait6(2):pc
    +43202:AUE_CAP_RIGHTS_LIMIT:cap_rights_limit(2):fm
    +43203:AUE_CAP_IOCTLS_LIMIT:cap_ioctls_limit(2):fm
    +43204:AUE_CAP_IOCTLS_GET:cap_ioctls_get(2):fm
    +43205:AUE_CAP_FCNTLS_LIMIT:cap_fcntls_limit(2):fm
    +43206:AUE_CAP_FCNTLS_GET:cap_fcntls_get(2):fm
     #
     # Solaris userspace events.
     #
    diff --git a/lib/libc/include/compat.h b/lib/libc/include/compat.h
    index 76945400278..3739fe105c8 100644
    --- a/lib/libc/include/compat.h
    +++ b/lib/libc/include/compat.h
    @@ -42,6 +42,8 @@ __sym_compat(__semctl, freebsd7___semctl, FBSD_1.0);
     __sym_compat(msgctl, freebsd7_msgctl, FBSD_1.0);
     __sym_compat(shmctl, freebsd7_shmctl, FBSD_1.0);
     
    +__sym_compat(cap_getrights, cap_rights_get, FBSD_1.2);
    +
     #undef __sym_compat
     
     #endif	/* __LIBC_COMPAT_H__ */
    diff --git a/lib/libc/sys/Makefile.inc b/lib/libc/sys/Makefile.inc
    index 9f216dc5cc0..03c00900e22 100644
    --- a/lib/libc/sys/Makefile.inc
    +++ b/lib/libc/sys/Makefile.inc
    @@ -93,7 +93,9 @@ MAN+=	abort2.2 \
     	bind.2 \
     	brk.2 \
     	cap_enter.2 \
    -	cap_new.2 \
    +	cap_fcntls_limit.2 \
    +	cap_ioctls_limit.2 \
    +	cap_rights_limit.2 \
     	chdir.2 \
     	chflags.2 \
     	chmod.2 \
    @@ -270,7 +272,9 @@ MLINKS+=access.2 eaccess.2 \
     	access.2 faccessat.2
     MLINKS+=brk.2 sbrk.2
     MLINKS+=cap_enter.2 cap_getmode.2
    -MLINKS+=cap_new.2 cap_getrights.2
    +MLINKS+=cap_fcntls_limit.2 cap_fcntls_get.2
    +MLINKS+=cap_ioctls_limit.2 cap_ioctls_get.2
    +MLINKS+=cap_rights_limit.2 cap_rights_get.2
     MLINKS+=chdir.2 fchdir.2
     MLINKS+=chflags.2 fchflags.2 \
     	chflags.2 lchflags.2
    diff --git a/lib/libc/sys/Symbol.map b/lib/libc/sys/Symbol.map
    index d1262557384..7738e46d8c8 100644
    --- a/lib/libc/sys/Symbol.map
    +++ b/lib/libc/sys/Symbol.map
    @@ -364,7 +364,6 @@ FBSD_1.2 {
     	cap_enter;
     	cap_getmode;
     	cap_new;
    -	cap_getrights;
     	getloginclass;
     	pdfork;
     	pdgetpid;
    @@ -379,6 +378,12 @@ FBSD_1.2 {
     };
     
     FBSD_1.3 {
    +	cap_fcntls_get;
    +	cap_fcntls_limit;
    +	cap_ioctls_get;
    +	cap_ioctls_limit;
    +	cap_rights_get;
    +	cap_rights_limit;
     	cap_sandboxed;
     	clock_getcpuclockid2;
     	ffclock_getcounter;
    diff --git a/lib/libc/sys/cap_enter.2 b/lib/libc/sys/cap_enter.2
    index c3cefe887c8..33696692fa0 100644
    --- a/lib/libc/sys/cap_enter.2
    +++ b/lib/libc/sys/cap_enter.2
    @@ -58,8 +58,10 @@ or
     .Xr pdfork 2
     will be placed in capability mode from inception.
     .Pp
    -When combined with capabilities created with
    -.Xr cap_new 2 ,
    +When combined with
    +.Xr cap_rights_limit 2 ,
    +.Xr cap_ioctls_limit 2 ,
    +.Xr cap_fcntls_limit 2 ,
     .Fn cap_enter
     may be used to create kernel-enforced sandboxes in which
     appropriately-crafted applications or application components may be run.
    @@ -71,11 +73,6 @@ sandbox.
     Creating effective process sandboxes is a tricky process that involves
     identifying the least possible rights required by the process and then
     passing those rights into the process in a safe manner.
    -See the CAVEAT
    -section of
    -.Xr cap_new 2
    -for why this is particularly tricky with UNIX file descriptors as the
    -canonical representation of a right.
     Consumers of
     .Fn cap_enter
     should also be aware of other inherited rights, such as access to VM
    @@ -87,8 +84,33 @@ to create a runtime environment inside the sandbox that has as few implicitly
     acquired rights as possible.
     .Sh RETURN VALUES
     .Rv -std cap_enter cap_getmode
    +.Sh ERRORS
    +The
    +.Fn cap_enter
    +and
    +.Fn cap_getmode
    +system calls
    +will fail if:
    +.Bl -tag -width Er
    +.It Bq Er ENOSYS
    +The kernel is compiled without:
    +.Pp
    +.Cd "options CAPABILITY_MODE"
    +.El
    +.Pp
    +The
    +.Fn cap_getmode
    +system call may also return the following error:
    +.Bl -tag -width Er
    +.It Bq Er EFAULT
    +Pointer
    +.Fa modep
    +points outside the process's allocated address space.
    +.El
     .Sh SEE ALSO
    -.Xr cap_new 2 ,
    +.Xr cap_fcntls_limit 2 ,
    +.Xr cap_ioctls_limit 2 ,
    +.Xr cap_rights_limit 2 ,
     .Xr fexecve 2 ,
     .Xr cap_sandboxed 3 ,
     .Xr capsicum 4
    diff --git a/lib/libc/sys/cap_fcntls_limit.2 b/lib/libc/sys/cap_fcntls_limit.2
    new file mode 100644
    index 00000000000..8fa74634762
    --- /dev/null
    +++ b/lib/libc/sys/cap_fcntls_limit.2
    @@ -0,0 +1,127 @@
    +.\"
    +.\" Copyright (c) 2012 The FreeBSD Foundation
    +.\" All rights reserved.
    +.\"
    +.\" This documentation was written by Pawel Jakub Dawidek under sponsorship
    +.\" the FreeBSD Foundation.
    +.\"
    +.\" Redistribution and use in source and binary forms, with or without
    +.\" modification, are permitted provided that the following conditions
    +.\" are met:
    +.\" 1. Redistributions of source code must retain the above copyright
    +.\"    notice, this list of conditions and the following disclaimer.
    +.\" 2. Redistributions in binary form must reproduce the above copyright
    +.\"    notice, this list of conditions and the following disclaimer in the
    +.\"    documentation and/or other materials provided with the distribution.
    +.\"
    +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
    +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    +.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
    +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    +.\" SUCH DAMAGE.
    +.\"
    +.\" $FreeBSD$
    +.\"
    +.Dd September 20, 2012
    +.Dt CAP_FCNTLS_LIMIT 2
    +.Os
    +.Sh NAME
    +.Nm cap_fcntls_limit ,
    +.Nm cap_fcntls_get
    +.Nd manage allowed fcntl commands
    +.Sh LIBRARY
    +.Lb libc
    +.Sh SYNOPSIS
    +.In sys/capability.h
    +.Ft int
    +.Fn cap_fcntls_limit "int fd" "uint32_t fcntlrights"
    +.Ft int
    +.Fn cap_fcntls_get "int fd" "uint32_t *fcntlrightsp"
    +.Sh DESCRIPTION
    +If a file descriptor is granted the
    +.Dv CAP_FCNTL
    +capability right, the list of allowed
    +.Xr fcntl 2
    +commands can be selectively reduced (but never expanded) with the
    +.Fn cap_fcntls_limit
    +system call.
    +.Pp
    +A bitmask of allowed fcntls commands for a given file descriptor can be obtained
    +with the
    +.Fn cap_fcntls_get
    +system call.
    +.Sh FLAGS
    +The following flags may be specified in the
    +.Fa fcntlrights
    +argument or returned in the
    +.Fa fcntlrightsp
    +argument:
    +.Bl -tag -width CAP_FCNTL_GETOWN
    +.It Dv CAP_FCNTL_GETFL
    +Permit
    +.Dv F_GETFL
    +command.
    +.It Dv CAP_FCNTL_SETFL
    +Permit
    +.Dv F_SETFL
    +command.
    +.It Dv CAP_FCNTL_GETOWN
    +Permit
    +.Dv F_GETOWN
    +command.
    +.It Dv CAP_FCNTL_SETOWN
    +Permit
    +.Dv F_SETOWN
    +command.
    +.El
    +.Sh RETURN VALUES
    +.Rv -std
    +.Sh ERRORS
    +.Fn cap_fcntls_limit
    +succeeds unless:
    +.Bl -tag -width Er
    +.It Bq Er EBADF
    +The
    +.Fa fd
    +argument is not a valid descriptor.
    +.It Bq Er EINVAL
    +An invalid flag has been passed in
    +.Fa fcntlrights .
    +.It Bq Er ENOTCAPABLE
    +.Fa fcntlrights
    +would expand the list of allowed
    +.Xr fcntl 2
    +commands.
    +.El
    +.Pp
    +.Fn cap_fcntls_get
    +succeeds unless:
    +.Bl -tag -width Er
    +.It Bq Er EBADF
    +The
    +.Fa fd
    +argument is not a valid descriptor.
    +.It Bq Er EFAULT
    +The
    +.Fa fcntlrightsp
    +argument points at an invalid address.
    +.El
    +.Sh SEE ALSO
    +.Xr cap_ioctls_limit 2 ,
    +.Xr cap_rights_limit 2 ,
    +.Xr fcntl 2
    +.Sh HISTORY
    +Support for capabilities and capabilities mode was developed as part of the
    +.Tn TrustedBSD
    +Project.
    +.Pp
    +.Sh AUTHORS
    +This function was created by
    +.An Pawel Jakub Dawidek Aq pawel@dawidek.net
    +under sponsorship of the FreeBSD Foundation.
    diff --git a/lib/libc/sys/cap_ioctls_limit.2 b/lib/libc/sys/cap_ioctls_limit.2
    new file mode 100644
    index 00000000000..5eca18c1799
    --- /dev/null
    +++ b/lib/libc/sys/cap_ioctls_limit.2
    @@ -0,0 +1,158 @@
    +.\"
    +.\" Copyright (c) 2012 The FreeBSD Foundation
    +.\" All rights reserved.
    +.\"
    +.\" This documentation was written by Pawel Jakub Dawidek under sponsorship
    +.\" the FreeBSD Foundation.
    +.\"
    +.\" Redistribution and use in source and binary forms, with or without
    +.\" modification, are permitted provided that the following conditions
    +.\" are met:
    +.\" 1. Redistributions of source code must retain the above copyright
    +.\"    notice, this list of conditions and the following disclaimer.
    +.\" 2. Redistributions in binary form must reproduce the above copyright
    +.\"    notice, this list of conditions and the following disclaimer in the
    +.\"    documentation and/or other materials provided with the distribution.
    +.\"
    +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
    +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    +.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
    +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    +.\" SUCH DAMAGE.
    +.\"
    +.\" $FreeBSD$
    +.\"
    +.Dd September 20, 2012
    +.Dt CAP_IOCTLS_LIMIT 2
    +.Os
    +.Sh NAME
    +.Nm cap_ioctls_limit ,
    +.Nm cap_ioctls_get
    +.Nd manage allowed ioctl commands
    +.Sh LIBRARY
    +.Lb libc
    +.Sh SYNOPSIS
    +.In sys/capability.h
    +.Ft int
    +.Fn cap_ioctls_limit "int fd" "const unsigned long *cmds" "size_t ncmds"
    +.Ft ssize_t
    +.Fn cap_ioctls_get "int fd" "unsigned long *cmds" "size_t maxcmds"
    +.Sh DESCRIPTION
    +If a file descriptor is granted the
    +.Dv CAP_IOCTL
    +capability right, the list of allowed
    +.Xr ioctl 2
    +commands can be selectively reduced (but never expanded) with the
    +.Fn cap_ioctls_limit
    +system call.
    +The
    +.Fa cmds
    +argument is an array of
    +.Xr ioctl 2
    +commands and the
    +.Fa ncmds
    +argument specifies the number of elements in the array.
    +There might be up to
    +.Va 256
    +elements in the array.
    +.Pp
    +The list of allowed ioctl commands for a given file descriptor can be obtained
    +with the
    +.Fn cap_ioctls_get
    +system call.
    +The
    +.Fa cmds
    +argument points at memory that can hold up to
    +.Fa maxcmds
    +values.
    +The function populates the provided buffer with up to
    +.Fa maxcmds
    +elements, but always returns the total number of ioctl commands allowed for the
    +given file descriptor.
    +The total number of ioctls commands for the given file descriptor can be
    +obtained by passing
    +.Dv NULL as the
    +.Fa cmds
    +argument and
    +.Va 0
    +as the
    +.Fa maxcmds
    +argument.
    +If all ioctl commands are allowed
    +.Dv ( CAP_IOCTL
    +capability right is assigned to the file descriptor and the
    +.Fn cap_ioctls_limit
    +system call was never called for this file descriptor), the
    +.Fn cap_ioctls_get
    +system call will return
    +.Dv CAP_IOCTLS_ALL
    +and won't modify the buffer pointed out by the
    +.Fa cmds
    +argument.
    +.Sh RETURN VALUES
    +.Rv -std cap_ioctls_limit
    +.Pp
    +The
    +.Fn cap_ioctls_limit
    +function, if successfull, returns the total number of allowed ioctl commands or
    +the value
    +.Dv INT_MAX
    +if all ioctls commands are allowed.
    +On failure the value
    +.Va -1
    +is returned and the global variable errno is set to indicate the error.
    +.Sh ERRORS
    +.Fn cap_ioctls_limit
    +succeeds unless:
    +.Bl -tag -width Er
    +.It Bq Er EBADF
    +The
    +.Fa fd
    +argument is not a valid descriptor.
    +.It Bq Er EFAULT
    +The
    +.Fa cmds
    +argument points at an invalid address.
    +.It Bq Er EINVAL
    +The
    +.Fa ncmds
    +argument is greater than
    +.Va 256 .
    +.It Bq Er ENOTCAPABLE
    +.Fa cmds
    +would expand the list of allowed
    +.Xr ioctl 2
    +commands.
    +.El
    +.Pp
    +.Fn cap_ioctls_get
    +succeeds unless:
    +.Bl -tag -width Er
    +.It Bq Er EBADF
    +The
    +.Fa fd
    +argument is not a valid descriptor.
    +.It Bq Er EFAULT
    +The
    +.Fa cmds
    +argument points at invalid address.
    +.El
    +.Sh SEE ALSO
    +.Xr cap_fcntls_limit 2 ,
    +.Xr cap_rights_limit 2 ,
    +.Xr ioctl 2
    +.Sh HISTORY
    +Support for capabilities and capabilities mode was developed as part of the
    +.Tn TrustedBSD
    +Project.
    +.Pp
    +.Sh AUTHORS
    +This function was created by
    +.An Pawel Jakub Dawidek Aq pawel@dawidek.net
    +under sponsorship of the FreeBSD Foundation.
    diff --git a/lib/libc/sys/cap_new.2 b/lib/libc/sys/cap_rights_limit.2
    similarity index 62%
    rename from lib/libc/sys/cap_new.2
    rename to lib/libc/sys/cap_rights_limit.2
    index a18fd3bf69f..d8d87775558 100644
    --- a/lib/libc/sys/cap_new.2
    +++ b/lib/libc/sys/cap_rights_limit.2
    @@ -1,10 +1,14 @@
     .\"
     .\" Copyright (c) 2008-2010 Robert N. M. Watson
    +.\" Copyright (c) 2012-2013 The FreeBSD Foundation
     .\" All rights reserved.
     .\"
     .\" This software was developed at the University of Cambridge Computer
     .\" Laboratory with support from a grant from Google, Inc.
     .\"
    +.\" Portions of this documentation were written by Pawel Jakub Dawidek
    +.\" under sponsorship from the FreeBSD Foundation.
    +.\"
     .\" Redistribution and use in source and binary forms, with or without
     .\" modification, are permitted provided that the following conditions
     .\" are met:
    @@ -28,76 +32,48 @@
     .\"
     .\" $FreeBSD$
     .\"
    -.Dd July 20, 2011
    -.Dt CAP_NEW 2
    +.Dd February 23, 2013
    +.Dt CAP_RIGHTS_LIMIT 2
     .Os
     .Sh NAME
    -.Nm cap_new ,
    -.Nm cap_getrights
    -.Nd System calls to manipulate capabilities
    +.Nm cap_rights_limit ,
    +.Nm cap_rights_get
    +.Nd manage capability rights
     .Sh LIBRARY
     .Lb libc
     .Sh SYNOPSIS
     .In sys/capability.h
     .Ft int
    -.Fn cap_new "int fd" "cap_rights_t rights"
    +.Fn cap_rights_limit "int fd" "cap_rights_t rights"
     .Ft int
    -.Fn cap_getrights "int fd" "cap_rights_t *rightsp"
    +.Fn cap_rights_get "int fd" "cap_rights_t *rightsp"
     .Sh DESCRIPTION
    -Capabilities are special file descriptors derived from an existing file
    -descriptor, such as one returned by
    +When a file descriptor is created by a function such as
     .Xr fhopen 2 ,
     .Xr kqueue 2 ,
     .Xr mq_open 2 ,
     .Xr open 2 ,
    +.Xr openat 2 ,
    +.Xr pdfork 2 ,
     .Xr pipe 2 ,
     .Xr shm_open 2 ,
     .Xr socket 2 ,
     or
     .Xr socketpair 2 ,
    -but with a restricted set of permitted operations determined by a rights
    -mask set when the capability is created.
    -These restricted rights cannot be changed after the capability is created,
    -although further capabilities with yet more restricted rights may be created
    -from an existing capability.
    -In every other sense, a capability behaves in the same way as the file
    -descriptor it was created from.
    +it is assigned all capability rights.
    +Those rights can be reduced (but never expanded) by using the
    +.Fn cap_rights_limit
    +system call.
    +Once capability rights are reduced, operations on the file descriptor will be
    +limited to those permitted by
    +.Fa rights .
     .Pp
    -.Fn cap_new
    -creates a new capability for the existing file descriptor
    -.Fa fd ,
    -and returns a file descriptor for it.
    -Operations on the capability will be limited to those permitted by
    -.Fa rights ,
    -which is static for the lifetime of the capability.
    -If
    -.Fa fd
    -refers to an existing capability, then
    -.Fa rights
    -must be equal to or a subset of the rights on that capability.
    -As with
    -.Xr dup 2
    -and
    -.Xr dup2 2 ,
    -many properties are shared between the new capability and the existing file
    -descriptor, including open file flags, blocking disposition, and file offset.
    -Many applications will prefer to use the
    -.Xr cap_limitfd 3
    -library call, part of
    -.Xr libcapsicum 3 ,
    -as it offers a more convenient interface.
    -.Pp
    -.Fn cap_getrights
    -queries the rights associated with the capability referred to by file
    -descriptor
    -.Fa fd .
    -.Pp
    -These system calls, when combined with
    -.Xr cap_enter 2 ,
    -may be used to construct process sandboxes with highly granular rights
    -assignment.
    +A bitmask of capability rights assigned to a file descriptor can be obtained with
    +the
    +.Fn cap_rights_get
    +system call.
     .Sh RIGHTS
    -The following rights may be specified in a new capability rights mask:
    +The following rights may be specified in a rights mask:
     .Bl -tag -width CAP_EXTATTR_DELETE
     .It Dv CAP_ACCEPT
     Permit
    @@ -134,6 +110,13 @@ Permit
     also required for
     .Xr sendto 2
     with a non-NULL destination address.
    +.It Dv CAP_CREATE
    +Permit
    +.Xr openat 2
    +with the
    +.Dv O_CREAT
    +flag.
    +.\" XXXPJD: Doesn't exist anymore.
     .It Dv CAP_EVENT
     Permit
     .Xr select 2 ,
    @@ -143,7 +126,12 @@ and
     to be used in monitoring the file descriptor for events.
     .It Dv CAP_FEXECVE
     Permit
    -.Xr fexecve 2 ;
    +.Xr fexecve 2
    +and
    +.Xr openat 2
    +with the
    +.Dv O_EXEC
    +flag;
     .Dv CAP_READ
     will also be required.
     .It Dv CAP_EXTATTR_DELETE
    @@ -166,19 +154,49 @@ Permit
     .Xr fchflags 2 .
     .It Dv CAP_FCHMOD
     Permit
    -.Xr fchmod 2 .
    +.Xr fchmod 2
    +and
    +.Xr fchmodat 2 .
    +.It Dv CAP_FCHMODAT
    +An alias to
    +.Dv CAP_FCHMOD .
     .It Dv CAP_FCHOWN
     Permit
    -.Xr fchown 2 .
    +.Xr fchown 2
    +and
    +.Xr fchownat 2 .
    +.It Dv CAP_FCHOWNAT
    +An alias to
    +.Dv CAP_FCHOWN .
     .It Dv CAP_FCNTL
     Permit
    -.Xr fcntl 2 ;
    -be aware that this call provides indirect access to other operations, such as
    -.Xr flock 2 .
    +.Xr fcntl 2 .
    +Note that only the
    +.Dv F_GETFL ,
    +.Dv F_SETFL ,
    +.Dv F_GETOWN
    +and
    +.Dv F_SETOWN
    +commands require this capability right.
    +Also note that the list of permitted commands can be further limited with the
    +.Xr cap_fcntls_limit 2
    +system call.
     .It Dv CAP_FLOCK
     Permit
    -.Xr flock 2
    -and related calls.
    +.Xr flock 2 ,
    +.Xr fcntl 2
    +(with
    +.Dv F_GETLK ,
    +.Dv F_SETLK
    +or
    +.Dv F_SETLKW
    +flag) and
    +.Xr openat 2
    +(with
    +.Dv O_EXLOCK
    +or
    +.Dv O_SHLOCK
    +flag).
     .It Dv CAP_FPATHCONF
     Permit
     .Xr fpathconf 2 .
    @@ -186,22 +204,42 @@ Permit
     Permit UFS background-fsck operations on the descriptor.
     .It Dv CAP_FSTAT
     Permit
    -.Xr fstat 2 .
    +.Xr fstat 2
    +and
    +.Xr fstatat 2 .
    +.It Dv CAP_FSTATAT
    +An alias to
    +.Dv CAP_FSTAT .
     .It Dv CAP_FSTATFS
     Permit
     .Xr fstatfs 2 .
     .It Dv CAP_FSYNC
     Permit
    -.Xr aio_fsync 2
    +.Xr aio_fsync 2 ,
    +.Xr fsync 2
     and
    -.Xr fsync 2 .
    -.Pp
    +.Xr openat 2
    +with
    +.Dv O_FSYNC
    +or
    +.Dv O_SYNC
    +flag.
     .It Dv CAP_FTRUNCATE
     Permit
    -.Xr ftruncate 2 .
    +.Xr ftruncate 2
    +and
    +.Xr openat 2
    +with the
    +.Dv O_TRUNC
    +flag.
     .It Dv CAP_FUTIMES
     Permit
    -.Xr futimes 2 .
    +.Xr futimes 2
    +and
    +.Xr futimesat 2 .
    +.It Dv CAP_FUTIMESAT
    +An alias to
    +.Dv CAP_FUTIMES .
     .It Dv CAP_GETPEERNAME
     Permit
     .Xr getpeername 2 .
    @@ -216,42 +254,106 @@ Permit
     .Xr ioctl 2 .
     Be aware that this system call has enormous scope, including potentially
     global scope for some objects.
    +The list of permitted ioctl commands can be further limited with the
    +.Xr cap_ioctls_limit 2
    +system call.
    +.\" XXXPJD: Doesn't exist anymore.
     .It Dv CAP_KEVENT
     Permit
     .Xr kevent 2 ;
     .Dv CAP_EVENT
     is also required on file descriptors that will be monitored using
     .Xr kevent 2 .
    +.It Dv CAP_LINKAT
    +Permit
    +.Xr linkat 2
    +and
    +.Xr renameat 2 .
    +This right is required for the destination directory descriptor.
     .It Dv CAP_LISTEN
     Permit
     .Xr listen 2 ;
     not much use (generally) without
     .Dv CAP_BIND .
     .It Dv CAP_LOOKUP
    -Permit the file descriptor to be used as a starting directory for calls such
    -as
    +Permit the file descriptor to be used as a starting directory for calls such as
     .Xr linkat 2 ,
     .Xr openat 2 ,
     and
     .Xr unlinkat 2 .
    -Note that these calls are not available in capability mode as they manipulate
    -a global name space; see
    -.Xr cap_enter 2
    -for details.
     .It Dv CAP_MAC_GET
     Permit
     .Xr mac_get_fd 3 .
     .It Dv CAP_MAC_SET
     Permit
     .Xr mac_set_fd 3 .
    +.It Dv CAP_MKDIRAT
    +Permit
    +.Xr mkdirat 2 .
    +.It Dv CAP_MKFIFOAT
    +Permit
    +.Xr mkfifoat 2 .
    +.It Dv CAP_MKNODAT
    +Permit
    +.Xr mknodat 2 .
     .It Dv CAP_MMAP
     Permit
    -.Xr mmap 2 ;
    -specific invocations may also require
    +.Xr mmap 2
    +with the
    +.Dv PROT_NONE
    +protection.
    +.It Dv CAP_MMAP_R
    +Permit
    +.Xr mmap 2
    +with the
    +.Dv PROT_READ
    +protection.
    +This also implies
     .Dv CAP_READ
    -or
    -.Dv CAP_WRITE .
    -.Pp
    +and
    +.Dv CAP_SEEK
    +rights.
    +.It Dv CAP_MMAP_W
    +Permit
    +.Xr mmap 2
    +with the
    +.Dv PROT_WRITE
    +protection.
    +This also implies
    +.Dv CAP_WRITE
    +and
    +.Dv CAP_SEEK
    +rights.
    +.It Dv CAP_MMAP_X
    +Permit
    +.Xr mmap 2
    +with the
    +.Dv PROT_EXEC
    +protection.
    +This also implies
    +.Dv CAP_SEEK
    +right.
    +.It Dv CAP_MMAP_RW
    +Implies
    +.Dv CAP_MMAP_R
    +and
    +.Dv CAP_MMAP_W .
    +.It Dv CAP_MMAP_RX
    +Implies
    +.Dv CAP_MMAP_R
    +and
    +.Dv CAP_MMAP_X .
    +.It Dv CAP_MMAP_WX
    +Implies
    +.Dv CAP_MMAP_W
    +and
    +.Dv CAP_MMAP_X .
    +.It Dv CAP_MMAP_RWX
    +Implies
    +.Dv CAP_MMAP_R ,
    +.Dv CAP_MMAP_W
    +and
    +.Dv CAP_MMAP_X .
     .It Dv CAP_PDGETPID
     Permit
     .Xr pdgetpid 2 .
    @@ -264,30 +366,46 @@ Permit
     .It Dv CAP_PEELOFF
     Permit
     .Xr sctp_peeloff 2 .
    +.\" XXXPJD: Not documented.
    +.It Dv CAP_POLL_EVENT
    +.\" XXXPJD: Not documented.
    +.It Dv CAP_POST_EVENT
    +.It Dv CAP_PREAD
    +Implies
    +.Dv CAP_SEEK
    +and
    +.Dv CAP_READ .
    +.It Dv CAP_PWRITE
    +Implies
    +.Dv CAP_SEEK
    +and
    +.Dv CAP_WRITE .
     .It Dv CAP_READ
     Allow
     .Xr aio_read 2 ,
    -.Xr pread 2 ,
    +.Xr openat
    +with the
    +.Dv O_RDONLY flag,
     .Xr read 2 ,
     .Xr recv 2 ,
     .Xr recvfrom 2 ,
    -.Xr recvmsg 2 ,
    +.Xr recvmsg 2
     and related system calls.
    -.Pp
    -For files and other seekable objects,
    -.Dv CAP_SEEK
    -may also be required.
    -.It Dv CAP_REVOKE
    +.It Dv CAP_RECV
    +An alias to
    +.Dv CAP_READ .
    +.It Dv CAP_RENAMEAT
     Permit
    -.Xr frevoke 2
    -in certain ABI compatibility modes that support this system call.
    +.Xr renameat 2 .
    +This right is required for the source directory descriptor.
     .It Dv CAP_SEEK
     Permit operations that seek on the file descriptor, such as
     .Xr lseek 2 ,
    -but also required for I/O system calls that modify the file offset, such as
    -.Xr read 2
    +but also required for I/O system calls that can read or write at any position
    +in the file, such as
    +.Xr pread 2
     and
    -.Xr write 2 .
    +.Xr pwrite 2 .
     .It Dv CAP_SEM_GETVALUE
     Permit
     .Xr sem_getvalue 3 .
    @@ -299,6 +417,9 @@ Permit
     .Xr sem_wait 3
     and
     .Xr sem_trywait 3 .
    +.It Dv CAP_SEND
    +An alias to
    +.Dv CAP_WRITE .
     .It Dv CAP_SETSOCKOPT
     Permit
     .Xr setsockopt 2 ;
    @@ -308,49 +429,56 @@ connecting, and other behaviors with global scope.
     Permit explicit
     .Xr shutdown 2 ;
     closing the socket will also generally shut down any connections on it.
    +.It Dv CAP_SYMLINKAT
    +Permit
    +.Xr symlinkat 2 .
     .It Dv CAP_TTYHOOK
     Allow configuration of TTY hooks, such as
     .Xr snp 4 ,
     on the file descriptor.
    +.It Dv CAP_UNLINKAT
    +Permit
    +.Xr unlinkat 2
    +and
    +.Xr renameat 2 .
    +This right is only required for
    +.Xr renameat 2
    +on the destination directory descriptor if the destination object already
    +exists and will be removed by the rename.
     .It Dv CAP_WRITE
     Allow
     .Xr aio_write 2 ,
    -.Xr pwrite 2 ,
    +.Xr openat 2
    +with
    +.Dv O_WRONLY
    +and
    +.Dv O_APPEND
    +flags,
     .Xr send 2 ,
     .Xr sendmsg 2 ,
     .Xr sendto 2 ,
     .Xr write 2 ,
     and related system calls.
    -.Pp
    -For files and other seekable objects,
    -.Dv CAP_SEEK
    -may also be required.
    -.Pp
     For
     .Xr sendto 2
     with a non-NULL connection address,
     .Dv CAP_CONNECT
     is also required.
    +For
    +.Xr openat 2
    +with the
    +.Dv O_WRONLY
    +flag, but without the
    +.Dv O_APPEND
    +flag,
    +.Dv CAP_SEEK
    +is also required.
     .El
    -.Sh CAVEAT
    -The
    -.Fn cap_new
    -system call and the capabilities it creates may be used to assign
    -fine-grained rights to sandboxed processes running in capability mode.
    -However, the semantics of objects accessed via file descriptors are complex,
    -so caution should be exercised in passing object capabilities into sandboxes.
     .Sh RETURN VALUES
    -If successful,
    -.Fn cap_new
    -returns a non-negative integer, termed a file descriptor.
    -It returns -1 on failure, and sets
    -.Va errno
    -to indicate the error.
    -.Pp
    -.Rv -std cap_getrights
    +.Rv -std
     .Sh ERRORS
    -.Fn cap_new
    -may return the following errors:
    +.Fn cap_rights_limit
    +succeeds unless:
     .Bl -tag -width Er
     .It Bq Er EBADF
     The
    @@ -359,29 +487,23 @@ argument is not a valid active descriptor.
     .It Bq Er EINVAL
     An invalid right has been requested in
     .Fa rights .
    -.It Bq Er EMFILE
    -The process has already reached its limit for open file descriptors.
    -.It Bq Er ENFILE
    -The system file table is full.
    -.It Bq Er EPERM
    +.It Bq Er ENOTCAPABLE
     .Fa rights
     contains requested rights not present in the current rights mask associated
    -with the capability referenced by
    -.Fa fd ,
    -if any.
    +with the given file descriptor.
     .El
     .Pp
    -.Fn cap_getrights
    -may return the following errors:
    +.Fn cap_rights_get
    +succeeds unless:
     .Bl -tag -width Er
     .It Bq Er EBADF
     The
     .Fa fd
     argument is not a valid active descriptor.
    -.It Bq Er EINVAL
    +.It Bq Er EFAULT
     The
    -.Fa fd
    -argument is not a capability.
    +.Fa rightsp
    +argument points at an invalid address.
     .El
     .Sh SEE ALSO
     .Xr accept 2 ,
    @@ -390,6 +512,9 @@ argument is not a capability.
     .Xr aio_write 2 ,
     .Xr bind 2 ,
     .Xr cap_enter 2 ,
    +.Xr cap_fcntls_limit 2 ,
    +.Xr cap_ioctls_limit 2 ,
    +.Xr cap_rights_limit 2 ,
     .Xr connect 2 ,
     .Xr dup 2 ,
     .Xr dup2 2 ,
    @@ -421,6 +546,7 @@ argument is not a capability.
     .Xr mq_open 2 ,
     .Xr open 2 ,
     .Xr openat 2 ,
    +.Xr pdfork 2 ,
     .Xr pdgetpid 2 ,
     .Xr pdkill 2 ,
     .Xr pdwait4 2 ,
    @@ -432,6 +558,7 @@ argument is not a capability.
     .Xr recv 2 ,
     .Xr recvfrom 2 ,
     .Xr recvmsg 2 ,
    +.Xr renameat 2 ,
     .Xr sctp_peeloff 2 ,
     .Xr select 2 ,
     .Xr send 2 ,
    @@ -442,6 +569,7 @@ argument is not a capability.
     .Xr shutdown 2 ,
     .Xr socket 2 ,
     .Xr socketpair 2 ,
    +.Xr symlinkat 2 ,
     .Xr unlinkat 2 ,
     .Xr write 2 ,
     .Xr acl_delete_fd_np 3 ,
    @@ -462,11 +590,11 @@ argument is not a capability.
     Support for capabilities and capabilities mode was developed as part of the
     .Tn TrustedBSD
     Project.
    +.Pp
     .Sh AUTHORS
    -These functions and the capability facility were created by
    -.An "Robert N. M. Watson"
    -at the University of Cambridge Computer Laboratory with support from a grant
    -from Google, Inc.
    +This function was created by
    +.An Pawel Jakub Dawidek Aq pawel@dawidek.net
    +under sponsorship of the FreeBSD Foundation.
     .Sh BUGS
     This man page should list the set of permitted system calls more specifically
     for each capability right.
    diff --git a/lib/libc/sys/dup.2 b/lib/libc/sys/dup.2
    index 7a07c211bef..6e1de206470 100644
    --- a/lib/libc/sys/dup.2
    +++ b/lib/libc/sys/dup.2
    @@ -115,11 +115,6 @@ and
     is a valid descriptor, then
     .Fn dup2
     is successful, and does nothing.
    -.Pp
    -The related
    -.Xr cap_new 2
    -system call allows file descriptors to be duplicated with restrictions on
    -their use.
     .Sh RETURN VALUES
     The value -1 is returned if an error occurs in either call.
     The external variable
    @@ -152,7 +147,6 @@ argument is negative or exceeds the maximum allowable descriptor number
     .El
     .Sh SEE ALSO
     .Xr accept 2 ,
    -.Xr cap_new 2 ,
     .Xr close 2 ,
     .Xr fcntl 2 ,
     .Xr getdtablesize 2 ,
    diff --git a/lib/libprocstat/libprocstat.c b/lib/libprocstat/libprocstat.c
    index 9d9c111f7d8..f23ec96dfa2 100644
    --- a/lib/libprocstat/libprocstat.c
    +++ b/lib/libprocstat/libprocstat.c
    @@ -600,7 +600,6 @@ kinfo_fflags2fst(int kfflags)
     	} kfflags2fst[] = {
     		{ KF_FLAG_APPEND, PS_FST_FFLAG_APPEND },
     		{ KF_FLAG_ASYNC, PS_FST_FFLAG_ASYNC },
    -		{ KF_FLAG_CAPABILITY, PS_FST_FFLAG_CAPABILITY },
     		{ KF_FLAG_CREAT, PS_FST_FFLAG_CREAT },
     		{ KF_FLAG_DIRECT, PS_FST_FFLAG_DIRECT },
     		{ KF_FLAG_EXCL, PS_FST_FFLAG_EXCL },
    diff --git a/lib/libprocstat/libprocstat.h b/lib/libprocstat/libprocstat.h
    index 662ea372ab5..1c55aa75620 100644
    --- a/lib/libprocstat/libprocstat.h
    +++ b/lib/libprocstat/libprocstat.h
    @@ -88,7 +88,6 @@
     #define	PS_FST_FFLAG_DIRECT	0x1000
     #define	PS_FST_FFLAG_EXEC	0x2000
     #define	PS_FST_FFLAG_HASLOCK	0x4000
    -#define	PS_FST_FFLAG_CAPABILITY	0x8000
     
     struct procstat;
     struct filestat {
    diff --git a/sys/bsm/audit_kevents.h b/sys/bsm/audit_kevents.h
    index d227981ff76..9d71fa28335 100644
    --- a/sys/bsm/audit_kevents.h
    +++ b/sys/bsm/audit_kevents.h
    @@ -588,7 +588,7 @@
     #define	AUE_OPENAT		43184	/* FreeBSD. */
     #define	AUE_POSIX_OPENPT	43185	/* FreeBSD. */
     #define	AUE_CAP_NEW		43186	/* TrustedBSD. */
    -#define	AUE_CAP_GETRIGHTS	43187	/* TrustedBSD. */
    +#define	AUE_CAP_RIGHTS_GET	43187	/* TrustedBSD. */
     #define	AUE_CAP_ENTER		43188	/* TrustedBSD. */
     #define	AUE_CAP_GETMODE		43189	/* TrustedBSD. */
     #define	AUE_POSIX_SPAWN		43190	/* Darwin. */
    @@ -603,6 +603,11 @@
     #define	AUE_PDGETPID		43199	/* FreeBSD. */
     #define	AUE_PDWAIT		43200	/* FreeBSD. */
     #define	AUE_WAIT6		43201	/* FreeBSD. */
    +#define	AUE_CAP_RIGHTS_LIMIT	43202	/* TrustedBSD. */
    +#define	AUE_CAP_IOCTLS_LIMIT	43203	/* TrustedBSD. */
    +#define	AUE_CAP_IOCTLS_GET	43204	/* TrustedBSD. */
    +#define	AUE_CAP_FCNTLS_LIMIT	43205	/* TrustedBSD. */
    +#define	AUE_CAP_FCNTLS_GET	43206	/* TrustedBSD. */
     
     /*
      * Darwin BSM uses a number of AUE_O_* definitions, which are aliased to the
    diff --git a/sys/cddl/compat/opensolaris/sys/file.h b/sys/cddl/compat/opensolaris/sys/file.h
    index 7a3df369603..0b8f8750661 100644
    --- a/sys/cddl/compat/opensolaris/sys/file.h
    +++ b/sys/cddl/compat/opensolaris/sys/file.h
    @@ -39,15 +39,11 @@ typedef	struct file	file_t;
     #include 
     
     static __inline file_t *
    -getf(int fd)
    +getf(int fd, cap_rights_t rights)
     {
     	struct file *fp;
     
    -	/*
    -	 * We wouldn't need all of these rights on every invocation
    -	 * if we had more information about intent.
    -	 */
    -	if (fget(curthread, fd, CAP_READ | CAP_WRITE | CAP_SEEK, &fp) == 0)
    +	if (fget(curthread, fd, rights, &fp) == 0)
     		return (fp);
     	return (NULL);
     }
    diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
    index af0c9f75d33..fce4bb58922 100644
    --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
    +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
    @@ -3822,7 +3822,7 @@ zfs_ioc_recv(zfs_cmd_t *zc)
     		return (error);
     
     	fd = zc->zc_cookie;
    -	fp = getf(fd);
    +	fp = getf(fd, CAP_PREAD);
     	if (fp == NULL) {
     		nvlist_free(props);
     		return (EBADF);
    @@ -4079,7 +4079,7 @@ zfs_ioc_send(zfs_cmd_t *zc)
     		error = dmu_send_estimate(tosnap, fromsnap, zc->zc_obj,
     		    &zc->zc_objset_type);
     	} else {
    -		file_t *fp = getf(zc->zc_cookie);
    +		file_t *fp = getf(zc->zc_cookie, CAP_WRITE);
     		if (fp == NULL) {
     			dsl_dataset_rele(ds, FTAG);
     			if (dsfrom)
    @@ -4675,7 +4675,7 @@ zfs_ioc_diff(zfs_cmd_t *zc)
     		return (error);
     	}
     
    -	fp = getf(zc->zc_cookie);
    +	fp = getf(zc->zc_cookie, CAP_WRITE);
     	if (fp == NULL) {
     		dmu_objset_rele(fromsnap, FTAG);
     		dmu_objset_rele(tosnap, FTAG);
    diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_onexit.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_onexit.c
    index ca0acfd3206..c12826f2969 100644
    --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_onexit.c
    +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_onexit.c
    @@ -124,7 +124,7 @@ zfs_onexit_fd_hold(int fd, minor_t *minorp)
     	void *data;
     	int error;
     
    -	fp = getf(fd);
    +	fp = getf(fd, CAP_NONE);
     	if (fp == NULL)
     		return (EBADF);
     
    diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master
    index 41064475b99..6552d137e5a 100644
    --- a/sys/compat/freebsd32/syscalls.master
    +++ b/sys/compat/freebsd32/syscalls.master
    @@ -963,7 +963,7 @@
     				    struct shmid_ds32 *buf); }
     513	AUE_LPATHCONF	NOPROTO	{ int lpathconf(char *path, int name); }
     514	AUE_CAP_NEW	NOPROTO	{ int cap_new(int fd, uint64_t rights); }
    -515	AUE_CAP_GETRIGHTS	NOPROTO	{ int cap_getrights(int fd, \
    +515	AUE_CAP_RIGHTS_GET	NOPROTO	{ int cap_rights_get(int fd, \
     				    uint64_t *rightsp); }
     516	AUE_CAP_ENTER	NOPROTO	{ int cap_enter(void); }
     517	AUE_CAP_GETMODE	NOPROTO	{ int cap_getmode(u_int *modep); }
    @@ -1005,3 +1005,13 @@
     				    struct wrusage32 *wrusage, \
     				    siginfo_t *info); }
     
    +533	AUE_CAP_RIGHTS_LIMIT	NOPROTO	{ int cap_rights_limit(int fd, \
    +				    uint64_t rights); }
    +534	AUE_CAP_IOCTLS_LIMIT	NOPROTO	{ int cap_ioctls_limit(int fd, \
    +				    const u_long *cmds, size_t ncmds); }
    +535	AUE_CAP_IOCTLS_GET	NOPROTO	{ ssize_t cap_ioctls_get(int fd, \
    +				    u_long *cmds, size_t maxcmds); }
    +536	AUE_CAP_FCNTLS_LIMIT	NOPROTO	{ int cap_fcntls_limit(int fd, \
    +				    uint32_t fcntlrights); }
    +537	AUE_CAP_FCNTLS_GET	NOPROTO	{ int cap_fcntls_get(int fd, \
    +				    uint32_t *fcntlrightsp); }
    diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c
    index 0318a5cde6f..346d1781d78 100644
    --- a/sys/compat/linux/linux_file.c
    +++ b/sys/compat/linux/linux_file.c
    @@ -154,6 +154,7 @@ linux_common_open(struct thread *td, int dirfd, char *path, int l_flags, int mod
     			SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
     			    PROC_UNLOCK(p);
     			    sx_unlock(&proctree_lock);
    +			    /* XXXPJD: Verify if TIOCSCTTY is allowed. */
     			    if (fp->f_type == DTYPE_VNODE)
     				    (void) fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0,
     					     td->td_ucred, td);
    @@ -1038,11 +1039,11 @@ linux_pread(td, uap)
     	error = sys_pread(td, &bsd);
     
     	if (error == 0) {
    -   	   	/* This seems to violate POSIX but linux does it */
    -		if ((error = fgetvp(td, uap->fd, CAP_READ, &vp)) != 0)
    -   		   	return (error);
    +		/* This seems to violate POSIX but linux does it */
    +		if ((error = fgetvp(td, uap->fd, CAP_PREAD, &vp)) != 0)
    +			return (error);
     		if (vp->v_type == VDIR) {
    -   		   	vrele(vp);
    +			vrele(vp);
     			return (EISDIR);
     		}
     		vrele(vp);
    diff --git a/sys/compat/svr4/svr4_fcntl.c b/sys/compat/svr4/svr4_fcntl.c
    index b9d3ace3ef1..86fab788efa 100644
    --- a/sys/compat/svr4/svr4_fcntl.c
    +++ b/sys/compat/svr4/svr4_fcntl.c
    @@ -265,14 +265,14 @@ fd_revoke(td, fd)
     	/*
     	 * If we ever want to support Capsicum on SVR4 processes (unlikely)
     	 * or FreeBSD grows a native frevoke() (more likely), we will need a
    -	 * CAP_REVOKE here.
    +	 * CAP_FREVOKE here.
     	 *
    -	 * In the meantime, use CAP_MASK_VALID: if a SVR4 process wants to
    +	 * In the meantime, use CAP_ALL: if a SVR4 process wants to
     	 * do an frevoke(), it needs to do it on either a regular file
     	 * descriptor or a fully-privileged capability (which is effectively
     	 * the same as a non-capability-restricted file descriptor).
     	 */
    -	if ((error = fgetvp(td, fd, CAP_MASK_VALID, &vp)) != 0)
    +	if ((error = fgetvp(td, fd, CAP_ALL, &vp)) != 0)
     		return (error);
     
     	if (vp->v_type != VCHR && vp->v_type != VBLK) {
    diff --git a/sys/compat/svr4/svr4_filio.c b/sys/compat/svr4/svr4_filio.c
    index 967169b7dc9..0fbba0754a0 100644
    --- a/sys/compat/svr4/svr4_filio.c
    +++ b/sys/compat/svr4/svr4_filio.c
    @@ -197,22 +197,24 @@ svr4_fil_ioctl(fp, td, retval, fd, cmd, data)
     	u_long cmd;
     	caddr_t data;
     {
    -	int error;
    -	int num;
     	struct filedesc *fdp = td->td_proc->p_fd;
    +	struct filedescent *fde;
    +	int error, num;
     
     	*retval = 0;
     
     	switch (cmd) {
     	case SVR4_FIOCLEX:
     		FILEDESC_XLOCK(fdp);
    -		fdp->fd_ofileflags[fd] |= UF_EXCLOSE;
    +		fde = &fdp->fd_ofiles[fd];
    +		fde->fde_flags |= UF_EXCLOSE;
     		FILEDESC_XUNLOCK(fdp);
     		return 0;
     
     	case SVR4_FIONCLEX:
     		FILEDESC_XLOCK(fdp);
    -		fdp->fd_ofileflags[fd] &= ~UF_EXCLOSE;
    +		fde = &fdp->fd_ofiles[fd];
    +		fde->fde_flags &= ~UF_EXCLOSE;
     		FILEDESC_XUNLOCK(fdp);
     		return 0;
     
    diff --git a/sys/compat/svr4/svr4_misc.c b/sys/compat/svr4/svr4_misc.c
    index d6bc4ebbb9c..0cfaeaebb6c 100644
    --- a/sys/compat/svr4/svr4_misc.c
    +++ b/sys/compat/svr4/svr4_misc.c
    @@ -247,10 +247,8 @@ svr4_sys_getdents64(td, uap)
     
     	DPRINTF(("svr4_sys_getdents64(%d, *, %d)\n",
     		uap->fd, uap->nbytes));
    -	if ((error = getvnode(td->td_proc->p_fd, uap->fd,
    -	    CAP_READ | CAP_SEEK, &fp)) != 0) {
    +	if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_READ, &fp)) != 0)
     		return (error);
    -	}
     
     	if ((fp->f_flag & FREAD) == 0) {
     		fdrop(fp, td);
    @@ -426,8 +424,7 @@ svr4_sys_getdents(td, uap)
     	if (uap->nbytes < 0)
     		return (EINVAL);
     
    -	if ((error = getvnode(td->td_proc->p_fd, uap->fd,
    -	    CAP_READ | CAP_SEEK, &fp)) != 0)
    +	if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_READ, &fp)) != 0)
     		return (error);
     
     	if ((fp->f_flag & FREAD) == 0) {
    diff --git a/sys/compat/svr4/svr4_stream.c b/sys/compat/svr4/svr4_stream.c
    index 27014e38cdd..1c7e83edb91 100644
    --- a/sys/compat/svr4/svr4_stream.c
    +++ b/sys/compat/svr4/svr4_stream.c
    @@ -1449,7 +1449,7 @@ svr4_sys_putmsg(td, uap)
     	struct file     *fp;
     	int error;
     
    -	if ((error = fget(td, uap->fd, CAP_WRITE, &fp)) != 0) {
    +	if ((error = fget(td, uap->fd, CAP_SEND, &fp)) != 0) {
     #ifdef DEBUG_SVR4
     	        uprintf("putmsg: bad fp\n");
     #endif
    @@ -1621,7 +1621,7 @@ svr4_sys_getmsg(td, uap)
     	struct file     *fp;
     	int error;
     
    -	if ((error = fget(td, uap->fd, CAP_READ, &fp)) != 0) {
    +	if ((error = fget(td, uap->fd, CAP_RECV, &fp)) != 0) {
     #ifdef DEBUG_SVR4
     	        uprintf("getmsg: bad fp\n");
     #endif
    diff --git a/sys/dev/iscsi/initiator/iscsi.c b/sys/dev/iscsi/initiator/iscsi.c
    index a93a68577f7..3737b7fdabb 100644
    --- a/sys/dev/iscsi/initiator/iscsi.c
    +++ b/sys/dev/iscsi/initiator/iscsi.c
    @@ -387,11 +387,11 @@ i_setsoc(isc_session_t *sp, int fd, struct thread *td)
          if(sp->soc != NULL)
     	  isc_stop_receiver(sp);
     
    -     error = fget(td, fd, CAP_SOCK_ALL, &sp->fp);
    +     error = fget(td, fd, CAP_SOCK_CLIENT, &sp->fp);
          if(error)
     	  return error;
     
    -     if((error = fgetsock(td, fd, CAP_SOCK_ALL, &sp->soc, 0)) == 0) {
    +     if((error = fgetsock(td, fd, CAP_SOCK_CLIENT, &sp->soc, 0)) == 0) {
     	  sp->td = td;
     	  isc_start_receiver(sp);
          }
    diff --git a/sys/fs/fdescfs/fdesc_vfsops.c b/sys/fs/fdescfs/fdesc_vfsops.c
    index c3dbccfc972..cb5e3c0d0a1 100644
    --- a/sys/fs/fdescfs/fdesc_vfsops.c
    +++ b/sys/fs/fdescfs/fdesc_vfsops.c
    @@ -205,7 +205,7 @@ fdesc_statfs(mp, sbp)
     	last = min(fdp->fd_nfiles, lim);
     	freefd = 0;
     	for (i = fdp->fd_freefile; i < last; i++)
    -		if (fdp->fd_ofiles[i] == NULL)
    +		if (fdp->fd_ofiles[i].fde_file == NULL)
     			freefd++;
     
     	/*
    diff --git a/sys/fs/fdescfs/fdesc_vnops.c b/sys/fs/fdescfs/fdesc_vnops.c
    index 3c4f44d17c9..7923fc65985 100644
    --- a/sys/fs/fdescfs/fdesc_vnops.c
    +++ b/sys/fs/fdescfs/fdesc_vnops.c
    @@ -534,7 +534,7 @@ fdesc_readdir(ap)
     			dp->d_type = DT_DIR;
     			break;
     		default:
    -			if (fdp->fd_ofiles[fcnt] == NULL)
    +			if (fdp->fd_ofiles[fcnt].fde_file == NULL)
     				break;
     			dp->d_namlen = sprintf(dp->d_name, "%d", fcnt);
     			dp->d_reclen = UIO_MX;
    diff --git a/sys/fs/nfs/nfsdport.h b/sys/fs/nfs/nfsdport.h
    index 529ada296e2..a09a6dd1ee6 100644
    --- a/sys/fs/nfs/nfsdport.h
    +++ b/sys/fs/nfs/nfsdport.h
    @@ -94,8 +94,6 @@ struct nfsexstuff {
     #define	NFSFPCRED(f)	((f)->f_cred)
     #define	NFSFPFLAG(f)	((f)->f_flag)
     
    -int fp_getfvp(NFSPROC_T *, int, struct file **, struct vnode **);
    -
     #define	NFSNAMEICNDSET(n, c, o, f)	do {				\
     	(n)->cn_cred = (c);						\
     	(n)->cn_nameiop = (o);						\
    diff --git a/sys/fs/nfsclient/nfs_clport.c b/sys/fs/nfsclient/nfs_clport.c
    index 1179eb53283..a07a67f252c 100644
    --- a/sys/fs/nfsclient/nfs_clport.c
    +++ b/sys/fs/nfsclient/nfs_clport.c
    @@ -1215,7 +1215,7 @@ nfssvc_nfscl(struct thread *td, struct nfssvc_args *uap)
     		 * pretend that we need them all. It is better to be too
     		 * careful than too reckless.
     		 */
    -		if ((error = fget(td, nfscbdarg.sock, CAP_SOCK_ALL, &fp))
    +		if ((error = fget(td, nfscbdarg.sock, CAP_SOCK_CLIENT, &fp))
     		    != 0) {
     			return (error);
     		}
    diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c
    index 1731c720fc3..ef98e2b8922 100644
    --- a/sys/fs/nfsserver/nfs_nfsdport.c
    +++ b/sys/fs/nfsserver/nfs_nfsdport.c
    @@ -2767,7 +2767,7 @@ out:
     /*
      * glue for fp.
      */
    -int
    +static int
     fp_getfvp(struct thread *p, int fd, struct file **fpp, struct vnode **vpp)
     {
     	struct filedesc *fdp;
    @@ -2775,8 +2775,8 @@ fp_getfvp(struct thread *p, int fd, struct file **fpp, struct vnode **vpp)
     	int error = 0;
     
     	fdp = p->td_proc->p_fd;
    -	if (fd >= fdp->fd_nfiles ||
    -	    (fp = fdp->fd_ofiles[fd]) == NULL) {
    +	if (fd < 0 || fd >= fdp->fd_nfiles ||
    +	    (fp = fdp->fd_ofiles[fd].fde_file) == NULL) {
     		error = EBADF;
     		goto out;
     	}
    @@ -3041,7 +3041,7 @@ nfssvc_nfsd(struct thread *td, struct nfssvc_args *uap)
     		 * pretend that we need them all. It is better to be too
     		 * careful than too reckless.
     		 */
    -		if ((error = fget(td, sockarg.sock, CAP_SOCK_ALL, &fp)) != 0)
    +		if ((error = fget(td, sockarg.sock, CAP_SOCK_SERVER, &fp)) != 0)
     			goto out;
     		if (fp->f_type != DTYPE_SOCKET) {
     			fdrop(fp, td);
    diff --git a/sys/i386/ibcs2/ibcs2_misc.c b/sys/i386/ibcs2/ibcs2_misc.c
    index 0692122b070..9f382aaf707 100644
    --- a/sys/i386/ibcs2/ibcs2_misc.c
    +++ b/sys/i386/ibcs2/ibcs2_misc.c
    @@ -337,8 +337,7 @@ ibcs2_getdents(td, uap)
     #define	BSD_DIRENT(cp)		((struct dirent *)(cp))
     #define	IBCS2_RECLEN(reclen)	(reclen + sizeof(u_short))
     
    -	if ((error = getvnode(td->td_proc->p_fd, uap->fd,
    -	    CAP_READ | CAP_SEEK, &fp)) != 0)
    +	if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_READ, &fp)) != 0)
     		return (error);
     	if ((fp->f_flag & FREAD) == 0) {
     		fdrop(fp, td);
    @@ -491,8 +490,8 @@ ibcs2_read(td, uap)
     	u_long *cookies = NULL, *cookiep;
     	int ncookies;
     
    -	if ((error = getvnode(td->td_proc->p_fd, uap->fd,
    -	    CAP_READ | CAP_SEEK, &fp)) != 0) {
    +	if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_READ,
    +	    &fp)) != 0) {
     		if (error == EINVAL)
     			return sys_read(td, (struct read_args *)uap);
     		else
    diff --git a/sys/kern/capabilities.conf b/sys/kern/capabilities.conf
    index 11aad16526a..3c087827d8b 100644
    --- a/sys/kern/capabilities.conf
    +++ b/sys/kern/capabilities.conf
    @@ -110,9 +110,14 @@ aio_write
     ## Allow capability mode and capability system calls.
     ##
     cap_enter
    +cap_fcntls_get
    +cap_fcntls_limit
     cap_getmode
    -cap_getrights
    +cap_ioctls_get
    +cap_ioctls_limit
     cap_new
    +cap_rights_get
    +cap_rights_limit
     
     ##
     ## Allow read-only clock operations.
    @@ -239,7 +244,7 @@ getcontext
     ## Allow directory I/O on a file descriptor, subject to capability rights.
     ## Originally we had separate capabilities for directory-specific read
     ## operations, but on BSD we allow reading the raw directory data, so we just
    -## rely on CAP_READ and CAP_SEEK now.
    +## rely on CAP_READ now.
     ##
     getdents
     getdirentries
    @@ -317,13 +322,10 @@ gettimeofday
     getuid
     
     ##
    -## Disallow ioctl(2) for now, as frequently ioctl(2) operations have global
    -## scope, but this is a tricky one as it is also required for tty control.
    -## We do have a capability right for this operation.
    +## Allow ioctl(2), which hopefully will be limited by applications only to
    +## required commands with cap_ioctls_limit(2) syscall.
     ##
    -## XXXRW: This needs to be revisited.
    -##
    -#ioctl
    +ioctl
     
     ##
     ## Allow querying current process credential state.
    diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
    index acdea406eda..b146bab5ac7 100644
    --- a/sys/kern/kern_descrip.c
    +++ b/sys/kern/kern_descrip.c
    @@ -110,15 +110,8 @@ MALLOC_DECLARE(M_FADVISE);
     static uma_zone_t file_zone;
     
     
    -/* Flags for do_dup() */
    -#define DUP_FIXED	0x1	/* Force fixed allocation */
    -#define DUP_FCNTL	0x2	/* fcntl()-style errors */
    -#define	DUP_CLOEXEC	0x4	/* Atomically set FD_CLOEXEC. */
    -
     static int	closefp(struct filedesc *fdp, int fd, struct file *fp,
     		    struct thread *td, int holdleaders);
    -static int	do_dup(struct thread *td, int flags, int old, int new,
    -		    register_t *retval);
     static int	fd_first_free(struct filedesc *fdp, int low, int size);
     static int	fd_last_used(struct filedesc *fdp, int size);
     static void	fdgrowtable(struct filedesc *fdp, int nfd);
    @@ -166,7 +159,7 @@ static int	fill_vnode_info(struct vnode *vp, struct kinfo_file *kif);
      * the process exits.
      */
     struct freetable {
    -	struct file **ft_table;
    +	struct filedescent *ft_table;
     	SLIST_ENTRY(freetable) ft_next;
     };
     
    @@ -177,8 +170,7 @@ struct freetable {
     struct filedesc0 {
     	struct filedesc fd_fd;
     	SLIST_HEAD(, freetable) fd_free;
    -	struct file *fd_dfiles[NDFILE];
    -	char fd_dfileflags[NDFILE];
    +	struct	filedescent fd_dfiles[NDFILE];
     	NDSLOTTYPE fd_dmap[NDSLOTS(NDFILE)];
     };
     
    @@ -284,7 +276,8 @@ fdunused(struct filedesc *fdp, int fd)
     	FILEDESC_XLOCK_ASSERT(fdp);
     
     	KASSERT(fdisused(fdp, fd), ("fd=%d is already unused", fd));
    -	KASSERT(fdp->fd_ofiles[fd] == NULL, ("fd=%d is still in use", fd));
    +	KASSERT(fdp->fd_ofiles[fd].fde_file == NULL,
    +	    ("fd=%d is still in use", fd));
     
     	fdp->fd_map[NDSLOT(fd)] &= ~NDBIT(fd);
     	if (fd < fdp->fd_freefile)
    @@ -293,6 +286,20 @@ fdunused(struct filedesc *fdp, int fd)
     		fdp->fd_lastfile = fd_last_used(fdp, fd);
     }
     
    +/*
    + * Free a file descriptor.
    + */
    +static inline void
    +fdfree(struct filedesc *fdp, int fd)
    +{
    +	struct filedescent *fde;
    +
    +	fde = &fdp->fd_ofiles[fd];
    +	filecaps_free(&fde->fde_caps);
    +	bzero(fde, sizeof(*fde));
    +	fdunused(fdp, fd);
    +}
    +
     /*
      * System calls on descriptors.
      */
    @@ -434,36 +441,14 @@ sys_fcntl(struct thread *td, struct fcntl_args *uap)
     	return (error);
     }
     
    -static inline int
    -fdunwrap(int fd, cap_rights_t rights, struct filedesc *fdp, struct file **fpp)
    -{
    -
    -	FILEDESC_LOCK_ASSERT(fdp);
    -
    -	*fpp = fget_locked(fdp, fd);
    -	if (*fpp == NULL)
    -		return (EBADF);
    -
    -#ifdef CAPABILITIES
    -	if ((*fpp)->f_type == DTYPE_CAPABILITY) {
    -		int err = cap_funwrap(*fpp, rights, fpp);
    -		if (err != 0) {
    -			*fpp = NULL;
    -			return (err);
    -		}
    -	}
    -#endif /* CAPABILITIES */
    -	return (0);
    -}
    -
     int
     kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
     {
     	struct filedesc *fdp;
     	struct flock *flp;
    -	struct file *fp;
    +	struct file *fp, *fp2;
    +	struct filedescent *fde;
     	struct proc *p;
    -	char *pop;
     	struct vnode *vp;
     	int error, flg, tmp;
     	u_int old, new;
    @@ -505,8 +490,9 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
     			error = EBADF;
     			break;
     		}
    -		pop = &fdp->fd_ofileflags[fd];
    -		td->td_retval[0] = (*pop & UF_EXCLOSE) ? FD_CLOEXEC : 0;
    +		fde = &fdp->fd_ofiles[fd];
    +		td->td_retval[0] =
    +		    (fde->fde_flags & UF_EXCLOSE) ? FD_CLOEXEC : 0;
     		FILEDESC_SUNLOCK(fdp);
     		break;
     
    @@ -517,32 +503,24 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
     			error = EBADF;
     			break;
     		}
    -		pop = &fdp->fd_ofileflags[fd];
    -		*pop = (*pop &~ UF_EXCLOSE) |
    +		fde = &fdp->fd_ofiles[fd];
    +		fde->fde_flags = (fde->fde_flags & ~UF_EXCLOSE) |
     		    (arg & FD_CLOEXEC ? UF_EXCLOSE : 0);
     		FILEDESC_XUNLOCK(fdp);
     		break;
     
     	case F_GETFL:
    -		FILEDESC_SLOCK(fdp);
    -		error = fdunwrap(fd, CAP_FCNTL, fdp, &fp);
    -		if (error != 0) {
    -			FILEDESC_SUNLOCK(fdp);
    +		error = fget_unlocked(fdp, fd, CAP_FCNTL, F_GETFL, &fp, NULL);
    +		if (error != 0)
     			break;
    -		}
     		td->td_retval[0] = OFLAGS(fp->f_flag);
    -		FILEDESC_SUNLOCK(fdp);
    +		fdrop(fp, td);
     		break;
     
     	case F_SETFL:
    -		FILEDESC_SLOCK(fdp);
    -		error = fdunwrap(fd, CAP_FCNTL, fdp, &fp);
    -		if (error != 0) {
    -			FILEDESC_SUNLOCK(fdp);
    +		error = fget_unlocked(fdp, fd, CAP_FCNTL, F_SETFL, &fp, NULL);
    +		if (error != 0)
     			break;
    -		}
    -		fhold(fp);
    -		FILEDESC_SUNLOCK(fdp);
     		do {
     			tmp = flg = fp->f_flag;
     			tmp &= ~FCNTLFLAGS;
    @@ -550,7 +528,7 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
     		} while(atomic_cmpset_int(&fp->f_flag, flg, tmp) == 0);
     		tmp = fp->f_flag & FNONBLOCK;
     		error = fo_ioctl(fp, FIONBIO, &tmp, td->td_ucred, td);
    -		if (error) {
    +		if (error != 0) {
     			fdrop(fp, td);
     			break;
     		}
    @@ -567,14 +545,9 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
     		break;
     
     	case F_GETOWN:
    -		FILEDESC_SLOCK(fdp);
    -		error = fdunwrap(fd, CAP_FCNTL, fdp, &fp);
    -		if (error != 0) {
    -			FILEDESC_SUNLOCK(fdp);
    +		error = fget_unlocked(fdp, fd, CAP_FCNTL, F_GETOWN, &fp, NULL);
    +		if (error != 0)
     			break;
    -		}
    -		fhold(fp);
    -		FILEDESC_SUNLOCK(fdp);
     		error = fo_ioctl(fp, FIOGETOWN, &tmp, td->td_ucred, td);
     		if (error == 0)
     			td->td_retval[0] = tmp;
    @@ -582,14 +555,9 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
     		break;
     
     	case F_SETOWN:
    -		FILEDESC_SLOCK(fdp);
    -		error = fdunwrap(fd, CAP_FCNTL, fdp, &fp);
    -		if (error != 0) {
    -			FILEDESC_SUNLOCK(fdp);
    +		error = fget_unlocked(fdp, fd, CAP_FCNTL, F_SETOWN, &fp, NULL);
    +		if (error != 0)
     			break;
    -		}
    -		fhold(fp);
    -		FILEDESC_SUNLOCK(fdp);
     		tmp = arg;
     		error = fo_ioctl(fp, FIOSETOWN, &tmp, td->td_ucred, td);
     		fdrop(fp, td);
    @@ -608,17 +576,15 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
     
     	case F_SETLK:
     	do_setlk:
    -		FILEDESC_SLOCK(fdp);
    -		error = fdunwrap(fd, CAP_FLOCK, fdp, &fp);
    -		if (error != 0) {
    -			FILEDESC_SUNLOCK(fdp);
    +		error = fget_unlocked(fdp, fd, CAP_FLOCK, 0, &fp, NULL);
    +		if (error != 0)
     			break;
    -		}
     		if (fp->f_type != DTYPE_VNODE) {
    -			FILEDESC_SUNLOCK(fdp);
     			error = EBADF;
    +			fdrop(fp, td);
     			break;
     		}
    +
     		flp = (struct flock *)arg;
     		if (flp->l_whence == SEEK_CUR) {
     			foffset = foffset_get(fp);
    @@ -627,16 +593,12 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
     			     foffset > OFF_MAX - flp->l_start)) {
     				FILEDESC_SUNLOCK(fdp);
     				error = EOVERFLOW;
    +				fdrop(fp, td);
     				break;
     			}
     			flp->l_start += foffset;
     		}
     
    -		/*
    -		 * VOP_ADVLOCK() may block.
    -		 */
    -		fhold(fp);
    -		FILEDESC_SUNLOCK(fdp);
     		vp = fp->f_vnode;
     		switch (flp->l_type) {
     		case F_RDLCK:
    @@ -703,37 +665,37 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
     		 * that the closing thread was a bit slower and that the
     		 * advisory lock succeeded before the close.
     		 */
    -		FILEDESC_SLOCK(fdp);
    -		if (fget_locked(fdp, fd) != fp) {
    -			FILEDESC_SUNLOCK(fdp);
    +		error = fget_unlocked(fdp, fd, 0, 0, &fp2, NULL);
    +		if (error != 0) {
    +			fdrop(fp, td);
    +			break;
    +		}
    +		if (fp != fp2) {
     			flp->l_whence = SEEK_SET;
     			flp->l_start = 0;
     			flp->l_len = 0;
     			flp->l_type = F_UNLCK;
     			(void) VOP_ADVLOCK(vp, (caddr_t)p->p_leader,
     			    F_UNLCK, flp, F_POSIX);
    -		} else
    -			FILEDESC_SUNLOCK(fdp);
    +		}
     		fdrop(fp, td);
    +		fdrop(fp2, td);
     		break;
     
     	case F_GETLK:
    -		FILEDESC_SLOCK(fdp);
    -		error = fdunwrap(fd, CAP_FLOCK, fdp, &fp);
    -		if (error != 0) {
    -			FILEDESC_SUNLOCK(fdp);
    +		error = fget_unlocked(fdp, fd, CAP_FLOCK, 0, &fp, NULL);
    +		if (error != 0)
     			break;
    -		}
     		if (fp->f_type != DTYPE_VNODE) {
    -			FILEDESC_SUNLOCK(fdp);
     			error = EBADF;
    +			fdrop(fp, td);
     			break;
     		}
     		flp = (struct flock *)arg;
     		if (flp->l_type != F_RDLCK && flp->l_type != F_WRLCK &&
     		    flp->l_type != F_UNLCK) {
    -			FILEDESC_SUNLOCK(fdp);
     			error = EINVAL;
    +			fdrop(fp, td);
     			break;
     		}
     		if (flp->l_whence == SEEK_CUR) {
    @@ -744,15 +706,11 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
     			     foffset < OFF_MIN - flp->l_start)) {
     				FILEDESC_SUNLOCK(fdp);
     				error = EOVERFLOW;
    +				fdrop(fp, td);
     				break;
     			}
     			flp->l_start += foffset;
     		}
    -		/*
    -		 * VOP_ADVLOCK() may block.
    -		 */
    -		fhold(fp);
    -		FILEDESC_SUNLOCK(fdp);
     		vp = fp->f_vnode;
     		error = VOP_ADVLOCK(vp, (caddr_t)p->p_leader, F_GETLK, flp,
     		    F_POSIX);
    @@ -763,19 +721,14 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
     		arg = arg ? 128 * 1024: 0;
     		/* FALLTHROUGH */
     	case F_READAHEAD:
    -		FILEDESC_SLOCK(fdp);
    -		if ((fp = fget_locked(fdp, fd)) == NULL) {
    -			FILEDESC_SUNLOCK(fdp);
    -			error = EBADF;
    +		error = fget_unlocked(fdp, fd, 0, 0, &fp, NULL);
    +		if (error != 0)
     			break;
    -		}
     		if (fp->f_type != DTYPE_VNODE) {
    -			FILEDESC_SUNLOCK(fdp);
    +			fdrop(fp, td);
     			error = EBADF;
     			break;
     		}
    -		fhold(fp);
    -		FILEDESC_SUNLOCK(fdp);
     		if (arg >= 0) {
     			vp = fp->f_vnode;
     			error = vn_lock(vp, LK_SHARED);
    @@ -809,11 +762,12 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
     /*
      * Common code for dup, dup2, fcntl(F_DUPFD) and fcntl(F_DUP2FD).
      */
    -static int
    +int
     do_dup(struct thread *td, int flags, int old, int new,
         register_t *retval)
     {
     	struct filedesc *fdp;
    +	struct filedescent *oldfde, *newfde;
     	struct proc *p;
     	struct file *fp;
     	struct file *delfp;
    @@ -842,14 +796,15 @@ do_dup(struct thread *td, int flags, int old, int new,
     		FILEDESC_XUNLOCK(fdp);
     		return (EBADF);
     	}
    +	oldfde = &fdp->fd_ofiles[old];
     	if (flags & DUP_FIXED && old == new) {
     		*retval = new;
     		if (flags & DUP_CLOEXEC)
    -			fdp->fd_ofileflags[new] |= UF_EXCLOSE;
    +			fdp->fd_ofiles[new].fde_flags |= UF_EXCLOSE;
     		FILEDESC_XUNLOCK(fdp);
     		return (0);
     	}
    -	fp = fdp->fd_ofiles[old];
    +	fp = oldfde->fde_file;
     	fhold(fp);
     
     	/*
    @@ -878,8 +833,10 @@ do_dup(struct thread *td, int flags, int old, int new,
     			}
     #endif
     			fdgrowtable(fdp, new + 1);
    +			oldfde = &fdp->fd_ofiles[old];
     		}
    -		if (fdp->fd_ofiles[new] == NULL)
    +		newfde = &fdp->fd_ofiles[new];
    +		if (newfde->fde_file == NULL)
     			fdused(fdp, new);
     	} else {
     		if ((error = fdalloc(td, new, &new)) != 0) {
    @@ -887,20 +844,23 @@ do_dup(struct thread *td, int flags, int old, int new,
     			fdrop(fp, td);
     			return (error);
     		}
    +		newfde = &fdp->fd_ofiles[new];
     	}
     
    -	KASSERT(fp == fdp->fd_ofiles[old], ("old fd has been modified"));
    +	KASSERT(fp == oldfde->fde_file, ("old fd has been modified"));
     	KASSERT(old != new, ("new fd is same as old"));
     
    -	delfp = fdp->fd_ofiles[new];
    +	delfp = newfde->fde_file;
    +
     	/*
     	 * Duplicate the source descriptor.
     	 */
    -	fdp->fd_ofiles[new] = fp;
    +	*newfde = *oldfde;
    +	filecaps_copy(&oldfde->fde_caps, &newfde->fde_caps);
     	if ((flags & DUP_CLOEXEC) != 0)
    -		fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] | UF_EXCLOSE;
    +		newfde->fde_flags = oldfde->fde_flags | UF_EXCLOSE;
     	else
    -		fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] & ~UF_EXCLOSE;
    +		newfde->fde_flags = oldfde->fde_flags & ~UF_EXCLOSE;
     	if (new > fdp->fd_lastfile)
     		fdp->fd_lastfile = new;
     	*retval = new;
    @@ -1141,7 +1101,6 @@ static int
     closefp(struct filedesc *fdp, int fd, struct file *fp, struct thread *td,
         int holdleaders)
     {
    -	struct file *fp_object;
     	int error;
     
     	FILEDESC_XLOCK_ASSERT(fdp);
    @@ -1167,12 +1126,10 @@ closefp(struct filedesc *fdp, int fd, struct file *fp, struct thread *td,
     	knote_fdclose(td, fd);
     
     	/*
    -	 * When we're closing an fd with a capability, we need to notify
    -	 * mqueue if the underlying object is of type mqueue.
    +	 * We need to notify mqueue if the object is of type mqueue.
     	 */
    -	(void)cap_funwrap(fp, 0, &fp_object);
    -	if (fp_object->f_type == DTYPE_MQUEUE)
    -		mq_fdclose(td, fd, fp_object);
    +	if (fp->f_type == DTYPE_MQUEUE)
    +		mq_fdclose(td, fd, fp);
     	FILEDESC_XUNLOCK(fdp);
     
     	error = closef(fp, td);
    @@ -1224,9 +1181,7 @@ kern_close(td, fd)
     		FILEDESC_XUNLOCK(fdp);
     		return (EBADF);
     	}
    -	fdp->fd_ofiles[fd] = NULL;
    -	fdp->fd_ofileflags[fd] = 0;
    -	fdunused(fdp, fd);
    +	fdfree(fdp, fd);
     
     	/* closefp() drops the FILEDESC lock for us. */
     	return (closefp(fdp, fd, fp, td, 1));
    @@ -1258,7 +1213,7 @@ sys_closefrom(struct thread *td, struct closefrom_args *uap)
     		uap->lowfd = 0;
     	FILEDESC_SLOCK(fdp);
     	for (fd = uap->lowfd; fd < fdp->fd_nfiles; fd++) {
    -		if (fdp->fd_ofiles[fd] != NULL) {
    +		if (fdp->fd_ofiles[fd].fde_file != NULL) {
     			FILEDESC_SUNLOCK(fdp);
     			(void)kern_close(td, fd);
     			FILEDESC_SLOCK(fdp);
    @@ -1409,6 +1364,91 @@ out:
     	return (error);
     }
     
    +/*
    + * Initialize filecaps structure.
    + */
    +void
    +filecaps_init(struct filecaps *fcaps)
    +{
    +
    +	bzero(fcaps, sizeof(*fcaps));
    +	fcaps->fc_nioctls = -1;
    +}
    +
    +/*
    + * Copy filecaps structure allocating memory for ioctls array if needed.
    + */
    +void
    +filecaps_copy(const struct filecaps *src, struct filecaps *dst)
    +{
    +	size_t size;
    +
    +	*dst = *src;
    +	if (src->fc_ioctls != NULL) {
    +		KASSERT(src->fc_nioctls > 0,
    +		    ("fc_ioctls != NULL, but fc_nioctls=%hd", src->fc_nioctls));
    +
    +		size = sizeof(src->fc_ioctls[0]) * src->fc_nioctls;
    +		dst->fc_ioctls = malloc(size, M_TEMP, M_WAITOK);
    +		bcopy(src->fc_ioctls, dst->fc_ioctls, size);
    +	}
    +}
    +
    +/*
    + * Move filecaps structure to the new place and clear the old place.
    + */
    +static void
    +filecaps_move(struct filecaps *src, struct filecaps *dst)
    +{
    +
    +	*dst = *src;
    +	bzero(src, sizeof(*src));
    +}
    +
    +/*
    + * Fill the given filecaps structure with full rights.
    + */
    +static void
    +filecaps_fill(struct filecaps *fcaps)
    +{
    +
    +	fcaps->fc_rights = CAP_ALL;
    +	fcaps->fc_ioctls = NULL;
    +	fcaps->fc_nioctls = -1;
    +	fcaps->fc_fcntls = CAP_FCNTL_ALL;
    +}
    +
    +/*
    + * Free memory allocated within filecaps structure.
    + */
    +void
    +filecaps_free(struct filecaps *fcaps)
    +{
    +
    +	free(fcaps->fc_ioctls, M_TEMP);
    +	bzero(fcaps, sizeof(*fcaps));
    +}
    +
    +/*
    + * Validate the given filecaps structure.
    + */
    +static void
    +filecaps_validate(const struct filecaps *fcaps, const char *func)
    +{
    +
    +	KASSERT((fcaps->fc_rights & ~CAP_MASK_VALID) == 0,
    +	    ("%s: invalid rights", func));
    +	KASSERT((fcaps->fc_fcntls & ~CAP_FCNTL_ALL) == 0,
    +	    ("%s: invalid fcntls", func));
    +	KASSERT(fcaps->fc_fcntls == 0 || (fcaps->fc_rights & CAP_FCNTL) != 0,
    +	    ("%s: fcntls without CAP_FCNTL", func));
    +	KASSERT(fcaps->fc_ioctls != NULL ? fcaps->fc_nioctls > 0 :
    +	    (fcaps->fc_nioctls == -1 || fcaps->fc_nioctls == 0),
    +	    ("%s: invalid ioctls", func));
    +	KASSERT(fcaps->fc_nioctls == 0 || (fcaps->fc_rights & CAP_IOCTL) != 0,
    +	    ("%s: ioctls without CAP_IOCTL", func));
    +}
    +
     /*
      * Grow the file table to accomodate (at least) nfd descriptors.
      */
    @@ -1417,9 +1457,8 @@ fdgrowtable(struct filedesc *fdp, int nfd)
     {
     	struct filedesc0 *fdp0;
     	struct freetable *ft;
    -	struct file **ntable;
    -	struct file **otable;
    -	char *nfileflags, *ofileflags;
    +	struct filedescent *ntable;
    +	struct filedescent *otable;
     	int nnfiles, onfiles;
     	NDSLOTTYPE *nmap, *omap;
     
    @@ -1430,7 +1469,6 @@ fdgrowtable(struct filedesc *fdp, int nfd)
     	/* save old values */
     	onfiles = fdp->fd_nfiles;
     	otable = fdp->fd_ofiles;
    -	ofileflags = fdp->fd_ofileflags;
     	omap = fdp->fd_map;
     
     	/* compute the size of the new table */
    @@ -1440,27 +1478,25 @@ fdgrowtable(struct filedesc *fdp, int nfd)
     		return;
     
     	/*
    -	 * Allocate a new table and map.  We need enough space for a) the
    -	 * file entries themselves, b) the file flags, and c) the struct
    -	 * freetable we will use when we decommission the table and place
    -	 * it on the freelist.  We place the struct freetable in the
    -	 * middle so we don't have to worry about padding.
    +	 * Allocate a new table and map.  We need enough space for the
    +	 * file entries themselves and the struct freetable we will use
    +	 * when we decommission the table and place it on the freelist.
    +	 * We place the struct freetable in the middle so we don't have
    +	 * to worry about padding.
     	 */
    -	ntable = malloc(nnfiles * sizeof(*ntable) + sizeof(struct freetable) +
    -	    nnfiles * sizeof(*nfileflags), M_FILEDESC, M_ZERO | M_WAITOK);
    -	nfileflags = (char *)&ntable[nnfiles] + sizeof(struct freetable);
    +	ntable = malloc(nnfiles * sizeof(ntable[0]) + sizeof(struct freetable),
    +	    M_FILEDESC, M_ZERO | M_WAITOK);
     	nmap = malloc(NDSLOTS(nnfiles) * NDSLOTSIZE, M_FILEDESC,
     	    M_ZERO | M_WAITOK);
     
     	/* copy the old data over and point at the new tables */
     	memcpy(ntable, otable, onfiles * sizeof(*otable));
    -	memcpy(nfileflags, ofileflags, onfiles * sizeof(*ofileflags));
     	memcpy(nmap, omap, NDSLOTS(onfiles) * sizeof(*omap));
     
     	/* update the pointers and counters */
     	fdp->fd_nfiles = nnfiles;
    +	memcpy(ntable, otable, onfiles * sizeof(ntable[0]));
     	fdp->fd_ofiles = ntable;
    -	fdp->fd_ofileflags = nfileflags;
     	fdp->fd_map = nmap;
     
     	/*
    @@ -1536,8 +1572,9 @@ fdalloc(struct thread *td, int minfd, int *result)
     	    ("invalid descriptor %d", fd));
     	KASSERT(!fdisused(fdp, fd),
     	    ("fd_first_free() returned non-free descriptor"));
    -	KASSERT(fdp->fd_ofiles[fd] == NULL, ("file descriptor isn't free"));
    -	KASSERT(fdp->fd_ofileflags[fd] == 0, ("file flags are set"));
    +	KASSERT(fdp->fd_ofiles[fd].fde_file == NULL,
    +	    ("file descriptor isn't free"));
    +	KASSERT(fdp->fd_ofiles[fd].fde_flags == 0, ("file flags are set"));
     	fdused(fdp, fd);
     	*result = fd;
     	return (0);
    @@ -1568,7 +1605,7 @@ fdavail(struct thread *td, int n)
     		return (1);
     	last = min(fdp->fd_nfiles, lim);
     	for (i = fdp->fd_freefile; i < last; i++) {
    -		if (fdp->fd_ofiles[i] == NULL && --n <= 0)
    +		if (fdp->fd_ofiles[i].fde_file == NULL && --n <= 0)
     			return (1);
     	}
     	return (0);
    @@ -1591,7 +1628,7 @@ falloc(struct thread *td, struct file **resultfp, int *resultfd, int flags)
     	if (error)
     		return (error);		/* no reference held on error */
     
    -	error = finstall(td, fp, &fd, flags);
    +	error = finstall(td, fp, &fd, flags, NULL);
     	if (error) {
     		fdrop(fp, td);		/* one reference (fp only) */
     		return (error);
    @@ -1645,13 +1682,17 @@ falloc_noinstall(struct thread *td, struct file **resultfp)
      * Install a file in a file descriptor table.
      */
     int
    -finstall(struct thread *td, struct file *fp, int *fd, int flags)
    +finstall(struct thread *td, struct file *fp, int *fd, int flags,
    +    struct filecaps *fcaps)
     {
     	struct filedesc *fdp = td->td_proc->p_fd;
    +	struct filedescent *fde;
     	int error;
     
     	KASSERT(fd != NULL, ("%s: fd == NULL", __func__));
     	KASSERT(fp != NULL, ("%s: fp == NULL", __func__));
    +	if (fcaps != NULL)
    +		filecaps_validate(fcaps, __func__);
     
     	FILEDESC_XLOCK(fdp);
     	if ((error = fdalloc(td, 0, fd))) {
    @@ -1659,9 +1700,14 @@ finstall(struct thread *td, struct file *fp, int *fd, int flags)
     		return (error);
     	}
     	fhold(fp);
    -	fdp->fd_ofiles[*fd] = fp;
    +	fde = &fdp->fd_ofiles[*fd];
    +	fde->fde_file = fp;
     	if ((flags & O_CLOEXEC) != 0)
    -		fdp->fd_ofileflags[*fd] |= UF_EXCLOSE;
    +		fde->fde_flags |= UF_EXCLOSE;
    +	if (fcaps != NULL)
    +		filecaps_move(fcaps, &fde->fde_caps);
    +	else
    +		filecaps_fill(&fde->fde_caps);
     	FILEDESC_XUNLOCK(fdp);
     	return (0);
     }
    @@ -1696,7 +1742,6 @@ fdinit(struct filedesc *fdp)
     	newfdp->fd_fd.fd_holdcnt = 1;
     	newfdp->fd_fd.fd_cmask = CMASK;
     	newfdp->fd_fd.fd_ofiles = newfdp->fd_dfiles;
    -	newfdp->fd_fd.fd_ofileflags = newfdp->fd_dfileflags;
     	newfdp->fd_fd.fd_nfiles = NDFILE;
     	newfdp->fd_fd.fd_map = newfdp->fd_dmap;
     	newfdp->fd_fd.fd_lastfile = -1;
    @@ -1764,7 +1809,7 @@ fdunshare(struct proc *p, struct thread *td)
     
     		FILEDESC_XUNLOCK(p->p_fd);
     		tmp = fdcopy(p->p_fd);
    -		fdfree(td);
    +		fdescfree(td);
     		p->p_fd = tmp;
     	} else
     		FILEDESC_XUNLOCK(p->p_fd);
    @@ -1778,6 +1823,7 @@ struct filedesc *
     fdcopy(struct filedesc *fdp)
     {
     	struct filedesc *newfdp;
    +	struct filedescent *nfde, *ofde;
     	int i;
     
     	/* Certain daemons might not have file descriptors. */
    @@ -1796,12 +1842,14 @@ fdcopy(struct filedesc *fdp)
     	/* copy all passable descriptors (i.e. not kqueue) */
     	newfdp->fd_freefile = -1;
     	for (i = 0; i <= fdp->fd_lastfile; ++i) {
    +		ofde = &fdp->fd_ofiles[i];
     		if (fdisused(fdp, i) &&
    -		    (fdp->fd_ofiles[i]->f_ops->fo_flags & DFLAG_PASSABLE) &&
    -		    fdp->fd_ofiles[i]->f_ops != &badfileops) {
    -			newfdp->fd_ofiles[i] = fdp->fd_ofiles[i];
    -			newfdp->fd_ofileflags[i] = fdp->fd_ofileflags[i];
    -			fhold(newfdp->fd_ofiles[i]);
    +		    (ofde->fde_file->f_ops->fo_flags & DFLAG_PASSABLE) &&
    +		    ofde->fde_file->f_ops != &badfileops) {
    +			nfde = &newfdp->fd_ofiles[i];
    +			*nfde = *ofde;
    +			filecaps_copy(&ofde->fde_caps, &nfde->fde_caps);
    +			fhold(nfde->fde_file);
     			newfdp->fd_lastfile = i;
     		} else {
     			if (newfdp->fd_freefile == -1)
    @@ -1811,9 +1859,10 @@ fdcopy(struct filedesc *fdp)
     	newfdp->fd_cmask = fdp->fd_cmask;
     	FILEDESC_SUNLOCK(fdp);
     	FILEDESC_XLOCK(newfdp);
    -	for (i = 0; i <= newfdp->fd_lastfile; ++i)
    -		if (newfdp->fd_ofiles[i] != NULL)
    +	for (i = 0; i <= newfdp->fd_lastfile; ++i) {
    +		if (newfdp->fd_ofiles[i].fde_file != NULL)
     			fdused(newfdp, i);
    +	}
     	if (newfdp->fd_freefile == -1)
     		newfdp->fd_freefile = i;
     	FILEDESC_XUNLOCK(newfdp);
    @@ -1824,7 +1873,7 @@ fdcopy(struct filedesc *fdp)
      * Release a filedesc structure.
      */
     void
    -fdfree(struct thread *td)
    +fdescfree(struct thread *td)
     {
     	struct filedesc *fdp;
     	int i;
    @@ -1849,12 +1898,12 @@ fdfree(struct thread *td)
     	if (fdtol != NULL) {
     		FILEDESC_XLOCK(fdp);
     		KASSERT(fdtol->fdl_refcount > 0,
    -			("filedesc_to_refcount botch: fdl_refcount=%d",
    -			 fdtol->fdl_refcount));
    +		    ("filedesc_to_refcount botch: fdl_refcount=%d",
    +		    fdtol->fdl_refcount));
     		if (fdtol->fdl_refcount == 1 &&
     		    (td->td_proc->p_leader->p_flag & P_ADVLOCK) != 0) {
     			for (i = 0; i <= fdp->fd_lastfile; i++) {
    -				fp = fdp->fd_ofiles[i];
    +				fp = fdp->fd_ofiles[i].fde_file;
     				if (fp == NULL || fp->f_type != DTYPE_VNODE)
     					continue;
     				fhold(fp);
    @@ -1914,10 +1963,10 @@ fdfree(struct thread *td)
     		return;
     
     	for (i = 0; i <= fdp->fd_lastfile; i++) {
    -		fp = fdp->fd_ofiles[i];
    +		fp = fdp->fd_ofiles[i].fde_file;
     		if (fp != NULL) {
     			FILEDESC_XLOCK(fdp);
    -			fdp->fd_ofiles[i] = NULL;
    +			fdfree(fdp, i);
     			FILEDESC_XUNLOCK(fdp);
     			(void) closef(fp, td);
     		}
    @@ -1982,6 +2031,7 @@ void
     setugidsafety(struct thread *td)
     {
     	struct filedesc *fdp;
    +	struct file *fp;
     	int i;
     
     	/* Certain daemons might not have file descriptors. */
    @@ -1997,18 +2047,14 @@ setugidsafety(struct thread *td)
     	for (i = 0; i <= fdp->fd_lastfile; i++) {
     		if (i > 2)
     			break;
    -		if (fdp->fd_ofiles[i] && is_unsafe(fdp->fd_ofiles[i])) {
    -			struct file *fp;
    -
    +		fp = fdp->fd_ofiles[i].fde_file;
    +		if (fp != NULL && is_unsafe(fp)) {
     			knote_fdclose(td, i);
     			/*
     			 * NULL-out descriptor prior to close to avoid
     			 * a race while close blocks.
     			 */
    -			fp = fdp->fd_ofiles[i];
    -			fdp->fd_ofiles[i] = NULL;
    -			fdp->fd_ofileflags[i] = 0;
    -			fdunused(fdp, i);
    +			fdfree(fdp, i);
     			FILEDESC_XUNLOCK(fdp);
     			(void) closef(fp, td);
     			FILEDESC_XLOCK(fdp);
    @@ -2029,9 +2075,8 @@ fdclose(struct filedesc *fdp, struct file *fp, int idx, struct thread *td)
     {
     
     	FILEDESC_XLOCK(fdp);
    -	if (fdp->fd_ofiles[idx] == fp) {
    -		fdp->fd_ofiles[idx] = NULL;
    -		fdunused(fdp, idx);
    +	if (fdp->fd_ofiles[idx].fde_file == fp) {
    +		fdfree(fdp, idx);
     		FILEDESC_XUNLOCK(fdp);
     		fdrop(fp, td);
     	} else
    @@ -2045,6 +2090,7 @@ void
     fdcloseexec(struct thread *td)
     {
     	struct filedesc *fdp;
    +	struct filedescent *fde;
     	struct file *fp;
     	int i;
     
    @@ -2054,17 +2100,16 @@ fdcloseexec(struct thread *td)
     		return;
     
     	/*
    -	 * We cannot cache fd_ofiles or fd_ofileflags since operations
    +	 * We cannot cache fd_ofiles since operations
     	 * may block and rip them out from under us.
     	 */
     	FILEDESC_XLOCK(fdp);
     	for (i = 0; i <= fdp->fd_lastfile; i++) {
    -		fp = fdp->fd_ofiles[i];
    +		fde = &fdp->fd_ofiles[i];
    +		fp = fde->fde_file;
     		if (fp != NULL && (fp->f_type == DTYPE_MQUEUE ||
    -		    (fdp->fd_ofileflags[i] & UF_EXCLOSE))) {
    -			fdp->fd_ofiles[i] = NULL;
    -			fdp->fd_ofileflags[i] = 0;
    -			fdunused(fdp, i);
    +		    (fde->fde_flags & UF_EXCLOSE))) {
    +			fdfree(fdp, i);
     			(void) closefp(fdp, i, fp, td, 0);
     			/* closefp() drops the FILEDESC lock. */
     			FILEDESC_XLOCK(fdp);
    @@ -2094,7 +2139,7 @@ fdcheckstd(struct thread *td)
     	devnull = -1;
     	error = 0;
     	for (i = 0; i < 3; i++) {
    -		if (fdp->fd_ofiles[i] != NULL)
    +		if (fdp->fd_ofiles[i].fde_file != NULL)
     			continue;
     		if (devnull < 0) {
     			save = td->td_retval[0];
    @@ -2129,7 +2174,6 @@ closef(struct file *fp, struct thread *td)
     	struct flock lf;
     	struct filedesc_to_leader *fdtol;
     	struct filedesc *fdp;
    -	struct file *fp_object;
     
     	/*
     	 * POSIX record locking dictates that any close releases ALL
    @@ -2142,13 +2186,9 @@ closef(struct file *fp, struct thread *td)
     	 * NULL thread pointer when there really is no owning
     	 * context that might have locks, or the locks will be
     	 * leaked.
    -	 *
    -	 * If this is a capability, we do lock processing under the underlying
    -	 * node, not the capability itself.
     	 */
    -	(void)cap_funwrap(fp, 0, &fp_object);
    -	if (fp_object->f_type == DTYPE_VNODE && td != NULL) {
    -		vp = fp_object->f_vnode;
    +	if (fp->f_type == DTYPE_VNODE && td != NULL) {
    +		vp = fp->f_vnode;
     		if ((td->td_proc->p_leader->p_flag & P_ADVLOCK) != 0) {
     			lf.l_whence = SEEK_SET;
     			lf.l_start = 0;
    @@ -2177,7 +2217,7 @@ closef(struct file *fp, struct thread *td)
     				lf.l_start = 0;
     				lf.l_len = 0;
     				lf.l_type = F_UNLCK;
    -				vp = fp_object->f_vnode;
    +				vp = fp->f_vnode;
     				(void) VOP_ADVLOCK(vp,
     				    (caddr_t)fdtol->fdl_leader, F_UNLCK, &lf,
     				    F_POSIX);
    @@ -2211,14 +2251,19 @@ finit(struct file *fp, u_int flag, short type, void *data, struct fileops *ops)
     	atomic_store_rel_ptr((volatile uintptr_t *)&fp->f_ops, (uintptr_t)ops);
     }
     
    -struct file *
    -fget_unlocked(struct filedesc *fdp, int fd)
    +int
    +fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t needrights,
    +    int needfcntl, struct file **fpp, cap_rights_t *haverightsp)
     {
     	struct file *fp;
     	u_int count;
    +#ifdef CAPABILITIES
    +	cap_rights_t haverights;
    +	int error;
    +#endif
     
     	if (fd < 0 || fd >= fdp->fd_nfiles)
    -		return (NULL);
    +		return (EBADF);
     	/*
     	 * Fetch the descriptor locklessly.  We avoid fdrop() races by
     	 * never raising a refcount above 0.  To accomplish this we have
    @@ -2228,9 +2273,20 @@ fget_unlocked(struct filedesc *fdp, int fd)
     	 * due to preemption.
     	 */
     	for (;;) {
    -		fp = fdp->fd_ofiles[fd];
    +		fp = fdp->fd_ofiles[fd].fde_file;
     		if (fp == NULL)
    -			break;
    +			return (EBADF);
    +#ifdef CAPABILITIES
    +		haverights = cap_rights(fdp, fd);
    +		error = cap_check(haverights, needrights);
    +		if (error != 0)
    +			return (error);
    +		if ((needrights & CAP_FCNTL) != 0) {
    +			error = cap_fcntl_check(fdp, fd, needfcntl);
    +			if (error != 0)
    +				return (error);
    +		}
    +#endif
     		count = fp->f_count;
     		if (count == 0)
     			continue;
    @@ -2240,12 +2296,19 @@ fget_unlocked(struct filedesc *fdp, int fd)
     		 */
     		if (atomic_cmpset_acq_int(&fp->f_count, count, count + 1) != 1)
     			continue;
    -		if (fp == fdp->fd_ofiles[fd])
    +		if (fp == fdp->fd_ofiles[fd].fde_file)
     			break;
     		fdrop(fp, curthread);
     	}
    -
    -	return (fp);
    +	*fpp = fp;
    +	if (haverightsp != NULL) {
    +#ifdef CAPABILITIES
    +		*haverightsp = haverights;
    +#else
    +		*haverightsp = CAP_ALL;
    +#endif
    +	}
    +	return (0);
     }
     
     /*
    @@ -2255,33 +2318,29 @@ fget_unlocked(struct filedesc *fdp, int fd)
      * If the descriptor doesn't exist or doesn't match 'flags', EBADF is
      * returned.
      *
    - * If the FGET_GETCAP flag is set, the capability itself will be returned.
    - * Calling _fget() with FGET_GETCAP on a non-capability will return EINVAL.
    - * Otherwise, if the file is a capability, its rights will be checked against
    - * the capability rights mask, and if successful, the object will be unwrapped.
    + * File's rights will be checked against the capability rights mask.
      *
      * If an error occured the non-zero error is returned and *fpp is set to
      * NULL.  Otherwise *fpp is held and set and zero is returned.  Caller is
      * responsible for fdrop().
      */
    -#define	FGET_GETCAP	0x00000001
     static __inline int
     _fget(struct thread *td, int fd, struct file **fpp, int flags,
    -    cap_rights_t needrights, cap_rights_t *haverightsp, u_char *maxprotp,
    -    int fget_flags)
    +    cap_rights_t needrights, u_char *maxprotp)
     {
     	struct filedesc *fdp;
     	struct file *fp;
    -#ifdef CAPABILITIES
    -	struct file *fp_fromcap;
    -#endif
    +	cap_rights_t haverights;
     	int error;
     
     	*fpp = NULL;
     	if (td == NULL || (fdp = td->td_proc->p_fd) == NULL)
     		return (EBADF);
    -	if ((fp = fget_unlocked(fdp, fd)) == NULL)
    -		return (EBADF);
    +	if (maxprotp != NULL)
    +		needrights |= CAP_MMAP;
    +	error = fget_unlocked(fdp, fd, needrights, 0, &fp, &haverights);
    +	if (error != 0)
    +		return (error);
     	if (fp->f_ops == &badfileops) {
     		fdrop(fp, td);
     		return (EBADF);
    @@ -2289,50 +2348,11 @@ _fget(struct thread *td, int fd, struct file **fpp, int flags,
     
     #ifdef CAPABILITIES
     	/*
    -	 * If this is a capability, what rights does it have?
    +	 * If requested, convert capability rights to access flags.
     	 */
    -	if (haverightsp != NULL) {
    -		if (fp->f_type == DTYPE_CAPABILITY)
    -			*haverightsp = cap_rights(fp);
    -		else
    -			*haverightsp = CAP_MASK_VALID;
    -	}
    -
    -	/*
    -	 * If a capability has been requested, return the capability directly.
    -	 * Otherwise, check capability rights, extract the underlying object,
    -	 * and check its access flags.
    -	 */
    -	if (fget_flags & FGET_GETCAP) {
    -		if (fp->f_type != DTYPE_CAPABILITY) {
    -			fdrop(fp, td);
    -			return (EINVAL);
    -		}
    -	} else {
    -		if (maxprotp == NULL)
    -			error = cap_funwrap(fp, needrights, &fp_fromcap);
    -		else
    -			error = cap_funwrap_mmap(fp, needrights, maxprotp,
    -			    &fp_fromcap);
    -		if (error != 0) {
    -			fdrop(fp, td);
    -			return (error);
    -		}
    -
    -		/*
    -		 * If we've unwrapped a file, drop the original capability
    -		 * and hold the new descriptor.  fp after this point refers to
    -		 * the actual (unwrapped) object, not the capability.
    -		 */
    -		if (fp != fp_fromcap) {
    -			fhold(fp_fromcap);
    -			fdrop(fp, td);
    -			fp = fp_fromcap;
    -		}
    -	}
    +	if (maxprotp != NULL)
    +		*maxprotp = cap_rights_to_vmprot(haverights);
     #else /* !CAPABILITIES */
    -	KASSERT(fp->f_type != DTYPE_CAPABILITY,
    -	    ("%s: saw capability", __func__));
     	if (maxprotp != NULL)
     		*maxprotp = VM_PROT_ALL;
     #endif /* CAPABILITIES */
    @@ -2371,7 +2391,7 @@ int
     fget(struct thread *td, int fd, cap_rights_t rights, struct file **fpp)
     {
     
    -	return(_fget(td, fd, fpp, 0, rights, NULL, NULL, 0));
    +	return(_fget(td, fd, fpp, 0, rights, NULL));
     }
     
     int
    @@ -2379,36 +2399,23 @@ fget_mmap(struct thread *td, int fd, cap_rights_t rights, u_char *maxprotp,
         struct file **fpp)
     {
     
    -	return (_fget(td, fd, fpp, 0, rights, NULL, maxprotp, 0));
    +	return (_fget(td, fd, fpp, 0, rights, maxprotp));
     }
     
     int
     fget_read(struct thread *td, int fd, cap_rights_t rights, struct file **fpp)
     {
     
    -	return(_fget(td, fd, fpp, FREAD, rights, NULL, NULL, 0));
    +	return(_fget(td, fd, fpp, FREAD, rights, NULL));
     }
     
     int
     fget_write(struct thread *td, int fd, cap_rights_t rights, struct file **fpp)
     {
     
    -	return (_fget(td, fd, fpp, FWRITE, rights, NULL, NULL, 0));
    +	return (_fget(td, fd, fpp, FWRITE, rights, NULL));
     }
     
    -/*
    - * Unlike the other fget() calls, which accept and check capability rights
    - * but never return capabilities, fgetcap() returns the capability but doesn't
    - * check capability rights.
    - */
    -int
    -fgetcap(struct thread *td, int fd, struct file **fpp)
    -{
    -
    -	return (_fget(td, fd, fpp, 0, 0, NULL, NULL, FGET_GETCAP));
    -}
    -
    -
     /*
      * Like fget() but loads the underlying vnode, or returns an error if the
      * descriptor does not represent a vnode.  Note that pipes use vnodes but
    @@ -2418,14 +2425,14 @@ fgetcap(struct thread *td, int fd, struct file **fpp)
      */
     static __inline int
     _fgetvp(struct thread *td, int fd, int flags, cap_rights_t needrights,
    -    cap_rights_t *haverightsp, struct vnode **vpp)
    +    struct vnode **vpp)
     {
     	struct file *fp;
     	int error;
     
     	*vpp = NULL;
    -	if ((error = _fget(td, fd, &fp, flags, needrights, haverightsp,
    -	    NULL, 0)) != 0)
    +	error = _fget(td, fd, &fp, flags, needrights, NULL);
    +	if (error)
     		return (error);
     	if (fp->f_vnode == NULL) {
     		error = EINVAL;
    @@ -2442,28 +2449,54 @@ int
     fgetvp(struct thread *td, int fd, cap_rights_t rights, struct vnode **vpp)
     {
     
    -	return (_fgetvp(td, fd, 0, rights, NULL, vpp));
    +	return (_fgetvp(td, fd, 0, rights, vpp));
     }
     
     int
    -fgetvp_rights(struct thread *td, int fd, cap_rights_t need, cap_rights_t *have,
    -    struct vnode **vpp)
    +fgetvp_rights(struct thread *td, int fd, cap_rights_t need,
    +    struct filecaps *havecaps, struct vnode **vpp)
     {
    -	return (_fgetvp(td, fd, 0, need, have, vpp));
    +	struct filedesc *fdp;
    +	struct file *fp;
    +#ifdef CAPABILITIES
    +	int error;
    +#endif
    +
    +	if (td == NULL || (fdp = td->td_proc->p_fd) == NULL)
    +		return (EBADF);
    +
    +	fp = fget_locked(fdp, fd);
    +	if (fp == NULL || fp->f_ops == &badfileops)
    +		return (EBADF);
    +
    +#ifdef CAPABILITIES
    +	error = cap_check(cap_rights(fdp, fd), need);
    +	if (error != 0)
    +		return (error);
    +#endif
    +
    +	if (fp->f_vnode == NULL)
    +		return (EINVAL);
    +
    +	*vpp = fp->f_vnode;
    +	vref(*vpp);
    +	filecaps_copy(&fdp->fd_ofiles[fd].fde_caps, havecaps);
    +
    +	return (0);
     }
     
     int
     fgetvp_read(struct thread *td, int fd, cap_rights_t rights, struct vnode **vpp)
     {
     
    -	return (_fgetvp(td, fd, FREAD, rights, NULL, vpp));
    +	return (_fgetvp(td, fd, FREAD, rights, vpp));
     }
     
     int
     fgetvp_exec(struct thread *td, int fd, cap_rights_t rights, struct vnode **vpp)
     {
     
    -	return (_fgetvp(td, fd, FEXEC, rights, NULL, vpp));
    +	return (_fgetvp(td, fd, FEXEC, rights, vpp));
     }
     
     #ifdef notyet
    @@ -2472,7 +2505,7 @@ fgetvp_write(struct thread *td, int fd, cap_rights_t rights,
         struct vnode **vpp)
     {
     
    -	return (_fgetvp(td, fd, FWRITE, rights, NULL, vpp));
    +	return (_fgetvp(td, fd, FWRITE, rights, vpp));
     }
     #endif
     
    @@ -2497,7 +2530,7 @@ fgetsock(struct thread *td, int fd, cap_rights_t rights, struct socket **spp,
     	*spp = NULL;
     	if (fflagp != NULL)
     		*fflagp = 0;
    -	if ((error = _fget(td, fd, &fp, 0, rights, NULL, NULL, 0)) != 0)
    +	if ((error = _fget(td, fd, &fp, 0, rights, NULL)) != 0)
     		return (error);
     	if (fp->f_type != DTYPE_SOCKET) {
     		error = ENOTSOCK;
    @@ -2533,9 +2566,6 @@ fputsock(struct socket *so)
     
     /*
      * Handle the last reference to a file being closed.
    - *
    - * No special capability handling here, as the capability's fo_close will run
    - * instead of the object here, and perform any necessary drop on the object.
      */
     int
     _fdrop(struct file *fp, struct thread *td)
    @@ -2612,7 +2642,8 @@ done2:
      * Duplicate the specified descriptor to a free descriptor.
      */
     int
    -dupfdopen(struct thread *td, struct filedesc *fdp, int dfd, int mode, int openerror, int *indxp)
    +dupfdopen(struct thread *td, struct filedesc *fdp, int dfd, int mode,
    +    int openerror, int *indxp)
     {
     	struct file *fp;
     	int error, indx;
    @@ -2656,18 +2687,17 @@ dupfdopen(struct thread *td, struct filedesc *fdp, int dfd, int mode, int opener
     			FILEDESC_XUNLOCK(fdp);
     			return (EACCES);
     		}
    -		fdp->fd_ofiles[indx] = fp;
    -		fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
     		fhold(fp);
    +		fdp->fd_ofiles[indx] = fdp->fd_ofiles[dfd];
    +		filecaps_copy(&fdp->fd_ofiles[dfd].fde_caps,
    +		    &fdp->fd_ofiles[indx].fde_caps);
     		break;
     	case ENXIO:
     		/*
     		 * Steal away the file pointer from dfd and stuff it into indx.
     		 */
    -		fdp->fd_ofiles[indx] = fp;
    -		fdp->fd_ofiles[dfd] = NULL;
    -		fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
    -		fdp->fd_ofileflags[dfd] = 0;
    +		fdp->fd_ofiles[indx] = fdp->fd_ofiles[dfd];
    +		bzero(&fdp->fd_ofiles[dfd], sizeof(fdp->fd_ofiles[dfd]));
     		fdunused(fdp, dfd);
     		break;
     	}
    @@ -2823,7 +2853,7 @@ sysctl_kern_file(SYSCTL_HANDLER_ARGS)
     			continue;
     		FILEDESC_SLOCK(fdp);
     		for (n = 0; fdp->fd_refcnt > 0 && n < fdp->fd_nfiles; ++n) {
    -			if ((fp = fdp->fd_ofiles[n]) == NULL)
    +			if ((fp = fdp->fd_ofiles[n].fde_file) == NULL)
     				continue;
     			xf.xf_fd = n;
     			xf.xf_file = fp;
    @@ -2935,7 +2965,7 @@ sysctl_kern_proc_ofiledesc(SYSCTL_HANDLER_ARGS)
     		export_vnode_for_osysctl(fdp->fd_jdir, KF_FD_TYPE_JAIL, kif,
     				fdp, req);
     	for (i = 0; i < fdp->fd_nfiles; i++) {
    -		if ((fp = fdp->fd_ofiles[i]) == NULL)
    +		if ((fp = fdp->fd_ofiles[i].fde_file) == NULL)
     			continue;
     		bzero(kif, sizeof(*kif));
     		kif->kf_structsize = sizeof(*kif);
    @@ -2945,21 +2975,6 @@ sysctl_kern_proc_ofiledesc(SYSCTL_HANDLER_ARGS)
     		shmfd = NULL;
     		kif->kf_fd = i;
     
    -#ifdef CAPABILITIES
    -		/*
    -		 * When reporting a capability, most fields will be from the
    -		 * underlying object, but do mark as a capability. With
    -		 * ofiledesc, we don't have a field to export the cap_rights_t,
    -		 * but we do with the new filedesc.
    -		 */
    -		if (fp->f_type == DTYPE_CAPABILITY) {
    -			kif->kf_flags |= KF_FLAG_CAPABILITY;
    -			(void)cap_funwrap(fp, 0, &fp);
    -		}
    -#else
    -		KASSERT(fp->f_type != DTYPE_CAPABILITY,
    -		    ("sysctl_kern_proc_ofiledesc: saw capability"));
    -#endif
     		switch (fp->f_type) {
     		case DTYPE_VNODE:
     			kif->kf_type = KF_TYPE_VNODE;
    @@ -3128,8 +3143,8 @@ CTASSERT(sizeof(struct kinfo_file) == KINFO_FILE_SIZE);
     
     static int
     export_fd_for_sysctl(void *data, int type, int fd, int fflags, int refcnt,
    -    int64_t offset, int fd_is_cap, cap_rights_t fd_cap_rights,
    -    struct kinfo_file *kif, struct sysctl_req *req)
    +    int64_t offset, cap_rights_t fd_cap_rights, struct kinfo_file *kif,
    +    struct sysctl_req *req)
     {
     	struct {
     		int	fflag;
    @@ -3191,10 +3206,7 @@ export_fd_for_sysctl(void *data, int type, int fd, int fflags, int refcnt,
     	for (i = 0; i < NFFLAGS; i++)
     		if (fflags & fflags_table[i].fflag)
     			kif->kf_flags |=  fflags_table[i].kf_fflag;
    -	if (fd_is_cap)
    -		kif->kf_flags |= KF_FLAG_CAPABILITY;
    -	if (fd_is_cap)
    -		kif->kf_cap_rights = fd_cap_rights;
    +	kif->kf_cap_rights = fd_cap_rights;
     	kif->kf_fd = fd;
     	kif->kf_type = type;
     	kif->kf_ref_count = refcnt;
    @@ -3222,7 +3234,7 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS)
     	int64_t offset;
     	void *data;
     	int error, i, *name;
    -	int fd_is_cap, type, refcnt, fflags;
    +	int type, refcnt, fflags;
     	cap_rights_t fd_cap_rights;
     
     	name = (int *)arg1;
    @@ -3252,13 +3264,13 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS)
     	kif = malloc(sizeof(*kif), M_TEMP, M_WAITOK);
     	if (tracevp != NULL)
     		export_fd_for_sysctl(tracevp, KF_TYPE_VNODE, KF_FD_TYPE_TRACE,
    -		    FREAD | FWRITE, -1, -1, 0, 0, kif, req);
    +		    FREAD | FWRITE, -1, -1, 0, kif, req);
     	if (textvp != NULL)
     		export_fd_for_sysctl(textvp, KF_TYPE_VNODE, KF_FD_TYPE_TEXT,
    -		    FREAD, -1, -1, 0, 0, kif, req);
    +		    FREAD, -1, -1, 0, kif, req);
     	if (cttyvp != NULL)
     		export_fd_for_sysctl(cttyvp, KF_TYPE_VNODE, KF_FD_TYPE_CTTY,
    -		    FREAD | FWRITE, -1, -1, 0, 0, kif, req);
    +		    FREAD | FWRITE, -1, -1, 0, kif, req);
     	if (fdp == NULL)
     		goto fail;
     	FILEDESC_SLOCK(fdp);
    @@ -3268,7 +3280,7 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS)
     		data = fdp->fd_cdir;
     		FILEDESC_SUNLOCK(fdp);
     		export_fd_for_sysctl(data, KF_TYPE_VNODE, KF_FD_TYPE_CWD,
    -		    FREAD, -1, -1, 0, 0, kif, req);
    +		    FREAD, -1, -1, 0, kif, req);
     		FILEDESC_SLOCK(fdp);
     	}
     	/* root directory */
    @@ -3277,7 +3289,7 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS)
     		data = fdp->fd_rdir;
     		FILEDESC_SUNLOCK(fdp);
     		export_fd_for_sysctl(data, KF_TYPE_VNODE, KF_FD_TYPE_ROOT,
    -		    FREAD, -1, -1, 0, 0, kif, req);
    +		    FREAD, -1, -1, 0, kif, req);
     		FILEDESC_SLOCK(fdp);
     	}
     	/* jail directory */
    @@ -3286,30 +3298,17 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS)
     		data = fdp->fd_jdir;
     		FILEDESC_SUNLOCK(fdp);
     		export_fd_for_sysctl(data, KF_TYPE_VNODE, KF_FD_TYPE_JAIL,
    -		    FREAD, -1, -1, 0, 0, kif, req);
    +		    FREAD, -1, -1, 0, kif, req);
     		FILEDESC_SLOCK(fdp);
     	}
     	for (i = 0; i < fdp->fd_nfiles; i++) {
    -		if ((fp = fdp->fd_ofiles[i]) == NULL)
    +		if ((fp = fdp->fd_ofiles[i].fde_file) == NULL)
     			continue;
     		data = NULL;
    -		fd_is_cap = 0;
    -		fd_cap_rights = 0;
    -
     #ifdef CAPABILITIES
    -		/*
    -		 * When reporting a capability, most fields will be from the
    -		 * underlying object, but do mark as a capability and export
    -		 * the capability rights mask.
    -		 */
    -		if (fp->f_type == DTYPE_CAPABILITY) {
    -			fd_is_cap = 1;
    -			fd_cap_rights = cap_rights(fp);
    -			(void)cap_funwrap(fp, 0, &fp);
    -		}
    +		fd_cap_rights = cap_rights(fdp, i);
     #else /* !CAPABILITIES */
    -		KASSERT(fp->f_type != DTYPE_CAPABILITY,
    -		    ("sysctl_kern_proc_filedesc: saw capability"));
    +		fd_cap_rights = 0;
     #endif
     		switch (fp->f_type) {
     		case DTYPE_VNODE:
    @@ -3385,7 +3384,7 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS)
     		if (type == KF_TYPE_VNODE || type == KF_TYPE_FIFO)
     			FILEDESC_SUNLOCK(fdp);
     		error = export_fd_for_sysctl(data, type, i, fflags, refcnt,
    -		    offset, fd_is_cap, fd_cap_rights, kif, req);
    +		    offset, fd_cap_rights, kif, req);
     		if (type == KF_TYPE_VNODE || type == KF_TYPE_FIFO)
     			FILEDESC_SLOCK(fdp);
     		if (error) {
    @@ -3644,7 +3643,7 @@ file_to_first_proc(struct file *fp)
     		if (fdp == NULL)
     			continue;
     		for (n = 0; n < fdp->fd_nfiles; n++) {
    -			if (fp == fdp->fd_ofiles[n])
    +			if (fp == fdp->fd_ofiles[n].fde_file)
     				return (p);
     		}
     	}
    @@ -3694,7 +3693,7 @@ DB_SHOW_COMMAND(files, db_show_files)
     		if ((fdp = p->p_fd) == NULL)
     			continue;
     		for (n = 0; n < fdp->fd_nfiles; ++n) {
    -			if ((fp = fdp->fd_ofiles[n]) == NULL)
    +			if ((fp = fdp->fd_ofiles[n].fde_file) == NULL)
     				continue;
     			db_print_file(fp, header);
     			header = 0;
    diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
    index 965ce31af77..7c0d2d67ded 100644
    --- a/sys/kern/kern_exec.c
    +++ b/sys/kern/kern_exec.c
    @@ -438,9 +438,6 @@ interpret:
     	} else {
     		AUDIT_ARG_FD(args->fd);
     		/*
    -		 * Some might argue that CAP_READ and/or CAP_MMAP should also
    -		 * be required here; such arguments will be entertained.
    -		 *
     		 * Descriptors opened only with O_EXEC or O_RDONLY are allowed.
     		 */
     		error = fgetvp_exec(td, args->fd, CAP_FEXECVE, &binvp);
    diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
    index 82f0344c829..5bd2daa7197 100644
    --- a/sys/kern/kern_exit.c
    +++ b/sys/kern/kern_exit.c
    @@ -297,7 +297,7 @@ exit1(struct thread *td, int rv)
     	 * Close open files and release open-file table.
     	 * This may block!
     	 */
    -	fdfree(td);
    +	fdescfree(td);
     
     	/*
     	 * If this thread tickled GEOM, we need to wait for the giggling to
    diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
    index 287d202eed9..b5a4934e244 100644
    --- a/sys/kern/kern_fork.c
    +++ b/sys/kern/kern_fork.c
    @@ -342,7 +342,7 @@ fork_norfproc(struct thread *td, int flags)
     	if (flags & RFCFDG) {
     		struct filedesc *fdtmp;
     		fdtmp = fdinit(td->td_proc->p_fd);
    -		fdfree(td);
    +		fdescfree(td);
     		p1->p_fd = fdtmp;
     	}
     
    diff --git a/sys/kern/sys_capability.c b/sys/kern/sys_capability.c
    index 6fb4feee559..ba168e93819 100644
    --- a/sys/kern/sys_capability.c
    +++ b/sys/kern/sys_capability.c
    @@ -1,11 +1,15 @@
     /*-
      * Copyright (c) 2008-2011 Robert N. M. Watson
      * Copyright (c) 2010-2011 Jonathan Anderson
    + * Copyright (c) 2012 FreeBSD Foundation
      * All rights reserved.
      *
      * This software was developed at the University of Cambridge Computer
      * Laboratory with support from a grant from Google, Inc.
      *
    + * Portions of this software were developed by Pawel Jakub Dawidek under
    + * sponsorship from the FreeBSD Foundation.
    + *
      * Redistribution and use in source and binary forms, with or without
      * modification, are permitted provided that the following conditions
      * are met:
    @@ -62,6 +66,7 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    +#include 
     #include 
     #include 
     #include 
    @@ -139,135 +144,99 @@ sys_cap_getmode(struct thread *td, struct cap_getmode_args *uap)
     
     FEATURE(security_capabilities, "Capsicum Capabilities");
     
    -/*
    - * struct capability describes a capability, and is hung off of its struct
    - * file f_data field.  cap_file and cap_rightss are static once hooked up, as
    - * neither the object it references nor the rights it encapsulates are
    - * permitted to change.
    - */
    -struct capability {
    -	struct file	*cap_object;	/* Underlying object's file. */
    -	struct file	*cap_file;	/* Back-pointer to cap's file. */
    -	cap_rights_t	 cap_rights;	/* Mask of rights on object. */
    -};
    -
    -/*
    - * Capabilities have a fileops vector, but in practice none should ever be
    - * called except for fo_close, as the capability will normally not be
    - * returned during a file descriptor lookup in the system call code.
    - */
    -static fo_rdwr_t capability_read;
    -static fo_rdwr_t capability_write;
    -static fo_truncate_t capability_truncate;
    -static fo_ioctl_t capability_ioctl;
    -static fo_poll_t capability_poll;
    -static fo_kqfilter_t capability_kqfilter;
    -static fo_stat_t capability_stat;
    -static fo_close_t capability_close;
    -static fo_chmod_t capability_chmod;
    -static fo_chown_t capability_chown;
    -
    -static struct fileops capability_ops = {
    -	.fo_read = capability_read,
    -	.fo_write = capability_write,
    -	.fo_truncate = capability_truncate,
    -	.fo_ioctl = capability_ioctl,
    -	.fo_poll = capability_poll,
    -	.fo_kqfilter = capability_kqfilter,
    -	.fo_stat = capability_stat,
    -	.fo_close = capability_close,
    -	.fo_chmod = capability_chmod,
    -	.fo_chown = capability_chown,
    -	.fo_flags = DFLAG_PASSABLE,
    -};
    -
    -static struct fileops capability_ops_unpassable = {
    -	.fo_read = capability_read,
    -	.fo_write = capability_write,
    -	.fo_truncate = capability_truncate,
    -	.fo_ioctl = capability_ioctl,
    -	.fo_poll = capability_poll,
    -	.fo_kqfilter = capability_kqfilter,
    -	.fo_stat = capability_stat,
    -	.fo_close = capability_close,
    -	.fo_chmod = capability_chmod,
    -	.fo_chown = capability_chown,
    -	.fo_flags = 0,
    -};
    -
    -static uma_zone_t capability_zone;
    -
    -static void
    -capability_init(void *dummy __unused)
    +static inline int
    +_cap_check(cap_rights_t have, cap_rights_t need, enum ktr_cap_fail_type type)
     {
     
    -	capability_zone = uma_zcreate("capability", sizeof(struct capability),
    -	    NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
    -	if (capability_zone == NULL)
    -		panic("capability_init: capability_zone not initialized");
    -}
    -SYSINIT(vfs, SI_SUB_VFS, SI_ORDER_ANY, capability_init, NULL);
     
    -/*
    - * Test whether a capability grants the requested rights.
    - */
    -static int
    -cap_check(struct capability *c, cap_rights_t rights)
    -{
    -
    -	if ((c->cap_rights | rights) != c->cap_rights) {
    +	if ((need & ~have) != 0) {
     #ifdef KTRACE
     		if (KTRPOINT(curthread, KTR_CAPFAIL))
    -			ktrcapfail(CAPFAIL_NOTCAPABLE, rights, c->cap_rights);
    +			ktrcapfail(type, need, have);
     #endif
     		return (ENOTCAPABLE);
     	}
     	return (0);
     }
     
    +/*
    + * Test whether a capability grants the requested rights.
    + */
    +int
    +cap_check(cap_rights_t have, cap_rights_t need)
    +{
    +
    +	return (_cap_check(have, need, CAPFAIL_NOTCAPABLE));
    +}
    +
    +/*
    + * Convert capability rights into VM access flags.
    + */
    +u_char
    +cap_rights_to_vmprot(cap_rights_t have)
    +{
    +	u_char maxprot;
    +
    +	maxprot = VM_PROT_NONE;
    +	if (have & CAP_MMAP_R)
    +		maxprot |= VM_PROT_READ;
    +	if (have & CAP_MMAP_W)
    +		maxprot |= VM_PROT_WRITE;
    +	if (have & CAP_MMAP_X)
    +		maxprot |= VM_PROT_EXECUTE;
    +
    +	return (maxprot);
    +}
    +
     /*
      * Extract rights from a capability for monitoring purposes -- not for use in
      * any other way, as we want to keep all capability permission evaluation in
      * this one file.
      */
     cap_rights_t
    -cap_rights(struct file *fp_cap)
    +cap_rights(struct filedesc *fdp, int fd)
     {
    -	struct capability *c;
     
    -	KASSERT(fp_cap->f_type == DTYPE_CAPABILITY,
    -	    ("cap_rights: !capability"));
    -
    -	c = fp_cap->f_data;
    -	return (c->cap_rights);
    +	return (fdp->fd_ofiles[fd].fde_rights);
     }
     
     /*
    - * System call to create a new capability reference to either an existing
    - * file object or an an existing capability.
    + * System call to limit rights of the given capability.
      */
     int
    -sys_cap_new(struct thread *td, struct cap_new_args *uap)
    +sys_cap_rights_limit(struct thread *td, struct cap_rights_limit_args *uap)
     {
    -	int error, capfd;
    -	int fd = uap->fd;
    -	struct file *fp;
    -	cap_rights_t rights = uap->rights;
    +	struct filedesc *fdp;
    +	cap_rights_t rights;
    +	int error, fd;
    +
    +	fd = uap->fd;
    +	rights = uap->rights;
     
     	AUDIT_ARG_FD(fd);
     	AUDIT_ARG_RIGHTS(rights);
    -	error = fget(td, fd, rights, &fp);
    -	if (error)
    -		return (error);
    -	AUDIT_ARG_FILE(td->td_proc, fp);
    -	error = kern_capwrap(td, fp, rights, &capfd);
    -	/*
    -	 * Release our reference to the file (kern_capwrap has held a reference
    -	 * for the filedesc array).
    -	 */
    -	fdrop(fp, td);
    -	if (error == 0)
    -		td->td_retval[0] = capfd;
    +
    +	if ((rights & ~CAP_ALL) != 0)
    +		return (EINVAL);
    +
    +	fdp = td->td_proc->p_fd;
    +	FILEDESC_XLOCK(fdp);
    +	if (fget_locked(fdp, fd) == NULL) {
    +		FILEDESC_XUNLOCK(fdp);
    +		return (EBADF);
    +	}
    +	error = _cap_check(cap_rights(fdp, fd), rights, CAPFAIL_INCREASE);
    +	if (error == 0) {
    +		fdp->fd_ofiles[fd].fde_rights = rights;
    +		if ((rights & CAP_IOCTL) == 0) {
    +			free(fdp->fd_ofiles[fd].fde_ioctls, M_TEMP);
    +			fdp->fd_ofiles[fd].fde_ioctls = NULL;
    +			fdp->fd_ofiles[fd].fde_nioctls = 0;
    +		}
    +		if ((rights & CAP_FCNTL) == 0)
    +			fdp->fd_ofiles[fd].fde_fcntls = 0;
    +	}
    +	FILEDESC_XUNLOCK(fdp);
     	return (error);
     }
     
    @@ -275,255 +244,372 @@ sys_cap_new(struct thread *td, struct cap_new_args *uap)
      * System call to query the rights mask associated with a capability.
      */
     int
    -sys_cap_getrights(struct thread *td, struct cap_getrights_args *uap)
    +sys_cap_rights_get(struct thread *td, struct cap_rights_get_args *uap)
     {
    -	struct capability *cp;
    -	struct file *fp;
    -	int error;
    +	struct filedesc *fdp;
    +	cap_rights_t rights;
    +	int fd;
     
    -	AUDIT_ARG_FD(uap->fd);
    -	error = fgetcap(td, uap->fd, &fp);
    -	if (error)
    -		return (error);
    -	cp = fp->f_data;
    -	error = copyout(&cp->cap_rights, uap->rightsp, sizeof(*uap->rightsp));
    -	fdrop(fp, td);
    +	fd = uap->fd;
    +
    +	AUDIT_ARG_FD(fd);
    +
    +	fdp = td->td_proc->p_fd;
    +	FILEDESC_SLOCK(fdp);
    +	if (fget_locked(fdp, fd) == NULL) {
    +		FILEDESC_SUNLOCK(fdp);
    +		return (EBADF);
    +	}
    +	rights = cap_rights(fdp, fd);
    +	FILEDESC_SUNLOCK(fdp);
    +	return (copyout(&rights, uap->rightsp, sizeof(*uap->rightsp)));
    +}
    +
    +/*
    + * Test whether a capability grants the given ioctl command.
    + * If descriptor doesn't have CAP_IOCTL, then ioctls list is empty and
    + * ENOTCAPABLE will be returned.
    + */
    +int
    +cap_ioctl_check(struct filedesc *fdp, int fd, u_long cmd)
    +{
    +	u_long *cmds;
    +	ssize_t ncmds;
    +	long i;
    +
    +	FILEDESC_LOCK_ASSERT(fdp);
    +	KASSERT(fd >= 0 && fd < fdp->fd_nfiles,
    +	    ("%s: invalid fd=%d", __func__, fd));
    +
    +	ncmds = fdp->fd_ofiles[fd].fde_nioctls;
    +	if (ncmds == -1)
    +		return (0);
    +
    +	cmds = fdp->fd_ofiles[fd].fde_ioctls;
    +	for (i = 0; i < ncmds; i++) {
    +		if (cmds[i] == cmd)
    +			return (0);
    +	}
    +
    +	return (ENOTCAPABLE);
    +}
    +
    +/*
    + * Check if the current ioctls list can be replaced by the new one.
    + */
    +static int
    +cap_ioctl_limit_check(struct filedesc *fdp, int fd, const u_long *cmds,
    +    size_t ncmds)
    +{
    +	u_long *ocmds;
    +	ssize_t oncmds;
    +	u_long i;
    +	long j;
    +
    +	oncmds = fdp->fd_ofiles[fd].fde_nioctls;
    +	if (oncmds == -1)
    +		return (0);
    +	if (oncmds < (ssize_t)ncmds)
    +		return (ENOTCAPABLE);
    +
    +	ocmds = fdp->fd_ofiles[fd].fde_ioctls;
    +	for (i = 0; i < ncmds; i++) {
    +		for (j = 0; j < oncmds; j++) {
    +			if (cmds[i] == ocmds[j])
    +				break;
    +		}
    +		if (j == oncmds)
    +			return (ENOTCAPABLE);
    +	}
    +
    +	return (0);
    +}
    +
    +int
    +sys_cap_ioctls_limit(struct thread *td, struct cap_ioctls_limit_args *uap)
    +{
    +	struct filedesc *fdp;
    +	u_long *cmds, *ocmds;
    +	size_t ncmds;
    +	int error, fd;
    +
    +	fd = uap->fd;
    +	ncmds = uap->ncmds;
    +
    +	AUDIT_ARG_FD(fd);
    +
    +	if (ncmds > 256)	/* XXX: Is 256 sane? */
    +		return (EINVAL);
    +
    +	if (ncmds == 0) {
    +		cmds = NULL;
    +	} else {
    +		cmds = malloc(sizeof(cmds[0]) * ncmds, M_TEMP, M_WAITOK);
    +		error = copyin(uap->cmds, cmds, sizeof(cmds[0]) * ncmds);
    +		if (error != 0) {
    +			free(cmds, M_TEMP);
    +			return (error);
    +		}
    +	}
    +
    +	fdp = td->td_proc->p_fd;
    +	FILEDESC_XLOCK(fdp);
    +
    +	if (fget_locked(fdp, fd) == NULL) {
    +		error = EBADF;
    +		goto out;
    +	}
    +
    +	error = cap_ioctl_limit_check(fdp, fd, cmds, ncmds);
    +	if (error != 0)
    +		goto out;
    +
    +	ocmds = fdp->fd_ofiles[fd].fde_ioctls;
    +	fdp->fd_ofiles[fd].fde_ioctls = cmds;
    +	fdp->fd_ofiles[fd].fde_nioctls = ncmds;
    +
    +	cmds = ocmds;
    +	error = 0;
    +out:
    +	FILEDESC_XUNLOCK(fdp);
    +	free(cmds, M_TEMP);
    +	return (error);
    +}
    +
    +int
    +sys_cap_ioctls_get(struct thread *td, struct cap_ioctls_get_args *uap)
    +{
    +	struct filedesc *fdp;
    +	struct filedescent *fdep;
    +	u_long *cmds;
    +	size_t maxcmds;
    +	int error, fd;
    +
    +	fd = uap->fd;
    +	cmds = uap->cmds;
    +	maxcmds = uap->maxcmds;
    +
    +	AUDIT_ARG_FD(fd);
    +
    +	fdp = td->td_proc->p_fd;
    +	FILEDESC_SLOCK(fdp);
    +
    +	if (fget_locked(fdp, fd) == NULL) {
    +		error = EBADF;
    +		goto out;
    +	}
    +
    +	/*
    +	 * If all ioctls are allowed (fde_nioctls == -1 && fde_ioctls == NULL)
    +	 * the only sane thing we can do is to not populate the given array and
    +	 * return CAP_IOCTLS_ALL.
    +	 */
    +
    +	fdep = &fdp->fd_ofiles[fd];
    +	if (cmds != NULL && fdep->fde_ioctls != NULL) {
    +		error = copyout(fdep->fde_ioctls, cmds,
    +		    sizeof(cmds[0]) * MIN(fdep->fde_nioctls, maxcmds));
    +		if (error != 0)
    +			goto out;
    +	}
    +	if (fdep->fde_nioctls == -1)
    +		td->td_retval[0] = CAP_IOCTLS_ALL;
    +	else
    +		td->td_retval[0] = fdep->fde_nioctls;
    +
    +	error = 0;
    +out:
    +	FILEDESC_SUNLOCK(fdp);
     	return (error);
     }
     
     /*
    - * Create a capability to wrap around an existing file.
    + * Test whether a capability grants the given fcntl command.
      */
     int
    -kern_capwrap(struct thread *td, struct file *fp, cap_rights_t rights,
    -    int *capfdp)
    +cap_fcntl_check(struct filedesc *fdp, int fd, int cmd)
     {
    -	struct capability *cp, *cp_old;
    -	struct file *fp_object, *fcapp;
    -	int error;
    +	uint32_t fcntlcap;
     
    -	if ((rights | CAP_MASK_VALID) != CAP_MASK_VALID)
    +	KASSERT(fd >= 0 && fd < fdp->fd_nfiles,
    +	    ("%s: invalid fd=%d", __func__, fd));
    +
    +	fcntlcap = (1 << cmd);
    +	KASSERT((CAP_FCNTL_ALL & fcntlcap) != 0,
    +	    ("Unsupported fcntl=%d.", cmd));
    +
    +	if ((fdp->fd_ofiles[fd].fde_fcntls & fcntlcap) != 0)
    +		return (0);
    +
    +	return (ENOTCAPABLE);
    +}
    +
    +int
    +sys_cap_fcntls_limit(struct thread *td, struct cap_fcntls_limit_args *uap)
    +{
    +	struct filedesc *fdp;
    +	uint32_t fcntlrights;
    +	int fd;
    +
    +	fd = uap->fd;
    +	fcntlrights = uap->fcntlrights;
    +
    +	AUDIT_ARG_FD(fd);
    +	AUDIT_ARG_FCNTL_RIGHTS(fcntlrights);
    +
    +	if ((fcntlrights & ~CAP_FCNTL_ALL) != 0)
     		return (EINVAL);
     
    -	/*
    -	 * If a new capability is being derived from an existing capability,
    -	 * then the new capability rights must be a subset of the existing
    -	 * rights.
    -	 */
    -	if (fp->f_type == DTYPE_CAPABILITY) {
    -		cp_old = fp->f_data;
    -		if ((cp_old->cap_rights | rights) != cp_old->cap_rights) {
    -#ifdef KTRACE
    -			if (KTRPOINT(curthread, KTR_CAPFAIL))
    -				ktrcapfail(CAPFAIL_INCREASE,
    -				    rights, cp_old->cap_rights);
    -#endif
    -			return (ENOTCAPABLE);
    -		}
    +	fdp = td->td_proc->p_fd;
    +	FILEDESC_XLOCK(fdp);
    +
    +	if (fget_locked(fdp, fd) == NULL) {
    +		FILEDESC_XUNLOCK(fdp);
    +		return (EBADF);
     	}
     
    -	/*
    -	 * Allocate a new file descriptor to hang the capability off of.
    -	 */
    -	error = falloc(td, &fcapp, capfdp, fp->f_flag);
    -	if (error)
    -		return (error);
    +	if ((fcntlrights & ~fdp->fd_ofiles[fd].fde_fcntls) != 0) {
    +		FILEDESC_XUNLOCK(fdp);
    +		return (ENOTCAPABLE);
    +	}
     
    -	/*
    -	 * Rather than nesting capabilities, directly reference the object an
    -	 * existing capability references.  There's nothing else interesting
    -	 * to preserve for future use, as we've incorporated the previous
    -	 * rights mask into the new one.  This prevents us from having to
    -	 * deal with capability chains.
    -	 */
    -	if (fp->f_type == DTYPE_CAPABILITY)
    -		fp_object = ((struct capability *)fp->f_data)->cap_object;
    -	else
    -		fp_object = fp;
    -	fhold(fp_object);
    -	cp = uma_zalloc(capability_zone, M_WAITOK | M_ZERO);
    -	cp->cap_rights = rights;
    -	cp->cap_object = fp_object;
    -	cp->cap_file = fcapp;
    -	if (fp->f_flag & DFLAG_PASSABLE)
    -		finit(fcapp, fp->f_flag, DTYPE_CAPABILITY, cp,
    -		    &capability_ops);
    -	else
    -		finit(fcapp, fp->f_flag, DTYPE_CAPABILITY, cp,
    -		    &capability_ops_unpassable);
    +	fdp->fd_ofiles[fd].fde_fcntls = fcntlrights;
    +	FILEDESC_XUNLOCK(fdp);
     
    -	/*
    -	 * Release our private reference (the proc filedesc still has one).
    -	 */
    -	fdrop(fcapp, td);
     	return (0);
     }
     
    -/*
    - * Given a file descriptor, test it against a capability rights mask and then
    - * return the file descriptor on which to actually perform the requested
    - * operation.  As long as the reference to fp_cap remains valid, the returned
    - * pointer in *fp will remain valid, so no extra reference management is
    - * required, and the caller should fdrop() fp_cap as normal when done with
    - * both.
    - */
     int
    -cap_funwrap(struct file *fp_cap, cap_rights_t rights, struct file **fpp)
    +sys_cap_fcntls_get(struct thread *td, struct cap_fcntls_get_args *uap)
     {
    -	struct capability *c;
    -	int error;
    +	struct filedesc *fdp;
    +	uint32_t rights;
    +	int fd;
     
    -	if (fp_cap->f_type != DTYPE_CAPABILITY) {
    -		*fpp = fp_cap;
    -		return (0);
    +	fd = uap->fd;
    +
    +	AUDIT_ARG_FD(fd);
    +
    +	fdp = td->td_proc->p_fd;
    +	FILEDESC_SLOCK(fdp);
    +	if (fget_locked(fdp, fd) == NULL) {
    +		FILEDESC_SUNLOCK(fdp);
    +		return (EBADF);
     	}
    -	c = fp_cap->f_data;
    -	error = cap_check(c, rights);
    -	if (error)
    -		return (error);
    -	*fpp = c->cap_object;
    -	return (0);
    +	rights = fdp->fd_ofiles[fd].fde_fcntls;
    +	FILEDESC_SUNLOCK(fdp);
    +
    +	return (copyout(&rights, uap->fcntlrightsp, sizeof(rights)));
     }
     
     /*
    - * Slightly different routine for memory mapping file descriptors: unwrap the
    - * capability and check CAP_MMAP, but also return a bitmask representing the
    - * maximum mapping rights the capability allows on the object.
    + * For backward compatibility.
      */
     int
    -cap_funwrap_mmap(struct file *fp_cap, cap_rights_t rights, u_char *maxprotp,
    -    struct file **fpp)
    +sys_cap_new(struct thread *td, struct cap_new_args *uap)
     {
    -	struct capability *c;
    -	u_char maxprot;
    -	int error;
    +	struct filedesc *fdp;
    +	cap_rights_t rights;
    +	register_t newfd;
    +	int error, fd;
     
    -	if (fp_cap->f_type != DTYPE_CAPABILITY) {
    -		*fpp = fp_cap;
    -		*maxprotp = VM_PROT_ALL;
    -		return (0);
    +	fd = uap->fd;
    +	rights = uap->rights;
    +
    +	AUDIT_ARG_FD(fd);
    +	AUDIT_ARG_RIGHTS(rights);
    +
    +	if ((rights & ~CAP_ALL) != 0)
    +		return (EINVAL);
    +
    +	fdp = td->td_proc->p_fd;
    +	FILEDESC_SLOCK(fdp);
    +	if (fget_locked(fdp, fd) == NULL) {
    +		FILEDESC_SUNLOCK(fdp);
    +		return (EBADF);
     	}
    -	c = fp_cap->f_data;
    -	error = cap_check(c, rights | CAP_MMAP);
    -	if (error)
    +	error = _cap_check(cap_rights(fdp, fd), rights, CAPFAIL_INCREASE);
    +	FILEDESC_SUNLOCK(fdp);
    +	if (error != 0)
     		return (error);
    -	*fpp = c->cap_object;
    -	maxprot = 0;
    -	if (c->cap_rights & CAP_READ)
    -		maxprot |= VM_PROT_READ;
    -	if (c->cap_rights & CAP_WRITE)
    -		maxprot |= VM_PROT_WRITE;
    -	if (c->cap_rights & CAP_MAPEXEC)
    -		maxprot |= VM_PROT_EXECUTE;
    -	*maxprotp = maxprot;
    +
    +	error = do_dup(td, 0, fd, 0, &newfd);
    +	if (error != 0)
    +		return (error);
    +
    +	FILEDESC_XLOCK(fdp);
    +	/*
    +	 * We don't really care about the race between checking capability
    +	 * rights for the source descriptor and now. If capability rights
    +	 * were ok at that earlier point, the process had this descriptor
    +	 * with those rights, so we don't increase them in security sense,
    +	 * the process might have done the cap_new(2) a bit earlier to get
    +	 * the same effect.
    +	 */
    +	fdp->fd_ofiles[newfd].fde_rights = rights;
    +	if ((rights & CAP_IOCTL) == 0) {
    +		free(fdp->fd_ofiles[newfd].fde_ioctls, M_TEMP);
    +		fdp->fd_ofiles[newfd].fde_ioctls = NULL;
    +		fdp->fd_ofiles[newfd].fde_nioctls = 0;
    +	}
    +	if ((rights & CAP_FCNTL) == 0)
    +		fdp->fd_ofiles[newfd].fde_fcntls = 0;
    +	FILEDESC_XUNLOCK(fdp);
    +
    +	td->td_retval[0] = newfd;
    +
     	return (0);
     }
     
    -/*
    - * When a capability is closed, simply drop the reference on the underlying
    - * object and free the capability.  fdrop() will handle the case where the
    - * underlying object also needs to close, and the caller will have already
    - * performed any object-specific lock or mqueue handling.
    - */
    -static int
    -capability_close(struct file *fp, struct thread *td)
    -{
    -	struct capability *c;
    -	struct file *fp_object;
    -
    -	KASSERT(fp->f_type == DTYPE_CAPABILITY,
    -	    ("capability_close: !capability"));
    -
    -	c = fp->f_data;
    -	fp->f_ops = &badfileops;
    -	fp->f_data = NULL;
    -	fp_object = c->cap_object;
    -	uma_zfree(capability_zone, c);
    -	return (fdrop(fp_object, td));
    -}
    -
    -/*
    - * In general, file descriptor operations should never make it to the
    - * capability, only the underlying file descriptor operation vector, so panic
    - * if we do turn up here.
    - */
    -static int
    -capability_read(struct file *fp, struct uio *uio, struct ucred *active_cred,
    -    int flags, struct thread *td)
    -{
    -
    -	panic("capability_read");
    -}
    -
    -static int
    -capability_write(struct file *fp, struct uio *uio, struct ucred *active_cred,
    -    int flags, struct thread *td)
    -{
    -
    -	panic("capability_write");
    -}
    -
    -static int
    -capability_truncate(struct file *fp, off_t length, struct ucred *active_cred,
    -    struct thread *td)
    -{
    -
    -	panic("capability_truncate");
    -}
    -
    -static int
    -capability_ioctl(struct file *fp, u_long com, void *data,
    -    struct ucred *active_cred, struct thread *td)
    -{
    -
    -	panic("capability_ioctl");
    -}
    -
    -static int
    -capability_poll(struct file *fp, int events, struct ucred *active_cred,
    -    struct thread *td)
    -{
    -
    -	panic("capability_poll");
    -}
    -
    -static int
    -capability_kqfilter(struct file *fp, struct knote *kn)
    -{
    -
    -	panic("capability_kqfilter");
    -}
    -
    -static int
    -capability_stat(struct file *fp, struct stat *sb, struct ucred *active_cred,
    -    struct thread *td)
    -{
    -
    -	panic("capability_stat");
    -}
    -
    -int
    -capability_chmod(struct file *fp, mode_t mode, struct ucred *active_cred,
    -    struct thread *td)
    -{
    -
    -	panic("capability_chmod");
    -}
    -
    -int
    -capability_chown(struct file *fp, uid_t uid, gid_t gid,
    -    struct ucred *active_cred, struct thread *td)
    -{
    -
    -	panic("capability_chown");
    -}
    -
     #else /* !CAPABILITIES */
     
     /*
      * Stub Capability functions for when options CAPABILITIES isn't compiled
      * into the kernel.
      */
    +
    +int
    +sys_cap_rights_limit(struct thread *td, struct cap_rights_limit_args *uap)
    +{
    +
    +	return (ENOSYS);
    +}
    +
    +int
    +sys_cap_rights_get(struct thread *td, struct cap_rights_get_args *uap)
    +{
    +
    +	return (ENOSYS);
    +}
    +
    +int
    +sys_cap_ioctls_limit(struct thread *td, struct cap_ioctls_limit_args *uap)
    +{
    +
    +	return (ENOSYS);
    +}
    +
    +int
    +sys_cap_ioctls_get(struct thread *td, struct cap_ioctls_get_args *uap)
    +{
    +
    +	return (ENOSYS);
    +}
    +
    +int
    +sys_cap_fcntls_limit(struct thread *td, struct cap_fcntls_limit_args *uap)
    +{
    +
    +	return (ENOSYS);
    +}
    +
    +int
    +sys_cap_fcntls_get(struct thread *td, struct cap_fcntls_get_args *uap)
    +{
    +
    +	return (ENOSYS);
    +}
    +
     int
     sys_cap_new(struct thread *td, struct cap_new_args *uap)
     {
    @@ -531,35 +617,4 @@ sys_cap_new(struct thread *td, struct cap_new_args *uap)
     	return (ENOSYS);
     }
     
    -int
    -sys_cap_getrights(struct thread *td, struct cap_getrights_args *uap)
    -{
    -
    -	return (ENOSYS);
    -}
    -
    -int
    -cap_funwrap(struct file *fp_cap, cap_rights_t rights, struct file **fpp)
    -{
    -
    -	KASSERT(fp_cap->f_type != DTYPE_CAPABILITY,
    -	    ("cap_funwrap: saw capability"));
    -
    -	*fpp = fp_cap;
    -	return (0);
    -}
    -
    -int
    -cap_funwrap_mmap(struct file *fp_cap, cap_rights_t rights, u_char *maxprotp,
    -    struct file **fpp)
    -{
    -
    -	KASSERT(fp_cap->f_type != DTYPE_CAPABILITY,
    -	    ("cap_funwrap_mmap: saw capability"));
    -
    -	*fpp = fp_cap;
    -	*maxprotp = VM_PROT_ALL;
    -	return (0);
    -}
    -
     #endif /* CAPABILITIES */
    diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c
    index b97ff7f5ea2..39f33f3af6f 100644
    --- a/sys/kern/sys_generic.c
    +++ b/sys/kern/sys_generic.c
    @@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    +#include 
     #include 
     #include 
     #include 
    @@ -244,7 +245,7 @@ kern_readv(struct thread *td, int fd, struct uio *auio)
     	struct file *fp;
     	int error;
     
    -	error = fget_read(td, fd, CAP_READ | CAP_SEEK, &fp);
    +	error = fget_read(td, fd, CAP_READ, &fp);
     	if (error)
     		return (error);
     	error = dofileread(td, fd, fp, auio, (off_t)-1, 0);
    @@ -287,7 +288,7 @@ kern_preadv(td, fd, auio, offset)
     	struct file *fp;
     	int error;
     
    -	error = fget_read(td, fd, CAP_READ, &fp);
    +	error = fget_read(td, fd, CAP_PREAD, &fp);
     	if (error)
     		return (error);
     	if (!(fp->f_ops->fo_flags & DFLAG_SEEKABLE))
    @@ -453,7 +454,7 @@ kern_writev(struct thread *td, int fd, struct uio *auio)
     	struct file *fp;
     	int error;
     
    -	error = fget_write(td, fd, CAP_WRITE | CAP_SEEK, &fp);
    +	error = fget_write(td, fd, CAP_WRITE, &fp);
     	if (error)
     		return (error);
     	error = dofilewrite(td, fd, fp, auio, (off_t)-1, 0);
    @@ -496,7 +497,7 @@ kern_pwritev(td, fd, auio, offset)
     	struct file *fp;
     	int error;
     
    -	error = fget_write(td, fd, CAP_WRITE, &fp);
    +	error = fget_write(td, fd, CAP_PWRITE, &fp);
     	if (error)
     		return (error);
     	if (!(fp->f_ops->fo_flags & DFLAG_SEEKABLE))
    @@ -704,28 +705,60 @@ kern_ioctl(struct thread *td, int fd, u_long com, caddr_t data)
     {
     	struct file *fp;
     	struct filedesc *fdp;
    -	int error;
    -	int tmp;
    +	int error, tmp, locked;
     
     	AUDIT_ARG_FD(fd);
     	AUDIT_ARG_CMD(com);
    -	if ((error = fget(td, fd, CAP_IOCTL, &fp)) != 0)
    -		return (error);
    -	if ((fp->f_flag & (FREAD | FWRITE)) == 0) {
    -		fdrop(fp, td);
    -		return (EBADF);
    -	}
    +
     	fdp = td->td_proc->p_fd;
    +
     	switch (com) {
     	case FIONCLEX:
    -		FILEDESC_XLOCK(fdp);
    -		fdp->fd_ofileflags[fd] &= ~UF_EXCLOSE;
    -		FILEDESC_XUNLOCK(fdp);
    -		goto out;
     	case FIOCLEX:
     		FILEDESC_XLOCK(fdp);
    -		fdp->fd_ofileflags[fd] |= UF_EXCLOSE;
    -		FILEDESC_XUNLOCK(fdp);
    +		locked = LA_XLOCKED;
    +		break;
    +	default:
    +#ifdef CAPABILITIES
    +		FILEDESC_SLOCK(fdp);
    +		locked = LA_SLOCKED;
    +#else
    +		locked = LA_UNLOCKED;
    +#endif
    +		break;
    +	}
    +
    +#ifdef CAPABILITIES
    +	if ((fp = fget_locked(fdp, fd)) == NULL) {
    +		error = EBADF;
    +		goto out;
    +	}
    +	if ((error = cap_ioctl_check(fdp, fd, com)) != 0) {
    +		fp = NULL;	/* fhold() was not called yet */
    +		goto out;
    +	}
    +	fhold(fp);
    +	if (locked == LA_SLOCKED) {
    +		FILEDESC_SUNLOCK(fdp);
    +		locked = LA_UNLOCKED;
    +	}
    +#else
    +	if ((error = fget(td, fd, CAP_IOCTL, &fp)) != 0) {
    +		fp = NULL;
    +		goto out;
    +	}
    +#endif
    +	if ((fp->f_flag & (FREAD | FWRITE)) == 0) {
    +		error = EBADF;
    +		goto out;
    +	}
    +
    +	switch (com) {
    +	case FIONCLEX:
    +		fdp->fd_ofiles[fd].fde_flags &= ~UF_EXCLOSE;
    +		goto out;
    +	case FIOCLEX:
    +		fdp->fd_ofiles[fd].fde_flags |= UF_EXCLOSE;
     		goto out;
     	case FIONBIO:
     		if ((tmp = *(int *)data))
    @@ -745,7 +778,21 @@ kern_ioctl(struct thread *td, int fd, u_long com, caddr_t data)
     
     	error = fo_ioctl(fp, com, data, td->td_ucred, td);
     out:
    -	fdrop(fp, td);
    +	switch (locked) {
    +	case LA_XLOCKED:
    +		FILEDESC_XUNLOCK(fdp);
    +		break;
    +#ifdef CAPABILITIES
    +	case LA_SLOCKED:
    +		FILEDESC_SUNLOCK(fdp);
    +		break;
    +#endif
    +	default:
    +		FILEDESC_UNLOCK_ASSERT(fdp);
    +		break;
    +	}
    +	if (fp != NULL)
    +		fdrop(fp, td);
     	return (error);
     }
     
    @@ -1130,32 +1177,8 @@ selsetbits(fd_mask **ibits, fd_mask **obits, int idx, fd_mask bit, int events)
     static __inline int
     getselfd_cap(struct filedesc *fdp, int fd, struct file **fpp)
     {
    -	struct file *fp;
    -#ifdef CAPABILITIES
    -	struct file *fp_fromcap;
    -	int error;
    -#endif
     
    -	if ((fp = fget_unlocked(fdp, fd)) == NULL)
    -		return (EBADF);
    -#ifdef CAPABILITIES
    -	/*
    -	 * If the file descriptor is for a capability, test rights and use
    -	 * the file descriptor references by the capability.
    -	 */
    -	error = cap_funwrap(fp, CAP_POLL_EVENT, &fp_fromcap);
    -	if (error) {
    -		fdrop(fp, curthread);
    -		return (error);
    -	}
    -	if (fp != fp_fromcap) {
    -		fhold(fp_fromcap);
    -		fdrop(fp, curthread);
    -		fp = fp_fromcap;
    -	}
    -#endif /* CAPABILITIES */
    -	*fpp = fp;
    -	return (0);
    +	return (fget_unlocked(fdp, fd, CAP_POLL_EVENT, 0, fpp, NULL));
     }
     
     /*
    @@ -1349,13 +1372,14 @@ pollrescan(struct thread *td)
     		/* If the selinfo wasn't cleared the event didn't fire. */
     		if (si != NULL)
     			continue;
    -		fp = fdp->fd_ofiles[fd->fd];
    +		fp = fdp->fd_ofiles[fd->fd].fde_file;
     #ifdef CAPABILITIES
    -		if ((fp == NULL)
    -		    || (cap_funwrap(fp, CAP_POLL_EVENT, &fp) != 0)) {
    +		if (fp == NULL ||
    +		    cap_check(cap_rights(fdp, fd->fd), CAP_POLL_EVENT) != 0)
     #else
    -		if (fp == NULL) {
    +		if (fp == NULL)
     #endif
    +		{
     			fd->revents = POLLNVAL;
     			n++;
     			continue;
    @@ -1408,9 +1432,8 @@ pollscan(td, fds, nfd)
     	u_int nfd;
     {
     	struct filedesc *fdp = td->td_proc->p_fd;
    -	int i;
     	struct file *fp;
    -	int n = 0;
    +	int i, n = 0;
     
     	FILEDESC_SLOCK(fdp);
     	for (i = 0; i < nfd; i++, fds++) {
    @@ -1420,13 +1443,15 @@ pollscan(td, fds, nfd)
     		} else if (fds->fd < 0) {
     			fds->revents = 0;
     		} else {
    -			fp = fdp->fd_ofiles[fds->fd];
    +			fp = fdp->fd_ofiles[fds->fd].fde_file;
     #ifdef CAPABILITIES
    -			if ((fp == NULL)
    -			    || (cap_funwrap(fp, CAP_POLL_EVENT, &fp) != 0)) {
    +			if (fp == NULL ||
    +			    cap_check(cap_rights(fdp, fds->fd),
    +			    CAP_POLL_EVENT) != 0)
     #else
    -			if (fp == NULL) {
    +			if (fp == NULL)
     #endif
    +			{
     				fds->revents = POLLNVAL;
     				n++;
     			} else {
    diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
    index 148dea3e499..1a890104c56 100644
    --- a/sys/kern/syscalls.master
    +++ b/sys/kern/syscalls.master
    @@ -917,7 +917,7 @@
     				    struct shmid_ds *buf); }
     513	AUE_LPATHCONF	STD	{ int lpathconf(char *path, int name); }
     514	AUE_CAP_NEW	STD	{ int cap_new(int fd, uint64_t rights); }
    -515	AUE_CAP_GETRIGHTS	STD	{ int cap_getrights(int fd, \
    +515	AUE_CAP_RIGHTS_GET	STD	{ int cap_rights_get(int fd, \
     				    uint64_t *rightsp); }
     516	AUE_CAP_ENTER	STD	{ int cap_enter(void); }
     517	AUE_CAP_GETMODE	STD	{ int cap_getmode(u_int *modep); }
    @@ -955,5 +955,15 @@
     				    int *status, int options, \
     				    struct __wrusage *wrusage, \
     				    siginfo_t *info); }
    +533	AUE_CAP_RIGHTS_LIMIT	STD	{ int cap_rights_limit(int fd, \
    +					    uint64_t rights); }
    +534	AUE_CAP_IOCTLS_LIMIT	STD	{ int cap_ioctls_limit(int fd, \
    +					    const u_long *cmds, size_t ncmds); }
    +535	AUE_CAP_IOCTLS_GET	STD	{ ssize_t cap_ioctls_get(int fd, \
    +					    u_long *cmds, size_t maxcmds); }
    +536	AUE_CAP_FCNTLS_LIMIT	STD	{ int cap_fcntls_limit(int fd, \
    +					    uint32_t fcntlrights); }
    +537	AUE_CAP_FCNTLS_GET	STD	{ int cap_fcntls_get(int fd, \
    +					    uint32_t *fcntlrightsp); }
     ; Please copy any additions and changes to the following compatability tables:
     ; sys/compat/freebsd32/syscalls.master
    diff --git a/sys/kern/tty.c b/sys/kern/tty.c
    index 5c7b7537b45..02eccd7ca0f 100644
    --- a/sys/kern/tty.c
    +++ b/sys/kern/tty.c
    @@ -1840,23 +1840,15 @@ ttyhook_register(struct tty **rtp, struct proc *p, int fd,
     	int error, ref;
     
     	/* Validate the file descriptor. */
    -	if ((fdp = p->p_fd) == NULL)
    -		return (EBADF);
    -
    -	fp = fget_unlocked(fdp, fd);
    -	if (fp == NULL)
    -		return (EBADF);
    +	fdp = p->p_fd;
    +	error = fget_unlocked(fdp, fd, CAP_TTYHOOK, 0, &fp, NULL);
    +	if (error != 0)
    +		return (error);
     	if (fp->f_ops == &badfileops) {
     		error = EBADF;
     		goto done1;
     	}
     
    -#ifdef CAPABILITIES
    -	error = cap_funwrap(fp, CAP_TTYHOOK, &fp);
    -	if (error)
    -		goto done1;
    -#endif
    -
     	/*
     	 * Make sure the vnode is bound to a character device.
     	 * Unlocked check for the vnode type is ok there, because we
    diff --git a/sys/kern/uipc_mqueue.c b/sys/kern/uipc_mqueue.c
    index 9da464ce637..2d18e77dc3e 100644
    --- a/sys/kern/uipc_mqueue.c
    +++ b/sys/kern/uipc_mqueue.c
    @@ -45,6 +45,7 @@
     #include 
     __FBSDID("$FreeBSD$");
     
    +#include "opt_capsicum.h"
     #include "opt_compat.h"
     
     #include 
    @@ -2032,8 +2033,8 @@ kern_kmq_open(struct thread *td, const char *upath, int flags, mode_t mode,
     	    &mqueueops);
     
     	FILEDESC_XLOCK(fdp);
    -	if (fdp->fd_ofiles[fd] == fp)
    -		fdp->fd_ofileflags[fd] |= UF_EXCLOSE;
    +	if (fdp->fd_ofiles[fd].fde_file == fp)
    +		fdp->fd_ofiles[fd].fde_flags |= UF_EXCLOSE;
     	FILEDESC_XUNLOCK(fdp);
     	td->td_retval[0] = fd;
     	fdrop(fp, td);
    @@ -2275,11 +2276,13 @@ again:
     		error = EBADF;
     		goto out;
     	}
    -	error = cap_funwrap(fp2, CAP_POLL_EVENT, &fp2);
    +#ifdef CAPABILITIES
    +	error = cap_check(cap_rights(fdp, uap->mqd), CAP_POLL_EVENT);
     	if (error) {
     		FILEDESC_SUNLOCK(fdp);
     		goto out;
     	}
    +#endif
     	if (fp2 != fp) {
     		FILEDESC_SUNLOCK(fdp);
     		error = EBADF;
    diff --git a/sys/kern/uipc_sem.c b/sys/kern/uipc_sem.c
    index c219844f4fa..2de34092385 100644
    --- a/sys/kern/uipc_sem.c
    +++ b/sys/kern/uipc_sem.c
    @@ -579,8 +579,8 @@ ksem_create(struct thread *td, const char *name, semid_t *semidp, mode_t mode,
     	finit(fp, FREAD | FWRITE, DTYPE_SEM, ks, &ksem_ops);
     
     	FILEDESC_XLOCK(fdp);
    -	if (fdp->fd_ofiles[fd] == fp)
    -		fdp->fd_ofileflags[fd] |= UF_EXCLOSE;
    +	if (fdp->fd_ofiles[fd].fde_file == fp)
    +		fdp->fd_ofiles[fd].fde_flags |= UF_EXCLOSE;
     	FILEDESC_XUNLOCK(fdp);
     	fdrop(fp, td);
     
    diff --git a/sys/kern/uipc_shm.c b/sys/kern/uipc_shm.c
    index 7f75bdc4a28..0cbb8b309f6 100644
    --- a/sys/kern/uipc_shm.c
    +++ b/sys/kern/uipc_shm.c
    @@ -629,8 +629,8 @@ sys_shm_open(struct thread *td, struct shm_open_args *uap)
     	finit(fp, FFLAGS(uap->flags & O_ACCMODE), DTYPE_SHM, shmfd, &shm_ops);
     
     	FILEDESC_XLOCK(fdp);
    -	if (fdp->fd_ofiles[fd] == fp)
    -		fdp->fd_ofileflags[fd] |= UF_EXCLOSE;
    +	if (fdp->fd_ofiles[fd].fde_file == fp)
    +		fdp->fd_ofiles[fd].fde_flags |= UF_EXCLOSE;
     	FILEDESC_XUNLOCK(fdp);
     	td->td_retval[0] = fd;
     	fdrop(fp, td);
    diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c
    index 665eb6df0f4..847db35b503 100644
    --- a/sys/kern/uipc_syscalls.c
    +++ b/sys/kern/uipc_syscalls.c
    @@ -121,38 +121,20 @@ SYSCTL_INT(_kern_ipc, OID_AUTO, nsfbufsused, CTLFLAG_RD, &nsfbufsused, 0,
         "Number of sendfile(2) sf_bufs in use");
     
     /*
    - * Convert a user file descriptor to a kernel file entry and check that, if
    - * it is a capability, the right rights are present. A reference on the file
    - * entry is held upon returning.
    + * Convert a user file descriptor to a kernel file entry and check if required
    + * capability rights are present.
    + * A reference on the file entry is held upon returning.
      */
     static int
     getsock_cap(struct filedesc *fdp, int fd, cap_rights_t rights,
         struct file **fpp, u_int *fflagp)
     {
     	struct file *fp;
    -#ifdef CAPABILITIES
    -	struct file *fp_fromcap;
     	int error;
    -#endif
     
    -	if (fdp == NULL || (fp = fget_unlocked(fdp, fd)) == NULL)
    -		return (EBADF);
    -#ifdef CAPABILITIES
    -	/*
    -	 * If the file descriptor is for a capability, test rights and use
    -	 * the file descriptor referenced by the capability.
    -	 */
    -	error = cap_funwrap(fp, rights, &fp_fromcap);
    -	if (error) {
    -		fdrop(fp, curthread);
    +	error = fget_unlocked(fdp, fd, rights, 0, &fp, NULL);
    +	if (error != 0)
     		return (error);
    -	}
    -	if (fp != fp_fromcap) {
    -		fhold(fp_fromcap);
    -		fdrop(fp, curthread);
    -		fp = fp_fromcap;
    -	}
    -#endif /* CAPABILITIES */
     	if (fp->f_type != DTYPE_SOCKET) {
     		fdrop(fp, curthread);
     		return (ENOTSOCK);
    @@ -765,7 +747,7 @@ kern_sendit(td, s, mp, flags, control, segflg)
     #endif
     
     	AUDIT_ARG_FD(s);
    -	rights = CAP_WRITE;
    +	rights = CAP_SEND;
     	if (mp->msg_name != NULL) {
     		AUDIT_ARG_SOCKADDR(td, mp->msg_name);
     		rights |= CAP_CONNECT;
    @@ -974,7 +956,7 @@ kern_recvit(td, s, mp, fromseg, controlp)
     		*controlp = NULL;
     
     	AUDIT_ARG_FD(s);
    -	error = getsock_cap(td->td_proc->p_fd, s, CAP_READ, &fp, NULL);
    +	error = getsock_cap(td->td_proc->p_fd, s, CAP_RECV, &fp, NULL);
     	if (error)
     		return (error);
     	so = fp->f_data;
    @@ -1850,7 +1832,11 @@ kern_sendfile(struct thread *td, struct sendfile_args *uap,
     	 * we send only the header/trailer and no payload data.
     	 */
     	AUDIT_ARG_FD(uap->fd);
    -	if ((error = fgetvp_read(td, uap->fd, CAP_READ, &vp)) != 0)
    +	/*
    +	 * sendfile(2) can start at any offset within a file so we require
    +	 * CAP_READ+CAP_SEEK = CAP_PREAD.
    +	 */
    +	if ((error = fgetvp_read(td, uap->fd, CAP_PREAD, &vp)) != 0)
     		goto out;
     	vn_lock(vp, LK_SHARED | LK_RETRY);
     	if (vp->v_type == VREG) {
    @@ -1886,7 +1872,7 @@ kern_sendfile(struct thread *td, struct sendfile_args *uap,
     	 * The socket must be a stream socket and connected.
     	 * Remember if it a blocking or non-blocking socket.
     	 */
    -	if ((error = getsock_cap(td->td_proc->p_fd, uap->s, CAP_WRITE,
    +	if ((error = getsock_cap(td->td_proc->p_fd, uap->s, CAP_SEND,
     	    &sock_fp, NULL)) != 0)
     		goto out;
     	so = sock_fp->f_data;
    @@ -2423,7 +2409,7 @@ sys_sctp_generic_sendmsg (td, uap)
     		u_sinfo = &sinfo;
     	}
     
    -	rights = CAP_WRITE;
    +	rights = CAP_SEND;
     	if (uap->tolen) {
     		error = getsockaddr(&to, uap->to, uap->tolen);
     		if (error) {
    @@ -2534,7 +2520,7 @@ sys_sctp_generic_sendmsg_iov(td, uap)
     			return (error);
     		u_sinfo = &sinfo;
     	}
    -	rights = CAP_WRITE;
    +	rights = CAP_SEND;
     	if (uap->tolen) {
     		error = getsockaddr(&to, uap->to, uap->tolen);
     		if (error) {
    @@ -2658,7 +2644,7 @@ sys_sctp_generic_recvmsg(td, uap)
     #endif
     
     	AUDIT_ARG_FD(uap->sd);
    -	error = getsock_cap(td->td_proc->p_fd, uap->sd, CAP_READ, &fp, NULL);
    +	error = getsock_cap(td->td_proc->p_fd, uap->sd, CAP_RECV, &fp, NULL);
     	if (error) {
     		return (error);
     	}
    diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
    index a6c308f80fb..dcfd009d62a 100644
    --- a/sys/kern/uipc_usrreq.c
    +++ b/sys/kern/uipc_usrreq.c
    @@ -279,7 +279,7 @@ static void	unp_drop(struct unpcb *, int);
     static void	unp_gc(__unused void *, int);
     static void	unp_scan(struct mbuf *, void (*)(struct file *));
     static void	unp_discard(struct file *);
    -static void	unp_freerights(struct file **, int);
    +static void	unp_freerights(struct filedescent *, int);
     static void	unp_init(void);
     static int	unp_internalize(struct mbuf **, struct thread *);
     static void	unp_internalize_fp(struct file *);
    @@ -1642,14 +1642,14 @@ unp_drop(struct unpcb *unp, int errno)
     }
     
     static void
    -unp_freerights(struct file **rp, int fdcount)
    +unp_freerights(struct filedescent *fde, int fdcount)
     {
    -	int i;
     	struct file *fp;
    +	int i;
     
    -	for (i = 0; i < fdcount; i++) {
    -		fp = *rp;
    -		*rp++ = NULL;
    +	for (i = 0; i < fdcount; i++, fde++) {
    +		fp = fde->fde_file;
    +		bzero(fde, sizeof(*fde));
     		unp_discard(fp);
     	}
     }
    @@ -1661,8 +1661,8 @@ unp_externalize(struct mbuf *control, struct mbuf **controlp)
     	struct cmsghdr *cm = mtod(control, struct cmsghdr *);
     	int i;
     	int *fdp;
    -	struct file **rp;
    -	struct file *fp;
    +	struct filedesc *fdesc = td->td_proc->p_fd;
    +	struct filedescent *fde, *fdep;
     	void *data;
     	socklen_t clen = control->m_len, datalen;
     	int error, newfds;
    @@ -1683,20 +1683,20 @@ unp_externalize(struct mbuf *control, struct mbuf **controlp)
     		datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
     		if (cm->cmsg_level == SOL_SOCKET
     		    && cm->cmsg_type == SCM_RIGHTS) {
    -			newfds = datalen / sizeof(struct file *);
    -			rp = data;
    +			newfds = datalen / sizeof(*fdep);
    +			fdep = data;
     
     			/* If we're not outputting the descriptors free them. */
     			if (error || controlp == NULL) {
    -				unp_freerights(rp, newfds);
    +				unp_freerights(fdep, newfds);
     				goto next;
     			}
    -			FILEDESC_XLOCK(td->td_proc->p_fd);
    +			FILEDESC_XLOCK(fdesc);
     			/* if the new FD's will not fit free them.  */
     			if (!fdavail(td, newfds)) {
    -				FILEDESC_XUNLOCK(td->td_proc->p_fd);
    +				FILEDESC_XUNLOCK(fdesc);
     				error = EMSGSIZE;
    -				unp_freerights(rp, newfds);
    +				unp_freerights(fdep, newfds);
     				goto next;
     			}
     
    @@ -1710,23 +1710,24 @@ unp_externalize(struct mbuf *control, struct mbuf **controlp)
     			*controlp = sbcreatecontrol(NULL, newlen,
     			    SCM_RIGHTS, SOL_SOCKET);
     			if (*controlp == NULL) {
    -				FILEDESC_XUNLOCK(td->td_proc->p_fd);
    +				FILEDESC_XUNLOCK(fdesc);
     				error = E2BIG;
    -				unp_freerights(rp, newfds);
    +				unp_freerights(fdep, newfds);
     				goto next;
     			}
     
     			fdp = (int *)
     			    CMSG_DATA(mtod(*controlp, struct cmsghdr *));
    -			for (i = 0; i < newfds; i++) {
    +			for (i = 0; i < newfds; i++, fdep++, fdp++) {
     				if (fdalloc(td, 0, &f))
     					panic("unp_externalize fdalloc failed");
    -				fp = *rp++;
    -				td->td_proc->p_fd->fd_ofiles[f] = fp;
    -				unp_externalize_fp(fp);
    -				*fdp++ = f;
    +				fde = &fdesc->fd_ofiles[f];
    +				fde->fde_file = fdep->fde_file;
    +				filecaps_copy(&fdep->fde_caps, &fde->fde_caps);
    +				unp_externalize_fp(fde->fde_file);
    +				*fdp = f;
     			}
    -			FILEDESC_XUNLOCK(td->td_proc->p_fd);
    +			FILEDESC_XUNLOCK(fdesc);
     		} else {
     			/* We can just copy anything else across. */
     			if (error || controlp == NULL)
    @@ -1797,11 +1798,11 @@ unp_internalize(struct mbuf **controlp, struct thread *td)
     {
     	struct mbuf *control = *controlp;
     	struct proc *p = td->td_proc;
    -	struct filedesc *fdescp = p->p_fd;
    +	struct filedesc *fdesc = p->p_fd;
     	struct bintime *bt;
     	struct cmsghdr *cm = mtod(control, struct cmsghdr *);
     	struct cmsgcred *cmcred;
    -	struct file **rp;
    +	struct filedescent *fde, *fdep;
     	struct file *fp;
     	struct timeval *tv;
     	int i, fd, *fdp;
    @@ -1854,18 +1855,17 @@ unp_internalize(struct mbuf **controlp, struct thread *td)
     			 * files.  If not, reject the entire operation.
     			 */
     			fdp = data;
    -			FILEDESC_SLOCK(fdescp);
    +			FILEDESC_SLOCK(fdesc);
     			for (i = 0; i < oldfds; i++) {
     				fd = *fdp++;
    -				if (fd < 0 || fd >= fdescp->fd_nfiles ||
    -				    fdescp->fd_ofiles[fd] == NULL) {
    -					FILEDESC_SUNLOCK(fdescp);
    +				if (fget_locked(fdesc, fd) == NULL) {
    +					FILEDESC_SUNLOCK(fdesc);
     					error = EBADF;
     					goto out;
     				}
    -				fp = fdescp->fd_ofiles[fd];
    +				fp = fdesc->fd_ofiles[fd].fde_file;
     				if (!(fp->f_ops->fo_flags & DFLAG_PASSABLE)) {
    -					FILEDESC_SUNLOCK(fdescp);
    +					FILEDESC_SUNLOCK(fdesc);
     					error = EOPNOTSUPP;
     					goto out;
     				}
    @@ -1874,25 +1874,26 @@ unp_internalize(struct mbuf **controlp, struct thread *td)
     
     			/*
     			 * Now replace the integer FDs with pointers to the
    -			 * associated global file table entry..
    +			 * file structure and capability rights.
     			 */
    -			newlen = oldfds * sizeof(struct file *);
    +			newlen = oldfds * sizeof(*fdep);
     			*controlp = sbcreatecontrol(NULL, newlen,
     			    SCM_RIGHTS, SOL_SOCKET);
     			if (*controlp == NULL) {
    -				FILEDESC_SUNLOCK(fdescp);
    +				FILEDESC_SUNLOCK(fdesc);
     				error = E2BIG;
     				goto out;
     			}
     			fdp = data;
    -			rp = (struct file **)
    +			fdep = (struct filedescent *)
     			    CMSG_DATA(mtod(*controlp, struct cmsghdr *));
    -			for (i = 0; i < oldfds; i++) {
    -				fp = fdescp->fd_ofiles[*fdp++];
    -				*rp++ = fp;
    -				unp_internalize_fp(fp);
    +			for (i = 0; i < oldfds; i++, fdep++, fdp++) {
    +				fde = &fdesc->fd_ofiles[*fdp];
    +				fdep->fde_file = fde->fde_file;
    +				filecaps_copy(&fde->fde_caps, &fdep->fde_caps);
    +				unp_internalize_fp(fdep->fde_file);
     			}
    -			FILEDESC_SUNLOCK(fdescp);
    +			FILEDESC_SUNLOCK(fdesc);
     			break;
     
     		case SCM_TIMESTAMP:
    @@ -2252,7 +2253,7 @@ static void
     unp_scan(struct mbuf *m0, void (*op)(struct file *))
     {
     	struct mbuf *m;
    -	struct file **rp;
    +	struct filedescent *fdep;
     	struct cmsghdr *cm;
     	void *data;
     	int i;
    @@ -2277,10 +2278,10 @@ unp_scan(struct mbuf *m0, void (*op)(struct file *))
     
     				if (cm->cmsg_level == SOL_SOCKET &&
     				    cm->cmsg_type == SCM_RIGHTS) {
    -					qfds = datalen / sizeof (struct file *);
    -					rp = data;
    -					for (i = 0; i < qfds; i++)
    -						(*op)(*rp++);
    +					qfds = datalen / sizeof(*fdep);
    +					fdep = data;
    +					for (i = 0; i < qfds; i++, fdep++)
    +						(*op)(fdep->fde_file);
     				}
     
     				if (CMSG_SPACE(datalen) < clen) {
    diff --git a/sys/kern/vfs_aio.c b/sys/kern/vfs_aio.c
    index 99b0197445a..cba1638b195 100644
    --- a/sys/kern/vfs_aio.c
    +++ b/sys/kern/vfs_aio.c
    @@ -1593,16 +1593,16 @@ aio_aqueue(struct thread *td, struct aiocb *job, struct aioliojob *lj,
     	fd = aiocbe->uaiocb.aio_fildes;
     	switch (opcode) {
     	case LIO_WRITE:
    -		error = fget_write(td, fd, CAP_WRITE | CAP_SEEK, &fp);
    +		error = fget_write(td, fd, CAP_PWRITE, &fp);
     		break;
     	case LIO_READ:
    -		error = fget_read(td, fd, CAP_READ | CAP_SEEK, &fp);
    +		error = fget_read(td, fd, CAP_PREAD, &fp);
     		break;
     	case LIO_SYNC:
     		error = fget(td, fd, CAP_FSYNC, &fp);
     		break;
     	case LIO_NOP:
    -		error = fget(td, fd, 0, &fp);
    +		error = fget(td, fd, CAP_NONE, &fp);
     		break;
     	default:
     		error = EINVAL;
    diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c
    index fbde152d6a6..94d11f291b5 100644
    --- a/sys/kern/vfs_lookup.c
    +++ b/sys/kern/vfs_lookup.c
    @@ -227,17 +227,18 @@ namei(struct nameidata *ndp)
     				AUDIT_ARG_ATFD2(ndp->ni_dirfd);
     			error = fgetvp_rights(td, ndp->ni_dirfd,
     			    ndp->ni_rightsneeded | CAP_LOOKUP,
    -			    &(ndp->ni_baserights), &dp);
    +			    &ndp->ni_filecaps, &dp);
     #ifdef CAPABILITIES
     			/*
    -			 * Lookups relative to a capability must also be
    +			 * If file descriptor doesn't have all rights,
    +			 * all lookups relative to it must also be
     			 * strictly relative.
    -			 *
    -			 * Note that a capability with rights CAP_MASK_VALID
    -			 * is treated exactly like a regular file descriptor.
     			 */
    -			if (ndp->ni_baserights != CAP_MASK_VALID)
    +			if (ndp->ni_filecaps.fc_rights != CAP_ALL ||
    +			    ndp->ni_filecaps.fc_fcntls != CAP_FCNTL_ALL ||
    +			    ndp->ni_filecaps.fc_nioctls != -1) {
     				ndp->ni_strictrelative = 1;
    +			}
     #endif
     		}
     		if (error != 0 || dp != NULL) {
    diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
    index bd44a3a180e..787399abcb4 100644
    --- a/sys/kern/vfs_syscalls.c
    +++ b/sys/kern/vfs_syscalls.c
    @@ -970,6 +970,8 @@ flags_to_rights(int flags)
     			/* FALLTHROUGH */
     		case O_WRONLY:
     			rights |= CAP_WRITE;
    +			if (!(flags & O_APPEND))
    +				rights |= CAP_SEEK;
     			break;
     		}
     	}
    @@ -1143,19 +1145,22 @@ success:
     	 * If we haven't already installed the FD (for dupfdopen), do so now.
     	 */
     	if (indx == -1) {
    +		struct filecaps *fcaps;
    +
     #ifdef CAPABILITIES
    -		if (nd.ni_strictrelative == 1) {
    -			/*
    -			 * We are doing a strict relative lookup; wrap the
    -			 * result in a capability.
    -			 */
    -			if ((error = kern_capwrap(td, fp, nd.ni_baserights,
    -			    &indx)) != 0)
    -				goto bad;
    -		} else
    +		if (nd.ni_strictrelative == 1)
    +			fcaps = &nd.ni_filecaps;
    +		else
     #endif
    -			if ((error = finstall(td, fp, &indx, flags)) != 0)
    -				goto bad;
    +			fcaps = NULL;
    +		error = finstall(td, fp, &indx, flags, fcaps);
    +		/* On success finstall() consumes fcaps. */
    +		if (error != 0) {
    +			filecaps_free(&nd.ni_filecaps);
    +			goto bad;
    +		}
    +	} else {
    +		filecaps_free(&nd.ni_filecaps);
     	}
     
     	/*
    @@ -1279,7 +1284,7 @@ kern_mknodat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
     restart:
     	bwillwrite();
     	NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1,
    -	    pathseg, path, fd, CAP_MKNOD, td);
    +	    pathseg, path, fd, CAP_MKNODAT, td);
     	if ((error = namei(&nd)) != 0)
     		return (error);
     	vp = nd.ni_vp;
    @@ -1399,7 +1404,7 @@ kern_mkfifoat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
     restart:
     	bwillwrite();
     	NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1,
    -	    pathseg, path, fd, CAP_MKFIFO, td);
    +	    pathseg, path, fd, CAP_MKFIFOAT, td);
     	if ((error = namei(&nd)) != 0)
     		return (error);
     	if (nd.ni_vp != NULL) {
    @@ -1553,7 +1558,7 @@ kern_linkat(struct thread *td, int fd1, int fd2, char *path1, char *path2,
     		return (error);
     	}
     	NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE2,
    -	    segflg, path2, fd2, CAP_CREATE, td);
    +	    segflg, path2, fd2, CAP_LINKAT, td);
     	if ((error = namei(&nd)) == 0) {
     		if (nd.ni_vp != NULL) {
     			if (nd.ni_dvp == nd.ni_vp)
    @@ -1646,7 +1651,7 @@ kern_symlinkat(struct thread *td, char *path1, int fd, char *path2,
     restart:
     	bwillwrite();
     	NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1,
    -	    segflg, path2, fd, CAP_CREATE, td);
    +	    segflg, path2, fd, CAP_SYMLINKAT, td);
     	if ((error = namei(&nd)) != 0)
     		goto out;
     	if (nd.ni_vp) {
    @@ -1798,7 +1803,7 @@ kern_unlinkat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
     restart:
     	bwillwrite();
     	NDINIT_ATRIGHTS(&nd, DELETE, LOCKPARENT | LOCKLEAF | AUDITVNODE1,
    -	    pathseg, path, fd, CAP_DELETE, td);
    +	    pathseg, path, fd, CAP_UNLINKAT, td);
     	if ((error = namei(&nd)) != 0)
     		return (error == EINVAL ? EPERM : error);
     	vp = nd.ni_vp;
    @@ -3502,10 +3507,10 @@ kern_renameat(struct thread *td, int oldfd, char *old, int newfd, char *new,
     	bwillwrite();
     #ifdef MAC
     	NDINIT_ATRIGHTS(&fromnd, DELETE, LOCKPARENT | LOCKLEAF | SAVESTART |
    -	    AUDITVNODE1, pathseg, old, oldfd, CAP_DELETE, td);
    +	    AUDITVNODE1, pathseg, old, oldfd, CAP_RENAMEAT, td);
     #else
     	NDINIT_ATRIGHTS(&fromnd, DELETE, WANTPARENT | SAVESTART | AUDITVNODE1,
    -	    pathseg, old, oldfd, CAP_DELETE, td);
    +	    pathseg, old, oldfd, CAP_RENAMEAT, td);
     #endif
     
     	if ((error = namei(&fromnd)) != 0)
    @@ -3527,7 +3532,7 @@ kern_renameat(struct thread *td, int oldfd, char *old, int newfd, char *new,
     		goto out1;
     	}
     	NDINIT_ATRIGHTS(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE |
    -	    SAVESTART | AUDITVNODE2, pathseg, new, newfd, CAP_CREATE, td);
    +	    SAVESTART | AUDITVNODE2, pathseg, new, newfd, CAP_LINKAT, td);
     	if (fromnd.ni_vp->v_type == VDIR)
     		tond.ni_cnd.cn_flags |= WILLBEDIR;
     	if ((error = namei(&tond)) != 0) {
    @@ -3550,6 +3555,15 @@ kern_renameat(struct thread *td, int oldfd, char *old, int newfd, char *new,
     			error = EISDIR;
     			goto out;
     		}
    +#ifdef CAPABILITIES
    +		/*
    +		 * If the target already exists we require CAP_UNLINKAT
    +		 * from 'newfd'.
    +		 */
    +		error = cap_check(tond.ni_filecaps.fc_rights, CAP_UNLINKAT);
    +		if (error != 0)
    +			goto out;
    +#endif
     	}
     	if (fvp == tdvp) {
     		error = EINVAL;
    @@ -3650,7 +3664,7 @@ kern_mkdirat(struct thread *td, int fd, char *path, enum uio_seg segflg,
     restart:
     	bwillwrite();
     	NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1,
    -	    segflg, path, fd, CAP_MKDIR, td);
    +	    segflg, path, fd, CAP_MKDIRAT, td);
     	nd.ni_cnd.cn_flags |= WILLBEDIR;
     	if ((error = namei(&nd)) != 0)
     		return (error);
    @@ -3734,7 +3748,7 @@ kern_rmdirat(struct thread *td, int fd, char *path, enum uio_seg pathseg)
     restart:
     	bwillwrite();
     	NDINIT_ATRIGHTS(&nd, DELETE, LOCKPARENT | LOCKLEAF | AUDITVNODE1,
    -	    pathseg, path, fd, CAP_RMDIR, td);
    +	    pathseg, path, fd, CAP_UNLINKAT, td);
     	if ((error = namei(&nd)) != 0)
     		return (error);
     	vp = nd.ni_vp;
    @@ -3987,8 +4001,7 @@ kern_getdirentries(struct thread *td, int fd, char *buf, u_int count,
     	if (count > IOSIZE_MAX)
     		return (EINVAL);
     	auio.uio_resid = count;
    -	if ((error = getvnode(td->td_proc->p_fd, fd, CAP_READ | CAP_SEEK,
    -	    &fp)) != 0)
    +	if ((error = getvnode(td->td_proc->p_fd, fd, CAP_READ, &fp)) != 0)
     		return (error);
     	if ((fp->f_flag & FREAD) == 0) {
     		fdrop(fp, td);
    @@ -4151,33 +4164,14 @@ out:
      * entry is held upon returning.
      */
     int
    -getvnode(struct filedesc *fdp, int fd, cap_rights_t rights,
    -    struct file **fpp)
    +getvnode(struct filedesc *fdp, int fd, cap_rights_t rights, struct file **fpp)
     {
     	struct file *fp;
    -#ifdef CAPABILITIES
    -	struct file *fp_fromcap;
     	int error;
    -#endif
     
    -	if (fdp == NULL || (fp = fget_unlocked(fdp, fd)) == NULL)
    -		return (EBADF);
    -#ifdef CAPABILITIES
    -	/*
    -	 * If the file descriptor is for a capability, test rights and use the
    -	 * file descriptor referenced by the capability.
    -	 */
    -	error = cap_funwrap(fp, rights, &fp_fromcap);
    -	if (error) {
    -		fdrop(fp, curthread);
    +	error = fget_unlocked(fdp, fd, rights, 0, &fp, NULL);
    +	if (error != 0)
     		return (error);
    -	}
    -	if (fp != fp_fromcap) {
    -		fhold(fp_fromcap);
    -		fdrop(fp, curthread);
    -		fp = fp_fromcap;
    -	}
    -#endif /* CAPABILITIES */
     
     	/*
     	 * The file could be not of the vnode type, or it may be not
    @@ -4361,7 +4355,7 @@ sys_fhopen(td, uap)
     			goto bad;
     	}
     
    -	error = finstall(td, fp, &indx, fmode);
    +	error = finstall(td, fp, &indx, fmode, NULL);
     bad:
     	fdrop(fp, td);
     	td->td_retval[0] = indx;
    @@ -4614,7 +4608,7 @@ kern_posix_fadvise(struct thread *td, int fd, off_t offset, off_t len,
     		return (EINVAL);
     	}
     	/* XXX: CAP_POSIX_FADVISE? */
    -	error = fget(td, fd, 0, &fp);
    +	error = fget(td, fd, CAP_NONE, &fp);
     	if (error != 0)
     		goto out;
     
    diff --git a/sys/netsmb/smb_dev.c b/sys/netsmb/smb_dev.c
    index dfedd8898a2..a09d74d5f45 100644
    --- a/sys/netsmb/smb_dev.c
    +++ b/sys/netsmb/smb_dev.c
    @@ -399,9 +399,7 @@ nsmb_getfp(struct filedesc* fdp, int fd, int flag)
     	struct file* fp;
     
     	FILEDESC_SLOCK(fdp);
    -	if (fd < 0 || fd >= fdp->fd_nfiles ||
    -	    (fp = fdp->fd_ofiles[fd]) == NULL ||
    -	    (fp->f_flag & flag) == 0) {
    +	if ((fp = fget_locked(fdp, fd)) == NULL || (fp->f_flag & flag) == 0) {
     		FILEDESC_SUNLOCK(fdp);
     		return (NULL);
     	}
    diff --git a/sys/nfsserver/nfs_srvkrpc.c b/sys/nfsserver/nfs_srvkrpc.c
    index 64f2aaad1ef..6b3a6b7c70f 100644
    --- a/sys/nfsserver/nfs_srvkrpc.c
    +++ b/sys/nfsserver/nfs_srvkrpc.c
    @@ -174,7 +174,8 @@ nfssvc_nfsserver(struct thread *td, struct nfssvc_args *uap)
     		    sizeof(addsockarg));
     		if (error)
     			return (error);
    -		if ((error = fget(td, addsockarg.sock, CAP_SOCK_ALL, &fp)) != 0)
    +		error = fget(td, addsockarg.sock, CAP_SOCK_SERVER, &fp);
    +		if (error)
     			return (error);
     		if (fp->f_type != DTYPE_SOCKET) {
     			fdrop(fp, td);
    diff --git a/sys/ofed/include/linux/file.h b/sys/ofed/include/linux/file.h
    index cbeec399cf2..b9bd8b15429 100644
    --- a/sys/ofed/include/linux/file.h
    +++ b/sys/ofed/include/linux/file.h
    @@ -47,7 +47,8 @@ linux_fget(unsigned int fd)
     {
     	struct file *file;
     
    -	file = fget_unlocked(curthread->td_proc->p_fd, fd);
    +	if (fget_unlocked(curthread->td_proc->p_fd, fd, 0, 0, &file, NULL) != 0)
    +		return (NULL);
     	return (struct linux_file *)file->f_data;
     }
     
    @@ -69,8 +70,7 @@ put_unused_fd(unsigned int fd)
     {
     	struct file *file;
     
    -	file = fget_unlocked(curthread->td_proc->p_fd, fd);
    -	if (file == NULL)
    +	if (fget_unlocked(curthread->td_proc->p_fd, fd, 0, 0, &file, NULL) != 0)
     		return;
     	fdclose(curthread->td_proc->p_fd, file, fd, curthread);
     }
    @@ -80,7 +80,8 @@ fd_install(unsigned int fd, struct linux_file *filp)
     {
     	struct file *file;
     
    -	file = fget_unlocked(curthread->td_proc->p_fd, fd);
    +	if (fget_unlocked(curthread->td_proc->p_fd, fd, 0, 0, &file, NULL) != 0)
    +		file = NULL;
     	filp->_file = file;
             finit(file, filp->f_mode, DTYPE_DEV, filp, &linuxfileops);
     }
    diff --git a/sys/security/audit/audit.h b/sys/security/audit/audit.h
    index f43f6c8c702..733a3c79166 100644
    --- a/sys/security/audit/audit.h
    +++ b/sys/security/audit/audit.h
    @@ -115,6 +115,7 @@ void	 audit_arg_file(struct proc *p, struct file *fp);
     void	 audit_arg_argv(char *argv, int argc, int length);
     void	 audit_arg_envv(char *envv, int envc, int length);
     void	 audit_arg_rights(cap_rights_t rights);
    +void	 audit_arg_fcntl_rights(uint32_t fcntlrights);
     void	 audit_sysclose(struct thread *td, int fd);
     void	 audit_cred_copy(struct ucred *src, struct ucred *dest);
     void	 audit_cred_destroy(struct ucred *cred);
    @@ -241,6 +242,11 @@ void	 audit_thread_free(struct thread *td);
     		audit_arg_rights((rights));				\
     } while (0)
     
    +#define	AUDIT_ARG_FCNTL_RIGHTS(fcntlrights) do {			\
    +	if (AUDITING_TD(curthread))					\
    +		audit_arg_fcntl_rights((fcntlrights));			\
    +} while (0)
    +
     #define	AUDIT_ARG_RUID(ruid) do {					\
     	if (AUDITING_TD(curthread))					\
     		audit_arg_ruid((ruid));					\
    @@ -354,6 +360,7 @@ void	 audit_thread_free(struct thread *td);
     #define	AUDIT_ARG_PROCESS(p)
     #define	AUDIT_ARG_RGID(rgid)
     #define	AUDIT_ARG_RIGHTS(rights)
    +#define	AUDIT_ARG_FCNTL_RIGHTS(fcntlrights)
     #define	AUDIT_ARG_RUID(ruid)
     #define	AUDIT_ARG_SIGNUM(signum)
     #define	AUDIT_ARG_SGID(sgid)
    diff --git a/sys/security/audit/audit_arg.c b/sys/security/audit/audit_arg.c
    index 41d6b4217b1..ec04b8bef7b 100644
    --- a/sys/security/audit/audit_arg.c
    +++ b/sys/security/audit/audit_arg.c
    @@ -871,6 +871,19 @@ audit_arg_rights(cap_rights_t rights)
     	ARG_SET_VALID(ar, ARG_RIGHTS);
     }
     
    +void
    +audit_arg_fcntl_rights(uint32_t fcntlrights)
    +{
    +	struct kaudit_record *ar;
    +
    +	ar = currecord();
    +	if (ar == NULL)
    +		return;
    +
    +	ar->k_ar.ar_arg_fcntl_rights = fcntlrights;
    +	ARG_SET_VALID(ar, ARG_FCNTL_RIGHTS);
    +}
    +
     /*
      * The close() system call uses it's own audit call to capture the path/vnode
      * information because those pieces are not easily obtained within the system
    diff --git a/sys/security/audit/audit_bsm.c b/sys/security/audit/audit_bsm.c
    index 8881ceaf556..9c69b1e040d 100644
    --- a/sys/security/audit/audit_bsm.c
    +++ b/sys/security/audit/audit_bsm.c
    @@ -1597,6 +1597,7 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
     		break;
     
     	case AUE_CAP_NEW:
    +	case AUE_CAP_RIGHTS_LIMIT:
     		/*
     		 * XXXRW/XXXJA: Would be nice to audit socket/etc information.
     		 */
    @@ -1607,13 +1608,25 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
     		}
     		break;
     
    -	case AUE_CAP_GETRIGHTS:
    +	case AUE_CAP_FCNTLS_GET:
    +	case AUE_CAP_IOCTLS_GET:
    +	case AUE_CAP_IOCTLS_LIMIT:
    +	case AUE_CAP_RIGHTS_GET:
     		if (ARG_IS_VALID(kar, ARG_FD)) {
     			tok = au_to_arg32(1, "fd", ar->ar_arg_fd);
     			kau_write(rec, tok);
     		}
     		break;
     
    +	case AUE_CAP_FCNTLS_LIMIT:
    +		FD_VNODE1_TOKENS;
    +		if (ARG_IS_VALID(kar, ARG_FCNTL_RIGHTS)) {
    +			tok = au_to_arg32(2, "fcntlrights",
    +			    ar->ar_arg_fcntl_rights);
    +			kau_write(rec, tok);
    +		}
    +		break;
    +
     	case AUE_CAP_ENTER:
     	case AUE_CAP_GETMODE:
     		break;
    diff --git a/sys/security/audit/audit_private.h b/sys/security/audit/audit_private.h
    index 10ccd5b296d..e23ba087ae1 100644
    --- a/sys/security/audit/audit_private.h
    +++ b/sys/security/audit/audit_private.h
    @@ -230,6 +230,7 @@ struct audit_record {
     	int			ar_arg_exitretval;
     	struct sockaddr_storage ar_arg_sockaddr;
     	cap_rights_t		ar_arg_rights;
    +	uint32_t		ar_arg_fcntl_rights;
     	char			ar_jailname[MAXHOSTNAMELEN];
     };
     
    @@ -291,6 +292,7 @@ struct audit_record {
     #define	ARG_ATFD1		0x0004000000000000ULL
     #define	ARG_ATFD2		0x0008000000000000ULL
     #define	ARG_RIGHTS		0x0010000000000000ULL
    +#define	ARG_FCNTL_RIGHTS	0x0020000000000000ULL
     #define	ARG_NONE		0x0000000000000000ULL
     #define	ARG_ALL			0xFFFFFFFFFFFFFFFFULL
     
    diff --git a/sys/sys/capability.h b/sys/sys/capability.h
    index a163c4c2c3d..27e56c2952e 100644
    --- a/sys/sys/capability.h
    +++ b/sys/sys/capability.h
    @@ -1,10 +1,14 @@
     /*-
      * Copyright (c) 2008-2010 Robert N. M. Watson
    + * Copyright (c) 2012 FreeBSD Foundation
      * All rights reserved.
      *
      * This software was developed at the University of Cambridge Computer
      * Laboratory with support from a grant from Google, Inc.
      *
    + * Portions of this software were developed by Pawel Jakub Dawidek under
    + * sponsorship from the FreeBSD Foundation.
    + *
      * Redistribution and use in source and binary forms, with or without
      * modification, are permitted provided that the following conditions
      * are met:
    @@ -36,9 +40,10 @@
     #define	_SYS_CAPABILITY_H_
     
     #include 
    -#include 
    +#include 
     
     #include 
    +#include 
     
     /*
      * Possible rights on capabilities.
    @@ -54,34 +59,69 @@
      * involve reads or writes depending a great deal on context.
      */
     
    -/* General file I/O. */
    -#define	CAP_READ		0x0000000000000001ULL	/* read/recv */
    -#define	CAP_WRITE		0x0000000000000002ULL	/* write/send */
    -#define	CAP_MMAP		0x0000000000000004ULL	/* mmap */
    -#define	CAP_MAPEXEC		0x0000000000000008ULL	/* mmap(2) as exec */
    -#define	CAP_FEXECVE		0x0000000000000010ULL
    -#define	CAP_FSYNC		0x0000000000000020ULL
    -#define	CAP_FTRUNCATE		0x0000000000000040ULL
    +#define	CAP_NONE		0x0000000000000000ULL
    +
    +/*
    + * General file I/O.
    + */
    +/* Allows for openat(O_RDONLY), read(2), readv(2). */
    +#define	CAP_READ		0x0000000000000001ULL
    +/* Allows for openat(O_WRONLY | O_APPEND), write(2), writev(2). */
    +#define	CAP_WRITE		0x0000000000000002ULL
    +/* Allows for lseek(2). */
     #define	CAP_SEEK		0x0000000000000080ULL
    +/* Allows for pread(2), preadv(2). */
    +#define	CAP_PREAD		(CAP_SEEK | CAP_READ)
    +/* Allows for openat(O_WRONLY) (without O_APPEND), pwrite(2), pwritev(2). */
    +#define	CAP_PWRITE		(CAP_SEEK | CAP_WRITE)
    +/* Allows for mmap(PROT_NONE). */
    +#define	CAP_MMAP		0x0000000000000004ULL
    +/* Allows for mmap(PROT_READ). */
    +#define	CAP_MMAP_R		(CAP_MMAP | CAP_SEEK | CAP_READ)
    +/* Allows for mmap(PROT_WRITE). */
    +#define	CAP_MMAP_W		(CAP_MMAP | CAP_SEEK | CAP_WRITE)
    +/* Allows for mmap(PROT_EXEC). */
    +#define	CAP_MMAP_X		(CAP_MMAP | CAP_SEEK | 0x0000000000000008ULL)
    +/* Allows for mmap(PROT_READ | PROT_WRITE). */
    +#define	CAP_MMAP_RW		(CAP_MMAP_R | CAP_MMAP_W)
    +/* Allows for mmap(PROT_READ | PROT_EXEC). */
    +#define	CAP_MMAP_RX		(CAP_MMAP_R | CAP_MMAP_X)
    +/* Allows for mmap(PROT_WRITE | PROT_EXEC). */
    +#define	CAP_MMAP_WX		(CAP_MMAP_W | CAP_MMAP_X)
    +/* Allows for mmap(PROT_READ | PROT_WRITE | PROT_EXEC). */
    +#define	CAP_MMAP_RWX		(CAP_MMAP_R | CAP_MMAP_W | CAP_MMAP_X)
    +/* Allows for openat(O_CREAT). */
    +#define	CAP_CREATE		0x0000000000080000ULL
    +/* Allows for openat(O_EXEC) and fexecve(2) in turn. */
    +#define	CAP_FEXECVE		0x0000000000000010ULL
    +/* Allows for openat(O_SYNC), openat(O_FSYNC), fsync(2). */
    +#define	CAP_FSYNC		0x0000000000000020ULL
    +/* Allows for openat(O_TRUNC), ftruncate(2). */
    +#define	CAP_FTRUNCATE		0x0000000000000040ULL
     
     /* VFS methods. */
    -#define	CAP_FCHFLAGS		0x0000000000000100ULL
     #define	CAP_FCHDIR		0x0000000000000200ULL
    +#define	CAP_FCHFLAGS		0x0000000000000100ULL
     #define	CAP_FCHMOD		0x0000000000000400ULL
    +#define	CAP_FCHMODAT		CAP_FCHMOD
     #define	CAP_FCHOWN		0x0000000000000800ULL
    +#define	CAP_FCHOWNAT		CAP_FCHOWN
     #define	CAP_FCNTL		0x0000000000001000ULL
    -#define	CAP_FPATHCONF		0x0000000000002000ULL
     #define	CAP_FLOCK		0x0000000000004000ULL
    +#define	CAP_FPATHCONF		0x0000000000002000ULL
     #define	CAP_FSCK		0x0000000000008000ULL
     #define	CAP_FSTAT		0x0000000000010000ULL
    +#define	CAP_FSTATAT		CAP_FSTAT
     #define	CAP_FSTATFS		0x0000000000020000ULL
     #define	CAP_FUTIMES		0x0000000000040000ULL
    -#define	CAP_CREATE		0x0000000000080000ULL
    -#define	CAP_DELETE		0x0000000000100000ULL
    -#define	CAP_MKDIR		0x0000000000200000ULL
    -#define	CAP_RMDIR		0x0000000000400000ULL
    -#define	CAP_MKFIFO		0x0000000000800000ULL
    -#define	CAP_MKNOD		0x0080000000000000ULL
    +#define	CAP_FUTIMESAT		CAP_FUTIMES
    +#define	CAP_LINKAT		0x0000000000400000ULL
    +#define	CAP_MKDIRAT		0x0000000000200000ULL
    +#define	CAP_MKFIFOAT		0x0000000000800000ULL
    +#define	CAP_MKNODAT		0x0080000000000000ULL
    +#define	CAP_RENAMEAT		0x0200000000000000ULL
    +#define	CAP_SYMLINKAT		0x0100000000000000ULL
    +#define	CAP_UNLINKAT		0x0000000000100000ULL
     
     /* Lookups - used to constrain *at() calls. */
     #define	CAP_LOOKUP		0x0000000001000000ULL
    @@ -107,13 +147,18 @@
     #define	CAP_GETSOCKOPT		0x0000004000000000ULL
     #define	CAP_LISTEN		0x0000008000000000ULL
     #define	CAP_PEELOFF		0x0000010000000000ULL
    +#define	CAP_RECV		CAP_READ
    +#define	CAP_SEND		CAP_WRITE
     #define	CAP_SETSOCKOPT		0x0000020000000000ULL
     #define	CAP_SHUTDOWN		0x0000040000000000ULL
     
    -#define	CAP_SOCK_ALL \
    -	(CAP_ACCEPT | CAP_BIND | CAP_CONNECT \
    -	 | CAP_GETPEERNAME | CAP_GETSOCKNAME | CAP_GETSOCKOPT \
    -	 | CAP_LISTEN | CAP_PEELOFF | CAP_SETSOCKOPT | CAP_SHUTDOWN)
    +#define	CAP_SOCK_CLIENT \
    +	(CAP_CONNECT | CAP_GETPEERNAME | CAP_GETSOCKNAME | CAP_GETSOCKOPT | \
    +	 CAP_PEELOFF | CAP_RECV | CAP_SEND | CAP_SETSOCKOPT | CAP_SHUTDOWN)
    +#define	CAP_SOCK_SERVER \
    +	(CAP_ACCEPT | CAP_BIND | CAP_GETPEERNAME | CAP_GETSOCKNAME | \
    +	 CAP_GETSOCKOPT | CAP_LISTEN | CAP_PEELOFF | CAP_RECV | CAP_SEND | \
    +	 CAP_SETSOCKOPT | CAP_SHUTDOWN)
     
     /* Mandatory Access Control. */
     #define	CAP_MAC_GET		0x0000080000000000ULL
    @@ -138,40 +183,77 @@
     #define	CAP_PDKILL		0x0040000000000000ULL
     
     /* The mask of all valid method rights. */
    -#define	CAP_MASK_VALID		0x00ffffffffffffffULL
    +#define	CAP_MASK_VALID		0x03ffffffffffffffULL
    +#define	CAP_ALL			CAP_MASK_VALID
    +
    +/* Available bits. */
    +#define	CAP_UNUSED5		0x0400000000000000ULL
    +#define	CAP_UNUSED4		0x0800000000000000ULL
    +#define	CAP_UNUSED3		0x1000000000000000ULL
    +#define	CAP_UNUSED2		0x2000000000000000ULL
    +#define	CAP_UNUSED1		0x4000000000000000ULL
    +#define	CAP_UNUSED0		0x8000000000000000ULL
    +
    +/*
    + * The following defines are provided for backward API compatibility and
    + * should not be used in new code.
    + */
    +#define	CAP_MAPEXEC		CAP_MMAP_X
    +#define	CAP_DELETE		CAP_UNLINKAT
    +#define	CAP_MKDIR		CAP_MKDIRAT
    +#define	CAP_RMDIR		CAP_UNLINKAT
    +#define	CAP_MKFIFO		CAP_MKFIFOAT
    +#define	CAP_MKNOD		CAP_MKNODAT
    +#define	CAP_SOCK_ALL		(CAP_SOCK_CLIENT | CAP_SOCK_SERVER)
    +
    +/*
    + * Allowed fcntl(2) commands.
    + */
    +#define	CAP_FCNTL_GETFL		(1 << F_GETFL)
    +#define	CAP_FCNTL_SETFL		(1 << F_SETFL)
    +#if __BSD_VISIBLE || __XSI_VISIBLE || __POSIX_VISIBLE >= 200112
    +#define	CAP_FCNTL_GETOWN	(1 << F_GETOWN)
    +#define	CAP_FCNTL_SETOWN	(1 << F_SETOWN)
    +#endif
    +#if __BSD_VISIBLE || __XSI_VISIBLE || __POSIX_VISIBLE >= 200112
    +#define	CAP_FCNTL_ALL		(CAP_FCNTL_GETFL | CAP_FCNTL_SETFL | \
    +				 CAP_FCNTL_GETOWN | CAP_FCNTL_SETOWN)
    +#else
    +#define	CAP_FCNTL_ALL		(CAP_FCNTL_GETFL | CAP_FCNTL_SETFL)
    +#endif
    +
    +#define	CAP_IOCTLS_ALL	SSIZE_MAX
     
     #ifdef _KERNEL
     
    -#define IN_CAPABILITY_MODE(td) (td->td_ucred->cr_flags & CRED_FLAG_CAPMODE)
    +#include 
    +
    +#define IN_CAPABILITY_MODE(td) ((td->td_ucred->cr_flags & CRED_FLAG_CAPMODE) != 0)
    +
    +struct filedesc;
     
     /*
    - * Create a capability to wrap a file object.
    + * Test whether a capability grants the requested rights.
      */
    -int	kern_capwrap(struct thread *td, struct file *fp, cap_rights_t rights,
    -	    int *capfd);
    -
    +int	cap_check(cap_rights_t have, cap_rights_t need);
     /*
    - * Unwrap a capability if its rights mask is a superset of 'rights'.
    - *
    - * Unwrapping a non-capability is effectively a no-op; the value of fp_cap
    - * is simply copied into fpp.
    + * Convert capability rights into VM access flags.
      */
    -int	cap_funwrap(struct file *fp_cap, cap_rights_t rights,
    -	    struct file **fpp);
    -int	cap_funwrap_mmap(struct file *fp_cap, cap_rights_t rights,
    -	    u_char *maxprotp, struct file **fpp);
    +u_char	cap_rights_to_vmprot(cap_rights_t have);
     
     /*
      * For the purposes of procstat(1) and similar tools, allow kern_descrip.c to
    - * extract the rights from a capability.  However, this should not be used by
    - * kernel code generally, instead cap_funwrap() should be used in order to
    - * keep all access control in one place.
    + * extract the rights from a capability.
      */
    -cap_rights_t	cap_rights(struct file *fp_cap);
    +cap_rights_t	cap_rights(struct filedesc *fdp, int fd);
    +
    +int	cap_ioctl_check(struct filedesc *fdp, int fd, u_long cmd);
    +int	cap_fcntl_check(struct filedesc *fdp, int fd, int cmd);
     
     #else /* !_KERNEL */
     
     __BEGIN_DECLS
    +#include 
     
     /*
      * cap_enter(): Cause the process to enter capability mode, which will
    @@ -186,22 +268,47 @@ __BEGIN_DECLS
      */
     int	cap_enter(void);
     
    +/*
    + * Are we sandboxed (in capability mode)?
    + * This is a libc wrapper around the cap_getmode(2) system call.
    + */
    +bool	cap_sandboxed(void);
    +
     /*
      * cap_getmode(): Are we in capability mode?
      */
    -int	cap_getmode(u_int* modep);
    +int	cap_getmode(u_int *modep);
     
     /*
    - * cap_new(): Create a new capability derived from an existing file
    - * descriptor with the specified rights.  If the existing file descriptor is
    - * a capability, then the new rights must be a subset of the existing rights.
    + * Limits capability rights for the given descriptor (CAP_*).
      */
    -int	cap_new(int fd, cap_rights_t rights);
    -
    +int cap_rights_limit(int fd, cap_rights_t rights);
     /*
    - * cap_getrights(): Query the rights on a capability.
    + * Returns bitmask of capability rights for the given descriptor.
      */
    -int	cap_getrights(int fd, cap_rights_t *rightsp);
    +int cap_rights_get(int fd, cap_rights_t *rightsp);
    +/*
    + * Limits allowed ioctls for the given descriptor.
    + */
    +int cap_ioctls_limit(int fd, const unsigned long *cmds, size_t ncmds);
    +/*
    + * Returns array of allowed ioctls for the given descriptor.
    + * If all ioctls are allowed, the cmds array is not populated and
    + * the function returns CAP_IOCTLS_ALL.
    + */
    +ssize_t cap_ioctls_get(int fd, unsigned long *cmds, size_t maxcmds);
    +/*
    + * Limits allowed fcntls for the given descriptor (CAP_FCNTL_*).
    + */
    +int cap_fcntls_limit(int fd, uint32_t fcntlrights);
    +/*
    + * Returns bitmask of allowed fcntls for the given descriptor.
    + */
    +int cap_fcntls_get(int fd, uint32_t *fcntlrightsp);
    +
    +/* For backward compatibility. */
    +int cap_new(int fd, cap_rights_t rights);
    +#define	cap_getrights(fd, rightsp)	cap_rights_get((fd), (rightsp))
     
     __END_DECLS
     
    diff --git a/sys/sys/file.h b/sys/sys/file.h
    index cf5f1ea4965..cfdc1d898fe 100644
    --- a/sys/sys/file.h
    +++ b/sys/sys/file.h
    @@ -64,12 +64,12 @@ struct socket;
     #define	DTYPE_SEM	9	/* posix semaphore */
     #define	DTYPE_PTS	10	/* pseudo teletype master device */
     #define	DTYPE_DEV	11	/* Device specific fd type */
    -#define	DTYPE_CAPABILITY	12	/* capability */
    -#define	DTYPE_PROCDESC	13	/* process descriptor */
    +#define	DTYPE_PROCDESC	12	/* process descriptor */
     
     #ifdef _KERNEL
     
     struct file;
    +struct filecaps;
     struct ucred;
     
     #define	FOF_OFFSET	0x01	/* Use the offset in uio argument */
    @@ -217,7 +217,6 @@ int fget_read(struct thread *td, int fd, cap_rights_t rights,
         struct file **fpp);
     int fget_write(struct thread *td, int fd, cap_rights_t rights,
         struct file **fpp);
    -int fgetcap(struct thread *td, int fd, struct file **fpp);
     int _fdrop(struct file *fp, struct thread *td);
     
     /*
    @@ -242,7 +241,7 @@ int fgetvp(struct thread *td, int fd, cap_rights_t rights, struct vnode **vpp);
     int fgetvp_exec(struct thread *td, int fd, cap_rights_t rights,
         struct vnode **vpp);
     int fgetvp_rights(struct thread *td, int fd, cap_rights_t need,
    -    cap_rights_t *have, struct vnode **vpp);
    +    struct filecaps *havecaps, struct vnode **vpp);
     int fgetvp_read(struct thread *td, int fd, cap_rights_t rights,
         struct vnode **vpp);
     int fgetvp_write(struct thread *td, int fd, cap_rights_t rights,
    diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h
    index 07cfb1f921d..f3e3a0976b7 100644
    --- a/sys/sys/filedesc.h
    +++ b/sys/sys/filedesc.h
    @@ -41,6 +41,23 @@
     
     #include 
     
    +struct filecaps {
    +	cap_rights_t	 fc_rights;	/* per-descriptor capability rights */
    +	uint32_t	 fc_fcntls;	/* per-descriptor allowed fcntls */
    +	u_long		*fc_ioctls;	/* per-descriptor allowed ioctls */
    +	int16_t		 fc_nioctls;	/* fc_ioctls array size */
    +};
    +
    +struct filedescent {
    +	struct file	*fde_file;		/* file structure for open file */
    +	struct filecaps	 fde_caps;		/* per-descriptor rights */
    +	uint8_t		 fde_flags;		/* per-process open file flags */
    +};
    +#define	fde_rights	fde_caps.fc_rights
    +#define	fde_fcntls	fde_caps.fc_fcntls
    +#define	fde_ioctls	fde_caps.fc_ioctls
    +#define	fde_nioctls	fde_caps.fc_nioctls
    +
     /*
      * This structure is used for the management of descriptors.  It may be
      * shared by multiple processes.
    @@ -48,8 +65,7 @@
     #define NDSLOTTYPE	u_long
     
     struct filedesc {
    -	struct	file **fd_ofiles;	/* file structures for open files */
    -	char	*fd_ofileflags;		/* per-process open file flags */
    +	struct	filedescent *fd_ofiles;	/* open files */
     	struct	vnode *fd_cdir;		/* current directory */
     	struct	vnode *fd_rdir;		/* root directory */
     	struct	vnode *fd_jdir;		/* jail root directory */
    @@ -92,6 +108,15 @@ struct filedesc_to_leader {
     
     #ifdef _KERNEL
     
    +#include 	/* CTASSERT() */
    +
    +CTASSERT(sizeof(cap_rights_t) == sizeof(uint64_t));
    +
    +/* Flags for do_dup() */
    +#define	DUP_FIXED	0x1	/* Force fixed allocation. */
    +#define	DUP_FCNTL	0x2	/* fcntl()-style errors. */
    +#define	DUP_CLOEXEC	0x4	/* Atomically set FD_CLOEXEC. */
    +
     /* Lock a file descriptor table. */
     #define	FILEDESC_LOCK_INIT(fdp)	sx_init(&(fdp)->fd_sx, "filedesc structure")
     #define	FILEDESC_LOCK_DESTROY(fdp)	sx_destroy(&(fdp)->fd_sx)
    @@ -109,13 +134,20 @@ struct filedesc_to_leader {
     
     struct thread;
     
    +void	filecaps_init(struct filecaps *fcaps);
    +void	filecaps_copy(const struct filecaps *src, struct filecaps *dst);
    +void	filecaps_free(struct filecaps *fcaps);
    +
     int	closef(struct file *fp, struct thread *td);
    +int	do_dup(struct thread *td, int flags, int old, int new,
    +	    register_t *retval);
     int	dupfdopen(struct thread *td, struct filedesc *fdp, int dfd, int mode,
     	    int openerror, int *indxp);
     int	falloc(struct thread *td, struct file **resultfp, int *resultfd,
     	    int flags);
     int	falloc_noinstall(struct thread *td, struct file **resultfp);
    -int	finstall(struct thread *td, struct file *fp, int *resultfp, int flags);
    +int	finstall(struct thread *td, struct file *fp, int *resultfp, int flags,
    +	    struct filecaps *fcaps);
     int	fdalloc(struct thread *td, int minfd, int *result);
     int	fdavail(struct thread *td, int n);
     int	fdcheckstd(struct thread *td);
    @@ -123,7 +155,7 @@ void	fdclose(struct filedesc *fdp, struct file *fp, int idx, struct thread *td);
     void	fdcloseexec(struct thread *td);
     struct	filedesc *fdcopy(struct filedesc *fdp);
     void	fdunshare(struct proc *p, struct thread *td);
    -void	fdfree(struct thread *td);
    +void	fdescfree(struct thread *td);
     struct	filedesc *fdinit(struct filedesc *fdp);
     struct	filedesc *fdshare(struct filedesc *fdp);
     struct filedesc_to_leader *
    @@ -135,7 +167,8 @@ void	mountcheckdirs(struct vnode *olddp, struct vnode *newdp);
     void	setugidsafety(struct thread *td);
     
     /* Return a referenced file from an unlocked descriptor. */
    -struct file *fget_unlocked(struct filedesc *fdp, int fd);
    +int	fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t needrights,
    +	    int needfcntl, struct file **fpp, cap_rights_t *haverightsp);
     
     /* Requires a FILEDESC_{S,X}LOCK held and returns without a ref. */
     static __inline struct file *
    @@ -147,7 +180,7 @@ fget_locked(struct filedesc *fdp, int fd)
     	if (fd < 0 || fd >= fdp->fd_nfiles)
     		return (NULL);
     
    -	return (fdp->fd_ofiles[fd]);
    +	return (fdp->fd_ofiles[fd].fde_file);
     }
     
     #endif /* _KERNEL */
    diff --git a/sys/sys/namei.h b/sys/sys/namei.h
    index 3b439160bc2..a9992f43c68 100644
    --- a/sys/sys/namei.h
    +++ b/sys/sys/namei.h
    @@ -33,6 +33,7 @@
     #ifndef _SYS_NAMEI_H_
     #define	_SYS_NAMEI_H_
     
    +#include 
     #include 
     #include 
     
    @@ -75,7 +76,7 @@ struct nameidata {
     	/*
     	 * Results: returned from namei
     	 */
    -	cap_rights_t ni_baserights;	/* rights the *at base has (or -1) */
    +	struct filecaps ni_filecaps;	/* rights the *at base has */
     	/*
     	 * Results: returned from/manipulated by lookup
     	 */
    @@ -180,7 +181,7 @@ NDINIT_ALL(struct nameidata *ndp,
     	ndp->ni_startdir = startdir;
     	ndp->ni_strictrelative = 0;
     	ndp->ni_rightsneeded = rights;
    -	ndp->ni_baserights = 0;
    +	filecaps_init(&ndp->ni_filecaps);
     	ndp->ni_cnd.cn_thread = td;
     }
     
    diff --git a/sys/sys/user.h b/sys/sys/user.h
    index ddaccb8ad50..5de76acaa5b 100644
    --- a/sys/sys/user.h
    +++ b/sys/sys/user.h
    @@ -251,8 +251,7 @@ struct user {
     #define	KF_TYPE_SHM	8
     #define	KF_TYPE_SEM	9
     #define	KF_TYPE_PTS	10
    -/* no KF_TYPE_CAPABILITY (11), since capabilities wrap other file objects */
    -#define	KF_TYPE_PROCDESC	12
    +#define	KF_TYPE_PROCDESC	11
     #define	KF_TYPE_UNKNOWN	255
     
     #define	KF_VTYPE_VNON	0
    @@ -288,7 +287,6 @@ struct user {
     #define	KF_FLAG_TRUNC		0x00001000
     #define	KF_FLAG_EXCL		0x00002000
     #define	KF_FLAG_EXEC		0x00004000
    -#define	KF_FLAG_CAPABILITY	0x00008000
     
     /*
      * Old format.  Has variable hidden padding due to alignment.
    diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c
    index 05bb8ae7ed5..cf94fe53d02 100644
    --- a/sys/vm/vm_mmap.c
    +++ b/sys/vm/vm_mmap.c
    @@ -305,13 +305,13 @@ sys_mmap(td, uap)
     		 */
     		rights = CAP_MMAP;
     		if (prot & PROT_READ)
    -			rights |= CAP_READ;
    +			rights |= CAP_MMAP_R;
     		if ((flags & MAP_SHARED) != 0) {
     			if (prot & PROT_WRITE)
    -				rights |= CAP_WRITE;
    +				rights |= CAP_MMAP_W;
     		}
     		if (prot & PROT_EXEC)
    -			rights |= CAP_MAPEXEC;
    +			rights |= CAP_MMAP_X;
     		if ((error = fget_mmap(td, uap->fd, rights, &cap_maxprot,
     		    &fp)) != 0)
     			goto done;
    diff --git a/usr.bin/kdump/kdump.c b/usr.bin/kdump/kdump.c
    index 2769832f670..82317f2c576 100644
    --- a/usr.bin/kdump/kdump.c
    +++ b/usr.bin/kdump/kdump.c
    @@ -1008,6 +1008,7 @@ ktrsyscall(struct ktr_syscall *ktr, u_int flags)
     				narg--;
     				break;
     			case SYS_cap_new:
    +			case SYS_cap_rights_limit:
     				print_number(ip, narg, c);
     				putchar(',');
     				arg = *ip;
    @@ -1035,6 +1036,14 @@ ktrsyscall(struct ktr_syscall *ktr, u_int flags)
     				}
     				capname(arg);
     				break;
    +			case SYS_cap_fcntls_limit:
    +				print_number(ip, narg, c);
    +				putchar(',');
    +				arg = *ip;
    +				ip++;
    +				narg--;
    +				capfcntlname(arg);
    +				break;
     			case SYS_posix_fadvise:
     				print_number(ip, narg, c);
     				print_number(ip, narg, c);
    diff --git a/usr.bin/kdump/mksubr b/usr.bin/kdump/mksubr
    index d56f0303573..aed8291ff8c 100644
    --- a/usr.bin/kdump/mksubr
    +++ b/usr.bin/kdump/mksubr
    @@ -361,6 +361,7 @@ _EOF_
     auto_or_type     "accessmodename"      "[A-Z]_OK[[:space:]]+0?x?[0-9A-Fa-f]+"         "sys/unistd.h"
     auto_switch_type "acltypename"         "ACL_TYPE_[A-Z4_]+[[:space:]]+0x[0-9]+"        "sys/acl.h"
     auto_or_type     "capname"             "CAP_[A-Z]+[[:space:]]+0x[01248]{16}ULL"       "sys/capability.h"
    +auto_or_type     "capfcntlname"        "CAP_FCNTL_[A-Z]+[[:space:]]+\(1"              "sys/capability.h"
     auto_switch_type "extattrctlname"      "EXTATTR_NAMESPACE_[A-Z]+[[:space:]]+0x[0-9]+" "sys/extattr.h"
     auto_switch_type "fadvisebehavname"    "POSIX_FADV_[A-Z]+[[:space:]]+[0-9]+"          "sys/fcntl.h"
     auto_or_type     "flagsname"           "O_[A-Z]+[[:space:]]+0x[0-9A-Fa-f]+"           "sys/fcntl.h"
    diff --git a/usr.bin/procstat/procstat_files.c b/usr.bin/procstat/procstat_files.c
    index 377390080a5..030bba138f4 100644
    --- a/usr.bin/procstat/procstat_files.c
    +++ b/usr.bin/procstat/procstat_files.c
    @@ -139,33 +139,34 @@ static struct cap_desc {
     	/* General file I/O. */
     	{ CAP_READ,		"rd" },
     	{ CAP_WRITE,		"wr" },
    +	{ CAP_SEEK,		"se" },
     	{ CAP_MMAP,		"mm" },
    -	{ CAP_MAPEXEC,		"me" },
    +	{ CAP_CREATE,		"cr" },
     	{ CAP_FEXECVE,		"fe" },
     	{ CAP_FSYNC,		"fy" },
     	{ CAP_FTRUNCATE,	"ft" },
    -	{ CAP_SEEK,		"se" },
     
     	/* VFS methods. */
    -	{ CAP_FCHFLAGS,		"cf" },
     	{ CAP_FCHDIR,		"cd" },
    +	{ CAP_FCHFLAGS,		"cf" },
     	{ CAP_FCHMOD,		"cm" },
     	{ CAP_FCHOWN,		"cn" },
     	{ CAP_FCNTL,		"fc" },
    -	{ CAP_FPATHCONF,	"fp" },
     	{ CAP_FLOCK,		"fl" },
    +	{ CAP_FPATHCONF,	"fp" },
     	{ CAP_FSCK,		"fk" },
     	{ CAP_FSTAT,		"fs" },
     	{ CAP_FSTATFS,		"sf" },
     	{ CAP_FUTIMES,		"fu" },
    -	{ CAP_CREATE,		"cr" },
    -	{ CAP_DELETE,		"de" },
    -	{ CAP_MKDIR,		"md" },
    -	{ CAP_RMDIR,		"rm" },
    -	{ CAP_MKFIFO,		"mf" },
    -	{ CAP_MKNOD,		"mn" },
    +	{ CAP_LINKAT,		"li" },
    +	{ CAP_MKDIRAT,		"md" },
    +	{ CAP_MKFIFOAT,		"mf" },
    +	{ CAP_MKNODAT,		"mn" },
    +	{ CAP_RENAMEAT,		"rn" },
    +	{ CAP_SYMLINKAT,	"sl" },
    +	{ CAP_UNLINKAT,		"un" },
     
    -	/* Lookups - used to constraint *at() calls. */
    +	/* Lookups - used to constrain *at() calls. */
     	{ CAP_LOOKUP,		"lo" },
     
     	/* Extended attributes. */
    @@ -213,6 +214,24 @@ static struct cap_desc {
     	{ CAP_PDGETPID,		"pg" },
     	{ CAP_PDWAIT,		"pw" },
     	{ CAP_PDKILL,		"pk" },
    +
    +	/* Aliases and defines that combine multiple rights. */
    +	{ CAP_PREAD,		"prd" },
    +	{ CAP_PWRITE,		"pwr" },
    +
    +	{ CAP_MMAP_R,		"mmr" },
    +	{ CAP_MMAP_W,		"mmw" },
    +	{ CAP_MMAP_X,		"mmx" },
    +	{ CAP_MMAP_RW,		"mrw" },
    +	{ CAP_MMAP_RX,		"mrx" },
    +	{ CAP_MMAP_WX,		"mwx" },
    +	{ CAP_MMAP_RWX,		"mma" },
    +
    +	{ CAP_RECV,		"re" },
    +	{ CAP_SEND,		"sd" },
    +
    +	{ CAP_SOCK_CLIENT,	"scl" },
    +	{ CAP_SOCK_SERVER,	"ssr" },
     };
     static const u_int	cap_desc_count = sizeof(cap_desc) /
     			    sizeof(cap_desc[0]);
    @@ -225,7 +244,7 @@ width_capability(cap_rights_t rights)
     	count = 0;
     	width = 0;
     	for (i = 0; i < cap_desc_count; i++) {
    -		if (rights & cap_desc[i].cd_right) {
    +		if ((cap_desc[i].cd_right & ~rights) == 0) {
     			width += strlen(cap_desc[i].cd_desc);
     			if (count)
     				width++;
    @@ -249,7 +268,7 @@ print_capability(cap_rights_t rights, u_int capwidth)
     			printf("-");
     	}
     	for (i = 0; i < cap_desc_count; i++) {
    -		if (rights & cap_desc[i].cd_right) {
    +		if ((cap_desc[i].cd_right & ~rights) == 0) {
     			printf("%s%s", count ? "," : "", cap_desc[i].cd_desc);
     			width += strlen(cap_desc[i].cd_desc);
     			if (count)
    @@ -261,7 +280,7 @@ print_capability(cap_rights_t rights, u_int capwidth)
     
     void
     procstat_files(struct procstat *procstat, struct kinfo_proc *kipp)
    -{ 
    +{
     	struct sockstat sock;
     	struct filestat_list *head;
     	struct filestat *fst;
    @@ -423,8 +442,6 @@ procstat_files(struct procstat *procstat, struct kinfo_proc *kipp)
     		printf("%s", fst->fs_fflags & PS_FST_FFLAG_NONBLOCK ? "n" : "-");
     		printf("%s", fst->fs_fflags & PS_FST_FFLAG_DIRECT ? "d" : "-");
     		printf("%s", fst->fs_fflags & PS_FST_FFLAG_HASLOCK ? "l" : "-");
    -		printf("%s ", fst->fs_fflags & PS_FST_FFLAG_CAPABILITY ?
    -		    "c" : "-");
     		if (!Cflag) {
     			if (fst->fs_ref_count > -1)
     				printf("%3d ", fst->fs_ref_count);
    
    From 1dc31587bf980dbeab3db2d647675e44a290cd83 Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Sat, 2 Mar 2013 00:55:09 +0000
    Subject: [PATCH 0518/1476] Regen after r247602.
    
    ---
     sys/compat/freebsd32/freebsd32_proto.h        |   2 +-
     sys/compat/freebsd32/freebsd32_syscall.h      |  11 +-
     sys/compat/freebsd32/freebsd32_syscalls.c     |   9 +-
     sys/compat/freebsd32/freebsd32_sysent.c       |   9 +-
     .../freebsd32/freebsd32_systrace_args.c       | 146 +++++++++++++++++-
     sys/kern/init_sysent.c                        |  11 +-
     sys/kern/syscalls.c                           |   9 +-
     sys/kern/systrace_args.c                      | 146 +++++++++++++++++-
     sys/sys/syscall.h                             |  11 +-
     sys/sys/syscall.mk                            |  11 +-
     sys/sys/sysproto.h                            |  40 ++++-
     11 files changed, 374 insertions(+), 31 deletions(-)
    
    diff --git a/sys/compat/freebsd32/freebsd32_proto.h b/sys/compat/freebsd32/freebsd32_proto.h
    index 2b241df82d0..52156bd8f06 100644
    --- a/sys/compat/freebsd32/freebsd32_proto.h
    +++ b/sys/compat/freebsd32/freebsd32_proto.h
    @@ -3,7 +3,7 @@
      *
      * DO NOT EDIT-- this file is automatically generated.
      * $FreeBSD$
    - * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 242958 2012-11-13 12:52:31Z kib 
    + * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 247602 2013-03-02 00:53:12Z pjd 
      */
     
     #ifndef _FREEBSD32_SYSPROTO_H_
    diff --git a/sys/compat/freebsd32/freebsd32_syscall.h b/sys/compat/freebsd32/freebsd32_syscall.h
    index 76311ba2e14..4b689d35495 100644
    --- a/sys/compat/freebsd32/freebsd32_syscall.h
    +++ b/sys/compat/freebsd32/freebsd32_syscall.h
    @@ -3,7 +3,7 @@
      *
      * DO NOT EDIT-- this file is automatically generated.
      * $FreeBSD$
    - * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 242958 2012-11-13 12:52:31Z kib 
    + * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 247602 2013-03-02 00:53:12Z pjd 
      */
     
     #define	FREEBSD32_SYS_syscall	0
    @@ -416,7 +416,7 @@
     #define	FREEBSD32_SYS_freebsd32_shmctl	512
     #define	FREEBSD32_SYS_lpathconf	513
     #define	FREEBSD32_SYS_cap_new	514
    -#define	FREEBSD32_SYS_cap_getrights	515
    +#define	FREEBSD32_SYS_cap_rights_get	515
     #define	FREEBSD32_SYS_cap_enter	516
     #define	FREEBSD32_SYS_cap_getmode	517
     #define	FREEBSD32_SYS_freebsd32_pselect	522
    @@ -430,4 +430,9 @@
     #define	FREEBSD32_SYS_freebsd32_posix_fallocate	530
     #define	FREEBSD32_SYS_freebsd32_posix_fadvise	531
     #define	FREEBSD32_SYS_freebsd32_wait6	532
    -#define	FREEBSD32_SYS_MAXSYSCALL	533
    +#define	FREEBSD32_SYS_cap_rights_limit	533
    +#define	FREEBSD32_SYS_cap_ioctls_limit	534
    +#define	FREEBSD32_SYS_cap_ioctls_get	535
    +#define	FREEBSD32_SYS_cap_fcntls_limit	536
    +#define	FREEBSD32_SYS_cap_fcntls_get	537
    +#define	FREEBSD32_SYS_MAXSYSCALL	538
    diff --git a/sys/compat/freebsd32/freebsd32_syscalls.c b/sys/compat/freebsd32/freebsd32_syscalls.c
    index 499b3e86c7c..4878b20020a 100644
    --- a/sys/compat/freebsd32/freebsd32_syscalls.c
    +++ b/sys/compat/freebsd32/freebsd32_syscalls.c
    @@ -3,7 +3,7 @@
      *
      * DO NOT EDIT-- this file is automatically generated.
      * $FreeBSD$
    - * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 242958 2012-11-13 12:52:31Z kib 
    + * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 247602 2013-03-02 00:53:12Z pjd 
      */
     
     const char *freebsd32_syscallnames[] = {
    @@ -538,7 +538,7 @@ const char *freebsd32_syscallnames[] = {
     	"freebsd32_shmctl",			/* 512 = freebsd32_shmctl */
     	"lpathconf",			/* 513 = lpathconf */
     	"cap_new",			/* 514 = cap_new */
    -	"cap_getrights",			/* 515 = cap_getrights */
    +	"cap_rights_get",			/* 515 = cap_rights_get */
     	"cap_enter",			/* 516 = cap_enter */
     	"cap_getmode",			/* 517 = cap_getmode */
     	"#518",			/* 518 = pdfork */
    @@ -556,4 +556,9 @@ const char *freebsd32_syscallnames[] = {
     	"freebsd32_posix_fallocate",			/* 530 = freebsd32_posix_fallocate */
     	"freebsd32_posix_fadvise",			/* 531 = freebsd32_posix_fadvise */
     	"freebsd32_wait6",			/* 532 = freebsd32_wait6 */
    +	"cap_rights_limit",			/* 533 = cap_rights_limit */
    +	"cap_ioctls_limit",			/* 534 = cap_ioctls_limit */
    +	"cap_ioctls_get",			/* 535 = cap_ioctls_get */
    +	"cap_fcntls_limit",			/* 536 = cap_fcntls_limit */
    +	"cap_fcntls_get",			/* 537 = cap_fcntls_get */
     };
    diff --git a/sys/compat/freebsd32/freebsd32_sysent.c b/sys/compat/freebsd32/freebsd32_sysent.c
    index 814d88e0be2..65da2c7612c 100644
    --- a/sys/compat/freebsd32/freebsd32_sysent.c
    +++ b/sys/compat/freebsd32/freebsd32_sysent.c
    @@ -3,7 +3,7 @@
      *
      * DO NOT EDIT-- this file is automatically generated.
      * $FreeBSD$
    - * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 242958 2012-11-13 12:52:31Z kib 
    + * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 247602 2013-03-02 00:53:12Z pjd 
      */
     
     #include "opt_compat.h"
    @@ -575,7 +575,7 @@ struct sysent freebsd32_sysent[] = {
     	{ AS(freebsd32_shmctl_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT },	/* 512 = freebsd32_shmctl */
     	{ AS(lpathconf_args), (sy_call_t *)sys_lpathconf, AUE_LPATHCONF, NULL, 0, 0, 0, SY_THR_STATIC },	/* 513 = lpathconf */
     	{ AS(cap_new_args), (sy_call_t *)sys_cap_new, AUE_CAP_NEW, NULL, 0, 0, 0, SY_THR_STATIC },	/* 514 = cap_new */
    -	{ AS(cap_getrights_args), (sy_call_t *)sys_cap_getrights, AUE_CAP_GETRIGHTS, NULL, 0, 0, 0, SY_THR_STATIC },	/* 515 = cap_getrights */
    +	{ AS(cap_rights_get_args), (sy_call_t *)sys_cap_rights_get, AUE_CAP_RIGHTS_GET, NULL, 0, 0, 0, SY_THR_STATIC },	/* 515 = cap_rights_get */
     	{ 0, (sy_call_t *)sys_cap_enter, AUE_CAP_ENTER, NULL, 0, 0, 0, SY_THR_STATIC },	/* 516 = cap_enter */
     	{ AS(cap_getmode_args), (sy_call_t *)sys_cap_getmode, AUE_CAP_GETMODE, NULL, 0, 0, 0, SY_THR_STATIC },	/* 517 = cap_getmode */
     	{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT },			/* 518 = pdfork */
    @@ -593,4 +593,9 @@ struct sysent freebsd32_sysent[] = {
     	{ AS(freebsd32_posix_fallocate_args), (sy_call_t *)freebsd32_posix_fallocate, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC },	/* 530 = freebsd32_posix_fallocate */
     	{ AS(freebsd32_posix_fadvise_args), (sy_call_t *)freebsd32_posix_fadvise, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC },	/* 531 = freebsd32_posix_fadvise */
     	{ AS(freebsd32_wait6_args), (sy_call_t *)freebsd32_wait6, AUE_WAIT6, NULL, 0, 0, 0, SY_THR_STATIC },	/* 532 = freebsd32_wait6 */
    +	{ AS(cap_rights_limit_args), (sy_call_t *)sys_cap_rights_limit, AUE_CAP_RIGHTS_LIMIT, NULL, 0, 0, 0, SY_THR_STATIC },	/* 533 = cap_rights_limit */
    +	{ AS(cap_ioctls_limit_args), (sy_call_t *)sys_cap_ioctls_limit, AUE_CAP_IOCTLS_LIMIT, NULL, 0, 0, 0, SY_THR_STATIC },	/* 534 = cap_ioctls_limit */
    +	{ AS(cap_ioctls_get_args), (sy_call_t *)sys_cap_ioctls_get, AUE_CAP_IOCTLS_GET, NULL, 0, 0, 0, SY_THR_STATIC },	/* 535 = cap_ioctls_get */
    +	{ AS(cap_fcntls_limit_args), (sy_call_t *)sys_cap_fcntls_limit, AUE_CAP_FCNTLS_LIMIT, NULL, 0, 0, 0, SY_THR_STATIC },	/* 536 = cap_fcntls_limit */
    +	{ AS(cap_fcntls_get_args), (sy_call_t *)sys_cap_fcntls_get, AUE_CAP_FCNTLS_GET, NULL, 0, 0, 0, SY_THR_STATIC },	/* 537 = cap_fcntls_get */
     };
    diff --git a/sys/compat/freebsd32/freebsd32_systrace_args.c b/sys/compat/freebsd32/freebsd32_systrace_args.c
    index 36a646c106d..e2d7adb676e 100644
    --- a/sys/compat/freebsd32/freebsd32_systrace_args.c
    +++ b/sys/compat/freebsd32/freebsd32_systrace_args.c
    @@ -2956,9 +2956,9 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
     		*n_args = 2;
     		break;
     	}
    -	/* cap_getrights */
    +	/* cap_rights_get */
     	case 515: {
    -		struct cap_getrights_args *p = params;
    +		struct cap_rights_get_args *p = params;
     		iarg[0] = p->fd; /* int */
     		uarg[1] = (intptr_t) p->rightsp; /* uint64_t * */
     		*n_args = 2;
    @@ -3088,6 +3088,48 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
     		*n_args = 6;
     		break;
     	}
    +	/* cap_rights_limit */
    +	case 533: {
    +		struct cap_rights_limit_args *p = params;
    +		iarg[0] = p->fd; /* int */
    +		uarg[1] = p->rights; /* uint64_t */
    +		*n_args = 2;
    +		break;
    +	}
    +	/* cap_ioctls_limit */
    +	case 534: {
    +		struct cap_ioctls_limit_args *p = params;
    +		iarg[0] = p->fd; /* int */
    +		uarg[1] = (intptr_t) p->cmds; /* const u_long * */
    +		uarg[2] = p->ncmds; /* size_t */
    +		*n_args = 3;
    +		break;
    +	}
    +	/* cap_ioctls_get */
    +	case 535: {
    +		struct cap_ioctls_get_args *p = params;
    +		iarg[0] = p->fd; /* int */
    +		uarg[1] = (intptr_t) p->cmds; /* u_long * */
    +		uarg[2] = p->maxcmds; /* size_t */
    +		*n_args = 3;
    +		break;
    +	}
    +	/* cap_fcntls_limit */
    +	case 536: {
    +		struct cap_fcntls_limit_args *p = params;
    +		iarg[0] = p->fd; /* int */
    +		uarg[1] = p->fcntlrights; /* uint32_t */
    +		*n_args = 2;
    +		break;
    +	}
    +	/* cap_fcntls_get */
    +	case 537: {
    +		struct cap_fcntls_get_args *p = params;
    +		iarg[0] = p->fd; /* int */
    +		uarg[1] = (intptr_t) p->fcntlrightsp; /* uint32_t * */
    +		*n_args = 2;
    +		break;
    +	}
     	default:
     		*n_args = 0;
     		break;
    @@ -8002,7 +8044,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
     			break;
     		};
     		break;
    -	/* cap_getrights */
    +	/* cap_rights_get */
     	case 515:
     		switch(ndx) {
     		case 0:
    @@ -8243,6 +8285,77 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
     			break;
     		};
     		break;
    +	/* cap_rights_limit */
    +	case 533:
    +		switch(ndx) {
    +		case 0:
    +			p = "int";
    +			break;
    +		case 1:
    +			p = "uint64_t";
    +			break;
    +		default:
    +			break;
    +		};
    +		break;
    +	/* cap_ioctls_limit */
    +	case 534:
    +		switch(ndx) {
    +		case 0:
    +			p = "int";
    +			break;
    +		case 1:
    +			p = "const u_long *";
    +			break;
    +		case 2:
    +			p = "size_t";
    +			break;
    +		default:
    +			break;
    +		};
    +		break;
    +	/* cap_ioctls_get */
    +	case 535:
    +		switch(ndx) {
    +		case 0:
    +			p = "int";
    +			break;
    +		case 1:
    +			p = "u_long *";
    +			break;
    +		case 2:
    +			p = "size_t";
    +			break;
    +		default:
    +			break;
    +		};
    +		break;
    +	/* cap_fcntls_limit */
    +	case 536:
    +		switch(ndx) {
    +		case 0:
    +			p = "int";
    +			break;
    +		case 1:
    +			p = "uint32_t";
    +			break;
    +		default:
    +			break;
    +		};
    +		break;
    +	/* cap_fcntls_get */
    +	case 537:
    +		switch(ndx) {
    +		case 0:
    +			p = "int";
    +			break;
    +		case 1:
    +			p = "uint32_t *";
    +			break;
    +		default:
    +			break;
    +		};
    +		break;
     	default:
     		break;
     	};
    @@ -9938,7 +10051,7 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
     		if (ndx == 0 || ndx == 1)
     			p = "int";
     		break;
    -	/* cap_getrights */
    +	/* cap_rights_get */
     	case 515:
     		if (ndx == 0 || ndx == 1)
     			p = "int";
    @@ -10005,6 +10118,31 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
     		if (ndx == 0 || ndx == 1)
     			p = "int";
     		break;
    +	/* cap_rights_limit */
    +	case 533:
    +		if (ndx == 0 || ndx == 1)
    +			p = "int";
    +		break;
    +	/* cap_ioctls_limit */
    +	case 534:
    +		if (ndx == 0 || ndx == 1)
    +			p = "int";
    +		break;
    +	/* cap_ioctls_get */
    +	case 535:
    +		if (ndx == 0 || ndx == 1)
    +			p = "ssize_t";
    +		break;
    +	/* cap_fcntls_limit */
    +	case 536:
    +		if (ndx == 0 || ndx == 1)
    +			p = "int";
    +		break;
    +	/* cap_fcntls_get */
    +	case 537:
    +		if (ndx == 0 || ndx == 1)
    +			p = "int";
    +		break;
     	default:
     		break;
     	};
    diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c
    index ce47f5641dc..b5ed57be6a7 100644
    --- a/sys/kern/init_sysent.c
    +++ b/sys/kern/init_sysent.c
    @@ -3,7 +3,7 @@
      *
      * DO NOT EDIT-- this file is automatically generated.
      * $FreeBSD$
    - * created from FreeBSD: head/sys/kern/syscalls.master 242958 2012-11-13 12:52:31Z kib 
    + * created from FreeBSD: head/sys/kern/syscalls.master 247602 2013-03-02 00:53:12Z pjd 
      */
     
     #include "opt_compat.h"
    @@ -88,7 +88,7 @@ struct sysent sysent[] = {
     	{ AS(acct_args), (sy_call_t *)sys_acct, AUE_ACCT, NULL, 0, 0, 0, SY_THR_STATIC },	/* 51 = acct */
     	{ compat(0,sigpending), AUE_SIGPENDING, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC },	/* 52 = old sigpending */
     	{ AS(sigaltstack_args), (sy_call_t *)sys_sigaltstack, AUE_SIGALTSTACK, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC },	/* 53 = sigaltstack */
    -	{ AS(ioctl_args), (sy_call_t *)sys_ioctl, AUE_IOCTL, NULL, 0, 0, 0, SY_THR_STATIC },	/* 54 = ioctl */
    +	{ AS(ioctl_args), (sy_call_t *)sys_ioctl, AUE_IOCTL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC },	/* 54 = ioctl */
     	{ AS(reboot_args), (sy_call_t *)sys_reboot, AUE_REBOOT, NULL, 0, 0, 0, SY_THR_STATIC },	/* 55 = reboot */
     	{ AS(revoke_args), (sy_call_t *)sys_revoke, AUE_REVOKE, NULL, 0, 0, 0, SY_THR_STATIC },	/* 56 = revoke */
     	{ AS(symlink_args), (sy_call_t *)sys_symlink, AUE_SYMLINK, NULL, 0, 0, 0, SY_THR_STATIC },	/* 57 = symlink */
    @@ -549,7 +549,7 @@ struct sysent sysent[] = {
     	{ AS(shmctl_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT },	/* 512 = shmctl */
     	{ AS(lpathconf_args), (sy_call_t *)sys_lpathconf, AUE_LPATHCONF, NULL, 0, 0, 0, SY_THR_STATIC },	/* 513 = lpathconf */
     	{ AS(cap_new_args), (sy_call_t *)sys_cap_new, AUE_CAP_NEW, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC },	/* 514 = cap_new */
    -	{ AS(cap_getrights_args), (sy_call_t *)sys_cap_getrights, AUE_CAP_GETRIGHTS, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC },	/* 515 = cap_getrights */
    +	{ AS(cap_rights_get_args), (sy_call_t *)sys_cap_rights_get, AUE_CAP_RIGHTS_GET, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC },	/* 515 = cap_rights_get */
     	{ 0, (sy_call_t *)sys_cap_enter, AUE_CAP_ENTER, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC },	/* 516 = cap_enter */
     	{ AS(cap_getmode_args), (sy_call_t *)sys_cap_getmode, AUE_CAP_GETMODE, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC },	/* 517 = cap_getmode */
     	{ AS(pdfork_args), (sy_call_t *)sys_pdfork, AUE_PDFORK, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC },	/* 518 = pdfork */
    @@ -567,4 +567,9 @@ struct sysent sysent[] = {
     	{ AS(posix_fallocate_args), (sy_call_t *)sys_posix_fallocate, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC },	/* 530 = posix_fallocate */
     	{ AS(posix_fadvise_args), (sy_call_t *)sys_posix_fadvise, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC },	/* 531 = posix_fadvise */
     	{ AS(wait6_args), (sy_call_t *)sys_wait6, AUE_WAIT6, NULL, 0, 0, 0, SY_THR_STATIC },	/* 532 = wait6 */
    +	{ AS(cap_rights_limit_args), (sy_call_t *)sys_cap_rights_limit, AUE_CAP_RIGHTS_LIMIT, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC },	/* 533 = cap_rights_limit */
    +	{ AS(cap_ioctls_limit_args), (sy_call_t *)sys_cap_ioctls_limit, AUE_CAP_IOCTLS_LIMIT, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC },	/* 534 = cap_ioctls_limit */
    +	{ AS(cap_ioctls_get_args), (sy_call_t *)sys_cap_ioctls_get, AUE_CAP_IOCTLS_GET, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC },	/* 535 = cap_ioctls_get */
    +	{ AS(cap_fcntls_limit_args), (sy_call_t *)sys_cap_fcntls_limit, AUE_CAP_FCNTLS_LIMIT, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC },	/* 536 = cap_fcntls_limit */
    +	{ AS(cap_fcntls_get_args), (sy_call_t *)sys_cap_fcntls_get, AUE_CAP_FCNTLS_GET, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC },	/* 537 = cap_fcntls_get */
     };
    diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c
    index 96f240086f8..e0660142a75 100644
    --- a/sys/kern/syscalls.c
    +++ b/sys/kern/syscalls.c
    @@ -3,7 +3,7 @@
      *
      * DO NOT EDIT-- this file is automatically generated.
      * $FreeBSD$
    - * created from FreeBSD: head/sys/kern/syscalls.master 242958 2012-11-13 12:52:31Z kib 
    + * created from FreeBSD: head/sys/kern/syscalls.master 247602 2013-03-02 00:53:12Z pjd 
      */
     
     const char *syscallnames[] = {
    @@ -522,7 +522,7 @@ const char *syscallnames[] = {
     	"shmctl",			/* 512 = shmctl */
     	"lpathconf",			/* 513 = lpathconf */
     	"cap_new",			/* 514 = cap_new */
    -	"cap_getrights",			/* 515 = cap_getrights */
    +	"cap_rights_get",			/* 515 = cap_rights_get */
     	"cap_enter",			/* 516 = cap_enter */
     	"cap_getmode",			/* 517 = cap_getmode */
     	"pdfork",			/* 518 = pdfork */
    @@ -540,4 +540,9 @@ const char *syscallnames[] = {
     	"posix_fallocate",			/* 530 = posix_fallocate */
     	"posix_fadvise",			/* 531 = posix_fadvise */
     	"wait6",			/* 532 = wait6 */
    +	"cap_rights_limit",			/* 533 = cap_rights_limit */
    +	"cap_ioctls_limit",			/* 534 = cap_ioctls_limit */
    +	"cap_ioctls_get",			/* 535 = cap_ioctls_get */
    +	"cap_fcntls_limit",			/* 536 = cap_fcntls_limit */
    +	"cap_fcntls_get",			/* 537 = cap_fcntls_get */
     };
    diff --git a/sys/kern/systrace_args.c b/sys/kern/systrace_args.c
    index c755f922298..d811da2f346 100644
    --- a/sys/kern/systrace_args.c
    +++ b/sys/kern/systrace_args.c
    @@ -3134,9 +3134,9 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
     		*n_args = 2;
     		break;
     	}
    -	/* cap_getrights */
    +	/* cap_rights_get */
     	case 515: {
    -		struct cap_getrights_args *p = params;
    +		struct cap_rights_get_args *p = params;
     		iarg[0] = p->fd; /* int */
     		uarg[1] = (intptr_t) p->rightsp; /* uint64_t * */
     		*n_args = 2;
    @@ -3286,6 +3286,48 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
     		*n_args = 6;
     		break;
     	}
    +	/* cap_rights_limit */
    +	case 533: {
    +		struct cap_rights_limit_args *p = params;
    +		iarg[0] = p->fd; /* int */
    +		uarg[1] = p->rights; /* uint64_t */
    +		*n_args = 2;
    +		break;
    +	}
    +	/* cap_ioctls_limit */
    +	case 534: {
    +		struct cap_ioctls_limit_args *p = params;
    +		iarg[0] = p->fd; /* int */
    +		uarg[1] = (intptr_t) p->cmds; /* const u_long * */
    +		uarg[2] = p->ncmds; /* size_t */
    +		*n_args = 3;
    +		break;
    +	}
    +	/* cap_ioctls_get */
    +	case 535: {
    +		struct cap_ioctls_get_args *p = params;
    +		iarg[0] = p->fd; /* int */
    +		uarg[1] = (intptr_t) p->cmds; /* u_long * */
    +		uarg[2] = p->maxcmds; /* size_t */
    +		*n_args = 3;
    +		break;
    +	}
    +	/* cap_fcntls_limit */
    +	case 536: {
    +		struct cap_fcntls_limit_args *p = params;
    +		iarg[0] = p->fd; /* int */
    +		uarg[1] = p->fcntlrights; /* uint32_t */
    +		*n_args = 2;
    +		break;
    +	}
    +	/* cap_fcntls_get */
    +	case 537: {
    +		struct cap_fcntls_get_args *p = params;
    +		iarg[0] = p->fd; /* int */
    +		uarg[1] = (intptr_t) p->fcntlrightsp; /* uint32_t * */
    +		*n_args = 2;
    +		break;
    +	}
     	default:
     		*n_args = 0;
     		break;
    @@ -8477,7 +8519,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
     			break;
     		};
     		break;
    -	/* cap_getrights */
    +	/* cap_rights_get */
     	case 515:
     		switch(ndx) {
     		case 0:
    @@ -8745,6 +8787,77 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
     			break;
     		};
     		break;
    +	/* cap_rights_limit */
    +	case 533:
    +		switch(ndx) {
    +		case 0:
    +			p = "int";
    +			break;
    +		case 1:
    +			p = "uint64_t";
    +			break;
    +		default:
    +			break;
    +		};
    +		break;
    +	/* cap_ioctls_limit */
    +	case 534:
    +		switch(ndx) {
    +		case 0:
    +			p = "int";
    +			break;
    +		case 1:
    +			p = "const u_long *";
    +			break;
    +		case 2:
    +			p = "size_t";
    +			break;
    +		default:
    +			break;
    +		};
    +		break;
    +	/* cap_ioctls_get */
    +	case 535:
    +		switch(ndx) {
    +		case 0:
    +			p = "int";
    +			break;
    +		case 1:
    +			p = "u_long *";
    +			break;
    +		case 2:
    +			p = "size_t";
    +			break;
    +		default:
    +			break;
    +		};
    +		break;
    +	/* cap_fcntls_limit */
    +	case 536:
    +		switch(ndx) {
    +		case 0:
    +			p = "int";
    +			break;
    +		case 1:
    +			p = "uint32_t";
    +			break;
    +		default:
    +			break;
    +		};
    +		break;
    +	/* cap_fcntls_get */
    +	case 537:
    +		switch(ndx) {
    +		case 0:
    +			p = "int";
    +			break;
    +		case 1:
    +			p = "uint32_t *";
    +			break;
    +		default:
    +			break;
    +		};
    +		break;
     	default:
     		break;
     	};
    @@ -10556,7 +10669,7 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
     		if (ndx == 0 || ndx == 1)
     			p = "int";
     		break;
    -	/* cap_getrights */
    +	/* cap_rights_get */
     	case 515:
     		if (ndx == 0 || ndx == 1)
     			p = "int";
    @@ -10638,6 +10751,31 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
     		if (ndx == 0 || ndx == 1)
     			p = "int";
     		break;
    +	/* cap_rights_limit */
    +	case 533:
    +		if (ndx == 0 || ndx == 1)
    +			p = "int";
    +		break;
    +	/* cap_ioctls_limit */
    +	case 534:
    +		if (ndx == 0 || ndx == 1)
    +			p = "int";
    +		break;
    +	/* cap_ioctls_get */
    +	case 535:
    +		if (ndx == 0 || ndx == 1)
    +			p = "ssize_t";
    +		break;
    +	/* cap_fcntls_limit */
    +	case 536:
    +		if (ndx == 0 || ndx == 1)
    +			p = "int";
    +		break;
    +	/* cap_fcntls_get */
    +	case 537:
    +		if (ndx == 0 || ndx == 1)
    +			p = "int";
    +		break;
     	default:
     		break;
     	};
    diff --git a/sys/sys/syscall.h b/sys/sys/syscall.h
    index 6b0cd67be8e..5a2a1f6cf6e 100644
    --- a/sys/sys/syscall.h
    +++ b/sys/sys/syscall.h
    @@ -3,7 +3,7 @@
      *
      * DO NOT EDIT-- this file is automatically generated.
      * $FreeBSD$
    - * created from FreeBSD: head/sys/kern/syscalls.master 242958 2012-11-13 12:52:31Z kib 
    + * created from FreeBSD: head/sys/kern/syscalls.master 247602 2013-03-02 00:53:12Z pjd 
      */
     
     #define	SYS_syscall	0
    @@ -435,7 +435,7 @@
     #define	SYS_shmctl	512
     #define	SYS_lpathconf	513
     #define	SYS_cap_new	514
    -#define	SYS_cap_getrights	515
    +#define	SYS_cap_rights_get	515
     #define	SYS_cap_enter	516
     #define	SYS_cap_getmode	517
     #define	SYS_pdfork	518
    @@ -452,4 +452,9 @@
     #define	SYS_posix_fallocate	530
     #define	SYS_posix_fadvise	531
     #define	SYS_wait6	532
    -#define	SYS_MAXSYSCALL	533
    +#define	SYS_cap_rights_limit	533
    +#define	SYS_cap_ioctls_limit	534
    +#define	SYS_cap_ioctls_get	535
    +#define	SYS_cap_fcntls_limit	536
    +#define	SYS_cap_fcntls_get	537
    +#define	SYS_MAXSYSCALL	538
    diff --git a/sys/sys/syscall.mk b/sys/sys/syscall.mk
    index 25f0470bc1c..3e2a3d4f831 100644
    --- a/sys/sys/syscall.mk
    +++ b/sys/sys/syscall.mk
    @@ -1,7 +1,7 @@
     # FreeBSD system call names.
     # DO NOT EDIT-- this file is automatically generated.
     # $FreeBSD$
    -# created from FreeBSD: head/sys/kern/syscalls.master 242958 2012-11-13 12:52:31Z kib 
    +# created from FreeBSD: head/sys/kern/syscalls.master 247602 2013-03-02 00:53:12Z pjd 
     MIASM =  \
     	syscall.o \
     	exit.o \
    @@ -384,7 +384,7 @@ MIASM =  \
     	shmctl.o \
     	lpathconf.o \
     	cap_new.o \
    -	cap_getrights.o \
    +	cap_rights_get.o \
     	cap_enter.o \
     	cap_getmode.o \
     	pdfork.o \
    @@ -400,4 +400,9 @@ MIASM =  \
     	rctl_remove_rule.o \
     	posix_fallocate.o \
     	posix_fadvise.o \
    -	wait6.o
    +	wait6.o \
    +	cap_rights_limit.o \
    +	cap_ioctls_limit.o \
    +	cap_ioctls_get.o \
    +	cap_fcntls_limit.o \
    +	cap_fcntls_get.o
    diff --git a/sys/sys/sysproto.h b/sys/sys/sysproto.h
    index ef59ad5af6d..8ef408079b9 100644
    --- a/sys/sys/sysproto.h
    +++ b/sys/sys/sysproto.h
    @@ -3,7 +3,7 @@
      *
      * DO NOT EDIT-- this file is automatically generated.
      * $FreeBSD$
    - * created from FreeBSD: head/sys/kern/syscalls.master 242958 2012-11-13 12:52:31Z kib 
    + * created from FreeBSD: head/sys/kern/syscalls.master 247602 2013-03-02 00:53:12Z pjd 
      */
     
     #ifndef _SYS_SYSPROTO_H_
    @@ -1676,7 +1676,7 @@ struct cap_new_args {
     	char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
     	char rights_l_[PADL_(uint64_t)]; uint64_t rights; char rights_r_[PADR_(uint64_t)];
     };
    -struct cap_getrights_args {
    +struct cap_rights_get_args {
     	char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
     	char rightsp_l_[PADL_(uint64_t *)]; uint64_t * rightsp; char rightsp_r_[PADR_(uint64_t *)];
     };
    @@ -1762,6 +1762,28 @@ struct wait6_args {
     	char wrusage_l_[PADL_(struct __wrusage *)]; struct __wrusage * wrusage; char wrusage_r_[PADR_(struct __wrusage *)];
     	char info_l_[PADL_(siginfo_t *)]; siginfo_t * info; char info_r_[PADR_(siginfo_t *)];
     };
    +struct cap_rights_limit_args {
    +	char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
    +	char rights_l_[PADL_(uint64_t)]; uint64_t rights; char rights_r_[PADR_(uint64_t)];
    +};
    +struct cap_ioctls_limit_args {
    +	char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
    +	char cmds_l_[PADL_(const u_long *)]; const u_long * cmds; char cmds_r_[PADR_(const u_long *)];
    +	char ncmds_l_[PADL_(size_t)]; size_t ncmds; char ncmds_r_[PADR_(size_t)];
    +};
    +struct cap_ioctls_get_args {
    +	char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
    +	char cmds_l_[PADL_(u_long *)]; u_long * cmds; char cmds_r_[PADR_(u_long *)];
    +	char maxcmds_l_[PADL_(size_t)]; size_t maxcmds; char maxcmds_r_[PADR_(size_t)];
    +};
    +struct cap_fcntls_limit_args {
    +	char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
    +	char fcntlrights_l_[PADL_(uint32_t)]; uint32_t fcntlrights; char fcntlrights_r_[PADR_(uint32_t)];
    +};
    +struct cap_fcntls_get_args {
    +	char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
    +	char fcntlrightsp_l_[PADL_(uint32_t *)]; uint32_t * fcntlrightsp; char fcntlrightsp_r_[PADR_(uint32_t *)];
    +};
     int	nosys(struct thread *, struct nosys_args *);
     void	sys_sys_exit(struct thread *, struct sys_exit_args *);
     int	sys_fork(struct thread *, struct fork_args *);
    @@ -2127,7 +2149,7 @@ int	sys_msgctl(struct thread *, struct msgctl_args *);
     int	sys_shmctl(struct thread *, struct shmctl_args *);
     int	sys_lpathconf(struct thread *, struct lpathconf_args *);
     int	sys_cap_new(struct thread *, struct cap_new_args *);
    -int	sys_cap_getrights(struct thread *, struct cap_getrights_args *);
    +int	sys_cap_rights_get(struct thread *, struct cap_rights_get_args *);
     int	sys_cap_enter(struct thread *, struct cap_enter_args *);
     int	sys_cap_getmode(struct thread *, struct cap_getmode_args *);
     int	sys_pdfork(struct thread *, struct pdfork_args *);
    @@ -2144,6 +2166,11 @@ int	sys_rctl_remove_rule(struct thread *, struct rctl_remove_rule_args *);
     int	sys_posix_fallocate(struct thread *, struct posix_fallocate_args *);
     int	sys_posix_fadvise(struct thread *, struct posix_fadvise_args *);
     int	sys_wait6(struct thread *, struct wait6_args *);
    +int	sys_cap_rights_limit(struct thread *, struct cap_rights_limit_args *);
    +int	sys_cap_ioctls_limit(struct thread *, struct cap_ioctls_limit_args *);
    +int	sys_cap_ioctls_get(struct thread *, struct cap_ioctls_get_args *);
    +int	sys_cap_fcntls_limit(struct thread *, struct cap_fcntls_limit_args *);
    +int	sys_cap_fcntls_get(struct thread *, struct cap_fcntls_get_args *);
     
     #ifdef COMPAT_43
     
    @@ -2823,7 +2850,7 @@ int	freebsd7_shmctl(struct thread *, struct freebsd7_shmctl_args *);
     #define	SYS_AUE_shmctl	AUE_SHMCTL
     #define	SYS_AUE_lpathconf	AUE_LPATHCONF
     #define	SYS_AUE_cap_new	AUE_CAP_NEW
    -#define	SYS_AUE_cap_getrights	AUE_CAP_GETRIGHTS
    +#define	SYS_AUE_cap_rights_get	AUE_CAP_RIGHTS_GET
     #define	SYS_AUE_cap_enter	AUE_CAP_ENTER
     #define	SYS_AUE_cap_getmode	AUE_CAP_GETMODE
     #define	SYS_AUE_pdfork	AUE_PDFORK
    @@ -2840,6 +2867,11 @@ int	freebsd7_shmctl(struct thread *, struct freebsd7_shmctl_args *);
     #define	SYS_AUE_posix_fallocate	AUE_NULL
     #define	SYS_AUE_posix_fadvise	AUE_NULL
     #define	SYS_AUE_wait6	AUE_WAIT6
    +#define	SYS_AUE_cap_rights_limit	AUE_CAP_RIGHTS_LIMIT
    +#define	SYS_AUE_cap_ioctls_limit	AUE_CAP_IOCTLS_LIMIT
    +#define	SYS_AUE_cap_ioctls_get	AUE_CAP_IOCTLS_GET
    +#define	SYS_AUE_cap_fcntls_limit	AUE_CAP_FCNTLS_LIMIT
    +#define	SYS_AUE_cap_fcntls_get	AUE_CAP_FCNTLS_GET
     
     #undef PAD_
     #undef PADL_
    
    From f29088987a3d43515435e136202ac48632806263 Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Sat, 2 Mar 2013 00:56:53 +0000
    Subject: [PATCH 0519/1476] Update existing regression tests after Capsicum
     overhaul.
    
    ---
     .../security/cap_test/cap_test_capabilities.c | 473 +++++++++++++-----
     .../security/cap_test/cap_test_relative.c     |   3 +-
     2 files changed, 362 insertions(+), 114 deletions(-)
    
    diff --git a/tools/regression/security/cap_test/cap_test_capabilities.c b/tools/regression/security/cap_test/cap_test_capabilities.c
    index 450ad88c510..b6423f8a6cc 100644
    --- a/tools/regression/security/cap_test/cap_test_capabilities.c
    +++ b/tools/regression/security/cap_test/cap_test_capabilities.c
    @@ -1,8 +1,12 @@
     /*-
      * Copyright (c) 2009-2011 Robert N. M. Watson
      * Copyright (c) 2011 Jonathan Anderson
    + * Copyright (c) 2012 FreeBSD Foundation
      * All rights reserved.
      *
    + * Portions of this software were developed by Pawel Jakub Dawidek under
    + * sponsorship from the FreeBSD Foundation.
    + *
      * Redistribution and use in source and binary forms, with or without
      * modification, are permitted provided that the following conditions
      * are met:
    @@ -43,6 +47,7 @@ __FBSDID("$FreeBSD$");
     #include 
     #include 
     #include 
    +#include 
     #include 
     #include 
     #include 
    @@ -60,14 +65,20 @@ __FBSDID("$FreeBSD$");
      */
     #define	CHECK_RESULT(syscall, rights_needed, succeeded)	do {		\
     	if ((rights & (rights_needed)) == (rights_needed)) {		\
    -		if (!(succeeded))					\
    +		if (succeeded) {					\
    +			if (success == -1)				\
    +				success = PASSED;			\
    +		} else {						\
     			SYSCALL_FAIL(syscall, "failed");		\
    +		}							\
     	} else {							\
    -		if (succeeded)						\
    +		if (succeeded) {					\
     			FAILX("%s:\tsucceeded when it shouldn't have"	\
    -			    " (rights 0x%jx)", #syscall, rights);	\
    -		else if (errno != ENOTCAPABLE)				\
    +			    " (rights 0x%jx)", #syscall,		\
    +			    (uintmax_t)rights);				\
    +		} else if (errno != ENOTCAPABLE) {			\
     			SYSCALL_FAIL(syscall, "errno != ENOTCAPABLE");	\
    +		}							\
     	}								\
     	errno = 0;							\
     } while (0)
    @@ -79,8 +90,11 @@ __FBSDID("$FreeBSD$");
     	if ((rights & (rights_needed)) == (rights_needed)) {		\
     		if (p == MAP_FAILED)					\
     			SYSCALL_FAIL(mmap, "failed");			\
    -		else							\
    +		else {							\
     			(void)munmap(p, getpagesize());			\
    +			if (success == -1)				\
    +				success = PASSED;			\
    +		}							\
     	} else {							\
     		if (p != MAP_FAILED) {					\
     			FAILX("%s:\tsucceeded when it shouldn't have"	\
    @@ -97,96 +111,200 @@ __FBSDID("$FreeBSD$");
      * make sure only those rights work. 
     */
     static int
    -try_file_ops(int fd, cap_rights_t rights)
    +try_file_ops(int filefd, int dirfd, cap_rights_t rights)
     {
     	struct stat sb;
     	struct statfs sf;
    -	int fd_cap, fd_capcap;
    +	cap_rights_t erights;
    +	int fd_cap, fd_capcap, dfd_cap;
     	ssize_t ssize, ssize2;
     	off_t off;
     	void *p;
     	char ch;
     	int ret, is_nfs;
     	struct pollfd pollfd;
    -	int success = PASSED;
    +	int success = -1;
     
    -	REQUIRE(fstatfs(fd, &sf));
    -	is_nfs = (strncmp("nfs", sf.f_fstypename, sizeof(sf.f_fstypename))
    -	    == 0);
    +	REQUIRE(fstatfs(filefd, &sf));
    +	is_nfs = (strcmp("nfs", sf.f_fstypename) == 0);
     
    -	REQUIRE(fd_cap = cap_new(fd, rights));
    +	REQUIRE(fd_cap = cap_new(filefd, rights));
    +	CHECK(cap_getrights(fd_cap, &erights) == 0);
    +	CHECK(rights == erights);
     	REQUIRE(fd_capcap = cap_new(fd_cap, rights));
    +	CHECK(cap_getrights(fd_capcap, &erights) == 0);
    +	CHECK(rights == erights);
     	CHECK(fd_capcap != fd_cap);
    -
    -	pollfd.fd = fd_cap;
    -	pollfd.events = POLLIN | POLLERR | POLLHUP;
    -	pollfd.revents = 0;
    +	REQUIRE(dfd_cap = cap_new(dirfd, rights));
    +	CHECK(cap_getrights(dfd_cap, &erights) == 0);
    +	CHECK(rights == erights);
     
     	ssize = read(fd_cap, &ch, sizeof(ch));
    -	CHECK_RESULT(read, CAP_READ | CAP_SEEK, ssize >= 0);
    -
    -	ssize = pread(fd_cap, &ch, sizeof(ch), 0);
    -	ssize2 = pread(fd_cap, &ch, sizeof(ch), 0);
    -	CHECK_RESULT(pread, CAP_READ, ssize >= 0);
    -	CHECK(ssize == ssize2);
    +	CHECK_RESULT(read, CAP_READ, ssize >= 0);
     
     	ssize = write(fd_cap, &ch, sizeof(ch));
    -	CHECK_RESULT(write, CAP_WRITE | CAP_SEEK, ssize >= 0);
    -
    -	ssize = pwrite(fd_cap, &ch, sizeof(ch), 0);
    -	CHECK_RESULT(pwrite, CAP_WRITE, ssize >= 0);
    +	CHECK_RESULT(write, CAP_WRITE, ssize >= 0);
     
     	off = lseek(fd_cap, 0, SEEK_SET);
     	CHECK_RESULT(lseek, CAP_SEEK, off >= 0);
     
    +	ssize = pread(fd_cap, &ch, sizeof(ch), 0);
    +	ssize2 = pread(fd_cap, &ch, sizeof(ch), 0);
    +	CHECK_RESULT(pread, CAP_PREAD, ssize >= 0);
    +	CHECK(ssize == ssize2);
    +
    +	ssize = pwrite(fd_cap, &ch, sizeof(ch), 0);
    +	CHECK_RESULT(pwrite, CAP_PWRITE, ssize >= 0);
    +
    +	p = mmap(NULL, getpagesize(), PROT_NONE, MAP_SHARED, fd_cap, 0);
    +	CHECK_MMAP_RESULT(CAP_MMAP);
    +
    +	p = mmap(NULL, getpagesize(), PROT_READ, MAP_SHARED, fd_cap, 0);
    +	CHECK_MMAP_RESULT(CAP_MMAP_R);
    +
    +	p = mmap(NULL, getpagesize(), PROT_WRITE, MAP_SHARED, fd_cap, 0);
    +	CHECK_MMAP_RESULT(CAP_MMAP_W);
    +
    +	p = mmap(NULL, getpagesize(), PROT_EXEC, MAP_SHARED, fd_cap, 0);
    +	CHECK_MMAP_RESULT(CAP_MMAP_X);
    +
    +	p = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED,
    +	    fd_cap, 0);
    +	CHECK_MMAP_RESULT(CAP_MMAP_RW);
    +
    +	p = mmap(NULL, getpagesize(), PROT_READ | PROT_EXEC, MAP_SHARED,
    +	    fd_cap, 0);
    +	CHECK_MMAP_RESULT(CAP_MMAP_RX);
    +
    +	p = mmap(NULL, getpagesize(), PROT_EXEC | PROT_WRITE, MAP_SHARED,
    +	    fd_cap, 0);
    +	CHECK_MMAP_RESULT(CAP_MMAP_WX);
    +
    +	p = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC,
    +	    MAP_SHARED, fd_cap, 0);
    +	CHECK_MMAP_RESULT(CAP_MMAP_RWX);
    +
    +	/* TODO: openat(O_APPEND) */
    +	ret = openat(dfd_cap, "cap_create", O_CREAT | O_RDONLY, 0600);
    +	CHECK_RESULT(openat(O_CREATE | O_RDONLY),
    +	    CAP_CREATE | CAP_READ | CAP_LOOKUP, ret >= 0);
    +	CHECK(ret == -1 || close(ret) == 0);
    +	CHECK(ret == -1 || unlinkat(dirfd, "cap_create", 0) == 0);
    +	ret = openat(dfd_cap, "cap_create", O_CREAT | O_WRONLY, 0600);
    +	CHECK_RESULT(openat(O_CREATE | O_WRONLY),
    +	    CAP_CREATE | CAP_WRITE | CAP_LOOKUP, ret >= 0);
    +	CHECK(ret == -1 || close(ret) == 0);
    +	CHECK(ret == -1 || unlinkat(dirfd, "cap_create", 0) == 0);
    +	ret = openat(dfd_cap, "cap_create", O_CREAT | O_RDWR, 0600);
    +	CHECK_RESULT(openat(O_CREATE | O_RDWR),
    +	    CAP_CREATE | CAP_READ | CAP_WRITE | CAP_LOOKUP, ret >= 0);
    +	CHECK(ret == -1 || close(ret) == 0);
    +	CHECK(ret == -1 || unlinkat(dirfd, "cap_create", 0) == 0);
    +
    +	ret = fsync(fd_cap);
    +	CHECK_RESULT(fsync, CAP_FSYNC, ret == 0);
    +
    +	ret = openat(dirfd, "cap_fsync", O_CREAT, 0600);
    +	CHECK(ret >= 0);
    +	CHECK(close(ret) == 0);
    +	ret = openat(dfd_cap, "cap_fsync", O_FSYNC | O_RDONLY, 0600);
    +	CHECK_RESULT(openat(O_FSYNC | O_RDONLY),
    +	    CAP_FSYNC | CAP_READ | CAP_LOOKUP, ret >= 0);
    +	CHECK(ret == -1 || close(ret) == 0);
    +	ret = openat(dfd_cap, "cap_fsync", O_FSYNC | O_WRONLY, 0600);
    +	CHECK_RESULT(openat(O_FSYNC | O_WRONLY),
    +	    CAP_FSYNC | CAP_WRITE | CAP_LOOKUP, ret >= 0);
    +	CHECK(ret == -1 || close(ret) == 0);
    +	ret = openat(dfd_cap, "cap_fsync", O_FSYNC | O_RDWR, 0600);
    +	CHECK_RESULT(openat(O_FSYNC | O_RDWR),
    +	    CAP_FSYNC | CAP_READ | CAP_WRITE | CAP_LOOKUP, ret >= 0);
    +	CHECK(ret == -1 || close(ret) == 0);
    +	ret = openat(dfd_cap, "cap_fsync", O_SYNC | O_RDONLY, 0600);
    +	CHECK_RESULT(openat(O_SYNC | O_RDONLY),
    +	    CAP_FSYNC | CAP_READ | CAP_LOOKUP, ret >= 0);
    +	CHECK(ret == -1 || close(ret) == 0);
    +	ret = openat(dfd_cap, "cap_fsync", O_SYNC | O_WRONLY, 0600);
    +	CHECK_RESULT(openat(O_SYNC | O_WRONLY),
    +	    CAP_FSYNC | CAP_WRITE | CAP_LOOKUP, ret >= 0);
    +	CHECK(ret == -1 || close(ret) == 0);
    +	ret = openat(dfd_cap, "cap_fsync", O_SYNC | O_RDWR, 0600);
    +	CHECK_RESULT(openat(O_SYNC | O_RDWR),
    +	    CAP_FSYNC | CAP_READ | CAP_WRITE | CAP_LOOKUP, ret >= 0);
    +	CHECK(ret == -1 || close(ret) == 0);
    +	CHECK(unlinkat(dirfd, "cap_fsync", 0) == 0);
    +
    +	ret = ftruncate(fd_cap, 0);
    +	CHECK_RESULT(ftruncate, CAP_FTRUNCATE, ret == 0);
    +
    +	ret = openat(dirfd, "cap_ftruncate", O_CREAT, 0600);
    +	CHECK(ret >= 0);
    +	CHECK(close(ret) == 0);
    +	ret = openat(dfd_cap, "cap_ftruncate", O_TRUNC | O_RDONLY);
    +	CHECK_RESULT(openat(O_TRUNC | O_RDONLY),
    +	    CAP_FTRUNCATE | CAP_READ | CAP_LOOKUP, ret >= 0);
    +	CHECK(ret == -1 || close(ret) == 0);
    +	ret = openat(dfd_cap, "cap_ftruncate", O_TRUNC | O_WRONLY);
    +	CHECK_RESULT(openat(O_TRUNC | O_WRONLY),
    +	    CAP_FTRUNCATE | CAP_WRITE | CAP_LOOKUP, ret >= 0);
    +	CHECK(ret == -1 || close(ret) == 0);
    +	ret = openat(dfd_cap, "cap_ftruncate", O_TRUNC | O_RDWR);
    +	CHECK_RESULT(openat(O_TRUNC | O_RDWR),
    +	    CAP_FTRUNCATE | CAP_READ | CAP_WRITE | CAP_LOOKUP, ret >= 0);
    +	CHECK(ret == -1 || close(ret) == 0);
    +	CHECK(unlinkat(dirfd, "cap_ftruncate", 0) == 0);
    +
     	/*
     	 * Note: this is not expected to work over NFS.
     	 */
     	ret = fchflags(fd_cap, UF_NODUMP);
     	CHECK_RESULT(fchflags, CAP_FCHFLAGS,
    -	    (ret == 0) || (is_nfs && (errno == EOPNOTSUPP)));
    +	    ret == 0 || (is_nfs && errno == EOPNOTSUPP));
     
    -	ret = fstat(fd_cap, &sb);
    -	CHECK_RESULT(fstat, CAP_FSTAT, ret == 0);
    -
    -	p = mmap(NULL, getpagesize(), PROT_READ, MAP_SHARED, fd_cap, 0);
    -	CHECK_MMAP_RESULT(CAP_MMAP | CAP_READ);
    -
    -	p = mmap(NULL, getpagesize(), PROT_WRITE, MAP_SHARED, fd_cap, 0);
    -	CHECK_MMAP_RESULT(CAP_MMAP | CAP_WRITE);
    -
    -	p = mmap(NULL, getpagesize(), PROT_EXEC, MAP_SHARED, fd_cap, 0);
    -	CHECK_MMAP_RESULT(CAP_MMAP | CAP_MAPEXEC);
    -
    -	p = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED,
    -	    fd_cap, 0);
    -	CHECK_MMAP_RESULT(CAP_MMAP | CAP_READ | CAP_WRITE);
    -
    -	p = mmap(NULL, getpagesize(), PROT_READ | PROT_EXEC, MAP_SHARED,
    -	    fd_cap, 0);
    -	CHECK_MMAP_RESULT(CAP_MMAP | CAP_READ | CAP_MAPEXEC);
    -
    -	p = mmap(NULL, getpagesize(), PROT_EXEC | PROT_WRITE, MAP_SHARED,
    -	    fd_cap, 0);
    -	CHECK_MMAP_RESULT(CAP_MMAP | CAP_MAPEXEC | CAP_WRITE);
    -
    -	p = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC,
    -	    MAP_SHARED, fd_cap, 0);
    -	CHECK_MMAP_RESULT(CAP_MMAP | CAP_READ | CAP_WRITE | CAP_MAPEXEC);
    -
    -	ret = fsync(fd_cap);
    -	CHECK_RESULT(fsync, CAP_FSYNC, ret == 0);
    +#ifdef TODO	/* No such syscalls yet. */
    +	ret = openat(dirfd, "cap_fchflagsat", O_CREAT, 0600);
    +	CHECK(ret >= 0);
    +	CHECK(close(ret) == 0);
    +	ret = fchflagsat(dfd_cap, "cap_fchflagsat", UF_NODUMP, 0);
    +	CHECK_RESULT(fchflagsat, CAP_FCHFLAGSAT | CAP_LOOKUP, ret == 0);
    +	CHECK(unlinkat(dirfd, "cap_fchflagsat", 0) == 0);
    +#endif
     
     	ret = fchown(fd_cap, -1, -1);
     	CHECK_RESULT(fchown, CAP_FCHOWN, ret == 0);
     
    +	ret = openat(dirfd, "cap_fchownat", O_CREAT, 0600);
    +	CHECK(ret >= 0);
    +	CHECK(close(ret) == 0);
    +	ret = fchownat(dfd_cap, "cap_fchownat", -1, -1, 0);
    +	CHECK_RESULT(fchownat, CAP_FCHOWN | CAP_LOOKUP, ret == 0);
    +	CHECK(unlinkat(dirfd, "cap_fchownat", 0) == 0);
    +
     	ret = fchmod(fd_cap, 0644);
     	CHECK_RESULT(fchmod, CAP_FCHMOD, ret == 0);
     
    +	ret = openat(dirfd, "cap_fchmodat", O_CREAT, 0600);
    +	CHECK(ret >= 0);
    +	CHECK(close(ret) == 0);
    +	ret = fchmodat(dfd_cap, "cap_fchmodat", 0600, 0);
    +	CHECK_RESULT(fchmodat, CAP_FCHMOD | CAP_LOOKUP, ret == 0);
    +	CHECK(unlinkat(dirfd, "cap_fchmodat", 0) == 0);
    +
    +	ret = fcntl(fd_cap, F_GETFL);
    +	CHECK_RESULT(fcntl(F_GETFL), CAP_FCNTL, ret >= 0);
    +	ret = fcntl(fd_cap, F_SETFL, ret);
    +	CHECK_RESULT(fcntl(F_SETFL), CAP_FCNTL, ret == 0);
    +
     	/* XXX flock */
     
    -	ret = ftruncate(fd_cap, 0);
    -	CHECK_RESULT(ftruncate, CAP_FTRUNCATE, ret == 0);
    +	ret = fstat(fd_cap, &sb);
    +	CHECK_RESULT(fstat, CAP_FSTAT, ret == 0);
    +
    +	ret = openat(dirfd, "cap_fstatat", O_CREAT, 0600);
    +	CHECK(ret >= 0);
    +	CHECK(close(ret) == 0);
    +	ret = fstatat(dfd_cap, "cap_fstatat", &sb, 0);
    +	CHECK_RESULT(fstatat, CAP_FSTAT | CAP_LOOKUP, ret == 0);
    +	CHECK(unlinkat(dirfd, "cap_fstatat", 0) == 0);
     
     	ret = fstatfs(fd_cap, &sf);
     	CHECK_RESULT(fstatfs, CAP_FSTATFS, ret == 0);
    @@ -197,6 +315,55 @@ try_file_ops(int fd, cap_rights_t rights)
     	ret = futimes(fd_cap, NULL);
     	CHECK_RESULT(futimes, CAP_FUTIMES, ret == 0);
     
    +	ret = openat(dirfd, "cap_futimesat", O_CREAT, 0600);
    +	CHECK(ret >= 0);
    +	CHECK(close(ret) == 0);
    +	ret = futimesat(dfd_cap, "cap_futimesat", NULL);
    +	CHECK_RESULT(futimesat, CAP_FUTIMES | CAP_LOOKUP, ret == 0);
    +	CHECK(unlinkat(dirfd, "cap_futimesat", 0) == 0);
    +
    +	ret = openat(dirfd, "cap_linkat_src", O_CREAT, 0600);
    +	CHECK(ret >= 0);
    +	CHECK(close(ret) == 0);
    +	ret = linkat(dirfd, "cap_linkat_src", dfd_cap, "cap_linkat_dst", 0);
    +	CHECK_RESULT(linkat, CAP_LINKAT | CAP_LOOKUP, ret == 0);
    +	CHECK(unlinkat(dirfd, "cap_linkat_src", 0) == 0);
    +	CHECK(ret == -1 || unlinkat(dirfd, "cap_linkat_dst", 0) == 0);
    +
    +	ret = mkdirat(dfd_cap, "cap_mkdirat", 0700);
    +	CHECK_RESULT(mkdirat, CAP_MKDIRAT | CAP_LOOKUP, ret == 0);
    +	CHECK(ret == -1 || unlinkat(dirfd, "cap_mkdirat", AT_REMOVEDIR) == 0);
    +
    +	ret = mkfifoat(dfd_cap, "cap_mkfifoat", 0600);
    +	CHECK_RESULT(mkfifoat, CAP_MKFIFOAT | CAP_LOOKUP, ret == 0);
    +	CHECK(ret == -1 || unlinkat(dirfd, "cap_mkfifoat", 0) == 0);
    +
    +	ret = mknodat(dfd_cap, "cap_mknodat", S_IFCHR | 0600, 0);
    +	CHECK_RESULT(mknodat, CAP_MKNODAT | CAP_LOOKUP, ret == 0);
    +	CHECK(ret == -1 || unlinkat(dirfd, "cap_mknodat", 0) == 0);
    +
    +	/* TODO: renameat(2) */
    +
    +	ret = symlinkat("test", dfd_cap, "cap_symlinkat");
    +	CHECK_RESULT(symlinkat, CAP_SYMLINKAT | CAP_LOOKUP, ret == 0);
    +	CHECK(ret == -1 || unlinkat(dirfd, "cap_symlinkat", 0) == 0);
    +
    +	ret = openat(dirfd, "cap_unlinkat", O_CREAT, 0600);
    +	CHECK(ret >= 0);
    +	CHECK(close(ret) == 0);
    +	ret = unlinkat(dfd_cap, "cap_unlinkat", 0);
    +	CHECK_RESULT(unlinkat, CAP_UNLINKAT | CAP_LOOKUP, ret == 0);
    +	CHECK(ret == 0 || unlinkat(dirfd, "cap_unlinkat", 0) == 0);
    +	ret = mkdirat(dirfd, "cap_unlinkat", 0700);
    +	CHECK(ret == 0);
    +	ret = unlinkat(dfd_cap, "cap_unlinkat", AT_REMOVEDIR);
    +	CHECK_RESULT(unlinkat, CAP_UNLINKAT | CAP_LOOKUP, ret == 0);
    +	CHECK(ret == 0 || unlinkat(dirfd, "cap_unlinkat", AT_REMOVEDIR) == 0);
    +
    +	pollfd.fd = fd_cap;
    +	pollfd.events = POLLIN | POLLERR | POLLHUP;
    +	pollfd.revents = 0;
    +
     	ret = poll(&pollfd, 1, 0);
     	if (rights & CAP_POLL_EVENT)
     		CHECK((pollfd.revents & POLLNVAL) == 0);
    @@ -205,79 +372,159 @@ try_file_ops(int fd, cap_rights_t rights)
     
     	/* XXX: select, kqueue */
     
    -	close (fd_cap);
    +	close(fd_cap);
    +	close(fd_capcap);
    +
    +	if (success == -1) {
    +		fprintf(stderr, "No tests for rights 0x%jx.\n",
    +		    (uintmax_t)rights);
    +		success = FAILED;
    +	}
     	return (success);
     }
     
    -#define TRY(fd, rights) \
    +#define TRY(rights) \
     do { \
     	if (success == PASSED) \
    -		success = try_file_ops(fd, rights); \
    +		success = try_file_ops(filefd, dirfd, (rights)); \
     	else \
     		/* We've already failed, but try the test anyway. */ \
    -		try_file_ops(fd, rights); \
    +		try_file_ops(filefd, dirfd, (rights)); \
     } while (0)
     
    +#define	KEEP_ERRNO(...)	do {						\
    +	int _saved_errno = errno;					\
    +	__VA_ARGS__;							\
    +	errno = _saved_errno;						\
    +} while (0);
    +
     int
     test_capabilities(void)
     {
    -	int fd;
    +	int filefd, dirfd, tmpfd;
     	int success = PASSED;
    +	char file[] = "/tmp/cap_test.XXXXXXXXXX";
    +	char dir[] = "/tmp/cap_test.XXXXXXXXXX";
     
    -	fd = open("/tmp/cap_test_capabilities", O_RDWR | O_CREAT, 0644);
    -	if (fd < 0)
    +	filefd = mkstemp(file);
    +	if (filefd < 0)
    +		err(-1, "mkstemp");
    +	if (mkdtemp(dir) == NULL) {
    +		KEEP_ERRNO(unlink(file));
    +		err(-1, "mkdtemp");
    +	}
    +	dirfd = open(dir, O_RDONLY | O_DIRECTORY);
    +	if (dirfd == -1) {
    +		KEEP_ERRNO(unlink(file));
    +		KEEP_ERRNO(rmdir(dir));
     		err(-1, "open");
    +	}
    +	tmpfd = open("/tmp", O_RDONLY | O_DIRECTORY);
    +	if (tmpfd == -1) {
    +		KEEP_ERRNO(unlink(file));
    +		KEEP_ERRNO(rmdir(dir));
    +		err(-1, "open");
    +	}
     
    -	if (cap_enter() < 0)
    +	if (cap_enter() == -1) {
    +		KEEP_ERRNO(unlink(file));
    +		KEEP_ERRNO(rmdir(dir));
     		err(-1, "cap_enter");
    +	}
     
    -	/* XXX: Really want to try all combinations. */
    -	TRY(fd, CAP_READ);
    -	TRY(fd, CAP_READ | CAP_SEEK);
    -	TRY(fd, CAP_WRITE);
    -	TRY(fd, CAP_WRITE | CAP_SEEK);
    -	TRY(fd, CAP_READ | CAP_WRITE);
    -	TRY(fd, CAP_READ | CAP_WRITE | CAP_SEEK);
    -	TRY(fd, CAP_SEEK);
    -	TRY(fd, CAP_FCHFLAGS);
    -	TRY(fd, CAP_IOCTL);
    -	TRY(fd, CAP_FSTAT);
    -	TRY(fd, CAP_MMAP);
    -	TRY(fd, CAP_MMAP | CAP_READ);
    -	TRY(fd, CAP_MMAP | CAP_WRITE);
    -	TRY(fd, CAP_MMAP | CAP_MAPEXEC);
    -	TRY(fd, CAP_MMAP | CAP_READ | CAP_WRITE);
    -	TRY(fd, CAP_MMAP | CAP_READ | CAP_MAPEXEC);
    -	TRY(fd, CAP_MMAP | CAP_MAPEXEC | CAP_WRITE);
    -	TRY(fd, CAP_MMAP | CAP_READ | CAP_WRITE | CAP_MAPEXEC);
    -	TRY(fd, CAP_FCNTL);
    -	TRY(fd, CAP_POST_EVENT);
    -	TRY(fd, CAP_POLL_EVENT);
    -	TRY(fd, CAP_FSYNC);
    -	TRY(fd, CAP_FCHOWN);
    -	TRY(fd, CAP_FCHMOD);
    -	TRY(fd, CAP_FTRUNCATE);
    -	TRY(fd, CAP_FLOCK);
    -	TRY(fd, CAP_FSTATFS);
    -	TRY(fd, CAP_FPATHCONF);
    -	TRY(fd, CAP_FUTIMES);
    -	TRY(fd, CAP_ACL_GET);
    -	TRY(fd, CAP_ACL_SET);
    -	TRY(fd, CAP_ACL_DELETE);
    -	TRY(fd, CAP_ACL_CHECK);
    -	TRY(fd, CAP_EXTATTR_GET);
    -	TRY(fd, CAP_EXTATTR_SET);
    -	TRY(fd, CAP_EXTATTR_DELETE);
    -	TRY(fd, CAP_EXTATTR_LIST);
    -	TRY(fd, CAP_MAC_GET);
    -	TRY(fd, CAP_MAC_SET);
    +	TRY(CAP_READ);
    +	TRY(CAP_WRITE);
    +	TRY(CAP_SEEK);
    +	TRY(CAP_PREAD);
    +	TRY(CAP_PWRITE);
    +	TRY(CAP_READ | CAP_WRITE);
    +	TRY(CAP_PREAD | CAP_PWRITE);
    +	TRY(CAP_MMAP);
    +	TRY(CAP_MMAP_R);
    +	TRY(CAP_MMAP_W);
    +	TRY(CAP_MMAP_X);
    +	TRY(CAP_MMAP_RW);
    +	TRY(CAP_MMAP_RX);
    +	TRY(CAP_MMAP_WX);
    +	TRY(CAP_MMAP_RWX);
    +	TRY(CAP_CREATE | CAP_READ | CAP_LOOKUP);
    +	TRY(CAP_CREATE | CAP_WRITE | CAP_LOOKUP);
    +	TRY(CAP_CREATE | CAP_READ | CAP_WRITE | CAP_LOOKUP);
    +#ifdef TODO
    +	TRY(CAP_FEXECVE);
    +#endif
    +	TRY(CAP_FSYNC);
    +	TRY(CAP_FSYNC | CAP_READ | CAP_LOOKUP);
    +	TRY(CAP_FSYNC | CAP_WRITE | CAP_LOOKUP);
    +	TRY(CAP_FSYNC | CAP_READ | CAP_WRITE | CAP_LOOKUP);
    +	TRY(CAP_FTRUNCATE);
    +	TRY(CAP_FTRUNCATE | CAP_READ | CAP_LOOKUP);
    +	TRY(CAP_FTRUNCATE | CAP_WRITE | CAP_LOOKUP);
    +	TRY(CAP_FTRUNCATE | CAP_READ | CAP_WRITE | CAP_LOOKUP);
    +#ifdef TODO
    +	TRY(CAP_FCHDIR);
    +#endif
    +	TRY(CAP_FCHFLAGS);
    +	TRY(CAP_FCHOWN);
    +	TRY(CAP_FCHOWN | CAP_LOOKUP);
    +	TRY(CAP_FCHMOD | CAP_LOOKUP);
    +	TRY(CAP_FCNTL);
    +#ifdef TODO
    +	TRY(CAP_FLOCK);
    +#endif
    +	TRY(CAP_FPATHCONF);
    +#ifdef TODO
    +	TRY(CAP_FSCK);
    +#endif
    +	TRY(CAP_FSTAT | CAP_LOOKUP);
    +	TRY(CAP_FSTATFS);
    +	TRY(CAP_FUTIMES | CAP_LOOKUP);
    +	TRY(CAP_LINKAT | CAP_LOOKUP);
    +	TRY(CAP_MKDIRAT | CAP_LOOKUP);
    +	TRY(CAP_MKFIFOAT | CAP_LOOKUP);
    +	TRY(CAP_MKNODAT | CAP_LOOKUP);
    +	TRY(CAP_SYMLINKAT | CAP_LOOKUP);
    +	TRY(CAP_UNLINKAT | CAP_LOOKUP);
    +	/* Rename needs CAP_RENAMEAT on source directory and CAP_LINKAT on destination directory. */
    +	TRY(CAP_RENAMEAT | CAP_UNLINKAT | CAP_LOOKUP);
    +#ifdef TODO
    +	TRY(CAP_LOOKUP);
    +	TRY(CAP_EXTATTR_DELETE);
    +	TRY(CAP_EXTATTR_GET);
    +	TRY(CAP_EXTATTR_LIST);
    +	TRY(CAP_EXTATTR_SET);
    +	TRY(CAP_ACL_CHECK);
    +	TRY(CAP_ACL_DELETE);
    +	TRY(CAP_ACL_GET);
    +	TRY(CAP_ACL_SET);
    +	TRY(CAP_ACCEPT);
    +	TRY(CAP_BIND);
    +	TRY(CAP_CONNECT);
    +	TRY(CAP_GETPEERNAME);
    +	TRY(CAP_GETSOCKNAME);
    +	TRY(CAP_GETSOCKOPT);
    +	TRY(CAP_LISTEN);
    +	TRY(CAP_PEELOFF);
    +	TRY(CAP_RECV);
    +	TRY(CAP_SEND);
    +	TRY(CAP_SETSOCKOPT);
    +	TRY(CAP_SHUTDOWN);
    +	TRY(CAP_MAC_GET);
    +	TRY(CAP_MAC_SET);
    +	TRY(CAP_SEM_GETVALUE);
    +	TRY(CAP_SEM_POST);
    +	TRY(CAP_SEM_WAIT);
    +	TRY(CAP_POST_EVENT);
    +	TRY(CAP_POLL_EVENT);
    +	TRY(CAP_IOCTL);
    +	TRY(CAP_TTYHOOK);
    +	TRY(CAP_PDGETPID);
    +	TRY(CAP_PDWAIT);
    +	TRY(CAP_PDKILL);
    +#endif
     
    -	/*
    -	 * Socket-specific.
    -	 */
    -	TRY(fd, CAP_GETPEERNAME);
    -	TRY(fd, CAP_GETSOCKNAME);
    -	TRY(fd, CAP_ACCEPT);
    +	(void)unlinkat(tmpfd, file + strlen("/tmp/"), 0);
    +	(void)unlinkat(tmpfd, dir + strlen("/tmp/"), AT_REMOVEDIR);
     
     	return (success);
     }
    diff --git a/tools/regression/security/cap_test/cap_test_relative.c b/tools/regression/security/cap_test/cap_test_relative.c
    index 1f62e848e07..27410eb5eef 100644
    --- a/tools/regression/security/cap_test/cap_test_relative.c
    +++ b/tools/regression/security/cap_test/cap_test_relative.c
    @@ -61,7 +61,8 @@ test_relative(void)
     	cap_rights_t rights;
     
     	REQUIRE(etc = open("/etc/", O_RDONLY));
    -	CHECK_SYSCALL_FAILS(EINVAL, cap_getrights, etc, &rights);
    +	CHECK_SYSCALL_SUCCEEDS(cap_getrights, etc, &rights);
    +	CHECK_RIGHTS(rights, CAP_ALL);
     
     	MAKE_CAPABILITY(etc_cap, etc, CAP_READ);
     	MAKE_CAPABILITY(etc_cap_ro, etc, CAP_READ | CAP_LOOKUP);
    
    From de503941768ff3ac147dfaf2b48bae4637777f53 Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Sat, 2 Mar 2013 01:00:26 +0000
    Subject: [PATCH 0520/1476] Add regression tests for the new Capsicum system
     calls.
    
    Sponsored by:	The FreeBSD Foundation
    ---
     tools/regression/capsicum/syscalls/Makefile   |  28 +
     .../capsicum/syscalls/cap_fcntls_limit.c      | 540 ++++++++++++++++++
     .../capsicum/syscalls/cap_getmode.c           | 167 ++++++
     .../capsicum/syscalls/cap_ioctls_limit.c      | 462 +++++++++++++++
     tools/regression/capsicum/syscalls/misc.c     | 128 +++++
     tools/regression/capsicum/syscalls/misc.h     |  62 ++
     6 files changed, 1387 insertions(+)
     create mode 100644 tools/regression/capsicum/syscalls/Makefile
     create mode 100644 tools/regression/capsicum/syscalls/cap_fcntls_limit.c
     create mode 100644 tools/regression/capsicum/syscalls/cap_getmode.c
     create mode 100644 tools/regression/capsicum/syscalls/cap_ioctls_limit.c
     create mode 100644 tools/regression/capsicum/syscalls/misc.c
     create mode 100644 tools/regression/capsicum/syscalls/misc.h
    
    diff --git a/tools/regression/capsicum/syscalls/Makefile b/tools/regression/capsicum/syscalls/Makefile
    new file mode 100644
    index 00000000000..5d342265628
    --- /dev/null
    +++ b/tools/regression/capsicum/syscalls/Makefile
    @@ -0,0 +1,28 @@
    +# $FreeBSD$
    +
    +SYSCALLS=	cap_fcntls_limit cap_getmode cap_ioctls_limit
    +
    +CFLAGS=		-O2 -pipe -std=gnu99 -fstack-protector
    +CFLAGS+=	-Wsystem-headers -Werror -Wall -Wno-format-y2k -W -Wno-unused-parameter
    +CFLAGS+=	-Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith -Wreturn-type
    +CFLAGS+=	-Wcast-qual -Wwrite-strings -Wswitch -Wshadow -Wunused-parameter
    +CFLAGS+=	-Wcast-align -Wchar-subscripts -Winline -Wnested-externs -Wredundant-decls
    +CFLAGS+=	-Wold-style-definition -Wno-pointer-sign
    +
    +all:	${SYSCALLS} ${SYSCALLS:=.t}
    +
    +.for SYSCALL in ${SYSCALLS}
    +
    +${SYSCALL}:	${SYSCALL}.c misc.c
    +	${CC} ${CFLAGS} ${@}.c misc.c -o $@
    +
    +${SYSCALL}.t:	${SYSCALL}
    +	@printf "#!/bin/sh\n\n%s/%s\n" ${.CURDIR} ${@:.t=} > $@
    +
    +.endfor
    +
    +test:	all
    +	@prove -r ${.CURDIR}
    +
    +clean:
    +	rm -f ${SYSCALLS} ${SYSCALLS:=.t}
    diff --git a/tools/regression/capsicum/syscalls/cap_fcntls_limit.c b/tools/regression/capsicum/syscalls/cap_fcntls_limit.c
    new file mode 100644
    index 00000000000..c97203d4775
    --- /dev/null
    +++ b/tools/regression/capsicum/syscalls/cap_fcntls_limit.c
    @@ -0,0 +1,540 @@
    +/*-
    + * Copyright (c) 2012 The FreeBSD Foundation
    + * All rights reserved.
    + *
    + * This software was developed by Pawel Jakub Dawidek under sponsorship from
    + * the FreeBSD Foundation.
    + *
    + * Redistribution and use in source and binary forms, with or without
    + * modification, are permitted provided that the following conditions
    + * are met:
    + * 1. Redistributions of source code must retain the above copyright
    + *    notice, this list of conditions and the following disclaimer.
    + * 2. Redistributions in binary form must reproduce the above copyright
    + *    notice, this list of conditions and the following disclaimer in the
    + *    documentation and/or other materials provided with the distribution.
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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 
    +__FBSDID("$FreeBSD$");
    +
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +
    +#include "misc.h"
    +
    +static void
    +fcntl_tests_0(int fd)
    +{
    +	uint32_t fcntlrights;
    +
    +	fcntlrights = 0;
    +	CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);
    +	CHECK(fcntlrights == CAP_FCNTL_ALL);
    +
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +	CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
    +	CHECK(fcntl(fd, F_SETFD, 0) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +
    +	CHECK(fcntl(fd, F_GETFL) == O_RDWR);
    +	CHECK(fcntl(fd, F_SETFL, O_NONBLOCK) == 0);
    +	CHECK(fcntl(fd, F_GETFL) == (O_RDWR | O_NONBLOCK));
    +	CHECK(fcntl(fd, F_SETFL, 0) == 0);
    +	CHECK(fcntl(fd, F_GETFL) == O_RDWR);
    +
    +	errno = 0;
    +	CHECK(cap_fcntls_limit(fd, ~CAP_FCNTL_ALL) == -1);
    +	CHECK(errno == EINVAL);
    +	CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL | CAP_FCNTL_SETFL) == 0);
    +	fcntlrights = 0;
    +	CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);
    +	CHECK(fcntlrights == (CAP_FCNTL_GETFL | CAP_FCNTL_SETFL));
    +	CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL | CAP_FCNTL_SETFL) == 0);
    +	fcntlrights = 0;
    +	CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);
    +	CHECK(fcntlrights == (CAP_FCNTL_GETFL | CAP_FCNTL_SETFL));
    +
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +	CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
    +	CHECK(fcntl(fd, F_SETFD, 0) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +
    +	CHECK(fcntl(fd, F_GETFL) == O_RDWR);
    +	CHECK(fcntl(fd, F_SETFL, O_NONBLOCK) == 0);
    +	CHECK(fcntl(fd, F_GETFL) == (O_RDWR | O_NONBLOCK));
    +	CHECK(fcntl(fd, F_SETFL, 0) == 0);
    +	CHECK(fcntl(fd, F_GETFL) == O_RDWR);
    +
    +	CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL) == 0);
    +	fcntlrights = 0;
    +	CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);
    +	CHECK(fcntlrights == CAP_FCNTL_GETFL);
    +	errno = 0;
    +	CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL | CAP_FCNTL_SETFL) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	fcntlrights = 0;
    +	CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);
    +	CHECK(fcntlrights == CAP_FCNTL_GETFL);
    +
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +	CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
    +	CHECK(fcntl(fd, F_SETFD, 0) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +
    +	CHECK(fcntl(fd, F_GETFL) == O_RDWR);
    +	errno = 0;
    +	CHECK(fcntl(fd, F_SETFL, O_NONBLOCK) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	CHECK(fcntl(fd, F_GETFL) == O_RDWR);
    +	errno = 0;
    +	CHECK(fcntl(fd, F_SETFL, 0) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	CHECK(fcntl(fd, F_GETFL) == O_RDWR);
    +
    +	CHECK(cap_fcntls_limit(fd, 0) == 0);
    +	fcntlrights = CAP_FCNTL_ALL;
    +	CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);
    +	CHECK(fcntlrights == 0);
    +	errno = 0;
    +	CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL | CAP_FCNTL_SETFL) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	fcntlrights = CAP_FCNTL_ALL;
    +	CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);
    +	CHECK(fcntlrights == 0);
    +	errno = 0;
    +	CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	fcntlrights = CAP_FCNTL_ALL;
    +	CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);
    +	CHECK(fcntlrights == 0);
    +
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +	CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
    +	CHECK(fcntl(fd, F_SETFD, 0) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +
    +	errno = 0;
    +	CHECK(fcntl(fd, F_GETFL) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	errno = 0;
    +	CHECK(fcntl(fd, F_SETFL, O_NONBLOCK) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	errno = 0;
    +	CHECK(fcntl(fd, F_SETFL, 0) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	errno = 0;
    +	CHECK(fcntl(fd, F_GETFL) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +}
    +
    +static void
    +fcntl_tests_1(int fd)
    +{
    +	uint32_t fcntlrights;
    +
    +	CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL) == 0);
    +	fcntlrights = 0;
    +	CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);
    +	CHECK(fcntlrights == CAP_FCNTL_GETFL);
    +
    +	CHECK(cap_rights_limit(fd, CAP_ALL & ~CAP_FCNTL) == 0);
    +
    +	fcntlrights = CAP_FCNTL_ALL;
    +	CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);
    +	CHECK(fcntlrights == 0);
    +
    +	errno = 0;
    +	CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL | CAP_FCNTL_SETFL) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	fcntlrights = CAP_FCNTL_ALL;
    +	CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);
    +	CHECK(fcntlrights == 0);
    +	errno = 0;
    +	CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	fcntlrights = CAP_FCNTL_ALL;
    +	CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);
    +	CHECK(fcntlrights == 0);
    +
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +	CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
    +	CHECK(fcntl(fd, F_SETFD, 0) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +
    +	errno = 0;
    +	CHECK(fcntl(fd, F_GETFL) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	errno = 0;
    +	CHECK(fcntl(fd, F_SETFL, O_NONBLOCK) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	errno = 0;
    +	CHECK(fcntl(fd, F_SETFL, 0) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	errno = 0;
    +	CHECK(fcntl(fd, F_GETFL) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +}
    +
    +static void
    +fcntl_tests_2(int fd)
    +{
    +	uint32_t fcntlrights;
    +
    +	CHECK(cap_rights_limit(fd, CAP_ALL & ~CAP_FCNTL) == 0);
    +
    +	fcntlrights = CAP_FCNTL_ALL;
    +	CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);
    +	CHECK(fcntlrights == 0);
    +
    +	errno = 0;
    +	CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL | CAP_FCNTL_SETFL) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	fcntlrights = CAP_FCNTL_ALL;
    +	CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);
    +	CHECK(fcntlrights == 0);
    +	errno = 0;
    +	CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	fcntlrights = CAP_FCNTL_ALL;
    +	CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);
    +	CHECK(fcntlrights == 0);
    +
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +	CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
    +	CHECK(fcntl(fd, F_SETFD, 0) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +
    +	errno = 0;
    +	CHECK(fcntl(fd, F_GETFL) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	errno = 0;
    +	CHECK(fcntl(fd, F_SETFL, O_NONBLOCK) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	errno = 0;
    +	CHECK(fcntl(fd, F_SETFL, 0) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	errno = 0;
    +	CHECK(fcntl(fd, F_GETFL) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +}
    +
    +static void
    +fcntl_tests_send_0(int sock)
    +{
    +	int fd;
    +
    +	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
    +	CHECK(descriptor_send(sock, fd) == 0);
    +	CHECK(close(fd) == 0);
    +
    +	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
    +	CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL | CAP_FCNTL_SETFL) == 0);
    +	CHECK(descriptor_send(sock, fd) == 0);
    +	CHECK(close(fd) == 0);
    +
    +	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
    +	CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL) == 0);
    +	CHECK(descriptor_send(sock, fd) == 0);
    +	CHECK(close(fd) == 0);
    +
    +	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
    +	CHECK(cap_fcntls_limit(fd, 0) == 0);
    +	CHECK(descriptor_send(sock, fd) == 0);
    +	CHECK(close(fd) == 0);
    +}
    +
    +static void
    +fcntl_tests_recv_0(int sock)
    +{
    +	uint32_t fcntlrights;
    +	int fd;
    +
    +	CHECK(descriptor_recv(sock, &fd) == 0);
    +
    +	fcntlrights = 0;
    +	CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);
    +	CHECK(fcntlrights == CAP_FCNTL_ALL);
    +
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +	CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
    +	CHECK(fcntl(fd, F_SETFD, 0) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +
    +	CHECK(fcntl(fd, F_GETFL) == O_RDWR);
    +	CHECK(fcntl(fd, F_SETFL, O_NONBLOCK) == 0);
    +	CHECK(fcntl(fd, F_GETFL) == (O_RDWR | O_NONBLOCK));
    +	CHECK(fcntl(fd, F_SETFL, 0) == 0);
    +	CHECK(fcntl(fd, F_GETFL) == O_RDWR);
    +
    +	CHECK(close(fd) == 0);
    +
    +	CHECK(descriptor_recv(sock, &fd) == 0);
    +
    +	fcntlrights = 0;
    +	CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);
    +	CHECK(fcntlrights == (CAP_FCNTL_GETFL | CAP_FCNTL_SETFL));
    +	CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL | CAP_FCNTL_SETFL) == 0);
    +	fcntlrights = 0;
    +	CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);
    +	CHECK(fcntlrights == (CAP_FCNTL_GETFL | CAP_FCNTL_SETFL));
    +
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +	CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
    +	CHECK(fcntl(fd, F_SETFD, 0) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +
    +	CHECK(fcntl(fd, F_GETFL) == O_RDWR);
    +	CHECK(fcntl(fd, F_SETFL, O_NONBLOCK) == 0);
    +	CHECK(fcntl(fd, F_GETFL) == (O_RDWR | O_NONBLOCK));
    +	CHECK(fcntl(fd, F_SETFL, 0) == 0);
    +	CHECK(fcntl(fd, F_GETFL) == O_RDWR);
    +
    +	CHECK(close(fd) == 0);
    +
    +	CHECK(descriptor_recv(sock, &fd) == 0);
    +
    +	fcntlrights = 0;
    +	CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);
    +	CHECK(fcntlrights == CAP_FCNTL_GETFL);
    +	errno = 0;
    +	CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL | CAP_FCNTL_SETFL) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	fcntlrights = 0;
    +	CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);
    +	CHECK(fcntlrights == CAP_FCNTL_GETFL);
    +	CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL) == 0);
    +	fcntlrights = 0;
    +	CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);
    +	CHECK(fcntlrights == CAP_FCNTL_GETFL);
    +
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +	CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
    +	CHECK(fcntl(fd, F_SETFD, 0) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +
    +	CHECK(fcntl(fd, F_GETFL) == O_RDWR);
    +	errno = 0;
    +	CHECK(fcntl(fd, F_SETFL, O_NONBLOCK) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	CHECK(fcntl(fd, F_GETFL) == O_RDWR);
    +	errno = 0;
    +	CHECK(fcntl(fd, F_SETFL, 0) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	CHECK(fcntl(fd, F_GETFL) == O_RDWR);
    +
    +	CHECK(close(fd) == 0);
    +
    +	CHECK(descriptor_recv(sock, &fd) == 0);
    +
    +	fcntlrights = 0;
    +	CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);
    +	CHECK(fcntlrights == 0);
    +	errno = 0;
    +	CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL | CAP_FCNTL_SETFL) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	fcntlrights = 0;
    +	CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);
    +	CHECK(fcntlrights == 0);
    +	errno = 0;
    +	CHECK(cap_fcntls_limit(fd, CAP_FCNTL_GETFL) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	fcntlrights = 0;
    +	CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);
    +	CHECK(fcntlrights == 0);
    +	errno = 0;
    +	CHECK(cap_fcntls_limit(fd, CAP_FCNTL_SETFL) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	fcntlrights = 0;
    +	CHECK(cap_fcntls_get(fd, &fcntlrights) == 0);
    +	CHECK(fcntlrights == 0);
    +
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +	CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
    +	CHECK(fcntl(fd, F_SETFD, 0) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +
    +	errno = 0;
    +	CHECK(fcntl(fd, F_GETFL) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	errno = 0;
    +	CHECK(fcntl(fd, F_SETFL, O_NONBLOCK) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	errno = 0;
    +	CHECK(fcntl(fd, F_SETFL, 0) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	errno = 0;
    +	CHECK(fcntl(fd, F_GETFL) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +
    +	CHECK(close(fd) == 0);
    +}
    +
    +int
    +main(void)
    +{
    +	int fd, pfd, sp[2];
    +	pid_t pid;
    +
    +	printf("1..870\n");
    +
    +	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
    +	fcntl_tests_0(fd);
    +	CHECK(close(fd) == 0);
    +
    +	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
    +	fcntl_tests_1(fd);
    +	CHECK(close(fd) == 0);
    +
    +	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
    +	fcntl_tests_2(fd);
    +	CHECK(close(fd) == 0);
    +
    +	/* Child inherits descriptor and operates on it first. */
    +	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
    +	CHECK((pid = fork()) >= 0);
    +	if (pid == 0) {
    +		fcntl_tests_0(fd);
    +		CHECK(close(fd) == 0);
    +		exit(0);
    +	} else {
    +		CHECK(waitpid(pid, NULL, 0) == pid);
    +		fcntl_tests_0(fd);
    +	}
    +	CHECK(close(fd) == 0);
    +
    +	/* Child inherits descriptor, but operates on it after parent. */
    +	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
    +	CHECK((pid = fork()) >= 0);
    +	if (pid == 0) {
    +		sleep(1);
    +		fcntl_tests_0(fd);
    +		CHECK(close(fd) == 0);
    +		exit(0);
    +	} else {
    +		fcntl_tests_0(fd);
    +		CHECK(waitpid(pid, NULL, 0) == pid);
    +	}
    +	CHECK(close(fd) == 0);
    +
    +	/* Child inherits descriptor and operates on it first. */
    +	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
    +	CHECK((pid = pdfork(&pfd, 0)) >= 0);
    +	if (pid == 0) {
    +		fcntl_tests_1(fd);
    +		exit(0);
    +	} else {
    +		CHECK(pdwait(pfd) == 0);
    +/*
    +		It fails with EBADF, which I believe is a bug.
    +		CHECK(close(pfd) == 0);
    +*/
    +		fcntl_tests_1(fd);
    +	}
    +	CHECK(close(fd) == 0);
    +
    +	/* Child inherits descriptor, but operates on it after parent. */
    +	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
    +	CHECK((pid = pdfork(&pfd, 0)) >= 0);
    +	if (pid == 0) {
    +		sleep(1);
    +		fcntl_tests_1(fd);
    +		exit(0);
    +	} else {
    +		fcntl_tests_1(fd);
    +		CHECK(pdwait(pfd) == 0);
    +/*
    +		It fails with EBADF, which I believe is a bug.
    +		CHECK(close(pfd) == 0);
    +*/
    +	}
    +	CHECK(close(fd) == 0);
    +
    +	/* Child inherits descriptor and operates on it first. */
    +	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
    +	CHECK((pid = fork()) >= 0);
    +	if (pid == 0) {
    +		fcntl_tests_2(fd);
    +		exit(0);
    +	} else {
    +		CHECK(waitpid(pid, NULL, 0) == pid);
    +		fcntl_tests_2(fd);
    +	}
    +	CHECK(close(fd) == 0);
    +
    +	/* Child inherits descriptor, but operates on it after parent. */
    +	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
    +	CHECK((pid = fork()) >= 0);
    +	if (pid == 0) {
    +		sleep(1);
    +		fcntl_tests_2(fd);
    +		exit(0);
    +	} else {
    +		fcntl_tests_2(fd);
    +		CHECK(waitpid(pid, NULL, 0) == pid);
    +	}
    +	CHECK(close(fd) == 0);
    +
    +	/* Send descriptors from parent to child. */
    +	CHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, sp) == 0);
    +	CHECK((pid = fork()) >= 0);
    +	if (pid == 0) {
    +		CHECK(close(sp[0]) == 0);
    +		fcntl_tests_recv_0(sp[1]);
    +		CHECK(close(sp[1]) == 0);
    +		exit(0);
    +	} else {
    +		CHECK(close(sp[1]) == 0);
    +		fcntl_tests_send_0(sp[0]);
    +		CHECK(waitpid(pid, NULL, 0) == pid);
    +		CHECK(close(sp[0]) == 0);
    +	}
    +
    +	/* Send descriptors from child to parent. */
    +	CHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, sp) == 0);
    +	CHECK((pid = fork()) >= 0);
    +	if (pid == 0) {
    +		CHECK(close(sp[0]) == 0);
    +		fcntl_tests_send_0(sp[1]);
    +		CHECK(close(sp[1]) == 0);
    +		exit(0);
    +	} else {
    +		CHECK(close(sp[1]) == 0);
    +		fcntl_tests_recv_0(sp[0]);
    +		CHECK(waitpid(pid, NULL, 0) == pid);
    +		CHECK(close(sp[0]) == 0);
    +	}
    +
    +	exit(0);
    +}
    diff --git a/tools/regression/capsicum/syscalls/cap_getmode.c b/tools/regression/capsicum/syscalls/cap_getmode.c
    new file mode 100644
    index 00000000000..1a38202defc
    --- /dev/null
    +++ b/tools/regression/capsicum/syscalls/cap_getmode.c
    @@ -0,0 +1,167 @@
    +/*-
    + * Copyright (c) 2012 The FreeBSD Foundation
    + * All rights reserved.
    + *
    + * This software was developed by Pawel Jakub Dawidek under sponsorship from
    + * the FreeBSD Foundation.
    + *
    + * Redistribution and use in source and binary forms, with or without
    + * modification, are permitted provided that the following conditions
    + * are met:
    + * 1. Redistributions of source code must retain the above copyright
    + *    notice, this list of conditions and the following disclaimer.
    + * 2. Redistributions in binary form must reproduce the above copyright
    + *    notice, this list of conditions and the following disclaimer in the
    + *    documentation and/or other materials provided with the distribution.
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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 
    +__FBSDID("$FreeBSD$");
    +
    +#include 
    +#include 
    +#include 
    +#include 
    +
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +
    +#include "misc.h"
    +
    +int
    +main(void)
    +{
    +	unsigned int mode;
    +	pid_t pid;
    +	int pfd;
    +
    +	printf("1..27\n");
    +
    +	mode = 666;
    +	CHECK(cap_getmode(&mode) == 0);
    +	/* If cap_getmode() succeeded mode should be modified. */
    +	CHECK(mode != 666);
    +	/* We are not in capability mode. */
    +	CHECK(mode == 0);
    +
    +	/* Expect EFAULT. */
    +	errno = 0;
    +	CHECK(cap_getmode(NULL) == -1);
    +	CHECK(errno == EFAULT);
    +	errno = 0;
    +	CHECK(cap_getmode((void *)(uintptr_t)0xdeadc0de) == -1);
    +	CHECK(errno == EFAULT);
    +
    +	/* If parent is not in capability mode, child after fork() also won't be. */
    +	pid = fork();
    +	switch (pid) {
    +	case -1:
    +		err(1, "fork() failed");
    +	case 0:
    +		mode = 666;
    +		CHECK(cap_getmode(&mode) == 0);
    +		/* If cap_getmode() succeeded mode should be modified. */
    +		CHECK(mode != 666);
    +		/* We are not in capability mode. */
    +		CHECK(mode == 0);
    +		exit(0);
    +	default:
    +		if (waitpid(pid, NULL, 0) == -1)
    +			err(1, "waitpid() failed");
    +	}
    +
    +	/* If parent is not in capability mode, child after pdfork() also won't be. */
    +	pid = pdfork(&pfd, 0);
    +	switch (pid) {
    +	case -1:
    +		err(1, "pdfork() failed");
    +	case 0:
    +		mode = 666;
    +		CHECK(cap_getmode(&mode) == 0);
    +		/* If cap_getmode() succeeded mode should be modified. */
    +		CHECK(mode != 666);
    +		/* We are not in capability mode. */
    +		CHECK(mode == 0);
    +		exit(0);
    +	default:
    +		if (pdwait(pfd) == -1)
    +			err(1, "pdwait() failed");
    +		close(pfd);
    +	}
    +
    +	/* In capability mode... */
    +
    +	CHECK(cap_enter() == 0);
    +
    +	mode = 666;
    +	CHECK(cap_getmode(&mode) == 0);
    +	/* If cap_getmode() succeeded mode should be modified. */
    +	CHECK(mode != 666);
    +	/* We are in capability mode. */
    +	CHECK(mode == 1);
    +
    +	/* Expect EFAULT. */
    +	errno = 0;
    +	CHECK(cap_getmode(NULL) == -1);
    +	CHECK(errno == EFAULT);
    +	errno = 0;
    +	CHECK(cap_getmode((void *)(uintptr_t)0xdeadc0de) == -1);
    +	CHECK(errno == EFAULT);
    +
    +	/* If parent is in capability mode, child after fork() also will be. */
    +	pid = fork();
    +	switch (pid) {
    +	case -1:
    +		err(1, "fork() failed");
    +	case 0:
    +		mode = 666;
    +		CHECK(cap_getmode(&mode) == 0);
    +		/* If cap_getmode() succeeded mode should be modified. */
    +		CHECK(mode != 666);
    +		/* We are in capability mode. */
    +		CHECK(mode == 1);
    +		exit(0);
    +	default:
    +		/*
    +		 * wait(2) and friends are not permitted in the capability mode,
    +		 * so we can only just wait for a while.
    +		 */
    +		sleep(1);
    +	}
    +
    +	/* If parent is in capability mode, child after pdfork() also will be. */
    +	pid = pdfork(&pfd, 0);
    +	switch (pid) {
    +	case -1:
    +		err(1, "pdfork() failed");
    +	case 0:
    +		mode = 666;
    +		CHECK(cap_getmode(&mode) == 0);
    +		/* If cap_getmode() succeeded mode should be modified. */
    +		CHECK(mode != 666);
    +		/* We are in capability mode. */
    +		CHECK(mode == 1);
    +		exit(0);
    +	default:
    +		if (pdwait(pfd) == -1)
    +			err(1, "pdwait() failed");
    +		close(pfd);
    +	}
    +
    +	exit(0);
    +}
    diff --git a/tools/regression/capsicum/syscalls/cap_ioctls_limit.c b/tools/regression/capsicum/syscalls/cap_ioctls_limit.c
    new file mode 100644
    index 00000000000..3a08fac4ac7
    --- /dev/null
    +++ b/tools/regression/capsicum/syscalls/cap_ioctls_limit.c
    @@ -0,0 +1,462 @@
    +/*-
    + * Copyright (c) 2012 The FreeBSD Foundation
    + * All rights reserved.
    + *
    + * This software was developed by Pawel Jakub Dawidek under sponsorship from
    + * the FreeBSD Foundation.
    + *
    + * Redistribution and use in source and binary forms, with or without
    + * modification, are permitted provided that the following conditions
    + * are met:
    + * 1. Redistributions of source code must retain the above copyright
    + *    notice, this list of conditions and the following disclaimer.
    + * 2. Redistributions in binary form must reproduce the above copyright
    + *    notice, this list of conditions and the following disclaimer in the
    + *    documentation and/or other materials provided with the distribution.
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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 
    +__FBSDID("$FreeBSD$");
    +
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +
    +#include "misc.h"
    +
    +static void
    +ioctl_tests_0(int fd)
    +{
    +	unsigned long cmds[2];
    +
    +	CHECK(cap_ioctls_get(fd, NULL, 0) == INT_MAX);
    +
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +	CHECK(ioctl(fd, FIOCLEX) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
    +	CHECK(ioctl(fd, FIONCLEX) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +
    +	cmds[0] = FIOCLEX;
    +	cmds[1] = FIONCLEX;
    +	CHECK(cap_ioctls_limit(fd, cmds, nitems(cmds)) == 0);
    +	cmds[0] = cmds[1] = 0;
    +	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == nitems(cmds));
    +	CHECK((cmds[0] == FIOCLEX && cmds[1] == FIONCLEX) ||
    +	    (cmds[0] == FIONCLEX && cmds[1] == FIOCLEX));
    +	cmds[0] = FIOCLEX;
    +	cmds[1] = FIONCLEX;
    +	CHECK(cap_ioctls_limit(fd, cmds, nitems(cmds)) == 0);
    +	cmds[0] = cmds[1] = 0;
    +	CHECK(cap_ioctls_get(fd, cmds, 1) == nitems(cmds));
    +	CHECK(cmds[0] == FIOCLEX || cmds[0] == FIONCLEX);
    +	CHECK(cmds[1] == 0);
    +
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +	CHECK(ioctl(fd, FIOCLEX) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
    +	CHECK(ioctl(fd, FIONCLEX) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +
    +	cmds[0] = FIOCLEX;
    +	CHECK(cap_ioctls_limit(fd, cmds, 1) == 0);
    +	cmds[0] = cmds[1] = 0;
    +	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 1);
    +	CHECK(cmds[0] == FIOCLEX);
    +	cmds[0] = FIOCLEX;
    +	cmds[1] = FIONCLEX;
    +	errno = 0;
    +	CHECK(cap_ioctls_limit(fd, cmds, nitems(cmds)) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	cmds[0] = cmds[1] = 0;
    +	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 1);
    +	CHECK(cmds[0] == FIOCLEX);
    +
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +	CHECK(ioctl(fd, FIOCLEX) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
    +	errno = 0;
    +	CHECK(ioctl(fd, FIONCLEX) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
    +	CHECK(fcntl(fd, F_SETFD, 0) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +
    +	CHECK(cap_ioctls_limit(fd, NULL, 0) == 0);
    +	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
    +	cmds[0] = FIOCLEX;
    +	errno = 0;
    +	CHECK(cap_ioctls_limit(fd, cmds, 1) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
    +
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +	errno = 0;
    +	CHECK(ioctl(fd, FIOCLEX) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +	CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
    +	errno = 0;
    +	CHECK(ioctl(fd, FIONCLEX) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
    +	CHECK(fcntl(fd, F_SETFD, 0) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +}
    +
    +static void
    +ioctl_tests_1(int fd)
    +{
    +	unsigned long cmds[2];
    +
    +	cmds[0] = FIOCLEX;
    +	CHECK(cap_ioctls_limit(fd, cmds, 1) == 0);
    +	cmds[0] = cmds[1] = 0;
    +	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 1);
    +	CHECK(cmds[0] == FIOCLEX);
    +	CHECK(cmds[1] == 0);
    +
    +	CHECK(cap_rights_limit(fd, CAP_ALL & ~CAP_IOCTL) == 0);
    +	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
    +
    +	cmds[0] = FIOCLEX;
    +	cmds[1] = FIONCLEX;
    +	errno = 0;
    +	CHECK(cap_ioctls_limit(fd, cmds, nitems(cmds)) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
    +	cmds[0] = FIOCLEX;
    +	errno = 0;
    +	CHECK(cap_ioctls_limit(fd, cmds, 1) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
    +
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +	errno = 0;
    +	CHECK(ioctl(fd, FIOCLEX) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +	CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
    +	errno = 0;
    +	CHECK(ioctl(fd, FIONCLEX) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
    +	CHECK(fcntl(fd, F_SETFD, 0) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +}
    +
    +static void
    +ioctl_tests_2(int fd)
    +{
    +	unsigned long cmds[2];
    +
    +	CHECK(cap_rights_limit(fd, CAP_ALL & ~CAP_IOCTL) == 0);
    +	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
    +
    +	cmds[0] = FIOCLEX;
    +	cmds[1] = FIONCLEX;
    +	errno = 0;
    +	CHECK(cap_ioctls_limit(fd, cmds, nitems(cmds)) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
    +	cmds[0] = FIOCLEX;
    +	errno = 0;
    +	CHECK(cap_ioctls_limit(fd, cmds, 1) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
    +
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +	errno = 0;
    +	CHECK(ioctl(fd, FIOCLEX) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +	CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
    +	errno = 0;
    +	CHECK(ioctl(fd, FIONCLEX) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
    +	CHECK(fcntl(fd, F_SETFD, 0) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +}
    +
    +static void
    +ioctl_tests_send_0(int sock)
    +{
    +	unsigned long cmds[2];
    +	int fd;
    +
    +	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
    +	CHECK(descriptor_send(sock, fd) == 0);
    +	CHECK(close(fd) == 0);
    +
    +	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
    +	cmds[0] = FIOCLEX;
    +	cmds[1] = FIONCLEX;
    +	CHECK(cap_ioctls_limit(fd, cmds, nitems(cmds)) == 0);
    +	CHECK(descriptor_send(sock, fd) == 0);
    +	CHECK(close(fd) == 0);
    +
    +	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
    +	cmds[0] = FIOCLEX;
    +	CHECK(cap_ioctls_limit(fd, cmds, 1) == 0);
    +	CHECK(descriptor_send(sock, fd) == 0);
    +	CHECK(close(fd) == 0);
    +
    +	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
    +	CHECK(cap_ioctls_limit(fd, NULL, 0) == 0);
    +	CHECK(descriptor_send(sock, fd) == 0);
    +	CHECK(close(fd) == 0);
    +}
    +
    +static void
    +ioctl_tests_recv_0(int sock)
    +{
    +	unsigned long cmds[2];
    +	int fd;
    +
    +	CHECK(descriptor_recv(sock, &fd) == 0);
    +
    +	CHECK(cap_ioctls_get(fd, NULL, 0) == INT_MAX);
    +
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +	CHECK(ioctl(fd, FIOCLEX) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
    +	CHECK(ioctl(fd, FIONCLEX) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +
    +	CHECK(close(fd) == 0);
    +
    +	CHECK(descriptor_recv(sock, &fd) == 0);
    +
    +	cmds[0] = cmds[1] = 0;
    +	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == nitems(cmds));
    +	CHECK((cmds[0] == FIOCLEX && cmds[1] == FIONCLEX) ||
    +	    (cmds[0] == FIONCLEX && cmds[1] == FIOCLEX));
    +
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +	CHECK(ioctl(fd, FIOCLEX) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
    +	CHECK(ioctl(fd, FIONCLEX) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +
    +	CHECK(close(fd) == 0);
    +
    +	CHECK(descriptor_recv(sock, &fd) == 0);
    +
    +	cmds[0] = cmds[1] = 0;
    +	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 1);
    +	CHECK(cmds[0] == FIOCLEX);
    +
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +	CHECK(ioctl(fd, FIOCLEX) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
    +	errno = 0;
    +	CHECK(ioctl(fd, FIONCLEX) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
    +	CHECK(fcntl(fd, F_SETFD, 0) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +
    +	CHECK(close(fd) == 0);
    +
    +	CHECK(descriptor_recv(sock, &fd) == 0);
    +
    +	CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0);
    +
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +	errno = 0;
    +	CHECK(ioctl(fd, FIOCLEX) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +	CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
    +	errno = 0;
    +	CHECK(ioctl(fd, FIONCLEX) == -1);
    +	CHECK(errno == ENOTCAPABLE);
    +	CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC);
    +	CHECK(fcntl(fd, F_SETFD, 0) == 0);
    +	CHECK(fcntl(fd, F_GETFD) == 0);
    +
    +	CHECK(close(fd) == 0);
    +}
    +
    +int
    +main(void)
    +{
    +	int fd, pfd, sp[2];
    +	pid_t pid;
    +
    +	printf("1..607\n");
    +
    +	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
    +	ioctl_tests_0(fd);
    +	CHECK(close(fd) == 0);
    +
    +	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
    +	ioctl_tests_1(fd);
    +	CHECK(close(fd) == 0);
    +
    +	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
    +	ioctl_tests_2(fd);
    +	CHECK(close(fd) == 0);
    +
    +	/* Child inherits descriptor and operates on it first. */
    +	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
    +	pid = fork();
    +	switch (pid) {
    +	case -1:
    +		err(1, "fork() failed");
    +	case 0:
    +		ioctl_tests_0(fd);
    +		CHECK(close(fd) == 0);
    +		exit(0);
    +	default:
    +		if (waitpid(pid, NULL, 0) == -1)
    +			err(1, "waitpid() failed");
    +		ioctl_tests_0(fd);
    +	}
    +	CHECK(close(fd) == 0);
    +
    +	/* Child inherits descriptor, but operates on it after parent. */
    +	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
    +	pid = fork();
    +	switch (pid) {
    +	case -1:
    +		err(1, "fork() failed");
    +	case 0:
    +		sleep(1);
    +		ioctl_tests_0(fd);
    +		CHECK(close(fd) == 0);
    +		exit(0);
    +	default:
    +		ioctl_tests_0(fd);
    +		if (waitpid(pid, NULL, 0) == -1)
    +			err(1, "waitpid() failed");
    +	}
    +	CHECK(close(fd) == 0);
    +
    +	/* Child inherits descriptor and operates on it first. */
    +	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
    +	pid = pdfork(&pfd, 0);
    +	switch (pid) {
    +	case -1:
    +		err(1, "pdfork() failed");
    +	case 0:
    +		ioctl_tests_1(fd);
    +		exit(0);
    +	default:
    +		if (pdwait(pfd) == -1)
    +			err(1, "pdwait() failed");
    +		close(pfd);
    +		ioctl_tests_1(fd);
    +	}
    +	CHECK(close(fd) == 0);
    +
    +	/* Child inherits descriptor, but operates on it after parent. */
    +	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
    +	pid = pdfork(&pfd, 0);
    +	switch (pid) {
    +	case -1:
    +		err(1, "pdfork() failed");
    +	case 0:
    +		sleep(1);
    +		ioctl_tests_1(fd);
    +		exit(0);
    +	default:
    +		ioctl_tests_1(fd);
    +		if (pdwait(pfd) == -1)
    +			err(1, "pdwait() failed");
    +		close(pfd);
    +	}
    +	CHECK(close(fd) == 0);
    +
    +	/* Child inherits descriptor and operates on it first. */
    +	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
    +	pid = fork();
    +	switch (pid) {
    +	case -1:
    +		err(1, "fork() failed");
    +	case 0:
    +		ioctl_tests_2(fd);
    +		exit(0);
    +	default:
    +		if (waitpid(pid, NULL, 0) == -1)
    +			err(1, "waitpid() failed");
    +		ioctl_tests_2(fd);
    +	}
    +	CHECK(close(fd) == 0);
    +
    +	/* Child inherits descriptor, but operates on it after parent. */
    +	CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
    +	pid = fork();
    +	switch (pid) {
    +	case -1:
    +		err(1, "fork() failed");
    +	case 0:
    +		sleep(1);
    +		ioctl_tests_2(fd);
    +		exit(0);
    +	default:
    +		ioctl_tests_2(fd);
    +		if (waitpid(pid, NULL, 0) == -1)
    +			err(1, "waitpid() failed");
    +	}
    +	CHECK(close(fd) == 0);
    +
    +	/* Send descriptors from parent to child. */
    +	CHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, sp) == 0);
    +	CHECK((pid = fork()) >= 0);
    +	if (pid == 0) {
    +		CHECK(close(sp[0]) == 0);
    +		ioctl_tests_recv_0(sp[1]);
    +		CHECK(close(sp[1]) == 0);
    +		exit(0);
    +	} else {
    +		CHECK(close(sp[1]) == 0);
    +		ioctl_tests_send_0(sp[0]);
    +		CHECK(waitpid(pid, NULL, 0) == pid);
    +		CHECK(close(sp[0]) == 0);
    +	}
    +
    +	/* Send descriptors from child to parent. */
    +	CHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, sp) == 0);
    +	CHECK((pid = fork()) >= 0);
    +	if (pid == 0) {
    +		CHECK(close(sp[0]) == 0);
    +		ioctl_tests_send_0(sp[1]);
    +		CHECK(close(sp[1]) == 0);
    +		exit(0);
    +	} else {
    +		CHECK(close(sp[1]) == 0);
    +		ioctl_tests_recv_0(sp[0]);
    +		CHECK(waitpid(pid, NULL, 0) == pid);
    +		CHECK(close(sp[0]) == 0);
    +	}
    +
    +	exit(0);
    +}
    diff --git a/tools/regression/capsicum/syscalls/misc.c b/tools/regression/capsicum/syscalls/misc.c
    new file mode 100644
    index 00000000000..303a9117910
    --- /dev/null
    +++ b/tools/regression/capsicum/syscalls/misc.c
    @@ -0,0 +1,128 @@
    +/*-
    + * Copyright (c) 2012 The FreeBSD Foundation
    + * All rights reserved.
    + *
    + * This software was developed by Pawel Jakub Dawidek under sponsorship from
    + * the FreeBSD Foundation.
    + *
    + * Redistribution and use in source and binary forms, with or without
    + * modification, are permitted provided that the following conditions
    + * are met:
    + * 1. Redistributions of source code must retain the above copyright
    + *    notice, this list of conditions and the following disclaimer.
    + * 2. Redistributions in binary form must reproduce the above copyright
    + *    notice, this list of conditions and the following disclaimer in the
    + *    documentation and/or other materials provided with the distribution.
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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 
    +__FBSDID("$FreeBSD$");
    +
    +#include 
    +#include 
    +#include 
    +
    +#include 
    +#include 
    +#include 
    +#include 
    +
    +#include "misc.h"
    +
    +int
    +pdwait(int pfd)
    +{
    +	fd_set fdset;
    +
    +	FD_ZERO(&fdset);
    +	FD_SET(pfd, &fdset);
    +
    +	return (select(pfd + 1, NULL, &fdset, NULL, NULL) == -1 ? -1 : 0);
    +}
    +
    +int
    +descriptor_send(int sock, int fd)
    +{
    +	unsigned char ctrl[CMSG_SPACE(sizeof(fd))];
    +	struct msghdr msg;
    +	struct cmsghdr *cmsg;
    +
    +	assert(sock >= 0);
    +	assert(fd >= 0);
    +
    +	bzero(&msg, sizeof(msg));
    +	bzero(&ctrl, sizeof(ctrl));
    +
    +	msg.msg_iov = NULL;
    +	msg.msg_iovlen = 0;
    +	msg.msg_control = ctrl;
    +	msg.msg_controllen = sizeof(ctrl);
    +
    +	cmsg = CMSG_FIRSTHDR(&msg);
    +	cmsg->cmsg_level = SOL_SOCKET;
    +	cmsg->cmsg_type = SCM_RIGHTS;
    +	cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
    +	bcopy(&fd, CMSG_DATA(cmsg), sizeof(fd));
    +
    +	if (sendmsg(sock, &msg, 0) == -1)
    +		return (errno);
    +
    +	return (0);
    +}
    +
    +int
    +descriptor_recv(int sock, int *fdp)
    +{
    +	unsigned char ctrl[CMSG_SPACE(sizeof(*fdp))];
    +	struct msghdr msg;
    +	struct cmsghdr *cmsg;
    +	struct iovec iov;
    +	int val;
    +
    +	assert(sock >= 0);
    +	assert(fdp != NULL);
    +
    +	bzero(&msg, sizeof(msg));
    +	bzero(&ctrl, sizeof(ctrl));
    +
    +#if 1
    +	/*
    +	 * This doesn't really make sense, as we don't plan to receive any
    +	 * data, but if no buffer is provided and recv(2) returns 0 without
    +	 * control message. Must be kernel bug.
    +	 */
    +	iov.iov_base = &val;
    +	iov.iov_len = sizeof(val);
    +	msg.msg_iov = &iov;
    +	msg.msg_iovlen = 1;
    +#else
    +	msg.msg_iov = NULL;
    +	msg.msg_iovlen = 0;
    +#endif
    +	msg.msg_control = ctrl;
    +	msg.msg_controllen = sizeof(ctrl);
    +
    +	if (recvmsg(sock, &msg, 0) == -1)
    +		return (errno);
    +
    +	cmsg = CMSG_FIRSTHDR(&msg);
    +	if (cmsg == NULL || cmsg->cmsg_level != SOL_SOCKET ||
    +	    cmsg->cmsg_type != SCM_RIGHTS) {
    +		return (EINVAL);
    +	}
    +	bcopy(CMSG_DATA(cmsg), fdp, sizeof(*fdp));
    +
    +	return (0);
    +}
    diff --git a/tools/regression/capsicum/syscalls/misc.h b/tools/regression/capsicum/syscalls/misc.h
    new file mode 100644
    index 00000000000..4968c3e059b
    --- /dev/null
    +++ b/tools/regression/capsicum/syscalls/misc.h
    @@ -0,0 +1,62 @@
    +/*-
    + * Copyright (c) 2012 The FreeBSD Foundation
    + * All rights reserved.
    + *
    + * This software was developed by Pawel Jakub Dawidek under sponsorship from
    + * the FreeBSD Foundation.
    + *
    + * Redistribution and use in source and binary forms, with or without
    + * modification, are permitted provided that the following conditions
    + * are met:
    + * 1. Redistributions of source code must retain the above copyright
    + *    notice, this list of conditions and the following disclaimer.
    + * 2. Redistributions in binary form must reproduce the above copyright
    + *    notice, this list of conditions and the following disclaimer in the
    + *    documentation and/or other materials provided with the distribution.
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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 _MISC_H_
    +#define	_MISC_H_
    +
    +#define	OK()	do {							\
    +	int _serrno = errno;						\
    +	printf("ok # line %u\n", __LINE__);				\
    +	fflush(stdout);							\
    +	errno = _serrno;						\
    +} while (0)
    +#define	NOK()	do {							\
    +	int _serrno = errno;						\
    +	printf("not ok # line %u\n", __LINE__);				\
    +	fflush(stdout);							\
    +	errno = _serrno;						\
    +} while (0)
    +#define	CHECK(cond)	do {						\
    +	if ((cond))							\
    +		OK();							\
    +	else								\
    +		NOK();							\
    +} while (0)
    +
    +/*
    + * This can be removed once pdwait4(2) is implemented.
    + */
    +int pdwait(int pfd);
    +
    +int descriptor_send(int sock, int fd);
    +int descriptor_recv(int sock, int *fdp);
    +
    +#endif	/* !_MISC_H_ */
    
    From 61fc9468e09b1f03093d461046a4015fe29dfdfa Mon Sep 17 00:00:00 2001
    From: Andrew Turner 
    Date: Sat, 2 Mar 2013 02:19:04 +0000
    Subject: [PATCH 0521/1476] Ensure the stack is correctly aligned before
     calling the first C function.
    
    ---
     sys/arm/arm/locore.S | 1 +
     1 file changed, 1 insertion(+)
    
    diff --git a/sys/arm/arm/locore.S b/sys/arm/arm/locore.S
    index 00a61e70e7f..37e88fe03ef 100644
    --- a/sys/arm/arm/locore.S
    +++ b/sys/arm/arm/locore.S
    @@ -204,6 +204,7 @@ mmu_done:
     virt_done:
     	mov	r1, #20			/* loader info size is 20 bytes also second arg */
     	subs	sp, sp, r1		/* allocate arm_boot_params struct on stack */
    +	bic	sp, sp, #7		/* align stack to 8 bytes */
     	mov	r0, sp			/* loader info pointer is first arg */
     	str	r1, [r0]		/* Store length of loader info */
     	str	r9, [r0, #4]		/* Store r0 from boot loader */
    
    From 6f02c16b639099c4d9571c6d914d60b1fb15f160 Mon Sep 17 00:00:00 2001
    From: Andrew Turner 
    Date: Sat, 2 Mar 2013 03:23:14 +0000
    Subject: [PATCH 0522/1476] Build the Raspberry Pi dtb file when building the
     kernel so we can copy it to the boot partition for U-Boot.
    
    ---
     sys/arm/conf/RPI-B | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/sys/arm/conf/RPI-B b/sys/arm/conf/RPI-B
    index d9e8d38f086..4d840cb01d5 100644
    --- a/sys/arm/conf/RPI-B
    +++ b/sys/arm/conf/RPI-B
    @@ -117,4 +117,4 @@ options         FDT
     # Note:  DTB is normally loaded and modified by RPi boot loader, then
     # handed to kernel via U-Boot and ubldr.
     #options         FDT_DTB_STATIC
    -#makeoptions     FDT_DTS_FILE=bcm2835-rpi-b.dts
    +makeoptions     FDT_DTS_FILE=bcm2835-rpi-b.dts
    
    From e40f53aa44eb364936dec7c633c1a3ac044add9c Mon Sep 17 00:00:00 2001
    From: Andrew Turner 
    Date: Sat, 2 Mar 2013 05:02:29 +0000
    Subject: [PATCH 0523/1476] Move some virtual memory constants to the top of
     the file where they are on other architectures [1].
    
    While here:
     - Remove an unused and commented out include.
     - Add a comment describing the file that other copies have.
     - Fix the style of the defines and add a comment on what each one is.
    
    Suggested by:	[1] alc
    ---
     sys/arm/include/vmparam.h | 46 +++++++++++++++++++++------------------
     1 file changed, 25 insertions(+), 21 deletions(-)
    
    diff --git a/sys/arm/include/vmparam.h b/sys/arm/include/vmparam.h
    index aec94f82325..9765b34abbd 100644
    --- a/sys/arm/include/vmparam.h
    +++ b/sys/arm/include/vmparam.h
    @@ -34,9 +34,32 @@
     #ifndef	_MACHINE_VMPARAM_H_
     #define	_MACHINE_VMPARAM_H_
     
    +/*
    + * Machine dependent constants for ARM.
    + */
    +
    +/*
    + * Virtual memory related constants, all in bytes
    + */
    +#ifndef	MAXTSIZ
    +#define	MAXTSIZ		(64UL*1024*1024)	/* max text size */
    +#endif
    +#ifndef	DFLDSIZ
    +#define	DFLDSIZ		(128UL*1024*1024)	/* initial data size limit */
    +#endif
    +#ifndef	MAXDSIZ
    +#define	MAXDSIZ		(512UL*1024*1024)	/* max data size */
    +#endif
    +#ifndef	DFLSSIZ
    +#define	DFLSSIZ		(2UL*1024*1024)		/* initial stack size limit */
    +#endif
    +#ifndef	MAXSSIZ
    +#define	MAXSSIZ		(8UL*1024*1024)		/* max stack size */
    +#endif
    +#ifndef	SGROWSIZ
    +#define	SGROWSIZ	(128UL*1024)		/* amount to grow stack */
    +#endif
     
    -/*#include 
    -*/
     /*
      * Address space constants
      */
    @@ -153,25 +176,6 @@
         VM_MIN_KERNEL_ADDRESS + 1) * 2 / 5)
     #endif
     
    -#ifndef MAXTSIZ
    -#define MAXTSIZ 	(64*1024*1024)
    -#endif
    -#ifndef DFLDSIZ
    -#define DFLDSIZ         (128*1024*1024)
    -#endif
    -#ifndef MAXDSIZ
    -#define MAXDSIZ         (512*1024*1024)
    -#endif
    -#ifndef DFLSSIZ
    -#define DFLSSIZ         (2*1024*1024)
    -#endif
    -#ifndef MAXSSIZ
    -#define MAXSSIZ         (8*1024*1024)
    -#endif
    -#ifndef SGROWSIZ
    -#define SGROWSIZ        (128*1024)
    -#endif
    -
     #ifdef ARM_USE_SMALL_ALLOC
     #define UMA_MD_SMALL_ALLOC
     #endif /* ARM_USE_SMALL_ALLOC */
    
    From 9b6799ad6b516c2a0251d3c8580629eec2c0d734 Mon Sep 17 00:00:00 2001
    From: Marcel Moolenaar 
    Date: Sat, 2 Mar 2013 05:03:36 +0000
    Subject: [PATCH 0524/1476] Fix nandfs support by providing the same crc32
     function as is used in newfs_nandfs. In libstand we get crc32 from libz. The
     polynomial is not the same as used for nandfs, which is the crc32 used in the
     kernel.
    
    ---
     lib/libstand/nandfs.c | 25 +++++++++++++++++++++++--
     1 file changed, 23 insertions(+), 2 deletions(-)
    
    diff --git a/lib/libstand/nandfs.c b/lib/libstand/nandfs.c
    index d5fcb9dde4f..2ddf8c34330 100644
    --- a/lib/libstand/nandfs.c
    +++ b/lib/libstand/nandfs.c
    @@ -125,6 +125,27 @@ struct fs_ops nandfs_fsops = {
     
     #define	NINDIR(fs)	((fs)->nf_blocksize / sizeof(nandfs_daddr_t))
     
    +/* from NetBSD's src/sys/net/if_ethersubr.c */
    +static uint32_t
    +nandfs_crc32(uint32_t crc, const uint8_t *buf, size_t len)
    +{
    +	static const uint32_t crctab[] = {
    +		0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
    +		0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
    +		0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
    +		0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
    +	};
    +	size_t i;
    +
    +	crc = crc ^ ~0U;
    +	for (i = 0; i < len; i++) {
    +		crc ^= buf[i];
    +		crc = (crc >> 4) ^ crctab[crc & 0xf];
    +		crc = (crc >> 4) ^ crctab[crc & 0xf];
    +	}
    +	return (crc ^ ~0U);
    +}
    +
     static int
     nandfs_check_fsdata_crc(struct nandfs_fsdata *fsdata)
     {
    @@ -138,7 +159,7 @@ nandfs_check_fsdata_crc(struct nandfs_fsdata *fsdata)
     
     	/* Calculate */
     	fsdata->f_sum = (0);
    -	comp_crc = crc32(0, (uint8_t *)fsdata, fsdata->f_bytes);
    +	comp_crc = nandfs_crc32(0, (uint8_t *)fsdata, fsdata->f_bytes);
     
     	/* Restore */
     	fsdata->f_sum = fsdata_crc;
    @@ -162,7 +183,7 @@ nandfs_check_superblock_crc(struct nandfs_fsdata *fsdata,
     
     	/* Calculate */
     	super->s_sum = (0);
    -	comp_crc = crc32(0, (uint8_t *)super, fsdata->f_sbbytes);
    +	comp_crc = nandfs_crc32(0, (uint8_t *)super, fsdata->f_sbbytes);
     
     	/* Restore */
     	super->s_sum = super_crc;
    
    From ecc7e36ccb84d93303c545628a4d91afdd5e3991 Mon Sep 17 00:00:00 2001
    From: Marcel Moolenaar 
    Date: Sat, 2 Mar 2013 05:07:51 +0000
    Subject: [PATCH 0525/1476] Fix warnings (control reaches end of non-void
     function).
    
    ---
     lib/libstand/nandfs.c | 3 ++-
     1 file changed, 2 insertions(+), 1 deletion(-)
    
    diff --git a/lib/libstand/nandfs.c b/lib/libstand/nandfs.c
    index 2ddf8c34330..63d92d2ac61 100644
    --- a/lib/libstand/nandfs.c
    +++ b/lib/libstand/nandfs.c
    @@ -418,7 +418,7 @@ nandfs_open(const char *path, struct open_file *f)
     	return (0);
     }
     
    -static int
    +static void
     nandfs_free_node(struct nandfs_node *node)
     {
     	struct bmap_buf *bmap, *tmp;
    @@ -445,6 +445,7 @@ nandfs_close(struct open_file *f)
     	nandfs_free_node(fs->nf_opened_node);
     	free(fs->nf_sb);
     	free(fs);
    +	return (0);
     }
     
     static int
    
    From e4d4e0756ac0f04bbed21ba1e66b8283a45bc10b Mon Sep 17 00:00:00 2001
    From: Marcel Moolenaar 
    Date: Sat, 2 Mar 2013 05:28:55 +0000
    Subject: [PATCH 0526/1476] Make this WARNS=9 clean on i386 w/ clang.
    
    ---
     lib/libstand/nandfs.c | 29 ++++++++++++++---------------
     1 file changed, 14 insertions(+), 15 deletions(-)
    
    diff --git a/lib/libstand/nandfs.c b/lib/libstand/nandfs.c
    index 63d92d2ac61..713dc125de7 100644
    --- a/lib/libstand/nandfs.c
    +++ b/lib/libstand/nandfs.c
    @@ -95,8 +95,7 @@ static off_t nandfs_seek(struct open_file *, off_t, int);
     static int nandfs_stat(struct open_file *, struct stat *);
     static int nandfs_readdir(struct open_file *, struct dirent *);
     
    -static int nandfs_buf_read(struct nandfs *, char **, size_t *);
    -static struct nandfs_node *nandfs_lookup_inode(struct nandfs *, nandfs_daddr_t);
    +static int nandfs_buf_read(struct nandfs *, void **, size_t *);
     static struct nandfs_node *nandfs_lookup_path(struct nandfs *, const char *);
     static int nandfs_read_inode(struct nandfs *, struct nandfs_node *,
         nandfs_lbn_t, u_int, void *, int);
    @@ -453,7 +452,7 @@ nandfs_read(struct open_file *f, void *addr, size_t size, size_t *resid)
     {
     	struct nandfs *fs = (struct nandfs *)f->f_fsdata;
     	size_t csize, buf_size;
    -	uint8_t *buf;
    +	void *buf;
     	int error = 0;
     
     	NANDFS_DEBUG("nandfs_read(file=%p, addr=%p, size=%d)\n", f, addr, size);
    @@ -462,7 +461,7 @@ nandfs_read(struct open_file *f, void *addr, size_t size, size_t *resid)
     		if (fs->nf_offset >= fs->nf_opened_node->inode->i_size)
     			break;
     
    -		error = nandfs_buf_read(fs, (void *)&buf, &buf_size);
    +		error = nandfs_buf_read(fs, &buf, &buf_size);
     		if (error)
     			break;
     
    @@ -539,7 +538,7 @@ nandfs_readdir(struct open_file *f, struct dirent *d)
     {
     	struct nandfs *fs = f->f_fsdata;
     	struct nandfs_dir_entry *dirent;
    -	uint8_t *buf;
    +	void *buf;
     	size_t buf_size;
     
     	NANDFS_DEBUG("nandfs_readdir(file=%p, dirent=%p)\n", f, d);
    @@ -550,7 +549,7 @@ nandfs_readdir(struct open_file *f, struct dirent *d)
     		return (ENOENT);
     	}
     
    -	if (nandfs_buf_read(fs, (void *)&buf, &buf_size)) {
    +	if (nandfs_buf_read(fs, &buf, &buf_size)) {
     		NANDFS_DEBUG("nandfs_readdir(file=%p, dirent=%p)"
     		    "buf_read failed\n", f, d);
     		return (EIO);
    @@ -568,7 +567,7 @@ nandfs_readdir(struct open_file *f, struct dirent *d)
     }
     
     static int
    -nandfs_buf_read(struct nandfs *fs, char **buf_p, size_t *size_p)
    +nandfs_buf_read(struct nandfs *fs, void **buf_p, size_t *size_p)
     {
     	nandfs_daddr_t blknr, blkoff;
     
    @@ -634,8 +633,8 @@ nandfs_lookup_path(struct nandfs *fs, const char *path)
     	struct nandfs_node *node;
     	struct nandfs_dir_entry *dirent;
     	char *namebuf;
    -	uint64_t i, j, done, counter, pinode, inode;
    -	int nlinks = 0, len, link_len, nameidx;
    +	uint64_t i, done, pinode, inode;
    +	int nlinks = 0, counter, len, link_len, nameidx;
     	uint8_t *buffer, *orig;
     	char *strp, *lpath;
     
    @@ -672,7 +671,8 @@ nandfs_lookup_path(struct nandfs *fs, const char *path)
     			buffer = orig;
     			done = counter = 0;
     			while (1) {
    -				dirent = (struct nandfs_dir_entry *)buffer;
    +				dirent = 
    +				    (struct nandfs_dir_entry *)(void *)buffer;
     				NANDFS_DEBUG("%s: dirent.name = %s\n",
     				    __func__, dirent->name);
     				NANDFS_DEBUG("%s: dirent.rec_len = %d\n",
    @@ -768,9 +768,9 @@ static int
     nandfs_read_inode(struct nandfs *fs, struct nandfs_node *node,
         nandfs_daddr_t blknr, u_int nblks, void *buf, int raw)
     {
    -	int i;
     	uint64_t *pblks;
     	uint64_t *vblks;
    +	u_int i;
     	int error;
     
     	pblks = malloc(nblks * sizeof(uint64_t));
    @@ -799,7 +799,7 @@ nandfs_read_inode(struct nandfs *fs, struct nandfs_node *node,
     			return (EIO);
     		}
     
    -		buf += fs->nf_blocksize;
    +		buf = (void *)((uintptr_t)buf + fs->nf_blocksize);
     	}
     
     	free(pblks);
    @@ -881,8 +881,7 @@ nandfs_bmap_lookup(struct nandfs *fs, struct nandfs_node *node,
     {
     	struct nandfs_inode *ino;
     	nandfs_daddr_t ind_block_num;
    -	uint64_t *map, *indir;
    -	uint64_t idx0, idx1, vblk, tmp;
    +	uint64_t *map;
     	int idx;
     	int level;
     
    @@ -1028,7 +1027,7 @@ ioread(struct open_file *f, off_t pos, void *buf, u_int length)
     	err = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, pos,
     	    nsec * bsize, buffer, NULL);
     
    -	memcpy(buf, buffer + off, length);
    +	memcpy(buf, (void *)((uintptr_t)buffer + off), length);
     	free(buffer);
     
     	return (err);
    
    From fdf25068b7a65ea973c6cee4baecf2e4f28e9b48 Mon Sep 17 00:00:00 2001
    From: Joel Dahl 
    Date: Sat, 2 Mar 2013 06:55:55 +0000
    Subject: [PATCH 0527/1476] mdoc: remove superfluous paragraph macro.
    
    ---
     lib/libc/sys/cap_fcntls_limit.2 | 1 -
     lib/libc/sys/cap_ioctls_limit.2 | 1 -
     lib/libc/sys/cap_rights_limit.2 | 1 -
     3 files changed, 3 deletions(-)
    
    diff --git a/lib/libc/sys/cap_fcntls_limit.2 b/lib/libc/sys/cap_fcntls_limit.2
    index 8fa74634762..b1fca2c6748 100644
    --- a/lib/libc/sys/cap_fcntls_limit.2
    +++ b/lib/libc/sys/cap_fcntls_limit.2
    @@ -120,7 +120,6 @@ argument points at an invalid address.
     Support for capabilities and capabilities mode was developed as part of the
     .Tn TrustedBSD
     Project.
    -.Pp
     .Sh AUTHORS
     This function was created by
     .An Pawel Jakub Dawidek Aq pawel@dawidek.net
    diff --git a/lib/libc/sys/cap_ioctls_limit.2 b/lib/libc/sys/cap_ioctls_limit.2
    index 5eca18c1799..2c21211956c 100644
    --- a/lib/libc/sys/cap_ioctls_limit.2
    +++ b/lib/libc/sys/cap_ioctls_limit.2
    @@ -151,7 +151,6 @@ argument points at invalid address.
     Support for capabilities and capabilities mode was developed as part of the
     .Tn TrustedBSD
     Project.
    -.Pp
     .Sh AUTHORS
     This function was created by
     .An Pawel Jakub Dawidek Aq pawel@dawidek.net
    diff --git a/lib/libc/sys/cap_rights_limit.2 b/lib/libc/sys/cap_rights_limit.2
    index d8d87775558..0c527aad775 100644
    --- a/lib/libc/sys/cap_rights_limit.2
    +++ b/lib/libc/sys/cap_rights_limit.2
    @@ -590,7 +590,6 @@ argument points at an invalid address.
     Support for capabilities and capabilities mode was developed as part of the
     .Tn TrustedBSD
     Project.
    -.Pp
     .Sh AUTHORS
     This function was created by
     .An Pawel Jakub Dawidek Aq pawel@dawidek.net
    
    From fe138cc2af4a6aba36b910780433f5591fe9a61d Mon Sep 17 00:00:00 2001
    From: Adrian Chadd 
    Date: Sat, 2 Mar 2013 08:12:41 +0000
    Subject: [PATCH 0528/1476] Disable the ctl driver in GENERIC.
    
    It unfortunately steals a fair chunk of RAM at startup even if it's not
    actively used, which prevents FreeBSD VMs of 128MB from successfully
    booting and running.
    ---
     UPDATING               | 7 +++++++
     sys/amd64/conf/GENERIC | 2 +-
     sys/i386/conf/GENERIC  | 2 +-
     3 files changed, 9 insertions(+), 2 deletions(-)
    
    diff --git a/UPDATING b/UPDATING
    index 74da04d05b6..50e6452f1cb 100644
    --- a/UPDATING
    +++ b/UPDATING
    @@ -26,6 +26,13 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 10.x IS SLOW:
     	disable the most expensive debugging functionality run
     	"ln -s 'abort:false,junk:false' /etc/malloc.conf".)
     
    +20130301:
    +	The ctl device has been disabled in GENERIC for i386 and amd64.
    +	This was done due to the extra memory being allocated at system
    +	initialisation time by the ctl driver which was only used if
    +	a CAM target device was created.  This makes a FreeBSD system
    +	unusable on 128MB or less of RAM.
    +
     20130208:
     	A new compression method (lz4) has been merged to -HEAD.  Please
     	refer to zpool-features(7) for more information.
    diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC
    index 5819a0d576e..3988195f969 100644
    --- a/sys/amd64/conf/GENERIC
    +++ b/sys/amd64/conf/GENERIC
    @@ -138,7 +138,7 @@ device		sa		# Sequential Access (tape etc)
     device		cd		# CD
     device		pass		# Passthrough device (direct ATA/SCSI access)
     device		ses		# Enclosure Services (SES and SAF-TE)
    -device		ctl		# CAM Target Layer
    +#device		ctl		# CAM Target Layer
     
     # RAID controllers interfaced to the SCSI subsystem
     device		amr		# AMI MegaRAID
    diff --git a/sys/i386/conf/GENERIC b/sys/i386/conf/GENERIC
    index 47af43b423d..3a98ded3105 100644
    --- a/sys/i386/conf/GENERIC
    +++ b/sys/i386/conf/GENERIC
    @@ -146,7 +146,7 @@ device		sa		# Sequential Access (tape etc)
     device		cd		# CD
     device		pass		# Passthrough device (direct ATA/SCSI access)
     device		ses		# Enclosure Services (SES and SAF-TE)
    -device		ctl		# CAM Target Layer
    +#device		ctl		# CAM Target Layer
     
     # RAID controllers interfaced to the SCSI subsystem
     device		amr		# AMI MegaRAID
    
    From 6d4e99aaef0e0239e8340db2d7176da8ba547f81 Mon Sep 17 00:00:00 2001
    From: Pawel Jakub Dawidek 
    Date: Sat, 2 Mar 2013 09:58:47 +0000
    Subject: [PATCH 0529/1476] If the target file already exists, check for the
     CAP_UNLINKAT capabiity right on the target directory descriptor, but only if
     this is renameat(2) and real target directory descriptor is given (not
     AT_FDCWD). Without this fix regular rename(2) fails if the target file
     already exists.
    
    Reported by:	Michael Butler 
    Reported by:	Larry Rosenman 
    Sponsored by:	The FreeBSD Foundation
    ---
     sys/kern/vfs_syscalls.c | 17 ++++++++++-------
     1 file changed, 10 insertions(+), 7 deletions(-)
    
    diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
    index 787399abcb4..4c1d97c7d6e 100644
    --- a/sys/kern/vfs_syscalls.c
    +++ b/sys/kern/vfs_syscalls.c
    @@ -3556,13 +3556,16 @@ kern_renameat(struct thread *td, int oldfd, char *old, int newfd, char *new,
     			goto out;
     		}
     #ifdef CAPABILITIES
    -		/*
    -		 * If the target already exists we require CAP_UNLINKAT
    -		 * from 'newfd'.
    -		 */
    -		error = cap_check(tond.ni_filecaps.fc_rights, CAP_UNLINKAT);
    -		if (error != 0)
    -			goto out;
    +		if (newfd != AT_FDCWD) {
    +			/*
    +			 * If the target already exists we require CAP_UNLINKAT
    +			 * from 'newfd'.
    +			 */
    +			error = cap_check(tond.ni_filecaps.fc_rights,
    +			    CAP_UNLINKAT);
    +			if (error != 0)
    +				goto out;
    +		}
     #endif
     	}
     	if (fvp == tdvp) {
    
    From 6d6a91c50f1b41d67b94760a06758e867fda35fa Mon Sep 17 00:00:00 2001
    From: Jilles Tjoelker 
    Date: Sat, 2 Mar 2013 12:42:23 +0000
    Subject: [PATCH 0530/1476] nullfs: Improve f_flags in statfs().
    
    Include some flags of the nullfs mount itself:
    MNT_RDONLY, MNT_NOEXEC, MNT_NOSUID, MNT_UNION, MNT_NOSYMFOLLOW.
    
    This allows userland code calling statfs() or fstatfs() to see these flags.
    In particular, this allows opendir() to detect that a -t nullfs -o union
    mount needs deduplication (otherwise at least . and .. are returned twice)
    and allows rtld to detect a -t nullfs -o noexec mount as noexec.
    
    Turn off the MNT_ROOTFS flag from the underlying filesystem because the
    nullfs mount is definitely not the root filesystem.
    
    Reviewed by:	kib
    MFC after:	1 week
    ---
     sys/fs/nullfs/null_vfsops.c | 3 ++-
     1 file changed, 2 insertions(+), 1 deletion(-)
    
    diff --git a/sys/fs/nullfs/null_vfsops.c b/sys/fs/nullfs/null_vfsops.c
    index 3724e0a3bb6..02932bd932b 100644
    --- a/sys/fs/nullfs/null_vfsops.c
    +++ b/sys/fs/nullfs/null_vfsops.c
    @@ -313,7 +313,8 @@ nullfs_statfs(mp, sbp)
     
     	/* now copy across the "interesting" information and fake the rest */
     	sbp->f_type = mstat.f_type;
    -	sbp->f_flags = mstat.f_flags;
    +	sbp->f_flags = (sbp->f_flags & (MNT_RDONLY | MNT_NOEXEC | MNT_NOSUID |
    +	    MNT_UNION | MNT_NOSYMFOLLOW)) | (mstat.f_flags & ~MNT_ROOTFS);
     	sbp->f_bsize = mstat.f_bsize;
     	sbp->f_iosize = mstat.f_iosize;
     	sbp->f_blocks = mstat.f_blocks;
    
    From 562799bb30f81d39d037bf931c08c4577522723d Mon Sep 17 00:00:00 2001
    From: Marius Strobl 
    Date: Sat, 2 Mar 2013 13:04:58 +0000
    Subject: [PATCH 0531/1476] Revert the part of r247600 which turned the
     overtemperature and power fail interrupt shutdown handlers into filters.
     Shutdown_nice(9) acquires a sleep lock, which filters shouldn't do. It also
     seems that kern_reboot(9) still may require Giant to be hold.
    
    Submitted by:	bde
    ---
     sys/sparc64/pci/psycho.c | 34 ++++++++++++++++------------------
     1 file changed, 16 insertions(+), 18 deletions(-)
    
    diff --git a/sys/sparc64/pci/psycho.c b/sys/sparc64/pci/psycho.c
    index 8f4f23e5fb7..a6e1469210c 100644
    --- a/sys/sparc64/pci/psycho.c
    +++ b/sys/sparc64/pci/psycho.c
    @@ -81,7 +81,7 @@ static const struct psycho_desc *psycho_find_desc(const struct psycho_desc *,
         const char *);
     static const struct psycho_desc *psycho_get_desc(device_t);
     static void psycho_set_intr(struct psycho_softc *, u_int, bus_addr_t,
    -    driver_filter_t);
    +    driver_filter_t, driver_intr_t);
     static int psycho_find_intrmap(struct psycho_softc *, u_int, bus_addr_t *,
         bus_addr_t *, u_long *);
     static void sabre_dmamap_sync(bus_dma_tag_t dt, bus_dmamap_t map,
    @@ -96,8 +96,8 @@ static driver_filter_t psycho_ue;
     static driver_filter_t psycho_ce;
     static driver_filter_t psycho_pci_bus;
     static driver_filter_t psycho_powerdebug;
    -static driver_filter_t psycho_powerdown;
    -static driver_filter_t psycho_overtemp;
    +static driver_intr_t psycho_powerdown;
    +static driver_intr_t psycho_overtemp;
     #ifdef PSYCHO_MAP_WAKEUP
     static driver_filter_t psycho_wakeup;
     #endif
    @@ -619,17 +619,17 @@ psycho_attach(device_t dev)
     		 * XXX Not all controllers have these, but installing them
     		 * is better than trying to sort through this mess.
     		 */
    -		psycho_set_intr(sc, 1, PSR_UE_INT_MAP, psycho_ue);
    -		psycho_set_intr(sc, 2, PSR_CE_INT_MAP, psycho_ce);
    +		psycho_set_intr(sc, 1, PSR_UE_INT_MAP, psycho_ue, NULL);
    +		psycho_set_intr(sc, 2, PSR_CE_INT_MAP, psycho_ce, NULL);
     		switch (psycho_powerfail) {
     		case 0:
     			break;
     		case 2:
     			psycho_set_intr(sc, 3, PSR_POWER_INT_MAP,
    -			    psycho_powerdebug);
    +			    psycho_powerdebug, NULL);
     			break;
     		default:
    -			psycho_set_intr(sc, 3, PSR_POWER_INT_MAP,
    +			psycho_set_intr(sc, 3, PSR_POWER_INT_MAP, NULL,
     			    psycho_powerdown);
     			break;
     		}
    @@ -643,7 +643,7 @@ psycho_attach(device_t dev)
     			 * The spare hardware interrupt is used for the
     			 * over-temperature interrupt.
     			 */
    -			psycho_set_intr(sc, 4, PSR_SPARE_INT_MAP,
    +			psycho_set_intr(sc, 4, PSR_SPARE_INT_MAP, NULL,
     			    psycho_overtemp);
     #ifdef PSYCHO_MAP_WAKEUP
     			/*
    @@ -651,7 +651,7 @@ psycho_attach(device_t dev)
     			 * now.
     			 */
     			psycho_set_intr(sc, 5, PSR_PWRMGT_INT_MAP,
    -			    psycho_wakeup);
    +			    psycho_wakeup, NULL);
     #endif /* PSYCHO_MAP_WAKEUP */
     		}
     	}
    @@ -661,7 +661,7 @@ psycho_attach(device_t dev)
     	 * interrupt but they are also only used for PCI bus A.
     	 */
     	psycho_set_intr(sc, 0, sc->sc_half == 0 ? PSR_PCIAERR_INT_MAP :
    -	    PSR_PCIBERR_INT_MAP, psycho_pci_bus);
    +	    PSR_PCIBERR_INT_MAP, psycho_pci_bus, NULL);
     
     	/*
     	 * Set the latency timer register as this isn't always done by the
    @@ -701,7 +701,7 @@ psycho_attach(device_t dev)
     
     static void
     psycho_set_intr(struct psycho_softc *sc, u_int index, bus_addr_t intrmap,
    -    driver_filter_t handler)
    +    driver_filter_t filt, driver_intr_t intr)
     {
     	u_long vec;
     	int rid;
    @@ -722,7 +722,7 @@ psycho_set_intr(struct psycho_softc *sc, u_int index, bus_addr_t intrmap,
     	    INTVEC(PSYCHO_READ8(sc, intrmap)) != vec ||
     	    intr_vectors[vec].iv_ic != &psycho_ic ||
     	    bus_setup_intr(sc->sc_dev, sc->sc_irq_res[index],
    -	    INTR_TYPE_MISC | INTR_BRIDGE, handler, NULL, sc,
    +	    INTR_TYPE_MISC | INTR_BRIDGE, filt, intr, sc,
     	    &sc->sc_ihand[index]) != 0)
     		panic("%s: failed to set up interrupt %d", __func__, index);
     }
    @@ -858,32 +858,30 @@ psycho_powerdebug(void *arg __unused)
     	return (FILTER_HANDLED);
     }
     
    -static int
    +static void
     psycho_powerdown(void *arg __unused)
     {
     	static int shutdown;
     
     	/* As the interrupt is cleared we may be called multiple times. */
     	if (shutdown != 0)
    -		return (FILTER_HANDLED);
    +		return;
     	shutdown++;
     	printf("Power Failure Detected: Shutting down NOW.\n");
     	shutdown_nice(RB_POWEROFF);
    -	return (FILTER_HANDLED);
     }
     
    -static int
    +static void
     psycho_overtemp(void *arg __unused)
     {
     	static int shutdown;
     
     	/* As the interrupt is cleared we may be called multiple times. */
     	if (shutdown != 0)
    -		return (FILTER_HANDLED);
    +		return;
     	shutdown++;
     	printf("DANGER: OVER TEMPERATURE detected.\nShutting down NOW.\n");
     	shutdown_nice(RB_POWEROFF);
    -	return (FILTER_HANDLED);
     }
     
     #ifdef PSYCHO_MAP_WAKEUP
    
    From e8aabc79db4711f1fc92b9a405ea36f54ebfdad0 Mon Sep 17 00:00:00 2001
    From: Marius Strobl 
    Date: Sat, 2 Mar 2013 13:08:13 +0000
    Subject: [PATCH 0532/1476] - Revert the part of r247601 which turned the
     overtemperature and power fail   interrupt shutdown handlers into filters.
     Shutdown_nice(9) acquires a sleep   lock, which filters shouldn't do. It also
     seems that kern_reboot(9) still   may require Giant to be hold. - Correct an
     incorrect argument to shutdown_nice(9).
    
    Submitted by:	bde
    ---
     sys/sparc64/sbus/sbus.c | 20 +++++++++-----------
     1 file changed, 9 insertions(+), 11 deletions(-)
    
    diff --git a/sys/sparc64/sbus/sbus.c b/sys/sparc64/sbus/sbus.c
    index 6c69e2dcc5d..580624fce0e 100644
    --- a/sys/sparc64/sbus/sbus.c
    +++ b/sys/sparc64/sbus/sbus.c
    @@ -152,8 +152,8 @@ static void sbus_intr_assign(void *);
     static void sbus_intr_clear(void *);
     static int sbus_find_intrmap(struct sbus_softc *, u_int, bus_addr_t *,
         bus_addr_t *);
    -static driver_filter_t sbus_overtemp;
    -static driver_filter_t sbus_pwrfail;
    +static driver_intr_t sbus_overtemp;
    +static driver_intr_t sbus_pwrfail;
     static int sbus_print_res(struct sbus_devinfo *);
     
     static device_method_t sbus_methods[] = {
    @@ -410,7 +410,7 @@ sbus_attach(device_t dev)
     	    INTVEC(SYSIO_READ8(sc, SBR_THERM_INT_MAP)) != vec ||
     	    intr_vectors[vec].iv_ic != &sbus_ic ||
     	    bus_setup_intr(dev, sc->sc_ot_ires, INTR_TYPE_MISC | INTR_BRIDGE,
    -	    sbus_overtemp, NULL, sc, &sc->sc_ot_ihand) != 0)
    +	    NULL, sbus_overtemp, sc, &sc->sc_ot_ihand) != 0)
     		panic("%s: failed to set up temperature interrupt", __func__);
     	i = 3;
     	sc->sc_pf_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &i,
    @@ -420,7 +420,7 @@ sbus_attach(device_t dev)
     	    INTVEC(SYSIO_READ8(sc, SBR_POWER_INT_MAP)) != vec ||
     	    intr_vectors[vec].iv_ic != &sbus_ic ||
     	    bus_setup_intr(dev, sc->sc_pf_ires, INTR_TYPE_MISC | INTR_BRIDGE,
    -	    sbus_pwrfail, NULL, sc, &sc->sc_pf_ihand) != 0)
    +	    NULL, sbus_pwrfail, sc, &sc->sc_pf_ihand) != 0)
     		panic("%s: failed to set up power fail interrupt", __func__);
     
     	/* Initialize the counter-timer. */
    @@ -897,33 +897,31 @@ sbus_get_devinfo(device_t bus, device_t child)
      * This handles the interrupt and powers off the machine.
      * The same needs to be done to PCI controller drivers.
      */
    -static int
    +static void
     sbus_overtemp(void *arg __unused)
     {
     	static int shutdown;
     
     	/* As the interrupt is cleared we may be called multiple times. */
     	if (shutdown != 0)
    -		return (FILTER_HANDLED);
    +		return;
     	shutdown++;
     	printf("DANGER: OVER TEMPERATURE detected\nShutting down NOW.\n");
     	shutdown_nice(RB_POWEROFF);
    -	return (FILTER_HANDLED);
     }
     
     /* Try to shut down in time in case of power failure. */
    -static int
    +static void
     sbus_pwrfail(void *arg __unused)
     {
     	static int shutdown;
     
     	/* As the interrupt is cleared we may be called multiple times. */
     	if (shutdown != 0)
    -		return (FILTER_HANDLED);
    +		return;
     	shutdown++;
     	printf("Power failure detected\nShutting down NOW.\n");
    -	shutdown_nice(FILTER_HANDLED);
    -	return (FILTER_HANDLED);
    +	shutdown_nice(RB_POWEROFF);
     }
     
     static int
    
    From b38d37f7b52975e917997cf0c7d72cef30dfead5 Mon Sep 17 00:00:00 2001
    From: Attilio Rao 
    Date: Sat, 2 Mar 2013 14:19:08 +0000
    Subject: [PATCH 0533/1476] Merge from vmc-playground branch: Rename the
     pv_entry_t iterator from pv_list to pv_next. Besides being more correct
     technically (as the name seems to suggest this is a list while it is an
     iterator), it will also be needed by vm_radix work to avoid a nameclash on
     macro expansions.
    
    Sponsored by:	EMC / Isilon storage division
    Reviewed by:	alc, jeff
    Tested by:	flo, pho, jhb, davide
    ---
     sys/amd64/amd64/pmap.c   | 54 +++++++++++++++++++-------------------
     sys/amd64/include/pmap.h |  2 +-
     sys/i386/i386/pmap.c     | 56 ++++++++++++++++++++--------------------
     sys/i386/include/pmap.h  |  2 +-
     4 files changed, 57 insertions(+), 57 deletions(-)
    
    diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
    index f2d8967f6fb..532bd36a5f9 100644
    --- a/sys/amd64/amd64/pmap.c
    +++ b/sys/amd64/amd64/pmap.c
    @@ -2222,7 +2222,7 @@ reclaim_pv_chunk(pmap_t locked_pmap, struct rwlock **lockp)
     				if ((tpte & PG_A) != 0)
     					vm_page_aflag_set(m, PGA_REFERENCED);
     				CHANGE_PV_LIST_LOCK_TO_VM_PAGE(lockp, m);
    -				TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
    +				TAILQ_REMOVE(&m->md.pv_list, pv, pv_next);
     				if (TAILQ_EMPTY(&m->md.pv_list) &&
     				    (m->flags & PG_FICTITIOUS) == 0) {
     					pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
    @@ -2506,9 +2506,9 @@ pmap_pvh_remove(struct md_page *pvh, pmap_t pmap, vm_offset_t va)
     	pv_entry_t pv;
     
     	rw_assert(&pvh_global_lock, RA_LOCKED);
    -	TAILQ_FOREACH(pv, &pvh->pv_list, pv_list) {
    +	TAILQ_FOREACH(pv, &pvh->pv_list, pv_next) {
     		if (pmap == PV_PMAP(pv) && va == pv->pv_va) {
    -			TAILQ_REMOVE(&pvh->pv_list, pv, pv_list);
    +			TAILQ_REMOVE(&pvh->pv_list, pv, pv_next);
     			break;
     		}
     	}
    @@ -2547,7 +2547,7 @@ pmap_pv_demote_pde(pmap_t pmap, vm_offset_t va, vm_paddr_t pa,
     	pv = pmap_pvh_remove(pvh, pmap, va);
     	KASSERT(pv != NULL, ("pmap_pv_demote_pde: pv not found"));
     	m = PHYS_TO_VM_PAGE(pa);
    -	TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_list);
    +	TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next);
     	/* Instantiate the remaining NPTEPG - 1 pv entries. */
     	PV_STAT(atomic_add_long(&pv_entry_allocs, NPTEPG - 1));
     	va_last = va + NBPDR - PAGE_SIZE;
    @@ -2565,7 +2565,7 @@ pmap_pv_demote_pde(pmap_t pmap, vm_offset_t va, vm_paddr_t pa,
     				m++;
     				KASSERT((m->oflags & VPO_UNMANAGED) == 0,
     			    ("pmap_pv_demote_pde: page %p is not managed", m));
    -				TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_list);
    +				TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next);
     				if (va == va_last)
     					goto out;
     			}
    @@ -2613,7 +2613,7 @@ pmap_pv_promote_pde(pmap_t pmap, vm_offset_t va, vm_paddr_t pa,
     	pv = pmap_pvh_remove(&m->md, pmap, va);
     	KASSERT(pv != NULL, ("pmap_pv_promote_pde: pv not found"));
     	pvh = pa_to_pvh(pa);
    -	TAILQ_INSERT_TAIL(&pvh->pv_list, pv, pv_list);
    +	TAILQ_INSERT_TAIL(&pvh->pv_list, pv, pv_next);
     	/* Free the remaining NPTEPG - 1 pv entries. */
     	va_last = va + NBPDR - PAGE_SIZE;
     	do {
    @@ -2654,7 +2654,7 @@ pmap_try_insert_pv_entry(pmap_t pmap, vm_offset_t va, vm_page_t m,
     	if ((pv = get_pv_entry(pmap, NULL)) != NULL) {
     		pv->pv_va = va;
     		CHANGE_PV_LIST_LOCK_TO_VM_PAGE(lockp, m);
    -		TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_list);
    +		TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next);
     		return (TRUE);
     	} else
     		return (FALSE);
    @@ -2678,7 +2678,7 @@ pmap_pv_insert_pde(pmap_t pmap, vm_offset_t va, vm_paddr_t pa,
     		pv->pv_va = va;
     		CHANGE_PV_LIST_LOCK_TO_PHYS(lockp, pa);
     		pvh = pa_to_pvh(pa);
    -		TAILQ_INSERT_TAIL(&pvh->pv_list, pv, pv_list);
    +		TAILQ_INSERT_TAIL(&pvh->pv_list, pv, pv_next);
     		return (TRUE);
     	} else
     		return (FALSE);
    @@ -3157,7 +3157,7 @@ small_mappings:
     			vm_page_dirty(m);
     		pmap_unuse_pt(pmap, pv->pv_va, *pde, &free);
     		pmap_invalidate_page(pmap, pv->pv_va);
    -		TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
    +		TAILQ_REMOVE(&m->md.pv_list, pv, pv_next);
     		free_pv_entry(pmap, pv);
     		PMAP_UNLOCK(pmap);
     	}
    @@ -3602,7 +3602,7 @@ retry:
     		pv = get_pv_entry(pmap, &lock);
     		pv->pv_va = va;
     		CHANGE_PV_LIST_LOCK_TO_PHYS(&lock, pa);
    -		TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_list);
    +		TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next);
     		if ((newpte & PG_RW) != 0)
     			vm_page_aflag_set(m, PGA_WRITEABLE);
     	}
    @@ -4295,7 +4295,7 @@ pmap_page_exists_quick(pmap_t pmap, vm_page_t m)
     	rw_rlock(&pvh_global_lock);
     	lock = VM_PAGE_TO_PV_LIST_LOCK(m);
     	rw_rlock(lock);
    -	TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
    +	TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) {
     		if (PV_PMAP(pv) == pmap) {
     			rv = TRUE;
     			break;
    @@ -4306,7 +4306,7 @@ pmap_page_exists_quick(pmap_t pmap, vm_page_t m)
     	}
     	if (!rv && loops < 16 && (m->flags & PG_FICTITIOUS) == 0) {
     		pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
    -		TAILQ_FOREACH(pv, &pvh->pv_list, pv_list) {
    +		TAILQ_FOREACH(pv, &pvh->pv_list, pv_next) {
     			if (PV_PMAP(pv) == pmap) {
     				rv = TRUE;
     				break;
    @@ -4358,7 +4358,7 @@ pmap_pvh_wired_mappings(struct md_page *pvh, int count)
     	pv_entry_t pv;
     
     	rw_assert(&pvh_global_lock, RA_WLOCKED);
    -	TAILQ_FOREACH(pv, &pvh->pv_list, pv_list) {
    +	TAILQ_FOREACH(pv, &pvh->pv_list, pv_next) {
     		pmap = PV_PMAP(pv);
     		PMAP_LOCK(pmap);
     		pte = pmap_pte(pmap, pv->pv_va);
    @@ -4489,7 +4489,7 @@ pmap_remove_pages(pmap_t pmap)
     				if ((tpte & PG_PS) != 0) {
     					pmap_resident_count_dec(pmap, NBPDR / PAGE_SIZE);
     					pvh = pa_to_pvh(tpte & PG_PS_FRAME);
    -					TAILQ_REMOVE(&pvh->pv_list, pv, pv_list);
    +					TAILQ_REMOVE(&pvh->pv_list, pv, pv_next);
     					if (TAILQ_EMPTY(&pvh->pv_list)) {
     						for (mt = m; mt < &m[NBPDR / PAGE_SIZE]; mt++)
     							if ((mt->aflags & PGA_WRITEABLE) != 0 &&
    @@ -4508,7 +4508,7 @@ pmap_remove_pages(pmap_t pmap)
     					}
     				} else {
     					pmap_resident_count_dec(pmap, 1);
    -					TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
    +					TAILQ_REMOVE(&m->md.pv_list, pv, pv_next);
     					if ((m->aflags & PGA_WRITEABLE) != 0 &&
     					    TAILQ_EMPTY(&m->md.pv_list) &&
     					    (m->flags & PG_FICTITIOUS) == 0) {
    @@ -4583,7 +4583,7 @@ pmap_is_modified_pvh(struct md_page *pvh)
     
     	rw_assert(&pvh_global_lock, RA_WLOCKED);
     	rv = FALSE;
    -	TAILQ_FOREACH(pv, &pvh->pv_list, pv_list) {
    +	TAILQ_FOREACH(pv, &pvh->pv_list, pv_next) {
     		pmap = PV_PMAP(pv);
     		PMAP_LOCK(pmap);
     		pte = pmap_pte(pmap, pv->pv_va);
    @@ -4654,7 +4654,7 @@ pmap_is_referenced_pvh(struct md_page *pvh)
     
     	rw_assert(&pvh_global_lock, RA_WLOCKED);
     	rv = FALSE;
    -	TAILQ_FOREACH(pv, &pvh->pv_list, pv_list) {
    +	TAILQ_FOREACH(pv, &pvh->pv_list, pv_next) {
     		pmap = PV_PMAP(pv);
     		PMAP_LOCK(pmap);
     		pte = pmap_pte(pmap, pv->pv_va);
    @@ -4695,7 +4695,7 @@ pmap_remove_write(vm_page_t m)
     	if ((m->flags & PG_FICTITIOUS) != 0)
     		goto small_mappings;
     	pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
    -	TAILQ_FOREACH_SAFE(pv, &pvh->pv_list, pv_list, next_pv) {
    +	TAILQ_FOREACH_SAFE(pv, &pvh->pv_list, pv_next, next_pv) {
     		pmap = PV_PMAP(pv);
     		PMAP_LOCK(pmap);
     		va = pv->pv_va;
    @@ -4705,7 +4705,7 @@ pmap_remove_write(vm_page_t m)
     		PMAP_UNLOCK(pmap);
     	}
     small_mappings:
    -	TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
    +	TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) {
     		pmap = PV_PMAP(pv);
     		PMAP_LOCK(pmap);
     		pde = pmap_pde(pmap, pv->pv_va);
    @@ -4758,7 +4758,7 @@ pmap_ts_referenced(vm_page_t m)
     	if ((m->flags & PG_FICTITIOUS) != 0)
     		goto small_mappings;
     	pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
    -	TAILQ_FOREACH_SAFE(pv, &pvh->pv_list, pv_list, pvn) {
    +	TAILQ_FOREACH_SAFE(pv, &pvh->pv_list, pv_next, pvn) {
     		pmap = PV_PMAP(pv);
     		PMAP_LOCK(pmap);
     		va = pv->pv_va;
    @@ -4792,9 +4792,9 @@ small_mappings:
     	if ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) {
     		pvf = pv;
     		do {
    -			pvn = TAILQ_NEXT(pv, pv_list);
    -			TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
    -			TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_list);
    +			pvn = TAILQ_NEXT(pv, pv_next);
    +			TAILQ_REMOVE(&m->md.pv_list, pv, pv_next);
    +			TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next);
     			pmap = PV_PMAP(pv);
     			PMAP_LOCK(pmap);
     			pde = pmap_pde(pmap, pv->pv_va);
    @@ -4846,7 +4846,7 @@ pmap_clear_modify(vm_page_t m)
     	if ((m->flags & PG_FICTITIOUS) != 0)
     		goto small_mappings;
     	pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
    -	TAILQ_FOREACH_SAFE(pv, &pvh->pv_list, pv_list, next_pv) {
    +	TAILQ_FOREACH_SAFE(pv, &pvh->pv_list, pv_next, next_pv) {
     		pmap = PV_PMAP(pv);
     		PMAP_LOCK(pmap);
     		va = pv->pv_va;
    @@ -4878,7 +4878,7 @@ pmap_clear_modify(vm_page_t m)
     		PMAP_UNLOCK(pmap);
     	}
     small_mappings:
    -	TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
    +	TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) {
     		pmap = PV_PMAP(pv);
     		PMAP_LOCK(pmap);
     		pde = pmap_pde(pmap, pv->pv_va);
    @@ -4915,7 +4915,7 @@ pmap_clear_reference(vm_page_t m)
     	if ((m->flags & PG_FICTITIOUS) != 0)
     		goto small_mappings;
     	pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
    -	TAILQ_FOREACH_SAFE(pv, &pvh->pv_list, pv_list, next_pv) {
    +	TAILQ_FOREACH_SAFE(pv, &pvh->pv_list, pv_next, next_pv) {
     		pmap = PV_PMAP(pv);
     		PMAP_LOCK(pmap);
     		va = pv->pv_va;
    @@ -4938,7 +4938,7 @@ pmap_clear_reference(vm_page_t m)
     		PMAP_UNLOCK(pmap);
     	}
     small_mappings:
    -	TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
    +	TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) {
     		pmap = PV_PMAP(pv);
     		PMAP_LOCK(pmap);
     		pde = pmap_pde(pmap, pv->pv_va);
    diff --git a/sys/amd64/include/pmap.h b/sys/amd64/include/pmap.h
    index 334d6c68ca1..0fc8867731a 100644
    --- a/sys/amd64/include/pmap.h
    +++ b/sys/amd64/include/pmap.h
    @@ -277,7 +277,7 @@ extern struct pmap	kernel_pmap_store;
      */
     typedef struct pv_entry {
     	vm_offset_t	pv_va;		/* virtual address for mapping */
    -	TAILQ_ENTRY(pv_entry)	pv_list;
    +	TAILQ_ENTRY(pv_entry)	pv_next;
     } *pv_entry_t;
     
     /*
    diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c
    index 3c47a456785..9aaf1ebd13d 100644
    --- a/sys/i386/i386/pmap.c
    +++ b/sys/i386/i386/pmap.c
    @@ -2286,7 +2286,7 @@ pmap_pv_reclaim(pmap_t locked_pmap)
     					vm_page_dirty(m);
     				if ((tpte & PG_A) != 0)
     					vm_page_aflag_set(m, PGA_REFERENCED);
    -				TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
    +				TAILQ_REMOVE(&m->md.pv_list, pv, pv_next);
     				if (TAILQ_EMPTY(&m->md.pv_list) &&
     				    (m->flags & PG_FICTITIOUS) == 0) {
     					pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
    @@ -2491,9 +2491,9 @@ pmap_pvh_remove(struct md_page *pvh, pmap_t pmap, vm_offset_t va)
     	pv_entry_t pv;
     
     	rw_assert(&pvh_global_lock, RA_WLOCKED);
    -	TAILQ_FOREACH(pv, &pvh->pv_list, pv_list) {
    +	TAILQ_FOREACH(pv, &pvh->pv_list, pv_next) {
     		if (pmap == PV_PMAP(pv) && va == pv->pv_va) {
    -			TAILQ_REMOVE(&pvh->pv_list, pv, pv_list);
    +			TAILQ_REMOVE(&pvh->pv_list, pv, pv_next);
     			break;
     		}
     	}
    @@ -2521,7 +2521,7 @@ pmap_pv_demote_pde(pmap_t pmap, vm_offset_t va, vm_paddr_t pa)
     	pv = pmap_pvh_remove(pvh, pmap, va);
     	KASSERT(pv != NULL, ("pmap_pv_demote_pde: pv not found"));
     	m = PHYS_TO_VM_PAGE(pa);
    -	TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_list);
    +	TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next);
     	/* Instantiate the remaining NPTEPG - 1 pv entries. */
     	va_last = va + NBPDR - PAGE_SIZE;
     	do {
    @@ -2557,7 +2557,7 @@ pmap_pv_promote_pde(pmap_t pmap, vm_offset_t va, vm_paddr_t pa)
     	pv = pmap_pvh_remove(&m->md, pmap, va);
     	KASSERT(pv != NULL, ("pmap_pv_promote_pde: pv not found"));
     	pvh = pa_to_pvh(pa);
    -	TAILQ_INSERT_TAIL(&pvh->pv_list, pv, pv_list);
    +	TAILQ_INSERT_TAIL(&pvh->pv_list, pv, pv_next);
     	/* Free the remaining NPTEPG - 1 pv entries. */
     	va_last = va + NBPDR - PAGE_SIZE;
     	do {
    @@ -2604,7 +2604,7 @@ pmap_insert_entry(pmap_t pmap, vm_offset_t va, vm_page_t m)
     	PMAP_LOCK_ASSERT(pmap, MA_OWNED);
     	pv = get_pv_entry(pmap, FALSE);
     	pv->pv_va = va;
    -	TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_list);
    +	TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next);
     }
     
     /*
    @@ -2620,7 +2620,7 @@ pmap_try_insert_pv_entry(pmap_t pmap, vm_offset_t va, vm_page_t m)
     	if (pv_entry_count < pv_entry_high_water && 
     	    (pv = get_pv_entry(pmap, TRUE)) != NULL) {
     		pv->pv_va = va;
    -		TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_list);
    +		TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next);
     		return (TRUE);
     	} else
     		return (FALSE);
    @@ -2640,7 +2640,7 @@ pmap_pv_insert_pde(pmap_t pmap, vm_offset_t va, vm_paddr_t pa)
     	    (pv = get_pv_entry(pmap, TRUE)) != NULL) {
     		pv->pv_va = va;
     		pvh = pa_to_pvh(pa);
    -		TAILQ_INSERT_TAIL(&pvh->pv_list, pv, pv_list);
    +		TAILQ_INSERT_TAIL(&pvh->pv_list, pv, pv_next);
     		return (TRUE);
     	} else
     		return (FALSE);
    @@ -3095,7 +3095,7 @@ small_mappings:
     			vm_page_dirty(m);
     		pmap_unuse_pt(pmap, pv->pv_va, &free);
     		pmap_invalidate_page(pmap, pv->pv_va);
    -		TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
    +		TAILQ_REMOVE(&m->md.pv_list, pv, pv_next);
     		free_pv_entry(pmap, pv);
     		PMAP_UNLOCK(pmap);
     	}
    @@ -3550,7 +3550,7 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_prot_t access, vm_page_t m,
     		if (pv == NULL)
     			pv = get_pv_entry(pmap, FALSE);
     		pv->pv_va = va;
    -		TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_list);
    +		TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next);
     		pa |= PG_MANAGED;
     	} else if (pv != NULL)
     		free_pv_entry(pmap, pv);
    @@ -4258,7 +4258,7 @@ pmap_page_exists_quick(pmap_t pmap, vm_page_t m)
     	    ("pmap_page_exists_quick: page %p is not managed", m));
     	rv = FALSE;
     	rw_wlock(&pvh_global_lock);
    -	TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
    +	TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) {
     		if (PV_PMAP(pv) == pmap) {
     			rv = TRUE;
     			break;
    @@ -4269,7 +4269,7 @@ pmap_page_exists_quick(pmap_t pmap, vm_page_t m)
     	}
     	if (!rv && loops < 16 && (m->flags & PG_FICTITIOUS) == 0) {
     		pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
    -		TAILQ_FOREACH(pv, &pvh->pv_list, pv_list) {
    +		TAILQ_FOREACH(pv, &pvh->pv_list, pv_next) {
     			if (PV_PMAP(pv) == pmap) {
     				rv = TRUE;
     				break;
    @@ -4321,7 +4321,7 @@ pmap_pvh_wired_mappings(struct md_page *pvh, int count)
     
     	rw_assert(&pvh_global_lock, RA_WLOCKED);
     	sched_pin();
    -	TAILQ_FOREACH(pv, &pvh->pv_list, pv_list) {
    +	TAILQ_FOREACH(pv, &pvh->pv_list, pv_next) {
     		pmap = PV_PMAP(pv);
     		PMAP_LOCK(pmap);
     		pte = pmap_pte_quick(pmap, pv->pv_va);
    @@ -4448,7 +4448,7 @@ pmap_remove_pages(pmap_t pmap)
     				if ((tpte & PG_PS) != 0) {
     					pmap->pm_stats.resident_count -= NBPDR / PAGE_SIZE;
     					pvh = pa_to_pvh(tpte & PG_PS_FRAME);
    -					TAILQ_REMOVE(&pvh->pv_list, pv, pv_list);
    +					TAILQ_REMOVE(&pvh->pv_list, pv, pv_next);
     					if (TAILQ_EMPTY(&pvh->pv_list)) {
     						for (mt = m; mt < &m[NBPDR / PAGE_SIZE]; mt++)
     							if (TAILQ_EMPTY(&mt->md.pv_list))
    @@ -4466,7 +4466,7 @@ pmap_remove_pages(pmap_t pmap)
     					}
     				} else {
     					pmap->pm_stats.resident_count--;
    -					TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
    +					TAILQ_REMOVE(&m->md.pv_list, pv, pv_next);
     					if (TAILQ_EMPTY(&m->md.pv_list) &&
     					    (m->flags & PG_FICTITIOUS) == 0) {
     						pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
    @@ -4536,7 +4536,7 @@ pmap_is_modified_pvh(struct md_page *pvh)
     	rw_assert(&pvh_global_lock, RA_WLOCKED);
     	rv = FALSE;
     	sched_pin();
    -	TAILQ_FOREACH(pv, &pvh->pv_list, pv_list) {
    +	TAILQ_FOREACH(pv, &pvh->pv_list, pv_next) {
     		pmap = PV_PMAP(pv);
     		PMAP_LOCK(pmap);
     		pte = pmap_pte_quick(pmap, pv->pv_va);
    @@ -4609,7 +4609,7 @@ pmap_is_referenced_pvh(struct md_page *pvh)
     	rw_assert(&pvh_global_lock, RA_WLOCKED);
     	rv = FALSE;
     	sched_pin();
    -	TAILQ_FOREACH(pv, &pvh->pv_list, pv_list) {
    +	TAILQ_FOREACH(pv, &pvh->pv_list, pv_next) {
     		pmap = PV_PMAP(pv);
     		PMAP_LOCK(pmap);
     		pte = pmap_pte_quick(pmap, pv->pv_va);
    @@ -4652,7 +4652,7 @@ pmap_remove_write(vm_page_t m)
     	if ((m->flags & PG_FICTITIOUS) != 0)
     		goto small_mappings;
     	pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
    -	TAILQ_FOREACH_SAFE(pv, &pvh->pv_list, pv_list, next_pv) {
    +	TAILQ_FOREACH_SAFE(pv, &pvh->pv_list, pv_next, next_pv) {
     		va = pv->pv_va;
     		pmap = PV_PMAP(pv);
     		PMAP_LOCK(pmap);
    @@ -4662,7 +4662,7 @@ pmap_remove_write(vm_page_t m)
     		PMAP_UNLOCK(pmap);
     	}
     small_mappings:
    -	TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
    +	TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) {
     		pmap = PV_PMAP(pv);
     		PMAP_LOCK(pmap);
     		pde = pmap_pde(pmap, pv->pv_va);
    @@ -4721,7 +4721,7 @@ pmap_ts_referenced(vm_page_t m)
     	sched_pin();
     	if ((m->flags & PG_FICTITIOUS) != 0)
     		goto small_mappings;
    -	TAILQ_FOREACH_SAFE(pv, &pvh->pv_list, pv_list, pvn) {
    +	TAILQ_FOREACH_SAFE(pv, &pvh->pv_list, pv_next, pvn) {
     		va = pv->pv_va;
     		pmap = PV_PMAP(pv);
     		PMAP_LOCK(pmap);
    @@ -4755,9 +4755,9 @@ small_mappings:
     	if ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) {
     		pvf = pv;
     		do {
    -			pvn = TAILQ_NEXT(pv, pv_list);
    -			TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
    -			TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_list);
    +			pvn = TAILQ_NEXT(pv, pv_next);
    +			TAILQ_REMOVE(&m->md.pv_list, pv, pv_next);
    +			TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next);
     			pmap = PV_PMAP(pv);
     			PMAP_LOCK(pmap);
     			pde = pmap_pde(pmap, pv->pv_va);
    @@ -4811,7 +4811,7 @@ pmap_clear_modify(vm_page_t m)
     	if ((m->flags & PG_FICTITIOUS) != 0)
     		goto small_mappings;
     	pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
    -	TAILQ_FOREACH_SAFE(pv, &pvh->pv_list, pv_list, next_pv) {
    +	TAILQ_FOREACH_SAFE(pv, &pvh->pv_list, pv_next, next_pv) {
     		va = pv->pv_va;
     		pmap = PV_PMAP(pv);
     		PMAP_LOCK(pmap);
    @@ -4848,7 +4848,7 @@ pmap_clear_modify(vm_page_t m)
     		PMAP_UNLOCK(pmap);
     	}
     small_mappings:
    -	TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
    +	TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) {
     		pmap = PV_PMAP(pv);
     		PMAP_LOCK(pmap);
     		pde = pmap_pde(pmap, pv->pv_va);
    @@ -4892,7 +4892,7 @@ pmap_clear_reference(vm_page_t m)
     	if ((m->flags & PG_FICTITIOUS) != 0)
     		goto small_mappings;
     	pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
    -	TAILQ_FOREACH_SAFE(pv, &pvh->pv_list, pv_list, next_pv) {
    +	TAILQ_FOREACH_SAFE(pv, &pvh->pv_list, pv_next, next_pv) {
     		va = pv->pv_va;
     		pmap = PV_PMAP(pv);
     		PMAP_LOCK(pmap);
    @@ -4915,7 +4915,7 @@ pmap_clear_reference(vm_page_t m)
     		PMAP_UNLOCK(pmap);
     	}
     small_mappings:
    -	TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
    +	TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) {
     		pmap = PV_PMAP(pv);
     		PMAP_LOCK(pmap);
     		pde = pmap_pde(pmap, pv->pv_va);
    @@ -5426,7 +5426,7 @@ pmap_pvdump(vm_paddr_t pa)
     
     	printf("pa %x", pa);
     	m = PHYS_TO_VM_PAGE(pa);
    -	TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
    +	TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) {
     		pmap = PV_PMAP(pv);
     		printf(" -> pmap %p, va %x", (void *)pmap, pv->pv_va);
     		pads(pmap);
    diff --git a/sys/i386/include/pmap.h b/sys/i386/include/pmap.h
    index 7a827f8b994..1de47f23ea8 100644
    --- a/sys/i386/include/pmap.h
    +++ b/sys/i386/include/pmap.h
    @@ -468,7 +468,7 @@ extern struct pmap	kernel_pmap_store;
      */
     typedef struct pv_entry {
     	vm_offset_t	pv_va;		/* virtual address for mapping */
    -	TAILQ_ENTRY(pv_entry)	pv_list;
    +	TAILQ_ENTRY(pv_entry)	pv_next;
     } *pv_entry_t;
     
     /*
    
    From 39bddcde9672324c16c236249f1a2cf1de712fc6 Mon Sep 17 00:00:00 2001
    From: "Alexander V. Chernikov" 
    Date: Sat, 2 Mar 2013 14:47:10 +0000
    Subject: [PATCH 0534/1476] Fix callout expiring dynamic rules.
    
    PR:		kern/175530
    Submitted by:	Vladimir Spiridenkov 
    MFC after:	2 weeks
    ---
     sys/netpfil/ipfw/ip_fw_dynamic.c | 6 +++---
     1 file changed, 3 insertions(+), 3 deletions(-)
    
    diff --git a/sys/netpfil/ipfw/ip_fw_dynamic.c b/sys/netpfil/ipfw/ip_fw_dynamic.c
    index 656e826a624..b0456d37f98 100644
    --- a/sys/netpfil/ipfw/ip_fw_dynamic.c
    +++ b/sys/netpfil/ipfw/ip_fw_dynamic.c
    @@ -980,8 +980,8 @@ ipfw_dyn_tick(void * vnetx)
     
     	chain = &V_layer3_chain;
     
    -	/* Run keepalive checks every keepalive_interval iff ka is enabled */
    -	if ((V_dyn_keepalive_last + V_dyn_keepalive_interval >= time_uptime) &&
    +	/* Run keepalive checks every keepalive_period iff ka is enabled */
    +	if ((V_dyn_keepalive_last + V_dyn_keepalive_period <= time_uptime) &&
     	    (V_dyn_keepalive != 0)) {
     		V_dyn_keepalive_last = time_uptime;
     		check_ka = 1;
    @@ -1320,7 +1320,7 @@ ipfw_dyn_init(struct ip_fw_chain *chain)
             V_dyn_keepalive_interval = 20;
             V_dyn_keepalive_period = 5;
             V_dyn_keepalive = 1;    /* do send keepalives */
    -	V_dyn_keepalive = time_uptime;
    +	V_dyn_keepalive_last = time_uptime;
             
             V_dyn_max = 4096;       /* max # of dynamic rules */
     
    
    From 258bee160c22bfaa2ae20a018cb208b8ab1960a7 Mon Sep 17 00:00:00 2001
    From: Attilio Rao 
    Date: Sat, 2 Mar 2013 14:54:33 +0000
    Subject: [PATCH 0535/1476] Garbage collect HPFS bits which are now already
     completely disconnected from the tree since few months (please note that the
     userland bits were already disconnected since a long time, thus there is no
     need to update the OLD* entries).
    
    This is not targeted for MFC.
    ---
     sbin/mount_hpfs/Makefile     |   14 -
     sbin/mount_hpfs/mount_hpfs.8 |  100 ---
     sbin/mount_hpfs/mount_hpfs.c |  244 -------
     sys/fs/hpfs/hpfs.h           |  387 -----------
     sys/fs/hpfs/hpfs_alsubr.c    |  907 ------------------------
     sys/fs/hpfs/hpfs_ioctl.h     |   43 --
     sys/fs/hpfs/hpfs_lookup.c    |  213 ------
     sys/fs/hpfs/hpfs_subr.c      |  869 -----------------------
     sys/fs/hpfs/hpfs_subr.h      |   89 ---
     sys/fs/hpfs/hpfs_vfsops.c    |  545 ---------------
     sys/fs/hpfs/hpfs_vnops.c     | 1264 ----------------------------------
     sys/fs/hpfs/hpfsmount.h      |   39 --
     sys/modules/hpfs/Makefile    |   10 -
     13 files changed, 4724 deletions(-)
     delete mode 100644 sbin/mount_hpfs/Makefile
     delete mode 100644 sbin/mount_hpfs/mount_hpfs.8
     delete mode 100644 sbin/mount_hpfs/mount_hpfs.c
     delete mode 100644 sys/fs/hpfs/hpfs.h
     delete mode 100644 sys/fs/hpfs/hpfs_alsubr.c
     delete mode 100644 sys/fs/hpfs/hpfs_ioctl.h
     delete mode 100644 sys/fs/hpfs/hpfs_lookup.c
     delete mode 100644 sys/fs/hpfs/hpfs_subr.c
     delete mode 100644 sys/fs/hpfs/hpfs_subr.h
     delete mode 100644 sys/fs/hpfs/hpfs_vfsops.c
     delete mode 100644 sys/fs/hpfs/hpfs_vnops.c
     delete mode 100644 sys/fs/hpfs/hpfsmount.h
     delete mode 100644 sys/modules/hpfs/Makefile
    
    diff --git a/sbin/mount_hpfs/Makefile b/sbin/mount_hpfs/Makefile
    deleted file mode 100644
    index 9e65b8e1833..00000000000
    --- a/sbin/mount_hpfs/Makefile
    +++ /dev/null
    @@ -1,14 +0,0 @@
    -#
    -# $FreeBSD$
    -#
    -
    -PROG=	mount_hpfs
    -SRCS=	mount_hpfs.c getmntopts.c
    -MAN=	mount_hpfs.8
    -
    -MOUNT=	${.CURDIR}/../mount
    -CFLAGS+= -I${MOUNT} -DHPFS
    -
    -.PATH:	${MOUNT}
    -
    -.include 
    diff --git a/sbin/mount_hpfs/mount_hpfs.8 b/sbin/mount_hpfs/mount_hpfs.8
    deleted file mode 100644
    index 81e3ea3932f..00000000000
    --- a/sbin/mount_hpfs/mount_hpfs.8
    +++ /dev/null
    @@ -1,100 +0,0 @@
    -.\"
    -.\" Copyright (c) 1993,1994 Christopher G. Demetriou
    -.\" Copyright (c) 1999 Semen Ustimenko 
    -.\" All rights reserved.
    -.\"
    -.\" Redistribution and use in source and binary forms, with or without
    -.\" modification, are permitted provided that the following conditions
    -.\" are met:
    -.\" 1. Redistributions of source code must retain the above copyright
    -.\"    notice, this list of conditions and the following disclaimer.
    -.\" 2. Redistributions in binary form must reproduce the above copyright
    -.\"    notice, this list of conditions and the following disclaimer in the
    -.\"    documentation and/or other materials provided with the distribution.
    -.\" 3. All advertising materials mentioning features or use of this software
    -.\"    must display the following acknowledgment:
    -.\"      This product includes software developed by Christopher G. Demetriou.
    -.\" 3. The name of the author may not be used to endorse or promote products
    -.\"    derived from this software without specific prior written permission
    -.\"
    -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
    -.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    -.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    -.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
    -.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    -.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    -.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    -.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    -.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    -.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    -.\"
    -.\" $FreeBSD$
    -.\"
    -.Dd May 20, 1999
    -.Dt MOUNT_HPFS 8
    -.Os
    -.Sh NAME
    -.Nm mount_hpfs
    -.Nd mount an HPFS file system
    -.Sh SYNOPSIS
    -.Nm
    -.Op Fl o Ar options
    -.Op Fl u Ar uid
    -.Op Fl g Ar gid
    -.Op Fl m Ar mask
    -.Pa special
    -.Pa node
    -.Sh DESCRIPTION
    -The
    -.Nm
    -utility attaches the HPFS file system residing on the device
    -.Pa special
    -to the global file system namespace at the location
    -indicated by
    -.Pa node .
    -This command is normally executed by
    -.Xr mount 8
    -at boot time, but can be used by any user to mount an
    -HPFS file system on any directory that they own (provided,
    -of course, that they have appropriate access to the device that
    -contains the file system).
    -.Pp
    -The options are as follows:
    -.Bl -tag -width Ds
    -.It Fl u Ar uid
    -Set the owner of the files in the file system to
    -.Ar uid .
    -The default owner is the owner of the directory
    -on which the file system is being mounted.
    -.It Fl g Ar gid
    -Set the group of the files in the file system to
    -.Ar gid .
    -The default group is the group of the directory
    -on which the file system is being mounted.
    -.It Fl m Ar mask
    -Specify the maximum file permissions for files
    -in the file system.
    -.El
    -.Sh EXAMPLES
    -To mount an hpfs volume located in /dev/wd1s1:
    -.Bd -literal -offset indent
    -# mount_hpfs /dev/wd1s1 /mnt
    -.Ed
    -.Sh WRITING
    -There is limited writing ability and it is not well-tested.
    -It is strongly recommended to mount readonly!
    -.Sh SEE ALSO
    -.Xr mount 2 ,
    -.Xr unmount 2 ,
    -.Xr fstab 5 ,
    -.Xr mount 8
    -.Sh HISTORY
    -The
    -.Nm
    -utility first appeared in
    -.Fx 3.0 .
    -.Sh AUTHORS
    -HPFS kernel implementation,
    -.Nm
    -and manual were written by
    -.An Semen Ustimenko Aq semenu@FreeBSD.org .
    diff --git a/sbin/mount_hpfs/mount_hpfs.c b/sbin/mount_hpfs/mount_hpfs.c
    deleted file mode 100644
    index 0106377c745..00000000000
    --- a/sbin/mount_hpfs/mount_hpfs.c
    +++ /dev/null
    @@ -1,244 +0,0 @@
    -/*
    - * Copyright (c) 1994 Christopher G. Demetriou
    - * Copyright (c) 1999 Semen Ustimenko (semenu@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.
    - * 3. All advertising materials mentioning features or use of this software
    - *    must display the following acknowledgement:
    - *      This product includes software developed by Christopher G. Demetriou.
    - * 4. The name of the author may not be used to endorse or promote products
    - *    derived from this software without specific prior written permission
    - *
    - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
    - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
    - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    - *
    - * $FreeBSD$
    - */
    -
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -
    -#include "mntopts.h"
    -
    -static struct mntopt mopts[] = {
    -	MOPT_STDOPTS,
    -	MOPT_END
    -};
    -
    -static gid_t	a_gid(char *);
    -static uid_t	a_uid(char *);
    -static mode_t	a_mask(char *);
    -static void	usage(void) __dead2;
    -static void	load_u2wtable(struct hpfs_args *, char *);
    -
    -int
    -main(int argc, char *argv[])
    -{
    -	struct hpfs_args args;
    -	struct stat sb;
    -	int c, mntflags, set_gid, set_uid, set_mask;
    -	int forcerw = 0;
    -	char *dev, *dir, ndir[MAXPATHLEN];
    -
    -	mntflags = set_gid = set_uid = set_mask = 0;
    -	(void)memset(&args, '\0', sizeof(args));
    -
    -	while ((c = getopt(argc, argv, "u:g:m:o:c:W:F")) !=  -1) {
    -		switch (c) {
    -		case 'F':
    -			forcerw=1;
    -			break;
    -		case 'u':
    -			args.uid = a_uid(optarg);
    -			set_uid = 1;
    -			break;
    -		case 'g':
    -			args.gid = a_gid(optarg);
    -			set_gid = 1;
    -			break;
    -		case 'm':
    -			args.mode = a_mask(optarg);
    -			set_mask = 1;
    -			break;
    -		case 'o':
    -			getmntopts(optarg, mopts, &mntflags, 0);
    -			break;
    -		case 'W':
    -			load_u2wtable(&args, optarg);
    -			args.flags |= HPFSMNT_TABLES;
    -			break;
    -		case '?':
    -		default:
    -			usage();
    -			break;
    -		}
    -	}
    -
    -	if (optind + 2 != argc)
    -		usage();
    -
    -	if (!(mntflags & MNT_RDONLY) && !forcerw) {
    -		warnx("Write support is BETA, you need -F flag to enable RW mount!");
    -		exit (111);
    -	}
    -
    -	dev = argv[optind];
    -	dir = argv[optind + 1];
    -	if (dir[0] != '/') {
    -		warnx("\"%s\" is a relative path", dir);
    -		if (getcwd(ndir, sizeof(ndir)) == NULL)
    -			err(EX_OSERR, "getcwd");
    -		strncat(ndir, "/", sizeof(ndir) - strlen(ndir) - 1);
    -		strncat(ndir, dir, sizeof(ndir) - strlen(ndir) - 1);
    -		dir = ndir;
    -		warnx("using \"%s\" instead", dir);
    -	}
    -
    -	args.fspec = dev;
    -	args.export.ex_root = 65534;	/* unchecked anyway on DOS fs */
    -	if (mntflags & MNT_RDONLY)
    -		args.export.ex_flags = MNT_EXRDONLY;
    -	else
    -		args.export.ex_flags = 0;
    -
    -	if (!set_gid || !set_uid || !set_mask) {
    -		if (stat(dir, &sb) == -1)
    -			err(EX_OSERR, "stat %s", dir);
    -
    -		if (!set_uid)
    -			args.uid = sb.st_uid;
    -		if (!set_gid)
    -			args.gid = sb.st_gid;
    -		if (!set_mask)
    -			args.mode = sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
    -	}
    -
    -	if (mount("hpfs", dir, mntflags, &args) < 0)
    -		err(EX_OSERR, "%s", dev);
    -
    -	exit (0);
    -}
    -
    -gid_t
    -a_gid(char *s)
    -{
    -	struct group *gr;
    -	char *gname;
    -	gid_t gid;
    -
    -	if ((gr = getgrnam(s)) != NULL)
    -		gid = gr->gr_gid;
    -	else {
    -		for (gname = s; *s && isdigit(*s); ++s);
    -		if (!*s)
    -			gid = atoi(gname);
    -		else
    -			errx(EX_NOUSER, "unknown group id: %s", gname);
    -	}
    -	return (gid);
    -}
    -
    -uid_t
    -a_uid(char *s)
    -{
    -	struct passwd *pw;
    -	char *uname;
    -	uid_t uid;
    -
    -	if ((pw = getpwnam(s)) != NULL)
    -		uid = pw->pw_uid;
    -	else {
    -		for (uname = s; *s && isdigit(*s); ++s);
    -		if (!*s)
    -			uid = atoi(uname);
    -		else
    -			errx(EX_NOUSER, "unknown user id: %s", uname);
    -	}
    -	return (uid);
    -}
    -
    -mode_t
    -a_mask(char *s)
    -{
    -	int done, rv=0;
    -	char *ep;
    -
    -	done = 0;
    -	if (*s >= '0' && *s <= '7') {
    -		done = 1;
    -		rv = strtol(optarg, &ep, 8);
    -	}
    -	if (!done || rv < 0 || *ep)
    -		errx(EX_USAGE, "invalid file mode: %s", s);
    -	return (rv);
    -}
    -
    -void
    -usage(void)
    -{
    -	fprintf(stderr, "usage: mount_hpfs [-u user] [-g group] [-m mask] bdev dir\n");
    -	exit(EX_USAGE);
    -}
    -
    -void
    -load_u2wtable (struct hpfs_args *pargs, char *name)
    -{
    -	FILE *f;
    -	int i, code;
    -	char buf[128];
    -	char *fn;
    -
    -	if (*name == '/')
    -		fn = name;
    -	else {
    -		snprintf(buf, sizeof(buf), "/usr/libdata/msdosfs/%s", name);
    -		buf[127] = '\0';
    -		fn = buf;
    -	}
    -	if ((f = fopen(fn, "r")) == NULL)
    -		err(EX_NOINPUT, "%s", fn);
    -	for (i = 0; i < 128; i++) {
    -		if (fscanf(f, "%i", &code) != 1)
    -			errx(EX_DATAERR, "u2w: missing item number %d", i);
    -		/* pargs->u2w[i] = code; */
    -	}
    -	for (i = 0; i < 128; i++) {
    -		if (fscanf(f, "%i", &code) != 1)
    -			errx(EX_DATAERR, "d2u: missing item number %d", i);
    -		pargs->d2u[i] = code;
    -	}
    -	for (i = 0; i < 128; i++) {
    -		if (fscanf(f, "%i", &code) != 1)
    -			errx(EX_DATAERR, "u2d: missing item number %d", i);
    -		pargs->u2d[i] = code;
    -	}
    -	fclose(f);
    -}
    diff --git a/sys/fs/hpfs/hpfs.h b/sys/fs/hpfs/hpfs.h
    deleted file mode 100644
    index fba0c4515ae..00000000000
    --- a/sys/fs/hpfs/hpfs.h
    +++ /dev/null
    @@ -1,387 +0,0 @@
    -/*-
    - * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@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$
    - */
    -
    -/*#define HPFS_DEBUG 10*/
    -typedef u_int32_t lsn_t;	/* Logical Sector Number */
    -typedef	struct {
    -	lsn_t	lsn1;
    -	lsn_t	lsn2;
    -} rsp_t;			/* Redundant Sector Pointer */
    -typedef	struct {
    -	u_int32_t cnt;
    -	lsn_t	lsn;
    -} sptr_t;			/* Storage Pointer */
    -
    -#define	SUBLOCK	0x10
    -#define	SUSIZE	DEV_BSIZE
    -#define	SPBLOCK	0x11
    -#define	SPSIZE	DEV_BSIZE
    -#define	BMSIZE	(4 * DEV_BSIZE)
    -#define	HPFS_MAXFILENAME	255
    -
    -#define	SU_MAGIC	((u_int64_t)0xFA53E9C5F995E849)
    -struct sublock {
    -	u_int64_t	su_magic;	
    -	u_int8_t	su_hpfsver;
    -	u_int8_t	su_fnctver;
    -	u_int16_t	unused;
    -	lsn_t		su_rootfno;	/* Root Fnode */
    -	u_int32_t	su_btotal;	/* Total blocks */
    -	u_int32_t	su_badbtotal;	/* Bad Sectors total */
    -	rsp_t		su_bitmap;
    -	rsp_t		su_badbl;
    -	u_long		su_chkdskdate;
    -	u_long		su_dskoptdate;
    -	u_int32_t	su_dbbsz;	/* Sectors in DirBlock Band */
    -	lsn_t		su_dbbstart;
    -	lsn_t		su_dbbend;
    -	lsn_t		su_dbbbitmap;
    -	char		su_volname[0x20];
    -	lsn_t		su_uidt;	/* Ptr to User ID Table (8 sect) */
    -};
    -
    -#define	SP_MAGIC	((u_int64_t)0xFA5229C5F9911849)
    -#define	SP_DIRTY	0x0001
    -#define	SP_SPDBINUSE	0x0002
    -#define	SP_HFINUSE	0x0004
    -#define	SP_BADSECT	0x0008
    -#define	SP_BADBMBL	0x0010
    -#define	SP_FASTFRMT	0x0020
    -#define	SP_OLDHPFS	0x0080
    -#define	SP_IDASD	0x0100
    -#define	SP_RDASD	0x0200
    -#define	SP_DASD		0x0400
    -#define	SP_MMACTIVE	0x0800
    -#define	SP_DCEACLS	0x1000
    -#define	SP_DSADDIRTY	0x2000
    -struct spblock {
    -	u_int64_t	sp_magic;
    -	u_int16_t	sp_flag;
    -	u_int8_t	sp_mmcontf;
    -	u_int8_t	unused;
    -	lsn_t		sp_hf;		/* HotFix list */
    -	u_int32_t	sp_hfinuse;	/* HotFixes in use */
    -	u_int32_t	sp_hfavail;	/* HotFixes available */
    -	u_int32_t	sp_spdbavail;	/* Spare DirBlocks available */
    -	u_int32_t	sp_spdbmax;	/* Spare DirBlocks maximum */
    -	lsn_t		sp_cpi;
    -	u_int32_t	sp_cpinum;
    -	u_int32_t	sp_suchecksum;
    -	u_int32_t	sp_spchecksum;
    -	u_int8_t	reserved[0x3C];
    -	lsn_t		sp_spdb[0x65];
    -};
    -
    -#define	DE_SPECIAL	0x0001
    -#define	DE_ACL		0x0002
    -#define	DE_DOWN		0x0004
    -#define	DE_END		0x0008
    -#define	DE_EALIST	0x0010
    -#define	DE_EPERM	0x0020
    -#define	DE_EXPLACL	0x0040
    -#define	DE_NEEDEA	0x0080
    -#define	DE_RONLY	0x0100
    -#define	DE_HIDDEN	0x0200
    -#define	DE_SYSTEM	0x0400
    -#define	DE_VOLLABEL	0x0800
    -#define	DE_DIR		0x1000
    -#define	DE_ARCHIV	0x2000
    -#define	DE_DOWNLSN(dep) (*(lsn_t *)((caddr_t)(dep) + (dep)->de_reclen - sizeof(lsn_t)))
    -#define	DE_NEXTDE(dep)	((struct hpfsdirent *)((caddr_t)(dep) + (dep)->de_reclen))
    -typedef struct hpfsdirent {
    -	u_int16_t	de_reclen;
    -	u_int16_t	de_flag;
    -	lsn_t		de_fnode;
    -	u_long		de_mtime;
    -	u_int32_t	de_size;
    -	u_long		de_atime;
    -	u_long		de_ctime;
    -	u_int32_t	de_ealen;
    -	u_int8_t	de_flexflag;
    -	u_int8_t	de_cpid;
    -	u_int8_t	de_namelen;
    -	char		de_name[1];
    -/*	...		de_flex; */
    -/*	lsn_t		de_down; */
    -} hpfsdirent_t;
    -
    -#define	D_BSIZE	(DEV_BSIZE*4)
    -#define D_MAGIC	0x77E40AAE
    -#define	D_DIRENT(dbp)	((hpfsdirent_t *)((caddr_t)dbp + sizeof(dirblk_t)))
    -#define	D_DE(dbp, deoff) ((hpfsdirent_t *)((caddr_t)dbp + sizeof(dirblk_t) + (deoff)))
    -typedef struct dirblk {
    -	u_int32_t	d_magic;
    -	u_int32_t	d_freeoff;	/* Offset of first free byte */
    -	u_int32_t	d_chcnt;	/* Change count */
    -	lsn_t		d_parent;
    -	lsn_t		d_self;
    -} dirblk_t;
    -
    -/*
    - * Allocation Block (ALBLK)
    - */
    -#define	AB_HBOFFEO	0x01
    -#define	AB_FNPARENT	0x20
    -#define	AB_SUGGBSCH	0x40
    -#define	AB_NODES	0x80
    -#define	AB_ALLEAF(abp)	((alleaf_t *)((caddr_t)(abp) + sizeof(alblk_t)))
    -#define	AB_ALNODE(abp)	((alnode_t *)((caddr_t)(abp) + sizeof(alblk_t)))
    -#define	AB_FREEALP(abp)	((alleaf_t *)((caddr_t)(abp) + (abp)->ab_freeoff))
    -#define	AB_FREEANP(abp)	((alnode_t *)((caddr_t)(abp) + (abp)->ab_freeoff))
    -#define	AB_LASTALP(abp)	(AB_ALLEAF(abp) + (abp)->ab_busycnt - 1)
    -#define	AB_LASTANP(abp)	(AB_ALNODE(abp) + (abp)->ab_busycnt - 1)
    -#define	AB_ADDNREC(abp, sz, n)	{		\
    -	(abp)->ab_busycnt += (n);		\
    -	(abp)->ab_freecnt -= (n);		\
    -	(abp)->ab_freeoff += (n) * (sz);	\
    -}
    -#define	AB_RMNREC(abp, sz, n)		{	\
    -	(abp)->ab_busycnt -= (n);		\
    -	(abp)->ab_freecnt += (n);		\
    -	(abp)->ab_freeoff -= (n) * (sz);\
    -}
    -#define	AB_ADDAL(abp)	AB_ADDNREC(abp,sizeof(alleaf_t), 1)
    -#define	AB_ADDAN(abp)	AB_ADDNREC(abp,sizeof(alnode_t), 1)
    -#define	AB_RMAL(abp)	AB_RMNREC(abp,sizeof(alleaf_t), 1)
    -#define	AB_RMAN(abp)	AB_RMNREC(abp,sizeof(alnode_t), 1)
    -typedef struct alblk {
    -	u_int8_t	ab_flag;
    -	u_int8_t	ab_res[3];
    -	u_int8_t	ab_freecnt;
    -	u_int8_t	ab_busycnt;
    -	u_int16_t	ab_freeoff;
    -} alblk_t;
    -
    -/*
    - * FNode
    - */
    -#define	FNODESIZE	DEV_BSIZE
    -#define	FN_MAGIC	0xF7E40AAE
    -struct fnode {
    -	u_int32_t	fn_magic;
    -	u_int64_t	fn_readhist;
    -	u_int8_t	fn_namelen;
    -	char		fn_name[0xF];		/* First 15 symbols or less */
    -	lsn_t		fn_parent;
    -	sptr_t		fn_extacl;
    -	u_int16_t	fn_acllen;
    -	u_int8_t	fn_extaclflag;
    -	u_int8_t	fn_histbitcount;
    -	sptr_t		fn_extea;
    -	u_int16_t	fn_ealen;		/* Len of EAs in Fnode */
    -	u_int8_t	fn_exteaflag;		/* EAs in exteas */
    -	u_int8_t	fn_flag;
    -	alblk_t		fn_ab;
    -	u_int8_t	fn_abd[0x60];
    -	u_int32_t	fn_size;
    -	u_int32_t	fn_reqea;
    -	u_int8_t	fn_uid[0x10];
    -	u_int16_t	fn_intoff;
    -	u_int8_t	fn_1dasdthr;
    -	u_int8_t	fn_dasdthr;
    -	u_int32_t	fn_dasdlim;
    -	u_int32_t	fn_dasdusage;
    -	u_int8_t	fn_int[0x13c];
    -};
    -
    -#define	EA_NAME(eap)	((char *)(((caddr_t)(eap)) + sizeof(struct ea)))
    -struct ea {
    -	u_int8_t	ea_type;	/* 0 - plain val */
    -					/* 1 - sptr to val */
    -					/* 3 - lsn point to AlSec, cont. val */
    -	u_int8_t	ea_namelen;
    -	u_int16_t	ea_vallen;
    -	/*u_int8_t	ea_name[]; */
    -	/*u_int8_t	ea_val[]; */
    -};
    -
    -/*
    - * Allocation Block Data (ALNODE)
    - *
    - * NOTE: AlNodes are used when there are too many fragments
    - * to represent the data in the AlBlk
    - */
    -#define	AN_SET(anp,nextoff,lsn)		{	\
    -	(anp)->an_nextoff = (nextoff); 		\
    -	(anp)->an_lsn = (lsn); 			\
    -}
    -typedef struct alnode {
    -	u_int32_t	an_nextoff;	/* next node offset in blocks */
    -	lsn_t		an_lsn;		/* position of AlSec structure */
    -} alnode_t;
    -
    -/*
    - * Allocaion  Block Data (ALLEAF)
    - *
    - * NOTE: Leaves are used to point at contiguous block of data
    - * (a fragment or an "extent");
    - */
    -#define	AL_SET(alp,off,len,lsn)		{	\
    -	(alp)->al_off = (off); 			\
    -	(alp)->al_len = (len); 			\
    -	(alp)->al_lsn = (lsn); 			\
    -}
    -typedef struct alleaf {
    -	u_int32_t	al_off;		/* offset in blocks */
    -	u_int32_t	al_len;		/* len in blocks */
    -	lsn_t		al_lsn;		/* phys position */
    -} alleaf_t;
    -
    -/*
    - * Allocation Sector
    - *
    - * NOTE: AlSecs  are not  initialized before use, so they ussually
    - * look full of junk. Use the AlBlk  tto validate the data.
    - */
    -#define	AS_MAGIC	0x37E40AAE
    -typedef struct alsec {
    -	u_int32_t	as_magic;
    -	lsn_t		as_self;
    -	lsn_t		as_parent;
    -	alblk_t		as_ab;
    -	u_int8_t	as_abd[0x1E0];
    -} alsec_t;
    -
    -/*
    - * Code Page structures
    - */
    -struct cpdblk {
    -	u_int16_t	b_country;	/* Country code */
    -	u_int16_t	b_cpid;		/* CP ID */
    -	u_int16_t	b_dbcscnt;	/* Count of DBCS ranges in CP */
    -	char		b_upcase[0x80];	/* Case conversion table */
    -	u_int16_t	b_dbcsrange;	/* Start/End DBCS range pairs */
    -	
    -};
    -
    -#define	CPD_MAGIC	((u_int32_t)0x894521F7)
    -struct cpdsec {
    -	u_int32_t	d_magic;
    -	u_int16_t	d_cpcnt;	/* CP Data count */
    -	u_int16_t	d_cpfirst;	/* Index of first CP Data */
    -	u_int32_t	d_checksum[3];	/* CP Data checksumms */
    -	u_int16_t	d_offset[3];	/* Offsets of CP Data blocks */
    -	struct cpdblk	d_cpdblk[3];	/* Array of CP Data Blocks */
    -};
    -
    -struct cpiblk {
    -	u_int16_t	b_country;	/* Country code */
    -	u_int16_t	b_cpid;		/* CP ID */
    -	u_int32_t	b_checksum;
    -	lsn_t		b_cpdsec;	/* Pointer to CP Data Sector */
    -	u_int16_t	b_vcpid;	/* Volume spec. CP ID */
    -	u_int16_t	b_dbcscnt;	/* Count of DBCS ranges in CP */
    -};
    -
    -#define	CPI_MAGIC	((u_int32_t)0x494521F7)
    -struct cpisec {
    -	u_int32_t	s_magic;
    -	u_int32_t	s_cpicnt;	/* Count of CPI's in this sector */
    -	u_int32_t	s_cpifirst;	/* Index of first CPI in this sector */
    -	lsn_t		s_next;		/* Pointer to next CPI Sector */
    -	struct cpiblk	s_cpi[0x1F];	/* Array of CPI blocks */
    -};
    -
    -struct hpfsmount {
    -	struct sublock	hpm_su;
    -	struct spblock	hpm_sp;
    -	struct mount *	hpm_mp;
    -	struct vnode *	hpm_devvp;	/* XXX: lose this, it's in hpfsmount */
    -	struct g_consumer *hpm_cp;
    -	struct bufobj *hpm_bo;
    -	struct cdev *hpm_dev;
    -	uid_t          	hpm_uid;
    -	gid_t           hpm_gid;
    -	mode_t          hpm_mode;
    -
    -	lsn_t *		hpm_bmind;
    -	struct cpdblk *	hpm_cpdblk;	/* Array of CP Data Blocks */
    -	u_char		hpm_u2d[0x80];	/* Unix to DOS Table*/
    -	u_char		hpm_d2u[0x80];	/* DOS to Unix Table*/
    -
    -	u_long		hpm_bavail;	/* Blocks available */
    -	u_long		hpm_dbnum;	/* Data Band number */
    -	u_int8_t *	hpm_bitmap;
    -};
    -
    -#define	H_PARVALID	0x0002		/* parent info is valid */
    -#define	H_CHANGE	0x0004		/* node date was changed */
    -#define	H_PARCHANGE	0x0008		/* parent node date was changed */
    -#define	H_INVAL		0x0010		/* Invalid node */
    -struct hpfsnode {
    -	struct mtx h_interlock;
    -
    -	struct hpfsmount *h_hpmp;
    -	struct fnode 	h_fn;
    -	struct vnode *	h_vp;
    -	struct vnode *	h_devvp;	/* XXX: remove, hpfsmount has it */
    -	struct cdev *h_dev;
    -	lsn_t		h_no;
    -	uid_t          	h_uid;
    -	gid_t           h_gid;
    -	mode_t          h_mode;
    -	u_int32_t	h_flag;
    -
    -	/* parent dir information */
    -	u_long		h_mtime;
    -	u_long		h_atime;
    -	u_long		h_ctime;
    -	char 		h_name[HPFS_MAXFILENAME+1]; /* Used to speedup dirent */
    -	int 		h_namelen;		    /* lookup */
    -};
    -
    -/* This overlays the fid structure (see ) */
    -struct hpfid {
    -        u_int16_t hpfid_len;     /* Length of structure. */
    -        u_int16_t hpfid_pad;     /* Force 32-bit alignment. */
    -        lsn_t     hpfid_ino;     /* File number (ino). */
    -        int32_t   hpfid_gen;     /* Generation number. */
    -};
    -
    -#if defined(HPFS_DEBUG)
    -#define dprintf(a) printf a
    -#if HPFS_DEBUG > 1
    -#define ddprintf(a) printf a
    -#else
    -#define ddprintf(a)
    -#endif
    -#else
    -#define dprintf(a)
    -#define ddprintf(a)
    -#endif
    -
    -#if __FreeBSD_version >= 300000
    -MALLOC_DECLARE(M_HPFSMNT);
    -MALLOC_DECLARE(M_HPFSNO);
    -#endif
    -#define VFSTOHPFS(mp)	((struct hpfsmount *)((mp)->mnt_data))
    -#define	VTOHP(v)	((struct hpfsnode *)((v)->v_data))
    -#define	HPTOV(h)	((struct vnode *)((h)->h_vp))
    -#define	FID(f)		(*((lsn_t *)(f)->fid_data))
    -
    -extern struct vop_vector hpfs_vnodeops;
    diff --git a/sys/fs/hpfs/hpfs_alsubr.c b/sys/fs/hpfs/hpfs_alsubr.c
    deleted file mode 100644
    index 226865fd1e2..00000000000
    --- a/sys/fs/hpfs/hpfs_alsubr.c
    +++ /dev/null
    @@ -1,907 +0,0 @@
    -/*-
    - * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@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$
    - */
    -
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -
    -#include 
    -#include 
    -
    -#define	AE_DONE		0		/* Nothing to change */
    -#define	AE_SPLIT	2		/* Split was done, ranp is valid */
    -
    -int		hpfs_addextentr (struct hpfsmount *, lsn_t, alleaf_t *,
    -			         alnode_t *, u_long *);
    -int		hpfs_allocalsec (struct hpfsmount *, lsn_t, struct buf **);
    -int		hpfs_alblk2alsec (struct hpfsmount *, alblk_t *, alsec_t **,
    -				  struct buf **);
    -int		hpfs_splitalsec (struct hpfsmount *, alsec_t *, alsec_t **,
    -				 struct buf **);
    -int		hpfs_concatalsec (struct hpfsmount *, alsec_t *, alsec_t *,
    -				  alnode_t *);
    -
    -/*
    - * Map file offset to disk offset. hpfsnode have to be locked.
    - */
    -int
    -hpfs_hpbmap(hp, bn, bnp, runp)
    -	struct hpfsnode *hp;
    -	daddr_t  bn;
    -	daddr_t *bnp;
    -	int *runp;
    -{
    -	struct buf *bp;
    -	alblk_t * abp;
    -	alleaf_t *alp;
    -	alnode_t *anp;
    -	int error, i;
    -
    -	dprintf(("hpfs_hpbmap(0x%x, 0x%x): ",hp->h_no, bn));
    -
    -	bp = NULL;
    -	abp = &hp->h_fn.fn_ab;
    -	alp = (alleaf_t *)&hp->h_fn.fn_abd;
    -	anp = (alnode_t *)&hp->h_fn.fn_abd;
    -
    -dive:
    -	if (abp->ab_flag & AB_NODES) {
    -		for (i=0; iab_busycnt; i++, anp++) {
    -			dprintf(("[0x%x,0x%x] ",anp->an_nextoff,anp->an_lsn));
    -			if (bn < anp->an_nextoff) {
    -				alsec_t *asp;
    -
    -				dprintf(("< found | "));
    -
    -				if (bp)
    -					brelse(bp);
    -				error = bread(hp->h_devvp, anp->an_lsn, 
    -					      DEV_BSIZE, NOCRED, &bp);
    -				if (error) {
    -					printf("hpfs_hpbmap: bread error\n");
    -					brelse(bp);
    -					return (error);
    -				}
    -
    -				asp = (alsec_t *) bp->b_data;
    -				if (asp->as_magic != AS_MAGIC) {
    -					brelse(bp);
    -					printf("hpfs_hpbmap: "
    -					       "MAGIC DOESN'T MATCH");
    -					return (EINVAL);
    -				}
    -
    -				abp = &asp->as_ab;
    -				alp = (alleaf_t *)&asp->as_abd;
    -				anp = (alnode_t *)&asp->as_abd;
    -
    -				goto dive;
    -			}
    -		}
    -	} else {
    -		for (i=0; iab_busycnt; i++, alp++) {
    -			dprintf(("[0x%x,0x%x,0x%x] ",
    -				 alp->al_off,alp->al_len,alp->al_lsn));
    -
    -			if ((bn >= alp->al_off) &&
    -			    (!alp->al_len || (bn < alp->al_off + alp->al_len))) {
    -				dprintf(("found, "));
    -
    -				*bnp = bn - alp->al_off + alp->al_lsn;
    -
    -				dprintf((" 0x%x ", *bnp));
    -
    -				if (runp != NULL) {
    -					if (alp->al_len)
    -						*runp = alp->al_off - 1 +
    -							alp->al_len - bn;
    -					else
    -						*runp = 3; /* XXX */
    -
    -					dprintf((" 0x%x cont", *runp));
    -				}
    -
    -				if (bp)
    -					brelse(bp);
    -
    -				dprintf(("\n"));
    -				return (0);
    -			}
    -		}
    -	}
    -
    -	dprintf(("END, notfound\n"));
    -	if (bp)
    -		brelse(bp);
    -
    -	dprintf(("hpfs_hpbmap: offset too big\n"));
    -
    -	return (EFBIG);
    -}
    -
    -/*
    - * Find place and preinitialize AlSec structure
    - * AlBlk is initialized to contain AlLeafs.
    - */
    -int
    -hpfs_allocalsec (
    -	struct hpfsmount *hpmp,
    -	lsn_t parlsn,
    -	struct buf **bpp)
    -{
    -	alsec_t * asp;
    -	struct buf * bp;
    -	lsn_t lsn;
    -	int error;
    -
    -	*bpp = NULL;
    -
    -	error = hpfs_bmfblookup(hpmp, &lsn);
    -	if (error) {
    -		printf("hpfs_allocalsec: CAN'T ALLOC SPACE FOR AlSec\n");
    -		return (error);
    -	}
    -
    -	error = hpfs_bmmarkbusy(hpmp, lsn, 1);
    -	if (error) 
    -		return (error);
    -
    -	bp = getblk(hpmp->hpm_devvp, lsn, DEV_BSIZE, 0, 0, 0);
    -	clrbuf(bp);
    -
    -	/* Fill AlSec info */
    -	asp = (alsec_t *) bp->b_data;
    -	asp->as_magic = AS_MAGIC;
    -	asp->as_self = lsn;
    -	asp->as_parent = parlsn;
    -
    -	/* Fill AlBlk */
    -	asp->as_ab.ab_flag = 0;
    -	asp->as_ab.ab_busycnt = 0;
    -	asp->as_ab.ab_freecnt = 0x28;
    -	asp->as_ab.ab_freeoff = sizeof(alblk_t);
    -
    -	*bpp = bp;
    -
    -	return (0);
    -}
    -
    -/*
    - * Split AlSec structure into new allocated:
    - * allocate new AlSec; then move second half of asp's entries in
    - * into it; set proper flags.
    - *
    - * IF AlSec CONTAINS AlNodes, THEN YOU ALMOST EVERYTIME HAVE TO
    - * FIX LAST AlNode in OLD AlSec (NEXTOFF TO BE 0xFFFFFFFF).
    - * TOGETHER WITH FIXING ALL CHILDREN'S AlSecs (THEY HAVE GOT NEW PARENT).
    - */
    -int
    -hpfs_splitalsec (
    -	struct hpfsmount *hpmp,
    -	alsec_t *asp,
    -	alsec_t **naspp,
    -	struct buf **nbpp)
    -{
    -	alsec_t *nasp;
    -	struct buf *nbp;
    -	alblk_t *abp;
    -	alblk_t *nabp;
    -	int error, n1, n2, sz;
    -
    -	error = hpfs_allocalsec(hpmp, asp->as_parent, &nbp);
    -	if (error)
    -		return (error);
    -
    -	nasp = (alsec_t *)nbp->b_data;
    -	nabp = &nasp->as_ab;
    -	abp = &asp->as_ab;
    -
    -	n1 = (abp->ab_busycnt + 1) / 2;
    -	n2 = (abp->ab_busycnt - n1);
    -	sz = (abp->ab_flag & AB_NODES) ? sizeof(alnode_t) : sizeof(alleaf_t);
    -
    -	bcopy((caddr_t)abp + sizeof(alblk_t) + n1 * sz, 
    -	      (caddr_t)nabp + sizeof(alblk_t), n2 * sz);
    -
    -	nabp->ab_flag = abp->ab_flag;
    -	nabp->ab_busycnt = n2;
    -	nabp->ab_freecnt = (0x1e0 / sz - n2);
    -	nabp->ab_freeoff += n2 * sz;
    -
    -	abp->ab_busycnt -= n1;
    -	abp->ab_freecnt += n1;
    -	abp->ab_freeoff -= n1 * sz;
    -
    -	*naspp = nasp;
    -	*nbpp = nbp;
    -
    -	return (0);
    -}
    -
    -/*
    - * Try to concatenate two AlSec's
    - *
    - * Moves all entries from AlSec corresponding (as1p, aanp[1]) into 
    - * corresponding aanp[0] one. If not enought space, then return ENOSPC.
    - *
    - * WARNING! YOU HAVE TO FIX aanp VALUES YOURSELF LATER:
    - * aanp[0].an_nextoff = aanp[1].an_nextoff;
    - */
    -int
    -hpfs_concatalsec (
    -	struct hpfsmount *hpmp,
    -	alsec_t *as0p,
    -	alsec_t *as1p,
    -	alnode_t *aanp)
    -{
    -	alblk_t *ab0p;
    -	alblk_t *ab1p;
    -	int sz;
    -	
    -	dprintf(("hpfs_concatalsec: AlSecs at 0x%x and 0x%x \n",
    -		as0p->as_self,as1p->as_self));
    -
    -	ab0p = &as0p->as_ab;
    -	ab1p = &as1p->as_ab;
    -	sz = (ab0p->ab_flag & AB_NODES) ? sizeof(alnode_t) : sizeof(alleaf_t);
    -
    -	if (ab0p->ab_freecnt > ab1p->ab_busycnt) {
    -		/*
    -		 * Concatenate AlSecs
    -		 */
    -		if (ab0p->ab_flag & AB_NODES) 
    -			AB_LASTANP(ab0p)->an_nextoff = aanp[0].an_nextoff;
    -
    -		bcopy (AB_ALNODE(ab1p), AB_FREEANP(ab0p),
    -			 ab1p->ab_busycnt * sz);
    -
    -		AB_ADDNREC(ab0p, sz, ab1p->ab_busycnt);
    -
    -		return (0);
    -	} else {
    -		/* Not enought space to concatenate */
    -		return (ENOSPC);
    -	}
    -}
    -
    -/*
    - * Transform AlBlk structure into new allocated 
    - * AlSec.
    - *
    - * DOESN'T SET AlSec'S PARENT LSN.
    - */
    -int
    -hpfs_alblk2alsec (
    -	struct hpfsmount *hpmp,
    -	alblk_t *abp,
    -	alsec_t **naspp,
    -	struct buf **nbpp)
    -{
    -	alsec_t *nasp;
    -	alblk_t *nabp;
    -	struct buf *nbp;
    -	int error, sz;
    -
    -	error = hpfs_allocalsec(hpmp, 0, &nbp);
    -	if (error)
    -		return (error);
    -
    -	nasp = (alsec_t *)nbp->b_data;
    -	nabp = &nasp->as_ab;
    -
    -	sz = (abp->ab_flag & AB_NODES) ? sizeof(alnode_t) : sizeof(alleaf_t);
    -
    -	bcopy (abp, nabp, sizeof(alblk_t) + sz * abp->ab_busycnt);
    -
    -	nabp->ab_freecnt = 0x1e0 / sz - nabp->ab_busycnt;
    -
    -	*naspp = nasp;
    -	*nbpp = nbp;
    -
    -	return (0);
    -}
    -
    -/*
    - * Allocate len blocks and concatenate them to file.
    - * If we hadn't found contignous run of len blocks, concatenate
    - * as much as we can, and return.
    - * 
    - */
    -int
    -hpfs_addextent (
    -	struct hpfsmount *hpmp,
    -	struct hpfsnode *hp,
    -	u_long len)
    -{
    -	alblk_t *rabp;
    -	alnode_t ranp[2];
    -	alleaf_t al;
    -	int error;
    -	u_long pf;
    -
    -	/*
    -	 * We don't know for now start lsn of block
    -	 */
    -	al.al_lsn = ~0;
    -	al.al_len = len;
    -	al.al_off = (hp->h_fn.fn_size + DEV_BSIZE - 1) >> DEV_BSHIFT;
    -
    -	rabp = &hp->h_fn.fn_ab;
    -
    -	/* Init AlBlk if this is first extent */
    -	if (al.al_off == 0) {
    -		lsn_t nlsn;
    -		u_long nlen;
    -
    -		dprintf(("hpfs_addextent: init AlBlk in root\n"));
    -
    -		rabp->ab_busycnt = 0;
    -		rabp->ab_freecnt = 0x8;
    -		rabp->ab_freeoff = sizeof(alblk_t);
    -		rabp->ab_flag = 0;
    -
    -		error = hpfs_bmlookup (hpmp, 0, hp->h_no + 1, al.al_len, &nlsn, &nlen);
    -		if (error)
    -			return (error);
    -
    -		error = hpfs_bmmarkbusy(hpmp, nlsn, nlen);
    -		if (error)
    -			return (error);
    -						
    -		dprintf(("hpfs_addextent: new: 0x%x 0x%lx, ", nlsn, nlen));
    -
    -		AL_SET(AB_FREEALP(rabp), al.al_off, nlen, nlsn);
    -		AB_ADDAL(rabp);
    -
    -		al.al_off += nlen;
    -		al.al_len -= nlen;
    -	}
    -
    -retry:
    -	dprintf(("hpfs_addextent: AlBlk: [0x%x, 0x%x, 0x%x] need: 0x%x\n",
    -		 rabp->ab_freecnt, rabp->ab_busycnt, rabp->ab_flag, al.al_len));
    -
    -	while ((al.al_len) && (rabp->ab_freecnt > 0)) {
    -		if (rabp->ab_flag & AB_NODES) {
    -			alnode_t *anp;
    -			/*
    -			 * This is level containing AlNodes, so try to 
    -			 * insert recursively into last entry.
    -			 */
    -			anp = AB_LASTANP(rabp);
    -			dprintf(("hpfs_addextent: AlNode: [0x%x,0x%x] \n",
    -				 anp->an_nextoff,anp->an_lsn));
    -
    -			/*
    -			 * Try to insert...
    -			 */
    -			error = hpfs_addextentr (hpmp, anp->an_lsn, &al, ranp, &pf);
    -			if (error) {
    -				printf("hpfs_addextent: FAILED %d\n",error);
    -				return (error);
    -			}
    -
    -			switch (pf) {
    -			case AE_SPLIT:
    -				dprintf(("hpfs_addextent: successful (split)\n"));
    -				/*
    -				 * Then hpfs_addextentr has split tree below, now
    -				 * we need to fix this level. Particulary:
    -				 * fix last AlNode and add another one.
    -				 */
    -
    -				bcopy(ranp, AB_LASTANP(rabp), sizeof(alnode_t) * 2);
    -				AB_ADDAN(rabp);
    -				break;
    -
    -			default:
    -			case AE_DONE:
    -				dprintf(("hpfs_addextent: successful\n"));
    -				break;
    -			}
    -		} else {
    -			alleaf_t *alp;
    -
    -			alp = AB_LASTALP(rabp);
    -			dprintf(("hpfs_addextent: AlLeaf: [0x%x,0x%x,0x%x] \n",
    -				 alp->al_off,alp->al_len,alp->al_lsn));
    -
    -			/* Check if we trying to add in right place */
    -			if (alp->al_off + alp->al_len == al.al_off) {
    -				lsn_t nlsn;
    -				u_long nlen;
    -
    -				/*
    -				 * Search bitmap for block begining from
    -				 * alp->al_lsn + alp->al_len and long of ralp->al_len
    -				 */
    -				error = hpfs_bmlookup (hpmp, 0,
    -					alp->al_lsn + alp->al_len, al.al_len, &nlsn, &nlen);
    -				if (error)
    -					return (error);
    -
    -				error = hpfs_bmmarkbusy(hpmp, nlsn, nlen);
    -				if (error)
    -					return (error);
    -						
    -				dprintf(("hpfs_addextent: new: 0x%x 0x%lx, ", nlsn, nlen));
    -
    -				if (alp->al_lsn + alp->al_len == nlsn) {
    -					dprintf(("extended existed leaf\n"));
    -
    -					alp->al_len += nlen;
    -				} else {
    -					dprintf(("created new leaf\n"));
    -					AL_SET(AB_FREEALP(rabp), al.al_off, nlen, nlsn);
    -					AB_ADDAL(rabp);
    -				}
    -				al.al_off += nlen;
    -				al.al_len -= nlen;
    -			} else {
    -				printf("hpfs_addextent: INTERNAL INCONSISTENCE\n");
    -				return (EINVAL);
    -			}
    -		}
    -	}
    -
    -	/*
    -	 * Move AlBlk contain to new AlSec (it will fit more
    -	 * entries) if overflowed (no more free entries).
    -	 */
    -	if (rabp->ab_freecnt <= 0) {
    -		struct buf *nbp;
    -		alsec_t * nrasp;
    -
    -		dprintf(("hpfs_addextent: overflow, convt\n"));
    -
    -		/*
    -		 * Convert AlBlk to new AlSec, it will set
    -		 * AB_FNPARENT also.
    -		 */
    -		rabp->ab_flag |= AB_FNPARENT;
    -		error = hpfs_alblk2alsec (hpmp, rabp, &nrasp, &nbp);
    -		if (error) {
    -			printf("hpfs_addextent: CAN'T CONVT\n");
    -			return (error);
    -		}
    -		nrasp->as_parent = hp->h_no;
    -
    -		/*
    -		 * Scan all childrens (if exist), set new parent and
    -		 * clean their AB_FNPARENT flag.
    -		 */
    -		if (rabp->ab_flag & AB_NODES) {
    -			int i;
    -			alsec_t * asp;
    -			alnode_t * anp;
    -			struct buf * bp;
    -
    -			anp = AB_ALNODE(rabp);
    -			for (i=0; iab_busycnt; i++) {
    -				error = hpfs_breadalsec(hpmp, anp->an_lsn, &bp);
    -				if (error)
    -					return (error);
    -
    -				asp = (alsec_t *)bp->b_data;
    -				asp->as_ab.ab_flag &= ~AB_FNPARENT;
    -				asp->as_parent = nrasp->as_self;
    -
    -				bdwrite(bp);
    -				anp ++;
    -			}
    -		}
    -
    -		/* Convert AlBlk to contain AlNodes */
    -		rabp->ab_flag = AB_NODES;
    -		rabp->ab_busycnt = 0;
    -		rabp->ab_freecnt = 0xC;
    -		rabp->ab_freeoff = sizeof(alblk_t);
    -
    -		/* Add AlNode for new allocated AlSec */
    -		AN_SET(AB_FREEANP(rabp), ~0, nrasp->as_self);
    -		AB_ADDAN(rabp);
    -
    -		bdwrite(nbp);
    -	}
    -
    -	if (al.al_len) {
    -		dprintf(("hpfs_addextent: root retry\n"));
    -		goto retry;
    -	}
    -
    -	return (0);
    -}
    -
    -/*
    - * Descent down to the end of tree, then search for
    - * ralp->len contignous run begining from last run's end and
    - * concatenate new block! If we can't find one, then...
    - */
    -int
    -hpfs_addextentr (
    -	struct hpfsmount *hpmp,		/* Mix info */
    -	lsn_t rlsn,			/* LSN containing AlSec */
    -	alleaf_t *ralp,			/* AlLeaf to insert */
    -	alnode_t *ranp,			/* New AlNodes' values */
    -	u_long *resp)			/* Mix returning info */
    -{
    -	struct buf *rbp;
    -	alsec_t *rasp;
    -	alblk_t *rabp;
    -	alleaf_t *alp;
    -	alnode_t *anp;
    -	int error;
    -	u_long pf;
    -	u_long wb;
    -
    -	*resp = 0;
    -
    -	dprintf(("hpfs_addextentr: AlSec at 0x%x\n", rlsn));
    -
    -	error = hpfs_breadalsec(hpmp, rlsn, &rbp);
    -	if (error)
    -		return (error);
    -
    -	rasp = (alsec_t *)rbp->b_data;
    -	rabp = &rasp->as_ab;
    -	wb = 0;
    -
    -	dprintf(("hpfs_addextentr: AlBlk: [0x%x, 0x%x, 0x%x]\n",
    -		 rabp->ab_freecnt, rabp->ab_busycnt, rabp->ab_flag));
    -
    -	while ((ralp->al_len) && (rabp->ab_freecnt > 0)) {
    -		if (rabp->ab_flag & AB_NODES) {
    -			/*
    -			 * This is level containing AlNodes, so try to 
    -			 * insert recursively into last entry.
    -			 */
    -			anp = AB_LASTANP(rabp);
    -			dprintf(("hpfs_addextentr: AlNode: [0x%x,0x%x] \n",
    -				 anp->an_nextoff,anp->an_lsn));
    -
    -			/*
    -			 * Try to insert...
    -			 */
    -			error = hpfs_addextentr (hpmp, anp->an_lsn, ralp, ranp, &pf);
    -			if (error) {
    -				printf("hpfs_addextentr: FAILED %d\n",error);
    -				goto fail;
    -			}
    -
    -			switch (pf) {
    -			case AE_SPLIT:
    -				dprintf(("hpfs_addextentr: successful (split)\n"));
    -				/*
    -				 * Then hpfs_addextentr has split tree below, now
    -				 * we need to fix this level. Particulary:
    -				 * fix last AlNode and add another one.
    -				 */
    -				bcopy(ranp, AB_LASTANP(rabp), sizeof(alnode_t) * 2);
    -				AB_ADDAN(rabp);
    -				wb = 1;
    -				break;
    -
    -			default:
    -			case AE_DONE:
    -				dprintf(("hpfs_addextentr: successful\n"));
    -				break;		
    -			}
    -		} else {
    -			alp = AB_LASTALP(rabp);
    -			dprintf(("hpfs_addextentr: AlLeaf: [0x%x,0x%x,0x%x] \n",
    -				 alp->al_off,alp->al_len,alp->al_lsn));
    -
    -			/* Check if we trying to add in right place */
    -			if (alp->al_off + alp->al_len == ralp->al_off) {
    -				lsn_t nlsn;
    -				u_long nlen;
    -				/*
    -				 * Search bitmap for block begining from
    -				 * alp->al_lsn + alp->al_len and long of ralp->al_len
    -				 */
    -				error = hpfs_bmlookup (hpmp, 0,
    -					alp->al_lsn + alp->al_len, ralp->al_len, &nlsn, &nlen);
    -				if (error)
    -					goto fail;
    -
    -				error = hpfs_bmmarkbusy(hpmp, nlsn, nlen);
    -				if (error)
    -					goto fail;
    -						
    -				dprintf(("hpfs_addextentr: new: 0x%x 0x%lx, ", nlsn, nlen));
    -
    -				/* 
    -				 * If ending of existed entry fits the
    -				 * begining of the extent being added,
    -				 * then we add concatenate two extents.
    -				 */
    -				if (alp->al_lsn + alp->al_len == nlsn) {
    -					dprintf(("concat\n"));
    -					alp->al_len += nlen;
    -				} else {
    -					dprintf(("created new leaf\n"));
    -					AL_SET(AB_FREEALP(rabp), ralp->al_off, nlen, nlsn);
    -					AB_ADDAL(rabp);
    -				}
    -
    -				ralp->al_len -= nlen;
    -				ralp->al_off += nlen;
    -			} else {
    -				printf("hpfs_addextentr: INTERNAL INCONSISTENCE\n");
    -				error = (EINVAL);
    -				goto fail;
    -			}
    -		}
    -	}
    -
    -	/*
    -	 * Split AlBlk if overflowed.
    -	 */
    -	if (rabp->ab_freecnt <= 0) {
    -		struct buf *nbp;
    -		alsec_t * nrasp;
    -
    -		dprintf(("hpfs_addextentr: overflow, split\n"));
    -
    -		error = hpfs_splitalsec (hpmp, rasp, &nrasp, &nbp);
    -		if (error) {
    -			printf("hpfs_addextent: CAN'T SPLIT\n");
    -			goto fail;
    -		}
    -
    -		if (rabp->ab_flag & AB_NODES) {
    -			int i;
    -			alsec_t * asp;
    -			alnode_t * anp;
    -			struct buf * bp;
    -
    -			ranp[0].an_nextoff = 
    -				AB_LASTANP(&rasp->as_ab)->an_nextoff;
    -
    -			/* We need to set left subtree's last entry
    -			 * offset to 0xFFFFFFFF for OS/2 to be able
    -			 * to read our files. It treats absence  of
    -			 * 0xFFFFFFFF as error.
    -			 */
    -			AB_LASTANP(&rasp->as_ab)->an_nextoff = ~0;
    -
    -			/* We need to fix new allocated AlSec's
    -			 * children, becouse their parent has changed.
    -			 */
    -			anp = AB_ALNODE(&nrasp->as_ab);
    -			for (i=0; ias_ab.ab_busycnt; i++) {
    -				error = hpfs_breadalsec(hpmp, anp->an_lsn, &bp);
    -				if (error) {
    -					brelse(nbp);
    -					goto fail;
    -				}
    -
    -				asp = (alsec_t *)bp->b_data;
    -				asp->as_parent = nrasp->as_self;
    -
    -				bdwrite(bp);
    -				anp ++;
    -			}
    -		} else {
    -			ranp[0].an_nextoff = 
    -				AB_ALLEAF(&nrasp->as_ab)->al_off;
    -		}
    -
    -		ranp[0].an_lsn = rasp->as_self;
    -		ranp[1].an_nextoff = ~0;
    -		ranp[1].an_lsn = nrasp->as_self;
    -
    -		bdwrite(nbp);
    -
    -		*resp = AE_SPLIT;
    -		wb = 1;
    -	}
    -
    -	if (wb)
    -		bdwrite (rbp);
    -	else
    -		brelse(rbp);
    -
    -	return (0);
    -
    -fail:
    -	brelse(rbp);
    -
    -	return (error);
    -}
    -
    -/*
    - * Recursive routine walking down the b-tree and deallocating all
    - * extents above bn. Returns *resp != 0 if alblk was totally 
    - * deallocated and may be freed. Tries to keep b-tree.
    - *
    - * (XXXX) NOTE! THIS ROUTINE WILL NEVER DECREMENT DEPTH OF
    - * THE TREE.
    - */
    -int
    -hpfs_truncatealblk (
    -	struct hpfsmount *hpmp,
    -	alblk_t *abp,
    -	lsn_t bn,
    -	int *resp)
    -{
    -	int error;
    -	alleaf_t *alp;
    -	alnode_t *anp;
    -	alsec_t *asp;
    -	struct buf *bp;
    -
    -	dprintf(("hpfs_truncatealblk: AlBlk: [0x%x,0x%x, 0x%x]\n",
    -		 abp->ab_freecnt, abp->ab_busycnt, abp->ab_flag));
    -
    -	if (abp->ab_flag & AB_NODES) {
    -		/*
    -		 * Scan array of AlNodes backward,
    -		 * diving in recursion if needed
    -		 */
    -		anp = AB_LASTANP(abp);
    -
    -		while (abp->ab_busycnt && (bn <= anp->an_nextoff)) {
    -			dprintf(("hpfs_truncatealblk: AlNode: [0x%x,0x%x] \n",
    -				anp->an_nextoff,anp->an_lsn));
    -
    -			error = hpfs_breadalsec(hpmp, anp->an_lsn, &bp);
    -			if (error)
    -				return (error);
    -
    -			asp = (alsec_t *)bp->b_data;
    -
    -			error = hpfs_truncatealblk (hpmp,
    -					&asp->as_ab, bn, resp);
    -			if (error) {
    -				brelse(bp);
    -				return (error);
    -			}
    -
    -			if (*resp) {
    -				brelse (bp);
    -
    -				error = hpfs_bmmarkfree(hpmp,
    -						anp->an_lsn, 1);
    -				if (error)
    -					return (error);
    -
    -				AB_RMAN(abp);
    -				anp --;
    -			} else {
    -				/* 
    -				 * We have deallocated some entries, some space
    -				 * migth been freed, then try to concat two 
    -				 * last AlSec.
    -				 */
    -				anp->an_nextoff = ~0;
    -				if (abp->ab_busycnt >= 2) {
    -					alsec_t *as0p;
    -					struct buf *b0p;
    -
    -					error = hpfs_breadalsec(hpmp,
    -							(anp-1)->an_lsn, &b0p);
    -					if (error)
    -						return (error);
    -
    -					as0p = (alsec_t *)b0p->b_data;
    -					error = hpfs_concatalsec(hpmp,
    -							as0p, asp, anp - 1);
    -					if (error == ENOSPC) {
    -						/* Not enought space */
    -						brelse (b0p);
    -						bdwrite (bp);
    -					} else if (error == 0) {
    -						/* All OK  */
    -						(anp-1)->an_nextoff = anp->an_nextoff;
    -
    -						bdwrite (b0p);
    -						brelse (bp);
    -
    -						error = hpfs_bmmarkfree(hpmp,
    -								anp->an_lsn, 1);
    -						if (error)
    -							return (error);
    -
    -						AB_RMAN(abp);
    -					} else {
    -						/* True error */
    -						brelse (b0p);
    -						brelse (bp);
    -						return (error);
    -					}
    -				} else {
    -					/* Nowhere to concatenate */
    -					bdwrite (bp);
    -				}
    -
    -				/* There can not be any more entries
    -				 * over greater bn, becouse last AlSec
    -				 * wasn't freed totally. So go out.
    -				 */
    -				break;
    -			}
    -		}
    -
    -		if (abp->ab_busycnt == 0)
    -			*resp = 1;
    -		else
    -			*resp = 0;
    -	} else {
    -		/*
    -		 * Scan array of AlLeafs backward,
    -		 * free all above bn.
    -		 */
    -		alp = AB_LASTALP(abp);
    -
    -		while (abp->ab_busycnt && (bn < alp->al_off + alp->al_len)){
    -			dprintf(("hpfs_truncatealblk: AlLeaf: [0x%x,0x%x,0x%x] \n",
    -				 alp->al_off,alp->al_len,alp->al_lsn));
    -
    -			if (bn <= alp->al_off) {
    -				error = hpfs_bmmarkfree(hpmp, alp->al_lsn,
    -						alp->al_len);
    -				if (error)
    -					return (error);
    -
    -				AB_RMAL(abp);
    -				alp --;
    -			} else if ((bn > alp->al_off) &&
    -			    	   (bn < alp->al_off + alp->al_len)){
    -				error = hpfs_bmmarkfree(hpmp,
    -						alp->al_lsn + bn - alp->al_off,
    -						alp->al_len - bn + alp->al_off);
    -				if (error)
    -					return (error);
    -
    -				alp->al_len = bn - alp->al_off;
    -
    -				break;
    -			} else
    -				break;
    -		}
    -	}
    -
    -	/* Signal parent deallocation, if need */
    -	if (abp->ab_busycnt == 0) 
    -		*resp = 1;
    -	else
    -		*resp = 0;
    -
    -	return (0);
    -}
    diff --git a/sys/fs/hpfs/hpfs_ioctl.h b/sys/fs/hpfs/hpfs_ioctl.h
    deleted file mode 100644
    index 7f60729b1ba..00000000000
    --- a/sys/fs/hpfs/hpfs_ioctl.h
    +++ /dev/null
    @@ -1,43 +0,0 @@
    -/*-
    - * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@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 _HPFS_IOCTL_H_
    -#define _HPFS_IOCTL_H_
    -#include 
    -
    -struct hpfs_rdea {
    -	u_long	ea_no;
    -	u_long	ea_sz;
    -	void *	ea_data;
    -};
    -
    -#define	HPFSIOCGEANUM	_IOR('H', 0, u_long)	/* Get EA number */
    -#define	HPFSIOCGEASZ	_IOWR('H', 1, u_long)	/* Get EA size */
    -#define	HPFSIOCRDEA	_IOWR('H', 2, struct hpfs_rdea)	/* Read EA */
    -
    -#endif
    diff --git a/sys/fs/hpfs/hpfs_lookup.c b/sys/fs/hpfs/hpfs_lookup.c
    deleted file mode 100644
    index 88542cb2160..00000000000
    --- a/sys/fs/hpfs/hpfs_lookup.c
    +++ /dev/null
    @@ -1,213 +0,0 @@
    -/*-
    - * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@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$
    - */
    -
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -
    -#include 
    -#include 
    -#include 
    -
    -int	hpfs_removedirent (struct hpfsmount *, lsn_t, char *, int, int *);
    -
    -/*
    - * This routine traverse the b+ tree representing directory
    - * looking for file named 'name'. Returns buf struct and hpfsdirent
    - * pointer. Calling routine is supposed to brelse buffer.
    - * name is supposed in Unix encodeing.
    - */
    -int
    -hpfs_genlookupbyname (
    -	struct hpfsnode *dhp,
    -	char *name,
    -	int namelen,
    -	struct buf **bpp,
    -	struct hpfsdirent **depp)
    -{
    -	struct hpfsmount *hpmp = dhp->h_hpmp;
    -	struct buf *bp;
    -	struct dirblk *dp;
    -	struct hpfsdirent *dep;
    -	lsn_t lsn;
    -	int error, res;
    -
    -	dprintf(("hpfs_genlookupbyname(0x%x, %s (%d)): \n", 
    -		dhp->h_no, name, namelen));
    -
    -	lsn = ((alleaf_t *)dhp->h_fn.fn_abd)->al_lsn;
    -dive:
    -	error = hpfs_breaddirblk (hpmp, lsn, &bp);
    -	if (error)
    -		return (error);
    -
    -	dp = (struct dirblk *) bp->b_data;
    -	dep = D_DIRENT(dp);
    -
    -	while(!(dep->de_flag & DE_END)) {
    -		dprintf(("no: 0x%x, size: %d, name: %2d:%.*s, flag: 0x%x\n",
    -			dep->de_fnode, dep->de_size, dep->de_namelen,
    -			dep->de_namelen, dep->de_name, dep->de_flag));
    -
    -		res = hpfs_cmpfname(hpmp, name, namelen,
    -				dep->de_name, dep->de_namelen, dep->de_cpid);
    -		if (res == 0) {
    -			*bpp = bp;
    -			*depp = dep;
    -			return (0);
    -		} else if (res < 0)
    -			break;
    -
    -		dep = (hpfsdirent_t *)(((caddr_t)dep) + dep->de_reclen);
    -	}
    -
    -	if (dep->de_flag & DE_DOWN) {
    -		lsn = DE_DOWNLSN(dep);
    -		brelse(bp);
    -		goto dive;
    -	}
    -
    -	brelse(bp);
    -
    -	return (ENOENT);
    -}
    -
    -int
    -hpfs_makefnode (
    -	struct vnode * dvp,
    -	struct vnode ** vpp,
    -	struct componentname *cnp,
    -	struct vattr *vap)
    -{
    -#ifdef HPFS_DEBUG
    -	register struct hpfsnode *dhp = VTOHP(dvp);
    -	dprintf(("hpfs_makefnode(0x%x, %s, %ld): \n",
    -		dhp->h_no, cnp->cn_nameptr, cnp->cn_namelen));
    -#endif
    -
    -	return (EOPNOTSUPP);
    -}
    -
    -int
    -hpfs_removedirent (
    -	struct hpfsmount *hpmp,
    -	lsn_t lsn,
    -	char *name,
    -	int namelen,
    -	int *retp)
    -{
    -#if 0
    -	struct buf *bp;
    -	dirblk_t *dbp;
    -	struct hpfsdirent *dep;
    -	int deoff;
    -	int error, ret;
    -
    -	dprintf(("hpfs_removedirent(0x%x, %.*s, %d): \n",
    -		 lsn, namelen, name, namelen));
    -
    -	error = hpfs_breaddirblk (hpmp, lsn, &bp);
    -	if (error)
    -		return (error);
    -
    -	dbp = (dirblk_t *) bp->b_data;
    -	deoff = sizeof(dirblk_t);
    -	dep = DB_DIRENT(dbp);
    -
    -	while(!(dep->de_flag & DE_END)) {
    -		dprintf(("no: 0x%x, size: %d, name: %2d:%.*s, flag: 0x%x\n",
    -			dep->de_fnode, dep->de_size, dep->de_namelen,
    -			dep->de_namelen, dep->de_name, dep->de_flag));
    -
    -		res = hpfs_cmpfname(hpmp, name, namelen,
    -				dep->de_name, dep->de_namelen, dep->de_cpid);
    -		if (res == 0) {
    -			if (dep->de_flag & DE_DOWN) {
    -				/*XXXXXX*/
    -			} else {
    -				/* XXX we can copy less */
    -				bcopy (DE_NEXTDE(dep), dep, DB_BSIZE - deoff - dep->de_reclen);
    -				dbp->d_freeoff -= dep->de_reclen;
    -				*retp = 0;
    -			}
    -			bdwrite (bp);
    -			return (0);
    -		} else if (res < 0)
    -			break;
    -
    -		deoff += dep->de_reclen;
    -		dep = DB_NEXTDE(dep);
    -	}
    -
    -	if (dep->de_flag & DE_DOWN) {
    -		error = hpfs_removede (hpmp, DE_DOWNLSN(dep), name, namelen, &ret);
    -		if (error) {
    -			brelse (bp);
    -			return (error);
    -		}
    -		if (ret == 0) {
    -			if (deoff > sizeof (dirblk_t)) {
    -			} else if (deoff + dep->de_reclen < dbp->db_freeoff) {
    -			}
    -		}
    -	} else {
    -		error = ENOENT;
    -	}
    -
    -	brelse (bp);
    -	return (error);
    -#endif
    -	return (EOPNOTSUPP);
    -}
    -
    -int
    -hpfs_removefnode (
    -	struct vnode * dvp,
    -	struct vnode * vp,
    -	struct componentname *cnp)
    -{
    -#ifdef HPFS_DEBUG
    -	register struct hpfsnode *dhp = VTOHP(dvp);
    -	register struct hpfsnode *hp = VTOHP(vp);
    -	dprintf(("hpfs_removefnode(0x%x, 0x%x, %s, %ld): \n",
    -		dhp->h_no, hp->h_no, cnp->cn_nameptr, cnp->cn_namelen));
    -#endif
    -
    -
    -	return (EOPNOTSUPP);
    -}
    diff --git a/sys/fs/hpfs/hpfs_subr.c b/sys/fs/hpfs/hpfs_subr.c
    deleted file mode 100644
    index c7fe94f72a4..00000000000
    --- a/sys/fs/hpfs/hpfs_subr.c
    +++ /dev/null
    @@ -1,869 +0,0 @@
    -/*-
    - * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@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$
    - */
    -
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -
    -#include 
    -#include 
    -#include 
    -
    -u_long
    -hpfs_checksum(
    -	u_int8_t *object,
    -	int size)
    -{
    -	register int i;
    -	u_long csum=0L;
    -	for (i=0; i < size; i++) {
    -		csum += (u_long) *object++;
    -		csum = (csum << 7) + (csum >> (25));
    -	}
    -	return (csum);
    -}
    -
    -void
    -hpfs_bmdeinit(
    -	struct hpfsmount *hpmp)
    -{
    -	struct buf *bp;
    -	int i;
    -
    -	dprintf(("hpmp_bmdeinit: "));
    -
    -	if (!(hpmp->hpm_mp->mnt_flag & MNT_RDONLY)) {
    -		/*
    -		 * Write down BitMap.
    -		 */
    -		for (i=0; ihpm_dbnum; i++) {
    -			dprintf(("[%d: 0x%x] ", i, hpmp->hpm_bmind[i]));
    -
    -			bp = getblk(hpmp->hpm_devvp, hpmp->hpm_bmind[i],
    -				    BMSIZE, 0, 0, 0);
    -			clrbuf(bp);
    -
    -			bcopy(hpmp->hpm_bitmap + BMSIZE * i, bp->b_data,
    -			      BMSIZE);
    -
    -			bwrite(bp);
    -		}
    -	}
    -
    -	free(hpmp->hpm_bitmap,M_HPFSMNT);
    -	free(hpmp->hpm_bmind,M_HPFSMNT);
    -
    -	dprintf(("\n"));
    -}
    -
    -/*
    - * Initialize BitMap management, includes calculation of
    - * available blocks number.
    - */
    -int
    -hpfs_bminit(
    -	struct hpfsmount *hpmp)
    -{
    -	struct buf *bp;
    -	int error, i, k;
    -	u_long dbavail;
    -
    -	dprintf(("hpfs_bminit: "));
    -
    -	hpmp->hpm_dbnum = (hpmp->hpm_su.su_btotal + 0x3FFF) / 0x4000;
    -
    -	dprintf(("0x%lx data bands, ", hpmp->hpm_dbnum));
    -
    -	hpmp->hpm_bmind = malloc(hpmp->hpm_dbnum * sizeof(lsn_t),
    -		M_HPFSMNT, M_WAITOK);
    -
    -	hpmp->hpm_bitmap = malloc(hpmp->hpm_dbnum * BMSIZE,
    -		M_HPFSMNT, M_WAITOK);
    -
    -	error = bread(hpmp->hpm_devvp, hpmp->hpm_su.su_bitmap.lsn1,
    -		((hpmp->hpm_dbnum + 0x7F) & ~(0x7F)) << 2, NOCRED, &bp);
    -	if (error) {
    -		brelse(bp);
    -		free(hpmp->hpm_bitmap, M_HPFSMNT);
    -		free(hpmp->hpm_bmind, M_HPFSMNT);
    -		dprintf((" error %d\n", error));
    -		return (error);
    -	}
    -	bcopy(bp->b_data, hpmp->hpm_bmind, hpmp->hpm_dbnum * sizeof(lsn_t));
    -	
    -	brelse(bp);
    -
    -	/*
    -	 * Read in all BitMap
    -	 */
    -	for (i=0; ihpm_dbnum; i++) {
    -		dprintf(("[%d: 0x%x] ", i, hpmp->hpm_bmind[i]));
    -
    -		error = bread(hpmp->hpm_devvp, hpmp->hpm_bmind[i],
    -				BMSIZE, NOCRED, &bp);
    -		if (error) {
    -			brelse(bp);
    -			free(hpmp->hpm_bitmap, M_HPFSMNT);
    -			free(hpmp->hpm_bmind, M_HPFSMNT);
    -			dprintf((" error %d\n", error));
    -			return (error);
    -		}
    -		bcopy(bp->b_data, hpmp->hpm_bitmap + BMSIZE * i, BMSIZE);
    -
    -		brelse(bp);
    -	}
    -
    -	/*
    -	 * Look througth BitMap	and count free bits
    -	 */
    -	dbavail = 0;
    -	for (i=0; i < hpmp->hpm_su.su_btotal >> 5; i++) {
    -		register u_int32_t mask;
    -		for (k=0, mask=1; k < 32; k++, mask<<=1)
    -			if(((u_int32_t *)hpmp->hpm_bitmap)[i] & mask) 
    -				dbavail ++;
    -
    -	}
    -	hpmp->hpm_bavail = dbavail;
    -
    -	return (0);
    -}
    -
    -int
    -hpfs_cmpfname (
    -	struct hpfsmount *hpmp,
    -	char * uname,
    -	int ulen,
    -	char * dname,
    -	int dlen,
    -	u_int16_t cp)
    -{
    -	register int i, res;
    -
    -	for (i = 0; i < ulen && i < dlen; i++) {
    -		res = hpfs_toupper(hpmp, hpfs_u2d(hpmp, uname[i]), cp) - 
    -		      hpfs_toupper(hpmp, dname[i], cp);
    -		if (res)
    -			return res;
    -	}
    -	return (ulen - dlen);
    -}
    -
    -int
    -hpfs_cpstrnnicmp (
    -	struct hpfsmount *hpmp,
    -	char * str1,
    -	int str1len,
    -	u_int16_t str1cp,
    -	char * str2,
    -	int str2len,
    -	u_int16_t str2cp)
    -{
    -	int i, res;
    -
    -	for (i = 0; i < str1len && i < str2len; i++) {
    -		res = (int)hpfs_toupper(hpmp, ((u_char *)str1)[i], str1cp) - 
    -		      (int)hpfs_toupper(hpmp, ((u_char *)str2)[i], str2cp);
    -		if (res)
    -			return res;
    -	}
    -	return (str1len - str2len);
    -}
    -
    -
    -int
    -hpfs_cpload (
    -	struct hpfsmount *hpmp,
    -	struct cpiblk *cpibp,
    -	struct cpdblk *cpdbp)
    -{
    -	struct buf *bp;
    -	struct cpdsec * cpdsp;
    -	int error, i;
    -
    -	error = bread(hpmp->hpm_devvp, cpibp->b_cpdsec, DEV_BSIZE, NOCRED, &bp);
    -	if (error) {
    -		brelse(bp);
    -		return (error);
    -	}
    -
    -	cpdsp = (struct cpdsec *)bp->b_data;
    -
    -	for (i=cpdsp->d_cpfirst; id_cpcnt; i++) {
    -		if (cpdsp->d_cpdblk[i].b_cpid == cpibp->b_cpid) {
    -			bcopy(cpdsp->d_cpdblk + i, cpdbp, 
    -			      sizeof(struct cpdblk));
    -
    -			brelse(bp);
    -
    -			return (0);
    -		}
    -	}
    -
    -	brelse(bp);
    -
    -	return (ENOENT);
    -}
    -
    -
    -/*
    - * Initialize Code Page information management.
    - * Load all copdepages in memory.
    - */
    -int
    -hpfs_cpinit (
    -	struct mount *mp,
    -	struct hpfsmount *hpmp)
    -{
    -	struct buf *bp;
    -	int error, i;
    -	lsn_t lsn;
    -	int cpicnt;
    -	struct cpisec * cpisp;
    -	struct cpiblk * cpibp;
    -	struct cpdblk * cpdbp;
    -
    -	dprintf(("hpfs_cpinit: \n"));
    -
    -	error = vfs_copyopt(mp->mnt_optnew, "d2u", hpmp->hpm_d2u,
    -	    sizeof hpmp->hpm_d2u);
    -	if (error == ENOENT)
    -		for (i=0x0; i<0x80;i++)
    -			hpmp->hpm_d2u[i] = i + 0x80;
    -	else if (error)
    -		return (error);
    -
    -	error = vfs_copyopt(mp->mnt_optnew, "u2d", hpmp->hpm_u2d,
    -	    sizeof hpmp->hpm_u2d);
    -	if (error == ENOENT)
    -		for (i=0x0; i<0x80;i++)
    -			hpmp->hpm_u2d[i] = i + 0x80;
    -	else if (error)
    -		return (error);
    -
    -	cpicnt = hpmp->hpm_sp.sp_cpinum;
    -
    -	hpmp->hpm_cpdblk = malloc(cpicnt * sizeof(struct cpdblk),
    -	    M_HPFSMNT, M_WAITOK);
    -
    -	cpdbp = hpmp->hpm_cpdblk;
    -	lsn = hpmp->hpm_sp.sp_cpi;
    -
    -	while (cpicnt > 0) {
    -		error = bread(hpmp->hpm_devvp, lsn, DEV_BSIZE, NOCRED, &bp);
    -		if (error) {
    -			brelse(bp);
    -			return (error);
    -		}
    -
    -		cpisp = (struct cpisec *)bp->b_data;
    -
    -		cpibp = cpisp->s_cpi;
    -		for (i=0; is_cpicnt; i++, cpicnt --, cpdbp++, cpibp++) {
    -			dprintf(("hpfs_cpinit: Country: %d, CP: %d (%d)\n",
    -				 cpibp->b_country, cpibp->b_cpid, 
    -				 cpibp->b_vcpid));
    -
    -			error = hpfs_cpload(hpmp, cpibp, cpdbp);
    -			if (error) {
    -				brelse(bp);
    -				return (error);
    -			}
    -		}
    -		lsn = cpisp->s_next;
    -		brelse(bp);
    -	}
    -
    -	return (0);
    -}
    -
    -int
    -hpfs_cpdeinit (
    -	struct hpfsmount *hpmp)
    -{
    -	dprintf(("hpmp_cpdeinit: "));
    -	free(hpmp->hpm_cpdblk,M_HPFSMNT);
    -	return (0);
    -}
    -
    -/*
    - * Lookup for a run of blocks.
    - */
    -int
    -hpfs_bmlookup (
    -	struct hpfsmount *hpmp,
    -	u_long flags,	/* 1 means we want right len blocks in run, not less */
    -	lsn_t lsn,		/* We want near this one */
    -	u_long len,		/* We want such long */
    -	lsn_t *lsnp,	/* We got here */
    -	u_long *lenp)	/* We got this long */
    -{
    -	u_int32_t * bitmap;
    -	register u_int32_t mask;
    -	int i,k;
    -	int cband, vcband;
    -	u_int bandsz;
    -	int count;
    -
    -	dprintf(("hpfs_bmlookup: lsn: 0x%x, len 0x%lx | Step1\n", lsn, len));
    -
    -	if (lsn > hpmp->hpm_su.su_btotal) {
    -		printf("hpfs_bmlookup: OUT OF VOLUME\n");
    -		return ENOSPC;
    -	}
    -	if (len > hpmp->hpm_bavail) {
    -		printf("hpfs_bmlookup: OUT OF SPACE\n");
    -		return ENOSPC;
    -	}
    - 	i = lsn >> 5;
    -	k = lsn & 0x1F;
    -	mask = 1 << k;
    -	bitmap = (u_int32_t *)hpmp->hpm_bitmap + i;
    -
    -	if (*bitmap & mask) {
    -		*lsnp = lsn;
    -		*lenp = 0;
    -		for (; k < 32; k++, mask<<=1) {
    -			if (*bitmap & mask)
    -				(*lenp) ++;
    -			else {
    -				if (flags & 1)
    -					goto step2;
    -				else 
    -					return (0);
    -			}
    -
    -			if (*lenp == len)
    -				return (0);
    -		}
    -
    -		bitmap++;
    -		i++;
    -		for (; i < hpmp->hpm_su.su_btotal >> 5; i++, bitmap++) {
    -			for (k=0, mask=1; k < 32; k++, mask<<=1) {
    -				if (*bitmap & mask)
    -					(*lenp) ++;
    -				else {
    -					if (flags & 1)
    -						goto step2;
    -					else 
    -						return (0);
    -				}
    -
    -				if (*lenp == len)
    -					return (0);
    -			}
    -		}
    -		return (0);
    -	}
    -
    -step2:
    -	/*
    -	 * Lookup all bands begining from cband, lookup for first block
    -	 */
    -	cband = (lsn >> 14);
    -	dprintf(("hpfs_bmlookup: Step2: band 0x%x (0x%lx)\n",
    -		 cband, hpmp->hpm_dbnum));
    -	for (vcband = 0; vcband < hpmp->hpm_dbnum; vcband ++, cband++) {
    -		cband = cband % hpmp->hpm_dbnum;
    -		bandsz = min (hpmp->hpm_su.su_btotal - (cband << 14), 0x4000);
    -		dprintf(("hpfs_bmlookup: band: %d, sz: 0x%x\n", cband, bandsz));
    -
    -		bitmap = (u_int32_t *)hpmp->hpm_bitmap + (cband << 9);
    -		*lsnp = cband << 14;
    -		*lenp = 0;
    -		count = 0;
    -		for (i=0; i < bandsz >> 5; i++, bitmap++) {
    -			for (k=0, mask=1; k < 32; k++, mask<<=1) {
    -				if (*bitmap & mask) {
    -					if (count) {
    -						(*lenp) ++;
    -					} else {
    -						count = 1;
    -						*lsnp = (cband << 14) + (i << 5) + k;
    -						*lenp = 1;
    -					}
    -				} else {
    -					if ((*lenp) && !(flags & 1)) {
    -						return (0);
    -					} else {
    -						count = 0;
    -					}
    -				}
    -
    -				if (*lenp == len)
    -					return (0);
    -			}
    -		}
    -		if (cband == hpmp->hpm_dbnum - 1)  {
    -			if ((*lenp) && !(flags & 1)) {
    -				return (0);
    -			} else {
    -				count = 0;
    -			}
    -		}
    -	}
    -
    -	return (ENOSPC);
    -}
    -
    -/*
    - * Lookup a single free block.	XXX Need locking on BitMap operations
    - * VERY STUPID ROUTINE!!!
    - */
    -int
    -hpfs_bmfblookup (
    -	struct hpfsmount *hpmp,
    -	lsn_t *lp)
    -{
    -	u_int32_t * bitmap;
    -	int i,k;
    -
    -	dprintf(("hpfs_bmfblookup: "));
    -
    -	bitmap = (u_int32_t *)hpmp->hpm_bitmap;
    -	for (i=0; i < hpmp->hpm_su.su_btotal >> 5; i++, bitmap++) {
    -		k = ffs(*bitmap);
    -		if (k) {
    -			*lp = (i << 5) + k - 1;
    -			dprintf((" found: 0x%x\n",*lp));
    -			return (0);
    -		}
    -	}
    -
    -	return (ENOSPC);
    -}
    -
    -/*
    - * Mark contignous block of blocks.
    - */
    -int
    -hpfs_bmmark (
    -	struct hpfsmount *hpmp,
    -	lsn_t bn,
    -	u_long bl,
    -	int state)
    -{
    -	u_int32_t * bitmap;
    -	int i, didprint = 0;
    -
    -	dprintf(("hpfs_bmmark(0x%x, 0x%lx, %d): \n",bn,bl, state));
    -
    -	if ((bn > hpmp->hpm_su.su_btotal) || (bn+bl > hpmp->hpm_su.su_btotal)) {
    -		printf("hpfs_bmmark: MARKING OUT OF VOLUME\n");
    -		return 0;
    -	}
    -	bitmap = (u_int32_t *)hpmp->hpm_bitmap;
    -	bitmap += bn >> 5;
    -
    -	while (bl > 0) {
    -		for (i = bn & 0x1F; (i < 0x20) && (bl > 0) ; i++, bl--) {
    -			if (state) {
    -				if ( *bitmap & (1 << i)) {
    -					if (!didprint) {
    -						printf("hpfs_bmmark: ALREADY FREE\n");
    -						didprint = 1;
    -					}
    -				} else 
    -					hpmp->hpm_bavail++;
    -
    -				*bitmap |= (1 << i);
    -			} else {
    -				if ((~(*bitmap)) & (1 << i)) {
    -					if (!didprint) {
    -						printf("hpfs_bmmark: ALREADY BUSY\n");
    -						didprint = 1;
    -					}
    -				} else 
    -					hpmp->hpm_bavail--;
    -
    -				*bitmap &= ~(1 << i);
    -			}
    -		}
    -		bn = 0;
    -		bitmap++;
    -	}
    -
    -	return (0);
    -}
    -
    -
    -int
    -hpfs_validateparent (
    -	struct hpfsnode *hp)
    -{
    -	struct hpfsnode *dhp;
    -	struct vnode *dvp;
    -	struct hpfsmount *hpmp = hp->h_hpmp;
    -	struct buf *bp;
    -	struct dirblk *dp;
    -	struct hpfsdirent *dep;
    -	lsn_t lsn, olsn;
    -	int level, error;
    -
    -	dprintf(("hpfs_validatetimes(0x%x): [parent: 0x%x] ",
    -		hp->h_no, hp->h_fn.fn_parent));
    -
    -	if (hp->h_no == hp->h_fn.fn_parent) {
    -		dhp = hp;
    -	} else {
    -		error = VFS_VGET(hpmp->hpm_mp, hp->h_fn.fn_parent,
    -				 LK_EXCLUSIVE, &dvp);
    -		if (error)
    -			return (error);
    -		dhp = VTOHP(dvp);
    -	}
    -
    -	lsn = ((alleaf_t *)dhp->h_fn.fn_abd)->al_lsn;
    -
    -	olsn = 0;
    -	level = 1;
    -	bp = NULL;
    -
    -dive:
    -	dprintf(("[dive 0x%x] ", lsn));
    -	if (bp != NULL)
    -		brelse(bp);
    -	error = bread(dhp->h_devvp, lsn, D_BSIZE, NOCRED, &bp);
    -	if (error)
    -		goto failed;
    -
    -	dp = (struct dirblk *) bp->b_data;
    -	if (dp->d_magic != D_MAGIC) {
    -		printf("hpfs_validatetimes: magic doesn't match\n");
    -		error = EINVAL;
    -		goto failed;
    -	}
    -
    -	dep = D_DIRENT(dp);
    -
    -	if (olsn) {
    -		dprintf(("[restore 0x%x] ", olsn));
    -
    -		while(!(dep->de_flag & DE_END) ) {
    -			if((dep->de_flag & DE_DOWN) &&
    -			   (olsn == DE_DOWNLSN(dep)))
    -					 break;
    -			dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen);
    -		}
    -
    -		if((dep->de_flag & DE_DOWN) && (olsn == DE_DOWNLSN(dep))) {
    -			if (dep->de_flag & DE_END)
    -				goto blockdone;
    -
    -			if (hp->h_no == dep->de_fnode) {
    -				dprintf(("[found] "));
    -				goto readdone;
    -			}
    -
    -			dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen);
    -		} else {
    -			printf("hpfs_validatetimes: ERROR! oLSN not found\n");
    -			error = EINVAL;
    -			goto failed;
    -		}
    -	}
    -
    -	olsn = 0;
    -
    -	while(!(dep->de_flag & DE_END)) {
    -		if(dep->de_flag & DE_DOWN) {
    -			lsn = DE_DOWNLSN(dep);
    -			level++;
    -			goto dive;
    -		}
    -
    -		if (hp->h_no == dep->de_fnode) {
    -			dprintf(("[found] "));
    -			goto readdone;
    -		}
    -
    -		dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen);
    -	}
    -
    -	if(dep->de_flag & DE_DOWN) {
    -		dprintf(("[enddive] "));
    -		lsn = DE_DOWNLSN(dep);
    -		level++;
    -		goto dive;
    -	}
    -
    -blockdone:
    -	dprintf(("[EOB] "));
    -	olsn = lsn;
    -	lsn = dp->d_parent;
    -	level--;
    -	dprintf(("[level %d] ", level));
    -	if (level > 0)
    -		goto dive;	/* undive really */
    -
    -	goto failed;
    -
    -readdone:
    -	bcopy(dep->de_name,hp->h_name,dep->de_namelen);
    -	hp->h_name[dep->de_namelen] = '\0';
    -	hp->h_namelen = dep->de_namelen;
    -	hp->h_ctime = dep->de_ctime;
    -	hp->h_atime = dep->de_atime;
    -	hp->h_mtime = dep->de_mtime;
    -	hp->h_flag |= H_PARVALID;
    -
    -	dprintf(("[readdone]"));
    -
    -failed:
    -	dprintf(("\n"));
    -	if (bp != NULL)
    -		brelse(bp);
    -	if (hp != dhp)
    -		vput(dvp);
    -
    -	return (error);
    -}
    -
    -struct timespec
    -hpfstimetounix (
    -	u_long hptime)
    -{
    -	struct timespec t;
    -
    -	t.tv_nsec = 0;
    -	t.tv_sec = hptime;
    -
    -	return t;
    -}
    -
    -/*
    - * Write down changes done to parent dir, these are only times for now. 
    - * hpfsnode have to be locked.
    - */
    -int
    -hpfs_updateparent (
    -	struct hpfsnode *hp)
    -{
    -	struct hpfsnode *dhp;
    -	struct vnode *dvp;
    -	struct hpfsdirent *dep;
    -	struct buf * bp;
    -	int error;
    -
    -	dprintf(("hpfs_updateparent(0x%x): \n", hp->h_no));
    -
    -	if (!(hp->h_flag & H_PARCHANGE))
    -		return (0);
    -
    -	if (!(hp->h_flag & H_PARVALID)) {
    -		error = hpfs_validateparent (hp);
    -		if (error)
    -			return (error);
    -	}
    -
    -	if (hp->h_no == hp->h_fn.fn_parent) {
    -		dhp = hp;
    -	} else {
    -		error = VFS_VGET(hp->h_hpmp->hpm_mp, hp->h_fn.fn_parent,
    -				 LK_EXCLUSIVE, &dvp);
    -		if (error)
    -			return (error);
    -		dhp = VTOHP(dvp);
    -	}
    -
    -	error = hpfs_genlookupbyname (dhp, hp->h_name, hp->h_namelen,
    -					&bp, &dep);
    -	if (error) {
    -		goto failed;
    -	}
    -
    -	dep->de_atime = hp->h_atime;
    -	dep->de_mtime = hp->h_mtime;
    -	dep->de_size = hp->h_fn.fn_size;
    -
    -	bdwrite (bp);
    -
    -	hp->h_flag &= ~H_PARCHANGE;
    -
    -	error = 0;
    -failed:
    -	if (hp != dhp)
    -		vput(dvp);
    -
    -	return (0);
    -}
    -
    -/*
    - * Write down on disk changes done to fnode. hpfsnode have to be locked.
    - */
    -int
    -hpfs_update (
    -	struct hpfsnode *hp)
    -{
    -	struct buf * bp;
    -
    -	dprintf(("hpfs_update(0x%x): \n", hp->h_no));
    -
    -	if (!(hp->h_flag & H_CHANGE))
    -		return (0);
    -
    -	bp = getblk(hp->h_devvp, hp->h_no, FNODESIZE, 0, 0, 0);
    -	clrbuf(bp);
    -
    -	bcopy (&hp->h_fn, bp->b_data, sizeof(struct fnode));
    -	bdwrite (bp);
    -
    -	hp->h_flag &= ~H_CHANGE;
    -
    -	if (hp->h_flag & H_PARCHANGE)
    -		return (hpfs_updateparent(hp));
    -
    -	return (0);
    -}
    -
    -/*
    - * Truncate file to specifed size. hpfsnode have to be locked.
    - */
    -int
    -hpfs_truncate (
    -	struct hpfsnode *hp,
    -	u_long size)
    -{
    -	struct hpfsmount *hpmp = hp->h_hpmp;
    -	lsn_t newblen, oldblen;
    -	int error, pf;
    -
    -	dprintf(("hpfs_truncate(0x%x, 0x%x -> 0x%lx): ",
    -		hp->h_no, hp->h_fn.fn_size, size));
    -
    -	newblen = (size + DEV_BSIZE - 1) >> DEV_BSHIFT;
    -	oldblen = (hp->h_fn.fn_size + DEV_BSIZE - 1) >> DEV_BSHIFT;
    -
    -	dprintf(("blen: 0x%x -> 0x%x\n", oldblen, newblen));
    -
    -	error = hpfs_truncatealblk (hpmp, &hp->h_fn.fn_ab, newblen, &pf);
    -	if (error)
    -		return (error);
    -	if (pf) {
    -		hp->h_fn.fn_ab.ab_flag = 0;
    -		hp->h_fn.fn_ab.ab_freecnt = 0x8;
    -		hp->h_fn.fn_ab.ab_busycnt = 0x0;
    -		hp->h_fn.fn_ab.ab_freeoff = sizeof(alblk_t);
    -	}
    -
    -	hp->h_fn.fn_size = size;
    -
    -	hp->h_flag |= (H_CHANGE | H_PARCHANGE);
    -
    -	dprintf(("hpfs_truncate: successful\n"));
    -
    -	return (0);
    -}
    -
    -/*
    - * Enlarge file to specifed size. hpfsnode have to be locked.
    - */
    -int
    -hpfs_extend (
    -	struct hpfsnode *hp,
    -	u_long size)
    -{
    -	struct hpfsmount *hpmp = hp->h_hpmp;
    -	lsn_t newblen, oldblen;
    -	int error;
    -
    -	dprintf(("hpfs_extend(0x%x, 0x%x -> 0x%lx): ",
    -		hp->h_no, hp->h_fn.fn_size, size));
    -
    -	if (hpmp->hpm_bavail < 0x10) 
    -		return (ENOSPC);
    -
    -	newblen = (size + DEV_BSIZE - 1) >> DEV_BSHIFT;
    -	oldblen = (hp->h_fn.fn_size + DEV_BSIZE - 1) >> DEV_BSHIFT;
    -
    -	dprintf(("blen: 0x%x -> 0x%x\n", oldblen, newblen));
    -
    -	error = hpfs_addextent(hpmp, hp, newblen - oldblen);
    -	if (error) {
    -		printf("hpfs_extend: FAILED TO ADD EXTENT %d\n", error);
    -		return (error);
    -	}
    -
    -	hp->h_fn.fn_size = size;
    -
    -	hp->h_flag |= (H_CHANGE | H_PARCHANGE);
    -
    -	dprintf(("hpfs_extend: successful\n"));
    -
    -	return (0);
    -}
    -
    -/*
    - * Read AlSec structure, and check if magic is valid.
    - * You don't need to brelse buf on error.
    - */
    -int
    -hpfs_breadstruct (
    -	struct hpfsmount *hpmp,
    -	lsn_t lsn,
    -	u_int len,
    -	u_int32_t magic,
    -	struct buf **bpp)
    -{
    -	struct buf *bp;
    -	u_int32_t *mp;
    -	int error;
    -
    -	dprintf(("hpfs_breadstruct: reading at 0x%x\n", lsn));
    -
    -	*bpp = NULL;
    -
    -	error = bread(hpmp->hpm_devvp, lsn, len, NOCRED, &bp);
    -	if (error) {
    -		brelse(bp);
    -		return (error);
    -	}
    -	mp = (u_int32_t *) bp->b_data;
    -	if (*mp != magic) {
    -		brelse(bp);
    -		printf("hpfs_breadstruct: MAGIC DOESN'T MATCH (0x%08x != 0x%08x)\n",
    -			*mp, magic);
    -		return (EINVAL);
    -	}
    -
    -	*bpp = bp;
    -
    -	return (0);
    -}
    -
    diff --git a/sys/fs/hpfs/hpfs_subr.h b/sys/fs/hpfs/hpfs_subr.h
    deleted file mode 100644
    index e8a24b45894..00000000000
    --- a/sys/fs/hpfs/hpfs_subr.h
    +++ /dev/null
    @@ -1,89 +0,0 @@
    -/*-
    - * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@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$
    - */
    -
    -#define	hpfs_bmmarkfree(hpmp, bn,bl) hpfs_bmmark(hpmp, bn, bl, 1)
    -#define	hpfs_bmmarkbusy(hpmp, bn,bl) hpfs_bmmark(hpmp, bn, bl, 0)
    -
    -u_long		hpfs_checksum (u_int8_t *, int);
    -
    -int		hpfs_bminit (struct hpfsmount *);
    -void		hpfs_bmdeinit (struct hpfsmount *);
    -int		hpfs_bmfblookup (struct hpfsmount *, lsn_t *);
    -int		hpfs_bmmark (struct hpfsmount *, lsn_t, u_long, int);
    -int		hpfs_bmlookup (struct hpfsmount *, u_long, lsn_t, u_long,
    -				lsn_t *, u_long *);
    -
    -struct hpfs_args;
    -int		hpfs_cpinit (struct mount *, struct hpfsmount *);
    -int		hpfs_cpdeinit (struct hpfsmount *);
    -int		hpfs_cpload (struct hpfsmount *, struct cpiblk *,
    -			     struct cpdblk *);
    -int		hpfs_cpstrnnicmp (struct hpfsmount *, char *, int, u_int16_t,
    -				  char *, int, u_int16_t);
    -int		hpfs_cmpfname (struct hpfsmount *, char *, int,
    -			       char *, int, u_int16_t);
    -
    -/* XXX Need unsigned conversion? */
    -#define	hpfs_u2d(hpmp, c)	((((u_char)(c))&0x80)?(hpmp->hpm_u2d[((u_char)(c))&0x7F]):((u_char)(c)))
    -#define hpfs_d2u(hpmp, c)	((((u_char)(c))&0x80)?(hpmp->hpm_d2u[((u_char)(c))&0x7F]):((u_char)(c)))
    -#define	hpfs_toupper(hpmp, c, cp)	((((u_char)(c))&0x80) ? ((u_char)((hpmp)->hpm_cpdblk[(cp)].b_upcase[((u_char)(c))&0x7F])) : ((((u_char)(c)) >= 'a' && ((u_char)(c)) <='z')?(((u_char)(c))-'a'+'A'):((u_char)(c))))
    -
    -
    -int		hpfs_truncate (struct hpfsnode *, u_long);
    -int		hpfs_extend (struct hpfsnode *, u_long);
    -
    -int		hpfs_updateparent (struct hpfsnode *);
    -int		hpfs_update (struct hpfsnode *);
    -
    -int		hpfs_validateparent (struct hpfsnode *);
    -struct timespec	hpfstimetounix (u_long);
    -int		hpfs_genlookupbyname (struct hpfsnode *, char *, int,
    -				      struct buf **, struct hpfsdirent **);
    -
    -int		hpfs_makefnode (struct vnode *, struct vnode **,
    -				struct componentname *, struct vattr *);
    -int		hpfs_removefnode (struct vnode *, struct vnode *,
    -				struct componentname *);
    -
    -int		hpfs_breadstruct (struct hpfsmount *, lsn_t, u_int, u_int32_t,
    -				 struct buf **);
    -#define	hpfs_breadalsec(hpmp, lsn, bpp) \
    -	hpfs_breadstruct(hpmp, lsn, DEV_BSIZE, AS_MAGIC, bpp)
    -#define	hpfs_breaddirblk(hpmp, lsn, bpp) \
    -	hpfs_breadstruct(hpmp, lsn, D_BSIZE, D_MAGIC, bpp)
    -
    -#if 0
    -#define	hpfs_hplock(hp, p)						\
    -	lockmgr(&(hp)->h_intlock, LK_EXCLUSIVE, (p))
    -#define	hpfs_hpunlock(hp, p)						\
    -	lockmgr(&(hp)->h_intlock, LK_RELEASE, (p))
    -#endif
    -
    -int		hpfs_hpbmap (struct hpfsnode *, daddr_t, daddr_t *, int *);
    -int		hpfs_truncatealblk (struct hpfsmount *, alblk_t *, lsn_t,int *);
    -int		hpfs_addextent (struct hpfsmount *, struct hpfsnode *, u_long);
    diff --git a/sys/fs/hpfs/hpfs_vfsops.c b/sys/fs/hpfs/hpfs_vfsops.c
    deleted file mode 100644
    index edc37b245a4..00000000000
    --- a/sys/fs/hpfs/hpfs_vfsops.c
    +++ /dev/null
    @@ -1,545 +0,0 @@
    -/*-
    - * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@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$
    - */
    -
    -
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -
    -#include 
    -#include 
    -
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -
    -#include 
    -#include 
    -#include 
    -
    -MALLOC_DEFINE(M_HPFSMNT, "hpfs_mount", "HPFS mount structure");
    -MALLOC_DEFINE(M_HPFSNO, "hpfs_node", "HPFS node structure");
    -
    -struct sockaddr;
    -
    -static int	hpfs_mountfs(register struct vnode *, struct mount *, 
    -				  struct thread *);
    -
    -static vfs_fhtovp_t     hpfs_fhtovp;
    -static vfs_vget_t       hpfs_vget;
    -static vfs_cmount_t     hpfs_cmount;
    -static vfs_mount_t      hpfs_mount;
    -static vfs_root_t       hpfs_root;
    -static vfs_statfs_t     hpfs_statfs;
    -static vfs_unmount_t    hpfs_unmount;
    -
    -static int
    -hpfs_cmount ( 
    -	struct mntarg *ma,
    -	void *data,
    -	uint64_t flags)
    -{
    -	struct hpfs_args args;
    -	struct export_args exp;
    -	int error;
    -
    -	error = copyin(data, (caddr_t)&args, sizeof (struct hpfs_args));
    -	if (error)
    -		return (error);
    -	vfs_oexport_conv(&args.export, &exp);
    -
    -	ma = mount_argsu(ma, "from", args.fspec, MAXPATHLEN);
    -	ma = mount_arg(ma, "export", &exp, sizeof(exp));
    -	ma = mount_argf(ma, "uid", "%d", args.uid);
    -	ma = mount_argf(ma, "gid", "%d", args.gid);
    -	ma = mount_argf(ma, "mode", "%d", args.mode);
    -	if (args.flags & HPFSMNT_TABLES) {
    -		ma = mount_arg(ma, "d2u", args.d2u, sizeof args.d2u);
    -		ma = mount_arg(ma, "u2d", args.u2d, sizeof args.u2d);
    -	}
    -
    -	error = kernel_mount(ma, flags);
    -
    -	return (error);
    -}
    -
    -static const char *hpfs_opts[] = {
    -	"from", "export", "uid", "gid", "mode", "d2u", "u2d", NULL
    -};
    -
    -static int
    -hpfs_mount (struct mount *mp)
    -{
    -	int		err = 0, error;
    -	struct vnode	*devvp;
    -	struct thread *td;
    -	struct nameidata ndp;
    -	struct export_args export;
    -	char *from;
    -
    -	td = curthread;
    -	dprintf(("hpfs_omount():\n"));
    -	/*
    -	 ***
    -	 * Mounting non-root filesystem or updating a filesystem
    -	 ***
    -	 */
    -	if (vfs_filteropt(mp->mnt_optnew, hpfs_opts))
    -		return (EINVAL);
    -
    -	from = vfs_getopts(mp->mnt_optnew, "from", &error);
    -	if (error)
    -		return (error);
    -
    -	/*
    -	 * If updating, check whether changing from read-only to
    -	 * read/write; if there is no device name, that's all we do.
    -	 */
    -	if (mp->mnt_flag & MNT_UPDATE) {
    -		dprintf(("hpfs_omount: MNT_UPDATE: "));
    -
    -		if (from == NULL) {
    -			error = vfs_copyopt(mp->mnt_optnew, "export",
    -			    &export, sizeof export);
    -			if (error)
    -				return (error);
    -			dprintf(("export 0x%x\n",args.export.ex_flags));
    -			err = vfs_export(mp, &export);
    -			if (err) {
    -				printf("hpfs_omount: vfs_export failed %d\n",
    -					err);
    -			}
    -			goto success;
    -		} else {
    -			dprintf(("name [FAILED]\n"));
    -			err = EINVAL;
    -			goto success;
    -		}
    -		dprintf(("\n"));
    -	}
    -
    -	/*
    -	 * Not an update, or updating the name: look up the name
    -	 * and verify that it refers to a sensible block device.
    -	 */
    -	NDINIT(&ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, from, td);
    -	err = namei(&ndp);
    -	if (err) {
    -		/* can't get devvp!*/
    -		goto error_1;
    -	}
    -
    -	devvp = ndp.ni_vp;
    -
    -	if (!vn_isdisk(devvp, &err)) {
    -		vput(devvp);
    -		return (err);
    -	}
    -
    -	/*
    -	 ********************
    -	 * NEW MOUNT
    -	 ********************
    -	 */
    -
    -	/*
    -	 * Since this is a new mount, we want the names for
    -	 * the device and the mount point copied in.  If an
    -	 * error occurs, the mountpoint is discarded by the
    -	 * upper level code.  Note that vfs_omount() handles
    -	 * copying the mountpoint f_mntonname for us, so we
    -	 * don't have to do it here unless we want to set it
    -	 * to something other than "path" for some rason.
    -	 */
    -	/* Save "mounted from" info for mount point (NULL pad)*/
    -	vfs_mountedfrom(mp, from);
    -
    -	err = hpfs_mountfs(devvp, mp, td);
    -	if (err) {
    -		vrele(devvp);
    -		goto error_1;
    -	}
    -
    -	goto success;
    -
    -error_1:	/* no state to back out*/
    -	/* XXX: Missing NDFREE(&ndp, ...) */
    -
    -success:
    -	return( err);
    -}
    -
    -/*
    - * Common code for mount and mountroot
    - */
    -int
    -hpfs_mountfs(devvp, mp, td)
    -	register struct vnode *devvp;
    -	struct mount *mp;
    -	struct thread *td;
    -{
    -	int error, ronly, v;
    -	struct sublock *sup;
    -	struct spblock *spp;
    -	struct hpfsmount *hpmp;
    -	struct buf *bp = NULL;
    -	struct vnode *vp;
    -	struct cdev *dev = devvp->v_rdev;
    -	struct g_consumer *cp;
    -	struct bufobj *bo;
    -
    -	if (mp->mnt_flag & MNT_ROOTFS)
    -		return (EOPNOTSUPP);
    -	dprintf(("hpfs_mountfs():\n"));
    -	ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
    -	/* XXX: use VOP_ACCESS to check FS perms */
    -	DROP_GIANT();
    -	g_topology_lock();
    -	error = g_vfs_open(devvp, &cp, "hpfs", ronly ? 0 : 1);
    -	g_topology_unlock();
    -	PICKUP_GIANT();
    -	VOP_UNLOCK(devvp, 0);
    -	if (error)
    -		return (error);
    -
    -	bo = &devvp->v_bufobj;
    -	bo->bo_private = cp;
    -	bo->bo_ops = g_vfs_bufops;
    -
    -	/*
    -	 * Do actual mount
    -	 */
    -	hpmp = malloc(sizeof(struct hpfsmount), M_HPFSMNT, M_WAITOK | M_ZERO);
    -
    -	hpmp->hpm_cp = cp;
    -	hpmp->hpm_bo = bo;
    -
    -	/* Read in SuperBlock */
    -	error = bread(devvp, SUBLOCK, SUSIZE, NOCRED, &bp);
    -	if (error)
    -		goto failed;
    -	bcopy(bp->b_data, &hpmp->hpm_su, sizeof(struct sublock));
    -	brelse(bp); bp = NULL;
    -
    -	/* Read in SpareBlock */
    -	error = bread(devvp, SPBLOCK, SPSIZE, NOCRED, &bp);
    -	if (error)
    -		goto failed;
    -	bcopy(bp->b_data, &hpmp->hpm_sp, sizeof(struct spblock));
    -	brelse(bp); bp = NULL;
    -
    -	sup = &hpmp->hpm_su;
    -	spp = &hpmp->hpm_sp;
    -
    -	/* Check magic */
    -	if (sup->su_magic != SU_MAGIC) {
    -		printf("hpfs_mountfs: SuperBlock MAGIC DOESN'T MATCH\n");
    -		error = EINVAL;
    -		goto failed;
    -	}
    -	if (spp->sp_magic != SP_MAGIC) {
    -		printf("hpfs_mountfs: SpareBlock MAGIC DOESN'T MATCH\n");
    -		error = EINVAL;
    -		goto failed;
    -	}
    -
    -	mp->mnt_data = hpmp;
    -	hpmp->hpm_devvp = devvp;
    -	hpmp->hpm_dev = devvp->v_rdev;
    -	hpmp->hpm_mp = mp;
    -	if (vfs_scanopt(mp->mnt_optnew, "uid", "%d", &v) == 1)
    -		hpmp->hpm_uid = v;
    -	if (vfs_scanopt(mp->mnt_optnew, "gid", "%d", &v) == 1)
    -		hpmp->hpm_gid = v;
    -	if (vfs_scanopt(mp->mnt_optnew, "mode", "%d", &v) == 1)
    -		hpmp->hpm_mode = v;
    -
    -	error = hpfs_bminit(hpmp);
    -	if (error)
    -		goto failed;
    -
    -	error = hpfs_cpinit(mp, hpmp);
    -	if (error) {
    -		hpfs_bmdeinit(hpmp);
    -		goto failed;
    -	}
    -
    -	error = hpfs_root(mp, LK_EXCLUSIVE, &vp);
    -	if (error) {
    -		hpfs_cpdeinit(hpmp);
    -		hpfs_bmdeinit(hpmp);
    -		goto failed;
    -	}
    -
    -	vput(vp);
    -
    -	mp->mnt_stat.f_fsid.val[0] = (long)dev2udev(dev);
    -	mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
    -	mp->mnt_maxsymlinklen = 0;
    -	MNT_ILOCK(mp);
    -	mp->mnt_flag |= MNT_LOCAL;
    -	MNT_IUNLOCK(mp);
    -	return (0);
    -
    -failed:
    -	if (bp)
    -		brelse (bp);
    -	mp->mnt_data = NULL;
    -	DROP_GIANT();
    -	g_topology_lock();
    -	g_vfs_close(cp);
    -	g_topology_unlock();
    -	PICKUP_GIANT();
    -	return (error);
    -}
    -
    -static int
    -hpfs_unmount( 
    -	struct mount *mp,
    -	int mntflags)
    -{
    -	int error, flags;
    -	register struct hpfsmount *hpmp = VFSTOHPFS(mp);
    -
    -	dprintf(("hpfs_unmount():\n"));
    -
    -	flags = 0;
    -	if(mntflags & MNT_FORCE)
    -		flags |= FORCECLOSE;
    -
    -	dprintf(("hpfs_unmount: vflushing...\n"));
    -	
    -	error = vflush(mp, 0, flags, curthread);
    -	if (error) {
    -		printf("hpfs_unmount: vflush failed: %d\n",error);
    -		return (error);
    -	}
    -
    -	vinvalbuf(hpmp->hpm_devvp, V_SAVE, 0, 0);
    -	DROP_GIANT();
    -	g_topology_lock();
    -	g_vfs_close(hpmp->hpm_cp);
    -	g_topology_unlock();
    -	PICKUP_GIANT();
    -	vrele(hpmp->hpm_devvp);
    -
    -	dprintf(("hpfs_umount: freeing memory...\n"));
    -	hpfs_cpdeinit(hpmp);
    -	hpfs_bmdeinit(hpmp);
    -	mp->mnt_data = NULL;
    -	MNT_ILOCK(mp);
    -	mp->mnt_flag &= ~MNT_LOCAL;
    -	MNT_IUNLOCK(mp);
    -	free(hpmp, M_HPFSMNT);
    -
    -	return (0);
    -}
    -
    -static int
    -hpfs_root(
    -	struct mount *mp,
    -	int flags,
    -	struct vnode **vpp)
    -{
    -	int error = 0;
    -	struct hpfsmount *hpmp = VFSTOHPFS(mp);
    -
    -	dprintf(("hpfs_root():\n"));
    -	error = VFS_VGET(mp, (ino_t)hpmp->hpm_su.su_rootfno, LK_EXCLUSIVE, vpp);
    -	if(error) {
    -		printf("hpfs_root: VFS_VGET failed: %d\n",error);
    -		return (error);
    -	}
    -
    -	return (error);
    -}
    -
    -static int
    -hpfs_statfs(
    -	struct mount *mp,
    -	struct statfs *sbp)
    -{
    -	struct hpfsmount *hpmp = VFSTOHPFS(mp);
    -
    -	dprintf(("hpfs_statfs(): HPFS%d.%d\n",
    -		hpmp->hpm_su.su_hpfsver, hpmp->hpm_su.su_fnctver));
    -
    -	sbp->f_type = mp->mnt_vfc->vfc_typenum;
    -	sbp->f_bsize = DEV_BSIZE;
    -	sbp->f_iosize = DEV_BSIZE;
    -	sbp->f_blocks = hpmp->hpm_su.su_btotal;
    -	sbp->f_bfree = sbp->f_bavail = hpmp->hpm_bavail;
    -	sbp->f_ffree = 0;
    -	sbp->f_files = 0;
    -	sbp->f_flags = mp->mnt_flag;
    -	
    -	return (0);
    -}
    -
    -/*ARGSUSED*/
    -static int
    -hpfs_fhtovp(
    -	struct mount *mp,
    -	struct fid *fhp,
    -	int flags,
    -	struct vnode **vpp)
    -{
    -	struct vnode *nvp;
    -	struct hpfid *hpfhp = (struct hpfid *)fhp;
    -	int error;
    -
    -	if ((error = VFS_VGET(mp, hpfhp->hpfid_ino, LK_EXCLUSIVE, &nvp)) != 0) {
    -		*vpp = NULLVP;
    -		return (error);
    -	}
    -	/* XXX as unlink/rmdir/mkdir/creat are not currently possible
    -	 * with HPFS, we don't need to check anything else for now */
    -	*vpp = nvp;
    -
    -	return (0);
    -}
    -
    -static int
    -hpfs_vget(
    -	struct mount *mp,
    -	ino_t ino,
    -	int flags,
    -	struct vnode **vpp) 
    -{
    -	struct hpfsmount *hpmp = VFSTOHPFS(mp);
    -	struct vnode *vp;
    -	struct hpfsnode *hp;
    -	struct buf *bp;
    -	int error;
    -
    -	dprintf(("hpfs_vget(0x%x): ",ino));
    -
    -	error = vfs_hash_get(mp, ino, flags, curthread, vpp, NULL, NULL);
    -	if (error || *vpp != NULL)
    -		return (error);
    -
    -	*vpp = NULL;
    -	hp = NULL;
    -	vp = NULL;
    -
    -	/*
    -	 * We have to lock node creation for a while,
    -	 * but then we have to call getnewvnode(), 
    -	 * this may cause hpfs_reclaim() to be called,
    -	 * this may need to VOP_VGET() parent dir for
    -	 * update reasons, and if parent is not in
    -	 * hash, we have to lock node creation...
    -	 * To solve this, we MALLOC, getnewvnode and init while
    -	 * not locked (probability of node appearence
    -	 * at that time is little, and anyway - we'll
    -	 * check for it).
    -	 */
    -	hp = malloc(sizeof(struct hpfsnode), 
    -		M_HPFSNO, M_WAITOK);
    -
    -	error = getnewvnode("hpfs", mp, &hpfs_vnodeops, &vp);
    -	if (error) {
    -		printf("hpfs_vget: can't get new vnode\n");
    -		free(hp, M_HPFSNO);
    -		return (error);
    -	}
    -
    -	dprintf(("prenew "));
    -
    -	vp->v_data = hp;
    -
    -	if (ino == (ino_t)hpmp->hpm_su.su_rootfno) 
    -		vp->v_vflag |= VV_ROOT;
    -
    -
    -	mtx_init(&hp->h_interlock, "hpfsnode interlock", NULL, MTX_DEF);
    -
    -	hp->h_flag = H_INVAL;
    -	hp->h_vp = vp;
    -	hp->h_hpmp = hpmp;
    -	hp->h_no = ino;
    -	hp->h_dev = hpmp->hpm_dev;
    -	hp->h_uid = hpmp->hpm_uid;
    -	hp->h_gid = hpmp->hpm_uid;
    -	hp->h_mode = hpmp->hpm_mode;
    -	hp->h_devvp = hpmp->hpm_devvp;
    -
    -	lockmgr(vp->v_vnlock, LK_EXCLUSIVE, NULL);
    -	error = insmntque(vp, mp);
    -	if (error != 0) {
    -		free(hp, M_HPFSNO);
    -		return (error);
    -	}
    -	error = vfs_hash_insert(vp, ino, flags, curthread, vpp, NULL, NULL);
    -	if (error || *vpp != NULL)
    -		return (error);
    -
    -	error = bread(hpmp->hpm_devvp, ino, FNODESIZE, NOCRED, &bp);
    -	if (error) {
    -		printf("hpfs_vget: can't read ino %ju\n", (uintmax_t)ino);
    -		vput(vp);
    -		return (error);
    -	}
    -	bcopy(bp->b_data, &hp->h_fn, sizeof(struct fnode));
    -	brelse(bp);
    -
    -	if (hp->h_fn.fn_magic != FN_MAGIC) {
    -		printf("hpfs_vget: MAGIC DOESN'T MATCH\n");
    -		vput(vp);
    -		return (EINVAL);
    -	}
    -
    -	vp->v_type = hp->h_fn.fn_flag ? VDIR:VREG;
    -	hp->h_flag &= ~H_INVAL;
    -
    -	*vpp = vp;
    -
    -	return (0);
    -}
    -
    -static struct vfsops hpfs_vfsops = {
    -	.vfs_fhtovp =		hpfs_fhtovp,
    -	.vfs_cmount =		hpfs_cmount,
    -	.vfs_mount =		hpfs_mount,
    -	.vfs_root =		hpfs_root,
    -	.vfs_statfs =		hpfs_statfs,
    -	.vfs_unmount =		hpfs_unmount,
    -	.vfs_vget =		hpfs_vget,
    -};
    -VFS_SET(hpfs_vfsops, hpfs, 0);
    diff --git a/sys/fs/hpfs/hpfs_vnops.c b/sys/fs/hpfs/hpfs_vnops.c
    deleted file mode 100644
    index 9abe77c3a1e..00000000000
    --- a/sys/fs/hpfs/hpfs_vnops.c
    +++ /dev/null
    @@ -1,1264 +0,0 @@
    -/*-
    - * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@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$
    - */
    -
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -
    -#include  /* for pathconf(2) constants */
    -
    -#include 
    -#include 
    -#include 
    -#include 
    -
    -static int	hpfs_de_uiomove(struct hpfsmount *, struct hpfsdirent *,
    -				     struct uio *);
    -static vop_ioctl_t	hpfs_ioctl;
    -static vop_read_t	hpfs_read;
    -static vop_write_t	hpfs_write;
    -static vop_getattr_t	hpfs_getattr;
    -static vop_setattr_t	hpfs_setattr;
    -static vop_inactive_t	hpfs_inactive;
    -static vop_print_t	hpfs_print;
    -static vop_reclaim_t	hpfs_reclaim;
    -static vop_strategy_t	hpfs_strategy;
    -static vop_access_t	hpfs_access;
    -static vop_open_t	hpfs_open;
    -static vop_close_t	hpfs_close;
    -static vop_readdir_t	hpfs_readdir;
    -static vop_cachedlookup_t	hpfs_lookup;
    -static vop_create_t	hpfs_create;
    -static vop_remove_t	hpfs_remove;
    -static vop_bmap_t	hpfs_bmap;
    -static vop_fsync_t	hpfs_fsync;
    -static vop_pathconf_t	hpfs_pathconf;
    -static vop_vptofh_t	hpfs_vptofh;
    -
    -static int
    -hpfs_fsync(ap)
    -	struct vop_fsync_args /* {
    -		struct vnode *a_vp;
    -		struct ucred *a_cred;
    -		int a_waitfor;
    -		struct thread *a_td;
    -	} */ *ap;
    -{
    -	/*
    -	 * Flush our dirty buffers.
    -	 */
    -	vop_stdfsync(ap);
    -
    -	/*
    -	 * Write out the on-disc version of the vnode.
    -	 */
    -	return hpfs_update(VTOHP(ap->a_vp));
    -}
    -
    -static int
    -hpfs_ioctl (
    -	struct vop_ioctl_args /* {
    -		struct vnode *a_vp;
    -		u_long a_command;
    -		caddr_t a_data;
    -		int a_fflag;
    -		struct ucred *a_cred;
    -		struct thread *a_td;
    -	} */ *ap)
    -{
    -	register struct vnode *vp = ap->a_vp;
    -	register struct hpfsnode *hp = VTOHP(vp);
    -	int error;
    -
    -	printf("hpfs_ioctl(0x%x, 0x%lx, 0x%p, 0x%x): ",
    -		hp->h_no, ap->a_command, ap->a_data, ap->a_fflag);
    -
    -	switch (ap->a_command) {
    -	case HPFSIOCGEANUM: {
    -		u_long eanum;
    -		u_long passed;
    -		struct ea *eap;
    -
    -		eanum = 0;
    -
    -		if (hp->h_fn.fn_ealen > 0) {
    -			eap = (struct ea *)&(hp->h_fn.fn_int);
    -			passed = 0;
    -
    -			while (passed < hp->h_fn.fn_ealen) {
    -
    -				printf("EAname: %s\n", EA_NAME(eap));
    -
    -				eanum++;
    -				passed += sizeof(struct ea) +
    -					  eap->ea_namelen + 1 + eap->ea_vallen;
    -				eap = (struct ea *)((caddr_t)hp->h_fn.fn_int +
    -						passed);
    -			}
    -			error = 0;
    -		} else {
    -			error = ENOENT;
    -		}
    -
    -		printf("%lu eas\n", eanum);
    -
    -		*(u_long *)ap->a_data = eanum;
    -
    -		break;
    -	}
    -	case HPFSIOCGEASZ: {
    -		u_long eanum;
    -		u_long passed;
    -		struct ea *eap;
    -
    -		printf("EA%ld\n", *(u_long *)ap->a_data);
    -
    -		eanum = 0;
    -		if (hp->h_fn.fn_ealen > 0) {
    -			eap = (struct ea *)&(hp->h_fn.fn_int);
    -			passed = 0;
    -
    -			error = ENOENT;
    -			while (passed < hp->h_fn.fn_ealen) {
    -				printf("EAname: %s\n", EA_NAME(eap));
    -
    -				if (eanum == *(u_long *)ap->a_data) {
    -					*(u_long *)ap->a_data =
    -					  	eap->ea_namelen + 1 +
    -						eap->ea_vallen;
    -
    -					error = 0;
    -					break;
    -				}
    -
    -				eanum++;
    -				passed += sizeof(struct ea) +
    -					  eap->ea_namelen + 1 + eap->ea_vallen;
    -				eap = (struct ea *)((caddr_t)hp->h_fn.fn_int +
    -						passed);
    -			}
    -		} else {
    -			error = ENOENT;
    -		}
    -
    -		break;
    -	}
    -	case HPFSIOCRDEA: {
    -		u_long eanum;
    -		u_long passed;
    -		struct hpfs_rdea *rdeap;
    -		struct ea *eap;
    -
    -		rdeap = (struct hpfs_rdea *)ap->a_data;
    -		printf("EA%ld\n", rdeap->ea_no);
    -
    -		eanum = 0;
    -		if (hp->h_fn.fn_ealen > 0) {
    -			eap = (struct ea *)&(hp->h_fn.fn_int);
    -			passed = 0;
    -
    -			error = ENOENT;
    -			while (passed < hp->h_fn.fn_ealen) {
    -				printf("EAname: %s\n", EA_NAME(eap));
    -
    -				if (eanum == rdeap->ea_no) {
    -					rdeap->ea_sz = eap->ea_namelen + 1 +
    -							eap->ea_vallen;
    -					copyout(EA_NAME(eap),rdeap->ea_data,
    -						rdeap->ea_sz);
    -					error = 0;
    -					break;
    -				}
    -
    -				eanum++;
    -				passed += sizeof(struct ea) +
    -					  eap->ea_namelen + 1 + eap->ea_vallen;
    -				eap = (struct ea *)((caddr_t)hp->h_fn.fn_int +
    -						passed);
    -			}
    -		} else {
    -			error = ENOENT;
    -		}
    -
    -		break;
    -	}
    -	default:
    -		error = ENOTTY;
    -		break;
    -	}
    -	return (error);
    -}
    -
    -/*
    - * Map file offset to disk offset.
    - */
    -int
    -hpfs_bmap(ap)
    -	struct vop_bmap_args /* {
    -		struct vnode *a_vp;
    -		daddr_t  a_bn;
    -		struct bufobj **a_bop;
    -		daddr_t *a_bnp;
    -		int *a_runp;
    -		int *a_runb;
    -	} */ *ap;
    -{
    -	register struct hpfsnode *hp = VTOHP(ap->a_vp);
    -	daddr_t blkno;
    -	int error;
    -
    -	if (ap->a_bop != NULL) 
    -		*ap->a_bop = &hp->h_devvp->v_bufobj;
    -	if (ap->a_runb != NULL)
    -		*ap->a_runb = 0;
    -	if (ap->a_bnp == NULL)
    -		return (0);
    -
    -	dprintf(("hpfs_bmap(0x%x, 0x%x): ",hp->h_no, ap->a_bn));
    -
    -	error = hpfs_hpbmap (hp, ap->a_bn, &blkno, ap->a_runp);
    -	*ap->a_bnp = blkno;
    -
    -	return (error);
    -}
    -
    -static int
    -hpfs_read(ap)
    -	struct vop_read_args /* {
    -		struct vnode *a_vp;
    -		struct uio *a_uio;
    -		int a_ioflag;
    -		struct ucred *a_cred;
    -	} */ *ap;
    -{
    -	register struct vnode *vp = ap->a_vp;
    -	register struct hpfsnode *hp = VTOHP(vp);
    -	struct uio *uio = ap->a_uio;
    -	struct buf *bp;
    -	u_int xfersz, toread;
    -	u_int off;
    -	daddr_t lbn, bn;
    -	int resid;
    -	int runl;
    -	int error = 0;
    -
    -	resid = min (uio->uio_resid, hp->h_fn.fn_size - uio->uio_offset);
    -
    -	dprintf(("hpfs_read(0x%x, off: %d resid: %d, segflg: %d): [resid: 0x%x]\n",hp->h_no,(u_int32_t)uio->uio_offset,uio->uio_resid,uio->uio_segflg, resid));
    -
    -	while (resid) {
    -		lbn = uio->uio_offset >> DEV_BSHIFT;
    -		off = uio->uio_offset & (DEV_BSIZE - 1);
    -		dprintf(("hpfs_read: resid: 0x%x lbn: 0x%x off: 0x%x\n",
    -			uio->uio_resid, lbn, off));
    -		error = hpfs_hpbmap(hp, lbn, &bn, &runl);
    -		if (error)
    -			return (error);
    -
    -		toread = min(off + resid, min(DFLTPHYS, (runl+1)*DEV_BSIZE));
    -		xfersz = (toread + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1);
    -		dprintf(("hpfs_read: bn: 0x%x (0x%x) toread: 0x%x (0x%x)\n",
    -			bn, runl, toread, xfersz));
    -
    -		if (toread == 0) 
    -			break;
    -
    -		error = bread(hp->h_devvp, bn, xfersz, NOCRED, &bp);
    -		if (error) {
    -			brelse(bp);
    -			break;
    -		}
    -
    -		error = uiomove(bp->b_data + off, toread - off, uio);
    -		if(error) {
    -			brelse(bp);
    -			break;
    -		}
    -		brelse(bp);
    -		resid -= toread;
    -	}
    -	dprintf(("hpfs_read: successful\n"));
    -	return (error);
    -}
    -
    -static int
    -hpfs_write(ap)
    -	struct vop_write_args /* {
    -		struct vnode *a_vp;
    -		struct uio *a_uio;
    -		int  a_ioflag;
    -		struct ucred *a_cred;
    -	} */ *ap;
    -{
    -	register struct vnode *vp = ap->a_vp;
    -	register struct hpfsnode *hp = VTOHP(vp);
    -	struct uio *uio = ap->a_uio;
    -	struct buf *bp;
    -	u_int xfersz, towrite;
    -	u_int off;
    -	daddr_t lbn, bn;
    -	int runl;
    -	int error = 0;
    -
    -	dprintf(("hpfs_write(0x%x, off: %d resid: %d, segflg: %d):\n",hp->h_no,(u_int32_t)uio->uio_offset,uio->uio_resid,uio->uio_segflg));
    -
    -	if (ap->a_ioflag & IO_APPEND) {
    -		dprintf(("hpfs_write: APPEND mode\n"));
    -		uio->uio_offset = hp->h_fn.fn_size;
    -	}
    -	if (uio->uio_offset + uio->uio_resid > hp->h_fn.fn_size) {
    -		error = hpfs_extend (hp, uio->uio_offset + uio->uio_resid);
    -		if (error) {
    -			printf("hpfs_write: hpfs_extend FAILED %d\n", error);
    -			return (error);
    -		}
    -	}
    -
    -	while (uio->uio_resid) {
    -		lbn = uio->uio_offset >> DEV_BSHIFT;
    -		off = uio->uio_offset & (DEV_BSIZE - 1);
    -		dprintf(("hpfs_write: resid: 0x%x lbn: 0x%x off: 0x%x\n",
    -			uio->uio_resid, lbn, off));
    -		error = hpfs_hpbmap(hp, lbn, &bn, &runl);
    -		if (error)
    -			return (error);
    -
    -		towrite = min(off + uio->uio_resid, min(DFLTPHYS, (runl+1)*DEV_BSIZE));
    -		xfersz = (towrite + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1);
    -		dprintf(("hpfs_write: bn: 0x%x (0x%x) towrite: 0x%x (0x%x)\n",
    -			bn, runl, towrite, xfersz));
    -
    -		if ((off == 0) && (towrite == xfersz)) {
    -			bp = getblk(hp->h_devvp, bn, xfersz, 0, 0, 0);
    -			clrbuf(bp);
    -		} else {
    -			error = bread(hp->h_devvp, bn, xfersz, NOCRED, &bp);
    -			if (error) {
    -				brelse(bp);
    -				return (error);
    -			}
    -		}
    -
    -		error = uiomove(bp->b_data + off, towrite - off, uio);
    -		if(error) {
    -			brelse(bp);
    -			return (error);
    -		}
    -
    -		if (ap->a_ioflag & IO_SYNC)
    -			bwrite(bp);
    -		else
    -			bawrite(bp);
    -	}
    -
    -	dprintf(("hpfs_write: successful\n"));
    -	return (0);
    -}
    -
    -/*
    - * XXXXX do we need hpfsnode locking inside?
    - */
    -static int
    -hpfs_getattr(ap)
    -	struct vop_getattr_args /* {
    -		struct vnode *a_vp;
    -		struct vattr *a_vap;
    -		struct ucred *a_cred;
    -	} */ *ap;
    -{
    -	register struct vnode *vp = ap->a_vp;
    -	register struct hpfsnode *hp = VTOHP(vp);
    -	register struct vattr *vap = ap->a_vap;
    -	int error;
    -
    -	dprintf(("hpfs_getattr(0x%x):\n", hp->h_no));
    -
    -	vap->va_fsid = dev2udev(hp->h_dev);
    -	vap->va_fileid = hp->h_no;
    -	vap->va_mode = hp->h_mode;
    -	vap->va_nlink = 1;
    -	vap->va_uid = hp->h_uid;
    -	vap->va_gid = hp->h_gid;
    -	vap->va_rdev = NODEV;
    -	vap->va_size = hp->h_fn.fn_size;
    -	vap->va_bytes = ((hp->h_fn.fn_size + DEV_BSIZE-1) & ~(DEV_BSIZE-1)) +
    -			DEV_BSIZE;
    -
    -	if (!(hp->h_flag & H_PARVALID)) {
    -		error = hpfs_validateparent(hp);
    -		if (error) 
    -			return (error);
    -	}
    -	vap->va_atime = hpfstimetounix(hp->h_atime);
    -	vap->va_mtime = hpfstimetounix(hp->h_mtime);
    -	vap->va_ctime = hpfstimetounix(hp->h_ctime);
    -
    -	vap->va_flags = 0;
    -	vap->va_gen = 0;
    -	vap->va_blocksize = DEV_BSIZE;
    -	vap->va_type = vp->v_type;
    -	vap->va_filerev = 0;
    -
    -	return (0);
    -}
    -
    -/*
    - * XXXXX do we need hpfsnode locking inside?
    - */
    -static int
    -hpfs_setattr(ap)
    -	struct vop_setattr_args /* {
    -		struct vnode *a_vp;
    -		struct vattr *a_vap;
    -		struct ucred *a_cred;
    -	} */ *ap;
    -{
    -	struct vnode *vp = ap->a_vp;
    -	struct hpfsnode *hp = VTOHP(vp);
    -	struct vattr *vap = ap->a_vap;
    -	struct ucred *cred = ap->a_cred;
    -	struct thread *td = curthread;
    -	int error;
    -
    -	dprintf(("hpfs_setattr(0x%x):\n", hp->h_no));
    -
    -	/*
    -	 * Check for unsettable attributes.
    -	 */
    -	if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
    -	    (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
    -	    (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
    -	    (vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
    -		dprintf(("hpfs_setattr: changing nonsettable attr\n"));
    -		return (EINVAL);
    -	}
    -
    -	/* Can't change flags XXX Could be implemented */
    -	if (vap->va_flags != VNOVAL) {
    -		printf("hpfs_setattr: FLAGS CANNOT BE SET\n");
    -		return (EINVAL);
    -	}
    -
    -	/* Can't change uid/gid XXX Could be implemented */
    -	if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) {
    -		printf("hpfs_setattr: UID/GID CANNOT BE SET\n");
    -		return (EINVAL);
    -	}
    -
    -	/* Can't change mode XXX Could be implemented */
    -	if (vap->va_mode != (mode_t)VNOVAL) {
    -		printf("hpfs_setattr: MODE CANNOT BE SET\n");
    -		return (EINVAL);
    -	}
    -
    -	/* Update times */
    -	if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
    -		if (vp->v_mount->mnt_flag & MNT_RDONLY)
    -			return (EROFS);
    -		if (vap->va_vaflags & VA_UTIMES_NULL) {
    -			error = VOP_ACCESS(vp, VADMIN, cred, td);
    -			if (error)
    -				error = VOP_ACCESS(vp, VWRITE, cred, td);
    -		} else
    -			error = VOP_ACCESS(vp, VADMIN, cred, td);
    -		if (vap->va_atime.tv_sec != VNOVAL)
    -			hp->h_atime = vap->va_atime.tv_sec;
    -		if (vap->va_mtime.tv_sec != VNOVAL)
    -			hp->h_mtime = vap->va_mtime.tv_sec;
    -
    -		hp->h_flag |= H_PARCHANGE;
    -	}
    -
    -	if (vap->va_size != VNOVAL) {
    -		switch (vp->v_type) {
    -		case VDIR:
    -			return (EISDIR);
    -		case VREG:
    -			if (vp->v_mount->mnt_flag & MNT_RDONLY)
    -				return (EROFS);
    -			break;
    -		default:
    -			printf("hpfs_setattr: WRONG v_type\n");
    -			return (EINVAL);
    -		}
    -
    -		if (vap->va_size < hp->h_fn.fn_size) {
    -			error = vtruncbuf(vp, cred, vap->va_size, DEV_BSIZE);
    -			if (error)
    -				return (error);
    -			error = hpfs_truncate(hp, vap->va_size);
    -			if (error)
    -				return (error);
    -
    -		} else if (vap->va_size > hp->h_fn.fn_size) {
    -			vnode_pager_setsize(vp, vap->va_size);
    -			error = hpfs_extend(hp, vap->va_size);
    -			if (error)
    -				return (error);
    -		}
    -	}
    -
    -	return (0);
    -}
    -
    -/*
    - * Last reference to a node.  If necessary, write or delete it.
    - */
    -int
    -hpfs_inactive(ap)
    -	struct vop_inactive_args /* {
    -		struct vnode *a_vp;
    -	} */ *ap;
    -{
    -	register struct vnode *vp = ap->a_vp;
    -	register struct hpfsnode *hp = VTOHP(vp);
    -	int error;
    -
    -	dprintf(("hpfs_inactive(0x%x): \n", hp->h_no));
    -
    -	if (hp->h_flag & H_CHANGE) {
    -		dprintf(("hpfs_inactive: node changed, update\n"));
    -		error = hpfs_update (hp);
    -		if (error)
    -			return (error);
    -	}
    -
    -	if (hp->h_flag & H_PARCHANGE) {
    -		dprintf(("hpfs_inactive: parent node changed, update\n"));
    -		error = hpfs_updateparent (hp);
    -		if (error)
    -			return (error);
    -	}
    -
    -	if (hp->h_flag & H_INVAL) {
    -		vrecycle(vp);
    -		return (0);
    -	}
    -
    -	return (0);
    -}
    -
    -/*
    - * Reclaim an inode so that it can be used for other purposes.
    - */
    -int
    -hpfs_reclaim(ap)
    -	struct vop_reclaim_args /* {
    -		struct vnode *a_vp;
    -	} */ *ap;
    -{
    -	register struct vnode *vp = ap->a_vp;
    -	register struct hpfsnode *hp = VTOHP(vp);
    -
    -	dprintf(("hpfs_reclaim(0x%x0): \n", hp->h_no));
    -
    -	/*
    -	 * Destroy the vm object and flush associated pages.
    -	 */
    -	vnode_destroy_vobject(vp);
    -
    -	vfs_hash_remove(vp);
    -
    -	mtx_destroy(&hp->h_interlock);
    -
    -	vp->v_data = NULL;
    -
    -	free(hp, M_HPFSNO);
    -
    -	return (0);
    -}
    -
    -static int
    -hpfs_print(ap)
    -	struct vop_print_args /* {
    -		struct vnode *a_vp;
    -	} */ *ap;
    -{
    -	register struct vnode *vp = ap->a_vp;
    -	register struct hpfsnode *hp = VTOHP(vp);
    -
    -	printf("\tino 0x%x\n", hp->h_no);
    -	return (0);
    -}
    -
    -/*
    - * Calculate the logical to physical mapping if not done already,
    - * then call the device strategy routine.
    - *
    - * In order to be able to swap to a file, the hpfs_hpbmap operation may not
    - * deadlock on memory.  See hpfs_bmap() for details. XXXXXXX (not impl)
    - */
    -int
    -hpfs_strategy(ap)
    -	struct vop_strategy_args /* {
    -		struct buf *a_bp;
    -	} */ *ap;
    -{
    -	register struct buf *bp = ap->a_bp;
    -	register struct vnode *vp = ap->a_vp;
    -	register struct hpfsnode *hp = VTOHP(ap->a_vp);
    -	daddr_t blkno;
    -	struct bufobj *bo;
    -	int error;
    -
    -	dprintf(("hpfs_strategy(): \n"));
    -
    -	if (vp->v_type == VBLK || vp->v_type == VCHR)
    -		panic("hpfs_strategy: spec");
    -	if (bp->b_blkno == bp->b_lblkno) {
    -		error = hpfs_hpbmap (hp, bp->b_lblkno, &blkno, NULL);
    -		bp->b_blkno = blkno;
    -		if (error) {
    -			printf("hpfs_strategy: hpfs_bpbmap FAILED %d\n", error);
    -			bp->b_error = error;
    -			bp->b_ioflags |= BIO_ERROR;
    -			bufdone(bp);
    -			return (0);
    -		}
    -		if ((long)bp->b_blkno == -1)
    -			vfs_bio_clrbuf(bp);
    -	}
    -	if ((long)bp->b_blkno == -1) {
    -		bufdone(bp);
    -		return (0);
    -	}
    -	bp->b_iooffset = dbtob(bp->b_blkno);
    -	bo = hp->h_hpmp->hpm_bo;
    -	BO_STRATEGY(bo, bp);
    -	return (0);
    -}
    -
    -/*
    - * XXXXX do we need hpfsnode locking inside?
    - */
    -int
    -hpfs_access(ap)
    -	struct vop_access_args /* {
    -		struct vnode *a_vp;
    -		accmode_t a_accmode;
    -		struct ucred *a_cred;
    -		struct thread *a_td;
    -	} */ *ap;
    -{
    -	struct vnode *vp = ap->a_vp;
    -	struct hpfsnode *hp = VTOHP(vp);
    -	accmode_t accmode = ap->a_accmode;
    -
    -	dprintf(("hpfs_access(0x%x):\n", hp->h_no));
    -
    -	/*
    -	 * Disallow write attempts on read-only filesystems;
    -	 * unless the file is a socket, fifo, or a block or
    -	 * character device resident on the filesystem.
    -	 */
    -	if (accmode & VWRITE) {
    -		switch ((int)vp->v_type) {
    -		case VDIR:
    -		case VLNK:
    -		case VREG:
    -			if (vp->v_mount->mnt_flag & MNT_RDONLY)
    -				return (EROFS);
    -			break;
    -		}
    -	}
    -
    -	return (vaccess(vp->v_type, hp->h_mode, hp->h_uid, hp->h_gid,
    -	    ap->a_accmode, ap->a_cred, NULL));
    -}
    -
    -/*
    - * Open called.
    - *
    - * Nothing to do.
    - */
    -/* ARGSUSED */
    -static int
    -hpfs_open(ap)
    -	struct vop_open_args /* {
    -		struct vnode *a_vp;
    -		int  a_mode;
    -		struct ucred *a_cred;
    -		struct thread *a_td;
    -	} */ *ap;
    -{
    -#ifdef HPFS_DEBUG
    -	register struct vnode *vp = ap->a_vp;
    -	register struct hpfsnode *hp = VTOHP(vp);
    -
    -	printf("hpfs_open(0x%x):\n",hp->h_no);
    -#endif
    -
    -	/*
    -	 * Files marked append-only must be opened for appending.
    -	 */
    -
    -	return (0);
    -}
    -
    -/*
    - * Close called.
    - *
    - * Update the times on the inode.
    - */
    -/* ARGSUSED */
    -static int
    -hpfs_close(ap)
    -	struct vop_close_args /* {
    -		struct vnode *a_vp;
    -		int  a_fflag;
    -		struct ucred *a_cred;
    -		struct thread *a_td;
    -	} */ *ap;
    -{
    -#ifdef HPFS_DEBUG
    -	register struct vnode *vp = ap->a_vp;
    -	register struct hpfsnode *hp = VTOHP(vp);
    -
    -	printf("hpfs_close: %d\n",hp->h_no);
    -#endif
    -
    -	return (0);
    -}
    -
    -static int
    -hpfs_de_uiomove (
    -	struct hpfsmount *hpmp,
    -	struct hpfsdirent *dep,
    -	struct uio *uio)
    -{
    -	struct dirent cde;
    -	int i, error;
    -
    -	dprintf(("[no: 0x%x, size: %d, name: %2d:%.*s, flag: 0x%x] ",
    -		dep->de_fnode, dep->de_size, dep->de_namelen,
    -		dep->de_namelen, dep->de_name, dep->de_flag));
    -
    -	/*strncpy(cde.d_name, dep->de_name, dep->de_namelen);*/
    -	for (i=0; ide_namelen; i++) 
    -		cde.d_name[i] = hpfs_d2u(hpmp, dep->de_name[i]);
    -
    -	cde.d_name[dep->de_namelen] = '\0';
    -	cde.d_namlen = dep->de_namelen;
    -	cde.d_fileno = dep->de_fnode;
    -	cde.d_type = (dep->de_flag & DE_DIR) ? DT_DIR : DT_REG;
    -	cde.d_reclen = sizeof(struct dirent);
    -
    -	error = uiomove((char *)&cde, sizeof(struct dirent), uio);
    -	if (error)
    -		return (error);
    -	
    -	dprintf(("[0x%x] ", uio->uio_resid));
    -	return (error);
    -}
    -
    -
    -static struct dirent hpfs_de_dot = {
    -	.d_fileno = 0,
    -	.d_reclen = sizeof(struct dirent),
    -	.d_type = DT_DIR,
    -	.d_namlen = 1,
    -	.d_name = "."
    -};
    -static struct dirent hpfs_de_dotdot = {
    -	.d_fileno = 0,
    -	.d_reclen = sizeof(struct dirent),
    -	.d_type = DT_DIR,
    -	.d_namlen = 2,
    -	.d_name = ".."
    -};
    -
    -int
    -hpfs_readdir(ap)
    -	struct vop_readdir_args /* {
    -		struct vnode *a_vp;
    -		struct uio *a_uio;
    -		struct ucred *a_cred;
    -		int *a_ncookies;
    -		u_int **cookies;
    -	} */ *ap;
    -{
    -	register struct vnode *vp = ap->a_vp;
    -	register struct hpfsnode *hp = VTOHP(vp);
    -	struct hpfsmount *hpmp = hp->h_hpmp;
    -	struct uio *uio = ap->a_uio;
    -	int ncookies = 0, i, num, cnum;
    -	int error = 0;
    -	off_t off;
    -	struct buf *bp;
    -	struct dirblk *dp;
    -	struct hpfsdirent *dep;
    -	lsn_t olsn;
    -	lsn_t lsn;
    -	int level;
    -
    -	dprintf(("hpfs_readdir(0x%x, 0x%x, 0x%x): ",hp->h_no,(u_int32_t)uio->uio_offset,uio->uio_resid));
    -
    -	off = uio->uio_offset;
    -
    -	if( uio->uio_offset < sizeof(struct dirent) ) {
    -		dprintf((". faked, "));
    -		hpfs_de_dot.d_fileno = hp->h_no;
    -		error = uiomove((char *)&hpfs_de_dot,sizeof(struct dirent),uio);
    -		if(error) {
    -			return (error);
    -		}
    -
    -		ncookies ++;
    -	}
    -
    -	if( uio->uio_offset < 2 * sizeof(struct dirent) ) {
    -		dprintf((".. faked, "));
    -		hpfs_de_dotdot.d_fileno = hp->h_fn.fn_parent;
    -
    -		error = uiomove((char *)&hpfs_de_dotdot, sizeof(struct dirent),
    -				uio);
    -		if(error) {
    -			return (error);
    -		}
    -
    -		ncookies ++;
    -	}
    -
    -	num = uio->uio_offset / sizeof(struct dirent) - 2;
    -	cnum = 0;
    -
    -	lsn = ((alleaf_t *)hp->h_fn.fn_abd)->al_lsn;
    -
    -	olsn = 0;
    -	level = 1;
    -
    -dive:
    -	dprintf(("[dive 0x%x] ", lsn));
    -	error = bread(hp->h_devvp, lsn, D_BSIZE, NOCRED, &bp);
    -	if (error) {
    -		brelse(bp);
    -		return (error);
    -	}
    -
    -	dp = (struct dirblk *) bp->b_data;
    -	if (dp->d_magic != D_MAGIC) {
    -		printf("hpfs_readdir: MAGIC DOESN'T MATCH\n");
    -		brelse(bp);
    -		return (EINVAL);
    -	}
    -
    -	dep = D_DIRENT(dp);
    -
    -	if (olsn) {
    -		dprintf(("[restore 0x%x] ", olsn));
    -
    -		while(!(dep->de_flag & DE_END) ) {
    -			if((dep->de_flag & DE_DOWN) &&
    -			   (olsn == DE_DOWNLSN(dep)))
    -					 break;
    -			dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen);
    -		}
    -
    -		if((dep->de_flag & DE_DOWN) && (olsn == DE_DOWNLSN(dep))) {
    -			if (dep->de_flag & DE_END)
    -				goto blockdone;
    -
    -			if (!(dep->de_flag & DE_SPECIAL)) {
    -				if (num <= cnum) {
    -					if (uio->uio_resid < sizeof(struct dirent)) {
    -						brelse(bp);
    -						dprintf(("[resid] "));
    -						goto readdone;
    -					}
    -
    -					error = hpfs_de_uiomove(hpmp, dep, uio);
    -					if (error) {
    -						brelse (bp);
    -						return (error);
    -					}
    -					ncookies++;
    -
    -					if (uio->uio_resid < sizeof(struct dirent)) {
    -						brelse(bp);
    -						dprintf(("[resid] "));
    -						goto readdone;
    -					}
    -				}
    -				cnum++;
    -			}
    -
    -			dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen);
    -		} else {
    -			printf("hpfs_readdir: ERROR! oLSN not found\n");
    -			brelse(bp);
    -			return (EINVAL);
    -		}
    -	}
    -
    -	olsn = 0;
    -
    -	while(!(dep->de_flag & DE_END)) {
    -		if(dep->de_flag & DE_DOWN) {
    -			lsn = DE_DOWNLSN(dep);
    -			brelse(bp);
    -			level++;
    -			goto dive;
    -		}
    -
    -		if (!(dep->de_flag & DE_SPECIAL)) {
    -			if (num <= cnum) {
    -				if (uio->uio_resid < sizeof(struct dirent)) {
    -					brelse(bp);
    -					dprintf(("[resid] "));
    -					goto readdone;
    -				}
    -
    -				error = hpfs_de_uiomove(hpmp, dep, uio);
    -				if (error) {
    -					brelse (bp);
    -					return (error);
    -				}
    -				ncookies++;
    -				
    -				if (uio->uio_resid < sizeof(struct dirent)) {
    -					brelse(bp);
    -					dprintf(("[resid] "));
    -					goto readdone;
    -				}
    -			}
    -			cnum++;
    -		}
    -
    -		dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen);
    -	}
    -
    -	if(dep->de_flag & DE_DOWN) {
    -		dprintf(("[enddive] "));
    -		lsn = DE_DOWNLSN(dep);
    -		brelse(bp);
    -		level++;
    -		goto dive;
    -	}
    -
    -blockdone:
    -	dprintf(("[EOB] "));
    -	olsn = lsn;
    -	lsn = dp->d_parent;
    -	brelse(bp);
    -	level--;
    -
    -	dprintf(("[level %d] ", level));
    -
    -	if (level > 0)
    -		goto dive;	/* undive really */
    -
    -	if (ap->a_eofflag) {
    -	    dprintf(("[EOF] "));
    -	    *ap->a_eofflag = 1;
    -	}
    -
    -readdone:
    -	dprintf(("[readdone]\n"));
    -	if (!error && ap->a_ncookies != NULL) {
    -		struct dirent* dpStart;
    -		struct dirent* dp;
    -		u_long *cookies;
    -		u_long *cookiep;
    -
    -		dprintf(("%d cookies, ",ncookies));
    -		if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
    -			panic("hpfs_readdir: unexpected uio from NFS server");
    -		dpStart = (struct dirent *)
    -		     ((caddr_t)uio->uio_iov->iov_base -
    -			 (uio->uio_offset - off));
    -		cookies = malloc(ncookies * sizeof(u_long),
    -		       M_TEMP, M_WAITOK);
    -		for (dp = dpStart, cookiep = cookies, i=0;
    -		     i < ncookies;
    -		     dp = (struct dirent *)((caddr_t) dp + dp->d_reclen), i++) {
    -			off += dp->d_reclen;
    -			*cookiep++ = (u_int) off;
    -		}
    -		*ap->a_ncookies = ncookies;
    -		*ap->a_cookies = cookies;
    -	}
    -
    -	return (0);
    -}
    -
    -int
    -hpfs_lookup(ap)
    -	struct vop_cachedlookup_args /* {
    -		struct vnode *a_dvp;
    -		struct vnode **a_vpp;
    -		struct componentname *a_cnp;
    -	} */ *ap;
    -{
    -	register struct vnode *dvp = ap->a_dvp;
    -	register struct hpfsnode *dhp = VTOHP(dvp);
    -	struct hpfsmount *hpmp = dhp->h_hpmp;
    -	struct componentname *cnp = ap->a_cnp;
    -	struct ucred *cred = cnp->cn_cred;
    -	int error;
    -	int nameiop = cnp->cn_nameiop;
    -	int flags = cnp->cn_flags;
    -	dprintf(("hpfs_lookup(0x%x, %s, %ld):\n",
    -		dhp->h_no, cnp->cn_nameptr, cnp->cn_namelen));
    -
    -	if (nameiop != CREATE && nameiop != DELETE && nameiop != LOOKUP) {
    -		printf("hpfs_lookup: LOOKUP, DELETE and CREATE are only supported\n");
    -		return (EOPNOTSUPP);
    -	}
    -
    -	error = VOP_ACCESS(dvp, VEXEC, cred, cnp->cn_thread);
    -	if(error)
    -		return (error);
    -
    -	if( (cnp->cn_namelen == 1) &&
    -	    !strncmp(cnp->cn_nameptr,".",1) ) {
    -		dprintf(("hpfs_lookup(0x%x,...): . faked\n",dhp->h_no));
    -
    -		VREF(dvp);
    -		*ap->a_vpp = dvp;
    -
    -		return (0);
    -	} else if( (cnp->cn_namelen == 2) &&
    -	    !strncmp(cnp->cn_nameptr,"..",2) && (flags & ISDOTDOT) ) {
    -		dprintf(("hpfs_lookup(0x%x,...): .. faked (0x%x)\n",
    -			dhp->h_no, dhp->h_fn.fn_parent));
    -
    -		if (VFS_VGET(hpmp->hpm_mp, dhp->h_fn.fn_parent,
    -		    LK_NOWAIT | LK_EXCLUSIVE, ap->a_vpp)) {
    -			VOP_UNLOCK(dvp,0);
    -			error = VFS_VGET(hpmp->hpm_mp,
    -				 dhp->h_fn.fn_parent, LK_EXCLUSIVE, ap->a_vpp); 
    -			vn_lock(dvp, LK_EXCLUSIVE|LK_RETRY);
    -			if (error)
    -				return(error);
    -		}
    -		return (0);
    -	} else {
    -		struct buf *bp;
    -		struct hpfsdirent *dep;
    -		struct hpfsnode *hp;
    -
    -		error = hpfs_genlookupbyname(dhp,
    -				cnp->cn_nameptr, cnp->cn_namelen, &bp, &dep);
    -		if (error) {
    -			if ((error == ENOENT) && (flags & ISLASTCN) &&
    -			    (nameiop == CREATE || nameiop == RENAME)) {
    -				cnp->cn_flags |= SAVENAME;
    -				return (EJUSTRETURN);
    -			}
    -
    -			return (error);
    -		}
    -
    -		dprintf(("hpfs_lookup: fnode: 0x%x, CPID: 0x%x\n",
    -			 dep->de_fnode, dep->de_cpid));
    -
    -		if (nameiop == DELETE && (flags & ISLASTCN)) {
    -			error = VOP_ACCESS(dvp, VWRITE, cred, cnp->cn_thread);
    -			if (error) {
    -				brelse(bp);
    -				return (error);
    -			}
    -		}
    -
    -		if (dhp->h_no == dep->de_fnode) {
    -			brelse(bp);
    -			VREF(dvp);
    -			*ap->a_vpp = dvp;
    -			return (0);
    -		}
    -
    -		error = VFS_VGET(hpmp->hpm_mp, dep->de_fnode, LK_EXCLUSIVE,
    -				 ap->a_vpp);
    -		if (error) {
    -			printf("hpfs_lookup: VFS_VGET FAILED %d\n", error);
    -			brelse(bp);
    -			return(error);
    -		}
    -
    -		hp = VTOHP(*ap->a_vpp);
    -
    -		hp->h_mtime = dep->de_mtime;
    -		hp->h_ctime = dep->de_ctime;
    -		hp->h_atime = dep->de_atime;
    -		bcopy(dep->de_name, hp->h_name, dep->de_namelen);
    -		hp->h_name[dep->de_namelen] = '\0';
    -		hp->h_namelen = dep->de_namelen;
    -		hp->h_flag |= H_PARVALID;
    -
    -		brelse(bp);
    -
    -		if ((flags & MAKEENTRY) &&
    -		    (!(flags & ISLASTCN) || 
    -		     (nameiop != DELETE && nameiop != CREATE)))
    -			cache_enter(dvp, *ap->a_vpp, cnp);
    -	}
    -	return (error);
    -}
    -
    -int
    -hpfs_remove(ap)
    -	struct vop_remove_args /* {
    -		struct vnode *a_dvp;
    -		struct vnode *a_vp;
    -		struct componentname *a_cnp;
    -	} */ *ap;
    -{
    -	int error;
    -
    -	dprintf(("hpfs_remove(0x%x, %s, %ld): \n", VTOHP(ap->a_vp)->h_no,
    -		ap->a_cnp->cn_nameptr, ap->a_cnp->cn_namelen));
    -
    -	if (ap->a_vp->v_type == VDIR)
    -		return (EPERM);
    -
    -	error = hpfs_removefnode (ap->a_dvp, ap->a_vp, ap->a_cnp);
    -	return (error);
    -}
    -
    -int
    -hpfs_create(ap)
    -	struct vop_create_args /* {
    -		struct vnode *a_dvp;
    -		struct vnode **a_vpp;
    -		struct componentname *a_cnp;
    -		struct vattr *a_vap;
    -	} */ *ap;
    -{
    -	int error;
    -
    -	dprintf(("hpfs_create(0x%x, %s, %ld): \n", VTOHP(ap->a_dvp)->h_no,
    -		ap->a_cnp->cn_nameptr, ap->a_cnp->cn_namelen));
    -
    -	if (!(ap->a_cnp->cn_flags & HASBUF)) 
    -		panic ("hpfs_create: no name\n");
    -
    -	error = hpfs_makefnode (ap->a_dvp, ap->a_vpp, ap->a_cnp, ap->a_vap);
    -
    -	return (error);
    -}
    -
    -/*
    - * Return POSIX pathconf information applicable to NTFS filesystem
    - */
    -int
    -hpfs_pathconf(ap)
    -	struct vop_pathconf_args /* {
    -		struct vnode *a_vp;
    -		int a_name;
    -		register_t *a_retval;
    -	} */ *ap;
    -{
    -	switch (ap->a_name) {
    -	case _PC_LINK_MAX:
    -		*ap->a_retval = 1;
    -		return (0);
    -	case _PC_NAME_MAX:
    -		*ap->a_retval = HPFS_MAXFILENAME;
    -		return (0);
    -	case _PC_PATH_MAX:
    -		*ap->a_retval = PATH_MAX;
    -		return (0);
    -	case _PC_CHOWN_RESTRICTED:
    -		*ap->a_retval = 1;
    -		return (0);
    -	case _PC_NO_TRUNC:
    -		*ap->a_retval = 0;
    -		return (0);
    -	default:
    -		return (EINVAL);
    -	}
    -	/* NOTREACHED */
    -}
    -
    -int
    -hpfs_vptofh(ap)
    -	struct vop_vptofh_args /* {
    -		struct vnode *a_vp;
    -		struct fid *a_fhp;
    -	} */ *ap;
    -{
    -	register struct hpfsnode *hpp;
    -	register struct hpfid *hpfhp;
    -
    -	hpp = VTOHP(ap->a_vp);
    -	hpfhp = (struct hpfid *)ap->a_fhp;
    -	hpfhp->hpfid_len = sizeof(struct hpfid);
    -	hpfhp->hpfid_ino = hpp->h_no;
    -	/* hpfhp->hpfid_gen = hpp->h_gen; */
    -	return (0);
    -}
    -
    -
    -/*
    - * Global vfs data structures
    - */
    -struct vop_vector hpfs_vnodeops = {
    -	.vop_default =		&default_vnodeops,
    -
    -	.vop_access =		hpfs_access,
    -	.vop_bmap =		hpfs_bmap,
    -	.vop_cachedlookup =	hpfs_lookup,
    -	.vop_close =		hpfs_close,
    -	.vop_create =		hpfs_create,
    -	.vop_fsync =		hpfs_fsync,
    -	.vop_getattr =		hpfs_getattr,
    -	.vop_inactive =		hpfs_inactive,
    -	.vop_ioctl =		hpfs_ioctl,
    -	.vop_lookup =		vfs_cache_lookup,
    -	.vop_open =		hpfs_open,
    -	.vop_pathconf =		hpfs_pathconf,
    -	.vop_print =		hpfs_print,
    -	.vop_read =		hpfs_read,
    -	.vop_readdir =		hpfs_readdir,
    -	.vop_reclaim =		hpfs_reclaim,
    -	.vop_remove =		hpfs_remove,
    -	.vop_setattr =		hpfs_setattr,
    -	.vop_strategy =		hpfs_strategy,
    -	.vop_write =		hpfs_write,
    -	.vop_vptofh =		hpfs_vptofh,
    -};
    diff --git a/sys/fs/hpfs/hpfsmount.h b/sys/fs/hpfs/hpfsmount.h
    deleted file mode 100644
    index 5ca42b3bf66..00000000000
    --- a/sys/fs/hpfs/hpfsmount.h
    +++ /dev/null
    @@ -1,39 +0,0 @@
    -/*-
    - * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@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$
    - */
    -
    -#define HPFSMNT_TABLES		0x0001
    -struct hpfs_args {
    -	char	*fspec;			/* block special device to mount */
    -	struct	oexport_args export;	/* network export information */
    -	uid_t	uid;			/* uid that owns hpfs files */
    -	gid_t	gid;			/* gid that owns hpfs files */
    -	mode_t	mode;			/* mask to be applied for hpfs perms */
    -	u_long	flags;			/* additional flags */
    -	u_char	d2u[0x80];
    -	u_char	u2d[0x80];
    -};
    diff --git a/sys/modules/hpfs/Makefile b/sys/modules/hpfs/Makefile
    deleted file mode 100644
    index 750fda00dae..00000000000
    --- a/sys/modules/hpfs/Makefile
    +++ /dev/null
    @@ -1,10 +0,0 @@
    -# $FreeBSD$
    -
    -.PATH: ${.CURDIR}/../../fs/hpfs
    -
    -KMOD=	hpfs
    -SRCS=	vnode_if.h \
    -	hpfs_vfsops.c hpfs_vnops.c hpfs_subr.c hpfs_lookup.c \
    -	hpfs_alsubr.c
    -
    -.include 
    
    From 67f1f66fc7db7c5a1c09fce8bdab74ac056f8c25 Mon Sep 17 00:00:00 2001
    From: Attilio Rao 
    Date: Sat, 2 Mar 2013 15:33:54 +0000
    Subject: [PATCH 0536/1476] Garbage collect XFS bits which are now already
     completely disconnected from the tree since few months.
    
    This is not targeted for MFC.
    ---
     ObsoleteFiles.inc                         |    2 +
     share/man/man5/xfs.5                      |  108 -
     sys/gnu/fs/xfs/FreeBSD/support/atomic.h   |   36 -
     sys/gnu/fs/xfs/FreeBSD/support/debug.c    |   97 -
     sys/gnu/fs/xfs/FreeBSD/support/debug.h    |   79 -
     sys/gnu/fs/xfs/FreeBSD/support/kdb.c      |   62 -
     sys/gnu/fs/xfs/FreeBSD/support/kdb.h      |   44 -
     sys/gnu/fs/xfs/FreeBSD/support/kmem.c     |    3 -
     sys/gnu/fs/xfs/FreeBSD/support/kmem.h     |   86 -
     sys/gnu/fs/xfs/FreeBSD/support/ktrace.c   |  334 -
     sys/gnu/fs/xfs/FreeBSD/support/ktrace.h   |  101 -
     sys/gnu/fs/xfs/FreeBSD/support/move.h     |   48 -
     sys/gnu/fs/xfs/FreeBSD/support/mrlock.c   |   14 -
     sys/gnu/fs/xfs/FreeBSD/support/mrlock.h   |   41 -
     sys/gnu/fs/xfs/FreeBSD/support/mutex.h    |   29 -
     sys/gnu/fs/xfs/FreeBSD/support/rwlock.h   |   23 -
     sys/gnu/fs/xfs/FreeBSD/support/rwsem.h    |   21 -
     sys/gnu/fs/xfs/FreeBSD/support/sema.h     |   53 -
     sys/gnu/fs/xfs/FreeBSD/support/spin.h     |   42 -
     sys/gnu/fs/xfs/FreeBSD/support/support.h  |   49 -
     sys/gnu/fs/xfs/FreeBSD/support/sv.h       |   30 -
     sys/gnu/fs/xfs/FreeBSD/support/time.h     |   37 -
     sys/gnu/fs/xfs/FreeBSD/support/uuid.c     |  165 -
     sys/gnu/fs/xfs/FreeBSD/support/uuid.h     |   45 -
     sys/gnu/fs/xfs/FreeBSD/xfs_buf.c          |  334 -
     sys/gnu/fs/xfs/FreeBSD/xfs_buf.h          |  348 -
     sys/gnu/fs/xfs/FreeBSD/xfs_compat.h       |  173 -
     sys/gnu/fs/xfs/FreeBSD/xfs_config.h       |   38 -
     sys/gnu/fs/xfs/FreeBSD/xfs_cred.h         |   46 -
     sys/gnu/fs/xfs/FreeBSD/xfs_dmistubs.c     |  144 -
     sys/gnu/fs/xfs/FreeBSD/xfs_freebsd.h      |  350 -
     sys/gnu/fs/xfs/FreeBSD/xfs_freebsd_iget.c |  419 --
     sys/gnu/fs/xfs/FreeBSD/xfs_frw.c          |  891 ---
     sys/gnu/fs/xfs/FreeBSD/xfs_frw.h          |  106 -
     sys/gnu/fs/xfs/FreeBSD/xfs_fs_subr.c      |  131 -
     sys/gnu/fs/xfs/FreeBSD/xfs_fs_subr.h      |   49 -
     sys/gnu/fs/xfs/FreeBSD/xfs_globals.c      |   77 -
     sys/gnu/fs/xfs/FreeBSD/xfs_ioctl.c        | 1460 ----
     sys/gnu/fs/xfs/FreeBSD/xfs_iops.h         |   61 -
     sys/gnu/fs/xfs/FreeBSD/xfs_mountops.c     |  500 --
     sys/gnu/fs/xfs/FreeBSD/xfs_mountops.h     |   59 -
     sys/gnu/fs/xfs/FreeBSD/xfs_node.h         |   16 -
     sys/gnu/fs/xfs/FreeBSD/xfs_stats.c        |  105 -
     sys/gnu/fs/xfs/FreeBSD/xfs_stats.h        |  161 -
     sys/gnu/fs/xfs/FreeBSD/xfs_super.c        |  279 -
     sys/gnu/fs/xfs/FreeBSD/xfs_super.h        |  113 -
     sys/gnu/fs/xfs/FreeBSD/xfs_sysctl.c       |   43 -
     sys/gnu/fs/xfs/FreeBSD/xfs_sysctl.h       |  102 -
     sys/gnu/fs/xfs/FreeBSD/xfs_version.h      |   44 -
     sys/gnu/fs/xfs/FreeBSD/xfs_vfs.c          |  356 -
     sys/gnu/fs/xfs/FreeBSD/xfs_vfs.h          |  232 -
     sys/gnu/fs/xfs/FreeBSD/xfs_vnode.c        |  272 -
     sys/gnu/fs/xfs/FreeBSD/xfs_vnode.h        |  673 --
     sys/gnu/fs/xfs/FreeBSD/xfs_vnops.c        | 1680 -----
     sys/gnu/fs/xfs/xfs.h                      |   23 -
     sys/gnu/fs/xfs/xfs_acl.c                  |  928 ---
     sys/gnu/fs/xfs/xfs_acl.h                  |  102 -
     sys/gnu/fs/xfs/xfs_ag.h                   |  231 -
     sys/gnu/fs/xfs/xfs_alloc.c                | 2603 -------
     sys/gnu/fs/xfs/xfs_alloc.h                |  189 -
     sys/gnu/fs/xfs/xfs_alloc_btree.c          | 2203 ------
     sys/gnu/fs/xfs/xfs_alloc_btree.h          |  159 -
     sys/gnu/fs/xfs/xfs_arch.h                 |  239 -
     sys/gnu/fs/xfs/xfs_attr.c                 | 2646 -------
     sys/gnu/fs/xfs/xfs_attr.h                 |  172 -
     sys/gnu/fs/xfs/xfs_attr_leaf.c            | 3083 --------
     sys/gnu/fs/xfs/xfs_attr_leaf.h            |  282 -
     sys/gnu/fs/xfs/xfs_attr_sf.h              |  114 -
     sys/gnu/fs/xfs/xfs_behavior.c             |  203 -
     sys/gnu/fs/xfs/xfs_behavior.h             |  190 -
     sys/gnu/fs/xfs/xfs_bit.c                  |  296 -
     sys/gnu/fs/xfs/xfs_bit.h                  |   67 -
     sys/gnu/fs/xfs/xfs_bmap.c                 | 6547 -----------------
     sys/gnu/fs/xfs/xfs_bmap.h                 |  386 -
     sys/gnu/fs/xfs/xfs_bmap_btree.c           | 2782 --------
     sys/gnu/fs/xfs/xfs_bmap_btree.h           |  377 -
     sys/gnu/fs/xfs/xfs_btree.c                |  943 ---
     sys/gnu/fs/xfs/xfs_btree.h                |  473 --
     sys/gnu/fs/xfs/xfs_buf_item.c             | 1203 ----
     sys/gnu/fs/xfs/xfs_buf_item.h             |  157 -
     sys/gnu/fs/xfs/xfs_cap.c                  |  207 -
     sys/gnu/fs/xfs/xfs_cap.h                  |   70 -
     sys/gnu/fs/xfs/xfs_clnt.h                 |  103 -
     sys/gnu/fs/xfs/xfs_da_btree.c             | 2590 -------
     sys/gnu/fs/xfs/xfs_da_btree.h             |  270 -
     sys/gnu/fs/xfs/xfs_dfrag.c                |  413 --
     sys/gnu/fs/xfs/xfs_dfrag.h                |   56 -
     sys/gnu/fs/xfs/xfs_dinode.h               |  281 -
     sys/gnu/fs/xfs/xfs_dir.c                  | 1218 ----
     sys/gnu/fs/xfs/xfs_dir.h                  |  142 -
     sys/gnu/fs/xfs/xfs_dir2.c                 |  851 ---
     sys/gnu/fs/xfs/xfs_dir2.h                 |   87 -
     sys/gnu/fs/xfs/xfs_dir2_block.c           | 1229 ----
     sys/gnu/fs/xfs/xfs_dir2_block.h           |   95 -
     sys/gnu/fs/xfs/xfs_dir2_data.c            |  837 ---
     sys/gnu/fs/xfs/xfs_dir2_data.h            |  188 -
     sys/gnu/fs/xfs/xfs_dir2_leaf.c            | 1877 -----
     sys/gnu/fs/xfs/xfs_dir2_leaf.h            |  270 -
     sys/gnu/fs/xfs/xfs_dir2_node.c            | 1999 ------
     sys/gnu/fs/xfs/xfs_dir2_node.h            |  104 -
     sys/gnu/fs/xfs/xfs_dir2_sf.c              | 1296 ----
     sys/gnu/fs/xfs/xfs_dir2_sf.h              |  195 -
     sys/gnu/fs/xfs/xfs_dir2_trace.c           |  216 -
     sys/gnu/fs/xfs/xfs_dir2_trace.h           |   72 -
     sys/gnu/fs/xfs/xfs_dir_leaf.c             | 2215 ------
     sys/gnu/fs/xfs/xfs_dir_leaf.h             |  231 -
     sys/gnu/fs/xfs/xfs_dir_sf.h               |  155 -
     sys/gnu/fs/xfs/xfs_dmapi.h                |  198 -
     sys/gnu/fs/xfs/xfs_dmops.c                |   37 -
     sys/gnu/fs/xfs/xfs_error.c                |  311 -
     sys/gnu/fs/xfs/xfs_error.h                |  193 -
     sys/gnu/fs/xfs/xfs_extfree_item.c         |  587 --
     sys/gnu/fs/xfs/xfs_extfree_item.h         |  111 -
     sys/gnu/fs/xfs/xfs_fs.h                   |  527 --
     sys/gnu/fs/xfs/xfs_fsops.c                |  599 --
     sys/gnu/fs/xfs/xfs_fsops.h                |   30 -
     sys/gnu/fs/xfs/xfs_ialloc.c               | 1411 ----
     sys/gnu/fs/xfs/xfs_ialloc.h               |  154 -
     sys/gnu/fs/xfs/xfs_ialloc_btree.c         | 2080 ------
     sys/gnu/fs/xfs/xfs_ialloc_btree.h         |  177 -
     sys/gnu/fs/xfs/xfs_iget.c                 | 1052 ---
     sys/gnu/fs/xfs/xfs_imap.h                 |   40 -
     sys/gnu/fs/xfs/xfs_inode.c                | 4796 -------------
     sys/gnu/fs/xfs/xfs_inode.h                |  516 --
     sys/gnu/fs/xfs/xfs_inode_item.c           | 1086 ---
     sys/gnu/fs/xfs/xfs_inode_item.h           |  178 -
     sys/gnu/fs/xfs/xfs_inum.h                 |   81 -
     sys/gnu/fs/xfs/xfs_iocore.c               |  123 -
     sys/gnu/fs/xfs/xfs_iomap.c                | 1006 ---
     sys/gnu/fs/xfs/xfs_iomap.h                |   90 -
     sys/gnu/fs/xfs/xfs_itable.c               |  848 ---
     sys/gnu/fs/xfs/xfs_itable.h               |   91 -
     sys/gnu/fs/xfs/xfs_log.c                  | 3708 ----------
     sys/gnu/fs/xfs/xfs_log.h                  |  192 -
     sys/gnu/fs/xfs/xfs_log_priv.h             |  511 --
     sys/gnu/fs/xfs/xfs_log_recover.c          | 4078 -----------
     sys/gnu/fs/xfs/xfs_log_recover.h          |   67 -
     sys/gnu/fs/xfs/xfs_mac.c                  |   72 -
     sys/gnu/fs/xfs/xfs_mac.h                  |  106 -
     sys/gnu/fs/xfs/xfs_mount.c                | 2207 ------
     sys/gnu/fs/xfs/xfs_mount.h                |  626 --
     sys/gnu/fs/xfs/xfs_qmops.c                |  128 -
     sys/gnu/fs/xfs/xfs_quota.h                |  372 -
     sys/gnu/fs/xfs/xfs_refcache.c             |  431 --
     sys/gnu/fs/xfs/xfs_refcache.h             |   54 -
     sys/gnu/fs/xfs/xfs_rename.c               |  636 --
     sys/gnu/fs/xfs/xfs_rtalloc.c              | 2449 -------
     sys/gnu/fs/xfs/xfs_rtalloc.h              |  173 -
     sys/gnu/fs/xfs/xfs_rw.c                   |  341 -
     sys/gnu/fs/xfs/xfs_rw.h                   |   98 -
     sys/gnu/fs/xfs/xfs_sb.h                   |  492 --
     sys/gnu/fs/xfs/xfs_trans.c                | 1382 ----
     sys/gnu/fs/xfs/xfs_trans.h                | 1016 ---
     sys/gnu/fs/xfs/xfs_trans_ail.c            |  581 --
     sys/gnu/fs/xfs/xfs_trans_buf.c            | 1113 ---
     sys/gnu/fs/xfs/xfs_trans_extfree.c        |  141 -
     sys/gnu/fs/xfs/xfs_trans_inode.c          |  310 -
     sys/gnu/fs/xfs/xfs_trans_item.c           |  539 --
     sys/gnu/fs/xfs/xfs_trans_priv.h           |   61 -
     sys/gnu/fs/xfs/xfs_trans_space.h          |   91 -
     sys/gnu/fs/xfs/xfs_types.h                |  179 -
     sys/gnu/fs/xfs/xfs_utils.c                |  472 --
     sys/gnu/fs/xfs/xfs_utils.h                |   38 -
     sys/gnu/fs/xfs/xfs_vfsops.c               | 2030 ------
     sys/gnu/fs/xfs/xfs_vnodeops.c             | 4719 -------------
     sys/gnu/fs/xfs/xfsidbg.c                  | 7769 ---------------------
     sys/modules/xfs/Makefile                  |   89 -
     167 files changed, 2 insertions(+), 108267 deletions(-)
     delete mode 100644 share/man/man5/xfs.5
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/support/atomic.h
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/support/debug.c
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/support/debug.h
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/support/kdb.c
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/support/kdb.h
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/support/kmem.c
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/support/kmem.h
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/support/ktrace.c
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/support/ktrace.h
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/support/move.h
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/support/mrlock.c
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/support/mrlock.h
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/support/mutex.h
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/support/rwlock.h
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/support/rwsem.h
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/support/sema.h
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/support/spin.h
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/support/support.h
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/support/sv.h
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/support/time.h
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/support/uuid.c
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/support/uuid.h
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/xfs_buf.c
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/xfs_buf.h
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/xfs_compat.h
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/xfs_config.h
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/xfs_cred.h
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/xfs_dmistubs.c
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/xfs_freebsd.h
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/xfs_freebsd_iget.c
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/xfs_frw.c
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/xfs_frw.h
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/xfs_fs_subr.c
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/xfs_fs_subr.h
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/xfs_globals.c
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/xfs_ioctl.c
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/xfs_iops.h
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/xfs_mountops.c
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/xfs_mountops.h
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/xfs_node.h
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/xfs_stats.c
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/xfs_stats.h
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/xfs_super.c
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/xfs_super.h
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/xfs_sysctl.c
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/xfs_sysctl.h
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/xfs_version.h
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/xfs_vfs.c
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/xfs_vfs.h
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/xfs_vnode.c
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/xfs_vnode.h
     delete mode 100644 sys/gnu/fs/xfs/FreeBSD/xfs_vnops.c
     delete mode 100644 sys/gnu/fs/xfs/xfs.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_acl.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_acl.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_ag.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_alloc.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_alloc.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_alloc_btree.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_alloc_btree.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_arch.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_attr.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_attr.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_attr_leaf.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_attr_leaf.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_attr_sf.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_behavior.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_behavior.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_bit.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_bit.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_bmap.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_bmap.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_bmap_btree.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_bmap_btree.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_btree.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_btree.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_buf_item.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_buf_item.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_cap.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_cap.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_clnt.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_da_btree.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_da_btree.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_dfrag.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_dfrag.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_dinode.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_dir.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_dir.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_dir2.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_dir2.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_dir2_block.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_dir2_block.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_dir2_data.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_dir2_data.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_dir2_leaf.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_dir2_leaf.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_dir2_node.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_dir2_node.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_dir2_sf.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_dir2_sf.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_dir2_trace.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_dir2_trace.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_dir_leaf.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_dir_leaf.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_dir_sf.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_dmapi.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_dmops.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_error.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_error.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_extfree_item.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_extfree_item.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_fs.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_fsops.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_fsops.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_ialloc.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_ialloc.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_ialloc_btree.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_ialloc_btree.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_iget.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_imap.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_inode.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_inode.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_inode_item.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_inode_item.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_inum.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_iocore.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_iomap.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_iomap.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_itable.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_itable.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_log.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_log.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_log_priv.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_log_recover.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_log_recover.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_mac.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_mac.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_mount.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_mount.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_qmops.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_quota.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_refcache.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_refcache.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_rename.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_rtalloc.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_rtalloc.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_rw.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_rw.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_sb.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_trans.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_trans.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_trans_ail.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_trans_buf.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_trans_extfree.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_trans_inode.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_trans_item.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_trans_priv.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_trans_space.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_types.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_utils.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_utils.h
     delete mode 100644 sys/gnu/fs/xfs/xfs_vfsops.c
     delete mode 100644 sys/gnu/fs/xfs/xfs_vnodeops.c
     delete mode 100644 sys/gnu/fs/xfs/xfsidbg.c
     delete mode 100644 sys/modules/xfs/Makefile
    
    diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc
    index 33bb90b910b..93d50fe9498 100644
    --- a/ObsoleteFiles.inc
    +++ b/ObsoleteFiles.inc
    @@ -38,6 +38,8 @@
     #   xargs -n1 | sort | uniq -d;
     # done
     
    +# 20130302: XFS support removed
    +OLD_FILES+=usr/share/man/man5/xfs.5.gz
     # 20130116: removed long unused directories for .1aout section manpages
     OLD_FILES+=usr/share/man/en.ISO8859-1/man1aout
     OLD_FILES+=usr/share/man/en.UTF-8/man1aout
    diff --git a/share/man/man5/xfs.5 b/share/man/man5/xfs.5
    deleted file mode 100644
    index 67504aa676a..00000000000
    --- a/share/man/man5/xfs.5
    +++ /dev/null
    @@ -1,108 +0,0 @@
    -.\"
    -.\" Copyright (c) 2007 Craig Rodrigues
    -.\" All rights reserved.
    -.\"
    -.\" Redistribution and use in source and binary forms, with or without
    -.\" modification, are permitted provided that the following conditions
    -.\" are met:
    -.\" 1. Redistributions of source code must retain the above copyright
    -.\"    notice, this list of conditions and the following disclaimer.
    -.\" 2. Redistributions in binary form must reproduce the above copyright
    -.\"    notice, this list of conditions and the following disclaimer in the
    -.\"    documentation and/or other materials provided with the distribution.
    -.\"
    -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
    -.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    -.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    -.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
    -.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    -.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    -.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    -.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    -.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    -.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    -.\"
    -.\" $FreeBSD$
    -.\"
    -.Dd January 16, 2011
    -.Dt XFS 5
    -.Os
    -.Sh NAME
    -.Nm xfs
    -.Nd "XFS file system"
    -.Sh SYNOPSIS
    -To link into the kernel:
    -.Bd -ragged -offset indent
    -.Cd "options XFS"
    -.Ed
    -.Pp
    -To load as a kernel loadable module:
    -.Pp
    -.Dl "kldload xfs"
    -.Sh DESCRIPTION
    -The
    -.Nm
    -driver will permit the
    -.Fx
    -kernel to access
    -.Tn XFS
    -file systems.
    -.Sh EXAMPLES
    -To mount a
    -.Nm
    -volume located on
    -.Pa /dev/ad1s1 :
    -.Pp
    -.Dl "mount -t xfs -o ro /dev/ad1s1 /mnt"
    -.Sh SEE ALSO
    -.Xr nmount 2 ,
    -.Xr unmount 2 ,
    -.Xr fstab 5 ,
    -.Xr mount 8
    -.Sh NOTES
    -The
    -.Pa sysutils/xfsprogs
    -port contains the
    -.Cm mkfs.xfs
    -utility for
    -creating XFS file systems, and also other utilities for analyzing,
    -and repairing XFS file systems.
    -.Sh HISTORY
    -XFS was originally written by SGI for the IRIX operating system.
    -SGI ported XFS to Linux, and released the source code under the GNU
    -Public License.  For more details, see:
    -.Pa http://oss.sgi.com/projects/xfs
    -.Pp
    -The port to
    -.Fx
    -was based on the Linux port, and started by
    -.An -nosplit
    -.An Russell Cattelan Aq cattelan@xfs.org ,
    -.An Alexander Kabaev Aq kan@FreeBSD.org ,
    -and
    -.An Craig Rodrigues Aq rodrigc@FreeBSD.org .
    -.Pp
    -The
    -.Nm
    -file system support
    -first appeared in
    -.Fx 7.0 .
    -.Sh AUTHORS
    -This manual page was written by
    -.An Craig Rodrigues Aq rodrigc@FreeBSD.org .
    -.Sh CAVEATS
    -The port of XFS to
    -.Fx
    -is currently incomplete.
    -Only read-only access is supported for XFS volumes.
    -Writing to a volume is not supported.
    -.Pp
    -The
    -.Fl p
    -flag to
    -.Cm mkfs.xfs
    -can be used to create an XFS file system which is populated with files
    -and other metadata.
    -This can be used to quickly create a read-only file system which
    -can be tested on
    -.Fx .
    diff --git a/sys/gnu/fs/xfs/FreeBSD/support/atomic.h b/sys/gnu/fs/xfs/FreeBSD/support/atomic.h
    deleted file mode 100644
    index 618de8ccf38..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/support/atomic.h
    +++ /dev/null
    @@ -1,36 +0,0 @@
    -#ifndef __XFS_SUPPORT_ATOMIC_H__
    -
    -#include 
    -#include 
    -
    -typedef struct {
    -	volatile unsigned int	val;
    -} atomic_t;
    -
    -#define	atomic_read(v)			((v)->val)
    -#define atomic_set(v, i)		((v)->val = (i))
    -
    -#define	atomic_add(i, v)		atomic_add_int(&(v)->val, (i))
    -#define	atomic_inc(v)			atomic_add_int(&(v)->val, 1)
    -#define	atomic_dec(v)			atomic_subtract_int(&(v)->val, 1)
    -#define	atomic_sub(i, v)		atomic_subtract_int(&(v)->val, (i))
    -#define	atomic_dec_and_test(v)		(atomic_fetchadd_int(&(v)->val, -1) == 1)
    -
    -/*
    - * This is used for two variables in XFS, one of which is a debug trace
    - * buffer index.
    - */
    -
    -static __inline__ int atomicIncWithWrap(volatile unsigned int *ip, int val)
    -{
    -	unsigned int oldval, newval;
    -
    -	do {
    -		oldval = *ip;
    -		newval = (oldval + 1 >= val) ? 0 : oldval + 1;
    -        } while (atomic_cmpset_rel_int(ip, oldval, newval) == 0);
    -
    -	return oldval;
    -}
    -
    -#endif /* __XFS_SUPPORT_ATOMIC_H__ */
    diff --git a/sys/gnu/fs/xfs/FreeBSD/support/debug.c b/sys/gnu/fs/xfs/FreeBSD/support/debug.c
    deleted file mode 100644
    index cf2ef946edf..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/support/debug.c
    +++ /dev/null
    @@ -1,97 +0,0 @@
    -/*
    - * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
    - * 
    - * This program is free software; you can redistribute it and/or modify it
    - * under the terms of version 2 of the GNU General Public License as
    - * published by the Free Software Foundation.
    - * 
    - * This program is distributed in the hope that it would be useful, but
    - * WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    - * 
    - * Further, this software is distributed without any warranty that it is
    - * free of the rightful claim of any third person regarding infringement
    - * or the like.  Any license provided herein, whether implied or
    - * otherwise, applies only to this software file.  Patent licenses, if
    - * any, provided herein do not apply to combinations of this program with
    - * other software, or any other product whatsoever.
    - * 
    - * You should have received a copy of the GNU General Public License along
    - * with this program; if not, write the Free Software Foundation, Inc., 59
    - * Temple Place - Suite 330, Boston MA 02111-1307, USA.
    - * 
    - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
    - * Mountain View, CA  94043, or:
    - * 
    - * http://www.sgi.com 
    - * 
    - * For further information regarding this notice, see: 
    - * 
    - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
    - */
    - 
    -
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -
    -#include 
    -
    -static SYSCTL_NODE(_debug, OID_AUTO, xfs, CTLFLAG_RD, 0, "XFS debug options");
    -
    -static int verbosity = 10;
    -SYSCTL_INT(_debug_xfs, OID_AUTO, verbosity, CTLFLAG_RW, &verbosity, 0, "");
    -
    -#ifdef DEBUG
    -
    -static int doass = 1;
    -SYSCTL_INT(_debug_xfs, OID_AUTO, assert, CTLFLAG_RW, &doass, 0, "");
    -
    -void
    -assfail(char *a, char *f, int l)
    -{
    -	if (doass == 0) return;
    -	panic("XFS assertion failed: %s, file: %s, line: %d\n", a, f, l);
    -}
    -
    -int
    -get_thread_id(void)
    -{
    -	return curthread->td_proc->p_pid;
    -}
    -
    -#endif
    -
    -void
    -cmn_err(register int level, char *fmt, ...)
    -{
    -	char    *fp = fmt;
    -	char    message[256];
    -	va_list ap;
    -
    -	if (verbosity < level)
    -		return;
    -
    -	va_start(ap, fmt);
    -	if (*fmt == '!') fp++;
    -	vsprintf(message, fp, ap);
    -	printf("%s\n", message);
    -	va_end(ap);
    -}
    -
    -
    -void
    -icmn_err(register int level, char *fmt, va_list ap)
    -{ 
    -	char	message[256];
    -
    -	if (verbosity < level)
    -		return;
    -
    -	vsprintf(message, fmt, ap);
    -	printf("cmn_err level %d %s\n",level, message);
    -}
    -
    diff --git a/sys/gnu/fs/xfs/FreeBSD/support/debug.h b/sys/gnu/fs/xfs/FreeBSD/support/debug.h
    deleted file mode 100644
    index 816a717c134..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/support/debug.h
    +++ /dev/null
    @@ -1,79 +0,0 @@
    -/*
    - * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
    - * 
    - * This program is free software; you can redistribute it and/or modify it
    - * under the terms of version 2 of the GNU General Public License as
    - * published by the Free Software Foundation.
    - * 
    - * This program is distributed in the hope that it would be useful, but
    - * WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    - * 
    - * Further, this software is distributed without any warranty that it is
    - * free of the rightful claim of any third person regarding infringement
    - * or the like.  Any license provided herein, whether implied or
    - * otherwise, applies only to this software file.  Patent licenses, if
    - * any, provided herein do not apply to combinations of this program with
    - * other software, or any other product whatsoever.
    - * 
    - * You should have received a copy of the GNU General Public License along
    - * with this program; if not, write the Free Software Foundation, Inc., 59
    - * Temple Place - Suite 330, Boston MA 02111-1307, USA.
    - * 
    - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
    - * Mountain View, CA  94043, or:
    - * 
    - * http://www.sgi.com 
    - * 
    - * For further information regarding this notice, see: 
    - * 
    - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
    - */
    -#ifndef	__XFS_SUPPORT_DEBUG_H__
    -#define	__XFS_SUPPORT_DEBUG_H__
    -
    -#include  
    -
    -#define CE_DEBUG        7               /* debug        */
    -#define CE_CONT         6               /* continuation */
    -#define CE_NOTE         5               /* notice       */
    -#define CE_WARN         4               /* warning      */
    -#define CE_ALERT        1               /* alert        */
    -#define CE_PANIC        0               /* panic        */
    -
    -extern void icmn_err(int, char *, va_list);
    -extern void cmn_err(int, char *, ...);
    -
    -#define prdev(fmt,targ,args...) \
    -	printf("Device %s - " fmt "\n", XFS_BUFTARG_NAME(targ), ## args)
    -
    -#ifndef STATIC
    -# define STATIC static
    -#endif
    -
    -#if defined(INVARIANTS)
    -# ifndef DEBUG
    -#  define DEBUG
    -# endif
    -#endif
    -
    -#if defined(DEBUG)
    -# ifdef lint
    -#  define ASSERT(EX) 	((void)0) /* avoid "constant in conditional" babble */
    -# else
    -#  define ASSERT(EX) ((EX)?((void)0):assfail(#EX, __FILE__, __LINE__))
    -# endif	/* lint */
    -#else /* !DEBUG */
    -# define ASSERT(x)	((void)0)
    -#endif /* !DEBUG */
    -
    -#ifdef DEBUG	
    -extern void assfail(char *, char *, int);
    -extern int get_thread_id(void);
    -#else
    -#define assfail(a, b, c)	((void)0)
    -#endif
    -
    -#define ASSERT_ALWAYS(EX)  ((EX)?((void)0):assfail(#EX, __FILE__, __LINE__))
    -
    -#endif  /* __XFS_SUPPORT_DEBUG_H__ */
    diff --git a/sys/gnu/fs/xfs/FreeBSD/support/kdb.c b/sys/gnu/fs/xfs/FreeBSD/support/kdb.c
    deleted file mode 100644
    index b133dfe5f35..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/support/kdb.c
    +++ /dev/null
    @@ -1,62 +0,0 @@
    -#include 
    -#include 
    -#include 
    -
    -#include 
    -
    -#include "opt_ddb.h"
    -#ifdef DDB
    -#include 
    -#endif
    -
    -#include 
    -
    -#ifdef DDB
    -DB_FUNC(xfs, xfs_ddb_cmd, db_cmd_table, CS_MORE, NULL)
    -{
    -	db_error("No commands registered.\n");
    -}
    -#endif
    -
    -int
    -kdb_register(char *cmd, kdb_func_t func, char *usage, char *help, short minlen)
    -{
    -	return 0;
    -}
    -
    -int
    -kdb_unregister(char *cmd)
    -{
    -	return 0;
    -}
    -
    -int
    -kdbgetaddrarg(int argc, const char **argv, int *nextarg,
    -    kdb_machreg_t *value,  long *offset, char **name, struct pt_regs *regs)
    -{
    -	return 0;
    -}
    -
    -int
    -kdbnearsym(unsigned long addr, kdb_symtab_t *symtab)
    -
    -{
    -	return 0;
    -}
    -
    -void
    -kdb_printf(const char *fmt, ...)
    -{
    -}
    -
    -int
    -kdb_getarea_size(void *res, unsigned long addr, size_t size)
    -{
    -	return 0;
    -}
    -
    -int
    -kdb_putarea_size(unsigned long addr, void *res, size_t size)
    -{
    -	return 0;
    -}
    diff --git a/sys/gnu/fs/xfs/FreeBSD/support/kdb.h b/sys/gnu/fs/xfs/FreeBSD/support/kdb.h
    deleted file mode 100644
    index d85bd6de763..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/support/kdb.h
    +++ /dev/null
    @@ -1,44 +0,0 @@
    -#ifndef __XFS_SUPPORT_KGDB_H__
    -#define __XFS_SUPPORT_KGDB_H__
    -
    -#define	KDB_ARGCOUNT	EINVAL
    -
    -struct pt_regs
    -{
    -	int	dummy;
    -};
    -
    -#define	MODULE_AUTHOR(s)	static char __module_author[] = s;
    -#define	MODULE_DESCRIPTION(s)	static char __module_description[] = s;
    -#define	MODULE_LICENSE(s)	static char __module_license[] = s
    -
    -
    -typedef int (*kdb_func_t)(int, const char **, const char **, struct pt_regs *);
    -typedef register_t kdb_machreg_t;
    -
    -/*
    - * Symbol table format.
    - */
    -typedef struct __ksymtab {
    -	unsigned long value;	/* Address of symbol */
    -	const char *sym_name;	/* Full symbol name, including any version */   
    -	unsigned long sym_start;
    -	unsigned long sym_end;
    -} kdb_symtab_t;
    -
    -extern int	kdb_register(char *, kdb_func_t, char *, char *, short);
    -extern int	kdb_unregister(char *);
    -
    -extern int	kdbgetaddrarg(int, const char**, int*, kdb_machreg_t *,
    -			long *, char **, struct pt_regs *);
    -extern int	kdbnearsym(unsigned long, kdb_symtab_t *);
    -extern void	kdb_printf(const char *,...)
    -			__attribute__ ((format (printf, 1, 2)));
    -
    -extern int	kdb_getarea_size(void *, unsigned long, size_t);
    -extern int	kdb_putarea_size(unsigned long, void *, size_t);
    -
    -#define kdb_getarea(x,addr)     kdb_getarea_size(&(x), addr, sizeof((x)))
    -#define kdb_putarea(addr,x)     kdb_putarea_size(addr, &(x), sizeof((x)))
    -
    -#endif /* __XFS_SUPPORT_KGDB_H__ */
    diff --git a/sys/gnu/fs/xfs/FreeBSD/support/kmem.c b/sys/gnu/fs/xfs/FreeBSD/support/kmem.c
    deleted file mode 100644
    index c98e4bcb4d7..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/support/kmem.c
    +++ /dev/null
    @@ -1,3 +0,0 @@
    -#include 
    -
    -MALLOC_DEFINE(M_XFS, "XFSALLOC", "XFS memory");
    diff --git a/sys/gnu/fs/xfs/FreeBSD/support/kmem.h b/sys/gnu/fs/xfs/FreeBSD/support/kmem.h
    deleted file mode 100644
    index 4976008f649..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/support/kmem.h
    +++ /dev/null
    @@ -1,86 +0,0 @@
    -#ifndef __XFS_SUPPORT_KMEM_H__
    -#define __XFS_SUPPORT_KMEM_H__
    -
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -
    -typedef unsigned long xfs_pflags_t;
    -
    -#define PFLAGS_TEST_NOIO()              0
    -#define PFLAGS_TEST_FSTRANS()           0
    -
    -#define PFLAGS_SET_NOIO(STATEP) do {    \
    -} while (0)
    -
    -#define PFLAGS_SET_FSTRANS(STATEP) do { \
    -} while (0)
    -
    -#define PFLAGS_RESTORE(STATEP) do {     \
    -} while (0)
    -
    -#define PFLAGS_DUP(OSTATEP, NSTATEP) do { \
    -} while (0)
    -
    -/* Restore the PF_FSTRANS state to what was saved in STATEP */
    -#define PFLAGS_RESTORE_FSTRANS(STATEP) do {     		\
    -} while (0)
    -
    -/*
    - * memory management routines
    - */
    -#define KM_SLEEP	M_WAITOK
    -#define KM_NOSLEEP	M_NOWAIT
    -#define KM_NOFS		M_WAITOK
    -#define KM_MAYFAIL	0
    -
    -#define kmem_zone	uma_zone
    -
    -typedef struct uma_zone kmem_zone_t;
    -typedef struct uma_zone xfs_zone_t;
    -
    -
    -#define KM_ZONE_HWALIGN	0
    -#define KM_ZONE_RECLAIM	0
    -#define KM_ZONE_SPREAD	0
    -
    -#define kmem_zone_init(len, name)		\
    -	uma_zcreate(name, len, NULL, NULL, NULL, NULL, 0, 0)
    -
    -static inline kmem_zone_t *
    -kmem_zone_init_flags(int size, char *zone_name, unsigned long flags,
    -		     void (*construct)(void *, kmem_zone_t *, unsigned long))
    -{
    -	return uma_zcreate(zone_name, size, NULL, NULL, NULL, NULL, 0, 0);
    -}
    -
    -#define kmem_zone_free(zone, ptr)		\
    -	uma_zfree(zone, ptr)
    -
    -static inline void
    -kmem_zone_destroy(kmem_zone_t *zone)
    -{
    -	uma_zdestroy(zone);
    -}
    -
    -#define kmem_zone_alloc(zone, flg)		\
    -	uma_zalloc(zone, flg)
    -#define kmem_zone_zalloc(zone, flg)		\
    -	uma_zalloc(zone, (flg) | M_ZERO)
    -
    -#define	kmem_alloc(len, flg)			\
    -	malloc(len, M_XFS, flg)
    -#define	kmem_zalloc(len, flg)			\
    -	malloc(len, M_XFS, (flg) | M_ZERO)
    -#define kmem_free(ptr, size)			\
    -	free(ptr, M_XFS)
    -#define kmem_realloc(ptr, nsize, osize, flg)	\
    -	realloc(ptr, nsize, M_XFS, flg)
    -
    -MALLOC_DECLARE(M_XFS);
    -
    -#endif /* __XFS_SUPPORT_KMEM_H__ */
    diff --git a/sys/gnu/fs/xfs/FreeBSD/support/ktrace.c b/sys/gnu/fs/xfs/FreeBSD/support/ktrace.c
    deleted file mode 100644
    index 45a42bfbb32..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/support/ktrace.c
    +++ /dev/null
    @@ -1,334 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include 
    -
    -static kmem_zone_t *ktrace_hdr_zone;
    -static kmem_zone_t *ktrace_ent_zone;
    -static int          ktrace_zentries;
    -static struct mtx   wrap_lock;
    -
    -void
    -ktrace_init(int zentries)
    -{
    -	ktrace_zentries = zentries;
    -
    -	ktrace_hdr_zone = kmem_zone_init(sizeof(ktrace_t),
    -					"ktrace_hdr");
    -	ASSERT(ktrace_hdr_zone);
    -
    -	ktrace_ent_zone = kmem_zone_init(ktrace_zentries
    -					* sizeof(ktrace_entry_t),
    -					"ktrace_ent");
    -	ASSERT(ktrace_ent_zone);
    -
    -	mtx_init(&wrap_lock, "xfsktr", NULL, MTX_DEF);
    -}
    -
    -void
    -ktrace_uninit(void)
    -{
    -	kmem_zone_destroy(ktrace_hdr_zone);
    -	kmem_zone_destroy(ktrace_ent_zone);
    -
    -	mtx_destroy(&wrap_lock);
    -}
    -
    -/*
    - * ktrace_alloc()
    - *
    - * Allocate a ktrace header and enough buffering for the given
    - * number of entries.
    - */
    -ktrace_t *
    -ktrace_alloc(int nentries, int sleep)
    -{
    -	ktrace_t        *ktp;
    -	ktrace_entry_t  *ktep;
    -
    -	ktp = (ktrace_t*)kmem_zone_alloc(ktrace_hdr_zone, sleep);
    -
    -	if (ktp == (ktrace_t*)NULL) {
    -		/*
    -		 * KM_SLEEP callers don't expect failure.
    -		 */
    -		if (sleep & KM_SLEEP)
    -			panic("ktrace_alloc: NULL memory on KM_SLEEP request!");
    -
    -		return NULL;
    -	}
    -
    -	/*
    -	 * Special treatment for buffers with the ktrace_zentries entries
    -	 */
    -	if (nentries == ktrace_zentries) {
    -		ktep = (ktrace_entry_t*)kmem_zone_zalloc(ktrace_ent_zone,
    -							    sleep);
    -	} else {
    -		ktep = (ktrace_entry_t*)kmem_zalloc((nentries * sizeof(*ktep)),
    -							    sleep);
    -	}
    -
    -	if (ktep == NULL) {
    -		/*
    -		 * KM_SLEEP callers don't expect failure.
    -		 */
    -		if (sleep & KM_SLEEP)
    -			panic("ktrace_alloc: NULL memory on KM_SLEEP request!");
    -
    -		kmem_free(ktp, sizeof(*ktp));
    -
    -		return NULL;
    -	}
    -
    -	spinlock_init(&(ktp->kt_lock), "kt_lock");
    -
    -	ktp->kt_entries  = ktep;
    -	ktp->kt_nentries = nentries;
    -	ktp->kt_index    = 0;
    -	ktp->kt_rollover = 0;
    -	return ktp;
    -}
    -
    -
    -/*
    - * ktrace_free()
    - *
    - * Free up the ktrace header and buffer.  It is up to the caller
    - * to ensure that no-one is referencing it.
    - */
    -void
    -ktrace_free(ktrace_t *ktp)
    -{
    -	int     entries_size;
    -
    -	if (ktp == (ktrace_t *)NULL)
    -		return;
    -
    -	spinlock_destroy(&ktp->kt_lock);
    -
    -	/*
    -	 * Special treatment for the Vnode trace buffer.
    -	 */
    -	if (ktp->kt_nentries == ktrace_zentries) {
    -		kmem_zone_free(ktrace_ent_zone, ktp->kt_entries);
    -	} else {
    -		entries_size = (int)(ktp->kt_nentries * sizeof(ktrace_entry_t));
    -
    -		kmem_free(ktp->kt_entries, entries_size);
    -	}
    -
    -	kmem_zone_free(ktrace_hdr_zone, ktp);
    -}
    -
    -
    -/*
    - * Enter the given values into the "next" entry in the trace buffer.
    - * kt_index is always the index of the next entry to be filled.
    - */
    -void
    -ktrace_enter(
    -	ktrace_t        *ktp,
    -	void            *val0,
    -	void            *val1,
    -	void            *val2,
    -	void            *val3,
    -	void            *val4,
    -	void            *val5,
    -	void            *val6,
    -	void            *val7,
    -	void            *val8,
    -	void            *val9,
    -	void            *val10,
    -	void            *val11,
    -	void            *val12,
    -	void            *val13,
    -	void            *val14,
    -	void            *val15)
    -{
    -	int             index;
    -	ktrace_entry_t  *ktep;
    -
    -	ASSERT(ktp != NULL);
    -
    -	/*
    -	 * Grab an entry by pushing the index up to the next one.
    -	 */
    -	mtx_lock(&wrap_lock);
    -	index = ktp->kt_index;
    -	if (++ktp->kt_index == ktp->kt_nentries)
    -		ktp->kt_index = 0;
    -	mtx_unlock(&wrap_lock);
    -
    -	if (!ktp->kt_rollover && index == ktp->kt_nentries - 1)
    -		ktp->kt_rollover = 1;
    -
    -	ASSERT((index >= 0) && (index < ktp->kt_nentries));
    -
    -	ktep = &(ktp->kt_entries[index]);
    -
    -	ktep->val[0]  = val0;
    -	ktep->val[1]  = val1;
    -	ktep->val[2]  = val2;
    -	ktep->val[3]  = val3;
    -	ktep->val[4]  = val4;
    -	ktep->val[5]  = val5;
    -	ktep->val[6]  = val6;
    -	ktep->val[7]  = val7;
    -	ktep->val[8]  = val8;
    -	ktep->val[9]  = val9;
    -	ktep->val[10] = val10;
    -	ktep->val[11] = val11;
    -	ktep->val[12] = val12;
    -	ktep->val[13] = val13;
    -	ktep->val[14] = val14;
    -	ktep->val[15] = val15;
    -}
    -
    -/*
    - * Return the number of entries in the trace buffer.
    - */
    -int
    -ktrace_nentries(
    -	ktrace_t        *ktp)
    -{
    -	if (ktp == NULL) {
    -		return 0;
    -	}
    -
    -	return (ktp->kt_rollover ? ktp->kt_nentries : ktp->kt_index);
    -}
    -
    -/*
    - * ktrace_first()
    - *
    - * This is used to find the start of the trace buffer.
    - * In conjunction with ktrace_next() it can be used to
    - * iterate through the entire trace buffer.  This code does
    - * not do any locking because it is assumed that it is called
    - * from the debugger.
    - *
    - * The caller must pass in a pointer to a ktrace_snap
    - * structure in which we will keep some state used to
    - * iterate through the buffer.  This state must not touched
    - * by any code outside of this module.
    - */
    -ktrace_entry_t *
    -ktrace_first(ktrace_t   *ktp, ktrace_snap_t     *ktsp)
    -{
    -	ktrace_entry_t  *ktep;
    -	int             index;
    -	int             nentries;
    -
    -	if (ktp->kt_rollover)
    -		index = ktp->kt_index;
    -	else
    -		index = 0;
    -
    -	ktsp->ks_start = index;
    -	ktep = &(ktp->kt_entries[index]);
    -
    -	nentries = ktrace_nentries(ktp);
    -	index++;
    -	if (index < nentries) {
    -		ktsp->ks_index = index;
    -	} else {
    -		ktsp->ks_index = 0;
    -		if (index > nentries)
    -			ktep = NULL;
    -	}
    -	return ktep;
    -}
    -
    -/*
    - * ktrace_next()
    - *
    - * This is used to iterate through the entries of the given
    - * trace buffer.  The caller must pass in the ktrace_snap_t
    - * structure initialized by ktrace_first().  The return value
    - * will be either a pointer to the next ktrace_entry or NULL
    - * if all of the entries have been traversed.
    - */
    -ktrace_entry_t *
    -ktrace_next(
    -	ktrace_t        *ktp,
    -	ktrace_snap_t   *ktsp)
    -{
    -	int             index;
    -	ktrace_entry_t  *ktep;
    -
    -	index = ktsp->ks_index;
    -	if (index == ktsp->ks_start) {
    -		ktep = NULL;
    -	} else {
    -		ktep = &ktp->kt_entries[index];
    -	}
    -
    -	index++;
    -	if (index == ktrace_nentries(ktp)) {
    -		ktsp->ks_index = 0;
    -	} else {
    -		ktsp->ks_index = index;
    -	}
    -
    -	return ktep;
    -}
    -
    -/*
    - * ktrace_skip()
    - *
    - * Skip the next "count" entries and return the entry after that.
    - * Return NULL if this causes us to iterate past the beginning again.
    - */
    -ktrace_entry_t *
    -ktrace_skip(
    -	ktrace_t        *ktp,
    -	int             count,
    -	ktrace_snap_t   *ktsp)
    -{
    -	int             index;
    -	int             new_index;
    -	ktrace_entry_t  *ktep;
    -	int             nentries = ktrace_nentries(ktp);
    -
    -	index = ktsp->ks_index;
    -	new_index = index + count;
    -	while (new_index >= nentries) {
    -		new_index -= nentries;
    -	}
    -	if (index == ktsp->ks_start) {
    -		/*
    -		 * We've iterated around to the start, so we're done.
    -		 */
    -		ktep = NULL;
    -	} else if ((new_index < index) && (index < ktsp->ks_index)) {
    -		/*
    -		 * We've skipped past the start again, so we're done.
    -		 */
    -		ktep = NULL;
    -		ktsp->ks_index = ktsp->ks_start;
    -	} else {
    -		ktep = &(ktp->kt_entries[new_index]);
    -		new_index++;
    -		if (new_index == nentries) {
    -			ktsp->ks_index = 0;
    -		} else {
    -			ktsp->ks_index = new_index;
    -		}
    -	}
    -	return ktep;
    -}
    diff --git a/sys/gnu/fs/xfs/FreeBSD/support/ktrace.h b/sys/gnu/fs/xfs/FreeBSD/support/ktrace.h
    deleted file mode 100644
    index b566ef8fa75..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/support/ktrace.h
    +++ /dev/null
    @@ -1,101 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or modify it
    - * under the terms of version 2 of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful, but
    - * WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    - *
    - * Further, this software is distributed without any warranty that it is
    - * free of the rightful claim of any third person regarding infringement
    - * or the like.  Any license provided herein, whether implied or
    - * otherwise, applies only to this software file.  Patent licenses, if
    - * any, provided herein do not apply to combinations of this program with
    - * other software, or any other product whatsoever.
    - *
    - * You should have received a copy of the GNU General Public License along
    - * with this program; if not, write the Free Software Foundation, Inc., 59
    - * Temple Place - Suite 330, Boston MA 02111-1307, USA.
    - *
    - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
    - * Mountain View, CA  94043, or:
    - *
    - * http://www.sgi.com
    - *
    - * For further information regarding this notice, see:
    - *
    - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
    - */
    -#ifndef __XFS_SUPPORT_KTRACE_H__
    -#define __XFS_SUPPORT_KTRACE_H__
    -
    -#include 
    -
    -/*
    - * Trace buffer entry structure.
    - */
    -typedef struct ktrace_entry {
    -	void	*val[16];
    -} ktrace_entry_t;
    -
    -/*
    - * Trace buffer header structure.
    - */
    -typedef struct ktrace {
    -	lock_t		kt_lock;	/* mutex to guard counters */
    -	int		kt_nentries;	/* number of entries in trace buf */
    -	int		kt_index;	/* current index in entries */
    -	int		kt_rollover;
    -	ktrace_entry_t	*kt_entries;	/* buffer of entries */
    -} ktrace_t;
    -
    -/*
    - * Trace buffer snapshot structure.
    - */
    -typedef struct ktrace_snap {
    -	int		ks_start;	/* kt_index at time of snap */
    -	int		ks_index;	/* current index */
    -} ktrace_snap_t;
    -
    -
    -#ifdef CONFIG_XFS_TRACE
    -
    -extern void ktrace_init(int zentries);
    -extern void ktrace_uninit(void);
    -
    -extern ktrace_t *ktrace_alloc(int, int);
    -extern void ktrace_free(ktrace_t *);
    -
    -extern void ktrace_enter(
    -	ktrace_t	*,
    -	void		*,
    -	void		*,
    -	void		*,
    -	void		*,
    -	void		*,
    -	void		*,
    -	void		*,
    -	void		*,
    -	void		*,
    -	void		*,
    -	void		*,
    -	void		*,
    -	void		*,
    -	void		*,
    -	void		*,
    -	void		*);
    -
    -extern ktrace_entry_t   *ktrace_first(ktrace_t *, ktrace_snap_t *);
    -extern int              ktrace_nentries(ktrace_t *);
    -extern ktrace_entry_t   *ktrace_next(ktrace_t *, ktrace_snap_t *);
    -extern ktrace_entry_t   *ktrace_skip(ktrace_t *, int, ktrace_snap_t *);
    -
    -#else
    -#define ktrace_init(x)	do { } while (0)
    -#define ktrace_uninit()	do { } while (0)
    -#endif	/* CONFIG_XFS_TRACE */
    -
    -#endif	/* __XFS_SUPPORT_KTRACE_H__ */
    diff --git a/sys/gnu/fs/xfs/FreeBSD/support/move.h b/sys/gnu/fs/xfs/FreeBSD/support/move.h
    deleted file mode 100644
    index 856ec03f5ae..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/support/move.h
    +++ /dev/null
    @@ -1,48 +0,0 @@
    -/*
    - * Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or modify it
    - * under the terms of version 2 of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful, but
    - * WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    - *
    - * Further, this software is distributed without any warranty that it is
    - * free of the rightful claim of any third person regarding infringement
    - * or the like.	 Any license provided herein, whether implied or
    - * otherwise, applies only to this software file.  Patent licenses, if
    - * any, provided herein do not apply to combinations of this program with
    - * other software, or any other product whatsoever.
    - *
    - * You should have received a copy of the GNU General Public License along
    - * with this program; if not, write the Free Software Foundation, Inc., 59
    - * Temple Place - Suite 330, Boston MA 02111-1307, USA.
    - *
    - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
    - * Mountain View, CA  94043, or:
    - *
    - * http://www.sgi.com
    - *
    - * For further information regarding this notice, see:
    - *
    - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
    - */
    -
    -#ifndef __XFS_SUPPORT_MOVE_H__
    -#define __XFS_SUPPORT_MOVE_H__
    -
    -#include 
    -
    -typedef struct iovec iovec_t;
    -typedef struct uio   uio_t;
    -
    -static __inline__ int
    -uio_read(void *buf, int howmuch, struct uio *uiop)
    -{
    -	uiop->uio_rw = UIO_READ;
    -        return uiomove(buf,howmuch,uiop);
    -}
    -
    -#endif	/* __XFS_SUPPORT_MOVE_H__ */
    diff --git a/sys/gnu/fs/xfs/FreeBSD/support/mrlock.c b/sys/gnu/fs/xfs/FreeBSD/support/mrlock.c
    deleted file mode 100644
    index 5955f991bb8..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/support/mrlock.c
    +++ /dev/null
    @@ -1,14 +0,0 @@
    -#include 
    -#include 
    -#include 
    -#include 
    -
    -int
    -ismrlocked(mrlock_t *mrp, int type)
    -{
    -
    -	sx_assert(mrp, SX_LOCKED);
    -	if (type == MR_UPDATE)
    -		return sx_xlocked(mrp);
    -	return 1;
    -}
    diff --git a/sys/gnu/fs/xfs/FreeBSD/support/mrlock.h b/sys/gnu/fs/xfs/FreeBSD/support/mrlock.h
    deleted file mode 100644
    index b41efc57dc4..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/support/mrlock.h
    +++ /dev/null
    @@ -1,41 +0,0 @@
    -#ifndef __XFS_SUPPORT_MRLOCK_H__
    -#define __XFS_SUPPORT_MRLOCK_H__
    -
    -#include 
    -#include 
    -#include 
    -#include 
    -
    -/*
    - * Implement mrlocks on FreeBSD that work for XFS.
    - * Map mrlock functions to corresponding equivalents in
    - * sx.
    - */
    -typedef struct sx mrlock_t;
    -
    -#define MR_ACCESS	1
    -#define MR_UPDATE	2
    -
    -/*
    - * Compatibility defines, not really used
    - */
    -#define MRLOCK_BARRIER		0x1
    -#define MRLOCK_ALLOW_EQUAL_PRI	0x8
    -
    -#define mrlock_init(lock, type, name, seq) sx_init(lock, name)
    -#define mrtryaccess(lock)	sx_try_slock(lock)
    -#define mrtryupdate(lock)	sx_try_xlock(lock)
    -#define mraccess(lock)		sx_slock(lock)
    -#define mrupdate(lock)		sx_xlock(lock)
    -#define mrdemote(lock)		sx_downgrade(lock)
    -#define mrunlock(lock)		sx_unlock(lock)
    -
    -#define mrfree(lock) do {		\
    -	if (sx_xlocked(lock))		\
    -		sx_xunlock(lock);	\
    -	sx_destroy(lock);		\
    -} while (0)
    -
    -int ismrlocked(mrlock_t *mrp, int type);
    -
    -#endif /* __XFS_SUPPORT_MRLOCK_H__ */
    diff --git a/sys/gnu/fs/xfs/FreeBSD/support/mutex.h b/sys/gnu/fs/xfs/FreeBSD/support/mutex.h
    deleted file mode 100644
    index d9b89b3adcf..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/support/mutex.h
    +++ /dev/null
    @@ -1,29 +0,0 @@
    -#ifndef __XFS_SUPPORT_MUTEX_H__
    -#define __XFS_SUPPORT_MUTEX_H__
    -
    -#include 
    -#include 
    -#include 
    -#include 
    -
    -/*
    - * Map the mutex'es from IRIX to FreeBSD. Irix holds mutexes across
    - * sleeps, so on FreeBSD we have a choice of sema, sx or lockmgr
    - * to use as a underlining implemenation. Go with sx always locked
    - * in exclusive mode for now as it gets all the benefits of witness
    - * checking.
    - */
    -typedef struct sx mutex_t;
    -
    -#define mutex_init(lock, type, name)	sx_init(lock, name)
    -#define mutex_lock(lock, num)		sx_xlock(lock)
    -#define mutex_trylock(lock)	        sx_try_xlock(lock)
    -#define mutex_unlock(lock)		sx_xunlock(lock)
    -#define mutex_destroy(lock)		sx_destroy(lock)
    -
    -/*
    - * Type for mutex_init()
    - */
    -#define MUTEX_DEFAULT		0
    -
    -#endif /* __XFS_SUPPORT_MUTEX_H__ */
    diff --git a/sys/gnu/fs/xfs/FreeBSD/support/rwlock.h b/sys/gnu/fs/xfs/FreeBSD/support/rwlock.h
    deleted file mode 100644
    index bfbec23709e..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/support/rwlock.h
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -#ifndef __XFS_SUPPORT_RWLOCK_H__
    -#define __XFS_SUPPORT_RWLOCK_H__
    -
    -#include 
    -#include 
    -#include 
    -#include 
    -
    -typedef	struct sx rwlock_t;
    -typedef int    wait_queue_head_t;
    -
    -#define	rwlock_init(lock)	sx_init(lock, "rwlock")
    -#define	rwlock_destroy(lock)	sx_destroy(lock)
    -#define	read_lock(lock)		sx_slock(lock)
    -#define	read_unlock(lock)	sx_sunlock(lock)
    -#define	write_lock(lock)	sx_xlock(lock)
    -#define write_trylock(lock)	sx_try_xlock(lock)
    -#define	write_unlock(lock)	sx_xunlock(lock)
    -#define	rwlock_trypromote(lock)	sx_try_upgrade(lock)
    -#define	rwlock_demote(lock)	sx_downgrade(lock)
    -
    -
    -#endif /* __XFS_SUPPORT_RWLOCK_H__ */
    diff --git a/sys/gnu/fs/xfs/FreeBSD/support/rwsem.h b/sys/gnu/fs/xfs/FreeBSD/support/rwsem.h
    deleted file mode 100644
    index bb972327bb7..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/support/rwsem.h
    +++ /dev/null
    @@ -1,21 +0,0 @@
    -#ifndef __XFS_SUPPORT_RWSEM_H__
    -#define __XFS_SUPPORT_RWSEM_H__
    -
    -#include 
    -#include 
    -#include 
    -#include 
    -
    -#define rw_semaphore	sx
    -
    -#define	init_rwsem(sem)		sx_init(sem, "rwsem")
    -#define	free_rwsem(sem)		sx_destroy(sem)
    -#define	down_read(sem)		sx_slock(sem)
    -#define	down_read_trylock(sem)	sx_try_slock(sem)
    -#define	down_write(sem)		sx_xlock(sem)
    -#define	down_write_trylock(sem)	sx_try_xlock(sem)
    -#define	up_read(sem)		sx_sunlock(sem)
    -#define	up_write(sem)		sx_xunlock(sem)
    -#define	downgrade_write(sem)	sx_downgrade(sem)
    -
    -#endif /* __XFS_SUPPORT_RWSEM_H__ */
    diff --git a/sys/gnu/fs/xfs/FreeBSD/support/sema.h b/sys/gnu/fs/xfs/FreeBSD/support/sema.h
    deleted file mode 100644
    index db7795b93d2..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/support/sema.h
    +++ /dev/null
    @@ -1,53 +0,0 @@
    -/*-
    - * Copyright (c) 1992, 1993
    - *	The Regents of the University of California.  All rights reserved.
    - *
    - * Redistribution and use in source and binary forms, with or without
    - * modification, are permitted provided that the following conditions
    - * are met:
    - * 1. Redistributions of source code must retain the above copyright
    - *    notice, this list of conditions and the following disclaimer.
    - * 2. Redistributions in binary form must reproduce the above copyright
    - *    notice, this list of conditions and the following disclaimer in the
    - *    documentation and/or other materials provided with the distribution.
    - * 3. All advertising materials mentioning features or use of this software
    - *    must display the following acknowledgement:
    - *	This product includes software developed by the University of
    - *	California, Berkeley and its contributors.
    - * 4. Neither the name of the University nor the names of its contributors
    - *    may be used to endorse or promote products derived from this software
    - *    without specific prior written permission.
    - *
    - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    - * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
    - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    - * SUCH DAMAGE.
    - */
    -
    -#ifndef __XFS_SUPPORT_SEMA_H__
    -#define __XFS_SUPPORT_SEMA_H__
    -
    -#include 
    -
    -/*
    - * sema_t structure just maps to struct sema in FreeBSD kernel.
    - */
    -
    -typedef struct sema sema_t;
    -
    -#define init_sema(sp, val, c, d)	sema_init(sp, val, c)
    -#define initnsema(sp, val, name)	sema_init(sp, val, name)
    -#define psema(sp, b)			sema_wait(sp)
    -#define vsema(sp)			sema_post(sp)
    -#define valusema(sp)			sema_value(sp)
    -#define freesema(sp)			sema_destroy(sp)
    -#define cpsema(sp)			sema_trywait(sp)
    -
    -#endif /* __XFS_SUPPORT_SEMA_H__ */
    diff --git a/sys/gnu/fs/xfs/FreeBSD/support/spin.h b/sys/gnu/fs/xfs/FreeBSD/support/spin.h
    deleted file mode 100644
    index e337e32f8f6..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/support/spin.h
    +++ /dev/null
    @@ -1,42 +0,0 @@
    -#ifndef __XFS_SUPPORT_SPIN_H__
    -#define __XFS_SUPPORT_SPIN_H__
    -
    -#include 
    -#include 
    -#include 
    -#include 
    -
    -#define SPLDECL(s)	register_t s
    -
    -/*
    - * Map the spinlocks from IRIX to FreeBSD
    - */
    -#define spinlock_init(lock, name)	mtx_init(lock, name, NULL, MTX_DEF)
    -#define spinlock_destroy(lock)		mtx_destroy(lock)
    -
    -/*
    - * Map lock_t from IRIX to FreeBSD mutexes
    - */
    -typedef struct mtx lock_t;
    -
    -#define nested_spinunlock(lock)		mtx_unlock(lock)
    -#define nested_spinlock(lock)		mtx_lock(lock)
    -#define nested_spintrylock(lock)	mtx_trylock(lock)
    -
    -#define spin_lock(lock)			mtx_lock(lock)
    -#define spin_unlock(lock)		mtx_unlock(lock)
    -
    -#if LOCK_DEBUG > 0
    -#define mutex_spinlock(lock)		(spin_lock(lock),0)
    -#else
    -static __inline register_t
    -mutex_spinlock(lock_t *lock)		{ mtx_lock(lock); return 0; }
    -#endif
    -
    -#define mutex_spinunlock(lock, s) \
    -	do { \
    -		spin_unlock(lock); \
    -		if (s != 0) {} \
    -	} while (0)
    -
    -#endif /* __XFS_SUPPORT_SPIN_H__ */
    diff --git a/sys/gnu/fs/xfs/FreeBSD/support/support.h b/sys/gnu/fs/xfs/FreeBSD/support/support.h
    deleted file mode 100644
    index d7804fa8b26..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/support/support.h
    +++ /dev/null
    @@ -1,49 +0,0 @@
    -/*
    - * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
    - * 
    - * This program is free software; you can redistribute it and/or modify it
    - * under the terms of version 2 of the GNU General Public License as
    - * published by the Free Software Foundation.
    - * 
    - * This program is distributed in the hope that it would be useful, but
    - * WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    - * 
    - * Further, this software is distributed without any warranty that it is
    - * free of the rightful claim of any third person regarding infringement
    - * or the like.  Any license provided herein, whether implied or
    - * otherwise, applies only to this software file.  Patent licenses, if
    - * any, provided herein do not apply to combinations of this program with
    - * other software, or any other product whatsoever.
    - * 
    - * You should have received a copy of the GNU General Public License along
    - * with this program; if not, write the Free Software Foundation, Inc., 59
    - * Temple Place - Suite 330, Boston MA 02111-1307, USA.
    - * 
    - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
    - * Mountain View, CA  94043, or:
    - * 
    - * http://www.sgi.com 
    - * 
    - * For further information regarding this notice, see: 
    - * 
    - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
    - */
    -#ifndef __XFS_SUPPORT_H__
    -#define __XFS_SUPPORT_H__
    -
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -
    -#endif /* __XFS_SUPPORT_H__ */
    diff --git a/sys/gnu/fs/xfs/FreeBSD/support/sv.h b/sys/gnu/fs/xfs/FreeBSD/support/sv.h
    deleted file mode 100644
    index 1a378d22759..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/support/sv.h
    +++ /dev/null
    @@ -1,30 +0,0 @@
    -#ifndef __XFS_SUPPORT_SV_H__
    -#define __XFS_SUPPORT_SV_H__
    -
    -#include 
    -
    -/* 
    - * Synchronisation variables 
    - *
    - * parameters "pri", "svf" and "rts" are not (yet?) implemented
    - *
    - */
    -
    -typedef struct cv sv_t;
    -
    -#define init_sv(sv,type,name,flag)	cv_init(sv, name)
    -#define sv_init(sv,flag,name)		cv_init(sv, name)
    -/* sv_wait should exit with lock unlocked */
    -#define sv_wait(sv, pri, lock, spl)	cv_wait_unlock(sv, lock)
    -#define sv_wait_sig(sv, pri, lock, spl) cv_wait_sig_nolock(sv, lock)
    -#define sv_signal(sv)			cv_signal(sv)
    -#define sv_broadcast(sv)		cv_broadcast(sv)
    -#define sv_destroy(sv)			cv_destroy(sv)
    -
    -#define SV_FIFO         0x0             /* sv_t is FIFO type */
    -#define SV_LIFO         0x2             /* sv_t is LIFO type */
    -#define SV_PRIO         0x4             /* sv_t is PRIO type */
    -#define SV_KEYED        0x6             /* sv_t is KEYED type */
    -#define SV_DEFAULT      SV_FIFO
    -
    -#endif /* __XFS_SUPPORT_SV_H__ */
    diff --git a/sys/gnu/fs/xfs/FreeBSD/support/time.h b/sys/gnu/fs/xfs/FreeBSD/support/time.h
    deleted file mode 100644
    index 9b3a974c243..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/support/time.h
    +++ /dev/null
    @@ -1,37 +0,0 @@
    -/*
    - * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
    - * 
    - * This program is free software; you can redistribute it and/or modify it
    - * under the terms of version 2 of the GNU General Public License as
    - * published by the Free Software Foundation.
    - * 
    - * This program is distributed in the hope that it would be useful, but
    - * WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    - * 
    - * Further, this software is distributed without any warranty that it is
    - * free of the rightful claim of any third person regarding infringement
    - * or the like.  Any license provided herein, whether implied or
    - * otherwise, applies only to this software file.  Patent licenses, if
    - * any, provided herein do not apply to combinations of this program with
    - * other software, or any other product whatsoever.
    - * 
    - * You should have received a copy of the GNU General Public License along
    - * with this program; if not, write the Free Software Foundation, Inc., 59
    - * Temple Place - Suite 330, Boston MA 02111-1307, USA.
    - * 
    - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
    - * Mountain View, CA  94043, or:
    - * 
    - * http://www.sgi.com 
    - * 
    - * For further information regarding this notice, see: 
    - * 
    - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
    - */
    -#ifndef __XFS_SUPPORT_TIME_H__
    -#define __XFS_SUPPORT_TIME_H__
    -
    -#define	delay(ticks)	DELAY(ticks)
    -
    -#endif /* __XFS_SUPPORT_TIME_H__ */
    diff --git a/sys/gnu/fs/xfs/FreeBSD/support/uuid.c b/sys/gnu/fs/xfs/FreeBSD/support/uuid.c
    deleted file mode 100644
    index 55344c01419..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/support/uuid.c
    +++ /dev/null
    @@ -1,165 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or modify it
    - * under the terms of version 2 of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful, but
    - * WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    - *
    - * Further, this software is distributed without any warranty that it is
    - * free of the rightful claim of any third person regarding infringement
    - * or the like.  Any license provided herein, whether implied or
    - * otherwise, applies only to this software file.  Patent licenses, if
    - * any, provided herein do not apply to combinations of this program with
    - * other software, or any other product whatsoever.
    - *
    - * You should have received a copy of the GNU General Public License along
    - * with this program; if not, write the Free Software Foundation, Inc., 59
    - * Temple Place - Suite 330, Boston MA 02111-1307, USA.
    - *
    - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
    - * Mountain View, CA  94043, or:
    - *
    - * http://www.sgi.com
    - *
    - * For further information regarding this notice, see:
    - *
    - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
    - */
    -
    -#include 
    -#include 
    -#include 
    -#include 
    -
    -#include 
    -#include 
    -#include 
    -#include 
    -
    -static mutex_t	uuid_monitor;
    -static int	uuid_table_size;
    -static uuid_t	*uuid_table;
    -
    -void
    -uuid_init(void)
    -{
    -	mutex_init(&uuid_monitor, MUTEX_DEFAULT, "uuid_monitor");
    -}
    -
    -void
    -uuid_cleanup(void)
    -{
    -	mutex_destroy(&uuid_monitor);
    -}
    -
    -/*
    - * uuid_getnodeuniq - obtain the node unique fields of a UUID.
    - *
    - * This is not in any way a standard or condoned UUID function;
    - * it just something that's needed for user-level file handles.
    - */
    -void
    -uuid_getnodeuniq(uuid_t *uuid, int fsid [2])
    -{
    -	char	*uu = (char *)uuid;
    -
    -	/* on IRIX, this function assumes big-endian fields within
    -	 * the uuid, so we use INT_GET to get the same result on
    -	 * little-endian systems
    -	 */
    -
    -	fsid[0] = (INT_GET(*(u_int16_t*)(uu+8), ARCH_CONVERT) << 16) +
    -		   INT_GET(*(u_int16_t*)(uu+4), ARCH_CONVERT);
    -	fsid[1] =  INT_GET(*(u_int32_t*)(uu  ), ARCH_CONVERT);
    -}
    -
    -void
    -uuid_create_nil(uuid_t *uuid)
    -{
    -	memset(uuid, 0, sizeof(*uuid));
    -}
    -
    -int
    -uuid_is_nil(uuid_t *uuid)
    -{
    -	int	i;
    -	char	*cp = (char *)uuid;
    -
    -	if (uuid == NULL)
    -		return 0;
    -	/* implied check of version number here... */
    -	for (i = 0; i < sizeof *uuid; i++)
    -		if (*cp++) return 0;	/* not nil */
    -	return 1;	/* is nil */
    -}
    -
    -int
    -uuid_equal(uuid_t *uuid1, uuid_t *uuid2)
    -{
    -	return memcmp(uuid1, uuid2, sizeof(uuid_t)) ? 0 : 1;
    -}
    -
    -/*
    - * Given a 128-bit uuid, return a 64-bit value by adding the top and bottom
    - * 64-bit words.  NOTE: This function can not be changed EVER.  Although
    - * brain-dead, some applications depend on this 64-bit value remaining
    - * persistent.  Specifically, DMI vendors store the value as a persistent
    - * filehandle.
    - */
    -__uint64_t
    -uuid_hash64(uuid_t *uuid)
    -{
    -	__uint64_t	*sp = (__uint64_t *)uuid;
    -
    -	return sp[0] + sp[1];
    -}
    -
    -int
    -uuid_table_insert(uuid_t *uuid)
    -{
    -	int	i, hole;
    -
    -	mutex_lock(&uuid_monitor, PVFS);
    -	for (i = 0, hole = -1; i < uuid_table_size; i++) {
    -		if (uuid_is_nil(&uuid_table[i])) {
    -			hole = i;
    -			continue;
    -		}
    -		if (uuid_equal(uuid, &uuid_table[i])) {
    -			mutex_unlock(&uuid_monitor);
    -			return 0;
    -		}
    -	}
    -	if (hole < 0) {
    -		uuid_table = kmem_realloc(uuid_table,
    -			(uuid_table_size + 1) * sizeof(*uuid_table),
    -			uuid_table_size  * sizeof(*uuid_table),
    -			KM_SLEEP);
    -		hole = uuid_table_size++;
    -	}
    -	uuid_table[hole] = *uuid;
    -	mutex_unlock(&uuid_monitor);
    -	return 1;
    -}
    -
    -void
    -uuid_table_remove(uuid_t *uuid)
    -{
    -	int	i;
    -
    -	mutex_lock(&uuid_monitor, PVFS);
    -	for (i = 0; i < uuid_table_size; i++) {
    -		if (uuid_is_nil(&uuid_table[i]))
    -			continue;
    -		if (!uuid_equal(uuid, &uuid_table[i]))
    -			continue;
    -		uuid_create_nil(&uuid_table[i]);
    -		break;
    -	}
    -	ASSERT(i < uuid_table_size);
    -	mutex_unlock(&uuid_monitor);
    -}
    diff --git a/sys/gnu/fs/xfs/FreeBSD/support/uuid.h b/sys/gnu/fs/xfs/FreeBSD/support/uuid.h
    deleted file mode 100644
    index d8f389ae5a2..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/support/uuid.h
    +++ /dev/null
    @@ -1,45 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or modify it
    - * under the terms of version 2 of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful, but
    - * WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    - *
    - * Further, this software is distributed without any warranty that it is
    - * free of the rightful claim of any third person regarding infringement
    - * or the like.  Any license provided herein, whether implied or
    - * otherwise, applies only to this software file.  Patent licenses, if
    - * any, provided herein do not apply to combinations of this program with
    - * other software, or any other product whatsoever.
    - *
    - * You should have received a copy of the GNU General Public License along
    - * with this program; if not, write the Free Software Foundation, Inc., 59
    - * Temple Place - Suite 330, Boston MA 02111-1307, USA.
    - *
    - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
    - * Mountain View, CA  94043, or:
    - *
    - * http://www.sgi.com
    - *
    - * For further information regarding this notice, see:
    - *
    - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
    - */
    -#ifndef __XFS_SUPPORT_UUID_H__
    -#define __XFS_SUPPORT_UUID_H__
    -
    -void uuid_init(void);
    -void uuid_cleanup(void);
    -void uuid_create_nil(uuid_t *uuid);
    -int uuid_is_nil(uuid_t *uuid);
    -int uuid_equal(uuid_t *uuid1, uuid_t *uuid2);
    -void uuid_getnodeuniq(uuid_t *uuid, int fsid [2]);
    -__uint64_t uuid_hash64(uuid_t *uuid);
    -int uuid_table_insert(uuid_t *uuid);
    -void uuid_table_remove(uuid_t *uuid);
    -
    -#endif	/* __XFS_SUPPORT_UUID_H__ */
    diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_buf.c b/sys/gnu/fs/xfs/FreeBSD/xfs_buf.c
    deleted file mode 100644
    index b1821a827f2..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/xfs_buf.c
    +++ /dev/null
    @@ -1,334 +0,0 @@
    -/*
    - * Copyright (c) 2001,2005 Russell Cattelan
    - * 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 "xfs.h"
    -#include "xfs_types.h"
    -#include "xfs_inum.h"
    -#include "xfs_log.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_clnt.h"
    -#include "xfs_mountops.h"
    -
    -#include 
    -#include 
    -
    -xfs_buf_t *
    -xfs_buf_read_flags(xfs_buftarg_t *target, xfs_daddr_t blkno, size_t len, int flags)
    -{
    -	struct buf *bp;
    -	KASSERT((target != NULL), ("got NULL buftarg_t"));
    -
    -	if (bread(target->specvp, blkno, BBTOB(len), NOCRED, &bp)) {
    -		printf("bread failed specvp %p blkno %jd BBTOB(len) %ld\n",
    -		       target->specvp, (intmax_t)blkno, (long)BBTOB(len));
    -		bp = NULL;
    -	}
    -
    -	/* not really sure what B_MANAGED really does for us
    -	 * maybe we should drop this and just stick with a locked buf
    -	 */
    -
    -	if (flags & B_MANAGED)
    -		bp->b_flags |= B_MANAGED;
    -	xfs_buf_set_target(bp, target);
    -	return (bp);
    -}
    -
    -xfs_buf_t *
    -xfs_buf_get_flags(xfs_buftarg_t *target, xfs_daddr_t blkno, size_t len, int flags)
    -{
    -	struct buf *bp = NULL;
    -	KASSERT((target != NULL), ("got NULL buftarg_t"));
    -	bp = getblk(target->specvp, blkno, BBTOB(len), 0, 0, 0);
    -	if (bp != NULL)
    -		xfs_buf_set_target(bp, target);
    -	return (bp);
    -}
    -
    -xfs_buf_t*
    -xfs_buf_get_empty(size_t size,  xfs_buftarg_t *target)
    -{
    -	struct buf *bp;
    -
    -	bp = geteblk(0, 0);
    -	if (bp != NULL) {
    -		bp->b_bufsize = size;
    -		bp->b_bcount = size;
    -
    -		BUF_ASSERT_HELD(bp);
    -
    -		xfs_buf_set_target(bp, target);
    -	}
    -	return (bp);
    -}
    -
    -xfs_buf_t*
    -xfs_buf_get_noaddr(size_t len, xfs_buftarg_t *target)
    -{
    -	struct buf *bp;
    -	if (len >= MAXPHYS)
    -		return (NULL);
    -
    -	bp = geteblk(len, 0);
    -	if (bp != NULL) {
    -		BUF_ASSERT_HELD(bp);
    -
    -		xfs_buf_set_target(bp, target);
    -	}
    -	return (bp);
    -}
    -
    -void
    -xfs_buf_free(xfs_buf_t *bp)
    -{
    -	bp->b_flags |= B_INVAL;
    -	BUF_KERNPROC(bp);			 /* ugly hack #1 */
    -	if (bp->b_kvasize == 0) {
    -		bp->b_saveaddr = bp->b_kvabase;  /* ugly hack #2 */
    -		bp->b_data = bp->b_saveaddr;
    -		bp->b_bcount  = 0;
    -		bp->b_bufsize = 0;
    -	}
    -	brelse(bp);
    -}
    -
    -void
    -xfs_buf_readahead(
    -		  xfs_buftarg_t		*target,
    -		  xfs_daddr_t		ioff,
    -		  size_t		isize,
    -		  xfs_buf_flags_t	flags)
    -{
    -	daddr_t rablkno;
    -	int rabsize;
    -
    -	rablkno = ioff;
    -	rabsize = BBTOB(isize);
    -	breada(target->specvp, &rablkno, &rabsize, 1, NOCRED);
    -}
    -
    -void
    -xfs_buf_set_target(xfs_buf_t *bp, xfs_buftarg_t *targ)
    -{
    -	bp->b_bufobj = &targ->specvp->v_bufobj;
    -	bp->b_caller1 = targ;
    -}
    -
    -xfs_buftarg_t *
    -xfs_buf_get_target(xfs_buf_t *bp)
    -{
    -	return (xfs_buftarg_t *)bp->b_caller1;
    -}
    -
    -int
    -XFS_bwrite(xfs_buf_t *bp)
    -{
    -	int error;
    -	if (bp->b_vp == NULL) {
    -		error = xfs_buf_iorequest(bp);
    -
    -		if ((bp->b_flags & B_ASYNC) == 0) {
    -			error = bufwait(bp);
    -#if 0
    -			if (BUF_LOCKRECURSED(bp))
    -				BUF_UNLOCK(bp);
    -			else
    -				brelse(bp);
    -#endif
    -			brelse(bp);
    -		}
    -		return (error);
    -	}
    -	error = bwrite(bp);
    -	return (error);
    -}
    -
    -void
    -xfs_buf_pin(xfs_buf_t *bp)
    -{
    -	bpin(bp);
    -}
    -
    -void
    -xfs_buf_unpin(xfs_buf_t *bp)
    -{
    -	bunpin(bp);
    -}
    -
    -int
    -xfs_buf_ispin(xfs_buf_t *bp)
    -{
    -	return bp->b_pin_count;
    -}
    -
    -#if 0
    -void
    -xfs_buf_wait_unpin(
    -	xfs_buf_t *bp)
    -{
    -	bunpin_wait(bp);
    -}
    -#endif
    -
    -/*
    - *	Move data into or out of a buffer.
    - */
    -void
    -xfs_buf_iomove(
    -	xfs_buf_t		*bp,	/* buffer to process		*/
    -	size_t			boff,	/* starting buffer offset	*/
    -	size_t			bsize,	/* length to copy		*/
    -	caddr_t			data,	/* data address			*/
    -	xfs_buf_rw_t		mode)	/* read/write/zero flag		*/
    -{
    -
    -  printf("xfs_buf_iomove NI\n");
    -#ifdef RMC
    -	size_t			bend, cpoff, csize;
    -	struct page		*page;
    -
    -	bend = boff + bsize;
    -	while (boff < bend) {
    -		page = bp->b_pages[xfs_buf_btoct(boff + bp->b_offset)];
    -		cpoff = xfs_buf_poff(boff + bp->b_offset);
    -		csize = min_t(size_t,
    -			      PAGE_CACHE_SIZE-cpoff, bp->b_count_desired-boff);
    -
    -		ASSERT(((csize + cpoff) <= PAGE_CACHE_SIZE));
    -
    -		switch (mode) {
    -		case XBRW_ZERO:
    -			memset(page_address(page) + cpoff, 0, csize);
    -			break;
    -		case XBRW_READ:
    -			memcpy(data, page_address(page) + cpoff, csize);
    -			break;
    -		case XBRW_WRITE:
    -			memcpy(page_address(page) + cpoff, data, csize);
    -		}
    -
    -		boff += csize;
    -		data += csize;
    -	}
    -#endif
    -}
    -
    -/*
    - *	Handling of buffer targets (buftargs).
    - */
    -
    -/*
    - *	Wait for any bufs with callbacks that have been submitted but
    - *	have not yet returned... walk the hash list for the target.
    - */
    -void
    -xfs_wait_buftarg(
    -		 xfs_buftarg_t *bp)
    -{
    -	printf("xfs_wait_buftarg(%p) NI\n", bp);
    -}
    -
    -int
    -xfs_flush_buftarg(
    -	xfs_buftarg_t		*btp,
    -	int wait)
    -{
    -	int error = 0;
    -
    -	error = vinvalbuf(btp->specvp, V_SAVE | V_NORMAL, 0, 0);
    -	return error;
    -}
    -
    -void
    -xfs_free_buftarg(
    -	xfs_buftarg_t		*btp,
    -	int			external)
    -{
    -	xfs_flush_buftarg(btp, /* wait */ 0);
    -	kmem_free(btp, sizeof(*btp));
    -}
    -
    -int
    -xfs_readonly_buftarg(
    -	xfs_buftarg_t		*btp)
    -{
    -	struct g_consumer *cp;
    -
    -	KASSERT(btp->specvp->v_bufobj.bo_ops == &xfs_bo_ops,
    -	   ("Bogus xfs_buftarg_t pointer"));
    -	cp = btp->specvp->v_bufobj.bo_private;
    -	return (cp->acw == 0);
    -}
    -
    -#if 0
    -void
    -xfs_relse_buftarg(
    -	xfs_buftarg_t		*btp)
    -{
    -	printf("xfs_relse_buftargNI %p\n",btp);
    -}
    -#endif
    -
    -unsigned int
    -xfs_getsize_buftarg(
    -	xfs_buftarg_t		*btp)
    -{
    -	struct g_consumer       *cp;
    -	cp = btp->specvp->v_bufobj.bo_private;
    -	return (cp->provider->sectorsize);
    -}
    -
    -int
    -xfs_setsize_buftarg(
    -	xfs_buftarg_t		*btp,
    -	unsigned int		blocksize,
    -	unsigned int		sectorsize)
    -{
    -	printf("xfs_setsize_buftarg NI %p\n",btp);
    -	return 0;
    -}
    -
    -xfs_buftarg_t *
    -xfs_alloc_buftarg(
    -		  struct vnode	*bdev,
    -		  int		external)
    -{
    -	xfs_buftarg_t		*btp;
    -
    -	btp = kmem_zalloc(sizeof(*btp), KM_SLEEP);
    -
    -	btp->dev    = bdev->v_rdev;
    -	btp->specvp = bdev;
    -	return btp;
    -}
    diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_buf.h b/sys/gnu/fs/xfs/FreeBSD/xfs_buf.h
    deleted file mode 100644
    index 34e579d5b74..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/xfs_buf.h
    +++ /dev/null
    @@ -1,348 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or modify it
    - * under the terms of version 2 of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful, but
    - * WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    - *
    - * Further, this software is distributed without any warranty that it is
    - * free of the rightful claim of any third person regarding infringement
    - * or the like.	 Any license provided herein, whether implied or
    - * otherwise, applies only to this software file.  Patent licenses, if
    - * any, provided herein do not apply to combinations of this program with
    - * other software, or any other product whatsoever.
    - *
    - * You should have received a copy of the GNU General Public License along
    - * with this program; if not, write the Free Software Foundation, Inc., 59
    - * Temple Place - Suite 330, Boston MA 02111-1307, USA.
    - *
    - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
    - * Mountain View, CA  94043, or:
    - *
    - * http://www.sgi.com
    - *
    - * For further information regarding this notice, see:
    - *
    - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
    - */
    -#ifndef __XFS_BUF_H__
    -#define __XFS_BUF_H__
    -
    -#include 
    -#include 
    -
    -struct xfs_buf;
    -struct xfs_mount;
    -struct vnode;
    -typedef struct buf xfs_buf_t;
    -typedef uint32_t xfs_buf_flags_t;
    -#define xfs_buf buf
    -
    -extern struct buf_ops xfs_bo_ops;
    -
    -typedef enum {
    -	XBRW_READ = 1,			/* transfer into target memory */
    -	XBRW_WRITE = 2,			/* transfer from target memory */
    -	XBRW_ZERO = 3,			/* Zero target memory */
    -} xfs_buf_rw_t;
    -
    -/* Buffer Read and Write Routines */
    -extern void xfs_buf_ioend(xfs_buf_t *,	int);
    -extern void xfs_buf_ioerror(xfs_buf_t *, int);
    -extern int xfs_buf_iostart(xfs_buf_t *, xfs_buf_flags_t);
    -extern int xfs_buf_iorequest(xfs_buf_t *);
    -extern int xfs_buf_iowait(xfs_buf_t *);
    -extern void xfs_buf_iomove(xfs_buf_t *, size_t, size_t, xfs_caddr_t, xfs_buf_rw_t);
    -
    -/* Pinning Buffer Storage in Memory */
    -extern void xfs_buf_pin(xfs_buf_t *);
    -extern void xfs_buf_unpin(xfs_buf_t *);
    -extern int xfs_buf_ispin(xfs_buf_t *);
    -
    -
    -typedef void (*xfs_buf_iodone_t)(struct xfs_buf *); /* call-back function on I/O completion */
    -typedef void (*xfs_buf_relse_t)(struct xfs_buf *); /* call-back function on I/O completion */
    -typedef int (*xfs_buf_bdstrat_t)(struct xfs_buf *);
    -
    -typedef struct xfs_buftarg {
    -	/* this probaby redundant info, but stick with linux conventions for now */
    -	unsigned int	bt_bsize;
    -	unsigned int	bt_sshift;
    -	size_t		bt_smask;
    -	struct cdev	*dev;
    -	struct vnode	*specvp;
    -} xfs_buftarg_t;
    -
    -
    -/* Finding and Reading Buffers */
    -extern void xfs_buf_readahead(xfs_buftarg_t *, xfs_off_t, size_t, xfs_buf_flags_t);
    -/* Misc buffer rountines */
    -extern int xfs_readonly_buftarg(xfs_buftarg_t *);
    -
    -/* These are just for xfs_syncsub... it sets an internal variable
    - * then passes it to VOP_FLUSH_PAGES or adds the flags to a newly gotten buf_t
    - */
    -#define XBF_DONT_BLOCK		0
    -
    -#define	XFS_B_ASYNC		B_ASYNC
    -#define	XFS_B_DELWRI		B_DELWRI
    -#define	XFS_B_READ		BIO_READ
    -#define	XFS_B_WRITE		BIO_WRITE
    -
    -#define	XFS_B_STALE		B_INVAL
    -#define	XFS_BUF_LOCK		0
    -#define	XFS_BUF_TRYLOCK		0
    -#define	XFS_BUF_MAPPED		0
    -#define	BUF_BUSY		0
    -
    -#define	XBF_ORDERED             0
    -
    -				/* debugging routines might need this */
    -#define XFS_BUF_BFLAGS(x)	((x)->b_flags)
    -#define XFS_BUF_ZEROFLAGS(x)	((x)->b_flags = 0)
    -#define XFS_BUF_STALE(x)	((x)->b_flags |= (XFS_B_STALE|B_NOCACHE))
    -#define XFS_BUF_UNSTALE(x)	((x)->b_flags &= ~(XFS_B_STALE|B_NOCACHE))
    -#define XFS_BUF_ISSTALE(x)	((x)->b_flags & (XFS_B_STALE|B_NOCACHE))
    -#define XFS_BUF_SUPER_STALE(x)	{(x)->b_flags |= (XFS_B_STALE|B_NOCACHE); \
    -				(x)->b_flags &= ~(XFS_B_DELWRI|B_CACHE);}
    -
    -#define XFS_BUF_MANAGE		B_MANAGED
    -#define XFS_BUF_UNMANAGE(x)	((x)->b_flags &= ~B_MANAGED)
    -
    -#define XFS_BUF_DELAYWRITE(x)		((x)->b_flags |= XFS_B_DELWRI)
    -#define XFS_BUF_UNDELAYWRITE(x)	((x)->b_flags &= ~XFS_B_DELWRI)
    -#define XFS_BUF_ISDELAYWRITE(x)	((x)->b_flags & XFS_B_DELWRI)
    -
    -#define XFS_BUF_ERROR(x,no)	xfs_buf_set_error((x), (no))
    -#define XFS_BUF_GETERROR(x)	xfs_buf_get_error(x)
    -#define XFS_BUF_ISERROR(x)	(((x)->b_ioflags & BIO_ERROR) != 0)
    -
    -void static __inline__
    -xfs_buf_set_error(struct buf *bp, int err)
    -{
    -	bp->b_ioflags |= BIO_ERROR;
    -	bp->b_error = err;
    -}
    -
    -int static __inline__
    -xfs_buf_get_error(struct buf *bp)
    -{
    -	return XFS_BUF_ISERROR(bp) ? (bp->b_error ? bp->b_error : EIO) : 0;
    -}
    -
    -#define XFS_BUF_DONE(x)		((x)->b_flags |= B_CACHE)
    -#define XFS_BUF_UNDONE(x)	((x)->b_flags &= ~B_CACHE)
    -#define XFS_BUF_ISDONE(x)	((x)->b_flags & B_CACHE)
    -
    -#define XFS_BUF_BUSY(x)		((x)->b_flags |= BUF_BUSY)
    -#define XFS_BUF_UNBUSY(x)	((x)->b_flags &= ~BUF_BUSY)
    -#define XFS_BUF_ISBUSY(x)	(1)
    -
    -#define XFS_BUF_ASYNC(x)	((x)->b_flags |=  B_ASYNC)
    -#define XFS_BUF_UNASYNC(x)	((x)->b_flags &= ~B_ASYNC)
    -#define XFS_BUF_ISASYNC(x)	((x)->b_flags &   B_ASYNC)
    -
    -#define XFS_BUF_ORDERED(bp)	((bp)->b_flags |= XBF_ORDERED)
    -#define XFS_BUF_UNORDERED(bp)	((bp)->b_flags &= ~XBF_ORDERED)
    -#define XFS_BUF_ISORDERED(bp)	((bp)->b_flags & XBF_ORDERED)
    -
    -#define XFS_BUF_FLUSH(x)	((x)->b_flags |=  B_00800000)
    -#define XFS_BUF_UNFLUSH(x)	((x)->b_flags &= ~B_00800000)
    -#define XFS_BUF_ISFLUSH(x) 	((x)->b_flags &   B_00800000)
    -
    -#define XFS_BUF_SHUT(x)		printf("XFS_BUF_SHUT not implemented yet\n")
    -#define XFS_BUF_UNSHUT(x)	printf("XFS_BUF_UNSHUT not implemented yet\n")
    -#define XFS_BUF_ISSHUT(x)	(0)
    -
    -#define XFS_BUF_HOLD(x)		((void)0)
    -#define XFS_BUF_UNHOLD(x)	((void)0)
    -
    -#define XFS_BUF_READ(x)		((x)->b_iocmd = BIO_READ)
    -#define XFS_BUF_UNREAD(x)	((x)->b_iocmd = 0)
    -#define XFS_BUF_ISREAD(x)	((x)->b_iocmd == BIO_READ)
    -
    -#define XFS_BUF_WRITE(x)	((x)->b_iocmd = BIO_WRITE)
    -#define XFS_BUF_UNWRITE(x)	((x)->b_iocmd = 0)
    -#define XFS_BUF_ISWRITE(x)	((x)->b_iocmd == BIO_WRITE)
    -
    -#define XFS_BUF_ISUNINITIAL(x)	(0)
    -#define XFS_BUF_UNUNINITIAL(x)	(0)
    -
    -#define XFS_BUF_IODONE_FUNC(x)		(x)->b_iodone
    -#define XFS_BUF_SET_IODONE_FUNC(x, f)	(x)->b_iodone = (f)
    -#define XFS_BUF_CLR_IODONE_FUNC(x)	(x)->b_iodone = NULL
    -
    -#define XFS_BUF_SET_BDSTRAT_FUNC(x, f)	do { if(f != NULL) {} } while(0)
    -#define XFS_BUF_CLR_BDSTRAT_FUNC(x)	((void)0)
    -
    -#define XFS_BUF_BP_ISMAPPED(bp)		(1)
    -
    -#define XFS_BUF_FSPRIVATE(buf, type) \
    -			((type)(buf)->b_fsprivate1)
    -#define XFS_BUF_SET_FSPRIVATE(buf, value) \
    -			(buf)->b_fsprivate1 = (void *)(value)
    -#define XFS_BUF_FSPRIVATE2(buf, type) \
    -			((type)(buf)->b_fsprivate2)
    -#define XFS_BUF_SET_FSPRIVATE2(buf, value) \
    -			(buf)->b_fsprivate2 = (void *)(value)
    -#define XFS_BUF_FSPRIVATE3(buf, type) \
    -			((type)(buf)->b_fsprivate3)
    -#define XFS_BUF_SET_FSPRIVATE3(buf, value) \
    -			(buf)->b_fsprivate3 = (void *)(value)
    -#define XFS_BUF_SET_START(buf) \
    -		printf("XFS_BUF_SET_START: %s:%d\n", __FILE__, __LINE__)
    -
    -#define XFS_BUF_SET_BRELSE_FUNC(buf, value) \
    -	do { \
    -		printf("XFS_BUF_SET_BRELSE_FUNC: %s:%d\n", \
    -		        __FILE__, __LINE__); \
    -		if (value != NULL ) {} \
    -	} while(0)
    -
    -#define XFS_BUF_PTR(bp)		(xfs_caddr_t)((bp)->b_data)
    -
    -static __inline xfs_caddr_t
    -xfs_buf_offset(xfs_buf_t *bp, size_t offset)
    -{
    -	return XFS_BUF_PTR(bp) + offset;
    -}
    -
    -#define XFS_BUF_SET_PTR(bp, val, count)	\
    -				do { \
    -					(bp)->b_data = (val); \
    -					(bp)->b_bcount = (count); \
    -				} while(0)
    -
    -#define XFS_BUF_ADDR(bp)	((bp)->b_blkno)
    -#define XFS_BUF_SET_ADDR(bp, blk) \
    -				((bp)->b_blkno = blk)
    -#define XFS_BUF_OFFSET(bp)	((bp)->b_offset)
    -#define XFS_BUF_SET_OFFSET(bp, off) \
    -				((bp)->b_offset = off)
    -#define XFS_BUF_COUNT(bp)	((bp)->b_bcount)
    -#define XFS_BUF_SET_COUNT(bp, cnt) \
    -				((bp)->b_bcount = cnt)
    -#define XFS_BUF_SIZE(bp)	((bp)->b_bufsize)
    -#define XFS_BUF_SET_SIZE(bp, cnt) \
    -			        ((bp)->b_bufsize = cnt)
    -#define	XFS_BUF_SET_VTYPE_REF(bp, type, ref)
    -#define	XFS_BUF_SET_VTYPE(bp, type)
    -#define	XFS_BUF_SET_REF(bp, ref)
    -
    -#define	XFS_BUF_VALUSEMA(bp)	(BUF_ISLOCKED(bp) ? 0 : 1)
    -#define	XFS_BUF_CPSEMA(bp) \
    -	(BUF_LOCK(bp, LK_EXCLUSIVE|LK_CANRECURSE | LK_SLEEPFAIL, NULL) == 0)
    -
    -#define	XFS_BUF_PSEMA(bp,x)	BUF_LOCK(bp, LK_EXCLUSIVE|LK_CANRECURSE, NULL)
    -#define	XFS_BUF_VSEMA(bp)	BUF_UNLOCK(bp)
    -
    -#define	XFS_BUF_V_IODONESEMA(bp) bdone(bp)
    -
    -/* setup the buffer target from a buftarg structure */
    -#define XFS_BUF_SET_TARGET(bp, target) \
    -	xfs_buf_set_target(bp, target)
    -
    -void xfs_buf_set_target(xfs_buf_t *, xfs_buftarg_t *);
    -xfs_buftarg_t *xfs_buf_get_target(xfs_buf_t *);
    -
    -/* return the dev_t being used */
    -#define XFS_BUF_TARGET(bp)	xfs_buf_get_target(bp)
    -#define	XFS_BUFTARG_NAME(targp)	devtoname((targp)->dev)
    -
    -#define XFS_BUF_SET_VTYPE_REF(bp, type, ref)
    -#define XFS_BUF_SET_VTYPE(bp, type)
    -#define XFS_BUF_SET_REF(bp, ref)
    -
    -#define XFS_BUF_ISPINNED(bp)	xfs_buf_ispin(bp)
    -
    -xfs_buf_t *
    -xfs_buf_read_flags(xfs_buftarg_t *, xfs_daddr_t, size_t, int);
    -
    -#define xfs_buf_read(target, blkno, len, flags) \
    -                xfs_buf_read_flags(target, blkno, len, \
    -                       XFS_BUF_LOCK | XFS_BUF_MAPPED)
    -
    -xfs_buf_t *
    -xfs_buf_get_flags(xfs_buftarg_t *, xfs_daddr_t, size_t, int);
    -
    -#define xfs_buf_get(target, blkno, len, flags) \
    -                xfs_buf_get_flags(target, blkno, len, \
    -                       XFS_BUF_LOCK | XFS_BUF_MAPPED)
    -
    -/* the return value is never used ... why does linux define this functions this way? */
    -static inline int xfs_bawrite(void *mp, xfs_buf_t *bp)
    -{
    -	/* Ditto for xfs_bawrite
    -	bp->b_fspriv3 = mp;
    -	bp->b_strat = xfs_bdstrat_cb;
    -	xfs_buf_delwri_dequeue(bp);
    -	return xfs_buf_iostart(bp, XBF_WRITE | XBF_ASYNC | _XBF_RUN_QUEUES);
    -	*/
    -	bawrite(bp);
    -	return 0;
    -}
    -
    -static inline int xfs_bdwrite(void *mp, xfs_buf_t *bp)
    -{
    -  /* this is for io shutdown checking need to do this at some point RMC */
    -  /* probably should just change xfs to call a buf write function */
    -#if 0 /* RMC */
    -	bp->b_strat = xfs_bdstrat_cb;
    -	bp->b_fspriv3 = mp;
    -	return xfs_buf_iostart(bp, XBF_DELWRI | XBF_ASYNC);
    -#endif
    -	bdwrite(bp);
    -	return 0;
    -}
    -
    -#define xfs_bpin(bp)		xfs_buf_pin(bp)
    -#define xfs_bunpin(bp)		xfs_buf_unpin(bp)
    -
    -#define xfs_buf_relse(bp)            brelse(bp)
    -#define xfs_bp_mapin(bp)             bp_mapin(bp)
    -#define xfs_xfsd_list_evict(x)       _xfs_xfsd_list_evict(x)
    -#define xfs_buftrace(x,y)            CTR2(KTR_BUF, "%s bp %p flags %X", bp, bp->b_flags)
    -#define xfs_biodone(bp)              bufdone_finish(bp)
    -
    -#define xfs_incore(xfs_buftarg,blkno,len,lockit)  \
    -			  incore(&xfs_buftarg->specvp->v_bufobj, blkno);
    -
    -#define xfs_biomove(bp, off, len, data, rw) \
    -	xfs_buf_iomove((bp), (off), (len), (data),			\
    -		       ((rw) == XFS_B_WRITE) ? XBRW_WRITE : XBRW_READ)
    -
    -#define xfs_biozero(bp, off, len) \
    -	xfs_buf_iomove((bp), (off), (len), NULL, XBRW_ZERO)
    -
    -/* already a function xfs_bwrite... fix this */
    -#define XFS_bdwrite(bp)			bdwrite(bp)
    -#define xfs_iowait(bp)			bufwait(bp)
    -
    -#define XFS_bdstrat(bp)			xfs_buf_iorequest(bp)
    -
    -#define xfs_baread(target, rablkno, ralen)  \
    -	xfs_buf_readahead((target), (rablkno), (ralen), XBF_DONT_BLOCK)
    -
    -struct xfs_mount;
    -
    -int XFS_bwrite(xfs_buf_t *bp);
    -xfs_buf_t* xfs_buf_get_empty(size_t, xfs_buftarg_t *targ);
    -xfs_buf_t* xfs_buf_get_noaddr(size_t, xfs_buftarg_t *targ);
    -void xfs_buf_free(xfs_buf_t *);
    -
    -extern void xfs_bwait_unpin(xfs_buf_t *bp);
    -extern xfs_buftarg_t *xfs_alloc_buftarg(struct vnode *, int);
    -extern void xfs_free_buftarg(xfs_buftarg_t *, int);
    -extern void xfs_wait_buftarg(xfs_buftarg_t *);
    -extern int xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int);
    -extern unsigned int xfs_getsize_buftarg(struct xfs_buftarg *);
    -extern int xfs_flush_buftarg(xfs_buftarg_t *, int);
    -
    -#define xfs_binval(buftarg)		xfs_flush_buftarg(buftarg, 1)
    -#define XFS_bflush(buftarg)		xfs_flush_buftarg(buftarg, 1)
    -
    -#endif
    diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_compat.h b/sys/gnu/fs/xfs/FreeBSD/xfs_compat.h
    deleted file mode 100644
    index 55a03c96bda..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/xfs_compat.h
    +++ /dev/null
    @@ -1,173 +0,0 @@
    -#ifndef __XFS_COMPAT_H__
    -#define	__XFS_COMPAT_H__
    -
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -
    -#ifdef _KERNEL
    -#define __KERNEL__
    -#endif
    -
    -#define printk printf
    -
    -#define MAJOR(x) major(x)
    -#define MINOR(x) minor(x)
    -
    -/*
    - * SYSV compatibility types missing in FreeBSD.
    - */
    -typedef unsigned long		ulong;
    -typedef unsigned int		uint;
    -typedef unsigned short		ushort;
    -
    -/*
    - * Additional type declarations for XFS.
    - */
    -typedef signed char		__s8;
    -typedef unsigned char		__u8;
    -typedef signed short int	__s16;
    -typedef unsigned short int	__u16;
    -typedef signed int		__s32;
    -typedef unsigned int		__u32;
    -typedef signed long long int	__s64;
    -typedef unsigned long long int	__u64;
    -
    -/* linus now has sparse which expects big endian or little endian */
    -typedef __u16 __be16;
    -typedef __u32 __be32;
    -typedef __u64 __be64;
    -
    -/*
    - * Linux types with direct FreeBSD conterparts
    - */
    -typedef off_t			loff_t;
    -typedef struct timespec		timespec_t;
    -typedef	struct uuid		uuid_t;
    -typedef struct fid		fid_t;
    -typedef dev_t			os_dev_t;
    -
    -/*
    - *  Linux block devices are device vnodes in FreeBSD.
    - */
    -#define	block_device		vnode
    -
    -/*
    - *  Get the current CPU ID. 
    - */
    -#define	smp_processor_id()	PCPU_GET(cpuid)
    -
    -/*
    - * FreeBSD does not have BITS_PER_LONG defined.
    - */
    -#if defined(LONG_BIT)
    -#define	BITS_PER_LONG		LONG_BIT
    -#elif defined(__i386__)
    -#define	BITS_PER_LONG		32
    -#endif
    -
    -#define rol32(x, y)	(((x)<<(y))|((x)>>(32-(y))))
    -/*
    - * boolean_t is enum on Linux, int on FreeBSD.
    - * Provide value defines.
    - */
    -#define	B_FALSE			0
    -#define	B_TRUE			1
    -
    -/*
    - * GCC 3.x static branch prediction hints
    - */
    -#if __GNUC__ < 3
    -#define __builtin_expect(x, expected_value) (x)
    -#endif
    -
    -#ifndef likely
    -#define	likely(x)	__builtin_expect((x), 1)
    -#endif
    -
    -#ifndef unlikely
    -#define	unlikely(x)	__builtin_expect((x), 0)
    -#endif
    -
    -/*
    - * ANSI and GCC extension keywords compatibity
    - */
    -#ifndef inline
    -#define	inline __inline__
    -#endif
    -
    -#ifndef asm
    -#define	asm __asm
    -#endif
    -
    -#ifndef typeof
    -#define	typeof __typeof
    -#endif
    -
    -/*
    - * Miscellaneous limit constants
    - */
    -#define	MAX_LFS_FILESIZE	0x7fffffffffffffffLL
    -
    -/*
    - * Map simple functions to their FreeBSD kernel equivalents
    - */
    -#ifndef copy_to_user
    -#define	copy_to_user(dst, src, len)	copyout((src), (dst), (len))
    -#endif
    -
    -#ifndef copy_from_user
    -#define	copy_from_user(dst, src, len)	copyin((src), (dst), (len))
    -#endif
    -
    -/*
    - * Map simple global vairables to FreeBSD kernel equivalents
    - */
    -#if !defined(xfs_physmem)
    -#define	xfs_physmem	physmem
    -#endif
    -
    -#ifndef HZ
    -#define	HZ		hz
    -#endif
    -
    -/*
    - * These should be implemented properly for all architectures
    - * we want to support.
    - */
    -#define	get_unaligned(ptr)	(*(ptr))
    -#define	put_unaligned(val, ptr)	((void)( *(ptr) = (val) ))
    -
    -/*
    - * Linux type-safe min/max macros.
    - */
    -#define	min_t(type,x,y)		MIN((x),(y)) 
    -#define	max_t(type,x,y)		MAX((x),(y)) 
    -
    -
    -typedef struct mtx xfs_mutex_t;
    -/*
    - * Cedentials manipulation.
    - */
    -#define current_fsuid(credp)	(credp)->cr_uid
    -#define current_fsgid(credp)	(credp)->cr_groups[0]
    -
    -#define PAGE_CACHE_SIZE PAGE_SIZE
    -
    -#define IS_ERR(err) (err)
    -
    -static inline unsigned long ffz(unsigned long val)
    -{
    -        return ffsl(~val);
    -}
    -
    -#endif /* __XFS_COMPAT_H__ */
    diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_config.h b/sys/gnu/fs/xfs/FreeBSD/xfs_config.h
    deleted file mode 100644
    index a115f5438e8..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/xfs_config.h
    +++ /dev/null
    @@ -1,38 +0,0 @@
    -#ifndef __XFS_CONFIG_H__
    -#define	__XFS_CONFIG_H__
    -
    -#define	HAVE_FID		1
    -/*
    - * Linux config variables, harcoded to values desirable for FreeBSD.
    - */
    -#define	CONFIG_SYSCTL		1
    -#define	CONFIG_LBD		1
    -#define	CONFIG_XFS_TRACE	0
    -
    -/*
    - * Tracing.
    - */
    -#if CONFIG_XFS_TRACE == 1
    -#define	XFS_ALLOC_TRACE		1
    -#define	XFS_ALLOC_TRACE		1
    -#define	XFS_ATTR_TRACE		1
    -#define	XFS_BLI_TRACE		1
    -#define	XFS_BMAP_TRACE		1
    -#define	XFS_BMBT_TRACE		1
    -#define	XFS_DIR_TRACE		1
    -#define	XFS_DIR2_TRACE		1
    -#define	XFS_DQUOT_TRACE		1
    -#define	XFS_ILOCK_TRACE		1
    -#define	XFS_LOG_TRACE		1
    -#define	XFS_RW_TRACE		1
    -#endif
    -
    -/*
    - * XFS config defines.
    - */
    -#define XFS_BIG_BLKNOS		1
    -#define XFS_BIG_INUMS		0
    -
    -#undef XFS_STATS_OFF
    -
    -#endif /* __XFS_CONFIG_H__ */
    diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_cred.h b/sys/gnu/fs/xfs/FreeBSD/xfs_cred.h
    deleted file mode 100644
    index bc599776e66..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/xfs_cred.h
    +++ /dev/null
    @@ -1,46 +0,0 @@
    -/*
    - * Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or modify it
    - * under the terms of version 2 of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful, but
    - * WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    - *
    - * Further, this software is distributed without any warranty that it is
    - * free of the rightful claim of any third person regarding infringement
    - * or the like.  Any license provided herein, whether implied or
    - * otherwise, applies only to this software file.  Patent licenses, if
    - * any, provided herein do not apply to combinations of this program with
    - * other software, or any other product whatsoever.
    - *
    - * You should have received a copy of the GNU General Public License along
    - * with this program; if not, write the Free Software Foundation, Inc., 59
    - * Temple Place - Suite 330, Boston MA 02111-1307, USA.
    - *
    - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
    - * Mountain View, CA  94043, or:
    - *
    - * http://www.sgi.com
    - *
    - * For further information regarding this notice, see:
    - *
    - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
    - */
    -#ifndef __XFS_CRED_H__
    -#define __XFS_CRED_H__
    -
    -#include 
    -/*
    - * struct cred is struct ucred on FreeBSD
    - */
    -typedef struct ucred cred_t;
    -
    -#define	cred	ucred
    -
    -#define capable(cap)	(1)
    -#define capable_cred(cr, cap)	(1)
    -
    -#endif  /* __XFS_CRED_H__ */
    diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_dmistubs.c b/sys/gnu/fs/xfs/FreeBSD/xfs_dmistubs.c
    deleted file mode 100644
    index 8f0eda17fb2..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/xfs_dmistubs.c
    +++ /dev/null
    @@ -1,144 +0,0 @@
    -/*
    - * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or modify it
    - * under the terms of version 2 of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    - *
    - * Further, this software is distributed without any warranty that it is
    - * free of the rightful claim of any third person regarding infringement
    - * or the like.  Any license provided herein, whether implied or
    - * otherwise, applies only to this software file.  Patent licenses, if
    - * any, provided herein do not apply to combinations of this program with
    - * other software, or any other product whatsoever.
    - *
    - * You should have received a copy of the GNU General Public License along
    - * with this program; if not, write the Free Software Foundation, Inc., 59
    - * Temple Place - Suite 330, Boston MA 02111-1307, USA.
    - *
    - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
    - * Mountain View, CA  94043, or:
    - *
    - * http://www.sgi.com
    - *
    - * For further information regarding this notice, see:
    - *
    - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
    - */
    -
    -#include "xfs.h"
    -
    -#include "xfs_types.h"
    -#include "xfs_inum.h"
    -#include "xfs_log.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -
    -static int nopkg(void);
    -
    -static __inline int
    -nopkg()
    -{
    -	return (ENOSYS);
    -}
    -
    -int dmapi_init(void);
    -int
    -dmapi_init (void)
    -{
    -	return (0);
    -}
    -
    -void dmapi_uninit(void);
    -void
    -dmapi_uninit (void)
    -{
    -}
    -
    -int dm_data_event(void);
    -int
    -dm_data_event (void)
    -{
    -	return nopkg();
    -}
    -
    -int dm_namesp_event(void);
    -int
    -dm_namesp_event (void)
    -{
    -	return nopkg();
    -}
    -
    -/*	The following stubs are for routines needed for the X/Open
    - *	version of DMAPI.
    - */
    -int xfs_dm_mount(xfs_vfs_t *, xfs_vnode_t *, char *, char *); 
    -int
    -xfs_dm_mount(
    -	xfs_vfs_t	*vfsp,
    -	xfs_vnode_t	*mvp,
    -	char		*dir_name,
    -	char		*fsname)
    -{
    -	return nopkg();
    -}
    -
    -int
    -dm_send_destroy_event(bhv_desc_t *bdp, dm_right_t vp_right);
    -int
    -dm_send_destroy_event(bhv_desc_t *bdp, dm_right_t vp_right)
    -{
    -	return nopkg();
    -}
    -
    -int
    -dm_send_mount_event(xfs_vfs_t *vfsp, dm_right_t vfsp_right, bhv_desc_t *bdp,
    -	dm_right_t vp_right, bhv_desc_t *rootbdp, dm_right_t rootvp_right,
    -	char *name1, char *name2);
    -int
    -dm_send_mount_event(xfs_vfs_t *vfsp, dm_right_t vfsp_right, bhv_desc_t *bdp,
    -	dm_right_t vp_right, bhv_desc_t *rootbdp, dm_right_t rootvp_right,
    -	char *name1, char *name2)
    -{
    -	return nopkg();
    -}
    -
    -
    -int
    -dm_send_namesp_event(dm_eventtype_t event, bhv_desc_t *bdp1,
    -	dm_right_t vp1_right, bhv_desc_t *bdp2, dm_right_t vp2_right,
    -	char *name1, char *name2, mode_t mode, int retcode, int flags);
    -int
    -dm_send_namesp_event(dm_eventtype_t event, bhv_desc_t *bdp1,
    -	dm_right_t vp1_right, bhv_desc_t *bdp2, dm_right_t vp2_right,
    -	char *name1, char *name2, mode_t mode, int retcode, int flags)
    -{
    -	return nopkg();
    -}
    -
    -
    -void
    -dm_send_unmount_event(xfs_vfs_t *vfsp, xfs_vnode_t *vp, dm_right_t vfsp_right,
    -	mode_t mode, int retcode, int flags);
    -void
    -dm_send_unmount_event(xfs_vfs_t *vfsp, xfs_vnode_t *vp, dm_right_t vfsp_right,
    -	mode_t mode, int retcode, int flags)
    -{
    -}
    -
    -
    -int
    -dm_vp_to_handle (xfs_vnode_t *vp, xfs_handle_t *handlep);
    -int
    -dm_vp_to_handle (xfs_vnode_t *vp, xfs_handle_t *handlep)
    -{
    -	return nopkg();
    -}
    diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_freebsd.h b/sys/gnu/fs/xfs/FreeBSD/xfs_freebsd.h
    deleted file mode 100644
    index cc1d8df0adc..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/xfs_freebsd.h
    +++ /dev/null
    @@ -1,350 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or modify it
    - * under the terms of version 2 of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful, but
    - * WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    - *
    - * Further, this software is distributed without any warranty that it is
    - * free of the rightful claim of any third person regarding infringement
    - * or the like.  Any license provided herein, whether implied or
    - * otherwise, applies only to this software file.  Patent licenses, if
    - * any, provided herein do not apply to combinations of this program with
    - * other software, or any other product whatsoever.
    - *
    - * You should have received a copy of the GNU General Public License along
    - * with this program; if not, write the Free Software Foundation, Inc., 59
    - * Temple Place - Suite 330, Boston MA 02111-1307, USA.
    - *
    - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
    - * Mountain View, CA  94043, or:
    - *
    - * http://www.sgi.com
    - *
    - * For further information regarding this notice, see:
    - *
    - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
    - */
    -#ifndef __XFS_FREEBSD__
    -#define __XFS_FREEBSD__
    -
    -#include 
    -#include 
    -
    -/*
    - * Some types are conditional depending on the target system.
    - * XFS_BIG_BLKNOS needs block layer disk addresses to be 64 bits.
    - * XFS_BIG_INUMS needs the VFS inode number to be 64 bits, as well
    - * as requiring XFS_BIG_BLKNOS to be set.
    - */
    -#define XFS_BIG_BLKNOS	1
    -#define XFS_BIG_INUMS	0
    -
    -#include 
    -#include 
    -
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -
    -/*
    - * Feature macros (disable/enable)
    - */
    -#undef  HAVE_REFCACHE	/* Do not use refcache. */
    -#undef  HAVE_SENDFILE	/* sendfile(2) is available in FreeBSD. */
    -
    -#ifndef EVMS_MAJOR
    -#define EVMS_MAJOR 117
    -#endif
    -
    -#define restricted_chown	xfs_params.restrict_chown.val
    -#define irix_sgid_inherit	xfs_params.sgid_inherit.val
    -#define irix_symlink_mode	xfs_params.symlink_mode.val
    -#define xfs_panic_mask		xfs_params.panic_mask.val
    -#define xfs_error_level		xfs_params.error_level.val
    -#define xfs_syncd_centisecs	xfs_params.syncd_timer.val
    -#define xfs_probe_dmapi		xfs_params.probe_dmapi.val
    -#define xfs_probe_ioops		xfs_params.probe_ioops.val
    -#define xfs_probe_quota		xfs_params.probe_quota.val
    -#define xfs_stats_clear		xfs_params.stats_clear.val
    -#define xfs_inherit_sync	xfs_params.inherit_sync.val
    -#define xfs_inherit_nodump	xfs_params.inherit_nodump.val
    -#define xfs_inherit_noatime	xfs_params.inherit_noatim.val
    -#define xfs_buf_timer_centisecs	xfs_params.xfs_buf_timer.val
    -#define xfs_buf_age_centisecs	xfs_params.xfs_buf_age.val
    -#define xfs_inherit_nosymlinks	xfs_params.inherit_nosym.val
    -#define xfs_rotorstep		xfs_params.rotorstep.val
    -
    -#define current_cpu()		smp_processor_id()
    -#define current_pid()		(curthread->td_proc->p_pid)
    -
    -#define NBPP		PAGE_SIZE
    -#define DPPSHFT		(PAGE_SHIFT - 9)
    -#define NDPP		(1 << (PAGE_SHIFT - 9))
    -#define dtop(DD)	(((DD) + NDPP - 1) >> DPPSHFT)
    -#define dtopt(DD)	((DD) >> DPPSHFT)
    -#define dpoff(DD)	((DD) & (NDPP-1))
    -
    -#define NBBY		8		/* number of bits per byte */
    -#define	NBPC		PAGE_SIZE	/* Number of bytes per click */
    -#define	BPCSHIFT	PAGE_SHIFT	/* LOG2(NBPC) if exact */
    -
    -/* number of BB's per block device block */
    -#define	BLKDEV_BB	BTOBB(BLKDEV_IOSIZE)
    -
    -/* bytes to clicks */
    -#define	btoct(x)	((__psunsigned_t)(x)>>BPCSHIFT)
    -#define	btoc64(x)	(((__uint64_t)(x)+(NBPC-1))>>BPCSHIFT)
    -#define	btoct64(x)	((__uint64_t)(x)>>BPCSHIFT)
    -#define	io_btoc(x)	(((__psunsigned_t)(x)+(IO_NBPC-1))>>IO_BPCSHIFT)
    -#define	io_btoct(x)	((__psunsigned_t)(x)>>IO_BPCSHIFT)
    -
    -/* off_t bytes to clicks */
    -#define offtoc(x)       (((__uint64_t)(x)+(NBPC-1))>>BPCSHIFT)
    -#define offtoct(x)      ((xfs_off_t)(x)>>BPCSHIFT)
    -
    -/* clicks to off_t bytes */
    -#define	ctooff(x)	((xfs_off_t)(x)<>BPCSHIFT)
    -#define	ctob64(x)	((__uint64_t)(x)<>XFS_DEV_BITSMINOR) \
    -				    & XFS_DEV_MAXMAJ))
    -#define XFS_DEV_MINOR(dev)	((int)((dev)&XFS_DEV_MAXMIN))
    -#define XFS_MKDEV(major,minor) ((xfs_dev_t)(((major)<f_fsid.val[0] = /*dev2udev(mp->m_dev) */ 1;	\
    -		(statp)->f_fsid.val[1] = 0;			\
    -	})	
    -
    -
    -/* Move the kernel do_div definition off to one side */
    -
    -#if defined __i386__
    -/* For ia32 we need to pull some tricks to get past various versions
    - * of the compiler which do not like us using do_div in the middle
    - * of large functions.
    - */
    -static inline __u32 xfs_do_div(void *a, __u32 b, int n)
    -{
    -	__u32	mod;
    -
    -	switch (n) {
    -		case 4:
    -			mod = *(__u32 *)a % b;
    -			*(__u32 *)a = *(__u32 *)a / b;
    -			return mod;
    -		case 8:
    -			{
    -			unsigned long __upper, __low, __high, __mod;
    -			__u64	c = *(__u64 *)a;
    -			__upper = __high = c >> 32;
    -			__low = c;
    -			if (__high) {
    -				__upper = __high % (b);
    -				__high = __high / (b);
    -			}
    -			asm("divl %2":"=a" (__low), "=d" (__mod):"rm" (b), "0" (__low), "1" (__upper));
    -			asm("":"=A" (c):"a" (__low),"d" (__high));
    -			*(__u64 *)a = c;
    -			return __mod;
    -			}
    -	}
    -
    -	/* NOTREACHED */
    -	return 0;
    -}
    -
    -/* Side effect free 64 bit mod operation */
    -static inline __u32 xfs_do_mod(void *a, __u32 b, int n)
    -{
    -	switch (n) {
    -		case 4:
    -			return *(__u32 *)a % b;
    -		case 8:
    -			{
    -			unsigned long __upper, __low, __high, __mod;
    -			__u64	c = *(__u64 *)a;
    -			__upper = __high = c >> 32;
    -			__low = c;
    -			if (__high) {
    -				__upper = __high % (b);
    -				__high = __high / (b);
    -			}
    -			asm("divl %2":"=a" (__low), "=d" (__mod):"rm" (b), "0" (__low), "1" (__upper));
    -			asm("":"=A" (c):"a" (__low),"d" (__high));
    -			return __mod;
    -			}
    -	}
    -
    -	/* NOTREACHED */
    -	return 0;
    -}
    -#else
    -
    -#define do_div(n, base) ({\
    -	int __res; \
    -	__res = ((__u64)(n)) % (__u32)(base); \
    -	(n) = ((__u64)(n)) / (__u32)(base); \
    -	__res; })
    -
    -static inline __u32 xfs_do_div(void *a, __u32 b, int n)
    -{
    -	__u32	mod;
    -
    -	switch (n) {
    -		case 4:
    -			mod = *(__u32 *)a % b;
    -			*(__u32 *)a = *(__u32 *)a / b;
    -			return mod;
    -		case 8:
    -			mod = do_div(*(__u64 *)a, b);
    -			return mod;
    -	}
    -
    -	/* NOTREACHED */
    -	return 0;
    -}
    -
    -/* Side effect free 64 bit mod operation */
    -static inline __u32 xfs_do_mod(void *a, __u32 b, int n)
    -{
    -	switch (n) {
    -		case 4:
    -			return *(__u32 *)a % b;
    -		case 8:
    -			{
    -			__u64	c = *(__u64 *)a;
    -			return do_div(c, b);
    -			}
    -	}
    -
    -	/* NOTREACHED */
    -	return 0;
    -}
    -#endif
    -
    -#undef do_div
    -#define do_div(a, b)	xfs_do_div(&(a), (b), sizeof(a))
    -#define do_mod(a, b)	xfs_do_mod(&(a), (b), sizeof(a))
    -
    -static inline __uint64_t roundup_64(__uint64_t x, __uint32_t y)
    -{
    -	x += y - 1;
    -	do_div(x, y);
    -	return(x * y);
    -}
    -
    -#endif /* __XFS_FREEBSD__ */
    diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_freebsd_iget.c b/sys/gnu/fs/xfs/FreeBSD/xfs_freebsd_iget.c
    deleted file mode 100644
    index e4e1e8d57a3..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/xfs_freebsd_iget.c
    +++ /dev/null
    @@ -1,419 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
    - * Copyright (c) 2006 Russell Cattelan Digital Elves, Inc. All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or modify it
    - * under the terms of version 2 of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful, but
    - * WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    - *
    - * Further, this software is distributed without any warranty that it is
    - * free of the rightful claim of any third person regarding infringement
    - * or the like.  Any license provided herein, whether implied or
    - * otherwise, applies only to this software file.  Patent licenses, if
    - * any, provided herein do not apply to combinations of this program with
    - * other software, or any other product whatsoever.
    - *
    - * You should have received a copy of the GNU General Public License along
    - * with this program; if not, write the Free Software Foundation, Inc., 59
    - * Temple Place - Suite 330, Boston MA 02111-1307, USA.
    - *
    - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
    - * Mountain View, CA  94043, or:
    - *
    - * http://www.sgi.com
    - *
    - * For further information regarding this notice, see:
    - *
    - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
    - */
    -
    -#include "xfs.h"
    -
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_inum.h"
    -#include "xfs_log.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_btree.h"
    -#include "xfs_ialloc.h"
    -#include "xfs_quota.h"
    -#include "xfs_utils.h"
    -#include "xfs_vnode.h"
    -
    -static int xfs_vn_allocate(xfs_mount_t *, xfs_inode_t *, struct xfs_vnode **);
    -
    -/*
    - * Look up an inode by number in the given file system.
    - * The inode is looked up in the hash table for the file system
    - * represented by the mount point parameter mp.  Each bucket of
    - * the hash table is guarded by an individual semaphore.
    - *
    - * If the inode is found in the hash table, its corresponding vnode
    - * is obtained with a call to vn_get().  This call takes care of
    - * coordination with the reclamation of the inode and vnode.  Note
    - * that the vmap structure is filled in while holding the hash lock.
    - * This gives us the state of the inode/vnode when we found it and
    - * is used for coordination in vn_get().
    - *
    - * If it is not in core, read it in from the file system's device and
    - * add the inode into the hash table.
    - *
    - * The inode is locked according to the value of the lock_flags parameter.
    - * This flag parameter indicates how and if the inode's IO lock and inode lock
    - * should be taken.
    - *
    - * mp -- the mount point structure for the current file system.  It points
    - *       to the inode hash table.
    - * tp -- a pointer to the current transaction if there is one.  This is
    - *       simply passed through to the xfs_iread() call.
    - * ino -- the number of the inode desired.  This is the unique identifier
    - *        within the file system for the inode being requested.
    - * lock_flags -- flags indicating how to lock the inode.  See the comment
    - *		 for xfs_ilock() for a list of valid values.
    - * bno -- the block number starting the buffer containing the inode,
    - *	  if known (as by bulkstat), else 0.
    - */
    -int
    -xfs_iget(
    -	xfs_mount_t	*mp,
    -	xfs_trans_t	*tp,
    -	xfs_ino_t	ino,
    -	uint		flags,
    -	uint		lock_flags,
    -	xfs_inode_t	**ipp,
    -	xfs_daddr_t	bno)
    -{
    -	xfs_ihash_t	*ih;
    -	xfs_inode_t	*ip;
    -	xfs_inode_t	*iq;
    -	xfs_vnode_t	*vp;
    -	ulong		version;
    -	int		error;
    -	/* REFERENCED */
    -	int		newnode;
    -	xfs_chash_t	*ch;
    -	xfs_chashlist_t	*chl, *chlnew;
    -	vmap_t		vmap;
    -	SPLDECL(s);
    -
    -	XFS_STATS_INC(xs_ig_attempts);
    -
    -	ih = XFS_IHASH(mp, ino);
    -
    -again:
    -	read_lock(&ih->ih_lock);
    -
    -	for (ip = ih->ih_next; ip != NULL; ip = ip->i_next) {
    -		if (ip->i_ino == ino) {
    -			vp = XFS_ITOV(ip);
    -			VMAP(vp, vmap);
    -			/*
    -			 * Inode cache hit: if ip is not at the front of
    -			 * its hash chain, move it there now.
    -			 * Do this with the lock held for update, but
    -			 * do statistics after releasing the lock.
    -			 */
    -			if (ip->i_prevp != &ih->ih_next
    -			    && rwlock_trypromote(&ih->ih_lock)) {
    -
    -				if ((iq = ip->i_next)) {
    -					iq->i_prevp = ip->i_prevp;
    -				}
    -				*ip->i_prevp = iq;
    -				iq = ih->ih_next;
    -				iq->i_prevp = &ip->i_next;
    -				ip->i_next = iq;
    -				ip->i_prevp = &ih->ih_next;
    -				ih->ih_next = ip;
    -				write_unlock(&ih->ih_lock);
    -			} else {
    -				read_unlock(&ih->ih_lock);
    -			}
    -
    -			XFS_STATS_INC(xs_ig_found);
    -
    -			/*
    -			 * Get a reference to the vnode/inode.
    -			 * vn_get() takes care of coordination with
    -			 * the file system inode release and reclaim
    -			 * functions.  If it returns NULL, the inode
    -			 * has been reclaimed so just start the search
    -			 * over again.  We probably won't find it,
    -			 * but we could be racing with another cpu
    -			 * looking for the same inode so we have to at
    -			 * least look.
    -			 */
    -			if (!(vp = vn_get(vp, &vmap))) {
    -				XFS_STATS_INC(xs_ig_frecycle);
    -				goto again;
    -			}
    -
    -			if (lock_flags != 0) {
    -				ip->i_flags &= ~XFS_IRECLAIM;
    -				xfs_ilock(ip, lock_flags);
    -			}
    -
    -			newnode = (ip->i_d.di_mode == 0);
    -			if (newnode) {
    -				xfs_iocore_inode_reinit(ip);
    -			}
    -			ip->i_flags &= ~XFS_ISTALE;
    -
    -			vn_trace_exit(vp, "xfs_iget.found",
    -						(inst_t *)__return_address);
    -			goto return_ip;
    -		}
    -	}
    -
    -	/*
    -	 * Inode cache miss: save the hash chain version stamp and unlock
    -	 * the chain, so we don't deadlock in vn_alloc.
    -	 */
    -	XFS_STATS_INC(xs_ig_missed);
    -
    -	version = ih->ih_version;
    -
    -	read_unlock(&ih->ih_lock);
    -
    -	/*
    -	 * Read the disk inode attributes into a new inode structure and get
    -	 * a new vnode for it. This should also initialize i_ino and i_mount.
    -	 */
    -	error = xfs_iread(mp, tp, ino, &ip, bno);
    -	if (error) {
    -		return error;
    -	}
    -
    -	error = xfs_vn_allocate(mp, ip, &vp);
    -	if (error) {
    -		return error;
    -	}
    -	vn_trace_exit(vp, "xfs_iget.alloc", (inst_t *)__return_address);
    -
    -	xfs_inode_lock_init(ip, vp);
    -	xfs_iocore_inode_init(ip);
    -
    -	if (lock_flags != 0) {
    -		xfs_ilock(ip, lock_flags);
    -	}
    -
    -	/*
    -	 * Put ip on its hash chain, unless someone else hashed a duplicate
    -	 * after we released the hash lock.
    -	 */
    -	write_lock(&ih->ih_lock);
    -
    -	if (ih->ih_version != version) {
    -		for (iq = ih->ih_next; iq != NULL; iq = iq->i_next) {
    -			if (iq->i_ino == ino) {
    -				write_unlock(&ih->ih_lock);
    -				xfs_idestroy(ip);
    -
    -				XFS_STATS_INC(xs_ig_dup);
    -				goto again;
    -			}
    -		}
    -	}
    -
    -	/*
    -	 * These values _must_ be set before releasing ihlock!
    -	 */
    -	ip->i_hash = ih;
    -	if ((iq = ih->ih_next)) {
    -		iq->i_prevp = &ip->i_next;
    -	}
    -	ip->i_next = iq;
    -	ip->i_prevp = &ih->ih_next;
    -	ih->ih_next = ip;
    -	ip->i_udquot = ip->i_gdquot = NULL;
    -	ih->ih_version++;
    -
    -	write_unlock(&ih->ih_lock);
    -
    -	/*
    -	 * put ip on its cluster's hash chain
    -	 */
    -	ASSERT(ip->i_chash == NULL && ip->i_cprev == NULL &&
    -	       ip->i_cnext == NULL);
    -
    -	chlnew = NULL;
    -	ch = XFS_CHASH(mp, ip->i_blkno);
    - chlredo:
    -	s = mutex_spinlock(&ch->ch_lock);
    -	for (chl = ch->ch_list; chl != NULL; chl = chl->chl_next) {
    -		if (chl->chl_blkno == ip->i_blkno) {
    -
    -			/* insert this inode into the doubly-linked list
    -			 * where chl points */
    -			if ((iq = chl->chl_ip)) {
    -				ip->i_cprev = iq->i_cprev;
    -				iq->i_cprev->i_cnext = ip;
    -				iq->i_cprev = ip;
    -				ip->i_cnext = iq;
    -			} else {
    -				ip->i_cnext = ip;
    -				ip->i_cprev = ip;
    -			}
    -			chl->chl_ip = ip;
    -			ip->i_chash = chl;
    -			break;
    -		}
    -	}
    -
    -	/* no hash list found for this block; add a new hash list */
    -	if (chl == NULL)  {
    -		if (chlnew == NULL) {
    -			mutex_spinunlock(&ch->ch_lock, s);
    -			ASSERT(xfs_chashlist_zone != NULL);
    -			chlnew = (xfs_chashlist_t *)
    -					kmem_zone_alloc(xfs_chashlist_zone,
    -						KM_SLEEP);
    -			ASSERT(chlnew != NULL);
    -			goto chlredo;
    -		} else {
    -			ip->i_cnext = ip;
    -			ip->i_cprev = ip;
    -			ip->i_chash = chlnew;
    -			chlnew->chl_ip = ip;
    -			chlnew->chl_blkno = ip->i_blkno;
    -			chlnew->chl_next = ch->ch_list;
    -			ch->ch_list = chlnew;
    -			chlnew = NULL;
    -		}
    -	} else {
    -		if (chlnew != NULL) {
    -			kmem_zone_free(xfs_chashlist_zone, chlnew);
    -		}
    -	}
    -
    -	mutex_spinunlock(&ch->ch_lock, s);
    -
    -	/*
    -	 * Link ip to its mount and thread it on the mount's inode list.
    -	 */
    -	XFS_MOUNT_ILOCK(mp);
    -	if ((iq = mp->m_inodes)) {
    -		ASSERT(iq->i_mprev->i_mnext == iq);
    -		ip->i_mprev = iq->i_mprev;
    -		iq->i_mprev->i_mnext = ip;
    -		iq->i_mprev = ip;
    -		ip->i_mnext = iq;
    -	} else {
    -		ip->i_mnext = ip;
    -		ip->i_mprev = ip;
    -	}
    -	mp->m_inodes = ip;
    -
    -	XFS_MOUNT_IUNLOCK(mp);
    -
    -	newnode = 1;
    -
    - return_ip:
    -	ASSERT(ip->i_df.if_ext_max ==
    -	       XFS_IFORK_DSIZE(ip) / sizeof(xfs_bmbt_rec_t));
    -
    -	ASSERT(((ip->i_d.di_flags & XFS_DIFLAG_REALTIME) != 0) ==
    -	       ((ip->i_iocore.io_flags & XFS_IOCORE_RT) != 0));
    -
    -	*ipp = ip;
    -
    -	/*
    -	 * If we have a real type for an on-disk inode, we can set ops(&unlock)
    -	 * now.	 If it's a new inode being created, xfs_ialloc will handle it.
    -	 */
    -	XVFS_INIT_VNODE(XFS_MTOVFS(mp), vp, XFS_ITOBHV(ip), 1);
    -
    -	return 0;
    -}
    -
    -/*
    - * Special iput for brand-new inodes that are still locked
    - */
    -void
    -xfs_iput_new(xfs_inode_t	*ip,
    -	     uint		lock_flags)
    -{
    -	xfs_vnode_t		*vp = XFS_ITOV(ip);
    -
    -	vn_trace_entry(vp, "xfs_iput_new", (inst_t *)__return_address);
    -
    -	printf("xfs_iput_new: ip %p\n",ip);
    -	
    -	if ((ip->i_d.di_mode == 0)) {
    -		ASSERT(!(ip->i_flags & XFS_IRECLAIMABLE));
    -		//vn_mark_bad(vp);
    -		printf("xfs_iput_new: ip %p di_mode == 0\n",ip);
    -		/* mabe call vgone here? RMC */
    -	}
    -	if (lock_flags)
    -		xfs_iunlock(ip, lock_flags);
    -
    -	ASSERT_VOP_LOCKED(vp->v_vnode, "xfs_iput_new");
    -	vput(vp->v_vnode);
    -}
    -
    -extern struct vop_vector xfs_vnops;
    -
    -static int
    -xfs_vn_allocate(xfs_mount_t *mp, xfs_inode_t *ip, struct xfs_vnode **vpp)
    -{
    -	struct vnode *vp;
    -	struct xfs_vnode *vdata;
    -	int error;
    -
    -	/* Use zone allocator here? */
    -	vdata = kmem_zalloc(sizeof(*vdata), KM_SLEEP);
    -
    -	error = getnewvnode("xfs", XVFSTOMNT(XFS_MTOVFS(mp)),
    -			    &xfs_vnops, &vp);
    -	if (error) {
    -		kmem_free(vdata, sizeof(*vdata));
    -		return (error);
    -	}
    -
    -	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
    -	VN_LOCK_AREC(vp);
    -	error = insmntque(vp, XVFSTOMNT(XFS_MTOVFS(mp)));
    -	if (error != 0) {
    -		kmem_free(vdata, sizeof(*vdata));
    -		return (error);
    -	}
    -
    -	vp->v_data = (void *)vdata;
    -	vdata->v_number= 0;
    -	vdata->v_inode = ip;
    -	vdata->v_vfsp  = XFS_MTOVFS(mp);
    -	vdata->v_vnode = vp;
    -
    - 	vn_bhv_head_init(VN_BHV_HEAD(vdata), "vnode");
    -
    -
    -#ifdef  CONFIG_XFS_VNODE_TRACING
    -        vp->v_trace = ktrace_alloc(VNODE_TRACE_SIZE, KM_SLEEP);
    -#endif  /* CONFIG_XFS_VNODE_TRACING */
    -
    -        vn_trace_exit(vp, "vn_initialize", (inst_t *)__return_address);
    -
    -	if (error == 0)
    -		*vpp = vdata;
    -
    -	return (error);
    -}
    diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_frw.c b/sys/gnu/fs/xfs/FreeBSD/xfs_frw.c
    deleted file mode 100644
    index 557ef1a52fc..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/xfs_frw.c
    +++ /dev/null
    @@ -1,891 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_alloc.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_quota.h"
    -#include "xfs_mount.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_bmap.h"
    -#include "xfs_btree.h"
    -#include "xfs_ialloc.h"
    -#include "xfs_rtalloc.h"
    -#include "xfs_error.h"
    -#include "xfs_itable.h"
    -#include "xfs_rw.h"
    -#include "xfs_acl.h"
    -#include "xfs_cap.h"
    -#include "xfs_mac.h"
    -#include "xfs_attr.h"
    -#include "xfs_inode_item.h"
    -#include "xfs_buf_item.h"
    -#include "xfs_utils.h"
    -#include "xfs_iomap.h"
    -
    -#if defined(XFS_RW_TRACE)
    -void
    -xfs_rw_enter_trace(
    -	int		tag,
    -	xfs_iocore_t	*io,
    -	const char	*buf,
    -	size_t		size,
    -	loff_t		offset,
    -	int		ioflags)
    -{
    -	xfs_inode_t	*ip = XFS_IO_INODE(io);
    -
    -	if (ip->i_rwtrace == NULL)
    -		return;
    -	ktrace_enter(ip->i_rwtrace,
    -		(void *)(unsigned long)tag,
    -		(void *)ip,
    -		(void *)((unsigned long)((ip->i_d.di_size >> 32) & 0xffffffff)),
    -		(void *)((unsigned long)(ip->i_d.di_size & 0xffffffff)),
    -		(void *)(__psint_t)buf,
    -		(void *)((unsigned long)size),
    -		(void *)((unsigned long)((offset >> 32) & 0xffffffff)),
    -		(void *)((unsigned long)(offset & 0xffffffff)),
    -		(void *)((unsigned long)ioflags),
    -		(void *)((unsigned long)((io->io_new_size >> 32) & 0xffffffff)),
    -		(void *)((unsigned long)(io->io_new_size & 0xffffffff)),
    -		(void *)NULL,
    -		(void *)NULL,
    -		(void *)NULL,
    -		(void *)NULL,
    -		(void *)NULL);
    -}
    -
    -void
    -xfs_inval_cached_trace(
    -	xfs_iocore_t	*io,
    -	xfs_off_t	offset,
    -	xfs_off_t	len,
    -	xfs_off_t	first,
    -	xfs_off_t	last)
    -{
    -	xfs_inode_t	*ip = XFS_IO_INODE(io);
    -
    -	if (ip->i_rwtrace == NULL)
    -		return;
    -	ktrace_enter(ip->i_rwtrace,
    -		(void *)(__psint_t)XFS_INVAL_CACHED,
    -		(void *)ip,
    -		(void *)((unsigned long)((offset >> 32) & 0xffffffff)),
    -		(void *)((unsigned long)(offset & 0xffffffff)),
    -		(void *)((unsigned long)((len >> 32) & 0xffffffff)),
    -		(void *)((unsigned long)(len & 0xffffffff)),
    -		(void *)((unsigned long)((first >> 32) & 0xffffffff)),
    -		(void *)((unsigned long)(first & 0xffffffff)),
    -		(void *)((unsigned long)((last >> 32) & 0xffffffff)),
    -		(void *)((unsigned long)(last & 0xffffffff)),
    -		(void *)NULL,
    -		(void *)NULL,
    -		(void *)NULL,
    -		(void *)NULL,
    -		(void *)NULL,
    -		(void *)NULL);
    -}
    -#endif
    -
    -/*
    - *	xfs_iozero
    - *
    - *	xfs_iozero clears the specified range of buffer supplied,
    - *	and marks all the affected blocks as valid and modified.  If
    - *	an affected block is not allocated, it will be allocated.  If
    - *	an affected block is not completely overwritten, and is not
    - *	valid before the operation, it will be read from disk before
    - *	being partially zeroed.
    - */
    -STATIC int
    -xfs_iozero(
    -	xfs_vnode_t		*vp,	/* vnode			*/
    -	xfs_off_t		pos,	/* offset in file		*/
    -	size_t			count,	/* size of data to zero		*/
    -	xfs_off_t		end_size)	/* max file size to set */
    -{
    -	int			status;
    -	status = 0; /* XXXKAN: */
    -#ifdef XXXKAN
    -	unsigned		bytes;
    -	struct page		*page;
    -	struct address_space	*mapping;
    -	char			*kaddr;
    -
    -	mapping = ip->i_mapping;
    -	do {
    -		unsigned long index, offset;
    -
    -		offset = (pos & (PAGE_CACHE_SIZE -1)); /* Within page */
    -		index = pos >> PAGE_CACHE_SHIFT;
    -		bytes = PAGE_CACHE_SIZE - offset;
    -		if (bytes > count)
    -			bytes = count;
    -
    -		status = -ENOMEM;
    -		page = grab_cache_page(mapping, index);
    -		if (!page)
    -			break;
    -
    -		kaddr = kmap(page);
    -		status = mapping->a_ops->prepare_write(NULL, page, offset,
    -							offset + bytes);
    -		if (status) {
    -			goto unlock;
    -		}
    -
    -		memset((void *) (kaddr + offset), 0, bytes);
    -		flush_dcache_page(page);
    -		status = mapping->a_ops->commit_write(NULL, page, offset,
    -							offset + bytes);
    -		if (!status) {
    -			pos += bytes;
    -			count -= bytes;
    -			if (pos > i_size_read(ip))
    -				i_size_write(ip, pos < end_size ? pos : end_size);
    -		}
    -
    -unlock:
    -		kunmap(page);
    -		unlock_page(page);
    -		page_cache_release(page);
    -		if (status)
    -			break;
    -	} while (count);
    -#endif
    -	return (-status);
    -}
    -
    -ssize_t			/* bytes read, or (-)  error */
    -xfs_read(
    -	bhv_desc_t      *bdp,
    -	uio_t		*uio,
    -	int		ioflags,
    -	cred_t          *credp)
    -{
    -	ssize_t		ret, size;
    -	xfs_fsize_t	n;
    -	xfs_inode_t	*ip;
    -	xfs_mount_t	*mp;
    -
    -	ip = XFS_BHVTOI(bdp);
    -	mp = ip->i_mount;
    -
    -	XFS_STATS_INC(xs_read_calls);
    -
    -	if (unlikely(ioflags & IO_ISDIRECT)) {
    -		if (((__psint_t)buf & BBMASK) ||
    -		    (uio->uio_offset & mp->m_blockmask) ||
    -		    (uio->uio_resid & mp->m_blockmask)) {
    -			if (uio->uio_offset >= ip->i_d.di_size) {
    -				return (0);
    -			}
    -			return EINVAL;
    -		}
    -	}
    -
    -	if (uio->uio_resid == 0)
    -		return 0;
    -	n = XFS_MAXIOFFSET(mp) - uio->uio_offset;
    -	if (n <= 0)
    -		return EFBIG;
    -
    -	size = (n < uio->uio_resid)? n : uio->uio_resid;
    -
    -	if (XFS_FORCED_SHUTDOWN(mp)) {
    -		return EIO;
    -	}
    -
    -	xfs_ilock(ip, XFS_IOLOCK_SHARED);
    -
    -#ifdef XXX
    -	if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) &&
    -	    !(ioflags & IO_INVIS)) {
    -		int error;
    -		vrwlock_t locktype = VRWLOCK_READ;
    -		int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG_RD(ioflags);
    -
    -		error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp),
    -			uio->uio_offset, size, dmflags, &locktype);
    -		if (error) {
    -			xfs_iunlock(ip, XFS_IOLOCK_SHARED);
    -			return (error);
    -		}
    -	}
    -#endif
    -
    -	ret = xfs_read_file(mp, ip, uio, ioflags);
    -
    -	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
    -
    -	XFS_STATS_ADD(xs_read_bytes, ret);
    -
    -	if (likely((ioflags & IO_INVIS) == 0)) {
    -		xfs_ichgtime(ip, XFS_ICHGTIME_ACC);
    -	}
    -
    -	return ret;
    -}
    -
    -/*
    - * This routine is called to handle zeroing any space in the last
    - * block of the file that is beyond the EOF.  We do this since the
    - * size is being increased without writing anything to that block
    - * and we don't want anyone to read the garbage on the disk.
    - */
    -STATIC int				/* error (positive) */
    -xfs_zero_last_block(
    -	xfs_vnode_t	*vp,
    -	xfs_iocore_t	*io,
    -	xfs_fsize_t	isize,
    -	xfs_fsize_t	end_size)
    -{
    -	xfs_fileoff_t	last_fsb;
    -	xfs_mount_t	*mp;
    -	int		nimaps;
    -	int		zero_offset;
    -	int		zero_len;
    -	int		error = 0;
    -	xfs_bmbt_irec_t	imap;
    -	xfs_off_t	loff;
    -
    -	ASSERT(ismrlocked(io->io_lock, MR_UPDATE) != 0);
    -
    -	mp = io->io_mount;
    -
    -	zero_offset = XFS_B_FSB_OFFSET(mp, isize);
    -	if (zero_offset == 0) {
    -		/*
    -		 * There are no extra bytes in the last block on disk to
    -		 * zero, so return.
    -		 */
    -		return 0;
    -	}
    -
    -	last_fsb = XFS_B_TO_FSBT(mp, isize);
    -	nimaps = 1;
    -	error = XFS_BMAPI(mp, NULL, io, last_fsb, 1, 0, NULL, 0, &imap,
    -			  &nimaps, NULL, NULL);
    -	if (error) {
    -		return error;
    -	}
    -	ASSERT(nimaps > 0);
    -	/*
    -	 * If the block underlying isize is just a hole, then there
    -	 * is nothing to zero.
    -	 */
    -	if (imap.br_startblock == HOLESTARTBLOCK) {
    -		return 0;
    -	}
    -	/*
    -	 * Zero the part of the last block beyond the EOF, and write it
    -	 * out sync.  We need to drop the ilock while we do this so we
    -	 * don't deadlock when the buffer cache calls back to us.
    -	 */
    -	XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL| XFS_EXTSIZE_RD);
    -	loff = XFS_FSB_TO_B(mp, last_fsb);
    -
    -	zero_len = mp->m_sb.sb_blocksize - zero_offset;
    -
    -	error = xfs_iozero(vp, loff + zero_offset, zero_len, end_size);
    -
    -	XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
    -	ASSERT(error >= 0);
    -	return error;
    -}
    -
    -/*
    - * Zero any on disk space between the current EOF and the new,
    - * larger EOF.  This handles the normal case of zeroing the remainder
    - * of the last block in the file and the unusual case of zeroing blocks
    - * out beyond the size of the file.  This second case only happens
    - * with fixed size extents and when the system crashes before the inode
    - * size was updated but after blocks were allocated.  If fill is set,
    - * then any holes in the range are filled and zeroed.  If not, the holes
    - * are left alone as holes.
    - */
    -
    -int					/* error (positive) */
    -xfs_zero_eof(
    -	xfs_vnode_t	*vp,
    -	xfs_iocore_t	*io,
    -	xfs_off_t	offset,		/* starting I/O offset */
    -	xfs_fsize_t	isize,		/* current inode size */
    -	xfs_fsize_t	end_size)	/* terminal inode size */
    -{
    -	xfs_fileoff_t	start_zero_fsb;
    -	xfs_fileoff_t	end_zero_fsb;
    -	xfs_fileoff_t	zero_count_fsb;
    -	xfs_fileoff_t	last_fsb;
    -	xfs_extlen_t	buf_len_fsb;
    -	xfs_mount_t	*mp;
    -	int		nimaps;
    -	int		error = 0;
    -	xfs_bmbt_irec_t	imap;
    -
    -	ASSERT(ismrlocked(io->io_lock, MR_UPDATE));
    -	ASSERT(ismrlocked(io->io_iolock, MR_UPDATE));
    -	ASSERT(offset > isize);
    -
    -	mp = io->io_mount;
    -
    -	/*
    -	 * First handle zeroing the block on which isize resides.
    -	 * We only zero a part of that block so it is handled specially.
    -	 */
    -	error = xfs_zero_last_block(vp, io, isize, end_size);
    -	if (error) {
    -		ASSERT(ismrlocked(io->io_lock, MR_UPDATE));
    -		ASSERT(ismrlocked(io->io_iolock, MR_UPDATE));
    -		return error;
    -	}
    -
    -	/*
    -	 * Calculate the range between the new size and the old
    -	 * where blocks needing to be zeroed may exist.  To get the
    -	 * block where the last byte in the file currently resides,
    -	 * we need to subtract one from the size and truncate back
    -	 * to a block boundary.  We subtract 1 in case the size is
    -	 * exactly on a block boundary.
    -	 */
    -	last_fsb = isize ? XFS_B_TO_FSBT(mp, isize - 1) : (xfs_fileoff_t)-1;
    -	start_zero_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)isize);
    -	end_zero_fsb = XFS_B_TO_FSBT(mp, offset - 1);
    -	ASSERT((xfs_sfiloff_t)last_fsb < (xfs_sfiloff_t)start_zero_fsb);
    -	if (last_fsb == end_zero_fsb) {
    -		/*
    -		 * The size was only incremented on its last block.
    -		 * We took care of that above, so just return.
    -		 */
    -		return 0;
    -	}
    -
    -	ASSERT(start_zero_fsb <= end_zero_fsb);
    -	while (start_zero_fsb <= end_zero_fsb) {
    -		nimaps = 1;
    -		zero_count_fsb = end_zero_fsb - start_zero_fsb + 1;
    -		error = XFS_BMAPI(mp, NULL, io, start_zero_fsb, zero_count_fsb,
    -				  0, NULL, 0, &imap, &nimaps, NULL, NULL);
    -		if (error) {
    -			ASSERT(ismrlocked(io->io_lock, MR_UPDATE));
    -			ASSERT(ismrlocked(io->io_iolock, MR_UPDATE));
    -			return error;
    -		}
    -		ASSERT(nimaps > 0);
    -
    -		if (imap.br_state == XFS_EXT_UNWRITTEN ||
    -		    imap.br_startblock == HOLESTARTBLOCK) {
    -			/*
    -			 * This loop handles initializing pages that were
    -			 * partially initialized by the code below this
    -			 * loop. It basically zeroes the part of the page
    -			 * that sits on a hole and sets the page as P_HOLE
    -			 * and calls remapf if it is a mapped file.
    -			 */
    -			start_zero_fsb = imap.br_startoff + imap.br_blockcount;
    -			ASSERT(start_zero_fsb <= (end_zero_fsb + 1));
    -			continue;
    -		}
    -
    -		/*
    -		 * There are blocks in the range requested.
    -		 * Zero them a single write at a time.  We actually
    -		 * don't zero the entire range returned if it is
    -		 * too big and simply loop around to get the rest.
    -		 * That is not the most efficient thing to do, but it
    -		 * is simple and this path should not be exercised often.
    -		 */
    -		buf_len_fsb = XFS_FILBLKS_MIN(imap.br_blockcount,
    -					      mp->m_writeio_blocks << 8);
    -		/*
    -		 * Drop the inode lock while we're doing the I/O.
    -		 * We'll still have the iolock to protect us.
    -		 */
    -		XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
    -
    -		error = xfs_iozero(vp,
    -				   XFS_FSB_TO_B(mp, start_zero_fsb),
    -				   XFS_FSB_TO_B(mp, buf_len_fsb),
    -				   end_size);
    -
    -		if (error) {
    -			goto out_lock;
    -		}
    -
    -		start_zero_fsb = imap.br_startoff + buf_len_fsb;
    -		ASSERT(start_zero_fsb <= (end_zero_fsb + 1));
    -
    -		XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
    -	}
    -
    -	return 0;
    -
    -out_lock:
    -
    -	XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
    -	ASSERT(error >= 0);
    -	return error;
    -}
    -
    -ssize_t				/* bytes written, or (-) error */
    -xfs_write(
    -	bhv_desc_t      *bdp,
    -	uio_t		*uio,
    -	int		ioflag,
    -	cred_t          *credp)
    -{
    -	xfs_inode_t	*xip;
    -	xfs_mount_t	*mp;
    -	ssize_t		ret = 0;
    -	int		error = 0;
    -	xfs_fsize_t     isize, new_size;
    -	xfs_fsize_t	n, limit;
    -	xfs_fsize_t	size;
    -	xfs_iocore_t    *io;
    -	xfs_vnode_t	*vp;
    -	int		iolock;
    -	//int		eventsent = 0;
    -	vrwlock_t	locktype;
    -	xfs_off_t	offset_c;
    -	xfs_off_t	*offset;
    -	xfs_off_t	pos;
    -
    -	XFS_STATS_INC(xs_write_calls);
    -
    -	vp = BHV_TO_VNODE(bdp);
    -	xip = XFS_BHVTOI(bdp);
    -
    -	io = &xip->i_iocore;
    -	mp = io->io_mount;
    -
    -	if (XFS_FORCED_SHUTDOWN(xip->i_mount)) {
    -		return EIO;
    -	}
    -
    -	size = uio->uio_resid;
    -	pos = offset_c = uio->uio_offset;
    -	offset = &offset_c;
    -
    -	if (unlikely(ioflag & IO_ISDIRECT)) {
    -		if (((__psint_t)buf & BBMASK) ||
    -		    (*offset & mp->m_blockmask) ||
    -		    (size  & mp->m_blockmask)) {
    -			return EINVAL;
    -		}
    -		iolock = XFS_IOLOCK_SHARED;
    -		locktype = VRWLOCK_WRITE_DIRECT;
    -	} else {
    -		if (io->io_flags & XFS_IOCORE_RT)
    -			return EINVAL;
    -		iolock = XFS_IOLOCK_EXCL;
    -		locktype = VRWLOCK_WRITE;
    -	}
    -
    -	iolock = XFS_IOLOCK_EXCL;
    -	locktype = VRWLOCK_WRITE;
    -
    -	xfs_ilock(xip, XFS_ILOCK_EXCL|iolock);
    -
    -	isize = xip->i_d.di_size;
    -	limit = XFS_MAXIOFFSET(mp);
    -
    -	if (ioflag & O_APPEND)
    -		*offset = isize;
    -
    -//start:
    -	n = limit - *offset;
    -	if (n <= 0) {
    -		xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock);
    -		return EFBIG;
    -	}
    -	if (n < size)
    -		size = n;
    -
    -	new_size = *offset + size;
    -	if (new_size > isize) {
    -		io->io_new_size = new_size;
    -	}
    -
    -#ifdef RMC
    -	/* probably be a long time before if ever that we do dmapi */
    -	if ((DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_WRITE) &&
    -	    !(ioflags & IO_INVIS) && !eventsent)) {
    -		loff_t		savedsize = *offset;
    -		int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG_RD(ioflags);
    -
    -		xfs_iunlock(xip, XFS_ILOCK_EXCL);
    -		error = XFS_SEND_DATA(xip->i_mount, DM_EVENT_WRITE, vp,
    -				      *offset, size,
    -				      dmflags, &locktype);
    -		if (error) {
    -			if (iolock) xfs_iunlock(xip, iolock);
    -			return -error;
    -		}
    -		xfs_ilock(xip, XFS_ILOCK_EXCL);
    -		eventsent = 1;
    -
    -		/*
    -		 * The iolock was dropped and reaquired in XFS_SEND_DATA
    -		 * so we have to recheck the size when appending.
    -		 * We will only "goto start;" once, since having sent the
    -		 * event prevents another call to XFS_SEND_DATA, which is
    -		 * what allows the size to change in the first place.
    -		 */
    -		if ((file->f_flags & O_APPEND) &&
    -		    savedsize != xip->i_d.di_size) {
    -			*offset = isize = xip->i_d.di_size;
    -			goto start;
    -		}
    -	}
    -#endif
    -
    -	/*
    -	 * If the offset is beyond the size of the file, we have a couple
    -	 * of things to do. First, if there is already space allocated
    -	 * we need to either create holes or zero the disk or ...
    -	 *
    -	 * If there is a page where the previous size lands, we need
    -	 * to zero it out up to the new size.
    -	 */
    -
    -	if (!(ioflag & IO_ISDIRECT) && (*offset > isize && isize)) {
    -		error = xfs_zero_eof(BHV_TO_VNODE(bdp), io, *offset,
    -			isize, *offset + size);
    -		if (error) {
    -			xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock);
    -			return(-error);
    -		}
    -	}
    -	xfs_iunlock(xip, XFS_ILOCK_EXCL);
    -
    -#if 0
    -	/*
    -	 * If we're writing the file then make sure to clear the
    -	 * setuid and setgid bits if the process is not being run
    -	 * by root.  This keeps people from modifying setuid and
    -	 * setgid binaries.
    -	 */
    -
    -	if (((xip->i_d.di_mode & S_ISUID) ||
    -	    ((xip->i_d.di_mode & (S_ISGID | S_IXGRP)) ==
    -		(S_ISGID | S_IXGRP))) &&
    -	     !capable(CAP_FSETID)) {
    -		error = xfs_write_clear_setuid(xip);
    -		if (likely(!error))
    -			error = -remove_suid(file->f_dentry);
    -		if (unlikely(error)) {
    -			xfs_iunlock(xip, iolock);
    -			goto out_unlock_mutex;
    -		}
    -	}
    -#endif
    -
    -
    -//retry:
    -	if (unlikely(ioflag & IO_ISDIRECT)) {
    -
    -#ifdef RMC
    -		xfs_off_t	pos = *offset;
    -		struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
    -		struct inode    *inode = mapping->host;
    -
    -		ret = precheck_file_write(file, inode, &size,  &pos);
    -		if (ret || size == 0)
    -			goto error;
    -
    -		xfs_inval_cached_pages(vp, io, pos, 1, 1);
    -		inode->i_ctime = inode->i_mtime = CURRENT_TIME;
    -		/* mark_inode_dirty_sync(inode); - we do this later */
    -
    -		xfs_rw_enter_trace(XFS_DIOWR_ENTER, io, buf, size, pos, ioflags);
    -		ret = generic_file_direct_IO(WRITE, file, (char *)buf, size, pos);
    -		xfs_inval_cached_pages(vp, io, pos, 1, 1);
    -		if (ret > 0)
    -			*offset += ret;
    -#endif
    -	} else {
    -		xfs_rw_enter_trace(XFS_WRITE_ENTER, io, buf, size, *offset, ioflags);
    -		ret = xfs_write_file(xip,uio,ioflag);
    -	}
    -
    -	xfs_ichgtime(xip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
    -
    -
    -//error:
    -	if (ret <= 0) {
    -		if (iolock)
    -			xfs_rwunlock(bdp, locktype);
    -		return ret;
    -	}
    -
    -	XFS_STATS_ADD(xs_write_bytes, ret);
    -
    -	if (*offset > xip->i_d.di_size) {
    -		xfs_ilock(xip, XFS_ILOCK_EXCL);
    -		if (*offset > xip->i_d.di_size) {
    -			printf("xfs_write look at doing more here %s:%d\n",__FILE__,__LINE__);
    -#ifdef RMC
    -			struct inode	*inode = LINVFS_GET_IP(vp);
    -			i_size_write(inode, *offset);
    -			mark_inode_dirty_sync(inode);
    -#endif
    -
    -			xip->i_d.di_size = *offset;
    -			xip->i_update_core = 1;
    -			xip->i_update_size = 1;
    -		}
    -		xfs_iunlock(xip, XFS_ILOCK_EXCL);
    -	}
    -
    -	/* Handle various SYNC-type writes */
    -#if 0
    -//	if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) {
    -#endif
    -	if (ioflag & IO_SYNC) {
    -		/*
    -		 * If we're treating this as O_DSYNC and we have not updated the
    -		 * size, force the log.
    -		 */
    -		if (!(mp->m_flags & XFS_MOUNT_OSYNCISOSYNC) &&
    -		    !(xip->i_update_size)) {
    -			xfs_inode_log_item_t	*iip = xip->i_itemp;
    -
    -			/*
    -			 * If an allocation transaction occurred
    -			 * without extending the size, then we have to force
    -			 * the log up the proper point to ensure that the
    -			 * allocation is permanent.  We can't count on
    -			 * the fact that buffered writes lock out direct I/O
    -			 * writes - the direct I/O write could have extended
    -			 * the size nontransactionally, then finished before
    -			 * we started.  xfs_write_file will think that the file
    -			 * didn't grow but the update isn't safe unless the
    -			 * size change is logged.
    -			 *
    -			 * Force the log if we've committed a transaction
    -			 * against the inode or if someone else has and
    -			 * the commit record hasn't gone to disk (e.g.
    -			 * the inode is pinned).  This guarantees that
    -			 * all changes affecting the inode are permanent
    -			 * when we return.
    -			 */
    -			if (iip && iip->ili_last_lsn) {
    -				xfs_log_force(mp, iip->ili_last_lsn,
    -						XFS_LOG_FORCE | XFS_LOG_SYNC);
    -			} else if (xfs_ipincount(xip) > 0) {
    -				xfs_log_force(mp, (xfs_lsn_t)0,
    -						XFS_LOG_FORCE | XFS_LOG_SYNC);
    -			}
    -
    -		} else {
    -			xfs_trans_t	*tp;
    -
    -			/*
    -			 * O_SYNC or O_DSYNC _with_ a size update are handled
    -			 * the same way.
    -			 *
    -			 * If the write was synchronous then we need to make
    -			 * sure that the inode modification time is permanent.
    -			 * We'll have updated the timestamp above, so here
    -			 * we use a synchronous transaction to log the inode.
    -			 * It's not fast, but it's necessary.
    -			 *
    -			 * If this a dsync write and the size got changed
    -			 * non-transactionally, then we need to ensure that
    -			 * the size change gets logged in a synchronous
    -			 * transaction.
    -			 */
    -
    -			tp = xfs_trans_alloc(mp, XFS_TRANS_WRITE_SYNC);
    -			if ((error = xfs_trans_reserve(tp, 0,
    -						      XFS_SWRITE_LOG_RES(mp),
    -						      0, 0, 0))) {
    -				/* Transaction reserve failed */
    -				xfs_trans_cancel(tp, 0);
    -			} else {
    -				/* Transaction reserve successful */
    -				xfs_ilock(xip, XFS_ILOCK_EXCL);
    -				xfs_trans_ijoin(tp, xip, XFS_ILOCK_EXCL);
    -				xfs_trans_ihold(tp, xip);
    -				xfs_trans_log_inode(tp, xip, XFS_ILOG_CORE);
    -				xfs_trans_set_sync(tp);
    -				error = xfs_trans_commit(tp, 0, NULL);
    -				xfs_iunlock(xip, XFS_ILOCK_EXCL);
    -			}
    -			if (error)
    -				goto out_unlock_internal;
    -		}
    -
    -		xfs_rwunlock(bdp, locktype);
    -		return ret;
    -
    -	} /* (ioflags & O_SYNC) */
    -
    -out_unlock_internal:
    -	xfs_rwunlock(bdp, locktype);
    -#if 0
    -out_unlock_mutex:
    -	if (need_i_mutex)
    -		mutex_unlock(&inode->i_mutex);
    -#endif
    - //out_nounlocks:
    -	return -error;
    -}
    -
    -/*
    - * Initiate IO on given buffer.
    - */
    -int
    -xfs_buf_iorequest(struct xfs_buf *bp)
    -{
    -	bp->b_flags &= ~(B_INVAL|B_DONE);
    -	bp->b_ioflags &= ~BIO_ERROR;
    -
    -	if (bp->b_flags & B_ASYNC)
    -		BUF_KERNPROC(bp);
    -
    -	if (bp->b_vp == NULL) {
    -		if (bp->b_iocmd == BIO_WRITE) {
    -			bp->b_flags &= ~(B_DELWRI | B_DEFERRED);
    -			bufobj_wref(bp->b_bufobj);
    -		}
    -
    -		bp->b_iooffset = (bp->b_blkno << BBSHIFT);
    -		bstrategy(bp);
    -	} else {
    -		if (bp->b_iocmd == BIO_WRITE) {
    -			/* Mark the buffer clean */
    -			bundirty(bp);
    -			bufobj_wref(bp->b_bufobj);
    -			vfs_busy_pages(bp, 1);
    -		} else if (bp->b_iocmd == BIO_READ) {
    -			vfs_busy_pages(bp, 0);
    -		}
    -		bp->b_iooffset = dbtob(bp->b_blkno);
    -		bstrategy(bp);
    -	}
    -	return 0;
    -}
    -
    -/*
    - * All xfs metadata buffers except log state machine buffers
    - * get this attached as their b_bdstrat callback function.
    - * This is so that we can catch a buffer
    - * after prematurely unpinning it to forcibly shutdown the filesystem.
    - */
    -int
    -xfs_bdstrat_cb(struct xfs_buf *bp)
    -{
    -	xfs_mount_t	*mp;
    -
    -	mp = XFS_BUF_FSPRIVATE3(bp, xfs_mount_t *);
    -	if (!XFS_FORCED_SHUTDOWN(mp)) {
    -		xfs_buf_iorequest(bp);
    -		return 0;
    -	} else {
    -		xfs_buftrace("XFS__BDSTRAT IOERROR", bp);
    -		/*
    -		 * Metadata write that didn't get logged but
    -		 * written delayed anyway. These aren't associated
    -		 * with a transaction, and can be ignored.
    -		 */
    -		if (XFS_BUF_IODONE_FUNC(bp) == NULL &&
    -		    (XFS_BUF_ISREAD(bp)) == 0)
    -			return (xfs_bioerror_relse(bp));
    -		else
    -			return (xfs_bioerror(bp));
    -	}
    -}
    -
    -
    -int
    -xfs_bmap(bhv_desc_t	*bdp,
    -	xfs_off_t	offset,
    -	ssize_t		count,
    -	int		flags,
    -	xfs_iomap_t	*iomapp,
    -	int		*niomaps)
    -{
    -	xfs_inode_t	*ip = XFS_BHVTOI(bdp);
    -	xfs_iocore_t	*io = &ip->i_iocore;
    -
    -	ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFREG);
    -	ASSERT(((ip->i_d.di_flags & XFS_DIFLAG_REALTIME) != 0) ==
    -	       ((ip->i_iocore.io_flags & XFS_IOCORE_RT) != 0));
    -
    -	return xfs_iomap(io, offset, count, flags, iomapp, niomaps);
    -}
    -
    -/*
    - * Wrapper around bdstrat so that we can stop data
    - * from going to disk in case we are shutting down the filesystem.
    - * Typically user data goes thru this path; one of the exceptions
    - * is the superblock.
    - */
    -int
    -xfsbdstrat(
    -	struct xfs_mount	*mp,
    -	struct xfs_buf		*bp)
    -{
    -	ASSERT(mp);
    -	if (!XFS_FORCED_SHUTDOWN(mp)) {
    -
    -		xfs_buf_iorequest(bp);
    -		return 0;
    -	}
    -
    -	xfs_buftrace("XFSBDSTRAT IOERROR", bp);
    -	return (xfs_bioerror_relse(bp));
    -}
    -
    -/*
    - * If the underlying (data/log/rt) device is readonly, there are some
    - * operations that cannot proceed.
    - */
    -int
    -xfs_dev_is_read_only(
    -	xfs_mount_t		*mp,
    -	char			*message)
    -{
    -	if (xfs_readonly_buftarg(mp->m_ddev_targp) ||
    -	    xfs_readonly_buftarg(mp->m_logdev_targp) ||
    -	    (mp->m_rtdev_targp && xfs_readonly_buftarg(mp->m_rtdev_targp))) {
    -		cmn_err(CE_NOTE,
    -			"XFS: %s required on read-only device.", message);
    -		cmn_err(CE_NOTE,
    -			"XFS: write access unavailable, cannot proceed.");
    -		return EROFS;
    -	}
    -	return 0;
    -}
    diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_frw.h b/sys/gnu/fs/xfs/FreeBSD/xfs_frw.h
    deleted file mode 100644
    index 78d93f9a85d..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/xfs_frw.h
    +++ /dev/null
    @@ -1,106 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or modify it
    - * under the terms of version 2 of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful, but
    - * WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    - *
    - * Further, this software is distributed without any warranty that it is
    - * free of the rightful claim of any third person regarding infringement
    - * or the like.  Any license provided herein, whether implied or
    - * otherwise, applies only to this software file.  Patent licenses, if
    - * any, provided herein do not apply to combinations of this program with
    - * other software, or any other product whatsoever.
    - *
    - * You should have received a copy of the GNU General Public License along
    - * with this program; if not, write the Free Software Foundation, Inc., 59
    - * Temple Place - Suite 330, Boston MA 02111-1307, USA.
    - *
    - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
    - * Mountain View, CA  94043, or:
    - *
    - * http://www.sgi.com
    - *
    - * For further information regarding this notice, see:
    - *
    - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
    - */
    -#ifndef __XFS_FRW_H__
    -#define __XFS_FRW_H__
    -
    -struct xfs_vnode;
    -struct bhv_desc;
    -struct xfs_mount;
    -struct xfs_iocore;
    -struct xfs_inode;
    -struct xfs_bmbt_irec;
    -struct xfs_buf;
    -struct xfs_iomap;
    -
    -#if defined(XFS_RW_TRACE)
    -/*
    - * Defines for the trace mechanisms in xfs_lrw.c.
    - */
    -#define	XFS_RW_KTRACE_SIZE	128
    -
    -#define	XFS_READ_ENTER		1
    -#define	XFS_WRITE_ENTER		2
    -#define XFS_IOMAP_READ_ENTER	3
    -#define	XFS_IOMAP_WRITE_ENTER	4
    -#define	XFS_IOMAP_READ_MAP	5
    -#define	XFS_IOMAP_WRITE_MAP	6
    -#define	XFS_IOMAP_WRITE_NOSPACE	7
    -#define	XFS_ITRUNC_START	8
    -#define	XFS_ITRUNC_FINISH1	9
    -#define	XFS_ITRUNC_FINISH2	10
    -#define	XFS_CTRUNC1		11
    -#define	XFS_CTRUNC2		12
    -#define	XFS_CTRUNC3		13
    -#define	XFS_CTRUNC4		14
    -#define	XFS_CTRUNC5		15
    -#define	XFS_CTRUNC6		16
    -#define	XFS_BUNMAPI		17
    -#define	XFS_INVAL_CACHED	18
    -#define	XFS_DIORD_ENTER		19
    -#define	XFS_DIOWR_ENTER		20
    -#define	XFS_SENDFILE_ENTER	21
    -#define	XFS_WRITEPAGE_ENTER	22
    -#define	XFS_RELEASEPAGE_ENTER	23
    -#define	XFS_IOMAP_ALLOC_ENTER	24
    -#define	XFS_IOMAP_ALLOC_MAP	25
    -#define	XFS_IOMAP_UNWRITTEN	26
    -extern void xfs_rw_enter_trace(int, struct xfs_iocore *,
    -			const char *, size_t, loff_t, int);
    -extern void xfs_inval_cached_trace(struct xfs_iocore *,
    -			xfs_off_t, xfs_off_t, xfs_off_t, xfs_off_t);
    -#else
    -#define xfs_rw_enter_trace(tag, io, buf, size, offset, ioflags)
    -#define xfs_inval_cached_trace(io, offset, len, first, last)
    -#endif
    -
    -/*
    - * Maximum count of bmaps used by read and write paths.
    - */
    -#define	XFS_MAX_RW_NBMAPS	4
    -
    -extern int xfs_bmap(struct bhv_desc *, xfs_off_t, ssize_t, int,
    -			struct xfs_iomap *, int *);
    -extern int xfsbdstrat(struct xfs_mount *, struct xfs_buf *);
    -extern int xfs_bdstrat_cb(struct xfs_buf *);
    -
    -extern int xfs_zero_eof(struct xfs_vnode *, struct xfs_iocore *, xfs_off_t,
    -				xfs_fsize_t, xfs_fsize_t);
    -extern void xfs_inval_cached_pages(struct xfs_vnode*, struct xfs_iocore *,
    -				xfs_off_t, int, int);
    -extern ssize_t xfs_read(bhv_desc_t *, uio_t *, int, cred_t *);
    -extern ssize_t xfs_write(bhv_desc_t *, uio_t *, int, cred_t *);
    -extern int xfs_dev_is_read_only(struct xfs_mount *, char *);
    -
    -extern int xfs_read_file(struct xfs_mount *mp, struct xfs_inode *ip, struct uio *uio,
    -		    int ioflag);
    -extern int xfs_write_file(struct xfs_inode *, struct uio *, int);
    -#endif	/* __XFS_FRW_H__ */
    diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_fs_subr.c b/sys/gnu/fs/xfs/FreeBSD/xfs_fs_subr.c
    deleted file mode 100644
    index dec6e2f8784..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/xfs_fs_subr.c
    +++ /dev/null
    @@ -1,131 +0,0 @@
    -/*
    - * Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or modify it
    - * under the terms of version 2 of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful, but
    - * WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    - *
    - * Further, this software is distributed without any warranty that it is
    - * free of the rightful claim of any third person regarding infringement
    - * or the like.  Any license provided herein, whether implied or
    - * otherwise, applies only to this software file.  Patent licenses, if
    - * any, provided herein do not apply to combinations of this program with
    - * other software, or any other product whatsoever.
    - *
    - * You should have received a copy of the GNU General Public License along
    - * with this program; if not, write the Free Software Foundation, Inc., 59
    - * Temple Place - Suite 330, Boston MA 02111-1307, USA.
    - *
    - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
    - * Mountain View, CA  94043, or:
    - *
    - * http://www.sgi.com
    - *
    - * For further information regarding this notice, see:
    - *
    - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
    - */
    -
    -#include "xfs.h"
    -
    -/*
    - * Stub for no-op vnode operations that return error status.
    - */
    -int
    -fs_noerr()
    -{
    -	return 0;
    -}
    -
    -/*
    - * Operation unsupported under this file system.
    - */
    -int
    -fs_nosys()
    -{
    -	return ENOSYS;
    -}
    -
    -/*
    - * Stub for inactive, strategy, and read/write lock/unlock.  Does nothing.
    - */
    -/* ARGSUSED */
    -void
    -fs_noval()
    -{
    -}
    -
    -/*
    - * vnode pcache layer for vnode_tosspages.
    - * 'last' parameter unused but left in for IRIX compatibility
    - */
    -void
    -fs_tosspages(
    -	bhv_desc_t	*bdp,
    -	xfs_off_t	first,
    -	xfs_off_t	last,
    -	int		fiopt)
    -{
    -#ifdef XXXKAN
    -	vnode_t		*vp = BHV_TO_VNODE(bdp);
    -	struct inode	*ip = LINVFS_GET_IP(vp);
    -
    -	if (VN_CACHED(vp))
    -		truncate_inode_pages(ip->i_mapping, first);
    -#endif
    -}
    -
    -
    -/*
    - * vnode pcache layer for vnode_flushinval_pages.
    - * 'last' parameter unused but left in for IRIX compatibility
    - */
    -void
    -fs_flushinval_pages(
    -	bhv_desc_t	*bdp,
    -	xfs_off_t	first,
    -	xfs_off_t	last,
    -	int		fiopt)
    -{
    -#ifdef XXXKAN
    -	vnode_t		*vp = BHV_TO_VNODE(bdp);
    -	struct inode	*ip = LINVFS_GET_IP(vp);
    -
    -	if (VN_CACHED(vp)) {
    -		filemap_fdatasync(ip->i_mapping);
    -		fsync_inode_data_buffers(ip);
    -		filemap_fdatawait(ip->i_mapping);
    -
    -		truncate_inode_pages(ip->i_mapping, first);
    -	}
    -#endif
    -}
    -
    -/*
    - * vnode pcache layer for vnode_flush_pages.
    - * 'last' parameter unused but left in for IRIX compatibility
    - */
    -int
    -fs_flush_pages(
    -	bhv_desc_t	*bdp,
    -	xfs_off_t	first,
    -	xfs_off_t	last,
    -	uint64_t	flags,
    -	int		fiopt)
    -{
    -#ifdef XXXKAN
    -	vnode_t		*vp = BHV_TO_VNODE(bdp);
    -	struct inode	*ip = LINVFS_GET_IP(vp);
    -
    -	if (VN_CACHED(vp)) {
    -		filemap_fdatasync(ip->i_mapping);
    -		fsync_inode_data_buffers(ip);
    -		filemap_fdatawait(ip->i_mapping);
    -	}
    -#endif
    -	return 0;
    -}
    diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_fs_subr.h b/sys/gnu/fs/xfs/FreeBSD/xfs_fs_subr.h
    deleted file mode 100644
    index 198b8dd7818..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/xfs_fs_subr.h
    +++ /dev/null
    @@ -1,49 +0,0 @@
    -/*
    - * Copyright (c) 2000, 2002 Silicon Graphics, Inc.  All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or modify it
    - * under the terms of version 2 of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful, but
    - * WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    - *
    - * Further, this software is distributed without any warranty that it is
    - * free of the rightful claim of any third person regarding infringement
    - * or the like.  Any license provided herein, whether implied or
    - * otherwise, applies only to this software file.  Patent licenses, if
    - * any, provided herein do not apply to combinations of this program with
    - * other software, or any other product whatsoever.
    - *
    - * You should have received a copy of the GNU General Public License along
    - * with this program; if not, write the Free Software Foundation, Inc., 59
    - * Temple Place - Suite 330, Boston MA 02111-1307, USA.
    - *
    - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
    - * Mountain View, CA  94043, or:
    - *
    - * http://www.sgi.com
    - *
    - * For further information regarding this notice, see:
    - *
    - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
    - */
    -#ifndef	__XFS_SUBR_H__
    -#define __XFS_SUBR_H__
    -
    -/*
    - * Utilities shared among file system implementations.
    - */
    -
    -struct cred;
    -
    -extern int	fs_noerr(void);
    -extern int	fs_nosys(void);
    -extern int	fs_nodev(void);
    -extern void	fs_noval(void);
    -extern void	fs_tosspages(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
    -extern void	fs_flushinval_pages(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
    -extern int	fs_flush_pages(bhv_desc_t *, xfs_off_t, xfs_off_t, uint64_t, int);
    -
    -#endif	/* __XFS_FS_SUBR_H__ */
    diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_globals.c b/sys/gnu/fs/xfs/FreeBSD/xfs_globals.c
    deleted file mode 100644
    index 1d4ac817611..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/xfs_globals.c
    +++ /dev/null
    @@ -1,77 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or modify it
    - * under the terms of version 2 of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful, but
    - * WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    - *
    - * Further, this software is distributed without any warranty that it is
    - * free of the rightful claim of any third person regarding infringement
    - * or the like.  Any license provided herein, whether implied or
    - * otherwise, applies only to this software file.  Patent licenses, if
    - * any, provided herein do not apply to combinations of this program with
    - * other software, or any other product whatsoever.
    - *
    - * You should have received a copy of the GNU General Public License along
    - * with this program; if not, write the Free Software Foundation, Inc., 59
    - * Temple Place - Suite 330, Boston MA 02111-1307, USA.
    - *
    - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
    - * Mountain View, CA  94043, or:
    - *
    - * http://www.sgi.com
    - *
    - * For further information regarding this notice, see:
    - *
    - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
    - */
    -
    -/*
    - * This file contains globals needed by XFS that were normally defined
    - * somewhere else in IRIX.
    - */
    -
    -#include "xfs.h"
    -#include "xfs_types.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_bit.h"
    -#include "xfs_refcache.h"
    -
    -/*
    - * Tunable XFS parameters.  xfs_params is required even when CONFIG_SYSCTL=n,
    - * other XFS code uses these values.
    - */
    -
    -xfs_param_t xfs_params = {
    -			  /*	MIN	DFLT	MAX	*/
    -#ifdef HAVE_REFCACHE
    -	.refcache_size	= {	0,	128,	XFS_REFCACHE_SIZE_MAX },
    -	.refcache_purge	= {	0,	32,	XFS_REFCACHE_SIZE_MAX },
    -#endif
    -	.restrict_chown	= {	0,		1,		1	},
    -	.sgid_inherit	= {	0,		0,		1	},
    -	.symlink_mode	= {	0,		0,		1	},
    -	.panic_mask	= {	0,		0,		127	},
    -	.error_level	= {	0,		3,		11	},
    -	.syncd_timer	= {	1*100,		30*100,		7200*100},
    -	.probe_dmapi	= {	0,		0,		1	},
    -	.probe_ioops	= {	0,		0,		1	},
    -	.probe_quota	= {	0,		1,		1	},
    -	.stats_clear	= {	0,		0,		1	},
    -	.inherit_sync	= {	0,		1,		1	},
    -	.inherit_nodump	= {	0,		1,		1	},
    -	.inherit_noatim = {	0,		1,		1	},
    -	.xfs_buf_timer	= {	100/2,		1*100,		30*100	},
    -	.xfs_buf_age	= {	1*100,		15*100,		7200*100},
    -	.inherit_nosym	= {	0,		0,		1	},
    -	.rotorstep	= {	1,		1,		255	},
    -};
    -
    -/*
    - * Global system credential structure.
    - */
    -cred_t sys_cred_val, *sys_cred = &sys_cred_val;
    diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_ioctl.c b/sys/gnu/fs/xfs/FreeBSD/xfs_ioctl.c
    deleted file mode 100644
    index ff5582c2d59..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/xfs_ioctl.c
    +++ /dev/null
    @@ -1,1460 +0,0 @@
    -/*
    - * Copyright (c) 2000-2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_alloc.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_btree.h"
    -#include "xfs_ialloc.h"
    -#include "xfs_rtalloc.h"
    -#include "xfs_itable.h"
    -#include "xfs_error.h"
    -#include "xfs_rw.h"
    -#include "xfs_acl.h"
    -#include "xfs_cap.h"
    -#include "xfs_mac.h"
    -#include "xfs_attr.h"
    -#include "xfs_bmap.h"
    -#include "xfs_buf_item.h"
    -#include "xfs_utils.h"
    -#include "xfs_dfrag.h"
    -#include "xfs_fsops.h"
    -
    -
    -#include 
    -#if 1
    -/*
    - * ioctl commands that are used by Linux filesystems
    - */
    -#define XFS_IOC_GETXFLAGS	_IOR('f', 1, long)
    -#define XFS_IOC_SETXFLAGS	_IOW('f', 2, long)
    -#define XFS_IOC_GETVERSION	_IOR('v', 1, long)
    -
    -#undef copy_to_user
    -static __inline__ int
    -copy_to_user(void *dst, void *src, int len) {
    -	memcpy(dst,src,len);
    -	return 0;
    -}
    -#undef copy_from_user
    -static __inline__ int
    -copy_from_user(void *dst, void *src, int len) {
    -	memcpy(dst,src,len);
    -	return 0;
    -}
    -
    -/*
    - * xfs_find_handle maps from userspace xfs_fsop_handlereq structure to
    - * a file or fs handle.
    - *
    - * XFS_IOC_PATH_TO_FSHANDLE
    - *    returns fs handle for a mount point or path within that mount point
    - * XFS_IOC_FD_TO_HANDLE
    - *    returns full handle for a FD opened in user space
    - * XFS_IOC_PATH_TO_HANDLE
    - *    returns full handle for a path
    - */
    -STATIC int
    -xfs_find_handle(
    -	unsigned int		cmd,
    -	void			__user *arg)
    -{
    -#ifdef RMC
    -	int			hsize;
    -#endif
    -	xfs_handle_t		handle;
    -	xfs_fsop_handlereq_t	hreq;
    -#ifdef RMC
    -	struct inode		*inode;
    -	xfs_vnode_t		*vp;
    -#endif
    -
    -	if (copy_from_user(&hreq, arg, sizeof(hreq)))
    -		return -XFS_ERROR(EFAULT);
    -
    -	memset((char *)&handle, 0, sizeof(handle));
    -
    -	switch (cmd) {
    -#if 0
    -	case XFS_IOC_PATH_TO_FSHANDLE:
    -	case XFS_IOC_PATH_TO_HANDLE: {
    -		struct nameidata	nd;
    -		int			error;
    -
    -		NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF,
    -		    UIO_USERSPACE, hreq.path, td);
    -		error = namei(&nd);
    -		if (error)
    -			return error;
    -		NDFREE(&nd, NDF_ONLY_PNBUF);
    -		break;
    -	}
    -
    -	case XFS_IOC_FD_TO_HANDLE: {
    -		struct file	*file;
    -		int		error;
    -
    -		error = getvnode(td->td_proc->p_fd, hreq.fd, &file);
    -		if (error)
    -		    return error;
    -
    -		error = vget(vp, LK_EXCLUSIVE, td);
    -		if (error) {
    -		    fdrop(file);
    -		    return error;
    -		}
    -		fdrop(file);
    -		break;
    -	}
    -#endif
    -
    -	default:
    -		ASSERT(0);
    -		return XFS_ERROR(EINVAL);
    -	}
    -
    -#ifdef RMC
    -	if (inode->i_sb->s_magic != XFS_SB_MAGIC) {
    -		/* we're not in XFS anymore, Toto */
    -		iput(inode);
    -		return XFS_ERROR(EINVAL);
    -	}
    -
    -	switch (inode->i_mode & S_IFMT) {
    -	case S_IFREG:
    -	case S_IFDIR:
    -	case S_IFLNK:
    -		break;
    -	default:
    -		iput(inode);
    -		return XFS_ERROR(EBADF);
    -	}
    -	/* we need the vnode */
    -	vp = vn_from_inode(inode);
    -
    -	/* now we can grab the fsid */
    -	memcpy(&handle.ha_fsid, vp->v_vfsp->vfs_altfsid, sizeof(xfs_fsid_t));
    -	hsize = sizeof(xfs_fsid_t);
    -
    -	if (cmd != XFS_IOC_PATH_TO_FSHANDLE) {
    -		xfs_inode_t	*ip;
    -		int		lock_mode;
    -
    -		/* need to get access to the xfs_inode to read the generation */
    -		ip = xfs_vtoi(vp);
    -		ASSERT(ip);
    -		lock_mode = xfs_ilock_map_shared(ip);
    -
    -		/* fill in fid section of handle from inode */
    -		handle.ha_fid.xfs_fid_len = sizeof(xfs_fid_t) -
    -					    sizeof(handle.ha_fid.xfs_fid_len);
    -		handle.ha_fid.xfs_fid_pad = 0;
    -		handle.ha_fid.xfs_fid_gen = ip->i_d.di_gen;
    -		handle.ha_fid.xfs_fid_ino = ip->i_ino;
    -
    -		xfs_iunlock_map_shared(ip, lock_mode);
    -
    -		hsize = XFS_HSIZE(handle);
    -	}
    -
    -	/* now copy our handle into the user buffer & write out the size */
    -	if (copy_to_user(hreq.ohandle, &handle, hsize) ||
    -	    copy_to_user(hreq.ohandlen, &hsize, sizeof(__s32))) {
    -		iput(inode);
    -		return XFS_ERROR(EFAULT);
    -	}
    -
    -	iput(inode);
    -#endif
    -	return 0;
    -}
    -
    -
    -/*
    - * Convert userspace handle data into vnode (and inode).
    - * We [ab]use the fact that all the fsop_handlereq ioctl calls
    - * have a data structure argument whose first component is always
    - * a xfs_fsop_handlereq_t, so we can cast to and from this type.
    - * This allows us to optimise the copy_from_user calls and gives
    - * a handy, shared routine.
    - *
    - * If no error, caller must always VN_RELE the returned vp.
    - */
    -STATIC int
    -xfs_vget_fsop_handlereq(
    -	xfs_mount_t		*mp,
    -	struct inode		*parinode,	/* parent inode pointer    */
    -	xfs_fsop_handlereq_t	*hreq,
    -	xfs_vnode_t		**vp,
    -	struct inode		**inode)
    -{
    -#if 0
    -	void			__user *hanp;
    -	size_t			hlen;
    -	xfs_fid_t		*xfid;
    -	xfs_handle_t		*handlep;
    -	xfs_handle_t		handle;
    -	xfs_inode_t		*ip;
    -	struct inode		*inodep;
    -	xfs_vnode_t		*vpp;
    -	xfs_ino_t		ino;
    -	__u32			igen;
    -	int			error;
    -
    -	/*
    -	 * Only allow handle opens under a directory.
    -	 */
    -	if (!S_ISDIR(parinode->i_mode))
    -		return XFS_ERROR(ENOTDIR);
    -
    -	hanp = hreq->ihandle;
    -	hlen = hreq->ihandlen;
    -	handlep = &handle;
    -
    -	if (hlen < sizeof(handlep->ha_fsid) || hlen > sizeof(*handlep))
    -		return XFS_ERROR(EINVAL);
    -	if (copy_from_user(handlep, hanp, hlen))
    -		return XFS_ERROR(EFAULT);
    -	if (hlen < sizeof(*handlep))
    -		memset(((char *)handlep) + hlen, 0, sizeof(*handlep) - hlen);
    -	if (hlen > sizeof(handlep->ha_fsid)) {
    -		if (handlep->ha_fid.xfs_fid_len !=
    -				(hlen - sizeof(handlep->ha_fsid)
    -					- sizeof(handlep->ha_fid.xfs_fid_len))
    -		    || handlep->ha_fid.xfs_fid_pad)
    -			return XFS_ERROR(EINVAL);
    -	}
    -
    -	/*
    -	 * Crack the handle, obtain the inode # & generation #
    -	 */
    -	xfid = (struct xfs_fid *)&handlep->ha_fid;
    -	if (xfid->xfs_fid_len == sizeof(*xfid) - sizeof(xfid->xfs_fid_len)) {
    -		ino  = xfid->xfs_fid_ino;
    -		igen = xfid->xfs_fid_gen;
    -	} else {
    -		return XFS_ERROR(EINVAL);
    -	}
    -
    -	/*
    -	 * Get the XFS inode, building a vnode to go with it.
    -	 */
    -	error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, 0);
    -	if (error)
    -		return error;
    -	if (ip == NULL)
    -		return XFS_ERROR(EIO);
    -	if (ip->i_d.di_mode == 0 || ip->i_d.di_gen != igen) {
    -		xfs_iput_new(ip, XFS_ILOCK_SHARED);
    -		return XFS_ERROR(ENOENT);
    -	}
    -
    -	vpp = XFS_ITOV(ip);
    -	inodep = vn_to_inode(vpp);
    -	xfs_iunlock(ip, XFS_ILOCK_SHARED);
    -
    -	*vp = vpp;
    -	*inode = inodep;
    -#endif
    -	return 0;
    -}
    -
    -STATIC int
    -xfs_open_by_handle(
    -	xfs_mount_t		*mp,
    -	void			__user *arg,
    -	struct file		*parfilp,
    -	struct inode		*parinode)
    -{
    -	int			new_fd = 0;
    -#if 0
    -	int			error;
    -	int			permflag;
    -	struct file		*filp;
    -	struct inode		*inode;
    -	struct dentry		*dentry;
    -	xfs_vnode_t		*vp;
    -	xfs_fsop_handlereq_t	hreq;
    -
    -	if (!capable(CAP_SYS_ADMIN))
    -		return -XFS_ERROR(EPERM);
    -	if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t)))
    -		return XFS_ERROR(EFAULT);
    -
    -	error = xfs_vget_fsop_handlereq(mp, parinode, &hreq, &vp, &inode);
    -	if (error)
    -		return error;
    -
    -	/* Restrict xfs_open_by_handle to directories & regular files. */
    -	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) {
    -		iput(inode);
    -		return XFS_ERROR(EINVAL);
    -	}
    -
    -#if BITS_PER_LONG != 32
    -	hreq.oflags |= O_LARGEFILE;
    -#endif
    -	/* Put open permission in namei format. */
    -	permflag = hreq.oflags;
    -	if ((permflag+1) & O_ACCMODE)
    -		permflag++;
    -	if (permflag & O_TRUNC)
    -		permflag |= 2;
    -
    -	if ((!(permflag & O_APPEND) || (permflag & O_TRUNC)) &&
    -	    (permflag & FMODE_WRITE) && IS_APPEND(inode)) {
    -		iput(inode);
    -		return XFS_ERROR(EPERM);
    -	}
    -
    -	if ((permflag & FMODE_WRITE) && IS_IMMUTABLE(inode)) {
    -		iput(inode);
    -		return XFS_ERROR(EACCES);
    -	}
    -
    -	/* Can't write directories. */
    -	if ( S_ISDIR(inode->i_mode) && (permflag & FMODE_WRITE)) {
    -		iput(inode);
    -		return XFS_ERROR(EISDIR);
    -	}
    -
    -	if ((new_fd = get_unused_fd()) < 0) {
    -		iput(inode);
    -		return new_fd;
    -	}
    -
    -	dentry = d_alloc_anon(inode);
    -	if (dentry == NULL) {
    -		iput(inode);
    -		put_unused_fd(new_fd);
    -		return XFS_ERROR(ENOMEM);
    -	}
    -
    -	/* Ensure umount returns EBUSY on umounts while this file is open. */
    -	mntget(parfilp->f_vfsmnt);
    -
    -	/* Create file pointer. */
    -	filp = dentry_open(dentry, parfilp->f_vfsmnt, hreq.oflags);
    -	if (IS_ERR(filp)) {
    -		put_unused_fd(new_fd);
    -		return -XFS_ERROR(-PTR_ERR(filp));
    -	}
    -	if (inode->i_mode & S_IFREG)
    -		filp->f_op = &xfs_invis_file_operations;
    -
    -	fd_install(new_fd, filp);
    -#endif
    -	return new_fd;
    -}
    -
    -STATIC int
    -xfs_readlink_by_handle(
    -	xfs_mount_t		*mp,
    -	void			__user *arg,
    -	struct file		*parfilp,
    -	struct inode		*parinode)
    -{
    -	int			error;
    -	struct iovec		aiov;
    -	struct uio		auio;
    -	struct inode		*inode;
    -	xfs_fsop_handlereq_t	hreq;
    -	xfs_vnode_t		*vp = NULL;
    -	__u32			olen;
    -
    -	if (!capable(CAP_SYS_ADMIN))
    -		return -XFS_ERROR(EPERM);
    -	if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t)))
    -		return -XFS_ERROR(EFAULT);
    -
    -	error = xfs_vget_fsop_handlereq(mp, parinode, &hreq, &vp, &inode);
    -	if (error)
    -		return -error;
    -
    -#if 0
    -	/* Restrict this handle operation to symlinks only. */
    -	if (vp->v_type != VLNK) {
    -		VN_RELE(vp);
    -		return -XFS_ERROR(EINVAL);
    -	}
    -#endif
    -
    -	if (copy_from_user(&olen, hreq.ohandlen, sizeof(__u32))) {
    -		VN_RELE(vp);
    -		return -XFS_ERROR(EFAULT);
    -	}
    -	aiov.iov_len	= olen;
    -	aiov.iov_base	= hreq.ohandle;
    -
    -	auio.uio_iov	= &aiov;
    -	auio.uio_iovcnt	= 1;
    -	auio.uio_offset	= 0;
    -	auio.uio_segflg	= UIO_USERSPACE;
    -	auio.uio_resid	= olen;
    -
    -	XVOP_READLINK(vp, &auio, IO_INVIS, NULL, error);
    -
    -	VN_RELE(vp);
    -	return (olen - auio.uio_resid);
    -}
    -
    -STATIC int
    -xfs_fssetdm_by_handle(
    -	xfs_mount_t		*mp,
    -	void			__user *arg,
    -	struct file		*parfilp,
    -	struct inode		*parinode)
    -{
    -	int			error = 0;
    -#if 0
    -	struct fsdmidata	fsd;
    -	xfs_fsop_setdm_handlereq_t dmhreq;
    -	struct inode		*inode;
    -	bhv_desc_t		*bdp;
    -	xfs_vnode_t		*vp;
    -
    -	if (!capable(CAP_MKNOD))
    -		return XFS_ERROR(EPERM);
    -	if (copy_from_user(&dmhreq, arg, sizeof(xfs_fsop_setdm_handlereq_t)))
    -		return XFS_ERROR(EFAULT);
    -
    -	error = xfs_vget_fsop_handlereq(mp, parinode, &dmhreq.hreq, &vp, &inode);
    -	if (error)
    -		return error;
    -
    -	if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
    -		VN_RELE(vp);
    -		return XFS_ERROR(EPERM);
    -	}
    -
    -	if (copy_from_user(&fsd, dmhreq.data, sizeof(fsd))) {
    -		VN_RELE(vp);
    -		return XFS_ERROR(EFAULT);
    -	}
    -
    -	bdp = bhv_base_unlocked(VN_BHV_HEAD(vp));
    -	error = xfs_set_dmattrs(bdp, fsd.fsd_dmevmask, fsd.fsd_dmstate, NULL);
    -
    -	VN_RELE(vp);
    -	if (error)
    -		return error;
    -#endif
    -	return error;
    -}
    -
    -STATIC int
    -xfs_attrlist_by_handle(
    -	xfs_mount_t		*mp,
    -	void			__user *arg,
    -	struct file		*parfilp,
    -	struct inode		*parinode)
    -{
    -	int			error = 0;
    -#if 0
    -	attrlist_cursor_kern_t	*cursor;
    -	xfs_fsop_attrlist_handlereq_t al_hreq;
    -	struct inode		*inode;
    -	xfs_vnode_t		*vp;
    -	char			*kbuf;
    -
    -	if (!capable(CAP_SYS_ADMIN))
    -		return -XFS_ERROR(EPERM);
    -	if (copy_from_user(&al_hreq, arg, sizeof(xfs_fsop_attrlist_handlereq_t)))
    -		return -XFS_ERROR(EFAULT);
    -	if (al_hreq.buflen > XATTR_LIST_MAX)
    -		return -XFS_ERROR(EINVAL);
    -
    -	error = xfs_vget_fsop_handlereq(mp, parinode, &al_hreq.hreq,
    -			&vp, &inode);
    -	if (error)
    -		goto out;
    -
    -	kbuf = kmalloc(al_hreq.buflen, GFP_KERNEL);
    -	if (!kbuf)
    -		goto out_vn_rele;
    -
    -	cursor = (attrlist_cursor_kern_t *)&al_hreq.pos;
    -	XVOP_ATTR_LIST(vp, kbuf, al_hreq.buflen, al_hreq.flags,
    -			cursor, NULL, error);
    -	if (error)
    -		goto out_kfree;
    -
    -	if (copy_to_user(al_hreq.buffer, kbuf, al_hreq.buflen))
    -		error = -EFAULT;
    -
    - out_kfree:
    -	kfree(kbuf);
    - out_vn_rele:
    -	VN_RELE(vp);
    - out:
    -#endif
    -	return error;
    -}
    -
    -#if 0
    -STATIC int
    -xfs_attrmulti_attr_get(
    -	xfs_vnode_t		*vp,
    -	char			*name,
    -	char			__user *ubuf,
    -	__uint32_t		*len,
    -	__uint32_t		flags)
    -{
    -	int			error = EFAULT;
    -	char			*kbuf;
    -
    -	if (*len > XATTR_SIZE_MAX)
    -		return EINVAL;
    -	kbuf = kmalloc(*len, GFP_KERNEL);
    -	if (!kbuf)
    -		return ENOMEM;
    -
    -	XVOP_ATTR_GET(vp, name, kbuf, len, flags, NULL, error);
    -	if (error)
    -		goto out_kfree;
    -
    -	if (copy_to_user(ubuf, kbuf, *len))
    -		error = EFAULT;
    -
    - out_kfree:
    -	kfree(kbuf);
    -	return error;
    -}
    -#endif
    -
    -#if 0
    -STATIC int
    -xfs_attrmulti_attr_set(
    -	xfs_vnode_t		*vp,
    -	char			*name,
    -	const char		__user *ubuf,
    -	__uint32_t		len,
    -	__uint32_t		flags)
    -{
    -	int			error = EFAULT;
    -	char			*kbuf;
    -
    -	if (IS_RDONLY(&vp->v_inode))
    -		return -EROFS;
    -	if (IS_IMMUTABLE(&vp->v_inode) || IS_APPEND(&vp->v_inode))
    -		return EPERM;
    -	if (len > XATTR_SIZE_MAX)
    -		return EINVAL;
    -
    -	kbuf = kmalloc(len, GFP_KERNEL);
    -	if (!kbuf)
    -		return ENOMEM;
    -
    -	if (copy_from_user(kbuf, ubuf, len))
    -		goto out_kfree;
    -
    -	XVOP_ATTR_SET(vp, name, kbuf, len, flags, NULL, error);
    -
    - out_kfree:
    -	kfree(kbuf);
    -	return error;
    -}
    -#endif
    -
    -#if 0
    -STATIC int
    -xfs_attrmulti_attr_remove(
    -	xfs_vnode_t		*vp,
    -	char			*name,
    -	__uint32_t		flags)
    -{
    -	int			error;
    -
    -	if (IS_RDONLY(&vp->v_inode))
    -		return -EROFS;
    -	if (IS_IMMUTABLE(&vp->v_inode) || IS_APPEND(&vp->v_inode))
    -		return EPERM;
    -
    -	XVOP_ATTR_REMOVE(vp, name, flags, NULL, error);
    -	return error;
    -}
    -#endif
    -
    -STATIC int
    -xfs_attrmulti_by_handle(
    -	xfs_mount_t		*mp,
    -	void			__user *arg,
    -	struct file		*parfilp,
    -	struct inode		*parinode)
    -{
    -	int			error = 0;
    -#if 0
    -	xfs_attr_multiop_t	*ops;
    -	xfs_fsop_attrmulti_handlereq_t am_hreq;
    -	struct inode		*inode;
    -	xfs_vnode_t		*vp;
    -	unsigned int		i, size;
    -	char			*attr_name;
    -
    -	if (!capable(CAP_SYS_ADMIN))
    -		return -XFS_ERROR(EPERM);
    -	if (copy_from_user(&am_hreq, arg, sizeof(xfs_fsop_attrmulti_handlereq_t)))
    -		return -XFS_ERROR(EFAULT);
    -
    -	error = xfs_vget_fsop_handlereq(mp, parinode, &am_hreq.hreq, &vp, &inode);
    -	if (error)
    -		goto out;
    -
    -	error = E2BIG;
    -	size = am_hreq.opcount * sizeof(attr_multiop_t);
    -	if (!size || size > 16 * PAGE_SIZE)
    -		goto out_vn_rele;
    -
    -	error = ENOMEM;
    -	ops = kmalloc(size, GFP_KERNEL);
    -	if (!ops)
    -		goto out_vn_rele;
    -
    -	error = EFAULT;
    -	if (copy_from_user(ops, am_hreq.ops, size))
    -		goto out_kfree_ops;
    -
    -	attr_name = kmalloc(MAXNAMELEN, GFP_KERNEL);
    -	if (!attr_name)
    -		goto out_kfree_ops;
    -
    -
    -	error = 0;
    -	for (i = 0; i < am_hreq.opcount; i++) {
    -		ops[i].am_error = strncpy_from_user(attr_name,
    -				ops[i].am_attrname, MAXNAMELEN);
    -		if (ops[i].am_error == 0 || ops[i].am_error == MAXNAMELEN)
    -			error = -ERANGE;
    -		if (ops[i].am_error < 0)
    -			break;
    -
    -		switch (ops[i].am_opcode) {
    -		case ATTR_OP_GET:
    -			ops[i].am_error = xfs_attrmulti_attr_get(vp,
    -					attr_name, ops[i].am_attrvalue,
    -					&ops[i].am_length, ops[i].am_flags);
    -			break;
    -		case ATTR_OP_SET:
    -			ops[i].am_error = xfs_attrmulti_attr_set(vp,
    -					attr_name, ops[i].am_attrvalue,
    -					ops[i].am_length, ops[i].am_flags);
    -			break;
    -		case ATTR_OP_REMOVE:
    -			ops[i].am_error = xfs_attrmulti_attr_remove(vp,
    -					attr_name, ops[i].am_flags);
    -			break;
    -		default:
    -			ops[i].am_error = EINVAL;
    -		}
    -	}
    -
    -	if (copy_to_user(am_hreq.ops, ops, size))
    -		error = XFS_ERROR(EFAULT);
    -
    -	kfree(attr_name);
    - out_kfree_ops:
    -	kfree(ops);
    - out_vn_rele:
    -	VN_RELE(vp);
    - out:
    -#endif
    -	return error;
    -}
    -
    -/* prototypes for a few of the stack-hungry cases that have
    - * their own functions.  Functions are defined after their use
    - * so gcc doesn't get fancy and inline them with -03 */
    -
    -STATIC int
    -xfs_ioc_space(
    -	bhv_desc_t		*bdp,
    -	xfs_vnode_t		*vp,
    -	struct file		*filp,
    -	int			flags,
    -	u_long			cmd,
    -	void			__user *arg);
    -
    -STATIC int
    -xfs_ioc_bulkstat(
    -	xfs_mount_t		*mp,
    -	unsigned int		cmd,
    -	void			__user *arg);
    -
    -STATIC int
    -xfs_ioc_fsgeometry_v1(
    -	xfs_mount_t		*mp,
    -	void			__user *arg);
    -
    -STATIC int
    -xfs_ioc_fsgeometry(
    -	xfs_mount_t		*mp,
    -	void			__user *arg);
    -
    -STATIC int
    -xfs_ioc_xattr(
    -	xfs_vnode_t		*vp,
    -	xfs_inode_t		*ip,
    -	struct file		*filp,
    -	unsigned int		cmd,
    -	void			__user *arg);
    -
    -STATIC int
    -xfs_ioc_getbmap(
    -	bhv_desc_t		*bdp,
    -	struct file		*filp,
    -	int			flags,
    -	unsigned int		cmd,
    -	void			__user *arg);
    -
    -STATIC int
    -xfs_ioc_getbmapx(
    -	bhv_desc_t		*bdp,
    -	void			__user *arg);
    -
    -int
    -xfs_ioctl(
    -	bhv_desc_t		*bdp,
    -	struct inode		*inode,
    -	struct file		*filp,
    -	int			ioflags,
    -	u_long			cmd,
    -	void			*arg)
    -{
    -	int			error;
    -	xfs_vnode_t		*vp;
    -	xfs_inode_t		*ip;
    -	xfs_mount_t		*mp;
    -
    -//	vp = vn_from_inode(inode);
    -	vp = BHV_TO_VNODE(bdp);
    -
    -	printf("xfs_ioctl: bdp %p flags 0x%x cmd 0x%lx basecmd 0x%lx arg %p\n",
    -	       bdp, ioflags, cmd,
    -	       IOCBASECMD(cmd),
    -	       arg);
    -
    -
    -	vn_trace_entry(vp, "xfs_ioctl", (inst_t *)__return_address);
    -
    -	ip = XFS_BHVTOI(bdp);
    -	mp = ip->i_mount;
    -
    -
    -#if 0
    -	if ((cmd << 24 >> 24) ==  (XFS_IOC_GETBMAPX << 24 >> 24)) {
    -		cmd = XFS_IOC_GETBMAPX;
    -	}
    -#endif
    -
    -
    -
    -	switch (cmd) {
    -
    -	case XFS_IOC_ALLOCSP:
    -	case XFS_IOC_FREESP:
    -	case XFS_IOC_RESVSP:
    -	case XFS_IOC_UNRESVSP:
    -	case XFS_IOC_ALLOCSP64:
    -	case XFS_IOC_FREESP64:
    -	case XFS_IOC_RESVSP64:
    -	case XFS_IOC_UNRESVSP64:
    -		/*
    -		 * Only allow the sys admin to reserve space unless
    -		 * unwritten extents are enabled.
    -		 */
    -		if (!XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb) &&
    -		    !capable(CAP_SYS_ADMIN))
    -			return -EPERM;
    -
    -		return xfs_ioc_space(bdp, vp, filp, ioflags, cmd, arg);
    -
    -	case XFS_IOC_DIOINFO: {
    -		struct dioattr	da;
    -		xfs_buftarg_t	*target =
    -			(ip->i_d.di_flags & XFS_DIFLAG_REALTIME) ?
    -			mp->m_rtdev_targp : mp->m_ddev_targp;
    -
    -		da.d_mem = da.d_miniosz = 1 << target->bt_sshift;
    -		da.d_maxiosz = INT_MAX & ~(da.d_miniosz - 1);
    -
    -		if (copy_to_user(arg, &da, sizeof(da)))
    -			return XFS_ERROR(EFAULT);
    -		return 0;
    -	}
    -
    -	case XFS_IOC_FSBULKSTAT_SINGLE:
    -	case XFS_IOC_FSBULKSTAT:
    -	case XFS_IOC_FSINUMBERS:
    -		return xfs_ioc_bulkstat(mp, cmd, arg);
    -
    -	case XFS_IOC_FSGEOMETRY_V1:
    -		return xfs_ioc_fsgeometry_v1(mp, arg);
    -
    -	case XFS_IOC_FSGEOMETRY:
    -		return xfs_ioc_fsgeometry(mp, arg);
    -
    -	case XFS_IOC_GETVERSION:
    -	case XFS_IOC_GETXFLAGS:
    -	case XFS_IOC_SETXFLAGS:
    -	case XFS_IOC_FSGETXATTR:
    -	case XFS_IOC_FSSETXATTR:
    -	case XFS_IOC_FSGETXATTRA:
    -		return xfs_ioc_xattr(vp, ip, filp, cmd, arg);
    -
    -	case XFS_IOC_FSSETDM: {
    -		struct fsdmidata	dmi;
    -
    -		if (copy_from_user(&dmi, arg, sizeof(dmi)))
    -			return XFS_ERROR(EFAULT);
    -
    -		error = xfs_set_dmattrs(bdp, dmi.fsd_dmevmask, dmi.fsd_dmstate,
    -							NULL);
    -		return error;
    -	}
    -
    -	case XFS_IOC_GETBMAP:
    -	case XFS_IOC_GETBMAPA:
    -		return xfs_ioc_getbmap(bdp, filp, ioflags, cmd, arg);
    -
    -	case XFS_IOC_GETBMAPX:
    -		return xfs_ioc_getbmapx(bdp, arg);
    -
    -	case XFS_IOC_FD_TO_HANDLE:
    -	case XFS_IOC_PATH_TO_HANDLE:
    -	case XFS_IOC_PATH_TO_FSHANDLE:
    -		return xfs_find_handle(cmd, arg);
    -
    -	case XFS_IOC_OPEN_BY_HANDLE:
    -		return xfs_open_by_handle(mp, arg, filp, inode);
    -
    -	case XFS_IOC_FSSETDM_BY_HANDLE:
    -		return xfs_fssetdm_by_handle(mp, arg, filp, inode);
    -
    -	case XFS_IOC_READLINK_BY_HANDLE:
    -		return xfs_readlink_by_handle(mp, arg, filp, inode);
    -
    -	case XFS_IOC_ATTRLIST_BY_HANDLE:
    -		return xfs_attrlist_by_handle(mp, arg, filp, inode);
    -
    -	case XFS_IOC_ATTRMULTI_BY_HANDLE:
    -		return xfs_attrmulti_by_handle(mp, arg, filp, inode);
    -
    -	case XFS_IOC_SWAPEXT: {
    -		error = xfs_swapext((struct xfs_swapext __user *)arg);
    -		return error;
    -	}
    -
    -	case XFS_IOC_FSCOUNTS: {
    -		xfs_fsop_counts_t out;
    -
    -		error = xfs_fs_counts(mp, &out);
    -		if (error)
    -			return error;
    -
    -		if (copy_to_user(arg, &out, sizeof(out)))
    -			return XFS_ERROR(EFAULT);
    -		return 0;
    -	}
    -
    -	case XFS_IOC_SET_RESBLKS: {
    -		xfs_fsop_resblks_t inout;
    -		__uint64_t	   in;
    -
    -		if (!capable(CAP_SYS_ADMIN))
    -			return EPERM;
    -
    -		if (copy_from_user(&inout, arg, sizeof(inout)))
    -			return XFS_ERROR(EFAULT);
    -
    -		/* input parameter is passed in resblks field of structure */
    -		in = inout.resblks;
    -		error = xfs_reserve_blocks(mp, &in, &inout);
    -		if (error)
    -			return error;
    -
    -		if (copy_to_user(arg, &inout, sizeof(inout)))
    -			return XFS_ERROR(EFAULT);
    -		return 0;
    -	}
    -
    -	case XFS_IOC_GET_RESBLKS: {
    -		xfs_fsop_resblks_t out;
    -
    -		if (!capable(CAP_SYS_ADMIN))
    -			return EPERM;
    -
    -		error = xfs_reserve_blocks(mp, NULL, &out);
    -		if (error)
    -			return error;
    -
    -		if (copy_to_user(arg, &out, sizeof(out)))
    -			return XFS_ERROR(EFAULT);
    -
    -		return 0;
    -	}
    -
    -	case XFS_IOC_FSGROWFSDATA: {
    -		xfs_growfs_data_t in;
    -
    -		if (!capable(CAP_SYS_ADMIN))
    -			return EPERM;
    -
    -		if (copy_from_user(&in, arg, sizeof(in)))
    -			return XFS_ERROR(EFAULT);
    -
    -		error = xfs_growfs_data(mp, &in);
    -		return error;
    -	}
    -
    -	case XFS_IOC_FSGROWFSLOG: {
    -		xfs_growfs_log_t in;
    -
    -		if (!capable(CAP_SYS_ADMIN))
    -			return EPERM;
    -
    -		if (copy_from_user(&in, arg, sizeof(in)))
    -			return XFS_ERROR(EFAULT);
    -
    -		error = xfs_growfs_log(mp, &in);
    -		return error;
    -	}
    -
    -	case XFS_IOC_FSGROWFSRT: {
    -		xfs_growfs_rt_t in;
    -
    -		if (!capable(CAP_SYS_ADMIN))
    -			return EPERM;
    -
    -		if (copy_from_user(&in, arg, sizeof(in)))
    -			return XFS_ERROR(EFAULT);
    -
    -		error = xfs_growfs_rt(mp, &in);
    -		return error;
    -	}
    -#if 0
    -	case XFS_IOC_FREEZE:
    -		if (!capable(CAP_SYS_ADMIN))
    -			return -EPERM;
    -		xfs_fs_freeze(mp);
    -		return 0;
    -
    -	case XFS_IOC_THAW:
    -		if (!capable(CAP_SYS_ADMIN))
    -			return -EPERM;
    -		xfs_fs_thaw(mp);
    -		return 0;
    -#endif
    -
    -	case XFS_IOC_GOINGDOWN: {
    -		__uint32_t in;
    -
    -		if (!capable(CAP_SYS_ADMIN))
    -			return EPERM;
    -
    -		if (copy_from_user(&in, arg, sizeof(__uint32_t)))
    -			return XFS_ERROR(EFAULT);
    -
    -		error = xfs_fs_goingdown(mp, in);
    -		return error;
    -	}
    -
    -	case XFS_IOC_ERROR_INJECTION: {
    -		xfs_error_injection_t in;
    -
    -		if (!capable(CAP_SYS_ADMIN))
    -			return EPERM;
    -
    -		if (copy_from_user(&in, arg, sizeof(in)))
    -			return XFS_ERROR(EFAULT);
    -
    -		error = xfs_errortag_add(in.errtag, mp);
    -		return error;
    -	}
    -
    -	case XFS_IOC_ERROR_CLEARALL:
    -		if (!capable(CAP_SYS_ADMIN))
    -			return EPERM;
    -
    -		error = xfs_errortag_clearall(mp);
    -		return error;
    -
    -	default:
    -		return ENOTTY;
    -	}
    -}
    -
    -STATIC int
    -xfs_ioc_space(
    -	bhv_desc_t		*bdp,
    -	xfs_vnode_t		*vp,
    -	struct file		*filp,
    -	int			ioflags,
    -	u_long			cmd,
    -	void			__user *arg)
    -{
    -	xfs_flock64_t		bf;
    -	int			attr_flags = 0;
    -	int			error;
    -
    -#if 0
    -	if (vp->v_inode.i_flags & (S_IMMUTABLE|S_APPEND))
    -		return -XFS_ERROR(EPERM);
    -
    -	if (!(filp->f_mode & FMODE_WRITE))
    -		return -XFS_ERROR(EBADF);
    -#endif
    -
    -	if (!VN_ISREG(vp))
    -		return -XFS_ERROR(EINVAL);
    -
    -	if (copy_from_user(&bf, arg, sizeof(bf)))
    -		return -XFS_ERROR(EFAULT);
    -
    -#if 0
    -	if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
    -		attr_flags |= ATTR_NONBLOCK;
    -#endif
    -	if (ioflags & IO_INVIS)
    -		attr_flags |= ATTR_DMI;
    -
    -	error = xfs_change_file_space(bdp, cmd,
    -				      &bf, filp->f_offset,
    -				      NULL, attr_flags);
    -	return -error;
    -}
    -
    -STATIC int
    -xfs_ioc_bulkstat(
    -	xfs_mount_t		*mp,
    -	unsigned int		cmd,
    -	void			__user *arg)
    -{
    -	xfs_fsop_bulkreq_t	bulkreq;
    -	int			count;	/* # of records returned */
    -	xfs_ino_t		inlast;	/* last inode number */
    -	int			done;
    -	int			error;
    -
    -	/* done = 1 if there are more stats to get and if bulkstat */
    -	/* should be called again (unused here, but used in dmapi) */
    -
    -#if 0
    -	if (!capable(CAP_SYS_ADMIN))
    -		return -EPERM;
    -#endif
    -
    -	if (XFS_FORCED_SHUTDOWN(mp))
    -		return -XFS_ERROR(EIO);
    -
    -	if (copy_from_user(&bulkreq, arg, sizeof(xfs_fsop_bulkreq_t)))
    -		return -XFS_ERROR(EFAULT);
    -
    -	if (copy_from_user(&inlast, bulkreq.lastip, sizeof(__s64)))
    -		return -XFS_ERROR(EFAULT);
    -
    -	if ((count = bulkreq.icount) <= 0)
    -		return -XFS_ERROR(EINVAL);
    -
    -	if (cmd == XFS_IOC_FSINUMBERS)
    -		error = xfs_inumbers(mp, &inlast, &count,
    -						bulkreq.ubuffer);
    -	else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE)
    -		error = xfs_bulkstat_single(mp, &inlast,
    -						bulkreq.ubuffer, &done);
    -	else {	/* XFS_IOC_FSBULKSTAT */
    -		if (count == 1 && inlast != 0) {
    -			inlast++;
    -			error = xfs_bulkstat_single(mp, &inlast,
    -					bulkreq.ubuffer, &done);
    -		} else {
    -			error = xfs_bulkstat(mp, &inlast, &count,
    -				(bulkstat_one_pf)xfs_bulkstat_one, NULL,
    -				sizeof(xfs_bstat_t), bulkreq.ubuffer,
    -				BULKSTAT_FG_QUICK, &done);
    -		}
    -	}
    -
    -	if (error)
    -		return -error;
    -
    -	if (bulkreq.ocount != NULL) {
    -		if (copy_to_user(bulkreq.lastip, &inlast,
    -						sizeof(xfs_ino_t)))
    -			return -XFS_ERROR(EFAULT);
    -
    -		if (copy_to_user(bulkreq.ocount, &count, sizeof(count)))
    -			return -XFS_ERROR(EFAULT);
    -	}
    -
    -	return 0;
    -}
    -
    -STATIC int
    -xfs_ioc_fsgeometry_v1(
    -	xfs_mount_t		*mp,
    -	void			__user *arg)
    -{
    -	xfs_fsop_geom_v1_t	fsgeo;
    -	int			error;
    -
    -	error = xfs_fs_geometry(mp, (xfs_fsop_geom_t *)&fsgeo, 3);
    -	if (error)
    -		return -error;
    -
    -	if (copy_to_user(arg, &fsgeo, sizeof(fsgeo)))
    -		return -XFS_ERROR(EFAULT);
    -	return 0;
    -}
    -
    -STATIC int
    -xfs_ioc_fsgeometry(
    -	xfs_mount_t		*mp,
    -	void			__user *arg)
    -{
    -	xfs_fsop_geom_t		fsgeo;
    -	int			error;
    -
    -	error = xfs_fs_geometry(mp, &fsgeo, 4);
    -	if (error)
    -		goto error;
    -
    -	printf ("xfs_ioc_fsgeometry: error? %d arg %p\n",error,arg);
    -
    -#if 0
    -	if (copy_to_user(arg, &fsgeo, sizeof(fsgeo)))
    -		return XFS_ERROR(EFAULT);
    -#endif
    -	memcpy(arg, &fsgeo, sizeof(fsgeo));
    -
    -	printf ("xfs_ioc_fsgeometry: error? %d arg %p\n",error,arg);
    -error:
    -	return error;
    -}
    -
    -/*
    - * Linux extended inode flags interface.
    - */
    -#define LINUX_XFLAG_SYNC	0x00000008 /* Synchronous updates */
    -#define LINUX_XFLAG_IMMUTABLE	0x00000010 /* Immutable file */
    -#define LINUX_XFLAG_APPEND	0x00000020 /* writes to file may only append */
    -#define LINUX_XFLAG_NODUMP	0x00000040 /* do not dump file */
    -#define LINUX_XFLAG_NOATIME	0x00000080 /* do not update atime */
    -
    -STATIC unsigned int
    -xfs_merge_ioc_xflags(
    -	unsigned int	flags,
    -	unsigned int	start)
    -{
    -	unsigned int	xflags = start;
    -
    -	if (flags & LINUX_XFLAG_IMMUTABLE)
    -		xflags |= XFS_XFLAG_IMMUTABLE;
    -	else
    -		xflags &= ~XFS_XFLAG_IMMUTABLE;
    -	if (flags & LINUX_XFLAG_APPEND)
    -		xflags |= XFS_XFLAG_APPEND;
    -	else
    -		xflags &= ~XFS_XFLAG_APPEND;
    -	if (flags & LINUX_XFLAG_SYNC)
    -		xflags |= XFS_XFLAG_SYNC;
    -	else
    -		xflags &= ~XFS_XFLAG_SYNC;
    -	if (flags & LINUX_XFLAG_NOATIME)
    -		xflags |= XFS_XFLAG_NOATIME;
    -	else
    -		xflags &= ~XFS_XFLAG_NOATIME;
    -	if (flags & LINUX_XFLAG_NODUMP)
    -		xflags |= XFS_XFLAG_NODUMP;
    -	else
    -		xflags &= ~XFS_XFLAG_NODUMP;
    -
    -	return xflags;
    -}
    -
    -STATIC unsigned int
    -xfs_di2lxflags(
    -	__uint16_t	di_flags)
    -{
    -	unsigned int	flags = 0;
    -
    -	if (di_flags & XFS_DIFLAG_IMMUTABLE)
    -		flags |= LINUX_XFLAG_IMMUTABLE;
    -	if (di_flags & XFS_DIFLAG_APPEND)
    -		flags |= LINUX_XFLAG_APPEND;
    -	if (di_flags & XFS_DIFLAG_SYNC)
    -		flags |= LINUX_XFLAG_SYNC;
    -	if (di_flags & XFS_DIFLAG_NOATIME)
    -		flags |= LINUX_XFLAG_NOATIME;
    -	if (di_flags & XFS_DIFLAG_NODUMP)
    -		flags |= LINUX_XFLAG_NODUMP;
    -	return flags;
    -}
    -
    -STATIC int
    -xfs_ioc_xattr(
    -	xfs_vnode_t		*vp,
    -	xfs_inode_t		*ip,
    -	struct file		*filp,
    -	unsigned int		cmd,
    -	void			__user *arg)
    -{
    -	struct fsxattr		fa;
    -	struct xfs_vattr	*vattr;
    -	int			error;
    -	int			attr_flags;
    -	unsigned int		flags;
    -
    -	error = 0;
    -	attr_flags = 0;
    -
    -	vattr = kmem_alloc(sizeof(struct xfs_vattr), KM_SLEEP);
    -	if (unlikely(!vattr))
    -		return ENOMEM;
    -
    -	switch (cmd) {
    -	case XFS_IOC_FSGETXATTR: {
    -		vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \
    -				 XFS_AT_NEXTENTS | XFS_AT_PROJID;
    -		XVOP_GETATTR(vp, vattr, 0, NULL, error);
    -		if (unlikely(error)) {
    -			break;
    -		}
    -
    -		fa.fsx_xflags	= vattr->va_xflags;
    -		fa.fsx_extsize	= vattr->va_extsize;
    -		fa.fsx_nextents = vattr->va_nextents;
    -		fa.fsx_projid	= vattr->va_projid;
    -
    -		if (copy_to_user(arg, &fa, sizeof(fa))) {
    -			error = EFAULT;
    -			break;
    -		}
    -		break;
    -	}
    -
    -	case XFS_IOC_FSSETXATTR: {
    -		if (copy_from_user(&fa, arg, sizeof(fa))) {
    -			error = EFAULT;
    -			break;
    -		}
    -
    -		attr_flags = 0;
    -#if 0
    -		if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
    -			attr_flags |= ATTR_NONBLOCK;
    -#endif
    -
    -		vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | XFS_AT_PROJID;
    -		vattr->va_xflags  = fa.fsx_xflags;
    -		vattr->va_extsize = fa.fsx_extsize;
    -		vattr->va_projid  = fa.fsx_projid;
    -
    -		XVOP_SETATTR(vp, vattr, attr_flags, NULL, error);
    -#if 0
    -		if (likely(!error))
    -			__vn_revalidate(vp, vattr);	/* update flags */
    -#endif
    -		break;
    -	}
    -
    -	case XFS_IOC_FSGETXATTRA: {
    -		vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \
    -				 XFS_AT_ANEXTENTS | XFS_AT_PROJID;
    -		XVOP_GETATTR(vp, vattr, 0, NULL, error);
    -		if (unlikely(error)) {
    -			break;
    -		}
    -
    -		fa.fsx_xflags	= vattr->va_xflags;
    -		fa.fsx_extsize	= vattr->va_extsize;
    -		fa.fsx_nextents = vattr->va_anextents;
    -		fa.fsx_projid	= vattr->va_projid;
    -
    -		if (copy_to_user(arg, &fa, sizeof(fa))) {
    -			error = EFAULT;
    -			break;
    -		}
    -		break;
    -	}
    -
    -	case XFS_IOC_GETXFLAGS: {
    -		flags = xfs_di2lxflags(ip->i_d.di_flags);
    -		if (copy_to_user(arg, &flags, sizeof(flags)))
    -			error = EFAULT;
    -		break;
    -	}
    -
    -	case XFS_IOC_SETXFLAGS: {
    -		if (copy_from_user(&flags, arg, sizeof(flags))) {
    -			error = EFAULT;
    -			break;
    -		}
    -
    -		if (flags & ~(LINUX_XFLAG_IMMUTABLE | LINUX_XFLAG_APPEND | \
    -			      LINUX_XFLAG_NOATIME | LINUX_XFLAG_NODUMP | \
    -			      LINUX_XFLAG_SYNC)) {
    -			error = EOPNOTSUPP;
    -			break;
    -		}
    -
    -#if 0
    -		attr_flags = 0;
    -		if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
    -			attr_flags |= ATTR_NONBLOCK;
    -#endif
    -
    -		vattr->va_mask = XFS_AT_XFLAGS;
    -		vattr->va_xflags = xfs_merge_ioc_xflags(flags,
    -							xfs_ip2xflags(ip));
    -
    -		XVOP_SETATTR(vp, vattr, attr_flags, NULL, error);
    -#if 0
    -		if (likely(!error))
    -			__vn_revalidate(vp, vattr);	/* update flags */
    -#endif
    -		break;
    -	}
    -
    -#if 0
    -	case XFS_IOC_GETVERSION: {
    -		flags = vn_to_inode(vp)->i_generation;
    -		if (copy_to_user(arg, &flags, sizeof(flags)))
    -			error = EFAULT;
    -		break;
    -	}
    -#endif
    -
    -	default:
    -		error = ENOTTY;
    -		break;
    -	}
    -
    -	kmem_free(vattr,sizeof(struct xfs_vattr));
    -	return error;
    -}
    -
    -STATIC int
    -xfs_ioc_getbmap(
    -	bhv_desc_t		*bdp,
    -	struct file		*filp,
    -	int			ioflags,
    -	unsigned int		cmd,
    -	void			__user *arg)
    -{
    -	struct getbmap		bm;
    -	int			iflags;
    -	int			error;
    -
    -	if (copy_from_user(&bm, arg, sizeof(bm)))
    -		return -XFS_ERROR(EFAULT);
    -
    -	if (bm.bmv_count < 2)
    -		return -XFS_ERROR(EINVAL);
    -
    -	iflags = (cmd == XFS_IOC_GETBMAPA ? BMV_IF_ATTRFORK : 0);
    -	if (ioflags & IO_INVIS)
    -		iflags |= BMV_IF_NO_DMAPI_READ;
    -
    -	error = xfs_getbmap(bdp, &bm, (struct getbmap __user *)arg+1, iflags);
    -	if (error)
    -		return -error;
    -
    -	if (copy_to_user(arg, &bm, sizeof(bm)))
    -		return -XFS_ERROR(EFAULT);
    -	return 0;
    -}
    -
    -STATIC int
    -xfs_ioc_getbmapx(
    -	bhv_desc_t		*bdp,
    -	void			__user *arg)
    -{
    -	struct getbmapx		bmx;
    -	struct getbmap		bm;
    -	int			iflags;
    -	int			error;
    -
    -	printf("%s:%d\n",__FILE__,__LINE__);
    -	if (copy_from_user(&bmx, arg, sizeof(bmx)))
    -		return XFS_ERROR(EFAULT);
    -
    -	printf("%s:%d\n",__FILE__,__LINE__);
    -	if (bmx.bmv_count < 2)
    -		return XFS_ERROR(EINVAL);
    -
    -	/*
    -	 * Map input getbmapx structure to a getbmap
    -	 * structure for xfs_getbmap.
    -	 */
    -	GETBMAP_CONVERT(bmx, bm);
    -
    -	iflags = bmx.bmv_iflags;
    -
    -	if (iflags & (~BMV_IF_VALID))
    -		return XFS_ERROR(EINVAL);
    -
    -	iflags |= BMV_IF_EXTENDED;
    -
    -	printf("%s:%d arg+1 %p arg %p\n",__FILE__,__LINE__,(struct getbmapx __user *)arg+1,arg);
    -	error = xfs_getbmap(bdp, &bm, (struct getbmapx __user *)arg+1, iflags);
    -	if (error)
    -		return error;
    -
    -	printf("%s:%d\n",__FILE__,__LINE__);
    -	GETBMAP_CONVERT(bm, bmx);
    -
    -	printf("%s:%d\n",__FILE__,__LINE__);
    -	if (copy_to_user(arg, &bmx, sizeof(bmx)))
    -		return XFS_ERROR(EFAULT);
    -
    -	printf("%s:%d\n",__FILE__,__LINE__);
    -	return 0;
    -}
    -
    -#else
    -
    -int
    -xfs_ioctl(
    -	bhv_desc_t		*bdp,
    -	struct inode		*inode,
    -	struct file		*filp,
    -	int			ioflags,
    -	u_long			cmd,
    -	unsigned long		arg)
    -{
    -	return EINVAL;
    -}
    -
    -#endif
    diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_iops.h b/sys/gnu/fs/xfs/FreeBSD/xfs_iops.h
    deleted file mode 100644
    index 8f585b6a750..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/xfs_iops.h
    +++ /dev/null
    @@ -1,61 +0,0 @@
    -/*
    - * Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or modify it
    - * under the terms of version 2 of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful, but
    - * WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    - *
    - * Further, this software is distributed without any warranty that it is
    - * free of the rightful claim of any third person regarding infringement
    - * or the like.  Any license provided herein, whether implied or
    - * otherwise, applies only to this software file.  Patent licenses, if
    - * any, provided herein do not apply to combinations of this program with
    - * other software, or any other product whatsoever.
    - *
    - * You should have received a copy of the GNU General Public License along
    - * with this program; if not, write the Free Software Foundation, Inc., 59
    - * Temple Place - Suite 330, Boston MA 02111-1307, USA.
    - *
    - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
    - * Mountain View, CA  94043, or:
    - *
    - * http://www.sgi.com
    - *
    - * For further information regarding this notice, see:
    - *
    - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
    - */
    -#ifndef __XFS_IOPS_H__
    -#define __XFS_IOPS_H__
    -
    -/*
    - * Extended system attributes.
    - * So far only POSIX ACLs are supported, but this will need to
    - * grow in time (capabilities, mandatory access control, etc).
    - */
    -#define XFS_SYSTEM_NAMESPACE	SYSTEM_POSIXACL
    -
    -/*
    - * Define a table of the namespaces XFS supports
    - */
    -typedef int (*xattr_exists_t)(xfs_vnode_t *);
    -
    -typedef struct xattr_namespace {
    -	char		*name;
    -	unsigned int	namelen;
    -	xattr_exists_t	exists;
    -} xattr_namespace_t;
    -
    -#define SYSTEM_NAMES	0
    -#define ROOT_NAMES	1
    -#define USER_NAMES	2
    -extern struct xattr_namespace *xfs_namespaces;
    -
    -extern int xfs_ioctl(struct bhv_desc *, struct inode *, struct file *,
    -		    int, u_long, void *);
    -
    -#endif /* __XFS_IOPS_H__ */
    diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_mountops.c b/sys/gnu/fs/xfs/FreeBSD/xfs_mountops.c
    deleted file mode 100644
    index 8597c6c28a1..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/xfs_mountops.c
    +++ /dev/null
    @@ -1,500 +0,0 @@
    -/*
    - * Copyright (c) 2001,2006 Alexander Kabaev, Russell Cattelan Digital Elves Inc.
    - * 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 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -
    -#include 
    -#include 
    -
    -#include "xfs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_inum.h"
    -#include "xfs_log.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_btree.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_ialloc.h"
    -#include "xfs_inode.h"
    -#include "xfs_alloc.h"
    -#include "xfs_rtalloc.h"
    -#include "xfs_bmap.h"
    -#include "xfs_error.h"
    -#include "xfs_rw.h"
    -#include "xfs_quota.h"
    -#include "xfs_fsops.h"
    -#include "xfs_clnt.h"
    -
    -#include 
    -
    -static MALLOC_DEFINE(M_XFSNODE, "XFS node", "XFS vnode private part");
    -
    -static vfs_mount_t	_xfs_mount;
    -static vfs_unmount_t	_xfs_unmount;
    -static vfs_root_t	_xfs_root;
    -static vfs_quotactl_t	_xfs_quotactl;
    -static vfs_statfs_t	_xfs_statfs;
    -static vfs_sync_t	_xfs_sync;
    -static vfs_vget_t	_xfs_vget;
    -static vfs_fhtovp_t	_xfs_fhtovp;
    -static vfs_init_t	_xfs_init;
    -static vfs_uninit_t	_xfs_uninit;
    -static vfs_extattrctl_t	_xfs_extattrctl;
    -
    -static b_strategy_t	xfs_geom_strategy;
    -
    -static const char *xfs_opts[] =
    -	{ "from", "flags", "logbufs", "logbufsize",
    -	  "rtname", "logname", "iosizelog", "sunit",
    -	  "swidth", "export",
    -	  NULL };
    -
    -static void
    -parse_int(struct mount *mp, const char *opt, int *val, int *error)
    -{
    -	char *tmp, *ep;
    -
    -	tmp = vfs_getopts(mp->mnt_optnew, opt, error);
    -	if (*error != 0) {
    -		return;
    -	}
    -	if (tmp != NULL) {
    -		*val = (int)strtol(tmp, &ep, 10);
    -		if (*ep) {
    -			*error = EINVAL;
    -			return;
    -		}
    -	}
    -}
    -
    -static int
    -_xfs_param_copyin(struct mount *mp, struct thread *td)
    -{
    -	struct xfsmount *xmp = MNTTOXFS(mp);
    -	struct xfs_mount_args *args = &xmp->m_args;
    -	char *path;
    -	char *fsname;
    -	char *rtname;
    -	char *logname;
    -	int error;
    -
    -	path = vfs_getopts(mp->mnt_optnew, "fspath", &error);
    -	if  (error)
    -		return (error);
    -
    -	bzero(args, sizeof(struct xfs_mount_args));
    -	args->logbufs = -1;
    -	args->logbufsize = -1;
    -
    -	parse_int(mp, "flags", &args->flags, &error);
    -	if (error != 0 && error != ENOENT)
    -		return error;
    -
    -	args->flags |= XFSMNT_32BITINODES;
    -
    -	parse_int(mp, "sunit", &args->sunit, &error);
    -	if (error != 0 && error != ENOENT)
    -		return error;
    -
    -	parse_int(mp, "swidth", &args->swidth, &error);
    -	if (error != 0 && error != ENOENT)
    -		return error;
    -
    -	parse_int(mp, "logbufs", &args->logbufs, &error);
    -	if (error != 0 && error != ENOENT)
    -		return error;
    -
    -	parse_int(mp, "logbufsize", &args->logbufsize, &error);
    -	if (error != 0 && error != ENOENT)
    -		return error;
    -
    -	fsname = vfs_getopts(mp->mnt_optnew, "from", &error);
    -	if (error == 0 && fsname != NULL) {
    -		strncpy(args->fsname, fsname, sizeof(args->fsname) - 1);
    -	}
    -
    -	logname = vfs_getopts(mp->mnt_optnew, "logname", &error);
    -	if (error == 0 && logname != NULL) {
    -		strncpy(args->logname, logname, sizeof(args->logname) - 1);
    -	}
    -
    -	rtname = vfs_getopts(mp->mnt_optnew, "rtname", &error);
    -	if (error == 0 && rtname != NULL) {
    -		strncpy(args->rtname, rtname, sizeof(args->rtname) - 1);
    -	}
    -
    -	strncpy(args->mtpt, path, sizeof(args->mtpt));
    -
    -	printf("fsname '%s' logname '%s' rtname '%s'\n"
    -	       "flags 0x%x sunit %d swidth %d logbufs %d logbufsize %d\n",
    -	       args->fsname, args->logname, args->rtname, args->flags,
    -	       args->sunit, args->swidth, args->logbufs, args->logbufsize);
    -
    -	vfs_mountedfrom(mp, args->fsname);
    -
    -	return (0);
    -}
    -
    -static int
    -_xfs_mount(struct mount		*mp)
    -{
    -	struct xfsmount		*xmp;
    -	struct xfs_vnode	*rootvp;
    -	struct ucred		*curcred;
    -	struct vnode		*rvp, *devvp;
    -	struct cdev		*ddev;
    -	struct g_consumer	*cp;
    -	struct thread		*td;
    -	int			error;
    -	
    -	td = curthread;
    -	ddev = NULL;
    -	cp = NULL;
    -
    -	if (vfs_filteropt(mp->mnt_optnew, xfs_opts))
    -		return (EINVAL);
    -
    -	if (mp->mnt_flag & MNT_UPDATE)
    -		return (0);
    -	if ((mp->mnt_flag & MNT_RDONLY) == 0)
    -		return (EPERM);
    -
    -        xmp = xfsmount_allocate(mp);
    -        if (xmp == NULL)
    -                return (ENOMEM);
    -
    -	if((error = _xfs_param_copyin(mp, td)) != 0)
    -		goto fail;
    -
    -	curcred = td->td_ucred;
    -	XVFS_MOUNT(XFSTOVFS(xmp), &xmp->m_args, curcred, error);
    -	if (error)
    -		goto fail;
    -
    - 	XVFS_ROOT(XFSTOVFS(xmp), &rootvp, error);
    -	ddev = XFS_VFSTOM(XFSTOVFS(xmp))->m_ddev_targp->dev;
    -	devvp = XFS_VFSTOM(XFSTOVFS(xmp))->m_ddev_targp->specvp;
    -	if (error)
    -		goto fail_unmount;
    -
    - 	if (ddev->si_iosize_max != 0)
    -		mp->mnt_iosize_max = ddev->si_iosize_max;
    -        if (mp->mnt_iosize_max > MAXPHYS)
    -		mp->mnt_iosize_max = MAXPHYS;
    -
    -        mp->mnt_flag |= MNT_LOCAL;
    -        mp->mnt_stat.f_fsid.val[0] = dev2udev(ddev);
    -        mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
    -
    -        if ((error = VFS_STATFS(mp, &mp->mnt_stat)) != 0)
    -		goto fail_unmount;
    -
    -	rvp = rootvp->v_vnode;
    -	rvp->v_vflag |= VV_ROOT;
    -	VN_RELE(rootvp);
    -
    -	return (0);
    -
    - fail_unmount:
    -	XVFS_UNMOUNT(XFSTOVFS(xmp), 0, curcred, error);
    -
    -	if (devvp != NULL) {
    -		cp = devvp->v_bufobj.bo_private;
    -		if (cp != NULL) {
    -			DROP_GIANT();
    -			g_topology_lock();
    -			g_vfs_close(cp);
    -			g_topology_unlock();
    -			PICKUP_GIANT();
    -		}
    -	}
    -
    - fail:
    -	if (xmp != NULL)
    -		xfsmount_deallocate(xmp);
    -
    -	return (error);
    -}
    -
    -/*
    - * Free reference to null layer
    - */
    -static int
    -_xfs_unmount(mp, mntflags)
    -	struct mount *mp;
    -	int mntflags;
    -{
    -	struct vnode *devvp;
    -	struct g_consumer *cp;
    -	int error;
    -	cp = NULL;
    -	devvp = NULL;
    -
    -	devvp = XFS_VFSTOM((MNTTOVFS(mp)))->m_ddev_targp->specvp;
    -	if (devvp != NULL)
    -		cp = devvp->v_bufobj.bo_private;
    -
    -	XVFS_UNMOUNT(MNTTOVFS(mp), 0, curthread->td_ucred, error);
    -	if (error == 0) {
    -		if (cp != NULL) {
    -			DROP_GIANT();
    -			g_topology_lock();
    -			g_vfs_close(cp);
    -			g_topology_unlock();
    -			PICKUP_GIANT();
    -		}
    -	}
    -	return (error);
    -}
    -
    -static int
    -_xfs_root(mp, flags, vpp)
    -	struct mount *mp;
    -	int flags;
    -	struct vnode **vpp;
    -{
    -	xfs_vnode_t *vp;
    -	int error;
    -
    -        XVFS_ROOT(MNTTOVFS(mp), &vp, error);
    -	if (error == 0) {
    -		*vpp = vp->v_vnode;
    -		VOP_LOCK(*vpp, flags);
    -	}
    -	return (error);
    -}
    -
    -static int
    -_xfs_quotactl(mp, cmd, uid, arg)
    -	struct mount *mp;
    -	int cmd;
    -	uid_t uid;
    -	void *arg;
    -{
    -	printf("xfs_quotactl\n");
    -	return EOPNOTSUPP;
    -}
    -
    -static int
    -_xfs_statfs(mp, sbp)
    -	struct mount *mp;
    -	struct statfs *sbp;
    -{
    -	int error;
    -
    -        XVFS_STATVFS(MNTTOVFS(mp), sbp, NULL, error);
    -        if (error)
    -		return error;
    -
    -	/* Fix up the values XFS statvfs calls does not know about. */
    -	sbp->f_iosize = sbp->f_bsize;
    -
    -	return (error);
    -}
    -
    -static int
    -_xfs_sync(mp, waitfor)
    -	struct mount *mp;
    -	int waitfor;
    -{
    -	int error;
    -	int flags = SYNC_FSDATA|SYNC_ATTR|SYNC_REFCACHE;
    -
    -	if (waitfor == MNT_WAIT)
    -		flags |= SYNC_WAIT;
    -	else if (waitfor == MNT_LAZY)
    -		flags |= SYNC_BDFLUSH;
    -        XVFS_SYNC(MNTTOVFS(mp), flags, curthread->td_ucred, error);
    -	return (error);
    -}
    -
    -static int
    -_xfs_vget(mp, ino, flags, vpp)
    -	struct mount *mp;
    -	ino_t ino;
    -	int flags;
    -	struct vnode **vpp;
    -{
    -	xfs_vnode_t *vp = NULL;
    -	int error;
    -
    -	printf("XVFS_GET_VNODE(MNTTOVFS(mp), &vp, ino, error);\n");
    -	error = ENOSYS;
    -	if (error == 0)
    -		*vpp = vp->v_vnode;
    -	return (error);
    -}
    -
    -static int
    -_xfs_fhtovp(mp, fidp, flags, vpp)
    -	struct mount *mp;
    -	struct fid *fidp;
    -	int flags;
    -	struct vnode **vpp;
    -{
    -	printf("xfs_fhtovp\n");
    -	return ENOSYS;
    -}
    -
    -static int
    -_xfs_extattrctl(struct mount *mp, int cm,
    -                struct vnode *filename_v,
    -                int attrnamespace, const char *attrname)
    -{
    -	printf("xfs_extattrctl\n");
    -	return ENOSYS;
    -}
    -
    -int
    -_xfs_init(vfsp)
    -	struct vfsconf *vfsp;
    -{
    -	int error;
    -
    -	error = init_xfs_fs();
    -
    -	return (error);
    -}
    -
    -int
    -_xfs_uninit(vfsp)
    -	struct vfsconf *vfsp;
    -{
    -	exit_xfs_fs();
    -	return 0;
    -}
    -
    -static struct vfsops xfs_fsops = {
    -	.vfs_mount =	_xfs_mount,
    -	.vfs_unmount =	_xfs_unmount,
    -	.vfs_root =	_xfs_root,
    -	.vfs_quotactl = _xfs_quotactl,
    -	.vfs_statfs =	_xfs_statfs,
    -	.vfs_sync =	_xfs_sync,
    -	.vfs_vget =	_xfs_vget,
    -	.vfs_fhtovp =	_xfs_fhtovp,
    -	.vfs_init =	_xfs_init,
    -	.vfs_uninit =	_xfs_uninit,
    -	.vfs_extattrctl = _xfs_extattrctl,
    -};
    -
    -VFS_SET(xfs_fsops, xfs, VFCF_READONLY);
    -
    -/*
    - *  Copy GEOM VFS functions here to provide a conveniet place to
    - *  track all XFS-related IO without being distracted by other
    - *  filesystems which happen to be mounted on the machine at the
    - *  same time.
    - */
    -
    -static void
    -xfs_geom_biodone(struct bio *bip)
    -{
    -	struct buf *bp;
    -
    -	if (bip->bio_error) {
    -		printf("g_vfs_done():");
    -		g_print_bio(bip);
    -		printf("error = %d\n", bip->bio_error);
    -	}
    -	bp = bip->bio_caller2;
    -	bp->b_error = bip->bio_error;
    -	bp->b_ioflags = bip->bio_flags;
    -	if (bip->bio_error)
    -		bp->b_ioflags |= BIO_ERROR;
    -	bp->b_resid = bp->b_bcount - bip->bio_completed;
    -	g_destroy_bio(bip);
    -	mtx_lock(&Giant);
    -	bufdone(bp);
    -	mtx_unlock(&Giant);
    -}
    -
    -static void
    -xfs_geom_strategy(struct bufobj *bo, struct buf *bp)
    -{
    -	struct g_consumer *cp;
    -	struct bio *bip;
    -
    -	cp = bo->bo_private;
    -	G_VALID_CONSUMER(cp);
    -
    -	bip = g_alloc_bio();
    -	bip->bio_cmd = bp->b_iocmd;
    -	bip->bio_offset = bp->b_iooffset;
    -	bip->bio_data = bp->b_data;
    -	bip->bio_done = xfs_geom_biodone;
    -	bip->bio_caller2 = bp;
    -	bip->bio_length = bp->b_bcount;
    -	g_io_request(bip, cp);
    -}
    -
    -static int
    -xfs_geom_bufwrite(struct buf *bp)
    -{
    -	return bufwrite(bp);
    -}
    -
    -static int
    -xfs_geom_bufsync(struct bufobj *bo, int waitfor)
    -{
    -
    -	return (bufsync(bo, waitfor));
    -}
    -
    -static void
    -xfs_geom_bufbdflush(struct bufobj *bo, struct buf *bp)
    -{
    -	bufbdflush(bo, bp);
    -}
    -
    -struct buf_ops xfs_bo_ops = {
    -	.bop_name =     "XFS",
    -	.bop_write =    xfs_geom_bufwrite,
    -	.bop_strategy = xfs_geom_strategy,
    -	.bop_sync =     xfs_geom_bufsync,
    -	.bop_bdflush =	xfs_geom_bufbdflush,
    -};
    diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_mountops.h b/sys/gnu/fs/xfs/FreeBSD/xfs_mountops.h
    deleted file mode 100644
    index c8a766d5155..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/xfs_mountops.h
    +++ /dev/null
    @@ -1,59 +0,0 @@
    -/*-
    - * Copyright (c) 2001 Alexander Kabaev
    - * 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	_XFS_XFS_H_
    -#define	_XFS_XFS_H_
    -
    -#define	XFSFS_VMAJOR   0
    -#define	XFS_VMINOR     1
    -#define	XFS_VERSION    ((XFS_VMAJOR << 16) | XFS_VMINOR)
    -#define XFS_NAME       "xfs"
    -
    -#ifdef _KERNEL
    -
    -struct xfsmount {
    -	struct xfs_mount_args	m_args;		/* Mount parameters */
    -	struct mount *		m_mp;		/* Back pointer */
    -	xfs_vfs_t		m_vfs;		/* SHOULD BE FIRST */
    -};
    -
    -#define XFSTOMNT(xmp)	((xmp)->m_mp)
    -#define XFSTOVFS(xmp)	(&(xmp)->m_vfs)
    -
    -#define	MNTTOXFS(mp)	((struct xfsmount *)((mp)->mnt_data))
    -#define	MNTTOVFS(mp)	XFSTOVFS(MNTTOXFS(mp))
    -
    -#define VFSTOMNT(vfsp)	(vfsp)->vfs_mp
    -#define VFSTOXFS(vfsp)	MNTTOXFS(VFSTOMNT(vfsp))
    -
    -struct  xfsmount *xfsmount_allocate(struct mount *mp);
    -void	xfsmount_deallocate(struct xfsmount *xmp);
    -
    -#endif	/* _KERNEL */
    -
    -#endif	/* _XFS_XFS_H*/
    -
    diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_node.h b/sys/gnu/fs/xfs/FreeBSD/xfs_node.h
    deleted file mode 100644
    index d8b613c3c50..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/xfs_node.h
    +++ /dev/null
    @@ -1,16 +0,0 @@
    -#ifndef __XFS_NODE_H__
    -#define __XFS_NODE_H__
    -
    -/*
    - * Save one allocation on FreeBSD and always allocate both inode and
    - * xfs_vnode struct as a single memory block.
    - */
    -struct xfs_node
    -{
    -	struct xfs_inode n_inode;
    -	struct xfs_vnode n_vnode;
    -};
    -
    -#define XFS_CAST_IP2VP(ip)	(&((struct xfs_node *)(ip))->n_vnode)
    -
    -#endif	/* __XFS_NODE_H__ */
    diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_stats.c b/sys/gnu/fs/xfs/FreeBSD/xfs_stats.c
    deleted file mode 100644
    index 40b30568e84..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/xfs_stats.c
    +++ /dev/null
    @@ -1,105 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or modify it
    - * under the terms of version 2 of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful, but
    - * WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    - *
    - * Further, this software is distributed without any warranty that it is
    - * free of the rightful claim of any third person regarding infringement
    - * or the like.  Any license provided herein, whether implied or
    - * otherwise, applies only to this software file.  Patent licenses, if
    - * any, provided herein do not apply to combinations of this program with
    - * other software, or any other product whatsoever.
    - *
    - * You should have received a copy of the GNU General Public License along
    - * with this program; if not, write the Free Software Foundation, Inc., 59
    - * Temple Place - Suite 330, Boston MA 02111-1307, USA.
    - *
    - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
    - * Mountain View, CA  94043, or:
    - *
    - * http://www.sgi.com
    - *
    - * For further information regarding this notice, see:
    - *
    - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
    - */
    -
    -#include "xfs.h"
    -
    -struct xfsstats xfsstats;
    -
    -STATIC int
    -xfs_read_xfsstats(
    -	char		*buffer,
    -	char		**start,
    -	off_t		offset,
    -	int		count,
    -	int		*eof,
    -	void		*data)
    -{
    -	int		i, j, len;
    -	static struct xstats_entry {
    -		char	*desc;
    -		int	endpoint;
    -	} xstats[] = {
    -		{ "extent_alloc",	XFSSTAT_END_EXTENT_ALLOC	},
    -		{ "abt",		XFSSTAT_END_ALLOC_BTREE		},
    -		{ "blk_map",		XFSSTAT_END_BLOCK_MAPPING	},
    -		{ "bmbt",		XFSSTAT_END_BLOCK_MAP_BTREE	},
    -		{ "dir",		XFSSTAT_END_DIRECTORY_OPS	},
    -		{ "trans",		XFSSTAT_END_TRANSACTIONS	},
    -		{ "ig",			XFSSTAT_END_INODE_OPS		},
    -		{ "log",		XFSSTAT_END_LOG_OPS		},
    -		{ "push_ail",		XFSSTAT_END_TAIL_PUSHING	},
    -		{ "xstrat",		XFSSTAT_END_WRITE_CONVERT	},
    -		{ "rw",			XFSSTAT_END_READ_WRITE_OPS	},
    -		{ "attr",		XFSSTAT_END_ATTRIBUTE_OPS	},
    -		{ "icluster",		XFSSTAT_END_INODE_CLUSTER	},
    -		{ "vnodes",		XFSSTAT_END_VNODE_OPS		},
    -	};
    -
    -	for (i=j=len = 0; i < sizeof(xstats)/sizeof(struct xstats_entry); i++) {
    -		len += sprintf(buffer + len, "%s", xstats[i].desc);
    -		/* inner loop does each group */
    -		while (j < xstats[i].endpoint) {
    -			len += sprintf(buffer + len, " %u",
    -					*(((__u32*)&xfsstats) + j));
    -			j++;
    -		}
    -		buffer[len++] = '\n';
    -	}
    -	/* extra precision counters */
    -	len += sprintf(buffer + len, "xpc %ju %ju %ju\n",
    -			(uintmax_t)xfsstats.xs_xstrat_bytes,
    -			(uintmax_t)xfsstats.xs_write_bytes,
    -			(uintmax_t)xfsstats.xs_read_bytes);
    -
    -	if (offset >= len) {
    -		*start = buffer;
    -		*eof = 1;
    -		return 0;
    -	}
    -	*start = buffer + offset;
    -	if ((len -= offset) > count)
    -		return count;
    -	*eof = 1;
    -
    -	return len;
    -}
    -
    -void
    -xfs_init_procfs(void)
    -{
    -	if (&xfs_read_xfsstats != NULL);
    -}
    -
    -void
    -xfs_cleanup_procfs(void)
    -{
    -}
    diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_stats.h b/sys/gnu/fs/xfs/FreeBSD/xfs_stats.h
    deleted file mode 100644
    index 04ddc95d46f..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/xfs_stats.h
    +++ /dev/null
    @@ -1,161 +0,0 @@
    -/*
    - * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or modify it
    - * under the terms of version 2 of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful, but
    - * WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    - *
    - * Further, this software is distributed without any warranty that it is
    - * free of the rightful claim of any third person regarding infringement
    - * or the like.  Any license provided herein, whether implied or
    - * otherwise, applies only to this software file.  Patent licenses, if
    - * any, provided herein do not apply to combinations of this program with
    - * other software, or any other product whatsoever.
    - *
    - * You should have received a copy of the GNU General Public License along
    - * with this program; if not, write the Free Software Foundation, Inc., 59
    - * Temple Place - Suite 330, Boston MA 02111-1307, USA.
    - *
    - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
    - * Mountain View, CA  94043, or:
    - *
    - * http://www.sgi.com
    - *
    - * For further information regarding this notice, see:
    - *
    - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
    - */
    -#ifndef __XFS_STATS_H__
    -#define __XFS_STATS_H__
    -
    -
    -#if !defined(XFS_STATS_OFF)
    -
    -/*
    - * XFS global statistics
    - */
    -struct xfsstats {
    -# define XFSSTAT_END_EXTENT_ALLOC	4
    -	__uint32_t		xs_allocx;
    -	__uint32_t		xs_allocb;
    -	__uint32_t		xs_freex;
    -	__uint32_t		xs_freeb;
    -# define XFSSTAT_END_ALLOC_BTREE	(XFSSTAT_END_EXTENT_ALLOC+4)
    -	__uint32_t		xs_abt_lookup;
    -	__uint32_t		xs_abt_compare;
    -	__uint32_t		xs_abt_insrec;
    -	__uint32_t		xs_abt_delrec;
    -# define XFSSTAT_END_BLOCK_MAPPING	(XFSSTAT_END_ALLOC_BTREE+7)
    -	__uint32_t		xs_blk_mapr;
    -	__uint32_t		xs_blk_mapw;
    -	__uint32_t		xs_blk_unmap;
    -	__uint32_t		xs_add_exlist;
    -	__uint32_t		xs_del_exlist;
    -	__uint32_t		xs_look_exlist;
    -	__uint32_t		xs_cmp_exlist;
    -# define XFSSTAT_END_BLOCK_MAP_BTREE	(XFSSTAT_END_BLOCK_MAPPING+4)
    -	__uint32_t		xs_bmbt_lookup;
    -	__uint32_t		xs_bmbt_compare;
    -	__uint32_t		xs_bmbt_insrec;
    -	__uint32_t		xs_bmbt_delrec;
    -# define XFSSTAT_END_DIRECTORY_OPS	(XFSSTAT_END_BLOCK_MAP_BTREE+4)
    -	__uint32_t		xs_dir_lookup;
    -	__uint32_t		xs_dir_create;
    -	__uint32_t		xs_dir_remove;
    -	__uint32_t		xs_dir_getdents;
    -# define XFSSTAT_END_TRANSACTIONS	(XFSSTAT_END_DIRECTORY_OPS+3)
    -	__uint32_t		xs_trans_sync;
    -	__uint32_t		xs_trans_async;
    -	__uint32_t		xs_trans_empty;
    -# define XFSSTAT_END_INODE_OPS		(XFSSTAT_END_TRANSACTIONS+7)
    -	__uint32_t		xs_ig_attempts;
    -	__uint32_t		xs_ig_found;
    -	__uint32_t		xs_ig_frecycle;
    -	__uint32_t		xs_ig_missed;
    -	__uint32_t		xs_ig_dup;
    -	__uint32_t		xs_ig_reclaims;
    -	__uint32_t		xs_ig_attrchg;
    -# define XFSSTAT_END_LOG_OPS		(XFSSTAT_END_INODE_OPS+5)
    -	__uint32_t		xs_log_writes;
    -	__uint32_t		xs_log_blocks;
    -	__uint32_t		xs_log_noiclogs;
    -	__uint32_t		xs_log_force;
    -	__uint32_t		xs_log_force_sleep;
    -# define XFSSTAT_END_TAIL_PUSHING	(XFSSTAT_END_LOG_OPS+10)
    -	__uint32_t		xs_try_logspace;
    -	__uint32_t		xs_sleep_logspace;
    -	__uint32_t		xs_push_ail;
    -	__uint32_t		xs_push_ail_success;
    -	__uint32_t		xs_push_ail_pushbuf;
    -	__uint32_t		xs_push_ail_pinned;
    -	__uint32_t		xs_push_ail_locked;
    -	__uint32_t		xs_push_ail_flushing;
    -	__uint32_t		xs_push_ail_restarts;
    -	__uint32_t		xs_push_ail_flush;
    -# define XFSSTAT_END_WRITE_CONVERT	(XFSSTAT_END_TAIL_PUSHING+2)
    -	__uint32_t		xs_xstrat_quick;
    -	__uint32_t		xs_xstrat_split;
    -# define XFSSTAT_END_READ_WRITE_OPS	(XFSSTAT_END_WRITE_CONVERT+2)
    -	__uint32_t		xs_write_calls;
    -	__uint32_t		xs_read_calls;
    -# define XFSSTAT_END_ATTRIBUTE_OPS	(XFSSTAT_END_READ_WRITE_OPS+4)
    -	__uint32_t		xs_attr_get;
    -	__uint32_t		xs_attr_set;
    -	__uint32_t		xs_attr_remove;
    -	__uint32_t		xs_attr_list;
    -# define XFSSTAT_END_INODE_CLUSTER	(XFSSTAT_END_ATTRIBUTE_OPS+3)
    -	__uint32_t		xs_iflush_count;
    -	__uint32_t		xs_icluster_flushcnt;
    -	__uint32_t		xs_icluster_flushinode;
    -# define XFSSTAT_END_VNODE_OPS		(XFSSTAT_END_INODE_CLUSTER+8)
    -	__uint32_t		vn_active;	/* # vnodes not on free lists */
    -	__uint32_t		vn_alloc;	/* # times vn_alloc called */
    -	__uint32_t		vn_get;		/* # times vn_get called */
    -	__uint32_t		vn_hold;	/* # times vn_hold called */
    -	__uint32_t		vn_rele;	/* # times vn_rele called */
    -	__uint32_t		vn_reclaim;	/* # times vn_reclaim called */
    -	__uint32_t		vn_remove;	/* # times vn_remove called */
    -	__uint32_t		vn_free;	/* # times vn_free called */
    -#define XFSSTAT_END_BUF			(XFSSTAT_END_VNODE_OPS+9)
    -	__uint32_t		pb_get;
    -	__uint32_t		pb_create;
    -	__uint32_t		pb_get_locked;
    -	__uint32_t		pb_get_locked_waited;
    -	__uint32_t		pb_busy_locked;
    -	__uint32_t		pb_miss_locked;
    -	__uint32_t		pb_page_retries;
    -	__uint32_t		pb_page_found;
    -	__uint32_t		pb_get_read;
    -/* Extra precision counters */
    -	__uint64_t		xs_xstrat_bytes;
    -	__uint64_t		xs_write_bytes;
    -	__uint64_t		xs_read_bytes;
    -};
    -
    -extern struct xfsstats xfsstats;
    -
    -# define XFS_STATS_INC(count)		( xfsstats.count++ )
    -# define XFS_STATS_DEC(count)		( xfsstats.count-- )
    -# define XFS_STATS_ADD(count, inc)	( xfsstats.count += (inc) )
    -
    -extern void xfs_init_procfs(void);
    -extern void xfs_cleanup_procfs(void);
    -
    -
    -#else	/* !CONFIG_PROC_FS */
    -
    -# define XFS_STATS_INC(count)
    -# define XFS_STATS_DEC(count)
    -# define XFS_STATS_ADD(count, inc)
    -
    -static __inline void xfs_init_procfs(void) { };
    -static __inline void xfs_cleanup_procfs(void) { };
    -
    -#endif	/* !CONFIG_PROC_FS */
    -
    -#endif /* __XFS_STATS_H__ */
    -
    diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_super.c b/sys/gnu/fs/xfs/FreeBSD/xfs_super.c
    deleted file mode 100644
    index 747a5dae262..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/xfs_super.c
    +++ /dev/null
    @@ -1,279 +0,0 @@
    -/*
    - * Copyright (c) 2000-2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_clnt.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_alloc.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_quota.h"
    -#include "xfs_mount.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_btree.h"
    -#include "xfs_ialloc.h"
    -#include "xfs_bmap.h"
    -#include "xfs_rtalloc.h"
    -#include "xfs_error.h"
    -#include "xfs_itable.h"
    -#include "xfs_rw.h"
    -#include "xfs_acl.h"
    -#include "xfs_cap.h"
    -#include "xfs_mac.h"
    -#include "xfs_attr.h"
    -#include "xfs_buf_item.h"
    -#include "xfs_utils.h"
    -#include "xfs_version.h"
    -#include "xfs_buf.h"
    -
    -#include 
    -
    -#include 
    -#include 
    -
    -extern struct vop_vector xfs_fifoops;
    -extern struct xfs_vnodeops xfs_vnodeops;
    -
    -__uint64_t
    -xfs_max_file_offset(
    -	unsigned int		blockshift)
    -{
    -
    -	return (OFF_MAX);
    -}
    -
    -void
    -xfs_initialize_vnode(
    -	bhv_desc_t		*bdp,
    -	xfs_vnode_t		*xvp,
    -	bhv_desc_t		*inode_bhv,
    -	int			unlock)
    -{
    -	xfs_inode_t		*ip = XFS_BHVTOI(inode_bhv);
    -
    -	if (!inode_bhv->bd_vobj) {
    -		xvp->v_vfsp = bhvtovfs(bdp);
    -		bhv_desc_init(inode_bhv, ip, xvp, &xfs_vnodeops);
    -		bhv_insert(VN_BHV_HEAD(xvp), inode_bhv);
    -	}
    -
    -	/*
    -	 * XXX: Use VNON as an indication of freshly allocated vnode
    -	 * which need to be initialized and unlocked.
    -	 * This is _not_ like the same place in Linux version of
    -	 * routine.
    -	 */
    -
    -	if (xvp->v_vnode->v_type != VNON)
    -	  return;
    -
    -	xvp->v_vnode->v_type =  IFTOVT(ip->i_d.di_mode);
    -
    -	if (xvp->v_vnode->v_type == VFIFO)
    -		xvp->v_vnode->v_op = &xfs_fifoops;
    -
    -	ASSERT_VOP_LOCKED(xvp->v_vnode, "xfs_initialize_vnode");
    -
    -	/* For new inodes we need to set the ops vectors,
    -	 * and unlock the inode.
    -	 */
    -	if (ip->i_d.di_mode != 0 && unlock)
    -		VOP_UNLOCK(xvp->v_vnode, 0);
    -}
    -
    -#if 0
    -struct vnode *
    -xfs_get_inode(
    -	bhv_desc_t	*bdp,
    -	xfs_ino_t	ino,
    -	int		flags)
    -{
    -	return NULL;
    -}
    -#endif
    -
    -/*ARGSUSED*/
    -int
    -xfs_blkdev_get(
    -	xfs_mount_t		*mp,
    -	const char		*name,
    -	struct vnode		**bdevp)
    -{
    -	struct nameidata	nd;
    -	struct nameidata	*ndp = &nd;
    -	int			error, ronly;
    -	struct thread		*td;
    -	struct vnode		*devvp;
    -	struct g_consumer	*cp;
    -	struct g_provider	*pp;
    -	accmode_t		accmode;
    -
    -	td = curthread;
    -
    -	NDINIT(ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, name, td);
    -	if ((error = namei(ndp)) != 0)
    -		return (error);
    -	NDFREE(ndp, NDF_ONLY_PNBUF);
    -	devvp = ndp->ni_vp;
    -
    -	if (!vn_isdisk(devvp, &error)) {
    -		vrele(devvp);
    -		return (error);
    -	}
    -
    -	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
    -
    -	ronly = ((XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY) != 0);
    -	accmode = VREAD;
    -	if (!ronly)
    -		accmode |= VWRITE;
    -	error = VOP_ACCESS(devvp, accmode, td->td_ucred, td);
    -	if (error)
    -		error = priv_check(td, PRIV_VFS_MOUNT_PERM);
    -	if (error) {
    -		vput(devvp);
    -		return (error);
    -	}
    -
    -	DROP_GIANT();
    -	g_topology_lock();
    -
    -	/*
    -	 * XXX: Do not allow more than one consumer to open a device
    -	 *      associated with a particular GEOM provider.
    -	 *      This disables multiple read-only mounts of a device,
    -	 *      but it gets rid of panics in bmemfree() when you try to
    -	 *      mount the same device more than once.
    -	 *      During mounting, XFS does a bread() of the superblock, but does
    -	 *      not brelse() it.  A subsequent mount of the same device
    -	 *      will try to bread() the superblock, resulting in a panic in 
    -	 *      bremfree(), "buffer not on queue".
    -	 */
    -	pp = g_dev_getprovider(devvp->v_rdev);
    - 	if ((pp != NULL) && ((pp->acr | pp->acw | pp->ace ) != 0)) 
    -		error = EPERM;
    -	else 
    -		error = g_vfs_open(devvp, &cp, "xfs", ronly ? 0 : 1);
    -
    -	g_topology_unlock();
    -	PICKUP_GIANT();
    -
    -	if (error) {
    -		vput(devvp);
    -		return (error);
    -	}
    -	VOP_UNLOCK(devvp, 0);
    -
    -	devvp->v_bufobj.bo_private = cp;
    -	devvp->v_bufobj.bo_ops = &xfs_bo_ops;
    -
    -	*bdevp = devvp;
    -	return (0);
    -}
    -
    -void
    -xfs_blkdev_put(
    -	struct vnode	*devvp)
    -{
    -	struct g_consumer	*cp;
    -
    -	if (devvp == NULL)
    -		return;
    -
    -	vinvalbuf(devvp, V_SAVE, 0, 0);
    -
    -	cp = devvp->v_bufobj.bo_private;
    -	DROP_GIANT();
    -	g_topology_lock();
    -	g_wither_geom_close(cp->geom, ENXIO);
    -	g_topology_unlock();
    -	PICKUP_GIANT();
    -
    -        vrele(devvp);
    -}
    -
    -void
    -xfs_mountfs_check_barriers(xfs_mount_t *mp)
    -{
    -	printf("xfs_mountfs_check_barriers NI\n");
    -}
    -
    -void
    -xfs_flush_inode(
    -		xfs_inode_t	*ip)
    -{
    -	printf("xfs_flush_inode NI\n");
    -}
    -
    -void
    -xfs_flush_device(
    -		 xfs_inode_t	*ip)
    -{
    -	printf("xfs_flush_device NI\n");
    -        xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC);
    -}
    -
    -
    -void
    -xfs_blkdev_issue_flush(
    -	xfs_buftarg_t		*buftarg)
    -{
    -	printf("xfs_blkdev_issue_flush NI\n");
    -}
    -
    -int
    -init_xfs_fs( void )
    -{
    -	static const char	message[] =
    -		XFS_VERSION_STRING " with " XFS_BUILD_OPTIONS " enabled\n";
    -
    -	printf(message);
    -
    -	vn_init();
    -	xfs_init();
    -	uuid_init();
    -#ifdef RMC
    -	vfs_initdmapi();
    -#endif
    -	vfs_initquota();
    -
    -	return 0;
    -}
    -
    -void
    -exit_xfs_fs(void)
    -{
    -	xfs_cleanup();
    -	vfs_exitquota();
    -#ifdef RMC
    -	vfs_exitdmapi();
    -#endif
    -}
    -
    diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_super.h b/sys/gnu/fs/xfs/FreeBSD/xfs_super.h
    deleted file mode 100644
    index 0180451eb74..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/xfs_super.h
    +++ /dev/null
    @@ -1,113 +0,0 @@
    -/*
    - * Copyright (c) 2000-2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_SUPER_H__
    -#define __XFS_SUPER_H__
    -
    -#ifdef CONFIG_XFS_DMAPI
    -# define vfs_insertdmapi(vfs)	vfs_insertops(vfsp, &xfs_dmops)
    -# define vfs_initdmapi()	dmapi_init()
    -# define vfs_exitdmapi()	dmapi_uninit()
    -#else
    -# define vfs_insertdmapi(vfs)	do { } while (0)
    -# define vfs_initdmapi()	do { } while (0)
    -# define vfs_exitdmapi()	do { } while (0)
    -#endif
    -
    -#ifdef CONFIG_XFS_QUOTA
    -# define vfs_insertquota(vfs)	vfs_insertops(vfsp, &xfs_qmops)
    -# define vfs_initquota()	xfs_qm_init()
    -# define vfs_exitquota()	xfs_qm_exit()
    -#else
    -# define vfs_insertquota(vfs)	do { } while (0)
    -# define vfs_initquota()	do { } while (0)
    -# define vfs_exitquota()	do { } while (0)
    -#endif
    -
    -#ifdef CONFIG_XFS_POSIX_ACL
    -# define XFS_ACL_STRING		"ACLs, "
    -# define set_posix_acl_flag(sb)	((sb)->s_flags |= MS_POSIXACL)
    -#else
    -# define XFS_ACL_STRING
    -# define set_posix_acl_flag(sb)	do { } while (0)
    -#endif
    -
    -#ifdef CONFIG_XFS_SECURITY
    -# define XFS_SECURITY_STRING	"security attributes, "
    -# define ENOSECURITY		0
    -#else
    -# define XFS_SECURITY_STRING
    -# define ENOSECURITY		EOPNOTSUPP
    -#endif
    -
    -#ifdef CONFIG_XFS_RT
    -# define XFS_REALTIME_STRING	"realtime, "
    -#else
    -# define XFS_REALTIME_STRING
    -#endif
    -
    -#if XFS_BIG_BLKNOS
    -# if XFS_BIG_INUMS
    -#  define XFS_BIGFS_STRING	"large block/inode numbers, "
    -# else
    -#  define XFS_BIGFS_STRING	"large block numbers, "
    -# endif
    -#else
    -# define XFS_BIGFS_STRING
    -#endif
    -
    -#ifdef CONFIG_XFS_TRACE
    -# define XFS_TRACE_STRING	"tracing, "
    -#else
    -# define XFS_TRACE_STRING
    -#endif
    -
    -#ifdef XFSDEBUG
    -# define XFS_DBG_STRING		"debug"
    -#else
    -# define XFS_DBG_STRING		"no debug"
    -#endif
    -
    -#define XFS_BUILD_OPTIONS	XFS_ACL_STRING \
    -				XFS_SECURITY_STRING \
    -				XFS_REALTIME_STRING \
    -				XFS_BIGFS_STRING \
    -				XFS_TRACE_STRING \
    -				XFS_DBG_STRING /* DBG must be last */
    -
    -struct xfs_inode;
    -struct xfs_mount;
    -struct xfs_buftarg;
    -
    -extern __uint64_t xfs_max_file_offset(unsigned int);
    -
    -extern void xfs_initialize_vnode(bhv_desc_t *, xfs_vnode_t *, bhv_desc_t *, int);
    -
    -extern void xfs_flush_inode(struct xfs_inode *);
    -extern void xfs_flush_device(struct xfs_inode *);
    -
    -extern int  xfs_blkdev_get(struct xfs_mount *, const char *,
    -				struct block_device **);
    -extern void xfs_blkdev_put(struct block_device *);
    -extern void xfs_blkdev_issue_flush(struct xfs_buftarg *);
    -
    -extern struct export_operations xfs_export_operations;
    -
    -extern int init_xfs_fs(void);
    -extern void exit_xfs_fs(void);
    -
    -#endif	/* __XFS_SUPER_H__ */
    diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_sysctl.c b/sys/gnu/fs/xfs/FreeBSD/xfs_sysctl.c
    deleted file mode 100644
    index 9ba2d45b33c..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/xfs_sysctl.c
    +++ /dev/null
    @@ -1,43 +0,0 @@
    -/*
    - * Copyright (c) 2001-2002 Silicon Graphics, Inc.  All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or modify it
    - * under the terms of version 2 of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful, but
    - * WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    - *
    - * Further, this software is distributed without any warranty that it is
    - * free of the rightful claim of any third person regarding infringement
    - * or the like.  Any license provided herein, whether implied or
    - * otherwise, applies only to this software file.  Patent licenses, if
    - * any, provided herein do not apply to combinations of this program with
    - * other software, or any other product whatsoever.
    - *
    - * You should have received a copy of the GNU General Public License along
    - * with this program; if not, write the Free Software Foundation, Inc., 59
    - * Temple Place - Suite 330, Boston MA 02111-1307, USA.
    - *
    - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
    - * Mountain View, CA  94043, or:
    - *
    - * http://www.sgi.com
    - *
    - * For further information regarding this notice, see:
    - *
    - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
    - */
    -
    -#include "xfs.h"
    -
    -void
    -xfs_sysctl_register(void)
    -{
    -}
    -
    -void
    -xfs_sysctl_unregister(void)
    -{
    -}
    diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_sysctl.h b/sys/gnu/fs/xfs/FreeBSD/xfs_sysctl.h
    deleted file mode 100644
    index fa68ff0ca0c..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/xfs_sysctl.h
    +++ /dev/null
    @@ -1,102 +0,0 @@
    -/*
    - * Copyright (c) 2001-2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_SYSCTL_H__
    -#define __XFS_SYSCTL_H__
    -
    -/*
    - * Tunable xfs parameters
    - */
    -
    -typedef struct xfs_sysctl_val {
    -	int min;
    -	int val;
    -	int max;
    -} xfs_sysctl_val_t;
    -
    -typedef struct xfs_param {
    -	xfs_sysctl_val_t refcache_size;	/* Size of NFS reference cache.      */
    -	xfs_sysctl_val_t refcache_purge;/* # of entries to purge each time.  */
    -	xfs_sysctl_val_t restrict_chown;/* Root/non-root can give away files.*/
    -	xfs_sysctl_val_t sgid_inherit;	/* Inherit S_ISGID if process' GID is
    -					 * not a member of parent dir GID. */
    -	xfs_sysctl_val_t symlink_mode;	/* Link creat mode affected by umask */
    -	xfs_sysctl_val_t panic_mask;	/* bitmask to cause panic on errors. */
    -	xfs_sysctl_val_t error_level;	/* Degree of reporting for problems  */
    -	xfs_sysctl_val_t syncd_timer;	/* Interval between xfssyncd wakeups */
    -	xfs_sysctl_val_t stats_clear;	/* Reset all XFS statistics to zero. */
    -	xfs_sysctl_val_t probe_dmapi;	/* probe for DMAPI module on mount. */
    -	xfs_sysctl_val_t probe_ioops;	/* probe for an IO module on mount. */
    -	xfs_sysctl_val_t probe_quota;	/* probe for quota module on mount. */
    -	xfs_sysctl_val_t inherit_sync;	/* Inherit the "sync" inode flag. */
    -	xfs_sysctl_val_t inherit_nodump;/* Inherit the "nodump" inode flag. */
    -	xfs_sysctl_val_t inherit_noatim;/* Inherit the "noatime" inode flag. */
    -	xfs_sysctl_val_t xfs_buf_timer;	/* Interval between xfsbufd wakeups. */
    -	xfs_sysctl_val_t xfs_buf_age;	/* Metadata buffer age before flush. */
    -	xfs_sysctl_val_t inherit_nosym;	/* Inherit the "nosymlinks" flag. */
    -	xfs_sysctl_val_t rotorstep;	/* inode32 AG rotoring control knob */
    -} xfs_param_t;
    -
    -/*
    - * xfs_error_level:
    - *
    - * How much error reporting will be done when internal problems are
    - * encountered.  These problems normally return an EFSCORRUPTED to their
    - * caller, with no other information reported.
    - *
    - * 0	No error reports
    - * 1	Report EFSCORRUPTED errors that will cause a filesystem shutdown
    - * 5	Report all EFSCORRUPTED errors (all of the above errors, plus any
    - *	additional errors that are known to not cause shutdowns)
    - *
    - * xfs_panic_mask bit 0x8 turns the error reports into panics
    - */
    -
    -enum {
    -	/* XFS_REFCACHE_SIZE = 1 */
    -	/* XFS_REFCACHE_PURGE = 2 */
    -	XFS_RESTRICT_CHOWN = 3,
    -	XFS_SGID_INHERIT = 4,
    -	XFS_SYMLINK_MODE = 5,
    -	XFS_PANIC_MASK = 6,
    -	XFS_ERRLEVEL = 7,
    -	XFS_SYNCD_TIMER = 8,
    -	XFS_PROBE_DMAPI = 9,
    -	XFS_PROBE_IOOPS = 10,
    -	XFS_PROBE_QUOTA = 11,
    -	XFS_STATS_CLEAR = 12,
    -	XFS_INHERIT_SYNC = 13,
    -	XFS_INHERIT_NODUMP = 14,
    -	XFS_INHERIT_NOATIME = 15,
    -	XFS_BUF_TIMER = 16,
    -	XFS_BUF_AGE = 17,
    -	/* XFS_IO_BYPASS = 18 */
    -	XFS_INHERIT_NOSYM = 19,
    -	XFS_ROTORSTEP = 20,
    -};
    -
    -extern xfs_param_t	xfs_params;
    -
    -#ifdef CONFIG_SYSCTL
    -extern void xfs_sysctl_register(void);
    -extern void xfs_sysctl_unregister(void);
    -#else
    -# define xfs_sysctl_register()		do { } while (0)
    -# define xfs_sysctl_unregister()	do { } while (0)
    -#endif /* CONFIG_SYSCTL */
    -
    -#endif /* __XFS_SYSCTL_H__ */
    diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_version.h b/sys/gnu/fs/xfs/FreeBSD/xfs_version.h
    deleted file mode 100644
    index 96f96394417..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/xfs_version.h
    +++ /dev/null
    @@ -1,44 +0,0 @@
    -/*
    - * Copyright (c) 2001-2002 Silicon Graphics, Inc.  All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or modify it
    - * under the terms of version 2 of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful, but
    - * WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    - *
    - * Further, this software is distributed without any warranty that it is
    - * free of the rightful claim of any third person regarding infringement
    - * or the like.	 Any license provided herein, whether implied or
    - * otherwise, applies only to this software file.  Patent licenses, if
    - * any, provided herein do not apply to combinations of this program with
    - * other software, or any other product whatsoever.
    - *
    - * You should have received a copy of the GNU General Public License along
    - * with this program; if not, write the Free Software Foundation, Inc., 59
    - * Temple Place - Suite 330, Boston MA 02111-1307, USA.
    - *
    - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
    - * Mountain View, CA  94043, or:
    - *
    - * http://www.sgi.com
    - *
    - * For further information regarding this notice, see:
    - *
    - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
    - */
    -
    -/*
    - * Dummy file that can contain a timestamp to put into the
    - * XFS init string, to help users keep track of what they're
    - * running
    - */
    -
    -#ifndef __XFS_VERSION_H__
    -#define __XFS_VERSION_H__
    -
    -#define XFS_VERSION_STRING "SGI XFS"
    -
    -#endif /* __XFS_VERSION_H__ */
    diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_vfs.c b/sys/gnu/fs/xfs/FreeBSD/xfs_vfs.c
    deleted file mode 100644
    index ee405b5d4da..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/xfs_vfs.c
    +++ /dev/null
    @@ -1,356 +0,0 @@
    -/*
    - * Copyright (c) 2000-2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_inum.h"
    -#include "xfs_log.h"
    -#include "xfs_clnt.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_imap.h"
    -#include "xfs_alloc.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_quota.h"
    -
    -#include "xfs_mountops.h"
    -
    -int
    -xvfs_mount(
    -	struct bhv_desc		*bdp,
    -	struct xfs_mount_args	*args,
    -	struct cred		*cr)
    -{
    -	struct bhv_desc		*next = bdp;
    -
    -	ASSERT(next);
    -	while (! (bhvtovfsops(next))->xvfs_mount)
    -		next = BHV_NEXT(next);
    -	return ((*bhvtovfsops(next)->xvfs_mount)(next, args, cr));
    -}
    -
    -int
    -xvfs_parseargs(
    -	struct bhv_desc		*bdp,
    -	char			*s,
    -	struct xfs_mount_args	*args,
    -	int			f)
    -{
    -	struct bhv_desc		*next = bdp;
    -
    -	ASSERT(next);
    -	while (! (bhvtovfsops(next))->xvfs_parseargs)
    -		next = BHV_NEXT(next);
    -	return ((*bhvtovfsops(next)->xvfs_parseargs)(next, s, args, f));
    -}
    -
    -int
    -xvfs_showargs(
    -	struct bhv_desc		*bdp,
    -	struct sbuf		*m)
    -{
    -	struct bhv_desc		*next = bdp;
    -
    -	ASSERT(next);
    -	while (! (bhvtovfsops(next))->xvfs_showargs)
    -		next = BHV_NEXT(next);
    -	return ((*bhvtovfsops(next)->xvfs_showargs)(next, m));
    -}
    -
    -int
    -xvfs_unmount(
    -	struct bhv_desc		*bdp,
    -	int			fl,
    -	struct cred		*cr)
    -{
    -	struct bhv_desc		*next = bdp;
    -
    -	ASSERT(next);
    -	while (! (bhvtovfsops(next))->xvfs_unmount)
    -		next = BHV_NEXT(next);
    -	return ((*bhvtovfsops(next)->xvfs_unmount)(next, fl, cr));
    -}
    -
    -int
    -xvfs_mntupdate(
    -	struct bhv_desc		*bdp,
    -	int			*fl,
    -	struct xfs_mount_args	*args)
    -{
    -	struct bhv_desc		*next = bdp;
    -
    -	ASSERT(next);
    -	while (! (bhvtovfsops(next))->xvfs_mntupdate)
    -		next = BHV_NEXT(next);
    -	return ((*bhvtovfsops(next)->xvfs_mntupdate)(next, fl, args));
    -}
    -
    -int
    -xvfs_root(
    -	struct bhv_desc		*bdp,
    -	struct xfs_vnode	**vpp)
    -{
    -	struct bhv_desc		*next = bdp;
    -
    -	ASSERT(next);
    -	while (! (bhvtovfsops(next))->xvfs_root)
    -		next = BHV_NEXT(next);
    -	return ((*bhvtovfsops(next)->xvfs_root)(next, vpp));
    -}
    -
    -int
    -xvfs_statvfs(
    -	struct bhv_desc		*bdp,
    -	struct statfs		*sp,
    -	struct xfs_vnode	*vp)
    -{
    -	struct bhv_desc		*next = bdp;
    -
    -	ASSERT(next);
    -	while (! (bhvtovfsops(next))->xvfs_statvfs)
    -		next = BHV_NEXT(next);
    -	return ((*bhvtovfsops(next)->xvfs_statvfs)(next, sp, vp));
    -}
    -
    -int
    -xvfs_sync(
    -	struct bhv_desc		*bdp,
    -	int			fl,
    -	struct cred		*cr)
    -{
    -	struct bhv_desc		*next = bdp;
    -
    -	ASSERT(next);
    -	while (! (bhvtovfsops(next))->xvfs_sync)
    -		next = BHV_NEXT(next);
    -	return ((*bhvtovfsops(next)->xvfs_sync)(next, fl, cr));
    -}
    -
    -int
    -xvfs_vget(
    -	struct bhv_desc		*bdp,
    -	struct xfs_vnode	**vpp,
    -	struct fid		*fidp)
    -{
    -	struct bhv_desc		*next = bdp;
    -
    -	ASSERT(next);
    -	while (! (bhvtovfsops(next))->xvfs_vget)
    -		next = BHV_NEXT(next);
    -	return ((*bhvtovfsops(next)->xvfs_vget)(next, vpp, fidp));
    -}
    -
    -int
    -xvfs_dmapiops(
    -	struct bhv_desc		*bdp,
    -	caddr_t			addr)
    -{
    -	struct bhv_desc		*next = bdp;
    -
    -	ASSERT(next);
    -	while (! (bhvtovfsops(next))->xvfs_dmapiops)
    -		next = BHV_NEXT(next);
    -	return ((*bhvtovfsops(next)->xvfs_dmapiops)(next, addr));
    -}
    -
    -int
    -xvfs_quotactl(
    -	struct bhv_desc		*bdp,
    -	int			cmd,
    -	int			id,
    -	caddr_t			addr)
    -{
    -	struct bhv_desc		*next = bdp;
    -
    -	ASSERT(next);
    -	while (! (bhvtovfsops(next))->xvfs_quotactl)
    -		next = BHV_NEXT(next);
    -	return ((*bhvtovfsops(next)->xvfs_quotactl)(next, cmd, id, addr));
    -}
    -
    -struct inode *
    -xvfs_get_inode(
    -	struct bhv_desc		*bdp,
    -	xfs_ino_t		ino,
    -	int			fl)
    -{
    -	struct bhv_desc		*next = bdp;
    -
    -	while (! (bhvtovfsops(next))->xvfs_get_inode)
    -		next = BHV_NEXTNULL(next);
    -	return ((*bhvtovfsops(next)->xvfs_get_inode)(next, ino, fl));
    -}
    -
    -void
    -xvfs_init_vnode(
    -	struct bhv_desc		*bdp,
    -	struct xfs_vnode	*vp,
    -	struct bhv_desc		*bp,
    -	int			unlock)
    -{
    -	struct bhv_desc		*next = bdp;
    -
    -	ASSERT(next);
    -	while (! (bhvtovfsops(next))->xvfs_init_vnode)
    -		next = BHV_NEXT(next);
    -	((*bhvtovfsops(next)->xvfs_init_vnode)(next, vp, bp, unlock));
    -}
    -
    -void
    -xvfs_force_shutdown(
    -	struct bhv_desc		*bdp,
    -	int			fl,
    -	char			*file,
    -	int			line)
    -{
    -	struct bhv_desc		*next = bdp;
    -
    -	ASSERT(next);
    -	while (! (bhvtovfsops(next))->xvfs_force_shutdown)
    -		next = BHV_NEXT(next);
    -	((*bhvtovfsops(next)->xvfs_force_shutdown)(next, fl, file, line));
    -}
    -
    -xfs_vfs_t *
    -vfs_allocate(struct mount *mp)
    -{
    -	struct xfs_vfs	 *vfsp;
    -	struct xfsmount  *xmp;
    -
    -	xmp  = kmem_zalloc(sizeof(*xmp), KM_SLEEP);
    -	vfsp = XFSTOVFS(xmp);
    -
    -	bhv_head_init(VFS_BHVHEAD(vfsp), "vfs");
    -
    -	xmp->m_mp = mp;
    -	mp->mnt_data = xmp;
    -	vfsp->vfs_mp = mp;
    -
    -	return vfsp;
    -}
    -
    -void
    -vfs_deallocate(
    -	struct xfs_vfs		*vfsp)
    -{
    -	struct xfsmount *xmp;
    -
    -	bhv_head_destroy(VFS_BHVHEAD(vfsp));
    -
    -	xmp = VFSTOXFS(vfsp);
    -	kmem_free(xmp, sizeof(*xmp));
    -}
    -
    -/*
    - * Allocate and initialize a new XFS mount structure
    - */
    -struct xfsmount *
    -xfsmount_allocate(struct mount *mp)
    -{
    -	xfs_vfs_t	*vfsp;
    -
    -	vfsp = vfs_allocate(mp);
    -
    -	ASSERT(vfsp);
    -
    -	if (mp->mnt_flag & MNT_RDONLY)
    -		vfsp->vfs_flag |= VFS_RDONLY;
    -
    -	bhv_insert_all_vfsops(vfsp);
    -	return (VFSTOXFS(vfsp));
    -}
    -
    -void
    -xfsmount_deallocate(struct xfsmount *xmp)
    -{
    -	xfs_vfs_t	*vfsp;
    -
    -	vfsp = XFSTOVFS(xmp);
    -	bhv_remove_all_vfsops(vfsp, 1);
    -	vfs_deallocate(vfsp);
    -}
    -
    -
    -void
    -vfs_insertops(
    -	struct xfs_vfs		*vfsp,
    -	struct bhv_vfsops	*vfsops)
    -{
    -	struct bhv_desc		*bdp;
    -
    -	bdp = kmem_alloc(sizeof(struct bhv_desc), KM_SLEEP);
    -	bhv_desc_init(bdp, NULL, vfsp, vfsops);
    -	bhv_insert(&vfsp->vfs_bh, bdp);
    -}
    -
    -void
    -vfs_insertbhv(
    -	struct xfs_vfs		*vfsp,
    -	struct bhv_desc		*bdp,
    -	struct xvfsops		*vfsops,
    -	void			*mount)
    -{
    -	bhv_desc_init(bdp, mount, vfsp, vfsops);
    -	bhv_insert_initial(&vfsp->vfs_bh, bdp);
    -}
    -
    -void
    -bhv_remove_vfsops(
    -	struct xfs_vfs		*vfsp,
    -	int			pos)
    -{
    -	struct bhv_desc		*bhv;
    -
    -	bhv = bhv_lookup_range(&vfsp->vfs_bh, pos, pos);
    -	if (bhv) {
    -		bhv_remove(&vfsp->vfs_bh, bhv);
    -		kmem_free(bhv, sizeof(*bhv));
    -	}
    -}
    -
    -void
    -bhv_remove_all_vfsops(
    -	struct xfs_vfs		*vfsp,
    -	int			freebase)
    -{
    -	struct xfs_mount	*mp;
    -
    -	bhv_remove_vfsops(vfsp, VFS_POSITION_QM);
    -	bhv_remove_vfsops(vfsp, VFS_POSITION_DM);
    -	bhv_remove_vfsops(vfsp, VFS_POSITION_IO);
    -	if (!freebase)
    -		return;
    -	mp = XFS_BHVTOM(bhv_lookup(VFS_BHVHEAD(vfsp), &xfs_vfsops));
    -	VFS_REMOVEBHV(vfsp, &mp->m_bhv);
    -	xfs_mount_free(mp, 0);
    -}
    -
    -void
    -bhv_insert_all_vfsops(
    -	struct xfs_vfs		*vfsp)
    -{
    -	struct xfs_mount	*mp;
    -
    -	mp = xfs_mount_init();
    -	vfs_insertbhv(vfsp, &mp->m_bhv, &xfs_vfsops, mp);
    -        vfs_insertdmapi(vfsp);
    -        vfs_insertquota(vfsp);
    -}
    diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_vfs.h b/sys/gnu/fs/xfs/FreeBSD/xfs_vfs.h
    deleted file mode 100644
    index ada484997c4..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/xfs_vfs.h
    +++ /dev/null
    @@ -1,232 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or modify it
    - * under the terms of version 2 of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful, but
    - * WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    - *
    - * Further, this software is distributed without any warranty that it is
    - * free of the rightful claim of any third person regarding infringement
    - * or the like.  Any license provided herein, whether implied or
    - * otherwise, applies only to this software file.  Patent licenses, if
    - * any, provided herein do not apply to combinations of this program with
    - * other software, or any other product whatsoever.
    - *
    - * You should have received a copy of the GNU General Public License along
    - * with this program; if not, write the Free Software Foundation, Inc., 59
    - * Temple Place - Suite 330, Boston MA 02111-1307, USA.
    - *
    - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
    - * Mountain View, CA  94043, or:
    - *
    - * http://www.sgi.com
    - *
    - * For further information regarding this notice, see:
    - *
    - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
    - */
    -#ifndef __XFS_VFS_H__
    -#define __XFS_VFS_H__
    -
    -#include 
    -#include "xfs_fs.h"
    -
    -struct fid;
    -struct cred;
    -struct xfs_vnode;
    -struct statfs;
    -struct sbuf;
    -struct xfs_mount_args;
    -struct mount;
    -
    -typedef struct statfs xfs_statfs_t;
    -
    -typedef struct xfs_vfs {
    -	u_int			vfs_flag;	/* flags */
    -	xfs_fsid_t		vfs_fsid;	/* file system ID */
    -	xfs_fsid_t		*vfs_altfsid;	/* An ID fixed for life of FS */
    -	bhv_head_t		vfs_bh;		/* head of vfs behavior chain */
    -	struct mount		*vfs_mp;	/* FreeBSD mount struct */
    -} xfs_vfs_t;
    -
    -#define	MNTTOXVFS(mp)		((struct xfs_vfs*)(mp)->mnt_data)
    -#define	XVFSTOMNT(vfs)		((vfs)->vfs_mp)
    -
    -#define vfs_fbhv		vfs_bh.bh_first	/* 1st on vfs behavior chain */
    -
    -#define bhvtovfs(bdp)		( (struct xfs_vfs *)BHV_VOBJ(bdp) )
    -#define bhvtovfsops(bdp)	( (struct xvfsops *)BHV_OPS(bdp) )
    -#define VFS_BHVHEAD(vfs)	( &(vfs)->vfs_bh )
    -#define VFS_REMOVEBHV(vfs, bdp)	( bhv_remove(VFS_BHVHEAD(vfs), bdp) )
    -
    -#define VFS_POSITION_BASE	BHV_POSITION_BASE	/* chain bottom */
    -#define VFS_POSITION_TOP	BHV_POSITION_TOP	/* chain top */
    -#define VFS_POSITION_INVALID	BHV_POSITION_INVALID	/* invalid pos. num */
    -
    -typedef enum {
    -	VFS_BHV_UNKNOWN,	/* not specified */
    -	VFS_BHV_XFS,		/* xfs */
    -	VFS_BHV_DM,		/* data migration */
    -	VFS_BHV_QM,		/* quota manager */
    -	VFS_BHV_IO,		/* IO path */
    -	VFS_BHV_END		/* housekeeping end-of-range */
    -} vfs_bhv_t;
    -
    -#define VFS_POSITION_XFS	(BHV_POSITION_BASE)
    -#define VFS_POSITION_DM		(VFS_POSITION_BASE+10)
    -#define VFS_POSITION_QM		(VFS_POSITION_BASE+20)
    -#define VFS_POSITION_IO		(VFS_POSITION_BASE+30)
    -
    -#define VFS_RDONLY		0x0001	/* read-only vfs */
    -#define VFS_GRPID		0x0002	/* group-ID assigned from directory */
    -#define VFS_DMI			0x0004	/* filesystem has the DMI enabled */
    -#define VFS_32BITINODES		0x0008	/* do not use inums above 32 bits */
    -#define VFS_END			0x0008	/* max flag */
    -
    -#define SYNC_ATTR		0x0001	/* sync attributes */
    -#define SYNC_CLOSE		0x0002	/* close file system down */
    -#define SYNC_DELWRI		0x0004	/* look at delayed writes */
    -#define SYNC_WAIT		0x0008	/* wait for i/o to complete */
    -#define SYNC_BDFLUSH		0x0010	/* BDFLUSH is calling -- don't block */
    -#define SYNC_FSDATA		0x0020	/* flush fs data (e.g. superblocks) */
    -#define SYNC_REFCACHE		0x0040  /* prune some of the nfs ref cache */
    -#define SYNC_REMOUNT		0x0080  /* remount readonly, no dummy LRs */
    -#define SYNC_QUIESCE		0x0100  /* quiesce filesystem for a snapshot */
    -
    -#define IGET_NOALLOC		0x0001	/* vfs_get_inode may return NULL */
    -
    -typedef int	(*xvfs_mount_t)(bhv_desc_t *,
    -				struct xfs_mount_args *, struct cred *);
    -typedef int	(*xvfs_parseargs_t)(bhv_desc_t *, char *,
    -				struct xfs_mount_args *, int);
    -typedef	int	(*xvfs_showargs_t)(bhv_desc_t *, struct sbuf *);
    -typedef int	(*xvfs_unmount_t)(bhv_desc_t *, int, struct cred *);
    -typedef int	(*xvfs_mntupdate_t)(bhv_desc_t *, int *,
    -				struct xfs_mount_args *);
    -typedef int	(*xvfs_root_t)(bhv_desc_t *, struct xfs_vnode **);
    -typedef int	(*xvfs_statvfs_t)(bhv_desc_t *, xfs_statfs_t *, struct xfs_vnode *);
    -typedef int	(*xvfs_sync_t)(bhv_desc_t *, int, struct cred *);
    -typedef int	(*xvfs_vget_t)(bhv_desc_t *, struct xfs_vnode **, struct fid *);
    -typedef int	(*xvfs_dmapiops_t)(bhv_desc_t *, caddr_t);
    -typedef int	(*xvfs_quotactl_t)(bhv_desc_t *, int, int, caddr_t);
    -typedef void	(*xvfs_init_vnode_t)(bhv_desc_t *,
    -				struct xfs_vnode *, bhv_desc_t *, int);
    -typedef void	(*xvfs_force_shutdown_t)(bhv_desc_t *, int, char *, int);
    -typedef	struct inode * (*xvfs_get_inode_t)(bhv_desc_t *, xfs_ino_t, int);
    -typedef void	(*xvfs_freeze_t)(bhv_desc_t *);
    -
    -typedef struct xvfsops {
    -	bhv_position_t		xvfs_position;	/* behavior chain position */
    -	xvfs_mount_t		xvfs_mount;	/* mount file system */
    -	xvfs_parseargs_t	xvfs_parseargs;	/* parse mount options */
    -	xvfs_showargs_t		xvfs_showargs;	/* unparse mount options */
    -	xvfs_unmount_t		xvfs_unmount;	/* unmount file system */
    -	xvfs_mntupdate_t	xvfs_mntupdate;	/* update file system options */
    -	xvfs_root_t		xvfs_root;	/* get root vnode */
    -	xvfs_statvfs_t		xvfs_statvfs;	/* file system statistics */
    -	xvfs_sync_t		xvfs_sync;	/* flush files */
    -	xvfs_vget_t		xvfs_vget;	/* get vnode from fid */
    -	xvfs_dmapiops_t		xvfs_dmapiops;	/* data migration */
    -	xvfs_quotactl_t		xvfs_quotactl;	/* disk quota */
    -	xvfs_get_inode_t	xvfs_get_inode;	/* bhv specific iget */
    -	xvfs_init_vnode_t	xvfs_init_vnode;	/* initialize a new vnode */
    -	xvfs_force_shutdown_t	xvfs_force_shutdown;	/* crash and burn */
    -	xvfs_freeze_t		xvfs_freeze;	/* freeze fs for snapshot */
    -} xvfsops_t;
    -
    -/*
    - * VFS's.  Operates on vfs structure pointers (starts at bhv head).
    - */
    -#define VHEAD(v)			((v)->vfs_fbhv)
    -#define XVFS_MOUNT(v, ma,cr, rv)	((rv) = xvfs_mount(VHEAD(v), ma,cr))
    -#define XVFS_PARSEARGS(v, o,ma,f, rv)	((rv) = xvfs_parseargs(VHEAD(v), o,ma,f))
    -#define XVFS_SHOWARGS(v, m, rv)		((rv) = xvfs_showargs(VHEAD(v), m))
    -#define XVFS_UNMOUNT(v, f, cr, rv)	((rv) = xvfs_unmount(VHEAD(v), f,cr))
    -#define XVFS_MNTUPDATE(v, fl, args, rv)	((rv) = xvfs_mntupdate(VHEAD(v), fl, args))
    -#define XVFS_ROOT(v, vpp, rv)		((rv) = xvfs_root(VHEAD(v), vpp))
    -#define XVFS_STATVFS(v, sp,vp, rv)	((rv) = xvfs_statvfs(VHEAD(v), sp,vp))
    -#define XVFS_SYNC(v, flag,cr, rv)	((rv) = xvfs_sync(VHEAD(v), flag,cr))
    -#define XVFS_VGET(v, vpp,fidp, rv)	((rv) = xvfs_vget(VHEAD(v), vpp,fidp))
    -#define XVFS_DMAPIOPS(v, p, rv)		((rv) = xvfs_dmapiops(VHEAD(v), p))
    -#define XVFS_QUOTACTL(v, c,id,p, rv)	((rv) = xvfs_quotactl(VHEAD(v), c,id,p))
    -#define XVFS_GET_INODE(v, ino, fl)	( xvfs_get_inode(VHEAD(v), ino,fl) )
    -#define XVFS_INIT_VNODE(v, vp,b,ul)	( xvfs_init_vnode(VHEAD(v), vp,b,ul) )
    -#define XVFS_FORCE_SHUTDOWN(v, fl,f,l)	( xvfs_force_shutdown(VHEAD(v), fl,f,l) )
    -
    -/*
    - * PVFS's.  Operates on behavior descriptor pointers.
    - */
    -#define PVFS_MOUNT(b, ma,cr, rv)	((rv) = xvfs_mount(b, ma,cr))
    -#define PVFS_PARSEARGS(b, o,ma,f, rv)	((rv) = xvfs_parseargs(b, o,ma,f))
    -#define PVFS_SHOWARGS(b, m, rv)		((rv) = xvfs_showargs(b, m))
    -#define PVFS_UNMOUNT(b, f,cr, rv)	((rv) = xvfs_unmount(b, f,cr))
    -#define PVFS_MNTUPDATE(b, fl, args, rv)	((rv) = xvfs_mntupdate(b, fl, args))
    -#define PVFS_ROOT(b, vpp, rv)		((rv) = xvfs_root(b, vpp))
    -#define PVFS_STATVFS(b, sp,vp, rv)	((rv) = xvfs_statvfs(b, sp,vp))
    -#define PVFS_SYNC(b, flag,cr, rv)	((rv) = xvfs_sync(b, flag,cr))
    -#define PVFS_VGET(b, vpp,fidp, rv)	((rv) = xvfs_vget(b, vpp,fidp))
    -#define PVFS_DMAPIOPS(b, p, rv)		((rv) = xvfs_dmapiops(b, p))
    -#define PVFS_QUOTACTL(b, c,id,p, rv)	((rv) = xvfs_quotactl(b, c,id,p))
    -#define PVFS_GET_INODE(b, ino,fl)	( xvfs_get_inode(b, ino,fl) )
    -#define PVFS_INIT_VNODE(b, vp,b2,ul)	( xvfs_init_vnode(b, vp,b2,ul) )
    -#define PVFS_FORCE_SHUTDOWN(b, fl,f,l)	( xvfs_force_shutdown(b, fl,f,l) )
    -
    -extern int xvfs_mount(bhv_desc_t *, struct xfs_mount_args *, struct cred *);
    -extern int xvfs_parseargs(bhv_desc_t *, char *, struct xfs_mount_args *, int);
    -extern int xvfs_showargs(bhv_desc_t *, struct sbuf *);
    -extern int xvfs_unmount(bhv_desc_t *, int, struct cred *);
    -extern int xvfs_mntupdate(bhv_desc_t *, int *, struct xfs_mount_args *);
    -extern int xvfs_root(bhv_desc_t *, struct xfs_vnode **);
    -extern int xvfs_statvfs(bhv_desc_t *, xfs_statfs_t *, struct xfs_vnode *);
    -extern int xvfs_sync(bhv_desc_t *, int, struct cred *);
    -extern int xvfs_vget(bhv_desc_t *, struct xfs_vnode **, struct fid *);
    -extern int xvfs_dmapiops(bhv_desc_t *, caddr_t);
    -extern int xvfs_quotactl(bhv_desc_t *, int, int, caddr_t);
    -extern struct inode *xvfs_get_inode(bhv_desc_t *, xfs_ino_t, int);
    -extern void xvfs_init_vnode(bhv_desc_t *, struct xfs_vnode *, bhv_desc_t *, int);
    -extern void xvfs_force_shutdown(bhv_desc_t *, int, char *, int);
    -
    -#define XFS_DMOPS		"xfs_dm_operations"	/* Data Migration */
    -#define XFS_QMOPS		"xfs_qm_operations"	/* Quota Manager  */
    -#define XFS_IOOPS		"xfs_io_operations"	/* I/O subsystem  */
    -#define XFS_DM_MODULE		"xfs_dmapi"
    -#define XFS_QM_MODULE		"xfs_quota"
    -#define XFS_IO_MODULE		"xfs_ioops"
    -
    -typedef struct bhv_vfsops {
    -	struct xvfsops		bhv_common;
    -	void *			bhv_custom;
    -} bhv_vfsops_t;
    -
    -typedef struct bhv_module {
    -	bhv_desc_t		bm_desc;
    -	const char *		bm_name;
    -	bhv_vfsops_t *		bm_ops;
    -} bhv_module_t;
    -
    -#define vfs_bhv_lookup(v, id)	( bhv_lookup_range(&(v)->vfs_bh, (id), (id)) )
    -#define vfs_bhv_custom(b)	( ((bhv_vfsops_t *)BHV_OPS(b))->bhv_custom )
    -#define vfs_bhv_set_custom(b,o)	( (b)->bhv_custom = (void *)(o))
    -#define vfs_bhv_clr_custom(b)	( (b)->bhv_custom = NULL )
    -
    -extern xfs_vfs_t *vfs_allocate(struct mount *);
    -extern void vfs_deallocate(xfs_vfs_t *);
    -extern void vfs_insertops(xfs_vfs_t *, bhv_vfsops_t *);
    -extern void vfs_insertbhv(xfs_vfs_t *, bhv_desc_t *, xvfsops_t *, void *);
    -
    -#define bhv_lookup_module(n,m)	( (m) ? \
    -				inter_module_get_request(n, m) : \
    -				inter_module_get(n) )
    -#define bhv_remove_module(n)	inter_module_put(n)
    -#define bhv_module_init(n,m,op)	inter_module_register(n,m,op)
    -#define bhv_module_exit(n)	inter_module_unregister(n)
    -
    -extern void bhv_insert_all_vfsops(struct xfs_vfs *);
    -extern void bhv_remove_all_vfsops(struct xfs_vfs *, int);
    -extern void bhv_remove_vfsops(struct xfs_vfs *, int);
    -
    -#endif	/* __XFS_VFS_H__ */
    diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_vnode.c b/sys/gnu/fs/xfs/FreeBSD/xfs_vnode.c
    deleted file mode 100644
    index 3b3f3e5b491..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/xfs_vnode.c
    +++ /dev/null
    @@ -1,272 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or modify it
    - * under the terms of version 2 of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful, but
    - * WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    - *
    - * Further, this software is distributed without any warranty that it is
    - * free of the rightful claim of any third person regarding infringement
    - * or the like.  Any license provided herein, whether implied or
    - * otherwise, applies only to this software file.  Patent licenses, if
    - * any, provided herein do not apply to combinations of this program with
    - * other software, or any other product whatsoever.
    - *
    - * You should have received a copy of the GNU General Public License along
    - * with this program; if not, write the Free Software Foundation, Inc., 59
    - * Temple Place - Suite 330, Boston MA 02111-1307, USA.
    - *
    - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
    - * Mountain View, CA  94043, or:
    - *
    - * http://www.sgi.com
    - *
    - * For further information regarding this notice, see:
    - *
    - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
    - */
    -
    -#include "xfs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_inum.h"
    -#include "xfs_log.h"
    -#include "xfs_trans.h"
    -#include "xfs_trans_priv.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_btree.h"
    -#include "xfs_imap.h"
    -#include "xfs_alloc.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_ialloc.h"
    -#include "xfs_inode.h"
    -#include "xfs_inode_item.h"
    -
    -void
    -vn_init(void)
    -{
    -}
    -
    -void
    -vn_iowait(
    -	  struct xfs_vnode *vp)
    -{
    -	printf("vn_iowait doing nothing on FreeBSD?\n");
    -}
    -
    -struct xfs_vnode *
    -vn_initialize(
    -	xfs_vnode_t	*vp)
    -{
    -	XFS_STATS_INC(vn_active);
    -	XFS_STATS_INC(vn_alloc);
    -
    -	/* Initialize the first behavior and the behavior chain head. */
    -	vn_bhv_head_init(VN_BHV_HEAD(vp), "vnode");
    -
    -#ifdef	CONFIG_XFS_VNODE_TRACING
    -	vp->v_trace = ktrace_alloc(VNODE_TRACE_SIZE, KM_SLEEP);
    -#endif	/* CONFIG_XFS_VNODE_TRACING */
    -
    -	vn_trace_exit(vp, "vn_initialize", (inst_t *)__return_address);
    -	return vp;
    -}
    -
    -/*
    - * Get a reference on a vnode. Need to drop vnode reference
    - * to accomodate for vhold by VMAP regardless of whether or
    - * not we were able to successfully grab the vnode.
    - */
    -xfs_vnode_t *
    -vn_get(
    -	struct xfs_vnode	*xfs_vp,
    -	vmap_t			*vmap)
    -{
    -	struct vnode *vp;
    -	int error;
    -
    -	XFS_STATS_INC(vn_get);
    -
    -	vp = vmap->v_vp;
    -
    -	error = vget(vp, LK_EXCLUSIVE, curthread);
    -	vdrop(vp);
    -	if (error)
    -		return (NULL);
    -
    -	/*
    -	 * Drop the vnode returned by vget here.
    -	 * VOP_RECLAIM(9) should block on internal XFS locks so that
    -	 * the reclaiming scheme still remains consistent even if the
    -	 * vp is not locked.
    -	 */
    -	VOP_UNLOCK(vp, 0);
    -	if (vp->v_data != xfs_vp) {
    -		vput(vp);
    -		return (NULL);
    -	}
    -
    -	vn_trace_exit(vp, "vn_get", (inst_t *)__return_address);
    -	return xfs_vp;
    -}
    -
    -/*
    - * purge a vnode from the cache
    - * At this point the vnode is guaranteed to have no references (vn_count == 0)
    - * The caller has to make sure that there are no ways someone could
    - * get a handle (via vn_get) on the vnode (usually done via a mount/vfs lock).
    - */
    -void
    -vn_purge(struct xfs_vnode        *xfs_vp)
    -{
    -        struct vnode *vp;
    -
    -        vn_trace_entry(vp, "vn_purge", (inst_t *)__return_address);
    -
    -        vp = xfs_vp->v_vnode;
    -
    -        vn_lock(vp, LK_EXCLUSIVE);
    -	if (vp->v_holdcnt == 0)
    -		vhold(vp);
    -	vgone(vp);
    -        VOP_UNLOCK(vp, 0);
    -}
    -
    -void xfs_ichgtime(
    -	xfs_inode_t	*ip,
    -	int		flags)
    -{
    -	timespec_t  tv;
    -	
    -	vfs_timestamp(&tv);
    -	if (flags & XFS_ICHGTIME_MOD) {
    -		ip->i_d.di_mtime.t_sec = (__int32_t)tv.tv_sec;
    -		ip->i_d.di_mtime.t_nsec = (__int32_t)tv.tv_nsec;
    -	}
    -	if (flags & XFS_ICHGTIME_ACC) {
    -		ip->i_d.di_atime.t_sec = (__int32_t)tv.tv_sec;
    -		ip->i_d.di_atime.t_nsec = (__int32_t)tv.tv_nsec;
    -	}
    -	if (flags & XFS_ICHGTIME_CHG) {
    -		ip->i_d.di_ctime.t_sec = (__int32_t)tv.tv_sec;
    -		ip->i_d.di_ctime.t_nsec = (__int32_t)tv.tv_nsec;
    -	}
    -	
    -//printf ("xfs_ichgtime NI\n");
    -
    -}
    -
    -
    -/*
    - * Bring the atime in the XFS inode uptodate.
    - * Used before logging the inode to disk or when the Linux inode goes away.
    - */
    -
    -/*
    - * It's unclear if we need this since this is for syncing the linux inode's atime
    - * to the xfs inode's atime.
    - * Since FreeBSD doesn't have atime in the vnode is there anything to really
    - * sync over?
    - * For now just make this a update atime call
    - */
    -
    -void
    -xfs_synchronize_atime(
    -	xfs_inode_t	*ip)
    -{
    -#if 0
    -	xfs_vnode_t	*vp;
    -#endif
    -
    -	timespec_t  tv;
    -	
    -/* vfs_timestamp looks at the system time accuracy variable */
    -	vfs_timestamp(&tv);
    -#if 0
    -	printf("xfs_synchronize_atime old (%d,%d) new (%d,%ld)\n",
    -	       ip->i_d.di_atime.t_sec,
    -	       ip->i_d.di_atime.t_nsec,
    -	       tv.tv_sec,
    -	       tv.tv_nsec);
    -#endif
    -
    -	ip->i_d.di_atime.t_sec = (__int32_t)tv.tv_sec;
    -	ip->i_d.di_atime.t_nsec = (__int32_t)tv.tv_nsec;
    -}
    -
    -#ifdef RMC
    -/*
    - * Extracting atime values in various formats
    - */
    -void vn_atime_to_bstime(struct xfs_vnode *vp, xfs_bstime_t *bs_atime)
    -{
    -	bs_atime->tv_sec = vp->v_inode.i_atime.tv_sec;
    -	bs_atime->tv_nsec = vp->v_inode.i_atime.tv_nsec;
    -	printf("vn_atime_to_bstime NI\n");
    -}
    -#endif
    -
    -
    -#ifdef	CONFIG_XFS_VNODE_TRACING
    -
    -#define KTRACE_ENTER(vp, vk, s, line, ra)			\
    -	ktrace_enter(	(vp)->v_trace,				\
    -/*  0 */		(void *)(__psint_t)(vk),		\
    -/*  1 */		(void *)(s),				\
    -/*  2 */		(void *)(__psint_t) line,		\
    -/*  3 */		(void *)(vn_count(vp)), \
    -/*  4 */		(void *)(ra),				\
    -/*  5 */		(void *)(__psunsigned_t)(vp)->v_flag,	\
    -/*  6 */		(void *)(__psint_t)smp_processor_id(),	\
    -/*  7 */		(void *)(__psint_t)(current->pid),	\
    -/*  8 */		(void *)__return_address,		\
    -/*  9 */		0, 0, 0, 0, 0, 0, 0)
    -
    -/*
    - * Vnode tracing code.
    - */
    -void
    -vn_trace_entry(xfs_vnode_t *vp, char *func, inst_t *ra)
    -{
    -	KTRACE_ENTER(vp, VNODE_KTRACE_ENTRY, func, 0, ra);
    -}
    -
    -void
    -vn_trace_exit(xfs_vnode_t *vp, char *func, inst_t *ra)
    -{
    -	KTRACE_ENTER(vp, VNODE_KTRACE_EXIT, func, 0, ra);
    -}
    -
    -void
    -vn_trace_hold(xfs_vnode_t *vp, char *file, int line, inst_t *ra)
    -{
    -	KTRACE_ENTER(vp, VNODE_KTRACE_HOLD, file, line, ra);
    -}
    -
    -void
    -vn_trace_ref(xfs_vnode_t *vp, char *file, int line, inst_t *ra)
    -{
    -	KTRACE_ENTER(vp, VNODE_KTRACE_REF, file, line, ra);
    -}
    -
    -void
    -vn_trace_rele(xfs_vnode_t *vp, char *file, int line, inst_t *ra)
    -{
    -	KTRACE_ENTER(vp, VNODE_KTRACE_RELE, file, line, ra);
    -}
    -#endif	/* CONFIG_XFS_VNODE_TRACING */
    diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_vnode.h b/sys/gnu/fs/xfs/FreeBSD/xfs_vnode.h
    deleted file mode 100644
    index 1e02bb031ab..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/xfs_vnode.h
    +++ /dev/null
    @@ -1,673 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or modify it
    - * under the terms of version 2 of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful, but
    - * WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    - *
    - * Further, this software is distributed without any warranty that it is
    - * free of the rightful claim of any third person regarding infringement
    - * or the like.  Any license provided herein, whether implied or
    - * otherwise, applies only to this software file.  Patent licenses, if
    - * any, provided herein do not apply to combinations of this program with
    - * other software, or any other product whatsoever.
    - *
    - * You should have received a copy of the GNU General Public License along
    - * with this program; if not, write the Free Software Foundation, Inc., 59
    - * Temple Place - Suite 330, Boston MA 02111-1307, USA.
    - *
    - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
    - * Mountain View, CA  94043, or:
    - *
    - * http://www.sgi.com
    - *
    - * For further information regarding this notice, see:
    - *
    - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
    - *
    - * Portions Copyright (c) 1989, 1993
    - *	The Regents of the University of California.  All rights reserved.
    - *
    - * Redistribution and use in source and binary forms, with or without
    - * modification, are permitted provided that the following conditions
    - * are met:
    - * 1. Redistributions of source code must retain the above copyright
    - *    notice, this list of conditions and the following disclaimer.
    - * 2. Redistributions in binary form must reproduce the above copyright
    - *    notice, this list of conditions and the following disclaimer in the
    - *    documentation and/or other materials provided with the distribution.
    - * 3. Neither the name of the University nor the names of its contributors
    - *    may be used to endorse or promote products derived from this software
    - *    without specific prior written permission.
    - *
    - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    - * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
    - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    - * SUCH DAMAGE.
    - */
    -#ifndef __XFS_VNODE_H__
    -#define __XFS_VNODE_H__
    -
    -#include 
    -#include 
    -
    -struct  xfs_iomap;
    -typedef struct componentname vname_t;
    -typedef bhv_head_t vn_bhv_head_t;
    -
    -/*
    - * MP locking protocols:
    - *	v_flag, v_vfsp				VN_LOCK/VN_UNLOCK
    - *	v_type					read-only or fs-dependent
    - */
    -typedef struct xfs_vnode {
    -	__u32		v_flag;			/* vnode flags (see below) */
    -	struct xfs_vfs	*v_vfsp;		/* ptr to containing VFS */
    -	xfs_ino_t	v_number;		/* in-core vnode number */
    -	vn_bhv_head_t	v_bh;			/* behavior head */
    -	struct vnode	*v_vnode;		/* FreeBSD vnode */
    -	struct xfs_inode *v_inode;		/* XFS inode */
    -#ifdef XFS_VNODE_TRACE
    -	struct ktrace	*v_trace;		/* trace header structure    */
    -#endif
    -} xfs_vnode_t;
    -
    -
    -/* vnode types */
    -#define VN_ISLNK(vp)	((vp)->v_vnode->v_type & VLNK)
    -#define VN_ISREG(vp)	((vp)->v_vnode->v_type & VREG)
    -#define VN_ISDIR(vp)	((vp)->v_vnode->v_type & VDIR)
    -#define VN_ISCHR(vp)	((vp)->v_vnode->v_type & VCHR)
    -#define VN_ISBLK(vp)	((vp)->v_vnode->v_type & VBLK)
    -#define VN_BAD(vp)	((vp)->v_vnode->v_type & VBAD)
    -
    -#define v_fbhv			v_bh.bh_first	       /* first behavior */
    -#define v_fops			v_bh.bh_first->bd_ops  /* first behavior ops */
    -
    -#define VNODE_POSITION_BASE	BHV_POSITION_BASE	/* chain bottom */
    -#define VNODE_POSITION_TOP	BHV_POSITION_TOP	/* chain top */
    -#define VNODE_POSITION_INVALID	BHV_POSITION_INVALID	/* invalid pos. num */
    -
    -typedef enum {
    -	VN_BHV_UNKNOWN,		/* not specified */
    -	VN_BHV_XFS,		/* xfs */
    -	VN_BHV_DM,		/* data migration */
    -	VN_BHV_QM,		/* quota manager */
    -	VN_BHV_IO,		/* IO path */
    -	VN_BHV_END		/* housekeeping end-of-range */
    -} vn_bhv_t;
    -
    -#define VNODE_POSITION_XFS	(VNODE_POSITION_BASE)
    -#define VNODE_POSITION_DM	(VNODE_POSITION_BASE+10)
    -#define VNODE_POSITION_QM	(VNODE_POSITION_BASE+20)
    -#define VNODE_POSITION_IO	(VNODE_POSITION_BASE+30)
    -
    -#define	VPTOXFSVP(vp) ((struct xfs_vnode *)(vp)->v_data)
    -
    -/*
    - * Macros for dealing with the behavior descriptor inside of the vnode.
    - */
    -#define BHV_TO_VNODE(bdp)	((xfs_vnode_t *)BHV_VOBJ(bdp))
    -#define BHV_TO_VNODE_NULL(bdp)	((xfs_vnode_t *)BHV_VOBJNULL(bdp))
    -
    -#define VN_BHV_HEAD(vp)			((bhv_head_t *)(&((vp)->v_bh)))
    -#define vn_bhv_head_init(bhp,name)	bhv_head_init(bhp,name)
    -#define vn_bhv_remove(bhp,bdp)		bhv_remove(bhp,bdp)
    -#define vn_bhv_lookup(bhp,ops)		bhv_lookup(bhp,ops)
    -#define vn_bhv_lookup_unlocked(bhp,ops) bhv_lookup_unlocked(bhp,ops)
    -
    -/*
    - * Vnode to Linux inode mapping.
    - */
    -#define LINVFS_GET_VP(inode)	((xfs_vnode_t *)NULL)
    -#define LINVFS_GET_IP(vp)	((xfs_inode_t *)NULL)
    -
    -/*
    - * Vnode flags.
    - */
    -#define VINACT		       0x1	/* vnode is being inactivated	*/
    -#define VRECLM		       0x2	/* vnode is being reclaimed	*/
    -#define VWAIT		       0x4	/* waiting for VINACT/VRECLM to end */
    -#define VMODIFIED	       0x8	/* XFS inode state possibly differs */
    -					/* to the Linux inode state.	*/
    -
    -/*
    - * Values for the VOP_RWLOCK and VOP_RWUNLOCK flags parameter.
    - */
    -typedef enum vrwlock {
    -	VRWLOCK_NONE,
    -	VRWLOCK_READ,
    -	VRWLOCK_WRITE,
    -	VRWLOCK_WRITE_DIRECT,
    -	VRWLOCK_TRY_READ,
    -	VRWLOCK_TRY_WRITE
    -} vrwlock_t;
    -
    -/*
    - * Return values for VOP_INACTIVE.  A return value of
    - * VN_INACTIVE_NOCACHE implies that the file system behavior
    - * has disassociated its state and bhv_desc_t from the vnode.
    - */
    -#define	VN_INACTIVE_CACHE	0
    -#define	VN_INACTIVE_NOCACHE	1
    -
    -/*
    - * Values for the cmd code given to VOP_VNODE_CHANGE.
    - */
    -typedef enum vchange {
    -	VCHANGE_FLAGS_FRLOCKS		= 0,
    -	VCHANGE_FLAGS_ENF_LOCKING	= 1,
    -	VCHANGE_FLAGS_TRUNCATED		= 2,
    -	VCHANGE_FLAGS_PAGE_DIRTY	= 3,
    -	VCHANGE_FLAGS_IOEXCL_COUNT	= 4
    -} vchange_t;
    -
    -struct file_lock;
    -struct xfs_iomap_s;
    -struct xfs_vattr;
    -struct attrlist_cursor_kern;
    -
    -typedef int	(*xfs_vop_open_t)(bhv_desc_t *, struct cred *);
    -typedef ssize_t (*xfs_vop_read_t)(bhv_desc_t *, uio_t *, int, struct cred *);
    -typedef ssize_t (*xfs_vop_write_t)(bhv_desc_t *, uio_t *, int, struct cred *);
    -typedef int	(*xfs_vop_ioctl_t)(bhv_desc_t *, struct inode *, struct file *,
    -				int, u_long, void *);
    -typedef int	(*xfs_vop_getattr_t)(bhv_desc_t *, struct xfs_vattr *, int,
    -				struct cred *);
    -typedef int	(*xfs_vop_setattr_t)(bhv_desc_t *, struct xfs_vattr *, int,
    -				struct cred *);
    -typedef int	(*xfs_vop_access_t)(bhv_desc_t *, int, struct cred *);
    -typedef int	(*xfs_vop_lookup_t)(bhv_desc_t *, vname_t *, xfs_vnode_t **,
    -				int, xfs_vnode_t *, struct cred *);
    -typedef int	(*xfs_vop_create_t)(bhv_desc_t *, vname_t *, struct xfs_vattr *,
    -				xfs_vnode_t **, struct cred *);
    -typedef int	(*xfs_vop_remove_t)(bhv_desc_t *, bhv_desc_t *, vname_t *, struct cred *);
    -typedef int	(*xfs_vop_link_t)(bhv_desc_t *, xfs_vnode_t *, vname_t *,
    -				struct cred *);
    -typedef int	(*xfs_vop_rename_t)(bhv_desc_t *, vname_t *, xfs_vnode_t *, vname_t *,
    -				struct cred *);
    -typedef int	(*xfs_vop_mkdir_t)(bhv_desc_t *, vname_t *, struct xfs_vattr *,
    -				xfs_vnode_t **, struct cred *);
    -typedef int	(*xfs_vop_rmdir_t)(bhv_desc_t *, vname_t *, struct cred *);
    -typedef int	(*xfs_vop_readdir_t)(bhv_desc_t *, struct uio *, struct cred *,
    -				int *);
    -typedef int	(*xfs_vop_symlink_t)(bhv_desc_t *, vname_t *, struct xfs_vattr *,
    -				char *, xfs_vnode_t **, struct cred *);
    -
    -typedef int	(*xfs_vop_readlink_t)(bhv_desc_t *, struct uio *, int,
    -				struct cred *);
    -typedef int	(*xfs_vop_fsync_t)(bhv_desc_t *, int, struct cred *,
    -				xfs_off_t, xfs_off_t);
    -typedef int	(*xfs_vop_inactive_t)(bhv_desc_t *, struct cred *);
    -typedef int	(*xfs_vop_fid2_t)(bhv_desc_t *, struct fid *);
    -typedef int	(*xfs_vop_release_t)(bhv_desc_t *);
    -typedef int	(*xfs_vop_rwlock_t)(bhv_desc_t *, vrwlock_t);
    -typedef void	(*xfs_vop_rwunlock_t)(bhv_desc_t *, vrwlock_t);
    -typedef	int	(*xfs_vop_frlock_t)(bhv_desc_t *, int, struct file_lock *,int,
    -				xfs_off_t, struct cred *);
    -typedef int	(*xfs_vop_bmap_t)(bhv_desc_t *, xfs_off_t, ssize_t, int,
    -				struct xfs_iomap *, int *);
    -typedef int	(*xfs_vop_reclaim_t)(bhv_desc_t *);
    -typedef int	(*xfs_vop_attr_get_t)(bhv_desc_t *, const char *, char *, int *, int,
    -				struct cred *);
    -typedef	int	(*xfs_vop_attr_set_t)(bhv_desc_t *, const char *, char *, int, int,
    -				struct cred *);
    -typedef	int	(*xfs_vop_attr_remove_t)(bhv_desc_t *, const char *, int, struct cred *);
    -typedef	int	(*xfs_vop_attr_list_t)(bhv_desc_t *, char *, int, int,
    -				struct attrlist_cursor_kern *, struct cred *);
    -typedef void	(*xfs_vop_link_removed_t)(bhv_desc_t *, xfs_vnode_t *, int);
    -typedef void	(*xfs_vop_vnode_change_t)(bhv_desc_t *, vchange_t, __psint_t);
    -typedef void	(*xfs_vop_ptossvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
    -typedef void	(*xfs_vop_pflushinvalvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
    -typedef int	(*xfs_vop_pflushvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t,
    -				uint64_t, int);
    -typedef int	(*xfs_vop_iflush_t)(bhv_desc_t *, int);
    -
    -
    -typedef struct xfs_vnodeops {
    -	bhv_position_t  vn_position;    /* position within behavior chain */
    -	xfs_vop_open_t		vop_open;
    -	xfs_vop_read_t		vop_read;
    -	xfs_vop_write_t		vop_write;
    -	xfs_vop_ioctl_t		vop_ioctl;
    -	xfs_vop_getattr_t	vop_getattr;
    -	xfs_vop_setattr_t	vop_setattr;
    -	xfs_vop_access_t	vop_access;
    -	xfs_vop_lookup_t	vop_lookup;
    -	xfs_vop_create_t	vop_create;
    -	xfs_vop_remove_t	vop_remove;
    -	xfs_vop_link_t		vop_link;
    -	xfs_vop_rename_t	vop_rename;
    -	xfs_vop_mkdir_t		vop_mkdir;
    -	xfs_vop_rmdir_t		vop_rmdir;
    -	xfs_vop_readdir_t	vop_readdir;
    -	xfs_vop_symlink_t	vop_symlink;
    -	xfs_vop_readlink_t	vop_readlink;
    -	xfs_vop_fsync_t		vop_fsync;
    -	xfs_vop_inactive_t	vop_inactive;
    -	xfs_vop_fid2_t		vop_fid2;
    -	xfs_vop_rwlock_t	vop_rwlock;
    -	xfs_vop_rwunlock_t	vop_rwunlock;
    -	xfs_vop_frlock_t	vop_frlock;
    -	xfs_vop_bmap_t		vop_bmap;
    -	xfs_vop_reclaim_t	vop_reclaim;
    -	xfs_vop_attr_get_t	vop_attr_get;
    -	xfs_vop_attr_set_t	vop_attr_set;
    -	xfs_vop_attr_remove_t	vop_attr_remove;
    -	xfs_vop_attr_list_t	vop_attr_list;
    -	xfs_vop_link_removed_t	vop_link_removed;
    -	xfs_vop_vnode_change_t	vop_vnode_change;
    -	xfs_vop_ptossvp_t	vop_tosspages;
    -	xfs_vop_pflushinvalvp_t	vop_flushinval_pages;
    -	xfs_vop_pflushvp_t	vop_flush_pages;
    -	xfs_vop_release_t	vop_release;
    -	xfs_vop_iflush_t	vop_iflush;
    -} xfs_vnodeops_t;
    -
    -/*
    - * VOP's.
    - */
    -#define _VOP_(op, vp)	(*((xfs_vnodeops_t *)(vp)->v_fops)->op)
    -
    -#define XVOP_READ(vp,uio,ioflags,cr,rv)			\
    -	rv = _VOP_(vop_read, vp)((vp)->v_fbhv,uio,ioflags,cr)
    -#define XVOP_WRITE(vp,file,uio,ioflags,cr,rv)		\
    -	rv = _VOP_(vop_write, vp)((vp)->v_fbhv,uio,ioflags,cr)
    -#define XVOP_BMAP(vp,of,sz,rw,b,n,rv)					\
    -	rv = _VOP_(vop_bmap, vp)((vp)->v_fbhv,of,sz,rw,b,n)
    -#define XVOP_OPEN(vp, cr, rv)						\
    -	rv = _VOP_(vop_open, vp)((vp)->v_fbhv, cr)
    -#define XVOP_GETATTR(vp, vap, f, cr, rv)				\
    -	rv = _VOP_(vop_getattr, vp)((vp)->v_fbhv, vap, f, cr)
    -#define	XVOP_SETATTR(vp, vap, f, cr, rv)				\
    -	rv = _VOP_(vop_setattr, vp)((vp)->v_fbhv, vap, f, cr)
    -#define	XVOP_ACCESS(vp, accmode, cr, rv)					\
    -	rv = _VOP_(vop_access, vp)((vp)->v_fbhv, accmode, cr)
    -#define	XVOP_LOOKUP(vp,d,vpp,f,rdir,cr,rv)				\
    -	rv = _VOP_(vop_lookup, vp)((vp)->v_fbhv,d,vpp,f,rdir,cr)
    -#define XVOP_CREATE(dvp,d,vap,vpp,cr,rv)					\
    -	rv = _VOP_(vop_create, dvp)((dvp)->v_fbhv,d,vap,vpp,cr)
    -#define XVOP_REMOVE(dvp,d,cr,rv)						\
    -	rv = _VOP_(vop_remove, dvp)((dvp)->v_fbhv,d,cr)
    -#define	XVOP_LINK(tdvp,fvp,d,cr,rv)					\
    -	rv = _VOP_(vop_link, tdvp)((tdvp)->v_fbhv,fvp,d,cr)
    -#define	XVOP_RENAME(fvp,fnm,tdvp,tnm,cr,rv)				\
    -	rv = _VOP_(vop_rename, fvp)((fvp)->v_fbhv,fnm,tdvp,tnm,cr)
    -#define	XVOP_MKDIR(dp,d,vap,vpp,cr,rv)					\
    -	rv = _VOP_(vop_mkdir, dp)((dp)->v_fbhv,d,vap,vpp,cr)
    -#define	XVOP_RMDIR(dp,d,cr,rv)						\
    -	rv = _VOP_(vop_rmdir, dp)((dp)->v_fbhv,d,cr)
    -#define	XVOP_READDIR(vp,uiop,cr,eofp,rv)				\
    -	rv = _VOP_(vop_readdir, vp)((vp)->v_fbhv,uiop,cr,eofp)
    -#define	XVOP_SYMLINK(dvp,d,vap,tnm,vpp,cr,rv)				\
    -	rv = _VOP_(vop_symlink, dvp) ((dvp)->v_fbhv,d,vap,tnm,vpp,cr)
    -#define	XVOP_READLINK(vp,uiop,fl,cr,rv)					\
    -	rv = _VOP_(vop_readlink, vp)((vp)->v_fbhv,uiop,fl,cr)
    -
    -#define	XVOP_FSYNC(vp,f,cr,b,e,rv)					\
    -	rv = _VOP_(vop_fsync, vp)((vp)->v_fbhv,f,cr,b,e)
    -#define XVOP_INACTIVE(vp, cr, rv)					\
    -	rv = _VOP_(vop_inactive, vp)((vp)->v_fbhv, cr)
    -#define XVOP_RELEASE(vp, rv)						\
    -	rv = _VOP_(vop_release, vp)((vp)->v_fbhv)
    -#define XVOP_FID2(vp, fidp, rv)						\
    -	rv = _VOP_(vop_fid2, vp)((vp)->v_fbhv, fidp)
    -#define XVOP_RWLOCK(vp,i)						\
    -	(void)_VOP_(vop_rwlock, vp)((vp)->v_fbhv, i)
    -#define XVOP_RWLOCK_TRY(vp,i)						\
    -	_VOP_(vop_rwlock, vp)((vp)->v_fbhv, i)
    -#define XVOP_RWUNLOCK(vp,i)						\
    -	(void)_VOP_(vop_rwunlock, vp)((vp)->v_fbhv, i)
    -#define XVOP_FRLOCK(vp,c,fl,flags,offset,fr,rv)				\
    -	rv = _VOP_(vop_frlock, vp)((vp)->v_fbhv,c,fl,flags,offset,fr)
    -#define XVOP_RECLAIM(vp, rv)						\
    -	rv = _VOP_(vop_reclaim, vp)((vp)->v_fbhv)
    -#define XVOP_ATTR_GET(vp, name, val, vallenp, fl, cred, rv)		\
    -	rv = _VOP_(vop_attr_get, vp)((vp)->v_fbhv,name,val,vallenp,fl,cred)
    -#define	XVOP_ATTR_SET(vp, name, val, vallen, fl, cred, rv)		\
    -	rv = _VOP_(vop_attr_set, vp)((vp)->v_fbhv,name,val,vallen,fl,cred)
    -#define	XVOP_ATTR_REMOVE(vp, name, flags, cred, rv)			\
    -	rv = _VOP_(vop_attr_remove, vp)((vp)->v_fbhv,name,flags,cred)
    -#define	XVOP_ATTR_LIST(vp, buf, buflen, fl, cursor, cred, rv)		\
    -	rv = _VOP_(vop_attr_list, vp)((vp)->v_fbhv,buf,buflen,fl,cursor,cred)
    -#define XVOP_LINK_REMOVED(vp, dvp, linkzero)				\
    -	(void)_VOP_(vop_link_removed, vp)((vp)->v_fbhv, dvp, linkzero)
    -#define XVOP_VNODE_CHANGE(vp, cmd, val)					\
    -	(void)_VOP_(vop_vnode_change, vp)((vp)->v_fbhv,cmd,val)
    -/*
    - * These are page cache functions that now go thru VOPs.
    - * 'last' parameter is unused and left in for IRIX compatibility
    - */
    -#define XVOP_TOSS_PAGES(vp, first, last, fiopt)				\
    -	_VOP_(vop_tosspages, vp)((vp)->v_fbhv,first, last, fiopt)
    -/*
    - * 'last' parameter is unused and left in for IRIX compatibility
    - */
    -#define XVOP_FLUSHINVAL_PAGES(vp, first, last, fiopt)			\
    -	_VOP_(vop_flushinval_pages, vp)((vp)->v_fbhv,first,last,fiopt)
    -/*
    - * 'last' parameter is unused and left in for IRIX compatibility
    - */
    -#define XVOP_FLUSH_PAGES(vp, first, last, flags, fiopt, rv)		\
    -	rv = _VOP_(vop_flush_pages, vp)((vp)->v_fbhv,first,last,flags,fiopt)
    -#define XVOP_IOCTL(vp, inode, filp, fl, cmd, arg, rv)			\
    -	rv = _VOP_(vop_ioctl, vp)((vp)->v_fbhv,inode,filp,fl,cmd,arg)
    -#define XVOP_IFLUSH(vp, flags, rv)					\
    -	rv = _VOP_(vop_iflush, vp)((vp)->v_fbhv, flags)
    -
    -/*
    - * Flags for read/write calls - select values from FreeBSD IO_ flags
    - * or non-conflicting bits.
    - */
    -#define IO_ISDIRECT	IO_DIRECT	/* bypass page cache */
    -#define IO_INVIS	0x02000		/* don't update inode timestamps */
    -/* #define IO_ISLOCKED	0x04000		don't do inode locking, strictly a CXFS thing */
    -
    -/*
    - * Flags for VOP_IFLUSH call
    - */
    -#define FLUSH_SYNC		1	/* wait for flush to complete	*/
    -#define FLUSH_INODE		2	/* flush the inode itself	*/
    -#define FLUSH_LOG		4	/* force the last log entry for
    -					 * this inode out to disk	*/
    -
    -/*
    - * Flush/Invalidate options for VOP_TOSS_PAGES, VOP_FLUSHINVAL_PAGES and
    - *	VOP_FLUSH_PAGES.
    - */
    -#define FI_NONE			0	/* none */
    -#define FI_REMAPF		1	/* Do a remapf prior to the operation */
    -#define FI_REMAPF_LOCKED	2	/* Do a remapf prior to the operation.
    -					   Prevent VM access to the pages until
    -					   the operation completes. */
    -
    -/*
    - * Vnode attributes.  va_mask indicates those attributes the caller
    - * wants to set or extract.
    - */
    -typedef struct xfs_vattr {
    -	int		va_mask;	/* bit-mask of attributes present */
    -	mode_t		va_mode;	/* file access mode and type */
    -	nlink_t		va_nlink;	/* number of references to file */
    -	uid_t		va_uid;		/* owner user id */
    -	gid_t		va_gid;		/* owner group id */
    -	xfs_ino_t	va_nodeid;	/* file id */
    -	xfs_off_t	va_size;	/* file size in bytes */
    -	u_long		va_blocksize;	/* blocksize preferred for i/o */
    -	struct timespec	va_atime;	/* time of last access */
    -	struct timespec	va_mtime;	/* time of last modification */
    -	struct timespec	va_ctime;	/* time file changed */
    -	u_int		va_gen;		/* generation number of file */
    -	xfs_dev_t	va_rdev;	/* device the special file represents */
    -	__int64_t	va_nblocks;	/* number of blocks allocated */
    -	u_long		va_xflags;	/* random extended file flags */
    -	u_long		va_extsize;	/* file extent size */
    -	u_long		va_nextents;	/* number of extents in file */
    -	u_long		va_anextents;	/* number of attr extents in file */
    -	int		va_projid;	/* project id */
    -} xfs_vattr_t;
    -
    -/*
    - * setattr or getattr attributes
    - */
    -#define XFS_AT_TYPE		0x00000001
    -#define XFS_AT_MODE		0x00000002
    -#define XFS_AT_UID		0x00000004
    -#define XFS_AT_GID		0x00000008
    -#define XFS_AT_FSID		0x00000010
    -#define XFS_AT_NODEID		0x00000020
    -#define XFS_AT_NLINK		0x00000040
    -#define XFS_AT_SIZE		0x00000080
    -#define XFS_AT_ATIME		0x00000100
    -#define XFS_AT_MTIME		0x00000200
    -#define XFS_AT_CTIME		0x00000400
    -#define XFS_AT_RDEV		0x00000800
    -#define XFS_AT_BLKSIZE		0x00001000
    -#define XFS_AT_NBLOCKS		0x00002000
    -#define XFS_AT_VCODE		0x00004000
    -#define XFS_AT_MAC		0x00008000
    -#define XFS_AT_UPDATIME		0x00010000
    -#define XFS_AT_UPDMTIME		0x00020000
    -#define XFS_AT_UPDCTIME		0x00040000
    -#define XFS_AT_ACL		0x00080000
    -#define XFS_AT_CAP		0x00100000
    -#define XFS_AT_INF		0x00200000
    -#define XFS_AT_XFLAGS		0x00400000
    -#define XFS_AT_EXTSIZE		0x00800000
    -#define XFS_AT_NEXTENTS		0x01000000
    -#define XFS_AT_ANEXTENTS	0x02000000
    -#define XFS_AT_PROJID		0x04000000
    -#define XFS_AT_SIZE_NOPERM	0x08000000
    -#define XFS_AT_GENCOUNT		0x10000000
    -
    -#define XFS_AT_ALL	(XFS_AT_TYPE|XFS_AT_MODE|XFS_AT_UID|XFS_AT_GID|\
    -		XFS_AT_FSID|XFS_AT_NODEID|XFS_AT_NLINK|XFS_AT_SIZE|\
    -		XFS_AT_ATIME|XFS_AT_MTIME|XFS_AT_CTIME|XFS_AT_RDEV|\
    -		XFS_AT_BLKSIZE|XFS_AT_NBLOCKS|XFS_AT_VCODE|XFS_AT_MAC|\
    -		XFS_AT_ACL|XFS_AT_CAP|XFS_AT_INF|XFS_AT_XFLAGS|XFS_AT_EXTSIZE|\
    -		XFS_AT_NEXTENTS|XFS_AT_ANEXTENTS|XFS_AT_PROJID|XFS_AT_GENCOUNT)
    -
    -#define XFS_AT_STAT	(XFS_AT_TYPE|XFS_AT_MODE|XFS_AT_UID|XFS_AT_GID|\
    -		XFS_AT_FSID|XFS_AT_NODEID|XFS_AT_NLINK|XFS_AT_SIZE|\
    -		XFS_AT_ATIME|XFS_AT_MTIME|XFS_AT_CTIME|XFS_AT_RDEV|\
    -		XFS_AT_BLKSIZE|XFS_AT_NBLOCKS|XFS_AT_PROJID)
    -
    -#define XFS_AT_TIMES	(XFS_AT_ATIME|XFS_AT_MTIME|XFS_AT_CTIME)
    -
    -#define XFS_AT_UPDTIMES	(XFS_AT_UPDATIME|XFS_AT_UPDMTIME|XFS_AT_UPDCTIME)
    -
    -#define XFS_AT_NOSET	(XFS_AT_NLINK|XFS_AT_RDEV|XFS_AT_FSID|XFS_AT_NODEID|\
    -		XFS_AT_TYPE|XFS_AT_BLKSIZE|XFS_AT_NBLOCKS|XFS_AT_VCODE|\
    -		XFS_AT_NEXTENTS|XFS_AT_ANEXTENTS|XFS_AT_GENCOUNT)
    -
    -#ifndef __FreeBSD__
    -/*
    - *  Modes.
    - */
    -#define VSUID	S_ISUID		/* set user id on execution */
    -#define VSGID	S_ISGID		/* set group id on execution */
    -#define VSVTX	S_ISVTX		/* save swapped text even after use */
    -#define VREAD	S_IRUSR		/* read, write, execute permissions */
    -#define VWRITE	S_IWUSR
    -#define VEXEC	S_IXUSR
    -#endif /* __FreeBSD__ */
    -
    -#define MODEMASK ALLPERMS	/* mode bits plus permission bits */
    -
    -/*
    - * Check whether mandatory file locking is enabled.
    - */
    -#define MANDLOCK(vp, mode)	\
    -	((vp)->v_vnode->v_type == VREG && ((mode) & (S_ISGID|(VEXEC>>3))) == S_ISGID)
    -
    -extern void		vn_init(void);
    -extern int		vn_wait(struct xfs_vnode *);
    -extern void		vn_iowait(struct xfs_vnode *);
    -extern xfs_vnode_t	*vn_initialize(struct xfs_vnode *);
    -
    -/*
    - * Acquiring and invalidating vnodes:
    - *
    - *	if (vn_get(vp, version, 0))
    - *		...;
    - *	vn_purge(vp, version);
    - *
    - * vn_get and vn_purge must be called with vmap_t arguments, sampled
    - * while a lock that the vnode's VOP_RECLAIM function acquires is
    - * held, to ensure that the vnode sampled with the lock held isn't
    - * recycled (VOP_RECLAIMed) or deallocated between the release of the lock
    - * and the subsequent vn_get or vn_purge.
    - */
    -
    -/*
    - * vnode_map structures _must_ match vn_epoch and vnode structure sizes.
    - */
    -typedef struct vnode_map {
    -	xfs_vfs_t	*v_vfsp;
    -	xfs_ino_t	v_ino;
    -	struct vnode	*v_vp;
    -} vmap_t;
    -
    -#if 1
    -#define VMAP(vp, vmap)	{(vmap).v_vfsp	 = (vp)->v_vfsp;	\
    -			 (vmap).v_vp     = (vp)->v_vnode;	\
    -			 (vmap).v_ino	 = (vp)->v_inode->i_ino;\
    -			 vhold((vp)->v_vnode);			\
    -			}
    -#endif
    -
    -extern void	vn_purge(struct xfs_vnode *);
    -extern xfs_vnode_t	*vn_get(struct xfs_vnode *, vmap_t *);
    -extern int	vn_revalidate(struct xfs_vnode *);
    -
    -static inline int vn_count(struct xfs_vnode *vp)
    -{
    -	return vp->v_vnode->v_usecount;
    -}
    -
    -/*
    - * Vnode reference counting functions (and macros for compatibility).
    - */
    -extern xfs_vnode_t	*vn_hold(struct xfs_vnode *);
    -extern void	vn_rele(struct xfs_vnode *);
    -
    -#if defined(XFS_VNODE_TRACE)
    -#define VN_HOLD(vp)		\
    -	((void)vref((vp)->v_vnode), \
    -	  vn_trace_hold(vp, __FILE__, __LINE__, (inst_t *)__return_address))
    -#define VN_RELE(vp)		\
    -	  (vn_trace_rele(vp, __FILE__, __LINE__, (inst_t *)__return_address), \
    -	   vrele((vp)->v_vnode))
    -#else
    -#define VN_HOLD(vp)		vref((vp)->v_vnode)
    -#define VN_RELE(vp)		vrele((vp)->v_vnode)
    -#endif
    -
    -/*
    - * Vname handling macros.
    - */
    -#define VNAME(cnp)		((cnp)->cn_nameptr)
    -#define VNAMELEN(cnp)		((cnp)->cn_namelen)
    -#define VNAME_TO_VNODE(dentry)	(printf("VNAME_TO_VNODE NI"), (xfs_vnode_t *)0)
    -
    -/*
    - * Vnode spinlock manipulation.
    - */
    -#define VN_LOCK(vp)		VI_LOCK(vp->v_vnode)
    -#define VN_UNLOCK(vp, s)	VI_UNLOCK(vp->v_vnode)
    -#define VN_FLAGSET(vp,b)	vn_flagset(vp,b)
    -#define VN_FLAGCLR(vp,b)	vn_flagclr(vp,b)
    -
    -static __inline__ void vn_flagset(struct xfs_vnode *vp, __u32 flag)
    -{
    -	VN_LOCK(vp);
    -	vp->v_flag |= flag;
    -	VN_UNLOCK(vp, 0);
    -}
    -
    -static __inline__ void vn_flagclr(struct xfs_vnode *vp, __u32 flag)
    -{
    -	VN_LOCK(vp);
    -	vp->v_flag &= ~flag;
    -	VN_UNLOCK(vp, 0);
    -}
    -
    -/*
    - * Update modify/access/change times on the vnode
    - */
    -#define VN_MTIMESET(vp, tvp)
    -#define VN_ATIMESET(vp, tvp)
    -#define VN_CTIMESET(vp, tvp)
    -
    -/*
    - * Some useful predicates.
    - */
    -#define	VN_MAPPED(vp)	0
    -#define	VN_CACHED(vp)	0
    -#define VN_DIRTY(vp)	0
    -#define VMODIFY(vp)	VN_FLAGSET(vp, VMODIFIED)
    -#define VUNMODIFY(vp)	VN_FLAGCLR(vp, VMODIFIED)
    -
    -
    -/*
    - * Flags to VOP_SETATTR/VOP_GETATTR.
    - */
    -#define	ATTR_UTIME	0x01	/* non-default utime(2) request */
    -#define	ATTR_DMI	0x08	/* invocation from a DMI function */
    -#define	ATTR_LAZY	0x80	/* set/get attributes lazily */
    -#define	ATTR_NONBLOCK	0x100	/* return EAGAIN if operation would block */
    -#define ATTR_NOLOCK	0x200	/* Don't grab any conflicting locks */
    -#define ATTR_NOSIZETOK	0x400	/* Don't get the SIZE token */
    -
    -/*
    - * Flags to VOP_FSYNC and VOP_RECLAIM.
    - */
    -#define FSYNC_NOWAIT	0	/* asynchronous flush */
    -#define FSYNC_WAIT	0x1	/* synchronous fsync or forced reclaim */
    -#define FSYNC_INVAL	0x2	/* flush and invalidate cached data */
    -#define FSYNC_DATA	0x4	/* synchronous fsync of data only */
    -
    -
    -static inline struct xfs_vnode *vn_grab(struct xfs_vnode *vp)
    -{
    -	printf("vn_grab NI\n");
    -//	struct inode *inode = igrab(vn_to_inode(vp));
    -//	return inode ? vn_from_inode(inode) : NULL;
    -	return NULL;
    -}
    -
    -static inline void vn_atime_to_bstime(struct xfs_vnode *vp, xfs_bstime_t *bs_atime)
    -{
    -	printf("%s NI\n", __func__);
    -//        bs_atime->tv_sec = vp->v_inode.i_atime.tv_sec;
    -//        bs_atime->tv_nsec = vp->v_inode.i_atime.tv_nsec;
    -} 
    -
    -static inline void vn_atime_to_timespec(struct xfs_vnode *vp, struct timespec *ts)
    -{
    -//	*ts = vp->v_vnode->va_atime;
    -}
    -
    -/*
    - * Tracking vnode activity.
    - */
    -#if defined(XFS_VNODE_TRACE)
    -
    -#define	VNODE_TRACE_SIZE	16		/* number of trace entries */
    -#define	VNODE_KTRACE_ENTRY	1
    -#define	VNODE_KTRACE_EXIT	2
    -#define	VNODE_KTRACE_HOLD	3
    -#define	VNODE_KTRACE_REF	4
    -#define	VNODE_KTRACE_RELE	5
    -
    -extern void vn_trace_entry(struct xfs_vnode *, char *, inst_t *);
    -extern void vn_trace_exit(struct xfs_vnode *, char *, inst_t *);
    -extern void vn_trace_hold(struct xfs_vnode *, char *, int, inst_t *);
    -extern void vn_trace_ref(struct xfs_vnode *, char *, int, inst_t *);
    -extern void vn_trace_rele(struct xfs_vnode *, char *, int, inst_t *);
    -
    -
    -
    -#define	VN_TRACE(vp)		\
    -	vn_trace_ref(vp, __FILE__, __LINE__, (inst_t *)__return_address)
    -#else
    -#define	vn_trace_entry(a,b,c)
    -#define	vn_trace_exit(a,b,c)
    -#define	vn_trace_hold(a,b,c,d)
    -#define	vn_trace_ref(a,b,c,d)
    -#define	vn_trace_rele(a,b,c,d)
    -#define	VN_TRACE(vp)
    -#endif
    -
    -#endif	/* __XFS_VNODE_H__ */
    diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_vnops.c b/sys/gnu/fs/xfs/FreeBSD/xfs_vnops.c
    deleted file mode 100644
    index 01aa0e5ffe0..00000000000
    --- a/sys/gnu/fs/xfs/FreeBSD/xfs_vnops.c
    +++ /dev/null
    @@ -1,1680 +0,0 @@
    -/*
    - * Copyright (c) 2001, Alexander Kabaev
    - * Copyright (c) 2006, Russell Cattelan Digital Elves Inc.
    - * 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 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -#include 
    -
    -#define NO_VFS_MACROS
    -#include "xfs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_inum.h"
    -#include "xfs_log.h"
    -#include "xfs_trans.h"
    -#include "xfs_trans_priv.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_btree.h"
    -#include "xfs_imap.h"
    -#include "xfs_attr.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_ialloc.h"
    -#include "xfs_alloc.h"
    -#include "xfs_inode.h"
    -#include "xfs_inode_item.h"
    -#include "xfs_acl.h"
    -#include "xfs_cap.h"
    -#include "xfs_mac.h"
    -#include "xfs_iomap.h"
    -#include "xfs_clnt.h"
    -#include "xfs_mountops.h"
    -
    -/*
    - * Prototypes for XFS vnode operations.
    - */
    -static vop_access_t		_xfs_access;
    -static vop_advlock_t		_xfs_advlock;
    -static vop_bmap_t		_xfs_bmap;
    -static vop_cachedlookup_t	_xfs_cachedlookup;
    -static vop_close_t		_xfs_close;
    -static vop_create_t		_xfs_create;
    -static vop_deleteextattr_t	_xfs_deleteextattr;
    -static vop_fsync_t		_xfs_fsync;
    -static vop_getattr_t		_xfs_getattr;
    -static vop_getextattr_t		_xfs_getextattr;
    -static vop_inactive_t		_xfs_inactive;
    -static vop_ioctl_t		_xfs_ioctl;
    -static vop_link_t		_xfs_link;
    -static vop_listextattr_t	_xfs_listextattr;
    -static vop_mkdir_t		_xfs_mkdir;
    -static vop_mknod_t		_xfs_mknod;
    -static vop_open_t		_xfs_open;
    -static vop_read_t		_xfs_read;
    -static vop_readdir_t		_xfs_readdir;
    -static vop_readlink_t		_xfs_readlink;
    -static vop_reclaim_t		_xfs_reclaim;
    -static vop_remove_t		_xfs_remove;
    -static vop_rename_t		_xfs_rename;
    -static vop_rmdir_t		_xfs_rmdir;
    -static vop_setattr_t		_xfs_setattr;
    -static vop_setextattr_t		_xfs_setextattr;
    -static vop_strategy_t		_xfs_strategy;
    -static vop_symlink_t		_xfs_symlink;
    -static vop_write_t		_xfs_write;
    -static vop_vptofh_t		_xfs_vptofh;
    -
    -struct vop_vector xfs_vnops = {
    -	.vop_default =		&default_vnodeops,
    -	.vop_access =		_xfs_access,
    -	.vop_advlock =		_xfs_advlock,
    -	.vop_bmap =		_xfs_bmap,
    -	.vop_cachedlookup =	_xfs_cachedlookup,
    -	.vop_close =		_xfs_close,
    -	.vop_create =		_xfs_create,
    -	.vop_deleteextattr =	_xfs_deleteextattr,
    -	.vop_fsync =		_xfs_fsync,
    -	.vop_getattr =		_xfs_getattr,
    -	.vop_getextattr =	_xfs_getextattr,
    -	.vop_inactive =		_xfs_inactive,
    -	.vop_ioctl =		_xfs_ioctl,
    -	.vop_link =		_xfs_link,
    -	.vop_listextattr =	_xfs_listextattr,
    -	.vop_lookup =		vfs_cache_lookup,
    -	.vop_mkdir =		_xfs_mkdir,
    -	.vop_mknod =		_xfs_mknod,
    -	.vop_open =		_xfs_open,
    -	.vop_read =		_xfs_read,
    -	.vop_readdir =		_xfs_readdir,
    -	.vop_readlink =		_xfs_readlink,
    -	.vop_reclaim =		_xfs_reclaim,
    -	.vop_remove =		_xfs_remove,
    -	.vop_rename =		_xfs_rename,
    -	.vop_rmdir =		_xfs_rmdir,
    -	.vop_setattr =		_xfs_setattr,
    -	.vop_setextattr =	_xfs_setextattr,
    -	.vop_strategy =		_xfs_strategy,
    -	.vop_symlink =		_xfs_symlink,
    -	.vop_write =		_xfs_write,
    -	.vop_vptofh =		_xfs_vptofh,
    -};
    -
    -/*
    - *  FIFO's specific operations.
    - */
    -
    -static vop_close_t	_xfsfifo_close;
    -static vop_read_t	_xfsfifo_read;
    -static vop_kqfilter_t	_xfsfifo_kqfilter;
    -static vop_write_t	_xfsfifo_write;
    -
    -struct vop_vector xfs_fifoops = {
    -	.vop_default =		&fifo_specops,
    -	.vop_access =		_xfs_access,
    -	.vop_close =		_xfsfifo_close,
    -	.vop_fsync =		_xfs_fsync,
    -	.vop_getattr =		_xfs_getattr,
    -	.vop_inactive =		_xfs_inactive,
    -	.vop_kqfilter =		_xfsfifo_kqfilter,
    -	.vop_read =		_xfsfifo_read,
    -	.vop_reclaim =		_xfs_reclaim,
    -	.vop_setattr =		_xfs_setattr,
    -	.vop_write =		_xfsfifo_write,
    -	.vop_vptofh =		_xfs_vptofh,
    -};
    -
    -static int
    -_xfs_access(
    -    	struct vop_access_args /* {
    -		struct vnode *a_vp;
    -		accmode_t a_accmode;
    -		struct ucred *a_cred;
    -		struct thread *a_td;
    -	} */ *ap)
    -{
    -	int error;
    -
    -	XVOP_ACCESS(VPTOXFSVP(ap->a_vp), ap->a_accmode, ap->a_cred, error);
    -	return (error);
    -}
    -
    -static int
    -_xfs_open(
    -    	struct vop_open_args /* {
    -		struct vnode *a_vp;
    -		int  a_mode;
    -		struct ucred *a_cred;
    -		struct thread *a_td;
    -		struct file *a_fp;
    -	} */ *ap)
    -{
    -	int error;
    -
    -	XVOP_OPEN(VPTOXFSVP(ap->a_vp), ap->a_cred, error);
    -	if (error == 0)
    -		vnode_create_vobject(ap->a_vp, 0, ap->a_td);
    -	return (error);
    -}
    -
    -static int
    -_xfs_close(
    -	struct vop_close_args /* {
    -		struct vnodeop_desc *a_desc;
    -		struct vnode *a_vp;
    -		int  a_fflag;
    -		struct ucred *a_cred;
    -		struct thread *a_td;
    -	} */ *ap)
    -{
    -	int error = 0;
    -	/* XVOP_CLOSE(VPTOXFSVP(ap->a_vp), NULL, error); */
    -	return (error);
    -}
    -
    -static int
    -_xfs_getattr(
    -	struct vop_getattr_args /* {
    -		struct vnode *a_vp;
    -		struct vattr *a_vap;
    -		struct ucred *a_cred;
    -	} */ *ap)
    -{
    -	struct vnode	*vp = ap->a_vp;
    -	struct vattr	*vap = ap->a_vap;
    -	struct mount	*mp;
    -	xfs_vattr_t	va;
    -	int		error;
    -	/* extract the xfs vnode from the private data */
    -	//xfs_vnode_t	*xvp = (xfs_vnode_t *)vp->v_data;
    -
    -	memset(&va,0,sizeof(xfs_vattr_t));
    -	va.va_mask = XFS_AT_STAT|XFS_AT_GENCOUNT|XFS_AT_XFLAGS;
    -
    -	XVOP_GETATTR(VPTOXFSVP(vp), &va, 0, ap->a_cred, error);
    -	if (error)
    -		return (error);
    -
    -	mp  = vp->v_mount;
    -
    -	vap->va_type = IFTOVT(((xfs_vnode_t *)vp->v_data)->v_inode->i_d.di_mode);
    -	vap->va_mode = va.va_mode;
    -	vap->va_nlink = va.va_nlink;
    -	vap->va_uid = va.va_uid;
    -	vap->va_gid = va.va_gid;
    -	vap->va_fsid = mp->mnt_stat.f_fsid.val[0];
    -	vap->va_fileid = va.va_nodeid;
    -	vap->va_size = va.va_size;
    -	vap->va_blocksize = va.va_blocksize;
    -	vap->va_atime = va.va_atime;
    -	vap->va_mtime = va.va_mtime;
    -	vap->va_ctime = va.va_ctime;
    -	vap->va_gen = va.va_gen;
    -	vap->va_rdev = va.va_rdev;
    -	vap->va_bytes = (va.va_nblocks << BBSHIFT);
    -
    -	/* XFS now supports devices that have block sizes
    -	 * other than 512 so BBSHIFT will work for now
    -	 * but need to get this value from the super block
    -	 */
    -
    -	/*
    -	 * Fields with no direct equivalent in XFS
    -	 */
    -	vap->va_filerev = 0;
    -	vap->va_flags = 0;
    -
    -	return (0);
    -}
    -
    -static int
    -_xfs_setattr(
    -	struct vop_setattr_args /* {
    -		struct vnode *a_vp;
    -		struct vattr *a_vap;
    -		struct ucred *a_cred;
    -	} */ *ap)
    -{
    -	struct vnode *vp = ap->a_vp;
    -	struct vattr *vap = ap->a_vap;
    -	xfs_vattr_t   va;
    -	int error;
    -
    -	/*
    -	 * Check for unsettable attributes.
    -	 */
    -#ifdef RMC
    -	if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
    -	    (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
    -	    (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
    -	    ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL))
    -		return (EINVAL);
    -#endif
    -
    -	memset(&va, 0, sizeof(va));
    -
    -	if (vap->va_uid != (uid_t)VNOVAL) {
    -		va.va_mask |= XFS_AT_UID;
    -		va.va_uid = vap->va_uid;
    -	}
    -	if (vap->va_gid != (gid_t)VNOVAL) {
    -		va.va_mask |= XFS_AT_GID;
    -		va.va_gid = vap->va_gid;
    -	}
    -	if (vap->va_size != VNOVAL) {
    -		va.va_mask |= XFS_AT_SIZE;
    -		va.va_size = vap->va_size;
    -	}
    -	if (vap->va_atime.tv_sec != VNOVAL) {
    -		va.va_mask |= XFS_AT_ATIME;
    -		va.va_atime = vap->va_atime;
    -	}
    -	if (vap->va_mtime.tv_sec != VNOVAL) {
    -		va.va_mask |= XFS_AT_MTIME;
    -		va.va_mtime = vap->va_mtime;
    -	}
    -	if (vap->va_ctime.tv_sec != VNOVAL) {
    -		va.va_mask |= XFS_AT_CTIME;
    -		va.va_ctime = vap->va_ctime;
    -	}
    -	if (vap->va_mode != (mode_t)VNOVAL) {
    -		va.va_mask |= XFS_AT_MODE;
    -		va.va_mode = vap->va_mode;
    -	}
    -
    -	XVOP_SETATTR(VPTOXFSVP(vp), &va, 0, ap->a_cred, error);
    -	return (error);
    -}
    -
    -static int
    -_xfs_inactive(
    -	struct vop_inactive_args  /* {
    -		struct vnode *a_vp;
    -		struct thread *a_td;
    -	} */ *ap)
    -{
    -	struct vnode *vp = ap->a_vp;
    -	struct thread *td = ap->a_td;
    -	int error;
    -
    -	XVOP_INACTIVE(VPTOXFSVP(vp), td->td_ucred, error);
    -	return (error);
    -}
    -
    -static int
    -_xfs_read(
    -	struct vop_read_args /* {
    -		struct vnode *a_vp;
    -		struct uio *a_uio;
    -		int  a_ioflag;
    -		struct ucred *a_cred;
    -	} */ *ap)
    -{
    -	struct vnode *vp = ap->a_vp;
    - 	struct uio *uio = ap->a_uio;
    -	int error;
    -
    -	switch (vp->v_type) {
    -	case VREG:
    -		break;
    -	case VDIR:
    -		return (EISDIR);
    -	default:
    -		return (EPERM);
    -	};
    -
    -	XVOP_READ(VPTOXFSVP(vp), uio, ap->a_ioflag, ap->a_cred, error);
    -	return error;
    -}
    -
    -int
    -xfs_read_file(xfs_mount_t *mp, xfs_inode_t *ip, struct uio *uio, int ioflag)
    -{
    -	xfs_fileoff_t lbn, nextlbn;
    -	xfs_fsize_t bytesinfile;
    -	long size, xfersize, blkoffset;
    -	struct buf *bp;
    -	struct vnode *vp;
    -	int error, orig_resid;
    -	int seqcount;
    -
    -	seqcount = ioflag >> IO_SEQSHIFT;
    -
    -	orig_resid = uio->uio_resid;
    -	if (orig_resid <= 0)
    -		return (0);
    -
    -	vp = XFS_ITOV(ip)->v_vnode;
    -
    -	/*
    -	 * Ok so we couldn't do it all in one vm trick...
    -	 * so cycle around trying smaller bites..
    -	 */
    -	for (error = 0, bp = NULL; uio->uio_resid > 0; bp = NULL) {
    -		if ((bytesinfile = ip->i_d.di_size - uio->uio_offset) <= 0)
    -			break;
    -
    -		lbn = XFS_B_TO_FSBT(mp, uio->uio_offset);
    -		nextlbn = lbn + 1;
    -
    -		/*
    -		 * size of buffer.  The buffer representing the
    -		 * end of the file is rounded up to the size of
    -		 * the block type ( fragment or full block,
    -		 * depending ).
    -		 */
    -		size = mp->m_sb.sb_blocksize;
    -		blkoffset = XFS_B_FSB_OFFSET(mp, uio->uio_offset);
    -
    -		/*
    -		 * The amount we want to transfer in this iteration is
    -		 * one FS block less the amount of the data before
    -		 * our startpoint (duh!)
    -		 */
    -		xfersize = mp->m_sb.sb_blocksize - blkoffset;
    -
    -		/*
    -		 * But if we actually want less than the block,
    -		 * or the file doesn't have a whole block more of data,
    -		 * then use the lesser number.
    -		 */
    -		if (uio->uio_resid < xfersize)
    -			xfersize = uio->uio_resid;
    -		if (bytesinfile < xfersize)
    -			xfersize = bytesinfile;
    -
    -		if (XFS_FSB_TO_B(mp, nextlbn) >= ip->i_d.di_size ) {
    -			/*
    -			 * Don't do readahead if this is the end of the file.
    -			 */
    -			error = bread(vp, lbn, size, NOCRED, &bp);
    -		} else if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0) {
    -			/*
    -			 * Otherwise if we are allowed to cluster,
    -			 * grab as much as we can.
    -			 *
    -			 * XXX  This may not be a win if we are not
    -			 * doing sequential access.
    -			 */
    -			error = cluster_read(vp, ip->i_d.di_size, lbn,
    -				size, NOCRED, uio->uio_resid, seqcount, &bp);
    -		} else if (seqcount > 1) {
    -			/*
    -			 * If we are NOT allowed to cluster, then
    -			 * if we appear to be acting sequentially,
    -			 * fire off a request for a readahead
    -			 * as well as a read. Note that the 4th and 5th
    -			 * arguments point to arrays of the size specified in
    -			 * the 6th argument.
    -			 */
    -			int nextsize = mp->m_sb.sb_blocksize;
    -			error = breadn(vp, lbn,
    -			    size, &nextlbn, &nextsize, 1, NOCRED, &bp);
    -		} else {
    -			/*
    -			 * Failing all of the above, just read what the
    -			 * user asked for. Interestingly, the same as
    -			 * the first option above.
    -			 */
    -			error = bread(vp, lbn, size, NOCRED, &bp);
    -		}
    -		if (error) {
    -			brelse(bp);
    -			bp = NULL;
    -			break;
    -		}
    -
    -		/*
    -		 * If IO_DIRECT then set B_DIRECT for the buffer.  This
    -		 * will cause us to attempt to release the buffer later on
    -		 * and will cause the buffer cache to attempt to free the
    -		 * underlying pages.
    -		 */
    -		if (ioflag & IO_DIRECT)
    -			bp->b_flags |= B_DIRECT;
    -
    -		/*
    -		 * We should only get non-zero b_resid when an I/O error
    -		 * has occurred, which should cause us to break above.
    -		 * However, if the short read did not cause an error,
    -		 * then we want to ensure that we do not uiomove bad
    -		 * or uninitialized data.
    -		 */
    -		size -= bp->b_resid;
    -		if (size < xfersize) {
    -			if (size == 0)
    -				break;
    -			xfersize = size;
    -		}
    -
    -		/*
    -		 * otherwise use the general form
    -		 */
    -		error = uiomove((char *)bp->b_data + blkoffset,
    -			    (int)xfersize, uio);
    -
    -		if (error)
    -			break;
    -
    -		if (ioflag & (IO_VMIO|IO_DIRECT) ) {
    -			/*
    -			 * If there are no dependencies, and it's VMIO,
    -			 * then we don't need the buf, mark it available
    -			 * for freeing. The VM has the data.
    -			 */
    -			bp->b_flags |= B_RELBUF;
    -			brelse(bp);
    -		} else {
    -			/*
    -			 * Otherwise let whoever
    -			 * made the request take care of
    -			 * freeing it. We just queue
    -			 * it onto another list.
    -			 */
    -			bqrelse(bp);
    -		}
    -	}
    -
    -	/*
    -	 * This can only happen in the case of an error
    -	 * because the loop above resets bp to NULL on each iteration
    -	 * and on normal completion has not set a new value into it.
    -	 * so it must have come from a 'break' statement
    -	 */
    -	if (bp != NULL) {
    -		if (ioflag & (IO_VMIO|IO_DIRECT)) {
    -			bp->b_flags |= B_RELBUF;
    -			brelse(bp);
    -		} else
    -			bqrelse(bp);
    -	}
    -
    -	return (error);
    -}
    -
    -static int
    -_xfs_write(struct vop_write_args /* {
    -		struct vnode *a_vp;
    -		struct uio *a_uio;
    -		int  a_ioflag;
    -		struct ucred *a_cred;
    -	} */ *ap)
    -{
    -	struct vnode *vp = ap->a_vp;
    -	struct uio *uio = ap->a_uio;
    -	int ioflag = ap->a_ioflag;
    -	int error;
    -
    -	xfs_vnode_t *xvp = (xfs_vnode_t *)vp->v_data;
    -
    -	error = xfs_write(xvp->v_bh.bh_first, uio, ioflag, ap->a_cred);
    -
    -	if (error < 0) {
    -		printf("Xfs_write got error %d\n",error);
    -		return -error;
    -	}
    -	return 0;
    -}
    -
    -
    -int
    -xfs_write_file(xfs_inode_t *xip, struct uio *uio, int ioflag)
    -{
    -	struct buf	*bp;
    -	//struct thread	*td;
    -	daddr_t		lbn;
    -	off_t		osize = 0;
    -	off_t		offset= 0;
    -	int		blkoffset, error, resid, xfersize;
    -	int		fsblocksize;
    -	int		seqcount;
    -	xfs_iomap_t	iomap;
    -	int		maps = 1;
    -
    -	xfs_vnode_t	*xvp = XFS_ITOV(xip);
    -	struct vnode	*vp = xvp->v_vnode;
    -
    -	xfs_mount_t	*mp = (&xip->i_iocore)->io_mount;
    -
    -	seqcount = ioflag >> IO_SEQSHIFT;
    -
    -	memset(&iomap,0,sizeof(xfs_iomap_t));
    -
    -	/*
    -	 * Maybe this should be above the vnode op call, but so long as
    -	 * file servers have no limits, I don't think it matters.
    -	 */
    -#if 0
    -	td = uio->uio_td;
    -	if (vn_rlimit_fsize(vp, uio, uio->uio_td))
    -		return (EFBIG);
    -#endif
    -
    -	resid = uio->uio_resid;
    -	offset = uio->uio_offset;
    -	osize = xip->i_d.di_size;
    -
    -   /* xfs bmap wants bytes for both offset and size */
    -	XVOP_BMAP(xvp,
    -		  uio->uio_offset,
    -		  uio->uio_resid,
    -		  BMAPI_WRITE|BMAPI_DIRECT,
    -		  &iomap, &maps, error);
    -	if(error) {
    -		printf("XVOP_BMAP failed\n");
    -		goto error;
    -	}
    -
    -	for (error = 0; uio->uio_resid > 0;) {
    -
    -		lbn = XFS_B_TO_FSBT(mp, offset);
    -		blkoffset = XFS_B_FSB_OFFSET(mp, offset);
    -		xfersize = mp->m_sb.sb_blocksize - blkoffset;
    -		fsblocksize = mp->m_sb.sb_blocksize;
    -
    -		if (uio->uio_resid < xfersize)
    -			xfersize = uio->uio_resid;
    -
    -		/*
    -		 * getblk sets buf by  blkno *  bo->bo_bsize
    -		 * bo_bsize is set from the mnt point fsize
    -		 * so we call getblk in the case using fsblocks
    -		 * not basic blocks
    -		 */
    -
    -		bp = getblk(vp, lbn, fsblocksize, 0, 0, 0);
    -		if(!bp) {
    -			printf("getblk failed\n");
    -			error = EINVAL;
    -			break;
    -		}
    -
    -		if (!(bp->b_flags & B_CACHE)  && fsblocksize > xfersize)
    -			vfs_bio_clrbuf(bp);
    -
    -		if (offset + xfersize >  xip->i_d.di_size) {
    -			xip->i_d.di_size = offset + xfersize;
    -			vnode_pager_setsize(vp, offset + fsblocksize);
    -		}
    -
    -		/* move the offset for the next itteration of the loop */
    -		offset += xfersize;
    -
    -		error = uiomove((char *)bp->b_data + blkoffset, xfersize, uio);
    -
    -		if ((ioflag & IO_VMIO) &&
    -		   (LIST_FIRST(&bp->b_dep) == NULL)) /* in ext2fs? */
    -			bp->b_flags |= B_RELBUF;
    -
    -		/* force to full direct for now */
    -		bp->b_flags |= B_DIRECT;
    -		/* and sync ... the delay path is not pushing data out */
    -		ioflag |= IO_SYNC;
    -
    -		if (ioflag & IO_SYNC) {
    -			(void)bwrite(bp);
    -		} else if (0 /* RMC xfersize + blkoffset == fs->s_frag_size */) {
    -			if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERW) == 0) {
    -				bp->b_flags |= B_CLUSTEROK;
    -				cluster_write(vp, bp, osize, seqcount);
    -			} else {
    -				bawrite(bp);
    -			}
    -		} else {
    -			bp->b_flags |= B_CLUSTEROK;
    -			bdwrite(bp);
    -		}
    -		if (error || xfersize == 0)
    -			break;
    -	}
    -	/*
    -	 * If we successfully wrote any data, and we are not the superuser
    -	 * we clear the setuid and setgid bits as a precaution against
    -	 * tampering.
    -	 */
    -#if 0
    -	if (resid > uio->uio_resid && ap->a_cred && ap->a_cred->cr_uid != 0)
    -		ip->i_mode &= ~(ISUID | ISGID);
    -#endif
    -	if (error) {
    -		if (ioflag & IO_UNIT) {
    -#if 0
    -			(void)ext2_truncate(vp, osize,
    -			    ioflag & IO_SYNC, ap->a_cred, uio->uio_td);
    -#endif
    -			uio->uio_offset -= resid - uio->uio_resid;
    -			uio->uio_resid = resid;
    -		}
    -	} else if (resid > uio->uio_resid && (ioflag & IO_SYNC)) {
    -		/* Update the vnode here? */
    -	}
    -
    -error:
    -	return error;
    -}
    -
    -static int
    -_xfs_create(
    -    	struct vop_create_args  /* {
    -		struct vnode *a_dvp;
    -		struct vnode **a_vpp;
    -		struct componentname *a_cnp;
    -		struct vattr *a_vap;
    -	} */ *ap)
    -{
    -	struct vnode *dvp = ap->a_dvp;
    - 	struct vattr *vap = ap->a_vap;
    -	struct thread *td = curthread;
    -	struct ucred *credp = td->td_ucred;
    -	struct componentname *cnp = ap->a_cnp;
    -	xfs_vnode_t *xvp;
    -	xfs_vattr_t va;
    -	int error;
    -
    -	memset(&va, 0, sizeof (va));
    -	va.va_mask |= XFS_AT_MODE;
    -	va.va_mode = vap->va_mode;
    -	va.va_mask |= XFS_AT_TYPE;
    -	va.va_mode |=  VTTOIF(vap->va_type);
    -
    -	xvp = NULL;
    -	XVOP_CREATE(VPTOXFSVP(dvp), cnp, &va, &xvp, credp, error);
    -
    -	if (error == 0) {
    -		*ap->a_vpp = xvp->v_vnode;
    -		VOP_LOCK(xvp->v_vnode, LK_EXCLUSIVE);
    -	}
    -
    -	return (error);
    -}
    -
    -extern int xfs_remove(bhv_desc_t *, bhv_desc_t *, vname_t *, cred_t *);
    -
    -static int
    -_xfs_remove(
    -	struct vop_remove_args /* {
    -		struct vnodeop_desc *a_desc;
    -		struct vnode * a_dvp;
    -		struct vnode * a_vp;
    -		struct componentname * a_cnp;
    -	} */ *ap)
    -{
    -	struct vnode *vp = ap->a_vp;
    -	struct thread *td = curthread;
    -	struct ucred  *credp = td->td_ucred;
    -	/*
    -	struct vnode *dvp = ap->a_dvp; 
    - 	struct componentname *cnp = ap->a_cnp;
    -	*/
    -	int error;
    -
    -	if (vp->v_type == VDIR || vp->v_usecount != 1)
    -		return (EPERM);
    -
    -	error = xfs_remove(VPTOXFSVP(ap->a_dvp)->v_bh.bh_first,
    -			   VPTOXFSVP(ap->a_vp)->v_bh.bh_first,
    -			   ap->a_cnp,credp);
    -
    -	cache_purge(vp);
    -	return error;
    -}
    -
    -static int
    -_xfs_rename(
    -	struct vop_rename_args /* {
    -		struct vnode *a_fdvp;
    -		struct vnode *a_fvp;
    -		struct componentname *a_fcnp;
    -		struct vnode *a_tdvp;
    -		struct vnode *a_tvp;
    -		struct componentname *a_tcnp;
    -	} */ *ap)
    -{
    -	struct vnode *fvp = ap->a_fvp;
    -	struct vnode *tvp = ap->a_tvp;
    -	struct vnode *fdvp = ap->a_fdvp;
    -	struct vnode *tdvp = ap->a_tdvp;
    -/* 	struct componentname *tcnp = ap->a_tcnp; */
    -/*	struct componentname *fcnp = ap->a_fcnp;*/
    -	int error = EPERM;
    -
    -	if (error)
    -		goto out;
    -
    -	/* Check for cross-device rename */
    -	if ((fvp->v_mount != tdvp->v_mount) ||
    -	    (tvp && (fvp->v_mount != tvp->v_mount))) {
    -		error = EXDEV;
    -		goto out;
    -	}
    -
    -	if (tvp && tvp->v_usecount > 1) {
    -		error = EBUSY;
    -		goto out;
    -	}
    -
    -	if (fvp->v_type == VDIR) {
    -		if (tvp != NULL && tvp->v_type == VDIR)
    -			cache_purge(tdvp);
    -		cache_purge(fdvp);
    -	}
    -out:
    -	if (tdvp == tvp)
    -		vrele(tdvp);
    -	else
    -		vput(tdvp);
    -	if (tvp)
    -		vput(tvp);
    -	vrele(fdvp);
    -	vrele(fvp);
    -	vgone(fvp);
    -	if (tvp)
    -		vgone(tvp);
    -	return (error);
    -}
    -
    -static int
    -_xfs_link(
    -	struct vop_link_args /* {
    -		struct vnode *a_tdvp;
    -		struct vnode *a_vp;
    -		struct componentname *a_cnp;
    -	} */ *ap)
    -{
    -	xfs_vnode_t *tdvp, *vp;
    -	int error;
    -
    -	tdvp = VPTOXFSVP(ap->a_tdvp);
    -	vp = VPTOXFSVP(ap->a_vp);
    -	XVOP_LINK(tdvp, vp, ap->a_cnp, NULL, error);
    -	return (error);
    -}
    -
    -static int
    -_xfs_symlink(
    -	struct vop_symlink_args /* {
    -		struct vnode *a_dvp;
    -		struct vnode **a_vpp;
    -		struct componentname *a_cnp;
    -		struct vattr *a_vap;
    -		char *a_target;
    -	} */ *ap)
    -{
    -	struct thread *td = curthread;
    -	struct ucred  *credp = td->td_ucred;
    -	xfs_vnode_t *xvp;
    -	xfs_vattr_t va;
    -	int error;
    -
    -	memset(&va, 0, sizeof (va));
    -
    -	va.va_mask |= XFS_AT_MODE;
    -	va.va_mode = ap->a_vap->va_mode | S_IFLNK;
    -	va.va_mask |= XFS_AT_TYPE;
    -
    -	XVOP_SYMLINK(VPTOXFSVP(ap->a_dvp), ap->a_cnp, &va, ap->a_target,
    -	    &xvp, credp, error);
    -
    -	if (error == 0) {
    -		*ap->a_vpp = xvp->v_vnode;
    -		VOP_LOCK(xvp->v_vnode, LK_EXCLUSIVE);
    -	}
    -
    -	return (error);
    -}
    -
    -static int
    -_xfs_mknod(
    -	struct vop_mknod_args /* {
    -		struct vnode *a_dvp;
    -		struct vnode **a_vpp;
    -		struct componentname *a_cnp;
    -		struct vattr *a_vap;
    -	} */ *ap)
    -{
    -	struct vnode *dvp = ap->a_dvp;
    - 	struct vattr *vap = ap->a_vap;
    -	struct thread *td = curthread;
    -	struct ucred *credp = td->td_ucred;
    -	struct componentname *cnp = ap->a_cnp;
    -	xfs_vnode_t *xvp;
    -	xfs_vattr_t va;
    -	int error;
    -
    -	memset(&va, 0, sizeof (va));
    -	va.va_mask |= XFS_AT_MODE;
    -	va.va_mode = vap->va_mode | S_IFIFO;
    -	va.va_mask |= XFS_AT_TYPE;
    -	va.va_mask |= XFS_AT_RDEV;
    -	va.va_rdev = vap->va_rdev;
    -
    -	xvp = NULL;
    -	XVOP_CREATE(VPTOXFSVP(dvp), cnp, &va, &xvp, credp, error);
    -
    -	if (error == 0) {
    -		*ap->a_vpp = xvp->v_vnode;
    -		VOP_LOCK(xvp->v_vnode, LK_EXCLUSIVE);
    -	}
    -
    -	return (error);
    -}
    -
    -static int
    -_xfs_mkdir(
    -	struct vop_mkdir_args /* {
    -		 struct vnode *a_dvp;
    -		 struct vnode **a_vpp;
    -		 struct componentname *a_cnp;
    -		 struct vattr *a_vap;
    -	} */ *ap)
    -{
    -	struct vnode *dvp = ap->a_dvp;
    - 	struct vattr *vap = ap->a_vap;
    -	struct thread *td = curthread;
    -	struct ucred *credp = td->td_ucred;
    -	struct componentname *cnp = ap->a_cnp;
    -	xfs_vnode_t *xvp;
    -	xfs_vattr_t va;
    -	int error;
    -
    -	memset(&va, 0, sizeof (va));
    -	va.va_mask |= XFS_AT_MODE;
    -	va.va_mode = vap->va_mode | S_IFDIR;
    -	va.va_mask |= XFS_AT_TYPE;
    -
    -	xvp = NULL;
    -	XVOP_MKDIR(VPTOXFSVP(dvp), cnp, &va, &xvp, credp, error);
    -
    -	if (error == 0) {
    -		*ap->a_vpp = xvp->v_vnode;
    -		VOP_LOCK(xvp->v_vnode, LK_EXCLUSIVE);
    -	}
    -
    -	return (error);
    -}
    -
    -static int
    -_xfs_rmdir(
    -	struct vop_rmdir_args /* {
    -		struct vnode *a_dvp;
    -		struct vnode *a_vp;
    -		struct componentname *a_cnp;
    -	} */ *ap)
    -{
    -	struct vnode *vp = ap->a_vp;
    -	struct vnode *dvp = ap->a_dvp;
    -/* 	struct componentname *cnp = ap->a_cnp; */
    -	int error;
    -
    -	if (dvp == vp)
    -		return (EINVAL);
    -
    -	error = EPERM;
    -
    -	return (error);
    -}
    -
    -static int
    -_xfs_readdir(
    -	struct vop_readdir_args /* {
    -		struct vnode *a_vp;
    -		struct uio *a_uio;
    -		struct ucred *a_cred;
    -		int *a_eofflag;
    -		int *a_ncookies;
    -		u_long **a_cookies;
    -	} */ *ap)
    -{
    -	struct vnode *vp = ap->a_vp;
    -	struct uio *uio = ap->a_uio;
    -	int error;
    -	off_t	off;
    -	int	eof = 0;
    -
    -	if (vp->v_type != VDIR)
    -		return (EPERM);
    -	if (ap->a_ncookies) {
    -		return (EOPNOTSUPP);
    -	}
    -
    -	error = 0;
    -	while (!eof){
    -		off = (int)uio->uio_offset;
    -
    -		XVOP_READDIR(VPTOXFSVP(vp), uio, NULL, &eof, error);
    -		if ((uio->uio_offset == off) || error) {
    -			break;
    -		}
    -	}
    -
    -	if (ap->a_eofflag)
    -		*ap->a_eofflag = (eof != 0);
    -
    -        return (error);
    -}
    -
    -
    -static int
    -_xfs_readlink(
    -	struct vop_readlink_args /* {
    -		struct vnode *a_vp;
    -		struct uio *a_uio;
    -		struct ucred *a_cred;
    -	} */ *ap)
    -{
    -	struct vnode *vp = ap->a_vp;
    -	struct uio *uio = ap->a_uio;
    -	struct ucred *cred = ap->a_cred;
    -	int error;
    -
    -	XVOP_READLINK(VPTOXFSVP(vp), uio, 0, cred, error);
    -	return (error);
    -}
    -
    -static int
    -_xfs_fsync(
    -	struct vop_fsync_args /* {
    -		struct vnode * a_vp;
    -		int  a_waitfor;
    -		struct thread * a_td;
    -	} */ *ap)
    -{
    -	xfs_vnode_t  *vp = VPTOXFSVP(ap->a_vp);
    -	int flags = FSYNC_DATA;
    -	int error;
    -
    -	if (ap->a_waitfor == MNT_WAIT)
    -		flags |= FSYNC_WAIT;
    -	XVOP_FSYNC(vp, flags, ap->a_td->td_ucred, (xfs_off_t)0, (xfs_off_t)-1, error);
    -
    -	return (error);
    -}
    -
    -static int
    -_xfs_bmap(
    -	struct vop_bmap_args /* {
    -		struct vnode *a_vp;
    -		daddr_t  a_bn;
    -		struct bufobj **a_bop;
    -		daddr_t *a_bnp;
    -		int *a_runp;
    -		int *a_runb;
    -	} */ *ap)
    -{
    -	xfs_iomap_t iomap;
    -	xfs_off_t offset;
    -	ssize_t   size;
    -	struct mount *mp;
    -	struct xfs_mount *xmp;
    -	struct xfs_vnode *xvp;
    -	int error, maxrun, retbm;
    -
    -	mp  = ap->a_vp->v_mount;
    -	xmp = XFS_VFSTOM(MNTTOVFS(mp));
    -	if (ap->a_bop != NULL)
    -		*ap->a_bop = &xmp->m_ddev_targp->specvp->v_bufobj;
    -	if (ap->a_bnp == NULL)
    -		return (0);
    -
    -	xvp = VPTOXFSVP(ap->a_vp);
    -	retbm = 1;
    -
    -	offset = XFS_FSB_TO_B(xmp, ap->a_bn);
    -	size = XFS_FSB_TO_B(xmp, 1);
    -	XVOP_BMAP(xvp, offset, size, BMAPI_READ, &iomap, &retbm, error);
    -	if (error)
    -		return (error);
    -	if (retbm == 0 || iomap.iomap_bn == IOMAP_DADDR_NULL) {
    -		*ap->a_bnp = (daddr_t)-1;
    -		if (ap->a_runb)
    -			*ap->a_runb = 0;
    -		if (ap->a_runp)
    -			*ap->a_runp = 0;
    -	} else {
    -		*ap->a_bnp = iomap.iomap_bn + btodb(iomap.iomap_delta);
    -		maxrun = mp->mnt_iosize_max / mp->mnt_stat.f_iosize - 1;
    -		if (ap->a_runb) {
    -			*ap->a_runb = XFS_B_TO_FSB(xmp, iomap.iomap_delta);
    -			if (*ap->a_runb > maxrun)
    -				*ap->a_runb  = maxrun;
    -		}
    -		if (ap->a_runp) {
    -			*ap->a_runp =
    -			    XFS_B_TO_FSB(xmp, iomap.iomap_bsize
    -				- iomap.iomap_delta - size);
    -			if (*ap->a_runp > maxrun)
    -				*ap->a_runp  = maxrun;
    -		}
    -	}
    -	return (0);
    -}
    -
    -static int
    -_xfs_strategy(
    -	struct vop_strategy_args /* {
    -		struct vnode *a_vp;
    -		struct buf *a_bp;
    -	} */ *ap)
    -{
    -	daddr_t blkno;
    -	struct buf *bp;
    -	struct bufobj *bo;
    -	struct vnode *vp;
    -	struct xfs_mount *xmp;
    -	int error;
    -
    -	bp = ap->a_bp;
    -	vp = ap->a_vp;
    -
    -	KASSERT(ap->a_vp == ap->a_bp->b_vp, ("%s(%p != %p)",
    -	    __func__, ap->a_vp, ap->a_bp->b_vp));
    -	if (bp->b_blkno == bp->b_lblkno) {
    -		error = VOP_BMAP(vp, bp->b_lblkno, NULL, &blkno, NULL, NULL);
    -		bp->b_blkno = blkno;
    -		bp->b_iooffset = (blkno << BBSHIFT);
    -		if (error) {
    -			bp->b_error = error;
    -			bp->b_ioflags |= BIO_ERROR;
    -			bufdone(bp);
    -			return (0);
    -		}
    -		if ((long)bp->b_blkno == -1)
    -			vfs_bio_clrbuf(bp);
    -        }
    -	if ((long)bp->b_blkno == -1) {
    -		bufdone(bp);
    -		return (0);
    -	}
    -
    -	xmp = XFS_VFSTOM(MNTTOVFS(vp->v_mount));
    -	bo = &xmp->m_ddev_targp->specvp->v_bufobj;
    -	bo->bo_ops->bop_strategy(bo, bp);
    -	return (0);
    -}
    -
    -int
    -_xfs_ioctl(
    -	struct vop_ioctl_args /* {
    -		struct vnode *a_vp;
    -		u_long a_command;
    -		caddr_t a_data;
    -		int fflag;
    -		struct ucred *cred;
    -		struct thread *a_td;
    -	} */ *ap)
    -{
    -/* 	struct vnode *vp = ap->a_vp; */
    -/* 	struct thread *p = ap->a_td; */
    -/* 	struct file *fp; */
    -	int error;
    -
    -	xfs_vnode_t *xvp = VPTOXFSVP(ap->a_vp);
    -
    -	printf("_xfs_ioctl cmd 0x%lx data %p\n",ap->a_command,ap->a_data);
    -
    -//	XVOP_IOCTL(xvp,(void *)NULL,(void *)NULL,ap->a_fflag,ap->a_command,ap->a_data,error);
    -	error = xfs_ioctl(xvp->v_bh.bh_first,NULL,NULL,ap->a_fflag,ap->a_command,ap->a_data);
    -
    -	return error;
    -}
    -
    -int
    -_xfs_advlock(
    -	struct vop_advlock_args /* {
    -		struct vnode *a_vp;
    -		caddr_t  a_id;
    -		int  a_op;
    -		struct flock *a_fl;
    -		int  a_flags;
    -	} */ *ap)
    -{
    -/* 	struct vnode *vp = ap->a_vp;*/
    -	struct flock *fl = ap->a_fl;
    -/* 	caddr_t id = (caddr_t)1 */ /* ap->a_id */;
    -/* 	int flags = ap->a_flags; */
    -	off_t start, end, size;
    -	int error/* , lkop */;
    -
    -	/*KAN: temp */
    -	return (EOPNOTSUPP);
    -
    -	size = 0;
    -	error = 0;
    -	switch (fl->l_whence) {
    -	    case SEEK_SET:
    -	    case SEEK_CUR:
    -		start = fl->l_start;
    -		break;
    -	    case SEEK_END:
    -		start = fl->l_start + size;
    -	    default:
    -		return (EINVAL);
    -	}
    -	if (start < 0)
    -		return (EINVAL);
    -	if (fl->l_len == 0)
    -		end = -1;
    -	else {
    -		end = start + fl->l_len - 1;
    -		if (end < start)
    -			return (EINVAL);
    -	}
    -#ifdef notyet
    -	switch (ap->a_op) {
    -	    case F_SETLK:
    -		error = lf_advlock(ap, &vp->v_lockf, size);
    -		break;
    -	    case F_UNLCK:
    -		lf_advlock(ap, &vp->v_lockf, size);
    -		break;
    -	    case F_GETLK:
    -		error = lf_advlock(ap, &vp->v_lockf, size);
    -		break;
    -	    default:
    -		return (EINVAL);
    -	}
    -#endif
    -	return (error);
    -}
    -
    -static int
    -_xfs_cachedlookup(
    -	struct vop_cachedlookup_args /* {
    -		struct vnode * a_dvp;
    -		struct vnode ** a_vpp;
    -		struct componentname * a_cnp;
    -	} */ *ap)
    -{
    -	struct vnode *dvp, *tvp;
    -	struct xfs_vnode *cvp;
    -	int islastcn;
    -	int error;
    -	struct vnode **vpp = ap->a_vpp;
    -	struct componentname *cnp = ap->a_cnp;
    -	struct ucred *cred = cnp->cn_cred;
    -	int flags = cnp->cn_flags;
    -	int nameiop = cnp->cn_nameiop;
    -	struct thread *td = cnp->cn_thread;
    -
    -	char *pname = cnp->cn_nameptr;
    -	int namelen = cnp->cn_namelen;
    -
    -	*vpp = NULL;
    -	dvp = ap->a_dvp;
    -	islastcn = flags & ISLASTCN;
    -
    -	XVOP_LOOKUP(VPTOXFSVP(dvp), cnp, &cvp, 0, NULL, cred, error);
    -
    -	if (error == ENOENT) {
    -		if ((nameiop == CREATE || nameiop == RENAME ||
    -		     nameiop == DELETE) && islastcn)
    -		{
    -			error = VOP_ACCESS(dvp, VWRITE, cred, td);
    -			if (error)
    -				return (error);
    -			cnp->cn_flags |= SAVENAME;
    -			return (EJUSTRETURN);
    -		}
    -		if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE)
    -			cache_enter(dvp, *vpp, cnp);
    -		return (error);
    -	}
    -	if (error)
    -		return (error);
    -
    -	tvp = cvp->v_vnode;
    -
    -	if (nameiop == DELETE && islastcn) {
    -		if ((error = vn_lock(tvp, LK_EXCLUSIVE))) {
    -			vrele(tvp);
    -			goto err_out;
    -		}
    -		*vpp = tvp;
    -
    -		/* Directory should be writable for deletes. */
    -	        error = VOP_ACCESS(dvp, VWRITE, cred, td);
    -         	if (error)
    -		 	goto err_out;
    -
    -		/* XXXKAN: Permission checks for sticky dirs? */
    -		return (0);
    -	 }
    -
    -	if (nameiop == RENAME && islastcn) {
    -		if ((error = vn_lock(tvp, LK_EXCLUSIVE))) {
    -			vrele(tvp);
    -			goto err_out;
    -		}
    -		*vpp = tvp;
    -
    -		if ((error = VOP_ACCESS(dvp, VWRITE, cred, td)))
    -			goto err_out;
    -		return (0);
    -	}
    -
    -	if (flags & ISDOTDOT) {
    -		VOP_UNLOCK(dvp, 0);
    -		error = vn_lock(tvp, cnp->cn_lkflags);
    -		if (error) {
    -			vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
    -			vrele(tvp);
    -			goto err_out;
    -		}
    -		*vpp = tvp;
    -	} else if (namelen == 1 && pname[0] == '.') {
    -		*vpp = tvp;
    -		KASSERT(tvp == dvp, ("not same directory"));
    -	} else {
    -		if ((error = vn_lock(tvp, cnp->cn_lkflags))) {
    -			vrele(tvp);
    -			goto err_out;
    -		}
    -		*vpp = tvp;
    -	}
    -
    -	if (cnp->cn_flags & MAKEENTRY)
    -		cache_enter(dvp, *vpp, cnp);
    -	return (0);
    -
    -err_out:
    -	if (*vpp != 0)
    -		vput(*vpp);
    -	return (error);
    -}
    -
    -static int
    -_xfs_reclaim(
    -	struct vop_reclaim_args /* {
    -		struct vnode *a_vp;
    -		struct thread  *a_td;
    -	} */ *ap)
    -{
    -
    -	struct vnode *vp = ap->a_vp;
    -	struct xfs_vnode *xfs_vp = VPTOXFSVP(vp);
    -	int error;
    -
    -	XVOP_RECLAIM(xfs_vp, error);
    -	kmem_free(xfs_vp, sizeof(*xfs_vp));
    -	vp->v_data = NULL;
    -	return (error);
    -}
    -
    -static int
    -_xfs_kqfilter(
    -	struct vop_kqfilter_args /* {
    -		struct vnodeop_desc *a_desc;
    -		struct vnode *a_vp;
    -		struct knote *a_kn;
    -	} */ *ap)
    -{
    -	return (0);
    -}
    -
    -struct xfs_inode *
    -xfs_vtoi(struct xfs_vnode *xvp)
    -{
    -	return(XFS_BHVTOI(xvp->v_fbhv));
    -}
    -
    -/*
    - * Read wrapper for fifos.
    - */
    -static int
    -_xfsfifo_read(
    -	struct vop_read_args /* {
    -		struct vnode *a_vp;
    -		struct uio *a_uio;
    -		int  a_ioflag;
    -		struct ucred *a_cred;
    -	} */ *ap)
    -{
    -	int error, resid;
    -	struct xfs_inode *ip;
    -	struct uio *uio;
    -
    -	uio = ap->a_uio;
    -	resid = uio->uio_resid;
    -	error = fifo_specops.vop_read(ap);
    -	ip = xfs_vtoi(VPTOXFSVP(ap->a_vp));
    -	if ((ap->a_vp->v_mount->mnt_flag & MNT_NOATIME) == 0 && ip != NULL &&
    -	    (uio->uio_resid != resid || (error == 0 && resid != 0)))
    -		xfs_ichgtime(ip, XFS_ICHGTIME_ACC);
    -	return (error);
    -}
    -
    -/*
    - * Write wrapper for fifos.
    - */
    -static int
    -_xfsfifo_write(
    -	struct vop_write_args /* {
    -		struct vnode *a_vp;
    -		struct uio *a_uio;
    -		int  a_ioflag;
    -		struct ucred *a_cred;
    -	} */ *ap)
    -{
    -	int error, resid;
    -	struct uio *uio;
    -	struct xfs_inode *ip;
    -
    -	uio = ap->a_uio;
    -	resid = uio->uio_resid;
    -	error = fifo_specops.vop_write(ap);
    -	ip = xfs_vtoi(VPTOXFSVP(ap->a_vp));
    -	if (ip != NULL && (uio->uio_resid != resid ||
    -	    (error == 0 && resid != 0)))
    -		xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
    -	return (error);
    -}
    -
    -/*
    - * Close wrapper for fifos.
    - *
    - * Update the times on the inode then do device close.
    - */
    -static int
    -_xfsfifo_close(
    -	struct vop_close_args /* {
    -		struct vnode *a_vp;
    -		int  a_fflag;
    -		struct ucred *a_cred;
    -		struct thread *a_td;
    -	} */ *ap)
    -{
    -
    -	return (fifo_specops.vop_close(ap));
    -}
    -
    -/*
    - * Kqfilter wrapper for fifos.
    - *
    - * Fall through to ufs kqfilter routines if needed
    - */
    -static int
    -_xfsfifo_kqfilter(
    -	struct vop_kqfilter_args /* {
    -		struct vnodeop_desc *a_desc;
    -		struct vnode *a_vp;
    -		struct knote *a_kn;
    -	} */ *ap)
    -{
    -	int error;
    -
    -	error = fifo_specops.vop_kqfilter(ap);
    -	if (error)
    -		error = _xfs_kqfilter(ap);
    -	return (error);
    -}
    -
    -static int
    -_xfs_getextattr(
    -	struct vop_getextattr_args /* {
    -		struct vnode *a_vp;
    -		int a_attrnamespace;
    -		const char *a_name;
    -		struct uio *a_uio;
    -		size_t *a_size;
    -		struct ucred *a_cred;
    -		struct thread *a_td;
    -	} */ *ap)
    -{
    -	int error;
    -	char *value;
    -	int size;
    -
    -	error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace,
    -	    ap->a_cred, ap->a_td, VREAD);
    -        if (error)
    -		return (error);
    -
    -	size = ATTR_MAX_VALUELEN;
    -	value = (char *)kmem_zalloc(size, KM_SLEEP);
    -	if (value == NULL)
    -		return (ENOMEM);
    -
    -	XVOP_ATTR_GET(VPTOXFSVP(ap->a_vp), ap->a_name, value, &size, 1,
    -	    ap->a_cred, error);
    -
    -	if (ap->a_uio != NULL) {
    -		if (ap->a_uio->uio_iov->iov_len < size)
    -			error = ERANGE;
    -		else
    -			uiomove(value, size, ap->a_uio);
    -	}
    -
    -	if (ap->a_size != NULL)
    -		*ap->a_size = size;
    -
    -	kmem_free(value, ATTR_MAX_VALUELEN);
    -	return (error);
    -}		
    -
    -static int
    -_xfs_listextattr(
    -	struct vop_listextattr_args /* {
    -		struct vnode *a_vp;
    -		int a_attrnamespace;
    -		struct uio *a_uio;
    -		size_t *a_size;
    -		struct ucred *a_cred;
    -		struct thread *a_td;
    -	} */ *ap)
    -{
    -	int error;
    -	char *buf = NULL;
    -	int buf_len = 0;
    -	attrlist_cursor_kern_t  cursor = { 0 };
    -	int i;
    -	char name_len;
    -	int attrnames_len = 0;
    -	int xfs_flags = ATTR_KERNAMELS;
    -
    -	error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace,
    -	    ap->a_cred, ap->a_td, VREAD);
    -        if (error)
    -		return (error);
    -
    -	if (ap->a_attrnamespace & EXTATTR_NAMESPACE_USER)
    -		xfs_flags |= ATTR_KERNORMALS;
    -
    -	if (ap->a_attrnamespace & EXTATTR_NAMESPACE_SYSTEM)
    -		xfs_flags |= ATTR_KERNROOTLS;
    -
    -	if (ap->a_uio == NULL || ap->a_uio->uio_iov[0].iov_base == NULL) {
    -		xfs_flags |= ATTR_KERNOVAL;
    -		buf_len = 0;
    -	} else {
    -		buf = ap->a_uio->uio_iov[0].iov_base;
    -		buf_len = ap->a_uio->uio_iov[0].iov_len;
    -	}
    -
    -	XVOP_ATTR_LIST(VPTOXFSVP(ap->a_vp), buf, buf_len, xfs_flags,
    -		    &cursor, ap->a_cred, error);
    -	if (error < 0) {
    -		attrnames_len = -error;
    -		error = 0;
    -	}
    -	if (buf == NULL)
    -		goto done;
    -
    -	/*
    -	 * extattr_list expects a list of names.  Each list
    -	 * entry consists of one byte for the name length, followed
    -	 * by the name (not null terminated)
    -	 */
    -	name_len=0;
    -	for(i=attrnames_len-1; i > 0 ; --i) {
    -		buf[i] = buf[i-1];
    -		if (buf[i])
    -			++name_len;
    -		else {
    -			buf[i] = name_len;
    -			name_len = 0;
    -		}
    -	} 
    -	buf[0] = name_len;
    -
    -	if (ap->a_uio != NULL)
    -		ap->a_uio->uio_resid -= attrnames_len;
    -
    -done:
    -	if (ap->a_size != NULL)
    -		*ap->a_size = attrnames_len;
    -
    -	return (error);
    -}
    -
    -static int
    -_xfs_setextattr(struct vop_setextattr_args *ap)
    -/*
    -vop_setextattr {
    -	IN struct vnode *a_vp;
    -	IN int a_attrnamespace;
    -	IN const char *a_name;
    -	INOUT struct uio *a_uio;
    -	IN struct ucred *a_cred;
    -	IN struct thread *a_td;
    -};
    -*/
    -{
    -	char *val;
    -	size_t vallen;
    -	int error, xfs_flags;
    -
    -	if (ap->a_vp->v_type == VCHR)
    -		return (EOPNOTSUPP);
    -
    -	if (ap->a_uio == NULL)
    -		return (EINVAL);
    -	vallen = ap->a_uio->uio_resid;
    -	if (vallen > ATTR_MAX_VALUELEN)
    -		return (EOVERFLOW);
    -
    -	if (ap->a_name[0] == '\0')
    -		return (EINVAL);
    -
    -	error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace,
    -	    ap->a_cred, ap->a_td, VWRITE);
    -	if (error)
    -		return (error);
    -
    -	xfs_flags = 0;
    -	if (ap->a_attrnamespace & EXTATTR_NAMESPACE_USER)
    -		xfs_flags |= ATTR_KERNORMALS;
    -	if (ap->a_attrnamespace & EXTATTR_NAMESPACE_SYSTEM)
    -		xfs_flags |= ATTR_KERNROOTLS;
    -
    -	val = (char *)kmem_zalloc(vallen, KM_SLEEP);
    -	if (val == NULL)
    -		return (ENOMEM);
    -	error = uiomove(val, (int)vallen, ap->a_uio);
    -	if (error)
    -		goto err_out;
    -
    -	XVOP_ATTR_SET(VPTOXFSVP(ap->a_vp), ap->a_name, val, vallen, xfs_flags,
    -	    ap->a_cred, error);
    -err_out:
    -	kmem_free(val, vallen);
    -	return(error);
    -}
    -
    -static int
    -_xfs_deleteextattr(struct vop_deleteextattr_args *ap)
    -/*
    -vop_deleteextattr {
    -	IN struct vnode *a_vp;
    -	IN int a_attrnamespace;
    -	IN const char *a_name;
    -	IN struct ucred *a_cred;
    -	IN struct thread *a_td;
    -};
    -*/
    -{
    -	int error, xfs_flags;
    -
    -	if (ap->a_vp->v_type == VCHR)
    -		return (EOPNOTSUPP);
    -
    -	if (ap->a_name[0] == '\0')
    -		return (EINVAL);
    -
    -	error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace,
    -	    ap->a_cred, ap->a_td, VWRITE);
    -	if (error)
    -		return (error);
    -
    -	xfs_flags = 0;
    -	if (ap->a_attrnamespace & EXTATTR_NAMESPACE_USER)
    -		xfs_flags |= ATTR_KERNORMALS;
    -	if (ap->a_attrnamespace & EXTATTR_NAMESPACE_SYSTEM)
    -		xfs_flags |= ATTR_KERNROOTLS;
    -
    -	XVOP_ATTR_REMOVE(VPTOXFSVP(ap->a_vp), ap->a_name, xfs_flags,
    -	    ap->a_cred, error);
    -	return (error);
    -}
    -
    -static int
    -_xfs_vptofh(struct vop_vptofh_args *ap)
    -/*
    -vop_vptofh {
    -	IN struct vnode *a_vp;
    -	IN struct fid *a_fhp;
    -};
    -*/
    -{
    -	printf("xfs_vptofh");
    -	return ENOSYS;
    -}
    diff --git a/sys/gnu/fs/xfs/xfs.h b/sys/gnu/fs/xfs/xfs.h
    deleted file mode 100644
    index 0db97bb8e52..00000000000
    --- a/sys/gnu/fs/xfs/xfs.h
    +++ /dev/null
    @@ -1,23 +0,0 @@
    -
    -/*
    - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_H__
    -#define __XFS_H__
    -
    -#include 
    -#endif	/* __XFS_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_acl.c b/sys/gnu/fs/xfs/xfs_acl.c
    deleted file mode 100644
    index 9e70eb1103a..00000000000
    --- a/sys/gnu/fs/xfs/xfs_acl.c
    +++ /dev/null
    @@ -1,928 +0,0 @@
    -/*
    - * Copyright (c) 2001-2002,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_inum.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_btree.h"
    -#include "xfs_acl.h"
    -#include "xfs_mac.h"
    -#include "xfs_attr.h"
    -
    -#include 
    -#include 
    -
    -STATIC int	xfs_acl_setmode(xfs_vnode_t *, xfs_acl_t *, int *);
    -STATIC void     xfs_acl_filter_mode(mode_t, xfs_acl_t *);
    -STATIC void	xfs_acl_get_endian(xfs_acl_t *);
    -STATIC int	xfs_acl_access(uid_t, gid_t, xfs_acl_t *, mode_t, cred_t *);
    -STATIC int	xfs_acl_invalid(xfs_acl_t *);
    -STATIC void	xfs_acl_sync_mode(mode_t, xfs_acl_t *);
    -STATIC void	xfs_acl_get_attr(xfs_vnode_t *, xfs_acl_t *, int, int, int *);
    -STATIC void	xfs_acl_set_attr(xfs_vnode_t *, xfs_acl_t *, int, int *);
    -STATIC int	xfs_acl_allow_set(xfs_vnode_t *, int);
    -
    -kmem_zone_t *xfs_acl_zone;
    -
    -
    -/*
    - * Test for existence of access ACL attribute as efficiently as possible.
    - */
    -int
    -xfs_acl_vhasacl_access(
    -	xfs_vnode_t		*vp)
    -{
    -	int		error;
    -
    -	xfs_acl_get_attr(vp, NULL, _ACL_TYPE_ACCESS, ATTR_KERNOVAL, &error);
    -	return (error == 0);
    -}
    -
    -/*
    - * Test for existence of default ACL attribute as efficiently as possible.
    - */
    -int
    -xfs_acl_vhasacl_default(
    -	xfs_vnode_t		*vp)
    -{
    -	int		error;
    -
    -	if (!VN_ISDIR(vp))
    -		return 0;
    -	xfs_acl_get_attr(vp, NULL, _ACL_TYPE_DEFAULT, ATTR_KERNOVAL, &error);
    -	return (error == 0);
    -}
    -
    -/*
    - * Convert from extended attribute representation to in-memory for XFS.
    - */
    -STATIC int
    -posix_acl_xattr_to_xfs(
    -	posix_acl_xattr_header	*src,
    -	size_t			size,
    -	xfs_acl_t		*dest)
    -{
    -	posix_acl_xattr_entry	*src_entry;
    -	xfs_acl_entry_t		*dest_entry;
    -	int			n;
    -
    -	if (!src || !dest)
    -		return EINVAL;
    -
    -	if (size < sizeof(posix_acl_xattr_header))
    -		return EINVAL;
    -
    -	if (src->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION))
    -		return EOPNOTSUPP;
    -
    -	memset(dest, 0, sizeof(xfs_acl_t));
    -	dest->acl_cnt = posix_acl_xattr_count(size);
    -	if (dest->acl_cnt < 0 || dest->acl_cnt > XFS_ACL_MAX_ENTRIES)
    -		return EINVAL;
    -
    -	/*
    -	 * acl_set_file(3) may request that we set default ACLs with
    -	 * zero length -- defend (gracefully) against that here.
    -	 */
    -	if (!dest->acl_cnt)
    -		return 0;
    -
    -	src_entry = (posix_acl_xattr_entry *)((char *)src + sizeof(*src));
    -	dest_entry = &dest->acl_entry[0];
    -
    -	for (n = 0; n < dest->acl_cnt; n++, src_entry++, dest_entry++) {
    -		dest_entry->ae_perm = le16_to_cpu(src_entry->e_perm);
    -		if (_ACL_PERM_INVALID(dest_entry->ae_perm))
    -			return EINVAL;
    -		dest_entry->ae_tag  = le16_to_cpu(src_entry->e_tag);
    -		switch(dest_entry->ae_tag) {
    -		case ACL_USER:
    -		case ACL_GROUP:
    -			dest_entry->ae_id = le32_to_cpu(src_entry->e_id);
    -			break;
    -		case ACL_USER_OBJ:
    -		case ACL_GROUP_OBJ:
    -		case ACL_MASK:
    -		case ACL_OTHER:
    -			dest_entry->ae_id = ACL_UNDEFINED_ID;
    -			break;
    -		default:
    -			return EINVAL;
    -		}
    -	}
    -	if (xfs_acl_invalid(dest))
    -		return EINVAL;
    -
    -	return 0;
    -}
    -
    -/*
    - * Comparison function called from xfs_sort().
    - * Primary key is ae_tag, secondary key is ae_id.
    - */
    -STATIC int
    -xfs_acl_entry_compare(
    -	const void	*va,
    -	const void	*vb)
    -{
    -	xfs_acl_entry_t	*a = (xfs_acl_entry_t *)va,
    -			*b = (xfs_acl_entry_t *)vb;
    -
    -	if (a->ae_tag == b->ae_tag)
    -		return (a->ae_id - b->ae_id);
    -	return (a->ae_tag - b->ae_tag);
    -}
    -
    -/*
    - * Convert from in-memory XFS to extended attribute representation.
    - */
    -STATIC int
    -posix_acl_xfs_to_xattr(
    -	xfs_acl_t		*src,
    -	posix_acl_xattr_header	*dest,
    -	size_t			size)
    -{
    -	int			n;
    -	size_t			new_size = posix_acl_xattr_size(src->acl_cnt);
    -	posix_acl_xattr_entry	*dest_entry;
    -	xfs_acl_entry_t		*src_entry;
    -
    -	if (size < new_size)
    -		return -ERANGE;
    -
    -	/* Need to sort src XFS ACL by  */
    -	xfs_sort(src->acl_entry, src->acl_cnt, sizeof(src->acl_entry[0]),
    -		 xfs_acl_entry_compare);
    -
    -	dest->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
    -	dest_entry = &dest->a_entries[0];
    -	src_entry = &src->acl_entry[0];
    -	for (n = 0; n < src->acl_cnt; n++, dest_entry++, src_entry++) {
    -		dest_entry->e_perm = cpu_to_le16(src_entry->ae_perm);
    -		if (_ACL_PERM_INVALID(src_entry->ae_perm))
    -			return -EINVAL;
    -		dest_entry->e_tag  = cpu_to_le16(src_entry->ae_tag);
    -		switch (src_entry->ae_tag) {
    -		case ACL_USER:
    -		case ACL_GROUP:
    -			dest_entry->e_id = cpu_to_le32(src_entry->ae_id);
    -				break;
    -		case ACL_USER_OBJ:
    -		case ACL_GROUP_OBJ:
    -		case ACL_MASK:
    -		case ACL_OTHER:
    -			dest_entry->e_id = cpu_to_le32(ACL_UNDEFINED_ID);
    -			break;
    -		default:
    -			return -EINVAL;
    -		}
    -	}
    -	return new_size;
    -}
    -
    -int
    -xfs_acl_vget(
    -	xfs_vnode_t		*vp,
    -	void		*acl,
    -	size_t		size,
    -	int		kind)
    -{
    -	int			error;
    -	xfs_acl_t		*xfs_acl = NULL;
    -	posix_acl_xattr_header	*ext_acl = acl;
    -	int			flags = 0;
    -
    -	VN_HOLD(vp);
    -	if(size) {
    -		if (!(_ACL_ALLOC(xfs_acl))) {
    -			error = ENOMEM;
    -			goto out;
    -		}
    -		memset(xfs_acl, 0, sizeof(xfs_acl_t));
    -	} else
    -		flags = ATTR_KERNOVAL;
    -
    -	xfs_acl_get_attr(vp, xfs_acl, kind, flags, &error);
    -	if (error)
    -		goto out;
    -
    -	if (!size) {
    -		error = -posix_acl_xattr_size(XFS_ACL_MAX_ENTRIES);
    -	} else {
    -		if (xfs_acl_invalid(xfs_acl)) {
    -			error = EINVAL;
    -			goto out;
    -		}
    -		if (kind == _ACL_TYPE_ACCESS) {
    -			xfs_vattr_t	va;
    -
    -			va.va_mask = XFS_AT_MODE;
    -			XVOP_GETATTR(vp, &va, 0, sys_cred, error);
    -			if (error)
    -				goto out;
    -			xfs_acl_sync_mode(va.va_mode, xfs_acl);
    -		}
    -		error = -posix_acl_xfs_to_xattr(xfs_acl, ext_acl, size);
    -	}
    -out:
    -	VN_RELE(vp);
    -	if(xfs_acl)
    -		_ACL_FREE(xfs_acl);
    -	return -error;
    -}
    -
    -int
    -xfs_acl_vremove(
    -	xfs_vnode_t		*vp,
    -	int		kind)
    -{
    -	int		error;
    -
    -	VN_HOLD(vp);
    -	error = xfs_acl_allow_set(vp, kind);
    -	if (!error) {
    -		XVOP_ATTR_REMOVE(vp, kind == _ACL_TYPE_DEFAULT?
    -				SGI_ACL_DEFAULT: SGI_ACL_FILE,
    -				ATTR_ROOT, sys_cred, error);
    -		if (error == ENOATTR)
    -			error = 0;	/* 'scool */
    -	}
    -	VN_RELE(vp);
    -	return -error;
    -}
    -
    -int
    -xfs_acl_vset(
    -	xfs_vnode_t			*vp,
    -	void			*acl,
    -	size_t			size,
    -	int			kind)
    -{
    -	posix_acl_xattr_header	*ext_acl = acl;
    -	xfs_acl_t		*xfs_acl;
    -	int			error;
    -	int			basicperms = 0; /* more than std unix perms? */
    -
    -	if (!acl)
    -		return -EINVAL;
    -
    -	if (!(_ACL_ALLOC(xfs_acl)))
    -		return -ENOMEM;
    -
    -	error = posix_acl_xattr_to_xfs(ext_acl, size, xfs_acl);
    -	if (error) {
    -		_ACL_FREE(xfs_acl);
    -		return -error;
    -	}
    -	if (!xfs_acl->acl_cnt) {
    -		_ACL_FREE(xfs_acl);
    -		return 0;
    -	}
    -
    -	VN_HOLD(vp);
    -	error = xfs_acl_allow_set(vp, kind);
    -	if (error)
    -		goto out;
    -
    -	/* Incoming ACL exists, set file mode based on its value */
    -	if (kind == _ACL_TYPE_ACCESS)
    -		xfs_acl_setmode(vp, xfs_acl, &basicperms);
    -
    -	/*
    -	 * If we have more than std unix permissions, set up the actual attr.
    -	 * Otherwise, delete any existing attr.  This prevents us from
    -	 * having actual attrs for permissions that can be stored in the
    -	 * standard permission bits.
    -	 */
    -	if (!basicperms) {
    -		xfs_acl_set_attr(vp, xfs_acl, kind, &error);
    -	} else {
    -		xfs_acl_vremove(vp, _ACL_TYPE_ACCESS);
    -	}
    -
    -out:
    -	VN_RELE(vp);
    -	_ACL_FREE(xfs_acl);
    -	return -error;
    -}
    -
    -int
    -xfs_acl_iaccess(
    -	xfs_inode_t	*ip,
    -	mode_t		mode,
    -	cred_t		*cr)
    -{
    -	xfs_acl_t	*acl;
    -	int		rval;
    -
    -	if (!(_ACL_ALLOC(acl)))
    -		return -1;
    -
    -	/* If the file has no ACL return -1. */
    -	rval = sizeof(xfs_acl_t);
    -	if (xfs_attr_fetch(ip, SGI_ACL_FILE, SGI_ACL_FILE_SIZE,
    -			(char *)acl, &rval, ATTR_ROOT | ATTR_KERNACCESS, cr)) {
    -		_ACL_FREE(acl);
    -		return -1;
    -	}
    -	xfs_acl_get_endian(acl);
    -
    -	/* If the file has an empty ACL return -1. */
    -	if (acl->acl_cnt == XFS_ACL_NOT_PRESENT) {
    -		_ACL_FREE(acl);
    -		return -1;
    -	}
    -
    -	/* Synchronize ACL with mode bits */
    -	xfs_acl_sync_mode(ip->i_d.di_mode, acl);
    -
    -	rval = xfs_acl_access(ip->i_d.di_uid, ip->i_d.di_gid, acl, mode, cr);
    -	_ACL_FREE(acl);
    -	return rval;
    -}
    -
    -STATIC int
    -xfs_acl_allow_set(
    -	xfs_vnode_t		*vp,
    -	int		kind)
    -{
    -	xfs_vattr_t	va;
    -	int		error;
    -
    -	if (vp->v_inode.i_flags & (S_IMMUTABLE|S_APPEND))
    -		return EPERM;
    -	if (kind == _ACL_TYPE_DEFAULT && !VN_ISDIR(vp))
    -		return ENOTDIR;
    -	if (vp->v_vfsp->vfs_flag & VFS_RDONLY)
    -		return EROFS;
    -	va.va_mask = XFS_AT_UID;
    -	XVOP_GETATTR(vp, &va, 0, NULL, error);
    -	if (error)
    -		return error;
    -	if (va.va_uid != current->fsuid && !capable(CAP_FOWNER))
    -		return EPERM;
    -	return error;
    -}
    -
    -/*
    - * The access control process to determine the access permission:
    - *	if uid == file owner id, use the file owner bits.
    - *	if gid == file owner group id, use the file group bits.
    - *	scan ACL for a matching user or group, and use matched entry
    - *	permission. Use total permissions of all matching group entries,
    - *	until all acl entries are exhausted. The final permission produced
    - *	by matching acl entry or entries needs to be & with group permission.
    - *	if not owner, owning group, or matching entry in ACL, use file
    - *	other bits.  
    - */
    -STATIC int
    -xfs_acl_capability_check(
    -	mode_t		mode,
    -	cred_t		*cr)
    -{
    -	if ((mode & ACL_READ) && !capable_cred(cr, CAP_DAC_READ_SEARCH))
    -		return EACCES;
    -	if ((mode & ACL_WRITE) && !capable_cred(cr, CAP_DAC_OVERRIDE))
    -		return EACCES;
    -	if ((mode & ACL_EXECUTE) && !capable_cred(cr, CAP_DAC_OVERRIDE))
    -		return EACCES;
    -
    -	return 0;
    -}
    -
    -/*
    - * Note: cr is only used here for the capability check if the ACL test fails.
    - *       It is not used to find out the credentials uid or groups etc, as was
    - *       done in IRIX. It is assumed that the uid and groups for the current
    - *       thread are taken from "current" instead of the cr parameter.
    - */
    -STATIC int
    -xfs_acl_access(
    -	uid_t		fuid,
    -	gid_t		fgid,
    -	xfs_acl_t	*fap,
    -	mode_t		md,
    -	cred_t		*cr)
    -{
    -	xfs_acl_entry_t	matched;
    -	int		i, allows;
    -	int		maskallows = -1;	/* true, but not 1, either */
    -	int		seen_userobj = 0;
    -
    -	matched.ae_tag = 0;	/* Invalid type */
    -	matched.ae_perm = 0;
    -	md >>= 6;	/* Normalize the bits for comparison */
    -
    -	for (i = 0; i < fap->acl_cnt; i++) {
    -		/*
    -		 * Break out if we've got a user_obj entry or
    -		 * a user entry and the mask (and have processed USER_OBJ)
    -		 */
    -		if (matched.ae_tag == ACL_USER_OBJ)
    -			break;
    -		if (matched.ae_tag == ACL_USER) {
    -			if (maskallows != -1 && seen_userobj)
    -				break;
    -			if (fap->acl_entry[i].ae_tag != ACL_MASK &&
    -			    fap->acl_entry[i].ae_tag != ACL_USER_OBJ)
    -				continue;
    -		}
    -		/* True if this entry allows the requested access */
    -		allows = ((fap->acl_entry[i].ae_perm & md) == md);
    -
    -		switch (fap->acl_entry[i].ae_tag) {
    -		case ACL_USER_OBJ:
    -			seen_userobj = 1;
    -			if (fuid != current->fsuid)
    -				continue;
    -			matched.ae_tag = ACL_USER_OBJ;
    -			matched.ae_perm = allows;
    -			break;
    -		case ACL_USER:
    -			if (fap->acl_entry[i].ae_id != current->fsuid)
    -				continue;
    -			matched.ae_tag = ACL_USER;
    -			matched.ae_perm = allows;
    -			break;
    -		case ACL_GROUP_OBJ:
    -			if ((matched.ae_tag == ACL_GROUP_OBJ ||
    -			    matched.ae_tag == ACL_GROUP) && !allows)
    -				continue;
    -			if (!in_group_p(fgid))
    -				continue;
    -			matched.ae_tag = ACL_GROUP_OBJ;
    -			matched.ae_perm = allows;
    -			break;
    -		case ACL_GROUP:
    -			if ((matched.ae_tag == ACL_GROUP_OBJ ||
    -			    matched.ae_tag == ACL_GROUP) && !allows)
    -				continue;
    -			if (!in_group_p(fap->acl_entry[i].ae_id))
    -				continue;
    -			matched.ae_tag = ACL_GROUP;
    -			matched.ae_perm = allows;
    -			break;
    -		case ACL_MASK:
    -			maskallows = allows;
    -			break;
    -		case ACL_OTHER:
    -			if (matched.ae_tag != 0)
    -				continue;
    -			matched.ae_tag = ACL_OTHER;
    -			matched.ae_perm = allows;
    -			break;
    -		}
    -	}
    -	/*
    -	 * First possibility is that no matched entry allows access.
    -	 * The capability to override DAC may exist, so check for it.
    -	 */
    -	switch (matched.ae_tag) {
    -	case ACL_OTHER:
    -	case ACL_USER_OBJ:
    -		if (matched.ae_perm)
    -			return 0;
    -		break;
    -	case ACL_USER:
    -	case ACL_GROUP_OBJ:
    -	case ACL_GROUP:
    -		if (maskallows && matched.ae_perm)
    -			return 0;
    -		break;
    -	case 0:
    -		break;
    -	}
    -
    -	return xfs_acl_capability_check(md, cr);
    -}
    -
    -/*
    - * ACL validity checker.
    - *   This acl validation routine checks each ACL entry read in makes sense.
    - */
    -STATIC int
    -xfs_acl_invalid(
    -	xfs_acl_t	*aclp)
    -{
    -	xfs_acl_entry_t	*entry, *e;
    -	int		user = 0, group = 0, other = 0, mask = 0;
    -	int		mask_required = 0;
    -	int		i, j;
    -
    -	if (!aclp)
    -		goto acl_invalid;
    -
    -	if (aclp->acl_cnt > XFS_ACL_MAX_ENTRIES)
    -		goto acl_invalid;
    -
    -	for (i = 0; i < aclp->acl_cnt; i++) {
    -		entry = &aclp->acl_entry[i];
    -		switch (entry->ae_tag) {
    -		case ACL_USER_OBJ:
    -			if (user++)
    -				goto acl_invalid;
    -			break;
    -		case ACL_GROUP_OBJ:
    -			if (group++)
    -				goto acl_invalid;
    -			break;
    -		case ACL_OTHER:
    -			if (other++)
    -				goto acl_invalid;
    -			break;
    -		case ACL_USER:
    -		case ACL_GROUP:
    -			for (j = i + 1; j < aclp->acl_cnt; j++) {
    -				e = &aclp->acl_entry[j];
    -				if (e->ae_id == entry->ae_id &&
    -				    e->ae_tag == entry->ae_tag)
    -					goto acl_invalid;
    -			}
    -			mask_required++;
    -			break;
    -		case ACL_MASK:
    -			if (mask++)
    -				goto acl_invalid;
    -			break;
    -		default:
    -			goto acl_invalid;
    -		}
    -	}
    -	if (!user || !group || !other || (mask_required && !mask))
    -		goto acl_invalid;
    -	else
    -		return 0;
    -acl_invalid:
    -	return EINVAL;
    -}
    -
    -/*
    - * Do ACL endian conversion.
    - */
    -STATIC void
    -xfs_acl_get_endian(
    -	xfs_acl_t	*aclp)
    -{
    -	xfs_acl_entry_t	*ace, *end;
    -
    -	INT_SET(aclp->acl_cnt, ARCH_CONVERT, aclp->acl_cnt);
    -	end = &aclp->acl_entry[0]+aclp->acl_cnt;
    -	for (ace = &aclp->acl_entry[0]; ace < end; ace++) {
    -		INT_SET(ace->ae_tag, ARCH_CONVERT, ace->ae_tag);
    -		INT_SET(ace->ae_id, ARCH_CONVERT, ace->ae_id);
    -		INT_SET(ace->ae_perm, ARCH_CONVERT, ace->ae_perm);
    -	}
    -}
    -
    -/*
    - * Get the ACL from the EA and do endian conversion.
    - */
    -STATIC void
    -xfs_acl_get_attr(
    -	xfs_vnode_t		*vp,
    -	xfs_acl_t	*aclp,
    -	int		kind,
    -	int		flags,
    -	int		*error)
    -{
    -	int		len = sizeof(xfs_acl_t);
    -
    -	ASSERT((flags & ATTR_KERNOVAL) ? (aclp == NULL) : 1);
    -	flags |= ATTR_ROOT;
    -	XVOP_ATTR_GET(vp,
    -		kind == _ACL_TYPE_ACCESS ? SGI_ACL_FILE : SGI_ACL_DEFAULT,
    -		(char *)aclp, &len, flags, sys_cred, *error);
    -	if (*error || (flags & ATTR_KERNOVAL))
    -		return;
    -	xfs_acl_get_endian(aclp);
    -}
    -
    -/*
    - * Set the EA with the ACL and do endian conversion.
    - */
    -STATIC void
    -xfs_acl_set_attr(
    -	xfs_vnode_t		*vp,
    -	xfs_acl_t	*aclp,
    -	int		kind,
    -	int		*error)
    -{
    -	xfs_acl_entry_t	*ace, *newace, *end;
    -	xfs_acl_t	*newacl;
    -	int		len;
    -
    -	if (!(_ACL_ALLOC(newacl))) {
    -		*error = ENOMEM;
    -		return;
    -	}
    -
    -	len = sizeof(xfs_acl_t) -
    -	      (sizeof(xfs_acl_entry_t) * (XFS_ACL_MAX_ENTRIES - aclp->acl_cnt));
    -	end = &aclp->acl_entry[0]+aclp->acl_cnt;
    -	for (ace = &aclp->acl_entry[0], newace = &newacl->acl_entry[0];
    -	     ace < end;
    -	     ace++, newace++) {
    -		INT_SET(newace->ae_tag, ARCH_CONVERT, ace->ae_tag);
    -		INT_SET(newace->ae_id, ARCH_CONVERT, ace->ae_id);
    -		INT_SET(newace->ae_perm, ARCH_CONVERT, ace->ae_perm);
    -	}
    -	INT_SET(newacl->acl_cnt, ARCH_CONVERT, aclp->acl_cnt);
    -	XVOP_ATTR_SET(vp,
    -		kind == _ACL_TYPE_ACCESS ? SGI_ACL_FILE: SGI_ACL_DEFAULT,
    -		(char *)newacl, len, ATTR_ROOT, sys_cred, *error);
    -	_ACL_FREE(newacl);
    -}
    -
    -int
    -xfs_acl_vtoacl(
    -	xfs_vnode_t		*vp,
    -	xfs_acl_t	*access_acl,
    -	xfs_acl_t	*default_acl)
    -{
    -	xfs_vattr_t	va;
    -	int		error = 0;
    -
    -	if (access_acl) {
    -		/*
    -		 * Get the Access ACL and the mode.  If either cannot
    -		 * be obtained for some reason, invalidate the access ACL.
    -		 */
    -		xfs_acl_get_attr(vp, access_acl, _ACL_TYPE_ACCESS, 0, &error);
    -		if (!error) {
    -			/* Got the ACL, need the mode... */
    -			va.va_mask = XFS_AT_MODE;
    -			XVOP_GETATTR(vp, &va, 0, sys_cred, error);
    -		}
    -
    -		if (error)
    -			access_acl->acl_cnt = XFS_ACL_NOT_PRESENT;
    -		else /* We have a good ACL and the file mode, synchronize. */
    -			xfs_acl_sync_mode(va.va_mode, access_acl);
    -	}
    -
    -	if (default_acl) {
    -		xfs_acl_get_attr(vp, default_acl, _ACL_TYPE_DEFAULT, 0, &error);
    -		if (error)
    -			default_acl->acl_cnt = XFS_ACL_NOT_PRESENT;
    -	}
    -	return error;
    -}
    -
    -/*
    - * This function retrieves the parent directory's acl, processes it
    - * and lets the child inherit the acl(s) that it should.
    - */
    -int
    -xfs_acl_inherit(
    -	xfs_vnode_t	*vp,
    -	xfs_vattr_t	*vap,
    -	xfs_acl_t	*pdaclp)
    -{
    -	xfs_acl_t	*cacl;
    -	int		error = 0;
    -	int		basicperms = 0;
    -
    -	/*
    -	 * If the parent does not have a default ACL, or it's an
    -	 * invalid ACL, we're done.
    -	 */
    -	if (!vp)
    -		return 0;
    -	if (!pdaclp || xfs_acl_invalid(pdaclp))
    -		return 0;
    -
    -	/*
    -	 * Copy the default ACL of the containing directory to
    -	 * the access ACL of the new file and use the mode that
    -	 * was passed in to set up the correct initial values for
    -	 * the u::,g::[m::], and o:: entries.  This is what makes
    -	 * umask() "work" with ACL's.
    -	 */
    -
    -	if (!(_ACL_ALLOC(cacl)))
    -		return ENOMEM;
    -
    -	memcpy(cacl, pdaclp, sizeof(xfs_acl_t));
    -	xfs_acl_filter_mode(vap->va_mode, cacl);
    -	xfs_acl_setmode(vp, cacl, &basicperms);
    -
    -	/*
    -	 * Set the Default and Access ACL on the file.  The mode is already
    -	 * set on the file, so we don't need to worry about that.
    -	 *
    -	 * If the new file is a directory, its default ACL is a copy of
    -	 * the containing directory's default ACL.
    -	 */
    -	if (VN_ISDIR(vp))
    -		xfs_acl_set_attr(vp, pdaclp, _ACL_TYPE_DEFAULT, &error);
    -	if (!error && !basicperms)
    -		xfs_acl_set_attr(vp, cacl, _ACL_TYPE_ACCESS, &error);
    -	_ACL_FREE(cacl);
    -	return error;
    -}
    -
    -/*
    - * Set up the correct mode on the file based on the supplied ACL.  This
    - * makes sure that the mode on the file reflects the state of the
    - * u::,g::[m::], and o:: entries in the ACL.  Since the mode is where
    - * the ACL is going to get the permissions for these entries, we must
    - * synchronize the mode whenever we set the ACL on a file.
    - */
    -STATIC int
    -xfs_acl_setmode(
    -	xfs_vnode_t		*vp,
    -	xfs_acl_t	*acl,
    -	int		*basicperms)
    -{
    -	xfs_vattr_t	va;
    -	xfs_acl_entry_t	*ap;
    -	xfs_acl_entry_t	*gap = NULL;
    -	int		i, error, nomask = 1;
    -
    -	*basicperms = 1;
    -
    -	if (acl->acl_cnt == XFS_ACL_NOT_PRESENT)
    -		return 0;
    -
    -	/*
    -	 * Copy the u::, g::, o::, and m:: bits from the ACL into the
    -	 * mode.  The m:: bits take precedence over the g:: bits.
    -	 */
    -	va.va_mask = XFS_AT_MODE;
    -	XVOP_GETATTR(vp, &va, 0, sys_cred, error);
    -	if (error)
    -		return error;
    -
    -	va.va_mask = XFS_AT_MODE;
    -	va.va_mode &= ~(S_IRWXU|S_IRWXG|S_IRWXO);
    -	ap = acl->acl_entry;
    -	for (i = 0; i < acl->acl_cnt; ++i) {
    -		switch (ap->ae_tag) {
    -		case ACL_USER_OBJ:
    -			va.va_mode |= ap->ae_perm << 6;
    -			break;
    -		case ACL_GROUP_OBJ:
    -			gap = ap;
    -			break;
    -		case ACL_MASK:	/* more than just standard modes */
    -			nomask = 0;
    -			va.va_mode |= ap->ae_perm << 3;
    -			*basicperms = 0;
    -			break;
    -		case ACL_OTHER:
    -			va.va_mode |= ap->ae_perm;
    -			break;
    -		default:	/* more than just standard modes */
    -			*basicperms = 0;
    -			break;
    -		}
    -		ap++;
    -	}
    -
    -	/* Set the group bits from ACL_GROUP_OBJ if there's no ACL_MASK */
    -	if (gap && nomask)
    -		va.va_mode |= gap->ae_perm << 3;
    -
    -	XVOP_SETATTR(vp, &va, 0, sys_cred, error);
    -	return error;
    -}
    -
    -/*
    - * The permissions for the special ACL entries (u::, g::[m::], o::) are
    - * actually stored in the file mode (if there is both a group and a mask,
    - * the group is stored in the ACL entry and the mask is stored on the file).
    - * This allows the mode to remain automatically in sync with the ACL without
    - * the need for a call-back to the ACL system at every point where the mode
    - * could change.  This function takes the permissions from the specified mode
    - * and places it in the supplied ACL.
    - *
    - * This implementation draws its validity from the fact that, when the ACL
    - * was assigned, the mode was copied from the ACL.
    - * If the mode did not change, therefore, the mode remains exactly what was
    - * taken from the special ACL entries at assignment.
    - * If a subsequent chmod() was done, the POSIX spec says that the change in
    - * mode must cause an update to the ACL seen at user level and used for
    - * access checks.  Before and after a mode change, therefore, the file mode
    - * most accurately reflects what the special ACL entries should permit/deny.
    - *
    - * CAVEAT: If someone sets the SGI_ACL_FILE attribute directly,
    - *         the existing mode bits will override whatever is in the
    - *         ACL. Similarly, if there is a pre-existing ACL that was
    - *         never in sync with its mode (owing to a bug in 6.5 and
    - *         before), it will now magically (or mystically) be
    - *         synchronized.  This could cause slight astonishment, but
    - *         it is better than inconsistent permissions.
    - *
    - * The supplied ACL is a template that may contain any combination
    - * of special entries.  These are treated as place holders when we fill
    - * out the ACL.  This routine does not add or remove special entries, it
    - * simply unites each special entry with its associated set of permissions.
    - */
    -STATIC void
    -xfs_acl_sync_mode(
    -	mode_t		mode,
    -	xfs_acl_t	*acl)
    -{
    -	int		i, nomask = 1;
    -	xfs_acl_entry_t	*ap;
    -	xfs_acl_entry_t	*gap = NULL;
    -
    -	/*
    -	 * Set ACL entries. POSIX1003.1eD16 requires that the MASK
    -	 * be set instead of the GROUP entry, if there is a MASK.
    -	 */
    -	for (ap = acl->acl_entry, i = 0; i < acl->acl_cnt; ap++, i++) {
    -		switch (ap->ae_tag) {
    -		case ACL_USER_OBJ:
    -			ap->ae_perm = (mode >> 6) & 0x7;
    -			break;
    -		case ACL_GROUP_OBJ:
    -			gap = ap;
    -			break;
    -		case ACL_MASK:
    -			nomask = 0;
    -			ap->ae_perm = (mode >> 3) & 0x7;
    -			break;
    -		case ACL_OTHER:
    -			ap->ae_perm = mode & 0x7;
    -			break;
    -		default:
    -			break;
    -		}
    -	}
    -	/* Set the ACL_GROUP_OBJ if there's no ACL_MASK */
    -	if (gap && nomask)
    -		gap->ae_perm = (mode >> 3) & 0x7;
    -}
    -
    -/*
    - * When inheriting an Access ACL from a directory Default ACL,
    - * the ACL bits are set to the intersection of the ACL default
    - * permission bits and the file permission bits in mode. If there
    - * are no permission bits on the file then we must not give them
    - * the ACL. This is what what makes umask() work with ACLs.
    - */
    -STATIC void
    -xfs_acl_filter_mode(
    -	mode_t		mode,
    -	xfs_acl_t	*acl)
    -{
    -	int		i, nomask = 1;
    -	xfs_acl_entry_t	*ap;
    -	xfs_acl_entry_t	*gap = NULL;
    -
    -	/*
    -	 * Set ACL entries. POSIX1003.1eD16 requires that the MASK
    -	 * be merged with GROUP entry, if there is a MASK.
    -	 */
    -	for (ap = acl->acl_entry, i = 0; i < acl->acl_cnt; ap++, i++) {
    -		switch (ap->ae_tag) {
    -		case ACL_USER_OBJ:
    -			ap->ae_perm &= (mode >> 6) & 0x7;
    -			break;
    -		case ACL_GROUP_OBJ:
    -			gap = ap;
    -			break;
    -		case ACL_MASK:
    -			nomask = 0;
    -			ap->ae_perm &= (mode >> 3) & 0x7;
    -			break;
    -		case ACL_OTHER:
    -			ap->ae_perm &= mode & 0x7;
    -			break;
    -		default:
    -			break;
    -		}
    -	}
    -	/* Set the ACL_GROUP_OBJ if there's no ACL_MASK */
    -	if (gap && nomask)
    -		gap->ae_perm &= (mode >> 3) & 0x7;
    -}
    -
    diff --git a/sys/gnu/fs/xfs/xfs_acl.h b/sys/gnu/fs/xfs/xfs_acl.h
    deleted file mode 100644
    index 538d0d65b04..00000000000
    --- a/sys/gnu/fs/xfs/xfs_acl.h
    +++ /dev/null
    @@ -1,102 +0,0 @@
    -/*
    - * Copyright (c) 2001-2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_ACL_H__
    -#define __XFS_ACL_H__
    -
    -/*
    - * Access Control Lists
    - */
    -typedef __uint16_t	xfs_acl_perm_t;
    -typedef __int32_t	xfs_acl_type_t;
    -typedef __int32_t	xfs_acl_tag_t;
    -typedef __int32_t	xfs_acl_id_t;
    -
    -#define XFS_ACL_MAX_ENTRIES 25
    -#define XFS_ACL_NOT_PRESENT (-1)
    -
    -typedef struct xfs_acl_entry {
    -	xfs_acl_tag_t	ae_tag;
    -	xfs_acl_id_t	ae_id;
    -	xfs_acl_perm_t	ae_perm;
    -} xfs_acl_entry_t;
    -
    -typedef struct xfs_acl {
    -	__int32_t	acl_cnt;
    -	xfs_acl_entry_t	acl_entry[XFS_ACL_MAX_ENTRIES];
    -} xfs_acl_t;
    -
    -/* On-disk XFS extended attribute names */
    -#define SGI_ACL_FILE	"SGI_ACL_FILE"
    -#define SGI_ACL_DEFAULT	"SGI_ACL_DEFAULT"
    -#define SGI_ACL_FILE_SIZE	(sizeof(SGI_ACL_FILE)-1)
    -#define SGI_ACL_DEFAULT_SIZE	(sizeof(SGI_ACL_DEFAULT)-1)
    -
    -
    -#ifdef CONFIG_XFS_POSIX_ACL
    -
    -struct vattr;
    -struct vnode;
    -struct xfs_inode;
    -
    -extern struct kmem_zone *xfs_acl_zone;
    -#define xfs_acl_zone_init(zone, name)	\
    -		(zone) = kmem_zone_init(sizeof(xfs_acl_t), (name))
    -#define xfs_acl_zone_destroy(zone)	kmem_zone_destroy(zone)
    -
    -extern int xfs_acl_inherit(struct vnode *, struct vattr *, xfs_acl_t *);
    -extern int xfs_acl_iaccess(struct xfs_inode *, mode_t, cred_t *);
    -extern int xfs_acl_vtoacl(struct vnode *, xfs_acl_t *, xfs_acl_t *);
    -extern int xfs_acl_vhasacl_access(struct vnode *);
    -extern int xfs_acl_vhasacl_default(struct vnode *);
    -extern int xfs_acl_vset(struct vnode *, void *, size_t, int);
    -extern int xfs_acl_vget(struct vnode *, void *, size_t, int);
    -extern int xfs_acl_vremove(struct vnode *vp, int);
    -
    -#define _ACL_TYPE_ACCESS	1
    -#define _ACL_TYPE_DEFAULT	2
    -#define _ACL_PERM_INVALID(perm)	((perm) & ~(ACL_READ|ACL_WRITE|ACL_EXECUTE))
    -
    -#define _ACL_INHERIT(c,v,d)	(xfs_acl_inherit(c,v,d))
    -#define _ACL_GET_ACCESS(pv,pa)	(xfs_acl_vtoacl(pv,pa,NULL) == 0)
    -#define _ACL_GET_DEFAULT(pv,pd)	(xfs_acl_vtoacl(pv,NULL,pd) == 0)
    -#define _ACL_ACCESS_EXISTS	xfs_acl_vhasacl_access
    -#define _ACL_DEFAULT_EXISTS	xfs_acl_vhasacl_default
    -#define _ACL_XFS_IACCESS(i,m,c) (XFS_IFORK_Q(i) ? xfs_acl_iaccess(i,m,c) : -1)
    -
    -#define _ACL_ALLOC(a)		((a) = kmem_zone_alloc(xfs_acl_zone, KM_SLEEP))
    -#define _ACL_FREE(a)		((a)? kmem_zone_free(xfs_acl_zone, (a)):(void)0)
    -
    -#else
    -#define xfs_acl_zone_init(zone,name)
    -#define xfs_acl_zone_destroy(zone)
    -#define xfs_acl_vset(v,p,sz,t)	(-EOPNOTSUPP)
    -#define xfs_acl_vget(v,p,sz,t)	(-EOPNOTSUPP)
    -#define xfs_acl_vremove(v,t)	(-EOPNOTSUPP)
    -#define xfs_acl_vhasacl_access(v)	(0)
    -#define xfs_acl_vhasacl_default(v)	(0)
    -#define _ACL_ALLOC(a)		(1)	/* successfully allocate nothing */
    -#define _ACL_FREE(a)		((void)0)
    -#define _ACL_INHERIT(c,v,d)	(0)
    -#define _ACL_GET_ACCESS(pv,pa)	(0)
    -#define _ACL_GET_DEFAULT(pv,pd)	(0)
    -#define _ACL_ACCESS_EXISTS	(NULL)
    -#define _ACL_DEFAULT_EXISTS	(NULL)
    -#define _ACL_XFS_IACCESS(i,m,c) (-1)
    -#endif
    -
    -#endif	/* __XFS_ACL_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_ag.h b/sys/gnu/fs/xfs/xfs_ag.h
    deleted file mode 100644
    index dc2361dd740..00000000000
    --- a/sys/gnu/fs/xfs/xfs_ag.h
    +++ /dev/null
    @@ -1,231 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_AG_H__
    -#define	__XFS_AG_H__
    -
    -/*
    - * Allocation group header
    - * This is divided into three structures, placed in sequential 512-byte
    - * buffers after a copy of the superblock (also in a 512-byte buffer).
    - */
    -
    -struct xfs_buf;
    -struct xfs_mount;
    -struct xfs_trans;
    -
    -#define	XFS_AGF_MAGIC	0x58414746	/* 'XAGF' */
    -#define	XFS_AGI_MAGIC	0x58414749	/* 'XAGI' */
    -#define	XFS_AGF_VERSION	1
    -#define	XFS_AGI_VERSION	1
    -
    -#define	XFS_AGF_GOOD_VERSION(v)	((v) == XFS_AGF_VERSION)
    -#define	XFS_AGI_GOOD_VERSION(v)	((v) == XFS_AGI_VERSION)
    -
    -/*
    - * Btree number 0 is bno, 1 is cnt.  This value gives the size of the
    - * arrays below.
    - */
    -#define	XFS_BTNUM_AGF	((int)XFS_BTNUM_CNTi + 1)
    -
    -/*
    - * The second word of agf_levels in the first a.g. overlaps the EFS
    - * superblock's magic number.  Since the magic numbers valid for EFS
    - * are > 64k, our value cannot be confused for an EFS superblock's.
    - */
    -
    -typedef struct xfs_agf {
    -	/*
    -	 * Common allocation group header information
    -	 */
    -	__be32		agf_magicnum;	/* magic number == XFS_AGF_MAGIC */
    -	__be32		agf_versionnum;	/* header version == XFS_AGF_VERSION */
    -	__be32		agf_seqno;	/* sequence # starting from 0 */
    -	__be32		agf_length;	/* size in blocks of a.g. */
    -	/*
    -	 * Freespace information
    -	 */
    -	__be32		agf_roots[XFS_BTNUM_AGF];	/* root blocks */
    -	__be32		agf_spare0;	/* spare field */
    -	__be32		agf_levels[XFS_BTNUM_AGF];	/* btree levels */
    -	__be32		agf_spare1;	/* spare field */
    -	__be32		agf_flfirst;	/* first freelist block's index */
    -	__be32		agf_fllast;	/* last freelist block's index */
    -	__be32		agf_flcount;	/* count of blocks in freelist */
    -	__be32		agf_freeblks;	/* total free blocks */
    -	__be32		agf_longest;	/* longest free space */
    -} xfs_agf_t;
    -
    -#define	XFS_AGF_MAGICNUM	0x00000001
    -#define	XFS_AGF_VERSIONNUM	0x00000002
    -#define	XFS_AGF_SEQNO		0x00000004
    -#define	XFS_AGF_LENGTH		0x00000008
    -#define	XFS_AGF_ROOTS		0x00000010
    -#define	XFS_AGF_LEVELS		0x00000020
    -#define	XFS_AGF_FLFIRST		0x00000040
    -#define	XFS_AGF_FLLAST		0x00000080
    -#define	XFS_AGF_FLCOUNT		0x00000100
    -#define	XFS_AGF_FREEBLKS	0x00000200
    -#define	XFS_AGF_LONGEST		0x00000400
    -#define	XFS_AGF_NUM_BITS	11
    -#define	XFS_AGF_ALL_BITS	((1 << XFS_AGF_NUM_BITS) - 1)
    -
    -/* disk block (xfs_daddr_t) in the AG */
    -#define XFS_AGF_DADDR(mp)	((xfs_daddr_t)(1 << (mp)->m_sectbb_log))
    -#define	XFS_AGF_BLOCK(mp)	XFS_HDR_BLOCK(mp, XFS_AGF_DADDR(mp))
    -#define	XFS_BUF_TO_AGF(bp)	((xfs_agf_t *)XFS_BUF_PTR(bp))
    -
    -
    -/*
    - * Size of the unlinked inode hash table in the agi.
    - */
    -#define	XFS_AGI_UNLINKED_BUCKETS	64
    -
    -typedef struct xfs_agi {
    -	/*
    -	 * Common allocation group header information
    -	 */
    -	__be32		agi_magicnum;	/* magic number == XFS_AGI_MAGIC */
    -	__be32		agi_versionnum;	/* header version == XFS_AGI_VERSION */
    -	__be32		agi_seqno;	/* sequence # starting from 0 */
    -	__be32		agi_length;	/* size in blocks of a.g. */
    -	/*
    -	 * Inode information
    -	 * Inodes are mapped by interpreting the inode number, so no
    -	 * mapping data is needed here.
    -	 */
    -	__be32		agi_count;	/* count of allocated inodes */
    -	__be32		agi_root;	/* root of inode btree */
    -	__be32		agi_level;	/* levels in inode btree */
    -	__be32		agi_freecount;	/* number of free inodes */
    -	__be32		agi_newino;	/* new inode just allocated */
    -	__be32		agi_dirino;	/* last directory inode chunk */
    -	/*
    -	 * Hash table of inodes which have been unlinked but are
    -	 * still being referenced.
    -	 */
    -	__be32		agi_unlinked[XFS_AGI_UNLINKED_BUCKETS];
    -} xfs_agi_t;
    -
    -#define	XFS_AGI_MAGICNUM	0x00000001
    -#define	XFS_AGI_VERSIONNUM	0x00000002
    -#define	XFS_AGI_SEQNO		0x00000004
    -#define	XFS_AGI_LENGTH		0x00000008
    -#define	XFS_AGI_COUNT		0x00000010
    -#define	XFS_AGI_ROOT		0x00000020
    -#define	XFS_AGI_LEVEL		0x00000040
    -#define	XFS_AGI_FREECOUNT	0x00000080
    -#define	XFS_AGI_NEWINO		0x00000100
    -#define	XFS_AGI_DIRINO		0x00000200
    -#define	XFS_AGI_UNLINKED	0x00000400
    -#define	XFS_AGI_NUM_BITS	11
    -#define	XFS_AGI_ALL_BITS	((1 << XFS_AGI_NUM_BITS) - 1)
    -
    -/* disk block (xfs_daddr_t) in the AG */
    -#define XFS_AGI_DADDR(mp)	((xfs_daddr_t)(2 << (mp)->m_sectbb_log))
    -#define	XFS_AGI_BLOCK(mp)	XFS_HDR_BLOCK(mp, XFS_AGI_DADDR(mp))
    -#define	XFS_BUF_TO_AGI(bp)	((xfs_agi_t *)XFS_BUF_PTR(bp))
    -
    -/*
    - * The third a.g. block contains the a.g. freelist, an array
    - * of block pointers to blocks owned by the allocation btree code.
    - */
    -#define XFS_AGFL_DADDR(mp)	((xfs_daddr_t)(3 << (mp)->m_sectbb_log))
    -#define	XFS_AGFL_BLOCK(mp)	XFS_HDR_BLOCK(mp, XFS_AGFL_DADDR(mp))
    -#define XFS_AGFL_SIZE(mp)	((mp)->m_sb.sb_sectsize / sizeof(xfs_agblock_t))
    -#define	XFS_BUF_TO_AGFL(bp)	((xfs_agfl_t *)XFS_BUF_PTR(bp))
    -
    -typedef struct xfs_agfl {
    -	xfs_agblock_t	agfl_bno[1];	/* actually XFS_AGFL_SIZE(mp) */
    -} xfs_agfl_t;
    -
    -/*
    - * Busy block/extent entry.  Used in perag to mark blocks that have been freed
    - * but whose transactions aren't committed to disk yet.
    - */
    -typedef struct xfs_perag_busy {
    -	xfs_agblock_t	busy_start;
    -	xfs_extlen_t	busy_length;
    -	struct xfs_trans *busy_tp;	/* transaction that did the free */
    -} xfs_perag_busy_t;
    -
    -/*
    - * Per-ag incore structure, copies of information in agf and agi,
    - * to improve the performance of allocation group selection.
    - *
    - * pick sizes which fit in allocation buckets well
    - */
    -#if (BITS_PER_LONG == 32)
    -#define XFS_PAGB_NUM_SLOTS	84
    -#elif (BITS_PER_LONG == 64)
    -#define XFS_PAGB_NUM_SLOTS	128
    -#endif
    -
    -typedef struct xfs_perag
    -{
    -	char		pagf_init;	/* this agf's entry is initialized */
    -	char		pagi_init;	/* this agi's entry is initialized */
    -	char		pagf_metadata;	/* the agf is preferred to be metadata */
    -	char		pagi_inodeok;	/* The agi is ok for inodes */
    -	__uint8_t	pagf_levels[XFS_BTNUM_AGF];
    -					/* # of levels in bno & cnt btree */
    -	__uint32_t	pagf_flcount;	/* count of blocks in freelist */
    -	xfs_extlen_t	pagf_freeblks;	/* total free blocks */
    -	xfs_extlen_t	pagf_longest;	/* longest free space */
    -	xfs_agino_t	pagi_freecount;	/* number of free inodes */
    -#ifdef __KERNEL__
    -	lock_t		pagb_lock;	/* lock for pagb_list */
    -#endif
    -	int		pagb_count;	/* pagb slots in use */
    -	xfs_perag_busy_t *pagb_list;	/* unstable blocks */
    -} xfs_perag_t;
    -
    -#define	XFS_AG_MAXLEVELS(mp)		((mp)->m_ag_maxlevels)
    -#define	XFS_MIN_FREELIST_RAW(bl,cl,mp)	\
    -	(MIN(bl + 1, XFS_AG_MAXLEVELS(mp)) + MIN(cl + 1, XFS_AG_MAXLEVELS(mp)))
    -#define	XFS_MIN_FREELIST(a,mp)		\
    -	(XFS_MIN_FREELIST_RAW(		\
    -		be32_to_cpu((a)->agf_levels[XFS_BTNUM_BNOi]), \
    -		be32_to_cpu((a)->agf_levels[XFS_BTNUM_CNTi]), mp))
    -#define	XFS_MIN_FREELIST_PAG(pag,mp)	\
    -	(XFS_MIN_FREELIST_RAW(		\
    -		(uint_t)(pag)->pagf_levels[XFS_BTNUM_BNOi], \
    -		(uint_t)(pag)->pagf_levels[XFS_BTNUM_CNTi], mp))
    -
    -#define XFS_AGB_TO_FSB(mp,agno,agbno)	\
    -	(((xfs_fsblock_t)(agno) << (mp)->m_sb.sb_agblklog) | (agbno))
    -#define	XFS_FSB_TO_AGNO(mp,fsbno)	\
    -	((xfs_agnumber_t)((fsbno) >> (mp)->m_sb.sb_agblklog))
    -#define	XFS_FSB_TO_AGBNO(mp,fsbno)	\
    -	((xfs_agblock_t)((fsbno) & XFS_MASK32LO((mp)->m_sb.sb_agblklog)))
    -#define	XFS_AGB_TO_DADDR(mp,agno,agbno)	\
    -	((xfs_daddr_t)XFS_FSB_TO_BB(mp, \
    -		(xfs_fsblock_t)(agno) * (mp)->m_sb.sb_agblocks + (agbno)))
    -#define	XFS_AG_DADDR(mp,agno,d)		(XFS_AGB_TO_DADDR(mp, agno, 0) + (d))
    -
    -/*
    - * For checking for bad ranges of xfs_daddr_t's, covering multiple
    - * allocation groups or a single xfs_daddr_t that's a superblock copy.
    - */
    -#define	XFS_AG_CHECK_DADDR(mp,d,len)	\
    -	((len) == 1 ? \
    -	    ASSERT((d) == XFS_SB_DADDR || \
    -		   XFS_DADDR_TO_AGBNO(mp, d) != XFS_SB_DADDR) : \
    -	    ASSERT(XFS_DADDR_TO_AGNO(mp, d) == \
    -		   XFS_DADDR_TO_AGNO(mp, (d) + (len) - 1)))
    -
    -#endif	/* __XFS_AG_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_alloc.c b/sys/gnu/fs/xfs/xfs_alloc.c
    deleted file mode 100644
    index 1c2f50e7731..00000000000
    --- a/sys/gnu/fs/xfs/xfs_alloc.c
    +++ /dev/null
    @@ -1,2603 +0,0 @@
    -/*
    - * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_btree.h"
    -#include "xfs_ialloc.h"
    -#include "xfs_alloc.h"
    -#include "xfs_error.h"
    -
    -
    -#define XFS_ABSDIFF(a,b)	(((a) <= (b)) ? ((b) - (a)) : ((a) - (b)))
    -
    -#define	XFSA_FIXUP_BNO_OK	1
    -#define	XFSA_FIXUP_CNT_OK	2
    -
    -STATIC int
    -xfs_alloc_search_busy(xfs_trans_t *tp,
    -		    xfs_agnumber_t agno,
    -		    xfs_agblock_t bno,
    -		    xfs_extlen_t len);
    -
    -#if defined(XFS_ALLOC_TRACE)
    -ktrace_t *xfs_alloc_trace_buf;
    -
    -#define	TRACE_ALLOC(s,a)	\
    -	xfs_alloc_trace_alloc(fname, s, a, __LINE__)
    -#define	TRACE_FREE(s,a,b,x,f)	\
    -	xfs_alloc_trace_free(fname, s, mp, a, b, x, f, __LINE__)
    -#define	TRACE_MODAGF(s,a,f)	\
    -	xfs_alloc_trace_modagf(fname, s, mp, a, f, __LINE__)
    -#define	TRACE_BUSY(fname,s,ag,agb,l,sl,tp)	\
    -	xfs_alloc_trace_busy(fname, s, mp, ag, agb, l, sl, tp, XFS_ALLOC_KTRACE_BUSY, __LINE__)
    -#define	TRACE_UNBUSY(fname,s,ag,sl,tp)	\
    -	xfs_alloc_trace_busy(fname, s, mp, ag, -1, -1, sl, tp, XFS_ALLOC_KTRACE_UNBUSY, __LINE__)
    -#define	TRACE_BUSYSEARCH(fname,s,ag,agb,l,sl,tp)	\
    -	xfs_alloc_trace_busy(fname, s, mp, ag, agb, l, sl, tp, XFS_ALLOC_KTRACE_BUSYSEARCH, __LINE__)
    -#else
    -#define	TRACE_ALLOC(s,a)
    -#define	TRACE_FREE(s,a,b,x,f)
    -#define	TRACE_MODAGF(s,a,f)
    -#define	TRACE_BUSY(s,a,ag,agb,l,sl,tp)
    -#define	TRACE_UNBUSY(fname,s,ag,sl,tp)
    -#define	TRACE_BUSYSEARCH(fname,s,ag,agb,l,sl,tp)
    -#endif	/* XFS_ALLOC_TRACE */
    -
    -/*
    - * Prototypes for per-ag allocation routines
    - */
    -
    -STATIC int xfs_alloc_ag_vextent_exact(xfs_alloc_arg_t *);
    -STATIC int xfs_alloc_ag_vextent_near(xfs_alloc_arg_t *);
    -STATIC int xfs_alloc_ag_vextent_size(xfs_alloc_arg_t *);
    -STATIC int xfs_alloc_ag_vextent_small(xfs_alloc_arg_t *,
    -	xfs_btree_cur_t *, xfs_agblock_t *, xfs_extlen_t *, int *);
    -
    -/*
    - * Internal functions.
    - */
    -
    -/*
    - * Compute aligned version of the found extent.
    - * Takes alignment and min length into account.
    - */
    -STATIC int				/* success (>= minlen) */
    -xfs_alloc_compute_aligned(
    -	xfs_agblock_t	foundbno,	/* starting block in found extent */
    -	xfs_extlen_t	foundlen,	/* length in found extent */
    -	xfs_extlen_t	alignment,	/* alignment for allocation */
    -	xfs_extlen_t	minlen,		/* minimum length for allocation */
    -	xfs_agblock_t	*resbno,	/* result block number */
    -	xfs_extlen_t	*reslen)	/* result length */
    -{
    -	xfs_agblock_t	bno;
    -	xfs_extlen_t	diff;
    -	xfs_extlen_t	len;
    -
    -	if (alignment > 1 && foundlen >= minlen) {
    -		bno = roundup(foundbno, alignment);
    -		diff = bno - foundbno;
    -		len = diff >= foundlen ? 0 : foundlen - diff;
    -	} else {
    -		bno = foundbno;
    -		len = foundlen;
    -	}
    -	*resbno = bno;
    -	*reslen = len;
    -	return len >= minlen;
    -}
    -
    -/*
    - * Compute best start block and diff for "near" allocations.
    - * freelen >= wantlen already checked by caller.
    - */
    -STATIC xfs_extlen_t			/* difference value (absolute) */
    -xfs_alloc_compute_diff(
    -	xfs_agblock_t	wantbno,	/* target starting block */
    -	xfs_extlen_t	wantlen,	/* target length */
    -	xfs_extlen_t	alignment,	/* target alignment */
    -	xfs_agblock_t	freebno,	/* freespace's starting block */
    -	xfs_extlen_t	freelen,	/* freespace's length */
    -	xfs_agblock_t	*newbnop)	/* result: best start block from free */
    -{
    -	xfs_agblock_t	freeend;	/* end of freespace extent */
    -	xfs_agblock_t	newbno1;	/* return block number */
    -	xfs_agblock_t	newbno2;	/* other new block number */
    -	xfs_extlen_t	newlen1=0;	/* length with newbno1 */
    -	xfs_extlen_t	newlen2=0;	/* length with newbno2 */
    -	xfs_agblock_t	wantend;	/* end of target extent */
    -
    -	ASSERT(freelen >= wantlen);
    -	freeend = freebno + freelen;
    -	wantend = wantbno + wantlen;
    -	if (freebno >= wantbno) {
    -		if ((newbno1 = roundup(freebno, alignment)) >= freeend)
    -			newbno1 = NULLAGBLOCK;
    -	} else if (freeend >= wantend && alignment > 1) {
    -		newbno1 = roundup(wantbno, alignment);
    -		newbno2 = newbno1 - alignment;
    -		if (newbno1 >= freeend)
    -			newbno1 = NULLAGBLOCK;
    -		else
    -			newlen1 = XFS_EXTLEN_MIN(wantlen, freeend - newbno1);
    -		if (newbno2 < freebno)
    -			newbno2 = NULLAGBLOCK;
    -		else
    -			newlen2 = XFS_EXTLEN_MIN(wantlen, freeend - newbno2);
    -		if (newbno1 != NULLAGBLOCK && newbno2 != NULLAGBLOCK) {
    -			if (newlen1 < newlen2 ||
    -			    (newlen1 == newlen2 &&
    -			     XFS_ABSDIFF(newbno1, wantbno) >
    -			     XFS_ABSDIFF(newbno2, wantbno)))
    -				newbno1 = newbno2;
    -		} else if (newbno2 != NULLAGBLOCK)
    -			newbno1 = newbno2;
    -	} else if (freeend >= wantend) {
    -		newbno1 = wantbno;
    -	} else if (alignment > 1) {
    -		newbno1 = roundup(freeend - wantlen, alignment);
    -		if (newbno1 > freeend - wantlen &&
    -		    newbno1 - alignment >= freebno)
    -			newbno1 -= alignment;
    -		else if (newbno1 >= freeend)
    -			newbno1 = NULLAGBLOCK;
    -	} else
    -		newbno1 = freeend - wantlen;
    -	*newbnop = newbno1;
    -	return newbno1 == NULLAGBLOCK ? 0 : XFS_ABSDIFF(newbno1, wantbno);
    -}
    -
    -/*
    - * Fix up the length, based on mod and prod.
    - * len should be k * prod + mod for some k.
    - * If len is too small it is returned unchanged.
    - * If len hits maxlen it is left alone.
    - */
    -STATIC void
    -xfs_alloc_fix_len(
    -	xfs_alloc_arg_t	*args)		/* allocation argument structure */
    -{
    -	xfs_extlen_t	k;
    -	xfs_extlen_t	rlen;
    -
    -	ASSERT(args->mod < args->prod);
    -	rlen = args->len;
    -	ASSERT(rlen >= args->minlen);
    -	ASSERT(rlen <= args->maxlen);
    -	if (args->prod <= 1 || rlen < args->mod || rlen == args->maxlen ||
    -	    (args->mod == 0 && rlen < args->prod))
    -		return;
    -	k = rlen % args->prod;
    -	if (k == args->mod)
    -		return;
    -	if (k > args->mod) {
    -		if ((int)(rlen = rlen - k - args->mod) < (int)args->minlen)
    -			return;
    -	} else {
    -		if ((int)(rlen = rlen - args->prod - (args->mod - k)) <
    -		    (int)args->minlen)
    -			return;
    -	}
    -	ASSERT(rlen >= args->minlen);
    -	ASSERT(rlen <= args->maxlen);
    -	args->len = rlen;
    -}
    -
    -/*
    - * Fix up length if there is too little space left in the a.g.
    - * Return 1 if ok, 0 if too little, should give up.
    - */
    -STATIC int
    -xfs_alloc_fix_minleft(
    -	xfs_alloc_arg_t	*args)		/* allocation argument structure */
    -{
    -	xfs_agf_t	*agf;		/* a.g. freelist header */
    -	int		diff;		/* free space difference */
    -
    -	if (args->minleft == 0)
    -		return 1;
    -	agf = XFS_BUF_TO_AGF(args->agbp);
    -	diff = be32_to_cpu(agf->agf_freeblks)
    -		+ be32_to_cpu(agf->agf_flcount)
    -		- args->len - args->minleft;
    -	if (diff >= 0)
    -		return 1;
    -	args->len += diff;		/* shrink the allocated space */
    -	if (args->len >= args->minlen)
    -		return 1;
    -	args->agbno = NULLAGBLOCK;
    -	return 0;
    -}
    -
    -/*
    - * Update the two btrees, logically removing from freespace the extent
    - * starting at rbno, rlen blocks.  The extent is contained within the
    - * actual (current) free extent fbno for flen blocks.
    - * Flags are passed in indicating whether the cursors are set to the
    - * relevant records.
    - */
    -STATIC int				/* error code */
    -xfs_alloc_fixup_trees(
    -	xfs_btree_cur_t	*cnt_cur,	/* cursor for by-size btree */
    -	xfs_btree_cur_t	*bno_cur,	/* cursor for by-block btree */
    -	xfs_agblock_t	fbno,		/* starting block of free extent */
    -	xfs_extlen_t	flen,		/* length of free extent */
    -	xfs_agblock_t	rbno,		/* starting block of returned extent */
    -	xfs_extlen_t	rlen,		/* length of returned extent */
    -	int		flags)		/* flags, XFSA_FIXUP_... */
    -{
    -	int		error;		/* error code */
    -	int		i;		/* operation results */
    -	xfs_agblock_t	nfbno1;		/* first new free startblock */
    -	xfs_agblock_t	nfbno2;		/* second new free startblock */
    -	xfs_extlen_t	nflen1=0;	/* first new free length */
    -	xfs_extlen_t	nflen2=0;	/* second new free length */
    -
    -	/*
    -	 * Look up the record in the by-size tree if necessary.
    -	 */
    -	if (flags & XFSA_FIXUP_CNT_OK) {
    -#ifdef DEBUG
    -		if ((error = xfs_alloc_get_rec(cnt_cur, &nfbno1, &nflen1, &i)))
    -			return error;
    -		XFS_WANT_CORRUPTED_RETURN(
    -			i == 1 && nfbno1 == fbno && nflen1 == flen);
    -#endif
    -	} else {
    -		if ((error = xfs_alloc_lookup_eq(cnt_cur, fbno, flen, &i)))
    -			return error;
    -		XFS_WANT_CORRUPTED_RETURN(i == 1);
    -	}
    -	/*
    -	 * Look up the record in the by-block tree if necessary.
    -	 */
    -	if (flags & XFSA_FIXUP_BNO_OK) {
    -#ifdef DEBUG
    -		if ((error = xfs_alloc_get_rec(bno_cur, &nfbno1, &nflen1, &i)))
    -			return error;
    -		XFS_WANT_CORRUPTED_RETURN(
    -			i == 1 && nfbno1 == fbno && nflen1 == flen);
    -#endif
    -	} else {
    -		if ((error = xfs_alloc_lookup_eq(bno_cur, fbno, flen, &i)))
    -			return error;
    -		XFS_WANT_CORRUPTED_RETURN(i == 1);
    -	}
    -#ifdef DEBUG
    -	{
    -		xfs_alloc_block_t	*bnoblock;
    -		xfs_alloc_block_t	*cntblock;
    -
    -		if (bno_cur->bc_nlevels == 1 &&
    -		    cnt_cur->bc_nlevels == 1) {
    -			bnoblock = XFS_BUF_TO_ALLOC_BLOCK(bno_cur->bc_bufs[0]);
    -			cntblock = XFS_BUF_TO_ALLOC_BLOCK(cnt_cur->bc_bufs[0]);
    -			XFS_WANT_CORRUPTED_RETURN(
    -				be16_to_cpu(bnoblock->bb_numrecs) ==
    -				be16_to_cpu(cntblock->bb_numrecs));
    -		}
    -	}
    -#endif
    -	/*
    -	 * Deal with all four cases: the allocated record is contained
    -	 * within the freespace record, so we can have new freespace
    -	 * at either (or both) end, or no freespace remaining.
    -	 */
    -	if (rbno == fbno && rlen == flen)
    -		nfbno1 = nfbno2 = NULLAGBLOCK;
    -	else if (rbno == fbno) {
    -		nfbno1 = rbno + rlen;
    -		nflen1 = flen - rlen;
    -		nfbno2 = NULLAGBLOCK;
    -	} else if (rbno + rlen == fbno + flen) {
    -		nfbno1 = fbno;
    -		nflen1 = flen - rlen;
    -		nfbno2 = NULLAGBLOCK;
    -	} else {
    -		nfbno1 = fbno;
    -		nflen1 = rbno - fbno;
    -		nfbno2 = rbno + rlen;
    -		nflen2 = (fbno + flen) - nfbno2;
    -	}
    -	/*
    -	 * Delete the entry from the by-size btree.
    -	 */
    -	if ((error = xfs_alloc_delete(cnt_cur, &i)))
    -		return error;
    -	XFS_WANT_CORRUPTED_RETURN(i == 1);
    -	/*
    -	 * Add new by-size btree entry(s).
    -	 */
    -	if (nfbno1 != NULLAGBLOCK) {
    -		if ((error = xfs_alloc_lookup_eq(cnt_cur, nfbno1, nflen1, &i)))
    -			return error;
    -		XFS_WANT_CORRUPTED_RETURN(i == 0);
    -		if ((error = xfs_alloc_insert(cnt_cur, &i)))
    -			return error;
    -		XFS_WANT_CORRUPTED_RETURN(i == 1);
    -	}
    -	if (nfbno2 != NULLAGBLOCK) {
    -		if ((error = xfs_alloc_lookup_eq(cnt_cur, nfbno2, nflen2, &i)))
    -			return error;
    -		XFS_WANT_CORRUPTED_RETURN(i == 0);
    -		if ((error = xfs_alloc_insert(cnt_cur, &i)))
    -			return error;
    -		XFS_WANT_CORRUPTED_RETURN(i == 1);
    -	}
    -	/*
    -	 * Fix up the by-block btree entry(s).
    -	 */
    -	if (nfbno1 == NULLAGBLOCK) {
    -		/*
    -		 * No remaining freespace, just delete the by-block tree entry.
    -		 */
    -		if ((error = xfs_alloc_delete(bno_cur, &i)))
    -			return error;
    -		XFS_WANT_CORRUPTED_RETURN(i == 1);
    -	} else {
    -		/*
    -		 * Update the by-block entry to start later|be shorter.
    -		 */
    -		if ((error = xfs_alloc_update(bno_cur, nfbno1, nflen1)))
    -			return error;
    -	}
    -	if (nfbno2 != NULLAGBLOCK) {
    -		/*
    -		 * 2 resulting free entries, need to add one.
    -		 */
    -		if ((error = xfs_alloc_lookup_eq(bno_cur, nfbno2, nflen2, &i)))
    -			return error;
    -		XFS_WANT_CORRUPTED_RETURN(i == 0);
    -		if ((error = xfs_alloc_insert(bno_cur, &i)))
    -			return error;
    -		XFS_WANT_CORRUPTED_RETURN(i == 1);
    -	}
    -	return 0;
    -}
    -
    -/*
    - * Read in the allocation group free block array.
    - */
    -STATIC int				/* error */
    -xfs_alloc_read_agfl(
    -	xfs_mount_t	*mp,		/* mount point structure */
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_agnumber_t	agno,		/* allocation group number */
    -	xfs_buf_t	**bpp)		/* buffer for the ag free block array */
    -{
    -	xfs_buf_t	*bp;		/* return value */
    -	int		error;
    -
    -	ASSERT(agno != NULLAGNUMBER);
    -	error = xfs_trans_read_buf(
    -			mp, tp, mp->m_ddev_targp,
    -			XFS_AG_DADDR(mp, agno, XFS_AGFL_DADDR(mp)),
    -			XFS_FSS_TO_BB(mp, 1), 0, &bp);
    -	if (error)
    -		return error;
    -	ASSERT(bp);
    -	ASSERT(!XFS_BUF_GETERROR(bp));
    -	XFS_BUF_SET_VTYPE_REF(bp, B_FS_AGFL, XFS_AGFL_REF);
    -	*bpp = bp;
    -	return 0;
    -}
    -
    -#if defined(XFS_ALLOC_TRACE)
    -/*
    - * Add an allocation trace entry for an alloc call.
    - */
    -STATIC void
    -xfs_alloc_trace_alloc(
    -	char		*name,		/* function tag string */
    -	char		*str,		/* additional string */
    -	xfs_alloc_arg_t	*args,		/* allocation argument structure */
    -	int		line)		/* source line number */
    -{
    -	ktrace_enter(xfs_alloc_trace_buf,
    -		(void *)(__psint_t)(XFS_ALLOC_KTRACE_ALLOC | (line << 16)),
    -		(void *)name,
    -		(void *)str,
    -		(void *)args->mp,
    -		(void *)(__psunsigned_t)args->agno,
    -		(void *)(__psunsigned_t)args->agbno,
    -		(void *)(__psunsigned_t)args->minlen,
    -		(void *)(__psunsigned_t)args->maxlen,
    -		(void *)(__psunsigned_t)args->mod,
    -		(void *)(__psunsigned_t)args->prod,
    -		(void *)(__psunsigned_t)args->minleft,
    -		(void *)(__psunsigned_t)args->total,
    -		(void *)(__psunsigned_t)args->alignment,
    -		(void *)(__psunsigned_t)args->len,
    -		(void *)((((__psint_t)args->type) << 16) |
    -			 (__psint_t)args->otype),
    -		(void *)(__psint_t)((args->wasdel << 3) |
    -				    (args->wasfromfl << 2) |
    -				    (args->isfl << 1) |
    -				    (args->userdata << 0)));
    -}
    -
    -/*
    - * Add an allocation trace entry for a free call.
    - */
    -STATIC void
    -xfs_alloc_trace_free(
    -	char		*name,		/* function tag string */
    -	char		*str,		/* additional string */
    -	xfs_mount_t	*mp,		/* file system mount point */
    -	xfs_agnumber_t	agno,		/* allocation group number */
    -	xfs_agblock_t	agbno,		/* a.g. relative block number */
    -	xfs_extlen_t	len,		/* length of extent */
    -	int		isfl,		/* set if is freelist allocation/free */
    -	int		line)		/* source line number */
    -{
    -	ktrace_enter(xfs_alloc_trace_buf,
    -		(void *)(__psint_t)(XFS_ALLOC_KTRACE_FREE | (line << 16)),
    -		(void *)name,
    -		(void *)str,
    -		(void *)mp,
    -		(void *)(__psunsigned_t)agno,
    -		(void *)(__psunsigned_t)agbno,
    -		(void *)(__psunsigned_t)len,
    -		(void *)(__psint_t)isfl,
    -		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
    -}
    -
    -/*
    - * Add an allocation trace entry for modifying an agf.
    - */
    -STATIC void
    -xfs_alloc_trace_modagf(
    -	char		*name,		/* function tag string */
    -	char		*str,		/* additional string */
    -	xfs_mount_t	*mp,		/* file system mount point */
    -	xfs_agf_t	*agf,		/* new agf value */
    -	int		flags,		/* logging flags for agf */
    -	int		line)		/* source line number */
    -{
    -	ktrace_enter(xfs_alloc_trace_buf,
    -		(void *)(__psint_t)(XFS_ALLOC_KTRACE_MODAGF | (line << 16)),
    -		(void *)name,
    -		(void *)str,
    -		(void *)mp,
    -		(void *)(__psint_t)flags,
    -		(void *)(__psunsigned_t)be32_to_cpu(agf->agf_seqno),
    -		(void *)(__psunsigned_t)be32_to_cpu(agf->agf_length),
    -		(void *)(__psunsigned_t)be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNO]),
    -		(void *)(__psunsigned_t)be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNT]),
    -		(void *)(__psunsigned_t)be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]),
    -		(void *)(__psunsigned_t)be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]),
    -		(void *)(__psunsigned_t)be32_to_cpu(agf->agf_flfirst),
    -		(void *)(__psunsigned_t)be32_to_cpu(agf->agf_fllast),
    -		(void *)(__psunsigned_t)be32_to_cpu(agf->agf_flcount),
    -		(void *)(__psunsigned_t)be32_to_cpu(agf->agf_freeblks),
    -		(void *)(__psunsigned_t)be32_to_cpu(agf->agf_longest));
    -}
    -
    -STATIC void
    -xfs_alloc_trace_busy(
    -	char		*name,		/* function tag string */
    -	char		*str,		/* additional string */
    -	xfs_mount_t	*mp,		/* file system mount point */
    -	xfs_agnumber_t	agno,		/* allocation group number */
    -	xfs_agblock_t	agbno,		/* a.g. relative block number */
    -	xfs_extlen_t	len,		/* length of extent */
    -	int		slot,		/* perag Busy slot */
    -	xfs_trans_t	*tp,
    -	int		trtype,		/* type: add, delete, search */
    -	int		line)		/* source line number */
    -{
    -	ktrace_enter(xfs_alloc_trace_buf,
    -		(void *)(__psint_t)(trtype | (line << 16)),
    -		(void *)name,
    -		(void *)str,
    -		(void *)mp,
    -		(void *)(__psunsigned_t)agno,
    -		(void *)(__psunsigned_t)agbno,
    -		(void *)(__psunsigned_t)len,
    -		(void *)(__psint_t)slot,
    -		(void *)tp,
    -		NULL, NULL, NULL, NULL, NULL, NULL, NULL);
    -}
    -#endif	/* XFS_ALLOC_TRACE */
    -
    -/*
    - * Allocation group level functions.
    - */
    -
    -/*
    - * Allocate a variable extent in the allocation group agno.
    - * Type and bno are used to determine where in the allocation group the
    - * extent will start.
    - * Extent's length (returned in *len) will be between minlen and maxlen,
    - * and of the form k * prod + mod unless there's nothing that large.
    - * Return the starting a.g. block, or NULLAGBLOCK if we can't do it.
    - */
    -STATIC int			/* error */
    -xfs_alloc_ag_vextent(
    -	xfs_alloc_arg_t	*args)	/* argument structure for allocation */
    -{
    -	int		error=0;
    -#ifdef XFS_ALLOC_TRACE
    -	static char	fname[] = "xfs_alloc_ag_vextent";
    -#endif
    -
    -	ASSERT(args->minlen > 0);
    -	ASSERT(args->maxlen > 0);
    -	ASSERT(args->minlen <= args->maxlen);
    -	ASSERT(args->mod < args->prod);
    -	ASSERT(args->alignment > 0);
    -	/*
    -	 * Branch to correct routine based on the type.
    -	 */
    -	args->wasfromfl = 0;
    -	switch (args->type) {
    -	case XFS_ALLOCTYPE_THIS_AG:
    -		error = xfs_alloc_ag_vextent_size(args);
    -		break;
    -	case XFS_ALLOCTYPE_NEAR_BNO:
    -		error = xfs_alloc_ag_vextent_near(args);
    -		break;
    -	case XFS_ALLOCTYPE_THIS_BNO:
    -		error = xfs_alloc_ag_vextent_exact(args);
    -		break;
    -	default:
    -		ASSERT(0);
    -		/* NOTREACHED */
    -	}
    -	if (error)
    -		return error;
    -	/*
    -	 * If the allocation worked, need to change the agf structure
    -	 * (and log it), and the superblock.
    -	 */
    -	if (args->agbno != NULLAGBLOCK) {
    -		xfs_agf_t	*agf;	/* allocation group freelist header */
    -#ifdef XFS_ALLOC_TRACE
    -		xfs_mount_t	*mp = args->mp;
    -#endif
    -		long		slen = (long)args->len;
    -
    -		ASSERT(args->len >= args->minlen && args->len <= args->maxlen);
    -		ASSERT(!(args->wasfromfl) || !args->isfl);
    -		ASSERT(args->agbno % args->alignment == 0);
    -		if (!(args->wasfromfl)) {
    -
    -			agf = XFS_BUF_TO_AGF(args->agbp);
    -			be32_add(&agf->agf_freeblks, -(args->len));
    -			xfs_trans_agblocks_delta(args->tp,
    -						 -((long)(args->len)));
    -			args->pag->pagf_freeblks -= args->len;
    -			ASSERT(be32_to_cpu(agf->agf_freeblks) <=
    -				be32_to_cpu(agf->agf_length));
    -			TRACE_MODAGF(NULL, agf, XFS_AGF_FREEBLKS);
    -			xfs_alloc_log_agf(args->tp, args->agbp,
    -						XFS_AGF_FREEBLKS);
    -			/* search the busylist for these blocks */
    -			xfs_alloc_search_busy(args->tp, args->agno,
    -					args->agbno, args->len);
    -		}
    -		if (!args->isfl)
    -			xfs_trans_mod_sb(args->tp,
    -				args->wasdel ? XFS_TRANS_SB_RES_FDBLOCKS :
    -					XFS_TRANS_SB_FDBLOCKS, -slen);
    -		XFS_STATS_INC(xs_allocx);
    -		XFS_STATS_ADD(xs_allocb, args->len);
    -	}
    -	return 0;
    -}
    -
    -/*
    - * Allocate a variable extent at exactly agno/bno.
    - * Extent's length (returned in *len) will be between minlen and maxlen,
    - * and of the form k * prod + mod unless there's nothing that large.
    - * Return the starting a.g. block (bno), or NULLAGBLOCK if we can't do it.
    - */
    -STATIC int			/* error */
    -xfs_alloc_ag_vextent_exact(
    -	xfs_alloc_arg_t	*args)	/* allocation argument structure */
    -{
    -	xfs_btree_cur_t	*bno_cur;/* by block-number btree cursor */
    -	xfs_btree_cur_t	*cnt_cur;/* by count btree cursor */
    -	xfs_agblock_t	end;	/* end of allocated extent */
    -	int		error;
    -	xfs_agblock_t	fbno;	/* start block of found extent */
    -	xfs_agblock_t	fend;	/* end block of found extent */
    -	xfs_extlen_t	flen;	/* length of found extent */
    -#ifdef XFS_ALLOC_TRACE
    -	static char	fname[] = "xfs_alloc_ag_vextent_exact";
    -#endif
    -	int		i;	/* success/failure of operation */
    -	xfs_agblock_t	maxend;	/* end of maximal extent */
    -	xfs_agblock_t	minend;	/* end of minimal extent */
    -	xfs_extlen_t	rlen;	/* length of returned extent */
    -
    -	ASSERT(args->alignment == 1);
    -	/*
    -	 * Allocate/initialize a cursor for the by-number freespace btree.
    -	 */
    -	bno_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
    -		args->agno, XFS_BTNUM_BNO, NULL, 0);
    -	/*
    -	 * Lookup bno and minlen in the btree (minlen is irrelevant, really).
    -	 * Look for the closest free block <= bno, it must contain bno
    -	 * if any free block does.
    -	 */
    -	if ((error = xfs_alloc_lookup_le(bno_cur, args->agbno, args->minlen, &i)))
    -		goto error0;
    -	if (!i) {
    -		/*
    -		 * Didn't find it, return null.
    -		 */
    -		xfs_btree_del_cursor(bno_cur, XFS_BTREE_NOERROR);
    -		args->agbno = NULLAGBLOCK;
    -		return 0;
    -	}
    -	/*
    -	 * Grab the freespace record.
    -	 */
    -	if ((error = xfs_alloc_get_rec(bno_cur, &fbno, &flen, &i)))
    -		goto error0;
    -	XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -	ASSERT(fbno <= args->agbno);
    -	minend = args->agbno + args->minlen;
    -	maxend = args->agbno + args->maxlen;
    -	fend = fbno + flen;
    -	/*
    -	 * Give up if the freespace isn't long enough for the minimum request.
    -	 */
    -	if (fend < minend) {
    -		xfs_btree_del_cursor(bno_cur, XFS_BTREE_NOERROR);
    -		args->agbno = NULLAGBLOCK;
    -		return 0;
    -	}
    -	/*
    -	 * End of extent will be smaller of the freespace end and the
    -	 * maximal requested end.
    -	 */
    -	end = XFS_AGBLOCK_MIN(fend, maxend);
    -	/*
    -	 * Fix the length according to mod and prod if given.
    -	 */
    -	args->len = end - args->agbno;
    -	xfs_alloc_fix_len(args);
    -	if (!xfs_alloc_fix_minleft(args)) {
    -		xfs_btree_del_cursor(bno_cur, XFS_BTREE_NOERROR);
    -		return 0;
    -	}
    -	rlen = args->len;
    -	ASSERT(args->agbno + rlen <= fend);
    -	end = args->agbno + rlen;
    -	/*
    -	 * We are allocating agbno for rlen [agbno .. end]
    -	 * Allocate/initialize a cursor for the by-size btree.
    -	 */
    -	cnt_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
    -		args->agno, XFS_BTNUM_CNT, NULL, 0);
    -	ASSERT(args->agbno + args->len <=
    -		be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length));
    -	if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur, fbno, flen,
    -			args->agbno, args->len, XFSA_FIXUP_BNO_OK))) {
    -		xfs_btree_del_cursor(cnt_cur, XFS_BTREE_ERROR);
    -		goto error0;
    -	}
    -	xfs_btree_del_cursor(bno_cur, XFS_BTREE_NOERROR);
    -	xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR);
    -	TRACE_ALLOC("normal", args);
    -	args->wasfromfl = 0;
    -	return 0;
    -
    -error0:
    -	xfs_btree_del_cursor(bno_cur, XFS_BTREE_ERROR);
    -	TRACE_ALLOC("error", args);
    -	return error;
    -}
    -
    -/*
    - * Allocate a variable extent near bno in the allocation group agno.
    - * Extent's length (returned in len) will be between minlen and maxlen,
    - * and of the form k * prod + mod unless there's nothing that large.
    - * Return the starting a.g. block, or NULLAGBLOCK if we can't do it.
    - */
    -STATIC int				/* error */
    -xfs_alloc_ag_vextent_near(
    -	xfs_alloc_arg_t	*args)		/* allocation argument structure */
    -{
    -	xfs_btree_cur_t	*bno_cur_gt;	/* cursor for bno btree, right side */
    -	xfs_btree_cur_t	*bno_cur_lt;	/* cursor for bno btree, left side */
    -	xfs_btree_cur_t	*cnt_cur;	/* cursor for count btree */
    -#ifdef XFS_ALLOC_TRACE
    -	static char	fname[] = "xfs_alloc_ag_vextent_near";
    -#endif
    -	xfs_agblock_t	gtbno;		/* start bno of right side entry */
    -	xfs_agblock_t	gtbnoa;		/* aligned ... */
    -	xfs_extlen_t	gtdiff;		/* difference to right side entry */
    -	xfs_extlen_t	gtlen;		/* length of right side entry */
    -	xfs_extlen_t	gtlena;		/* aligned ... */
    -	xfs_agblock_t	gtnew;		/* useful start bno of right side */
    -	int		error;		/* error code */
    -	int		i;		/* result code, temporary */
    -	int		j;		/* result code, temporary */
    -	xfs_agblock_t	ltbno;		/* start bno of left side entry */
    -	xfs_agblock_t	ltbnoa;		/* aligned ... */
    -	xfs_extlen_t	ltdiff;		/* difference to left side entry */
    -	/*REFERENCED*/
    -	xfs_agblock_t	ltend;		/* end bno of left side entry */
    -	xfs_extlen_t	ltlen;		/* length of left side entry */
    -	xfs_extlen_t	ltlena;		/* aligned ... */
    -	xfs_agblock_t	ltnew;		/* useful start bno of left side */
    -	xfs_extlen_t	rlen;		/* length of returned extent */
    -#if defined(DEBUG) && defined(__KERNEL__)
    -	/*
    -	 * Randomly don't execute the first algorithm.
    -	 */
    -	int		dofirst;	/* set to do first algorithm */
    -
    -	dofirst = random() & 1;
    -#endif
    -	/*
    -	 * Get a cursor for the by-size btree.
    -	 */
    -	cnt_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
    -		args->agno, XFS_BTNUM_CNT, NULL, 0);
    -	ltlen = 0;
    -	bno_cur_lt = bno_cur_gt = NULL;
    -	/*
    -	 * See if there are any free extents as big as maxlen.
    -	 */
    -	if ((error = xfs_alloc_lookup_ge(cnt_cur, 0, args->maxlen, &i)))
    -		goto error0;
    -	/*
    -	 * If none, then pick up the last entry in the tree unless the
    -	 * tree is empty.
    -	 */
    -	if (!i) {
    -		if ((error = xfs_alloc_ag_vextent_small(args, cnt_cur, <bno,
    -				<len, &i)))
    -			goto error0;
    -		if (i == 0 || ltlen == 0) {
    -			xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR);
    -			return 0;
    -		}
    -		ASSERT(i == 1);
    -	}
    -	args->wasfromfl = 0;
    -	/*
    -	 * First algorithm.
    -	 * If the requested extent is large wrt the freespaces available
    -	 * in this a.g., then the cursor will be pointing to a btree entry
    -	 * near the right edge of the tree.  If it's in the last btree leaf
    -	 * block, then we just examine all the entries in that block
    -	 * that are big enough, and pick the best one.
    -	 * This is written as a while loop so we can break out of it,
    -	 * but we never loop back to the top.
    -	 */
    -	while (xfs_btree_islastblock(cnt_cur, 0)) {
    -		xfs_extlen_t	bdiff;
    -		int		besti=0;
    -		xfs_extlen_t	blen=0;
    -		xfs_agblock_t	bnew=0;
    -
    -#if defined(DEBUG) && defined(__KERNEL__)
    -		if (!dofirst)
    -			break;
    -#endif
    -		/*
    -		 * Start from the entry that lookup found, sequence through
    -		 * all larger free blocks.  If we're actually pointing at a
    -		 * record smaller than maxlen, go to the start of this block,
    -		 * and skip all those smaller than minlen.
    -		 */
    -		if (ltlen || args->alignment > 1) {
    -			cnt_cur->bc_ptrs[0] = 1;
    -			do {
    -				if ((error = xfs_alloc_get_rec(cnt_cur, <bno,
    -						<len, &i)))
    -					goto error0;
    -				XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -				if (ltlen >= args->minlen)
    -					break;
    -				if ((error = xfs_alloc_increment(cnt_cur, 0, &i)))
    -					goto error0;
    -			} while (i);
    -			ASSERT(ltlen >= args->minlen);
    -			if (!i)
    -				break;
    -		}
    -		i = cnt_cur->bc_ptrs[0];
    -		for (j = 1, blen = 0, bdiff = 0;
    -		     !error && j && (blen < args->maxlen || bdiff > 0);
    -		     error = xfs_alloc_increment(cnt_cur, 0, &j)) {
    -			/*
    -			 * For each entry, decide if it's better than
    -			 * the previous best entry.
    -			 */
    -			if ((error = xfs_alloc_get_rec(cnt_cur, <bno, <len, &i)))
    -				goto error0;
    -			XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -			if (!xfs_alloc_compute_aligned(ltbno, ltlen,
    -					args->alignment, args->minlen,
    -					<bnoa, <lena))
    -				continue;
    -			args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen);
    -			xfs_alloc_fix_len(args);
    -			ASSERT(args->len >= args->minlen);
    -			if (args->len < blen)
    -				continue;
    -			ltdiff = xfs_alloc_compute_diff(args->agbno, args->len,
    -				args->alignment, ltbno, ltlen, <new);
    -			if (ltnew != NULLAGBLOCK &&
    -			    (args->len > blen || ltdiff < bdiff)) {
    -				bdiff = ltdiff;
    -				bnew = ltnew;
    -				blen = args->len;
    -				besti = cnt_cur->bc_ptrs[0];
    -			}
    -		}
    -		/*
    -		 * It didn't work.  We COULD be in a case where
    -		 * there's a good record somewhere, so try again.
    -		 */
    -		if (blen == 0)
    -			break;
    -		/*
    -		 * Point at the best entry, and retrieve it again.
    -		 */
    -		cnt_cur->bc_ptrs[0] = besti;
    -		if ((error = xfs_alloc_get_rec(cnt_cur, <bno, <len, &i)))
    -			goto error0;
    -		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -		ltend = ltbno + ltlen;
    -		ASSERT(ltend <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length));
    -		args->len = blen;
    -		if (!xfs_alloc_fix_minleft(args)) {
    -			xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR);
    -			TRACE_ALLOC("nominleft", args);
    -			return 0;
    -		}
    -		blen = args->len;
    -		/*
    -		 * We are allocating starting at bnew for blen blocks.
    -		 */
    -		args->agbno = bnew;
    -		ASSERT(bnew >= ltbno);
    -		ASSERT(bnew + blen <= ltend);
    -		/*
    -		 * Set up a cursor for the by-bno tree.
    -		 */
    -		bno_cur_lt = xfs_btree_init_cursor(args->mp, args->tp,
    -			args->agbp, args->agno, XFS_BTNUM_BNO, NULL, 0);
    -		/*
    -		 * Fix up the btree entries.
    -		 */
    -		if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur_lt, ltbno,
    -				ltlen, bnew, blen, XFSA_FIXUP_CNT_OK)))
    -			goto error0;
    -		xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR);
    -		xfs_btree_del_cursor(bno_cur_lt, XFS_BTREE_NOERROR);
    -		TRACE_ALLOC("first", args);
    -		return 0;
    -	}
    -	/*
    -	 * Second algorithm.
    -	 * Search in the by-bno tree to the left and to the right
    -	 * simultaneously, until in each case we find a space big enough,
    -	 * or run into the edge of the tree.  When we run into the edge,
    -	 * we deallocate that cursor.
    -	 * If both searches succeed, we compare the two spaces and pick
    -	 * the better one.
    -	 * With alignment, it's possible for both to fail; the upper
    -	 * level algorithm that picks allocation groups for allocations
    -	 * is not supposed to do this.
    -	 */
    -	/*
    -	 * Allocate and initialize the cursor for the leftward search.
    -	 */
    -	bno_cur_lt = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
    -		args->agno, XFS_BTNUM_BNO, NULL, 0);
    -	/*
    -	 * Lookup <= bno to find the leftward search's starting point.
    -	 */
    -	if ((error = xfs_alloc_lookup_le(bno_cur_lt, args->agbno, args->maxlen, &i)))
    -		goto error0;
    -	if (!i) {
    -		/*
    -		 * Didn't find anything; use this cursor for the rightward
    -		 * search.
    -		 */
    -		bno_cur_gt = bno_cur_lt;
    -		bno_cur_lt = NULL;
    -	}
    -	/*
    -	 * Found something.  Duplicate the cursor for the rightward search.
    -	 */
    -	else if ((error = xfs_btree_dup_cursor(bno_cur_lt, &bno_cur_gt)))
    -		goto error0;
    -	/*
    -	 * Increment the cursor, so we will point at the entry just right
    -	 * of the leftward entry if any, or to the leftmost entry.
    -	 */
    -	if ((error = xfs_alloc_increment(bno_cur_gt, 0, &i)))
    -		goto error0;
    -	if (!i) {
    -		/*
    -		 * It failed, there are no rightward entries.
    -		 */
    -		xfs_btree_del_cursor(bno_cur_gt, XFS_BTREE_NOERROR);
    -		bno_cur_gt = NULL;
    -	}
    -	/*
    -	 * Loop going left with the leftward cursor, right with the
    -	 * rightward cursor, until either both directions give up or
    -	 * we find an entry at least as big as minlen.
    -	 */
    -	do {
    -		if (bno_cur_lt) {
    -			if ((error = xfs_alloc_get_rec(bno_cur_lt, <bno, <len, &i)))
    -				goto error0;
    -			XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -			if (xfs_alloc_compute_aligned(ltbno, ltlen,
    -					args->alignment, args->minlen,
    -					<bnoa, <lena))
    -				break;
    -			if ((error = xfs_alloc_decrement(bno_cur_lt, 0, &i)))
    -				goto error0;
    -			if (!i) {
    -				xfs_btree_del_cursor(bno_cur_lt,
    -						     XFS_BTREE_NOERROR);
    -				bno_cur_lt = NULL;
    -			}
    -		}
    -		if (bno_cur_gt) {
    -			if ((error = xfs_alloc_get_rec(bno_cur_gt, >bno, >len, &i)))
    -				goto error0;
    -			XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -			if (xfs_alloc_compute_aligned(gtbno, gtlen,
    -					args->alignment, args->minlen,
    -					>bnoa, >lena))
    -				break;
    -			if ((error = xfs_alloc_increment(bno_cur_gt, 0, &i)))
    -				goto error0;
    -			if (!i) {
    -				xfs_btree_del_cursor(bno_cur_gt,
    -						     XFS_BTREE_NOERROR);
    -				bno_cur_gt = NULL;
    -			}
    -		}
    -	} while (bno_cur_lt || bno_cur_gt);
    -	/*
    -	 * Got both cursors still active, need to find better entry.
    -	 */
    -	if (bno_cur_lt && bno_cur_gt) {
    -		/*
    -		 * Left side is long enough, look for a right side entry.
    -		 */
    -		if (ltlena >= args->minlen) {
    -			/*
    -			 * Fix up the length.
    -			 */
    -			args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen);
    -			xfs_alloc_fix_len(args);
    -			rlen = args->len;
    -			ltdiff = xfs_alloc_compute_diff(args->agbno, rlen,
    -				args->alignment, ltbno, ltlen, <new);
    -			/*
    -			 * Not perfect.
    -			 */
    -			if (ltdiff) {
    -				/*
    -				 * Look until we find a better one, run out of
    -				 * space, or run off the end.
    -				 */
    -				while (bno_cur_lt && bno_cur_gt) {
    -					if ((error = xfs_alloc_get_rec(
    -							bno_cur_gt, >bno,
    -							>len, &i)))
    -						goto error0;
    -					XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -					xfs_alloc_compute_aligned(gtbno, gtlen,
    -						args->alignment, args->minlen,
    -						>bnoa, >lena);
    -					/*
    -					 * The left one is clearly better.
    -					 */
    -					if (gtbnoa >= args->agbno + ltdiff) {
    -						xfs_btree_del_cursor(
    -							bno_cur_gt,
    -							XFS_BTREE_NOERROR);
    -						bno_cur_gt = NULL;
    -						break;
    -					}
    -					/*
    -					 * If we reach a big enough entry,
    -					 * compare the two and pick the best.
    -					 */
    -					if (gtlena >= args->minlen) {
    -						args->len =
    -							XFS_EXTLEN_MIN(gtlena,
    -								args->maxlen);
    -						xfs_alloc_fix_len(args);
    -						rlen = args->len;
    -						gtdiff = xfs_alloc_compute_diff(
    -							args->agbno, rlen,
    -							args->alignment,
    -							gtbno, gtlen, >new);
    -						/*
    -						 * Right side is better.
    -						 */
    -						if (gtdiff < ltdiff) {
    -							xfs_btree_del_cursor(
    -								bno_cur_lt,
    -								XFS_BTREE_NOERROR);
    -							bno_cur_lt = NULL;
    -						}
    -						/*
    -						 * Left side is better.
    -						 */
    -						else {
    -							xfs_btree_del_cursor(
    -								bno_cur_gt,
    -								XFS_BTREE_NOERROR);
    -							bno_cur_gt = NULL;
    -						}
    -						break;
    -					}
    -					/*
    -					 * Fell off the right end.
    -					 */
    -					if ((error = xfs_alloc_increment(
    -							bno_cur_gt, 0, &i)))
    -						goto error0;
    -					if (!i) {
    -						xfs_btree_del_cursor(
    -							bno_cur_gt,
    -							XFS_BTREE_NOERROR);
    -						bno_cur_gt = NULL;
    -						break;
    -					}
    -				}
    -			}
    -			/*
    -			 * The left side is perfect, trash the right side.
    -			 */
    -			else {
    -				xfs_btree_del_cursor(bno_cur_gt,
    -						     XFS_BTREE_NOERROR);
    -				bno_cur_gt = NULL;
    -			}
    -		}
    -		/*
    -		 * It's the right side that was found first, look left.
    -		 */
    -		else {
    -			/*
    -			 * Fix up the length.
    -			 */
    -			args->len = XFS_EXTLEN_MIN(gtlena, args->maxlen);
    -			xfs_alloc_fix_len(args);
    -			rlen = args->len;
    -			gtdiff = xfs_alloc_compute_diff(args->agbno, rlen,
    -				args->alignment, gtbno, gtlen, >new);
    -			/*
    -			 * Right side entry isn't perfect.
    -			 */
    -			if (gtdiff) {
    -				/*
    -				 * Look until we find a better one, run out of
    -				 * space, or run off the end.
    -				 */
    -				while (bno_cur_lt && bno_cur_gt) {
    -					if ((error = xfs_alloc_get_rec(
    -							bno_cur_lt, <bno,
    -							<len, &i)))
    -						goto error0;
    -					XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -					xfs_alloc_compute_aligned(ltbno, ltlen,
    -						args->alignment, args->minlen,
    -						<bnoa, <lena);
    -					/*
    -					 * The right one is clearly better.
    -					 */
    -					if (ltbnoa <= args->agbno - gtdiff) {
    -						xfs_btree_del_cursor(
    -							bno_cur_lt,
    -							XFS_BTREE_NOERROR);
    -						bno_cur_lt = NULL;
    -						break;
    -					}
    -					/*
    -					 * If we reach a big enough entry,
    -					 * compare the two and pick the best.
    -					 */
    -					if (ltlena >= args->minlen) {
    -						args->len = XFS_EXTLEN_MIN(
    -							ltlena, args->maxlen);
    -						xfs_alloc_fix_len(args);
    -						rlen = args->len;
    -						ltdiff = xfs_alloc_compute_diff(
    -							args->agbno, rlen,
    -							args->alignment,
    -							ltbno, ltlen, <new);
    -						/*
    -						 * Left side is better.
    -						 */
    -						if (ltdiff < gtdiff) {
    -							xfs_btree_del_cursor(
    -								bno_cur_gt,
    -								XFS_BTREE_NOERROR);
    -							bno_cur_gt = NULL;
    -						}
    -						/*
    -						 * Right side is better.
    -						 */
    -						else {
    -							xfs_btree_del_cursor(
    -								bno_cur_lt,
    -								XFS_BTREE_NOERROR);
    -							bno_cur_lt = NULL;
    -						}
    -						break;
    -					}
    -					/*
    -					 * Fell off the left end.
    -					 */
    -					if ((error = xfs_alloc_decrement(
    -							bno_cur_lt, 0, &i)))
    -						goto error0;
    -					if (!i) {
    -						xfs_btree_del_cursor(bno_cur_lt,
    -							XFS_BTREE_NOERROR);
    -						bno_cur_lt = NULL;
    -						break;
    -					}
    -				}
    -			}
    -			/*
    -			 * The right side is perfect, trash the left side.
    -			 */
    -			else {
    -				xfs_btree_del_cursor(bno_cur_lt,
    -					XFS_BTREE_NOERROR);
    -				bno_cur_lt = NULL;
    -			}
    -		}
    -	}
    -	/*
    -	 * If we couldn't get anything, give up.
    -	 */
    -	if (bno_cur_lt == NULL && bno_cur_gt == NULL) {
    -		TRACE_ALLOC("neither", args);
    -		args->agbno = NULLAGBLOCK;
    -		return 0;
    -	}
    -	/*
    -	 * At this point we have selected a freespace entry, either to the
    -	 * left or to the right.  If it's on the right, copy all the
    -	 * useful variables to the "left" set so we only have one
    -	 * copy of this code.
    -	 */
    -	if (bno_cur_gt) {
    -		bno_cur_lt = bno_cur_gt;
    -		bno_cur_gt = NULL;
    -		ltbno = gtbno;
    -		ltbnoa = gtbnoa;
    -		ltlen = gtlen;
    -		ltlena = gtlena;
    -		j = 1;
    -	} else
    -		j = 0;
    -	/*
    -	 * Fix up the length and compute the useful address.
    -	 */
    -	ltend = ltbno + ltlen;
    -	args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen);
    -	xfs_alloc_fix_len(args);
    -	if (!xfs_alloc_fix_minleft(args)) {
    -		TRACE_ALLOC("nominleft", args);
    -		xfs_btree_del_cursor(bno_cur_lt, XFS_BTREE_NOERROR);
    -		xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR);
    -		return 0;
    -	}
    -	rlen = args->len;
    -	(void)xfs_alloc_compute_diff(args->agbno, rlen, args->alignment, ltbno,
    -		ltlen, <new);
    -	ASSERT(ltnew >= ltbno);
    -	ASSERT(ltnew + rlen <= ltend);
    -	ASSERT(ltnew + rlen <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length));
    -	args->agbno = ltnew;
    -	if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur_lt, ltbno, ltlen,
    -			ltnew, rlen, XFSA_FIXUP_BNO_OK)))
    -		goto error0;
    -	TRACE_ALLOC(j ? "gt" : "lt", args);
    -	xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR);
    -	xfs_btree_del_cursor(bno_cur_lt, XFS_BTREE_NOERROR);
    -	return 0;
    -
    - error0:
    -	TRACE_ALLOC("error", args);
    -	if (cnt_cur != NULL)
    -		xfs_btree_del_cursor(cnt_cur, XFS_BTREE_ERROR);
    -	if (bno_cur_lt != NULL)
    -		xfs_btree_del_cursor(bno_cur_lt, XFS_BTREE_ERROR);
    -	if (bno_cur_gt != NULL)
    -		xfs_btree_del_cursor(bno_cur_gt, XFS_BTREE_ERROR);
    -	return error;
    -}
    -
    -/*
    - * Allocate a variable extent anywhere in the allocation group agno.
    - * Extent's length (returned in len) will be between minlen and maxlen,
    - * and of the form k * prod + mod unless there's nothing that large.
    - * Return the starting a.g. block, or NULLAGBLOCK if we can't do it.
    - */
    -STATIC int				/* error */
    -xfs_alloc_ag_vextent_size(
    -	xfs_alloc_arg_t	*args)		/* allocation argument structure */
    -{
    -	xfs_btree_cur_t	*bno_cur;	/* cursor for bno btree */
    -	xfs_btree_cur_t	*cnt_cur;	/* cursor for cnt btree */
    -	int		error;		/* error result */
    -	xfs_agblock_t	fbno;		/* start of found freespace */
    -	xfs_extlen_t	flen;		/* length of found freespace */
    -#ifdef XFS_ALLOC_TRACE
    -	static char	fname[] = "xfs_alloc_ag_vextent_size";
    -#endif
    -	int		i;		/* temp status variable */
    -	xfs_agblock_t	rbno;		/* returned block number */
    -	xfs_extlen_t	rlen;		/* length of returned extent */
    -
    -	/*
    -	 * Allocate and initialize a cursor for the by-size btree.
    -	 */
    -	cnt_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
    -		args->agno, XFS_BTNUM_CNT, NULL, 0);
    -	bno_cur = NULL;
    -	/*
    -	 * Look for an entry >= maxlen+alignment-1 blocks.
    -	 */
    -	if ((error = xfs_alloc_lookup_ge(cnt_cur, 0,
    -			args->maxlen + args->alignment - 1, &i)))
    -		goto error0;
    -	/*
    -	 * If none, then pick up the last entry in the tree unless the
    -	 * tree is empty.
    -	 */
    -	if (!i) {
    -		if ((error = xfs_alloc_ag_vextent_small(args, cnt_cur, &fbno,
    -				&flen, &i)))
    -			goto error0;
    -		if (i == 0 || flen == 0) {
    -			xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR);
    -			TRACE_ALLOC("noentry", args);
    -			return 0;
    -		}
    -		ASSERT(i == 1);
    -	}
    -	/*
    -	 * There's a freespace as big as maxlen+alignment-1, get it.
    -	 */
    -	else {
    -		if ((error = xfs_alloc_get_rec(cnt_cur, &fbno, &flen, &i)))
    -			goto error0;
    -		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -	}
    -	/*
    -	 * In the first case above, we got the last entry in the
    -	 * by-size btree.  Now we check to see if the space hits maxlen
    -	 * once aligned; if not, we search left for something better.
    -	 * This can't happen in the second case above.
    -	 */
    -	xfs_alloc_compute_aligned(fbno, flen, args->alignment, args->minlen,
    -		&rbno, &rlen);
    -	rlen = XFS_EXTLEN_MIN(args->maxlen, rlen);
    -	XFS_WANT_CORRUPTED_GOTO(rlen == 0 ||
    -			(rlen <= flen && rbno + rlen <= fbno + flen), error0);
    -	if (rlen < args->maxlen) {
    -		xfs_agblock_t	bestfbno;
    -		xfs_extlen_t	bestflen;
    -		xfs_agblock_t	bestrbno;
    -		xfs_extlen_t	bestrlen;
    -
    -		bestrlen = rlen;
    -		bestrbno = rbno;
    -		bestflen = flen;
    -		bestfbno = fbno;
    -		for (;;) {
    -			if ((error = xfs_alloc_decrement(cnt_cur, 0, &i)))
    -				goto error0;
    -			if (i == 0)
    -				break;
    -			if ((error = xfs_alloc_get_rec(cnt_cur, &fbno, &flen,
    -					&i)))
    -				goto error0;
    -			XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -			if (flen < bestrlen)
    -				break;
    -			xfs_alloc_compute_aligned(fbno, flen, args->alignment,
    -				args->minlen, &rbno, &rlen);
    -			rlen = XFS_EXTLEN_MIN(args->maxlen, rlen);
    -			XFS_WANT_CORRUPTED_GOTO(rlen == 0 ||
    -				(rlen <= flen && rbno + rlen <= fbno + flen),
    -				error0);
    -			if (rlen > bestrlen) {
    -				bestrlen = rlen;
    -				bestrbno = rbno;
    -				bestflen = flen;
    -				bestfbno = fbno;
    -				if (rlen == args->maxlen)
    -					break;
    -			}
    -		}
    -		if ((error = xfs_alloc_lookup_eq(cnt_cur, bestfbno, bestflen,
    -				&i)))
    -			goto error0;
    -		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -		rlen = bestrlen;
    -		rbno = bestrbno;
    -		flen = bestflen;
    -		fbno = bestfbno;
    -	}
    -	args->wasfromfl = 0;
    -	/*
    -	 * Fix up the length.
    -	 */
    -	args->len = rlen;
    -	xfs_alloc_fix_len(args);
    -	if (rlen < args->minlen || !xfs_alloc_fix_minleft(args)) {
    -		xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR);
    -		TRACE_ALLOC("nominleft", args);
    -		args->agbno = NULLAGBLOCK;
    -		return 0;
    -	}
    -	rlen = args->len;
    -	XFS_WANT_CORRUPTED_GOTO(rlen <= flen, error0);
    -	/*
    -	 * Allocate and initialize a cursor for the by-block tree.
    -	 */
    -	bno_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
    -		args->agno, XFS_BTNUM_BNO, NULL, 0);
    -	if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur, fbno, flen,
    -			rbno, rlen, XFSA_FIXUP_CNT_OK)))
    -		goto error0;
    -	xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR);
    -	xfs_btree_del_cursor(bno_cur, XFS_BTREE_NOERROR);
    -	cnt_cur = bno_cur = NULL;
    -	args->len = rlen;
    -	args->agbno = rbno;
    -	XFS_WANT_CORRUPTED_GOTO(
    -		args->agbno + args->len <=
    -			be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length),
    -		error0);
    -	TRACE_ALLOC("normal", args);
    -	return 0;
    -
    -error0:
    -	TRACE_ALLOC("error", args);
    -	if (cnt_cur)
    -		xfs_btree_del_cursor(cnt_cur, XFS_BTREE_ERROR);
    -	if (bno_cur)
    -		xfs_btree_del_cursor(bno_cur, XFS_BTREE_ERROR);
    -	return error;
    -}
    -
    -/*
    - * Deal with the case where only small freespaces remain.
    - * Either return the contents of the last freespace record,
    - * or allocate space from the freelist if there is nothing in the tree.
    - */
    -STATIC int			/* error */
    -xfs_alloc_ag_vextent_small(
    -	xfs_alloc_arg_t	*args,	/* allocation argument structure */
    -	xfs_btree_cur_t	*ccur,	/* by-size cursor */
    -	xfs_agblock_t	*fbnop,	/* result block number */
    -	xfs_extlen_t	*flenp,	/* result length */
    -	int		*stat)	/* status: 0-freelist, 1-normal/none */
    -{
    -	int		error;
    -	xfs_agblock_t	fbno;
    -	xfs_extlen_t	flen;
    -#ifdef XFS_ALLOC_TRACE
    -	static char	fname[] = "xfs_alloc_ag_vextent_small";
    -#endif
    -	int		i;
    -
    -	if ((error = xfs_alloc_decrement(ccur, 0, &i)))
    -		goto error0;
    -	if (i) {
    -		if ((error = xfs_alloc_get_rec(ccur, &fbno, &flen, &i)))
    -			goto error0;
    -		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -	}
    -	/*
    -	 * Nothing in the btree, try the freelist.  Make sure
    -	 * to respect minleft even when pulling from the
    -	 * freelist.
    -	 */
    -	else if (args->minlen == 1 && args->alignment == 1 && !args->isfl &&
    -		 (be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_flcount)
    -		  > args->minleft)) {
    -		if ((error = xfs_alloc_get_freelist(args->tp, args->agbp, &fbno)))
    -			goto error0;
    -		if (fbno != NULLAGBLOCK) {
    -			if (args->userdata) {
    -				xfs_buf_t	*bp;
    -
    -				bp = xfs_btree_get_bufs(args->mp, args->tp,
    -					args->agno, fbno, 0);
    -				xfs_trans_binval(args->tp, bp);
    -			}
    -			args->len = 1;
    -			args->agbno = fbno;
    -			XFS_WANT_CORRUPTED_GOTO(
    -				args->agbno + args->len <=
    -				be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length),
    -				error0);
    -			args->wasfromfl = 1;
    -			TRACE_ALLOC("freelist", args);
    -			*stat = 0;
    -			return 0;
    -		}
    -		/*
    -		 * Nothing in the freelist.
    -		 */
    -		else
    -			flen = 0;
    -	}
    -	/*
    -	 * Can't allocate from the freelist for some reason.
    -	 */
    -	else {
    -		fbno = NULLAGBLOCK;
    -		flen = 0;
    -	}
    -	/*
    -	 * Can't do the allocation, give up.
    -	 */
    -	if (flen < args->minlen) {
    -		args->agbno = NULLAGBLOCK;
    -		TRACE_ALLOC("notenough", args);
    -		flen = 0;
    -	}
    -	*fbnop = fbno;
    -	*flenp = flen;
    -	*stat = 1;
    -	TRACE_ALLOC("normal", args);
    -	return 0;
    -
    -error0:
    -	TRACE_ALLOC("error", args);
    -	return error;
    -}
    -
    -/*
    - * Free the extent starting at agno/bno for length.
    - */
    -STATIC int			/* error */
    -xfs_free_ag_extent(
    -	xfs_trans_t	*tp,	/* transaction pointer */
    -	xfs_buf_t	*agbp,	/* buffer for a.g. freelist header */
    -	xfs_agnumber_t	agno,	/* allocation group number */
    -	xfs_agblock_t	bno,	/* starting block number */
    -	xfs_extlen_t	len,	/* length of extent */
    -	int		isfl)	/* set if is freelist blocks - no sb acctg */
    -{
    -	xfs_btree_cur_t	*bno_cur;	/* cursor for by-block btree */
    -	xfs_btree_cur_t	*cnt_cur;	/* cursor for by-size btree */
    -	int		error;		/* error return value */
    -#ifdef XFS_ALLOC_TRACE
    -	static char	fname[] = "xfs_free_ag_extent";
    -#endif
    -	xfs_agblock_t	gtbno;		/* start of right neighbor block */
    -	xfs_extlen_t	gtlen;		/* length of right neighbor block */
    -	int		haveleft;	/* have a left neighbor block */
    -	int		haveright;	/* have a right neighbor block */
    -	int		i;		/* temp, result code */
    -	xfs_agblock_t	ltbno;		/* start of left neighbor block */
    -	xfs_extlen_t	ltlen;		/* length of left neighbor block */
    -	xfs_mount_t	*mp;		/* mount point struct for filesystem */
    -	xfs_agblock_t	nbno;		/* new starting block of freespace */
    -	xfs_extlen_t	nlen;		/* new length of freespace */
    -
    -	mp = tp->t_mountp;
    -	/*
    -	 * Allocate and initialize a cursor for the by-block btree.
    -	 */
    -	bno_cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_BNO, NULL,
    -		0);
    -	cnt_cur = NULL;
    -	/*
    -	 * Look for a neighboring block on the left (lower block numbers)
    -	 * that is contiguous with this space.
    -	 */
    -	if ((error = xfs_alloc_lookup_le(bno_cur, bno, len, &haveleft)))
    -		goto error0;
    -	if (haveleft) {
    -		/*
    -		 * There is a block to our left.
    -		 */
    -		if ((error = xfs_alloc_get_rec(bno_cur, <bno, <len, &i)))
    -			goto error0;
    -		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -		/*
    -		 * It's not contiguous, though.
    -		 */
    -		if (ltbno + ltlen < bno)
    -			haveleft = 0;
    -		else {
    -			/*
    -			 * If this failure happens the request to free this
    -			 * space was invalid, it's (partly) already free.
    -			 * Very bad.
    -			 */
    -			XFS_WANT_CORRUPTED_GOTO(ltbno + ltlen <= bno, error0);
    -		}
    -	}
    -	/*
    -	 * Look for a neighboring block on the right (higher block numbers)
    -	 * that is contiguous with this space.
    -	 */
    -	if ((error = xfs_alloc_increment(bno_cur, 0, &haveright)))
    -		goto error0;
    -	if (haveright) {
    -		/*
    -		 * There is a block to our right.
    -		 */
    -		if ((error = xfs_alloc_get_rec(bno_cur, >bno, >len, &i)))
    -			goto error0;
    -		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -		/*
    -		 * It's not contiguous, though.
    -		 */
    -		if (bno + len < gtbno)
    -			haveright = 0;
    -		else {
    -			/*
    -			 * If this failure happens the request to free this
    -			 * space was invalid, it's (partly) already free.
    -			 * Very bad.
    -			 */
    -			XFS_WANT_CORRUPTED_GOTO(gtbno >= bno + len, error0);
    -		}
    -	}
    -	/*
    -	 * Now allocate and initialize a cursor for the by-size tree.
    -	 */
    -	cnt_cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_CNT, NULL,
    -		0);
    -	/*
    -	 * Have both left and right contiguous neighbors.
    -	 * Merge all three into a single free block.
    -	 */
    -	if (haveleft && haveright) {
    -		/*
    -		 * Delete the old by-size entry on the left.
    -		 */
    -		if ((error = xfs_alloc_lookup_eq(cnt_cur, ltbno, ltlen, &i)))
    -			goto error0;
    -		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -		if ((error = xfs_alloc_delete(cnt_cur, &i)))
    -			goto error0;
    -		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -		/*
    -		 * Delete the old by-size entry on the right.
    -		 */
    -		if ((error = xfs_alloc_lookup_eq(cnt_cur, gtbno, gtlen, &i)))
    -			goto error0;
    -		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -		if ((error = xfs_alloc_delete(cnt_cur, &i)))
    -			goto error0;
    -		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -		/*
    -		 * Delete the old by-block entry for the right block.
    -		 */
    -		if ((error = xfs_alloc_delete(bno_cur, &i)))
    -			goto error0;
    -		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -		/*
    -		 * Move the by-block cursor back to the left neighbor.
    -		 */
    -		if ((error = xfs_alloc_decrement(bno_cur, 0, &i)))
    -			goto error0;
    -		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -#ifdef DEBUG
    -		/*
    -		 * Check that this is the right record: delete didn't
    -		 * mangle the cursor.
    -		 */
    -		{
    -			xfs_agblock_t	xxbno;
    -			xfs_extlen_t	xxlen;
    -
    -			if ((error = xfs_alloc_get_rec(bno_cur, &xxbno, &xxlen,
    -					&i)))
    -				goto error0;
    -			XFS_WANT_CORRUPTED_GOTO(
    -				i == 1 && xxbno == ltbno && xxlen == ltlen,
    -				error0);
    -		}
    -#endif
    -		/*
    -		 * Update remaining by-block entry to the new, joined block.
    -		 */
    -		nbno = ltbno;
    -		nlen = len + ltlen + gtlen;
    -		if ((error = xfs_alloc_update(bno_cur, nbno, nlen)))
    -			goto error0;
    -	}
    -	/*
    -	 * Have only a left contiguous neighbor.
    -	 * Merge it together with the new freespace.
    -	 */
    -	else if (haveleft) {
    -		/*
    -		 * Delete the old by-size entry on the left.
    -		 */
    -		if ((error = xfs_alloc_lookup_eq(cnt_cur, ltbno, ltlen, &i)))
    -			goto error0;
    -		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -		if ((error = xfs_alloc_delete(cnt_cur, &i)))
    -			goto error0;
    -		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -		/*
    -		 * Back up the by-block cursor to the left neighbor, and
    -		 * update its length.
    -		 */
    -		if ((error = xfs_alloc_decrement(bno_cur, 0, &i)))
    -			goto error0;
    -		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -		nbno = ltbno;
    -		nlen = len + ltlen;
    -		if ((error = xfs_alloc_update(bno_cur, nbno, nlen)))
    -			goto error0;
    -	}
    -	/*
    -	 * Have only a right contiguous neighbor.
    -	 * Merge it together with the new freespace.
    -	 */
    -	else if (haveright) {
    -		/*
    -		 * Delete the old by-size entry on the right.
    -		 */
    -		if ((error = xfs_alloc_lookup_eq(cnt_cur, gtbno, gtlen, &i)))
    -			goto error0;
    -		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -		if ((error = xfs_alloc_delete(cnt_cur, &i)))
    -			goto error0;
    -		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -		/*
    -		 * Update the starting block and length of the right
    -		 * neighbor in the by-block tree.
    -		 */
    -		nbno = bno;
    -		nlen = len + gtlen;
    -		if ((error = xfs_alloc_update(bno_cur, nbno, nlen)))
    -			goto error0;
    -	}
    -	/*
    -	 * No contiguous neighbors.
    -	 * Insert the new freespace into the by-block tree.
    -	 */
    -	else {
    -		nbno = bno;
    -		nlen = len;
    -		if ((error = xfs_alloc_insert(bno_cur, &i)))
    -			goto error0;
    -		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -	}
    -	xfs_btree_del_cursor(bno_cur, XFS_BTREE_NOERROR);
    -	bno_cur = NULL;
    -	/*
    -	 * In all cases we need to insert the new freespace in the by-size tree.
    -	 */
    -	if ((error = xfs_alloc_lookup_eq(cnt_cur, nbno, nlen, &i)))
    -		goto error0;
    -	XFS_WANT_CORRUPTED_GOTO(i == 0, error0);
    -	if ((error = xfs_alloc_insert(cnt_cur, &i)))
    -		goto error0;
    -	XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -	xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR);
    -	cnt_cur = NULL;
    -	/*
    -	 * Update the freespace totals in the ag and superblock.
    -	 */
    -	{
    -		xfs_agf_t	*agf;
    -		xfs_perag_t	*pag;		/* per allocation group data */
    -
    -		agf = XFS_BUF_TO_AGF(agbp);
    -		pag = &mp->m_perag[agno];
    -		be32_add(&agf->agf_freeblks, len);
    -		xfs_trans_agblocks_delta(tp, len);
    -		pag->pagf_freeblks += len;
    -		XFS_WANT_CORRUPTED_GOTO(
    -			be32_to_cpu(agf->agf_freeblks) <=
    -			be32_to_cpu(agf->agf_length),
    -			error0);
    -		TRACE_MODAGF(NULL, agf, XFS_AGF_FREEBLKS);
    -		xfs_alloc_log_agf(tp, agbp, XFS_AGF_FREEBLKS);
    -		if (!isfl)
    -			xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, (long)len);
    -		XFS_STATS_INC(xs_freex);
    -		XFS_STATS_ADD(xs_freeb, len);
    -	}
    -	TRACE_FREE(haveleft ?
    -			(haveright ? "both" : "left") :
    -			(haveright ? "right" : "none"),
    -		agno, bno, len, isfl);
    -
    -	/*
    -	 * Since blocks move to the free list without the coordination
    -	 * used in xfs_bmap_finish, we can't allow block to be available
    -	 * for reallocation and non-transaction writing (user data)
    -	 * until we know that the transaction that moved it to the free
    -	 * list is permanently on disk.  We track the blocks by declaring
    -	 * these blocks as "busy"; the busy list is maintained on a per-ag
    -	 * basis and each transaction records which entries should be removed
    -	 * when the iclog commits to disk.  If a busy block is allocated,
    -	 * the iclog is pushed up to the LSN that freed the block.
    -	 */
    -	xfs_alloc_mark_busy(tp, agno, bno, len);
    -	return 0;
    -
    - error0:
    -	TRACE_FREE("error", agno, bno, len, isfl);
    -	if (bno_cur)
    -		xfs_btree_del_cursor(bno_cur, XFS_BTREE_ERROR);
    -	if (cnt_cur)
    -		xfs_btree_del_cursor(cnt_cur, XFS_BTREE_ERROR);
    -	return error;
    -}
    -
    -/*
    - * Visible (exported) allocation/free functions.
    - * Some of these are used just by xfs_alloc_btree.c and this file.
    - */
    -
    -/*
    - * Compute and fill in value of m_ag_maxlevels.
    - */
    -void
    -xfs_alloc_compute_maxlevels(
    -	xfs_mount_t	*mp)	/* file system mount structure */
    -{
    -	int		level;
    -	uint		maxblocks;
    -	uint		maxleafents;
    -	int		minleafrecs;
    -	int		minnoderecs;
    -
    -	maxleafents = (mp->m_sb.sb_agblocks + 1) / 2;
    -	minleafrecs = mp->m_alloc_mnr[0];
    -	minnoderecs = mp->m_alloc_mnr[1];
    -	maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs;
    -	for (level = 1; maxblocks > 1; level++)
    -		maxblocks = (maxblocks + minnoderecs - 1) / minnoderecs;
    -	mp->m_ag_maxlevels = level;
    -}
    -
    -/*
    - * Decide whether to use this allocation group for this allocation.
    - * If so, fix up the btree freelist's size.
    - */
    -STATIC int			/* error */
    -xfs_alloc_fix_freelist(
    -	xfs_alloc_arg_t	*args,	/* allocation argument structure */
    -	int		flags)	/* XFS_ALLOC_FLAG_... */
    -{
    -	xfs_buf_t	*agbp;	/* agf buffer pointer */
    -	xfs_agf_t	*agf;	/* a.g. freespace structure pointer */
    -	xfs_buf_t	*agflbp;/* agfl buffer pointer */
    -	xfs_agblock_t	bno;	/* freelist block */
    -	xfs_extlen_t	delta;	/* new blocks needed in freelist */
    -	int		error;	/* error result code */
    -	xfs_extlen_t	longest;/* longest extent in allocation group */
    -	xfs_mount_t	*mp;	/* file system mount point structure */
    -	xfs_extlen_t	need;	/* total blocks needed in freelist */
    -	xfs_perag_t	*pag;	/* per-ag information structure */
    -	xfs_alloc_arg_t	targs;	/* local allocation arguments */
    -	xfs_trans_t	*tp;	/* transaction pointer */
    -
    -	mp = args->mp;
    -
    -	pag = args->pag;
    -	tp = args->tp;
    -	if (!pag->pagf_init) {
    -		if ((error = xfs_alloc_read_agf(mp, tp, args->agno, flags,
    -				&agbp)))
    -			return error;
    -		if (!pag->pagf_init) {
    -			args->agbp = NULL;
    -			return 0;
    -		}
    -	} else
    -		agbp = NULL;
    -
    -	/* If this is a metadata preferred pag and we are user data
    -	 * then try somewhere else if we are not being asked to
    -	 * try harder at this point
    -	 */
    -	if (pag->pagf_metadata && args->userdata && flags) {
    -		args->agbp = NULL;
    -		return 0;
    -	}
    -
    -	need = XFS_MIN_FREELIST_PAG(pag, mp);
    -	delta = need > pag->pagf_flcount ? need - pag->pagf_flcount : 0;
    -	/*
    -	 * If it looks like there isn't a long enough extent, or enough
    -	 * total blocks, reject it.
    -	 */
    -	longest = (pag->pagf_longest > delta) ?
    -		(pag->pagf_longest - delta) :
    -		(pag->pagf_flcount > 0 || pag->pagf_longest > 0);
    -	if (args->minlen + args->alignment + args->minalignslop - 1 > longest ||
    -	    (args->minleft &&
    -	     (int)(pag->pagf_freeblks + pag->pagf_flcount -
    -		   need - args->total) <
    -	     (int)args->minleft)) {
    -		if (agbp)
    -			xfs_trans_brelse(tp, agbp);
    -		args->agbp = NULL;
    -		return 0;
    -	}
    -	/*
    -	 * Get the a.g. freespace buffer.
    -	 * Can fail if we're not blocking on locks, and it's held.
    -	 */
    -	if (agbp == NULL) {
    -		if ((error = xfs_alloc_read_agf(mp, tp, args->agno, flags,
    -				&agbp)))
    -			return error;
    -		if (agbp == NULL) {
    -			args->agbp = NULL;
    -			return 0;
    -		}
    -	}
    -	/*
    -	 * Figure out how many blocks we should have in the freelist.
    -	 */
    -	agf = XFS_BUF_TO_AGF(agbp);
    -	need = XFS_MIN_FREELIST(agf, mp);
    -	delta = need > be32_to_cpu(agf->agf_flcount) ?
    -		(need - be32_to_cpu(agf->agf_flcount)) : 0;
    -	/*
    -	 * If there isn't enough total or single-extent, reject it.
    -	 */
    -	longest = be32_to_cpu(agf->agf_longest);
    -	longest = (longest > delta) ? (longest - delta) :
    -		(be32_to_cpu(agf->agf_flcount) > 0 || longest > 0);
    -	if (args->minlen + args->alignment + args->minalignslop - 1 > longest ||
    -	     (args->minleft &&
    -		(int)(be32_to_cpu(agf->agf_freeblks) +
    -		   be32_to_cpu(agf->agf_flcount) - need - args->total) <
    -	     (int)args->minleft)) {
    -		xfs_trans_brelse(tp, agbp);
    -		args->agbp = NULL;
    -		return 0;
    -	}
    -	/*
    -	 * Make the freelist shorter if it's too long.
    -	 */
    -	while (be32_to_cpu(agf->agf_flcount) > need) {
    -		xfs_buf_t	*bp;
    -
    -		if ((error = xfs_alloc_get_freelist(tp, agbp, &bno)))
    -			return error;
    -		if ((error = xfs_free_ag_extent(tp, agbp, args->agno, bno, 1, 1)))
    -			return error;
    -		bp = xfs_btree_get_bufs(mp, tp, args->agno, bno, 0);
    -		xfs_trans_binval(tp, bp);
    -	}
    -	/*
    -	 * Initialize the args structure.
    -	 */
    -	targs.tp = tp;
    -	targs.mp = mp;
    -	targs.agbp = agbp;
    -	targs.agno = args->agno;
    -	targs.mod = targs.minleft = targs.wasdel = targs.userdata =
    -		targs.minalignslop = 0;
    -	targs.alignment = targs.minlen = targs.prod = targs.isfl = 1;
    -	targs.type = XFS_ALLOCTYPE_THIS_AG;
    -	targs.pag = pag;
    -	if ((error = xfs_alloc_read_agfl(mp, tp, targs.agno, &agflbp)))
    -		return error;
    -	/*
    -	 * Make the freelist longer if it's too short.
    -	 */
    -	while (be32_to_cpu(agf->agf_flcount) < need) {
    -		targs.agbno = 0;
    -		targs.maxlen = need - be32_to_cpu(agf->agf_flcount);
    -		/*
    -		 * Allocate as many blocks as possible at once.
    -		 */
    -		if ((error = xfs_alloc_ag_vextent(&targs)))
    -			return error;
    -		/*
    -		 * Stop if we run out.  Won't happen if callers are obeying
    -		 * the restrictions correctly.  Can happen for free calls
    -		 * on a completely full ag.
    -		 */
    -		if (targs.agbno == NULLAGBLOCK)
    -			break;
    -		/*
    -		 * Put each allocated block on the list.
    -		 */
    -		for (bno = targs.agbno; bno < targs.agbno + targs.len; bno++) {
    -			if ((error = xfs_alloc_put_freelist(tp, agbp, agflbp,
    -					bno)))
    -				return error;
    -		}
    -	}
    -	args->agbp = agbp;
    -	return 0;
    -}
    -
    -/*
    - * Get a block from the freelist.
    - * Returns with the buffer for the block gotten.
    - */
    -int				/* error */
    -xfs_alloc_get_freelist(
    -	xfs_trans_t	*tp,	/* transaction pointer */
    -	xfs_buf_t	*agbp,	/* buffer containing the agf structure */
    -	xfs_agblock_t	*bnop)	/* block address retrieved from freelist */
    -{
    -	xfs_agf_t	*agf;	/* a.g. freespace structure */
    -	xfs_agfl_t	*agfl;	/* a.g. freelist structure */
    -	xfs_buf_t	*agflbp;/* buffer for a.g. freelist structure */
    -	xfs_agblock_t	bno;	/* block number returned */
    -	int		error;
    -#ifdef XFS_ALLOC_TRACE
    -	static char	fname[] = "xfs_alloc_get_freelist";
    -#endif
    -	xfs_mount_t	*mp;	/* mount structure */
    -	xfs_perag_t	*pag;	/* per allocation group data */
    -
    -	agf = XFS_BUF_TO_AGF(agbp);
    -	/*
    -	 * Freelist is empty, give up.
    -	 */
    -	if (!agf->agf_flcount) {
    -		*bnop = NULLAGBLOCK;
    -		return 0;
    -	}
    -	/*
    -	 * Read the array of free blocks.
    -	 */
    -	mp = tp->t_mountp;
    -	if ((error = xfs_alloc_read_agfl(mp, tp,
    -			be32_to_cpu(agf->agf_seqno), &agflbp)))
    -		return error;
    -	agfl = XFS_BUF_TO_AGFL(agflbp);
    -	/*
    -	 * Get the block number and update the data structures.
    -	 */
    -	bno = INT_GET(agfl->agfl_bno[be32_to_cpu(agf->agf_flfirst)], ARCH_CONVERT);
    -	be32_add(&agf->agf_flfirst, 1);
    -	xfs_trans_brelse(tp, agflbp);
    -	if (be32_to_cpu(agf->agf_flfirst) == XFS_AGFL_SIZE(mp))
    -		agf->agf_flfirst = 0;
    -	pag = &mp->m_perag[be32_to_cpu(agf->agf_seqno)];
    -	be32_add(&agf->agf_flcount, -1);
    -	xfs_trans_agflist_delta(tp, -1);
    -	pag->pagf_flcount--;
    -	TRACE_MODAGF(NULL, agf, XFS_AGF_FLFIRST | XFS_AGF_FLCOUNT);
    -	xfs_alloc_log_agf(tp, agbp, XFS_AGF_FLFIRST | XFS_AGF_FLCOUNT);
    -	*bnop = bno;
    -
    -	/*
    -	 * As blocks are freed, they are added to the per-ag busy list
    -	 * and remain there until the freeing transaction is committed to
    -	 * disk.  Now that we have allocated blocks, this list must be
    -	 * searched to see if a block is being reused.  If one is, then
    -	 * the freeing transaction must be pushed to disk NOW by forcing
    -	 * to disk all iclogs up that transaction's LSN.
    -	 */
    -	xfs_alloc_search_busy(tp, be32_to_cpu(agf->agf_seqno), bno, 1);
    -	return 0;
    -}
    -
    -/*
    - * Log the given fields from the agf structure.
    - */
    -void
    -xfs_alloc_log_agf(
    -	xfs_trans_t	*tp,	/* transaction pointer */
    -	xfs_buf_t	*bp,	/* buffer for a.g. freelist header */
    -	int		fields)	/* mask of fields to be logged (XFS_AGF_...) */
    -{
    -	int	first;		/* first byte offset */
    -	int	last;		/* last byte offset */
    -	static const short	offsets[] = {
    -		offsetof(xfs_agf_t, agf_magicnum),
    -		offsetof(xfs_agf_t, agf_versionnum),
    -		offsetof(xfs_agf_t, agf_seqno),
    -		offsetof(xfs_agf_t, agf_length),
    -		offsetof(xfs_agf_t, agf_roots[0]),
    -		offsetof(xfs_agf_t, agf_levels[0]),
    -		offsetof(xfs_agf_t, agf_flfirst),
    -		offsetof(xfs_agf_t, agf_fllast),
    -		offsetof(xfs_agf_t, agf_flcount),
    -		offsetof(xfs_agf_t, agf_freeblks),
    -		offsetof(xfs_agf_t, agf_longest),
    -		sizeof(xfs_agf_t)
    -	};
    -
    -	xfs_btree_offsets(fields, offsets, XFS_AGF_NUM_BITS, &first, &last);
    -	xfs_trans_log_buf(tp, bp, (uint)first, (uint)last);
    -}
    -
    -/*
    - * Interface for inode allocation to force the pag data to be initialized.
    - */
    -int					/* error */
    -xfs_alloc_pagf_init(
    -	xfs_mount_t		*mp,	/* file system mount structure */
    -	xfs_trans_t		*tp,	/* transaction pointer */
    -	xfs_agnumber_t		agno,	/* allocation group number */
    -	int			flags)	/* XFS_ALLOC_FLAGS_... */
    -{
    -	xfs_buf_t		*bp;
    -	int			error;
    -
    -	if ((error = xfs_alloc_read_agf(mp, tp, agno, flags, &bp)))
    -		return error;
    -	if (bp)
    -		xfs_trans_brelse(tp, bp);
    -	return 0;
    -}
    -
    -/*
    - * Put the block on the freelist for the allocation group.
    - */
    -int					/* error */
    -xfs_alloc_put_freelist(
    -	xfs_trans_t		*tp,	/* transaction pointer */
    -	xfs_buf_t		*agbp,	/* buffer for a.g. freelist header */
    -	xfs_buf_t		*agflbp,/* buffer for a.g. free block array */
    -	xfs_agblock_t		bno)	/* block being freed */
    -{
    -	xfs_agf_t		*agf;	/* a.g. freespace structure */
    -	xfs_agfl_t		*agfl;	/* a.g. free block array */
    -	xfs_agblock_t		*blockp;/* pointer to array entry */
    -	int			error;
    -#ifdef XFS_ALLOC_TRACE
    -	static char		fname[] = "xfs_alloc_put_freelist";
    -#endif
    -	xfs_mount_t		*mp;	/* mount structure */
    -	xfs_perag_t		*pag;	/* per allocation group data */
    -
    -	agf = XFS_BUF_TO_AGF(agbp);
    -	mp = tp->t_mountp;
    -
    -	if (!agflbp && (error = xfs_alloc_read_agfl(mp, tp,
    -			be32_to_cpu(agf->agf_seqno), &agflbp)))
    -		return error;
    -	agfl = XFS_BUF_TO_AGFL(agflbp);
    -	be32_add(&agf->agf_fllast, 1);
    -	if (be32_to_cpu(agf->agf_fllast) == XFS_AGFL_SIZE(mp))
    -		agf->agf_fllast = 0;
    -	pag = &mp->m_perag[be32_to_cpu(agf->agf_seqno)];
    -	be32_add(&agf->agf_flcount, 1);
    -	xfs_trans_agflist_delta(tp, 1);
    -	pag->pagf_flcount++;
    -	ASSERT(be32_to_cpu(agf->agf_flcount) <= XFS_AGFL_SIZE(mp));
    -	blockp = &agfl->agfl_bno[be32_to_cpu(agf->agf_fllast)];
    -	INT_SET(*blockp, ARCH_CONVERT, bno);
    -	TRACE_MODAGF(NULL, agf, XFS_AGF_FLLAST | XFS_AGF_FLCOUNT);
    -	xfs_alloc_log_agf(tp, agbp, XFS_AGF_FLLAST | XFS_AGF_FLCOUNT);
    -	xfs_trans_log_buf(tp, agflbp,
    -		(int)((xfs_caddr_t)blockp - (xfs_caddr_t)agfl),
    -		(int)((xfs_caddr_t)blockp - (xfs_caddr_t)agfl +
    -			sizeof(xfs_agblock_t) - 1));
    -	return 0;
    -}
    -
    -/*
    - * Read in the allocation group header (free/alloc section).
    - */
    -int					/* error */
    -xfs_alloc_read_agf(
    -	xfs_mount_t	*mp,		/* mount point structure */
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_agnumber_t	agno,		/* allocation group number */
    -	int		flags,		/* XFS_ALLOC_FLAG_... */
    -	xfs_buf_t	**bpp)		/* buffer for the ag freelist header */
    -{
    -	xfs_agf_t	*agf;		/* ag freelist header */
    -	int		agf_ok;		/* set if agf is consistent */
    -	xfs_buf_t	*bp;		/* return value */
    -	xfs_perag_t	*pag;		/* per allocation group data */
    -	int		error;
    -
    -	ASSERT(agno != NULLAGNUMBER);
    -	error = xfs_trans_read_buf(
    -			mp, tp, mp->m_ddev_targp,
    -			XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)),
    -			XFS_FSS_TO_BB(mp, 1),
    -			(flags & XFS_ALLOC_FLAG_TRYLOCK) ? XFS_BUF_TRYLOCK : 0U,
    -			&bp);
    -	if (error)
    -		return error;
    -	ASSERT(!bp || !XFS_BUF_GETERROR(bp));
    -	if (!bp) {
    -		*bpp = NULL;
    -		return 0;
    -	}
    -	/*
    -	 * Validate the magic number of the agf block.
    -	 */
    -	agf = XFS_BUF_TO_AGF(bp);
    -	agf_ok =
    -		be32_to_cpu(agf->agf_magicnum) == XFS_AGF_MAGIC &&
    -		XFS_AGF_GOOD_VERSION(be32_to_cpu(agf->agf_versionnum)) &&
    -		be32_to_cpu(agf->agf_freeblks) <= be32_to_cpu(agf->agf_length) &&
    -		be32_to_cpu(agf->agf_flfirst) < XFS_AGFL_SIZE(mp) &&
    -		be32_to_cpu(agf->agf_fllast) < XFS_AGFL_SIZE(mp) &&
    -		be32_to_cpu(agf->agf_flcount) <= XFS_AGFL_SIZE(mp);
    -	if (unlikely(XFS_TEST_ERROR(!agf_ok, mp, XFS_ERRTAG_ALLOC_READ_AGF,
    -			XFS_RANDOM_ALLOC_READ_AGF))) {
    -		XFS_CORRUPTION_ERROR("xfs_alloc_read_agf",
    -				     XFS_ERRLEVEL_LOW, mp, agf);
    -		xfs_trans_brelse(tp, bp);
    -		return XFS_ERROR(EFSCORRUPTED);
    -	}
    -	pag = &mp->m_perag[agno];
    -	if (!pag->pagf_init) {
    -		pag->pagf_freeblks = be32_to_cpu(agf->agf_freeblks);
    -		pag->pagf_flcount = be32_to_cpu(agf->agf_flcount);
    -		pag->pagf_longest = be32_to_cpu(agf->agf_longest);
    -		pag->pagf_levels[XFS_BTNUM_BNOi] =
    -			be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNOi]);
    -		pag->pagf_levels[XFS_BTNUM_CNTi] =
    -			be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi]);
    -		spinlock_init(&pag->pagb_lock, "xfspagb");
    -		pag->pagb_list = kmem_zalloc(XFS_PAGB_NUM_SLOTS *
    -					sizeof(xfs_perag_busy_t), KM_SLEEP);
    -		pag->pagf_init = 1;
    -	}
    -#ifdef DEBUG
    -	else if (!XFS_FORCED_SHUTDOWN(mp)) {
    -		ASSERT(pag->pagf_freeblks == be32_to_cpu(agf->agf_freeblks));
    -		ASSERT(pag->pagf_flcount == be32_to_cpu(agf->agf_flcount));
    -		ASSERT(pag->pagf_longest == be32_to_cpu(agf->agf_longest));
    -		ASSERT(pag->pagf_levels[XFS_BTNUM_BNOi] ==
    -		       be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNOi]));
    -		ASSERT(pag->pagf_levels[XFS_BTNUM_CNTi] ==
    -		       be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi]));
    -	}
    -#endif
    -	XFS_BUF_SET_VTYPE_REF(bp, B_FS_AGF, XFS_AGF_REF);
    -	*bpp = bp;
    -	return 0;
    -}
    -
    -/*
    - * Allocate an extent (variable-size).
    - * Depending on the allocation type, we either look in a single allocation
    - * group or loop over the allocation groups to find the result.
    - */
    -int				/* error */
    -xfs_alloc_vextent(
    -	xfs_alloc_arg_t	*args)	/* allocation argument structure */
    -{
    -	xfs_agblock_t	agsize;	/* allocation group size */
    -	int		error;
    -	int		flags;	/* XFS_ALLOC_FLAG_... locking flags */
    -#ifdef XFS_ALLOC_TRACE
    -	static char	fname[] = "xfs_alloc_vextent";
    -#endif
    -	xfs_extlen_t	minleft;/* minimum left value, temp copy */
    -	xfs_mount_t	*mp;	/* mount structure pointer */
    -	xfs_agnumber_t	sagno;	/* starting allocation group number */
    -	xfs_alloctype_t	type;	/* input allocation type */
    -	int		bump_rotor = 0;
    -	int		no_min = 0;
    -	xfs_agnumber_t	rotorstep = xfs_rotorstep; /* inode32 agf stepper */
    -
    -	mp = args->mp;
    -	type = args->otype = args->type;
    -	args->agbno = NULLAGBLOCK;
    -	/*
    -	 * Just fix this up, for the case where the last a.g. is shorter
    -	 * (or there's only one a.g.) and the caller couldn't easily figure
    -	 * that out (xfs_bmap_alloc).
    -	 */
    -	agsize = mp->m_sb.sb_agblocks;
    -	if (args->maxlen > agsize)
    -		args->maxlen = agsize;
    -	if (args->alignment == 0)
    -		args->alignment = 1;
    -	ASSERT(XFS_FSB_TO_AGNO(mp, args->fsbno) < mp->m_sb.sb_agcount);
    -	ASSERT(XFS_FSB_TO_AGBNO(mp, args->fsbno) < agsize);
    -	ASSERT(args->minlen <= args->maxlen);
    -	ASSERT(args->minlen <= agsize);
    -	ASSERT(args->mod < args->prod);
    -	if (XFS_FSB_TO_AGNO(mp, args->fsbno) >= mp->m_sb.sb_agcount ||
    -	    XFS_FSB_TO_AGBNO(mp, args->fsbno) >= agsize ||
    -	    args->minlen > args->maxlen || args->minlen > agsize ||
    -	    args->mod >= args->prod) {
    -		args->fsbno = NULLFSBLOCK;
    -		TRACE_ALLOC("badargs", args);
    -		return 0;
    -	}
    -	minleft = args->minleft;
    -
    -	switch (type) {
    -	case XFS_ALLOCTYPE_THIS_AG:
    -	case XFS_ALLOCTYPE_NEAR_BNO:
    -	case XFS_ALLOCTYPE_THIS_BNO:
    -		/*
    -		 * These three force us into a single a.g.
    -		 */
    -		args->agno = XFS_FSB_TO_AGNO(mp, args->fsbno);
    -		down_read(&mp->m_peraglock);
    -		args->pag = &mp->m_perag[args->agno];
    -		args->minleft = 0;
    -		error = xfs_alloc_fix_freelist(args, 0);
    -		args->minleft = minleft;
    -		if (error) {
    -			TRACE_ALLOC("nofix", args);
    -			goto error0;
    -		}
    -		if (!args->agbp) {
    -			up_read(&mp->m_peraglock);
    -			TRACE_ALLOC("noagbp", args);
    -			break;
    -		}
    -		args->agbno = XFS_FSB_TO_AGBNO(mp, args->fsbno);
    -		if ((error = xfs_alloc_ag_vextent(args)))
    -			goto error0;
    -		up_read(&mp->m_peraglock);
    -		break;
    -	case XFS_ALLOCTYPE_START_BNO:
    -		/*
    -		 * Try near allocation first, then anywhere-in-ag after
    -		 * the first a.g. fails.
    -		 */
    -		if ((args->userdata  == XFS_ALLOC_INITIAL_USER_DATA) &&
    -		    (mp->m_flags & XFS_MOUNT_32BITINODES)) {
    -			args->fsbno = XFS_AGB_TO_FSB(mp,
    -					((mp->m_agfrotor / rotorstep) %
    -					mp->m_sb.sb_agcount), 0);
    -			bump_rotor = 1;
    -		}
    -		args->agbno = XFS_FSB_TO_AGBNO(mp, args->fsbno);
    -		args->type = XFS_ALLOCTYPE_NEAR_BNO;
    -		/* FALLTHROUGH */
    -	case XFS_ALLOCTYPE_ANY_AG:
    -	case XFS_ALLOCTYPE_START_AG:
    -	case XFS_ALLOCTYPE_FIRST_AG:
    -		/*
    -		 * Rotate through the allocation groups looking for a winner.
    -		 */
    -		if (type == XFS_ALLOCTYPE_ANY_AG) {
    -			/*
    -			 * Start with the last place we left off.
    -			 */
    -			args->agno = sagno = (mp->m_agfrotor / rotorstep) %
    -					mp->m_sb.sb_agcount;
    -			args->type = XFS_ALLOCTYPE_THIS_AG;
    -			flags = XFS_ALLOC_FLAG_TRYLOCK;
    -		} else if (type == XFS_ALLOCTYPE_FIRST_AG) {
    -			/*
    -			 * Start with allocation group given by bno.
    -			 */
    -			args->agno = XFS_FSB_TO_AGNO(mp, args->fsbno);
    -			args->type = XFS_ALLOCTYPE_THIS_AG;
    -			sagno = 0;
    -			flags = 0;
    -		} else {
    -			if (type == XFS_ALLOCTYPE_START_AG)
    -				args->type = XFS_ALLOCTYPE_THIS_AG;
    -			/*
    -			 * Start with the given allocation group.
    -			 */
    -			args->agno = sagno = XFS_FSB_TO_AGNO(mp, args->fsbno);
    -			flags = XFS_ALLOC_FLAG_TRYLOCK;
    -		}
    -		/*
    -		 * Loop over allocation groups twice; first time with
    -		 * trylock set, second time without.
    -		 */
    -		down_read(&mp->m_peraglock);
    -		for (;;) {
    -			args->pag = &mp->m_perag[args->agno];
    -			if (no_min) args->minleft = 0;
    -			error = xfs_alloc_fix_freelist(args, flags);
    -			args->minleft = minleft;
    -			if (error) {
    -				TRACE_ALLOC("nofix", args);
    -				goto error0;
    -			}
    -			/*
    -			 * If we get a buffer back then the allocation will fly.
    -			 */
    -			if (args->agbp) {
    -				if ((error = xfs_alloc_ag_vextent(args)))
    -					goto error0;
    -				break;
    -			}
    -			TRACE_ALLOC("loopfailed", args);
    -			/*
    -			 * Didn't work, figure out the next iteration.
    -			 */
    -			if (args->agno == sagno &&
    -			    type == XFS_ALLOCTYPE_START_BNO)
    -				args->type = XFS_ALLOCTYPE_THIS_AG;
    -			if (++(args->agno) == mp->m_sb.sb_agcount)
    -				args->agno = 0;
    -			/*
    -			 * Reached the starting a.g., must either be done
    -			 * or switch to non-trylock mode.
    -			 */
    -			if (args->agno == sagno) {
    -				if (no_min == 1) {
    -					args->agbno = NULLAGBLOCK;
    -					TRACE_ALLOC("allfailed", args);
    -					break;
    -				}
    -				if (flags == 0) {
    -					no_min = 1;
    -				} else {
    -					flags = 0;
    -					if (type == XFS_ALLOCTYPE_START_BNO) {
    -						args->agbno = XFS_FSB_TO_AGBNO(mp,
    -							args->fsbno);
    -						args->type = XFS_ALLOCTYPE_NEAR_BNO;
    -					}
    -				}
    -			}
    -		}
    -		up_read(&mp->m_peraglock);
    -		if (bump_rotor || (type == XFS_ALLOCTYPE_ANY_AG)) {
    -			if (args->agno == sagno)
    -				mp->m_agfrotor = (mp->m_agfrotor + 1) %
    -					(mp->m_sb.sb_agcount * rotorstep);
    -			else
    -				mp->m_agfrotor = (args->agno * rotorstep + 1) %
    -					(mp->m_sb.sb_agcount * rotorstep);
    -		}
    -		break;
    -	default:
    -		ASSERT(0);
    -		/* NOTREACHED */
    -	}
    -	if (args->agbno == NULLAGBLOCK)
    -		args->fsbno = NULLFSBLOCK;
    -	else {
    -		args->fsbno = XFS_AGB_TO_FSB(mp, args->agno, args->agbno);
    -#ifdef DEBUG
    -		ASSERT(args->len >= args->minlen);
    -		ASSERT(args->len <= args->maxlen);
    -		ASSERT(args->agbno % args->alignment == 0);
    -		XFS_AG_CHECK_DADDR(mp, XFS_FSB_TO_DADDR(mp, args->fsbno),
    -			args->len);
    -#endif
    -	}
    -	return 0;
    -error0:
    -	up_read(&mp->m_peraglock);
    -	return error;
    -}
    -
    -/*
    - * Free an extent.
    - * Just break up the extent address and hand off to xfs_free_ag_extent
    - * after fixing up the freelist.
    - */
    -int				/* error */
    -xfs_free_extent(
    -	xfs_trans_t	*tp,	/* transaction pointer */
    -	xfs_fsblock_t	bno,	/* starting block number of extent */
    -	xfs_extlen_t	len)	/* length of extent */
    -{
    -#ifdef DEBUG
    -	xfs_agf_t	*agf;	/* a.g. freespace header */
    -#endif
    -	xfs_alloc_arg_t	args;	/* allocation argument structure */
    -	int		error;
    -
    -	ASSERT(len != 0);
    -	args.tp = tp;
    -	args.mp = tp->t_mountp;
    -	args.agno = XFS_FSB_TO_AGNO(args.mp, bno);
    -	ASSERT(args.agno < args.mp->m_sb.sb_agcount);
    -	args.agbno = XFS_FSB_TO_AGBNO(args.mp, bno);
    -	args.alignment = 1;
    -	args.minlen = args.minleft = args.minalignslop = 0;
    -	down_read(&args.mp->m_peraglock);
    -	args.pag = &args.mp->m_perag[args.agno];
    -	if ((error = xfs_alloc_fix_freelist(&args, 0)))
    -		goto error0;
    -#ifdef DEBUG
    -	ASSERT(args.agbp != NULL);
    -	agf = XFS_BUF_TO_AGF(args.agbp);
    -	ASSERT(args.agbno + len <= be32_to_cpu(agf->agf_length));
    -#endif
    -	error = xfs_free_ag_extent(tp, args.agbp, args.agno, args.agbno,
    -		len, 0);
    -error0:
    -	up_read(&args.mp->m_peraglock);
    -	return error;
    -}
    -
    -
    -/*
    - * AG Busy list management
    - * The busy list contains block ranges that have been freed but whose
    - * transactions have not yet hit disk.  If any block listed in a busy
    - * list is reused, the transaction that freed it must be forced to disk
    - * before continuing to use the block.
    - *
    - * xfs_alloc_mark_busy - add to the per-ag busy list
    - * xfs_alloc_clear_busy - remove an item from the per-ag busy list
    - */
    -void
    -xfs_alloc_mark_busy(xfs_trans_t *tp,
    -		    xfs_agnumber_t agno,
    -		    xfs_agblock_t bno,
    -		    xfs_extlen_t len)
    -{
    -	xfs_mount_t		*mp;
    -	xfs_perag_busy_t	*bsy;
    -	int			n;
    -	SPLDECL(s);
    -
    -	mp = tp->t_mountp;
    -	s = mutex_spinlock(&mp->m_perag[agno].pagb_lock);
    -
    -	/* search pagb_list for an open slot */
    -	for (bsy = mp->m_perag[agno].pagb_list, n = 0;
    -	     n < XFS_PAGB_NUM_SLOTS;
    -	     bsy++, n++) {
    -		if (bsy->busy_tp == NULL) {
    -			break;
    -		}
    -	}
    -
    -	if (n < XFS_PAGB_NUM_SLOTS) {
    -		bsy = &mp->m_perag[agno].pagb_list[n];
    -		mp->m_perag[agno].pagb_count++;
    -		TRACE_BUSY("xfs_alloc_mark_busy", "got", agno, bno, len, n, tp);
    -		bsy->busy_start = bno;
    -		bsy->busy_length = len;
    -		bsy->busy_tp = tp;
    -		xfs_trans_add_busy(tp, agno, n);
    -	} else {
    -		TRACE_BUSY("xfs_alloc_mark_busy", "FULL", agno, bno, len, -1, tp);
    -		/*
    -		 * The busy list is full!  Since it is now not possible to
    -		 * track the free block, make this a synchronous transaction
    -		 * to insure that the block is not reused before this
    -		 * transaction commits.
    -		 */
    -		xfs_trans_set_sync(tp);
    -	}
    -
    -	mutex_spinunlock(&mp->m_perag[agno].pagb_lock, s);
    -}
    -
    -void
    -xfs_alloc_clear_busy(xfs_trans_t *tp,
    -		     xfs_agnumber_t agno,
    -		     int idx)
    -{
    -	xfs_mount_t		*mp;
    -	xfs_perag_busy_t	*list;
    -	SPLDECL(s);
    -
    -	mp = tp->t_mountp;
    -
    -	s = mutex_spinlock(&mp->m_perag[agno].pagb_lock);
    -	list = mp->m_perag[agno].pagb_list;
    -
    -	ASSERT(idx < XFS_PAGB_NUM_SLOTS);
    -	if (list[idx].busy_tp == tp) {
    -		TRACE_UNBUSY("xfs_alloc_clear_busy", "found", agno, idx, tp);
    -		list[idx].busy_tp = NULL;
    -		mp->m_perag[agno].pagb_count--;
    -	} else {
    -		TRACE_UNBUSY("xfs_alloc_clear_busy", "missing", agno, idx, tp);
    -	}
    -
    -	mutex_spinunlock(&mp->m_perag[agno].pagb_lock, s);
    -}
    -
    -
    -/*
    - * returns non-zero if any of (agno,bno):len is in a busy list
    - */
    -STATIC int
    -xfs_alloc_search_busy(xfs_trans_t *tp,
    -		    xfs_agnumber_t agno,
    -		    xfs_agblock_t bno,
    -		    xfs_extlen_t len)
    -{
    -	xfs_mount_t		*mp;
    -	xfs_perag_busy_t	*bsy;
    -	int			n;
    -	xfs_agblock_t		uend, bend;
    -	xfs_lsn_t		lsn;
    -	int			cnt;
    -	SPLDECL(s);
    -
    -	mp = tp->t_mountp;
    -
    -	s = mutex_spinlock(&mp->m_perag[agno].pagb_lock);
    -	cnt = mp->m_perag[agno].pagb_count;
    -
    -	uend = bno + len - 1;
    -
    -	/* search pagb_list for this slot, skipping open slots */
    -	for (bsy = mp->m_perag[agno].pagb_list, n = 0;
    -	     cnt; bsy++, n++) {
    -
    -		/*
    -		 * (start1,length1) within (start2, length2)
    -		 */
    -		if (bsy->busy_tp != NULL) {
    -			bend = bsy->busy_start + bsy->busy_length - 1;
    -			if ((bno > bend) ||
    -			    (uend < bsy->busy_start)) {
    -				cnt--;
    -			} else {
    -				TRACE_BUSYSEARCH("xfs_alloc_search_busy",
    -						 "found1", agno, bno, len, n,
    -						 tp);
    -				break;
    -			}
    -		}
    -	}
    -
    -	/*
    -	 * If a block was found, force the log through the LSN of the
    -	 * transaction that freed the block
    -	 */
    -	if (cnt) {
    -		TRACE_BUSYSEARCH("xfs_alloc_search_busy", "found", agno, bno, len, n, tp);
    -		lsn = bsy->busy_tp->t_commit_lsn;
    -		mutex_spinunlock(&mp->m_perag[agno].pagb_lock, s);
    -		xfs_log_force(mp, lsn, XFS_LOG_FORCE|XFS_LOG_SYNC);
    -	} else {
    -		TRACE_BUSYSEARCH("xfs_alloc_search_busy", "not-found", agno, bno, len, n, tp);
    -		n = -1;
    -		mutex_spinunlock(&mp->m_perag[agno].pagb_lock, s);
    -	}
    -
    -	return n;
    -}
    diff --git a/sys/gnu/fs/xfs/xfs_alloc.h b/sys/gnu/fs/xfs/xfs_alloc.h
    deleted file mode 100644
    index 2d1f8928b26..00000000000
    --- a/sys/gnu/fs/xfs/xfs_alloc.h
    +++ /dev/null
    @@ -1,189 +0,0 @@
    -/*
    - * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_ALLOC_H__
    -#define	__XFS_ALLOC_H__
    -
    -struct xfs_buf;
    -struct xfs_mount;
    -struct xfs_perag;
    -struct xfs_trans;
    -
    -/*
    - * Freespace allocation types.  Argument to xfs_alloc_[v]extent.
    - */
    -typedef enum xfs_alloctype
    -{
    -	XFS_ALLOCTYPE_ANY_AG,		/* allocate anywhere, use rotor */
    -	XFS_ALLOCTYPE_FIRST_AG,		/* ... start at ag 0 */
    -	XFS_ALLOCTYPE_START_AG,		/* anywhere, start in this a.g. */
    -	XFS_ALLOCTYPE_THIS_AG,		/* anywhere in this a.g. */
    -	XFS_ALLOCTYPE_START_BNO,	/* near this block else anywhere */
    -	XFS_ALLOCTYPE_NEAR_BNO,		/* in this a.g. and near this block */
    -	XFS_ALLOCTYPE_THIS_BNO		/* at exactly this block */
    -} xfs_alloctype_t;
    -
    -/*
    - * Flags for xfs_alloc_fix_freelist.
    - */
    -#define	XFS_ALLOC_FLAG_TRYLOCK	0x00000001  /* use trylock for buffer locking */
    -
    -/*
    - * Argument structure for xfs_alloc routines.
    - * This is turned into a structure to avoid having 20 arguments passed
    - * down several levels of the stack.
    - */
    -typedef struct xfs_alloc_arg {
    -	struct xfs_trans *tp;		/* transaction pointer */
    -	struct xfs_mount *mp;		/* file system mount point */
    -	struct xfs_buf	*agbp;		/* buffer for a.g. freelist header */
    -	struct xfs_perag *pag;		/* per-ag struct for this agno */
    -	xfs_fsblock_t	fsbno;		/* file system block number */
    -	xfs_agnumber_t	agno;		/* allocation group number */
    -	xfs_agblock_t	agbno;		/* allocation group-relative block # */
    -	xfs_extlen_t	minlen;		/* minimum size of extent */
    -	xfs_extlen_t	maxlen;		/* maximum size of extent */
    -	xfs_extlen_t	mod;		/* mod value for extent size */
    -	xfs_extlen_t	prod;		/* prod value for extent size */
    -	xfs_extlen_t	minleft;	/* min blocks must be left after us */
    -	xfs_extlen_t	total;		/* total blocks needed in xaction */
    -	xfs_extlen_t	alignment;	/* align answer to multiple of this */
    -	xfs_extlen_t	minalignslop;	/* slop for minlen+alignment calcs */
    -	xfs_extlen_t	len;		/* output: actual size of extent */
    -	xfs_alloctype_t	type;		/* allocation type XFS_ALLOCTYPE_... */
    -	xfs_alloctype_t	otype;		/* original allocation type */
    -	char		wasdel;		/* set if allocation was prev delayed */
    -	char		wasfromfl;	/* set if allocation is from freelist */
    -	char		isfl;		/* set if is freelist blocks - !acctg */
    -	char		userdata;	/* set if this is user data */
    -} xfs_alloc_arg_t;
    -
    -/*
    - * Defines for userdata
    - */
    -#define XFS_ALLOC_USERDATA		1	/* allocation is for user data*/
    -#define XFS_ALLOC_INITIAL_USER_DATA	2	/* special case start of file */
    -
    -
    -#ifdef __KERNEL__
    -
    -#if defined(XFS_ALLOC_TRACE)
    -/*
    - * Allocation tracing buffer size.
    - */
    -#define	XFS_ALLOC_TRACE_SIZE	4096
    -extern ktrace_t *xfs_alloc_trace_buf;
    -
    -/*
    - * Types for alloc tracing.
    - */
    -#define	XFS_ALLOC_KTRACE_ALLOC	1
    -#define	XFS_ALLOC_KTRACE_FREE	2
    -#define	XFS_ALLOC_KTRACE_MODAGF	3
    -#define	XFS_ALLOC_KTRACE_BUSY	4
    -#define	XFS_ALLOC_KTRACE_UNBUSY	5
    -#define	XFS_ALLOC_KTRACE_BUSYSEARCH	6
    -#endif
    -
    -/*
    - * Compute and fill in value of m_ag_maxlevels.
    - */
    -void
    -xfs_alloc_compute_maxlevels(
    -	struct xfs_mount	*mp);	/* file system mount structure */
    -
    -/*
    - * Get a block from the freelist.
    - * Returns with the buffer for the block gotten.
    - */
    -int				/* error */
    -xfs_alloc_get_freelist(
    -	struct xfs_trans *tp,	/* transaction pointer */
    -	struct xfs_buf	*agbp,	/* buffer containing the agf structure */
    -	xfs_agblock_t	*bnop);	/* block address retrieved from freelist */
    -
    -/*
    - * Log the given fields from the agf structure.
    - */
    -void
    -xfs_alloc_log_agf(
    -	struct xfs_trans *tp,	/* transaction pointer */
    -	struct xfs_buf	*bp,	/* buffer for a.g. freelist header */
    -	int		fields);/* mask of fields to be logged (XFS_AGF_...) */
    -
    -/*
    - * Interface for inode allocation to force the pag data to be initialized.
    - */
    -int				/* error */
    -xfs_alloc_pagf_init(
    -	struct xfs_mount *mp,	/* file system mount structure */
    -	struct xfs_trans *tp,	/* transaction pointer */
    -	xfs_agnumber_t	agno,	/* allocation group number */
    -	int		flags);	/* XFS_ALLOC_FLAGS_... */
    -
    -/*
    - * Put the block on the freelist for the allocation group.
    - */
    -int				/* error */
    -xfs_alloc_put_freelist(
    -	struct xfs_trans *tp,	/* transaction pointer */
    -	struct xfs_buf	*agbp,	/* buffer for a.g. freelist header */
    -	struct xfs_buf	*agflbp,/* buffer for a.g. free block array */
    -	xfs_agblock_t	bno);	/* block being freed */
    -
    -/*
    - * Read in the allocation group header (free/alloc section).
    - */
    -int					/* error  */
    -xfs_alloc_read_agf(
    -	struct xfs_mount *mp,		/* mount point structure */
    -	struct xfs_trans *tp,		/* transaction pointer */
    -	xfs_agnumber_t	agno,		/* allocation group number */
    -	int		flags,		/* XFS_ALLOC_FLAG_... */
    -	struct xfs_buf	**bpp);		/* buffer for the ag freelist header */
    -
    -/*
    - * Allocate an extent (variable-size).
    - */
    -int				/* error */
    -xfs_alloc_vextent(
    -	xfs_alloc_arg_t	*args);	/* allocation argument structure */
    -
    -/*
    - * Free an extent.
    - */
    -int				/* error */
    -xfs_free_extent(
    -	struct xfs_trans *tp,	/* transaction pointer */
    -	xfs_fsblock_t	bno,	/* starting block number of extent */
    -	xfs_extlen_t	len);	/* length of extent */
    -
    -void
    -xfs_alloc_mark_busy(xfs_trans_t *tp,
    -		xfs_agnumber_t agno,
    -		xfs_agblock_t bno,
    -		xfs_extlen_t len);
    -
    -void
    -xfs_alloc_clear_busy(xfs_trans_t *tp,
    -		xfs_agnumber_t ag,
    -		int idx);
    -
    -
    -#endif	/* __KERNEL__ */
    -
    -#endif	/* __XFS_ALLOC_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_alloc_btree.c b/sys/gnu/fs/xfs/xfs_alloc_btree.c
    deleted file mode 100644
    index a1d92da86cc..00000000000
    --- a/sys/gnu/fs/xfs/xfs_alloc_btree.c
    +++ /dev/null
    @@ -1,2203 +0,0 @@
    -/*
    - * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_btree.h"
    -#include "xfs_ialloc.h"
    -#include "xfs_alloc.h"
    -#include "xfs_error.h"
    -
    -/*
    - * Prototypes for internal functions.
    - */
    -
    -STATIC void xfs_alloc_log_block(xfs_trans_t *, xfs_buf_t *, int);
    -STATIC void xfs_alloc_log_keys(xfs_btree_cur_t *, xfs_buf_t *, int, int);
    -STATIC void xfs_alloc_log_ptrs(xfs_btree_cur_t *, xfs_buf_t *, int, int);
    -STATIC void xfs_alloc_log_recs(xfs_btree_cur_t *, xfs_buf_t *, int, int);
    -STATIC int xfs_alloc_lshift(xfs_btree_cur_t *, int, int *);
    -STATIC int xfs_alloc_newroot(xfs_btree_cur_t *, int *);
    -STATIC int xfs_alloc_rshift(xfs_btree_cur_t *, int, int *);
    -STATIC int xfs_alloc_split(xfs_btree_cur_t *, int, xfs_agblock_t *,
    -		xfs_alloc_key_t *, xfs_btree_cur_t **, int *);
    -STATIC int xfs_alloc_updkey(xfs_btree_cur_t *, xfs_alloc_key_t *, int);
    -
    -/*
    - * Internal functions.
    - */
    -
    -/*
    - * Single level of the xfs_alloc_delete record deletion routine.
    - * Delete record pointed to by cur/level.
    - * Remove the record from its block then rebalance the tree.
    - * Return 0 for error, 1 for done, 2 to go on to the next level.
    - */
    -STATIC int				/* error */
    -xfs_alloc_delrec(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	int			level,	/* level removing record from */
    -	int			*stat)	/* fail/done/go-on */
    -{
    -	xfs_agf_t		*agf;	/* allocation group freelist header */
    -	xfs_alloc_block_t	*block;	/* btree block record/key lives in */
    -	xfs_agblock_t		bno;	/* btree block number */
    -	xfs_buf_t		*bp;	/* buffer for block */
    -	int			error;	/* error return value */
    -	int			i;	/* loop index */
    -	xfs_alloc_key_t		key;	/* kp points here if block is level 0 */
    -	xfs_agblock_t		lbno;	/* left block's block number */
    -	xfs_buf_t		*lbp;	/* left block's buffer pointer */
    -	xfs_alloc_block_t	*left;	/* left btree block */
    -	xfs_alloc_key_t		*lkp=NULL;	/* left block key pointer */
    -	xfs_alloc_ptr_t		*lpp=NULL;	/* left block address pointer */
    -	int			lrecs=0;	/* number of records in left block */
    -	xfs_alloc_rec_t		*lrp;	/* left block record pointer */
    -	xfs_mount_t		*mp;	/* mount structure */
    -	int			ptr;	/* index in btree block for this rec */
    -	xfs_agblock_t		rbno;	/* right block's block number */
    -	xfs_buf_t		*rbp;	/* right block's buffer pointer */
    -	xfs_alloc_block_t	*right;	/* right btree block */
    -	xfs_alloc_key_t		*rkp;	/* right block key pointer */
    -	xfs_alloc_ptr_t		*rpp;	/* right block address pointer */
    -	int			rrecs=0;	/* number of records in right block */
    -	xfs_alloc_rec_t		*rrp;	/* right block record pointer */
    -	xfs_btree_cur_t		*tcur;	/* temporary btree cursor */
    -
    -	/*
    -	 * Get the index of the entry being deleted, check for nothing there.
    -	 */
    -	ptr = cur->bc_ptrs[level];
    -	if (ptr == 0) {
    -		*stat = 0;
    -		return 0;
    -	}
    -	/*
    -	 * Get the buffer & block containing the record or key/ptr.
    -	 */
    -	bp = cur->bc_bufs[level];
    -	block = XFS_BUF_TO_ALLOC_BLOCK(bp);
    -#ifdef DEBUG
    -	if ((error = xfs_btree_check_sblock(cur, block, level, bp)))
    -		return error;
    -#endif
    -	/*
    -	 * Fail if we're off the end of the block.
    -	 */
    -	if (ptr > be16_to_cpu(block->bb_numrecs)) {
    -		*stat = 0;
    -		return 0;
    -	}
    -	XFS_STATS_INC(xs_abt_delrec);
    -	/*
    -	 * It's a nonleaf.  Excise the key and ptr being deleted, by
    -	 * sliding the entries past them down one.
    -	 * Log the changed areas of the block.
    -	 */
    -	if (level > 0) {
    -		lkp = XFS_ALLOC_KEY_ADDR(block, 1, cur);
    -		lpp = XFS_ALLOC_PTR_ADDR(block, 1, cur);
    -#ifdef DEBUG
    -		for (i = ptr; i < be16_to_cpu(block->bb_numrecs); i++) {
    -			if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(lpp[i]), level)))
    -				return error;
    -		}
    -#endif
    -		if (ptr < be16_to_cpu(block->bb_numrecs)) {
    -			memmove(&lkp[ptr - 1], &lkp[ptr],
    -				(be16_to_cpu(block->bb_numrecs) - ptr) * sizeof(*lkp));
    -			memmove(&lpp[ptr - 1], &lpp[ptr],
    -				(be16_to_cpu(block->bb_numrecs) - ptr) * sizeof(*lpp));
    -			xfs_alloc_log_ptrs(cur, bp, ptr, be16_to_cpu(block->bb_numrecs) - 1);
    -			xfs_alloc_log_keys(cur, bp, ptr, be16_to_cpu(block->bb_numrecs) - 1);
    -		}
    -	}
    -	/*
    -	 * It's a leaf.  Excise the record being deleted, by sliding the
    -	 * entries past it down one.  Log the changed areas of the block.
    -	 */
    -	else {
    -		lrp = XFS_ALLOC_REC_ADDR(block, 1, cur);
    -		if (ptr < be16_to_cpu(block->bb_numrecs)) {
    -			memmove(&lrp[ptr - 1], &lrp[ptr],
    -				(be16_to_cpu(block->bb_numrecs) - ptr) * sizeof(*lrp));
    -			xfs_alloc_log_recs(cur, bp, ptr, be16_to_cpu(block->bb_numrecs) - 1);
    -		}
    -		/*
    -		 * If it's the first record in the block, we'll need a key
    -		 * structure to pass up to the next level (updkey).
    -		 */
    -		if (ptr == 1) {
    -			key.ar_startblock = lrp->ar_startblock;
    -			key.ar_blockcount = lrp->ar_blockcount;
    -			lkp = &key;
    -		}
    -	}
    -	/*
    -	 * Decrement and log the number of entries in the block.
    -	 */
    -	be16_add(&block->bb_numrecs, -1);
    -	xfs_alloc_log_block(cur->bc_tp, bp, XFS_BB_NUMRECS);
    -	/*
    -	 * See if the longest free extent in the allocation group was
    -	 * changed by this operation.  True if it's the by-size btree, and
    -	 * this is the leaf level, and there is no right sibling block,
    -	 * and this was the last record.
    -	 */
    -	agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);
    -	mp = cur->bc_mp;
    -
    -	if (level == 0 &&
    -	    cur->bc_btnum == XFS_BTNUM_CNT &&
    -	    be32_to_cpu(block->bb_rightsib) == NULLAGBLOCK &&
    -	    ptr > be16_to_cpu(block->bb_numrecs)) {
    -		ASSERT(ptr == be16_to_cpu(block->bb_numrecs) + 1);
    -		/*
    -		 * There are still records in the block.  Grab the size
    -		 * from the last one.
    -		 */
    -		if (be16_to_cpu(block->bb_numrecs)) {
    -			rrp = XFS_ALLOC_REC_ADDR(block, be16_to_cpu(block->bb_numrecs), cur);
    -			agf->agf_longest = rrp->ar_blockcount;
    -		}
    -		/*
    -		 * No free extents left.
    -		 */
    -		else
    -			agf->agf_longest = 0;
    -		mp->m_perag[be32_to_cpu(agf->agf_seqno)].pagf_longest =
    -			be32_to_cpu(agf->agf_longest);
    -		xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp,
    -			XFS_AGF_LONGEST);
    -	}
    -	/*
    -	 * Is this the root level?  If so, we're almost done.
    -	 */
    -	if (level == cur->bc_nlevels - 1) {
    -		/*
    -		 * If this is the root level,
    -		 * and there's only one entry left,
    -		 * and it's NOT the leaf level,
    -		 * then we can get rid of this level.
    -		 */
    -		if (be16_to_cpu(block->bb_numrecs) == 1 && level > 0) {
    -			/*
    -			 * lpp is still set to the first pointer in the block.
    -			 * Make it the new root of the btree.
    -			 */
    -			bno = be32_to_cpu(agf->agf_roots[cur->bc_btnum]);
    -			agf->agf_roots[cur->bc_btnum] = *lpp;
    -			be32_add(&agf->agf_levels[cur->bc_btnum], -1);
    -			mp->m_perag[be32_to_cpu(agf->agf_seqno)].pagf_levels[cur->bc_btnum]--;
    -			/*
    -			 * Put this buffer/block on the ag's freelist.
    -			 */
    -			if ((error = xfs_alloc_put_freelist(cur->bc_tp,
    -					cur->bc_private.a.agbp, NULL, bno)))
    -				return error;
    -			/*
    -			 * Since blocks move to the free list without the
    -			 * coordination used in xfs_bmap_finish, we can't allow
    -			 * block to be available for reallocation and
    -			 * non-transaction writing (user data) until we know
    -			 * that the transaction that moved it to the free list
    -			 * is permanently on disk. We track the blocks by
    -			 * declaring these blocks as "busy"; the busy list is
    -			 * maintained on a per-ag basis and each transaction
    -			 * records which entries should be removed when the
    -			 * iclog commits to disk. If a busy block is
    -			 * allocated, the iclog is pushed up to the LSN
    -			 * that freed the block.
    -			 */
    -			xfs_alloc_mark_busy(cur->bc_tp,
    -				be32_to_cpu(agf->agf_seqno), bno, 1);
    -
    -			xfs_trans_agbtree_delta(cur->bc_tp, -1);
    -			xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp,
    -				XFS_AGF_ROOTS | XFS_AGF_LEVELS);
    -			/*
    -			 * Update the cursor so there's one fewer level.
    -			 */
    -			xfs_btree_setbuf(cur, level, NULL);
    -			cur->bc_nlevels--;
    -		} else if (level > 0 &&
    -			   (error = xfs_alloc_decrement(cur, level, &i)))
    -			return error;
    -		*stat = 1;
    -		return 0;
    -	}
    -	/*
    -	 * If we deleted the leftmost entry in the block, update the
    -	 * key values above us in the tree.
    -	 */
    -	if (ptr == 1 && (error = xfs_alloc_updkey(cur, lkp, level + 1)))
    -		return error;
    -	/*
    -	 * If the number of records remaining in the block is at least
    -	 * the minimum, we're done.
    -	 */
    -	if (be16_to_cpu(block->bb_numrecs) >= XFS_ALLOC_BLOCK_MINRECS(level, cur)) {
    -		if (level > 0 && (error = xfs_alloc_decrement(cur, level, &i)))
    -			return error;
    -		*stat = 1;
    -		return 0;
    -	}
    -	/*
    -	 * Otherwise, we have to move some records around to keep the
    -	 * tree balanced.  Look at the left and right sibling blocks to
    -	 * see if we can re-balance by moving only one record.
    -	 */
    -	rbno = be32_to_cpu(block->bb_rightsib);
    -	lbno = be32_to_cpu(block->bb_leftsib);
    -	bno = NULLAGBLOCK;
    -	ASSERT(rbno != NULLAGBLOCK || lbno != NULLAGBLOCK);
    -	/*
    -	 * Duplicate the cursor so our btree manipulations here won't
    -	 * disrupt the next level up.
    -	 */
    -	if ((error = xfs_btree_dup_cursor(cur, &tcur)))
    -		return error;
    -	/*
    -	 * If there's a right sibling, see if it's ok to shift an entry
    -	 * out of it.
    -	 */
    -	if (rbno != NULLAGBLOCK) {
    -		/*
    -		 * Move the temp cursor to the last entry in the next block.
    -		 * Actually any entry but the first would suffice.
    -		 */
    -		i = xfs_btree_lastrec(tcur, level);
    -		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -		if ((error = xfs_alloc_increment(tcur, level, &i)))
    -			goto error0;
    -		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -		i = xfs_btree_lastrec(tcur, level);
    -		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -		/*
    -		 * Grab a pointer to the block.
    -		 */
    -		rbp = tcur->bc_bufs[level];
    -		right = XFS_BUF_TO_ALLOC_BLOCK(rbp);
    -#ifdef DEBUG
    -		if ((error = xfs_btree_check_sblock(cur, right, level, rbp)))
    -			goto error0;
    -#endif
    -		/*
    -		 * Grab the current block number, for future use.
    -		 */
    -		bno = be32_to_cpu(right->bb_leftsib);
    -		/*
    -		 * If right block is full enough so that removing one entry
    -		 * won't make it too empty, and left-shifting an entry out
    -		 * of right to us works, we're done.
    -		 */
    -		if (be16_to_cpu(right->bb_numrecs) - 1 >=
    -		     XFS_ALLOC_BLOCK_MINRECS(level, cur)) {
    -			if ((error = xfs_alloc_lshift(tcur, level, &i)))
    -				goto error0;
    -			if (i) {
    -				ASSERT(be16_to_cpu(block->bb_numrecs) >=
    -				       XFS_ALLOC_BLOCK_MINRECS(level, cur));
    -				xfs_btree_del_cursor(tcur,
    -						     XFS_BTREE_NOERROR);
    -				if (level > 0 &&
    -				    (error = xfs_alloc_decrement(cur, level,
    -					    &i)))
    -					return error;
    -				*stat = 1;
    -				return 0;
    -			}
    -		}
    -		/*
    -		 * Otherwise, grab the number of records in right for
    -		 * future reference, and fix up the temp cursor to point
    -		 * to our block again (last record).
    -		 */
    -		rrecs = be16_to_cpu(right->bb_numrecs);
    -		if (lbno != NULLAGBLOCK) {
    -			i = xfs_btree_firstrec(tcur, level);
    -			XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -			if ((error = xfs_alloc_decrement(tcur, level, &i)))
    -				goto error0;
    -			XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -		}
    -	}
    -	/*
    -	 * If there's a left sibling, see if it's ok to shift an entry
    -	 * out of it.
    -	 */
    -	if (lbno != NULLAGBLOCK) {
    -		/*
    -		 * Move the temp cursor to the first entry in the
    -		 * previous block.
    -		 */
    -		i = xfs_btree_firstrec(tcur, level);
    -		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -		if ((error = xfs_alloc_decrement(tcur, level, &i)))
    -			goto error0;
    -		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -		xfs_btree_firstrec(tcur, level);
    -		/*
    -		 * Grab a pointer to the block.
    -		 */
    -		lbp = tcur->bc_bufs[level];
    -		left = XFS_BUF_TO_ALLOC_BLOCK(lbp);
    -#ifdef DEBUG
    -		if ((error = xfs_btree_check_sblock(cur, left, level, lbp)))
    -			goto error0;
    -#endif
    -		/*
    -		 * Grab the current block number, for future use.
    -		 */
    -		bno = be32_to_cpu(left->bb_rightsib);
    -		/*
    -		 * If left block is full enough so that removing one entry
    -		 * won't make it too empty, and right-shifting an entry out
    -		 * of left to us works, we're done.
    -		 */
    -		if (be16_to_cpu(left->bb_numrecs) - 1 >=
    -		     XFS_ALLOC_BLOCK_MINRECS(level, cur)) {
    -			if ((error = xfs_alloc_rshift(tcur, level, &i)))
    -				goto error0;
    -			if (i) {
    -				ASSERT(be16_to_cpu(block->bb_numrecs) >=
    -				       XFS_ALLOC_BLOCK_MINRECS(level, cur));
    -				xfs_btree_del_cursor(tcur,
    -						     XFS_BTREE_NOERROR);
    -				if (level == 0)
    -					cur->bc_ptrs[0]++;
    -				*stat = 1;
    -				return 0;
    -			}
    -		}
    -		/*
    -		 * Otherwise, grab the number of records in right for
    -		 * future reference.
    -		 */
    -		lrecs = be16_to_cpu(left->bb_numrecs);
    -	}
    -	/*
    -	 * Delete the temp cursor, we're done with it.
    -	 */
    -	xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
    -	/*
    -	 * If here, we need to do a join to keep the tree balanced.
    -	 */
    -	ASSERT(bno != NULLAGBLOCK);
    -	/*
    -	 * See if we can join with the left neighbor block.
    -	 */
    -	if (lbno != NULLAGBLOCK &&
    -	    lrecs + be16_to_cpu(block->bb_numrecs) <= XFS_ALLOC_BLOCK_MAXRECS(level, cur)) {
    -		/*
    -		 * Set "right" to be the starting block,
    -		 * "left" to be the left neighbor.
    -		 */
    -		rbno = bno;
    -		right = block;
    -		rbp = bp;
    -		if ((error = xfs_btree_read_bufs(mp, cur->bc_tp,
    -				cur->bc_private.a.agno, lbno, 0, &lbp,
    -				XFS_ALLOC_BTREE_REF)))
    -			return error;
    -		left = XFS_BUF_TO_ALLOC_BLOCK(lbp);
    -		if ((error = xfs_btree_check_sblock(cur, left, level, lbp)))
    -			return error;
    -	}
    -	/*
    -	 * If that won't work, see if we can join with the right neighbor block.
    -	 */
    -	else if (rbno != NULLAGBLOCK &&
    -		 rrecs + be16_to_cpu(block->bb_numrecs) <=
    -		  XFS_ALLOC_BLOCK_MAXRECS(level, cur)) {
    -		/*
    -		 * Set "left" to be the starting block,
    -		 * "right" to be the right neighbor.
    -		 */
    -		lbno = bno;
    -		left = block;
    -		lbp = bp;
    -		if ((error = xfs_btree_read_bufs(mp, cur->bc_tp,
    -				cur->bc_private.a.agno, rbno, 0, &rbp,
    -				XFS_ALLOC_BTREE_REF)))
    -			return error;
    -		right = XFS_BUF_TO_ALLOC_BLOCK(rbp);
    -		if ((error = xfs_btree_check_sblock(cur, right, level, rbp)))
    -			return error;
    -	}
    -	/*
    -	 * Otherwise, we can't fix the imbalance.
    -	 * Just return.  This is probably a logic error, but it's not fatal.
    -	 */
    -	else {
    -		if (level > 0 && (error = xfs_alloc_decrement(cur, level, &i)))
    -			return error;
    -		*stat = 1;
    -		return 0;
    -	}
    -	/*
    -	 * We're now going to join "left" and "right" by moving all the stuff
    -	 * in "right" to "left" and deleting "right".
    -	 */
    -	if (level > 0) {
    -		/*
    -		 * It's a non-leaf.  Move keys and pointers.
    -		 */
    -		lkp = XFS_ALLOC_KEY_ADDR(left, be16_to_cpu(left->bb_numrecs) + 1, cur);
    -		lpp = XFS_ALLOC_PTR_ADDR(left, be16_to_cpu(left->bb_numrecs) + 1, cur);
    -		rkp = XFS_ALLOC_KEY_ADDR(right, 1, cur);
    -		rpp = XFS_ALLOC_PTR_ADDR(right, 1, cur);
    -#ifdef DEBUG
    -		for (i = 0; i < be16_to_cpu(right->bb_numrecs); i++) {
    -			if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(rpp[i]), level)))
    -				return error;
    -		}
    -#endif
    -		memcpy(lkp, rkp, be16_to_cpu(right->bb_numrecs) * sizeof(*lkp));
    -		memcpy(lpp, rpp, be16_to_cpu(right->bb_numrecs) * sizeof(*lpp));
    -		xfs_alloc_log_keys(cur, lbp, be16_to_cpu(left->bb_numrecs) + 1,
    -				   be16_to_cpu(left->bb_numrecs) +
    -				   be16_to_cpu(right->bb_numrecs));
    -		xfs_alloc_log_ptrs(cur, lbp, be16_to_cpu(left->bb_numrecs) + 1,
    -				   be16_to_cpu(left->bb_numrecs) +
    -				   be16_to_cpu(right->bb_numrecs));
    -	} else {
    -		/*
    -		 * It's a leaf.  Move records.
    -		 */
    -		lrp = XFS_ALLOC_REC_ADDR(left, be16_to_cpu(left->bb_numrecs) + 1, cur);
    -		rrp = XFS_ALLOC_REC_ADDR(right, 1, cur);
    -		memcpy(lrp, rrp, be16_to_cpu(right->bb_numrecs) * sizeof(*lrp));
    -		xfs_alloc_log_recs(cur, lbp, be16_to_cpu(left->bb_numrecs) + 1,
    -				   be16_to_cpu(left->bb_numrecs) +
    -				   be16_to_cpu(right->bb_numrecs));
    -	}
    -	/*
    -	 * If we joined with the left neighbor, set the buffer in the
    -	 * cursor to the left block, and fix up the index.
    -	 */
    -	if (bp != lbp) {
    -		xfs_btree_setbuf(cur, level, lbp);
    -		cur->bc_ptrs[level] += be16_to_cpu(left->bb_numrecs);
    -	}
    -	/*
    -	 * If we joined with the right neighbor and there's a level above
    -	 * us, increment the cursor at that level.
    -	 */
    -	else if (level + 1 < cur->bc_nlevels &&
    -		 (error = xfs_alloc_increment(cur, level + 1, &i)))
    -		return error;
    -	/*
    -	 * Fix up the number of records in the surviving block.
    -	 */
    -	be16_add(&left->bb_numrecs, be16_to_cpu(right->bb_numrecs));
    -	/*
    -	 * Fix up the right block pointer in the surviving block, and log it.
    -	 */
    -	left->bb_rightsib = right->bb_rightsib;
    -	xfs_alloc_log_block(cur->bc_tp, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB);
    -	/*
    -	 * If there is a right sibling now, make it point to the
    -	 * remaining block.
    -	 */
    -	if (be32_to_cpu(left->bb_rightsib) != NULLAGBLOCK) {
    -		xfs_alloc_block_t	*rrblock;
    -		xfs_buf_t		*rrbp;
    -
    -		if ((error = xfs_btree_read_bufs(mp, cur->bc_tp,
    -				cur->bc_private.a.agno, be32_to_cpu(left->bb_rightsib), 0,
    -				&rrbp, XFS_ALLOC_BTREE_REF)))
    -			return error;
    -		rrblock = XFS_BUF_TO_ALLOC_BLOCK(rrbp);
    -		if ((error = xfs_btree_check_sblock(cur, rrblock, level, rrbp)))
    -			return error;
    -		rrblock->bb_leftsib = cpu_to_be32(lbno);
    -		xfs_alloc_log_block(cur->bc_tp, rrbp, XFS_BB_LEFTSIB);
    -	}
    -	/*
    -	 * Free the deleting block by putting it on the freelist.
    -	 */
    -	if ((error = xfs_alloc_put_freelist(cur->bc_tp, cur->bc_private.a.agbp,
    -			NULL, rbno)))
    -		return error;
    -	/*
    -	 * Since blocks move to the free list without the coordination
    -	 * used in xfs_bmap_finish, we can't allow block to be available
    -	 * for reallocation and non-transaction writing (user data)
    -	 * until we know that the transaction that moved it to the free
    -	 * list is permanently on disk. We track the blocks by declaring
    -	 * these blocks as "busy"; the busy list is maintained on a
    -	 * per-ag basis and each transaction records which entries
    -	 * should be removed when the iclog commits to disk. If a
    -	 * busy block is allocated, the iclog is pushed up to the
    -	 * LSN that freed the block.
    -	 */
    -	xfs_alloc_mark_busy(cur->bc_tp, be32_to_cpu(agf->agf_seqno), bno, 1);
    -	xfs_trans_agbtree_delta(cur->bc_tp, -1);
    -
    -	/*
    -	 * Adjust the current level's cursor so that we're left referring
    -	 * to the right node, after we're done.
    -	 * If this leaves the ptr value 0 our caller will fix it up.
    -	 */
    -	if (level > 0)
    -		cur->bc_ptrs[level]--;
    -	/*
    -	 * Return value means the next level up has something to do.
    -	 */
    -	*stat = 2;
    -	return 0;
    -
    -error0:
    -	xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR);
    -	return error;
    -}
    -
    -/*
    - * Insert one record/level.  Return information to the caller
    - * allowing the next level up to proceed if necessary.
    - */
    -STATIC int				/* error */
    -xfs_alloc_insrec(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	int			level,	/* level to insert record at */
    -	xfs_agblock_t		*bnop,	/* i/o: block number inserted */
    -	xfs_alloc_rec_t		*recp,	/* i/o: record data inserted */
    -	xfs_btree_cur_t		**curp,	/* output: new cursor replacing cur */
    -	int			*stat)	/* output: success/failure */
    -{
    -	xfs_agf_t		*agf;	/* allocation group freelist header */
    -	xfs_alloc_block_t	*block;	/* btree block record/key lives in */
    -	xfs_buf_t		*bp;	/* buffer for block */
    -	int			error;	/* error return value */
    -	int			i;	/* loop index */
    -	xfs_alloc_key_t		key;	/* key value being inserted */
    -	xfs_alloc_key_t		*kp;	/* pointer to btree keys */
    -	xfs_agblock_t		nbno;	/* block number of allocated block */
    -	xfs_btree_cur_t		*ncur;	/* new cursor to be used at next lvl */
    -	xfs_alloc_key_t		nkey;	/* new key value, from split */
    -	xfs_alloc_rec_t		nrec;	/* new record value, for caller */
    -	int			optr;	/* old ptr value */
    -	xfs_alloc_ptr_t		*pp;	/* pointer to btree addresses */
    -	int			ptr;	/* index in btree block for this rec */
    -	xfs_alloc_rec_t		*rp;	/* pointer to btree records */
    -
    -	ASSERT(be32_to_cpu(recp->ar_blockcount) > 0);
    -
    -	/*
    -	 * GCC doesn't understand the (arguably complex) control flow in
    -	 * this function and complains about uninitialized structure fields
    -	 * without this.
    -	 */
    -	memset(&nrec, 0, sizeof(nrec));
    -
    -	/*
    -	 * If we made it to the root level, allocate a new root block
    -	 * and we're done.
    -	 */
    -	if (level >= cur->bc_nlevels) {
    -		XFS_STATS_INC(xs_abt_insrec);
    -		if ((error = xfs_alloc_newroot(cur, &i)))
    -			return error;
    -		*bnop = NULLAGBLOCK;
    -		*stat = i;
    -		return 0;
    -	}
    -	/*
    -	 * Make a key out of the record data to be inserted, and save it.
    -	 */
    -	key.ar_startblock = recp->ar_startblock;
    -	key.ar_blockcount = recp->ar_blockcount;
    -	optr = ptr = cur->bc_ptrs[level];
    -	/*
    -	 * If we're off the left edge, return failure.
    -	 */
    -	if (ptr == 0) {
    -		*stat = 0;
    -		return 0;
    -	}
    -	XFS_STATS_INC(xs_abt_insrec);
    -	/*
    -	 * Get pointers to the btree buffer and block.
    -	 */
    -	bp = cur->bc_bufs[level];
    -	block = XFS_BUF_TO_ALLOC_BLOCK(bp);
    -#ifdef DEBUG
    -	if ((error = xfs_btree_check_sblock(cur, block, level, bp)))
    -		return error;
    -	/*
    -	 * Check that the new entry is being inserted in the right place.
    -	 */
    -	if (ptr <= be16_to_cpu(block->bb_numrecs)) {
    -		if (level == 0) {
    -			rp = XFS_ALLOC_REC_ADDR(block, ptr, cur);
    -			xfs_btree_check_rec(cur->bc_btnum, recp, rp);
    -		} else {
    -			kp = XFS_ALLOC_KEY_ADDR(block, ptr, cur);
    -			xfs_btree_check_key(cur->bc_btnum, &key, kp);
    -		}
    -	}
    -#endif
    -	nbno = NULLAGBLOCK;
    -	ncur = (xfs_btree_cur_t *)0;
    -	/*
    -	 * If the block is full, we can't insert the new entry until we
    -	 * make the block un-full.
    -	 */
    -	if (be16_to_cpu(block->bb_numrecs) == XFS_ALLOC_BLOCK_MAXRECS(level, cur)) {
    -		/*
    -		 * First, try shifting an entry to the right neighbor.
    -		 */
    -		if ((error = xfs_alloc_rshift(cur, level, &i)))
    -			return error;
    -		if (i) {
    -			/* nothing */
    -		}
    -		/*
    -		 * Next, try shifting an entry to the left neighbor.
    -		 */
    -		else {
    -			if ((error = xfs_alloc_lshift(cur, level, &i)))
    -				return error;
    -			if (i)
    -				optr = ptr = cur->bc_ptrs[level];
    -			else {
    -				/*
    -				 * Next, try splitting the current block in
    -				 * half. If this works we have to re-set our
    -				 * variables because we could be in a
    -				 * different block now.
    -				 */
    -				if ((error = xfs_alloc_split(cur, level, &nbno,
    -						&nkey, &ncur, &i)))
    -					return error;
    -				if (i) {
    -					bp = cur->bc_bufs[level];
    -					block = XFS_BUF_TO_ALLOC_BLOCK(bp);
    -#ifdef DEBUG
    -					if ((error =
    -						xfs_btree_check_sblock(cur,
    -							block, level, bp)))
    -						return error;
    -#endif
    -					ptr = cur->bc_ptrs[level];
    -					nrec.ar_startblock = nkey.ar_startblock;
    -					nrec.ar_blockcount = nkey.ar_blockcount;
    -				}
    -				/*
    -				 * Otherwise the insert fails.
    -				 */
    -				else {
    -					*stat = 0;
    -					return 0;
    -				}
    -			}
    -		}
    -	}
    -	/*
    -	 * At this point we know there's room for our new entry in the block
    -	 * we're pointing at.
    -	 */
    -	if (level > 0) {
    -		/*
    -		 * It's a non-leaf entry.  Make a hole for the new data
    -		 * in the key and ptr regions of the block.
    -		 */
    -		kp = XFS_ALLOC_KEY_ADDR(block, 1, cur);
    -		pp = XFS_ALLOC_PTR_ADDR(block, 1, cur);
    -#ifdef DEBUG
    -		for (i = be16_to_cpu(block->bb_numrecs); i >= ptr; i--) {
    -			if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(pp[i - 1]), level)))
    -				return error;
    -		}
    -#endif
    -		memmove(&kp[ptr], &kp[ptr - 1],
    -			(be16_to_cpu(block->bb_numrecs) - ptr + 1) * sizeof(*kp));
    -		memmove(&pp[ptr], &pp[ptr - 1],
    -			(be16_to_cpu(block->bb_numrecs) - ptr + 1) * sizeof(*pp));
    -#ifdef DEBUG
    -		if ((error = xfs_btree_check_sptr(cur, *bnop, level)))
    -			return error;
    -#endif
    -		/*
    -		 * Now stuff the new data in, bump numrecs and log the new data.
    -		 */
    -		kp[ptr - 1] = key;
    -		pp[ptr - 1] = cpu_to_be32(*bnop);
    -		be16_add(&block->bb_numrecs, 1);
    -		xfs_alloc_log_keys(cur, bp, ptr, be16_to_cpu(block->bb_numrecs));
    -		xfs_alloc_log_ptrs(cur, bp, ptr, be16_to_cpu(block->bb_numrecs));
    -#ifdef DEBUG
    -		if (ptr < be16_to_cpu(block->bb_numrecs))
    -			xfs_btree_check_key(cur->bc_btnum, kp + ptr - 1,
    -				kp + ptr);
    -#endif
    -	} else {
    -		/*
    -		 * It's a leaf entry.  Make a hole for the new record.
    -		 */
    -		rp = XFS_ALLOC_REC_ADDR(block, 1, cur);
    -		memmove(&rp[ptr], &rp[ptr - 1],
    -			(be16_to_cpu(block->bb_numrecs) - ptr + 1) * sizeof(*rp));
    -		/*
    -		 * Now stuff the new record in, bump numrecs
    -		 * and log the new data.
    -		 */
    -		rp[ptr - 1] = *recp; /* INT_: struct copy */
    -		be16_add(&block->bb_numrecs, 1);
    -		xfs_alloc_log_recs(cur, bp, ptr, be16_to_cpu(block->bb_numrecs));
    -#ifdef DEBUG
    -		if (ptr < be16_to_cpu(block->bb_numrecs))
    -			xfs_btree_check_rec(cur->bc_btnum, rp + ptr - 1,
    -				rp + ptr);
    -#endif
    -	}
    -	/*
    -	 * Log the new number of records in the btree header.
    -	 */
    -	xfs_alloc_log_block(cur->bc_tp, bp, XFS_BB_NUMRECS);
    -	/*
    -	 * If we inserted at the start of a block, update the parents' keys.
    -	 */
    -	if (optr == 1 && (error = xfs_alloc_updkey(cur, &key, level + 1)))
    -		return error;
    -	/*
    -	 * Look to see if the longest extent in the allocation group
    -	 * needs to be updated.
    -	 */
    -
    -	agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);
    -	if (level == 0 &&
    -	    cur->bc_btnum == XFS_BTNUM_CNT &&
    -	    be32_to_cpu(block->bb_rightsib) == NULLAGBLOCK &&
    -	    be32_to_cpu(recp->ar_blockcount) > be32_to_cpu(agf->agf_longest)) {
    -		/*
    -		 * If this is a leaf in the by-size btree and there
    -		 * is no right sibling block and this block is bigger
    -		 * than the previous longest block, update it.
    -		 */
    -		agf->agf_longest = recp->ar_blockcount;
    -		cur->bc_mp->m_perag[be32_to_cpu(agf->agf_seqno)].pagf_longest
    -			= be32_to_cpu(recp->ar_blockcount);
    -		xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp,
    -			XFS_AGF_LONGEST);
    -	}
    -	/*
    -	 * Return the new block number, if any.
    -	 * If there is one, give back a record value and a cursor too.
    -	 */
    -	*bnop = nbno;
    -	if (nbno != NULLAGBLOCK) {
    -		*recp = nrec; /* INT_: struct copy */
    -		*curp = ncur; /* INT_: struct copy */
    -	}
    -	*stat = 1;
    -	return 0;
    -}
    -
    -/*
    - * Log header fields from a btree block.
    - */
    -STATIC void
    -xfs_alloc_log_block(
    -	xfs_trans_t		*tp,	/* transaction pointer */
    -	xfs_buf_t		*bp,	/* buffer containing btree block */
    -	int			fields)	/* mask of fields: XFS_BB_... */
    -{
    -	int			first;	/* first byte offset logged */
    -	int			last;	/* last byte offset logged */
    -	static const short	offsets[] = {	/* table of offsets */
    -		offsetof(xfs_alloc_block_t, bb_magic),
    -		offsetof(xfs_alloc_block_t, bb_level),
    -		offsetof(xfs_alloc_block_t, bb_numrecs),
    -		offsetof(xfs_alloc_block_t, bb_leftsib),
    -		offsetof(xfs_alloc_block_t, bb_rightsib),
    -		sizeof(xfs_alloc_block_t)
    -	};
    -
    -	xfs_btree_offsets(fields, offsets, XFS_BB_NUM_BITS, &first, &last);
    -	xfs_trans_log_buf(tp, bp, first, last);
    -}
    -
    -/*
    - * Log keys from a btree block (nonleaf).
    - */
    -STATIC void
    -xfs_alloc_log_keys(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	xfs_buf_t		*bp,	/* buffer containing btree block */
    -	int			kfirst,	/* index of first key to log */
    -	int			klast)	/* index of last key to log */
    -{
    -	xfs_alloc_block_t	*block;	/* btree block to log from */
    -	int			first;	/* first byte offset logged */
    -	xfs_alloc_key_t		*kp;	/* key pointer in btree block */
    -	int			last;	/* last byte offset logged */
    -
    -	block = XFS_BUF_TO_ALLOC_BLOCK(bp);
    -	kp = XFS_ALLOC_KEY_ADDR(block, 1, cur);
    -	first = (int)((xfs_caddr_t)&kp[kfirst - 1] - (xfs_caddr_t)block);
    -	last = (int)(((xfs_caddr_t)&kp[klast] - 1) - (xfs_caddr_t)block);
    -	xfs_trans_log_buf(cur->bc_tp, bp, first, last);
    -}
    -
    -/*
    - * Log block pointer fields from a btree block (nonleaf).
    - */
    -STATIC void
    -xfs_alloc_log_ptrs(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	xfs_buf_t		*bp,	/* buffer containing btree block */
    -	int			pfirst,	/* index of first pointer to log */
    -	int			plast)	/* index of last pointer to log */
    -{
    -	xfs_alloc_block_t	*block;	/* btree block to log from */
    -	int			first;	/* first byte offset logged */
    -	int			last;	/* last byte offset logged */
    -	xfs_alloc_ptr_t		*pp;	/* block-pointer pointer in btree blk */
    -
    -	block = XFS_BUF_TO_ALLOC_BLOCK(bp);
    -	pp = XFS_ALLOC_PTR_ADDR(block, 1, cur);
    -	first = (int)((xfs_caddr_t)&pp[pfirst - 1] - (xfs_caddr_t)block);
    -	last = (int)(((xfs_caddr_t)&pp[plast] - 1) - (xfs_caddr_t)block);
    -	xfs_trans_log_buf(cur->bc_tp, bp, first, last);
    -}
    -
    -/*
    - * Log records from a btree block (leaf).
    - */
    -STATIC void
    -xfs_alloc_log_recs(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	xfs_buf_t		*bp,	/* buffer containing btree block */
    -	int			rfirst,	/* index of first record to log */
    -	int			rlast)	/* index of last record to log */
    -{
    -	xfs_alloc_block_t	*block;	/* btree block to log from */
    -	int			first;	/* first byte offset logged */
    -	int			last;	/* last byte offset logged */
    -	xfs_alloc_rec_t		*rp;	/* record pointer for btree block */
    -
    -
    -	block = XFS_BUF_TO_ALLOC_BLOCK(bp);
    -	rp = XFS_ALLOC_REC_ADDR(block, 1, cur);
    -#ifdef DEBUG
    -	{
    -		xfs_agf_t	*agf;
    -		xfs_alloc_rec_t	*p;
    -
    -		agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);
    -		for (p = &rp[rfirst - 1]; p <= &rp[rlast - 1]; p++)
    -			ASSERT(be32_to_cpu(p->ar_startblock) +
    -			       be32_to_cpu(p->ar_blockcount) <=
    -			       be32_to_cpu(agf->agf_length));
    -	}
    -#endif
    -	first = (int)((xfs_caddr_t)&rp[rfirst - 1] - (xfs_caddr_t)block);
    -	last = (int)(((xfs_caddr_t)&rp[rlast] - 1) - (xfs_caddr_t)block);
    -	xfs_trans_log_buf(cur->bc_tp, bp, first, last);
    -}
    -
    -/*
    - * Lookup the record.  The cursor is made to point to it, based on dir.
    - * Return 0 if can't find any such record, 1 for success.
    - */
    -STATIC int				/* error */
    -xfs_alloc_lookup(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	xfs_lookup_t		dir,	/* <=, ==, or >= */
    -	int			*stat)	/* success/failure */
    -{
    -	xfs_agblock_t		agbno;	/* a.g. relative btree block number */
    -	xfs_agnumber_t		agno;	/* allocation group number */
    -	xfs_alloc_block_t	*block=NULL;	/* current btree block */
    -	int			diff;	/* difference for the current key */
    -	int			error;	/* error return value */
    -	int			keyno=0;	/* current key number */
    -	int			level;	/* level in the btree */
    -	xfs_mount_t		*mp;	/* file system mount point */
    -
    -	XFS_STATS_INC(xs_abt_lookup);
    -	/*
    -	 * Get the allocation group header, and the root block number.
    -	 */
    -	mp = cur->bc_mp;
    -
    -	{
    -		xfs_agf_t	*agf;	/* a.g. freespace header */
    -
    -		agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);
    -		agno = be32_to_cpu(agf->agf_seqno);
    -		agbno = be32_to_cpu(agf->agf_roots[cur->bc_btnum]);
    -	}
    -	/*
    -	 * Iterate over each level in the btree, starting at the root.
    -	 * For each level above the leaves, find the key we need, based
    -	 * on the lookup record, then follow the corresponding block
    -	 * pointer down to the next level.
    -	 */
    -	for (level = cur->bc_nlevels - 1, diff = 1; level >= 0; level--) {
    -		xfs_buf_t	*bp;	/* buffer pointer for btree block */
    -		xfs_daddr_t	d;	/* disk address of btree block */
    -
    -		/*
    -		 * Get the disk address we're looking for.
    -		 */
    -		d = XFS_AGB_TO_DADDR(mp, agno, agbno);
    -		/*
    -		 * If the old buffer at this level is for a different block,
    -		 * throw it away, otherwise just use it.
    -		 */
    -		bp = cur->bc_bufs[level];
    -		if (bp && XFS_BUF_ADDR(bp) != d)
    -			bp = (xfs_buf_t *)0;
    -		if (!bp) {
    -			/*
    -			 * Need to get a new buffer.  Read it, then
    -			 * set it in the cursor, releasing the old one.
    -			 */
    -			if ((error = xfs_btree_read_bufs(mp, cur->bc_tp, agno,
    -					agbno, 0, &bp, XFS_ALLOC_BTREE_REF)))
    -				return error;
    -			xfs_btree_setbuf(cur, level, bp);
    -			/*
    -			 * Point to the btree block, now that we have the buffer
    -			 */
    -			block = XFS_BUF_TO_ALLOC_BLOCK(bp);
    -			if ((error = xfs_btree_check_sblock(cur, block, level,
    -					bp)))
    -				return error;
    -		} else
    -			block = XFS_BUF_TO_ALLOC_BLOCK(bp);
    -		/*
    -		 * If we already had a key match at a higher level, we know
    -		 * we need to use the first entry in this block.
    -		 */
    -		if (diff == 0)
    -			keyno = 1;
    -		/*
    -		 * Otherwise we need to search this block.  Do a binary search.
    -		 */
    -		else {
    -			int		high;	/* high entry number */
    -			xfs_alloc_key_t	*kkbase=NULL;/* base of keys in block */
    -			xfs_alloc_rec_t	*krbase=NULL;/* base of records in block */
    -			int		low;	/* low entry number */
    -
    -			/*
    -			 * Get a pointer to keys or records.
    -			 */
    -			if (level > 0)
    -				kkbase = XFS_ALLOC_KEY_ADDR(block, 1, cur);
    -			else
    -				krbase = XFS_ALLOC_REC_ADDR(block, 1, cur);
    -			/*
    -			 * Set low and high entry numbers, 1-based.
    -			 */
    -			low = 1;
    -			if (!(high = be16_to_cpu(block->bb_numrecs))) {
    -				/*
    -				 * If the block is empty, the tree must
    -				 * be an empty leaf.
    -				 */
    -				ASSERT(level == 0 && cur->bc_nlevels == 1);
    -				cur->bc_ptrs[0] = dir != XFS_LOOKUP_LE;
    -				*stat = 0;
    -				return 0;
    -			}
    -			/*
    -			 * Binary search the block.
    -			 */
    -			while (low <= high) {
    -				xfs_extlen_t	blockcount;	/* key value */
    -				xfs_agblock_t	startblock;	/* key value */
    -
    -				XFS_STATS_INC(xs_abt_compare);
    -				/*
    -				 * keyno is average of low and high.
    -				 */
    -				keyno = (low + high) >> 1;
    -				/*
    -				 * Get startblock & blockcount.
    -				 */
    -				if (level > 0) {
    -					xfs_alloc_key_t	*kkp;
    -
    -					kkp = kkbase + keyno - 1;
    -					startblock = be32_to_cpu(kkp->ar_startblock);
    -					blockcount = be32_to_cpu(kkp->ar_blockcount);
    -				} else {
    -					xfs_alloc_rec_t	*krp;
    -
    -					krp = krbase + keyno - 1;
    -					startblock = be32_to_cpu(krp->ar_startblock);
    -					blockcount = be32_to_cpu(krp->ar_blockcount);
    -				}
    -				/*
    -				 * Compute difference to get next direction.
    -				 */
    -				if (cur->bc_btnum == XFS_BTNUM_BNO)
    -					diff = (int)startblock -
    -					       (int)cur->bc_rec.a.ar_startblock;
    -				else if (!(diff = (int)blockcount -
    -					    (int)cur->bc_rec.a.ar_blockcount))
    -					diff = (int)startblock -
    -					    (int)cur->bc_rec.a.ar_startblock;
    -				/*
    -				 * Less than, move right.
    -				 */
    -				if (diff < 0)
    -					low = keyno + 1;
    -				/*
    -				 * Greater than, move left.
    -				 */
    -				else if (diff > 0)
    -					high = keyno - 1;
    -				/*
    -				 * Equal, we're done.
    -				 */
    -				else
    -					break;
    -			}
    -		}
    -		/*
    -		 * If there are more levels, set up for the next level
    -		 * by getting the block number and filling in the cursor.
    -		 */
    -		if (level > 0) {
    -			/*
    -			 * If we moved left, need the previous key number,
    -			 * unless there isn't one.
    -			 */
    -			if (diff > 0 && --keyno < 1)
    -				keyno = 1;
    -			agbno = be32_to_cpu(*XFS_ALLOC_PTR_ADDR(block, keyno, cur));
    -#ifdef DEBUG
    -			if ((error = xfs_btree_check_sptr(cur, agbno, level)))
    -				return error;
    -#endif
    -			cur->bc_ptrs[level] = keyno;
    -		}
    -	}
    -	/*
    -	 * Done with the search.
    -	 * See if we need to adjust the results.
    -	 */
    -	if (dir != XFS_LOOKUP_LE && diff < 0) {
    -		keyno++;
    -		/*
    -		 * If ge search and we went off the end of the block, but it's
    -		 * not the last block, we're in the wrong block.
    -		 */
    -		if (dir == XFS_LOOKUP_GE &&
    -		    keyno > be16_to_cpu(block->bb_numrecs) &&
    -		    be32_to_cpu(block->bb_rightsib) != NULLAGBLOCK) {
    -			int	i;
    -
    -			cur->bc_ptrs[0] = keyno;
    -			if ((error = xfs_alloc_increment(cur, 0, &i)))
    -				return error;
    -			XFS_WANT_CORRUPTED_RETURN(i == 1);
    -			*stat = 1;
    -			return 0;
    -		}
    -	}
    -	else if (dir == XFS_LOOKUP_LE && diff > 0)
    -		keyno--;
    -	cur->bc_ptrs[0] = keyno;
    -	/*
    -	 * Return if we succeeded or not.
    -	 */
    -	if (keyno == 0 || keyno > be16_to_cpu(block->bb_numrecs))
    -		*stat = 0;
    -	else
    -		*stat = ((dir != XFS_LOOKUP_EQ) || (diff == 0));
    -	return 0;
    -}
    -
    -/*
    - * Move 1 record left from cur/level if possible.
    - * Update cur to reflect the new path.
    - */
    -STATIC int				/* error */
    -xfs_alloc_lshift(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	int			level,	/* level to shift record on */
    -	int			*stat)	/* success/failure */
    -{
    -	int			error;	/* error return value */
    -#ifdef DEBUG
    -	int			i;	/* loop index */
    -#endif
    -	xfs_alloc_key_t		key;	/* key value for leaf level upward */
    -	xfs_buf_t		*lbp;	/* buffer for left neighbor block */
    -	xfs_alloc_block_t	*left;	/* left neighbor btree block */
    -	int			nrec;	/* new number of left block entries */
    -	xfs_buf_t		*rbp;	/* buffer for right (current) block */
    -	xfs_alloc_block_t	*right;	/* right (current) btree block */
    -	xfs_alloc_key_t		*rkp=NULL;	/* key pointer for right block */
    -	xfs_alloc_ptr_t		*rpp=NULL;	/* address pointer for right block */
    -	xfs_alloc_rec_t		*rrp=NULL;	/* record pointer for right block */
    -
    -	/*
    -	 * Set up variables for this block as "right".
    -	 */
    -	rbp = cur->bc_bufs[level];
    -	right = XFS_BUF_TO_ALLOC_BLOCK(rbp);
    -#ifdef DEBUG
    -	if ((error = xfs_btree_check_sblock(cur, right, level, rbp)))
    -		return error;
    -#endif
    -	/*
    -	 * If we've got no left sibling then we can't shift an entry left.
    -	 */
    -	if (be32_to_cpu(right->bb_leftsib) == NULLAGBLOCK) {
    -		*stat = 0;
    -		return 0;
    -	}
    -	/*
    -	 * If the cursor entry is the one that would be moved, don't
    -	 * do it... it's too complicated.
    -	 */
    -	if (cur->bc_ptrs[level] <= 1) {
    -		*stat = 0;
    -		return 0;
    -	}
    -	/*
    -	 * Set up the left neighbor as "left".
    -	 */
    -	if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp,
    -			cur->bc_private.a.agno, be32_to_cpu(right->bb_leftsib),
    -			0, &lbp, XFS_ALLOC_BTREE_REF)))
    -		return error;
    -	left = XFS_BUF_TO_ALLOC_BLOCK(lbp);
    -	if ((error = xfs_btree_check_sblock(cur, left, level, lbp)))
    -		return error;
    -	/*
    -	 * If it's full, it can't take another entry.
    -	 */
    -	if (be16_to_cpu(left->bb_numrecs) == XFS_ALLOC_BLOCK_MAXRECS(level, cur)) {
    -		*stat = 0;
    -		return 0;
    -	}
    -	nrec = be16_to_cpu(left->bb_numrecs) + 1;
    -	/*
    -	 * If non-leaf, copy a key and a ptr to the left block.
    -	 */
    -	if (level > 0) {
    -		xfs_alloc_key_t	*lkp;	/* key pointer for left block */
    -		xfs_alloc_ptr_t	*lpp;	/* address pointer for left block */
    -
    -		lkp = XFS_ALLOC_KEY_ADDR(left, nrec, cur);
    -		rkp = XFS_ALLOC_KEY_ADDR(right, 1, cur);
    -		*lkp = *rkp;
    -		xfs_alloc_log_keys(cur, lbp, nrec, nrec);
    -		lpp = XFS_ALLOC_PTR_ADDR(left, nrec, cur);
    -		rpp = XFS_ALLOC_PTR_ADDR(right, 1, cur);
    -#ifdef DEBUG
    -		if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(*rpp), level)))
    -			return error;
    -#endif
    -		*lpp = *rpp; /* INT_: copy */
    -		xfs_alloc_log_ptrs(cur, lbp, nrec, nrec);
    -		xfs_btree_check_key(cur->bc_btnum, lkp - 1, lkp);
    -	}
    -	/*
    -	 * If leaf, copy a record to the left block.
    -	 */
    -	else {
    -		xfs_alloc_rec_t	*lrp;	/* record pointer for left block */
    -
    -		lrp = XFS_ALLOC_REC_ADDR(left, nrec, cur);
    -		rrp = XFS_ALLOC_REC_ADDR(right, 1, cur);
    -		*lrp = *rrp;
    -		xfs_alloc_log_recs(cur, lbp, nrec, nrec);
    -		xfs_btree_check_rec(cur->bc_btnum, lrp - 1, lrp);
    -	}
    -	/*
    -	 * Bump and log left's numrecs, decrement and log right's numrecs.
    -	 */
    -	be16_add(&left->bb_numrecs, 1);
    -	xfs_alloc_log_block(cur->bc_tp, lbp, XFS_BB_NUMRECS);
    -	be16_add(&right->bb_numrecs, -1);
    -	xfs_alloc_log_block(cur->bc_tp, rbp, XFS_BB_NUMRECS);
    -	/*
    -	 * Slide the contents of right down one entry.
    -	 */
    -	if (level > 0) {
    -#ifdef DEBUG
    -		for (i = 0; i < be16_to_cpu(right->bb_numrecs); i++) {
    -			if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(rpp[i + 1]),
    -					level)))
    -				return error;
    -		}
    -#endif
    -		memmove(rkp, rkp + 1, be16_to_cpu(right->bb_numrecs) * sizeof(*rkp));
    -		memmove(rpp, rpp + 1, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp));
    -		xfs_alloc_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));
    -		xfs_alloc_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));
    -	} else {
    -		memmove(rrp, rrp + 1, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp));
    -		xfs_alloc_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));
    -		key.ar_startblock = rrp->ar_startblock;
    -		key.ar_blockcount = rrp->ar_blockcount;
    -		rkp = &key;
    -	}
    -	/*
    -	 * Update the parent key values of right.
    -	 */
    -	if ((error = xfs_alloc_updkey(cur, rkp, level + 1)))
    -		return error;
    -	/*
    -	 * Slide the cursor value left one.
    -	 */
    -	cur->bc_ptrs[level]--;
    -	*stat = 1;
    -	return 0;
    -}
    -
    -/*
    - * Allocate a new root block, fill it in.
    - */
    -STATIC int				/* error */
    -xfs_alloc_newroot(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	int			*stat)	/* success/failure */
    -{
    -	int			error;	/* error return value */
    -	xfs_agblock_t		lbno;	/* left block number */
    -	xfs_buf_t		*lbp;	/* left btree buffer */
    -	xfs_alloc_block_t	*left;	/* left btree block */
    -	xfs_mount_t		*mp;	/* mount structure */
    -	xfs_agblock_t		nbno;	/* new block number */
    -	xfs_buf_t		*nbp;	/* new (root) buffer */
    -	xfs_alloc_block_t	*new;	/* new (root) btree block */
    -	int			nptr;	/* new value for key index, 1 or 2 */
    -	xfs_agblock_t		rbno;	/* right block number */
    -	xfs_buf_t		*rbp;	/* right btree buffer */
    -	xfs_alloc_block_t	*right;	/* right btree block */
    -
    -	mp = cur->bc_mp;
    -
    -	ASSERT(cur->bc_nlevels < XFS_AG_MAXLEVELS(mp));
    -	/*
    -	 * Get a buffer from the freelist blocks, for the new root.
    -	 */
    -	if ((error = xfs_alloc_get_freelist(cur->bc_tp, cur->bc_private.a.agbp,
    -			&nbno)))
    -		return error;
    -	/*
    -	 * None available, we fail.
    -	 */
    -	if (nbno == NULLAGBLOCK) {
    -		*stat = 0;
    -		return 0;
    -	}
    -	xfs_trans_agbtree_delta(cur->bc_tp, 1);
    -	nbp = xfs_btree_get_bufs(mp, cur->bc_tp, cur->bc_private.a.agno, nbno,
    -		0);
    -	new = XFS_BUF_TO_ALLOC_BLOCK(nbp);
    -	/*
    -	 * Set the root data in the a.g. freespace structure.
    -	 */
    -	{
    -		xfs_agf_t	*agf;	/* a.g. freespace header */
    -		xfs_agnumber_t	seqno;
    -
    -		agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);
    -		agf->agf_roots[cur->bc_btnum] = cpu_to_be32(nbno);
    -		be32_add(&agf->agf_levels[cur->bc_btnum], 1);
    -		seqno = be32_to_cpu(agf->agf_seqno);
    -		mp->m_perag[seqno].pagf_levels[cur->bc_btnum]++;
    -		xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp,
    -			XFS_AGF_ROOTS | XFS_AGF_LEVELS);
    -	}
    -	/*
    -	 * At the previous root level there are now two blocks: the old
    -	 * root, and the new block generated when it was split.
    -	 * We don't know which one the cursor is pointing at, so we
    -	 * set up variables "left" and "right" for each case.
    -	 */
    -	lbp = cur->bc_bufs[cur->bc_nlevels - 1];
    -	left = XFS_BUF_TO_ALLOC_BLOCK(lbp);
    -#ifdef DEBUG
    -	if ((error = xfs_btree_check_sblock(cur, left, cur->bc_nlevels - 1, lbp)))
    -		return error;
    -#endif
    -	if (be32_to_cpu(left->bb_rightsib) != NULLAGBLOCK) {
    -		/*
    -		 * Our block is left, pick up the right block.
    -		 */
    -		lbno = XFS_DADDR_TO_AGBNO(mp, XFS_BUF_ADDR(lbp));
    -		rbno = be32_to_cpu(left->bb_rightsib);
    -		if ((error = xfs_btree_read_bufs(mp, cur->bc_tp,
    -				cur->bc_private.a.agno, rbno, 0, &rbp,
    -				XFS_ALLOC_BTREE_REF)))
    -			return error;
    -		right = XFS_BUF_TO_ALLOC_BLOCK(rbp);
    -		if ((error = xfs_btree_check_sblock(cur, right,
    -				cur->bc_nlevels - 1, rbp)))
    -			return error;
    -		nptr = 1;
    -	} else {
    -		/*
    -		 * Our block is right, pick up the left block.
    -		 */
    -		rbp = lbp;
    -		right = left;
    -		rbno = XFS_DADDR_TO_AGBNO(mp, XFS_BUF_ADDR(rbp));
    -		lbno = be32_to_cpu(right->bb_leftsib);
    -		if ((error = xfs_btree_read_bufs(mp, cur->bc_tp,
    -				cur->bc_private.a.agno, lbno, 0, &lbp,
    -				XFS_ALLOC_BTREE_REF)))
    -			return error;
    -		left = XFS_BUF_TO_ALLOC_BLOCK(lbp);
    -		if ((error = xfs_btree_check_sblock(cur, left,
    -				cur->bc_nlevels - 1, lbp)))
    -			return error;
    -		nptr = 2;
    -	}
    -	/*
    -	 * Fill in the new block's btree header and log it.
    -	 */
    -	new->bb_magic = cpu_to_be32(xfs_magics[cur->bc_btnum]);
    -	new->bb_level = cpu_to_be16(cur->bc_nlevels);
    -	new->bb_numrecs = cpu_to_be16(2);
    -	new->bb_leftsib = cpu_to_be32(NULLAGBLOCK);
    -	new->bb_rightsib = cpu_to_be32(NULLAGBLOCK);
    -	xfs_alloc_log_block(cur->bc_tp, nbp, XFS_BB_ALL_BITS);
    -	ASSERT(lbno != NULLAGBLOCK && rbno != NULLAGBLOCK);
    -	/*
    -	 * Fill in the key data in the new root.
    -	 */
    -	{
    -		xfs_alloc_key_t		*kp;	/* btree key pointer */
    -
    -		kp = XFS_ALLOC_KEY_ADDR(new, 1, cur);
    -		if (be16_to_cpu(left->bb_level) > 0) {
    -			kp[0] = *XFS_ALLOC_KEY_ADDR(left, 1, cur); /* INT_: structure copy */
    -			kp[1] = *XFS_ALLOC_KEY_ADDR(right, 1, cur);/* INT_: structure copy */
    -		} else {
    -			xfs_alloc_rec_t	*rp;	/* btree record pointer */
    -
    -			rp = XFS_ALLOC_REC_ADDR(left, 1, cur);
    -			kp[0].ar_startblock = rp->ar_startblock;
    -			kp[0].ar_blockcount = rp->ar_blockcount;
    -			rp = XFS_ALLOC_REC_ADDR(right, 1, cur);
    -			kp[1].ar_startblock = rp->ar_startblock;
    -			kp[1].ar_blockcount = rp->ar_blockcount;
    -		}
    -	}
    -	xfs_alloc_log_keys(cur, nbp, 1, 2);
    -	/*
    -	 * Fill in the pointer data in the new root.
    -	 */
    -	{
    -		xfs_alloc_ptr_t		*pp;	/* btree address pointer */
    -
    -		pp = XFS_ALLOC_PTR_ADDR(new, 1, cur);
    -		pp[0] = cpu_to_be32(lbno);
    -		pp[1] = cpu_to_be32(rbno);
    -	}
    -	xfs_alloc_log_ptrs(cur, nbp, 1, 2);
    -	/*
    -	 * Fix up the cursor.
    -	 */
    -	xfs_btree_setbuf(cur, cur->bc_nlevels, nbp);
    -	cur->bc_ptrs[cur->bc_nlevels] = nptr;
    -	cur->bc_nlevels++;
    -	*stat = 1;
    -	return 0;
    -}
    -
    -/*
    - * Move 1 record right from cur/level if possible.
    - * Update cur to reflect the new path.
    - */
    -STATIC int				/* error */
    -xfs_alloc_rshift(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	int			level,	/* level to shift record on */
    -	int			*stat)	/* success/failure */
    -{
    -	int			error;	/* error return value */
    -	int			i;	/* loop index */
    -	xfs_alloc_key_t		key;	/* key value for leaf level upward */
    -	xfs_buf_t		*lbp;	/* buffer for left (current) block */
    -	xfs_alloc_block_t	*left;	/* left (current) btree block */
    -	xfs_buf_t		*rbp;	/* buffer for right neighbor block */
    -	xfs_alloc_block_t	*right;	/* right neighbor btree block */
    -	xfs_alloc_key_t		*rkp;	/* key pointer for right block */
    -	xfs_btree_cur_t		*tcur;	/* temporary cursor */
    -
    -	/*
    -	 * Set up variables for this block as "left".
    -	 */
    -	lbp = cur->bc_bufs[level];
    -	left = XFS_BUF_TO_ALLOC_BLOCK(lbp);
    -#ifdef DEBUG
    -	if ((error = xfs_btree_check_sblock(cur, left, level, lbp)))
    -		return error;
    -#endif
    -	/*
    -	 * If we've got no right sibling then we can't shift an entry right.
    -	 */
    -	if (be32_to_cpu(left->bb_rightsib) == NULLAGBLOCK) {
    -		*stat = 0;
    -		return 0;
    -	}
    -	/*
    -	 * If the cursor entry is the one that would be moved, don't
    -	 * do it... it's too complicated.
    -	 */
    -	if (cur->bc_ptrs[level] >= be16_to_cpu(left->bb_numrecs)) {
    -		*stat = 0;
    -		return 0;
    -	}
    -	/*
    -	 * Set up the right neighbor as "right".
    -	 */
    -	if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp,
    -			cur->bc_private.a.agno, be32_to_cpu(left->bb_rightsib),
    -			0, &rbp, XFS_ALLOC_BTREE_REF)))
    -		return error;
    -	right = XFS_BUF_TO_ALLOC_BLOCK(rbp);
    -	if ((error = xfs_btree_check_sblock(cur, right, level, rbp)))
    -		return error;
    -	/*
    -	 * If it's full, it can't take another entry.
    -	 */
    -	if (be16_to_cpu(right->bb_numrecs) == XFS_ALLOC_BLOCK_MAXRECS(level, cur)) {
    -		*stat = 0;
    -		return 0;
    -	}
    -	/*
    -	 * Make a hole at the start of the right neighbor block, then
    -	 * copy the last left block entry to the hole.
    -	 */
    -	if (level > 0) {
    -		xfs_alloc_key_t	*lkp;	/* key pointer for left block */
    -		xfs_alloc_ptr_t	*lpp;	/* address pointer for left block */
    -		xfs_alloc_ptr_t	*rpp;	/* address pointer for right block */
    -
    -		lkp = XFS_ALLOC_KEY_ADDR(left, be16_to_cpu(left->bb_numrecs), cur);
    -		lpp = XFS_ALLOC_PTR_ADDR(left, be16_to_cpu(left->bb_numrecs), cur);
    -		rkp = XFS_ALLOC_KEY_ADDR(right, 1, cur);
    -		rpp = XFS_ALLOC_PTR_ADDR(right, 1, cur);
    -#ifdef DEBUG
    -		for (i = be16_to_cpu(right->bb_numrecs) - 1; i >= 0; i--) {
    -			if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(rpp[i]), level)))
    -				return error;
    -		}
    -#endif
    -		memmove(rkp + 1, rkp, be16_to_cpu(right->bb_numrecs) * sizeof(*rkp));
    -		memmove(rpp + 1, rpp, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp));
    -#ifdef DEBUG
    -		if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(*lpp), level)))
    -			return error;
    -#endif
    -		*rkp = *lkp; /* INT_: copy */
    -		*rpp = *lpp; /* INT_: copy */
    -		xfs_alloc_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1);
    -		xfs_alloc_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1);
    -		xfs_btree_check_key(cur->bc_btnum, rkp, rkp + 1);
    -	} else {
    -		xfs_alloc_rec_t	*lrp;	/* record pointer for left block */
    -		xfs_alloc_rec_t	*rrp;	/* record pointer for right block */
    -
    -		lrp = XFS_ALLOC_REC_ADDR(left, be16_to_cpu(left->bb_numrecs), cur);
    -		rrp = XFS_ALLOC_REC_ADDR(right, 1, cur);
    -		memmove(rrp + 1, rrp, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp));
    -		*rrp = *lrp;
    -		xfs_alloc_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1);
    -		key.ar_startblock = rrp->ar_startblock;
    -		key.ar_blockcount = rrp->ar_blockcount;
    -		rkp = &key;
    -		xfs_btree_check_rec(cur->bc_btnum, rrp, rrp + 1);
    -	}
    -	/*
    -	 * Decrement and log left's numrecs, bump and log right's numrecs.
    -	 */
    -	be16_add(&left->bb_numrecs, -1);
    -	xfs_alloc_log_block(cur->bc_tp, lbp, XFS_BB_NUMRECS);
    -	be16_add(&right->bb_numrecs, 1);
    -	xfs_alloc_log_block(cur->bc_tp, rbp, XFS_BB_NUMRECS);
    -	/*
    -	 * Using a temporary cursor, update the parent key values of the
    -	 * block on the right.
    -	 */
    -	if ((error = xfs_btree_dup_cursor(cur, &tcur)))
    -		return error;
    -	i = xfs_btree_lastrec(tcur, level);
    -	XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -	if ((error = xfs_alloc_increment(tcur, level, &i)) ||
    -	    (error = xfs_alloc_updkey(tcur, rkp, level + 1)))
    -		goto error0;
    -	xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
    -	*stat = 1;
    -	return 0;
    -error0:
    -	xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR);
    -	return error;
    -}
    -
    -/*
    - * Split cur/level block in half.
    - * Return new block number and its first record (to be inserted into parent).
    - */
    -STATIC int				/* error */
    -xfs_alloc_split(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	int			level,	/* level to split */
    -	xfs_agblock_t		*bnop,	/* output: block number allocated */
    -	xfs_alloc_key_t		*keyp,	/* output: first key of new block */
    -	xfs_btree_cur_t		**curp,	/* output: new cursor */
    -	int			*stat)	/* success/failure */
    -{
    -	int			error;	/* error return value */
    -	int			i;	/* loop index/record number */
    -	xfs_agblock_t		lbno;	/* left (current) block number */
    -	xfs_buf_t		*lbp;	/* buffer for left block */
    -	xfs_alloc_block_t	*left;	/* left (current) btree block */
    -	xfs_agblock_t		rbno;	/* right (new) block number */
    -	xfs_buf_t		*rbp;	/* buffer for right block */
    -	xfs_alloc_block_t	*right;	/* right (new) btree block */
    -
    -	/*
    -	 * Allocate the new block from the freelist.
    -	 * If we can't do it, we're toast.  Give up.
    -	 */
    -	if ((error = xfs_alloc_get_freelist(cur->bc_tp, cur->bc_private.a.agbp,
    -			&rbno)))
    -		return error;
    -	if (rbno == NULLAGBLOCK) {
    -		*stat = 0;
    -		return 0;
    -	}
    -	xfs_trans_agbtree_delta(cur->bc_tp, 1);
    -	rbp = xfs_btree_get_bufs(cur->bc_mp, cur->bc_tp, cur->bc_private.a.agno,
    -		rbno, 0);
    -	/*
    -	 * Set up the new block as "right".
    -	 */
    -	right = XFS_BUF_TO_ALLOC_BLOCK(rbp);
    -	/*
    -	 * "Left" is the current (according to the cursor) block.
    -	 */
    -	lbp = cur->bc_bufs[level];
    -	left = XFS_BUF_TO_ALLOC_BLOCK(lbp);
    -#ifdef DEBUG
    -	if ((error = xfs_btree_check_sblock(cur, left, level, lbp)))
    -		return error;
    -#endif
    -	/*
    -	 * Fill in the btree header for the new block.
    -	 */
    -	right->bb_magic = cpu_to_be32(xfs_magics[cur->bc_btnum]);
    -	right->bb_level = left->bb_level;
    -	right->bb_numrecs = cpu_to_be16(be16_to_cpu(left->bb_numrecs) / 2);
    -	/*
    -	 * Make sure that if there's an odd number of entries now, that
    -	 * each new block will have the same number of entries.
    -	 */
    -	if ((be16_to_cpu(left->bb_numrecs) & 1) &&
    -	    cur->bc_ptrs[level] <= be16_to_cpu(right->bb_numrecs) + 1)
    -		be16_add(&right->bb_numrecs, 1);
    -	i = be16_to_cpu(left->bb_numrecs) - be16_to_cpu(right->bb_numrecs) + 1;
    -	/*
    -	 * For non-leaf blocks, copy keys and addresses over to the new block.
    -	 */
    -	if (level > 0) {
    -		xfs_alloc_key_t	*lkp;	/* left btree key pointer */
    -		xfs_alloc_ptr_t	*lpp;	/* left btree address pointer */
    -		xfs_alloc_key_t	*rkp;	/* right btree key pointer */
    -		xfs_alloc_ptr_t	*rpp;	/* right btree address pointer */
    -
    -		lkp = XFS_ALLOC_KEY_ADDR(left, i, cur);
    -		lpp = XFS_ALLOC_PTR_ADDR(left, i, cur);
    -		rkp = XFS_ALLOC_KEY_ADDR(right, 1, cur);
    -		rpp = XFS_ALLOC_PTR_ADDR(right, 1, cur);
    -#ifdef DEBUG
    -		for (i = 0; i < be16_to_cpu(right->bb_numrecs); i++) {
    -			if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(lpp[i]), level)))
    -				return error;
    -		}
    -#endif
    -		memcpy(rkp, lkp, be16_to_cpu(right->bb_numrecs) * sizeof(*rkp));
    -		memcpy(rpp, lpp, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp));
    -		xfs_alloc_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));
    -		xfs_alloc_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));
    -		*keyp = *rkp;
    -	}
    -	/*
    -	 * For leaf blocks, copy records over to the new block.
    -	 */
    -	else {
    -		xfs_alloc_rec_t	*lrp;	/* left btree record pointer */
    -		xfs_alloc_rec_t	*rrp;	/* right btree record pointer */
    -
    -		lrp = XFS_ALLOC_REC_ADDR(left, i, cur);
    -		rrp = XFS_ALLOC_REC_ADDR(right, 1, cur);
    -		memcpy(rrp, lrp, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp));
    -		xfs_alloc_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));
    -		keyp->ar_startblock = rrp->ar_startblock;
    -		keyp->ar_blockcount = rrp->ar_blockcount;
    -	}
    -	/*
    -	 * Find the left block number by looking in the buffer.
    -	 * Adjust numrecs, sibling pointers.
    -	 */
    -	lbno = XFS_DADDR_TO_AGBNO(cur->bc_mp, XFS_BUF_ADDR(lbp));
    -	be16_add(&left->bb_numrecs, -(be16_to_cpu(right->bb_numrecs)));
    -	right->bb_rightsib = left->bb_rightsib;
    -	left->bb_rightsib = cpu_to_be32(rbno);
    -	right->bb_leftsib = cpu_to_be32(lbno);
    -	xfs_alloc_log_block(cur->bc_tp, rbp, XFS_BB_ALL_BITS);
    -	xfs_alloc_log_block(cur->bc_tp, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB);
    -	/*
    -	 * If there's a block to the new block's right, make that block
    -	 * point back to right instead of to left.
    -	 */
    -	if (be32_to_cpu(right->bb_rightsib) != NULLAGBLOCK) {
    -		xfs_alloc_block_t	*rrblock;	/* rr btree block */
    -		xfs_buf_t		*rrbp;		/* buffer for rrblock */
    -
    -		if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp,
    -				cur->bc_private.a.agno, be32_to_cpu(right->bb_rightsib), 0,
    -				&rrbp, XFS_ALLOC_BTREE_REF)))
    -			return error;
    -		rrblock = XFS_BUF_TO_ALLOC_BLOCK(rrbp);
    -		if ((error = xfs_btree_check_sblock(cur, rrblock, level, rrbp)))
    -			return error;
    -		rrblock->bb_leftsib = cpu_to_be32(rbno);
    -		xfs_alloc_log_block(cur->bc_tp, rrbp, XFS_BB_LEFTSIB);
    -	}
    -	/*
    -	 * If the cursor is really in the right block, move it there.
    -	 * If it's just pointing past the last entry in left, then we'll
    -	 * insert there, so don't change anything in that case.
    -	 */
    -	if (cur->bc_ptrs[level] > be16_to_cpu(left->bb_numrecs) + 1) {
    -		xfs_btree_setbuf(cur, level, rbp);
    -		cur->bc_ptrs[level] -= be16_to_cpu(left->bb_numrecs);
    -	}
    -	/*
    -	 * If there are more levels, we'll need another cursor which refers to
    -	 * the right block, no matter where this cursor was.
    -	 */
    -	if (level + 1 < cur->bc_nlevels) {
    -		if ((error = xfs_btree_dup_cursor(cur, curp)))
    -			return error;
    -		(*curp)->bc_ptrs[level + 1]++;
    -	}
    -	*bnop = rbno;
    -	*stat = 1;
    -	return 0;
    -}
    -
    -/*
    - * Update keys at all levels from here to the root along the cursor's path.
    - */
    -STATIC int				/* error */
    -xfs_alloc_updkey(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	xfs_alloc_key_t		*keyp,	/* new key value to update to */
    -	int			level)	/* starting level for update */
    -{
    -	int			ptr;	/* index of key in block */
    -
    -	/*
    -	 * Go up the tree from this level toward the root.
    -	 * At each level, update the key value to the value input.
    -	 * Stop when we reach a level where the cursor isn't pointing
    -	 * at the first entry in the block.
    -	 */
    -	for (ptr = 1; ptr == 1 && level < cur->bc_nlevels; level++) {
    -		xfs_alloc_block_t	*block;	/* btree block */
    -		xfs_buf_t		*bp;	/* buffer for block */
    -#ifdef DEBUG
    -		int			error;	/* error return value */
    -#endif
    -		xfs_alloc_key_t		*kp;	/* ptr to btree block keys */
    -
    -		bp = cur->bc_bufs[level];
    -		block = XFS_BUF_TO_ALLOC_BLOCK(bp);
    -#ifdef DEBUG
    -		if ((error = xfs_btree_check_sblock(cur, block, level, bp)))
    -			return error;
    -#endif
    -		ptr = cur->bc_ptrs[level];
    -		kp = XFS_ALLOC_KEY_ADDR(block, ptr, cur);
    -		*kp = *keyp;
    -		xfs_alloc_log_keys(cur, bp, ptr, ptr);
    -	}
    -	return 0;
    -}
    -
    -/*
    - * Externally visible routines.
    - */
    -
    -/*
    - * Decrement cursor by one record at the level.
    - * For nonzero levels the leaf-ward information is untouched.
    - */
    -int					/* error */
    -xfs_alloc_decrement(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	int			level,	/* level in btree, 0 is leaf */
    -	int			*stat)	/* success/failure */
    -{
    -	xfs_alloc_block_t	*block;	/* btree block */
    -	int			error;	/* error return value */
    -	int			lev;	/* btree level */
    -
    -	ASSERT(level < cur->bc_nlevels);
    -	/*
    -	 * Read-ahead to the left at this level.
    -	 */
    -	xfs_btree_readahead(cur, level, XFS_BTCUR_LEFTRA);
    -	/*
    -	 * Decrement the ptr at this level.  If we're still in the block
    -	 * then we're done.
    -	 */
    -	if (--cur->bc_ptrs[level] > 0) {
    -		*stat = 1;
    -		return 0;
    -	}
    -	/*
    -	 * Get a pointer to the btree block.
    -	 */
    -	block = XFS_BUF_TO_ALLOC_BLOCK(cur->bc_bufs[level]);
    -#ifdef DEBUG
    -	if ((error = xfs_btree_check_sblock(cur, block, level,
    -			cur->bc_bufs[level])))
    -		return error;
    -#endif
    -	/*
    -	 * If we just went off the left edge of the tree, return failure.
    -	 */
    -	if (be32_to_cpu(block->bb_leftsib) == NULLAGBLOCK) {
    -		*stat = 0;
    -		return 0;
    -	}
    -	/*
    -	 * March up the tree decrementing pointers.
    -	 * Stop when we don't go off the left edge of a block.
    -	 */
    -	for (lev = level + 1; lev < cur->bc_nlevels; lev++) {
    -		if (--cur->bc_ptrs[lev] > 0)
    -			break;
    -		/*
    -		 * Read-ahead the left block, we're going to read it
    -		 * in the next loop.
    -		 */
    -		xfs_btree_readahead(cur, lev, XFS_BTCUR_LEFTRA);
    -	}
    -	/*
    -	 * If we went off the root then we are seriously confused.
    -	 */
    -	ASSERT(lev < cur->bc_nlevels);
    -	/*
    -	 * Now walk back down the tree, fixing up the cursor's buffer
    -	 * pointers and key numbers.
    -	 */
    -	for (block = XFS_BUF_TO_ALLOC_BLOCK(cur->bc_bufs[lev]); lev > level; ) {
    -		xfs_agblock_t	agbno;	/* block number of btree block */
    -		xfs_buf_t	*bp;	/* buffer pointer for block */
    -
    -		agbno = be32_to_cpu(*XFS_ALLOC_PTR_ADDR(block, cur->bc_ptrs[lev], cur));
    -		if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp,
    -				cur->bc_private.a.agno, agbno, 0, &bp,
    -				XFS_ALLOC_BTREE_REF)))
    -			return error;
    -		lev--;
    -		xfs_btree_setbuf(cur, lev, bp);
    -		block = XFS_BUF_TO_ALLOC_BLOCK(bp);
    -		if ((error = xfs_btree_check_sblock(cur, block, lev, bp)))
    -			return error;
    -		cur->bc_ptrs[lev] = be16_to_cpu(block->bb_numrecs);
    -	}
    -	*stat = 1;
    -	return 0;
    -}
    -
    -/*
    - * Delete the record pointed to by cur.
    - * The cursor refers to the place where the record was (could be inserted)
    - * when the operation returns.
    - */
    -int					/* error */
    -xfs_alloc_delete(
    -	xfs_btree_cur_t	*cur,		/* btree cursor */
    -	int		*stat)		/* success/failure */
    -{
    -	int		error;		/* error return value */
    -	int		i;		/* result code */
    -	int		level;		/* btree level */
    -
    -	/*
    -	 * Go up the tree, starting at leaf level.
    -	 * If 2 is returned then a join was done; go to the next level.
    -	 * Otherwise we are done.
    -	 */
    -	for (level = 0, i = 2; i == 2; level++) {
    -		if ((error = xfs_alloc_delrec(cur, level, &i)))
    -			return error;
    -	}
    -	if (i == 0) {
    -		for (level = 1; level < cur->bc_nlevels; level++) {
    -			if (cur->bc_ptrs[level] == 0) {
    -				if ((error = xfs_alloc_decrement(cur, level, &i)))
    -					return error;
    -				break;
    -			}
    -		}
    -	}
    -	*stat = i;
    -	return 0;
    -}
    -
    -/*
    - * Get the data from the pointed-to record.
    - */
    -int					/* error */
    -xfs_alloc_get_rec(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	xfs_agblock_t		*bno,	/* output: starting block of extent */
    -	xfs_extlen_t		*len,	/* output: length of extent */
    -	int			*stat)	/* output: success/failure */
    -{
    -	xfs_alloc_block_t	*block;	/* btree block */
    -#ifdef DEBUG
    -	int			error;	/* error return value */
    -#endif
    -	int			ptr;	/* record number */
    -
    -	ptr = cur->bc_ptrs[0];
    -	block = XFS_BUF_TO_ALLOC_BLOCK(cur->bc_bufs[0]);
    -#ifdef DEBUG
    -	if ((error = xfs_btree_check_sblock(cur, block, 0, cur->bc_bufs[0])))
    -		return error;
    -#endif
    -	/*
    -	 * Off the right end or left end, return failure.
    -	 */
    -	if (ptr > be16_to_cpu(block->bb_numrecs) || ptr <= 0) {
    -		*stat = 0;
    -		return 0;
    -	}
    -	/*
    -	 * Point to the record and extract its data.
    -	 */
    -	{
    -		xfs_alloc_rec_t		*rec;	/* record data */
    -
    -		rec = XFS_ALLOC_REC_ADDR(block, ptr, cur);
    -		*bno = be32_to_cpu(rec->ar_startblock);
    -		*len = be32_to_cpu(rec->ar_blockcount);
    -	}
    -	*stat = 1;
    -	return 0;
    -}
    -
    -/*
    - * Increment cursor by one record at the level.
    - * For nonzero levels the leaf-ward information is untouched.
    - */
    -int					/* error */
    -xfs_alloc_increment(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	int			level,	/* level in btree, 0 is leaf */
    -	int			*stat)	/* success/failure */
    -{
    -	xfs_alloc_block_t	*block;	/* btree block */
    -	xfs_buf_t		*bp;	/* tree block buffer */
    -	int			error;	/* error return value */
    -	int			lev;	/* btree level */
    -
    -	ASSERT(level < cur->bc_nlevels);
    -	/*
    -	 * Read-ahead to the right at this level.
    -	 */
    -	xfs_btree_readahead(cur, level, XFS_BTCUR_RIGHTRA);
    -	/*
    -	 * Get a pointer to the btree block.
    -	 */
    -	bp = cur->bc_bufs[level];
    -	block = XFS_BUF_TO_ALLOC_BLOCK(bp);
    -#ifdef DEBUG
    -	if ((error = xfs_btree_check_sblock(cur, block, level, bp)))
    -		return error;
    -#endif
    -	/*
    -	 * Increment the ptr at this level.  If we're still in the block
    -	 * then we're done.
    -	 */
    -	if (++cur->bc_ptrs[level] <= be16_to_cpu(block->bb_numrecs)) {
    -		*stat = 1;
    -		return 0;
    -	}
    -	/*
    -	 * If we just went off the right edge of the tree, return failure.
    -	 */
    -	if (be32_to_cpu(block->bb_rightsib) == NULLAGBLOCK) {
    -		*stat = 0;
    -		return 0;
    -	}
    -	/*
    -	 * March up the tree incrementing pointers.
    -	 * Stop when we don't go off the right edge of a block.
    -	 */
    -	for (lev = level + 1; lev < cur->bc_nlevels; lev++) {
    -		bp = cur->bc_bufs[lev];
    -		block = XFS_BUF_TO_ALLOC_BLOCK(bp);
    -#ifdef DEBUG
    -		if ((error = xfs_btree_check_sblock(cur, block, lev, bp)))
    -			return error;
    -#endif
    -		if (++cur->bc_ptrs[lev] <= be16_to_cpu(block->bb_numrecs))
    -			break;
    -		/*
    -		 * Read-ahead the right block, we're going to read it
    -		 * in the next loop.
    -		 */
    -		xfs_btree_readahead(cur, lev, XFS_BTCUR_RIGHTRA);
    -	}
    -	/*
    -	 * If we went off the root then we are seriously confused.
    -	 */
    -	ASSERT(lev < cur->bc_nlevels);
    -	/*
    -	 * Now walk back down the tree, fixing up the cursor's buffer
    -	 * pointers and key numbers.
    -	 */
    -	for (bp = cur->bc_bufs[lev], block = XFS_BUF_TO_ALLOC_BLOCK(bp);
    -	     lev > level; ) {
    -		xfs_agblock_t	agbno;	/* block number of btree block */
    -
    -		agbno = be32_to_cpu(*XFS_ALLOC_PTR_ADDR(block, cur->bc_ptrs[lev], cur));
    -		if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp,
    -				cur->bc_private.a.agno, agbno, 0, &bp,
    -				XFS_ALLOC_BTREE_REF)))
    -			return error;
    -		lev--;
    -		xfs_btree_setbuf(cur, lev, bp);
    -		block = XFS_BUF_TO_ALLOC_BLOCK(bp);
    -		if ((error = xfs_btree_check_sblock(cur, block, lev, bp)))
    -			return error;
    -		cur->bc_ptrs[lev] = 1;
    -	}
    -	*stat = 1;
    -	return 0;
    -}
    -
    -/*
    - * Insert the current record at the point referenced by cur.
    - * The cursor may be inconsistent on return if splits have been done.
    - */
    -int					/* error */
    -xfs_alloc_insert(
    -	xfs_btree_cur_t	*cur,		/* btree cursor */
    -	int		*stat)		/* success/failure */
    -{
    -	int		error;		/* error return value */
    -	int		i;		/* result value, 0 for failure */
    -	int		level;		/* current level number in btree */
    -	xfs_agblock_t	nbno;		/* new block number (split result) */
    -	xfs_btree_cur_t	*ncur;		/* new cursor (split result) */
    -	xfs_alloc_rec_t	nrec;		/* record being inserted this level */
    -	xfs_btree_cur_t	*pcur;		/* previous level's cursor */
    -
    -	level = 0;
    -	nbno = NULLAGBLOCK;
    -	nrec.ar_startblock = cpu_to_be32(cur->bc_rec.a.ar_startblock);
    -	nrec.ar_blockcount = cpu_to_be32(cur->bc_rec.a.ar_blockcount);
    -	ncur = (xfs_btree_cur_t *)0;
    -	pcur = cur;
    -	/*
    -	 * Loop going up the tree, starting at the leaf level.
    -	 * Stop when we don't get a split block, that must mean that
    -	 * the insert is finished with this level.
    -	 */
    -	do {
    -		/*
    -		 * Insert nrec/nbno into this level of the tree.
    -		 * Note if we fail, nbno will be null.
    -		 */
    -		if ((error = xfs_alloc_insrec(pcur, level++, &nbno, &nrec, &ncur,
    -				&i))) {
    -			if (pcur != cur)
    -				xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR);
    -			return error;
    -		}
    -		/*
    -		 * See if the cursor we just used is trash.
    -		 * Can't trash the caller's cursor, but otherwise we should
    -		 * if ncur is a new cursor or we're about to be done.
    -		 */
    -		if (pcur != cur && (ncur || nbno == NULLAGBLOCK)) {
    -			cur->bc_nlevels = pcur->bc_nlevels;
    -			xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR);
    -		}
    -		/*
    -		 * If we got a new cursor, switch to it.
    -		 */
    -		if (ncur) {
    -			pcur = ncur;
    -			ncur = (xfs_btree_cur_t *)0;
    -		}
    -	} while (nbno != NULLAGBLOCK);
    -	*stat = i;
    -	return 0;
    -}
    -
    -/*
    - * Lookup the record equal to [bno, len] in the btree given by cur.
    - */
    -int					/* error */
    -xfs_alloc_lookup_eq(
    -	xfs_btree_cur_t	*cur,		/* btree cursor */
    -	xfs_agblock_t	bno,		/* starting block of extent */
    -	xfs_extlen_t	len,		/* length of extent */
    -	int		*stat)		/* success/failure */
    -{
    -	cur->bc_rec.a.ar_startblock = bno;
    -	cur->bc_rec.a.ar_blockcount = len;
    -	return xfs_alloc_lookup(cur, XFS_LOOKUP_EQ, stat);
    -}
    -
    -/*
    - * Lookup the first record greater than or equal to [bno, len]
    - * in the btree given by cur.
    - */
    -int					/* error */
    -xfs_alloc_lookup_ge(
    -	xfs_btree_cur_t	*cur,		/* btree cursor */
    -	xfs_agblock_t	bno,		/* starting block of extent */
    -	xfs_extlen_t	len,		/* length of extent */
    -	int		*stat)		/* success/failure */
    -{
    -	cur->bc_rec.a.ar_startblock = bno;
    -	cur->bc_rec.a.ar_blockcount = len;
    -	return xfs_alloc_lookup(cur, XFS_LOOKUP_GE, stat);
    -}
    -
    -/*
    - * Lookup the first record less than or equal to [bno, len]
    - * in the btree given by cur.
    - */
    -int					/* error */
    -xfs_alloc_lookup_le(
    -	xfs_btree_cur_t	*cur,		/* btree cursor */
    -	xfs_agblock_t	bno,		/* starting block of extent */
    -	xfs_extlen_t	len,		/* length of extent */
    -	int		*stat)		/* success/failure */
    -{
    -	cur->bc_rec.a.ar_startblock = bno;
    -	cur->bc_rec.a.ar_blockcount = len;
    -	return xfs_alloc_lookup(cur, XFS_LOOKUP_LE, stat);
    -}
    -
    -/*
    - * Update the record referred to by cur, to the value given by [bno, len].
    - * This either works (return 0) or gets an EFSCORRUPTED error.
    - */
    -int					/* error */
    -xfs_alloc_update(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	xfs_agblock_t		bno,	/* starting block of extent */
    -	xfs_extlen_t		len)	/* length of extent */
    -{
    -	xfs_alloc_block_t	*block;	/* btree block to update */
    -	int			error;	/* error return value */
    -	int			ptr;	/* current record number (updating) */
    -
    -	ASSERT(len > 0);
    -	/*
    -	 * Pick up the a.g. freelist struct and the current block.
    -	 */
    -	block = XFS_BUF_TO_ALLOC_BLOCK(cur->bc_bufs[0]);
    -#ifdef DEBUG
    -	if ((error = xfs_btree_check_sblock(cur, block, 0, cur->bc_bufs[0])))
    -		return error;
    -#endif
    -	/*
    -	 * Get the address of the rec to be updated.
    -	 */
    -	ptr = cur->bc_ptrs[0];
    -	{
    -		xfs_alloc_rec_t		*rp;	/* pointer to updated record */
    -
    -		rp = XFS_ALLOC_REC_ADDR(block, ptr, cur);
    -		/*
    -		 * Fill in the new contents and log them.
    -		 */
    -		rp->ar_startblock = cpu_to_be32(bno);
    -		rp->ar_blockcount = cpu_to_be32(len);
    -		xfs_alloc_log_recs(cur, cur->bc_bufs[0], ptr, ptr);
    -	}
    -	/*
    -	 * If it's the by-size btree and it's the last leaf block and
    -	 * it's the last record... then update the size of the longest
    -	 * extent in the a.g., which we cache in the a.g. freelist header.
    -	 */
    -	if (cur->bc_btnum == XFS_BTNUM_CNT &&
    -	    be32_to_cpu(block->bb_rightsib) == NULLAGBLOCK &&
    -	    ptr == be16_to_cpu(block->bb_numrecs)) {
    -		xfs_agf_t	*agf;	/* a.g. freespace header */
    -		xfs_agnumber_t	seqno;
    -
    -		agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);
    -		seqno = be32_to_cpu(agf->agf_seqno);
    -		cur->bc_mp->m_perag[seqno].pagf_longest = len;
    -		agf->agf_longest = cpu_to_be32(len);
    -		xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp,
    -			XFS_AGF_LONGEST);
    -	}
    -	/*
    -	 * Updating first record in leaf. Pass new key value up to our parent.
    -	 */
    -	if (ptr == 1) {
    -		xfs_alloc_key_t	key;	/* key containing [bno, len] */
    -
    -		key.ar_startblock = cpu_to_be32(bno);
    -		key.ar_blockcount = cpu_to_be32(len);
    -		if ((error = xfs_alloc_updkey(cur, &key, 1)))
    -			return error;
    -	}
    -	return 0;
    -}
    diff --git a/sys/gnu/fs/xfs/xfs_alloc_btree.h b/sys/gnu/fs/xfs/xfs_alloc_btree.h
    deleted file mode 100644
    index bce81c7a4fd..00000000000
    --- a/sys/gnu/fs/xfs/xfs_alloc_btree.h
    +++ /dev/null
    @@ -1,159 +0,0 @@
    -/*
    - * Copyright (c) 2000,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_ALLOC_BTREE_H__
    -#define	__XFS_ALLOC_BTREE_H__
    -
    -/*
    - * Freespace on-disk structures
    - */
    -
    -struct xfs_buf;
    -struct xfs_btree_cur;
    -struct xfs_btree_sblock;
    -struct xfs_mount;
    -
    -/*
    - * There are two on-disk btrees, one sorted by blockno and one sorted
    - * by blockcount and blockno.  All blocks look the same to make the code
    - * simpler; if we have time later, we'll make the optimizations.
    - */
    -#define	XFS_ABTB_MAGIC	0x41425442	/* 'ABTB' for bno tree */
    -#define	XFS_ABTC_MAGIC	0x41425443	/* 'ABTC' for cnt tree */
    -
    -/*
    - * Data record/key structure
    - */
    -typedef struct xfs_alloc_rec {
    -	__be32		ar_startblock;	/* starting block number */
    -	__be32		ar_blockcount;	/* count of free blocks */
    -} xfs_alloc_rec_t, xfs_alloc_key_t;
    -
    -typedef struct xfs_alloc_rec_incore {
    -	xfs_agblock_t	ar_startblock;	/* starting block number */
    -	xfs_extlen_t	ar_blockcount;	/* count of free blocks */
    -} xfs_alloc_rec_incore_t;
    -
    -/* btree pointer type */
    -typedef __be32 xfs_alloc_ptr_t;
    -/* btree block header type */
    -typedef	struct xfs_btree_sblock xfs_alloc_block_t;
    -
    -#define	XFS_BUF_TO_ALLOC_BLOCK(bp)	((xfs_alloc_block_t *)XFS_BUF_PTR(bp))
    -
    -/*
    - * Real block structures have a size equal to the disk block size.
    - */
    -#define	XFS_ALLOC_BLOCK_SIZE(lev,cur)	(1 << (cur)->bc_blocklog)
    -#define	XFS_ALLOC_BLOCK_MAXRECS(lev,cur) ((cur)->bc_mp->m_alloc_mxr[lev != 0])
    -#define	XFS_ALLOC_BLOCK_MINRECS(lev,cur) ((cur)->bc_mp->m_alloc_mnr[lev != 0])
    -
    -/*
    - * Minimum and maximum blocksize and sectorsize.
    - * The blocksize upper limit is pretty much arbitrary.
    - * The sectorsize upper limit is due to sizeof(sb_sectsize).
    - */
    -#define XFS_MIN_BLOCKSIZE_LOG	9	/* i.e. 512 bytes */
    -#define XFS_MAX_BLOCKSIZE_LOG	16	/* i.e. 65536 bytes */
    -#define XFS_MIN_BLOCKSIZE	(1 << XFS_MIN_BLOCKSIZE_LOG)
    -#define XFS_MAX_BLOCKSIZE	(1 << XFS_MAX_BLOCKSIZE_LOG)
    -#define XFS_MIN_SECTORSIZE_LOG	9	/* i.e. 512 bytes */
    -#define XFS_MAX_SECTORSIZE_LOG	15	/* i.e. 32768 bytes */
    -#define XFS_MIN_SECTORSIZE	(1 << XFS_MIN_SECTORSIZE_LOG)
    -#define XFS_MAX_SECTORSIZE	(1 << XFS_MAX_SECTORSIZE_LOG)
    -
    -/*
    - * Block numbers in the AG:
    - * SB is sector 0, AGF is sector 1, AGI is sector 2, AGFL is sector 3.
    - */
    -#define	XFS_BNO_BLOCK(mp)	((xfs_agblock_t)(XFS_AGFL_BLOCK(mp) + 1))
    -#define	XFS_CNT_BLOCK(mp)	((xfs_agblock_t)(XFS_BNO_BLOCK(mp) + 1))
    -
    -/*
    - * Record, key, and pointer address macros for btree blocks.
    - */
    -#define	XFS_ALLOC_REC_ADDR(bb,i,cur)	\
    -	XFS_BTREE_REC_ADDR(XFS_ALLOC_BLOCK_SIZE(0,cur), xfs_alloc, \
    -				bb, i, XFS_ALLOC_BLOCK_MAXRECS(0, cur))
    -
    -#define	XFS_ALLOC_KEY_ADDR(bb,i,cur)	\
    -	XFS_BTREE_KEY_ADDR(XFS_ALLOC_BLOCK_SIZE(1,cur), xfs_alloc, \
    -				bb, i, XFS_ALLOC_BLOCK_MAXRECS(1, cur))
    -
    -#define	XFS_ALLOC_PTR_ADDR(bb,i,cur)	\
    -	XFS_BTREE_PTR_ADDR(XFS_ALLOC_BLOCK_SIZE(1,cur), xfs_alloc, \
    -				bb, i, XFS_ALLOC_BLOCK_MAXRECS(1, cur))
    -
    -/*
    - * Decrement cursor by one record at the level.
    - * For nonzero levels the leaf-ward information is untouched.
    - */
    -extern int xfs_alloc_decrement(struct xfs_btree_cur *cur, int level, int *stat);
    -
    -/*
    - * Delete the record pointed to by cur.
    - * The cursor refers to the place where the record was (could be inserted)
    - * when the operation returns.
    - */
    -extern int xfs_alloc_delete(struct xfs_btree_cur *cur, int *stat);
    -
    -/*
    - * Get the data from the pointed-to record.
    - */
    -extern int xfs_alloc_get_rec(struct xfs_btree_cur *cur,	xfs_agblock_t *bno,
    -				xfs_extlen_t *len, int *stat);
    -
    -/*
    - * Increment cursor by one record at the level.
    - * For nonzero levels the leaf-ward information is untouched.
    - */
    -extern int xfs_alloc_increment(struct xfs_btree_cur *cur, int level, int *stat);
    -
    -/*
    - * Insert the current record at the point referenced by cur.
    - * The cursor may be inconsistent on return if splits have been done.
    - */
    -extern int xfs_alloc_insert(struct xfs_btree_cur *cur, int *stat);
    -
    -/*
    - * Lookup the record equal to [bno, len] in the btree given by cur.
    - */
    -extern int xfs_alloc_lookup_eq(struct xfs_btree_cur *cur, xfs_agblock_t bno,
    -				xfs_extlen_t len, int *stat);
    -
    -/*
    - * Lookup the first record greater than or equal to [bno, len]
    - * in the btree given by cur.
    - */
    -extern int xfs_alloc_lookup_ge(struct xfs_btree_cur *cur, xfs_agblock_t bno,
    -				xfs_extlen_t len, int *stat);
    -
    -/*
    - * Lookup the first record less than or equal to [bno, len]
    - * in the btree given by cur.
    - */
    -extern int xfs_alloc_lookup_le(struct xfs_btree_cur *cur, xfs_agblock_t bno,
    -				xfs_extlen_t len, int *stat);
    -
    -/*
    - * Update the record referred to by cur, to the value given by [bno, len].
    - * This either works (return 0) or gets an EFSCORRUPTED error.
    - */
    -extern int xfs_alloc_update(struct xfs_btree_cur *cur, xfs_agblock_t bno,
    -				xfs_extlen_t len);
    -
    -#endif	/* __XFS_ALLOC_BTREE_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_arch.h b/sys/gnu/fs/xfs/xfs_arch.h
    deleted file mode 100644
    index a7d9de54c81..00000000000
    --- a/sys/gnu/fs/xfs/xfs_arch.h
    +++ /dev/null
    @@ -1,239 +0,0 @@
    -/*
    - * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_ARCH_H__
    -#define __XFS_ARCH_H__
    -
    -#ifndef XFS_BIG_INUMS
    -# error XFS_BIG_INUMS must be defined true or false
    -#endif
    -
    -#include 
    -
    -#define	__LITTLE_ENDIAN	_LITTLE_ENDIAN
    -#define	__BIG_ENDIAN	_BIG_ENDIAN
    -#define	__BYTE_ORDER	_BYTE_ORDER
    -#define __user
    -/* Compatibiliy defines */
    -#define	__swab16	__bswap16
    -#define	__swab32	__bswap32
    -#define	__swab64	__bswap64
    -
    -#define ARCH_NOCONVERT 1
    -#if _BYTE_ORDER != _LITTLE_ENDIAN
    -#define	XFS_NATIVE_HOST	1
    -# define ARCH_CONVERT	ARCH_NOCONVERT
    -#else
    -#undef XFS_NATIVE_HOST
    -#define ARCH_CONVERT	0
    -#endif
    -
    -
    -#ifdef XFS_NATIVE_HOST
    -#define cpu_to_be16(val)	((__be16)(val))
    -#define cpu_to_be32(val)	((__be32)(val))
    -#define cpu_to_be64(val)	((__be64)(val))
    -#define be16_to_cpu(val)	((__uint16_t)(val))
    -#define be32_to_cpu(val)	((__uint32_t)(val))
    -#define be64_to_cpu(val)	((__uint64_t)(val))
    -#else
    -#define cpu_to_be16(val)	(__swab16((__uint16_t)(val)))
    -#define cpu_to_be32(val)	(__swab32((__uint32_t)(val)))
    -#define cpu_to_be64(val)	(__swab64((__uint64_t)(val)))
    -#define be16_to_cpu(val)	(__swab16((__be16)(val)))
    -#define be32_to_cpu(val)	(__swab32((__be32)(val)))
    -#define be64_to_cpu(val)	(__swab64((__be64)(val)))
    -#endif
    -
    -//#endif	/* __KERNEL__ */
    -
    -/* do we need conversion? */
    -//#define ARCH_NOCONVERT 1
    -//#ifdef XFS_NATIVE_HOST
    -//# define ARCH_CONVERT	ARCH_NOCONVERT
    -//#else
    -//# define ARCH_CONVERT	0
    -//#endif
    -
    -/* generic swapping macros */
    -
    -#ifndef HAVE_SWABMACROS
    -#define INT_SWAP16(type,var) ((typeof(type))(__swab16((__u16)(var))))
    -#define INT_SWAP32(type,var) ((typeof(type))(__swab32((__u32)(var))))
    -#define INT_SWAP64(type,var) ((typeof(type))(__swab64((__u64)(var))))
    -#endif
    -
    -#define INT_SWAP(type, var) \
    -    ((sizeof(type) == 8) ? INT_SWAP64(type,var) : \
    -    ((sizeof(type) == 4) ? INT_SWAP32(type,var) : \
    -    ((sizeof(type) == 2) ? INT_SWAP16(type,var) : \
    -    (var))))
    -
    -/*
    - * get and set integers from potentially unaligned locations
    - */
    -
    -#define INT_GET_UNALIGNED_16_BE(pointer) \
    -   ((__u16)((((__u8*)(pointer))[0] << 8) | (((__u8*)(pointer))[1])))
    -#define INT_SET_UNALIGNED_16_BE(pointer,value) \
    -    { \
    -	((__u8*)(pointer))[0] = (((value) >> 8) & 0xff); \
    -	((__u8*)(pointer))[1] = (((value)     ) & 0xff); \
    -    }
    -
    -/* define generic INT_ macros */
    -
    -#define INT_GET(reference,arch) \
    -    (((arch) == ARCH_NOCONVERT) \
    -	? \
    -	    (reference) \
    -	: \
    -	    INT_SWAP((reference),(reference)) \
    -    )
    -
    -/* does not return a value */
    -#define INT_SET(reference,arch,valueref) \
    -    (__builtin_constant_p(valueref) ? \
    -	(void)( (reference) = ( ((arch) != ARCH_NOCONVERT) ? (INT_SWAP((reference),(valueref))) : (valueref)) ) : \
    -	(void)( \
    -	    ((reference) = (valueref)), \
    -	    ( ((arch) != ARCH_NOCONVERT) ? (reference) = INT_SWAP((reference),(reference)) : 0 ) \
    -	) \
    -    )
    -
    -/* does not return a value */
    -#define INT_MOD_EXPR(reference,arch,code) \
    -    (((arch) == ARCH_NOCONVERT) \
    -	? \
    -	    (void)((reference) code) \
    -	: \
    -	    (void)( \
    -		(reference) = INT_GET((reference),arch) , \
    -		((reference) code), \
    -		INT_SET(reference, arch, reference) \
    -	    ) \
    -    )
    -
    -/* does not return a value */
    -#define INT_MOD(reference,arch,delta) \
    -    (void)( \
    -	INT_MOD_EXPR(reference,arch,+=(delta)) \
    -    )
    -
    -/*
    - * INT_COPY - copy a value between two locations with the
    - *	      _same architecture_ but _potentially different sizes_
    - *
    - *	    if the types of the two parameters are equal or they are
    - *		in native architecture, a simple copy is done
    - *
    - *	    otherwise, architecture conversions are done
    - *
    - */
    -
    -/* does not return a value */
    -#define INT_COPY(dst,src,arch) \
    -    ( \
    -	((sizeof(dst) == sizeof(src)) || ((arch) == ARCH_NOCONVERT)) \
    -	    ? \
    -		(void)((dst) = (src)) \
    -	    : \
    -		INT_SET(dst, arch, INT_GET(src, arch)) \
    -    )
    -
    -/*
    - * INT_XLATE - copy a value in either direction between two locations
    - *	       with different architectures
    - *
    - *		    dir < 0	- copy from memory to buffer (native to arch)
    - *		    dir > 0	- copy from buffer to memory (arch to native)
    - */
    -
    -/* does not return a value */
    -#define INT_XLATE(buf,mem,dir,arch) {\
    -    ASSERT(dir); \
    -    if (dir>0) { \
    -	(mem)=INT_GET(buf, arch); \
    -    } else { \
    -	INT_SET(buf, arch, mem); \
    -    } \
    -}
    -
    -static inline void be16_add(__be16 *a, __s16 b)
    -{
    -	*a = cpu_to_be16(be16_to_cpu(*a) + b);
    -}
    -
    -static inline void be32_add(__be32 *a, __s32 b)
    -{
    -	*a = cpu_to_be32(be32_to_cpu(*a) + b);
    -}
    -
    -static inline void be64_add(__be64 *a, __s64 b)
    -{
    -	*a = cpu_to_be64(be64_to_cpu(*a) + b);
    -}
    -
    -/*
    - * In directories inode numbers are stored as unaligned arrays of unsigned
    - * 8bit integers on disk.
    - *
    - * For v1 directories or v2 directories that contain inode numbers that
    - * do not fit into 32bit the array has eight members, but the first member
    - * is always zero:
    - *
    - *  |unused|48-55|40-47|32-39|24-31|16-23| 8-15| 0- 7|
    - *
    - * For v2 directories that only contain entries with inode numbers that fit
    - * into 32bits a four-member array is used:
    - *
    - *  |24-31|16-23| 8-15| 0- 7|
    - */ 
    -
    -#define XFS_GET_DIR_INO4(di) \
    -	(((__u32)(di).i[0] << 24) | ((di).i[1] << 16) | ((di).i[2] << 8) | ((di).i[3]))
    -
    -#define XFS_PUT_DIR_INO4(from, di) \
    -do { \
    -	(di).i[0] = (((from) & 0xff000000ULL) >> 24); \
    -	(di).i[1] = (((from) & 0x00ff0000ULL) >> 16); \
    -	(di).i[2] = (((from) & 0x0000ff00ULL) >> 8); \
    -	(di).i[3] = ((from) & 0x000000ffULL); \
    -} while (0)
    -
    -#define XFS_DI_HI(di) \
    -	(((__u32)(di).i[1] << 16) | ((di).i[2] << 8) | ((di).i[3]))
    -#define XFS_DI_LO(di) \
    -	(((__u32)(di).i[4] << 24) | ((di).i[5] << 16) | ((di).i[6] << 8) | ((di).i[7]))
    -
    -#define XFS_GET_DIR_INO8(di)        \
    -	(((xfs_ino_t)XFS_DI_LO(di) & 0xffffffffULL) | \
    -	 ((xfs_ino_t)XFS_DI_HI(di) << 32))
    -
    -#define XFS_PUT_DIR_INO8(from, di) \
    -do { \
    -	(di).i[0] = 0; \
    -	(di).i[1] = (((from) & 0x00ff000000000000ULL) >> 48); \
    -	(di).i[2] = (((from) & 0x0000ff0000000000ULL) >> 40); \
    -	(di).i[3] = (((from) & 0x000000ff00000000ULL) >> 32); \
    -	(di).i[4] = (((from) & 0x00000000ff000000ULL) >> 24); \
    -	(di).i[5] = (((from) & 0x0000000000ff0000ULL) >> 16); \
    -	(di).i[6] = (((from) & 0x000000000000ff00ULL) >> 8); \
    -	(di).i[7] = ((from) & 0x00000000000000ffULL); \
    -} while (0)
    -	
    -#endif	/* __XFS_ARCH_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_attr.c b/sys/gnu/fs/xfs/xfs_attr.c
    deleted file mode 100644
    index 3a8122ce16f..00000000000
    --- a/sys/gnu/fs/xfs/xfs_attr.c
    +++ /dev/null
    @@ -1,2646 +0,0 @@
    -/*
    - * Copyright (c) 2000-2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -
    -//#include 
    -
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_da_btree.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_alloc.h"
    -#include "xfs_btree.h"
    -#include "xfs_inode_item.h"
    -#include "xfs_bmap.h"
    -#include "xfs_attr.h"
    -#include "xfs_attr_leaf.h"
    -#include "xfs_error.h"
    -#include "xfs_quota.h"
    -#include "xfs_trans_space.h"
    -#include "xfs_acl.h"
    -#include "xfs_rw.h"
    -
    -/*
    - * xfs_attr.c
    - *
    - * Provide the external interfaces to manage attribute lists.
    - */
    -
    -#define ATTR_SYSCOUNT	2
    -STATIC struct attrnames posix_acl_access;
    -STATIC struct attrnames posix_acl_default;
    -STATIC struct attrnames *attr_system_names[ATTR_SYSCOUNT];
    -
    -/*========================================================================
    - * Function prototypes for the kernel.
    - *========================================================================*/
    -
    -/*
    - * Internal routines when attribute list fits inside the inode.
    - */
    -STATIC int xfs_attr_shortform_addname(xfs_da_args_t *args);
    -
    -/*
    - * Internal routines when attribute list is one block.
    - */
    -STATIC int xfs_attr_leaf_get(xfs_da_args_t *args);
    -STATIC int xfs_attr_leaf_addname(xfs_da_args_t *args);
    -STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args);
    -STATIC int xfs_attr_leaf_list(xfs_attr_list_context_t *context);
    -
    -/*
    - * Internal routines when attribute list is more than one block.
    - */
    -STATIC int xfs_attr_node_get(xfs_da_args_t *args);
    -STATIC int xfs_attr_node_addname(xfs_da_args_t *args);
    -STATIC int xfs_attr_node_removename(xfs_da_args_t *args);
    -STATIC int xfs_attr_node_list(xfs_attr_list_context_t *context);
    -STATIC int xfs_attr_fillstate(xfs_da_state_t *state);
    -STATIC int xfs_attr_refillstate(xfs_da_state_t *state);
    -
    -/*
    - * Routines to manipulate out-of-line attribute values.
    - */
    -STATIC int xfs_attr_rmtval_get(xfs_da_args_t *args);
    -STATIC int xfs_attr_rmtval_set(xfs_da_args_t *args);
    -STATIC int xfs_attr_rmtval_remove(xfs_da_args_t *args);
    -
    -#define ATTR_RMTVALUE_MAPSIZE	1	/* # of map entries at once */
    -
    -#if defined(XFS_ATTR_TRACE)
    -ktrace_t *xfs_attr_trace_buf;
    -#endif
    -
    -
    -/*========================================================================
    - * Overall external interface routines.
    - *========================================================================*/
    -
    -int
    -xfs_attr_fetch(xfs_inode_t *ip, const char *name, int namelen,
    -	       char *value, int *valuelenp, int flags, struct cred *cred)
    -{
    -	xfs_da_args_t   args;
    -	int             error;
    -
    -	if ((XFS_IFORK_Q(ip) == 0) ||
    -	    (ip->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
    -	     ip->i_d.di_anextents == 0))
    -		return(ENOATTR);
    -
    -	/*
    -	 * Fill in the arg structure for this request.
    -	 */
    -	memset((char *)&args, 0, sizeof(args));
    -	args.name = name;
    -	args.namelen = namelen;
    -	args.value = value;
    -	args.valuelen = *valuelenp;
    -	args.flags = flags;
    -	args.hashval = xfs_da_hashname(args.name, args.namelen);
    -	args.dp = ip;
    -	args.whichfork = XFS_ATTR_FORK;
    -
    -	/*
    -	 * Decide on what work routines to call based on the inode size.
    -	 */
    -	if (XFS_IFORK_Q(ip) == 0 ||
    -	    (ip->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
    -	     ip->i_d.di_anextents == 0)) {
    -		error = XFS_ERROR(ENOATTR);
    -	} else if (ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
    -		error = xfs_attr_shortform_getvalue(&args);
    -	} else if (xfs_bmap_one_block(ip, XFS_ATTR_FORK)) {
    -		error = xfs_attr_leaf_get(&args);
    -	} else {
    -		error = xfs_attr_node_get(&args);
    -	}
    -
    -	/*
    -	 * Return the number of bytes in the value to the caller.
    -	 */
    -	*valuelenp = args.valuelen;
    -
    -	if (error == EEXIST)
    -		error = 0;
    -	return(error);
    -}
    -
    -int
    -xfs_attr_get(bhv_desc_t *bdp, const char *name, char *value, int *valuelenp,
    -	     int flags, struct cred *cred)
    -{
    -	xfs_inode_t	*ip = XFS_BHVTOI(bdp);
    -	int		error, namelen;
    -
    -	XFS_STATS_INC(xs_attr_get);
    -
    -	if (!name)
    -		return(EINVAL);
    -	namelen = strlen(name);
    -	if (namelen >= MAXNAMELEN)
    -		return(EFAULT);		/* match IRIX behaviour */
    -
    -	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
    -		return(EIO);
    -
    -	xfs_ilock(ip, XFS_ILOCK_SHARED);
    -	error = xfs_attr_fetch(ip, name, namelen, value, valuelenp, flags, cred);
    -	xfs_iunlock(ip, XFS_ILOCK_SHARED);
    -	return(error);
    -}
    -
    -STATIC int
    -xfs_attr_set_int(xfs_inode_t *dp, const char *name, int namelen,
    -		 char *value, int valuelen, int flags)
    -{
    -	xfs_da_args_t	args;
    -	xfs_fsblock_t	firstblock;
    -	xfs_bmap_free_t flist;
    -	int		error, err2, committed;
    -	int		local, size;
    -	uint		nblks;
    -	xfs_mount_t	*mp = dp->i_mount;
    -	int             rsvd = (flags & ATTR_ROOT) != 0;
    -
    -	/*
    -	 * Attach the dquots to the inode.
    -	 */
    -	if ((error = XFS_QM_DQATTACH(mp, dp, 0)))
    -		return (error);
    -
    -	/*
    -	 * Determine space new attribute will use, and if it would be
    -	 * "local" or "remote" (note: local != inline).
    -	 */
    -	size = xfs_attr_leaf_newentsize(namelen, valuelen,
    -					mp->m_sb.sb_blocksize, &local);
    -
    -	/*
    -	 * If the inode doesn't have an attribute fork, add one.
    -	 * (inode must not be locked when we call this routine)
    -	 */
    -	if (XFS_IFORK_Q(dp) == 0) {
    -		if ((error = xfs_bmap_add_attrfork(dp, size, rsvd)))
    -			return(error);
    -	}
    -
    -	/*
    -	 * Fill in the arg structure for this request.
    -	 */
    -	memset((char *)&args, 0, sizeof(args));
    -	args.name = name;
    -	args.namelen = namelen;
    -	args.value = value;
    -	args.valuelen = valuelen;
    -	args.flags = flags;
    -	args.hashval = xfs_da_hashname(args.name, args.namelen);
    -	args.dp = dp;
    -	args.firstblock = &firstblock;
    -	args.flist = &flist;
    -	args.whichfork = XFS_ATTR_FORK;
    -	args.addname = 1;
    -	args.oknoent = 1;
    -
    -	nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
    -	if (local) {
    -		if (size > (mp->m_sb.sb_blocksize >> 1)) {
    -			/* Double split possible */
    -			nblks <<= 1;
    -		}
    -	} else {
    -		uint	dblocks = XFS_B_TO_FSB(mp, valuelen);
    -		/* Out of line attribute, cannot double split, but make
    -		 * room for the attribute value itself.
    -		 */
    -		nblks += dblocks;
    -		nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK);
    -	}
    -
    -	/* Size is now blocks for attribute data */
    -	args.total = nblks;
    -
    -	/*
    -	 * Start our first transaction of the day.
    -	 *
    -	 * All future transactions during this code must be "chained" off
    -	 * this one via the trans_dup() call.  All transactions will contain
    -	 * the inode, and the inode will always be marked with trans_ihold().
    -	 * Since the inode will be locked in all transactions, we must log
    -	 * the inode in every transaction to let it float upward through
    -	 * the log.
    -	 */
    -	args.trans = xfs_trans_alloc(mp, XFS_TRANS_ATTR_SET);
    -
    -	/*
    -	 * Root fork attributes can use reserved data blocks for this
    -	 * operation if necessary
    -	 */
    -
    -	if (rsvd)
    -		args.trans->t_flags |= XFS_TRANS_RESERVE;
    -
    -	if ((error = xfs_trans_reserve(args.trans, (uint) nblks,
    -				      XFS_ATTRSET_LOG_RES(mp, nblks),
    -				      0, XFS_TRANS_PERM_LOG_RES,
    -				      XFS_ATTRSET_LOG_COUNT))) {
    -		xfs_trans_cancel(args.trans, 0);
    -		return(error);
    -	}
    -	xfs_ilock(dp, XFS_ILOCK_EXCL);
    -
    -	error = XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, args.trans, dp, nblks, 0,
    -			 rsvd ? XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES :
    -				XFS_QMOPT_RES_REGBLKS);
    -	if (error) {
    -		xfs_iunlock(dp, XFS_ILOCK_EXCL);
    -		xfs_trans_cancel(args.trans, XFS_TRANS_RELEASE_LOG_RES);
    -		return (error);
    -	}
    -
    -	xfs_trans_ijoin(args.trans, dp, XFS_ILOCK_EXCL);
    -	xfs_trans_ihold(args.trans, dp);
    -
    -	/*
    -	 * If the attribute list is non-existent or a shortform list,
    -	 * upgrade it to a single-leaf-block attribute list.
    -	 */
    -	if ((dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) ||
    -	    ((dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS) &&
    -	     (dp->i_d.di_anextents == 0))) {
    -
    -		/*
    -		 * Build initial attribute list (if required).
    -		 */
    -		if (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS)
    -			xfs_attr_shortform_create(&args);
    -
    -		/*
    -		 * Try to add the attr to the attribute list in
    -		 * the inode.
    -		 */
    -		error = xfs_attr_shortform_addname(&args);
    -		if (error != ENOSPC) {
    -			/*
    -			 * Commit the shortform mods, and we're done.
    -			 * NOTE: this is also the error path (EEXIST, etc).
    -			 */
    -			ASSERT(args.trans != NULL);
    -
    -			/*
    -			 * If this is a synchronous mount, make sure that
    -			 * the transaction goes to disk before returning
    -			 * to the user.
    -			 */
    -			if (mp->m_flags & XFS_MOUNT_WSYNC) {
    -				xfs_trans_set_sync(args.trans);
    -			}
    -			err2 = xfs_trans_commit(args.trans,
    -						 XFS_TRANS_RELEASE_LOG_RES,
    -						 NULL);
    -			xfs_iunlock(dp, XFS_ILOCK_EXCL);
    -
    -			/*
    -			 * Hit the inode change time.
    -			 */
    -			if (!error && (flags & ATTR_KERNOTIME) == 0) {
    -				xfs_ichgtime(dp, XFS_ICHGTIME_CHG);
    -			}
    -			return(error == 0 ? err2 : error);
    -		}
    -
    -		/*
    -		 * It won't fit in the shortform, transform to a leaf block.
    -		 * GROT: another possible req'mt for a double-split btree op.
    -		 */
    -		XFS_BMAP_INIT(args.flist, args.firstblock);
    -		error = xfs_attr_shortform_to_leaf(&args);
    -		if (!error) {
    -			error = xfs_bmap_finish(&args.trans, args.flist,
    -						*args.firstblock, &committed);
    -		}
    -		if (error) {
    -			ASSERT(committed);
    -			args.trans = NULL;
    -			xfs_bmap_cancel(&flist);
    -			goto out;
    -		}
    -
    -		/*
    -		 * bmap_finish() may have committed the last trans and started
    -		 * a new one.  We need the inode to be in all transactions.
    -		 */
    -		if (committed) {
    -			xfs_trans_ijoin(args.trans, dp, XFS_ILOCK_EXCL);
    -			xfs_trans_ihold(args.trans, dp);
    -		}
    -
    -		/*
    -		 * Commit the leaf transformation.  We'll need another (linked)
    -		 * transaction to add the new attribute to the leaf.
    -		 */
    -		if ((error = xfs_attr_rolltrans(&args.trans, dp)))
    -			goto out;
    -
    -	}
    -
    -	if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
    -		error = xfs_attr_leaf_addname(&args);
    -	} else {
    -		error = xfs_attr_node_addname(&args);
    -	}
    -	if (error) {
    -		goto out;
    -	}
    -
    -	/*
    -	 * If this is a synchronous mount, make sure that the
    -	 * transaction goes to disk before returning to the user.
    -	 */
    -	if (mp->m_flags & XFS_MOUNT_WSYNC) {
    -		xfs_trans_set_sync(args.trans);
    -	}
    -
    -	/*
    -	 * Commit the last in the sequence of transactions.
    -	 */
    -	xfs_trans_log_inode(args.trans, dp, XFS_ILOG_CORE);
    -	error = xfs_trans_commit(args.trans, XFS_TRANS_RELEASE_LOG_RES,
    -				 NULL);
    -	xfs_iunlock(dp, XFS_ILOCK_EXCL);
    -
    -	/*
    -	 * Hit the inode change time.
    -	 */
    -	if (!error && (flags & ATTR_KERNOTIME) == 0) {
    -		xfs_ichgtime(dp, XFS_ICHGTIME_CHG);
    -	}
    -
    -	return(error);
    -
    -out:
    -	if (args.trans)
    -		xfs_trans_cancel(args.trans,
    -			XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
    -	xfs_iunlock(dp, XFS_ILOCK_EXCL);
    -	return(error);
    -}
    -
    -int
    -xfs_attr_set(bhv_desc_t *bdp, const char *name, char *value, int valuelen, int flags,
    -	     struct cred *cred)
    -{
    -	xfs_inode_t	*dp;
    -	int             namelen;
    -
    -	namelen = strlen(name);
    -	if (namelen >= MAXNAMELEN)
    -		return EFAULT;		/* match IRIX behaviour */
    -
    -	XFS_STATS_INC(xs_attr_set);
    -
    -	dp = XFS_BHVTOI(bdp);
    -	if (XFS_FORCED_SHUTDOWN(dp->i_mount))
    -		return (EIO);
    -
    -	return xfs_attr_set_int(dp, name, namelen, value, valuelen, flags);
    -}
    -
    -/*
    - * Generic handler routine to remove a name from an attribute list.
    - * Transitions attribute list from Btree to shortform as necessary.
    - */
    -STATIC int
    -xfs_attr_remove_int(xfs_inode_t *dp, const char *name, int namelen, int flags)
    -{
    -	xfs_da_args_t	args;
    -	xfs_fsblock_t	firstblock;
    -	xfs_bmap_free_t	flist;
    -	int		error;
    -	xfs_mount_t	*mp = dp->i_mount;
    -
    -	/*
    -	 * Fill in the arg structure for this request.
    -	 */
    -	memset((char *)&args, 0, sizeof(args));
    -	args.name = name;
    -	args.namelen = namelen;
    -	args.flags = flags;
    -	args.hashval = xfs_da_hashname(args.name, args.namelen);
    -	args.dp = dp;
    -	args.firstblock = &firstblock;
    -	args.flist = &flist;
    -	args.total = 0;
    -	args.whichfork = XFS_ATTR_FORK;
    -
    -	/*
    -	 * Attach the dquots to the inode.
    -	 */
    -	if ((error = XFS_QM_DQATTACH(mp, dp, 0)))
    -		return (error);
    -
    -	/*
    -	 * Start our first transaction of the day.
    -	 *
    -	 * All future transactions during this code must be "chained" off
    -	 * this one via the trans_dup() call.  All transactions will contain
    -	 * the inode, and the inode will always be marked with trans_ihold().
    -	 * Since the inode will be locked in all transactions, we must log
    -	 * the inode in every transaction to let it float upward through
    -	 * the log.
    -	 */
    -	args.trans = xfs_trans_alloc(mp, XFS_TRANS_ATTR_RM);
    -
    -	/*
    -	 * Root fork attributes can use reserved data blocks for this
    -	 * operation if necessary
    -	 */
    -
    -	if (flags & ATTR_ROOT)
    -		args.trans->t_flags |= XFS_TRANS_RESERVE;
    -
    -	if ((error = xfs_trans_reserve(args.trans,
    -				      XFS_ATTRRM_SPACE_RES(mp),
    -				      XFS_ATTRRM_LOG_RES(mp),
    -				      0, XFS_TRANS_PERM_LOG_RES,
    -				      XFS_ATTRRM_LOG_COUNT))) {
    -		xfs_trans_cancel(args.trans, 0);
    -		return(error);
    -	}
    -
    -	xfs_ilock(dp, XFS_ILOCK_EXCL);
    -	/*
    -	 * No need to make quota reservations here. We expect to release some
    -	 * blocks not allocate in the common case.
    -	 */
    -	xfs_trans_ijoin(args.trans, dp, XFS_ILOCK_EXCL);
    -	xfs_trans_ihold(args.trans, dp);
    -
    -	/*
    -	 * Decide on what work routines to call based on the inode size.
    -	 */
    -	if (XFS_IFORK_Q(dp) == 0 ||
    -	    (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
    -	     dp->i_d.di_anextents == 0)) {
    -		error = XFS_ERROR(ENOATTR);
    -		goto out;
    -	}
    -	if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
    -		ASSERT(dp->i_afp->if_flags & XFS_IFINLINE);
    -		error = xfs_attr_shortform_remove(&args);
    -		if (error) {
    -			goto out;
    -		}
    -	} else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
    -		error = xfs_attr_leaf_removename(&args);
    -	} else {
    -		error = xfs_attr_node_removename(&args);
    -	}
    -	if (error) {
    -		goto out;
    -	}
    -
    -	/*
    -	 * If this is a synchronous mount, make sure that the
    -	 * transaction goes to disk before returning to the user.
    -	 */
    -	if (mp->m_flags & XFS_MOUNT_WSYNC) {
    -		xfs_trans_set_sync(args.trans);
    -	}
    -
    -	/*
    -	 * Commit the last in the sequence of transactions.
    -	 */
    -	xfs_trans_log_inode(args.trans, dp, XFS_ILOG_CORE);
    -	error = xfs_trans_commit(args.trans, XFS_TRANS_RELEASE_LOG_RES,
    -				 NULL);
    -	xfs_iunlock(dp, XFS_ILOCK_EXCL);
    -
    -	/*
    -	 * Hit the inode change time.
    -	 */
    -	if (!error && (flags & ATTR_KERNOTIME) == 0) {
    -		xfs_ichgtime(dp, XFS_ICHGTIME_CHG);
    -	}
    -
    -	return(error);
    -
    -out:
    -	if (args.trans)
    -		xfs_trans_cancel(args.trans,
    -			XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
    -	xfs_iunlock(dp, XFS_ILOCK_EXCL);
    -	return(error);
    -}
    -
    -int
    -xfs_attr_remove(bhv_desc_t *bdp, const char *name, int flags, struct cred *cred)
    -{
    -	xfs_inode_t         *dp;
    -	int                 namelen;
    -
    -	namelen = strlen(name);
    -	if (namelen >= MAXNAMELEN)
    -		return EFAULT;		/* match IRIX behaviour */
    -
    -	XFS_STATS_INC(xs_attr_remove);
    -
    -	dp = XFS_BHVTOI(bdp);
    -	if (XFS_FORCED_SHUTDOWN(dp->i_mount))
    -		return (EIO);
    -
    -	xfs_ilock(dp, XFS_ILOCK_SHARED);
    -	if (XFS_IFORK_Q(dp) == 0 ||
    -		   (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
    -		    dp->i_d.di_anextents == 0)) {
    -		xfs_iunlock(dp, XFS_ILOCK_SHARED);
    -		return(XFS_ERROR(ENOATTR));
    -	}
    -	xfs_iunlock(dp, XFS_ILOCK_SHARED);
    -
    -	return xfs_attr_remove_int(dp, name, namelen, flags);
    -}
    -
    -/*
    - * Generate a list of extended attribute names and optionally
    - * also value lengths.  Positive return value follows the XFS
    - * convention of being an error, zero or negative return code
    - * is the length of the buffer returned (negated), indicating
    - * success.
    - */
    -int
    -xfs_attr_list(bhv_desc_t *bdp, char *buffer, int bufsize, int flags,
    -		      attrlist_cursor_kern_t *cursor, struct cred *cred)
    -{
    -	xfs_attr_list_context_t context;
    -	xfs_inode_t *dp;
    -	int error;
    -
    -	XFS_STATS_INC(xs_attr_list);
    -
    -	/*
    -	 * Validate the cursor.
    -	 */
    -	if (cursor->pad1 || cursor->pad2)
    -		return(XFS_ERROR(EINVAL));
    -	if ((cursor->initted == 0) &&
    -	    (cursor->hashval || cursor->blkno || cursor->offset))
    -		return(XFS_ERROR(EINVAL));
    -
    -	/*
    -	 * Check for a properly aligned buffer.
    -	 */
    -	if (((long)buffer) & (sizeof(int)-1))
    -		return(XFS_ERROR(EFAULT));
    -	if (flags & ATTR_KERNOVAL)
    -		bufsize = 0;
    -
    -	/*
    -	 * Initialize the output buffer.
    -	 */
    -	context.dp = dp = XFS_BHVTOI(bdp);
    -	context.cursor = cursor;
    -	context.count = 0;
    -	context.dupcnt = 0;
    -	context.resynch = 1;
    -	context.flags = flags;
    -	if (!(flags & ATTR_KERNAMELS)) {
    -		context.bufsize = (bufsize & ~(sizeof(int)-1));  /* align */
    -		context.firstu = context.bufsize;
    -		context.alist = (attrlist_t *)buffer;
    -		context.alist->al_count = 0;
    -		context.alist->al_more = 0;
    -		context.alist->al_offset[0] = context.bufsize;
    -	}
    -	else {
    -		context.bufsize = bufsize;
    -		context.firstu = context.bufsize;
    -		context.alist = (attrlist_t *)buffer;
    -	}
    -
    -	if (XFS_FORCED_SHUTDOWN(dp->i_mount))
    -		return (EIO);
    -
    -	xfs_ilock(dp, XFS_ILOCK_SHARED);
    -	/*
    -	 * Decide on what work routines to call based on the inode size.
    -	 */
    -	xfs_attr_trace_l_c("syscall start", &context);
    -	if (XFS_IFORK_Q(dp) == 0 ||
    -	    (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
    -	     dp->i_d.di_anextents == 0)) {
    -		error = 0;
    -	} else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
    -		error = xfs_attr_shortform_list(&context);
    -	} else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
    -		error = xfs_attr_leaf_list(&context);
    -	} else {
    -		error = xfs_attr_node_list(&context);
    -	}
    -	xfs_iunlock(dp, XFS_ILOCK_SHARED);
    -	xfs_attr_trace_l_c("syscall end", &context);
    -
    -	if (!(context.flags & (ATTR_KERNOVAL|ATTR_KERNAMELS))) {
    -		ASSERT(error >= 0);
    -	}
    -	else {	/* must return negated buffer size or the error */
    -		if (context.count < 0)
    -			error = XFS_ERROR(ERANGE);
    -		else
    -			error = -context.count;
    -	}
    -
    -	return(error);
    -}
    -
    -int								/* error */
    -xfs_attr_inactive(xfs_inode_t *dp)
    -{
    -	xfs_trans_t *trans;
    -	xfs_mount_t *mp;
    -	int error;
    -
    -	mp = dp->i_mount;
    -	ASSERT(! XFS_NOT_DQATTACHED(mp, dp));
    -
    -	xfs_ilock(dp, XFS_ILOCK_SHARED);
    -	if ((XFS_IFORK_Q(dp) == 0) ||
    -	    (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) ||
    -	    (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
    -	     dp->i_d.di_anextents == 0)) {
    -		xfs_iunlock(dp, XFS_ILOCK_SHARED);
    -		return(0);
    -	}
    -	xfs_iunlock(dp, XFS_ILOCK_SHARED);
    -
    -	/*
    -	 * Start our first transaction of the day.
    -	 *
    -	 * All future transactions during this code must be "chained" off
    -	 * this one via the trans_dup() call.  All transactions will contain
    -	 * the inode, and the inode will always be marked with trans_ihold().
    -	 * Since the inode will be locked in all transactions, we must log
    -	 * the inode in every transaction to let it float upward through
    -	 * the log.
    -	 */
    -	trans = xfs_trans_alloc(mp, XFS_TRANS_ATTRINVAL);
    -	if ((error = xfs_trans_reserve(trans, 0, XFS_ATTRINVAL_LOG_RES(mp), 0,
    -				      XFS_TRANS_PERM_LOG_RES,
    -				      XFS_ATTRINVAL_LOG_COUNT))) {
    -		xfs_trans_cancel(trans, 0);
    -		return(error);
    -	}
    -	xfs_ilock(dp, XFS_ILOCK_EXCL);
    -
    -	/*
    -	 * No need to make quota reservations here. We expect to release some
    -	 * blocks, not allocate, in the common case.
    -	 */
    -	xfs_trans_ijoin(trans, dp, XFS_ILOCK_EXCL);
    -	xfs_trans_ihold(trans, dp);
    -
    -	/*
    -	 * Decide on what work routines to call based on the inode size.
    -	 */
    -	if ((XFS_IFORK_Q(dp) == 0) ||
    -	    (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) ||
    -	    (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
    -	     dp->i_d.di_anextents == 0)) {
    -		error = 0;
    -		goto out;
    -	}
    -	error = xfs_attr_root_inactive(&trans, dp);
    -	if (error)
    -		goto out;
    -	/*
    -	 * signal synchronous inactive transactions unless this
    -	 * is a synchronous mount filesystem in which case we
    -	 * know that we're here because we've been called out of
    -	 * xfs_inactive which means that the last reference is gone
    -	 * and the unlink transaction has already hit the disk so
    -	 * async inactive transactions are safe.
    -	 */
    -	if ((error = xfs_itruncate_finish(&trans, dp, 0LL, XFS_ATTR_FORK,
    -				(!(mp->m_flags & XFS_MOUNT_WSYNC)
    -				 ? 1 : 0))))
    -		goto out;
    -
    -	/*
    -	 * Commit the last in the sequence of transactions.
    -	 */
    -	xfs_trans_log_inode(trans, dp, XFS_ILOG_CORE);
    -	error = xfs_trans_commit(trans, XFS_TRANS_RELEASE_LOG_RES,
    -				 NULL);
    -	xfs_iunlock(dp, XFS_ILOCK_EXCL);
    -
    -	return(error);
    -
    -out:
    -	xfs_trans_cancel(trans, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
    -	xfs_iunlock(dp, XFS_ILOCK_EXCL);
    -	return(error);
    -}
    -
    -
    -
    -/*========================================================================
    - * External routines when attribute list is inside the inode
    - *========================================================================*/
    -
    -/*
    - * Add a name to the shortform attribute list structure
    - * This is the external routine.
    - */
    -STATIC int
    -xfs_attr_shortform_addname(xfs_da_args_t *args)
    -{
    -	int newsize, forkoff, retval;
    -
    -	retval = xfs_attr_shortform_lookup(args);
    -	if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) {
    -		return(retval);
    -	} else if (retval == EEXIST) {
    -		if (args->flags & ATTR_CREATE)
    -			return(retval);
    -		retval = xfs_attr_shortform_remove(args);
    -		ASSERT(retval == 0);
    -	}
    -
    -	if (args->namelen >= XFS_ATTR_SF_ENTSIZE_MAX ||
    -	    args->valuelen >= XFS_ATTR_SF_ENTSIZE_MAX)
    -		return(XFS_ERROR(ENOSPC));
    -
    -	newsize = XFS_ATTR_SF_TOTSIZE(args->dp);
    -	newsize += XFS_ATTR_SF_ENTSIZE_BYNAME(args->namelen, args->valuelen);
    -
    -	forkoff = xfs_attr_shortform_bytesfit(args->dp, newsize);
    -	if (!forkoff)
    -		return(XFS_ERROR(ENOSPC));
    -
    -	xfs_attr_shortform_add(args, forkoff);
    -	return(0);
    -}
    -
    -
    -/*========================================================================
    - * External routines when attribute list is one block
    - *========================================================================*/
    -
    -/*
    - * Add a name to the leaf attribute list structure
    - *
    - * This leaf block cannot have a "remote" value, we only call this routine
    - * if bmap_one_block() says there is only one block (ie: no remote blks).
    - */
    -int
    -xfs_attr_leaf_addname(xfs_da_args_t *args)
    -{
    -	xfs_inode_t *dp;
    -	xfs_dabuf_t *bp;
    -	int retval, error, committed, forkoff;
    -
    -	/*
    -	 * Read the (only) block in the attribute list in.
    -	 */
    -	dp = args->dp;
    -	args->blkno = 0;
    -	error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1, &bp,
    -					     XFS_ATTR_FORK);
    -	if (error)
    -		return(error);
    -	ASSERT(bp != NULL);
    -
    -	/*
    -	 * Look up the given attribute in the leaf block.  Figure out if
    -	 * the given flags produce an error or call for an atomic rename.
    -	 */
    -	retval = xfs_attr_leaf_lookup_int(bp, args);
    -	if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) {
    -		xfs_da_brelse(args->trans, bp);
    -		return(retval);
    -	} else if (retval == EEXIST) {
    -		if (args->flags & ATTR_CREATE) {	/* pure create op */
    -			xfs_da_brelse(args->trans, bp);
    -			return(retval);
    -		}
    -		args->rename = 1;			/* an atomic rename */
    -		args->blkno2 = args->blkno;		/* set 2nd entry info*/
    -		args->index2 = args->index;
    -		args->rmtblkno2 = args->rmtblkno;
    -		args->rmtblkcnt2 = args->rmtblkcnt;
    -	}
    -
    -	/*
    -	 * Add the attribute to the leaf block, transitioning to a Btree
    -	 * if required.
    -	 */
    -	retval = xfs_attr_leaf_add(bp, args);
    -	xfs_da_buf_done(bp);
    -	if (retval == ENOSPC) {
    -		/*
    -		 * Promote the attribute list to the Btree format, then
    -		 * Commit that transaction so that the node_addname() call
    -		 * can manage its own transactions.
    -		 */
    -		XFS_BMAP_INIT(args->flist, args->firstblock);
    -		error = xfs_attr_leaf_to_node(args);
    -		if (!error) {
    -			error = xfs_bmap_finish(&args->trans, args->flist,
    -						*args->firstblock, &committed);
    -		}
    -		if (error) {
    -			ASSERT(committed);
    -			args->trans = NULL;
    -			xfs_bmap_cancel(args->flist);
    -			return(error);
    -		}
    -
    -		/*
    -		 * bmap_finish() may have committed the last trans and started
    -		 * a new one.  We need the inode to be in all transactions.
    -		 */
    -		if (committed) {
    -			xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL);
    -			xfs_trans_ihold(args->trans, dp);
    -		}
    -
    -		/*
    -		 * Commit the current trans (including the inode) and start
    -		 * a new one.
    -		 */
    -		if ((error = xfs_attr_rolltrans(&args->trans, dp)))
    -			return (error);
    -
    -		/*
    -		 * Fob the whole rest of the problem off on the Btree code.
    -		 */
    -		error = xfs_attr_node_addname(args);
    -		return(error);
    -	}
    -
    -	/*
    -	 * Commit the transaction that added the attr name so that
    -	 * later routines can manage their own transactions.
    -	 */
    -	if ((error = xfs_attr_rolltrans(&args->trans, dp)))
    -		return (error);
    -
    -	/*
    -	 * If there was an out-of-line value, allocate the blocks we
    -	 * identified for its storage and copy the value.  This is done
    -	 * after we create the attribute so that we don't overflow the
    -	 * maximum size of a transaction and/or hit a deadlock.
    -	 */
    -	if (args->rmtblkno > 0) {
    -		error = xfs_attr_rmtval_set(args);
    -		if (error)
    -			return(error);
    -	}
    -
    -	/*
    -	 * If this is an atomic rename operation, we must "flip" the
    -	 * incomplete flags on the "new" and "old" attribute/value pairs
    -	 * so that one disappears and one appears atomically.  Then we
    -	 * must remove the "old" attribute/value pair.
    -	 */
    -	if (args->rename) {
    -		/*
    -		 * In a separate transaction, set the incomplete flag on the
    -		 * "old" attr and clear the incomplete flag on the "new" attr.
    -		 */
    -		error = xfs_attr_leaf_flipflags(args);
    -		if (error)
    -			return(error);
    -
    -		/*
    -		 * Dismantle the "old" attribute/value pair by removing
    -		 * a "remote" value (if it exists).
    -		 */
    -		args->index = args->index2;
    -		args->blkno = args->blkno2;
    -		args->rmtblkno = args->rmtblkno2;
    -		args->rmtblkcnt = args->rmtblkcnt2;
    -		if (args->rmtblkno) {
    -			error = xfs_attr_rmtval_remove(args);
    -			if (error)
    -				return(error);
    -		}
    -
    -		/*
    -		 * Read in the block containing the "old" attr, then
    -		 * remove the "old" attr from that block (neat, huh!)
    -		 */
    -		error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1,
    -						     &bp, XFS_ATTR_FORK);
    -		if (error)
    -			return(error);
    -		ASSERT(bp != NULL);
    -		(void)xfs_attr_leaf_remove(bp, args);
    -
    -		/*
    -		 * If the result is small enough, shrink it all into the inode.
    -		 */
    -		if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
    -			XFS_BMAP_INIT(args->flist, args->firstblock);
    -			error = xfs_attr_leaf_to_shortform(bp, args, forkoff);
    -			/* bp is gone due to xfs_da_shrink_inode */
    -			if (!error) {
    -				error = xfs_bmap_finish(&args->trans,
    -							args->flist,
    -							*args->firstblock,
    -							&committed);
    -			}
    -			if (error) {
    -				ASSERT(committed);
    -				args->trans = NULL;
    -				xfs_bmap_cancel(args->flist);
    -				return(error);
    -			}
    -
    -			/*
    -			 * bmap_finish() may have committed the last trans
    -			 * and started a new one.  We need the inode to be
    -			 * in all transactions.
    -			 */
    -			if (committed) {
    -				xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL);
    -				xfs_trans_ihold(args->trans, dp);
    -			}
    -		} else
    -			xfs_da_buf_done(bp);
    -
    -		/*
    -		 * Commit the remove and start the next trans in series.
    -		 */
    -		error = xfs_attr_rolltrans(&args->trans, dp);
    -
    -	} else if (args->rmtblkno > 0) {
    -		/*
    -		 * Added a "remote" value, just clear the incomplete flag.
    -		 */
    -		error = xfs_attr_leaf_clearflag(args);
    -	}
    -	return(error);
    -}
    -
    -/*
    - * Remove a name from the leaf attribute list structure
    - *
    - * This leaf block cannot have a "remote" value, we only call this routine
    - * if bmap_one_block() says there is only one block (ie: no remote blks).
    - */
    -STATIC int
    -xfs_attr_leaf_removename(xfs_da_args_t *args)
    -{
    -	xfs_inode_t *dp;
    -	xfs_dabuf_t *bp;
    -	int error, committed, forkoff;
    -
    -	/*
    -	 * Remove the attribute.
    -	 */
    -	dp = args->dp;
    -	args->blkno = 0;
    -	error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1, &bp,
    -					     XFS_ATTR_FORK);
    -	if (error) {
    -		return(error);
    -	}
    -
    -	ASSERT(bp != NULL);
    -	error = xfs_attr_leaf_lookup_int(bp, args);
    -	if (error == ENOATTR) {
    -		xfs_da_brelse(args->trans, bp);
    -		return(error);
    -	}
    -
    -	(void)xfs_attr_leaf_remove(bp, args);
    -
    -	/*
    -	 * If the result is small enough, shrink it all into the inode.
    -	 */
    -	if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
    -		XFS_BMAP_INIT(args->flist, args->firstblock);
    -		error = xfs_attr_leaf_to_shortform(bp, args, forkoff);
    -		/* bp is gone due to xfs_da_shrink_inode */
    -		if (!error) {
    -			error = xfs_bmap_finish(&args->trans, args->flist,
    -						*args->firstblock, &committed);
    -		}
    -		if (error) {
    -			ASSERT(committed);
    -			args->trans = NULL;
    -			xfs_bmap_cancel(args->flist);
    -			return(error);
    -		}
    -
    -		/*
    -		 * bmap_finish() may have committed the last trans and started
    -		 * a new one.  We need the inode to be in all transactions.
    -		 */
    -		if (committed) {
    -			xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL);
    -			xfs_trans_ihold(args->trans, dp);
    -		}
    -	} else
    -		xfs_da_buf_done(bp);
    -	return(0);
    -}
    -
    -/*
    - * Look up a name in a leaf attribute list structure.
    - *
    - * This leaf block cannot have a "remote" value, we only call this routine
    - * if bmap_one_block() says there is only one block (ie: no remote blks).
    - */
    -STATIC int
    -xfs_attr_leaf_get(xfs_da_args_t *args)
    -{
    -	xfs_dabuf_t *bp;
    -	int error;
    -
    -	args->blkno = 0;
    -	error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1, &bp,
    -					     XFS_ATTR_FORK);
    -	if (error)
    -		return(error);
    -	ASSERT(bp != NULL);
    -
    -	error = xfs_attr_leaf_lookup_int(bp, args);
    -	if (error != EEXIST)  {
    -		xfs_da_brelse(args->trans, bp);
    -		return(error);
    -	}
    -	error = xfs_attr_leaf_getvalue(bp, args);
    -	xfs_da_brelse(args->trans, bp);
    -	if (!error && (args->rmtblkno > 0) && !(args->flags & ATTR_KERNOVAL)) {
    -		error = xfs_attr_rmtval_get(args);
    -	}
    -	return(error);
    -}
    -
    -/*
    - * Copy out attribute entries for attr_list(), for leaf attribute lists.
    - */
    -STATIC int
    -xfs_attr_leaf_list(xfs_attr_list_context_t *context)
    -{
    -	xfs_attr_leafblock_t *leaf;
    -	int error;
    -	xfs_dabuf_t *bp;
    -
    -	context->cursor->blkno = 0;
    -	error = xfs_da_read_buf(NULL, context->dp, 0, -1, &bp, XFS_ATTR_FORK);
    -	if (error)
    -		return(error);
    -	ASSERT(bp != NULL);
    -	leaf = bp->data;
    -	if (unlikely(be16_to_cpu(leaf->hdr.info.magic) != XFS_ATTR_LEAF_MAGIC)) {
    -		XFS_CORRUPTION_ERROR("xfs_attr_leaf_list", XFS_ERRLEVEL_LOW,
    -				     context->dp->i_mount, leaf);
    -		xfs_da_brelse(NULL, bp);
    -		return(XFS_ERROR(EFSCORRUPTED));
    -	}
    -
    -	(void)xfs_attr_leaf_list_int(bp, context);
    -	xfs_da_brelse(NULL, bp);
    -	return(0);
    -}
    -
    -
    -/*========================================================================
    - * External routines when attribute list size > XFS_LBSIZE(mp).
    - *========================================================================*/
    -
    -/*
    - * Add a name to a Btree-format attribute list.
    - *
    - * This will involve walking down the Btree, and may involve splitting
    - * leaf nodes and even splitting intermediate nodes up to and including
    - * the root node (a special case of an intermediate node).
    - *
    - * "Remote" attribute values confuse the issue and atomic rename operations
    - * add a whole extra layer of confusion on top of that.
    - */
    -STATIC int
    -xfs_attr_node_addname(xfs_da_args_t *args)
    -{
    -	xfs_da_state_t *state;
    -	xfs_da_state_blk_t *blk;
    -	xfs_inode_t *dp;
    -	xfs_mount_t *mp;
    -	int committed, retval, error;
    -
    -	/*
    -	 * Fill in bucket of arguments/results/context to carry around.
    -	 */
    -	dp = args->dp;
    -	mp = dp->i_mount;
    -restart:
    -	state = xfs_da_state_alloc();
    -	state->args = args;
    -	state->mp = mp;
    -	state->blocksize = state->mp->m_sb.sb_blocksize;
    -	state->node_ents = state->mp->m_attr_node_ents;
    -
    -	/*
    -	 * Search to see if name already exists, and get back a pointer
    -	 * to where it should go.
    -	 */
    -	error = xfs_da_node_lookup_int(state, &retval);
    -	if (error)
    -		goto out;
    -	blk = &state->path.blk[ state->path.active-1 ];
    -	ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
    -	if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) {
    -		goto out;
    -	} else if (retval == EEXIST) {
    -		if (args->flags & ATTR_CREATE)
    -			goto out;
    -		args->rename = 1;			/* atomic rename op */
    -		args->blkno2 = args->blkno;		/* set 2nd entry info*/
    -		args->index2 = args->index;
    -		args->rmtblkno2 = args->rmtblkno;
    -		args->rmtblkcnt2 = args->rmtblkcnt;
    -		args->rmtblkno = 0;
    -		args->rmtblkcnt = 0;
    -	}
    -
    -	retval = xfs_attr_leaf_add(blk->bp, state->args);
    -	if (retval == ENOSPC) {
    -		if (state->path.active == 1) {
    -			/*
    -			 * Its really a single leaf node, but it had
    -			 * out-of-line values so it looked like it *might*
    -			 * have been a b-tree.
    -			 */
    -			xfs_da_state_free(state);
    -			XFS_BMAP_INIT(args->flist, args->firstblock);
    -			error = xfs_attr_leaf_to_node(args);
    -			if (!error) {
    -				error = xfs_bmap_finish(&args->trans,
    -							args->flist,
    -							*args->firstblock,
    -							&committed);
    -			}
    -			if (error) {
    -				ASSERT(committed);
    -				args->trans = NULL;
    -				xfs_bmap_cancel(args->flist);
    -				goto out;
    -			}
    -
    -			/*
    -			 * bmap_finish() may have committed the last trans
    -			 * and started a new one.  We need the inode to be
    -			 * in all transactions.
    -			 */
    -			if (committed) {
    -				xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL);
    -				xfs_trans_ihold(args->trans, dp);
    -			}
    -
    -			/*
    -			 * Commit the node conversion and start the next
    -			 * trans in the chain.
    -			 */
    -			if ((error = xfs_attr_rolltrans(&args->trans, dp)))
    -				goto out;
    -
    -			goto restart;
    -		}
    -
    -		/*
    -		 * Split as many Btree elements as required.
    -		 * This code tracks the new and old attr's location
    -		 * in the index/blkno/rmtblkno/rmtblkcnt fields and
    -		 * in the index2/blkno2/rmtblkno2/rmtblkcnt2 fields.
    -		 */
    -		XFS_BMAP_INIT(args->flist, args->firstblock);
    -		error = xfs_da_split(state);
    -		if (!error) {
    -			error = xfs_bmap_finish(&args->trans, args->flist,
    -						*args->firstblock, &committed);
    -		}
    -		if (error) {
    -			ASSERT(committed);
    -			args->trans = NULL;
    -			xfs_bmap_cancel(args->flist);
    -			goto out;
    -		}
    -
    -		/*
    -		 * bmap_finish() may have committed the last trans and started
    -		 * a new one.  We need the inode to be in all transactions.
    -		 */
    -		if (committed) {
    -			xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL);
    -			xfs_trans_ihold(args->trans, dp);
    -		}
    -	} else {
    -		/*
    -		 * Addition succeeded, update Btree hashvals.
    -		 */
    -		xfs_da_fixhashpath(state, &state->path);
    -	}
    -
    -	/*
    -	 * Kill the state structure, we're done with it and need to
    -	 * allow the buffers to come back later.
    -	 */
    -	xfs_da_state_free(state);
    -	state = NULL;
    -
    -	/*
    -	 * Commit the leaf addition or btree split and start the next
    -	 * trans in the chain.
    -	 */
    -	if ((error = xfs_attr_rolltrans(&args->trans, dp)))
    -		goto out;
    -
    -	/*
    -	 * If there was an out-of-line value, allocate the blocks we
    -	 * identified for its storage and copy the value.  This is done
    -	 * after we create the attribute so that we don't overflow the
    -	 * maximum size of a transaction and/or hit a deadlock.
    -	 */
    -	if (args->rmtblkno > 0) {
    -		error = xfs_attr_rmtval_set(args);
    -		if (error)
    -			return(error);
    -	}
    -
    -	/*
    -	 * If this is an atomic rename operation, we must "flip" the
    -	 * incomplete flags on the "new" and "old" attribute/value pairs
    -	 * so that one disappears and one appears atomically.  Then we
    -	 * must remove the "old" attribute/value pair.
    -	 */
    -	if (args->rename) {
    -		/*
    -		 * In a separate transaction, set the incomplete flag on the
    -		 * "old" attr and clear the incomplete flag on the "new" attr.
    -		 */
    -		error = xfs_attr_leaf_flipflags(args);
    -		if (error)
    -			goto out;
    -
    -		/*
    -		 * Dismantle the "old" attribute/value pair by removing
    -		 * a "remote" value (if it exists).
    -		 */
    -		args->index = args->index2;
    -		args->blkno = args->blkno2;
    -		args->rmtblkno = args->rmtblkno2;
    -		args->rmtblkcnt = args->rmtblkcnt2;
    -		if (args->rmtblkno) {
    -			error = xfs_attr_rmtval_remove(args);
    -			if (error)
    -				return(error);
    -		}
    -
    -		/*
    -		 * Re-find the "old" attribute entry after any split ops.
    -		 * The INCOMPLETE flag means that we will find the "old"
    -		 * attr, not the "new" one.
    -		 */
    -		args->flags |= XFS_ATTR_INCOMPLETE;
    -		state = xfs_da_state_alloc();
    -		state->args = args;
    -		state->mp = mp;
    -		state->blocksize = state->mp->m_sb.sb_blocksize;
    -		state->node_ents = state->mp->m_attr_node_ents;
    -		state->inleaf = 0;
    -		error = xfs_da_node_lookup_int(state, &retval);
    -		if (error)
    -			goto out;
    -
    -		/*
    -		 * Remove the name and update the hashvals in the tree.
    -		 */
    -		blk = &state->path.blk[ state->path.active-1 ];
    -		ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
    -		error = xfs_attr_leaf_remove(blk->bp, args);
    -		xfs_da_fixhashpath(state, &state->path);
    -
    -		/*
    -		 * Check to see if the tree needs to be collapsed.
    -		 */
    -		if (retval && (state->path.active > 1)) {
    -			XFS_BMAP_INIT(args->flist, args->firstblock);
    -			error = xfs_da_join(state);
    -			if (!error) {
    -				error = xfs_bmap_finish(&args->trans,
    -							args->flist,
    -							*args->firstblock,
    -							&committed);
    -			}
    -			if (error) {
    -				ASSERT(committed);
    -				args->trans = NULL;
    -				xfs_bmap_cancel(args->flist);
    -				goto out;
    -			}
    -
    -			/*
    -			 * bmap_finish() may have committed the last trans
    -			 * and started a new one.  We need the inode to be
    -			 * in all transactions.
    -			 */
    -			if (committed) {
    -				xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL);
    -				xfs_trans_ihold(args->trans, dp);
    -			}
    -		}
    -
    -		/*
    -		 * Commit and start the next trans in the chain.
    -		 */
    -		if ((error = xfs_attr_rolltrans(&args->trans, dp)))
    -			goto out;
    -
    -	} else if (args->rmtblkno > 0) {
    -		/*
    -		 * Added a "remote" value, just clear the incomplete flag.
    -		 */
    -		error = xfs_attr_leaf_clearflag(args);
    -		if (error)
    -			goto out;
    -	}
    -	retval = error = 0;
    -
    -out:
    -	if (state)
    -		xfs_da_state_free(state);
    -	if (error)
    -		return(error);
    -	return(retval);
    -}
    -
    -/*
    - * Remove a name from a B-tree attribute list.
    - *
    - * This will involve walking down the Btree, and may involve joining
    - * leaf nodes and even joining intermediate nodes up to and including
    - * the root node (a special case of an intermediate node).
    - */
    -STATIC int
    -xfs_attr_node_removename(xfs_da_args_t *args)
    -{
    -	xfs_da_state_t *state;
    -	xfs_da_state_blk_t *blk;
    -	xfs_inode_t *dp;
    -	xfs_dabuf_t *bp;
    -	int retval, error, committed, forkoff;
    -
    -	/*
    -	 * Tie a string around our finger to remind us where we are.
    -	 */
    -	dp = args->dp;
    -	state = xfs_da_state_alloc();
    -	state->args = args;
    -	state->mp = dp->i_mount;
    -	state->blocksize = state->mp->m_sb.sb_blocksize;
    -	state->node_ents = state->mp->m_attr_node_ents;
    -
    -	/*
    -	 * Search to see if name exists, and get back a pointer to it.
    -	 */
    -	error = xfs_da_node_lookup_int(state, &retval);
    -	if (error || (retval != EEXIST)) {
    -		if (error == 0)
    -			error = retval;
    -		goto out;
    -	}
    -
    -	/*
    -	 * If there is an out-of-line value, de-allocate the blocks.
    -	 * This is done before we remove the attribute so that we don't
    -	 * overflow the maximum size of a transaction and/or hit a deadlock.
    -	 */
    -	blk = &state->path.blk[ state->path.active-1 ];
    -	ASSERT(blk->bp != NULL);
    -	ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
    -	if (args->rmtblkno > 0) {
    -		/*
    -		 * Fill in disk block numbers in the state structure
    -		 * so that we can get the buffers back after we commit
    -		 * several transactions in the following calls.
    -		 */
    -		error = xfs_attr_fillstate(state);
    -		if (error)
    -			goto out;
    -
    -		/*
    -		 * Mark the attribute as INCOMPLETE, then bunmapi() the
    -		 * remote value.
    -		 */
    -		error = xfs_attr_leaf_setflag(args);
    -		if (error)
    -			goto out;
    -		error = xfs_attr_rmtval_remove(args);
    -		if (error)
    -			goto out;
    -
    -		/*
    -		 * Refill the state structure with buffers, the prior calls
    -		 * released our buffers.
    -		 */
    -		error = xfs_attr_refillstate(state);
    -		if (error)
    -			goto out;
    -	}
    -
    -	/*
    -	 * Remove the name and update the hashvals in the tree.
    -	 */
    -	blk = &state->path.blk[ state->path.active-1 ];
    -	ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
    -	retval = xfs_attr_leaf_remove(blk->bp, args);
    -	xfs_da_fixhashpath(state, &state->path);
    -
    -	/*
    -	 * Check to see if the tree needs to be collapsed.
    -	 */
    -	if (retval && (state->path.active > 1)) {
    -		XFS_BMAP_INIT(args->flist, args->firstblock);
    -		error = xfs_da_join(state);
    -		if (!error) {
    -			error = xfs_bmap_finish(&args->trans, args->flist,
    -						*args->firstblock, &committed);
    -		}
    -		if (error) {
    -			ASSERT(committed);
    -			args->trans = NULL;
    -			xfs_bmap_cancel(args->flist);
    -			goto out;
    -		}
    -
    -		/*
    -		 * bmap_finish() may have committed the last trans and started
    -		 * a new one.  We need the inode to be in all transactions.
    -		 */
    -		if (committed) {
    -			xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL);
    -			xfs_trans_ihold(args->trans, dp);
    -		}
    -
    -		/*
    -		 * Commit the Btree join operation and start a new trans.
    -		 */
    -		if ((error = xfs_attr_rolltrans(&args->trans, dp)))
    -			goto out;
    -	}
    -
    -	/*
    -	 * If the result is small enough, push it all into the inode.
    -	 */
    -	if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
    -		/*
    -		 * Have to get rid of the copy of this dabuf in the state.
    -		 */
    -		ASSERT(state->path.active == 1);
    -		ASSERT(state->path.blk[0].bp);
    -		xfs_da_buf_done(state->path.blk[0].bp);
    -		state->path.blk[0].bp = NULL;
    -
    -		error = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp,
    -						     XFS_ATTR_FORK);
    -		if (error)
    -			goto out;
    -		ASSERT(be16_to_cpu(((xfs_attr_leafblock_t *)
    -				      bp->data)->hdr.info.magic)
    -						       == XFS_ATTR_LEAF_MAGIC);
    -
    -		if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
    -			XFS_BMAP_INIT(args->flist, args->firstblock);
    -			error = xfs_attr_leaf_to_shortform(bp, args, forkoff);
    -			/* bp is gone due to xfs_da_shrink_inode */
    -			if (!error) {
    -				error = xfs_bmap_finish(&args->trans,
    -							args->flist,
    -							*args->firstblock,
    -							&committed);
    -			}
    -			if (error) {
    -				ASSERT(committed);
    -				args->trans = NULL;
    -				xfs_bmap_cancel(args->flist);
    -				goto out;
    -			}
    -
    -			/*
    -			 * bmap_finish() may have committed the last trans
    -			 * and started a new one.  We need the inode to be
    -			 * in all transactions.
    -			 */
    -			if (committed) {
    -				xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL);
    -				xfs_trans_ihold(args->trans, dp);
    -			}
    -		} else
    -			xfs_da_brelse(args->trans, bp);
    -	}
    -	error = 0;
    -
    -out:
    -	xfs_da_state_free(state);
    -	return(error);
    -}
    -
    -/*
    - * Fill in the disk block numbers in the state structure for the buffers
    - * that are attached to the state structure.
    - * This is done so that we can quickly reattach ourselves to those buffers
    - * after some set of transaction commits have released these buffers.
    - */
    -STATIC int
    -xfs_attr_fillstate(xfs_da_state_t *state)
    -{
    -	xfs_da_state_path_t *path;
    -	xfs_da_state_blk_t *blk;
    -	int level;
    -
    -	/*
    -	 * Roll down the "path" in the state structure, storing the on-disk
    -	 * block number for those buffers in the "path".
    -	 */
    -	path = &state->path;
    -	ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
    -	for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
    -		if (blk->bp) {
    -			blk->disk_blkno = xfs_da_blkno(blk->bp);
    -			xfs_da_buf_done(blk->bp);
    -			blk->bp = NULL;
    -		} else {
    -			blk->disk_blkno = 0;
    -		}
    -	}
    -
    -	/*
    -	 * Roll down the "altpath" in the state structure, storing the on-disk
    -	 * block number for those buffers in the "altpath".
    -	 */
    -	path = &state->altpath;
    -	ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
    -	for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
    -		if (blk->bp) {
    -			blk->disk_blkno = xfs_da_blkno(blk->bp);
    -			xfs_da_buf_done(blk->bp);
    -			blk->bp = NULL;
    -		} else {
    -			blk->disk_blkno = 0;
    -		}
    -	}
    -
    -	return(0);
    -}
    -
    -/*
    - * Reattach the buffers to the state structure based on the disk block
    - * numbers stored in the state structure.
    - * This is done after some set of transaction commits have released those
    - * buffers from our grip.
    - */
    -STATIC int
    -xfs_attr_refillstate(xfs_da_state_t *state)
    -{
    -	xfs_da_state_path_t *path;
    -	xfs_da_state_blk_t *blk;
    -	int level, error;
    -
    -	/*
    -	 * Roll down the "path" in the state structure, storing the on-disk
    -	 * block number for those buffers in the "path".
    -	 */
    -	path = &state->path;
    -	ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
    -	for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
    -		if (blk->disk_blkno) {
    -			error = xfs_da_read_buf(state->args->trans,
    -						state->args->dp,
    -						blk->blkno, blk->disk_blkno,
    -						&blk->bp, XFS_ATTR_FORK);
    -			if (error)
    -				return(error);
    -		} else {
    -			blk->bp = NULL;
    -		}
    -	}
    -
    -	/*
    -	 * Roll down the "altpath" in the state structure, storing the on-disk
    -	 * block number for those buffers in the "altpath".
    -	 */
    -	path = &state->altpath;
    -	ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
    -	for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
    -		if (blk->disk_blkno) {
    -			error = xfs_da_read_buf(state->args->trans,
    -						state->args->dp,
    -						blk->blkno, blk->disk_blkno,
    -						&blk->bp, XFS_ATTR_FORK);
    -			if (error)
    -				return(error);
    -		} else {
    -			blk->bp = NULL;
    -		}
    -	}
    -
    -	return(0);
    -}
    -
    -/*
    - * Look up a filename in a node attribute list.
    - *
    - * This routine gets called for any attribute fork that has more than one
    - * block, ie: both true Btree attr lists and for single-leaf-blocks with
    - * "remote" values taking up more blocks.
    - */
    -STATIC int
    -xfs_attr_node_get(xfs_da_args_t *args)
    -{
    -	xfs_da_state_t *state;
    -	xfs_da_state_blk_t *blk;
    -	int error, retval;
    -	int i;
    -
    -	state = xfs_da_state_alloc();
    -	state->args = args;
    -	state->mp = args->dp->i_mount;
    -	state->blocksize = state->mp->m_sb.sb_blocksize;
    -	state->node_ents = state->mp->m_attr_node_ents;
    -
    -	/*
    -	 * Search to see if name exists, and get back a pointer to it.
    -	 */
    -	error = xfs_da_node_lookup_int(state, &retval);
    -	if (error) {
    -		retval = error;
    -	} else if (retval == EEXIST) {
    -		blk = &state->path.blk[ state->path.active-1 ];
    -		ASSERT(blk->bp != NULL);
    -		ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
    -
    -		/*
    -		 * Get the value, local or "remote"
    -		 */
    -		retval = xfs_attr_leaf_getvalue(blk->bp, args);
    -		if (!retval && (args->rmtblkno > 0)
    -		    && !(args->flags & ATTR_KERNOVAL)) {
    -			retval = xfs_attr_rmtval_get(args);
    -		}
    -	}
    -
    -	/*
    -	 * If not in a transaction, we have to release all the buffers.
    -	 */
    -	for (i = 0; i < state->path.active; i++) {
    -		xfs_da_brelse(args->trans, state->path.blk[i].bp);
    -		state->path.blk[i].bp = NULL;
    -	}
    -
    -	xfs_da_state_free(state);
    -	return(retval);
    -}
    -
    -STATIC int							/* error */
    -xfs_attr_node_list(xfs_attr_list_context_t *context)
    -{
    -	attrlist_cursor_kern_t *cursor;
    -	xfs_attr_leafblock_t *leaf;
    -	xfs_da_intnode_t *node;
    -	xfs_da_node_entry_t *btree;
    -	int error, i;
    -	xfs_dabuf_t *bp;
    -
    -	cursor = context->cursor;
    -	cursor->initted = 1;
    -
    -	/*
    -	 * Do all sorts of validation on the passed-in cursor structure.
    -	 * If anything is amiss, ignore the cursor and look up the hashval
    -	 * starting from the btree root.
    -	 */
    -	bp = NULL;
    -	if (cursor->blkno > 0) {
    -		error = xfs_da_read_buf(NULL, context->dp, cursor->blkno, -1,
    -					      &bp, XFS_ATTR_FORK);
    -		if ((error != 0) && (error != EFSCORRUPTED))
    -			return(error);
    -		if (bp) {
    -			node = bp->data;
    -			switch (be16_to_cpu(node->hdr.info.magic)) {
    -			case XFS_DA_NODE_MAGIC:
    -				xfs_attr_trace_l_cn("wrong blk", context, node);
    -				xfs_da_brelse(NULL, bp);
    -				bp = NULL;
    -				break;
    -			case XFS_ATTR_LEAF_MAGIC:
    -				leaf = bp->data;
    -				if (cursor->hashval > be32_to_cpu(leaf->entries[
    -				    be16_to_cpu(leaf->hdr.count)-1].hashval)) {
    -					xfs_attr_trace_l_cl("wrong blk",
    -							   context, leaf);
    -					xfs_da_brelse(NULL, bp);
    -					bp = NULL;
    -				} else if (cursor->hashval <=
    -					     be32_to_cpu(leaf->entries[0].hashval)) {
    -					xfs_attr_trace_l_cl("maybe wrong blk",
    -							   context, leaf);
    -					xfs_da_brelse(NULL, bp);
    -					bp = NULL;
    -				}
    -				break;
    -			default:
    -				xfs_attr_trace_l_c("wrong blk - ??", context);
    -				xfs_da_brelse(NULL, bp);
    -				bp = NULL;
    -			}
    -		}
    -	}
    -
    -	/*
    -	 * We did not find what we expected given the cursor's contents,
    -	 * so we start from the top and work down based on the hash value.
    -	 * Note that start of node block is same as start of leaf block.
    -	 */
    -	if (bp == NULL) {
    -		cursor->blkno = 0;
    -		for (;;) {
    -			error = xfs_da_read_buf(NULL, context->dp,
    -						      cursor->blkno, -1, &bp,
    -						      XFS_ATTR_FORK);
    -			if (error)
    -				return(error);
    -			if (unlikely(bp == NULL)) {
    -				XFS_ERROR_REPORT("xfs_attr_node_list(2)",
    -						 XFS_ERRLEVEL_LOW,
    -						 context->dp->i_mount);
    -				return(XFS_ERROR(EFSCORRUPTED));
    -			}
    -			node = bp->data;
    -			if (be16_to_cpu(node->hdr.info.magic)
    -							== XFS_ATTR_LEAF_MAGIC)
    -				break;
    -			if (unlikely(be16_to_cpu(node->hdr.info.magic)
    -							!= XFS_DA_NODE_MAGIC)) {
    -				XFS_CORRUPTION_ERROR("xfs_attr_node_list(3)",
    -						     XFS_ERRLEVEL_LOW,
    -						     context->dp->i_mount,
    -						     node);
    -				xfs_da_brelse(NULL, bp);
    -				return(XFS_ERROR(EFSCORRUPTED));
    -			}
    -			btree = node->btree;
    -			for (i = 0; i < be16_to_cpu(node->hdr.count);
    -								btree++, i++) {
    -				if (cursor->hashval
    -						<= be32_to_cpu(btree->hashval)) {
    -					cursor->blkno = be32_to_cpu(btree->before);
    -					xfs_attr_trace_l_cb("descending",
    -							    context, btree);
    -					break;
    -				}
    -			}
    -			if (i == be16_to_cpu(node->hdr.count)) {
    -				xfs_da_brelse(NULL, bp);
    -				return(0);
    -			}
    -			xfs_da_brelse(NULL, bp);
    -		}
    -	}
    -	ASSERT(bp != NULL);
    -
    -	/*
    -	 * Roll upward through the blocks, processing each leaf block in
    -	 * order.  As long as there is space in the result buffer, keep
    -	 * adding the information.
    -	 */
    -	for (;;) {
    -		leaf = bp->data;
    -		if (unlikely(be16_to_cpu(leaf->hdr.info.magic)
    -						!= XFS_ATTR_LEAF_MAGIC)) {
    -			XFS_CORRUPTION_ERROR("xfs_attr_node_list(4)",
    -					     XFS_ERRLEVEL_LOW,
    -					     context->dp->i_mount, leaf);
    -			xfs_da_brelse(NULL, bp);
    -			return(XFS_ERROR(EFSCORRUPTED));
    -		}
    -		error = xfs_attr_leaf_list_int(bp, context);
    -		if (error || !leaf->hdr.info.forw)
    -			break;	/* not really an error, buffer full or EOF */
    -		cursor->blkno = be32_to_cpu(leaf->hdr.info.forw);
    -		xfs_da_brelse(NULL, bp);
    -		error = xfs_da_read_buf(NULL, context->dp, cursor->blkno, -1,
    -					      &bp, XFS_ATTR_FORK);
    -		if (error)
    -			return(error);
    -		if (unlikely((bp == NULL))) {
    -			XFS_ERROR_REPORT("xfs_attr_node_list(5)",
    -					 XFS_ERRLEVEL_LOW,
    -					 context->dp->i_mount);
    -			return(XFS_ERROR(EFSCORRUPTED));
    -		}
    -	}
    -	xfs_da_brelse(NULL, bp);
    -	return(0);
    -}
    -
    -
    -/*========================================================================
    - * External routines for manipulating out-of-line attribute values.
    - *========================================================================*/
    -
    -/*
    - * Read the value associated with an attribute from the out-of-line buffer
    - * that we stored it in.
    - */
    -STATIC int
    -xfs_attr_rmtval_get(xfs_da_args_t *args)
    -{
    -	xfs_bmbt_irec_t map[ATTR_RMTVALUE_MAPSIZE];
    -	xfs_mount_t *mp;
    -	xfs_daddr_t dblkno;
    -	xfs_caddr_t dst;
    -	xfs_buf_t *bp;
    -	int nmap, error, tmp, valuelen, blkcnt, i;
    -	xfs_dablk_t lblkno;
    -
    -	ASSERT(!(args->flags & ATTR_KERNOVAL));
    -
    -	mp = args->dp->i_mount;
    -	dst = args->value;
    -	valuelen = args->valuelen;
    -	lblkno = args->rmtblkno;
    -	while (valuelen > 0) {
    -		nmap = ATTR_RMTVALUE_MAPSIZE;
    -		error = xfs_bmapi(args->trans, args->dp, (xfs_fileoff_t)lblkno,
    -				  args->rmtblkcnt,
    -				  XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
    -				  NULL, 0, map, &nmap, NULL, NULL);
    -		if (error)
    -			return(error);
    -		ASSERT(nmap >= 1);
    -
    -		for (i = 0; (i < nmap) && (valuelen > 0); i++) {
    -			ASSERT((map[i].br_startblock != DELAYSTARTBLOCK) &&
    -			       (map[i].br_startblock != HOLESTARTBLOCK));
    -			dblkno = XFS_FSB_TO_DADDR(mp, map[i].br_startblock);
    -			blkcnt = XFS_FSB_TO_BB(mp, map[i].br_blockcount);
    -			error = xfs_read_buf(mp, mp->m_ddev_targp, dblkno,
    -					     blkcnt, XFS_BUF_LOCK, &bp);
    -			if (error)
    -				return(error);
    -
    -			tmp = (valuelen < XFS_BUF_SIZE(bp))
    -				? valuelen : XFS_BUF_SIZE(bp);
    -			xfs_biomove(bp, 0, tmp, dst, XFS_B_READ);
    -			xfs_buf_relse(bp);
    -			dst += tmp;
    -			valuelen -= tmp;
    -
    -			lblkno += map[i].br_blockcount;
    -		}
    -	}
    -	ASSERT(valuelen == 0);
    -	return(0);
    -}
    -
    -/*
    - * Write the value associated with an attribute into the out-of-line buffer
    - * that we have defined for it.
    - */
    -STATIC int
    -xfs_attr_rmtval_set(xfs_da_args_t *args)
    -{
    -	xfs_mount_t *mp;
    -	xfs_fileoff_t lfileoff;
    -	xfs_inode_t *dp;
    -	xfs_bmbt_irec_t map;
    -	xfs_daddr_t dblkno;
    -	xfs_caddr_t src;
    -	xfs_buf_t *bp;
    -	xfs_dablk_t lblkno;
    -	int blkcnt, valuelen, nmap, error, tmp, committed;
    -
    -	dp = args->dp;
    -	mp = dp->i_mount;
    -	src = args->value;
    -
    -	/*
    -	 * Find a "hole" in the attribute address space large enough for
    -	 * us to drop the new attribute's value into.
    -	 */
    -	blkcnt = XFS_B_TO_FSB(mp, args->valuelen);
    -	lfileoff = 0;
    -	error = xfs_bmap_first_unused(args->trans, args->dp, blkcnt, &lfileoff,
    -						   XFS_ATTR_FORK);
    -	if (error) {
    -		return(error);
    -	}
    -	args->rmtblkno = lblkno = (xfs_dablk_t)lfileoff;
    -	args->rmtblkcnt = blkcnt;
    -
    -	/*
    -	 * Roll through the "value", allocating blocks on disk as required.
    -	 */
    -	while (blkcnt > 0) {
    -		/*
    -		 * Allocate a single extent, up to the size of the value.
    -		 */
    -		XFS_BMAP_INIT(args->flist, args->firstblock);
    -		nmap = 1;
    -		error = xfs_bmapi(args->trans, dp, (xfs_fileoff_t)lblkno,
    -				  blkcnt,
    -				  XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA |
    -							XFS_BMAPI_WRITE,
    -				  args->firstblock, args->total, &map, &nmap,
    -				  args->flist, NULL);
    -		if (!error) {
    -			error = xfs_bmap_finish(&args->trans, args->flist,
    -						*args->firstblock, &committed);
    -		}
    -		if (error) {
    -			ASSERT(committed);
    -			args->trans = NULL;
    -			xfs_bmap_cancel(args->flist);
    -			return(error);
    -		}
    -
    -		/*
    -		 * bmap_finish() may have committed the last trans and started
    -		 * a new one.  We need the inode to be in all transactions.
    -		 */
    -		if (committed) {
    -			xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL);
    -			xfs_trans_ihold(args->trans, dp);
    -		}
    -
    -		ASSERT(nmap == 1);
    -		ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
    -		       (map.br_startblock != HOLESTARTBLOCK));
    -		lblkno += map.br_blockcount;
    -		blkcnt -= map.br_blockcount;
    -
    -		/*
    -		 * Start the next trans in the chain.
    -		 */
    -		if ((error = xfs_attr_rolltrans(&args->trans, dp)))
    -			return (error);
    -	}
    -
    -	/*
    -	 * Roll through the "value", copying the attribute value to the
    -	 * already-allocated blocks.  Blocks are written synchronously
    -	 * so that we can know they are all on disk before we turn off
    -	 * the INCOMPLETE flag.
    -	 */
    -	lblkno = args->rmtblkno;
    -	valuelen = args->valuelen;
    -	while (valuelen > 0) {
    -		/*
    -		 * Try to remember where we decided to put the value.
    -		 */
    -		XFS_BMAP_INIT(args->flist, args->firstblock);
    -		nmap = 1;
    -		error = xfs_bmapi(NULL, dp, (xfs_fileoff_t)lblkno,
    -				  args->rmtblkcnt,
    -				  XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
    -				  args->firstblock, 0, &map, &nmap,
    -				  NULL, NULL);
    -		if (error) {
    -			return(error);
    -		}
    -		ASSERT(nmap == 1);
    -		ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
    -		       (map.br_startblock != HOLESTARTBLOCK));
    -
    -		dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock),
    -		blkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount);
    -
    -		bp = xfs_buf_get_flags(mp->m_ddev_targp, dblkno,
    -							blkcnt, XFS_BUF_LOCK);
    -		ASSERT(bp);
    -		ASSERT(!XFS_BUF_GETERROR(bp));
    -
    -		tmp = (valuelen < XFS_BUF_SIZE(bp)) ? valuelen :
    -							XFS_BUF_SIZE(bp);
    -		xfs_biomove(bp, 0, tmp, src, XFS_B_WRITE);
    -		if (tmp < XFS_BUF_SIZE(bp))
    -			xfs_biozero(bp, tmp, XFS_BUF_SIZE(bp) - tmp);
    -		if ((error = xfs_bwrite(mp, bp))) {/* GROT: NOTE: synchronous write */
    -			return (error);
    -		}
    -		src += tmp;
    -		valuelen -= tmp;
    -
    -		lblkno += map.br_blockcount;
    -	}
    -	ASSERT(valuelen == 0);
    -	return(0);
    -}
    -
    -/*
    - * Remove the value associated with an attribute by deleting the
    - * out-of-line buffer that it is stored on.
    - */
    -STATIC int
    -xfs_attr_rmtval_remove(xfs_da_args_t *args)
    -{
    -	xfs_mount_t *mp;
    -	xfs_bmbt_irec_t map;
    -	xfs_buf_t *bp;
    -	xfs_daddr_t dblkno;
    -	xfs_dablk_t lblkno;
    -	int valuelen, blkcnt, nmap, error, done, committed;
    -
    -	mp = args->dp->i_mount;
    -
    -	/*
    -	 * Roll through the "value", invalidating the attribute value's
    -	 * blocks.
    -	 */
    -	lblkno = args->rmtblkno;
    -	valuelen = args->rmtblkcnt;
    -	while (valuelen > 0) {
    -		/*
    -		 * Try to remember where we decided to put the value.
    -		 */
    -		XFS_BMAP_INIT(args->flist, args->firstblock);
    -		nmap = 1;
    -		error = xfs_bmapi(NULL, args->dp, (xfs_fileoff_t)lblkno,
    -					args->rmtblkcnt,
    -					XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
    -					args->firstblock, 0, &map, &nmap,
    -					args->flist, NULL);
    -		if (error) {
    -			return(error);
    -		}
    -		ASSERT(nmap == 1);
    -		ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
    -		       (map.br_startblock != HOLESTARTBLOCK));
    -
    -		dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock),
    -		blkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount);
    -
    -		/*
    -		 * If the "remote" value is in the cache, remove it.
    -		 */
    -		bp = xfs_incore(mp->m_ddev_targp, dblkno, blkcnt,
    -				XFS_INCORE_TRYLOCK);
    -		if (bp) {
    -			XFS_BUF_STALE(bp);
    -			XFS_BUF_UNDELAYWRITE(bp);
    -			xfs_buf_relse(bp);
    -			bp = NULL;
    -		}
    -
    -		valuelen -= map.br_blockcount;
    -
    -		lblkno += map.br_blockcount;
    -	}
    -
    -	/*
    -	 * Keep de-allocating extents until the remote-value region is gone.
    -	 */
    -	lblkno = args->rmtblkno;
    -	blkcnt = args->rmtblkcnt;
    -	done = 0;
    -	while (!done) {
    -		XFS_BMAP_INIT(args->flist, args->firstblock);
    -		error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt,
    -				    XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
    -				    1, args->firstblock, args->flist,
    -				    NULL, &done);
    -		if (!error) {
    -			error = xfs_bmap_finish(&args->trans, args->flist,
    -						*args->firstblock, &committed);
    -		}
    -		if (error) {
    -			ASSERT(committed);
    -			args->trans = NULL;
    -			xfs_bmap_cancel(args->flist);
    -			return(error);
    -		}
    -
    -		/*
    -		 * bmap_finish() may have committed the last trans and started
    -		 * a new one.  We need the inode to be in all transactions.
    -		 */
    -		if (committed) {
    -			xfs_trans_ijoin(args->trans, args->dp, XFS_ILOCK_EXCL);
    -			xfs_trans_ihold(args->trans, args->dp);
    -		}
    -
    -		/*
    -		 * Close out trans and start the next one in the chain.
    -		 */
    -		if ((error = xfs_attr_rolltrans(&args->trans, args->dp)))
    -			return (error);
    -	}
    -	return(0);
    -}
    -
    -#if defined(XFS_ATTR_TRACE)
    -/*
    - * Add a trace buffer entry for an attr_list context structure.
    - */
    -void
    -xfs_attr_trace_l_c(char *where, struct xfs_attr_list_context *context)
    -{
    -	xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_C, where,
    -		(__psunsigned_t)context->dp,
    -		(__psunsigned_t)context->cursor->hashval,
    -		(__psunsigned_t)context->cursor->blkno,
    -		(__psunsigned_t)context->cursor->offset,
    -		(__psunsigned_t)context->alist,
    -		(__psunsigned_t)context->bufsize,
    -		(__psunsigned_t)context->count,
    -		(__psunsigned_t)context->firstu,
    -		(__psunsigned_t)
    -			((context->count > 0) &&
    -			!(context->flags & (ATTR_KERNAMELS|ATTR_KERNOVAL)))
    -				? (ATTR_ENTRY(context->alist,
    -					      context->count-1)->a_valuelen)
    -				: 0,
    -		(__psunsigned_t)context->dupcnt,
    -		(__psunsigned_t)context->flags,
    -		(__psunsigned_t)NULL,
    -		(__psunsigned_t)NULL,
    -		(__psunsigned_t)NULL);
    -}
    -
    -/*
    - * Add a trace buffer entry for a context structure and a Btree node.
    - */
    -void
    -xfs_attr_trace_l_cn(char *where, struct xfs_attr_list_context *context,
    -			 struct xfs_da_intnode *node)
    -{
    -	xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_CN, where,
    -		(__psunsigned_t)context->dp,
    -		(__psunsigned_t)context->cursor->hashval,
    -		(__psunsigned_t)context->cursor->blkno,
    -		(__psunsigned_t)context->cursor->offset,
    -		(__psunsigned_t)context->alist,
    -		(__psunsigned_t)context->bufsize,
    -		(__psunsigned_t)context->count,
    -		(__psunsigned_t)context->firstu,
    -		(__psunsigned_t)
    -			((context->count > 0) &&
    -			!(context->flags & (ATTR_KERNAMELS|ATTR_KERNOVAL)))
    -				? (ATTR_ENTRY(context->alist,
    -					      context->count-1)->a_valuelen)
    -				: 0,
    -		(__psunsigned_t)context->dupcnt,
    -		(__psunsigned_t)context->flags,
    -		(__psunsigned_t)be16_to_cpu(node->hdr.count),
    -		(__psunsigned_t)be32_to_cpu(node->btree[0].hashval),
    -		(__psunsigned_t)be32_to_cpu(node->btree[
    -				    be16_to_cpu(node->hdr.count)-1].hashval));
    -}
    -
    -/*
    - * Add a trace buffer entry for a context structure and a Btree element.
    - */
    -void
    -xfs_attr_trace_l_cb(char *where, struct xfs_attr_list_context *context,
    -			  struct xfs_da_node_entry *btree)
    -{
    -	xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_CB, where,
    -		(__psunsigned_t)context->dp,
    -		(__psunsigned_t)context->cursor->hashval,
    -		(__psunsigned_t)context->cursor->blkno,
    -		(__psunsigned_t)context->cursor->offset,
    -		(__psunsigned_t)context->alist,
    -		(__psunsigned_t)context->bufsize,
    -		(__psunsigned_t)context->count,
    -		(__psunsigned_t)context->firstu,
    -		(__psunsigned_t)
    -			((context->count > 0) &&
    -			!(context->flags & (ATTR_KERNAMELS|ATTR_KERNOVAL)))
    -				? (ATTR_ENTRY(context->alist,
    -					      context->count-1)->a_valuelen)
    -				: 0,
    -		(__psunsigned_t)context->dupcnt,
    -		(__psunsigned_t)context->flags,
    -		(__psunsigned_t)be32_to_cpu(btree->hashval),
    -		(__psunsigned_t)be32_to_cpu(btree->before),
    -		(__psunsigned_t)NULL);
    -}
    -
    -/*
    - * Add a trace buffer entry for a context structure and a leaf block.
    - */
    -void
    -xfs_attr_trace_l_cl(char *where, struct xfs_attr_list_context *context,
    -			      struct xfs_attr_leafblock *leaf)
    -{
    -	xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_CL, where,
    -		(__psunsigned_t)context->dp,
    -		(__psunsigned_t)context->cursor->hashval,
    -		(__psunsigned_t)context->cursor->blkno,
    -		(__psunsigned_t)context->cursor->offset,
    -		(__psunsigned_t)context->alist,
    -		(__psunsigned_t)context->bufsize,
    -		(__psunsigned_t)context->count,
    -		(__psunsigned_t)context->firstu,
    -		(__psunsigned_t)
    -			((context->count > 0) &&
    -			!(context->flags & (ATTR_KERNAMELS|ATTR_KERNOVAL)))
    -				? (ATTR_ENTRY(context->alist,
    -					      context->count-1)->a_valuelen)
    -				: 0,
    -		(__psunsigned_t)context->dupcnt,
    -		(__psunsigned_t)context->flags,
    -		(__psunsigned_t)be16_to_cpu(leaf->hdr.count),
    -		(__psunsigned_t)be32_to_cpu(leaf->entries[0].hashval),
    -		(__psunsigned_t)be32_to_cpu(leaf->entries[
    -				be16_to_cpu(leaf->hdr.count)-1].hashval));
    -}
    -
    -/*
    - * Add a trace buffer entry for the arguments given to the routine,
    - * generic form.
    - */
    -void
    -xfs_attr_trace_enter(int type, char *where,
    -			 __psunsigned_t a2, __psunsigned_t a3,
    -			 __psunsigned_t a4, __psunsigned_t a5,
    -			 __psunsigned_t a6, __psunsigned_t a7,
    -			 __psunsigned_t a8, __psunsigned_t a9,
    -			 __psunsigned_t a10, __psunsigned_t a11,
    -			 __psunsigned_t a12, __psunsigned_t a13,
    -			 __psunsigned_t a14, __psunsigned_t a15)
    -{
    -	ASSERT(xfs_attr_trace_buf);
    -	ktrace_enter(xfs_attr_trace_buf, (void *)((__psunsigned_t)type),
    -					 (void *)where,
    -					 (void *)a2,  (void *)a3,  (void *)a4,
    -					 (void *)a5,  (void *)a6,  (void *)a7,
    -					 (void *)a8,  (void *)a9,  (void *)a10,
    -					 (void *)a11, (void *)a12, (void *)a13,
    -					 (void *)a14, (void *)a15);
    -}
    -#endif	/* XFS_ATTR_TRACE */
    -
    -
    -/*========================================================================
    - * System (pseudo) namespace attribute interface routines.
    - *========================================================================*/
    -
    -STATIC int
    -posix_acl_access_set(
    -	xfs_vnode_t *vp, char *name, void *data, size_t size, int xflags)
    -{
    -	return xfs_acl_vset(vp, data, size, _ACL_TYPE_ACCESS);
    -}
    -
    -STATIC int
    -posix_acl_access_remove(
    -	struct xfs_vnode *vp, char *name, int xflags)
    -{
    -	return xfs_acl_vremove(vp, _ACL_TYPE_ACCESS);
    -}
    -
    -STATIC int
    -posix_acl_access_get(
    -	xfs_vnode_t *vp, char *name, void *data, size_t size, int xflags)
    -{
    -	return xfs_acl_vget(vp, data, size, _ACL_TYPE_ACCESS);
    -}
    -
    -STATIC int
    -posix_acl_access_exists(
    -	xfs_vnode_t *vp)
    -{
    -	return xfs_acl_vhasacl_access(vp);
    -}
    -
    -STATIC int
    -posix_acl_default_set(
    -	xfs_vnode_t *vp, char *name, void *data, size_t size, int xflags)
    -{
    -	return xfs_acl_vset(vp, data, size, _ACL_TYPE_DEFAULT);
    -}
    -
    -STATIC int
    -posix_acl_default_get(
    -	xfs_vnode_t *vp, char *name, void *data, size_t size, int xflags)
    -{
    -	return xfs_acl_vget(vp, data, size, _ACL_TYPE_DEFAULT);
    -}
    -
    -STATIC int
    -posix_acl_default_remove(
    -	struct xfs_vnode *vp, char *name, int xflags)
    -{
    -	return xfs_acl_vremove(vp, _ACL_TYPE_DEFAULT);
    -}
    -
    -STATIC int
    -posix_acl_default_exists(
    -	xfs_vnode_t *vp)
    -{
    -	return xfs_acl_vhasacl_default(vp);
    -}
    -
    -STATIC struct attrnames posix_acl_access = {
    -	.attr_name	= "posix_acl_access",
    -	.attr_namelen	= sizeof("posix_acl_access") - 1,
    -	.attr_get	= posix_acl_access_get,
    -	.attr_set	= posix_acl_access_set,
    -	.attr_remove	= posix_acl_access_remove,
    -	.attr_exists	= posix_acl_access_exists,
    -};
    -
    -STATIC struct attrnames posix_acl_default = {
    -	.attr_name	= "posix_acl_default",
    -	.attr_namelen	= sizeof("posix_acl_default") - 1,
    -	.attr_get	= posix_acl_default_get,
    -	.attr_set	= posix_acl_default_set,
    -	.attr_remove	= posix_acl_default_remove,
    -	.attr_exists	= posix_acl_default_exists,
    -};
    -
    -STATIC struct attrnames *attr_system_names[] =
    -	{ &posix_acl_access, &posix_acl_default };
    -
    -
    -/*========================================================================
    - * Namespace-prefix-style attribute name interface routines.
    - *========================================================================*/
    -
    -STATIC int
    -attr_generic_set(
    -	struct xfs_vnode *vp, char *name, void *data, size_t size, int xflags)
    -{
    -	int 	error;
    -
    -	XVOP_ATTR_SET(vp, name, data, size, xflags, NULL, error);
    -	return -error;
    -}
    -
    -STATIC int
    -attr_generic_get(
    -	struct xfs_vnode *vp, char *name, void *data, size_t size, int xflags)
    -{
    -	int	error, asize = size;
    -
    -	XVOP_ATTR_GET(vp, name, data, &asize, xflags, NULL, error);
    -	if (!error)
    -		return asize;
    -	return -error;
    -}
    -
    -STATIC int
    -attr_generic_remove(
    -	struct xfs_vnode *vp, char *name, int xflags)
    -{
    -	int	error;
    -
    -	XVOP_ATTR_REMOVE(vp, name, xflags, NULL, error);
    -	return -error;
    -}
    -
    -STATIC int
    -attr_generic_listadd(
    -	attrnames_t		*prefix,
    -	attrnames_t		*namesp,
    -	void			*data,
    -	size_t			size,
    -	ssize_t			*result)
    -{
    -	char			*p = (char *)data + *result;
    -
    -	*result += prefix->attr_namelen;
    -	*result += namesp->attr_namelen + 1;
    -	if (!size)
    -		return 0;
    -	if (*result > size)
    -		return -ERANGE;
    -	strcpy(p, prefix->attr_name);
    -	p += prefix->attr_namelen;
    -	strcpy(p, namesp->attr_name);
    -	p += namesp->attr_namelen + 1;
    -	return 0;
    -}
    -
    -STATIC int
    -attr_system_list(
    -	struct xfs_vnode		*vp,
    -	void			*data,
    -	size_t			size,
    -	ssize_t			*result)
    -{
    -	attrnames_t		*namesp;
    -	int			i, error = 0;
    -
    -	for (i = 0; i < ATTR_SYSCOUNT; i++) {
    -		namesp = attr_system_names[i];
    -		if (!namesp->attr_exists || !namesp->attr_exists(vp))
    -			continue;
    -		error = attr_generic_listadd(&attr_system, namesp,
    -						data, size, result);
    -		if (error)
    -			break;
    -	}
    -	return error;
    -}
    -
    -int
    -attr_generic_list(
    -	struct xfs_vnode *vp, void *data, size_t size, int xflags, ssize_t *result)
    -{
    -	attrlist_cursor_kern_t	cursor = { 0 };
    -	int			error;
    -
    -	XVOP_ATTR_LIST(vp, data, size, xflags, &cursor, NULL, error);
    -	if (error > 0)
    -		return -error;
    -	*result = -error;
    -	return attr_system_list(vp, data, size, result);
    -}
    -
    -attrnames_t *
    -attr_lookup_namespace(
    -	char			*name,
    -	struct attrnames	**names,
    -	int			nnames)
    -{
    -	int			i;
    -
    -	for (i = 0; i < nnames; i++)
    -		if (!strncmp(name, names[i]->attr_name, names[i]->attr_namelen))
    -			return names[i];
    -	return NULL;
    -}
    -
    -/*
    - * Some checks to prevent people abusing EAs to get over quota:
    - * - Don't allow modifying user EAs on devices/symlinks;
    - * - Don't allow modifying user EAs if sticky bit set;
    - */
    -STATIC int
    -attr_user_capable(
    -	struct xfs_vnode	*vp,
    -	cred_t		*cred)
    -{
    -#ifdef XXXKAN
    -	struct inode	*inode = vn_to_inode(vp);
    -
    -	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
    -		return -EPERM;
    -	if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode) &&
    -	    !capable(CAP_SYS_ADMIN))
    -		return -EPERM;
    -	if (S_ISDIR(inode->i_mode) && (inode->i_mode & S_ISVTX) &&
    -	    (current_fsuid(cred) != inode->i_uid) && !capable(CAP_FOWNER))
    -		return -EPERM;
    -#endif
    -	return 0;
    -}
    -
    -STATIC int
    -attr_trusted_capable(
    -	struct xfs_vnode	*vp,
    -	cred_t		*cred)
    -{
    -#ifdef XXXKAN
    -	struct inode	*inode = vn_to_inode(vp);
    -
    -	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
    -		return -EPERM;
    -	if (!capable(CAP_SYS_ADMIN))
    -		return -EPERM;
    -#endif
    -	return 0;
    -}
    -
    -STATIC int
    -attr_secure_capable(
    -	struct xfs_vnode *vp,
    -	cred_t		 *cred)
    -{
    -	return -ENOSECURITY;
    -}
    -
    -STATIC int
    -attr_system_set(
    -	struct xfs_vnode *vp, char *name, void *data, size_t size, int xflags)
    -{
    -	attrnames_t	*namesp;
    -	int		error;
    -
    -	if (xflags & ATTR_CREATE)
    -		return -EINVAL;
    -
    -	namesp = attr_lookup_namespace(name, attr_system_names, ATTR_SYSCOUNT);
    -	if (!namesp)
    -		return -EOPNOTSUPP;
    -	error = namesp->attr_set(vp, name, data, size, xflags);
    -#ifdef XXXKAN
    -	if (!error)
    -		error = vn_revalidate(vp);
    -#endif
    -	return error;
    -}
    -
    -STATIC int
    -attr_system_get(
    -	struct xfs_vnode *vp, char *name, void *data, size_t size, int xflags)
    -{
    -	attrnames_t	*namesp;
    -
    -	namesp = attr_lookup_namespace(name, attr_system_names, ATTR_SYSCOUNT);
    -	if (!namesp)
    -		return -EOPNOTSUPP;
    -	return namesp->attr_get(vp, name, data, size, xflags);
    -}
    -
    -STATIC int
    -attr_system_remove(
    -	struct xfs_vnode *vp, char *name, int xflags)
    -{
    -	attrnames_t	*namesp;
    -
    -	namesp = attr_lookup_namespace(name, attr_system_names, ATTR_SYSCOUNT);
    -	if (!namesp)
    -		return -EOPNOTSUPP;
    -	return namesp->attr_remove(vp, name, xflags);
    -}
    -
    -struct attrnames attr_system = {
    -	.attr_name	= "system.",
    -	.attr_namelen	= sizeof("system.") - 1,
    -	.attr_flag	= ATTR_SYSTEM,
    -	.attr_get	= attr_system_get,
    -	.attr_set	= attr_system_set,
    -	.attr_remove	= attr_system_remove,
    -	.attr_capable	= (attrcapable_t)fs_noerr,
    -};
    -
    -struct attrnames attr_trusted = {
    -	.attr_name	= "trusted.",
    -	.attr_namelen	= sizeof("trusted.") - 1,
    -	.attr_flag	= ATTR_ROOT,
    -	.attr_get	= attr_generic_get,
    -	.attr_set	= attr_generic_set,
    -	.attr_remove	= attr_generic_remove,
    -	.attr_capable	= attr_trusted_capable,
    -};
    -
    -struct attrnames attr_secure = {
    -	.attr_name	= "security.",
    -	.attr_namelen	= sizeof("security.") - 1,
    -	.attr_flag	= ATTR_SECURE,
    -	.attr_get	= attr_generic_get,
    -	.attr_set	= attr_generic_set,
    -	.attr_remove	= attr_generic_remove,
    -	.attr_capable	= attr_secure_capable,
    -};
    -
    -struct attrnames attr_user = {
    -	.attr_name	= "user.",
    -	.attr_namelen	= sizeof("user.") - 1,
    -	.attr_get	= attr_generic_get,
    -	.attr_set	= attr_generic_set,
    -	.attr_remove	= attr_generic_remove,
    -	.attr_capable	= attr_user_capable,
    -};
    -
    -struct attrnames *attr_namespaces[] =
    -	{ &attr_system, &attr_trusted, &attr_secure, &attr_user };
    diff --git a/sys/gnu/fs/xfs/xfs_attr.h b/sys/gnu/fs/xfs/xfs_attr.h
    deleted file mode 100644
    index 6135b1b761f..00000000000
    --- a/sys/gnu/fs/xfs/xfs_attr.h
    +++ /dev/null
    @@ -1,172 +0,0 @@
    -/*
    - * Copyright (c) 2000,2002-2003,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_ATTR_H__
    -#define	__XFS_ATTR_H__
    -
    -/*
    - * xfs_attr.h
    - *
    - * Large attribute lists are structured around Btrees where all the data
    - * elements are in the leaf nodes.  Attribute names are hashed into an int,
    - * then that int is used as the index into the Btree.  Since the hashval
    - * of an attribute name may not be unique, we may have duplicate keys.
    - * The internal links in the Btree are logical block offsets into the file.
    - *
    - * Small attribute lists use a different format and are packed as tightly
    - * as possible so as to fit into the literal area of the inode.
    - */
    -
    -/*========================================================================
    - * External interfaces
    - *========================================================================*/
    -
    -struct cred;
    -struct xfs_vnode;
    -
    -typedef int (*attrset_t)(struct xfs_vnode *, char *, void *, size_t, int);
    -typedef int (*attrget_t)(struct xfs_vnode *, char *, void *, size_t, int);
    -typedef int (*attrremove_t)(struct xfs_vnode *, char *, int);
    -typedef int (*attrexists_t)(struct xfs_vnode *);
    -typedef int (*attrcapable_t)(struct xfs_vnode *, struct cred *);
    -
    -typedef struct attrnames {
    -	char *		attr_name;
    -	unsigned int	attr_namelen;
    -	unsigned int	attr_flag;
    -	attrget_t	attr_get;
    -	attrset_t	attr_set;
    -	attrremove_t	attr_remove;
    -	attrexists_t	attr_exists;
    -	attrcapable_t	attr_capable;
    -} attrnames_t;
    -
    -#define ATTR_NAMECOUNT	4
    -extern struct attrnames attr_user;
    -extern struct attrnames attr_secure;
    -extern struct attrnames attr_system;
    -extern struct attrnames attr_trusted;
    -extern struct attrnames *attr_namespaces[ATTR_NAMECOUNT];
    -
    -extern attrnames_t *attr_lookup_namespace(char *, attrnames_t **, int);
    -extern int attr_generic_list(struct xfs_vnode *, void *, size_t, int, ssize_t *);
    -
    -#define ATTR_DONTFOLLOW	0x0001	/* -- unused, from IRIX -- */
    -#define ATTR_ROOT	0x0002	/* use attrs in root (trusted) namespace */
    -#define ATTR_TRUST	0x0004	/* -- unused, from IRIX -- */
    -#define ATTR_SECURE	0x0008	/* use attrs in security namespace */
    -#define ATTR_CREATE	0x0010	/* pure create: fail if attr already exists */
    -#define ATTR_REPLACE	0x0020	/* pure set: fail if attr does not exist */
    -#define ATTR_SYSTEM	0x0100	/* use attrs in system (pseudo) namespace */
    -
    -#define ATTR_KERNACCESS	0x0400	/* [kernel] iaccess, inode held io-locked */
    -#define ATTR_KERNOTIME	0x1000	/* [kernel] don't update inode timestamps */
    -#define ATTR_KERNOVAL	0x2000	/* [kernel] get attr size only, not value */
    -#define ATTR_KERNAMELS	0x4000	/* [kernel] list attr names (simple list) */
    -
    -#define ATTR_KERNORMALS	0x0800	/* [kernel] normal attr list: user+secure */
    -#define ATTR_KERNROOTLS	0x8000	/* [kernel] include root in the attr list */
    -#define ATTR_KERNFULLS	(ATTR_KERNORMALS|ATTR_KERNROOTLS)
    -
    -/*
    - * The maximum size (into the kernel or returned from the kernel) of an
    - * attribute value or the buffer used for an attr_list() call.  Larger
    - * sizes will result in an ERANGE return code.
    - */
    -#define	ATTR_MAX_VALUELEN	(64*1024)	/* max length of a value */
    -
    -/*
    - * Define how lists of attribute names are returned to the user from
    - * the attr_list() call.  A large, 32bit aligned, buffer is passed in
    - * along with its size.  We put an array of offsets at the top that each
    - * reference an attrlist_ent_t and pack the attrlist_ent_t's at the bottom.
    - */
    -typedef struct attrlist {
    -	__s32	al_count;	/* number of entries in attrlist */
    -	__s32	al_more;	/* T/F: more attrs (do call again) */
    -	__s32	al_offset[1];	/* byte offsets of attrs [var-sized] */
    -} attrlist_t;
    -
    -/*
    - * Show the interesting info about one attribute.  This is what the
    - * al_offset[i] entry points to.
    - */
    -typedef struct attrlist_ent {	/* data from attr_list() */
    -	__u32	a_valuelen;	/* number bytes in value of attr */
    -	char	a_name[1];	/* attr name (NULL terminated) */
    -} attrlist_ent_t;
    -
    -/*
    - * Given a pointer to the (char*) buffer containing the attr_list() result,
    - * and an index, return a pointer to the indicated attribute in the buffer.
    - */
    -#define	ATTR_ENTRY(buffer, index)		\
    -	((attrlist_ent_t *)			\
    -	 &((char *)buffer)[ ((attrlist_t *)(buffer))->al_offset[index] ])
    -
    -/*
    - * Multi-attribute operation vector.
    - */
    -typedef struct attr_multiop {
    -	int	am_opcode;	/* operation to perform (ATTR_OP_GET, etc.) */
    -	int	am_error;	/* [out arg] result of this sub-op (an errno) */
    -	char	*am_attrname;	/* attribute name to work with */
    -	char	*am_attrvalue;	/* [in/out arg] attribute value (raw bytes) */
    -	int	am_length;	/* [in/out arg] length of value */
    -	int	am_flags;	/* bitwise OR of attr API flags defined above */
    -} attr_multiop_t;
    -
    -#define ATTR_OP_GET	1	/* return the indicated attr's value */
    -#define ATTR_OP_SET	2	/* set/create the indicated attr/value pair */
    -#define ATTR_OP_REMOVE	3	/* remove the indicated attr */
    -
    -/*
    - * Kernel-internal version of the attrlist cursor.
    - */
    -typedef struct attrlist_cursor_kern {
    -	__u32	hashval;	/* hash value of next entry to add */
    -	__u32	blkno;		/* block containing entry (suggestion) */
    -	__u32	offset;		/* offset in list of equal-hashvals */
    -	__u16	pad1;		/* padding to match user-level */
    -	__u8	pad2;		/* padding to match user-level */
    -	__u8	initted;	/* T/F: cursor has been initialized */
    -} attrlist_cursor_kern_t;
    -
    -
    -/*========================================================================
    - * Function prototypes for the kernel.
    - *========================================================================*/
    -
    -struct xfs_inode;
    -struct attrlist_cursor_kern;
    -struct xfs_da_args;
    -
    -/*
    - * Overall external interface routines.
    - */
    -int xfs_attr_get(bhv_desc_t *, const char *, char *, int *, int, struct cred *);
    -int xfs_attr_set(bhv_desc_t *, const char *, char *, int, int, struct cred *);
    -int xfs_attr_remove(bhv_desc_t *, const char *, int, struct cred *);
    -int xfs_attr_list(bhv_desc_t *, char *, int, int,
    -			 struct attrlist_cursor_kern *, struct cred *);
    -int xfs_attr_inactive(struct xfs_inode *dp);
    -
    -int xfs_attr_shortform_getvalue(struct xfs_da_args *);
    -int xfs_attr_fetch(struct xfs_inode *, const char *, int,
    -			char *, int *, int, struct cred *);
    -
    -#endif	/* __XFS_ATTR_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_attr_leaf.c b/sys/gnu/fs/xfs/xfs_attr_leaf.c
    deleted file mode 100644
    index 3a48b412525..00000000000
    --- a/sys/gnu/fs/xfs/xfs_attr_leaf.c
    +++ /dev/null
    @@ -1,3083 +0,0 @@
    -/*
    - * Copyright (c) 2000-2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_da_btree.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_alloc.h"
    -#include "xfs_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_inode_item.h"
    -#include "xfs_bmap.h"
    -#include "xfs_attr.h"
    -#include "xfs_attr_leaf.h"
    -#include "xfs_error.h"
    -
    -/*
    - * xfs_attr_leaf.c
    - *
    - * Routines to implement leaf blocks of attributes as Btrees of hashed names.
    - */
    -
    -/*========================================================================
    - * Function prototypes for the kernel.
    - *========================================================================*/
    -
    -/*
    - * Routines used for growing the Btree.
    - */
    -STATIC int xfs_attr_leaf_create(xfs_da_args_t *args, xfs_dablk_t which_block,
    -				    xfs_dabuf_t **bpp);
    -STATIC int xfs_attr_leaf_add_work(xfs_dabuf_t *leaf_buffer, xfs_da_args_t *args,
    -					      int freemap_index);
    -STATIC void xfs_attr_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *leaf_buffer);
    -STATIC void xfs_attr_leaf_rebalance(xfs_da_state_t *state,
    -						   xfs_da_state_blk_t *blk1,
    -						   xfs_da_state_blk_t *blk2);
    -STATIC int xfs_attr_leaf_figure_balance(xfs_da_state_t *state,
    -					   xfs_da_state_blk_t *leaf_blk_1,
    -					   xfs_da_state_blk_t *leaf_blk_2,
    -					   int *number_entries_in_blk1,
    -					   int *number_usedbytes_in_blk1);
    -
    -/*
    - * Routines used for shrinking the Btree.
    - */
    -STATIC int xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp,
    -				  xfs_dabuf_t *bp, int level);
    -STATIC int xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp,
    -				  xfs_dabuf_t *bp);
    -STATIC int xfs_attr_leaf_freextent(xfs_trans_t **trans, xfs_inode_t *dp,
    -				   xfs_dablk_t blkno, int blkcnt);
    -
    -/*
    - * Utility routines.
    - */
    -STATIC void xfs_attr_leaf_moveents(xfs_attr_leafblock_t *src_leaf,
    -					 int src_start,
    -					 xfs_attr_leafblock_t *dst_leaf,
    -					 int dst_start, int move_count,
    -					 xfs_mount_t *mp);
    -STATIC int xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index);
    -STATIC int xfs_attr_put_listent(xfs_attr_list_context_t *context,
    -			     attrnames_t *, char *name, int namelen,
    -			     int valuelen);
    -
    -
    -/*========================================================================
    - * External routines when attribute fork size < XFS_LITINO(mp).
    - *========================================================================*/
    -
    -/*
    - * Query whether the requested number of additional bytes of extended
    - * attribute space will be able to fit inline.
    - * Returns zero if not, else the di_forkoff fork offset to be used in the
    - * literal area for attribute data once the new bytes have been added.
    - *
    - * di_forkoff must be 8 byte aligned, hence is stored as a >>3 value;
    - * special case for dev/uuid inodes, they have fixed size data forks.
    - */
    -int
    -xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes)
    -{
    -	int offset;
    -	int minforkoff;	/* lower limit on valid forkoff locations */
    -	int maxforkoff;	/* upper limit on valid forkoff locations */
    -	xfs_mount_t *mp = dp->i_mount;
    -
    -	offset = (XFS_LITINO(mp) - bytes) >> 3; /* rounded down */
    -
    -	switch (dp->i_d.di_format) {
    -	case XFS_DINODE_FMT_DEV:
    -		minforkoff = roundup(sizeof(xfs_dev_t), 8) >> 3;
    -		return (offset >= minforkoff) ? minforkoff : 0;
    -	case XFS_DINODE_FMT_UUID:
    -		minforkoff = roundup(sizeof(uuid_t), 8) >> 3;
    -		return (offset >= minforkoff) ? minforkoff : 0;
    -	}
    -
    -	if (!(mp->m_flags & XFS_MOUNT_ATTR2)) {
    -		if (bytes <= XFS_IFORK_ASIZE(dp))
    -			return mp->m_attroffset >> 3;
    -		return 0;
    -	}
    -
    -	/* data fork btree root can have at least this many key/ptr pairs */
    -	minforkoff = MAX(dp->i_df.if_bytes, XFS_BMDR_SPACE_CALC(MINDBTPTRS));
    -	minforkoff = roundup(minforkoff, 8) >> 3;
    -
    -	/* attr fork btree root can have at least this many key/ptr pairs */
    -	maxforkoff = XFS_LITINO(mp) - XFS_BMDR_SPACE_CALC(MINABTPTRS);
    -	maxforkoff = maxforkoff >> 3;	/* rounded down */
    -
    -	if (offset >= minforkoff && offset < maxforkoff)
    -		return offset;
    -	if (offset >= maxforkoff)
    -		return maxforkoff;
    -	return 0;
    -}
    -
    -/*
    - * Switch on the ATTR2 superblock bit (implies also FEATURES2)
    - */
    -STATIC void
    -xfs_sbversion_add_attr2(xfs_mount_t *mp, xfs_trans_t *tp)
    -{
    -	unsigned long s;
    -
    -	if ((mp->m_flags & XFS_MOUNT_ATTR2) &&
    -	    !(XFS_SB_VERSION_HASATTR2(&mp->m_sb))) {
    -		s = XFS_SB_LOCK(mp);
    -		if (!XFS_SB_VERSION_HASATTR2(&mp->m_sb)) {
    -			XFS_SB_VERSION_ADDATTR2(&mp->m_sb);
    -			XFS_SB_UNLOCK(mp, s);
    -			xfs_mod_sb(tp, XFS_SB_VERSIONNUM | XFS_SB_FEATURES2);
    -		} else
    -			XFS_SB_UNLOCK(mp, s);
    -	}
    -}
    -
    -/*
    - * Create the initial contents of a shortform attribute list.
    - */
    -void
    -xfs_attr_shortform_create(xfs_da_args_t *args)
    -{
    -	xfs_attr_sf_hdr_t *hdr;
    -	xfs_inode_t *dp;
    -	xfs_ifork_t *ifp;
    -
    -	dp = args->dp;
    -	ASSERT(dp != NULL);
    -	ifp = dp->i_afp;
    -	ASSERT(ifp != NULL);
    -	ASSERT(ifp->if_bytes == 0);
    -	if (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS) {
    -		ifp->if_flags &= ~XFS_IFEXTENTS;	/* just in case */
    -		dp->i_d.di_aformat = XFS_DINODE_FMT_LOCAL;
    -		ifp->if_flags |= XFS_IFINLINE;
    -	} else {
    -		ASSERT(ifp->if_flags & XFS_IFINLINE);
    -	}
    -	xfs_idata_realloc(dp, sizeof(*hdr), XFS_ATTR_FORK);
    -	hdr = (xfs_attr_sf_hdr_t *)ifp->if_u1.if_data;
    -	hdr->count = 0;
    -	hdr->totsize = cpu_to_be16(sizeof(*hdr));
    -	xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_ADATA);
    -}
    -
    -/*
    - * Add a name/value pair to the shortform attribute list.
    - * Overflow from the inode has already been checked for.
    - */
    -void
    -xfs_attr_shortform_add(xfs_da_args_t *args, int forkoff)
    -{
    -	xfs_attr_shortform_t *sf;
    -	xfs_attr_sf_entry_t *sfe;
    -	int i, offset, size;
    -	xfs_mount_t *mp;
    -	xfs_inode_t *dp;
    -	xfs_ifork_t *ifp;
    -
    -	dp = args->dp;
    -	mp = dp->i_mount;
    -	dp->i_d.di_forkoff = forkoff;
    -	dp->i_df.if_ext_max =
    -		XFS_IFORK_DSIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t);
    -	dp->i_afp->if_ext_max =
    -		XFS_IFORK_ASIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t);
    -
    -	ifp = dp->i_afp;
    -	ASSERT(ifp->if_flags & XFS_IFINLINE);
    -	sf = (xfs_attr_shortform_t *)ifp->if_u1.if_data;
    -	sfe = &sf->list[0];
    -	for (i = 0; i < sf->hdr.count; sfe = XFS_ATTR_SF_NEXTENTRY(sfe), i++) {
    -#ifdef DEBUG
    -		if (sfe->namelen != args->namelen)
    -			continue;
    -		if (memcmp(args->name, sfe->nameval, args->namelen) != 0)
    -			continue;
    -		if (((args->flags & ATTR_SECURE) != 0) !=
    -		    ((sfe->flags & XFS_ATTR_SECURE) != 0))
    -			continue;
    -		if (((args->flags & ATTR_ROOT) != 0) !=
    -		    ((sfe->flags & XFS_ATTR_ROOT) != 0))
    -			continue;
    -		ASSERT(0);
    -#endif
    -	}
    -
    -	offset = (char *)sfe - (char *)sf;
    -	size = XFS_ATTR_SF_ENTSIZE_BYNAME(args->namelen, args->valuelen);
    -	xfs_idata_realloc(dp, size, XFS_ATTR_FORK);
    -	sf = (xfs_attr_shortform_t *)ifp->if_u1.if_data;
    -	sfe = (xfs_attr_sf_entry_t *)((char *)sf + offset);
    -
    -	sfe->namelen = args->namelen;
    -	sfe->valuelen = args->valuelen;
    -	sfe->flags = (args->flags & ATTR_SECURE) ? XFS_ATTR_SECURE :
    -			((args->flags & ATTR_ROOT) ? XFS_ATTR_ROOT : 0);
    -	memcpy(sfe->nameval, args->name, args->namelen);
    -	memcpy(&sfe->nameval[args->namelen], args->value, args->valuelen);
    -	sf->hdr.count++;
    -	be16_add(&sf->hdr.totsize, size);
    -	xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_ADATA);
    -
    -	xfs_sbversion_add_attr2(mp, args->trans);
    -}
    -
    -/*
    - * Remove an attribute from the shortform attribute list structure.
    - */
    -int
    -xfs_attr_shortform_remove(xfs_da_args_t *args)
    -{
    -	xfs_attr_shortform_t *sf;
    -	xfs_attr_sf_entry_t *sfe;
    -	int base, size=0, end, totsize, i;
    -	xfs_mount_t *mp;
    -	xfs_inode_t *dp;
    -
    -	dp = args->dp;
    -	mp = dp->i_mount;
    -	base = sizeof(xfs_attr_sf_hdr_t);
    -	sf = (xfs_attr_shortform_t *)dp->i_afp->if_u1.if_data;
    -	sfe = &sf->list[0];
    -	end = sf->hdr.count;
    -	for (i = 0; i < end; sfe = XFS_ATTR_SF_NEXTENTRY(sfe),
    -					base += size, i++) {
    -		size = XFS_ATTR_SF_ENTSIZE(sfe);
    -		if (sfe->namelen != args->namelen)
    -			continue;
    -		if (memcmp(sfe->nameval, args->name, args->namelen) != 0)
    -			continue;
    -		if (((args->flags & ATTR_SECURE) != 0) !=
    -		    ((sfe->flags & XFS_ATTR_SECURE) != 0))
    -			continue;
    -		if (((args->flags & ATTR_ROOT) != 0) !=
    -		    ((sfe->flags & XFS_ATTR_ROOT) != 0))
    -			continue;
    -		break;
    -	}
    -	if (i == end)
    -		return(XFS_ERROR(ENOATTR));
    -
    -	/*
    -	 * Fix up the attribute fork data, covering the hole
    -	 */
    -	end = base + size;
    -	totsize = be16_to_cpu(sf->hdr.totsize);
    -	if (end != totsize)
    -		memmove(&((char *)sf)[base], &((char *)sf)[end], totsize - end);
    -	sf->hdr.count--;
    -	be16_add(&sf->hdr.totsize, -size);
    -
    -	/*
    -	 * Fix up the start offset of the attribute fork
    -	 */
    -	totsize -= size;
    -	if (totsize == sizeof(xfs_attr_sf_hdr_t) && !args->addname &&
    -	    (mp->m_flags & XFS_MOUNT_ATTR2)) {
    -		/*
    -		 * Last attribute now removed, revert to original
    -		 * inode format making all literal area available
    -		 * to the data fork once more.
    -		 */
    -		xfs_idestroy_fork(dp, XFS_ATTR_FORK);
    -		dp->i_d.di_forkoff = 0;
    -		dp->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
    -		ASSERT(dp->i_d.di_anextents == 0);
    -		ASSERT(dp->i_afp == NULL);
    -		dp->i_df.if_ext_max =
    -			XFS_IFORK_DSIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t);
    -		xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE);
    -	} else {
    -		xfs_idata_realloc(dp, -size, XFS_ATTR_FORK);
    -		dp->i_d.di_forkoff = xfs_attr_shortform_bytesfit(dp, totsize);
    -		ASSERT(dp->i_d.di_forkoff);
    -		ASSERT(totsize > sizeof(xfs_attr_sf_hdr_t) || args->addname ||
    -			!(mp->m_flags & XFS_MOUNT_ATTR2));
    -		dp->i_afp->if_ext_max =
    -			XFS_IFORK_ASIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t);
    -		dp->i_df.if_ext_max =
    -			XFS_IFORK_DSIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t);
    -		xfs_trans_log_inode(args->trans, dp,
    -					XFS_ILOG_CORE | XFS_ILOG_ADATA);
    -	}
    -
    -	xfs_sbversion_add_attr2(mp, args->trans);
    -
    -	return(0);
    -}
    -
    -/*
    - * Look up a name in a shortform attribute list structure.
    - */
    -/*ARGSUSED*/
    -int
    -xfs_attr_shortform_lookup(xfs_da_args_t *args)
    -{
    -	xfs_attr_shortform_t *sf;
    -	xfs_attr_sf_entry_t *sfe;
    -	int i;
    -	xfs_ifork_t *ifp;
    -
    -	ifp = args->dp->i_afp;
    -	ASSERT(ifp->if_flags & XFS_IFINLINE);
    -	sf = (xfs_attr_shortform_t *)ifp->if_u1.if_data;
    -	sfe = &sf->list[0];
    -	for (i = 0; i < sf->hdr.count;
    -				sfe = XFS_ATTR_SF_NEXTENTRY(sfe), i++) {
    -		if (sfe->namelen != args->namelen)
    -			continue;
    -		if (memcmp(args->name, sfe->nameval, args->namelen) != 0)
    -			continue;
    -		if (((args->flags & ATTR_SECURE) != 0) !=
    -		    ((sfe->flags & XFS_ATTR_SECURE) != 0))
    -			continue;
    -		if (((args->flags & ATTR_ROOT) != 0) !=
    -		    ((sfe->flags & XFS_ATTR_ROOT) != 0))
    -			continue;
    -		return(XFS_ERROR(EEXIST));
    -	}
    -	return(XFS_ERROR(ENOATTR));
    -}
    -
    -/*
    - * Look up a name in a shortform attribute list structure.
    - */
    -/*ARGSUSED*/
    -int
    -xfs_attr_shortform_getvalue(xfs_da_args_t *args)
    -{
    -	xfs_attr_shortform_t *sf;
    -	xfs_attr_sf_entry_t *sfe;
    -	int i;
    -
    -	ASSERT(args->dp->i_d.di_aformat == XFS_IFINLINE);
    -	sf = (xfs_attr_shortform_t *)args->dp->i_afp->if_u1.if_data;
    -	sfe = &sf->list[0];
    -	for (i = 0; i < sf->hdr.count;
    -				sfe = XFS_ATTR_SF_NEXTENTRY(sfe), i++) {
    -		if (sfe->namelen != args->namelen)
    -			continue;
    -		if (memcmp(args->name, sfe->nameval, args->namelen) != 0)
    -			continue;
    -		if (((args->flags & ATTR_SECURE) != 0) !=
    -		    ((sfe->flags & XFS_ATTR_SECURE) != 0))
    -			continue;
    -		if (((args->flags & ATTR_ROOT) != 0) !=
    -		    ((sfe->flags & XFS_ATTR_ROOT) != 0))
    -			continue;
    -		if (args->flags & ATTR_KERNOVAL) {
    -			args->valuelen = sfe->valuelen;
    -			return(XFS_ERROR(EEXIST));
    -		}
    -		if (args->valuelen < sfe->valuelen) {
    -			args->valuelen = sfe->valuelen;
    -			return(XFS_ERROR(ERANGE));
    -		}
    -		args->valuelen = sfe->valuelen;
    -		memcpy(args->value, &sfe->nameval[args->namelen],
    -						    args->valuelen);
    -		return(XFS_ERROR(EEXIST));
    -	}
    -	return(XFS_ERROR(ENOATTR));
    -}
    -
    -/*
    - * Convert from using the shortform to the leaf.
    - */
    -int
    -xfs_attr_shortform_to_leaf(xfs_da_args_t *args)
    -{
    -	xfs_inode_t *dp;
    -	xfs_attr_shortform_t *sf;
    -	xfs_attr_sf_entry_t *sfe;
    -	xfs_da_args_t nargs;
    -	char *tmpbuffer;
    -	int error, i, size;
    -	xfs_dablk_t blkno;
    -	xfs_dabuf_t *bp;
    -	xfs_ifork_t *ifp;
    -
    -	dp = args->dp;
    -	ifp = dp->i_afp;
    -	sf = (xfs_attr_shortform_t *)ifp->if_u1.if_data;
    -	size = be16_to_cpu(sf->hdr.totsize);
    -	tmpbuffer = kmem_alloc(size, KM_SLEEP);
    -	ASSERT(tmpbuffer != NULL);
    -	memcpy(tmpbuffer, ifp->if_u1.if_data, size);
    -	sf = (xfs_attr_shortform_t *)tmpbuffer;
    -
    -	xfs_idata_realloc(dp, -size, XFS_ATTR_FORK);
    -	bp = NULL;
    -	error = xfs_da_grow_inode(args, &blkno);
    -	if (error) {
    -		/*
    -		 * If we hit an IO error middle of the transaction inside
    -		 * grow_inode(), we may have inconsistent data. Bail out.
    -		 */
    -		if (error == EIO)
    -			goto out;
    -		xfs_idata_realloc(dp, size, XFS_ATTR_FORK);	/* try to put */
    -		memcpy(ifp->if_u1.if_data, tmpbuffer, size);	/* it back */
    -		goto out;
    -	}
    -
    -	ASSERT(blkno == 0);
    -	error = xfs_attr_leaf_create(args, blkno, &bp);
    -	if (error) {
    -		error = xfs_da_shrink_inode(args, 0, bp);
    -		bp = NULL;
    -		if (error)
    -			goto out;
    -		xfs_idata_realloc(dp, size, XFS_ATTR_FORK);	/* try to put */
    -		memcpy(ifp->if_u1.if_data, tmpbuffer, size);	/* it back */
    -		goto out;
    -	}
    -
    -	memset((char *)&nargs, 0, sizeof(nargs));
    -	nargs.dp = dp;
    -	nargs.firstblock = args->firstblock;
    -	nargs.flist = args->flist;
    -	nargs.total = args->total;
    -	nargs.whichfork = XFS_ATTR_FORK;
    -	nargs.trans = args->trans;
    -	nargs.oknoent = 1;
    -
    -	sfe = &sf->list[0];
    -	for (i = 0; i < sf->hdr.count; i++) {
    -		nargs.name = (char *)sfe->nameval;
    -		nargs.namelen = sfe->namelen;
    -		nargs.value = (char *)&sfe->nameval[nargs.namelen];
    -		nargs.valuelen = sfe->valuelen;
    -		nargs.hashval = xfs_da_hashname((char *)sfe->nameval,
    -						sfe->namelen);
    -		nargs.flags = (sfe->flags & XFS_ATTR_SECURE) ? ATTR_SECURE :
    -				((sfe->flags & XFS_ATTR_ROOT) ? ATTR_ROOT : 0);
    -		error = xfs_attr_leaf_lookup_int(bp, &nargs); /* set a->index */
    -		ASSERT(error == ENOATTR);
    -		error = xfs_attr_leaf_add(bp, &nargs);
    -		ASSERT(error != ENOSPC);
    -		if (error)
    -			goto out;
    -		sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
    -	}
    -	error = 0;
    -
    -out:
    -	if(bp)
    -		xfs_da_buf_done(bp);
    -	kmem_free(tmpbuffer, size);
    -	return(error);
    -}
    -
    -STATIC int
    -xfs_attr_shortform_compare(const void *a, const void *b)
    -{
    -	const xfs_attr_sf_sort_t *sa, *sb;
    -
    -	sa = (const xfs_attr_sf_sort_t *)a;
    -	sb = (const xfs_attr_sf_sort_t *)b;
    -	if (sa->hash < sb->hash) {
    -		return(-1);
    -	} else if (sa->hash > sb->hash) {
    -		return(1);
    -	} else {
    -		return(sa->entno - sb->entno);
    -	}
    -}
    -
    -/*
    - * Copy out entries of shortform attribute lists for attr_list().
    - * Shortform attribute lists are not stored in hashval sorted order.
    - * If the output buffer is not large enough to hold them all, then we
    - * we have to calculate each entries' hashvalue and sort them before
    - * we can begin returning them to the user.
    - */
    -/*ARGSUSED*/
    -int
    -xfs_attr_shortform_list(xfs_attr_list_context_t *context)
    -{
    -	attrlist_cursor_kern_t *cursor;
    -	xfs_attr_sf_sort_t *sbuf, *sbp;
    -	xfs_attr_shortform_t *sf;
    -	xfs_attr_sf_entry_t *sfe;
    -	xfs_inode_t *dp;
    -	int sbsize, nsbuf, count, i;
    -
    -	ASSERT(context != NULL);
    -	dp = context->dp;
    -	ASSERT(dp != NULL);
    -	ASSERT(dp->i_afp != NULL);
    -	sf = (xfs_attr_shortform_t *)dp->i_afp->if_u1.if_data;
    -	ASSERT(sf != NULL);
    -	if (!sf->hdr.count)
    -		return(0);
    -	cursor = context->cursor;
    -	ASSERT(cursor != NULL);
    -
    -	xfs_attr_trace_l_c("sf start", context);
    -
    -	/*
    -	 * If the buffer is large enough, do not bother with sorting.
    -	 * Note the generous fudge factor of 16 overhead bytes per entry.
    -	 */
    -	if ((dp->i_afp->if_bytes + sf->hdr.count * 16) < context->bufsize) {
    -		for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) {
    -			attrnames_t	*namesp;
    -
    -			if (((context->flags & ATTR_SECURE) != 0) !=
    -			    ((sfe->flags & XFS_ATTR_SECURE) != 0) &&
    -			    !(context->flags & ATTR_KERNORMALS)) {
    -				sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
    -				continue;
    -			}
    -			if (((context->flags & ATTR_ROOT) != 0) !=
    -			    ((sfe->flags & XFS_ATTR_ROOT) != 0) &&
    -			    !(context->flags & ATTR_KERNROOTLS)) {
    -				sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
    -				continue;
    -			}
    -			namesp = (sfe->flags & XFS_ATTR_SECURE) ? &attr_secure:
    -				((sfe->flags & XFS_ATTR_ROOT) ? &attr_trusted :
    -				  &attr_user);
    -			if (context->flags & ATTR_KERNOVAL) {
    -				ASSERT(context->flags & ATTR_KERNAMELS);
    -				context->count += namesp->attr_namelen +
    -					sfe->namelen + 1;
    -			}
    -			else {
    -				if (xfs_attr_put_listent(context, namesp,
    -						   (char *)sfe->nameval,
    -						   (int)sfe->namelen,
    -						   (int)sfe->valuelen))
    -					break;
    -			}
    -			sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
    -		}
    -		xfs_attr_trace_l_c("sf big-gulp", context);
    -		return(0);
    -	}
    -
    -	/*
    -	 * It didn't all fit, so we have to sort everything on hashval.
    -	 */
    -	sbsize = sf->hdr.count * sizeof(*sbuf);
    -	sbp = sbuf = kmem_alloc(sbsize, KM_SLEEP);
    -
    -	/*
    -	 * Scan the attribute list for the rest of the entries, storing
    -	 * the relevant info from only those that match into a buffer.
    -	 */
    -	nsbuf = 0;
    -	for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) {
    -		if (unlikely(
    -		    ((char *)sfe < (char *)sf) ||
    -		    ((char *)sfe >= ((char *)sf + dp->i_afp->if_bytes)))) {
    -			XFS_CORRUPTION_ERROR("xfs_attr_shortform_list",
    -					     XFS_ERRLEVEL_LOW,
    -					     context->dp->i_mount, sfe);
    -			xfs_attr_trace_l_c("sf corrupted", context);
    -			kmem_free(sbuf, sbsize);
    -			return XFS_ERROR(EFSCORRUPTED);
    -		}
    -		if (((context->flags & ATTR_SECURE) != 0) !=
    -		    ((sfe->flags & XFS_ATTR_SECURE) != 0) &&
    -		    !(context->flags & ATTR_KERNORMALS)) {
    -			sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
    -			continue;
    -		}
    -		if (((context->flags & ATTR_ROOT) != 0) !=
    -		    ((sfe->flags & XFS_ATTR_ROOT) != 0) &&
    -		    !(context->flags & ATTR_KERNROOTLS)) {
    -			sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
    -			continue;
    -		}
    -		sbp->entno = i;
    -		sbp->hash = xfs_da_hashname((char *)sfe->nameval, sfe->namelen);
    -		sbp->name = (char *)sfe->nameval;
    -		sbp->namelen = sfe->namelen;
    -		/* These are bytes, and both on-disk, don't endian-flip */
    -		sbp->valuelen = sfe->valuelen;
    -		sbp->flags = sfe->flags;
    -		sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
    -		sbp++;
    -		nsbuf++;
    -	}
    -
    -	/*
    -	 * Sort the entries on hash then entno.
    -	 */
    -	xfs_sort(sbuf, nsbuf, sizeof(*sbuf), xfs_attr_shortform_compare);
    -
    -	/*
    -	 * Re-find our place IN THE SORTED LIST.
    -	 */
    -	count = 0;
    -	cursor->initted = 1;
    -	cursor->blkno = 0;
    -	for (sbp = sbuf, i = 0; i < nsbuf; i++, sbp++) {
    -		if (sbp->hash == cursor->hashval) {
    -			if (cursor->offset == count) {
    -				break;
    -			}
    -			count++;
    -		} else if (sbp->hash > cursor->hashval) {
    -			break;
    -		}
    -	}
    -	if (i == nsbuf) {
    -		kmem_free(sbuf, sbsize);
    -		xfs_attr_trace_l_c("blk end", context);
    -		return(0);
    -	}
    -
    -	/*
    -	 * Loop putting entries into the user buffer.
    -	 */
    -	for ( ; i < nsbuf; i++, sbp++) {
    -		attrnames_t	*namesp;
    -
    -		namesp = (sbp->flags & XFS_ATTR_SECURE) ? &attr_secure :
    -			((sbp->flags & XFS_ATTR_ROOT) ? &attr_trusted :
    -			  &attr_user);
    -
    -		if (cursor->hashval != sbp->hash) {
    -			cursor->hashval = sbp->hash;
    -			cursor->offset = 0;
    -		}
    -		if (context->flags & ATTR_KERNOVAL) {
    -			ASSERT(context->flags & ATTR_KERNAMELS);
    -			context->count += namesp->attr_namelen +
    -						sbp->namelen + 1;
    -		} else {
    -			if (xfs_attr_put_listent(context, namesp,
    -					sbp->name, sbp->namelen,
    -					sbp->valuelen))
    -				break;
    -		}
    -		cursor->offset++;
    -	}
    -
    -	kmem_free(sbuf, sbsize);
    -	xfs_attr_trace_l_c("sf E-O-F", context);
    -	return(0);
    -}
    -
    -/*
    - * Check a leaf attribute block to see if all the entries would fit into
    - * a shortform attribute list.
    - */
    -int
    -xfs_attr_shortform_allfit(xfs_dabuf_t *bp, xfs_inode_t *dp)
    -{
    -	xfs_attr_leafblock_t *leaf;
    -	xfs_attr_leaf_entry_t *entry;
    -	xfs_attr_leaf_name_local_t *name_loc;
    -	int bytes, i;
    -
    -	leaf = bp->data;
    -	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
    -
    -	entry = &leaf->entries[0];
    -	bytes = sizeof(struct xfs_attr_sf_hdr);
    -	for (i = 0; i < be16_to_cpu(leaf->hdr.count); entry++, i++) {
    -		if (entry->flags & XFS_ATTR_INCOMPLETE)
    -			continue;		/* don't copy partial entries */
    -		if (!(entry->flags & XFS_ATTR_LOCAL))
    -			return(0);
    -		name_loc = XFS_ATTR_LEAF_NAME_LOCAL(leaf, i);
    -		if (name_loc->namelen >= XFS_ATTR_SF_ENTSIZE_MAX)
    -			return(0);
    -		if (be16_to_cpu(name_loc->valuelen) >= XFS_ATTR_SF_ENTSIZE_MAX)
    -			return(0);
    -		bytes += sizeof(struct xfs_attr_sf_entry)-1
    -				+ name_loc->namelen
    -				+ be16_to_cpu(name_loc->valuelen);
    -	}
    -	if ((dp->i_mount->m_flags & XFS_MOUNT_ATTR2) &&
    -	    (bytes == sizeof(struct xfs_attr_sf_hdr)))
    -		return(-1);
    -	return(xfs_attr_shortform_bytesfit(dp, bytes));
    -}
    -
    -/*
    - * Convert a leaf attribute list to shortform attribute list
    - */
    -int
    -xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args, int forkoff)
    -{
    -	xfs_attr_leafblock_t *leaf;
    -	xfs_attr_leaf_entry_t *entry;
    -	xfs_attr_leaf_name_local_t *name_loc;
    -	xfs_da_args_t nargs;
    -	xfs_inode_t *dp;
    -	char *tmpbuffer;
    -	int error, i;
    -
    -	dp = args->dp;
    -	tmpbuffer = kmem_alloc(XFS_LBSIZE(dp->i_mount), KM_SLEEP);
    -	ASSERT(tmpbuffer != NULL);
    -
    -	ASSERT(bp != NULL);
    -	memcpy(tmpbuffer, bp->data, XFS_LBSIZE(dp->i_mount));
    -	leaf = (xfs_attr_leafblock_t *)tmpbuffer;
    -	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
    -	memset(bp->data, 0, XFS_LBSIZE(dp->i_mount));
    -
    -	/*
    -	 * Clean out the prior contents of the attribute list.
    -	 */
    -	error = xfs_da_shrink_inode(args, 0, bp);
    -	if (error)
    -		goto out;
    -
    -	if (forkoff == -1) {
    -		ASSERT(dp->i_mount->m_flags & XFS_MOUNT_ATTR2);
    -
    -		/*
    -		 * Last attribute was removed, revert to original
    -		 * inode format making all literal area available
    -		 * to the data fork once more.
    -		 */
    -		xfs_idestroy_fork(dp, XFS_ATTR_FORK);
    -		dp->i_d.di_forkoff = 0;
    -		dp->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
    -		ASSERT(dp->i_d.di_anextents == 0);
    -		ASSERT(dp->i_afp == NULL);
    -		dp->i_df.if_ext_max =
    -			XFS_IFORK_DSIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t);
    -		xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE);
    -		goto out;
    -	}
    -
    -	xfs_attr_shortform_create(args);
    -
    -	/*
    -	 * Copy the attributes
    -	 */
    -	memset((char *)&nargs, 0, sizeof(nargs));
    -	nargs.dp = dp;
    -	nargs.firstblock = args->firstblock;
    -	nargs.flist = args->flist;
    -	nargs.total = args->total;
    -	nargs.whichfork = XFS_ATTR_FORK;
    -	nargs.trans = args->trans;
    -	nargs.oknoent = 1;
    -	entry = &leaf->entries[0];
    -	for (i = 0; i < be16_to_cpu(leaf->hdr.count); entry++, i++) {
    -		if (entry->flags & XFS_ATTR_INCOMPLETE)
    -			continue;	/* don't copy partial entries */
    -		if (!entry->nameidx)
    -			continue;
    -		ASSERT(entry->flags & XFS_ATTR_LOCAL);
    -		name_loc = XFS_ATTR_LEAF_NAME_LOCAL(leaf, i);
    -		nargs.name = (char *)name_loc->nameval;
    -		nargs.namelen = name_loc->namelen;
    -		nargs.value = (char *)&name_loc->nameval[nargs.namelen];
    -		nargs.valuelen = be16_to_cpu(name_loc->valuelen);
    -		nargs.hashval = be32_to_cpu(entry->hashval);
    -		nargs.flags = (entry->flags & XFS_ATTR_SECURE) ? ATTR_SECURE :
    -			      ((entry->flags & XFS_ATTR_ROOT) ? ATTR_ROOT : 0);
    -		xfs_attr_shortform_add(&nargs, forkoff);
    -	}
    -	error = 0;
    -
    -out:
    -	kmem_free(tmpbuffer, XFS_LBSIZE(dp->i_mount));
    -	return(error);
    -}
    -
    -/*
    - * Convert from using a single leaf to a root node and a leaf.
    - */
    -int
    -xfs_attr_leaf_to_node(xfs_da_args_t *args)
    -{
    -	xfs_attr_leafblock_t *leaf;
    -	xfs_da_intnode_t *node;
    -	xfs_inode_t *dp;
    -	xfs_dabuf_t *bp1, *bp2;
    -	xfs_dablk_t blkno;
    -	int error;
    -
    -	dp = args->dp;
    -	bp1 = bp2 = NULL;
    -	error = xfs_da_grow_inode(args, &blkno);
    -	if (error)
    -		goto out;
    -	error = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp1,
    -					     XFS_ATTR_FORK);
    -	if (error)
    -		goto out;
    -	ASSERT(bp1 != NULL);
    -	bp2 = NULL;
    -	error = xfs_da_get_buf(args->trans, args->dp, blkno, -1, &bp2,
    -					    XFS_ATTR_FORK);
    -	if (error)
    -		goto out;
    -	ASSERT(bp2 != NULL);
    -	memcpy(bp2->data, bp1->data, XFS_LBSIZE(dp->i_mount));
    -	xfs_da_buf_done(bp1);
    -	bp1 = NULL;
    -	xfs_da_log_buf(args->trans, bp2, 0, XFS_LBSIZE(dp->i_mount) - 1);
    -
    -	/*
    -	 * Set up the new root node.
    -	 */
    -	error = xfs_da_node_create(args, 0, 1, &bp1, XFS_ATTR_FORK);
    -	if (error)
    -		goto out;
    -	node = bp1->data;
    -	leaf = bp2->data;
    -	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
    -	/* both on-disk, don't endian-flip twice */
    -	node->btree[0].hashval =
    -		leaf->entries[be16_to_cpu(leaf->hdr.count)-1 ].hashval;
    -	node->btree[0].before = cpu_to_be32(blkno);
    -	node->hdr.count = cpu_to_be16(1);
    -	xfs_da_log_buf(args->trans, bp1, 0, XFS_LBSIZE(dp->i_mount) - 1);
    -	error = 0;
    -out:
    -	if (bp1)
    -		xfs_da_buf_done(bp1);
    -	if (bp2)
    -		xfs_da_buf_done(bp2);
    -	return(error);
    -}
    -
    -
    -/*========================================================================
    - * Routines used for growing the Btree.
    - *========================================================================*/
    -
    -/*
    - * Create the initial contents of a leaf attribute list
    - * or a leaf in a node attribute list.
    - */
    -STATIC int
    -xfs_attr_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp)
    -{
    -	xfs_attr_leafblock_t *leaf;
    -	xfs_attr_leaf_hdr_t *hdr;
    -	xfs_inode_t *dp;
    -	xfs_dabuf_t *bp;
    -	int error;
    -
    -	dp = args->dp;
    -	ASSERT(dp != NULL);
    -	error = xfs_da_get_buf(args->trans, args->dp, blkno, -1, &bp,
    -					    XFS_ATTR_FORK);
    -	if (error)
    -		return(error);
    -	ASSERT(bp != NULL);
    -	leaf = bp->data;
    -	memset((char *)leaf, 0, XFS_LBSIZE(dp->i_mount));
    -	hdr = &leaf->hdr;
    -	hdr->info.magic = cpu_to_be16(XFS_ATTR_LEAF_MAGIC);
    -	hdr->firstused = cpu_to_be16(XFS_LBSIZE(dp->i_mount));
    -	if (!hdr->firstused) {
    -		hdr->firstused = cpu_to_be16(
    -			XFS_LBSIZE(dp->i_mount) - XFS_ATTR_LEAF_NAME_ALIGN);
    -	}
    -
    -	hdr->freemap[0].base = cpu_to_be16(sizeof(xfs_attr_leaf_hdr_t));
    -	hdr->freemap[0].size = cpu_to_be16(be16_to_cpu(hdr->firstused) -
    -					   sizeof(xfs_attr_leaf_hdr_t));
    -
    -	xfs_da_log_buf(args->trans, bp, 0, XFS_LBSIZE(dp->i_mount) - 1);
    -
    -	*bpp = bp;
    -	return(0);
    -}
    -
    -/*
    - * Split the leaf node, rebalance, then add the new entry.
    - */
    -int
    -xfs_attr_leaf_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk,
    -				   xfs_da_state_blk_t *newblk)
    -{
    -	xfs_dablk_t blkno;
    -	int error;
    -
    -	/*
    -	 * Allocate space for a new leaf node.
    -	 */
    -	ASSERT(oldblk->magic == XFS_ATTR_LEAF_MAGIC);
    -	error = xfs_da_grow_inode(state->args, &blkno);
    -	if (error)
    -		return(error);
    -	error = xfs_attr_leaf_create(state->args, blkno, &newblk->bp);
    -	if (error)
    -		return(error);
    -	newblk->blkno = blkno;
    -	newblk->magic = XFS_ATTR_LEAF_MAGIC;
    -
    -	/*
    -	 * Rebalance the entries across the two leaves.
    -	 * NOTE: rebalance() currently depends on the 2nd block being empty.
    -	 */
    -	xfs_attr_leaf_rebalance(state, oldblk, newblk);
    -	error = xfs_da_blk_link(state, oldblk, newblk);
    -	if (error)
    -		return(error);
    -
    -	/*
    -	 * Save info on "old" attribute for "atomic rename" ops, leaf_add()
    -	 * modifies the index/blkno/rmtblk/rmtblkcnt fields to show the
    -	 * "new" attrs info.  Will need the "old" info to remove it later.
    -	 *
    -	 * Insert the "new" entry in the correct block.
    -	 */
    -	if (state->inleaf)
    -		error = xfs_attr_leaf_add(oldblk->bp, state->args);
    -	else
    -		error = xfs_attr_leaf_add(newblk->bp, state->args);
    -
    -	/*
    -	 * Update last hashval in each block since we added the name.
    -	 */
    -	oldblk->hashval = xfs_attr_leaf_lasthash(oldblk->bp, NULL);
    -	newblk->hashval = xfs_attr_leaf_lasthash(newblk->bp, NULL);
    -	return(error);
    -}
    -
    -/*
    - * Add a name to the leaf attribute list structure.
    - */
    -int
    -xfs_attr_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args)
    -{
    -	xfs_attr_leafblock_t *leaf;
    -	xfs_attr_leaf_hdr_t *hdr;
    -	xfs_attr_leaf_map_t *map;
    -	int tablesize, entsize, sum, tmp, i;
    -
    -	leaf = bp->data;
    -	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
    -	ASSERT((args->index >= 0)
    -		&& (args->index <= be16_to_cpu(leaf->hdr.count)));
    -	hdr = &leaf->hdr;
    -	entsize = xfs_attr_leaf_newentsize(args->namelen, args->valuelen,
    -			   args->trans->t_mountp->m_sb.sb_blocksize, NULL);
    -
    -	/*
    -	 * Search through freemap for first-fit on new name length.
    -	 * (may need to figure in size of entry struct too)
    -	 */
    -	tablesize = (be16_to_cpu(hdr->count) + 1)
    -					* sizeof(xfs_attr_leaf_entry_t)
    -					+ sizeof(xfs_attr_leaf_hdr_t);
    -	map = &hdr->freemap[XFS_ATTR_LEAF_MAPSIZE-1];
    -	for (sum = 0, i = XFS_ATTR_LEAF_MAPSIZE-1; i >= 0; map--, i--) {
    -		if (tablesize > be16_to_cpu(hdr->firstused)) {
    -			sum += be16_to_cpu(map->size);
    -			continue;
    -		}
    -		if (!map->size)
    -			continue;	/* no space in this map */
    -		tmp = entsize;
    -		if (be16_to_cpu(map->base) < be16_to_cpu(hdr->firstused))
    -			tmp += sizeof(xfs_attr_leaf_entry_t);
    -		if (be16_to_cpu(map->size) >= tmp) {
    -			tmp = xfs_attr_leaf_add_work(bp, args, i);
    -			return(tmp);
    -		}
    -		sum += be16_to_cpu(map->size);
    -	}
    -
    -	/*
    -	 * If there are no holes in the address space of the block,
    -	 * and we don't have enough freespace, then compaction will do us
    -	 * no good and we should just give up.
    -	 */
    -	if (!hdr->holes && (sum < entsize))
    -		return(XFS_ERROR(ENOSPC));
    -
    -	/*
    -	 * Compact the entries to coalesce free space.
    -	 * This may change the hdr->count via dropping INCOMPLETE entries.
    -	 */
    -	xfs_attr_leaf_compact(args->trans, bp);
    -
    -	/*
    -	 * After compaction, the block is guaranteed to have only one
    -	 * free region, in freemap[0].  If it is not big enough, give up.
    -	 */
    -	if (be16_to_cpu(hdr->freemap[0].size)
    -				< (entsize + sizeof(xfs_attr_leaf_entry_t)))
    -		return(XFS_ERROR(ENOSPC));
    -
    -	return(xfs_attr_leaf_add_work(bp, args, 0));
    -}
    -
    -/*
    - * Add a name to a leaf attribute list structure.
    - */
    -STATIC int
    -xfs_attr_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int mapindex)
    -{
    -	xfs_attr_leafblock_t *leaf;
    -	xfs_attr_leaf_hdr_t *hdr;
    -	xfs_attr_leaf_entry_t *entry;
    -	xfs_attr_leaf_name_local_t *name_loc;
    -	xfs_attr_leaf_name_remote_t *name_rmt;
    -	xfs_attr_leaf_map_t *map;
    -	xfs_mount_t *mp;
    -	int tmp, i;
    -
    -	leaf = bp->data;
    -	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
    -	hdr = &leaf->hdr;
    -	ASSERT((mapindex >= 0) && (mapindex < XFS_ATTR_LEAF_MAPSIZE));
    -	ASSERT((args->index >= 0) && (args->index <= be16_to_cpu(hdr->count)));
    -
    -	/*
    -	 * Force open some space in the entry array and fill it in.
    -	 */
    -	entry = &leaf->entries[args->index];
    -	if (args->index < be16_to_cpu(hdr->count)) {
    -		tmp  = be16_to_cpu(hdr->count) - args->index;
    -		tmp *= sizeof(xfs_attr_leaf_entry_t);
    -		memmove((char *)(entry+1), (char *)entry, tmp);
    -		xfs_da_log_buf(args->trans, bp,
    -		    XFS_DA_LOGRANGE(leaf, entry, tmp + sizeof(*entry)));
    -	}
    -	be16_add(&hdr->count, 1);
    -
    -	/*
    -	 * Allocate space for the new string (at the end of the run).
    -	 */
    -	map = &hdr->freemap[mapindex];
    -	mp = args->trans->t_mountp;
    -	ASSERT(be16_to_cpu(map->base) < XFS_LBSIZE(mp));
    -	ASSERT((be16_to_cpu(map->base) & 0x3) == 0);
    -	ASSERT(be16_to_cpu(map->size) >=
    -		xfs_attr_leaf_newentsize(args->namelen, args->valuelen,
    -					 mp->m_sb.sb_blocksize, NULL));
    -	ASSERT(be16_to_cpu(map->size) < XFS_LBSIZE(mp));
    -	ASSERT((be16_to_cpu(map->size) & 0x3) == 0);
    -	be16_add(&map->size,
    -		-xfs_attr_leaf_newentsize(args->namelen, args->valuelen,
    -					  mp->m_sb.sb_blocksize, &tmp));
    -	entry->nameidx = cpu_to_be16(be16_to_cpu(map->base) +
    -				     be16_to_cpu(map->size));
    -	entry->hashval = cpu_to_be32(args->hashval);
    -	entry->flags = tmp ? XFS_ATTR_LOCAL : 0;
    -	entry->flags |= (args->flags & ATTR_SECURE) ? XFS_ATTR_SECURE :
    -			((args->flags & ATTR_ROOT) ? XFS_ATTR_ROOT : 0);
    -	if (args->rename) {
    -		entry->flags |= XFS_ATTR_INCOMPLETE;
    -		if ((args->blkno2 == args->blkno) &&
    -		    (args->index2 <= args->index)) {
    -			args->index2++;
    -		}
    -	}
    -	xfs_da_log_buf(args->trans, bp,
    -			  XFS_DA_LOGRANGE(leaf, entry, sizeof(*entry)));
    -	ASSERT((args->index == 0) ||
    -	       (be32_to_cpu(entry->hashval) >= be32_to_cpu((entry-1)->hashval)));
    -	ASSERT((args->index == be16_to_cpu(hdr->count)-1) ||
    -	       (be32_to_cpu(entry->hashval) <= be32_to_cpu((entry+1)->hashval)));
    -
    -	/*
    -	 * Copy the attribute name and value into the new space.
    -	 *
    -	 * For "remote" attribute values, simply note that we need to
    -	 * allocate space for the "remote" value.  We can't actually
    -	 * allocate the extents in this transaction, and we can't decide
    -	 * which blocks they should be as we might allocate more blocks
    -	 * as part of this transaction (a split operation for example).
    -	 */
    -	if (entry->flags & XFS_ATTR_LOCAL) {
    -		name_loc = XFS_ATTR_LEAF_NAME_LOCAL(leaf, args->index);
    -		name_loc->namelen = args->namelen;
    -		name_loc->valuelen = cpu_to_be16(args->valuelen);
    -		memcpy((char *)name_loc->nameval, args->name, args->namelen);
    -		memcpy((char *)&name_loc->nameval[args->namelen], args->value,
    -				   be16_to_cpu(name_loc->valuelen));
    -	} else {
    -		name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf, args->index);
    -		name_rmt->namelen = args->namelen;
    -		memcpy((char *)name_rmt->name, args->name, args->namelen);
    -		entry->flags |= XFS_ATTR_INCOMPLETE;
    -		/* just in case */
    -		name_rmt->valuelen = 0;
    -		name_rmt->valueblk = 0;
    -		args->rmtblkno = 1;
    -		args->rmtblkcnt = XFS_B_TO_FSB(mp, args->valuelen);
    -	}
    -	xfs_da_log_buf(args->trans, bp,
    -	     XFS_DA_LOGRANGE(leaf, XFS_ATTR_LEAF_NAME(leaf, args->index),
    -				   xfs_attr_leaf_entsize(leaf, args->index)));
    -
    -	/*
    -	 * Update the control info for this leaf node
    -	 */
    -	if (be16_to_cpu(entry->nameidx) < be16_to_cpu(hdr->firstused)) {
    -		/* both on-disk, don't endian-flip twice */
    -		hdr->firstused = entry->nameidx;
    -	}
    -	ASSERT(be16_to_cpu(hdr->firstused) >=
    -	       ((be16_to_cpu(hdr->count) * sizeof(*entry)) + sizeof(*hdr)));
    -	tmp = (be16_to_cpu(hdr->count)-1) * sizeof(xfs_attr_leaf_entry_t)
    -					+ sizeof(xfs_attr_leaf_hdr_t);
    -	map = &hdr->freemap[0];
    -	for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; map++, i++) {
    -		if (be16_to_cpu(map->base) == tmp) {
    -			be16_add(&map->base, sizeof(xfs_attr_leaf_entry_t));
    -			be16_add(&map->size,
    -				 -((int)sizeof(xfs_attr_leaf_entry_t)));
    -		}
    -	}
    -	be16_add(&hdr->usedbytes, xfs_attr_leaf_entsize(leaf, args->index));
    -	xfs_da_log_buf(args->trans, bp,
    -		XFS_DA_LOGRANGE(leaf, hdr, sizeof(*hdr)));
    -	return(0);
    -}
    -
    -/*
    - * Garbage collect a leaf attribute list block by copying it to a new buffer.
    - */
    -STATIC void
    -xfs_attr_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *bp)
    -{
    -	xfs_attr_leafblock_t *leaf_s, *leaf_d;
    -	xfs_attr_leaf_hdr_t *hdr_s, *hdr_d;
    -	xfs_mount_t *mp;
    -	char *tmpbuffer;
    -
    -	mp = trans->t_mountp;
    -	tmpbuffer = kmem_alloc(XFS_LBSIZE(mp), KM_SLEEP);
    -	ASSERT(tmpbuffer != NULL);
    -	memcpy(tmpbuffer, bp->data, XFS_LBSIZE(mp));
    -	memset(bp->data, 0, XFS_LBSIZE(mp));
    -
    -	/*
    -	 * Copy basic information
    -	 */
    -	leaf_s = (xfs_attr_leafblock_t *)tmpbuffer;
    -	leaf_d = bp->data;
    -	hdr_s = &leaf_s->hdr;
    -	hdr_d = &leaf_d->hdr;
    -	hdr_d->info = hdr_s->info;	/* struct copy */
    -	hdr_d->firstused = cpu_to_be16(XFS_LBSIZE(mp));
    -	/* handle truncation gracefully */
    -	if (!hdr_d->firstused) {
    -		hdr_d->firstused = cpu_to_be16(
    -				XFS_LBSIZE(mp) - XFS_ATTR_LEAF_NAME_ALIGN);
    -	}
    -	hdr_d->usedbytes = 0;
    -	hdr_d->count = 0;
    -	hdr_d->holes = 0;
    -	hdr_d->freemap[0].base = cpu_to_be16(sizeof(xfs_attr_leaf_hdr_t));
    -	hdr_d->freemap[0].size = cpu_to_be16(be16_to_cpu(hdr_d->firstused) -
    -					     sizeof(xfs_attr_leaf_hdr_t));
    -
    -	/*
    -	 * Copy all entry's in the same (sorted) order,
    -	 * but allocate name/value pairs packed and in sequence.
    -	 */
    -	xfs_attr_leaf_moveents(leaf_s, 0, leaf_d, 0,
    -				be16_to_cpu(hdr_s->count), mp);
    -	xfs_da_log_buf(trans, bp, 0, XFS_LBSIZE(mp) - 1);
    -
    -	kmem_free(tmpbuffer, XFS_LBSIZE(mp));
    -}
    -
    -/*
    - * Redistribute the attribute list entries between two leaf nodes,
    - * taking into account the size of the new entry.
    - *
    - * NOTE: if new block is empty, then it will get the upper half of the
    - * old block.  At present, all (one) callers pass in an empty second block.
    - *
    - * This code adjusts the args->index/blkno and args->index2/blkno2 fields
    - * to match what it is doing in splitting the attribute leaf block.  Those
    - * values are used in "atomic rename" operations on attributes.  Note that
    - * the "new" and "old" values can end up in different blocks.
    - */
    -STATIC void
    -xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
    -				       xfs_da_state_blk_t *blk2)
    -{
    -	xfs_da_args_t *args;
    -	xfs_da_state_blk_t *tmp_blk;
    -	xfs_attr_leafblock_t *leaf1, *leaf2;
    -	xfs_attr_leaf_hdr_t *hdr1, *hdr2;
    -	int count, totallen, max, space, swap;
    -
    -	/*
    -	 * Set up environment.
    -	 */
    -	ASSERT(blk1->magic == XFS_ATTR_LEAF_MAGIC);
    -	ASSERT(blk2->magic == XFS_ATTR_LEAF_MAGIC);
    -	leaf1 = blk1->bp->data;
    -	leaf2 = blk2->bp->data;
    -	ASSERT(be16_to_cpu(leaf1->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
    -	ASSERT(be16_to_cpu(leaf2->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
    -	args = state->args;
    -
    -	/*
    -	 * Check ordering of blocks, reverse if it makes things simpler.
    -	 *
    -	 * NOTE: Given that all (current) callers pass in an empty
    -	 * second block, this code should never set "swap".
    -	 */
    -	swap = 0;
    -	if (xfs_attr_leaf_order(blk1->bp, blk2->bp)) {
    -		tmp_blk = blk1;
    -		blk1 = blk2;
    -		blk2 = tmp_blk;
    -		leaf1 = blk1->bp->data;
    -		leaf2 = blk2->bp->data;
    -		swap = 1;
    -	}
    -	hdr1 = &leaf1->hdr;
    -	hdr2 = &leaf2->hdr;
    -
    -	/*
    -	 * Examine entries until we reduce the absolute difference in
    -	 * byte usage between the two blocks to a minimum.  Then get
    -	 * the direction to copy and the number of elements to move.
    -	 *
    -	 * "inleaf" is true if the new entry should be inserted into blk1.
    -	 * If "swap" is also true, then reverse the sense of "inleaf".
    -	 */
    -	state->inleaf = xfs_attr_leaf_figure_balance(state, blk1, blk2,
    -							    &count, &totallen);
    -	if (swap)
    -		state->inleaf = !state->inleaf;
    -
    -	/*
    -	 * Move any entries required from leaf to leaf:
    -	 */
    -	if (count < be16_to_cpu(hdr1->count)) {
    -		/*
    -		 * Figure the total bytes to be added to the destination leaf.
    -		 */
    -		/* number entries being moved */
    -		count = be16_to_cpu(hdr1->count) - count;
    -		space  = be16_to_cpu(hdr1->usedbytes) - totallen;
    -		space += count * sizeof(xfs_attr_leaf_entry_t);
    -
    -		/*
    -		 * leaf2 is the destination, compact it if it looks tight.
    -		 */
    -		max  = be16_to_cpu(hdr2->firstused)
    -						- sizeof(xfs_attr_leaf_hdr_t);
    -		max -= be16_to_cpu(hdr2->count) * sizeof(xfs_attr_leaf_entry_t);
    -		if (space > max) {
    -			xfs_attr_leaf_compact(args->trans, blk2->bp);
    -		}
    -
    -		/*
    -		 * Move high entries from leaf1 to low end of leaf2.
    -		 */
    -		xfs_attr_leaf_moveents(leaf1, be16_to_cpu(hdr1->count) - count,
    -				leaf2, 0, count, state->mp);
    -
    -		xfs_da_log_buf(args->trans, blk1->bp, 0, state->blocksize-1);
    -		xfs_da_log_buf(args->trans, blk2->bp, 0, state->blocksize-1);
    -	} else if (count > be16_to_cpu(hdr1->count)) {
    -		/*
    -		 * I assert that since all callers pass in an empty
    -		 * second buffer, this code should never execute.
    -		 */
    -
    -		/*
    -		 * Figure the total bytes to be added to the destination leaf.
    -		 */
    -		/* number entries being moved */
    -		count -= be16_to_cpu(hdr1->count);
    -		space  = totallen - be16_to_cpu(hdr1->usedbytes);
    -		space += count * sizeof(xfs_attr_leaf_entry_t);
    -
    -		/*
    -		 * leaf1 is the destination, compact it if it looks tight.
    -		 */
    -		max  = be16_to_cpu(hdr1->firstused)
    -						- sizeof(xfs_attr_leaf_hdr_t);
    -		max -= be16_to_cpu(hdr1->count) * sizeof(xfs_attr_leaf_entry_t);
    -		if (space > max) {
    -			xfs_attr_leaf_compact(args->trans, blk1->bp);
    -		}
    -
    -		/*
    -		 * Move low entries from leaf2 to high end of leaf1.
    -		 */
    -		xfs_attr_leaf_moveents(leaf2, 0, leaf1,
    -				be16_to_cpu(hdr1->count), count, state->mp);
    -
    -		xfs_da_log_buf(args->trans, blk1->bp, 0, state->blocksize-1);
    -		xfs_da_log_buf(args->trans, blk2->bp, 0, state->blocksize-1);
    -	}
    -
    -	/*
    -	 * Copy out last hashval in each block for B-tree code.
    -	 */
    -	blk1->hashval = be32_to_cpu(
    -		leaf1->entries[be16_to_cpu(leaf1->hdr.count)-1].hashval);
    -	blk2->hashval = be32_to_cpu(
    -		leaf2->entries[be16_to_cpu(leaf2->hdr.count)-1].hashval);
    -
    -	/*
    -	 * Adjust the expected index for insertion.
    -	 * NOTE: this code depends on the (current) situation that the
    -	 * second block was originally empty.
    -	 *
    -	 * If the insertion point moved to the 2nd block, we must adjust
    -	 * the index.  We must also track the entry just following the
    -	 * new entry for use in an "atomic rename" operation, that entry
    -	 * is always the "old" entry and the "new" entry is what we are
    -	 * inserting.  The index/blkno fields refer to the "old" entry,
    -	 * while the index2/blkno2 fields refer to the "new" entry.
    -	 */
    -	if (blk1->index > be16_to_cpu(leaf1->hdr.count)) {
    -		ASSERT(state->inleaf == 0);
    -		blk2->index = blk1->index - be16_to_cpu(leaf1->hdr.count);
    -		args->index = args->index2 = blk2->index;
    -		args->blkno = args->blkno2 = blk2->blkno;
    -	} else if (blk1->index == be16_to_cpu(leaf1->hdr.count)) {
    -		if (state->inleaf) {
    -			args->index = blk1->index;
    -			args->blkno = blk1->blkno;
    -			args->index2 = 0;
    -			args->blkno2 = blk2->blkno;
    -		} else {
    -			blk2->index = blk1->index
    -				    - be16_to_cpu(leaf1->hdr.count);
    -			args->index = args->index2 = blk2->index;
    -			args->blkno = args->blkno2 = blk2->blkno;
    -		}
    -	} else {
    -		ASSERT(state->inleaf == 1);
    -		args->index = args->index2 = blk1->index;
    -		args->blkno = args->blkno2 = blk1->blkno;
    -	}
    -}
    -
    -/*
    - * Examine entries until we reduce the absolute difference in
    - * byte usage between the two blocks to a minimum.
    - * GROT: Is this really necessary?  With other than a 512 byte blocksize,
    - * GROT: there will always be enough room in either block for a new entry.
    - * GROT: Do a double-split for this case?
    - */
    -STATIC int
    -xfs_attr_leaf_figure_balance(xfs_da_state_t *state,
    -				    xfs_da_state_blk_t *blk1,
    -				    xfs_da_state_blk_t *blk2,
    -				    int *countarg, int *usedbytesarg)
    -{
    -	xfs_attr_leafblock_t *leaf1, *leaf2;
    -	xfs_attr_leaf_hdr_t *hdr1, *hdr2;
    -	xfs_attr_leaf_entry_t *entry;
    -	int count, max, index, totallen, half;
    -	int lastdelta, foundit, tmp;
    -
    -	/*
    -	 * Set up environment.
    -	 */
    -	leaf1 = blk1->bp->data;
    -	leaf2 = blk2->bp->data;
    -	hdr1 = &leaf1->hdr;
    -	hdr2 = &leaf2->hdr;
    -	foundit = 0;
    -	totallen = 0;
    -
    -	/*
    -	 * Examine entries until we reduce the absolute difference in
    -	 * byte usage between the two blocks to a minimum.
    -	 */
    -	max = be16_to_cpu(hdr1->count) + be16_to_cpu(hdr2->count);
    -	half  = (max+1) * sizeof(*entry);
    -	half += be16_to_cpu(hdr1->usedbytes) +
    -		be16_to_cpu(hdr2->usedbytes) +
    -		xfs_attr_leaf_newentsize(
    -				state->args->namelen,
    -				state->args->valuelen,
    -				state->blocksize, NULL);
    -	half /= 2;
    -	lastdelta = state->blocksize;
    -	entry = &leaf1->entries[0];
    -	for (count = index = 0; count < max; entry++, index++, count++) {
    -
    -#define XFS_ATTR_ABS(A)	(((A) < 0) ? -(A) : (A))
    -		/*
    -		 * The new entry is in the first block, account for it.
    -		 */
    -		if (count == blk1->index) {
    -			tmp = totallen + sizeof(*entry) +
    -				xfs_attr_leaf_newentsize(
    -						state->args->namelen,
    -						state->args->valuelen,
    -						state->blocksize, NULL);
    -			if (XFS_ATTR_ABS(half - tmp) > lastdelta)
    -				break;
    -			lastdelta = XFS_ATTR_ABS(half - tmp);
    -			totallen = tmp;
    -			foundit = 1;
    -		}
    -
    -		/*
    -		 * Wrap around into the second block if necessary.
    -		 */
    -		if (count == be16_to_cpu(hdr1->count)) {
    -			leaf1 = leaf2;
    -			entry = &leaf1->entries[0];
    -			index = 0;
    -		}
    -
    -		/*
    -		 * Figure out if next leaf entry would be too much.
    -		 */
    -		tmp = totallen + sizeof(*entry) + xfs_attr_leaf_entsize(leaf1,
    -									index);
    -		if (XFS_ATTR_ABS(half - tmp) > lastdelta)
    -			break;
    -		lastdelta = XFS_ATTR_ABS(half - tmp);
    -		totallen = tmp;
    -#undef XFS_ATTR_ABS
    -	}
    -
    -	/*
    -	 * Calculate the number of usedbytes that will end up in lower block.
    -	 * If new entry not in lower block, fix up the count.
    -	 */
    -	totallen -= count * sizeof(*entry);
    -	if (foundit) {
    -		totallen -= sizeof(*entry) +
    -				xfs_attr_leaf_newentsize(
    -						state->args->namelen,
    -						state->args->valuelen,
    -						state->blocksize, NULL);
    -	}
    -
    -	*countarg = count;
    -	*usedbytesarg = totallen;
    -	return(foundit);
    -}
    -
    -/*========================================================================
    - * Routines used for shrinking the Btree.
    - *========================================================================*/
    -
    -/*
    - * Check a leaf block and its neighbors to see if the block should be
    - * collapsed into one or the other neighbor.  Always keep the block
    - * with the smaller block number.
    - * If the current block is over 50% full, don't try to join it, return 0.
    - * If the block is empty, fill in the state structure and return 2.
    - * If it can be collapsed, fill in the state structure and return 1.
    - * If nothing can be done, return 0.
    - *
    - * GROT: allow for INCOMPLETE entries in calculation.
    - */
    -int
    -xfs_attr_leaf_toosmall(xfs_da_state_t *state, int *action)
    -{
    -	xfs_attr_leafblock_t *leaf;
    -	xfs_da_state_blk_t *blk;
    -	xfs_da_blkinfo_t *info;
    -	int count, bytes, forward, error, retval, i;
    -	xfs_dablk_t blkno;
    -	xfs_dabuf_t *bp;
    -
    -	/*
    -	 * Check for the degenerate case of the block being over 50% full.
    -	 * If so, it's not worth even looking to see if we might be able
    -	 * to coalesce with a sibling.
    -	 */
    -	blk = &state->path.blk[ state->path.active-1 ];
    -	info = blk->bp->data;
    -	ASSERT(be16_to_cpu(info->magic) == XFS_ATTR_LEAF_MAGIC);
    -	leaf = (xfs_attr_leafblock_t *)info;
    -	count = be16_to_cpu(leaf->hdr.count);
    -	bytes = sizeof(xfs_attr_leaf_hdr_t) +
    -		count * sizeof(xfs_attr_leaf_entry_t) +
    -		be16_to_cpu(leaf->hdr.usedbytes);
    -	if (bytes > (state->blocksize >> 1)) {
    -		*action = 0;	/* blk over 50%, don't try to join */
    -		return(0);
    -	}
    -
    -	/*
    -	 * Check for the degenerate case of the block being empty.
    -	 * If the block is empty, we'll simply delete it, no need to
    -	 * coalesce it with a sibling block.  We choose (arbitrarily)
    -	 * to merge with the forward block unless it is NULL.
    -	 */
    -	if (count == 0) {
    -		/*
    -		 * Make altpath point to the block we want to keep and
    -		 * path point to the block we want to drop (this one).
    -		 */
    -		forward = (info->forw != 0);
    -		memcpy(&state->altpath, &state->path, sizeof(state->path));
    -		error = xfs_da_path_shift(state, &state->altpath, forward,
    -						 0, &retval);
    -		if (error)
    -			return(error);
    -		if (retval) {
    -			*action = 0;
    -		} else {
    -			*action = 2;
    -		}
    -		return(0);
    -	}
    -
    -	/*
    -	 * Examine each sibling block to see if we can coalesce with
    -	 * at least 25% free space to spare.  We need to figure out
    -	 * whether to merge with the forward or the backward block.
    -	 * We prefer coalescing with the lower numbered sibling so as
    -	 * to shrink an attribute list over time.
    -	 */
    -	/* start with smaller blk num */
    -	forward = (be32_to_cpu(info->forw) < be32_to_cpu(info->back));
    -	for (i = 0; i < 2; forward = !forward, i++) {
    -		if (forward)
    -			blkno = be32_to_cpu(info->forw);
    -		else
    -			blkno = be32_to_cpu(info->back);
    -		if (blkno == 0)
    -			continue;
    -		error = xfs_da_read_buf(state->args->trans, state->args->dp,
    -					blkno, -1, &bp, XFS_ATTR_FORK);
    -		if (error)
    -			return(error);
    -		ASSERT(bp != NULL);
    -
    -		leaf = (xfs_attr_leafblock_t *)info;
    -		count  = be16_to_cpu(leaf->hdr.count);
    -		bytes  = state->blocksize - (state->blocksize>>2);
    -		bytes -= be16_to_cpu(leaf->hdr.usedbytes);
    -		leaf = bp->data;
    -		ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
    -		count += be16_to_cpu(leaf->hdr.count);
    -		bytes -= be16_to_cpu(leaf->hdr.usedbytes);
    -		bytes -= count * sizeof(xfs_attr_leaf_entry_t);
    -		bytes -= sizeof(xfs_attr_leaf_hdr_t);
    -		xfs_da_brelse(state->args->trans, bp);
    -		if (bytes >= 0)
    -			break;	/* fits with at least 25% to spare */
    -	}
    -	if (i >= 2) {
    -		*action = 0;
    -		return(0);
    -	}
    -
    -	/*
    -	 * Make altpath point to the block we want to keep (the lower
    -	 * numbered block) and path point to the block we want to drop.
    -	 */
    -	memcpy(&state->altpath, &state->path, sizeof(state->path));
    -	if (blkno < blk->blkno) {
    -		error = xfs_da_path_shift(state, &state->altpath, forward,
    -						 0, &retval);
    -	} else {
    -		error = xfs_da_path_shift(state, &state->path, forward,
    -						 0, &retval);
    -	}
    -	if (error)
    -		return(error);
    -	if (retval) {
    -		*action = 0;
    -	} else {
    -		*action = 1;
    -	}
    -	return(0);
    -}
    -
    -/*
    - * Remove a name from the leaf attribute list structure.
    - *
    - * Return 1 if leaf is less than 37% full, 0 if >= 37% full.
    - * If two leaves are 37% full, when combined they will leave 25% free.
    - */
    -int
    -xfs_attr_leaf_remove(xfs_dabuf_t *bp, xfs_da_args_t *args)
    -{
    -	xfs_attr_leafblock_t *leaf;
    -	xfs_attr_leaf_hdr_t *hdr;
    -	xfs_attr_leaf_map_t *map;
    -	xfs_attr_leaf_entry_t *entry;
    -	int before, after, smallest, entsize;
    -	int tablesize, tmp, i;
    -	xfs_mount_t *mp;
    -
    -	leaf = bp->data;
    -	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
    -	hdr = &leaf->hdr;
    -	mp = args->trans->t_mountp;
    -	ASSERT((be16_to_cpu(hdr->count) > 0)
    -		&& (be16_to_cpu(hdr->count) < (XFS_LBSIZE(mp)/8)));
    -	ASSERT((args->index >= 0)
    -		&& (args->index < be16_to_cpu(hdr->count)));
    -	ASSERT(be16_to_cpu(hdr->firstused) >=
    -	       ((be16_to_cpu(hdr->count) * sizeof(*entry)) + sizeof(*hdr)));
    -	entry = &leaf->entries[args->index];
    -	ASSERT(be16_to_cpu(entry->nameidx) >= be16_to_cpu(hdr->firstused));
    -	ASSERT(be16_to_cpu(entry->nameidx) < XFS_LBSIZE(mp));
    -
    -	/*
    -	 * Scan through free region table:
    -	 *    check for adjacency of free'd entry with an existing one,
    -	 *    find smallest free region in case we need to replace it,
    -	 *    adjust any map that borders the entry table,
    -	 */
    -	tablesize = be16_to_cpu(hdr->count) * sizeof(xfs_attr_leaf_entry_t)
    -					+ sizeof(xfs_attr_leaf_hdr_t);
    -	map = &hdr->freemap[0];
    -	tmp = be16_to_cpu(map->size);
    -	before = after = -1;
    -	smallest = XFS_ATTR_LEAF_MAPSIZE - 1;
    -	entsize = xfs_attr_leaf_entsize(leaf, args->index);
    -	for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; map++, i++) {
    -		ASSERT(be16_to_cpu(map->base) < XFS_LBSIZE(mp));
    -		ASSERT(be16_to_cpu(map->size) < XFS_LBSIZE(mp));
    -		if (be16_to_cpu(map->base) == tablesize) {
    -			be16_add(&map->base,
    -				 -((int)sizeof(xfs_attr_leaf_entry_t)));
    -			be16_add(&map->size, sizeof(xfs_attr_leaf_entry_t));
    -		}
    -
    -		if ((be16_to_cpu(map->base) + be16_to_cpu(map->size))
    -				== be16_to_cpu(entry->nameidx)) {
    -			before = i;
    -		} else if (be16_to_cpu(map->base)
    -			== (be16_to_cpu(entry->nameidx) + entsize)) {
    -			after = i;
    -		} else if (be16_to_cpu(map->size) < tmp) {
    -			tmp = be16_to_cpu(map->size);
    -			smallest = i;
    -		}
    -	}
    -
    -	/*
    -	 * Coalesce adjacent freemap regions,
    -	 * or replace the smallest region.
    -	 */
    -	if ((before >= 0) || (after >= 0)) {
    -		if ((before >= 0) && (after >= 0)) {
    -			map = &hdr->freemap[before];
    -			be16_add(&map->size, entsize);
    -			be16_add(&map->size,
    -				 be16_to_cpu(hdr->freemap[after].size));
    -			hdr->freemap[after].base = 0;
    -			hdr->freemap[after].size = 0;
    -		} else if (before >= 0) {
    -			map = &hdr->freemap[before];
    -			be16_add(&map->size, entsize);
    -		} else {
    -			map = &hdr->freemap[after];
    -			/* both on-disk, don't endian flip twice */
    -			map->base = entry->nameidx;
    -			be16_add(&map->size, entsize);
    -		}
    -	} else {
    -		/*
    -		 * Replace smallest region (if it is smaller than free'd entry)
    -		 */
    -		map = &hdr->freemap[smallest];
    -		if (be16_to_cpu(map->size) < entsize) {
    -			map->base = cpu_to_be16(be16_to_cpu(entry->nameidx));
    -			map->size = cpu_to_be16(entsize);
    -		}
    -	}
    -
    -	/*
    -	 * Did we remove the first entry?
    -	 */
    -	if (be16_to_cpu(entry->nameidx) == be16_to_cpu(hdr->firstused))
    -		smallest = 1;
    -	else
    -		smallest = 0;
    -
    -	/*
    -	 * Compress the remaining entries and zero out the removed stuff.
    -	 */
    -	memset(XFS_ATTR_LEAF_NAME(leaf, args->index), 0, entsize);
    -	be16_add(&hdr->usedbytes, -entsize);
    -	xfs_da_log_buf(args->trans, bp,
    -	     XFS_DA_LOGRANGE(leaf, XFS_ATTR_LEAF_NAME(leaf, args->index),
    -				   entsize));
    -
    -	tmp = (be16_to_cpu(hdr->count) - args->index)
    -					* sizeof(xfs_attr_leaf_entry_t);
    -	memmove((char *)entry, (char *)(entry+1), tmp);
    -	be16_add(&hdr->count, -1);
    -	xfs_da_log_buf(args->trans, bp,
    -	    XFS_DA_LOGRANGE(leaf, entry, tmp + sizeof(*entry)));
    -	entry = &leaf->entries[be16_to_cpu(hdr->count)];
    -	memset((char *)entry, 0, sizeof(xfs_attr_leaf_entry_t));
    -
    -	/*
    -	 * If we removed the first entry, re-find the first used byte
    -	 * in the name area.  Note that if the entry was the "firstused",
    -	 * then we don't have a "hole" in our block resulting from
    -	 * removing the name.
    -	 */
    -	if (smallest) {
    -		tmp = XFS_LBSIZE(mp);
    -		entry = &leaf->entries[0];
    -		for (i = be16_to_cpu(hdr->count)-1; i >= 0; entry++, i--) {
    -			ASSERT(be16_to_cpu(entry->nameidx) >=
    -			       be16_to_cpu(hdr->firstused));
    -			ASSERT(be16_to_cpu(entry->nameidx) < XFS_LBSIZE(mp));
    -
    -			if (be16_to_cpu(entry->nameidx) < tmp)
    -				tmp = be16_to_cpu(entry->nameidx);
    -		}
    -		hdr->firstused = cpu_to_be16(tmp);
    -		if (!hdr->firstused) {
    -			hdr->firstused = cpu_to_be16(
    -					tmp - XFS_ATTR_LEAF_NAME_ALIGN);
    -		}
    -	} else {
    -		hdr->holes = 1;		/* mark as needing compaction */
    -	}
    -	xfs_da_log_buf(args->trans, bp,
    -			  XFS_DA_LOGRANGE(leaf, hdr, sizeof(*hdr)));
    -
    -	/*
    -	 * Check if leaf is less than 50% full, caller may want to
    -	 * "join" the leaf with a sibling if so.
    -	 */
    -	tmp  = sizeof(xfs_attr_leaf_hdr_t);
    -	tmp += be16_to_cpu(leaf->hdr.count) * sizeof(xfs_attr_leaf_entry_t);
    -	tmp += be16_to_cpu(leaf->hdr.usedbytes);
    -	return(tmp < mp->m_attr_magicpct); /* leaf is < 37% full */
    -}
    -
    -/*
    - * Move all the attribute list entries from drop_leaf into save_leaf.
    - */
    -void
    -xfs_attr_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
    -				       xfs_da_state_blk_t *save_blk)
    -{
    -	xfs_attr_leafblock_t *drop_leaf, *save_leaf, *tmp_leaf;
    -	xfs_attr_leaf_hdr_t *drop_hdr, *save_hdr, *tmp_hdr;
    -	xfs_mount_t *mp;
    -	char *tmpbuffer;
    -
    -	/*
    -	 * Set up environment.
    -	 */
    -	mp = state->mp;
    -	ASSERT(drop_blk->magic == XFS_ATTR_LEAF_MAGIC);
    -	ASSERT(save_blk->magic == XFS_ATTR_LEAF_MAGIC);
    -	drop_leaf = drop_blk->bp->data;
    -	save_leaf = save_blk->bp->data;
    -	ASSERT(be16_to_cpu(drop_leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
    -	ASSERT(be16_to_cpu(save_leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
    -	drop_hdr = &drop_leaf->hdr;
    -	save_hdr = &save_leaf->hdr;
    -
    -	/*
    -	 * Save last hashval from dying block for later Btree fixup.
    -	 */
    -	drop_blk->hashval = be32_to_cpu(
    -		drop_leaf->entries[be16_to_cpu(drop_leaf->hdr.count)-1].hashval);
    -
    -	/*
    -	 * Check if we need a temp buffer, or can we do it in place.
    -	 * Note that we don't check "leaf" for holes because we will
    -	 * always be dropping it, toosmall() decided that for us already.
    -	 */
    -	if (save_hdr->holes == 0) {
    -		/*
    -		 * dest leaf has no holes, so we add there.  May need
    -		 * to make some room in the entry array.
    -		 */
    -		if (xfs_attr_leaf_order(save_blk->bp, drop_blk->bp)) {
    -			xfs_attr_leaf_moveents(drop_leaf, 0, save_leaf, 0,
    -			     be16_to_cpu(drop_hdr->count), mp);
    -		} else {
    -			xfs_attr_leaf_moveents(drop_leaf, 0, save_leaf,
    -				  be16_to_cpu(save_hdr->count),
    -				  be16_to_cpu(drop_hdr->count), mp);
    -		}
    -	} else {
    -		/*
    -		 * Destination has holes, so we make a temporary copy
    -		 * of the leaf and add them both to that.
    -		 */
    -		tmpbuffer = kmem_alloc(state->blocksize, KM_SLEEP);
    -		ASSERT(tmpbuffer != NULL);
    -		memset(tmpbuffer, 0, state->blocksize);
    -		tmp_leaf = (xfs_attr_leafblock_t *)tmpbuffer;
    -		tmp_hdr = &tmp_leaf->hdr;
    -		tmp_hdr->info = save_hdr->info;	/* struct copy */
    -		tmp_hdr->count = 0;
    -		tmp_hdr->firstused = cpu_to_be16(state->blocksize);
    -		if (!tmp_hdr->firstused) {
    -			tmp_hdr->firstused = cpu_to_be16(
    -				state->blocksize - XFS_ATTR_LEAF_NAME_ALIGN);
    -		}
    -		tmp_hdr->usedbytes = 0;
    -		if (xfs_attr_leaf_order(save_blk->bp, drop_blk->bp)) {
    -			xfs_attr_leaf_moveents(drop_leaf, 0, tmp_leaf, 0,
    -				be16_to_cpu(drop_hdr->count), mp);
    -			xfs_attr_leaf_moveents(save_leaf, 0, tmp_leaf,
    -				  be16_to_cpu(tmp_leaf->hdr.count),
    -				  be16_to_cpu(save_hdr->count), mp);
    -		} else {
    -			xfs_attr_leaf_moveents(save_leaf, 0, tmp_leaf, 0,
    -				be16_to_cpu(save_hdr->count), mp);
    -			xfs_attr_leaf_moveents(drop_leaf, 0, tmp_leaf,
    -				be16_to_cpu(tmp_leaf->hdr.count),
    -				be16_to_cpu(drop_hdr->count), mp);
    -		}
    -		memcpy((char *)save_leaf, (char *)tmp_leaf, state->blocksize);
    -		kmem_free(tmpbuffer, state->blocksize);
    -	}
    -
    -	xfs_da_log_buf(state->args->trans, save_blk->bp, 0,
    -					   state->blocksize - 1);
    -
    -	/*
    -	 * Copy out last hashval in each block for B-tree code.
    -	 */
    -	save_blk->hashval = be32_to_cpu(
    -		save_leaf->entries[be16_to_cpu(save_leaf->hdr.count)-1].hashval);
    -}
    -
    -/*========================================================================
    - * Routines used for finding things in the Btree.
    - *========================================================================*/
    -
    -/*
    - * Look up a name in a leaf attribute list structure.
    - * This is the internal routine, it uses the caller's buffer.
    - *
    - * Note that duplicate keys are allowed, but only check within the
    - * current leaf node.  The Btree code must check in adjacent leaf nodes.
    - *
    - * Return in args->index the index into the entry[] array of either
    - * the found entry, or where the entry should have been (insert before
    - * that entry).
    - *
    - * Don't change the args->value unless we find the attribute.
    - */
    -int
    -xfs_attr_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args)
    -{
    -	xfs_attr_leafblock_t *leaf;
    -	xfs_attr_leaf_entry_t *entry;
    -	xfs_attr_leaf_name_local_t *name_loc;
    -	xfs_attr_leaf_name_remote_t *name_rmt;
    -	int probe, span;
    -	xfs_dahash_t hashval;
    -
    -	leaf = bp->data;
    -	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
    -	ASSERT(be16_to_cpu(leaf->hdr.count)
    -					< (XFS_LBSIZE(args->dp->i_mount)/8));
    -
    -	/*
    -	 * Binary search.  (note: small blocks will skip this loop)
    -	 */
    -	hashval = args->hashval;
    -	probe = span = be16_to_cpu(leaf->hdr.count) / 2;
    -	for (entry = &leaf->entries[probe]; span > 4;
    -		   entry = &leaf->entries[probe]) {
    -		span /= 2;
    -		if (be32_to_cpu(entry->hashval) < hashval)
    -			probe += span;
    -		else if (be32_to_cpu(entry->hashval) > hashval)
    -			probe -= span;
    -		else
    -			break;
    -	}
    -	ASSERT((probe >= 0) && 
    -	       (!leaf->hdr.count
    -	       || (probe < be16_to_cpu(leaf->hdr.count))));
    -	ASSERT((span <= 4) || (be32_to_cpu(entry->hashval) == hashval));
    -
    -	/*
    -	 * Since we may have duplicate hashval's, find the first matching
    -	 * hashval in the leaf.
    -	 */
    -	while ((probe > 0) && (be32_to_cpu(entry->hashval) >= hashval)) {
    -		entry--;
    -		probe--;
    -	}
    -	while ((probe < be16_to_cpu(leaf->hdr.count)) &&
    -	       (be32_to_cpu(entry->hashval) < hashval)) {
    -		entry++;
    -		probe++;
    -	}
    -	if ((probe == be16_to_cpu(leaf->hdr.count)) ||
    -	    (be32_to_cpu(entry->hashval) != hashval)) {
    -		args->index = probe;
    -		return(XFS_ERROR(ENOATTR));
    -	}
    -
    -	/*
    -	 * Duplicate keys may be present, so search all of them for a match.
    -	 */
    -	for (  ; (probe < be16_to_cpu(leaf->hdr.count)) &&
    -			(be32_to_cpu(entry->hashval) == hashval);
    -			entry++, probe++) {
    -/*
    - * GROT: Add code to remove incomplete entries.
    - */
    -		/*
    -		 * If we are looking for INCOMPLETE entries, show only those.
    -		 * If we are looking for complete entries, show only those.
    -		 */
    -		if ((args->flags & XFS_ATTR_INCOMPLETE) !=
    -		    (entry->flags & XFS_ATTR_INCOMPLETE)) {
    -			continue;
    -		}
    -		if (entry->flags & XFS_ATTR_LOCAL) {
    -			name_loc = XFS_ATTR_LEAF_NAME_LOCAL(leaf, probe);
    -			if (name_loc->namelen != args->namelen)
    -				continue;
    -			if (memcmp(args->name, (char *)name_loc->nameval,
    -					     args->namelen) != 0)
    -				continue;
    -			if (((args->flags & ATTR_SECURE) != 0) !=
    -			    ((entry->flags & XFS_ATTR_SECURE) != 0))
    -				continue;
    -			if (((args->flags & ATTR_ROOT) != 0) !=
    -			    ((entry->flags & XFS_ATTR_ROOT) != 0))
    -				continue;
    -			args->index = probe;
    -			return(XFS_ERROR(EEXIST));
    -		} else {
    -			name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf, probe);
    -			if (name_rmt->namelen != args->namelen)
    -				continue;
    -			if (memcmp(args->name, (char *)name_rmt->name,
    -					     args->namelen) != 0)
    -				continue;
    -			if (((args->flags & ATTR_SECURE) != 0) !=
    -			    ((entry->flags & XFS_ATTR_SECURE) != 0))
    -				continue;
    -			if (((args->flags & ATTR_ROOT) != 0) !=
    -			    ((entry->flags & XFS_ATTR_ROOT) != 0))
    -				continue;
    -			args->index = probe;
    -			args->rmtblkno = be32_to_cpu(name_rmt->valueblk);
    -			args->rmtblkcnt = XFS_B_TO_FSB(args->dp->i_mount,
    -						   be32_to_cpu(name_rmt->valuelen));
    -			return(XFS_ERROR(EEXIST));
    -		}
    -	}
    -	args->index = probe;
    -	return(XFS_ERROR(ENOATTR));
    -}
    -
    -/*
    - * Get the value associated with an attribute name from a leaf attribute
    - * list structure.
    - */
    -int
    -xfs_attr_leaf_getvalue(xfs_dabuf_t *bp, xfs_da_args_t *args)
    -{
    -	int valuelen;
    -	xfs_attr_leafblock_t *leaf;
    -	xfs_attr_leaf_entry_t *entry;
    -	xfs_attr_leaf_name_local_t *name_loc;
    -	xfs_attr_leaf_name_remote_t *name_rmt;
    -
    -	leaf = bp->data;
    -	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
    -	ASSERT(be16_to_cpu(leaf->hdr.count)
    -					< (XFS_LBSIZE(args->dp->i_mount)/8));
    -	ASSERT(args->index < be16_to_cpu(leaf->hdr.count));
    -
    -	entry = &leaf->entries[args->index];
    -	if (entry->flags & XFS_ATTR_LOCAL) {
    -		name_loc = XFS_ATTR_LEAF_NAME_LOCAL(leaf, args->index);
    -		ASSERT(name_loc->namelen == args->namelen);
    -		ASSERT(memcmp(args->name, name_loc->nameval, args->namelen) == 0);
    -		valuelen = be16_to_cpu(name_loc->valuelen);
    -		if (args->flags & ATTR_KERNOVAL) {
    -			args->valuelen = valuelen;
    -			return(0);
    -		}
    -		if (args->valuelen < valuelen) {
    -			args->valuelen = valuelen;
    -			return(XFS_ERROR(ERANGE));
    -		}
    -		args->valuelen = valuelen;
    -		memcpy(args->value, &name_loc->nameval[args->namelen], valuelen);
    -	} else {
    -		name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf, args->index);
    -		ASSERT(name_rmt->namelen == args->namelen);
    -		ASSERT(memcmp(args->name, name_rmt->name, args->namelen) == 0);
    -		valuelen = be32_to_cpu(name_rmt->valuelen);
    -		args->rmtblkno = be32_to_cpu(name_rmt->valueblk);
    -		args->rmtblkcnt = XFS_B_TO_FSB(args->dp->i_mount, valuelen);
    -		if (args->flags & ATTR_KERNOVAL) {
    -			args->valuelen = valuelen;
    -			return(0);
    -		}
    -		if (args->valuelen < valuelen) {
    -			args->valuelen = valuelen;
    -			return(XFS_ERROR(ERANGE));
    -		}
    -		args->valuelen = valuelen;
    -	}
    -	return(0);
    -}
    -
    -/*========================================================================
    - * Utility routines.
    - *========================================================================*/
    -
    -/*
    - * Move the indicated entries from one leaf to another.
    - * NOTE: this routine modifies both source and destination leaves.
    - */
    -/*ARGSUSED*/
    -STATIC void
    -xfs_attr_leaf_moveents(xfs_attr_leafblock_t *leaf_s, int start_s,
    -			xfs_attr_leafblock_t *leaf_d, int start_d,
    -			int count, xfs_mount_t *mp)
    -{
    -	xfs_attr_leaf_hdr_t *hdr_s, *hdr_d;
    -	xfs_attr_leaf_entry_t *entry_s, *entry_d;
    -	int desti, tmp, i;
    -
    -	/*
    -	 * Check for nothing to do.
    -	 */
    -	if (count == 0)
    -		return;
    -
    -	/*
    -	 * Set up environment.
    -	 */
    -	ASSERT(be16_to_cpu(leaf_s->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
    -	ASSERT(be16_to_cpu(leaf_d->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
    -	hdr_s = &leaf_s->hdr;
    -	hdr_d = &leaf_d->hdr;
    -	ASSERT((be16_to_cpu(hdr_s->count) > 0) &&
    -	       (be16_to_cpu(hdr_s->count) < (XFS_LBSIZE(mp)/8)));
    -	ASSERT(be16_to_cpu(hdr_s->firstused) >=
    -		((be16_to_cpu(hdr_s->count)
    -					* sizeof(*entry_s))+sizeof(*hdr_s)));
    -	ASSERT(be16_to_cpu(hdr_d->count) < (XFS_LBSIZE(mp)/8));
    -	ASSERT(be16_to_cpu(hdr_d->firstused) >=
    -		((be16_to_cpu(hdr_d->count)
    -					* sizeof(*entry_d))+sizeof(*hdr_d)));
    -
    -	ASSERT(start_s < be16_to_cpu(hdr_s->count));
    -	ASSERT(start_d <= be16_to_cpu(hdr_d->count));
    -	ASSERT(count <= be16_to_cpu(hdr_s->count));
    -
    -	/*
    -	 * Move the entries in the destination leaf up to make a hole?
    -	 */
    -	if (start_d < be16_to_cpu(hdr_d->count)) {
    -		tmp  = be16_to_cpu(hdr_d->count) - start_d;
    -		tmp *= sizeof(xfs_attr_leaf_entry_t);
    -		entry_s = &leaf_d->entries[start_d];
    -		entry_d = &leaf_d->entries[start_d + count];
    -		memmove((char *)entry_d, (char *)entry_s, tmp);
    -	}
    -
    -	/*
    -	 * Copy all entry's in the same (sorted) order,
    -	 * but allocate attribute info packed and in sequence.
    -	 */
    -	entry_s = &leaf_s->entries[start_s];
    -	entry_d = &leaf_d->entries[start_d];
    -	desti = start_d;
    -	for (i = 0; i < count; entry_s++, entry_d++, desti++, i++) {
    -		ASSERT(be16_to_cpu(entry_s->nameidx)
    -				>= be16_to_cpu(hdr_s->firstused));
    -		tmp = xfs_attr_leaf_entsize(leaf_s, start_s + i);
    -#ifdef GROT
    -		/*
    -		 * Code to drop INCOMPLETE entries.  Difficult to use as we
    -		 * may also need to change the insertion index.  Code turned
    -		 * off for 6.2, should be revisited later.
    -		 */
    -		if (entry_s->flags & XFS_ATTR_INCOMPLETE) { /* skip partials? */
    -			memset(XFS_ATTR_LEAF_NAME(leaf_s, start_s + i), 0, tmp);
    -			be16_add(&hdr_s->usedbytes, -tmp);
    -			be16_add(&hdr_s->count, -1);
    -			entry_d--;	/* to compensate for ++ in loop hdr */
    -			desti--;
    -			if ((start_s + i) < offset)
    -				result++;	/* insertion index adjustment */
    -		} else {
    -#endif /* GROT */
    -			be16_add(&hdr_d->firstused, -tmp);
    -			/* both on-disk, don't endian flip twice */
    -			entry_d->hashval = entry_s->hashval;
    -			/* both on-disk, don't endian flip twice */
    -			entry_d->nameidx = hdr_d->firstused;
    -			entry_d->flags = entry_s->flags;
    -			ASSERT(be16_to_cpu(entry_d->nameidx) + tmp
    -							<= XFS_LBSIZE(mp));
    -			memmove(XFS_ATTR_LEAF_NAME(leaf_d, desti),
    -				XFS_ATTR_LEAF_NAME(leaf_s, start_s + i), tmp);
    -			ASSERT(be16_to_cpu(entry_s->nameidx) + tmp
    -							<= XFS_LBSIZE(mp));
    -			memset(XFS_ATTR_LEAF_NAME(leaf_s, start_s + i), 0, tmp);
    -			be16_add(&hdr_s->usedbytes, -tmp);
    -			be16_add(&hdr_d->usedbytes, tmp);
    -			be16_add(&hdr_s->count, -1);
    -			be16_add(&hdr_d->count, 1);
    -			tmp = be16_to_cpu(hdr_d->count)
    -						* sizeof(xfs_attr_leaf_entry_t)
    -						+ sizeof(xfs_attr_leaf_hdr_t);
    -			ASSERT(be16_to_cpu(hdr_d->firstused) >= tmp);
    -#ifdef GROT
    -		}
    -#endif /* GROT */
    -	}
    -
    -	/*
    -	 * Zero out the entries we just copied.
    -	 */
    -	if (start_s == be16_to_cpu(hdr_s->count)) {
    -		tmp = count * sizeof(xfs_attr_leaf_entry_t);
    -		entry_s = &leaf_s->entries[start_s];
    -		ASSERT(((char *)entry_s + tmp) <=
    -		       ((char *)leaf_s + XFS_LBSIZE(mp)));
    -		memset((char *)entry_s, 0, tmp);
    -	} else {
    -		/*
    -		 * Move the remaining entries down to fill the hole,
    -		 * then zero the entries at the top.
    -		 */
    -		tmp  = be16_to_cpu(hdr_s->count) - count;
    -		tmp *= sizeof(xfs_attr_leaf_entry_t);
    -		entry_s = &leaf_s->entries[start_s + count];
    -		entry_d = &leaf_s->entries[start_s];
    -		memmove((char *)entry_d, (char *)entry_s, tmp);
    -
    -		tmp = count * sizeof(xfs_attr_leaf_entry_t);
    -		entry_s = &leaf_s->entries[be16_to_cpu(hdr_s->count)];
    -		ASSERT(((char *)entry_s + tmp) <=
    -		       ((char *)leaf_s + XFS_LBSIZE(mp)));
    -		memset((char *)entry_s, 0, tmp);
    -	}
    -
    -	/*
    -	 * Fill in the freemap information
    -	 */
    -	hdr_d->freemap[0].base = cpu_to_be16(sizeof(xfs_attr_leaf_hdr_t));
    -	be16_add(&hdr_d->freemap[0].base, be16_to_cpu(hdr_d->count) *
    -			sizeof(xfs_attr_leaf_entry_t));
    -	hdr_d->freemap[0].size = cpu_to_be16(be16_to_cpu(hdr_d->firstused)
    -			      - be16_to_cpu(hdr_d->freemap[0].base));
    -	hdr_d->freemap[1].base = 0;
    -	hdr_d->freemap[2].base = 0;
    -	hdr_d->freemap[1].size = 0;
    -	hdr_d->freemap[2].size = 0;
    -	hdr_s->holes = 1;	/* leaf may not be compact */
    -}
    -
    -/*
    - * Compare two leaf blocks "order".
    - * Return 0 unless leaf2 should go before leaf1.
    - */
    -int
    -xfs_attr_leaf_order(xfs_dabuf_t *leaf1_bp, xfs_dabuf_t *leaf2_bp)
    -{
    -	xfs_attr_leafblock_t *leaf1, *leaf2;
    -
    -	leaf1 = leaf1_bp->data;
    -	leaf2 = leaf2_bp->data;
    -	ASSERT((be16_to_cpu(leaf1->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC) &&
    -	       (be16_to_cpu(leaf2->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC));
    -	if ((be16_to_cpu(leaf1->hdr.count) > 0) &&
    -	    (be16_to_cpu(leaf2->hdr.count) > 0) &&
    -	    ((be32_to_cpu(leaf2->entries[0].hashval) <
    -	      be32_to_cpu(leaf1->entries[0].hashval)) ||
    -	     (be32_to_cpu(leaf2->entries[
    -			be16_to_cpu(leaf2->hdr.count)-1].hashval) <
    -	      be32_to_cpu(leaf1->entries[
    -			be16_to_cpu(leaf1->hdr.count)-1].hashval)))) {
    -		return(1);
    -	}
    -	return(0);
    -}
    -
    -/*
    - * Pick up the last hashvalue from a leaf block.
    - */
    -xfs_dahash_t
    -xfs_attr_leaf_lasthash(xfs_dabuf_t *bp, int *count)
    -{
    -	xfs_attr_leafblock_t *leaf;
    -
    -	leaf = bp->data;
    -	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
    -	if (count)
    -		*count = be16_to_cpu(leaf->hdr.count);
    -	if (!leaf->hdr.count)
    -		return(0);
    -	return be32_to_cpu(leaf->entries[be16_to_cpu(leaf->hdr.count)-1].hashval);
    -}
    -
    -/*
    - * Calculate the number of bytes used to store the indicated attribute
    - * (whether local or remote only calculate bytes in this block).
    - */
    -STATIC int
    -xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index)
    -{
    -	xfs_attr_leaf_name_local_t *name_loc;
    -	xfs_attr_leaf_name_remote_t *name_rmt;
    -	int size;
    -
    -	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
    -	if (leaf->entries[index].flags & XFS_ATTR_LOCAL) {
    -		name_loc = XFS_ATTR_LEAF_NAME_LOCAL(leaf, index);
    -		size = XFS_ATTR_LEAF_ENTSIZE_LOCAL(name_loc->namelen,
    -						   be16_to_cpu(name_loc->valuelen));
    -	} else {
    -		name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf, index);
    -		size = XFS_ATTR_LEAF_ENTSIZE_REMOTE(name_rmt->namelen);
    -	}
    -	return(size);
    -}
    -
    -/*
    - * Calculate the number of bytes that would be required to store the new
    - * attribute (whether local or remote only calculate bytes in this block).
    - * This routine decides as a side effect whether the attribute will be
    - * a "local" or a "remote" attribute.
    - */
    -int
    -xfs_attr_leaf_newentsize(int namelen, int valuelen, int blocksize, int *local)
    -{
    -	int size;
    -
    -	size = XFS_ATTR_LEAF_ENTSIZE_LOCAL(namelen, valuelen);
    -	if (size < XFS_ATTR_LEAF_ENTSIZE_LOCAL_MAX(blocksize)) {
    -		if (local) {
    -			*local = 1;
    -		}
    -	} else {
    -		size = XFS_ATTR_LEAF_ENTSIZE_REMOTE(namelen);
    -		if (local) {
    -			*local = 0;
    -		}
    -	}
    -	return(size);
    -}
    -
    -/*
    - * Copy out attribute list entries for attr_list(), for leaf attribute lists.
    - */
    -int
    -xfs_attr_leaf_list_int(xfs_dabuf_t *bp, xfs_attr_list_context_t *context)
    -{
    -	attrlist_cursor_kern_t *cursor;
    -	xfs_attr_leafblock_t *leaf;
    -	xfs_attr_leaf_entry_t *entry;
    -	xfs_attr_leaf_name_local_t *name_loc;
    -	xfs_attr_leaf_name_remote_t *name_rmt;
    -	int retval, i;
    -
    -	ASSERT(bp != NULL);
    -	leaf = bp->data;
    -	cursor = context->cursor;
    -	cursor->initted = 1;
    -
    -	xfs_attr_trace_l_cl("blk start", context, leaf);
    -
    -	/*
    -	 * Re-find our place in the leaf block if this is a new syscall.
    -	 */
    -	if (context->resynch) {
    -		entry = &leaf->entries[0];
    -		for (i = 0; i < be16_to_cpu(leaf->hdr.count); entry++, i++) {
    -			if (be32_to_cpu(entry->hashval) == cursor->hashval) {
    -				if (cursor->offset == context->dupcnt) {
    -					context->dupcnt = 0;
    -					break;
    -				}
    -				context->dupcnt++;
    -			} else if (be32_to_cpu(entry->hashval) >
    -					cursor->hashval) {
    -				context->dupcnt = 0;
    -				break;
    -			}
    -		}
    -		if (i == be16_to_cpu(leaf->hdr.count)) {
    -			xfs_attr_trace_l_c("not found", context);
    -			return(0);
    -		}
    -	} else {
    -		entry = &leaf->entries[0];
    -		i = 0;
    -	}
    -	context->resynch = 0;
    -
    -	/*
    -	 * We have found our place, start copying out the new attributes.
    -	 */
    -	retval = 0;
    -	for (  ; (i < be16_to_cpu(leaf->hdr.count))
    -	     && (retval == 0); entry++, i++) {
    -		attrnames_t	*namesp;
    -
    -		if (be32_to_cpu(entry->hashval) != cursor->hashval) {
    -			cursor->hashval = be32_to_cpu(entry->hashval);
    -			cursor->offset = 0;
    -		}
    -
    -		if (entry->flags & XFS_ATTR_INCOMPLETE)
    -			continue;		/* skip incomplete entries */
    -		if (((context->flags & ATTR_SECURE) != 0) !=
    -		    ((entry->flags & XFS_ATTR_SECURE) != 0) &&
    -		    !(context->flags & ATTR_KERNORMALS))
    -			continue;		/* skip non-matching entries */
    -		if (((context->flags & ATTR_ROOT) != 0) !=
    -		    ((entry->flags & XFS_ATTR_ROOT) != 0) &&
    -		    !(context->flags & ATTR_KERNROOTLS))
    -			continue;		/* skip non-matching entries */
    -
    -		namesp = (entry->flags & XFS_ATTR_SECURE) ? &attr_secure :
    -			((entry->flags & XFS_ATTR_ROOT) ? &attr_trusted :
    -			  &attr_user);
    -
    -		if (entry->flags & XFS_ATTR_LOCAL) {
    -			name_loc = XFS_ATTR_LEAF_NAME_LOCAL(leaf, i);
    -			if (context->flags & ATTR_KERNOVAL) {
    -				ASSERT(context->flags & ATTR_KERNAMELS);
    -				context->count += namesp->attr_namelen +
    -						(int)name_loc->namelen + 1;
    -			} else {
    -				retval = xfs_attr_put_listent(context, namesp,
    -					(char *)name_loc->nameval,
    -					(int)name_loc->namelen,
    -					be16_to_cpu(name_loc->valuelen));
    -			}
    -		} else {
    -			name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf, i);
    -			if (context->flags & ATTR_KERNOVAL) {
    -				ASSERT(context->flags & ATTR_KERNAMELS);
    -				context->count += namesp->attr_namelen +
    -						(int)name_rmt->namelen + 1;
    -			} else {
    -				retval = xfs_attr_put_listent(context, namesp,
    -					(char *)name_rmt->name,
    -					(int)name_rmt->namelen,
    -					be32_to_cpu(name_rmt->valuelen));
    -			}
    -		}
    -		if (retval == 0) {
    -			cursor->offset++;
    -		}
    -	}
    -	xfs_attr_trace_l_cl("blk end", context, leaf);
    -	return(retval);
    -}
    -
    -#define	ATTR_ENTBASESIZE		/* minimum bytes used by an attr */ \
    -	(((struct attrlist_ent *) 0)->a_name - (char *) 0)
    -#define	ATTR_ENTSIZE(namelen)		/* actual bytes used by an attr */ \
    -	((ATTR_ENTBASESIZE + (namelen) + 1 + sizeof(u_int32_t)-1) \
    -	 & ~(sizeof(u_int32_t)-1))
    -
    -/*
    - * Format an attribute and copy it out to the user's buffer.
    - * Take care to check values and protect against them changing later,
    - * we may be reading them directly out of a user buffer.
    - */
    -/*ARGSUSED*/
    -STATIC int
    -xfs_attr_put_listent(xfs_attr_list_context_t *context,
    -		     attrnames_t *namesp, char *name, int namelen, int valuelen)
    -{
    -	attrlist_ent_t *aep;
    -	int arraytop;
    -
    -	ASSERT(!(context->flags & ATTR_KERNOVAL));
    -	if (context->flags & ATTR_KERNAMELS) {
    -		char *offset;
    -
    -		ASSERT(context->count >= 0);
    -
    -		arraytop = context->count + namesp->attr_namelen + namelen + 1;
    -		if (arraytop > context->firstu) {
    -			context->count = -1;	/* insufficient space */
    -			return(1);
    -		}
    -		offset = (char *)context->alist + context->count;
    -		strncpy(offset, namesp->attr_name, namesp->attr_namelen);
    -		offset += namesp->attr_namelen;
    -		strncpy(offset, name, namelen);			/* real name */
    -		offset += namelen;
    -		*offset = '\0';
    -		context->count += namesp->attr_namelen + namelen + 1;
    -		return(0);
    -	}
    -
    -	ASSERT(context->count >= 0);
    -	ASSERT(context->count < (ATTR_MAX_VALUELEN/8));
    -	ASSERT(context->firstu >= sizeof(*context->alist));
    -	ASSERT(context->firstu <= context->bufsize);
    -
    -	arraytop = sizeof(*context->alist) +
    -			context->count * sizeof(context->alist->al_offset[0]);
    -	context->firstu -= ATTR_ENTSIZE(namelen);
    -	if (context->firstu < arraytop) {
    -		xfs_attr_trace_l_c("buffer full", context);
    -		context->alist->al_more = 1;
    -		return(1);
    -	}
    -
    -	aep = (attrlist_ent_t *)&(((char *)context->alist)[ context->firstu ]);
    -	aep->a_valuelen = valuelen;
    -	memcpy(aep->a_name, name, namelen);
    -	aep->a_name[ namelen ] = 0;
    -	context->alist->al_offset[ context->count++ ] = context->firstu;
    -	context->alist->al_count = context->count;
    -	xfs_attr_trace_l_c("add", context);
    -	return(0);
    -}
    -
    -/*========================================================================
    - * Manage the INCOMPLETE flag in a leaf entry
    - *========================================================================*/
    -
    -/*
    - * Clear the INCOMPLETE flag on an entry in a leaf block.
    - */
    -int
    -xfs_attr_leaf_clearflag(xfs_da_args_t *args)
    -{
    -	xfs_attr_leafblock_t *leaf;
    -	xfs_attr_leaf_entry_t *entry;
    -	xfs_attr_leaf_name_remote_t *name_rmt;
    -	xfs_dabuf_t *bp;
    -	int error;
    -#ifdef DEBUG
    -	xfs_attr_leaf_name_local_t *name_loc;
    -	int namelen;
    -	char *name;
    -#endif /* DEBUG */
    -
    -	/*
    -	 * Set up the operation.
    -	 */
    -	error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1, &bp,
    -					     XFS_ATTR_FORK);
    -	if (error) {
    -		return(error);
    -	}
    -	ASSERT(bp != NULL);
    -
    -	leaf = bp->data;
    -	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
    -	ASSERT(args->index < be16_to_cpu(leaf->hdr.count));
    -	ASSERT(args->index >= 0);
    -	entry = &leaf->entries[ args->index ];
    -	ASSERT(entry->flags & XFS_ATTR_INCOMPLETE);
    -
    -#ifdef DEBUG
    -	if (entry->flags & XFS_ATTR_LOCAL) {
    -		name_loc = XFS_ATTR_LEAF_NAME_LOCAL(leaf, args->index);
    -		namelen = name_loc->namelen;
    -		name = (char *)name_loc->nameval;
    -	} else {
    -		name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf, args->index);
    -		namelen = name_rmt->namelen;
    -		name = (char *)name_rmt->name;
    -	}
    -	ASSERT(be32_to_cpu(entry->hashval) == args->hashval);
    -	ASSERT(namelen == args->namelen);
    -	ASSERT(memcmp(name, args->name, namelen) == 0);
    -#endif /* DEBUG */
    -
    -	entry->flags &= ~XFS_ATTR_INCOMPLETE;
    -	xfs_da_log_buf(args->trans, bp,
    -			 XFS_DA_LOGRANGE(leaf, entry, sizeof(*entry)));
    -
    -	if (args->rmtblkno) {
    -		ASSERT((entry->flags & XFS_ATTR_LOCAL) == 0);
    -		name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf, args->index);
    -		name_rmt->valueblk = cpu_to_be32(args->rmtblkno);
    -		name_rmt->valuelen = cpu_to_be32(args->valuelen);
    -		xfs_da_log_buf(args->trans, bp,
    -			 XFS_DA_LOGRANGE(leaf, name_rmt, sizeof(*name_rmt)));
    -	}
    -	xfs_da_buf_done(bp);
    -
    -	/*
    -	 * Commit the flag value change and start the next trans in series.
    -	 */
    -	error = xfs_attr_rolltrans(&args->trans, args->dp);
    -
    -	return(error);
    -}
    -
    -/*
    - * Set the INCOMPLETE flag on an entry in a leaf block.
    - */
    -int
    -xfs_attr_leaf_setflag(xfs_da_args_t *args)
    -{
    -	xfs_attr_leafblock_t *leaf;
    -	xfs_attr_leaf_entry_t *entry;
    -	xfs_attr_leaf_name_remote_t *name_rmt;
    -	xfs_dabuf_t *bp;
    -	int error;
    -
    -	/*
    -	 * Set up the operation.
    -	 */
    -	error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1, &bp,
    -					     XFS_ATTR_FORK);
    -	if (error) {
    -		return(error);
    -	}
    -	ASSERT(bp != NULL);
    -
    -	leaf = bp->data;
    -	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
    -	ASSERT(args->index < be16_to_cpu(leaf->hdr.count));
    -	ASSERT(args->index >= 0);
    -	entry = &leaf->entries[ args->index ];
    -
    -	ASSERT((entry->flags & XFS_ATTR_INCOMPLETE) == 0);
    -	entry->flags |= XFS_ATTR_INCOMPLETE;
    -	xfs_da_log_buf(args->trans, bp,
    -			XFS_DA_LOGRANGE(leaf, entry, sizeof(*entry)));
    -	if ((entry->flags & XFS_ATTR_LOCAL) == 0) {
    -		name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf, args->index);
    -		name_rmt->valueblk = 0;
    -		name_rmt->valuelen = 0;
    -		xfs_da_log_buf(args->trans, bp,
    -			 XFS_DA_LOGRANGE(leaf, name_rmt, sizeof(*name_rmt)));
    -	}
    -	xfs_da_buf_done(bp);
    -
    -	/*
    -	 * Commit the flag value change and start the next trans in series.
    -	 */
    -	error = xfs_attr_rolltrans(&args->trans, args->dp);
    -
    -	return(error);
    -}
    -
    -/*
    - * In a single transaction, clear the INCOMPLETE flag on the leaf entry
    - * given by args->blkno/index and set the INCOMPLETE flag on the leaf
    - * entry given by args->blkno2/index2.
    - *
    - * Note that they could be in different blocks, or in the same block.
    - */
    -int
    -xfs_attr_leaf_flipflags(xfs_da_args_t *args)
    -{
    -	xfs_attr_leafblock_t *leaf1, *leaf2;
    -	xfs_attr_leaf_entry_t *entry1, *entry2;
    -	xfs_attr_leaf_name_remote_t *name_rmt;
    -	xfs_dabuf_t *bp1, *bp2;
    -	int error;
    -#ifdef DEBUG
    -	xfs_attr_leaf_name_local_t *name_loc;
    -	int namelen1, namelen2;
    -	char *name1, *name2;
    -#endif /* DEBUG */
    -
    -	/*
    -	 * Read the block containing the "old" attr
    -	 */
    -	error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1, &bp1,
    -					     XFS_ATTR_FORK);
    -	if (error) {
    -		return(error);
    -	}
    -	ASSERT(bp1 != NULL);
    -
    -	/*
    -	 * Read the block containing the "new" attr, if it is different
    -	 */
    -	if (args->blkno2 != args->blkno) {
    -		error = xfs_da_read_buf(args->trans, args->dp, args->blkno2,
    -					-1, &bp2, XFS_ATTR_FORK);
    -		if (error) {
    -			return(error);
    -		}
    -		ASSERT(bp2 != NULL);
    -	} else {
    -		bp2 = bp1;
    -	}
    -
    -	leaf1 = bp1->data;
    -	ASSERT(be16_to_cpu(leaf1->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
    -	ASSERT(args->index < be16_to_cpu(leaf1->hdr.count));
    -	ASSERT(args->index >= 0);
    -	entry1 = &leaf1->entries[ args->index ];
    -
    -	leaf2 = bp2->data;
    -	ASSERT(be16_to_cpu(leaf2->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
    -	ASSERT(args->index2 < be16_to_cpu(leaf2->hdr.count));
    -	ASSERT(args->index2 >= 0);
    -	entry2 = &leaf2->entries[ args->index2 ];
    -
    -#ifdef DEBUG
    -	if (entry1->flags & XFS_ATTR_LOCAL) {
    -		name_loc = XFS_ATTR_LEAF_NAME_LOCAL(leaf1, args->index);
    -		namelen1 = name_loc->namelen;
    -		name1 = (char *)name_loc->nameval;
    -	} else {
    -		name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf1, args->index);
    -		namelen1 = name_rmt->namelen;
    -		name1 = (char *)name_rmt->name;
    -	}
    -	if (entry2->flags & XFS_ATTR_LOCAL) {
    -		name_loc = XFS_ATTR_LEAF_NAME_LOCAL(leaf2, args->index2);
    -		namelen2 = name_loc->namelen;
    -		name2 = (char *)name_loc->nameval;
    -	} else {
    -		name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf2, args->index2);
    -		namelen2 = name_rmt->namelen;
    -		name2 = (char *)name_rmt->name;
    -	}
    -	ASSERT(be32_to_cpu(entry1->hashval) == be32_to_cpu(entry2->hashval));
    -	ASSERT(namelen1 == namelen2);
    -	ASSERT(memcmp(name1, name2, namelen1) == 0);
    -#endif /* DEBUG */
    -
    -	ASSERT(entry1->flags & XFS_ATTR_INCOMPLETE);
    -	ASSERT((entry2->flags & XFS_ATTR_INCOMPLETE) == 0);
    -
    -	entry1->flags &= ~XFS_ATTR_INCOMPLETE;
    -	xfs_da_log_buf(args->trans, bp1,
    -			  XFS_DA_LOGRANGE(leaf1, entry1, sizeof(*entry1)));
    -	if (args->rmtblkno) {
    -		ASSERT((entry1->flags & XFS_ATTR_LOCAL) == 0);
    -		name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf1, args->index);
    -		name_rmt->valueblk = cpu_to_be32(args->rmtblkno);
    -		name_rmt->valuelen = cpu_to_be32(args->valuelen);
    -		xfs_da_log_buf(args->trans, bp1,
    -			 XFS_DA_LOGRANGE(leaf1, name_rmt, sizeof(*name_rmt)));
    -	}
    -
    -	entry2->flags |= XFS_ATTR_INCOMPLETE;
    -	xfs_da_log_buf(args->trans, bp2,
    -			  XFS_DA_LOGRANGE(leaf2, entry2, sizeof(*entry2)));
    -	if ((entry2->flags & XFS_ATTR_LOCAL) == 0) {
    -		name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf2, args->index2);
    -		name_rmt->valueblk = 0;
    -		name_rmt->valuelen = 0;
    -		xfs_da_log_buf(args->trans, bp2,
    -			 XFS_DA_LOGRANGE(leaf2, name_rmt, sizeof(*name_rmt)));
    -	}
    -	xfs_da_buf_done(bp1);
    -	if (bp1 != bp2)
    -		xfs_da_buf_done(bp2);
    -
    -	/*
    -	 * Commit the flag value change and start the next trans in series.
    -	 */
    -	error = xfs_attr_rolltrans(&args->trans, args->dp);
    -
    -	return(error);
    -}
    -
    -/*========================================================================
    - * Indiscriminately delete the entire attribute fork
    - *========================================================================*/
    -
    -/*
    - * Recurse (gasp!) through the attribute nodes until we find leaves.
    - * We're doing a depth-first traversal in order to invalidate everything.
    - */
    -int
    -xfs_attr_root_inactive(xfs_trans_t **trans, xfs_inode_t *dp)
    -{
    -	xfs_da_blkinfo_t *info;
    -	xfs_daddr_t blkno;
    -	xfs_dabuf_t *bp;
    -	int error;
    -
    -	/*
    -	 * Read block 0 to see what we have to work with.
    -	 * We only get here if we have extents, since we remove
    -	 * the extents in reverse order the extent containing
    -	 * block 0 must still be there.
    -	 */
    -	error = xfs_da_read_buf(*trans, dp, 0, -1, &bp, XFS_ATTR_FORK);
    -	if (error)
    -		return(error);
    -	blkno = xfs_da_blkno(bp);
    -
    -	/*
    -	 * Invalidate the tree, even if the "tree" is only a single leaf block.
    -	 * This is a depth-first traversal!
    -	 */
    -	info = bp->data;
    -	if (be16_to_cpu(info->magic) == XFS_DA_NODE_MAGIC) {
    -		error = xfs_attr_node_inactive(trans, dp, bp, 1);
    -	} else if (be16_to_cpu(info->magic) == XFS_ATTR_LEAF_MAGIC) {
    -		error = xfs_attr_leaf_inactive(trans, dp, bp);
    -	} else {
    -		error = XFS_ERROR(EIO);
    -		xfs_da_brelse(*trans, bp);
    -	}
    -	if (error)
    -		return(error);
    -
    -	/*
    -	 * Invalidate the incore copy of the root block.
    -	 */
    -	error = xfs_da_get_buf(*trans, dp, 0, blkno, &bp, XFS_ATTR_FORK);
    -	if (error)
    -		return(error);
    -	xfs_da_binval(*trans, bp);	/* remove from cache */
    -	/*
    -	 * Commit the invalidate and start the next transaction.
    -	 */
    -	error = xfs_attr_rolltrans(trans, dp);
    -
    -	return (error);
    -}
    -
    -/*
    - * Recurse (gasp!) through the attribute nodes until we find leaves.
    - * We're doing a depth-first traversal in order to invalidate everything.
    - */
    -STATIC int
    -xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp,
    -				   int level)
    -{
    -	xfs_da_blkinfo_t *info;
    -	xfs_da_intnode_t *node;
    -	xfs_dablk_t child_fsb;
    -	xfs_daddr_t parent_blkno, child_blkno;
    -	int error, count, i;
    -	xfs_dabuf_t *child_bp;
    -
    -	/*
    -	 * Since this code is recursive (gasp!) we must protect ourselves.
    -	 */
    -	if (level > XFS_DA_NODE_MAXDEPTH) {
    -		xfs_da_brelse(*trans, bp);	/* no locks for later trans */
    -		return(XFS_ERROR(EIO));
    -	}
    -
    -	node = bp->data;
    -	ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC);
    -	parent_blkno = xfs_da_blkno(bp);	/* save for re-read later */
    -	count = be16_to_cpu(node->hdr.count);
    -	if (!count) {
    -		xfs_da_brelse(*trans, bp);
    -		return(0);
    -	}
    -	child_fsb = be32_to_cpu(node->btree[0].before);
    -	xfs_da_brelse(*trans, bp);	/* no locks for later trans */
    -
    -	/*
    -	 * If this is the node level just above the leaves, simply loop
    -	 * over the leaves removing all of them.  If this is higher up
    -	 * in the tree, recurse downward.
    -	 */
    -	for (i = 0; i < count; i++) {
    -		/*
    -		 * Read the subsidiary block to see what we have to work with.
    -		 * Don't do this in a transaction.  This is a depth-first
    -		 * traversal of the tree so we may deal with many blocks
    -		 * before we come back to this one.
    -		 */
    -		error = xfs_da_read_buf(*trans, dp, child_fsb, -2, &child_bp,
    -						XFS_ATTR_FORK);
    -		if (error)
    -			return(error);
    -		if (child_bp) {
    -						/* save for re-read later */
    -			child_blkno = xfs_da_blkno(child_bp);
    -
    -			/*
    -			 * Invalidate the subtree, however we have to.
    -			 */
    -			info = child_bp->data;
    -			if (be16_to_cpu(info->magic) == XFS_DA_NODE_MAGIC) {
    -				error = xfs_attr_node_inactive(trans, dp,
    -						child_bp, level+1);
    -			} else if (be16_to_cpu(info->magic) == XFS_ATTR_LEAF_MAGIC) {
    -				error = xfs_attr_leaf_inactive(trans, dp,
    -						child_bp);
    -			} else {
    -				error = XFS_ERROR(EIO);
    -				xfs_da_brelse(*trans, child_bp);
    -			}
    -			if (error)
    -				return(error);
    -
    -			/*
    -			 * Remove the subsidiary block from the cache
    -			 * and from the log.
    -			 */
    -			error = xfs_da_get_buf(*trans, dp, 0, child_blkno,
    -				&child_bp, XFS_ATTR_FORK);
    -			if (error)
    -				return(error);
    -			xfs_da_binval(*trans, child_bp);
    -		}
    -
    -		/*
    -		 * If we're not done, re-read the parent to get the next
    -		 * child block number.
    -		 */
    -		if ((i+1) < count) {
    -			error = xfs_da_read_buf(*trans, dp, 0, parent_blkno,
    -				&bp, XFS_ATTR_FORK);
    -			if (error)
    -				return(error);
    -			child_fsb = be32_to_cpu(node->btree[i+1].before);
    -			xfs_da_brelse(*trans, bp);
    -		}
    -		/*
    -		 * Atomically commit the whole invalidate stuff.
    -		 */
    -		if ((error = xfs_attr_rolltrans(trans, dp)))
    -			return (error);
    -	}
    -
    -	return(0);
    -}
    -
    -/*
    - * Invalidate all of the "remote" value regions pointed to by a particular
    - * leaf block.
    - * Note that we must release the lock on the buffer so that we are not
    - * caught holding something that the logging code wants to flush to disk.
    - */
    -STATIC int
    -xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp)
    -{
    -	xfs_attr_leafblock_t *leaf;
    -	xfs_attr_leaf_entry_t *entry;
    -	xfs_attr_leaf_name_remote_t *name_rmt;
    -	xfs_attr_inactive_list_t *list, *lp;
    -	int error, count, size, tmp, i;
    -
    -	leaf = bp->data;
    -	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_ATTR_LEAF_MAGIC);
    -
    -	/*
    -	 * Count the number of "remote" value extents.
    -	 */
    -	count = 0;
    -	entry = &leaf->entries[0];
    -	for (i = 0; i < be16_to_cpu(leaf->hdr.count); entry++, i++) {
    -		if (be16_to_cpu(entry->nameidx) &&
    -		    ((entry->flags & XFS_ATTR_LOCAL) == 0)) {
    -			name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf, i);
    -			if (name_rmt->valueblk)
    -				count++;
    -		}
    -	}
    -
    -	/*
    -	 * If there are no "remote" values, we're done.
    -	 */
    -	if (count == 0) {
    -		xfs_da_brelse(*trans, bp);
    -		return(0);
    -	}
    -
    -	/*
    -	 * Allocate storage for a list of all the "remote" value extents.
    -	 */
    -	size = count * sizeof(xfs_attr_inactive_list_t);
    -	list = (xfs_attr_inactive_list_t *)kmem_alloc(size, KM_SLEEP);
    -
    -	/*
    -	 * Identify each of the "remote" value extents.
    -	 */
    -	lp = list;
    -	entry = &leaf->entries[0];
    -	for (i = 0; i < be16_to_cpu(leaf->hdr.count); entry++, i++) {
    -		if (be16_to_cpu(entry->nameidx) &&
    -		    ((entry->flags & XFS_ATTR_LOCAL) == 0)) {
    -			name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf, i);
    -			if (name_rmt->valueblk) {
    -				lp->valueblk = be32_to_cpu(name_rmt->valueblk);
    -				lp->valuelen = XFS_B_TO_FSB(dp->i_mount,
    -						    be32_to_cpu(name_rmt->valuelen));
    -				lp++;
    -			}
    -		}
    -	}
    -	xfs_da_brelse(*trans, bp);	/* unlock for trans. in freextent() */
    -
    -	/*
    -	 * Invalidate each of the "remote" value extents.
    -	 */
    -	error = 0;
    -	for (lp = list, i = 0; i < count; i++, lp++) {
    -		tmp = xfs_attr_leaf_freextent(trans, dp,
    -				lp->valueblk, lp->valuelen);
    -
    -		if (error == 0)
    -			error = tmp;	/* save only the 1st errno */
    -	}
    -
    -	kmem_free((xfs_caddr_t)list, size);
    -	return(error);
    -}
    -
    -/*
    - * Look at all the extents for this logical region,
    - * invalidate any buffers that are incore/in transactions.
    - */
    -STATIC int
    -xfs_attr_leaf_freextent(xfs_trans_t **trans, xfs_inode_t *dp,
    -				    xfs_dablk_t blkno, int blkcnt)
    -{
    -	xfs_bmbt_irec_t map;
    -	xfs_dablk_t tblkno;
    -	int tblkcnt, dblkcnt, nmap, error;
    -	xfs_daddr_t dblkno;
    -	xfs_buf_t *bp;
    -
    -	/*
    -	 * Roll through the "value", invalidating the attribute value's
    -	 * blocks.
    -	 */
    -	tblkno = blkno;
    -	tblkcnt = blkcnt;
    -	while (tblkcnt > 0) {
    -		/*
    -		 * Try to remember where we decided to put the value.
    -		 */
    -		nmap = 1;
    -		error = xfs_bmapi(*trans, dp, (xfs_fileoff_t)tblkno, tblkcnt,
    -					XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
    -					NULL, 0, &map, &nmap, NULL, NULL);
    -		if (error) {
    -			return(error);
    -		}
    -		ASSERT(nmap == 1);
    -		ASSERT(map.br_startblock != DELAYSTARTBLOCK);
    -
    -		/*
    -		 * If it's a hole, these are already unmapped
    -		 * so there's nothing to invalidate.
    -		 */
    -		if (map.br_startblock != HOLESTARTBLOCK) {
    -
    -			dblkno = XFS_FSB_TO_DADDR(dp->i_mount,
    -						  map.br_startblock);
    -			dblkcnt = XFS_FSB_TO_BB(dp->i_mount,
    -						map.br_blockcount);
    -			bp = xfs_trans_get_buf(*trans,
    -					dp->i_mount->m_ddev_targp,
    -					dblkno, dblkcnt, XFS_BUF_LOCK);
    -			xfs_trans_binval(*trans, bp);
    -			/*
    -			 * Roll to next transaction.
    -			 */
    -			if ((error = xfs_attr_rolltrans(trans, dp)))
    -				return (error);
    -		}
    -
    -		tblkno += map.br_blockcount;
    -		tblkcnt -= map.br_blockcount;
    -	}
    -
    -	return(0);
    -}
    -
    -
    -/*
    - * Roll from one trans in the sequence of PERMANENT transactions to the next.
    - */
    -int
    -xfs_attr_rolltrans(xfs_trans_t **transp, xfs_inode_t *dp)
    -{
    -	xfs_trans_t *trans;
    -	unsigned int logres, count;
    -	int	error;
    -
    -	/*
    -	 * Ensure that the inode is always logged.
    -	 */
    -	trans = *transp;
    -	xfs_trans_log_inode(trans, dp, XFS_ILOG_CORE);
    -
    -	/*
    -	 * Copy the critical parameters from one trans to the next.
    -	 */
    -	logres = trans->t_log_res;
    -	count = trans->t_log_count;
    -	*transp = xfs_trans_dup(trans);
    -
    -	/*
    -	 * Commit the current transaction.
    -	 * If this commit failed, then it'd just unlock those items that
    -	 * are not marked ihold. That also means that a filesystem shutdown
    -	 * is in progress. The caller takes the responsibility to cancel
    -	 * the duplicate transaction that gets returned.
    -	 */
    -	if ((error = xfs_trans_commit(trans, 0, NULL)))
    -		return (error);
    -
    -	trans = *transp;
    -
    -	/*
    -	 * Reserve space in the log for th next transaction.
    -	 * This also pushes items in the "AIL", the list of logged items,
    -	 * out to disk if they are taking up space at the tail of the log
    -	 * that we want to use.  This requires that either nothing be locked
    -	 * across this call, or that anything that is locked be logged in
    -	 * the prior and the next transactions.
    -	 */
    -	error = xfs_trans_reserve(trans, 0, logres, 0,
    -				  XFS_TRANS_PERM_LOG_RES, count);
    -	/*
    -	 *  Ensure that the inode is in the new transaction and locked.
    -	 */
    -	if (!error) {
    -		xfs_trans_ijoin(trans, dp, XFS_ILOCK_EXCL);
    -		xfs_trans_ihold(trans, dp);
    -	}
    -	return (error);
    -
    -}
    diff --git a/sys/gnu/fs/xfs/xfs_attr_leaf.h b/sys/gnu/fs/xfs/xfs_attr_leaf.h
    deleted file mode 100644
    index 8b8e3a8db70..00000000000
    --- a/sys/gnu/fs/xfs/xfs_attr_leaf.h
    +++ /dev/null
    @@ -1,282 +0,0 @@
    -/*
    - * Copyright (c) 2000,2002-2003,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_ATTR_LEAF_H__
    -#define	__XFS_ATTR_LEAF_H__
    -
    -/*
    - * Attribute storage layout, internal structure, access macros, etc.
    - *
    - * Attribute lists are structured around Btrees where all the data
    - * elements are in the leaf nodes.  Attribute names are hashed into an int,
    - * then that int is used as the index into the Btree.  Since the hashval
    - * of an attribute name may not be unique, we may have duplicate keys.  The
    - * internal links in the Btree are logical block offsets into the file.
    - */
    -
    -struct attrlist;
    -struct attrlist_cursor_kern;
    -struct attrnames;
    -struct xfs_dabuf;
    -struct xfs_da_args;
    -struct xfs_da_state;
    -struct xfs_da_state_blk;
    -struct xfs_inode;
    -struct xfs_trans;
    -
    -/*========================================================================
    - * Attribute structure when equal to XFS_LBSIZE(mp) bytes.
    - *========================================================================*/
    -
    -/*
    - * This is the structure of the leaf nodes in the Btree.
    - *
    - * Struct leaf_entry's are packed from the top.  Name/values grow from the
    - * bottom but are not packed.  The freemap contains run-length-encoded entries
    - * for the free bytes after the leaf_entry's, but only the N largest such,
    - * smaller runs are dropped.  When the freemap doesn't show enough space
    - * for an allocation, we compact the name/value area and try again.  If we
    - * still don't have enough space, then we have to split the block.  The
    - * name/value structs (both local and remote versions) must be 32bit aligned.
    - *
    - * Since we have duplicate hash keys, for each key that matches, compare
    - * the actual name string.  The root and intermediate node search always
    - * takes the first-in-the-block key match found, so we should only have
    - * to work "forw"ard.  If none matches, continue with the "forw"ard leaf
    - * nodes until the hash key changes or the attribute name is found.
    - *
    - * We store the fact that an attribute is a ROOT/USER/SECURE attribute in
    - * the leaf_entry.  The namespaces are independent only because we also look
    - * at the namespace bit when we are looking for a matching attribute name.
    - *
    - * We also store an "incomplete" bit in the leaf_entry.  It shows that an
    - * attribute is in the middle of being created and should not be shown to
    - * the user if we crash during the time that the bit is set.  We clear the
    - * bit when we have finished setting up the attribute.  We do this because
    - * we cannot create some large attributes inside a single transaction, and we
    - * need some indication that we weren't finished if we crash in the middle.
    - */
    -#define XFS_ATTR_LEAF_MAPSIZE	3	/* how many freespace slots */
    -
    -typedef struct xfs_attr_leaf_map {	/* RLE map of free bytes */
    -	__be16	base;			  /* base of free region */
    -	__be16	size;			  /* length of free region */
    -} xfs_attr_leaf_map_t;
    -
    -typedef struct xfs_attr_leaf_hdr {	/* constant-structure header block */
    -	xfs_da_blkinfo_t info;		/* block type, links, etc. */
    -	__be16	count;			/* count of active leaf_entry's */
    -	__be16	usedbytes;		/* num bytes of names/values stored */
    -	__be16	firstused;		/* first used byte in name area */
    -	__u8	holes;			/* != 0 if blk needs compaction */
    -	__u8	pad1;
    -	xfs_attr_leaf_map_t freemap[XFS_ATTR_LEAF_MAPSIZE];
    -					/* N largest free regions */
    -} xfs_attr_leaf_hdr_t;
    -
    -typedef struct xfs_attr_leaf_entry {	/* sorted on key, not name */
    -	__be32	hashval;		/* hash value of name */
    - 	__be16	nameidx;		/* index into buffer of name/value */
    -	__u8	flags;			/* LOCAL/ROOT/SECURE/INCOMPLETE flag */
    -	__u8	pad2;			/* unused pad byte */
    -} xfs_attr_leaf_entry_t;
    -
    -typedef struct xfs_attr_leaf_name_local {
    -	__be16	valuelen;		/* number of bytes in value */
    -	__u8	namelen;		/* length of name bytes */
    -	__u8	nameval[1];		/* name/value bytes */
    -} xfs_attr_leaf_name_local_t;
    -
    -typedef struct xfs_attr_leaf_name_remote {
    -	__be32	valueblk;		/* block number of value bytes */
    -	__be32	valuelen;		/* number of bytes in value */
    -	__u8	namelen;		/* length of name bytes */
    -	__u8	name[1];		/* name bytes */
    -} xfs_attr_leaf_name_remote_t;
    -
    -typedef struct xfs_attr_leafblock {
    -	xfs_attr_leaf_hdr_t	hdr;	/* constant-structure header block */
    -	xfs_attr_leaf_entry_t	entries[1];	/* sorted on key, not name */
    -	xfs_attr_leaf_name_local_t namelist;	/* grows from bottom of buf */
    -	xfs_attr_leaf_name_remote_t valuelist;	/* grows from bottom of buf */
    -} xfs_attr_leafblock_t;
    -
    -/*
    - * Flags used in the leaf_entry[i].flags field.
    - * NOTE: the INCOMPLETE bit must not collide with the flags bits specified
    - * on the system call, they are "or"ed together for various operations.
    - */
    -#define	XFS_ATTR_LOCAL_BIT	0	/* attr is stored locally */
    -#define	XFS_ATTR_ROOT_BIT	1	/* limit access to trusted attrs */
    -#define	XFS_ATTR_SECURE_BIT	2	/* limit access to secure attrs */
    -#define	XFS_ATTR_INCOMPLETE_BIT	7	/* attr in middle of create/delete */
    -#define XFS_ATTR_LOCAL		(1 << XFS_ATTR_LOCAL_BIT)
    -#define XFS_ATTR_ROOT		(1 << XFS_ATTR_ROOT_BIT)
    -#define XFS_ATTR_SECURE		(1 << XFS_ATTR_SECURE_BIT)
    -#define XFS_ATTR_INCOMPLETE	(1 << XFS_ATTR_INCOMPLETE_BIT)
    -
    -/*
    - * Alignment for namelist and valuelist entries (since they are mixed
    - * there can be only one alignment value)
    - */
    -#define	XFS_ATTR_LEAF_NAME_ALIGN	((uint)sizeof(xfs_dablk_t))
    -
    -/*
    - * Cast typed pointers for "local" and "remote" name/value structs.
    - */
    -#define XFS_ATTR_LEAF_NAME_REMOTE(leafp,idx)	\
    -	xfs_attr_leaf_name_remote(leafp,idx)
    -static inline xfs_attr_leaf_name_remote_t *
    -xfs_attr_leaf_name_remote(xfs_attr_leafblock_t *leafp, int idx)
    -{
    -	return (xfs_attr_leaf_name_remote_t *)
    -		&((char *)leafp)[be16_to_cpu(leafp->entries[idx].nameidx)];
    -}
    -
    -#define XFS_ATTR_LEAF_NAME_LOCAL(leafp,idx)	\
    -	xfs_attr_leaf_name_local(leafp,idx)
    -static inline xfs_attr_leaf_name_local_t *
    -xfs_attr_leaf_name_local(xfs_attr_leafblock_t *leafp, int idx)
    -{
    -	return (xfs_attr_leaf_name_local_t *)
    -		&((char *)leafp)[be16_to_cpu(leafp->entries[idx].nameidx)];
    -}
    -
    -#define XFS_ATTR_LEAF_NAME(leafp,idx)		\
    -	xfs_attr_leaf_name(leafp,idx)
    -static inline char *xfs_attr_leaf_name(xfs_attr_leafblock_t *leafp, int idx)
    -{
    -	return &((char *)leafp)[be16_to_cpu(leafp->entries[idx].nameidx)];
    -}
    -
    -/*
    - * Calculate total bytes used (including trailing pad for alignment) for
    - * a "local" name/value structure, a "remote" name/value structure, and
    - * a pointer which might be either.
    - */
    -#define XFS_ATTR_LEAF_ENTSIZE_REMOTE(nlen)	\
    -	xfs_attr_leaf_entsize_remote(nlen)
    -static inline int xfs_attr_leaf_entsize_remote(int nlen)
    -{
    -	return ((uint)sizeof(xfs_attr_leaf_name_remote_t) - 1 + (nlen) + \
    -		XFS_ATTR_LEAF_NAME_ALIGN - 1) & ~(XFS_ATTR_LEAF_NAME_ALIGN - 1);
    -}
    -
    -#define XFS_ATTR_LEAF_ENTSIZE_LOCAL(nlen,vlen)	\
    -	xfs_attr_leaf_entsize_local(nlen,vlen)
    -static inline int xfs_attr_leaf_entsize_local(int nlen, int vlen)
    -{
    -	return ((uint)sizeof(xfs_attr_leaf_name_local_t) - 1 + (nlen) + (vlen) +
    -		XFS_ATTR_LEAF_NAME_ALIGN - 1) & ~(XFS_ATTR_LEAF_NAME_ALIGN - 1);
    -}
    -
    -#define XFS_ATTR_LEAF_ENTSIZE_LOCAL_MAX(bsize)	\
    -	xfs_attr_leaf_entsize_local_max(bsize)
    -static inline int xfs_attr_leaf_entsize_local_max(int bsize)
    -{
    -	return (((bsize) >> 1) + ((bsize) >> 2));
    -}
    -
    -
    -/*========================================================================
    - * Structure used to pass context around among the routines.
    - *========================================================================*/
    -
    -typedef struct xfs_attr_list_context {
    -	struct xfs_inode		*dp;	/* inode */
    -	struct attrlist_cursor_kern	*cursor;/* position in list */
    -	struct attrlist			*alist;	/* output buffer */
    -	int				count;	/* num used entries */
    -	int				dupcnt;	/* count dup hashvals seen */
    -	int				bufsize;/* total buffer size */
    -	int				firstu;	/* first used byte in buffer */
    -	int				flags;	/* from VOP call */
    -	int				resynch;/* T/F: resynch with cursor */
    -} xfs_attr_list_context_t;
    -
    -/*
    - * Used to keep a list of "remote value" extents when unlinking an inode.
    - */
    -typedef struct xfs_attr_inactive_list {
    -	xfs_dablk_t	valueblk;	/* block number of value bytes */
    -	int		valuelen;	/* number of bytes in value */
    -} xfs_attr_inactive_list_t;
    -
    -
    -/*========================================================================
    - * Function prototypes for the kernel.
    - *========================================================================*/
    -
    -/*
    - * Internal routines when attribute fork size < XFS_LITINO(mp).
    - */
    -void	xfs_attr_shortform_create(struct xfs_da_args *args);
    -void	xfs_attr_shortform_add(struct xfs_da_args *args, int forkoff);
    -int	xfs_attr_shortform_lookup(struct xfs_da_args *args);
    -int	xfs_attr_shortform_to_leaf(struct xfs_da_args *args);
    -int	xfs_attr_shortform_remove(struct xfs_da_args *args);
    -int	xfs_attr_shortform_list(struct xfs_attr_list_context *context);
    -int	xfs_attr_shortform_allfit(struct xfs_dabuf *bp, struct xfs_inode *dp);
    -int	xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes);
    -
    -
    -/*
    - * Internal routines when attribute fork size == XFS_LBSIZE(mp).
    - */
    -int	xfs_attr_leaf_to_node(struct xfs_da_args *args);
    -int	xfs_attr_leaf_to_shortform(struct xfs_dabuf *bp,
    -				   struct xfs_da_args *args, int forkoff);
    -int	xfs_attr_leaf_clearflag(struct xfs_da_args *args);
    -int	xfs_attr_leaf_setflag(struct xfs_da_args *args);
    -int	xfs_attr_leaf_flipflags(xfs_da_args_t *args);
    -
    -/*
    - * Routines used for growing the Btree.
    - */
    -int	xfs_attr_leaf_split(struct xfs_da_state *state,
    -				   struct xfs_da_state_blk *oldblk,
    -				   struct xfs_da_state_blk *newblk);
    -int	xfs_attr_leaf_lookup_int(struct xfs_dabuf *leaf,
    -					struct xfs_da_args *args);
    -int	xfs_attr_leaf_getvalue(struct xfs_dabuf *bp, struct xfs_da_args *args);
    -int	xfs_attr_leaf_add(struct xfs_dabuf *leaf_buffer,
    -				 struct xfs_da_args *args);
    -int	xfs_attr_leaf_remove(struct xfs_dabuf *leaf_buffer,
    -				    struct xfs_da_args *args);
    -int	xfs_attr_leaf_list_int(struct xfs_dabuf *bp,
    -				      struct xfs_attr_list_context *context);
    -
    -/*
    - * Routines used for shrinking the Btree.
    - */
    -int	xfs_attr_leaf_toosmall(struct xfs_da_state *state, int *retval);
    -void	xfs_attr_leaf_unbalance(struct xfs_da_state *state,
    -				       struct xfs_da_state_blk *drop_blk,
    -				       struct xfs_da_state_blk *save_blk);
    -int	xfs_attr_root_inactive(struct xfs_trans **trans, struct xfs_inode *dp);
    -
    -/*
    - * Utility routines.
    - */
    -xfs_dahash_t	xfs_attr_leaf_lasthash(struct xfs_dabuf *bp, int *count);
    -int	xfs_attr_leaf_order(struct xfs_dabuf *leaf1_bp,
    -				   struct xfs_dabuf *leaf2_bp);
    -int	xfs_attr_leaf_newentsize(int namelen, int valuelen, int blocksize,
    -					int *local);
    -int	xfs_attr_rolltrans(struct xfs_trans **transp, struct xfs_inode *dp);
    -
    -#endif	/* __XFS_ATTR_LEAF_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_attr_sf.h b/sys/gnu/fs/xfs/xfs_attr_sf.h
    deleted file mode 100644
    index f67f917803b..00000000000
    --- a/sys/gnu/fs/xfs/xfs_attr_sf.h
    +++ /dev/null
    @@ -1,114 +0,0 @@
    -/*
    - * Copyright (c) 2000,2002,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_ATTR_SF_H__
    -#define	__XFS_ATTR_SF_H__
    -
    -/*
    - * Attribute storage when stored inside the inode.
    - *
    - * Small attribute lists are packed as tightly as possible so as
    - * to fit into the literal area of the inode.
    - */
    -
    -struct xfs_inode;
    -
    -/*
    - * Entries are packed toward the top as tight as possible.
    - */
    -typedef struct xfs_attr_shortform {
    -	struct xfs_attr_sf_hdr {	/* constant-structure header block */
    -		__be16	totsize;	/* total bytes in shortform list */
    -		__u8	count;	/* count of active entries */
    -	} hdr;
    -	struct xfs_attr_sf_entry {
    -		__uint8_t namelen;	/* actual length of name (no NULL) */
    -		__uint8_t valuelen;	/* actual length of value (no NULL) */
    -		__uint8_t flags;	/* flags bits (see xfs_attr_leaf.h) */
    -		__uint8_t nameval[1];	/* name & value bytes concatenated */
    -	} list[1];			/* variable sized array */
    -} xfs_attr_shortform_t;
    -typedef struct xfs_attr_sf_hdr xfs_attr_sf_hdr_t;
    -typedef struct xfs_attr_sf_entry xfs_attr_sf_entry_t;
    -
    -/*
    - * We generate this then sort it, attr_list() must return things in hash-order.
    - */
    -typedef struct xfs_attr_sf_sort {
    -	__uint8_t	entno;		/* entry number in original list */
    -	__uint8_t	namelen;	/* length of name value (no null) */
    -	__uint8_t	valuelen;	/* length of value */
    -	__uint8_t	flags;		/* flags bits (see xfs_attr_leaf.h) */
    -	xfs_dahash_t	hash;		/* this entry's hash value */
    -	char		*name;		/* name value, pointer into buffer */
    -} xfs_attr_sf_sort_t;
    -
    -#define XFS_ATTR_SF_ENTSIZE_BYNAME(nlen,vlen)	/* space name/value uses */ \
    -	(((int)sizeof(xfs_attr_sf_entry_t)-1 + (nlen)+(vlen)))
    -#define XFS_ATTR_SF_ENTSIZE_MAX			/* max space for name&value */ \
    -	((1 << (NBBY*(int)sizeof(__uint8_t))) - 1)
    -#define XFS_ATTR_SF_ENTSIZE(sfep)		/* space an entry uses */ \
    -	((int)sizeof(xfs_attr_sf_entry_t)-1 + (sfep)->namelen+(sfep)->valuelen)
    -#define XFS_ATTR_SF_NEXTENTRY(sfep)		/* next entry in struct */ \
    -	((xfs_attr_sf_entry_t *)((char *)(sfep) + XFS_ATTR_SF_ENTSIZE(sfep)))
    -#define XFS_ATTR_SF_TOTSIZE(dp)			/* total space in use */ \
    -	(be16_to_cpu(((xfs_attr_shortform_t *)	\
    -		((dp)->i_afp->if_u1.if_data))->hdr.totsize))
    -
    -#if defined(XFS_ATTR_TRACE)
    -/*
    - * Kernel tracing support for attribute lists
    - */
    -struct xfs_attr_list_context;
    -struct xfs_da_intnode;
    -struct xfs_da_node_entry;
    -struct xfs_attr_leafblock;
    -
    -#define	XFS_ATTR_TRACE_SIZE	4096	/* size of global trace buffer */
    -extern ktrace_t	*xfs_attr_trace_buf;
    -
    -/*
    - * Trace record types.
    - */
    -#define	XFS_ATTR_KTRACE_L_C	1	/* context */
    -#define	XFS_ATTR_KTRACE_L_CN	2	/* context, node */
    -#define	XFS_ATTR_KTRACE_L_CB	3	/* context, btree */
    -#define	XFS_ATTR_KTRACE_L_CL	4	/* context, leaf */
    -
    -void xfs_attr_trace_l_c(char *where, struct xfs_attr_list_context *context);
    -void xfs_attr_trace_l_cn(char *where, struct xfs_attr_list_context *context,
    -			      struct xfs_da_intnode *node);
    -void xfs_attr_trace_l_cb(char *where, struct xfs_attr_list_context *context,
    -			      struct xfs_da_node_entry *btree);
    -void xfs_attr_trace_l_cl(char *where, struct xfs_attr_list_context *context,
    -			      struct xfs_attr_leafblock *leaf);
    -void xfs_attr_trace_enter(int type, char *where,
    -			     __psunsigned_t a2, __psunsigned_t a3,
    -			     __psunsigned_t a4, __psunsigned_t a5,
    -			     __psunsigned_t a6, __psunsigned_t a7,
    -			     __psunsigned_t a8, __psunsigned_t a9,
    -			     __psunsigned_t a10, __psunsigned_t a11,
    -			     __psunsigned_t a12, __psunsigned_t a13,
    -			     __psunsigned_t a14, __psunsigned_t a15);
    -#else
    -#define	xfs_attr_trace_l_c(w,c)
    -#define	xfs_attr_trace_l_cn(w,c,n)
    -#define	xfs_attr_trace_l_cb(w,c,b)
    -#define	xfs_attr_trace_l_cl(w,c,l)
    -#endif /* XFS_ATTR_TRACE */
    -
    -#endif	/* __XFS_ATTR_SF_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_behavior.c b/sys/gnu/fs/xfs/xfs_behavior.c
    deleted file mode 100644
    index f4fe3715a80..00000000000
    --- a/sys/gnu/fs/xfs/xfs_behavior.c
    +++ /dev/null
    @@ -1,203 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -
    -/*
    - * Source file used to associate/disassociate behaviors with virtualized
    - * objects.  See xfs_behavior.h for more information about behaviors, etc.
    - *
    - * The implementation is split between functions in this file and macros
    - * in xfs_behavior.h.
    - */
    -
    -/*
    - * Insert a new behavior descriptor into a behavior chain.
    - *
    - * The behavior chain is ordered based on the 'position' number which
    - * lives in the first field of the ops vector (higher numbers first).
    - *
    - * Attempts to insert duplicate ops result in an EINVAL return code.
    - * Otherwise, return 0 to indicate success.
    - */
    -int
    -bhv_insert(bhv_head_t *bhp, bhv_desc_t *bdp)
    -{
    -	bhv_desc_t	*curdesc, *prev;
    -	int		position;
    -
    -	/*
    -	 * Validate the position value of the new behavior.
    -	 */
    -	position = BHV_POSITION(bdp);
    -	ASSERT(position >= BHV_POSITION_BASE && position <= BHV_POSITION_TOP);
    -
    -	/*
    -	 * Find location to insert behavior.  Check for duplicates.
    -	 */
    -	prev = NULL;
    -	for (curdesc = bhp->bh_first;
    -	     curdesc != NULL;
    -	     curdesc = curdesc->bd_next) {
    -
    -		/* Check for duplication. */
    -		if (curdesc->bd_ops == bdp->bd_ops) {
    -			ASSERT(0);
    -			return EINVAL;
    -		}
    -
    -		/* Find correct position */
    -		if (position >= BHV_POSITION(curdesc)) {
    -			ASSERT(position != BHV_POSITION(curdesc));
    -			break;		/* found it */
    -		}
    -
    -		prev = curdesc;
    -	}
    -
    -	if (prev == NULL) {
    -		/* insert at front of chain */
    -		bdp->bd_next = bhp->bh_first;
    -		bhp->bh_first = bdp;
    -	} else {
    -		/* insert after prev */
    -		bdp->bd_next = prev->bd_next;
    -		prev->bd_next = bdp;
    -	}
    -
    -	return 0;
    -}
    -
    -/*
    - * Remove a behavior descriptor from a position in a behavior chain;
    - * the position is guaranteed not to be the first position.
    - * Should only be called by the bhv_remove() macro.
    - */
    -void
    -bhv_remove_not_first(bhv_head_t *bhp, bhv_desc_t *bdp)
    -{
    -	bhv_desc_t	*curdesc, *prev;
    -
    -	ASSERT(bhp->bh_first != NULL);
    -	ASSERT(bhp->bh_first->bd_next != NULL);
    -
    -	prev = bhp->bh_first;
    -	for (curdesc = bhp->bh_first->bd_next;
    -	     curdesc != NULL;
    -	     curdesc = curdesc->bd_next) {
    -
    -		if (curdesc == bdp)
    -			break;		/* found it */
    -		prev = curdesc;
    -	}
    -
    -	ASSERT(curdesc == bdp);
    -	prev->bd_next = bdp->bd_next;	/* remove from after prev */
    -}
    -
    -/*
    - * Look for a specific ops vector on the specified behavior chain.
    - * Return the associated behavior descriptor.  Or NULL, if not found.
    - */
    -bhv_desc_t *
    -bhv_lookup(bhv_head_t *bhp, void *ops)
    -{
    -	bhv_desc_t	*curdesc;
    -
    -	for (curdesc = bhp->bh_first;
    -	     curdesc != NULL;
    -	     curdesc = curdesc->bd_next) {
    -
    -		if (curdesc->bd_ops == ops)
    -			return curdesc;
    -	}
    -
    -	return NULL;
    -}
    -
    -/*
    - * Looks for the first behavior within a specified range of positions.
    - * Return the associated behavior descriptor.  Or NULL, if none found.
    - */
    -bhv_desc_t *
    -bhv_lookup_range(bhv_head_t *bhp, int low, int high)
    -{
    -	bhv_desc_t	*curdesc;
    -
    -	for (curdesc = bhp->bh_first;
    -	     curdesc != NULL;
    -	     curdesc = curdesc->bd_next) {
    -
    -		int	position = BHV_POSITION(curdesc);
    -
    -		if (position <= high) {
    -			if (position >= low)
    -				return curdesc;
    -			return NULL;
    -		}
    -	}
    -
    -	return NULL;
    -}
    -
    -/*
    - * Return the base behavior in the chain, or NULL if the chain
    - * is empty.
    - *
    - * The caller has not read locked the behavior chain, so acquire the
    - * lock before traversing the chain.
    - */
    -bhv_desc_t *
    -bhv_base(bhv_head_t *bhp)
    -{
    -	bhv_desc_t	*curdesc;
    -
    -	for (curdesc = bhp->bh_first;
    -	     curdesc != NULL;
    -	     curdesc = curdesc->bd_next) {
    -
    -		if (curdesc->bd_next == NULL) {
    -			return curdesc;
    -		}
    -	}
    -
    -	return NULL;
    -}
    -
    -void
    -bhv_head_init(
    -	bhv_head_t *bhp,
    -	char *name)
    -{
    -	bhp->bh_first = NULL;
    -}
    -
    -void
    -bhv_insert_initial(
    -	bhv_head_t *bhp,
    -	bhv_desc_t *bdp)
    -{
    -	ASSERT(bhp->bh_first == NULL);
    -	(bhp)->bh_first = bdp;
    -}
    -
    -void
    -bhv_head_destroy(
    -	bhv_head_t *bhp)
    -{
    -	ASSERT(bhp->bh_first == NULL);
    -}
    diff --git a/sys/gnu/fs/xfs/xfs_behavior.h b/sys/gnu/fs/xfs/xfs_behavior.h
    deleted file mode 100644
    index 1d8ff103201..00000000000
    --- a/sys/gnu/fs/xfs/xfs_behavior.h
    +++ /dev/null
    @@ -1,190 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_BEHAVIOR_H__
    -#define __XFS_BEHAVIOR_H__
    -
    -/*
    - * Header file used to associate behaviors with virtualized objects.
    - *
    - * A virtualized object is an internal, virtualized representation of
    - * OS entities such as persistent files, processes, or sockets.  Examples
    - * of virtualized objects include vnodes, vprocs, and vsockets.  Often
    - * a virtualized object is referred to simply as an "object."
    - *
    - * A behavior is essentially an implementation layer associated with
    - * an object.  Multiple behaviors for an object are chained together,
    - * the order of chaining determining the order of invocation.  Each
    - * behavior of a given object implements the same set of interfaces
    - * (e.g., the VOP interfaces).
    - *
    - * Behaviors may be dynamically inserted into an object's behavior chain,
    - * such that the addition is transparent to consumers that already have
    - * references to the object.  Typically, a given behavior will be inserted
    - * at a particular location in the behavior chain.  Insertion of new
    - * behaviors is synchronized with operations-in-progress (oip's) so that
    - * the oip's always see a consistent view of the chain.
    - *
    - * The term "interposition" is used to refer to the act of inserting
    - * a behavior such that it interposes on (i.e., is inserted in front
    - * of) a particular other behavior.  A key example of this is when a
    - * system implementing distributed single system image wishes to
    - * interpose a distribution layer (providing distributed coherency)
    - * in front of an object that is otherwise only accessed locally.
    - *
    - * Note that the traditional vnode/inode combination is simply a virtualized
    - * object that has exactly one associated behavior.
    - *
    - * Behavior synchronization is logic which is necessary under certain
    - * circumstances that there is no conflict between ongoing operations
    - * traversing the behavior chain and those dynamically modifying the
    - * behavior chain.  Because behavior synchronization adds extra overhead
    - * to virtual operation invocation, we want to restrict, as much as
    - * we can, the requirement for this extra code, to those situations
    - * in which it is truly necessary.
    - *
    - * Behavior synchronization is needed whenever there's at least one class
    - * of object in the system for which:
    - * 1) multiple behaviors for a given object are supported,
    - * -- AND --
    - * 2a) insertion of a new behavior can happen dynamically at any time during
    - *     the life of an active object,
    - *	-- AND --
    - *	3a) insertion of a new behavior needs to synchronize with existing
    - *	    ops-in-progress.
    - *	-- OR --
    - *	3b) multiple different behaviors can be dynamically inserted at
    - *	    any time during the life of an active object
    - *	-- OR --
    - *	3c) removal of a behavior can occur at any time during the life of
    - *	    an active object.
    - * -- OR --
    - * 2b) removal of a behavior can occur at any time during the life of an
    - *     active object
    - *
    - */
    -
    -struct bhv_head_lock;
    -
    -/*
    - * Behavior head.  Head of the chain of behaviors.
    - * Contained within each virtualized object data structure.
    - */
    -typedef struct bhv_head {
    -	struct bhv_desc *bh_first;	/* first behavior in chain */
    -	struct bhv_head_lock *bh_lockp;	/* pointer to lock info struct */
    -} bhv_head_t;
    -
    -/*
    - * Behavior descriptor.	 Descriptor associated with each behavior.
    - * Contained within the behavior's private data structure.
    - */
    -typedef struct bhv_desc {
    -	void		*bd_pdata;	/* private data for this behavior */
    -	void		*bd_vobj;	/* virtual object associated with */
    -	void		*bd_ops;	/* ops for this behavior */
    -	struct bhv_desc *bd_next;	/* next behavior in chain */
    -} bhv_desc_t;
    -
    -/*
    - * Behavior identity field.  A behavior's identity determines the position
    - * where it lives within a behavior chain, and it's always the first field
    - * of the behavior's ops vector. The optional id field further identifies the
    - * subsystem responsible for the behavior.
    - */
    -typedef struct bhv_identity {
    -	__u16	bi_id;		/* owning subsystem id */
    -	__u16	bi_position;	/* position in chain */
    -} bhv_identity_t;
    -
    -typedef bhv_identity_t bhv_position_t;
    -
    -#define BHV_IDENTITY_INIT(id,pos)	{id, pos}
    -#define BHV_IDENTITY_INIT_POSITION(pos) BHV_IDENTITY_INIT(0, pos)
    -
    -/*
    - * Define boundaries of position values.
    - */
    -#define BHV_POSITION_INVALID	0	/* invalid position number */
    -#define BHV_POSITION_BASE	1	/* base (last) implementation layer */
    -#define BHV_POSITION_TOP	63	/* top (first) implementation layer */
    -
    -/*
    - * Plumbing macros.
    - */
    -#define BHV_HEAD_FIRST(bhp)	(ASSERT((bhp)->bh_first), (bhp)->bh_first)
    -#define BHV_NEXT(bdp)		(ASSERT((bdp)->bd_next), (bdp)->bd_next)
    -#define BHV_NEXTNULL(bdp)	((bdp)->bd_next)
    -#define BHV_VOBJ(bdp)		(ASSERT((bdp)->bd_vobj), (bdp)->bd_vobj)
    -#define BHV_VOBJNULL(bdp)	((bdp)->bd_vobj)
    -#define BHV_PDATA(bdp)		(bdp)->bd_pdata
    -#define BHV_OPS(bdp)		(bdp)->bd_ops
    -#define BHV_IDENTITY(bdp)	((bhv_identity_t *)(bdp)->bd_ops)
    -#define BHV_POSITION(bdp)	(BHV_IDENTITY(bdp)->bi_position)
    -
    -extern void bhv_head_init(bhv_head_t *, char *);
    -extern void bhv_head_destroy(bhv_head_t *);
    -extern int  bhv_insert(bhv_head_t *, bhv_desc_t *);
    -extern void bhv_insert_initial(bhv_head_t *, bhv_desc_t *);
    -
    -/*
    - * Initialize a new behavior descriptor.
    - * Arguments:
    - *   bdp - pointer to behavior descriptor
    - *   pdata - pointer to behavior's private data
    - *   vobj - pointer to associated virtual object
    - *   ops - pointer to ops for this behavior
    - */
    -#define bhv_desc_init(bdp, pdata, vobj, ops)		\
    - {							\
    -	(bdp)->bd_pdata = pdata;			\
    -	(bdp)->bd_vobj = vobj;				\
    -	(bdp)->bd_ops = ops;				\
    -	(bdp)->bd_next = NULL;				\
    - }
    -
    -/*
    - * Remove a behavior descriptor from a behavior chain.
    - */
    -#define bhv_remove(bhp, bdp)				\
    - {							\
    -	if ((bhp)->bh_first == (bdp)) {			\
    -		/*					\
    -		* Remove from front of chain.		\
    -		* Atomic wrt oip's.			\
    -		*/					\
    -	       (bhp)->bh_first = (bdp)->bd_next;	\
    -	} else {					\
    -	       /* remove from non-front of chain */	\
    -	       bhv_remove_not_first(bhp, bdp);		\
    -	}						\
    -	(bdp)->bd_vobj = NULL;				\
    - }
    -
    -/*
    - * Behavior module prototypes.
    - */
    -extern void		bhv_remove_not_first(bhv_head_t *bhp, bhv_desc_t *bdp);
    -extern bhv_desc_t *	bhv_lookup(bhv_head_t *bhp, void *ops);
    -extern bhv_desc_t *	bhv_lookup_range(bhv_head_t *bhp, int low, int high);
    -extern bhv_desc_t *	bhv_base(bhv_head_t *bhp);
    -
    -/* No bhv locking on Linux */
    -#define bhv_lookup_unlocked	bhv_lookup
    -#define bhv_base_unlocked	bhv_base
    -
    -#endif /* __XFS_BEHAVIOR_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_bit.c b/sys/gnu/fs/xfs/xfs_bit.c
    deleted file mode 100644
    index 8b2d8f5bd1f..00000000000
    --- a/sys/gnu/fs/xfs/xfs_bit.c
    +++ /dev/null
    @@ -1,296 +0,0 @@
    -/*
    - * Copyright (c) 2000-2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_trans.h"
    -#include "xfs_buf_item.h"
    -
    -/*
    - * XFS bit manipulation routines, used in non-realtime code.
    - */
    -
    -#ifndef HAVE_ARCH_HIGHBIT
    -/*
    - * Index of high bit number in byte, -1 for none set, 0..7 otherwise.
    - */
    -STATIC const char xfs_highbit[256] = {
    -       -1, 0, 1, 1, 2, 2, 2, 2,			/* 00 .. 07 */
    -	3, 3, 3, 3, 3, 3, 3, 3,			/* 08 .. 0f */
    -	4, 4, 4, 4, 4, 4, 4, 4,			/* 10 .. 17 */
    -	4, 4, 4, 4, 4, 4, 4, 4,			/* 18 .. 1f */
    -	5, 5, 5, 5, 5, 5, 5, 5,			/* 20 .. 27 */
    -	5, 5, 5, 5, 5, 5, 5, 5,			/* 28 .. 2f */
    -	5, 5, 5, 5, 5, 5, 5, 5,			/* 30 .. 37 */
    -	5, 5, 5, 5, 5, 5, 5, 5,			/* 38 .. 3f */
    -	6, 6, 6, 6, 6, 6, 6, 6,			/* 40 .. 47 */
    -	6, 6, 6, 6, 6, 6, 6, 6,			/* 48 .. 4f */
    -	6, 6, 6, 6, 6, 6, 6, 6,			/* 50 .. 57 */
    -	6, 6, 6, 6, 6, 6, 6, 6,			/* 58 .. 5f */
    -	6, 6, 6, 6, 6, 6, 6, 6,			/* 60 .. 67 */
    -	6, 6, 6, 6, 6, 6, 6, 6,			/* 68 .. 6f */
    -	6, 6, 6, 6, 6, 6, 6, 6,			/* 70 .. 77 */
    -	6, 6, 6, 6, 6, 6, 6, 6,			/* 78 .. 7f */
    -	7, 7, 7, 7, 7, 7, 7, 7,			/* 80 .. 87 */
    -	7, 7, 7, 7, 7, 7, 7, 7,			/* 88 .. 8f */
    -	7, 7, 7, 7, 7, 7, 7, 7,			/* 90 .. 97 */
    -	7, 7, 7, 7, 7, 7, 7, 7,			/* 98 .. 9f */
    -	7, 7, 7, 7, 7, 7, 7, 7,			/* a0 .. a7 */
    -	7, 7, 7, 7, 7, 7, 7, 7,			/* a8 .. af */
    -	7, 7, 7, 7, 7, 7, 7, 7,			/* b0 .. b7 */
    -	7, 7, 7, 7, 7, 7, 7, 7,			/* b8 .. bf */
    -	7, 7, 7, 7, 7, 7, 7, 7,			/* c0 .. c7 */
    -	7, 7, 7, 7, 7, 7, 7, 7,			/* c8 .. cf */
    -	7, 7, 7, 7, 7, 7, 7, 7,			/* d0 .. d7 */
    -	7, 7, 7, 7, 7, 7, 7, 7,			/* d8 .. df */
    -	7, 7, 7, 7, 7, 7, 7, 7,			/* e0 .. e7 */
    -	7, 7, 7, 7, 7, 7, 7, 7,			/* e8 .. ef */
    -	7, 7, 7, 7, 7, 7, 7, 7,			/* f0 .. f7 */
    -	7, 7, 7, 7, 7, 7, 7, 7,			/* f8 .. ff */
    -};
    -#endif
    -
    -/*
    - * Count of bits set in byte, 0..8.
    - */
    -static const char xfs_countbit[256] = {
    -	0, 1, 1, 2, 1, 2, 2, 3,			/* 00 .. 07 */
    -	1, 2, 2, 3, 2, 3, 3, 4,			/* 08 .. 0f */
    -	1, 2, 2, 3, 2, 3, 3, 4,			/* 10 .. 17 */
    -	2, 3, 3, 4, 3, 4, 4, 5,			/* 18 .. 1f */
    -	1, 2, 2, 3, 2, 3, 3, 4,			/* 20 .. 27 */
    -	2, 3, 3, 4, 3, 4, 4, 5,			/* 28 .. 2f */
    -	2, 3, 3, 4, 3, 4, 4, 5,			/* 30 .. 37 */
    -	3, 4, 4, 5, 4, 5, 5, 6,			/* 38 .. 3f */
    -	1, 2, 2, 3, 2, 3, 3, 4,			/* 40 .. 47 */
    -	2, 3, 3, 4, 3, 4, 4, 5,			/* 48 .. 4f */
    -	2, 3, 3, 4, 3, 4, 4, 5,			/* 50 .. 57 */
    -	3, 4, 4, 5, 4, 5, 5, 6,			/* 58 .. 5f */
    -	2, 3, 3, 4, 3, 4, 4, 5,			/* 60 .. 67 */
    -	3, 4, 4, 5, 4, 5, 5, 6,			/* 68 .. 6f */
    -	3, 4, 4, 5, 4, 5, 5, 6,			/* 70 .. 77 */
    -	4, 5, 5, 6, 5, 6, 6, 7,			/* 78 .. 7f */
    -	1, 2, 2, 3, 2, 3, 3, 4,			/* 80 .. 87 */
    -	2, 3, 3, 4, 3, 4, 4, 5,			/* 88 .. 8f */
    -	2, 3, 3, 4, 3, 4, 4, 5,			/* 90 .. 97 */
    -	3, 4, 4, 5, 4, 5, 5, 6,			/* 98 .. 9f */
    -	2, 3, 3, 4, 3, 4, 4, 5,			/* a0 .. a7 */
    -	3, 4, 4, 5, 4, 5, 5, 6,			/* a8 .. af */
    -	3, 4, 4, 5, 4, 5, 5, 6,			/* b0 .. b7 */
    -	4, 5, 5, 6, 5, 6, 6, 7,			/* b8 .. bf */
    -	2, 3, 3, 4, 3, 4, 4, 5,			/* c0 .. c7 */
    -	3, 4, 4, 5, 4, 5, 5, 6,			/* c8 .. cf */
    -	3, 4, 4, 5, 4, 5, 5, 6,			/* d0 .. d7 */
    -	4, 5, 5, 6, 5, 6, 6, 7,			/* d8 .. df */
    -	3, 4, 4, 5, 4, 5, 5, 6,			/* e0 .. e7 */
    -	4, 5, 5, 6, 5, 6, 6, 7,			/* e8 .. ef */
    -	4, 5, 5, 6, 5, 6, 6, 7,			/* f0 .. f7 */
    -	5, 6, 6, 7, 6, 7, 7, 8,			/* f8 .. ff */
    -};
    -
    -/*
    - * xfs_highbit32: get high bit set out of 32-bit argument, -1 if none set.
    - */
    -int
    -xfs_highbit32(
    -	__uint32_t	v)
    -{
    -#ifdef HAVE_ARCH_HIGHBIT
    -	return highbit32(v);
    -#else
    -	int		i;
    -
    -	if (v & 0xffff0000)
    -		if (v & 0xff000000)
    -			i = 24;
    -		else
    -			i = 16;
    -	else if (v & 0x0000ffff)
    -		if (v & 0x0000ff00)
    -			i = 8;
    -		else
    -			i = 0;
    -	else
    -		return -1;
    -	return i + xfs_highbit[(v >> i) & 0xff];
    -#endif
    -}
    -
    -/*
    - * xfs_lowbit64: get low bit set out of 64-bit argument, -1 if none set.
    - */
    -int
    -xfs_lowbit64(
    -	__uint64_t	v)
    -{
    -	__uint32_t	w = (__uint32_t)v;
    -	int		n = 0;
    -
    -	if (w) {	/* lower bits */
    -		n = ffs(w);
    -	} else {	/* upper bits */
    -		w = (__uint32_t)(v >> 32);
    -		if (w && (n = ffs(w)))
    -			n += 32;
    -	}
    -	return n - 1;
    -}
    -
    -/*
    - * xfs_highbit64: get high bit set out of 64-bit argument, -1 if none set.
    - */
    -int
    -xfs_highbit64(
    -	__uint64_t	v)
    -{
    -	__uint32_t	h = (__uint32_t)(v >> 32);
    -
    -	if (h)
    -		return xfs_highbit32(h) + 32;
    -	return xfs_highbit32((__uint32_t)v);
    -}
    -
    -
    -/*
    - * Count the number of bits set in the bitmap starting with bit
    - * start_bit.  Size is the size of the bitmap in words.
    - *
    - * Do the counting by mapping a byte value to the number of set
    - * bits for that value using the xfs_countbit array, i.e.
    - * xfs_countbit[0] == 0, xfs_countbit[1] == 1, xfs_countbit[2] == 1,
    - * xfs_countbit[3] == 2, etc.
    - */
    -int
    -xfs_count_bits(uint *map, uint size, uint start_bit)
    -{
    -	register int	bits;
    -	register unsigned char	*bytep;
    -	register unsigned char	*end_map;
    -	int		byte_bit;
    -
    -	bits = 0;
    -	end_map = (char*)(map + size);
    -	bytep = (char*)(map + (start_bit & ~0x7));
    -	byte_bit = start_bit & 0x7;
    -
    -	/*
    -	 * If the caller fell off the end of the map, return 0.
    -	 */
    -	if (bytep >= end_map) {
    -		return (0);
    -	}
    -
    -	/*
    -	 * If start_bit is not byte aligned, then process the
    -	 * first byte separately.
    -	 */
    -	if (byte_bit != 0) {
    -		/*
    -		 * Shift off the bits we don't want to look at,
    -		 * before indexing into xfs_countbit.
    -		 */
    -		bits += xfs_countbit[(*bytep >> byte_bit)];
    -		bytep++;
    -	}
    -
    -	/*
    -	 * Count the bits in each byte until the end of the bitmap.
    -	 */
    -	while (bytep < end_map) {
    -		bits += xfs_countbit[*bytep];
    -		bytep++;
    -	}
    -
    -	return (bits);
    -}
    -
    -/*
    - * Count the number of contiguous bits set in the bitmap starting with bit
    - * start_bit.  Size is the size of the bitmap in words.
    - */
    -int
    -xfs_contig_bits(uint *map, uint	size, uint start_bit)
    -{
    -	uint * p = ((unsigned int *) map) + (start_bit >> BIT_TO_WORD_SHIFT);
    -	uint result = 0;
    -	uint tmp;
    -
    -	size <<= BIT_TO_WORD_SHIFT;
    -
    -	ASSERT(start_bit < size);
    -	size -= start_bit & ~(NBWORD - 1);
    -	start_bit &= (NBWORD - 1);
    -	if (start_bit) {
    -		tmp = *p++;
    -		/* set to one first offset bits prior to start */
    -		tmp |= (~0U >> (NBWORD-start_bit));
    -		if (tmp != ~0U)
    -			goto found;
    -		result += NBWORD;
    -		size -= NBWORD;
    -	}
    -	while (size) {
    -		if ((tmp = *p++) != ~0U)
    -			goto found;
    -		result += NBWORD;
    -		size -= NBWORD;
    -	}
    -	return result - start_bit;
    -found:
    -	return result + ffz(tmp) - start_bit;
    -}
    -
    -/*
    - * This takes the bit number to start looking from and
    - * returns the next set bit from there.  It returns -1
    - * if there are no more bits set or the start bit is
    - * beyond the end of the bitmap.
    - *
    - * Size is the number of words, not bytes, in the bitmap.
    - */
    -int xfs_next_bit(uint *map, uint size, uint start_bit)
    -{
    -	uint * p = ((unsigned int *) map) + (start_bit >> BIT_TO_WORD_SHIFT);
    -	uint result = start_bit & ~(NBWORD - 1);
    -	uint tmp;
    -
    -	size <<= BIT_TO_WORD_SHIFT;
    -
    -	if (start_bit >= size)
    -		return -1;
    -	size -= result;
    -	start_bit &= (NBWORD - 1);
    -	if (start_bit) {
    -		tmp = *p++;
    -		/* set to zero first offset bits prior to start */
    -		tmp &= (~0U << start_bit);
    -		if (tmp != 0U)
    -			goto found;
    -		result += NBWORD;
    -		size -= NBWORD;
    -	}
    -	while (size) {
    -		if ((tmp = *p++) != 0U)
    -			goto found;
    -		result += NBWORD;
    -		size -= NBWORD;
    -	}
    -	return -1;
    -found:
    -	return result + ffs(tmp) - 1;
    -}
    diff --git a/sys/gnu/fs/xfs/xfs_bit.h b/sys/gnu/fs/xfs/xfs_bit.h
    deleted file mode 100644
    index 0bbe5681754..00000000000
    --- a/sys/gnu/fs/xfs/xfs_bit.h
    +++ /dev/null
    @@ -1,67 +0,0 @@
    -/*
    - * Copyright (c) 2000,2002,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_BIT_H__
    -#define	__XFS_BIT_H__
    -
    -/*
    - * XFS bit manipulation routines.
    - */
    -
    -/*
    - * masks with n high/low bits set, 32-bit values & 64-bit values
    - */
    -#define	XFS_MASK32HI(n)		xfs_mask32hi(n)
    -static inline __uint32_t xfs_mask32hi(int n)
    -{
    -	return (__uint32_t)-1 << (32 - (n));
    -}
    -#define	XFS_MASK64HI(n)		xfs_mask64hi(n)
    -static inline __uint64_t xfs_mask64hi(int n)
    -{
    -	return (__uint64_t)-1 << (64 - (n));
    -}
    -#define	XFS_MASK32LO(n)		xfs_mask32lo(n)
    -static inline __uint32_t xfs_mask32lo(int n)
    -{
    -	return ((__uint32_t)1 << (n)) - 1;
    -}
    -#define	XFS_MASK64LO(n)		xfs_mask64lo(n)
    -static inline __uint64_t xfs_mask64lo(int n)
    -{
    -	return ((__uint64_t)1 << (n)) - 1;
    -}
    -
    -/* Get high bit set out of 32-bit argument, -1 if none set */
    -extern int xfs_highbit32(__uint32_t v);
    -
    -/* Get low bit set out of 64-bit argument, -1 if none set */
    -extern int xfs_lowbit64(__uint64_t v);
    -
    -/* Get high bit set out of 64-bit argument, -1 if none set */
    -extern int xfs_highbit64(__uint64_t);
    -
    -/* Count set bits in map starting with start_bit */
    -extern int xfs_count_bits(uint *map, uint size, uint start_bit);
    -
    -/* Count continuous one bits in map starting with start_bit */
    -extern int xfs_contig_bits(uint *map, uint size, uint start_bit);
    -
    -/* Find next set bit in map */
    -extern int xfs_next_bit(uint *map, uint size, uint start_bit);
    -
    -#endif	/* __XFS_BIT_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_bmap.c b/sys/gnu/fs/xfs/xfs_bmap.c
    deleted file mode 100644
    index 5c7ab963539..00000000000
    --- a/sys/gnu/fs/xfs/xfs_bmap.c
    +++ /dev/null
    @@ -1,6547 +0,0 @@
    -/*
    - * Copyright (c) 2000-2006 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_da_btree.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_btree.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_ialloc.h"
    -#include "xfs_itable.h"
    -#include "xfs_inode_item.h"
    -#include "xfs_extfree_item.h"
    -#include "xfs_alloc.h"
    -#include "xfs_bmap.h"
    -#include "xfs_rtalloc.h"
    -#include "xfs_error.h"
    -#include "xfs_dir_leaf.h"
    -#include "xfs_attr_leaf.h"
    -#include "xfs_rw.h"
    -#include "xfs_quota.h"
    -#include "xfs_trans_space.h"
    -#include "xfs_buf_item.h"
    -
    -
    -#ifdef DEBUG
    -STATIC void
    -xfs_bmap_check_leaf_extents(xfs_btree_cur_t *cur, xfs_inode_t *ip, int whichfork);
    -#endif
    -
    -kmem_zone_t		*xfs_bmap_free_item_zone;
    -
    -/*
    - * Prototypes for internal bmap routines.
    - */
    -
    -
    -/*
    - * Called from xfs_bmap_add_attrfork to handle extents format files.
    - */
    -STATIC int					/* error */
    -xfs_bmap_add_attrfork_extents(
    -	xfs_trans_t		*tp,		/* transaction pointer */
    -	xfs_inode_t		*ip,		/* incore inode pointer */
    -	xfs_fsblock_t		*firstblock,	/* first block allocated */
    -	xfs_bmap_free_t		*flist,		/* blocks to free at commit */
    -	int			*flags);	/* inode logging flags */
    -
    -/*
    - * Called from xfs_bmap_add_attrfork to handle local format files.
    - */
    -STATIC int					/* error */
    -xfs_bmap_add_attrfork_local(
    -	xfs_trans_t		*tp,		/* transaction pointer */
    -	xfs_inode_t		*ip,		/* incore inode pointer */
    -	xfs_fsblock_t		*firstblock,	/* first block allocated */
    -	xfs_bmap_free_t		*flist,		/* blocks to free at commit */
    -	int			*flags);	/* inode logging flags */
    -
    -/*
    - * Called by xfs_bmapi to update file extent records and the btree
    - * after allocating space (or doing a delayed allocation).
    - */
    -STATIC int				/* error */
    -xfs_bmap_add_extent(
    -	xfs_inode_t		*ip,	/* incore inode pointer */
    -	xfs_extnum_t		idx,	/* extent number to update/insert */
    -	xfs_btree_cur_t		**curp,	/* if *curp is null, not a btree */
    -	xfs_bmbt_irec_t		*new,	/* new data to add to file extents */
    -	xfs_fsblock_t		*first,	/* pointer to firstblock variable */
    -	xfs_bmap_free_t		*flist,	/* list of extents to be freed */
    -	int			*logflagsp, /* inode logging flags */
    -	xfs_extdelta_t		*delta, /* Change made to incore extents */
    -	int			whichfork, /* data or attr fork */
    -	int			rsvd);	/* OK to allocate reserved blocks */
    -
    -/*
    - * Called by xfs_bmap_add_extent to handle cases converting a delayed
    - * allocation to a real allocation.
    - */
    -STATIC int				/* error */
    -xfs_bmap_add_extent_delay_real(
    -	xfs_inode_t		*ip,	/* incore inode pointer */
    -	xfs_extnum_t		idx,	/* extent number to update/insert */
    -	xfs_btree_cur_t		**curp,	/* if *curp is null, not a btree */
    -	xfs_bmbt_irec_t		*new,	/* new data to add to file extents */
    -	xfs_filblks_t		*dnew,	/* new delayed-alloc indirect blocks */
    -	xfs_fsblock_t		*first,	/* pointer to firstblock variable */
    -	xfs_bmap_free_t		*flist,	/* list of extents to be freed */
    -	int			*logflagsp, /* inode logging flags */
    -	xfs_extdelta_t		*delta, /* Change made to incore extents */
    -	int			rsvd);	/* OK to allocate reserved blocks */
    -
    -/*
    - * Called by xfs_bmap_add_extent to handle cases converting a hole
    - * to a delayed allocation.
    - */
    -STATIC int				/* error */
    -xfs_bmap_add_extent_hole_delay(
    -	xfs_inode_t		*ip,	/* incore inode pointer */
    -	xfs_extnum_t		idx,	/* extent number to update/insert */
    -	xfs_btree_cur_t		*cur,	/* if null, not a btree */
    -	xfs_bmbt_irec_t		*new,	/* new data to add to file extents */
    -	int			*logflagsp,/* inode logging flags */
    -	xfs_extdelta_t		*delta, /* Change made to incore extents */
    -	int			rsvd);	/* OK to allocate reserved blocks */
    -
    -/*
    - * Called by xfs_bmap_add_extent to handle cases converting a hole
    - * to a real allocation.
    - */
    -STATIC int				/* error */
    -xfs_bmap_add_extent_hole_real(
    -	xfs_inode_t		*ip,	/* incore inode pointer */
    -	xfs_extnum_t		idx,	/* extent number to update/insert */
    -	xfs_btree_cur_t		*cur,	/* if null, not a btree */
    -	xfs_bmbt_irec_t		*new,	/* new data to add to file extents */
    -	int			*logflagsp, /* inode logging flags */
    -	xfs_extdelta_t		*delta, /* Change made to incore extents */
    -	int			whichfork); /* data or attr fork */
    -
    -/*
    - * Called by xfs_bmap_add_extent to handle cases converting an unwritten
    - * allocation to a real allocation or vice versa.
    - */
    -STATIC int				/* error */
    -xfs_bmap_add_extent_unwritten_real(
    -	xfs_inode_t		*ip,	/* incore inode pointer */
    -	xfs_extnum_t		idx,	/* extent number to update/insert */
    -	xfs_btree_cur_t		**curp,	/* if *curp is null, not a btree */
    -	xfs_bmbt_irec_t		*new,	/* new data to add to file extents */
    -	int			*logflagsp, /* inode logging flags */
    -	xfs_extdelta_t		*delta); /* Change made to incore extents */
    -
    -/*
    - * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file.
    - * It figures out where to ask the underlying allocator to put the new extent.
    - */
    -STATIC int				/* error */
    -xfs_bmap_alloc(
    -	xfs_bmalloca_t		*ap);	/* bmap alloc argument struct */
    -
    -/*
    - * Transform a btree format file with only one leaf node, where the
    - * extents list will fit in the inode, into an extents format file.
    - * Since the file extents are already in-core, all we have to do is
    - * give up the space for the btree root and pitch the leaf block.
    - */
    -STATIC int				/* error */
    -xfs_bmap_btree_to_extents(
    -	xfs_trans_t		*tp,	/* transaction pointer */
    -	xfs_inode_t		*ip,	/* incore inode pointer */
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	int			*logflagsp, /* inode logging flags */
    -	int			whichfork); /* data or attr fork */
    -
    -#ifdef DEBUG
    -#if 0
    -/*
    - * Check that the extents list for the inode ip is in the right order.
    - */
    -STATIC void
    -xfs_bmap_check_extents(
    -	xfs_inode_t		*ip,		/* incore inode pointer */
    -	int			whichfork);	/* data or attr fork */
    -#endif
    -#endif
    -
    -/*
    - * Called by xfs_bmapi to update file extent records and the btree
    - * after removing space (or undoing a delayed allocation).
    - */
    -STATIC int				/* error */
    -xfs_bmap_del_extent(
    -	xfs_inode_t		*ip,	/* incore inode pointer */
    -	xfs_trans_t		*tp,	/* current trans pointer */
    -	xfs_extnum_t		idx,	/* extent number to update/insert */
    -	xfs_bmap_free_t		*flist,	/* list of extents to be freed */
    -	xfs_btree_cur_t		*cur,	/* if null, not a btree */
    -	xfs_bmbt_irec_t		*new,	/* new data to add to file extents */
    -	int			*logflagsp,/* inode logging flags */
    -	xfs_extdelta_t		*delta, /* Change made to incore extents */
    -	int			whichfork, /* data or attr fork */
    -	int			rsvd);	 /* OK to allocate reserved blocks */
    -
    -/*
    - * Remove the entry "free" from the free item list.  Prev points to the
    - * previous entry, unless "free" is the head of the list.
    - */
    -STATIC void
    -xfs_bmap_del_free(
    -	xfs_bmap_free_t		*flist,	/* free item list header */
    -	xfs_bmap_free_item_t	*prev,	/* previous item on list, if any */
    -	xfs_bmap_free_item_t	*free);	/* list item to be freed */
    -
    -/*
    - * Convert an extents-format file into a btree-format file.
    - * The new file will have a root block (in the inode) and a single child block.
    - */
    -STATIC int					/* error */
    -xfs_bmap_extents_to_btree(
    -	xfs_trans_t		*tp,		/* transaction pointer */
    -	xfs_inode_t		*ip,		/* incore inode pointer */
    -	xfs_fsblock_t		*firstblock,	/* first-block-allocated */
    -	xfs_bmap_free_t		*flist,		/* blocks freed in xaction */
    -	xfs_btree_cur_t		**curp,		/* cursor returned to caller */
    -	int			wasdel,		/* converting a delayed alloc */
    -	int			*logflagsp,	/* inode logging flags */
    -	int			whichfork);	/* data or attr fork */
    -
    -/*
    - * Convert a local file to an extents file.
    - * This code is sort of bogus, since the file data needs to get
    - * logged so it won't be lost.  The bmap-level manipulations are ok, though.
    - */
    -STATIC int				/* error */
    -xfs_bmap_local_to_extents(
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_inode_t	*ip,		/* incore inode pointer */
    -	xfs_fsblock_t	*firstblock,	/* first block allocated in xaction */
    -	xfs_extlen_t	total,		/* total blocks needed by transaction */
    -	int		*logflagsp,	/* inode logging flags */
    -	int		whichfork);	/* data or attr fork */
    -
    -/*
    - * Search the extents list for the inode, for the extent containing bno.
    - * If bno lies in a hole, point to the next entry.  If bno lies past eof,
    - * *eofp will be set, and *prevp will contain the last entry (null if none).
    - * Else, *lastxp will be set to the index of the found
    - * entry; *gotp will contain the entry.
    - */
    -STATIC xfs_bmbt_rec_t *			/* pointer to found extent entry */
    -xfs_bmap_search_extents(
    -	xfs_inode_t	*ip,		/* incore inode pointer */
    -	xfs_fileoff_t	bno,		/* block number searched for */
    -	int		whichfork,	/* data or attr fork */
    -	int		*eofp,		/* out: end of file found */
    -	xfs_extnum_t	*lastxp,	/* out: last extent index */
    -	xfs_bmbt_irec_t	*gotp,		/* out: extent entry found */
    -	xfs_bmbt_irec_t	*prevp);	/* out: previous extent entry found */
    -
    -/*
    - * Check the last inode extent to determine whether this allocation will result
    - * in blocks being allocated at the end of the file. When we allocate new data
    - * blocks at the end of the file which do not start at the previous data block,
    - * we will try to align the new blocks at stripe unit boundaries.
    - */
    -STATIC int				/* error */
    -xfs_bmap_isaeof(
    -	xfs_inode_t	*ip,		/* incore inode pointer */
    -	xfs_fileoff_t   off,		/* file offset in fsblocks */
    -	int             whichfork,	/* data or attribute fork */
    -	char		*aeof);		/* return value */
    -
    -#ifdef XFS_BMAP_TRACE
    -/*
    - * Add a bmap trace buffer entry.  Base routine for the others.
    - */
    -STATIC void
    -xfs_bmap_trace_addentry(
    -	int		opcode,		/* operation */
    -	char		*fname,		/* function name */
    -	char		*desc,		/* operation description */
    -	xfs_inode_t	*ip,		/* incore inode pointer */
    -	xfs_extnum_t	idx,		/* index of entry(ies) */
    -	xfs_extnum_t	cnt,		/* count of entries, 1 or 2 */
    -	xfs_bmbt_rec_t	*r1,		/* first record */
    -	xfs_bmbt_rec_t	*r2,		/* second record or null */
    -	int		whichfork);	/* data or attr fork */
    -
    -/*
    - * Add bmap trace entry prior to a call to xfs_iext_remove.
    - */
    -STATIC void
    -xfs_bmap_trace_delete(
    -	char		*fname,		/* function name */
    -	char		*desc,		/* operation description */
    -	xfs_inode_t	*ip,		/* incore inode pointer */
    -	xfs_extnum_t	idx,		/* index of entry(entries) deleted */
    -	xfs_extnum_t	cnt,		/* count of entries deleted, 1 or 2 */
    -	int		whichfork);	/* data or attr fork */
    -
    -/*
    - * Add bmap trace entry prior to a call to xfs_iext_insert, or
    - * reading in the extents list from the disk (in the btree).
    - */
    -STATIC void
    -xfs_bmap_trace_insert(
    -	char		*fname,		/* function name */
    -	char		*desc,		/* operation description */
    -	xfs_inode_t	*ip,		/* incore inode pointer */
    -	xfs_extnum_t	idx,		/* index of entry(entries) inserted */
    -	xfs_extnum_t	cnt,		/* count of entries inserted, 1 or 2 */
    -	xfs_bmbt_irec_t	*r1,		/* inserted record 1 */
    -	xfs_bmbt_irec_t	*r2,		/* inserted record 2 or null */
    -	int		whichfork);	/* data or attr fork */
    -
    -/*
    - * Add bmap trace entry after updating an extent record in place.
    - */
    -STATIC void
    -xfs_bmap_trace_post_update(
    -	char		*fname,		/* function name */
    -	char		*desc,		/* operation description */
    -	xfs_inode_t	*ip,		/* incore inode pointer */
    -	xfs_extnum_t	idx,		/* index of entry updated */
    -	int		whichfork);	/* data or attr fork */
    -
    -/*
    - * Add bmap trace entry prior to updating an extent record in place.
    - */
    -STATIC void
    -xfs_bmap_trace_pre_update(
    -	char		*fname,		/* function name */
    -	char		*desc,		/* operation description */
    -	xfs_inode_t	*ip,		/* incore inode pointer */
    -	xfs_extnum_t	idx,		/* index of entry to be updated */
    -	int		whichfork);	/* data or attr fork */
    -
    -#else
    -#define	xfs_bmap_trace_delete(f,d,ip,i,c,w)
    -#define	xfs_bmap_trace_insert(f,d,ip,i,c,r1,r2,w)
    -#define	xfs_bmap_trace_post_update(f,d,ip,i,w)
    -#define	xfs_bmap_trace_pre_update(f,d,ip,i,w)
    -#endif	/* XFS_BMAP_TRACE */
    -
    -/*
    - * Compute the worst-case number of indirect blocks that will be used
    - * for ip's delayed extent of length "len".
    - */
    -STATIC xfs_filblks_t
    -xfs_bmap_worst_indlen(
    -	xfs_inode_t		*ip,	/* incore inode pointer */
    -	xfs_filblks_t		len);	/* delayed extent length */
    -
    -#ifdef DEBUG
    -/*
    - * Perform various validation checks on the values being returned
    - * from xfs_bmapi().
    - */
    -STATIC void
    -xfs_bmap_validate_ret(
    -	xfs_fileoff_t		bno,
    -	xfs_filblks_t		len,
    -	int			flags,
    -	xfs_bmbt_irec_t		*mval,
    -	int			nmap,
    -	int			ret_nmap);
    -#else
    -#define	xfs_bmap_validate_ret(bno,len,flags,mval,onmap,nmap)
    -#endif /* DEBUG */
    -
    -#if defined(XFS_RW_TRACE)
    -STATIC void
    -xfs_bunmap_trace(
    -	xfs_inode_t		*ip,
    -	xfs_fileoff_t		bno,
    -	xfs_filblks_t		len,
    -	int			flags,
    -	inst_t			*ra);
    -#else
    -#define	xfs_bunmap_trace(ip, bno, len, flags, ra)
    -#endif	/* XFS_RW_TRACE */
    -
    -STATIC int
    -xfs_bmap_count_tree(
    -	xfs_mount_t     *mp,
    -	xfs_trans_t     *tp,
    -	xfs_ifork_t	*ifp,
    -	xfs_fsblock_t   blockno,
    -	int             levelin,
    -	int		*count);
    -
    -STATIC int
    -xfs_bmap_count_leaves(
    -	xfs_ifork_t		*ifp,
    -	xfs_extnum_t		idx,
    -	int			numrecs,
    -	int			*count);
    -
    -STATIC int
    -xfs_bmap_disk_count_leaves(
    -	xfs_ifork_t		*ifp,
    -	xfs_mount_t		*mp,
    -	xfs_extnum_t		idx,
    -	xfs_bmbt_block_t	*block,
    -	int			numrecs,
    -	int			*count);
    -
    -/*
    - * Bmap internal routines.
    - */
    -
    -/*
    - * Called from xfs_bmap_add_attrfork to handle btree format files.
    - */
    -STATIC int					/* error */
    -xfs_bmap_add_attrfork_btree(
    -	xfs_trans_t		*tp,		/* transaction pointer */
    -	xfs_inode_t		*ip,		/* incore inode pointer */
    -	xfs_fsblock_t		*firstblock,	/* first block allocated */
    -	xfs_bmap_free_t		*flist,		/* blocks to free at commit */
    -	int			*flags)		/* inode logging flags */
    -{
    -	xfs_btree_cur_t		*cur;		/* btree cursor */
    -	int			error;		/* error return value */
    -	xfs_mount_t		*mp;		/* file system mount struct */
    -	int			stat;		/* newroot status */
    -
    -	mp = ip->i_mount;
    -	if (ip->i_df.if_broot_bytes <= XFS_IFORK_DSIZE(ip))
    -		*flags |= XFS_ILOG_DBROOT;
    -	else {
    -		cur = xfs_btree_init_cursor(mp, tp, NULL, 0, XFS_BTNUM_BMAP, ip,
    -			XFS_DATA_FORK);
    -		cur->bc_private.b.flist = flist;
    -		cur->bc_private.b.firstblock = *firstblock;
    -		if ((error = xfs_bmbt_lookup_ge(cur, 0, 0, 0, &stat)))
    -			goto error0;
    -		ASSERT(stat == 1);	/* must be at least one entry */
    -		if ((error = xfs_bmbt_newroot(cur, flags, &stat)))
    -			goto error0;
    -		if (stat == 0) {
    -			xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
    -			return XFS_ERROR(ENOSPC);
    -		}
    -		*firstblock = cur->bc_private.b.firstblock;
    -		cur->bc_private.b.allocated = 0;
    -		xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
    -	}
    -	return 0;
    -error0:
    -	xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
    -	return error;
    -}
    -
    -/*
    - * Called from xfs_bmap_add_attrfork to handle extents format files.
    - */
    -STATIC int					/* error */
    -xfs_bmap_add_attrfork_extents(
    -	xfs_trans_t		*tp,		/* transaction pointer */
    -	xfs_inode_t		*ip,		/* incore inode pointer */
    -	xfs_fsblock_t		*firstblock,	/* first block allocated */
    -	xfs_bmap_free_t		*flist,		/* blocks to free at commit */
    -	int			*flags)		/* inode logging flags */
    -{
    -	xfs_btree_cur_t		*cur;		/* bmap btree cursor */
    -	int			error;		/* error return value */
    -
    -	if (ip->i_d.di_nextents * sizeof(xfs_bmbt_rec_t) <= XFS_IFORK_DSIZE(ip))
    -		return 0;
    -	cur = NULL;
    -	error = xfs_bmap_extents_to_btree(tp, ip, firstblock, flist, &cur, 0,
    -		flags, XFS_DATA_FORK);
    -	if (cur) {
    -		cur->bc_private.b.allocated = 0;
    -		xfs_btree_del_cursor(cur,
    -			error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
    -	}
    -	return error;
    -}
    -
    -/*
    - * Called from xfs_bmap_add_attrfork to handle local format files.
    - */
    -STATIC int					/* error */
    -xfs_bmap_add_attrfork_local(
    -	xfs_trans_t		*tp,		/* transaction pointer */
    -	xfs_inode_t		*ip,		/* incore inode pointer */
    -	xfs_fsblock_t		*firstblock,	/* first block allocated */
    -	xfs_bmap_free_t		*flist,		/* blocks to free at commit */
    -	int			*flags)		/* inode logging flags */
    -{
    -	xfs_da_args_t		dargs;		/* args for dir/attr code */
    -	int			error;		/* error return value */
    -	xfs_mount_t		*mp;		/* mount structure pointer */
    -
    -	if (ip->i_df.if_bytes <= XFS_IFORK_DSIZE(ip))
    -		return 0;
    -	if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
    -		mp = ip->i_mount;
    -		memset(&dargs, 0, sizeof(dargs));
    -		dargs.dp = ip;
    -		dargs.firstblock = firstblock;
    -		dargs.flist = flist;
    -		dargs.total = mp->m_dirblkfsbs;
    -		dargs.whichfork = XFS_DATA_FORK;
    -		dargs.trans = tp;
    -		error = XFS_DIR_SHORTFORM_TO_SINGLE(mp, &dargs);
    -	} else
    -		error = xfs_bmap_local_to_extents(tp, ip, firstblock, 1, flags,
    -			XFS_DATA_FORK);
    -	return error;
    -}
    -
    -/*
    - * Called by xfs_bmapi to update file extent records and the btree
    - * after allocating space (or doing a delayed allocation).
    - */
    -STATIC int				/* error */
    -xfs_bmap_add_extent(
    -	xfs_inode_t		*ip,	/* incore inode pointer */
    -	xfs_extnum_t		idx,	/* extent number to update/insert */
    -	xfs_btree_cur_t		**curp,	/* if *curp is null, not a btree */
    -	xfs_bmbt_irec_t		*new,	/* new data to add to file extents */
    -	xfs_fsblock_t		*first,	/* pointer to firstblock variable */
    -	xfs_bmap_free_t		*flist,	/* list of extents to be freed */
    -	int			*logflagsp, /* inode logging flags */
    -	xfs_extdelta_t		*delta, /* Change made to incore extents */
    -	int			whichfork, /* data or attr fork */
    -	int			rsvd)	/* OK to use reserved data blocks */
    -{
    -	xfs_btree_cur_t		*cur;	/* btree cursor or null */
    -	xfs_filblks_t		da_new; /* new count del alloc blocks used */
    -	xfs_filblks_t		da_old; /* old count del alloc blocks used */
    -	int			error;	/* error return value */
    -#ifdef XFS_BMAP_TRACE
    -	static char		fname[] = "xfs_bmap_add_extent";
    -#endif
    -	xfs_ifork_t		*ifp;	/* inode fork ptr */
    -	int			logflags; /* returned value */
    -	xfs_extnum_t		nextents; /* number of extents in file now */
    -
    -	XFS_STATS_INC(xs_add_exlist);
    -	cur = *curp;
    -	ifp = XFS_IFORK_PTR(ip, whichfork);
    -	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
    -	ASSERT(idx <= nextents);
    -	da_old = da_new = 0;
    -	error = 0;
    -	/*
    -	 * This is the first extent added to a new/empty file.
    -	 * Special case this one, so other routines get to assume there are
    -	 * already extents in the list.
    -	 */
    -	if (nextents == 0) {
    -		xfs_bmap_trace_insert(fname, "insert empty", ip, 0, 1, new,
    -			NULL, whichfork);
    -		xfs_iext_insert(ifp, 0, 1, new);
    -		ASSERT(cur == NULL);
    -		ifp->if_lastex = 0;
    -		if (!ISNULLSTARTBLOCK(new->br_startblock)) {
    -			XFS_IFORK_NEXT_SET(ip, whichfork, 1);
    -			logflags = XFS_ILOG_CORE | XFS_ILOG_FEXT(whichfork);
    -		} else
    -			logflags = 0;
    -		/* DELTA: single new extent */
    -		if (delta) {
    -			if (delta->xed_startoff > new->br_startoff)
    -				delta->xed_startoff = new->br_startoff;
    -			if (delta->xed_blockcount <
    -					new->br_startoff + new->br_blockcount)
    -				delta->xed_blockcount = new->br_startoff +
    -						new->br_blockcount;
    -		}
    -	}
    -	/*
    -	 * Any kind of new delayed allocation goes here.
    -	 */
    -	else if (ISNULLSTARTBLOCK(new->br_startblock)) {
    -		if (cur)
    -			ASSERT((cur->bc_private.b.flags &
    -				XFS_BTCUR_BPRV_WASDEL) == 0);
    -		if ((error = xfs_bmap_add_extent_hole_delay(ip, idx, cur, new,
    -				&logflags, delta, rsvd)))
    -			goto done;
    -	}
    -	/*
    -	 * Real allocation off the end of the file.
    -	 */
    -	else if (idx == nextents) {
    -		if (cur)
    -			ASSERT((cur->bc_private.b.flags &
    -				XFS_BTCUR_BPRV_WASDEL) == 0);
    -		if ((error = xfs_bmap_add_extent_hole_real(ip, idx, cur, new,
    -				&logflags, delta, whichfork)))
    -			goto done;
    -	} else {
    -		xfs_bmbt_irec_t	prev;	/* old extent at offset idx */
    -
    -		/*
    -		 * Get the record referred to by idx.
    -		 */
    -		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx), &prev);
    -		/*
    -		 * If it's a real allocation record, and the new allocation ends
    -		 * after the start of the referred to record, then we're filling
    -		 * in a delayed or unwritten allocation with a real one, or
    -		 * converting real back to unwritten.
    -		 */
    -		if (!ISNULLSTARTBLOCK(new->br_startblock) &&
    -		    new->br_startoff + new->br_blockcount > prev.br_startoff) {
    -			if (prev.br_state != XFS_EXT_UNWRITTEN &&
    -			    ISNULLSTARTBLOCK(prev.br_startblock)) {
    -				da_old = STARTBLOCKVAL(prev.br_startblock);
    -				if (cur)
    -					ASSERT(cur->bc_private.b.flags &
    -						XFS_BTCUR_BPRV_WASDEL);
    -				if ((error = xfs_bmap_add_extent_delay_real(ip,
    -					idx, &cur, new, &da_new, first, flist,
    -					&logflags, delta, rsvd)))
    -					goto done;
    -			} else if (new->br_state == XFS_EXT_NORM) {
    -				ASSERT(new->br_state == XFS_EXT_NORM);
    -				if ((error = xfs_bmap_add_extent_unwritten_real(
    -					ip, idx, &cur, new, &logflags, delta)))
    -					goto done;
    -			} else {
    -				ASSERT(new->br_state == XFS_EXT_UNWRITTEN);
    -				if ((error = xfs_bmap_add_extent_unwritten_real(
    -					ip, idx, &cur, new, &logflags, delta)))
    -					goto done;
    -			}
    -			ASSERT(*curp == cur || *curp == NULL);
    -		}
    -		/*
    -		 * Otherwise we're filling in a hole with an allocation.
    -		 */
    -		else {
    -			if (cur)
    -				ASSERT((cur->bc_private.b.flags &
    -					XFS_BTCUR_BPRV_WASDEL) == 0);
    -			if ((error = xfs_bmap_add_extent_hole_real(ip, idx, cur,
    -					new, &logflags, delta, whichfork)))
    -				goto done;
    -		}
    -	}
    -
    -	ASSERT(*curp == cur || *curp == NULL);
    -	/*
    -	 * Convert to a btree if necessary.
    -	 */
    -	if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
    -	    XFS_IFORK_NEXTENTS(ip, whichfork) > ifp->if_ext_max) {
    -		int	tmp_logflags;	/* partial log flag return val */
    -
    -		ASSERT(cur == NULL);
    -		error = xfs_bmap_extents_to_btree(ip->i_transp, ip, first,
    -			flist, &cur, da_old > 0, &tmp_logflags, whichfork);
    -		logflags |= tmp_logflags;
    -		if (error)
    -			goto done;
    -	}
    -	/*
    -	 * Adjust for changes in reserved delayed indirect blocks.
    -	 * Nothing to do for disk quotas here.
    -	 */
    -	if (da_old || da_new) {
    -		xfs_filblks_t	nblks;
    -
    -		nblks = da_new;
    -		if (cur)
    -			nblks += cur->bc_private.b.allocated;
    -		ASSERT(nblks <= da_old);
    -		if (nblks < da_old)
    -			xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS,
    -				(int)(da_old - nblks), rsvd);
    -	}
    -	/*
    -	 * Clear out the allocated field, done with it now in any case.
    -	 */
    -	if (cur) {
    -		cur->bc_private.b.allocated = 0;
    -		*curp = cur;
    -	}
    -done:
    -#ifdef DEBUG
    -	if (!error)
    -		xfs_bmap_check_leaf_extents(*curp, ip, whichfork);
    -#endif
    -	*logflagsp = logflags;
    -	return error;
    -}
    -
    -/*
    - * Called by xfs_bmap_add_extent to handle cases converting a delayed
    - * allocation to a real allocation.
    - */
    -STATIC int				/* error */
    -xfs_bmap_add_extent_delay_real(
    -	xfs_inode_t		*ip,	/* incore inode pointer */
    -	xfs_extnum_t		idx,	/* extent number to update/insert */
    -	xfs_btree_cur_t		**curp,	/* if *curp is null, not a btree */
    -	xfs_bmbt_irec_t		*new,	/* new data to add to file extents */
    -	xfs_filblks_t		*dnew,	/* new delayed-alloc indirect blocks */
    -	xfs_fsblock_t		*first,	/* pointer to firstblock variable */
    -	xfs_bmap_free_t		*flist,	/* list of extents to be freed */
    -	int			*logflagsp, /* inode logging flags */
    -	xfs_extdelta_t		*delta, /* Change made to incore extents */
    -	int			rsvd)	/* OK to use reserved data block allocation */
    -{
    -	xfs_btree_cur_t		*cur;	/* btree cursor */
    -	int			diff;	/* temp value */
    -	xfs_bmbt_rec_t		*ep;	/* extent entry for idx */
    -	int			error;	/* error return value */
    -#ifdef XFS_BMAP_TRACE
    -	static char		fname[] = "xfs_bmap_add_extent_delay_real";
    -#endif
    -	int			i;	/* temp state */
    -	xfs_ifork_t		*ifp;	/* inode fork pointer */
    -	xfs_fileoff_t		new_endoff;	/* end offset of new entry */
    -	xfs_bmbt_irec_t		r[3];	/* neighbor extent entries */
    -					/* left is 0, right is 1, prev is 2 */
    -	int			rval=0;	/* return value (logging flags) */
    -	int			state = 0;/* state bits, accessed thru macros */
    -	xfs_filblks_t		temp=0;	/* value for dnew calculations */
    -	xfs_filblks_t		temp2=0;/* value for dnew calculations */
    -	int			tmp_rval;	/* partial logging flags */
    -	enum {				/* bit number definitions for state */
    -		LEFT_CONTIG,	RIGHT_CONTIG,
    -		LEFT_FILLING,	RIGHT_FILLING,
    -		LEFT_DELAY,	RIGHT_DELAY,
    -		LEFT_VALID,	RIGHT_VALID
    -	};
    -
    -#define	LEFT		r[0]
    -#define	RIGHT		r[1]
    -#define	PREV		r[2]
    -#define	MASK(b)		(1 << (b))
    -#define	MASK2(a,b)	(MASK(a) | MASK(b))
    -#define	MASK3(a,b,c)	(MASK2(a,b) | MASK(c))
    -#define	MASK4(a,b,c,d)	(MASK3(a,b,c) | MASK(d))
    -#define	STATE_SET(b,v)	((v) ? (state |= MASK(b)) : (state &= ~MASK(b)))
    -#define	STATE_TEST(b)	(state & MASK(b))
    -#define	STATE_SET_TEST(b,v)	((v) ? ((state |= MASK(b)), 1) : \
    -				       ((state &= ~MASK(b)), 0))
    -#define	SWITCH_STATE		\
    -	(state & MASK4(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG))
    -
    -	/*
    -	 * Set up a bunch of variables to make the tests simpler.
    -	 */
    -	cur = *curp;
    -	ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
    -	ep = xfs_iext_get_ext(ifp, idx);
    -	xfs_bmbt_get_all(ep, &PREV);
    -	new_endoff = new->br_startoff + new->br_blockcount;
    -	ASSERT(PREV.br_startoff <= new->br_startoff);
    -	ASSERT(PREV.br_startoff + PREV.br_blockcount >= new_endoff);
    -	/*
    -	 * Set flags determining what part of the previous delayed allocation
    -	 * extent is being replaced by a real allocation.
    -	 */
    -	STATE_SET(LEFT_FILLING, PREV.br_startoff == new->br_startoff);
    -	STATE_SET(RIGHT_FILLING,
    -		PREV.br_startoff + PREV.br_blockcount == new_endoff);
    -	/*
    -	 * Check and set flags if this segment has a left neighbor.
    -	 * Don't set contiguous if the combined extent would be too large.
    -	 */
    -	if (STATE_SET_TEST(LEFT_VALID, idx > 0)) {
    -		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx - 1), &LEFT);
    -		STATE_SET(LEFT_DELAY, ISNULLSTARTBLOCK(LEFT.br_startblock));
    -	}
    -	STATE_SET(LEFT_CONTIG,
    -		STATE_TEST(LEFT_VALID) && !STATE_TEST(LEFT_DELAY) &&
    -		LEFT.br_startoff + LEFT.br_blockcount == new->br_startoff &&
    -		LEFT.br_startblock + LEFT.br_blockcount == new->br_startblock &&
    -		LEFT.br_state == new->br_state &&
    -		LEFT.br_blockcount + new->br_blockcount <= MAXEXTLEN);
    -	/*
    -	 * Check and set flags if this segment has a right neighbor.
    -	 * Don't set contiguous if the combined extent would be too large.
    -	 * Also check for all-three-contiguous being too large.
    -	 */
    -	if (STATE_SET_TEST(RIGHT_VALID,
    -			idx <
    -			ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t) - 1)) {
    -		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx + 1), &RIGHT);
    -		STATE_SET(RIGHT_DELAY, ISNULLSTARTBLOCK(RIGHT.br_startblock));
    -	}
    -	STATE_SET(RIGHT_CONTIG,
    -		STATE_TEST(RIGHT_VALID) && !STATE_TEST(RIGHT_DELAY) &&
    -		new_endoff == RIGHT.br_startoff &&
    -		new->br_startblock + new->br_blockcount ==
    -		    RIGHT.br_startblock &&
    -		new->br_state == RIGHT.br_state &&
    -		new->br_blockcount + RIGHT.br_blockcount <= MAXEXTLEN &&
    -		((state & MASK3(LEFT_CONTIG, LEFT_FILLING, RIGHT_FILLING)) !=
    -		  MASK3(LEFT_CONTIG, LEFT_FILLING, RIGHT_FILLING) ||
    -		 LEFT.br_blockcount + new->br_blockcount + RIGHT.br_blockcount
    -		     <= MAXEXTLEN));
    -	error = 0;
    -	/*
    -	 * Switch out based on the FILLING and CONTIG state bits.
    -	 */
    -	switch (SWITCH_STATE) {
    -
    -	case MASK4(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):
    -		/*
    -		 * Filling in all of a previously delayed allocation extent.
    -		 * The left and right neighbors are both contiguous with new.
    -		 */
    -		xfs_bmap_trace_pre_update(fname, "LF|RF|LC|RC", ip, idx - 1,
    -			XFS_DATA_FORK);
    -		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
    -			LEFT.br_blockcount + PREV.br_blockcount +
    -			RIGHT.br_blockcount);
    -		xfs_bmap_trace_post_update(fname, "LF|RF|LC|RC", ip, idx - 1,
    -			XFS_DATA_FORK);
    -		xfs_bmap_trace_delete(fname, "LF|RF|LC|RC", ip, idx, 2,
    -			XFS_DATA_FORK);
    -		xfs_iext_remove(ifp, idx, 2);
    -		ip->i_df.if_lastex = idx - 1;
    -		ip->i_d.di_nextents--;
    -		if (cur == NULL)
    -			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
    -		else {
    -			rval = XFS_ILOG_CORE;
    -			if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff,
    -					RIGHT.br_startblock,
    -					RIGHT.br_blockcount, &i)))
    -				goto done;
    -			ASSERT(i == 1);
    -			if ((error = xfs_bmbt_delete(cur, &i)))
    -				goto done;
    -			ASSERT(i == 1);
    -			if ((error = xfs_bmbt_decrement(cur, 0, &i)))
    -				goto done;
    -			ASSERT(i == 1);
    -			if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
    -					LEFT.br_startblock,
    -					LEFT.br_blockcount +
    -					PREV.br_blockcount +
    -					RIGHT.br_blockcount, LEFT.br_state)))
    -				goto done;
    -		}
    -		*dnew = 0;
    -		/* DELTA: Three in-core extents are replaced by one. */
    -		temp = LEFT.br_startoff;
    -		temp2 = LEFT.br_blockcount +
    -			PREV.br_blockcount +
    -			RIGHT.br_blockcount;
    -		break;
    -
    -	case MASK3(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG):
    -		/*
    -		 * Filling in all of a previously delayed allocation extent.
    -		 * The left neighbor is contiguous, the right is not.
    -		 */
    -		xfs_bmap_trace_pre_update(fname, "LF|RF|LC", ip, idx - 1,
    -			XFS_DATA_FORK);
    -		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
    -			LEFT.br_blockcount + PREV.br_blockcount);
    -		xfs_bmap_trace_post_update(fname, "LF|RF|LC", ip, idx - 1,
    -			XFS_DATA_FORK);
    -		ip->i_df.if_lastex = idx - 1;
    -		xfs_bmap_trace_delete(fname, "LF|RF|LC", ip, idx, 1,
    -			XFS_DATA_FORK);
    -		xfs_iext_remove(ifp, idx, 1);
    -		if (cur == NULL)
    -			rval = XFS_ILOG_DEXT;
    -		else {
    -			rval = 0;
    -			if ((error = xfs_bmbt_lookup_eq(cur, LEFT.br_startoff,
    -					LEFT.br_startblock, LEFT.br_blockcount,
    -					&i)))
    -				goto done;
    -			ASSERT(i == 1);
    -			if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
    -					LEFT.br_startblock,
    -					LEFT.br_blockcount +
    -					PREV.br_blockcount, LEFT.br_state)))
    -				goto done;
    -		}
    -		*dnew = 0;
    -		/* DELTA: Two in-core extents are replaced by one. */
    -		temp = LEFT.br_startoff;
    -		temp2 = LEFT.br_blockcount +
    -			PREV.br_blockcount;
    -		break;
    -
    -	case MASK3(LEFT_FILLING, RIGHT_FILLING, RIGHT_CONTIG):
    -		/*
    -		 * Filling in all of a previously delayed allocation extent.
    -		 * The right neighbor is contiguous, the left is not.
    -		 */
    -		xfs_bmap_trace_pre_update(fname, "LF|RF|RC", ip, idx,
    -			XFS_DATA_FORK);
    -		xfs_bmbt_set_startblock(ep, new->br_startblock);
    -		xfs_bmbt_set_blockcount(ep,
    -			PREV.br_blockcount + RIGHT.br_blockcount);
    -		xfs_bmap_trace_post_update(fname, "LF|RF|RC", ip, idx,
    -			XFS_DATA_FORK);
    -		ip->i_df.if_lastex = idx;
    -		xfs_bmap_trace_delete(fname, "LF|RF|RC", ip, idx + 1, 1,
    -			XFS_DATA_FORK);
    -		xfs_iext_remove(ifp, idx + 1, 1);
    -		if (cur == NULL)
    -			rval = XFS_ILOG_DEXT;
    -		else {
    -			rval = 0;
    -			if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff,
    -					RIGHT.br_startblock,
    -					RIGHT.br_blockcount, &i)))
    -				goto done;
    -			ASSERT(i == 1);
    -			if ((error = xfs_bmbt_update(cur, PREV.br_startoff,
    -					new->br_startblock,
    -					PREV.br_blockcount +
    -					RIGHT.br_blockcount, PREV.br_state)))
    -				goto done;
    -		}
    -		*dnew = 0;
    -		/* DELTA: Two in-core extents are replaced by one. */
    -		temp = PREV.br_startoff;
    -		temp2 = PREV.br_blockcount +
    -			RIGHT.br_blockcount;
    -		break;
    -
    -	case MASK2(LEFT_FILLING, RIGHT_FILLING):
    -		/*
    -		 * Filling in all of a previously delayed allocation extent.
    -		 * Neither the left nor right neighbors are contiguous with
    -		 * the new one.
    -		 */
    -		xfs_bmap_trace_pre_update(fname, "LF|RF", ip, idx,
    -			XFS_DATA_FORK);
    -		xfs_bmbt_set_startblock(ep, new->br_startblock);
    -		xfs_bmap_trace_post_update(fname, "LF|RF", ip, idx,
    -			XFS_DATA_FORK);
    -		ip->i_df.if_lastex = idx;
    -		ip->i_d.di_nextents++;
    -		if (cur == NULL)
    -			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
    -		else {
    -			rval = XFS_ILOG_CORE;
    -			if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
    -					new->br_startblock, new->br_blockcount,
    -					&i)))
    -				goto done;
    -			ASSERT(i == 0);
    -			cur->bc_rec.b.br_state = XFS_EXT_NORM;
    -			if ((error = xfs_bmbt_insert(cur, &i)))
    -				goto done;
    -			ASSERT(i == 1);
    -		}
    -		*dnew = 0;
    -		/* DELTA: The in-core extent described by new changed type. */
    -		temp = new->br_startoff;
    -		temp2 = new->br_blockcount;
    -		break;
    -
    -	case MASK2(LEFT_FILLING, LEFT_CONTIG):
    -		/*
    -		 * Filling in the first part of a previous delayed allocation.
    -		 * The left neighbor is contiguous.
    -		 */
    -		xfs_bmap_trace_pre_update(fname, "LF|LC", ip, idx - 1,
    -			XFS_DATA_FORK);
    -		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
    -			LEFT.br_blockcount + new->br_blockcount);
    -		xfs_bmbt_set_startoff(ep,
    -			PREV.br_startoff + new->br_blockcount);
    -		xfs_bmap_trace_post_update(fname, "LF|LC", ip, idx - 1,
    -			XFS_DATA_FORK);
    -		temp = PREV.br_blockcount - new->br_blockcount;
    -		xfs_bmap_trace_pre_update(fname, "LF|LC", ip, idx,
    -			XFS_DATA_FORK);
    -		xfs_bmbt_set_blockcount(ep, temp);
    -		ip->i_df.if_lastex = idx - 1;
    -		if (cur == NULL)
    -			rval = XFS_ILOG_DEXT;
    -		else {
    -			rval = 0;
    -			if ((error = xfs_bmbt_lookup_eq(cur, LEFT.br_startoff,
    -					LEFT.br_startblock, LEFT.br_blockcount,
    -					&i)))
    -				goto done;
    -			ASSERT(i == 1);
    -			if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
    -					LEFT.br_startblock,
    -					LEFT.br_blockcount +
    -					new->br_blockcount,
    -					LEFT.br_state)))
    -				goto done;
    -		}
    -		temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
    -			STARTBLOCKVAL(PREV.br_startblock));
    -		xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
    -		xfs_bmap_trace_post_update(fname, "LF|LC", ip, idx,
    -			XFS_DATA_FORK);
    -		*dnew = temp;
    -		/* DELTA: The boundary between two in-core extents moved. */
    -		temp = LEFT.br_startoff;
    -		temp2 = LEFT.br_blockcount +
    -			PREV.br_blockcount;
    -		break;
    -
    -	case MASK(LEFT_FILLING):
    -		/*
    -		 * Filling in the first part of a previous delayed allocation.
    -		 * The left neighbor is not contiguous.
    -		 */
    -		xfs_bmap_trace_pre_update(fname, "LF", ip, idx, XFS_DATA_FORK);
    -		xfs_bmbt_set_startoff(ep, new_endoff);
    -		temp = PREV.br_blockcount - new->br_blockcount;
    -		xfs_bmbt_set_blockcount(ep, temp);
    -		xfs_bmap_trace_insert(fname, "LF", ip, idx, 1, new, NULL,
    -			XFS_DATA_FORK);
    -		xfs_iext_insert(ifp, idx, 1, new);
    -		ip->i_df.if_lastex = idx;
    -		ip->i_d.di_nextents++;
    -		if (cur == NULL)
    -			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
    -		else {
    -			rval = XFS_ILOG_CORE;
    -			if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
    -					new->br_startblock, new->br_blockcount,
    -					&i)))
    -				goto done;
    -			ASSERT(i == 0);
    -			cur->bc_rec.b.br_state = XFS_EXT_NORM;
    -			if ((error = xfs_bmbt_insert(cur, &i)))
    -				goto done;
    -			ASSERT(i == 1);
    -		}
    -		if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
    -		    ip->i_d.di_nextents > ip->i_df.if_ext_max) {
    -			error = xfs_bmap_extents_to_btree(ip->i_transp, ip,
    -					first, flist, &cur, 1, &tmp_rval,
    -					XFS_DATA_FORK);
    -			rval |= tmp_rval;
    -			if (error)
    -				goto done;
    -		}
    -		temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
    -			STARTBLOCKVAL(PREV.br_startblock) -
    -			(cur ? cur->bc_private.b.allocated : 0));
    -		ep = xfs_iext_get_ext(ifp, idx + 1);
    -		xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
    -		xfs_bmap_trace_post_update(fname, "LF", ip, idx + 1,
    -			XFS_DATA_FORK);
    -		*dnew = temp;
    -		/* DELTA: One in-core extent is split in two. */
    -		temp = PREV.br_startoff;
    -		temp2 = PREV.br_blockcount;
    -		break;
    -
    -	case MASK2(RIGHT_FILLING, RIGHT_CONTIG):
    -		/*
    -		 * Filling in the last part of a previous delayed allocation.
    -		 * The right neighbor is contiguous with the new allocation.
    -		 */
    -		temp = PREV.br_blockcount - new->br_blockcount;
    -		xfs_bmap_trace_pre_update(fname, "RF|RC", ip, idx,
    -			XFS_DATA_FORK);
    -		xfs_bmap_trace_pre_update(fname, "RF|RC", ip, idx + 1,
    -			XFS_DATA_FORK);
    -		xfs_bmbt_set_blockcount(ep, temp);
    -		xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, idx + 1),
    -			new->br_startoff, new->br_startblock,
    -			new->br_blockcount + RIGHT.br_blockcount,
    -			RIGHT.br_state);
    -		xfs_bmap_trace_post_update(fname, "RF|RC", ip, idx + 1,
    -			XFS_DATA_FORK);
    -		ip->i_df.if_lastex = idx + 1;
    -		if (cur == NULL)
    -			rval = XFS_ILOG_DEXT;
    -		else {
    -			rval = 0;
    -			if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff,
    -					RIGHT.br_startblock,
    -					RIGHT.br_blockcount, &i)))
    -				goto done;
    -			ASSERT(i == 1);
    -			if ((error = xfs_bmbt_update(cur, new->br_startoff,
    -					new->br_startblock,
    -					new->br_blockcount +
    -					RIGHT.br_blockcount,
    -					RIGHT.br_state)))
    -				goto done;
    -		}
    -		temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
    -			STARTBLOCKVAL(PREV.br_startblock));
    -		xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
    -		xfs_bmap_trace_post_update(fname, "RF|RC", ip, idx,
    -			XFS_DATA_FORK);
    -		*dnew = temp;
    -		/* DELTA: The boundary between two in-core extents moved. */
    -		temp = PREV.br_startoff;
    -		temp2 = PREV.br_blockcount +
    -			RIGHT.br_blockcount;
    -		break;
    -
    -	case MASK(RIGHT_FILLING):
    -		/*
    -		 * Filling in the last part of a previous delayed allocation.
    -		 * The right neighbor is not contiguous.
    -		 */
    -		temp = PREV.br_blockcount - new->br_blockcount;
    -		xfs_bmap_trace_pre_update(fname, "RF", ip, idx, XFS_DATA_FORK);
    -		xfs_bmbt_set_blockcount(ep, temp);
    -		xfs_bmap_trace_insert(fname, "RF", ip, idx + 1, 1,
    -			new, NULL, XFS_DATA_FORK);
    -		xfs_iext_insert(ifp, idx + 1, 1, new);
    -		ip->i_df.if_lastex = idx + 1;
    -		ip->i_d.di_nextents++;
    -		if (cur == NULL)
    -			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
    -		else {
    -			rval = XFS_ILOG_CORE;
    -			if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
    -					new->br_startblock, new->br_blockcount,
    -					&i)))
    -				goto done;
    -			ASSERT(i == 0);
    -			cur->bc_rec.b.br_state = XFS_EXT_NORM;
    -			if ((error = xfs_bmbt_insert(cur, &i)))
    -				goto done;
    -			ASSERT(i == 1);
    -		}
    -		if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
    -		    ip->i_d.di_nextents > ip->i_df.if_ext_max) {
    -			error = xfs_bmap_extents_to_btree(ip->i_transp, ip,
    -				first, flist, &cur, 1, &tmp_rval,
    -				XFS_DATA_FORK);
    -			rval |= tmp_rval;
    -			if (error)
    -				goto done;
    -		}
    -		temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
    -			STARTBLOCKVAL(PREV.br_startblock) -
    -			(cur ? cur->bc_private.b.allocated : 0));
    -		ep = xfs_iext_get_ext(ifp, idx);
    -		xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
    -		xfs_bmap_trace_post_update(fname, "RF", ip, idx, XFS_DATA_FORK);
    -		*dnew = temp;
    -		/* DELTA: One in-core extent is split in two. */
    -		temp = PREV.br_startoff;
    -		temp2 = PREV.br_blockcount;
    -		break;
    -
    -	case 0:
    -		/*
    -		 * Filling in the middle part of a previous delayed allocation.
    -		 * Contiguity is impossible here.
    -		 * This case is avoided almost all the time.
    -		 */
    -		temp = new->br_startoff - PREV.br_startoff;
    -		xfs_bmap_trace_pre_update(fname, "0", ip, idx, XFS_DATA_FORK);
    -		xfs_bmbt_set_blockcount(ep, temp);
    -		r[0] = *new;
    -		r[1].br_startoff = new_endoff;
    -		temp2 = PREV.br_startoff + PREV.br_blockcount - new_endoff;
    -		r[1].br_blockcount = temp2;
    -		xfs_bmap_trace_insert(fname, "0", ip, idx + 1, 2, &r[0], &r[1],
    -			XFS_DATA_FORK);
    -		xfs_iext_insert(ifp, idx + 1, 2, &r[0]);
    -		ip->i_df.if_lastex = idx + 1;
    -		ip->i_d.di_nextents++;
    -		if (cur == NULL)
    -			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
    -		else {
    -			rval = XFS_ILOG_CORE;
    -			if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
    -					new->br_startblock, new->br_blockcount,
    -					&i)))
    -				goto done;
    -			ASSERT(i == 0);
    -			cur->bc_rec.b.br_state = XFS_EXT_NORM;
    -			if ((error = xfs_bmbt_insert(cur, &i)))
    -				goto done;
    -			ASSERT(i == 1);
    -		}
    -		if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS &&
    -		    ip->i_d.di_nextents > ip->i_df.if_ext_max) {
    -			error = xfs_bmap_extents_to_btree(ip->i_transp, ip,
    -					first, flist, &cur, 1, &tmp_rval,
    -					XFS_DATA_FORK);
    -			rval |= tmp_rval;
    -			if (error)
    -				goto done;
    -		}
    -		temp = xfs_bmap_worst_indlen(ip, temp);
    -		temp2 = xfs_bmap_worst_indlen(ip, temp2);
    -		diff = (int)(temp + temp2 - STARTBLOCKVAL(PREV.br_startblock) -
    -			(cur ? cur->bc_private.b.allocated : 0));
    -		if (diff > 0 &&
    -		    xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS, -diff, rsvd)) {
    -			/*
    -			 * Ick gross gag me with a spoon.
    -			 */
    -			ASSERT(0);	/* want to see if this ever happens! */
    -			while (diff > 0) {
    -				if (temp) {
    -					temp--;
    -					diff--;
    -					if (!diff ||
    -					    !xfs_mod_incore_sb(ip->i_mount,
    -						    XFS_SBS_FDBLOCKS, -diff, rsvd))
    -						break;
    -				}
    -				if (temp2) {
    -					temp2--;
    -					diff--;
    -					if (!diff ||
    -					    !xfs_mod_incore_sb(ip->i_mount,
    -						    XFS_SBS_FDBLOCKS, -diff, rsvd))
    -						break;
    -				}
    -			}
    -		}
    -		ep = xfs_iext_get_ext(ifp, idx);
    -		xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
    -		xfs_bmap_trace_post_update(fname, "0", ip, idx, XFS_DATA_FORK);
    -		xfs_bmap_trace_pre_update(fname, "0", ip, idx + 2,
    -			XFS_DATA_FORK);
    -		xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, idx + 2),
    -			NULLSTARTBLOCK((int)temp2));
    -		xfs_bmap_trace_post_update(fname, "0", ip, idx + 2,
    -			XFS_DATA_FORK);
    -		*dnew = temp + temp2;
    -		/* DELTA: One in-core extent is split in three. */
    -		temp = PREV.br_startoff;
    -		temp2 = PREV.br_blockcount;
    -		break;
    -
    -	case MASK3(LEFT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):
    -	case MASK3(RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):
    -	case MASK2(LEFT_FILLING, RIGHT_CONTIG):
    -	case MASK2(RIGHT_FILLING, LEFT_CONTIG):
    -	case MASK2(LEFT_CONTIG, RIGHT_CONTIG):
    -	case MASK(LEFT_CONTIG):
    -	case MASK(RIGHT_CONTIG):
    -		/*
    -		 * These cases are all impossible.
    -		 */
    -		ASSERT(0);
    -	}
    -	*curp = cur;
    -	if (delta) {
    -		temp2 += temp;
    -		if (delta->xed_startoff > temp)
    -			delta->xed_startoff = temp;
    -		if (delta->xed_blockcount < temp2)
    -			delta->xed_blockcount = temp2;
    -	}
    -done:
    -	*logflagsp = rval;
    -	return error;
    -#undef	LEFT
    -#undef	RIGHT
    -#undef	PREV
    -#undef	MASK
    -#undef	MASK2
    -#undef	MASK3
    -#undef	MASK4
    -#undef	STATE_SET
    -#undef	STATE_TEST
    -#undef	STATE_SET_TEST
    -#undef	SWITCH_STATE
    -}
    -
    -/*
    - * Called by xfs_bmap_add_extent to handle cases converting an unwritten
    - * allocation to a real allocation or vice versa.
    - */
    -STATIC int				/* error */
    -xfs_bmap_add_extent_unwritten_real(
    -	xfs_inode_t		*ip,	/* incore inode pointer */
    -	xfs_extnum_t		idx,	/* extent number to update/insert */
    -	xfs_btree_cur_t		**curp,	/* if *curp is null, not a btree */
    -	xfs_bmbt_irec_t		*new,	/* new data to add to file extents */
    -	int			*logflagsp, /* inode logging flags */
    -	xfs_extdelta_t		*delta) /* Change made to incore extents */
    -{
    -	xfs_btree_cur_t		*cur;	/* btree cursor */
    -	xfs_bmbt_rec_t		*ep;	/* extent entry for idx */
    -	int			error;	/* error return value */
    -#ifdef XFS_BMAP_TRACE
    -	static char		fname[] = "xfs_bmap_add_extent_unwritten_real";
    -#endif
    -	int			i;	/* temp state */
    -	xfs_ifork_t		*ifp;	/* inode fork pointer */
    -	xfs_fileoff_t		new_endoff;	/* end offset of new entry */
    -	xfs_exntst_t		newext;	/* new extent state */
    -	xfs_exntst_t		oldext;	/* old extent state */
    -	xfs_bmbt_irec_t		r[3];	/* neighbor extent entries */
    -					/* left is 0, right is 1, prev is 2 */
    -	int			rval=0;	/* return value (logging flags) */
    -	int			state = 0;/* state bits, accessed thru macros */
    -	xfs_filblks_t		temp=0;
    -	xfs_filblks_t		temp2=0;
    -	enum {				/* bit number definitions for state */
    -		LEFT_CONTIG,	RIGHT_CONTIG,
    -		LEFT_FILLING,	RIGHT_FILLING,
    -		LEFT_DELAY,	RIGHT_DELAY,
    -		LEFT_VALID,	RIGHT_VALID
    -	};
    -
    -#define	LEFT		r[0]
    -#define	RIGHT		r[1]
    -#define	PREV		r[2]
    -#define	MASK(b)		(1 << (b))
    -#define	MASK2(a,b)	(MASK(a) | MASK(b))
    -#define	MASK3(a,b,c)	(MASK2(a,b) | MASK(c))
    -#define	MASK4(a,b,c,d)	(MASK3(a,b,c) | MASK(d))
    -#define	STATE_SET(b,v)	((v) ? (state |= MASK(b)) : (state &= ~MASK(b)))
    -#define	STATE_TEST(b)	(state & MASK(b))
    -#define	STATE_SET_TEST(b,v)	((v) ? ((state |= MASK(b)), 1) : \
    -				       ((state &= ~MASK(b)), 0))
    -#define	SWITCH_STATE		\
    -	(state & MASK4(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG))
    -
    -	/*
    -	 * Set up a bunch of variables to make the tests simpler.
    -	 */
    -	error = 0;
    -	cur = *curp;
    -	ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
    -	ep = xfs_iext_get_ext(ifp, idx);
    -	xfs_bmbt_get_all(ep, &PREV);
    -	newext = new->br_state;
    -	oldext = (newext == XFS_EXT_UNWRITTEN) ?
    -		XFS_EXT_NORM : XFS_EXT_UNWRITTEN;
    -	ASSERT(PREV.br_state == oldext);
    -	new_endoff = new->br_startoff + new->br_blockcount;
    -	ASSERT(PREV.br_startoff <= new->br_startoff);
    -	ASSERT(PREV.br_startoff + PREV.br_blockcount >= new_endoff);
    -	/*
    -	 * Set flags determining what part of the previous oldext allocation
    -	 * extent is being replaced by a newext allocation.
    -	 */
    -	STATE_SET(LEFT_FILLING, PREV.br_startoff == new->br_startoff);
    -	STATE_SET(RIGHT_FILLING,
    -		PREV.br_startoff + PREV.br_blockcount == new_endoff);
    -	/*
    -	 * Check and set flags if this segment has a left neighbor.
    -	 * Don't set contiguous if the combined extent would be too large.
    -	 */
    -	if (STATE_SET_TEST(LEFT_VALID, idx > 0)) {
    -		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx - 1), &LEFT);
    -		STATE_SET(LEFT_DELAY, ISNULLSTARTBLOCK(LEFT.br_startblock));
    -	}
    -	STATE_SET(LEFT_CONTIG,
    -		STATE_TEST(LEFT_VALID) && !STATE_TEST(LEFT_DELAY) &&
    -		LEFT.br_startoff + LEFT.br_blockcount == new->br_startoff &&
    -		LEFT.br_startblock + LEFT.br_blockcount == new->br_startblock &&
    -		LEFT.br_state == newext &&
    -		LEFT.br_blockcount + new->br_blockcount <= MAXEXTLEN);
    -	/*
    -	 * Check and set flags if this segment has a right neighbor.
    -	 * Don't set contiguous if the combined extent would be too large.
    -	 * Also check for all-three-contiguous being too large.
    -	 */
    -	if (STATE_SET_TEST(RIGHT_VALID,
    -			idx <
    -			ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t) - 1)) {
    -		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx + 1), &RIGHT);
    -		STATE_SET(RIGHT_DELAY, ISNULLSTARTBLOCK(RIGHT.br_startblock));
    -	}
    -	STATE_SET(RIGHT_CONTIG,
    -		STATE_TEST(RIGHT_VALID) && !STATE_TEST(RIGHT_DELAY) &&
    -		new_endoff == RIGHT.br_startoff &&
    -		new->br_startblock + new->br_blockcount ==
    -		    RIGHT.br_startblock &&
    -		newext == RIGHT.br_state &&
    -		new->br_blockcount + RIGHT.br_blockcount <= MAXEXTLEN &&
    -		((state & MASK3(LEFT_CONTIG, LEFT_FILLING, RIGHT_FILLING)) !=
    -		  MASK3(LEFT_CONTIG, LEFT_FILLING, RIGHT_FILLING) ||
    -		 LEFT.br_blockcount + new->br_blockcount + RIGHT.br_blockcount
    -		     <= MAXEXTLEN));
    -	/*
    -	 * Switch out based on the FILLING and CONTIG state bits.
    -	 */
    -	switch (SWITCH_STATE) {
    -
    -	case MASK4(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):
    -		/*
    -		 * Setting all of a previous oldext extent to newext.
    -		 * The left and right neighbors are both contiguous with new.
    -		 */
    -		xfs_bmap_trace_pre_update(fname, "LF|RF|LC|RC", ip, idx - 1,
    -			XFS_DATA_FORK);
    -		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
    -			LEFT.br_blockcount + PREV.br_blockcount +
    -			RIGHT.br_blockcount);
    -		xfs_bmap_trace_post_update(fname, "LF|RF|LC|RC", ip, idx - 1,
    -			XFS_DATA_FORK);
    -		xfs_bmap_trace_delete(fname, "LF|RF|LC|RC", ip, idx, 2,
    -			XFS_DATA_FORK);
    -		xfs_iext_remove(ifp, idx, 2);
    -		ip->i_df.if_lastex = idx - 1;
    -		ip->i_d.di_nextents -= 2;
    -		if (cur == NULL)
    -			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
    -		else {
    -			rval = XFS_ILOG_CORE;
    -			if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff,
    -					RIGHT.br_startblock,
    -					RIGHT.br_blockcount, &i)))
    -				goto done;
    -			ASSERT(i == 1);
    -			if ((error = xfs_bmbt_delete(cur, &i)))
    -				goto done;
    -			ASSERT(i == 1);
    -			if ((error = xfs_bmbt_decrement(cur, 0, &i)))
    -				goto done;
    -			ASSERT(i == 1);
    -			if ((error = xfs_bmbt_delete(cur, &i)))
    -				goto done;
    -			ASSERT(i == 1);
    -			if ((error = xfs_bmbt_decrement(cur, 0, &i)))
    -				goto done;
    -			ASSERT(i == 1);
    -			if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
    -				LEFT.br_startblock,
    -				LEFT.br_blockcount + PREV.br_blockcount +
    -				RIGHT.br_blockcount, LEFT.br_state)))
    -				goto done;
    -		}
    -		/* DELTA: Three in-core extents are replaced by one. */
    -		temp = LEFT.br_startoff;
    -		temp2 = LEFT.br_blockcount +
    -			PREV.br_blockcount +
    -			RIGHT.br_blockcount;
    -		break;
    -
    -	case MASK3(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG):
    -		/*
    -		 * Setting all of a previous oldext extent to newext.
    -		 * The left neighbor is contiguous, the right is not.
    -		 */
    -		xfs_bmap_trace_pre_update(fname, "LF|RF|LC", ip, idx - 1,
    -			XFS_DATA_FORK);
    -		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
    -			LEFT.br_blockcount + PREV.br_blockcount);
    -		xfs_bmap_trace_post_update(fname, "LF|RF|LC", ip, idx - 1,
    -			XFS_DATA_FORK);
    -		ip->i_df.if_lastex = idx - 1;
    -		xfs_bmap_trace_delete(fname, "LF|RF|LC", ip, idx, 1,
    -			XFS_DATA_FORK);
    -		xfs_iext_remove(ifp, idx, 1);
    -		ip->i_d.di_nextents--;
    -		if (cur == NULL)
    -			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
    -		else {
    -			rval = XFS_ILOG_CORE;
    -			if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
    -					PREV.br_startblock, PREV.br_blockcount,
    -					&i)))
    -				goto done;
    -			ASSERT(i == 1);
    -			if ((error = xfs_bmbt_delete(cur, &i)))
    -				goto done;
    -			ASSERT(i == 1);
    -			if ((error = xfs_bmbt_decrement(cur, 0, &i)))
    -				goto done;
    -			ASSERT(i == 1);
    -			if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
    -				LEFT.br_startblock,
    -				LEFT.br_blockcount + PREV.br_blockcount,
    -				LEFT.br_state)))
    -				goto done;
    -		}
    -		/* DELTA: Two in-core extents are replaced by one. */
    -		temp = LEFT.br_startoff;
    -		temp2 = LEFT.br_blockcount +
    -			PREV.br_blockcount;
    -		break;
    -
    -	case MASK3(LEFT_FILLING, RIGHT_FILLING, RIGHT_CONTIG):
    -		/*
    -		 * Setting all of a previous oldext extent to newext.
    -		 * The right neighbor is contiguous, the left is not.
    -		 */
    -		xfs_bmap_trace_pre_update(fname, "LF|RF|RC", ip, idx,
    -			XFS_DATA_FORK);
    -		xfs_bmbt_set_blockcount(ep,
    -			PREV.br_blockcount + RIGHT.br_blockcount);
    -		xfs_bmbt_set_state(ep, newext);
    -		xfs_bmap_trace_post_update(fname, "LF|RF|RC", ip, idx,
    -			XFS_DATA_FORK);
    -		ip->i_df.if_lastex = idx;
    -		xfs_bmap_trace_delete(fname, "LF|RF|RC", ip, idx + 1, 1,
    -			XFS_DATA_FORK);
    -		xfs_iext_remove(ifp, idx + 1, 1);
    -		ip->i_d.di_nextents--;
    -		if (cur == NULL)
    -			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
    -		else {
    -			rval = XFS_ILOG_CORE;
    -			if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff,
    -					RIGHT.br_startblock,
    -					RIGHT.br_blockcount, &i)))
    -				goto done;
    -			ASSERT(i == 1);
    -			if ((error = xfs_bmbt_delete(cur, &i)))
    -				goto done;
    -			ASSERT(i == 1);
    -			if ((error = xfs_bmbt_decrement(cur, 0, &i)))
    -				goto done;
    -			ASSERT(i == 1);
    -			if ((error = xfs_bmbt_update(cur, new->br_startoff,
    -				new->br_startblock,
    -				new->br_blockcount + RIGHT.br_blockcount,
    -				newext)))
    -				goto done;
    -		}
    -		/* DELTA: Two in-core extents are replaced by one. */
    -		temp = PREV.br_startoff;
    -		temp2 = PREV.br_blockcount +
    -			RIGHT.br_blockcount;
    -		break;
    -
    -	case MASK2(LEFT_FILLING, RIGHT_FILLING):
    -		/*
    -		 * Setting all of a previous oldext extent to newext.
    -		 * Neither the left nor right neighbors are contiguous with
    -		 * the new one.
    -		 */
    -		xfs_bmap_trace_pre_update(fname, "LF|RF", ip, idx,
    -			XFS_DATA_FORK);
    -		xfs_bmbt_set_state(ep, newext);
    -		xfs_bmap_trace_post_update(fname, "LF|RF", ip, idx,
    -			XFS_DATA_FORK);
    -		ip->i_df.if_lastex = idx;
    -		if (cur == NULL)
    -			rval = XFS_ILOG_DEXT;
    -		else {
    -			rval = 0;
    -			if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
    -					new->br_startblock, new->br_blockcount,
    -					&i)))
    -				goto done;
    -			ASSERT(i == 1);
    -			if ((error = xfs_bmbt_update(cur, new->br_startoff,
    -				new->br_startblock, new->br_blockcount,
    -				newext)))
    -				goto done;
    -		}
    -		/* DELTA: The in-core extent described by new changed type. */
    -		temp = new->br_startoff;
    -		temp2 = new->br_blockcount;
    -		break;
    -
    -	case MASK2(LEFT_FILLING, LEFT_CONTIG):
    -		/*
    -		 * Setting the first part of a previous oldext extent to newext.
    -		 * The left neighbor is contiguous.
    -		 */
    -		xfs_bmap_trace_pre_update(fname, "LF|LC", ip, idx - 1,
    -			XFS_DATA_FORK);
    -		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
    -			LEFT.br_blockcount + new->br_blockcount);
    -		xfs_bmbt_set_startoff(ep,
    -			PREV.br_startoff + new->br_blockcount);
    -		xfs_bmap_trace_post_update(fname, "LF|LC", ip, idx - 1,
    -			XFS_DATA_FORK);
    -		xfs_bmap_trace_pre_update(fname, "LF|LC", ip, idx,
    -			XFS_DATA_FORK);
    -		xfs_bmbt_set_startblock(ep,
    -			new->br_startblock + new->br_blockcount);
    -		xfs_bmbt_set_blockcount(ep,
    -			PREV.br_blockcount - new->br_blockcount);
    -		xfs_bmap_trace_post_update(fname, "LF|LC", ip, idx,
    -			XFS_DATA_FORK);
    -		ip->i_df.if_lastex = idx - 1;
    -		if (cur == NULL)
    -			rval = XFS_ILOG_DEXT;
    -		else {
    -			rval = 0;
    -			if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
    -					PREV.br_startblock, PREV.br_blockcount,
    -					&i)))
    -				goto done;
    -			ASSERT(i == 1);
    -			if ((error = xfs_bmbt_update(cur,
    -				PREV.br_startoff + new->br_blockcount,
    -				PREV.br_startblock + new->br_blockcount,
    -				PREV.br_blockcount - new->br_blockcount,
    -				oldext)))
    -				goto done;
    -			if ((error = xfs_bmbt_decrement(cur, 0, &i)))
    -				goto done;
    -			if (xfs_bmbt_update(cur, LEFT.br_startoff,
    -				LEFT.br_startblock,
    -				LEFT.br_blockcount + new->br_blockcount,
    -				LEFT.br_state))
    -				goto done;
    -		}
    -		/* DELTA: The boundary between two in-core extents moved. */
    -		temp = LEFT.br_startoff;
    -		temp2 = LEFT.br_blockcount +
    -			PREV.br_blockcount;
    -		break;
    -
    -	case MASK(LEFT_FILLING):
    -		/*
    -		 * Setting the first part of a previous oldext extent to newext.
    -		 * The left neighbor is not contiguous.
    -		 */
    -		xfs_bmap_trace_pre_update(fname, "LF", ip, idx, XFS_DATA_FORK);
    -		ASSERT(ep && xfs_bmbt_get_state(ep) == oldext);
    -		xfs_bmbt_set_startoff(ep, new_endoff);
    -		xfs_bmbt_set_blockcount(ep,
    -			PREV.br_blockcount - new->br_blockcount);
    -		xfs_bmbt_set_startblock(ep,
    -			new->br_startblock + new->br_blockcount);
    -		xfs_bmap_trace_post_update(fname, "LF", ip, idx, XFS_DATA_FORK);
    -		xfs_bmap_trace_insert(fname, "LF", ip, idx, 1, new, NULL,
    -			XFS_DATA_FORK);
    -		xfs_iext_insert(ifp, idx, 1, new);
    -		ip->i_df.if_lastex = idx;
    -		ip->i_d.di_nextents++;
    -		if (cur == NULL)
    -			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
    -		else {
    -			rval = XFS_ILOG_CORE;
    -			if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
    -					PREV.br_startblock, PREV.br_blockcount,
    -					&i)))
    -				goto done;
    -			ASSERT(i == 1);
    -			if ((error = xfs_bmbt_update(cur,
    -				PREV.br_startoff + new->br_blockcount,
    -				PREV.br_startblock + new->br_blockcount,
    -				PREV.br_blockcount - new->br_blockcount,
    -				oldext)))
    -				goto done;
    -			cur->bc_rec.b = *new;
    -			if ((error = xfs_bmbt_insert(cur, &i)))
    -				goto done;
    -			ASSERT(i == 1);
    -		}
    -		/* DELTA: One in-core extent is split in two. */
    -		temp = PREV.br_startoff;
    -		temp2 = PREV.br_blockcount;
    -		break;
    -
    -	case MASK2(RIGHT_FILLING, RIGHT_CONTIG):
    -		/*
    -		 * Setting the last part of a previous oldext extent to newext.
    -		 * The right neighbor is contiguous with the new allocation.
    -		 */
    -		xfs_bmap_trace_pre_update(fname, "RF|RC", ip, idx,
    -			XFS_DATA_FORK);
    -		xfs_bmap_trace_pre_update(fname, "RF|RC", ip, idx + 1,
    -			XFS_DATA_FORK);
    -		xfs_bmbt_set_blockcount(ep,
    -			PREV.br_blockcount - new->br_blockcount);
    -		xfs_bmap_trace_post_update(fname, "RF|RC", ip, idx,
    -			XFS_DATA_FORK);
    -		xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, idx + 1),
    -			new->br_startoff, new->br_startblock,
    -			new->br_blockcount + RIGHT.br_blockcount, newext);
    -		xfs_bmap_trace_post_update(fname, "RF|RC", ip, idx + 1,
    -			XFS_DATA_FORK);
    -		ip->i_df.if_lastex = idx + 1;
    -		if (cur == NULL)
    -			rval = XFS_ILOG_DEXT;
    -		else {
    -			rval = 0;
    -			if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
    -					PREV.br_startblock,
    -					PREV.br_blockcount, &i)))
    -				goto done;
    -			ASSERT(i == 1);
    -			if ((error = xfs_bmbt_update(cur, PREV.br_startoff,
    -				PREV.br_startblock,
    -				PREV.br_blockcount - new->br_blockcount,
    -				oldext)))
    -				goto done;
    -			if ((error = xfs_bmbt_increment(cur, 0, &i)))
    -				goto done;
    -			if ((error = xfs_bmbt_update(cur, new->br_startoff,
    -				new->br_startblock,
    -				new->br_blockcount + RIGHT.br_blockcount,
    -				newext)))
    -				goto done;
    -		}
    -		/* DELTA: The boundary between two in-core extents moved. */
    -		temp = PREV.br_startoff;
    -		temp2 = PREV.br_blockcount +
    -			RIGHT.br_blockcount;
    -		break;
    -
    -	case MASK(RIGHT_FILLING):
    -		/*
    -		 * Setting the last part of a previous oldext extent to newext.
    -		 * The right neighbor is not contiguous.
    -		 */
    -		xfs_bmap_trace_pre_update(fname, "RF", ip, idx, XFS_DATA_FORK);
    -		xfs_bmbt_set_blockcount(ep,
    -			PREV.br_blockcount - new->br_blockcount);
    -		xfs_bmap_trace_post_update(fname, "RF", ip, idx, XFS_DATA_FORK);
    -		xfs_bmap_trace_insert(fname, "RF", ip, idx + 1, 1,
    -			new, NULL, XFS_DATA_FORK);
    -		xfs_iext_insert(ifp, idx + 1, 1, new);
    -		ip->i_df.if_lastex = idx + 1;
    -		ip->i_d.di_nextents++;
    -		if (cur == NULL)
    -			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
    -		else {
    -			rval = XFS_ILOG_CORE;
    -			if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
    -					PREV.br_startblock, PREV.br_blockcount,
    -					&i)))
    -				goto done;
    -			ASSERT(i == 1);
    -			if ((error = xfs_bmbt_update(cur, PREV.br_startoff,
    -				PREV.br_startblock,
    -				PREV.br_blockcount - new->br_blockcount,
    -				oldext)))
    -				goto done;
    -			if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
    -					new->br_startblock, new->br_blockcount,
    -					&i)))
    -				goto done;
    -			ASSERT(i == 0);
    -			cur->bc_rec.b.br_state = XFS_EXT_NORM;
    -			if ((error = xfs_bmbt_insert(cur, &i)))
    -				goto done;
    -			ASSERT(i == 1);
    -		}
    -		/* DELTA: One in-core extent is split in two. */
    -		temp = PREV.br_startoff;
    -		temp2 = PREV.br_blockcount;
    -		break;
    -
    -	case 0:
    -		/*
    -		 * Setting the middle part of a previous oldext extent to
    -		 * newext.  Contiguity is impossible here.
    -		 * One extent becomes three extents.
    -		 */
    -		xfs_bmap_trace_pre_update(fname, "0", ip, idx, XFS_DATA_FORK);
    -		xfs_bmbt_set_blockcount(ep,
    -			new->br_startoff - PREV.br_startoff);
    -		xfs_bmap_trace_post_update(fname, "0", ip, idx, XFS_DATA_FORK);
    -		r[0] = *new;
    -		r[1].br_startoff = new_endoff;
    -		r[1].br_blockcount =
    -			PREV.br_startoff + PREV.br_blockcount - new_endoff;
    -		r[1].br_startblock = new->br_startblock + new->br_blockcount;
    -		r[1].br_state = oldext;
    -		xfs_bmap_trace_insert(fname, "0", ip, idx + 1, 2, &r[0], &r[1],
    -			XFS_DATA_FORK);
    -		xfs_iext_insert(ifp, idx + 1, 2, &r[0]);
    -		ip->i_df.if_lastex = idx + 1;
    -		ip->i_d.di_nextents += 2;
    -		if (cur == NULL)
    -			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;
    -		else {
    -			rval = XFS_ILOG_CORE;
    -			if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,
    -					PREV.br_startblock, PREV.br_blockcount,
    -					&i)))
    -				goto done;
    -			ASSERT(i == 1);
    -			/* new right extent - oldext */
    -			if ((error = xfs_bmbt_update(cur, r[1].br_startoff,
    -				r[1].br_startblock, r[1].br_blockcount,
    -				r[1].br_state)))
    -				goto done;
    -			/* new left extent - oldext */
    -			PREV.br_blockcount =
    -				new->br_startoff - PREV.br_startoff;
    -			cur->bc_rec.b = PREV;
    -			if ((error = xfs_bmbt_insert(cur, &i)))
    -				goto done;
    -			ASSERT(i == 1);
    -			if ((error = xfs_bmbt_increment(cur, 0, &i)))
    -				goto done;
    -			ASSERT(i == 1);
    -			/* new middle extent - newext */
    -			cur->bc_rec.b = *new;
    -			if ((error = xfs_bmbt_insert(cur, &i)))
    -				goto done;
    -			ASSERT(i == 1);
    -		}
    -		/* DELTA: One in-core extent is split in three. */
    -		temp = PREV.br_startoff;
    -		temp2 = PREV.br_blockcount;
    -		break;
    -
    -	case MASK3(LEFT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):
    -	case MASK3(RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):
    -	case MASK2(LEFT_FILLING, RIGHT_CONTIG):
    -	case MASK2(RIGHT_FILLING, LEFT_CONTIG):
    -	case MASK2(LEFT_CONTIG, RIGHT_CONTIG):
    -	case MASK(LEFT_CONTIG):
    -	case MASK(RIGHT_CONTIG):
    -		/*
    -		 * These cases are all impossible.
    -		 */
    -		ASSERT(0);
    -	}
    -	*curp = cur;
    -	if (delta) {
    -		temp2 += temp;
    -		if (delta->xed_startoff > temp)
    -			delta->xed_startoff = temp;
    -		if (delta->xed_blockcount < temp2)
    -			delta->xed_blockcount = temp2;
    -	}
    -done:
    -	*logflagsp = rval;
    -	return error;
    -#undef	LEFT
    -#undef	RIGHT
    -#undef	PREV
    -#undef	MASK
    -#undef	MASK2
    -#undef	MASK3
    -#undef	MASK4
    -#undef	STATE_SET
    -#undef	STATE_TEST
    -#undef	STATE_SET_TEST
    -#undef	SWITCH_STATE
    -}
    -
    -/*
    - * Called by xfs_bmap_add_extent to handle cases converting a hole
    - * to a delayed allocation.
    - */
    -/*ARGSUSED*/
    -STATIC int				/* error */
    -xfs_bmap_add_extent_hole_delay(
    -	xfs_inode_t		*ip,	/* incore inode pointer */
    -	xfs_extnum_t		idx,	/* extent number to update/insert */
    -	xfs_btree_cur_t		*cur,	/* if null, not a btree */
    -	xfs_bmbt_irec_t		*new,	/* new data to add to file extents */
    -	int			*logflagsp, /* inode logging flags */
    -	xfs_extdelta_t		*delta, /* Change made to incore extents */
    -	int			rsvd)		/* OK to allocate reserved blocks */
    -{
    -	xfs_bmbt_rec_t		*ep;	/* extent record for idx */
    -#ifdef XFS_BMAP_TRACE
    -	static char		fname[] = "xfs_bmap_add_extent_hole_delay";
    -#endif
    -	xfs_ifork_t		*ifp;	/* inode fork pointer */
    -	xfs_bmbt_irec_t		left;	/* left neighbor extent entry */
    -	xfs_filblks_t		newlen=0;	/* new indirect size */
    -	xfs_filblks_t		oldlen=0;	/* old indirect size */
    -	xfs_bmbt_irec_t		right;	/* right neighbor extent entry */
    -	int			state;  /* state bits, accessed thru macros */
    -	xfs_filblks_t		temp=0;	/* temp for indirect calculations */
    -	xfs_filblks_t		temp2=0;
    -	enum {				/* bit number definitions for state */
    -		LEFT_CONTIG,	RIGHT_CONTIG,
    -		LEFT_DELAY,	RIGHT_DELAY,
    -		LEFT_VALID,	RIGHT_VALID
    -	};
    -
    -#define	MASK(b)			(1 << (b))
    -#define	MASK2(a,b)		(MASK(a) | MASK(b))
    -#define	STATE_SET(b,v)		((v) ? (state |= MASK(b)) : (state &= ~MASK(b)))
    -#define	STATE_TEST(b)		(state & MASK(b))
    -#define	STATE_SET_TEST(b,v)	((v) ? ((state |= MASK(b)), 1) : \
    -				       ((state &= ~MASK(b)), 0))
    -#define	SWITCH_STATE		(state & MASK2(LEFT_CONTIG, RIGHT_CONTIG))
    -
    -	ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
    -	ep = xfs_iext_get_ext(ifp, idx);
    -	state = 0;
    -	ASSERT(ISNULLSTARTBLOCK(new->br_startblock));
    -	/*
    -	 * Check and set flags if this segment has a left neighbor
    -	 */
    -	if (STATE_SET_TEST(LEFT_VALID, idx > 0)) {
    -		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx - 1), &left);
    -		STATE_SET(LEFT_DELAY, ISNULLSTARTBLOCK(left.br_startblock));
    -	}
    -	/*
    -	 * Check and set flags if the current (right) segment exists.
    -	 * If it doesn't exist, we're converting the hole at end-of-file.
    -	 */
    -	if (STATE_SET_TEST(RIGHT_VALID,
    -			   idx <
    -			   ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t))) {
    -		xfs_bmbt_get_all(ep, &right);
    -		STATE_SET(RIGHT_DELAY, ISNULLSTARTBLOCK(right.br_startblock));
    -	}
    -	/*
    -	 * Set contiguity flags on the left and right neighbors.
    -	 * Don't let extents get too large, even if the pieces are contiguous.
    -	 */
    -	STATE_SET(LEFT_CONTIG,
    -		STATE_TEST(LEFT_VALID) && STATE_TEST(LEFT_DELAY) &&
    -		left.br_startoff + left.br_blockcount == new->br_startoff &&
    -		left.br_blockcount + new->br_blockcount <= MAXEXTLEN);
    -	STATE_SET(RIGHT_CONTIG,
    -		STATE_TEST(RIGHT_VALID) && STATE_TEST(RIGHT_DELAY) &&
    -		new->br_startoff + new->br_blockcount == right.br_startoff &&
    -		new->br_blockcount + right.br_blockcount <= MAXEXTLEN &&
    -		(!STATE_TEST(LEFT_CONTIG) ||
    -		 (left.br_blockcount + new->br_blockcount +
    -		     right.br_blockcount <= MAXEXTLEN)));
    -	/*
    -	 * Switch out based on the contiguity flags.
    -	 */
    -	switch (SWITCH_STATE) {
    -
    -	case MASK2(LEFT_CONTIG, RIGHT_CONTIG):
    -		/*
    -		 * New allocation is contiguous with delayed allocations
    -		 * on the left and on the right.
    -		 * Merge all three into a single extent record.
    -		 */
    -		temp = left.br_blockcount + new->br_blockcount +
    -			right.br_blockcount;
    -		xfs_bmap_trace_pre_update(fname, "LC|RC", ip, idx - 1,
    -			XFS_DATA_FORK);
    -		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), temp);
    -		oldlen = STARTBLOCKVAL(left.br_startblock) +
    -			STARTBLOCKVAL(new->br_startblock) +
    -			STARTBLOCKVAL(right.br_startblock);
    -		newlen = xfs_bmap_worst_indlen(ip, temp);
    -		xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, idx - 1),
    -			NULLSTARTBLOCK((int)newlen));
    -		xfs_bmap_trace_post_update(fname, "LC|RC", ip, idx - 1,
    -			XFS_DATA_FORK);
    -		xfs_bmap_trace_delete(fname, "LC|RC", ip, idx, 1,
    -			XFS_DATA_FORK);
    -		xfs_iext_remove(ifp, idx, 1);
    -		ip->i_df.if_lastex = idx - 1;
    -		/* DELTA: Two in-core extents were replaced by one. */
    -		temp2 = temp;
    -		temp = left.br_startoff;
    -		break;
    -
    -	case MASK(LEFT_CONTIG):
    -		/*
    -		 * New allocation is contiguous with a delayed allocation
    -		 * on the left.
    -		 * Merge the new allocation with the left neighbor.
    -		 */
    -		temp = left.br_blockcount + new->br_blockcount;
    -		xfs_bmap_trace_pre_update(fname, "LC", ip, idx - 1,
    -			XFS_DATA_FORK);
    -		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), temp);
    -		oldlen = STARTBLOCKVAL(left.br_startblock) +
    -			STARTBLOCKVAL(new->br_startblock);
    -		newlen = xfs_bmap_worst_indlen(ip, temp);
    -		xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, idx - 1),
    -			NULLSTARTBLOCK((int)newlen));
    -		xfs_bmap_trace_post_update(fname, "LC", ip, idx - 1,
    -			XFS_DATA_FORK);
    -		ip->i_df.if_lastex = idx - 1;
    -		/* DELTA: One in-core extent grew into a hole. */
    -		temp2 = temp;
    -		temp = left.br_startoff;
    -		break;
    -
    -	case MASK(RIGHT_CONTIG):
    -		/*
    -		 * New allocation is contiguous with a delayed allocation
    -		 * on the right.
    -		 * Merge the new allocation with the right neighbor.
    -		 */
    -		xfs_bmap_trace_pre_update(fname, "RC", ip, idx, XFS_DATA_FORK);
    -		temp = new->br_blockcount + right.br_blockcount;
    -		oldlen = STARTBLOCKVAL(new->br_startblock) +
    -			STARTBLOCKVAL(right.br_startblock);
    -		newlen = xfs_bmap_worst_indlen(ip, temp);
    -		xfs_bmbt_set_allf(ep, new->br_startoff,
    -			NULLSTARTBLOCK((int)newlen), temp, right.br_state);
    -		xfs_bmap_trace_post_update(fname, "RC", ip, idx, XFS_DATA_FORK);
    -		ip->i_df.if_lastex = idx;
    -		/* DELTA: One in-core extent grew into a hole. */
    -		temp2 = temp;
    -		temp = new->br_startoff;
    -		break;
    -
    -	case 0:
    -		/*
    -		 * New allocation is not contiguous with another
    -		 * delayed allocation.
    -		 * Insert a new entry.
    -		 */
    -		oldlen = newlen = 0;
    -		xfs_bmap_trace_insert(fname, "0", ip, idx, 1, new, NULL,
    -			XFS_DATA_FORK);
    -		xfs_iext_insert(ifp, idx, 1, new);
    -		ip->i_df.if_lastex = idx;
    -		/* DELTA: A new in-core extent was added in a hole. */
    -		temp2 = new->br_blockcount;
    -		temp = new->br_startoff;
    -		break;
    -	}
    -	if (oldlen != newlen) {
    -		ASSERT(oldlen > newlen);
    -		xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS,
    -			(int)(oldlen - newlen), rsvd);
    -		/*
    -		 * Nothing to do for disk quota accounting here.
    -		 */
    -	}
    -	if (delta) {
    -		temp2 += temp;
    -		if (delta->xed_startoff > temp)
    -			delta->xed_startoff = temp;
    -		if (delta->xed_blockcount < temp2)
    -			delta->xed_blockcount = temp2;
    -	}
    -	*logflagsp = 0;
    -	return 0;
    -#undef	MASK
    -#undef	MASK2
    -#undef	STATE_SET
    -#undef	STATE_TEST
    -#undef	STATE_SET_TEST
    -#undef	SWITCH_STATE
    -}
    -
    -/*
    - * Called by xfs_bmap_add_extent to handle cases converting a hole
    - * to a real allocation.
    - */
    -STATIC int				/* error */
    -xfs_bmap_add_extent_hole_real(
    -	xfs_inode_t		*ip,	/* incore inode pointer */
    -	xfs_extnum_t		idx,	/* extent number to update/insert */
    -	xfs_btree_cur_t		*cur,	/* if null, not a btree */
    -	xfs_bmbt_irec_t		*new,	/* new data to add to file extents */
    -	int			*logflagsp, /* inode logging flags */
    -	xfs_extdelta_t		*delta, /* Change made to incore extents */
    -	int			whichfork) /* data or attr fork */
    -{
    -	xfs_bmbt_rec_t		*ep;	/* pointer to extent entry ins. point */
    -	int			error;	/* error return value */
    -#ifdef XFS_BMAP_TRACE
    -	static char		fname[] = "xfs_bmap_add_extent_hole_real";
    -#endif
    -	int			i;	/* temp state */
    -	xfs_ifork_t		*ifp;	/* inode fork pointer */
    -	xfs_bmbt_irec_t		left;	/* left neighbor extent entry */
    -	xfs_bmbt_irec_t		right;	/* right neighbor extent entry */
    -	int			rval=0;	/* return value (logging flags) */
    -	int			state;	/* state bits, accessed thru macros */
    -	xfs_filblks_t		temp=0;
    -	xfs_filblks_t		temp2=0;
    -	enum {				/* bit number definitions for state */
    -		LEFT_CONTIG,	RIGHT_CONTIG,
    -		LEFT_DELAY,	RIGHT_DELAY,
    -		LEFT_VALID,	RIGHT_VALID
    -	};
    -
    -#define	MASK(b)			(1 << (b))
    -#define	MASK2(a,b)		(MASK(a) | MASK(b))
    -#define	STATE_SET(b,v)		((v) ? (state |= MASK(b)) : (state &= ~MASK(b)))
    -#define	STATE_TEST(b)		(state & MASK(b))
    -#define	STATE_SET_TEST(b,v)	((v) ? ((state |= MASK(b)), 1) : \
    -				       ((state &= ~MASK(b)), 0))
    -#define	SWITCH_STATE		(state & MASK2(LEFT_CONTIG, RIGHT_CONTIG))
    -
    -	ifp = XFS_IFORK_PTR(ip, whichfork);
    -	ASSERT(idx <= ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t));
    -	ep = xfs_iext_get_ext(ifp, idx);
    -	state = 0;
    -	/*
    -	 * Check and set flags if this segment has a left neighbor.
    -	 */
    -	if (STATE_SET_TEST(LEFT_VALID, idx > 0)) {
    -		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx - 1), &left);
    -		STATE_SET(LEFT_DELAY, ISNULLSTARTBLOCK(left.br_startblock));
    -	}
    -	/*
    -	 * Check and set flags if this segment has a current value.
    -	 * Not true if we're inserting into the "hole" at eof.
    -	 */
    -	if (STATE_SET_TEST(RIGHT_VALID,
    -			   idx <
    -			   ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t))) {
    -		xfs_bmbt_get_all(ep, &right);
    -		STATE_SET(RIGHT_DELAY, ISNULLSTARTBLOCK(right.br_startblock));
    -	}
    -	/*
    -	 * We're inserting a real allocation between "left" and "right".
    -	 * Set the contiguity flags.  Don't let extents get too large.
    -	 */
    -	STATE_SET(LEFT_CONTIG,
    -		STATE_TEST(LEFT_VALID) && !STATE_TEST(LEFT_DELAY) &&
    -		left.br_startoff + left.br_blockcount == new->br_startoff &&
    -		left.br_startblock + left.br_blockcount == new->br_startblock &&
    -		left.br_state == new->br_state &&
    -		left.br_blockcount + new->br_blockcount <= MAXEXTLEN);
    -	STATE_SET(RIGHT_CONTIG,
    -		STATE_TEST(RIGHT_VALID) && !STATE_TEST(RIGHT_DELAY) &&
    -		new->br_startoff + new->br_blockcount == right.br_startoff &&
    -		new->br_startblock + new->br_blockcount ==
    -		    right.br_startblock &&
    -		new->br_state == right.br_state &&
    -		new->br_blockcount + right.br_blockcount <= MAXEXTLEN &&
    -		(!STATE_TEST(LEFT_CONTIG) ||
    -		 left.br_blockcount + new->br_blockcount +
    -		     right.br_blockcount <= MAXEXTLEN));
    -
    -	error = 0;
    -	/*
    -	 * Select which case we're in here, and implement it.
    -	 */
    -	switch (SWITCH_STATE) {
    -
    -	case MASK2(LEFT_CONTIG, RIGHT_CONTIG):
    -		/*
    -		 * New allocation is contiguous with real allocations on the
    -		 * left and on the right.
    -		 * Merge all three into a single extent record.
    -		 */
    -		xfs_bmap_trace_pre_update(fname, "LC|RC", ip, idx - 1,
    -			whichfork);
    -		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
    -			left.br_blockcount + new->br_blockcount +
    -			right.br_blockcount);
    -		xfs_bmap_trace_post_update(fname, "LC|RC", ip, idx - 1,
    -			whichfork);
    -		xfs_bmap_trace_delete(fname, "LC|RC", ip,
    -			idx, 1, whichfork);
    -		xfs_iext_remove(ifp, idx, 1);
    -		ifp->if_lastex = idx - 1;
    -		XFS_IFORK_NEXT_SET(ip, whichfork,
    -			XFS_IFORK_NEXTENTS(ip, whichfork) - 1);
    -		if (cur == NULL) {
    -			rval = XFS_ILOG_CORE | XFS_ILOG_FEXT(whichfork);
    -		} else {
    -			rval = XFS_ILOG_CORE;
    -			if ((error = xfs_bmbt_lookup_eq(cur,
    -					right.br_startoff,
    -					right.br_startblock,
    -					right.br_blockcount, &i)))
    -				goto done;
    -			ASSERT(i == 1);
    -			if ((error = xfs_bmbt_delete(cur, &i)))
    -				goto done;
    -			ASSERT(i == 1);
    -			if ((error = xfs_bmbt_decrement(cur, 0, &i)))
    -				goto done;
    -			ASSERT(i == 1);
    -			if ((error = xfs_bmbt_update(cur, left.br_startoff,
    -					left.br_startblock,
    -					left.br_blockcount +
    -						new->br_blockcount +
    -						right.br_blockcount,
    -					left.br_state)))
    -				goto done;
    -		}
    -		/* DELTA: Two in-core extents were replaced by one. */
    -		temp = left.br_startoff;
    -		temp2 = left.br_blockcount +
    -			new->br_blockcount +
    -			right.br_blockcount;
    -		break;
    -
    -	case MASK(LEFT_CONTIG):
    -		/*
    -		 * New allocation is contiguous with a real allocation
    -		 * on the left.
    -		 * Merge the new allocation with the left neighbor.
    -		 */
    -		xfs_bmap_trace_pre_update(fname, "LC", ip, idx - 1, whichfork);
    -		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
    -			left.br_blockcount + new->br_blockcount);
    -		xfs_bmap_trace_post_update(fname, "LC", ip, idx - 1, whichfork);
    -		ifp->if_lastex = idx - 1;
    -		if (cur == NULL) {
    -			rval = XFS_ILOG_FEXT(whichfork);
    -		} else {
    -			rval = 0;
    -			if ((error = xfs_bmbt_lookup_eq(cur,
    -					left.br_startoff,
    -					left.br_startblock,
    -					left.br_blockcount, &i)))
    -				goto done;
    -			ASSERT(i == 1);
    -			if ((error = xfs_bmbt_update(cur, left.br_startoff,
    -					left.br_startblock,
    -					left.br_blockcount +
    -						new->br_blockcount,
    -					left.br_state)))
    -				goto done;
    -		}
    -		/* DELTA: One in-core extent grew. */
    -		temp = left.br_startoff;
    -		temp2 = left.br_blockcount +
    -			new->br_blockcount;
    -		break;
    -
    -	case MASK(RIGHT_CONTIG):
    -		/*
    -		 * New allocation is contiguous with a real allocation
    -		 * on the right.
    -		 * Merge the new allocation with the right neighbor.
    -		 */
    -		xfs_bmap_trace_pre_update(fname, "RC", ip, idx, whichfork);
    -		xfs_bmbt_set_allf(ep, new->br_startoff, new->br_startblock,
    -			new->br_blockcount + right.br_blockcount,
    -			right.br_state);
    -		xfs_bmap_trace_post_update(fname, "RC", ip, idx, whichfork);
    -		ifp->if_lastex = idx;
    -		if (cur == NULL) {
    -			rval = XFS_ILOG_FEXT(whichfork);
    -		} else {
    -			rval = 0;
    -			if ((error = xfs_bmbt_lookup_eq(cur,
    -					right.br_startoff,
    -					right.br_startblock,
    -					right.br_blockcount, &i)))
    -				goto done;
    -			ASSERT(i == 1);
    -			if ((error = xfs_bmbt_update(cur, new->br_startoff,
    -					new->br_startblock,
    -					new->br_blockcount +
    -						right.br_blockcount,
    -					right.br_state)))
    -				goto done;
    -		}
    -		/* DELTA: One in-core extent grew. */
    -		temp = new->br_startoff;
    -		temp2 = new->br_blockcount +
    -			right.br_blockcount;
    -		break;
    -
    -	case 0:
    -		/*
    -		 * New allocation is not contiguous with another
    -		 * real allocation.
    -		 * Insert a new entry.
    -		 */
    -		xfs_bmap_trace_insert(fname, "0", ip, idx, 1, new, NULL,
    -			whichfork);
    -		xfs_iext_insert(ifp, idx, 1, new);
    -		ifp->if_lastex = idx;
    -		XFS_IFORK_NEXT_SET(ip, whichfork,
    -			XFS_IFORK_NEXTENTS(ip, whichfork) + 1);
    -		if (cur == NULL) {
    -			rval = XFS_ILOG_CORE | XFS_ILOG_FEXT(whichfork);
    -		} else {
    -			rval = XFS_ILOG_CORE;
    -			if ((error = xfs_bmbt_lookup_eq(cur,
    -					new->br_startoff,
    -					new->br_startblock,
    -					new->br_blockcount, &i)))
    -				goto done;
    -			ASSERT(i == 0);
    -			cur->bc_rec.b.br_state = new->br_state;
    -			if ((error = xfs_bmbt_insert(cur, &i)))
    -				goto done;
    -			ASSERT(i == 1);
    -		}
    -		/* DELTA: A new extent was added in a hole. */
    -		temp = new->br_startoff;
    -		temp2 = new->br_blockcount;
    -		break;
    -	}
    -	if (delta) {
    -		temp2 += temp;
    -		if (delta->xed_startoff > temp)
    -			delta->xed_startoff = temp;
    -		if (delta->xed_blockcount < temp2)
    -			delta->xed_blockcount = temp2;
    -	}
    -done:
    -	*logflagsp = rval;
    -	return error;
    -#undef	MASK
    -#undef	MASK2
    -#undef	STATE_SET
    -#undef	STATE_TEST
    -#undef	STATE_SET_TEST
    -#undef	SWITCH_STATE
    -}
    -
    -/*
    - * Adjust the size of the new extent based on di_extsize and rt extsize.
    - */
    -STATIC int
    -xfs_bmap_extsize_align(
    -	xfs_mount_t	*mp,
    -	xfs_bmbt_irec_t	*gotp,		/* next extent pointer */
    -	xfs_bmbt_irec_t	*prevp,		/* previous extent pointer */
    -	xfs_extlen_t	extsz,		/* align to this extent size */
    -	int		rt,		/* is this a realtime inode? */
    -	int		eof,		/* is extent at end-of-file? */
    -	int		delay,		/* creating delalloc extent? */
    -	int		convert,	/* overwriting unwritten extent? */
    -	xfs_fileoff_t	*offp,		/* in/out: aligned offset */
    -	xfs_extlen_t	*lenp)		/* in/out: aligned length */
    -{
    -	xfs_fileoff_t	orig_off;	/* original offset */
    -	xfs_extlen_t	orig_alen;	/* original length */
    -	xfs_fileoff_t	orig_end;	/* original off+len */
    -	xfs_fileoff_t	nexto;		/* next file offset */
    -	xfs_fileoff_t	prevo;		/* previous file offset */
    -	xfs_fileoff_t	align_off;	/* temp for offset */
    -	xfs_extlen_t	align_alen;	/* temp for length */
    -	xfs_extlen_t	temp;		/* temp for calculations */
    -
    -	if (convert)
    -		return 0;
    -
    -	orig_off = align_off = *offp;
    -	orig_alen = align_alen = *lenp;
    -	orig_end = orig_off + orig_alen;
    -
    -	/*
    -	 * If this request overlaps an existing extent, then don't
    -	 * attempt to perform any additional alignment.
    -	 */
    -	if (!delay && !eof &&
    -	    (orig_off >= gotp->br_startoff) &&
    -	    (orig_end <= gotp->br_startoff + gotp->br_blockcount)) {
    -		return 0;
    -	}
    -
    -	/*
    -	 * If the file offset is unaligned vs. the extent size
    -	 * we need to align it.  This will be possible unless
    -	 * the file was previously written with a kernel that didn't
    -	 * perform this alignment, or if a truncate shot us in the
    -	 * foot.
    -	 */
    -	temp = do_mod(orig_off, extsz);
    -	if (temp) {
    -		align_alen += temp;
    -		align_off -= temp;
    -	}
    -	/*
    -	 * Same adjustment for the end of the requested area.
    -	 */
    -	if ((temp = (align_alen % extsz))) {
    -		align_alen += extsz - temp;
    -	}
    -	/*
    -	 * If the previous block overlaps with this proposed allocation
    -	 * then move the start forward without adjusting the length.
    -	 */
    -	if (prevp->br_startoff != NULLFILEOFF) {
    -		if (prevp->br_startblock == HOLESTARTBLOCK)
    -			prevo = prevp->br_startoff;
    -		else
    -			prevo = prevp->br_startoff + prevp->br_blockcount;
    -	} else
    -		prevo = 0;
    -	if (align_off != orig_off && align_off < prevo)
    -		align_off = prevo;
    -	/*
    -	 * If the next block overlaps with this proposed allocation
    -	 * then move the start back without adjusting the length,
    -	 * but not before offset 0.
    -	 * This may of course make the start overlap previous block,
    -	 * and if we hit the offset 0 limit then the next block
    -	 * can still overlap too.
    -	 */
    -	if (!eof && gotp->br_startoff != NULLFILEOFF) {
    -		if ((delay && gotp->br_startblock == HOLESTARTBLOCK) ||
    -		    (!delay && gotp->br_startblock == DELAYSTARTBLOCK))
    -			nexto = gotp->br_startoff + gotp->br_blockcount;
    -		else
    -			nexto = gotp->br_startoff;
    -	} else
    -		nexto = NULLFILEOFF;
    -	if (!eof &&
    -	    align_off + align_alen != orig_end &&
    -	    align_off + align_alen > nexto)
    -		align_off = nexto > align_alen ? nexto - align_alen : 0;
    -	/*
    -	 * If we're now overlapping the next or previous extent that
    -	 * means we can't fit an extsz piece in this hole.  Just move
    -	 * the start forward to the first valid spot and set
    -	 * the length so we hit the end.
    -	 */
    -	if (align_off != orig_off && align_off < prevo)
    -		align_off = prevo;
    -	if (align_off + align_alen != orig_end &&
    -	    align_off + align_alen > nexto &&
    -	    nexto != NULLFILEOFF) {
    -		ASSERT(nexto > prevo);
    -		align_alen = nexto - align_off;
    -	}
    -
    -	/*
    -	 * If realtime, and the result isn't a multiple of the realtime
    -	 * extent size we need to remove blocks until it is.
    -	 */
    -	if (rt && (temp = (align_alen % mp->m_sb.sb_rextsize))) {
    -		/*
    -		 * We're not covering the original request, or
    -		 * we won't be able to once we fix the length.
    -		 */
    -		if (orig_off < align_off ||
    -		    orig_end > align_off + align_alen ||
    -		    align_alen - temp < orig_alen)
    -			return XFS_ERROR(EINVAL);
    -		/*
    -		 * Try to fix it by moving the start up.
    -		 */
    -		if (align_off + temp <= orig_off) {
    -			align_alen -= temp;
    -			align_off += temp;
    -		}
    -		/*
    -		 * Try to fix it by moving the end in.
    -		 */
    -		else if (align_off + align_alen - temp >= orig_end)
    -			align_alen -= temp;
    -		/*
    -		 * Set the start to the minimum then trim the length.
    -		 */
    -		else {
    -			align_alen -= orig_off - align_off;
    -			align_off = orig_off;
    -			align_alen -= align_alen % mp->m_sb.sb_rextsize;
    -		}
    -		/*
    -		 * Result doesn't cover the request, fail it.
    -		 */
    -		if (orig_off < align_off || orig_end > align_off + align_alen)
    -			return XFS_ERROR(EINVAL);
    -	} else {
    -		ASSERT(orig_off >= align_off);
    -		ASSERT(orig_end <= align_off + align_alen);
    -	}
    -
    -#ifdef DEBUG
    -	if (!eof && gotp->br_startoff != NULLFILEOFF)
    -		ASSERT(align_off + align_alen <= gotp->br_startoff);
    -	if (prevp->br_startoff != NULLFILEOFF)
    -		ASSERT(align_off >= prevp->br_startoff + prevp->br_blockcount);
    -#endif
    -
    -	*lenp = align_alen;
    -	*offp = align_off;
    -	return 0;
    -}
    -
    -#define XFS_ALLOC_GAP_UNITS	4
    -
    -STATIC int
    -xfs_bmap_adjacent(
    -	xfs_bmalloca_t	*ap)		/* bmap alloc argument struct */
    -{
    -	xfs_fsblock_t	adjust;		/* adjustment to block numbers */
    -	xfs_agnumber_t	fb_agno;	/* ag number of ap->firstblock */
    -	xfs_mount_t	*mp;		/* mount point structure */
    -	int		nullfb;		/* true if ap->firstblock isn't set */
    -	int		rt;		/* true if inode is realtime */
    -
    -#define	ISVALID(x,y)	\
    -	(rt ? \
    -		(x) < mp->m_sb.sb_rblocks : \
    -		XFS_FSB_TO_AGNO(mp, x) == XFS_FSB_TO_AGNO(mp, y) && \
    -		XFS_FSB_TO_AGNO(mp, x) < mp->m_sb.sb_agcount && \
    -		XFS_FSB_TO_AGBNO(mp, x) < mp->m_sb.sb_agblocks)
    -
    -	mp = ap->ip->i_mount;
    -	nullfb = ap->firstblock == NULLFSBLOCK;
    -	rt = XFS_IS_REALTIME_INODE(ap->ip) && ap->userdata;
    -	fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock);
    -	/*
    -	 * If allocating at eof, and there's a previous real block,
    -	 * try to use it's last block as our starting point.
    -	 */
    -	if (ap->eof && ap->prevp->br_startoff != NULLFILEOFF &&
    -	    !ISNULLSTARTBLOCK(ap->prevp->br_startblock) &&
    -	    ISVALID(ap->prevp->br_startblock + ap->prevp->br_blockcount,
    -		    ap->prevp->br_startblock)) {
    -		ap->rval = ap->prevp->br_startblock + ap->prevp->br_blockcount;
    -		/*
    -		 * Adjust for the gap between prevp and us.
    -		 */
    -		adjust = ap->off -
    -			(ap->prevp->br_startoff + ap->prevp->br_blockcount);
    -		if (adjust &&
    -		    ISVALID(ap->rval + adjust, ap->prevp->br_startblock))
    -			ap->rval += adjust;
    -	}
    -	/*
    -	 * If not at eof, then compare the two neighbor blocks.
    -	 * Figure out whether either one gives us a good starting point,
    -	 * and pick the better one.
    -	 */
    -	else if (!ap->eof) {
    -		xfs_fsblock_t	gotbno;		/* right side block number */
    -		xfs_fsblock_t	gotdiff=0;	/* right side difference */
    -		xfs_fsblock_t	prevbno;	/* left side block number */
    -		xfs_fsblock_t	prevdiff=0;	/* left side difference */
    -
    -		/*
    -		 * If there's a previous (left) block, select a requested
    -		 * start block based on it.
    -		 */
    -		if (ap->prevp->br_startoff != NULLFILEOFF &&
    -		    !ISNULLSTARTBLOCK(ap->prevp->br_startblock) &&
    -		    (prevbno = ap->prevp->br_startblock +
    -			       ap->prevp->br_blockcount) &&
    -		    ISVALID(prevbno, ap->prevp->br_startblock)) {
    -			/*
    -			 * Calculate gap to end of previous block.
    -			 */
    -			adjust = prevdiff = ap->off -
    -				(ap->prevp->br_startoff +
    -				 ap->prevp->br_blockcount);
    -			/*
    -			 * Figure the startblock based on the previous block's
    -			 * end and the gap size.
    -			 * Heuristic!
    -			 * If the gap is large relative to the piece we're
    -			 * allocating, or using it gives us an invalid block
    -			 * number, then just use the end of the previous block.
    -			 */
    -			if (prevdiff <= XFS_ALLOC_GAP_UNITS * ap->alen &&
    -			    ISVALID(prevbno + prevdiff,
    -				    ap->prevp->br_startblock))
    -				prevbno += adjust;
    -			else
    -				prevdiff += adjust;
    -			/*
    -			 * If the firstblock forbids it, can't use it,
    -			 * must use default.
    -			 */
    -			if (!rt && !nullfb &&
    -			    XFS_FSB_TO_AGNO(mp, prevbno) != fb_agno)
    -				prevbno = NULLFSBLOCK;
    -		}
    -		/*
    -		 * No previous block or can't follow it, just default.
    -		 */
    -		else
    -			prevbno = NULLFSBLOCK;
    -		/*
    -		 * If there's a following (right) block, select a requested
    -		 * start block based on it.
    -		 */
    -		if (!ISNULLSTARTBLOCK(ap->gotp->br_startblock)) {
    -			/*
    -			 * Calculate gap to start of next block.
    -			 */
    -			adjust = gotdiff = ap->gotp->br_startoff - ap->off;
    -			/*
    -			 * Figure the startblock based on the next block's
    -			 * start and the gap size.
    -			 */
    -			gotbno = ap->gotp->br_startblock;
    -			/*
    -			 * Heuristic!
    -			 * If the gap is large relative to the piece we're
    -			 * allocating, or using it gives us an invalid block
    -			 * number, then just use the start of the next block
    -			 * offset by our length.
    -			 */
    -			if (gotdiff <= XFS_ALLOC_GAP_UNITS * ap->alen &&
    -			    ISVALID(gotbno - gotdiff, gotbno))
    -				gotbno -= adjust;
    -			else if (ISVALID(gotbno - ap->alen, gotbno)) {
    -				gotbno -= ap->alen;
    -				gotdiff += adjust - ap->alen;
    -			} else
    -				gotdiff += adjust;
    -			/*
    -			 * If the firstblock forbids it, can't use it,
    -			 * must use default.
    -			 */
    -			if (!rt && !nullfb &&
    -			    XFS_FSB_TO_AGNO(mp, gotbno) != fb_agno)
    -				gotbno = NULLFSBLOCK;
    -		}
    -		/*
    -		 * No next block, just default.
    -		 */
    -		else
    -			gotbno = NULLFSBLOCK;
    -		/*
    -		 * If both valid, pick the better one, else the only good
    -		 * one, else ap->rval is already set (to 0 or the inode block).
    -		 */
    -		if (prevbno != NULLFSBLOCK && gotbno != NULLFSBLOCK)
    -			ap->rval = prevdiff <= gotdiff ? prevbno : gotbno;
    -		else if (prevbno != NULLFSBLOCK)
    -			ap->rval = prevbno;
    -		else if (gotbno != NULLFSBLOCK)
    -			ap->rval = gotbno;
    -	}
    -#undef ISVALID
    -	return 0;
    -}
    -
    -STATIC int
    -xfs_bmap_rtalloc(
    -	xfs_bmalloca_t	*ap)		/* bmap alloc argument struct */
    -{
    -	xfs_alloctype_t	atype = 0;	/* type for allocation routines */
    -	int		error;		/* error return value */
    -	xfs_mount_t	*mp;		/* mount point structure */
    -	xfs_extlen_t	prod = 0;	/* product factor for allocators */
    -	xfs_extlen_t	ralen = 0;	/* realtime allocation length */
    -	xfs_extlen_t	align;		/* minimum allocation alignment */
    -	xfs_rtblock_t	rtx;		/* realtime extent number */
    -	xfs_rtblock_t	rtb;
    -
    -	mp = ap->ip->i_mount;
    -	align = ap->ip->i_d.di_extsize ?
    -		ap->ip->i_d.di_extsize : mp->m_sb.sb_rextsize;
    -	prod = align / mp->m_sb.sb_rextsize;
    -	error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp,
    -					align, 1, ap->eof, 0,
    -					ap->conv, &ap->off, &ap->alen);
    -	if (error)
    -		return error;
    -	ASSERT(ap->alen);
    -	ASSERT(ap->alen % mp->m_sb.sb_rextsize == 0);
    -
    -	/*
    -	 * If the offset & length are not perfectly aligned
    -	 * then kill prod, it will just get us in trouble.
    -	 */
    -	if (do_mod(ap->off, align) || ap->alen % align)
    -		prod = 1;
    -	/*
    -	 * Set ralen to be the actual requested length in rtextents.
    -	 */
    -	ralen = ap->alen / mp->m_sb.sb_rextsize;
    -	/*
    -	 * If the old value was close enough to MAXEXTLEN that
    -	 * we rounded up to it, cut it back so it's valid again.
    -	 * Note that if it's a really large request (bigger than
    -	 * MAXEXTLEN), we don't hear about that number, and can't
    -	 * adjust the starting point to match it.
    -	 */
    -	if (ralen * mp->m_sb.sb_rextsize >= MAXEXTLEN)
    -		ralen = MAXEXTLEN / mp->m_sb.sb_rextsize;
    -	/*
    -	 * If it's an allocation to an empty file at offset 0,
    -	 * pick an extent that will space things out in the rt area.
    -	 */
    -	if (ap->eof && ap->off == 0) {
    -		error = xfs_rtpick_extent(mp, ap->tp, ralen, &rtx);
    -		if (error)
    -			return error;
    -		ap->rval = rtx * mp->m_sb.sb_rextsize;
    -	} else {
    -		ap->rval = 0;
    -	}
    -
    -	xfs_bmap_adjacent(ap);
    -
    -	/*
    -	 * Realtime allocation, done through xfs_rtallocate_extent.
    -	 */
    -	atype = ap->rval == 0 ?  XFS_ALLOCTYPE_ANY_AG : XFS_ALLOCTYPE_NEAR_BNO;
    -	do_div(ap->rval, mp->m_sb.sb_rextsize);
    -	rtb = ap->rval;
    -	ap->alen = ralen;
    -	if ((error = xfs_rtallocate_extent(ap->tp, ap->rval, 1, ap->alen,
    -				&ralen, atype, ap->wasdel, prod, &rtb)))
    -		return error;
    -	if (rtb == NULLFSBLOCK && prod > 1 &&
    -	    (error = xfs_rtallocate_extent(ap->tp, ap->rval, 1,
    -					   ap->alen, &ralen, atype,
    -					   ap->wasdel, 1, &rtb)))
    -		return error;
    -	ap->rval = rtb;
    -	if (ap->rval != NULLFSBLOCK) {
    -		ap->rval *= mp->m_sb.sb_rextsize;
    -		ralen *= mp->m_sb.sb_rextsize;
    -		ap->alen = ralen;
    -		ap->ip->i_d.di_nblocks += ralen;
    -		xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE);
    -		if (ap->wasdel)
    -			ap->ip->i_delayed_blks -= ralen;
    -		/*
    -		 * Adjust the disk quota also. This was reserved
    -		 * earlier.
    -		 */
    -		XFS_TRANS_MOD_DQUOT_BYINO(mp, ap->tp, ap->ip,
    -			ap->wasdel ? XFS_TRANS_DQ_DELRTBCOUNT :
    -					XFS_TRANS_DQ_RTBCOUNT, (long) ralen);
    -	} else {
    -		ap->alen = 0;
    -	}
    -	return 0;
    -}
    -
    -STATIC int
    -xfs_bmap_btalloc(
    -	xfs_bmalloca_t	*ap)		/* bmap alloc argument struct */
    -{
    -	xfs_mount_t	*mp;		/* mount point structure */
    -	xfs_alloctype_t	atype = 0;	/* type for allocation routines */
    -	xfs_extlen_t	align;		/* minimum allocation alignment */
    -	xfs_agnumber_t	ag;
    -	xfs_agnumber_t	fb_agno;	/* ag number of ap->firstblock */
    -	xfs_agnumber_t	startag;
    -	xfs_alloc_arg_t	args;
    -	xfs_extlen_t	blen;
    -	xfs_extlen_t	delta;
    -	xfs_extlen_t	longest;
    -	xfs_extlen_t	need;
    -	xfs_extlen_t	nextminlen = 0;
    -	xfs_perag_t	*pag;
    -	int		nullfb;		/* true if ap->firstblock isn't set */
    -	int		isaligned;
    -	int		notinit;
    -	int		tryagain;
    -	int		error;
    -
    -	mp = ap->ip->i_mount;
    -	align = (ap->userdata && ap->ip->i_d.di_extsize &&
    -		(ap->ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE)) ?
    -		ap->ip->i_d.di_extsize : 0;
    -	if (unlikely(align)) {
    -		error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp,
    -						align, 0, ap->eof, 0, ap->conv,
    -						&ap->off, &ap->alen);
    -		ASSERT(!error);
    -		ASSERT(ap->alen);
    -	}
    -	nullfb = ap->firstblock == NULLFSBLOCK;
    -	fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock);
    -	if (nullfb)
    -		ap->rval = XFS_INO_TO_FSB(mp, ap->ip->i_ino);
    -	else
    -		ap->rval = ap->firstblock;
    -
    -	xfs_bmap_adjacent(ap);
    -
    -	/*
    -	 * If allowed, use ap->rval; otherwise must use firstblock since
    -	 * it's in the right allocation group.
    -	 */
    -	if (nullfb || XFS_FSB_TO_AGNO(mp, ap->rval) == fb_agno)
    -		;
    -	else
    -		ap->rval = ap->firstblock;
    -	/*
    -	 * Normal allocation, done through xfs_alloc_vextent.
    -	 */
    -	tryagain = isaligned = 0;
    -	args.tp = ap->tp;
    -	args.mp = mp;
    -	args.fsbno = ap->rval;
    -	args.maxlen = MIN(ap->alen, mp->m_sb.sb_agblocks);
    -	blen = 0;
    -	if (nullfb) {
    -		args.type = XFS_ALLOCTYPE_START_BNO;
    -		args.total = ap->total;
    -		/*
    -		 * Find the longest available space.
    -		 * We're going to try for the whole allocation at once.
    -		 */
    -		startag = ag = XFS_FSB_TO_AGNO(mp, args.fsbno);
    -		notinit = 0;
    -		down_read(&mp->m_peraglock);
    -		while (blen < ap->alen) {
    -			pag = &mp->m_perag[ag];
    -			if (!pag->pagf_init &&
    -			    (error = xfs_alloc_pagf_init(mp, args.tp,
    -				    ag, XFS_ALLOC_FLAG_TRYLOCK))) {
    -				up_read(&mp->m_peraglock);
    -				return error;
    -			}
    -			/*
    -			 * See xfs_alloc_fix_freelist...
    -			 */
    -			if (pag->pagf_init) {
    -				need = XFS_MIN_FREELIST_PAG(pag, mp);
    -				delta = need > pag->pagf_flcount ?
    -					need - pag->pagf_flcount : 0;
    -				longest = (pag->pagf_longest > delta) ?
    -					(pag->pagf_longest - delta) :
    -					(pag->pagf_flcount > 0 ||
    -					 pag->pagf_longest > 0);
    -				if (blen < longest)
    -					blen = longest;
    -			} else
    -				notinit = 1;
    -			if (++ag == mp->m_sb.sb_agcount)
    -				ag = 0;
    -			if (ag == startag)
    -				break;
    -		}
    -		up_read(&mp->m_peraglock);
    -		/*
    -		 * Since the above loop did a BUF_TRYLOCK, it is
    -		 * possible that there is space for this request.
    -		 */
    -		if (notinit || blen < ap->minlen)
    -			args.minlen = ap->minlen;
    -		/*
    -		 * If the best seen length is less than the request
    -		 * length, use the best as the minimum.
    -		 */
    -		else if (blen < ap->alen)
    -			args.minlen = blen;
    -		/*
    -		 * Otherwise we've seen an extent as big as alen,
    -		 * use that as the minimum.
    -		 */
    -		else
    -			args.minlen = ap->alen;
    -	} else if (ap->low) {
    -		args.type = XFS_ALLOCTYPE_FIRST_AG;
    -		args.total = args.minlen = ap->minlen;
    -	} else {
    -		args.type = XFS_ALLOCTYPE_NEAR_BNO;
    -		args.total = ap->total;
    -		args.minlen = ap->minlen;
    -	}
    -	if (unlikely(ap->userdata && ap->ip->i_d.di_extsize &&
    -		    (ap->ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE))) {
    -		args.prod = ap->ip->i_d.di_extsize;
    -		if ((args.mod = (xfs_extlen_t)do_mod(ap->off, args.prod)))
    -			args.mod = (xfs_extlen_t)(args.prod - args.mod);
    -	} else if (unlikely(mp->m_sb.sb_blocksize >= NBPP)) {
    -		args.prod = 1;
    -		args.mod = 0;
    -	} else {
    -		args.prod = NBPP >> mp->m_sb.sb_blocklog;
    -		if ((args.mod = (xfs_extlen_t)(do_mod(ap->off, args.prod))))
    -			args.mod = (xfs_extlen_t)(args.prod - args.mod);
    -	}
    -	/*
    -	 * If we are not low on available data blocks, and the
    -	 * underlying logical volume manager is a stripe, and
    -	 * the file offset is zero then try to allocate data
    -	 * blocks on stripe unit boundary.
    -	 * NOTE: ap->aeof is only set if the allocation length
    -	 * is >= the stripe unit and the allocation offset is
    -	 * at the end of file.
    -	 */
    -	if (!ap->low && ap->aeof) {
    -		if (!ap->off) {
    -			args.alignment = mp->m_dalign;
    -			atype = args.type;
    -			isaligned = 1;
    -			/*
    -			 * Adjust for alignment
    -			 */
    -			if (blen > args.alignment && blen <= ap->alen)
    -				args.minlen = blen - args.alignment;
    -			args.minalignslop = 0;
    -		} else {
    -			/*
    -			 * First try an exact bno allocation.
    -			 * If it fails then do a near or start bno
    -			 * allocation with alignment turned on.
    -			 */
    -			atype = args.type;
    -			tryagain = 1;
    -			args.type = XFS_ALLOCTYPE_THIS_BNO;
    -			args.alignment = 1;
    -			/*
    -			 * Compute the minlen+alignment for the
    -			 * next case.  Set slop so that the value
    -			 * of minlen+alignment+slop doesn't go up
    -			 * between the calls.
    -			 */
    -			if (blen > mp->m_dalign && blen <= ap->alen)
    -				nextminlen = blen - mp->m_dalign;
    -			else
    -				nextminlen = args.minlen;
    -			if (nextminlen + mp->m_dalign > args.minlen + 1)
    -				args.minalignslop =
    -					nextminlen + mp->m_dalign -
    -					args.minlen - 1;
    -			else
    -				args.minalignslop = 0;
    -		}
    -	} else {
    -		args.alignment = 1;
    -		args.minalignslop = 0;
    -	}
    -	args.minleft = ap->minleft;
    -	args.wasdel = ap->wasdel;
    -	args.isfl = 0;
    -	args.userdata = ap->userdata;
    -	if ((error = xfs_alloc_vextent(&args)))
    -		return error;
    -	if (tryagain && args.fsbno == NULLFSBLOCK) {
    -		/*
    -		 * Exact allocation failed. Now try with alignment
    -		 * turned on.
    -		 */
    -		args.type = atype;
    -		args.fsbno = ap->rval;
    -		args.alignment = mp->m_dalign;
    -		args.minlen = nextminlen;
    -		args.minalignslop = 0;
    -		isaligned = 1;
    -		if ((error = xfs_alloc_vextent(&args)))
    -			return error;
    -	}
    -	if (isaligned && args.fsbno == NULLFSBLOCK) {
    -		/*
    -		 * allocation failed, so turn off alignment and
    -		 * try again.
    -		 */
    -		args.type = atype;
    -		args.fsbno = ap->rval;
    -		args.alignment = 0;
    -		if ((error = xfs_alloc_vextent(&args)))
    -			return error;
    -	}
    -	if (args.fsbno == NULLFSBLOCK && nullfb &&
    -	    args.minlen > ap->minlen) {
    -		args.minlen = ap->minlen;
    -		args.type = XFS_ALLOCTYPE_START_BNO;
    -		args.fsbno = ap->rval;
    -		if ((error = xfs_alloc_vextent(&args)))
    -			return error;
    -	}
    -	if (args.fsbno == NULLFSBLOCK && nullfb) {
    -		args.fsbno = 0;
    -		args.type = XFS_ALLOCTYPE_FIRST_AG;
    -		args.total = ap->minlen;
    -		args.minleft = 0;
    -		if ((error = xfs_alloc_vextent(&args)))
    -			return error;
    -		ap->low = 1;
    -	}
    -	if (args.fsbno != NULLFSBLOCK) {
    -		ap->firstblock = ap->rval = args.fsbno;
    -		ASSERT(nullfb || fb_agno == args.agno ||
    -		       (ap->low && fb_agno < args.agno));
    -		ap->alen = args.len;
    -		ap->ip->i_d.di_nblocks += args.len;
    -		xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE);
    -		if (ap->wasdel)
    -			ap->ip->i_delayed_blks -= args.len;
    -		/*
    -		 * Adjust the disk quota also. This was reserved
    -		 * earlier.
    -		 */
    -		XFS_TRANS_MOD_DQUOT_BYINO(mp, ap->tp, ap->ip,
    -			ap->wasdel ? XFS_TRANS_DQ_DELBCOUNT :
    -					XFS_TRANS_DQ_BCOUNT,
    -			(long) args.len);
    -	} else {
    -		ap->rval = NULLFSBLOCK;
    -		ap->alen = 0;
    -	}
    -	return 0;
    -}
    -
    -/*
    - * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file.
    - * It figures out where to ask the underlying allocator to put the new extent.
    - */
    -STATIC int
    -xfs_bmap_alloc(
    -	xfs_bmalloca_t	*ap)		/* bmap alloc argument struct */
    -{
    -	if ((ap->ip->i_d.di_flags & XFS_DIFLAG_REALTIME) && ap->userdata)
    -		return xfs_bmap_rtalloc(ap);
    -	return xfs_bmap_btalloc(ap);
    -}
    -
    -/*
    - * Transform a btree format file with only one leaf node, where the
    - * extents list will fit in the inode, into an extents format file.
    - * Since the file extents are already in-core, all we have to do is
    - * give up the space for the btree root and pitch the leaf block.
    - */
    -STATIC int				/* error */
    -xfs_bmap_btree_to_extents(
    -	xfs_trans_t		*tp,	/* transaction pointer */
    -	xfs_inode_t		*ip,	/* incore inode pointer */
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	int			*logflagsp, /* inode logging flags */
    -	int			whichfork)  /* data or attr fork */
    -{
    -	/* REFERENCED */
    -	xfs_bmbt_block_t	*cblock;/* child btree block */
    -	xfs_fsblock_t		cbno;	/* child block number */
    -	xfs_buf_t		*cbp;	/* child block's buffer */
    -	int			error;	/* error return value */
    -	xfs_ifork_t		*ifp;	/* inode fork data */
    -	xfs_mount_t		*mp;	/* mount point structure */
    -	xfs_bmbt_ptr_t		*pp;	/* ptr to block address */
    -	xfs_bmbt_block_t	*rblock;/* root btree block */
    -
    -	ifp = XFS_IFORK_PTR(ip, whichfork);
    -	ASSERT(ifp->if_flags & XFS_IFEXTENTS);
    -	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE);
    -	rblock = ifp->if_broot;
    -	ASSERT(be16_to_cpu(rblock->bb_level) == 1);
    -	ASSERT(be16_to_cpu(rblock->bb_numrecs) == 1);
    -	ASSERT(XFS_BMAP_BROOT_MAXRECS(ifp->if_broot_bytes) == 1);
    -	mp = ip->i_mount;
    -	pp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, ifp->if_broot_bytes);
    -	*logflagsp = 0;
    -#ifdef DEBUG
    -	if ((error = xfs_btree_check_lptr(cur, INT_GET(*pp, ARCH_CONVERT), 1)))
    -		return error;
    -#endif
    -	cbno = INT_GET(*pp, ARCH_CONVERT);
    -	if ((error = xfs_btree_read_bufl(mp, tp, cbno, 0, &cbp,
    -			XFS_BMAP_BTREE_REF)))
    -		return error;
    -	cblock = XFS_BUF_TO_BMBT_BLOCK(cbp);
    -	if ((error = xfs_btree_check_lblock(cur, cblock, 0, cbp)))
    -		return error;
    -	xfs_bmap_add_free(cbno, 1, cur->bc_private.b.flist, mp);
    -	ip->i_d.di_nblocks--;
    -	XFS_TRANS_MOD_DQUOT_BYINO(mp, tp, ip, XFS_TRANS_DQ_BCOUNT, -1L);
    -	xfs_trans_binval(tp, cbp);
    -	if (cur->bc_bufs[0] == cbp)
    -		cur->bc_bufs[0] = NULL;
    -	xfs_iroot_realloc(ip, -1, whichfork);
    -	ASSERT(ifp->if_broot == NULL);
    -	ASSERT((ifp->if_flags & XFS_IFBROOT) == 0);
    -	XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
    -	*logflagsp = XFS_ILOG_CORE | XFS_ILOG_FEXT(whichfork);
    -	return 0;
    -}
    -
    -/*
    - * Called by xfs_bmapi to update file extent records and the btree
    - * after removing space (or undoing a delayed allocation).
    - */
    -STATIC int				/* error */
    -xfs_bmap_del_extent(
    -	xfs_inode_t		*ip,	/* incore inode pointer */
    -	xfs_trans_t		*tp,	/* current transaction pointer */
    -	xfs_extnum_t		idx,	/* extent number to update/delete */
    -	xfs_bmap_free_t		*flist,	/* list of extents to be freed */
    -	xfs_btree_cur_t		*cur,	/* if null, not a btree */
    -	xfs_bmbt_irec_t		*del,	/* data to remove from extents */
    -	int			*logflagsp, /* inode logging flags */
    -	xfs_extdelta_t		*delta, /* Change made to incore extents */
    -	int			whichfork, /* data or attr fork */
    -	int			rsvd)	/* OK to allocate reserved blocks */
    -{
    -	xfs_filblks_t		da_new;	/* new delay-alloc indirect blocks */
    -	xfs_filblks_t		da_old;	/* old delay-alloc indirect blocks */
    -	xfs_fsblock_t		del_endblock=0;	/* first block past del */
    -	xfs_fileoff_t		del_endoff;	/* first offset past del */
    -	int			delay;	/* current block is delayed allocated */
    -	int			do_fx;	/* free extent at end of routine */
    -	xfs_bmbt_rec_t		*ep;	/* current extent entry pointer */
    -	int			error;	/* error return value */
    -	int			flags;	/* inode logging flags */
    -#ifdef XFS_BMAP_TRACE
    -	static char		fname[] = "xfs_bmap_del_extent";
    -#endif
    -	xfs_bmbt_irec_t		got;	/* current extent entry */
    -	xfs_fileoff_t		got_endoff;	/* first offset past got */
    -	int			i;	/* temp state */
    -	xfs_ifork_t		*ifp;	/* inode fork pointer */
    -	xfs_mount_t		*mp;	/* mount structure */
    -	xfs_filblks_t		nblks;	/* quota/sb block count */
    -	xfs_bmbt_irec_t		new;	/* new record to be inserted */
    -	/* REFERENCED */
    -	uint			qfield;	/* quota field to update */
    -	xfs_filblks_t		temp;	/* for indirect length calculations */
    -	xfs_filblks_t		temp2;	/* for indirect length calculations */
    -
    -	XFS_STATS_INC(xs_del_exlist);
    -	mp = ip->i_mount;
    -	ifp = XFS_IFORK_PTR(ip, whichfork);
    -	ASSERT((idx >= 0) && (idx < ifp->if_bytes /
    -		(uint)sizeof(xfs_bmbt_rec_t)));
    -	ASSERT(del->br_blockcount > 0);
    -	ep = xfs_iext_get_ext(ifp, idx);
    -	xfs_bmbt_get_all(ep, &got);
    -	ASSERT(got.br_startoff <= del->br_startoff);
    -	del_endoff = del->br_startoff + del->br_blockcount;
    -	got_endoff = got.br_startoff + got.br_blockcount;
    -	ASSERT(got_endoff >= del_endoff);
    -	delay = ISNULLSTARTBLOCK(got.br_startblock);
    -	ASSERT(ISNULLSTARTBLOCK(del->br_startblock) == delay);
    -	flags = 0;
    -	qfield = 0;
    -	error = 0;
    -	/*
    -	 * If deleting a real allocation, must free up the disk space.
    -	 */
    -	if (!delay) {
    -		flags = XFS_ILOG_CORE;
    -		/*
    -		 * Realtime allocation.  Free it and record di_nblocks update.
    -		 */
    -		if (whichfork == XFS_DATA_FORK &&
    -		    (ip->i_d.di_flags & XFS_DIFLAG_REALTIME)) {
    -			xfs_fsblock_t	bno;
    -			xfs_filblks_t	len;
    -
    -			ASSERT(do_mod(del->br_blockcount,
    -				      mp->m_sb.sb_rextsize) == 0);
    -			ASSERT(do_mod(del->br_startblock,
    -				      mp->m_sb.sb_rextsize) == 0);
    -			bno = del->br_startblock;
    -			len = del->br_blockcount;
    -			do_div(bno, mp->m_sb.sb_rextsize);
    -			do_div(len, mp->m_sb.sb_rextsize);
    -			if ((error = xfs_rtfree_extent(ip->i_transp, bno,
    -					(xfs_extlen_t)len)))
    -				goto done;
    -			do_fx = 0;
    -			nblks = len * mp->m_sb.sb_rextsize;
    -			qfield = XFS_TRANS_DQ_RTBCOUNT;
    -		}
    -		/*
    -		 * Ordinary allocation.
    -		 */
    -		else {
    -			do_fx = 1;
    -			nblks = del->br_blockcount;
    -			qfield = XFS_TRANS_DQ_BCOUNT;
    -		}
    -		/*
    -		 * Set up del_endblock and cur for later.
    -		 */
    -		del_endblock = del->br_startblock + del->br_blockcount;
    -		if (cur) {
    -			if ((error = xfs_bmbt_lookup_eq(cur, got.br_startoff,
    -					got.br_startblock, got.br_blockcount,
    -					&i)))
    -				goto done;
    -			ASSERT(i == 1);
    -		}
    -		da_old = da_new = 0;
    -	} else {
    -		da_old = STARTBLOCKVAL(got.br_startblock);
    -		da_new = 0;
    -		nblks = 0;
    -		do_fx = 0;
    -	}
    -	/*
    -	 * Set flag value to use in switch statement.
    -	 * Left-contig is 2, right-contig is 1.
    -	 */
    -	switch (((got.br_startoff == del->br_startoff) << 1) |
    -		(got_endoff == del_endoff)) {
    -	case 3:
    -		/*
    -		 * Matches the whole extent.  Delete the entry.
    -		 */
    -		xfs_bmap_trace_delete(fname, "3", ip, idx, 1, whichfork);
    -		xfs_iext_remove(ifp, idx, 1);
    -		ifp->if_lastex = idx;
    -		if (delay)
    -			break;
    -		XFS_IFORK_NEXT_SET(ip, whichfork,
    -			XFS_IFORK_NEXTENTS(ip, whichfork) - 1);
    -		flags |= XFS_ILOG_CORE;
    -		if (!cur) {
    -			flags |= XFS_ILOG_FEXT(whichfork);
    -			break;
    -		}
    -		if ((error = xfs_bmbt_delete(cur, &i)))
    -			goto done;
    -		ASSERT(i == 1);
    -		break;
    -
    -	case 2:
    -		/*
    -		 * Deleting the first part of the extent.
    -		 */
    -		xfs_bmap_trace_pre_update(fname, "2", ip, idx, whichfork);
    -		xfs_bmbt_set_startoff(ep, del_endoff);
    -		temp = got.br_blockcount - del->br_blockcount;
    -		xfs_bmbt_set_blockcount(ep, temp);
    -		ifp->if_lastex = idx;
    -		if (delay) {
    -			temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
    -				da_old);
    -			xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
    -			xfs_bmap_trace_post_update(fname, "2", ip, idx,
    -				whichfork);
    -			da_new = temp;
    -			break;
    -		}
    -		xfs_bmbt_set_startblock(ep, del_endblock);
    -		xfs_bmap_trace_post_update(fname, "2", ip, idx, whichfork);
    -		if (!cur) {
    -			flags |= XFS_ILOG_FEXT(whichfork);
    -			break;
    -		}
    -		if ((error = xfs_bmbt_update(cur, del_endoff, del_endblock,
    -				got.br_blockcount - del->br_blockcount,
    -				got.br_state)))
    -			goto done;
    -		break;
    -
    -	case 1:
    -		/*
    -		 * Deleting the last part of the extent.
    -		 */
    -		temp = got.br_blockcount - del->br_blockcount;
    -		xfs_bmap_trace_pre_update(fname, "1", ip, idx, whichfork);
    -		xfs_bmbt_set_blockcount(ep, temp);
    -		ifp->if_lastex = idx;
    -		if (delay) {
    -			temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
    -				da_old);
    -			xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
    -			xfs_bmap_trace_post_update(fname, "1", ip, idx,
    -				whichfork);
    -			da_new = temp;
    -			break;
    -		}
    -		xfs_bmap_trace_post_update(fname, "1", ip, idx, whichfork);
    -		if (!cur) {
    -			flags |= XFS_ILOG_FEXT(whichfork);
    -			break;
    -		}
    -		if ((error = xfs_bmbt_update(cur, got.br_startoff,
    -				got.br_startblock,
    -				got.br_blockcount - del->br_blockcount,
    -				got.br_state)))
    -			goto done;
    -		break;
    -
    -	case 0:
    -		/*
    -		 * Deleting the middle of the extent.
    -		 */
    -		temp = del->br_startoff - got.br_startoff;
    -		xfs_bmap_trace_pre_update(fname, "0", ip, idx, whichfork);
    -		xfs_bmbt_set_blockcount(ep, temp);
    -		new.br_startoff = del_endoff;
    -		temp2 = got_endoff - del_endoff;
    -		new.br_blockcount = temp2;
    -		new.br_state = got.br_state;
    -		if (!delay) {
    -			new.br_startblock = del_endblock;
    -			flags |= XFS_ILOG_CORE;
    -			if (cur) {
    -				if ((error = xfs_bmbt_update(cur,
    -						got.br_startoff,
    -						got.br_startblock, temp,
    -						got.br_state)))
    -					goto done;
    -				if ((error = xfs_bmbt_increment(cur, 0, &i)))
    -					goto done;
    -				cur->bc_rec.b = new;
    -				error = xfs_bmbt_insert(cur, &i);
    -				if (error && error != ENOSPC)
    -					goto done;
    -				/*
    -				 * If get no-space back from btree insert,
    -				 * it tried a split, and we have a zero
    -				 * block reservation.
    -				 * Fix up our state and return the error.
    -				 */
    -				if (error == ENOSPC) {
    -					/*
    -					 * Reset the cursor, don't trust
    -					 * it after any insert operation.
    -					 */
    -					if ((error = xfs_bmbt_lookup_eq(cur,
    -							got.br_startoff,
    -							got.br_startblock,
    -							temp, &i)))
    -						goto done;
    -					ASSERT(i == 1);
    -					/*
    -					 * Update the btree record back
    -					 * to the original value.
    -					 */
    -					if ((error = xfs_bmbt_update(cur,
    -							got.br_startoff,
    -							got.br_startblock,
    -							got.br_blockcount,
    -							got.br_state)))
    -						goto done;
    -					/*
    -					 * Reset the extent record back
    -					 * to the original value.
    -					 */
    -					xfs_bmbt_set_blockcount(ep,
    -						got.br_blockcount);
    -					flags = 0;
    -					error = XFS_ERROR(ENOSPC);
    -					goto done;
    -				}
    -				ASSERT(i == 1);
    -			} else
    -				flags |= XFS_ILOG_FEXT(whichfork);
    -			XFS_IFORK_NEXT_SET(ip, whichfork,
    -				XFS_IFORK_NEXTENTS(ip, whichfork) + 1);
    -		} else {
    -			ASSERT(whichfork == XFS_DATA_FORK);
    -			temp = xfs_bmap_worst_indlen(ip, temp);
    -			xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
    -			temp2 = xfs_bmap_worst_indlen(ip, temp2);
    -			new.br_startblock = NULLSTARTBLOCK((int)temp2);
    -			da_new = temp + temp2;
    -			while (da_new > da_old) {
    -				if (temp) {
    -					temp--;
    -					da_new--;
    -					xfs_bmbt_set_startblock(ep,
    -						NULLSTARTBLOCK((int)temp));
    -				}
    -				if (da_new == da_old)
    -					break;
    -				if (temp2) {
    -					temp2--;
    -					da_new--;
    -					new.br_startblock =
    -						NULLSTARTBLOCK((int)temp2);
    -				}
    -			}
    -		}
    -		xfs_bmap_trace_post_update(fname, "0", ip, idx, whichfork);
    -		xfs_bmap_trace_insert(fname, "0", ip, idx + 1, 1, &new, NULL,
    -			whichfork);
    -		xfs_iext_insert(ifp, idx + 1, 1, &new);
    -		ifp->if_lastex = idx + 1;
    -		break;
    -	}
    -	/*
    -	 * If we need to, add to list of extents to delete.
    -	 */
    -	if (do_fx)
    -		xfs_bmap_add_free(del->br_startblock, del->br_blockcount, flist,
    -			mp);
    -	/*
    -	 * Adjust inode # blocks in the file.
    -	 */
    -	if (nblks)
    -		ip->i_d.di_nblocks -= nblks;
    -	/*
    -	 * Adjust quota data.
    -	 */
    -	if (qfield)
    -		XFS_TRANS_MOD_DQUOT_BYINO(mp, tp, ip, qfield, (long)-nblks);
    -
    -	/*
    -	 * Account for change in delayed indirect blocks.
    -	 * Nothing to do for disk quota accounting here.
    -	 */
    -	ASSERT(da_old >= da_new);
    -	if (da_old > da_new)
    -		xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, (int)(da_old - da_new),
    -			rsvd);
    -	if (delta) {
    -		/* DELTA: report the original extent. */
    -		if (delta->xed_startoff > got.br_startoff)
    -			delta->xed_startoff = got.br_startoff;
    -		if (delta->xed_blockcount < got.br_startoff+got.br_blockcount)
    -			delta->xed_blockcount = got.br_startoff +
    -							got.br_blockcount;
    -	}
    -done:
    -	*logflagsp = flags;
    -	return error;
    -}
    -
    -/*
    - * Remove the entry "free" from the free item list.  Prev points to the
    - * previous entry, unless "free" is the head of the list.
    - */
    -STATIC void
    -xfs_bmap_del_free(
    -	xfs_bmap_free_t		*flist,	/* free item list header */
    -	xfs_bmap_free_item_t	*prev,	/* previous item on list, if any */
    -	xfs_bmap_free_item_t	*free)	/* list item to be freed */
    -{
    -	if (prev)
    -		prev->xbfi_next = free->xbfi_next;
    -	else
    -		flist->xbf_first = free->xbfi_next;
    -	flist->xbf_count--;
    -	kmem_zone_free(xfs_bmap_free_item_zone, free);
    -}
    -
    -/*
    - * Convert an extents-format file into a btree-format file.
    - * The new file will have a root block (in the inode) and a single child block.
    - */
    -STATIC int					/* error */
    -xfs_bmap_extents_to_btree(
    -	xfs_trans_t		*tp,		/* transaction pointer */
    -	xfs_inode_t		*ip,		/* incore inode pointer */
    -	xfs_fsblock_t		*firstblock,	/* first-block-allocated */
    -	xfs_bmap_free_t		*flist,		/* blocks freed in xaction */
    -	xfs_btree_cur_t		**curp,		/* cursor returned to caller */
    -	int			wasdel,		/* converting a delayed alloc */
    -	int			*logflagsp,	/* inode logging flags */
    -	int			whichfork)	/* data or attr fork */
    -{
    -	xfs_bmbt_block_t	*ablock;	/* allocated (child) bt block */
    -	xfs_buf_t		*abp;		/* buffer for ablock */
    -	xfs_alloc_arg_t		args;		/* allocation arguments */
    -	xfs_bmbt_rec_t		*arp;		/* child record pointer */
    -	xfs_bmbt_block_t	*block;		/* btree root block */
    -	xfs_btree_cur_t		*cur;		/* bmap btree cursor */
    -	xfs_bmbt_rec_t		*ep;		/* extent record pointer */
    -	int			error;		/* error return value */
    -	xfs_extnum_t		i, cnt;		/* extent record index */
    -	xfs_ifork_t		*ifp;		/* inode fork pointer */
    -	xfs_bmbt_key_t		*kp;		/* root block key pointer */
    -	xfs_mount_t		*mp;		/* mount structure */
    -	xfs_extnum_t		nextents;	/* number of file extents */
    -	xfs_bmbt_ptr_t		*pp;		/* root block address pointer */
    -
    -	ifp = XFS_IFORK_PTR(ip, whichfork);
    -	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS);
    -	ASSERT(ifp->if_ext_max ==
    -	       XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
    -	/*
    -	 * Make space in the inode incore.
    -	 */
    -	xfs_iroot_realloc(ip, 1, whichfork);
    -	ifp->if_flags |= XFS_IFBROOT;
    -	/*
    -	 * Fill in the root.
    -	 */
    -	block = ifp->if_broot;
    -	block->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
    -	block->bb_level = cpu_to_be16(1);
    -	block->bb_numrecs = cpu_to_be16(1);
    -	block->bb_leftsib = cpu_to_be64(NULLDFSBNO);
    -	block->bb_rightsib = cpu_to_be64(NULLDFSBNO);
    -	/*
    -	 * Need a cursor.  Can't allocate until bb_level is filled in.
    -	 */
    -	mp = ip->i_mount;
    -	cur = xfs_btree_init_cursor(mp, tp, NULL, 0, XFS_BTNUM_BMAP, ip,
    -		whichfork);
    -	cur->bc_private.b.firstblock = *firstblock;
    -	cur->bc_private.b.flist = flist;
    -	cur->bc_private.b.flags = wasdel ? XFS_BTCUR_BPRV_WASDEL : 0;
    -	/*
    -	 * Convert to a btree with two levels, one record in root.
    -	 */
    -	XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_BTREE);
    -	args.tp = tp;
    -	args.mp = mp;
    -	if (*firstblock == NULLFSBLOCK) {
    -		args.type = XFS_ALLOCTYPE_START_BNO;
    -		args.fsbno = XFS_INO_TO_FSB(mp, ip->i_ino);
    -	} else if (flist->xbf_low) {
    -		args.type = XFS_ALLOCTYPE_START_BNO;
    -		args.fsbno = *firstblock;
    -	} else {
    -		args.type = XFS_ALLOCTYPE_NEAR_BNO;
    -		args.fsbno = *firstblock;
    -	}
    -	args.minlen = args.maxlen = args.prod = 1;
    -	args.total = args.minleft = args.alignment = args.mod = args.isfl =
    -		args.minalignslop = 0;
    -	args.wasdel = wasdel;
    -	*logflagsp = 0;
    -	if ((error = xfs_alloc_vextent(&args))) {
    -		xfs_iroot_realloc(ip, -1, whichfork);
    -		xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
    -		return error;
    -	}
    -	/*
    -	 * Allocation can't fail, the space was reserved.
    -	 */
    -	ASSERT(args.fsbno != NULLFSBLOCK);
    -	ASSERT(*firstblock == NULLFSBLOCK ||
    -	       args.agno == XFS_FSB_TO_AGNO(mp, *firstblock) ||
    -	       (flist->xbf_low &&
    -		args.agno > XFS_FSB_TO_AGNO(mp, *firstblock)));
    -	*firstblock = cur->bc_private.b.firstblock = args.fsbno;
    -	cur->bc_private.b.allocated++;
    -	ip->i_d.di_nblocks++;
    -	XFS_TRANS_MOD_DQUOT_BYINO(mp, tp, ip, XFS_TRANS_DQ_BCOUNT, 1L);
    -	abp = xfs_btree_get_bufl(mp, tp, args.fsbno, 0);
    -	/*
    -	 * Fill in the child block.
    -	 */
    -	ablock = XFS_BUF_TO_BMBT_BLOCK(abp);
    -	ablock->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
    -	ablock->bb_level = 0;
    -	ablock->bb_leftsib = cpu_to_be64(NULLDFSBNO);
    -	ablock->bb_rightsib = cpu_to_be64(NULLDFSBNO);
    -	arp = XFS_BMAP_REC_IADDR(ablock, 1, cur);
    -	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
    -	for (cnt = i = 0; i < nextents; i++) {
    -		ep = xfs_iext_get_ext(ifp, i);
    -		if (!ISNULLSTARTBLOCK(xfs_bmbt_get_startblock(ep))) {
    -			arp->l0 = INT_GET(ep->l0, ARCH_CONVERT);
    -			arp->l1 = INT_GET(ep->l1, ARCH_CONVERT);
    -			arp++; cnt++;
    -		}
    -	}
    -	ASSERT(cnt == XFS_IFORK_NEXTENTS(ip, whichfork));
    -	ablock->bb_numrecs = cpu_to_be16(cnt);
    -	/*
    -	 * Fill in the root key and pointer.
    -	 */
    -	kp = XFS_BMAP_KEY_IADDR(block, 1, cur);
    -	arp = XFS_BMAP_REC_IADDR(ablock, 1, cur);
    -	INT_SET(kp->br_startoff, ARCH_CONVERT, xfs_bmbt_disk_get_startoff(arp));
    -	pp = XFS_BMAP_PTR_IADDR(block, 1, cur);
    -	INT_SET(*pp, ARCH_CONVERT, args.fsbno);
    -	/*
    -	 * Do all this logging at the end so that
    -	 * the root is at the right level.
    -	 */
    -	xfs_bmbt_log_block(cur, abp, XFS_BB_ALL_BITS);
    -	xfs_bmbt_log_recs(cur, abp, 1, be16_to_cpu(ablock->bb_numrecs));
    -	ASSERT(*curp == NULL);
    -	*curp = cur;
    -	*logflagsp = XFS_ILOG_CORE | XFS_ILOG_FBROOT(whichfork);
    -	return 0;
    -}
    -
    -/*
    - * Helper routine to reset inode di_forkoff field when switching
    - * attribute fork from local to extent format - we reset it where
    - * possible to make space available for inline data fork extents.
    - */
    -STATIC void
    -xfs_bmap_forkoff_reset(
    -	xfs_mount_t	*mp,
    -	xfs_inode_t	*ip,
    -	int		whichfork)
    -{
    -	if (whichfork == XFS_ATTR_FORK &&
    -	    (ip->i_d.di_format != XFS_DINODE_FMT_DEV) &&
    -	    (ip->i_d.di_format != XFS_DINODE_FMT_UUID) &&
    -	    ((mp->m_attroffset >> 3) > ip->i_d.di_forkoff)) {
    -		ip->i_d.di_forkoff = mp->m_attroffset >> 3;
    -		ip->i_df.if_ext_max = XFS_IFORK_DSIZE(ip) /
    -					(uint)sizeof(xfs_bmbt_rec_t);
    -		ip->i_afp->if_ext_max = XFS_IFORK_ASIZE(ip) /
    -					(uint)sizeof(xfs_bmbt_rec_t);
    -	}
    -}
    -
    -/*
    - * Convert a local file to an extents file.
    - * This code is out of bounds for data forks of regular files,
    - * since the file data needs to get logged so things will stay consistent.
    - * (The bmap-level manipulations are ok, though).
    - */
    -STATIC int				/* error */
    -xfs_bmap_local_to_extents(
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_inode_t	*ip,		/* incore inode pointer */
    -	xfs_fsblock_t	*firstblock,	/* first block allocated in xaction */
    -	xfs_extlen_t	total,		/* total blocks needed by transaction */
    -	int		*logflagsp,	/* inode logging flags */
    -	int		whichfork)	/* data or attr fork */
    -{
    -	int		error;		/* error return value */
    -	int		flags;		/* logging flags returned */
    -#ifdef XFS_BMAP_TRACE
    -	static char	fname[] = "xfs_bmap_local_to_extents";
    -#endif
    -	xfs_ifork_t	*ifp;		/* inode fork pointer */
    -
    -	/*
    -	 * We don't want to deal with the case of keeping inode data inline yet.
    -	 * So sending the data fork of a regular inode is invalid.
    -	 */
    -	ASSERT(!((ip->i_d.di_mode & S_IFMT) == S_IFREG &&
    -		 whichfork == XFS_DATA_FORK));
    -	ifp = XFS_IFORK_PTR(ip, whichfork);
    -	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
    -	flags = 0;
    -	error = 0;
    -	if (ifp->if_bytes) {
    -		xfs_alloc_arg_t	args;	/* allocation arguments */
    -		xfs_buf_t	*bp;	/* buffer for extent block */
    -		xfs_bmbt_rec_t	*ep;	/* extent record pointer */
    -
    -		args.tp = tp;
    -		args.mp = ip->i_mount;
    -		ASSERT((ifp->if_flags &
    -			(XFS_IFINLINE|XFS_IFEXTENTS|XFS_IFEXTIREC)) == XFS_IFINLINE);
    -		/*
    -		 * Allocate a block.  We know we need only one, since the
    -		 * file currently fits in an inode.
    -		 */
    -		if (*firstblock == NULLFSBLOCK) {
    -			args.fsbno = XFS_INO_TO_FSB(args.mp, ip->i_ino);
    -			args.type = XFS_ALLOCTYPE_START_BNO;
    -		} else {
    -			args.fsbno = *firstblock;
    -			args.type = XFS_ALLOCTYPE_NEAR_BNO;
    -		}
    -		args.total = total;
    -		args.mod = args.minleft = args.alignment = args.wasdel =
    -			args.isfl = args.minalignslop = 0;
    -		args.minlen = args.maxlen = args.prod = 1;
    -		if ((error = xfs_alloc_vextent(&args)))
    -			goto done;
    -		/*
    -		 * Can't fail, the space was reserved.
    -		 */
    -		ASSERT(args.fsbno != NULLFSBLOCK);
    -		ASSERT(args.len == 1);
    -		*firstblock = args.fsbno;
    -		bp = xfs_btree_get_bufl(args.mp, tp, args.fsbno, 0);
    -		memcpy((char *)XFS_BUF_PTR(bp), ifp->if_u1.if_data,
    -			ifp->if_bytes);
    -		xfs_trans_log_buf(tp, bp, 0, ifp->if_bytes - 1);
    -		xfs_bmap_forkoff_reset(args.mp, ip, whichfork);
    -		xfs_idata_realloc(ip, -ifp->if_bytes, whichfork);
    -		xfs_iext_add(ifp, 0, 1);
    -		ep = xfs_iext_get_ext(ifp, 0);
    -		xfs_bmbt_set_allf(ep, 0, args.fsbno, 1, XFS_EXT_NORM);
    -		xfs_bmap_trace_post_update(fname, "new", ip, 0, whichfork);
    -		XFS_IFORK_NEXT_SET(ip, whichfork, 1);
    -		ip->i_d.di_nblocks = 1;
    -		XFS_TRANS_MOD_DQUOT_BYINO(args.mp, tp, ip,
    -			XFS_TRANS_DQ_BCOUNT, 1L);
    -		flags |= XFS_ILOG_FEXT(whichfork);
    -	} else {
    -		ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) == 0);
    -		xfs_bmap_forkoff_reset(ip->i_mount, ip, whichfork);
    -	}
    -	ifp->if_flags &= ~XFS_IFINLINE;
    -	ifp->if_flags |= XFS_IFEXTENTS;
    -	XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
    -	flags |= XFS_ILOG_CORE;
    -done:
    -	*logflagsp = flags;
    -	return error;
    -}
    -
    -/*
    - * Search the extent records for the entry containing block bno.
    - * If bno lies in a hole, point to the next entry.  If bno lies
    - * past eof, *eofp will be set, and *prevp will contain the last
    - * entry (null if none).  Else, *lastxp will be set to the index
    - * of the found entry; *gotp will contain the entry.
    - */
    -xfs_bmbt_rec_t *			/* pointer to found extent entry */
    -xfs_bmap_search_multi_extents(
    -	xfs_ifork_t	*ifp,		/* inode fork pointer */
    -	xfs_fileoff_t	bno,		/* block number searched for */
    -	int		*eofp,		/* out: end of file found */
    -	xfs_extnum_t	*lastxp,	/* out: last extent index */
    -	xfs_bmbt_irec_t	*gotp,		/* out: extent entry found */
    -	xfs_bmbt_irec_t	*prevp)		/* out: previous extent entry found */
    -{
    -	xfs_bmbt_rec_t	*ep;		/* extent record pointer */
    -	xfs_extnum_t	lastx;		/* last extent index */
    -
    -	/*
    -	 * Initialize the extent entry structure to catch access to
    -	 * uninitialized br_startblock field.
    -	 */
    -	gotp->br_startoff = 0xffa5a5a5a5a5a5a5LL;
    -	gotp->br_blockcount = 0xa55a5a5a5a5a5a5aLL;
    -	gotp->br_state = XFS_EXT_INVALID;
    -#if XFS_BIG_BLKNOS
    -	gotp->br_startblock = 0xffffa5a5a5a5a5a5LL;
    -#else
    -	gotp->br_startblock = 0xffffa5a5;
    -#endif
    -	prevp->br_startoff = NULLFILEOFF;
    -
    -	ep = xfs_iext_bno_to_ext(ifp, bno, &lastx);
    -	if (lastx > 0) {
    -		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, lastx - 1), prevp);
    -	}
    -	if (lastx < (ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t))) {
    -		xfs_bmbt_get_all(ep, gotp);
    -		*eofp = 0;
    -	} else {
    -		if (lastx > 0) {
    -			*gotp = *prevp;
    -		}
    -		*eofp = 1;
    -		ep = NULL;
    -	}
    -	*lastxp = lastx;
    -	return ep;
    -}
    -
    -/*
    - * Search the extents list for the inode, for the extent containing bno.
    - * If bno lies in a hole, point to the next entry.  If bno lies past eof,
    - * *eofp will be set, and *prevp will contain the last entry (null if none).
    - * Else, *lastxp will be set to the index of the found
    - * entry; *gotp will contain the entry.
    - */
    -STATIC xfs_bmbt_rec_t *                 /* pointer to found extent entry */
    -xfs_bmap_search_extents(
    -	xfs_inode_t     *ip,            /* incore inode pointer */
    -	xfs_fileoff_t   bno,            /* block number searched for */
    -	int             whichfork,      /* data or attr fork */
    -	int             *eofp,          /* out: end of file found */
    -	xfs_extnum_t    *lastxp,        /* out: last extent index */
    -	xfs_bmbt_irec_t *gotp,          /* out: extent entry found */
    -	xfs_bmbt_irec_t *prevp)         /* out: previous extent entry found */
    -{
    -	xfs_ifork_t	*ifp;		/* inode fork pointer */
    -	xfs_bmbt_rec_t  *ep;            /* extent record pointer */
    -	int		rt;		/* realtime flag    */
    -
    -	XFS_STATS_INC(xs_look_exlist);
    -	ifp = XFS_IFORK_PTR(ip, whichfork);
    -
    -	ep = xfs_bmap_search_multi_extents(ifp, bno, eofp, lastxp, gotp, prevp);
    -
    -	rt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip);
    -	if (unlikely(!rt && !gotp->br_startblock && (*lastxp != NULLEXTNUM))) {
    -                cmn_err(CE_PANIC,"Access to block zero: fs: <%s> inode: %lld "
    -			"start_block : %llx start_off : %llx blkcnt : %llx "
    -			"extent-state : %x \n",
    -			(ip->i_mount)->m_fsname, (long long)ip->i_ino,
    -			(unsigned long long)gotp->br_startblock,
    -			(unsigned long long)gotp->br_startoff,
    -			(unsigned long long)gotp->br_blockcount,
    -			gotp->br_state);
    -        }
    -        return ep;
    -}
    -
    -
    -#ifdef XFS_BMAP_TRACE
    -ktrace_t	*xfs_bmap_trace_buf;
    -
    -/*
    - * Add a bmap trace buffer entry.  Base routine for the others.
    - */
    -STATIC void
    -xfs_bmap_trace_addentry(
    -	int		opcode,		/* operation */
    -	char		*fname,		/* function name */
    -	char		*desc,		/* operation description */
    -	xfs_inode_t	*ip,		/* incore inode pointer */
    -	xfs_extnum_t	idx,		/* index of entry(ies) */
    -	xfs_extnum_t	cnt,		/* count of entries, 1 or 2 */
    -	xfs_bmbt_rec_t	*r1,		/* first record */
    -	xfs_bmbt_rec_t	*r2,		/* second record or null */
    -	int		whichfork)	/* data or attr fork */
    -{
    -	xfs_bmbt_rec_t	tr2;
    -
    -	ASSERT(cnt == 1 || cnt == 2);
    -	ASSERT(r1 != NULL);
    -	if (cnt == 1) {
    -		ASSERT(r2 == NULL);
    -		r2 = &tr2;
    -		memset(&tr2, 0, sizeof(tr2));
    -	} else
    -		ASSERT(r2 != NULL);
    -	ktrace_enter(xfs_bmap_trace_buf,
    -		(void *)(__psint_t)(opcode | (whichfork << 16)),
    -		(void *)fname, (void *)desc, (void *)ip,
    -		(void *)(__psint_t)idx,
    -		(void *)(__psint_t)cnt,
    -		(void *)(__psunsigned_t)(ip->i_ino >> 32),
    -		(void *)(__psunsigned_t)(unsigned)ip->i_ino,
    -		(void *)(__psunsigned_t)(r1->l0 >> 32),
    -		(void *)(__psunsigned_t)(unsigned)(r1->l0),
    -		(void *)(__psunsigned_t)(r1->l1 >> 32),
    -		(void *)(__psunsigned_t)(unsigned)(r1->l1),
    -		(void *)(__psunsigned_t)(r2->l0 >> 32),
    -		(void *)(__psunsigned_t)(unsigned)(r2->l0),
    -		(void *)(__psunsigned_t)(r2->l1 >> 32),
    -		(void *)(__psunsigned_t)(unsigned)(r2->l1)
    -		);
    -	ASSERT(ip->i_xtrace);
    -	ktrace_enter(ip->i_xtrace,
    -		(void *)(__psint_t)(opcode | (whichfork << 16)),
    -		(void *)fname, (void *)desc, (void *)ip,
    -		(void *)(__psint_t)idx,
    -		(void *)(__psint_t)cnt,
    -		(void *)(__psunsigned_t)(ip->i_ino >> 32),
    -		(void *)(__psunsigned_t)(unsigned)ip->i_ino,
    -		(void *)(__psunsigned_t)(r1->l0 >> 32),
    -		(void *)(__psunsigned_t)(unsigned)(r1->l0),
    -		(void *)(__psunsigned_t)(r1->l1 >> 32),
    -		(void *)(__psunsigned_t)(unsigned)(r1->l1),
    -		(void *)(__psunsigned_t)(r2->l0 >> 32),
    -		(void *)(__psunsigned_t)(unsigned)(r2->l0),
    -		(void *)(__psunsigned_t)(r2->l1 >> 32),
    -		(void *)(__psunsigned_t)(unsigned)(r2->l1)
    -		);
    -}
    -
    -/*
    - * Add bmap trace entry prior to a call to xfs_iext_remove.
    - */
    -STATIC void
    -xfs_bmap_trace_delete(
    -	char		*fname,		/* function name */
    -	char		*desc,		/* operation description */
    -	xfs_inode_t	*ip,		/* incore inode pointer */
    -	xfs_extnum_t	idx,		/* index of entry(entries) deleted */
    -	xfs_extnum_t	cnt,		/* count of entries deleted, 1 or 2 */
    -	int		whichfork)	/* data or attr fork */
    -{
    -	xfs_ifork_t	*ifp;		/* inode fork pointer */
    -
    -	ifp = XFS_IFORK_PTR(ip, whichfork);
    -	xfs_bmap_trace_addentry(XFS_BMAP_KTRACE_DELETE, fname, desc, ip, idx,
    -		cnt, xfs_iext_get_ext(ifp, idx),
    -		cnt == 2 ? xfs_iext_get_ext(ifp, idx + 1) : NULL,
    -		whichfork);
    -}
    -
    -/*
    - * Add bmap trace entry prior to a call to xfs_iext_insert, or
    - * reading in the extents list from the disk (in the btree).
    - */
    -STATIC void
    -xfs_bmap_trace_insert(
    -	char		*fname,		/* function name */
    -	char		*desc,		/* operation description */
    -	xfs_inode_t	*ip,		/* incore inode pointer */
    -	xfs_extnum_t	idx,		/* index of entry(entries) inserted */
    -	xfs_extnum_t	cnt,		/* count of entries inserted, 1 or 2 */
    -	xfs_bmbt_irec_t	*r1,		/* inserted record 1 */
    -	xfs_bmbt_irec_t	*r2,		/* inserted record 2 or null */
    -	int		whichfork)	/* data or attr fork */
    -{
    -	xfs_bmbt_rec_t	tr1;		/* compressed record 1 */
    -	xfs_bmbt_rec_t	tr2;		/* compressed record 2 if needed */
    -
    -	xfs_bmbt_set_all(&tr1, r1);
    -	if (cnt == 2) {
    -		ASSERT(r2 != NULL);
    -		xfs_bmbt_set_all(&tr2, r2);
    -	} else {
    -		ASSERT(cnt == 1);
    -		ASSERT(r2 == NULL);
    -	}
    -	xfs_bmap_trace_addentry(XFS_BMAP_KTRACE_INSERT, fname, desc, ip, idx,
    -		cnt, &tr1, cnt == 2 ? &tr2 : NULL, whichfork);
    -}
    -
    -/*
    - * Add bmap trace entry after updating an extent record in place.
    - */
    -STATIC void
    -xfs_bmap_trace_post_update(
    -	char		*fname,		/* function name */
    -	char		*desc,		/* operation description */
    -	xfs_inode_t	*ip,		/* incore inode pointer */
    -	xfs_extnum_t	idx,		/* index of entry updated */
    -	int		whichfork)	/* data or attr fork */
    -{
    -	xfs_ifork_t	*ifp;		/* inode fork pointer */
    -
    -	ifp = XFS_IFORK_PTR(ip, whichfork);
    -	xfs_bmap_trace_addentry(XFS_BMAP_KTRACE_POST_UP, fname, desc, ip, idx,
    -		1, xfs_iext_get_ext(ifp, idx), NULL, whichfork);
    -}
    -
    -/*
    - * Add bmap trace entry prior to updating an extent record in place.
    - */
    -STATIC void
    -xfs_bmap_trace_pre_update(
    -	char		*fname,		/* function name */
    -	char		*desc,		/* operation description */
    -	xfs_inode_t	*ip,		/* incore inode pointer */
    -	xfs_extnum_t	idx,		/* index of entry to be updated */
    -	int		whichfork)	/* data or attr fork */
    -{
    -	xfs_ifork_t	*ifp;		/* inode fork pointer */
    -
    -	ifp = XFS_IFORK_PTR(ip, whichfork);
    -	xfs_bmap_trace_addentry(XFS_BMAP_KTRACE_PRE_UP, fname, desc, ip, idx, 1,
    -		xfs_iext_get_ext(ifp, idx), NULL, whichfork);
    -}
    -#endif	/* XFS_BMAP_TRACE */
    -
    -/*
    - * Compute the worst-case number of indirect blocks that will be used
    - * for ip's delayed extent of length "len".
    - */
    -STATIC xfs_filblks_t
    -xfs_bmap_worst_indlen(
    -	xfs_inode_t	*ip,		/* incore inode pointer */
    -	xfs_filblks_t	len)		/* delayed extent length */
    -{
    -	int		level;		/* btree level number */
    -	int		maxrecs;	/* maximum record count at this level */
    -	xfs_mount_t	*mp;		/* mount structure */
    -	xfs_filblks_t	rval;		/* return value */
    -
    -	mp = ip->i_mount;
    -	maxrecs = mp->m_bmap_dmxr[0];
    -	for (level = 0, rval = 0;
    -	     level < XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK);
    -	     level++) {
    -		len += maxrecs - 1;
    -		do_div(len, maxrecs);
    -		rval += len;
    -		if (len == 1)
    -			return rval + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) -
    -				level - 1;
    -		if (level == 0)
    -			maxrecs = mp->m_bmap_dmxr[1];
    -	}
    -	return rval;
    -}
    -
    -#if defined(XFS_RW_TRACE)
    -STATIC void
    -xfs_bunmap_trace(
    -	xfs_inode_t		*ip,
    -	xfs_fileoff_t		bno,
    -	xfs_filblks_t		len,
    -	int			flags,
    -	inst_t			*ra)
    -{
    -	if (ip->i_rwtrace == NULL)
    -		return;
    -	ktrace_enter(ip->i_rwtrace,
    -		(void *)(__psint_t)XFS_BUNMAP,
    -		(void *)ip,
    -		(void *)(__psint_t)((ip->i_d.di_size >> 32) & 0xffffffff),
    -		(void *)(__psint_t)(ip->i_d.di_size & 0xffffffff),
    -		(void *)(__psint_t)(((xfs_dfiloff_t)bno >> 32) & 0xffffffff),
    -		(void *)(__psint_t)((xfs_dfiloff_t)bno & 0xffffffff),
    -		(void *)(__psint_t)len,
    -		(void *)(__psint_t)flags,
    -		(void *)current_cpu(),
    -		(void *)ra,
    -		(void *)0,
    -		(void *)0,
    -		(void *)0,
    -		(void *)0,
    -		(void *)0,
    -		(void *)0);
    -}
    -#endif
    -
    -/*
    - * Convert inode from non-attributed to attributed.
    - * Must not be in a transaction, ip must not be locked.
    - */
    -int						/* error code */
    -xfs_bmap_add_attrfork(
    -	xfs_inode_t		*ip,		/* incore inode pointer */
    -	int			size,		/* space new attribute needs */
    -	int			rsvd)		/* xact may use reserved blks */
    -{
    -	xfs_fsblock_t		firstblock;	/* 1st block/ag allocated */
    -	xfs_bmap_free_t		flist;		/* freed extent records */
    -	xfs_mount_t		*mp;		/* mount structure */
    -	xfs_trans_t		*tp;		/* transaction pointer */
    -	unsigned long		s;		/* spinlock spl value */
    -	int			blks;		/* space reservation */
    -	int			version = 1;	/* superblock attr version */
    -	int			committed;	/* xaction was committed */
    -	int			logflags;	/* logging flags */
    -	int			error;		/* error return value */
    -
    -	ASSERT(XFS_IFORK_Q(ip) == 0);
    -	ASSERT(ip->i_df.if_ext_max ==
    -	       XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t));
    -
    -	mp = ip->i_mount;
    -	ASSERT(!XFS_NOT_DQATTACHED(mp, ip));
    -	tp = xfs_trans_alloc(mp, XFS_TRANS_ADDAFORK);
    -	blks = XFS_ADDAFORK_SPACE_RES(mp);
    -	if (rsvd)
    -		tp->t_flags |= XFS_TRANS_RESERVE;
    -	if ((error = xfs_trans_reserve(tp, blks, XFS_ADDAFORK_LOG_RES(mp), 0,
    -			XFS_TRANS_PERM_LOG_RES, XFS_ADDAFORK_LOG_COUNT)))
    -		goto error0;
    -	xfs_ilock(ip, XFS_ILOCK_EXCL);
    -	error = XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, blks, 0, rsvd ?
    -			XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES :
    -			XFS_QMOPT_RES_REGBLKS);
    -	if (error) {
    -		xfs_iunlock(ip, XFS_ILOCK_EXCL);
    -		xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES);
    -		return error;
    -	}
    -	if (XFS_IFORK_Q(ip))
    -		goto error1;
    -	if (ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS) {
    -		/*
    -		 * For inodes coming from pre-6.2 filesystems.
    -		 */
    -		ASSERT(ip->i_d.di_aformat == 0);
    -		ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
    -	}
    -	ASSERT(ip->i_d.di_anextents == 0);
    -	VN_HOLD(XFS_ITOV(ip));
    -	xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
    -	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
    -	switch (ip->i_d.di_format) {
    -	case XFS_DINODE_FMT_DEV:
    -		ip->i_d.di_forkoff = roundup(sizeof(xfs_dev_t), 8) >> 3;
    -		break;
    -	case XFS_DINODE_FMT_UUID:
    -		ip->i_d.di_forkoff = roundup(sizeof(uuid_t), 8) >> 3;
    -		break;
    -	case XFS_DINODE_FMT_LOCAL:
    -	case XFS_DINODE_FMT_EXTENTS:
    -	case XFS_DINODE_FMT_BTREE:
    -		ip->i_d.di_forkoff = xfs_attr_shortform_bytesfit(ip, size);
    -		if (!ip->i_d.di_forkoff)
    -			ip->i_d.di_forkoff = mp->m_attroffset >> 3;
    -		else if (mp->m_flags & XFS_MOUNT_ATTR2)
    -			version = 2;
    -		break;
    -	default:
    -		ASSERT(0);
    -		error = XFS_ERROR(EINVAL);
    -		goto error1;
    -	}
    -	ip->i_df.if_ext_max =
    -		XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t);
    -	ASSERT(ip->i_afp == NULL);
    -	ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_SLEEP);
    -	ip->i_afp->if_ext_max =
    -		XFS_IFORK_ASIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t);
    -	ip->i_afp->if_flags = XFS_IFEXTENTS;
    -	logflags = 0;
    -	XFS_BMAP_INIT(&flist, &firstblock);
    -	switch (ip->i_d.di_format) {
    -	case XFS_DINODE_FMT_LOCAL:
    -		error = xfs_bmap_add_attrfork_local(tp, ip, &firstblock, &flist,
    -			&logflags);
    -		break;
    -	case XFS_DINODE_FMT_EXTENTS:
    -		error = xfs_bmap_add_attrfork_extents(tp, ip, &firstblock,
    -			&flist, &logflags);
    -		break;
    -	case XFS_DINODE_FMT_BTREE:
    -		error = xfs_bmap_add_attrfork_btree(tp, ip, &firstblock, &flist,
    -			&logflags);
    -		break;
    -	default:
    -		error = 0;
    -		break;
    -	}
    -	if (logflags)
    -		xfs_trans_log_inode(tp, ip, logflags);
    -	if (error)
    -		goto error2;
    -	if (!XFS_SB_VERSION_HASATTR(&mp->m_sb) ||
    -	   (!XFS_SB_VERSION_HASATTR2(&mp->m_sb) && version == 2)) {
    -		__int64_t sbfields = 0;
    -
    -		s = XFS_SB_LOCK(mp);
    -		if (!XFS_SB_VERSION_HASATTR(&mp->m_sb)) {
    -			XFS_SB_VERSION_ADDATTR(&mp->m_sb);
    -			sbfields |= XFS_SB_VERSIONNUM;
    -		}
    -		if (!XFS_SB_VERSION_HASATTR2(&mp->m_sb) && version == 2) {
    -			XFS_SB_VERSION_ADDATTR2(&mp->m_sb);
    -			sbfields |= (XFS_SB_VERSIONNUM | XFS_SB_FEATURES2);
    -		}
    -		if (sbfields) {
    -			XFS_SB_UNLOCK(mp, s);
    -			xfs_mod_sb(tp, sbfields);
    -		} else
    -			XFS_SB_UNLOCK(mp, s);
    -	}
    -	if ((error = xfs_bmap_finish(&tp, &flist, firstblock, &committed)))
    -		goto error2;
    -	error = xfs_trans_commit(tp, XFS_TRANS_PERM_LOG_RES, NULL);
    -	ASSERT(ip->i_df.if_ext_max ==
    -	       XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t));
    -	return error;
    -error2:
    -	xfs_bmap_cancel(&flist);
    -error1:
    -	ASSERT(ismrlocked(&ip->i_lock,MR_UPDATE));
    -	xfs_iunlock(ip, XFS_ILOCK_EXCL);
    -error0:
    -	xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
    -	ASSERT(ip->i_df.if_ext_max ==
    -	       XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t));
    -	return error;
    -}
    -
    -/*
    - * Add the extent to the list of extents to be free at transaction end.
    - * The list is maintained sorted (by block number).
    - */
    -/* ARGSUSED */
    -void
    -xfs_bmap_add_free(
    -	xfs_fsblock_t		bno,		/* fs block number of extent */
    -	xfs_filblks_t		len,		/* length of extent */
    -	xfs_bmap_free_t		*flist,		/* list of extents */
    -	xfs_mount_t		*mp)		/* mount point structure */
    -{
    -	xfs_bmap_free_item_t	*cur;		/* current (next) element */
    -	xfs_bmap_free_item_t	*new;		/* new element */
    -	xfs_bmap_free_item_t	*prev;		/* previous element */
    -#ifdef DEBUG
    -	xfs_agnumber_t		agno;
    -	xfs_agblock_t		agbno;
    -
    -	ASSERT(bno != NULLFSBLOCK);
    -	ASSERT(len > 0);
    -	ASSERT(len <= MAXEXTLEN);
    -	ASSERT(!ISNULLSTARTBLOCK(bno));
    -	agno = XFS_FSB_TO_AGNO(mp, bno);
    -	agbno = XFS_FSB_TO_AGBNO(mp, bno);
    -	ASSERT(agno < mp->m_sb.sb_agcount);
    -	ASSERT(agbno < mp->m_sb.sb_agblocks);
    -	ASSERT(len < mp->m_sb.sb_agblocks);
    -	ASSERT(agbno + len <= mp->m_sb.sb_agblocks);
    -#endif
    -	ASSERT(xfs_bmap_free_item_zone != NULL);
    -	new = kmem_zone_alloc(xfs_bmap_free_item_zone, KM_SLEEP);
    -	new->xbfi_startblock = bno;
    -	new->xbfi_blockcount = (xfs_extlen_t)len;
    -	for (prev = NULL, cur = flist->xbf_first;
    -	     cur != NULL;
    -	     prev = cur, cur = cur->xbfi_next) {
    -		if (cur->xbfi_startblock >= bno)
    -			break;
    -	}
    -	if (prev)
    -		prev->xbfi_next = new;
    -	else
    -		flist->xbf_first = new;
    -	new->xbfi_next = cur;
    -	flist->xbf_count++;
    -}
    -
    -/*
    - * Compute and fill in the value of the maximum depth of a bmap btree
    - * in this filesystem.  Done once, during mount.
    - */
    -void
    -xfs_bmap_compute_maxlevels(
    -	xfs_mount_t	*mp,		/* file system mount structure */
    -	int		whichfork)	/* data or attr fork */
    -{
    -	int		level;		/* btree level */
    -	uint		maxblocks;	/* max blocks at this level */
    -	uint		maxleafents;	/* max leaf entries possible */
    -	int		maxrootrecs;	/* max records in root block */
    -	int		minleafrecs;	/* min records in leaf block */
    -	int		minnoderecs;	/* min records in node block */
    -	int		sz;		/* root block size */
    -
    -	/*
    -	 * The maximum number of extents in a file, hence the maximum
    -	 * number of leaf entries, is controlled by the type of di_nextents
    -	 * (a signed 32-bit number, xfs_extnum_t), or by di_anextents
    -	 * (a signed 16-bit number, xfs_aextnum_t).
    -	 */
    -	if (whichfork == XFS_DATA_FORK) {
    -		maxleafents = MAXEXTNUM;
    -		sz = (mp->m_flags & XFS_MOUNT_ATTR2) ?
    -			XFS_BMDR_SPACE_CALC(MINDBTPTRS) : mp->m_attroffset;
    -	} else {
    -		maxleafents = MAXAEXTNUM;
    -		sz = (mp->m_flags & XFS_MOUNT_ATTR2) ?
    -			XFS_BMDR_SPACE_CALC(MINABTPTRS) :
    -			mp->m_sb.sb_inodesize - mp->m_attroffset;
    -	}
    -	maxrootrecs = (int)XFS_BTREE_BLOCK_MAXRECS(sz, xfs_bmdr, 0);
    -	minleafrecs = mp->m_bmap_dmnr[0];
    -	minnoderecs = mp->m_bmap_dmnr[1];
    -	maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs;
    -	for (level = 1; maxblocks > 1; level++) {
    -		if (maxblocks <= maxrootrecs)
    -			maxblocks = 1;
    -		else
    -			maxblocks = (maxblocks + minnoderecs - 1) / minnoderecs;
    -	}
    -	mp->m_bm_maxlevels[whichfork] = level;
    -}
    -
    -/*
    - * Routine to be called at transaction's end by xfs_bmapi, xfs_bunmapi
    - * caller.  Frees all the extents that need freeing, which must be done
    - * last due to locking considerations.  We never free any extents in
    - * the first transaction.  This is to allow the caller to make the first
    - * transaction a synchronous one so that the pointers to the data being
    - * broken in this transaction will be permanent before the data is actually
    - * freed.  This is necessary to prevent blocks from being reallocated
    - * and written to before the free and reallocation are actually permanent.
    - * We do not just make the first transaction synchronous here, because
    - * there are more efficient ways to gain the same protection in some cases
    - * (see the file truncation code).
    - *
    - * Return 1 if the given transaction was committed and a new one
    - * started, and 0 otherwise in the committed parameter.
    - */
    -/*ARGSUSED*/
    -int						/* error */
    -xfs_bmap_finish(
    -	xfs_trans_t		**tp,		/* transaction pointer addr */
    -	xfs_bmap_free_t		*flist,		/* i/o: list extents to free */
    -	xfs_fsblock_t		firstblock,	/* controlled ag for allocs */
    -	int			*committed)	/* xact committed or not */
    -{
    -	xfs_efd_log_item_t	*efd;		/* extent free data */
    -	xfs_efi_log_item_t	*efi;		/* extent free intention */
    -	int			error;		/* error return value */
    -	xfs_bmap_free_item_t	*free;		/* free extent item */
    -	unsigned int		logres;		/* new log reservation */
    -	unsigned int		logcount;	/* new log count */
    -	xfs_mount_t		*mp;		/* filesystem mount structure */
    -	xfs_bmap_free_item_t	*next;		/* next item on free list */
    -	xfs_trans_t		*ntp;		/* new transaction pointer */
    -
    -	ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES);
    -	if (flist->xbf_count == 0) {
    -		*committed = 0;
    -		return 0;
    -	}
    -	ntp = *tp;
    -	efi = xfs_trans_get_efi(ntp, flist->xbf_count);
    -	for (free = flist->xbf_first; free; free = free->xbfi_next)
    -		xfs_trans_log_efi_extent(ntp, efi, free->xbfi_startblock,
    -			free->xbfi_blockcount);
    -	logres = ntp->t_log_res;
    -	logcount = ntp->t_log_count;
    -	ntp = xfs_trans_dup(*tp);
    -	error = xfs_trans_commit(*tp, 0, NULL);
    -	*tp = ntp;
    -	*committed = 1;
    -	/*
    -	 * We have a new transaction, so we should return committed=1,
    -	 * even though we're returning an error.
    -	 */
    -	if (error) {
    -		return error;
    -	}
    -	if ((error = xfs_trans_reserve(ntp, 0, logres, 0, XFS_TRANS_PERM_LOG_RES,
    -			logcount)))
    -		return error;
    -	efd = xfs_trans_get_efd(ntp, efi, flist->xbf_count);
    -	for (free = flist->xbf_first; free != NULL; free = next) {
    -		next = free->xbfi_next;
    -		if ((error = xfs_free_extent(ntp, free->xbfi_startblock,
    -				free->xbfi_blockcount))) {
    -			/*
    -			 * The bmap free list will be cleaned up at a
    -			 * higher level.  The EFI will be canceled when
    -			 * this transaction is aborted.
    -			 * Need to force shutdown here to make sure it
    -			 * happens, since this transaction may not be
    -			 * dirty yet.
    -			 */
    -			mp = ntp->t_mountp;
    -			if (!XFS_FORCED_SHUTDOWN(mp))
    -				xfs_force_shutdown(mp,
    -						   (error == EFSCORRUPTED) ?
    -						   XFS_CORRUPT_INCORE :
    -						   XFS_METADATA_IO_ERROR);
    -			return error;
    -		}
    -		xfs_trans_log_efd_extent(ntp, efd, free->xbfi_startblock,
    -			free->xbfi_blockcount);
    -		xfs_bmap_del_free(flist, NULL, free);
    -	}
    -	return 0;
    -}
    -
    -/*
    - * Free up any items left in the list.
    - */
    -void
    -xfs_bmap_cancel(
    -	xfs_bmap_free_t		*flist)	/* list of bmap_free_items */
    -{
    -	xfs_bmap_free_item_t	*free;	/* free list item */
    -	xfs_bmap_free_item_t	*next;
    -
    -	if (flist->xbf_count == 0)
    -		return;
    -	ASSERT(flist->xbf_first != NULL);
    -	for (free = flist->xbf_first; free; free = next) {
    -		next = free->xbfi_next;
    -		xfs_bmap_del_free(flist, NULL, free);
    -	}
    -	ASSERT(flist->xbf_count == 0);
    -}
    -
    -/*
    - * Returns the file-relative block number of the first unused block(s)
    - * in the file with at least "len" logically contiguous blocks free.
    - * This is the lowest-address hole if the file has holes, else the first block
    - * past the end of file.
    - * Return 0 if the file is currently local (in-inode).
    - */
    -int						/* error */
    -xfs_bmap_first_unused(
    -	xfs_trans_t	*tp,			/* transaction pointer */
    -	xfs_inode_t	*ip,			/* incore inode */
    -	xfs_extlen_t	len,			/* size of hole to find */
    -	xfs_fileoff_t	*first_unused,		/* unused block */
    -	int		whichfork)		/* data or attr fork */
    -{
    -	xfs_bmbt_rec_t	*ep;			/* pointer to an extent entry */
    -	int		error;			/* error return value */
    -	int		idx;			/* extent record index */
    -	xfs_ifork_t	*ifp;			/* inode fork pointer */
    -	xfs_fileoff_t	lastaddr;		/* last block number seen */
    -	xfs_fileoff_t	lowest;			/* lowest useful block */
    -	xfs_fileoff_t	max;			/* starting useful block */
    -	xfs_fileoff_t	off;			/* offset for this block */
    -	xfs_extnum_t	nextents;		/* number of extent entries */
    -
    -	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE ||
    -	       XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS ||
    -	       XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL);
    -	if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
    -		*first_unused = 0;
    -		return 0;
    -	}
    -	ifp = XFS_IFORK_PTR(ip, whichfork);
    -	if (!(ifp->if_flags & XFS_IFEXTENTS) &&
    -	    (error = xfs_iread_extents(tp, ip, whichfork)))
    -		return error;
    -	lowest = *first_unused;
    -	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
    -	for (idx = 0, lastaddr = 0, max = lowest; idx < nextents; idx++) {
    -		ep = xfs_iext_get_ext(ifp, idx);
    -		off = xfs_bmbt_get_startoff(ep);
    -		/*
    -		 * See if the hole before this extent will work.
    -		 */
    -		if (off >= lowest + len && off - max >= len) {
    -			*first_unused = max;
    -			return 0;
    -		}
    -		lastaddr = off + xfs_bmbt_get_blockcount(ep);
    -		max = XFS_FILEOFF_MAX(lastaddr, lowest);
    -	}
    -	*first_unused = max;
    -	return 0;
    -}
    -
    -/*
    - * Returns the file-relative block number of the last block + 1 before
    - * last_block (input value) in the file.
    - * This is not based on i_size, it is based on the extent records.
    - * Returns 0 for local files, as they do not have extent records.
    - */
    -int						/* error */
    -xfs_bmap_last_before(
    -	xfs_trans_t	*tp,			/* transaction pointer */
    -	xfs_inode_t	*ip,			/* incore inode */
    -	xfs_fileoff_t	*last_block,		/* last block */
    -	int		whichfork)		/* data or attr fork */
    -{
    -	xfs_fileoff_t	bno;			/* input file offset */
    -	int		eof;			/* hit end of file */
    -	xfs_bmbt_rec_t	*ep;			/* pointer to last extent */
    -	int		error;			/* error return value */
    -	xfs_bmbt_irec_t	got;			/* current extent value */
    -	xfs_ifork_t	*ifp;			/* inode fork pointer */
    -	xfs_extnum_t	lastx;			/* last extent used */
    -	xfs_bmbt_irec_t	prev;			/* previous extent value */
    -
    -	if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
    -	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
    -	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL)
    -	       return XFS_ERROR(EIO);
    -	if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
    -		*last_block = 0;
    -		return 0;
    -	}
    -	ifp = XFS_IFORK_PTR(ip, whichfork);
    -	if (!(ifp->if_flags & XFS_IFEXTENTS) &&
    -	    (error = xfs_iread_extents(tp, ip, whichfork)))
    -		return error;
    -	bno = *last_block - 1;
    -	ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got,
    -		&prev);
    -	if (eof || xfs_bmbt_get_startoff(ep) > bno) {
    -		if (prev.br_startoff == NULLFILEOFF)
    -			*last_block = 0;
    -		else
    -			*last_block = prev.br_startoff + prev.br_blockcount;
    -	}
    -	/*
    -	 * Otherwise *last_block is already the right answer.
    -	 */
    -	return 0;
    -}
    -
    -/*
    - * Returns the file-relative block number of the first block past eof in
    - * the file.  This is not based on i_size, it is based on the extent records.
    - * Returns 0 for local files, as they do not have extent records.
    - */
    -int						/* error */
    -xfs_bmap_last_offset(
    -	xfs_trans_t	*tp,			/* transaction pointer */
    -	xfs_inode_t	*ip,			/* incore inode */
    -	xfs_fileoff_t	*last_block,		/* last block */
    -	int		whichfork)		/* data or attr fork */
    -{
    -	xfs_bmbt_rec_t	*ep;			/* pointer to last extent */
    -	int		error;			/* error return value */
    -	xfs_ifork_t	*ifp;			/* inode fork pointer */
    -	xfs_extnum_t	nextents;		/* number of extent entries */
    -
    -	if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
    -	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
    -	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL)
    -	       return XFS_ERROR(EIO);
    -	if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
    -		*last_block = 0;
    -		return 0;
    -	}
    -	ifp = XFS_IFORK_PTR(ip, whichfork);
    -	if (!(ifp->if_flags & XFS_IFEXTENTS) &&
    -	    (error = xfs_iread_extents(tp, ip, whichfork)))
    -		return error;
    -	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
    -	if (!nextents) {
    -		*last_block = 0;
    -		return 0;
    -	}
    -	ep = xfs_iext_get_ext(ifp, nextents - 1);
    -	*last_block = xfs_bmbt_get_startoff(ep) + xfs_bmbt_get_blockcount(ep);
    -	return 0;
    -}
    -
    -/*
    - * Returns whether the selected fork of the inode has exactly one
    - * block or not.  For the data fork we check this matches di_size,
    - * implying the file's range is 0..bsize-1.
    - */
    -int					/* 1=>1 block, 0=>otherwise */
    -xfs_bmap_one_block(
    -	xfs_inode_t	*ip,		/* incore inode */
    -	int		whichfork)	/* data or attr fork */
    -{
    -	xfs_bmbt_rec_t	*ep;		/* ptr to fork's extent */
    -	xfs_ifork_t	*ifp;		/* inode fork pointer */
    -	int		rval;		/* return value */
    -	xfs_bmbt_irec_t	s;		/* internal version of extent */
    -
    -#ifndef DEBUG
    -	if (whichfork == XFS_DATA_FORK)
    -		return ip->i_d.di_size == ip->i_mount->m_sb.sb_blocksize;
    -#endif	/* !DEBUG */
    -	if (XFS_IFORK_NEXTENTS(ip, whichfork) != 1)
    -		return 0;
    -	if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
    -		return 0;
    -	ifp = XFS_IFORK_PTR(ip, whichfork);
    -	ASSERT(ifp->if_flags & XFS_IFEXTENTS);
    -	ep = xfs_iext_get_ext(ifp, 0);
    -	xfs_bmbt_get_all(ep, &s);
    -	rval = s.br_startoff == 0 && s.br_blockcount == 1;
    -	if (rval && whichfork == XFS_DATA_FORK)
    -		ASSERT(ip->i_d.di_size == ip->i_mount->m_sb.sb_blocksize);
    -	return rval;
    -}
    -
    -/*
    - * Read in the extents to if_extents.
    - * All inode fields are set up by caller, we just traverse the btree
    - * and copy the records in. If the file system cannot contain unwritten
    - * extents, the records are checked for no "state" flags.
    - */
    -int					/* error */
    -xfs_bmap_read_extents(
    -	xfs_trans_t		*tp,	/* transaction pointer */
    -	xfs_inode_t		*ip,	/* incore inode */
    -	int			whichfork) /* data or attr fork */
    -{
    -	xfs_bmbt_block_t	*block;	/* current btree block */
    -	xfs_fsblock_t		bno;	/* block # of "block" */
    -	xfs_buf_t		*bp;	/* buffer for "block" */
    -	int			error;	/* error return value */
    -	xfs_exntfmt_t		exntf;	/* XFS_EXTFMT_NOSTATE, if checking */
    -#ifdef XFS_BMAP_TRACE
    -	static char		fname[] = "xfs_bmap_read_extents";
    -#endif
    -	xfs_extnum_t		i, j;	/* index into the extents list */
    -	xfs_ifork_t		*ifp;	/* fork structure */
    -	int			level;	/* btree level, for checking */
    -	xfs_mount_t		*mp;	/* file system mount structure */
    -	xfs_bmbt_ptr_t		*pp;	/* pointer to block address */
    -	/* REFERENCED */
    -	xfs_extnum_t		room;	/* number of entries there's room for */
    -
    -	bno = NULLFSBLOCK;
    -	mp = ip->i_mount;
    -	ifp = XFS_IFORK_PTR(ip, whichfork);
    -	exntf = (whichfork != XFS_DATA_FORK) ? XFS_EXTFMT_NOSTATE :
    -					XFS_EXTFMT_INODE(ip);
    -	block = ifp->if_broot;
    -	/*
    -	 * Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out.
    -	 */
    -	level = be16_to_cpu(block->bb_level);
    -	ASSERT(level > 0);
    -	pp = XFS_BMAP_BROOT_PTR_ADDR(block, 1, ifp->if_broot_bytes);
    -	ASSERT(INT_GET(*pp, ARCH_CONVERT) != NULLDFSBNO);
    -	ASSERT(XFS_FSB_TO_AGNO(mp, INT_GET(*pp, ARCH_CONVERT)) < mp->m_sb.sb_agcount);
    -	ASSERT(XFS_FSB_TO_AGBNO(mp, INT_GET(*pp, ARCH_CONVERT)) < mp->m_sb.sb_agblocks);
    -	bno = INT_GET(*pp, ARCH_CONVERT);
    -	/*
    -	 * Go down the tree until leaf level is reached, following the first
    -	 * pointer (leftmost) at each level.
    -	 */
    -	while (level-- > 0) {
    -		if ((error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp,
    -				XFS_BMAP_BTREE_REF)))
    -			return error;
    -		block = XFS_BUF_TO_BMBT_BLOCK(bp);
    -		XFS_WANT_CORRUPTED_GOTO(
    -			XFS_BMAP_SANITY_CHECK(mp, block, level),
    -			error0);
    -		if (level == 0)
    -			break;
    -		pp = XFS_BTREE_PTR_ADDR(mp->m_sb.sb_blocksize, xfs_bmbt, block,
    -			1, mp->m_bmap_dmxr[1]);
    -		XFS_WANT_CORRUPTED_GOTO(
    -			XFS_FSB_SANITY_CHECK(mp, INT_GET(*pp, ARCH_CONVERT)),
    -			error0);
    -		bno = INT_GET(*pp, ARCH_CONVERT);
    -		xfs_trans_brelse(tp, bp);
    -	}
    -	/*
    -	 * Here with bp and block set to the leftmost leaf node in the tree.
    -	 */
    -	room = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
    -	i = 0;
    -	/*
    -	 * Loop over all leaf nodes.  Copy information to the extent records.
    -	 */
    -	for (;;) {
    -		xfs_bmbt_rec_t	*frp, *trp;
    -		xfs_fsblock_t	nextbno;
    -		xfs_extnum_t	num_recs;
    -		xfs_extnum_t	start;
    -
    -
    -		num_recs = be16_to_cpu(block->bb_numrecs);
    -		if (unlikely(i + num_recs > room)) {
    -			ASSERT(i + num_recs <= room);
    -			xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
    -				"corrupt dinode %Lu, (btree extents).",
    -				(unsigned long long) ip->i_ino);
    -			XFS_ERROR_REPORT("xfs_bmap_read_extents(1)",
    -					 XFS_ERRLEVEL_LOW,
    -					ip->i_mount);
    -			goto error0;
    -		}
    -		XFS_WANT_CORRUPTED_GOTO(
    -			XFS_BMAP_SANITY_CHECK(mp, block, 0),
    -			error0);
    -		/*
    -		 * Read-ahead the next leaf block, if any.
    -		 */
    -		nextbno = be64_to_cpu(block->bb_rightsib);
    -		if (nextbno != NULLFSBLOCK)
    -			xfs_btree_reada_bufl(mp, nextbno, 1);
    -		/*
    -		 * Copy records into the extent records.
    -		 */
    -		frp = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize, xfs_bmbt,
    -			block, 1, mp->m_bmap_dmxr[0]);
    -		start = i;
    -		for (j = 0; j < num_recs; j++, i++, frp++) {
    -			trp = xfs_iext_get_ext(ifp, i);
    -			trp->l0 = INT_GET(frp->l0, ARCH_CONVERT);
    -			trp->l1 = INT_GET(frp->l1, ARCH_CONVERT);
    -		}
    -		if (exntf == XFS_EXTFMT_NOSTATE) {
    -			/*
    -			 * Check all attribute bmap btree records and
    -			 * any "older" data bmap btree records for a
    -			 * set bit in the "extent flag" position.
    -			 */
    -			if (unlikely(xfs_check_nostate_extents(ifp,
    -					start, num_recs))) {
    -				XFS_ERROR_REPORT("xfs_bmap_read_extents(2)",
    -						 XFS_ERRLEVEL_LOW,
    -						 ip->i_mount);
    -				goto error0;
    -			}
    -		}
    -		xfs_trans_brelse(tp, bp);
    -		bno = nextbno;
    -		/*
    -		 * If we've reached the end, stop.
    -		 */
    -		if (bno == NULLFSBLOCK)
    -			break;
    -		if ((error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp,
    -				XFS_BMAP_BTREE_REF)))
    -			return error;
    -		block = XFS_BUF_TO_BMBT_BLOCK(bp);
    -	}
    -	ASSERT(i == (ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)));
    -	ASSERT(i == XFS_IFORK_NEXTENTS(ip, whichfork));
    -	xfs_bmap_trace_exlist(fname, ip, i, whichfork);
    -	return 0;
    -error0:
    -	xfs_trans_brelse(tp, bp);
    -	return XFS_ERROR(EFSCORRUPTED);
    -}
    -
    -#ifdef XFS_BMAP_TRACE
    -/*
    - * Add bmap trace insert entries for all the contents of the extent records.
    - */
    -void
    -xfs_bmap_trace_exlist(
    -	char		*fname,		/* function name */
    -	xfs_inode_t	*ip,		/* incore inode pointer */
    -	xfs_extnum_t	cnt,		/* count of entries in the list */
    -	int		whichfork)	/* data or attr fork */
    -{
    -	xfs_bmbt_rec_t	*ep;		/* current extent record */
    -	xfs_extnum_t	idx;		/* extent record index */
    -	xfs_ifork_t	*ifp;		/* inode fork pointer */
    -	xfs_bmbt_irec_t	s;		/* file extent record */
    -
    -	ifp = XFS_IFORK_PTR(ip, whichfork);
    -	ASSERT(cnt == (ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)));
    -	for (idx = 0; idx < cnt; idx++) {
    -		ep = xfs_iext_get_ext(ifp, idx);
    -		xfs_bmbt_get_all(ep, &s);
    -		xfs_bmap_trace_insert(fname, "exlist", ip, idx, 1, &s, NULL,
    -			whichfork);
    -	}
    -}
    -#endif
    -
    -#ifdef DEBUG
    -/*
    - * Validate that the bmbt_irecs being returned from bmapi are valid
    - * given the callers original parameters.  Specifically check the
    - * ranges of the returned irecs to ensure that they only extent beyond
    - * the given parameters if the XFS_BMAPI_ENTIRE flag was set.
    - */
    -STATIC void
    -xfs_bmap_validate_ret(
    -	xfs_fileoff_t		bno,
    -	xfs_filblks_t		len,
    -	int			flags,
    -	xfs_bmbt_irec_t		*mval,
    -	int			nmap,
    -	int			ret_nmap)
    -{
    -	int			i;		/* index to map values */
    -
    -	ASSERT(ret_nmap <= nmap);
    -
    -	for (i = 0; i < ret_nmap; i++) {
    -		ASSERT(mval[i].br_blockcount > 0);
    -		if (!(flags & XFS_BMAPI_ENTIRE)) {
    -			ASSERT(mval[i].br_startoff >= bno);
    -			ASSERT(mval[i].br_blockcount <= len);
    -			ASSERT(mval[i].br_startoff + mval[i].br_blockcount <=
    -			       bno + len);
    -		} else {
    -			ASSERT(mval[i].br_startoff < bno + len);
    -			ASSERT(mval[i].br_startoff + mval[i].br_blockcount >
    -			       bno);
    -		}
    -		ASSERT(i == 0 ||
    -		       mval[i - 1].br_startoff + mval[i - 1].br_blockcount ==
    -		       mval[i].br_startoff);
    -		if ((flags & XFS_BMAPI_WRITE) && !(flags & XFS_BMAPI_DELAY))
    -			ASSERT(mval[i].br_startblock != DELAYSTARTBLOCK &&
    -			       mval[i].br_startblock != HOLESTARTBLOCK);
    -		ASSERT(mval[i].br_state == XFS_EXT_NORM ||
    -		       mval[i].br_state == XFS_EXT_UNWRITTEN);
    -	}
    -}
    -#endif /* DEBUG */
    -
    -
    -/*
    - * Map file blocks to filesystem blocks.
    - * File range is given by the bno/len pair.
    - * Adds blocks to file if a write ("flags & XFS_BMAPI_WRITE" set)
    - * into a hole or past eof.
    - * Only allocates blocks from a single allocation group,
    - * to avoid locking problems.
    - * The returned value in "firstblock" from the first call in a transaction
    - * must be remembered and presented to subsequent calls in "firstblock".
    - * An upper bound for the number of blocks to be allocated is supplied to
    - * the first call in "total"; if no allocation group has that many free
    - * blocks then the call will fail (return NULLFSBLOCK in "firstblock").
    - */
    -int					/* error */
    -xfs_bmapi(
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_inode_t	*ip,		/* incore inode */
    -	xfs_fileoff_t	bno,		/* starting file offs. mapped */
    -	xfs_filblks_t	len,		/* length to map in file */
    -	int		flags,		/* XFS_BMAPI_... */
    -	xfs_fsblock_t	*firstblock,	/* first allocated block
    -					   controls a.g. for allocs */
    -	xfs_extlen_t	total,		/* total blocks needed */
    -	xfs_bmbt_irec_t	*mval,		/* output: map values */
    -	int		*nmap,		/* i/o: mval size/count */
    -	xfs_bmap_free_t	*flist,		/* i/o: list extents to free */
    -	xfs_extdelta_t	*delta)		/* o: change made to incore extents */
    -{
    -	xfs_fsblock_t	abno;		/* allocated block number */
    -	xfs_extlen_t	alen;		/* allocated extent length */
    -	xfs_fileoff_t	aoff;		/* allocated file offset */
    -	xfs_bmalloca_t	bma;		/* args for xfs_bmap_alloc */
    -	xfs_btree_cur_t	*cur;		/* bmap btree cursor */
    -	xfs_fileoff_t	end;		/* end of mapped file region */
    -	int		eof;		/* we've hit the end of extents */
    -	xfs_bmbt_rec_t	*ep;		/* extent record pointer */
    -	int		error;		/* error return */
    -	xfs_bmbt_irec_t	got;		/* current file extent record */
    -	xfs_ifork_t	*ifp;		/* inode fork pointer */
    -	xfs_extlen_t	indlen;		/* indirect blocks length */
    -	xfs_extnum_t	lastx;		/* last useful extent number */
    -	int		logflags;	/* flags for transaction logging */
    -	xfs_extlen_t	minleft;	/* min blocks left after allocation */
    -	xfs_extlen_t	minlen;		/* min allocation size */
    -	xfs_mount_t	*mp;		/* xfs mount structure */
    -	int		n;		/* current extent index */
    -	int		nallocs;	/* number of extents alloc\'d */
    -	xfs_extnum_t	nextents;	/* number of extents in file */
    -	xfs_fileoff_t	obno;		/* old block number (offset) */
    -	xfs_bmbt_irec_t	prev;		/* previous file extent record */
    -	int		tmp_logflags;	/* temp flags holder */
    -	int		whichfork;	/* data or attr fork */
    -	char		inhole;		/* current location is hole in file */
    -	char		wasdelay;	/* old extent was delayed */
    -	char		wr;		/* this is a write request */
    -	char		rt;		/* this is a realtime file */
    -#ifdef DEBUG
    -	xfs_fileoff_t	orig_bno;	/* original block number value */
    -	int		orig_flags;	/* original flags arg value */
    -	xfs_filblks_t	orig_len;	/* original value of len arg */
    -	xfs_bmbt_irec_t	*orig_mval;	/* original value of mval */
    -	int		orig_nmap;	/* original value of *nmap */
    -
    -	orig_bno = bno;
    -	orig_len = len;
    -	orig_flags = flags;
    -	orig_mval = mval;
    -	orig_nmap = *nmap;
    -#endif
    -	ASSERT(*nmap >= 1);
    -	ASSERT(*nmap <= XFS_BMAP_MAX_NMAP || !(flags & XFS_BMAPI_WRITE));
    -	whichfork = (flags & XFS_BMAPI_ATTRFORK) ?
    -		XFS_ATTR_FORK : XFS_DATA_FORK;
    -	mp = ip->i_mount;
    -	if (unlikely(XFS_TEST_ERROR(
    -	    (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
    -	     XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
    -	     XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL),
    -	     mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) {
    -		XFS_ERROR_REPORT("xfs_bmapi", XFS_ERRLEVEL_LOW, mp);
    -		return XFS_ERROR(EFSCORRUPTED);
    -	}
    -	if (XFS_FORCED_SHUTDOWN(mp))
    -		return XFS_ERROR(EIO);
    -	rt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip);
    -	ifp = XFS_IFORK_PTR(ip, whichfork);
    -	ASSERT(ifp->if_ext_max ==
    -	       XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
    -	if ((wr = (flags & XFS_BMAPI_WRITE)) != 0)
    -		XFS_STATS_INC(xs_blk_mapw);
    -	else
    -		XFS_STATS_INC(xs_blk_mapr);
    -	/*
    -	 * IGSTATE flag is used to combine extents which
    -	 * differ only due to the state of the extents.
    -	 * This technique is used from xfs_getbmap()
    -	 * when the caller does not wish to see the
    -	 * separation (which is the default).
    -	 *
    -	 * This technique is also used when writing a
    -	 * buffer which has been partially written,
    -	 * (usually by being flushed during a chunkread),
    -	 * to ensure one write takes place. This also
    -	 * prevents a change in the xfs inode extents at
    -	 * this time, intentionally. This change occurs
    -	 * on completion of the write operation, in
    -	 * xfs_strat_comp(), where the xfs_bmapi() call
    -	 * is transactioned, and the extents combined.
    -	 */
    -	if ((flags & XFS_BMAPI_IGSTATE) && wr)	/* if writing unwritten space */
    -		wr = 0;				/* no allocations are allowed */
    -	ASSERT(wr || !(flags & XFS_BMAPI_DELAY));
    -	logflags = 0;
    -	nallocs = 0;
    -	cur = NULL;
    -	if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
    -		ASSERT(wr && tp);
    -		if ((error = xfs_bmap_local_to_extents(tp, ip,
    -				firstblock, total, &logflags, whichfork)))
    -			goto error0;
    -	}
    -	if (wr && *firstblock == NULLFSBLOCK) {
    -		if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE)
    -			minleft = be16_to_cpu(ifp->if_broot->bb_level) + 1;
    -		else
    -			minleft = 1;
    -	} else
    -		minleft = 0;
    -	if (!(ifp->if_flags & XFS_IFEXTENTS) &&
    -	    (error = xfs_iread_extents(tp, ip, whichfork)))
    -		goto error0;
    -	ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got,
    -		&prev);
    -	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
    -	n = 0;
    -	end = bno + len;
    -	obno = bno;
    -	bma.ip = NULL;
    -	if (delta) {
    -		delta->xed_startoff = NULLFILEOFF;
    -		delta->xed_blockcount = 0;
    -	}
    -	while (bno < end && n < *nmap) {
    -		/*
    -		 * Reading past eof, act as though there's a hole
    -		 * up to end.
    -		 */
    -		if (eof && !wr)
    -			got.br_startoff = end;
    -		inhole = eof || got.br_startoff > bno;
    -		wasdelay = wr && !inhole && !(flags & XFS_BMAPI_DELAY) &&
    -			ISNULLSTARTBLOCK(got.br_startblock);
    -		/*
    -		 * First, deal with the hole before the allocated space
    -		 * that we found, if any.
    -		 */
    -		if (wr && (inhole || wasdelay)) {
    -			/*
    -			 * For the wasdelay case, we could also just
    -			 * allocate the stuff asked for in this bmap call
    -			 * but that wouldn't be as good.
    -			 */
    -			if (wasdelay && !(flags & XFS_BMAPI_EXACT)) {
    -				alen = (xfs_extlen_t)got.br_blockcount;
    -				aoff = got.br_startoff;
    -				if (lastx != NULLEXTNUM && lastx) {
    -					ep = xfs_iext_get_ext(ifp, lastx - 1);
    -					xfs_bmbt_get_all(ep, &prev);
    -				}
    -			} else if (wasdelay) {
    -				alen = (xfs_extlen_t)
    -					XFS_FILBLKS_MIN(len,
    -						(got.br_startoff +
    -						 got.br_blockcount) - bno);
    -				aoff = bno;
    -			} else {
    -				alen = (xfs_extlen_t)
    -					XFS_FILBLKS_MIN(len, MAXEXTLEN);
    -				if (!eof)
    -					alen = (xfs_extlen_t)
    -						XFS_FILBLKS_MIN(alen,
    -							got.br_startoff - bno);
    -				aoff = bno;
    -			}
    -			minlen = (flags & XFS_BMAPI_CONTIG) ? alen : 1;
    -			if (flags & XFS_BMAPI_DELAY) {
    -				xfs_extlen_t	extsz;
    -
    -				/* Figure out the extent size, adjust alen */
    -				if (rt) {
    -					if (!(extsz = ip->i_d.di_extsize))
    -						extsz = mp->m_sb.sb_rextsize;
    -				} else {
    -					extsz = ip->i_d.di_extsize;
    -				}
    -				if (extsz) {
    -					error = xfs_bmap_extsize_align(mp,
    -							&got, &prev, extsz,
    -							rt, eof,
    -							flags&XFS_BMAPI_DELAY,
    -							flags&XFS_BMAPI_CONVERT,
    -							&aoff, &alen);
    -					ASSERT(!error);
    -				}
    -
    -				if (rt)
    -					extsz = alen / mp->m_sb.sb_rextsize;
    -
    -				/*
    -				 * Make a transaction-less quota reservation for
    -				 * delayed allocation blocks. This number gets
    -				 * adjusted later.  We return if we haven't
    -				 * allocated blocks already inside this loop.
    -				 */
    -				if ((error = XFS_TRANS_RESERVE_QUOTA_NBLKS(
    -						mp, NULL, ip, (long)alen, 0,
    -						rt ? XFS_QMOPT_RES_RTBLKS :
    -						     XFS_QMOPT_RES_REGBLKS))) {
    -					if (n == 0) {
    -						*nmap = 0;
    -						ASSERT(cur == NULL);
    -						return error;
    -					}
    -					break;
    -				}
    -
    -				/*
    -				 * Split changing sb for alen and indlen since
    -				 * they could be coming from different places.
    -				 */
    -				indlen = (xfs_extlen_t)
    -					xfs_bmap_worst_indlen(ip, alen);
    -				ASSERT(indlen > 0);
    -
    -				if (rt) {
    -					error = xfs_mod_incore_sb(mp,
    -							XFS_SBS_FREXTENTS,
    -							-(extsz), (flags &
    -							XFS_BMAPI_RSVBLOCKS));
    -				} else {
    -					error = xfs_mod_incore_sb(mp,
    -							XFS_SBS_FDBLOCKS,
    -							-(alen), (flags &
    -							XFS_BMAPI_RSVBLOCKS));
    -				}
    -				if (!error) {
    -					error = xfs_mod_incore_sb(mp,
    -							XFS_SBS_FDBLOCKS,
    -							-(indlen), (flags &
    -							XFS_BMAPI_RSVBLOCKS));
    -					if (error && rt)
    -						xfs_mod_incore_sb(mp,
    -							XFS_SBS_FREXTENTS,
    -							extsz, (flags &
    -							XFS_BMAPI_RSVBLOCKS));
    -					else if (error)
    -						xfs_mod_incore_sb(mp,
    -							XFS_SBS_FDBLOCKS,
    -							alen, (flags &
    -							XFS_BMAPI_RSVBLOCKS));
    -				}
    -
    -				if (error) {
    -					if (XFS_IS_QUOTA_ON(mp))
    -						/* unreserve the blocks now */
    -						(void)
    -						XFS_TRANS_UNRESERVE_QUOTA_NBLKS(
    -							mp, NULL, ip,
    -							(long)alen, 0, rt ?
    -							XFS_QMOPT_RES_RTBLKS :
    -							XFS_QMOPT_RES_REGBLKS);
    -					break;
    -				}
    -
    -				ip->i_delayed_blks += alen;
    -				abno = NULLSTARTBLOCK(indlen);
    -			} else {
    -				/*
    -				 * If first time, allocate and fill in
    -				 * once-only bma fields.
    -				 */
    -				if (bma.ip == NULL) {
    -					bma.tp = tp;
    -					bma.ip = ip;
    -					bma.prevp = &prev;
    -					bma.gotp = &got;
    -					bma.total = total;
    -					bma.userdata = 0;
    -				}
    -				/* Indicate if this is the first user data
    -				 * in the file, or just any user data.
    -				 */
    -				if (!(flags & XFS_BMAPI_METADATA)) {
    -					bma.userdata = (aoff == 0) ?
    -						XFS_ALLOC_INITIAL_USER_DATA :
    -						XFS_ALLOC_USERDATA;
    -				}
    -				/*
    -				 * Fill in changeable bma fields.
    -				 */
    -				bma.eof = eof;
    -				bma.firstblock = *firstblock;
    -				bma.alen = alen;
    -				bma.off = aoff;
    -				bma.conv = (flags & XFS_BMAPI_CONVERT) != 0;
    -				bma.wasdel = wasdelay;
    -				bma.minlen = minlen;
    -				bma.low = flist->xbf_low;
    -				bma.minleft = minleft;
    -				/*
    -				 * Only want to do the alignment at the
    -				 * eof if it is userdata and allocation length
    -				 * is larger than a stripe unit.
    -				 */
    -				if (mp->m_dalign && alen >= mp->m_dalign &&
    -				    (!(flags & XFS_BMAPI_METADATA)) &&
    -				    (whichfork == XFS_DATA_FORK)) {
    -					if ((error = xfs_bmap_isaeof(ip, aoff,
    -							whichfork, &bma.aeof)))
    -						goto error0;
    -				} else
    -					bma.aeof = 0;
    -				/*
    -				 * Call allocator.
    -				 */
    -				if ((error = xfs_bmap_alloc(&bma)))
    -					goto error0;
    -				/*
    -				 * Copy out result fields.
    -				 */
    -				abno = bma.rval;
    -				if ((flist->xbf_low = bma.low))
    -					minleft = 0;
    -				alen = bma.alen;
    -				aoff = bma.off;
    -				ASSERT(*firstblock == NULLFSBLOCK ||
    -				       XFS_FSB_TO_AGNO(mp, *firstblock) ==
    -				       XFS_FSB_TO_AGNO(mp, bma.firstblock) ||
    -				       (flist->xbf_low &&
    -					XFS_FSB_TO_AGNO(mp, *firstblock) <
    -					XFS_FSB_TO_AGNO(mp, bma.firstblock)));
    -				*firstblock = bma.firstblock;
    -				if (cur)
    -					cur->bc_private.b.firstblock =
    -						*firstblock;
    -				if (abno == NULLFSBLOCK)
    -					break;
    -				if ((ifp->if_flags & XFS_IFBROOT) && !cur) {
    -					cur = xfs_btree_init_cursor(mp,
    -						tp, NULL, 0, XFS_BTNUM_BMAP,
    -						ip, whichfork);
    -					cur->bc_private.b.firstblock =
    -						*firstblock;
    -					cur->bc_private.b.flist = flist;
    -				}
    -				/*
    -				 * Bump the number of extents we've allocated
    -				 * in this call.
    -				 */
    -				nallocs++;
    -			}
    -			if (cur)
    -				cur->bc_private.b.flags =
    -					wasdelay ? XFS_BTCUR_BPRV_WASDEL : 0;
    -			got.br_startoff = aoff;
    -			got.br_startblock = abno;
    -			got.br_blockcount = alen;
    -			got.br_state = XFS_EXT_NORM;	/* assume normal */
    -			/*
    -			 * Determine state of extent, and the filesystem.
    -			 * A wasdelay extent has been initialized, so
    -			 * shouldn't be flagged as unwritten.
    -			 */
    -			if (wr && XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb)) {
    -				if (!wasdelay && (flags & XFS_BMAPI_PREALLOC))
    -					got.br_state = XFS_EXT_UNWRITTEN;
    -			}
    -			error = xfs_bmap_add_extent(ip, lastx, &cur, &got,
    -				firstblock, flist, &tmp_logflags, delta,
    -				whichfork, (flags & XFS_BMAPI_RSVBLOCKS));
    -			logflags |= tmp_logflags;
    -			if (error)
    -				goto error0;
    -			lastx = ifp->if_lastex;
    -			ep = xfs_iext_get_ext(ifp, lastx);
    -			nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
    -			xfs_bmbt_get_all(ep, &got);
    -			ASSERT(got.br_startoff <= aoff);
    -			ASSERT(got.br_startoff + got.br_blockcount >=
    -				aoff + alen);
    -#ifdef DEBUG
    -			if (flags & XFS_BMAPI_DELAY) {
    -				ASSERT(ISNULLSTARTBLOCK(got.br_startblock));
    -				ASSERT(STARTBLOCKVAL(got.br_startblock) > 0);
    -			}
    -			ASSERT(got.br_state == XFS_EXT_NORM ||
    -			       got.br_state == XFS_EXT_UNWRITTEN);
    -#endif
    -			/*
    -			 * Fall down into the found allocated space case.
    -			 */
    -		} else if (inhole) {
    -			/*
    -			 * Reading in a hole.
    -			 */
    -			mval->br_startoff = bno;
    -			mval->br_startblock = HOLESTARTBLOCK;
    -			mval->br_blockcount =
    -				XFS_FILBLKS_MIN(len, got.br_startoff - bno);
    -			mval->br_state = XFS_EXT_NORM;
    -			bno += mval->br_blockcount;
    -			len -= mval->br_blockcount;
    -			mval++;
    -			n++;
    -			continue;
    -		}
    -		/*
    -		 * Then deal with the allocated space we found.
    -		 */
    -		ASSERT(ep != NULL);
    -		if (!(flags & XFS_BMAPI_ENTIRE) &&
    -		    (got.br_startoff + got.br_blockcount > obno)) {
    -			if (obno > bno)
    -				bno = obno;
    -			ASSERT((bno >= obno) || (n == 0));
    -			ASSERT(bno < end);
    -			mval->br_startoff = bno;
    -			if (ISNULLSTARTBLOCK(got.br_startblock)) {
    -				ASSERT(!wr || (flags & XFS_BMAPI_DELAY));
    -				mval->br_startblock = DELAYSTARTBLOCK;
    -			} else
    -				mval->br_startblock =
    -					got.br_startblock +
    -					(bno - got.br_startoff);
    -			/*
    -			 * Return the minimum of what we got and what we
    -			 * asked for for the length.  We can use the len
    -			 * variable here because it is modified below
    -			 * and we could have been there before coming
    -			 * here if the first part of the allocation
    -			 * didn't overlap what was asked for.
    -			 */
    -			mval->br_blockcount =
    -				XFS_FILBLKS_MIN(end - bno, got.br_blockcount -
    -					(bno - got.br_startoff));
    -			mval->br_state = got.br_state;
    -			ASSERT(mval->br_blockcount <= len);
    -		} else {
    -			*mval = got;
    -			if (ISNULLSTARTBLOCK(mval->br_startblock)) {
    -				ASSERT(!wr || (flags & XFS_BMAPI_DELAY));
    -				mval->br_startblock = DELAYSTARTBLOCK;
    -			}
    -		}
    -
    -		/*
    -		 * Check if writing previously allocated but
    -		 * unwritten extents.
    -		 */
    -		if (wr && mval->br_state == XFS_EXT_UNWRITTEN &&
    -		    ((flags & (XFS_BMAPI_PREALLOC|XFS_BMAPI_DELAY)) == 0)) {
    -			/*
    -			 * Modify (by adding) the state flag, if writing.
    -			 */
    -			ASSERT(mval->br_blockcount <= len);
    -			if ((ifp->if_flags & XFS_IFBROOT) && !cur) {
    -				cur = xfs_btree_init_cursor(mp,
    -					tp, NULL, 0, XFS_BTNUM_BMAP,
    -					ip, whichfork);
    -				cur->bc_private.b.firstblock =
    -					*firstblock;
    -				cur->bc_private.b.flist = flist;
    -			}
    -			mval->br_state = XFS_EXT_NORM;
    -			error = xfs_bmap_add_extent(ip, lastx, &cur, mval,
    -				firstblock, flist, &tmp_logflags, delta,
    -				whichfork, (flags & XFS_BMAPI_RSVBLOCKS));
    -			logflags |= tmp_logflags;
    -			if (error)
    -				goto error0;
    -			lastx = ifp->if_lastex;
    -			ep = xfs_iext_get_ext(ifp, lastx);
    -			nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
    -			xfs_bmbt_get_all(ep, &got);
    -			/*
    -			 * We may have combined previously unwritten
    -			 * space with written space, so generate
    -			 * another request.
    -			 */
    -			if (mval->br_blockcount < len)
    -				continue;
    -		}
    -
    -		ASSERT((flags & XFS_BMAPI_ENTIRE) ||
    -		       ((mval->br_startoff + mval->br_blockcount) <= end));
    -		ASSERT((flags & XFS_BMAPI_ENTIRE) ||
    -		       (mval->br_blockcount <= len) ||
    -		       (mval->br_startoff < obno));
    -		bno = mval->br_startoff + mval->br_blockcount;
    -		len = end - bno;
    -		if (n > 0 && mval->br_startoff == mval[-1].br_startoff) {
    -			ASSERT(mval->br_startblock == mval[-1].br_startblock);
    -			ASSERT(mval->br_blockcount > mval[-1].br_blockcount);
    -			ASSERT(mval->br_state == mval[-1].br_state);
    -			mval[-1].br_blockcount = mval->br_blockcount;
    -			mval[-1].br_state = mval->br_state;
    -		} else if (n > 0 && mval->br_startblock != DELAYSTARTBLOCK &&
    -			   mval[-1].br_startblock != DELAYSTARTBLOCK &&
    -			   mval[-1].br_startblock != HOLESTARTBLOCK &&
    -			   mval->br_startblock ==
    -			   mval[-1].br_startblock + mval[-1].br_blockcount &&
    -			   ((flags & XFS_BMAPI_IGSTATE) ||
    -				mval[-1].br_state == mval->br_state)) {
    -			ASSERT(mval->br_startoff ==
    -			       mval[-1].br_startoff + mval[-1].br_blockcount);
    -			mval[-1].br_blockcount += mval->br_blockcount;
    -		} else if (n > 0 &&
    -			   mval->br_startblock == DELAYSTARTBLOCK &&
    -			   mval[-1].br_startblock == DELAYSTARTBLOCK &&
    -			   mval->br_startoff ==
    -			   mval[-1].br_startoff + mval[-1].br_blockcount) {
    -			mval[-1].br_blockcount += mval->br_blockcount;
    -			mval[-1].br_state = mval->br_state;
    -		} else if (!((n == 0) &&
    -			     ((mval->br_startoff + mval->br_blockcount) <=
    -			      obno))) {
    -			mval++;
    -			n++;
    -		}
    -		/*
    -		 * If we're done, stop now.  Stop when we've allocated
    -		 * XFS_BMAP_MAX_NMAP extents no matter what.  Otherwise
    -		 * the transaction may get too big.
    -		 */
    -		if (bno >= end || n >= *nmap || nallocs >= *nmap)
    -			break;
    -		/*
    -		 * Else go on to the next record.
    -		 */
    -		ep = xfs_iext_get_ext(ifp, ++lastx);
    -		if (lastx >= nextents) {
    -			eof = 1;
    -			prev = got;
    -		} else
    -			xfs_bmbt_get_all(ep, &got);
    -	}
    -	ifp->if_lastex = lastx;
    -	*nmap = n;
    -	/*
    -	 * Transform from btree to extents, give it cur.
    -	 */
    -	if (tp && XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE &&
    -	    XFS_IFORK_NEXTENTS(ip, whichfork) <= ifp->if_ext_max) {
    -		ASSERT(wr && cur);
    -		error = xfs_bmap_btree_to_extents(tp, ip, cur,
    -			&tmp_logflags, whichfork);
    -		logflags |= tmp_logflags;
    -		if (error)
    -			goto error0;
    -	}
    -	ASSERT(ifp->if_ext_max ==
    -	       XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
    -	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE ||
    -	       XFS_IFORK_NEXTENTS(ip, whichfork) > ifp->if_ext_max);
    -	error = 0;
    -	if (delta && delta->xed_startoff != NULLFILEOFF) {
    -		/* A change was actually made.
    -		 * Note that delta->xed_blockount is an offset at this
    -		 * point and needs to be converted to a block count.
    -		 */
    -		ASSERT(delta->xed_blockcount > delta->xed_startoff);
    -		delta->xed_blockcount -= delta->xed_startoff;
    -	}
    -error0:
    -	/*
    -	 * Log everything.  Do this after conversion, there's no point in
    -	 * logging the extent records if we've converted to btree format.
    -	 */
    -	if ((logflags & XFS_ILOG_FEXT(whichfork)) &&
    -	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
    -		logflags &= ~XFS_ILOG_FEXT(whichfork);
    -	else if ((logflags & XFS_ILOG_FBROOT(whichfork)) &&
    -		 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)
    -		logflags &= ~XFS_ILOG_FBROOT(whichfork);
    -	/*
    -	 * Log whatever the flags say, even if error.  Otherwise we might miss
    -	 * detecting a case where the data is changed, there's an error,
    -	 * and it's not logged so we don't shutdown when we should.
    -	 */
    -	if (logflags) {
    -		ASSERT(tp && wr);
    -		xfs_trans_log_inode(tp, ip, logflags);
    -	}
    -	if (cur) {
    -		if (!error) {
    -			ASSERT(*firstblock == NULLFSBLOCK ||
    -			       XFS_FSB_TO_AGNO(mp, *firstblock) ==
    -			       XFS_FSB_TO_AGNO(mp,
    -				       cur->bc_private.b.firstblock) ||
    -			       (flist->xbf_low &&
    -				XFS_FSB_TO_AGNO(mp, *firstblock) <
    -				XFS_FSB_TO_AGNO(mp,
    -					cur->bc_private.b.firstblock)));
    -			*firstblock = cur->bc_private.b.firstblock;
    -		}
    -		xfs_btree_del_cursor(cur,
    -			error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
    -	}
    -	if (!error)
    -		xfs_bmap_validate_ret(orig_bno, orig_len, orig_flags, orig_mval,
    -			orig_nmap, *nmap);
    -	return error;
    -}
    -
    -/*
    - * Map file blocks to filesystem blocks, simple version.
    - * One block (extent) only, read-only.
    - * For flags, only the XFS_BMAPI_ATTRFORK flag is examined.
    - * For the other flag values, the effect is as if XFS_BMAPI_METADATA
    - * was set and all the others were clear.
    - */
    -int						/* error */
    -xfs_bmapi_single(
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_inode_t	*ip,		/* incore inode */
    -	int		whichfork,	/* data or attr fork */
    -	xfs_fsblock_t	*fsb,		/* output: mapped block */
    -	xfs_fileoff_t	bno)		/* starting file offs. mapped */
    -{
    -	int		eof;		/* we've hit the end of extents */
    -	int		error;		/* error return */
    -	xfs_bmbt_irec_t	got;		/* current file extent record */
    -	xfs_ifork_t	*ifp;		/* inode fork pointer */
    -	xfs_extnum_t	lastx;		/* last useful extent number */
    -	xfs_bmbt_irec_t	prev;		/* previous file extent record */
    -
    -	ifp = XFS_IFORK_PTR(ip, whichfork);
    -	if (unlikely(
    -	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
    -	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)) {
    -	       XFS_ERROR_REPORT("xfs_bmapi_single", XFS_ERRLEVEL_LOW,
    -				ip->i_mount);
    -	       return XFS_ERROR(EFSCORRUPTED);
    -	}
    -	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
    -		return XFS_ERROR(EIO);
    -	XFS_STATS_INC(xs_blk_mapr);
    -	if (!(ifp->if_flags & XFS_IFEXTENTS) &&
    -	    (error = xfs_iread_extents(tp, ip, whichfork)))
    -		return error;
    -	(void)xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got,
    -		&prev);
    -	/*
    -	 * Reading past eof, act as though there's a hole
    -	 * up to end.
    -	 */
    -	if (eof || got.br_startoff > bno) {
    -		*fsb = NULLFSBLOCK;
    -		return 0;
    -	}
    -	ASSERT(!ISNULLSTARTBLOCK(got.br_startblock));
    -	ASSERT(bno < got.br_startoff + got.br_blockcount);
    -	*fsb = got.br_startblock + (bno - got.br_startoff);
    -	ifp->if_lastex = lastx;
    -	return 0;
    -}
    -
    -/*
    - * Unmap (remove) blocks from a file.
    - * If nexts is nonzero then the number of extents to remove is limited to
    - * that value.  If not all extents in the block range can be removed then
    - * *done is set.
    - */
    -int						/* error */
    -xfs_bunmapi(
    -	xfs_trans_t		*tp,		/* transaction pointer */
    -	struct xfs_inode	*ip,		/* incore inode */
    -	xfs_fileoff_t		bno,		/* starting offset to unmap */
    -	xfs_filblks_t		len,		/* length to unmap in file */
    -	int			flags,		/* misc flags */
    -	xfs_extnum_t		nexts,		/* number of extents max */
    -	xfs_fsblock_t		*firstblock,	/* first allocated block
    -						   controls a.g. for allocs */
    -	xfs_bmap_free_t		*flist,		/* i/o: list extents to free */
    -	xfs_extdelta_t		*delta,		/* o: change made to incore
    -						   extents */
    -	int			*done)		/* set if not done yet */
    -{
    -	xfs_btree_cur_t		*cur;		/* bmap btree cursor */
    -	xfs_bmbt_irec_t		del;		/* extent being deleted */
    -	int			eof;		/* is deleting at eof */
    -	xfs_bmbt_rec_t		*ep;		/* extent record pointer */
    -	int			error;		/* error return value */
    -	xfs_extnum_t		extno;		/* extent number in list */
    -	xfs_bmbt_irec_t		got;		/* current extent record */
    -	xfs_ifork_t		*ifp;		/* inode fork pointer */
    -	int			isrt;		/* freeing in rt area */
    -	xfs_extnum_t		lastx;		/* last extent index used */
    -	int			logflags;	/* transaction logging flags */
    -	xfs_extlen_t		mod;		/* rt extent offset */
    -	xfs_mount_t		*mp;		/* mount structure */
    -	xfs_extnum_t		nextents;	/* number of file extents */
    -	xfs_bmbt_irec_t		prev;		/* previous extent record */
    -	xfs_fileoff_t		start;		/* first file offset deleted */
    -	int			tmp_logflags;	/* partial logging flags */
    -	int			wasdel;		/* was a delayed alloc extent */
    -	int			whichfork;	/* data or attribute fork */
    -	int			rsvd;		/* OK to allocate reserved blocks */
    -	xfs_fsblock_t		sum;
    -
    -	xfs_bunmap_trace(ip, bno, len, flags, (inst_t *)__return_address);
    -	whichfork = (flags & XFS_BMAPI_ATTRFORK) ?
    -		XFS_ATTR_FORK : XFS_DATA_FORK;
    -	ifp = XFS_IFORK_PTR(ip, whichfork);
    -	if (unlikely(
    -	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
    -	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)) {
    -		XFS_ERROR_REPORT("xfs_bunmapi", XFS_ERRLEVEL_LOW,
    -				 ip->i_mount);
    -		return XFS_ERROR(EFSCORRUPTED);
    -	}
    -	mp = ip->i_mount;
    -	if (XFS_FORCED_SHUTDOWN(mp))
    -		return XFS_ERROR(EIO);
    -	rsvd = (flags & XFS_BMAPI_RSVBLOCKS) != 0;
    -	ASSERT(len > 0);
    -	ASSERT(nexts >= 0);
    -	ASSERT(ifp->if_ext_max ==
    -	       XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
    -	if (!(ifp->if_flags & XFS_IFEXTENTS) &&
    -	    (error = xfs_iread_extents(tp, ip, whichfork)))
    -		return error;
    -	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
    -	if (nextents == 0) {
    -		*done = 1;
    -		return 0;
    -	}
    -	XFS_STATS_INC(xs_blk_unmap);
    -	isrt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip);
    -	start = bno;
    -	bno = start + len - 1;
    -	ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got,
    -		&prev);
    -	if (delta) {
    -		delta->xed_startoff = NULLFILEOFF;
    -		delta->xed_blockcount = 0;
    -	}
    -	/*
    -	 * Check to see if the given block number is past the end of the
    -	 * file, back up to the last block if so...
    -	 */
    -	if (eof) {
    -		ep = xfs_iext_get_ext(ifp, --lastx);
    -		xfs_bmbt_get_all(ep, &got);
    -		bno = got.br_startoff + got.br_blockcount - 1;
    -	}
    -	logflags = 0;
    -	if (ifp->if_flags & XFS_IFBROOT) {
    -		ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE);
    -		cur = xfs_btree_init_cursor(mp, tp, NULL, 0, XFS_BTNUM_BMAP, ip,
    -			whichfork);
    -		cur->bc_private.b.firstblock = *firstblock;
    -		cur->bc_private.b.flist = flist;
    -		cur->bc_private.b.flags = 0;
    -	} else
    -		cur = NULL;
    -	extno = 0;
    -	while (bno != (xfs_fileoff_t)-1 && bno >= start && lastx >= 0 &&
    -	       (nexts == 0 || extno < nexts)) {
    -		/*
    -		 * Is the found extent after a hole in which bno lives?
    -		 * Just back up to the previous extent, if so.
    -		 */
    -		if (got.br_startoff > bno) {
    -			if (--lastx < 0)
    -				break;
    -			ep = xfs_iext_get_ext(ifp, lastx);
    -			xfs_bmbt_get_all(ep, &got);
    -		}
    -		/*
    -		 * Is the last block of this extent before the range
    -		 * we're supposed to delete?  If so, we're done.
    -		 */
    -		bno = XFS_FILEOFF_MIN(bno,
    -			got.br_startoff + got.br_blockcount - 1);
    -		if (bno < start)
    -			break;
    -		/*
    -		 * Then deal with the (possibly delayed) allocated space
    -		 * we found.
    -		 */
    -		ASSERT(ep != NULL);
    -		del = got;
    -		wasdel = ISNULLSTARTBLOCK(del.br_startblock);
    -		if (got.br_startoff < start) {
    -			del.br_startoff = start;
    -			del.br_blockcount -= start - got.br_startoff;
    -			if (!wasdel)
    -				del.br_startblock += start - got.br_startoff;
    -		}
    -		if (del.br_startoff + del.br_blockcount > bno + 1)
    -			del.br_blockcount = bno + 1 - del.br_startoff;
    -		sum = del.br_startblock + del.br_blockcount;
    -		if (isrt &&
    -		    (mod = do_mod(sum, mp->m_sb.sb_rextsize))) {
    -			/*
    -			 * Realtime extent not lined up at the end.
    -			 * The extent could have been split into written
    -			 * and unwritten pieces, or we could just be
    -			 * unmapping part of it.  But we can't really
    -			 * get rid of part of a realtime extent.
    -			 */
    -			if (del.br_state == XFS_EXT_UNWRITTEN ||
    -			    !XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb)) {
    -				/*
    -				 * This piece is unwritten, or we're not
    -				 * using unwritten extents.  Skip over it.
    -				 */
    -				ASSERT(bno >= mod);
    -				bno -= mod > del.br_blockcount ?
    -					del.br_blockcount : mod;
    -				if (bno < got.br_startoff) {
    -					if (--lastx >= 0)
    -						xfs_bmbt_get_all(xfs_iext_get_ext(
    -							ifp, lastx), &got);
    -				}
    -				continue;
    -			}
    -			/*
    -			 * It's written, turn it unwritten.
    -			 * This is better than zeroing it.
    -			 */
    -			ASSERT(del.br_state == XFS_EXT_NORM);
    -			ASSERT(xfs_trans_get_block_res(tp) > 0);
    -			/*
    -			 * If this spans a realtime extent boundary,
    -			 * chop it back to the start of the one we end at.
    -			 */
    -			if (del.br_blockcount > mod) {
    -				del.br_startoff += del.br_blockcount - mod;
    -				del.br_startblock += del.br_blockcount - mod;
    -				del.br_blockcount = mod;
    -			}
    -			del.br_state = XFS_EXT_UNWRITTEN;
    -			error = xfs_bmap_add_extent(ip, lastx, &cur, &del,
    -				firstblock, flist, &logflags, delta,
    -				XFS_DATA_FORK, 0);
    -			if (error)
    -				goto error0;
    -			goto nodelete;
    -		}
    -		if (isrt && (mod = do_mod(del.br_startblock, mp->m_sb.sb_rextsize))) {
    -			/*
    -			 * Realtime extent is lined up at the end but not
    -			 * at the front.  We'll get rid of full extents if
    -			 * we can.
    -			 */
    -			mod = mp->m_sb.sb_rextsize - mod;
    -			if (del.br_blockcount > mod) {
    -				del.br_blockcount -= mod;
    -				del.br_startoff += mod;
    -				del.br_startblock += mod;
    -			} else if ((del.br_startoff == start &&
    -				    (del.br_state == XFS_EXT_UNWRITTEN ||
    -				     xfs_trans_get_block_res(tp) == 0)) ||
    -				   !XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb)) {
    -				/*
    -				 * Can't make it unwritten.  There isn't
    -				 * a full extent here so just skip it.
    -				 */
    -				ASSERT(bno >= del.br_blockcount);
    -				bno -= del.br_blockcount;
    -				if (bno < got.br_startoff) {
    -					if (--lastx >= 0)
    -						xfs_bmbt_get_all(--ep, &got);
    -				}
    -				continue;
    -			} else if (del.br_state == XFS_EXT_UNWRITTEN) {
    -				/*
    -				 * This one is already unwritten.
    -				 * It must have a written left neighbor.
    -				 * Unwrite the killed part of that one and
    -				 * try again.
    -				 */
    -				ASSERT(lastx > 0);
    -				xfs_bmbt_get_all(xfs_iext_get_ext(ifp,
    -						lastx - 1), &prev);
    -				ASSERT(prev.br_state == XFS_EXT_NORM);
    -				ASSERT(!ISNULLSTARTBLOCK(prev.br_startblock));
    -				ASSERT(del.br_startblock ==
    -				       prev.br_startblock + prev.br_blockcount);
    -				if (prev.br_startoff < start) {
    -					mod = start - prev.br_startoff;
    -					prev.br_blockcount -= mod;
    -					prev.br_startblock += mod;
    -					prev.br_startoff = start;
    -				}
    -				prev.br_state = XFS_EXT_UNWRITTEN;
    -				error = xfs_bmap_add_extent(ip, lastx - 1, &cur,
    -					&prev, firstblock, flist, &logflags,
    -					delta, XFS_DATA_FORK, 0);
    -				if (error)
    -					goto error0;
    -				goto nodelete;
    -			} else {
    -				ASSERT(del.br_state == XFS_EXT_NORM);
    -				del.br_state = XFS_EXT_UNWRITTEN;
    -				error = xfs_bmap_add_extent(ip, lastx, &cur,
    -					&del, firstblock, flist, &logflags,
    -					delta, XFS_DATA_FORK, 0);
    -				if (error)
    -					goto error0;
    -				goto nodelete;
    -			}
    -		}
    -		if (wasdel) {
    -			ASSERT(STARTBLOCKVAL(del.br_startblock) > 0);
    -			/* Update realtime/data freespace, unreserve quota */
    -			if (isrt) {
    -				xfs_filblks_t rtexts;
    -
    -				rtexts = XFS_FSB_TO_B(mp, del.br_blockcount);
    -				do_div(rtexts, mp->m_sb.sb_rextsize);
    -				xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS,
    -						(int)rtexts, rsvd);
    -				(void)XFS_TRANS_RESERVE_QUOTA_NBLKS(mp,
    -					NULL, ip, -((long)del.br_blockcount), 0,
    -					XFS_QMOPT_RES_RTBLKS);
    -			} else {
    -				xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS,
    -						(int)del.br_blockcount, rsvd);
    -				(void)XFS_TRANS_RESERVE_QUOTA_NBLKS(mp,
    -					NULL, ip, -((long)del.br_blockcount), 0,
    -					XFS_QMOPT_RES_REGBLKS);
    -			}
    -			ip->i_delayed_blks -= del.br_blockcount;
    -			if (cur)
    -				cur->bc_private.b.flags |=
    -					XFS_BTCUR_BPRV_WASDEL;
    -		} else if (cur)
    -			cur->bc_private.b.flags &= ~XFS_BTCUR_BPRV_WASDEL;
    -		/*
    -		 * If it's the case where the directory code is running
    -		 * with no block reservation, and the deleted block is in
    -		 * the middle of its extent, and the resulting insert
    -		 * of an extent would cause transformation to btree format,
    -		 * then reject it.  The calling code will then swap
    -		 * blocks around instead.
    -		 * We have to do this now, rather than waiting for the
    -		 * conversion to btree format, since the transaction
    -		 * will be dirty.
    -		 */
    -		if (!wasdel && xfs_trans_get_block_res(tp) == 0 &&
    -		    XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
    -		    XFS_IFORK_NEXTENTS(ip, whichfork) >= ifp->if_ext_max &&
    -		    del.br_startoff > got.br_startoff &&
    -		    del.br_startoff + del.br_blockcount <
    -		    got.br_startoff + got.br_blockcount) {
    -			error = XFS_ERROR(ENOSPC);
    -			goto error0;
    -		}
    -		error = xfs_bmap_del_extent(ip, tp, lastx, flist, cur, &del,
    -				&tmp_logflags, delta, whichfork, rsvd);
    -		logflags |= tmp_logflags;
    -		if (error)
    -			goto error0;
    -		bno = del.br_startoff - 1;
    -nodelete:
    -		lastx = ifp->if_lastex;
    -		/*
    -		 * If not done go on to the next (previous) record.
    -		 * Reset ep in case the extents array was re-alloced.
    -		 */
    -		ep = xfs_iext_get_ext(ifp, lastx);
    -		if (bno != (xfs_fileoff_t)-1 && bno >= start) {
    -			if (lastx >= XFS_IFORK_NEXTENTS(ip, whichfork) ||
    -			    xfs_bmbt_get_startoff(ep) > bno) {
    -				if (--lastx >= 0)
    -					ep = xfs_iext_get_ext(ifp, lastx);
    -			}
    -			if (lastx >= 0)
    -				xfs_bmbt_get_all(ep, &got);
    -			extno++;
    -		}
    -	}
    -	ifp->if_lastex = lastx;
    -	*done = bno == (xfs_fileoff_t)-1 || bno < start || lastx < 0;
    -	ASSERT(ifp->if_ext_max ==
    -	       XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
    -	/*
    -	 * Convert to a btree if necessary.
    -	 */
    -	if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
    -	    XFS_IFORK_NEXTENTS(ip, whichfork) > ifp->if_ext_max) {
    -		ASSERT(cur == NULL);
    -		error = xfs_bmap_extents_to_btree(tp, ip, firstblock, flist,
    -			&cur, 0, &tmp_logflags, whichfork);
    -		logflags |= tmp_logflags;
    -		if (error)
    -			goto error0;
    -	}
    -	/*
    -	 * transform from btree to extents, give it cur
    -	 */
    -	else if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE &&
    -		 XFS_IFORK_NEXTENTS(ip, whichfork) <= ifp->if_ext_max) {
    -		ASSERT(cur != NULL);
    -		error = xfs_bmap_btree_to_extents(tp, ip, cur, &tmp_logflags,
    -			whichfork);
    -		logflags |= tmp_logflags;
    -		if (error)
    -			goto error0;
    -	}
    -	/*
    -	 * transform from extents to local?
    -	 */
    -	ASSERT(ifp->if_ext_max ==
    -	       XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
    -	error = 0;
    -	if (delta && delta->xed_startoff != NULLFILEOFF) {
    -		/* A change was actually made.
    -		 * Note that delta->xed_blockount is an offset at this
    -		 * point and needs to be converted to a block count.
    -		 */
    -		ASSERT(delta->xed_blockcount > delta->xed_startoff);
    -		delta->xed_blockcount -= delta->xed_startoff;
    -	}
    -error0:
    -	/*
    -	 * Log everything.  Do this after conversion, there's no point in
    -	 * logging the extent records if we've converted to btree format.
    -	 */
    -	if ((logflags & XFS_ILOG_FEXT(whichfork)) &&
    -	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
    -		logflags &= ~XFS_ILOG_FEXT(whichfork);
    -	else if ((logflags & XFS_ILOG_FBROOT(whichfork)) &&
    -		 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)
    -		logflags &= ~XFS_ILOG_FBROOT(whichfork);
    -	/*
    -	 * Log inode even in the error case, if the transaction
    -	 * is dirty we'll need to shut down the filesystem.
    -	 */
    -	if (logflags)
    -		xfs_trans_log_inode(tp, ip, logflags);
    -	if (cur) {
    -		if (!error) {
    -			*firstblock = cur->bc_private.b.firstblock;
    -			cur->bc_private.b.allocated = 0;
    -		}
    -		xfs_btree_del_cursor(cur,
    -			error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
    -	}
    -	return error;
    -}
    -
    -#undef copy_to_user
    -static __inline__ int
    -copy_to_user(void *dst, void *src, int len) {
    -	memcpy(dst,src,len);
    -	return 0;
    -}
    -#undef copy_from_user
    -static __inline__ int
    -copy_from_user(void *dst, void *src, int len) {
    -	memcpy(dst,src,len);
    -	return 0;
    -}
    -/*
    - * Fcntl interface to xfs_bmapi.
    - */
    -int						/* error code */
    -xfs_getbmap(
    -	bhv_desc_t		*bdp,		/* XFS behavior descriptor*/
    -	struct getbmap		*bmv,		/* user bmap structure */
    -	void			__user *ap,	/* pointer to user's array */
    -	int			interface)	/* interface flags */
    -{
    -	__int64_t		bmvend;		/* last block requested */
    -	int			error;		/* return value */
    -	__int64_t		fixlen;		/* length for -1 case */
    -	int			i;		/* extent number */
    -	xfs_inode_t		*ip;		/* xfs incore inode pointer */
    -	xfs_vnode_t		*vp;		/* corresponding vnode */
    -	int			lock;		/* lock state */
    -	xfs_bmbt_irec_t		*map;		/* buffer for user's data */
    -	xfs_mount_t		*mp;		/* file system mount point */
    -	int			nex;		/* # of user extents can do */
    -	int			nexleft;	/* # of user extents left */
    -	int			subnex;		/* # of bmapi's can do */
    -	int			nmap;		/* number of map entries */
    -	struct getbmap		out;		/* output structure */
    -	int			whichfork;	/* data or attr fork */
    -	int			prealloced;	/* this is a file with
    -						 * preallocated data space */
    -	int			sh_unwritten;	/* true, if unwritten */
    -						/* extents listed separately */
    -	int			bmapi_flags;	/* flags for xfs_bmapi */
    -	__int32_t		oflags;		/* getbmapx bmv_oflags field */
    -
    -	vp = BHV_TO_VNODE(bdp);
    -	ip = XFS_BHVTOI(bdp);
    -	mp = ip->i_mount;
    -
    -	whichfork = interface & BMV_IF_ATTRFORK ? XFS_ATTR_FORK : XFS_DATA_FORK;
    -	sh_unwritten = (interface & BMV_IF_PREALLOC) != 0;
    -
    -	/*	If the BMV_IF_NO_DMAPI_READ interface bit specified, do not
    -	 *	generate a DMAPI read event.  Otherwise, if the DM_EVENT_READ
    -	 *	bit is set for the file, generate a read event in order
    -	 *	that the DMAPI application may do its thing before we return
    -	 *	the extents.  Usually this means restoring user file data to
    -	 *	regions of the file that look like holes.
    -	 *
    -	 *	The "old behavior" (from XFS_IOC_GETBMAP) is to not specify
    -	 *	BMV_IF_NO_DMAPI_READ so that read events are generated.
    -	 *	If this were not true, callers of ioctl( XFS_IOC_GETBMAP )
    -	 *	could misinterpret holes in a DMAPI file as true holes,
    -	 *	when in fact they may represent offline user data.
    -	 */
    -	if (   (interface & BMV_IF_NO_DMAPI_READ) == 0
    -	    && DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ)
    -	    && whichfork == XFS_DATA_FORK) {
    -
    -		error = XFS_SEND_DATA(mp, DM_EVENT_READ, vp, 0, 0, 0, NULL);
    -		if (error)
    -			return XFS_ERROR(error);
    -	}
    -
    -	if (whichfork == XFS_ATTR_FORK) {
    -		if (XFS_IFORK_Q(ip)) {
    -			if (ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS &&
    -			    ip->i_d.di_aformat != XFS_DINODE_FMT_BTREE &&
    -			    ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)
    -				return XFS_ERROR(EINVAL);
    -		} else if (unlikely(
    -			   ip->i_d.di_aformat != 0 &&
    -			   ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS)) {
    -			XFS_ERROR_REPORT("xfs_getbmap", XFS_ERRLEVEL_LOW,
    -					 ip->i_mount);
    -			return XFS_ERROR(EFSCORRUPTED);
    -		}
    -	} else if (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS &&
    -		   ip->i_d.di_format != XFS_DINODE_FMT_BTREE &&
    -		   ip->i_d.di_format != XFS_DINODE_FMT_LOCAL)
    -		return XFS_ERROR(EINVAL);
    -	if (whichfork == XFS_DATA_FORK) {
    -		if ((ip->i_d.di_extsize && (ip->i_d.di_flags &
    -				(XFS_DIFLAG_REALTIME|XFS_DIFLAG_EXTSIZE))) ||
    -		    ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC|XFS_DIFLAG_APPEND)){
    -			prealloced = 1;
    -			fixlen = XFS_MAXIOFFSET(mp);
    -		} else {
    -			prealloced = 0;
    -			fixlen = ip->i_d.di_size;
    -		}
    -	} else {
    -		prealloced = 0;
    -		fixlen = 1LL << 32;
    -	}
    -
    -	if (bmv->bmv_length == -1) {
    -		fixlen = XFS_FSB_TO_BB(mp, XFS_B_TO_FSB(mp, fixlen));
    -		bmv->bmv_length = MAX( (__int64_t)(fixlen - bmv->bmv_offset),
    -					(__int64_t)0);
    -	} else if (bmv->bmv_length < 0)
    -		return XFS_ERROR(EINVAL);
    -	if (bmv->bmv_length == 0) {
    -		bmv->bmv_entries = 0;
    -		return 0;
    -	}
    -	nex = bmv->bmv_count - 1;
    -	if (nex <= 0)
    -		return XFS_ERROR(EINVAL);
    -	bmvend = bmv->bmv_offset + bmv->bmv_length;
    -
    -	xfs_ilock(ip, XFS_IOLOCK_SHARED);
    -
    -	if (whichfork == XFS_DATA_FORK && ip->i_delayed_blks) {
    -		/* xfs_fsize_t last_byte = xfs_file_last_byte(ip); */
    -		XVOP_FLUSH_PAGES(vp, (xfs_off_t)0, -1, 0, FI_REMAPF, error);
    -	}
    -
    -	ASSERT(whichfork == XFS_ATTR_FORK || ip->i_delayed_blks == 0);
    -
    -	lock = xfs_ilock_map_shared(ip);
    -
    -	/*
    -	 * Don't let nex be bigger than the number of extents
    -	 * we can have assuming alternating holes and real extents.
    -	 */
    -	if (nex > XFS_IFORK_NEXTENTS(ip, whichfork) * 2 + 1)
    -		nex = XFS_IFORK_NEXTENTS(ip, whichfork) * 2 + 1;
    -
    -	bmapi_flags = XFS_BMAPI_AFLAG(whichfork) |
    -			((sh_unwritten) ? 0 : XFS_BMAPI_IGSTATE);
    -
    -	/*
    -	 * Allocate enough space to handle "subnex" maps at a time.
    -	 */
    -	subnex = 16;
    -	map = kmem_alloc(subnex * sizeof(*map), KM_SLEEP);
    -
    -	bmv->bmv_entries = 0;
    -
    -	if (XFS_IFORK_NEXTENTS(ip, whichfork) == 0) {
    -		error = 0;
    -		goto unlock_and_return;
    -	}
    -
    -	nexleft = nex;
    -
    -	do {
    -		nmap = (nexleft > subnex) ? subnex : nexleft;
    -		error = xfs_bmapi(NULL, ip, XFS_BB_TO_FSBT(mp, bmv->bmv_offset),
    -				  XFS_BB_TO_FSB(mp, bmv->bmv_length),
    -				  bmapi_flags, NULL, 0, map, &nmap,
    -				  NULL, NULL);
    -		if (error)
    -			goto unlock_and_return;
    -		ASSERT(nmap <= subnex);
    -
    -		for (i = 0; i < nmap && nexleft && bmv->bmv_length; i++) {
    -			nexleft--;
    -			oflags = (map[i].br_state == XFS_EXT_UNWRITTEN) ?
    -					BMV_OF_PREALLOC : 0;
    -			out.bmv_offset = XFS_FSB_TO_BB(mp, map[i].br_startoff);
    -			out.bmv_length = XFS_FSB_TO_BB(mp, map[i].br_blockcount);
    -			ASSERT(map[i].br_startblock != DELAYSTARTBLOCK);
    -                        if (map[i].br_startblock == HOLESTARTBLOCK &&
    -                           ((prealloced && out.bmv_offset + out.bmv_length == bmvend) ||
    -                             whichfork == XFS_ATTR_FORK )) {
    -                                /*
    -                                 * came to hole at end of file or the end of
    -                                   attribute fork
    -                                 */
    -				goto unlock_and_return;
    -			} else {
    -				out.bmv_block =
    -				    (map[i].br_startblock == HOLESTARTBLOCK) ?
    -					-1 :
    -					XFS_FSB_TO_DB(ip, map[i].br_startblock);
    -
    -				/* return either getbmap/getbmapx structure. */
    -				if (interface & BMV_IF_EXTENDED) {
    -					struct	getbmapx	outx;
    -
    -					GETBMAP_CONVERT(out,outx);
    -					outx.bmv_oflags = oflags;
    -					outx.bmv_unused1 = outx.bmv_unused2 = 0;
    -					if (copy_to_user(ap, &outx,
    -							sizeof(outx))) {
    -						error = XFS_ERROR(EFAULT);
    -						goto unlock_and_return;
    -					}
    -				} else {
    -					if (copy_to_user(ap, &out,
    -							sizeof(out))) {
    -						error = XFS_ERROR(EFAULT);
    -						goto unlock_and_return;
    -					}
    -				}
    -				bmv->bmv_offset =
    -					out.bmv_offset + out.bmv_length;
    -				bmv->bmv_length = MAX((__int64_t)0,
    -					(__int64_t)(bmvend - bmv->bmv_offset));
    -				bmv->bmv_entries++;
    -				ap = (interface & BMV_IF_EXTENDED) ?
    -						(void __user *)
    -					((struct getbmapx __user *)ap + 1) :
    -						(void __user *)
    -					((struct getbmap __user *)ap + 1);
    -			}
    -		}
    -	} while (nmap && nexleft && bmv->bmv_length);
    -
    -unlock_and_return:
    -	xfs_iunlock_map_shared(ip, lock);
    -	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
    -
    -	kmem_free(map, subnex * sizeof(*map));
    -
    -	return error;
    -}
    -
    -/*
    - * Check the last inode extent to determine whether this allocation will result
    - * in blocks being allocated at the end of the file. When we allocate new data
    - * blocks at the end of the file which do not start at the previous data block,
    - * we will try to align the new blocks at stripe unit boundaries.
    - */
    -STATIC int				/* error */
    -xfs_bmap_isaeof(
    -	xfs_inode_t	*ip,		/* incore inode pointer */
    -	xfs_fileoff_t   off,		/* file offset in fsblocks */
    -	int             whichfork,	/* data or attribute fork */
    -	char		*aeof)		/* return value */
    -{
    -	int		error;		/* error return value */
    -	xfs_ifork_t	*ifp;		/* inode fork pointer */
    -	xfs_bmbt_rec_t	*lastrec;	/* extent record pointer */
    -	xfs_extnum_t	nextents;	/* number of file extents */
    -	xfs_bmbt_irec_t	s;		/* expanded extent record */
    -
    -	ASSERT(whichfork == XFS_DATA_FORK);
    -	ifp = XFS_IFORK_PTR(ip, whichfork);
    -	if (!(ifp->if_flags & XFS_IFEXTENTS) &&
    -	    (error = xfs_iread_extents(NULL, ip, whichfork)))
    -		return error;
    -	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
    -	if (nextents == 0) {
    -		*aeof = 1;
    -		return 0;
    -	}
    -	/*
    -	 * Go to the last extent
    -	 */
    -	lastrec = xfs_iext_get_ext(ifp, nextents - 1);
    -	xfs_bmbt_get_all(lastrec, &s);
    -	/*
    -	 * Check we are allocating in the last extent (for delayed allocations)
    -	 * or past the last extent for non-delayed allocations.
    -	 */
    -	*aeof = (off >= s.br_startoff &&
    -		 off < s.br_startoff + s.br_blockcount &&
    -		 ISNULLSTARTBLOCK(s.br_startblock)) ||
    -		off >= s.br_startoff + s.br_blockcount;
    -	return 0;
    -}
    -
    -/*
    - * Check if the endoff is outside the last extent. If so the caller will grow
    - * the allocation to a stripe unit boundary.
    - */
    -int					/* error */
    -xfs_bmap_eof(
    -	xfs_inode_t	*ip,		/* incore inode pointer */
    -	xfs_fileoff_t	endoff,		/* file offset in fsblocks */
    -	int		whichfork,	/* data or attribute fork */
    -	int		*eof)		/* result value */
    -{
    -	xfs_fsblock_t	blockcount;	/* extent block count */
    -	int		error;		/* error return value */
    -	xfs_ifork_t	*ifp;		/* inode fork pointer */
    -	xfs_bmbt_rec_t	*lastrec;	/* extent record pointer */
    -	xfs_extnum_t	nextents;	/* number of file extents */
    -	xfs_fileoff_t	startoff;	/* extent starting file offset */
    -
    -	ASSERT(whichfork == XFS_DATA_FORK);
    -	ifp = XFS_IFORK_PTR(ip, whichfork);
    -	if (!(ifp->if_flags & XFS_IFEXTENTS) &&
    -	    (error = xfs_iread_extents(NULL, ip, whichfork)))
    -		return error;
    -	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
    -	if (nextents == 0) {
    -		*eof = 1;
    -		return 0;
    -	}
    -	/*
    -	 * Go to the last extent
    -	 */
    -	lastrec = xfs_iext_get_ext(ifp, nextents - 1);
    -	startoff = xfs_bmbt_get_startoff(lastrec);
    -	blockcount = xfs_bmbt_get_blockcount(lastrec);
    -	*eof = endoff >= startoff + blockcount;
    -	return 0;
    -}
    -
    -#ifdef DEBUG
    -#if 0
    -/*
    - * Check that the extents list for the inode ip is in the right order.
    - */
    -STATIC void
    -xfs_bmap_check_extents(
    -	xfs_inode_t		*ip,		/* incore inode pointer */
    -	int			whichfork)	/* data or attr fork */
    -{
    -	xfs_bmbt_rec_t		*ep;		/* current extent entry */
    -	xfs_extnum_t		idx;		/* extent record index */
    -	xfs_ifork_t		*ifp;		/* inode fork pointer */
    -	xfs_extnum_t		nextents;	/* number of extents in list */
    -	xfs_bmbt_rec_t		*nextp;		/* next extent entry */
    -
    -	ifp = XFS_IFORK_PTR(ip, whichfork);
    -	ASSERT(ifp->if_flags & XFS_IFEXTENTS);
    -	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
    -	ep = xfs_iext_get_ext(ifp, 0);
    -	for (idx = 0; idx < nextents - 1; idx++) {
    -		nextp = xfs_iext_get_ext(ifp, idx + 1);
    -		xfs_btree_check_rec(XFS_BTNUM_BMAP, (void *)ep,
    -			(void *)(nextp));
    -		ep = nextp;
    -	}
    -}
    -#endif
    -
    -STATIC
    -xfs_buf_t *
    -xfs_bmap_get_bp(
    -	xfs_btree_cur_t         *cur,
    -	xfs_fsblock_t		bno)
    -{
    -	int i;
    -	xfs_buf_t *bp;
    -
    -	if (!cur)
    -		return(NULL);
    -
    -	bp = NULL;
    -	for(i = 0; i < XFS_BTREE_MAXLEVELS; i++) {
    -		bp = cur->bc_bufs[i];
    -		if (!bp) break;
    -		if (XFS_BUF_ADDR(bp) == bno)
    -			break;	/* Found it */
    -	}
    -	if (i == XFS_BTREE_MAXLEVELS)
    -		bp = NULL;
    -
    -	if (!bp) { /* Chase down all the log items to see if the bp is there */
    -		xfs_log_item_chunk_t    *licp;
    -		xfs_trans_t		*tp;
    -
    -		tp = cur->bc_tp;
    -		licp = &tp->t_items;
    -		while (!bp && licp != NULL) {
    -			if (XFS_LIC_ARE_ALL_FREE(licp)) {
    -				licp = licp->lic_next;
    -				continue;
    -			}
    -			for (i = 0; i < licp->lic_unused; i++) {
    -				xfs_log_item_desc_t	*lidp;
    -				xfs_log_item_t		*lip;
    -				xfs_buf_log_item_t	*bip;
    -				xfs_buf_t		*lbp;
    -
    -				if (XFS_LIC_ISFREE(licp, i)) {
    -					continue;
    -				}
    -
    -				lidp = XFS_LIC_SLOT(licp, i);
    -				lip = lidp->lid_item;
    -				if (lip->li_type != XFS_LI_BUF)
    -					continue;
    -
    -				bip = (xfs_buf_log_item_t *)lip;
    -				lbp = bip->bli_buf;
    -
    -				if (XFS_BUF_ADDR(lbp) == bno) {
    -					bp = lbp;
    -					break; /* Found it */
    -				}
    -			}
    -			licp = licp->lic_next;
    -		}
    -	}
    -	return(bp);
    -}
    -
    -STATIC void
    -xfs_check_block(
    -	xfs_bmbt_block_t        *block,
    -	xfs_mount_t		*mp,
    -	int			root,
    -	short			sz)
    -{
    -	int			i, j, dmxr;
    -	xfs_bmbt_ptr_t		*pp, *thispa;	/* pointer to block address */
    -	xfs_bmbt_key_t		*prevp, *keyp;
    -
    -	ASSERT(be16_to_cpu(block->bb_level) > 0);
    -
    -	prevp = NULL;
    -	for( i = 1; i <= be16_to_cpu(block->bb_numrecs); i++) {
    -		dmxr = mp->m_bmap_dmxr[0];
    -
    -		if (root) {
    -			keyp = XFS_BMAP_BROOT_KEY_ADDR(block, i, sz);
    -		} else {
    -			keyp = XFS_BTREE_KEY_ADDR(mp->m_sb.sb_blocksize,
    -				xfs_bmbt, block, i, dmxr);
    -		}
    -
    -		if (prevp) {
    -			xfs_btree_check_key(XFS_BTNUM_BMAP, prevp, keyp);
    -		}
    -		prevp = keyp;
    -
    -		/*
    -		 * Compare the block numbers to see if there are dups.
    -		 */
    -
    -		if (root) {
    -			pp = XFS_BMAP_BROOT_PTR_ADDR(block, i, sz);
    -		} else {
    -			pp = XFS_BTREE_PTR_ADDR(mp->m_sb.sb_blocksize,
    -				xfs_bmbt, block, i, dmxr);
    -		}
    -		for (j = i+1; j <= be16_to_cpu(block->bb_numrecs); j++) {
    -			if (root) {
    -				thispa = XFS_BMAP_BROOT_PTR_ADDR(block, j, sz);
    -			} else {
    -				thispa = XFS_BTREE_PTR_ADDR(mp->m_sb.sb_blocksize,
    -					xfs_bmbt, block, j, dmxr);
    -			}
    -			if (INT_GET(*thispa, ARCH_CONVERT) ==
    -			    INT_GET(*pp, ARCH_CONVERT)) {
    -				cmn_err(CE_WARN, "%s: thispa(%d) == pp(%d) %Ld",
    -					__FUNCTION__, j, i,
    -					INT_GET(*thispa, ARCH_CONVERT));
    -				panic("%s: ptrs are equal in node\n",
    -					__FUNCTION__);
    -			}
    -		}
    -	}
    -}
    -
    -/*
    - * Check that the extents for the inode ip are in the right order in all
    - * btree leaves.
    - */
    -
    -STATIC void
    -xfs_bmap_check_leaf_extents(
    -	xfs_btree_cur_t		*cur,	/* btree cursor or null */
    -	xfs_inode_t		*ip,		/* incore inode pointer */
    -	int			whichfork)	/* data or attr fork */
    -{
    -	xfs_bmbt_block_t	*block;	/* current btree block */
    -	xfs_fsblock_t		bno;	/* block # of "block" */
    -	xfs_buf_t		*bp;	/* buffer for "block" */
    -	int			error;	/* error return value */
    -	xfs_extnum_t		i=0, j;	/* index into the extents list */
    -	xfs_ifork_t		*ifp;	/* fork structure */
    -	int			level;	/* btree level, for checking */
    -	xfs_mount_t		*mp;	/* file system mount structure */
    -	xfs_bmbt_ptr_t		*pp;	/* pointer to block address */
    -	xfs_bmbt_rec_t		*ep;	/* pointer to current extent */
    -	xfs_bmbt_rec_t		*lastp; /* pointer to previous extent */
    -	xfs_bmbt_rec_t		*nextp;	/* pointer to next extent */
    -	int			bp_release = 0;
    -
    -	if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE) {
    -		return;
    -	}
    -
    -	bno = NULLFSBLOCK;
    -	mp = ip->i_mount;
    -	ifp = XFS_IFORK_PTR(ip, whichfork);
    -	block = ifp->if_broot;
    -	/*
    -	 * Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out.
    -	 */
    -	level = be16_to_cpu(block->bb_level);
    -	ASSERT(level > 0);
    -	xfs_check_block(block, mp, 1, ifp->if_broot_bytes);
    -	pp = XFS_BMAP_BROOT_PTR_ADDR(block, 1, ifp->if_broot_bytes);
    -	ASSERT(INT_GET(*pp, ARCH_CONVERT) != NULLDFSBNO);
    -	ASSERT(XFS_FSB_TO_AGNO(mp, INT_GET(*pp, ARCH_CONVERT)) < mp->m_sb.sb_agcount);
    -	ASSERT(XFS_FSB_TO_AGBNO(mp, INT_GET(*pp, ARCH_CONVERT)) < mp->m_sb.sb_agblocks);
    -	bno = INT_GET(*pp, ARCH_CONVERT);
    -	/*
    -	 * Go down the tree until leaf level is reached, following the first
    -	 * pointer (leftmost) at each level.
    -	 */
    -	while (level-- > 0) {
    -		/* See if buf is in cur first */
    -		bp = xfs_bmap_get_bp(cur, XFS_FSB_TO_DADDR(mp, bno));
    -		if (bp) {
    -			bp_release = 0;
    -		} else {
    -			bp_release = 1;
    -		}
    -		if (!bp && (error = xfs_btree_read_bufl(mp, NULL, bno, 0, &bp,
    -				XFS_BMAP_BTREE_REF)))
    -			goto error_norelse;
    -		block = XFS_BUF_TO_BMBT_BLOCK(bp);
    -		XFS_WANT_CORRUPTED_GOTO(
    -			XFS_BMAP_SANITY_CHECK(mp, block, level),
    -			error0);
    -		if (level == 0)
    -			break;
    -
    -		/*
    -		 * Check this block for basic sanity (increasing keys and
    -		 * no duplicate blocks).
    -		 */
    -
    -		xfs_check_block(block, mp, 0, 0);
    -		pp = XFS_BTREE_PTR_ADDR(mp->m_sb.sb_blocksize, xfs_bmbt, block,
    -			1, mp->m_bmap_dmxr[1]);
    -		XFS_WANT_CORRUPTED_GOTO(XFS_FSB_SANITY_CHECK(mp, INT_GET(*pp, ARCH_CONVERT)), error0);
    -		bno = INT_GET(*pp, ARCH_CONVERT);
    -		if (bp_release) {
    -			bp_release = 0;
    -			xfs_trans_brelse(NULL, bp);
    -		}
    -	}
    -
    -	/*
    -	 * Here with bp and block set to the leftmost leaf node in the tree.
    -	 */
    -	i = 0;
    -
    -	/*
    -	 * Loop over all leaf nodes checking that all extents are in the right order.
    -	 */
    -	lastp = NULL;
    -	for (;;) {
    -		xfs_fsblock_t	nextbno;
    -		xfs_extnum_t	num_recs;
    -
    -
    -		num_recs = be16_to_cpu(block->bb_numrecs);
    -
    -		/*
    -		 * Read-ahead the next leaf block, if any.
    -		 */
    -
    -		nextbno = be64_to_cpu(block->bb_rightsib);
    -
    -		/*
    -		 * Check all the extents to make sure they are OK.
    -		 * If we had a previous block, the last entry should
    -		 * conform with the first entry in this one.
    -		 */
    -
    -		ep = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize, xfs_bmbt,
    -			block, 1, mp->m_bmap_dmxr[0]);
    -		for (j = 1; j < num_recs; j++) {
    -			nextp = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize, xfs_bmbt,
    -				block, j + 1, mp->m_bmap_dmxr[0]);
    -			if (lastp) {
    -				xfs_btree_check_rec(XFS_BTNUM_BMAP,
    -					(void *)lastp, (void *)ep);
    -			}
    -			xfs_btree_check_rec(XFS_BTNUM_BMAP, (void *)ep,
    -				(void *)(nextp));
    -			lastp = ep;
    -			ep = nextp;
    -		}
    -
    -		i += num_recs;
    -		if (bp_release) {
    -			bp_release = 0;
    -			xfs_trans_brelse(NULL, bp);
    -		}
    -		bno = nextbno;
    -		/*
    -		 * If we've reached the end, stop.
    -		 */
    -		if (bno == NULLFSBLOCK)
    -			break;
    -
    -		bp = xfs_bmap_get_bp(cur, XFS_FSB_TO_DADDR(mp, bno));
    -		if (bp) {
    -			bp_release = 0;
    -		} else {
    -			bp_release = 1;
    -		}
    -		if (!bp && (error = xfs_btree_read_bufl(mp, NULL, bno, 0, &bp,
    -				XFS_BMAP_BTREE_REF)))
    -			goto error_norelse;
    -		block = XFS_BUF_TO_BMBT_BLOCK(bp);
    -	}
    -	if (bp_release) {
    -		bp_release = 0;
    -		xfs_trans_brelse(NULL, bp);
    -	}
    -	return;
    -
    -error0:
    -	cmn_err(CE_WARN, "%s: at error0", __FUNCTION__);
    -	if (bp_release)
    -		xfs_trans_brelse(NULL, bp);
    -error_norelse:
    -	cmn_err(CE_WARN, "%s: BAD after btree leaves for %d extents",
    -		__FUNCTION__, i);
    -	panic("%s: CORRUPTED BTREE OR SOMETHING", __FUNCTION__);
    -	return;
    -}
    -#endif
    -
    -/*
    - * Count fsblocks of the given fork.
    - */
    -int						/* error */
    -xfs_bmap_count_blocks(
    -	xfs_trans_t		*tp,		/* transaction pointer */
    -	xfs_inode_t		*ip,		/* incore inode */
    -	int			whichfork,	/* data or attr fork */
    -	int			*count)		/* out: count of blocks */
    -{
    -	xfs_bmbt_block_t	*block;	/* current btree block */
    -	xfs_fsblock_t		bno;	/* block # of "block" */
    -	xfs_ifork_t		*ifp;	/* fork structure */
    -	int			level;	/* btree level, for checking */
    -	xfs_mount_t		*mp;	/* file system mount structure */
    -	xfs_bmbt_ptr_t		*pp;	/* pointer to block address */
    -
    -	bno = NULLFSBLOCK;
    -	mp = ip->i_mount;
    -	ifp = XFS_IFORK_PTR(ip, whichfork);
    -	if ( XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS ) {
    -		if (unlikely(xfs_bmap_count_leaves(ifp, 0,
    -			ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t),
    -			count) < 0)) {
    -			XFS_ERROR_REPORT("xfs_bmap_count_blocks(1)",
    -					 XFS_ERRLEVEL_LOW, mp);
    -			return XFS_ERROR(EFSCORRUPTED);
    -		}
    -		return 0;
    -	}
    -
    -	/*
    -	 * Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out.
    -	 */
    -	block = ifp->if_broot;
    -	level = be16_to_cpu(block->bb_level);
    -	ASSERT(level > 0);
    -	pp = XFS_BMAP_BROOT_PTR_ADDR(block, 1, ifp->if_broot_bytes);
    -	ASSERT(INT_GET(*pp, ARCH_CONVERT) != NULLDFSBNO);
    -	ASSERT(XFS_FSB_TO_AGNO(mp, INT_GET(*pp, ARCH_CONVERT)) < mp->m_sb.sb_agcount);
    -	ASSERT(XFS_FSB_TO_AGBNO(mp, INT_GET(*pp, ARCH_CONVERT)) < mp->m_sb.sb_agblocks);
    -	bno = INT_GET(*pp, ARCH_CONVERT);
    -
    -	if (unlikely(xfs_bmap_count_tree(mp, tp, ifp, bno, level, count) < 0)) {
    -		XFS_ERROR_REPORT("xfs_bmap_count_blocks(2)", XFS_ERRLEVEL_LOW,
    -				 mp);
    -		return XFS_ERROR(EFSCORRUPTED);
    -	}
    -
    -	return 0;
    -}
    -
    -/*
    - * Recursively walks each level of a btree
    - * to count total fsblocks is use.
    - */
    -int                                     /* error */
    -xfs_bmap_count_tree(
    -	xfs_mount_t     *mp,            /* file system mount point */
    -	xfs_trans_t     *tp,            /* transaction pointer */
    -	xfs_ifork_t	*ifp,		/* inode fork pointer */
    -	xfs_fsblock_t   blockno,	/* file system block number */
    -	int             levelin,	/* level in btree */
    -	int		*count)		/* Count of blocks */
    -{
    -	int			error;
    -	xfs_buf_t		*bp, *nbp;
    -	int			level = levelin;
    -	xfs_bmbt_ptr_t          *pp;
    -	xfs_fsblock_t           bno = blockno;
    -	xfs_fsblock_t		nextbno;
    -	xfs_bmbt_block_t        *block, *nextblock;
    -	int			numrecs;
    -
    -	if ((error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp, XFS_BMAP_BTREE_REF)))
    -		return error;
    -	*count += 1;
    -	block = XFS_BUF_TO_BMBT_BLOCK(bp);
    -
    -	if (--level) {
    -		/* Not at node above leafs, count this level of nodes */
    -		nextbno = be64_to_cpu(block->bb_rightsib);
    -		while (nextbno != NULLFSBLOCK) {
    -			if ((error = xfs_btree_read_bufl(mp, tp, nextbno,
    -				0, &nbp, XFS_BMAP_BTREE_REF)))
    -				return error;
    -			*count += 1;
    -			nextblock = XFS_BUF_TO_BMBT_BLOCK(nbp);
    -			nextbno = be64_to_cpu(nextblock->bb_rightsib);
    -			xfs_trans_brelse(tp, nbp);
    -		}
    -
    -		/* Dive to the next level */
    -		pp = XFS_BTREE_PTR_ADDR(mp->m_sb.sb_blocksize,
    -			xfs_bmbt, block, 1, mp->m_bmap_dmxr[1]);
    -		bno = INT_GET(*pp, ARCH_CONVERT);
    -		if (unlikely((error =
    -		     xfs_bmap_count_tree(mp, tp, ifp, bno, level, count)) < 0)) {
    -			xfs_trans_brelse(tp, bp);
    -			XFS_ERROR_REPORT("xfs_bmap_count_tree(1)",
    -					 XFS_ERRLEVEL_LOW, mp);
    -			return XFS_ERROR(EFSCORRUPTED);
    -		}
    -		xfs_trans_brelse(tp, bp);
    -	} else {
    -		/* count all level 1 nodes and their leaves */
    -		for (;;) {
    -			nextbno = be64_to_cpu(block->bb_rightsib);
    -			numrecs = be16_to_cpu(block->bb_numrecs);
    -			if (unlikely(xfs_bmap_disk_count_leaves(ifp, mp,
    -					0, block, numrecs, count) < 0)) {
    -				xfs_trans_brelse(tp, bp);
    -				XFS_ERROR_REPORT("xfs_bmap_count_tree(2)",
    -						 XFS_ERRLEVEL_LOW, mp);
    -				return XFS_ERROR(EFSCORRUPTED);
    -			}
    -			xfs_trans_brelse(tp, bp);
    -			if (nextbno == NULLFSBLOCK)
    -				break;
    -			bno = nextbno;
    -			if ((error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp,
    -				XFS_BMAP_BTREE_REF)))
    -				return error;
    -			*count += 1;
    -			block = XFS_BUF_TO_BMBT_BLOCK(bp);
    -		}
    -	}
    -	return 0;
    -}
    -
    -/*
    - * Count leaf blocks given a range of extent records.
    - */
    -int
    -xfs_bmap_count_leaves(
    -	xfs_ifork_t		*ifp,
    -	xfs_extnum_t		idx,
    -	int			numrecs,
    -	int			*count)
    -{
    -	int		b;
    -	xfs_bmbt_rec_t	*frp;
    -
    -	for (b = 0; b < numrecs; b++) {
    -		frp = xfs_iext_get_ext(ifp, idx + b);
    -		*count += xfs_bmbt_get_blockcount(frp);
    -	}
    -	return 0;
    -}
    -
    -/*
    - * Count leaf blocks given a range of extent records originally
    - * in btree format.
    - */
    -int
    -xfs_bmap_disk_count_leaves(
    -	xfs_ifork_t		*ifp,
    -	xfs_mount_t		*mp,
    -	xfs_extnum_t		idx,
    -	xfs_bmbt_block_t	*block,
    -	int			numrecs,
    -	int			*count)
    -{
    -	int		b;
    -	xfs_bmbt_rec_t	*frp;
    -
    -	for (b = 1; b <= numrecs; b++) {
    -		frp = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize,
    -			xfs_bmbt, block, idx + b, mp->m_bmap_dmxr[0]);
    -		*count += xfs_bmbt_disk_get_blockcount(frp);
    -	}
    -	return 0;
    -}
    -
    -
    diff --git a/sys/gnu/fs/xfs/xfs_bmap.h b/sys/gnu/fs/xfs/xfs_bmap.h
    deleted file mode 100644
    index 80e93409b78..00000000000
    --- a/sys/gnu/fs/xfs/xfs_bmap.h
    +++ /dev/null
    @@ -1,386 +0,0 @@
    -/*
    - * Copyright (c) 2000-2006 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_BMAP_H__
    -#define	__XFS_BMAP_H__
    -
    -struct getbmap;
    -struct xfs_bmbt_irec;
    -struct xfs_ifork;
    -struct xfs_inode;
    -struct xfs_mount;
    -struct xfs_trans;
    -
    -/*
    - * DELTA: describe a change to the in-core extent list.
    - *
    - * Internally the use of xed_blockount is somewhat funky.
    - * xed_blockcount contains an offset much of the time because this
    - * makes merging changes easier.  (xfs_fileoff_t and xfs_filblks_t are
    - * the same underlying type).
    - */
    -typedef struct xfs_extdelta
    -{
    -	xfs_fileoff_t		xed_startoff;	/* offset of range */
    -	xfs_filblks_t		xed_blockcount;	/* blocks in range */
    -} xfs_extdelta_t;
    -
    -/*
    - * List of extents to be free "later".
    - * The list is kept sorted on xbf_startblock.
    - */
    -typedef struct xfs_bmap_free_item
    -{
    -	xfs_fsblock_t		xbfi_startblock;/* starting fs block number */
    -	xfs_extlen_t		xbfi_blockcount;/* number of blocks in extent */
    -	struct xfs_bmap_free_item *xbfi_next;	/* link to next entry */
    -} xfs_bmap_free_item_t;
    -
    -/*
    - * Header for free extent list.
    - */
    -typedef	struct xfs_bmap_free
    -{
    -	xfs_bmap_free_item_t	*xbf_first;	/* list of to-be-free extents */
    -	int			xbf_count;	/* count of items on list */
    -	int			xbf_low;	/* kludge: alloc in low mode */
    -} xfs_bmap_free_t;
    -
    -#define	XFS_BMAP_MAX_NMAP	4
    -
    -/*
    - * Flags for xfs_bmapi
    - */
    -#define	XFS_BMAPI_WRITE		0x001	/* write operation: allocate space */
    -#define XFS_BMAPI_DELAY		0x002	/* delayed write operation */
    -#define XFS_BMAPI_ENTIRE	0x004	/* return entire extent, not trimmed */
    -#define XFS_BMAPI_METADATA	0x008	/* mapping metadata not user data */
    -#define XFS_BMAPI_EXACT		0x010	/* allocate only to spec'd bounds */
    -#define XFS_BMAPI_ATTRFORK	0x020	/* use attribute fork not data */
    -#define XFS_BMAPI_ASYNC		0x040	/* bunmapi xactions can be async */
    -#define XFS_BMAPI_RSVBLOCKS	0x080	/* OK to alloc. reserved data blocks */
    -#define	XFS_BMAPI_PREALLOC	0x100	/* preallocation op: unwritten space */
    -#define	XFS_BMAPI_IGSTATE	0x200	/* Ignore state - */
    -					/* combine contig. space */
    -#define	XFS_BMAPI_CONTIG	0x400	/* must allocate only one extent */
    -/*	XFS_BMAPI_DIRECT_IO	0x800	*/
    -#define XFS_BMAPI_CONVERT	0x1000	/* unwritten extent conversion - */
    -					/* need write cache flushing and no */
    -					/* additional allocation alignments */
    -
    -#define	XFS_BMAPI_AFLAG(w)	xfs_bmapi_aflag(w)
    -static inline int xfs_bmapi_aflag(int w)
    -{
    -	return (w == XFS_ATTR_FORK ? XFS_BMAPI_ATTRFORK : 0);
    -}
    -
    -/*
    - * Special values for xfs_bmbt_irec_t br_startblock field.
    - */
    -#define	DELAYSTARTBLOCK		((xfs_fsblock_t)-1LL)
    -#define	HOLESTARTBLOCK		((xfs_fsblock_t)-2LL)
    -
    -#define	XFS_BMAP_INIT(flp,fbp)	xfs_bmap_init(flp,fbp)
    -static inline void xfs_bmap_init(xfs_bmap_free_t *flp, xfs_fsblock_t *fbp)
    -{
    -	((flp)->xbf_first = NULL, (flp)->xbf_count = 0, \
    -		(flp)->xbf_low = 0, *(fbp) = NULLFSBLOCK);
    -}
    -
    -/*
    - * Argument structure for xfs_bmap_alloc.
    - */
    -typedef struct xfs_bmalloca {
    -	xfs_fsblock_t		firstblock; /* i/o first block allocated */
    -	xfs_fsblock_t		rval;	/* starting block of new extent */
    -	xfs_fileoff_t		off;	/* offset in file filling in */
    -	struct xfs_trans	*tp;	/* transaction pointer */
    -	struct xfs_inode	*ip;	/* incore inode pointer */
    -	struct xfs_bmbt_irec	*prevp;	/* extent before the new one */
    -	struct xfs_bmbt_irec	*gotp;	/* extent after, or delayed */
    -	xfs_extlen_t		alen;	/* i/o length asked/allocated */
    -	xfs_extlen_t		total;	/* total blocks needed for xaction */
    -	xfs_extlen_t		minlen;	/* mininum allocation size (blocks) */
    -	xfs_extlen_t		minleft; /* amount must be left after alloc */
    -	char			eof;	/* set if allocating past last extent */
    -	char			wasdel;	/* replacing a delayed allocation */
    -	char			userdata;/* set if is user data */
    -	char			low;	/* low on space, using seq'l ags */
    -	char			aeof;	/* allocated space at eof */
    -	char			conv;	/* overwriting unwritten extents */
    -} xfs_bmalloca_t;
    -
    -#ifdef __KERNEL__
    -
    -#if defined(XFS_BMAP_TRACE)
    -/*
    - * Trace operations for bmap extent tracing
    - */
    -#define	XFS_BMAP_KTRACE_DELETE	1
    -#define	XFS_BMAP_KTRACE_INSERT	2
    -#define	XFS_BMAP_KTRACE_PRE_UP	3
    -#define	XFS_BMAP_KTRACE_POST_UP	4
    -
    -#define	XFS_BMAP_TRACE_SIZE	4096	/* size of global trace buffer */
    -#define	XFS_BMAP_KTRACE_SIZE	32	/* size of per-inode trace buffer */
    -extern ktrace_t	*xfs_bmap_trace_buf;
    -
    -/*
    - * Add bmap trace insert entries for all the contents of the extent list.
    - */
    -void
    -xfs_bmap_trace_exlist(
    -	char			*fname,		/* function name */
    -	struct xfs_inode	*ip,		/* incore inode pointer */
    -	xfs_extnum_t		cnt,		/* count of entries in list */
    -	int			whichfork);	/* data or attr fork */
    -#else
    -#define	xfs_bmap_trace_exlist(f,ip,c,w)
    -#endif
    -
    -/*
    - * Convert inode from non-attributed to attributed.
    - * Must not be in a transaction, ip must not be locked.
    - */
    -int					/* error code */
    -xfs_bmap_add_attrfork(
    -	struct xfs_inode	*ip,	/* incore inode pointer */
    -	int			size,	/* space needed for new attribute */
    -	int			rsvd);	/* flag for reserved block allocation */
    -
    -/*
    - * Add the extent to the list of extents to be free at transaction end.
    - * The list is maintained sorted (by block number).
    - */
    -void
    -xfs_bmap_add_free(
    -	xfs_fsblock_t		bno,		/* fs block number of extent */
    -	xfs_filblks_t		len,		/* length of extent */
    -	xfs_bmap_free_t		*flist,		/* list of extents */
    -	struct xfs_mount	*mp);		/* mount point structure */
    -
    -/*
    - * Routine to clean up the free list data structure when
    - * an error occurs during a transaction.
    - */
    -void
    -xfs_bmap_cancel(
    -	xfs_bmap_free_t		*flist);	/* free list to clean up */
    -
    -/*
    - * Compute and fill in the value of the maximum depth of a bmap btree
    - * in this filesystem.  Done once, during mount.
    - */
    -void
    -xfs_bmap_compute_maxlevels(
    -	struct xfs_mount	*mp,	/* file system mount structure */
    -	int			whichfork);	/* data or attr fork */
    -
    -/*
    - * Routine to be called at transaction's end by xfs_bmapi, xfs_bunmapi
    - * caller.  Frees all the extents that need freeing, which must be done
    - * last due to locking considerations.
    - *
    - * Return 1 if the given transaction was committed and a new one allocated,
    - * and 0 otherwise.
    - */
    -int						/* error */
    -xfs_bmap_finish(
    -	struct xfs_trans	**tp,		/* transaction pointer addr */
    -	xfs_bmap_free_t		*flist,		/* i/o: list extents to free */
    -	xfs_fsblock_t		firstblock,	/* controlled a.g. for allocs */
    -	int			*committed);	/* xact committed or not */
    -
    -/*
    - * Returns the file-relative block number of the first unused block in the file.
    - * This is the lowest-address hole if the file has holes, else the first block
    - * past the end of file.
    - */
    -int						/* error */
    -xfs_bmap_first_unused(
    -	struct xfs_trans	*tp,		/* transaction pointer */
    -	struct xfs_inode	*ip,		/* incore inode */
    -	xfs_extlen_t		len,		/* size of hole to find */
    -	xfs_fileoff_t		*unused,	/* unused block num */
    -	int			whichfork);	/* data or attr fork */
    -
    -/*
    - * Returns the file-relative block number of the last block + 1 before
    - * last_block (input value) in the file.
    - * This is not based on i_size, it is based on the extent list.
    - * Returns 0 for local files, as they do not have an extent list.
    - */
    -int						/* error */
    -xfs_bmap_last_before(
    -	struct xfs_trans	*tp,		/* transaction pointer */
    -	struct xfs_inode	*ip,		/* incore inode */
    -	xfs_fileoff_t		*last_block,	/* last block */
    -	int			whichfork);	/* data or attr fork */
    -
    -/*
    - * Returns the file-relative block number of the first block past eof in
    - * the file.  This is not based on i_size, it is based on the extent list.
    - * Returns 0 for local files, as they do not have an extent list.
    - */
    -int						/* error */
    -xfs_bmap_last_offset(
    -	struct xfs_trans	*tp,		/* transaction pointer */
    -	struct xfs_inode	*ip,		/* incore inode */
    -	xfs_fileoff_t		*unused,	/* last block num */
    -	int			whichfork);	/* data or attr fork */
    -
    -/*
    - * Returns whether the selected fork of the inode has exactly one
    - * block or not.  For the data fork we check this matches di_size,
    - * implying the file's range is 0..bsize-1.
    - */
    -int
    -xfs_bmap_one_block(
    -	struct xfs_inode	*ip,		/* incore inode */
    -	int			whichfork);	/* data or attr fork */
    -
    -/*
    - * Read in the extents to iu_extents.
    - * All inode fields are set up by caller, we just traverse the btree
    - * and copy the records in.
    - */
    -int						/* error */
    -xfs_bmap_read_extents(
    -	struct xfs_trans	*tp,		/* transaction pointer */
    -	struct xfs_inode	*ip,		/* incore inode */
    -	int			whichfork);	/* data or attr fork */
    -
    -/*
    - * Map file blocks to filesystem blocks.
    - * File range is given by the bno/len pair.
    - * Adds blocks to file if a write ("flags & XFS_BMAPI_WRITE" set)
    - * into a hole or past eof.
    - * Only allocates blocks from a single allocation group,
    - * to avoid locking problems.
    - * The returned value in "firstblock" from the first call in a transaction
    - * must be remembered and presented to subsequent calls in "firstblock".
    - * An upper bound for the number of blocks to be allocated is supplied to
    - * the first call in "total"; if no allocation group has that many free
    - * blocks then the call will fail (return NULLFSBLOCK in "firstblock").
    - */
    -int						/* error */
    -xfs_bmapi(
    -	struct xfs_trans	*tp,		/* transaction pointer */
    -	struct xfs_inode	*ip,		/* incore inode */
    -	xfs_fileoff_t		bno,		/* starting file offs. mapped */
    -	xfs_filblks_t		len,		/* length to map in file */
    -	int			flags,		/* XFS_BMAPI_... */
    -	xfs_fsblock_t		*firstblock,	/* first allocated block
    -						   controls a.g. for allocs */
    -	xfs_extlen_t		total,		/* total blocks needed */
    -	struct xfs_bmbt_irec	*mval,		/* output: map values */
    -	int			*nmap,		/* i/o: mval size/count */
    -	xfs_bmap_free_t		*flist,		/* i/o: list extents to free */
    -	xfs_extdelta_t		*delta);	/* o: change made to incore
    -						   extents */
    -
    -/*
    - * Map file blocks to filesystem blocks, simple version.
    - * One block only, read-only.
    - * For flags, only the XFS_BMAPI_ATTRFORK flag is examined.
    - * For the other flag values, the effect is as if XFS_BMAPI_METADATA
    - * was set and all the others were clear.
    - */
    -int						/* error */
    -xfs_bmapi_single(
    -	struct xfs_trans	*tp,		/* transaction pointer */
    -	struct xfs_inode	*ip,		/* incore inode */
    -	int			whichfork,	/* data or attr fork */
    -	xfs_fsblock_t		*fsb,		/* output: mapped block */
    -	xfs_fileoff_t		bno);		/* starting file offs. mapped */
    -
    -/*
    - * Unmap (remove) blocks from a file.
    - * If nexts is nonzero then the number of extents to remove is limited to
    - * that value.  If not all extents in the block range can be removed then
    - * *done is set.
    - */
    -int						/* error */
    -xfs_bunmapi(
    -	struct xfs_trans	*tp,		/* transaction pointer */
    -	struct xfs_inode	*ip,		/* incore inode */
    -	xfs_fileoff_t		bno,		/* starting offset to unmap */
    -	xfs_filblks_t		len,		/* length to unmap in file */
    -	int			flags,		/* XFS_BMAPI_... */
    -	xfs_extnum_t		nexts,		/* number of extents max */
    -	xfs_fsblock_t		*firstblock,	/* first allocated block
    -						   controls a.g. for allocs */
    -	xfs_bmap_free_t		*flist,		/* i/o: list extents to free */
    -	xfs_extdelta_t		*delta,		/* o: change made to incore
    -						   extents */
    -	int			*done);		/* set if not done yet */
    -
    -/*
    - * Fcntl interface to xfs_bmapi.
    - */
    -int						/* error code */
    -xfs_getbmap(
    -	bhv_desc_t		*bdp,		/* XFS behavior descriptor*/
    -	struct getbmap		*bmv,		/* user bmap structure */
    -	void			__user *ap,	/* pointer to user's array */
    -	int			iflags);	/* interface flags */
    -
    -/*
    - * Check if the endoff is outside the last extent. If so the caller will grow
    - * the allocation to a stripe unit boundary
    - */
    -int
    -xfs_bmap_eof(
    -	struct xfs_inode        *ip,
    -	xfs_fileoff_t           endoff,
    -	int                     whichfork,
    -	int                     *eof);
    -
    -/*
    - * Count fsblocks of the given fork.
    - */
    -int
    -xfs_bmap_count_blocks(
    -	xfs_trans_t		*tp,
    -	struct xfs_inode	*ip,
    -	int			whichfork,
    -	int			*count);
    -
    -/*
    - * Check an extent list, which has just been read, for
    - * any bit in the extent flag field.
    - */
    -int
    -xfs_check_nostate_extents(
    -	struct xfs_ifork	*ifp,
    -	xfs_extnum_t		idx,
    -	xfs_extnum_t		num);
    -
    -/*
    - * Search the extent records for the entry containing block bno.
    - * If bno lies in a hole, point to the next entry.  If bno lies
    - * past eof, *eofp will be set, and *prevp will contain the last
    - * entry (null if none).  Else, *lastxp will be set to the index
    - * of the found entry; *gotp will contain the entry.
    - */
    -xfs_bmbt_rec_t *
    -xfs_bmap_search_multi_extents(struct xfs_ifork *, xfs_fileoff_t, int *,
    -			xfs_extnum_t *, xfs_bmbt_irec_t *, xfs_bmbt_irec_t *);
    -
    -#endif	/* __KERNEL__ */
    -
    -#endif	/* __XFS_BMAP_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_bmap_btree.c b/sys/gnu/fs/xfs/xfs_bmap_btree.c
    deleted file mode 100644
    index 725123f07ff..00000000000
    --- a/sys/gnu/fs/xfs/xfs_bmap_btree.c
    +++ /dev/null
    @@ -1,2782 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_inode_item.h"
    -#include "xfs_alloc.h"
    -#include "xfs_btree.h"
    -#include "xfs_ialloc.h"
    -#include "xfs_itable.h"
    -#include "xfs_bmap.h"
    -#include "xfs_error.h"
    -#include "xfs_quota.h"
    -
    -#if defined(XFS_BMBT_TRACE)
    -ktrace_t	*xfs_bmbt_trace_buf;
    -#endif
    -
    -/*
    - * Prototypes for internal btree functions.
    - */
    -
    -
    -STATIC int xfs_bmbt_killroot(xfs_btree_cur_t *);
    -STATIC void xfs_bmbt_log_keys(xfs_btree_cur_t *, xfs_buf_t *, int, int);
    -STATIC void xfs_bmbt_log_ptrs(xfs_btree_cur_t *, xfs_buf_t *, int, int);
    -STATIC int xfs_bmbt_lshift(xfs_btree_cur_t *, int, int *);
    -STATIC int xfs_bmbt_rshift(xfs_btree_cur_t *, int, int *);
    -STATIC int xfs_bmbt_split(xfs_btree_cur_t *, int, xfs_fsblock_t *,
    -		xfs_bmbt_key_t *, xfs_btree_cur_t **, int *);
    -STATIC int xfs_bmbt_updkey(xfs_btree_cur_t *, xfs_bmbt_key_t *, int);
    -
    -
    -#if defined(XFS_BMBT_TRACE)
    -
    -static char	ARGS[] = "args";
    -static char	ENTRY[] = "entry";
    -static char	ERROR[] = "error";
    -#undef EXIT
    -static char	EXIT[] = "exit";
    -
    -/*
    - * Add a trace buffer entry for the arguments given to the routine,
    - * generic form.
    - */
    -STATIC void
    -xfs_bmbt_trace_enter(
    -	char		*func,
    -	xfs_btree_cur_t	*cur,
    -	char		*s,
    -	int		type,
    -	int		line,
    -	__psunsigned_t	a0,
    -	__psunsigned_t	a1,
    -	__psunsigned_t	a2,
    -	__psunsigned_t	a3,
    -	__psunsigned_t	a4,
    -	__psunsigned_t	a5,
    -	__psunsigned_t	a6,
    -	__psunsigned_t	a7,
    -	__psunsigned_t	a8,
    -	__psunsigned_t	a9,
    -	__psunsigned_t	a10)
    -{
    -	xfs_inode_t	*ip;
    -	int		whichfork;
    -
    -	ip = cur->bc_private.b.ip;
    -	whichfork = cur->bc_private.b.whichfork;
    -	ktrace_enter(xfs_bmbt_trace_buf,
    -		(void *)((__psint_t)type | (whichfork << 8) | (line << 16)),
    -		(void *)func, (void *)s, (void *)ip, (void *)cur,
    -		(void *)a0, (void *)a1, (void *)a2, (void *)a3,
    -		(void *)a4, (void *)a5, (void *)a6, (void *)a7,
    -		(void *)a8, (void *)a9, (void *)a10);
    -	ASSERT(ip->i_btrace);
    -	ktrace_enter(ip->i_btrace,
    -		(void *)((__psint_t)type | (whichfork << 8) | (line << 16)),
    -		(void *)func, (void *)s, (void *)ip, (void *)cur,
    -		(void *)a0, (void *)a1, (void *)a2, (void *)a3,
    -		(void *)a4, (void *)a5, (void *)a6, (void *)a7,
    -		(void *)a8, (void *)a9, (void *)a10);
    -}
    -/*
    - * Add a trace buffer entry for arguments, for a buffer & 1 integer arg.
    - */
    -STATIC void
    -xfs_bmbt_trace_argbi(
    -	char		*func,
    -	xfs_btree_cur_t	*cur,
    -	xfs_buf_t	*b,
    -	int		i,
    -	int		line)
    -{
    -	xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGBI, line,
    -		(__psunsigned_t)b, i, 0, 0,
    -		0, 0, 0, 0,
    -		0, 0, 0);
    -}
    -
    -/*
    - * Add a trace buffer entry for arguments, for a buffer & 2 integer args.
    - */
    -STATIC void
    -xfs_bmbt_trace_argbii(
    -	char		*func,
    -	xfs_btree_cur_t	*cur,
    -	xfs_buf_t	*b,
    -	int		i0,
    -	int		i1,
    -	int		line)
    -{
    -	xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGBII, line,
    -		(__psunsigned_t)b, i0, i1, 0,
    -		0, 0, 0, 0,
    -		0, 0, 0);
    -}
    -
    -/*
    - * Add a trace buffer entry for arguments, for 3 block-length args
    - * and an integer arg.
    - */
    -STATIC void
    -xfs_bmbt_trace_argfffi(
    -	char			*func,
    -	xfs_btree_cur_t		*cur,
    -	xfs_dfiloff_t		o,
    -	xfs_dfsbno_t		b,
    -	xfs_dfilblks_t		i,
    -	int			j,
    -	int			line)
    -{
    -	xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGFFFI, line,
    -		o >> 32, (int)o, b >> 32, (int)b,
    -		i >> 32, (int)i, (int)j, 0,
    -		0, 0, 0);
    -}
    -
    -/*
    - * Add a trace buffer entry for arguments, for one integer arg.
    - */
    -STATIC void
    -xfs_bmbt_trace_argi(
    -	char		*func,
    -	xfs_btree_cur_t	*cur,
    -	int		i,
    -	int		line)
    -{
    -	xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGI, line,
    -		i, 0, 0, 0,
    -		0, 0, 0, 0,
    -		0, 0, 0);
    -}
    -
    -/*
    - * Add a trace buffer entry for arguments, for int, fsblock, key.
    - */
    -STATIC void
    -xfs_bmbt_trace_argifk(
    -	char			*func,
    -	xfs_btree_cur_t		*cur,
    -	int			i,
    -	xfs_fsblock_t		f,
    -	xfs_bmbt_key_t		*k,
    -	int			line)
    -{
    -	xfs_dfsbno_t		d;
    -	xfs_dfiloff_t		o;
    -
    -	d = (xfs_dfsbno_t)f;
    -	o = INT_GET(k->br_startoff, ARCH_CONVERT);
    -	xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGIFK, line,
    -		i, d >> 32, (int)d, o >> 32,
    -		(int)o, 0, 0, 0,
    -		0, 0, 0);
    -}
    -
    -/*
    - * Add a trace buffer entry for arguments, for int, fsblock, rec.
    - */
    -STATIC void
    -xfs_bmbt_trace_argifr(
    -	char			*func,
    -	xfs_btree_cur_t		*cur,
    -	int			i,
    -	xfs_fsblock_t		f,
    -	xfs_bmbt_rec_t		*r,
    -	int			line)
    -{
    -	xfs_dfsbno_t		b;
    -	xfs_dfilblks_t		c;
    -	xfs_dfsbno_t		d;
    -	xfs_dfiloff_t		o;
    -	xfs_bmbt_irec_t		s;
    -
    -	d = (xfs_dfsbno_t)f;
    -	xfs_bmbt_disk_get_all(r, &s);
    -	o = (xfs_dfiloff_t)s.br_startoff;
    -	b = (xfs_dfsbno_t)s.br_startblock;
    -	c = s.br_blockcount;
    -	xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGIFR, line,
    -		i, d >> 32, (int)d, o >> 32,
    -		(int)o, b >> 32, (int)b, c >> 32,
    -		(int)c, 0, 0);
    -}
    -
    -/*
    - * Add a trace buffer entry for arguments, for int, key.
    - */
    -STATIC void
    -xfs_bmbt_trace_argik(
    -	char			*func,
    -	xfs_btree_cur_t		*cur,
    -	int			i,
    -	xfs_bmbt_key_t		*k,
    -	int			line)
    -{
    -	xfs_dfiloff_t		o;
    -
    -	o = INT_GET(k->br_startoff, ARCH_CONVERT);
    -	xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGIFK, line,
    -		i, o >> 32, (int)o, 0,
    -		0, 0, 0, 0,
    -		0, 0, 0);
    -}
    -
    -/*
    - * Add a trace buffer entry for the cursor/operation.
    - */
    -STATIC void
    -xfs_bmbt_trace_cursor(
    -	char		*func,
    -	xfs_btree_cur_t	*cur,
    -	char		*s,
    -	int		line)
    -{
    -	xfs_bmbt_rec_t	r;
    -
    -	xfs_bmbt_set_all(&r, &cur->bc_rec.b);
    -	xfs_bmbt_trace_enter(func, cur, s, XFS_BMBT_KTRACE_CUR, line,
    -		(cur->bc_nlevels << 24) | (cur->bc_private.b.flags << 16) |
    -		cur->bc_private.b.allocated,
    -		INT_GET(r.l0, ARCH_CONVERT) >> 32, (int)INT_GET(r.l0, ARCH_CONVERT), INT_GET(r.l1, ARCH_CONVERT) >> 32, (int)INT_GET(r.l1, ARCH_CONVERT),
    -		(unsigned long)cur->bc_bufs[0], (unsigned long)cur->bc_bufs[1],
    -		(unsigned long)cur->bc_bufs[2], (unsigned long)cur->bc_bufs[3],
    -		(cur->bc_ptrs[0] << 16) | cur->bc_ptrs[1],
    -		(cur->bc_ptrs[2] << 16) | cur->bc_ptrs[3]);
    -}
    -
    -#define	XFS_BMBT_TRACE_ARGBI(c,b,i)	\
    -	xfs_bmbt_trace_argbi(fname, c, b, i, __LINE__)
    -#define	XFS_BMBT_TRACE_ARGBII(c,b,i,j)	\
    -	xfs_bmbt_trace_argbii(fname, c, b, i, j, __LINE__)
    -#define	XFS_BMBT_TRACE_ARGFFFI(c,o,b,i,j)	\
    -	xfs_bmbt_trace_argfffi(fname, c, o, b, i, j, __LINE__)
    -#define	XFS_BMBT_TRACE_ARGI(c,i)	\
    -	xfs_bmbt_trace_argi(fname, c, i, __LINE__)
    -#define	XFS_BMBT_TRACE_ARGIFK(c,i,f,k)	\
    -	xfs_bmbt_trace_argifk(fname, c, i, f, k, __LINE__)
    -#define	XFS_BMBT_TRACE_ARGIFR(c,i,f,r)	\
    -	xfs_bmbt_trace_argifr(fname, c, i, f, r, __LINE__)
    -#define	XFS_BMBT_TRACE_ARGIK(c,i,k)	\
    -	xfs_bmbt_trace_argik(fname, c, i, k, __LINE__)
    -#define	XFS_BMBT_TRACE_CURSOR(c,s)	\
    -	xfs_bmbt_trace_cursor(fname, c, s, __LINE__)
    -#else
    -#define	XFS_BMBT_TRACE_ARGBI(c,b,i)
    -#define	XFS_BMBT_TRACE_ARGBII(c,b,i,j)
    -#define	XFS_BMBT_TRACE_ARGFFFI(c,o,b,i,j)
    -#define	XFS_BMBT_TRACE_ARGI(c,i)
    -#define	XFS_BMBT_TRACE_ARGIFK(c,i,f,k)
    -#define	XFS_BMBT_TRACE_ARGIFR(c,i,f,r)
    -#define	XFS_BMBT_TRACE_ARGIK(c,i,k)
    -#define	XFS_BMBT_TRACE_CURSOR(c,s)
    -#endif	/* XFS_BMBT_TRACE */
    -
    -
    -/*
    - * Internal functions.
    - */
    -
    -/*
    - * Delete record pointed to by cur/level.
    - */
    -STATIC int					/* error */
    -xfs_bmbt_delrec(
    -	xfs_btree_cur_t		*cur,
    -	int			level,
    -	int			*stat)		/* success/failure */
    -{
    -	xfs_bmbt_block_t	*block;		/* bmap btree block */
    -	xfs_fsblock_t		bno;		/* fs-relative block number */
    -	xfs_buf_t		*bp;		/* buffer for block */
    -	int			error;		/* error return value */
    -#ifdef XFS_BMBT_TRACE
    -	static char		fname[] = "xfs_bmbt_delrec";
    -#endif
    -	int			i;		/* loop counter */
    -	int			j;		/* temp state */
    -	xfs_bmbt_key_t		key;		/* bmap btree key */
    -	xfs_bmbt_key_t		*kp=NULL;	/* pointer to bmap btree key */
    -	xfs_fsblock_t		lbno;		/* left sibling block number */
    -	xfs_buf_t		*lbp;		/* left buffer pointer */
    -	xfs_bmbt_block_t	*left;		/* left btree block */
    -	xfs_bmbt_key_t		*lkp;		/* left btree key */
    -	xfs_bmbt_ptr_t		*lpp;		/* left address pointer */
    -	int			lrecs=0;	/* left record count */
    -	xfs_bmbt_rec_t		*lrp;		/* left record pointer */
    -	xfs_mount_t		*mp;		/* file system mount point */
    -	xfs_bmbt_ptr_t		*pp;		/* pointer to bmap block addr */
    -	int			ptr;		/* key/record index */
    -	xfs_fsblock_t		rbno;		/* right sibling block number */
    -	xfs_buf_t		*rbp;		/* right buffer pointer */
    -	xfs_bmbt_block_t	*right;		/* right btree block */
    -	xfs_bmbt_key_t		*rkp;		/* right btree key */
    -	xfs_bmbt_rec_t		*rp;		/* pointer to bmap btree rec */
    -	xfs_bmbt_ptr_t		*rpp;		/* right address pointer */
    -	xfs_bmbt_block_t	*rrblock;	/* right-right btree block */
    -	xfs_buf_t		*rrbp;		/* right-right buffer pointer */
    -	int			rrecs=0;	/* right record count */
    -	xfs_bmbt_rec_t		*rrp;		/* right record pointer */
    -	xfs_btree_cur_t		*tcur;		/* temporary btree cursor */
    -	int			numrecs;	/* temporary numrec count */
    -	int			numlrecs, numrrecs;
    -
    -	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
    -	XFS_BMBT_TRACE_ARGI(cur, level);
    -	ptr = cur->bc_ptrs[level];
    -	tcur = (xfs_btree_cur_t *)0;
    -	if (ptr == 0) {
    -		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -		*stat = 0;
    -		return 0;
    -	}
    -	block = xfs_bmbt_get_block(cur, level, &bp);
    -	numrecs = be16_to_cpu(block->bb_numrecs);
    -#ifdef DEBUG
    -	if ((error = xfs_btree_check_lblock(cur, block, level, bp))) {
    -		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -		goto error0;
    -	}
    -#endif
    -	if (ptr > numrecs) {
    -		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -		*stat = 0;
    -		return 0;
    -	}
    -	XFS_STATS_INC(xs_bmbt_delrec);
    -	if (level > 0) {
    -		kp = XFS_BMAP_KEY_IADDR(block, 1, cur);
    -		pp = XFS_BMAP_PTR_IADDR(block, 1, cur);
    -#ifdef DEBUG
    -		for (i = ptr; i < numrecs; i++) {
    -			if ((error = xfs_btree_check_lptr(cur, INT_GET(pp[i], ARCH_CONVERT), level))) {
    -				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -				goto error0;
    -			}
    -		}
    -#endif
    -		if (ptr < numrecs) {
    -			memmove(&kp[ptr - 1], &kp[ptr],
    -				(numrecs - ptr) * sizeof(*kp));
    -			memmove(&pp[ptr - 1], &pp[ptr], /* INT_: direct copy */
    -				(numrecs - ptr) * sizeof(*pp));
    -			xfs_bmbt_log_ptrs(cur, bp, ptr, numrecs - 1);
    -			xfs_bmbt_log_keys(cur, bp, ptr, numrecs - 1);
    -		}
    -	} else {
    -		rp = XFS_BMAP_REC_IADDR(block, 1, cur);
    -		if (ptr < numrecs) {
    -			memmove(&rp[ptr - 1], &rp[ptr],
    -				(numrecs - ptr) * sizeof(*rp));
    -			xfs_bmbt_log_recs(cur, bp, ptr, numrecs - 1);
    -		}
    -		if (ptr == 1) {
    -			INT_SET(key.br_startoff, ARCH_CONVERT, xfs_bmbt_disk_get_startoff(rp));
    -			kp = &key;
    -		}
    -	}
    -	numrecs--;
    -	block->bb_numrecs = cpu_to_be16(numrecs);
    -	xfs_bmbt_log_block(cur, bp, XFS_BB_NUMRECS);
    -	/*
    -	 * We're at the root level.
    -	 * First, shrink the root block in-memory.
    -	 * Try to get rid of the next level down.
    -	 * If we can't then there's nothing left to do.
    -	 */
    -	if (level == cur->bc_nlevels - 1) {
    -		xfs_iroot_realloc(cur->bc_private.b.ip, -1,
    -			cur->bc_private.b.whichfork);
    -		if ((error = xfs_bmbt_killroot(cur))) {
    -			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -			goto error0;
    -		}
    -		if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &j))) {
    -			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -			goto error0;
    -		}
    -		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -		*stat = 1;
    -		return 0;
    -	}
    -	if (ptr == 1 && (error = xfs_bmbt_updkey(cur, kp, level + 1))) {
    -		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -		goto error0;
    -	}
    -	if (numrecs >= XFS_BMAP_BLOCK_IMINRECS(level, cur)) {
    -		if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &j))) {
    -			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -			goto error0;
    -		}
    -		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -		*stat = 1;
    -		return 0;
    -	}
    -	rbno = be64_to_cpu(block->bb_rightsib);
    -	lbno = be64_to_cpu(block->bb_leftsib);
    -	/*
    -	 * One child of root, need to get a chance to copy its contents
    -	 * into the root and delete it. Can't go up to next level,
    -	 * there's nothing to delete there.
    -	 */
    -	if (lbno == NULLFSBLOCK && rbno == NULLFSBLOCK &&
    -	    level == cur->bc_nlevels - 2) {
    -		if ((error = xfs_bmbt_killroot(cur))) {
    -			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -			goto error0;
    -		}
    -		if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &i))) {
    -			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -			goto error0;
    -		}
    -		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -		*stat = 1;
    -		return 0;
    -	}
    -	ASSERT(rbno != NULLFSBLOCK || lbno != NULLFSBLOCK);
    -	if ((error = xfs_btree_dup_cursor(cur, &tcur))) {
    -		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -		goto error0;
    -	}
    -	bno = NULLFSBLOCK;
    -	if (rbno != NULLFSBLOCK) {
    -		i = xfs_btree_lastrec(tcur, level);
    -		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -		if ((error = xfs_bmbt_increment(tcur, level, &i))) {
    -			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -			goto error0;
    -		}
    -		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -		i = xfs_btree_lastrec(tcur, level);
    -		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -		rbp = tcur->bc_bufs[level];
    -		right = XFS_BUF_TO_BMBT_BLOCK(rbp);
    -#ifdef DEBUG
    -		if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) {
    -			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -			goto error0;
    -		}
    -#endif
    -		bno = be64_to_cpu(right->bb_leftsib);
    -		if (be16_to_cpu(right->bb_numrecs) - 1 >=
    -		    XFS_BMAP_BLOCK_IMINRECS(level, cur)) {
    -			if ((error = xfs_bmbt_lshift(tcur, level, &i))) {
    -				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -				goto error0;
    -			}
    -			if (i) {
    -				ASSERT(be16_to_cpu(block->bb_numrecs) >=
    -				       XFS_BMAP_BLOCK_IMINRECS(level, tcur));
    -				xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
    -				tcur = NULL;
    -				if (level > 0) {
    -					if ((error = xfs_bmbt_decrement(cur,
    -							level, &i))) {
    -						XFS_BMBT_TRACE_CURSOR(cur,
    -							ERROR);
    -						goto error0;
    -					}
    -				}
    -				XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -				*stat = 1;
    -				return 0;
    -			}
    -		}
    -		rrecs = be16_to_cpu(right->bb_numrecs);
    -		if (lbno != NULLFSBLOCK) {
    -			i = xfs_btree_firstrec(tcur, level);
    -			XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -			if ((error = xfs_bmbt_decrement(tcur, level, &i))) {
    -				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -				goto error0;
    -			}
    -			XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -		}
    -	}
    -	if (lbno != NULLFSBLOCK) {
    -		i = xfs_btree_firstrec(tcur, level);
    -		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -		/*
    -		 * decrement to last in block
    -		 */
    -		if ((error = xfs_bmbt_decrement(tcur, level, &i))) {
    -			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -			goto error0;
    -		}
    -		i = xfs_btree_firstrec(tcur, level);
    -		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -		lbp = tcur->bc_bufs[level];
    -		left = XFS_BUF_TO_BMBT_BLOCK(lbp);
    -#ifdef DEBUG
    -		if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) {
    -			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -			goto error0;
    -		}
    -#endif
    -		bno = be64_to_cpu(left->bb_rightsib);
    -		if (be16_to_cpu(left->bb_numrecs) - 1 >=
    -		    XFS_BMAP_BLOCK_IMINRECS(level, cur)) {
    -			if ((error = xfs_bmbt_rshift(tcur, level, &i))) {
    -				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -				goto error0;
    -			}
    -			if (i) {
    -				ASSERT(be16_to_cpu(block->bb_numrecs) >=
    -				       XFS_BMAP_BLOCK_IMINRECS(level, tcur));
    -				xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
    -				tcur = NULL;
    -				if (level == 0)
    -					cur->bc_ptrs[0]++;
    -				XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -				*stat = 1;
    -				return 0;
    -			}
    -		}
    -		lrecs = be16_to_cpu(left->bb_numrecs);
    -	}
    -	xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
    -	tcur = NULL;
    -	mp = cur->bc_mp;
    -	ASSERT(bno != NULLFSBLOCK);
    -	if (lbno != NULLFSBLOCK &&
    -	    lrecs + be16_to_cpu(block->bb_numrecs) <= XFS_BMAP_BLOCK_IMAXRECS(level, cur)) {
    -		rbno = bno;
    -		right = block;
    -		rbp = bp;
    -		if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, lbno, 0, &lbp,
    -				XFS_BMAP_BTREE_REF))) {
    -			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -			goto error0;
    -		}
    -		left = XFS_BUF_TO_BMBT_BLOCK(lbp);
    -		if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) {
    -			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -			goto error0;
    -		}
    -	} else if (rbno != NULLFSBLOCK &&
    -		   rrecs + be16_to_cpu(block->bb_numrecs) <=
    -		   XFS_BMAP_BLOCK_IMAXRECS(level, cur)) {
    -		lbno = bno;
    -		left = block;
    -		lbp = bp;
    -		if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, rbno, 0, &rbp,
    -				XFS_BMAP_BTREE_REF))) {
    -			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -			goto error0;
    -		}
    -		right = XFS_BUF_TO_BMBT_BLOCK(rbp);
    -		if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) {
    -			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -			goto error0;
    -		}
    -		lrecs = be16_to_cpu(left->bb_numrecs);
    -	} else {
    -		if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &i))) {
    -			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -			goto error0;
    -		}
    -		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -		*stat = 1;
    -		return 0;
    -	}
    -	numlrecs = be16_to_cpu(left->bb_numrecs);
    -	numrrecs = be16_to_cpu(right->bb_numrecs);
    -	if (level > 0) {
    -		lkp = XFS_BMAP_KEY_IADDR(left, numlrecs + 1, cur);
    -		lpp = XFS_BMAP_PTR_IADDR(left, numlrecs + 1, cur);
    -		rkp = XFS_BMAP_KEY_IADDR(right, 1, cur);
    -		rpp = XFS_BMAP_PTR_IADDR(right, 1, cur);
    -#ifdef DEBUG
    -		for (i = 0; i < numrrecs; i++) {
    -			if ((error = xfs_btree_check_lptr(cur, INT_GET(rpp[i], ARCH_CONVERT), level))) {
    -				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -				goto error0;
    -			}
    -		}
    -#endif
    -		memcpy(lkp, rkp, numrrecs * sizeof(*lkp));
    -		memcpy(lpp, rpp, numrrecs * sizeof(*lpp));
    -		xfs_bmbt_log_keys(cur, lbp, numlrecs + 1, numlrecs + numrrecs);
    -		xfs_bmbt_log_ptrs(cur, lbp, numlrecs + 1, numlrecs + numrrecs);
    -	} else {
    -		lrp = XFS_BMAP_REC_IADDR(left, numlrecs + 1, cur);
    -		rrp = XFS_BMAP_REC_IADDR(right, 1, cur);
    -		memcpy(lrp, rrp, numrrecs * sizeof(*lrp));
    -		xfs_bmbt_log_recs(cur, lbp, numlrecs + 1, numlrecs + numrrecs);
    -	}
    -	be16_add(&left->bb_numrecs, numrrecs);
    -	left->bb_rightsib = right->bb_rightsib;
    -	xfs_bmbt_log_block(cur, lbp, XFS_BB_RIGHTSIB | XFS_BB_NUMRECS);
    -	if (be64_to_cpu(left->bb_rightsib) != NULLDFSBNO) {
    -		if ((error = xfs_btree_read_bufl(mp, cur->bc_tp,
    -				be64_to_cpu(left->bb_rightsib),
    -				0, &rrbp, XFS_BMAP_BTREE_REF))) {
    -			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -			goto error0;
    -		}
    -		rrblock = XFS_BUF_TO_BMBT_BLOCK(rrbp);
    -		if ((error = xfs_btree_check_lblock(cur, rrblock, level, rrbp))) {
    -			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -			goto error0;
    -		}
    -		rrblock->bb_leftsib = cpu_to_be64(lbno);
    -		xfs_bmbt_log_block(cur, rrbp, XFS_BB_LEFTSIB);
    -	}
    -	xfs_bmap_add_free(XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(rbp)), 1,
    -		cur->bc_private.b.flist, mp);
    -	cur->bc_private.b.ip->i_d.di_nblocks--;
    -	xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip, XFS_ILOG_CORE);
    -	XFS_TRANS_MOD_DQUOT_BYINO(mp, cur->bc_tp, cur->bc_private.b.ip,
    -			XFS_TRANS_DQ_BCOUNT, -1L);
    -	xfs_trans_binval(cur->bc_tp, rbp);
    -	if (bp != lbp) {
    -		cur->bc_bufs[level] = lbp;
    -		cur->bc_ptrs[level] += lrecs;
    -		cur->bc_ra[level] = 0;
    -	} else if ((error = xfs_bmbt_increment(cur, level + 1, &i))) {
    -		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -		goto error0;
    -	}
    -	if (level > 0)
    -		cur->bc_ptrs[level]--;
    -	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -	*stat = 2;
    -	return 0;
    -
    -error0:
    -	if (tcur)
    -		xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR);
    -	return error;
    -}
    -
    -#ifdef DEBUG
    -/*
    - * Get the data from the pointed-to record.
    - */
    -int
    -xfs_bmbt_get_rec(
    -	xfs_btree_cur_t		*cur,
    -	xfs_fileoff_t		*off,
    -	xfs_fsblock_t		*bno,
    -	xfs_filblks_t		*len,
    -	xfs_exntst_t		*state,
    -	int			*stat)
    -{
    -	xfs_bmbt_block_t	*block;
    -	xfs_buf_t		*bp;
    -#ifdef DEBUG
    -	int			error;
    -#endif
    -	int			ptr;
    -	xfs_bmbt_rec_t		*rp;
    -
    -	block = xfs_bmbt_get_block(cur, 0, &bp);
    -	ptr = cur->bc_ptrs[0];
    -#ifdef DEBUG
    -	if ((error = xfs_btree_check_lblock(cur, block, 0, bp)))
    -		return error;
    -#endif
    -	if (ptr > be16_to_cpu(block->bb_numrecs) || ptr <= 0) {
    -		*stat = 0;
    -		return 0;
    -	}
    -	rp = XFS_BMAP_REC_IADDR(block, ptr, cur);
    -	*off = xfs_bmbt_disk_get_startoff(rp);
    -	*bno = xfs_bmbt_disk_get_startblock(rp);
    -	*len = xfs_bmbt_disk_get_blockcount(rp);
    -	*state = xfs_bmbt_disk_get_state(rp);
    -	*stat = 1;
    -	return 0;
    -}
    -#endif
    -
    -/*
    - * Insert one record/level.  Return information to the caller
    - * allowing the next level up to proceed if necessary.
    - */
    -STATIC int					/* error */
    -xfs_bmbt_insrec(
    -	xfs_btree_cur_t		*cur,
    -	int			level,
    -	xfs_fsblock_t		*bnop,
    -	xfs_bmbt_rec_t		*recp,
    -	xfs_btree_cur_t		**curp,
    -	int			*stat)		/* no-go/done/continue */
    -{
    -	xfs_bmbt_block_t	*block;		/* bmap btree block */
    -	xfs_buf_t		*bp;		/* buffer for block */
    -	int			error;		/* error return value */
    -#ifdef XFS_BMBT_TRACE
    -	static char		fname[] = "xfs_bmbt_insrec";
    -#endif
    -	int			i;		/* loop index */
    -	xfs_bmbt_key_t		key;		/* bmap btree key */
    -	xfs_bmbt_key_t		*kp=NULL;	/* pointer to bmap btree key */
    -	int			logflags;	/* inode logging flags */
    -	xfs_fsblock_t		nbno;		/* new block number */
    -	struct xfs_btree_cur	*ncur;		/* new btree cursor */
    -	xfs_bmbt_key_t		nkey;		/* new btree key value */
    -	xfs_bmbt_rec_t		nrec;		/* new record count */
    -	int			optr;		/* old key/record index */
    -	xfs_bmbt_ptr_t		*pp;		/* pointer to bmap block addr */
    -	int			ptr;		/* key/record index */
    -	xfs_bmbt_rec_t		*rp=NULL;	/* pointer to bmap btree rec */
    -	int			numrecs;
    -
    -	ASSERT(level < cur->bc_nlevels);
    -	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
    -	XFS_BMBT_TRACE_ARGIFR(cur, level, *bnop, recp);
    -	ncur = (xfs_btree_cur_t *)0;
    -	INT_SET(key.br_startoff, ARCH_CONVERT,
    -		xfs_bmbt_disk_get_startoff(recp));
    -	optr = ptr = cur->bc_ptrs[level];
    -	if (ptr == 0) {
    -		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -		*stat = 0;
    -		return 0;
    -	}
    -	XFS_STATS_INC(xs_bmbt_insrec);
    -	block = xfs_bmbt_get_block(cur, level, &bp);
    -	numrecs = be16_to_cpu(block->bb_numrecs);
    -	nkey.br_startoff = 0;
    -#ifdef DEBUG
    -	if ((error = xfs_btree_check_lblock(cur, block, level, bp))) {
    -		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -		return error;
    -	}
    -	if (ptr <= numrecs) {
    -		if (level == 0) {
    -			rp = XFS_BMAP_REC_IADDR(block, ptr, cur);
    -			xfs_btree_check_rec(XFS_BTNUM_BMAP, recp, rp);
    -		} else {
    -			kp = XFS_BMAP_KEY_IADDR(block, ptr, cur);
    -			xfs_btree_check_key(XFS_BTNUM_BMAP, &key, kp);
    -		}
    -	}
    -#endif
    -	nbno = NULLFSBLOCK;
    -	if (numrecs == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) {
    -		if (numrecs < XFS_BMAP_BLOCK_DMAXRECS(level, cur)) {
    -			/*
    -			 * A root block, that can be made bigger.
    -			 */
    -			xfs_iroot_realloc(cur->bc_private.b.ip, 1,
    -				cur->bc_private.b.whichfork);
    -			block = xfs_bmbt_get_block(cur, level, &bp);
    -		} else if (level == cur->bc_nlevels - 1) {
    -			if ((error = xfs_bmbt_newroot(cur, &logflags, stat)) ||
    -			    *stat == 0) {
    -				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -				return error;
    -			}
    -			xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip,
    -				logflags);
    -			block = xfs_bmbt_get_block(cur, level, &bp);
    -		} else {
    -			if ((error = xfs_bmbt_rshift(cur, level, &i))) {
    -				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -				return error;
    -			}
    -			if (i) {
    -				/* nothing */
    -			} else {
    -				if ((error = xfs_bmbt_lshift(cur, level, &i))) {
    -					XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -					return error;
    -				}
    -				if (i) {
    -					optr = ptr = cur->bc_ptrs[level];
    -				} else {
    -					if ((error = xfs_bmbt_split(cur, level,
    -							&nbno, &nkey, &ncur,
    -							&i))) {
    -						XFS_BMBT_TRACE_CURSOR(cur,
    -							ERROR);
    -						return error;
    -					}
    -					if (i) {
    -						block = xfs_bmbt_get_block(
    -							    cur, level, &bp);
    -#ifdef DEBUG
    -						if ((error =
    -						    xfs_btree_check_lblock(cur,
    -							    block, level, bp))) {
    -							XFS_BMBT_TRACE_CURSOR(
    -								cur, ERROR);
    -							return error;
    -						}
    -#endif
    -						ptr = cur->bc_ptrs[level];
    -						xfs_bmbt_disk_set_allf(&nrec,
    -							nkey.br_startoff, 0, 0,
    -							XFS_EXT_NORM);
    -					} else {
    -						XFS_BMBT_TRACE_CURSOR(cur,
    -							EXIT);
    -						*stat = 0;
    -						return 0;
    -					}
    -				}
    -			}
    -		}
    -	}
    -	numrecs = be16_to_cpu(block->bb_numrecs);
    -	if (level > 0) {
    -		kp = XFS_BMAP_KEY_IADDR(block, 1, cur);
    -		pp = XFS_BMAP_PTR_IADDR(block, 1, cur);
    -#ifdef DEBUG
    -		for (i = numrecs; i >= ptr; i--) {
    -			if ((error = xfs_btree_check_lptr(cur, INT_GET(pp[i - 1], ARCH_CONVERT),
    -					level))) {
    -				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -				return error;
    -			}
    -		}
    -#endif
    -		memmove(&kp[ptr], &kp[ptr - 1],
    -			(numrecs - ptr + 1) * sizeof(*kp));
    -		memmove(&pp[ptr], &pp[ptr - 1], /* INT_: direct copy */
    -			(numrecs - ptr + 1) * sizeof(*pp));
    -#ifdef DEBUG
    -		if ((error = xfs_btree_check_lptr(cur, (xfs_bmbt_ptr_t)*bnop,
    -				level))) {
    -			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -			return error;
    -		}
    -#endif
    -		kp[ptr - 1] = key;
    -		INT_SET(pp[ptr - 1], ARCH_CONVERT, *bnop);
    -		numrecs++;
    -		block->bb_numrecs = cpu_to_be16(numrecs);
    -		xfs_bmbt_log_keys(cur, bp, ptr, numrecs);
    -		xfs_bmbt_log_ptrs(cur, bp, ptr, numrecs);
    -	} else {
    -		rp = XFS_BMAP_REC_IADDR(block, 1, cur);
    -		memmove(&rp[ptr], &rp[ptr - 1],
    -			(numrecs - ptr + 1) * sizeof(*rp));
    -		rp[ptr - 1] = *recp;
    -		numrecs++;
    -		block->bb_numrecs = cpu_to_be16(numrecs);
    -		xfs_bmbt_log_recs(cur, bp, ptr, numrecs);
    -	}
    -	xfs_bmbt_log_block(cur, bp, XFS_BB_NUMRECS);
    -#ifdef DEBUG
    -	if (ptr < numrecs) {
    -		if (level == 0)
    -			xfs_btree_check_rec(XFS_BTNUM_BMAP, rp + ptr - 1,
    -				rp + ptr);
    -		else
    -			xfs_btree_check_key(XFS_BTNUM_BMAP, kp + ptr - 1,
    -				kp + ptr);
    -	}
    -#endif
    -	if (optr == 1 && (error = xfs_bmbt_updkey(cur, &key, level + 1))) {
    -		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -		return error;
    -	}
    -	*bnop = nbno;
    -	if (nbno != NULLFSBLOCK) {
    -		*recp = nrec;
    -		*curp = ncur;
    -	}
    -	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -	*stat = 1;
    -	return 0;
    -}
    -
    -STATIC int
    -xfs_bmbt_killroot(
    -	xfs_btree_cur_t		*cur)
    -{
    -	xfs_bmbt_block_t	*block;
    -	xfs_bmbt_block_t	*cblock;
    -	xfs_buf_t		*cbp;
    -	xfs_bmbt_key_t		*ckp;
    -	xfs_bmbt_ptr_t		*cpp;
    -#ifdef DEBUG
    -	int			error;
    -#endif
    -#ifdef XFS_BMBT_TRACE
    -	static char		fname[] = "xfs_bmbt_killroot";
    -#endif
    -	int			i;
    -	xfs_bmbt_key_t		*kp;
    -	xfs_inode_t		*ip;
    -	xfs_ifork_t		*ifp;
    -	int			level;
    -	xfs_bmbt_ptr_t		*pp;
    -
    -	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
    -	level = cur->bc_nlevels - 1;
    -	ASSERT(level >= 1);
    -	/*
    -	 * Don't deal with the root block needs to be a leaf case.
    -	 * We're just going to turn the thing back into extents anyway.
    -	 */
    -	if (level == 1) {
    -		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -		return 0;
    -	}
    -	block = xfs_bmbt_get_block(cur, level, &cbp);
    -	/*
    -	 * Give up if the root has multiple children.
    -	 */
    -	if (be16_to_cpu(block->bb_numrecs) != 1) {
    -		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -		return 0;
    -	}
    -	/*
    -	 * Only do this if the next level will fit.
    -	 * Then the data must be copied up to the inode,
    -	 * instead of freeing the root you free the next level.
    -	 */
    -	cbp = cur->bc_bufs[level - 1];
    -	cblock = XFS_BUF_TO_BMBT_BLOCK(cbp);
    -	if (be16_to_cpu(cblock->bb_numrecs) > XFS_BMAP_BLOCK_DMAXRECS(level, cur)) {
    -		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -		return 0;
    -	}
    -	ASSERT(be64_to_cpu(cblock->bb_leftsib) == NULLDFSBNO);
    -	ASSERT(be64_to_cpu(cblock->bb_rightsib) == NULLDFSBNO);
    -	ip = cur->bc_private.b.ip;
    -	ifp = XFS_IFORK_PTR(ip, cur->bc_private.b.whichfork);
    -	ASSERT(XFS_BMAP_BLOCK_IMAXRECS(level, cur) ==
    -	       XFS_BMAP_BROOT_MAXRECS(ifp->if_broot_bytes));
    -	i = (int)(be16_to_cpu(cblock->bb_numrecs) - XFS_BMAP_BLOCK_IMAXRECS(level, cur));
    -	if (i) {
    -		xfs_iroot_realloc(ip, i, cur->bc_private.b.whichfork);
    -		block = ifp->if_broot;
    -	}
    -	be16_add(&block->bb_numrecs, i);
    -	ASSERT(block->bb_numrecs == cblock->bb_numrecs);
    -	kp = XFS_BMAP_KEY_IADDR(block, 1, cur);
    -	ckp = XFS_BMAP_KEY_IADDR(cblock, 1, cur);
    -	memcpy(kp, ckp, be16_to_cpu(block->bb_numrecs) * sizeof(*kp));
    -	pp = XFS_BMAP_PTR_IADDR(block, 1, cur);
    -	cpp = XFS_BMAP_PTR_IADDR(cblock, 1, cur);
    -#ifdef DEBUG
    -	for (i = 0; i < be16_to_cpu(cblock->bb_numrecs); i++) {
    -		if ((error = xfs_btree_check_lptr(cur, INT_GET(cpp[i], ARCH_CONVERT), level - 1))) {
    -			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -			return error;
    -		}
    -	}
    -#endif
    -	memcpy(pp, cpp, be16_to_cpu(block->bb_numrecs) * sizeof(*pp));
    -	xfs_bmap_add_free(XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(cbp)), 1,
    -			cur->bc_private.b.flist, cur->bc_mp);
    -	ip->i_d.di_nblocks--;
    -	XFS_TRANS_MOD_DQUOT_BYINO(cur->bc_mp, cur->bc_tp, ip,
    -			XFS_TRANS_DQ_BCOUNT, -1L);
    -	xfs_trans_binval(cur->bc_tp, cbp);
    -	cur->bc_bufs[level - 1] = NULL;
    -	be16_add(&block->bb_level, -1);
    -	xfs_trans_log_inode(cur->bc_tp, ip,
    -		XFS_ILOG_CORE | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork));
    -	cur->bc_nlevels--;
    -	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -	return 0;
    -}
    -
    -/*
    - * Log key values from the btree block.
    - */
    -STATIC void
    -xfs_bmbt_log_keys(
    -	xfs_btree_cur_t	*cur,
    -	xfs_buf_t	*bp,
    -	int		kfirst,
    -	int		klast)
    -{
    -#ifdef XFS_BMBT_TRACE
    -	static char	fname[] = "xfs_bmbt_log_keys";
    -#endif
    -	xfs_trans_t	*tp;
    -
    -	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
    -	XFS_BMBT_TRACE_ARGBII(cur, bp, kfirst, klast);
    -	tp = cur->bc_tp;
    -	if (bp) {
    -		xfs_bmbt_block_t	*block;
    -		int			first;
    -		xfs_bmbt_key_t		*kp;
    -		int			last;
    -
    -		block = XFS_BUF_TO_BMBT_BLOCK(bp);
    -		kp = XFS_BMAP_KEY_DADDR(block, 1, cur);
    -		first = (int)((xfs_caddr_t)&kp[kfirst - 1] - (xfs_caddr_t)block);
    -		last = (int)(((xfs_caddr_t)&kp[klast] - 1) - (xfs_caddr_t)block);
    -		xfs_trans_log_buf(tp, bp, first, last);
    -	} else {
    -		xfs_inode_t		 *ip;
    -
    -		ip = cur->bc_private.b.ip;
    -		xfs_trans_log_inode(tp, ip,
    -			XFS_ILOG_FBROOT(cur->bc_private.b.whichfork));
    -	}
    -	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -}
    -
    -/*
    - * Log pointer values from the btree block.
    - */
    -STATIC void
    -xfs_bmbt_log_ptrs(
    -	xfs_btree_cur_t	*cur,
    -	xfs_buf_t	*bp,
    -	int		pfirst,
    -	int		plast)
    -{
    -#ifdef XFS_BMBT_TRACE
    -	static char	fname[] = "xfs_bmbt_log_ptrs";
    -#endif
    -	xfs_trans_t	*tp;
    -
    -	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
    -	XFS_BMBT_TRACE_ARGBII(cur, bp, pfirst, plast);
    -	tp = cur->bc_tp;
    -	if (bp) {
    -		xfs_bmbt_block_t	*block;
    -		int			first;
    -		int			last;
    -		xfs_bmbt_ptr_t		*pp;
    -
    -		block = XFS_BUF_TO_BMBT_BLOCK(bp);
    -		pp = XFS_BMAP_PTR_DADDR(block, 1, cur);
    -		first = (int)((xfs_caddr_t)&pp[pfirst - 1] - (xfs_caddr_t)block);
    -		last = (int)(((xfs_caddr_t)&pp[plast] - 1) - (xfs_caddr_t)block);
    -		xfs_trans_log_buf(tp, bp, first, last);
    -	} else {
    -		xfs_inode_t		*ip;
    -
    -		ip = cur->bc_private.b.ip;
    -		xfs_trans_log_inode(tp, ip,
    -			XFS_ILOG_FBROOT(cur->bc_private.b.whichfork));
    -	}
    -	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -}
    -
    -/*
    - * Lookup the record.  The cursor is made to point to it, based on dir.
    - */
    -STATIC int				/* error */
    -xfs_bmbt_lookup(
    -	xfs_btree_cur_t		*cur,
    -	xfs_lookup_t		dir,
    -	int			*stat)		/* success/failure */
    -{
    -	xfs_bmbt_block_t	*block=NULL;
    -	xfs_buf_t		*bp;
    -	xfs_daddr_t		d;
    -	xfs_sfiloff_t		diff;
    -	int			error;		/* error return value */
    -#ifdef XFS_BMBT_TRACE
    -	static char	fname[] = "xfs_bmbt_lookup";
    -#endif
    -	xfs_fsblock_t		fsbno=0;
    -	int			high;
    -	int			i;
    -	int			keyno=0;
    -	xfs_bmbt_key_t		*kkbase=NULL;
    -	xfs_bmbt_key_t		*kkp;
    -	xfs_bmbt_rec_t		*krbase=NULL;
    -	xfs_bmbt_rec_t		*krp;
    -	int			level;
    -	int			low;
    -	xfs_mount_t		*mp;
    -	xfs_bmbt_ptr_t		*pp;
    -	xfs_bmbt_irec_t		*rp;
    -	xfs_fileoff_t		startoff;
    -	xfs_trans_t		*tp;
    -
    -	XFS_STATS_INC(xs_bmbt_lookup);
    -	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
    -	XFS_BMBT_TRACE_ARGI(cur, (int)dir);
    -	tp = cur->bc_tp;
    -	mp = cur->bc_mp;
    -	rp = &cur->bc_rec.b;
    -	for (level = cur->bc_nlevels - 1, diff = 1; level >= 0; level--) {
    -		if (level < cur->bc_nlevels - 1) {
    -			d = XFS_FSB_TO_DADDR(mp, fsbno);
    -			bp = cur->bc_bufs[level];
    -			if (bp && XFS_BUF_ADDR(bp) != d)
    -				bp = (xfs_buf_t *)0;
    -			if (!bp) {
    -				if ((error = xfs_btree_read_bufl(mp, tp, fsbno,
    -						0, &bp, XFS_BMAP_BTREE_REF))) {
    -					XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -					return error;
    -				}
    -				xfs_btree_setbuf(cur, level, bp);
    -				block = XFS_BUF_TO_BMBT_BLOCK(bp);
    -				if ((error = xfs_btree_check_lblock(cur, block,
    -						level, bp))) {
    -					XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -					return error;
    -				}
    -			} else
    -				block = XFS_BUF_TO_BMBT_BLOCK(bp);
    -		} else
    -			block = xfs_bmbt_get_block(cur, level, &bp);
    -		if (diff == 0)
    -			keyno = 1;
    -		else {
    -			if (level > 0)
    -				kkbase = XFS_BMAP_KEY_IADDR(block, 1, cur);
    -			else
    -				krbase = XFS_BMAP_REC_IADDR(block, 1, cur);
    -			low = 1;
    -			if (!(high = be16_to_cpu(block->bb_numrecs))) {
    -				ASSERT(level == 0);
    -				cur->bc_ptrs[0] = dir != XFS_LOOKUP_LE;
    -				XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -				*stat = 0;
    -				return 0;
    -			}
    -			while (low <= high) {
    -				XFS_STATS_INC(xs_bmbt_compare);
    -				keyno = (low + high) >> 1;
    -				if (level > 0) {
    -					kkp = kkbase + keyno - 1;
    -					startoff = INT_GET(kkp->br_startoff, ARCH_CONVERT);
    -				} else {
    -					krp = krbase + keyno - 1;
    -					startoff = xfs_bmbt_disk_get_startoff(krp);
    -				}
    -				diff = (xfs_sfiloff_t)
    -						(startoff - rp->br_startoff);
    -				if (diff < 0)
    -					low = keyno + 1;
    -				else if (diff > 0)
    -					high = keyno - 1;
    -				else
    -					break;
    -			}
    -		}
    -		if (level > 0) {
    -			if (diff > 0 && --keyno < 1)
    -				keyno = 1;
    -			pp = XFS_BMAP_PTR_IADDR(block, keyno, cur);
    -#ifdef DEBUG
    -			if ((error = xfs_btree_check_lptr(cur, INT_GET(*pp, ARCH_CONVERT), level))) {
    -				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -				return error;
    -			}
    -#endif
    -			fsbno = INT_GET(*pp, ARCH_CONVERT);
    -			cur->bc_ptrs[level] = keyno;
    -		}
    -	}
    -	if (dir != XFS_LOOKUP_LE && diff < 0) {
    -		keyno++;
    -		/*
    -		 * If ge search and we went off the end of the block, but it's
    -		 * not the last block, we're in the wrong block.
    -		 */
    -		if (dir == XFS_LOOKUP_GE && keyno > be16_to_cpu(block->bb_numrecs) &&
    -		    be64_to_cpu(block->bb_rightsib) != NULLDFSBNO) {
    -			cur->bc_ptrs[0] = keyno;
    -			if ((error = xfs_bmbt_increment(cur, 0, &i))) {
    -				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -				return error;
    -			}
    -			XFS_WANT_CORRUPTED_RETURN(i == 1);
    -			XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -			*stat = 1;
    -			return 0;
    -		}
    -	}
    -	else if (dir == XFS_LOOKUP_LE && diff > 0)
    -		keyno--;
    -	cur->bc_ptrs[0] = keyno;
    -	if (keyno == 0 || keyno > be16_to_cpu(block->bb_numrecs)) {
    -		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -		*stat = 0;
    -	} else {
    -		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -		*stat = ((dir != XFS_LOOKUP_EQ) || (diff == 0));
    -	}
    -	return 0;
    -}
    -
    -/*
    - * Move 1 record left from cur/level if possible.
    - * Update cur to reflect the new path.
    - */
    -STATIC int					/* error */
    -xfs_bmbt_lshift(
    -	xfs_btree_cur_t		*cur,
    -	int			level,
    -	int			*stat)		/* success/failure */
    -{
    -	int			error;		/* error return value */
    -#ifdef XFS_BMBT_TRACE
    -	static char		fname[] = "xfs_bmbt_lshift";
    -#endif
    -#ifdef DEBUG
    -	int			i;		/* loop counter */
    -#endif
    -	xfs_bmbt_key_t		key;		/* bmap btree key */
    -	xfs_buf_t		*lbp;		/* left buffer pointer */
    -	xfs_bmbt_block_t	*left;		/* left btree block */
    -	xfs_bmbt_key_t		*lkp=NULL;	/* left btree key */
    -	xfs_bmbt_ptr_t		*lpp;		/* left address pointer */
    -	int			lrecs;		/* left record count */
    -	xfs_bmbt_rec_t		*lrp=NULL;	/* left record pointer */
    -	xfs_mount_t		*mp;		/* file system mount point */
    -	xfs_buf_t		*rbp;		/* right buffer pointer */
    -	xfs_bmbt_block_t	*right;		/* right btree block */
    -	xfs_bmbt_key_t		*rkp=NULL;	/* right btree key */
    -	xfs_bmbt_ptr_t		*rpp=NULL;	/* right address pointer */
    -	xfs_bmbt_rec_t		*rrp=NULL;	/* right record pointer */
    -	int			rrecs;		/* right record count */
    -
    -	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
    -	XFS_BMBT_TRACE_ARGI(cur, level);
    -	if (level == cur->bc_nlevels - 1) {
    -		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -		*stat = 0;
    -		return 0;
    -	}
    -	rbp = cur->bc_bufs[level];
    -	right = XFS_BUF_TO_BMBT_BLOCK(rbp);
    -#ifdef DEBUG
    -	if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) {
    -		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -		return error;
    -	}
    -#endif
    -	if (be64_to_cpu(right->bb_leftsib) == NULLDFSBNO) {
    -		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -		*stat = 0;
    -		return 0;
    -	}
    -	if (cur->bc_ptrs[level] <= 1) {
    -		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -		*stat = 0;
    -		return 0;
    -	}
    -	mp = cur->bc_mp;
    -	if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, be64_to_cpu(right->bb_leftsib), 0,
    -			&lbp, XFS_BMAP_BTREE_REF))) {
    -		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -		return error;
    -	}
    -	left = XFS_BUF_TO_BMBT_BLOCK(lbp);
    -	if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) {
    -		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -		return error;
    -	}
    -	if (be16_to_cpu(left->bb_numrecs) == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) {
    -		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -		*stat = 0;
    -		return 0;
    -	}
    -	lrecs = be16_to_cpu(left->bb_numrecs) + 1;
    -	if (level > 0) {
    -		lkp = XFS_BMAP_KEY_IADDR(left, lrecs, cur);
    -		rkp = XFS_BMAP_KEY_IADDR(right, 1, cur);
    -		*lkp = *rkp;
    -		xfs_bmbt_log_keys(cur, lbp, lrecs, lrecs);
    -		lpp = XFS_BMAP_PTR_IADDR(left, lrecs, cur);
    -		rpp = XFS_BMAP_PTR_IADDR(right, 1, cur);
    -#ifdef DEBUG
    -		if ((error = xfs_btree_check_lptr(cur, INT_GET(*rpp, ARCH_CONVERT), level))) {
    -			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -			return error;
    -		}
    -#endif
    -		*lpp = *rpp; /* INT_: direct copy */
    -		xfs_bmbt_log_ptrs(cur, lbp, lrecs, lrecs);
    -	} else {
    -		lrp = XFS_BMAP_REC_IADDR(left, lrecs, cur);
    -		rrp = XFS_BMAP_REC_IADDR(right, 1, cur);
    -		*lrp = *rrp;
    -		xfs_bmbt_log_recs(cur, lbp, lrecs, lrecs);
    -	}
    -	left->bb_numrecs = cpu_to_be16(lrecs);
    -	xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS);
    -#ifdef DEBUG
    -	if (level > 0)
    -		xfs_btree_check_key(XFS_BTNUM_BMAP, lkp - 1, lkp);
    -	else
    -		xfs_btree_check_rec(XFS_BTNUM_BMAP, lrp - 1, lrp);
    -#endif
    -	rrecs = be16_to_cpu(right->bb_numrecs) - 1;
    -	right->bb_numrecs = cpu_to_be16(rrecs);
    -	xfs_bmbt_log_block(cur, rbp, XFS_BB_NUMRECS);
    -	if (level > 0) {
    -#ifdef DEBUG
    -		for (i = 0; i < rrecs; i++) {
    -			if ((error = xfs_btree_check_lptr(cur, INT_GET(rpp[i + 1], ARCH_CONVERT),
    -					level))) {
    -				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -				return error;
    -			}
    -		}
    -#endif
    -		memmove(rkp, rkp + 1, rrecs * sizeof(*rkp));
    -		memmove(rpp, rpp + 1, rrecs * sizeof(*rpp));
    -		xfs_bmbt_log_keys(cur, rbp, 1, rrecs);
    -		xfs_bmbt_log_ptrs(cur, rbp, 1, rrecs);
    -	} else {
    -		memmove(rrp, rrp + 1, rrecs * sizeof(*rrp));
    -		xfs_bmbt_log_recs(cur, rbp, 1, rrecs);
    -		INT_SET(key.br_startoff, ARCH_CONVERT,
    -			xfs_bmbt_disk_get_startoff(rrp));
    -		rkp = &key;
    -	}
    -	if ((error = xfs_bmbt_updkey(cur, rkp, level + 1))) {
    -		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -		return error;
    -	}
    -	cur->bc_ptrs[level]--;
    -	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -	*stat = 1;
    -	return 0;
    -}
    -
    -/*
    - * Move 1 record right from cur/level if possible.
    - * Update cur to reflect the new path.
    - */
    -STATIC int					/* error */
    -xfs_bmbt_rshift(
    -	xfs_btree_cur_t		*cur,
    -	int			level,
    -	int			*stat)		/* success/failure */
    -{
    -	int			error;		/* error return value */
    -#ifdef XFS_BMBT_TRACE
    -	static char		fname[] = "xfs_bmbt_rshift";
    -#endif
    -	int			i;		/* loop counter */
    -	xfs_bmbt_key_t		key;		/* bmap btree key */
    -	xfs_buf_t		*lbp;		/* left buffer pointer */
    -	xfs_bmbt_block_t	*left;		/* left btree block */
    -	xfs_bmbt_key_t		*lkp;		/* left btree key */
    -	xfs_bmbt_ptr_t		*lpp;		/* left address pointer */
    -	xfs_bmbt_rec_t		*lrp;		/* left record pointer */
    -	xfs_mount_t		*mp;		/* file system mount point */
    -	xfs_buf_t		*rbp;		/* right buffer pointer */
    -	xfs_bmbt_block_t	*right;		/* right btree block */
    -	xfs_bmbt_key_t		*rkp;		/* right btree key */
    -	xfs_bmbt_ptr_t		*rpp;		/* right address pointer */
    -	xfs_bmbt_rec_t		*rrp=NULL;	/* right record pointer */
    -	struct xfs_btree_cur	*tcur;		/* temporary btree cursor */
    -
    -	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
    -	XFS_BMBT_TRACE_ARGI(cur, level);
    -	if (level == cur->bc_nlevels - 1) {
    -		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -		*stat = 0;
    -		return 0;
    -	}
    -	lbp = cur->bc_bufs[level];
    -	left = XFS_BUF_TO_BMBT_BLOCK(lbp);
    -#ifdef DEBUG
    -	if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) {
    -		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -		return error;
    -	}
    -#endif
    -	if (be64_to_cpu(left->bb_rightsib) == NULLDFSBNO) {
    -		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -		*stat = 0;
    -		return 0;
    -	}
    -	if (cur->bc_ptrs[level] >= be16_to_cpu(left->bb_numrecs)) {
    -		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -		*stat = 0;
    -		return 0;
    -	}
    -	mp = cur->bc_mp;
    -	if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, be64_to_cpu(left->bb_rightsib), 0,
    -			&rbp, XFS_BMAP_BTREE_REF))) {
    -		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -		return error;
    -	}
    -	right = XFS_BUF_TO_BMBT_BLOCK(rbp);
    -	if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) {
    -		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -		return error;
    -	}
    -	if (be16_to_cpu(right->bb_numrecs) == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) {
    -		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -		*stat = 0;
    -		return 0;
    -	}
    -	if (level > 0) {
    -		lkp = XFS_BMAP_KEY_IADDR(left, be16_to_cpu(left->bb_numrecs), cur);
    -		lpp = XFS_BMAP_PTR_IADDR(left, be16_to_cpu(left->bb_numrecs), cur);
    -		rkp = XFS_BMAP_KEY_IADDR(right, 1, cur);
    -		rpp = XFS_BMAP_PTR_IADDR(right, 1, cur);
    -#ifdef DEBUG
    -		for (i = be16_to_cpu(right->bb_numrecs) - 1; i >= 0; i--) {
    -			if ((error = xfs_btree_check_lptr(cur, INT_GET(rpp[i], ARCH_CONVERT), level))) {
    -				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -				return error;
    -			}
    -		}
    -#endif
    -		memmove(rkp + 1, rkp, be16_to_cpu(right->bb_numrecs) * sizeof(*rkp));
    -		memmove(rpp + 1, rpp, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp));
    -#ifdef DEBUG
    -		if ((error = xfs_btree_check_lptr(cur, INT_GET(*lpp, ARCH_CONVERT), level))) {
    -			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -			return error;
    -		}
    -#endif
    -		*rkp = *lkp;
    -		*rpp = *lpp; /* INT_: direct copy */
    -		xfs_bmbt_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1);
    -		xfs_bmbt_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1);
    -	} else {
    -		lrp = XFS_BMAP_REC_IADDR(left, be16_to_cpu(left->bb_numrecs), cur);
    -		rrp = XFS_BMAP_REC_IADDR(right, 1, cur);
    -		memmove(rrp + 1, rrp, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp));
    -		*rrp = *lrp;
    -		xfs_bmbt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1);
    -		INT_SET(key.br_startoff, ARCH_CONVERT,
    -			xfs_bmbt_disk_get_startoff(rrp));
    -		rkp = &key;
    -	}
    -	be16_add(&left->bb_numrecs, -1);
    -	xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS);
    -	be16_add(&right->bb_numrecs, 1);
    -#ifdef DEBUG
    -	if (level > 0)
    -		xfs_btree_check_key(XFS_BTNUM_BMAP, rkp, rkp + 1);
    -	else
    -		xfs_btree_check_rec(XFS_BTNUM_BMAP, rrp, rrp + 1);
    -#endif
    -	xfs_bmbt_log_block(cur, rbp, XFS_BB_NUMRECS);
    -	if ((error = xfs_btree_dup_cursor(cur, &tcur))) {
    -		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -		return error;
    -	}
    -	i = xfs_btree_lastrec(tcur, level);
    -	XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -	if ((error = xfs_bmbt_increment(tcur, level, &i))) {
    -		XFS_BMBT_TRACE_CURSOR(tcur, ERROR);
    -		goto error1;
    -	}
    -	XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -	if ((error = xfs_bmbt_updkey(tcur, rkp, level + 1))) {
    -		XFS_BMBT_TRACE_CURSOR(tcur, ERROR);
    -		goto error1;
    -	}
    -	xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
    -	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -	*stat = 1;
    -	return 0;
    -error0:
    -	XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -error1:
    -	xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR);
    -	return error;
    -}
    -
    -/*
    - * Determine the extent state.
    - */
    -/* ARGSUSED */
    -STATIC xfs_exntst_t
    -xfs_extent_state(
    -	xfs_filblks_t		blks,
    -	int			extent_flag)
    -{
    -	if (extent_flag) {
    -		ASSERT(blks != 0);	/* saved for DMIG */
    -		return XFS_EXT_UNWRITTEN;
    -	}
    -	return XFS_EXT_NORM;
    -}
    -
    -
    -/*
    - * Split cur/level block in half.
    - * Return new block number and its first record (to be inserted into parent).
    - */
    -STATIC int					/* error */
    -xfs_bmbt_split(
    -	xfs_btree_cur_t		*cur,
    -	int			level,
    -	xfs_fsblock_t		*bnop,
    -	xfs_bmbt_key_t		*keyp,
    -	xfs_btree_cur_t		**curp,
    -	int			*stat)		/* success/failure */
    -{
    -	xfs_alloc_arg_t		args;		/* block allocation args */
    -	int			error;		/* error return value */
    -#ifdef XFS_BMBT_TRACE
    -	static char		fname[] = "xfs_bmbt_split";
    -#endif
    -	int			i;		/* loop counter */
    -	xfs_fsblock_t		lbno;		/* left sibling block number */
    -	xfs_buf_t		*lbp;		/* left buffer pointer */
    -	xfs_bmbt_block_t	*left;		/* left btree block */
    -	xfs_bmbt_key_t		*lkp;		/* left btree key */
    -	xfs_bmbt_ptr_t		*lpp;		/* left address pointer */
    -	xfs_bmbt_rec_t		*lrp;		/* left record pointer */
    -	xfs_buf_t		*rbp;		/* right buffer pointer */
    -	xfs_bmbt_block_t	*right;		/* right btree block */
    -	xfs_bmbt_key_t		*rkp;		/* right btree key */
    -	xfs_bmbt_ptr_t		*rpp;		/* right address pointer */
    -	xfs_bmbt_block_t	*rrblock;	/* right-right btree block */
    -	xfs_buf_t		*rrbp;		/* right-right buffer pointer */
    -	xfs_bmbt_rec_t		*rrp;		/* right record pointer */
    -
    -	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
    -	XFS_BMBT_TRACE_ARGIFK(cur, level, *bnop, keyp);
    -	args.tp = cur->bc_tp;
    -	args.mp = cur->bc_mp;
    -	lbp = cur->bc_bufs[level];
    -	lbno = XFS_DADDR_TO_FSB(args.mp, XFS_BUF_ADDR(lbp));
    -	left = XFS_BUF_TO_BMBT_BLOCK(lbp);
    -	args.fsbno = cur->bc_private.b.firstblock;
    -	if (args.fsbno == NULLFSBLOCK) {
    -		args.fsbno = lbno;
    -		args.type = XFS_ALLOCTYPE_START_BNO;
    -	} else if (cur->bc_private.b.flist->xbf_low)
    -		args.type = XFS_ALLOCTYPE_FIRST_AG;
    -	else
    -		args.type = XFS_ALLOCTYPE_NEAR_BNO;
    -	args.mod = args.minleft = args.alignment = args.total = args.isfl =
    -		args.userdata = args.minalignslop = 0;
    -	args.minlen = args.maxlen = args.prod = 1;
    -	args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL;
    -	if (!args.wasdel && xfs_trans_get_block_res(args.tp) == 0) {
    -		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -		return XFS_ERROR(ENOSPC);
    -	}
    -	if ((error = xfs_alloc_vextent(&args))) {
    -		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -		return error;
    -	}
    -	if (args.fsbno == NULLFSBLOCK) {
    -		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -		*stat = 0;
    -		return 0;
    -	}
    -	ASSERT(args.len == 1);
    -	cur->bc_private.b.firstblock = args.fsbno;
    -	cur->bc_private.b.allocated++;
    -	cur->bc_private.b.ip->i_d.di_nblocks++;
    -	xfs_trans_log_inode(args.tp, cur->bc_private.b.ip, XFS_ILOG_CORE);
    -	XFS_TRANS_MOD_DQUOT_BYINO(args.mp, args.tp, cur->bc_private.b.ip,
    -			XFS_TRANS_DQ_BCOUNT, 1L);
    -	rbp = xfs_btree_get_bufl(args.mp, args.tp, args.fsbno, 0);
    -	right = XFS_BUF_TO_BMBT_BLOCK(rbp);
    -#ifdef DEBUG
    -	if ((error = xfs_btree_check_lblock(cur, left, level, rbp))) {
    -		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -		return error;
    -	}
    -#endif
    -	right->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
    -	right->bb_level = left->bb_level;
    -	right->bb_numrecs = cpu_to_be16(be16_to_cpu(left->bb_numrecs) / 2);
    -	if ((be16_to_cpu(left->bb_numrecs) & 1) &&
    -	    cur->bc_ptrs[level] <= be16_to_cpu(right->bb_numrecs) + 1)
    -		be16_add(&right->bb_numrecs, 1);
    -	i = be16_to_cpu(left->bb_numrecs) - be16_to_cpu(right->bb_numrecs) + 1;
    -	if (level > 0) {
    -		lkp = XFS_BMAP_KEY_IADDR(left, i, cur);
    -		lpp = XFS_BMAP_PTR_IADDR(left, i, cur);
    -		rkp = XFS_BMAP_KEY_IADDR(right, 1, cur);
    -		rpp = XFS_BMAP_PTR_IADDR(right, 1, cur);
    -#ifdef DEBUG
    -		for (i = 0; i < be16_to_cpu(right->bb_numrecs); i++) {
    -			if ((error = xfs_btree_check_lptr(cur, INT_GET(lpp[i], ARCH_CONVERT), level))) {
    -				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -				return error;
    -			}
    -		}
    -#endif
    -		memcpy(rkp, lkp, be16_to_cpu(right->bb_numrecs) * sizeof(*rkp));
    -		memcpy(rpp, lpp, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp));
    -		xfs_bmbt_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));
    -		xfs_bmbt_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));
    -		keyp->br_startoff = INT_GET(rkp->br_startoff, ARCH_CONVERT);
    -	} else {
    -		lrp = XFS_BMAP_REC_IADDR(left, i, cur);
    -		rrp = XFS_BMAP_REC_IADDR(right, 1, cur);
    -		memcpy(rrp, lrp, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp));
    -		xfs_bmbt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));
    -		keyp->br_startoff = xfs_bmbt_disk_get_startoff(rrp);
    -	}
    -	be16_add(&left->bb_numrecs, -(be16_to_cpu(right->bb_numrecs)));
    -	right->bb_rightsib = left->bb_rightsib;
    -	left->bb_rightsib = cpu_to_be64(args.fsbno);
    -	right->bb_leftsib = cpu_to_be64(lbno);
    -	xfs_bmbt_log_block(cur, rbp, XFS_BB_ALL_BITS);
    -	xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB);
    -	if (be64_to_cpu(right->bb_rightsib) != NULLDFSBNO) {
    -		if ((error = xfs_btree_read_bufl(args.mp, args.tp,
    -				be64_to_cpu(right->bb_rightsib), 0, &rrbp,
    -				XFS_BMAP_BTREE_REF))) {
    -			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -			return error;
    -		}
    -		rrblock = XFS_BUF_TO_BMBT_BLOCK(rrbp);
    -		if ((error = xfs_btree_check_lblock(cur, rrblock, level, rrbp))) {
    -			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -			return error;
    -		}
    -		rrblock->bb_leftsib = cpu_to_be64(args.fsbno);
    -		xfs_bmbt_log_block(cur, rrbp, XFS_BB_LEFTSIB);
    -	}
    -	if (cur->bc_ptrs[level] > be16_to_cpu(left->bb_numrecs) + 1) {
    -		xfs_btree_setbuf(cur, level, rbp);
    -		cur->bc_ptrs[level] -= be16_to_cpu(left->bb_numrecs);
    -	}
    -	if (level + 1 < cur->bc_nlevels) {
    -		if ((error = xfs_btree_dup_cursor(cur, curp))) {
    -			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -			return error;
    -		}
    -		(*curp)->bc_ptrs[level + 1]++;
    -	}
    -	*bnop = args.fsbno;
    -	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -	*stat = 1;
    -	return 0;
    -}
    -
    -
    -/*
    - * Update keys for the record.
    - */
    -STATIC int
    -xfs_bmbt_updkey(
    -	xfs_btree_cur_t		*cur,
    -	xfs_bmbt_key_t		*keyp,	/* on-disk format */
    -	int			level)
    -{
    -	xfs_bmbt_block_t	*block;
    -	xfs_buf_t		*bp;
    -#ifdef DEBUG
    -	int			error;
    -#endif
    -#ifdef XFS_BMBT_TRACE
    -	static char		fname[] = "xfs_bmbt_updkey";
    -#endif
    -	xfs_bmbt_key_t		*kp;
    -	int			ptr;
    -
    -	ASSERT(level >= 1);
    -	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
    -	XFS_BMBT_TRACE_ARGIK(cur, level, keyp);
    -	for (ptr = 1; ptr == 1 && level < cur->bc_nlevels; level++) {
    -		block = xfs_bmbt_get_block(cur, level, &bp);
    -#ifdef DEBUG
    -		if ((error = xfs_btree_check_lblock(cur, block, level, bp))) {
    -			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -			return error;
    -		}
    -#endif
    -		ptr = cur->bc_ptrs[level];
    -		kp = XFS_BMAP_KEY_IADDR(block, ptr, cur);
    -		*kp = *keyp;
    -		xfs_bmbt_log_keys(cur, bp, ptr, ptr);
    -	}
    -	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -	return 0;
    -}
    -
    -/*
    - * Convert on-disk form of btree root to in-memory form.
    - */
    -void
    -xfs_bmdr_to_bmbt(
    -	xfs_bmdr_block_t	*dblock,
    -	int			dblocklen,
    -	xfs_bmbt_block_t	*rblock,
    -	int			rblocklen)
    -{
    -	int			dmxr;
    -	xfs_bmbt_key_t		*fkp;
    -	xfs_bmbt_ptr_t		*fpp;
    -	xfs_bmbt_key_t		*tkp;
    -	xfs_bmbt_ptr_t		*tpp;
    -
    -	rblock->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
    -	rblock->bb_level = dblock->bb_level;
    -	ASSERT(be16_to_cpu(rblock->bb_level) > 0);
    -	rblock->bb_numrecs = dblock->bb_numrecs;
    -	rblock->bb_leftsib = cpu_to_be64(NULLDFSBNO);
    -	rblock->bb_rightsib = cpu_to_be64(NULLDFSBNO);
    -	dmxr = (int)XFS_BTREE_BLOCK_MAXRECS(dblocklen, xfs_bmdr, 0);
    -	fkp = XFS_BTREE_KEY_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr);
    -	tkp = XFS_BMAP_BROOT_KEY_ADDR(rblock, 1, rblocklen);
    -	fpp = XFS_BTREE_PTR_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr);
    -	tpp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen);
    -	dmxr = be16_to_cpu(dblock->bb_numrecs);
    -	memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
    -	memcpy(tpp, fpp, sizeof(*fpp) * dmxr); /* INT_: direct copy */
    -}
    -
    -/*
    - * Decrement cursor by one record at the level.
    - * For nonzero levels the leaf-ward information is untouched.
    - */
    -int						/* error */
    -xfs_bmbt_decrement(
    -	xfs_btree_cur_t		*cur,
    -	int			level,
    -	int			*stat)		/* success/failure */
    -{
    -	xfs_bmbt_block_t	*block;
    -	xfs_buf_t		*bp;
    -	int			error;		/* error return value */
    -#ifdef XFS_BMBT_TRACE
    -	static char		fname[] = "xfs_bmbt_decrement";
    -#endif
    -	xfs_fsblock_t		fsbno;
    -	int			lev;
    -	xfs_mount_t		*mp;
    -	xfs_trans_t		*tp;
    -
    -	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
    -	XFS_BMBT_TRACE_ARGI(cur, level);
    -	ASSERT(level < cur->bc_nlevels);
    -	if (level < cur->bc_nlevels - 1)
    -		xfs_btree_readahead(cur, level, XFS_BTCUR_LEFTRA);
    -	if (--cur->bc_ptrs[level] > 0) {
    -		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -		*stat = 1;
    -		return 0;
    -	}
    -	block = xfs_bmbt_get_block(cur, level, &bp);
    -#ifdef DEBUG
    -	if ((error = xfs_btree_check_lblock(cur, block, level, bp))) {
    -		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -		return error;
    -	}
    -#endif
    -	if (be64_to_cpu(block->bb_leftsib) == NULLDFSBNO) {
    -		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -		*stat = 0;
    -		return 0;
    -	}
    -	for (lev = level + 1; lev < cur->bc_nlevels; lev++) {
    -		if (--cur->bc_ptrs[lev] > 0)
    -			break;
    -		if (lev < cur->bc_nlevels - 1)
    -			xfs_btree_readahead(cur, lev, XFS_BTCUR_LEFTRA);
    -	}
    -	if (lev == cur->bc_nlevels) {
    -		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -		*stat = 0;
    -		return 0;
    -	}
    -	tp = cur->bc_tp;
    -	mp = cur->bc_mp;
    -	for (block = xfs_bmbt_get_block(cur, lev, &bp); lev > level; ) {
    -		fsbno = INT_GET(*XFS_BMAP_PTR_IADDR(block, cur->bc_ptrs[lev], cur), ARCH_CONVERT);
    -		if ((error = xfs_btree_read_bufl(mp, tp, fsbno, 0, &bp,
    -				XFS_BMAP_BTREE_REF))) {
    -			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -			return error;
    -		}
    -		lev--;
    -		xfs_btree_setbuf(cur, lev, bp);
    -		block = XFS_BUF_TO_BMBT_BLOCK(bp);
    -		if ((error = xfs_btree_check_lblock(cur, block, lev, bp))) {
    -			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -			return error;
    -		}
    -		cur->bc_ptrs[lev] = be16_to_cpu(block->bb_numrecs);
    -	}
    -	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -	*stat = 1;
    -	return 0;
    -}
    -
    -/*
    - * Delete the record pointed to by cur.
    - */
    -int					/* error */
    -xfs_bmbt_delete(
    -	xfs_btree_cur_t	*cur,
    -	int		*stat)		/* success/failure */
    -{
    -	int		error;		/* error return value */
    -#ifdef XFS_BMBT_TRACE
    -	static char	fname[] = "xfs_bmbt_delete";
    -#endif
    -	int		i;
    -	int		level;
    -
    -	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
    -	for (level = 0, i = 2; i == 2; level++) {
    -		if ((error = xfs_bmbt_delrec(cur, level, &i))) {
    -			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -			return error;
    -		}
    -	}
    -	if (i == 0) {
    -		for (level = 1; level < cur->bc_nlevels; level++) {
    -			if (cur->bc_ptrs[level] == 0) {
    -				if ((error = xfs_bmbt_decrement(cur, level,
    -						&i))) {
    -					XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -					return error;
    -				}
    -				break;
    -			}
    -		}
    -	}
    -	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -	*stat = i;
    -	return 0;
    -}
    -
    -/*
    - * Convert a compressed bmap extent record to an uncompressed form.
    - * This code must be in sync with the routines xfs_bmbt_get_startoff,
    - * xfs_bmbt_get_startblock, xfs_bmbt_get_blockcount and xfs_bmbt_get_state.
    - */
    -
    -STATIC __inline__ void
    -__xfs_bmbt_get_all(
    -		__uint64_t l0,
    -		__uint64_t l1,
    -		xfs_bmbt_irec_t *s)
    -{
    -	int	ext_flag;
    -	xfs_exntst_t st;
    -
    -	ext_flag = (int)(l0 >> (64 - BMBT_EXNTFLAG_BITLEN));
    -	s->br_startoff = ((xfs_fileoff_t)l0 &
    -			   XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
    -#if XFS_BIG_BLKNOS
    -	s->br_startblock = (((xfs_fsblock_t)l0 & XFS_MASK64LO(9)) << 43) |
    -			   (((xfs_fsblock_t)l1) >> 21);
    -#else
    -#ifdef DEBUG
    -	{
    -		xfs_dfsbno_t	b;
    -
    -		b = (((xfs_dfsbno_t)l0 & XFS_MASK64LO(9)) << 43) |
    -		    (((xfs_dfsbno_t)l1) >> 21);
    -		ASSERT((b >> 32) == 0 || ISNULLDSTARTBLOCK(b));
    -		s->br_startblock = (xfs_fsblock_t)b;
    -	}
    -#else	/* !DEBUG */
    -	s->br_startblock = (xfs_fsblock_t)(((xfs_dfsbno_t)l1) >> 21);
    -#endif	/* DEBUG */
    -#endif	/* XFS_BIG_BLKNOS */
    -	s->br_blockcount = (xfs_filblks_t)(l1 & XFS_MASK64LO(21));
    -	/* This is xfs_extent_state() in-line */
    -	if (ext_flag) {
    -		ASSERT(s->br_blockcount != 0);	/* saved for DMIG */
    -		st = XFS_EXT_UNWRITTEN;
    -	} else
    -		st = XFS_EXT_NORM;
    -	s->br_state = st;
    -}
    -
    -void
    -xfs_bmbt_get_all(
    -	xfs_bmbt_rec_t	*r,
    -	xfs_bmbt_irec_t *s)
    -{
    -	__xfs_bmbt_get_all(r->l0, r->l1, s);
    -}
    -
    -/*
    - * Get the block pointer for the given level of the cursor.
    - * Fill in the buffer pointer, if applicable.
    - */
    -xfs_bmbt_block_t *
    -xfs_bmbt_get_block(
    -	xfs_btree_cur_t		*cur,
    -	int			level,
    -	xfs_buf_t		**bpp)
    -{
    -	xfs_ifork_t		*ifp;
    -	xfs_bmbt_block_t	*rval;
    -
    -	if (level < cur->bc_nlevels - 1) {
    -		*bpp = cur->bc_bufs[level];
    -		rval = XFS_BUF_TO_BMBT_BLOCK(*bpp);
    -	} else {
    -		*bpp = NULL;
    -		ifp = XFS_IFORK_PTR(cur->bc_private.b.ip,
    -			cur->bc_private.b.whichfork);
    -		rval = ifp->if_broot;
    -	}
    -	return rval;
    -}
    -
    -/*
    - * Extract the blockcount field from an in memory bmap extent record.
    - */
    -xfs_filblks_t
    -xfs_bmbt_get_blockcount(
    -	xfs_bmbt_rec_t	*r)
    -{
    -	return (xfs_filblks_t)(r->l1 & XFS_MASK64LO(21));
    -}
    -
    -/*
    - * Extract the startblock field from an in memory bmap extent record.
    - */
    -xfs_fsblock_t
    -xfs_bmbt_get_startblock(
    -	xfs_bmbt_rec_t	*r)
    -{
    -#if XFS_BIG_BLKNOS
    -	return (((xfs_fsblock_t)r->l0 & XFS_MASK64LO(9)) << 43) |
    -	       (((xfs_fsblock_t)r->l1) >> 21);
    -#else
    -#ifdef DEBUG
    -	xfs_dfsbno_t	b;
    -
    -	b = (((xfs_dfsbno_t)r->l0 & XFS_MASK64LO(9)) << 43) |
    -	    (((xfs_dfsbno_t)r->l1) >> 21);
    -	ASSERT((b >> 32) == 0 || ISNULLDSTARTBLOCK(b));
    -	return (xfs_fsblock_t)b;
    -#else	/* !DEBUG */
    -	return (xfs_fsblock_t)(((xfs_dfsbno_t)r->l1) >> 21);
    -#endif	/* DEBUG */
    -#endif	/* XFS_BIG_BLKNOS */
    -}
    -
    -/*
    - * Extract the startoff field from an in memory bmap extent record.
    - */
    -xfs_fileoff_t
    -xfs_bmbt_get_startoff(
    -	xfs_bmbt_rec_t	*r)
    -{
    -	return ((xfs_fileoff_t)r->l0 &
    -		 XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
    -}
    -
    -xfs_exntst_t
    -xfs_bmbt_get_state(
    -	xfs_bmbt_rec_t	*r)
    -{
    -	int	ext_flag;
    -
    -	ext_flag = (int)((r->l0) >> (64 - BMBT_EXNTFLAG_BITLEN));
    -	return xfs_extent_state(xfs_bmbt_get_blockcount(r),
    -				ext_flag);
    -}
    -
    -#ifndef XFS_NATIVE_HOST
    -/* Endian flipping versions of the bmbt extraction functions */
    -void
    -xfs_bmbt_disk_get_all(
    -	xfs_bmbt_rec_t	*r,
    -	xfs_bmbt_irec_t *s)
    -{
    -	__uint64_t	l0, l1;
    -
    -	l0 = INT_GET(r->l0, ARCH_CONVERT);
    -	l1 = INT_GET(r->l1, ARCH_CONVERT);
    -
    -	__xfs_bmbt_get_all(l0, l1, s);
    -}
    -
    -/*
    - * Extract the blockcount field from an on disk bmap extent record.
    - */
    -xfs_filblks_t
    -xfs_bmbt_disk_get_blockcount(
    -	xfs_bmbt_rec_t	*r)
    -{
    -	return (xfs_filblks_t)(INT_GET(r->l1, ARCH_CONVERT) & XFS_MASK64LO(21));
    -}
    -
    -/*
    - * Extract the startblock field from an on disk bmap extent record.
    - */
    -xfs_fsblock_t
    -xfs_bmbt_disk_get_startblock(
    -	xfs_bmbt_rec_t	*r)
    -{
    -#if XFS_BIG_BLKNOS
    -	return (((xfs_fsblock_t)INT_GET(r->l0, ARCH_CONVERT) & XFS_MASK64LO(9)) << 43) |
    -	       (((xfs_fsblock_t)INT_GET(r->l1, ARCH_CONVERT)) >> 21);
    -#else
    -#ifdef DEBUG
    -	xfs_dfsbno_t	b;
    -
    -	b = (((xfs_dfsbno_t)INT_GET(r->l0, ARCH_CONVERT) & XFS_MASK64LO(9)) << 43) |
    -	    (((xfs_dfsbno_t)INT_GET(r->l1, ARCH_CONVERT)) >> 21);
    -	ASSERT((b >> 32) == 0 || ISNULLDSTARTBLOCK(b));
    -	return (xfs_fsblock_t)b;
    -#else	/* !DEBUG */
    -	return (xfs_fsblock_t)(((xfs_dfsbno_t)INT_GET(r->l1, ARCH_CONVERT)) >> 21);
    -#endif	/* DEBUG */
    -#endif	/* XFS_BIG_BLKNOS */
    -}
    -
    -/*
    - * Extract the startoff field from a disk format bmap extent record.
    - */
    -xfs_fileoff_t
    -xfs_bmbt_disk_get_startoff(
    -	xfs_bmbt_rec_t	*r)
    -{
    -	return ((xfs_fileoff_t)INT_GET(r->l0, ARCH_CONVERT) &
    -		 XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
    -}
    -
    -xfs_exntst_t
    -xfs_bmbt_disk_get_state(
    -	xfs_bmbt_rec_t  *r)
    -{
    -	int	ext_flag;
    -
    -	ext_flag = (int)((INT_GET(r->l0, ARCH_CONVERT)) >> (64 - BMBT_EXNTFLAG_BITLEN));
    -	return xfs_extent_state(xfs_bmbt_disk_get_blockcount(r),
    -				ext_flag);
    -}
    -#endif /* XFS_NATIVE_HOST */
    -
    -
    -/*
    - * Increment cursor by one record at the level.
    - * For nonzero levels the leaf-ward information is untouched.
    - */
    -int						/* error */
    -xfs_bmbt_increment(
    -	xfs_btree_cur_t		*cur,
    -	int			level,
    -	int			*stat)		/* success/failure */
    -{
    -	xfs_bmbt_block_t	*block;
    -	xfs_buf_t		*bp;
    -	int			error;		/* error return value */
    -#ifdef XFS_BMBT_TRACE
    -	static char		fname[] = "xfs_bmbt_increment";
    -#endif
    -	xfs_fsblock_t		fsbno;
    -	int			lev;
    -	xfs_mount_t		*mp;
    -	xfs_trans_t		*tp;
    -
    -	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
    -	XFS_BMBT_TRACE_ARGI(cur, level);
    -	ASSERT(level < cur->bc_nlevels);
    -	if (level < cur->bc_nlevels - 1)
    -		xfs_btree_readahead(cur, level, XFS_BTCUR_RIGHTRA);
    -	block = xfs_bmbt_get_block(cur, level, &bp);
    -#ifdef DEBUG
    -	if ((error = xfs_btree_check_lblock(cur, block, level, bp))) {
    -		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -		return error;
    -	}
    -#endif
    -	if (++cur->bc_ptrs[level] <= be16_to_cpu(block->bb_numrecs)) {
    -		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -		*stat = 1;
    -		return 0;
    -	}
    -	if (be64_to_cpu(block->bb_rightsib) == NULLDFSBNO) {
    -		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -		*stat = 0;
    -		return 0;
    -	}
    -	for (lev = level + 1; lev < cur->bc_nlevels; lev++) {
    -		block = xfs_bmbt_get_block(cur, lev, &bp);
    -#ifdef DEBUG
    -		if ((error = xfs_btree_check_lblock(cur, block, lev, bp))) {
    -			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -			return error;
    -		}
    -#endif
    -		if (++cur->bc_ptrs[lev] <= be16_to_cpu(block->bb_numrecs))
    -			break;
    -		if (lev < cur->bc_nlevels - 1)
    -			xfs_btree_readahead(cur, lev, XFS_BTCUR_RIGHTRA);
    -	}
    -	if (lev == cur->bc_nlevels) {
    -		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -		*stat = 0;
    -		return 0;
    -	}
    -	tp = cur->bc_tp;
    -	mp = cur->bc_mp;
    -	for (block = xfs_bmbt_get_block(cur, lev, &bp); lev > level; ) {
    -		fsbno = INT_GET(*XFS_BMAP_PTR_IADDR(block, cur->bc_ptrs[lev], cur), ARCH_CONVERT);
    -		if ((error = xfs_btree_read_bufl(mp, tp, fsbno, 0, &bp,
    -				XFS_BMAP_BTREE_REF))) {
    -			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -			return error;
    -		}
    -		lev--;
    -		xfs_btree_setbuf(cur, lev, bp);
    -		block = XFS_BUF_TO_BMBT_BLOCK(bp);
    -		if ((error = xfs_btree_check_lblock(cur, block, lev, bp))) {
    -			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -			return error;
    -		}
    -		cur->bc_ptrs[lev] = 1;
    -	}
    -	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -	*stat = 1;
    -	return 0;
    -}
    -
    -/*
    - * Insert the current record at the point referenced by cur.
    - */
    -int					/* error */
    -xfs_bmbt_insert(
    -	xfs_btree_cur_t	*cur,
    -	int		*stat)		/* success/failure */
    -{
    -	int		error;		/* error return value */
    -#ifdef XFS_BMBT_TRACE
    -	static char	fname[] = "xfs_bmbt_insert";
    -#endif
    -	int		i;
    -	int		level;
    -	xfs_fsblock_t	nbno;
    -	xfs_btree_cur_t	*ncur;
    -	xfs_bmbt_rec_t	nrec;
    -	xfs_btree_cur_t	*pcur;
    -
    -	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
    -	level = 0;
    -	nbno = NULLFSBLOCK;
    -	xfs_bmbt_disk_set_all(&nrec, &cur->bc_rec.b);
    -	ncur = (xfs_btree_cur_t *)0;
    -	pcur = cur;
    -	do {
    -		if ((error = xfs_bmbt_insrec(pcur, level++, &nbno, &nrec, &ncur,
    -				&i))) {
    -			if (pcur != cur)
    -				xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR);
    -			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -			return error;
    -		}
    -		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -		if (pcur != cur && (ncur || nbno == NULLFSBLOCK)) {
    -			cur->bc_nlevels = pcur->bc_nlevels;
    -			cur->bc_private.b.allocated +=
    -				pcur->bc_private.b.allocated;
    -			pcur->bc_private.b.allocated = 0;
    -			ASSERT((cur->bc_private.b.firstblock != NULLFSBLOCK) ||
    -			       (cur->bc_private.b.ip->i_d.di_flags &
    -				XFS_DIFLAG_REALTIME));
    -			cur->bc_private.b.firstblock =
    -				pcur->bc_private.b.firstblock;
    -			ASSERT(cur->bc_private.b.flist ==
    -			       pcur->bc_private.b.flist);
    -			xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR);
    -		}
    -		if (ncur) {
    -			pcur = ncur;
    -			ncur = (xfs_btree_cur_t *)0;
    -		}
    -	} while (nbno != NULLFSBLOCK);
    -	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -	*stat = i;
    -	return 0;
    -error0:
    -	XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -	return error;
    -}
    -
    -/*
    - * Log fields from the btree block header.
    - */
    -void
    -xfs_bmbt_log_block(
    -	xfs_btree_cur_t		*cur,
    -	xfs_buf_t		*bp,
    -	int			fields)
    -{
    -	int			first;
    -#ifdef XFS_BMBT_TRACE
    -	static char		fname[] = "xfs_bmbt_log_block";
    -#endif
    -	int			last;
    -	xfs_trans_t		*tp;
    -	static const short	offsets[] = {
    -		offsetof(xfs_bmbt_block_t, bb_magic),
    -		offsetof(xfs_bmbt_block_t, bb_level),
    -		offsetof(xfs_bmbt_block_t, bb_numrecs),
    -		offsetof(xfs_bmbt_block_t, bb_leftsib),
    -		offsetof(xfs_bmbt_block_t, bb_rightsib),
    -		sizeof(xfs_bmbt_block_t)
    -	};
    -
    -	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
    -	XFS_BMBT_TRACE_ARGBI(cur, bp, fields);
    -	tp = cur->bc_tp;
    -	if (bp) {
    -		xfs_btree_offsets(fields, offsets, XFS_BB_NUM_BITS, &first,
    -				  &last);
    -		xfs_trans_log_buf(tp, bp, first, last);
    -	} else
    -		xfs_trans_log_inode(tp, cur->bc_private.b.ip,
    -			XFS_ILOG_FBROOT(cur->bc_private.b.whichfork));
    -	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -}
    -
    -/*
    - * Log record values from the btree block.
    - */
    -void
    -xfs_bmbt_log_recs(
    -	xfs_btree_cur_t		*cur,
    -	xfs_buf_t		*bp,
    -	int			rfirst,
    -	int			rlast)
    -{
    -	xfs_bmbt_block_t	*block;
    -	int			first;
    -#ifdef XFS_BMBT_TRACE
    -	static char		fname[] = "xfs_bmbt_log_recs";
    -#endif
    -	int			last;
    -	xfs_bmbt_rec_t		*rp;
    -	xfs_trans_t		*tp;
    -
    -	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
    -	XFS_BMBT_TRACE_ARGBII(cur, bp, rfirst, rlast);
    -	ASSERT(bp);
    -	tp = cur->bc_tp;
    -	block = XFS_BUF_TO_BMBT_BLOCK(bp);
    -	rp = XFS_BMAP_REC_DADDR(block, 1, cur);
    -	first = (int)((xfs_caddr_t)&rp[rfirst - 1] - (xfs_caddr_t)block);
    -	last = (int)(((xfs_caddr_t)&rp[rlast] - 1) - (xfs_caddr_t)block);
    -	xfs_trans_log_buf(tp, bp, first, last);
    -	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -}
    -
    -int					/* error */
    -xfs_bmbt_lookup_eq(
    -	xfs_btree_cur_t	*cur,
    -	xfs_fileoff_t	off,
    -	xfs_fsblock_t	bno,
    -	xfs_filblks_t	len,
    -	int		*stat)		/* success/failure */
    -{
    -	cur->bc_rec.b.br_startoff = off;
    -	cur->bc_rec.b.br_startblock = bno;
    -	cur->bc_rec.b.br_blockcount = len;
    -	return xfs_bmbt_lookup(cur, XFS_LOOKUP_EQ, stat);
    -}
    -
    -int					/* error */
    -xfs_bmbt_lookup_ge(
    -	xfs_btree_cur_t	*cur,
    -	xfs_fileoff_t	off,
    -	xfs_fsblock_t	bno,
    -	xfs_filblks_t	len,
    -	int		*stat)		/* success/failure */
    -{
    -	cur->bc_rec.b.br_startoff = off;
    -	cur->bc_rec.b.br_startblock = bno;
    -	cur->bc_rec.b.br_blockcount = len;
    -	return xfs_bmbt_lookup(cur, XFS_LOOKUP_GE, stat);
    -}
    -
    -/*
    - * Give the bmap btree a new root block.  Copy the old broot contents
    - * down into a real block and make the broot point to it.
    - */
    -int						/* error */
    -xfs_bmbt_newroot(
    -	xfs_btree_cur_t		*cur,		/* btree cursor */
    -	int			*logflags,	/* logging flags for inode */
    -	int			*stat)		/* return status - 0 fail */
    -{
    -	xfs_alloc_arg_t		args;		/* allocation arguments */
    -	xfs_bmbt_block_t	*block;		/* bmap btree block */
    -	xfs_buf_t		*bp;		/* buffer for block */
    -	xfs_bmbt_block_t	*cblock;	/* child btree block */
    -	xfs_bmbt_key_t		*ckp;		/* child key pointer */
    -	xfs_bmbt_ptr_t		*cpp;		/* child ptr pointer */
    -	int			error;		/* error return code */
    -#ifdef XFS_BMBT_TRACE
    -	static char		fname[] = "xfs_bmbt_newroot";
    -#endif
    -#ifdef DEBUG
    -	int			i;		/* loop counter */
    -#endif
    -	xfs_bmbt_key_t		*kp;		/* pointer to bmap btree key */
    -	int			level;		/* btree level */
    -	xfs_bmbt_ptr_t		*pp;		/* pointer to bmap block addr */
    -
    -	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
    -	level = cur->bc_nlevels - 1;
    -	block = xfs_bmbt_get_block(cur, level, &bp);
    -	/*
    -	 * Copy the root into a real block.
    -	 */
    -	args.mp = cur->bc_mp;
    -	pp = XFS_BMAP_PTR_IADDR(block, 1, cur);
    -	args.tp = cur->bc_tp;
    -	args.fsbno = cur->bc_private.b.firstblock;
    -	args.mod = args.minleft = args.alignment = args.total = args.isfl =
    -		args.userdata = args.minalignslop = 0;
    -	args.minlen = args.maxlen = args.prod = 1;
    -	args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL;
    -	if (args.fsbno == NULLFSBLOCK) {
    -#ifdef DEBUG
    -		if ((error = xfs_btree_check_lptr(cur, INT_GET(*pp, ARCH_CONVERT), level))) {
    -			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -			return error;
    -		}
    -#endif
    -		args.fsbno = INT_GET(*pp, ARCH_CONVERT);
    -		args.type = XFS_ALLOCTYPE_START_BNO;
    -	} else if (args.wasdel)
    -		args.type = XFS_ALLOCTYPE_FIRST_AG;
    -	else
    -		args.type = XFS_ALLOCTYPE_NEAR_BNO;
    -	if ((error = xfs_alloc_vextent(&args))) {
    -		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -		return error;
    -	}
    -	if (args.fsbno == NULLFSBLOCK) {
    -		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -		*stat = 0;
    -		return 0;
    -	}
    -	ASSERT(args.len == 1);
    -	cur->bc_private.b.firstblock = args.fsbno;
    -	cur->bc_private.b.allocated++;
    -	cur->bc_private.b.ip->i_d.di_nblocks++;
    -	XFS_TRANS_MOD_DQUOT_BYINO(args.mp, args.tp, cur->bc_private.b.ip,
    -			  XFS_TRANS_DQ_BCOUNT, 1L);
    -	bp = xfs_btree_get_bufl(args.mp, cur->bc_tp, args.fsbno, 0);
    -	cblock = XFS_BUF_TO_BMBT_BLOCK(bp);
    -	*cblock = *block;
    -	be16_add(&block->bb_level, 1);
    -	block->bb_numrecs = cpu_to_be16(1);
    -	cur->bc_nlevels++;
    -	cur->bc_ptrs[level + 1] = 1;
    -	kp = XFS_BMAP_KEY_IADDR(block, 1, cur);
    -	ckp = XFS_BMAP_KEY_IADDR(cblock, 1, cur);
    -	memcpy(ckp, kp, be16_to_cpu(cblock->bb_numrecs) * sizeof(*kp));
    -	cpp = XFS_BMAP_PTR_IADDR(cblock, 1, cur);
    -#ifdef DEBUG
    -	for (i = 0; i < be16_to_cpu(cblock->bb_numrecs); i++) {
    -		if ((error = xfs_btree_check_lptr(cur, INT_GET(pp[i], ARCH_CONVERT), level))) {
    -			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -			return error;
    -		}
    -	}
    -#endif
    -	memcpy(cpp, pp, be16_to_cpu(cblock->bb_numrecs) * sizeof(*pp));
    -#ifdef DEBUG
    -	if ((error = xfs_btree_check_lptr(cur, (xfs_bmbt_ptr_t)args.fsbno,
    -			level))) {
    -		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -		return error;
    -	}
    -#endif
    -	INT_SET(*pp, ARCH_CONVERT, args.fsbno);
    -	xfs_iroot_realloc(cur->bc_private.b.ip, 1 - be16_to_cpu(cblock->bb_numrecs),
    -		cur->bc_private.b.whichfork);
    -	xfs_btree_setbuf(cur, level, bp);
    -	/*
    -	 * Do all this logging at the end so that
    -	 * the root is at the right level.
    -	 */
    -	xfs_bmbt_log_block(cur, bp, XFS_BB_ALL_BITS);
    -	xfs_bmbt_log_keys(cur, bp, 1, be16_to_cpu(cblock->bb_numrecs));
    -	xfs_bmbt_log_ptrs(cur, bp, 1, be16_to_cpu(cblock->bb_numrecs));
    -	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -	*logflags |=
    -		XFS_ILOG_CORE | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork);
    -	*stat = 1;
    -	return 0;
    -}
    -
    -/*
    - * Set all the fields in a bmap extent record from the uncompressed form.
    - */
    -void
    -xfs_bmbt_set_all(
    -	xfs_bmbt_rec_t	*r,
    -	xfs_bmbt_irec_t	*s)
    -{
    -	int	extent_flag;
    -
    -	ASSERT((s->br_state == XFS_EXT_NORM) ||
    -		(s->br_state == XFS_EXT_UNWRITTEN));
    -	extent_flag = (s->br_state == XFS_EXT_NORM) ? 0 : 1;
    -	ASSERT((s->br_startoff & XFS_MASK64HI(9)) == 0);
    -	ASSERT((s->br_blockcount & XFS_MASK64HI(43)) == 0);
    -#if XFS_BIG_BLKNOS
    -	ASSERT((s->br_startblock & XFS_MASK64HI(12)) == 0);
    -	r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
    -		 ((xfs_bmbt_rec_base_t)s->br_startoff << 9) |
    -		 ((xfs_bmbt_rec_base_t)s->br_startblock >> 43);
    -	r->l1 = ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
    -		 ((xfs_bmbt_rec_base_t)s->br_blockcount &
    -		 (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
    -#else	/* !XFS_BIG_BLKNOS */
    -	if (ISNULLSTARTBLOCK(s->br_startblock)) {
    -		r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
    -			((xfs_bmbt_rec_base_t)s->br_startoff << 9) |
    -			  (xfs_bmbt_rec_base_t)XFS_MASK64LO(9);
    -		r->l1 = XFS_MASK64HI(11) |
    -			  ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
    -			  ((xfs_bmbt_rec_base_t)s->br_blockcount &
    -			   (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
    -	} else {
    -		r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
    -			((xfs_bmbt_rec_base_t)s->br_startoff << 9);
    -		r->l1 = ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
    -			  ((xfs_bmbt_rec_base_t)s->br_blockcount &
    -			   (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
    -	}
    -#endif	/* XFS_BIG_BLKNOS */
    -}
    -
    -/*
    - * Set all the fields in a bmap extent record from the arguments.
    - */
    -void
    -xfs_bmbt_set_allf(
    -	xfs_bmbt_rec_t	*r,
    -	xfs_fileoff_t	o,
    -	xfs_fsblock_t	b,
    -	xfs_filblks_t	c,
    -	xfs_exntst_t	v)
    -{
    -	int	extent_flag;
    -
    -	ASSERT((v == XFS_EXT_NORM) || (v == XFS_EXT_UNWRITTEN));
    -	extent_flag = (v == XFS_EXT_NORM) ? 0 : 1;
    -	ASSERT((o & XFS_MASK64HI(64-BMBT_STARTOFF_BITLEN)) == 0);
    -	ASSERT((c & XFS_MASK64HI(64-BMBT_BLOCKCOUNT_BITLEN)) == 0);
    -#if XFS_BIG_BLKNOS
    -	ASSERT((b & XFS_MASK64HI(64-BMBT_STARTBLOCK_BITLEN)) == 0);
    -	r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
    -		((xfs_bmbt_rec_base_t)o << 9) |
    -		((xfs_bmbt_rec_base_t)b >> 43);
    -	r->l1 = ((xfs_bmbt_rec_base_t)b << 21) |
    -		((xfs_bmbt_rec_base_t)c &
    -		(xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
    -#else	/* !XFS_BIG_BLKNOS */
    -	if (ISNULLSTARTBLOCK(b)) {
    -		r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
    -			((xfs_bmbt_rec_base_t)o << 9) |
    -			 (xfs_bmbt_rec_base_t)XFS_MASK64LO(9);
    -		r->l1 = XFS_MASK64HI(11) |
    -			  ((xfs_bmbt_rec_base_t)b << 21) |
    -			  ((xfs_bmbt_rec_base_t)c &
    -			   (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
    -	} else {
    -		r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
    -			((xfs_bmbt_rec_base_t)o << 9);
    -		r->l1 = ((xfs_bmbt_rec_base_t)b << 21) |
    -			 ((xfs_bmbt_rec_base_t)c &
    -			 (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
    -	}
    -#endif	/* XFS_BIG_BLKNOS */
    -}
    -
    -#ifndef XFS_NATIVE_HOST
    -/*
    - * Set all the fields in a bmap extent record from the uncompressed form.
    - */
    -void
    -xfs_bmbt_disk_set_all(
    -	xfs_bmbt_rec_t	*r,
    -	xfs_bmbt_irec_t *s)
    -{
    -	int	extent_flag;
    -
    -	ASSERT((s->br_state == XFS_EXT_NORM) ||
    -		(s->br_state == XFS_EXT_UNWRITTEN));
    -	extent_flag = (s->br_state == XFS_EXT_NORM) ? 0 : 1;
    -	ASSERT((s->br_startoff & XFS_MASK64HI(9)) == 0);
    -	ASSERT((s->br_blockcount & XFS_MASK64HI(43)) == 0);
    -#if XFS_BIG_BLKNOS
    -	ASSERT((s->br_startblock & XFS_MASK64HI(12)) == 0);
    -	INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
    -		  ((xfs_bmbt_rec_base_t)s->br_startoff << 9) |
    -		  ((xfs_bmbt_rec_base_t)s->br_startblock >> 43));
    -	INT_SET(r->l1, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
    -		  ((xfs_bmbt_rec_base_t)s->br_blockcount &
    -		   (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
    -#else	/* !XFS_BIG_BLKNOS */
    -	if (ISNULLSTARTBLOCK(s->br_startblock)) {
    -		INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
    -			((xfs_bmbt_rec_base_t)s->br_startoff << 9) |
    -			  (xfs_bmbt_rec_base_t)XFS_MASK64LO(9));
    -		INT_SET(r->l1, ARCH_CONVERT, XFS_MASK64HI(11) |
    -			  ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
    -			  ((xfs_bmbt_rec_base_t)s->br_blockcount &
    -			   (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
    -	} else {
    -		INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
    -			((xfs_bmbt_rec_base_t)s->br_startoff << 9));
    -		INT_SET(r->l1, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
    -			  ((xfs_bmbt_rec_base_t)s->br_blockcount &
    -			   (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
    -	}
    -#endif	/* XFS_BIG_BLKNOS */
    -}
    -
    -/*
    - * Set all the fields in a disk format bmap extent record from the arguments.
    - */
    -void
    -xfs_bmbt_disk_set_allf(
    -	xfs_bmbt_rec_t	*r,
    -	xfs_fileoff_t	o,
    -	xfs_fsblock_t	b,
    -	xfs_filblks_t	c,
    -	xfs_exntst_t	v)
    -{
    -	int	extent_flag;
    -
    -	ASSERT((v == XFS_EXT_NORM) || (v == XFS_EXT_UNWRITTEN));
    -	extent_flag = (v == XFS_EXT_NORM) ? 0 : 1;
    -	ASSERT((o & XFS_MASK64HI(64-BMBT_STARTOFF_BITLEN)) == 0);
    -	ASSERT((c & XFS_MASK64HI(64-BMBT_BLOCKCOUNT_BITLEN)) == 0);
    -#if XFS_BIG_BLKNOS
    -	ASSERT((b & XFS_MASK64HI(64-BMBT_STARTBLOCK_BITLEN)) == 0);
    -	INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
    -		((xfs_bmbt_rec_base_t)o << 9) |
    -		((xfs_bmbt_rec_base_t)b >> 43));
    -	INT_SET(r->l1, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)b << 21) |
    -		  ((xfs_bmbt_rec_base_t)c &
    -		   (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
    -#else	/* !XFS_BIG_BLKNOS */
    -	if (ISNULLSTARTBLOCK(b)) {
    -		INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
    -			((xfs_bmbt_rec_base_t)o << 9) |
    -			 (xfs_bmbt_rec_base_t)XFS_MASK64LO(9));
    -		INT_SET(r->l1, ARCH_CONVERT, XFS_MASK64HI(11) |
    -			  ((xfs_bmbt_rec_base_t)b << 21) |
    -			  ((xfs_bmbt_rec_base_t)c &
    -			   (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
    -	} else {
    -		INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
    -			((xfs_bmbt_rec_base_t)o << 9));
    -		INT_SET(r->l1, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)b << 21) |
    -			  ((xfs_bmbt_rec_base_t)c &
    -			   (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
    -	}
    -#endif	/* XFS_BIG_BLKNOS */
    -}
    -#endif /* XFS_NATIVE_HOST */
    -
    -/*
    - * Set the blockcount field in a bmap extent record.
    - */
    -void
    -xfs_bmbt_set_blockcount(
    -	xfs_bmbt_rec_t	*r,
    -	xfs_filblks_t	v)
    -{
    -	ASSERT((v & XFS_MASK64HI(43)) == 0);
    -	r->l1 = (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64HI(43)) |
    -		  (xfs_bmbt_rec_base_t)(v & XFS_MASK64LO(21));
    -}
    -
    -/*
    - * Set the startblock field in a bmap extent record.
    - */
    -void
    -xfs_bmbt_set_startblock(
    -	xfs_bmbt_rec_t	*r,
    -	xfs_fsblock_t	v)
    -{
    -#if XFS_BIG_BLKNOS
    -	ASSERT((v & XFS_MASK64HI(12)) == 0);
    -	r->l0 = (r->l0 & (xfs_bmbt_rec_base_t)XFS_MASK64HI(55)) |
    -		  (xfs_bmbt_rec_base_t)(v >> 43);
    -	r->l1 = (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)) |
    -		  (xfs_bmbt_rec_base_t)(v << 21);
    -#else	/* !XFS_BIG_BLKNOS */
    -	if (ISNULLSTARTBLOCK(v)) {
    -		r->l0 |= (xfs_bmbt_rec_base_t)XFS_MASK64LO(9);
    -		r->l1 = (xfs_bmbt_rec_base_t)XFS_MASK64HI(11) |
    -			  ((xfs_bmbt_rec_base_t)v << 21) |
    -			  (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
    -	} else {
    -		r->l0 &= ~(xfs_bmbt_rec_base_t)XFS_MASK64LO(9);
    -		r->l1 = ((xfs_bmbt_rec_base_t)v << 21) |
    -			  (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
    -	}
    -#endif	/* XFS_BIG_BLKNOS */
    -}
    -
    -/*
    - * Set the startoff field in a bmap extent record.
    - */
    -void
    -xfs_bmbt_set_startoff(
    -	xfs_bmbt_rec_t	*r,
    -	xfs_fileoff_t	v)
    -{
    -	ASSERT((v & XFS_MASK64HI(9)) == 0);
    -	r->l0 = (r->l0 & (xfs_bmbt_rec_base_t) XFS_MASK64HI(1)) |
    -		((xfs_bmbt_rec_base_t)v << 9) |
    -		  (r->l0 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(9));
    -}
    -
    -/*
    - * Set the extent state field in a bmap extent record.
    - */
    -void
    -xfs_bmbt_set_state(
    -	xfs_bmbt_rec_t	*r,
    -	xfs_exntst_t	v)
    -{
    -	ASSERT(v == XFS_EXT_NORM || v == XFS_EXT_UNWRITTEN);
    -	if (v == XFS_EXT_NORM)
    -		r->l0 &= XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN);
    -	else
    -		r->l0 |= XFS_MASK64HI(BMBT_EXNTFLAG_BITLEN);
    -}
    -
    -/*
    - * Convert in-memory form of btree root to on-disk form.
    - */
    -void
    -xfs_bmbt_to_bmdr(
    -	xfs_bmbt_block_t	*rblock,
    -	int			rblocklen,
    -	xfs_bmdr_block_t	*dblock,
    -	int			dblocklen)
    -{
    -	int			dmxr;
    -	xfs_bmbt_key_t		*fkp;
    -	xfs_bmbt_ptr_t		*fpp;
    -	xfs_bmbt_key_t		*tkp;
    -	xfs_bmbt_ptr_t		*tpp;
    -
    -	ASSERT(be32_to_cpu(rblock->bb_magic) == XFS_BMAP_MAGIC);
    -	ASSERT(be64_to_cpu(rblock->bb_leftsib) == NULLDFSBNO);
    -	ASSERT(be64_to_cpu(rblock->bb_rightsib) == NULLDFSBNO);
    -	ASSERT(be16_to_cpu(rblock->bb_level) > 0);
    -	dblock->bb_level = rblock->bb_level;
    -	dblock->bb_numrecs = rblock->bb_numrecs;
    -	dmxr = (int)XFS_BTREE_BLOCK_MAXRECS(dblocklen, xfs_bmdr, 0);
    -	fkp = XFS_BMAP_BROOT_KEY_ADDR(rblock, 1, rblocklen);
    -	tkp = XFS_BTREE_KEY_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr);
    -	fpp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen);
    -	tpp = XFS_BTREE_PTR_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr);
    -	dmxr = be16_to_cpu(dblock->bb_numrecs);
    -	memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
    -	memcpy(tpp, fpp, sizeof(*fpp) * dmxr); /* INT_: direct copy */
    -}
    -
    -/*
    - * Update the record to the passed values.
    - */
    -int
    -xfs_bmbt_update(
    -	xfs_btree_cur_t		*cur,
    -	xfs_fileoff_t		off,
    -	xfs_fsblock_t		bno,
    -	xfs_filblks_t		len,
    -	xfs_exntst_t		state)
    -{
    -	xfs_bmbt_block_t	*block;
    -	xfs_buf_t		*bp;
    -	int			error;
    -#ifdef XFS_BMBT_TRACE
    -	static char		fname[] = "xfs_bmbt_update";
    -#endif
    -	xfs_bmbt_key_t		key;
    -	int			ptr;
    -	xfs_bmbt_rec_t		*rp;
    -
    -	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
    -	XFS_BMBT_TRACE_ARGFFFI(cur, (xfs_dfiloff_t)off, (xfs_dfsbno_t)bno,
    -		(xfs_dfilblks_t)len, (int)state);
    -	block = xfs_bmbt_get_block(cur, 0, &bp);
    -#ifdef DEBUG
    -	if ((error = xfs_btree_check_lblock(cur, block, 0, bp))) {
    -		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -		return error;
    -	}
    -#endif
    -	ptr = cur->bc_ptrs[0];
    -	rp = XFS_BMAP_REC_IADDR(block, ptr, cur);
    -	xfs_bmbt_disk_set_allf(rp, off, bno, len, state);
    -	xfs_bmbt_log_recs(cur, bp, ptr, ptr);
    -	if (ptr > 1) {
    -		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -		return 0;
    -	}
    -	INT_SET(key.br_startoff, ARCH_CONVERT, off);
    -	if ((error = xfs_bmbt_updkey(cur, &key, 1))) {
    -		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
    -		return error;
    -	}
    -	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
    -	return 0;
    -}
    -
    -/*
    - * Check extent records, which have just been read, for
    - * any bit in the extent flag field. ASSERT on debug
    - * kernels, as this condition should not occur.
    - * Return an error condition (1) if any flags found,
    - * otherwise return 0.
    - */
    -
    -int
    -xfs_check_nostate_extents(
    -	xfs_ifork_t		*ifp,
    -	xfs_extnum_t		idx,
    -	xfs_extnum_t		num)
    -{
    -	xfs_bmbt_rec_t		*ep;
    -
    -	for (; num > 0; num--, idx++) {
    -		ep = xfs_iext_get_ext(ifp, idx);
    -		if ((ep->l0 >>
    -		     (64 - BMBT_EXNTFLAG_BITLEN)) != 0) {
    -			ASSERT(0);
    -			return 1;
    -		}
    -	}
    -	return 0;
    -}
    diff --git a/sys/gnu/fs/xfs/xfs_bmap_btree.h b/sys/gnu/fs/xfs/xfs_bmap_btree.h
    deleted file mode 100644
    index 6478cfa0e53..00000000000
    --- a/sys/gnu/fs/xfs/xfs_bmap_btree.h
    +++ /dev/null
    @@ -1,377 +0,0 @@
    -/*
    - * Copyright (c) 2000,2002-2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_BMAP_BTREE_H__
    -#define __XFS_BMAP_BTREE_H__
    -
    -#define XFS_BMAP_MAGIC	0x424d4150	/* 'BMAP' */
    -
    -struct xfs_btree_cur;
    -struct xfs_btree_lblock;
    -struct xfs_mount;
    -struct xfs_inode;
    -
    -/*
    - * Bmap root header, on-disk form only.
    - */
    -typedef struct xfs_bmdr_block {
    -	__be16		bb_level;	/* 0 is a leaf */
    -	__be16		bb_numrecs;	/* current # of data records */
    -} xfs_bmdr_block_t;
    -
    -/*
    - * Bmap btree record and extent descriptor.
    - * For 32-bit kernels,
    - *  l0:31 is an extent flag (value 1 indicates non-normal).
    - *  l0:0-30 and l1:9-31 are startoff.
    - *  l1:0-8, l2:0-31, and l3:21-31 are startblock.
    - *  l3:0-20 are blockcount.
    - * For 64-bit kernels,
    - *  l0:63 is an extent flag (value 1 indicates non-normal).
    - *  l0:9-62 are startoff.
    - *  l0:0-8 and l1:21-63 are startblock.
    - *  l1:0-20 are blockcount.
    - */
    -
    -#ifndef XFS_NATIVE_HOST
    -
    -#define BMBT_TOTAL_BITLEN	128	/* 128 bits, 16 bytes */
    -#define BMBT_EXNTFLAG_BITOFF	0
    -#define BMBT_EXNTFLAG_BITLEN	1
    -#define BMBT_STARTOFF_BITOFF	(BMBT_EXNTFLAG_BITOFF + BMBT_EXNTFLAG_BITLEN)
    -#define BMBT_STARTOFF_BITLEN	54
    -#define BMBT_STARTBLOCK_BITOFF	(BMBT_STARTOFF_BITOFF + BMBT_STARTOFF_BITLEN)
    -#define BMBT_STARTBLOCK_BITLEN	52
    -#define BMBT_BLOCKCOUNT_BITOFF	\
    -	(BMBT_STARTBLOCK_BITOFF + BMBT_STARTBLOCK_BITLEN)
    -#define BMBT_BLOCKCOUNT_BITLEN	(BMBT_TOTAL_BITLEN - BMBT_BLOCKCOUNT_BITOFF)
    -
    -#else
    -
    -#define BMBT_TOTAL_BITLEN	128	/* 128 bits, 16 bytes */
    -#define BMBT_EXNTFLAG_BITOFF	63
    -#define BMBT_EXNTFLAG_BITLEN	1
    -#define BMBT_STARTOFF_BITOFF	(BMBT_EXNTFLAG_BITOFF - BMBT_STARTOFF_BITLEN)
    -#define BMBT_STARTOFF_BITLEN	54
    -#define BMBT_STARTBLOCK_BITOFF	85 /* 128 - 43 (other 9 is in first word) */
    -#define BMBT_STARTBLOCK_BITLEN	52
    -#define BMBT_BLOCKCOUNT_BITOFF	64 /* Start of second 64 bit container */
    -#define BMBT_BLOCKCOUNT_BITLEN	21
    -
    -#endif /* XFS_NATIVE_HOST */
    -
    -
    -#define BMBT_USE_64	1
    -
    -typedef struct xfs_bmbt_rec_32
    -{
    -	__uint32_t		l0, l1, l2, l3;
    -} xfs_bmbt_rec_32_t;
    -typedef struct xfs_bmbt_rec_64
    -{
    -	__uint64_t		l0, l1;
    -} xfs_bmbt_rec_64_t;
    -
    -typedef __uint64_t	xfs_bmbt_rec_base_t;	/* use this for casts */
    -typedef xfs_bmbt_rec_64_t xfs_bmbt_rec_t, xfs_bmdr_rec_t;
    -
    -/*
    - * Values and macros for delayed-allocation startblock fields.
    - */
    -#define STARTBLOCKVALBITS	17
    -#define STARTBLOCKMASKBITS	(15 + XFS_BIG_BLKNOS * 20)
    -#define DSTARTBLOCKMASKBITS	(15 + 20)
    -#define STARTBLOCKMASK		\
    -	(((((xfs_fsblock_t)1) << STARTBLOCKMASKBITS) - 1) << STARTBLOCKVALBITS)
    -#define DSTARTBLOCKMASK		\
    -	(((((xfs_dfsbno_t)1) << DSTARTBLOCKMASKBITS) - 1) << STARTBLOCKVALBITS)
    -
    -#define ISNULLSTARTBLOCK(x)	isnullstartblock(x)
    -static inline int isnullstartblock(xfs_fsblock_t x)
    -{
    -	return ((x) & STARTBLOCKMASK) == STARTBLOCKMASK;
    -}
    -
    -#define ISNULLDSTARTBLOCK(x)	isnulldstartblock(x)
    -static inline int isnulldstartblock(xfs_dfsbno_t x)
    -{
    -	return ((x) & DSTARTBLOCKMASK) == DSTARTBLOCKMASK;
    -}
    -
    -#define NULLSTARTBLOCK(k)	nullstartblock(k)
    -static inline xfs_fsblock_t nullstartblock(int k)
    -{
    -	ASSERT(k < (1 << STARTBLOCKVALBITS));
    -	return STARTBLOCKMASK | (k);
    -}
    -
    -#define STARTBLOCKVAL(x)	startblockval(x)
    -static inline xfs_filblks_t startblockval(xfs_fsblock_t x)
    -{
    -	return (xfs_filblks_t)((x) & ~STARTBLOCKMASK);
    -}
    -
    -/*
    - * Possible extent formats.
    - */
    -typedef enum {
    -	XFS_EXTFMT_NOSTATE = 0,
    -	XFS_EXTFMT_HASSTATE
    -} xfs_exntfmt_t;
    -
    -/*
    - * Possible extent states.
    - */
    -typedef enum {
    -	XFS_EXT_NORM, XFS_EXT_UNWRITTEN,
    -	XFS_EXT_DMAPI_OFFLINE, XFS_EXT_INVALID
    -} xfs_exntst_t;
    -
    -/*
    - * Extent state and extent format macros.
    - */
    -#define XFS_EXTFMT_INODE(x)	\
    -	(XFS_SB_VERSION_HASEXTFLGBIT(&((x)->i_mount->m_sb)) ? \
    -		XFS_EXTFMT_HASSTATE : XFS_EXTFMT_NOSTATE)
    -#define ISUNWRITTEN(x)	((x)->br_state == XFS_EXT_UNWRITTEN)
    -
    -/*
    - * Incore version of above.
    - */
    -typedef struct xfs_bmbt_irec
    -{
    -	xfs_fileoff_t	br_startoff;	/* starting file offset */
    -	xfs_fsblock_t	br_startblock;	/* starting block number */
    -	xfs_filblks_t	br_blockcount;	/* number of blocks */
    -	xfs_exntst_t	br_state;	/* extent state */
    -} xfs_bmbt_irec_t;
    -
    -/*
    - * Key structure for non-leaf levels of the tree.
    - */
    -typedef struct xfs_bmbt_key
    -{
    -	xfs_dfiloff_t	br_startoff;	/* starting file offset */
    -} xfs_bmbt_key_t, xfs_bmdr_key_t;
    -
    -typedef xfs_dfsbno_t xfs_bmbt_ptr_t, xfs_bmdr_ptr_t;	/* btree pointer type */
    -					/* btree block header type */
    -typedef struct xfs_btree_lblock xfs_bmbt_block_t;
    -
    -#define XFS_BUF_TO_BMBT_BLOCK(bp)	((xfs_bmbt_block_t *)XFS_BUF_PTR(bp))
    -
    -#define XFS_BMAP_IBLOCK_SIZE(lev,cur)	(1 << (cur)->bc_blocklog)
    -#define XFS_BMAP_RBLOCK_DSIZE(lev,cur)	((cur)->bc_private.b.forksize)
    -#define XFS_BMAP_RBLOCK_ISIZE(lev,cur)	\
    -	((int)XFS_IFORK_PTR((cur)->bc_private.b.ip, \
    -		    (cur)->bc_private.b.whichfork)->if_broot_bytes)
    -
    -#define XFS_BMAP_BLOCK_DSIZE(lev,cur)	\
    -	(((lev) == (cur)->bc_nlevels - 1 ? \
    -		XFS_BMAP_RBLOCK_DSIZE(lev,cur) : XFS_BMAP_IBLOCK_SIZE(lev,cur)))
    -#define XFS_BMAP_BLOCK_ISIZE(lev,cur)	\
    -	(((lev) == (cur)->bc_nlevels - 1 ? \
    -		XFS_BMAP_RBLOCK_ISIZE(lev,cur) : XFS_BMAP_IBLOCK_SIZE(lev,cur)))
    -
    -#define XFS_BMAP_BLOCK_DMAXRECS(lev,cur) \
    -	(((lev) == (cur)->bc_nlevels - 1 ? \
    -		XFS_BTREE_BLOCK_MAXRECS(XFS_BMAP_RBLOCK_DSIZE(lev,cur), \
    -			xfs_bmdr, (lev) == 0) : \
    -		((cur)->bc_mp->m_bmap_dmxr[(lev) != 0])))
    -#define XFS_BMAP_BLOCK_IMAXRECS(lev,cur) \
    -	(((lev) == (cur)->bc_nlevels - 1 ? \
    -			XFS_BTREE_BLOCK_MAXRECS(XFS_BMAP_RBLOCK_ISIZE(lev,cur),\
    -				xfs_bmbt, (lev) == 0) : \
    -			((cur)->bc_mp->m_bmap_dmxr[(lev) != 0])))
    -
    -#define XFS_BMAP_BLOCK_DMINRECS(lev,cur) \
    -	(((lev) == (cur)->bc_nlevels - 1 ? \
    -			XFS_BTREE_BLOCK_MINRECS(XFS_BMAP_RBLOCK_DSIZE(lev,cur),\
    -				xfs_bmdr, (lev) == 0) : \
    -			((cur)->bc_mp->m_bmap_dmnr[(lev) != 0])))
    -#define XFS_BMAP_BLOCK_IMINRECS(lev,cur) \
    -	(((lev) == (cur)->bc_nlevels - 1 ? \
    -			XFS_BTREE_BLOCK_MINRECS(XFS_BMAP_RBLOCK_ISIZE(lev,cur),\
    -				xfs_bmbt, (lev) == 0) : \
    -			((cur)->bc_mp->m_bmap_dmnr[(lev) != 0])))
    -
    -#define XFS_BMAP_REC_DADDR(bb,i,cur)	\
    -	(XFS_BTREE_REC_ADDR(XFS_BMAP_BLOCK_DSIZE(			\
    -			be16_to_cpu((bb)->bb_level), cur),		\
    -			xfs_bmbt, bb, i, XFS_BMAP_BLOCK_DMAXRECS(	\
    -				be16_to_cpu((bb)->bb_level), cur)))
    -#define XFS_BMAP_REC_IADDR(bb,i,cur)	\
    -	(XFS_BTREE_REC_ADDR(XFS_BMAP_BLOCK_ISIZE(			\
    -			be16_to_cpu((bb)->bb_level), cur),		\
    -			xfs_bmbt, bb, i, XFS_BMAP_BLOCK_IMAXRECS(	\
    -				be16_to_cpu((bb)->bb_level), cur)))
    -
    -#define XFS_BMAP_KEY_DADDR(bb,i,cur)	\
    -	(XFS_BTREE_KEY_ADDR(XFS_BMAP_BLOCK_DSIZE(			\
    -			be16_to_cpu((bb)->bb_level), cur),		\
    -			xfs_bmbt, bb, i, XFS_BMAP_BLOCK_DMAXRECS(	\
    -				be16_to_cpu((bb)->bb_level), cur)))
    -#define XFS_BMAP_KEY_IADDR(bb,i,cur)	\
    -	(XFS_BTREE_KEY_ADDR(XFS_BMAP_BLOCK_ISIZE(			\
    -			be16_to_cpu((bb)->bb_level), cur),		\
    -			xfs_bmbt, bb, i, XFS_BMAP_BLOCK_IMAXRECS(	\
    -				be16_to_cpu((bb)->bb_level), cur)))
    -
    -#define XFS_BMAP_PTR_DADDR(bb,i,cur)	\
    -	(XFS_BTREE_PTR_ADDR(XFS_BMAP_BLOCK_DSIZE(			\
    -			be16_to_cpu((bb)->bb_level), cur),		\
    -			xfs_bmbt, bb, i, XFS_BMAP_BLOCK_DMAXRECS(	\
    -				be16_to_cpu((bb)->bb_level), cur)))
    -#define XFS_BMAP_PTR_IADDR(bb,i,cur)	\
    -	(XFS_BTREE_PTR_ADDR(XFS_BMAP_BLOCK_ISIZE(			\
    -			be16_to_cpu((bb)->bb_level), cur),		\
    -			xfs_bmbt, bb, i, XFS_BMAP_BLOCK_IMAXRECS(	\
    -				be16_to_cpu((bb)->bb_level), cur)))
    -
    -/*
    - * These are to be used when we know the size of the block and
    - * we don't have a cursor.
    - */
    -#define XFS_BMAP_BROOT_REC_ADDR(bb,i,sz) \
    -	(XFS_BTREE_REC_ADDR(sz,xfs_bmbt,bb,i,XFS_BMAP_BROOT_MAXRECS(sz)))
    -#define XFS_BMAP_BROOT_KEY_ADDR(bb,i,sz) \
    -	(XFS_BTREE_KEY_ADDR(sz,xfs_bmbt,bb,i,XFS_BMAP_BROOT_MAXRECS(sz)))
    -#define XFS_BMAP_BROOT_PTR_ADDR(bb,i,sz) \
    -	(XFS_BTREE_PTR_ADDR(sz,xfs_bmbt,bb,i,XFS_BMAP_BROOT_MAXRECS(sz)))
    -
    -#define XFS_BMAP_BROOT_NUMRECS(bb)	be16_to_cpu((bb)->bb_numrecs)
    -#define XFS_BMAP_BROOT_MAXRECS(sz)	XFS_BTREE_BLOCK_MAXRECS(sz,xfs_bmbt,0)
    -
    -#define XFS_BMAP_BROOT_SPACE_CALC(nrecs) \
    -	(int)(sizeof(xfs_bmbt_block_t) + \
    -	       ((nrecs) * (sizeof(xfs_bmbt_key_t) + sizeof(xfs_bmbt_ptr_t))))
    -
    -#define XFS_BMAP_BROOT_SPACE(bb) \
    -	(XFS_BMAP_BROOT_SPACE_CALC(be16_to_cpu((bb)->bb_numrecs)))
    -#define XFS_BMDR_SPACE_CALC(nrecs) \
    -	(int)(sizeof(xfs_bmdr_block_t) + \
    -	       ((nrecs) * (sizeof(xfs_bmbt_key_t) + sizeof(xfs_bmbt_ptr_t))))
    -
    -/*
    - * Maximum number of bmap btree levels.
    - */
    -#define XFS_BM_MAXLEVELS(mp,w)		((mp)->m_bm_maxlevels[(w)])
    -
    -#define XFS_BMAP_SANITY_CHECK(mp,bb,level) \
    -	(be32_to_cpu((bb)->bb_magic) == XFS_BMAP_MAGIC && \
    -	 be16_to_cpu((bb)->bb_level) == level && \
    -	 be16_to_cpu((bb)->bb_numrecs) > 0 && \
    -	 be16_to_cpu((bb)->bb_numrecs) <= (mp)->m_bmap_dmxr[(level) != 0])
    -
    -
    -#ifdef __KERNEL__
    -
    -#if defined(XFS_BMBT_TRACE)
    -/*
    - * Trace buffer entry types.
    - */
    -#define XFS_BMBT_KTRACE_ARGBI	1
    -#define XFS_BMBT_KTRACE_ARGBII	2
    -#define XFS_BMBT_KTRACE_ARGFFFI 3
    -#define XFS_BMBT_KTRACE_ARGI	4
    -#define XFS_BMBT_KTRACE_ARGIFK	5
    -#define XFS_BMBT_KTRACE_ARGIFR	6
    -#define XFS_BMBT_KTRACE_ARGIK	7
    -#define XFS_BMBT_KTRACE_CUR	8
    -
    -#define XFS_BMBT_TRACE_SIZE	4096	/* size of global trace buffer */
    -#define XFS_BMBT_KTRACE_SIZE	32	/* size of per-inode trace buffer */
    -extern ktrace_t	*xfs_bmbt_trace_buf;
    -#endif
    -
    -/*
    - * Prototypes for xfs_bmap.c to call.
    - */
    -extern void xfs_bmdr_to_bmbt(xfs_bmdr_block_t *, int, xfs_bmbt_block_t *, int);
    -extern int xfs_bmbt_decrement(struct xfs_btree_cur *, int, int *);
    -extern int xfs_bmbt_delete(struct xfs_btree_cur *, int *);
    -extern void xfs_bmbt_get_all(xfs_bmbt_rec_t *r, xfs_bmbt_irec_t *s);
    -extern xfs_bmbt_block_t *xfs_bmbt_get_block(struct xfs_btree_cur *cur,
    -						int, struct xfs_buf **bpp);
    -extern xfs_filblks_t xfs_bmbt_get_blockcount(xfs_bmbt_rec_t *r);
    -extern xfs_fsblock_t xfs_bmbt_get_startblock(xfs_bmbt_rec_t *r);
    -extern xfs_fileoff_t xfs_bmbt_get_startoff(xfs_bmbt_rec_t *r);
    -extern xfs_exntst_t xfs_bmbt_get_state(xfs_bmbt_rec_t *r);
    -
    -#ifndef XFS_NATIVE_HOST
    -extern void xfs_bmbt_disk_get_all(xfs_bmbt_rec_t *r, xfs_bmbt_irec_t *s);
    -extern xfs_exntst_t xfs_bmbt_disk_get_state(xfs_bmbt_rec_t *r);
    -extern xfs_filblks_t xfs_bmbt_disk_get_blockcount(xfs_bmbt_rec_t *r);
    -extern xfs_fsblock_t xfs_bmbt_disk_get_startblock(xfs_bmbt_rec_t *r);
    -extern xfs_fileoff_t xfs_bmbt_disk_get_startoff(xfs_bmbt_rec_t *r);
    -#else
    -#define xfs_bmbt_disk_get_all(r, s)	xfs_bmbt_get_all(r, s)
    -#define xfs_bmbt_disk_get_state(r)	xfs_bmbt_get_state(r)
    -#define xfs_bmbt_disk_get_blockcount(r)	xfs_bmbt_get_blockcount(r)
    -#define xfs_bmbt_disk_get_startblock(r)	xfs_bmbt_get_blockcount(r)
    -#define xfs_bmbt_disk_get_startoff(r)	xfs_bmbt_get_startoff(r)
    -#endif /* XFS_NATIVE_HOST */
    -
    -extern int xfs_bmbt_increment(struct xfs_btree_cur *, int, int *);
    -extern int xfs_bmbt_insert(struct xfs_btree_cur *, int *);
    -extern void xfs_bmbt_log_block(struct xfs_btree_cur *, struct xfs_buf *, int);
    -extern void xfs_bmbt_log_recs(struct xfs_btree_cur *, struct xfs_buf *, int,
    -				int);
    -extern int xfs_bmbt_lookup_eq(struct xfs_btree_cur *, xfs_fileoff_t,
    -				xfs_fsblock_t, xfs_filblks_t, int *);
    -extern int xfs_bmbt_lookup_ge(struct xfs_btree_cur *, xfs_fileoff_t,
    -				xfs_fsblock_t, xfs_filblks_t, int *);
    -
    -/*
    - * Give the bmap btree a new root block.  Copy the old broot contents
    - * down into a real block and make the broot point to it.
    - */
    -extern int xfs_bmbt_newroot(struct xfs_btree_cur *cur, int *lflags, int *stat);
    -
    -extern void xfs_bmbt_set_all(xfs_bmbt_rec_t *r, xfs_bmbt_irec_t *s);
    -extern void xfs_bmbt_set_allf(xfs_bmbt_rec_t *r, xfs_fileoff_t o,
    -			xfs_fsblock_t b, xfs_filblks_t c, xfs_exntst_t v);
    -extern void xfs_bmbt_set_blockcount(xfs_bmbt_rec_t *r, xfs_filblks_t v);
    -extern void xfs_bmbt_set_startblock(xfs_bmbt_rec_t *r, xfs_fsblock_t v);
    -extern void xfs_bmbt_set_startoff(xfs_bmbt_rec_t *r, xfs_fileoff_t v);
    -extern void xfs_bmbt_set_state(xfs_bmbt_rec_t *r, xfs_exntst_t v);
    -
    -#ifndef XFS_NATIVE_HOST
    -extern void xfs_bmbt_disk_set_all(xfs_bmbt_rec_t *r, xfs_bmbt_irec_t *s);
    -extern void xfs_bmbt_disk_set_allf(xfs_bmbt_rec_t *r, xfs_fileoff_t o,
    -			xfs_fsblock_t b, xfs_filblks_t c, xfs_exntst_t v);
    -#else
    -#define xfs_bmbt_disk_set_all(r, s)		xfs_bmbt_set_all(r, s)
    -#define xfs_bmbt_disk_set_allf(r, o, b, c, v)	xfs_bmbt_set_allf(r, o, b, c, v)
    -#endif /* XFS_NATIVE_HOST */
    -
    -extern void xfs_bmbt_to_bmdr(xfs_bmbt_block_t *, int, xfs_bmdr_block_t *, int);
    -extern int xfs_bmbt_update(struct xfs_btree_cur *, xfs_fileoff_t,
    -				xfs_fsblock_t, xfs_filblks_t, xfs_exntst_t);
    -
    -#ifdef DEBUG
    -/*
    - * Get the data from the pointed-to record.
    - */
    -extern int xfs_bmbt_get_rec(struct xfs_btree_cur *, xfs_fileoff_t *,
    -				xfs_fsblock_t *, xfs_filblks_t *,
    -				xfs_exntst_t *, int *);
    -#endif
    -
    -#endif	/* __KERNEL__ */
    -
    -#endif	/* __XFS_BMAP_BTREE_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_btree.c b/sys/gnu/fs/xfs/xfs_btree.c
    deleted file mode 100644
    index 52d5d095fc3..00000000000
    --- a/sys/gnu/fs/xfs/xfs_btree.c
    +++ /dev/null
    @@ -1,943 +0,0 @@
    -/*
    - * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_btree.h"
    -#include "xfs_ialloc.h"
    -#include "xfs_error.h"
    -
    -/*
    - * Cursor allocation zone.
    - */
    -kmem_zone_t	*xfs_btree_cur_zone;
    -
    -/*
    - * Btree magic numbers.
    - */
    -const __uint32_t xfs_magics[XFS_BTNUM_MAX] =
    -{
    -	XFS_ABTB_MAGIC, XFS_ABTC_MAGIC, XFS_BMAP_MAGIC, XFS_IBT_MAGIC
    -};
    -
    -/*
    - * Prototypes for internal routines.
    - */
    -
    -/*
    - * Checking routine: return maxrecs for the block.
    - */
    -STATIC int				/* number of records fitting in block */
    -xfs_btree_maxrecs(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	xfs_btree_block_t	*block);/* generic btree block pointer */
    -
    -/*
    - * Internal routines.
    - */
    -
    -/*
    - * Retrieve the block pointer from the cursor at the given level.
    - * This may be a bmap btree root or from a buffer.
    - */
    -STATIC xfs_btree_block_t *			/* generic btree block pointer */
    -xfs_btree_get_block(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	int			level,	/* level in btree */
    -	struct xfs_buf		**bpp);	/* buffer containing the block */
    -
    -/*
    - * Checking routine: return maxrecs for the block.
    - */
    -STATIC int				/* number of records fitting in block */
    -xfs_btree_maxrecs(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	xfs_btree_block_t	*block)	/* generic btree block pointer */
    -{
    -	switch (cur->bc_btnum) {
    -	case XFS_BTNUM_BNO:
    -	case XFS_BTNUM_CNT:
    -		return (int)XFS_ALLOC_BLOCK_MAXRECS(
    -				be16_to_cpu(block->bb_h.bb_level), cur);
    -	case XFS_BTNUM_BMAP:
    -		return (int)XFS_BMAP_BLOCK_IMAXRECS(
    -				be16_to_cpu(block->bb_h.bb_level), cur);
    -	case XFS_BTNUM_INO:
    -		return (int)XFS_INOBT_BLOCK_MAXRECS(
    -				be16_to_cpu(block->bb_h.bb_level), cur);
    -	default:
    -		ASSERT(0);
    -		return 0;
    -	}
    -}
    -
    -/*
    - * External routines.
    - */
    -
    -#ifdef DEBUG
    -/*
    - * Debug routine: check that block header is ok.
    - */
    -void
    -xfs_btree_check_block(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	xfs_btree_block_t	*block,	/* generic btree block pointer */
    -	int			level,	/* level of the btree block */
    -	xfs_buf_t		*bp)	/* buffer containing block, if any */
    -{
    -	if (XFS_BTREE_LONG_PTRS(cur->bc_btnum))
    -		xfs_btree_check_lblock(cur, (xfs_btree_lblock_t *)block, level,
    -			bp);
    -	else
    -		xfs_btree_check_sblock(cur, (xfs_btree_sblock_t *)block, level,
    -			bp);
    -}
    -
    -/*
    - * Debug routine: check that keys are in the right order.
    - */
    -void
    -xfs_btree_check_key(
    -	xfs_btnum_t	btnum,		/* btree identifier */
    -	void		*ak1,		/* pointer to left (lower) key */
    -	void		*ak2)		/* pointer to right (higher) key */
    -{
    -	switch (btnum) {
    -	case XFS_BTNUM_BNO: {
    -		xfs_alloc_key_t	*k1;
    -		xfs_alloc_key_t	*k2;
    -
    -		k1 = ak1;
    -		k2 = ak2;
    -		ASSERT(be32_to_cpu(k1->ar_startblock) < be32_to_cpu(k2->ar_startblock));
    -		break;
    -	    }
    -	case XFS_BTNUM_CNT: {
    -		xfs_alloc_key_t	*k1;
    -		xfs_alloc_key_t	*k2;
    -
    -		k1 = ak1;
    -		k2 = ak2;
    -		ASSERT(be32_to_cpu(k1->ar_blockcount) < be32_to_cpu(k2->ar_blockcount) ||
    -		       (k1->ar_blockcount == k2->ar_blockcount &&
    -			be32_to_cpu(k1->ar_startblock) < be32_to_cpu(k2->ar_startblock)));
    -		break;
    -	    }
    -	case XFS_BTNUM_BMAP: {
    -		xfs_bmbt_key_t	*k1;
    -		xfs_bmbt_key_t	*k2;
    -
    -		k1 = ak1;
    -		k2 = ak2;
    -		ASSERT(INT_GET(k1->br_startoff, ARCH_CONVERT) < INT_GET(k2->br_startoff, ARCH_CONVERT));
    -		break;
    -	    }
    -	case XFS_BTNUM_INO: {
    -		xfs_inobt_key_t	*k1;
    -		xfs_inobt_key_t	*k2;
    -
    -		k1 = ak1;
    -		k2 = ak2;
    -		ASSERT(INT_GET(k1->ir_startino, ARCH_CONVERT) < INT_GET(k2->ir_startino, ARCH_CONVERT));
    -		break;
    -	    }
    -	default:
    -		ASSERT(0);
    -	}
    -}
    -#endif	/* DEBUG */
    -
    -/*
    - * Checking routine: check that long form block header is ok.
    - */
    -/* ARGSUSED */
    -int					/* error (0 or EFSCORRUPTED) */
    -xfs_btree_check_lblock(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	xfs_btree_lblock_t	*block,	/* btree long form block pointer */
    -	int			level,	/* level of the btree block */
    -	xfs_buf_t		*bp)	/* buffer for block, if any */
    -{
    -	int			lblock_ok; /* block passes checks */
    -	xfs_mount_t		*mp;	/* file system mount point */
    -
    -	mp = cur->bc_mp;
    -	lblock_ok =
    -		be32_to_cpu(block->bb_magic) == xfs_magics[cur->bc_btnum] &&
    -		be16_to_cpu(block->bb_level) == level &&
    -		be16_to_cpu(block->bb_numrecs) <=
    -			xfs_btree_maxrecs(cur, (xfs_btree_block_t *)block) &&
    -		block->bb_leftsib &&
    -		(be64_to_cpu(block->bb_leftsib) == NULLDFSBNO ||
    -		 XFS_FSB_SANITY_CHECK(mp, be64_to_cpu(block->bb_leftsib))) &&
    -		block->bb_rightsib &&
    -		(be64_to_cpu(block->bb_rightsib) == NULLDFSBNO ||
    -		 XFS_FSB_SANITY_CHECK(mp, be64_to_cpu(block->bb_rightsib)));
    -	if (unlikely(XFS_TEST_ERROR(!lblock_ok, mp, XFS_ERRTAG_BTREE_CHECK_LBLOCK,
    -			XFS_RANDOM_BTREE_CHECK_LBLOCK))) {
    -		if (bp)
    -			xfs_buftrace("LBTREE ERROR", bp);
    -		XFS_ERROR_REPORT("xfs_btree_check_lblock", XFS_ERRLEVEL_LOW,
    -				 mp);
    -		return XFS_ERROR(EFSCORRUPTED);
    -	}
    -	return 0;
    -}
    -
    -/*
    - * Checking routine: check that (long) pointer is ok.
    - */
    -int					/* error (0 or EFSCORRUPTED) */
    -xfs_btree_check_lptr(
    -	xfs_btree_cur_t	*cur,		/* btree cursor */
    -	xfs_dfsbno_t	ptr,		/* btree block disk address */
    -	int		level)		/* btree block level */
    -{
    -	xfs_mount_t	*mp;		/* file system mount point */
    -
    -	mp = cur->bc_mp;
    -	XFS_WANT_CORRUPTED_RETURN(
    -		level > 0 &&
    -		ptr != NULLDFSBNO &&
    -		XFS_FSB_SANITY_CHECK(mp, ptr));
    -	return 0;
    -}
    -
    -#ifdef DEBUG
    -/*
    - * Debug routine: check that records are in the right order.
    - */
    -void
    -xfs_btree_check_rec(
    -	xfs_btnum_t	btnum,		/* btree identifier */
    -	void		*ar1,		/* pointer to left (lower) record */
    -	void		*ar2)		/* pointer to right (higher) record */
    -{
    -	switch (btnum) {
    -	case XFS_BTNUM_BNO: {
    -		xfs_alloc_rec_t	*r1;
    -		xfs_alloc_rec_t	*r2;
    -
    -		r1 = ar1;
    -		r2 = ar2;
    -		ASSERT(be32_to_cpu(r1->ar_startblock) +
    -		       be32_to_cpu(r1->ar_blockcount) <=
    -		       be32_to_cpu(r2->ar_startblock));
    -		break;
    -	    }
    -	case XFS_BTNUM_CNT: {
    -		xfs_alloc_rec_t	*r1;
    -		xfs_alloc_rec_t	*r2;
    -
    -		r1 = ar1;
    -		r2 = ar2;
    -		ASSERT(be32_to_cpu(r1->ar_blockcount) < be32_to_cpu(r2->ar_blockcount) ||
    -		       (r1->ar_blockcount == r2->ar_blockcount &&
    -			be32_to_cpu(r1->ar_startblock) < be32_to_cpu(r2->ar_startblock)));
    -		break;
    -	    }
    -	case XFS_BTNUM_BMAP: {
    -		xfs_bmbt_rec_t	*r1;
    -		xfs_bmbt_rec_t	*r2;
    -
    -		r1 = ar1;
    -		r2 = ar2;
    -		ASSERT(xfs_bmbt_disk_get_startoff(r1) +
    -		       xfs_bmbt_disk_get_blockcount(r1) <=
    -		       xfs_bmbt_disk_get_startoff(r2));
    -		break;
    -	    }
    -	case XFS_BTNUM_INO: {
    -		xfs_inobt_rec_t	*r1;
    -		xfs_inobt_rec_t	*r2;
    -
    -		r1 = ar1;
    -		r2 = ar2;
    -		ASSERT(INT_GET(r1->ir_startino, ARCH_CONVERT) + XFS_INODES_PER_CHUNK <=
    -		       INT_GET(r2->ir_startino, ARCH_CONVERT));
    -		break;
    -	    }
    -	default:
    -		ASSERT(0);
    -	}
    -}
    -#endif	/* DEBUG */
    -
    -/*
    - * Checking routine: check that block header is ok.
    - */
    -/* ARGSUSED */
    -int					/* error (0 or EFSCORRUPTED) */
    -xfs_btree_check_sblock(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	xfs_btree_sblock_t	*block,	/* btree short form block pointer */
    -	int			level,	/* level of the btree block */
    -	xfs_buf_t		*bp)	/* buffer containing block */
    -{
    -	xfs_buf_t		*agbp;	/* buffer for ag. freespace struct */
    -	xfs_agf_t		*agf;	/* ag. freespace structure */
    -	xfs_agblock_t		agflen;	/* native ag. freespace length */
    -	int			sblock_ok; /* block passes checks */
    -
    -	agbp = cur->bc_private.a.agbp;
    -	agf = XFS_BUF_TO_AGF(agbp);
    -	agflen = be32_to_cpu(agf->agf_length);
    -	sblock_ok =
    -		be32_to_cpu(block->bb_magic) == xfs_magics[cur->bc_btnum] &&
    -		be16_to_cpu(block->bb_level) == level &&
    -		be16_to_cpu(block->bb_numrecs) <=
    -			xfs_btree_maxrecs(cur, (xfs_btree_block_t *)block) &&
    -		(be32_to_cpu(block->bb_leftsib) == NULLAGBLOCK ||
    -		 be32_to_cpu(block->bb_leftsib) < agflen) &&
    -		block->bb_leftsib &&
    -		(be32_to_cpu(block->bb_rightsib) == NULLAGBLOCK ||
    -		 be32_to_cpu(block->bb_rightsib) < agflen) &&
    -		block->bb_rightsib;
    -	if (unlikely(XFS_TEST_ERROR(!sblock_ok, cur->bc_mp,
    -			XFS_ERRTAG_BTREE_CHECK_SBLOCK,
    -			XFS_RANDOM_BTREE_CHECK_SBLOCK))) {
    -		if (bp)
    -			xfs_buftrace("SBTREE ERROR", bp);
    -		XFS_ERROR_REPORT("xfs_btree_check_sblock", XFS_ERRLEVEL_LOW,
    -				 cur->bc_mp);
    -		return XFS_ERROR(EFSCORRUPTED);
    -	}
    -	return 0;
    -}
    -
    -/*
    - * Checking routine: check that (short) pointer is ok.
    - */
    -int					/* error (0 or EFSCORRUPTED) */
    -xfs_btree_check_sptr(
    -	xfs_btree_cur_t	*cur,		/* btree cursor */
    -	xfs_agblock_t	ptr,		/* btree block disk address */
    -	int		level)		/* btree block level */
    -{
    -	xfs_buf_t	*agbp;		/* buffer for ag. freespace struct */
    -	xfs_agf_t	*agf;		/* ag. freespace structure */
    -
    -	agbp = cur->bc_private.a.agbp;
    -	agf = XFS_BUF_TO_AGF(agbp);
    -	XFS_WANT_CORRUPTED_RETURN(
    -		level > 0 &&
    -		ptr != NULLAGBLOCK && ptr != 0 &&
    -		ptr < be32_to_cpu(agf->agf_length));
    -	return 0;
    -}
    -
    -/*
    - * Delete the btree cursor.
    - */
    -void
    -xfs_btree_del_cursor(
    -	xfs_btree_cur_t	*cur,		/* btree cursor */
    -	int		error)		/* del because of error */
    -{
    -	int		i;		/* btree level */
    -
    -	/*
    -	 * Clear the buffer pointers, and release the buffers.
    -	 * If we're doing this in the face of an error, we
    -	 * need to make sure to inspect all of the entries
    -	 * in the bc_bufs array for buffers to be unlocked.
    -	 * This is because some of the btree code works from
    -	 * level n down to 0, and if we get an error along
    -	 * the way we won't have initialized all the entries
    -	 * down to 0.
    -	 */
    -	for (i = 0; i < cur->bc_nlevels; i++) {
    -		if (cur->bc_bufs[i])
    -			xfs_btree_setbuf(cur, i, NULL);
    -		else if (!error)
    -			break;
    -	}
    -	/*
    -	 * Can't free a bmap cursor without having dealt with the
    -	 * allocated indirect blocks' accounting.
    -	 */
    -	ASSERT(cur->bc_btnum != XFS_BTNUM_BMAP ||
    -	       cur->bc_private.b.allocated == 0);
    -	/*
    -	 * Free the cursor.
    -	 */
    -	kmem_zone_free(xfs_btree_cur_zone, cur);
    -}
    -
    -/*
    - * Duplicate the btree cursor.
    - * Allocate a new one, copy the record, re-get the buffers.
    - */
    -int					/* error */
    -xfs_btree_dup_cursor(
    -	xfs_btree_cur_t	*cur,		/* input cursor */
    -	xfs_btree_cur_t	**ncur)		/* output cursor */
    -{
    -	xfs_buf_t	*bp;		/* btree block's buffer pointer */
    -	int		error;		/* error return value */
    -	int		i;		/* level number of btree block */
    -	xfs_mount_t	*mp;		/* mount structure for filesystem */
    -	xfs_btree_cur_t	*new;		/* new cursor value */
    -	xfs_trans_t	*tp;		/* transaction pointer, can be NULL */
    -
    -	tp = cur->bc_tp;
    -	mp = cur->bc_mp;
    -	/*
    -	 * Allocate a new cursor like the old one.
    -	 */
    -	new = xfs_btree_init_cursor(mp, tp, cur->bc_private.a.agbp,
    -		cur->bc_private.a.agno, cur->bc_btnum, cur->bc_private.b.ip,
    -		cur->bc_private.b.whichfork);
    -	/*
    -	 * Copy the record currently in the cursor.
    -	 */
    -	new->bc_rec = cur->bc_rec;
    -	/*
    -	 * For each level current, re-get the buffer and copy the ptr value.
    -	 */
    -	for (i = 0; i < new->bc_nlevels; i++) {
    -		new->bc_ptrs[i] = cur->bc_ptrs[i];
    -		new->bc_ra[i] = cur->bc_ra[i];
    -		if ((bp = cur->bc_bufs[i])) {
    -			if ((error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
    -				XFS_BUF_ADDR(bp), mp->m_bsize, 0, &bp))) {
    -				xfs_btree_del_cursor(new, error);
    -				*ncur = NULL;
    -				return error;
    -			}
    -			new->bc_bufs[i] = bp;
    -			ASSERT(bp);
    -			ASSERT(!XFS_BUF_GETERROR(bp));
    -		} else
    -			new->bc_bufs[i] = NULL;
    -	}
    -	/*
    -	 * For bmap btrees, copy the firstblock, flist, and flags values,
    -	 * since init cursor doesn't get them.
    -	 */
    -	if (new->bc_btnum == XFS_BTNUM_BMAP) {
    -		new->bc_private.b.firstblock = cur->bc_private.b.firstblock;
    -		new->bc_private.b.flist = cur->bc_private.b.flist;
    -		new->bc_private.b.flags = cur->bc_private.b.flags;
    -	}
    -	*ncur = new;
    -	return 0;
    -}
    -
    -/*
    - * Change the cursor to point to the first record at the given level.
    - * Other levels are unaffected.
    - */
    -int					/* success=1, failure=0 */
    -xfs_btree_firstrec(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	int			level)	/* level to change */
    -{
    -	xfs_btree_block_t	*block;	/* generic btree block pointer */
    -	xfs_buf_t		*bp;	/* buffer containing block */
    -
    -	/*
    -	 * Get the block pointer for this level.
    -	 */
    -	block = xfs_btree_get_block(cur, level, &bp);
    -	xfs_btree_check_block(cur, block, level, bp);
    -	/*
    -	 * It's empty, there is no such record.
    -	 */
    -	if (!block->bb_h.bb_numrecs)
    -		return 0;
    -	/*
    -	 * Set the ptr value to 1, that's the first record/key.
    -	 */
    -	cur->bc_ptrs[level] = 1;
    -	return 1;
    -}
    -
    -/*
    - * Retrieve the block pointer from the cursor at the given level.
    - * This may be a bmap btree root or from a buffer.
    - */
    -STATIC xfs_btree_block_t *		/* generic btree block pointer */
    -xfs_btree_get_block(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	int			level,	/* level in btree */
    -	xfs_buf_t		**bpp)	/* buffer containing the block */
    -{
    -	xfs_btree_block_t	*block;	/* return value */
    -	xfs_buf_t		*bp;	/* return buffer */
    -	xfs_ifork_t		*ifp;	/* inode fork pointer */
    -	int			whichfork; /* data or attr fork */
    -
    -	if (cur->bc_btnum == XFS_BTNUM_BMAP && level == cur->bc_nlevels - 1) {
    -		whichfork = cur->bc_private.b.whichfork;
    -		ifp = XFS_IFORK_PTR(cur->bc_private.b.ip, whichfork);
    -		block = (xfs_btree_block_t *)ifp->if_broot;
    -		bp = NULL;
    -	} else {
    -		bp = cur->bc_bufs[level];
    -		block = XFS_BUF_TO_BLOCK(bp);
    -	}
    -	ASSERT(block != NULL);
    -	*bpp = bp;
    -	return block;
    -}
    -
    -/*
    - * Get a buffer for the block, return it with no data read.
    - * Long-form addressing.
    - */
    -xfs_buf_t *				/* buffer for fsbno */
    -xfs_btree_get_bufl(
    -	xfs_mount_t	*mp,		/* file system mount point */
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_fsblock_t	fsbno,		/* file system block number */
    -	uint		lock)		/* lock flags for get_buf */
    -{
    -	xfs_buf_t	*bp;		/* buffer pointer (return value) */
    -	xfs_daddr_t		d;		/* real disk block address */
    -
    -	ASSERT(fsbno != NULLFSBLOCK);
    -	d = XFS_FSB_TO_DADDR(mp, fsbno);
    -	bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock);
    -	ASSERT(bp);
    -	ASSERT(!XFS_BUF_GETERROR(bp));
    -	return bp;
    -}
    -
    -/*
    - * Get a buffer for the block, return it with no data read.
    - * Short-form addressing.
    - */
    -xfs_buf_t *				/* buffer for agno/agbno */
    -xfs_btree_get_bufs(
    -	xfs_mount_t	*mp,		/* file system mount point */
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_agnumber_t	agno,		/* allocation group number */
    -	xfs_agblock_t	agbno,		/* allocation group block number */
    -	uint		lock)		/* lock flags for get_buf */
    -{
    -	xfs_buf_t	*bp;		/* buffer pointer (return value) */
    -	xfs_daddr_t		d;		/* real disk block address */
    -
    -	ASSERT(agno != NULLAGNUMBER);
    -	ASSERT(agbno != NULLAGBLOCK);
    -	d = XFS_AGB_TO_DADDR(mp, agno, agbno);
    -	bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock);
    -	ASSERT(bp);
    -	ASSERT(!XFS_BUF_GETERROR(bp));
    -	return bp;
    -}
    -
    -/*
    - * Allocate a new btree cursor.
    - * The cursor is either for allocation (A) or bmap (B) or inodes (I).
    - */
    -xfs_btree_cur_t *			/* new btree cursor */
    -xfs_btree_init_cursor(
    -	xfs_mount_t	*mp,		/* file system mount point */
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_buf_t	*agbp,		/* (A only) buffer for agf structure */
    -					/* (I only) buffer for agi structure */
    -	xfs_agnumber_t	agno,		/* (AI only) allocation group number */
    -	xfs_btnum_t	btnum,		/* btree identifier */
    -	xfs_inode_t	*ip,		/* (B only) inode owning the btree */
    -	int		whichfork)	/* (B only) data or attr fork */
    -{
    -	xfs_agf_t	*agf;		/* (A) allocation group freespace */
    -	xfs_agi_t	*agi;		/* (I) allocation group inodespace */
    -	xfs_btree_cur_t	*cur;		/* return value */
    -	xfs_ifork_t	*ifp;		/* (I) inode fork pointer */
    -	int		nlevels=0;	/* number of levels in the btree */
    -
    -	ASSERT(xfs_btree_cur_zone != NULL);
    -	/*
    -	 * Allocate a new cursor.
    -	 */
    -	cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_SLEEP);
    -	/*
    -	 * Deduce the number of btree levels from the arguments.
    -	 */
    -	switch (btnum) {
    -	case XFS_BTNUM_BNO:
    -	case XFS_BTNUM_CNT:
    -		agf = XFS_BUF_TO_AGF(agbp);
    -		nlevels = be32_to_cpu(agf->agf_levels[btnum]);
    -		break;
    -	case XFS_BTNUM_BMAP:
    -		ifp = XFS_IFORK_PTR(ip, whichfork);
    -		nlevels = be16_to_cpu(ifp->if_broot->bb_level) + 1;
    -		break;
    -	case XFS_BTNUM_INO:
    -		agi = XFS_BUF_TO_AGI(agbp);
    -		nlevels = be32_to_cpu(agi->agi_level);
    -		break;
    -	default:
    -		ASSERT(0);
    -	}
    -	/*
    -	 * Fill in the common fields.
    -	 */
    -	cur->bc_tp = tp;
    -	cur->bc_mp = mp;
    -	cur->bc_nlevels = nlevels;
    -	cur->bc_btnum = btnum;
    -	cur->bc_blocklog = mp->m_sb.sb_blocklog;
    -	/*
    -	 * Fill in private fields.
    -	 */
    -	switch (btnum) {
    -	case XFS_BTNUM_BNO:
    -	case XFS_BTNUM_CNT:
    -		/*
    -		 * Allocation btree fields.
    -		 */
    -		cur->bc_private.a.agbp = agbp;
    -		cur->bc_private.a.agno = agno;
    -		break;
    -	case XFS_BTNUM_BMAP:
    -		/*
    -		 * Bmap btree fields.
    -		 */
    -		cur->bc_private.b.forksize = XFS_IFORK_SIZE(ip, whichfork);
    -		cur->bc_private.b.ip = ip;
    -		cur->bc_private.b.firstblock = NULLFSBLOCK;
    -		cur->bc_private.b.flist = NULL;
    -		cur->bc_private.b.allocated = 0;
    -		cur->bc_private.b.flags = 0;
    -		cur->bc_private.b.whichfork = whichfork;
    -		break;
    -	case XFS_BTNUM_INO:
    -		/*
    -		 * Inode allocation btree fields.
    -		 */
    -		cur->bc_private.i.agbp = agbp;
    -		cur->bc_private.i.agno = agno;
    -		break;
    -	default:
    -		ASSERT(0);
    -	}
    -	return cur;
    -}
    -
    -/*
    - * Check for the cursor referring to the last block at the given level.
    - */
    -int					/* 1=is last block, 0=not last block */
    -xfs_btree_islastblock(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	int			level)	/* level to check */
    -{
    -	xfs_btree_block_t	*block;	/* generic btree block pointer */
    -	xfs_buf_t		*bp;	/* buffer containing block */
    -
    -	block = xfs_btree_get_block(cur, level, &bp);
    -	xfs_btree_check_block(cur, block, level, bp);
    -	if (XFS_BTREE_LONG_PTRS(cur->bc_btnum))
    -		return be64_to_cpu(block->bb_u.l.bb_rightsib) == NULLDFSBNO;
    -	else
    -		return be32_to_cpu(block->bb_u.s.bb_rightsib) == NULLAGBLOCK;
    -}
    -
    -/*
    - * Change the cursor to point to the last record in the current block
    - * at the given level.  Other levels are unaffected.
    - */
    -int					/* success=1, failure=0 */
    -xfs_btree_lastrec(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	int			level)	/* level to change */
    -{
    -	xfs_btree_block_t	*block;	/* generic btree block pointer */
    -	xfs_buf_t		*bp;	/* buffer containing block */
    -
    -	/*
    -	 * Get the block pointer for this level.
    -	 */
    -	block = xfs_btree_get_block(cur, level, &bp);
    -	xfs_btree_check_block(cur, block, level, bp);
    -	/*
    -	 * It's empty, there is no such record.
    -	 */
    -	if (!block->bb_h.bb_numrecs)
    -		return 0;
    -	/*
    -	 * Set the ptr value to numrecs, that's the last record/key.
    -	 */
    -	cur->bc_ptrs[level] = be16_to_cpu(block->bb_h.bb_numrecs);
    -	return 1;
    -}
    -
    -/*
    - * Compute first and last byte offsets for the fields given.
    - * Interprets the offsets table, which contains struct field offsets.
    - */
    -void
    -xfs_btree_offsets(
    -	__int64_t	fields,		/* bitmask of fields */
    -	const short	*offsets,	/* table of field offsets */
    -	int		nbits,		/* number of bits to inspect */
    -	int		*first,		/* output: first byte offset */
    -	int		*last)		/* output: last byte offset */
    -{
    -	int		i;		/* current bit number */
    -	__int64_t	imask;		/* mask for current bit number */
    -
    -	ASSERT(fields != 0);
    -	/*
    -	 * Find the lowest bit, so the first byte offset.
    -	 */
    -	for (i = 0, imask = 1LL; ; i++, imask <<= 1) {
    -		if (imask & fields) {
    -			*first = offsets[i];
    -			break;
    -		}
    -	}
    -	/*
    -	 * Find the highest bit, so the last byte offset.
    -	 */
    -	for (i = nbits - 1, imask = 1LL << i; ; i--, imask >>= 1) {
    -		if (imask & fields) {
    -			*last = offsets[i + 1] - 1;
    -			break;
    -		}
    -	}
    -}
    -
    -/*
    - * Get a buffer for the block, return it read in.
    - * Long-form addressing.
    - */
    -int					/* error */
    -xfs_btree_read_bufl(
    -	xfs_mount_t	*mp,		/* file system mount point */
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_fsblock_t	fsbno,		/* file system block number */
    -	uint		lock,		/* lock flags for read_buf */
    -	xfs_buf_t	**bpp,		/* buffer for fsbno */
    -	int		refval)		/* ref count value for buffer */
    -{
    -	xfs_buf_t	*bp;		/* return value */
    -	xfs_daddr_t		d;		/* real disk block address */
    -	int		error;
    -
    -	ASSERT(fsbno != NULLFSBLOCK);
    -	d = XFS_FSB_TO_DADDR(mp, fsbno);
    -	if ((error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, d,
    -			mp->m_bsize, lock, &bp))) {
    -		return error;
    -	}
    -	ASSERT(!bp || !XFS_BUF_GETERROR(bp));
    -	if (bp != NULL) {
    -		XFS_BUF_SET_VTYPE_REF(bp, B_FS_MAP, refval);
    -	}
    -	*bpp = bp;
    -	return 0;
    -}
    -
    -/*
    - * Get a buffer for the block, return it read in.
    - * Short-form addressing.
    - */
    -int					/* error */
    -xfs_btree_read_bufs(
    -	xfs_mount_t	*mp,		/* file system mount point */
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_agnumber_t	agno,		/* allocation group number */
    -	xfs_agblock_t	agbno,		/* allocation group block number */
    -	uint		lock,		/* lock flags for read_buf */
    -	xfs_buf_t	**bpp,		/* buffer for agno/agbno */
    -	int		refval)		/* ref count value for buffer */
    -{
    -	xfs_buf_t	*bp;		/* return value */
    -	xfs_daddr_t	d;		/* real disk block address */
    -	int		error;
    -
    -	ASSERT(agno != NULLAGNUMBER);
    -	ASSERT(agbno != NULLAGBLOCK);
    -	d = XFS_AGB_TO_DADDR(mp, agno, agbno);
    -	if ((error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, d,
    -					mp->m_bsize, lock, &bp))) {
    -		return error;
    -	}
    -	ASSERT(!bp || !XFS_BUF_GETERROR(bp));
    -	if (bp != NULL) {
    -		switch (refval) {
    -		case XFS_ALLOC_BTREE_REF:
    -			XFS_BUF_SET_VTYPE_REF(bp, B_FS_MAP, refval);
    -			break;
    -		case XFS_INO_BTREE_REF:
    -			XFS_BUF_SET_VTYPE_REF(bp, B_FS_INOMAP, refval);
    -			break;
    -		}
    -	}
    -	*bpp = bp;
    -	return 0;
    -}
    -
    -/*
    - * Read-ahead the block, don't wait for it, don't return a buffer.
    - * Long-form addressing.
    - */
    -/* ARGSUSED */
    -void
    -xfs_btree_reada_bufl(
    -	xfs_mount_t	*mp,		/* file system mount point */
    -	xfs_fsblock_t	fsbno,		/* file system block number */
    -	xfs_extlen_t	count)		/* count of filesystem blocks */
    -{
    -	xfs_daddr_t		d;
    -
    -	ASSERT(fsbno != NULLFSBLOCK);
    -	d = XFS_FSB_TO_DADDR(mp, fsbno);
    -	xfs_baread(mp->m_ddev_targp, d, mp->m_bsize * count);
    -}
    -
    -/*
    - * Read-ahead the block, don't wait for it, don't return a buffer.
    - * Short-form addressing.
    - */
    -/* ARGSUSED */
    -void
    -xfs_btree_reada_bufs(
    -	xfs_mount_t	*mp,		/* file system mount point */
    -	xfs_agnumber_t	agno,		/* allocation group number */
    -	xfs_agblock_t	agbno,		/* allocation group block number */
    -	xfs_extlen_t	count)		/* count of filesystem blocks */
    -{
    -	xfs_daddr_t		d;
    -
    -	ASSERT(agno != NULLAGNUMBER);
    -	ASSERT(agbno != NULLAGBLOCK);
    -	d = XFS_AGB_TO_DADDR(mp, agno, agbno);
    -	xfs_baread(mp->m_ddev_targp, d, mp->m_bsize * count);
    -}
    -
    -/*
    - * Read-ahead btree blocks, at the given level.
    - * Bits in lr are set from XFS_BTCUR_{LEFT,RIGHT}RA.
    - */
    -int
    -xfs_btree_readahead_core(
    -	xfs_btree_cur_t		*cur,		/* btree cursor */
    -	int			lev,		/* level in btree */
    -	int			lr)		/* left/right bits */
    -{
    -	xfs_alloc_block_t	*a;
    -	xfs_bmbt_block_t	*b;
    -	xfs_inobt_block_t	*i;
    -	int			rval = 0;
    -
    -	ASSERT(cur->bc_bufs[lev] != NULL);
    -	cur->bc_ra[lev] |= lr;
    -	switch (cur->bc_btnum) {
    -	case XFS_BTNUM_BNO:
    -	case XFS_BTNUM_CNT:
    -		a = XFS_BUF_TO_ALLOC_BLOCK(cur->bc_bufs[lev]);
    -		if ((lr & XFS_BTCUR_LEFTRA) && be32_to_cpu(a->bb_leftsib) != NULLAGBLOCK) {
    -			xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.a.agno,
    -				be32_to_cpu(a->bb_leftsib), 1);
    -			rval++;
    -		}
    -		if ((lr & XFS_BTCUR_RIGHTRA) && be32_to_cpu(a->bb_rightsib) != NULLAGBLOCK) {
    -			xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.a.agno,
    -				be32_to_cpu(a->bb_rightsib), 1);
    -			rval++;
    -		}
    -		break;
    -	case XFS_BTNUM_BMAP:
    -		b = XFS_BUF_TO_BMBT_BLOCK(cur->bc_bufs[lev]);
    -		if ((lr & XFS_BTCUR_LEFTRA) && be64_to_cpu(b->bb_leftsib) != NULLDFSBNO) {
    -			xfs_btree_reada_bufl(cur->bc_mp, be64_to_cpu(b->bb_leftsib), 1);
    -			rval++;
    -		}
    -		if ((lr & XFS_BTCUR_RIGHTRA) && be64_to_cpu(b->bb_rightsib) != NULLDFSBNO) {
    -			xfs_btree_reada_bufl(cur->bc_mp, be64_to_cpu(b->bb_rightsib), 1);
    -			rval++;
    -		}
    -		break;
    -	case XFS_BTNUM_INO:
    -		i = XFS_BUF_TO_INOBT_BLOCK(cur->bc_bufs[lev]);
    -		if ((lr & XFS_BTCUR_LEFTRA) && be32_to_cpu(i->bb_leftsib) != NULLAGBLOCK) {
    -			xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.i.agno,
    -				be32_to_cpu(i->bb_leftsib), 1);
    -			rval++;
    -		}
    -		if ((lr & XFS_BTCUR_RIGHTRA) && be32_to_cpu(i->bb_rightsib) != NULLAGBLOCK) {
    -			xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.i.agno,
    -				be32_to_cpu(i->bb_rightsib), 1);
    -			rval++;
    -		}
    -		break;
    -	default:
    -		ASSERT(0);
    -	}
    -	return rval;
    -}
    -
    -/*
    - * Set the buffer for level "lev" in the cursor to bp, releasing
    - * any previous buffer.
    - */
    -void
    -xfs_btree_setbuf(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	int			lev,	/* level in btree */
    -	xfs_buf_t		*bp)	/* new buffer to set */
    -{
    -	xfs_btree_block_t	*b;	/* btree block */
    -	xfs_buf_t		*obp;	/* old buffer pointer */
    -
    -	obp = cur->bc_bufs[lev];
    -	if (obp)
    -		xfs_trans_brelse(cur->bc_tp, obp);
    -	cur->bc_bufs[lev] = bp;
    -	cur->bc_ra[lev] = 0;
    -	if (!bp)
    -		return;
    -	b = XFS_BUF_TO_BLOCK(bp);
    -	if (XFS_BTREE_LONG_PTRS(cur->bc_btnum)) {
    -		if (be64_to_cpu(b->bb_u.l.bb_leftsib) == NULLDFSBNO)
    -			cur->bc_ra[lev] |= XFS_BTCUR_LEFTRA;
    -		if (be64_to_cpu(b->bb_u.l.bb_rightsib) == NULLDFSBNO)
    -			cur->bc_ra[lev] |= XFS_BTCUR_RIGHTRA;
    -	} else {
    -		if (be32_to_cpu(b->bb_u.s.bb_leftsib) == NULLAGBLOCK)
    -			cur->bc_ra[lev] |= XFS_BTCUR_LEFTRA;
    -		if (be32_to_cpu(b->bb_u.s.bb_rightsib) == NULLAGBLOCK)
    -			cur->bc_ra[lev] |= XFS_BTCUR_RIGHTRA;
    -	}
    -}
    diff --git a/sys/gnu/fs/xfs/xfs_btree.h b/sys/gnu/fs/xfs/xfs_btree.h
    deleted file mode 100644
    index 44f1bd98064..00000000000
    --- a/sys/gnu/fs/xfs/xfs_btree.h
    +++ /dev/null
    @@ -1,473 +0,0 @@
    -/*
    - * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_BTREE_H__
    -#define	__XFS_BTREE_H__
    -
    -struct xfs_buf;
    -struct xfs_bmap_free;
    -struct xfs_inode;
    -struct xfs_mount;
    -struct xfs_trans;
    -
    -/*
    - * This nonsense is to make -wlint happy.
    - */
    -#define	XFS_LOOKUP_EQ	((xfs_lookup_t)XFS_LOOKUP_EQi)
    -#define	XFS_LOOKUP_LE	((xfs_lookup_t)XFS_LOOKUP_LEi)
    -#define	XFS_LOOKUP_GE	((xfs_lookup_t)XFS_LOOKUP_GEi)
    -
    -#define	XFS_BTNUM_BNO	((xfs_btnum_t)XFS_BTNUM_BNOi)
    -#define	XFS_BTNUM_CNT	((xfs_btnum_t)XFS_BTNUM_CNTi)
    -#define	XFS_BTNUM_BMAP	((xfs_btnum_t)XFS_BTNUM_BMAPi)
    -#define	XFS_BTNUM_INO	((xfs_btnum_t)XFS_BTNUM_INOi)
    -
    -/*
    - * Short form header: space allocation btrees.
    - */
    -typedef struct xfs_btree_sblock {
    -	__be32		bb_magic;	/* magic number for block type */
    -	__be16		bb_level;	/* 0 is a leaf */
    -	__be16		bb_numrecs;	/* current # of data records */
    -	__be32		bb_leftsib;	/* left sibling block or NULLAGBLOCK */
    -	__be32		bb_rightsib;	/* right sibling block or NULLAGBLOCK */
    -} xfs_btree_sblock_t;
    -
    -/*
    - * Long form header: bmap btrees.
    - */
    -typedef struct xfs_btree_lblock {
    -	__be32		bb_magic;	/* magic number for block type */
    -	__be16		bb_level;	/* 0 is a leaf */
    -	__be16		bb_numrecs;	/* current # of data records */
    -	__be64		bb_leftsib;	/* left sibling block or NULLDFSBNO */
    -	__be64		bb_rightsib;	/* right sibling block or NULLDFSBNO */
    -} xfs_btree_lblock_t;
    -
    -/*
    - * Combined header and structure, used by common code.
    - */
    -typedef struct xfs_btree_hdr
    -{
    -	__be32		bb_magic;	/* magic number for block type */
    -	__be16		bb_level;	/* 0 is a leaf */
    -	__be16		bb_numrecs;	/* current # of data records */
    -} xfs_btree_hdr_t;
    -
    -typedef struct xfs_btree_block {
    -	xfs_btree_hdr_t	bb_h;		/* header */
    -	union {
    -		struct {
    -			__be32		bb_leftsib;
    -			__be32		bb_rightsib;
    -		} s;			/* short form pointers */
    -		struct	{
    -			__be64		bb_leftsib;
    -			__be64		bb_rightsib;
    -		} l;			/* long form pointers */
    -	} bb_u;				/* rest */
    -} xfs_btree_block_t;
    -
    -/*
    - * For logging record fields.
    - */
    -#define	XFS_BB_MAGIC		0x01
    -#define	XFS_BB_LEVEL		0x02
    -#define	XFS_BB_NUMRECS		0x04
    -#define	XFS_BB_LEFTSIB		0x08
    -#define	XFS_BB_RIGHTSIB		0x10
    -#define	XFS_BB_NUM_BITS		5
    -#define	XFS_BB_ALL_BITS		((1 << XFS_BB_NUM_BITS) - 1)
    -
    -/*
    - * Boolean to select which form of xfs_btree_block_t.bb_u to use.
    - */
    -#define	XFS_BTREE_LONG_PTRS(btnum)	((btnum) == XFS_BTNUM_BMAP)
    -
    -/*
    - * Magic numbers for btree blocks.
    - */
    -extern const __uint32_t	xfs_magics[];
    -
    -/*
    - * Maximum and minimum records in a btree block.
    - * Given block size, type prefix, and leaf flag (0 or 1).
    - * The divisor below is equivalent to lf ? (e1) : (e2) but that produces
    - * compiler warnings.
    - */
    -#define	XFS_BTREE_BLOCK_MAXRECS(bsz,t,lf)	\
    -	((int)(((bsz) - (uint)sizeof(t ## _block_t)) / \
    -	 (((lf) * (uint)sizeof(t ## _rec_t)) + \
    -	  ((1 - (lf)) * \
    -	   ((uint)sizeof(t ## _key_t) + (uint)sizeof(t ## _ptr_t))))))
    -#define	XFS_BTREE_BLOCK_MINRECS(bsz,t,lf)	\
    -	(XFS_BTREE_BLOCK_MAXRECS(bsz,t,lf) / 2)
    -
    -/*
    - * Record, key, and pointer address calculation macros.
    - * Given block size, type prefix, block pointer, and index of requested entry
    - * (first entry numbered 1).
    - */
    -#define	XFS_BTREE_REC_ADDR(bsz,t,bb,i,mxr)	\
    -	((t ## _rec_t *)((char *)(bb) + sizeof(t ## _block_t) + \
    -	 ((i) - 1) * sizeof(t ## _rec_t)))
    -#define	XFS_BTREE_KEY_ADDR(bsz,t,bb,i,mxr)	\
    -	((t ## _key_t *)((char *)(bb) + sizeof(t ## _block_t) + \
    -	 ((i) - 1) * sizeof(t ## _key_t)))
    -#define	XFS_BTREE_PTR_ADDR(bsz,t,bb,i,mxr)	\
    -	((t ## _ptr_t *)((char *)(bb) + sizeof(t ## _block_t) + \
    -	 (mxr) * sizeof(t ## _key_t) + ((i) - 1) * sizeof(t ## _ptr_t)))
    -
    -#define	XFS_BTREE_MAXLEVELS	8	/* max of all btrees */
    -
    -/*
    - * Btree cursor structure.
    - * This collects all information needed by the btree code in one place.
    - */
    -typedef struct xfs_btree_cur
    -{
    -	struct xfs_trans	*bc_tp;	/* transaction we're in, if any */
    -	struct xfs_mount	*bc_mp;	/* file system mount struct */
    -	union {
    -		xfs_alloc_rec_incore_t	a;
    -		xfs_bmbt_irec_t		b;
    -		xfs_inobt_rec_t		i;
    -	}		bc_rec;		/* current insert/search record value */
    -	struct xfs_buf	*bc_bufs[XFS_BTREE_MAXLEVELS];	/* buf ptr per level */
    -	int		bc_ptrs[XFS_BTREE_MAXLEVELS];	/* key/record # */
    -	__uint8_t	bc_ra[XFS_BTREE_MAXLEVELS];	/* readahead bits */
    -#define	XFS_BTCUR_LEFTRA	1	/* left sibling has been read-ahead */
    -#define	XFS_BTCUR_RIGHTRA	2	/* right sibling has been read-ahead */
    -	__uint8_t	bc_nlevels;	/* number of levels in the tree */
    -	__uint8_t	bc_blocklog;	/* log2(blocksize) of btree blocks */
    -	xfs_btnum_t	bc_btnum;	/* identifies which btree type */
    -	union {
    -		struct {			/* needed for BNO, CNT */
    -			struct xfs_buf	*agbp;	/* agf buffer pointer */
    -			xfs_agnumber_t	agno;	/* ag number */
    -		} a;
    -		struct {			/* needed for BMAP */
    -			struct xfs_inode *ip;	/* pointer to our inode */
    -			struct xfs_bmap_free *flist;	/* list to free after */
    -			xfs_fsblock_t	firstblock;	/* 1st blk allocated */
    -			int		allocated;	/* count of alloced */
    -			short		forksize;	/* fork's inode space */
    -			char		whichfork;	/* data or attr fork */
    -			char		flags;		/* flags */
    -#define	XFS_BTCUR_BPRV_WASDEL	1			/* was delayed */
    -		} b;
    -		struct {			/* needed for INO */
    -			struct xfs_buf	*agbp;	/* agi buffer pointer */
    -			xfs_agnumber_t	agno;	/* ag number */
    -		} i;
    -	}		bc_private;	/* per-btree type data */
    -} xfs_btree_cur_t;
    -
    -#define	XFS_BTREE_NOERROR	0
    -#define	XFS_BTREE_ERROR		1
    -
    -/*
    - * Convert from buffer to btree block header.
    - */
    -#define	XFS_BUF_TO_BLOCK(bp)	((xfs_btree_block_t *)XFS_BUF_PTR(bp))
    -#define	XFS_BUF_TO_LBLOCK(bp)	((xfs_btree_lblock_t *)XFS_BUF_PTR(bp))
    -#define	XFS_BUF_TO_SBLOCK(bp)	((xfs_btree_sblock_t *)XFS_BUF_PTR(bp))
    -
    -
    -#ifdef __KERNEL__
    -
    -#ifdef DEBUG
    -/*
    - * Debug routine: check that block header is ok.
    - */
    -void
    -xfs_btree_check_block(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	xfs_btree_block_t	*block,	/* generic btree block pointer */
    -	int			level,	/* level of the btree block */
    -	struct xfs_buf		*bp);	/* buffer containing block, if any */
    -
    -/*
    - * Debug routine: check that keys are in the right order.
    - */
    -void
    -xfs_btree_check_key(
    -	xfs_btnum_t		btnum,	/* btree identifier */
    -	void			*ak1,	/* pointer to left (lower) key */
    -	void			*ak2);	/* pointer to right (higher) key */
    -
    -/*
    - * Debug routine: check that records are in the right order.
    - */
    -void
    -xfs_btree_check_rec(
    -	xfs_btnum_t		btnum,	/* btree identifier */
    -	void			*ar1,	/* pointer to left (lower) record */
    -	void			*ar2);	/* pointer to right (higher) record */
    -#else
    -#define	xfs_btree_check_block(a,b,c,d)
    -#define	xfs_btree_check_key(a,b,c)
    -#define	xfs_btree_check_rec(a,b,c)
    -#endif	/* DEBUG */
    -
    -/*
    - * Checking routine: check that long form block header is ok.
    - */
    -int					/* error (0 or EFSCORRUPTED) */
    -xfs_btree_check_lblock(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	xfs_btree_lblock_t	*block,	/* btree long form block pointer */
    -	int			level,	/* level of the btree block */
    -	struct xfs_buf		*bp);	/* buffer containing block, if any */
    -
    -/*
    - * Checking routine: check that (long) pointer is ok.
    - */
    -int					/* error (0 or EFSCORRUPTED) */
    -xfs_btree_check_lptr(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	xfs_dfsbno_t		ptr,	/* btree block disk address */
    -	int			level);	/* btree block level */
    -
    -/*
    - * Checking routine: check that short form block header is ok.
    - */
    -int					/* error (0 or EFSCORRUPTED) */
    -xfs_btree_check_sblock(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	xfs_btree_sblock_t	*block,	/* btree short form block pointer */
    -	int			level,	/* level of the btree block */
    -	struct xfs_buf		*bp);	/* buffer containing block */
    -
    -/*
    - * Checking routine: check that (short) pointer is ok.
    - */
    -int					/* error (0 or EFSCORRUPTED) */
    -xfs_btree_check_sptr(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	xfs_agblock_t		ptr,	/* btree block disk address */
    -	int			level);	/* btree block level */
    -
    -/*
    - * Delete the btree cursor.
    - */
    -void
    -xfs_btree_del_cursor(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	int			error);	/* del because of error */
    -
    -/*
    - * Duplicate the btree cursor.
    - * Allocate a new one, copy the record, re-get the buffers.
    - */
    -int					/* error */
    -xfs_btree_dup_cursor(
    -	xfs_btree_cur_t		*cur,	/* input cursor */
    -	xfs_btree_cur_t		**ncur);/* output cursor */
    -
    -/*
    - * Change the cursor to point to the first record in the current block
    - * at the given level.  Other levels are unaffected.
    - */
    -int					/* success=1, failure=0 */
    -xfs_btree_firstrec(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	int			level);	/* level to change */
    -
    -/*
    - * Get a buffer for the block, return it with no data read.
    - * Long-form addressing.
    - */
    -struct xfs_buf *				/* buffer for fsbno */
    -xfs_btree_get_bufl(
    -	struct xfs_mount	*mp,	/* file system mount point */
    -	struct xfs_trans	*tp,	/* transaction pointer */
    -	xfs_fsblock_t		fsbno,	/* file system block number */
    -	uint			lock);	/* lock flags for get_buf */
    -
    -/*
    - * Get a buffer for the block, return it with no data read.
    - * Short-form addressing.
    - */
    -struct xfs_buf *				/* buffer for agno/agbno */
    -xfs_btree_get_bufs(
    -	struct xfs_mount	*mp,	/* file system mount point */
    -	struct xfs_trans	*tp,	/* transaction pointer */
    -	xfs_agnumber_t		agno,	/* allocation group number */
    -	xfs_agblock_t		agbno,	/* allocation group block number */
    -	uint			lock);	/* lock flags for get_buf */
    -
    -/*
    - * Allocate a new btree cursor.
    - * The cursor is either for allocation (A) or bmap (B).
    - */
    -xfs_btree_cur_t *			/* new btree cursor */
    -xfs_btree_init_cursor(
    -	struct xfs_mount	*mp,	/* file system mount point */
    -	struct xfs_trans	*tp,	/* transaction pointer */
    -	struct xfs_buf		*agbp,	/* (A only) buffer for agf structure */
    -	xfs_agnumber_t		agno,	/* (A only) allocation group number */
    -	xfs_btnum_t		btnum,	/* btree identifier */
    -	struct xfs_inode	*ip,	/* (B only) inode owning the btree */
    -	int			whichfork); /* (B only) data/attr fork */
    -
    -/*
    - * Check for the cursor referring to the last block at the given level.
    - */
    -int					/* 1=is last block, 0=not last block */
    -xfs_btree_islastblock(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	int			level);	/* level to check */
    -
    -/*
    - * Change the cursor to point to the last record in the current block
    - * at the given level.  Other levels are unaffected.
    - */
    -int					/* success=1, failure=0 */
    -xfs_btree_lastrec(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	int			level);	/* level to change */
    -
    -/*
    - * Compute first and last byte offsets for the fields given.
    - * Interprets the offsets table, which contains struct field offsets.
    - */
    -void
    -xfs_btree_offsets(
    -	__int64_t		fields,	/* bitmask of fields */
    -	const short		*offsets,/* table of field offsets */
    -	int			nbits,	/* number of bits to inspect */
    -	int			*first,	/* output: first byte offset */
    -	int			*last);	/* output: last byte offset */
    -
    -/*
    - * Get a buffer for the block, return it read in.
    - * Long-form addressing.
    - */
    -int					/* error */
    -xfs_btree_read_bufl(
    -	struct xfs_mount	*mp,	/* file system mount point */
    -	struct xfs_trans	*tp,	/* transaction pointer */
    -	xfs_fsblock_t		fsbno,	/* file system block number */
    -	uint			lock,	/* lock flags for read_buf */
    -	struct xfs_buf		**bpp,	/* buffer for fsbno */
    -	int			refval);/* ref count value for buffer */
    -
    -/*
    - * Get a buffer for the block, return it read in.
    - * Short-form addressing.
    - */
    -int					/* error */
    -xfs_btree_read_bufs(
    -	struct xfs_mount	*mp,	/* file system mount point */
    -	struct xfs_trans	*tp,	/* transaction pointer */
    -	xfs_agnumber_t		agno,	/* allocation group number */
    -	xfs_agblock_t		agbno,	/* allocation group block number */
    -	uint			lock,	/* lock flags for read_buf */
    -	struct xfs_buf		**bpp,	/* buffer for agno/agbno */
    -	int			refval);/* ref count value for buffer */
    -
    -/*
    - * Read-ahead the block, don't wait for it, don't return a buffer.
    - * Long-form addressing.
    - */
    -void					/* error */
    -xfs_btree_reada_bufl(
    -	struct xfs_mount	*mp,	/* file system mount point */
    -	xfs_fsblock_t		fsbno,	/* file system block number */
    -	xfs_extlen_t		count);	/* count of filesystem blocks */
    -
    -/*
    - * Read-ahead the block, don't wait for it, don't return a buffer.
    - * Short-form addressing.
    - */
    -void					/* error */
    -xfs_btree_reada_bufs(
    -	struct xfs_mount	*mp,	/* file system mount point */
    -	xfs_agnumber_t		agno,	/* allocation group number */
    -	xfs_agblock_t		agbno,	/* allocation group block number */
    -	xfs_extlen_t		count);	/* count of filesystem blocks */
    -
    -/*
    - * Read-ahead btree blocks, at the given level.
    - * Bits in lr are set from XFS_BTCUR_{LEFT,RIGHT}RA.
    - */
    -int					/* readahead block count */
    -xfs_btree_readahead_core(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	int			lev,	/* level in btree */
    -	int			lr);	/* left/right bits */
    -
    -static inline int			/* readahead block count */
    -xfs_btree_readahead(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	int			lev,	/* level in btree */
    -	int			lr)	/* left/right bits */
    -{
    -	if ((cur->bc_ra[lev] | lr) == cur->bc_ra[lev])
    -		return 0;
    -
    -	return xfs_btree_readahead_core(cur, lev, lr);
    -}
    -
    -
    -/*
    - * Set the buffer for level "lev" in the cursor to bp, releasing
    - * any previous buffer.
    - */
    -void
    -xfs_btree_setbuf(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	int			lev,	/* level in btree */
    -	struct xfs_buf		*bp);	/* new buffer to set */
    -
    -#endif	/* __KERNEL__ */
    -
    -
    -/*
    - * Min and max functions for extlen, agblock, fileoff, and filblks types.
    - */
    -#define	XFS_EXTLEN_MIN(a,b)	\
    -	((xfs_extlen_t)(a) < (xfs_extlen_t)(b) ? \
    -		(xfs_extlen_t)(a) : (xfs_extlen_t)(b))
    -#define	XFS_EXTLEN_MAX(a,b)	\
    -	((xfs_extlen_t)(a) > (xfs_extlen_t)(b) ? \
    -		(xfs_extlen_t)(a) : (xfs_extlen_t)(b))
    -#define	XFS_AGBLOCK_MIN(a,b)	\
    -	((xfs_agblock_t)(a) < (xfs_agblock_t)(b) ? \
    -		(xfs_agblock_t)(a) : (xfs_agblock_t)(b))
    -#define	XFS_AGBLOCK_MAX(a,b)	\
    -	((xfs_agblock_t)(a) > (xfs_agblock_t)(b) ? \
    -		(xfs_agblock_t)(a) : (xfs_agblock_t)(b))
    -#define	XFS_FILEOFF_MIN(a,b)	\
    -	((xfs_fileoff_t)(a) < (xfs_fileoff_t)(b) ? \
    -		(xfs_fileoff_t)(a) : (xfs_fileoff_t)(b))
    -#define	XFS_FILEOFF_MAX(a,b)	\
    -	((xfs_fileoff_t)(a) > (xfs_fileoff_t)(b) ? \
    -		(xfs_fileoff_t)(a) : (xfs_fileoff_t)(b))
    -#define	XFS_FILBLKS_MIN(a,b)	\
    -	((xfs_filblks_t)(a) < (xfs_filblks_t)(b) ? \
    -		(xfs_filblks_t)(a) : (xfs_filblks_t)(b))
    -#define	XFS_FILBLKS_MAX(a,b)	\
    -	((xfs_filblks_t)(a) > (xfs_filblks_t)(b) ? \
    -		(xfs_filblks_t)(a) : (xfs_filblks_t)(b))
    -
    -#define	XFS_FSB_SANITY_CHECK(mp,fsb)	\
    -	(XFS_FSB_TO_AGNO(mp, fsb) < mp->m_sb.sb_agcount && \
    -		XFS_FSB_TO_AGBNO(mp, fsb) < mp->m_sb.sb_agblocks)
    -
    -#endif	/* __XFS_BTREE_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_buf_item.c b/sys/gnu/fs/xfs/xfs_buf_item.c
    deleted file mode 100644
    index 725057fe406..00000000000
    --- a/sys/gnu/fs/xfs/xfs_buf_item.c
    +++ /dev/null
    @@ -1,1203 +0,0 @@
    -/*
    - * Copyright (c) 2000-2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_dir.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_buf_item.h"
    -#include "xfs_trans_priv.h"
    -#include "xfs_error.h"
    -
    -
    -kmem_zone_t	*xfs_buf_item_zone;
    -
    -#ifdef XFS_TRANS_DEBUG
    -/*
    - * This function uses an alternate strategy for tracking the bytes
    - * that the user requests to be logged.  This can then be used
    - * in conjunction with the bli_orig array in the buf log item to
    - * catch bugs in our callers' code.
    - *
    - * We also double check the bits set in xfs_buf_item_log using a
    - * simple algorithm to check that every byte is accounted for.
    - */
    -STATIC void
    -xfs_buf_item_log_debug(
    -	xfs_buf_log_item_t	*bip,
    -	uint			first,
    -	uint			last)
    -{
    -	uint	x;
    -	uint	byte;
    -	uint	nbytes;
    -	uint	chunk_num;
    -	uint	word_num;
    -	uint	bit_num;
    -	uint	bit_set;
    -	uint	*wordp;
    -
    -	ASSERT(bip->bli_logged != NULL);
    -	byte = first;
    -	nbytes = last - first + 1;
    -	bfset(bip->bli_logged, first, nbytes);
    -	for (x = 0; x < nbytes; x++) {
    -		chunk_num = byte >> XFS_BLI_SHIFT;
    -		word_num = chunk_num >> BIT_TO_WORD_SHIFT;
    -		bit_num = chunk_num & (NBWORD - 1);
    -		wordp = &(bip->bli_format.blf_data_map[word_num]);
    -		bit_set = *wordp & (1 << bit_num);
    -		ASSERT(bit_set);
    -		byte++;
    -	}
    -}
    -
    -/*
    - * This function is called when we flush something into a buffer without
    - * logging it.  This happens for things like inodes which are logged
    - * separately from the buffer.
    - */
    -void
    -xfs_buf_item_flush_log_debug(
    -	xfs_buf_t	*bp,
    -	uint		first,
    -	uint		last)
    -{
    -	xfs_buf_log_item_t	*bip;
    -	uint			nbytes;
    -
    -	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*);
    -	if ((bip == NULL) || (bip->bli_item.li_type != XFS_LI_BUF)) {
    -		return;
    -	}
    -
    -	ASSERT(bip->bli_logged != NULL);
    -	nbytes = last - first + 1;
    -	bfset(bip->bli_logged, first, nbytes);
    -}
    -
    -/*
    - * This function is called to verify that our callers have logged
    - * all the bytes that they changed.
    - *
    - * It does this by comparing the original copy of the buffer stored in
    - * the buf log item's bli_orig array to the current copy of the buffer
    - * and ensuring that all bytes which mismatch are set in the bli_logged
    - * array of the buf log item.
    - */
    -STATIC void
    -xfs_buf_item_log_check(
    -	xfs_buf_log_item_t	*bip)
    -{
    -	char		*orig;
    -	char		*buffer;
    -	int		x;
    -	xfs_buf_t	*bp;
    -
    -	ASSERT(bip->bli_orig != NULL);
    -	ASSERT(bip->bli_logged != NULL);
    -
    -	bp = bip->bli_buf;
    -	ASSERT(XFS_BUF_COUNT(bp) > 0);
    -	ASSERT(XFS_BUF_PTR(bp) != NULL);
    -	orig = bip->bli_orig;
    -	buffer = XFS_BUF_PTR(bp);
    -	for (x = 0; x < XFS_BUF_COUNT(bp); x++) {
    -		if (orig[x] != buffer[x] && !btst(bip->bli_logged, x))
    -			cmn_err(CE_PANIC,
    -	"xfs_buf_item_log_check bip %x buffer %x orig %x index %d",
    -				bip, bp, orig, x);
    -	}
    -}
    -#else
    -#define		xfs_buf_item_log_debug(x,y,z)
    -#define		xfs_buf_item_log_check(x)
    -#endif
    -
    -STATIC void	xfs_buf_error_relse(xfs_buf_t *bp);
    -STATIC void	xfs_buf_do_callbacks(xfs_buf_t *bp, xfs_log_item_t *lip);
    -
    -/*
    - * This returns the number of log iovecs needed to log the
    - * given buf log item.
    - *
    - * It calculates this as 1 iovec for the buf log format structure
    - * and 1 for each stretch of non-contiguous chunks to be logged.
    - * Contiguous chunks are logged in a single iovec.
    - *
    - * If the XFS_BLI_STALE flag has been set, then log nothing.
    - */
    -STATIC uint
    -xfs_buf_item_size(
    -	xfs_buf_log_item_t	*bip)
    -{
    -	uint		nvecs;
    -	int		next_bit;
    -	int		last_bit;
    -	xfs_buf_t	*bp;
    -
    -	ASSERT(atomic_read(&bip->bli_refcount) > 0);
    -	if (bip->bli_flags & XFS_BLI_STALE) {
    -		/*
    -		 * The buffer is stale, so all we need to log
    -		 * is the buf log format structure with the
    -		 * cancel flag in it.
    -		 */
    -		xfs_buf_item_trace("SIZE STALE", bip);
    -		ASSERT(bip->bli_format.blf_flags & XFS_BLI_CANCEL);
    -		return 1;
    -	}
    -
    -	bp = bip->bli_buf;
    -	ASSERT(bip->bli_flags & XFS_BLI_LOGGED);
    -	nvecs = 1;
    -	last_bit = xfs_next_bit(bip->bli_format.blf_data_map,
    -					 bip->bli_format.blf_map_size, 0);
    -	ASSERT(last_bit != -1);
    -	nvecs++;
    -	while (last_bit != -1) {
    -		/*
    -		 * This takes the bit number to start looking from and
    -		 * returns the next set bit from there.  It returns -1
    -		 * if there are no more bits set or the start bit is
    -		 * beyond the end of the bitmap.
    -		 */
    -		next_bit = xfs_next_bit(bip->bli_format.blf_data_map,
    -						 bip->bli_format.blf_map_size,
    -						 last_bit + 1);
    -		/*
    -		 * If we run out of bits, leave the loop,
    -		 * else if we find a new set of bits bump the number of vecs,
    -		 * else keep scanning the current set of bits.
    -		 */
    -		if (next_bit == -1) {
    -			last_bit = -1;
    -		} else if (next_bit != last_bit + 1) {
    -			last_bit = next_bit;
    -			nvecs++;
    -		} else if (xfs_buf_offset(bp, next_bit * XFS_BLI_CHUNK) !=
    -			   (xfs_buf_offset(bp, last_bit * XFS_BLI_CHUNK) +
    -			    XFS_BLI_CHUNK)) {
    -			last_bit = next_bit;
    -			nvecs++;
    -		} else {
    -			last_bit++;
    -		}
    -	}
    -
    -	xfs_buf_item_trace("SIZE NORM", bip);
    -	return nvecs;
    -}
    -
    -/*
    - * This is called to fill in the vector of log iovecs for the
    - * given log buf item.  It fills the first entry with a buf log
    - * format structure, and the rest point to contiguous chunks
    - * within the buffer.
    - */
    -STATIC void
    -xfs_buf_item_format(
    -	xfs_buf_log_item_t	*bip,
    -	xfs_log_iovec_t		*log_vector)
    -{
    -	uint		base_size;
    -	uint		nvecs;
    -	xfs_log_iovec_t	*vecp;
    -	xfs_buf_t	*bp;
    -	int		first_bit;
    -	int		last_bit;
    -	int		next_bit;
    -	uint		nbits;
    -	uint		buffer_offset;
    -
    -	ASSERT(atomic_read(&bip->bli_refcount) > 0);
    -	ASSERT((bip->bli_flags & XFS_BLI_LOGGED) ||
    -	       (bip->bli_flags & XFS_BLI_STALE));
    -	bp = bip->bli_buf;
    -	ASSERT(XFS_BUF_BP_ISMAPPED(bp));
    -	vecp = log_vector;
    -
    -	/*
    -	 * The size of the base structure is the size of the
    -	 * declared structure plus the space for the extra words
    -	 * of the bitmap.  We subtract one from the map size, because
    -	 * the first element of the bitmap is accounted for in the
    -	 * size of the base structure.
    -	 */
    -	base_size =
    -		(uint)(sizeof(xfs_buf_log_format_t) +
    -		       ((bip->bli_format.blf_map_size - 1) * sizeof(uint)));
    -	vecp->i_addr = (xfs_caddr_t)&bip->bli_format;
    -	vecp->i_len = base_size;
    -	XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_BFORMAT);
    -	vecp++;
    -	nvecs = 1;
    -
    -	if (bip->bli_flags & XFS_BLI_STALE) {
    -		/*
    -		 * The buffer is stale, so all we need to log
    -		 * is the buf log format structure with the
    -		 * cancel flag in it.
    -		 */
    -		xfs_buf_item_trace("FORMAT STALE", bip);
    -		ASSERT(bip->bli_format.blf_flags & XFS_BLI_CANCEL);
    -		bip->bli_format.blf_size = nvecs;
    -		return;
    -	}
    -
    -	/*
    -	 * Fill in an iovec for each set of contiguous chunks.
    -	 */
    -	first_bit = xfs_next_bit(bip->bli_format.blf_data_map,
    -					 bip->bli_format.blf_map_size, 0);
    -	ASSERT(first_bit != -1);
    -	last_bit = first_bit;
    -	nbits = 1;
    -	for (;;) {
    -		/*
    -		 * This takes the bit number to start looking from and
    -		 * returns the next set bit from there.  It returns -1
    -		 * if there are no more bits set or the start bit is
    -		 * beyond the end of the bitmap.
    -		 */
    -		next_bit = xfs_next_bit(bip->bli_format.blf_data_map,
    -						 bip->bli_format.blf_map_size,
    -						 (uint)last_bit + 1);
    -		/*
    -		 * If we run out of bits fill in the last iovec and get
    -		 * out of the loop.
    -		 * Else if we start a new set of bits then fill in the
    -		 * iovec for the series we were looking at and start
    -		 * counting the bits in the new one.
    -		 * Else we're still in the same set of bits so just
    -		 * keep counting and scanning.
    -		 */
    -		if (next_bit == -1) {
    -			buffer_offset = first_bit * XFS_BLI_CHUNK;
    -			vecp->i_addr = xfs_buf_offset(bp, buffer_offset);
    -			vecp->i_len = nbits * XFS_BLI_CHUNK;
    -			XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_BCHUNK);
    -			nvecs++;
    -			break;
    -		} else if (next_bit != last_bit + 1) {
    -			buffer_offset = first_bit * XFS_BLI_CHUNK;
    -			vecp->i_addr = xfs_buf_offset(bp, buffer_offset);
    -			vecp->i_len = nbits * XFS_BLI_CHUNK;
    -			XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_BCHUNK);
    -			nvecs++;
    -			vecp++;
    -			first_bit = next_bit;
    -			last_bit = next_bit;
    -			nbits = 1;
    -		} else if (xfs_buf_offset(bp, next_bit << XFS_BLI_SHIFT) !=
    -			   (xfs_buf_offset(bp, last_bit << XFS_BLI_SHIFT) +
    -			    XFS_BLI_CHUNK)) {
    -			buffer_offset = first_bit * XFS_BLI_CHUNK;
    -			vecp->i_addr = xfs_buf_offset(bp, buffer_offset);
    -			vecp->i_len = nbits * XFS_BLI_CHUNK;
    -			XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_BCHUNK);
    -/* You would think we need to bump the nvecs here too, but we do not
    - * this number is used by recovery, and it gets confused by the boundary
    - * split here
    - *			nvecs++;
    - */
    -			vecp++;
    -			first_bit = next_bit;
    -			last_bit = next_bit;
    -			nbits = 1;
    -		} else {
    -			last_bit++;
    -			nbits++;
    -		}
    -	}
    -	bip->bli_format.blf_size = nvecs;
    -
    -	/*
    -	 * Check to make sure everything is consistent.
    -	 */
    -	xfs_buf_item_trace("FORMAT NORM", bip);
    -	xfs_buf_item_log_check(bip);
    -}
    -
    -/*
    - * This is called to pin the buffer associated with the buf log
    - * item in memory so it cannot be written out.  Simply call bpin()
    - * on the buffer to do this.
    - */
    -STATIC void
    -xfs_buf_item_pin(
    -	xfs_buf_log_item_t	*bip)
    -{
    -	xfs_buf_t	*bp;
    -
    -	bp = bip->bli_buf;
    -	ASSERT(XFS_BUF_ISBUSY(bp));
    -	ASSERT(atomic_read(&bip->bli_refcount) > 0);
    -	ASSERT((bip->bli_flags & XFS_BLI_LOGGED) ||
    -	       (bip->bli_flags & XFS_BLI_STALE));
    -	xfs_buf_item_trace("PIN", bip);
    -	xfs_buftrace("XFS_PIN", bp);
    -	xfs_bpin(bp);
    -}
    -
    -
    -/*
    - * This is called to unpin the buffer associated with the buf log
    - * item which was previously pinned with a call to xfs_buf_item_pin().
    - * Just call bunpin() on the buffer to do this.
    - *
    - * Also drop the reference to the buf item for the current transaction.
    - * If the XFS_BLI_STALE flag is set and we are the last reference,
    - * then free up the buf log item and unlock the buffer.
    - */
    -STATIC void
    -xfs_buf_item_unpin(
    -	xfs_buf_log_item_t	*bip,
    -	int			stale)
    -{
    -	xfs_mount_t	*mp;
    -	xfs_buf_t	*bp;
    -	int		freed;
    -	SPLDECL(s);
    -
    -	bp = bip->bli_buf;
    -	ASSERT(bp != NULL);
    -	ASSERT(XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *) == bip);
    -	ASSERT(atomic_read(&bip->bli_refcount) > 0);
    -	xfs_buf_item_trace("UNPIN", bip);
    -	xfs_buftrace("XFS_UNPIN", bp);
    -
    -	freed = atomic_dec_and_test(&bip->bli_refcount);
    -	mp = bip->bli_item.li_mountp;
    -	xfs_bunpin(bp);
    -	if (freed && stale) {
    -		ASSERT(bip->bli_flags & XFS_BLI_STALE);
    -		ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);
    -		ASSERT(!(XFS_BUF_ISDELAYWRITE(bp)));
    -		ASSERT(XFS_BUF_ISSTALE(bp));
    -		ASSERT(bip->bli_format.blf_flags & XFS_BLI_CANCEL);
    -		xfs_buf_item_trace("UNPIN STALE", bip);
    -		xfs_buftrace("XFS_UNPIN STALE", bp);
    -		/*
    -		 * If we get called here because of an IO error, we may
    -		 * or may not have the item on the AIL. xfs_trans_delete_ail()
    -		 * will take care of that situation.
    -		 * xfs_trans_delete_ail() drops the AIL lock.
    -		 */
    -		if (bip->bli_flags & XFS_BLI_STALE_INODE) {
    -			xfs_buf_do_callbacks(bp, (xfs_log_item_t *)bip);
    -			XFS_BUF_SET_FSPRIVATE(bp, NULL);
    -			XFS_BUF_CLR_IODONE_FUNC(bp);
    -		} else {
    -			AIL_LOCK(mp,s);
    -			xfs_trans_delete_ail(mp, (xfs_log_item_t *)bip, s);
    -			xfs_buf_item_relse(bp);
    -			ASSERT(XFS_BUF_FSPRIVATE(bp, void *) == NULL);
    -		}
    -		xfs_buf_relse(bp);
    -	}
    -}
    -
    -/*
    - * this is called from uncommit in the forced-shutdown path.
    - * we need to check to see if the reference count on the log item
    - * is going to drop to zero.  If so, unpin will free the log item
    - * so we need to free the item's descriptor (that points to the item)
    - * in the transaction.
    - */
    -STATIC void
    -xfs_buf_item_unpin_remove(
    -	xfs_buf_log_item_t	*bip,
    -	xfs_trans_t		*tp)
    -{
    -	xfs_buf_t		*bp;
    -	xfs_log_item_desc_t	*lidp;
    -	int			stale = 0;
    -
    -	bp = bip->bli_buf;
    -	/*
    -	 * will xfs_buf_item_unpin() call xfs_buf_item_relse()?
    -	 */
    -	if ((atomic_read(&bip->bli_refcount) == 1) &&
    -	    (bip->bli_flags & XFS_BLI_STALE)) {
    -		ASSERT(XFS_BUF_VALUSEMA(bip->bli_buf) <= 0);
    -		xfs_buf_item_trace("UNPIN REMOVE", bip);
    -		xfs_buftrace("XFS_UNPIN_REMOVE", bp);
    -		/*
    -		 * yes -- clear the xaction descriptor in-use flag
    -		 * and free the chunk if required.  We can safely
    -		 * do some work here and then call buf_item_unpin
    -		 * to do the rest because if the if is true, then
    -		 * we are holding the buffer locked so no one else
    -		 * will be able to bump up the refcount.
    -		 */
    -		lidp = xfs_trans_find_item(tp, (xfs_log_item_t *) bip);
    -		stale = lidp->lid_flags & XFS_LID_BUF_STALE;
    -		xfs_trans_free_item(tp, lidp);
    -		/*
    -		 * Since the transaction no longer refers to the buffer,
    -		 * the buffer should no longer refer to the transaction.
    -		 */
    -		XFS_BUF_SET_FSPRIVATE2(bp, NULL);
    -	}
    -
    -	xfs_buf_item_unpin(bip, stale);
    -
    -	return;
    -}
    -
    -/*
    - * This is called to attempt to lock the buffer associated with this
    - * buf log item.  Don't sleep on the buffer lock.  If we can't get
    - * the lock right away, return 0.  If we can get the lock, pull the
    - * buffer from the free list, mark it busy, and return 1.
    - */
    -STATIC uint
    -xfs_buf_item_trylock(
    -	xfs_buf_log_item_t	*bip)
    -{
    -	xfs_buf_t	*bp;
    -
    -	bp = bip->bli_buf;
    -
    -	if (XFS_BUF_ISPINNED(bp)) {
    -		return XFS_ITEM_PINNED;
    -	}
    -
    -	if (!XFS_BUF_CPSEMA(bp)) {
    -		return XFS_ITEM_LOCKED;
    -	}
    -
    -	/*
    -	 * Remove the buffer from the free list.  Only do this
    -	 * if it's on the free list.  Private buffers like the
    -	 * superblock buffer are not.
    -	 */
    -	XFS_BUF_HOLD(bp);
    -
    -	ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
    -	xfs_buf_item_trace("TRYLOCK SUCCESS", bip);
    -	return XFS_ITEM_SUCCESS;
    -}
    -
    -/*
    - * Release the buffer associated with the buf log item.
    - * If there is no dirty logged data associated with the
    - * buffer recorded in the buf log item, then free the
    - * buf log item and remove the reference to it in the
    - * buffer.
    - *
    - * This call ignores the recursion count.  It is only called
    - * when the buffer should REALLY be unlocked, regardless
    - * of the recursion count.
    - *
    - * If the XFS_BLI_HOLD flag is set in the buf log item, then
    - * free the log item if necessary but do not unlock the buffer.
    - * This is for support of xfs_trans_bhold(). Make sure the
    - * XFS_BLI_HOLD field is cleared if we don't free the item.
    - */
    -STATIC void
    -xfs_buf_item_unlock(
    -	xfs_buf_log_item_t	*bip)
    -{
    -	int		aborted;
    -	xfs_buf_t	*bp;
    -	uint		hold;
    -
    -	bp = bip->bli_buf;
    -	xfs_buftrace("XFS_UNLOCK", bp);
    -
    -	/*
    -	 * Clear the buffer's association with this transaction.
    -	 */
    -	XFS_BUF_SET_FSPRIVATE2(bp, NULL);
    -
    -	/*
    -	 * If this is a transaction abort, don't return early.
    -	 * Instead, allow the brelse to happen.
    -	 * Normally it would be done for stale (cancelled) buffers
    -	 * at unpin time, but we'll never go through the pin/unpin
    -	 * cycle if we abort inside commit.
    -	 */
    -	aborted = (bip->bli_item.li_flags & XFS_LI_ABORTED) != 0;
    -
    -	/*
    -	 * If the buf item is marked stale, then don't do anything.
    -	 * We'll unlock the buffer and free the buf item when the
    -	 * buffer is unpinned for the last time.
    -	 */
    -	if (bip->bli_flags & XFS_BLI_STALE) {
    -		bip->bli_flags &= ~XFS_BLI_LOGGED;
    -		xfs_buf_item_trace("UNLOCK STALE", bip);
    -		ASSERT(bip->bli_format.blf_flags & XFS_BLI_CANCEL);
    -		if (!aborted)
    -			return;
    -	}
    -
    -	/*
    -	 * Drop the transaction's reference to the log item if
    -	 * it was not logged as part of the transaction.  Otherwise
    -	 * we'll drop the reference in xfs_buf_item_unpin() when
    -	 * the transaction is really through with the buffer.
    -	 */
    -	if (!(bip->bli_flags & XFS_BLI_LOGGED)) {
    -		atomic_dec(&bip->bli_refcount);
    -	} else {
    -		/*
    -		 * Clear the logged flag since this is per
    -		 * transaction state.
    -		 */
    -		bip->bli_flags &= ~XFS_BLI_LOGGED;
    -	}
    -
    -	/*
    -	 * Before possibly freeing the buf item, determine if we should
    -	 * release the buffer at the end of this routine.
    -	 */
    -	hold = bip->bli_flags & XFS_BLI_HOLD;
    -	xfs_buf_item_trace("UNLOCK", bip);
    -
    -	/*
    -	 * If the buf item isn't tracking any data, free it.
    -	 * Otherwise, if XFS_BLI_HOLD is set clear it.
    -	 */
    -	if (xfs_count_bits(bip->bli_format.blf_data_map,
    -			      bip->bli_format.blf_map_size, 0) == 0) {
    -		xfs_buf_item_relse(bp);
    -	} else if (hold) {
    -		bip->bli_flags &= ~XFS_BLI_HOLD;
    -	}
    -
    -	/*
    -	 * Release the buffer if XFS_BLI_HOLD was not set.
    -	 */
    -	if (!hold) {
    -		xfs_buf_relse(bp);
    -	}
    -}
    -
    -/*
    - * This is called to find out where the oldest active copy of the
    - * buf log item in the on disk log resides now that the last log
    - * write of it completed at the given lsn.
    - * We always re-log all the dirty data in a buffer, so usually the
    - * latest copy in the on disk log is the only one that matters.  For
    - * those cases we simply return the given lsn.
    - *
    - * The one exception to this is for buffers full of newly allocated
    - * inodes.  These buffers are only relogged with the XFS_BLI_INODE_BUF
    - * flag set, indicating that only the di_next_unlinked fields from the
    - * inodes in the buffers will be replayed during recovery.  If the
    - * original newly allocated inode images have not yet been flushed
    - * when the buffer is so relogged, then we need to make sure that we
    - * keep the old images in the 'active' portion of the log.  We do this
    - * by returning the original lsn of that transaction here rather than
    - * the current one.
    - */
    -STATIC xfs_lsn_t
    -xfs_buf_item_committed(
    -	xfs_buf_log_item_t	*bip,
    -	xfs_lsn_t		lsn)
    -{
    -	xfs_buf_item_trace("COMMITTED", bip);
    -	if ((bip->bli_flags & XFS_BLI_INODE_ALLOC_BUF) &&
    -	    (bip->bli_item.li_lsn != 0)) {
    -		return bip->bli_item.li_lsn;
    -	}
    -	return (lsn);
    -}
    -
    -/*
    - * This is called when the transaction holding the buffer is aborted.
    - * Just behave as if the transaction had been cancelled. If we're shutting down
    - * and have aborted this transaction, we'll trap this buffer when it tries to
    - * get written out.
    - */
    -STATIC void
    -xfs_buf_item_abort(
    -	xfs_buf_log_item_t	*bip)
    -{
    -	xfs_buf_t	*bp;
    -
    -	bp = bip->bli_buf;
    -	xfs_buftrace("XFS_ABORT", bp);
    -	XFS_BUF_SUPER_STALE(bp);
    -	xfs_buf_item_unlock(bip);
    -	return;
    -}
    -
    -/*
    - * This is called to asynchronously write the buffer associated with this
    - * buf log item out to disk. The buffer will already have been locked by
    - * a successful call to xfs_buf_item_trylock().  If the buffer still has
    - * B_DELWRI set, then get it going out to disk with a call to bawrite().
    - * If not, then just release the buffer.
    - */
    -STATIC void
    -xfs_buf_item_push(
    -	xfs_buf_log_item_t	*bip)
    -{
    -	xfs_buf_t	*bp;
    -
    -	ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
    -	xfs_buf_item_trace("PUSH", bip);
    -
    -	bp = bip->bli_buf;
    -
    -	if (XFS_BUF_ISDELAYWRITE(bp)) {
    -		xfs_bawrite(bip->bli_item.li_mountp, bp);
    -	} else {
    -		xfs_buf_relse(bp);
    -	}
    -}
    -
    -/* ARGSUSED */
    -STATIC void
    -xfs_buf_item_committing(xfs_buf_log_item_t *bip, xfs_lsn_t commit_lsn)
    -{
    -}
    -
    -/*
    - * This is the ops vector shared by all buf log items.
    - */
    -STATIC struct xfs_item_ops xfs_buf_item_ops = {
    -	.iop_size	= (uint(*)(xfs_log_item_t*))xfs_buf_item_size,
    -	.iop_format	= (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
    -					xfs_buf_item_format,
    -	.iop_pin	= (void(*)(xfs_log_item_t*))xfs_buf_item_pin,
    -	.iop_unpin	= (void(*)(xfs_log_item_t*, int))xfs_buf_item_unpin,
    -	.iop_unpin_remove = (void(*)(xfs_log_item_t*, xfs_trans_t *))
    -					xfs_buf_item_unpin_remove,
    -	.iop_trylock	= (uint(*)(xfs_log_item_t*))xfs_buf_item_trylock,
    -	.iop_unlock	= (void(*)(xfs_log_item_t*))xfs_buf_item_unlock,
    -	.iop_committed	= (xfs_lsn_t(*)(xfs_log_item_t*, xfs_lsn_t))
    -					xfs_buf_item_committed,
    -	.iop_push	= (void(*)(xfs_log_item_t*))xfs_buf_item_push,
    -	.iop_abort	= (void(*)(xfs_log_item_t*))xfs_buf_item_abort,
    -	.iop_pushbuf	= NULL,
    -	.iop_committing = (void(*)(xfs_log_item_t*, xfs_lsn_t))
    -					xfs_buf_item_committing
    -};
    -
    -
    -/*
    - * Allocate a new buf log item to go with the given buffer.
    - * Set the buffer's b_fsprivate field to point to the new
    - * buf log item.  If there are other item's attached to the
    - * buffer (see xfs_buf_attach_iodone() below), then put the
    - * buf log item at the front.
    - */
    -void
    -xfs_buf_item_init(
    -	xfs_buf_t	*bp,
    -	xfs_mount_t	*mp)
    -{
    -	xfs_log_item_t		*lip;
    -	xfs_buf_log_item_t	*bip;
    -	int			chunks;
    -	int			map_size;
    -
    -	/*
    -	 * Check to see if there is already a buf log item for
    -	 * this buffer.  If there is, it is guaranteed to be
    -	 * the first.  If we do already have one, there is
    -	 * nothing to do here so return.
    -	 */
    -	if (XFS_BUF_FSPRIVATE3(bp, xfs_mount_t *) != mp)
    -		XFS_BUF_SET_FSPRIVATE3(bp, mp);
    -	XFS_BUF_SET_BDSTRAT_FUNC(bp, xfs_bdstrat_cb);
    -	if (XFS_BUF_FSPRIVATE(bp, void *) != NULL) {
    -		lip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *);
    -		if (lip->li_type == XFS_LI_BUF) {
    -			return;
    -		}
    -	}
    -
    -	/*
    -	 * chunks is the number of XFS_BLI_CHUNK size pieces
    -	 * the buffer can be divided into. Make sure not to
    -	 * truncate any pieces.  map_size is the size of the
    -	 * bitmap needed to describe the chunks of the buffer.
    -	 */
    -	chunks = (int)((XFS_BUF_COUNT(bp) + (XFS_BLI_CHUNK - 1)) >> XFS_BLI_SHIFT);
    -	map_size = (int)((chunks + NBWORD) >> BIT_TO_WORD_SHIFT);
    -
    -	bip = (xfs_buf_log_item_t*)kmem_zone_zalloc(xfs_buf_item_zone,
    -						    KM_SLEEP);
    -	bip->bli_item.li_type = XFS_LI_BUF;
    -	bip->bli_item.li_ops = &xfs_buf_item_ops;
    -	bip->bli_item.li_mountp = mp;
    -	bip->bli_buf = bp;
    -	bip->bli_format.blf_type = XFS_LI_BUF;
    -	bip->bli_format.blf_blkno = (__int64_t)XFS_BUF_ADDR(bp);
    -	bip->bli_format.blf_len = (ushort)BTOBB(XFS_BUF_COUNT(bp));
    -	bip->bli_format.blf_map_size = map_size;
    -#ifdef XFS_BLI_TRACE
    -	bip->bli_trace = ktrace_alloc(XFS_BLI_TRACE_SIZE, KM_SLEEP);
    -#endif
    -
    -#ifdef XFS_TRANS_DEBUG
    -	/*
    -	 * Allocate the arrays for tracking what needs to be logged
    -	 * and what our callers request to be logged.  bli_orig
    -	 * holds a copy of the original, clean buffer for comparison
    -	 * against, and bli_logged keeps a 1 bit flag per byte in
    -	 * the buffer to indicate which bytes the callers have asked
    -	 * to have logged.
    -	 */
    -	bip->bli_orig = (char *)kmem_alloc(XFS_BUF_COUNT(bp), KM_SLEEP);
    -	memcpy(bip->bli_orig, XFS_BUF_PTR(bp), XFS_BUF_COUNT(bp));
    -	bip->bli_logged = (char *)kmem_zalloc(XFS_BUF_COUNT(bp) / NBBY, KM_SLEEP);
    -#endif
    -
    -	/*
    -	 * Put the buf item into the list of items attached to the
    -	 * buffer at the front.
    -	 */
    -	if (XFS_BUF_FSPRIVATE(bp, void *) != NULL) {
    -		bip->bli_item.li_bio_list =
    -				XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *);
    -	}
    -	XFS_BUF_SET_FSPRIVATE(bp, bip);
    -}
    -
    -
    -/*
    - * Mark bytes first through last inclusive as dirty in the buf
    - * item's bitmap.
    - */
    -void
    -xfs_buf_item_log(
    -	xfs_buf_log_item_t	*bip,
    -	uint			first,
    -	uint			last)
    -{
    -	uint		first_bit;
    -	uint		last_bit;
    -	uint		bits_to_set;
    -	uint		bits_set;
    -	uint		word_num;
    -	uint		*wordp;
    -	uint		bit;
    -	uint		end_bit;
    -	uint		mask;
    -
    -	/*
    -	 * Mark the item as having some dirty data for
    -	 * quick reference in xfs_buf_item_dirty.
    -	 */
    -	bip->bli_flags |= XFS_BLI_DIRTY;
    -
    -	/*
    -	 * Convert byte offsets to bit numbers.
    -	 */
    -	first_bit = first >> XFS_BLI_SHIFT;
    -	last_bit = last >> XFS_BLI_SHIFT;
    -
    -	/*
    -	 * Calculate the total number of bits to be set.
    -	 */
    -	bits_to_set = last_bit - first_bit + 1;
    -
    -	/*
    -	 * Get a pointer to the first word in the bitmap
    -	 * to set a bit in.
    -	 */
    -	word_num = first_bit >> BIT_TO_WORD_SHIFT;
    -	wordp = &(bip->bli_format.blf_data_map[word_num]);
    -
    -	/*
    -	 * Calculate the starting bit in the first word.
    -	 */
    -	bit = first_bit & (uint)(NBWORD - 1);
    -
    -	/*
    -	 * First set any bits in the first word of our range.
    -	 * If it starts at bit 0 of the word, it will be
    -	 * set below rather than here.  That is what the variable
    -	 * bit tells us. The variable bits_set tracks the number
    -	 * of bits that have been set so far.  End_bit is the number
    -	 * of the last bit to be set in this word plus one.
    -	 */
    -	if (bit) {
    -		end_bit = MIN(bit + bits_to_set, (uint)NBWORD);
    -		mask = ((1 << (end_bit - bit)) - 1) << bit;
    -		*wordp |= mask;
    -		wordp++;
    -		bits_set = end_bit - bit;
    -	} else {
    -		bits_set = 0;
    -	}
    -
    -	/*
    -	 * Now set bits a whole word at a time that are between
    -	 * first_bit and last_bit.
    -	 */
    -	while ((bits_to_set - bits_set) >= NBWORD) {
    -		*wordp |= 0xffffffff;
    -		bits_set += NBWORD;
    -		wordp++;
    -	}
    -
    -	/*
    -	 * Finally, set any bits left to be set in one last partial word.
    -	 */
    -	end_bit = bits_to_set - bits_set;
    -	if (end_bit) {
    -		mask = (1 << end_bit) - 1;
    -		*wordp |= mask;
    -	}
    -
    -	xfs_buf_item_log_debug(bip, first, last);
    -}
    -
    -
    -/*
    - * Return 1 if the buffer has some data that has been logged (at any
    - * point, not just the current transaction) and 0 if not.
    - */
    -uint
    -xfs_buf_item_dirty(
    -	xfs_buf_log_item_t	*bip)
    -{
    -	return (bip->bli_flags & XFS_BLI_DIRTY);
    -}
    -
    -/*
    - * This is called when the buf log item is no longer needed.  It should
    - * free the buf log item associated with the given buffer and clear
    - * the buffer's pointer to the buf log item.  If there are no more
    - * items in the list, clear the b_iodone field of the buffer (see
    - * xfs_buf_attach_iodone() below).
    - */
    -void
    -xfs_buf_item_relse(
    -	xfs_buf_t	*bp)
    -{
    -	xfs_buf_log_item_t	*bip;
    -
    -	xfs_buftrace("XFS_RELSE", bp);
    -	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*);
    -	XFS_BUF_SET_FSPRIVATE(bp, bip->bli_item.li_bio_list);
    -	if ((XFS_BUF_FSPRIVATE(bp, void *) == NULL) &&
    -	    (XFS_BUF_IODONE_FUNC(bp) != NULL)) {
    -		ASSERT((XFS_BUF_ISUNINITIAL(bp)) == 0);
    -		XFS_BUF_CLR_IODONE_FUNC(bp);
    -	}
    -
    -#ifdef XFS_TRANS_DEBUG
    -	kmem_free(bip->bli_orig, XFS_BUF_COUNT(bp));
    -	bip->bli_orig = NULL;
    -	kmem_free(bip->bli_logged, XFS_BUF_COUNT(bp) / NBBY);
    -	bip->bli_logged = NULL;
    -#endif /* XFS_TRANS_DEBUG */
    -
    -#ifdef XFS_BLI_TRACE
    -	ktrace_free(bip->bli_trace);
    -#endif
    -	kmem_zone_free(xfs_buf_item_zone, bip);
    -}
    -
    -
    -/*
    - * Add the given log item with its callback to the list of callbacks
    - * to be called when the buffer's I/O completes.  If it is not set
    - * already, set the buffer's b_iodone() routine to be
    - * xfs_buf_iodone_callbacks() and link the log item into the list of
    - * items rooted at b_fsprivate.  Items are always added as the second
    - * entry in the list if there is a first, because the buf item code
    - * assumes that the buf log item is first.
    - */
    -void
    -xfs_buf_attach_iodone(
    -	xfs_buf_t	*bp,
    -	void		(*cb)(xfs_buf_t *, xfs_log_item_t *),
    -	xfs_log_item_t	*lip)
    -{
    -	xfs_log_item_t	*head_lip;
    -
    -	ASSERT(XFS_BUF_ISBUSY(bp));
    -	ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);
    -
    -	lip->li_cb = cb;
    -	if (XFS_BUF_FSPRIVATE(bp, void *) != NULL) {
    -		head_lip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *);
    -		lip->li_bio_list = head_lip->li_bio_list;
    -		head_lip->li_bio_list = lip;
    -	} else {
    -		XFS_BUF_SET_FSPRIVATE(bp, lip);
    -	}
    -
    -	ASSERT((XFS_BUF_IODONE_FUNC(bp) == xfs_buf_iodone_callbacks) ||
    -	       (XFS_BUF_IODONE_FUNC(bp) == NULL));
    -	XFS_BUF_SET_IODONE_FUNC(bp, xfs_buf_iodone_callbacks);
    -}
    -
    -STATIC void
    -xfs_buf_do_callbacks(
    -	xfs_buf_t	*bp,
    -	xfs_log_item_t	*lip)
    -{
    -	xfs_log_item_t	*nlip;
    -
    -	while (lip != NULL) {
    -		nlip = lip->li_bio_list;
    -		ASSERT(lip->li_cb != NULL);
    -		/*
    -		 * Clear the next pointer so we don't have any
    -		 * confusion if the item is added to another buf.
    -		 * Don't touch the log item after calling its
    -		 * callback, because it could have freed itself.
    -		 */
    -		lip->li_bio_list = NULL;
    -		lip->li_cb(bp, lip);
    -		lip = nlip;
    -	}
    -}
    -
    -/*
    - * This is the iodone() function for buffers which have had callbacks
    - * attached to them by xfs_buf_attach_iodone().  It should remove each
    - * log item from the buffer's list and call the callback of each in turn.
    - * When done, the buffer's fsprivate field is set to NULL and the buffer
    - * is unlocked with a call to iodone().
    - */
    -void
    -xfs_buf_iodone_callbacks(
    -	xfs_buf_t	*bp)
    -{
    -	xfs_log_item_t	*lip;
    -	static ulong	lasttime;
    -	static xfs_buftarg_t *lasttarg;
    -	xfs_mount_t	*mp;
    -
    -	ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL);
    -	lip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *);
    -
    -	if (XFS_BUF_GETERROR(bp) != 0) {
    -		/*
    -		 * If we've already decided to shutdown the filesystem
    -		 * because of IO errors, there's no point in giving this
    -		 * a retry.
    -		 */
    -		mp = lip->li_mountp;
    -		if (XFS_FORCED_SHUTDOWN(mp)) {
    -			ASSERT(XFS_BUF_TARGET(bp) == mp->m_ddev_targp);
    -			XFS_BUF_SUPER_STALE(bp);
    -			xfs_buftrace("BUF_IODONE_CB", bp);
    -			xfs_buf_do_callbacks(bp, lip);
    -			XFS_BUF_SET_FSPRIVATE(bp, NULL);
    -			XFS_BUF_CLR_IODONE_FUNC(bp);
    -
    -			/*
    -			 * XFS_SHUT flag gets set when we go thru the
    -			 * entire buffer cache and deliberately start
    -			 * throwing away delayed write buffers.
    -			 * Since there's no biowait done on those,
    -			 * we should just brelse them.
    -			 */
    -			if (XFS_BUF_ISSHUT(bp)) {
    -			    XFS_BUF_UNSHUT(bp);
    -				xfs_buf_relse(bp);
    -			} else {
    -				xfs_biodone(bp);
    -			}
    -
    -			return;
    -		}
    -
    -		if ((XFS_BUF_TARGET(bp) != lasttarg) ||
    -		    (ticks >  (lasttime + 5*HZ))) {
    -			lasttime = ticks;
    -			prdev("XFS write error in file system meta-data "
    -			      "block 0x%jx in %s",
    -			      XFS_BUF_TARGET(bp),
    -			      (uintmax_t)XFS_BUF_ADDR(bp), mp->m_fsname);
    -		}
    -		lasttarg = XFS_BUF_TARGET(bp);
    -
    -		if (XFS_BUF_ISASYNC(bp)) {
    -			/*
    -			 * If the write was asynchronous then noone will be
    -			 * looking for the error.  Clear the error state
    -			 * and write the buffer out again delayed write.
    -			 *
    -			 * XXXsup This is OK, so long as we catch these
    -			 * before we start the umount; we don't want these
    -			 * DELWRI metadata bufs to be hanging around.
    -			 */
    -			XFS_BUF_ERROR(bp,0); /* errno of 0 unsets the flag */
    -
    -			if (!(XFS_BUF_ISSTALE(bp))) {
    -				XFS_BUF_DELAYWRITE(bp);
    -				XFS_BUF_DONE(bp);
    -				XFS_BUF_SET_START(bp);
    -			}
    -			ASSERT(XFS_BUF_IODONE_FUNC(bp));
    -			xfs_buftrace("BUF_IODONE ASYNC", bp);
    -			xfs_buf_relse(bp);
    -		} else {
    -			/*
    -			 * If the write of the buffer was not asynchronous,
    -			 * then we want to make sure to return the error
    -			 * to the caller of bwrite().  Because of this we
    -			 * cannot clear the B_ERROR state at this point.
    -			 * Instead we install a callback function that
    -			 * will be called when the buffer is released, and
    -			 * that routine will clear the error state and
    -			 * set the buffer to be written out again after
    -			 * some delay.
    -			 */
    -			/* We actually overwrite the existing b-relse
    -			   function at times, but we're gonna be shutting down
    -			   anyway. */
    -			XFS_BUF_SET_BRELSE_FUNC(bp,xfs_buf_error_relse);
    -			XFS_BUF_DONE(bp);
    -			XFS_BUF_V_IODONESEMA(bp);
    -		}
    -		return;
    -	}
    -#ifdef XFSERRORDEBUG
    -	xfs_buftrace("XFS BUFCB NOERR", bp);
    -#endif
    -	xfs_buf_do_callbacks(bp, lip);
    -	XFS_BUF_SET_FSPRIVATE(bp, NULL);
    -	XFS_BUF_CLR_IODONE_FUNC(bp);
    -	xfs_biodone(bp);
    -}
    -
    -/*
    - * This is a callback routine attached to a buffer which gets an error
    - * when being written out synchronously.
    - */
    -STATIC void
    -xfs_buf_error_relse(
    -	xfs_buf_t	*bp)
    -{
    -	xfs_log_item_t	*lip;
    -	xfs_mount_t	*mp;
    -
    -	lip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *);
    -	mp = (xfs_mount_t *)lip->li_mountp;
    -	ASSERT(XFS_BUF_TARGET(bp) == mp->m_ddev_targp);
    -
    -	XFS_BUF_STALE(bp);
    -	XFS_BUF_DONE(bp);
    -	XFS_BUF_UNDELAYWRITE(bp);
    -	XFS_BUF_ERROR(bp,0);
    -	xfs_buftrace("BUF_ERROR_RELSE", bp);
    -	if (! XFS_FORCED_SHUTDOWN(mp))
    -		xfs_force_shutdown(mp, XFS_METADATA_IO_ERROR);
    -	/*
    -	 * We have to unpin the pinned buffers so do the
    -	 * callbacks.
    -	 */
    -	xfs_buf_do_callbacks(bp, lip);
    -	XFS_BUF_SET_FSPRIVATE(bp, NULL);
    -	XFS_BUF_CLR_IODONE_FUNC(bp);
    -	XFS_BUF_SET_BRELSE_FUNC(bp,NULL);
    -	xfs_buf_relse(bp);
    -}
    -
    -
    -/*
    - * This is the iodone() function for buffers which have been
    - * logged.  It is called when they are eventually flushed out.
    - * It should remove the buf item from the AIL, and free the buf item.
    - * It is called by xfs_buf_iodone_callbacks() above which will take
    - * care of cleaning up the buffer itself.
    - */
    -/* ARGSUSED */
    -void
    -xfs_buf_iodone(
    -	xfs_buf_t		*bp,
    -	xfs_buf_log_item_t	*bip)
    -{
    -	struct xfs_mount	*mp;
    -	SPLDECL(s);
    -
    -	ASSERT(bip->bli_buf == bp);
    -
    -	mp = bip->bli_item.li_mountp;
    -
    -	/*
    -	 * If we are forcibly shutting down, this may well be
    -	 * off the AIL already. That's because we simulate the
    -	 * log-committed callbacks to unpin these buffers. Or we may never
    -	 * have put this item on AIL because of the transaction was
    -	 * aborted forcibly. xfs_trans_delete_ail() takes care of these.
    -	 *
    -	 * Either way, AIL is useless if we're forcing a shutdown.
    -	 */
    -	AIL_LOCK(mp,s);
    -	/*
    -	 * xfs_trans_delete_ail() drops the AIL lock.
    -	 */
    -	xfs_trans_delete_ail(mp, (xfs_log_item_t *)bip, s);
    -
    -#ifdef XFS_TRANS_DEBUG
    -	kmem_free(bip->bli_orig, XFS_BUF_COUNT(bp));
    -	bip->bli_orig = NULL;
    -	kmem_free(bip->bli_logged, XFS_BUF_COUNT(bp) / NBBY);
    -	bip->bli_logged = NULL;
    -#endif /* XFS_TRANS_DEBUG */
    -
    -#ifdef XFS_BLI_TRACE
    -	ktrace_free(bip->bli_trace);
    -#endif
    -	kmem_zone_free(xfs_buf_item_zone, bip);
    -}
    -
    -#if defined(XFS_BLI_TRACE)
    -void
    -xfs_buf_item_trace(
    -	char			*id,
    -	xfs_buf_log_item_t	*bip)
    -{
    -	xfs_buf_t		*bp;
    -	ASSERT(bip->bli_trace != NULL);
    -
    -	bp = bip->bli_buf;
    -	ktrace_enter(bip->bli_trace,
    -		     (void *)id,
    -		     (void *)bip->bli_buf,
    -		     (void *)((unsigned long)bip->bli_flags),
    -		     (void *)((unsigned long)bip->bli_recur),
    -		     (void *)((unsigned long)atomic_read(&bip->bli_refcount)),
    -		     (void *)((unsigned long)
    -				(0xFFFFFFFF & XFS_BUF_ADDR(bp) >> 32)),
    -		     (void *)((unsigned long)(0xFFFFFFFF & XFS_BUF_ADDR(bp))),
    -		     (void *)((unsigned long)XFS_BUF_COUNT(bp)),
    -		     (void *)((unsigned long)XFS_BUF_BFLAGS(bp)),
    -		     XFS_BUF_FSPRIVATE(bp, void *),
    -		     XFS_BUF_FSPRIVATE2(bp, void *),
    -		     (void *)(unsigned long)XFS_BUF_ISPINNED(bp),
    -		     (void *)XFS_BUF_IODONE_FUNC(bp),
    -		     (void *)((unsigned long)(XFS_BUF_VALUSEMA(bp))),
    -		     (void *)bip->bli_item.li_desc,
    -		     (void *)((unsigned long)bip->bli_item.li_flags));
    -}
    -#endif /* XFS_BLI_TRACE */
    -
    -
    diff --git a/sys/gnu/fs/xfs/xfs_buf_item.h b/sys/gnu/fs/xfs/xfs_buf_item.h
    deleted file mode 100644
    index 07c708c2b52..00000000000
    --- a/sys/gnu/fs/xfs/xfs_buf_item.h
    +++ /dev/null
    @@ -1,157 +0,0 @@
    -/*
    - * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef	__XFS_BUF_ITEM_H__
    -#define	__XFS_BUF_ITEM_H__
    -
    -/*
    - * This is the structure used to lay out a buf log item in the
    - * log.  The data map describes which 128 byte chunks of the buffer
    - * have been logged.  This structure works only on buffers that
    - * reside up to the first TB in the filesystem.  These buffers are
    - * generated only by pre-6.2 systems and are known as XFS_LI_6_1_BUF.
    - */
    -typedef struct xfs_buf_log_format_v1 {
    -	unsigned short	blf_type;	/* buf log item type indicator */
    -	unsigned short	blf_size;	/* size of this item */
    -	__int32_t	blf_blkno;	/* starting blkno of this buf */
    -	ushort		blf_flags;	/* misc state */
    -	ushort		blf_len;	/* number of blocks in this buf */
    -	unsigned int	blf_map_size;	/* size of data bitmap in words */
    -	unsigned int	blf_data_map[1];/* variable size bitmap of */
    -					/*   regions of buffer in this item */
    -} xfs_buf_log_format_v1_t;
    -
    -/*
    - * This is a form of the above structure with a 64 bit blkno field.
    - * For 6.2 and beyond, this is XFS_LI_BUF.  We use this to log everything.
    - */
    -typedef struct xfs_buf_log_format_t {
    -	unsigned short	blf_type;	/* buf log item type indicator */
    -	unsigned short	blf_size;	/* size of this item */
    -	ushort		blf_flags;	/* misc state */
    -	ushort		blf_len;	/* number of blocks in this buf */
    -	__int64_t	blf_blkno;	/* starting blkno of this buf */
    -	unsigned int	blf_map_size;	/* size of data bitmap in words */
    -	unsigned int	blf_data_map[1];/* variable size bitmap of */
    -					/*   regions of buffer in this item */
    -} xfs_buf_log_format_t;
    -
    -/*
    - * This flag indicates that the buffer contains on disk inodes
    - * and requires special recovery handling.
    - */
    -#define	XFS_BLI_INODE_BUF	0x1
    -/*
    - * This flag indicates that the buffer should not be replayed
    - * during recovery because its blocks are being freed.
    - */
    -#define	XFS_BLI_CANCEL		0x2
    -/*
    - * This flag indicates that the buffer contains on disk
    - * user or group dquots and may require special recovery handling.
    - */
    -#define	XFS_BLI_UDQUOT_BUF	0x4
    -#define XFS_BLI_PDQUOT_BUF	0x8
    -#define	XFS_BLI_GDQUOT_BUF	0x10
    -
    -#define	XFS_BLI_CHUNK		128
    -#define	XFS_BLI_SHIFT		7
    -#define	BIT_TO_WORD_SHIFT	5
    -#define	NBWORD			(NBBY * sizeof(unsigned int))
    -
    -/*
    - * buf log item flags
    - */
    -#define	XFS_BLI_HOLD		0x01
    -#define	XFS_BLI_DIRTY		0x02
    -#define	XFS_BLI_STALE		0x04
    -#define	XFS_BLI_LOGGED		0x08
    -#define	XFS_BLI_INODE_ALLOC_BUF	0x10
    -#define XFS_BLI_STALE_INODE	0x20
    -
    -
    -#ifdef __KERNEL__
    -
    -struct xfs_buf;
    -struct ktrace;
    -struct xfs_mount;
    -struct xfs_buf_log_item;
    -
    -#if defined(XFS_BLI_TRACE)
    -#define	XFS_BLI_TRACE_SIZE	32
    -
    -void	xfs_buf_item_trace(char *, struct xfs_buf_log_item *);
    -#else
    -#define	xfs_buf_item_trace(id, bip)
    -#endif
    -
    -/*
    - * This is the in core log item structure used to track information
    - * needed to log buffers.  It tracks how many times the lock has been
    - * locked, and which 128 byte chunks of the buffer are dirty.
    - */
    -typedef struct xfs_buf_log_item {
    -	xfs_log_item_t		bli_item;	/* common item structure */
    -	struct xfs_buf		*bli_buf;	/* real buffer pointer */
    -	unsigned int		bli_flags;	/* misc flags */
    -	unsigned int		bli_recur;	/* lock recursion count */
    -	atomic_t		bli_refcount;	/* cnt of tp refs */
    -#ifdef XFS_BLI_TRACE
    -	struct ktrace		*bli_trace;	/* event trace buf */
    -#endif
    -#ifdef XFS_TRANS_DEBUG
    -	char			*bli_orig;	/* original buffer copy */
    -	char			*bli_logged;	/* bytes logged (bitmap) */
    -#endif
    -	xfs_buf_log_format_t	bli_format;	/* in-log header */
    -} xfs_buf_log_item_t;
    -
    -/*
    - * This structure is used during recovery to record the buf log
    - * items which have been canceled and should not be replayed.
    - */
    -typedef struct xfs_buf_cancel {
    -	xfs_daddr_t		bc_blkno;
    -	uint			bc_len;
    -	int			bc_refcount;
    -	struct xfs_buf_cancel	*bc_next;
    -} xfs_buf_cancel_t;
    -
    -void	xfs_buf_item_init(struct xfs_buf *, struct xfs_mount *);
    -void	xfs_buf_item_relse(struct xfs_buf *);
    -void	xfs_buf_item_log(xfs_buf_log_item_t *, uint, uint);
    -uint	xfs_buf_item_dirty(xfs_buf_log_item_t *);
    -void	xfs_buf_attach_iodone(struct xfs_buf *,
    -			      void(*)(struct xfs_buf *, xfs_log_item_t *),
    -			      xfs_log_item_t *);
    -void	xfs_buf_iodone_callbacks(struct xfs_buf *);
    -void	xfs_buf_iodone(struct xfs_buf *, xfs_buf_log_item_t *);
    -
    -#ifdef XFS_TRANS_DEBUG
    -void
    -xfs_buf_item_flush_log_debug(
    -	struct xfs_buf *bp,
    -	uint	first,
    -	uint	last);
    -#else
    -#define	xfs_buf_item_flush_log_debug(bp, first, last)
    -#endif
    -
    -#endif	/* __KERNEL__ */
    -
    -#endif	/* __XFS_BUF_ITEM_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_cap.c b/sys/gnu/fs/xfs/xfs_cap.c
    deleted file mode 100644
    index 7f8e038a052..00000000000
    --- a/sys/gnu/fs/xfs/xfs_cap.c
    +++ /dev/null
    @@ -1,207 +0,0 @@
    -/*
    - * Copyright (c) 2002 Silicon Graphics, Inc.  All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or modify it
    - * under the terms of version 2 of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful, but
    - * WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    - *
    - * Further, this software is distributed without any warranty that it is
    - * free of the rightful claim of any third person regarding infringement
    - * or the like.  Any license provided herein, whether implied or
    - * otherwise, applies only to this software file.  Patent licenses, if
    - * any, provided herein do not apply to combinations of this program with
    - * other software, or any other product whatsoever.
    - *
    - * You should have received a copy of the GNU General Public License along
    - * with this program; if not, write the Free Software Foundation, Inc., 59
    - * Temple Place - Suite 330, Boston MA 02111-1307, USA.
    - *
    - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
    - * Mountain View, CA  94043, or:
    - *
    - * http://www.sgi.com
    - *
    - * For further information regarding this notice, see:
    - *
    - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
    - */
    -
    -#include "xfs.h"
    -
    -STATIC int xfs_cap_allow_set(xfs_vnode_t *);
    -
    -
    -/*
    - * Test for existence of capability attribute as efficiently as possible.
    - */
    -int
    -xfs_cap_vhascap(
    -	xfs_vnode_t	*vp)
    -{
    -	int		error;
    -	int		len = sizeof(xfs_cap_set_t);
    -	int		flags = ATTR_KERNOVAL|ATTR_ROOT;
    -
    -	XVOP_ATTR_GET(vp, SGI_CAP_LINUX, NULL, &len, flags, sys_cred, error);
    -	return (error == 0);
    -}
    -
    -/*
    - * Convert from extended attribute representation to in-memory for XFS.
    - */
    -STATIC int
    -posix_cap_xattr_to_xfs(
    -	posix_cap_xattr		*src,
    -	size_t			size,
    -	xfs_cap_set_t		*dest)
    -{
    -	if (!src || !dest)
    -		return EINVAL;
    -
    -	if (src->c_version != cpu_to_le32(POSIX_CAP_XATTR_VERSION))
    -		return EINVAL;
    -	if (src->c_abiversion != cpu_to_le32(_LINUX_CAPABILITY_VERSION))
    -		return EINVAL;
    -
    -	if (size < sizeof(posix_cap_xattr))
    -		return EINVAL;
    -
    -	ASSERT(sizeof(dest->cap_effective) == sizeof(src->c_effective));
    -
    -	dest->cap_effective	= src->c_effective;
    -	dest->cap_permitted	= src->c_permitted;
    -	dest->cap_inheritable	= src->c_inheritable;
    -
    -	return 0;
    -}
    -
    -/*
    - * Convert from in-memory XFS to extended attribute representation.
    - */
    -STATIC int
    -posix_cap_xfs_to_xattr(
    -	xfs_cap_set_t		*src,
    -	posix_cap_xattr		*xattr_cap,
    -	size_t			size)
    -{
    -	size_t			new_size = posix_cap_xattr_size();
    -
    -	if (size < new_size)
    -		return -ERANGE;
    -
    -	ASSERT(sizeof(xattr_cap->c_effective) == sizeof(src->cap_effective));
    -
    -	xattr_cap->c_version	= cpu_to_le32(POSIX_CAP_XATTR_VERSION);
    -	xattr_cap->c_abiversion	= cpu_to_le32(_LINUX_CAPABILITY_VERSION);
    -	xattr_cap->c_effective	= src->cap_effective;
    -	xattr_cap->c_permitted	= src->cap_permitted;
    -	xattr_cap->c_inheritable= src->cap_inheritable;
    -
    -	return new_size;
    -}
    -
    -int
    -xfs_cap_vget(
    -	xfs_vnode_t	*vp,
    -	void		*cap,
    -	size_t		size)
    -{
    -	int		error;
    -	int		len = sizeof(xfs_cap_set_t);
    -	int		flags = ATTR_ROOT;
    -	xfs_cap_set_t	xfs_cap = { 0 };
    -	posix_cap_xattr	*xattr_cap = cap;
    -	char		*data = (char *)&xfs_cap;
    -
    -	VN_HOLD(vp);
    -	if ((error = _MAC_VACCESS(vp, NULL, VREAD)))
    -		goto out;
    -
    -	if (!size) {
    -		flags |= ATTR_KERNOVAL;
    -		data = NULL;
    -	}
    -	XVOP_ATTR_GET(vp, SGI_CAP_LINUX, data, &len, flags, sys_cred, error);
    -	if (error)
    -		goto out;
    -	ASSERT(len == sizeof(xfs_cap_set_t));
    -
    -	error = (size)? -posix_cap_xattr_size() :
    -			-posix_cap_xfs_to_xattr(&xfs_cap, xattr_cap, size);
    -out:
    -	VN_RELE(vp);
    -	return -error;
    -}
    -
    -int
    -xfs_cap_vremove(
    -	xfs_vnode_t	*vp)
    -{
    -	int		error;
    -
    -	VN_HOLD(vp);
    -	error = xfs_cap_allow_set(vp);
    -	if (!error) {
    -		XVOP_ATTR_REMOVE(vp, SGI_CAP_LINUX, ATTR_ROOT, sys_cred, error);
    -		if (error == ENOATTR)
    -			error = 0;	/* 'scool */
    -	}
    -	VN_RELE(vp);
    -	return -error;
    -}
    -
    -int
    -xfs_cap_vset(
    -	xfs_vnode_t		*vp,
    -	void			*cap,
    -	size_t			size)
    -{
    -	posix_cap_xattr		*xattr_cap = cap;
    -	xfs_cap_set_t		xfs_cap;
    -	int			error;
    -
    -	if (!cap)
    -		return -EINVAL;
    -
    -	error = posix_cap_xattr_to_xfs(xattr_cap, size, &xfs_cap);
    -	if (error)
    -		return -error;
    -
    -	VN_HOLD(vp);
    -	error = xfs_cap_allow_set(vp);
    -	if (error)
    -		goto out;
    -
    -	XVOP_ATTR_SET(vp, SGI_CAP_LINUX, (char *)&xfs_cap,
    -			sizeof(xfs_cap_set_t), ATTR_ROOT, sys_cred, error);
    -out:
    -	VN_RELE(vp);
    -	return -error;
    -}
    -
    -STATIC int
    -xfs_cap_allow_set(
    -	xfs_vnode_t	*vp)
    -{
    -	vattr_t		va;
    -	int		error;
    -
    -	if (vp->v_vfsp->vfs_flag & VFS_RDONLY)
    -		return EROFS;
    -	if (vp->v_inode.i_flags & (S_IMMUTABLE|S_APPEND))
    -		return EPERM;
    -	if ((error = _MAC_VACCESS(vp, NULL, VWRITE)))
    -		return error;
    -	va.va_mask = XFS_AT_UID;
    -	XVOP_GETATTR(vp, &va, 0, NULL, error);
    -	if (error)
    -		return error;
    -	if (va.va_uid != current->fsuid && !capable(CAP_FOWNER))
    -		return EPERM;
    -	return error;
    -}
    -
    diff --git a/sys/gnu/fs/xfs/xfs_cap.h b/sys/gnu/fs/xfs/xfs_cap.h
    deleted file mode 100644
    index 8bff4d449a8..00000000000
    --- a/sys/gnu/fs/xfs/xfs_cap.h
    +++ /dev/null
    @@ -1,70 +0,0 @@
    -/*
    - * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_CAP_H__
    -#define __XFS_CAP_H__
    -
    -/*
    - * Capabilities
    - */
    -typedef __uint64_t xfs_cap_value_t;
    -
    -typedef struct xfs_cap_set {
    -	xfs_cap_value_t	cap_effective;	/* use in capability checks */
    -	xfs_cap_value_t	cap_permitted;	/* combined with file attrs */
    -	xfs_cap_value_t	cap_inheritable;/* pass through exec */
    -} xfs_cap_set_t;
    -
    -/* On-disk XFS extended attribute names */
    -#define SGI_CAP_FILE	"SGI_CAP_FILE"
    -#define SGI_CAP_FILE_SIZE	(sizeof(SGI_CAP_FILE)-1)
    -#define SGI_CAP_LINUX	"SGI_CAP_LINUX"
    -#define SGI_CAP_LINUX_SIZE	(sizeof(SGI_CAP_LINUX)-1)
    -
    -/*
    - * For Linux, we take the bitfields directly from capability.h
    - * and no longer attempt to keep this attribute ondisk compatible
    - * with IRIX.  Since this attribute is only set on executables,
    - * it just doesn't make much sense to try.  We do use a different
    - * named attribute though, to avoid confusion.
    - */
    -
    -#ifdef __KERNEL__
    -
    -#ifdef CONFIG_FS_POSIX_CAP
    -
    -#include 
    -
    -struct xfs_vnode;
    -
    -extern int xfs_cap_vhascap(struct xfs_vnode *);
    -extern int xfs_cap_vset(struct xfs_vnode *, void *, size_t);
    -extern int xfs_cap_vget(struct xfs_vnode *, void *, size_t);
    -extern int xfs_cap_vremove(struct xfs_vnode *vp);
    -
    -#define _CAP_EXISTS		xfs_cap_vhascap
    -
    -#else
    -#define xfs_cap_vset(v,p,sz)	(-EOPNOTSUPP)
    -#define xfs_cap_vget(v,p,sz)	(-EOPNOTSUPP)
    -#define xfs_cap_vremove(v)	(-EOPNOTSUPP)
    -#define _CAP_EXISTS		(NULL)
    -#endif
    -
    -#endif	/* __KERNEL__ */
    -
    -#endif  /* __XFS_CAP_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_clnt.h b/sys/gnu/fs/xfs/xfs_clnt.h
    deleted file mode 100644
    index 5b7eb81453b..00000000000
    --- a/sys/gnu/fs/xfs/xfs_clnt.h
    +++ /dev/null
    @@ -1,103 +0,0 @@
    -/*
    - * Copyright (c) 2000-2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_CLNT_H__
    -#define __XFS_CLNT_H__
    -
    -/*
    - * XFS arguments structure, constructed from the arguments we
    - * are passed via the mount system call.
    - *
    - * NOTE: The mount system call is handled differently between
    - * Linux and IRIX.  In IRIX we worked work with a binary data
    - * structure coming in across the syscall interface from user
    - * space (the mount userspace knows about each filesystem type
    - * and the set of valid options for it, and converts the users
    - * argument string into a binary structure _before_ making the
    - * system call), and the ABI issues that this implies.
    - *
    - * In Linux, we are passed a comma separated set of options;
    - * ie. a NULL terminated string of characters.  Userspace mount
    - * code does not have any knowledge of mount options expected by
    - * each filesystem type and so each filesystem parses its mount
    - * options in kernel space.
    - *
    - * For the Linux port, we kept this structure pretty much intact
    - * and use it internally (because the existing code groks it).
    - */
    -struct xfs_mount_args {
    -	int	flags;		/* flags -> see XFSMNT_... macros below */
    -	int	flags2;		/* flags -> see XFSMNT2_... macros below */
    -	int	logbufs;	/* Number of log buffers, -1 to default */
    -	int	logbufsize;	/* Size of log buffers, -1 to default */
    -	char	fsname[MAXNAMELEN+1];	/* data device name */
    -	char	rtname[MAXNAMELEN+1];	/* realtime device filename */
    -	char	logname[MAXNAMELEN+1];	/* journal device filename */
    -	char	mtpt[MAXNAMELEN+1];	/* filesystem mount point */
    -	int	sunit;		/* stripe unit (BBs) */
    -	int	swidth;		/* stripe width (BBs), multiple of sunit */
    -	uchar_t iosizelog;	/* log2 of the preferred I/O size */
    -	int	ihashsize;	/* inode hash table size (buckets) */
    -};
    -
    -/*
    - * XFS mount option flags -- args->flags1
    - */
    -#define	XFSMNT_ATTR2		0x00000001	/* allow ATTR2 EA format */
    -#define	XFSMNT_WSYNC		0x00000002	/* safe mode nfs mount
    -						 * compatible */
    -#define	XFSMNT_INO64		0x00000004	/* move inode numbers up
    -						 * past 2^32 */
    -#define XFSMNT_UQUOTA		0x00000008	/* user quota accounting */
    -#define XFSMNT_PQUOTA		0x00000010	/* IRIX prj quota accounting */
    -#define XFSMNT_UQUOTAENF	0x00000020	/* user quota limit
    -						 * enforcement */
    -#define XFSMNT_PQUOTAENF	0x00000040	/* IRIX project quota limit
    -						 * enforcement */
    -#define XFSMNT_QUIET		0x00000080	/* don't report mount errors */
    -#define XFSMNT_NOALIGN		0x00000200	/* don't allocate at
    -						 * stripe boundaries*/
    -#define XFSMNT_RETERR		0x00000400	/* return error to user */
    -#define XFSMNT_NORECOVERY	0x00000800	/* no recovery, implies
    -						 * read-only mount */
    -#define XFSMNT_SHARED		0x00001000	/* shared XFS mount */
    -#define XFSMNT_IOSIZE		0x00002000	/* optimize for I/O size */
    -#define XFSMNT_OSYNCISOSYNC	0x00004000	/* o_sync is REALLY o_sync */
    -						/* (osyncisdsync is default) */
    -#define XFSMNT_32BITINODES	0x00200000	/* restrict inodes to 32
    -						 * bits of address space */
    -#define XFSMNT_GQUOTA		0x00400000	/* group quota accounting */
    -#define XFSMNT_GQUOTAENF	0x00800000	/* group quota limit
    -						 * enforcement */
    -#define XFSMNT_NOUUID		0x01000000	/* Ignore fs uuid */
    -#define XFSMNT_DMAPI		0x02000000	/* enable dmapi/xdsm */
    -#define XFSMNT_BARRIER		0x04000000	/* use write barriers */
    -#define XFSMNT_IDELETE		0x08000000	/* inode cluster delete */
    -#define XFSMNT_SWALLOC		0x10000000	/* turn on stripe width
    -						 * allocation */
    -#define XFSMNT_IHASHSIZE	0x20000000	/* inode hash table size */
    -#define XFSMNT_DIRSYNC		0x40000000	/* sync creat,link,unlink,rename
    -						 * symlink,mkdir,rmdir,mknod */
    -#define XFSMNT_FLAGS2		0x80000000	/* more flags set in flags2 */
    -
    -/*
    - * XFS mount option flags -- args->flags2
    - */
    -#define XFSMNT2_COMPAT_IOSIZE	0x00000001	/* don't report large preferred
    -						 * I/O size in stat(2) */
    -
    -#endif	/* __XFS_CLNT_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_da_btree.c b/sys/gnu/fs/xfs/xfs_da_btree.c
    deleted file mode 100644
    index 47b86f9f69f..00000000000
    --- a/sys/gnu/fs/xfs/xfs_da_btree.c
    +++ /dev/null
    @@ -1,2590 +0,0 @@
    -/*
    - * Copyright (c) 2000-2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_da_btree.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_inode_item.h"
    -#include "xfs_alloc.h"
    -#include "xfs_btree.h"
    -#include "xfs_bmap.h"
    -#include "xfs_attr.h"
    -#include "xfs_attr_leaf.h"
    -#include "xfs_dir_leaf.h"
    -#include "xfs_dir2_data.h"
    -#include "xfs_dir2_leaf.h"
    -#include "xfs_dir2_block.h"
    -#include "xfs_dir2_node.h"
    -#include "xfs_error.h"
    -
    -/*
    - * xfs_da_btree.c
    - *
    - * Routines to implement directories as Btrees of hashed names.
    - */
    -
    -/*========================================================================
    - * Function prototypes for the kernel.
    - *========================================================================*/
    -
    -/*
    - * Routines used for growing the Btree.
    - */
    -STATIC int xfs_da_root_split(xfs_da_state_t *state,
    -					    xfs_da_state_blk_t *existing_root,
    -					    xfs_da_state_blk_t *new_child);
    -STATIC int xfs_da_node_split(xfs_da_state_t *state,
    -					    xfs_da_state_blk_t *existing_blk,
    -					    xfs_da_state_blk_t *split_blk,
    -					    xfs_da_state_blk_t *blk_to_add,
    -					    int treelevel,
    -					    int *result);
    -STATIC void xfs_da_node_rebalance(xfs_da_state_t *state,
    -					 xfs_da_state_blk_t *node_blk_1,
    -					 xfs_da_state_blk_t *node_blk_2);
    -STATIC void xfs_da_node_add(xfs_da_state_t *state,
    -				   xfs_da_state_blk_t *old_node_blk,
    -				   xfs_da_state_blk_t *new_node_blk);
    -
    -/*
    - * Routines used for shrinking the Btree.
    - */
    -STATIC int xfs_da_root_join(xfs_da_state_t *state,
    -					   xfs_da_state_blk_t *root_blk);
    -STATIC int xfs_da_node_toosmall(xfs_da_state_t *state, int *retval);
    -STATIC void xfs_da_node_remove(xfs_da_state_t *state,
    -					      xfs_da_state_blk_t *drop_blk);
    -STATIC void xfs_da_node_unbalance(xfs_da_state_t *state,
    -					 xfs_da_state_blk_t *src_node_blk,
    -					 xfs_da_state_blk_t *dst_node_blk);
    -
    -/*
    - * Utility routines.
    - */
    -STATIC uint	xfs_da_node_lasthash(xfs_dabuf_t *bp, int *count);
    -STATIC int	xfs_da_node_order(xfs_dabuf_t *node1_bp, xfs_dabuf_t *node2_bp);
    -STATIC xfs_dabuf_t *xfs_da_buf_make(int nbuf, xfs_buf_t **bps, inst_t *ra);
    -STATIC int	xfs_da_blk_unlink(xfs_da_state_t *state,
    -				  xfs_da_state_blk_t *drop_blk,
    -				  xfs_da_state_blk_t *save_blk);
    -STATIC void	xfs_da_state_kill_altpath(xfs_da_state_t *state);
    -
    -/*========================================================================
    - * Routines used for growing the Btree.
    - *========================================================================*/
    -
    -/*
    - * Create the initial contents of an intermediate node.
    - */
    -int
    -xfs_da_node_create(xfs_da_args_t *args, xfs_dablk_t blkno, int level,
    -				 xfs_dabuf_t **bpp, int whichfork)
    -{
    -	xfs_da_intnode_t *node;
    -	xfs_dabuf_t *bp;
    -	int error;
    -	xfs_trans_t *tp;
    -
    -	tp = args->trans;
    -	error = xfs_da_get_buf(tp, args->dp, blkno, -1, &bp, whichfork);
    -	if (error)
    -		return(error);
    -	ASSERT(bp != NULL);
    -	node = bp->data;
    -	node->hdr.info.forw = 0;
    -	node->hdr.info.back = 0;
    -	node->hdr.info.magic = cpu_to_be16(XFS_DA_NODE_MAGIC);
    -	node->hdr.info.pad = 0;
    -	node->hdr.count = 0;
    -	node->hdr.level = cpu_to_be16(level);
    -
    -	xfs_da_log_buf(tp, bp,
    -		XFS_DA_LOGRANGE(node, &node->hdr, sizeof(node->hdr)));
    -
    -	*bpp = bp;
    -	return(0);
    -}
    -
    -/*
    - * Split a leaf node, rebalance, then possibly split
    - * intermediate nodes, rebalance, etc.
    - */
    -int							/* error */
    -xfs_da_split(xfs_da_state_t *state)
    -{
    -	xfs_da_state_blk_t *oldblk, *newblk, *addblk;
    -	xfs_da_intnode_t *node;
    -	xfs_dabuf_t *bp;
    -	int max, action, error, i;
    -
    -	/*
    -	 * Walk back up the tree splitting/inserting/adjusting as necessary.
    -	 * If we need to insert and there isn't room, split the node, then
    -	 * decide which fragment to insert the new block from below into.
    -	 * Note that we may split the root this way, but we need more fixup.
    -	 */
    -	max = state->path.active - 1;
    -	ASSERT((max >= 0) && (max < XFS_DA_NODE_MAXDEPTH));
    -	ASSERT(state->path.blk[max].magic == XFS_ATTR_LEAF_MAGIC ||
    -	       state->path.blk[max].magic == XFS_DIRX_LEAF_MAGIC(state->mp));
    -
    -	addblk = &state->path.blk[max];		/* initial dummy value */
    -	for (i = max; (i >= 0) && addblk; state->path.active--, i--) {
    -		oldblk = &state->path.blk[i];
    -		newblk = &state->altpath.blk[i];
    -
    -		/*
    -		 * If a leaf node then
    -		 *     Allocate a new leaf node, then rebalance across them.
    -		 * else if an intermediate node then
    -		 *     We split on the last layer, must we split the node?
    -		 */
    -		switch (oldblk->magic) {
    -		case XFS_ATTR_LEAF_MAGIC:
    -			error = xfs_attr_leaf_split(state, oldblk, newblk);
    -			if ((error != 0) && (error != ENOSPC)) {
    -				return(error);	/* GROT: attr is inconsistent */
    -			}
    -			if (!error) {
    -				addblk = newblk;
    -				break;
    -			}
    -			/*
    -			 * Entry wouldn't fit, split the leaf again.
    -			 */
    -			state->extravalid = 1;
    -			if (state->inleaf) {
    -				state->extraafter = 0;	/* before newblk */
    -				error = xfs_attr_leaf_split(state, oldblk,
    -							    &state->extrablk);
    -			} else {
    -				state->extraafter = 1;	/* after newblk */
    -				error = xfs_attr_leaf_split(state, newblk,
    -							    &state->extrablk);
    -			}
    -			if (error)
    -				return(error);	/* GROT: attr inconsistent */
    -			addblk = newblk;
    -			break;
    -		case XFS_DIR_LEAF_MAGIC:
    -			ASSERT(XFS_DIR_IS_V1(state->mp));
    -			error = xfs_dir_leaf_split(state, oldblk, newblk);
    -			if ((error != 0) && (error != ENOSPC)) {
    -				return(error);	/* GROT: dir is inconsistent */
    -			}
    -			if (!error) {
    -				addblk = newblk;
    -				break;
    -			}
    -			/*
    -			 * Entry wouldn't fit, split the leaf again.
    -			 */
    -			state->extravalid = 1;
    -			if (state->inleaf) {
    -				state->extraafter = 0;	/* before newblk */
    -				error = xfs_dir_leaf_split(state, oldblk,
    -							   &state->extrablk);
    -				if (error)
    -					return(error);	/* GROT: dir incon. */
    -				addblk = newblk;
    -			} else {
    -				state->extraafter = 1;	/* after newblk */
    -				error = xfs_dir_leaf_split(state, newblk,
    -							   &state->extrablk);
    -				if (error)
    -					return(error);	/* GROT: dir incon. */
    -				addblk = newblk;
    -			}
    -			break;
    -		case XFS_DIR2_LEAFN_MAGIC:
    -			ASSERT(XFS_DIR_IS_V2(state->mp));
    -			error = xfs_dir2_leafn_split(state, oldblk, newblk);
    -			if (error)
    -				return error;
    -			addblk = newblk;
    -			break;
    -		case XFS_DA_NODE_MAGIC:
    -			error = xfs_da_node_split(state, oldblk, newblk, addblk,
    -							 max - i, &action);
    -			xfs_da_buf_done(addblk->bp);
    -			addblk->bp = NULL;
    -			if (error)
    -				return(error);	/* GROT: dir is inconsistent */
    -			/*
    -			 * Record the newly split block for the next time thru?
    -			 */
    -			if (action)
    -				addblk = newblk;
    -			else
    -				addblk = NULL;
    -			break;
    -		}
    -
    -		/*
    -		 * Update the btree to show the new hashval for this child.
    -		 */
    -		xfs_da_fixhashpath(state, &state->path);
    -		/*
    -		 * If we won't need this block again, it's getting dropped
    -		 * from the active path by the loop control, so we need
    -		 * to mark it done now.
    -		 */
    -		if (i > 0 || !addblk)
    -			xfs_da_buf_done(oldblk->bp);
    -	}
    -	if (!addblk)
    -		return(0);
    -
    -	/*
    -	 * Split the root node.
    -	 */
    -	ASSERT(state->path.active == 0);
    -	oldblk = &state->path.blk[0];
    -	error = xfs_da_root_split(state, oldblk, addblk);
    -	if (error) {
    -		xfs_da_buf_done(oldblk->bp);
    -		xfs_da_buf_done(addblk->bp);
    -		addblk->bp = NULL;
    -		return(error);	/* GROT: dir is inconsistent */
    -	}
    -
    -	/*
    -	 * Update pointers to the node which used to be block 0 and
    -	 * just got bumped because of the addition of a new root node.
    -	 * There might be three blocks involved if a double split occurred,
    -	 * and the original block 0 could be at any position in the list.
    -	 */
    -
    -	node = oldblk->bp->data;
    -	if (node->hdr.info.forw) {
    -		if (be32_to_cpu(node->hdr.info.forw) == addblk->blkno) {
    -			bp = addblk->bp;
    -		} else {
    -			ASSERT(state->extravalid);
    -			bp = state->extrablk.bp;
    -		}
    -		node = bp->data;
    -		node->hdr.info.back = cpu_to_be32(oldblk->blkno);
    -		xfs_da_log_buf(state->args->trans, bp,
    -		    XFS_DA_LOGRANGE(node, &node->hdr.info,
    -		    sizeof(node->hdr.info)));
    -	}
    -	node = oldblk->bp->data;
    -	if (node->hdr.info.back) {
    -		if (be32_to_cpu(node->hdr.info.back) == addblk->blkno) {
    -			bp = addblk->bp;
    -		} else {
    -			ASSERT(state->extravalid);
    -			bp = state->extrablk.bp;
    -		}
    -		node = bp->data;
    -		node->hdr.info.forw = cpu_to_be32(oldblk->blkno);
    -		xfs_da_log_buf(state->args->trans, bp,
    -		    XFS_DA_LOGRANGE(node, &node->hdr.info,
    -		    sizeof(node->hdr.info)));
    -	}
    -	xfs_da_buf_done(oldblk->bp);
    -	xfs_da_buf_done(addblk->bp);
    -	addblk->bp = NULL;
    -	return(0);
    -}
    -
    -/*
    - * Split the root.  We have to create a new root and point to the two
    - * parts (the split old root) that we just created.  Copy block zero to
    - * the EOF, extending the inode in process.
    - */
    -STATIC int						/* error */
    -xfs_da_root_split(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
    -				 xfs_da_state_blk_t *blk2)
    -{
    -	xfs_da_intnode_t *node, *oldroot;
    -	xfs_da_args_t *args;
    -	xfs_dablk_t blkno;
    -	xfs_dabuf_t *bp;
    -	int error, size;
    -	xfs_inode_t *dp;
    -	xfs_trans_t *tp;
    -	xfs_mount_t *mp;
    -	xfs_dir2_leaf_t *leaf;
    -
    -	/*
    -	 * Copy the existing (incorrect) block from the root node position
    -	 * to a free space somewhere.
    -	 */
    -	args = state->args;
    -	ASSERT(args != NULL);
    -	error = xfs_da_grow_inode(args, &blkno);
    -	if (error)
    -		return(error);
    -	dp = args->dp;
    -	tp = args->trans;
    -	mp = state->mp;
    -	error = xfs_da_get_buf(tp, dp, blkno, -1, &bp, args->whichfork);
    -	if (error)
    -		return(error);
    -	ASSERT(bp != NULL);
    -	node = bp->data;
    -	oldroot = blk1->bp->data;
    -	if (be16_to_cpu(oldroot->hdr.info.magic) == XFS_DA_NODE_MAGIC) {
    -		size = (int)((char *)&oldroot->btree[be16_to_cpu(oldroot->hdr.count)] -
    -			     (char *)oldroot);
    -	} else {
    -		ASSERT(XFS_DIR_IS_V2(mp));
    -		ASSERT(be16_to_cpu(oldroot->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
    -		leaf = (xfs_dir2_leaf_t *)oldroot;
    -		size = (int)((char *)&leaf->ents[be16_to_cpu(leaf->hdr.count)] -
    -			     (char *)leaf);
    -	}
    -	memcpy(node, oldroot, size);
    -	xfs_da_log_buf(tp, bp, 0, size - 1);
    -	xfs_da_buf_done(blk1->bp);
    -	blk1->bp = bp;
    -	blk1->blkno = blkno;
    -
    -	/*
    -	 * Set up the new root node.
    -	 */
    -	error = xfs_da_node_create(args,
    -		args->whichfork == XFS_DATA_FORK &&
    -		XFS_DIR_IS_V2(mp) ? mp->m_dirleafblk : 0,
    -		be16_to_cpu(node->hdr.level) + 1, &bp, args->whichfork);
    -	if (error)
    -		return(error);
    -	node = bp->data;
    -	node->btree[0].hashval = cpu_to_be32(blk1->hashval);
    -	node->btree[0].before = cpu_to_be32(blk1->blkno);
    -	node->btree[1].hashval = cpu_to_be32(blk2->hashval);
    -	node->btree[1].before = cpu_to_be32(blk2->blkno);
    -	node->hdr.count = cpu_to_be16(2);
    -
    -#ifdef DEBUG
    -	if (be16_to_cpu(oldroot->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC) {
    -		ASSERT(blk1->blkno >= mp->m_dirleafblk &&
    -		       blk1->blkno < mp->m_dirfreeblk);
    -		ASSERT(blk2->blkno >= mp->m_dirleafblk &&
    -		       blk2->blkno < mp->m_dirfreeblk);
    -	}
    -#endif
    -
    -	/* Header is already logged by xfs_da_node_create */
    -	xfs_da_log_buf(tp, bp,
    -		XFS_DA_LOGRANGE(node, node->btree,
    -			sizeof(xfs_da_node_entry_t) * 2));
    -	xfs_da_buf_done(bp);
    -
    -	return(0);
    -}
    -
    -/*
    - * Split the node, rebalance, then add the new entry.
    - */
    -STATIC int						/* error */
    -xfs_da_node_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk,
    -				 xfs_da_state_blk_t *newblk,
    -				 xfs_da_state_blk_t *addblk,
    -				 int treelevel, int *result)
    -{
    -	xfs_da_intnode_t *node;
    -	xfs_dablk_t blkno;
    -	int newcount, error;
    -	int useextra;
    -
    -	node = oldblk->bp->data;
    -	ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC);
    -
    -	/*
    -	 * With V2 the extra block is data or freespace.
    -	 */
    -	useextra = state->extravalid && (XFS_DIR_IS_V1(state->mp) ||
    -			state->args->whichfork == XFS_ATTR_FORK);
    -	newcount = 1 + useextra;
    -	/*
    -	 * Do we have to split the node?
    -	 */
    -	if ((be16_to_cpu(node->hdr.count) + newcount) > state->node_ents) {
    -		/*
    -		 * Allocate a new node, add to the doubly linked chain of
    -		 * nodes, then move some of our excess entries into it.
    -		 */
    -		error = xfs_da_grow_inode(state->args, &blkno);
    -		if (error)
    -			return(error);	/* GROT: dir is inconsistent */
    -
    -		error = xfs_da_node_create(state->args, blkno, treelevel,
    -					   &newblk->bp, state->args->whichfork);
    -		if (error)
    -			return(error);	/* GROT: dir is inconsistent */
    -		newblk->blkno = blkno;
    -		newblk->magic = XFS_DA_NODE_MAGIC;
    -		xfs_da_node_rebalance(state, oldblk, newblk);
    -		error = xfs_da_blk_link(state, oldblk, newblk);
    -		if (error)
    -			return(error);
    -		*result = 1;
    -	} else {
    -		*result = 0;
    -	}
    -
    -	/*
    -	 * Insert the new entry(s) into the correct block
    -	 * (updating last hashval in the process).
    -	 *
    -	 * xfs_da_node_add() inserts BEFORE the given index,
    -	 * and as a result of using node_lookup_int() we always
    -	 * point to a valid entry (not after one), but a split
    -	 * operation always results in a new block whose hashvals
    -	 * FOLLOW the current block.
    -	 *
    -	 * If we had double-split op below us, then add the extra block too.
    -	 */
    -	node = oldblk->bp->data;
    -	if (oldblk->index <= be16_to_cpu(node->hdr.count)) {
    -		oldblk->index++;
    -		xfs_da_node_add(state, oldblk, addblk);
    -		if (useextra) {
    -			if (state->extraafter)
    -				oldblk->index++;
    -			xfs_da_node_add(state, oldblk, &state->extrablk);
    -			state->extravalid = 0;
    -		}
    -	} else {
    -		newblk->index++;
    -		xfs_da_node_add(state, newblk, addblk);
    -		if (useextra) {
    -			if (state->extraafter)
    -				newblk->index++;
    -			xfs_da_node_add(state, newblk, &state->extrablk);
    -			state->extravalid = 0;
    -		}
    -	}
    -
    -	return(0);
    -}
    -
    -/*
    - * Balance the btree elements between two intermediate nodes,
    - * usually one full and one empty.
    - *
    - * NOTE: if blk2 is empty, then it will get the upper half of blk1.
    - */
    -STATIC void
    -xfs_da_node_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
    -				     xfs_da_state_blk_t *blk2)
    -{
    -	xfs_da_intnode_t *node1, *node2, *tmpnode;
    -	xfs_da_node_entry_t *btree_s, *btree_d;
    -	int count, tmp;
    -	xfs_trans_t *tp;
    -
    -	node1 = blk1->bp->data;
    -	node2 = blk2->bp->data;
    -	/*
    -	 * Figure out how many entries need to move, and in which direction.
    -	 * Swap the nodes around if that makes it simpler.
    -	 */
    -	if ((be16_to_cpu(node1->hdr.count) > 0) && (be16_to_cpu(node2->hdr.count) > 0) &&
    -	    ((be32_to_cpu(node2->btree[0].hashval) < be32_to_cpu(node1->btree[0].hashval)) ||
    -	     (be32_to_cpu(node2->btree[be16_to_cpu(node2->hdr.count)-1].hashval) <
    -	      be32_to_cpu(node1->btree[be16_to_cpu(node1->hdr.count)-1].hashval)))) {
    -		tmpnode = node1;
    -		node1 = node2;
    -		node2 = tmpnode;
    -	}
    -	ASSERT(be16_to_cpu(node1->hdr.info.magic) == XFS_DA_NODE_MAGIC);
    -	ASSERT(be16_to_cpu(node2->hdr.info.magic) == XFS_DA_NODE_MAGIC);
    -	count = (be16_to_cpu(node1->hdr.count) - be16_to_cpu(node2->hdr.count)) / 2;
    -	if (count == 0)
    -		return;
    -	tp = state->args->trans;
    -	/*
    -	 * Two cases: high-to-low and low-to-high.
    -	 */
    -	if (count > 0) {
    -		/*
    -		 * Move elements in node2 up to make a hole.
    -		 */
    -		if ((tmp = be16_to_cpu(node2->hdr.count)) > 0) {
    -			tmp *= (uint)sizeof(xfs_da_node_entry_t);
    -			btree_s = &node2->btree[0];
    -			btree_d = &node2->btree[count];
    -			memmove(btree_d, btree_s, tmp);
    -		}
    -
    -		/*
    -		 * Move the req'd B-tree elements from high in node1 to
    -		 * low in node2.
    -		 */
    -		be16_add(&node2->hdr.count, count);
    -		tmp = count * (uint)sizeof(xfs_da_node_entry_t);
    -		btree_s = &node1->btree[be16_to_cpu(node1->hdr.count) - count];
    -		btree_d = &node2->btree[0];
    -		memcpy(btree_d, btree_s, tmp);
    -		be16_add(&node1->hdr.count, -count);
    -	} else {
    -		/*
    -		 * Move the req'd B-tree elements from low in node2 to
    -		 * high in node1.
    -		 */
    -		count = -count;
    -		tmp = count * (uint)sizeof(xfs_da_node_entry_t);
    -		btree_s = &node2->btree[0];
    -		btree_d = &node1->btree[be16_to_cpu(node1->hdr.count)];
    -		memcpy(btree_d, btree_s, tmp);
    -		be16_add(&node1->hdr.count, count);
    -		xfs_da_log_buf(tp, blk1->bp,
    -			XFS_DA_LOGRANGE(node1, btree_d, tmp));
    -
    -		/*
    -		 * Move elements in node2 down to fill the hole.
    -		 */
    -		tmp  = be16_to_cpu(node2->hdr.count) - count;
    -		tmp *= (uint)sizeof(xfs_da_node_entry_t);
    -		btree_s = &node2->btree[count];
    -		btree_d = &node2->btree[0];
    -		memmove(btree_d, btree_s, tmp);
    -		be16_add(&node2->hdr.count, -count);
    -	}
    -
    -	/*
    -	 * Log header of node 1 and all current bits of node 2.
    -	 */
    -	xfs_da_log_buf(tp, blk1->bp,
    -		XFS_DA_LOGRANGE(node1, &node1->hdr, sizeof(node1->hdr)));
    -	xfs_da_log_buf(tp, blk2->bp,
    -		XFS_DA_LOGRANGE(node2, &node2->hdr,
    -			sizeof(node2->hdr) +
    -			sizeof(node2->btree[0]) * be16_to_cpu(node2->hdr.count)));
    -
    -	/*
    -	 * Record the last hashval from each block for upward propagation.
    -	 * (note: don't use the swapped node pointers)
    -	 */
    -	node1 = blk1->bp->data;
    -	node2 = blk2->bp->data;
    -	blk1->hashval = be32_to_cpu(node1->btree[be16_to_cpu(node1->hdr.count)-1].hashval);
    -	blk2->hashval = be32_to_cpu(node2->btree[be16_to_cpu(node2->hdr.count)-1].hashval);
    -
    -	/*
    -	 * Adjust the expected index for insertion.
    -	 */
    -	if (blk1->index >= be16_to_cpu(node1->hdr.count)) {
    -		blk2->index = blk1->index - be16_to_cpu(node1->hdr.count);
    -		blk1->index = be16_to_cpu(node1->hdr.count) + 1;	/* make it invalid */
    -	}
    -}
    -
    -/*
    - * Add a new entry to an intermediate node.
    - */
    -STATIC void
    -xfs_da_node_add(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk,
    -			       xfs_da_state_blk_t *newblk)
    -{
    -	xfs_da_intnode_t *node;
    -	xfs_da_node_entry_t *btree;
    -	int tmp;
    -	xfs_mount_t *mp;
    -
    -	node = oldblk->bp->data;
    -	mp = state->mp;
    -	ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC);
    -	ASSERT((oldblk->index >= 0) && (oldblk->index <= be16_to_cpu(node->hdr.count)));
    -	ASSERT(newblk->blkno != 0);
    -	if (state->args->whichfork == XFS_DATA_FORK && XFS_DIR_IS_V2(mp))
    -		ASSERT(newblk->blkno >= mp->m_dirleafblk &&
    -		       newblk->blkno < mp->m_dirfreeblk);
    -
    -	/*
    -	 * We may need to make some room before we insert the new node.
    -	 */
    -	tmp = 0;
    -	btree = &node->btree[ oldblk->index ];
    -	if (oldblk->index < be16_to_cpu(node->hdr.count)) {
    -		tmp = (be16_to_cpu(node->hdr.count) - oldblk->index) * (uint)sizeof(*btree);
    -		memmove(btree + 1, btree, tmp);
    -	}
    -	btree->hashval = cpu_to_be32(newblk->hashval);
    -	btree->before = cpu_to_be32(newblk->blkno);
    -	xfs_da_log_buf(state->args->trans, oldblk->bp,
    -		XFS_DA_LOGRANGE(node, btree, tmp + sizeof(*btree)));
    -	be16_add(&node->hdr.count, 1);
    -	xfs_da_log_buf(state->args->trans, oldblk->bp,
    -		XFS_DA_LOGRANGE(node, &node->hdr, sizeof(node->hdr)));
    -
    -	/*
    -	 * Copy the last hash value from the oldblk to propagate upwards.
    -	 */
    -	oldblk->hashval = be32_to_cpu(node->btree[be16_to_cpu(node->hdr.count)-1 ].hashval);
    -}
    -
    -/*========================================================================
    - * Routines used for shrinking the Btree.
    - *========================================================================*/
    -
    -/*
    - * Deallocate an empty leaf node, remove it from its parent,
    - * possibly deallocating that block, etc...
    - */
    -int
    -xfs_da_join(xfs_da_state_t *state)
    -{
    -	xfs_da_state_blk_t *drop_blk, *save_blk;
    -	int action, error;
    -
    -	action = 0;
    -	drop_blk = &state->path.blk[ state->path.active-1 ];
    -	save_blk = &state->altpath.blk[ state->path.active-1 ];
    -	ASSERT(state->path.blk[0].magic == XFS_DA_NODE_MAGIC);
    -	ASSERT(drop_blk->magic == XFS_ATTR_LEAF_MAGIC ||
    -	       drop_blk->magic == XFS_DIRX_LEAF_MAGIC(state->mp));
    -
    -	/*
    -	 * Walk back up the tree joining/deallocating as necessary.
    -	 * When we stop dropping blocks, break out.
    -	 */
    -	for (  ; state->path.active >= 2; drop_blk--, save_blk--,
    -		 state->path.active--) {
    -		/*
    -		 * See if we can combine the block with a neighbor.
    -		 *   (action == 0) => no options, just leave
    -		 *   (action == 1) => coalesce, then unlink
    -		 *   (action == 2) => block empty, unlink it
    -		 */
    -		switch (drop_blk->magic) {
    -		case XFS_ATTR_LEAF_MAGIC:
    -			error = xfs_attr_leaf_toosmall(state, &action);
    -			if (error)
    -				return(error);
    -			if (action == 0)
    -				return(0);
    -			xfs_attr_leaf_unbalance(state, drop_blk, save_blk);
    -			break;
    -		case XFS_DIR_LEAF_MAGIC:
    -			ASSERT(XFS_DIR_IS_V1(state->mp));
    -			error = xfs_dir_leaf_toosmall(state, &action);
    -			if (error)
    -				return(error);
    -			if (action == 0)
    -				return(0);
    -			xfs_dir_leaf_unbalance(state, drop_blk, save_blk);
    -			break;
    -		case XFS_DIR2_LEAFN_MAGIC:
    -			ASSERT(XFS_DIR_IS_V2(state->mp));
    -			error = xfs_dir2_leafn_toosmall(state, &action);
    -			if (error)
    -				return error;
    -			if (action == 0)
    -				return 0;
    -			xfs_dir2_leafn_unbalance(state, drop_blk, save_blk);
    -			break;
    -		case XFS_DA_NODE_MAGIC:
    -			/*
    -			 * Remove the offending node, fixup hashvals,
    -			 * check for a toosmall neighbor.
    -			 */
    -			xfs_da_node_remove(state, drop_blk);
    -			xfs_da_fixhashpath(state, &state->path);
    -			error = xfs_da_node_toosmall(state, &action);
    -			if (error)
    -				return(error);
    -			if (action == 0)
    -				return 0;
    -			xfs_da_node_unbalance(state, drop_blk, save_blk);
    -			break;
    -		}
    -		xfs_da_fixhashpath(state, &state->altpath);
    -		error = xfs_da_blk_unlink(state, drop_blk, save_blk);
    -		xfs_da_state_kill_altpath(state);
    -		if (error)
    -			return(error);
    -		error = xfs_da_shrink_inode(state->args, drop_blk->blkno,
    -							 drop_blk->bp);
    -		drop_blk->bp = NULL;
    -		if (error)
    -			return(error);
    -	}
    -	/*
    -	 * We joined all the way to the top.  If it turns out that
    -	 * we only have one entry in the root, make the child block
    -	 * the new root.
    -	 */
    -	xfs_da_node_remove(state, drop_blk);
    -	xfs_da_fixhashpath(state, &state->path);
    -	error = xfs_da_root_join(state, &state->path.blk[0]);
    -	return(error);
    -}
    -
    -/*
    - * We have only one entry in the root.  Copy the only remaining child of
    - * the old root to block 0 as the new root node.
    - */
    -STATIC int
    -xfs_da_root_join(xfs_da_state_t *state, xfs_da_state_blk_t *root_blk)
    -{
    -	xfs_da_intnode_t *oldroot;
    -	/* REFERENCED */
    -	xfs_da_blkinfo_t *blkinfo;
    -	xfs_da_args_t *args;
    -	xfs_dablk_t child;
    -	xfs_dabuf_t *bp;
    -	int error;
    -
    -	args = state->args;
    -	ASSERT(args != NULL);
    -	ASSERT(root_blk->magic == XFS_DA_NODE_MAGIC);
    -	oldroot = root_blk->bp->data;
    -	ASSERT(be16_to_cpu(oldroot->hdr.info.magic) == XFS_DA_NODE_MAGIC);
    -	ASSERT(!oldroot->hdr.info.forw);
    -	ASSERT(!oldroot->hdr.info.back);
    -
    -	/*
    -	 * If the root has more than one child, then don't do anything.
    -	 */
    -	if (be16_to_cpu(oldroot->hdr.count) > 1)
    -		return(0);
    -
    -	/*
    -	 * Read in the (only) child block, then copy those bytes into
    -	 * the root block's buffer and free the original child block.
    -	 */
    -	child = be32_to_cpu(oldroot->btree[0].before);
    -	ASSERT(child != 0);
    -	error = xfs_da_read_buf(args->trans, args->dp, child, -1, &bp,
    -					     args->whichfork);
    -	if (error)
    -		return(error);
    -	ASSERT(bp != NULL);
    -	blkinfo = bp->data;
    -	if (be16_to_cpu(oldroot->hdr.level) == 1) {
    -		ASSERT(be16_to_cpu(blkinfo->magic) == XFS_DIRX_LEAF_MAGIC(state->mp) ||
    -		       be16_to_cpu(blkinfo->magic) == XFS_ATTR_LEAF_MAGIC);
    -	} else {
    -		ASSERT(be16_to_cpu(blkinfo->magic) == XFS_DA_NODE_MAGIC);
    -	}
    -	ASSERT(!blkinfo->forw);
    -	ASSERT(!blkinfo->back);
    -	memcpy(root_blk->bp->data, bp->data, state->blocksize);
    -	xfs_da_log_buf(args->trans, root_blk->bp, 0, state->blocksize - 1);
    -	error = xfs_da_shrink_inode(args, child, bp);
    -	return(error);
    -}
    -
    -/*
    - * Check a node block and its neighbors to see if the block should be
    - * collapsed into one or the other neighbor.  Always keep the block
    - * with the smaller block number.
    - * If the current block is over 50% full, don't try to join it, return 0.
    - * If the block is empty, fill in the state structure and return 2.
    - * If it can be collapsed, fill in the state structure and return 1.
    - * If nothing can be done, return 0.
    - */
    -STATIC int
    -xfs_da_node_toosmall(xfs_da_state_t *state, int *action)
    -{
    -	xfs_da_intnode_t *node;
    -	xfs_da_state_blk_t *blk;
    -	xfs_da_blkinfo_t *info;
    -	int count, forward, error, retval, i;
    -	xfs_dablk_t blkno;
    -	xfs_dabuf_t *bp;
    -
    -	/*
    -	 * Check for the degenerate case of the block being over 50% full.
    -	 * If so, it's not worth even looking to see if we might be able
    -	 * to coalesce with a sibling.
    -	 */
    -	blk = &state->path.blk[ state->path.active-1 ];
    -	info = blk->bp->data;
    -	ASSERT(be16_to_cpu(info->magic) == XFS_DA_NODE_MAGIC);
    -	node = (xfs_da_intnode_t *)info;
    -	count = be16_to_cpu(node->hdr.count);
    -	if (count > (state->node_ents >> 1)) {
    -		*action = 0;	/* blk over 50%, don't try to join */
    -		return(0);	/* blk over 50%, don't try to join */
    -	}
    -
    -	/*
    -	 * Check for the degenerate case of the block being empty.
    -	 * If the block is empty, we'll simply delete it, no need to
    -	 * coalesce it with a sibling block.  We choose (arbitrarily)
    -	 * to merge with the forward block unless it is NULL.
    -	 */
    -	if (count == 0) {
    -		/*
    -		 * Make altpath point to the block we want to keep and
    -		 * path point to the block we want to drop (this one).
    -		 */
    -		forward = (info->forw != 0);
    -		memcpy(&state->altpath, &state->path, sizeof(state->path));
    -		error = xfs_da_path_shift(state, &state->altpath, forward,
    -						 0, &retval);
    -		if (error)
    -			return(error);
    -		if (retval) {
    -			*action = 0;
    -		} else {
    -			*action = 2;
    -		}
    -		return(0);
    -	}
    -
    -	/*
    -	 * Examine each sibling block to see if we can coalesce with
    -	 * at least 25% free space to spare.  We need to figure out
    -	 * whether to merge with the forward or the backward block.
    -	 * We prefer coalescing with the lower numbered sibling so as
    -	 * to shrink a directory over time.
    -	 */
    -	/* start with smaller blk num */
    -	forward = (be32_to_cpu(info->forw) < be32_to_cpu(info->back));
    -	for (i = 0; i < 2; forward = !forward, i++) {
    -		if (forward)
    -			blkno = be32_to_cpu(info->forw);
    -		else
    -			blkno = be32_to_cpu(info->back);
    -		if (blkno == 0)
    -			continue;
    -		error = xfs_da_read_buf(state->args->trans, state->args->dp,
    -					blkno, -1, &bp, state->args->whichfork);
    -		if (error)
    -			return(error);
    -		ASSERT(bp != NULL);
    -
    -		node = (xfs_da_intnode_t *)info;
    -		count  = state->node_ents;
    -		count -= state->node_ents >> 2;
    -		count -= be16_to_cpu(node->hdr.count);
    -		node = bp->data;
    -		ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC);
    -		count -= be16_to_cpu(node->hdr.count);
    -		xfs_da_brelse(state->args->trans, bp);
    -		if (count >= 0)
    -			break;	/* fits with at least 25% to spare */
    -	}
    -	if (i >= 2) {
    -		*action = 0;
    -		return(0);
    -	}
    -
    -	/*
    -	 * Make altpath point to the block we want to keep (the lower
    -	 * numbered block) and path point to the block we want to drop.
    -	 */
    -	memcpy(&state->altpath, &state->path, sizeof(state->path));
    -	if (blkno < blk->blkno) {
    -		error = xfs_da_path_shift(state, &state->altpath, forward,
    -						 0, &retval);
    -		if (error) {
    -			return(error);
    -		}
    -		if (retval) {
    -			*action = 0;
    -			return(0);
    -		}
    -	} else {
    -		error = xfs_da_path_shift(state, &state->path, forward,
    -						 0, &retval);
    -		if (error) {
    -			return(error);
    -		}
    -		if (retval) {
    -			*action = 0;
    -			return(0);
    -		}
    -	}
    -	*action = 1;
    -	return(0);
    -}
    -
    -/*
    - * Walk back up the tree adjusting hash values as necessary,
    - * when we stop making changes, return.
    - */
    -void
    -xfs_da_fixhashpath(xfs_da_state_t *state, xfs_da_state_path_t *path)
    -{
    -	xfs_da_state_blk_t *blk;
    -	xfs_da_intnode_t *node;
    -	xfs_da_node_entry_t *btree;
    -	xfs_dahash_t lasthash=0;
    -	int level, count;
    -
    -	level = path->active-1;
    -	blk = &path->blk[ level ];
    -	switch (blk->magic) {
    -	case XFS_ATTR_LEAF_MAGIC:
    -		lasthash = xfs_attr_leaf_lasthash(blk->bp, &count);
    -		if (count == 0)
    -			return;
    -		break;
    -	case XFS_DIR_LEAF_MAGIC:
    -		ASSERT(XFS_DIR_IS_V1(state->mp));
    -		lasthash = xfs_dir_leaf_lasthash(blk->bp, &count);
    -		if (count == 0)
    -			return;
    -		break;
    -	case XFS_DIR2_LEAFN_MAGIC:
    -		ASSERT(XFS_DIR_IS_V2(state->mp));
    -		lasthash = xfs_dir2_leafn_lasthash(blk->bp, &count);
    -		if (count == 0)
    -			return;
    -		break;
    -	case XFS_DA_NODE_MAGIC:
    -		lasthash = xfs_da_node_lasthash(blk->bp, &count);
    -		if (count == 0)
    -			return;
    -		break;
    -	}
    -	for (blk--, level--; level >= 0; blk--, level--) {
    -		node = blk->bp->data;
    -		ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC);
    -		btree = &node->btree[ blk->index ];
    -		if (be32_to_cpu(btree->hashval) == lasthash)
    -			break;
    -		blk->hashval = lasthash;
    -		btree->hashval = cpu_to_be32(lasthash);
    -		xfs_da_log_buf(state->args->trans, blk->bp,
    -				  XFS_DA_LOGRANGE(node, btree, sizeof(*btree)));
    -
    -		lasthash = be32_to_cpu(node->btree[be16_to_cpu(node->hdr.count)-1].hashval);
    -	}
    -}
    -
    -/*
    - * Remove an entry from an intermediate node.
    - */
    -STATIC void
    -xfs_da_node_remove(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk)
    -{
    -	xfs_da_intnode_t *node;
    -	xfs_da_node_entry_t *btree;
    -	int tmp;
    -
    -	node = drop_blk->bp->data;
    -	ASSERT(drop_blk->index < be16_to_cpu(node->hdr.count));
    -	ASSERT(drop_blk->index >= 0);
    -
    -	/*
    -	 * Copy over the offending entry, or just zero it out.
    -	 */
    -	btree = &node->btree[drop_blk->index];
    -	if (drop_blk->index < (be16_to_cpu(node->hdr.count)-1)) {
    -		tmp  = be16_to_cpu(node->hdr.count) - drop_blk->index - 1;
    -		tmp *= (uint)sizeof(xfs_da_node_entry_t);
    -		memmove(btree, btree + 1, tmp);
    -		xfs_da_log_buf(state->args->trans, drop_blk->bp,
    -		    XFS_DA_LOGRANGE(node, btree, tmp));
    -		btree = &node->btree[be16_to_cpu(node->hdr.count)-1];
    -	}
    -	memset((char *)btree, 0, sizeof(xfs_da_node_entry_t));
    -	xfs_da_log_buf(state->args->trans, drop_blk->bp,
    -	    XFS_DA_LOGRANGE(node, btree, sizeof(*btree)));
    -	be16_add(&node->hdr.count, -1);
    -	xfs_da_log_buf(state->args->trans, drop_blk->bp,
    -	    XFS_DA_LOGRANGE(node, &node->hdr, sizeof(node->hdr)));
    -
    -	/*
    -	 * Copy the last hash value from the block to propagate upwards.
    -	 */
    -	btree--;
    -	drop_blk->hashval = be32_to_cpu(btree->hashval);
    -}
    -
    -/*
    - * Unbalance the btree elements between two intermediate nodes,
    - * move all Btree elements from one node into another.
    - */
    -STATIC void
    -xfs_da_node_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
    -				     xfs_da_state_blk_t *save_blk)
    -{
    -	xfs_da_intnode_t *drop_node, *save_node;
    -	xfs_da_node_entry_t *btree;
    -	int tmp;
    -	xfs_trans_t *tp;
    -
    -	drop_node = drop_blk->bp->data;
    -	save_node = save_blk->bp->data;
    -	ASSERT(be16_to_cpu(drop_node->hdr.info.magic) == XFS_DA_NODE_MAGIC);
    -	ASSERT(be16_to_cpu(save_node->hdr.info.magic) == XFS_DA_NODE_MAGIC);
    -	tp = state->args->trans;
    -
    -	/*
    -	 * If the dying block has lower hashvals, then move all the
    -	 * elements in the remaining block up to make a hole.
    -	 */
    -	if ((be32_to_cpu(drop_node->btree[0].hashval) < be32_to_cpu(save_node->btree[ 0 ].hashval)) ||
    -	    (be32_to_cpu(drop_node->btree[be16_to_cpu(drop_node->hdr.count)-1].hashval) <
    -	     be32_to_cpu(save_node->btree[be16_to_cpu(save_node->hdr.count)-1].hashval)))
    -	{
    -		btree = &save_node->btree[be16_to_cpu(drop_node->hdr.count)];
    -		tmp = be16_to_cpu(save_node->hdr.count) * (uint)sizeof(xfs_da_node_entry_t);
    -		memmove(btree, &save_node->btree[0], tmp);
    -		btree = &save_node->btree[0];
    -		xfs_da_log_buf(tp, save_blk->bp,
    -			XFS_DA_LOGRANGE(save_node, btree,
    -				(be16_to_cpu(save_node->hdr.count) + be16_to_cpu(drop_node->hdr.count)) *
    -				sizeof(xfs_da_node_entry_t)));
    -	} else {
    -		btree = &save_node->btree[be16_to_cpu(save_node->hdr.count)];
    -		xfs_da_log_buf(tp, save_blk->bp,
    -			XFS_DA_LOGRANGE(save_node, btree,
    -				be16_to_cpu(drop_node->hdr.count) *
    -				sizeof(xfs_da_node_entry_t)));
    -	}
    -
    -	/*
    -	 * Move all the B-tree elements from drop_blk to save_blk.
    -	 */
    -	tmp = be16_to_cpu(drop_node->hdr.count) * (uint)sizeof(xfs_da_node_entry_t);
    -	memcpy(btree, &drop_node->btree[0], tmp);
    -	be16_add(&save_node->hdr.count, be16_to_cpu(drop_node->hdr.count));
    -
    -	xfs_da_log_buf(tp, save_blk->bp,
    -		XFS_DA_LOGRANGE(save_node, &save_node->hdr,
    -			sizeof(save_node->hdr)));
    -
    -	/*
    -	 * Save the last hashval in the remaining block for upward propagation.
    -	 */
    -	save_blk->hashval = be32_to_cpu(save_node->btree[be16_to_cpu(save_node->hdr.count)-1].hashval);
    -}
    -
    -/*========================================================================
    - * Routines used for finding things in the Btree.
    - *========================================================================*/
    -
    -/*
    - * Walk down the Btree looking for a particular filename, filling
    - * in the state structure as we go.
    - *
    - * We will set the state structure to point to each of the elements
    - * in each of the nodes where either the hashval is or should be.
    - *
    - * We support duplicate hashval's so for each entry in the current
    - * node that could contain the desired hashval, descend.  This is a
    - * pruned depth-first tree search.
    - */
    -int							/* error */
    -xfs_da_node_lookup_int(xfs_da_state_t *state, int *result)
    -{
    -	xfs_da_state_blk_t *blk;
    -	xfs_da_blkinfo_t *curr;
    -	xfs_da_intnode_t *node;
    -	xfs_da_node_entry_t *btree;
    -	xfs_dablk_t blkno;
    -	int probe, span, max, error, retval;
    -	xfs_dahash_t hashval;
    -	xfs_da_args_t *args;
    -
    -	args = state->args;
    -
    -	/*
    -	 * Descend thru the B-tree searching each level for the right
    -	 * node to use, until the right hashval is found.
    -	 */
    -	if (args->whichfork == XFS_DATA_FORK && XFS_DIR_IS_V2(state->mp))
    -		blkno = state->mp->m_dirleafblk;
    -	else
    -		blkno = 0;
    -	for (blk = &state->path.blk[0], state->path.active = 1;
    -			 state->path.active <= XFS_DA_NODE_MAXDEPTH;
    -			 blk++, state->path.active++) {
    -		/*
    -		 * Read the next node down in the tree.
    -		 */
    -		blk->blkno = blkno;
    -		error = xfs_da_read_buf(args->trans, args->dp, blkno,
    -					-1, &blk->bp, args->whichfork);
    -		if (error) {
    -			blk->blkno = 0;
    -			state->path.active--;
    -			return(error);
    -		}
    -		curr = blk->bp->data;
    -		ASSERT(be16_to_cpu(curr->magic) == XFS_DA_NODE_MAGIC ||
    -		       be16_to_cpu(curr->magic) == XFS_DIRX_LEAF_MAGIC(state->mp) ||
    -		       be16_to_cpu(curr->magic) == XFS_ATTR_LEAF_MAGIC);
    -
    -		/*
    -		 * Search an intermediate node for a match.
    -		 */
    -		blk->magic = be16_to_cpu(curr->magic);
    -		if (blk->magic == XFS_DA_NODE_MAGIC) {
    -			node = blk->bp->data;
    -			blk->hashval = be32_to_cpu(node->btree[be16_to_cpu(node->hdr.count)-1].hashval);
    -
    -			/*
    -			 * Binary search.  (note: small blocks will skip loop)
    -			 */
    -			max = be16_to_cpu(node->hdr.count);
    -			probe = span = max / 2;
    -			hashval = args->hashval;
    -			for (btree = &node->btree[probe]; span > 4;
    -				   btree = &node->btree[probe]) {
    -				span /= 2;
    -				if (be32_to_cpu(btree->hashval) < hashval)
    -					probe += span;
    -				else if (be32_to_cpu(btree->hashval) > hashval)
    -					probe -= span;
    -				else
    -					break;
    -			}
    -			ASSERT((probe >= 0) && (probe < max));
    -			ASSERT((span <= 4) || (be32_to_cpu(btree->hashval) == hashval));
    -
    -			/*
    -			 * Since we may have duplicate hashval's, find the first
    -			 * matching hashval in the node.
    -			 */
    -			while ((probe > 0) && (be32_to_cpu(btree->hashval) >= hashval)) {
    -				btree--;
    -				probe--;
    -			}
    -			while ((probe < max) && (be32_to_cpu(btree->hashval) < hashval)) {
    -				btree++;
    -				probe++;
    -			}
    -
    -			/*
    -			 * Pick the right block to descend on.
    -			 */
    -			if (probe == max) {
    -				blk->index = max-1;
    -				blkno = be32_to_cpu(node->btree[max-1].before);
    -			} else {
    -				blk->index = probe;
    -				blkno = be32_to_cpu(btree->before);
    -			}
    -		}
    -		else if (be16_to_cpu(curr->magic) == XFS_ATTR_LEAF_MAGIC) {
    -			blk->hashval = xfs_attr_leaf_lasthash(blk->bp, NULL);
    -			break;
    -		}
    -		else if (be16_to_cpu(curr->magic) == XFS_DIR_LEAF_MAGIC) {
    -			blk->hashval = xfs_dir_leaf_lasthash(blk->bp, NULL);
    -			break;
    -		}
    -		else if (be16_to_cpu(curr->magic) == XFS_DIR2_LEAFN_MAGIC) {
    -			blk->hashval = xfs_dir2_leafn_lasthash(blk->bp, NULL);
    -			break;
    -		}
    -	}
    -
    -	/*
    -	 * A leaf block that ends in the hashval that we are interested in
    -	 * (final hashval == search hashval) means that the next block may
    -	 * contain more entries with the same hashval, shift upward to the
    -	 * next leaf and keep searching.
    -	 */
    -	for (;;) {
    -		if (blk->magic == XFS_DIR_LEAF_MAGIC) {
    -			ASSERT(XFS_DIR_IS_V1(state->mp));
    -			retval = xfs_dir_leaf_lookup_int(blk->bp, args,
    -								  &blk->index);
    -		} else if (blk->magic == XFS_DIR2_LEAFN_MAGIC) {
    -			ASSERT(XFS_DIR_IS_V2(state->mp));
    -			retval = xfs_dir2_leafn_lookup_int(blk->bp, args,
    -							&blk->index, state);
    -		}
    -		else if (blk->magic == XFS_ATTR_LEAF_MAGIC) {
    -			retval = xfs_attr_leaf_lookup_int(blk->bp, args);
    -			blk->index = args->index;
    -			args->blkno = blk->blkno;
    -		}
    -		if (((retval == ENOENT) || (retval == ENOATTR)) &&
    -		    (blk->hashval == args->hashval)) {
    -			error = xfs_da_path_shift(state, &state->path, 1, 1,
    -							 &retval);
    -			if (error)
    -				return(error);
    -			if (retval == 0) {
    -				continue;
    -			}
    -			else if (blk->magic == XFS_ATTR_LEAF_MAGIC) {
    -				/* path_shift() gives ENOENT */
    -				retval = XFS_ERROR(ENOATTR);
    -			}
    -		}
    -		break;
    -	}
    -	*result = retval;
    -	return(0);
    -}
    -
    -/*========================================================================
    - * Utility routines.
    - *========================================================================*/
    -
    -/*
    - * Link a new block into a doubly linked list of blocks (of whatever type).
    - */
    -int							/* error */
    -xfs_da_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk,
    -			       xfs_da_state_blk_t *new_blk)
    -{
    -	xfs_da_blkinfo_t *old_info, *new_info, *tmp_info;
    -	xfs_da_args_t *args;
    -	int before=0, error;
    -	xfs_dabuf_t *bp;
    -
    -	/*
    -	 * Set up environment.
    -	 */
    -	args = state->args;
    -	ASSERT(args != NULL);
    -	old_info = old_blk->bp->data;
    -	new_info = new_blk->bp->data;
    -	ASSERT(old_blk->magic == XFS_DA_NODE_MAGIC ||
    -	       old_blk->magic == XFS_DIRX_LEAF_MAGIC(state->mp) ||
    -	       old_blk->magic == XFS_ATTR_LEAF_MAGIC);
    -	ASSERT(old_blk->magic == be16_to_cpu(old_info->magic));
    -	ASSERT(new_blk->magic == be16_to_cpu(new_info->magic));
    -	ASSERT(old_blk->magic == new_blk->magic);
    -
    -	switch (old_blk->magic) {
    -	case XFS_ATTR_LEAF_MAGIC:
    -		before = xfs_attr_leaf_order(old_blk->bp, new_blk->bp);
    -		break;
    -	case XFS_DIR_LEAF_MAGIC:
    -		ASSERT(XFS_DIR_IS_V1(state->mp));
    -		before = xfs_dir_leaf_order(old_blk->bp, new_blk->bp);
    -		break;
    -	case XFS_DIR2_LEAFN_MAGIC:
    -		ASSERT(XFS_DIR_IS_V2(state->mp));
    -		before = xfs_dir2_leafn_order(old_blk->bp, new_blk->bp);
    -		break;
    -	case XFS_DA_NODE_MAGIC:
    -		before = xfs_da_node_order(old_blk->bp, new_blk->bp);
    -		break;
    -	}
    -
    -	/*
    -	 * Link blocks in appropriate order.
    -	 */
    -	if (before) {
    -		/*
    -		 * Link new block in before existing block.
    -		 */
    -		new_info->forw = cpu_to_be32(old_blk->blkno);
    -		new_info->back = old_info->back;
    -		if (old_info->back) {
    -			error = xfs_da_read_buf(args->trans, args->dp,
    -						be32_to_cpu(old_info->back),
    -						-1, &bp, args->whichfork);
    -			if (error)
    -				return(error);
    -			ASSERT(bp != NULL);
    -			tmp_info = bp->data;
    -			ASSERT(be16_to_cpu(tmp_info->magic) == be16_to_cpu(old_info->magic));
    -			ASSERT(be32_to_cpu(tmp_info->forw) == old_blk->blkno);
    -			tmp_info->forw = cpu_to_be32(new_blk->blkno);
    -			xfs_da_log_buf(args->trans, bp, 0, sizeof(*tmp_info)-1);
    -			xfs_da_buf_done(bp);
    -		}
    -		old_info->back = cpu_to_be32(new_blk->blkno);
    -	} else {
    -		/*
    -		 * Link new block in after existing block.
    -		 */
    -		new_info->forw = old_info->forw;
    -		new_info->back = cpu_to_be32(old_blk->blkno);
    -		if (old_info->forw) {
    -			error = xfs_da_read_buf(args->trans, args->dp,
    -						be32_to_cpu(old_info->forw),
    -						-1, &bp, args->whichfork);
    -			if (error)
    -				return(error);
    -			ASSERT(bp != NULL);
    -			tmp_info = bp->data;
    -			ASSERT(tmp_info->magic == old_info->magic);
    -			ASSERT(be32_to_cpu(tmp_info->back) == old_blk->blkno);
    -			tmp_info->back = cpu_to_be32(new_blk->blkno);
    -			xfs_da_log_buf(args->trans, bp, 0, sizeof(*tmp_info)-1);
    -			xfs_da_buf_done(bp);
    -		}
    -		old_info->forw = cpu_to_be32(new_blk->blkno);
    -	}
    -
    -	xfs_da_log_buf(args->trans, old_blk->bp, 0, sizeof(*tmp_info) - 1);
    -	xfs_da_log_buf(args->trans, new_blk->bp, 0, sizeof(*tmp_info) - 1);
    -	return(0);
    -}
    -
    -/*
    - * Compare two intermediate nodes for "order".
    - */
    -STATIC int
    -xfs_da_node_order(xfs_dabuf_t *node1_bp, xfs_dabuf_t *node2_bp)
    -{
    -	xfs_da_intnode_t *node1, *node2;
    -
    -	node1 = node1_bp->data;
    -	node2 = node2_bp->data;
    -	ASSERT((be16_to_cpu(node1->hdr.info.magic) == XFS_DA_NODE_MAGIC) &&
    -	       (be16_to_cpu(node2->hdr.info.magic) == XFS_DA_NODE_MAGIC));
    -	if ((be16_to_cpu(node1->hdr.count) > 0) && (be16_to_cpu(node2->hdr.count) > 0) &&
    -	    ((be32_to_cpu(node2->btree[0].hashval) <
    -	      be32_to_cpu(node1->btree[0].hashval)) ||
    -	     (be32_to_cpu(node2->btree[be16_to_cpu(node2->hdr.count)-1].hashval) <
    -	      be32_to_cpu(node1->btree[be16_to_cpu(node1->hdr.count)-1].hashval)))) {
    -		return(1);
    -	}
    -	return(0);
    -}
    -
    -/*
    - * Pick up the last hashvalue from an intermediate node.
    - */
    -STATIC uint
    -xfs_da_node_lasthash(xfs_dabuf_t *bp, int *count)
    -{
    -	xfs_da_intnode_t *node;
    -
    -	node = bp->data;
    -	ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC);
    -	if (count)
    -		*count = be16_to_cpu(node->hdr.count);
    -	if (!node->hdr.count)
    -		return(0);
    -	return be32_to_cpu(node->btree[be16_to_cpu(node->hdr.count)-1].hashval);
    -}
    -
    -/*
    - * Unlink a block from a doubly linked list of blocks.
    - */
    -STATIC int						/* error */
    -xfs_da_blk_unlink(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
    -				 xfs_da_state_blk_t *save_blk)
    -{
    -	xfs_da_blkinfo_t *drop_info, *save_info, *tmp_info;
    -	xfs_da_args_t *args;
    -	xfs_dabuf_t *bp;
    -	int error;
    -
    -	/*
    -	 * Set up environment.
    -	 */
    -	args = state->args;
    -	ASSERT(args != NULL);
    -	save_info = save_blk->bp->data;
    -	drop_info = drop_blk->bp->data;
    -	ASSERT(save_blk->magic == XFS_DA_NODE_MAGIC ||
    -	       save_blk->magic == XFS_DIRX_LEAF_MAGIC(state->mp) ||
    -	       save_blk->magic == XFS_ATTR_LEAF_MAGIC);
    -	ASSERT(save_blk->magic == be16_to_cpu(save_info->magic));
    -	ASSERT(drop_blk->magic == be16_to_cpu(drop_info->magic));
    -	ASSERT(save_blk->magic == drop_blk->magic);
    -	ASSERT((be32_to_cpu(save_info->forw) == drop_blk->blkno) ||
    -	       (be32_to_cpu(save_info->back) == drop_blk->blkno));
    -	ASSERT((be32_to_cpu(drop_info->forw) == save_blk->blkno) ||
    -	       (be32_to_cpu(drop_info->back) == save_blk->blkno));
    -
    -	/*
    -	 * Unlink the leaf block from the doubly linked chain of leaves.
    -	 */
    -	if (be32_to_cpu(save_info->back) == drop_blk->blkno) {
    -		save_info->back = drop_info->back;
    -		if (drop_info->back) {
    -			error = xfs_da_read_buf(args->trans, args->dp,
    -						be32_to_cpu(drop_info->back),
    -						-1, &bp, args->whichfork);
    -			if (error)
    -				return(error);
    -			ASSERT(bp != NULL);
    -			tmp_info = bp->data;
    -			ASSERT(tmp_info->magic == save_info->magic);
    -			ASSERT(be32_to_cpu(tmp_info->forw) == drop_blk->blkno);
    -			tmp_info->forw = cpu_to_be32(save_blk->blkno);
    -			xfs_da_log_buf(args->trans, bp, 0,
    -						    sizeof(*tmp_info) - 1);
    -			xfs_da_buf_done(bp);
    -		}
    -	} else {
    -		save_info->forw = drop_info->forw;
    -		if (drop_info->forw) {
    -			error = xfs_da_read_buf(args->trans, args->dp,
    -						be32_to_cpu(drop_info->forw),
    -						-1, &bp, args->whichfork);
    -			if (error)
    -				return(error);
    -			ASSERT(bp != NULL);
    -			tmp_info = bp->data;
    -			ASSERT(tmp_info->magic == save_info->magic);
    -			ASSERT(be32_to_cpu(tmp_info->back) == drop_blk->blkno);
    -			tmp_info->back = cpu_to_be32(save_blk->blkno);
    -			xfs_da_log_buf(args->trans, bp, 0,
    -						    sizeof(*tmp_info) - 1);
    -			xfs_da_buf_done(bp);
    -		}
    -	}
    -
    -	xfs_da_log_buf(args->trans, save_blk->bp, 0, sizeof(*save_info) - 1);
    -	return(0);
    -}
    -
    -/*
    - * Move a path "forward" or "!forward" one block at the current level.
    - *
    - * This routine will adjust a "path" to point to the next block
    - * "forward" (higher hashvalues) or "!forward" (lower hashvals) in the
    - * Btree, including updating pointers to the intermediate nodes between
    - * the new bottom and the root.
    - */
    -int							/* error */
    -xfs_da_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path,
    -				 int forward, int release, int *result)
    -{
    -	xfs_da_state_blk_t *blk;
    -	xfs_da_blkinfo_t *info;
    -	xfs_da_intnode_t *node;
    -	xfs_da_args_t *args;
    -	xfs_dablk_t blkno=0;
    -	int level, error;
    -
    -	/*
    -	 * Roll up the Btree looking for the first block where our
    -	 * current index is not at the edge of the block.  Note that
    -	 * we skip the bottom layer because we want the sibling block.
    -	 */
    -	args = state->args;
    -	ASSERT(args != NULL);
    -	ASSERT(path != NULL);
    -	ASSERT((path->active > 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
    -	level = (path->active-1) - 1;	/* skip bottom layer in path */
    -	for (blk = &path->blk[level]; level >= 0; blk--, level--) {
    -		ASSERT(blk->bp != NULL);
    -		node = blk->bp->data;
    -		ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC);
    -		if (forward && (blk->index < be16_to_cpu(node->hdr.count)-1)) {
    -			blk->index++;
    -			blkno = be32_to_cpu(node->btree[blk->index].before);
    -			break;
    -		} else if (!forward && (blk->index > 0)) {
    -			blk->index--;
    -			blkno = be32_to_cpu(node->btree[blk->index].before);
    -			break;
    -		}
    -	}
    -	if (level < 0) {
    -		*result = XFS_ERROR(ENOENT);	/* we're out of our tree */
    -		ASSERT(args->oknoent);
    -		return(0);
    -	}
    -
    -	/*
    -	 * Roll down the edge of the subtree until we reach the
    -	 * same depth we were at originally.
    -	 */
    -	for (blk++, level++; level < path->active; blk++, level++) {
    -		/*
    -		 * Release the old block.
    -		 * (if it's dirty, trans won't actually let go)
    -		 */
    -		if (release)
    -			xfs_da_brelse(args->trans, blk->bp);
    -
    -		/*
    -		 * Read the next child block.
    -		 */
    -		blk->blkno = blkno;
    -		error = xfs_da_read_buf(args->trans, args->dp, blkno, -1,
    -						     &blk->bp, args->whichfork);
    -		if (error)
    -			return(error);
    -		ASSERT(blk->bp != NULL);
    -		info = blk->bp->data;
    -		ASSERT(be16_to_cpu(info->magic) == XFS_DA_NODE_MAGIC ||
    -		       be16_to_cpu(info->magic) == XFS_DIRX_LEAF_MAGIC(state->mp) ||
    -		       be16_to_cpu(info->magic) == XFS_ATTR_LEAF_MAGIC);
    -		blk->magic = be16_to_cpu(info->magic);
    -		if (blk->magic == XFS_DA_NODE_MAGIC) {
    -			node = (xfs_da_intnode_t *)info;
    -			blk->hashval = be32_to_cpu(node->btree[be16_to_cpu(node->hdr.count)-1].hashval);
    -			if (forward)
    -				blk->index = 0;
    -			else
    -				blk->index = be16_to_cpu(node->hdr.count)-1;
    -			blkno = be32_to_cpu(node->btree[blk->index].before);
    -		} else {
    -			ASSERT(level == path->active-1);
    -			blk->index = 0;
    -			switch(blk->magic) {
    -			case XFS_ATTR_LEAF_MAGIC:
    -				blk->hashval = xfs_attr_leaf_lasthash(blk->bp,
    -								      NULL);
    -				break;
    -			case XFS_DIR_LEAF_MAGIC:
    -				ASSERT(XFS_DIR_IS_V1(state->mp));
    -				blk->hashval = xfs_dir_leaf_lasthash(blk->bp,
    -								     NULL);
    -				break;
    -			case XFS_DIR2_LEAFN_MAGIC:
    -				ASSERT(XFS_DIR_IS_V2(state->mp));
    -				blk->hashval = xfs_dir2_leafn_lasthash(blk->bp,
    -								       NULL);
    -				break;
    -			default:
    -				ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC ||
    -				       blk->magic ==
    -				       XFS_DIRX_LEAF_MAGIC(state->mp));
    -				break;
    -			}
    -		}
    -	}
    -	*result = 0;
    -	return(0);
    -}
    -
    -
    -/*========================================================================
    - * Utility routines.
    - *========================================================================*/
    -
    -/*
    - * Implement a simple hash on a character string.
    - * Rotate the hash value by 7 bits, then XOR each character in.
    - * This is implemented with some source-level loop unrolling.
    - */
    -xfs_dahash_t
    -xfs_da_hashname(const uchar_t *name, int namelen)
    -{
    -	xfs_dahash_t hash;
    -
    -	/*
    -	 * Do four characters at a time as long as we can.
    -	 */
    -	for (hash = 0; namelen >= 4; namelen -= 4, name += 4)
    -		hash = (name[0] << 21) ^ (name[1] << 14) ^ (name[2] << 7) ^
    -		       (name[3] << 0) ^ rol32(hash, 7 * 4);
    -
    -	/*
    -	 * Now do the rest of the characters.
    -	 */
    -	switch (namelen) {
    -	case 3:
    -		return (name[0] << 14) ^ (name[1] << 7) ^ (name[2] << 0) ^
    -		       rol32(hash, 7 * 3);
    -	case 2:
    -		return (name[0] << 7) ^ (name[1] << 0) ^ rol32(hash, 7 * 2);
    -	case 1:
    -		return (name[0] << 0) ^ rol32(hash, 7 * 1);
    -	default: /* case 0: */
    -		return hash;
    -	}
    -}
    -
    -/*
    - * Add a block to the btree ahead of the file.
    - * Return the new block number to the caller.
    - */
    -int
    -xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno)
    -{
    -	xfs_fileoff_t bno, b;
    -	xfs_bmbt_irec_t map;
    -	xfs_bmbt_irec_t	*mapp;
    -	xfs_inode_t *dp;
    -	int nmap, error, w, count, c, got, i, mapi;
    -	xfs_fsize_t size;
    -	xfs_trans_t *tp;
    -	xfs_mount_t *mp;
    -
    -	dp = args->dp;
    -	mp = dp->i_mount;
    -	w = args->whichfork;
    -	tp = args->trans;
    -	/*
    -	 * For new directories adjust the file offset and block count.
    -	 */
    -	if (w == XFS_DATA_FORK && XFS_DIR_IS_V2(mp)) {
    -		bno = mp->m_dirleafblk;
    -		count = mp->m_dirblkfsbs;
    -	} else {
    -		bno = 0;
    -		count = 1;
    -	}
    -	/*
    -	 * Find a spot in the file space to put the new block.
    -	 */
    -	if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, w))) {
    -		return error;
    -	}
    -	if (w == XFS_DATA_FORK && XFS_DIR_IS_V2(mp))
    -		ASSERT(bno >= mp->m_dirleafblk && bno < mp->m_dirfreeblk);
    -	/*
    -	 * Try mapping it in one filesystem block.
    -	 */
    -	nmap = 1;
    -	ASSERT(args->firstblock != NULL);
    -	if ((error = xfs_bmapi(tp, dp, bno, count,
    -			XFS_BMAPI_AFLAG(w)|XFS_BMAPI_WRITE|XFS_BMAPI_METADATA|
    -			XFS_BMAPI_CONTIG,
    -			args->firstblock, args->total, &map, &nmap,
    -			args->flist, NULL))) {
    -		return error;
    -	}
    -	ASSERT(nmap <= 1);
    -	if (nmap == 1) {
    -		mapp = ↦
    -		mapi = 1;
    -	}
    -	/*
    -	 * If we didn't get it and the block might work if fragmented,
    -	 * try without the CONTIG flag.  Loop until we get it all.
    -	 */
    -	else if (nmap == 0 && count > 1) {
    -		mapp = kmem_alloc(sizeof(*mapp) * count, KM_SLEEP);
    -		for (b = bno, mapi = 0; b < bno + count; ) {
    -			nmap = MIN(XFS_BMAP_MAX_NMAP, count);
    -			c = (int)(bno + count - b);
    -			if ((error = xfs_bmapi(tp, dp, b, c,
    -					XFS_BMAPI_AFLAG(w)|XFS_BMAPI_WRITE|
    -					XFS_BMAPI_METADATA,
    -					args->firstblock, args->total,
    -					&mapp[mapi], &nmap, args->flist,
    -					NULL))) {
    -				kmem_free(mapp, sizeof(*mapp) * count);
    -				return error;
    -			}
    -			if (nmap < 1)
    -				break;
    -			mapi += nmap;
    -			b = mapp[mapi - 1].br_startoff +
    -			    mapp[mapi - 1].br_blockcount;
    -		}
    -	} else {
    -		mapi = 0;
    -		mapp = NULL;
    -	}
    -	/*
    -	 * Count the blocks we got, make sure it matches the total.
    -	 */
    -	for (i = 0, got = 0; i < mapi; i++)
    -		got += mapp[i].br_blockcount;
    -	if (got != count || mapp[0].br_startoff != bno ||
    -	    mapp[mapi - 1].br_startoff + mapp[mapi - 1].br_blockcount !=
    -	    bno + count) {
    -		if (mapp != &map)
    -			kmem_free(mapp, sizeof(*mapp) * count);
    -		return XFS_ERROR(ENOSPC);
    -	}
    -	if (mapp != &map)
    -		kmem_free(mapp, sizeof(*mapp) * count);
    -	*new_blkno = (xfs_dablk_t)bno;
    -	/*
    -	 * For version 1 directories, adjust the file size if it changed.
    -	 */
    -	if (w == XFS_DATA_FORK && XFS_DIR_IS_V1(mp)) {
    -		ASSERT(mapi == 1);
    -		if ((error = xfs_bmap_last_offset(tp, dp, &bno, w)))
    -			return error;
    -		size = XFS_FSB_TO_B(mp, bno);
    -		if (size != dp->i_d.di_size) {
    -			dp->i_d.di_size = size;
    -			xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
    -		}
    -	}
    -	return 0;
    -}
    -
    -/*
    - * Ick.  We need to always be able to remove a btree block, even
    - * if there's no space reservation because the filesystem is full.
    - * This is called if xfs_bunmapi on a btree block fails due to ENOSPC.
    - * It swaps the target block with the last block in the file.  The
    - * last block in the file can always be removed since it can't cause
    - * a bmap btree split to do that.
    - */
    -STATIC int
    -xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop,
    -		      xfs_dabuf_t **dead_bufp)
    -{
    -	xfs_dablk_t dead_blkno, last_blkno, sib_blkno, par_blkno;
    -	xfs_dabuf_t *dead_buf, *last_buf, *sib_buf, *par_buf;
    -	xfs_fileoff_t lastoff;
    -	xfs_inode_t *ip;
    -	xfs_trans_t *tp;
    -	xfs_mount_t *mp;
    -	int error, w, entno, level, dead_level;
    -	xfs_da_blkinfo_t *dead_info, *sib_info;
    -	xfs_da_intnode_t *par_node, *dead_node;
    -	xfs_dir_leafblock_t *dead_leaf;
    -	xfs_dir2_leaf_t *dead_leaf2;
    -	xfs_dahash_t dead_hash;
    -
    -	dead_buf = *dead_bufp;
    -	dead_blkno = *dead_blknop;
    -	tp = args->trans;
    -	ip = args->dp;
    -	w = args->whichfork;
    -	ASSERT(w == XFS_DATA_FORK);
    -	mp = ip->i_mount;
    -	if (XFS_DIR_IS_V2(mp)) {
    -		lastoff = mp->m_dirfreeblk;
    -		error = xfs_bmap_last_before(tp, ip, &lastoff, w);
    -	} else
    -		error = xfs_bmap_last_offset(tp, ip, &lastoff, w);
    -	if (error)
    -		return error;
    -	if (unlikely(lastoff == 0)) {
    -		XFS_ERROR_REPORT("xfs_da_swap_lastblock(1)", XFS_ERRLEVEL_LOW,
    -				 mp);
    -		return XFS_ERROR(EFSCORRUPTED);
    -	}
    -	/*
    -	 * Read the last block in the btree space.
    -	 */
    -	last_blkno = (xfs_dablk_t)lastoff - mp->m_dirblkfsbs;
    -	if ((error = xfs_da_read_buf(tp, ip, last_blkno, -1, &last_buf, w)))
    -		return error;
    -	/*
    -	 * Copy the last block into the dead buffer and log it.
    -	 */
    -	memcpy(dead_buf->data, last_buf->data, mp->m_dirblksize);
    -	xfs_da_log_buf(tp, dead_buf, 0, mp->m_dirblksize - 1);
    -	dead_info = dead_buf->data;
    -	/*
    -	 * Get values from the moved block.
    -	 */
    -	if (be16_to_cpu(dead_info->magic) == XFS_DIR_LEAF_MAGIC) {
    -		ASSERT(XFS_DIR_IS_V1(mp));
    -		dead_leaf = (xfs_dir_leafblock_t *)dead_info;
    -		dead_level = 0;
    -		dead_hash =
    -			INT_GET(dead_leaf->entries[INT_GET(dead_leaf->hdr.count, ARCH_CONVERT) - 1].hashval, ARCH_CONVERT);
    -	} else if (be16_to_cpu(dead_info->magic) == XFS_DIR2_LEAFN_MAGIC) {
    -		ASSERT(XFS_DIR_IS_V2(mp));
    -		dead_leaf2 = (xfs_dir2_leaf_t *)dead_info;
    -		dead_level = 0;
    -		dead_hash = be32_to_cpu(dead_leaf2->ents[be16_to_cpu(dead_leaf2->hdr.count) - 1].hashval);
    -	} else {
    -		ASSERT(be16_to_cpu(dead_info->magic) == XFS_DA_NODE_MAGIC);
    -		dead_node = (xfs_da_intnode_t *)dead_info;
    -		dead_level = be16_to_cpu(dead_node->hdr.level);
    -		dead_hash = be32_to_cpu(dead_node->btree[be16_to_cpu(dead_node->hdr.count) - 1].hashval);
    -	}
    -	sib_buf = par_buf = NULL;
    -	/*
    -	 * If the moved block has a left sibling, fix up the pointers.
    -	 */
    -	if ((sib_blkno = be32_to_cpu(dead_info->back))) {
    -		if ((error = xfs_da_read_buf(tp, ip, sib_blkno, -1, &sib_buf, w)))
    -			goto done;
    -		sib_info = sib_buf->data;
    -		if (unlikely(
    -		    be32_to_cpu(sib_info->forw) != last_blkno ||
    -		    sib_info->magic != dead_info->magic)) {
    -			XFS_ERROR_REPORT("xfs_da_swap_lastblock(2)",
    -					 XFS_ERRLEVEL_LOW, mp);
    -			error = XFS_ERROR(EFSCORRUPTED);
    -			goto done;
    -		}
    -		sib_info->forw = cpu_to_be32(dead_blkno);
    -		xfs_da_log_buf(tp, sib_buf,
    -			XFS_DA_LOGRANGE(sib_info, &sib_info->forw,
    -					sizeof(sib_info->forw)));
    -		xfs_da_buf_done(sib_buf);
    -		sib_buf = NULL;
    -	}
    -	/*
    -	 * If the moved block has a right sibling, fix up the pointers.
    -	 */
    -	if ((sib_blkno = be32_to_cpu(dead_info->forw))) {
    -		if ((error = xfs_da_read_buf(tp, ip, sib_blkno, -1, &sib_buf, w)))
    -			goto done;
    -		sib_info = sib_buf->data;
    -		if (unlikely(
    -		       be32_to_cpu(sib_info->back) != last_blkno ||
    -		       sib_info->magic != dead_info->magic)) {
    -			XFS_ERROR_REPORT("xfs_da_swap_lastblock(3)",
    -					 XFS_ERRLEVEL_LOW, mp);
    -			error = XFS_ERROR(EFSCORRUPTED);
    -			goto done;
    -		}
    -		sib_info->back = cpu_to_be32(dead_blkno);
    -		xfs_da_log_buf(tp, sib_buf,
    -			XFS_DA_LOGRANGE(sib_info, &sib_info->back,
    -					sizeof(sib_info->back)));
    -		xfs_da_buf_done(sib_buf);
    -		sib_buf = NULL;
    -	}
    -	par_blkno = XFS_DIR_IS_V1(mp) ? 0 : mp->m_dirleafblk;
    -	level = -1;
    -	/*
    -	 * Walk down the tree looking for the parent of the moved block.
    -	 */
    -	for (;;) {
    -		if ((error = xfs_da_read_buf(tp, ip, par_blkno, -1, &par_buf, w)))
    -			goto done;
    -		par_node = par_buf->data;
    -		if (unlikely(
    -		    be16_to_cpu(par_node->hdr.info.magic) != XFS_DA_NODE_MAGIC ||
    -		    (level >= 0 && level != be16_to_cpu(par_node->hdr.level) + 1))) {
    -			XFS_ERROR_REPORT("xfs_da_swap_lastblock(4)",
    -					 XFS_ERRLEVEL_LOW, mp);
    -			error = XFS_ERROR(EFSCORRUPTED);
    -			goto done;
    -		}
    -		level = be16_to_cpu(par_node->hdr.level);
    -		for (entno = 0;
    -		     entno < be16_to_cpu(par_node->hdr.count) &&
    -		     be32_to_cpu(par_node->btree[entno].hashval) < dead_hash;
    -		     entno++)
    -			continue;
    -		if (unlikely(entno == be16_to_cpu(par_node->hdr.count))) {
    -			XFS_ERROR_REPORT("xfs_da_swap_lastblock(5)",
    -					 XFS_ERRLEVEL_LOW, mp);
    -			error = XFS_ERROR(EFSCORRUPTED);
    -			goto done;
    -		}
    -		par_blkno = be32_to_cpu(par_node->btree[entno].before);
    -		if (level == dead_level + 1)
    -			break;
    -		xfs_da_brelse(tp, par_buf);
    -		par_buf = NULL;
    -	}
    -	/*
    -	 * We're in the right parent block.
    -	 * Look for the right entry.
    -	 */
    -	for (;;) {
    -		for (;
    -		     entno < be16_to_cpu(par_node->hdr.count) &&
    -		     be32_to_cpu(par_node->btree[entno].before) != last_blkno;
    -		     entno++)
    -			continue;
    -		if (entno < be16_to_cpu(par_node->hdr.count))
    -			break;
    -		par_blkno = be32_to_cpu(par_node->hdr.info.forw);
    -		xfs_da_brelse(tp, par_buf);
    -		par_buf = NULL;
    -		if (unlikely(par_blkno == 0)) {
    -			XFS_ERROR_REPORT("xfs_da_swap_lastblock(6)",
    -					 XFS_ERRLEVEL_LOW, mp);
    -			error = XFS_ERROR(EFSCORRUPTED);
    -			goto done;
    -		}
    -		if ((error = xfs_da_read_buf(tp, ip, par_blkno, -1, &par_buf, w)))
    -			goto done;
    -		par_node = par_buf->data;
    -		if (unlikely(
    -		    be16_to_cpu(par_node->hdr.level) != level ||
    -		    be16_to_cpu(par_node->hdr.info.magic) != XFS_DA_NODE_MAGIC)) {
    -			XFS_ERROR_REPORT("xfs_da_swap_lastblock(7)",
    -					 XFS_ERRLEVEL_LOW, mp);
    -			error = XFS_ERROR(EFSCORRUPTED);
    -			goto done;
    -		}
    -		entno = 0;
    -	}
    -	/*
    -	 * Update the parent entry pointing to the moved block.
    -	 */
    -	par_node->btree[entno].before = cpu_to_be32(dead_blkno);
    -	xfs_da_log_buf(tp, par_buf,
    -		XFS_DA_LOGRANGE(par_node, &par_node->btree[entno].before,
    -				sizeof(par_node->btree[entno].before)));
    -	xfs_da_buf_done(par_buf);
    -	xfs_da_buf_done(dead_buf);
    -	*dead_blknop = last_blkno;
    -	*dead_bufp = last_buf;
    -	return 0;
    -done:
    -	if (par_buf)
    -		xfs_da_brelse(tp, par_buf);
    -	if (sib_buf)
    -		xfs_da_brelse(tp, sib_buf);
    -	xfs_da_brelse(tp, last_buf);
    -	return error;
    -}
    -
    -/*
    - * Remove a btree block from a directory or attribute.
    - */
    -int
    -xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno,
    -		    xfs_dabuf_t *dead_buf)
    -{
    -	xfs_inode_t *dp;
    -	int done, error, w, count;
    -	xfs_fileoff_t bno;
    -	xfs_fsize_t size;
    -	xfs_trans_t *tp;
    -	xfs_mount_t *mp;
    -
    -	dp = args->dp;
    -	w = args->whichfork;
    -	tp = args->trans;
    -	mp = dp->i_mount;
    -	if (w == XFS_DATA_FORK && XFS_DIR_IS_V2(mp))
    -		count = mp->m_dirblkfsbs;
    -	else
    -		count = 1;
    -	for (;;) {
    -		/*
    -		 * Remove extents.  If we get ENOSPC for a dir we have to move
    -		 * the last block to the place we want to kill.
    -		 */
    -		if ((error = xfs_bunmapi(tp, dp, dead_blkno, count,
    -				XFS_BMAPI_AFLAG(w)|XFS_BMAPI_METADATA,
    -				0, args->firstblock, args->flist, NULL,
    -				&done)) == ENOSPC) {
    -			if (w != XFS_DATA_FORK)
    -				goto done;
    -			if ((error = xfs_da_swap_lastblock(args, &dead_blkno,
    -					&dead_buf)))
    -				goto done;
    -		} else if (error)
    -			goto done;
    -		else
    -			break;
    -	}
    -	ASSERT(done);
    -	xfs_da_binval(tp, dead_buf);
    -	/*
    -	 * Adjust the directory size for version 1.
    -	 */
    -	if (w == XFS_DATA_FORK && XFS_DIR_IS_V1(mp)) {
    -		if ((error = xfs_bmap_last_offset(tp, dp, &bno, w)))
    -			return error;
    -		size = XFS_FSB_TO_B(dp->i_mount, bno);
    -		if (size != dp->i_d.di_size) {
    -			dp->i_d.di_size = size;
    -			xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
    -		}
    -	}
    -	return 0;
    -done:
    -	xfs_da_binval(tp, dead_buf);
    -	return error;
    -}
    -
    -/*
    - * See if the mapping(s) for this btree block are valid, i.e.
    - * don't contain holes, are logically contiguous, and cover the whole range.
    - */
    -STATIC int
    -xfs_da_map_covers_blocks(
    -	int		nmap,
    -	xfs_bmbt_irec_t	*mapp,
    -	xfs_dablk_t	bno,
    -	int		count)
    -{
    -	int		i;
    -	xfs_fileoff_t	off;
    -
    -	for (i = 0, off = bno; i < nmap; i++) {
    -		if (mapp[i].br_startblock == HOLESTARTBLOCK ||
    -		    mapp[i].br_startblock == DELAYSTARTBLOCK) {
    -			return 0;
    -		}
    -		if (off != mapp[i].br_startoff) {
    -			return 0;
    -		}
    -		off += mapp[i].br_blockcount;
    -	}
    -	return off == bno + count;
    -}
    -
    -/*
    - * Make a dabuf.
    - * Used for get_buf, read_buf, read_bufr, and reada_buf.
    - */
    -STATIC int
    -xfs_da_do_buf(
    -	xfs_trans_t	*trans,
    -	xfs_inode_t	*dp,
    -	xfs_dablk_t	bno,
    -	xfs_daddr_t	*mappedbnop,
    -	xfs_dabuf_t	**bpp,
    -	int		whichfork,
    -	int		caller,
    -	inst_t		*ra)
    -{
    -	xfs_buf_t	*bp = NULL;
    -	xfs_buf_t	**bplist;
    -	int		error=0;
    -	int		i;
    -	xfs_bmbt_irec_t	map;
    -	xfs_bmbt_irec_t	*mapp;
    -	xfs_daddr_t	mappedbno;
    -	xfs_mount_t	*mp;
    -	int		nbplist=0;
    -	int		nfsb;
    -	int		nmap;
    -	xfs_dabuf_t	*rbp;
    -
    -	mp = dp->i_mount;
    -	if (whichfork == XFS_DATA_FORK && XFS_DIR_IS_V2(mp))
    -		nfsb = mp->m_dirblkfsbs;
    -	else
    -		nfsb = 1;
    -	mappedbno = *mappedbnop;
    -	/*
    -	 * Caller doesn't have a mapping.  -2 means don't complain
    -	 * if we land in a hole.
    -	 */
    -	if (mappedbno == -1 || mappedbno == -2) {
    -		/*
    -		 * Optimize the one-block case.
    -		 */
    -		if (nfsb == 1) {
    -			xfs_fsblock_t	fsb;
    -
    -			if ((error =
    -			    xfs_bmapi_single(trans, dp, whichfork, &fsb,
    -				    (xfs_fileoff_t)bno))) {
    -				return error;
    -			}
    -			mapp = ↦
    -			if (fsb == NULLFSBLOCK) {
    -				nmap = 0;
    -			} else {
    -				map.br_startblock = fsb;
    -				map.br_startoff = (xfs_fileoff_t)bno;
    -				map.br_blockcount = 1;
    -				nmap = 1;
    -			}
    -		} else {
    -			mapp = kmem_alloc(sizeof(*mapp) * nfsb, KM_SLEEP);
    -			nmap = nfsb;
    -			if ((error = xfs_bmapi(trans, dp, (xfs_fileoff_t)bno,
    -					nfsb,
    -					XFS_BMAPI_METADATA |
    -						XFS_BMAPI_AFLAG(whichfork),
    -					NULL, 0, mapp, &nmap, NULL, NULL)))
    -				goto exit0;
    -		}
    -	} else {
    -		map.br_startblock = XFS_DADDR_TO_FSB(mp, mappedbno);
    -		map.br_startoff = (xfs_fileoff_t)bno;
    -		map.br_blockcount = nfsb;
    -		mapp = ↦
    -		nmap = 1;
    -	}
    -	if (!xfs_da_map_covers_blocks(nmap, mapp, bno, nfsb)) {
    -		error = mappedbno == -2 ? 0 : XFS_ERROR(EFSCORRUPTED);
    -		if (unlikely(error == EFSCORRUPTED)) {
    -			if (xfs_error_level >= XFS_ERRLEVEL_LOW) {
    -				int	i;
    -				cmn_err(CE_ALERT, "xfs_da_do_buf: bno %lld\n",
    -					(long long)bno);
    -				cmn_err(CE_ALERT, "dir: inode %lld\n",
    -					(long long)dp->i_ino);
    -				for (i = 0; i < nmap; i++) {
    -					cmn_err(CE_ALERT,
    -						"[%02d] br_startoff %lld br_startblock %lld br_blockcount %lld br_state %d\n",
    -						i,
    -						(long long)mapp[i].br_startoff,
    -						(long long)mapp[i].br_startblock,
    -						(long long)mapp[i].br_blockcount,
    -						mapp[i].br_state);
    -				}
    -			}
    -			XFS_ERROR_REPORT("xfs_da_do_buf(1)",
    -					 XFS_ERRLEVEL_LOW, mp);
    -		}
    -		goto exit0;
    -	}
    -	if (caller != 3 && nmap > 1) {
    -		bplist = kmem_alloc(sizeof(*bplist) * nmap, KM_SLEEP);
    -		nbplist = 0;
    -	} else
    -		bplist = NULL;
    -	/*
    -	 * Turn the mapping(s) into buffer(s).
    -	 */
    -	for (i = 0; i < nmap; i++) {
    -		int	nmapped;
    -
    -		mappedbno = XFS_FSB_TO_DADDR(mp, mapp[i].br_startblock);
    -		if (i == 0)
    -			*mappedbnop = mappedbno;
    -		nmapped = (int)XFS_FSB_TO_BB(mp, mapp[i].br_blockcount);
    -		switch (caller) {
    -		case 0:
    -			bp = xfs_trans_get_buf(trans, mp->m_ddev_targp,
    -				mappedbno, nmapped, 0);
    -			error = bp ? XFS_BUF_GETERROR(bp) : XFS_ERROR(EIO);
    -			break;
    -		case 1:
    -		case 2:
    -			bp = NULL;
    -			error = xfs_trans_read_buf(mp, trans, mp->m_ddev_targp,
    -				mappedbno, nmapped, 0, &bp);
    -			break;
    -		case 3:
    -			xfs_baread(mp->m_ddev_targp, mappedbno, nmapped);
    -			error = 0;
    -			bp = NULL;
    -			break;
    -		}
    -		if (error) {
    -			if (bp)
    -				xfs_trans_brelse(trans, bp);
    -			goto exit1;
    -		}
    -		if (!bp)
    -			continue;
    -		if (caller == 1) {
    -			if (whichfork == XFS_ATTR_FORK) {
    -				XFS_BUF_SET_VTYPE_REF(bp, B_FS_ATTR_BTREE,
    -						XFS_ATTR_BTREE_REF);
    -			} else {
    -				XFS_BUF_SET_VTYPE_REF(bp, B_FS_DIR_BTREE,
    -						XFS_DIR_BTREE_REF);
    -			}
    -		}
    -		if (bplist) {
    -			bplist[nbplist++] = bp;
    -		}
    -	}
    -	/*
    -	 * Build a dabuf structure.
    -	 */
    -	if (bplist) {
    -		rbp = xfs_da_buf_make(nbplist, bplist, ra);
    -	} else if (bp)
    -		rbp = xfs_da_buf_make(1, &bp, ra);
    -	else
    -		rbp = NULL;
    -	/*
    -	 * For read_buf, check the magic number.
    -	 */
    -	if (caller == 1) {
    -		xfs_dir2_data_t		*data;
    -		xfs_dir2_free_t		*free;
    -		xfs_da_blkinfo_t	*info;
    -		uint			magic, magic1;
    -
    -		info = rbp->data;
    -		data = rbp->data;
    -		free = rbp->data;
    -		magic = be16_to_cpu(info->magic);
    -		magic1 = be32_to_cpu(data->hdr.magic);
    -		if (unlikely(
    -		    XFS_TEST_ERROR((magic != XFS_DA_NODE_MAGIC) &&
    -				   (magic != XFS_DIR_LEAF_MAGIC) &&
    -				   (magic != XFS_ATTR_LEAF_MAGIC) &&
    -				   (magic != XFS_DIR2_LEAF1_MAGIC) &&
    -				   (magic != XFS_DIR2_LEAFN_MAGIC) &&
    -				   (magic1 != XFS_DIR2_BLOCK_MAGIC) &&
    -				   (magic1 != XFS_DIR2_DATA_MAGIC) &&
    -				   (be32_to_cpu(free->hdr.magic) != XFS_DIR2_FREE_MAGIC),
    -				mp, XFS_ERRTAG_DA_READ_BUF,
    -				XFS_RANDOM_DA_READ_BUF))) {
    -			xfs_buftrace("DA READ ERROR", rbp->bps[0]);
    -			XFS_CORRUPTION_ERROR("xfs_da_do_buf(2)",
    -					     XFS_ERRLEVEL_LOW, mp, info);
    -			error = XFS_ERROR(EFSCORRUPTED);
    -			xfs_da_brelse(trans, rbp);
    -			nbplist = 0;
    -			goto exit1;
    -		}
    -	}
    -	if (bplist) {
    -		kmem_free(bplist, sizeof(*bplist) * nmap);
    -	}
    -	if (mapp != &map) {
    -		kmem_free(mapp, sizeof(*mapp) * nfsb);
    -	}
    -	if (bpp)
    -		*bpp = rbp;
    -	return 0;
    -exit1:
    -	if (bplist) {
    -		for (i = 0; i < nbplist; i++)
    -			xfs_trans_brelse(trans, bplist[i]);
    -		kmem_free(bplist, sizeof(*bplist) * nmap);
    -	}
    -exit0:
    -	if (mapp != &map)
    -		kmem_free(mapp, sizeof(*mapp) * nfsb);
    -	if (bpp)
    -		*bpp = NULL;
    -	return error;
    -}
    -
    -/*
    - * Get a buffer for the dir/attr block.
    - */
    -int
    -xfs_da_get_buf(
    -	xfs_trans_t	*trans,
    -	xfs_inode_t	*dp,
    -	xfs_dablk_t	bno,
    -	xfs_daddr_t		mappedbno,
    -	xfs_dabuf_t	**bpp,
    -	int		whichfork)
    -{
    -	return xfs_da_do_buf(trans, dp, bno, &mappedbno, bpp, whichfork, 0,
    -						 (inst_t *)__return_address);
    -}
    -
    -/*
    - * Get a buffer for the dir/attr block, fill in the contents.
    - */
    -int
    -xfs_da_read_buf(
    -	xfs_trans_t	*trans,
    -	xfs_inode_t	*dp,
    -	xfs_dablk_t	bno,
    -	xfs_daddr_t		mappedbno,
    -	xfs_dabuf_t	**bpp,
    -	int		whichfork)
    -{
    -	return xfs_da_do_buf(trans, dp, bno, &mappedbno, bpp, whichfork, 1,
    -		(inst_t *)__return_address);
    -}
    -
    -/*
    - * Readahead the dir/attr block.
    - */
    -xfs_daddr_t
    -xfs_da_reada_buf(
    -	xfs_trans_t	*trans,
    -	xfs_inode_t	*dp,
    -	xfs_dablk_t	bno,
    -	int		whichfork)
    -{
    -	xfs_daddr_t		rval;
    -
    -	rval = -1;
    -	if (xfs_da_do_buf(trans, dp, bno, &rval, NULL, whichfork, 3,
    -			(inst_t *)__return_address))
    -		return -1;
    -	else
    -		return rval;
    -}
    -
    -/*
    - * Calculate the number of bits needed to hold i different values.
    - */
    -uint
    -xfs_da_log2_roundup(uint i)
    -{
    -	uint rval;
    -
    -	for (rval = 0; rval < NBBY * sizeof(i); rval++) {
    -		if ((1 << rval) >= i)
    -			break;
    -	}
    -	return(rval);
    -}
    -
    -kmem_zone_t *xfs_da_state_zone;	/* anchor for state struct zone */
    -kmem_zone_t *xfs_dabuf_zone;		/* dabuf zone */
    -
    -/*
    - * Allocate a dir-state structure.
    - * We don't put them on the stack since they're large.
    - */
    -xfs_da_state_t *
    -xfs_da_state_alloc(void)
    -{
    -	return kmem_zone_zalloc(xfs_da_state_zone, KM_SLEEP);
    -}
    -
    -/*
    - * Kill the altpath contents of a da-state structure.
    - */
    -STATIC void
    -xfs_da_state_kill_altpath(xfs_da_state_t *state)
    -{
    -	int	i;
    -
    -	for (i = 0; i < state->altpath.active; i++) {
    -		if (state->altpath.blk[i].bp) {
    -			if (state->altpath.blk[i].bp != state->path.blk[i].bp)
    -				xfs_da_buf_done(state->altpath.blk[i].bp);
    -			state->altpath.blk[i].bp = NULL;
    -		}
    -	}
    -	state->altpath.active = 0;
    -}
    -
    -/*
    - * Free a da-state structure.
    - */
    -void
    -xfs_da_state_free(xfs_da_state_t *state)
    -{
    -	int	i;
    -
    -	xfs_da_state_kill_altpath(state);
    -	for (i = 0; i < state->path.active; i++) {
    -		if (state->path.blk[i].bp)
    -			xfs_da_buf_done(state->path.blk[i].bp);
    -	}
    -	if (state->extravalid && state->extrablk.bp)
    -		xfs_da_buf_done(state->extrablk.bp);
    -#ifdef DEBUG
    -	memset((char *)state, 0, sizeof(*state));
    -#endif /* DEBUG */
    -	kmem_zone_free(xfs_da_state_zone, state);
    -}
    -
    -#ifdef XFS_DABUF_DEBUG
    -xfs_dabuf_t	*xfs_dabuf_global_list;
    -lock_t		xfs_dabuf_global_lock;
    -#endif
    -
    -/*
    - * Create a dabuf.
    - */
    -/* ARGSUSED */
    -STATIC xfs_dabuf_t *
    -xfs_da_buf_make(int nbuf, xfs_buf_t **bps, inst_t *ra)
    -{
    -	xfs_buf_t	*bp;
    -	xfs_dabuf_t	*dabuf;
    -	int		i;
    -	int		off;
    -
    -	if (nbuf == 1)
    -		dabuf = kmem_zone_alloc(xfs_dabuf_zone, KM_SLEEP);
    -	else
    -		dabuf = kmem_alloc(XFS_DA_BUF_SIZE(nbuf), KM_SLEEP);
    -	dabuf->dirty = 0;
    -#ifdef XFS_DABUF_DEBUG
    -	dabuf->ra = ra;
    -	dabuf->target = XFS_BUF_TARGET(bps[0]);
    -	dabuf->blkno = XFS_BUF_ADDR(bps[0]);
    -#endif
    -	if (nbuf == 1) {
    -		dabuf->nbuf = 1;
    -		bp = bps[0];
    -		dabuf->bbcount = (short)BTOBB(XFS_BUF_COUNT(bp));
    -		dabuf->data = XFS_BUF_PTR(bp);
    -		dabuf->bps[0] = bp;
    -	} else {
    -		dabuf->nbuf = nbuf;
    -		for (i = 0, dabuf->bbcount = 0; i < nbuf; i++) {
    -			dabuf->bps[i] = bp = bps[i];
    -			dabuf->bbcount += BTOBB(XFS_BUF_COUNT(bp));
    -		}
    -		dabuf->data = kmem_alloc(BBTOB(dabuf->bbcount), KM_SLEEP);
    -		for (i = off = 0; i < nbuf; i++, off += XFS_BUF_COUNT(bp)) {
    -			bp = bps[i];
    -			memcpy((char *)dabuf->data + off, XFS_BUF_PTR(bp),
    -				XFS_BUF_COUNT(bp));
    -		}
    -	}
    -#ifdef XFS_DABUF_DEBUG
    -	{
    -		SPLDECL(s);
    -		xfs_dabuf_t	*p;
    -
    -		s = mutex_spinlock(&xfs_dabuf_global_lock);
    -		for (p = xfs_dabuf_global_list; p; p = p->next) {
    -			ASSERT(p->blkno != dabuf->blkno ||
    -			       p->target != dabuf->target);
    -		}
    -		dabuf->prev = NULL;
    -		if (xfs_dabuf_global_list)
    -			xfs_dabuf_global_list->prev = dabuf;
    -		dabuf->next = xfs_dabuf_global_list;
    -		xfs_dabuf_global_list = dabuf;
    -		mutex_spinunlock(&xfs_dabuf_global_lock, s);
    -	}
    -#endif
    -	return dabuf;
    -}
    -
    -/*
    - * Un-dirty a dabuf.
    - */
    -STATIC void
    -xfs_da_buf_clean(xfs_dabuf_t *dabuf)
    -{
    -	xfs_buf_t	*bp;
    -	int		i;
    -	int		off;
    -
    -	if (dabuf->dirty) {
    -		ASSERT(dabuf->nbuf > 1);
    -		dabuf->dirty = 0;
    -		for (i = off = 0; i < dabuf->nbuf;
    -				i++, off += XFS_BUF_COUNT(bp)) {
    -			bp = dabuf->bps[i];
    -			memcpy(XFS_BUF_PTR(bp), (char *)dabuf->data + off,
    -				XFS_BUF_COUNT(bp));
    -		}
    -	}
    -}
    -
    -/*
    - * Release a dabuf.
    - */
    -void
    -xfs_da_buf_done(xfs_dabuf_t *dabuf)
    -{
    -	ASSERT(dabuf);
    -	ASSERT(dabuf->nbuf && dabuf->data && dabuf->bbcount && dabuf->bps[0]);
    -	if (dabuf->dirty)
    -		xfs_da_buf_clean(dabuf);
    -	if (dabuf->nbuf > 1)
    -		kmem_free(dabuf->data, BBTOB(dabuf->bbcount));
    -#ifdef XFS_DABUF_DEBUG
    -	{
    -		SPLDECL(s);
    -
    -		s = mutex_spinlock(&xfs_dabuf_global_lock);
    -		if (dabuf->prev)
    -			dabuf->prev->next = dabuf->next;
    -		else
    -			xfs_dabuf_global_list = dabuf->next;
    -		if (dabuf->next)
    -			dabuf->next->prev = dabuf->prev;
    -		mutex_spinunlock(&xfs_dabuf_global_lock, s);
    -	}
    -	memset(dabuf, 0, XFS_DA_BUF_SIZE(dabuf->nbuf));
    -#endif
    -	if (dabuf->nbuf == 1)
    -		kmem_zone_free(xfs_dabuf_zone, dabuf);
    -	else
    -		kmem_free(dabuf, XFS_DA_BUF_SIZE(dabuf->nbuf));
    -}
    -
    -/*
    - * Log transaction from a dabuf.
    - */
    -void
    -xfs_da_log_buf(xfs_trans_t *tp, xfs_dabuf_t *dabuf, uint first, uint last)
    -{
    -	xfs_buf_t	*bp;
    -	uint		f;
    -	int		i;
    -	uint		l;
    -	int		off;
    -
    -	ASSERT(dabuf->nbuf && dabuf->data && dabuf->bbcount && dabuf->bps[0]);
    -	if (dabuf->nbuf == 1) {
    -		ASSERT(dabuf->data == (void *)XFS_BUF_PTR(dabuf->bps[0]));
    -		xfs_trans_log_buf(tp, dabuf->bps[0], first, last);
    -		return;
    -	}
    -	dabuf->dirty = 1;
    -	ASSERT(first <= last);
    -	for (i = off = 0; i < dabuf->nbuf; i++, off += XFS_BUF_COUNT(bp)) {
    -		bp = dabuf->bps[i];
    -		f = off;
    -		l = f + XFS_BUF_COUNT(bp) - 1;
    -		if (f < first)
    -			f = first;
    -		if (l > last)
    -			l = last;
    -		if (f <= l)
    -			xfs_trans_log_buf(tp, bp, f - off, l - off);
    -		/*
    -		 * B_DONE is set by xfs_trans_log buf.
    -		 * If we don't set it on a new buffer (get not read)
    -		 * then if we don't put anything in the buffer it won't
    -		 * be set, and at commit it it released into the cache,
    -		 * and then a read will fail.
    -		 */
    -		else if (!(XFS_BUF_ISDONE(bp)))
    -		  XFS_BUF_DONE(bp);
    -	}
    -	ASSERT(last < off);
    -}
    -
    -/*
    - * Release dabuf from a transaction.
    - * Have to free up the dabuf before the buffers are released,
    - * since the synchronization on the dabuf is really the lock on the buffer.
    - */
    -void
    -xfs_da_brelse(xfs_trans_t *tp, xfs_dabuf_t *dabuf)
    -{
    -	xfs_buf_t	*bp;
    -	xfs_buf_t	**bplist;
    -	int		i;
    -	int		nbuf;
    -
    -	ASSERT(dabuf->nbuf && dabuf->data && dabuf->bbcount && dabuf->bps[0]);
    -	if ((nbuf = dabuf->nbuf) == 1) {
    -		bplist = &bp;
    -		bp = dabuf->bps[0];
    -	} else {
    -		bplist = kmem_alloc(nbuf * sizeof(*bplist), KM_SLEEP);
    -		memcpy(bplist, dabuf->bps, nbuf * sizeof(*bplist));
    -	}
    -	xfs_da_buf_done(dabuf);
    -	for (i = 0; i < nbuf; i++)
    -		xfs_trans_brelse(tp, bplist[i]);
    -	if (bplist != &bp)
    -		kmem_free(bplist, nbuf * sizeof(*bplist));
    -}
    -
    -/*
    - * Invalidate dabuf from a transaction.
    - */
    -void
    -xfs_da_binval(xfs_trans_t *tp, xfs_dabuf_t *dabuf)
    -{
    -	xfs_buf_t	*bp;
    -	xfs_buf_t	**bplist;
    -	int		i;
    -	int		nbuf;
    -
    -	ASSERT(dabuf->nbuf && dabuf->data && dabuf->bbcount && dabuf->bps[0]);
    -	if ((nbuf = dabuf->nbuf) == 1) {
    -		bplist = &bp;
    -		bp = dabuf->bps[0];
    -	} else {
    -		bplist = kmem_alloc(nbuf * sizeof(*bplist), KM_SLEEP);
    -		memcpy(bplist, dabuf->bps, nbuf * sizeof(*bplist));
    -	}
    -	xfs_da_buf_done(dabuf);
    -	for (i = 0; i < nbuf; i++)
    -		xfs_trans_binval(tp, bplist[i]);
    -	if (bplist != &bp)
    -		kmem_free(bplist, nbuf * sizeof(*bplist));
    -}
    -
    -/*
    - * Get the first daddr from a dabuf.
    - */
    -xfs_daddr_t
    -xfs_da_blkno(xfs_dabuf_t *dabuf)
    -{
    -	ASSERT(dabuf->nbuf);
    -	ASSERT(dabuf->data);
    -	return XFS_BUF_ADDR(dabuf->bps[0]);
    -}
    diff --git a/sys/gnu/fs/xfs/xfs_da_btree.h b/sys/gnu/fs/xfs/xfs_da_btree.h
    deleted file mode 100644
    index 243a730d5ec..00000000000
    --- a/sys/gnu/fs/xfs/xfs_da_btree.h
    +++ /dev/null
    @@ -1,270 +0,0 @@
    -/*
    - * Copyright (c) 2000,2002,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_DA_BTREE_H__
    -#define	__XFS_DA_BTREE_H__
    -
    -struct xfs_buf;
    -struct xfs_bmap_free;
    -struct xfs_inode;
    -struct xfs_mount;
    -struct xfs_trans;
    -struct zone;
    -
    -/*========================================================================
    - * Directory Structure when greater than XFS_LBSIZE(mp) bytes.
    - *========================================================================*/
    -
    -/*
    - * This structure is common to both leaf nodes and non-leaf nodes in the Btree.
    - *
    - * Is is used to manage a doubly linked list of all blocks at the same
    - * level in the Btree, and to identify which type of block this is.
    - */
    -#define XFS_DA_NODE_MAGIC	0xfebe	/* magic number: non-leaf blocks */
    -#define XFS_DIR_LEAF_MAGIC	0xfeeb	/* magic number: directory leaf blks */
    -#define XFS_ATTR_LEAF_MAGIC	0xfbee	/* magic number: attribute leaf blks */
    -#define	XFS_DIR2_LEAF1_MAGIC	0xd2f1	/* magic number: v2 dirlf single blks */
    -#define	XFS_DIR2_LEAFN_MAGIC	0xd2ff	/* magic number: v2 dirlf multi blks */
    -
    -#define	XFS_DIRX_LEAF_MAGIC(mp)	\
    -	(XFS_DIR_IS_V1(mp) ? XFS_DIR_LEAF_MAGIC : XFS_DIR2_LEAFN_MAGIC)
    -
    -typedef struct xfs_da_blkinfo {
    -	__be32		forw;			/* previous block in list */
    -	__be32		back;			/* following block in list */
    -	__be16		magic;			/* validity check on block */
    -	__be16		pad;			/* unused */
    -} xfs_da_blkinfo_t;
    -
    -/*
    - * This is the structure of the root and intermediate nodes in the Btree.
    - * The leaf nodes are defined above.
    - *
    - * Entries are not packed.
    - *
    - * Since we have duplicate keys, use a binary search but always follow
    - * all match in the block, not just the first match found.
    - */
    -#define	XFS_DA_NODE_MAXDEPTH	5	/* max depth of Btree */
    -
    -typedef struct xfs_da_intnode {
    -	struct xfs_da_node_hdr {	/* constant-structure header block */
    -		xfs_da_blkinfo_t info;	/* block type, links, etc. */
    -		__be16	count;		/* count of active entries */
    -		__be16	level;		/* level above leaves (leaf == 0) */
    -	} hdr;
    -	struct xfs_da_node_entry {
    -		__be32	hashval;	/* hash value for this descendant */
    -		__be32	before;		/* Btree block before this key */
    -	} btree[1];			/* variable sized array of keys */
    -} xfs_da_intnode_t;
    -typedef struct xfs_da_node_hdr xfs_da_node_hdr_t;
    -typedef struct xfs_da_node_entry xfs_da_node_entry_t;
    -
    -#define XFS_DA_MAXHASH	((xfs_dahash_t)-1) /* largest valid hash value */
    -
    -#define	XFS_LBSIZE(mp)	(mp)->m_sb.sb_blocksize
    -#define	XFS_LBLOG(mp)	(mp)->m_sb.sb_blocklog
    -
    -#define	XFS_DA_MAKE_BNOENTRY(mp,bno,entry)	\
    -	(((bno) << (mp)->m_dircook_elog) | (entry))
    -#define	XFS_DA_MAKE_COOKIE(mp,bno,entry,hash)	\
    -	(((xfs_off_t)XFS_DA_MAKE_BNOENTRY(mp, bno, entry) << 32) | (hash))
    -#define	XFS_DA_COOKIE_HASH(mp,cookie)		((xfs_dahash_t)cookie)
    -#define	XFS_DA_COOKIE_BNO(mp,cookie)		\
    -	((((xfs_off_t)(cookie) >> 31) == -1LL ? \
    -		(xfs_dablk_t)0 : \
    -		(xfs_dablk_t)((xfs_off_t)(cookie) >> \
    -				((mp)->m_dircook_elog + 32))))
    -#define	XFS_DA_COOKIE_ENTRY(mp,cookie)		\
    -	((((xfs_off_t)(cookie) >> 31) == -1LL ?	\
    -		(xfs_dablk_t)0 : \
    -		(xfs_dablk_t)(((xfs_off_t)(cookie) >> 32) & \
    -				((1 << (mp)->m_dircook_elog) - 1))))
    -
    -
    -/*========================================================================
    - * Btree searching and modification structure definitions.
    - *========================================================================*/
    -
    -/*
    - * Structure to ease passing around component names.
    - */
    -typedef struct xfs_da_args {
    -	const uchar_t	*name;		/* string (maybe not NULL terminated) */
    -	int		namelen;	/* length of string (maybe no NULL) */
    -	uchar_t		*value;		/* set of bytes (maybe contain NULLs) */
    -	int		valuelen;	/* length of value */
    -	int		flags;		/* argument flags (eg: ATTR_NOCREATE) */
    -	xfs_dahash_t	hashval;	/* hash value of name */
    -	xfs_ino_t	inumber;	/* input/output inode number */
    -	struct xfs_inode *dp;		/* directory inode to manipulate */
    -	xfs_fsblock_t	*firstblock;	/* ptr to firstblock for bmap calls */
    -	struct xfs_bmap_free *flist;	/* ptr to freelist for bmap_finish */
    -	struct xfs_trans *trans;	/* current trans (changes over time) */
    -	xfs_extlen_t	total;		/* total blocks needed, for 1st bmap */
    -	int		whichfork;	/* data or attribute fork */
    -	xfs_dablk_t	blkno;		/* blkno of attr leaf of interest */
    -	int		index;		/* index of attr of interest in blk */
    -	xfs_dablk_t	rmtblkno;	/* remote attr value starting blkno */
    -	int		rmtblkcnt;	/* remote attr value block count */
    -	xfs_dablk_t	blkno2;		/* blkno of 2nd attr leaf of interest */
    -	int		index2;		/* index of 2nd attr in blk */
    -	xfs_dablk_t	rmtblkno2;	/* remote attr value starting blkno */
    -	int		rmtblkcnt2;	/* remote attr value block count */
    -	unsigned char	justcheck;	/* T/F: check for ok with no space */
    -	unsigned char	rename;		/* T/F: this is an atomic rename op */
    -	unsigned char	addname;	/* T/F: this is an add operation */
    -	unsigned char	oknoent;	/* T/F: ok to return ENOENT, else die */
    -} xfs_da_args_t;
    -
    -/*
    - * Structure to describe buffer(s) for a block.
    - * This is needed in the directory version 2 format case, when
    - * multiple non-contiguous fsblocks might be needed to cover one
    - * logical directory block.
    - * If the buffer count is 1 then the data pointer points to the
    - * same place as the b_addr field for the buffer, else to kmem_alloced memory.
    - */
    -typedef struct xfs_dabuf {
    -	int		nbuf;		/* number of buffer pointers present */
    -	short		dirty;		/* data needs to be copied back */
    -	short		bbcount;	/* how large is data in bbs */
    -	void		*data;		/* pointer for buffers' data */
    -#ifdef XFS_DABUF_DEBUG
    -	inst_t		*ra;		/* return address of caller to make */
    -	struct xfs_dabuf *next;		/* next in global chain */
    -	struct xfs_dabuf *prev;		/* previous in global chain */
    -	struct xfs_buftarg *target;	/* device for buffer */
    -	xfs_daddr_t	blkno;		/* daddr first in bps[0] */
    -#endif
    -	struct xfs_buf	*bps[1];	/* actually nbuf of these */
    -} xfs_dabuf_t;
    -#define	XFS_DA_BUF_SIZE(n)	\
    -	(sizeof(xfs_dabuf_t) + sizeof(struct xfs_buf *) * ((n) - 1))
    -
    -#ifdef XFS_DABUF_DEBUG
    -extern xfs_dabuf_t	*xfs_dabuf_global_list;
    -#endif
    -
    -/*
    - * Storage for holding state during Btree searches and split/join ops.
    - *
    - * Only need space for 5 intermediate nodes.  With a minimum of 62-way
    - * fanout to the Btree, we can support over 900 million directory blocks,
    - * which is slightly more than enough.
    - */
    -typedef struct xfs_da_state_blk {
    -	xfs_dabuf_t	*bp;		/* buffer containing block */
    -	xfs_dablk_t	blkno;		/* filesystem blkno of buffer */
    -	xfs_daddr_t	disk_blkno;	/* on-disk blkno (in BBs) of buffer */
    -	int		index;		/* relevant index into block */
    -	xfs_dahash_t	hashval;	/* last hash value in block */
    -	int		magic;		/* blk's magic number, ie: blk type */
    -} xfs_da_state_blk_t;
    -
    -typedef struct xfs_da_state_path {
    -	int			active;		/* number of active levels */
    -	xfs_da_state_blk_t	blk[XFS_DA_NODE_MAXDEPTH];
    -} xfs_da_state_path_t;
    -
    -typedef struct xfs_da_state {
    -	xfs_da_args_t		*args;		/* filename arguments */
    -	struct xfs_mount	*mp;		/* filesystem mount point */
    -	unsigned int		blocksize;	/* logical block size */
    -	unsigned int		node_ents;	/* how many entries in danode */
    -	xfs_da_state_path_t	path;		/* search/split paths */
    -	xfs_da_state_path_t	altpath;	/* alternate path for join */
    -	unsigned char		inleaf;		/* insert into 1->lf, 0->splf */
    -	unsigned char		extravalid;	/* T/F: extrablk is in use */
    -	unsigned char		extraafter;	/* T/F: extrablk is after new */
    -	xfs_da_state_blk_t	extrablk;	/* for double-splits on leafs */
    -						/* for dirv2 extrablk is data */
    -} xfs_da_state_t;
    -
    -/*
    - * Utility macros to aid in logging changed structure fields.
    - */
    -#define XFS_DA_LOGOFF(BASE, ADDR)	((char *)(ADDR) - (char *)(BASE))
    -#define XFS_DA_LOGRANGE(BASE, ADDR, SIZE)	\
    -		(uint)(XFS_DA_LOGOFF(BASE, ADDR)), \
    -		(uint)(XFS_DA_LOGOFF(BASE, ADDR)+(SIZE)-1)
    -
    -
    -#ifdef __KERNEL__
    -/*========================================================================
    - * Function prototypes for the kernel.
    - *========================================================================*/
    -
    -/*
    - * Routines used for growing the Btree.
    - */
    -int	xfs_da_node_create(xfs_da_args_t *args, xfs_dablk_t blkno, int level,
    -					 xfs_dabuf_t **bpp, int whichfork);
    -int	xfs_da_split(xfs_da_state_t *state);
    -
    -/*
    - * Routines used for shrinking the Btree.
    - */
    -int	xfs_da_join(xfs_da_state_t *state);
    -void	xfs_da_fixhashpath(xfs_da_state_t *state,
    -					  xfs_da_state_path_t *path_to_to_fix);
    -
    -/*
    - * Routines used for finding things in the Btree.
    - */
    -int	xfs_da_node_lookup_int(xfs_da_state_t *state, int *result);
    -int	xfs_da_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path,
    -					 int forward, int release, int *result);
    -/*
    - * Utility routines.
    - */
    -int	xfs_da_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk,
    -				       xfs_da_state_blk_t *new_blk);
    -
    -/*
    - * Utility routines.
    - */
    -int	xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno);
    -int	xfs_da_get_buf(struct xfs_trans *trans, struct xfs_inode *dp,
    -			      xfs_dablk_t bno, xfs_daddr_t mappedbno,
    -			      xfs_dabuf_t **bp, int whichfork);
    -int	xfs_da_read_buf(struct xfs_trans *trans, struct xfs_inode *dp,
    -			       xfs_dablk_t bno, xfs_daddr_t mappedbno,
    -			       xfs_dabuf_t **bpp, int whichfork);
    -xfs_daddr_t	xfs_da_reada_buf(struct xfs_trans *trans, struct xfs_inode *dp,
    -			xfs_dablk_t bno, int whichfork);
    -int	xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno,
    -					  xfs_dabuf_t *dead_buf);
    -
    -uint xfs_da_hashname(const uchar_t *name_string, int name_length);
    -uint xfs_da_log2_roundup(uint i);
    -xfs_da_state_t *xfs_da_state_alloc(void);
    -void xfs_da_state_free(xfs_da_state_t *state);
    -
    -void xfs_da_buf_done(xfs_dabuf_t *dabuf);
    -void xfs_da_log_buf(struct xfs_trans *tp, xfs_dabuf_t *dabuf, uint first,
    -			   uint last);
    -void xfs_da_brelse(struct xfs_trans *tp, xfs_dabuf_t *dabuf);
    -void xfs_da_binval(struct xfs_trans *tp, xfs_dabuf_t *dabuf);
    -xfs_daddr_t xfs_da_blkno(xfs_dabuf_t *dabuf);
    -
    -extern struct kmem_zone *xfs_da_state_zone;
    -#endif	/* __KERNEL__ */
    -
    -#endif	/* __XFS_DA_BTREE_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_dfrag.c b/sys/gnu/fs/xfs/xfs_dfrag.c
    deleted file mode 100644
    index 7b6b04ebcda..00000000000
    --- a/sys/gnu/fs/xfs/xfs_dfrag.c
    +++ /dev/null
    @@ -1,413 +0,0 @@
    -/*
    - * Copyright (c) 2000-2006 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_inode_item.h"
    -#include "xfs_bmap.h"
    -#include "xfs_btree.h"
    -#include "xfs_ialloc.h"
    -#include "xfs_itable.h"
    -#include "xfs_dfrag.h"
    -#include "xfs_error.h"
    -#include "xfs_mac.h"
    -#include "xfs_rw.h"
    -
    -#include 
    -#include 
    -
    -/*
    - * Syssgi interface for swapext
    - */
    -int
    -xfs_swapext(
    -	xfs_swapext_t	__user *sxu)
    -{
    -	xfs_swapext_t	*sxp;
    -	xfs_inode_t     *ip=NULL, *tip=NULL;
    -	xfs_mount_t     *mp;
    -	xfs_vnode_t	*vp = NULL, *tvp = NULL;
    -	struct vnode	*bvp, *btvp;
    -	int		error = 0;
    -
    -	sxp = kmem_alloc(sizeof(xfs_swapext_t), KM_MAYFAIL);
    -	if (!sxp) {
    -		error = XFS_ERROR(ENOMEM);
    -		goto error0;
    -	}
    -	struct thread	*td;
    -	struct cred	*cred;
    -
    -	td = curthread;
    -	cred = td->td_ucred;
    -
    -	if (copy_from_user(sxp, sxu, sizeof(xfs_swapext_t))) {
    -		error = XFS_ERROR(EFAULT);
    -		goto error0;
    -	}
    -
    -	/* Pull information for the target fd */
    -	if (fgetvp(td, (int)sxp->sx_fdtarget, CAP_READ | CAP_WRITE, &bvp)
    -	    != 0) {
    -		error = XFS_ERROR(EINVAL);
    -		goto error0;
    -	}
    -
    -	vp = VPTOXFSVP(bvp);
    -	ip = xfs_vtoi(vp);
    -	if (ip == NULL) {
    -		error = XFS_ERROR(EBADF);
    -		goto error0;
    -	}
    -
    -	if (fgetvp(td, (int)sxp->sx_fdtmp, CAP_READ | CAP_WRITE, &btvp) != 0) {
    -		error = XFS_ERROR(EINVAL);
    -		goto error0;
    -	}
    -
    -	tvp = VPTOXFSVP(btvp);
    -	tip = xfs_vtoi(tvp);
    -	if (tip == NULL) {
    -		error = XFS_ERROR(EBADF);
    -		goto error0;
    -	}
    -
    -	if (ip->i_mount != tip->i_mount) {
    -		error =  XFS_ERROR(EINVAL);
    -		goto error0;
    -	}
    -
    -	if (ip->i_ino == tip->i_ino) {
    -		error =  XFS_ERROR(EINVAL);
    -		goto error0;
    -	}
    -
    -	mp = ip->i_mount;
    -
    -	if (XFS_FORCED_SHUTDOWN(mp)) {
    -		error =  XFS_ERROR(EIO);
    -		goto error0;
    -	}
    -
    -	error = XFS_SWAP_EXTENTS(mp, &ip->i_iocore, &tip->i_iocore, sxp);
    -
    - error0:
    -#ifdef RMC
    -	if (fp != NULL)
    -		fput(fp);
    -	if (tfp != NULL)
    -		fput(tfp);
    -#endif
    -
    -	if (sxp != NULL)
    -		kmem_free(sxp, sizeof(xfs_swapext_t));
    -
    -	return error;
    -}
    -
    -int
    -xfs_swap_extents(
    -	xfs_inode_t	*ip,
    -	xfs_inode_t	*tip,
    -	xfs_swapext_t	*sxp)
    -{
    -	xfs_mount_t	*mp;
    -	xfs_inode_t	*ips[2];
    -	xfs_trans_t	*tp;
    -	xfs_bstat_t	*sbp = &sxp->sx_stat;
    -	xfs_vnode_t	*vp, *tvp;
    -	xfs_ifork_t	*tempifp, *ifp, *tifp;
    -	int		ilf_fields, tilf_fields;
    -	static uint	lock_flags = XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL;
    -	int		error = 0;
    -	int		aforkblks = 0;
    -	int		taforkblks = 0;
    -	__uint64_t	tmp;
    -	char		locked = 0;
    -
    -	mp = ip->i_mount;
    -
    -	tempifp = kmem_alloc(sizeof(xfs_ifork_t), KM_MAYFAIL);
    -	if (!tempifp) {
    -		error = XFS_ERROR(ENOMEM);
    -		goto error0;
    -	}
    -
    -	sbp = &sxp->sx_stat;
    -	vp = XFS_ITOV(ip);
    -	tvp = XFS_ITOV(tip);
    -
    -	/* Lock in i_ino order */
    -	if (ip->i_ino < tip->i_ino) {
    -		ips[0] = ip;
    -		ips[1] = tip;
    -	} else {
    -		ips[0] = tip;
    -		ips[1] = ip;
    -	}
    -
    -	xfs_lock_inodes(ips, 2, 0, lock_flags);
    -	locked = 1;
    -
    -	/* Check permissions */
    -	error = xfs_iaccess(ip, VWRITE, NULL);
    -	if (error)
    -		goto error0;
    -
    -	error = xfs_iaccess(tip, VWRITE, NULL);
    -	if (error)
    -		goto error0;
    -
    -	/* Verify that both files have the same format */
    -	if ((ip->i_d.di_mode & S_IFMT) != (tip->i_d.di_mode & S_IFMT)) {
    -		error = XFS_ERROR(EINVAL);
    -		goto error0;
    -	}
    -
    -	/* Verify both files are either real-time or non-realtime */
    -	if ((ip->i_d.di_flags & XFS_DIFLAG_REALTIME) !=
    -	    (tip->i_d.di_flags & XFS_DIFLAG_REALTIME)) {
    -		error = XFS_ERROR(EINVAL);
    -		goto error0;
    -	}
    -
    -	/* Should never get a local format */
    -	if (ip->i_d.di_format == XFS_DINODE_FMT_LOCAL ||
    -	    tip->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
    -		error = XFS_ERROR(EINVAL);
    -		goto error0;
    -	}
    -
    -	if (VN_CACHED(tvp) != 0) {
    -		xfs_inval_cached_trace(&tip->i_iocore, 0, -1, 0, -1);
    -		XVOP_FLUSHINVAL_PAGES(tvp, 0, -1, FI_REMAPF_LOCKED);
    -	}
    -
    -	/* Verify O_DIRECT for ftmp */
    -	if (VN_CACHED(tvp) != 0) {
    -		error = XFS_ERROR(EINVAL);
    -		goto error0;
    -	}
    -
    -	/* Verify all data are being swapped */
    -	if (sxp->sx_offset != 0 ||
    -	    sxp->sx_length != ip->i_d.di_size ||
    -	    sxp->sx_length != tip->i_d.di_size) {
    -		error = XFS_ERROR(EFAULT);
    -		goto error0;
    -	}
    -
    -	/*
    -	 * If the target has extended attributes, the tmp file
    -	 * must also in order to ensure the correct data fork
    -	 * format.
    -	 */
    -	if ( XFS_IFORK_Q(ip) != XFS_IFORK_Q(tip) ) {
    -		error = XFS_ERROR(EINVAL);
    -		goto error0;
    -	}
    -
    -	/*
    -	 * Compare the current change & modify times with that
    -	 * passed in.  If they differ, we abort this swap.
    -	 * This is the mechanism used to ensure the calling
    -	 * process that the file was not changed out from
    -	 * under it.
    -	 */
    -	if ((sbp->bs_ctime.tv_sec != ip->i_d.di_ctime.t_sec) ||
    -	    (sbp->bs_ctime.tv_nsec != ip->i_d.di_ctime.t_nsec) ||
    -	    (sbp->bs_mtime.tv_sec != ip->i_d.di_mtime.t_sec) ||
    -	    (sbp->bs_mtime.tv_nsec != ip->i_d.di_mtime.t_nsec)) {
    -		error = XFS_ERROR(EBUSY);
    -		goto error0;
    -	}
    -
    -	/* We need to fail if the file is memory mapped.  Once we have tossed
    -	 * all existing pages, the page fault will have no option
    -	 * but to go to the filesystem for pages. By making the page fault call
    -	 * VOP_READ (or write in the case of autogrow) they block on the iolock
    -	 * until we have switched the extents.
    -	 */
    -	if (VN_MAPPED(vp)) {
    -		error = XFS_ERROR(EBUSY);
    -		goto error0;
    -	}
    -
    -	xfs_iunlock(ip, XFS_ILOCK_EXCL);
    -	xfs_iunlock(tip, XFS_ILOCK_EXCL);
    -
    -	/*
    -	 * There is a race condition here since we gave up the
    -	 * ilock.  However, the data fork will not change since
    -	 * we have the iolock (locked for truncation too) so we
    -	 * are safe.  We don't really care if non-io related
    -	 * fields change.
    -	 */
    -
    -	XVOP_TOSS_PAGES(vp, 0, -1, FI_REMAPF);
    -
    -	tp = xfs_trans_alloc(mp, XFS_TRANS_SWAPEXT);
    -	if ((error = xfs_trans_reserve(tp, 0,
    -				     XFS_ICHANGE_LOG_RES(mp), 0,
    -				     0, 0))) {
    -		xfs_iunlock(ip,  XFS_IOLOCK_EXCL);
    -		xfs_iunlock(tip, XFS_IOLOCK_EXCL);
    -		xfs_trans_cancel(tp, 0);
    -		locked = 0;
    -		goto error0;
    -	}
    -	xfs_lock_inodes(ips, 2, 0, XFS_ILOCK_EXCL);
    -
    -	/*
    -	 * Count the number of extended attribute blocks
    -	 */
    -	if ( ((XFS_IFORK_Q(ip) != 0) && (ip->i_d.di_anextents > 0)) &&
    -	     (ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)) {
    -		error = xfs_bmap_count_blocks(tp, ip, XFS_ATTR_FORK, &aforkblks);
    -		if (error) {
    -			xfs_trans_cancel(tp, 0);
    -			goto error0;
    -		}
    -	}
    -	if ( ((XFS_IFORK_Q(tip) != 0) && (tip->i_d.di_anextents > 0)) &&
    -	     (tip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)) {
    -		error = xfs_bmap_count_blocks(tp, tip, XFS_ATTR_FORK,
    -			&taforkblks);
    -		if (error) {
    -			xfs_trans_cancel(tp, 0);
    -			goto error0;
    -		}
    -	}
    -
    -	/*
    -	 * Swap the data forks of the inodes
    -	 */
    -	ifp = &ip->i_df;
    -	tifp = &tip->i_df;
    -	*tempifp = *ifp;	/* struct copy */
    -	*ifp = *tifp;		/* struct copy */
    -	*tifp = *tempifp;	/* struct copy */
    -
    -	/*
    -	 * Fix the on-disk inode values
    -	 */
    -	tmp = (__uint64_t)ip->i_d.di_nblocks;
    -	ip->i_d.di_nblocks = tip->i_d.di_nblocks - taforkblks + aforkblks;
    -	tip->i_d.di_nblocks = tmp + taforkblks - aforkblks;
    -
    -	tmp = (__uint64_t) ip->i_d.di_nextents;
    -	ip->i_d.di_nextents = tip->i_d.di_nextents;
    -	tip->i_d.di_nextents = tmp;
    -
    -	tmp = (__uint64_t) ip->i_d.di_format;
    -	ip->i_d.di_format = tip->i_d.di_format;
    -	tip->i_d.di_format = tmp;
    -
    -	ilf_fields = XFS_ILOG_CORE;
    -
    -	switch(ip->i_d.di_format) {
    -	case XFS_DINODE_FMT_EXTENTS:
    -		/* If the extents fit in the inode, fix the
    -		 * pointer.  Otherwise it's already NULL or
    -		 * pointing to the extent.
    -		 */
    -		if (ip->i_d.di_nextents <= XFS_INLINE_EXTS) {
    -			ifp->if_u1.if_extents =
    -				ifp->if_u2.if_inline_ext;
    -		}
    -		ilf_fields |= XFS_ILOG_DEXT;
    -		break;
    -	case XFS_DINODE_FMT_BTREE:
    -		ilf_fields |= XFS_ILOG_DBROOT;
    -		break;
    -	}
    -
    -	tilf_fields = XFS_ILOG_CORE;
    -
    -	switch(tip->i_d.di_format) {
    -	case XFS_DINODE_FMT_EXTENTS:
    -		/* If the extents fit in the inode, fix the
    -		 * pointer.  Otherwise it's already NULL or
    -		 * pointing to the extent.
    -		 */
    -		if (tip->i_d.di_nextents <= XFS_INLINE_EXTS) {
    -			tifp->if_u1.if_extents =
    -				tifp->if_u2.if_inline_ext;
    -		}
    -		tilf_fields |= XFS_ILOG_DEXT;
    -		break;
    -	case XFS_DINODE_FMT_BTREE:
    -		tilf_fields |= XFS_ILOG_DBROOT;
    -		break;
    -	}
    -
    -#ifdef XXXKAN /* Not necessary, vnodes are vrefed already by fgetvp */
    -	/*
    -	 * Increment vnode ref counts since xfs_trans_commit &
    -	 * xfs_trans_cancel will both unlock the inodes and
    -	 * decrement the associated ref counts.
    -	 */
    -	VN_HOLD(vp);
    -	VN_HOLD(tvp);
    -#endif
    -
    -	xfs_trans_ijoin(tp, ip, lock_flags);
    -	xfs_trans_ijoin(tp, tip, lock_flags);
    -
    -	xfs_trans_log_inode(tp, ip,  ilf_fields);
    -	xfs_trans_log_inode(tp, tip, tilf_fields);
    -
    -	/*
    -	 * If this is a synchronous mount, make sure that the
    -	 * transaction goes to disk before returning to the user.
    -	 */
    -	if (mp->m_flags & XFS_MOUNT_WSYNC) {
    -		xfs_trans_set_sync(tp);
    -	}
    -
    -	error = xfs_trans_commit(tp, XFS_TRANS_SWAPEXT, NULL);
    -
    -	locked = 0;
    -
    - error0:
    -	if (locked) {
    -		xfs_iunlock(ip,  lock_flags);
    -		xfs_iunlock(tip, lock_flags);
    -	}
    -	if (tempifp != NULL)
    -		kmem_free(tempifp, sizeof(xfs_ifork_t));
    -	return error;
    -}
    diff --git a/sys/gnu/fs/xfs/xfs_dfrag.h b/sys/gnu/fs/xfs/xfs_dfrag.h
    deleted file mode 100644
    index da178205be6..00000000000
    --- a/sys/gnu/fs/xfs/xfs_dfrag.h
    +++ /dev/null
    @@ -1,56 +0,0 @@
    -/*
    - * Copyright (c) 2000,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_DFRAG_H__
    -#define	__XFS_DFRAG_H__
    -
    -/*
    - * Structure passed to xfs_swapext
    - */
    -
    -typedef struct xfs_swapext
    -{
    -	__int64_t	sx_version;	/* version */
    -	__int64_t	sx_fdtarget;	/* fd of target file */
    -	__int64_t	sx_fdtmp;	/* fd of tmp file */
    -	xfs_off_t	sx_offset;	/* offset into file */
    -	xfs_off_t	sx_length;	/* leng from offset */
    -	char		sx_pad[16];	/* pad space, unused */
    -	xfs_bstat_t	sx_stat;	/* stat of target b4 copy */
    -} xfs_swapext_t;
    -
    -/*
    - * Version flag
    - */
    -#define XFS_SX_VERSION		0
    -
    -#ifdef __KERNEL__
    -/*
    - * Prototypes for visible xfs_dfrag.c routines.
    - */
    -
    -/*
    - * Syscall interface for xfs_swapext
    - */
    -int	xfs_swapext(struct xfs_swapext __user *sx);
    -
    -int	xfs_swap_extents(struct xfs_inode *ip, struct xfs_inode *tip,
    -		struct xfs_swapext *sxp);
    -
    -#endif	/* __KERNEL__ */
    -
    -#endif	/* __XFS_DFRAG_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_dinode.h b/sys/gnu/fs/xfs/xfs_dinode.h
    deleted file mode 100644
    index 79d0d9e1fba..00000000000
    --- a/sys/gnu/fs/xfs/xfs_dinode.h
    +++ /dev/null
    @@ -1,281 +0,0 @@
    -/*
    - * Copyright (c) 2000,2002,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_DINODE_H__
    -#define	__XFS_DINODE_H__
    -
    -struct xfs_buf;
    -struct xfs_mount;
    -
    -#define	XFS_DINODE_VERSION_1	1
    -#define	XFS_DINODE_VERSION_2	2
    -#define XFS_DINODE_GOOD_VERSION(v)	\
    -	(((v) == XFS_DINODE_VERSION_1 || (v) == XFS_DINODE_VERSION_2))
    -#define	XFS_DINODE_MAGIC	0x494e	/* 'IN' */
    -
    -/*
    - * Disk inode structure.
    - * This is just the header; the inode is expanded to fill a variable size
    - * with the last field expanding.  It is split into the core and "other"
    - * because we only need the core part in the in-core inode.
    - */
    -typedef struct xfs_timestamp {
    -	__int32_t	t_sec;		/* timestamp seconds */
    -	__int32_t	t_nsec;		/* timestamp nanoseconds */
    -} xfs_timestamp_t;
    -
    -/*
    - * Note: Coordinate changes to this structure with the XFS_DI_* #defines
    - * below and the offsets table in xfs_ialloc_log_di().
    - */
    -typedef struct xfs_dinode_core
    -{
    -	__uint16_t	di_magic;	/* inode magic # = XFS_DINODE_MAGIC */
    -	__uint16_t	di_mode;	/* mode and type of file */
    -	__int8_t	di_version;	/* inode version */
    -	__int8_t	di_format;	/* format of di_c data */
    -	__uint16_t	di_onlink;	/* old number of links to file */
    -	__uint32_t	di_uid;		/* owner's user id */
    -	__uint32_t	di_gid;		/* owner's group id */
    -	__uint32_t	di_nlink;	/* number of links to file */
    -	__uint16_t	di_projid;	/* owner's project id */
    -	__uint8_t	di_pad[8];	/* unused, zeroed space */
    -	__uint16_t	di_flushiter;	/* incremented on flush */
    -	xfs_timestamp_t	di_atime;	/* time last accessed */
    -	xfs_timestamp_t	di_mtime;	/* time last modified */
    -	xfs_timestamp_t	di_ctime;	/* time created/inode modified */
    -	xfs_fsize_t	di_size;	/* number of bytes in file */
    -	xfs_drfsbno_t	di_nblocks;	/* # of direct & btree blocks used */
    -	xfs_extlen_t	di_extsize;	/* basic/minimum extent size for file */
    -	xfs_extnum_t	di_nextents;	/* number of extents in data fork */
    -	xfs_aextnum_t	di_anextents;	/* number of extents in attribute fork*/
    -	__uint8_t	di_forkoff;	/* attr fork offs, <<3 for 64b align */
    -	__int8_t	di_aformat;	/* format of attr fork's data */
    -	__uint32_t	di_dmevmask;	/* DMIG event mask */
    -	__uint16_t	di_dmstate;	/* DMIG state info */
    -	__uint16_t	di_flags;	/* random flags, XFS_DIFLAG_... */
    -	__uint32_t	di_gen;		/* generation number */
    -} xfs_dinode_core_t;
    -
    -#define DI_MAX_FLUSH 0xffff
    -
    -typedef struct xfs_dinode
    -{
    -	xfs_dinode_core_t	di_core;
    -	/*
    -	 * In adding anything between the core and the union, be
    -	 * sure to update the macros like XFS_LITINO below and
    -	 * XFS_BMAP_RBLOCK_DSIZE in xfs_bmap_btree.h.
    -	 */
    -	xfs_agino_t		di_next_unlinked;/* agi unlinked list ptr */
    -	union {
    -		xfs_bmdr_block_t di_bmbt;	/* btree root block */
    -		xfs_bmbt_rec_32_t di_bmx[1];	/* extent list */
    -		xfs_dir_shortform_t di_dirsf;	/* shortform directory */
    -		xfs_dir2_sf_t	di_dir2sf;	/* shortform directory v2 */
    -		char		di_c[1];	/* local contents */
    -		xfs_dev_t	di_dev;		/* device for S_IFCHR/S_IFBLK */
    -		uuid_t		di_muuid;	/* mount point value */
    -		char		di_symlink[1];	/* local symbolic link */
    -	}		di_u;
    -	union {
    -		xfs_bmdr_block_t di_abmbt;	/* btree root block */
    -		xfs_bmbt_rec_32_t di_abmx[1];	/* extent list */
    -		xfs_attr_shortform_t di_attrsf;	/* shortform attribute list */
    -	}		di_a;
    -} xfs_dinode_t;
    -
    -/*
    - * The 32 bit link count in the inode theoretically maxes out at UINT_MAX.
    - * Since the pathconf interface is signed, we use 2^31 - 1 instead.
    - * The old inode format had a 16 bit link count, so its maximum is USHRT_MAX.
    - */
    -#define	XFS_MAXLINK		((1U << 31) - 1U)
    -#define	XFS_MAXLINK_1		65535U
    -
    -/*
    - * Bit names for logging disk inodes only
    - */
    -#define	XFS_DI_MAGIC		0x0000001
    -#define	XFS_DI_MODE		0x0000002
    -#define	XFS_DI_VERSION		0x0000004
    -#define	XFS_DI_FORMAT		0x0000008
    -#define	XFS_DI_ONLINK		0x0000010
    -#define	XFS_DI_UID		0x0000020
    -#define	XFS_DI_GID		0x0000040
    -#define	XFS_DI_NLINK		0x0000080
    -#define	XFS_DI_PROJID		0x0000100
    -#define	XFS_DI_PAD		0x0000200
    -#define	XFS_DI_ATIME		0x0000400
    -#define	XFS_DI_MTIME		0x0000800
    -#define	XFS_DI_CTIME		0x0001000
    -#define	XFS_DI_SIZE		0x0002000
    -#define	XFS_DI_NBLOCKS		0x0004000
    -#define	XFS_DI_EXTSIZE		0x0008000
    -#define	XFS_DI_NEXTENTS		0x0010000
    -#define	XFS_DI_NAEXTENTS	0x0020000
    -#define	XFS_DI_FORKOFF		0x0040000
    -#define	XFS_DI_AFORMAT		0x0080000
    -#define	XFS_DI_DMEVMASK		0x0100000
    -#define	XFS_DI_DMSTATE		0x0200000
    -#define	XFS_DI_FLAGS		0x0400000
    -#define	XFS_DI_GEN		0x0800000
    -#define	XFS_DI_NEXT_UNLINKED	0x1000000
    -#define	XFS_DI_U		0x2000000
    -#define	XFS_DI_A		0x4000000
    -#define	XFS_DI_NUM_BITS		27
    -#define	XFS_DI_ALL_BITS		((1 << XFS_DI_NUM_BITS) - 1)
    -#define	XFS_DI_CORE_BITS	(XFS_DI_ALL_BITS & ~(XFS_DI_U|XFS_DI_A))
    -
    -/*
    - * Values for di_format
    - */
    -typedef enum xfs_dinode_fmt
    -{
    -	XFS_DINODE_FMT_DEV,		/* CHR, BLK: di_dev */
    -	XFS_DINODE_FMT_LOCAL,		/* DIR, REG: di_c */
    -					/* LNK: di_symlink */
    -	XFS_DINODE_FMT_EXTENTS,		/* DIR, REG, LNK: di_bmx */
    -	XFS_DINODE_FMT_BTREE,		/* DIR, REG, LNK: di_bmbt */
    -	XFS_DINODE_FMT_UUID		/* MNT: di_uuid */
    -} xfs_dinode_fmt_t;
    -
    -/*
    - * Inode minimum and maximum sizes.
    - */
    -#define	XFS_DINODE_MIN_LOG	8
    -#define	XFS_DINODE_MAX_LOG	11
    -#define	XFS_DINODE_MIN_SIZE	(1 << XFS_DINODE_MIN_LOG)
    -#define	XFS_DINODE_MAX_SIZE	(1 << XFS_DINODE_MAX_LOG)
    -
    -/*
    - * Inode size for given fs.
    - */
    -#define	XFS_LITINO(mp)	((mp)->m_litino)
    -#define	XFS_BROOT_SIZE_ADJ	\
    -	(sizeof(xfs_bmbt_block_t) - sizeof(xfs_bmdr_block_t))
    -
    -/*
    - * Inode data & attribute fork sizes, per inode.
    - */
    -#define XFS_CFORK_Q(dcp)                    ((dcp)->di_forkoff != 0)
    -#define	XFS_CFORK_Q_DISK(dcp)		    ((dcp)->di_forkoff != 0)
    -
    -#define XFS_CFORK_BOFF(dcp)                 ((int)((dcp)->di_forkoff << 3))
    -#define	XFS_CFORK_BOFF_DISK(dcp) \
    -	((int)(INT_GET((dcp)->di_forkoff, ARCH_CONVERT) << 3))
    -
    -#define	XFS_CFORK_DSIZE_DISK(dcp,mp) \
    -	(XFS_CFORK_Q_DISK(dcp) ? XFS_CFORK_BOFF_DISK(dcp) : XFS_LITINO(mp))
    -#define XFS_CFORK_DSIZE(dcp,mp) \
    -	(XFS_CFORK_Q(dcp) ? XFS_CFORK_BOFF(dcp) : XFS_LITINO(mp))
    -
    -#define	XFS_CFORK_ASIZE_DISK(dcp,mp) \
    -	(XFS_CFORK_Q_DISK(dcp) ? XFS_LITINO(mp) - XFS_CFORK_BOFF_DISK(dcp) : 0)
    -#define XFS_CFORK_ASIZE(dcp,mp) \
    -	(XFS_CFORK_Q(dcp) ? XFS_LITINO(mp) - XFS_CFORK_BOFF(dcp) : 0)
    -
    -#define	XFS_CFORK_SIZE_DISK(dcp,mp,w) \
    -	((w) == XFS_DATA_FORK ? \
    -		XFS_CFORK_DSIZE_DISK(dcp, mp) : \
    -	 	XFS_CFORK_ASIZE_DISK(dcp, mp))
    -#define XFS_CFORK_SIZE(dcp,mp,w) \
    -	((w) == XFS_DATA_FORK ? \
    -		XFS_CFORK_DSIZE(dcp, mp) : XFS_CFORK_ASIZE(dcp, mp))
    -
    -#define XFS_DFORK_DSIZE(dip,mp) \
    -	XFS_CFORK_DSIZE_DISK(&(dip)->di_core, mp)
    -#define XFS_DFORK_DSIZE_HOST(dip,mp) \
    -	XFS_CFORK_DSIZE(&(dip)->di_core, mp)
    -#define XFS_DFORK_ASIZE(dip,mp) \
    -	XFS_CFORK_ASIZE_DISK(&(dip)->di_core, mp)
    -#define XFS_DFORK_ASIZE_HOST(dip,mp) \
    -	XFS_CFORK_ASIZE(&(dip)->di_core, mp)
    -#define	XFS_DFORK_SIZE(dip,mp,w) \
    -	XFS_CFORK_SIZE_DISK(&(dip)->di_core, mp, w)
    -#define	XFS_DFORK_SIZE_HOST(dip,mp,w) \
    -	XFS_CFORK_SIZE(&(dip)->di_core, mp, w)
    -
    -#define	XFS_DFORK_Q(dip)                    XFS_CFORK_Q_DISK(&(dip)->di_core)
    -#define	XFS_DFORK_BOFF(dip)		    XFS_CFORK_BOFF_DISK(&(dip)->di_core)
    -#define	XFS_DFORK_DPTR(dip)		    ((dip)->di_u.di_c)
    -#define	XFS_DFORK_APTR(dip)	\
    -	((dip)->di_u.di_c + XFS_DFORK_BOFF(dip))
    -#define	XFS_DFORK_PTR(dip,w)	\
    -	((w) == XFS_DATA_FORK ? XFS_DFORK_DPTR(dip) : XFS_DFORK_APTR(dip))
    -#define	XFS_CFORK_FORMAT(dcp,w)	\
    -	((w) == XFS_DATA_FORK ? (dcp)->di_format : (dcp)->di_aformat)
    -#define	XFS_CFORK_FMT_SET(dcp,w,n) \
    -	((w) == XFS_DATA_FORK ? \
    -		((dcp)->di_format = (n)) : ((dcp)->di_aformat = (n)))
    -#define	XFS_DFORK_FORMAT(dip,w) XFS_CFORK_FORMAT(&(dip)->di_core, w)
    -
    -#define	XFS_CFORK_NEXTENTS_DISK(dcp,w) \
    -	((w) == XFS_DATA_FORK ? \
    -	 	INT_GET((dcp)->di_nextents, ARCH_CONVERT) : \
    -	 	INT_GET((dcp)->di_anextents, ARCH_CONVERT))
    -#define XFS_CFORK_NEXTENTS(dcp,w) \
    -	((w) == XFS_DATA_FORK ? (dcp)->di_nextents : (dcp)->di_anextents)
    -#define	XFS_DFORK_NEXTENTS(dip,w) XFS_CFORK_NEXTENTS_DISK(&(dip)->di_core, w)
    -#define	XFS_DFORK_NEXTENTS_HOST(dip,w) XFS_CFORK_NEXTENTS(&(dip)->di_core, w)
    -
    -#define	XFS_CFORK_NEXT_SET(dcp,w,n) \
    -	((w) == XFS_DATA_FORK ? \
    -		((dcp)->di_nextents = (n)) : ((dcp)->di_anextents = (n)))
    -
    -#define	XFS_BUF_TO_DINODE(bp)	((xfs_dinode_t *)XFS_BUF_PTR(bp))
    -
    -/*
    - * Values for di_flags
    - * There should be a one-to-one correspondence between these flags and the
    - * XFS_XFLAG_s.
    - */
    -#define XFS_DIFLAG_REALTIME_BIT  0	/* file's blocks come from rt area */
    -#define XFS_DIFLAG_PREALLOC_BIT  1	/* file space has been preallocated */
    -#define XFS_DIFLAG_NEWRTBM_BIT   2	/* for rtbitmap inode, new format */
    -#define XFS_DIFLAG_IMMUTABLE_BIT 3	/* inode is immutable */
    -#define XFS_DIFLAG_APPEND_BIT    4	/* inode is append-only */
    -#define XFS_DIFLAG_SYNC_BIT      5	/* inode is written synchronously */
    -#define XFS_DIFLAG_NOATIME_BIT   6	/* do not update atime */
    -#define XFS_DIFLAG_NODUMP_BIT    7	/* do not dump */
    -#define XFS_DIFLAG_RTINHERIT_BIT 8	/* create with realtime bit set */
    -#define XFS_DIFLAG_PROJINHERIT_BIT   9	/* create with parents projid */
    -#define XFS_DIFLAG_NOSYMLINKS_BIT   10	/* disallow symlink creation */
    -#define XFS_DIFLAG_EXTSIZE_BIT      11	/* inode extent size allocator hint */
    -#define XFS_DIFLAG_EXTSZINHERIT_BIT 12	/* inherit inode extent size */
    -#define XFS_DIFLAG_REALTIME      (1 << XFS_DIFLAG_REALTIME_BIT)
    -#define XFS_DIFLAG_PREALLOC      (1 << XFS_DIFLAG_PREALLOC_BIT)
    -#define XFS_DIFLAG_NEWRTBM       (1 << XFS_DIFLAG_NEWRTBM_BIT)
    -#define XFS_DIFLAG_IMMUTABLE     (1 << XFS_DIFLAG_IMMUTABLE_BIT)
    -#define XFS_DIFLAG_APPEND        (1 << XFS_DIFLAG_APPEND_BIT)
    -#define XFS_DIFLAG_SYNC          (1 << XFS_DIFLAG_SYNC_BIT)
    -#define XFS_DIFLAG_NOATIME       (1 << XFS_DIFLAG_NOATIME_BIT)
    -#define XFS_DIFLAG_NODUMP        (1 << XFS_DIFLAG_NODUMP_BIT)
    -#define XFS_DIFLAG_RTINHERIT     (1 << XFS_DIFLAG_RTINHERIT_BIT)
    -#define XFS_DIFLAG_PROJINHERIT   (1 << XFS_DIFLAG_PROJINHERIT_BIT)
    -#define XFS_DIFLAG_NOSYMLINKS    (1 << XFS_DIFLAG_NOSYMLINKS_BIT)
    -#define XFS_DIFLAG_EXTSIZE       (1 << XFS_DIFLAG_EXTSIZE_BIT)
    -#define XFS_DIFLAG_EXTSZINHERIT  (1 << XFS_DIFLAG_EXTSZINHERIT_BIT)
    -
    -#define XFS_DIFLAG_ANY \
    -	(XFS_DIFLAG_REALTIME | XFS_DIFLAG_PREALLOC | XFS_DIFLAG_NEWRTBM | \
    -	 XFS_DIFLAG_IMMUTABLE | XFS_DIFLAG_APPEND | XFS_DIFLAG_SYNC | \
    -	 XFS_DIFLAG_NOATIME | XFS_DIFLAG_NODUMP | XFS_DIFLAG_RTINHERIT | \
    -	 XFS_DIFLAG_PROJINHERIT | XFS_DIFLAG_NOSYMLINKS | XFS_DIFLAG_EXTSIZE | \
    -	 XFS_DIFLAG_EXTSZINHERIT)
    -
    -#endif	/* __XFS_DINODE_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_dir.c b/sys/gnu/fs/xfs/xfs_dir.c
    deleted file mode 100644
    index 7df722e6013..00000000000
    --- a/sys/gnu/fs/xfs/xfs_dir.c
    +++ /dev/null
    @@ -1,1218 +0,0 @@
    -/*
    - * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_da_btree.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_alloc.h"
    -#include "xfs_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_bmap.h"
    -#include "xfs_dir_leaf.h"
    -#include "xfs_error.h"
    -
    -/*
    - * xfs_dir.c
    - *
    - * Provide the external interfaces to manage directories.
    - */
    -
    -/*========================================================================
    - * Function prototypes for the kernel.
    - *========================================================================*/
    -
    -/*
    - * Functions for the dirops interfaces.
    - */
    -static void	xfs_dir_mount(struct xfs_mount *mp);
    -
    -static int	xfs_dir_isempty(struct xfs_inode *dp);
    -
    -static int	xfs_dir_init(struct xfs_trans *trans,
    -			     struct xfs_inode *dir,
    -			     struct xfs_inode *parent_dir);
    -
    -static int	xfs_dir_createname(struct xfs_trans *trans,
    -				   struct xfs_inode *dp,
    -				   char *name_string,
    -				   int name_len,
    -				   xfs_ino_t inode_number,
    -				   xfs_fsblock_t *firstblock,
    -				   xfs_bmap_free_t *flist,
    -				   xfs_extlen_t total);
    -
    -static int	xfs_dir_lookup(struct xfs_trans *tp,
    -			       struct xfs_inode *dp,
    -			       char *name_string,
    -			       int name_length,
    -			       xfs_ino_t *inode_number);
    -
    -static int	xfs_dir_removename(struct xfs_trans *trans,
    -				   struct xfs_inode *dp,
    -				   char *name_string,
    -				   int name_length,
    -				   xfs_ino_t ino,
    -				   xfs_fsblock_t *firstblock,
    -				   xfs_bmap_free_t *flist,
    -				   xfs_extlen_t total);
    -
    -static int	xfs_dir_getdents(struct xfs_trans *tp,
    -				 struct xfs_inode *dp,
    -				 struct uio *uiop,
    -				 int *eofp);
    -
    -static int	xfs_dir_replace(struct xfs_trans *tp,
    -				struct xfs_inode *dp,
    -				char *name_string,
    -				int name_length,
    -				xfs_ino_t inode_number,
    -				xfs_fsblock_t *firstblock,
    -				xfs_bmap_free_t *flist,
    -				xfs_extlen_t total);
    -
    -static int	xfs_dir_canenter(struct xfs_trans *tp,
    -				 struct xfs_inode *dp,
    -				 char *name_string,
    -				 int name_length);
    -
    -static int	xfs_dir_shortform_validate_ondisk(xfs_mount_t *mp,
    -						  xfs_dinode_t *dip);
    -
    -xfs_dirops_t xfsv1_dirops = {
    -	.xd_mount			= xfs_dir_mount,
    -	.xd_isempty			= xfs_dir_isempty,
    -	.xd_init			= xfs_dir_init,
    -	.xd_createname			= xfs_dir_createname,
    -	.xd_lookup			= xfs_dir_lookup,
    -	.xd_removename			= xfs_dir_removename,
    -	.xd_getdents			= xfs_dir_getdents,
    -	.xd_replace			= xfs_dir_replace,
    -	.xd_canenter			= xfs_dir_canenter,
    -	.xd_shortform_validate_ondisk	= xfs_dir_shortform_validate_ondisk,
    -	.xd_shortform_to_single		= xfs_dir_shortform_to_leaf,
    -};
    -
    -/*
    - * Internal routines when dirsize == XFS_LBSIZE(mp).
    - */
    -STATIC int xfs_dir_leaf_lookup(xfs_da_args_t *args);
    -STATIC int xfs_dir_leaf_removename(xfs_da_args_t *args, int *number_entries,
    -						 int *total_namebytes);
    -STATIC int xfs_dir_leaf_getdents(xfs_trans_t *trans, xfs_inode_t *dp,
    -					     uio_t *uio, int *eofp,
    -					     xfs_dirent_t *dbp,
    -					     xfs_dir_put_t put);
    -STATIC int xfs_dir_leaf_replace(xfs_da_args_t *args);
    -
    -/*
    - * Internal routines when dirsize > XFS_LBSIZE(mp).
    - */
    -STATIC int xfs_dir_node_addname(xfs_da_args_t *args);
    -STATIC int xfs_dir_node_lookup(xfs_da_args_t *args);
    -STATIC int xfs_dir_node_removename(xfs_da_args_t *args);
    -STATIC int xfs_dir_node_getdents(xfs_trans_t *trans, xfs_inode_t *dp,
    -					     uio_t *uio, int *eofp,
    -					     xfs_dirent_t *dbp,
    -					     xfs_dir_put_t put);
    -STATIC int xfs_dir_node_replace(xfs_da_args_t *args);
    -
    -#if defined(XFS_DIR_TRACE)
    -ktrace_t *xfs_dir_trace_buf;
    -#endif
    -
    -
    -/*========================================================================
    - * Overall external interface routines.
    - *========================================================================*/
    -
    -xfs_dahash_t	xfs_dir_hash_dot, xfs_dir_hash_dotdot;
    -
    -/*
    - * One-time startup routine called from xfs_init().
    - */
    -void
    -xfs_dir_startup(void)
    -{
    -	xfs_dir_hash_dot = xfs_da_hashname(".", 1);
    -	xfs_dir_hash_dotdot = xfs_da_hashname("..", 2);
    -}
    -
    -/*
    - * Initialize directory-related fields in the mount structure.
    - */
    -static void
    -xfs_dir_mount(xfs_mount_t *mp)
    -{
    -	uint shortcount, leafcount, count;
    -
    -	mp->m_dirversion = 1;
    -	if (!(mp->m_flags & XFS_MOUNT_ATTR2)) {
    -		shortcount = (mp->m_attroffset -
    -				(uint)sizeof(xfs_dir_sf_hdr_t)) /
    -				 (uint)sizeof(xfs_dir_sf_entry_t);
    -		leafcount = (XFS_LBSIZE(mp) -
    -				(uint)sizeof(xfs_dir_leaf_hdr_t)) /
    -				 ((uint)sizeof(xfs_dir_leaf_entry_t) +
    -				  (uint)sizeof(xfs_dir_leaf_name_t));
    -	} else {
    -		shortcount = (XFS_BMDR_SPACE_CALC(MINABTPTRS) -
    -			      (uint)sizeof(xfs_dir_sf_hdr_t)) /
    -			       (uint)sizeof(xfs_dir_sf_entry_t);
    -		leafcount = (XFS_LBSIZE(mp) -
    -			    (uint)sizeof(xfs_dir_leaf_hdr_t)) /
    -			     ((uint)sizeof(xfs_dir_leaf_entry_t) +
    -			      (uint)sizeof(xfs_dir_leaf_name_t));
    -	}
    -	count = shortcount > leafcount ? shortcount : leafcount;
    -	mp->m_dircook_elog = xfs_da_log2_roundup(count + 1);
    -	ASSERT(mp->m_dircook_elog <= mp->m_sb.sb_blocklog);
    -	mp->m_dir_node_ents = mp->m_attr_node_ents =
    -		(XFS_LBSIZE(mp) - (uint)sizeof(xfs_da_node_hdr_t)) /
    -		(uint)sizeof(xfs_da_node_entry_t);
    -	mp->m_dir_magicpct = (XFS_LBSIZE(mp) * 37) / 100;
    -	mp->m_dirblksize = mp->m_sb.sb_blocksize;
    -	mp->m_dirblkfsbs = 1;
    -}
    -
    -/*
    - * Return 1 if directory contains only "." and "..".
    - */
    -static int
    -xfs_dir_isempty(xfs_inode_t *dp)
    -{
    -	xfs_dir_sf_hdr_t *hdr;
    -
    -	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
    -	if (dp->i_d.di_size == 0)
    -		return(1);
    -	if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp))
    -		return(0);
    -	hdr = (xfs_dir_sf_hdr_t *)dp->i_df.if_u1.if_data;
    -	return(hdr->count == 0);
    -}
    -
    -/*
    - * Initialize a directory with its "." and ".." entries.
    - */
    -static int
    -xfs_dir_init(xfs_trans_t *trans, xfs_inode_t *dir, xfs_inode_t *parent_dir)
    -{
    -	xfs_da_args_t args;
    -	int error;
    -
    -	memset((char *)&args, 0, sizeof(args));
    -	args.dp = dir;
    -	args.trans = trans;
    -
    -	ASSERT((dir->i_d.di_mode & S_IFMT) == S_IFDIR);
    -	if ((error = xfs_dir_ino_validate(trans->t_mountp, parent_dir->i_ino)))
    -		return error;
    -
    -	return(xfs_dir_shortform_create(&args, parent_dir->i_ino));
    -}
    -
    -/*
    - * Generic handler routine to add a name to a directory.
    - * Transitions directory from shortform to Btree as necessary.
    - */
    -static int							/* error */
    -xfs_dir_createname(xfs_trans_t *trans, xfs_inode_t *dp, char *name,
    -		   int namelen, xfs_ino_t inum, xfs_fsblock_t *firstblock,
    -		   xfs_bmap_free_t *flist, xfs_extlen_t total)
    -{
    -	xfs_da_args_t args;
    -	int retval, newsize, done;
    -
    -	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
    -
    -	if ((retval = xfs_dir_ino_validate(trans->t_mountp, inum)))
    -		return (retval);
    -
    -	XFS_STATS_INC(xs_dir_create);
    -	/*
    -	 * Fill in the arg structure for this request.
    -	 */
    -	args.name = name;
    -	args.namelen = namelen;
    -	args.hashval = xfs_da_hashname(name, namelen);
    -	args.inumber = inum;
    -	args.dp = dp;
    -	args.firstblock = firstblock;
    -	args.flist = flist;
    -	args.total = total;
    -	args.whichfork = XFS_DATA_FORK;
    -	args.trans = trans;
    -	args.justcheck = 0;
    -	args.addname = args.oknoent = 1;
    -
    -	/*
    -	 * Decide on what work routines to call based on the inode size.
    -	 */
    -	done = 0;
    -	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
    -		newsize = XFS_DIR_SF_ENTSIZE_BYNAME(args.namelen);
    -		if ((dp->i_d.di_size + newsize) <= XFS_IFORK_DSIZE(dp)) {
    -			retval = xfs_dir_shortform_addname(&args);
    -			done = 1;
    -		} else {
    -			if (total == 0)
    -				return XFS_ERROR(ENOSPC);
    -			retval = xfs_dir_shortform_to_leaf(&args);
    -			done = retval != 0;
    -		}
    -	}
    -	if (!done && xfs_bmap_one_block(dp, XFS_DATA_FORK)) {
    -		retval = xfs_dir_leaf_addname(&args);
    -		done = retval != ENOSPC;
    -		if (!done) {
    -			if (total == 0)
    -				return XFS_ERROR(ENOSPC);
    -			retval = xfs_dir_leaf_to_node(&args);
    -			done = retval != 0;
    -		}
    -	}
    -	if (!done) {
    -		retval = xfs_dir_node_addname(&args);
    -	}
    -	return(retval);
    -}
    -
    -/*
    - * Generic handler routine to check if a name can be added to a directory,
    - * without adding any blocks to the directory.
    - */
    -static int							/* error */
    -xfs_dir_canenter(xfs_trans_t *trans, xfs_inode_t *dp, char *name, int namelen)
    -{
    -	xfs_da_args_t args;
    -	int retval, newsize;
    -
    -	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
    -	/*
    -	 * Fill in the arg structure for this request.
    -	 */
    -	args.name = name;
    -	args.namelen = namelen;
    -	args.hashval = xfs_da_hashname(name, namelen);
    -	args.inumber = 0;
    -	args.dp = dp;
    -	args.firstblock = NULL;
    -	args.flist = NULL;
    -	args.total = 0;
    -	args.whichfork = XFS_DATA_FORK;
    -	args.trans = trans;
    -	args.justcheck = args.addname = args.oknoent = 1;
    -
    -	/*
    -	 * Decide on what work routines to call based on the inode size.
    -	 */
    -	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
    -		newsize = XFS_DIR_SF_ENTSIZE_BYNAME(args.namelen);
    -		if ((dp->i_d.di_size + newsize) <= XFS_IFORK_DSIZE(dp))
    -			retval = 0;
    -		else
    -			retval = XFS_ERROR(ENOSPC);
    -	} else if (xfs_bmap_one_block(dp, XFS_DATA_FORK)) {
    -		retval = xfs_dir_leaf_addname(&args);
    -	} else {
    -		retval = xfs_dir_node_addname(&args);
    -	}
    -	return(retval);
    -}
    -
    -/*
    - * Generic handler routine to remove a name from a directory.
    - * Transitions directory from Btree to shortform as necessary.
    - */
    -static int							/* error */
    -xfs_dir_removename(xfs_trans_t *trans, xfs_inode_t *dp, char *name,
    -		   int namelen, xfs_ino_t ino, xfs_fsblock_t *firstblock,
    -		   xfs_bmap_free_t *flist, xfs_extlen_t total)
    -{
    -	xfs_da_args_t args;
    -	int count, totallen, newsize, retval;
    -
    -	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
    -	XFS_STATS_INC(xs_dir_remove);
    -	/*
    -	 * Fill in the arg structure for this request.
    -	 */
    -	args.name = name;
    -	args.namelen = namelen;
    -	args.hashval = xfs_da_hashname(name, namelen);
    -	args.inumber = ino;
    -	args.dp = dp;
    -	args.firstblock = firstblock;
    -	args.flist = flist;
    -	args.total = total;
    -	args.whichfork = XFS_DATA_FORK;
    -	args.trans = trans;
    -	args.justcheck = args.addname = args.oknoent = 0;
    -
    -	/*
    -	 * Decide on what work routines to call based on the inode size.
    -	 */
    -	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
    -		retval = xfs_dir_shortform_removename(&args);
    -	} else if (xfs_bmap_one_block(dp, XFS_DATA_FORK)) {
    -		count = totallen = 0;
    -		retval = xfs_dir_leaf_removename(&args, &count, &totallen);
    -		if (retval == 0) {
    -			newsize = XFS_DIR_SF_ALLFIT(count, totallen);
    -			if (newsize <= XFS_IFORK_DSIZE(dp)) {
    -				retval = xfs_dir_leaf_to_shortform(&args);
    -			}
    -		}
    -	} else {
    -		retval = xfs_dir_node_removename(&args);
    -	}
    -	return(retval);
    -}
    -
    -static int							/* error */
    -xfs_dir_lookup(xfs_trans_t *trans, xfs_inode_t *dp, char *name, int namelen,
    -				   xfs_ino_t *inum)
    -{
    -	xfs_da_args_t args;
    -	int retval;
    -
    -	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
    -
    -	XFS_STATS_INC(xs_dir_lookup);
    -	/*
    -	 * Fill in the arg structure for this request.
    -	 */
    -	args.name = name;
    -	args.namelen = namelen;
    -	args.hashval = xfs_da_hashname(name, namelen);
    -	args.inumber = 0;
    -	args.dp = dp;
    -	args.firstblock = NULL;
    -	args.flist = NULL;
    -	args.total = 0;
    -	args.whichfork = XFS_DATA_FORK;
    -	args.trans = trans;
    -	args.justcheck = args.addname = 0;
    -	args.oknoent = 1;
    -
    -	/*
    -	 * Decide on what work routines to call based on the inode size.
    -	 */
    -	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
    -		retval = xfs_dir_shortform_lookup(&args);
    -	} else if (xfs_bmap_one_block(dp, XFS_DATA_FORK)) {
    -		retval = xfs_dir_leaf_lookup(&args);
    -	} else {
    -		retval = xfs_dir_node_lookup(&args);
    -	}
    -	if (retval == EEXIST)
    -		retval = 0;
    -	*inum = args.inumber;
    -	return(retval);
    -}
    -
    -/*
    - * Implement readdir.
    - */
    -static int							/* error */
    -xfs_dir_getdents(xfs_trans_t *trans, xfs_inode_t *dp, uio_t *uio, int *eofp)
    -{
    -	xfs_dirent_t *dbp;
    -	int  alignment, retval;
    -	xfs_dir_put_t put;
    -
    -	XFS_STATS_INC(xs_dir_getdents);
    -	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
    -
    -	/*
    -	 * If our caller has given us a single contiguous memory buffer,
    -	 * just work directly within that buffer.  If it's in user memory,
    -	 * lock it down first.
    -	 */
    -	alignment = sizeof(xfs_off_t) - 1;
    -	if ((uio->uio_iovcnt == 1) &&
    -	    (((__psint_t)uio->uio_iov[0].iov_base & alignment) == 0) &&
    -	    ((uio->uio_iov[0].iov_len & alignment) == 0)) {
    -		dbp = NULL;
    -		put = xfs_dir_put_dirent64_direct;
    -	} else {
    -		dbp = kmem_alloc(sizeof(*dbp) + MAXNAMELEN, KM_SLEEP);
    -		put = xfs_dir_put_dirent64_uio;
    -	}
    -
    -	/*
    -	 * Decide on what work routines to call based on the inode size.
    -	 */
    -	*eofp = 0;
    -
    -	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
    -		retval = xfs_dir_shortform_getdents(dp, uio, eofp, dbp, put);
    -	} else if (xfs_bmap_one_block(dp, XFS_DATA_FORK)) {
    -		retval = xfs_dir_leaf_getdents(trans, dp, uio, eofp, dbp, put);
    -	} else {
    -		retval = xfs_dir_node_getdents(trans, dp, uio, eofp, dbp, put);
    -	}
    -	if (dbp != NULL)
    -		kmem_free(dbp, sizeof(*dbp) + MAXNAMELEN);
    -
    -	return(retval);
    -}
    -
    -static int							/* error */
    -xfs_dir_replace(xfs_trans_t *trans, xfs_inode_t *dp, char *name, int namelen,
    -				    xfs_ino_t inum, xfs_fsblock_t *firstblock,
    -				    xfs_bmap_free_t *flist, xfs_extlen_t total)
    -{
    -	xfs_da_args_t args;
    -	int retval;
    -
    -	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
    -
    -	if ((retval = xfs_dir_ino_validate(trans->t_mountp, inum)))
    -		return retval;
    -
    -	/*
    -	 * Fill in the arg structure for this request.
    -	 */
    -	args.name = name;
    -	args.namelen = namelen;
    -	args.hashval = xfs_da_hashname(name, namelen);
    -	args.inumber = inum;
    -	args.dp = dp;
    -	args.firstblock = firstblock;
    -	args.flist = flist;
    -	args.total = total;
    -	args.whichfork = XFS_DATA_FORK;
    -	args.trans = trans;
    -	args.justcheck = args.addname = args.oknoent = 0;
    -
    -	/*
    -	 * Decide on what work routines to call based on the inode size.
    -	 */
    -	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
    -		retval = xfs_dir_shortform_replace(&args);
    -	} else if (xfs_bmap_one_block(dp, XFS_DATA_FORK)) {
    -		retval = xfs_dir_leaf_replace(&args);
    -	} else {
    -		retval = xfs_dir_node_replace(&args);
    -	}
    -
    -	return(retval);
    -}
    -
    -static int
    -xfs_dir_shortform_validate_ondisk(xfs_mount_t *mp, xfs_dinode_t *dp)
    -{
    -	xfs_ino_t		ino;
    -	int			namelen_sum;
    -	int			count;
    -	xfs_dir_shortform_t	*sf;
    -	xfs_dir_sf_entry_t	*sfe;
    -	int			i;
    -
    -
    -
    -	if ((INT_GET(dp->di_core.di_mode, ARCH_CONVERT) & S_IFMT) != S_IFDIR) {
    -		return 0;
    -	}
    -	if (INT_GET(dp->di_core.di_format, ARCH_CONVERT) != XFS_DINODE_FMT_LOCAL) {
    -		return 0;
    -	}
    -	if (INT_GET(dp->di_core.di_size, ARCH_CONVERT) < sizeof(sf->hdr)) {
    -		xfs_fs_cmn_err(CE_WARN, mp, "Invalid shortform size: dp 0x%p",
    -			dp);
    -		return 1;
    -	}
    -	sf = (xfs_dir_shortform_t *)(&dp->di_u.di_dirsf);
    -	ino = XFS_GET_DIR_INO8(sf->hdr.parent);
    -	if (xfs_dir_ino_validate(mp, ino))
    -		return 1;
    -
    -	count =	sf->hdr.count;
    -	if ((count < 0) || ((count * 10) > XFS_LITINO(mp))) {
    -		xfs_fs_cmn_err(CE_WARN, mp,
    -			"Invalid shortform count: dp 0x%p", dp);
    -		return(1);
    -	}
    -
    -	if (count == 0) {
    -		return 0;
    -	}
    -
    -	namelen_sum = 0;
    -	sfe = &sf->list[0];
    -	for (i = sf->hdr.count - 1; i >= 0; i--) {
    -		ino = XFS_GET_DIR_INO8(sfe->inumber);
    -		xfs_dir_ino_validate(mp, ino);
    -		if (sfe->namelen >= XFS_LITINO(mp)) {
    -			xfs_fs_cmn_err(CE_WARN, mp,
    -				"Invalid shortform namelen: dp 0x%p", dp);
    -			return 1;
    -		}
    -		namelen_sum += sfe->namelen;
    -		sfe = XFS_DIR_SF_NEXTENTRY(sfe);
    -	}
    -	if (namelen_sum >= XFS_LITINO(mp)) {
    -		xfs_fs_cmn_err(CE_WARN, mp,
    -			"Invalid shortform namelen: dp 0x%p", dp);
    -		return 1;
    -	}
    -
    -	return 0;
    -}
    -
    -/*========================================================================
    - * External routines when dirsize == XFS_LBSIZE(dp->i_mount).
    - *========================================================================*/
    -
    -/*
    - * Add a name to the leaf directory structure
    - * This is the external routine.
    - */
    -int
    -xfs_dir_leaf_addname(xfs_da_args_t *args)
    -{
    -	int index, retval;
    -	xfs_dabuf_t *bp;
    -
    -	retval = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp,
    -					      XFS_DATA_FORK);
    -	if (retval)
    -		return(retval);
    -	ASSERT(bp != NULL);
    -
    -	retval = xfs_dir_leaf_lookup_int(bp, args, &index);
    -	if (retval == ENOENT)
    -		retval = xfs_dir_leaf_add(bp, args, index);
    -	xfs_da_buf_done(bp);
    -	return(retval);
    -}
    -
    -/*
    - * Remove a name from the leaf directory structure
    - * This is the external routine.
    - */
    -STATIC int
    -xfs_dir_leaf_removename(xfs_da_args_t *args, int *count, int *totallen)
    -{
    -	xfs_dir_leafblock_t *leaf;
    -	int index, retval;
    -	xfs_dabuf_t *bp;
    -
    -	retval = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp,
    -					      XFS_DATA_FORK);
    -	if (retval)
    -		return(retval);
    -	ASSERT(bp != NULL);
    -	leaf = bp->data;
    -	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
    -	retval = xfs_dir_leaf_lookup_int(bp, args, &index);
    -	if (retval == EEXIST) {
    -		(void)xfs_dir_leaf_remove(args->trans, bp, index);
    -		*count = INT_GET(leaf->hdr.count, ARCH_CONVERT);
    -		*totallen = INT_GET(leaf->hdr.namebytes, ARCH_CONVERT);
    -		retval = 0;
    -	}
    -	xfs_da_buf_done(bp);
    -	return(retval);
    -}
    -
    -/*
    - * Look up a name in a leaf directory structure.
    - * This is the external routine.
    - */
    -STATIC int
    -xfs_dir_leaf_lookup(xfs_da_args_t *args)
    -{
    -	int index, retval;
    -	xfs_dabuf_t *bp;
    -
    -	retval = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp,
    -					      XFS_DATA_FORK);
    -	if (retval)
    -		return(retval);
    -	ASSERT(bp != NULL);
    -	retval = xfs_dir_leaf_lookup_int(bp, args, &index);
    -	xfs_da_brelse(args->trans, bp);
    -	return(retval);
    -}
    -
    -/*
    - * Copy out directory entries for getdents(), for leaf directories.
    - */
    -STATIC int
    -xfs_dir_leaf_getdents(xfs_trans_t *trans, xfs_inode_t *dp, uio_t *uio,
    -				  int *eofp, xfs_dirent_t *dbp, xfs_dir_put_t put)
    -{
    -	xfs_dabuf_t *bp;
    -	int retval, eob;
    -
    -	retval = xfs_da_read_buf(dp->i_transp, dp, 0, -1, &bp, XFS_DATA_FORK);
    -	if (retval)
    -		return(retval);
    -	ASSERT(bp != NULL);
    -	retval = xfs_dir_leaf_getdents_int(bp, dp, 0, uio, &eob, dbp, put, -1);
    -	xfs_da_brelse(trans, bp);
    -	*eofp = (eob == 0);
    -	return(retval);
    -}
    -
    -/*
    - * Look up a name in a leaf directory structure, replace the inode number.
    - * This is the external routine.
    - */
    -STATIC int
    -xfs_dir_leaf_replace(xfs_da_args_t *args)
    -{
    -	int index, retval;
    -	xfs_dabuf_t *bp;
    -	xfs_ino_t inum;
    -	xfs_dir_leafblock_t *leaf;
    -	xfs_dir_leaf_entry_t *entry;
    -	xfs_dir_leaf_name_t *namest;
    -
    -	inum = args->inumber;
    -	retval = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp,
    -					      XFS_DATA_FORK);
    -	if (retval)
    -		return(retval);
    -	ASSERT(bp != NULL);
    -	retval = xfs_dir_leaf_lookup_int(bp, args, &index);
    -	if (retval == EEXIST) {
    -		leaf = bp->data;
    -		entry = &leaf->entries[index];
    -		namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT));
    -		/* XXX - replace assert? */
    -		XFS_DIR_SF_PUT_DIRINO(&inum, &namest->inumber);
    -		xfs_da_log_buf(args->trans, bp,
    -		    XFS_DA_LOGRANGE(leaf, namest, sizeof(namest->inumber)));
    -		xfs_da_buf_done(bp);
    -		retval = 0;
    -	} else
    -		xfs_da_brelse(args->trans, bp);
    -	return(retval);
    -}
    -
    -
    -/*========================================================================
    - * External routines when dirsize > XFS_LBSIZE(mp).
    - *========================================================================*/
    -
    -/*
    - * Add a name to a Btree-format directory.
    - *
    - * This will involve walking down the Btree, and may involve splitting
    - * leaf nodes and even splitting intermediate nodes up to and including
    - * the root node (a special case of an intermediate node).
    - */
    -STATIC int
    -xfs_dir_node_addname(xfs_da_args_t *args)
    -{
    -	xfs_da_state_t *state;
    -	xfs_da_state_blk_t *blk;
    -	int retval, error;
    -
    -	/*
    -	 * Fill in bucket of arguments/results/context to carry around.
    -	 */
    -	state = xfs_da_state_alloc();
    -	state->args = args;
    -	state->mp = args->dp->i_mount;
    -	state->blocksize = state->mp->m_sb.sb_blocksize;
    -	state->node_ents = state->mp->m_dir_node_ents;
    -
    -	/*
    -	 * Search to see if name already exists, and get back a pointer
    -	 * to where it should go.
    -	 */
    -	error = xfs_da_node_lookup_int(state, &retval);
    -	if (error)
    -		retval = error;
    -	if (retval != ENOENT)
    -		goto error;
    -	blk = &state->path.blk[ state->path.active-1 ];
    -	ASSERT(blk->magic == XFS_DIR_LEAF_MAGIC);
    -	retval = xfs_dir_leaf_add(blk->bp, args, blk->index);
    -	if (retval == 0) {
    -		/*
    -		 * Addition succeeded, update Btree hashvals.
    -		 */
    -		if (!args->justcheck)
    -			xfs_da_fixhashpath(state, &state->path);
    -	} else {
    -		/*
    -		 * Addition failed, split as many Btree elements as required.
    -		 */
    -		if (args->total == 0) {
    -			ASSERT(retval == ENOSPC);
    -			goto error;
    -		}
    -		retval = xfs_da_split(state);
    -	}
    -error:
    -	xfs_da_state_free(state);
    -
    -	return(retval);
    -}
    -
    -/*
    - * Remove a name from a B-tree directory.
    - *
    - * This will involve walking down the Btree, and may involve joining
    - * leaf nodes and even joining intermediate nodes up to and including
    - * the root node (a special case of an intermediate node).
    - */
    -STATIC int
    -xfs_dir_node_removename(xfs_da_args_t *args)
    -{
    -	xfs_da_state_t *state;
    -	xfs_da_state_blk_t *blk;
    -	int retval, error;
    -
    -	state = xfs_da_state_alloc();
    -	state->args = args;
    -	state->mp = args->dp->i_mount;
    -	state->blocksize = state->mp->m_sb.sb_blocksize;
    -	state->node_ents = state->mp->m_dir_node_ents;
    -
    -	/*
    -	 * Search to see if name exists, and get back a pointer to it.
    -	 */
    -	error = xfs_da_node_lookup_int(state, &retval);
    -	if (error)
    -		retval = error;
    -	if (retval != EEXIST) {
    -		xfs_da_state_free(state);
    -		return(retval);
    -	}
    -
    -	/*
    -	 * Remove the name and update the hashvals in the tree.
    -	 */
    -	blk = &state->path.blk[ state->path.active-1 ];
    -	ASSERT(blk->magic == XFS_DIR_LEAF_MAGIC);
    -	retval = xfs_dir_leaf_remove(args->trans, blk->bp, blk->index);
    -	xfs_da_fixhashpath(state, &state->path);
    -
    -	/*
    -	 * Check to see if the tree needs to be collapsed.
    -	 */
    -	error = 0;
    -	if (retval) {
    -		error = xfs_da_join(state);
    -	}
    -
    -	xfs_da_state_free(state);
    -	if (error)
    -		return(error);
    -	return(0);
    -}
    -
    -/*
    - * Look up a filename in a int directory.
    - * Use an internal routine to actually do all the work.
    - */
    -STATIC int
    -xfs_dir_node_lookup(xfs_da_args_t *args)
    -{
    -	xfs_da_state_t *state;
    -	int retval, error, i;
    -
    -	state = xfs_da_state_alloc();
    -	state->args = args;
    -	state->mp = args->dp->i_mount;
    -	state->blocksize = state->mp->m_sb.sb_blocksize;
    -	state->node_ents = state->mp->m_dir_node_ents;
    -
    -	/*
    -	 * Search to see if name exists,
    -	 * and get back a pointer to it.
    -	 */
    -	error = xfs_da_node_lookup_int(state, &retval);
    -	if (error) {
    -		retval = error;
    -	}
    -
    -	/*
    -	 * If not in a transaction, we have to release all the buffers.
    -	 */
    -	for (i = 0; i < state->path.active; i++) {
    -		xfs_da_brelse(args->trans, state->path.blk[i].bp);
    -		state->path.blk[i].bp = NULL;
    -	}
    -
    -	xfs_da_state_free(state);
    -	return(retval);
    -}
    -
    -STATIC int
    -xfs_dir_node_getdents(xfs_trans_t *trans, xfs_inode_t *dp, uio_t *uio,
    -				  int *eofp, xfs_dirent_t *dbp, xfs_dir_put_t put)
    -{
    -	xfs_da_intnode_t *node;
    -	xfs_da_node_entry_t *btree;
    -	xfs_dir_leafblock_t *leaf = NULL;
    -	xfs_dablk_t bno, nextbno;
    -	xfs_dahash_t cookhash;
    -	xfs_mount_t *mp;
    -	int error, eob, i;
    -	xfs_dabuf_t *bp;
    -	xfs_daddr_t nextda;
    -
    -	/*
    -	 * Pick up our context.
    -	 */
    -	mp = dp->i_mount;
    -	bp = NULL;
    -	bno = XFS_DA_COOKIE_BNO(mp, uio->uio_offset);
    -	cookhash = XFS_DA_COOKIE_HASH(mp, uio->uio_offset);
    -
    -	xfs_dir_trace_g_du("node: start", dp, uio);
    -
    -	/*
    -	 * Re-find our place, even if we're confused about what our place is.
    -	 *
    -	 * First we check the block number from the magic cookie, it is a
    -	 * cache of where we ended last time.  If we find a leaf block, and
    -	 * the starting hashval in that block is less than our desired
    -	 * hashval, then we run with it.
    -	 */
    -	if (bno > 0) {
    -		error = xfs_da_read_buf(trans, dp, bno, -2, &bp, XFS_DATA_FORK);
    -		if ((error != 0) && (error != EFSCORRUPTED))
    -			return(error);
    -		if (bp)
    -			leaf = bp->data;
    -		if (bp && be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR_LEAF_MAGIC) {
    -			xfs_dir_trace_g_dub("node: block not a leaf",
    -						   dp, uio, bno);
    -			xfs_da_brelse(trans, bp);
    -			bp = NULL;
    -		}
    -		if (bp && INT_GET(leaf->entries[0].hashval, ARCH_CONVERT) > cookhash) {
    -			xfs_dir_trace_g_dub("node: leaf hash too large",
    -						   dp, uio, bno);
    -			xfs_da_brelse(trans, bp);
    -			bp = NULL;
    -		}
    -		if (bp &&
    -		    cookhash > INT_GET(leaf->entries[INT_GET(leaf->hdr.count, ARCH_CONVERT) - 1].hashval, ARCH_CONVERT)) {
    -			xfs_dir_trace_g_dub("node: leaf hash too small",
    -						   dp, uio, bno);
    -			xfs_da_brelse(trans, bp);
    -			bp = NULL;
    -		}
    -	}
    -
    -	/*
    -	 * If we did not find a leaf block from the blockno in the cookie,
    -	 * or we there was no blockno in the cookie (eg: first time thru),
    -	 * the we start at the top of the Btree and re-find our hashval.
    -	 */
    -	if (bp == NULL) {
    -		xfs_dir_trace_g_du("node: start at root" , dp, uio);
    -		bno = 0;
    -		for (;;) {
    -			error = xfs_da_read_buf(trans, dp, bno, -1, &bp,
    -						       XFS_DATA_FORK);
    -			if (error)
    -				return(error);
    -			if (bp == NULL)
    -				return(XFS_ERROR(EFSCORRUPTED));
    -			node = bp->data;
    -			if (be16_to_cpu(node->hdr.info.magic) != XFS_DA_NODE_MAGIC)
    -				break;
    -			btree = &node->btree[0];
    -			xfs_dir_trace_g_dun("node: node detail", dp, uio, node);
    -			for (i = 0; i < be16_to_cpu(node->hdr.count); btree++, i++) {
    -				if (be32_to_cpu(btree->hashval) >= cookhash) {
    -					bno = be32_to_cpu(btree->before);
    -					break;
    -				}
    -			}
    -			if (i == be16_to_cpu(node->hdr.count)) {
    -				xfs_da_brelse(trans, bp);
    -				xfs_dir_trace_g_du("node: hash beyond EOF",
    -							  dp, uio);
    -				uio->uio_offset = XFS_DA_MAKE_COOKIE(mp, 0, 0,
    -							     XFS_DA_MAXHASH);
    -				*eofp = 1;
    -				return(0);
    -			}
    -			xfs_dir_trace_g_dub("node: going to block",
    -						   dp, uio, bno);
    -			xfs_da_brelse(trans, bp);
    -		}
    -	}
    -	ASSERT(cookhash != XFS_DA_MAXHASH);
    -
    -	/*
    -	 * We've dropped down to the (first) leaf block that contains the
    -	 * hashval we are interested in.  Continue rolling upward thru the
    -	 * leaf blocks until we fill up our buffer.
    -	 */
    -	for (;;) {
    -		leaf = bp->data;
    -		if (unlikely(be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR_LEAF_MAGIC)) {
    -			xfs_dir_trace_g_dul("node: not a leaf", dp, uio, leaf);
    -			xfs_da_brelse(trans, bp);
    -			XFS_CORRUPTION_ERROR("xfs_dir_node_getdents(1)",
    -					     XFS_ERRLEVEL_LOW, mp, leaf);
    -			return XFS_ERROR(EFSCORRUPTED);
    -		}
    -		xfs_dir_trace_g_dul("node: leaf detail", dp, uio, leaf);
    -		if ((nextbno = be32_to_cpu(leaf->hdr.info.forw))) {
    -			nextda = xfs_da_reada_buf(trans, dp, nextbno,
    -						  XFS_DATA_FORK);
    -		} else
    -			nextda = -1;
    -		error = xfs_dir_leaf_getdents_int(bp, dp, bno, uio, &eob, dbp,
    -						  put, nextda);
    -		xfs_da_brelse(trans, bp);
    -		bno = nextbno;
    -		if (eob) {
    -			xfs_dir_trace_g_dub("node: E-O-B", dp, uio, bno);
    -			*eofp = 0;
    -			return(error);
    -		}
    -		if (bno == 0)
    -			break;
    -		error = xfs_da_read_buf(trans, dp, bno, nextda, &bp,
    -					XFS_DATA_FORK);
    -		if (error)
    -			return(error);
    -		if (unlikely(bp == NULL)) {
    -			XFS_ERROR_REPORT("xfs_dir_node_getdents(2)",
    -					 XFS_ERRLEVEL_LOW, mp);
    -			return(XFS_ERROR(EFSCORRUPTED));
    -		}
    -	}
    -	*eofp = 1;
    -	xfs_dir_trace_g_du("node: E-O-F", dp, uio);
    -	return(0);
    -}
    -
    -/*
    - * Look up a filename in an int directory, replace the inode number.
    - * Use an internal routine to actually do the lookup.
    - */
    -STATIC int
    -xfs_dir_node_replace(xfs_da_args_t *args)
    -{
    -	xfs_da_state_t *state;
    -	xfs_da_state_blk_t *blk;
    -	xfs_dir_leafblock_t *leaf;
    -	xfs_dir_leaf_entry_t *entry;
    -	xfs_dir_leaf_name_t *namest;
    -	xfs_ino_t inum;
    -	int retval, error, i;
    -	xfs_dabuf_t *bp;
    -
    -	state = xfs_da_state_alloc();
    -	state->args = args;
    -	state->mp = args->dp->i_mount;
    -	state->blocksize = state->mp->m_sb.sb_blocksize;
    -	state->node_ents = state->mp->m_dir_node_ents;
    -	inum = args->inumber;
    -
    -	/*
    -	 * Search to see if name exists,
    -	 * and get back a pointer to it.
    -	 */
    -	error = xfs_da_node_lookup_int(state, &retval);
    -	if (error) {
    -		retval = error;
    -	}
    -
    -	if (retval == EEXIST) {
    -		blk = &state->path.blk[state->path.active - 1];
    -		ASSERT(blk->magic == XFS_DIR_LEAF_MAGIC);
    -		bp = blk->bp;
    -		leaf = bp->data;
    -		entry = &leaf->entries[blk->index];
    -		namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT));
    -		/* XXX - replace assert ? */
    -		XFS_DIR_SF_PUT_DIRINO(&inum, &namest->inumber);
    -		xfs_da_log_buf(args->trans, bp,
    -		    XFS_DA_LOGRANGE(leaf, namest, sizeof(namest->inumber)));
    -		xfs_da_buf_done(bp);
    -		blk->bp = NULL;
    -		retval = 0;
    -	} else {
    -		i = state->path.active - 1;
    -		xfs_da_brelse(args->trans, state->path.blk[i].bp);
    -		state->path.blk[i].bp = NULL;
    -	}
    -	for (i = 0; i < state->path.active - 1; i++) {
    -		xfs_da_brelse(args->trans, state->path.blk[i].bp);
    -		state->path.blk[i].bp = NULL;
    -	}
    -
    -	xfs_da_state_free(state);
    -	return(retval);
    -}
    -
    -#if defined(XFS_DIR_TRACE)
    -/*
    - * Add a trace buffer entry for an inode and a uio.
    - */
    -void
    -xfs_dir_trace_g_du(char *where, xfs_inode_t *dp, uio_t *uio)
    -{
    -	xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DU, where,
    -		     (void *)dp, (void *)dp->i_mount,
    -		     (void *)((unsigned long)(uio->uio_offset >> 32)),
    -		     (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)),
    -		     (void *)(unsigned long)uio->uio_resid,
    -		     NULL, NULL, NULL, NULL, NULL, NULL, NULL);
    -}
    -
    -/*
    - * Add a trace buffer entry for an inode and a uio.
    - */
    -void
    -xfs_dir_trace_g_dub(char *where, xfs_inode_t *dp, uio_t *uio, xfs_dablk_t bno)
    -{
    -	xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUB, where,
    -		     (void *)dp, (void *)dp->i_mount,
    -		     (void *)((unsigned long)(uio->uio_offset >> 32)),
    -		     (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)),
    -		     (void *)(unsigned long)uio->uio_resid,
    -		     (void *)(unsigned long)bno,
    -		     NULL, NULL, NULL, NULL, NULL, NULL);
    -}
    -
    -/*
    - * Add a trace buffer entry for an inode and a uio.
    - */
    -void
    -xfs_dir_trace_g_dun(char *where, xfs_inode_t *dp, uio_t *uio,
    -			xfs_da_intnode_t *node)
    -{
    -	int	last = be16_to_cpu(node->hdr.count) - 1;
    -
    -	xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUN, where,
    -		     (void *)dp, (void *)dp->i_mount,
    -		     (void *)((unsigned long)(uio->uio_offset >> 32)),
    -		     (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)),
    -		     (void *)(unsigned long)uio->uio_resid,
    -		     (void *)(unsigned long)be32_to_cpu(node->hdr.info.forw),
    -		     (void *)(unsigned long)
    -			be16_to_cpu(node->hdr.count),
    -		     (void *)(unsigned long)
    -			be32_to_cpu(node->btree[0].hashval),
    -		     (void *)(unsigned long)
    -			be32_to_cpu(node->btree[last].hashval),
    -		     NULL, NULL, NULL);
    -}
    -
    -/*
    - * Add a trace buffer entry for an inode and a uio.
    - */
    -void
    -xfs_dir_trace_g_dul(char *where, xfs_inode_t *dp, uio_t *uio,
    -			xfs_dir_leafblock_t *leaf)
    -{
    -	int	last = INT_GET(leaf->hdr.count, ARCH_CONVERT) - 1;
    -
    -	xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUL, where,
    -		     (void *)dp, (void *)dp->i_mount,
    -		     (void *)((unsigned long)(uio->uio_offset >> 32)),
    -		     (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)),
    -		     (void *)(unsigned long)uio->uio_resid,
    -		     (void *)(unsigned long)be32_to_cpu(leaf->hdr.info.forw),
    -		     (void *)(unsigned long)
    -			INT_GET(leaf->hdr.count, ARCH_CONVERT),
    -		     (void *)(unsigned long)
    -			INT_GET(leaf->entries[0].hashval, ARCH_CONVERT),
    -		     (void *)(unsigned long)
    -			INT_GET(leaf->entries[last].hashval, ARCH_CONVERT),
    -		     NULL, NULL, NULL);
    -}
    -
    -/*
    - * Add a trace buffer entry for an inode and a uio.
    - */
    -void
    -xfs_dir_trace_g_due(char *where, xfs_inode_t *dp, uio_t *uio,
    -			xfs_dir_leaf_entry_t *entry)
    -{
    -	xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUE, where,
    -		     (void *)dp, (void *)dp->i_mount,
    -		     (void *)((unsigned long)(uio->uio_offset >> 32)),
    -		     (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)),
    -		     (void *)(unsigned long)uio->uio_resid,
    -		     (void *)(unsigned long)
    -			INT_GET(entry->hashval, ARCH_CONVERT),
    -		     NULL, NULL, NULL, NULL, NULL, NULL);
    -}
    -
    -/*
    - * Add a trace buffer entry for an inode and a uio.
    - */
    -void
    -xfs_dir_trace_g_duc(char *where, xfs_inode_t *dp, uio_t *uio, xfs_off_t cookie)
    -{
    -	xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUC, where,
    -		     (void *)dp, (void *)dp->i_mount,
    -		     (void *)((unsigned long)(uio->uio_offset >> 32)),
    -		     (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)),
    -		     (void *)(unsigned long)uio->uio_resid,
    -		     (void *)((unsigned long)(cookie >> 32)),
    -		     (void *)((unsigned long)(cookie & 0xFFFFFFFF)),
    -		     NULL, NULL, NULL, NULL, NULL);
    -}
    -
    -/*
    - * Add a trace buffer entry for the arguments given to the routine,
    - * generic form.
    - */
    -void
    -xfs_dir_trace_enter(int type, char *where,
    -			void * a0, void * a1,
    -			void * a2, void * a3,
    -			void * a4, void * a5,
    -			void * a6, void * a7,
    -			void * a8, void * a9,
    -			void * a10, void * a11)
    -{
    -	ASSERT(xfs_dir_trace_buf);
    -	ktrace_enter(xfs_dir_trace_buf, (void *)(unsigned long)type,
    -					(void *)where,
    -					(void *)a0, (void *)a1, (void *)a2,
    -					(void *)a3, (void *)a4, (void *)a5,
    -					(void *)a6, (void *)a7, (void *)a8,
    -					(void *)a9, (void *)a10, (void *)a11,
    -					NULL, NULL);
    -}
    -#endif	/* XFS_DIR_TRACE */
    diff --git a/sys/gnu/fs/xfs/xfs_dir.h b/sys/gnu/fs/xfs/xfs_dir.h
    deleted file mode 100644
    index 8cc8afb9f6c..00000000000
    --- a/sys/gnu/fs/xfs/xfs_dir.h
    +++ /dev/null
    @@ -1,142 +0,0 @@
    -/*
    - * Copyright (c) 2000,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_DIR_H__
    -#define	__XFS_DIR_H__
    -
    -/*
    - * Large directories are structured around Btrees where all the data
    - * elements are in the leaf nodes.  Filenames are hashed into an int,
    - * then that int is used as the index into the Btree.  Since the hashval
    - * of a filename may not be unique, we may have duplicate keys.  The
    - * internal links in the Btree are logical block offsets into the file.
    - *
    - * Small directories use a different format and are packed as tightly
    - * as possible so as to fit into the literal area of the inode.
    - */
    -
    -/*========================================================================
    - * Function prototypes for the kernel.
    - *========================================================================*/
    -
    -struct uio;
    -struct xfs_bmap_free;
    -struct xfs_da_args;
    -struct xfs_dinode;
    -struct xfs_inode;
    -struct xfs_mount;
    -struct xfs_trans;
    -
    -/*
    - * Directory function types.
    - * Put in structures (xfs_dirops_t) for v1 and v2 directories.
    - */
    -typedef void	(*xfs_dir_mount_t)(struct xfs_mount *mp);
    -typedef int	(*xfs_dir_isempty_t)(struct xfs_inode *dp);
    -typedef int	(*xfs_dir_init_t)(struct xfs_trans *tp,
    -				  struct xfs_inode *dp,
    -				  struct xfs_inode *pdp);
    -typedef int	(*xfs_dir_createname_t)(struct xfs_trans *tp,
    -					struct xfs_inode *dp,
    -					char *name,
    -					int namelen,
    -					xfs_ino_t inum,
    -					xfs_fsblock_t *first,
    -					struct xfs_bmap_free *flist,
    -					xfs_extlen_t total);
    -typedef int	(*xfs_dir_lookup_t)(struct xfs_trans *tp,
    -				    struct xfs_inode *dp,
    -				    char *name,
    -				    int namelen,
    -				    xfs_ino_t *inum);
    -typedef int	(*xfs_dir_removename_t)(struct xfs_trans *tp,
    -					struct xfs_inode *dp,
    -					char *name,
    -					int namelen,
    -					xfs_ino_t ino,
    -					xfs_fsblock_t *first,
    -					struct xfs_bmap_free *flist,
    -					xfs_extlen_t total);
    -typedef int	(*xfs_dir_getdents_t)(struct xfs_trans *tp,
    -				      struct xfs_inode *dp,
    -				      struct uio *uio,
    -				      int *eofp);
    -typedef int	(*xfs_dir_replace_t)(struct xfs_trans *tp,
    -				     struct xfs_inode *dp,
    -				     char *name,
    -				     int namelen,
    -				     xfs_ino_t inum,
    -				     xfs_fsblock_t *first,
    -				     struct xfs_bmap_free *flist,
    -				     xfs_extlen_t total);
    -typedef int	(*xfs_dir_canenter_t)(struct xfs_trans *tp,
    -				      struct xfs_inode *dp,
    -				      char *name,
    -				      int namelen);
    -typedef int	(*xfs_dir_shortform_validate_ondisk_t)(struct xfs_mount *mp,
    -						       struct xfs_dinode *dip);
    -typedef int	(*xfs_dir_shortform_to_single_t)(struct xfs_da_args *args);
    -
    -typedef struct xfs_dirops {
    -	xfs_dir_mount_t				xd_mount;
    -	xfs_dir_isempty_t			xd_isempty;
    -	xfs_dir_init_t				xd_init;
    -	xfs_dir_createname_t			xd_createname;
    -	xfs_dir_lookup_t			xd_lookup;
    -	xfs_dir_removename_t			xd_removename;
    -	xfs_dir_getdents_t			xd_getdents;
    -	xfs_dir_replace_t			xd_replace;
    -	xfs_dir_canenter_t			xd_canenter;
    -	xfs_dir_shortform_validate_ondisk_t	xd_shortform_validate_ondisk;
    -	xfs_dir_shortform_to_single_t		xd_shortform_to_single;
    -} xfs_dirops_t;
    -
    -/*
    - * Overall external interface routines.
    - */
    -void	xfs_dir_startup(void);	/* called exactly once */
    -
    -#define	XFS_DIR_MOUNT(mp)	\
    -	((mp)->m_dirops.xd_mount(mp))
    -#define	XFS_DIR_ISEMPTY(mp,dp)	\
    -	((mp)->m_dirops.xd_isempty(dp))
    -#define	XFS_DIR_INIT(mp,tp,dp,pdp)	\
    -	((mp)->m_dirops.xd_init(tp,dp,pdp))
    -#define	XFS_DIR_CREATENAME(mp,tp,dp,name,namelen,inum,first,flist,total) \
    -	((mp)->m_dirops.xd_createname(tp,dp,name,namelen,inum,first,flist,\
    -				      total))
    -#define	XFS_DIR_LOOKUP(mp,tp,dp,name,namelen,inum)	\
    -	((mp)->m_dirops.xd_lookup(tp,dp,name,namelen,inum))
    -#define	XFS_DIR_REMOVENAME(mp,tp,dp,name,namelen,ino,first,flist,total)	\
    -	((mp)->m_dirops.xd_removename(tp,dp,name,namelen,ino,first,flist,total))
    -#define	XFS_DIR_GETDENTS(mp,tp,dp,uio,eofp)	\
    -	((mp)->m_dirops.xd_getdents(tp,dp,uio,eofp))
    -#define	XFS_DIR_REPLACE(mp,tp,dp,name,namelen,inum,first,flist,total)	\
    -	((mp)->m_dirops.xd_replace(tp,dp,name,namelen,inum,first,flist,total))
    -#define	XFS_DIR_CANENTER(mp,tp,dp,name,namelen)	\
    -	((mp)->m_dirops.xd_canenter(tp,dp,name,namelen))
    -#define	XFS_DIR_SHORTFORM_VALIDATE_ONDISK(mp,dip)	\
    -	((mp)->m_dirops.xd_shortform_validate_ondisk(mp,dip))
    -#define	XFS_DIR_SHORTFORM_TO_SINGLE(mp,args)	\
    -	((mp)->m_dirops.xd_shortform_to_single(args))
    -
    -#define	XFS_DIR_IS_V1(mp)	((mp)->m_dirversion == 1)
    -#define	XFS_DIR_IS_V2(mp)	((mp)->m_dirversion == 2)
    -extern xfs_dirops_t xfsv1_dirops;
    -extern xfs_dirops_t xfsv2_dirops;
    -
    -#endif	/* __XFS_DIR_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_dir2.c b/sys/gnu/fs/xfs/xfs_dir2.c
    deleted file mode 100644
    index 12ee653b502..00000000000
    --- a/sys/gnu/fs/xfs/xfs_dir2.c
    +++ /dev/null
    @@ -1,851 +0,0 @@
    -/*
    - * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_da_btree.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_inode_item.h"
    -#include "xfs_bmap.h"
    -#include "xfs_dir_leaf.h"
    -#include "xfs_dir2_data.h"
    -#include "xfs_dir2_leaf.h"
    -#include "xfs_dir2_block.h"
    -#include "xfs_dir2_node.h"
    -#include "xfs_dir2_trace.h"
    -#include "xfs_error.h"
    -
    -/*
    - * Declarations for interface routines.
    - */
    -static void	xfs_dir2_mount(xfs_mount_t *mp);
    -static int	xfs_dir2_isempty(xfs_inode_t *dp);
    -static int	xfs_dir2_init(xfs_trans_t *tp, xfs_inode_t *dp,
    -			      xfs_inode_t *pdp);
    -static int	xfs_dir2_createname(xfs_trans_t *tp, xfs_inode_t *dp,
    -				    char *name, int namelen, xfs_ino_t inum,
    -				    xfs_fsblock_t *first,
    -				    xfs_bmap_free_t *flist, xfs_extlen_t total);
    -static int	xfs_dir2_lookup(xfs_trans_t *tp, xfs_inode_t *dp, char *name,
    -				int namelen, xfs_ino_t *inum);
    -static int	xfs_dir2_removename(xfs_trans_t *tp, xfs_inode_t *dp,
    -				    char *name, int namelen, xfs_ino_t ino,
    -				    xfs_fsblock_t *first,
    -				    xfs_bmap_free_t *flist, xfs_extlen_t total);
    -static int	xfs_dir2_getdents(xfs_trans_t *tp, xfs_inode_t *dp, uio_t *uio,
    -				  int *eofp);
    -static int	xfs_dir2_replace(xfs_trans_t *tp, xfs_inode_t *dp, char *name,
    -				 int namelen, xfs_ino_t inum,
    -				 xfs_fsblock_t *first, xfs_bmap_free_t *flist,
    -				 xfs_extlen_t total);
    -static int	xfs_dir2_canenter(xfs_trans_t *tp, xfs_inode_t *dp, char *name,
    -				  int namelen);
    -static int	xfs_dir2_shortform_validate_ondisk(xfs_mount_t *mp,
    -						   xfs_dinode_t *dip);
    -
    -/*
    - * Utility routine declarations.
    - */
    -static int	xfs_dir2_put_dirent64_direct(xfs_dir2_put_args_t *pa);
    -static int	xfs_dir2_put_dirent64_uio(xfs_dir2_put_args_t *pa);
    -
    -/*
    - * Directory operations vector.
    - */
    -xfs_dirops_t	xfsv2_dirops = {
    -	.xd_mount			= xfs_dir2_mount,
    -	.xd_isempty			= xfs_dir2_isempty,
    -	.xd_init			= xfs_dir2_init,
    -	.xd_createname			= xfs_dir2_createname,
    -	.xd_lookup			= xfs_dir2_lookup,
    -	.xd_removename			= xfs_dir2_removename,
    -	.xd_getdents			= xfs_dir2_getdents,
    -	.xd_replace			= xfs_dir2_replace,
    -	.xd_canenter			= xfs_dir2_canenter,
    -	.xd_shortform_validate_ondisk	= xfs_dir2_shortform_validate_ondisk,
    -	.xd_shortform_to_single		= xfs_dir2_sf_to_block,
    -};
    -
    -/*
    - * Interface routines.
    - */
    -
    -/*
    - * Initialize directory-related fields in the mount structure.
    - */
    -static void
    -xfs_dir2_mount(
    -	xfs_mount_t	*mp)		/* filesystem mount point */
    -{
    -	mp->m_dirversion = 2;
    -	ASSERT((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) <=
    -	       XFS_MAX_BLOCKSIZE);
    -	mp->m_dirblksize = 1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog);
    -	mp->m_dirblkfsbs = 1 << mp->m_sb.sb_dirblklog;
    -	mp->m_dirdatablk = XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_DATA_FIRSTDB(mp));
    -	mp->m_dirleafblk = XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_LEAF_FIRSTDB(mp));
    -	mp->m_dirfreeblk = XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_FREE_FIRSTDB(mp));
    -	mp->m_attr_node_ents =
    -		(mp->m_sb.sb_blocksize - (uint)sizeof(xfs_da_node_hdr_t)) /
    -		(uint)sizeof(xfs_da_node_entry_t);
    -	mp->m_dir_node_ents =
    -		(mp->m_dirblksize - (uint)sizeof(xfs_da_node_hdr_t)) /
    -		(uint)sizeof(xfs_da_node_entry_t);
    -	mp->m_dir_magicpct = (mp->m_dirblksize * 37) / 100;
    -}
    -
    -/*
    - * Return 1 if directory contains only "." and "..".
    - */
    -static int				/* return code */
    -xfs_dir2_isempty(
    -	xfs_inode_t	*dp)		/* incore inode structure */
    -{
    -	xfs_dir2_sf_t	*sfp;		/* shortform directory structure */
    -
    -	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
    -	/*
    -	 * Might happen during shutdown.
    -	 */
    -	if (dp->i_d.di_size == 0) {
    -		return 1;
    -	}
    -	if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp))
    -		return 0;
    -	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
    -	return !sfp->hdr.count;
    -}
    -
    -/*
    - * Initialize a directory with its "." and ".." entries.
    - */
    -static int				/* error */
    -xfs_dir2_init(
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_inode_t	*dp,		/* incore directory inode */
    -	xfs_inode_t	*pdp)		/* incore parent directory inode */
    -{
    -	xfs_da_args_t	args;		/* operation arguments */
    -	int		error;		/* error return value */
    -
    -	memset((char *)&args, 0, sizeof(args));
    -	args.dp = dp;
    -	args.trans = tp;
    -	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
    -	if ((error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino))) {
    -		return error;
    -	}
    -	return xfs_dir2_sf_create(&args, pdp->i_ino);
    -}
    -
    -/*
    -  Enter a name in a directory.
    - */
    -static int					/* error */
    -xfs_dir2_createname(
    -	xfs_trans_t		*tp,		/* transaction pointer */
    -	xfs_inode_t		*dp,		/* incore directory inode */
    -	char			*name,		/* new entry name */
    -	int			namelen,	/* new entry name length */
    -	xfs_ino_t		inum,		/* new entry inode number */
    -	xfs_fsblock_t		*first,		/* bmap's firstblock */
    -	xfs_bmap_free_t		*flist,		/* bmap's freeblock list */
    -	xfs_extlen_t		total)		/* bmap's total block count */
    -{
    -	xfs_da_args_t		args;		/* operation arguments */
    -	int			rval;		/* return value */
    -	int			v;		/* type-checking value */
    -
    -	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
    -	if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum))) {
    -		return rval;
    -	}
    -	XFS_STATS_INC(xs_dir_create);
    -	/*
    -	 * Fill in the arg structure for this request.
    -	 */
    -	args.name = name;
    -	args.namelen = namelen;
    -	args.hashval = xfs_da_hashname(name, namelen);
    -	args.inumber = inum;
    -	args.dp = dp;
    -	args.firstblock = first;
    -	args.flist = flist;
    -	args.total = total;
    -	args.whichfork = XFS_DATA_FORK;
    -	args.trans = tp;
    -	args.justcheck = 0;
    -	args.addname = args.oknoent = 1;
    -	/*
    -	 * Decide on what work routines to call based on the inode size.
    -	 */
    -	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
    -		rval = xfs_dir2_sf_addname(&args);
    -	else if ((rval = xfs_dir2_isblock(tp, dp, &v))) {
    -		return rval;
    -	} else if (v)
    -		rval = xfs_dir2_block_addname(&args);
    -	else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) {
    -		return rval;
    -	} else if (v)
    -		rval = xfs_dir2_leaf_addname(&args);
    -	else
    -		rval = xfs_dir2_node_addname(&args);
    -	return rval;
    -}
    -
    -/*
    - * Lookup a name in a directory, give back the inode number.
    - */
    -static int				/* error */
    -xfs_dir2_lookup(
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_inode_t	*dp,		/* incore directory inode */
    -	char		*name,		/* lookup name */
    -	int		namelen,	/* lookup name length */
    -	xfs_ino_t	*inum)		/* out: inode number */
    -{
    -	xfs_da_args_t	args;		/* operation arguments */
    -	int		rval;		/* return value */
    -	int		v;		/* type-checking value */
    -
    -	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
    -	XFS_STATS_INC(xs_dir_lookup);
    -
    -	/*
    -	 * Fill in the arg structure for this request.
    -	 */
    -	args.name = name;
    -	args.namelen = namelen;
    -	args.hashval = xfs_da_hashname(name, namelen);
    -	args.inumber = 0;
    -	args.dp = dp;
    -	args.firstblock = NULL;
    -	args.flist = NULL;
    -	args.total = 0;
    -	args.whichfork = XFS_DATA_FORK;
    -	args.trans = tp;
    -	args.justcheck = args.addname = 0;
    -	args.oknoent = 1;
    -	/*
    -	 * Decide on what work routines to call based on the inode size.
    -	 */
    -	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
    -		rval = xfs_dir2_sf_lookup(&args);
    -	else if ((rval = xfs_dir2_isblock(tp, dp, &v))) {
    -		return rval;
    -	} else if (v)
    -		rval = xfs_dir2_block_lookup(&args);
    -	else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) {
    -		return rval;
    -	} else if (v)
    -		rval = xfs_dir2_leaf_lookup(&args);
    -	else
    -		rval = xfs_dir2_node_lookup(&args);
    -	if (rval == EEXIST)
    -		rval = 0;
    -	if (rval == 0)
    -		*inum = args.inumber;
    -	return rval;
    -}
    -
    -/*
    - * Remove an entry from a directory.
    - */
    -static int				/* error */
    -xfs_dir2_removename(
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_inode_t	*dp,		/* incore directory inode */
    -	char		*name,		/* name of entry to remove */
    -	int		namelen,	/* name length of entry to remove */
    -	xfs_ino_t	ino,		/* inode number of entry to remove */
    -	xfs_fsblock_t	*first,		/* bmap's firstblock */
    -	xfs_bmap_free_t	*flist,		/* bmap's freeblock list */
    -	xfs_extlen_t	total)		/* bmap's total block count */
    -{
    -	xfs_da_args_t	args;		/* operation arguments */
    -	int		rval;		/* return value */
    -	int		v;		/* type-checking value */
    -
    -	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
    -	XFS_STATS_INC(xs_dir_remove);
    -	/*
    -	 * Fill in the arg structure for this request.
    -	 */
    -	args.name = name;
    -	args.namelen = namelen;
    -	args.hashval = xfs_da_hashname(name, namelen);
    -	args.inumber = ino;
    -	args.dp = dp;
    -	args.firstblock = first;
    -	args.flist = flist;
    -	args.total = total;
    -	args.whichfork = XFS_DATA_FORK;
    -	args.trans = tp;
    -	args.justcheck = args.addname = args.oknoent = 0;
    -	/*
    -	 * Decide on what work routines to call based on the inode size.
    -	 */
    -	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
    -		rval = xfs_dir2_sf_removename(&args);
    -	else if ((rval = xfs_dir2_isblock(tp, dp, &v))) {
    -		return rval;
    -	} else if (v)
    -		rval = xfs_dir2_block_removename(&args);
    -	else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) {
    -		return rval;
    -	} else if (v)
    -		rval = xfs_dir2_leaf_removename(&args);
    -	else
    -		rval = xfs_dir2_node_removename(&args);
    -	return rval;
    -}
    -
    -/*
    - * Read a directory.
    - */
    -static int				/* error */
    -xfs_dir2_getdents(
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_inode_t	*dp,		/* incore directory inode */
    -	uio_t		*uio,		/* caller's buffer control */
    -	int		*eofp)		/* out: eof reached */
    -{
    -	int		alignment;	/* alignment required for ABI */
    -	xfs_dirent_t	*dbp;		/* malloc'ed buffer */
    -	xfs_dir2_put_t	put;		/* entry formatting routine */
    -	int		rval;		/* return value */
    -	int		v;		/* type-checking value */
    -
    -	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
    -	XFS_STATS_INC(xs_dir_getdents);
    -	/*
    -	 * If our caller has given us a single contiguous aligned memory buffer,
    -	 * just work directly within that buffer.  If it's in user memory,
    -	 * lock it down first.
    -	 */
    -	alignment = sizeof(xfs_off_t) - 1;
    -	if ((uio->uio_iovcnt == 1) &&
    -	    (((__psint_t)uio->uio_iov[0].iov_base & alignment) == 0) &&
    -	    ((uio->uio_iov[0].iov_len & alignment) == 0)) {
    -		dbp = NULL;
    -		put = xfs_dir2_put_dirent64_direct;
    -	} else {
    -		dbp = kmem_alloc(sizeof(*dbp) + MAXNAMELEN, KM_SLEEP);
    -		put = xfs_dir2_put_dirent64_uio;
    -	}
    -
    -	*eofp = 0;
    -	/*
    -	 * Decide on what work routines to call based on the inode size.
    -	 */
    -	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
    -		rval = xfs_dir2_sf_getdents(dp, uio, eofp, dbp, put);
    -	else if ((rval = xfs_dir2_isblock(tp, dp, &v))) {
    -		;
    -	} else if (v)
    -		rval = xfs_dir2_block_getdents(tp, dp, uio, eofp, dbp, put);
    -	else
    -		rval = xfs_dir2_leaf_getdents(tp, dp, uio, eofp, dbp, put);
    -	if (dbp != NULL)
    -		kmem_free(dbp, sizeof(*dbp) + MAXNAMELEN);
    -	return rval;
    -}
    -
    -/*
    - * Replace the inode number of a directory entry.
    - */
    -static int				/* error */
    -xfs_dir2_replace(
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_inode_t	*dp,		/* incore directory inode */
    -	char		*name,		/* name of entry to replace */
    -	int		namelen,	/* name length of entry to replace */
    -	xfs_ino_t	inum,		/* new inode number */
    -	xfs_fsblock_t	*first,		/* bmap's firstblock */
    -	xfs_bmap_free_t	*flist,		/* bmap's freeblock list */
    -	xfs_extlen_t	total)		/* bmap's total block count */
    -{
    -	xfs_da_args_t	args;		/* operation arguments */
    -	int		rval;		/* return value */
    -	int		v;		/* type-checking value */
    -
    -	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
    -
    -	if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum))) {
    -		return rval;
    -	}
    -	/*
    -	 * Fill in the arg structure for this request.
    -	 */
    -	args.name = name;
    -	args.namelen = namelen;
    -	args.hashval = xfs_da_hashname(name, namelen);
    -	args.inumber = inum;
    -	args.dp = dp;
    -	args.firstblock = first;
    -	args.flist = flist;
    -	args.total = total;
    -	args.whichfork = XFS_DATA_FORK;
    -	args.trans = tp;
    -	args.justcheck = args.addname = args.oknoent = 0;
    -	/*
    -	 * Decide on what work routines to call based on the inode size.
    -	 */
    -	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
    -		rval = xfs_dir2_sf_replace(&args);
    -	else if ((rval = xfs_dir2_isblock(tp, dp, &v))) {
    -		return rval;
    -	} else if (v)
    -		rval = xfs_dir2_block_replace(&args);
    -	else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) {
    -		return rval;
    -	} else if (v)
    -		rval = xfs_dir2_leaf_replace(&args);
    -	else
    -		rval = xfs_dir2_node_replace(&args);
    -	return rval;
    -}
    -
    -/*
    - * See if this entry can be added to the directory without allocating space.
    - */
    -static int				/* error */
    -xfs_dir2_canenter(
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_inode_t	*dp,		/* incore directory inode */
    -	char		*name,		/* name of entry to add */
    -	int		namelen)	/* name length of entry to add */
    -{
    -	xfs_da_args_t	args;		/* operation arguments */
    -	int		rval;		/* return value */
    -	int		v;		/* type-checking value */
    -
    -	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
    -	/*
    -	 * Fill in the arg structure for this request.
    -	 */
    -	args.name = name;
    -	args.namelen = namelen;
    -	args.hashval = xfs_da_hashname(name, namelen);
    -	args.inumber = 0;
    -	args.dp = dp;
    -	args.firstblock = NULL;
    -	args.flist = NULL;
    -	args.total = 0;
    -	args.whichfork = XFS_DATA_FORK;
    -	args.trans = tp;
    -	args.justcheck = args.addname = args.oknoent = 1;
    -	/*
    -	 * Decide on what work routines to call based on the inode size.
    -	 */
    -	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
    -		rval = xfs_dir2_sf_addname(&args);
    -	else if ((rval = xfs_dir2_isblock(tp, dp, &v))) {
    -		return rval;
    -	} else if (v)
    -		rval = xfs_dir2_block_addname(&args);
    -	else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) {
    -		return rval;
    -	} else if (v)
    -		rval = xfs_dir2_leaf_addname(&args);
    -	else
    -		rval = xfs_dir2_node_addname(&args);
    -	return rval;
    -}
    -
    -/*
    - * Dummy routine for shortform inode validation.
    - * Can't really do this.
    - */
    -/* ARGSUSED */
    -static int				/* error */
    -xfs_dir2_shortform_validate_ondisk(
    -	xfs_mount_t	*mp,		/* filesystem mount point */
    -	xfs_dinode_t	*dip)		/* ondisk inode */
    -{
    -	return 0;
    -}
    -
    -/*
    - * Utility routines.
    - */
    -
    -/*
    - * Add a block to the directory.
    - * This routine is for data and free blocks, not leaf/node blocks
    - * which are handled by xfs_da_grow_inode.
    - */
    -int					/* error */
    -xfs_dir2_grow_inode(
    -	xfs_da_args_t	*args,		/* operation arguments */
    -	int		space,		/* v2 dir's space XFS_DIR2_xxx_SPACE */
    -	xfs_dir2_db_t	*dbp)		/* out: block number added */
    -{
    -	xfs_fileoff_t	bno;		/* directory offset of new block */
    -	int		count;		/* count of filesystem blocks */
    -	xfs_inode_t	*dp;		/* incore directory inode */
    -	int		error;		/* error return value */
    -	int		got;		/* blocks actually mapped */
    -	int		i;		/* temp mapping index */
    -	xfs_bmbt_irec_t	map;		/* single structure for bmap */
    -	int		mapi;		/* mapping index */
    -	xfs_bmbt_irec_t	*mapp;		/* bmap mapping structure(s) */
    -	xfs_mount_t	*mp;		/* filesystem mount point */
    -	int		nmap;		/* number of bmap entries */
    -	xfs_trans_t	*tp;		/* transaction pointer */
    -
    -	xfs_dir2_trace_args_s("grow_inode", args, space);
    -	dp = args->dp;
    -	tp = args->trans;
    -	mp = dp->i_mount;
    -	/*
    -	 * Set lowest possible block in the space requested.
    -	 */
    -	bno = XFS_B_TO_FSBT(mp, space * XFS_DIR2_SPACE_SIZE);
    -	count = mp->m_dirblkfsbs;
    -	/*
    -	 * Find the first hole for our block.
    -	 */
    -	if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, XFS_DATA_FORK))) {
    -		return error;
    -	}
    -	nmap = 1;
    -	ASSERT(args->firstblock != NULL);
    -	/*
    -	 * Try mapping the new block contiguously (one extent).
    -	 */
    -	if ((error = xfs_bmapi(tp, dp, bno, count,
    -			XFS_BMAPI_WRITE|XFS_BMAPI_METADATA|XFS_BMAPI_CONTIG,
    -			args->firstblock, args->total, &map, &nmap,
    -			args->flist, NULL))) {
    -		return error;
    -	}
    -	ASSERT(nmap <= 1);
    -	/*
    -	 * Got it in 1.
    -	 */
    -	if (nmap == 1) {
    -		mapp = ↦
    -		mapi = 1;
    -	}
    -	/*
    -	 * Didn't work and this is a multiple-fsb directory block.
    -	 * Try again with contiguous flag turned on.
    -	 */
    -	else if (nmap == 0 && count > 1) {
    -		xfs_fileoff_t	b;	/* current file offset */
    -
    -		/*
    -		 * Space for maximum number of mappings.
    -		 */
    -		mapp = kmem_alloc(sizeof(*mapp) * count, KM_SLEEP);
    -		/*
    -		 * Iterate until we get to the end of our block.
    -		 */
    -		for (b = bno, mapi = 0; b < bno + count; ) {
    -			int	c;	/* current fsb count */
    -
    -			/*
    -			 * Can't map more than MAX_NMAP at once.
    -			 */
    -			nmap = MIN(XFS_BMAP_MAX_NMAP, count);
    -			c = (int)(bno + count - b);
    -			if ((error = xfs_bmapi(tp, dp, b, c,
    -					XFS_BMAPI_WRITE|XFS_BMAPI_METADATA,
    -					args->firstblock, args->total,
    -					&mapp[mapi], &nmap, args->flist,
    -					NULL))) {
    -				kmem_free(mapp, sizeof(*mapp) * count);
    -				return error;
    -			}
    -			if (nmap < 1)
    -				break;
    -			/*
    -			 * Add this bunch into our table, go to the next offset.
    -			 */
    -			mapi += nmap;
    -			b = mapp[mapi - 1].br_startoff +
    -			    mapp[mapi - 1].br_blockcount;
    -		}
    -	}
    -	/*
    -	 * Didn't work.
    -	 */
    -	else {
    -		mapi = 0;
    -		mapp = NULL;
    -	}
    -	/*
    -	 * See how many fsb's we got.
    -	 */
    -	for (i = 0, got = 0; i < mapi; i++)
    -		got += mapp[i].br_blockcount;
    -	/*
    -	 * Didn't get enough fsb's, or the first/last block's are wrong.
    -	 */
    -	if (got != count || mapp[0].br_startoff != bno ||
    -	    mapp[mapi - 1].br_startoff + mapp[mapi - 1].br_blockcount !=
    -	    bno + count) {
    -		if (mapp != &map)
    -			kmem_free(mapp, sizeof(*mapp) * count);
    -		return XFS_ERROR(ENOSPC);
    -	}
    -	/*
    -	 * Done with the temporary mapping table.
    -	 */
    -	if (mapp != &map)
    -		kmem_free(mapp, sizeof(*mapp) * count);
    -	*dbp = XFS_DIR2_DA_TO_DB(mp, (xfs_dablk_t)bno);
    -	/*
    -	 * Update file's size if this is the data space and it grew.
    -	 */
    -	if (space == XFS_DIR2_DATA_SPACE) {
    -		xfs_fsize_t	size;		/* directory file (data) size */
    -
    -		size = XFS_FSB_TO_B(mp, bno + count);
    -		if (size > dp->i_d.di_size) {
    -			dp->i_d.di_size = size;
    -			xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
    -		}
    -	}
    -	return 0;
    -}
    -
    -/*
    - * See if the directory is a single-block form directory.
    - */
    -int					/* error */
    -xfs_dir2_isblock(
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_inode_t	*dp,		/* incore directory inode */
    -	int		*vp)		/* out: 1 is block, 0 is not block */
    -{
    -	xfs_fileoff_t	last;		/* last file offset */
    -	xfs_mount_t	*mp;		/* filesystem mount point */
    -	int		rval;		/* return value */
    -
    -	mp = dp->i_mount;
    -	if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK))) {
    -		return rval;
    -	}
    -	rval = XFS_FSB_TO_B(mp, last) == mp->m_dirblksize;
    -	ASSERT(rval == 0 || dp->i_d.di_size == mp->m_dirblksize);
    -	*vp = rval;
    -	return 0;
    -}
    -
    -/*
    - * See if the directory is a single-leaf form directory.
    - */
    -int					/* error */
    -xfs_dir2_isleaf(
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_inode_t	*dp,		/* incore directory inode */
    -	int		*vp)		/* out: 1 is leaf, 0 is not leaf */
    -{
    -	xfs_fileoff_t	last;		/* last file offset */
    -	xfs_mount_t	*mp;		/* filesystem mount point */
    -	int		rval;		/* return value */
    -
    -	mp = dp->i_mount;
    -	if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK))) {
    -		return rval;
    -	}
    -	*vp = last == mp->m_dirleafblk + (1 << mp->m_sb.sb_dirblklog);
    -	return 0;
    -}
    -
    -/*
    - * Getdents put routine for 64-bit ABI, direct form.
    - */
    -static int					/* error */
    -xfs_dir2_put_dirent64_direct(
    -	xfs_dir2_put_args_t	*pa)		/* argument bundle */
    -{
    -	struct dirent		*idbp, dtmp;	/* dirent pointer */
    -	iovec_t			*iovp;		/* io vector */
    -	int			namelen;	/* entry name length */
    -	int			reclen;		/* entry total length */
    -	uio_t			*uio;		/* I/O control */
    -
    -	namelen = pa->namelen;
    -
    -	dtmp.d_namlen = namelen;
    -	dtmp.d_reclen = GENERIC_DIRSIZ(&dtmp);
    -	reclen = dtmp.d_reclen;
    -
    -	uio = pa->uio;
    -	/*
    -	 * Won't fit in the remaining space.
    -	 */
    -	if (reclen > uio->uio_resid) {
    -		pa->done = 0;
    -		return 0;
    -	}
    -	iovp = uio->uio_iov;
    -	idbp = (struct dirent *)iovp->iov_base;
    -	iovp->iov_base = (char *)idbp + reclen;
    -	iovp->iov_len -= reclen;
    -	uio->uio_resid -= reclen;
    -	idbp->d_reclen = reclen;
    -	idbp->d_fileno = pa->ino;
    -	idbp->d_type = DT_UNKNOWN;
    -	idbp->d_namlen = namelen;
    -	memcpy(idbp->d_name, pa->name, namelen);
    -	idbp->d_name[namelen] = '\0';
    -	pa->done = 1;
    -	return 0;
    -}
    -
    -/*
    - * Getdents put routine for 64-bit ABI, uio form.
    - */
    -static int					/* error */
    -xfs_dir2_put_dirent64_uio(
    -	xfs_dir2_put_args_t	*pa)		/* argument bundle */
    -{
    -	struct dirent		*idbp, dtmp;	/* dirent pointer */
    -	int			namelen;	/* entry name length */
    -	int			reclen;		/* entry total length */
    -	int			rval;		/* return value */
    -	uio_t			*uio;		/* I/O control */
    -
    -	namelen = pa->namelen;
    -
    -	dtmp.d_namlen = namelen;
    -	dtmp.d_reclen = GENERIC_DIRSIZ(&dtmp);
    -	reclen = dtmp.d_reclen;
    -
    -	uio = pa->uio;
    -	/*
    -	 * Won't fit in the remaining space.
    -	 */
    -	if (reclen > uio->uio_resid) {
    -		pa->done = 0;
    -		return 0;
    -	}
    -	idbp = &dtmp;
    -	idbp->d_reclen = reclen;
    -	idbp->d_fileno = pa->ino;
    -	idbp->d_type = DT_UNKNOWN;
    -	idbp->d_namlen = namelen;
    -	memcpy(idbp->d_name, pa->name, namelen);
    -	idbp->d_name[namelen] = '\0';
    -	rval = uio_read((caddr_t)idbp, reclen, uio);
    -	pa->done = (rval == 0);
    -	return rval;
    -}
    -
    -/*
    - * Remove the given block from the directory.
    - * This routine is used for data and free blocks, leaf/node are done
    - * by xfs_da_shrink_inode.
    - */
    -int
    -xfs_dir2_shrink_inode(
    -	xfs_da_args_t	*args,		/* operation arguments */
    -	xfs_dir2_db_t	db,		/* directory block number */
    -	xfs_dabuf_t	*bp)		/* block's buffer */
    -{
    -	xfs_fileoff_t	bno;		/* directory file offset */
    -	xfs_dablk_t	da;		/* directory file offset */
    -	int		done;		/* bunmap is finished */
    -	xfs_inode_t	*dp;		/* incore directory inode */
    -	int		error;		/* error return value */
    -	xfs_mount_t	*mp;		/* filesystem mount point */
    -	xfs_trans_t	*tp;		/* transaction pointer */
    -
    -	xfs_dir2_trace_args_db("shrink_inode", args, db, bp);
    -	dp = args->dp;
    -	mp = dp->i_mount;
    -	tp = args->trans;
    -	da = XFS_DIR2_DB_TO_DA(mp, db);
    -	/*
    -	 * Unmap the fsblock(s).
    -	 */
    -	if ((error = xfs_bunmapi(tp, dp, da, mp->m_dirblkfsbs,
    -			XFS_BMAPI_METADATA, 0, args->firstblock, args->flist,
    -			NULL, &done))) {
    -		/*
    -		 * ENOSPC actually can happen if we're in a removename with
    -		 * no space reservation, and the resulting block removal
    -		 * would cause a bmap btree split or conversion from extents
    -		 * to btree.  This can only happen for un-fragmented
    -		 * directory blocks, since you need to be punching out
    -		 * the middle of an extent.
    -		 * In this case we need to leave the block in the file,
    -		 * and not binval it.
    -		 * So the block has to be in a consistent empty state
    -		 * and appropriately logged.
    -		 * We don't free up the buffer, the caller can tell it
    -		 * hasn't happened since it got an error back.
    -		 */
    -		return error;
    -	}
    -	ASSERT(done);
    -	/*
    -	 * Invalidate the buffer from the transaction.
    -	 */
    -	xfs_da_binval(tp, bp);
    -	/*
    -	 * If it's not a data block, we're done.
    -	 */
    -	if (db >= XFS_DIR2_LEAF_FIRSTDB(mp))
    -		return 0;
    -	/*
    -	 * If the block isn't the last one in the directory, we're done.
    -	 */
    -	if (dp->i_d.di_size > XFS_DIR2_DB_OFF_TO_BYTE(mp, db + 1, 0))
    -		return 0;
    -	bno = da;
    -	if ((error = xfs_bmap_last_before(tp, dp, &bno, XFS_DATA_FORK))) {
    -		/*
    -		 * This can't really happen unless there's kernel corruption.
    -		 */
    -		return error;
    -	}
    -	if (db == mp->m_dirdatablk)
    -		ASSERT(bno == 0);
    -	else
    -		ASSERT(bno > 0);
    -	/*
    -	 * Set the size to the new last block.
    -	 */
    -	dp->i_d.di_size = XFS_FSB_TO_B(mp, bno);
    -	xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
    -	return 0;
    -}
    -
    -
    diff --git a/sys/gnu/fs/xfs/xfs_dir2.h b/sys/gnu/fs/xfs/xfs_dir2.h
    deleted file mode 100644
    index 7dd364b1e03..00000000000
    --- a/sys/gnu/fs/xfs/xfs_dir2.h
    +++ /dev/null
    @@ -1,87 +0,0 @@
    -/*
    - * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_DIR2_H__
    -#define	__XFS_DIR2_H__
    -
    -struct uio;
    -struct xfs_dabuf;
    -struct xfs_da_args;
    -struct xfs_dir2_put_args;
    -struct xfs_inode;
    -struct xfs_trans;
    -
    -/*
    - * Directory version 2.
    - * There are 4 possible formats:
    - *	shortform
    - *	single block - data with embedded leaf at the end
    - *	multiple data blocks, single leaf+freeindex block
    - *	data blocks, node&leaf blocks (btree), freeindex blocks
    - *
    - *	The shortform format is in xfs_dir2_sf.h.
    - *	The single block format is in xfs_dir2_block.h.
    - *	The data block format is in xfs_dir2_data.h.
    - *	The leaf and freeindex block formats are in xfs_dir2_leaf.h.
    - *	Node blocks are the same as the other version, in xfs_da_btree.h.
    - */
    -
    -/*
    - * Byte offset in data block and shortform entry.
    - */
    -typedef	__uint16_t	xfs_dir2_data_off_t;
    -#define	NULLDATAOFF	0xffffU
    -typedef uint		xfs_dir2_data_aoff_t;	/* argument form */
    -
    -/*
    - * Directory block number (logical dirblk in file)
    - */
    -typedef	__uint32_t	xfs_dir2_db_t;
    -
    -/*
    - * Byte offset in a directory.
    - */
    -typedef	xfs_off_t	xfs_dir2_off_t;
    -
    -/*
    - * For getdents, argument struct for put routines.
    - */
    -typedef int (*xfs_dir2_put_t)(struct xfs_dir2_put_args *pa);
    -typedef struct xfs_dir2_put_args {
    -	xfs_off_t	cook;		/* cookie of (next) entry */
    -	xfs_intino_t	ino;		/* inode number */
    -	xfs_dirent_t	*dbp;		/* buffer pointer */
    -	char		*name;		/* directory entry name */
    -	int		namelen;	/* length of name */
    -	int		done;		/* output: set if value was stored */
    -	xfs_dir2_put_t	put;		/* put function ptr (i/o) */
    -	struct uio	*uio;		/* uio control structure */
    -} xfs_dir2_put_args_t;
    -
    -/*
    - * Other interfaces used by the rest of the dir v2 code.
    - */
    -extern int xfs_dir2_grow_inode(struct xfs_da_args *args, int space,
    -				xfs_dir2_db_t *dbp);
    -extern int xfs_dir2_isblock(struct xfs_trans *tp, struct xfs_inode *dp,
    -				int *vp);
    -extern int xfs_dir2_isleaf(struct xfs_trans *tp, struct xfs_inode *dp,
    -				int *vp);
    -extern int xfs_dir2_shrink_inode(struct xfs_da_args *args, xfs_dir2_db_t db,
    -				struct xfs_dabuf *bp);
    -
    -#endif	/* __XFS_DIR2_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_dir2_block.c b/sys/gnu/fs/xfs/xfs_dir2_block.c
    deleted file mode 100644
    index 972ded59547..00000000000
    --- a/sys/gnu/fs/xfs/xfs_dir2_block.c
    +++ /dev/null
    @@ -1,1229 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_da_btree.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_inode_item.h"
    -#include "xfs_dir_leaf.h"
    -#include "xfs_dir2_data.h"
    -#include "xfs_dir2_leaf.h"
    -#include "xfs_dir2_block.h"
    -#include "xfs_dir2_trace.h"
    -#include "xfs_error.h"
    -
    -/*
    - * Local function prototypes.
    - */
    -static void xfs_dir2_block_log_leaf(xfs_trans_t *tp, xfs_dabuf_t *bp, int first,
    -				    int last);
    -static void xfs_dir2_block_log_tail(xfs_trans_t *tp, xfs_dabuf_t *bp);
    -static int xfs_dir2_block_lookup_int(xfs_da_args_t *args, xfs_dabuf_t **bpp,
    -				     int *entno);
    -static int xfs_dir2_block_sort(const void *a, const void *b);
    -
    -/*
    - * Add an entry to a block directory.
    - */
    -int						/* error */
    -xfs_dir2_block_addname(
    -	xfs_da_args_t		*args)		/* directory op arguments */
    -{
    -	xfs_dir2_data_free_t	*bf;		/* bestfree table in block */
    -	xfs_dir2_block_t	*block;		/* directory block structure */
    -	xfs_dir2_leaf_entry_t	*blp;		/* block leaf entries */
    -	xfs_dabuf_t		*bp;		/* buffer for block */
    -	xfs_dir2_block_tail_t	*btp;		/* block tail */
    -	int			compact;	/* need to compact leaf ents */
    -	xfs_dir2_data_entry_t	*dep;		/* block data entry */
    -	xfs_inode_t		*dp;		/* directory inode */
    -	xfs_dir2_data_unused_t	*dup;		/* block unused entry */
    -	int			error;		/* error return value */
    -	xfs_dir2_data_unused_t	*enddup=NULL;	/* unused at end of data */
    -	xfs_dahash_t		hash;		/* hash value of found entry */
    -	int			high;		/* high index for binary srch */
    -	int			highstale;	/* high stale index */
    -	int			lfloghigh=0;	/* last final leaf to log */
    -	int			lfloglow=0;	/* first final leaf to log */
    -	int			len;		/* length of the new entry */
    -	int			low;		/* low index for binary srch */
    -	int			lowstale;	/* low stale index */
    -	int			mid=0;		/* midpoint for binary srch */
    -	xfs_mount_t		*mp;		/* filesystem mount point */
    -	int			needlog;	/* need to log header */
    -	int			needscan;	/* need to rescan freespace */
    -	__be16			*tagp;		/* pointer to tag value */
    -	xfs_trans_t		*tp;		/* transaction structure */
    -
    -	xfs_dir2_trace_args("block_addname", args);
    -	dp = args->dp;
    -	tp = args->trans;
    -	mp = dp->i_mount;
    -	/*
    -	 * Read the (one and only) directory block into dabuf bp.
    -	 */
    -	if ((error =
    -	    xfs_da_read_buf(tp, dp, mp->m_dirdatablk, -1, &bp, XFS_DATA_FORK))) {
    -		return error;
    -	}
    -	ASSERT(bp != NULL);
    -	block = bp->data;
    -	/*
    -	 * Check the magic number, corrupted if wrong.
    -	 */
    -	if (unlikely(be32_to_cpu(block->hdr.magic) != XFS_DIR2_BLOCK_MAGIC)) {
    -		XFS_CORRUPTION_ERROR("xfs_dir2_block_addname",
    -				     XFS_ERRLEVEL_LOW, mp, block);
    -		xfs_da_brelse(tp, bp);
    -		return XFS_ERROR(EFSCORRUPTED);
    -	}
    -	len = XFS_DIR2_DATA_ENTSIZE(args->namelen);
    -	/*
    -	 * Set up pointers to parts of the block.
    -	 */
    -	bf = block->hdr.bestfree;
    -	btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
    -	blp = XFS_DIR2_BLOCK_LEAF_P(btp);
    -	/*
    -	 * No stale entries?  Need space for entry and new leaf.
    -	 */
    -	if (!btp->stale) {
    -		/*
    -		 * Tag just before the first leaf entry.
    -		 */
    -		tagp = (__be16 *)blp - 1;
    -		/*
    -		 * Data object just before the first leaf entry.
    -		 */
    -		enddup = (xfs_dir2_data_unused_t *)((char *)block + be16_to_cpu(*tagp));
    -		/*
    -		 * If it's not free then can't do this add without cleaning up:
    -		 * the space before the first leaf entry needs to be free so it
    -		 * can be expanded to hold the pointer to the new entry.
    -		 */
    -		if (be16_to_cpu(enddup->freetag) != XFS_DIR2_DATA_FREE_TAG)
    -			dup = enddup = NULL;
    -		/*
    -		 * Check out the biggest freespace and see if it's the same one.
    -		 */
    -		else {
    -			dup = (xfs_dir2_data_unused_t *)
    -			      ((char *)block + be16_to_cpu(bf[0].offset));
    -			if (dup == enddup) {
    -				/*
    -				 * It is the biggest freespace, is it too small
    -				 * to hold the new leaf too?
    -				 */
    -				if (be16_to_cpu(dup->length) < len + (uint)sizeof(*blp)) {
    -					/*
    -					 * Yes, we use the second-largest
    -					 * entry instead if it works.
    -					 */
    -					if (be16_to_cpu(bf[1].length) >= len)
    -						dup = (xfs_dir2_data_unused_t *)
    -						      ((char *)block +
    -						       be16_to_cpu(bf[1].offset));
    -					else
    -						dup = NULL;
    -				}
    -			} else {
    -				/*
    -				 * Not the same free entry,
    -				 * just check its length.
    -				 */
    -				if (be16_to_cpu(dup->length) < len) {
    -					dup = NULL;
    -				}
    -			}
    -		}
    -		compact = 0;
    -	}
    -	/*
    -	 * If there are stale entries we'll use one for the leaf.
    -	 * Is the biggest entry enough to avoid compaction?
    -	 */
    -	else if (be16_to_cpu(bf[0].length) >= len) {
    -		dup = (xfs_dir2_data_unused_t *)
    -		      ((char *)block + be16_to_cpu(bf[0].offset));
    -		compact = 0;
    -	}
    -	/*
    -	 * Will need to compact to make this work.
    -	 */
    -	else {
    -		/*
    -		 * Tag just before the first leaf entry.
    -		 */
    -		tagp = (__be16 *)blp - 1;
    -		/*
    -		 * Data object just before the first leaf entry.
    -		 */
    -		dup = (xfs_dir2_data_unused_t *)((char *)block + be16_to_cpu(*tagp));
    -		/*
    -		 * If it's not free then the data will go where the
    -		 * leaf data starts now, if it works at all.
    -		 */
    -		if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
    -			if (be16_to_cpu(dup->length) + (be32_to_cpu(btp->stale) - 1) *
    -			    (uint)sizeof(*blp) < len)
    -				dup = NULL;
    -		} else if ((be32_to_cpu(btp->stale) - 1) * (uint)sizeof(*blp) < len)
    -			dup = NULL;
    -		else
    -			dup = (xfs_dir2_data_unused_t *)blp;
    -		compact = 1;
    -	}
    -	/*
    -	 * If this isn't a real add, we're done with the buffer.
    -	 */
    -	if (args->justcheck)
    -		xfs_da_brelse(tp, bp);
    -	/*
    -	 * If we don't have space for the new entry & leaf ...
    -	 */
    -	if (!dup) {
    -		/*
    -		 * Not trying to actually do anything, or don't have
    -		 * a space reservation: return no-space.
    -		 */
    -		if (args->justcheck || args->total == 0)
    -			return XFS_ERROR(ENOSPC);
    -		/*
    -		 * Convert to the next larger format.
    -		 * Then add the new entry in that format.
    -		 */
    -		error = xfs_dir2_block_to_leaf(args, bp);
    -		xfs_da_buf_done(bp);
    -		if (error)
    -			return error;
    -		return xfs_dir2_leaf_addname(args);
    -	}
    -	/*
    -	 * Just checking, and it would work, so say so.
    -	 */
    -	if (args->justcheck)
    -		return 0;
    -	needlog = needscan = 0;
    -	/*
    -	 * If need to compact the leaf entries, do it now.
    -	 * Leave the highest-numbered stale entry stale.
    -	 * XXX should be the one closest to mid but mid is not yet computed.
    -	 */
    -	if (compact) {
    -		int	fromidx;		/* source leaf index */
    -		int	toidx;			/* target leaf index */
    -
    -		for (fromidx = toidx = be32_to_cpu(btp->count) - 1,
    -			highstale = lfloghigh = -1;
    -		     fromidx >= 0;
    -		     fromidx--) {
    -			if (be32_to_cpu(blp[fromidx].address) == XFS_DIR2_NULL_DATAPTR) {
    -				if (highstale == -1)
    -					highstale = toidx;
    -				else {
    -					if (lfloghigh == -1)
    -						lfloghigh = toidx;
    -					continue;
    -				}
    -			}
    -			if (fromidx < toidx)
    -				blp[toidx] = blp[fromidx];
    -			toidx--;
    -		}
    -		lfloglow = toidx + 1 - (be32_to_cpu(btp->stale) - 1);
    -		lfloghigh -= be32_to_cpu(btp->stale) - 1;
    -		be32_add(&btp->count, -(be32_to_cpu(btp->stale) - 1));
    -		xfs_dir2_data_make_free(tp, bp,
    -			(xfs_dir2_data_aoff_t)((char *)blp - (char *)block),
    -			(xfs_dir2_data_aoff_t)((be32_to_cpu(btp->stale) - 1) * sizeof(*blp)),
    -			&needlog, &needscan);
    -		blp += be32_to_cpu(btp->stale) - 1;
    -		btp->stale = cpu_to_be32(1);
    -		/*
    -		 * If we now need to rebuild the bestfree map, do so.
    -		 * This needs to happen before the next call to use_free.
    -		 */
    -		if (needscan) {
    -			xfs_dir2_data_freescan(mp, (xfs_dir2_data_t *)block,
    -				&needlog, NULL);
    -			needscan = 0;
    -		}
    -	}
    -	/*
    -	 * Set leaf logging boundaries to impossible state.
    -	 * For the no-stale case they're set explicitly.
    -	 */
    -	else if (btp->stale) {
    -		lfloglow = be32_to_cpu(btp->count);
    -		lfloghigh = -1;
    -	}
    -	/*
    -	 * Find the slot that's first lower than our hash value, -1 if none.
    -	 */
    -	for (low = 0, high = be32_to_cpu(btp->count) - 1; low <= high; ) {
    -		mid = (low + high) >> 1;
    -		if ((hash = be32_to_cpu(blp[mid].hashval)) == args->hashval)
    -			break;
    -		if (hash < args->hashval)
    -			low = mid + 1;
    -		else
    -			high = mid - 1;
    -	}
    -	while (mid >= 0 && be32_to_cpu(blp[mid].hashval) >= args->hashval) {
    -		mid--;
    -	}
    -	/*
    -	 * No stale entries, will use enddup space to hold new leaf.
    -	 */
    -	if (!btp->stale) {
    -		/*
    -		 * Mark the space needed for the new leaf entry, now in use.
    -		 */
    -		xfs_dir2_data_use_free(tp, bp, enddup,
    -			(xfs_dir2_data_aoff_t)
    -			((char *)enddup - (char *)block + be16_to_cpu(enddup->length) -
    -			 sizeof(*blp)),
    -			(xfs_dir2_data_aoff_t)sizeof(*blp),
    -			&needlog, &needscan);
    -		/*
    -		 * Update the tail (entry count).
    -		 */
    -		be32_add(&btp->count, 1);
    -		/*
    -		 * If we now need to rebuild the bestfree map, do so.
    -		 * This needs to happen before the next call to use_free.
    -		 */
    -		if (needscan) {
    -			xfs_dir2_data_freescan(mp, (xfs_dir2_data_t *)block,
    -				&needlog, NULL);
    -			needscan = 0;
    -		}
    -		/*
    -		 * Adjust pointer to the first leaf entry, we're about to move
    -		 * the table up one to open up space for the new leaf entry.
    -		 * Then adjust our index to match.
    -		 */
    -		blp--;
    -		mid++;
    -		if (mid)
    -			memmove(blp, &blp[1], mid * sizeof(*blp));
    -		lfloglow = 0;
    -		lfloghigh = mid;
    -	}
    -	/*
    -	 * Use a stale leaf for our new entry.
    -	 */
    -	else {
    -		for (lowstale = mid;
    -		     lowstale >= 0 &&
    -			be32_to_cpu(blp[lowstale].address) != XFS_DIR2_NULL_DATAPTR;
    -		     lowstale--)
    -			continue;
    -		for (highstale = mid + 1;
    -		     highstale < be32_to_cpu(btp->count) &&
    -			be32_to_cpu(blp[highstale].address) != XFS_DIR2_NULL_DATAPTR &&
    -			(lowstale < 0 || mid - lowstale > highstale - mid);
    -		     highstale++)
    -			continue;
    -		/*
    -		 * Move entries toward the low-numbered stale entry.
    -		 */
    -		if (lowstale >= 0 &&
    -		    (highstale == be32_to_cpu(btp->count) ||
    -		     mid - lowstale <= highstale - mid)) {
    -			if (mid - lowstale)
    -				memmove(&blp[lowstale], &blp[lowstale + 1],
    -					(mid - lowstale) * sizeof(*blp));
    -			lfloglow = MIN(lowstale, lfloglow);
    -			lfloghigh = MAX(mid, lfloghigh);
    -		}
    -		/*
    -		 * Move entries toward the high-numbered stale entry.
    -		 */
    -		else {
    -			ASSERT(highstale < be32_to_cpu(btp->count));
    -			mid++;
    -			if (highstale - mid)
    -				memmove(&blp[mid + 1], &blp[mid],
    -					(highstale - mid) * sizeof(*blp));
    -			lfloglow = MIN(mid, lfloglow);
    -			lfloghigh = MAX(highstale, lfloghigh);
    -		}
    -		be32_add(&btp->stale, -1);
    -	}
    -	/*
    -	 * Point to the new data entry.
    -	 */
    -	dep = (xfs_dir2_data_entry_t *)dup;
    -	/*
    -	 * Fill in the leaf entry.
    -	 */
    -	blp[mid].hashval = cpu_to_be32(args->hashval);
    -	blp[mid].address = cpu_to_be32(XFS_DIR2_BYTE_TO_DATAPTR(mp,
    -				(char *)dep - (char *)block));
    -	xfs_dir2_block_log_leaf(tp, bp, lfloglow, lfloghigh);
    -	/*
    -	 * Mark space for the data entry used.
    -	 */
    -	xfs_dir2_data_use_free(tp, bp, dup,
    -		(xfs_dir2_data_aoff_t)((char *)dup - (char *)block),
    -		(xfs_dir2_data_aoff_t)len, &needlog, &needscan);
    -	/*
    -	 * Create the new data entry.
    -	 */
    -	INT_SET(dep->inumber, ARCH_CONVERT, args->inumber);
    -	dep->namelen = args->namelen;
    -	memcpy(dep->name, args->name, args->namelen);
    -	tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
    -	*tagp = cpu_to_be16((char *)dep - (char *)block);
    -	/*
    -	 * Clean up the bestfree array and log the header, tail, and entry.
    -	 */
    -	if (needscan)
    -		xfs_dir2_data_freescan(mp, (xfs_dir2_data_t *)block, &needlog,
    -			NULL);
    -	if (needlog)
    -		xfs_dir2_data_log_header(tp, bp);
    -	xfs_dir2_block_log_tail(tp, bp);
    -	xfs_dir2_data_log_entry(tp, bp, dep);
    -	xfs_dir2_data_check(dp, bp);
    -	xfs_da_buf_done(bp);
    -	return 0;
    -}
    -
    -/*
    - * Readdir for block directories.
    - */
    -int						/* error */
    -xfs_dir2_block_getdents(
    -	xfs_trans_t		*tp,		/* transaction (NULL) */
    -	xfs_inode_t		*dp,		/* incore inode */
    -	uio_t			*uio,		/* caller's buffer control */
    -	int			*eofp,		/* eof reached? (out) */
    -	xfs_dirent_t		*dbp,		/* caller's buffer */
    -	xfs_dir2_put_t		put)		/* abi's formatting function */
    -{
    -	xfs_dir2_block_t	*block;		/* directory block structure */
    -	xfs_dabuf_t		*bp;		/* buffer for block */
    -	xfs_dir2_block_tail_t	*btp;		/* block tail */
    -	xfs_dir2_data_entry_t	*dep;		/* block data entry */
    -	xfs_dir2_data_unused_t	*dup;		/* block unused entry */
    -	char			*endptr;	/* end of the data entries */
    -	int			error;		/* error return value */
    -	xfs_mount_t		*mp;		/* filesystem mount point */
    -	xfs_dir2_put_args_t	p;		/* arg package for put rtn */
    -	char			*ptr;		/* current data entry */
    -	int			wantoff;	/* starting block offset */
    -
    -	mp = dp->i_mount;
    -	/*
    -	 * If the block number in the offset is out of range, we're done.
    -	 */
    -	if (XFS_DIR2_DATAPTR_TO_DB(mp, uio->uio_offset) > mp->m_dirdatablk) {
    -		*eofp = 1;
    -		return 0;
    -	}
    -	/*
    -	 * Can't read the block, give up, else get dabuf in bp.
    -	 */
    -	if ((error =
    -	    xfs_da_read_buf(tp, dp, mp->m_dirdatablk, -1, &bp, XFS_DATA_FORK))) {
    -		return error;
    -	}
    -	ASSERT(bp != NULL);
    -	/*
    -	 * Extract the byte offset we start at from the seek pointer.
    -	 * We'll skip entries before this.
    -	 */
    -	wantoff = XFS_DIR2_DATAPTR_TO_OFF(mp, uio->uio_offset);
    -	block = bp->data;
    -	xfs_dir2_data_check(dp, bp);
    -	/*
    -	 * Set up values for the loop.
    -	 */
    -	btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
    -	ptr = (char *)block->u;
    -	endptr = (char *)XFS_DIR2_BLOCK_LEAF_P(btp);
    -	p.dbp = dbp;
    -	p.put = put;
    -	p.uio = uio;
    -	/*
    -	 * Loop over the data portion of the block.
    -	 * Each object is a real entry (dep) or an unused one (dup).
    -	 */
    -	while (ptr < endptr) {
    -		dup = (xfs_dir2_data_unused_t *)ptr;
    -		/*
    -		 * Unused, skip it.
    -		 */
    -		if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
    -			ptr += be16_to_cpu(dup->length);
    -			continue;
    -		}
    -
    -		dep = (xfs_dir2_data_entry_t *)ptr;
    -
    -		/*
    -		 * Bump pointer for the next iteration.
    -		 */
    -		ptr += XFS_DIR2_DATA_ENTSIZE(dep->namelen);
    -		/*
    -		 * The entry is before the desired starting point, skip it.
    -		 */
    -		if ((char *)dep - (char *)block < wantoff)
    -			continue;
    -		/*
    -		 * Set up argument structure for put routine.
    -		 */
    -		p.namelen = dep->namelen;
    -
    -		p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
    -						    ptr - (char *)block);
    -		p.ino = INT_GET(dep->inumber, ARCH_CONVERT);
    -#if XFS_BIG_INUMS
    -		p.ino += mp->m_inoadd;
    -#endif
    -		p.name = (char *)dep->name;
    -
    -		/*
    -		 * Put the entry in the caller's buffer.
    -		 */
    -		error = p.put(&p);
    -
    -		/*
    -		 * If it didn't fit, set the final offset to here & return.
    -		 */
    -		if (!p.done) {
    -			uio->uio_offset =
    -				XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
    -					(char *)dep - (char *)block);
    -			xfs_da_brelse(tp, bp);
    -			return error;
    -		}
    -	}
    -
    -	/*
    -	 * Reached the end of the block.
    -	 * Set the offset to a non-existent block 1 and return.
    -	 */
    -	*eofp = 1;
    -
    -	uio->uio_offset =
    -		XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk + 1, 0);
    -
    -	xfs_da_brelse(tp, bp);
    -
    -	return 0;
    -}
    -
    -/*
    - * Log leaf entries from the block.
    - */
    -static void
    -xfs_dir2_block_log_leaf(
    -	xfs_trans_t		*tp,		/* transaction structure */
    -	xfs_dabuf_t		*bp,		/* block buffer */
    -	int			first,		/* index of first logged leaf */
    -	int			last)		/* index of last logged leaf */
    -{
    -	xfs_dir2_block_t	*block;		/* directory block structure */
    -	xfs_dir2_leaf_entry_t	*blp;		/* block leaf entries */
    -	xfs_dir2_block_tail_t	*btp;		/* block tail */
    -	xfs_mount_t		*mp;		/* filesystem mount point */
    -
    -	mp = tp->t_mountp;
    -	block = bp->data;
    -	btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
    -	blp = XFS_DIR2_BLOCK_LEAF_P(btp);
    -	xfs_da_log_buf(tp, bp, (uint)((char *)&blp[first] - (char *)block),
    -		(uint)((char *)&blp[last + 1] - (char *)block - 1));
    -}
    -
    -/*
    - * Log the block tail.
    - */
    -static void
    -xfs_dir2_block_log_tail(
    -	xfs_trans_t		*tp,		/* transaction structure */
    -	xfs_dabuf_t		*bp)		/* block buffer */
    -{
    -	xfs_dir2_block_t	*block;		/* directory block structure */
    -	xfs_dir2_block_tail_t	*btp;		/* block tail */
    -	xfs_mount_t		*mp;		/* filesystem mount point */
    -
    -	mp = tp->t_mountp;
    -	block = bp->data;
    -	btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
    -	xfs_da_log_buf(tp, bp, (uint)((char *)btp - (char *)block),
    -		(uint)((char *)(btp + 1) - (char *)block - 1));
    -}
    -
    -/*
    - * Look up an entry in the block.  This is the external routine,
    - * xfs_dir2_block_lookup_int does the real work.
    - */
    -int						/* error */
    -xfs_dir2_block_lookup(
    -	xfs_da_args_t		*args)		/* dir lookup arguments */
    -{
    -	xfs_dir2_block_t	*block;		/* block structure */
    -	xfs_dir2_leaf_entry_t	*blp;		/* block leaf entries */
    -	xfs_dabuf_t		*bp;		/* block buffer */
    -	xfs_dir2_block_tail_t	*btp;		/* block tail */
    -	xfs_dir2_data_entry_t	*dep;		/* block data entry */
    -	xfs_inode_t		*dp;		/* incore inode */
    -	int			ent;		/* entry index */
    -	int			error;		/* error return value */
    -	xfs_mount_t		*mp;		/* filesystem mount point */
    -
    -	xfs_dir2_trace_args("block_lookup", args);
    -	/*
    -	 * Get the buffer, look up the entry.
    -	 * If not found (ENOENT) then return, have no buffer.
    -	 */
    -	if ((error = xfs_dir2_block_lookup_int(args, &bp, &ent)))
    -		return error;
    -	dp = args->dp;
    -	mp = dp->i_mount;
    -	block = bp->data;
    -	xfs_dir2_data_check(dp, bp);
    -	btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
    -	blp = XFS_DIR2_BLOCK_LEAF_P(btp);
    -	/*
    -	 * Get the offset from the leaf entry, to point to the data.
    -	 */
    -	dep = (xfs_dir2_data_entry_t *)
    -	      ((char *)block + XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(blp[ent].address)));
    -	/*
    -	 * Fill in inode number, release the block.
    -	 */
    -	args->inumber = INT_GET(dep->inumber, ARCH_CONVERT);
    -	xfs_da_brelse(args->trans, bp);
    -	return XFS_ERROR(EEXIST);
    -}
    -
    -/*
    - * Internal block lookup routine.
    - */
    -static int					/* error */
    -xfs_dir2_block_lookup_int(
    -	xfs_da_args_t		*args,		/* dir lookup arguments */
    -	xfs_dabuf_t		**bpp,		/* returned block buffer */
    -	int			*entno)		/* returned entry number */
    -{
    -	xfs_dir2_dataptr_t	addr;		/* data entry address */
    -	xfs_dir2_block_t	*block;		/* block structure */
    -	xfs_dir2_leaf_entry_t	*blp;		/* block leaf entries */
    -	xfs_dabuf_t		*bp;		/* block buffer */
    -	xfs_dir2_block_tail_t	*btp;		/* block tail */
    -	xfs_dir2_data_entry_t	*dep;		/* block data entry */
    -	xfs_inode_t		*dp;		/* incore inode */
    -	int			error;		/* error return value */
    -	xfs_dahash_t		hash;		/* found hash value */
    -	int			high;		/* binary search high index */
    -	int			low;		/* binary search low index */
    -	int			mid;		/* binary search current idx */
    -	xfs_mount_t		*mp;		/* filesystem mount point */
    -	xfs_trans_t		*tp;		/* transaction pointer */
    -
    -	dp = args->dp;
    -	tp = args->trans;
    -	mp = dp->i_mount;
    -	/*
    -	 * Read the buffer, return error if we can't get it.
    -	 */
    -	if ((error =
    -	    xfs_da_read_buf(tp, dp, mp->m_dirdatablk, -1, &bp, XFS_DATA_FORK))) {
    -		return error;
    -	}
    -	ASSERT(bp != NULL);
    -	block = bp->data;
    -	xfs_dir2_data_check(dp, bp);
    -	btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
    -	blp = XFS_DIR2_BLOCK_LEAF_P(btp);
    -	/*
    -	 * Loop doing a binary search for our hash value.
    -	 * Find our entry, ENOENT if it's not there.
    -	 */
    -	for (low = 0, high = be32_to_cpu(btp->count) - 1; ; ) {
    -		ASSERT(low <= high);
    -		mid = (low + high) >> 1;
    -		if ((hash = be32_to_cpu(blp[mid].hashval)) == args->hashval)
    -			break;
    -		if (hash < args->hashval)
    -			low = mid + 1;
    -		else
    -			high = mid - 1;
    -		if (low > high) {
    -			ASSERT(args->oknoent);
    -			xfs_da_brelse(tp, bp);
    -			return XFS_ERROR(ENOENT);
    -		}
    -	}
    -	/*
    -	 * Back up to the first one with the right hash value.
    -	 */
    -	while (mid > 0 && be32_to_cpu(blp[mid - 1].hashval) == args->hashval) {
    -		mid--;
    -	}
    -	/*
    -	 * Now loop forward through all the entries with the
    -	 * right hash value looking for our name.
    -	 */
    -	do {
    -		if ((addr = be32_to_cpu(blp[mid].address)) == XFS_DIR2_NULL_DATAPTR)
    -			continue;
    -		/*
    -		 * Get pointer to the entry from the leaf.
    -		 */
    -		dep = (xfs_dir2_data_entry_t *)
    -			((char *)block + XFS_DIR2_DATAPTR_TO_OFF(mp, addr));
    -		/*
    -		 * Compare, if it's right give back buffer & entry number.
    -		 */
    -		if (dep->namelen == args->namelen &&
    -		    dep->name[0] == args->name[0] &&
    -		    memcmp(dep->name, args->name, args->namelen) == 0) {
    -			*bpp = bp;
    -			*entno = mid;
    -			return 0;
    -		}
    -	} while (++mid < be32_to_cpu(btp->count) && be32_to_cpu(blp[mid].hashval) == hash);
    -	/*
    -	 * No match, release the buffer and return ENOENT.
    -	 */
    -	ASSERT(args->oknoent);
    -	xfs_da_brelse(tp, bp);
    -	return XFS_ERROR(ENOENT);
    -}
    -
    -/*
    - * Remove an entry from a block format directory.
    - * If that makes the block small enough to fit in shortform, transform it.
    - */
    -int						/* error */
    -xfs_dir2_block_removename(
    -	xfs_da_args_t		*args)		/* directory operation args */
    -{
    -	xfs_dir2_block_t	*block;		/* block structure */
    -	xfs_dir2_leaf_entry_t	*blp;		/* block leaf pointer */
    -	xfs_dabuf_t		*bp;		/* block buffer */
    -	xfs_dir2_block_tail_t	*btp;		/* block tail */
    -	xfs_dir2_data_entry_t	*dep;		/* block data entry */
    -	xfs_inode_t		*dp;		/* incore inode */
    -	int			ent;		/* block leaf entry index */
    -	int			error;		/* error return value */
    -	xfs_mount_t		*mp;		/* filesystem mount point */
    -	int			needlog;	/* need to log block header */
    -	int			needscan;	/* need to fixup bestfree */
    -	xfs_dir2_sf_hdr_t	sfh;		/* shortform header */
    -	int			size;		/* shortform size */
    -	xfs_trans_t		*tp;		/* transaction pointer */
    -
    -	xfs_dir2_trace_args("block_removename", args);
    -	/*
    -	 * Look up the entry in the block.  Gets the buffer and entry index.
    -	 * It will always be there, the vnodeops level does a lookup first.
    -	 */
    -	if ((error = xfs_dir2_block_lookup_int(args, &bp, &ent))) {
    -		return error;
    -	}
    -	dp = args->dp;
    -	tp = args->trans;
    -	mp = dp->i_mount;
    -	block = bp->data;
    -	btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
    -	blp = XFS_DIR2_BLOCK_LEAF_P(btp);
    -	/*
    -	 * Point to the data entry using the leaf entry.
    -	 */
    -	dep = (xfs_dir2_data_entry_t *)
    -	      ((char *)block + XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(blp[ent].address)));
    -	/*
    -	 * Mark the data entry's space free.
    -	 */
    -	needlog = needscan = 0;
    -	xfs_dir2_data_make_free(tp, bp,
    -		(xfs_dir2_data_aoff_t)((char *)dep - (char *)block),
    -		XFS_DIR2_DATA_ENTSIZE(dep->namelen), &needlog, &needscan);
    -	/*
    -	 * Fix up the block tail.
    -	 */
    -	be32_add(&btp->stale, 1);
    -	xfs_dir2_block_log_tail(tp, bp);
    -	/*
    -	 * Remove the leaf entry by marking it stale.
    -	 */
    -	blp[ent].address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR);
    -	xfs_dir2_block_log_leaf(tp, bp, ent, ent);
    -	/*
    -	 * Fix up bestfree, log the header if necessary.
    -	 */
    -	if (needscan)
    -		xfs_dir2_data_freescan(mp, (xfs_dir2_data_t *)block, &needlog,
    -			NULL);
    -	if (needlog)
    -		xfs_dir2_data_log_header(tp, bp);
    -	xfs_dir2_data_check(dp, bp);
    -	/*
    -	 * See if the size as a shortform is good enough.
    -	 */
    -	if ((size = xfs_dir2_block_sfsize(dp, block, &sfh)) >
    -	    XFS_IFORK_DSIZE(dp)) {
    -		xfs_da_buf_done(bp);
    -		return 0;
    -	}
    -	/*
    -	 * If it works, do the conversion.
    -	 */
    -	return xfs_dir2_block_to_sf(args, bp, size, &sfh);
    -}
    -
    -/*
    - * Replace an entry in a V2 block directory.
    - * Change the inode number to the new value.
    - */
    -int						/* error */
    -xfs_dir2_block_replace(
    -	xfs_da_args_t		*args)		/* directory operation args */
    -{
    -	xfs_dir2_block_t	*block;		/* block structure */
    -	xfs_dir2_leaf_entry_t	*blp;		/* block leaf entries */
    -	xfs_dabuf_t		*bp;		/* block buffer */
    -	xfs_dir2_block_tail_t	*btp;		/* block tail */
    -	xfs_dir2_data_entry_t	*dep;		/* block data entry */
    -	xfs_inode_t		*dp;		/* incore inode */
    -	int			ent;		/* leaf entry index */
    -	int			error;		/* error return value */
    -	xfs_mount_t		*mp;		/* filesystem mount point */
    -
    -	xfs_dir2_trace_args("block_replace", args);
    -	/*
    -	 * Lookup the entry in the directory.  Get buffer and entry index.
    -	 * This will always succeed since the caller has already done a lookup.
    -	 */
    -	if ((error = xfs_dir2_block_lookup_int(args, &bp, &ent))) {
    -		return error;
    -	}
    -	dp = args->dp;
    -	mp = dp->i_mount;
    -	block = bp->data;
    -	btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
    -	blp = XFS_DIR2_BLOCK_LEAF_P(btp);
    -	/*
    -	 * Point to the data entry we need to change.
    -	 */
    -	dep = (xfs_dir2_data_entry_t *)
    -	      ((char *)block + XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(blp[ent].address)));
    -	ASSERT(INT_GET(dep->inumber, ARCH_CONVERT) != args->inumber);
    -	/*
    -	 * Change the inode number to the new value.
    -	 */
    -	INT_SET(dep->inumber, ARCH_CONVERT, args->inumber);
    -	xfs_dir2_data_log_entry(args->trans, bp, dep);
    -	xfs_dir2_data_check(dp, bp);
    -	xfs_da_buf_done(bp);
    -	return 0;
    -}
    -
    -/*
    - * Qsort comparison routine for the block leaf entries.
    - */
    -static int					/* sort order */
    -xfs_dir2_block_sort(
    -	const void			*a,	/* first leaf entry */
    -	const void			*b)	/* second leaf entry */
    -{
    -	const xfs_dir2_leaf_entry_t	*la;	/* first leaf entry */
    -	const xfs_dir2_leaf_entry_t	*lb;	/* second leaf entry */
    -
    -	la = a;
    -	lb = b;
    -	return be32_to_cpu(la->hashval) < be32_to_cpu(lb->hashval) ? -1 :
    -		(be32_to_cpu(la->hashval) > be32_to_cpu(lb->hashval) ? 1 : 0);
    -}
    -
    -/*
    - * Convert a V2 leaf directory to a V2 block directory if possible.
    - */
    -int						/* error */
    -xfs_dir2_leaf_to_block(
    -	xfs_da_args_t		*args,		/* operation arguments */
    -	xfs_dabuf_t		*lbp,		/* leaf buffer */
    -	xfs_dabuf_t		*dbp)		/* data buffer */
    -{
    -	__be16			*bestsp;	/* leaf bests table */
    -	xfs_dir2_block_t	*block;		/* block structure */
    -	xfs_dir2_block_tail_t	*btp;		/* block tail */
    -	xfs_inode_t		*dp;		/* incore directory inode */
    -	xfs_dir2_data_unused_t	*dup;		/* unused data entry */
    -	int			error;		/* error return value */
    -	int			from;		/* leaf from index */
    -	xfs_dir2_leaf_t		*leaf;		/* leaf structure */
    -	xfs_dir2_leaf_entry_t	*lep;		/* leaf entry */
    -	xfs_dir2_leaf_tail_t	*ltp;		/* leaf tail structure */
    -	xfs_mount_t		*mp;		/* file system mount point */
    -	int			needlog;	/* need to log data header */
    -	int			needscan;	/* need to scan for bestfree */
    -	xfs_dir2_sf_hdr_t	sfh;		/* shortform header */
    -	int			size;		/* bytes used */
    -	__be16			*tagp;		/* end of entry (tag) */
    -	int			to;		/* block/leaf to index */
    -	xfs_trans_t		*tp;		/* transaction pointer */
    -
    -	xfs_dir2_trace_args_bb("leaf_to_block", args, lbp, dbp);
    -	dp = args->dp;
    -	tp = args->trans;
    -	mp = dp->i_mount;
    -	leaf = lbp->data;
    -	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC);
    -	ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
    -	/*
    -	 * If there are data blocks other than the first one, take this
    -	 * opportunity to remove trailing empty data blocks that may have
    -	 * been left behind during no-space-reservation operations.
    -	 * These will show up in the leaf bests table.
    -	 */
    -	while (dp->i_d.di_size > mp->m_dirblksize) {
    -		bestsp = XFS_DIR2_LEAF_BESTS_P(ltp);
    -		if (be16_to_cpu(bestsp[be32_to_cpu(ltp->bestcount) - 1]) ==
    -		    mp->m_dirblksize - (uint)sizeof(block->hdr)) {
    -			if ((error =
    -			    xfs_dir2_leaf_trim_data(args, lbp,
    -				    (xfs_dir2_db_t)(be32_to_cpu(ltp->bestcount) - 1))))
    -				goto out;
    -		} else {
    -			error = 0;
    -			goto out;
    -		}
    -	}
    -	/*
    -	 * Read the data block if we don't already have it, give up if it fails.
    -	 */
    -	if (dbp == NULL &&
    -	    (error = xfs_da_read_buf(tp, dp, mp->m_dirdatablk, -1, &dbp,
    -		    XFS_DATA_FORK))) {
    -		goto out;
    -	}
    -	block = dbp->data;
    -	ASSERT(be32_to_cpu(block->hdr.magic) == XFS_DIR2_DATA_MAGIC);
    -	/*
    -	 * Size of the "leaf" area in the block.
    -	 */
    -	size = (uint)sizeof(block->tail) +
    -	       (uint)sizeof(*lep) * (be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale));
    -	/*
    -	 * Look at the last data entry.
    -	 */
    -	tagp = (__be16 *)((char *)block + mp->m_dirblksize) - 1;
    -	dup = (xfs_dir2_data_unused_t *)((char *)block + be16_to_cpu(*tagp));
    -	/*
    -	 * If it's not free or is too short we can't do it.
    -	 */
    -	if (be16_to_cpu(dup->freetag) != XFS_DIR2_DATA_FREE_TAG ||
    -	    be16_to_cpu(dup->length) < size) {
    -		error = 0;
    -		goto out;
    -	}
    -	/*
    -	 * Start converting it to block form.
    -	 */
    -	block->hdr.magic = cpu_to_be32(XFS_DIR2_BLOCK_MAGIC);
    -	needlog = 1;
    -	needscan = 0;
    -	/*
    -	 * Use up the space at the end of the block (blp/btp).
    -	 */
    -	xfs_dir2_data_use_free(tp, dbp, dup, mp->m_dirblksize - size, size,
    -		&needlog, &needscan);
    -	/*
    -	 * Initialize the block tail.
    -	 */
    -	btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
    -	btp->count = cpu_to_be32(be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale));
    -	btp->stale = 0;
    -	xfs_dir2_block_log_tail(tp, dbp);
    -	/*
    -	 * Initialize the block leaf area.  We compact out stale entries.
    -	 */
    -	lep = XFS_DIR2_BLOCK_LEAF_P(btp);
    -	for (from = to = 0; from < be16_to_cpu(leaf->hdr.count); from++) {
    -		if (be32_to_cpu(leaf->ents[from].address) == XFS_DIR2_NULL_DATAPTR)
    -			continue;
    -		lep[to++] = leaf->ents[from];
    -	}
    -	ASSERT(to == be32_to_cpu(btp->count));
    -	xfs_dir2_block_log_leaf(tp, dbp, 0, be32_to_cpu(btp->count) - 1);
    -	/*
    -	 * Scan the bestfree if we need it and log the data block header.
    -	 */
    -	if (needscan)
    -		xfs_dir2_data_freescan(mp, (xfs_dir2_data_t *)block, &needlog,
    -			NULL);
    -	if (needlog)
    -		xfs_dir2_data_log_header(tp, dbp);
    -	/*
    -	 * Pitch the old leaf block.
    -	 */
    -	error = xfs_da_shrink_inode(args, mp->m_dirleafblk, lbp);
    -	lbp = NULL;
    -	if (error) {
    -		goto out;
    -	}
    -	/*
    -	 * Now see if the resulting block can be shrunken to shortform.
    -	 */
    -	if ((size = xfs_dir2_block_sfsize(dp, block, &sfh)) >
    -	    XFS_IFORK_DSIZE(dp)) {
    -		error = 0;
    -		goto out;
    -	}
    -	return xfs_dir2_block_to_sf(args, dbp, size, &sfh);
    -out:
    -	if (lbp)
    -		xfs_da_buf_done(lbp);
    -	if (dbp)
    -		xfs_da_buf_done(dbp);
    -	return error;
    -}
    -
    -/*
    - * Convert the shortform directory to block form.
    - */
    -int						/* error */
    -xfs_dir2_sf_to_block(
    -	xfs_da_args_t		*args)		/* operation arguments */
    -{
    -	xfs_dir2_db_t		blkno;		/* dir-relative block # (0) */
    -	xfs_dir2_block_t	*block;		/* block structure */
    -	xfs_dir2_leaf_entry_t	*blp;		/* block leaf entries */
    -	xfs_dabuf_t		*bp;		/* block buffer */
    -	xfs_dir2_block_tail_t	*btp;		/* block tail pointer */
    -	char			*buf;		/* sf buffer */
    -	int			buf_len;
    -	xfs_dir2_data_entry_t	*dep;		/* data entry pointer */
    -	xfs_inode_t		*dp;		/* incore directory inode */
    -	int			dummy;		/* trash */
    -	xfs_dir2_data_unused_t	*dup;		/* unused entry pointer */
    -	int			endoffset;	/* end of data objects */
    -	int			error;		/* error return value */
    -	int			i;		/* index */
    -	xfs_mount_t		*mp;		/* filesystem mount point */
    -	int			needlog;	/* need to log block header */
    -	int			needscan;	/* need to scan block freespc */
    -	int			newoffset;	/* offset from current entry */
    -	int			offset;		/* target block offset */
    -	xfs_dir2_sf_entry_t	*sfep;		/* sf entry pointer */
    -	xfs_dir2_sf_t		*sfp;		/* shortform structure */
    -	__be16			*tagp;		/* end of data entry */
    -	xfs_trans_t		*tp;		/* transaction pointer */
    -
    -	xfs_dir2_trace_args("sf_to_block", args);
    -	dp = args->dp;
    -	tp = args->trans;
    -	mp = dp->i_mount;
    -	ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
    -	/*
    -	 * Bomb out if the shortform directory is way too short.
    -	 */
    -	if (dp->i_d.di_size < offsetof(xfs_dir2_sf_hdr_t, parent)) {
    -		ASSERT(XFS_FORCED_SHUTDOWN(mp));
    -		return XFS_ERROR(EIO);
    -	}
    -	ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
    -	ASSERT(dp->i_df.if_u1.if_data != NULL);
    -	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
    -	ASSERT(dp->i_d.di_size >= XFS_DIR2_SF_HDR_SIZE(sfp->hdr.i8count));
    -	/*
    -	 * Copy the directory into the stack buffer.
    -	 * Then pitch the incore inode data so we can make extents.
    -	 */
    -
    -	buf_len = dp->i_df.if_bytes;
    -	buf = kmem_alloc(dp->i_df.if_bytes, KM_SLEEP);
    -
    -	memcpy(buf, sfp, dp->i_df.if_bytes);
    -	xfs_idata_realloc(dp, -dp->i_df.if_bytes, XFS_DATA_FORK);
    -	dp->i_d.di_size = 0;
    -	xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
    -	/*
    -	 * Reset pointer - old sfp is gone.
    -	 */
    -	sfp = (xfs_dir2_sf_t *)buf;
    -	/*
    -	 * Add block 0 to the inode.
    -	 */
    -	error = xfs_dir2_grow_inode(args, XFS_DIR2_DATA_SPACE, &blkno);
    -	if (error) {
    -		kmem_free(buf, buf_len);
    -		return error;
    -	}
    -	/*
    -	 * Initialize the data block.
    -	 */
    -	error = xfs_dir2_data_init(args, blkno, &bp);
    -	if (error) {
    -		kmem_free(buf, buf_len);
    -		return error;
    -	}
    -	block = bp->data;
    -	block->hdr.magic = cpu_to_be32(XFS_DIR2_BLOCK_MAGIC);
    -	/*
    -	 * Compute size of block "tail" area.
    -	 */
    -	i = (uint)sizeof(*btp) +
    -	    (sfp->hdr.count + 2) * (uint)sizeof(xfs_dir2_leaf_entry_t);
    -	/*
    -	 * The whole thing is initialized to free by the init routine.
    -	 * Say we're using the leaf and tail area.
    -	 */
    -	dup = (xfs_dir2_data_unused_t *)block->u;
    -	needlog = needscan = 0;
    -	xfs_dir2_data_use_free(tp, bp, dup, mp->m_dirblksize - i, i, &needlog,
    -		&needscan);
    -	ASSERT(needscan == 0);
    -	/*
    -	 * Fill in the tail.
    -	 */
    -	btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
    -	btp->count = cpu_to_be32(sfp->hdr.count + 2);	/* ., .. */
    -	btp->stale = 0;
    -	blp = XFS_DIR2_BLOCK_LEAF_P(btp);
    -	endoffset = (uint)((char *)blp - (char *)block);
    -	/*
    -	 * Remove the freespace, we'll manage it.
    -	 */
    -	xfs_dir2_data_use_free(tp, bp, dup,
    -		(xfs_dir2_data_aoff_t)((char *)dup - (char *)block),
    -		be16_to_cpu(dup->length), &needlog, &needscan);
    -	/*
    -	 * Create entry for .
    -	 */
    -	dep = (xfs_dir2_data_entry_t *)
    -	      ((char *)block + XFS_DIR2_DATA_DOT_OFFSET);
    -	INT_SET(dep->inumber, ARCH_CONVERT, dp->i_ino);
    -	dep->namelen = 1;
    -	dep->name[0] = '.';
    -	tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
    -	*tagp = cpu_to_be16((char *)dep - (char *)block);
    -	xfs_dir2_data_log_entry(tp, bp, dep);
    -	blp[0].hashval = cpu_to_be32(xfs_dir_hash_dot);
    -	blp[0].address = cpu_to_be32(XFS_DIR2_BYTE_TO_DATAPTR(mp,
    -				(char *)dep - (char *)block));
    -	/*
    -	 * Create entry for ..
    -	 */
    -	dep = (xfs_dir2_data_entry_t *)
    -		((char *)block + XFS_DIR2_DATA_DOTDOT_OFFSET);
    -	INT_SET(dep->inumber, ARCH_CONVERT, XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent));
    -	dep->namelen = 2;
    -	dep->name[0] = dep->name[1] = '.';
    -	tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
    -	*tagp = cpu_to_be16((char *)dep - (char *)block);
    -	xfs_dir2_data_log_entry(tp, bp, dep);
    -	blp[1].hashval = cpu_to_be32(xfs_dir_hash_dotdot);
    -	blp[1].address = cpu_to_be32(XFS_DIR2_BYTE_TO_DATAPTR(mp,
    -				(char *)dep - (char *)block));
    -	offset = XFS_DIR2_DATA_FIRST_OFFSET;
    -	/*
    -	 * Loop over existing entries, stuff them in.
    -	 */
    -	if ((i = 0) == sfp->hdr.count)
    -		sfep = NULL;
    -	else
    -		sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
    -	/*
    -	 * Need to preserve the existing offset values in the sf directory.
    -	 * Insert holes (unused entries) where necessary.
    -	 */
    -	while (offset < endoffset) {
    -		/*
    -		 * sfep is null when we reach the end of the list.
    -		 */
    -		if (sfep == NULL)
    -			newoffset = endoffset;
    -		else
    -			newoffset = XFS_DIR2_SF_GET_OFFSET(sfep);
    -		/*
    -		 * There should be a hole here, make one.
    -		 */
    -		if (offset < newoffset) {
    -			dup = (xfs_dir2_data_unused_t *)
    -			      ((char *)block + offset);
    -			dup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
    -			dup->length = cpu_to_be16(newoffset - offset);
    -			*XFS_DIR2_DATA_UNUSED_TAG_P(dup) = cpu_to_be16(
    -				((char *)dup - (char *)block));
    -			xfs_dir2_data_log_unused(tp, bp, dup);
    -			(void)xfs_dir2_data_freeinsert((xfs_dir2_data_t *)block,
    -				dup, &dummy);
    -			offset += be16_to_cpu(dup->length);
    -			continue;
    -		}
    -		/*
    -		 * Copy a real entry.
    -		 */
    -		dep = (xfs_dir2_data_entry_t *)((char *)block + newoffset);
    -		INT_SET(dep->inumber, ARCH_CONVERT, XFS_DIR2_SF_GET_INUMBER(sfp,
    -				XFS_DIR2_SF_INUMBERP(sfep)));
    -		dep->namelen = sfep->namelen;
    -		memcpy(dep->name, sfep->name, dep->namelen);
    -		tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
    -		*tagp = cpu_to_be16((char *)dep - (char *)block);
    -		xfs_dir2_data_log_entry(tp, bp, dep);
    -		blp[2 + i].hashval = cpu_to_be32(xfs_da_hashname(
    -					(char *)sfep->name, sfep->namelen));
    -		blp[2 + i].address = cpu_to_be32(XFS_DIR2_BYTE_TO_DATAPTR(mp,
    -						 (char *)dep - (char *)block));
    -		offset = (int)((char *)(tagp + 1) - (char *)block);
    -		if (++i == sfp->hdr.count)
    -			sfep = NULL;
    -		else
    -			sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep);
    -	}
    -	/* Done with the temporary buffer */
    -	kmem_free(buf, buf_len);
    -	/*
    -	 * Sort the leaf entries by hash value.
    -	 */
    -	xfs_sort(blp, be32_to_cpu(btp->count), sizeof(*blp), xfs_dir2_block_sort);
    -	/*
    -	 * Log the leaf entry area and tail.
    -	 * Already logged the header in data_init, ignore needlog.
    -	 */
    -	ASSERT(needscan == 0);
    -	xfs_dir2_block_log_leaf(tp, bp, 0, be32_to_cpu(btp->count) - 1);
    -	xfs_dir2_block_log_tail(tp, bp);
    -	xfs_dir2_data_check(dp, bp);
    -	xfs_da_buf_done(bp);
    -	return 0;
    -}
    diff --git a/sys/gnu/fs/xfs/xfs_dir2_block.h b/sys/gnu/fs/xfs/xfs_dir2_block.h
    deleted file mode 100644
    index 6722effd0b2..00000000000
    --- a/sys/gnu/fs/xfs/xfs_dir2_block.h
    +++ /dev/null
    @@ -1,95 +0,0 @@
    -/*
    - * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_DIR2_BLOCK_H__
    -#define	__XFS_DIR2_BLOCK_H__
    -
    -/*
    - * xfs_dir2_block.h
    - * Directory version 2, single block format structures
    - */
    -
    -struct uio;
    -struct xfs_dabuf;
    -struct xfs_da_args;
    -struct xfs_dir2_data_hdr;
    -struct xfs_dir2_leaf_entry;
    -struct xfs_inode;
    -struct xfs_mount;
    -struct xfs_trans;
    -
    -/*
    - * The single block format is as follows:
    - * xfs_dir2_data_hdr_t structure
    - * xfs_dir2_data_entry_t and xfs_dir2_data_unused_t structures
    - * xfs_dir2_leaf_entry_t structures
    - * xfs_dir2_block_tail_t structure
    - */
    -
    -#define	XFS_DIR2_BLOCK_MAGIC	0x58443242	/* XD2B: for one block dirs */
    -
    -typedef struct xfs_dir2_block_tail {
    -	__be32		count;			/* count of leaf entries */
    -	__be32		stale;			/* count of stale lf entries */
    -} xfs_dir2_block_tail_t;
    -
    -/*
    - * Generic single-block structure, for xfs_db.
    - */
    -typedef struct xfs_dir2_block {
    -	xfs_dir2_data_hdr_t	hdr;		/* magic XFS_DIR2_BLOCK_MAGIC */
    -	xfs_dir2_data_union_t	u[1];
    -	xfs_dir2_leaf_entry_t	leaf[1];
    -	xfs_dir2_block_tail_t	tail;
    -} xfs_dir2_block_t;
    -
    -/*
    - * Pointer to the leaf header embedded in a data block (1-block format)
    - */
    -#define	XFS_DIR2_BLOCK_TAIL_P(mp,block)	xfs_dir2_block_tail_p(mp,block)
    -static inline xfs_dir2_block_tail_t *
    -xfs_dir2_block_tail_p(struct xfs_mount *mp, xfs_dir2_block_t *block)
    -{
    -	return (((xfs_dir2_block_tail_t *)
    -		((char *)(block) + (mp)->m_dirblksize)) - 1);
    -}
    -
    -/*
    - * Pointer to the leaf entries embedded in a data block (1-block format)
    - */
    -#define	XFS_DIR2_BLOCK_LEAF_P(btp)	xfs_dir2_block_leaf_p(btp)
    -static inline struct xfs_dir2_leaf_entry *
    -xfs_dir2_block_leaf_p(xfs_dir2_block_tail_t *btp)
    -{
    -	return ((struct xfs_dir2_leaf_entry *)btp) - be32_to_cpu(btp->count);
    -}
    -
    -/*
    - * Function declarations.
    - */
    -extern int xfs_dir2_block_addname(struct xfs_da_args *args);
    -extern int xfs_dir2_block_getdents(struct xfs_trans *tp, struct xfs_inode *dp,
    -				   struct uio *uio, int *eofp,
    -				   struct xfs_dirent *dbp, xfs_dir2_put_t put);
    -extern int xfs_dir2_block_lookup(struct xfs_da_args *args);
    -extern int xfs_dir2_block_removename(struct xfs_da_args *args);
    -extern int xfs_dir2_block_replace(struct xfs_da_args *args);
    -extern int xfs_dir2_leaf_to_block(struct xfs_da_args *args,
    -				  struct xfs_dabuf *lbp, struct xfs_dabuf *dbp);
    -extern int xfs_dir2_sf_to_block(struct xfs_da_args *args);
    -
    -#endif	/* __XFS_DIR2_BLOCK_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_dir2_data.c b/sys/gnu/fs/xfs/xfs_dir2_data.c
    deleted file mode 100644
    index bb3d03ff002..00000000000
    --- a/sys/gnu/fs/xfs/xfs_dir2_data.c
    +++ /dev/null
    @@ -1,837 +0,0 @@
    -/*
    - * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_da_btree.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_dir_leaf.h"
    -#include "xfs_dir2_data.h"
    -#include "xfs_dir2_leaf.h"
    -#include "xfs_dir2_block.h"
    -#include "xfs_error.h"
    -
    -#ifdef DEBUG
    -/*
    - * Check the consistency of the data block.
    - * The input can also be a block-format directory.
    - * Pop an assert if we find anything bad.
    - */
    -void
    -xfs_dir2_data_check(
    -	xfs_inode_t		*dp,		/* incore inode pointer */
    -	xfs_dabuf_t		*bp)		/* data block's buffer */
    -{
    -	xfs_dir2_dataptr_t	addr;		/* addr for leaf lookup */
    -	xfs_dir2_data_free_t	*bf;		/* bestfree table */
    -	xfs_dir2_block_tail_t	*btp=NULL;	/* block tail */
    -	int			count;		/* count of entries found */
    -	xfs_dir2_data_t		*d;		/* data block pointer */
    -	xfs_dir2_data_entry_t	*dep;		/* data entry */
    -	xfs_dir2_data_free_t	*dfp;		/* bestfree entry */
    -	xfs_dir2_data_unused_t	*dup;		/* unused entry */
    -	char			*endp;		/* end of useful data */
    -	int			freeseen;	/* mask of bestfrees seen */
    -	xfs_dahash_t		hash;		/* hash of current name */
    -	int			i;		/* leaf index */
    -	int			lastfree;	/* last entry was unused */
    -	xfs_dir2_leaf_entry_t	*lep=NULL;	/* block leaf entries */
    -	xfs_mount_t		*mp;		/* filesystem mount point */
    -	char			*p;		/* current data position */
    -	int			stale;		/* count of stale leaves */
    -
    -	mp = dp->i_mount;
    -	d = bp->data;
    -	ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC ||
    -	       be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
    -	bf = d->hdr.bestfree;
    -	p = (char *)d->u;
    -	if (be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC) {
    -		btp = XFS_DIR2_BLOCK_TAIL_P(mp, (xfs_dir2_block_t *)d);
    -		lep = XFS_DIR2_BLOCK_LEAF_P(btp);
    -		endp = (char *)lep;
    -	} else
    -		endp = (char *)d + mp->m_dirblksize;
    -	count = lastfree = freeseen = 0;
    -	/*
    -	 * Account for zero bestfree entries.
    -	 */
    -	if (!bf[0].length) {
    -		ASSERT(!bf[0].offset);
    -		freeseen |= 1 << 0;
    -	}
    -	if (!bf[1].length) {
    -		ASSERT(!bf[1].offset);
    -		freeseen |= 1 << 1;
    -	}
    -	if (!bf[2].length) {
    -		ASSERT(!bf[2].offset);
    -		freeseen |= 1 << 2;
    -	}
    -	ASSERT(be16_to_cpu(bf[0].length) >= be16_to_cpu(bf[1].length));
    -	ASSERT(be16_to_cpu(bf[1].length) >= be16_to_cpu(bf[2].length));
    -	/*
    -	 * Loop over the data/unused entries.
    -	 */
    -	while (p < endp) {
    -		dup = (xfs_dir2_data_unused_t *)p;
    -		/*
    -		 * If it's unused, look for the space in the bestfree table.
    -		 * If we find it, account for that, else make sure it
    -		 * doesn't need to be there.
    -		 */
    -		if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
    -			ASSERT(lastfree == 0);
    -			ASSERT(be16_to_cpu(*XFS_DIR2_DATA_UNUSED_TAG_P(dup)) ==
    -			       (char *)dup - (char *)d);
    -			dfp = xfs_dir2_data_freefind(d, dup);
    -			if (dfp) {
    -				i = (int)(dfp - bf);
    -				ASSERT((freeseen & (1 << i)) == 0);
    -				freeseen |= 1 << i;
    -			} else {
    -				ASSERT(be16_to_cpu(dup->length) <=
    -				       be16_to_cpu(bf[2].length));
    -			}
    -			p += be16_to_cpu(dup->length);
    -			lastfree = 1;
    -			continue;
    -		}
    -		/*
    -		 * It's a real entry.  Validate the fields.
    -		 * If this is a block directory then make sure it's
    -		 * in the leaf section of the block.
    -		 * The linear search is crude but this is DEBUG code.
    -		 */
    -		dep = (xfs_dir2_data_entry_t *)p;
    -		ASSERT(dep->namelen != 0);
    -		ASSERT(xfs_dir_ino_validate(mp, INT_GET(dep->inumber, ARCH_CONVERT)) == 0);
    -		ASSERT(be16_to_cpu(*XFS_DIR2_DATA_ENTRY_TAG_P(dep)) ==
    -		       (char *)dep - (char *)d);
    -		count++;
    -		lastfree = 0;
    -		if (be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC) {
    -			addr = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
    -				(xfs_dir2_data_aoff_t)
    -				((char *)dep - (char *)d));
    -			hash = xfs_da_hashname((char *)dep->name, dep->namelen);
    -			for (i = 0; i < be32_to_cpu(btp->count); i++) {
    -				if (be32_to_cpu(lep[i].address) == addr &&
    -				    be32_to_cpu(lep[i].hashval) == hash)
    -					break;
    -			}
    -			ASSERT(i < be32_to_cpu(btp->count));
    -		}
    -		p += XFS_DIR2_DATA_ENTSIZE(dep->namelen);
    -	}
    -	/*
    -	 * Need to have seen all the entries and all the bestfree slots.
    -	 */
    -	ASSERT(freeseen == 7);
    -	if (be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC) {
    -		for (i = stale = 0; i < be32_to_cpu(btp->count); i++) {
    -			if (be32_to_cpu(lep[i].address) == XFS_DIR2_NULL_DATAPTR)
    -				stale++;
    -			if (i > 0)
    -				ASSERT(be32_to_cpu(lep[i].hashval) >= be32_to_cpu(lep[i - 1].hashval));
    -		}
    -		ASSERT(count == be32_to_cpu(btp->count) - be32_to_cpu(btp->stale));
    -		ASSERT(stale == be32_to_cpu(btp->stale));
    -	}
    -}
    -#endif
    -
    -/*
    - * Given a data block and an unused entry from that block,
    - * return the bestfree entry if any that corresponds to it.
    - */
    -xfs_dir2_data_free_t *
    -xfs_dir2_data_freefind(
    -	xfs_dir2_data_t		*d,		/* data block */
    -	xfs_dir2_data_unused_t	*dup)		/* data unused entry */
    -{
    -	xfs_dir2_data_free_t	*dfp;		/* bestfree entry */
    -	xfs_dir2_data_aoff_t	off;		/* offset value needed */
    -#if defined(DEBUG) && defined(__KERNEL__)
    -	int			matched;	/* matched the value */
    -	int			seenzero;	/* saw a 0 bestfree entry */
    -#endif
    -
    -	off = (xfs_dir2_data_aoff_t)((char *)dup - (char *)d);
    -#if defined(DEBUG) && defined(__KERNEL__)
    -	/*
    -	 * Validate some consistency in the bestfree table.
    -	 * Check order, non-overlapping entries, and if we find the
    -	 * one we're looking for it has to be exact.
    -	 */
    -	ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC ||
    -	       be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
    -	for (dfp = &d->hdr.bestfree[0], seenzero = matched = 0;
    -	     dfp < &d->hdr.bestfree[XFS_DIR2_DATA_FD_COUNT];
    -	     dfp++) {
    -		if (!dfp->offset) {
    -			ASSERT(!dfp->length);
    -			seenzero = 1;
    -			continue;
    -		}
    -		ASSERT(seenzero == 0);
    -		if (be16_to_cpu(dfp->offset) == off) {
    -			matched = 1;
    -			ASSERT(dfp->length == dup->length);
    -		} else if (off < be16_to_cpu(dfp->offset))
    -			ASSERT(off + be16_to_cpu(dup->length) <= be16_to_cpu(dfp->offset));
    -		else
    -			ASSERT(be16_to_cpu(dfp->offset) + be16_to_cpu(dfp->length) <= off);
    -		ASSERT(matched || be16_to_cpu(dfp->length) >= be16_to_cpu(dup->length));
    -		if (dfp > &d->hdr.bestfree[0])
    -			ASSERT(be16_to_cpu(dfp[-1].length) >= be16_to_cpu(dfp[0].length));
    -	}
    -#endif
    -	/*
    -	 * If this is smaller than the smallest bestfree entry,
    -	 * it can't be there since they're sorted.
    -	 */
    -	if (be16_to_cpu(dup->length) <
    -	    be16_to_cpu(d->hdr.bestfree[XFS_DIR2_DATA_FD_COUNT - 1].length))
    -		return NULL;
    -	/*
    -	 * Look at the three bestfree entries for our guy.
    -	 */
    -	for (dfp = &d->hdr.bestfree[0];
    -	     dfp < &d->hdr.bestfree[XFS_DIR2_DATA_FD_COUNT];
    -	     dfp++) {
    -		if (!dfp->offset)
    -			return NULL;
    -		if (be16_to_cpu(dfp->offset) == off)
    -			return dfp;
    -	}
    -	/*
    -	 * Didn't find it.  This only happens if there are duplicate lengths.
    -	 */
    -	return NULL;
    -}
    -
    -/*
    - * Insert an unused-space entry into the bestfree table.
    - */
    -xfs_dir2_data_free_t *				/* entry inserted */
    -xfs_dir2_data_freeinsert(
    -	xfs_dir2_data_t		*d,		/* data block pointer */
    -	xfs_dir2_data_unused_t	*dup,		/* unused space */
    -	int			*loghead)	/* log the data header (out) */
    -{
    -	xfs_dir2_data_free_t	*dfp;		/* bestfree table pointer */
    -	xfs_dir2_data_free_t	new;		/* new bestfree entry */
    -
    -#ifdef __KERNEL__
    -	ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC ||
    -	       be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
    -#endif
    -	dfp = d->hdr.bestfree;
    -	new.length = dup->length;
    -	new.offset = cpu_to_be16((char *)dup - (char *)d);
    -	/*
    -	 * Insert at position 0, 1, or 2; or not at all.
    -	 */
    -	if (be16_to_cpu(new.length) > be16_to_cpu(dfp[0].length)) {
    -		dfp[2] = dfp[1];
    -		dfp[1] = dfp[0];
    -		dfp[0] = new;
    -		*loghead = 1;
    -		return &dfp[0];
    -	}
    -	if (be16_to_cpu(new.length) > be16_to_cpu(dfp[1].length)) {
    -		dfp[2] = dfp[1];
    -		dfp[1] = new;
    -		*loghead = 1;
    -		return &dfp[1];
    -	}
    -	if (be16_to_cpu(new.length) > be16_to_cpu(dfp[2].length)) {
    -		dfp[2] = new;
    -		*loghead = 1;
    -		return &dfp[2];
    -	}
    -	return NULL;
    -}
    -
    -/*
    - * Remove a bestfree entry from the table.
    - */
    -STATIC void
    -xfs_dir2_data_freeremove(
    -	xfs_dir2_data_t		*d,		/* data block pointer */
    -	xfs_dir2_data_free_t	*dfp,		/* bestfree entry pointer */
    -	int			*loghead)	/* out: log data header */
    -{
    -#ifdef __KERNEL__
    -	ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC ||
    -	       be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
    -#endif
    -	/*
    -	 * It's the first entry, slide the next 2 up.
    -	 */
    -	if (dfp == &d->hdr.bestfree[0]) {
    -		d->hdr.bestfree[0] = d->hdr.bestfree[1];
    -		d->hdr.bestfree[1] = d->hdr.bestfree[2];
    -	}
    -	/*
    -	 * It's the second entry, slide the 3rd entry up.
    -	 */
    -	else if (dfp == &d->hdr.bestfree[1])
    -		d->hdr.bestfree[1] = d->hdr.bestfree[2];
    -	/*
    -	 * Must be the last entry.
    -	 */
    -	else
    -		ASSERT(dfp == &d->hdr.bestfree[2]);
    -	/*
    -	 * Clear the 3rd entry, must be zero now.
    -	 */
    -	d->hdr.bestfree[2].length = 0;
    -	d->hdr.bestfree[2].offset = 0;
    -	*loghead = 1;
    -}
    -
    -/*
    - * Given a data block, reconstruct its bestfree map.
    - */
    -void
    -xfs_dir2_data_freescan(
    -	xfs_mount_t		*mp,		/* filesystem mount point */
    -	xfs_dir2_data_t		*d,		/* data block pointer */
    -	int			*loghead,	/* out: log data header */
    -	char			*aendp)		/* in: caller's endp */
    -{
    -	xfs_dir2_block_tail_t	*btp;		/* block tail */
    -	xfs_dir2_data_entry_t	*dep;		/* active data entry */
    -	xfs_dir2_data_unused_t	*dup;		/* unused data entry */
    -	char			*endp;		/* end of block's data */
    -	char			*p;		/* current entry pointer */
    -
    -#ifdef __KERNEL__
    -	ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC ||
    -	       be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
    -#endif
    -	/*
    -	 * Start by clearing the table.
    -	 */
    -	memset(d->hdr.bestfree, 0, sizeof(d->hdr.bestfree));
    -	*loghead = 1;
    -	/*
    -	 * Set up pointers.
    -	 */
    -	p = (char *)d->u;
    -	if (aendp)
    -		endp = aendp;
    -	else if (be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC) {
    -		btp = XFS_DIR2_BLOCK_TAIL_P(mp, (xfs_dir2_block_t *)d);
    -		endp = (char *)XFS_DIR2_BLOCK_LEAF_P(btp);
    -	} else
    -		endp = (char *)d + mp->m_dirblksize;
    -	/*
    -	 * Loop over the block's entries.
    -	 */
    -	while (p < endp) {
    -		dup = (xfs_dir2_data_unused_t *)p;
    -		/*
    -		 * If it's a free entry, insert it.
    -		 */
    -		if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
    -			ASSERT((char *)dup - (char *)d ==
    -			       be16_to_cpu(*XFS_DIR2_DATA_UNUSED_TAG_P(dup)));
    -			xfs_dir2_data_freeinsert(d, dup, loghead);
    -			p += be16_to_cpu(dup->length);
    -		}
    -		/*
    -		 * For active entries, check their tags and skip them.
    -		 */
    -		else {
    -			dep = (xfs_dir2_data_entry_t *)p;
    -			ASSERT((char *)dep - (char *)d ==
    -			       be16_to_cpu(*XFS_DIR2_DATA_ENTRY_TAG_P(dep)));
    -			p += XFS_DIR2_DATA_ENTSIZE(dep->namelen);
    -		}
    -	}
    -}
    -
    -/*
    - * Initialize a data block at the given block number in the directory.
    - * Give back the buffer for the created block.
    - */
    -int						/* error */
    -xfs_dir2_data_init(
    -	xfs_da_args_t		*args,		/* directory operation args */
    -	xfs_dir2_db_t		blkno,		/* logical dir block number */
    -	xfs_dabuf_t		**bpp)		/* output block buffer */
    -{
    -	xfs_dabuf_t		*bp;		/* block buffer */
    -	xfs_dir2_data_t		*d;		/* pointer to block */
    -	xfs_inode_t		*dp;		/* incore directory inode */
    -	xfs_dir2_data_unused_t	*dup;		/* unused entry pointer */
    -	int			error;		/* error return value */
    -	int			i;		/* bestfree index */
    -	xfs_mount_t		*mp;		/* filesystem mount point */
    -	xfs_trans_t		*tp;		/* transaction pointer */
    -	int                     t;              /* temp */
    -
    -	dp = args->dp;
    -	mp = dp->i_mount;
    -	tp = args->trans;
    -	/*
    -	 * Get the buffer set up for the block.
    -	 */
    -	error = xfs_da_get_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, blkno), -1, &bp,
    -		XFS_DATA_FORK);
    -	if (error) {
    -		return error;
    -	}
    -	ASSERT(bp != NULL);
    -	/*
    -	 * Initialize the header.
    -	 */
    -	d = bp->data;
    -	d->hdr.magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC);
    -	d->hdr.bestfree[0].offset = cpu_to_be16(sizeof(d->hdr));
    -	for (i = 1; i < XFS_DIR2_DATA_FD_COUNT; i++) {
    -		d->hdr.bestfree[i].length = 0;
    -		d->hdr.bestfree[i].offset = 0;
    -	}
    -	/*
    -	 * Set up an unused entry for the block's body.
    -	 */
    -	dup = &d->u[0].unused;
    -	dup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
    -
    -	t=mp->m_dirblksize - (uint)sizeof(d->hdr);
    -	d->hdr.bestfree[0].length = cpu_to_be16(t);
    -	dup->length = cpu_to_be16(t);
    -	*XFS_DIR2_DATA_UNUSED_TAG_P(dup) = cpu_to_be16((char *)dup - (char *)d);
    -	/*
    -	 * Log it and return it.
    -	 */
    -	xfs_dir2_data_log_header(tp, bp);
    -	xfs_dir2_data_log_unused(tp, bp, dup);
    -	*bpp = bp;
    -	return 0;
    -}
    -
    -/*
    - * Log an active data entry from the block.
    - */
    -void
    -xfs_dir2_data_log_entry(
    -	xfs_trans_t		*tp,		/* transaction pointer */
    -	xfs_dabuf_t		*bp,		/* block buffer */
    -	xfs_dir2_data_entry_t	*dep)		/* data entry pointer */
    -{
    -	xfs_dir2_data_t		*d;		/* data block pointer */
    -
    -	d = bp->data;
    -	ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC ||
    -	       be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
    -	xfs_da_log_buf(tp, bp, (uint)((char *)dep - (char *)d),
    -		(uint)((char *)(XFS_DIR2_DATA_ENTRY_TAG_P(dep) + 1) -
    -		       (char *)d - 1));
    -}
    -
    -/*
    - * Log a data block header.
    - */
    -void
    -xfs_dir2_data_log_header(
    -	xfs_trans_t		*tp,		/* transaction pointer */
    -	xfs_dabuf_t		*bp)		/* block buffer */
    -{
    -	xfs_dir2_data_t		*d;		/* data block pointer */
    -
    -	d = bp->data;
    -	ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC ||
    -	       be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
    -	xfs_da_log_buf(tp, bp, (uint)((char *)&d->hdr - (char *)d),
    -		(uint)(sizeof(d->hdr) - 1));
    -}
    -
    -/*
    - * Log a data unused entry.
    - */
    -void
    -xfs_dir2_data_log_unused(
    -	xfs_trans_t		*tp,		/* transaction pointer */
    -	xfs_dabuf_t		*bp,		/* block buffer */
    -	xfs_dir2_data_unused_t	*dup)		/* data unused pointer */
    -{
    -	xfs_dir2_data_t		*d;		/* data block pointer */
    -
    -	d = bp->data;
    -	ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC ||
    -	       be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
    -	/*
    -	 * Log the first part of the unused entry.
    -	 */
    -	xfs_da_log_buf(tp, bp, (uint)((char *)dup - (char *)d),
    -		(uint)((char *)&dup->length + sizeof(dup->length) -
    -		       1 - (char *)d));
    -	/*
    -	 * Log the end (tag) of the unused entry.
    -	 */
    -	xfs_da_log_buf(tp, bp,
    -		(uint)((char *)XFS_DIR2_DATA_UNUSED_TAG_P(dup) - (char *)d),
    -		(uint)((char *)XFS_DIR2_DATA_UNUSED_TAG_P(dup) - (char *)d +
    -		       sizeof(xfs_dir2_data_off_t) - 1));
    -}
    -
    -/*
    - * Make a byte range in the data block unused.
    - * Its current contents are unimportant.
    - */
    -void
    -xfs_dir2_data_make_free(
    -	xfs_trans_t		*tp,		/* transaction pointer */
    -	xfs_dabuf_t		*bp,		/* block buffer */
    -	xfs_dir2_data_aoff_t	offset,		/* starting byte offset */
    -	xfs_dir2_data_aoff_t	len,		/* length in bytes */
    -	int			*needlogp,	/* out: log header */
    -	int			*needscanp)	/* out: regen bestfree */
    -{
    -	xfs_dir2_data_t		*d;		/* data block pointer */
    -	xfs_dir2_data_free_t	*dfp;		/* bestfree pointer */
    -	char			*endptr;	/* end of data area */
    -	xfs_mount_t		*mp;		/* filesystem mount point */
    -	int			needscan;	/* need to regen bestfree */
    -	xfs_dir2_data_unused_t	*newdup;	/* new unused entry */
    -	xfs_dir2_data_unused_t	*postdup;	/* unused entry after us */
    -	xfs_dir2_data_unused_t	*prevdup;	/* unused entry before us */
    -
    -	mp = tp->t_mountp;
    -	d = bp->data;
    -	/*
    -	 * Figure out where the end of the data area is.
    -	 */
    -	if (be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC)
    -		endptr = (char *)d + mp->m_dirblksize;
    -	else {
    -		xfs_dir2_block_tail_t	*btp;	/* block tail */
    -
    -		ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
    -		btp = XFS_DIR2_BLOCK_TAIL_P(mp, (xfs_dir2_block_t *)d);
    -		endptr = (char *)XFS_DIR2_BLOCK_LEAF_P(btp);
    -	}
    -	/*
    -	 * If this isn't the start of the block, then back up to
    -	 * the previous entry and see if it's free.
    -	 */
    -	if (offset > sizeof(d->hdr)) {
    -		__be16			*tagp;	/* tag just before us */
    -
    -		tagp = (__be16 *)((char *)d + offset) - 1;
    -		prevdup = (xfs_dir2_data_unused_t *)((char *)d + be16_to_cpu(*tagp));
    -		if (be16_to_cpu(prevdup->freetag) != XFS_DIR2_DATA_FREE_TAG)
    -			prevdup = NULL;
    -	} else
    -		prevdup = NULL;
    -	/*
    -	 * If this isn't the end of the block, see if the entry after
    -	 * us is free.
    -	 */
    -	if ((char *)d + offset + len < endptr) {
    -		postdup =
    -			(xfs_dir2_data_unused_t *)((char *)d + offset + len);
    -		if (be16_to_cpu(postdup->freetag) != XFS_DIR2_DATA_FREE_TAG)
    -			postdup = NULL;
    -	} else
    -		postdup = NULL;
    -	ASSERT(*needscanp == 0);
    -	needscan = 0;
    -	/*
    -	 * Previous and following entries are both free,
    -	 * merge everything into a single free entry.
    -	 */
    -	if (prevdup && postdup) {
    -		xfs_dir2_data_free_t	*dfp2;	/* another bestfree pointer */
    -
    -		/*
    -		 * See if prevdup and/or postdup are in bestfree table.
    -		 */
    -		dfp = xfs_dir2_data_freefind(d, prevdup);
    -		dfp2 = xfs_dir2_data_freefind(d, postdup);
    -		/*
    -		 * We need a rescan unless there are exactly 2 free entries
    -		 * namely our two.  Then we know what's happening, otherwise
    -		 * since the third bestfree is there, there might be more
    -		 * entries.
    -		 */
    -		needscan = (d->hdr.bestfree[2].length != 0);
    -		/*
    -		 * Fix up the new big freespace.
    -		 */
    -		be16_add(&prevdup->length, len + be16_to_cpu(postdup->length));
    -		*XFS_DIR2_DATA_UNUSED_TAG_P(prevdup) =
    -			cpu_to_be16((char *)prevdup - (char *)d);
    -		xfs_dir2_data_log_unused(tp, bp, prevdup);
    -		if (!needscan) {
    -			/*
    -			 * Has to be the case that entries 0 and 1 are
    -			 * dfp and dfp2 (don't know which is which), and
    -			 * entry 2 is empty.
    -			 * Remove entry 1 first then entry 0.
    -			 */
    -			ASSERT(dfp && dfp2);
    -			if (dfp == &d->hdr.bestfree[1]) {
    -				dfp = &d->hdr.bestfree[0];
    -				ASSERT(dfp2 == dfp);
    -				dfp2 = &d->hdr.bestfree[1];
    -			}
    -			xfs_dir2_data_freeremove(d, dfp2, needlogp);
    -			xfs_dir2_data_freeremove(d, dfp, needlogp);
    -			/*
    -			 * Now insert the new entry.
    -			 */
    -			dfp = xfs_dir2_data_freeinsert(d, prevdup, needlogp);
    -			ASSERT(dfp == &d->hdr.bestfree[0]);
    -			ASSERT(dfp->length == prevdup->length);
    -			ASSERT(!dfp[1].length);
    -			ASSERT(!dfp[2].length);
    -		}
    -	}
    -	/*
    -	 * The entry before us is free, merge with it.
    -	 */
    -	else if (prevdup) {
    -		dfp = xfs_dir2_data_freefind(d, prevdup);
    -		be16_add(&prevdup->length, len);
    -		*XFS_DIR2_DATA_UNUSED_TAG_P(prevdup) =
    -			cpu_to_be16((char *)prevdup - (char *)d);
    -		xfs_dir2_data_log_unused(tp, bp, prevdup);
    -		/*
    -		 * If the previous entry was in the table, the new entry
    -		 * is longer, so it will be in the table too.  Remove
    -		 * the old one and add the new one.
    -		 */
    -		if (dfp) {
    -			xfs_dir2_data_freeremove(d, dfp, needlogp);
    -			(void)xfs_dir2_data_freeinsert(d, prevdup, needlogp);
    -		}
    -		/*
    -		 * Otherwise we need a scan if the new entry is big enough.
    -		 */
    -		else {
    -			needscan = be16_to_cpu(prevdup->length) >
    -				   be16_to_cpu(d->hdr.bestfree[2].length);
    -		}
    -	}
    -	/*
    -	 * The following entry is free, merge with it.
    -	 */
    -	else if (postdup) {
    -		dfp = xfs_dir2_data_freefind(d, postdup);
    -		newdup = (xfs_dir2_data_unused_t *)((char *)d + offset);
    -		newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
    -		newdup->length = cpu_to_be16(len + be16_to_cpu(postdup->length));
    -		*XFS_DIR2_DATA_UNUSED_TAG_P(newdup) =
    -			cpu_to_be16((char *)newdup - (char *)d);
    -		xfs_dir2_data_log_unused(tp, bp, newdup);
    -		/*
    -		 * If the following entry was in the table, the new entry
    -		 * is longer, so it will be in the table too.  Remove
    -		 * the old one and add the new one.
    -		 */
    -		if (dfp) {
    -			xfs_dir2_data_freeremove(d, dfp, needlogp);
    -			(void)xfs_dir2_data_freeinsert(d, newdup, needlogp);
    -		}
    -		/*
    -		 * Otherwise we need a scan if the new entry is big enough.
    -		 */
    -		else {
    -			needscan = be16_to_cpu(newdup->length) >
    -				   be16_to_cpu(d->hdr.bestfree[2].length);
    -		}
    -	}
    -	/*
    -	 * Neither neighbor is free.  Make a new entry.
    -	 */
    -	else {
    -		newdup = (xfs_dir2_data_unused_t *)((char *)d + offset);
    -		newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
    -		newdup->length = cpu_to_be16(len);
    -		*XFS_DIR2_DATA_UNUSED_TAG_P(newdup) =
    -			cpu_to_be16((char *)newdup - (char *)d);
    -		xfs_dir2_data_log_unused(tp, bp, newdup);
    -		(void)xfs_dir2_data_freeinsert(d, newdup, needlogp);
    -	}
    -	*needscanp = needscan;
    -}
    -
    -/*
    - * Take a byte range out of an existing unused space and make it un-free.
    - */
    -void
    -xfs_dir2_data_use_free(
    -	xfs_trans_t		*tp,		/* transaction pointer */
    -	xfs_dabuf_t		*bp,		/* data block buffer */
    -	xfs_dir2_data_unused_t	*dup,		/* unused entry */
    -	xfs_dir2_data_aoff_t	offset,		/* starting offset to use */
    -	xfs_dir2_data_aoff_t	len,		/* length to use */
    -	int			*needlogp,	/* out: need to log header */
    -	int			*needscanp)	/* out: need regen bestfree */
    -{
    -	xfs_dir2_data_t		*d;		/* data block */
    -	xfs_dir2_data_free_t	*dfp;		/* bestfree pointer */
    -	int			matchback;	/* matches end of freespace */
    -	int			matchfront;	/* matches start of freespace */
    -	int			needscan;	/* need to regen bestfree */
    -	xfs_dir2_data_unused_t	*newdup;	/* new unused entry */
    -	xfs_dir2_data_unused_t	*newdup2;	/* another new unused entry */
    -	int			oldlen;		/* old unused entry's length */
    -
    -	d = bp->data;
    -	ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC ||
    -	       be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
    -	ASSERT(be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG);
    -	ASSERT(offset >= (char *)dup - (char *)d);
    -	ASSERT(offset + len <= (char *)dup + be16_to_cpu(dup->length) - (char *)d);
    -	ASSERT((char *)dup - (char *)d == be16_to_cpu(*XFS_DIR2_DATA_UNUSED_TAG_P(dup)));
    -	/*
    -	 * Look up the entry in the bestfree table.
    -	 */
    -	dfp = xfs_dir2_data_freefind(d, dup);
    -	oldlen = be16_to_cpu(dup->length);
    -	ASSERT(dfp || oldlen <= be16_to_cpu(d->hdr.bestfree[2].length));
    -	/*
    -	 * Check for alignment with front and back of the entry.
    -	 */
    -	matchfront = (char *)dup - (char *)d == offset;
    -	matchback = (char *)dup + oldlen - (char *)d == offset + len;
    -	ASSERT(*needscanp == 0);
    -	needscan = 0;
    -	/*
    -	 * If we matched it exactly we just need to get rid of it from
    -	 * the bestfree table.
    -	 */
    -	if (matchfront && matchback) {
    -		if (dfp) {
    -			needscan = (d->hdr.bestfree[2].offset != 0);
    -			if (!needscan)
    -				xfs_dir2_data_freeremove(d, dfp, needlogp);
    -		}
    -	}
    -	/*
    -	 * We match the first part of the entry.
    -	 * Make a new entry with the remaining freespace.
    -	 */
    -	else if (matchfront) {
    -		newdup = (xfs_dir2_data_unused_t *)((char *)d + offset + len);
    -		newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
    -		newdup->length = cpu_to_be16(oldlen - len);
    -		*XFS_DIR2_DATA_UNUSED_TAG_P(newdup) =
    -			cpu_to_be16((char *)newdup - (char *)d);
    -		xfs_dir2_data_log_unused(tp, bp, newdup);
    -		/*
    -		 * If it was in the table, remove it and add the new one.
    -		 */
    -		if (dfp) {
    -			xfs_dir2_data_freeremove(d, dfp, needlogp);
    -			dfp = xfs_dir2_data_freeinsert(d, newdup, needlogp);
    -			ASSERT(dfp != NULL);
    -			ASSERT(dfp->length == newdup->length);
    -			ASSERT(be16_to_cpu(dfp->offset) == (char *)newdup - (char *)d);
    -			/*
    -			 * If we got inserted at the last slot,
    -			 * that means we don't know if there was a better
    -			 * choice for the last slot, or not.  Rescan.
    -			 */
    -			needscan = dfp == &d->hdr.bestfree[2];
    -		}
    -	}
    -	/*
    -	 * We match the last part of the entry.
    -	 * Trim the allocated space off the tail of the entry.
    -	 */
    -	else if (matchback) {
    -		newdup = dup;
    -		newdup->length = cpu_to_be16(((char *)d + offset) - (char *)newdup);
    -		*XFS_DIR2_DATA_UNUSED_TAG_P(newdup) =
    -			cpu_to_be16((char *)newdup - (char *)d);
    -		xfs_dir2_data_log_unused(tp, bp, newdup);
    -		/*
    -		 * If it was in the table, remove it and add the new one.
    -		 */
    -		if (dfp) {
    -			xfs_dir2_data_freeremove(d, dfp, needlogp);
    -			dfp = xfs_dir2_data_freeinsert(d, newdup, needlogp);
    -			ASSERT(dfp != NULL);
    -			ASSERT(dfp->length == newdup->length);
    -			ASSERT(be16_to_cpu(dfp->offset) == (char *)newdup - (char *)d);
    -			/*
    -			 * If we got inserted at the last slot,
    -			 * that means we don't know if there was a better
    -			 * choice for the last slot, or not.  Rescan.
    -			 */
    -			needscan = dfp == &d->hdr.bestfree[2];
    -		}
    -	}
    -	/*
    -	 * Poking out the middle of an entry.
    -	 * Make two new entries.
    -	 */
    -	else {
    -		newdup = dup;
    -		newdup->length = cpu_to_be16(((char *)d + offset) - (char *)newdup);
    -		*XFS_DIR2_DATA_UNUSED_TAG_P(newdup) =
    -			cpu_to_be16((char *)newdup - (char *)d);
    -		xfs_dir2_data_log_unused(tp, bp, newdup);
    -		newdup2 = (xfs_dir2_data_unused_t *)((char *)d + offset + len);
    -		newdup2->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
    -		newdup2->length = cpu_to_be16(oldlen - len - be16_to_cpu(newdup->length));
    -		*XFS_DIR2_DATA_UNUSED_TAG_P(newdup2) =
    -			cpu_to_be16((char *)newdup2 - (char *)d);
    -		xfs_dir2_data_log_unused(tp, bp, newdup2);
    -		/*
    -		 * If the old entry was in the table, we need to scan
    -		 * if the 3rd entry was valid, since these entries
    -		 * are smaller than the old one.
    -		 * If we don't need to scan that means there were 1 or 2
    -		 * entries in the table, and removing the old and adding
    -		 * the 2 new will work.
    -		 */
    -		if (dfp) {
    -			needscan = (d->hdr.bestfree[2].length != 0);
    -			if (!needscan) {
    -				xfs_dir2_data_freeremove(d, dfp, needlogp);
    -				(void)xfs_dir2_data_freeinsert(d, newdup,
    -					needlogp);
    -				(void)xfs_dir2_data_freeinsert(d, newdup2,
    -					needlogp);
    -			}
    -		}
    -	}
    -	*needscanp = needscan;
    -}
    diff --git a/sys/gnu/fs/xfs/xfs_dir2_data.h b/sys/gnu/fs/xfs/xfs_dir2_data.h
    deleted file mode 100644
    index 0847cbb53e1..00000000000
    --- a/sys/gnu/fs/xfs/xfs_dir2_data.h
    +++ /dev/null
    @@ -1,188 +0,0 @@
    -/*
    - * Copyright (c) 2000,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_DIR2_DATA_H__
    -#define	__XFS_DIR2_DATA_H__
    -
    -/*
    - * Directory format 2, data block structures.
    - */
    -
    -struct xfs_dabuf;
    -struct xfs_da_args;
    -struct xfs_inode;
    -struct xfs_trans;
    -
    -/*
    - * Constants.
    - */
    -#define	XFS_DIR2_DATA_MAGIC	0x58443244	/* XD2D: for multiblock dirs */
    -#define	XFS_DIR2_DATA_ALIGN_LOG	3		/* i.e., 8 bytes */
    -#define	XFS_DIR2_DATA_ALIGN	(1 << XFS_DIR2_DATA_ALIGN_LOG)
    -#define	XFS_DIR2_DATA_FREE_TAG	0xffff
    -#define	XFS_DIR2_DATA_FD_COUNT	3
    -
    -/*
    - * Directory address space divided into sections,
    - * spaces separated by 32gb.
    - */
    -#define	XFS_DIR2_SPACE_SIZE	(1ULL << (32 + XFS_DIR2_DATA_ALIGN_LOG))
    -#define	XFS_DIR2_DATA_SPACE	0
    -#define	XFS_DIR2_DATA_OFFSET	(XFS_DIR2_DATA_SPACE * XFS_DIR2_SPACE_SIZE)
    -#define	XFS_DIR2_DATA_FIRSTDB(mp)	\
    -	XFS_DIR2_BYTE_TO_DB(mp, XFS_DIR2_DATA_OFFSET)
    -
    -/*
    - * Offsets of . and .. in data space (always block 0)
    - */
    -#define	XFS_DIR2_DATA_DOT_OFFSET	\
    -	((xfs_dir2_data_aoff_t)sizeof(xfs_dir2_data_hdr_t))
    -#define	XFS_DIR2_DATA_DOTDOT_OFFSET	\
    -	(XFS_DIR2_DATA_DOT_OFFSET + XFS_DIR2_DATA_ENTSIZE(1))
    -#define	XFS_DIR2_DATA_FIRST_OFFSET		\
    -	(XFS_DIR2_DATA_DOTDOT_OFFSET + XFS_DIR2_DATA_ENTSIZE(2))
    -
    -/*
    - * Structures.
    - */
    -
    -/*
    - * Describe a free area in the data block.
    - * The freespace will be formatted as a xfs_dir2_data_unused_t.
    - */
    -typedef struct xfs_dir2_data_free {
    -	__be16			offset;		/* start of freespace */
    -	__be16			length;		/* length of freespace */
    -} xfs_dir2_data_free_t;
    -
    -/*
    - * Header for the data blocks.
    - * Always at the beginning of a directory-sized block.
    - * The code knows that XFS_DIR2_DATA_FD_COUNT is 3.
    - */
    -typedef struct xfs_dir2_data_hdr {
    -	__be32			magic;		/* XFS_DIR2_DATA_MAGIC */
    -						/* or XFS_DIR2_BLOCK_MAGIC */
    -	xfs_dir2_data_free_t	bestfree[XFS_DIR2_DATA_FD_COUNT];
    -} xfs_dir2_data_hdr_t;
    -
    -/*
    - * Active entry in a data block.  Aligned to 8 bytes.
    - * Tag appears as the last 2 bytes.
    - */
    -typedef struct xfs_dir2_data_entry {
    -	xfs_ino_t		inumber;	/* inode number */
    -	__uint8_t		namelen;	/* name length */
    -	__uint8_t		name[1];	/* name bytes, no null */
    -						/* variable offset */
    -	xfs_dir2_data_off_t	tag;		/* starting offset of us */
    -} xfs_dir2_data_entry_t;
    -
    -/*
    - * Unused entry in a data block.  Aligned to 8 bytes.
    - * Tag appears as the last 2 bytes.
    - */
    -typedef struct xfs_dir2_data_unused {
    -	__be16			freetag;	/* XFS_DIR2_DATA_FREE_TAG */
    -	__be16			length;		/* total free length */
    -						/* variable offset */
    -	__be16			tag;		/* starting offset of us */
    -} xfs_dir2_data_unused_t;
    -
    -typedef union {
    -	xfs_dir2_data_entry_t	entry;
    -	xfs_dir2_data_unused_t	unused;
    -} xfs_dir2_data_union_t;
    -
    -/*
    - * Generic data block structure, for xfs_db.
    - */
    -typedef struct xfs_dir2_data {
    -	xfs_dir2_data_hdr_t	hdr;		/* magic XFS_DIR2_DATA_MAGIC */
    -	xfs_dir2_data_union_t	u[1];
    -} xfs_dir2_data_t;
    -
    -/*
    - * Macros.
    - */
    -
    -/*
    - * Size of a data entry.
    - */
    -#define XFS_DIR2_DATA_ENTSIZE(n)	xfs_dir2_data_entsize(n)
    -static inline int xfs_dir2_data_entsize(int n)
    -{
    -	return (int)roundup(offsetof(xfs_dir2_data_entry_t, name[0]) + (n) + \
    -		 (uint)sizeof(xfs_dir2_data_off_t), XFS_DIR2_DATA_ALIGN);
    -}
    -
    -/*
    - * Pointer to an entry's tag word.
    - */
    -#define	XFS_DIR2_DATA_ENTRY_TAG_P(dep)	xfs_dir2_data_entry_tag_p(dep)
    -static inline __be16 *
    -xfs_dir2_data_entry_tag_p(xfs_dir2_data_entry_t *dep)
    -{
    -	return (__be16 *)((char *)dep +
    -		XFS_DIR2_DATA_ENTSIZE(dep->namelen) - sizeof(__be16));
    -}
    -
    -/*
    - * Pointer to a freespace's tag word.
    - */
    -#define	XFS_DIR2_DATA_UNUSED_TAG_P(dup) \
    -	xfs_dir2_data_unused_tag_p(dup)
    -static inline __be16 *
    -xfs_dir2_data_unused_tag_p(xfs_dir2_data_unused_t *dup)
    -{
    -	return (__be16 *)((char *)dup +
    -			be16_to_cpu(dup->length) - sizeof(__be16));
    -}
    -
    -/*
    - * Function declarations.
    - */
    -#ifdef DEBUG
    -extern void xfs_dir2_data_check(struct xfs_inode *dp, struct xfs_dabuf *bp);
    -#else
    -#define	xfs_dir2_data_check(dp,bp)
    -#endif
    -extern xfs_dir2_data_free_t *xfs_dir2_data_freefind(xfs_dir2_data_t *d,
    -				xfs_dir2_data_unused_t *dup);
    -extern xfs_dir2_data_free_t *xfs_dir2_data_freeinsert(xfs_dir2_data_t *d,
    -				xfs_dir2_data_unused_t *dup, int *loghead);
    -extern void xfs_dir2_data_freescan(struct xfs_mount *mp, xfs_dir2_data_t *d,
    -				int *loghead, char *aendp);
    -extern int xfs_dir2_data_init(struct xfs_da_args *args, xfs_dir2_db_t blkno,
    -				struct xfs_dabuf **bpp);
    -extern void xfs_dir2_data_log_entry(struct xfs_trans *tp, struct xfs_dabuf *bp,
    -				xfs_dir2_data_entry_t *dep);
    -extern void xfs_dir2_data_log_header(struct xfs_trans *tp,
    -				struct xfs_dabuf *bp);
    -extern void xfs_dir2_data_log_unused(struct xfs_trans *tp, struct xfs_dabuf *bp,
    -				xfs_dir2_data_unused_t *dup);
    -extern void xfs_dir2_data_make_free(struct xfs_trans *tp, struct xfs_dabuf *bp,
    -				xfs_dir2_data_aoff_t offset,
    -				xfs_dir2_data_aoff_t len, int *needlogp,
    -				int *needscanp);
    -extern void xfs_dir2_data_use_free(struct xfs_trans *tp, struct xfs_dabuf *bp,
    -			       xfs_dir2_data_unused_t *dup,
    -			       xfs_dir2_data_aoff_t offset,
    -			       xfs_dir2_data_aoff_t len, int *needlogp,
    -			       int *needscanp);
    -
    -#endif	/* __XFS_DIR2_DATA_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_dir2_leaf.c b/sys/gnu/fs/xfs/xfs_dir2_leaf.c
    deleted file mode 100644
    index 5fe88d546c7..00000000000
    --- a/sys/gnu/fs/xfs/xfs_dir2_leaf.c
    +++ /dev/null
    @@ -1,1877 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_da_btree.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_bmap.h"
    -#include "xfs_dir2_data.h"
    -#include "xfs_dir2_leaf.h"
    -#include "xfs_dir2_block.h"
    -#include "xfs_dir2_node.h"
    -#include "xfs_dir2_trace.h"
    -#include "xfs_error.h"
    -
    -/*
    - * Local function declarations.
    - */
    -#ifdef DEBUG
    -static void xfs_dir2_leaf_check(xfs_inode_t *dp, xfs_dabuf_t *bp);
    -#else
    -#define	xfs_dir2_leaf_check(dp, bp)
    -#endif
    -static int xfs_dir2_leaf_lookup_int(xfs_da_args_t *args, xfs_dabuf_t **lbpp,
    -				    int *indexp, xfs_dabuf_t **dbpp);
    -static void xfs_dir2_leaf_log_bests(struct xfs_trans *tp, struct xfs_dabuf *bp,
    -				    int first, int last);
    -static void xfs_dir2_leaf_log_tail(struct xfs_trans *tp, struct xfs_dabuf *bp);
    -
    -
    -/*
    - * Convert a block form directory to a leaf form directory.
    - */
    -int						/* error */
    -xfs_dir2_block_to_leaf(
    -	xfs_da_args_t		*args,		/* operation arguments */
    -	xfs_dabuf_t		*dbp)		/* input block's buffer */
    -{
    -	__be16			*bestsp;	/* leaf's bestsp entries */
    -	xfs_dablk_t		blkno;		/* leaf block's bno */
    -	xfs_dir2_block_t	*block;		/* block structure */
    -	xfs_dir2_leaf_entry_t	*blp;		/* block's leaf entries */
    -	xfs_dir2_block_tail_t	*btp;		/* block's tail */
    -	xfs_inode_t		*dp;		/* incore directory inode */
    -	int			error;		/* error return code */
    -	xfs_dabuf_t		*lbp;		/* leaf block's buffer */
    -	xfs_dir2_db_t		ldb;		/* leaf block's bno */
    -	xfs_dir2_leaf_t		*leaf;		/* leaf structure */
    -	xfs_dir2_leaf_tail_t	*ltp;		/* leaf's tail */
    -	xfs_mount_t		*mp;		/* filesystem mount point */
    -	int			needlog;	/* need to log block header */
    -	int			needscan;	/* need to rescan bestfree */
    -	xfs_trans_t		*tp;		/* transaction pointer */
    -
    -	xfs_dir2_trace_args_b("block_to_leaf", args, dbp);
    -	dp = args->dp;
    -	mp = dp->i_mount;
    -	tp = args->trans;
    -	/*
    -	 * Add the leaf block to the inode.
    -	 * This interface will only put blocks in the leaf/node range.
    -	 * Since that's empty now, we'll get the root (block 0 in range).
    -	 */
    -	if ((error = xfs_da_grow_inode(args, &blkno))) {
    -		return error;
    -	}
    -	ldb = XFS_DIR2_DA_TO_DB(mp, blkno);
    -	ASSERT(ldb == XFS_DIR2_LEAF_FIRSTDB(mp));
    -	/*
    -	 * Initialize the leaf block, get a buffer for it.
    -	 */
    -	if ((error = xfs_dir2_leaf_init(args, ldb, &lbp, XFS_DIR2_LEAF1_MAGIC))) {
    -		return error;
    -	}
    -	ASSERT(lbp != NULL);
    -	leaf = lbp->data;
    -	block = dbp->data;
    -	xfs_dir2_data_check(dp, dbp);
    -	btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
    -	blp = XFS_DIR2_BLOCK_LEAF_P(btp);
    -	/*
    -	 * Set the counts in the leaf header.
    -	 */
    -	leaf->hdr.count = cpu_to_be16(be32_to_cpu(btp->count));
    -	leaf->hdr.stale = cpu_to_be16(be32_to_cpu(btp->stale));
    -	/*
    -	 * Could compact these but I think we always do the conversion
    -	 * after squeezing out stale entries.
    -	 */
    -	memcpy(leaf->ents, blp, be32_to_cpu(btp->count) * sizeof(xfs_dir2_leaf_entry_t));
    -	xfs_dir2_leaf_log_ents(tp, lbp, 0, be16_to_cpu(leaf->hdr.count) - 1);
    -	needscan = 0;
    -	needlog = 1;
    -	/*
    -	 * Make the space formerly occupied by the leaf entries and block
    -	 * tail be free.
    -	 */
    -	xfs_dir2_data_make_free(tp, dbp,
    -		(xfs_dir2_data_aoff_t)((char *)blp - (char *)block),
    -		(xfs_dir2_data_aoff_t)((char *)block + mp->m_dirblksize -
    -				       (char *)blp),
    -		&needlog, &needscan);
    -	/*
    -	 * Fix up the block header, make it a data block.
    -	 */
    -	block->hdr.magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC);
    -	if (needscan)
    -		xfs_dir2_data_freescan(mp, (xfs_dir2_data_t *)block, &needlog,
    -			NULL);
    -	/*
    -	 * Set up leaf tail and bests table.
    -	 */
    -	ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
    -	ltp->bestcount = cpu_to_be32(1);
    -	bestsp = XFS_DIR2_LEAF_BESTS_P(ltp);
    -	bestsp[0] =  block->hdr.bestfree[0].length;
    -	/*
    -	 * Log the data header and leaf bests table.
    -	 */
    -	if (needlog)
    -		xfs_dir2_data_log_header(tp, dbp);
    -	xfs_dir2_leaf_check(dp, lbp);
    -	xfs_dir2_data_check(dp, dbp);
    -	xfs_dir2_leaf_log_bests(tp, lbp, 0, 0);
    -	xfs_da_buf_done(lbp);
    -	return 0;
    -}
    -
    -/*
    - * Add an entry to a leaf form directory.
    - */
    -int						/* error */
    -xfs_dir2_leaf_addname(
    -	xfs_da_args_t		*args)		/* operation arguments */
    -{
    -	__be16			*bestsp;	/* freespace table in leaf */
    -	int			compact;	/* need to compact leaves */
    -	xfs_dir2_data_t		*data;		/* data block structure */
    -	xfs_dabuf_t		*dbp;		/* data block buffer */
    -	xfs_dir2_data_entry_t	*dep;		/* data block entry */
    -	xfs_inode_t		*dp;		/* incore directory inode */
    -	xfs_dir2_data_unused_t	*dup;		/* data unused entry */
    -	int			error;		/* error return value */
    -	int			grown;		/* allocated new data block */
    -	int			highstale;	/* index of next stale leaf */
    -	int			i;		/* temporary, index */
    -	int			index;		/* leaf table position */
    -	xfs_dabuf_t		*lbp;		/* leaf's buffer */
    -	xfs_dir2_leaf_t		*leaf;		/* leaf structure */
    -	int			length;		/* length of new entry */
    -	xfs_dir2_leaf_entry_t	*lep;		/* leaf entry table pointer */
    -	int			lfloglow;	/* low leaf logging index */
    -	int			lfloghigh;	/* high leaf logging index */
    -	int			lowstale;	/* index of prev stale leaf */
    -	xfs_dir2_leaf_tail_t	*ltp;		/* leaf tail pointer */
    -	xfs_mount_t		*mp;		/* filesystem mount point */
    -	int			needbytes;	/* leaf block bytes needed */
    -	int			needlog;	/* need to log data header */
    -	int			needscan;	/* need to rescan data free */
    -	__be16			*tagp;		/* end of data entry */
    -	xfs_trans_t		*tp;		/* transaction pointer */
    -	xfs_dir2_db_t		use_block;	/* data block number */
    -
    -	xfs_dir2_trace_args("leaf_addname", args);
    -	dp = args->dp;
    -	tp = args->trans;
    -	mp = dp->i_mount;
    -	/*
    -	 * Read the leaf block.
    -	 */
    -	error = xfs_da_read_buf(tp, dp, mp->m_dirleafblk, -1, &lbp,
    -		XFS_DATA_FORK);
    -	if (error) {
    -		return error;
    -	}
    -	ASSERT(lbp != NULL);
    -	/*
    -	 * Look up the entry by hash value and name.
    -	 * We know it's not there, our caller has already done a lookup.
    -	 * So the index is of the entry to insert in front of.
    -	 * But if there are dup hash values the index is of the first of those.
    -	 */
    -	index = xfs_dir2_leaf_search_hash(args, lbp);
    -	leaf = lbp->data;
    -	ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
    -	bestsp = XFS_DIR2_LEAF_BESTS_P(ltp);
    -	length = XFS_DIR2_DATA_ENTSIZE(args->namelen);
    -	/*
    -	 * See if there are any entries with the same hash value
    -	 * and space in their block for the new entry.
    -	 * This is good because it puts multiple same-hash value entries
    -	 * in a data block, improving the lookup of those entries.
    -	 */
    -	for (use_block = -1, lep = &leaf->ents[index];
    -	     index < be16_to_cpu(leaf->hdr.count) && be32_to_cpu(lep->hashval) == args->hashval;
    -	     index++, lep++) {
    -		if (be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR)
    -			continue;
    -		i = XFS_DIR2_DATAPTR_TO_DB(mp, be32_to_cpu(lep->address));
    -		ASSERT(i < be32_to_cpu(ltp->bestcount));
    -		ASSERT(be16_to_cpu(bestsp[i]) != NULLDATAOFF);
    -		if (be16_to_cpu(bestsp[i]) >= length) {
    -			use_block = i;
    -			break;
    -		}
    -	}
    -	/*
    -	 * Didn't find a block yet, linear search all the data blocks.
    -	 */
    -	if (use_block == -1) {
    -		for (i = 0; i < be32_to_cpu(ltp->bestcount); i++) {
    -			/*
    -			 * Remember a block we see that's missing.
    -			 */
    -			if (be16_to_cpu(bestsp[i]) == NULLDATAOFF && use_block == -1)
    -				use_block = i;
    -			else if (be16_to_cpu(bestsp[i]) >= length) {
    -				use_block = i;
    -				break;
    -			}
    -		}
    -	}
    -	/*
    -	 * How many bytes do we need in the leaf block?
    -	 */
    -	needbytes =
    -		(leaf->hdr.stale ? 0 : (uint)sizeof(leaf->ents[0])) +
    -		(use_block != -1 ? 0 : (uint)sizeof(leaf->bests[0]));
    -	/*
    -	 * Now kill use_block if it refers to a missing block, so we
    -	 * can use it as an indication of allocation needed.
    -	 */
    -	if (use_block != -1 && be16_to_cpu(bestsp[use_block]) == NULLDATAOFF)
    -		use_block = -1;
    -	/*
    -	 * If we don't have enough free bytes but we can make enough
    -	 * by compacting out stale entries, we'll do that.
    -	 */
    -	if ((char *)bestsp - (char *)&leaf->ents[be16_to_cpu(leaf->hdr.count)] < needbytes &&
    -	    be16_to_cpu(leaf->hdr.stale) > 1) {
    -		compact = 1;
    -	}
    -	/*
    -	 * Otherwise if we don't have enough free bytes we need to
    -	 * convert to node form.
    -	 */
    -	else if ((char *)bestsp - (char *)&leaf->ents[be16_to_cpu(leaf->hdr.count)] <
    -		 needbytes) {
    -		/*
    -		 * Just checking or no space reservation, give up.
    -		 */
    -		if (args->justcheck || args->total == 0) {
    -			xfs_da_brelse(tp, lbp);
    -			return XFS_ERROR(ENOSPC);
    -		}
    -		/*
    -		 * Convert to node form.
    -		 */
    -		error = xfs_dir2_leaf_to_node(args, lbp);
    -		xfs_da_buf_done(lbp);
    -		if (error)
    -			return error;
    -		/*
    -		 * Then add the new entry.
    -		 */
    -		return xfs_dir2_node_addname(args);
    -	}
    -	/*
    -	 * Otherwise it will fit without compaction.
    -	 */
    -	else
    -		compact = 0;
    -	/*
    -	 * If just checking, then it will fit unless we needed to allocate
    -	 * a new data block.
    -	 */
    -	if (args->justcheck) {
    -		xfs_da_brelse(tp, lbp);
    -		return use_block == -1 ? XFS_ERROR(ENOSPC) : 0;
    -	}
    -	/*
    -	 * If no allocations are allowed, return now before we've
    -	 * changed anything.
    -	 */
    -	if (args->total == 0 && use_block == -1) {
    -		xfs_da_brelse(tp, lbp);
    -		return XFS_ERROR(ENOSPC);
    -	}
    -	/*
    -	 * Need to compact the leaf entries, removing stale ones.
    -	 * Leave one stale entry behind - the one closest to our
    -	 * insertion index - and we'll shift that one to our insertion
    -	 * point later.
    -	 */
    -	if (compact) {
    -		xfs_dir2_leaf_compact_x1(lbp, &index, &lowstale, &highstale,
    -			&lfloglow, &lfloghigh);
    -	}
    -	/*
    -	 * There are stale entries, so we'll need log-low and log-high
    -	 * impossibly bad values later.
    -	 */
    -	else if (be16_to_cpu(leaf->hdr.stale)) {
    -		lfloglow = be16_to_cpu(leaf->hdr.count);
    -		lfloghigh = -1;
    -	}
    -	/*
    -	 * If there was no data block space found, we need to allocate
    -	 * a new one.
    -	 */
    -	if (use_block == -1) {
    -		/*
    -		 * Add the new data block.
    -		 */
    -		if ((error = xfs_dir2_grow_inode(args, XFS_DIR2_DATA_SPACE,
    -				&use_block))) {
    -			xfs_da_brelse(tp, lbp);
    -			return error;
    -		}
    -		/*
    -		 * Initialize the block.
    -		 */
    -		if ((error = xfs_dir2_data_init(args, use_block, &dbp))) {
    -			xfs_da_brelse(tp, lbp);
    -			return error;
    -		}
    -		/*
    -		 * If we're adding a new data block on the end we need to
    -		 * extend the bests table.  Copy it up one entry.
    -		 */
    -		if (use_block >= be32_to_cpu(ltp->bestcount)) {
    -			bestsp--;
    -			memmove(&bestsp[0], &bestsp[1],
    -				be32_to_cpu(ltp->bestcount) * sizeof(bestsp[0]));
    -			be32_add(<p->bestcount, 1);
    -			xfs_dir2_leaf_log_tail(tp, lbp);
    -			xfs_dir2_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1);
    -		}
    -		/*
    -		 * If we're filling in a previously empty block just log it.
    -		 */
    -		else
    -			xfs_dir2_leaf_log_bests(tp, lbp, use_block, use_block);
    -		data = dbp->data;
    -		bestsp[use_block] = data->hdr.bestfree[0].length;
    -		grown = 1;
    -	}
    -	/*
    -	 * Already had space in some data block.
    -	 * Just read that one in.
    -	 */
    -	else {
    -		if ((error =
    -		    xfs_da_read_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, use_block),
    -			    -1, &dbp, XFS_DATA_FORK))) {
    -			xfs_da_brelse(tp, lbp);
    -			return error;
    -		}
    -		data = dbp->data;
    -		grown = 0;
    -	}
    -	xfs_dir2_data_check(dp, dbp);
    -	/*
    -	 * Point to the biggest freespace in our data block.
    -	 */
    -	dup = (xfs_dir2_data_unused_t *)
    -	      ((char *)data + be16_to_cpu(data->hdr.bestfree[0].offset));
    -	ASSERT(be16_to_cpu(dup->length) >= length);
    -	needscan = needlog = 0;
    -	/*
    -	 * Mark the initial part of our freespace in use for the new entry.
    -	 */
    -	xfs_dir2_data_use_free(tp, dbp, dup,
    -		(xfs_dir2_data_aoff_t)((char *)dup - (char *)data), length,
    -		&needlog, &needscan);
    -	/*
    -	 * Initialize our new entry (at last).
    -	 */
    -	dep = (xfs_dir2_data_entry_t *)dup;
    -	INT_SET(dep->inumber, ARCH_CONVERT, args->inumber);
    -	dep->namelen = args->namelen;
    -	memcpy(dep->name, args->name, dep->namelen);
    -	tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
    -	*tagp = cpu_to_be16((char *)dep - (char *)data);
    -	/*
    -	 * Need to scan fix up the bestfree table.
    -	 */
    -	if (needscan)
    -		xfs_dir2_data_freescan(mp, data, &needlog, NULL);
    -	/*
    -	 * Need to log the data block's header.
    -	 */
    -	if (needlog)
    -		xfs_dir2_data_log_header(tp, dbp);
    -	xfs_dir2_data_log_entry(tp, dbp, dep);
    -	/*
    -	 * If the bests table needs to be changed, do it.
    -	 * Log the change unless we've already done that.
    -	 */
    -	if (be16_to_cpu(bestsp[use_block]) != be16_to_cpu(data->hdr.bestfree[0].length)) {
    -		bestsp[use_block] = data->hdr.bestfree[0].length;
    -		if (!grown)
    -			xfs_dir2_leaf_log_bests(tp, lbp, use_block, use_block);
    -	}
    -	/*
    -	 * Now we need to make room to insert the leaf entry.
    -	 * If there are no stale entries, we just insert a hole at index.
    -	 */
    -	if (!leaf->hdr.stale) {
    -		/*
    -		 * lep is still good as the index leaf entry.
    -		 */
    -		if (index < be16_to_cpu(leaf->hdr.count))
    -			memmove(lep + 1, lep,
    -				(be16_to_cpu(leaf->hdr.count) - index) * sizeof(*lep));
    -		/*
    -		 * Record low and high logging indices for the leaf.
    -		 */
    -		lfloglow = index;
    -		lfloghigh = be16_to_cpu(leaf->hdr.count);
    -		be16_add(&leaf->hdr.count, 1);
    -	}
    -	/*
    -	 * There are stale entries.
    -	 * We will use one of them for the new entry.
    -	 * It's probably not at the right location, so we'll have to
    -	 * shift some up or down first.
    -	 */
    -	else {
    -		/*
    -		 * If we didn't compact before, we need to find the nearest
    -		 * stale entries before and after our insertion point.
    -		 */
    -		if (compact == 0) {
    -			/*
    -			 * Find the first stale entry before the insertion
    -			 * point, if any.
    -			 */
    -			for (lowstale = index - 1;
    -			     lowstale >= 0 &&
    -				be32_to_cpu(leaf->ents[lowstale].address) !=
    -				XFS_DIR2_NULL_DATAPTR;
    -			     lowstale--)
    -				continue;
    -			/*
    -			 * Find the next stale entry at or after the insertion
    -			 * point, if any.   Stop if we go so far that the
    -			 * lowstale entry would be better.
    -			 */
    -			for (highstale = index;
    -			     highstale < be16_to_cpu(leaf->hdr.count) &&
    -				be32_to_cpu(leaf->ents[highstale].address) !=
    -				XFS_DIR2_NULL_DATAPTR &&
    -				(lowstale < 0 ||
    -				 index - lowstale - 1 >= highstale - index);
    -			     highstale++)
    -				continue;
    -		}
    -		/*
    -		 * If the low one is better, use it.
    -		 */
    -		if (lowstale >= 0 &&
    -		    (highstale == be16_to_cpu(leaf->hdr.count) ||
    -		     index - lowstale - 1 < highstale - index)) {
    -			ASSERT(index - lowstale - 1 >= 0);
    -			ASSERT(be32_to_cpu(leaf->ents[lowstale].address) ==
    -			       XFS_DIR2_NULL_DATAPTR);
    -			/*
    -			 * Copy entries up to cover the stale entry
    -			 * and make room for the new entry.
    -			 */
    -			if (index - lowstale - 1 > 0)
    -				memmove(&leaf->ents[lowstale],
    -					&leaf->ents[lowstale + 1],
    -					(index - lowstale - 1) * sizeof(*lep));
    -			lep = &leaf->ents[index - 1];
    -			lfloglow = MIN(lowstale, lfloglow);
    -			lfloghigh = MAX(index - 1, lfloghigh);
    -		}
    -		/*
    -		 * The high one is better, so use that one.
    -		 */
    -		else {
    -			ASSERT(highstale - index >= 0);
    -			ASSERT(be32_to_cpu(leaf->ents[highstale].address) ==
    -			       XFS_DIR2_NULL_DATAPTR);
    -			/*
    -			 * Copy entries down to cover the stale entry
    -			 * and make room for the new entry.
    -			 */
    -			if (highstale - index > 0)
    -				memmove(&leaf->ents[index + 1],
    -					&leaf->ents[index],
    -					(highstale - index) * sizeof(*lep));
    -			lep = &leaf->ents[index];
    -			lfloglow = MIN(index, lfloglow);
    -			lfloghigh = MAX(highstale, lfloghigh);
    -		}
    -		be16_add(&leaf->hdr.stale, -1);
    -	}
    -	/*
    -	 * Fill in the new leaf entry.
    -	 */
    -	lep->hashval = cpu_to_be32(args->hashval);
    -	lep->address = cpu_to_be32(XFS_DIR2_DB_OFF_TO_DATAPTR(mp, use_block,
    -				be16_to_cpu(*tagp)));
    -	/*
    -	 * Log the leaf fields and give up the buffers.
    -	 */
    -	xfs_dir2_leaf_log_header(tp, lbp);
    -	xfs_dir2_leaf_log_ents(tp, lbp, lfloglow, lfloghigh);
    -	xfs_dir2_leaf_check(dp, lbp);
    -	xfs_da_buf_done(lbp);
    -	xfs_dir2_data_check(dp, dbp);
    -	xfs_da_buf_done(dbp);
    -	return 0;
    -}
    -
    -#ifdef DEBUG
    -/*
    - * Check the internal consistency of a leaf1 block.
    - * Pop an assert if something is wrong.
    - */
    -void
    -xfs_dir2_leaf_check(
    -	xfs_inode_t		*dp,		/* incore directory inode */
    -	xfs_dabuf_t		*bp)		/* leaf's buffer */
    -{
    -	int			i;		/* leaf index */
    -	xfs_dir2_leaf_t		*leaf;		/* leaf structure */
    -	xfs_dir2_leaf_tail_t	*ltp;		/* leaf tail pointer */
    -	xfs_mount_t		*mp;		/* filesystem mount point */
    -	int			stale;		/* count of stale leaves */
    -
    -	leaf = bp->data;
    -	mp = dp->i_mount;
    -	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC);
    -	/*
    -	 * This value is not restrictive enough.
    -	 * Should factor in the size of the bests table as well.
    -	 * We can deduce a value for that from di_size.
    -	 */
    -	ASSERT(be16_to_cpu(leaf->hdr.count) <= XFS_DIR2_MAX_LEAF_ENTS(mp));
    -	ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
    -	/*
    -	 * Leaves and bests don't overlap.
    -	 */
    -	ASSERT((char *)&leaf->ents[be16_to_cpu(leaf->hdr.count)] <=
    -	       (char *)XFS_DIR2_LEAF_BESTS_P(ltp));
    -	/*
    -	 * Check hash value order, count stale entries.
    -	 */
    -	for (i = stale = 0; i < be16_to_cpu(leaf->hdr.count); i++) {
    -		if (i + 1 < be16_to_cpu(leaf->hdr.count))
    -			ASSERT(be32_to_cpu(leaf->ents[i].hashval) <=
    -			       be32_to_cpu(leaf->ents[i + 1].hashval));
    -		if (be32_to_cpu(leaf->ents[i].address) == XFS_DIR2_NULL_DATAPTR)
    -			stale++;
    -	}
    -	ASSERT(be16_to_cpu(leaf->hdr.stale) == stale);
    -}
    -#endif	/* DEBUG */
    -
    -/*
    - * Compact out any stale entries in the leaf.
    - * Log the header and changed leaf entries, if any.
    - */
    -void
    -xfs_dir2_leaf_compact(
    -	xfs_da_args_t	*args,		/* operation arguments */
    -	xfs_dabuf_t	*bp)		/* leaf buffer */
    -{
    -	int		from;		/* source leaf index */
    -	xfs_dir2_leaf_t	*leaf;		/* leaf structure */
    -	int		loglow;		/* first leaf entry to log */
    -	int		to;		/* target leaf index */
    -
    -	leaf = bp->data;
    -	if (!leaf->hdr.stale) {
    -		return;
    -	}
    -	/*
    -	 * Compress out the stale entries in place.
    -	 */
    -	for (from = to = 0, loglow = -1; from < be16_to_cpu(leaf->hdr.count); from++) {
    -		if (be32_to_cpu(leaf->ents[from].address) == XFS_DIR2_NULL_DATAPTR)
    -			continue;
    -		/*
    -		 * Only actually copy the entries that are different.
    -		 */
    -		if (from > to) {
    -			if (loglow == -1)
    -				loglow = to;
    -			leaf->ents[to] = leaf->ents[from];
    -		}
    -		to++;
    -	}
    -	/*
    -	 * Update and log the header, log the leaf entries.
    -	 */
    -	ASSERT(be16_to_cpu(leaf->hdr.stale) == from - to);
    -	be16_add(&leaf->hdr.count, -(be16_to_cpu(leaf->hdr.stale)));
    -	leaf->hdr.stale = 0;
    -	xfs_dir2_leaf_log_header(args->trans, bp);
    -	if (loglow != -1)
    -		xfs_dir2_leaf_log_ents(args->trans, bp, loglow, to - 1);
    -}
    -
    -/*
    - * Compact the leaf entries, removing stale ones.
    - * Leave one stale entry behind - the one closest to our
    - * insertion index - and the caller will shift that one to our insertion
    - * point later.
    - * Return new insertion index, where the remaining stale entry is,
    - * and leaf logging indices.
    - */
    -void
    -xfs_dir2_leaf_compact_x1(
    -	xfs_dabuf_t	*bp,		/* leaf buffer */
    -	int		*indexp,	/* insertion index */
    -	int		*lowstalep,	/* out: stale entry before us */
    -	int		*highstalep,	/* out: stale entry after us */
    -	int		*lowlogp,	/* out: low log index */
    -	int		*highlogp)	/* out: high log index */
    -{
    -	int		from;		/* source copy index */
    -	int		highstale;	/* stale entry at/after index */
    -	int		index;		/* insertion index */
    -	int		keepstale;	/* source index of kept stale */
    -	xfs_dir2_leaf_t	*leaf;		/* leaf structure */
    -	int		lowstale;	/* stale entry before index */
    -	int		newindex=0;	/* new insertion index */
    -	int		to;		/* destination copy index */
    -
    -	leaf = bp->data;
    -	ASSERT(be16_to_cpu(leaf->hdr.stale) > 1);
    -	index = *indexp;
    -	/*
    -	 * Find the first stale entry before our index, if any.
    -	 */
    -	for (lowstale = index - 1;
    -	     lowstale >= 0 &&
    -		be32_to_cpu(leaf->ents[lowstale].address) != XFS_DIR2_NULL_DATAPTR;
    -	     lowstale--)
    -		continue;
    -	/*
    -	 * Find the first stale entry at or after our index, if any.
    -	 * Stop if the answer would be worse than lowstale.
    -	 */
    -	for (highstale = index;
    -	     highstale < be16_to_cpu(leaf->hdr.count) &&
    -		be32_to_cpu(leaf->ents[highstale].address) != XFS_DIR2_NULL_DATAPTR &&
    -		(lowstale < 0 || index - lowstale > highstale - index);
    -	     highstale++)
    -		continue;
    -	/*
    -	 * Pick the better of lowstale and highstale.
    -	 */
    -	if (lowstale >= 0 &&
    -	    (highstale == be16_to_cpu(leaf->hdr.count) ||
    -	     index - lowstale <= highstale - index))
    -		keepstale = lowstale;
    -	else
    -		keepstale = highstale;
    -	/*
    -	 * Copy the entries in place, removing all the stale entries
    -	 * except keepstale.
    -	 */
    -	for (from = to = 0; from < be16_to_cpu(leaf->hdr.count); from++) {
    -		/*
    -		 * Notice the new value of index.
    -		 */
    -		if (index == from)
    -			newindex = to;
    -		if (from != keepstale &&
    -		    be32_to_cpu(leaf->ents[from].address) == XFS_DIR2_NULL_DATAPTR) {
    -			if (from == to)
    -				*lowlogp = to;
    -			continue;
    -		}
    -		/*
    -		 * Record the new keepstale value for the insertion.
    -		 */
    -		if (from == keepstale)
    -			lowstale = highstale = to;
    -		/*
    -		 * Copy only the entries that have moved.
    -		 */
    -		if (from > to)
    -			leaf->ents[to] = leaf->ents[from];
    -		to++;
    -	}
    -	ASSERT(from > to);
    -	/*
    -	 * If the insertion point was past the last entry,
    -	 * set the new insertion point accordingly.
    -	 */
    -	if (index == from)
    -		newindex = to;
    -	*indexp = newindex;
    -	/*
    -	 * Adjust the leaf header values.
    -	 */
    -	be16_add(&leaf->hdr.count, -(from - to));
    -	leaf->hdr.stale = cpu_to_be16(1);
    -	/*
    -	 * Remember the low/high stale value only in the "right"
    -	 * direction.
    -	 */
    -	if (lowstale >= newindex)
    -		lowstale = -1;
    -	else
    -		highstale = be16_to_cpu(leaf->hdr.count);
    -	*highlogp = be16_to_cpu(leaf->hdr.count) - 1;
    -	*lowstalep = lowstale;
    -	*highstalep = highstale;
    -}
    -
    -/*
    - * Getdents (readdir) for leaf and node directories.
    - * This reads the data blocks only, so is the same for both forms.
    - */
    -int						/* error */
    -xfs_dir2_leaf_getdents(
    -	xfs_trans_t		*tp,		/* transaction pointer */
    -	xfs_inode_t		*dp,		/* incore directory inode */
    -	uio_t			*uio,		/* I/O control & vectors */
    -	int			*eofp,		/* out: reached end of dir */
    -	xfs_dirent_t		*dbp,		/* caller's buffer */
    -	xfs_dir2_put_t		put)		/* ABI formatting routine */
    -{
    -	xfs_dabuf_t		*bp;		/* data block buffer */
    -	int			byteoff;	/* offset in current block */
    -	xfs_dir2_db_t		curdb;		/* db for current block */
    -	xfs_dir2_off_t		curoff;		/* current overall offset */
    -	xfs_dir2_data_t		*data;		/* data block structure */
    -	xfs_dir2_data_entry_t	*dep;		/* data entry */
    -	xfs_dir2_data_unused_t	*dup;		/* unused entry */
    -	int			eof;		/* reached end of directory */
    -	int			error = 0;	/* error return value */
    -	int			i;		/* temporary loop index */
    -	int			j;		/* temporary loop index */
    -	int			length;		/* temporary length value */
    -	xfs_bmbt_irec_t		*map;		/* map vector for blocks */
    -	xfs_extlen_t		map_blocks;	/* number of fsbs in map */
    -	xfs_dablk_t		map_off;	/* last mapped file offset */
    -	int			map_size;	/* total entries in *map */
    -	int			map_valid;	/* valid entries in *map */
    -	xfs_mount_t		*mp;		/* filesystem mount point */
    -	xfs_dir2_off_t		newoff;		/* new curoff after new blk */
    -	int			nmap;		/* mappings to ask xfs_bmapi */
    -	xfs_dir2_put_args_t	*p;		/* formatting arg bundle */
    -	char			*ptr = NULL;	/* pointer to current data */
    -	int			ra_current;	/* number of read-ahead blks */
    -	int			ra_index;	/* *map index for read-ahead */
    -	int			ra_offset;	/* map entry offset for ra */
    -	int			ra_want;	/* readahead count wanted */
    -
    -	/*
    -	 * If the offset is at or past the largest allowed value,
    -	 * give up right away, return eof.
    -	 */
    -	if (uio->uio_offset >= XFS_DIR2_MAX_DATAPTR) {
    -		*eofp = 1;
    -		return 0;
    -	}
    -	mp = dp->i_mount;
    -	/*
    -	 * Setup formatting arguments.
    -	 */
    -	p = kmem_alloc(sizeof(*p), KM_SLEEP);
    -	p->dbp = dbp;
    -	p->put = put;
    -	p->uio = uio;
    -	/*
    -	 * Set up to bmap a number of blocks based on the caller's
    -	 * buffer size, the directory block size, and the filesystem
    -	 * block size.
    -	 */
    -	map_size =
    -		howmany(uio->uio_resid + mp->m_dirblksize,
    -			mp->m_sb.sb_blocksize);
    -	map = kmem_alloc(map_size * sizeof(*map), KM_SLEEP);
    -	map_valid = ra_index = ra_offset = ra_current = map_blocks = 0;
    -	bp = NULL;
    -	eof = 1;
    -	/*
    -	 * Inside the loop we keep the main offset value as a byte offset
    -	 * in the directory file.
    -	 */
    -	curoff = XFS_DIR2_DATAPTR_TO_BYTE(mp, uio->uio_offset);
    -	/*
    -	 * Force this conversion through db so we truncate the offset
    -	 * down to get the start of the data block.
    -	 */
    -	map_off = XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_BYTE_TO_DB(mp, curoff));
    -	/*
    -	 * Loop over directory entries until we reach the end offset.
    -	 * Get more blocks and readahead as necessary.
    -	 */
    -	while (curoff < XFS_DIR2_LEAF_OFFSET) {
    -		/*
    -		 * If we have no buffer, or we're off the end of the
    -		 * current buffer, need to get another one.
    -		 */
    -		if (!bp || ptr >= (char *)bp->data + mp->m_dirblksize) {
    -			/*
    -			 * If we have a buffer, we need to release it and
    -			 * take it out of the mapping.
    -			 */
    -			if (bp) {
    -				xfs_da_brelse(tp, bp);
    -				bp = NULL;
    -				map_blocks -= mp->m_dirblkfsbs;
    -				/*
    -				 * Loop to get rid of the extents for the
    -				 * directory block.
    -				 */
    -				for (i = mp->m_dirblkfsbs; i > 0; ) {
    -					j = MIN((int)map->br_blockcount, i);
    -					map->br_blockcount -= j;
    -					map->br_startblock += j;
    -					map->br_startoff += j;
    -					/*
    -					 * If mapping is done, pitch it from
    -					 * the table.
    -					 */
    -					if (!map->br_blockcount && --map_valid)
    -						memmove(&map[0], &map[1],
    -							sizeof(map[0]) *
    -							map_valid);
    -					i -= j;
    -				}
    -			}
    -			/*
    -			 * Recalculate the readahead blocks wanted.
    -			 */
    -			ra_want = howmany(uio->uio_resid + mp->m_dirblksize,
    -					  mp->m_sb.sb_blocksize) - 1;
    -			/*
    -			 * If we don't have as many as we want, and we haven't
    -			 * run out of data blocks, get some more mappings.
    -			 */
    -			if (1 + ra_want > map_blocks &&
    -			    map_off <
    -			    XFS_DIR2_BYTE_TO_DA(mp, XFS_DIR2_LEAF_OFFSET)) {
    -				/*
    -				 * Get more bmaps, fill in after the ones
    -				 * we already have in the table.
    -				 */
    -				nmap = map_size - map_valid;
    -				error = xfs_bmapi(tp, dp,
    -					map_off,
    -					XFS_DIR2_BYTE_TO_DA(mp,
    -						XFS_DIR2_LEAF_OFFSET) - map_off,
    -					XFS_BMAPI_METADATA, NULL, 0,
    -					&map[map_valid], &nmap, NULL, NULL);
    -				/*
    -				 * Don't know if we should ignore this or
    -				 * try to return an error.
    -				 * The trouble with returning errors
    -				 * is that readdir will just stop without
    -				 * actually passing the error through.
    -				 */
    -				if (error)
    -					break;	/* XXX */
    -				/*
    -				 * If we got all the mappings we asked for,
    -				 * set the final map offset based on the
    -				 * last bmap value received.
    -				 * Otherwise, we've reached the end.
    -				 */
    -				if (nmap == map_size - map_valid)
    -					map_off =
    -					map[map_valid + nmap - 1].br_startoff +
    -					map[map_valid + nmap - 1].br_blockcount;
    -				else
    -					map_off =
    -						XFS_DIR2_BYTE_TO_DA(mp,
    -							XFS_DIR2_LEAF_OFFSET);
    -				/*
    -				 * Look for holes in the mapping, and
    -				 * eliminate them.  Count up the valid blocks.
    -				 */
    -				for (i = map_valid; i < map_valid + nmap; ) {
    -					if (map[i].br_startblock ==
    -					    HOLESTARTBLOCK) {
    -						nmap--;
    -						length = map_valid + nmap - i;
    -						if (length)
    -							memmove(&map[i],
    -								&map[i + 1],
    -								sizeof(map[i]) *
    -								length);
    -					} else {
    -						map_blocks +=
    -							map[i].br_blockcount;
    -						i++;
    -					}
    -				}
    -				map_valid += nmap;
    -			}
    -			/*
    -			 * No valid mappings, so no more data blocks.
    -			 */
    -			if (!map_valid) {
    -				curoff = XFS_DIR2_DA_TO_BYTE(mp, map_off);
    -				break;
    -			}
    -			/*
    -			 * Read the directory block starting at the first
    -			 * mapping.
    -			 */
    -			curdb = XFS_DIR2_DA_TO_DB(mp, map->br_startoff);
    -			error = xfs_da_read_buf(tp, dp, map->br_startoff,
    -				map->br_blockcount >= mp->m_dirblkfsbs ?
    -				    XFS_FSB_TO_DADDR(mp, map->br_startblock) :
    -				    -1,
    -				&bp, XFS_DATA_FORK);
    -			/*
    -			 * Should just skip over the data block instead
    -			 * of giving up.
    -			 */
    -			if (error)
    -				break;	/* XXX */
    -			/*
    -			 * Adjust the current amount of read-ahead: we just
    -			 * read a block that was previously ra.
    -			 */
    -			if (ra_current)
    -				ra_current -= mp->m_dirblkfsbs;
    -			/*
    -			 * Do we need more readahead?
    -			 */
    -			for (ra_index = ra_offset = i = 0;
    -			     ra_want > ra_current && i < map_blocks;
    -			     i += mp->m_dirblkfsbs) {
    -				ASSERT(ra_index < map_valid);
    -				/*
    -				 * Read-ahead a contiguous directory block.
    -				 */
    -				if (i > ra_current &&
    -				    map[ra_index].br_blockcount >=
    -				    mp->m_dirblkfsbs) {
    -					xfs_baread(mp->m_ddev_targp,
    -						XFS_FSB_TO_DADDR(mp,
    -						   map[ra_index].br_startblock +
    -						   ra_offset),
    -						(int)BTOBB(mp->m_dirblksize));
    -					ra_current = i;
    -				}
    -				/*
    -				 * Read-ahead a non-contiguous directory block.
    -				 * This doesn't use our mapping, but this
    -				 * is a very rare case.
    -				 */
    -				else if (i > ra_current) {
    -					(void)xfs_da_reada_buf(tp, dp,
    -						map[ra_index].br_startoff +
    -						ra_offset, XFS_DATA_FORK);
    -					ra_current = i;
    -				}
    -				/*
    -				 * Advance offset through the mapping table.
    -				 */
    -				for (j = 0; j < mp->m_dirblkfsbs; j++) {
    -					/*
    -					 * The rest of this extent but not
    -					 * more than a dir block.
    -					 */
    -					length = MIN(mp->m_dirblkfsbs,
    -						(int)(map[ra_index].br_blockcount -
    -						ra_offset));
    -					j += length;
    -					ra_offset += length;
    -					/*
    -					 * Advance to the next mapping if
    -					 * this one is used up.
    -					 */
    -					if (ra_offset ==
    -					    map[ra_index].br_blockcount) {
    -						ra_offset = 0;
    -						ra_index++;
    -					}
    -				}
    -			}
    -			/*
    -			 * Having done a read, we need to set a new offset.
    -			 */
    -			newoff = XFS_DIR2_DB_OFF_TO_BYTE(mp, curdb, 0);
    -			/*
    -			 * Start of the current block.
    -			 */
    -			if (curoff < newoff)
    -				curoff = newoff;
    -			/*
    -			 * Make sure we're in the right block.
    -			 */
    -			else if (curoff > newoff)
    -				ASSERT(XFS_DIR2_BYTE_TO_DB(mp, curoff) ==
    -				       curdb);
    -			data = bp->data;
    -			xfs_dir2_data_check(dp, bp);
    -			/*
    -			 * Find our position in the block.
    -			 */
    -			ptr = (char *)&data->u;
    -			byteoff = XFS_DIR2_BYTE_TO_OFF(mp, curoff);
    -			/*
    -			 * Skip past the header.
    -			 */
    -			if (byteoff == 0)
    -				curoff += (uint)sizeof(data->hdr);
    -			/*
    -			 * Skip past entries until we reach our offset.
    -			 */
    -			else {
    -				while ((char *)ptr - (char *)data < byteoff) {
    -					dup = (xfs_dir2_data_unused_t *)ptr;
    -
    -					if (be16_to_cpu(dup->freetag)
    -						  == XFS_DIR2_DATA_FREE_TAG) {
    -
    -						length = be16_to_cpu(dup->length);
    -						ptr += length;
    -						continue;
    -					}
    -					dep = (xfs_dir2_data_entry_t *)ptr;
    -					length =
    -					   XFS_DIR2_DATA_ENTSIZE(dep->namelen);
    -					ptr += length;
    -				}
    -				/*
    -				 * Now set our real offset.
    -				 */
    -				curoff =
    -					XFS_DIR2_DB_OFF_TO_BYTE(mp,
    -					    XFS_DIR2_BYTE_TO_DB(mp, curoff),
    -					    (char *)ptr - (char *)data);
    -				if (ptr >= (char *)data + mp->m_dirblksize) {
    -					continue;
    -				}
    -			}
    -		}
    -		/*
    -		 * We have a pointer to an entry.
    -		 * Is it a live one?
    -		 */
    -		dup = (xfs_dir2_data_unused_t *)ptr;
    -		/*
    -		 * No, it's unused, skip over it.
    -		 */
    -		if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
    -			length = be16_to_cpu(dup->length);
    -			ptr += length;
    -			curoff += length;
    -			continue;
    -		}
    -
    -		/*
    -		 * Copy the entry into the putargs, and try formatting it.
    -		 */
    -		dep = (xfs_dir2_data_entry_t *)ptr;
    -
    -		p->namelen = dep->namelen;
    -
    -		length = XFS_DIR2_DATA_ENTSIZE(p->namelen);
    -
    -		p->cook = XFS_DIR2_BYTE_TO_DATAPTR(mp, curoff + length);
    -
    -		p->ino = INT_GET(dep->inumber, ARCH_CONVERT);
    -#if XFS_BIG_INUMS
    -		p->ino += mp->m_inoadd;
    -#endif
    -		p->name = (char *)dep->name;
    -
    -		error = p->put(p);
    -
    -		/*
    -		 * Won't fit.  Return to caller.
    -		 */
    -		if (!p->done) {
    -			eof = 0;
    -			break;
    -		}
    -		/*
    -		 * Advance to next entry in the block.
    -		 */
    -		ptr += length;
    -		curoff += length;
    -	}
    -
    -	/*
    -	 * All done.  Set output offset value to current offset.
    -	 */
    -	*eofp = eof;
    -	if (curoff > XFS_DIR2_DATAPTR_TO_BYTE(mp, XFS_DIR2_MAX_DATAPTR))
    -		uio->uio_offset = XFS_DIR2_MAX_DATAPTR;
    -	else
    -		uio->uio_offset = XFS_DIR2_BYTE_TO_DATAPTR(mp, curoff);
    -	kmem_free(map, map_size * sizeof(*map));
    -	kmem_free(p, sizeof(*p));
    -	if (bp)
    -		xfs_da_brelse(tp, bp);
    -	return error;
    -}
    -
    -/*
    - * Initialize a new leaf block, leaf1 or leafn magic accepted.
    - */
    -int
    -xfs_dir2_leaf_init(
    -	xfs_da_args_t		*args,		/* operation arguments */
    -	xfs_dir2_db_t		bno,		/* directory block number */
    -	xfs_dabuf_t		**bpp,		/* out: leaf buffer */
    -	int			magic)		/* magic number for block */
    -{
    -	xfs_dabuf_t		*bp;		/* leaf buffer */
    -	xfs_inode_t		*dp;		/* incore directory inode */
    -	int			error;		/* error return code */
    -	xfs_dir2_leaf_t		*leaf;		/* leaf structure */
    -	xfs_dir2_leaf_tail_t	*ltp;		/* leaf tail structure */
    -	xfs_mount_t		*mp;		/* filesystem mount point */
    -	xfs_trans_t		*tp;		/* transaction pointer */
    -
    -	dp = args->dp;
    -	ASSERT(dp != NULL);
    -	tp = args->trans;
    -	mp = dp->i_mount;
    -	ASSERT(bno >= XFS_DIR2_LEAF_FIRSTDB(mp) &&
    -	       bno < XFS_DIR2_FREE_FIRSTDB(mp));
    -	/*
    -	 * Get the buffer for the block.
    -	 */
    -	error = xfs_da_get_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, bno), -1, &bp,
    -		XFS_DATA_FORK);
    -	if (error) {
    -		return error;
    -	}
    -	ASSERT(bp != NULL);
    -	leaf = bp->data;
    -	/*
    -	 * Initialize the header.
    -	 */
    -	leaf->hdr.info.magic = cpu_to_be16(magic);
    -	leaf->hdr.info.forw = 0;
    -	leaf->hdr.info.back = 0;
    -	leaf->hdr.count = 0;
    -	leaf->hdr.stale = 0;
    -	xfs_dir2_leaf_log_header(tp, bp);
    -	/*
    -	 * If it's a leaf-format directory initialize the tail.
    -	 * In this case our caller has the real bests table to copy into
    -	 * the block.
    -	 */
    -	if (magic == XFS_DIR2_LEAF1_MAGIC) {
    -		ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
    -		ltp->bestcount = 0;
    -		xfs_dir2_leaf_log_tail(tp, bp);
    -	}
    -	*bpp = bp;
    -	return 0;
    -}
    -
    -/*
    - * Log the bests entries indicated from a leaf1 block.
    - */
    -static void
    -xfs_dir2_leaf_log_bests(
    -	xfs_trans_t		*tp,		/* transaction pointer */
    -	xfs_dabuf_t		*bp,		/* leaf buffer */
    -	int			first,		/* first entry to log */
    -	int			last)		/* last entry to log */
    -{
    -	__be16			*firstb;	/* pointer to first entry */
    -	__be16			*lastb;		/* pointer to last entry */
    -	xfs_dir2_leaf_t		*leaf;		/* leaf structure */
    -	xfs_dir2_leaf_tail_t	*ltp;		/* leaf tail structure */
    -
    -	leaf = bp->data;
    -	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC);
    -	ltp = XFS_DIR2_LEAF_TAIL_P(tp->t_mountp, leaf);
    -	firstb = XFS_DIR2_LEAF_BESTS_P(ltp) + first;
    -	lastb = XFS_DIR2_LEAF_BESTS_P(ltp) + last;
    -	xfs_da_log_buf(tp, bp, (uint)((char *)firstb - (char *)leaf),
    -		(uint)((char *)lastb - (char *)leaf + sizeof(*lastb) - 1));
    -}
    -
    -/*
    - * Log the leaf entries indicated from a leaf1 or leafn block.
    - */
    -void
    -xfs_dir2_leaf_log_ents(
    -	xfs_trans_t		*tp,		/* transaction pointer */
    -	xfs_dabuf_t		*bp,		/* leaf buffer */
    -	int			first,		/* first entry to log */
    -	int			last)		/* last entry to log */
    -{
    -	xfs_dir2_leaf_entry_t	*firstlep;	/* pointer to first entry */
    -	xfs_dir2_leaf_entry_t	*lastlep;	/* pointer to last entry */
    -	xfs_dir2_leaf_t		*leaf;		/* leaf structure */
    -
    -	leaf = bp->data;
    -	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC ||
    -	       be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
    -	firstlep = &leaf->ents[first];
    -	lastlep = &leaf->ents[last];
    -	xfs_da_log_buf(tp, bp, (uint)((char *)firstlep - (char *)leaf),
    -		(uint)((char *)lastlep - (char *)leaf + sizeof(*lastlep) - 1));
    -}
    -
    -/*
    - * Log the header of the leaf1 or leafn block.
    - */
    -void
    -xfs_dir2_leaf_log_header(
    -	xfs_trans_t		*tp,		/* transaction pointer */
    -	xfs_dabuf_t		*bp)		/* leaf buffer */
    -{
    -	xfs_dir2_leaf_t		*leaf;		/* leaf structure */
    -
    -	leaf = bp->data;
    -	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC ||
    -	       be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
    -	xfs_da_log_buf(tp, bp, (uint)((char *)&leaf->hdr - (char *)leaf),
    -		(uint)(sizeof(leaf->hdr) - 1));
    -}
    -
    -/*
    - * Log the tail of the leaf1 block.
    - */
    -STATIC void
    -xfs_dir2_leaf_log_tail(
    -	xfs_trans_t		*tp,		/* transaction pointer */
    -	xfs_dabuf_t		*bp)		/* leaf buffer */
    -{
    -	xfs_dir2_leaf_t		*leaf;		/* leaf structure */
    -	xfs_dir2_leaf_tail_t	*ltp;		/* leaf tail structure */
    -	xfs_mount_t		*mp;		/* filesystem mount point */
    -
    -	mp = tp->t_mountp;
    -	leaf = bp->data;
    -	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC);
    -	ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
    -	xfs_da_log_buf(tp, bp, (uint)((char *)ltp - (char *)leaf),
    -		(uint)(mp->m_dirblksize - 1));
    -}
    -
    -/*
    - * Look up the entry referred to by args in the leaf format directory.
    - * Most of the work is done by the xfs_dir2_leaf_lookup_int routine which
    - * is also used by the node-format code.
    - */
    -int
    -xfs_dir2_leaf_lookup(
    -	xfs_da_args_t		*args)		/* operation arguments */
    -{
    -	xfs_dabuf_t		*dbp;		/* data block buffer */
    -	xfs_dir2_data_entry_t	*dep;		/* data block entry */
    -	xfs_inode_t		*dp;		/* incore directory inode */
    -	int			error;		/* error return code */
    -	int			index;		/* found entry index */
    -	xfs_dabuf_t		*lbp;		/* leaf buffer */
    -	xfs_dir2_leaf_t		*leaf;		/* leaf structure */
    -	xfs_dir2_leaf_entry_t	*lep;		/* leaf entry */
    -	xfs_trans_t		*tp;		/* transaction pointer */
    -
    -	xfs_dir2_trace_args("leaf_lookup", args);
    -	/*
    -	 * Look up name in the leaf block, returning both buffers and index.
    -	 */
    -	if ((error = xfs_dir2_leaf_lookup_int(args, &lbp, &index, &dbp))) {
    -		return error;
    -	}
    -	tp = args->trans;
    -	dp = args->dp;
    -	xfs_dir2_leaf_check(dp, lbp);
    -	leaf = lbp->data;
    -	/*
    -	 * Get to the leaf entry and contained data entry address.
    -	 */
    -	lep = &leaf->ents[index];
    -	/*
    -	 * Point to the data entry.
    -	 */
    -	dep = (xfs_dir2_data_entry_t *)
    -	      ((char *)dbp->data +
    -	       XFS_DIR2_DATAPTR_TO_OFF(dp->i_mount, be32_to_cpu(lep->address)));
    -	/*
    -	 * Return the found inode number.
    -	 */
    -	args->inumber = INT_GET(dep->inumber, ARCH_CONVERT);
    -	xfs_da_brelse(tp, dbp);
    -	xfs_da_brelse(tp, lbp);
    -	return XFS_ERROR(EEXIST);
    -}
    -
    -/*
    - * Look up name/hash in the leaf block.
    - * Fill in indexp with the found index, and dbpp with the data buffer.
    - * If not found dbpp will be NULL, and ENOENT comes back.
    - * lbpp will always be filled in with the leaf buffer unless there's an error.
    - */
    -static int					/* error */
    -xfs_dir2_leaf_lookup_int(
    -	xfs_da_args_t		*args,		/* operation arguments */
    -	xfs_dabuf_t		**lbpp,		/* out: leaf buffer */
    -	int			*indexp,	/* out: index in leaf block */
    -	xfs_dabuf_t		**dbpp)		/* out: data buffer */
    -{
    -	xfs_dir2_db_t		curdb;		/* current data block number */
    -	xfs_dabuf_t		*dbp;		/* data buffer */
    -	xfs_dir2_data_entry_t	*dep;		/* data entry */
    -	xfs_inode_t		*dp;		/* incore directory inode */
    -	int			error;		/* error return code */
    -	int			index;		/* index in leaf block */
    -	xfs_dabuf_t		*lbp;		/* leaf buffer */
    -	xfs_dir2_leaf_entry_t	*lep;		/* leaf entry */
    -	xfs_dir2_leaf_t		*leaf;		/* leaf structure */
    -	xfs_mount_t		*mp;		/* filesystem mount point */
    -	xfs_dir2_db_t		newdb;		/* new data block number */
    -	xfs_trans_t		*tp;		/* transaction pointer */
    -
    -	dp = args->dp;
    -	tp = args->trans;
    -	mp = dp->i_mount;
    -	/*
    -	 * Read the leaf block into the buffer.
    -	 */
    -	if ((error =
    -	    xfs_da_read_buf(tp, dp, mp->m_dirleafblk, -1, &lbp,
    -		    XFS_DATA_FORK))) {
    -		return error;
    -	}
    -	*lbpp = lbp;
    -	leaf = lbp->data;
    -	xfs_dir2_leaf_check(dp, lbp);
    -	/*
    -	 * Look for the first leaf entry with our hash value.
    -	 */
    -	index = xfs_dir2_leaf_search_hash(args, lbp);
    -	/*
    -	 * Loop over all the entries with the right hash value
    -	 * looking to match the name.
    -	 */
    -	for (lep = &leaf->ents[index], dbp = NULL, curdb = -1;
    -	     index < be16_to_cpu(leaf->hdr.count) && be32_to_cpu(lep->hashval) == args->hashval;
    -	     lep++, index++) {
    -		/*
    -		 * Skip over stale leaf entries.
    -		 */
    -		if (be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR)
    -			continue;
    -		/*
    -		 * Get the new data block number.
    -		 */
    -		newdb = XFS_DIR2_DATAPTR_TO_DB(mp, be32_to_cpu(lep->address));
    -		/*
    -		 * If it's not the same as the old data block number,
    -		 * need to pitch the old one and read the new one.
    -		 */
    -		if (newdb != curdb) {
    -			if (dbp)
    -				xfs_da_brelse(tp, dbp);
    -			if ((error =
    -			    xfs_da_read_buf(tp, dp,
    -				    XFS_DIR2_DB_TO_DA(mp, newdb), -1, &dbp,
    -				    XFS_DATA_FORK))) {
    -				xfs_da_brelse(tp, lbp);
    -				return error;
    -			}
    -			xfs_dir2_data_check(dp, dbp);
    -			curdb = newdb;
    -		}
    -		/*
    -		 * Point to the data entry.
    -		 */
    -		dep = (xfs_dir2_data_entry_t *)
    -		      ((char *)dbp->data +
    -		       XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(lep->address)));
    -		/*
    -		 * If it matches then return it.
    -		 */
    -		if (dep->namelen == args->namelen &&
    -		    dep->name[0] == args->name[0] &&
    -		    memcmp(dep->name, args->name, args->namelen) == 0) {
    -			*dbpp = dbp;
    -			*indexp = index;
    -			return 0;
    -		}
    -	}
    -	/*
    -	 * No match found, return ENOENT.
    -	 */
    -	ASSERT(args->oknoent);
    -	if (dbp)
    -		xfs_da_brelse(tp, dbp);
    -	xfs_da_brelse(tp, lbp);
    -	return XFS_ERROR(ENOENT);
    -}
    -
    -/*
    - * Remove an entry from a leaf format directory.
    - */
    -int						/* error */
    -xfs_dir2_leaf_removename(
    -	xfs_da_args_t		*args)		/* operation arguments */
    -{
    -	__be16			*bestsp;	/* leaf block best freespace */
    -	xfs_dir2_data_t		*data;		/* data block structure */
    -	xfs_dir2_db_t		db;		/* data block number */
    -	xfs_dabuf_t		*dbp;		/* data block buffer */
    -	xfs_dir2_data_entry_t	*dep;		/* data entry structure */
    -	xfs_inode_t		*dp;		/* incore directory inode */
    -	int			error;		/* error return code */
    -	xfs_dir2_db_t		i;		/* temporary data block # */
    -	int			index;		/* index into leaf entries */
    -	xfs_dabuf_t		*lbp;		/* leaf buffer */
    -	xfs_dir2_leaf_t		*leaf;		/* leaf structure */
    -	xfs_dir2_leaf_entry_t	*lep;		/* leaf entry */
    -	xfs_dir2_leaf_tail_t	*ltp;		/* leaf tail structure */
    -	xfs_mount_t		*mp;		/* filesystem mount point */
    -	int			needlog;	/* need to log data header */
    -	int			needscan;	/* need to rescan data frees */
    -	xfs_dir2_data_off_t	oldbest;	/* old value of best free */
    -	xfs_trans_t		*tp;		/* transaction pointer */
    -
    -	xfs_dir2_trace_args("leaf_removename", args);
    -	/*
    -	 * Lookup the leaf entry, get the leaf and data blocks read in.
    -	 */
    -	if ((error = xfs_dir2_leaf_lookup_int(args, &lbp, &index, &dbp))) {
    -		return error;
    -	}
    -	dp = args->dp;
    -	tp = args->trans;
    -	mp = dp->i_mount;
    -	leaf = lbp->data;
    -	data = dbp->data;
    -	xfs_dir2_data_check(dp, dbp);
    -	/*
    -	 * Point to the leaf entry, use that to point to the data entry.
    -	 */
    -	lep = &leaf->ents[index];
    -	db = XFS_DIR2_DATAPTR_TO_DB(mp, be32_to_cpu(lep->address));
    -	dep = (xfs_dir2_data_entry_t *)
    -	      ((char *)data + XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(lep->address)));
    -	needscan = needlog = 0;
    -	oldbest = be16_to_cpu(data->hdr.bestfree[0].length);
    -	ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
    -	bestsp = XFS_DIR2_LEAF_BESTS_P(ltp);
    -	ASSERT(be16_to_cpu(bestsp[db]) == oldbest);
    -	/*
    -	 * Mark the former data entry unused.
    -	 */
    -	xfs_dir2_data_make_free(tp, dbp,
    -		(xfs_dir2_data_aoff_t)((char *)dep - (char *)data),
    -		XFS_DIR2_DATA_ENTSIZE(dep->namelen), &needlog, &needscan);
    -	/*
    -	 * We just mark the leaf entry stale by putting a null in it.
    -	 */
    -	be16_add(&leaf->hdr.stale, 1);
    -	xfs_dir2_leaf_log_header(tp, lbp);
    -	lep->address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR);
    -	xfs_dir2_leaf_log_ents(tp, lbp, index, index);
    -	/*
    -	 * Scan the freespace in the data block again if necessary,
    -	 * log the data block header if necessary.
    -	 */
    -	if (needscan)
    -		xfs_dir2_data_freescan(mp, data, &needlog, NULL);
    -	if (needlog)
    -		xfs_dir2_data_log_header(tp, dbp);
    -	/*
    -	 * If the longest freespace in the data block has changed,
    -	 * put the new value in the bests table and log that.
    -	 */
    -	if (be16_to_cpu(data->hdr.bestfree[0].length) != oldbest) {
    -		bestsp[db] = data->hdr.bestfree[0].length;
    -		xfs_dir2_leaf_log_bests(tp, lbp, db, db);
    -	}
    -	xfs_dir2_data_check(dp, dbp);
    -	/*
    -	 * If the data block is now empty then get rid of the data block.
    -	 */
    -	if (be16_to_cpu(data->hdr.bestfree[0].length) ==
    -	    mp->m_dirblksize - (uint)sizeof(data->hdr)) {
    -		ASSERT(db != mp->m_dirdatablk);
    -		if ((error = xfs_dir2_shrink_inode(args, db, dbp))) {
    -			/*
    -			 * Nope, can't get rid of it because it caused
    -			 * allocation of a bmap btree block to do so.
    -			 * Just go on, returning success, leaving the
    -			 * empty block in place.
    -			 */
    -			if (error == ENOSPC && args->total == 0) {
    -				xfs_da_buf_done(dbp);
    -				error = 0;
    -			}
    -			xfs_dir2_leaf_check(dp, lbp);
    -			xfs_da_buf_done(lbp);
    -			return error;
    -		}
    -		dbp = NULL;
    -		/*
    -		 * If this is the last data block then compact the
    -		 * bests table by getting rid of entries.
    -		 */
    -		if (db == be32_to_cpu(ltp->bestcount) - 1) {
    -			/*
    -			 * Look for the last active entry (i).
    -			 */
    -			for (i = db - 1; i > 0; i--) {
    -				if (be16_to_cpu(bestsp[i]) != NULLDATAOFF)
    -					break;
    -			}
    -			/*
    -			 * Copy the table down so inactive entries at the
    -			 * end are removed.
    -			 */
    -			memmove(&bestsp[db - i], bestsp,
    -				(be32_to_cpu(ltp->bestcount) - (db - i)) * sizeof(*bestsp));
    -			be32_add(<p->bestcount, -(db - i));
    -			xfs_dir2_leaf_log_tail(tp, lbp);
    -			xfs_dir2_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1);
    -		} else
    -			bestsp[db] = cpu_to_be16(NULLDATAOFF);
    -	}
    -	/*
    -	 * If the data block was not the first one, drop it.
    -	 */
    -	else if (db != mp->m_dirdatablk && dbp != NULL) {
    -		xfs_da_buf_done(dbp);
    -		dbp = NULL;
    -	}
    -	xfs_dir2_leaf_check(dp, lbp);
    -	/*
    -	 * See if we can convert to block form.
    -	 */
    -	return xfs_dir2_leaf_to_block(args, lbp, dbp);
    -}
    -
    -/*
    - * Replace the inode number in a leaf format directory entry.
    - */
    -int						/* error */
    -xfs_dir2_leaf_replace(
    -	xfs_da_args_t		*args)		/* operation arguments */
    -{
    -	xfs_dabuf_t		*dbp;		/* data block buffer */
    -	xfs_dir2_data_entry_t	*dep;		/* data block entry */
    -	xfs_inode_t		*dp;		/* incore directory inode */
    -	int			error;		/* error return code */
    -	int			index;		/* index of leaf entry */
    -	xfs_dabuf_t		*lbp;		/* leaf buffer */
    -	xfs_dir2_leaf_t		*leaf;		/* leaf structure */
    -	xfs_dir2_leaf_entry_t	*lep;		/* leaf entry */
    -	xfs_trans_t		*tp;		/* transaction pointer */
    -
    -	xfs_dir2_trace_args("leaf_replace", args);
    -	/*
    -	 * Look up the entry.
    -	 */
    -	if ((error = xfs_dir2_leaf_lookup_int(args, &lbp, &index, &dbp))) {
    -		return error;
    -	}
    -	dp = args->dp;
    -	leaf = lbp->data;
    -	/*
    -	 * Point to the leaf entry, get data address from it.
    -	 */
    -	lep = &leaf->ents[index];
    -	/*
    -	 * Point to the data entry.
    -	 */
    -	dep = (xfs_dir2_data_entry_t *)
    -	      ((char *)dbp->data +
    -	       XFS_DIR2_DATAPTR_TO_OFF(dp->i_mount, be32_to_cpu(lep->address)));
    -	ASSERT(args->inumber != INT_GET(dep->inumber, ARCH_CONVERT));
    -	/*
    -	 * Put the new inode number in, log it.
    -	 */
    -	INT_SET(dep->inumber, ARCH_CONVERT, args->inumber);
    -	tp = args->trans;
    -	xfs_dir2_data_log_entry(tp, dbp, dep);
    -	xfs_da_buf_done(dbp);
    -	xfs_dir2_leaf_check(dp, lbp);
    -	xfs_da_brelse(tp, lbp);
    -	return 0;
    -}
    -
    -/*
    - * Return index in the leaf block (lbp) which is either the first
    - * one with this hash value, or if there are none, the insert point
    - * for that hash value.
    - */
    -int						/* index value */
    -xfs_dir2_leaf_search_hash(
    -	xfs_da_args_t		*args,		/* operation arguments */
    -	xfs_dabuf_t		*lbp)		/* leaf buffer */
    -{
    -	xfs_dahash_t		hash=0;		/* hash from this entry */
    -	xfs_dahash_t		hashwant;	/* hash value looking for */
    -	int			high;		/* high leaf index */
    -	int			low;		/* low leaf index */
    -	xfs_dir2_leaf_t		*leaf;		/* leaf structure */
    -	xfs_dir2_leaf_entry_t	*lep;		/* leaf entry */
    -	int			mid=0;		/* current leaf index */
    -
    -	leaf = lbp->data;
    -#ifndef __KERNEL__
    -	if (!leaf->hdr.count)
    -		return 0;
    -#endif
    -	/*
    -	 * Note, the table cannot be empty, so we have to go through the loop.
    -	 * Binary search the leaf entries looking for our hash value.
    -	 */
    -	for (lep = leaf->ents, low = 0, high = be16_to_cpu(leaf->hdr.count) - 1,
    -		hashwant = args->hashval;
    -	     low <= high; ) {
    -		mid = (low + high) >> 1;
    -		if ((hash = be32_to_cpu(lep[mid].hashval)) == hashwant)
    -			break;
    -		if (hash < hashwant)
    -			low = mid + 1;
    -		else
    -			high = mid - 1;
    -	}
    -	/*
    -	 * Found one, back up through all the equal hash values.
    -	 */
    -	if (hash == hashwant) {
    -		while (mid > 0 && be32_to_cpu(lep[mid - 1].hashval) == hashwant) {
    -			mid--;
    -		}
    -	}
    -	/*
    -	 * Need to point to an entry higher than ours.
    -	 */
    -	else if (hash < hashwant)
    -		mid++;
    -	return mid;
    -}
    -
    -/*
    - * Trim off a trailing data block.  We know it's empty since the leaf
    - * freespace table says so.
    - */
    -int						/* error */
    -xfs_dir2_leaf_trim_data(
    -	xfs_da_args_t		*args,		/* operation arguments */
    -	xfs_dabuf_t		*lbp,		/* leaf buffer */
    -	xfs_dir2_db_t		db)		/* data block number */
    -{
    -	__be16			*bestsp;	/* leaf bests table */
    -#ifdef DEBUG
    -	xfs_dir2_data_t		*data;		/* data block structure */
    -#endif
    -	xfs_dabuf_t		*dbp;		/* data block buffer */
    -	xfs_inode_t		*dp;		/* incore directory inode */
    -	int			error;		/* error return value */
    -	xfs_dir2_leaf_t		*leaf;		/* leaf structure */
    -	xfs_dir2_leaf_tail_t	*ltp;		/* leaf tail structure */
    -	xfs_mount_t		*mp;		/* filesystem mount point */
    -	xfs_trans_t		*tp;		/* transaction pointer */
    -
    -	dp = args->dp;
    -	mp = dp->i_mount;
    -	tp = args->trans;
    -	/*
    -	 * Read the offending data block.  We need its buffer.
    -	 */
    -	if ((error = xfs_da_read_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, db), -1, &dbp,
    -			XFS_DATA_FORK))) {
    -		return error;
    -	}
    -#ifdef DEBUG
    -	data = dbp->data;
    -	ASSERT(be32_to_cpu(data->hdr.magic) == XFS_DIR2_DATA_MAGIC);
    -#endif
    -	/* this seems to be an error
    -	 * data is only valid if DEBUG is defined?
    -	 * RMC 09/08/1999
    -	 */
    -
    -	leaf = lbp->data;
    -	ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
    -	ASSERT(be16_to_cpu(data->hdr.bestfree[0].length) ==
    -	       mp->m_dirblksize - (uint)sizeof(data->hdr));
    -	ASSERT(db == be32_to_cpu(ltp->bestcount) - 1);
    -	/*
    -	 * Get rid of the data block.
    -	 */
    -	if ((error = xfs_dir2_shrink_inode(args, db, dbp))) {
    -		ASSERT(error != ENOSPC);
    -		xfs_da_brelse(tp, dbp);
    -		return error;
    -	}
    -	/*
    -	 * Eliminate the last bests entry from the table.
    -	 */
    -	bestsp = XFS_DIR2_LEAF_BESTS_P(ltp);
    -	be32_add(<p->bestcount, -1);
    -	memmove(&bestsp[1], &bestsp[0], be32_to_cpu(ltp->bestcount) * sizeof(*bestsp));
    -	xfs_dir2_leaf_log_tail(tp, lbp);
    -	xfs_dir2_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1);
    -	return 0;
    -}
    -
    -/*
    - * Convert node form directory to leaf form directory.
    - * The root of the node form dir needs to already be a LEAFN block.
    - * Just return if we can't do anything.
    - */
    -int						/* error */
    -xfs_dir2_node_to_leaf(
    -	xfs_da_state_t		*state)		/* directory operation state */
    -{
    -	xfs_da_args_t		*args;		/* operation arguments */
    -	xfs_inode_t		*dp;		/* incore directory inode */
    -	int			error;		/* error return code */
    -	xfs_dabuf_t		*fbp;		/* buffer for freespace block */
    -	xfs_fileoff_t		fo;		/* freespace file offset */
    -	xfs_dir2_free_t		*free;		/* freespace structure */
    -	xfs_dabuf_t		*lbp;		/* buffer for leaf block */
    -	xfs_dir2_leaf_tail_t	*ltp;		/* tail of leaf structure */
    -	xfs_dir2_leaf_t		*leaf;		/* leaf structure */
    -	xfs_mount_t		*mp;		/* filesystem mount point */
    -	int			rval;		/* successful free trim? */
    -	xfs_trans_t		*tp;		/* transaction pointer */
    -
    -	/*
    -	 * There's more than a leaf level in the btree, so there must
    -	 * be multiple leafn blocks.  Give up.
    -	 */
    -	if (state->path.active > 1)
    -		return 0;
    -	args = state->args;
    -	xfs_dir2_trace_args("node_to_leaf", args);
    -	mp = state->mp;
    -	dp = args->dp;
    -	tp = args->trans;
    -	/*
    -	 * Get the last offset in the file.
    -	 */
    -	if ((error = xfs_bmap_last_offset(tp, dp, &fo, XFS_DATA_FORK))) {
    -		return error;
    -	}
    -	fo -= mp->m_dirblkfsbs;
    -	/*
    -	 * If there are freespace blocks other than the first one,
    -	 * take this opportunity to remove trailing empty freespace blocks
    -	 * that may have been left behind during no-space-reservation
    -	 * operations.
    -	 */
    -	while (fo > mp->m_dirfreeblk) {
    -		if ((error = xfs_dir2_node_trim_free(args, fo, &rval))) {
    -			return error;
    -		}
    -		if (rval)
    -			fo -= mp->m_dirblkfsbs;
    -		else
    -			return 0;
    -	}
    -	/*
    -	 * Now find the block just before the freespace block.
    -	 */
    -	if ((error = xfs_bmap_last_before(tp, dp, &fo, XFS_DATA_FORK))) {
    -		return error;
    -	}
    -	/*
    -	 * If it's not the single leaf block, give up.
    -	 */
    -	if (XFS_FSB_TO_B(mp, fo) > XFS_DIR2_LEAF_OFFSET + mp->m_dirblksize)
    -		return 0;
    -	lbp = state->path.blk[0].bp;
    -	leaf = lbp->data;
    -	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
    -	/*
    -	 * Read the freespace block.
    -	 */
    -	if ((error = xfs_da_read_buf(tp, dp, mp->m_dirfreeblk, -1, &fbp,
    -			XFS_DATA_FORK))) {
    -		return error;
    -	}
    -	free = fbp->data;
    -	ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);
    -	ASSERT(!free->hdr.firstdb);
    -	/*
    -	 * Now see if the leafn and free data will fit in a leaf1.
    -	 * If not, release the buffer and give up.
    -	 */
    -	if ((uint)sizeof(leaf->hdr) +
    -	    (be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale)) * (uint)sizeof(leaf->ents[0]) +
    -	    be32_to_cpu(free->hdr.nvalid) * (uint)sizeof(leaf->bests[0]) +
    -	    (uint)sizeof(leaf->tail) >
    -	    mp->m_dirblksize) {
    -		xfs_da_brelse(tp, fbp);
    -		return 0;
    -	}
    -	/*
    -	 * If the leaf has any stale entries in it, compress them out.
    -	 * The compact routine will log the header.
    -	 */
    -	if (be16_to_cpu(leaf->hdr.stale))
    -		xfs_dir2_leaf_compact(args, lbp);
    -	else
    -		xfs_dir2_leaf_log_header(tp, lbp);
    -	leaf->hdr.info.magic = cpu_to_be16(XFS_DIR2_LEAF1_MAGIC);
    -	/*
    -	 * Set up the leaf tail from the freespace block.
    -	 */
    -	ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
    -	ltp->bestcount = free->hdr.nvalid;
    -	/*
    -	 * Set up the leaf bests table.
    -	 */
    -	memcpy(XFS_DIR2_LEAF_BESTS_P(ltp), free->bests,
    -		be32_to_cpu(ltp->bestcount) * sizeof(leaf->bests[0]));
    -	xfs_dir2_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1);
    -	xfs_dir2_leaf_log_tail(tp, lbp);
    -	xfs_dir2_leaf_check(dp, lbp);
    -	/*
    -	 * Get rid of the freespace block.
    -	 */
    -	error = xfs_dir2_shrink_inode(args, XFS_DIR2_FREE_FIRSTDB(mp), fbp);
    -	if (error) {
    -		/*
    -		 * This can't fail here because it can only happen when
    -		 * punching out the middle of an extent, and this is an
    -		 * isolated block.
    -		 */
    -		ASSERT(error != ENOSPC);
    -		return error;
    -	}
    -	fbp = NULL;
    -	/*
    -	 * Now see if we can convert the single-leaf directory
    -	 * down to a block form directory.
    -	 * This routine always kills the dabuf for the leaf, so
    -	 * eliminate it from the path.
    -	 */
    -	error = xfs_dir2_leaf_to_block(args, lbp, NULL);
    -	state->path.blk[0].bp = NULL;
    -	return error;
    -}
    diff --git a/sys/gnu/fs/xfs/xfs_dir2_leaf.h b/sys/gnu/fs/xfs/xfs_dir2_leaf.h
    deleted file mode 100644
    index f57ca116241..00000000000
    --- a/sys/gnu/fs/xfs/xfs_dir2_leaf.h
    +++ /dev/null
    @@ -1,270 +0,0 @@
    -/*
    - * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_DIR2_LEAF_H__
    -#define	__XFS_DIR2_LEAF_H__
    -
    -struct uio;
    -struct xfs_dabuf;
    -struct xfs_da_args;
    -struct xfs_inode;
    -struct xfs_mount;
    -struct xfs_trans;
    -
    -/*
    - * Offset of the leaf/node space.  First block in this space
    - * is the btree root.
    - */
    -#define	XFS_DIR2_LEAF_SPACE	1
    -#define	XFS_DIR2_LEAF_OFFSET	(XFS_DIR2_LEAF_SPACE * XFS_DIR2_SPACE_SIZE)
    -#define	XFS_DIR2_LEAF_FIRSTDB(mp)	\
    -	XFS_DIR2_BYTE_TO_DB(mp, XFS_DIR2_LEAF_OFFSET)
    -
    -/*
    - * Offset in data space of a data entry.
    - */
    -typedef	__uint32_t	xfs_dir2_dataptr_t;
    -#define	XFS_DIR2_MAX_DATAPTR	((xfs_dir2_dataptr_t)0xffffffff)
    -#define	XFS_DIR2_NULL_DATAPTR	((xfs_dir2_dataptr_t)0)
    -
    -/*
    - * Leaf block header.
    - */
    -typedef struct xfs_dir2_leaf_hdr {
    -	xfs_da_blkinfo_t	info;		/* header for da routines */
    -	__be16			count;		/* count of entries */
    -	__be16			stale;		/* count of stale entries */
    -} xfs_dir2_leaf_hdr_t;
    -
    -/*
    - * Leaf block entry.
    - */
    -typedef struct xfs_dir2_leaf_entry {
    -	__be32			hashval;	/* hash value of name */
    -	__be32			address;	/* address of data entry */
    -} xfs_dir2_leaf_entry_t;
    -
    -/*
    - * Leaf block tail.
    - */
    -typedef struct xfs_dir2_leaf_tail {
    -	__be32			bestcount;
    -} xfs_dir2_leaf_tail_t;
    -
    -/*
    - * Leaf block.
    - * bests and tail are at the end of the block for single-leaf only
    - * (magic = XFS_DIR2_LEAF1_MAGIC not XFS_DIR2_LEAFN_MAGIC).
    - */
    -typedef struct xfs_dir2_leaf {
    -	xfs_dir2_leaf_hdr_t	hdr;		/* leaf header */
    -	xfs_dir2_leaf_entry_t	ents[1];	/* entries */
    -						/* ... */
    -	xfs_dir2_data_off_t	bests[1];	/* best free counts */
    -	xfs_dir2_leaf_tail_t	tail;		/* leaf tail */
    -} xfs_dir2_leaf_t;
    -
    -/*
    - * DB blocks here are logical directory block numbers, not filesystem blocks.
    - */
    -
    -#define	XFS_DIR2_MAX_LEAF_ENTS(mp)	xfs_dir2_max_leaf_ents(mp)
    -static inline int xfs_dir2_max_leaf_ents(struct xfs_mount *mp)
    -{
    -	return (int)(((mp)->m_dirblksize - (uint)sizeof(xfs_dir2_leaf_hdr_t)) /
    -	       (uint)sizeof(xfs_dir2_leaf_entry_t));
    -}
    -
    -/*
    - * Get address of the bestcount field in the single-leaf block.
    - */
    -#define	XFS_DIR2_LEAF_TAIL_P(mp,lp)	xfs_dir2_leaf_tail_p(mp, lp)
    -static inline xfs_dir2_leaf_tail_t *
    -xfs_dir2_leaf_tail_p(struct xfs_mount *mp, xfs_dir2_leaf_t *lp)
    -{
    -	return (xfs_dir2_leaf_tail_t *)
    -		((char *)(lp) + (mp)->m_dirblksize - 
    -		  (uint)sizeof(xfs_dir2_leaf_tail_t));
    -}
    -
    -/*
    - * Get address of the bests array in the single-leaf block.
    - */
    -#define	XFS_DIR2_LEAF_BESTS_P(ltp)	xfs_dir2_leaf_bests_p(ltp)
    -static inline __be16 *
    -xfs_dir2_leaf_bests_p(xfs_dir2_leaf_tail_t *ltp)
    -{
    -	return (__be16 *)ltp - be32_to_cpu(ltp->bestcount);
    -}
    -
    -/*
    - * Convert dataptr to byte in file space
    - */
    -#define	XFS_DIR2_DATAPTR_TO_BYTE(mp,dp)	xfs_dir2_dataptr_to_byte(mp, dp)
    -static inline xfs_dir2_off_t
    -xfs_dir2_dataptr_to_byte(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
    -{
    -	return (xfs_dir2_off_t)(dp) << XFS_DIR2_DATA_ALIGN_LOG;
    -}
    -
    -/*
    - * Convert byte in file space to dataptr.  It had better be aligned.
    - */
    -#define	XFS_DIR2_BYTE_TO_DATAPTR(mp,by)	xfs_dir2_byte_to_dataptr(mp,by)
    -static inline xfs_dir2_dataptr_t
    -xfs_dir2_byte_to_dataptr(struct xfs_mount *mp, xfs_dir2_off_t by)
    -{
    -	return (xfs_dir2_dataptr_t)((by) >> XFS_DIR2_DATA_ALIGN_LOG);
    -}
    -
    -/*
    - * Convert byte in space to (DB) block
    - */
    -#define	XFS_DIR2_BYTE_TO_DB(mp,by)	xfs_dir2_byte_to_db(mp, by)
    -static inline xfs_dir2_db_t
    -xfs_dir2_byte_to_db(struct xfs_mount *mp, xfs_dir2_off_t by)
    -{
    -	return (xfs_dir2_db_t)((by) >> \
    -		 ((mp)->m_sb.sb_blocklog + (mp)->m_sb.sb_dirblklog));
    -}
    -
    -/*
    - * Convert dataptr to a block number
    - */
    -#define	XFS_DIR2_DATAPTR_TO_DB(mp,dp)	xfs_dir2_dataptr_to_db(mp, dp)
    -static inline xfs_dir2_db_t
    -xfs_dir2_dataptr_to_db(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
    -{
    -	return XFS_DIR2_BYTE_TO_DB(mp, XFS_DIR2_DATAPTR_TO_BYTE(mp, dp));
    -}
    -
    -/*
    - * Convert byte in space to offset in a block
    - */
    -#define	XFS_DIR2_BYTE_TO_OFF(mp,by)	xfs_dir2_byte_to_off(mp, by)
    -static inline xfs_dir2_data_aoff_t
    -xfs_dir2_byte_to_off(struct xfs_mount *mp, xfs_dir2_off_t by)
    -{
    -	return (xfs_dir2_data_aoff_t)((by) & \
    -		((1 << ((mp)->m_sb.sb_blocklog + (mp)->m_sb.sb_dirblklog)) - 1));
    -}
    -
    -/*
    - * Convert dataptr to a byte offset in a block
    - */
    -#define	XFS_DIR2_DATAPTR_TO_OFF(mp,dp)	xfs_dir2_dataptr_to_off(mp, dp)
    -static inline xfs_dir2_data_aoff_t
    -xfs_dir2_dataptr_to_off(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
    -{
    -	return XFS_DIR2_BYTE_TO_OFF(mp, XFS_DIR2_DATAPTR_TO_BYTE(mp, dp));
    -}
    -
    -/*
    - * Convert block and offset to byte in space
    - */
    -#define	XFS_DIR2_DB_OFF_TO_BYTE(mp,db,o)	\
    -	xfs_dir2_db_off_to_byte(mp, db, o)
    -static inline xfs_dir2_off_t
    -xfs_dir2_db_off_to_byte(struct xfs_mount *mp, xfs_dir2_db_t db,
    -			xfs_dir2_data_aoff_t o)
    -{
    -	return ((xfs_dir2_off_t)(db) << \
    -		((mp)->m_sb.sb_blocklog + (mp)->m_sb.sb_dirblklog)) + (o);
    -}
    -
    -/*
    - * Convert block (DB) to block (dablk)
    - */
    -#define	XFS_DIR2_DB_TO_DA(mp,db)	xfs_dir2_db_to_da(mp, db)
    -static inline xfs_dablk_t
    -xfs_dir2_db_to_da(struct xfs_mount *mp, xfs_dir2_db_t db)
    -{
    -	return (xfs_dablk_t)((db) << (mp)->m_sb.sb_dirblklog);
    -}
    -
    -/*
    - * Convert byte in space to (DA) block
    - */
    -#define	XFS_DIR2_BYTE_TO_DA(mp,by)	xfs_dir2_byte_to_da(mp, by)
    -static inline xfs_dablk_t
    -xfs_dir2_byte_to_da(struct xfs_mount *mp, xfs_dir2_off_t by)
    -{
    -	return XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_BYTE_TO_DB(mp, by));
    -}
    -
    -/*
    - * Convert block and offset to dataptr
    - */
    -#define	XFS_DIR2_DB_OFF_TO_DATAPTR(mp,db,o)	\
    -	xfs_dir2_db_off_to_dataptr(mp, db, o)
    -static inline xfs_dir2_dataptr_t
    -xfs_dir2_db_off_to_dataptr(struct xfs_mount *mp, xfs_dir2_db_t db,
    -			   xfs_dir2_data_aoff_t o)
    -{
    -	return XFS_DIR2_BYTE_TO_DATAPTR(mp, XFS_DIR2_DB_OFF_TO_BYTE(mp, db, o));
    -}
    -
    -/*
    - * Convert block (dablk) to block (DB)
    - */
    -#define	XFS_DIR2_DA_TO_DB(mp,da)	xfs_dir2_da_to_db(mp, da)
    -static inline xfs_dir2_db_t
    -xfs_dir2_da_to_db(struct xfs_mount *mp, xfs_dablk_t da)
    -{
    -	return (xfs_dir2_db_t)((da) >> (mp)->m_sb.sb_dirblklog);
    -}
    -
    -/*
    - * Convert block (dablk) to byte offset in space
    - */
    -#define XFS_DIR2_DA_TO_BYTE(mp,da)	xfs_dir2_da_to_byte(mp, da)
    -static inline xfs_dir2_off_t
    -xfs_dir2_da_to_byte(struct xfs_mount *mp, xfs_dablk_t da)
    -{
    -	return XFS_DIR2_DB_OFF_TO_BYTE(mp, XFS_DIR2_DA_TO_DB(mp, da), 0);
    -}
    -
    -/*
    - * Function declarations.
    - */
    -extern int xfs_dir2_block_to_leaf(struct xfs_da_args *args,
    -				  struct xfs_dabuf *dbp);
    -extern int xfs_dir2_leaf_addname(struct xfs_da_args *args);
    -extern void xfs_dir2_leaf_compact(struct xfs_da_args *args,
    -				  struct xfs_dabuf *bp);
    -extern void xfs_dir2_leaf_compact_x1(struct xfs_dabuf *bp, int *indexp,
    -				     int *lowstalep, int *highstalep,
    -				     int *lowlogp, int *highlogp);
    -extern int xfs_dir2_leaf_getdents(struct xfs_trans *tp, struct xfs_inode *dp,
    -				  struct uio *uio, int *eofp,
    -				  struct xfs_dirent *dbp, xfs_dir2_put_t put);
    -extern int xfs_dir2_leaf_init(struct xfs_da_args *args, xfs_dir2_db_t bno,
    -			      struct xfs_dabuf **bpp, int magic);
    -extern void xfs_dir2_leaf_log_ents(struct xfs_trans *tp, struct xfs_dabuf *bp,
    -				   int first, int last);
    -extern void xfs_dir2_leaf_log_header(struct xfs_trans *tp,
    -				     struct xfs_dabuf *bp);
    -extern int xfs_dir2_leaf_lookup(struct xfs_da_args *args);
    -extern int xfs_dir2_leaf_removename(struct xfs_da_args *args);
    -extern int xfs_dir2_leaf_replace(struct xfs_da_args *args);
    -extern int xfs_dir2_leaf_search_hash(struct xfs_da_args *args,
    -				     struct xfs_dabuf *lbp);
    -extern int xfs_dir2_leaf_trim_data(struct xfs_da_args *args,
    -				   struct xfs_dabuf *lbp, xfs_dir2_db_t db);
    -extern int xfs_dir2_node_to_leaf(struct xfs_da_state *state);
    -
    -#endif	/* __XFS_DIR2_LEAF_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_dir2_node.c b/sys/gnu/fs/xfs/xfs_dir2_node.c
    deleted file mode 100644
    index ac511ab9c52..00000000000
    --- a/sys/gnu/fs/xfs/xfs_dir2_node.c
    +++ /dev/null
    @@ -1,1999 +0,0 @@
    -/*
    - * Copyright (c) 2000-2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_da_btree.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_bmap.h"
    -#include "xfs_dir2_data.h"
    -#include "xfs_dir2_leaf.h"
    -#include "xfs_dir2_block.h"
    -#include "xfs_dir2_node.h"
    -#include "xfs_dir2_trace.h"
    -#include "xfs_error.h"
    -
    -/*
    - * Function declarations.
    - */
    -static void xfs_dir2_free_log_header(xfs_trans_t *tp, xfs_dabuf_t *bp);
    -static int xfs_dir2_leafn_add(xfs_dabuf_t *bp, xfs_da_args_t *args, int index);
    -#ifdef DEBUG
    -static void xfs_dir2_leafn_check(xfs_inode_t *dp, xfs_dabuf_t *bp);
    -#else
    -#define	xfs_dir2_leafn_check(dp, bp)
    -#endif
    -static void xfs_dir2_leafn_moveents(xfs_da_args_t *args, xfs_dabuf_t *bp_s,
    -				    int start_s, xfs_dabuf_t *bp_d, int start_d,
    -				    int count);
    -static void xfs_dir2_leafn_rebalance(xfs_da_state_t *state,
    -				     xfs_da_state_blk_t *blk1,
    -				     xfs_da_state_blk_t *blk2);
    -static int xfs_dir2_leafn_remove(xfs_da_args_t *args, xfs_dabuf_t *bp,
    -				 int index, xfs_da_state_blk_t *dblk,
    -				 int *rval);
    -static int xfs_dir2_node_addname_int(xfs_da_args_t *args,
    -				     xfs_da_state_blk_t *fblk);
    -
    -/*
    - * Log entries from a freespace block.
    - */
    -void
    -xfs_dir2_free_log_bests(
    -	xfs_trans_t		*tp,		/* transaction pointer */
    -	xfs_dabuf_t		*bp,		/* freespace buffer */
    -	int			first,		/* first entry to log */
    -	int			last)		/* last entry to log */
    -{
    -	xfs_dir2_free_t		*free;		/* freespace structure */
    -
    -	free = bp->data;
    -	ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);
    -	xfs_da_log_buf(tp, bp,
    -		(uint)((char *)&free->bests[first] - (char *)free),
    -		(uint)((char *)&free->bests[last] - (char *)free +
    -		       sizeof(free->bests[0]) - 1));
    -}
    -
    -/*
    - * Log header from a freespace block.
    - */
    -static void
    -xfs_dir2_free_log_header(
    -	xfs_trans_t		*tp,		/* transaction pointer */
    -	xfs_dabuf_t		*bp)		/* freespace buffer */
    -{
    -	xfs_dir2_free_t		*free;		/* freespace structure */
    -
    -	free = bp->data;
    -	ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);
    -	xfs_da_log_buf(tp, bp, (uint)((char *)&free->hdr - (char *)free),
    -		(uint)(sizeof(xfs_dir2_free_hdr_t) - 1));
    -}
    -
    -/*
    - * Convert a leaf-format directory to a node-format directory.
    - * We need to change the magic number of the leaf block, and copy
    - * the freespace table out of the leaf block into its own block.
    - */
    -int						/* error */
    -xfs_dir2_leaf_to_node(
    -	xfs_da_args_t		*args,		/* operation arguments */
    -	xfs_dabuf_t		*lbp)		/* leaf buffer */
    -{
    -	xfs_inode_t		*dp;		/* incore directory inode */
    -	int			error;		/* error return value */
    -	xfs_dabuf_t		*fbp;		/* freespace buffer */
    -	xfs_dir2_db_t		fdb;		/* freespace block number */
    -	xfs_dir2_free_t		*free;		/* freespace structure */
    -	__be16			*from;		/* pointer to freespace entry */
    -	int			i;		/* leaf freespace index */
    -	xfs_dir2_leaf_t		*leaf;		/* leaf structure */
    -	xfs_dir2_leaf_tail_t	*ltp;		/* leaf tail structure */
    -	xfs_mount_t		*mp;		/* filesystem mount point */
    -	int			n;		/* count of live freespc ents */
    -	xfs_dir2_data_off_t	off;		/* freespace entry value */
    -	__be16			*to;		/* pointer to freespace entry */
    -	xfs_trans_t		*tp;		/* transaction pointer */
    -
    -	xfs_dir2_trace_args_b("leaf_to_node", args, lbp);
    -	dp = args->dp;
    -	mp = dp->i_mount;
    -	tp = args->trans;
    -	/*
    -	 * Add a freespace block to the directory.
    -	 */
    -	if ((error = xfs_dir2_grow_inode(args, XFS_DIR2_FREE_SPACE, &fdb))) {
    -		return error;
    -	}
    -	ASSERT(fdb == XFS_DIR2_FREE_FIRSTDB(mp));
    -	/*
    -	 * Get the buffer for the new freespace block.
    -	 */
    -	if ((error = xfs_da_get_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, fdb), -1, &fbp,
    -			XFS_DATA_FORK))) {
    -		return error;
    -	}
    -	ASSERT(fbp != NULL);
    -	free = fbp->data;
    -	leaf = lbp->data;
    -	ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
    -	/*
    -	 * Initialize the freespace block header.
    -	 */
    -	free->hdr.magic = cpu_to_be32(XFS_DIR2_FREE_MAGIC);
    -	free->hdr.firstdb = 0;
    -	ASSERT(be32_to_cpu(ltp->bestcount) <= (uint)dp->i_d.di_size / mp->m_dirblksize);
    -	free->hdr.nvalid = ltp->bestcount;
    -	/*
    -	 * Copy freespace entries from the leaf block to the new block.
    -	 * Count active entries.
    -	 */
    -	for (i = n = 0, from = XFS_DIR2_LEAF_BESTS_P(ltp), to = free->bests;
    -	     i < be32_to_cpu(ltp->bestcount); i++, from++, to++) {
    -		if ((off = be16_to_cpu(*from)) != NULLDATAOFF)
    -			n++;
    -		*to = cpu_to_be16(off);
    -	}
    -	free->hdr.nused = cpu_to_be32(n);
    -	leaf->hdr.info.magic = cpu_to_be16(XFS_DIR2_LEAFN_MAGIC);
    -	/*
    -	 * Log everything.
    -	 */
    -	xfs_dir2_leaf_log_header(tp, lbp);
    -	xfs_dir2_free_log_header(tp, fbp);
    -	xfs_dir2_free_log_bests(tp, fbp, 0, be32_to_cpu(free->hdr.nvalid) - 1);
    -	xfs_da_buf_done(fbp);
    -	xfs_dir2_leafn_check(dp, lbp);
    -	return 0;
    -}
    -
    -/*
    - * Add a leaf entry to a leaf block in a node-form directory.
    - * The other work necessary is done from the caller.
    - */
    -static int					/* error */
    -xfs_dir2_leafn_add(
    -	xfs_dabuf_t		*bp,		/* leaf buffer */
    -	xfs_da_args_t		*args,		/* operation arguments */
    -	int			index)		/* insertion pt for new entry */
    -{
    -	int			compact;	/* compacting stale leaves */
    -	xfs_inode_t		*dp;		/* incore directory inode */
    -	int			highstale;	/* next stale entry */
    -	xfs_dir2_leaf_t		*leaf;		/* leaf structure */
    -	xfs_dir2_leaf_entry_t	*lep;		/* leaf entry */
    -	int			lfloghigh;	/* high leaf entry logging */
    -	int			lfloglow;	/* low leaf entry logging */
    -	int			lowstale;	/* previous stale entry */
    -	xfs_mount_t		*mp;		/* filesystem mount point */
    -	xfs_trans_t		*tp;		/* transaction pointer */
    -
    -	xfs_dir2_trace_args_sb("leafn_add", args, index, bp);
    -	dp = args->dp;
    -	mp = dp->i_mount;
    -	tp = args->trans;
    -	leaf = bp->data;
    -
    -	/*
    -	 * Quick check just to make sure we are not going to index
    -	 * into other peoples memory
    -	 */
    -	if (index < 0)
    -		return XFS_ERROR(EFSCORRUPTED);
    -
    -	/*
    -	 * If there are already the maximum number of leaf entries in
    -	 * the block, if there are no stale entries it won't fit.
    -	 * Caller will do a split.  If there are stale entries we'll do
    -	 * a compact.
    -	 */
    -
    -	if (be16_to_cpu(leaf->hdr.count) == XFS_DIR2_MAX_LEAF_ENTS(mp)) {
    -		if (!leaf->hdr.stale)
    -			return XFS_ERROR(ENOSPC);
    -		compact = be16_to_cpu(leaf->hdr.stale) > 1;
    -	} else
    -		compact = 0;
    -	ASSERT(index == 0 || be32_to_cpu(leaf->ents[index - 1].hashval) <= args->hashval);
    -	ASSERT(index == be16_to_cpu(leaf->hdr.count) ||
    -	       be32_to_cpu(leaf->ents[index].hashval) >= args->hashval);
    -
    -	if (args->justcheck)
    -		return 0;
    -
    -	/*
    -	 * Compact out all but one stale leaf entry.  Leaves behind
    -	 * the entry closest to index.
    -	 */
    -	if (compact) {
    -		xfs_dir2_leaf_compact_x1(bp, &index, &lowstale, &highstale,
    -			&lfloglow, &lfloghigh);
    -	}
    -	/*
    -	 * Set impossible logging indices for this case.
    -	 */
    -	else if (leaf->hdr.stale) {
    -		lfloglow = be16_to_cpu(leaf->hdr.count);
    -		lfloghigh = -1;
    -	}
    -	/*
    -	 * No stale entries, just insert a space for the new entry.
    -	 */
    -	if (!leaf->hdr.stale) {
    -		lep = &leaf->ents[index];
    -		if (index < be16_to_cpu(leaf->hdr.count))
    -			memmove(lep + 1, lep,
    -				(be16_to_cpu(leaf->hdr.count) - index) * sizeof(*lep));
    -		lfloglow = index;
    -		lfloghigh = be16_to_cpu(leaf->hdr.count);
    -		be16_add(&leaf->hdr.count, 1);
    -	}
    -	/*
    -	 * There are stale entries.  We'll use one for the new entry.
    -	 */
    -	else {
    -		/*
    -		 * If we didn't do a compact then we need to figure out
    -		 * which stale entry will be used.
    -		 */
    -		if (compact == 0) {
    -			/*
    -			 * Find first stale entry before our insertion point.
    -			 */
    -			for (lowstale = index - 1;
    -			     lowstale >= 0 &&
    -				be32_to_cpu(leaf->ents[lowstale].address) !=
    -				XFS_DIR2_NULL_DATAPTR;
    -			     lowstale--)
    -				continue;
    -			/*
    -			 * Find next stale entry after insertion point.
    -			 * Stop looking if the answer would be worse than
    -			 * lowstale already found.
    -			 */
    -			for (highstale = index;
    -			     highstale < be16_to_cpu(leaf->hdr.count) &&
    -				be32_to_cpu(leaf->ents[highstale].address) !=
    -				XFS_DIR2_NULL_DATAPTR &&
    -				(lowstale < 0 ||
    -				 index - lowstale - 1 >= highstale - index);
    -			     highstale++)
    -				continue;
    -		}
    -		/*
    -		 * Using the low stale entry.
    -		 * Shift entries up toward the stale slot.
    -		 */
    -		if (lowstale >= 0 &&
    -		    (highstale == be16_to_cpu(leaf->hdr.count) ||
    -		     index - lowstale - 1 < highstale - index)) {
    -			ASSERT(be32_to_cpu(leaf->ents[lowstale].address) ==
    -			       XFS_DIR2_NULL_DATAPTR);
    -			ASSERT(index - lowstale - 1 >= 0);
    -			if (index - lowstale - 1 > 0)
    -				memmove(&leaf->ents[lowstale],
    -					&leaf->ents[lowstale + 1],
    -					(index - lowstale - 1) * sizeof(*lep));
    -			lep = &leaf->ents[index - 1];
    -			lfloglow = MIN(lowstale, lfloglow);
    -			lfloghigh = MAX(index - 1, lfloghigh);
    -		}
    -		/*
    -		 * Using the high stale entry.
    -		 * Shift entries down toward the stale slot.
    -		 */
    -		else {
    -			ASSERT(be32_to_cpu(leaf->ents[highstale].address) ==
    -			       XFS_DIR2_NULL_DATAPTR);
    -			ASSERT(highstale - index >= 0);
    -			if (highstale - index > 0)
    -				memmove(&leaf->ents[index + 1],
    -					&leaf->ents[index],
    -					(highstale - index) * sizeof(*lep));
    -			lep = &leaf->ents[index];
    -			lfloglow = MIN(index, lfloglow);
    -			lfloghigh = MAX(highstale, lfloghigh);
    -		}
    -		be16_add(&leaf->hdr.stale, -1);
    -	}
    -	/*
    -	 * Insert the new entry, log everything.
    -	 */
    -	lep->hashval = cpu_to_be32(args->hashval);
    -	lep->address = cpu_to_be32(XFS_DIR2_DB_OFF_TO_DATAPTR(mp,
    -				args->blkno, args->index));
    -	xfs_dir2_leaf_log_header(tp, bp);
    -	xfs_dir2_leaf_log_ents(tp, bp, lfloglow, lfloghigh);
    -	xfs_dir2_leafn_check(dp, bp);
    -	return 0;
    -}
    -
    -#ifdef DEBUG
    -/*
    - * Check internal consistency of a leafn block.
    - */
    -void
    -xfs_dir2_leafn_check(
    -	xfs_inode_t	*dp,			/* incore directory inode */
    -	xfs_dabuf_t	*bp)			/* leaf buffer */
    -{
    -	int		i;			/* leaf index */
    -	xfs_dir2_leaf_t	*leaf;			/* leaf structure */
    -	xfs_mount_t	*mp;			/* filesystem mount point */
    -	int		stale;			/* count of stale leaves */
    -
    -	leaf = bp->data;
    -	mp = dp->i_mount;
    -	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
    -	ASSERT(be16_to_cpu(leaf->hdr.count) <= XFS_DIR2_MAX_LEAF_ENTS(mp));
    -	for (i = stale = 0; i < be16_to_cpu(leaf->hdr.count); i++) {
    -		if (i + 1 < be16_to_cpu(leaf->hdr.count)) {
    -			ASSERT(be32_to_cpu(leaf->ents[i].hashval) <=
    -			       be32_to_cpu(leaf->ents[i + 1].hashval));
    -		}
    -		if (be32_to_cpu(leaf->ents[i].address) == XFS_DIR2_NULL_DATAPTR)
    -			stale++;
    -	}
    -	ASSERT(be16_to_cpu(leaf->hdr.stale) == stale);
    -}
    -#endif	/* DEBUG */
    -
    -/*
    - * Return the last hash value in the leaf.
    - * Stale entries are ok.
    - */
    -xfs_dahash_t					/* hash value */
    -xfs_dir2_leafn_lasthash(
    -	xfs_dabuf_t	*bp,			/* leaf buffer */
    -	int		*count)			/* count of entries in leaf */
    -{
    -	xfs_dir2_leaf_t	*leaf;			/* leaf structure */
    -
    -	leaf = bp->data;
    -	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
    -	if (count)
    -		*count = be16_to_cpu(leaf->hdr.count);
    -	if (!leaf->hdr.count)
    -		return 0;
    -	return be32_to_cpu(leaf->ents[be16_to_cpu(leaf->hdr.count) - 1].hashval);
    -}
    -
    -/*
    - * Look up a leaf entry in a node-format leaf block.
    - * If this is an addname then the extrablk in state is a freespace block,
    - * otherwise it's a data block.
    - */
    -int
    -xfs_dir2_leafn_lookup_int(
    -	xfs_dabuf_t		*bp,		/* leaf buffer */
    -	xfs_da_args_t		*args,		/* operation arguments */
    -	int			*indexp,	/* out: leaf entry index */
    -	xfs_da_state_t		*state)		/* state to fill in */
    -{
    -	xfs_dabuf_t		*curbp;		/* current data/free buffer */
    -	xfs_dir2_db_t		curdb;		/* current data block number */
    -	xfs_dir2_db_t		curfdb;		/* current free block number */
    -	xfs_dir2_data_entry_t	*dep;		/* data block entry */
    -	xfs_inode_t		*dp;		/* incore directory inode */
    -	int			error;		/* error return value */
    -	int			fi;		/* free entry index */
    -	xfs_dir2_free_t		*free=NULL;	/* free block structure */
    -	int			index;		/* leaf entry index */
    -	xfs_dir2_leaf_t		*leaf;		/* leaf structure */
    -	int			length=0;	/* length of new data entry */
    -	xfs_dir2_leaf_entry_t	*lep;		/* leaf entry */
    -	xfs_mount_t		*mp;		/* filesystem mount point */
    -	xfs_dir2_db_t		newdb;		/* new data block number */
    -	xfs_dir2_db_t		newfdb;		/* new free block number */
    -	xfs_trans_t		*tp;		/* transaction pointer */
    -
    -	dp = args->dp;
    -	tp = args->trans;
    -	mp = dp->i_mount;
    -	leaf = bp->data;
    -	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
    -#ifdef __KERNEL__
    -	ASSERT(be16_to_cpu(leaf->hdr.count) > 0);
    -#endif
    -	xfs_dir2_leafn_check(dp, bp);
    -	/*
    -	 * Look up the hash value in the leaf entries.
    -	 */
    -	index = xfs_dir2_leaf_search_hash(args, bp);
    -	/*
    -	 * Do we have a buffer coming in?
    -	 */
    -	if (state->extravalid)
    -		curbp = state->extrablk.bp;
    -	else
    -		curbp = NULL;
    -	/*
    -	 * For addname, it's a free block buffer, get the block number.
    -	 */
    -	if (args->addname) {
    -		curfdb = curbp ? state->extrablk.blkno : -1;
    -		curdb = -1;
    -		length = XFS_DIR2_DATA_ENTSIZE(args->namelen);
    -		if ((free = (curbp ? curbp->data : NULL)))
    -			ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);
    -	}
    -	/*
    -	 * For others, it's a data block buffer, get the block number.
    -	 */
    -	else {
    -		curfdb = -1;
    -		curdb = curbp ? state->extrablk.blkno : -1;
    -	}
    -	/*
    -	 * Loop over leaf entries with the right hash value.
    -	 */
    -	for (lep = &leaf->ents[index];
    -	     index < be16_to_cpu(leaf->hdr.count) && be32_to_cpu(lep->hashval) == args->hashval;
    -	     lep++, index++) {
    -		/*
    -		 * Skip stale leaf entries.
    -		 */
    -		if (be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR)
    -			continue;
    -		/*
    -		 * Pull the data block number from the entry.
    -		 */
    -		newdb = XFS_DIR2_DATAPTR_TO_DB(mp, be32_to_cpu(lep->address));
    -		/*
    -		 * For addname, we're looking for a place to put the new entry.
    -		 * We want to use a data block with an entry of equal
    -		 * hash value to ours if there is one with room.
    -		 */
    -		if (args->addname) {
    -			/*
    -			 * If this block isn't the data block we already have
    -			 * in hand, take a look at it.
    -			 */
    -			if (newdb != curdb) {
    -				curdb = newdb;
    -				/*
    -				 * Convert the data block to the free block
    -				 * holding its freespace information.
    -				 */
    -				newfdb = XFS_DIR2_DB_TO_FDB(mp, newdb);
    -				/*
    -				 * If it's not the one we have in hand,
    -				 * read it in.
    -				 */
    -				if (newfdb != curfdb) {
    -					/*
    -					 * If we had one before, drop it.
    -					 */
    -					if (curbp)
    -						xfs_da_brelse(tp, curbp);
    -					/*
    -					 * Read the free block.
    -					 */
    -					if ((error = xfs_da_read_buf(tp, dp,
    -							XFS_DIR2_DB_TO_DA(mp,
    -								newfdb),
    -							-1, &curbp,
    -							XFS_DATA_FORK))) {
    -						return error;
    -					}
    -					curfdb = newfdb;
    -					free = curbp->data;
    -					ASSERT(be32_to_cpu(free->hdr.magic) ==
    -					       XFS_DIR2_FREE_MAGIC);
    -					ASSERT((be32_to_cpu(free->hdr.firstdb) %
    -						XFS_DIR2_MAX_FREE_BESTS(mp)) ==
    -					       0);
    -					ASSERT(be32_to_cpu(free->hdr.firstdb) <= curdb);
    -					ASSERT(curdb <
    -					       be32_to_cpu(free->hdr.firstdb) +
    -					       be32_to_cpu(free->hdr.nvalid));
    -				}
    -				/*
    -				 * Get the index for our entry.
    -				 */
    -				fi = XFS_DIR2_DB_TO_FDINDEX(mp, curdb);
    -				/*
    -				 * If it has room, return it.
    -				 */
    -				if (unlikely(be16_to_cpu(free->bests[fi]) == NULLDATAOFF)) {
    -					XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int",
    -							 XFS_ERRLEVEL_LOW, mp);
    -					return XFS_ERROR(EFSCORRUPTED);
    -				}
    -				if (be16_to_cpu(free->bests[fi]) >= length) {
    -					*indexp = index;
    -					state->extravalid = 1;
    -					state->extrablk.bp = curbp;
    -					state->extrablk.blkno = curfdb;
    -					state->extrablk.index = fi;
    -					state->extrablk.magic =
    -						XFS_DIR2_FREE_MAGIC;
    -					ASSERT(args->oknoent);
    -					return XFS_ERROR(ENOENT);
    -				}
    -			}
    -		}
    -		/*
    -		 * Not adding a new entry, so we really want to find
    -		 * the name given to us.
    -		 */
    -		else {
    -			/*
    -			 * If it's a different data block, go get it.
    -			 */
    -			if (newdb != curdb) {
    -				/*
    -				 * If we had a block before, drop it.
    -				 */
    -				if (curbp)
    -					xfs_da_brelse(tp, curbp);
    -				/*
    -				 * Read the data block.
    -				 */
    -				if ((error =
    -				    xfs_da_read_buf(tp, dp,
    -					    XFS_DIR2_DB_TO_DA(mp, newdb), -1,
    -					    &curbp, XFS_DATA_FORK))) {
    -					return error;
    -				}
    -				xfs_dir2_data_check(dp, curbp);
    -				curdb = newdb;
    -			}
    -			/*
    -			 * Point to the data entry.
    -			 */
    -			dep = (xfs_dir2_data_entry_t *)
    -			      ((char *)curbp->data +
    -			       XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(lep->address)));
    -			/*
    -			 * Compare the entry, return it if it matches.
    -			 */
    -			if (dep->namelen == args->namelen &&
    -			    dep->name[0] == args->name[0] &&
    -			    memcmp(dep->name, args->name, args->namelen) == 0) {
    -				args->inumber = INT_GET(dep->inumber, ARCH_CONVERT);
    -				*indexp = index;
    -				state->extravalid = 1;
    -				state->extrablk.bp = curbp;
    -				state->extrablk.blkno = curdb;
    -				state->extrablk.index =
    -					(int)((char *)dep -
    -					      (char *)curbp->data);
    -				state->extrablk.magic = XFS_DIR2_DATA_MAGIC;
    -				return XFS_ERROR(EEXIST);
    -			}
    -		}
    -	}
    -	/*
    -	 * Didn't find a match.
    -	 * If we are holding a buffer, give it back in case our caller
    -	 * finds it useful.
    -	 */
    -	if ((state->extravalid = (curbp != NULL))) {
    -		state->extrablk.bp = curbp;
    -		state->extrablk.index = -1;
    -		/*
    -		 * For addname, giving back a free block.
    -		 */
    -		if (args->addname) {
    -			state->extrablk.blkno = curfdb;
    -			state->extrablk.magic = XFS_DIR2_FREE_MAGIC;
    -		}
    -		/*
    -		 * For other callers, giving back a data block.
    -		 */
    -		else {
    -			state->extrablk.blkno = curdb;
    -			state->extrablk.magic = XFS_DIR2_DATA_MAGIC;
    -		}
    -	}
    -	/*
    -	 * Return the final index, that will be the insertion point.
    -	 */
    -	*indexp = index;
    -	ASSERT(index == be16_to_cpu(leaf->hdr.count) || args->oknoent);
    -	return XFS_ERROR(ENOENT);
    -}
    -
    -/*
    - * Move count leaf entries from source to destination leaf.
    - * Log entries and headers.  Stale entries are preserved.
    - */
    -static void
    -xfs_dir2_leafn_moveents(
    -	xfs_da_args_t	*args,			/* operation arguments */
    -	xfs_dabuf_t	*bp_s,			/* source leaf buffer */
    -	int		start_s,		/* source leaf index */
    -	xfs_dabuf_t	*bp_d,			/* destination leaf buffer */
    -	int		start_d,		/* destination leaf index */
    -	int		count)			/* count of leaves to copy */
    -{
    -	xfs_dir2_leaf_t	*leaf_d;		/* destination leaf structure */
    -	xfs_dir2_leaf_t	*leaf_s;		/* source leaf structure */
    -	int		stale;			/* count stale leaves copied */
    -	xfs_trans_t	*tp;			/* transaction pointer */
    -
    -	xfs_dir2_trace_args_bibii("leafn_moveents", args, bp_s, start_s, bp_d,
    -		start_d, count);
    -	/*
    -	 * Silently return if nothing to do.
    -	 */
    -	if (count == 0) {
    -		return;
    -	}
    -	tp = args->trans;
    -	leaf_s = bp_s->data;
    -	leaf_d = bp_d->data;
    -	/*
    -	 * If the destination index is not the end of the current
    -	 * destination leaf entries, open up a hole in the destination
    -	 * to hold the new entries.
    -	 */
    -	if (start_d < be16_to_cpu(leaf_d->hdr.count)) {
    -		memmove(&leaf_d->ents[start_d + count], &leaf_d->ents[start_d],
    -			(be16_to_cpu(leaf_d->hdr.count) - start_d) *
    -			sizeof(xfs_dir2_leaf_entry_t));
    -		xfs_dir2_leaf_log_ents(tp, bp_d, start_d + count,
    -			count + be16_to_cpu(leaf_d->hdr.count) - 1);
    -	}
    -	/*
    -	 * If the source has stale leaves, count the ones in the copy range
    -	 * so we can update the header correctly.
    -	 */
    -	if (leaf_s->hdr.stale) {
    -		int	i;			/* temp leaf index */
    -
    -		for (i = start_s, stale = 0; i < start_s + count; i++) {
    -			if (be32_to_cpu(leaf_s->ents[i].address) == XFS_DIR2_NULL_DATAPTR)
    -				stale++;
    -		}
    -	} else
    -		stale = 0;
    -	/*
    -	 * Copy the leaf entries from source to destination.
    -	 */
    -	memcpy(&leaf_d->ents[start_d], &leaf_s->ents[start_s],
    -		count * sizeof(xfs_dir2_leaf_entry_t));
    -	xfs_dir2_leaf_log_ents(tp, bp_d, start_d, start_d + count - 1);
    -	/*
    -	 * If there are source entries after the ones we copied,
    -	 * delete the ones we copied by sliding the next ones down.
    -	 */
    -	if (start_s + count < be16_to_cpu(leaf_s->hdr.count)) {
    -		memmove(&leaf_s->ents[start_s], &leaf_s->ents[start_s + count],
    -			count * sizeof(xfs_dir2_leaf_entry_t));
    -		xfs_dir2_leaf_log_ents(tp, bp_s, start_s, start_s + count - 1);
    -	}
    -	/*
    -	 * Update the headers and log them.
    -	 */
    -	be16_add(&leaf_s->hdr.count, -(count));
    -	be16_add(&leaf_s->hdr.stale, -(stale));
    -	be16_add(&leaf_d->hdr.count, count);
    -	be16_add(&leaf_d->hdr.stale, stale);
    -	xfs_dir2_leaf_log_header(tp, bp_s);
    -	xfs_dir2_leaf_log_header(tp, bp_d);
    -	xfs_dir2_leafn_check(args->dp, bp_s);
    -	xfs_dir2_leafn_check(args->dp, bp_d);
    -}
    -
    -/*
    - * Determine the sort order of two leaf blocks.
    - * Returns 1 if both are valid and leaf2 should be before leaf1, else 0.
    - */
    -int						/* sort order */
    -xfs_dir2_leafn_order(
    -	xfs_dabuf_t	*leaf1_bp,		/* leaf1 buffer */
    -	xfs_dabuf_t	*leaf2_bp)		/* leaf2 buffer */
    -{
    -	xfs_dir2_leaf_t	*leaf1;			/* leaf1 structure */
    -	xfs_dir2_leaf_t	*leaf2;			/* leaf2 structure */
    -
    -	leaf1 = leaf1_bp->data;
    -	leaf2 = leaf2_bp->data;
    -	ASSERT(be16_to_cpu(leaf1->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
    -	ASSERT(be16_to_cpu(leaf2->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
    -	if (be16_to_cpu(leaf1->hdr.count) > 0 &&
    -	    be16_to_cpu(leaf2->hdr.count) > 0 &&
    -	    (be32_to_cpu(leaf2->ents[0].hashval) < be32_to_cpu(leaf1->ents[0].hashval) ||
    -	     be32_to_cpu(leaf2->ents[be16_to_cpu(leaf2->hdr.count) - 1].hashval) <
    -	     be32_to_cpu(leaf1->ents[be16_to_cpu(leaf1->hdr.count) - 1].hashval)))
    -		return 1;
    -	return 0;
    -}
    -
    -/*
    - * Rebalance leaf entries between two leaf blocks.
    - * This is actually only called when the second block is new,
    - * though the code deals with the general case.
    - * A new entry will be inserted in one of the blocks, and that
    - * entry is taken into account when balancing.
    - */
    -static void
    -xfs_dir2_leafn_rebalance(
    -	xfs_da_state_t		*state,		/* btree cursor */
    -	xfs_da_state_blk_t	*blk1,		/* first btree block */
    -	xfs_da_state_blk_t	*blk2)		/* second btree block */
    -{
    -	xfs_da_args_t		*args;		/* operation arguments */
    -	int			count;		/* count (& direction) leaves */
    -	int			isleft;		/* new goes in left leaf */
    -	xfs_dir2_leaf_t		*leaf1;		/* first leaf structure */
    -	xfs_dir2_leaf_t		*leaf2;		/* second leaf structure */
    -	int			mid;		/* midpoint leaf index */
    -#ifdef DEBUG
    -	int			oldstale;	/* old count of stale leaves */
    -#endif
    -	int			oldsum;		/* old total leaf count */
    -	int			swap;		/* swapped leaf blocks */
    -
    -	args = state->args;
    -	/*
    -	 * If the block order is wrong, swap the arguments.
    -	 */
    -	if ((swap = xfs_dir2_leafn_order(blk1->bp, blk2->bp))) {
    -		xfs_da_state_blk_t	*tmp;	/* temp for block swap */
    -
    -		tmp = blk1;
    -		blk1 = blk2;
    -		blk2 = tmp;
    -	}
    -	leaf1 = blk1->bp->data;
    -	leaf2 = blk2->bp->data;
    -	oldsum = be16_to_cpu(leaf1->hdr.count) + be16_to_cpu(leaf2->hdr.count);
    -#ifdef DEBUG
    -	oldstale = be16_to_cpu(leaf1->hdr.stale) + be16_to_cpu(leaf2->hdr.stale);
    -#endif
    -	mid = oldsum >> 1;
    -	/*
    -	 * If the old leaf count was odd then the new one will be even,
    -	 * so we need to divide the new count evenly.
    -	 */
    -	if (oldsum & 1) {
    -		xfs_dahash_t	midhash;	/* middle entry hash value */
    -
    -		if (mid >= be16_to_cpu(leaf1->hdr.count))
    -			midhash = be32_to_cpu(leaf2->ents[mid - be16_to_cpu(leaf1->hdr.count)].hashval);
    -		else
    -			midhash = be32_to_cpu(leaf1->ents[mid].hashval);
    -		isleft = args->hashval <= midhash;
    -	}
    -	/*
    -	 * If the old count is even then the new count is odd, so there's
    -	 * no preferred side for the new entry.
    -	 * Pick the left one.
    -	 */
    -	else
    -		isleft = 1;
    -	/*
    -	 * Calculate moved entry count.  Positive means left-to-right,
    -	 * negative means right-to-left.  Then move the entries.
    -	 */
    -	count = be16_to_cpu(leaf1->hdr.count) - mid + (isleft == 0);
    -	if (count > 0)
    -		xfs_dir2_leafn_moveents(args, blk1->bp,
    -			be16_to_cpu(leaf1->hdr.count) - count, blk2->bp, 0, count);
    -	else if (count < 0)
    -		xfs_dir2_leafn_moveents(args, blk2->bp, 0, blk1->bp,
    -			be16_to_cpu(leaf1->hdr.count), count);
    -	ASSERT(be16_to_cpu(leaf1->hdr.count) + be16_to_cpu(leaf2->hdr.count) == oldsum);
    -	ASSERT(be16_to_cpu(leaf1->hdr.stale) + be16_to_cpu(leaf2->hdr.stale) == oldstale);
    -	/*
    -	 * Mark whether we're inserting into the old or new leaf.
    -	 */
    -	if (be16_to_cpu(leaf1->hdr.count) < be16_to_cpu(leaf2->hdr.count))
    -		state->inleaf = swap;
    -	else if (be16_to_cpu(leaf1->hdr.count) > be16_to_cpu(leaf2->hdr.count))
    -		state->inleaf = !swap;
    -	else
    -		state->inleaf =
    -			swap ^ (blk1->index <= be16_to_cpu(leaf1->hdr.count));
    -	/*
    -	 * Adjust the expected index for insertion.
    -	 */
    -	if (!state->inleaf)
    -		blk2->index = blk1->index - be16_to_cpu(leaf1->hdr.count);
    -	
    -	/* 
    -	 * Finally sanity check just to make sure we are not returning a negative index 
    -	 */
    -	if(blk2->index < 0) {
    -		state->inleaf = 1;
    -		blk2->index = 0;
    -		cmn_err(CE_ALERT,
    -			"xfs_dir2_leafn_rebalance: picked the wrong leaf? reverting original leaf: "
    -			"blk1->index %d\n",
    -			blk1->index);
    -	}
    -}
    -
    -/*
    - * Remove an entry from a node directory.
    - * This removes the leaf entry and the data entry,
    - * and updates the free block if necessary.
    - */
    -static int					/* error */
    -xfs_dir2_leafn_remove(
    -	xfs_da_args_t		*args,		/* operation arguments */
    -	xfs_dabuf_t		*bp,		/* leaf buffer */
    -	int			index,		/* leaf entry index */
    -	xfs_da_state_blk_t	*dblk,		/* data block */
    -	int			*rval)		/* resulting block needs join */
    -{
    -	xfs_dir2_data_t		*data;		/* data block structure */
    -	xfs_dir2_db_t		db;		/* data block number */
    -	xfs_dabuf_t		*dbp;		/* data block buffer */
    -	xfs_dir2_data_entry_t	*dep;		/* data block entry */
    -	xfs_inode_t		*dp;		/* incore directory inode */
    -	xfs_dir2_leaf_t		*leaf;		/* leaf structure */
    -	xfs_dir2_leaf_entry_t	*lep;		/* leaf entry */
    -	int			longest;	/* longest data free entry */
    -	int			off;		/* data block entry offset */
    -	xfs_mount_t		*mp;		/* filesystem mount point */
    -	int			needlog;	/* need to log data header */
    -	int			needscan;	/* need to rescan data frees */
    -	xfs_trans_t		*tp;		/* transaction pointer */
    -
    -	xfs_dir2_trace_args_sb("leafn_remove", args, index, bp);
    -	dp = args->dp;
    -	tp = args->trans;
    -	mp = dp->i_mount;
    -	leaf = bp->data;
    -	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
    -	/*
    -	 * Point to the entry we're removing.
    -	 */
    -	lep = &leaf->ents[index];
    -	/*
    -	 * Extract the data block and offset from the entry.
    -	 */
    -	db = XFS_DIR2_DATAPTR_TO_DB(mp, be32_to_cpu(lep->address));
    -	ASSERT(dblk->blkno == db);
    -	off = XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(lep->address));
    -	ASSERT(dblk->index == off);
    -	/*
    -	 * Kill the leaf entry by marking it stale.
    -	 * Log the leaf block changes.
    -	 */
    -	be16_add(&leaf->hdr.stale, 1);
    -	xfs_dir2_leaf_log_header(tp, bp);
    -	lep->address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR);
    -	xfs_dir2_leaf_log_ents(tp, bp, index, index);
    -	/*
    -	 * Make the data entry free.  Keep track of the longest freespace
    -	 * in the data block in case it changes.
    -	 */
    -	dbp = dblk->bp;
    -	data = dbp->data;
    -	dep = (xfs_dir2_data_entry_t *)((char *)data + off);
    -	longest = be16_to_cpu(data->hdr.bestfree[0].length);
    -	needlog = needscan = 0;
    -	xfs_dir2_data_make_free(tp, dbp, off,
    -		XFS_DIR2_DATA_ENTSIZE(dep->namelen), &needlog, &needscan);
    -	/*
    -	 * Rescan the data block freespaces for bestfree.
    -	 * Log the data block header if needed.
    -	 */
    -	if (needscan)
    -		xfs_dir2_data_freescan(mp, data, &needlog, NULL);
    -	if (needlog)
    -		xfs_dir2_data_log_header(tp, dbp);
    -	xfs_dir2_data_check(dp, dbp);
    -	/*
    -	 * If the longest data block freespace changes, need to update
    -	 * the corresponding freeblock entry.
    -	 */
    -	if (longest < be16_to_cpu(data->hdr.bestfree[0].length)) {
    -		int		error;		/* error return value */
    -		xfs_dabuf_t	*fbp;		/* freeblock buffer */
    -		xfs_dir2_db_t	fdb;		/* freeblock block number */
    -		int		findex;		/* index in freeblock entries */
    -		xfs_dir2_free_t	*free;		/* freeblock structure */
    -		int		logfree;	/* need to log free entry */
    -
    -		/*
    -		 * Convert the data block number to a free block,
    -		 * read in the free block.
    -		 */
    -		fdb = XFS_DIR2_DB_TO_FDB(mp, db);
    -		if ((error = xfs_da_read_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, fdb),
    -				-1, &fbp, XFS_DATA_FORK))) {
    -			return error;
    -		}
    -		free = fbp->data;
    -		ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);
    -		ASSERT(be32_to_cpu(free->hdr.firstdb) ==
    -		       XFS_DIR2_MAX_FREE_BESTS(mp) *
    -		       (fdb - XFS_DIR2_FREE_FIRSTDB(mp)));
    -		/*
    -		 * Calculate which entry we need to fix.
    -		 */
    -		findex = XFS_DIR2_DB_TO_FDINDEX(mp, db);
    -		longest = be16_to_cpu(data->hdr.bestfree[0].length);
    -		/*
    -		 * If the data block is now empty we can get rid of it
    -		 * (usually).
    -		 */
    -		if (longest == mp->m_dirblksize - (uint)sizeof(data->hdr)) {
    -			/*
    -			 * Try to punch out the data block.
    -			 */
    -			error = xfs_dir2_shrink_inode(args, db, dbp);
    -			if (error == 0) {
    -				dblk->bp = NULL;
    -				data = NULL;
    -			}
    -			/*
    -			 * We can get ENOSPC if there's no space reservation.
    -			 * In this case just drop the buffer and some one else
    -			 * will eventually get rid of the empty block.
    -			 */
    -			else if (error == ENOSPC && args->total == 0)
    -				xfs_da_buf_done(dbp);
    -			else
    -				return error;
    -		}
    -		/*
    -		 * If we got rid of the data block, we can eliminate that entry
    -		 * in the free block.
    -		 */
    -		if (data == NULL) {
    -			/*
    -			 * One less used entry in the free table.
    -			 */
    -			free->hdr.nused = cpu_to_be32(-1);
    -			xfs_dir2_free_log_header(tp, fbp);
    -			/*
    -			 * If this was the last entry in the table, we can
    -			 * trim the table size back.  There might be other
    -			 * entries at the end referring to non-existent
    -			 * data blocks, get those too.
    -			 */
    -			if (findex == be32_to_cpu(free->hdr.nvalid) - 1) {
    -				int	i;		/* free entry index */
    -
    -				for (i = findex - 1;
    -				     i >= 0 && be16_to_cpu(free->bests[i]) == NULLDATAOFF;
    -				     i--)
    -					continue;
    -				free->hdr.nvalid = cpu_to_be32(i + 1);
    -				logfree = 0;
    -			}
    -			/*
    -			 * Not the last entry, just punch it out.
    -			 */
    -			else {
    -				free->bests[findex] = cpu_to_be16(NULLDATAOFF);
    -				logfree = 1;
    -			}
    -			/*
    -			 * If there are no useful entries left in the block,
    -			 * get rid of the block if we can.
    -			 */
    -			if (!free->hdr.nused) {
    -				error = xfs_dir2_shrink_inode(args, fdb, fbp);
    -				if (error == 0) {
    -					fbp = NULL;
    -					logfree = 0;
    -				} else if (error != ENOSPC || args->total != 0)
    -					return error;
    -				/*
    -				 * It's possible to get ENOSPC if there is no
    -				 * space reservation.  In this case some one
    -				 * else will eventually get rid of this block.
    -				 */
    -			}
    -		}
    -		/*
    -		 * Data block is not empty, just set the free entry to
    -		 * the new value.
    -		 */
    -		else {
    -			free->bests[findex] = cpu_to_be16(longest);
    -			logfree = 1;
    -		}
    -		/*
    -		 * Log the free entry that changed, unless we got rid of it.
    -		 */
    -		if (logfree)
    -			xfs_dir2_free_log_bests(tp, fbp, findex, findex);
    -		/*
    -		 * Drop the buffer if we still have it.
    -		 */
    -		if (fbp)
    -			xfs_da_buf_done(fbp);
    -	}
    -	xfs_dir2_leafn_check(dp, bp);
    -	/*
    -	 * Return indication of whether this leaf block is emtpy enough
    -	 * to justify trying to join it with a neighbor.
    -	 */
    -	*rval =
    -		((uint)sizeof(leaf->hdr) +
    -		 (uint)sizeof(leaf->ents[0]) *
    -		 (be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale))) <
    -		mp->m_dir_magicpct;
    -	return 0;
    -}
    -
    -/*
    - * Split the leaf entries in the old block into old and new blocks.
    - */
    -int						/* error */
    -xfs_dir2_leafn_split(
    -	xfs_da_state_t		*state,		/* btree cursor */
    -	xfs_da_state_blk_t	*oldblk,	/* original block */
    -	xfs_da_state_blk_t	*newblk)	/* newly created block */
    -{
    -	xfs_da_args_t		*args;		/* operation arguments */
    -	xfs_dablk_t		blkno;		/* new leaf block number */
    -	int			error;		/* error return value */
    -	xfs_mount_t		*mp;		/* filesystem mount point */
    -
    -	/*
    -	 * Allocate space for a new leaf node.
    -	 */
    -	args = state->args;
    -	mp = args->dp->i_mount;
    -	ASSERT(args != NULL);
    -	ASSERT(oldblk->magic == XFS_DIR2_LEAFN_MAGIC);
    -	error = xfs_da_grow_inode(args, &blkno);
    -	if (error) {
    -		return error;
    -	}
    -	/*
    -	 * Initialize the new leaf block.
    -	 */
    -	error = xfs_dir2_leaf_init(args, XFS_DIR2_DA_TO_DB(mp, blkno),
    -		&newblk->bp, XFS_DIR2_LEAFN_MAGIC);
    -	if (error) {
    -		return error;
    -	}
    -	newblk->blkno = blkno;
    -	newblk->magic = XFS_DIR2_LEAFN_MAGIC;
    -	/*
    -	 * Rebalance the entries across the two leaves, link the new
    -	 * block into the leaves.
    -	 */
    -	xfs_dir2_leafn_rebalance(state, oldblk, newblk);
    -	error = xfs_da_blk_link(state, oldblk, newblk);
    -	if (error) {
    -		return error;
    -	}
    -	/*
    -	 * Insert the new entry in the correct block.
    -	 */
    -	if (state->inleaf)
    -		error = xfs_dir2_leafn_add(oldblk->bp, args, oldblk->index);
    -	else
    -		error = xfs_dir2_leafn_add(newblk->bp, args, newblk->index);
    -	/*
    -	 * Update last hashval in each block since we added the name.
    -	 */
    -	oldblk->hashval = xfs_dir2_leafn_lasthash(oldblk->bp, NULL);
    -	newblk->hashval = xfs_dir2_leafn_lasthash(newblk->bp, NULL);
    -	xfs_dir2_leafn_check(args->dp, oldblk->bp);
    -	xfs_dir2_leafn_check(args->dp, newblk->bp);
    -	return error;
    -}
    -
    -/*
    - * Check a leaf block and its neighbors to see if the block should be
    - * collapsed into one or the other neighbor.  Always keep the block
    - * with the smaller block number.
    - * If the current block is over 50% full, don't try to join it, return 0.
    - * If the block is empty, fill in the state structure and return 2.
    - * If it can be collapsed, fill in the state structure and return 1.
    - * If nothing can be done, return 0.
    - */
    -int						/* error */
    -xfs_dir2_leafn_toosmall(
    -	xfs_da_state_t		*state,		/* btree cursor */
    -	int			*action)	/* resulting action to take */
    -{
    -	xfs_da_state_blk_t	*blk;		/* leaf block */
    -	xfs_dablk_t		blkno;		/* leaf block number */
    -	xfs_dabuf_t		*bp;		/* leaf buffer */
    -	int			bytes;		/* bytes in use */
    -	int			count;		/* leaf live entry count */
    -	int			error;		/* error return value */
    -	int			forward;	/* sibling block direction */
    -	int			i;		/* sibling counter */
    -	xfs_da_blkinfo_t	*info;		/* leaf block header */
    -	xfs_dir2_leaf_t		*leaf;		/* leaf structure */
    -	int			rval;		/* result from path_shift */
    -
    -	/*
    -	 * Check for the degenerate case of the block being over 50% full.
    -	 * If so, it's not worth even looking to see if we might be able
    -	 * to coalesce with a sibling.
    -	 */
    -	blk = &state->path.blk[state->path.active - 1];
    -	info = blk->bp->data;
    -	ASSERT(be16_to_cpu(info->magic) == XFS_DIR2_LEAFN_MAGIC);
    -	leaf = (xfs_dir2_leaf_t *)info;
    -	count = be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale);
    -	bytes = (uint)sizeof(leaf->hdr) + count * (uint)sizeof(leaf->ents[0]);
    -	if (bytes > (state->blocksize >> 1)) {
    -		/*
    -		 * Blk over 50%, don't try to join.
    -		 */
    -		*action = 0;
    -		return 0;
    -	}
    -	/*
    -	 * Check for the degenerate case of the block being empty.
    -	 * If the block is empty, we'll simply delete it, no need to
    -	 * coalesce it with a sibling block.  We choose (arbitrarily)
    -	 * to merge with the forward block unless it is NULL.
    -	 */
    -	if (count == 0) {
    -		/*
    -		 * Make altpath point to the block we want to keep and
    -		 * path point to the block we want to drop (this one).
    -		 */
    -		forward = (info->forw != 0);
    -		memcpy(&state->altpath, &state->path, sizeof(state->path));
    -		error = xfs_da_path_shift(state, &state->altpath, forward, 0,
    -			&rval);
    -		if (error)
    -			return error;
    -		*action = rval ? 2 : 0;
    -		return 0;
    -	}
    -	/*
    -	 * Examine each sibling block to see if we can coalesce with
    -	 * at least 25% free space to spare.  We need to figure out
    -	 * whether to merge with the forward or the backward block.
    -	 * We prefer coalescing with the lower numbered sibling so as
    -	 * to shrink a directory over time.
    -	 */
    -	forward = be32_to_cpu(info->forw) < be32_to_cpu(info->back);
    -	for (i = 0, bp = NULL; i < 2; forward = !forward, i++) {
    -		blkno = forward ? be32_to_cpu(info->forw) : be32_to_cpu(info->back);
    -		if (blkno == 0)
    -			continue;
    -		/*
    -		 * Read the sibling leaf block.
    -		 */
    -		if ((error =
    -		    xfs_da_read_buf(state->args->trans, state->args->dp, blkno,
    -			    -1, &bp, XFS_DATA_FORK))) {
    -			return error;
    -		}
    -		ASSERT(bp != NULL);
    -		/*
    -		 * Count bytes in the two blocks combined.
    -		 */
    -		leaf = (xfs_dir2_leaf_t *)info;
    -		count = be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale);
    -		bytes = state->blocksize - (state->blocksize >> 2);
    -		leaf = bp->data;
    -		ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
    -		count += be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale);
    -		bytes -= count * (uint)sizeof(leaf->ents[0]);
    -		/*
    -		 * Fits with at least 25% to spare.
    -		 */
    -		if (bytes >= 0)
    -			break;
    -		xfs_da_brelse(state->args->trans, bp);
    -	}
    -	/*
    -	 * Didn't like either block, give up.
    -	 */
    -	if (i >= 2) {
    -		*action = 0;
    -		return 0;
    -	}
    -	/*
    -	 * Done with the sibling leaf block here, drop the dabuf
    -	 * so path_shift can get it.
    -	 */
    -	xfs_da_buf_done(bp);
    -	/*
    -	 * Make altpath point to the block we want to keep (the lower
    -	 * numbered block) and path point to the block we want to drop.
    -	 */
    -	memcpy(&state->altpath, &state->path, sizeof(state->path));
    -	if (blkno < blk->blkno)
    -		error = xfs_da_path_shift(state, &state->altpath, forward, 0,
    -			&rval);
    -	else
    -		error = xfs_da_path_shift(state, &state->path, forward, 0,
    -			&rval);
    -	if (error) {
    -		return error;
    -	}
    -	*action = rval ? 0 : 1;
    -	return 0;
    -}
    -
    -/*
    - * Move all the leaf entries from drop_blk to save_blk.
    - * This is done as part of a join operation.
    - */
    -void
    -xfs_dir2_leafn_unbalance(
    -	xfs_da_state_t		*state,		/* cursor */
    -	xfs_da_state_blk_t	*drop_blk,	/* dead block */
    -	xfs_da_state_blk_t	*save_blk)	/* surviving block */
    -{
    -	xfs_da_args_t		*args;		/* operation arguments */
    -	xfs_dir2_leaf_t		*drop_leaf;	/* dead leaf structure */
    -	xfs_dir2_leaf_t		*save_leaf;	/* surviving leaf structure */
    -
    -	args = state->args;
    -	ASSERT(drop_blk->magic == XFS_DIR2_LEAFN_MAGIC);
    -	ASSERT(save_blk->magic == XFS_DIR2_LEAFN_MAGIC);
    -	drop_leaf = drop_blk->bp->data;
    -	save_leaf = save_blk->bp->data;
    -	ASSERT(be16_to_cpu(drop_leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
    -	ASSERT(be16_to_cpu(save_leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
    -	/*
    -	 * If there are any stale leaf entries, take this opportunity
    -	 * to purge them.
    -	 */
    -	if (drop_leaf->hdr.stale)
    -		xfs_dir2_leaf_compact(args, drop_blk->bp);
    -	if (save_leaf->hdr.stale)
    -		xfs_dir2_leaf_compact(args, save_blk->bp);
    -	/*
    -	 * Move the entries from drop to the appropriate end of save.
    -	 */
    -	drop_blk->hashval = be32_to_cpu(drop_leaf->ents[be16_to_cpu(drop_leaf->hdr.count) - 1].hashval);
    -	if (xfs_dir2_leafn_order(save_blk->bp, drop_blk->bp))
    -		xfs_dir2_leafn_moveents(args, drop_blk->bp, 0, save_blk->bp, 0,
    -			be16_to_cpu(drop_leaf->hdr.count));
    -	else
    -		xfs_dir2_leafn_moveents(args, drop_blk->bp, 0, save_blk->bp,
    -			be16_to_cpu(save_leaf->hdr.count), be16_to_cpu(drop_leaf->hdr.count));
    -	save_blk->hashval = be32_to_cpu(save_leaf->ents[be16_to_cpu(save_leaf->hdr.count) - 1].hashval);
    -	xfs_dir2_leafn_check(args->dp, save_blk->bp);
    -}
    -
    -/*
    - * Top-level node form directory addname routine.
    - */
    -int						/* error */
    -xfs_dir2_node_addname(
    -	xfs_da_args_t		*args)		/* operation arguments */
    -{
    -	xfs_da_state_blk_t	*blk;		/* leaf block for insert */
    -	int			error;		/* error return value */
    -	int			rval;		/* sub-return value */
    -	xfs_da_state_t		*state;		/* btree cursor */
    -
    -	xfs_dir2_trace_args("node_addname", args);
    -	/*
    -	 * Allocate and initialize the state (btree cursor).
    -	 */
    -	state = xfs_da_state_alloc();
    -	state->args = args;
    -	state->mp = args->dp->i_mount;
    -	state->blocksize = state->mp->m_dirblksize;
    -	state->node_ents = state->mp->m_dir_node_ents;
    -	/*
    -	 * Look up the name.  We're not supposed to find it, but
    -	 * this gives us the insertion point.
    -	 */
    -	error = xfs_da_node_lookup_int(state, &rval);
    -	if (error)
    -		rval = error;
    -	if (rval != ENOENT) {
    -		goto done;
    -	}
    -	/*
    -	 * Add the data entry to a data block.
    -	 * Extravalid is set to a freeblock found by lookup.
    -	 */
    -	rval = xfs_dir2_node_addname_int(args,
    -		state->extravalid ? &state->extrablk : NULL);
    -	if (rval) {
    -		goto done;
    -	}
    -	blk = &state->path.blk[state->path.active - 1];
    -	ASSERT(blk->magic == XFS_DIR2_LEAFN_MAGIC);
    -	/*
    -	 * Add the new leaf entry.
    -	 */
    -	rval = xfs_dir2_leafn_add(blk->bp, args, blk->index);
    -	if (rval == 0) {
    -		/*
    -		 * It worked, fix the hash values up the btree.
    -		 */
    -		if (!args->justcheck)
    -			xfs_da_fixhashpath(state, &state->path);
    -	} else {
    -		/*
    -		 * It didn't work, we need to split the leaf block.
    -		 */
    -		if (args->total == 0) {
    -			ASSERT(rval == ENOSPC);
    -			goto done;
    -		}
    -		/*
    -		 * Split the leaf block and insert the new entry.
    -		 */
    -		rval = xfs_da_split(state);
    -	}
    -done:
    -	xfs_da_state_free(state);
    -	return rval;
    -}
    -
    -/*
    - * Add the data entry for a node-format directory name addition.
    - * The leaf entry is added in xfs_dir2_leafn_add.
    - * We may enter with a freespace block that the lookup found.
    - */
    -static int					/* error */
    -xfs_dir2_node_addname_int(
    -	xfs_da_args_t		*args,		/* operation arguments */
    -	xfs_da_state_blk_t	*fblk)		/* optional freespace block */
    -{
    -	xfs_dir2_data_t		*data;		/* data block structure */
    -	xfs_dir2_db_t		dbno;		/* data block number */
    -	xfs_dabuf_t		*dbp;		/* data block buffer */
    -	xfs_dir2_data_entry_t	*dep;		/* data entry pointer */
    -	xfs_inode_t		*dp;		/* incore directory inode */
    -	xfs_dir2_data_unused_t	*dup;		/* data unused entry pointer */
    -	int			error;		/* error return value */
    -	xfs_dir2_db_t		fbno;		/* freespace block number */
    -	xfs_dabuf_t		*fbp;		/* freespace buffer */
    -	int			findex;		/* freespace entry index */
    -	xfs_dir2_free_t		*free=NULL;	/* freespace block structure */
    -	xfs_dir2_db_t		ifbno;		/* initial freespace block no */
    -	xfs_dir2_db_t		lastfbno=0;	/* highest freespace block no */
    -	int			length;		/* length of the new entry */
    -	int			logfree;	/* need to log free entry */
    -	xfs_mount_t		*mp;		/* filesystem mount point */
    -	int			needlog;	/* need to log data header */
    -	int			needscan;	/* need to rescan data frees */
    -	__be16			*tagp;		/* data entry tag pointer */
    -	xfs_trans_t		*tp;		/* transaction pointer */
    -
    -	dp = args->dp;
    -	mp = dp->i_mount;
    -	tp = args->trans;
    -	length = XFS_DIR2_DATA_ENTSIZE(args->namelen);
    -	/*
    -	 * If we came in with a freespace block that means that lookup
    -	 * found an entry with our hash value.  This is the freespace
    -	 * block for that data entry.
    -	 */
    -	if (fblk) {
    -		fbp = fblk->bp;
    -		/*
    -		 * Remember initial freespace block number.
    -		 */
    -		ifbno = fblk->blkno;
    -		free = fbp->data;
    -		ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);
    -		findex = fblk->index;
    -		/*
    -		 * This means the free entry showed that the data block had
    -		 * space for our entry, so we remembered it.
    -		 * Use that data block.
    -		 */
    -		if (findex >= 0) {
    -			ASSERT(findex < be32_to_cpu(free->hdr.nvalid));
    -			ASSERT(be16_to_cpu(free->bests[findex]) != NULLDATAOFF);
    -			ASSERT(be16_to_cpu(free->bests[findex]) >= length);
    -			dbno = be32_to_cpu(free->hdr.firstdb) + findex;
    -		}
    -		/*
    -		 * The data block looked at didn't have enough room.
    -		 * We'll start at the beginning of the freespace entries.
    -		 */
    -		else {
    -			dbno = -1;
    -			findex = 0;
    -		}
    -	}
    -	/*
    -	 * Didn't come in with a freespace block, so don't have a data block.
    -	 */
    -	else {
    -		ifbno = dbno = -1;
    -		fbp = NULL;
    -		findex = 0;
    -	}
    -	/*
    -	 * If we don't have a data block yet, we're going to scan the
    -	 * freespace blocks looking for one.  Figure out what the
    -	 * highest freespace block number is.
    -	 */
    -	if (dbno == -1) {
    -		xfs_fileoff_t	fo;		/* freespace block number */
    -
    -		if ((error = xfs_bmap_last_offset(tp, dp, &fo, XFS_DATA_FORK)))
    -			return error;
    -		lastfbno = XFS_DIR2_DA_TO_DB(mp, (xfs_dablk_t)fo);
    -		fbno = ifbno;
    -	}
    -	/*
    -	 * While we haven't identified a data block, search the freeblock
    -	 * data for a good data block.  If we find a null freeblock entry,
    -	 * indicating a hole in the data blocks, remember that.
    -	 */
    -	while (dbno == -1) {
    -		/*
    -		 * If we don't have a freeblock in hand, get the next one.
    -		 */
    -		if (fbp == NULL) {
    -			/*
    -			 * Happens the first time through unless lookup gave
    -			 * us a freespace block to start with.
    -			 */
    -			if (++fbno == 0)
    -				fbno = XFS_DIR2_FREE_FIRSTDB(mp);
    -			/*
    -			 * If it's ifbno we already looked at it.
    -			 */
    -			if (fbno == ifbno)
    -				fbno++;
    -			/*
    -			 * If it's off the end we're done.
    -			 */
    -			if (fbno >= lastfbno)
    -				break;
    -			/*
    -			 * Read the block.  There can be holes in the
    -			 * freespace blocks, so this might not succeed.
    -			 * This should be really rare, so there's no reason
    -			 * to avoid it.
    -			 */
    -			if ((error = xfs_da_read_buf(tp, dp,
    -					XFS_DIR2_DB_TO_DA(mp, fbno), -2, &fbp,
    -					XFS_DATA_FORK))) {
    -				return error;
    -			}
    -			if (unlikely(fbp == NULL)) {
    -				continue;
    -			}
    -			free = fbp->data;
    -			ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);
    -			findex = 0;
    -		}
    -		/*
    -		 * Look at the current free entry.  Is it good enough?
    -		 */
    -		if (be16_to_cpu(free->bests[findex]) != NULLDATAOFF &&
    -		    be16_to_cpu(free->bests[findex]) >= length)
    -			dbno = be32_to_cpu(free->hdr.firstdb) + findex;
    -		else {
    -			/*
    -			 * Are we done with the freeblock?
    -			 */
    -			if (++findex == be32_to_cpu(free->hdr.nvalid)) {
    -				/*
    -				 * Drop the block.
    -				 */
    -				xfs_da_brelse(tp, fbp);
    -				fbp = NULL;
    -				if (fblk && fblk->bp)
    -					fblk->bp = NULL;
    -			}
    -		}
    -	}
    -	/*
    -	 * If we don't have a data block, we need to allocate one and make
    -	 * the freespace entries refer to it.
    -	 */
    -	if (unlikely(dbno == -1)) {
    -		/*
    -		 * Not allowed to allocate, return failure.
    -		 */
    -		if (args->justcheck || args->total == 0) {
    -			/*
    -			 * Drop the freespace buffer unless it came from our
    -			 * caller.
    -			 */
    -			if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL)
    -				xfs_da_buf_done(fbp);
    -			return XFS_ERROR(ENOSPC);
    -		}
    -		/*
    -		 * Allocate and initialize the new data block.
    -		 */
    -		if (unlikely((error = xfs_dir2_grow_inode(args,
    -							 XFS_DIR2_DATA_SPACE,
    -							 &dbno)) ||
    -		    (error = xfs_dir2_data_init(args, dbno, &dbp)))) {
    -			/*
    -			 * Drop the freespace buffer unless it came from our
    -			 * caller.
    -			 */
    -			if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL)
    -				xfs_da_buf_done(fbp);
    -			return error;
    -		}
    -		/*
    -		 * If (somehow) we have a freespace block, get rid of it.
    -		 */
    -		if (fbp)
    -			xfs_da_brelse(tp, fbp);
    -		if (fblk && fblk->bp)
    -			fblk->bp = NULL;
    -
    -		/*
    -		 * Get the freespace block corresponding to the data block
    -		 * that was just allocated.
    -		 */
    -		fbno = XFS_DIR2_DB_TO_FDB(mp, dbno);
    -		if (unlikely(error = xfs_da_read_buf(tp, dp,
    -				XFS_DIR2_DB_TO_DA(mp, fbno), -2, &fbp,
    -				XFS_DATA_FORK))) {
    -			xfs_da_buf_done(dbp);
    -			return error;
    -  		}
    -		/*
    -		 * If there wasn't a freespace block, the read will
    -		 * return a NULL fbp.  Allocate and initialize a new one.
    -		 */
    -		if( fbp == NULL ) {
    -			if ((error = xfs_dir2_grow_inode(args, XFS_DIR2_FREE_SPACE,
    -							&fbno))) {
    -				return error;
    -			}
    -
    -			if (unlikely(XFS_DIR2_DB_TO_FDB(mp, dbno) != fbno)) {
    -				cmn_err(CE_ALERT,
    -					"xfs_dir2_node_addname_int: dir ino "
    -					"%llu needed freesp block %lld for\n"
    -					"  data block %lld, got %lld\n"
    -					"  ifbno %llu lastfbno %d\n",
    -					(unsigned long long)dp->i_ino,
    -					(long long)XFS_DIR2_DB_TO_FDB(mp, dbno),
    -					(long long)dbno, (long long)fbno,
    -					(unsigned long long)ifbno, lastfbno);
    -				if (fblk) {
    -					cmn_err(CE_ALERT,
    -						" fblk 0x%p blkno %llu "
    -						"index %d magic 0x%x\n",
    -						fblk,
    -						(unsigned long long)fblk->blkno,
    -						fblk->index,
    -						fblk->magic);
    -				} else {
    -					cmn_err(CE_ALERT,
    -						" ... fblk is NULL\n");
    -				}
    -				XFS_ERROR_REPORT("xfs_dir2_node_addname_int",
    -						 XFS_ERRLEVEL_LOW, mp);
    -				return XFS_ERROR(EFSCORRUPTED);
    -			}
    -
    -			/*
    -			 * Get a buffer for the new block.
    -			 */
    -			if ((error = xfs_da_get_buf(tp, dp,
    -						   XFS_DIR2_DB_TO_DA(mp, fbno),
    -						   -1, &fbp, XFS_DATA_FORK))) {
    -				return error;
    -			}
    -			ASSERT(fbp != NULL);
    -
    -			/*
    -			 * Initialize the new block to be empty, and remember
    -			 * its first slot as our empty slot.
    -			 */
    -			free = fbp->data;
    -			free->hdr.magic = cpu_to_be32(XFS_DIR2_FREE_MAGIC);
    -			free->hdr.firstdb = cpu_to_be32(
    -				(fbno - XFS_DIR2_FREE_FIRSTDB(mp)) *
    -				XFS_DIR2_MAX_FREE_BESTS(mp));
    -			free->hdr.nvalid = 0;
    -			free->hdr.nused = 0;
    -		} else {
    -			free = fbp->data;
    -			ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);
    -		}
    -
    -		/*
    -		 * Set the freespace block index from the data block number.
    -		 */
    -		findex = XFS_DIR2_DB_TO_FDINDEX(mp, dbno);
    -		/*
    -		 * If it's after the end of the current entries in the
    -		 * freespace block, extend that table.
    -		 */
    -		if (findex >= be32_to_cpu(free->hdr.nvalid)) {
    -			ASSERT(findex < XFS_DIR2_MAX_FREE_BESTS(mp));
    -			free->hdr.nvalid = cpu_to_be32(findex + 1);
    -			/*
    -			 * Tag new entry so nused will go up.
    -			 */
    -			free->bests[findex] = cpu_to_be16(NULLDATAOFF);
    -		}
    -		/*
    -		 * If this entry was for an empty data block
    -		 * (this should always be true) then update the header.
    -		 */
    -		if (be16_to_cpu(free->bests[findex]) == NULLDATAOFF) {
    -			be32_add(&free->hdr.nused, 1);
    -			xfs_dir2_free_log_header(tp, fbp);
    -		}
    -		/*
    -		 * Update the real value in the table.
    -		 * We haven't allocated the data entry yet so this will
    -		 * change again.
    -		 */
    -		data = dbp->data;
    -		free->bests[findex] = data->hdr.bestfree[0].length;
    -		logfree = 1;
    -	}
    -	/*
    -	 * We had a data block so we don't have to make a new one.
    -	 */
    -	else {
    -		/*
    -		 * If just checking, we succeeded.
    -		 */
    -		if (args->justcheck) {
    -			if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL)
    -				xfs_da_buf_done(fbp);
    -			return 0;
    -		}
    -		/*
    -		 * Read the data block in.
    -		 */
    -		if (unlikely(
    -		    error = xfs_da_read_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, dbno),
    -				-1, &dbp, XFS_DATA_FORK))) {
    -			if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL)
    -				xfs_da_buf_done(fbp);
    -			return error;
    -		}
    -		data = dbp->data;
    -		logfree = 0;
    -	}
    -	ASSERT(be16_to_cpu(data->hdr.bestfree[0].length) >= length);
    -	/*
    -	 * Point to the existing unused space.
    -	 */
    -	dup = (xfs_dir2_data_unused_t *)
    -	      ((char *)data + be16_to_cpu(data->hdr.bestfree[0].offset));
    -	needscan = needlog = 0;
    -	/*
    -	 * Mark the first part of the unused space, inuse for us.
    -	 */
    -	xfs_dir2_data_use_free(tp, dbp, dup,
    -		(xfs_dir2_data_aoff_t)((char *)dup - (char *)data), length,
    -		&needlog, &needscan);
    -	/*
    -	 * Fill in the new entry and log it.
    -	 */
    -	dep = (xfs_dir2_data_entry_t *)dup;
    -	INT_SET(dep->inumber, ARCH_CONVERT, args->inumber);
    -	dep->namelen = args->namelen;
    -	memcpy(dep->name, args->name, dep->namelen);
    -	tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
    -	*tagp = cpu_to_be16((char *)dep - (char *)data);
    -	xfs_dir2_data_log_entry(tp, dbp, dep);
    -	/*
    -	 * Rescan the block for bestfree if needed.
    -	 */
    -	if (needscan)
    -		xfs_dir2_data_freescan(mp, data, &needlog, NULL);
    -	/*
    -	 * Log the data block header if needed.
    -	 */
    -	if (needlog)
    -		xfs_dir2_data_log_header(tp, dbp);
    -	/*
    -	 * If the freespace entry is now wrong, update it.
    -	 */
    -	if (be16_to_cpu(free->bests[findex]) != be16_to_cpu(data->hdr.bestfree[0].length)) {
    -		free->bests[findex] = data->hdr.bestfree[0].length;
    -		logfree = 1;
    -	}
    -	/*
    -	 * Log the freespace entry if needed.
    -	 */
    -	if (logfree)
    -		xfs_dir2_free_log_bests(tp, fbp, findex, findex);
    -	/*
    -	 * If the caller didn't hand us the freespace block, drop it.
    -	 */
    -	if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL)
    -		xfs_da_buf_done(fbp);
    -	/*
    -	 * Return the data block and offset in args, then drop the data block.
    -	 */
    -	args->blkno = (xfs_dablk_t)dbno;
    -	args->index = be16_to_cpu(*tagp);
    -	xfs_da_buf_done(dbp);
    -	return 0;
    -}
    -
    -/*
    - * Lookup an entry in a node-format directory.
    - * All the real work happens in xfs_da_node_lookup_int.
    - * The only real output is the inode number of the entry.
    - */
    -int						/* error */
    -xfs_dir2_node_lookup(
    -	xfs_da_args_t	*args)			/* operation arguments */
    -{
    -	int		error;			/* error return value */
    -	int		i;			/* btree level */
    -	int		rval;			/* operation return value */
    -	xfs_da_state_t	*state;			/* btree cursor */
    -
    -	xfs_dir2_trace_args("node_lookup", args);
    -	/*
    -	 * Allocate and initialize the btree cursor.
    -	 */
    -	state = xfs_da_state_alloc();
    -	state->args = args;
    -	state->mp = args->dp->i_mount;
    -	state->blocksize = state->mp->m_dirblksize;
    -	state->node_ents = state->mp->m_dir_node_ents;
    -	/*
    -	 * Fill in the path to the entry in the cursor.
    -	 */
    -	error = xfs_da_node_lookup_int(state, &rval);
    -	if (error)
    -		rval = error;
    -	/*
    -	 * Release the btree blocks and leaf block.
    -	 */
    -	for (i = 0; i < state->path.active; i++) {
    -		xfs_da_brelse(args->trans, state->path.blk[i].bp);
    -		state->path.blk[i].bp = NULL;
    -	}
    -	/*
    -	 * Release the data block if we have it.
    -	 */
    -	if (state->extravalid && state->extrablk.bp) {
    -		xfs_da_brelse(args->trans, state->extrablk.bp);
    -		state->extrablk.bp = NULL;
    -	}
    -	xfs_da_state_free(state);
    -	return rval;
    -}
    -
    -/*
    - * Remove an entry from a node-format directory.
    - */
    -int						/* error */
    -xfs_dir2_node_removename(
    -	xfs_da_args_t		*args)		/* operation arguments */
    -{
    -	xfs_da_state_blk_t	*blk;		/* leaf block */
    -	int			error;		/* error return value */
    -	int			rval;		/* operation return value */
    -	xfs_da_state_t		*state;		/* btree cursor */
    -
    -	xfs_dir2_trace_args("node_removename", args);
    -	/*
    -	 * Allocate and initialize the btree cursor.
    -	 */
    -	state = xfs_da_state_alloc();
    -	state->args = args;
    -	state->mp = args->dp->i_mount;
    -	state->blocksize = state->mp->m_dirblksize;
    -	state->node_ents = state->mp->m_dir_node_ents;
    -	/*
    -	 * Look up the entry we're deleting, set up the cursor.
    -	 */
    -	error = xfs_da_node_lookup_int(state, &rval);
    -	if (error) {
    -		rval = error;
    -	}
    -	/*
    -	 * Didn't find it, upper layer screwed up.
    -	 */
    -	if (rval != EEXIST) {
    -		xfs_da_state_free(state);
    -		return rval;
    -	}
    -	blk = &state->path.blk[state->path.active - 1];
    -	ASSERT(blk->magic == XFS_DIR2_LEAFN_MAGIC);
    -	ASSERT(state->extravalid);
    -	/*
    -	 * Remove the leaf and data entries.
    -	 * Extrablk refers to the data block.
    -	 */
    -	error = xfs_dir2_leafn_remove(args, blk->bp, blk->index,
    -		&state->extrablk, &rval);
    -	if (error) {
    -		return error;
    -	}
    -	/*
    -	 * Fix the hash values up the btree.
    -	 */
    -	xfs_da_fixhashpath(state, &state->path);
    -	/*
    -	 * If we need to join leaf blocks, do it.
    -	 */
    -	if (rval && state->path.active > 1)
    -		error = xfs_da_join(state);
    -	/*
    -	 * If no errors so far, try conversion to leaf format.
    -	 */
    -	if (!error)
    -		error = xfs_dir2_node_to_leaf(state);
    -	xfs_da_state_free(state);
    -	return error;
    -}
    -
    -/*
    - * Replace an entry's inode number in a node-format directory.
    - */
    -int						/* error */
    -xfs_dir2_node_replace(
    -	xfs_da_args_t		*args)		/* operation arguments */
    -{
    -	xfs_da_state_blk_t	*blk;		/* leaf block */
    -	xfs_dir2_data_t		*data;		/* data block structure */
    -	xfs_dir2_data_entry_t	*dep;		/* data entry changed */
    -	int			error;		/* error return value */
    -	int			i;		/* btree level */
    -	xfs_ino_t		inum;		/* new inode number */
    -	xfs_dir2_leaf_t		*leaf;		/* leaf structure */
    -	xfs_dir2_leaf_entry_t	*lep;		/* leaf entry being changed */
    -	int			rval;		/* internal return value */
    -	xfs_da_state_t		*state;		/* btree cursor */
    -
    -	xfs_dir2_trace_args("node_replace", args);
    -	/*
    -	 * Allocate and initialize the btree cursor.
    -	 */
    -	state = xfs_da_state_alloc();
    -	state->args = args;
    -	state->mp = args->dp->i_mount;
    -	state->blocksize = state->mp->m_dirblksize;
    -	state->node_ents = state->mp->m_dir_node_ents;
    -	inum = args->inumber;
    -	/*
    -	 * Lookup the entry to change in the btree.
    -	 */
    -	error = xfs_da_node_lookup_int(state, &rval);
    -	if (error) {
    -		rval = error;
    -	}
    -	/*
    -	 * It should be found, since the vnodeops layer has looked it up
    -	 * and locked it.  But paranoia is good.
    -	 */
    -	if (rval == EEXIST) {
    -		/*
    -		 * Find the leaf entry.
    -		 */
    -		blk = &state->path.blk[state->path.active - 1];
    -		ASSERT(blk->magic == XFS_DIR2_LEAFN_MAGIC);
    -		leaf = blk->bp->data;
    -		lep = &leaf->ents[blk->index];
    -		ASSERT(state->extravalid);
    -		/*
    -		 * Point to the data entry.
    -		 */
    -		data = state->extrablk.bp->data;
    -		ASSERT(be32_to_cpu(data->hdr.magic) == XFS_DIR2_DATA_MAGIC);
    -		dep = (xfs_dir2_data_entry_t *)
    -		      ((char *)data +
    -		       XFS_DIR2_DATAPTR_TO_OFF(state->mp, be32_to_cpu(lep->address)));
    -		ASSERT(inum != INT_GET(dep->inumber, ARCH_CONVERT));
    -		/*
    -		 * Fill in the new inode number and log the entry.
    -		 */
    -		INT_SET(dep->inumber, ARCH_CONVERT, inum);
    -		xfs_dir2_data_log_entry(args->trans, state->extrablk.bp, dep);
    -		rval = 0;
    -	}
    -	/*
    -	 * Didn't find it, and we're holding a data block.  Drop it.
    -	 */
    -	else if (state->extravalid) {
    -		xfs_da_brelse(args->trans, state->extrablk.bp);
    -		state->extrablk.bp = NULL;
    -	}
    -	/*
    -	 * Release all the buffers in the cursor.
    -	 */
    -	for (i = 0; i < state->path.active; i++) {
    -		xfs_da_brelse(args->trans, state->path.blk[i].bp);
    -		state->path.blk[i].bp = NULL;
    -	}
    -	xfs_da_state_free(state);
    -	return rval;
    -}
    -
    -/*
    - * Trim off a trailing empty freespace block.
    - * Return (in rvalp) 1 if we did it, 0 if not.
    - */
    -int						/* error */
    -xfs_dir2_node_trim_free(
    -	xfs_da_args_t		*args,		/* operation arguments */
    -	xfs_fileoff_t		fo,		/* free block number */
    -	int			*rvalp)		/* out: did something */
    -{
    -	xfs_dabuf_t		*bp;		/* freespace buffer */
    -	xfs_inode_t		*dp;		/* incore directory inode */
    -	int			error;		/* error return code */
    -	xfs_dir2_free_t		*free;		/* freespace structure */
    -	xfs_mount_t		*mp;		/* filesystem mount point */
    -	xfs_trans_t		*tp;		/* transaction pointer */
    -
    -	dp = args->dp;
    -	mp = dp->i_mount;
    -	tp = args->trans;
    -	/*
    -	 * Read the freespace block.
    -	 */
    -	if (unlikely(error = xfs_da_read_buf(tp, dp, (xfs_dablk_t)fo, -2, &bp,
    -			XFS_DATA_FORK))) {
    -		return error;
    -	}
    -
    -	/*
    -	 * There can be holes in freespace.  If fo is a hole, there's
    -	 * nothing to do.
    -	 */
    -	if (bp == NULL) {
    -		return 0;
    -	}
    -	free = bp->data;
    -	ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);
    -	/*
    -	 * If there are used entries, there's nothing to do.
    -	 */
    -	if (be32_to_cpu(free->hdr.nused) > 0) {
    -		xfs_da_brelse(tp, bp);
    -		*rvalp = 0;
    -		return 0;
    -	}
    -	/*
    -	 * Blow the block away.
    -	 */
    -	if ((error =
    -	    xfs_dir2_shrink_inode(args, XFS_DIR2_DA_TO_DB(mp, (xfs_dablk_t)fo),
    -		    bp))) {
    -		/*
    -		 * Can't fail with ENOSPC since that only happens with no
    -		 * space reservation, when breaking up an extent into two
    -		 * pieces.  This is the last block of an extent.
    -		 */
    -		ASSERT(error != ENOSPC);
    -		xfs_da_brelse(tp, bp);
    -		return error;
    -	}
    -	/*
    -	 * Return that we succeeded.
    -	 */
    -	*rvalp = 1;
    -	return 0;
    -}
    diff --git a/sys/gnu/fs/xfs/xfs_dir2_node.h b/sys/gnu/fs/xfs/xfs_dir2_node.h
    deleted file mode 100644
    index c7c870ee785..00000000000
    --- a/sys/gnu/fs/xfs/xfs_dir2_node.h
    +++ /dev/null
    @@ -1,104 +0,0 @@
    -/*
    - * Copyright (c) 2000,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_DIR2_NODE_H__
    -#define	__XFS_DIR2_NODE_H__
    -
    -/*
    - * Directory version 2, btree node format structures
    - */
    -
    -struct uio;
    -struct xfs_dabuf;
    -struct xfs_da_args;
    -struct xfs_da_state;
    -struct xfs_da_state_blk;
    -struct xfs_inode;
    -struct xfs_trans;
    -
    -/*
    - * Offset of the freespace index.
    - */
    -#define	XFS_DIR2_FREE_SPACE	2
    -#define	XFS_DIR2_FREE_OFFSET	(XFS_DIR2_FREE_SPACE * XFS_DIR2_SPACE_SIZE)
    -#define	XFS_DIR2_FREE_FIRSTDB(mp)	\
    -	XFS_DIR2_BYTE_TO_DB(mp, XFS_DIR2_FREE_OFFSET)
    -
    -#define	XFS_DIR2_FREE_MAGIC	0x58443246	/* XD2F */
    -
    -typedef	struct xfs_dir2_free_hdr {
    -	__be32			magic;		/* XFS_DIR2_FREE_MAGIC */
    -	__be32			firstdb;	/* db of first entry */
    -	__be32			nvalid;		/* count of valid entries */
    -	__be32			nused;		/* count of used entries */
    -} xfs_dir2_free_hdr_t;
    -
    -typedef struct xfs_dir2_free {
    -	xfs_dir2_free_hdr_t	hdr;		/* block header */
    -	__be16			bests[1];	/* best free counts */
    -						/* unused entries are -1 */
    -} xfs_dir2_free_t;
    -
    -#define	XFS_DIR2_MAX_FREE_BESTS(mp)	\
    -	(((mp)->m_dirblksize - (uint)sizeof(xfs_dir2_free_hdr_t)) / \
    -	 (uint)sizeof(xfs_dir2_data_off_t))
    -
    -/*
    - * Convert data space db to the corresponding free db.
    - */
    -#define	XFS_DIR2_DB_TO_FDB(mp,db)	xfs_dir2_db_to_fdb(mp, db)
    -static inline xfs_dir2_db_t
    -xfs_dir2_db_to_fdb(struct xfs_mount *mp, xfs_dir2_db_t db)
    -{
    -	return (XFS_DIR2_FREE_FIRSTDB(mp) + (db) / XFS_DIR2_MAX_FREE_BESTS(mp));
    -}
    -
    -/*
    - * Convert data space db to the corresponding index in a free db.
    - */
    -#define	XFS_DIR2_DB_TO_FDINDEX(mp,db)	xfs_dir2_db_to_fdindex(mp, db)
    -static inline int
    -xfs_dir2_db_to_fdindex(struct xfs_mount *mp, xfs_dir2_db_t db)
    -{
    -	return ((db) % XFS_DIR2_MAX_FREE_BESTS(mp));
    -}
    -
    -extern void xfs_dir2_free_log_bests(struct xfs_trans *tp, struct xfs_dabuf *bp,
    -				    int first, int last);
    -extern int xfs_dir2_leaf_to_node(struct xfs_da_args *args,
    -				 struct xfs_dabuf *lbp);
    -extern xfs_dahash_t xfs_dir2_leafn_lasthash(struct xfs_dabuf *bp, int *count);
    -extern int xfs_dir2_leafn_lookup_int(struct xfs_dabuf *bp,
    -				     struct xfs_da_args *args, int *indexp,
    -				     struct xfs_da_state *state);
    -extern int xfs_dir2_leafn_order(struct xfs_dabuf *leaf1_bp,
    -				struct xfs_dabuf *leaf2_bp);
    -extern int xfs_dir2_leafn_split(struct xfs_da_state *state,
    -				struct xfs_da_state_blk *oldblk,
    -				struct xfs_da_state_blk *newblk);
    -extern int xfs_dir2_leafn_toosmall(struct xfs_da_state *state, int *action);
    -extern void xfs_dir2_leafn_unbalance(struct xfs_da_state *state,
    -				     struct xfs_da_state_blk *drop_blk,
    -				     struct xfs_da_state_blk *save_blk);
    -extern int xfs_dir2_node_addname(struct xfs_da_args *args);
    -extern int xfs_dir2_node_lookup(struct xfs_da_args *args);
    -extern int xfs_dir2_node_removename(struct xfs_da_args *args);
    -extern int xfs_dir2_node_replace(struct xfs_da_args *args);
    -extern int xfs_dir2_node_trim_free(struct xfs_da_args *args, xfs_fileoff_t fo,
    -				   int *rvalp);
    -
    -#endif	/* __XFS_DIR2_NODE_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_dir2_sf.c b/sys/gnu/fs/xfs/xfs_dir2_sf.c
    deleted file mode 100644
    index d98a41d1fe6..00000000000
    --- a/sys/gnu/fs/xfs/xfs_dir2_sf.c
    +++ /dev/null
    @@ -1,1296 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_da_btree.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_inode_item.h"
    -#include "xfs_dir_leaf.h"
    -#include "xfs_error.h"
    -#include "xfs_dir2_data.h"
    -#include "xfs_dir2_leaf.h"
    -#include "xfs_dir2_block.h"
    -#include "xfs_dir2_trace.h"
    -
    -/*
    - * Prototypes for internal functions.
    - */
    -static void xfs_dir2_sf_addname_easy(xfs_da_args_t *args,
    -				     xfs_dir2_sf_entry_t *sfep,
    -				     xfs_dir2_data_aoff_t offset,
    -				     int new_isize);
    -static void xfs_dir2_sf_addname_hard(xfs_da_args_t *args, int objchange,
    -				     int new_isize);
    -static int xfs_dir2_sf_addname_pick(xfs_da_args_t *args, int objchange,
    -				    xfs_dir2_sf_entry_t **sfepp,
    -				    xfs_dir2_data_aoff_t *offsetp);
    -#ifdef DEBUG
    -static void xfs_dir2_sf_check(xfs_da_args_t *args);
    -#else
    -#define	xfs_dir2_sf_check(args)
    -#endif /* DEBUG */
    -#if XFS_BIG_INUMS
    -static void xfs_dir2_sf_toino4(xfs_da_args_t *args);
    -static void xfs_dir2_sf_toino8(xfs_da_args_t *args);
    -#endif /* XFS_BIG_INUMS */
    -
    -/*
    - * Given a block directory (dp/block), calculate its size as a shortform (sf)
    - * directory and a header for the sf directory, if it will fit it the
    - * space currently present in the inode.  If it won't fit, the output
    - * size is too big (but not accurate).
    - */
    -int						/* size for sf form */
    -xfs_dir2_block_sfsize(
    -	xfs_inode_t		*dp,		/* incore inode pointer */
    -	xfs_dir2_block_t	*block,		/* block directory data */
    -	xfs_dir2_sf_hdr_t	*sfhp)		/* output: header for sf form */
    -{
    -	xfs_dir2_dataptr_t	addr;		/* data entry address */
    -	xfs_dir2_leaf_entry_t	*blp;		/* leaf area of the block */
    -	xfs_dir2_block_tail_t	*btp;		/* tail area of the block */
    -	int			count;		/* shortform entry count */
    -	xfs_dir2_data_entry_t	*dep;		/* data entry in the block */
    -	int			i;		/* block entry index */
    -	int			i8count;	/* count of big-inode entries */
    -	int			isdot;		/* entry is "." */
    -	int			isdotdot;	/* entry is ".." */
    -	xfs_mount_t		*mp;		/* mount structure pointer */
    -	int			namelen;	/* total name bytes */
    -	xfs_ino_t		parent = 0;	/* parent inode number */
    -	int			size=0;		/* total computed size */
    -
    -	mp = dp->i_mount;
    -
    -	count = i8count = namelen = 0;
    -	btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
    -	blp = XFS_DIR2_BLOCK_LEAF_P(btp);
    -
    -	/*
    -	 * Iterate over the block's data entries by using the leaf pointers.
    -	 */
    -	for (i = 0; i < be32_to_cpu(btp->count); i++) {
    -		if ((addr = be32_to_cpu(blp[i].address)) == XFS_DIR2_NULL_DATAPTR)
    -			continue;
    -		/*
    -		 * Calculate the pointer to the entry at hand.
    -		 */
    -		dep = (xfs_dir2_data_entry_t *)
    -		      ((char *)block + XFS_DIR2_DATAPTR_TO_OFF(mp, addr));
    -		/*
    -		 * Detect . and .., so we can special-case them.
    -		 * . is not included in sf directories.
    -		 * .. is included by just the parent inode number.
    -		 */
    -		isdot = dep->namelen == 1 && dep->name[0] == '.';
    -		isdotdot =
    -			dep->namelen == 2 &&
    -			dep->name[0] == '.' && dep->name[1] == '.';
    -#if XFS_BIG_INUMS
    -		if (!isdot)
    -			i8count += INT_GET(dep->inumber, ARCH_CONVERT) > XFS_DIR2_MAX_SHORT_INUM;
    -#endif
    -		if (!isdot && !isdotdot) {
    -			count++;
    -			namelen += dep->namelen;
    -		} else if (isdotdot)
    -			parent = INT_GET(dep->inumber, ARCH_CONVERT);
    -		/*
    -		 * Calculate the new size, see if we should give up yet.
    -		 */
    -		size = XFS_DIR2_SF_HDR_SIZE(i8count) +		/* header */
    -		       count +					/* namelen */
    -		       count * (uint)sizeof(xfs_dir2_sf_off_t) + /* offset */
    -		       namelen +				/* name */
    -		       (i8count ?				/* inumber */
    -				(uint)sizeof(xfs_dir2_ino8_t) * count :
    -				(uint)sizeof(xfs_dir2_ino4_t) * count);
    -		if (size > XFS_IFORK_DSIZE(dp))
    -			return size;		/* size value is a failure */
    -	}
    -	/*
    -	 * Create the output header, if it worked.
    -	 */
    -	sfhp->count = count;
    -	sfhp->i8count = i8count;
    -	XFS_DIR2_SF_PUT_INUMBER((xfs_dir2_sf_t *)sfhp, &parent, &sfhp->parent);
    -	return size;
    -}
    -
    -/*
    - * Convert a block format directory to shortform.
    - * Caller has already checked that it will fit, and built us a header.
    - */
    -int						/* error */
    -xfs_dir2_block_to_sf(
    -	xfs_da_args_t		*args,		/* operation arguments */
    -	xfs_dabuf_t		*bp,		/* block buffer */
    -	int			size,		/* shortform directory size */
    -	xfs_dir2_sf_hdr_t	*sfhp)		/* shortform directory hdr */
    -{
    -	xfs_dir2_block_t	*block;		/* block structure */
    -	xfs_dir2_block_tail_t	*btp;		/* block tail pointer */
    -	xfs_dir2_data_entry_t	*dep;		/* data entry pointer */
    -	xfs_inode_t		*dp;		/* incore directory inode */
    -	xfs_dir2_data_unused_t	*dup;		/* unused data pointer */
    -	char			*endptr;	/* end of data entries */
    -	int			error;		/* error return value */
    -	int			logflags;	/* inode logging flags */
    -	xfs_mount_t		*mp;		/* filesystem mount point */
    -	char			*ptr;		/* current data pointer */
    -	xfs_dir2_sf_entry_t	*sfep;		/* shortform entry */
    -	xfs_dir2_sf_t		*sfp;		/* shortform structure */
    -	xfs_ino_t               temp;
    -
    -	xfs_dir2_trace_args_sb("block_to_sf", args, size, bp);
    -	dp = args->dp;
    -	mp = dp->i_mount;
    -
    -	/*
    -	 * Make a copy of the block data, so we can shrink the inode
    -	 * and add local data.
    -	 */
    -	block = kmem_alloc(mp->m_dirblksize, KM_SLEEP);
    -	memcpy(block, bp->data, mp->m_dirblksize);
    -	logflags = XFS_ILOG_CORE;
    -	if ((error = xfs_dir2_shrink_inode(args, mp->m_dirdatablk, bp))) {
    -		ASSERT(error != ENOSPC);
    -		goto out;
    -	}
    -	/*
    -	 * The buffer is now unconditionally gone, whether
    -	 * xfs_dir2_shrink_inode worked or not.
    -	 *
    -	 * Convert the inode to local format.
    -	 */
    -	dp->i_df.if_flags &= ~XFS_IFEXTENTS;
    -	dp->i_df.if_flags |= XFS_IFINLINE;
    -	dp->i_d.di_format = XFS_DINODE_FMT_LOCAL;
    -	ASSERT(dp->i_df.if_bytes == 0);
    -	xfs_idata_realloc(dp, size, XFS_DATA_FORK);
    -	logflags |= XFS_ILOG_DDATA;
    -	/*
    -	 * Copy the header into the newly allocate local space.
    -	 */
    -	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
    -	memcpy(sfp, sfhp, XFS_DIR2_SF_HDR_SIZE(sfhp->i8count));
    -	dp->i_d.di_size = size;
    -	/*
    -	 * Set up to loop over the block's entries.
    -	 */
    -	btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
    -	ptr = (char *)block->u;
    -	endptr = (char *)XFS_DIR2_BLOCK_LEAF_P(btp);
    -	sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
    -	/*
    -	 * Loop over the active and unused entries.
    -	 * Stop when we reach the leaf/tail portion of the block.
    -	 */
    -	while (ptr < endptr) {
    -		/*
    -		 * If it's unused, just skip over it.
    -		 */
    -		dup = (xfs_dir2_data_unused_t *)ptr;
    -		if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
    -			ptr += be16_to_cpu(dup->length);
    -			continue;
    -		}
    -		dep = (xfs_dir2_data_entry_t *)ptr;
    -		/*
    -		 * Skip .
    -		 */
    -		if (dep->namelen == 1 && dep->name[0] == '.')
    -			ASSERT(INT_GET(dep->inumber, ARCH_CONVERT) == dp->i_ino);
    -		/*
    -		 * Skip .., but make sure the inode number is right.
    -		 */
    -		else if (dep->namelen == 2 &&
    -			 dep->name[0] == '.' && dep->name[1] == '.')
    -			ASSERT(INT_GET(dep->inumber, ARCH_CONVERT) ==
    -			       XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent));
    -		/*
    -		 * Normal entry, copy it into shortform.
    -		 */
    -		else {
    -			sfep->namelen = dep->namelen;
    -			XFS_DIR2_SF_PUT_OFFSET(sfep,
    -				(xfs_dir2_data_aoff_t)
    -				((char *)dep - (char *)block));
    -			memcpy(sfep->name, dep->name, dep->namelen);
    -			temp=INT_GET(dep->inumber, ARCH_CONVERT);
    -			XFS_DIR2_SF_PUT_INUMBER(sfp, &temp,
    -				XFS_DIR2_SF_INUMBERP(sfep));
    -			sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep);
    -		}
    -		ptr += XFS_DIR2_DATA_ENTSIZE(dep->namelen);
    -	}
    -	ASSERT((char *)sfep - (char *)sfp == size);
    -	xfs_dir2_sf_check(args);
    -out:
    -	xfs_trans_log_inode(args->trans, dp, logflags);
    -	kmem_free(block, mp->m_dirblksize);
    -	return error;
    -}
    -
    -/*
    - * Add a name to a shortform directory.
    - * There are two algorithms, "easy" and "hard" which we decide on
    - * before changing anything.
    - * Convert to block form if necessary, if the new entry won't fit.
    - */
    -int						/* error */
    -xfs_dir2_sf_addname(
    -	xfs_da_args_t		*args)		/* operation arguments */
    -{
    -	int			add_entsize;	/* size of the new entry */
    -	xfs_inode_t		*dp;		/* incore directory inode */
    -	int			error;		/* error return value */
    -	int			incr_isize;	/* total change in size */
    -	int			new_isize;	/* di_size after adding name */
    -	int			objchange;	/* changing to 8-byte inodes */
    -	xfs_dir2_data_aoff_t	offset = 0;	/* offset for new entry */
    -	int			old_isize;	/* di_size before adding name */
    -	int			pick;		/* which algorithm to use */
    -	xfs_dir2_sf_t		*sfp;		/* shortform structure */
    -	xfs_dir2_sf_entry_t	*sfep = NULL;	/* shortform entry */
    -
    -	xfs_dir2_trace_args("sf_addname", args);
    -	ASSERT(xfs_dir2_sf_lookup(args) == ENOENT);
    -	dp = args->dp;
    -	ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
    -	/*
    -	 * Make sure the shortform value has some of its header.
    -	 */
    -	if (dp->i_d.di_size < offsetof(xfs_dir2_sf_hdr_t, parent)) {
    -		ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount));
    -		return XFS_ERROR(EIO);
    -	}
    -	ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
    -	ASSERT(dp->i_df.if_u1.if_data != NULL);
    -	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
    -	ASSERT(dp->i_d.di_size >= XFS_DIR2_SF_HDR_SIZE(sfp->hdr.i8count));
    -	/*
    -	 * Compute entry (and change in) size.
    -	 */
    -	add_entsize = XFS_DIR2_SF_ENTSIZE_BYNAME(sfp, args->namelen);
    -	incr_isize = add_entsize;
    -	objchange = 0;
    -#if XFS_BIG_INUMS
    -	/*
    -	 * Do we have to change to 8 byte inodes?
    -	 */
    -	if (args->inumber > XFS_DIR2_MAX_SHORT_INUM && sfp->hdr.i8count == 0) {
    -		/*
    -		 * Yes, adjust the entry size and the total size.
    -		 */
    -		add_entsize +=
    -			(uint)sizeof(xfs_dir2_ino8_t) -
    -			(uint)sizeof(xfs_dir2_ino4_t);
    -		incr_isize +=
    -			(sfp->hdr.count + 2) *
    -			((uint)sizeof(xfs_dir2_ino8_t) -
    -			 (uint)sizeof(xfs_dir2_ino4_t));
    -		objchange = 1;
    -	}
    -#endif
    -	old_isize = (int)dp->i_d.di_size;
    -	new_isize = old_isize + incr_isize;
    -	/*
    -	 * Won't fit as shortform any more (due to size),
    -	 * or the pick routine says it won't (due to offset values).
    -	 */
    -	if (new_isize > XFS_IFORK_DSIZE(dp) ||
    -	    (pick =
    -	     xfs_dir2_sf_addname_pick(args, objchange, &sfep, &offset)) == 0) {
    -		/*
    -		 * Just checking or no space reservation, it doesn't fit.
    -		 */
    -		if (args->justcheck || args->total == 0)
    -			return XFS_ERROR(ENOSPC);
    -		/*
    -		 * Convert to block form then add the name.
    -		 */
    -		error = xfs_dir2_sf_to_block(args);
    -		if (error)
    -			return error;
    -		return xfs_dir2_block_addname(args);
    -	}
    -	/*
    -	 * Just checking, it fits.
    -	 */
    -	if (args->justcheck)
    -		return 0;
    -	/*
    -	 * Do it the easy way - just add it at the end.
    -	 */
    -	if (pick == 1)
    -		xfs_dir2_sf_addname_easy(args, sfep, offset, new_isize);
    -	/*
    -	 * Do it the hard way - look for a place to insert the new entry.
    -	 * Convert to 8 byte inode numbers first if necessary.
    -	 */
    -	else {
    -		ASSERT(pick == 2);
    -#if XFS_BIG_INUMS
    -		if (objchange)
    -			xfs_dir2_sf_toino8(args);
    -#endif
    -		xfs_dir2_sf_addname_hard(args, objchange, new_isize);
    -	}
    -	xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA);
    -	return 0;
    -}
    -
    -/*
    - * Add the new entry the "easy" way.
    - * This is copying the old directory and adding the new entry at the end.
    - * Since it's sorted by "offset" we need room after the last offset
    - * that's already there, and then room to convert to a block directory.
    - * This is already checked by the pick routine.
    - */
    -static void
    -xfs_dir2_sf_addname_easy(
    -	xfs_da_args_t		*args,		/* operation arguments */
    -	xfs_dir2_sf_entry_t	*sfep,		/* pointer to new entry */
    -	xfs_dir2_data_aoff_t	offset,		/* offset to use for new ent */
    -	int			new_isize)	/* new directory size */
    -{
    -	int			byteoff;	/* byte offset in sf dir */
    -	xfs_inode_t		*dp;		/* incore directory inode */
    -	xfs_dir2_sf_t		*sfp;		/* shortform structure */
    -
    -	dp = args->dp;
    -
    -	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
    -	byteoff = (int)((char *)sfep - (char *)sfp);
    -	/*
    -	 * Grow the in-inode space.
    -	 */
    -	xfs_idata_realloc(dp, XFS_DIR2_SF_ENTSIZE_BYNAME(sfp, args->namelen),
    -		XFS_DATA_FORK);
    -	/*
    -	 * Need to set up again due to realloc of the inode data.
    -	 */
    -	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
    -	sfep = (xfs_dir2_sf_entry_t *)((char *)sfp + byteoff);
    -	/*
    -	 * Fill in the new entry.
    -	 */
    -	sfep->namelen = args->namelen;
    -	XFS_DIR2_SF_PUT_OFFSET(sfep, offset);
    -	memcpy(sfep->name, args->name, sfep->namelen);
    -	XFS_DIR2_SF_PUT_INUMBER(sfp, &args->inumber,
    -		XFS_DIR2_SF_INUMBERP(sfep));
    -	/*
    -	 * Update the header and inode.
    -	 */
    -	sfp->hdr.count++;
    -#if XFS_BIG_INUMS
    -	if (args->inumber > XFS_DIR2_MAX_SHORT_INUM)
    -		sfp->hdr.i8count++;
    -#endif
    -	dp->i_d.di_size = new_isize;
    -	xfs_dir2_sf_check(args);
    -}
    -
    -/*
    - * Add the new entry the "hard" way.
    - * The caller has already converted to 8 byte inode numbers if necessary,
    - * in which case we need to leave the i8count at 1.
    - * Find a hole that the new entry will fit into, and copy
    - * the first part of the entries, the new entry, and the last part of
    - * the entries.
    - */
    -/* ARGSUSED */
    -static void
    -xfs_dir2_sf_addname_hard(
    -	xfs_da_args_t		*args,		/* operation arguments */
    -	int			objchange,	/* changing inode number size */
    -	int			new_isize)	/* new directory size */
    -{
    -	int			add_datasize;	/* data size need for new ent */
    -	char			*buf;		/* buffer for old */
    -	xfs_inode_t		*dp;		/* incore directory inode */
    -	int			eof;		/* reached end of old dir */
    -	int			nbytes;		/* temp for byte copies */
    -	xfs_dir2_data_aoff_t	new_offset;	/* next offset value */
    -	xfs_dir2_data_aoff_t	offset;		/* current offset value */
    -	int			old_isize;	/* previous di_size */
    -	xfs_dir2_sf_entry_t	*oldsfep;	/* entry in original dir */
    -	xfs_dir2_sf_t		*oldsfp;	/* original shortform dir */
    -	xfs_dir2_sf_entry_t	*sfep;		/* entry in new dir */
    -	xfs_dir2_sf_t		*sfp;		/* new shortform dir */
    -
    -	/*
    -	 * Copy the old directory to the stack buffer.
    -	 */
    -	dp = args->dp;
    -
    -	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
    -	old_isize = (int)dp->i_d.di_size;
    -	buf = kmem_alloc(old_isize, KM_SLEEP);
    -	oldsfp = (xfs_dir2_sf_t *)buf;
    -	memcpy(oldsfp, sfp, old_isize);
    -	/*
    -	 * Loop over the old directory finding the place we're going
    -	 * to insert the new entry.
    -	 * If it's going to end up at the end then oldsfep will point there.
    -	 */
    -	for (offset = XFS_DIR2_DATA_FIRST_OFFSET,
    -	      oldsfep = XFS_DIR2_SF_FIRSTENTRY(oldsfp),
    -	      add_datasize = XFS_DIR2_DATA_ENTSIZE(args->namelen),
    -	      eof = (char *)oldsfep == &buf[old_isize];
    -	     !eof;
    -	     offset = new_offset + XFS_DIR2_DATA_ENTSIZE(oldsfep->namelen),
    -	      oldsfep = XFS_DIR2_SF_NEXTENTRY(oldsfp, oldsfep),
    -	      eof = (char *)oldsfep == &buf[old_isize]) {
    -		new_offset = XFS_DIR2_SF_GET_OFFSET(oldsfep);
    -		if (offset + add_datasize <= new_offset)
    -			break;
    -	}
    -	/*
    -	 * Get rid of the old directory, then allocate space for
    -	 * the new one.  We do this so xfs_idata_realloc won't copy
    -	 * the data.
    -	 */
    -	xfs_idata_realloc(dp, -old_isize, XFS_DATA_FORK);
    -	xfs_idata_realloc(dp, new_isize, XFS_DATA_FORK);
    -	/*
    -	 * Reset the pointer since the buffer was reallocated.
    -	 */
    -	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
    -	/*
    -	 * Copy the first part of the directory, including the header.
    -	 */
    -	nbytes = (int)((char *)oldsfep - (char *)oldsfp);
    -	memcpy(sfp, oldsfp, nbytes);
    -	sfep = (xfs_dir2_sf_entry_t *)((char *)sfp + nbytes);
    -	/*
    -	 * Fill in the new entry, and update the header counts.
    -	 */
    -	sfep->namelen = args->namelen;
    -	XFS_DIR2_SF_PUT_OFFSET(sfep, offset);
    -	memcpy(sfep->name, args->name, sfep->namelen);
    -	XFS_DIR2_SF_PUT_INUMBER(sfp, &args->inumber,
    -		XFS_DIR2_SF_INUMBERP(sfep));
    -	sfp->hdr.count++;
    -#if XFS_BIG_INUMS
    -	if (args->inumber > XFS_DIR2_MAX_SHORT_INUM && !objchange)
    -		sfp->hdr.i8count++;
    -#endif
    -	/*
    -	 * If there's more left to copy, do that.
    -	 */
    -	if (!eof) {
    -		sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep);
    -		memcpy(sfep, oldsfep, old_isize - nbytes);
    -	}
    -	kmem_free(buf, old_isize);
    -	dp->i_d.di_size = new_isize;
    -	xfs_dir2_sf_check(args);
    -}
    -
    -/*
    - * Decide if the new entry will fit at all.
    - * If it will fit, pick between adding the new entry to the end (easy)
    - * or somewhere else (hard).
    - * Return 0 (won't fit), 1 (easy), 2 (hard).
    - */
    -/*ARGSUSED*/
    -static int					/* pick result */
    -xfs_dir2_sf_addname_pick(
    -	xfs_da_args_t		*args,		/* operation arguments */
    -	int			objchange,	/* inode # size changes */
    -	xfs_dir2_sf_entry_t	**sfepp,	/* out(1): new entry ptr */
    -	xfs_dir2_data_aoff_t	*offsetp)	/* out(1): new offset */
    -{
    -	xfs_inode_t		*dp;		/* incore directory inode */
    -	int			holefit;	/* found hole it will fit in */
    -	int			i;		/* entry number */
    -	xfs_mount_t		*mp;		/* filesystem mount point */
    -	xfs_dir2_data_aoff_t	offset;		/* data block offset */
    -	xfs_dir2_sf_entry_t	*sfep;		/* shortform entry */
    -	xfs_dir2_sf_t		*sfp;		/* shortform structure */
    -	int			size;		/* entry's data size */
    -	int			used;		/* data bytes used */
    -
    -	dp = args->dp;
    -	mp = dp->i_mount;
    -
    -	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
    -	size = XFS_DIR2_DATA_ENTSIZE(args->namelen);
    -	offset = XFS_DIR2_DATA_FIRST_OFFSET;
    -	sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
    -	holefit = 0;
    -	/*
    -	 * Loop over sf entries.
    -	 * Keep track of data offset and whether we've seen a place
    -	 * to insert the new entry.
    -	 */
    -	for (i = 0; i < sfp->hdr.count; i++) {
    -		if (!holefit)
    -			holefit = offset + size <= XFS_DIR2_SF_GET_OFFSET(sfep);
    -		offset = XFS_DIR2_SF_GET_OFFSET(sfep) +
    -			 XFS_DIR2_DATA_ENTSIZE(sfep->namelen);
    -		sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep);
    -	}
    -	/*
    -	 * Calculate data bytes used excluding the new entry, if this
    -	 * was a data block (block form directory).
    -	 */
    -	used = offset +
    -	       (sfp->hdr.count + 3) * (uint)sizeof(xfs_dir2_leaf_entry_t) +
    -	       (uint)sizeof(xfs_dir2_block_tail_t);
    -	/*
    -	 * If it won't fit in a block form then we can't insert it,
    -	 * we'll go back, convert to block, then try the insert and convert
    -	 * to leaf.
    -	 */
    -	if (used + (holefit ? 0 : size) > mp->m_dirblksize)
    -		return 0;
    -	/*
    -	 * If changing the inode number size, do it the hard way.
    -	 */
    -#if XFS_BIG_INUMS
    -	if (objchange) {
    -		return 2;
    -	}
    -#else
    -	ASSERT(objchange == 0);
    -#endif
    -	/*
    -	 * If it won't fit at the end then do it the hard way (use the hole).
    -	 */
    -	if (used + size > mp->m_dirblksize)
    -		return 2;
    -	/*
    -	 * Do it the easy way.
    -	 */
    -	*sfepp = sfep;
    -	*offsetp = offset;
    -	return 1;
    -}
    -
    -#ifdef DEBUG
    -/*
    - * Check consistency of shortform directory, assert if bad.
    - */
    -static void
    -xfs_dir2_sf_check(
    -	xfs_da_args_t		*args)		/* operation arguments */
    -{
    -	xfs_inode_t		*dp;		/* incore directory inode */
    -	int			i;		/* entry number */
    -	int			i8count;	/* number of big inode#s */
    -	xfs_ino_t		ino;		/* entry inode number */
    -	int			offset;		/* data offset */
    -	xfs_dir2_sf_entry_t	*sfep;		/* shortform dir entry */
    -	xfs_dir2_sf_t		*sfp;		/* shortform structure */
    -
    -	dp = args->dp;
    -
    -	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
    -	offset = XFS_DIR2_DATA_FIRST_OFFSET;
    -	ino = XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent);
    -	i8count = ino > XFS_DIR2_MAX_SHORT_INUM;
    -
    -	for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
    -	     i < sfp->hdr.count;
    -	     i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep)) {
    -		ASSERT(XFS_DIR2_SF_GET_OFFSET(sfep) >= offset);
    -		ino = XFS_DIR2_SF_GET_INUMBER(sfp, XFS_DIR2_SF_INUMBERP(sfep));
    -		i8count += ino > XFS_DIR2_MAX_SHORT_INUM;
    -		offset =
    -			XFS_DIR2_SF_GET_OFFSET(sfep) +
    -			XFS_DIR2_DATA_ENTSIZE(sfep->namelen);
    -	}
    -	ASSERT(i8count == sfp->hdr.i8count);
    -	ASSERT(XFS_BIG_INUMS || i8count == 0);
    -	ASSERT((char *)sfep - (char *)sfp == dp->i_d.di_size);
    -	ASSERT(offset +
    -	       (sfp->hdr.count + 2) * (uint)sizeof(xfs_dir2_leaf_entry_t) +
    -	       (uint)sizeof(xfs_dir2_block_tail_t) <=
    -	       dp->i_mount->m_dirblksize);
    -}
    -#endif	/* DEBUG */
    -
    -/*
    - * Create a new (shortform) directory.
    - */
    -int					/* error, always 0 */
    -xfs_dir2_sf_create(
    -	xfs_da_args_t	*args,		/* operation arguments */
    -	xfs_ino_t	pino)		/* parent inode number */
    -{
    -	xfs_inode_t	*dp;		/* incore directory inode */
    -	int		i8count;	/* parent inode is an 8-byte number */
    -	xfs_dir2_sf_t	*sfp;		/* shortform structure */
    -	int		size;		/* directory size */
    -
    -	xfs_dir2_trace_args_i("sf_create", args, pino);
    -	dp = args->dp;
    -
    -	ASSERT(dp != NULL);
    -	ASSERT(dp->i_d.di_size == 0);
    -	/*
    -	 * If it's currently a zero-length extent file,
    -	 * convert it to local format.
    -	 */
    -	if (dp->i_d.di_format == XFS_DINODE_FMT_EXTENTS) {
    -		dp->i_df.if_flags &= ~XFS_IFEXTENTS;	/* just in case */
    -		dp->i_d.di_format = XFS_DINODE_FMT_LOCAL;
    -		xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE);
    -		dp->i_df.if_flags |= XFS_IFINLINE;
    -	}
    -	ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
    -	ASSERT(dp->i_df.if_bytes == 0);
    -	i8count = pino > XFS_DIR2_MAX_SHORT_INUM;
    -	size = XFS_DIR2_SF_HDR_SIZE(i8count);
    -	/*
    -	 * Make a buffer for the data.
    -	 */
    -	xfs_idata_realloc(dp, size, XFS_DATA_FORK);
    -	/*
    -	 * Fill in the header,
    -	 */
    -	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
    -	sfp->hdr.i8count = i8count;
    -	/*
    -	 * Now can put in the inode number, since i8count is set.
    -	 */
    -	XFS_DIR2_SF_PUT_INUMBER(sfp, &pino, &sfp->hdr.parent);
    -	sfp->hdr.count = 0;
    -	dp->i_d.di_size = size;
    -	xfs_dir2_sf_check(args);
    -	xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA);
    -	return 0;
    -}
    -
    -int						/* error */
    -xfs_dir2_sf_getdents(
    -	xfs_inode_t		*dp,		/* incore directory inode */
    -	uio_t			*uio,		/* caller's buffer control */
    -	int			*eofp,		/* eof reached? (out) */
    -	xfs_dirent_t		*dbp,		/* caller's buffer */
    -	xfs_dir2_put_t		put)		/* abi's formatting function */
    -{
    -	int			error;		/* error return value */
    -	int			i;		/* shortform entry number */
    -	xfs_mount_t		*mp;		/* filesystem mount point */
    -	xfs_dir2_dataptr_t	off;		/* current entry's offset */
    -	xfs_dir2_put_args_t	p;		/* arg package for put rtn */
    -	xfs_dir2_sf_entry_t	*sfep;		/* shortform directory entry */
    -	xfs_dir2_sf_t		*sfp;		/* shortform structure */
    -	xfs_off_t			dir_offset;
    -
    -	mp = dp->i_mount;
    -
    -	ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
    -	/*
    -	 * Give up if the directory is way too short.
    -	 */
    -	if (dp->i_d.di_size < offsetof(xfs_dir2_sf_hdr_t, parent)) {
    -		ASSERT(XFS_FORCED_SHUTDOWN(mp));
    -		return XFS_ERROR(EIO);
    -	}
    -
    -	dir_offset = uio->uio_offset;
    -
    -	ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
    -	ASSERT(dp->i_df.if_u1.if_data != NULL);
    -
    -	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
    -
    -	ASSERT(dp->i_d.di_size >= XFS_DIR2_SF_HDR_SIZE(sfp->hdr.i8count));
    -
    -	/*
    -	 * If the block number in the offset is out of range, we're done.
    -	 */
    -	if (XFS_DIR2_DATAPTR_TO_DB(mp, dir_offset) > mp->m_dirdatablk) {
    -		*eofp = 1;
    -		return 0;
    -	}
    -
    -	/*
    -	 * Set up putargs structure.
    -	 */
    -	p.dbp = dbp;
    -	p.put = put;
    -	p.uio = uio;
    -	/*
    -	 * Put . entry unless we're starting past it.
    -	 */
    -	if (dir_offset <=
    -		    XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
    -					       XFS_DIR2_DATA_DOT_OFFSET)) {
    -		p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, 0,
    -						XFS_DIR2_DATA_DOTDOT_OFFSET);
    -		p.ino = dp->i_ino;
    -#if XFS_BIG_INUMS
    -		p.ino += mp->m_inoadd;
    -#endif
    -		p.name = ".";
    -		p.namelen = 1;
    -
    -		error = p.put(&p);
    -
    -		if (!p.done) {
    -			uio->uio_offset =
    -				XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
    -						XFS_DIR2_DATA_DOT_OFFSET);
    -			return error;
    -		}
    -	}
    -
    -	/*
    -	 * Put .. entry unless we're starting past it.
    -	 */
    -	if (dir_offset <=
    -		    XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
    -					       XFS_DIR2_DATA_DOTDOT_OFFSET)) {
    -		p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
    -						XFS_DIR2_DATA_FIRST_OFFSET);
    -		p.ino = XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent);
    -#if XFS_BIG_INUMS
    -		p.ino += mp->m_inoadd;
    -#endif
    -		p.name = "..";
    -		p.namelen = 2;
    -
    -		error = p.put(&p);
    -
    -		if (!p.done) {
    -			uio->uio_offset =
    -				XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
    -					XFS_DIR2_DATA_DOTDOT_OFFSET);
    -			return error;
    -		}
    -	}
    -
    -	/*
    -	 * Loop while there are more entries and put'ing works.
    -	 */
    -	for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
    -		     i < sfp->hdr.count;
    -			     i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep)) {
    -
    -		off = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
    -				XFS_DIR2_SF_GET_OFFSET(sfep));
    -
    -		if (dir_offset > off)
    -			continue;
    -
    -		p.namelen = sfep->namelen;
    -
    -		p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
    -			XFS_DIR2_SF_GET_OFFSET(sfep) +
    -			XFS_DIR2_DATA_ENTSIZE(p.namelen));
    -
    -		p.ino = XFS_DIR2_SF_GET_INUMBER(sfp, XFS_DIR2_SF_INUMBERP(sfep));
    -#if XFS_BIG_INUMS
    -		p.ino += mp->m_inoadd;
    -#endif
    -		p.name = (char *)sfep->name;
    -
    -		error = p.put(&p);
    -
    -		if (!p.done) {
    -			uio->uio_offset = off;
    -			return error;
    -		}
    -	}
    -
    -	/*
    -	 * They all fit.
    -	 */
    -	*eofp = 1;
    -
    -	uio->uio_offset =
    -		XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk + 1, 0);
    -
    -	return 0;
    -}
    -
    -/*
    - * Lookup an entry in a shortform directory.
    - * Returns EEXIST if found, ENOENT if not found.
    - */
    -int						/* error */
    -xfs_dir2_sf_lookup(
    -	xfs_da_args_t		*args)		/* operation arguments */
    -{
    -	xfs_inode_t		*dp;		/* incore directory inode */
    -	int			i;		/* entry index */
    -	xfs_dir2_sf_entry_t	*sfep;		/* shortform directory entry */
    -	xfs_dir2_sf_t		*sfp;		/* shortform structure */
    -
    -	xfs_dir2_trace_args("sf_lookup", args);
    -	xfs_dir2_sf_check(args);
    -	dp = args->dp;
    -
    -	ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
    -	/*
    -	 * Bail out if the directory is way too short.
    -	 */
    -	if (dp->i_d.di_size < offsetof(xfs_dir2_sf_hdr_t, parent)) {
    -		ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount));
    -		return XFS_ERROR(EIO);
    -	}
    -	ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
    -	ASSERT(dp->i_df.if_u1.if_data != NULL);
    -	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
    -	ASSERT(dp->i_d.di_size >= XFS_DIR2_SF_HDR_SIZE(sfp->hdr.i8count));
    -	/*
    -	 * Special case for .
    -	 */
    -	if (args->namelen == 1 && args->name[0] == '.') {
    -		args->inumber = dp->i_ino;
    -		return XFS_ERROR(EEXIST);
    -	}
    -	/*
    -	 * Special case for ..
    -	 */
    -	if (args->namelen == 2 &&
    -	    args->name[0] == '.' && args->name[1] == '.') {
    -		args->inumber = XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent);
    -		return XFS_ERROR(EEXIST);
    -	}
    -	/*
    -	 * Loop over all the entries trying to match ours.
    -	 */
    -	for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
    -	     i < sfp->hdr.count;
    -	     i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep)) {
    -		if (sfep->namelen == args->namelen &&
    -		    sfep->name[0] == args->name[0] &&
    -		    memcmp(args->name, sfep->name, args->namelen) == 0) {
    -			args->inumber =
    -				XFS_DIR2_SF_GET_INUMBER(sfp,
    -					XFS_DIR2_SF_INUMBERP(sfep));
    -			return XFS_ERROR(EEXIST);
    -		}
    -	}
    -	/*
    -	 * Didn't find it.
    -	 */
    -	ASSERT(args->oknoent);
    -	return XFS_ERROR(ENOENT);
    -}
    -
    -/*
    - * Remove an entry from a shortform directory.
    - */
    -int						/* error */
    -xfs_dir2_sf_removename(
    -	xfs_da_args_t		*args)
    -{
    -	int			byteoff;	/* offset of removed entry */
    -	xfs_inode_t		*dp;		/* incore directory inode */
    -	int			entsize;	/* this entry's size */
    -	int			i;		/* shortform entry index */
    -	int			newsize;	/* new inode size */
    -	int			oldsize;	/* old inode size */
    -	xfs_dir2_sf_entry_t	*sfep;		/* shortform directory entry */
    -	xfs_dir2_sf_t		*sfp;		/* shortform structure */
    -
    -	xfs_dir2_trace_args("sf_removename", args);
    -	dp = args->dp;
    -
    -	ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
    -	oldsize = (int)dp->i_d.di_size;
    -	/*
    -	 * Bail out if the directory is way too short.
    -	 */
    -	if (oldsize < offsetof(xfs_dir2_sf_hdr_t, parent)) {
    -		ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount));
    -		return XFS_ERROR(EIO);
    -	}
    -	ASSERT(dp->i_df.if_bytes == oldsize);
    -	ASSERT(dp->i_df.if_u1.if_data != NULL);
    -	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
    -	ASSERT(oldsize >= XFS_DIR2_SF_HDR_SIZE(sfp->hdr.i8count));
    -	/*
    -	 * Loop over the old directory entries.
    -	 * Find the one we're deleting.
    -	 */
    -	for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
    -	     i < sfp->hdr.count;
    -	     i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep)) {
    -		if (sfep->namelen == args->namelen &&
    -		    sfep->name[0] == args->name[0] &&
    -		    memcmp(sfep->name, args->name, args->namelen) == 0) {
    -			ASSERT(XFS_DIR2_SF_GET_INUMBER(sfp,
    -					XFS_DIR2_SF_INUMBERP(sfep)) ==
    -				args->inumber);
    -			break;
    -		}
    -	}
    -	/*
    -	 * Didn't find it.
    -	 */
    -	if (i == sfp->hdr.count) {
    -		return XFS_ERROR(ENOENT);
    -	}
    -	/*
    -	 * Calculate sizes.
    -	 */
    -	byteoff = (int)((char *)sfep - (char *)sfp);
    -	entsize = XFS_DIR2_SF_ENTSIZE_BYNAME(sfp, args->namelen);
    -	newsize = oldsize - entsize;
    -	/*
    -	 * Copy the part if any after the removed entry, sliding it down.
    -	 */
    -	if (byteoff + entsize < oldsize)
    -		memmove((char *)sfp + byteoff, (char *)sfp + byteoff + entsize,
    -			oldsize - (byteoff + entsize));
    -	/*
    -	 * Fix up the header and file size.
    -	 */
    -	sfp->hdr.count--;
    -	dp->i_d.di_size = newsize;
    -	/*
    -	 * Reallocate, making it smaller.
    -	 */
    -	xfs_idata_realloc(dp, newsize - oldsize, XFS_DATA_FORK);
    -	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
    -#if XFS_BIG_INUMS
    -	/*
    -	 * Are we changing inode number size?
    -	 */
    -	if (args->inumber > XFS_DIR2_MAX_SHORT_INUM) {
    -		if (sfp->hdr.i8count == 1)
    -			xfs_dir2_sf_toino4(args);
    -		else
    -			sfp->hdr.i8count--;
    -	}
    -#endif
    -	xfs_dir2_sf_check(args);
    -	xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA);
    -	return 0;
    -}
    -
    -/*
    - * Replace the inode number of an entry in a shortform directory.
    - */
    -int						/* error */
    -xfs_dir2_sf_replace(
    -	xfs_da_args_t		*args)		/* operation arguments */
    -{
    -	xfs_inode_t		*dp;		/* incore directory inode */
    -	int			i;		/* entry index */
    -#if XFS_BIG_INUMS || defined(DEBUG)
    -	xfs_ino_t		ino=0;		/* entry old inode number */
    -#endif
    -#if XFS_BIG_INUMS
    -	int			i8elevated;	/* sf_toino8 set i8count=1 */
    -#endif
    -	xfs_dir2_sf_entry_t	*sfep;		/* shortform directory entry */
    -	xfs_dir2_sf_t		*sfp;		/* shortform structure */
    -
    -	xfs_dir2_trace_args("sf_replace", args);
    -	dp = args->dp;
    -
    -	ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
    -	/*
    -	 * Bail out if the shortform directory is way too small.
    -	 */
    -	if (dp->i_d.di_size < offsetof(xfs_dir2_sf_hdr_t, parent)) {
    -		ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount));
    -		return XFS_ERROR(EIO);
    -	}
    -	ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
    -	ASSERT(dp->i_df.if_u1.if_data != NULL);
    -	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
    -	ASSERT(dp->i_d.di_size >= XFS_DIR2_SF_HDR_SIZE(sfp->hdr.i8count));
    -#if XFS_BIG_INUMS
    -	/*
    -	 * New inode number is large, and need to convert to 8-byte inodes.
    -	 */
    -	if (args->inumber > XFS_DIR2_MAX_SHORT_INUM && sfp->hdr.i8count == 0) {
    -		int	error;			/* error return value */
    -		int	newsize;		/* new inode size */
    -
    -		newsize =
    -			dp->i_df.if_bytes +
    -			(sfp->hdr.count + 1) *
    -			((uint)sizeof(xfs_dir2_ino8_t) -
    -			 (uint)sizeof(xfs_dir2_ino4_t));
    -		/*
    -		 * Won't fit as shortform, convert to block then do replace.
    -		 */
    -		if (newsize > XFS_IFORK_DSIZE(dp)) {
    -			error = xfs_dir2_sf_to_block(args);
    -			if (error) {
    -				return error;
    -			}
    -			return xfs_dir2_block_replace(args);
    -		}
    -		/*
    -		 * Still fits, convert to 8-byte now.
    -		 */
    -		xfs_dir2_sf_toino8(args);
    -		i8elevated = 1;
    -		sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
    -	} else
    -		i8elevated = 0;
    -#endif
    -	ASSERT(args->namelen != 1 || args->name[0] != '.');
    -	/*
    -	 * Replace ..'s entry.
    -	 */
    -	if (args->namelen == 2 &&
    -	    args->name[0] == '.' && args->name[1] == '.') {
    -#if XFS_BIG_INUMS || defined(DEBUG)
    -		ino = XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent);
    -		ASSERT(args->inumber != ino);
    -#endif
    -		XFS_DIR2_SF_PUT_INUMBER(sfp, &args->inumber, &sfp->hdr.parent);
    -	}
    -	/*
    -	 * Normal entry, look for the name.
    -	 */
    -	else {
    -		for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
    -		     i < sfp->hdr.count;
    -		     i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep)) {
    -			if (sfep->namelen == args->namelen &&
    -			    sfep->name[0] == args->name[0] &&
    -			    memcmp(args->name, sfep->name, args->namelen) == 0) {
    -#if XFS_BIG_INUMS || defined(DEBUG)
    -				ino = XFS_DIR2_SF_GET_INUMBER(sfp,
    -					XFS_DIR2_SF_INUMBERP(sfep));
    -				ASSERT(args->inumber != ino);
    -#endif
    -				XFS_DIR2_SF_PUT_INUMBER(sfp, &args->inumber,
    -					XFS_DIR2_SF_INUMBERP(sfep));
    -				break;
    -			}
    -		}
    -		/*
    -		 * Didn't find it.
    -		 */
    -		if (i == sfp->hdr.count) {
    -			ASSERT(args->oknoent);
    -#if XFS_BIG_INUMS
    -			if (i8elevated)
    -				xfs_dir2_sf_toino4(args);
    -#endif
    -			return XFS_ERROR(ENOENT);
    -		}
    -	}
    -#if XFS_BIG_INUMS
    -	/*
    -	 * See if the old number was large, the new number is small.
    -	 */
    -	if (ino > XFS_DIR2_MAX_SHORT_INUM &&
    -	    args->inumber <= XFS_DIR2_MAX_SHORT_INUM) {
    -		/*
    -		 * And the old count was one, so need to convert to small.
    -		 */
    -		if (sfp->hdr.i8count == 1)
    -			xfs_dir2_sf_toino4(args);
    -		else
    -			sfp->hdr.i8count--;
    -	}
    -	/*
    -	 * See if the old number was small, the new number is large.
    -	 */
    -	if (ino <= XFS_DIR2_MAX_SHORT_INUM &&
    -	    args->inumber > XFS_DIR2_MAX_SHORT_INUM) {
    -		/*
    -		 * add to the i8count unless we just converted to 8-byte
    -		 * inodes (which does an implied i8count = 1)
    -		 */
    -		ASSERT(sfp->hdr.i8count != 0);
    -		if (!i8elevated)
    -			sfp->hdr.i8count++;
    -	}
    -#endif
    -	xfs_dir2_sf_check(args);
    -	xfs_trans_log_inode(args->trans, dp, XFS_ILOG_DDATA);
    -	return 0;
    -}
    -
    -#if XFS_BIG_INUMS
    -/*
    - * Convert from 8-byte inode numbers to 4-byte inode numbers.
    - * The last 8-byte inode number is gone, but the count is still 1.
    - */
    -static void
    -xfs_dir2_sf_toino4(
    -	xfs_da_args_t		*args)		/* operation arguments */
    -{
    -	char			*buf;		/* old dir's buffer */
    -	xfs_inode_t		*dp;		/* incore directory inode */
    -	int			i;		/* entry index */
    -	xfs_ino_t		ino;		/* entry inode number */
    -	int			newsize;	/* new inode size */
    -	xfs_dir2_sf_entry_t	*oldsfep;	/* old sf entry */
    -	xfs_dir2_sf_t		*oldsfp;	/* old sf directory */
    -	int			oldsize;	/* old inode size */
    -	xfs_dir2_sf_entry_t	*sfep;		/* new sf entry */
    -	xfs_dir2_sf_t		*sfp;		/* new sf directory */
    -
    -	xfs_dir2_trace_args("sf_toino4", args);
    -	dp = args->dp;
    -
    -	/*
    -	 * Copy the old directory to the buffer.
    -	 * Then nuke it from the inode, and add the new buffer to the inode.
    -	 * Don't want xfs_idata_realloc copying the data here.
    -	 */
    -	oldsize = dp->i_df.if_bytes;
    -	buf = kmem_alloc(oldsize, KM_SLEEP);
    -	oldsfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
    -	ASSERT(oldsfp->hdr.i8count == 1);
    -	memcpy(buf, oldsfp, oldsize);
    -	/*
    -	 * Compute the new inode size.
    -	 */
    -	newsize =
    -		oldsize -
    -		(oldsfp->hdr.count + 1) *
    -		((uint)sizeof(xfs_dir2_ino8_t) - (uint)sizeof(xfs_dir2_ino4_t));
    -	xfs_idata_realloc(dp, -oldsize, XFS_DATA_FORK);
    -	xfs_idata_realloc(dp, newsize, XFS_DATA_FORK);
    -	/*
    -	 * Reset our pointers, the data has moved.
    -	 */
    -	oldsfp = (xfs_dir2_sf_t *)buf;
    -	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
    -	/*
    -	 * Fill in the new header.
    -	 */
    -	sfp->hdr.count = oldsfp->hdr.count;
    -	sfp->hdr.i8count = 0;
    -	ino = XFS_DIR2_SF_GET_INUMBER(oldsfp, &oldsfp->hdr.parent);
    -	XFS_DIR2_SF_PUT_INUMBER(sfp, &ino, &sfp->hdr.parent);
    -	/*
    -	 * Copy the entries field by field.
    -	 */
    -	for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp),
    -		    oldsfep = XFS_DIR2_SF_FIRSTENTRY(oldsfp);
    -	     i < sfp->hdr.count;
    -	     i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep),
    -		  oldsfep = XFS_DIR2_SF_NEXTENTRY(oldsfp, oldsfep)) {
    -		sfep->namelen = oldsfep->namelen;
    -		sfep->offset = oldsfep->offset;
    -		memcpy(sfep->name, oldsfep->name, sfep->namelen);
    -		ino = XFS_DIR2_SF_GET_INUMBER(oldsfp,
    -			XFS_DIR2_SF_INUMBERP(oldsfep));
    -		XFS_DIR2_SF_PUT_INUMBER(sfp, &ino, XFS_DIR2_SF_INUMBERP(sfep));
    -	}
    -	/*
    -	 * Clean up the inode.
    -	 */
    -	kmem_free(buf, oldsize);
    -	dp->i_d.di_size = newsize;
    -	xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA);
    -}
    -
    -/*
    - * Convert from 4-byte inode numbers to 8-byte inode numbers.
    - * The new 8-byte inode number is not there yet, we leave with the
    - * count 1 but no corresponding entry.
    - */
    -static void
    -xfs_dir2_sf_toino8(
    -	xfs_da_args_t		*args)		/* operation arguments */
    -{
    -	char			*buf;		/* old dir's buffer */
    -	xfs_inode_t		*dp;		/* incore directory inode */
    -	int			i;		/* entry index */
    -	xfs_ino_t		ino;		/* entry inode number */
    -	int			newsize;	/* new inode size */
    -	xfs_dir2_sf_entry_t	*oldsfep;	/* old sf entry */
    -	xfs_dir2_sf_t		*oldsfp;	/* old sf directory */
    -	int			oldsize;	/* old inode size */
    -	xfs_dir2_sf_entry_t	*sfep;		/* new sf entry */
    -	xfs_dir2_sf_t		*sfp;		/* new sf directory */
    -
    -	xfs_dir2_trace_args("sf_toino8", args);
    -	dp = args->dp;
    -
    -	/*
    -	 * Copy the old directory to the buffer.
    -	 * Then nuke it from the inode, and add the new buffer to the inode.
    -	 * Don't want xfs_idata_realloc copying the data here.
    -	 */
    -	oldsize = dp->i_df.if_bytes;
    -	buf = kmem_alloc(oldsize, KM_SLEEP);
    -	oldsfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
    -	ASSERT(oldsfp->hdr.i8count == 0);
    -	memcpy(buf, oldsfp, oldsize);
    -	/*
    -	 * Compute the new inode size.
    -	 */
    -	newsize =
    -		oldsize +
    -		(oldsfp->hdr.count + 1) *
    -		((uint)sizeof(xfs_dir2_ino8_t) - (uint)sizeof(xfs_dir2_ino4_t));
    -	xfs_idata_realloc(dp, -oldsize, XFS_DATA_FORK);
    -	xfs_idata_realloc(dp, newsize, XFS_DATA_FORK);
    -	/*
    -	 * Reset our pointers, the data has moved.
    -	 */
    -	oldsfp = (xfs_dir2_sf_t *)buf;
    -	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
    -	/*
    -	 * Fill in the new header.
    -	 */
    -	sfp->hdr.count = oldsfp->hdr.count;
    -	sfp->hdr.i8count = 1;
    -	ino = XFS_DIR2_SF_GET_INUMBER(oldsfp, &oldsfp->hdr.parent);
    -	XFS_DIR2_SF_PUT_INUMBER(sfp, &ino, &sfp->hdr.parent);
    -	/*
    -	 * Copy the entries field by field.
    -	 */
    -	for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp),
    -		    oldsfep = XFS_DIR2_SF_FIRSTENTRY(oldsfp);
    -	     i < sfp->hdr.count;
    -	     i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep),
    -		  oldsfep = XFS_DIR2_SF_NEXTENTRY(oldsfp, oldsfep)) {
    -		sfep->namelen = oldsfep->namelen;
    -		sfep->offset = oldsfep->offset;
    -		memcpy(sfep->name, oldsfep->name, sfep->namelen);
    -		ino = XFS_DIR2_SF_GET_INUMBER(oldsfp,
    -			XFS_DIR2_SF_INUMBERP(oldsfep));
    -		XFS_DIR2_SF_PUT_INUMBER(sfp, &ino, XFS_DIR2_SF_INUMBERP(sfep));
    -	}
    -	/*
    -	 * Clean up the inode.
    -	 */
    -	kmem_free(buf, oldsize);
    -	dp->i_d.di_size = newsize;
    -	xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA);
    -}
    -#endif	/* XFS_BIG_INUMS */
    diff --git a/sys/gnu/fs/xfs/xfs_dir2_sf.h b/sys/gnu/fs/xfs/xfs_dir2_sf.h
    deleted file mode 100644
    index 42f015b7001..00000000000
    --- a/sys/gnu/fs/xfs/xfs_dir2_sf.h
    +++ /dev/null
    @@ -1,195 +0,0 @@
    -/*
    - * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_DIR2_SF_H__
    -#define	__XFS_DIR2_SF_H__
    -
    -/*
    - * Directory layout when stored internal to an inode.
    - *
    - * Small directories are packed as tightly as possible so as to
    - * fit into the literal area of the inode.
    - */
    -
    -struct uio;
    -struct xfs_dabuf;
    -struct xfs_da_args;
    -struct xfs_dir2_block;
    -struct xfs_inode;
    -struct xfs_mount;
    -struct xfs_trans;
    -
    -/*
    - * Maximum size of a shortform directory.
    - */
    -#define	XFS_DIR2_SF_MAX_SIZE	\
    -	(XFS_DINODE_MAX_SIZE - (uint)sizeof(xfs_dinode_core_t) - \
    -	 (uint)sizeof(xfs_agino_t))
    -
    -/*
    - * Inode number stored as 8 8-bit values.
    - */
    -typedef	struct { __uint8_t i[8]; } xfs_dir2_ino8_t;
    -
    -/*
    - * Inode number stored as 4 8-bit values.
    - * Works a lot of the time, when all the inode numbers in a directory
    - * fit in 32 bits.
    - */
    -typedef struct { __uint8_t i[4]; } xfs_dir2_ino4_t;
    -
    -typedef union {
    -	xfs_dir2_ino8_t	i8;
    -	xfs_dir2_ino4_t	i4;
    -} xfs_dir2_inou_t;
    -#define	XFS_DIR2_MAX_SHORT_INUM	((xfs_ino_t)0xffffffffULL)
    -
    -/*
    - * Normalized offset (in a data block) of the entry, really xfs_dir2_data_off_t.
    - * Only need 16 bits, this is the byte offset into the single block form.
    - */
    -typedef struct { __uint8_t i[2]; } xfs_dir2_sf_off_t;
    -
    -/*
    - * The parent directory has a dedicated field, and the self-pointer must
    - * be calculated on the fly.
    - *
    - * Entries are packed toward the top as tightly as possible.  The header
    - * and the elements must be memcpy'd out into a work area to get correct
    - * alignment for the inode number fields.
    - */
    -typedef struct xfs_dir2_sf_hdr {
    -	__uint8_t		count;		/* count of entries */
    -	__uint8_t		i8count;	/* count of 8-byte inode #s */
    -	xfs_dir2_inou_t		parent;		/* parent dir inode number */
    -} xfs_dir2_sf_hdr_t;
    -
    -typedef struct xfs_dir2_sf_entry {
    -	__uint8_t		namelen;	/* actual name length */
    -	xfs_dir2_sf_off_t	offset;		/* saved offset */
    -	__uint8_t		name[1];	/* name, variable size */
    -	xfs_dir2_inou_t		inumber;	/* inode number, var. offset */
    -} xfs_dir2_sf_entry_t;
    -
    -typedef struct xfs_dir2_sf {
    -	xfs_dir2_sf_hdr_t	hdr;		/* shortform header */
    -	xfs_dir2_sf_entry_t	list[1];	/* shortform entries */
    -} xfs_dir2_sf_t;
    -
    -#define	XFS_DIR2_SF_HDR_SIZE(i8count)	xfs_dir2_sf_hdr_size(i8count)
    -static inline int xfs_dir2_sf_hdr_size(int i8count)
    -{
    -	return ((uint)sizeof(xfs_dir2_sf_hdr_t) - \
    -		((i8count) == 0) * \
    -		((uint)sizeof(xfs_dir2_ino8_t) - (uint)sizeof(xfs_dir2_ino4_t)));
    -}
    -
    -#define	XFS_DIR2_SF_INUMBERP(sfep)	xfs_dir2_sf_inumberp(sfep)
    -static inline xfs_dir2_inou_t *xfs_dir2_sf_inumberp(xfs_dir2_sf_entry_t *sfep)
    -{
    -	return (xfs_dir2_inou_t *)&(sfep)->name[(sfep)->namelen];
    -}
    -
    -#define	XFS_DIR2_SF_GET_INUMBER(sfp, from) \
    -	xfs_dir2_sf_get_inumber(sfp, from)
    -static inline xfs_intino_t
    -xfs_dir2_sf_get_inumber(xfs_dir2_sf_t *sfp, xfs_dir2_inou_t *from)
    -{
    -	return ((sfp)->hdr.i8count == 0 ? \
    -		(xfs_intino_t)XFS_GET_DIR_INO4((from)->i4) : \
    -		(xfs_intino_t)XFS_GET_DIR_INO8((from)->i8));
    -}
    -
    -#define	XFS_DIR2_SF_PUT_INUMBER(sfp,from,to) \
    -	xfs_dir2_sf_put_inumber(sfp,from,to)
    -static inline void xfs_dir2_sf_put_inumber(xfs_dir2_sf_t *sfp, xfs_ino_t *from,
    -						xfs_dir2_inou_t *to)
    -{
    -	if ((sfp)->hdr.i8count == 0)
    -		XFS_PUT_DIR_INO4(*(from), (to)->i4);
    -	else
    -		XFS_PUT_DIR_INO8(*(from), (to)->i8);
    -}
    -
    -#define	XFS_DIR2_SF_GET_OFFSET(sfep)	\
    -	xfs_dir2_sf_get_offset(sfep)
    -static inline xfs_dir2_data_aoff_t
    -xfs_dir2_sf_get_offset(xfs_dir2_sf_entry_t *sfep)
    -{
    -	return INT_GET_UNALIGNED_16_BE(&(sfep)->offset.i);
    -}
    -
    -#define	XFS_DIR2_SF_PUT_OFFSET(sfep,off) \
    -	xfs_dir2_sf_put_offset(sfep,off)
    -static inline void
    -xfs_dir2_sf_put_offset(xfs_dir2_sf_entry_t *sfep, xfs_dir2_data_aoff_t off)
    -{
    -	INT_SET_UNALIGNED_16_BE(&(sfep)->offset.i, off);
    -}
    -
    -#define XFS_DIR2_SF_ENTSIZE_BYNAME(sfp,len)	\
    -	xfs_dir2_sf_entsize_byname(sfp,len)
    -static inline int xfs_dir2_sf_entsize_byname(xfs_dir2_sf_t *sfp, int len)
    -{
    -	return ((uint)sizeof(xfs_dir2_sf_entry_t) - 1 + (len) - \
    -		((sfp)->hdr.i8count == 0) * \
    -		((uint)sizeof(xfs_dir2_ino8_t) - (uint)sizeof(xfs_dir2_ino4_t)));
    -}
    -
    -#define XFS_DIR2_SF_ENTSIZE_BYENTRY(sfp,sfep)	\
    -	xfs_dir2_sf_entsize_byentry(sfp,sfep)
    -static inline int
    -xfs_dir2_sf_entsize_byentry(xfs_dir2_sf_t *sfp, xfs_dir2_sf_entry_t *sfep)
    -{
    -	return ((uint)sizeof(xfs_dir2_sf_entry_t) - 1 + (sfep)->namelen - \
    -		((sfp)->hdr.i8count == 0) * \
    -		((uint)sizeof(xfs_dir2_ino8_t) - (uint)sizeof(xfs_dir2_ino4_t)));
    -}
    -
    -#define XFS_DIR2_SF_FIRSTENTRY(sfp)	xfs_dir2_sf_firstentry(sfp)
    -static inline xfs_dir2_sf_entry_t *xfs_dir2_sf_firstentry(xfs_dir2_sf_t *sfp)
    -{
    -	return ((xfs_dir2_sf_entry_t *) \
    -		((char *)(sfp) + XFS_DIR2_SF_HDR_SIZE(sfp->hdr.i8count)));
    -}
    -
    -#define XFS_DIR2_SF_NEXTENTRY(sfp,sfep)	xfs_dir2_sf_nextentry(sfp,sfep)
    -static inline xfs_dir2_sf_entry_t *
    -xfs_dir2_sf_nextentry(xfs_dir2_sf_t *sfp, xfs_dir2_sf_entry_t *sfep)
    -{
    -	return ((xfs_dir2_sf_entry_t *) \
    -		((char *)(sfep) + XFS_DIR2_SF_ENTSIZE_BYENTRY(sfp,sfep)));
    -}
    -
    -/*
    - * Functions.
    - */
    -extern int xfs_dir2_block_sfsize(struct xfs_inode *dp,
    -				 struct xfs_dir2_block *block,
    -				 xfs_dir2_sf_hdr_t *sfhp);
    -extern int xfs_dir2_block_to_sf(struct xfs_da_args *args, struct xfs_dabuf *bp,
    -				int size, xfs_dir2_sf_hdr_t *sfhp);
    -extern int xfs_dir2_sf_addname(struct xfs_da_args *args);
    -extern int xfs_dir2_sf_create(struct xfs_da_args *args, xfs_ino_t pino);
    -extern int xfs_dir2_sf_getdents(struct xfs_inode *dp, struct uio *uio,
    -				int *eofp, struct xfs_dirent *dbp,
    -				xfs_dir2_put_t put);
    -extern int xfs_dir2_sf_lookup(struct xfs_da_args *args);
    -extern int xfs_dir2_sf_removename(struct xfs_da_args *args);
    -extern int xfs_dir2_sf_replace(struct xfs_da_args *args);
    -
    -#endif	/* __XFS_DIR2_SF_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_dir2_trace.c b/sys/gnu/fs/xfs/xfs_dir2_trace.c
    deleted file mode 100644
    index c626943b411..00000000000
    --- a/sys/gnu/fs/xfs/xfs_dir2_trace.c
    +++ /dev/null
    @@ -1,216 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_inum.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_da_btree.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_dir2_trace.h"
    -
    -#ifdef XFS_DIR2_TRACE
    -ktrace_t	*xfs_dir2_trace_buf;
    -
    -/*
    - * Enter something in the trace buffers.
    - */
    -static void
    -xfs_dir2_trace_enter(
    -	xfs_inode_t	*dp,
    -	int		type,
    -	char		*where,
    -	char		*name,
    -	int		namelen,
    -	void		*a0,
    -	void		*a1,
    -	void		*a2,
    -	void		*a3,
    -	void		*a4,
    -	void		*a5,
    -	void		*a6,
    -	void		*a7)
    -{
    -	void		*n[5];
    -
    -	ASSERT(xfs_dir2_trace_buf);
    -	ASSERT(dp->i_dir_trace);
    -	if (name)
    -		memcpy(n, name, min((int)sizeof(n), namelen));
    -	else
    -		memset((char *)n, 0, sizeof(n));
    -	ktrace_enter(xfs_dir2_trace_buf,
    -		(void *)(long)type, (void *)where,
    -		(void *)a0, (void *)a1, (void *)a2, (void *)a3,
    -		(void *)a4, (void *)a5, (void *)a6, (void *)a7,
    -		(void *)(long)namelen,
    -		(void *)n[0], (void *)n[1], (void *)n[2],
    -		(void *)n[3], (void *)n[4]);
    -	ktrace_enter(dp->i_dir_trace,
    -		(void *)(long)type, (void *)where,
    -		(void *)a0, (void *)a1, (void *)a2, (void *)a3,
    -		(void *)a4, (void *)a5, (void *)a6, (void *)a7,
    -		(void *)(long)namelen,
    -		(void *)n[0], (void *)n[1], (void *)n[2],
    -		(void *)n[3], (void *)n[4]);
    -}
    -
    -void
    -xfs_dir2_trace_args(
    -	char		*where,
    -	xfs_da_args_t	*args)
    -{
    -	xfs_dir2_trace_enter(args->dp, XFS_DIR2_KTRACE_ARGS, where,
    -		(char *)args->name, (int)args->namelen,
    -		(void *)(unsigned long)args->hashval,
    -		(void *)((unsigned long)(args->inumber >> 32)),
    -		(void *)((unsigned long)(args->inumber & 0xFFFFFFFF)),
    -		(void *)args->dp, (void *)args->trans,
    -		(void *)(unsigned long)args->justcheck, NULL, NULL);
    -}
    -
    -void
    -xfs_dir2_trace_args_b(
    -	char		*where,
    -	xfs_da_args_t	*args,
    -	xfs_dabuf_t	*bp)
    -{
    -	xfs_dir2_trace_enter(args->dp, XFS_DIR2_KTRACE_ARGS_B, where,
    -		(char *)args->name, (int)args->namelen,
    -		(void *)(unsigned long)args->hashval,
    -		(void *)((unsigned long)(args->inumber >> 32)),
    -		(void *)((unsigned long)(args->inumber & 0xFFFFFFFF)),
    -		(void *)args->dp, (void *)args->trans,
    -		(void *)(unsigned long)args->justcheck,
    -		(void *)(bp ? bp->bps[0] : NULL), NULL);
    -}
    -
    -void
    -xfs_dir2_trace_args_bb(
    -	char		*where,
    -	xfs_da_args_t	*args,
    -	xfs_dabuf_t	*lbp,
    -	xfs_dabuf_t	*dbp)
    -{
    -	xfs_dir2_trace_enter(args->dp, XFS_DIR2_KTRACE_ARGS_BB, where,
    -		(char *)args->name, (int)args->namelen,
    -		(void *)(unsigned long)args->hashval,
    -		(void *)((unsigned long)(args->inumber >> 32)),
    -		(void *)((unsigned long)(args->inumber & 0xFFFFFFFF)),
    -		(void *)args->dp, (void *)args->trans,
    -		(void *)(unsigned long)args->justcheck,
    -		(void *)(lbp ? lbp->bps[0] : NULL),
    -		(void *)(dbp ? dbp->bps[0] : NULL));
    -}
    -
    -void
    -xfs_dir2_trace_args_bibii(
    -	char		*where,
    -	xfs_da_args_t	*args,
    -	xfs_dabuf_t	*bs,
    -	int		ss,
    -	xfs_dabuf_t	*bd,
    -	int		sd,
    -	int		c)
    -{
    -	xfs_buf_t	*bpbs = bs ? bs->bps[0] : NULL;
    -	xfs_buf_t	*bpbd = bd ? bd->bps[0] : NULL;
    -
    -	xfs_dir2_trace_enter(args->dp, XFS_DIR2_KTRACE_ARGS_BIBII, where,
    -		(char *)args->name, (int)args->namelen,
    -		(void *)args->dp, (void *)args->trans,
    -		(void *)bpbs, (void *)(long)ss, (void *)bpbd, (void *)(long)sd,
    -		(void *)(long)c, NULL);
    -}
    -
    -void
    -xfs_dir2_trace_args_db(
    -	char		*where,
    -	xfs_da_args_t	*args,
    -	xfs_dir2_db_t	db,
    -	xfs_dabuf_t	*bp)
    -{
    -	xfs_buf_t	*dbp = bp ? bp->bps[0] : NULL;
    -
    -	xfs_dir2_trace_enter(args->dp, XFS_DIR2_KTRACE_ARGS_DB, where,
    -		(char *)args->name, (int)args->namelen,
    -		(void *)(unsigned long)args->hashval,
    -		(void *)((unsigned long)(args->inumber >> 32)),
    -		(void *)((unsigned long)(args->inumber & 0xFFFFFFFF)),
    -		(void *)args->dp, (void *)args->trans,
    -		(void *)(unsigned long)args->justcheck, (void *)(long)db,
    -		(void *)dbp);
    -}
    -
    -void
    -xfs_dir2_trace_args_i(
    -	char		*where,
    -	xfs_da_args_t	*args,
    -	xfs_ino_t	i)
    -{
    -	xfs_dir2_trace_enter(args->dp, XFS_DIR2_KTRACE_ARGS_I, where,
    -		(char *)args->name, (int)args->namelen,
    -		(void *)(unsigned long)args->hashval,
    -		(void *)((unsigned long)(args->inumber >> 32)),
    -		(void *)((unsigned long)(args->inumber & 0xFFFFFFFF)),
    -		(void *)args->dp, (void *)args->trans,
    -		(void *)(unsigned long)args->justcheck,
    -		(void *)((unsigned long)(i >> 32)),
    -		(void *)((unsigned long)(i & 0xFFFFFFFF)));
    -}
    -
    -void
    -xfs_dir2_trace_args_s(
    -	char		*where,
    -	xfs_da_args_t	*args,
    -	int		s)
    -{
    -	xfs_dir2_trace_enter(args->dp, XFS_DIR2_KTRACE_ARGS_S, where,
    -		(char *)args->name, (int)args->namelen,
    -		(void *)(unsigned long)args->hashval,
    -		(void *)((unsigned long)(args->inumber >> 32)),
    -		(void *)((unsigned long)(args->inumber & 0xFFFFFFFF)),
    -		(void *)args->dp, (void *)args->trans,
    -		(void *)(unsigned long)args->justcheck, (void *)(long)s, NULL);
    -}
    -
    -void
    -xfs_dir2_trace_args_sb(
    -	char		*where,
    -	xfs_da_args_t	*args,
    -	int		s,
    -	xfs_dabuf_t	*bp)
    -{
    -	xfs_buf_t	*dbp = bp ? bp->bps[0] : NULL;
    -
    -	xfs_dir2_trace_enter(args->dp, XFS_DIR2_KTRACE_ARGS_SB, where,
    -		(char *)args->name, (int)args->namelen,
    -		(void *)(unsigned long)args->hashval,
    -		(void *)((unsigned long)(args->inumber >> 32)),
    -		(void *)((unsigned long)(args->inumber & 0xFFFFFFFF)),
    -		(void *)args->dp, (void *)args->trans,
    -		(void *)(unsigned long)args->justcheck, (void *)(long)s,
    -		(void *)dbp);
    -}
    -#endif	/* XFS_DIR2_TRACE */
    diff --git a/sys/gnu/fs/xfs/xfs_dir2_trace.h b/sys/gnu/fs/xfs/xfs_dir2_trace.h
    deleted file mode 100644
    index ca3c754f482..00000000000
    --- a/sys/gnu/fs/xfs/xfs_dir2_trace.h
    +++ /dev/null
    @@ -1,72 +0,0 @@
    -/*
    - * Copyright (c) 2000,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_DIR2_TRACE_H__
    -#define __XFS_DIR2_TRACE_H__
    -
    -/*
    - * Tracing for xfs v2 directories.
    - */
    -
    -#if defined(XFS_DIR2_TRACE)
    -
    -struct ktrace;
    -struct xfs_dabuf;
    -struct xfs_da_args;
    -
    -#define	XFS_DIR2_GTRACE_SIZE		4096	/* global buffer */
    -#define	XFS_DIR2_KTRACE_SIZE		32	/* per-inode buffer */
    -extern struct ktrace *xfs_dir2_trace_buf;
    -
    -#define	XFS_DIR2_KTRACE_ARGS		1	/* args only */
    -#define	XFS_DIR2_KTRACE_ARGS_B		2	/* args + buffer */
    -#define	XFS_DIR2_KTRACE_ARGS_BB		3	/* args + 2 buffers */
    -#define	XFS_DIR2_KTRACE_ARGS_DB		4	/* args, db, buffer */
    -#define	XFS_DIR2_KTRACE_ARGS_I		5	/* args, inum */
    -#define	XFS_DIR2_KTRACE_ARGS_S		6	/* args, int */
    -#define	XFS_DIR2_KTRACE_ARGS_SB		7	/* args, int, buffer */
    -#define	XFS_DIR2_KTRACE_ARGS_BIBII	8	/* args, buf/int/buf/int/int */
    -
    -void xfs_dir2_trace_args(char *where, struct xfs_da_args *args);
    -void xfs_dir2_trace_args_b(char *where, struct xfs_da_args *args,
    -			   struct xfs_dabuf *bp);
    -void xfs_dir2_trace_args_bb(char *where, struct xfs_da_args *args,
    -			    struct xfs_dabuf *lbp, struct xfs_dabuf *dbp);
    -void xfs_dir2_trace_args_bibii(char *where, struct xfs_da_args *args,
    -			       struct xfs_dabuf *bs, int ss,
    -			       struct xfs_dabuf *bd, int sd, int c);
    -void xfs_dir2_trace_args_db(char *where, struct xfs_da_args *args,
    -			    xfs_dir2_db_t db, struct xfs_dabuf *bp);
    -void xfs_dir2_trace_args_i(char *where, struct xfs_da_args *args, xfs_ino_t i);
    -void xfs_dir2_trace_args_s(char *where, struct xfs_da_args *args, int s);
    -void xfs_dir2_trace_args_sb(char *where, struct xfs_da_args *args, int s,
    -			    struct xfs_dabuf *bp);
    -
    -#else	/* XFS_DIR2_TRACE */
    -
    -#define	xfs_dir2_trace_args(where, args)
    -#define	xfs_dir2_trace_args_b(where, args, bp)
    -#define	xfs_dir2_trace_args_bb(where, args, lbp, dbp)
    -#define	xfs_dir2_trace_args_bibii(where, args, bs, ss, bd, sd, c)
    -#define	xfs_dir2_trace_args_db(where, args, db, bp)
    -#define	xfs_dir2_trace_args_i(where, args, i)
    -#define	xfs_dir2_trace_args_s(where, args, s)
    -#define	xfs_dir2_trace_args_sb(where, args, s, bp)
    -
    -#endif	/* XFS_DIR2_TRACE */
    -
    -#endif	/* __XFS_DIR2_TRACE_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_dir_leaf.c b/sys/gnu/fs/xfs/xfs_dir_leaf.c
    deleted file mode 100644
    index f89cde1a665..00000000000
    --- a/sys/gnu/fs/xfs/xfs_dir_leaf.c
    +++ /dev/null
    @@ -1,2215 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_da_btree.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_inode_item.h"
    -#include "xfs_alloc.h"
    -#include "xfs_btree.h"
    -#include "xfs_bmap.h"
    -#include "xfs_dir_leaf.h"
    -#include "xfs_error.h"
    -
    -/*
    - * xfs_dir_leaf.c
    - *
    - * Routines to implement leaf blocks of directories as Btrees of hashed names.
    - */
    -
    -/*========================================================================
    - * Function prototypes for the kernel.
    - *========================================================================*/
    -
    -/*
    - * Routines used for growing the Btree.
    - */
    -STATIC void xfs_dir_leaf_add_work(xfs_dabuf_t *leaf_buffer, xfs_da_args_t *args,
    -					      int insertion_index,
    -					      int freemap_index);
    -STATIC int xfs_dir_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *leaf_buffer,
    -					    int musthave, int justcheck);
    -STATIC void xfs_dir_leaf_rebalance(xfs_da_state_t *state,
    -						  xfs_da_state_blk_t *blk1,
    -						  xfs_da_state_blk_t *blk2);
    -STATIC int xfs_dir_leaf_figure_balance(xfs_da_state_t *state,
    -					  xfs_da_state_blk_t *leaf_blk_1,
    -					  xfs_da_state_blk_t *leaf_blk_2,
    -					  int *number_entries_in_blk1,
    -					  int *number_namebytes_in_blk1);
    -
    -STATIC int xfs_dir_leaf_create(struct xfs_da_args *args,
    -				xfs_dablk_t which_block,
    -				struct xfs_dabuf **bpp);
    -
    -/*
    - * Utility routines.
    - */
    -STATIC void xfs_dir_leaf_moveents(xfs_dir_leafblock_t *src_leaf,
    -					      int src_start,
    -					      xfs_dir_leafblock_t *dst_leaf,
    -					      int dst_start, int move_count,
    -					      xfs_mount_t *mp);
    -
    -
    -/*========================================================================
    - * External routines when dirsize < XFS_IFORK_DSIZE(dp).
    - *========================================================================*/
    -
    -
    -/*
    - * Validate a given inode number.
    - */
    -int
    -xfs_dir_ino_validate(xfs_mount_t *mp, xfs_ino_t ino)
    -{
    -	xfs_agblock_t	agblkno;
    -	xfs_agino_t	agino;
    -	xfs_agnumber_t	agno;
    -	int		ino_ok;
    -	int		ioff;
    -
    -	agno = XFS_INO_TO_AGNO(mp, ino);
    -	agblkno = XFS_INO_TO_AGBNO(mp, ino);
    -	ioff = XFS_INO_TO_OFFSET(mp, ino);
    -	agino = XFS_OFFBNO_TO_AGINO(mp, agblkno, ioff);
    -	ino_ok =
    -		agno < mp->m_sb.sb_agcount &&
    -		agblkno < mp->m_sb.sb_agblocks &&
    -		agblkno != 0 &&
    -		ioff < (1 << mp->m_sb.sb_inopblog) &&
    -		XFS_AGINO_TO_INO(mp, agno, agino) == ino;
    -	if (unlikely(XFS_TEST_ERROR(!ino_ok, mp, XFS_ERRTAG_DIR_INO_VALIDATE,
    -			XFS_RANDOM_DIR_INO_VALIDATE))) {
    -		xfs_fs_cmn_err(CE_WARN, mp, "Invalid inode number 0x%Lx",
    -				(unsigned long long) ino);
    -		XFS_ERROR_REPORT("xfs_dir_ino_validate", XFS_ERRLEVEL_LOW, mp);
    -		return XFS_ERROR(EFSCORRUPTED);
    -	}
    -	return 0;
    -}
    -
    -/*
    - * Create the initial contents of a shortform directory.
    - */
    -int
    -xfs_dir_shortform_create(xfs_da_args_t *args, xfs_ino_t parent)
    -{
    -	xfs_dir_sf_hdr_t *hdr;
    -	xfs_inode_t *dp;
    -
    -	dp = args->dp;
    -	ASSERT(dp != NULL);
    -	ASSERT(dp->i_d.di_size == 0);
    -	if (dp->i_d.di_format == XFS_DINODE_FMT_EXTENTS) {
    -		dp->i_df.if_flags &= ~XFS_IFEXTENTS;	/* just in case */
    -		dp->i_d.di_format = XFS_DINODE_FMT_LOCAL;
    -		xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE);
    -		dp->i_df.if_flags |= XFS_IFINLINE;
    -	}
    -	ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
    -	ASSERT(dp->i_df.if_bytes == 0);
    -	xfs_idata_realloc(dp, sizeof(*hdr), XFS_DATA_FORK);
    -	hdr = (xfs_dir_sf_hdr_t *)dp->i_df.if_u1.if_data;
    -	XFS_DIR_SF_PUT_DIRINO(&parent, &hdr->parent);
    -
    -	hdr->count = 0;
    -	dp->i_d.di_size = sizeof(*hdr);
    -	xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA);
    -	return 0;
    -}
    -
    -/*
    - * Add a name to the shortform directory structure.
    - * Overflow from the inode has already been checked for.
    - */
    -int
    -xfs_dir_shortform_addname(xfs_da_args_t *args)
    -{
    -	xfs_dir_shortform_t *sf;
    -	xfs_dir_sf_entry_t *sfe;
    -	int i, offset, size;
    -	xfs_inode_t *dp;
    -
    -	dp = args->dp;
    -	ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
    -	/*
    -	 * Catch the case where the conversion from shortform to leaf
    -	 * failed part way through.
    -	 */
    -	if (dp->i_d.di_size < sizeof(xfs_dir_sf_hdr_t)) {
    -		ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount));
    -		return XFS_ERROR(EIO);
    -	}
    -	ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
    -	ASSERT(dp->i_df.if_u1.if_data != NULL);
    -	sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data;
    -	sfe = &sf->list[0];
    -	for (i = sf->hdr.count-1; i >= 0; i--) {
    -		if (sfe->namelen == args->namelen &&
    -		    args->name[0] == sfe->name[0] &&
    -		    memcmp(args->name, sfe->name, args->namelen) == 0)
    -			return XFS_ERROR(EEXIST);
    -		sfe = XFS_DIR_SF_NEXTENTRY(sfe);
    -	}
    -
    -	offset = (int)((char *)sfe - (char *)sf);
    -	size = XFS_DIR_SF_ENTSIZE_BYNAME(args->namelen);
    -	xfs_idata_realloc(dp, size, XFS_DATA_FORK);
    -	sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data;
    -	sfe = (xfs_dir_sf_entry_t *)((char *)sf + offset);
    -
    -	XFS_DIR_SF_PUT_DIRINO(&args->inumber, &sfe->inumber);
    -	sfe->namelen = args->namelen;
    -	memcpy(sfe->name, args->name, sfe->namelen);
    -	sf->hdr.count++;
    -
    -	dp->i_d.di_size += size;
    -	xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA);
    -
    -	return 0;
    -}
    -
    -/*
    - * Remove a name from the shortform directory structure.
    - */
    -int
    -xfs_dir_shortform_removename(xfs_da_args_t *args)
    -{
    -	xfs_dir_shortform_t *sf;
    -	xfs_dir_sf_entry_t *sfe;
    -	int base, size = 0, i;
    -	xfs_inode_t *dp;
    -
    -	dp = args->dp;
    -	ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
    -	/*
    -	 * Catch the case where the conversion from shortform to leaf
    -	 * failed part way through.
    -	 */
    -	if (dp->i_d.di_size < sizeof(xfs_dir_sf_hdr_t)) {
    -		ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount));
    -		return XFS_ERROR(EIO);
    -	}
    -	ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
    -	ASSERT(dp->i_df.if_u1.if_data != NULL);
    -	base = sizeof(xfs_dir_sf_hdr_t);
    -	sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data;
    -	sfe = &sf->list[0];
    -	for (i = sf->hdr.count-1; i >= 0; i--) {
    -		size = XFS_DIR_SF_ENTSIZE_BYENTRY(sfe);
    -		if (sfe->namelen == args->namelen &&
    -		    sfe->name[0] == args->name[0] &&
    -		    memcmp(sfe->name, args->name, args->namelen) == 0)
    -			break;
    -		base += size;
    -		sfe = XFS_DIR_SF_NEXTENTRY(sfe);
    -	}
    -	if (i < 0) {
    -		ASSERT(args->oknoent);
    -		return XFS_ERROR(ENOENT);
    -	}
    -
    -	if ((base + size) != dp->i_d.di_size) {
    -		memmove(&((char *)sf)[base], &((char *)sf)[base+size],
    -					      dp->i_d.di_size - (base+size));
    -	}
    -	sf->hdr.count--;
    -
    -	xfs_idata_realloc(dp, -size, XFS_DATA_FORK);
    -	dp->i_d.di_size -= size;
    -	xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA);
    -
    -	return 0;
    -}
    -
    -/*
    - * Look up a name in a shortform directory structure.
    - */
    -int
    -xfs_dir_shortform_lookup(xfs_da_args_t *args)
    -{
    -	xfs_dir_shortform_t *sf;
    -	xfs_dir_sf_entry_t *sfe;
    -	int i;
    -	xfs_inode_t *dp;
    -
    -	dp = args->dp;
    -	ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
    -	/*
    -	 * Catch the case where the conversion from shortform to leaf
    -	 * failed part way through.
    -	 */
    -	if (dp->i_d.di_size < sizeof(xfs_dir_sf_hdr_t)) {
    -		ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount));
    -		return XFS_ERROR(EIO);
    -	}
    -	ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
    -	ASSERT(dp->i_df.if_u1.if_data != NULL);
    -	sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data;
    -	if (args->namelen == 2 &&
    -	    args->name[0] == '.' && args->name[1] == '.') {
    -		XFS_DIR_SF_GET_DIRINO(&sf->hdr.parent, &args->inumber);
    -		return(XFS_ERROR(EEXIST));
    -	}
    -	if (args->namelen == 1 && args->name[0] == '.') {
    -		args->inumber = dp->i_ino;
    -		return(XFS_ERROR(EEXIST));
    -	}
    -	sfe = &sf->list[0];
    -	for (i = sf->hdr.count-1; i >= 0; i--) {
    -		if (sfe->namelen == args->namelen &&
    -		    sfe->name[0] == args->name[0] &&
    -		    memcmp(args->name, sfe->name, args->namelen) == 0) {
    -			XFS_DIR_SF_GET_DIRINO(&sfe->inumber, &args->inumber);
    -			return(XFS_ERROR(EEXIST));
    -		}
    -		sfe = XFS_DIR_SF_NEXTENTRY(sfe);
    -	}
    -	ASSERT(args->oknoent);
    -	return(XFS_ERROR(ENOENT));
    -}
    -
    -/*
    - * Convert from using the shortform to the leaf.
    - */
    -int
    -xfs_dir_shortform_to_leaf(xfs_da_args_t *iargs)
    -{
    -	xfs_inode_t *dp;
    -	xfs_dir_shortform_t *sf;
    -	xfs_dir_sf_entry_t *sfe;
    -	xfs_da_args_t args;
    -	xfs_ino_t inumber;
    -	char *tmpbuffer;
    -	int retval, i, size;
    -	xfs_dablk_t blkno;
    -	xfs_dabuf_t *bp;
    -
    -	dp = iargs->dp;
    -	/*
    -	 * Catch the case where the conversion from shortform to leaf
    -	 * failed part way through.
    -	 */
    -	if (dp->i_d.di_size < sizeof(xfs_dir_sf_hdr_t)) {
    -		ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount));
    -		return XFS_ERROR(EIO);
    -	}
    -	ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
    -	ASSERT(dp->i_df.if_u1.if_data != NULL);
    -	size = dp->i_df.if_bytes;
    -	tmpbuffer = kmem_alloc(size, KM_SLEEP);
    -	ASSERT(tmpbuffer != NULL);
    -
    -	memcpy(tmpbuffer, dp->i_df.if_u1.if_data, size);
    -
    -	sf = (xfs_dir_shortform_t *)tmpbuffer;
    -	XFS_DIR_SF_GET_DIRINO(&sf->hdr.parent, &inumber);
    -
    -	xfs_idata_realloc(dp, -size, XFS_DATA_FORK);
    -	dp->i_d.di_size = 0;
    -	xfs_trans_log_inode(iargs->trans, dp, XFS_ILOG_CORE);
    -	retval = xfs_da_grow_inode(iargs, &blkno);
    -	if (retval)
    -		goto out;
    -
    -	ASSERT(blkno == 0);
    -	retval = xfs_dir_leaf_create(iargs, blkno, &bp);
    -	if (retval)
    -		goto out;
    -	xfs_da_buf_done(bp);
    -
    -	args.name = ".";
    -	args.namelen = 1;
    -	args.hashval = xfs_dir_hash_dot;
    -	args.inumber = dp->i_ino;
    -	args.dp = dp;
    -	args.firstblock = iargs->firstblock;
    -	args.flist = iargs->flist;
    -	args.total = iargs->total;
    -	args.whichfork = XFS_DATA_FORK;
    -	args.trans = iargs->trans;
    -	args.justcheck = 0;
    -	args.addname = args.oknoent = 1;
    -	retval = xfs_dir_leaf_addname(&args);
    -	if (retval)
    -		goto out;
    -
    -	args.name = "..";
    -	args.namelen = 2;
    -	args.hashval = xfs_dir_hash_dotdot;
    -	args.inumber = inumber;
    -	retval = xfs_dir_leaf_addname(&args);
    -	if (retval)
    -		goto out;
    -
    -	sfe = &sf->list[0];
    -	for (i = 0; i < sf->hdr.count; i++) {
    -		args.name = (char *)(sfe->name);
    -		args.namelen = sfe->namelen;
    -		args.hashval = xfs_da_hashname((char *)(sfe->name),
    -					       sfe->namelen);
    -		XFS_DIR_SF_GET_DIRINO(&sfe->inumber, &args.inumber);
    -		retval = xfs_dir_leaf_addname(&args);
    -		if (retval)
    -			goto out;
    -		sfe = XFS_DIR_SF_NEXTENTRY(sfe);
    -	}
    -	retval = 0;
    -
    -out:
    -	kmem_free(tmpbuffer, size);
    -	return retval;
    -}
    -
    -STATIC int
    -xfs_dir_shortform_compare(const void *a, const void *b)
    -{
    -	const xfs_dir_sf_sort_t *sa, *sb;
    -
    -	sa = (const xfs_dir_sf_sort_t *)a;
    -	sb = (const xfs_dir_sf_sort_t *)b;
    -	if (sa->hash < sb->hash)
    -		return -1;
    -	else if (sa->hash > sb->hash)
    -		return 1;
    -	else
    -		return sa->entno - sb->entno;
    -}
    -
    -/*
    - * Copy out directory entries for getdents(), for shortform directories.
    - */
    -/*ARGSUSED*/
    -int
    -xfs_dir_shortform_getdents(xfs_inode_t *dp, uio_t *uio, int *eofp,
    -				       xfs_dirent_t *dbp, xfs_dir_put_t put)
    -{
    -	xfs_dir_shortform_t *sf;
    -	xfs_dir_sf_entry_t *sfe;
    -	int retval, i, sbsize, nsbuf, lastresid=0, want_entno;
    -	xfs_mount_t *mp;
    -	xfs_dahash_t cookhash, hash;
    -	xfs_dir_put_args_t p;
    -	xfs_dir_sf_sort_t *sbuf, *sbp;
    -
    -	mp = dp->i_mount;
    -	sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data;
    -	cookhash = XFS_DA_COOKIE_HASH(mp, uio->uio_offset);
    -	want_entno = XFS_DA_COOKIE_ENTRY(mp, uio->uio_offset);
    -	nsbuf = sf->hdr.count + 2;
    -	sbsize = (nsbuf + 1) * sizeof(*sbuf);
    -	sbp = sbuf = kmem_alloc(sbsize, KM_SLEEP);
    -
    -	xfs_dir_trace_g_du("sf: start", dp, uio);
    -
    -	/*
    -	 * Collect all the entries into the buffer.
    -	 * Entry 0 is .
    -	 */
    -	sbp->entno = 0;
    -	sbp->seqno = 0;
    -	sbp->hash = xfs_dir_hash_dot;
    -	sbp->ino = dp->i_ino;
    -	sbp->name = ".";
    -	sbp->namelen = 1;
    -	sbp++;
    -
    -	/*
    -	 * Entry 1 is ..
    -	 */
    -	sbp->entno = 1;
    -	sbp->seqno = 0;
    -	sbp->hash = xfs_dir_hash_dotdot;
    -	sbp->ino = XFS_GET_DIR_INO8(sf->hdr.parent);
    -	sbp->name = "..";
    -	sbp->namelen = 2;
    -	sbp++;
    -
    -	/*
    -	 * Scan the directory data for the rest of the entries.
    -	 */
    -	for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) {
    -
    -		if (unlikely(
    -		    ((char *)sfe < (char *)sf) ||
    -		    ((char *)sfe >= ((char *)sf + dp->i_df.if_bytes)))) {
    -			xfs_dir_trace_g_du("sf: corrupted", dp, uio);
    -			XFS_CORRUPTION_ERROR("xfs_dir_shortform_getdents",
    -					     XFS_ERRLEVEL_LOW, mp, sfe);
    -			kmem_free(sbuf, sbsize);
    -			return XFS_ERROR(EFSCORRUPTED);
    -		}
    -
    -		sbp->entno = i + 2;
    -		sbp->seqno = 0;
    -		sbp->hash = xfs_da_hashname((char *)sfe->name, sfe->namelen);
    -		sbp->ino = XFS_GET_DIR_INO8(sfe->inumber);
    -		sbp->name = (char *)sfe->name;
    -		sbp->namelen = sfe->namelen;
    -		sfe = XFS_DIR_SF_NEXTENTRY(sfe);
    -		sbp++;
    -	}
    -
    -	/*
    -	 * Sort the entries on hash then entno.
    -	 */
    -	xfs_sort(sbuf, nsbuf, sizeof(*sbuf), xfs_dir_shortform_compare);
    -	/*
    -	 * Stuff in last entry.
    -	 */
    -	sbp->entno = nsbuf;
    -	sbp->hash = XFS_DA_MAXHASH;
    -	sbp->seqno = 0;
    -	/*
    -	 * Figure out the sequence numbers in case there's a hash duplicate.
    -	 */
    -	for (hash = sbuf->hash, sbp = sbuf + 1;
    -				sbp < &sbuf[nsbuf + 1]; sbp++) {
    -		if (sbp->hash == hash)
    -			sbp->seqno = sbp[-1].seqno + 1;
    -		else
    -			hash = sbp->hash;
    -	}
    -
    -	/*
    -	 * Set up put routine.
    -	 */
    -	p.dbp = dbp;
    -	p.put = put;
    -	p.uio = uio;
    -
    -	/*
    -	 * Find our place.
    -	 */
    -	for (sbp = sbuf; sbp < &sbuf[nsbuf + 1]; sbp++) {
    -		if (sbp->hash > cookhash ||
    -		    (sbp->hash == cookhash && sbp->seqno >= want_entno))
    -			break;
    -	}
    -
    -	/*
    -	 * Did we fail to find anything?  We stop at the last entry,
    -	 * the one we put maxhash into.
    -	 */
    -	if (sbp == &sbuf[nsbuf]) {
    -		kmem_free(sbuf, sbsize);
    -		xfs_dir_trace_g_du("sf: hash beyond end", dp, uio);
    -		uio->uio_offset = XFS_DA_MAKE_COOKIE(mp, 0, 0, XFS_DA_MAXHASH);
    -		*eofp = 1;
    -		return 0;
    -	}
    -
    -	/*
    -	 * Loop putting entries into the user buffer.
    -	 */
    -	while (sbp < &sbuf[nsbuf]) {
    -		/*
    -		 * Save the first resid in a run of equal-hashval entries
    -		 * so that we can back them out if they don't all fit.
    -		 */
    -		if (sbp->seqno == 0 || sbp == sbuf)
    -			lastresid = uio->uio_resid;
    -		XFS_PUT_COOKIE(p.cook, mp, 0, sbp[1].seqno, sbp[1].hash);
    -		p.ino = sbp->ino;
    -#if XFS_BIG_INUMS
    -		p.ino += mp->m_inoadd;
    -#endif
    -		p.name = sbp->name;
    -		p.namelen = sbp->namelen;
    -		retval = p.put(&p);
    -		if (!p.done) {
    -			uio->uio_offset =
    -				XFS_DA_MAKE_COOKIE(mp, 0, 0, sbp->hash);
    -			kmem_free(sbuf, sbsize);
    -			uio->uio_resid = lastresid;
    -			xfs_dir_trace_g_du("sf: E-O-B", dp, uio);
    -			return retval;
    -		}
    -		sbp++;
    -	}
    -	kmem_free(sbuf, sbsize);
    -	uio->uio_offset = p.cook.o;
    -	*eofp = 1;
    -	xfs_dir_trace_g_du("sf: E-O-F", dp, uio);
    -	return 0;
    -}
    -
    -/*
    - * Look up a name in a shortform directory structure, replace the inode number.
    - */
    -int
    -xfs_dir_shortform_replace(xfs_da_args_t *args)
    -{
    -	xfs_dir_shortform_t *sf;
    -	xfs_dir_sf_entry_t *sfe;
    -	xfs_inode_t *dp;
    -	int i;
    -
    -	dp = args->dp;
    -	ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
    -	/*
    -	 * Catch the case where the conversion from shortform to leaf
    -	 * failed part way through.
    -	 */
    -	if (dp->i_d.di_size < sizeof(xfs_dir_sf_hdr_t)) {
    -		ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount));
    -		return XFS_ERROR(EIO);
    -	}
    -	ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
    -	ASSERT(dp->i_df.if_u1.if_data != NULL);
    -	sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data;
    -	if (args->namelen == 2 &&
    -	    args->name[0] == '.' && args->name[1] == '.') {
    -		/* XXX - replace assert? */
    -		XFS_DIR_SF_PUT_DIRINO(&args->inumber, &sf->hdr.parent);
    -		xfs_trans_log_inode(args->trans, dp, XFS_ILOG_DDATA);
    -		return 0;
    -	}
    -	ASSERT(args->namelen != 1 || args->name[0] != '.');
    -	sfe = &sf->list[0];
    -	for (i = sf->hdr.count-1; i >= 0; i--) {
    -		if (sfe->namelen == args->namelen &&
    -		    sfe->name[0] == args->name[0] &&
    -		    memcmp(args->name, sfe->name, args->namelen) == 0) {
    -			ASSERT(memcmp((char *)&args->inumber,
    -				(char *)&sfe->inumber, sizeof(xfs_ino_t)));
    -			XFS_DIR_SF_PUT_DIRINO(&args->inumber, &sfe->inumber);
    -			xfs_trans_log_inode(args->trans, dp, XFS_ILOG_DDATA);
    -			return 0;
    -		}
    -		sfe = XFS_DIR_SF_NEXTENTRY(sfe);
    -	}
    -	ASSERT(args->oknoent);
    -	return XFS_ERROR(ENOENT);
    -}
    -
    -/*
    - * Convert a leaf directory to shortform structure
    - */
    -int
    -xfs_dir_leaf_to_shortform(xfs_da_args_t *iargs)
    -{
    -	xfs_dir_leafblock_t *leaf;
    -	xfs_dir_leaf_hdr_t *hdr;
    -	xfs_dir_leaf_entry_t *entry;
    -	xfs_dir_leaf_name_t *namest;
    -	xfs_da_args_t args;
    -	xfs_inode_t *dp;
    -	xfs_ino_t parent = 0;
    -	char *tmpbuffer;
    -	int retval, i;
    -	xfs_dabuf_t *bp;
    -
    -	dp = iargs->dp;
    -	tmpbuffer = kmem_alloc(XFS_LBSIZE(dp->i_mount), KM_SLEEP);
    -	ASSERT(tmpbuffer != NULL);
    -
    -	retval = xfs_da_read_buf(iargs->trans, iargs->dp, 0, -1, &bp,
    -					       XFS_DATA_FORK);
    -	if (retval)
    -		goto out;
    -	ASSERT(bp != NULL);
    -	memcpy(tmpbuffer, bp->data, XFS_LBSIZE(dp->i_mount));
    -	leaf = (xfs_dir_leafblock_t *)tmpbuffer;
    -	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
    -	memset(bp->data, 0, XFS_LBSIZE(dp->i_mount));
    -
    -	/*
    -	 * Find and special case the parent inode number
    -	 */
    -	hdr = &leaf->hdr;
    -	entry = &leaf->entries[0];
    -	for (i = INT_GET(hdr->count, ARCH_CONVERT)-1; i >= 0; entry++, i--) {
    -		namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT));
    -		if ((entry->namelen == 2) &&
    -		    (namest->name[0] == '.') &&
    -		    (namest->name[1] == '.')) {
    -			XFS_DIR_SF_GET_DIRINO(&namest->inumber, &parent);
    -			entry->nameidx = 0;
    -		} else if ((entry->namelen == 1) && (namest->name[0] == '.')) {
    -			entry->nameidx = 0;
    -		}
    -	}
    -	retval = xfs_da_shrink_inode(iargs, 0, bp);
    -	if (retval)
    -		goto out;
    -	retval = xfs_dir_shortform_create(iargs, parent);
    -	if (retval)
    -		goto out;
    -
    -	/*
    -	 * Copy the rest of the filenames
    -	 */
    -	entry = &leaf->entries[0];
    -	args.dp = dp;
    -	args.firstblock = iargs->firstblock;
    -	args.flist = iargs->flist;
    -	args.total = iargs->total;
    -	args.whichfork = XFS_DATA_FORK;
    -	args.trans = iargs->trans;
    -	args.justcheck = 0;
    -	args.addname = args.oknoent = 1;
    -	for (i = 0; i < INT_GET(hdr->count, ARCH_CONVERT); entry++, i++) {
    -		if (!entry->nameidx)
    -			continue;
    -		namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT));
    -		args.name = (char *)(namest->name);
    -		args.namelen = entry->namelen;
    -		args.hashval = INT_GET(entry->hashval, ARCH_CONVERT);
    -		XFS_DIR_SF_GET_DIRINO(&namest->inumber, &args.inumber);
    -		xfs_dir_shortform_addname(&args);
    -	}
    -
    -out:
    -	kmem_free(tmpbuffer, XFS_LBSIZE(dp->i_mount));
    -	return retval;
    -}
    -
    -/*
    - * Convert from using a single leaf to a root node and a leaf.
    - */
    -int
    -xfs_dir_leaf_to_node(xfs_da_args_t *args)
    -{
    -	xfs_dir_leafblock_t *leaf;
    -	xfs_da_intnode_t *node;
    -	xfs_inode_t *dp;
    -	xfs_dabuf_t *bp1, *bp2;
    -	xfs_dablk_t blkno;
    -	int retval;
    -
    -	dp = args->dp;
    -	retval = xfs_da_grow_inode(args, &blkno);
    -	ASSERT(blkno == 1);
    -	if (retval)
    -		return retval;
    -	retval = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp1,
    -					      XFS_DATA_FORK);
    -	if (retval)
    -		return retval;
    -	ASSERT(bp1 != NULL);
    -	retval = xfs_da_get_buf(args->trans, args->dp, 1, -1, &bp2,
    -					     XFS_DATA_FORK);
    -	if (retval) {
    -		xfs_da_buf_done(bp1);
    -		return retval;
    -	}
    -	ASSERT(bp2 != NULL);
    -	memcpy(bp2->data, bp1->data, XFS_LBSIZE(dp->i_mount));
    -	xfs_da_buf_done(bp1);
    -	xfs_da_log_buf(args->trans, bp2, 0, XFS_LBSIZE(dp->i_mount) - 1);
    -
    -	/*
    -	 * Set up the new root node.
    -	 */
    -	retval = xfs_da_node_create(args, 0, 1, &bp1, XFS_DATA_FORK);
    -	if (retval) {
    -		xfs_da_buf_done(bp2);
    -		return retval;
    -	}
    -	node = bp1->data;
    -	leaf = bp2->data;
    -	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
    -	node->btree[0].hashval = cpu_to_be32(
    -		INT_GET(leaf->entries[
    -			INT_GET(leaf->hdr.count, ARCH_CONVERT)-1].hashval, ARCH_CONVERT));
    -	xfs_da_buf_done(bp2);
    -	node->btree[0].before = cpu_to_be32(blkno);
    -	node->hdr.count = cpu_to_be16(1);
    -	xfs_da_log_buf(args->trans, bp1,
    -		XFS_DA_LOGRANGE(node, &node->btree[0], sizeof(node->btree[0])));
    -	xfs_da_buf_done(bp1);
    -
    -	return retval;
    -}
    -
    -
    -/*========================================================================
    - * Routines used for growing the Btree.
    - *========================================================================*/
    -
    -/*
    - * Create the initial contents of a leaf directory
    - * or a leaf in a node directory.
    - */
    -STATIC int
    -xfs_dir_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp)
    -{
    -	xfs_dir_leafblock_t *leaf;
    -	xfs_dir_leaf_hdr_t *hdr;
    -	xfs_inode_t *dp;
    -	xfs_dabuf_t *bp;
    -	int retval;
    -
    -	dp = args->dp;
    -	ASSERT(dp != NULL);
    -	retval = xfs_da_get_buf(args->trans, dp, blkno, -1, &bp, XFS_DATA_FORK);
    -	if (retval)
    -		return retval;
    -	ASSERT(bp != NULL);
    -	leaf = bp->data;
    -	memset((char *)leaf, 0, XFS_LBSIZE(dp->i_mount));
    -	hdr = &leaf->hdr;
    -	hdr->info.magic = cpu_to_be16(XFS_DIR_LEAF_MAGIC);
    -	INT_SET(hdr->firstused, ARCH_CONVERT, XFS_LBSIZE(dp->i_mount));
    -	if (!hdr->firstused)
    -		INT_SET(hdr->firstused, ARCH_CONVERT, XFS_LBSIZE(dp->i_mount) - 1);
    -	INT_SET(hdr->freemap[0].base, ARCH_CONVERT, sizeof(xfs_dir_leaf_hdr_t));
    -	INT_SET(hdr->freemap[0].size, ARCH_CONVERT, INT_GET(hdr->firstused, ARCH_CONVERT) - INT_GET(hdr->freemap[0].base, ARCH_CONVERT));
    -
    -	xfs_da_log_buf(args->trans, bp, 0, XFS_LBSIZE(dp->i_mount) - 1);
    -
    -	*bpp = bp;
    -	return 0;
    -}
    -
    -/*
    - * Split the leaf node, rebalance, then add the new entry.
    - */
    -int
    -xfs_dir_leaf_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk,
    -				  xfs_da_state_blk_t *newblk)
    -{
    -	xfs_dablk_t blkno;
    -	xfs_da_args_t *args;
    -	int error;
    -
    -	/*
    -	 * Allocate space for a new leaf node.
    -	 */
    -	args = state->args;
    -	ASSERT(args != NULL);
    -	ASSERT(oldblk->magic == XFS_DIR_LEAF_MAGIC);
    -	error = xfs_da_grow_inode(args, &blkno);
    -	if (error)
    -		return error;
    -	error = xfs_dir_leaf_create(args, blkno, &newblk->bp);
    -	if (error)
    -		return error;
    -	newblk->blkno = blkno;
    -	newblk->magic = XFS_DIR_LEAF_MAGIC;
    -
    -	/*
    -	 * Rebalance the entries across the two leaves.
    -	 */
    -	xfs_dir_leaf_rebalance(state, oldblk, newblk);
    -	error = xfs_da_blk_link(state, oldblk, newblk);
    -	if (error)
    -		return error;
    -
    -	/*
    -	 * Insert the new entry in the correct block.
    -	 */
    -	if (state->inleaf) {
    -		error = xfs_dir_leaf_add(oldblk->bp, args, oldblk->index);
    -	} else {
    -		error = xfs_dir_leaf_add(newblk->bp, args, newblk->index);
    -	}
    -
    -	/*
    -	 * Update last hashval in each block since we added the name.
    -	 */
    -	oldblk->hashval = xfs_dir_leaf_lasthash(oldblk->bp, NULL);
    -	newblk->hashval = xfs_dir_leaf_lasthash(newblk->bp, NULL);
    -	return error;
    -}
    -
    -/*
    - * Add a name to the leaf directory structure.
    - *
    - * Must take into account fragmented leaves and leaves where spacemap has
    - * lost some freespace information (ie: holes).
    - */
    -int
    -xfs_dir_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args, int index)
    -{
    -	xfs_dir_leafblock_t *leaf;
    -	xfs_dir_leaf_hdr_t *hdr;
    -	xfs_dir_leaf_map_t *map;
    -	int tablesize, entsize, sum, i, tmp, error;
    -
    -	leaf = bp->data;
    -	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
    -	ASSERT((index >= 0) && (index <= INT_GET(leaf->hdr.count, ARCH_CONVERT)));
    -	hdr = &leaf->hdr;
    -	entsize = XFS_DIR_LEAF_ENTSIZE_BYNAME(args->namelen);
    -
    -	/*
    -	 * Search through freemap for first-fit on new name length.
    -	 * (may need to figure in size of entry struct too)
    -	 */
    -	tablesize = (INT_GET(hdr->count, ARCH_CONVERT) + 1) * (uint)sizeof(xfs_dir_leaf_entry_t)
    -			+ (uint)sizeof(xfs_dir_leaf_hdr_t);
    -	map = &hdr->freemap[XFS_DIR_LEAF_MAPSIZE-1];
    -	for (sum = 0, i = XFS_DIR_LEAF_MAPSIZE-1; i >= 0; map--, i--) {
    -		if (tablesize > INT_GET(hdr->firstused, ARCH_CONVERT)) {
    -			sum += INT_GET(map->size, ARCH_CONVERT);
    -			continue;
    -		}
    -		if (!map->size)
    -			continue;	/* no space in this map */
    -		tmp = entsize;
    -		if (INT_GET(map->base, ARCH_CONVERT) < INT_GET(hdr->firstused, ARCH_CONVERT))
    -			tmp += (uint)sizeof(xfs_dir_leaf_entry_t);
    -		if (INT_GET(map->size, ARCH_CONVERT) >= tmp) {
    -			if (!args->justcheck)
    -				xfs_dir_leaf_add_work(bp, args, index, i);
    -			return 0;
    -		}
    -		sum += INT_GET(map->size, ARCH_CONVERT);
    -	}
    -
    -	/*
    -	 * If there are no holes in the address space of the block,
    -	 * and we don't have enough freespace, then compaction will do us
    -	 * no good and we should just give up.
    -	 */
    -	if (!hdr->holes && (sum < entsize))
    -		return XFS_ERROR(ENOSPC);
    -
    -	/*
    -	 * Compact the entries to coalesce free space.
    -	 * Pass the justcheck flag so the checking pass can return
    -	 * an error, without changing anything, if it won't fit.
    -	 */
    -	error = xfs_dir_leaf_compact(args->trans, bp,
    -			args->total == 0 ?
    -				entsize +
    -				(uint)sizeof(xfs_dir_leaf_entry_t) : 0,
    -			args->justcheck);
    -	if (error)
    -		return error;
    -	/*
    -	 * After compaction, the block is guaranteed to have only one
    -	 * free region, in freemap[0].  If it is not big enough, give up.
    -	 */
    -	if (INT_GET(hdr->freemap[0].size, ARCH_CONVERT) <
    -	    (entsize + (uint)sizeof(xfs_dir_leaf_entry_t)))
    -		return XFS_ERROR(ENOSPC);
    -
    -	if (!args->justcheck)
    -		xfs_dir_leaf_add_work(bp, args, index, 0);
    -	return 0;
    -}
    -
    -/*
    - * Add a name to a leaf directory structure.
    - */
    -STATIC void
    -xfs_dir_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int index,
    -		      int mapindex)
    -{
    -	xfs_dir_leafblock_t *leaf;
    -	xfs_dir_leaf_hdr_t *hdr;
    -	xfs_dir_leaf_entry_t *entry;
    -	xfs_dir_leaf_name_t *namest;
    -	xfs_dir_leaf_map_t *map;
    -	/* REFERENCED */
    -	xfs_mount_t *mp;
    -	int tmp, i;
    -
    -	leaf = bp->data;
    -	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
    -	hdr = &leaf->hdr;
    -	ASSERT((mapindex >= 0) && (mapindex < XFS_DIR_LEAF_MAPSIZE));
    -	ASSERT((index >= 0) && (index <= INT_GET(hdr->count, ARCH_CONVERT)));
    -
    -	/*
    -	 * Force open some space in the entry array and fill it in.
    -	 */
    -	entry = &leaf->entries[index];
    -	if (index < INT_GET(hdr->count, ARCH_CONVERT)) {
    -		tmp  = INT_GET(hdr->count, ARCH_CONVERT) - index;
    -		tmp *= (uint)sizeof(xfs_dir_leaf_entry_t);
    -		memmove(entry + 1, entry, tmp);
    -		xfs_da_log_buf(args->trans, bp,
    -		    XFS_DA_LOGRANGE(leaf, entry, tmp + (uint)sizeof(*entry)));
    -	}
    -	INT_MOD(hdr->count, ARCH_CONVERT, +1);
    -
    -	/*
    -	 * Allocate space for the new string (at the end of the run).
    -	 */
    -	map = &hdr->freemap[mapindex];
    -	mp = args->trans->t_mountp;
    -	ASSERT(INT_GET(map->base, ARCH_CONVERT) < XFS_LBSIZE(mp));
    -	ASSERT(INT_GET(map->size, ARCH_CONVERT) >= XFS_DIR_LEAF_ENTSIZE_BYNAME(args->namelen));
    -	ASSERT(INT_GET(map->size, ARCH_CONVERT) < XFS_LBSIZE(mp));
    -	INT_MOD(map->size, ARCH_CONVERT, -(XFS_DIR_LEAF_ENTSIZE_BYNAME(args->namelen)));
    -	INT_SET(entry->nameidx, ARCH_CONVERT, INT_GET(map->base, ARCH_CONVERT) + INT_GET(map->size, ARCH_CONVERT));
    -	INT_SET(entry->hashval, ARCH_CONVERT, args->hashval);
    -	entry->namelen = args->namelen;
    -	xfs_da_log_buf(args->trans, bp,
    -	    XFS_DA_LOGRANGE(leaf, entry, sizeof(*entry)));
    -
    -	/*
    -	 * Copy the string and inode number into the new space.
    -	 */
    -	namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT));
    -	XFS_DIR_SF_PUT_DIRINO(&args->inumber, &namest->inumber);
    -	memcpy(namest->name, args->name, args->namelen);
    -	xfs_da_log_buf(args->trans, bp,
    -	    XFS_DA_LOGRANGE(leaf, namest, XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry)));
    -
    -	/*
    -	 * Update the control info for this leaf node
    -	 */
    -	if (INT_GET(entry->nameidx, ARCH_CONVERT) < INT_GET(hdr->firstused, ARCH_CONVERT))
    -		INT_COPY(hdr->firstused, entry->nameidx, ARCH_CONVERT);
    -	ASSERT(INT_GET(hdr->firstused, ARCH_CONVERT) >= ((INT_GET(hdr->count, ARCH_CONVERT)*sizeof(*entry))+sizeof(*hdr)));
    -	tmp = (INT_GET(hdr->count, ARCH_CONVERT)-1) * (uint)sizeof(xfs_dir_leaf_entry_t)
    -			+ (uint)sizeof(xfs_dir_leaf_hdr_t);
    -	map = &hdr->freemap[0];
    -	for (i = 0; i < XFS_DIR_LEAF_MAPSIZE; map++, i++) {
    -		if (INT_GET(map->base, ARCH_CONVERT) == tmp) {
    -			INT_MOD(map->base, ARCH_CONVERT, (uint)sizeof(xfs_dir_leaf_entry_t));
    -			INT_MOD(map->size, ARCH_CONVERT, -((uint)sizeof(xfs_dir_leaf_entry_t)));
    -		}
    -	}
    -	INT_MOD(hdr->namebytes, ARCH_CONVERT, args->namelen);
    -	xfs_da_log_buf(args->trans, bp,
    -		XFS_DA_LOGRANGE(leaf, hdr, sizeof(*hdr)));
    -}
    -
    -/*
    - * Garbage collect a leaf directory block by copying it to a new buffer.
    - */
    -STATIC int
    -xfs_dir_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *bp, int musthave,
    -		     int justcheck)
    -{
    -	xfs_dir_leafblock_t *leaf_s, *leaf_d;
    -	xfs_dir_leaf_hdr_t *hdr_s, *hdr_d;
    -	xfs_mount_t *mp;
    -	char *tmpbuffer;
    -	char *tmpbuffer2=NULL;
    -	int rval;
    -	int lbsize;
    -
    -	mp = trans->t_mountp;
    -	lbsize = XFS_LBSIZE(mp);
    -	tmpbuffer = kmem_alloc(lbsize, KM_SLEEP);
    -	ASSERT(tmpbuffer != NULL);
    -	memcpy(tmpbuffer, bp->data, lbsize);
    -
    -	/*
    -	 * Make a second copy in case xfs_dir_leaf_moveents()
    -	 * below destroys the original.
    -	 */
    -	if (musthave || justcheck) {
    -		tmpbuffer2 = kmem_alloc(lbsize, KM_SLEEP);
    -		memcpy(tmpbuffer2, bp->data, lbsize);
    -	}
    -	memset(bp->data, 0, lbsize);
    -
    -	/*
    -	 * Copy basic information
    -	 */
    -	leaf_s = (xfs_dir_leafblock_t *)tmpbuffer;
    -	leaf_d = bp->data;
    -	hdr_s = &leaf_s->hdr;
    -	hdr_d = &leaf_d->hdr;
    -	hdr_d->info = hdr_s->info;	/* struct copy */
    -	INT_SET(hdr_d->firstused, ARCH_CONVERT, lbsize);
    -	if (!hdr_d->firstused)
    -		INT_SET(hdr_d->firstused, ARCH_CONVERT, lbsize - 1);
    -	hdr_d->namebytes = 0;
    -	hdr_d->count = 0;
    -	hdr_d->holes = 0;
    -	INT_SET(hdr_d->freemap[0].base, ARCH_CONVERT, sizeof(xfs_dir_leaf_hdr_t));
    -	INT_SET(hdr_d->freemap[0].size, ARCH_CONVERT, INT_GET(hdr_d->firstused, ARCH_CONVERT) - INT_GET(hdr_d->freemap[0].base, ARCH_CONVERT));
    -
    -	/*
    -	 * Copy all entry's in the same (sorted) order,
    -	 * but allocate filenames packed and in sequence.
    -	 * This changes the source (leaf_s) as well.
    -	 */
    -	xfs_dir_leaf_moveents(leaf_s, 0, leaf_d, 0, (int)INT_GET(hdr_s->count, ARCH_CONVERT), mp);
    -
    -	if (musthave && INT_GET(hdr_d->freemap[0].size, ARCH_CONVERT) < musthave)
    -		rval = XFS_ERROR(ENOSPC);
    -	else
    -		rval = 0;
    -
    -	if (justcheck || rval == ENOSPC) {
    -		ASSERT(tmpbuffer2);
    -		memcpy(bp->data, tmpbuffer2, lbsize);
    -	} else {
    -		xfs_da_log_buf(trans, bp, 0, lbsize - 1);
    -	}
    -
    -	kmem_free(tmpbuffer, lbsize);
    -	if (musthave || justcheck)
    -		kmem_free(tmpbuffer2, lbsize);
    -	return rval;
    -}
    -
    -/*
    - * Redistribute the directory entries between two leaf nodes,
    - * taking into account the size of the new entry.
    - *
    - * NOTE: if new block is empty, then it will get the upper half of old block.
    - */
    -STATIC void
    -xfs_dir_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
    -				      xfs_da_state_blk_t *blk2)
    -{
    -	xfs_da_state_blk_t *tmp_blk;
    -	xfs_dir_leafblock_t *leaf1, *leaf2;
    -	xfs_dir_leaf_hdr_t *hdr1, *hdr2;
    -	int count, totallen, max, space, swap;
    -
    -	/*
    -	 * Set up environment.
    -	 */
    -	ASSERT(blk1->magic == XFS_DIR_LEAF_MAGIC);
    -	ASSERT(blk2->magic == XFS_DIR_LEAF_MAGIC);
    -	leaf1 = blk1->bp->data;
    -	leaf2 = blk2->bp->data;
    -	ASSERT(be16_to_cpu(leaf1->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
    -	ASSERT(be16_to_cpu(leaf2->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
    -
    -	/*
    -	 * Check ordering of blocks, reverse if it makes things simpler.
    -	 */
    -	swap = 0;
    -	if (xfs_dir_leaf_order(blk1->bp, blk2->bp)) {
    -		tmp_blk = blk1;
    -		blk1 = blk2;
    -		blk2 = tmp_blk;
    -		leaf1 = blk1->bp->data;
    -		leaf2 = blk2->bp->data;
    -		swap = 1;
    -	}
    -	hdr1 = &leaf1->hdr;
    -	hdr2 = &leaf2->hdr;
    -
    -	/*
    -	 * Examine entries until we reduce the absolute difference in
    -	 * byte usage between the two blocks to a minimum.  Then get
    -	 * the direction to copy and the number of elements to move.
    -	 */
    -	state->inleaf = xfs_dir_leaf_figure_balance(state, blk1, blk2,
    -							   &count, &totallen);
    -	if (swap)
    -		state->inleaf = !state->inleaf;
    -
    -	/*
    -	 * Move any entries required from leaf to leaf:
    -	 */
    -	if (count < INT_GET(hdr1->count, ARCH_CONVERT)) {
    -		/*
    -		 * Figure the total bytes to be added to the destination leaf.
    -		 */
    -		count = INT_GET(hdr1->count, ARCH_CONVERT) - count;	/* number entries being moved */
    -		space  = INT_GET(hdr1->namebytes, ARCH_CONVERT) - totallen;
    -		space += count * ((uint)sizeof(xfs_dir_leaf_name_t)-1);
    -		space += count * (uint)sizeof(xfs_dir_leaf_entry_t);
    -
    -		/*
    -		 * leaf2 is the destination, compact it if it looks tight.
    -		 */
    -		max  = INT_GET(hdr2->firstused, ARCH_CONVERT) - (uint)sizeof(xfs_dir_leaf_hdr_t);
    -		max -= INT_GET(hdr2->count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t);
    -		if (space > max) {
    -			xfs_dir_leaf_compact(state->args->trans, blk2->bp,
    -								 0, 0);
    -		}
    -
    -		/*
    -		 * Move high entries from leaf1 to low end of leaf2.
    -		 */
    -		xfs_dir_leaf_moveents(leaf1, INT_GET(hdr1->count, ARCH_CONVERT) - count,
    -					     leaf2, 0, count, state->mp);
    -
    -		xfs_da_log_buf(state->args->trans, blk1->bp, 0,
    -						   state->blocksize-1);
    -		xfs_da_log_buf(state->args->trans, blk2->bp, 0,
    -						   state->blocksize-1);
    -
    -	} else if (count > INT_GET(hdr1->count, ARCH_CONVERT)) {
    -		/*
    -		 * Figure the total bytes to be added to the destination leaf.
    -		 */
    -		count -= INT_GET(hdr1->count, ARCH_CONVERT);		/* number entries being moved */
    -		space  = totallen - INT_GET(hdr1->namebytes, ARCH_CONVERT);
    -		space += count * ((uint)sizeof(xfs_dir_leaf_name_t)-1);
    -		space += count * (uint)sizeof(xfs_dir_leaf_entry_t);
    -
    -		/*
    -		 * leaf1 is the destination, compact it if it looks tight.
    -		 */
    -		max  = INT_GET(hdr1->firstused, ARCH_CONVERT) - (uint)sizeof(xfs_dir_leaf_hdr_t);
    -		max -= INT_GET(hdr1->count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t);
    -		if (space > max) {
    -			xfs_dir_leaf_compact(state->args->trans, blk1->bp,
    -								 0, 0);
    -		}
    -
    -		/*
    -		 * Move low entries from leaf2 to high end of leaf1.
    -		 */
    -		xfs_dir_leaf_moveents(leaf2, 0, leaf1, (int)INT_GET(hdr1->count, ARCH_CONVERT),
    -					     count, state->mp);
    -
    -		xfs_da_log_buf(state->args->trans, blk1->bp, 0,
    -						   state->blocksize-1);
    -		xfs_da_log_buf(state->args->trans, blk2->bp, 0,
    -						   state->blocksize-1);
    -	}
    -
    -	/*
    -	 * Copy out last hashval in each block for B-tree code.
    -	 */
    -	blk1->hashval = INT_GET(leaf1->entries[ INT_GET(leaf1->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT);
    -	blk2->hashval = INT_GET(leaf2->entries[ INT_GET(leaf2->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT);
    -
    -	/*
    -	 * Adjust the expected index for insertion.
    -	 * GROT: this doesn't work unless blk2 was originally empty.
    -	 */
    -	if (!state->inleaf) {
    -		blk2->index = blk1->index - INT_GET(leaf1->hdr.count, ARCH_CONVERT);
    -	}
    -}
    -
    -/*
    - * Examine entries until we reduce the absolute difference in
    - * byte usage between the two blocks to a minimum.
    - * GROT: Is this really necessary?  With other than a 512 byte blocksize,
    - * GROT: there will always be enough room in either block for a new entry.
    - * GROT: Do a double-split for this case?
    - */
    -STATIC int
    -xfs_dir_leaf_figure_balance(xfs_da_state_t *state,
    -					   xfs_da_state_blk_t *blk1,
    -					   xfs_da_state_blk_t *blk2,
    -					   int *countarg, int *namebytesarg)
    -{
    -	xfs_dir_leafblock_t *leaf1, *leaf2;
    -	xfs_dir_leaf_hdr_t *hdr1, *hdr2;
    -	xfs_dir_leaf_entry_t *entry;
    -	int count, max, totallen, half;
    -	int lastdelta, foundit, tmp;
    -
    -	/*
    -	 * Set up environment.
    -	 */
    -	leaf1 = blk1->bp->data;
    -	leaf2 = blk2->bp->data;
    -	hdr1 = &leaf1->hdr;
    -	hdr2 = &leaf2->hdr;
    -	foundit = 0;
    -	totallen = 0;
    -
    -	/*
    -	 * Examine entries until we reduce the absolute difference in
    -	 * byte usage between the two blocks to a minimum.
    -	 */
    -	max = INT_GET(hdr1->count, ARCH_CONVERT) + INT_GET(hdr2->count, ARCH_CONVERT);
    -	half  = (max+1) * (uint)(sizeof(*entry)+sizeof(xfs_dir_leaf_entry_t)-1);
    -	half += INT_GET(hdr1->namebytes, ARCH_CONVERT) + INT_GET(hdr2->namebytes, ARCH_CONVERT) + state->args->namelen;
    -	half /= 2;
    -	lastdelta = state->blocksize;
    -	entry = &leaf1->entries[0];
    -	for (count = 0; count < max; entry++, count++) {
    -
    -#define XFS_DIR_ABS(A)	(((A) < 0) ? -(A) : (A))
    -		/*
    -		 * The new entry is in the first block, account for it.
    -		 */
    -		if (count == blk1->index) {
    -			tmp = totallen + (uint)sizeof(*entry)
    -				+ XFS_DIR_LEAF_ENTSIZE_BYNAME(state->args->namelen);
    -			if (XFS_DIR_ABS(half - tmp) > lastdelta)
    -				break;
    -			lastdelta = XFS_DIR_ABS(half - tmp);
    -			totallen = tmp;
    -			foundit = 1;
    -		}
    -
    -		/*
    -		 * Wrap around into the second block if necessary.
    -		 */
    -		if (count == INT_GET(hdr1->count, ARCH_CONVERT)) {
    -			leaf1 = leaf2;
    -			entry = &leaf1->entries[0];
    -		}
    -
    -		/*
    -		 * Figure out if next leaf entry would be too much.
    -		 */
    -		tmp = totallen + (uint)sizeof(*entry)
    -				+ XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry);
    -		if (XFS_DIR_ABS(half - tmp) > lastdelta)
    -			break;
    -		lastdelta = XFS_DIR_ABS(half - tmp);
    -		totallen = tmp;
    -#undef XFS_DIR_ABS
    -	}
    -
    -	/*
    -	 * Calculate the number of namebytes that will end up in lower block.
    -	 * If new entry not in lower block, fix up the count.
    -	 */
    -	totallen -=
    -		count * (uint)(sizeof(*entry)+sizeof(xfs_dir_leaf_entry_t)-1);
    -	if (foundit) {
    -		totallen -= (sizeof(*entry)+sizeof(xfs_dir_leaf_entry_t)-1) +
    -			    state->args->namelen;
    -	}
    -
    -	*countarg = count;
    -	*namebytesarg = totallen;
    -	return foundit;
    -}
    -
    -/*========================================================================
    - * Routines used for shrinking the Btree.
    - *========================================================================*/
    -
    -/*
    - * Check a leaf block and its neighbors to see if the block should be
    - * collapsed into one or the other neighbor.  Always keep the block
    - * with the smaller block number.
    - * If the current block is over 50% full, don't try to join it, return 0.
    - * If the block is empty, fill in the state structure and return 2.
    - * If it can be collapsed, fill in the state structure and return 1.
    - * If nothing can be done, return 0.
    - */
    -int
    -xfs_dir_leaf_toosmall(xfs_da_state_t *state, int *action)
    -{
    -	xfs_dir_leafblock_t *leaf;
    -	xfs_da_state_blk_t *blk;
    -	xfs_da_blkinfo_t *info;
    -	int count, bytes, forward, error, retval, i;
    -	xfs_dablk_t blkno;
    -	xfs_dabuf_t *bp;
    -
    -	/*
    -	 * Check for the degenerate case of the block being over 50% full.
    -	 * If so, it's not worth even looking to see if we might be able
    -	 * to coalesce with a sibling.
    -	 */
    -	blk = &state->path.blk[ state->path.active-1 ];
    -	info = blk->bp->data;
    -	ASSERT(be16_to_cpu(info->magic) == XFS_DIR_LEAF_MAGIC);
    -	leaf = (xfs_dir_leafblock_t *)info;
    -	count = INT_GET(leaf->hdr.count, ARCH_CONVERT);
    -	bytes = (uint)sizeof(xfs_dir_leaf_hdr_t) +
    -		count * (uint)sizeof(xfs_dir_leaf_entry_t) +
    -		count * ((uint)sizeof(xfs_dir_leaf_name_t)-1) +
    -		INT_GET(leaf->hdr.namebytes, ARCH_CONVERT);
    -	if (bytes > (state->blocksize >> 1)) {
    -		*action = 0;	/* blk over 50%, don't try to join */
    -		return 0;
    -	}
    -
    -	/*
    -	 * Check for the degenerate case of the block being empty.
    -	 * If the block is empty, we'll simply delete it, no need to
    -	 * coalesce it with a sibling block.  We choose (arbitrarily)
    -	 * to merge with the forward block unless it is NULL.
    -	 */
    -	if (count == 0) {
    -		/*
    -		 * Make altpath point to the block we want to keep and
    -		 * path point to the block we want to drop (this one).
    -		 */
    -		forward = (info->forw != 0);
    -		memcpy(&state->altpath, &state->path, sizeof(state->path));
    -		error = xfs_da_path_shift(state, &state->altpath, forward,
    -						 0, &retval);
    -		if (error)
    -			return error;
    -		if (retval) {
    -			*action = 0;
    -		} else {
    -			*action = 2;
    -		}
    -		return 0;
    -	}
    -
    -	/*
    -	 * Examine each sibling block to see if we can coalesce with
    -	 * at least 25% free space to spare.  We need to figure out
    -	 * whether to merge with the forward or the backward block.
    -	 * We prefer coalescing with the lower numbered sibling so as
    -	 * to shrink a directory over time.
    -	 */
    -	forward = (be32_to_cpu(info->forw) < be32_to_cpu(info->back));	/* start with smaller blk num */
    -	for (i = 0; i < 2; forward = !forward, i++) {
    -		if (forward)
    -			blkno = be32_to_cpu(info->forw);
    -		else
    -			blkno = be32_to_cpu(info->back);
    -		if (blkno == 0)
    -			continue;
    -		error = xfs_da_read_buf(state->args->trans, state->args->dp,
    -							    blkno, -1, &bp,
    -							    XFS_DATA_FORK);
    -		if (error)
    -			return error;
    -		ASSERT(bp != NULL);
    -
    -		leaf = (xfs_dir_leafblock_t *)info;
    -		count  = INT_GET(leaf->hdr.count, ARCH_CONVERT);
    -		bytes  = state->blocksize - (state->blocksize>>2);
    -		bytes -= INT_GET(leaf->hdr.namebytes, ARCH_CONVERT);
    -		leaf = bp->data;
    -		ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
    -		count += INT_GET(leaf->hdr.count, ARCH_CONVERT);
    -		bytes -= INT_GET(leaf->hdr.namebytes, ARCH_CONVERT);
    -		bytes -= count * ((uint)sizeof(xfs_dir_leaf_name_t) - 1);
    -		bytes -= count * (uint)sizeof(xfs_dir_leaf_entry_t);
    -		bytes -= (uint)sizeof(xfs_dir_leaf_hdr_t);
    -		if (bytes >= 0)
    -			break;	/* fits with at least 25% to spare */
    -
    -		xfs_da_brelse(state->args->trans, bp);
    -	}
    -	if (i >= 2) {
    -		*action = 0;
    -		return 0;
    -	}
    -	xfs_da_buf_done(bp);
    -
    -	/*
    -	 * Make altpath point to the block we want to keep (the lower
    -	 * numbered block) and path point to the block we want to drop.
    -	 */
    -	memcpy(&state->altpath, &state->path, sizeof(state->path));
    -	if (blkno < blk->blkno) {
    -		error = xfs_da_path_shift(state, &state->altpath, forward,
    -						 0, &retval);
    -	} else {
    -		error = xfs_da_path_shift(state, &state->path, forward,
    -						 0, &retval);
    -	}
    -	if (error)
    -		return error;
    -	if (retval) {
    -		*action = 0;
    -	} else {
    -		*action = 1;
    -	}
    -	return 0;
    -}
    -
    -/*
    - * Remove a name from the leaf directory structure.
    - *
    - * Return 1 if leaf is less than 37% full, 0 if >= 37% full.
    - * If two leaves are 37% full, when combined they will leave 25% free.
    - */
    -int
    -xfs_dir_leaf_remove(xfs_trans_t *trans, xfs_dabuf_t *bp, int index)
    -{
    -	xfs_dir_leafblock_t *leaf;
    -	xfs_dir_leaf_hdr_t *hdr;
    -	xfs_dir_leaf_map_t *map;
    -	xfs_dir_leaf_entry_t *entry;
    -	xfs_dir_leaf_name_t *namest;
    -	int before, after, smallest, entsize;
    -	int tablesize, tmp, i;
    -	xfs_mount_t *mp;
    -
    -	leaf = bp->data;
    -	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
    -	hdr = &leaf->hdr;
    -	mp = trans->t_mountp;
    -	ASSERT((INT_GET(hdr->count, ARCH_CONVERT) > 0) && (INT_GET(hdr->count, ARCH_CONVERT) < (XFS_LBSIZE(mp)/8)));
    -	ASSERT((index >= 0) && (index < INT_GET(hdr->count, ARCH_CONVERT)));
    -	ASSERT(INT_GET(hdr->firstused, ARCH_CONVERT) >= ((INT_GET(hdr->count, ARCH_CONVERT)*sizeof(*entry))+sizeof(*hdr)));
    -	entry = &leaf->entries[index];
    -	ASSERT(INT_GET(entry->nameidx, ARCH_CONVERT) >= INT_GET(hdr->firstused, ARCH_CONVERT));
    -	ASSERT(INT_GET(entry->nameidx, ARCH_CONVERT) < XFS_LBSIZE(mp));
    -
    -	/*
    -	 * Scan through free region table:
    -	 *    check for adjacency of free'd entry with an existing one,
    -	 *    find smallest free region in case we need to replace it,
    -	 *    adjust any map that borders the entry table,
    -	 */
    -	tablesize = INT_GET(hdr->count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t)
    -			+ (uint)sizeof(xfs_dir_leaf_hdr_t);
    -	map = &hdr->freemap[0];
    -	tmp = INT_GET(map->size, ARCH_CONVERT);
    -	before = after = -1;
    -	smallest = XFS_DIR_LEAF_MAPSIZE - 1;
    -	entsize = XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry);
    -	for (i = 0; i < XFS_DIR_LEAF_MAPSIZE; map++, i++) {
    -		ASSERT(INT_GET(map->base, ARCH_CONVERT) < XFS_LBSIZE(mp));
    -		ASSERT(INT_GET(map->size, ARCH_CONVERT) < XFS_LBSIZE(mp));
    -		if (INT_GET(map->base, ARCH_CONVERT) == tablesize) {
    -			INT_MOD(map->base, ARCH_CONVERT, -((uint)sizeof(xfs_dir_leaf_entry_t)));
    -			INT_MOD(map->size, ARCH_CONVERT, (uint)sizeof(xfs_dir_leaf_entry_t));
    -		}
    -
    -		if ((INT_GET(map->base, ARCH_CONVERT) + INT_GET(map->size, ARCH_CONVERT)) == INT_GET(entry->nameidx, ARCH_CONVERT)) {
    -			before = i;
    -		} else if (INT_GET(map->base, ARCH_CONVERT) == (INT_GET(entry->nameidx, ARCH_CONVERT) + entsize)) {
    -			after = i;
    -		} else if (INT_GET(map->size, ARCH_CONVERT) < tmp) {
    -			tmp = INT_GET(map->size, ARCH_CONVERT);
    -			smallest = i;
    -		}
    -	}
    -
    -	/*
    -	 * Coalesce adjacent freemap regions,
    -	 * or replace the smallest region.
    -	 */
    -	if ((before >= 0) || (after >= 0)) {
    -		if ((before >= 0) && (after >= 0)) {
    -			map = &hdr->freemap[before];
    -			INT_MOD(map->size, ARCH_CONVERT, entsize);
    -			INT_MOD(map->size, ARCH_CONVERT, INT_GET(hdr->freemap[after].size, ARCH_CONVERT));
    -			hdr->freemap[after].base = 0;
    -			hdr->freemap[after].size = 0;
    -		} else if (before >= 0) {
    -			map = &hdr->freemap[before];
    -			INT_MOD(map->size, ARCH_CONVERT, entsize);
    -		} else {
    -			map = &hdr->freemap[after];
    -			INT_COPY(map->base, entry->nameidx, ARCH_CONVERT);
    -			INT_MOD(map->size, ARCH_CONVERT, entsize);
    -		}
    -	} else {
    -		/*
    -		 * Replace smallest region (if it is smaller than free'd entry)
    -		 */
    -		map = &hdr->freemap[smallest];
    -		if (INT_GET(map->size, ARCH_CONVERT) < entsize) {
    -			INT_COPY(map->base, entry->nameidx, ARCH_CONVERT);
    -			INT_SET(map->size, ARCH_CONVERT, entsize);
    -		}
    -	}
    -
    -	/*
    -	 * Did we remove the first entry?
    -	 */
    -	if (INT_GET(entry->nameidx, ARCH_CONVERT) == INT_GET(hdr->firstused, ARCH_CONVERT))
    -		smallest = 1;
    -	else
    -		smallest = 0;
    -
    -	/*
    -	 * Compress the remaining entries and zero out the removed stuff.
    -	 */
    -	namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT));
    -	memset((char *)namest, 0, entsize);
    -	xfs_da_log_buf(trans, bp, XFS_DA_LOGRANGE(leaf, namest, entsize));
    -
    -	INT_MOD(hdr->namebytes, ARCH_CONVERT, -(entry->namelen));
    -	tmp = (INT_GET(hdr->count, ARCH_CONVERT) - index) * (uint)sizeof(xfs_dir_leaf_entry_t);
    -	memmove(entry, entry + 1, tmp);
    -	INT_MOD(hdr->count, ARCH_CONVERT, -1);
    -	xfs_da_log_buf(trans, bp,
    -	    XFS_DA_LOGRANGE(leaf, entry, tmp + (uint)sizeof(*entry)));
    -	entry = &leaf->entries[INT_GET(hdr->count, ARCH_CONVERT)];
    -	memset((char *)entry, 0, sizeof(xfs_dir_leaf_entry_t));
    -
    -	/*
    -	 * If we removed the first entry, re-find the first used byte
    -	 * in the name area.  Note that if the entry was the "firstused",
    -	 * then we don't have a "hole" in our block resulting from
    -	 * removing the name.
    -	 */
    -	if (smallest) {
    -		tmp = XFS_LBSIZE(mp);
    -		entry = &leaf->entries[0];
    -		for (i = INT_GET(hdr->count, ARCH_CONVERT)-1; i >= 0; entry++, i--) {
    -			ASSERT(INT_GET(entry->nameidx, ARCH_CONVERT) >= INT_GET(hdr->firstused, ARCH_CONVERT));
    -			ASSERT(INT_GET(entry->nameidx, ARCH_CONVERT) < XFS_LBSIZE(mp));
    -			if (INT_GET(entry->nameidx, ARCH_CONVERT) < tmp)
    -				tmp = INT_GET(entry->nameidx, ARCH_CONVERT);
    -		}
    -		INT_SET(hdr->firstused, ARCH_CONVERT, tmp);
    -		if (!hdr->firstused)
    -			INT_SET(hdr->firstused, ARCH_CONVERT, tmp - 1);
    -	} else {
    -		hdr->holes = 1;		/* mark as needing compaction */
    -	}
    -
    -	xfs_da_log_buf(trans, bp, XFS_DA_LOGRANGE(leaf, hdr, sizeof(*hdr)));
    -
    -	/*
    -	 * Check if leaf is less than 50% full, caller may want to
    -	 * "join" the leaf with a sibling if so.
    -	 */
    -	tmp  = (uint)sizeof(xfs_dir_leaf_hdr_t);
    -	tmp += INT_GET(leaf->hdr.count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t);
    -	tmp += INT_GET(leaf->hdr.count, ARCH_CONVERT) * ((uint)sizeof(xfs_dir_leaf_name_t) - 1);
    -	tmp += INT_GET(leaf->hdr.namebytes, ARCH_CONVERT);
    -	if (tmp < mp->m_dir_magicpct)
    -		return 1;			/* leaf is < 37% full */
    -	return 0;
    -}
    -
    -/*
    - * Move all the directory entries from drop_leaf into save_leaf.
    - */
    -void
    -xfs_dir_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
    -				      xfs_da_state_blk_t *save_blk)
    -{
    -	xfs_dir_leafblock_t *drop_leaf, *save_leaf, *tmp_leaf;
    -	xfs_dir_leaf_hdr_t *drop_hdr, *save_hdr, *tmp_hdr;
    -	xfs_mount_t *mp;
    -	char *tmpbuffer;
    -
    -	/*
    -	 * Set up environment.
    -	 */
    -	mp = state->mp;
    -	ASSERT(drop_blk->magic == XFS_DIR_LEAF_MAGIC);
    -	ASSERT(save_blk->magic == XFS_DIR_LEAF_MAGIC);
    -	drop_leaf = drop_blk->bp->data;
    -	save_leaf = save_blk->bp->data;
    -	ASSERT(be16_to_cpu(drop_leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
    -	ASSERT(be16_to_cpu(save_leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
    -	drop_hdr = &drop_leaf->hdr;
    -	save_hdr = &save_leaf->hdr;
    -
    -	/*
    -	 * Save last hashval from dying block for later Btree fixup.
    -	 */
    -	drop_blk->hashval = INT_GET(drop_leaf->entries[ drop_leaf->hdr.count-1 ].hashval, ARCH_CONVERT);
    -
    -	/*
    -	 * Check if we need a temp buffer, or can we do it in place.
    -	 * Note that we don't check "leaf" for holes because we will
    -	 * always be dropping it, toosmall() decided that for us already.
    -	 */
    -	if (save_hdr->holes == 0) {
    -		/*
    -		 * dest leaf has no holes, so we add there.  May need
    -		 * to make some room in the entry array.
    -		 */
    -		if (xfs_dir_leaf_order(save_blk->bp, drop_blk->bp)) {
    -			xfs_dir_leaf_moveents(drop_leaf, 0, save_leaf, 0,
    -						 (int)INT_GET(drop_hdr->count, ARCH_CONVERT), mp);
    -		} else {
    -			xfs_dir_leaf_moveents(drop_leaf, 0,
    -					      save_leaf, INT_GET(save_hdr->count, ARCH_CONVERT),
    -					      (int)INT_GET(drop_hdr->count, ARCH_CONVERT), mp);
    -		}
    -	} else {
    -		/*
    -		 * Destination has holes, so we make a temporary copy
    -		 * of the leaf and add them both to that.
    -		 */
    -		tmpbuffer = kmem_alloc(state->blocksize, KM_SLEEP);
    -		ASSERT(tmpbuffer != NULL);
    -		memset(tmpbuffer, 0, state->blocksize);
    -		tmp_leaf = (xfs_dir_leafblock_t *)tmpbuffer;
    -		tmp_hdr = &tmp_leaf->hdr;
    -		tmp_hdr->info = save_hdr->info;	/* struct copy */
    -		tmp_hdr->count = 0;
    -		INT_SET(tmp_hdr->firstused, ARCH_CONVERT, state->blocksize);
    -		if (!tmp_hdr->firstused)
    -			INT_SET(tmp_hdr->firstused, ARCH_CONVERT, state->blocksize - 1);
    -		tmp_hdr->namebytes = 0;
    -		if (xfs_dir_leaf_order(save_blk->bp, drop_blk->bp)) {
    -			xfs_dir_leaf_moveents(drop_leaf, 0, tmp_leaf, 0,
    -						 (int)INT_GET(drop_hdr->count, ARCH_CONVERT), mp);
    -			xfs_dir_leaf_moveents(save_leaf, 0,
    -					      tmp_leaf, INT_GET(tmp_leaf->hdr.count, ARCH_CONVERT),
    -					      (int)INT_GET(save_hdr->count, ARCH_CONVERT), mp);
    -		} else {
    -			xfs_dir_leaf_moveents(save_leaf, 0, tmp_leaf, 0,
    -						 (int)INT_GET(save_hdr->count, ARCH_CONVERT), mp);
    -			xfs_dir_leaf_moveents(drop_leaf, 0,
    -					      tmp_leaf, INT_GET(tmp_leaf->hdr.count, ARCH_CONVERT),
    -					      (int)INT_GET(drop_hdr->count, ARCH_CONVERT), mp);
    -		}
    -		memcpy(save_leaf, tmp_leaf, state->blocksize);
    -		kmem_free(tmpbuffer, state->blocksize);
    -	}
    -
    -	xfs_da_log_buf(state->args->trans, save_blk->bp, 0,
    -					   state->blocksize - 1);
    -
    -	/*
    -	 * Copy out last hashval in each block for B-tree code.
    -	 */
    -	save_blk->hashval = INT_GET(save_leaf->entries[ INT_GET(save_leaf->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT);
    -}
    -
    -/*========================================================================
    - * Routines used for finding things in the Btree.
    - *========================================================================*/
    -
    -/*
    - * Look up a name in a leaf directory structure.
    - * This is the internal routine, it uses the caller's buffer.
    - *
    - * Note that duplicate keys are allowed, but only check within the
    - * current leaf node.  The Btree code must check in adjacent leaf nodes.
    - *
    - * Return in *index the index into the entry[] array of either the found
    - * entry, or where the entry should have been (insert before that entry).
    - *
    - * Don't change the args->inumber unless we find the filename.
    - */
    -int
    -xfs_dir_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args, int *index)
    -{
    -	xfs_dir_leafblock_t *leaf;
    -	xfs_dir_leaf_entry_t *entry;
    -	xfs_dir_leaf_name_t *namest;
    -	int probe, span;
    -	xfs_dahash_t hashval;
    -
    -	leaf = bp->data;
    -	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
    -	ASSERT(INT_GET(leaf->hdr.count, ARCH_CONVERT) < (XFS_LBSIZE(args->dp->i_mount)/8));
    -
    -	/*
    -	 * Binary search.  (note: small blocks will skip this loop)
    -	 */
    -	hashval = args->hashval;
    -	probe = span = INT_GET(leaf->hdr.count, ARCH_CONVERT) / 2;
    -	for (entry = &leaf->entries[probe]; span > 4;
    -		   entry = &leaf->entries[probe]) {
    -		span /= 2;
    -		if (INT_GET(entry->hashval, ARCH_CONVERT) < hashval)
    -			probe += span;
    -		else if (INT_GET(entry->hashval, ARCH_CONVERT) > hashval)
    -			probe -= span;
    -		else
    -			break;
    -	}
    -	ASSERT((probe >= 0) && \
    -	       ((!leaf->hdr.count) || (probe < INT_GET(leaf->hdr.count, ARCH_CONVERT))));
    -	ASSERT((span <= 4) || (INT_GET(entry->hashval, ARCH_CONVERT) == hashval));
    -
    -	/*
    -	 * Since we may have duplicate hashval's, find the first matching
    -	 * hashval in the leaf.
    -	 */
    -	while ((probe > 0) && (INT_GET(entry->hashval, ARCH_CONVERT) >= hashval)) {
    -		entry--;
    -		probe--;
    -	}
    -	while ((probe < INT_GET(leaf->hdr.count, ARCH_CONVERT)) && (INT_GET(entry->hashval, ARCH_CONVERT) < hashval)) {
    -		entry++;
    -		probe++;
    -	}
    -	if ((probe == INT_GET(leaf->hdr.count, ARCH_CONVERT)) || (INT_GET(entry->hashval, ARCH_CONVERT) != hashval)) {
    -		*index = probe;
    -		ASSERT(args->oknoent);
    -		return XFS_ERROR(ENOENT);
    -	}
    -
    -	/*
    -	 * Duplicate keys may be present, so search all of them for a match.
    -	 */
    -	while ((probe < INT_GET(leaf->hdr.count, ARCH_CONVERT)) && (INT_GET(entry->hashval, ARCH_CONVERT) == hashval)) {
    -		namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT));
    -		if (entry->namelen == args->namelen &&
    -		    namest->name[0] == args->name[0] &&
    -		    memcmp(args->name, namest->name, args->namelen) == 0) {
    -			XFS_DIR_SF_GET_DIRINO(&namest->inumber, &args->inumber);
    -			*index = probe;
    -			return XFS_ERROR(EEXIST);
    -		}
    -		entry++;
    -		probe++;
    -	}
    -	*index = probe;
    -	ASSERT(probe == INT_GET(leaf->hdr.count, ARCH_CONVERT) || args->oknoent);
    -	return XFS_ERROR(ENOENT);
    -}
    -
    -/*========================================================================
    - * Utility routines.
    - *========================================================================*/
    -
    -/*
    - * Move the indicated entries from one leaf to another.
    - * NOTE: this routine modifies both source and destination leaves.
    - */
    -/* ARGSUSED */
    -STATIC void
    -xfs_dir_leaf_moveents(xfs_dir_leafblock_t *leaf_s, int start_s,
    -		      xfs_dir_leafblock_t *leaf_d, int start_d,
    -		      int count, xfs_mount_t *mp)
    -{
    -	xfs_dir_leaf_hdr_t *hdr_s, *hdr_d;
    -	xfs_dir_leaf_entry_t *entry_s, *entry_d;
    -	int tmp, i;
    -
    -	/*
    -	 * Check for nothing to do.
    -	 */
    -	if (count == 0)
    -		return;
    -
    -	/*
    -	 * Set up environment.
    -	 */
    -	ASSERT(be16_to_cpu(leaf_s->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
    -	ASSERT(be16_to_cpu(leaf_d->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
    -	hdr_s = &leaf_s->hdr;
    -	hdr_d = &leaf_d->hdr;
    -	ASSERT((INT_GET(hdr_s->count, ARCH_CONVERT) > 0) && (INT_GET(hdr_s->count, ARCH_CONVERT) < (XFS_LBSIZE(mp)/8)));
    -	ASSERT(INT_GET(hdr_s->firstused, ARCH_CONVERT) >=
    -		((INT_GET(hdr_s->count, ARCH_CONVERT)*sizeof(*entry_s))+sizeof(*hdr_s)));
    -	ASSERT(INT_GET(hdr_d->count, ARCH_CONVERT) < (XFS_LBSIZE(mp)/8));
    -	ASSERT(INT_GET(hdr_d->firstused, ARCH_CONVERT) >=
    -		((INT_GET(hdr_d->count, ARCH_CONVERT)*sizeof(*entry_d))+sizeof(*hdr_d)));
    -
    -	ASSERT(start_s < INT_GET(hdr_s->count, ARCH_CONVERT));
    -	ASSERT(start_d <= INT_GET(hdr_d->count, ARCH_CONVERT));
    -	ASSERT(count <= INT_GET(hdr_s->count, ARCH_CONVERT));
    -
    -	/*
    -	 * Move the entries in the destination leaf up to make a hole?
    -	 */
    -	if (start_d < INT_GET(hdr_d->count, ARCH_CONVERT)) {
    -		tmp  = INT_GET(hdr_d->count, ARCH_CONVERT) - start_d;
    -		tmp *= (uint)sizeof(xfs_dir_leaf_entry_t);
    -		entry_s = &leaf_d->entries[start_d];
    -		entry_d = &leaf_d->entries[start_d + count];
    -		memcpy(entry_d, entry_s, tmp);
    -	}
    -
    -	/*
    -	 * Copy all entry's in the same (sorted) order,
    -	 * but allocate filenames packed and in sequence.
    -	 */
    -	entry_s = &leaf_s->entries[start_s];
    -	entry_d = &leaf_d->entries[start_d];
    -	for (i = 0; i < count; entry_s++, entry_d++, i++) {
    -		ASSERT(INT_GET(entry_s->nameidx, ARCH_CONVERT) >= INT_GET(hdr_s->firstused, ARCH_CONVERT));
    -		tmp = XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry_s);
    -		INT_MOD(hdr_d->firstused, ARCH_CONVERT, -(tmp));
    -		entry_d->hashval = entry_s->hashval; /* INT_: direct copy */
    -		INT_COPY(entry_d->nameidx, hdr_d->firstused, ARCH_CONVERT);
    -		entry_d->namelen = entry_s->namelen;
    -		ASSERT(INT_GET(entry_d->nameidx, ARCH_CONVERT) + tmp <= XFS_LBSIZE(mp));
    -		memcpy(XFS_DIR_LEAF_NAMESTRUCT(leaf_d, INT_GET(entry_d->nameidx, ARCH_CONVERT)),
    -		       XFS_DIR_LEAF_NAMESTRUCT(leaf_s, INT_GET(entry_s->nameidx, ARCH_CONVERT)), tmp);
    -		ASSERT(INT_GET(entry_s->nameidx, ARCH_CONVERT) + tmp <= XFS_LBSIZE(mp));
    -		memset((char *)XFS_DIR_LEAF_NAMESTRUCT(leaf_s, INT_GET(entry_s->nameidx, ARCH_CONVERT)),
    -		      0, tmp);
    -		INT_MOD(hdr_s->namebytes, ARCH_CONVERT, -(entry_d->namelen));
    -		INT_MOD(hdr_d->namebytes, ARCH_CONVERT, entry_d->namelen);
    -		INT_MOD(hdr_s->count, ARCH_CONVERT, -1);
    -		INT_MOD(hdr_d->count, ARCH_CONVERT, +1);
    -		tmp  = INT_GET(hdr_d->count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t)
    -				+ (uint)sizeof(xfs_dir_leaf_hdr_t);
    -		ASSERT(INT_GET(hdr_d->firstused, ARCH_CONVERT) >= tmp);
    -
    -	}
    -
    -	/*
    -	 * Zero out the entries we just copied.
    -	 */
    -	if (start_s == INT_GET(hdr_s->count, ARCH_CONVERT)) {
    -		tmp = count * (uint)sizeof(xfs_dir_leaf_entry_t);
    -		entry_s = &leaf_s->entries[start_s];
    -		ASSERT((char *)entry_s + tmp <= (char *)leaf_s + XFS_LBSIZE(mp));
    -		memset((char *)entry_s, 0, tmp);
    -	} else {
    -		/*
    -		 * Move the remaining entries down to fill the hole,
    -		 * then zero the entries at the top.
    -		 */
    -		tmp  = INT_GET(hdr_s->count, ARCH_CONVERT) - count;
    -		tmp *= (uint)sizeof(xfs_dir_leaf_entry_t);
    -		entry_s = &leaf_s->entries[start_s + count];
    -		entry_d = &leaf_s->entries[start_s];
    -		memcpy(entry_d, entry_s, tmp);
    -
    -		tmp = count * (uint)sizeof(xfs_dir_leaf_entry_t);
    -		entry_s = &leaf_s->entries[INT_GET(hdr_s->count, ARCH_CONVERT)];
    -		ASSERT((char *)entry_s + tmp <= (char *)leaf_s + XFS_LBSIZE(mp));
    -		memset((char *)entry_s, 0, tmp);
    -	}
    -
    -	/*
    -	 * Fill in the freemap information
    -	 */
    -	INT_SET(hdr_d->freemap[0].base, ARCH_CONVERT, (uint)sizeof(xfs_dir_leaf_hdr_t));
    -	INT_MOD(hdr_d->freemap[0].base, ARCH_CONVERT, INT_GET(hdr_d->count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t));
    -	INT_SET(hdr_d->freemap[0].size, ARCH_CONVERT, INT_GET(hdr_d->firstused, ARCH_CONVERT) - INT_GET(hdr_d->freemap[0].base, ARCH_CONVERT));
    -	INT_SET(hdr_d->freemap[1].base, ARCH_CONVERT, (hdr_d->freemap[2].base = 0));
    -	INT_SET(hdr_d->freemap[1].size, ARCH_CONVERT, (hdr_d->freemap[2].size = 0));
    -	hdr_s->holes = 1;	/* leaf may not be compact */
    -}
    -
    -/*
    - * Compare two leaf blocks "order".
    - */
    -int
    -xfs_dir_leaf_order(xfs_dabuf_t *leaf1_bp, xfs_dabuf_t *leaf2_bp)
    -{
    -	xfs_dir_leafblock_t *leaf1, *leaf2;
    -
    -	leaf1 = leaf1_bp->data;
    -	leaf2 = leaf2_bp->data;
    -	ASSERT((be16_to_cpu(leaf1->hdr.info.magic) == XFS_DIR_LEAF_MAGIC) &&
    -	       (be16_to_cpu(leaf2->hdr.info.magic) == XFS_DIR_LEAF_MAGIC));
    -	if ((INT_GET(leaf1->hdr.count, ARCH_CONVERT) > 0) && (INT_GET(leaf2->hdr.count, ARCH_CONVERT) > 0) &&
    -	    ((INT_GET(leaf2->entries[ 0 ].hashval, ARCH_CONVERT) <
    -	      INT_GET(leaf1->entries[ 0 ].hashval, ARCH_CONVERT)) ||
    -	     (INT_GET(leaf2->entries[ INT_GET(leaf2->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT) <
    -	      INT_GET(leaf1->entries[ INT_GET(leaf1->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT)))) {
    -		return 1;
    -	}
    -	return 0;
    -}
    -
    -/*
    - * Pick up the last hashvalue from a leaf block.
    - */
    -xfs_dahash_t
    -xfs_dir_leaf_lasthash(xfs_dabuf_t *bp, int *count)
    -{
    -	xfs_dir_leafblock_t *leaf;
    -
    -	leaf = bp->data;
    -	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
    -	if (count)
    -		*count = INT_GET(leaf->hdr.count, ARCH_CONVERT);
    -	if (!leaf->hdr.count)
    -		return(0);
    -	return(INT_GET(leaf->entries[ INT_GET(leaf->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT));
    -}
    -
    -/*
    - * Copy out directory entries for getdents(), for leaf directories.
    - */
    -int
    -xfs_dir_leaf_getdents_int(
    -	xfs_dabuf_t	*bp,
    -	xfs_inode_t	*dp,
    -	xfs_dablk_t	bno,
    -	uio_t		*uio,
    -	int		*eobp,
    -	xfs_dirent_t	*dbp,
    -	xfs_dir_put_t	put,
    -	xfs_daddr_t		nextda)
    -{
    -	xfs_dir_leafblock_t	*leaf;
    -	xfs_dir_leaf_entry_t	*entry;
    -	xfs_dir_leaf_name_t	*namest;
    -	int			entno, want_entno, i, nextentno;
    -	xfs_mount_t		*mp;
    -	xfs_dahash_t		cookhash;
    -	xfs_dahash_t		nexthash = 0;
    -#if (BITS_PER_LONG == 32)
    -	xfs_dahash_t		lasthash = XFS_DA_MAXHASH;
    -#endif
    -	xfs_dir_put_args_t	p;
    -
    -	mp = dp->i_mount;
    -	leaf = bp->data;
    -	if (be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR_LEAF_MAGIC) {
    -		*eobp = 1;
    -		return XFS_ERROR(ENOENT);	/* XXX wrong code */
    -	}
    -
    -	want_entno = XFS_DA_COOKIE_ENTRY(mp, uio->uio_offset);
    -
    -	cookhash = XFS_DA_COOKIE_HASH(mp, uio->uio_offset);
    -
    -	xfs_dir_trace_g_dul("leaf: start", dp, uio, leaf);
    -
    -	/*
    -	 * Re-find our place.
    -	 */
    -	for (i = entno = 0, entry = &leaf->entries[0];
    -		     i < INT_GET(leaf->hdr.count, ARCH_CONVERT);
    -			     entry++, i++) {
    -
    -		namest = XFS_DIR_LEAF_NAMESTRUCT(leaf,
    -				    INT_GET(entry->nameidx, ARCH_CONVERT));
    -
    -		if (unlikely(
    -		    ((char *)namest < (char *)leaf) ||
    -		    ((char *)namest >= (char *)leaf + XFS_LBSIZE(mp)))) {
    -			XFS_CORRUPTION_ERROR("xfs_dir_leaf_getdents_int(1)",
    -					     XFS_ERRLEVEL_LOW, mp, leaf);
    -			xfs_dir_trace_g_du("leaf: corrupted", dp, uio);
    -			return XFS_ERROR(EFSCORRUPTED);
    -		}
    -		if (INT_GET(entry->hashval, ARCH_CONVERT) >= cookhash) {
    -			if (   entno < want_entno
    -			    && INT_GET(entry->hashval, ARCH_CONVERT)
    -							== cookhash) {
    -				/*
    -				 * Trying to get to a particular offset in a
    -				 * run of equal-hashval entries.
    -				 */
    -				entno++;
    -			} else if (   want_entno > 0
    -				   && entno == want_entno
    -				   && INT_GET(entry->hashval, ARCH_CONVERT)
    -							== cookhash) {
    -				break;
    -			} else {
    -				entno = 0;
    -				break;
    -			}
    -		}
    -	}
    -
    -	if (i == INT_GET(leaf->hdr.count, ARCH_CONVERT)) {
    -		xfs_dir_trace_g_du("leaf: hash not found", dp, uio);
    -		if (!leaf->hdr.info.forw)
    -			uio->uio_offset =
    -				XFS_DA_MAKE_COOKIE(mp, 0, 0, XFS_DA_MAXHASH);
    -		/*
    -		 * Don't set uio_offset if there's another block:
    -		 * the node code will be setting uio_offset anyway.
    -		 */
    -		*eobp = 0;
    -		return 0;
    -	}
    -	xfs_dir_trace_g_due("leaf: hash found", dp, uio, entry);
    -
    -	p.dbp = dbp;
    -	p.put = put;
    -	p.uio = uio;
    -
    -	/*
    -	 * We're synchronized, start copying entries out to the user.
    -	 */
    -	for (; entno >= 0 && i < INT_GET(leaf->hdr.count, ARCH_CONVERT);
    -			     entry++, i++, (entno = nextentno)) {
    -		int lastresid=0, retval;
    -		xfs_dircook_t lastoffset;
    -		xfs_dahash_t thishash;
    -
    -		/*
    -		 * Check for a damaged directory leaf block and pick up
    -		 * the inode number from this entry.
    -		 */
    -		namest = XFS_DIR_LEAF_NAMESTRUCT(leaf,
    -				    INT_GET(entry->nameidx, ARCH_CONVERT));
    -
    -		if (unlikely(
    -		    ((char *)namest < (char *)leaf) ||
    -		    ((char *)namest >= (char *)leaf + XFS_LBSIZE(mp)))) {
    -			XFS_CORRUPTION_ERROR("xfs_dir_leaf_getdents_int(2)",
    -					     XFS_ERRLEVEL_LOW, mp, leaf);
    -			xfs_dir_trace_g_du("leaf: corrupted", dp, uio);
    -			return XFS_ERROR(EFSCORRUPTED);
    -		}
    -
    -		xfs_dir_trace_g_duc("leaf: middle cookie  ",
    -						   dp, uio, p.cook.o);
    -
    -		if (i < (INT_GET(leaf->hdr.count, ARCH_CONVERT) - 1)) {
    -			nexthash = INT_GET(entry[1].hashval, ARCH_CONVERT);
    -
    -			if (nexthash == INT_GET(entry->hashval, ARCH_CONVERT))
    -				nextentno = entno + 1;
    -			else
    -				nextentno = 0;
    -			XFS_PUT_COOKIE(p.cook, mp, bno, nextentno, nexthash);
    -			xfs_dir_trace_g_duc("leaf: middle cookie  ",
    -						   dp, uio, p.cook.o);
    -
    -		} else if ((thishash = be32_to_cpu(leaf->hdr.info.forw))) {
    -			xfs_dabuf_t *bp2;
    -			xfs_dir_leafblock_t *leaf2;
    -
    -			ASSERT(nextda != -1);
    -
    -			retval = xfs_da_read_buf(dp->i_transp, dp, thishash,
    -						 nextda, &bp2, XFS_DATA_FORK);
    -			if (retval)
    -				return retval;
    -
    -			ASSERT(bp2 != NULL);
    -
    -			leaf2 = bp2->data;
    -
    -			if (unlikely(
    -			       (be16_to_cpu(leaf2->hdr.info.magic)
    -						!= XFS_DIR_LEAF_MAGIC)
    -			    || (be32_to_cpu(leaf2->hdr.info.back)
    -						!= bno))) {	/* GROT */
    -				XFS_CORRUPTION_ERROR("xfs_dir_leaf_getdents_int(3)",
    -						     XFS_ERRLEVEL_LOW, mp,
    -						     leaf2);
    -				xfs_da_brelse(dp->i_transp, bp2);
    -
    -				return XFS_ERROR(EFSCORRUPTED);
    -			}
    -
    -			nexthash = INT_GET(leaf2->entries[0].hashval,
    -								ARCH_CONVERT);
    -			nextentno = -1;
    -			XFS_PUT_COOKIE(p.cook, mp, thishash, 0, nexthash);
    -			xfs_da_brelse(dp->i_transp, bp2);
    -			xfs_dir_trace_g_duc("leaf: next blk cookie",
    -						   dp, uio, p.cook.o);
    -		} else {
    -			nextentno = -1;
    -			XFS_PUT_COOKIE(p.cook, mp, 0, 0, XFS_DA_MAXHASH);
    -		}
    -
    -		/*
    -		 * Save off the cookie so we can fall back should the
    -		 * 'put' into the outgoing buffer fails.  To handle a run
    -		 * of equal-hashvals, the off_t structure on 64bit
    -		 * builds has entno built into the cookie to ID the
    -		 * entry.  On 32bit builds, we only have space for the
    -		 * hashval so we can't ID specific entries within a group
    -		 * of same hashval entries.   For this, lastoffset is set
    -		 * to the first in the run of equal hashvals so we don't
    -		 * include any entries unless we can include all entries
    -		 * that share the same hashval.  Hopefully the buffer
    -		 * provided is big enough to handle it (see pv763517).
    -		 */
    -#if (BITS_PER_LONG == 32)
    -		if ((thishash = INT_GET(entry->hashval, ARCH_CONVERT))
    -								!= lasthash) {
    -			XFS_PUT_COOKIE(lastoffset, mp, bno, entno, thishash);
    -			lastresid = uio->uio_resid;
    -			lasthash = thishash;
    -		} else {
    -			xfs_dir_trace_g_duc("leaf: DUP COOKIES, skipped",
    -						   dp, uio, p.cook.o);
    -		}
    -#else
    -		thishash = INT_GET(entry->hashval, ARCH_CONVERT);
    -		XFS_PUT_COOKIE(lastoffset, mp, bno, entno, thishash);
    -		lastresid = uio->uio_resid;
    -#endif /* BITS_PER_LONG == 32 */
    -
    -		/*
    -		 * Put the current entry into the outgoing buffer.  If we fail
    -		 * then restore the UIO to the first entry in the current
    -		 * run of equal-hashval entries (probably one 1 entry long).
    -		 */
    -		p.ino = XFS_GET_DIR_INO8(namest->inumber);
    -#if XFS_BIG_INUMS
    -		p.ino += mp->m_inoadd;
    -#endif
    -		p.name = (char *)namest->name;
    -		p.namelen = entry->namelen;
    -
    -		retval = p.put(&p);
    -
    -		if (!p.done) {
    -			uio->uio_offset = lastoffset.o;
    -			uio->uio_resid = lastresid;
    -
    -			*eobp = 1;
    -
    -			xfs_dir_trace_g_du("leaf: E-O-B", dp, uio);
    -
    -			return retval;
    -		}
    -	}
    -
    -	uio->uio_offset = p.cook.o;
    -
    -	*eobp = 0;
    -
    -	xfs_dir_trace_g_du("leaf: E-O-F", dp, uio);
    -
    -	return 0;
    -}
    -
    -/*
    - * Format a dirent64 structure and copy it out the user's buffer.
    - */
    -int
    -xfs_dir_put_dirent64_direct(xfs_dir_put_args_t *pa)
    -{
    -	iovec_t *iovp;
    -	int reclen, namelen;
    -	xfs_dirent_t *idbp;
    -	uio_t *uio;
    -
    -	namelen = pa->namelen;
    -	reclen = DIRENTSIZE(namelen);
    -	uio = pa->uio;
    -	if (reclen > uio->uio_resid) {
    -		pa->done = 0;
    -		return 0;
    -	}
    -	iovp = uio->uio_iov;
    -	idbp = (xfs_dirent_t *)iovp->iov_base;
    -	iovp->iov_base = (char *)idbp + reclen;
    -	iovp->iov_len -= reclen;
    -	uio->uio_resid -= reclen;
    -	idbp->d_reclen = reclen;
    -	idbp->d_ino = pa->ino;
    -	idbp->d_off = pa->cook.o;
    -	idbp->d_name[namelen] = '\0';
    -	pa->done = 1;
    -	memcpy(idbp->d_name, pa->name, namelen);
    -	return 0;
    -}
    -
    -/*
    - * Format a dirent64 structure and copy it out the user's buffer.
    - */
    -int
    -xfs_dir_put_dirent64_uio(xfs_dir_put_args_t *pa)
    -{
    -	int		retval, reclen, namelen;
    -	xfs_dirent_t	*idbp;
    -	uio_t		*uio;
    -
    -	namelen = pa->namelen;
    -	reclen = DIRENTSIZE(namelen);
    -	uio = pa->uio;
    -	if (reclen > uio->uio_resid) {
    -		pa->done = 0;
    -		return 0;
    -	}
    -	idbp = pa->dbp;
    -	idbp->d_reclen = reclen;
    -	idbp->d_ino = pa->ino;
    -	idbp->d_off = pa->cook.o;
    -	idbp->d_name[namelen] = '\0';
    -	memcpy(idbp->d_name, pa->name, namelen);
    -	retval = uio_read((caddr_t)idbp, reclen, uio);
    -	pa->done = (retval == 0);
    -	return retval;
    -}
    -
    -
    diff --git a/sys/gnu/fs/xfs/xfs_dir_leaf.h b/sys/gnu/fs/xfs/xfs_dir_leaf.h
    deleted file mode 100644
    index eb8cd9a4667..00000000000
    --- a/sys/gnu/fs/xfs/xfs_dir_leaf.h
    +++ /dev/null
    @@ -1,231 +0,0 @@
    -/*
    - * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_DIR_LEAF_H__
    -#define	__XFS_DIR_LEAF_H__
    -
    -/*
    - * Directory layout, internal structure, access macros, etc.
    - *
    - * Large directories are structured around Btrees where all the data
    - * elements are in the leaf nodes.  Filenames are hashed into an int,
    - * then that int is used as the index into the Btree.  Since the hashval
    - * of a filename may not be unique, we may have duplicate keys.  The
    - * internal links in the Btree are logical block offsets into the file.
    - */
    -
    -struct uio;
    -struct xfs_bmap_free;
    -struct xfs_dabuf;
    -struct xfs_da_args;
    -struct xfs_da_state;
    -struct xfs_da_state_blk;
    -struct xfs_dir_put_args;
    -struct xfs_inode;
    -struct xfs_mount;
    -struct xfs_trans;
    -
    -/*========================================================================
    - * Directory Structure when equal to XFS_LBSIZE(mp) bytes.
    - *========================================================================*/
    -
    -/*
    - * This is the structure of the leaf nodes in the Btree.
    - *
    - * Struct leaf_entry's are packed from the top.  Names grow from the bottom
    - * but are not packed.  The freemap contains run-length-encoded entries
    - * for the free bytes after the leaf_entry's, but only the N largest such,
    - * smaller runs are dropped.  When the freemap doesn't show enough space
    - * for an allocation, we compact the namelist area and try again.  If we
    - * still don't have enough space, then we have to split the block.
    - *
    - * Since we have duplicate hash keys, for each key that matches, compare
    - * the actual string.  The root and intermediate node search always takes
    - * the first-in-the-block key match found, so we should only have to work
    - * "forw"ard.  If none matches, continue with the "forw"ard leaf nodes
    - * until the hash key changes or the filename is found.
    - *
    - * The parent directory and the self-pointer are explicitly represented
    - * (ie: there are entries for "." and "..").
    - *
    - * Note that the count being a __uint16_t limits us to something like a
    - * blocksize of 1.3MB in the face of worst case (short) filenames.
    - */
    -#define XFS_DIR_LEAF_MAPSIZE	3	/* how many freespace slots */
    -
    -typedef struct xfs_dir_leaf_map {	/* RLE map of free bytes */
    -	__uint16_t	base;	 	/* base of free region */
    -	__uint16_t	size; 		/* run length of free region */
    -} xfs_dir_leaf_map_t;
    -
    -typedef struct xfs_dir_leaf_hdr {	/* constant-structure header block */
    -	xfs_da_blkinfo_t info;		/* block type, links, etc. */
    -	__uint16_t	count;		/* count of active leaf_entry's */
    -	__uint16_t	namebytes;	/* num bytes of name strings stored */
    -	__uint16_t	firstused;	/* first used byte in name area */
    -	__uint8_t	holes;		/* != 0 if blk needs compaction */
    -	__uint8_t	pad1;
    -	xfs_dir_leaf_map_t freemap[XFS_DIR_LEAF_MAPSIZE];
    -} xfs_dir_leaf_hdr_t;
    -
    -typedef struct xfs_dir_leaf_entry {	/* sorted on key, not name */
    -	xfs_dahash_t	hashval;	/* hash value of name */
    -	__uint16_t	nameidx;	/* index into buffer of name */
    -	__uint8_t	namelen;	/* length of name string */
    -	__uint8_t	pad2;
    -} xfs_dir_leaf_entry_t;
    -
    -typedef struct xfs_dir_leaf_name {
    -	xfs_dir_ino_t	inumber;	/* inode number for this key */
    -	__uint8_t	name[1];	/* name string itself */
    -} xfs_dir_leaf_name_t;
    -
    -typedef struct xfs_dir_leafblock {
    -	xfs_dir_leaf_hdr_t	hdr;	/* constant-structure header block */
    -	xfs_dir_leaf_entry_t	entries[1];	/* var sized array */
    -	xfs_dir_leaf_name_t	namelist[1];	/* grows from bottom of buf */
    -} xfs_dir_leafblock_t;
    -
    -/*
    - * Length of name for which a 512-byte block filesystem
    - * can get a double split.
    - */
    -#define	XFS_DIR_LEAF_CAN_DOUBLE_SPLIT_LEN	\
    -	(512 - (uint)sizeof(xfs_dir_leaf_hdr_t) - \
    -	 (uint)sizeof(xfs_dir_leaf_entry_t) * 2 - \
    -	 (uint)sizeof(xfs_dir_leaf_name_t) * 2 - (MAXNAMELEN - 2) + 1 + 1)
    -
    -typedef int (*xfs_dir_put_t)(struct xfs_dir_put_args *pa);
    -
    -typedef union {
    -	xfs_off_t		o;		/* offset (cookie) */
    -	/*
    -	 * Watch the order here (endian-ness dependent).
    -	 */
    -	struct {
    -#ifndef XFS_NATIVE_HOST
    -		xfs_dahash_t	h;	/* hash value */
    -		__uint32_t	be;	/* block and entry */
    -#else
    -		__uint32_t	be;	/* block and entry */
    -		xfs_dahash_t	h;	/* hash value */
    -#endif /* XFS_NATIVE_HOST */
    -	} s;
    -} xfs_dircook_t;
    -
    -#define	XFS_PUT_COOKIE(c,mp,bno,entry,hash)	\
    -	((c).s.be = XFS_DA_MAKE_BNOENTRY(mp, bno, entry), (c).s.h = (hash))
    -
    -typedef struct xfs_dir_put_args {
    -	xfs_dircook_t	cook;		/* cookie of (next) entry */
    -	xfs_intino_t	ino;		/* inode number */
    -	struct xfs_dirent *dbp;		/* buffer pointer */
    -	char		*name;		/* directory entry name */
    -	int		namelen;	/* length of name */
    -	int		done;		/* output: set if value was stored */
    -	xfs_dir_put_t	put;		/* put function ptr (i/o) */
    -	struct uio	*uio;		/* uio control structure */
    -} xfs_dir_put_args_t;
    -
    -#define XFS_DIR_LEAF_ENTSIZE_BYNAME(len)	\
    -	xfs_dir_leaf_entsize_byname(len)
    -static inline int xfs_dir_leaf_entsize_byname(int len)
    -{
    -	return (uint)sizeof(xfs_dir_leaf_name_t)-1 + len;
    -}
    -
    -#define XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry)	\
    -	xfs_dir_leaf_entsize_byentry(entry)
    -static inline int xfs_dir_leaf_entsize_byentry(xfs_dir_leaf_entry_t *entry)
    -{
    -	return (uint)sizeof(xfs_dir_leaf_name_t)-1 + (entry)->namelen;
    -}
    -
    -#define XFS_DIR_LEAF_NAMESTRUCT(leafp,offset)	\
    -	xfs_dir_leaf_namestruct(leafp,offset)
    -static inline xfs_dir_leaf_name_t *
    -xfs_dir_leaf_namestruct(xfs_dir_leafblock_t *leafp, int offset)
    -{
    -	return (xfs_dir_leaf_name_t *)&((char *)(leafp))[offset];
    -}
    -
    -/*========================================================================
    - * Function prototypes for the kernel.
    - *========================================================================*/
    -
    -/*
    - * Internal routines when dirsize < XFS_LITINO(mp).
    - */
    -int xfs_dir_shortform_create(struct xfs_da_args *args, xfs_ino_t parent);
    -int xfs_dir_shortform_addname(struct xfs_da_args *args);
    -int xfs_dir_shortform_lookup(struct xfs_da_args *args);
    -int xfs_dir_shortform_to_leaf(struct xfs_da_args *args);
    -int xfs_dir_shortform_removename(struct xfs_da_args *args);
    -int xfs_dir_shortform_getdents(struct xfs_inode *dp, struct uio *uio, int *eofp,
    -			       struct xfs_dirent *dbp, xfs_dir_put_t put);
    -int xfs_dir_shortform_replace(struct xfs_da_args *args);
    -
    -/*
    - * Internal routines when dirsize == XFS_LBSIZE(mp).
    - */
    -int xfs_dir_leaf_to_node(struct xfs_da_args *args);
    -int xfs_dir_leaf_to_shortform(struct xfs_da_args *args);
    -
    -/*
    - * Routines used for growing the Btree.
    - */
    -int	xfs_dir_leaf_split(struct xfs_da_state *state,
    -				  struct xfs_da_state_blk *oldblk,
    -				  struct xfs_da_state_blk *newblk);
    -int	xfs_dir_leaf_add(struct xfs_dabuf *leaf_buffer,
    -				struct xfs_da_args *args, int insertion_index);
    -int	xfs_dir_leaf_addname(struct xfs_da_args *args);
    -int	xfs_dir_leaf_lookup_int(struct xfs_dabuf *leaf_buffer,
    -				       struct xfs_da_args *args,
    -				       int *index_found_at);
    -int	xfs_dir_leaf_remove(struct xfs_trans *trans,
    -				   struct xfs_dabuf *leaf_buffer,
    -				   int index_to_remove);
    -int	xfs_dir_leaf_getdents_int(struct xfs_dabuf *bp, struct xfs_inode *dp,
    -					 xfs_dablk_t bno, struct uio *uio,
    -					 int *eobp, struct xfs_dirent *dbp,
    -					 xfs_dir_put_t put, xfs_daddr_t nextda);
    -
    -/*
    - * Routines used for shrinking the Btree.
    - */
    -int	xfs_dir_leaf_toosmall(struct xfs_da_state *state, int *retval);
    -void	xfs_dir_leaf_unbalance(struct xfs_da_state *state,
    -					     struct xfs_da_state_blk *drop_blk,
    -					     struct xfs_da_state_blk *save_blk);
    -
    -/*
    - * Utility routines.
    - */
    -uint	xfs_dir_leaf_lasthash(struct xfs_dabuf *bp, int *count);
    -int	xfs_dir_leaf_order(struct xfs_dabuf *leaf1_bp,
    -				  struct xfs_dabuf *leaf2_bp);
    -int	xfs_dir_put_dirent64_direct(xfs_dir_put_args_t *pa);
    -int	xfs_dir_put_dirent64_uio(xfs_dir_put_args_t *pa);
    -int	xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino);
    -
    -/*
    - * Global data.
    - */
    -extern xfs_dahash_t	xfs_dir_hash_dot, xfs_dir_hash_dotdot;
    -
    -#endif /* __XFS_DIR_LEAF_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_dir_sf.h b/sys/gnu/fs/xfs/xfs_dir_sf.h
    deleted file mode 100644
    index 5b20b4d3f57..00000000000
    --- a/sys/gnu/fs/xfs/xfs_dir_sf.h
    +++ /dev/null
    @@ -1,155 +0,0 @@
    -/*
    - * Copyright (c) 2000,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_DIR_SF_H__
    -#define	__XFS_DIR_SF_H__
    -
    -/*
    - * Directory layout when stored internal to an inode.
    - *
    - * Small directories are packed as tightly as possible so as to
    - * fit into the literal area of the inode.
    - */
    -
    -typedef struct { __uint8_t i[sizeof(xfs_ino_t)]; } xfs_dir_ino_t;
    -
    -/*
    - * The parent directory has a dedicated field, and the self-pointer must
    - * be calculated on the fly.
    - *
    - * Entries are packed toward the top as tight as possible.  The header
    - * and the elements much be memcpy'd out into a work area to get correct
    - * alignment for the inode number fields.
    - */
    -typedef struct xfs_dir_sf_hdr {		/* constant-structure header block */
    -	xfs_dir_ino_t	parent;		/* parent dir inode number */
    -	__uint8_t	count;		/* count of active entries */
    -} xfs_dir_sf_hdr_t;
    -
    -typedef struct xfs_dir_sf_entry {
    -	xfs_dir_ino_t	inumber;	/* referenced inode number */
    -	__uint8_t	namelen;	/* actual length of name (no NULL) */
    -	__uint8_t	name[1];	/* name */
    -} xfs_dir_sf_entry_t;
    -
    -typedef struct xfs_dir_shortform {
    -	xfs_dir_sf_hdr_t	hdr;
    -	xfs_dir_sf_entry_t	list[1];	/* variable sized array */
    -} xfs_dir_shortform_t;
    -
    -/*
    - * We generate this then sort it, so that readdirs are returned in
    - * hash-order.  Else seekdir won't work.
    - */
    -typedef struct xfs_dir_sf_sort {
    -	__uint8_t	entno;		/* .=0, ..=1, else entry# + 2 */
    -	__uint8_t	seqno;		/* sequence # with same hash value */
    -	__uint8_t	namelen;	/* length of name value (no null) */
    -	xfs_dahash_t	hash;		/* this entry's hash value */
    -	xfs_intino_t	ino;		/* this entry's inode number */
    -	char		*name;		/* name value, pointer into buffer */
    -} xfs_dir_sf_sort_t;
    -
    -#define	XFS_DIR_SF_GET_DIRINO(from,to)	xfs_dir_sf_get_dirino(from, to)
    -static inline void xfs_dir_sf_get_dirino(xfs_dir_ino_t *from, xfs_ino_t *to)
    -{
    -	*(to) = XFS_GET_DIR_INO8(*from);
    -}
    -
    -#define	XFS_DIR_SF_PUT_DIRINO(from,to)	xfs_dir_sf_put_dirino(from, to)
    -static inline void xfs_dir_sf_put_dirino(xfs_ino_t *from, xfs_dir_ino_t *to)
    -{
    -	XFS_PUT_DIR_INO8(*(from), *(to));
    -}
    -
    -#define XFS_DIR_SF_ENTSIZE_BYNAME(len)	xfs_dir_sf_entsize_byname(len)
    -static inline int xfs_dir_sf_entsize_byname(int len)
    -{
    -	return (uint)sizeof(xfs_dir_sf_entry_t)-1 + (len);
    -}
    -
    -#define XFS_DIR_SF_ENTSIZE_BYENTRY(sfep)	xfs_dir_sf_entsize_byentry(sfep)
    -static inline int xfs_dir_sf_entsize_byentry(xfs_dir_sf_entry_t *sfep)
    -{
    -	return (uint)sizeof(xfs_dir_sf_entry_t)-1 + (sfep)->namelen;
    -}
    -
    -#define XFS_DIR_SF_NEXTENTRY(sfep)		xfs_dir_sf_nextentry(sfep)
    -static inline xfs_dir_sf_entry_t *xfs_dir_sf_nextentry(xfs_dir_sf_entry_t *sfep)
    -{
    -	return (xfs_dir_sf_entry_t *) \
    -		((char *)(sfep) + XFS_DIR_SF_ENTSIZE_BYENTRY(sfep));
    -}
    -
    -#define XFS_DIR_SF_ALLFIT(count,totallen)	\
    -	xfs_dir_sf_allfit(count,totallen)
    -static inline int xfs_dir_sf_allfit(int count, int totallen)
    -{
    -	return ((uint)sizeof(xfs_dir_sf_hdr_t) + \
    -	       ((uint)sizeof(xfs_dir_sf_entry_t)-1)*(count) + (totallen));
    -}
    -
    -#if defined(XFS_DIR_TRACE)
    -
    -/*
    - * Kernel tracing support for directories.
    - */
    -struct uio;
    -struct xfs_inode;
    -struct xfs_da_intnode;
    -struct xfs_dinode;
    -struct xfs_dir_leafblock;
    -struct xfs_dir_leaf_entry;
    -
    -#define	XFS_DIR_TRACE_SIZE	4096	/* size of global trace buffer */
    -extern ktrace_t	*xfs_dir_trace_buf;
    -
    -/*
    - * Trace record types.
    - */
    -#define	XFS_DIR_KTRACE_G_DU	1	/* dp, uio */
    -#define	XFS_DIR_KTRACE_G_DUB	2	/* dp, uio, bno */
    -#define	XFS_DIR_KTRACE_G_DUN	3	/* dp, uio, node */
    -#define	XFS_DIR_KTRACE_G_DUL	4	/* dp, uio, leaf */
    -#define	XFS_DIR_KTRACE_G_DUE	5	/* dp, uio, leaf entry */
    -#define	XFS_DIR_KTRACE_G_DUC	6	/* dp, uio, cookie */
    -
    -void xfs_dir_trace_g_du(char *where, struct xfs_inode *dp, struct uio *uio);
    -void xfs_dir_trace_g_dub(char *where, struct xfs_inode *dp, struct uio *uio,
    -			      xfs_dablk_t bno);
    -void xfs_dir_trace_g_dun(char *where, struct xfs_inode *dp, struct uio *uio,
    -			      struct xfs_da_intnode *node);
    -void xfs_dir_trace_g_dul(char *where, struct xfs_inode *dp, struct uio *uio,
    -			      struct xfs_dir_leafblock *leaf);
    -void xfs_dir_trace_g_due(char *where, struct xfs_inode *dp, struct uio *uio,
    -			      struct xfs_dir_leaf_entry *entry);
    -void xfs_dir_trace_g_duc(char *where, struct xfs_inode *dp, struct uio *uio,
    -			      xfs_off_t cookie);
    -void xfs_dir_trace_enter(int type, char *where,
    -			     void *a0, void *a1, void *a2, void *a3,
    -			     void *a4, void *a5, void *a6, void *a7,
    -			     void *a8, void *a9, void *a10, void *a11);
    -#else
    -#define	xfs_dir_trace_g_du(w,d,u)
    -#define	xfs_dir_trace_g_dub(w,d,u,b)
    -#define	xfs_dir_trace_g_dun(w,d,u,n)
    -#define	xfs_dir_trace_g_dul(w,d,u,l)
    -#define	xfs_dir_trace_g_due(w,d,u,e)
    -#define	xfs_dir_trace_g_duc(w,d,u,c)
    -#endif /* DEBUG */
    -
    -#endif	/* __XFS_DIR_SF_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_dmapi.h b/sys/gnu/fs/xfs/xfs_dmapi.h
    deleted file mode 100644
    index 8ddd9a5ecda..00000000000
    --- a/sys/gnu/fs/xfs/xfs_dmapi.h
    +++ /dev/null
    @@ -1,198 +0,0 @@
    -/*
    - * Copyright (c) 2000-2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_DMAPI_H__
    -#define __XFS_DMAPI_H__
    -
    -//#include 
    -/*	Values used to define the on-disk version of dm_attrname_t. All
    - *	on-disk attribute names start with the 8-byte string "SGI_DMI_".
    - *
    - *      In the on-disk inode, DMAPI attribute names consist of the user-provided
    - *      name with the DMATTR_PREFIXSTRING pre-pended.  This string must NEVER be
    - *      changed.
    - */
    -
    -#define DMATTR_PREFIXLEN	8
    -#define DMATTR_PREFIXSTRING	"SGI_DMI_"
    -
    -typedef enum {
    -	DM_EVENT_INVALID	= -1,
    -	DM_EVENT_CANCEL		= 0,		/* not supported */
    -	DM_EVENT_MOUNT		= 1,
    -	DM_EVENT_PREUNMOUNT	= 2,
    -	DM_EVENT_UNMOUNT	= 3,
    -	DM_EVENT_DEBUT		= 4,		/* not supported */
    -	DM_EVENT_CREATE		= 5,
    -	DM_EVENT_CLOSE		= 6,		/* not supported */
    -	DM_EVENT_POSTCREATE	= 7,
    -	DM_EVENT_REMOVE		= 8,
    -	DM_EVENT_POSTREMOVE	= 9,
    -	DM_EVENT_RENAME		= 10,
    -	DM_EVENT_POSTRENAME	= 11,
    -	DM_EVENT_LINK		= 12,
    -	DM_EVENT_POSTLINK	= 13,
    -	DM_EVENT_SYMLINK	= 14,
    -	DM_EVENT_POSTSYMLINK	= 15,
    -	DM_EVENT_READ		= 16,
    -	DM_EVENT_WRITE		= 17,
    -	DM_EVENT_TRUNCATE	= 18,
    -	DM_EVENT_ATTRIBUTE	= 19,
    -	DM_EVENT_DESTROY	= 20,
    -	DM_EVENT_NOSPACE	= 21,
    -	DM_EVENT_USER		= 22,
    -	DM_EVENT_MAX		= 23
    -} dm_eventtype_t;
    -#define HAVE_DM_EVENTTYPE_T
    -
    -typedef enum {
    -	DM_RIGHT_NULL,
    -	DM_RIGHT_SHARED,
    -	DM_RIGHT_EXCL
    -} dm_right_t;
    -#define HAVE_DM_RIGHT_T
    -
    -/* Defines for determining if an event message should be sent. */
    -#define	DM_EVENT_ENABLED(vfsp, ip, event) ( \
    -	unlikely ((vfsp)->vfs_flag & VFS_DMI) && \
    -		( ((ip)->i_d.di_dmevmask & (1 << event)) || \
    -		  ((ip)->i_mount->m_dmevmask & (1 << event)) ) \
    -	)
    -
    -#define	DM_EVENT_ENABLED_IO(vfsp, io, event) ( \
    -	unlikely ((vfsp)->vfs_flag & VFS_DMI) && \
    -		( ((io)->io_dmevmask & (1 << event)) || \
    -		  ((io)->io_mount->m_dmevmask & (1 << event)) ) \
    -	)
    -
    -#define DM_XFS_VALID_FS_EVENTS		( \
    -	(1 << DM_EVENT_PREUNMOUNT)	| \
    -	(1 << DM_EVENT_UNMOUNT)		| \
    -	(1 << DM_EVENT_NOSPACE)		| \
    -	(1 << DM_EVENT_DEBUT)		| \
    -	(1 << DM_EVENT_CREATE)		| \
    -	(1 << DM_EVENT_POSTCREATE)	| \
    -	(1 << DM_EVENT_REMOVE)		| \
    -	(1 << DM_EVENT_POSTREMOVE)	| \
    -	(1 << DM_EVENT_RENAME)		| \
    -	(1 << DM_EVENT_POSTRENAME)	| \
    -	(1 << DM_EVENT_LINK)		| \
    -	(1 << DM_EVENT_POSTLINK)	| \
    -	(1 << DM_EVENT_SYMLINK)		| \
    -	(1 << DM_EVENT_POSTSYMLINK)	| \
    -	(1 << DM_EVENT_ATTRIBUTE)	| \
    -	(1 << DM_EVENT_DESTROY)		)
    -
    -/* Events valid in dm_set_eventlist() when called with a file handle for
    -   a regular file or a symlink.  These events are persistent.
    -*/
    -
    -#define	DM_XFS_VALID_FILE_EVENTS	( \
    -	(1 << DM_EVENT_ATTRIBUTE)	| \
    -	(1 << DM_EVENT_DESTROY)		)
    -
    -/* Events valid in dm_set_eventlist() when called with a file handle for
    -   a directory.  These events are persistent.
    -*/
    -
    -#define	DM_XFS_VALID_DIRECTORY_EVENTS	( \
    -	(1 << DM_EVENT_CREATE)		| \
    -	(1 << DM_EVENT_POSTCREATE)	| \
    -	(1 << DM_EVENT_REMOVE)		| \
    -	(1 << DM_EVENT_POSTREMOVE)	| \
    -	(1 << DM_EVENT_RENAME)		| \
    -	(1 << DM_EVENT_POSTRENAME)	| \
    -	(1 << DM_EVENT_LINK)		| \
    -	(1 << DM_EVENT_POSTLINK)	| \
    -	(1 << DM_EVENT_SYMLINK)		| \
    -	(1 << DM_EVENT_POSTSYMLINK)	| \
    -	(1 << DM_EVENT_ATTRIBUTE)	| \
    -	(1 << DM_EVENT_DESTROY)		)
    -
    -/* Events supported by the XFS filesystem. */
    -#define	DM_XFS_SUPPORTED_EVENTS		( \
    -	(1 << DM_EVENT_MOUNT)		| \
    -	(1 << DM_EVENT_PREUNMOUNT)	| \
    -	(1 << DM_EVENT_UNMOUNT)		| \
    -	(1 << DM_EVENT_NOSPACE)		| \
    -	(1 << DM_EVENT_CREATE)		| \
    -	(1 << DM_EVENT_POSTCREATE)	| \
    -	(1 << DM_EVENT_REMOVE)		| \
    -	(1 << DM_EVENT_POSTREMOVE)	| \
    -	(1 << DM_EVENT_RENAME)		| \
    -	(1 << DM_EVENT_POSTRENAME)	| \
    -	(1 << DM_EVENT_LINK)		| \
    -	(1 << DM_EVENT_POSTLINK)	| \
    -	(1 << DM_EVENT_SYMLINK)		| \
    -	(1 << DM_EVENT_POSTSYMLINK)	| \
    -	(1 << DM_EVENT_READ)		| \
    -	(1 << DM_EVENT_WRITE)		| \
    -	(1 << DM_EVENT_TRUNCATE)	| \
    -	(1 << DM_EVENT_ATTRIBUTE)	| \
    -	(1 << DM_EVENT_DESTROY)		)
    -
    -
    -/*
    - *	Definitions used for the flags field on dm_send_*_event().
    - */
    -
    -#define DM_FLAGS_NDELAY		0x001	/* return EAGAIN after dm_pending() */
    -#define DM_FLAGS_UNWANTED	0x002	/* event not in fsys dm_eventset_t */
    -#define DM_FLAGS_IMUX		0x004	/* thread holds i_mutex */
    -#define DM_FLAGS_IALLOCSEM_RD	0x010	/* thread holds i_alloc_sem rd */
    -#define DM_FLAGS_IALLOCSEM_WR	0x020	/* thread holds i_alloc_sem wr */
    -
    -/*
    - *	Based on IO_ISDIRECT, decide which i_ flag is set.
    - */
    -#if 0
    -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
    -#define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \
    -			      DM_FLAGS_IMUX : 0)
    -#define DM_SEM_FLAG_WR	(DM_FLAGS_IALLOCSEM_WR | DM_FLAGS_IMUX)
    -#endif
    -
    -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) && \
    -    (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,22))
    -#define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \
    -			      DM_FLAGS_IALLOCSEM_RD : DM_FLAGS_IMUX)
    -#define DM_SEM_FLAG_WR	(DM_FLAGS_IALLOCSEM_WR | DM_FLAGS_IMUX)
    -#endif
    -
    -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,21)
    -#define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \
    -			      0 : DM_FLAGS_IMUX)
    -#define DM_SEM_FLAG_WR	(DM_FLAGS_IMUX)
    -#endif
    -
    -#endif
    -
    -#define DM_SEM_FLAG_WR	0 /* RMC */
    -
    -/*
    - *	Macros to turn caller specified delay/block flags into
    - *	dm_send_xxxx_event flag DM_FLAGS_NDELAY.
    - */
    -
    -#define FILP_DELAY_FLAG(filp) ((filp->f_flags&(O_NDELAY|O_NONBLOCK)) ? \
    -			DM_FLAGS_NDELAY : 0)
    -#define AT_DELAY_FLAG(f) ((f&ATTR_NONBLOCK) ? DM_FLAGS_NDELAY : 0)
    -
    -
    -extern struct bhv_vfsops xfs_dmops;
    -
    -#endif  /* __XFS_DMAPI_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_dmops.c b/sys/gnu/fs/xfs/xfs_dmops.c
    deleted file mode 100644
    index 629795b3b3d..00000000000
    --- a/sys/gnu/fs/xfs/xfs_dmops.c
    +++ /dev/null
    @@ -1,37 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -
    -xfs_dmops_t	xfs_dmcore_stub = {
    -	.xfs_send_data		= (xfs_send_data_t)fs_nosys,
    -	.xfs_send_mmap		= (xfs_send_mmap_t)fs_noerr,
    -	.xfs_send_destroy	= (xfs_send_destroy_t)fs_nosys,
    -	.xfs_send_namesp	= (xfs_send_namesp_t)fs_nosys,
    -	.xfs_send_unmount	= (xfs_send_unmount_t)fs_noval,
    -};
    diff --git a/sys/gnu/fs/xfs/xfs_error.c b/sys/gnu/fs/xfs/xfs_error.c
    deleted file mode 100644
    index 409d8d8a288..00000000000
    --- a/sys/gnu/fs/xfs/xfs_error.c
    +++ /dev/null
    @@ -1,311 +0,0 @@
    -/*
    - * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_utils.h"
    -#include "xfs_error.h"
    -
    -#ifdef DEBUG
    -
    -int	xfs_etrap[XFS_ERROR_NTRAP] = {
    -	0,
    -};
    -
    -int
    -xfs_error_trap(int e)
    -{
    -	int i;
    -
    -	if (!e)
    -		return 0;
    -	for (i = 0; i < XFS_ERROR_NTRAP; i++) {
    -		if (xfs_etrap[i] == 0)
    -			break;
    -		if (e != xfs_etrap[i])
    -			continue;
    -		cmn_err(CE_NOTE, "xfs_error_trap: error %d", e);
    -		panic("xfs_error_trap");
    -		break;
    -	}
    -	return e;
    -}
    -#endif
    -
    -#if (defined(DEBUG) || defined(INDUCE_IO_ERROR))
    -
    -int	xfs_etest[XFS_NUM_INJECT_ERROR];
    -int64_t	xfs_etest_fsid[XFS_NUM_INJECT_ERROR];
    -char *	xfs_etest_fsname[XFS_NUM_INJECT_ERROR];
    -
    -void
    -xfs_error_test_init(void)
    -{
    -	memset(xfs_etest, 0, sizeof(xfs_etest));
    -	memset(xfs_etest_fsid, 0, sizeof(xfs_etest_fsid));
    -	memset(xfs_etest_fsname, 0, sizeof(xfs_etest_fsname));
    -}
    -
    -int
    -xfs_error_test(int error_tag, int *fsidp, char *expression,
    -	       int line, char *file, unsigned long randfactor)
    -{
    -	int i;
    -	int64_t fsid;
    -
    -	if (random() % randfactor)
    -		return 0;
    -
    -	memcpy(&fsid, fsidp, sizeof(xfs_fsid_t));
    -
    -	for (i = 0; i < XFS_NUM_INJECT_ERROR; i++)  {
    -		if (xfs_etest[i] == error_tag && xfs_etest_fsid[i] == fsid) {
    -			cmn_err(CE_WARN,
    -	"Injecting error (%s) at file %s, line %d, on filesystem \"%s\"",
    -				expression, file, line, xfs_etest_fsname[i]);
    -			return 1;
    -		}
    -	}
    -
    -	return 0;
    -}
    -
    -int
    -xfs_errortag_add(int error_tag, xfs_mount_t *mp)
    -{
    -	int i;
    -	int len;
    -	int64_t fsid;
    -
    -	memcpy(&fsid, mp->m_fixedfsid, sizeof(xfs_fsid_t));
    -
    -	for (i = 0; i < XFS_NUM_INJECT_ERROR; i++)  {
    -		if (xfs_etest_fsid[i] == fsid && xfs_etest[i] == error_tag) {
    -			cmn_err(CE_WARN, "XFS error tag #%d on", error_tag);
    -			return 0;
    -		}
    -	}
    -
    -	for (i = 0; i < XFS_NUM_INJECT_ERROR; i++)  {
    -		if (xfs_etest[i] == 0) {
    -			cmn_err(CE_WARN, "Turned on XFS error tag #%d",
    -				error_tag);
    -			xfs_etest[i] = error_tag;
    -			xfs_etest_fsid[i] = fsid;
    -			len = strlen(mp->m_fsname);
    -			xfs_etest_fsname[i] = kmem_alloc(len + 1, KM_SLEEP);
    -			strcpy(xfs_etest_fsname[i], mp->m_fsname);
    -			return 0;
    -		}
    -	}
    -
    -	cmn_err(CE_WARN, "error tag overflow, too many turned on");
    -
    -	return 1;
    -}
    -
    -int
    -xfs_errortag_clear(int error_tag, xfs_mount_t *mp)
    -{
    -	int i;
    -	int64_t fsid;
    -
    -	memcpy(&fsid, mp->m_fixedfsid, sizeof(xfs_fsid_t));
    -
    -	for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) {
    -		if (xfs_etest_fsid[i] == fsid && xfs_etest[i] == error_tag) {
    -			xfs_etest[i] = 0;
    -			xfs_etest_fsid[i] = 0LL;
    -			kmem_free(xfs_etest_fsname[i],
    -				  strlen(xfs_etest_fsname[i]) + 1);
    -			xfs_etest_fsname[i] = NULL;
    -			cmn_err(CE_WARN, "Cleared XFS error tag #%d",
    -				error_tag);
    -			return 0;
    -		}
    -	}
    -
    -	cmn_err(CE_WARN, "XFS error tag %d not on", error_tag);
    -
    -	return 1;
    -}
    -
    -int
    -xfs_errortag_clearall_umount(int64_t fsid, char *fsname, int loud)
    -{
    -	int i;
    -	int cleared = 0;
    -
    -	for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) {
    -		if ((fsid == 0LL || xfs_etest_fsid[i] == fsid) &&
    -		     xfs_etest[i] != 0) {
    -			cleared = 1;
    -			cmn_err(CE_WARN, "Clearing XFS error tag #%d",
    -				xfs_etest[i]);
    -			xfs_etest[i] = 0;
    -			xfs_etest_fsid[i] = 0LL;
    -			kmem_free(xfs_etest_fsname[i],
    -				  strlen(xfs_etest_fsname[i]) + 1);
    -			xfs_etest_fsname[i] = NULL;
    -		}
    -	}
    -
    -	if (loud || cleared)
    -		cmn_err(CE_WARN,
    -			"Cleared all XFS error tags for filesystem \"%s\"",
    -			fsname);
    -
    -	return 0;
    -}
    -
    -int
    -xfs_errortag_clearall(xfs_mount_t *mp)
    -{
    -	int64_t fsid;
    -
    -	memcpy(&fsid, mp->m_fixedfsid, sizeof(xfs_fsid_t));
    -
    -	return xfs_errortag_clearall_umount(fsid, mp->m_fsname, 1);
    -}
    -#endif /* DEBUG || INDUCE_IO_ERROR */
    -
    -static void
    -xfs_fs_vcmn_err(int level, xfs_mount_t *mp, char *fmt, va_list ap)
    -{
    -	if (mp != NULL) {
    -		char	*newfmt;
    -		int	len = 16 + mp->m_fsname_len + strlen(fmt);
    -
    -		newfmt = kmem_alloc(len, KM_SLEEP);
    -		sprintf(newfmt, "Filesystem \"%s\": %s", mp->m_fsname, fmt);
    -		icmn_err(level, newfmt, ap);
    -		kmem_free(newfmt, len);
    -	} else {
    -		icmn_err(level, fmt, ap);
    -	}
    -}
    -
    -void
    -xfs_fs_cmn_err(int level, xfs_mount_t *mp, char *fmt, ...)
    -{
    -	va_list ap;
    -
    -	va_start(ap, fmt);
    -	xfs_fs_vcmn_err(level, mp, fmt, ap);
    -	va_end(ap);
    -}
    -
    -void
    -xfs_cmn_err(int panic_tag, int level, xfs_mount_t *mp, char *fmt, ...)
    -{
    -	va_list ap;
    -
    -#ifdef DEBUG
    -	xfs_panic_mask |= XFS_PTAG_SHUTDOWN_CORRUPT;
    -#endif
    -
    -	if (xfs_panic_mask && (xfs_panic_mask & panic_tag)
    -	    && (level & CE_ALERT)) {
    -		level &= ~CE_ALERT;
    -		level |= CE_PANIC;
    -		cmn_err(CE_ALERT, "XFS: Transforming an alert into a BUG.");
    -	}
    -	va_start(ap, fmt);
    -	xfs_fs_vcmn_err(level, mp, fmt, ap);
    -	va_end(ap);
    -}
    -
    -void
    -xfs_error_report(
    -	char		*tag,
    -	int		level,
    -	xfs_mount_t	*mp,
    -	char		*fname,
    -	int		linenum,
    -	inst_t		*ra)
    -{
    -	if (level <= xfs_error_level) {
    -		xfs_cmn_err(XFS_PTAG_ERROR_REPORT,
    -			    CE_ALERT, mp,
    -		"XFS internal error %s at line %d of file %s.  Caller 0x%p\n",
    -			    tag, linenum, fname, ra);
    -
    -		xfs_stack_trace();
    -	}
    -}
    -
    -STATIC void
    -xfs_hex_dump(void *p, int length)
    -{
    -	__uint8_t *uip = (__uint8_t*)p;
    -	int	i;
    -	char	sbuf[128], *s;
    -
    -	s = sbuf;
    -	*s = '\0';
    -	for (i=0; im_fixedfsid, #expr, __LINE__, __FILE__, \
    -			 (rf)))
    -#else
    -#define XFS_TEST_ERROR(expr, mp, tag, rf)		\
    -	((expr) || \
    -	 xfs_error_test((tag), (mp)->m_fixedfsid, "expr", __LINE__, __FILE__, \
    -			(rf)))
    -#endif /* __ANSI_CPP__ */
    -
    -extern int xfs_errortag_add(int error_tag, xfs_mount_t *mp);
    -extern int xfs_errortag_clear(int error_tag, xfs_mount_t *mp);
    -extern int xfs_errortag_clearall(xfs_mount_t *mp);
    -extern int xfs_errortag_clearall_umount(int64_t fsid, char *fsname, int loud);
    -#else
    -#define XFS_TEST_ERROR(expr, mp, tag, rf)	(expr)
    -#define xfs_errortag_add(tag, mp)		(ENOSYS)
    -#define xfs_errortag_clearall(mp)		(ENOSYS)
    -#endif /* (DEBUG || INDUCE_IO_ERROR) */
    -
    -/*
    - * XFS panic tags -- allow a call to xfs_cmn_err() be turned into
    - *			a panic by setting xfs_panic_mask in a
    - *			sysctl.  update xfs_max[XFS_PARAM] if
    - *			more are added.
    - */
    -#define		XFS_NO_PTAG			0
    -#define		XFS_PTAG_IFLUSH			0x00000001
    -#define		XFS_PTAG_LOGRES			0x00000002
    -#define		XFS_PTAG_AILDELETE		0x00000004
    -#define		XFS_PTAG_ERROR_REPORT		0x00000008
    -#define		XFS_PTAG_SHUTDOWN_CORRUPT	0x00000010
    -#define		XFS_PTAG_SHUTDOWN_IOERROR	0x00000020
    -#define		XFS_PTAG_SHUTDOWN_LOGERROR	0x00000040
    -
    -struct xfs_mount;
    -/* PRINTFLIKE4 */
    -extern void xfs_cmn_err(int panic_tag, int level, struct xfs_mount *mp,
    -			char *fmt, ...);
    -/* PRINTFLIKE3 */
    -extern void xfs_fs_cmn_err(int level, struct xfs_mount *mp, char *fmt, ...);
    -
    -#define xfs_fs_repair_cmn_err(level, mp, fmt, args...) \
    -	xfs_fs_cmn_err(level, mp, fmt "  Unmount and run xfs_repair.", ## args)
    -
    -#define xfs_fs_mount_cmn_err(f, fmt, args...) \
    -	((f & XFS_MFSI_QUIET)? cmn_err(CE_WARN, "XFS: " fmt, ## args) : (void)0)
    -
    -#endif	/* __XFS_ERROR_H__ */
    -
    diff --git a/sys/gnu/fs/xfs/xfs_extfree_item.c b/sys/gnu/fs/xfs/xfs_extfree_item.c
    deleted file mode 100644
    index f19282ec854..00000000000
    --- a/sys/gnu/fs/xfs/xfs_extfree_item.c
    +++ /dev/null
    @@ -1,587 +0,0 @@
    -/*
    - * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_buf_item.h"
    -#include "xfs_sb.h"
    -#include "xfs_dir.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_trans_priv.h"
    -#include "xfs_extfree_item.h"
    -
    -
    -kmem_zone_t	*xfs_efi_zone;
    -kmem_zone_t	*xfs_efd_zone;
    -
    -STATIC void	xfs_efi_item_unlock(xfs_efi_log_item_t *);
    -STATIC void	xfs_efi_item_abort(xfs_efi_log_item_t *);
    -STATIC void	xfs_efd_item_abort(xfs_efd_log_item_t *);
    -
    -
    -void
    -xfs_efi_item_free(xfs_efi_log_item_t *efip)
    -{
    -	int nexts = efip->efi_format.efi_nextents;
    -
    -	if (nexts > XFS_EFI_MAX_FAST_EXTENTS) {
    -		kmem_free(efip, sizeof(xfs_efi_log_item_t) +
    -				(nexts - 1) * sizeof(xfs_extent_t));
    -	} else {
    -		kmem_zone_free(xfs_efi_zone, efip);
    -	}
    -}
    -
    -/*
    - * This returns the number of iovecs needed to log the given efi item.
    - * We only need 1 iovec for an efi item.  It just logs the efi_log_format
    - * structure.
    - */
    -/*ARGSUSED*/
    -STATIC uint
    -xfs_efi_item_size(xfs_efi_log_item_t *efip)
    -{
    -	return 1;
    -}
    -
    -/*
    - * This is called to fill in the vector of log iovecs for the
    - * given efi log item. We use only 1 iovec, and we point that
    - * at the efi_log_format structure embedded in the efi item.
    - * It is at this point that we assert that all of the extent
    - * slots in the efi item have been filled.
    - */
    -STATIC void
    -xfs_efi_item_format(xfs_efi_log_item_t	*efip,
    -		    xfs_log_iovec_t	*log_vector)
    -{
    -	uint	size;
    -
    -	ASSERT(efip->efi_next_extent == efip->efi_format.efi_nextents);
    -
    -	efip->efi_format.efi_type = XFS_LI_EFI;
    -
    -	size = sizeof(xfs_efi_log_format_t);
    -	size += (efip->efi_format.efi_nextents - 1) * sizeof(xfs_extent_t);
    -	efip->efi_format.efi_size = 1;
    -
    -	log_vector->i_addr = (xfs_caddr_t)&(efip->efi_format);
    -	log_vector->i_len = size;
    -	XLOG_VEC_SET_TYPE(log_vector, XLOG_REG_TYPE_EFI_FORMAT);
    -	ASSERT(size >= sizeof(xfs_efi_log_format_t));
    -}
    -
    -
    -/*
    - * Pinning has no meaning for an efi item, so just return.
    - */
    -/*ARGSUSED*/
    -STATIC void
    -xfs_efi_item_pin(xfs_efi_log_item_t *efip)
    -{
    -	return;
    -}
    -
    -
    -/*
    - * While EFIs cannot really be pinned, the unpin operation is the
    - * last place at which the EFI is manipulated during a transaction.
    - * Here we coordinate with xfs_efi_cancel() to determine who gets to
    - * free the EFI.
    - */
    -/*ARGSUSED*/
    -STATIC void
    -xfs_efi_item_unpin(xfs_efi_log_item_t *efip, int stale)
    -{
    -	xfs_mount_t	*mp;
    -	SPLDECL(s);
    -
    -	mp = efip->efi_item.li_mountp;
    -	AIL_LOCK(mp, s);
    -	if (efip->efi_flags & XFS_EFI_CANCELED) {
    -		/*
    -		 * xfs_trans_delete_ail() drops the AIL lock.
    -		 */
    -		xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s);
    -		xfs_efi_item_free(efip);
    -	} else {
    -		efip->efi_flags |= XFS_EFI_COMMITTED;
    -		AIL_UNLOCK(mp, s);
    -	}
    -}
    -
    -/*
    - * like unpin only we have to also clear the xaction descriptor
    - * pointing the log item if we free the item.  This routine duplicates
    - * unpin because efi_flags is protected by the AIL lock.  Freeing
    - * the descriptor and then calling unpin would force us to drop the AIL
    - * lock which would open up a race condition.
    - */
    -STATIC void
    -xfs_efi_item_unpin_remove(xfs_efi_log_item_t *efip, xfs_trans_t *tp)
    -{
    -	xfs_mount_t	*mp;
    -	xfs_log_item_desc_t	*lidp;
    -	SPLDECL(s);
    -
    -	mp = efip->efi_item.li_mountp;
    -	AIL_LOCK(mp, s);
    -	if (efip->efi_flags & XFS_EFI_CANCELED) {
    -		/*
    -		 * free the xaction descriptor pointing to this item
    -		 */
    -		lidp = xfs_trans_find_item(tp, (xfs_log_item_t *) efip);
    -		xfs_trans_free_item(tp, lidp);
    -		/*
    -		 * pull the item off the AIL.
    -		 * xfs_trans_delete_ail() drops the AIL lock.
    -		 */
    -		xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s);
    -		xfs_efi_item_free(efip);
    -	} else {
    -		efip->efi_flags |= XFS_EFI_COMMITTED;
    -		AIL_UNLOCK(mp, s);
    -	}
    -}
    -
    -/*
    - * Efi items have no locking or pushing.  However, since EFIs are
    - * pulled from the AIL when their corresponding EFDs are committed
    - * to disk, their situation is very similar to being pinned.  Return
    - * XFS_ITEM_PINNED so that the caller will eventually flush the log.
    - * This should help in getting the EFI out of the AIL.
    - */
    -/*ARGSUSED*/
    -STATIC uint
    -xfs_efi_item_trylock(xfs_efi_log_item_t *efip)
    -{
    -	return XFS_ITEM_PINNED;
    -}
    -
    -/*
    - * Efi items have no locking, so just return.
    - */
    -/*ARGSUSED*/
    -STATIC void
    -xfs_efi_item_unlock(xfs_efi_log_item_t *efip)
    -{
    -	if (efip->efi_item.li_flags & XFS_LI_ABORTED)
    -		xfs_efi_item_abort(efip);
    -	return;
    -}
    -
    -/*
    - * The EFI is logged only once and cannot be moved in the log, so
    - * simply return the lsn at which it's been logged.  The canceled
    - * flag is not paid any attention here.  Checking for that is delayed
    - * until the EFI is unpinned.
    - */
    -/*ARGSUSED*/
    -STATIC xfs_lsn_t
    -xfs_efi_item_committed(xfs_efi_log_item_t *efip, xfs_lsn_t lsn)
    -{
    -	return lsn;
    -}
    -
    -/*
    - * This is called when the transaction logging the EFI is aborted.
    - * Free up the EFI and return.  No need to clean up the slot for
    - * the item in the transaction.  That was done by the unpin code
    - * which is called prior to this routine in the abort/fs-shutdown path.
    - */
    -STATIC void
    -xfs_efi_item_abort(xfs_efi_log_item_t *efip)
    -{
    -	xfs_efi_item_free(efip);
    -}
    -
    -/*
    - * There isn't much you can do to push on an efi item.  It is simply
    - * stuck waiting for all of its corresponding efd items to be
    - * committed to disk.
    - */
    -/*ARGSUSED*/
    -STATIC void
    -xfs_efi_item_push(xfs_efi_log_item_t *efip)
    -{
    -	return;
    -}
    -
    -/*
    - * The EFI dependency tracking op doesn't do squat.  It can't because
    - * it doesn't know where the free extent is coming from.  The dependency
    - * tracking has to be handled by the "enclosing" metadata object.  For
    - * example, for inodes, the inode is locked throughout the extent freeing
    - * so the dependency should be recorded there.
    - */
    -/*ARGSUSED*/
    -STATIC void
    -xfs_efi_item_committing(xfs_efi_log_item_t *efip, xfs_lsn_t lsn)
    -{
    -	return;
    -}
    -
    -/*
    - * This is the ops vector shared by all efi log items.
    - */
    -STATIC struct xfs_item_ops xfs_efi_item_ops = {
    -	.iop_size	= (uint(*)(xfs_log_item_t*))xfs_efi_item_size,
    -	.iop_format	= (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
    -					xfs_efi_item_format,
    -	.iop_pin	= (void(*)(xfs_log_item_t*))xfs_efi_item_pin,
    -	.iop_unpin	= (void(*)(xfs_log_item_t*, int))xfs_efi_item_unpin,
    -	.iop_unpin_remove = (void(*)(xfs_log_item_t*, xfs_trans_t *))
    -					xfs_efi_item_unpin_remove,
    -	.iop_trylock	= (uint(*)(xfs_log_item_t*))xfs_efi_item_trylock,
    -	.iop_unlock	= (void(*)(xfs_log_item_t*))xfs_efi_item_unlock,
    -	.iop_committed	= (xfs_lsn_t(*)(xfs_log_item_t*, xfs_lsn_t))
    -					xfs_efi_item_committed,
    -	.iop_push	= (void(*)(xfs_log_item_t*))xfs_efi_item_push,
    -	.iop_abort	= (void(*)(xfs_log_item_t*))xfs_efi_item_abort,
    -	.iop_pushbuf	= NULL,
    -	.iop_committing = (void(*)(xfs_log_item_t*, xfs_lsn_t))
    -					xfs_efi_item_committing
    -};
    -
    -
    -/*
    - * Allocate and initialize an efi item with the given number of extents.
    - */
    -xfs_efi_log_item_t *
    -xfs_efi_init(xfs_mount_t	*mp,
    -	     uint		nextents)
    -
    -{
    -	xfs_efi_log_item_t	*efip;
    -	uint			size;
    -
    -	ASSERT(nextents > 0);
    -	if (nextents > XFS_EFI_MAX_FAST_EXTENTS) {
    -		size = (uint)(sizeof(xfs_efi_log_item_t) +
    -			((nextents - 1) * sizeof(xfs_extent_t)));
    -		efip = (xfs_efi_log_item_t*)kmem_zalloc(size, KM_SLEEP);
    -	} else {
    -		efip = (xfs_efi_log_item_t*)kmem_zone_zalloc(xfs_efi_zone,
    -							     KM_SLEEP);
    -	}
    -
    -	efip->efi_item.li_type = XFS_LI_EFI;
    -	efip->efi_item.li_ops = &xfs_efi_item_ops;
    -	efip->efi_item.li_mountp = mp;
    -	efip->efi_format.efi_nextents = nextents;
    -	efip->efi_format.efi_id = (__psint_t)(void*)efip;
    -
    -	return (efip);
    -}
    -
    -/*
    - * This is called by the efd item code below to release references to
    - * the given efi item.  Each efd calls this with the number of
    - * extents that it has logged, and when the sum of these reaches
    - * the total number of extents logged by this efi item we can free
    - * the efi item.
    - *
    - * Freeing the efi item requires that we remove it from the AIL.
    - * We'll use the AIL lock to protect our counters as well as
    - * the removal from the AIL.
    - */
    -void
    -xfs_efi_release(xfs_efi_log_item_t	*efip,
    -		uint			nextents)
    -{
    -	xfs_mount_t	*mp;
    -	int		extents_left;
    -	SPLDECL(s);
    -
    -	mp = efip->efi_item.li_mountp;
    -	ASSERT(efip->efi_next_extent > 0);
    -	ASSERT(efip->efi_flags & XFS_EFI_COMMITTED);
    -
    -	AIL_LOCK(mp, s);
    -	ASSERT(efip->efi_next_extent >= nextents);
    -	efip->efi_next_extent -= nextents;
    -	extents_left = efip->efi_next_extent;
    -	if (extents_left == 0) {
    -		/*
    -		 * xfs_trans_delete_ail() drops the AIL lock.
    -		 */
    -		xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s);
    -		xfs_efi_item_free(efip);
    -	} else {
    -		AIL_UNLOCK(mp, s);
    -	}
    -}
    -
    -/*
    - * This is called when the transaction that should be committing the
    - * EFD corresponding to the given EFI is aborted.  The committed and
    - * canceled flags are used to coordinate the freeing of the EFI and
    - * the references by the transaction that committed it.
    - */
    -STATIC void
    -xfs_efi_cancel(
    -	xfs_efi_log_item_t	*efip)
    -{
    -	xfs_mount_t	*mp;
    -	SPLDECL(s);
    -
    -	mp = efip->efi_item.li_mountp;
    -	AIL_LOCK(mp, s);
    -	if (efip->efi_flags & XFS_EFI_COMMITTED) {
    -		/*
    -		 * xfs_trans_delete_ail() drops the AIL lock.
    -		 */
    -		xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s);
    -		xfs_efi_item_free(efip);
    -	} else {
    -		efip->efi_flags |= XFS_EFI_CANCELED;
    -		AIL_UNLOCK(mp, s);
    -	}
    -}
    -
    -STATIC void
    -xfs_efd_item_free(xfs_efd_log_item_t *efdp)
    -{
    -	int nexts = efdp->efd_format.efd_nextents;
    -
    -	if (nexts > XFS_EFD_MAX_FAST_EXTENTS) {
    -		kmem_free(efdp, sizeof(xfs_efd_log_item_t) +
    -				(nexts - 1) * sizeof(xfs_extent_t));
    -	} else {
    -		kmem_zone_free(xfs_efd_zone, efdp);
    -	}
    -}
    -
    -/*
    - * This returns the number of iovecs needed to log the given efd item.
    - * We only need 1 iovec for an efd item.  It just logs the efd_log_format
    - * structure.
    - */
    -/*ARGSUSED*/
    -STATIC uint
    -xfs_efd_item_size(xfs_efd_log_item_t *efdp)
    -{
    -	return 1;
    -}
    -
    -/*
    - * This is called to fill in the vector of log iovecs for the
    - * given efd log item. We use only 1 iovec, and we point that
    - * at the efd_log_format structure embedded in the efd item.
    - * It is at this point that we assert that all of the extent
    - * slots in the efd item have been filled.
    - */
    -STATIC void
    -xfs_efd_item_format(xfs_efd_log_item_t	*efdp,
    -		    xfs_log_iovec_t	*log_vector)
    -{
    -	uint	size;
    -
    -	ASSERT(efdp->efd_next_extent == efdp->efd_format.efd_nextents);
    -
    -	efdp->efd_format.efd_type = XFS_LI_EFD;
    -
    -	size = sizeof(xfs_efd_log_format_t);
    -	size += (efdp->efd_format.efd_nextents - 1) * sizeof(xfs_extent_t);
    -	efdp->efd_format.efd_size = 1;
    -
    -	log_vector->i_addr = (xfs_caddr_t)&(efdp->efd_format);
    -	log_vector->i_len = size;
    -	XLOG_VEC_SET_TYPE(log_vector, XLOG_REG_TYPE_EFD_FORMAT);
    -	ASSERT(size >= sizeof(xfs_efd_log_format_t));
    -}
    -
    -
    -/*
    - * Pinning has no meaning for an efd item, so just return.
    - */
    -/*ARGSUSED*/
    -STATIC void
    -xfs_efd_item_pin(xfs_efd_log_item_t *efdp)
    -{
    -	return;
    -}
    -
    -
    -/*
    - * Since pinning has no meaning for an efd item, unpinning does
    - * not either.
    - */
    -/*ARGSUSED*/
    -STATIC void
    -xfs_efd_item_unpin(xfs_efd_log_item_t *efdp, int stale)
    -{
    -	return;
    -}
    -
    -/*ARGSUSED*/
    -STATIC void
    -xfs_efd_item_unpin_remove(xfs_efd_log_item_t *efdp, xfs_trans_t *tp)
    -{
    -	return;
    -}
    -
    -/*
    - * Efd items have no locking, so just return success.
    - */
    -/*ARGSUSED*/
    -STATIC uint
    -xfs_efd_item_trylock(xfs_efd_log_item_t *efdp)
    -{
    -	return XFS_ITEM_LOCKED;
    -}
    -
    -/*
    - * Efd items have no locking or pushing, so return failure
    - * so that the caller doesn't bother with us.
    - */
    -/*ARGSUSED*/
    -STATIC void
    -xfs_efd_item_unlock(xfs_efd_log_item_t *efdp)
    -{
    -	if (efdp->efd_item.li_flags & XFS_LI_ABORTED)
    -		xfs_efd_item_abort(efdp);
    -	return;
    -}
    -
    -/*
    - * When the efd item is committed to disk, all we need to do
    - * is delete our reference to our partner efi item and then
    - * free ourselves.  Since we're freeing ourselves we must
    - * return -1 to keep the transaction code from further referencing
    - * this item.
    - */
    -/*ARGSUSED*/
    -STATIC xfs_lsn_t
    -xfs_efd_item_committed(xfs_efd_log_item_t *efdp, xfs_lsn_t lsn)
    -{
    -	/*
    -	 * If we got a log I/O error, it's always the case that the LR with the
    -	 * EFI got unpinned and freed before the EFD got aborted.
    -	 */
    -	if ((efdp->efd_item.li_flags & XFS_LI_ABORTED) == 0)
    -		xfs_efi_release(efdp->efd_efip, efdp->efd_format.efd_nextents);
    -
    -	xfs_efd_item_free(efdp);
    -	return (xfs_lsn_t)-1;
    -}
    -
    -/*
    - * The transaction of which this EFD is a part has been aborted.
    - * Inform its companion EFI of this fact and then clean up after
    - * ourselves.  No need to clean up the slot for the item in the
    - * transaction.  That was done by the unpin code which is called
    - * prior to this routine in the abort/fs-shutdown path.
    - */
    -STATIC void
    -xfs_efd_item_abort(xfs_efd_log_item_t *efdp)
    -{
    -	/*
    -	 * If we got a log I/O error, it's always the case that the LR with the
    -	 * EFI got unpinned and freed before the EFD got aborted. So don't
    -	 * reference the EFI at all in that case.
    -	 */
    -	if ((efdp->efd_item.li_flags & XFS_LI_ABORTED) == 0)
    -		xfs_efi_cancel(efdp->efd_efip);
    -
    -	xfs_efd_item_free(efdp);
    -}
    -
    -/*
    - * There isn't much you can do to push on an efd item.  It is simply
    - * stuck waiting for the log to be flushed to disk.
    - */
    -/*ARGSUSED*/
    -STATIC void
    -xfs_efd_item_push(xfs_efd_log_item_t *efdp)
    -{
    -	return;
    -}
    -
    -/*
    - * The EFD dependency tracking op doesn't do squat.  It can't because
    - * it doesn't know where the free extent is coming from.  The dependency
    - * tracking has to be handled by the "enclosing" metadata object.  For
    - * example, for inodes, the inode is locked throughout the extent freeing
    - * so the dependency should be recorded there.
    - */
    -/*ARGSUSED*/
    -STATIC void
    -xfs_efd_item_committing(xfs_efd_log_item_t *efip, xfs_lsn_t lsn)
    -{
    -	return;
    -}
    -
    -/*
    - * This is the ops vector shared by all efd log items.
    - */
    -STATIC struct xfs_item_ops xfs_efd_item_ops = {
    -	.iop_size	= (uint(*)(xfs_log_item_t*))xfs_efd_item_size,
    -	.iop_format	= (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
    -					xfs_efd_item_format,
    -	.iop_pin	= (void(*)(xfs_log_item_t*))xfs_efd_item_pin,
    -	.iop_unpin	= (void(*)(xfs_log_item_t*, int))xfs_efd_item_unpin,
    -	.iop_unpin_remove = (void(*)(xfs_log_item_t*, xfs_trans_t*))
    -					xfs_efd_item_unpin_remove,
    -	.iop_trylock	= (uint(*)(xfs_log_item_t*))xfs_efd_item_trylock,
    -	.iop_unlock	= (void(*)(xfs_log_item_t*))xfs_efd_item_unlock,
    -	.iop_committed	= (xfs_lsn_t(*)(xfs_log_item_t*, xfs_lsn_t))
    -					xfs_efd_item_committed,
    -	.iop_push	= (void(*)(xfs_log_item_t*))xfs_efd_item_push,
    -	.iop_abort	= (void(*)(xfs_log_item_t*))xfs_efd_item_abort,
    -	.iop_pushbuf	= NULL,
    -	.iop_committing = (void(*)(xfs_log_item_t*, xfs_lsn_t))
    -					xfs_efd_item_committing
    -};
    -
    -
    -/*
    - * Allocate and initialize an efd item with the given number of extents.
    - */
    -xfs_efd_log_item_t *
    -xfs_efd_init(xfs_mount_t	*mp,
    -	     xfs_efi_log_item_t	*efip,
    -	     uint		nextents)
    -
    -{
    -	xfs_efd_log_item_t	*efdp;
    -	uint			size;
    -
    -	ASSERT(nextents > 0);
    -	if (nextents > XFS_EFD_MAX_FAST_EXTENTS) {
    -		size = (uint)(sizeof(xfs_efd_log_item_t) +
    -			((nextents - 1) * sizeof(xfs_extent_t)));
    -		efdp = (xfs_efd_log_item_t*)kmem_zalloc(size, KM_SLEEP);
    -	} else {
    -		efdp = (xfs_efd_log_item_t*)kmem_zone_zalloc(xfs_efd_zone,
    -							     KM_SLEEP);
    -	}
    -
    -	efdp->efd_item.li_type = XFS_LI_EFD;
    -	efdp->efd_item.li_ops = &xfs_efd_item_ops;
    -	efdp->efd_item.li_mountp = mp;
    -	efdp->efd_efip = efip;
    -	efdp->efd_format.efd_nextents = nextents;
    -	efdp->efd_format.efd_efi_id = efip->efi_format.efi_id;
    -
    -	return (efdp);
    -}
    diff --git a/sys/gnu/fs/xfs/xfs_extfree_item.h b/sys/gnu/fs/xfs/xfs_extfree_item.h
    deleted file mode 100644
    index 5bf681708fe..00000000000
    --- a/sys/gnu/fs/xfs/xfs_extfree_item.h
    +++ /dev/null
    @@ -1,111 +0,0 @@
    -/*
    - * Copyright (c) 2000,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef	__XFS_EXTFREE_ITEM_H__
    -#define	__XFS_EXTFREE_ITEM_H__
    -
    -struct xfs_mount;
    -struct kmem_zone;
    -
    -typedef struct xfs_extent {
    -	xfs_dfsbno_t	ext_start;
    -	xfs_extlen_t	ext_len;
    -} xfs_extent_t;
    -
    -/*
    - * This is the structure used to lay out an efi log item in the
    - * log.  The efi_extents field is a variable size array whose
    - * size is given by efi_nextents.
    - */
    -typedef struct xfs_efi_log_format {
    -	unsigned short		efi_type;	/* efi log item type */
    -	unsigned short		efi_size;	/* size of this item */
    -	uint			efi_nextents;	/* # extents to free */
    -	__uint64_t		efi_id;		/* efi identifier */
    -	xfs_extent_t		efi_extents[1];	/* array of extents to free */
    -} xfs_efi_log_format_t;
    -
    -/*
    - * This is the structure used to lay out an efd log item in the
    - * log.  The efd_extents array is a variable size array whose
    - * size is given by efd_nextents;
    - */
    -typedef struct xfs_efd_log_format {
    -	unsigned short		efd_type;	/* efd log item type */
    -	unsigned short		efd_size;	/* size of this item */
    -	uint			efd_nextents;	/* # of extents freed */
    -	__uint64_t		efd_efi_id;	/* id of corresponding efi */
    -	xfs_extent_t		efd_extents[1];	/* array of extents freed */
    -} xfs_efd_log_format_t;
    -
    -
    -#ifdef __KERNEL__
    -
    -/*
    - * Max number of extents in fast allocation path.
    - */
    -#define	XFS_EFI_MAX_FAST_EXTENTS	16
    -
    -/*
    - * Define EFI flags.
    - */
    -#define	XFS_EFI_RECOVERED	0x1
    -#define	XFS_EFI_COMMITTED	0x2
    -#define	XFS_EFI_CANCELED	0x4
    -
    -/*
    - * This is the "extent free intention" log item.  It is used
    - * to log the fact that some extents need to be free.  It is
    - * used in conjunction with the "extent free done" log item
    - * described below.
    - */
    -typedef struct xfs_efi_log_item {
    -	xfs_log_item_t		efi_item;
    -	uint			efi_flags;	/* misc flags */
    -	uint			efi_next_extent;
    -	xfs_efi_log_format_t	efi_format;
    -} xfs_efi_log_item_t;
    -
    -/*
    - * This is the "extent free done" log item.  It is used to log
    - * the fact that some extents earlier mentioned in an efi item
    - * have been freed.
    - */
    -typedef struct xfs_efd_log_item {
    -	xfs_log_item_t		efd_item;
    -	xfs_efi_log_item_t	*efd_efip;
    -	uint			efd_next_extent;
    -	xfs_efd_log_format_t	efd_format;
    -} xfs_efd_log_item_t;
    -
    -/*
    - * Max number of extents in fast allocation path.
    - */
    -#define	XFS_EFD_MAX_FAST_EXTENTS	16
    -
    -extern struct kmem_zone	*xfs_efi_zone;
    -extern struct kmem_zone	*xfs_efd_zone;
    -
    -xfs_efi_log_item_t	*xfs_efi_init(struct xfs_mount *, uint);
    -xfs_efd_log_item_t	*xfs_efd_init(struct xfs_mount *, xfs_efi_log_item_t *,
    -				      uint);
    -
    -void			xfs_efi_item_free(xfs_efi_log_item_t *);
    -
    -#endif	/* __KERNEL__ */
    -
    -#endif	/* __XFS_EXTFREE_ITEM_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_fs.h b/sys/gnu/fs/xfs/xfs_fs.h
    deleted file mode 100644
    index e9736a8e002..00000000000
    --- a/sys/gnu/fs/xfs/xfs_fs.h
    +++ /dev/null
    @@ -1,527 +0,0 @@
    -/*
    - * Copyright (c) 1995-2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU Lesser General Public License
    - * as published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU Lesser General Public License for more details.
    - *
    - * You should have received a copy of the GNU Lesser General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_FS_H__
    -#define __XFS_FS_H__
    -
    -/*
    - * SGI's XFS filesystem's major stuff (constants, structures)
    - */
    -
    -#define XFS_NAME	"xfs"
    -
    -/*
    - * Direct I/O attribute record used with XFS_IOC_DIOINFO
    - * d_miniosz is the min xfer size, xfer size multiple and file seek offset
    - * alignment.
    - */
    -#ifndef HAVE_DIOATTR
    -struct dioattr {
    -	__u32		d_mem;		/* data buffer memory alignment */
    -	__u32		d_miniosz;	/* min xfer size		*/
    -	__u32		d_maxiosz;	/* max xfer size		*/
    -};
    -#endif
    -
    -/*
    - * Structure for XFS_IOC_FSGETXATTR[A] and XFS_IOC_FSSETXATTR.
    - */
    -#ifndef HAVE_FSXATTR
    -struct fsxattr {
    -	__u32		fsx_xflags;	/* xflags field value (get/set) */
    -	__u32		fsx_extsize;	/* extsize field value (get/set)*/
    -	__u32		fsx_nextents;	/* nextents field value (get)	*/
    -	__u32		fsx_projid;	/* project identifier (get/set) */
    -	unsigned char	fsx_pad[12];
    -};
    -#endif
    -
    -/*
    - * Flags for the bs_xflags/fsx_xflags field
    - * There should be a one-to-one correspondence between these flags and the
    - * XFS_DIFLAG_s.
    - */
    -#define XFS_XFLAG_REALTIME	0x00000001	/* data in realtime volume */
    -#define XFS_XFLAG_PREALLOC	0x00000002	/* preallocated file extents */
    -#define XFS_XFLAG_IMMUTABLE	0x00000008	/* file cannot be modified */
    -#define XFS_XFLAG_APPEND	0x00000010	/* all writes append */
    -#define XFS_XFLAG_SYNC		0x00000020	/* all writes synchronous */
    -#define XFS_XFLAG_NOATIME	0x00000040	/* do not update access time */
    -#define XFS_XFLAG_NODUMP	0x00000080	/* do not include in backups */
    -#define XFS_XFLAG_RTINHERIT	0x00000100	/* create with rt bit set */
    -#define XFS_XFLAG_PROJINHERIT	0x00000200	/* create with parents projid */
    -#define XFS_XFLAG_NOSYMLINKS	0x00000400	/* disallow symlink creation */
    -#define XFS_XFLAG_EXTSIZE	0x00000800	/* extent size allocator hint */
    -#define XFS_XFLAG_EXTSZINHERIT	0x00001000	/* inherit inode extent size */
    -#define XFS_XFLAG_HASATTR	0x80000000	/* no DIFLAG for this	*/
    -
    -/*
    - * Structure for XFS_IOC_GETBMAP.
    - * On input, fill in bmv_offset and bmv_length of the first structure
    - * to indicate the area of interest in the file, and bmv_entry with the
    - * number of array elements given.  The first structure is updated on
    - * return to give the offset and length for the next call.
    - */
    -#ifndef HAVE_GETBMAP
    -struct getbmap {
    -	__s64		bmv_offset;	/* file offset of segment in blocks */
    -	__s64		bmv_block;	/* starting block (64-bit daddr_t)  */
    -	__s64		bmv_length;	/* length of segment, blocks	    */
    -	__s32		bmv_count;	/* # of entries in array incl. 1st  */
    -	__s32		bmv_entries;	/* # of entries filled in (output)  */
    -};
    -#endif
    -
    -/*
    - *	Structure for XFS_IOC_GETBMAPX.	 Fields bmv_offset through bmv_entries
    - *	are used exactly as in the getbmap structure.  The getbmapx structure
    - *	has additional bmv_iflags and bmv_oflags fields. The bmv_iflags field
    - *	is only used for the first structure.  It contains input flags
    - *	specifying XFS_IOC_GETBMAPX actions.  The bmv_oflags field is filled
    - *	in by the XFS_IOC_GETBMAPX command for each returned structure after
    - *	the first.
    - */
    -#ifndef HAVE_GETBMAPX
    -struct getbmapx {
    -	__s64		bmv_offset;	/* file offset of segment in blocks */
    -	__s64		bmv_block;	/* starting block (64-bit daddr_t)  */
    -	__s64		bmv_length;	/* length of segment, blocks	    */
    -	__s32		bmv_count;	/* # of entries in array incl. 1st  */
    -	__s32		bmv_entries;	/* # of entries filled in (output). */
    -	__s32		bmv_iflags;	/* input flags (1st structure)	    */
    -	__s32		bmv_oflags;	/* output flags (after 1st structure)*/
    -	__s32		bmv_unused1;	/* future use			    */
    -	__s32		bmv_unused2;	/* future use			    */
    -};
    -#endif
    -
    -/*	bmv_iflags values - set by XFS_IOC_GETBMAPX caller.	*/
    -#define BMV_IF_ATTRFORK		0x1	/* return attr fork rather than data */
    -#define BMV_IF_NO_DMAPI_READ	0x2	/* Do not generate DMAPI read event  */
    -#define BMV_IF_PREALLOC		0x4	/* rtn status BMV_OF_PREALLOC if req */
    -#define BMV_IF_VALID	(BMV_IF_ATTRFORK|BMV_IF_NO_DMAPI_READ|BMV_IF_PREALLOC)
    -#ifdef __KERNEL__
    -#define BMV_IF_EXTENDED 0x40000000	/* getpmapx if set */
    -#endif
    -
    -/*	bmv_oflags values - returned for for each non-header segment */
    -#define BMV_OF_PREALLOC		0x1	/* segment = unwritten pre-allocation */
    -
    -/*	Convert getbmap <-> getbmapx - move fields from p1 to p2. */
    -#define GETBMAP_CONVERT(p1,p2) {	\
    -	p2.bmv_offset = p1.bmv_offset;	\
    -	p2.bmv_block = p1.bmv_block;	\
    -	p2.bmv_length = p1.bmv_length;	\
    -	p2.bmv_count = p1.bmv_count;	\
    -	p2.bmv_entries = p1.bmv_entries; \
    -	\
    -printf("offset 0x%jx block 0x%jx length 0x%jx count 0x%jx entries %d\n", \
    -       (uint64_t)p2.bmv_offset, \
    -       (uint64_t)p2.bmv_block, \
    -       (uint64_t)p2.bmv_length, \
    -       (uint64_t)p2.bmv_count, \
    -       p2.bmv_entries); \
    -  }
    -
    -
    -/*
    - * Structure for XFS_IOC_FSSETDM.
    - * For use by backup and restore programs to set the XFS on-disk inode
    - * fields di_dmevmask and di_dmstate.  These must be set to exactly and
    - * only values previously obtained via xfs_bulkstat!  (Specifically the
    - * xfs_bstat_t fields bs_dmevmask and bs_dmstate.)
    - */
    -#ifndef HAVE_FSDMIDATA
    -struct fsdmidata {
    -	__u32		fsd_dmevmask;	/* corresponds to di_dmevmask */
    -	__u16		fsd_padding;
    -	__u16		fsd_dmstate;	/* corresponds to di_dmstate  */
    -};
    -#endif
    -
    -/*
    - * File segment locking set data type for 64 bit access.
    - * Also used for all the RESV/FREE interfaces.
    - */
    -typedef struct xfs_flock64 {
    -	__s16		l_type;
    -	__s16		l_whence;
    -	__s64		l_start;
    -	__s64		l_len;		/* len == 0 means until end of file */
    -	__s32		l_sysid;
    -	__u32		l_pid;
    -	__s32		l_pad[4];	/* reserve area			    */
    -} xfs_flock64_t;
    -
    -/*
    - * Output for XFS_IOC_FSGEOMETRY_V1
    - */
    -typedef struct xfs_fsop_geom_v1 {
    -	__u32		blocksize;	/* filesystem (data) block size */
    -	__u32		rtextsize;	/* realtime extent size		*/
    -	__u32		agblocks;	/* fsblocks in an AG		*/
    -	__u32		agcount;	/* number of allocation groups	*/
    -	__u32		logblocks;	/* fsblocks in the log		*/
    -	__u32		sectsize;	/* (data) sector size, bytes	*/
    -	__u32		inodesize;	/* inode size in bytes		*/
    -	__u32		imaxpct;	/* max allowed inode space(%)	*/
    -	__u64		datablocks;	/* fsblocks in data subvolume	*/
    -	__u64		rtblocks;	/* fsblocks in realtime subvol	*/
    -	__u64		rtextents;	/* rt extents in realtime subvol*/
    -	__u64		logstart;	/* starting fsblock of the log	*/
    -	unsigned char	uuid[16];	/* unique id of the filesystem	*/
    -	__u32		sunit;		/* stripe unit, fsblocks	*/
    -	__u32		swidth;		/* stripe width, fsblocks	*/
    -	__s32		version;	/* structure version		*/
    -	__u32		flags;		/* superblock version flags	*/
    -	__u32		logsectsize;	/* log sector size, bytes	*/
    -	__u32		rtsectsize;	/* realtime sector size, bytes	*/
    -	__u32		dirblocksize;	/* directory block size, bytes	*/
    -} xfs_fsop_geom_v1_t;
    -
    -/*
    - * Output for XFS_IOC_FSGEOMETRY
    - */
    -typedef struct xfs_fsop_geom {
    -	__u32		blocksize;	/* filesystem (data) block size */
    -	__u32		rtextsize;	/* realtime extent size		*/
    -	__u32		agblocks;	/* fsblocks in an AG		*/
    -	__u32		agcount;	/* number of allocation groups	*/
    -	__u32		logblocks;	/* fsblocks in the log		*/
    -	__u32		sectsize;	/* (data) sector size, bytes	*/
    -	__u32		inodesize;	/* inode size in bytes		*/
    -	__u32		imaxpct;	/* max allowed inode space(%)	*/
    -	__u64		datablocks;	/* fsblocks in data subvolume	*/
    -	__u64		rtblocks;	/* fsblocks in realtime subvol	*/
    -	__u64		rtextents;	/* rt extents in realtime subvol*/
    -	__u64		logstart;	/* starting fsblock of the log	*/
    -	unsigned char	uuid[16];	/* unique id of the filesystem	*/
    -	__u32		sunit;		/* stripe unit, fsblocks	*/
    -	__u32		swidth;		/* stripe width, fsblocks	*/
    -	__s32		version;	/* structure version		*/
    -	__u32		flags;		/* superblock version flags	*/
    -	__u32		logsectsize;	/* log sector size, bytes	*/
    -	__u32		rtsectsize;	/* realtime sector size, bytes	*/
    -	__u32		dirblocksize;	/* directory block size, bytes	*/
    -	__u32		logsunit;	/* log stripe unit, bytes */
    -} xfs_fsop_geom_t;
    -
    -/* Output for XFS_FS_COUNTS */
    -typedef struct xfs_fsop_counts {
    -	__u64	freedata;	/* free data section blocks */
    -	__u64	freertx;	/* free rt extents */
    -	__u64	freeino;	/* free inodes */
    -	__u64	allocino;	/* total allocated inodes */
    -} xfs_fsop_counts_t;
    -
    -/* Input/Output for XFS_GET_RESBLKS and XFS_SET_RESBLKS */
    -typedef struct xfs_fsop_resblks {
    -	__u64  resblks;
    -	__u64  resblks_avail;
    -} xfs_fsop_resblks_t;
    -
    -#define XFS_FSOP_GEOM_VERSION	0
    -
    -#define XFS_FSOP_GEOM_FLAGS_ATTR	0x0001	/* attributes in use	*/
    -#define XFS_FSOP_GEOM_FLAGS_NLINK	0x0002	/* 32-bit nlink values	*/
    -#define XFS_FSOP_GEOM_FLAGS_QUOTA	0x0004	/* quotas enabled	*/
    -#define XFS_FSOP_GEOM_FLAGS_IALIGN	0x0008	/* inode alignment	*/
    -#define XFS_FSOP_GEOM_FLAGS_DALIGN	0x0010	/* large data alignment */
    -#define XFS_FSOP_GEOM_FLAGS_SHARED	0x0020	/* read-only shared	*/
    -#define XFS_FSOP_GEOM_FLAGS_EXTFLG	0x0040	/* special extent flag	*/
    -#define XFS_FSOP_GEOM_FLAGS_DIRV2	0x0080	/* directory version 2	*/
    -#define XFS_FSOP_GEOM_FLAGS_LOGV2	0x0100	/* log format version 2	*/
    -#define XFS_FSOP_GEOM_FLAGS_SECTOR	0x0200	/* sector sizes >1BB	*/
    -#define XFS_FSOP_GEOM_FLAGS_ATTR2	0x0400	/* inline attributes rework */
    -
    -
    -/*
    - * Minimum and maximum sizes need for growth checks
    - */
    -#define XFS_MIN_AG_BLOCKS	64
    -#define XFS_MIN_LOG_BLOCKS	512
    -#define XFS_MAX_LOG_BLOCKS	(64 * 1024)
    -#define XFS_MIN_LOG_BYTES	(256 * 1024)
    -#define XFS_MAX_LOG_BYTES	(128 * 1024 * 1024)
    -
    -/*
    - * Structures for XFS_IOC_FSGROWFSDATA, XFS_IOC_FSGROWFSLOG & XFS_IOC_FSGROWFSRT
    - */
    -typedef struct xfs_growfs_data {
    -	__u64		newblocks;	/* new data subvol size, fsblocks */
    -	__u32		imaxpct;	/* new inode space percentage limit */
    -} xfs_growfs_data_t;
    -
    -typedef struct xfs_growfs_log {
    -	__u32		newblocks;	/* new log size, fsblocks */
    -	__u32		isint;		/* 1 if new log is internal */
    -} xfs_growfs_log_t;
    -
    -typedef struct xfs_growfs_rt {
    -	__u64		newblocks;	/* new realtime size, fsblocks */
    -	__u32		extsize;	/* new realtime extent size, fsblocks */
    -} xfs_growfs_rt_t;
    -
    -
    -/*
    - * Structures returned from ioctl XFS_IOC_FSBULKSTAT & XFS_IOC_FSBULKSTAT_SINGLE
    - */
    -typedef struct xfs_bstime {
    -	time_t		tv_sec;		/* seconds		*/
    -	__s32		tv_nsec;	/* and nanoseconds	*/
    -} xfs_bstime_t;
    -
    -typedef struct xfs_bstat {
    -	__u64		bs_ino;		/* inode number			*/
    -	__u16		bs_mode;	/* type and mode		*/
    -	__u16		bs_nlink;	/* number of links		*/
    -	__u32		bs_uid;		/* user id			*/
    -	__u32		bs_gid;		/* group id			*/
    -	__u32		bs_rdev;	/* device value			*/
    -	__s32		bs_blksize;	/* block size			*/
    -	__s64		bs_size;	/* file size			*/
    -	xfs_bstime_t	bs_atime;	/* access time			*/
    -	xfs_bstime_t	bs_mtime;	/* modify time			*/
    -	xfs_bstime_t	bs_ctime;	/* inode change time		*/
    -	int64_t		bs_blocks;	/* number of blocks		*/
    -	__u32		bs_xflags;	/* extended flags		*/
    -	__s32		bs_extsize;	/* extent size			*/
    -	__s32		bs_extents;	/* number of extents		*/
    -	__u32		bs_gen;		/* generation count		*/
    -	__u16		bs_projid;	/* project id			*/
    -	unsigned char	bs_pad[14];	/* pad space, unused		*/
    -	__u32		bs_dmevmask;	/* DMIG event mask		*/
    -	__u16		bs_dmstate;	/* DMIG state info		*/
    -	__u16		bs_aextents;	/* attribute number of extents	*/
    -} xfs_bstat_t;
    -
    -/*
    - * The user-level BulkStat Request interface structure.
    - */
    -typedef struct xfs_fsop_bulkreq {
    -	__u64		__user *lastip;	/* last inode # pointer		*/
    -	__s32		icount;		/* count of entries in buffer	*/
    -	void		__user *ubuffer;/* user buffer for inode desc.	*/
    -	__s32		__user *ocount;	/* output count pointer		*/
    -} xfs_fsop_bulkreq_t;
    -
    -
    -/*
    - * Structures returned from xfs_inumbers routine (XFS_IOC_FSINUMBERS).
    - */
    -typedef struct xfs_inogrp {
    -	__u64		xi_startino;	/* starting inode number	*/
    -	__s32		xi_alloccount;	/* # bits set in allocmask	*/
    -	__u64		xi_allocmask;	/* mask of allocated inodes	*/
    -} xfs_inogrp_t;
    -
    -
    -/*
    - * Error injection.
    - */
    -typedef struct xfs_error_injection {
    -	__s32		fd;
    -	__s32		errtag;
    -} xfs_error_injection_t;
    -
    -
    -/*
    - * The user-level Handle Request interface structure.
    - */
    -typedef struct xfs_fsop_handlereq {
    -	__u32		fd;		/* fd for FD_TO_HANDLE		*/
    -	void		__user *path;	/* user pathname		*/
    -	__u32		oflags;		/* open flags			*/
    -	void		__user *ihandle;/* user supplied handle		*/
    -	__u32		ihandlen;	/* user supplied length		*/
    -	void		__user *ohandle;/* user buffer for handle	*/
    -	__u32		__user *ohandlen;/* user buffer length		*/
    -} xfs_fsop_handlereq_t;
    -
    -/*
    - * Compound structures for passing args through Handle Request interfaces
    - * xfs_fssetdm_by_handle, xfs_attrlist_by_handle, xfs_attrmulti_by_handle
    - * - ioctls: XFS_IOC_FSSETDM_BY_HANDLE, XFS_IOC_ATTRLIST_BY_HANDLE, and
    - *	     XFS_IOC_ATTRMULTI_BY_HANDLE
    - */
    -
    -typedef struct xfs_fsop_setdm_handlereq {
    -	struct xfs_fsop_handlereq	hreq;	/* handle information	*/
    -	struct fsdmidata		__user *data;	/* DMAPI data	*/
    -} xfs_fsop_setdm_handlereq_t;
    -
    -typedef struct xfs_attrlist_cursor {
    -	__u32		opaque[4];
    -} xfs_attrlist_cursor_t;
    -
    -typedef struct xfs_fsop_attrlist_handlereq {
    -	struct xfs_fsop_handlereq	hreq; /* handle interface structure */
    -	struct xfs_attrlist_cursor	pos; /* opaque cookie, list offset */
    -	__u32				flags;	/* which namespace to use */
    -	__u32				buflen;	/* length of buffer supplied */
    -	void				__user *buffer;	/* returned names */
    -} xfs_fsop_attrlist_handlereq_t;
    -
    -typedef struct xfs_attr_multiop {
    -	__u32		am_opcode;
    -	__s32		am_error;
    -	void		__user *am_attrname;
    -	void		__user *am_attrvalue;
    -	__u32		am_length;
    -	__u32		am_flags;
    -} xfs_attr_multiop_t;
    -
    -typedef struct xfs_fsop_attrmulti_handlereq {
    -	struct xfs_fsop_handlereq	hreq; /* handle interface structure */
    -	__u32				opcount;/* count of following multiop */
    -	struct xfs_attr_multiop		__user *ops; /* attr_multi data */
    -} xfs_fsop_attrmulti_handlereq_t;
    -
    -/*
    - * per machine unique filesystem identifier types.
    - */
    -typedef struct { __u32 val[2]; } xfs_fsid_t; /* file system id type */
    -
    -
    -#ifndef HAVE_FID
    -#define MAXFIDSZ	46
    -
    -typedef struct fid {
    -	__u16		fid_len;		/* length of data in bytes */
    -	unsigned char	fid_data[MAXFIDSZ];	/* data (fid_len worth)  */
    -} fid_t;
    -#endif
    -
    -typedef struct xfs_fid {
    -	__u16	xfs_fid_len;		/* length of remainder	*/
    -	__u16	xfs_fid_pad;
    -	__u32	xfs_fid_gen;		/* generation number	*/
    -	__u64	xfs_fid_ino;		/* 64 bits inode number */
    -} xfs_fid_t;
    -
    -typedef struct xfs_fid2 {
    -	__u16	fid_len;	/* length of remainder */
    -	__u16	fid_pad;	/* padding, must be zero */
    -	__u32	fid_gen;	/* generation number */
    -	__u64	fid_ino;	/* inode number */
    -} xfs_fid2_t;
    -
    -typedef struct xfs_handle {
    -	union {
    -		__s64	    align;	/* force alignment of ha_fid	 */
    -		xfs_fsid_t  _ha_fsid;	/* unique file system identifier */
    -	} ha_u;
    -	xfs_fid_t	ha_fid;		/* file system specific file ID	 */
    -} xfs_handle_t;
    -#define ha_fsid ha_u._ha_fsid
    -
    -#define XFS_HSIZE(handle)	(((char *) &(handle).ha_fid.xfs_fid_pad	 \
    -				 - (char *) &(handle))			  \
    -				 + (handle).ha_fid.xfs_fid_len)
    -
    -#define XFS_HANDLE_CMP(h1, h2)	memcmp(h1, h2, sizeof(xfs_handle_t))
    -
    -#define FSHSIZE		sizeof(fsid_t)
    -
    -/* 
    - * Flags for going down operation
    - */
    -#define XFS_FSOP_GOING_FLAGS_DEFAULT		0x0	/* going down */
    -#define XFS_FSOP_GOING_FLAGS_LOGFLUSH		0x1	/* flush log but not data */
    -#define XFS_FSOP_GOING_FLAGS_NOLOGFLUSH		0x2	/* don't flush log nor data */
    -
    -/*
    - * ioctl commands that are used by Linux filesystems
    - */
    -#define XFS_IOC_GETXFLAGS	_IOR('f', 1, long)
    -#define XFS_IOC_SETXFLAGS	_IOW('f', 2, long)
    -#define XFS_IOC_GETVERSION	_IOR('v', 1, long)
    -
    -/*
    - * ioctl commands that replace IRIX fcntl()'s
    - * For 'documentation' purposed more than anything else,
    - * the "cmd #" field reflects the IRIX fcntl number.
    - */
    -#define XFS_IOC_ALLOCSP		_IOW ('X', 10, struct xfs_flock64)
    -#define XFS_IOC_FREESP		_IOW ('X', 11, struct xfs_flock64)
    -#define XFS_IOC_DIOINFO		_IOR ('X', 30, struct dioattr)
    -#define XFS_IOC_FSGETXATTR	_IOR ('X', 31, struct fsxattr)
    -#define XFS_IOC_FSSETXATTR	_IOW ('X', 32, struct fsxattr)
    -#define XFS_IOC_ALLOCSP64	_IOW ('X', 36, struct xfs_flock64)
    -#define XFS_IOC_FREESP64	_IOW ('X', 37, struct xfs_flock64)
    -#define XFS_IOC_GETBMAP		_IOWR('X', 38, struct getbmap)
    -#define XFS_IOC_FSSETDM		_IOW ('X', 39, struct fsdmidata)
    -#define XFS_IOC_RESVSP		_IOW ('X', 40, struct xfs_flock64)
    -#define XFS_IOC_UNRESVSP	_IOW ('X', 41, struct xfs_flock64)
    -#define XFS_IOC_RESVSP64	_IOW ('X', 42, struct xfs_flock64)
    -#define XFS_IOC_UNRESVSP64	_IOW ('X', 43, struct xfs_flock64)
    -#define XFS_IOC_GETBMAPA	_IOWR('X', 44, struct getbmap)
    -#define XFS_IOC_FSGETXATTRA	_IOR ('X', 45, struct fsxattr)
    -/*	XFS_IOC_SETBIOSIZE ---- deprecated 46	   */
    -/*	XFS_IOC_GETBIOSIZE ---- deprecated 47	   */
    -//#define XFS_IOC_GETBMAPX	_IOWR('X', 56, struct getbmapx)
    -#define XFS_IOC_GETBMAPX	_IOC(IOC_INOUT, 'X', 56, (256 * sizeof(struct getbmapx)))
    -
    -
    -/*
    - * ioctl commands that replace IRIX syssgi()'s
    - */
    -#define XFS_IOC_FSGEOMETRY_V1	     _IOR ('X', 100, struct xfs_fsop_geom_v1)
    -#define XFS_IOC_FSBULKSTAT	     _IOWR('X', 101, struct xfs_fsop_bulkreq)
    -#define XFS_IOC_FSBULKSTAT_SINGLE    _IOWR('X', 102, struct xfs_fsop_bulkreq)
    -#define XFS_IOC_FSINUMBERS	     _IOWR('X', 103, struct xfs_fsop_bulkreq)
    -#define XFS_IOC_PATH_TO_FSHANDLE     _IOWR('X', 104, struct xfs_fsop_handlereq)
    -#define XFS_IOC_PATH_TO_HANDLE	     _IOWR('X', 105, struct xfs_fsop_handlereq)
    -#define XFS_IOC_FD_TO_HANDLE	     _IOWR('X', 106, struct xfs_fsop_handlereq)
    -#define XFS_IOC_OPEN_BY_HANDLE	     _IOWR('X', 107, struct xfs_fsop_handlereq)
    -#define XFS_IOC_READLINK_BY_HANDLE   _IOWR('X', 108, struct xfs_fsop_handlereq)
    -#define XFS_IOC_SWAPEXT		     _IOWR('X', 109, struct xfs_swapext)
    -#define XFS_IOC_FSGROWFSDATA	     _IOW ('X', 110, struct xfs_growfs_data)
    -#define XFS_IOC_FSGROWFSLOG	     _IOW ('X', 111, struct xfs_growfs_log)
    -#define XFS_IOC_FSGROWFSRT	     _IOW ('X', 112, struct xfs_growfs_rt)
    -#define XFS_IOC_FSCOUNTS	     _IOR ('X', 113, struct xfs_fsop_counts)
    -#define XFS_IOC_SET_RESBLKS	     _IOWR('X', 114, struct xfs_fsop_resblks)
    -#define XFS_IOC_GET_RESBLKS	     _IOR ('X', 115, struct xfs_fsop_resblks)
    -#define XFS_IOC_ERROR_INJECTION	     _IOW ('X', 116, struct xfs_error_injection)
    -#define XFS_IOC_ERROR_CLEARALL	     _IOW ('X', 117, struct xfs_error_injection)
    -/*	XFS_IOC_ATTRCTL_BY_HANDLE -- deprecated 118	 */
    -#define XFS_IOC_FREEZE		     _IOWR('X', 119, int)
    -#define XFS_IOC_THAW		     _IOWR('X', 120, int)
    -#define XFS_IOC_FSSETDM_BY_HANDLE    _IOW ('X', 121, struct xfs_fsop_setdm_handlereq)
    -#define XFS_IOC_ATTRLIST_BY_HANDLE   _IOW ('X', 122, struct xfs_fsop_attrlist_handlereq)
    -#define XFS_IOC_ATTRMULTI_BY_HANDLE  _IOW ('X', 123, struct xfs_fsop_attrmulti_handlereq)
    -#define XFS_IOC_FSGEOMETRY	     _IOR ('X', 124, struct xfs_fsop_geom)
    -#define XFS_IOC_GOINGDOWN	     _IOR ('X', 125, __uint32_t)
    -/*	XFS_IOC_GETFSUUID ---------- deprecated 140	 */
    -
    -
    -#ifndef HAVE_BBMACROS
    -/*
    - * Block I/O parameterization.	A basic block (BB) is the lowest size of
    - * filesystem allocation, and must equal 512.  Length units given to bio
    - * routines are in BB's.
    - */
    -#define BBSHIFT		9
    -#define BBSIZE		(1<> BBSHIFT)
    -#define BTOBBT(bytes)	((__u64)(bytes) >> BBSHIFT)
    -#define BBTOB(bbs)	((bbs) << BBSHIFT)
    -#endif
    -
    -#endif	/* __XFS_FS_H__ */
    -
    diff --git a/sys/gnu/fs/xfs/xfs_fsops.c b/sys/gnu/fs/xfs/xfs_fsops.c
    deleted file mode 100644
    index 87341a54928..00000000000
    --- a/sys/gnu/fs/xfs/xfs_fsops.c
    +++ /dev/null
    @@ -1,599 +0,0 @@
    -/*
    - * Copyright (c) 2000-2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_inum.h"
    -#include "xfs_log.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_inode_item.h"
    -#include "xfs_btree.h"
    -#include "xfs_error.h"
    -#include "xfs_alloc.h"
    -#include "xfs_ialloc.h"
    -#include "xfs_fsops.h"
    -#include "xfs_itable.h"
    -#include "xfs_trans_space.h"
    -#include "xfs_rtalloc.h"
    -#include "xfs_rw.h"
    -
    -/*
    - * File system operations
    - */
    -
    -int
    -xfs_fs_geometry(
    -	xfs_mount_t		*mp,
    -	xfs_fsop_geom_t		*geo,
    -	int			new_version)
    -{
    -	geo->blocksize = mp->m_sb.sb_blocksize;
    -	geo->rtextsize = mp->m_sb.sb_rextsize;
    -	geo->agblocks = mp->m_sb.sb_agblocks;
    -	geo->agcount = mp->m_sb.sb_agcount;
    -	geo->logblocks = mp->m_sb.sb_logblocks;
    -	geo->sectsize = mp->m_sb.sb_sectsize;
    -	geo->inodesize = mp->m_sb.sb_inodesize;
    -	geo->imaxpct = mp->m_sb.sb_imax_pct;
    -	geo->datablocks = mp->m_sb.sb_dblocks;
    -	geo->rtblocks = mp->m_sb.sb_rblocks;
    -	geo->rtextents = mp->m_sb.sb_rextents;
    -	geo->logstart = mp->m_sb.sb_logstart;
    -	ASSERT(sizeof(geo->uuid)==sizeof(mp->m_sb.sb_uuid));
    -	memcpy(geo->uuid, &mp->m_sb.sb_uuid, sizeof(mp->m_sb.sb_uuid));
    -	if (new_version >= 2) {
    -		geo->sunit = mp->m_sb.sb_unit;
    -		geo->swidth = mp->m_sb.sb_width;
    -	}
    -	if (new_version >= 3) {
    -		geo->version = XFS_FSOP_GEOM_VERSION;
    -		geo->flags =
    -			(XFS_SB_VERSION_HASATTR(&mp->m_sb) ?
    -				XFS_FSOP_GEOM_FLAGS_ATTR : 0) |
    -			(XFS_SB_VERSION_HASNLINK(&mp->m_sb) ?
    -				XFS_FSOP_GEOM_FLAGS_NLINK : 0) |
    -			(XFS_SB_VERSION_HASQUOTA(&mp->m_sb) ?
    -				XFS_FSOP_GEOM_FLAGS_QUOTA : 0) |
    -			(XFS_SB_VERSION_HASALIGN(&mp->m_sb) ?
    -				XFS_FSOP_GEOM_FLAGS_IALIGN : 0) |
    -			(XFS_SB_VERSION_HASDALIGN(&mp->m_sb) ?
    -				XFS_FSOP_GEOM_FLAGS_DALIGN : 0) |
    -			(XFS_SB_VERSION_HASSHARED(&mp->m_sb) ?
    -				XFS_FSOP_GEOM_FLAGS_SHARED : 0) |
    -			(XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb) ?
    -				XFS_FSOP_GEOM_FLAGS_EXTFLG : 0) |
    -			(XFS_SB_VERSION_HASDIRV2(&mp->m_sb) ?
    -				XFS_FSOP_GEOM_FLAGS_DIRV2 : 0) |
    -			(XFS_SB_VERSION_HASSECTOR(&mp->m_sb) ?
    -				XFS_FSOP_GEOM_FLAGS_SECTOR : 0) |
    -			(XFS_SB_VERSION_HASATTR2(&mp->m_sb) ?
    -				XFS_FSOP_GEOM_FLAGS_ATTR2 : 0);
    -		geo->logsectsize = XFS_SB_VERSION_HASSECTOR(&mp->m_sb) ?
    -				mp->m_sb.sb_logsectsize : BBSIZE;
    -		geo->rtsectsize = mp->m_sb.sb_blocksize;
    -		geo->dirblocksize = mp->m_dirblksize;
    -	}
    -	if (new_version >= 4) {
    -		geo->flags |=
    -			(XFS_SB_VERSION_HASLOGV2(&mp->m_sb) ?
    -				XFS_FSOP_GEOM_FLAGS_LOGV2 : 0);
    -		geo->logsunit = mp->m_sb.sb_logsunit;
    -	}
    -	return 0;
    -}
    -
    -static int
    -xfs_growfs_data_private(
    -	xfs_mount_t		*mp,		/* mount point for filesystem */
    -	xfs_growfs_data_t	*in)		/* growfs data input struct */
    -{
    -	xfs_agf_t		*agf;
    -	xfs_agi_t		*agi;
    -	xfs_agnumber_t		agno;
    -	xfs_extlen_t		agsize;
    -	xfs_extlen_t		tmpsize;
    -	xfs_alloc_rec_t		*arec;
    -	xfs_btree_sblock_t	*block;
    -	xfs_buf_t		*bp;
    -	int			bucket;
    -	int			dpct;
    -	int			error;
    -	xfs_agnumber_t		nagcount;
    -	xfs_agnumber_t		nagimax = 0;
    -	xfs_rfsblock_t		nb, nb_mod;
    -	xfs_rfsblock_t		new;
    -	xfs_rfsblock_t		nfree;
    -	xfs_agnumber_t		oagcount;
    -	int			pct;
    -	xfs_sb_t		*sbp;
    -	xfs_trans_t		*tp;
    -
    -	nb = in->newblocks;
    -	pct = in->imaxpct;
    -	if (nb < mp->m_sb.sb_dblocks || pct < 0 || pct > 100)
    -		return XFS_ERROR(EINVAL);
    -	dpct = pct - mp->m_sb.sb_imax_pct;
    -	error = xfs_read_buf(mp, mp->m_ddev_targp,
    -			XFS_FSB_TO_BB(mp, nb) - XFS_FSS_TO_BB(mp, 1),
    -			XFS_FSS_TO_BB(mp, 1), 0, &bp);
    -	if (error)
    -		return error;
    -	ASSERT(bp);
    -	xfs_buf_relse(bp);
    -
    -	new = nb;	/* use new as a temporary here */
    -	nb_mod = do_div(new, mp->m_sb.sb_agblocks);
    -	nagcount = new + (nb_mod != 0);
    -	if (nb_mod && nb_mod < XFS_MIN_AG_BLOCKS) {
    -		nagcount--;
    -		nb = nagcount * mp->m_sb.sb_agblocks;
    -		if (nb < mp->m_sb.sb_dblocks)
    -			return XFS_ERROR(EINVAL);
    -	}
    -	new = nb - mp->m_sb.sb_dblocks;
    -	oagcount = mp->m_sb.sb_agcount;
    -	if (nagcount > oagcount) {
    -		down_write(&mp->m_peraglock);
    -		mp->m_perag = kmem_realloc(mp->m_perag,
    -			sizeof(xfs_perag_t) * nagcount,
    -			sizeof(xfs_perag_t) * oagcount,
    -			KM_SLEEP);
    -		memset(&mp->m_perag[oagcount], 0,
    -			(nagcount - oagcount) * sizeof(xfs_perag_t));
    -		mp->m_flags |= XFS_MOUNT_32BITINODES;
    -		nagimax = xfs_initialize_perag(XFS_MTOVFS(mp), mp, nagcount);
    -		up_write(&mp->m_peraglock);
    -	}
    -	tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFS);
    -	if ((error = xfs_trans_reserve(tp, XFS_GROWFS_SPACE_RES(mp),
    -			XFS_GROWDATA_LOG_RES(mp), 0, 0, 0))) {
    -		xfs_trans_cancel(tp, 0);
    -		return error;
    -	}
    -
    -	nfree = 0;
    -	for (agno = nagcount - 1; agno >= oagcount; agno--, new -= agsize) {
    -		/*
    -		 * AG freelist header block
    -		 */
    -		bp = xfs_buf_get(mp->m_ddev_targp,
    -				  XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)),
    -				  XFS_FSS_TO_BB(mp, 1), 0);
    -		agf = XFS_BUF_TO_AGF(bp);
    -		memset(agf, 0, mp->m_sb.sb_sectsize);
    -		agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC);
    -		agf->agf_versionnum = cpu_to_be32(XFS_AGF_VERSION);
    -		agf->agf_seqno = cpu_to_be32(agno);
    -		if (agno == nagcount - 1)
    -			agsize =
    -				nb -
    -				(agno * (xfs_rfsblock_t)mp->m_sb.sb_agblocks);
    -		else
    -			agsize = mp->m_sb.sb_agblocks;
    -		agf->agf_length = cpu_to_be32(agsize);
    -		agf->agf_roots[XFS_BTNUM_BNOi] = cpu_to_be32(XFS_BNO_BLOCK(mp));
    -		agf->agf_roots[XFS_BTNUM_CNTi] = cpu_to_be32(XFS_CNT_BLOCK(mp));
    -		agf->agf_levels[XFS_BTNUM_BNOi] = cpu_to_be32(1);
    -		agf->agf_levels[XFS_BTNUM_CNTi] = cpu_to_be32(1);
    -		agf->agf_flfirst = 0;
    -		agf->agf_fllast = cpu_to_be32(XFS_AGFL_SIZE(mp) - 1);
    -		agf->agf_flcount = 0;
    -		tmpsize = agsize - XFS_PREALLOC_BLOCKS(mp);
    -		agf->agf_freeblks = cpu_to_be32(tmpsize);
    -		agf->agf_longest = cpu_to_be32(tmpsize);
    -		error = xfs_bwrite(mp, bp);
    -		if (error) {
    -			goto error0;
    -		}
    -		/*
    -		 * AG inode header block
    -		 */
    -		bp = xfs_buf_get(mp->m_ddev_targp,
    -				  XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
    -				  XFS_FSS_TO_BB(mp, 1), 0);
    -		agi = XFS_BUF_TO_AGI(bp);
    -		memset(agi, 0, mp->m_sb.sb_sectsize);
    -		agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC);
    -		agi->agi_versionnum = cpu_to_be32(XFS_AGI_VERSION);
    -		agi->agi_seqno = cpu_to_be32(agno);
    -		agi->agi_length = cpu_to_be32(agsize);
    -		agi->agi_count = 0;
    -		agi->agi_root = cpu_to_be32(XFS_IBT_BLOCK(mp));
    -		agi->agi_level = cpu_to_be32(1);
    -		agi->agi_freecount = 0;
    -		agi->agi_newino = cpu_to_be32(NULLAGINO);
    -		agi->agi_dirino = cpu_to_be32(NULLAGINO);
    -		for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++)
    -			agi->agi_unlinked[bucket] = cpu_to_be32(NULLAGINO);
    -		error = xfs_bwrite(mp, bp);
    -		if (error) {
    -			goto error0;
    -		}
    -		/*
    -		 * BNO btree root block
    -		 */
    -		bp = xfs_buf_get(mp->m_ddev_targp,
    -			XFS_AGB_TO_DADDR(mp, agno, XFS_BNO_BLOCK(mp)),
    -			BTOBB(mp->m_sb.sb_blocksize), 0);
    -		block = XFS_BUF_TO_SBLOCK(bp);
    -		memset(block, 0, mp->m_sb.sb_blocksize);
    -		block->bb_magic = cpu_to_be32(XFS_ABTB_MAGIC);
    -		block->bb_level = 0;
    -		block->bb_numrecs = cpu_to_be16(1);
    -		block->bb_leftsib = cpu_to_be32(NULLAGBLOCK);
    -		block->bb_rightsib = cpu_to_be32(NULLAGBLOCK);
    -		arec = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize, xfs_alloc,
    -			block, 1, mp->m_alloc_mxr[0]);
    -		arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp));
    -		arec->ar_blockcount = cpu_to_be32(
    -			agsize - be32_to_cpu(arec->ar_startblock));
    -		error = xfs_bwrite(mp, bp);
    -		if (error) {
    -			goto error0;
    -		}
    -		/*
    -		 * CNT btree root block
    -		 */
    -		bp = xfs_buf_get(mp->m_ddev_targp,
    -			XFS_AGB_TO_DADDR(mp, agno, XFS_CNT_BLOCK(mp)),
    -			BTOBB(mp->m_sb.sb_blocksize), 0);
    -		block = XFS_BUF_TO_SBLOCK(bp);
    -		memset(block, 0, mp->m_sb.sb_blocksize);
    -		block->bb_magic = cpu_to_be32(XFS_ABTC_MAGIC);
    -		block->bb_level = 0;
    -		block->bb_numrecs = cpu_to_be16(1);
    -		block->bb_leftsib = cpu_to_be32(NULLAGBLOCK);
    -		block->bb_rightsib = cpu_to_be32(NULLAGBLOCK);
    -		arec = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize, xfs_alloc,
    -			block, 1, mp->m_alloc_mxr[0]);
    -		arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp));
    -		arec->ar_blockcount = cpu_to_be32(
    -			agsize - be32_to_cpu(arec->ar_startblock));
    -		nfree += be32_to_cpu(arec->ar_blockcount);
    -		error = xfs_bwrite(mp, bp);
    -		if (error) {
    -			goto error0;
    -		}
    -		/*
    -		 * INO btree root block
    -		 */
    -		bp = xfs_buf_get(mp->m_ddev_targp,
    -			XFS_AGB_TO_DADDR(mp, agno, XFS_IBT_BLOCK(mp)),
    -			BTOBB(mp->m_sb.sb_blocksize), 0);
    -		block = XFS_BUF_TO_SBLOCK(bp);
    -		memset(block, 0, mp->m_sb.sb_blocksize);
    -		block->bb_magic = cpu_to_be32(XFS_IBT_MAGIC);
    -		block->bb_level = 0;
    -		block->bb_numrecs = 0;
    -		block->bb_leftsib = cpu_to_be32(NULLAGBLOCK);
    -		block->bb_rightsib = cpu_to_be32(NULLAGBLOCK);
    -		error = xfs_bwrite(mp, bp);
    -		if (error) {
    -			goto error0;
    -		}
    -	}
    -	xfs_trans_agblocks_delta(tp, nfree);
    -	/*
    -	 * There are new blocks in the old last a.g.
    -	 */
    -	if (new) {
    -		/*
    -		 * Change the agi length.
    -		 */
    -		error = xfs_ialloc_read_agi(mp, tp, agno, &bp);
    -		if (error) {
    -			goto error0;
    -		}
    -		ASSERT(bp);
    -		agi = XFS_BUF_TO_AGI(bp);
    -		be32_add(&agi->agi_length, new);
    -		ASSERT(nagcount == oagcount ||
    -		       be32_to_cpu(agi->agi_length) == mp->m_sb.sb_agblocks);
    -		xfs_ialloc_log_agi(tp, bp, XFS_AGI_LENGTH);
    -		/*
    -		 * Change agf length.
    -		 */
    -		error = xfs_alloc_read_agf(mp, tp, agno, 0, &bp);
    -		if (error) {
    -			goto error0;
    -		}
    -		ASSERT(bp);
    -		agf = XFS_BUF_TO_AGF(bp);
    -		be32_add(&agf->agf_length, new);
    -		ASSERT(be32_to_cpu(agf->agf_length) ==
    -		       be32_to_cpu(agi->agi_length));
    -		/*
    -		 * Free the new space.
    -		 */
    -		error = xfs_free_extent(tp, XFS_AGB_TO_FSB(mp, agno,
    -			be32_to_cpu(agf->agf_length) - new), new);
    -		if (error) {
    -			goto error0;
    -		}
    -	}
    -	if (nagcount > oagcount)
    -		xfs_trans_mod_sb(tp, XFS_TRANS_SB_AGCOUNT, nagcount - oagcount);
    -	if (nb > mp->m_sb.sb_dblocks)
    -		xfs_trans_mod_sb(tp, XFS_TRANS_SB_DBLOCKS,
    -				 nb - mp->m_sb.sb_dblocks);
    -	if (nfree)
    -		xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, nfree);
    -	if (dpct)
    -		xfs_trans_mod_sb(tp, XFS_TRANS_SB_IMAXPCT, dpct);
    -	error = xfs_trans_commit(tp, 0, NULL);
    -	if (error) {
    -		return error;
    -	}
    -	/* New allocation groups fully initialized, so update mount struct */
    -	if (nagimax)
    -		mp->m_maxagi = nagimax;
    -	if (mp->m_sb.sb_imax_pct) {
    -		__uint64_t icount = mp->m_sb.sb_dblocks * mp->m_sb.sb_imax_pct;
    -		do_div(icount, 100);
    -		mp->m_maxicount = icount << mp->m_sb.sb_inopblog;
    -	} else
    -		mp->m_maxicount = 0;
    -	for (agno = 1; agno < nagcount; agno++) {
    -		error = xfs_read_buf(mp, mp->m_ddev_targp,
    -				  XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)),
    -				  XFS_FSS_TO_BB(mp, 1), 0, &bp);
    -		if (error) {
    -			xfs_fs_cmn_err(CE_WARN, mp,
    -			"error %d reading secondary superblock for ag %d",
    -				error, agno);
    -			break;
    -		}
    -		sbp = XFS_BUF_TO_SBP(bp);
    -		xfs_xlatesb(sbp, &mp->m_sb, -1, XFS_SB_ALL_BITS);
    -		/*
    -		 * If we get an error writing out the alternate superblocks,
    -		 * just issue a warning and continue.  The real work is
    -		 * already done and committed.
    -		 */
    -		if (!(error = xfs_bwrite(mp, bp))) {
    -			continue;
    -		} else {
    -			xfs_fs_cmn_err(CE_WARN, mp,
    -		"write error %d updating secondary superblock for ag %d",
    -				error, agno);
    -			break; /* no point in continuing */
    -		}
    -	}
    -	return 0;
    -
    - error0:
    -	xfs_trans_cancel(tp, XFS_TRANS_ABORT);
    -	return error;
    -}
    -
    -static int
    -xfs_growfs_log_private(
    -	xfs_mount_t		*mp,	/* mount point for filesystem */
    -	xfs_growfs_log_t	*in)	/* growfs log input struct */
    -{
    -	xfs_extlen_t		nb;
    -
    -	nb = in->newblocks;
    -	if (nb < XFS_MIN_LOG_BLOCKS || nb < XFS_B_TO_FSB(mp, XFS_MIN_LOG_BYTES))
    -		return XFS_ERROR(EINVAL);
    -	if (nb == mp->m_sb.sb_logblocks &&
    -	    in->isint == (mp->m_sb.sb_logstart != 0))
    -		return XFS_ERROR(EINVAL);
    -	/*
    -	 * Moving the log is hard, need new interfaces to sync
    -	 * the log first, hold off all activity while moving it.
    -	 * Can have shorter or longer log in the same space,
    -	 * or transform internal to external log or vice versa.
    -	 */
    -	return XFS_ERROR(ENOSYS);
    -}
    -
    -/*
    - * protected versions of growfs function acquire and release locks on the mount
    - * point - exported through ioctls: XFS_IOC_FSGROWFSDATA, XFS_IOC_FSGROWFSLOG,
    - * XFS_IOC_FSGROWFSRT
    - */
    -
    -
    -int
    -xfs_growfs_data(
    -	xfs_mount_t		*mp,
    -	xfs_growfs_data_t	*in)
    -{
    -	int error;
    -	if (!cpsema(&mp->m_growlock))
    -		return XFS_ERROR(EWOULDBLOCK);
    -	error = xfs_growfs_data_private(mp, in);
    -	vsema(&mp->m_growlock);
    -	return error;
    -}
    -
    -int
    -xfs_growfs_log(
    -	xfs_mount_t		*mp,
    -	xfs_growfs_log_t	*in)
    -{
    -	int error;
    -	if (!cpsema(&mp->m_growlock))
    -		return XFS_ERROR(EWOULDBLOCK);
    -	error = xfs_growfs_log_private(mp, in);
    -	vsema(&mp->m_growlock);
    -	return error;
    -}
    -
    -/*
    - * exported through ioctl XFS_IOC_FSCOUNTS
    - */
    -
    -int
    -xfs_fs_counts(
    -	xfs_mount_t		*mp,
    -	xfs_fsop_counts_t	*cnt)
    -{
    -	unsigned long	s;
    -
    -	xfs_icsb_sync_counters_lazy(mp);
    -	s = XFS_SB_LOCK(mp);
    -	cnt->freedata = mp->m_sb.sb_fdblocks;
    -	cnt->freertx = mp->m_sb.sb_frextents;
    -	cnt->freeino = mp->m_sb.sb_ifree;
    -	cnt->allocino = mp->m_sb.sb_icount;
    -	XFS_SB_UNLOCK(mp, s);
    -	return 0;
    -}
    -
    -/*
    - * exported through ioctl XFS_IOC_SET_RESBLKS & XFS_IOC_GET_RESBLKS
    - *
    - * xfs_reserve_blocks is called to set m_resblks
    - * in the in-core mount table. The number of unused reserved blocks
    - * is kept in m_resblks_avail.
    - *
    - * Reserve the requested number of blocks if available. Otherwise return
    - * as many as possible to satisfy the request. The actual number
    - * reserved are returned in outval
    - *
    - * A null inval pointer indicates that only the current reserved blocks
    - * available  should  be returned no settings are changed.
    - */
    -
    -int
    -xfs_reserve_blocks(
    -	xfs_mount_t             *mp,
    -	__uint64_t              *inval,
    -	xfs_fsop_resblks_t      *outval)
    -{
    -	__int64_t		lcounter, delta;
    -	__uint64_t		request;
    -	unsigned long		s;
    -
    -	/* If inval is null, report current values and return */
    -
    -	if (inval == (__uint64_t *)NULL) {
    -		outval->resblks = mp->m_resblks;
    -		outval->resblks_avail = mp->m_resblks_avail;
    -		return 0;
    -	}
    -
    -	request = *inval;
    -	s = XFS_SB_LOCK(mp);
    -
    -	/*
    -	 * If our previous reservation was larger than the current value,
    -	 * then move any unused blocks back to the free pool.
    -	 */
    -
    -	if (mp->m_resblks > request) {
    -		lcounter = mp->m_resblks_avail - request;
    -		if (lcounter  > 0) {		/* release unused blocks */
    -			mp->m_sb.sb_fdblocks += lcounter;
    -			mp->m_resblks_avail -= lcounter;
    -		}
    -		mp->m_resblks = request;
    -	} else {
    -		delta = request - mp->m_resblks;
    -		lcounter = mp->m_sb.sb_fdblocks - delta;
    -		if (lcounter < 0) {
    -			/* We can't satisfy the request, just get what we can */
    -			mp->m_resblks += mp->m_sb.sb_fdblocks;
    -			mp->m_resblks_avail += mp->m_sb.sb_fdblocks;
    -			mp->m_sb.sb_fdblocks = 0;
    -		} else {
    -			mp->m_sb.sb_fdblocks = lcounter;
    -			mp->m_resblks = request;
    -			mp->m_resblks_avail += delta;
    -		}
    -	}
    -
    -	outval->resblks = mp->m_resblks;
    -	outval->resblks_avail = mp->m_resblks_avail;
    -	XFS_SB_UNLOCK(mp, s);
    -	return 0;
    -}
    -
    -void
    -xfs_fs_log_dummy(xfs_mount_t *mp)
    -{
    -	xfs_trans_t *tp;
    -	xfs_inode_t *ip;
    -
    -
    -	tp = _xfs_trans_alloc(mp, XFS_TRANS_DUMMY1);
    -	atomic_inc(&mp->m_active_trans);
    -	if (xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0)) {
    -		xfs_trans_cancel(tp, 0);
    -		return;
    -	}
    -
    -	ip = mp->m_rootip;
    -	xfs_ilock(ip, XFS_ILOCK_EXCL);
    -
    -	xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
    -	xfs_trans_ihold(tp, ip);
    -	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
    -	xfs_trans_set_sync(tp);
    -	xfs_trans_commit(tp, 0, NULL);
    -
    -	xfs_iunlock(ip, XFS_ILOCK_EXCL);
    -}
    -
    -int
    -xfs_fs_goingdown(
    -	xfs_mount_t	*mp,
    -	__uint32_t	inflags)
    -{
    -	switch (inflags) {
    -	case XFS_FSOP_GOING_FLAGS_DEFAULT: {
    -#ifdef RMC
    -		struct xfs_vfs *vfsp = XFS_MTOVFS(mp);
    -		struct super_block *sb = freeze_bdev(vfsp->vfs_super->s_bdev);
    -
    -		if (sb && !IS_ERR(sb)) {
    -			xfs_force_shutdown(mp, XFS_FORCE_UMOUNT);
    -			thaw_bdev(sb->s_bdev, sb);
    -		}
    -#endif
    -		break;
    -	}
    -	case XFS_FSOP_GOING_FLAGS_LOGFLUSH:
    -		xfs_force_shutdown(mp, XFS_FORCE_UMOUNT);
    -		break;
    -	case XFS_FSOP_GOING_FLAGS_NOLOGFLUSH:
    -		xfs_force_shutdown(mp, XFS_FORCE_UMOUNT|XFS_LOG_IO_ERROR);
    -		break;
    -	default:
    -		return XFS_ERROR(EINVAL);
    -	}
    -
    -	return 0;
    -}
    diff --git a/sys/gnu/fs/xfs/xfs_fsops.h b/sys/gnu/fs/xfs/xfs_fsops.h
    deleted file mode 100644
    index 300d0c9d61a..00000000000
    --- a/sys/gnu/fs/xfs/xfs_fsops.h
    +++ /dev/null
    @@ -1,30 +0,0 @@
    -/*
    - * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_FSOPS_H__
    -#define	__XFS_FSOPS_H__
    -
    -extern int xfs_fs_geometry(xfs_mount_t *mp, xfs_fsop_geom_t *geo, int nversion);
    -extern int xfs_growfs_data(xfs_mount_t *mp, xfs_growfs_data_t *in);
    -extern int xfs_growfs_log(xfs_mount_t *mp, xfs_growfs_log_t *in);
    -extern int xfs_fs_counts(xfs_mount_t *mp, xfs_fsop_counts_t *cnt);
    -extern int xfs_reserve_blocks(xfs_mount_t *mp, __uint64_t *inval,
    -				xfs_fsop_resblks_t *outval);
    -extern int xfs_fs_goingdown(xfs_mount_t *mp, __uint32_t inflags);
    -extern void xfs_fs_log_dummy(xfs_mount_t *mp);
    -
    -#endif	/* __XFS_FSOPS_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_ialloc.c b/sys/gnu/fs/xfs/xfs_ialloc.c
    deleted file mode 100644
    index af1a240f0e0..00000000000
    --- a/sys/gnu/fs/xfs/xfs_ialloc.c
    +++ /dev/null
    @@ -1,1411 +0,0 @@
    -/*
    - * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_btree.h"
    -#include "xfs_ialloc.h"
    -#include "xfs_alloc.h"
    -#include "xfs_rtalloc.h"
    -#include "xfs_error.h"
    -#include "xfs_bmap.h"
    -
    -/*
    - * Log specified fields for the inode given by bp and off.
    - */
    -STATIC void
    -xfs_ialloc_log_di(
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_buf_t	*bp,		/* inode buffer */
    -	int		off,		/* index of inode in buffer */
    -	int		fields)		/* bitmask of fields to log */
    -{
    -	int			first;		/* first byte number */
    -	int			ioffset;	/* off in bytes */
    -	int			last;		/* last byte number */
    -	xfs_mount_t		*mp;		/* mount point structure */
    -	static const short	offsets[] = {	/* field offsets */
    -						/* keep in sync with bits */
    -		offsetof(xfs_dinode_core_t, di_magic),
    -		offsetof(xfs_dinode_core_t, di_mode),
    -		offsetof(xfs_dinode_core_t, di_version),
    -		offsetof(xfs_dinode_core_t, di_format),
    -		offsetof(xfs_dinode_core_t, di_onlink),
    -		offsetof(xfs_dinode_core_t, di_uid),
    -		offsetof(xfs_dinode_core_t, di_gid),
    -		offsetof(xfs_dinode_core_t, di_nlink),
    -		offsetof(xfs_dinode_core_t, di_projid),
    -		offsetof(xfs_dinode_core_t, di_pad),
    -		offsetof(xfs_dinode_core_t, di_atime),
    -		offsetof(xfs_dinode_core_t, di_mtime),
    -		offsetof(xfs_dinode_core_t, di_ctime),
    -		offsetof(xfs_dinode_core_t, di_size),
    -		offsetof(xfs_dinode_core_t, di_nblocks),
    -		offsetof(xfs_dinode_core_t, di_extsize),
    -		offsetof(xfs_dinode_core_t, di_nextents),
    -		offsetof(xfs_dinode_core_t, di_anextents),
    -		offsetof(xfs_dinode_core_t, di_forkoff),
    -		offsetof(xfs_dinode_core_t, di_aformat),
    -		offsetof(xfs_dinode_core_t, di_dmevmask),
    -		offsetof(xfs_dinode_core_t, di_dmstate),
    -		offsetof(xfs_dinode_core_t, di_flags),
    -		offsetof(xfs_dinode_core_t, di_gen),
    -		offsetof(xfs_dinode_t, di_next_unlinked),
    -		offsetof(xfs_dinode_t, di_u),
    -		offsetof(xfs_dinode_t, di_a),
    -		sizeof(xfs_dinode_t)
    -	};
    -
    -
    -	ASSERT(offsetof(xfs_dinode_t, di_core) == 0);
    -	ASSERT((fields & (XFS_DI_U|XFS_DI_A)) == 0);
    -	mp = tp->t_mountp;
    -	/*
    -	 * Get the inode-relative first and last bytes for these fields
    -	 */
    -	xfs_btree_offsets(fields, offsets, XFS_DI_NUM_BITS, &first, &last);
    -	/*
    -	 * Convert to buffer offsets and log it.
    -	 */
    -	ioffset = off << mp->m_sb.sb_inodelog;
    -	first += ioffset;
    -	last += ioffset;
    -	xfs_trans_log_buf(tp, bp, first, last);
    -}
    -
    -/*
    - * Allocation group level functions.
    - */
    -
    -/*
    - * Allocate new inodes in the allocation group specified by agbp.
    - * Return 0 for success, else error code.
    - */
    -STATIC int				/* error code or 0 */
    -xfs_ialloc_ag_alloc(
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_buf_t	*agbp,		/* alloc group buffer */
    -	int		*alloc)
    -{
    -	xfs_agi_t	*agi;		/* allocation group header */
    -	xfs_alloc_arg_t	args;		/* allocation argument structure */
    -	int		blks_per_cluster;  /* fs blocks per inode cluster */
    -	xfs_btree_cur_t	*cur;		/* inode btree cursor */
    -	xfs_daddr_t	d;		/* disk addr of buffer */
    -	int		error;
    -	xfs_buf_t	*fbuf;		/* new free inodes' buffer */
    -	xfs_dinode_t	*free;		/* new free inode structure */
    -	int		i;		/* inode counter */
    -	int		j;		/* block counter */
    -	int		nbufs;		/* num bufs of new inodes */
    -	xfs_agino_t	newino;		/* new first inode's number */
    -	xfs_agino_t	newlen;		/* new number of inodes */
    -	int		ninodes;	/* num inodes per buf */
    -	xfs_agino_t	thisino;	/* current inode number, for loop */
    -	int		version;	/* inode version number to use */
    -	int		isaligned = 0;	/* inode allocation at stripe unit */
    -					/* boundary */
    -
    -	args.tp = tp;
    -	args.mp = tp->t_mountp;
    -
    -	/*
    -	 * Locking will ensure that we don't have two callers in here
    -	 * at one time.
    -	 */
    -	newlen = XFS_IALLOC_INODES(args.mp);
    -	if (args.mp->m_maxicount &&
    -	    args.mp->m_sb.sb_icount + newlen > args.mp->m_maxicount)
    -		return XFS_ERROR(ENOSPC);
    -	args.minlen = args.maxlen = XFS_IALLOC_BLOCKS(args.mp);
    -	/*
    -	 * First try to allocate inodes contiguous with the last-allocated
    -	 * chunk of inodes.  If the filesystem is striped, this will fill
    -	 * an entire stripe unit with inodes.
    - 	 */
    -	agi = XFS_BUF_TO_AGI(agbp);
    -	newino = be32_to_cpu(agi->agi_newino);
    -	args.agbno = XFS_AGINO_TO_AGBNO(args.mp, newino) +
    -			XFS_IALLOC_BLOCKS(args.mp);
    -	if (likely(newino != NULLAGINO &&
    -		  (args.agbno < be32_to_cpu(agi->agi_length)))) {
    -		args.fsbno = XFS_AGB_TO_FSB(args.mp,
    -				be32_to_cpu(agi->agi_seqno), args.agbno);
    -		args.type = XFS_ALLOCTYPE_THIS_BNO;
    -		args.mod = args.total = args.wasdel = args.isfl =
    -			args.userdata = args.minalignslop = 0;
    -		args.prod = 1;
    -		args.alignment = 1;
    -		/*
    -		 * Allow space for the inode btree to split.
    -		 */
    -		args.minleft = XFS_IN_MAXLEVELS(args.mp) - 1;
    -		if ((error = xfs_alloc_vextent(&args)))
    -			return error;
    -	} else
    -		args.fsbno = NULLFSBLOCK;
    -
    -	if (unlikely(args.fsbno == NULLFSBLOCK)) {
    -		/*
    -		 * Set the alignment for the allocation.
    -		 * If stripe alignment is turned on then align at stripe unit
    -		 * boundary.
    -		 * If the cluster size is smaller than a filesystem block
    -		 * then we're doing I/O for inodes in filesystem block size
    -		 * pieces, so don't need alignment anyway.
    -		 */
    -		isaligned = 0;
    -		if (args.mp->m_sinoalign) {
    -			ASSERT(!(args.mp->m_flags & XFS_MOUNT_NOALIGN));
    -			args.alignment = args.mp->m_dalign;
    -			isaligned = 1;
    -		} else if (XFS_SB_VERSION_HASALIGN(&args.mp->m_sb) &&
    -			   args.mp->m_sb.sb_inoalignmt >=
    -			   XFS_B_TO_FSBT(args.mp,
    -			  	XFS_INODE_CLUSTER_SIZE(args.mp)))
    -				args.alignment = args.mp->m_sb.sb_inoalignmt;
    -		else
    -			args.alignment = 1;
    -		/*
    -		 * Need to figure out where to allocate the inode blocks.
    -		 * Ideally they should be spaced out through the a.g.
    -		 * For now, just allocate blocks up front.
    -		 */
    -		args.agbno = be32_to_cpu(agi->agi_root);
    -		args.fsbno = XFS_AGB_TO_FSB(args.mp,
    -				be32_to_cpu(agi->agi_seqno), args.agbno);
    -		/*
    -		 * Allocate a fixed-size extent of inodes.
    -		 */
    -		args.type = XFS_ALLOCTYPE_NEAR_BNO;
    -		args.mod = args.total = args.wasdel = args.isfl =
    -			args.userdata = args.minalignslop = 0;
    -		args.prod = 1;
    -		/*
    -		 * Allow space for the inode btree to split.
    -		 */
    -		args.minleft = XFS_IN_MAXLEVELS(args.mp) - 1;
    -		if ((error = xfs_alloc_vextent(&args)))
    -			return error;
    -	}
    -
    -	/*
    -	 * If stripe alignment is turned on, then try again with cluster
    -	 * alignment.
    -	 */
    -	if (isaligned && args.fsbno == NULLFSBLOCK) {
    -		args.type = XFS_ALLOCTYPE_NEAR_BNO;
    -		args.agbno = be32_to_cpu(agi->agi_root);
    -		args.fsbno = XFS_AGB_TO_FSB(args.mp,
    -				be32_to_cpu(agi->agi_seqno), args.agbno);
    -		if (XFS_SB_VERSION_HASALIGN(&args.mp->m_sb) &&
    -			args.mp->m_sb.sb_inoalignmt >=
    -			XFS_B_TO_FSBT(args.mp, XFS_INODE_CLUSTER_SIZE(args.mp)))
    -				args.alignment = args.mp->m_sb.sb_inoalignmt;
    -		else
    -			args.alignment = 1;
    -		if ((error = xfs_alloc_vextent(&args)))
    -			return error;
    -	}
    -
    -	if (args.fsbno == NULLFSBLOCK) {
    -		*alloc = 0;
    -		return 0;
    -	}
    -	ASSERT(args.len == args.minlen);
    -	/*
    -	 * Convert the results.
    -	 */
    -	newino = XFS_OFFBNO_TO_AGINO(args.mp, args.agbno, 0);
    -	/*
    -	 * Loop over the new block(s), filling in the inodes.
    -	 * For small block sizes, manipulate the inodes in buffers
    -	 * which are multiples of the blocks size.
    -	 */
    -	if (args.mp->m_sb.sb_blocksize >= XFS_INODE_CLUSTER_SIZE(args.mp)) {
    -		blks_per_cluster = 1;
    -		nbufs = (int)args.len;
    -		ninodes = args.mp->m_sb.sb_inopblock;
    -	} else {
    -		blks_per_cluster = XFS_INODE_CLUSTER_SIZE(args.mp) /
    -				   args.mp->m_sb.sb_blocksize;
    -		nbufs = (int)args.len / blks_per_cluster;
    -		ninodes = blks_per_cluster * args.mp->m_sb.sb_inopblock;
    -	}
    -	/*
    -	 * Figure out what version number to use in the inodes we create.
    -	 * If the superblock version has caught up to the one that supports
    -	 * the new inode format, then use the new inode version.  Otherwise
    -	 * use the old version so that old kernels will continue to be
    -	 * able to use the file system.
    -	 */
    -	if (XFS_SB_VERSION_HASNLINK(&args.mp->m_sb))
    -		version = XFS_DINODE_VERSION_2;
    -	else
    -		version = XFS_DINODE_VERSION_1;
    -
    -	for (j = 0; j < nbufs; j++) {
    -		/*
    -		 * Get the block.
    -		 */
    -		d = XFS_AGB_TO_DADDR(args.mp, be32_to_cpu(agi->agi_seqno),
    -				     args.agbno + (j * blks_per_cluster));
    -		fbuf = xfs_trans_get_buf(tp, args.mp->m_ddev_targp, d,
    -					 args.mp->m_bsize * blks_per_cluster,
    -					 XFS_BUF_LOCK);
    -		ASSERT(fbuf);
    -		ASSERT(!XFS_BUF_GETERROR(fbuf));
    -		/*
    -		 * Set initial values for the inodes in this buffer.
    -		 */
    -		xfs_biozero(fbuf, 0, ninodes << args.mp->m_sb.sb_inodelog);
    -		for (i = 0; i < ninodes; i++) {
    -			free = XFS_MAKE_IPTR(args.mp, fbuf, i);
    -			INT_SET(free->di_core.di_magic, ARCH_CONVERT, XFS_DINODE_MAGIC);
    -			INT_SET(free->di_core.di_version, ARCH_CONVERT, version);
    -			INT_SET(free->di_next_unlinked, ARCH_CONVERT, NULLAGINO);
    -			xfs_ialloc_log_di(tp, fbuf, i,
    -				XFS_DI_CORE_BITS | XFS_DI_NEXT_UNLINKED);
    -		}
    -		xfs_trans_inode_alloc_buf(tp, fbuf);
    -	}
    -	be32_add(&agi->agi_count, newlen);
    -	be32_add(&agi->agi_freecount, newlen);
    -	down_read(&args.mp->m_peraglock);
    -	args.mp->m_perag[be32_to_cpu(agi->agi_seqno)].pagi_freecount += newlen;
    -	up_read(&args.mp->m_peraglock);
    -	agi->agi_newino = cpu_to_be32(newino);
    -	/*
    -	 * Insert records describing the new inode chunk into the btree.
    -	 */
    -	cur = xfs_btree_init_cursor(args.mp, tp, agbp,
    -			be32_to_cpu(agi->agi_seqno),
    -			XFS_BTNUM_INO, (xfs_inode_t *)0, 0);
    -	for (thisino = newino;
    -	     thisino < newino + newlen;
    -	     thisino += XFS_INODES_PER_CHUNK) {
    -		if ((error = xfs_inobt_lookup_eq(cur, thisino,
    -				XFS_INODES_PER_CHUNK, XFS_INOBT_ALL_FREE, &i))) {
    -			xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
    -			return error;
    -		}
    -		ASSERT(i == 0);
    -		if ((error = xfs_inobt_insert(cur, &i))) {
    -			xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
    -			return error;
    -		}
    -		ASSERT(i == 1);
    -	}
    -	xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
    -	/*
    -	 * Log allocation group header fields
    -	 */
    -	xfs_ialloc_log_agi(tp, agbp,
    -		XFS_AGI_COUNT | XFS_AGI_FREECOUNT | XFS_AGI_NEWINO);
    -	/*
    -	 * Modify/log superblock values for inode count and inode free count.
    -	 */
    -	xfs_trans_mod_sb(tp, XFS_TRANS_SB_ICOUNT, (long)newlen);
    -	xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, (long)newlen);
    -	*alloc = 1;
    -	return 0;
    -}
    -
    -STATIC __inline xfs_agnumber_t
    -xfs_ialloc_next_ag(
    -	xfs_mount_t	*mp)
    -{
    -	xfs_agnumber_t	agno;
    -
    -	spin_lock(&mp->m_agirotor_lock);
    -	agno = mp->m_agirotor;
    -	if (++mp->m_agirotor == mp->m_maxagi)
    -		mp->m_agirotor = 0;
    -	spin_unlock(&mp->m_agirotor_lock);
    -
    -	return agno;
    -}
    -
    -/*
    - * Select an allocation group to look for a free inode in, based on the parent
    - * inode and then mode.  Return the allocation group buffer.
    - */
    -STATIC xfs_buf_t *			/* allocation group buffer */
    -xfs_ialloc_ag_select(
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_ino_t	parent,		/* parent directory inode number */
    -	mode_t		mode,		/* bits set to indicate file type */
    -	int		okalloc)	/* ok to allocate more space */
    -{
    -	xfs_buf_t	*agbp;		/* allocation group header buffer */
    -	xfs_agnumber_t	agcount;	/* number of ag's in the filesystem */
    -	xfs_agnumber_t	agno;		/* current ag number */
    -	int		flags;		/* alloc buffer locking flags */
    -	xfs_extlen_t	ineed;		/* blocks needed for inode allocation */
    -	xfs_extlen_t	longest = 0;	/* longest extent available */
    -	xfs_mount_t	*mp;		/* mount point structure */
    -	int		needspace;	/* file mode implies space allocated */
    -	xfs_perag_t	*pag;		/* per allocation group data */
    -	xfs_agnumber_t	pagno;		/* parent (starting) ag number */
    -
    -	/*
    -	 * Files of these types need at least one block if length > 0
    -	 * (and they won't fit in the inode, but that's hard to figure out).
    -	 */
    -	needspace = S_ISDIR(mode) || S_ISREG(mode) || S_ISLNK(mode);
    -	mp = tp->t_mountp;
    -	agcount = mp->m_maxagi;
    -	if (S_ISDIR(mode))
    -		pagno = xfs_ialloc_next_ag(mp);
    -	else {
    -		pagno = XFS_INO_TO_AGNO(mp, parent);
    -		if (pagno >= agcount)
    -			pagno = 0;
    -	}
    -	ASSERT(pagno < agcount);
    -	/*
    -	 * Loop through allocation groups, looking for one with a little
    -	 * free space in it.  Note we don't look for free inodes, exactly.
    -	 * Instead, we include whether there is a need to allocate inodes
    -	 * to mean that blocks must be allocated for them,
    -	 * if none are currently free.
    -	 */
    -	agno = pagno;
    -	flags = XFS_ALLOC_FLAG_TRYLOCK;
    -	down_read(&mp->m_peraglock);
    -	for (;;) {
    -		pag = &mp->m_perag[agno];
    -		if (!pag->pagi_init) {
    -			if (xfs_ialloc_read_agi(mp, tp, agno, &agbp)) {
    -				agbp = NULL;
    -				goto nextag;
    -			}
    -		} else
    -			agbp = NULL;
    -
    -		if (!pag->pagi_inodeok) {
    -			xfs_ialloc_next_ag(mp);
    -			goto unlock_nextag;
    -		}
    -
    -		/*
    -		 * Is there enough free space for the file plus a block
    -		 * of inodes (if we need to allocate some)?
    -		 */
    -		ineed = pag->pagi_freecount ? 0 : XFS_IALLOC_BLOCKS(mp);
    -		if (ineed && !pag->pagf_init) {
    -			if (agbp == NULL &&
    -			    xfs_ialloc_read_agi(mp, tp, agno, &agbp)) {
    -				agbp = NULL;
    -				goto nextag;
    -			}
    -			(void)xfs_alloc_pagf_init(mp, tp, agno, flags);
    -		}
    -		if (!ineed || pag->pagf_init) {
    -			if (ineed && !(longest = pag->pagf_longest))
    -				longest = pag->pagf_flcount > 0;
    -			if (!ineed ||
    -			    (pag->pagf_freeblks >= needspace + ineed &&
    -			     longest >= ineed &&
    -			     okalloc)) {
    -				if (agbp == NULL &&
    -				    xfs_ialloc_read_agi(mp, tp, agno, &agbp)) {
    -					agbp = NULL;
    -					goto nextag;
    -				}
    -				up_read(&mp->m_peraglock);
    -				return agbp;
    -			}
    -		}
    -unlock_nextag:
    -		if (agbp)
    -			xfs_trans_brelse(tp, agbp);
    -nextag:
    -		/*
    -		 * No point in iterating over the rest, if we're shutting
    -		 * down.
    -		 */
    -		if (XFS_FORCED_SHUTDOWN(mp)) {
    -			up_read(&mp->m_peraglock);
    -			return (xfs_buf_t *)0;
    -		}
    -		agno++;
    -		if (agno >= agcount)
    -			agno = 0;
    -		if (agno == pagno) {
    -			if (flags == 0) {
    -				up_read(&mp->m_peraglock);
    -				return (xfs_buf_t *)0;
    -			}
    -			flags = 0;
    -		}
    -	}
    -}
    -
    -/*
    - * Visible inode allocation functions.
    - */
    -
    -/*
    - * Allocate an inode on disk.
    - * Mode is used to tell whether the new inode will need space, and whether
    - * it is a directory.
    - *
    - * The arguments IO_agbp and alloc_done are defined to work within
    - * the constraint of one allocation per transaction.
    - * xfs_dialloc() is designed to be called twice if it has to do an
    - * allocation to make more free inodes.  On the first call,
    - * IO_agbp should be set to NULL. If an inode is available,
    - * i.e., xfs_dialloc() did not need to do an allocation, an inode
    - * number is returned.  In this case, IO_agbp would be set to the
    - * current ag_buf and alloc_done set to false.
    - * If an allocation needed to be done, xfs_dialloc would return
    - * the current ag_buf in IO_agbp and set alloc_done to true.
    - * The caller should then commit the current transaction, allocate a new
    - * transaction, and call xfs_dialloc() again, passing in the previous
    - * value of IO_agbp.  IO_agbp should be held across the transactions.
    - * Since the agbp is locked across the two calls, the second call is
    - * guaranteed to have a free inode available.
    - *
    - * Once we successfully pick an inode its number is returned and the
    - * on-disk data structures are updated.  The inode itself is not read
    - * in, since doing so would break ordering constraints with xfs_reclaim.
    - */
    -int
    -xfs_dialloc(
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_ino_t	parent,		/* parent inode (directory) */
    -	mode_t		mode,		/* mode bits for new inode */
    -	int		okalloc,	/* ok to allocate more space */
    -	xfs_buf_t	**IO_agbp,	/* in/out ag header's buffer */
    -	boolean_t	*alloc_done,	/* true if we needed to replenish
    -					   inode freelist */
    -	xfs_ino_t	*inop)		/* inode number allocated */
    -{
    -	xfs_agnumber_t	agcount;	/* number of allocation groups */
    -	xfs_buf_t	*agbp;		/* allocation group header's buffer */
    -	xfs_agnumber_t	agno;		/* allocation group number */
    -	xfs_agi_t	*agi;		/* allocation group header structure */
    -	xfs_btree_cur_t	*cur;		/* inode allocation btree cursor */
    -	int		error;		/* error return value */
    -	int		i;		/* result code */
    -	int		ialloced = 0;	/* inode allocation status */
    -	int		noroom = 0;	/* no space for inode blk allocation */
    -	xfs_ino_t	ino;		/* fs-relative inode to be returned */
    -	/* REFERENCED */
    -	int		j;		/* result code */
    -	xfs_mount_t	*mp;		/* file system mount structure */
    -	int		offset;		/* index of inode in chunk */
    -	xfs_agino_t	pagino;		/* parent's a.g. relative inode # */
    -	xfs_agnumber_t	pagno;		/* parent's allocation group number */
    -	xfs_inobt_rec_t	rec;		/* inode allocation record */
    -	xfs_agnumber_t	tagno;		/* testing allocation group number */
    -	xfs_btree_cur_t	*tcur;		/* temp cursor */
    -	xfs_inobt_rec_t	trec;		/* temp inode allocation record */
    -
    -
    -	if (*IO_agbp == NULL) {
    -		/*
    -		 * We do not have an agbp, so select an initial allocation
    -		 * group for inode allocation.
    -		 */
    -		agbp = xfs_ialloc_ag_select(tp, parent, mode, okalloc);
    -		/*
    -		 * Couldn't find an allocation group satisfying the
    -		 * criteria, give up.
    -		 */
    -		if (!agbp) {
    -			*inop = NULLFSINO;
    -			return 0;
    -		}
    -		agi = XFS_BUF_TO_AGI(agbp);
    -		ASSERT(be32_to_cpu(agi->agi_magicnum) == XFS_AGI_MAGIC);
    -	} else {
    -		/*
    -		 * Continue where we left off before.  In this case, we
    -		 * know that the allocation group has free inodes.
    -		 */
    -		agbp = *IO_agbp;
    -		agi = XFS_BUF_TO_AGI(agbp);
    -		ASSERT(be32_to_cpu(agi->agi_magicnum) == XFS_AGI_MAGIC);
    -		ASSERT(be32_to_cpu(agi->agi_freecount) > 0);
    -	}
    -	mp = tp->t_mountp;
    -	agcount = mp->m_sb.sb_agcount;
    -	agno = be32_to_cpu(agi->agi_seqno);
    -	tagno = agno;
    -	pagno = XFS_INO_TO_AGNO(mp, parent);
    -	pagino = XFS_INO_TO_AGINO(mp, parent);
    -
    -	/*
    -	 * If we have already hit the ceiling of inode blocks then clear
    -	 * okalloc so we scan all available agi structures for a free
    -	 * inode.
    -	 */
    -
    -	if (mp->m_maxicount &&
    -	    mp->m_sb.sb_icount + XFS_IALLOC_INODES(mp) > mp->m_maxicount) {
    -		noroom = 1;
    -		okalloc = 0;
    -	}
    -
    -	/*
    -	 * Loop until we find an allocation group that either has free inodes
    -	 * or in which we can allocate some inodes.  Iterate through the
    -	 * allocation groups upward, wrapping at the end.
    -	 */
    -	*alloc_done = B_FALSE;
    -	while (!agi->agi_freecount) {
    -		/*
    -		 * Don't do anything if we're not supposed to allocate
    -		 * any blocks, just go on to the next ag.
    -		 */
    -		if (okalloc) {
    -			/*
    -			 * Try to allocate some new inodes in the allocation
    -			 * group.
    -			 */
    -			if ((error = xfs_ialloc_ag_alloc(tp, agbp, &ialloced))) {
    -				xfs_trans_brelse(tp, agbp);
    -				if (error == ENOSPC) {
    -					*inop = NULLFSINO;
    -					return 0;
    -				} else
    -					return error;
    -			}
    -			if (ialloced) {
    -				/*
    -				 * We successfully allocated some inodes, return
    -				 * the current context to the caller so that it
    -				 * can commit the current transaction and call
    -				 * us again where we left off.
    -				 */
    -				ASSERT(be32_to_cpu(agi->agi_freecount) > 0);
    -				*alloc_done = B_TRUE;
    -				*IO_agbp = agbp;
    -				*inop = NULLFSINO;
    -				return 0;
    -			}
    -		}
    -		/*
    -		 * If it failed, give up on this ag.
    -		 */
    -		xfs_trans_brelse(tp, agbp);
    -		/*
    -		 * Go on to the next ag: get its ag header.
    -		 */
    -nextag:
    -		if (++tagno == agcount)
    -			tagno = 0;
    -		if (tagno == agno) {
    -			*inop = NULLFSINO;
    -			return noroom ? ENOSPC : 0;
    -		}
    -		down_read(&mp->m_peraglock);
    -		if (mp->m_perag[tagno].pagi_inodeok == 0) {
    -			up_read(&mp->m_peraglock);
    -			goto nextag;
    -		}
    -		error = xfs_ialloc_read_agi(mp, tp, tagno, &agbp);
    -		up_read(&mp->m_peraglock);
    -		if (error)
    -			goto nextag;
    -		agi = XFS_BUF_TO_AGI(agbp);
    -		ASSERT(be32_to_cpu(agi->agi_magicnum) == XFS_AGI_MAGIC);
    -	}
    -	/*
    -	 * Here with an allocation group that has a free inode.
    -	 * Reset agno since we may have chosen a new ag in the
    -	 * loop above.
    -	 */
    -	agno = tagno;
    -	*IO_agbp = NULL;
    -	cur = xfs_btree_init_cursor(mp, tp, agbp, be32_to_cpu(agi->agi_seqno),
    -				    XFS_BTNUM_INO, (xfs_inode_t *)0, 0);
    -	/*
    -	 * If pagino is 0 (this is the root inode allocation) use newino.
    -	 * This must work because we've just allocated some.
    -	 */
    -	if (!pagino)
    -		pagino = be32_to_cpu(agi->agi_newino);
    -#ifdef DEBUG
    -	if (cur->bc_nlevels == 1) {
    -		int	freecount = 0;
    -
    -		if ((error = xfs_inobt_lookup_ge(cur, 0, 0, 0, &i)))
    -			goto error0;
    -		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -		do {
    -			if ((error = xfs_inobt_get_rec(cur, &rec.ir_startino,
    -					&rec.ir_freecount, &rec.ir_free, &i)))
    -				goto error0;
    -			XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -			freecount += rec.ir_freecount;
    -			if ((error = xfs_inobt_increment(cur, 0, &i)))
    -				goto error0;
    -		} while (i == 1);
    -
    -		ASSERT(freecount == be32_to_cpu(agi->agi_freecount) ||
    -		       XFS_FORCED_SHUTDOWN(mp));
    -	}
    -#endif
    -	/*
    -	 * If in the same a.g. as the parent, try to get near the parent.
    -	 */
    -	if (pagno == agno) {
    -		if ((error = xfs_inobt_lookup_le(cur, pagino, 0, 0, &i)))
    -			goto error0;
    -		if (i != 0 &&
    -		    (error = xfs_inobt_get_rec(cur, &rec.ir_startino,
    -			    &rec.ir_freecount, &rec.ir_free, &j)) == 0 &&
    -		    j == 1 &&
    -		    rec.ir_freecount > 0) {
    -			/*
    -			 * Found a free inode in the same chunk
    -			 * as parent, done.
    -			 */
    -		}
    -		/*
    -		 * In the same a.g. as parent, but parent's chunk is full.
    -		 */
    -		else {
    -			int	doneleft;	/* done, to the left */
    -			int	doneright;	/* done, to the right */
    -
    -			if (error)
    -				goto error0;
    -			ASSERT(i == 1);
    -			ASSERT(j == 1);
    -			/*
    -			 * Duplicate the cursor, search left & right
    -			 * simultaneously.
    -			 */
    -			if ((error = xfs_btree_dup_cursor(cur, &tcur)))
    -				goto error0;
    -			/*
    -			 * Search left with tcur, back up 1 record.
    -			 */
    -			if ((error = xfs_inobt_decrement(tcur, 0, &i)))
    -				goto error1;
    -			doneleft = !i;
    -			if (!doneleft) {
    -				if ((error = xfs_inobt_get_rec(tcur,
    -						&trec.ir_startino,
    -						&trec.ir_freecount,
    -						&trec.ir_free, &i)))
    -					goto error1;
    -				XFS_WANT_CORRUPTED_GOTO(i == 1, error1);
    -			}
    -			/*
    -			 * Search right with cur, go forward 1 record.
    -			 */
    -			if ((error = xfs_inobt_increment(cur, 0, &i)))
    -				goto error1;
    -			doneright = !i;
    -			if (!doneright) {
    -				if ((error = xfs_inobt_get_rec(cur,
    -						&rec.ir_startino,
    -						&rec.ir_freecount,
    -						&rec.ir_free, &i)))
    -					goto error1;
    -				XFS_WANT_CORRUPTED_GOTO(i == 1, error1);
    -			}
    -			/*
    -			 * Loop until we find the closest inode chunk
    -			 * with a free one.
    -			 */
    -			while (!doneleft || !doneright) {
    -				int	useleft;  /* using left inode
    -						     chunk this time */
    -
    -				/*
    -				 * Figure out which block is closer,
    -				 * if both are valid.
    -				 */
    -				if (!doneleft && !doneright)
    -					useleft =
    -						pagino -
    -						(trec.ir_startino +
    -						 XFS_INODES_PER_CHUNK - 1) <
    -						 rec.ir_startino - pagino;
    -				else
    -					useleft = !doneleft;
    -				/*
    -				 * If checking the left, does it have
    -				 * free inodes?
    -				 */
    -				if (useleft && trec.ir_freecount) {
    -					/*
    -					 * Yes, set it up as the chunk to use.
    -					 */
    -					rec = trec;
    -					xfs_btree_del_cursor(cur,
    -						XFS_BTREE_NOERROR);
    -					cur = tcur;
    -					break;
    -				}
    -				/*
    -				 * If checking the right, does it have
    -				 * free inodes?
    -				 */
    -				if (!useleft && rec.ir_freecount) {
    -					/*
    -					 * Yes, it's already set up.
    -					 */
    -					xfs_btree_del_cursor(tcur,
    -						XFS_BTREE_NOERROR);
    -					break;
    -				}
    -				/*
    -				 * If used the left, get another one
    -				 * further left.
    -				 */
    -				if (useleft) {
    -					if ((error = xfs_inobt_decrement(tcur, 0,
    -							&i)))
    -						goto error1;
    -					doneleft = !i;
    -					if (!doneleft) {
    -						if ((error = xfs_inobt_get_rec(
    -							    tcur,
    -							    &trec.ir_startino,
    -							    &trec.ir_freecount,
    -							    &trec.ir_free, &i)))
    -							goto error1;
    -						XFS_WANT_CORRUPTED_GOTO(i == 1,
    -							error1);
    -					}
    -				}
    -				/*
    -				 * If used the right, get another one
    -				 * further right.
    -				 */
    -				else {
    -					if ((error = xfs_inobt_increment(cur, 0,
    -							&i)))
    -						goto error1;
    -					doneright = !i;
    -					if (!doneright) {
    -						if ((error = xfs_inobt_get_rec(
    -							    cur,
    -							    &rec.ir_startino,
    -							    &rec.ir_freecount,
    -							    &rec.ir_free, &i)))
    -							goto error1;
    -						XFS_WANT_CORRUPTED_GOTO(i == 1,
    -							error1);
    -					}
    -				}
    -			}
    -			ASSERT(!doneleft || !doneright);
    -		}
    -	}
    -	/*
    -	 * In a different a.g. from the parent.
    -	 * See if the most recently allocated block has any free.
    -	 */
    -	else if (be32_to_cpu(agi->agi_newino) != NULLAGINO) {
    -		if ((error = xfs_inobt_lookup_eq(cur,
    -				be32_to_cpu(agi->agi_newino), 0, 0, &i)))
    -			goto error0;
    -		if (i == 1 &&
    -		    (error = xfs_inobt_get_rec(cur, &rec.ir_startino,
    -			    &rec.ir_freecount, &rec.ir_free, &j)) == 0 &&
    -		    j == 1 &&
    -		    rec.ir_freecount > 0) {
    -			/*
    -			 * The last chunk allocated in the group still has
    -			 * a free inode.
    -			 */
    -		}
    -		/*
    -		 * None left in the last group, search the whole a.g.
    -		 */
    -		else {
    -			if (error)
    -				goto error0;
    -			if ((error = xfs_inobt_lookup_ge(cur, 0, 0, 0, &i)))
    -				goto error0;
    -			ASSERT(i == 1);
    -			for (;;) {
    -				if ((error = xfs_inobt_get_rec(cur,
    -						&rec.ir_startino,
    -						&rec.ir_freecount, &rec.ir_free,
    -						&i)))
    -					goto error0;
    -				XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -				if (rec.ir_freecount > 0)
    -					break;
    -				if ((error = xfs_inobt_increment(cur, 0, &i)))
    -					goto error0;
    -				XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -			}
    -		}
    -	}
    -	offset = XFS_IALLOC_FIND_FREE(&rec.ir_free);
    -	ASSERT(offset >= 0);
    -	ASSERT(offset < XFS_INODES_PER_CHUNK);
    -	ASSERT((XFS_AGINO_TO_OFFSET(mp, rec.ir_startino) %
    -				   XFS_INODES_PER_CHUNK) == 0);
    -	ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino + offset);
    -	XFS_INOBT_CLR_FREE(&rec, offset);
    -	rec.ir_freecount--;
    -	if ((error = xfs_inobt_update(cur, rec.ir_startino, rec.ir_freecount,
    -			rec.ir_free)))
    -		goto error0;
    -	be32_add(&agi->agi_freecount, -1);
    -	xfs_ialloc_log_agi(tp, agbp, XFS_AGI_FREECOUNT);
    -	down_read(&mp->m_peraglock);
    -	mp->m_perag[tagno].pagi_freecount--;
    -	up_read(&mp->m_peraglock);
    -#ifdef DEBUG
    -	if (cur->bc_nlevels == 1) {
    -		int	freecount = 0;
    -
    -		if ((error = xfs_inobt_lookup_ge(cur, 0, 0, 0, &i)))
    -			goto error0;
    -		do {
    -			if ((error = xfs_inobt_get_rec(cur, &rec.ir_startino,
    -					&rec.ir_freecount, &rec.ir_free, &i)))
    -				goto error0;
    -			XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -			freecount += rec.ir_freecount;
    -			if ((error = xfs_inobt_increment(cur, 0, &i)))
    -				goto error0;
    -		} while (i == 1);
    -		ASSERT(freecount == be32_to_cpu(agi->agi_freecount) ||
    -		       XFS_FORCED_SHUTDOWN(mp));
    -	}
    -#endif
    -	xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
    -	xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, -1);
    -	*inop = ino;
    -	return 0;
    -error1:
    -	xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR);
    -error0:
    -	xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
    -	return error;
    -}
    -
    -/*
    - * Free disk inode.  Carefully avoids touching the incore inode, all
    - * manipulations incore are the caller's responsibility.
    - * The on-disk inode is not changed by this operation, only the
    - * btree (free inode mask) is changed.
    - */
    -int
    -xfs_difree(
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_ino_t	inode,		/* inode to be freed */
    -	xfs_bmap_free_t	*flist,		/* extents to free */
    -	int		*delete,	/* set if inode cluster was deleted */
    -	xfs_ino_t	*first_ino)	/* first inode in deleted cluster */
    -{
    -	/* REFERENCED */
    -	xfs_agblock_t	agbno;	/* block number containing inode */
    -	xfs_buf_t	*agbp;	/* buffer containing allocation group header */
    -	xfs_agino_t	agino;	/* inode number relative to allocation group */
    -	xfs_agnumber_t	agno;	/* allocation group number */
    -	xfs_agi_t	*agi;	/* allocation group header */
    -	xfs_btree_cur_t	*cur;	/* inode btree cursor */
    -	int		error;	/* error return value */
    -	int		i;	/* result code */
    -	int		ilen;	/* inodes in an inode cluster */
    -	xfs_mount_t	*mp;	/* mount structure for filesystem */
    -	int		off;	/* offset of inode in inode chunk */
    -	xfs_inobt_rec_t	rec;	/* btree record */
    -
    -	mp = tp->t_mountp;
    -
    -	/*
    -	 * Break up inode number into its components.
    -	 */
    -	agno = XFS_INO_TO_AGNO(mp, inode);
    -	if (agno >= mp->m_sb.sb_agcount)  {
    -		cmn_err(CE_WARN,
    -			"xfs_difree: agno >= mp->m_sb.sb_agcount (%d >= %d) on %s.  Returning EINVAL.",
    -			agno, mp->m_sb.sb_agcount, mp->m_fsname);
    -		ASSERT(0);
    -		return XFS_ERROR(EINVAL);
    -	}
    -	agino = XFS_INO_TO_AGINO(mp, inode);
    -	if (inode != XFS_AGINO_TO_INO(mp, agno, agino))  {
    -		cmn_err(CE_WARN,
    -			"xfs_difree: inode != XFS_AGINO_TO_INO() "
    -			"(%llu != %llu) on %s.  Returning EINVAL.",
    -			(unsigned long long)inode,
    -			(unsigned long long)XFS_AGINO_TO_INO(mp, agno, agino),
    -			mp->m_fsname);
    -		ASSERT(0);
    -		return XFS_ERROR(EINVAL);
    -	}
    -	agbno = XFS_AGINO_TO_AGBNO(mp, agino);
    -	if (agbno >= mp->m_sb.sb_agblocks)  {
    -		cmn_err(CE_WARN,
    -			"xfs_difree: agbno >= mp->m_sb.sb_agblocks (%d >= %d) on %s.  Returning EINVAL.",
    -			agbno, mp->m_sb.sb_agblocks, mp->m_fsname);
    -		ASSERT(0);
    -		return XFS_ERROR(EINVAL);
    -	}
    -	/*
    -	 * Get the allocation group header.
    -	 */
    -	down_read(&mp->m_peraglock);
    -	error = xfs_ialloc_read_agi(mp, tp, agno, &agbp);
    -	up_read(&mp->m_peraglock);
    -	if (error) {
    -		cmn_err(CE_WARN,
    -			"xfs_difree: xfs_ialloc_read_agi() returned an error %d on %s.  Returning error.",
    -			error, mp->m_fsname);
    -		return error;
    -	}
    -	agi = XFS_BUF_TO_AGI(agbp);
    -	ASSERT(be32_to_cpu(agi->agi_magicnum) == XFS_AGI_MAGIC);
    -	ASSERT(agbno < be32_to_cpu(agi->agi_length));
    -	/*
    -	 * Initialize the cursor.
    -	 */
    -	cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_INO,
    -		(xfs_inode_t *)0, 0);
    -#ifdef DEBUG
    -	if (cur->bc_nlevels == 1) {
    -		int freecount = 0;
    -
    -		if ((error = xfs_inobt_lookup_ge(cur, 0, 0, 0, &i)))
    -			goto error0;
    -		do {
    -			if ((error = xfs_inobt_get_rec(cur, &rec.ir_startino,
    -					&rec.ir_freecount, &rec.ir_free, &i)))
    -				goto error0;
    -			if (i) {
    -				freecount += rec.ir_freecount;
    -				if ((error = xfs_inobt_increment(cur, 0, &i)))
    -					goto error0;
    -			}
    -		} while (i == 1);
    -		ASSERT(freecount == be32_to_cpu(agi->agi_freecount) ||
    -		       XFS_FORCED_SHUTDOWN(mp));
    -	}
    -#endif
    -	/*
    -	 * Look for the entry describing this inode.
    -	 */
    -	if ((error = xfs_inobt_lookup_le(cur, agino, 0, 0, &i))) {
    -		cmn_err(CE_WARN,
    -			"xfs_difree: xfs_inobt_lookup_le returned()  an error %d on %s.  Returning error.",
    -			error, mp->m_fsname);
    -		goto error0;
    -	}
    -	XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -	if ((error = xfs_inobt_get_rec(cur, &rec.ir_startino, &rec.ir_freecount,
    -			&rec.ir_free, &i))) {
    -		cmn_err(CE_WARN,
    -			"xfs_difree: xfs_inobt_get_rec()  returned an error %d on %s.  Returning error.",
    -			error, mp->m_fsname);
    -		goto error0;
    -	}
    -	XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -	/*
    -	 * Get the offset in the inode chunk.
    -	 */
    -	off = agino - rec.ir_startino;
    -	ASSERT(off >= 0 && off < XFS_INODES_PER_CHUNK);
    -	ASSERT(!XFS_INOBT_IS_FREE(&rec, off));
    -	/*
    -	 * Mark the inode free & increment the count.
    -	 */
    -	XFS_INOBT_SET_FREE(&rec, off);
    -	rec.ir_freecount++;
    -
    -	/*
    -	 * When an inode cluster is free, it becomes eligible for removal
    -	 */
    -	if ((mp->m_flags & XFS_MOUNT_IDELETE) &&
    -	    (rec.ir_freecount == XFS_IALLOC_INODES(mp))) {
    -
    -		*delete = 1;
    -		*first_ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino);
    -
    -		/*
    -		 * Remove the inode cluster from the AGI B+Tree, adjust the
    -		 * AGI and Superblock inode counts, and mark the disk space
    -		 * to be freed when the transaction is committed.
    -		 */
    -		ilen = XFS_IALLOC_INODES(mp);
    -		be32_add(&agi->agi_count, -ilen);
    -		be32_add(&agi->agi_freecount, -(ilen - 1));
    -		xfs_ialloc_log_agi(tp, agbp, XFS_AGI_COUNT | XFS_AGI_FREECOUNT);
    -		down_read(&mp->m_peraglock);
    -		mp->m_perag[agno].pagi_freecount -= ilen - 1;
    -		up_read(&mp->m_peraglock);
    -		xfs_trans_mod_sb(tp, XFS_TRANS_SB_ICOUNT, -ilen);
    -		xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, -(ilen - 1));
    -
    -		if ((error = xfs_inobt_delete(cur, &i))) {
    -			cmn_err(CE_WARN, "xfs_difree: xfs_inobt_delete returned an error %d on %s.\n",
    -				error, mp->m_fsname);
    -			goto error0;
    -		}
    -
    -		xfs_bmap_add_free(XFS_AGB_TO_FSB(mp,
    -				agno, XFS_INO_TO_AGBNO(mp,rec.ir_startino)),
    -				XFS_IALLOC_BLOCKS(mp), flist, mp);
    -	} else {
    -		*delete = 0;
    -
    -		if ((error = xfs_inobt_update(cur, rec.ir_startino, rec.ir_freecount, rec.ir_free))) {
    -			cmn_err(CE_WARN,
    -				"xfs_difree: xfs_inobt_update()  returned an error %d on %s.  Returning error.",
    -				error, mp->m_fsname);
    -			goto error0;
    -		}
    -		/* 
    -		 * Change the inode free counts and log the ag/sb changes.
    -		 */
    -		be32_add(&agi->agi_freecount, 1);
    -		xfs_ialloc_log_agi(tp, agbp, XFS_AGI_FREECOUNT);
    -		down_read(&mp->m_peraglock);
    -		mp->m_perag[agno].pagi_freecount++;
    -		up_read(&mp->m_peraglock);
    -		xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, 1);
    -	}
    -
    -#ifdef DEBUG
    -	if (cur->bc_nlevels == 1) {
    -		int freecount = 0;
    -
    -		if ((error = xfs_inobt_lookup_ge(cur, 0, 0, 0, &i)))
    -			goto error0;
    -		do {
    -			if ((error = xfs_inobt_get_rec(cur,
    -					&rec.ir_startino,
    -					&rec.ir_freecount,
    -					&rec.ir_free, &i)))
    -				goto error0;
    -			if (i) {
    -				freecount += rec.ir_freecount;
    -				if ((error = xfs_inobt_increment(cur, 0, &i)))
    -					goto error0;
    -			}
    -		} while (i == 1);
    -		ASSERT(freecount == be32_to_cpu(agi->agi_freecount) ||
    -		       XFS_FORCED_SHUTDOWN(mp));
    -	}
    -#endif
    -	xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
    -	return 0;
    -
    -error0:
    -	xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
    -	return error;
    -}
    -
    -/*
    - * Return the location of the inode in bno/off, for mapping it into a buffer.
    - */
    -/*ARGSUSED*/
    -int
    -xfs_dilocate(
    -	xfs_mount_t	*mp,	/* file system mount structure */
    -	xfs_trans_t	*tp,	/* transaction pointer */
    -	xfs_ino_t	ino,	/* inode to locate */
    -	xfs_fsblock_t	*bno,	/* output: block containing inode */
    -	int		*len,	/* output: num blocks in inode cluster */
    -	int		*off,	/* output: index in block of inode */
    -	uint		flags)	/* flags concerning inode lookup */
    -{
    -	xfs_agblock_t	agbno;	/* block number of inode in the alloc group */
    -	xfs_buf_t	*agbp;	/* agi buffer */
    -	xfs_agino_t	agino;	/* inode number within alloc group */
    -	xfs_agnumber_t	agno;	/* allocation group number */
    -	int		blks_per_cluster; /* num blocks per inode cluster */
    -	xfs_agblock_t	chunk_agbno;	/* first block in inode chunk */
    -	xfs_agino_t	chunk_agino;	/* first agino in inode chunk */
    -	__int32_t	chunk_cnt;	/* count of free inodes in chunk */
    -	xfs_inofree_t	chunk_free;	/* mask of free inodes in chunk */
    -	xfs_agblock_t	cluster_agbno;	/* first block in inode cluster */
    -	xfs_btree_cur_t	*cur;	/* inode btree cursor */
    -	int		error;	/* error code */
    -	int		i;	/* temp state */
    -	int		offset;	/* index of inode in its buffer */
    -	int		offset_agbno;	/* blks from chunk start to inode */
    -
    -	ASSERT(ino != NULLFSINO);
    -	/*
    -	 * Split up the inode number into its parts.
    -	 */
    -	agno = XFS_INO_TO_AGNO(mp, ino);
    -	agino = XFS_INO_TO_AGINO(mp, ino);
    -	agbno = XFS_AGINO_TO_AGBNO(mp, agino);
    -	if (agno >= mp->m_sb.sb_agcount || agbno >= mp->m_sb.sb_agblocks ||
    -	    ino != XFS_AGINO_TO_INO(mp, agno, agino)) {
    -#ifdef DEBUG
    -		if (agno >= mp->m_sb.sb_agcount) {
    -			xfs_fs_cmn_err(CE_ALERT, mp,
    -				       "xfs_dilocate: ino (0x%llx) agno (%d) >= "
    -				       "mp->m_sb.sb_agcount (%d)",
    -				       ino,
    -				       agno,  mp->m_sb.sb_agcount);
    -		}
    -		if (agbno >= mp->m_sb.sb_agblocks) {
    -			xfs_fs_cmn_err(CE_ALERT, mp,
    -					"xfs_dilocate: agbno (0x%llx) >= "
    -					"mp->m_sb.sb_agblocks (0x%lx)",
    -					(unsigned long long) agbno,
    -					(unsigned long) mp->m_sb.sb_agblocks);
    -		}
    -		if (ino != XFS_AGINO_TO_INO(mp, agno, agino)) {
    -			xfs_fs_cmn_err(CE_ALERT, mp,
    -					"xfs_dilocate: ino (0x%llx) != "
    -					"XFS_AGINO_TO_INO(mp, agno, agino) "
    -					"(0x%llx)",
    -					ino, XFS_AGINO_TO_INO(mp, agno, agino));
    -		}
    -#endif /* DEBUG */
    -		return XFS_ERROR(EINVAL);
    -	}
    -	if ((mp->m_sb.sb_blocksize >= XFS_INODE_CLUSTER_SIZE(mp)) ||
    -	    !(flags & XFS_IMAP_LOOKUP)) {
    -		offset = XFS_INO_TO_OFFSET(mp, ino);
    -		ASSERT(offset < mp->m_sb.sb_inopblock);
    -		*bno = XFS_AGB_TO_FSB(mp, agno, agbno);
    -		*off = offset;
    -		*len = 1;
    -		return 0;
    -	}
    -	blks_per_cluster = XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_blocklog;
    -	if (*bno != NULLFSBLOCK) {
    -		offset = XFS_INO_TO_OFFSET(mp, ino);
    -		ASSERT(offset < mp->m_sb.sb_inopblock);
    -		cluster_agbno = XFS_FSB_TO_AGBNO(mp, *bno);
    -		*off = ((agbno - cluster_agbno) * mp->m_sb.sb_inopblock) +
    -			offset;
    -		*len = blks_per_cluster;
    -		return 0;
    -	}
    -	if (mp->m_inoalign_mask) {
    -		offset_agbno = agbno & mp->m_inoalign_mask;
    -		chunk_agbno = agbno - offset_agbno;
    -	} else {
    -		down_read(&mp->m_peraglock);
    -		error = xfs_ialloc_read_agi(mp, tp, agno, &agbp);
    -		up_read(&mp->m_peraglock);
    -		if (error) {
    -#ifdef DEBUG
    -			xfs_fs_cmn_err(CE_ALERT, mp, "xfs_dilocate: "
    -					"xfs_ialloc_read_agi() returned "
    -					"error %d, agno %d",
    -					error, agno);
    -#endif /* DEBUG */
    -			return error;
    -		}
    -		cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_INO,
    -			(xfs_inode_t *)0, 0);
    -		if ((error = xfs_inobt_lookup_le(cur, agino, 0, 0, &i))) {
    -#ifdef DEBUG
    -			xfs_fs_cmn_err(CE_ALERT, mp, "xfs_dilocate: "
    -					"xfs_inobt_lookup_le() failed");
    -#endif /* DEBUG */
    -			goto error0;
    -		}
    -		if ((error = xfs_inobt_get_rec(cur, &chunk_agino, &chunk_cnt,
    -				&chunk_free, &i))) {
    -#ifdef DEBUG
    -			xfs_fs_cmn_err(CE_ALERT, mp, "xfs_dilocate: "
    -					"xfs_inobt_get_rec() failed");
    -#endif /* DEBUG */
    -			goto error0;
    -		}
    -		if (i == 0) {
    -#ifdef DEBUG
    -			xfs_fs_cmn_err(CE_ALERT, mp, "xfs_dilocate: "
    -					"xfs_inobt_get_rec() failed");
    -#endif /* DEBUG */
    -			error = XFS_ERROR(EINVAL);
    -		}
    -		xfs_trans_brelse(tp, agbp);
    -		xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
    -		if (error)
    -			return error;
    -		chunk_agbno = XFS_AGINO_TO_AGBNO(mp, chunk_agino);
    -		offset_agbno = agbno - chunk_agbno;
    -	}
    -	ASSERT(agbno >= chunk_agbno);
    -	cluster_agbno = chunk_agbno +
    -		((offset_agbno / blks_per_cluster) * blks_per_cluster);
    -	offset = ((agbno - cluster_agbno) * mp->m_sb.sb_inopblock) +
    -		XFS_INO_TO_OFFSET(mp, ino);
    -	*bno = XFS_AGB_TO_FSB(mp, agno, cluster_agbno);
    -	*off = offset;
    -	*len = blks_per_cluster;
    -	return 0;
    -error0:
    -	xfs_trans_brelse(tp, agbp);
    -	xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
    -	return error;
    -}
    -
    -/*
    - * Compute and fill in value of m_in_maxlevels.
    - */
    -void
    -xfs_ialloc_compute_maxlevels(
    -	xfs_mount_t	*mp)		/* file system mount structure */
    -{
    -	int		level;
    -	uint		maxblocks;
    -	uint		maxleafents;
    -	int		minleafrecs;
    -	int		minnoderecs;
    -
    -	maxleafents = (1LL << XFS_INO_AGINO_BITS(mp)) >>
    -		XFS_INODES_PER_CHUNK_LOG;
    -	minleafrecs = mp->m_alloc_mnr[0];
    -	minnoderecs = mp->m_alloc_mnr[1];
    -	maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs;
    -	for (level = 1; maxblocks > 1; level++)
    -		maxblocks = (maxblocks + minnoderecs - 1) / minnoderecs;
    -	mp->m_in_maxlevels = level;
    -}
    -
    -/*
    - * Log specified fields for the ag hdr (inode section)
    - */
    -void
    -xfs_ialloc_log_agi(
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_buf_t	*bp,		/* allocation group header buffer */
    -	int		fields)		/* bitmask of fields to log */
    -{
    -	int			first;		/* first byte number */
    -	int			last;		/* last byte number */
    -	static const short	offsets[] = {	/* field starting offsets */
    -					/* keep in sync with bit definitions */
    -		offsetof(xfs_agi_t, agi_magicnum),
    -		offsetof(xfs_agi_t, agi_versionnum),
    -		offsetof(xfs_agi_t, agi_seqno),
    -		offsetof(xfs_agi_t, agi_length),
    -		offsetof(xfs_agi_t, agi_count),
    -		offsetof(xfs_agi_t, agi_root),
    -		offsetof(xfs_agi_t, agi_level),
    -		offsetof(xfs_agi_t, agi_freecount),
    -		offsetof(xfs_agi_t, agi_newino),
    -		offsetof(xfs_agi_t, agi_dirino),
    -		offsetof(xfs_agi_t, agi_unlinked),
    -		sizeof(xfs_agi_t)
    -	};
    -#ifdef DEBUG
    -	xfs_agi_t		*agi;	/* allocation group header */
    -
    -	agi = XFS_BUF_TO_AGI(bp);
    -	ASSERT(be32_to_cpu(agi->agi_magicnum) == XFS_AGI_MAGIC);
    -#endif
    -	/*
    -	 * Compute byte offsets for the first and last fields.
    -	 */
    -	xfs_btree_offsets(fields, offsets, XFS_AGI_NUM_BITS, &first, &last);
    -	/*
    -	 * Log the allocation group inode header buffer.
    -	 */
    -	xfs_trans_log_buf(tp, bp, first, last);
    -}
    -
    -/*
    - * Read in the allocation group header (inode allocation section)
    - */
    -int
    -xfs_ialloc_read_agi(
    -	xfs_mount_t	*mp,		/* file system mount structure */
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_agnumber_t	agno,		/* allocation group number */
    -	xfs_buf_t	**bpp)		/* allocation group hdr buf */
    -{
    -	xfs_agi_t	*agi;		/* allocation group header */
    -	int		agi_ok;		/* agi is consistent */
    -	xfs_buf_t	*bp;		/* allocation group hdr buf */
    -	xfs_perag_t	*pag;		/* per allocation group data */
    -	int		error;
    -
    -	ASSERT(agno != NULLAGNUMBER);
    -	error = xfs_trans_read_buf(
    -			mp, tp, mp->m_ddev_targp,
    -			XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
    -			XFS_FSS_TO_BB(mp, 1), 0, &bp);
    -	if (error)
    -		return error;
    -	ASSERT(bp && !XFS_BUF_GETERROR(bp));
    -
    -	/*
    -	 * Validate the magic number of the agi block.
    -	 */
    -	agi = XFS_BUF_TO_AGI(bp);
    -	agi_ok =
    -		be32_to_cpu(agi->agi_magicnum) == XFS_AGI_MAGIC &&
    -		XFS_AGI_GOOD_VERSION(be32_to_cpu(agi->agi_versionnum));
    -	if (unlikely(XFS_TEST_ERROR(!agi_ok, mp, XFS_ERRTAG_IALLOC_READ_AGI,
    -			XFS_RANDOM_IALLOC_READ_AGI))) {
    -		XFS_CORRUPTION_ERROR("xfs_ialloc_read_agi", XFS_ERRLEVEL_LOW,
    -				     mp, agi);
    -		xfs_trans_brelse(tp, bp);
    -		return XFS_ERROR(EFSCORRUPTED);
    -	}
    -	pag = &mp->m_perag[agno];
    -	if (!pag->pagi_init) {
    -		pag->pagi_freecount = be32_to_cpu(agi->agi_freecount);
    -		pag->pagi_init = 1;
    -	} else {
    -		/*
    -		 * It's possible for these to be out of sync if
    -		 * we are in the middle of a forced shutdown.
    -		 */
    -		ASSERT(pag->pagi_freecount == be32_to_cpu(agi->agi_freecount) ||
    -			XFS_FORCED_SHUTDOWN(mp));
    -	}
    -
    -#ifdef DEBUG
    -	{
    -		int	i;
    -
    -		for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++)
    -			ASSERT(agi->agi_unlinked[i]);
    -	}
    -#endif
    -
    -	XFS_BUF_SET_VTYPE_REF(bp, B_FS_AGI, XFS_AGI_REF);
    -	*bpp = bp;
    -	return 0;
    -}
    diff --git a/sys/gnu/fs/xfs/xfs_ialloc.h b/sys/gnu/fs/xfs/xfs_ialloc.h
    deleted file mode 100644
    index 7f5debe1acb..00000000000
    --- a/sys/gnu/fs/xfs/xfs_ialloc.h
    +++ /dev/null
    @@ -1,154 +0,0 @@
    -/*
    - * Copyright (c) 2000,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_IALLOC_H__
    -#define	__XFS_IALLOC_H__
    -
    -struct xfs_buf;
    -struct xfs_dinode;
    -struct xfs_mount;
    -struct xfs_trans;
    -
    -/*
    - * Allocation parameters for inode allocation.
    - */
    -#define	XFS_IALLOC_INODES(mp)	(mp)->m_ialloc_inos
    -#define	XFS_IALLOC_BLOCKS(mp)	(mp)->m_ialloc_blks
    -
    -/*
    - * For small block file systems, move inodes in clusters of this size.
    - * When we don't have a lot of memory, however, we go a bit smaller
    - * to reduce the number of AGI and ialloc btree blocks we need to keep
    - * around for xfs_dilocate().  We choose which one to use in
    - * xfs_mount_int().
    - */
    -#define	XFS_INODE_BIG_CLUSTER_SIZE	8192
    -#define	XFS_INODE_SMALL_CLUSTER_SIZE	4096
    -#define	XFS_INODE_CLUSTER_SIZE(mp)	(mp)->m_inode_cluster_size
    -
    -/*
    - * Make an inode pointer out of the buffer/offset.
    - */
    -#define	XFS_MAKE_IPTR(mp,b,o)		xfs_make_iptr(mp,b,o)
    -static inline struct xfs_dinode *
    -xfs_make_iptr(struct xfs_mount *mp, struct xfs_buf *b, int o)
    -{
    -	return (xfs_dinode_t *)
    -		(xfs_buf_offset(b, o << (mp)->m_sb.sb_inodelog));
    -}
    -
    -/*
    - * Find a free (set) bit in the inode bitmask.
    - */
    -#define	XFS_IALLOC_FIND_FREE(fp)	xfs_ialloc_find_free(fp)
    -static inline int xfs_ialloc_find_free(xfs_inofree_t *fp)
    -{
    -	return xfs_lowbit64(*fp);
    -}
    -
    -
    -#ifdef __KERNEL__
    -/*
    - * Allocate an inode on disk.
    - * Mode is used to tell whether the new inode will need space, and whether
    - * it is a directory.
    - *
    - * To work within the constraint of one allocation per transaction,
    - * xfs_dialloc() is designed to be called twice if it has to do an
    - * allocation to make more free inodes.  If an inode is
    - * available without an allocation, agbp would be set to the current
    - * agbp and alloc_done set to false.
    - * If an allocation needed to be done, agbp would be set to the
    - * inode header of the allocation group and alloc_done set to true.
    - * The caller should then commit the current transaction and allocate a new
    - * transaction.  xfs_dialloc() should then be called again with
    - * the agbp value returned from the previous call.
    - *
    - * Once we successfully pick an inode its number is returned and the
    - * on-disk data structures are updated.  The inode itself is not read
    - * in, since doing so would break ordering constraints with xfs_reclaim.
    - *
    - * *agbp should be set to NULL on the first call, *alloc_done set to FALSE.
    - */
    -int					/* error */
    -xfs_dialloc(
    -	struct xfs_trans *tp,		/* transaction pointer */
    -	xfs_ino_t	parent,		/* parent inode (directory) */
    -	mode_t		mode,		/* mode bits for new inode */
    -	int		okalloc,	/* ok to allocate more space */
    -	struct xfs_buf	**agbp,		/* buf for a.g. inode header */
    -	boolean_t	*alloc_done,	/* an allocation was done to replenish
    -					   the free inodes */
    -	xfs_ino_t	*inop);		/* inode number allocated */
    -
    -/*
    - * Free disk inode.  Carefully avoids touching the incore inode, all
    - * manipulations incore are the caller's responsibility.
    - * The on-disk inode is not changed by this operation, only the
    - * btree (free inode mask) is changed.
    - */
    -int					/* error */
    -xfs_difree(
    -	struct xfs_trans *tp,		/* transaction pointer */
    -	xfs_ino_t	inode,		/* inode to be freed */
    -	struct xfs_bmap_free *flist,	/* extents to free */
    -	int		*delete,	/* set if inode cluster was deleted */
    -	xfs_ino_t	*first_ino);	/* first inode in deleted cluster */
    -
    -/*
    - * Return the location of the inode in bno/len/off,
    - * for mapping it into a buffer.
    - */
    -int
    -xfs_dilocate(
    -	struct xfs_mount *mp,		/* file system mount structure */
    -	struct xfs_trans *tp,		/* transaction pointer */
    -	xfs_ino_t	ino,		/* inode to locate */
    -	xfs_fsblock_t	*bno,		/* output: block containing inode */
    -	int		*len,		/* output: num blocks in cluster*/
    -	int		*off,		/* output: index in block of inode */
    -	uint		flags);		/* flags for inode btree lookup */
    -
    -/*
    - * Compute and fill in value of m_in_maxlevels.
    - */
    -void
    -xfs_ialloc_compute_maxlevels(
    -	struct xfs_mount *mp);		/* file system mount structure */
    -
    -/*
    - * Log specified fields for the ag hdr (inode section)
    - */
    -void
    -xfs_ialloc_log_agi(
    -	struct xfs_trans *tp,		/* transaction pointer */
    -	struct xfs_buf	*bp,		/* allocation group header buffer */
    -	int		fields);	/* bitmask of fields to log */
    -
    -/*
    - * Read in the allocation group header (inode allocation section)
    - */
    -int					/* error */
    -xfs_ialloc_read_agi(
    -	struct xfs_mount *mp,		/* file system mount structure */
    -	struct xfs_trans *tp,		/* transaction pointer */
    -	xfs_agnumber_t	agno,		/* allocation group number */
    -	struct xfs_buf	**bpp);		/* allocation group hdr buf */
    -
    -#endif	/* __KERNEL__ */
    -
    -#endif	/* __XFS_IALLOC_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_ialloc_btree.c b/sys/gnu/fs/xfs/xfs_ialloc_btree.c
    deleted file mode 100644
    index 60c65683462..00000000000
    --- a/sys/gnu/fs/xfs/xfs_ialloc_btree.c
    +++ /dev/null
    @@ -1,2080 +0,0 @@
    -/*
    - * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_btree.h"
    -#include "xfs_ialloc.h"
    -#include "xfs_alloc.h"
    -#include "xfs_error.h"
    -
    -STATIC void xfs_inobt_log_block(xfs_trans_t *, xfs_buf_t *, int);
    -STATIC void xfs_inobt_log_keys(xfs_btree_cur_t *, xfs_buf_t *, int, int);
    -STATIC void xfs_inobt_log_ptrs(xfs_btree_cur_t *, xfs_buf_t *, int, int);
    -STATIC void xfs_inobt_log_recs(xfs_btree_cur_t *, xfs_buf_t *, int, int);
    -STATIC int xfs_inobt_lshift(xfs_btree_cur_t *, int, int *);
    -STATIC int xfs_inobt_newroot(xfs_btree_cur_t *, int *);
    -STATIC int xfs_inobt_rshift(xfs_btree_cur_t *, int, int *);
    -STATIC int xfs_inobt_split(xfs_btree_cur_t *, int, xfs_agblock_t *,
    -		xfs_inobt_key_t *, xfs_btree_cur_t **, int *);
    -STATIC int xfs_inobt_updkey(xfs_btree_cur_t *, xfs_inobt_key_t *, int);
    -
    -/*
    - * Single level of the xfs_inobt_delete record deletion routine.
    - * Delete record pointed to by cur/level.
    - * Remove the record from its block then rebalance the tree.
    - * Return 0 for error, 1 for done, 2 to go on to the next level.
    - */
    -STATIC int				/* error */
    -xfs_inobt_delrec(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	int			level,	/* level removing record from */
    -	int			*stat)	/* fail/done/go-on */
    -{
    -	xfs_buf_t		*agbp;	/* buffer for a.g. inode header */
    -	xfs_mount_t		*mp;	/* mount structure */
    -	xfs_agi_t		*agi;	/* allocation group inode header */
    -	xfs_inobt_block_t	*block;	/* btree block record/key lives in */
    -	xfs_agblock_t		bno;	/* btree block number */
    -	xfs_buf_t		*bp;	/* buffer for block */
    -	int			error;	/* error return value */
    -	int			i;	/* loop index */
    -	xfs_inobt_key_t		key;	/* kp points here if block is level 0 */
    -	xfs_inobt_key_t		*kp = NULL;	/* pointer to btree keys */
    -	xfs_agblock_t		lbno;	/* left block's block number */
    -	xfs_buf_t		*lbp;	/* left block's buffer pointer */
    -	xfs_inobt_block_t	*left;	/* left btree block */
    -	xfs_inobt_key_t		*lkp;	/* left block key pointer */
    -	xfs_inobt_ptr_t		*lpp;	/* left block address pointer */
    -	int			lrecs = 0;	/* number of records in left block */
    -	xfs_inobt_rec_t		*lrp;	/* left block record pointer */
    -	xfs_inobt_ptr_t		*pp = NULL;	/* pointer to btree addresses */
    -	int			ptr;	/* index in btree block for this rec */
    -	xfs_agblock_t		rbno;	/* right block's block number */
    -	xfs_buf_t		*rbp;	/* right block's buffer pointer */
    -	xfs_inobt_block_t	*right;	/* right btree block */
    -	xfs_inobt_key_t		*rkp;	/* right block key pointer */
    -	xfs_inobt_rec_t		*rp;	/* pointer to btree records */
    -	xfs_inobt_ptr_t		*rpp;	/* right block address pointer */
    -	int			rrecs = 0;	/* number of records in right block */
    -	int			numrecs;
    -	xfs_inobt_rec_t		*rrp;	/* right block record pointer */
    -	xfs_btree_cur_t		*tcur;	/* temporary btree cursor */
    -
    -	mp = cur->bc_mp;
    -
    -	/*
    -	 * Get the index of the entry being deleted, check for nothing there.
    -	 */
    -	ptr = cur->bc_ptrs[level];
    -	if (ptr == 0) {
    -		*stat = 0;
    -		return 0;
    -	}
    -
    -	/*
    -	 * Get the buffer & block containing the record or key/ptr.
    -	 */
    -	bp = cur->bc_bufs[level];
    -	block = XFS_BUF_TO_INOBT_BLOCK(bp);
    -#ifdef DEBUG
    -	if ((error = xfs_btree_check_sblock(cur, block, level, bp)))
    -		return error;
    -#endif
    -	/*
    -	 * Fail if we're off the end of the block.
    -	 */
    -
    -	numrecs = be16_to_cpu(block->bb_numrecs);
    -	if (ptr > numrecs) {
    -		*stat = 0;
    -		return 0;
    -	}
    -	/*
    -	 * It's a nonleaf.  Excise the key and ptr being deleted, by
    -	 * sliding the entries past them down one.
    -	 * Log the changed areas of the block.
    -	 */
    -	if (level > 0) {
    -		kp = XFS_INOBT_KEY_ADDR(block, 1, cur);
    -		pp = XFS_INOBT_PTR_ADDR(block, 1, cur);
    -#ifdef DEBUG
    -		for (i = ptr; i < numrecs; i++) {
    -			if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(pp[i]), level)))
    -				return error;
    -		}
    -#endif
    -		if (ptr < numrecs) {
    -			memmove(&kp[ptr - 1], &kp[ptr],
    -				(numrecs - ptr) * sizeof(*kp));
    -			memmove(&pp[ptr - 1], &pp[ptr],
    -				(numrecs - ptr) * sizeof(*kp));
    -			xfs_inobt_log_keys(cur, bp, ptr, numrecs - 1);
    -			xfs_inobt_log_ptrs(cur, bp, ptr, numrecs - 1);
    -		}
    -	}
    -	/*
    -	 * It's a leaf.  Excise the record being deleted, by sliding the
    -	 * entries past it down one.  Log the changed areas of the block.
    -	 */
    -	else {
    -		rp = XFS_INOBT_REC_ADDR(block, 1, cur);
    -		if (ptr < numrecs) {
    -			memmove(&rp[ptr - 1], &rp[ptr],
    -				(numrecs - ptr) * sizeof(*rp));
    -			xfs_inobt_log_recs(cur, bp, ptr, numrecs - 1);
    -		}
    -		/*
    -		 * If it's the first record in the block, we'll need a key
    -		 * structure to pass up to the next level (updkey).
    -		 */
    -		if (ptr == 1) {
    -			key.ir_startino = rp->ir_startino;
    -			kp = &key;
    -		}
    -	}
    -	/*
    -	 * Decrement and log the number of entries in the block.
    -	 */
    -	numrecs--;
    -	block->bb_numrecs = cpu_to_be16(numrecs);
    -	xfs_inobt_log_block(cur->bc_tp, bp, XFS_BB_NUMRECS);
    -	/*
    -	 * Is this the root level?  If so, we're almost done.
    -	 */
    -	if (level == cur->bc_nlevels - 1) {
    -		/*
    -		 * If this is the root level,
    -		 * and there's only one entry left,
    -		 * and it's NOT the leaf level,
    -		 * then we can get rid of this level.
    -		 */
    -		if (numrecs == 1 && level > 0) {
    -			agbp = cur->bc_private.i.agbp;
    -			agi = XFS_BUF_TO_AGI(agbp);
    -			/*
    -			 * pp is still set to the first pointer in the block.
    -			 * Make it the new root of the btree.
    -			 */
    -			bno = be32_to_cpu(agi->agi_root);
    -			agi->agi_root = *pp;
    -			be32_add(&agi->agi_level, -1);
    -			/*
    -			 * Free the block.
    -			 */
    -			if ((error = xfs_free_extent(cur->bc_tp,
    -				XFS_AGB_TO_FSB(mp, cur->bc_private.i.agno, bno), 1)))
    -				return error;
    -			xfs_trans_binval(cur->bc_tp, bp);
    -			xfs_ialloc_log_agi(cur->bc_tp, agbp,
    -				XFS_AGI_ROOT | XFS_AGI_LEVEL);
    -			/*
    -			 * Update the cursor so there's one fewer level.
    -			 */
    -			cur->bc_bufs[level] = NULL;
    -			cur->bc_nlevels--;
    -		} else if (level > 0 &&
    -			   (error = xfs_inobt_decrement(cur, level, &i)))
    -			return error;
    -		*stat = 1;
    -		return 0;
    -	}
    -	/*
    -	 * If we deleted the leftmost entry in the block, update the
    -	 * key values above us in the tree.
    -	 */
    -	if (ptr == 1 && (error = xfs_inobt_updkey(cur, kp, level + 1)))
    -		return error;
    -	/*
    -	 * If the number of records remaining in the block is at least
    -	 * the minimum, we're done.
    -	 */
    -	if (numrecs >= XFS_INOBT_BLOCK_MINRECS(level, cur)) {
    -		if (level > 0 &&
    -		    (error = xfs_inobt_decrement(cur, level, &i)))
    -			return error;
    -		*stat = 1;
    -		return 0;
    -	}
    -	/*
    -	 * Otherwise, we have to move some records around to keep the
    -	 * tree balanced.  Look at the left and right sibling blocks to
    -	 * see if we can re-balance by moving only one record.
    -	 */
    -	rbno = be32_to_cpu(block->bb_rightsib);
    -	lbno = be32_to_cpu(block->bb_leftsib);
    -	bno = NULLAGBLOCK;
    -	ASSERT(rbno != NULLAGBLOCK || lbno != NULLAGBLOCK);
    -	/*
    -	 * Duplicate the cursor so our btree manipulations here won't
    -	 * disrupt the next level up.
    -	 */
    -	if ((error = xfs_btree_dup_cursor(cur, &tcur)))
    -		return error;
    -	/*
    -	 * If there's a right sibling, see if it's ok to shift an entry
    -	 * out of it.
    -	 */
    -	if (rbno != NULLAGBLOCK) {
    -		/*
    -		 * Move the temp cursor to the last entry in the next block.
    -		 * Actually any entry but the first would suffice.
    -		 */
    -		i = xfs_btree_lastrec(tcur, level);
    -		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -		if ((error = xfs_inobt_increment(tcur, level, &i)))
    -			goto error0;
    -		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -		i = xfs_btree_lastrec(tcur, level);
    -		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
    -		/*
    -		 * Grab a pointer to the block.
    -		 */
    -		rbp = tcur->bc_bufs[level];
    -		right = XFS_BUF_TO_INOBT_BLOCK(rbp);
    -#ifdef DEBUG
    -		if ((error = xfs_btree_check_sblock(cur, right, level, rbp)))
    -			goto error0;
    -#endif
    -		/*
    -		 * Grab the current block number, for future use.
    -		 */
    -		bno = be32_to_cpu(right->bb_leftsib);
    -		/*
    -		 * If right block is full enough so that removing one entry
    -		 * won't make it too empty, and left-shifting an entry out
    -		 * of right to us works, we're done.
    -		 */
    -		if (be16_to_cpu(right->bb_numrecs) - 1 >=
    -		     XFS_INOBT_BLOCK_MINRECS(level, cur)) {
    -			if ((error = xfs_inobt_lshift(tcur, level, &i)))
    -				goto error0;
    -			if (i) {
    -				ASSERT(be16_to_cpu(block->bb_numrecs) >=
    -				       XFS_INOBT_BLOCK_MINRECS(level, cur));
    -				xfs_btree_del_cursor(tcur,
    -						     XFS_BTREE_NOERROR);
    -				if (level > 0 &&
    -				    (error = xfs_inobt_decrement(cur, level,
    -						&i)))
    -					return error;
    -				*stat = 1;
    -				return 0;
    -			}
    -		}
    -		/*
    -		 * Otherwise, grab the number of records in right for
    -		 * future reference, and fix up the temp cursor to point
    -		 * to our block again (last record).
    -		 */
    -		rrecs = be16_to_cpu(right->bb_numrecs);
    -		if (lbno != NULLAGBLOCK) {
    -			xfs_btree_firstrec(tcur, level);
    -			if ((error = xfs_inobt_decrement(tcur, level, &i)))
    -				goto error0;
    -		}
    -	}
    -	/*
    -	 * If there's a left sibling, see if it's ok to shift an entry
    -	 * out of it.
    -	 */
    -	if (lbno != NULLAGBLOCK) {
    -		/*
    -		 * Move the temp cursor to the first entry in the
    -		 * previous block.
    -		 */
    -		xfs_btree_firstrec(tcur, level);
    -		if ((error = xfs_inobt_decrement(tcur, level, &i)))
    -			goto error0;
    -		xfs_btree_firstrec(tcur, level);
    -		/*
    -		 * Grab a pointer to the block.
    -		 */
    -		lbp = tcur->bc_bufs[level];
    -		left = XFS_BUF_TO_INOBT_BLOCK(lbp);
    -#ifdef DEBUG
    -		if ((error = xfs_btree_check_sblock(cur, left, level, lbp)))
    -			goto error0;
    -#endif
    -		/*
    -		 * Grab the current block number, for future use.
    -		 */
    -		bno = be32_to_cpu(left->bb_rightsib);
    -		/*
    -		 * If left block is full enough so that removing one entry
    -		 * won't make it too empty, and right-shifting an entry out
    -		 * of left to us works, we're done.
    -		 */
    -		if (be16_to_cpu(left->bb_numrecs) - 1 >=
    -		     XFS_INOBT_BLOCK_MINRECS(level, cur)) {
    -			if ((error = xfs_inobt_rshift(tcur, level, &i)))
    -				goto error0;
    -			if (i) {
    -				ASSERT(be16_to_cpu(block->bb_numrecs) >=
    -				       XFS_INOBT_BLOCK_MINRECS(level, cur));
    -				xfs_btree_del_cursor(tcur,
    -						     XFS_BTREE_NOERROR);
    -				if (level == 0)
    -					cur->bc_ptrs[0]++;
    -				*stat = 1;
    -				return 0;
    -			}
    -		}
    -		/*
    -		 * Otherwise, grab the number of records in right for
    -		 * future reference.
    -		 */
    -		lrecs = be16_to_cpu(left->bb_numrecs);
    -	}
    -	/*
    -	 * Delete the temp cursor, we're done with it.
    -	 */
    -	xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
    -	/*
    -	 * If here, we need to do a join to keep the tree balanced.
    -	 */
    -	ASSERT(bno != NULLAGBLOCK);
    -	/*
    -	 * See if we can join with the left neighbor block.
    -	 */
    -	if (lbno != NULLAGBLOCK &&
    -	    lrecs + numrecs <= XFS_INOBT_BLOCK_MAXRECS(level, cur)) {
    -		/*
    -		 * Set "right" to be the starting block,
    -		 * "left" to be the left neighbor.
    -		 */
    -		rbno = bno;
    -		right = block;
    -		rrecs = be16_to_cpu(right->bb_numrecs);
    -		rbp = bp;
    -		if ((error = xfs_btree_read_bufs(mp, cur->bc_tp,
    -				cur->bc_private.i.agno, lbno, 0, &lbp,
    -				XFS_INO_BTREE_REF)))
    -			return error;
    -		left = XFS_BUF_TO_INOBT_BLOCK(lbp);
    -		lrecs = be16_to_cpu(left->bb_numrecs);
    -		if ((error = xfs_btree_check_sblock(cur, left, level, lbp)))
    -			return error;
    -	}
    -	/*
    -	 * If that won't work, see if we can join with the right neighbor block.
    -	 */
    -	else if (rbno != NULLAGBLOCK &&
    -		 rrecs + numrecs <= XFS_INOBT_BLOCK_MAXRECS(level, cur)) {
    -		/*
    -		 * Set "left" to be the starting block,
    -		 * "right" to be the right neighbor.
    -		 */
    -		lbno = bno;
    -		left = block;
    -		lrecs = be16_to_cpu(left->bb_numrecs);
    -		lbp = bp;
    -		if ((error = xfs_btree_read_bufs(mp, cur->bc_tp,
    -				cur->bc_private.i.agno, rbno, 0, &rbp,
    -				XFS_INO_BTREE_REF)))
    -			return error;
    -		right = XFS_BUF_TO_INOBT_BLOCK(rbp);
    -		rrecs = be16_to_cpu(right->bb_numrecs);
    -		if ((error = xfs_btree_check_sblock(cur, right, level, rbp)))
    -			return error;
    -	}
    -	/*
    -	 * Otherwise, we can't fix the imbalance.
    -	 * Just return.  This is probably a logic error, but it's not fatal.
    -	 */
    -	else {
    -		if (level > 0 && (error = xfs_inobt_decrement(cur, level, &i)))
    -			return error;
    -		*stat = 1;
    -		return 0;
    -	}
    -	/*
    -	 * We're now going to join "left" and "right" by moving all the stuff
    -	 * in "right" to "left" and deleting "right".
    -	 */
    -	if (level > 0) {
    -		/*
    -		 * It's a non-leaf.  Move keys and pointers.
    -		 */
    -		lkp = XFS_INOBT_KEY_ADDR(left, lrecs + 1, cur);
    -		lpp = XFS_INOBT_PTR_ADDR(left, lrecs + 1, cur);
    -		rkp = XFS_INOBT_KEY_ADDR(right, 1, cur);
    -		rpp = XFS_INOBT_PTR_ADDR(right, 1, cur);
    -#ifdef DEBUG
    -		for (i = 0; i < rrecs; i++) {
    -			if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(rpp[i]), level)))
    -				return error;
    -		}
    -#endif
    -		memcpy(lkp, rkp, rrecs * sizeof(*lkp));
    -		memcpy(lpp, rpp, rrecs * sizeof(*lpp));
    -		xfs_inobt_log_keys(cur, lbp, lrecs + 1, lrecs + rrecs);
    -		xfs_inobt_log_ptrs(cur, lbp, lrecs + 1, lrecs + rrecs);
    -	} else {
    -		/*
    -		 * It's a leaf.  Move records.
    -		 */
    -		lrp = XFS_INOBT_REC_ADDR(left, lrecs + 1, cur);
    -		rrp = XFS_INOBT_REC_ADDR(right, 1, cur);
    -		memcpy(lrp, rrp, rrecs * sizeof(*lrp));
    -		xfs_inobt_log_recs(cur, lbp, lrecs + 1, lrecs + rrecs);
    -	}
    -	/*
    -	 * If we joined with the left neighbor, set the buffer in the
    -	 * cursor to the left block, and fix up the index.
    -	 */
    -	if (bp != lbp) {
    -		xfs_btree_setbuf(cur, level, lbp);
    -		cur->bc_ptrs[level] += lrecs;
    -	}
    -	/*
    -	 * If we joined with the right neighbor and there's a level above
    -	 * us, increment the cursor at that level.
    -	 */
    -	else if (level + 1 < cur->bc_nlevels &&
    -		 (error = xfs_alloc_increment(cur, level + 1, &i)))
    -		return error;
    -	/*
    -	 * Fix up the number of records in the surviving block.
    -	 */
    -	lrecs += rrecs;
    -	left->bb_numrecs = cpu_to_be16(lrecs);
    -	/*
    -	 * Fix up the right block pointer in the surviving block, and log it.
    -	 */
    -	left->bb_rightsib = right->bb_rightsib;
    -	xfs_inobt_log_block(cur->bc_tp, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB);
    -	/*
    -	 * If there is a right sibling now, make it point to the
    -	 * remaining block.
    -	 */
    -	if (be32_to_cpu(left->bb_rightsib) != NULLAGBLOCK) {
    -		xfs_inobt_block_t	*rrblock;
    -		xfs_buf_t		*rrbp;
    -
    -		if ((error = xfs_btree_read_bufs(mp, cur->bc_tp,
    -				cur->bc_private.i.agno, be32_to_cpu(left->bb_rightsib), 0,
    -				&rrbp, XFS_INO_BTREE_REF)))
    -			return error;
    -		rrblock = XFS_BUF_TO_INOBT_BLOCK(rrbp);
    -		if ((error = xfs_btree_check_sblock(cur, rrblock, level, rrbp)))
    -			return error;
    -		rrblock->bb_leftsib = cpu_to_be32(lbno);
    -		xfs_inobt_log_block(cur->bc_tp, rrbp, XFS_BB_LEFTSIB);
    -	}
    -	/*
    -	 * Free the deleting block.
    -	 */
    -	if ((error = xfs_free_extent(cur->bc_tp, XFS_AGB_TO_FSB(mp,
    -				     cur->bc_private.i.agno, rbno), 1)))
    -		return error;
    -	xfs_trans_binval(cur->bc_tp, rbp);
    -	/*
    -	 * Readjust the ptr at this level if it's not a leaf, since it's
    -	 * still pointing at the deletion point, which makes the cursor
    -	 * inconsistent.  If this makes the ptr 0, the caller fixes it up.
    -	 * We can't use decrement because it would change the next level up.
    -	 */
    -	if (level > 0)
    -		cur->bc_ptrs[level]--;
    -	/*
    -	 * Return value means the next level up has something to do.
    -	 */
    -	*stat = 2;
    -	return 0;
    -
    -error0:
    -	xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR);
    -	return error;
    -}
    -
    -/*
    - * Insert one record/level.  Return information to the caller
    - * allowing the next level up to proceed if necessary.
    - */
    -STATIC int				/* error */
    -xfs_inobt_insrec(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	int			level,	/* level to insert record at */
    -	xfs_agblock_t		*bnop,	/* i/o: block number inserted */
    -	xfs_inobt_rec_t		*recp,	/* i/o: record data inserted */
    -	xfs_btree_cur_t		**curp,	/* output: new cursor replacing cur */
    -	int			*stat)	/* success/failure */
    -{
    -	xfs_inobt_block_t	*block;	/* btree block record/key lives in */
    -	xfs_buf_t		*bp;	/* buffer for block */
    -	int			error;	/* error return value */
    -	int			i;	/* loop index */
    -	xfs_inobt_key_t		key;	/* key value being inserted */
    -	xfs_inobt_key_t		*kp=NULL;	/* pointer to btree keys */
    -	xfs_agblock_t		nbno;	/* block number of allocated block */
    -	xfs_btree_cur_t		*ncur;	/* new cursor to be used at next lvl */
    -	xfs_inobt_key_t		nkey;	/* new key value, from split */
    -	xfs_inobt_rec_t		nrec;	/* new record value, for caller */
    -	int			numrecs;
    -	int			optr;	/* old ptr value */
    -	xfs_inobt_ptr_t		*pp;	/* pointer to btree addresses */
    -	int			ptr;	/* index in btree block for this rec */
    -	xfs_inobt_rec_t		*rp=NULL;	/* pointer to btree records */
    -
    -	/*
    -	 * GCC doesn't understand the (arguably complex) control flow in
    -	 * this function and complains about uninitialized structure fields
    -	 * without this.
    -	 */
    -	memset(&nrec, 0, sizeof(nrec));
    -
    -	/*
    -	 * If we made it to the root level, allocate a new root block
    -	 * and we're done.
    -	 */
    -	if (level >= cur->bc_nlevels) {
    -		error = xfs_inobt_newroot(cur, &i);
    -		*bnop = NULLAGBLOCK;
    -		*stat = i;
    -		return error;
    -	}
    -	/*
    -	 * Make a key out of the record data to be inserted, and save it.
    -	 */
    -	key.ir_startino = recp->ir_startino; /* INT_: direct copy */
    -	optr = ptr = cur->bc_ptrs[level];
    -	/*
    -	 * If we're off the left edge, return failure.
    -	 */
    -	if (ptr == 0) {
    -		*stat = 0;
    -		return 0;
    -	}
    -	/*
    -	 * Get pointers to the btree buffer and block.
    -	 */
    -	bp = cur->bc_bufs[level];
    -	block = XFS_BUF_TO_INOBT_BLOCK(bp);
    -	numrecs = be16_to_cpu(block->bb_numrecs);
    -#ifdef DEBUG
    -	if ((error = xfs_btree_check_sblock(cur, block, level, bp)))
    -		return error;
    -	/*
    -	 * Check that the new entry is being inserted in the right place.
    -	 */
    -	if (ptr <= numrecs) {
    -		if (level == 0) {
    -			rp = XFS_INOBT_REC_ADDR(block, ptr, cur);
    -			xfs_btree_check_rec(cur->bc_btnum, recp, rp);
    -		} else {
    -			kp = XFS_INOBT_KEY_ADDR(block, ptr, cur);
    -			xfs_btree_check_key(cur->bc_btnum, &key, kp);
    -		}
    -	}
    -#endif
    -	nbno = NULLAGBLOCK;
    -	ncur = (xfs_btree_cur_t *)0;
    -	/*
    -	 * If the block is full, we can't insert the new entry until we
    -	 * make the block un-full.
    -	 */
    -	if (numrecs == XFS_INOBT_BLOCK_MAXRECS(level, cur)) {
    -		/*
    -		 * First, try shifting an entry to the right neighbor.
    -		 */
    -		if ((error = xfs_inobt_rshift(cur, level, &i)))
    -			return error;
    -		if (i) {
    -			/* nothing */
    -		}
    -		/*
    -		 * Next, try shifting an entry to the left neighbor.
    -		 */
    -		else {
    -			if ((error = xfs_inobt_lshift(cur, level, &i)))
    -				return error;
    -			if (i) {
    -				optr = ptr = cur->bc_ptrs[level];
    -			} else {
    -				/*
    -				 * Next, try splitting the current block
    -				 * in half. If this works we have to
    -				 * re-set our variables because
    -				 * we could be in a different block now.
    -				 */
    -				if ((error = xfs_inobt_split(cur, level, &nbno,
    -						&nkey, &ncur, &i)))
    -					return error;
    -				if (i) {
    -					bp = cur->bc_bufs[level];
    -					block = XFS_BUF_TO_INOBT_BLOCK(bp);
    -#ifdef DEBUG
    -					if ((error = xfs_btree_check_sblock(cur,
    -							block, level, bp)))
    -						return error;
    -#endif
    -					ptr = cur->bc_ptrs[level];
    -					nrec.ir_startino = nkey.ir_startino; /* INT_: direct copy */
    -				} else {
    -					/*
    -					 * Otherwise the insert fails.
    -					 */
    -					*stat = 0;
    -					return 0;
    -				}
    -			}
    -		}
    -	}
    -	/*
    -	 * At this point we know there's room for our new entry in the block
    -	 * we're pointing at.
    -	 */
    -	numrecs = be16_to_cpu(block->bb_numrecs);
    -	if (level > 0) {
    -		/*
    -		 * It's a non-leaf entry.  Make a hole for the new data
    -		 * in the key and ptr regions of the block.
    -		 */
    -		kp = XFS_INOBT_KEY_ADDR(block, 1, cur);
    -		pp = XFS_INOBT_PTR_ADDR(block, 1, cur);
    -#ifdef DEBUG
    -		for (i = numrecs; i >= ptr; i--) {
    -			if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(pp[i - 1]), level)))
    -				return error;
    -		}
    -#endif
    -		memmove(&kp[ptr], &kp[ptr - 1],
    -			(numrecs - ptr + 1) * sizeof(*kp));
    -		memmove(&pp[ptr], &pp[ptr - 1],
    -			(numrecs - ptr + 1) * sizeof(*pp));
    -		/*
    -		 * Now stuff the new data in, bump numrecs and log the new data.
    -		 */
    -#ifdef DEBUG
    -		if ((error = xfs_btree_check_sptr(cur, *bnop, level)))
    -			return error;
    -#endif
    -		kp[ptr - 1] = key; /* INT_: struct copy */
    -		pp[ptr - 1] = cpu_to_be32(*bnop);
    -		numrecs++;
    -		block->bb_numrecs = cpu_to_be16(numrecs);
    -		xfs_inobt_log_keys(cur, bp, ptr, numrecs);
    -		xfs_inobt_log_ptrs(cur, bp, ptr, numrecs);
    -	} else {
    -		/*
    -		 * It's a leaf entry.  Make a hole for the new record.
    -		 */
    -		rp = XFS_INOBT_REC_ADDR(block, 1, cur);
    -		memmove(&rp[ptr], &rp[ptr - 1],
    -			(numrecs - ptr + 1) * sizeof(*rp));
    -		/*
    -		 * Now stuff the new record in, bump numrecs
    -		 * and log the new data.
    -		 */
    -		rp[ptr - 1] = *recp; /* INT_: struct copy */
    -		numrecs++;
    -		block->bb_numrecs = cpu_to_be16(numrecs);
    -		xfs_inobt_log_recs(cur, bp, ptr, numrecs);
    -	}
    -	/*
    -	 * Log the new number of records in the btree header.
    -	 */
    -	xfs_inobt_log_block(cur->bc_tp, bp, XFS_BB_NUMRECS);
    -#ifdef DEBUG
    -	/*
    -	 * Check that the key/record is in the right place, now.
    -	 */
    -	if (ptr < numrecs) {
    -		if (level == 0)
    -			xfs_btree_check_rec(cur->bc_btnum, rp + ptr - 1,
    -				rp + ptr);
    -		else
    -			xfs_btree_check_key(cur->bc_btnum, kp + ptr - 1,
    -				kp + ptr);
    -	}
    -#endif
    -	/*
    -	 * If we inserted at the start of a block, update the parents' keys.
    -	 */
    -	if (optr == 1 && (error = xfs_inobt_updkey(cur, &key, level + 1)))
    -		return error;
    -	/*
    -	 * Return the new block number, if any.
    -	 * If there is one, give back a record value and a cursor too.
    -	 */
    -	*bnop = nbno;
    -	if (nbno != NULLAGBLOCK) {
    -		*recp = nrec; /* INT_: struct copy */
    -		*curp = ncur;
    -	}
    -	*stat = 1;
    -	return 0;
    -}
    -
    -/*
    - * Log header fields from a btree block.
    - */
    -STATIC void
    -xfs_inobt_log_block(
    -	xfs_trans_t		*tp,	/* transaction pointer */
    -	xfs_buf_t		*bp,	/* buffer containing btree block */
    -	int			fields)	/* mask of fields: XFS_BB_... */
    -{
    -	int			first;	/* first byte offset logged */
    -	int			last;	/* last byte offset logged */
    -	static const short	offsets[] = {	/* table of offsets */
    -		offsetof(xfs_inobt_block_t, bb_magic),
    -		offsetof(xfs_inobt_block_t, bb_level),
    -		offsetof(xfs_inobt_block_t, bb_numrecs),
    -		offsetof(xfs_inobt_block_t, bb_leftsib),
    -		offsetof(xfs_inobt_block_t, bb_rightsib),
    -		sizeof(xfs_inobt_block_t)
    -	};
    -
    -	xfs_btree_offsets(fields, offsets, XFS_BB_NUM_BITS, &first, &last);
    -	xfs_trans_log_buf(tp, bp, first, last);
    -}
    -
    -/*
    - * Log keys from a btree block (nonleaf).
    - */
    -STATIC void
    -xfs_inobt_log_keys(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	xfs_buf_t		*bp,	/* buffer containing btree block */
    -	int			kfirst,	/* index of first key to log */
    -	int			klast)	/* index of last key to log */
    -{
    -	xfs_inobt_block_t	*block;	/* btree block to log from */
    -	int			first;	/* first byte offset logged */
    -	xfs_inobt_key_t		*kp;	/* key pointer in btree block */
    -	int			last;	/* last byte offset logged */
    -
    -	block = XFS_BUF_TO_INOBT_BLOCK(bp);
    -	kp = XFS_INOBT_KEY_ADDR(block, 1, cur);
    -	first = (int)((xfs_caddr_t)&kp[kfirst - 1] - (xfs_caddr_t)block);
    -	last = (int)(((xfs_caddr_t)&kp[klast] - 1) - (xfs_caddr_t)block);
    -	xfs_trans_log_buf(cur->bc_tp, bp, first, last);
    -}
    -
    -/*
    - * Log block pointer fields from a btree block (nonleaf).
    - */
    -STATIC void
    -xfs_inobt_log_ptrs(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	xfs_buf_t		*bp,	/* buffer containing btree block */
    -	int			pfirst,	/* index of first pointer to log */
    -	int			plast)	/* index of last pointer to log */
    -{
    -	xfs_inobt_block_t	*block;	/* btree block to log from */
    -	int			first;	/* first byte offset logged */
    -	int			last;	/* last byte offset logged */
    -	xfs_inobt_ptr_t		*pp;	/* block-pointer pointer in btree blk */
    -
    -	block = XFS_BUF_TO_INOBT_BLOCK(bp);
    -	pp = XFS_INOBT_PTR_ADDR(block, 1, cur);
    -	first = (int)((xfs_caddr_t)&pp[pfirst - 1] - (xfs_caddr_t)block);
    -	last = (int)(((xfs_caddr_t)&pp[plast] - 1) - (xfs_caddr_t)block);
    -	xfs_trans_log_buf(cur->bc_tp, bp, first, last);
    -}
    -
    -/*
    - * Log records from a btree block (leaf).
    - */
    -STATIC void
    -xfs_inobt_log_recs(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	xfs_buf_t		*bp,	/* buffer containing btree block */
    -	int			rfirst,	/* index of first record to log */
    -	int			rlast)	/* index of last record to log */
    -{
    -	xfs_inobt_block_t	*block;	/* btree block to log from */
    -	int			first;	/* first byte offset logged */
    -	int			last;	/* last byte offset logged */
    -	xfs_inobt_rec_t		*rp;	/* record pointer for btree block */
    -
    -	block = XFS_BUF_TO_INOBT_BLOCK(bp);
    -	rp = XFS_INOBT_REC_ADDR(block, 1, cur);
    -	first = (int)((xfs_caddr_t)&rp[rfirst - 1] - (xfs_caddr_t)block);
    -	last = (int)(((xfs_caddr_t)&rp[rlast] - 1) - (xfs_caddr_t)block);
    -	xfs_trans_log_buf(cur->bc_tp, bp, first, last);
    -}
    -
    -/*
    - * Lookup the record.  The cursor is made to point to it, based on dir.
    - * Return 0 if can't find any such record, 1 for success.
    - */
    -STATIC int				/* error */
    -xfs_inobt_lookup(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	xfs_lookup_t		dir,	/* <=, ==, or >= */
    -	int			*stat)	/* success/failure */
    -{
    -	xfs_agblock_t		agbno;	/* a.g. relative btree block number */
    -	xfs_agnumber_t		agno;	/* allocation group number */
    -	xfs_inobt_block_t	*block=NULL;	/* current btree block */
    -	__int64_t		diff;	/* difference for the current key */
    -	int			error;	/* error return value */
    -	int			keyno=0;	/* current key number */
    -	int			level;	/* level in the btree */
    -	xfs_mount_t		*mp;	/* file system mount point */
    -
    -	/*
    -	 * Get the allocation group header, and the root block number.
    -	 */
    -	mp = cur->bc_mp;
    -	{
    -		xfs_agi_t	*agi;	/* a.g. inode header */
    -
    -		agi = XFS_BUF_TO_AGI(cur->bc_private.i.agbp);
    -		agno = be32_to_cpu(agi->agi_seqno);
    -		agbno = be32_to_cpu(agi->agi_root);
    -	}
    -	/*
    -	 * Iterate over each level in the btree, starting at the root.
    -	 * For each level above the leaves, find the key we need, based
    -	 * on the lookup record, then follow the corresponding block
    -	 * pointer down to the next level.
    -	 */
    -	for (level = cur->bc_nlevels - 1, diff = 1; level >= 0; level--) {
    -		xfs_buf_t	*bp;	/* buffer pointer for btree block */
    -		xfs_daddr_t	d;	/* disk address of btree block */
    -
    -		/*
    -		 * Get the disk address we're looking for.
    -		 */
    -		d = XFS_AGB_TO_DADDR(mp, agno, agbno);
    -		/*
    -		 * If the old buffer at this level is for a different block,
    -		 * throw it away, otherwise just use it.
    -		 */
    -		bp = cur->bc_bufs[level];
    -		if (bp && XFS_BUF_ADDR(bp) != d)
    -			bp = (xfs_buf_t *)0;
    -		if (!bp) {
    -			/*
    -			 * Need to get a new buffer.  Read it, then
    -			 * set it in the cursor, releasing the old one.
    -			 */
    -			if ((error = xfs_btree_read_bufs(mp, cur->bc_tp,
    -					agno, agbno, 0, &bp, XFS_INO_BTREE_REF)))
    -				return error;
    -			xfs_btree_setbuf(cur, level, bp);
    -			/*
    -			 * Point to the btree block, now that we have the buffer
    -			 */
    -			block = XFS_BUF_TO_INOBT_BLOCK(bp);
    -			if ((error = xfs_btree_check_sblock(cur, block, level,
    -					bp)))
    -				return error;
    -		} else
    -			block = XFS_BUF_TO_INOBT_BLOCK(bp);
    -		/*
    -		 * If we already had a key match at a higher level, we know
    -		 * we need to use the first entry in this block.
    -		 */
    -		if (diff == 0)
    -			keyno = 1;
    -		/*
    -		 * Otherwise we need to search this block.  Do a binary search.
    -		 */
    -		else {
    -			int		high;	/* high entry number */
    -			xfs_inobt_key_t	*kkbase=NULL;/* base of keys in block */
    -			xfs_inobt_rec_t	*krbase=NULL;/* base of records in block */
    -			int		low;	/* low entry number */
    -
    -			/*
    -			 * Get a pointer to keys or records.
    -			 */
    -			if (level > 0)
    -				kkbase = XFS_INOBT_KEY_ADDR(block, 1, cur);
    -			else
    -				krbase = XFS_INOBT_REC_ADDR(block, 1, cur);
    -			/*
    -			 * Set low and high entry numbers, 1-based.
    -			 */
    -			low = 1;
    -			if (!(high = be16_to_cpu(block->bb_numrecs))) {
    -				/*
    -				 * If the block is empty, the tree must
    -				 * be an empty leaf.
    -				 */
    -				ASSERT(level == 0 && cur->bc_nlevels == 1);
    -				cur->bc_ptrs[0] = dir != XFS_LOOKUP_LE;
    -				*stat = 0;
    -				return 0;
    -			}
    -			/*
    -			 * Binary search the block.
    -			 */
    -			while (low <= high) {
    -				xfs_agino_t	startino;	/* key value */
    -
    -				/*
    -				 * keyno is average of low and high.
    -				 */
    -				keyno = (low + high) >> 1;
    -				/*
    -				 * Get startino.
    -				 */
    -				if (level > 0) {
    -					xfs_inobt_key_t	*kkp;
    -
    -					kkp = kkbase + keyno - 1;
    -					startino = INT_GET(kkp->ir_startino, ARCH_CONVERT);
    -				} else {
    -					xfs_inobt_rec_t	*krp;
    -
    -					krp = krbase + keyno - 1;
    -					startino = INT_GET(krp->ir_startino, ARCH_CONVERT);
    -				}
    -				/*
    -				 * Compute difference to get next direction.
    -				 */
    -				diff = (__int64_t)
    -					startino - cur->bc_rec.i.ir_startino;
    -				/*
    -				 * Less than, move right.
    -				 */
    -				if (diff < 0)
    -					low = keyno + 1;
    -				/*
    -				 * Greater than, move left.
    -				 */
    -				else if (diff > 0)
    -					high = keyno - 1;
    -				/*
    -				 * Equal, we're done.
    -				 */
    -				else
    -					break;
    -			}
    -		}
    -		/*
    -		 * If there are more levels, set up for the next level
    -		 * by getting the block number and filling in the cursor.
    -		 */
    -		if (level > 0) {
    -			/*
    -			 * If we moved left, need the previous key number,
    -			 * unless there isn't one.
    -			 */
    -			if (diff > 0 && --keyno < 1)
    -				keyno = 1;
    -			agbno = be32_to_cpu(*XFS_INOBT_PTR_ADDR(block, keyno, cur));
    -#ifdef DEBUG
    -			if ((error = xfs_btree_check_sptr(cur, agbno, level)))
    -				return error;
    -#endif
    -			cur->bc_ptrs[level] = keyno;
    -		}
    -	}
    -	/*
    -	 * Done with the search.
    -	 * See if we need to adjust the results.
    -	 */
    -	if (dir != XFS_LOOKUP_LE && diff < 0) {
    -		keyno++;
    -		/*
    -		 * If ge search and we went off the end of the block, but it's
    -		 * not the last block, we're in the wrong block.
    -		 */
    -		if (dir == XFS_LOOKUP_GE &&
    -		    keyno > be16_to_cpu(block->bb_numrecs) &&
    -		    be32_to_cpu(block->bb_rightsib) != NULLAGBLOCK) {
    -			int	i;
    -
    -			cur->bc_ptrs[0] = keyno;
    -			if ((error = xfs_inobt_increment(cur, 0, &i)))
    -				return error;
    -			ASSERT(i == 1);
    -			*stat = 1;
    -			return 0;
    -		}
    -	}
    -	else if (dir == XFS_LOOKUP_LE && diff > 0)
    -		keyno--;
    -	cur->bc_ptrs[0] = keyno;
    -	/*
    -	 * Return if we succeeded or not.
    -	 */
    -	if (keyno == 0 || keyno > be16_to_cpu(block->bb_numrecs))
    -		*stat = 0;
    -	else
    -		*stat = ((dir != XFS_LOOKUP_EQ) || (diff == 0));
    -	return 0;
    -}
    -
    -/*
    - * Move 1 record left from cur/level if possible.
    - * Update cur to reflect the new path.
    - */
    -STATIC int				/* error */
    -xfs_inobt_lshift(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	int			level,	/* level to shift record on */
    -	int			*stat)	/* success/failure */
    -{
    -	int			error;	/* error return value */
    -#ifdef DEBUG
    -	int			i;	/* loop index */
    -#endif
    -	xfs_inobt_key_t		key;	/* key value for leaf level upward */
    -	xfs_buf_t		*lbp;	/* buffer for left neighbor block */
    -	xfs_inobt_block_t	*left;	/* left neighbor btree block */
    -	xfs_inobt_key_t		*lkp=NULL;	/* key pointer for left block */
    -	xfs_inobt_ptr_t		*lpp;	/* address pointer for left block */
    -	xfs_inobt_rec_t		*lrp=NULL;	/* record pointer for left block */
    -	int			nrec;	/* new number of left block entries */
    -	xfs_buf_t		*rbp;	/* buffer for right (current) block */
    -	xfs_inobt_block_t	*right;	/* right (current) btree block */
    -	xfs_inobt_key_t		*rkp=NULL;	/* key pointer for right block */
    -	xfs_inobt_ptr_t		*rpp=NULL;	/* address pointer for right block */
    -	xfs_inobt_rec_t		*rrp=NULL;	/* record pointer for right block */
    -
    -	/*
    -	 * Set up variables for this block as "right".
    -	 */
    -	rbp = cur->bc_bufs[level];
    -	right = XFS_BUF_TO_INOBT_BLOCK(rbp);
    -#ifdef DEBUG
    -	if ((error = xfs_btree_check_sblock(cur, right, level, rbp)))
    -		return error;
    -#endif
    -	/*
    -	 * If we've got no left sibling then we can't shift an entry left.
    -	 */
    -	if (be32_to_cpu(right->bb_leftsib) == NULLAGBLOCK) {
    -		*stat = 0;
    -		return 0;
    -	}
    -	/*
    -	 * If the cursor entry is the one that would be moved, don't
    -	 * do it... it's too complicated.
    -	 */
    -	if (cur->bc_ptrs[level] <= 1) {
    -		*stat = 0;
    -		return 0;
    -	}
    -	/*
    -	 * Set up the left neighbor as "left".
    -	 */
    -	if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp,
    -			cur->bc_private.i.agno, be32_to_cpu(right->bb_leftsib),
    -			0, &lbp, XFS_INO_BTREE_REF)))
    -		return error;
    -	left = XFS_BUF_TO_INOBT_BLOCK(lbp);
    -	if ((error = xfs_btree_check_sblock(cur, left, level, lbp)))
    -		return error;
    -	/*
    -	 * If it's full, it can't take another entry.
    -	 */
    -	if (be16_to_cpu(left->bb_numrecs) == XFS_INOBT_BLOCK_MAXRECS(level, cur)) {
    -		*stat = 0;
    -		return 0;
    -	}
    -	nrec = be16_to_cpu(left->bb_numrecs) + 1;
    -	/*
    -	 * If non-leaf, copy a key and a ptr to the left block.
    -	 */
    -	if (level > 0) {
    -		lkp = XFS_INOBT_KEY_ADDR(left, nrec, cur);
    -		rkp = XFS_INOBT_KEY_ADDR(right, 1, cur);
    -		*lkp = *rkp;
    -		xfs_inobt_log_keys(cur, lbp, nrec, nrec);
    -		lpp = XFS_INOBT_PTR_ADDR(left, nrec, cur);
    -		rpp = XFS_INOBT_PTR_ADDR(right, 1, cur);
    -#ifdef DEBUG
    -		if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(*rpp), level)))
    -			return error;
    -#endif
    -		*lpp = *rpp; /* INT_: no-change copy */
    -		xfs_inobt_log_ptrs(cur, lbp, nrec, nrec);
    -	}
    -	/*
    -	 * If leaf, copy a record to the left block.
    -	 */
    -	else {
    -		lrp = XFS_INOBT_REC_ADDR(left, nrec, cur);
    -		rrp = XFS_INOBT_REC_ADDR(right, 1, cur);
    -		*lrp = *rrp;
    -		xfs_inobt_log_recs(cur, lbp, nrec, nrec);
    -	}
    -	/*
    -	 * Bump and log left's numrecs, decrement and log right's numrecs.
    -	 */
    -	be16_add(&left->bb_numrecs, 1);
    -	xfs_inobt_log_block(cur->bc_tp, lbp, XFS_BB_NUMRECS);
    -#ifdef DEBUG
    -	if (level > 0)
    -		xfs_btree_check_key(cur->bc_btnum, lkp - 1, lkp);
    -	else
    -		xfs_btree_check_rec(cur->bc_btnum, lrp - 1, lrp);
    -#endif
    -	be16_add(&right->bb_numrecs, -1);
    -	xfs_inobt_log_block(cur->bc_tp, rbp, XFS_BB_NUMRECS);
    -	/*
    -	 * Slide the contents of right down one entry.
    -	 */
    -	if (level > 0) {
    -#ifdef DEBUG
    -		for (i = 0; i < be16_to_cpu(right->bb_numrecs); i++) {
    -			if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(rpp[i + 1]),
    -					level)))
    -				return error;
    -		}
    -#endif
    -		memmove(rkp, rkp + 1, be16_to_cpu(right->bb_numrecs) * sizeof(*rkp));
    -		memmove(rpp, rpp + 1, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp));
    -		xfs_inobt_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));
    -		xfs_inobt_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));
    -	} else {
    -		memmove(rrp, rrp + 1, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp));
    -		xfs_inobt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));
    -		key.ir_startino = rrp->ir_startino; /* INT_: direct copy */
    -		rkp = &key;
    -	}
    -	/*
    -	 * Update the parent key values of right.
    -	 */
    -	if ((error = xfs_inobt_updkey(cur, rkp, level + 1)))
    -		return error;
    -	/*
    -	 * Slide the cursor value left one.
    -	 */
    -	cur->bc_ptrs[level]--;
    -	*stat = 1;
    -	return 0;
    -}
    -
    -/*
    - * Allocate a new root block, fill it in.
    - */
    -STATIC int				/* error */
    -xfs_inobt_newroot(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	int			*stat)	/* success/failure */
    -{
    -	xfs_agi_t		*agi;	/* a.g. inode header */
    -	xfs_alloc_arg_t		args;	/* allocation argument structure */
    -	xfs_inobt_block_t	*block;	/* one half of the old root block */
    -	xfs_buf_t		*bp;	/* buffer containing block */
    -	int			error;	/* error return value */
    -	xfs_inobt_key_t		*kp;	/* btree key pointer */
    -	xfs_agblock_t		lbno;	/* left block number */
    -	xfs_buf_t		*lbp;	/* left buffer pointer */
    -	xfs_inobt_block_t	*left;	/* left btree block */
    -	xfs_buf_t		*nbp;	/* new (root) buffer */
    -	xfs_inobt_block_t	*new;	/* new (root) btree block */
    -	int			nptr;	/* new value for key index, 1 or 2 */
    -	xfs_inobt_ptr_t		*pp;	/* btree address pointer */
    -	xfs_agblock_t		rbno;	/* right block number */
    -	xfs_buf_t		*rbp;	/* right buffer pointer */
    -	xfs_inobt_block_t	*right;	/* right btree block */
    -	xfs_inobt_rec_t		*rp;	/* btree record pointer */
    -
    -	ASSERT(cur->bc_nlevels < XFS_IN_MAXLEVELS(cur->bc_mp));
    -
    -	/*
    -	 * Get a block & a buffer.
    -	 */
    -	agi = XFS_BUF_TO_AGI(cur->bc_private.i.agbp);
    -	args.tp = cur->bc_tp;
    -	args.mp = cur->bc_mp;
    -	args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_private.i.agno,
    -		be32_to_cpu(agi->agi_root));
    -	args.mod = args.minleft = args.alignment = args.total = args.wasdel =
    -		args.isfl = args.userdata = args.minalignslop = 0;
    -	args.minlen = args.maxlen = args.prod = 1;
    -	args.type = XFS_ALLOCTYPE_NEAR_BNO;
    -	if ((error = xfs_alloc_vextent(&args)))
    -		return error;
    -	/*
    -	 * None available, we fail.
    -	 */
    -	if (args.fsbno == NULLFSBLOCK) {
    -		*stat = 0;
    -		return 0;
    -	}
    -	ASSERT(args.len == 1);
    -	nbp = xfs_btree_get_bufs(args.mp, args.tp, args.agno, args.agbno, 0);
    -	new = XFS_BUF_TO_INOBT_BLOCK(nbp);
    -	/*
    -	 * Set the root data in the a.g. inode structure.
    -	 */
    -	agi->agi_root = cpu_to_be32(args.agbno);
    -	be32_add(&agi->agi_level, 1);
    -	xfs_ialloc_log_agi(args.tp, cur->bc_private.i.agbp,
    -		XFS_AGI_ROOT | XFS_AGI_LEVEL);
    -	/*
    -	 * At the previous root level there are now two blocks: the old
    -	 * root, and the new block generated when it was split.
    -	 * We don't know which one the cursor is pointing at, so we
    -	 * set up variables "left" and "right" for each case.
    -	 */
    -	bp = cur->bc_bufs[cur->bc_nlevels - 1];
    -	block = XFS_BUF_TO_INOBT_BLOCK(bp);
    -#ifdef DEBUG
    -	if ((error = xfs_btree_check_sblock(cur, block, cur->bc_nlevels - 1, bp)))
    -		return error;
    -#endif
    -	if (be32_to_cpu(block->bb_rightsib) != NULLAGBLOCK) {
    -		/*
    -		 * Our block is left, pick up the right block.
    -		 */
    -		lbp = bp;
    -		lbno = XFS_DADDR_TO_AGBNO(args.mp, XFS_BUF_ADDR(lbp));
    -		left = block;
    -		rbno = be32_to_cpu(left->bb_rightsib);
    -		if ((error = xfs_btree_read_bufs(args.mp, args.tp, args.agno,
    -				rbno, 0, &rbp, XFS_INO_BTREE_REF)))
    -			return error;
    -		bp = rbp;
    -		right = XFS_BUF_TO_INOBT_BLOCK(rbp);
    -		if ((error = xfs_btree_check_sblock(cur, right,
    -				cur->bc_nlevels - 1, rbp)))
    -			return error;
    -		nptr = 1;
    -	} else {
    -		/*
    -		 * Our block is right, pick up the left block.
    -		 */
    -		rbp = bp;
    -		rbno = XFS_DADDR_TO_AGBNO(args.mp, XFS_BUF_ADDR(rbp));
    -		right = block;
    -		lbno = be32_to_cpu(right->bb_leftsib);
    -		if ((error = xfs_btree_read_bufs(args.mp, args.tp, args.agno,
    -				lbno, 0, &lbp, XFS_INO_BTREE_REF)))
    -			return error;
    -		bp = lbp;
    -		left = XFS_BUF_TO_INOBT_BLOCK(lbp);
    -		if ((error = xfs_btree_check_sblock(cur, left,
    -				cur->bc_nlevels - 1, lbp)))
    -			return error;
    -		nptr = 2;
    -	}
    -	/*
    -	 * Fill in the new block's btree header and log it.
    -	 */
    -	new->bb_magic = cpu_to_be32(xfs_magics[cur->bc_btnum]);
    -	new->bb_level = cpu_to_be16(cur->bc_nlevels);
    -	new->bb_numrecs = cpu_to_be16(2);
    -	new->bb_leftsib = cpu_to_be32(NULLAGBLOCK);
    -	new->bb_rightsib = cpu_to_be32(NULLAGBLOCK);
    -	xfs_inobt_log_block(args.tp, nbp, XFS_BB_ALL_BITS);
    -	ASSERT(lbno != NULLAGBLOCK && rbno != NULLAGBLOCK);
    -	/*
    -	 * Fill in the key data in the new root.
    -	 */
    -	kp = XFS_INOBT_KEY_ADDR(new, 1, cur);
    -	if (be16_to_cpu(left->bb_level) > 0) {
    -		kp[0] = *XFS_INOBT_KEY_ADDR(left, 1, cur); /* INT_: struct copy */
    -		kp[1] = *XFS_INOBT_KEY_ADDR(right, 1, cur); /* INT_: struct copy */
    -	} else {
    -		rp = XFS_INOBT_REC_ADDR(left, 1, cur);
    -		INT_COPY(kp[0].ir_startino, rp->ir_startino, ARCH_CONVERT);
    -		rp = XFS_INOBT_REC_ADDR(right, 1, cur);
    -		INT_COPY(kp[1].ir_startino, rp->ir_startino, ARCH_CONVERT);
    -	}
    -	xfs_inobt_log_keys(cur, nbp, 1, 2);
    -	/*
    -	 * Fill in the pointer data in the new root.
    -	 */
    -	pp = XFS_INOBT_PTR_ADDR(new, 1, cur);
    -	pp[0] = cpu_to_be32(lbno);
    -	pp[1] = cpu_to_be32(rbno);
    -	xfs_inobt_log_ptrs(cur, nbp, 1, 2);
    -	/*
    -	 * Fix up the cursor.
    -	 */
    -	xfs_btree_setbuf(cur, cur->bc_nlevels, nbp);
    -	cur->bc_ptrs[cur->bc_nlevels] = nptr;
    -	cur->bc_nlevels++;
    -	*stat = 1;
    -	return 0;
    -}
    -
    -/*
    - * Move 1 record right from cur/level if possible.
    - * Update cur to reflect the new path.
    - */
    -STATIC int				/* error */
    -xfs_inobt_rshift(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	int			level,	/* level to shift record on */
    -	int			*stat)	/* success/failure */
    -{
    -	int			error;	/* error return value */
    -	int			i;	/* loop index */
    -	xfs_inobt_key_t		key;	/* key value for leaf level upward */
    -	xfs_buf_t		*lbp;	/* buffer for left (current) block */
    -	xfs_inobt_block_t	*left;	/* left (current) btree block */
    -	xfs_inobt_key_t		*lkp;	/* key pointer for left block */
    -	xfs_inobt_ptr_t		*lpp;	/* address pointer for left block */
    -	xfs_inobt_rec_t		*lrp;	/* record pointer for left block */
    -	xfs_buf_t		*rbp;	/* buffer for right neighbor block */
    -	xfs_inobt_block_t	*right;	/* right neighbor btree block */
    -	xfs_inobt_key_t		*rkp;	/* key pointer for right block */
    -	xfs_inobt_ptr_t		*rpp;	/* address pointer for right block */
    -	xfs_inobt_rec_t		*rrp=NULL;	/* record pointer for right block */
    -	xfs_btree_cur_t		*tcur;	/* temporary cursor */
    -
    -	/*
    -	 * Set up variables for this block as "left".
    -	 */
    -	lbp = cur->bc_bufs[level];
    -	left = XFS_BUF_TO_INOBT_BLOCK(lbp);
    -#ifdef DEBUG
    -	if ((error = xfs_btree_check_sblock(cur, left, level, lbp)))
    -		return error;
    -#endif
    -	/*
    -	 * If we've got no right sibling then we can't shift an entry right.
    -	 */
    -	if (be32_to_cpu(left->bb_rightsib) == NULLAGBLOCK) {
    -		*stat = 0;
    -		return 0;
    -	}
    -	/*
    -	 * If the cursor entry is the one that would be moved, don't
    -	 * do it... it's too complicated.
    -	 */
    -	if (cur->bc_ptrs[level] >= be16_to_cpu(left->bb_numrecs)) {
    -		*stat = 0;
    -		return 0;
    -	}
    -	/*
    -	 * Set up the right neighbor as "right".
    -	 */
    -	if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp,
    -			cur->bc_private.i.agno, be32_to_cpu(left->bb_rightsib),
    -			0, &rbp, XFS_INO_BTREE_REF)))
    -		return error;
    -	right = XFS_BUF_TO_INOBT_BLOCK(rbp);
    -	if ((error = xfs_btree_check_sblock(cur, right, level, rbp)))
    -		return error;
    -	/*
    -	 * If it's full, it can't take another entry.
    -	 */
    -	if (be16_to_cpu(right->bb_numrecs) == XFS_INOBT_BLOCK_MAXRECS(level, cur)) {
    -		*stat = 0;
    -		return 0;
    -	}
    -	/*
    -	 * Make a hole at the start of the right neighbor block, then
    -	 * copy the last left block entry to the hole.
    -	 */
    -	if (level > 0) {
    -		lkp = XFS_INOBT_KEY_ADDR(left, be16_to_cpu(left->bb_numrecs), cur);
    -		lpp = XFS_INOBT_PTR_ADDR(left, be16_to_cpu(left->bb_numrecs), cur);
    -		rkp = XFS_INOBT_KEY_ADDR(right, 1, cur);
    -		rpp = XFS_INOBT_PTR_ADDR(right, 1, cur);
    -#ifdef DEBUG
    -		for (i = be16_to_cpu(right->bb_numrecs) - 1; i >= 0; i--) {
    -			if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(rpp[i]), level)))
    -				return error;
    -		}
    -#endif
    -		memmove(rkp + 1, rkp, be16_to_cpu(right->bb_numrecs) * sizeof(*rkp));
    -		memmove(rpp + 1, rpp, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp));
    -#ifdef DEBUG
    -		if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(*lpp), level)))
    -			return error;
    -#endif
    -		*rkp = *lkp; /* INT_: no change copy */
    -		*rpp = *lpp; /* INT_: no change copy */
    -		xfs_inobt_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1);
    -		xfs_inobt_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1);
    -	} else {
    -		lrp = XFS_INOBT_REC_ADDR(left, be16_to_cpu(left->bb_numrecs), cur);
    -		rrp = XFS_INOBT_REC_ADDR(right, 1, cur);
    -		memmove(rrp + 1, rrp, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp));
    -		*rrp = *lrp;
    -		xfs_inobt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1);
    -		key.ir_startino = rrp->ir_startino; /* INT_: direct copy */
    -		rkp = &key;
    -	}
    -	/*
    -	 * Decrement and log left's numrecs, bump and log right's numrecs.
    -	 */
    -	be16_add(&left->bb_numrecs, -1);
    -	xfs_inobt_log_block(cur->bc_tp, lbp, XFS_BB_NUMRECS);
    -	be16_add(&right->bb_numrecs, 1);
    -#ifdef DEBUG
    -	if (level > 0)
    -		xfs_btree_check_key(cur->bc_btnum, rkp, rkp + 1);
    -	else
    -		xfs_btree_check_rec(cur->bc_btnum, rrp, rrp + 1);
    -#endif
    -	xfs_inobt_log_block(cur->bc_tp, rbp, XFS_BB_NUMRECS);
    -	/*
    -	 * Using a temporary cursor, update the parent key values of the
    -	 * block on the right.
    -	 */
    -	if ((error = xfs_btree_dup_cursor(cur, &tcur)))
    -		return error;
    -	xfs_btree_lastrec(tcur, level);
    -	if ((error = xfs_inobt_increment(tcur, level, &i)) ||
    -	    (error = xfs_inobt_updkey(tcur, rkp, level + 1))) {
    -		xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR);
    -		return error;
    -	}
    -	xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
    -	*stat = 1;
    -	return 0;
    -}
    -
    -/*
    - * Split cur/level block in half.
    - * Return new block number and its first record (to be inserted into parent).
    - */
    -STATIC int				/* error */
    -xfs_inobt_split(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	int			level,	/* level to split */
    -	xfs_agblock_t		*bnop,	/* output: block number allocated */
    -	xfs_inobt_key_t		*keyp,	/* output: first key of new block */
    -	xfs_btree_cur_t		**curp,	/* output: new cursor */
    -	int			*stat)	/* success/failure */
    -{
    -	xfs_alloc_arg_t		args;	/* allocation argument structure */
    -	int			error;	/* error return value */
    -	int			i;	/* loop index/record number */
    -	xfs_agblock_t		lbno;	/* left (current) block number */
    -	xfs_buf_t		*lbp;	/* buffer for left block */
    -	xfs_inobt_block_t	*left;	/* left (current) btree block */
    -	xfs_inobt_key_t		*lkp;	/* left btree key pointer */
    -	xfs_inobt_ptr_t		*lpp;	/* left btree address pointer */
    -	xfs_inobt_rec_t		*lrp;	/* left btree record pointer */
    -	xfs_buf_t		*rbp;	/* buffer for right block */
    -	xfs_inobt_block_t	*right;	/* right (new) btree block */
    -	xfs_inobt_key_t		*rkp;	/* right btree key pointer */
    -	xfs_inobt_ptr_t		*rpp;	/* right btree address pointer */
    -	xfs_inobt_rec_t		*rrp;	/* right btree record pointer */
    -
    -	/*
    -	 * Set up left block (current one).
    -	 */
    -	lbp = cur->bc_bufs[level];
    -	args.tp = cur->bc_tp;
    -	args.mp = cur->bc_mp;
    -	lbno = XFS_DADDR_TO_AGBNO(args.mp, XFS_BUF_ADDR(lbp));
    -	/*
    -	 * Allocate the new block.
    -	 * If we can't do it, we're toast.  Give up.
    -	 */
    -	args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_private.i.agno, lbno);
    -	args.mod = args.minleft = args.alignment = args.total = args.wasdel =
    -		args.isfl = args.userdata = args.minalignslop = 0;
    -	args.minlen = args.maxlen = args.prod = 1;
    -	args.type = XFS_ALLOCTYPE_NEAR_BNO;
    -	if ((error = xfs_alloc_vextent(&args)))
    -		return error;
    -	if (args.fsbno == NULLFSBLOCK) {
    -		*stat = 0;
    -		return 0;
    -	}
    -	ASSERT(args.len == 1);
    -	rbp = xfs_btree_get_bufs(args.mp, args.tp, args.agno, args.agbno, 0);
    -	/*
    -	 * Set up the new block as "right".
    -	 */
    -	right = XFS_BUF_TO_INOBT_BLOCK(rbp);
    -	/*
    -	 * "Left" is the current (according to the cursor) block.
    -	 */
    -	left = XFS_BUF_TO_INOBT_BLOCK(lbp);
    -#ifdef DEBUG
    -	if ((error = xfs_btree_check_sblock(cur, left, level, lbp)))
    -		return error;
    -#endif
    -	/*
    -	 * Fill in the btree header for the new block.
    -	 */
    -	right->bb_magic = cpu_to_be32(xfs_magics[cur->bc_btnum]);
    -	right->bb_level = left->bb_level;
    -	right->bb_numrecs = cpu_to_be16(be16_to_cpu(left->bb_numrecs) / 2);
    -	/*
    -	 * Make sure that if there's an odd number of entries now, that
    -	 * each new block will have the same number of entries.
    -	 */
    -	if ((be16_to_cpu(left->bb_numrecs) & 1) &&
    -	    cur->bc_ptrs[level] <= be16_to_cpu(right->bb_numrecs) + 1)
    -		be16_add(&right->bb_numrecs, 1);
    -	i = be16_to_cpu(left->bb_numrecs) - be16_to_cpu(right->bb_numrecs) + 1;
    -	/*
    -	 * For non-leaf blocks, copy keys and addresses over to the new block.
    -	 */
    -	if (level > 0) {
    -		lkp = XFS_INOBT_KEY_ADDR(left, i, cur);
    -		lpp = XFS_INOBT_PTR_ADDR(left, i, cur);
    -		rkp = XFS_INOBT_KEY_ADDR(right, 1, cur);
    -		rpp = XFS_INOBT_PTR_ADDR(right, 1, cur);
    -#ifdef DEBUG
    -		for (i = 0; i < be16_to_cpu(right->bb_numrecs); i++) {
    -			if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(lpp[i]), level)))
    -				return error;
    -		}
    -#endif
    -		memcpy(rkp, lkp, be16_to_cpu(right->bb_numrecs) * sizeof(*rkp));
    -		memcpy(rpp, lpp, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp));
    -		xfs_inobt_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));
    -		xfs_inobt_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));
    -		*keyp = *rkp;
    -	}
    -	/*
    -	 * For leaf blocks, copy records over to the new block.
    -	 */
    -	else {
    -		lrp = XFS_INOBT_REC_ADDR(left, i, cur);
    -		rrp = XFS_INOBT_REC_ADDR(right, 1, cur);
    -		memcpy(rrp, lrp, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp));
    -		xfs_inobt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));
    -		keyp->ir_startino = rrp->ir_startino; /* INT_: direct copy */
    -	}
    -	/*
    -	 * Find the left block number by looking in the buffer.
    -	 * Adjust numrecs, sibling pointers.
    -	 */
    -	be16_add(&left->bb_numrecs, -(be16_to_cpu(right->bb_numrecs)));
    -	right->bb_rightsib = left->bb_rightsib;
    -	left->bb_rightsib = cpu_to_be32(args.agbno);
    -	right->bb_leftsib = cpu_to_be32(lbno);
    -	xfs_inobt_log_block(args.tp, rbp, XFS_BB_ALL_BITS);
    -	xfs_inobt_log_block(args.tp, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB);
    -	/*
    -	 * If there's a block to the new block's right, make that block
    -	 * point back to right instead of to left.
    -	 */
    -	if (be32_to_cpu(right->bb_rightsib) != NULLAGBLOCK) {
    -		xfs_inobt_block_t	*rrblock;	/* rr btree block */
    -		xfs_buf_t		*rrbp;		/* buffer for rrblock */
    -
    -		if ((error = xfs_btree_read_bufs(args.mp, args.tp, args.agno,
    -				be32_to_cpu(right->bb_rightsib), 0, &rrbp,
    -				XFS_INO_BTREE_REF)))
    -			return error;
    -		rrblock = XFS_BUF_TO_INOBT_BLOCK(rrbp);
    -		if ((error = xfs_btree_check_sblock(cur, rrblock, level, rrbp)))
    -			return error;
    -		rrblock->bb_leftsib = cpu_to_be32(args.agbno);
    -		xfs_inobt_log_block(args.tp, rrbp, XFS_BB_LEFTSIB);
    -	}
    -	/*
    -	 * If the cursor is really in the right block, move it there.
    -	 * If it's just pointing past the last entry in left, then we'll
    -	 * insert there, so don't change anything in that case.
    -	 */
    -	if (cur->bc_ptrs[level] > be16_to_cpu(left->bb_numrecs) + 1) {
    -		xfs_btree_setbuf(cur, level, rbp);
    -		cur->bc_ptrs[level] -= be16_to_cpu(left->bb_numrecs);
    -	}
    -	/*
    -	 * If there are more levels, we'll need another cursor which refers
    -	 * the right block, no matter where this cursor was.
    -	 */
    -	if (level + 1 < cur->bc_nlevels) {
    -		if ((error = xfs_btree_dup_cursor(cur, curp)))
    -			return error;
    -		(*curp)->bc_ptrs[level + 1]++;
    -	}
    -	*bnop = args.agbno;
    -	*stat = 1;
    -	return 0;
    -}
    -
    -/*
    - * Update keys at all levels from here to the root along the cursor's path.
    - */
    -STATIC int				/* error */
    -xfs_inobt_updkey(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	xfs_inobt_key_t		*keyp,	/* new key value to update to */
    -	int			level)	/* starting level for update */
    -{
    -	int			ptr;	/* index of key in block */
    -
    -	/*
    -	 * Go up the tree from this level toward the root.
    -	 * At each level, update the key value to the value input.
    -	 * Stop when we reach a level where the cursor isn't pointing
    -	 * at the first entry in the block.
    -	 */
    -	for (ptr = 1; ptr == 1 && level < cur->bc_nlevels; level++) {
    -		xfs_buf_t		*bp;	/* buffer for block */
    -		xfs_inobt_block_t	*block;	/* btree block */
    -#ifdef DEBUG
    -		int			error;	/* error return value */
    -#endif
    -		xfs_inobt_key_t		*kp;	/* ptr to btree block keys */
    -
    -		bp = cur->bc_bufs[level];
    -		block = XFS_BUF_TO_INOBT_BLOCK(bp);
    -#ifdef DEBUG
    -		if ((error = xfs_btree_check_sblock(cur, block, level, bp)))
    -			return error;
    -#endif
    -		ptr = cur->bc_ptrs[level];
    -		kp = XFS_INOBT_KEY_ADDR(block, ptr, cur);
    -		*kp = *keyp;
    -		xfs_inobt_log_keys(cur, bp, ptr, ptr);
    -	}
    -	return 0;
    -}
    -
    -/*
    - * Externally visible routines.
    - */
    -
    -/*
    - * Decrement cursor by one record at the level.
    - * For nonzero levels the leaf-ward information is untouched.
    - */
    -int					/* error */
    -xfs_inobt_decrement(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	int			level,	/* level in btree, 0 is leaf */
    -	int			*stat)	/* success/failure */
    -{
    -	xfs_inobt_block_t	*block;	/* btree block */
    -	int			error;
    -	int			lev;	/* btree level */
    -
    -	ASSERT(level < cur->bc_nlevels);
    -	/*
    -	 * Read-ahead to the left at this level.
    -	 */
    -	xfs_btree_readahead(cur, level, XFS_BTCUR_LEFTRA);
    -	/*
    -	 * Decrement the ptr at this level.  If we're still in the block
    -	 * then we're done.
    -	 */
    -	if (--cur->bc_ptrs[level] > 0) {
    -		*stat = 1;
    -		return 0;
    -	}
    -	/*
    -	 * Get a pointer to the btree block.
    -	 */
    -	block = XFS_BUF_TO_INOBT_BLOCK(cur->bc_bufs[level]);
    -#ifdef DEBUG
    -	if ((error = xfs_btree_check_sblock(cur, block, level,
    -			cur->bc_bufs[level])))
    -		return error;
    -#endif
    -	/*
    -	 * If we just went off the left edge of the tree, return failure.
    -	 */
    -	if (be32_to_cpu(block->bb_leftsib) == NULLAGBLOCK) {
    -		*stat = 0;
    -		return 0;
    -	}
    -	/*
    -	 * March up the tree decrementing pointers.
    -	 * Stop when we don't go off the left edge of a block.
    -	 */
    -	for (lev = level + 1; lev < cur->bc_nlevels; lev++) {
    -		if (--cur->bc_ptrs[lev] > 0)
    -			break;
    -		/*
    -		 * Read-ahead the left block, we're going to read it
    -		 * in the next loop.
    -		 */
    -		xfs_btree_readahead(cur, lev, XFS_BTCUR_LEFTRA);
    -	}
    -	/*
    -	 * If we went off the root then we are seriously confused.
    -	 */
    -	ASSERT(lev < cur->bc_nlevels);
    -	/*
    -	 * Now walk back down the tree, fixing up the cursor's buffer
    -	 * pointers and key numbers.
    -	 */
    -	for (block = XFS_BUF_TO_INOBT_BLOCK(cur->bc_bufs[lev]); lev > level; ) {
    -		xfs_agblock_t	agbno;	/* block number of btree block */
    -		xfs_buf_t	*bp;	/* buffer containing btree block */
    -
    -		agbno = be32_to_cpu(*XFS_INOBT_PTR_ADDR(block, cur->bc_ptrs[lev], cur));
    -		if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp,
    -				cur->bc_private.i.agno, agbno, 0, &bp,
    -				XFS_INO_BTREE_REF)))
    -			return error;
    -		lev--;
    -		xfs_btree_setbuf(cur, lev, bp);
    -		block = XFS_BUF_TO_INOBT_BLOCK(bp);
    -		if ((error = xfs_btree_check_sblock(cur, block, lev, bp)))
    -			return error;
    -		cur->bc_ptrs[lev] = be16_to_cpu(block->bb_numrecs);
    -	}
    -	*stat = 1;
    -	return 0;
    -}
    -
    -/*
    - * Delete the record pointed to by cur.
    - * The cursor refers to the place where the record was (could be inserted)
    - * when the operation returns.
    - */
    -int					/* error */
    -xfs_inobt_delete(
    -	xfs_btree_cur_t	*cur,		/* btree cursor */
    -	int		*stat)		/* success/failure */
    -{
    -	int		error;
    -	int		i;		/* result code */
    -	int		level;		/* btree level */
    -
    -	/*
    -	 * Go up the tree, starting at leaf level.
    -	 * If 2 is returned then a join was done; go to the next level.
    -	 * Otherwise we are done.
    -	 */
    -	for (level = 0, i = 2; i == 2; level++) {
    -		if ((error = xfs_inobt_delrec(cur, level, &i)))
    -			return error;
    -	}
    -	if (i == 0) {
    -		for (level = 1; level < cur->bc_nlevels; level++) {
    -			if (cur->bc_ptrs[level] == 0) {
    -				if ((error = xfs_inobt_decrement(cur, level, &i)))
    -					return error;
    -				break;
    -			}
    -		}
    -	}
    -	*stat = i;
    -	return 0;
    -}
    -
    -
    -/*
    - * Get the data from the pointed-to record.
    - */
    -int					/* error */
    -xfs_inobt_get_rec(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	xfs_agino_t		*ino,	/* output: starting inode of chunk */
    -	__int32_t		*fcnt,	/* output: number of free inodes */
    -	xfs_inofree_t		*free,	/* output: free inode mask */
    -	int			*stat)	/* output: success/failure */
    -{
    -	xfs_inobt_block_t	*block;	/* btree block */
    -	xfs_buf_t		*bp;	/* buffer containing btree block */
    -#ifdef DEBUG
    -	int			error;	/* error return value */
    -#endif
    -	int			ptr;	/* record number */
    -	xfs_inobt_rec_t		*rec;	/* record data */
    -
    -	bp = cur->bc_bufs[0];
    -	ptr = cur->bc_ptrs[0];
    -	block = XFS_BUF_TO_INOBT_BLOCK(bp);
    -#ifdef DEBUG
    -	if ((error = xfs_btree_check_sblock(cur, block, 0, bp)))
    -		return error;
    -#endif
    -	/*
    -	 * Off the right end or left end, return failure.
    -	 */
    -	if (ptr > be16_to_cpu(block->bb_numrecs) || ptr <= 0) {
    -		*stat = 0;
    -		return 0;
    -	}
    -	/*
    -	 * Point to the record and extract its data.
    -	 */
    -	rec = XFS_INOBT_REC_ADDR(block, ptr, cur);
    -	*ino = INT_GET(rec->ir_startino, ARCH_CONVERT);
    -	*fcnt = INT_GET(rec->ir_freecount, ARCH_CONVERT);
    -	*free = INT_GET(rec->ir_free, ARCH_CONVERT);
    -	*stat = 1;
    -	return 0;
    -}
    -
    -/*
    - * Increment cursor by one record at the level.
    - * For nonzero levels the leaf-ward information is untouched.
    - */
    -int					/* error */
    -xfs_inobt_increment(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	int			level,	/* level in btree, 0 is leaf */
    -	int			*stat)	/* success/failure */
    -{
    -	xfs_inobt_block_t	*block;	/* btree block */
    -	xfs_buf_t		*bp;	/* buffer containing btree block */
    -	int			error;	/* error return value */
    -	int			lev;	/* btree level */
    -
    -	ASSERT(level < cur->bc_nlevels);
    -	/*
    -	 * Read-ahead to the right at this level.
    -	 */
    -	xfs_btree_readahead(cur, level, XFS_BTCUR_RIGHTRA);
    -	/*
    -	 * Get a pointer to the btree block.
    -	 */
    -	bp = cur->bc_bufs[level];
    -	block = XFS_BUF_TO_INOBT_BLOCK(bp);
    -#ifdef DEBUG
    -	if ((error = xfs_btree_check_sblock(cur, block, level, bp)))
    -		return error;
    -#endif
    -	/*
    -	 * Increment the ptr at this level.  If we're still in the block
    -	 * then we're done.
    -	 */
    -	if (++cur->bc_ptrs[level] <= be16_to_cpu(block->bb_numrecs)) {
    -		*stat = 1;
    -		return 0;
    -	}
    -	/*
    -	 * If we just went off the right edge of the tree, return failure.
    -	 */
    -	if (be32_to_cpu(block->bb_rightsib) == NULLAGBLOCK) {
    -		*stat = 0;
    -		return 0;
    -	}
    -	/*
    -	 * March up the tree incrementing pointers.
    -	 * Stop when we don't go off the right edge of a block.
    -	 */
    -	for (lev = level + 1; lev < cur->bc_nlevels; lev++) {
    -		bp = cur->bc_bufs[lev];
    -		block = XFS_BUF_TO_INOBT_BLOCK(bp);
    -#ifdef DEBUG
    -		if ((error = xfs_btree_check_sblock(cur, block, lev, bp)))
    -			return error;
    -#endif
    -		if (++cur->bc_ptrs[lev] <= be16_to_cpu(block->bb_numrecs))
    -			break;
    -		/*
    -		 * Read-ahead the right block, we're going to read it
    -		 * in the next loop.
    -		 */
    -		xfs_btree_readahead(cur, lev, XFS_BTCUR_RIGHTRA);
    -	}
    -	/*
    -	 * If we went off the root then we are seriously confused.
    -	 */
    -	ASSERT(lev < cur->bc_nlevels);
    -	/*
    -	 * Now walk back down the tree, fixing up the cursor's buffer
    -	 * pointers and key numbers.
    -	 */
    -	for (bp = cur->bc_bufs[lev], block = XFS_BUF_TO_INOBT_BLOCK(bp);
    -	     lev > level; ) {
    -		xfs_agblock_t	agbno;	/* block number of btree block */
    -
    -		agbno = be32_to_cpu(*XFS_INOBT_PTR_ADDR(block, cur->bc_ptrs[lev], cur));
    -		if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp,
    -				cur->bc_private.i.agno, agbno, 0, &bp,
    -				XFS_INO_BTREE_REF)))
    -			return error;
    -		lev--;
    -		xfs_btree_setbuf(cur, lev, bp);
    -		block = XFS_BUF_TO_INOBT_BLOCK(bp);
    -		if ((error = xfs_btree_check_sblock(cur, block, lev, bp)))
    -			return error;
    -		cur->bc_ptrs[lev] = 1;
    -	}
    -	*stat = 1;
    -	return 0;
    -}
    -
    -/*
    - * Insert the current record at the point referenced by cur.
    - * The cursor may be inconsistent on return if splits have been done.
    - */
    -int					/* error */
    -xfs_inobt_insert(
    -	xfs_btree_cur_t	*cur,		/* btree cursor */
    -	int		*stat)		/* success/failure */
    -{
    -	int		error;		/* error return value */
    -	int		i;		/* result value, 0 for failure */
    -	int		level;		/* current level number in btree */
    -	xfs_agblock_t	nbno;		/* new block number (split result) */
    -	xfs_btree_cur_t	*ncur;		/* new cursor (split result) */
    -	xfs_inobt_rec_t	nrec;		/* record being inserted this level */
    -	xfs_btree_cur_t	*pcur;		/* previous level's cursor */
    -
    -	level = 0;
    -	nbno = NULLAGBLOCK;
    -	INT_SET(nrec.ir_startino, ARCH_CONVERT, cur->bc_rec.i.ir_startino);
    -	INT_SET(nrec.ir_freecount, ARCH_CONVERT, cur->bc_rec.i.ir_freecount);
    -	INT_SET(nrec.ir_free, ARCH_CONVERT, cur->bc_rec.i.ir_free);
    -	ncur = (xfs_btree_cur_t *)0;
    -	pcur = cur;
    -	/*
    -	 * Loop going up the tree, starting at the leaf level.
    -	 * Stop when we don't get a split block, that must mean that
    -	 * the insert is finished with this level.
    -	 */
    -	do {
    -		/*
    -		 * Insert nrec/nbno into this level of the tree.
    -		 * Note if we fail, nbno will be null.
    -		 */
    -		if ((error = xfs_inobt_insrec(pcur, level++, &nbno, &nrec, &ncur,
    -				&i))) {
    -			if (pcur != cur)
    -				xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR);
    -			return error;
    -		}
    -		/*
    -		 * See if the cursor we just used is trash.
    -		 * Can't trash the caller's cursor, but otherwise we should
    -		 * if ncur is a new cursor or we're about to be done.
    -		 */
    -		if (pcur != cur && (ncur || nbno == NULLAGBLOCK)) {
    -			cur->bc_nlevels = pcur->bc_nlevels;
    -			xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR);
    -		}
    -		/*
    -		 * If we got a new cursor, switch to it.
    -		 */
    -		if (ncur) {
    -			pcur = ncur;
    -			ncur = (xfs_btree_cur_t *)0;
    -		}
    -	} while (nbno != NULLAGBLOCK);
    -	*stat = i;
    -	return 0;
    -}
    -
    -/*
    - * Lookup the record equal to ino in the btree given by cur.
    - */
    -int					/* error */
    -xfs_inobt_lookup_eq(
    -	xfs_btree_cur_t	*cur,		/* btree cursor */
    -	xfs_agino_t	ino,		/* starting inode of chunk */
    -	__int32_t	fcnt,		/* free inode count */
    -	xfs_inofree_t	free,		/* free inode mask */
    -	int		*stat)		/* success/failure */
    -{
    -	cur->bc_rec.i.ir_startino = ino;
    -	cur->bc_rec.i.ir_freecount = fcnt;
    -	cur->bc_rec.i.ir_free = free;
    -	return xfs_inobt_lookup(cur, XFS_LOOKUP_EQ, stat);
    -}
    -
    -/*
    - * Lookup the first record greater than or equal to ino
    - * in the btree given by cur.
    - */
    -int					/* error */
    -xfs_inobt_lookup_ge(
    -	xfs_btree_cur_t	*cur,		/* btree cursor */
    -	xfs_agino_t	ino,		/* starting inode of chunk */
    -	__int32_t	fcnt,		/* free inode count */
    -	xfs_inofree_t	free,		/* free inode mask */
    -	int		*stat)		/* success/failure */
    -{
    -	cur->bc_rec.i.ir_startino = ino;
    -	cur->bc_rec.i.ir_freecount = fcnt;
    -	cur->bc_rec.i.ir_free = free;
    -	return xfs_inobt_lookup(cur, XFS_LOOKUP_GE, stat);
    -}
    -
    -/*
    - * Lookup the first record less than or equal to ino
    - * in the btree given by cur.
    - */
    -int					/* error */
    -xfs_inobt_lookup_le(
    -	xfs_btree_cur_t	*cur,		/* btree cursor */
    -	xfs_agino_t	ino,		/* starting inode of chunk */
    -	__int32_t	fcnt,		/* free inode count */
    -	xfs_inofree_t	free,		/* free inode mask */
    -	int		*stat)		/* success/failure */
    -{
    -	cur->bc_rec.i.ir_startino = ino;
    -	cur->bc_rec.i.ir_freecount = fcnt;
    -	cur->bc_rec.i.ir_free = free;
    -	return xfs_inobt_lookup(cur, XFS_LOOKUP_LE, stat);
    -}
    -
    -/*
    - * Update the record referred to by cur, to the value given
    - * by [ino, fcnt, free].
    - * This either works (return 0) or gets an EFSCORRUPTED error.
    - */
    -int					/* error */
    -xfs_inobt_update(
    -	xfs_btree_cur_t		*cur,	/* btree cursor */
    -	xfs_agino_t		ino,	/* starting inode of chunk */
    -	__int32_t		fcnt,	/* free inode count */
    -	xfs_inofree_t		free)	/* free inode mask */
    -{
    -	xfs_inobt_block_t	*block;	/* btree block to update */
    -	xfs_buf_t		*bp;	/* buffer containing btree block */
    -	int			error;	/* error return value */
    -	int			ptr;	/* current record number (updating) */
    -	xfs_inobt_rec_t		*rp;	/* pointer to updated record */
    -
    -	/*
    -	 * Pick up the current block.
    -	 */
    -	bp = cur->bc_bufs[0];
    -	block = XFS_BUF_TO_INOBT_BLOCK(bp);
    -#ifdef DEBUG
    -	if ((error = xfs_btree_check_sblock(cur, block, 0, bp)))
    -		return error;
    -#endif
    -	/*
    -	 * Get the address of the rec to be updated.
    -	 */
    -	ptr = cur->bc_ptrs[0];
    -	rp = XFS_INOBT_REC_ADDR(block, ptr, cur);
    -	/*
    -	 * Fill in the new contents and log them.
    -	 */
    -	INT_SET(rp->ir_startino, ARCH_CONVERT, ino);
    -	INT_SET(rp->ir_freecount, ARCH_CONVERT, fcnt);
    -	INT_SET(rp->ir_free, ARCH_CONVERT, free);
    -	xfs_inobt_log_recs(cur, bp, ptr, ptr);
    -	/*
    -	 * Updating first record in leaf. Pass new key value up to our parent.
    -	 */
    -	if (ptr == 1) {
    -		xfs_inobt_key_t	key;	/* key containing [ino] */
    -
    -		INT_SET(key.ir_startino, ARCH_CONVERT, ino);
    -		if ((error = xfs_inobt_updkey(cur, &key, 1)))
    -			return error;
    -	}
    -	return 0;
    -}
    diff --git a/sys/gnu/fs/xfs/xfs_ialloc_btree.h b/sys/gnu/fs/xfs/xfs_ialloc_btree.h
    deleted file mode 100644
    index ae3904cb1ee..00000000000
    --- a/sys/gnu/fs/xfs/xfs_ialloc_btree.h
    +++ /dev/null
    @@ -1,177 +0,0 @@
    -/*
    - * Copyright (c) 2000,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_IALLOC_BTREE_H__
    -#define	__XFS_IALLOC_BTREE_H__
    -
    -/*
    - * Inode map on-disk structures
    - */
    -
    -struct xfs_buf;
    -struct xfs_btree_cur;
    -struct xfs_btree_sblock;
    -struct xfs_mount;
    -
    -/*
    - * There is a btree for the inode map per allocation group.
    - */
    -#define	XFS_IBT_MAGIC	0x49414254	/* 'IABT' */
    -
    -typedef	__uint64_t	xfs_inofree_t;
    -#define	XFS_INODES_PER_CHUNK	(NBBY * sizeof(xfs_inofree_t))
    -#define	XFS_INODES_PER_CHUNK_LOG	(XFS_NBBYLOG + 3)
    -#define	XFS_INOBT_ALL_FREE	((xfs_inofree_t)-1)
    -
    -#define	XFS_INOBT_MASKN(i,n)		xfs_inobt_maskn(i,n)
    -static inline xfs_inofree_t xfs_inobt_maskn(int i, int n)
    -{
    -	return (((n) >= XFS_INODES_PER_CHUNK ? \
    -		(xfs_inofree_t)0 : ((xfs_inofree_t)1 << (n))) - 1) << (i);
    -}
    -
    -/*
    - * Data record structure
    - */
    -typedef struct xfs_inobt_rec
    -{
    -	xfs_agino_t	ir_startino;	/* starting inode number */
    -	__int32_t	ir_freecount;	/* count of free inodes (set bits) */
    -	xfs_inofree_t	ir_free;	/* free inode mask */
    -} xfs_inobt_rec_t;
    -
    -/*
    - * Key structure
    - */
    -typedef struct xfs_inobt_key
    -{
    -	xfs_agino_t	ir_startino;	/* starting inode number */
    -} xfs_inobt_key_t;
    -
    -/* btree pointer type */
    -typedef __be32 xfs_inobt_ptr_t;
    -
    -/* btree block header type */
    -typedef	struct xfs_btree_sblock xfs_inobt_block_t;
    -
    -#define	XFS_BUF_TO_INOBT_BLOCK(bp)	((xfs_inobt_block_t *)XFS_BUF_PTR(bp))
    -
    -/*
    - * Bit manipulations for ir_free.
    - */
    -#define	XFS_INOBT_MASK(i)		((xfs_inofree_t)1 << (i))
    -#define	XFS_INOBT_IS_FREE(rp,i)		\
    -		(((rp)->ir_free & XFS_INOBT_MASK(i)) != 0)
    -#define	XFS_INOBT_IS_FREE_DISK(rp,i)	\
    -		((INT_GET((rp)->ir_free,ARCH_CONVERT) & XFS_INOBT_MASK(i)) != 0)
    -#define	XFS_INOBT_SET_FREE(rp,i)	((rp)->ir_free |= XFS_INOBT_MASK(i))
    -#define	XFS_INOBT_CLR_FREE(rp,i)	((rp)->ir_free &= ~XFS_INOBT_MASK(i))
    -
    -/*
    - * Real block structures have a size equal to the disk block size.
    - */
    -#define	XFS_INOBT_BLOCK_SIZE(lev,cur)	(1 << (cur)->bc_blocklog)
    -#define	XFS_INOBT_BLOCK_MAXRECS(lev,cur) ((cur)->bc_mp->m_inobt_mxr[lev != 0])
    -#define	XFS_INOBT_BLOCK_MINRECS(lev,cur) ((cur)->bc_mp->m_inobt_mnr[lev != 0])
    -#define	XFS_INOBT_IS_LAST_REC(cur)	\
    -	((cur)->bc_ptrs[0] == be16_to_cpu(XFS_BUF_TO_INOBT_BLOCK((cur)->bc_bufs[0])->bb_numrecs))
    -
    -/*
    - * Maximum number of inode btree levels.
    - */
    -#define	XFS_IN_MAXLEVELS(mp)		((mp)->m_in_maxlevels)
    -
    -/*
    - * block numbers in the AG.
    - */
    -#define	XFS_IBT_BLOCK(mp)		((xfs_agblock_t)(XFS_CNT_BLOCK(mp) + 1))
    -#define	XFS_PREALLOC_BLOCKS(mp)		((xfs_agblock_t)(XFS_IBT_BLOCK(mp) + 1))
    -
    -/*
    - * Record, key, and pointer address macros for btree blocks.
    - */
    -#define XFS_INOBT_REC_ADDR(bb,i,cur) \
    -	(XFS_BTREE_REC_ADDR(XFS_INOBT_BLOCK_SIZE(0,cur), xfs_inobt, bb, \
    -				i, XFS_INOBT_BLOCK_MAXRECS(0, cur)))
    -#define	XFS_INOBT_KEY_ADDR(bb,i,cur) \
    -	(XFS_BTREE_KEY_ADDR(XFS_INOBT_BLOCK_SIZE(1,cur), xfs_inobt, bb, \
    -				i, XFS_INOBT_BLOCK_MAXRECS(1, cur)))
    -
    -#define	XFS_INOBT_PTR_ADDR(bb,i,cur) \
    -	(XFS_BTREE_PTR_ADDR(XFS_INOBT_BLOCK_SIZE(1,cur), xfs_inobt, bb, \
    -				i, XFS_INOBT_BLOCK_MAXRECS(1, cur)))
    -
    -/*
    - * Decrement cursor by one record at the level.
    - * For nonzero levels the leaf-ward information is untouched.
    - */
    -extern int xfs_inobt_decrement(struct xfs_btree_cur *cur, int level, int *stat);
    -
    -/*
    - * Delete the record pointed to by cur.
    - * The cursor refers to the place where the record was (could be inserted)
    - * when the operation returns.
    - */
    -extern int xfs_inobt_delete(struct xfs_btree_cur *cur, int *stat);
    -
    -/*
    - * Get the data from the pointed-to record.
    - */
    -extern int xfs_inobt_get_rec(struct xfs_btree_cur *cur, xfs_agino_t *ino,
    -			     __int32_t *fcnt, xfs_inofree_t *free, int *stat);
    -
    -/*
    - * Increment cursor by one record at the level.
    - * For nonzero levels the leaf-ward information is untouched.
    - */
    -extern int xfs_inobt_increment(struct xfs_btree_cur *cur, int level, int *stat);
    -
    -/*
    - * Insert the current record at the point referenced by cur.
    - * The cursor may be inconsistent on return if splits have been done.
    - */
    -extern int xfs_inobt_insert(struct xfs_btree_cur *cur, int *stat);
    -
    -/*
    - * Lookup the record equal to ino in the btree given by cur.
    - */
    -extern int xfs_inobt_lookup_eq(struct xfs_btree_cur *cur, xfs_agino_t ino,
    -				__int32_t fcnt, xfs_inofree_t free, int *stat);
    -
    -/*
    - * Lookup the first record greater than or equal to ino
    - * in the btree given by cur.
    - */
    -extern int xfs_inobt_lookup_ge(struct xfs_btree_cur *cur, xfs_agino_t ino,
    -				__int32_t fcnt,	xfs_inofree_t free, int *stat);
    -
    -/*
    - * Lookup the first record less than or equal to ino
    - * in the btree given by cur.
    - */
    -extern int xfs_inobt_lookup_le(struct xfs_btree_cur *cur, xfs_agino_t ino,
    -				__int32_t fcnt,	xfs_inofree_t free, int *stat);
    -
    -/*
    - * Update the record referred to by cur, to the value given
    - * by [ino, fcnt, free].
    - * This either works (return 0) or gets an EFSCORRUPTED error.
    - */
    -extern int xfs_inobt_update(struct xfs_btree_cur *cur, xfs_agino_t ino,
    -				__int32_t fcnt, xfs_inofree_t free);
    -
    -#endif	/* __XFS_IALLOC_BTREE_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_iget.c b/sys/gnu/fs/xfs/xfs_iget.c
    deleted file mode 100644
    index 7b5803c5980..00000000000
    --- a/sys/gnu/fs/xfs/xfs_iget.c
    +++ /dev/null
    @@ -1,1052 +0,0 @@
    -/*
    - * Copyright (c) 2000-2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_btree.h"
    -#include "xfs_ialloc.h"
    -#include "xfs_quota.h"
    -#include "xfs_utils.h"
    -
    -/*
    - * Initialize the inode hash table for the newly mounted file system.
    - * Choose an initial table size based on user specified value, else
    - * use a simple algorithm using the maximum number of inodes as an
    - * indicator for table size, and clamp it between one and some large
    - * number of pages.
    - */
    -void
    -xfs_ihash_init(xfs_mount_t *mp)
    -{
    -	__uint64_t	icount;
    -	uint		i, flags = KM_SLEEP | KM_MAYFAIL;
    -
    -	if (!mp->m_ihsize) {
    -		icount = mp->m_maxicount ? mp->m_maxicount :
    -			 (mp->m_sb.sb_dblocks << mp->m_sb.sb_inopblog);
    -		mp->m_ihsize = 1 << max_t(uint, 8,
    -					(xfs_highbit64(icount) + 1) / 2);
    -		mp->m_ihsize = min_t(uint, mp->m_ihsize,
    -					(64 * NBPP) / sizeof(xfs_ihash_t));
    -	}
    -
    -	while (!(mp->m_ihash = (xfs_ihash_t *)kmem_zalloc(mp->m_ihsize *
    -						sizeof(xfs_ihash_t), flags))) {
    -		if ((mp->m_ihsize >>= 1) <= NBPP)
    -			flags = KM_SLEEP;
    -	}
    -	for (i = 0; i < mp->m_ihsize; i++) {
    -		rwlock_init(&(mp->m_ihash[i].ih_lock));
    -	}
    -}
    -
    -/*
    - * Free up structures allocated by xfs_ihash_init, at unmount time.
    - */
    -void
    -xfs_ihash_free(xfs_mount_t *mp)
    -{
    -	kmem_free(mp->m_ihash, mp->m_ihsize*sizeof(xfs_ihash_t));
    -	mp->m_ihash = NULL;
    -}
    -
    -/*
    - * Initialize the inode cluster hash table for the newly mounted file system.
    - * Its size is derived from the ihash table size.
    - */
    -void
    -xfs_chash_init(xfs_mount_t *mp)
    -{
    -	uint	i;
    -
    -	mp->m_chsize = max_t(uint, 1, mp->m_ihsize /
    -			 (XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog));
    -	mp->m_chsize = min_t(uint, mp->m_chsize, mp->m_ihsize);
    -	mp->m_chash = (xfs_chash_t *)kmem_zalloc(mp->m_chsize
    -						 * sizeof(xfs_chash_t),
    -						 KM_SLEEP);
    -	for (i = 0; i < mp->m_chsize; i++) {
    -		spinlock_init(&mp->m_chash[i].ch_lock,"xfshash");
    -	}
    -}
    -
    -/*
    - * Free up structures allocated by xfs_chash_init, at unmount time.
    - */
    -void
    -xfs_chash_free(xfs_mount_t *mp)
    -{
    -	int	i;
    -
    -	for (i = 0; i < mp->m_chsize; i++) {
    -		spinlock_destroy(&mp->m_chash[i].ch_lock);
    -	}
    -
    -	kmem_free(mp->m_chash, mp->m_chsize*sizeof(xfs_chash_t));
    -	mp->m_chash = NULL;
    -}
    -
    -/*
    - * Try to move an inode to the front of its hash list if possible
    - * (and if its not there already).  Called right after obtaining
    - * the list version number and then dropping the read_lock on the
    - * hash list in question (which is done right after looking up the
    - * inode in question...).
    - */
    -STATIC void
    -xfs_ihash_promote(
    -	xfs_ihash_t	*ih,
    -	xfs_inode_t	*ip,
    -	ulong		version)
    -{
    -	xfs_inode_t	*iq;
    -
    -	if ((ip->i_prevp != &ih->ih_next) && write_trylock(&ih->ih_lock)) {
    -		if (likely(version == ih->ih_version)) {
    -			/* remove from list */
    -			if ((iq = ip->i_next)) {
    -				iq->i_prevp = ip->i_prevp;
    -			}
    -			*ip->i_prevp = iq;
    -
    -			/* insert at list head */
    -			iq = ih->ih_next;
    -			iq->i_prevp = &ip->i_next;
    -			ip->i_next = iq;
    -			ip->i_prevp = &ih->ih_next;
    -			ih->ih_next = ip;
    -		}
    -		write_unlock(&ih->ih_lock);
    -	}
    -}
    -
    -/*
    - * Look up an inode by number in the given file system.
    - * The inode is looked up in the hash table for the file system
    - * represented by the mount point parameter mp.  Each bucket of
    - * the hash table is guarded by an individual semaphore.
    - *
    - * If the inode is found in the hash table, its corresponding vnode
    - * is obtained with a call to vn_get().  This call takes care of
    - * coordination with the reclamation of the inode and vnode.  Note
    - * that the vmap structure is filled in while holding the hash lock.
    - * This gives us the state of the inode/vnode when we found it and
    - * is used for coordination in vn_get().
    - *
    - * If it is not in core, read it in from the file system's device and
    - * add the inode into the hash table.
    - *
    - * The inode is locked according to the value of the lock_flags parameter.
    - * This flag parameter indicates how and if the inode's IO lock and inode lock
    - * should be taken.
    - *
    - * mp -- the mount point structure for the current file system.  It points
    - *       to the inode hash table.
    - * tp -- a pointer to the current transaction if there is one.  This is
    - *       simply passed through to the xfs_iread() call.
    - * ino -- the number of the inode desired.  This is the unique identifier
    - *        within the file system for the inode being requested.
    - * lock_flags -- flags indicating how to lock the inode.  See the comment
    - *		 for xfs_ilock() for a list of valid values.
    - * bno -- the block number starting the buffer containing the inode,
    - *	  if known (as by bulkstat), else 0.
    - */
    -#ifdef RMC
    -STATIC int
    -xfs_iget_core(
    -	xfs_vnode_t	*vp,
    -	xfs_mount_t	*mp,
    -	xfs_trans_t	*tp,
    -	xfs_ino_t	ino,
    -	uint		flags,
    -	uint		lock_flags,
    -	xfs_inode_t	**ipp,
    -	xfs_daddr_t	bno)
    -{
    -	xfs_ihash_t	*ih;
    -	xfs_inode_t	*ip;
    -	xfs_inode_t	*iq;
    -	xfs_vnode_t	*inode_vp;
    -	ulong		version;
    -	int		error;
    -	/* REFERENCED */
    -	xfs_chash_t	*ch;
    -	xfs_chashlist_t	*chl, *chlnew;
    -	SPLDECL(s);
    -
    -
    -	ih = XFS_IHASH(mp, ino);
    -
    -again:
    -	read_lock(&ih->ih_lock);
    -
    -	for (ip = ih->ih_next; ip != NULL; ip = ip->i_next) {
    -		if (ip->i_ino == ino) {
    -			/*
    -			 * If INEW is set this inode is being set up
    -			 * we need to pause and try again.
    -			 */
    -			if (ip->i_flags & XFS_INEW) {
    -				read_unlock(&ih->ih_lock);
    -				delay(1);
    -				XFS_STATS_INC(xs_ig_frecycle);
    -
    -				goto again;
    -			}
    -
    -			inode_vp = XFS_ITOV_NULL(ip);
    -			if (inode_vp == NULL) {
    -				/*
    -				 * If IRECLAIM is set this inode is
    -				 * on its way out of the system,
    -				 * we need to pause and try again.
    -				 */
    -				if (ip->i_flags & XFS_IRECLAIM) {
    -					read_unlock(&ih->ih_lock);
    -					delay(1);
    -					XFS_STATS_INC(xs_ig_frecycle);
    -
    -					goto again;
    -				}
    -
    -				vn_trace_exit(vp, "xfs_iget.alloc",
    -					(inst_t *)__return_address);
    -
    -				XFS_STATS_INC(xs_ig_found);
    -
    -				ip->i_flags &= ~XFS_IRECLAIMABLE;
    -				version = ih->ih_version;
    -				read_unlock(&ih->ih_lock);
    -				xfs_ihash_promote(ih, ip, version);
    -
    -#ifdef RMC
    -				XFS_MOUNT_ILOCK(mp);
    -				list_del_init(&ip->i_reclaim);
    -				XFS_MOUNT_IUNLOCK(mp);
    -#endif
    -
    -				goto finish_inode;
    -
    -			} else if (vp != inode_vp) {
    -#ifdef RMC
    -				struct inode *inode = vn_to_inode(inode_vp);
    -
    -				/* The inode is being torn down, pause and
    -				 * try again.
    -				 */
    -				if (inode->i_state & (I_FREEING | I_CLEAR)) {
    -					read_unlock(&ih->ih_lock);
    -					delay(1);
    -					XFS_STATS_INC(xs_ig_frecycle);
    -
    -					goto again;
    -				}
    -#endif
    -/* Chances are the other vnode (the one in the inode) is being torn
    - * down right now, and we landed on top of it. Question is, what do
    - * we do? Unhook the old inode and hook up the new one?
    - */
    -				cmn_err(CE_PANIC,
    -			"xfs_iget_core: ambiguous vns: vp/0x%p, invp/0x%p",
    -						inode_vp, vp);
    -			}
    -
    -			/*
    -			 * Inode cache hit: if ip is not at the front of
    -			 * its hash chain, move it there now.
    -			 * Do this with the lock held for update, but
    -			 * do statistics after releasing the lock.
    -			 */
    -			version = ih->ih_version;
    -			read_unlock(&ih->ih_lock);
    -			xfs_ihash_promote(ih, ip, version);
    -			XFS_STATS_INC(xs_ig_found);
    -
    -finish_inode:
    -			if (ip->i_d.di_mode == 0) {
    -				if (!(flags & IGET_CREATE))
    -					return ENOENT;
    -				xfs_iocore_inode_reinit(ip);
    -			}
    -	
    -			if (lock_flags != 0)
    -				xfs_ilock(ip, lock_flags);
    -
    -			ip->i_flags &= ~XFS_ISTALE;
    -
    -			vn_trace_exit(vp, "xfs_iget.found",
    -						(inst_t *)__return_address);
    -			goto return_ip;
    -		}
    -	}
    -
    -	/*
    -	 * Inode cache miss: save the hash chain version stamp and unlock
    -	 * the chain, so we don't deadlock in vn_alloc.
    -	 */
    -	XFS_STATS_INC(xs_ig_missed);
    -
    -	version = ih->ih_version;
    -
    -	read_unlock(&ih->ih_lock);
    -
    -	/*
    -	 * Read the disk inode attributes into a new inode structure and get
    -	 * a new vnode for it. This should also initialize i_ino and i_mount.
    -	 */
    -	error = xfs_iread(mp, tp, ino, &ip, bno);
    -	if (error) {
    -		return error;
    -	}
    -
    -	vn_trace_exit(vp, "xfs_iget.alloc", (inst_t *)__return_address);
    -
    -	xfs_inode_lock_init(ip, vp);
    -	xfs_iocore_inode_init(ip);
    -
    -	if (lock_flags != 0) {
    -		xfs_ilock(ip, lock_flags);
    -	}
    -		
    -	if ((ip->i_d.di_mode == 0) && !(flags & IGET_CREATE)) {
    -		xfs_idestroy(ip);
    -		return ENOENT;
    -	}
    -
    -	/*
    -	 * Put ip on its hash chain, unless someone else hashed a duplicate
    -	 * after we released the hash lock.
    -	 */
    -	write_lock(&ih->ih_lock);
    -
    -	if (ih->ih_version != version) {
    -		for (iq = ih->ih_next; iq != NULL; iq = iq->i_next) {
    -			if (iq->i_ino == ino) {
    -				write_unlock(&ih->ih_lock);
    -				xfs_idestroy(ip);
    -
    -				XFS_STATS_INC(xs_ig_dup);
    -				goto again;
    -			}
    -		}
    -	}
    -
    -	/*
    -	 * These values _must_ be set before releasing ihlock!
    -	 */
    -	ip->i_hash = ih;
    -	if ((iq = ih->ih_next)) {
    -		iq->i_prevp = &ip->i_next;
    -	}
    -	ip->i_next = iq;
    -	ip->i_prevp = &ih->ih_next;
    -	ih->ih_next = ip;
    -	ip->i_udquot = ip->i_gdquot = NULL;
    -	ih->ih_version++;
    -	ip->i_flags |= XFS_INEW;
    -
    -	write_unlock(&ih->ih_lock);
    -
    -	/*
    -	 * put ip on its cluster's hash chain
    -	 */
    -	ASSERT(ip->i_chash == NULL && ip->i_cprev == NULL &&
    -	       ip->i_cnext == NULL);
    -
    -	chlnew = NULL;
    -	ch = XFS_CHASH(mp, ip->i_blkno);
    - chlredo:
    -	s = mutex_spinlock(&ch->ch_lock);
    -	for (chl = ch->ch_list; chl != NULL; chl = chl->chl_next) {
    -		if (chl->chl_blkno == ip->i_blkno) {
    -
    -			/* insert this inode into the doubly-linked list
    -			 * where chl points */
    -			if ((iq = chl->chl_ip)) {
    -				ip->i_cprev = iq->i_cprev;
    -				iq->i_cprev->i_cnext = ip;
    -				iq->i_cprev = ip;
    -				ip->i_cnext = iq;
    -			} else {
    -				ip->i_cnext = ip;
    -				ip->i_cprev = ip;
    -			}
    -			chl->chl_ip = ip;
    -			ip->i_chash = chl;
    -			break;
    -		}
    -	}
    -
    -	/* no hash list found for this block; add a new hash list */
    -	if (chl == NULL)  {
    -		if (chlnew == NULL) {
    -			mutex_spinunlock(&ch->ch_lock, s);
    -			ASSERT(xfs_chashlist_zone != NULL);
    -			chlnew = (xfs_chashlist_t *)
    -					kmem_zone_alloc(xfs_chashlist_zone,
    -						KM_SLEEP);
    -			ASSERT(chlnew != NULL);
    -			goto chlredo;
    -		} else {
    -			ip->i_cnext = ip;
    -			ip->i_cprev = ip;
    -			ip->i_chash = chlnew;
    -			chlnew->chl_ip = ip;
    -			chlnew->chl_blkno = ip->i_blkno;
    -			if (ch->ch_list)
    -				ch->ch_list->chl_prev = chlnew;
    -			chlnew->chl_next = ch->ch_list;
    -			chlnew->chl_prev = NULL;
    -			ch->ch_list = chlnew;
    -			chlnew = NULL;
    -		}
    -	} else {
    -		if (chlnew != NULL) {
    -			kmem_zone_free(xfs_chashlist_zone, chlnew);
    -		}
    -	}
    -
    -	mutex_spinunlock(&ch->ch_lock, s);
    -
    -
    -	/*
    -	 * Link ip to its mount and thread it on the mount's inode list.
    -	 */
    -	XFS_MOUNT_ILOCK(mp);
    -	if ((iq = mp->m_inodes)) {
    -		ASSERT(iq->i_mprev->i_mnext == iq);
    -		ip->i_mprev = iq->i_mprev;
    -		iq->i_mprev->i_mnext = ip;
    -		iq->i_mprev = ip;
    -		ip->i_mnext = iq;
    -	} else {
    -		ip->i_mnext = ip;
    -		ip->i_mprev = ip;
    -	}
    -	mp->m_inodes = ip;
    -
    -	XFS_MOUNT_IUNLOCK(mp);
    -
    - return_ip:
    -	ASSERT(ip->i_df.if_ext_max ==
    -	       XFS_IFORK_DSIZE(ip) / sizeof(xfs_bmbt_rec_t));
    -
    -	ASSERT(((ip->i_d.di_flags & XFS_DIFLAG_REALTIME) != 0) ==
    -	       ((ip->i_iocore.io_flags & XFS_IOCORE_RT) != 0));
    -
    -	*ipp = ip;
    -
    -	/*
    -	 * If we have a real type for an on-disk inode, we can set ops(&unlock)
    -	 * now.	 If it's a new inode being created, xfs_ialloc will handle it.
    -	 */
    -	XVFS_INIT_VNODE(XFS_MTOVFS(mp), vp, XFS_ITOBHV(ip), 1);
    -
    -	return 0;
    -}
    -#endif
    -
    -#ifdef RMC
    -/*
    - * The 'normal' internal xfs_iget, if needed it will
    - * 'allocate', or 'get', the vnode.
    - */
    -int
    -xfs_iget(
    -	xfs_mount_t	*mp,
    -	xfs_trans_t	*tp,
    -	xfs_ino_t	ino,
    -	uint		flags,
    -	uint		lock_flags,
    -	xfs_inode_t	**ipp,
    -	xfs_daddr_t	bno)
    -{
    -	int		error;
    -	struct inode	*inode;
    -	xfs_vnode_t	*vp = NULL;
    -
    -	XFS_STATS_INC(xs_ig_attempts);
    -
    -retry:
    -	if ((inode = VFS_GET_INODE(XFS_MTOVFS(mp), ino, 0))) {
    -		xfs_inode_t	*ip;
    -
    -		vp = vn_from_inode(inode);
    -		if (inode->i_state & I_NEW) {
    -			vn_initialize(inode);
    -			error = xfs_iget_core(vp, mp, tp, ino, flags,
    -					lock_flags, ipp, bno);
    -			if (error) {
    -				vn_mark_bad(vp);
    -				if (inode->i_state & I_NEW)
    -					unlock_new_inode(inode);
    -				iput(inode);
    -			}
    -		} else {
    -			/*
    -			 * If the inode is not fully constructed due to
    -			 * filehandle mismatches wait for the inode to go
    -			 * away and try again.
    -			 *
    -			 * iget_locked will call __wait_on_freeing_inode
    -			 * to wait for the inode to go away.
    -			 */
    -			if (is_bad_inode(inode) ||
    -			    ((ip = xfs_vtoi(vp)) == NULL)) {
    -				iput(inode);
    -				delay(1);
    -				goto retry;
    -			}
    -
    -			if (lock_flags != 0)
    -				xfs_ilock(ip, lock_flags);
    -			XFS_STATS_INC(xs_ig_found);
    -			*ipp = ip;
    -			error = 0;
    -		}
    -	} else
    -		error = ENOMEM;	/* If we got no inode we are out of memory */
    -
    -	return error;
    -}
    -#endif
    -
    -/*
    - * Do the setup for the various locks within the incore inode.
    - */
    -void
    -xfs_inode_lock_init(
    -	xfs_inode_t	*ip,
    -	xfs_vnode_t	*vp)
    -{
    -	mrlock_init(&ip->i_lock, MRLOCK_ALLOW_EQUAL_PRI|MRLOCK_BARRIER,
    -		     "xfsino", (long)vp->v_number);
    -	mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", vp->v_number);
    -#ifdef RMC
    -	init_waitqueue_head(&ip->i_ipin_wait);
    -#endif
    -	atomic_set(&ip->i_pincount, 0);
    -	init_sema(&ip->i_flock, 1, "xfsfino", vp->v_number);
    -}
    -
    -/*
    - * Look for the inode corresponding to the given ino in the hash table.
    - * If it is there and its i_transp pointer matches tp, return it.
    - * Otherwise, return NULL.
    - */
    -xfs_inode_t *
    -xfs_inode_incore(xfs_mount_t	*mp,
    -		 xfs_ino_t	ino,
    -		 xfs_trans_t	*tp)
    -{
    -	xfs_ihash_t	*ih;
    -	xfs_inode_t	*ip;
    -	ulong		version;
    -
    -	ih = XFS_IHASH(mp, ino);
    -	read_lock(&ih->ih_lock);
    -	for (ip = ih->ih_next; ip != NULL; ip = ip->i_next) {
    -		if (ip->i_ino == ino) {
    -			/*
    -			 * If we find it and tp matches, return it.
    -			 * Also move it to the front of the hash list
    -			 * if we find it and it is not already there.
    -			 * Otherwise break from the loop and return
    -			 * NULL.
    -			 */
    -			if (ip->i_transp == tp) {
    -				version = ih->ih_version;
    -				read_unlock(&ih->ih_lock);
    -				xfs_ihash_promote(ih, ip, version);
    -				return (ip);
    -			}
    -			break;
    -		}
    -	}
    -	read_unlock(&ih->ih_lock);
    -	return (NULL);
    -}
    -
    -/*
    - * Decrement reference count of an inode structure and unlock it.
    - *
    - * ip -- the inode being released
    - * lock_flags -- this parameter indicates the inode's locks to be
    - *       to be released.  See the comment on xfs_iunlock() for a list
    - *	 of valid values.
    - */
    -void
    -xfs_iput(xfs_inode_t	*ip,
    -	 uint		lock_flags)
    -{
    -	xfs_vnode_t	*vp = XFS_ITOV(ip);
    -
    -	vn_trace_entry(vp, "xfs_iput", (inst_t *)__return_address);
    -
    -	xfs_iunlock(ip, lock_flags);
    -
    -	VN_RELE(vp);
    -}
    -
    -#ifdef RMC
    -/* in xfs_freebsd_iget.c
    - * Special iput for brand-new inodes that are still locked
    - */
    -void
    -xfs_iput_new(xfs_inode_t	*ip,
    -	     uint		lock_flags)
    -{
    -	xfs_vnode_t	*vp = XFS_ITOV(ip);
    -	struct inode	*inode = vn_to_inode(vp);
    -
    -	vn_trace_entry(vp, "xfs_iput_new", (inst_t *)__return_address);
    -
    -	if ((ip->i_d.di_mode == 0)) {
    -		ASSERT(!(ip->i_flags & XFS_IRECLAIMABLE));
    -		vn_mark_bad(vp);
    -	}
    -	if (inode->i_state & I_NEW)
    -		unlock_new_inode(inode);
    -	if (lock_flags)
    -		xfs_iunlock(ip, lock_flags);
    -	VN_RELE(vp);
    -}
    -#endif
    -
    -
    -/*
    - * This routine embodies the part of the reclaim code that pulls
    - * the inode from the inode hash table and the mount structure's
    - * inode list.
    - * This should only be called from xfs_reclaim().
    - */
    -void
    -xfs_ireclaim(
    -	     xfs_inode_t *ip)
    -{
    -	xfs_vnode_t	*vp;
    -
    -	/*
    -	 * Remove from old hash list and mount list.
    -	 */
    -	XFS_STATS_INC(xs_ig_reclaims);
    -
    -	xfs_iextract(ip);
    -
    -	/*
    -	 * Here we do a spurious inode lock in order to coordinate with
    -	 * xfs_sync().  This is because xfs_sync() references the inodes
    -	 * in the mount list without taking references on the corresponding
    -	 * vnodes.  We make that OK here by ensuring that we wait until
    -	 * the inode is unlocked in xfs_sync() before we go ahead and
    -	 * free it.  We get both the regular lock and the io lock because
    -	 * the xfs_sync() code may need to drop the regular one but will
    -	 * still hold the io lock.
    -	 */
    -	xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
    -
    -	/*
    -	 * Release dquots (and their references) if any. An inode may escape
    -	 * xfs_inactive and get here via vn_alloc->vn_reclaim path.
    -	 */
    -	XFS_QM_DQDETACH(ip->i_mount, ip);
    -
    -	/*
    -	 * Pull our behavior descriptor from the vnode chain.
    -	 */
    -	vp = XFS_ITOV_NULL(ip);
    -	if (vp) {
    -		vn_bhv_remove(VN_BHV_HEAD(vp), XFS_ITOBHV(ip));
    -	}
    -
    -	/*
    -	 * Free all memory associated with the inode.
    -	 */
    -	xfs_idestroy(ip);
    -}
    -
    -/*
    - * This routine removes an about-to-be-destroyed inode from
    - * all of the lists in which it is located with the exception
    - * of the behavior chain.
    - */
    -void
    -xfs_iextract(
    -	xfs_inode_t	*ip)
    -{
    -	xfs_ihash_t	*ih;
    -	xfs_inode_t	*iq;
    -	xfs_mount_t	*mp;
    -	xfs_chash_t	*ch;
    -	xfs_chashlist_t *chl, *chm;
    -	SPLDECL(s);
    -
    -	ih = ip->i_hash;
    -	write_lock(&ih->ih_lock);
    -	if ((iq = ip->i_next)) {
    -		iq->i_prevp = ip->i_prevp;
    -	}
    -	*ip->i_prevp = iq;
    -	ih->ih_version++;
    -	write_unlock(&ih->ih_lock);
    -
    -	/*
    -	 * Remove from cluster hash list
    -	 *   1) delete the chashlist if this is the last inode on the chashlist
    -	 *   2) unchain from list of inodes
    -	 *   3) point chashlist->chl_ip to 'chl_next' if to this inode.
    -	 */
    -	mp = ip->i_mount;
    -	ch = XFS_CHASH(mp, ip->i_blkno);
    -	s = mutex_spinlock(&ch->ch_lock);
    -
    -	if (ip->i_cnext == ip) {
    -		/* Last inode on chashlist */
    -		ASSERT(ip->i_cnext == ip && ip->i_cprev == ip);
    -		ASSERT(ip->i_chash != NULL);
    -		chm=NULL;
    -		chl = ip->i_chash;
    -		if (chl->chl_prev)
    -			chl->chl_prev->chl_next = chl->chl_next;
    -		else
    -			ch->ch_list = chl->chl_next;
    -		if (chl->chl_next)
    -			chl->chl_next->chl_prev = chl->chl_prev;
    -		kmem_zone_free(xfs_chashlist_zone, chl);
    -	} else {
    -		/* delete one inode from a non-empty list */
    -		iq = ip->i_cnext;
    -		iq->i_cprev = ip->i_cprev;
    -		ip->i_cprev->i_cnext = iq;
    -		if (ip->i_chash->chl_ip == ip) {
    -			ip->i_chash->chl_ip = iq;
    -		}
    -		ip->i_chash = __return_address;
    -		ip->i_cprev = __return_address;
    -		ip->i_cnext = __return_address;
    -	}
    -	mutex_spinunlock(&ch->ch_lock, s);
    -
    -	/*
    -	 * Remove from mount's inode list.
    -	 */
    -	XFS_MOUNT_ILOCK(mp);
    -	ASSERT((ip->i_mnext != NULL) && (ip->i_mprev != NULL));
    -	iq = ip->i_mnext;
    -	iq->i_mprev = ip->i_mprev;
    -	ip->i_mprev->i_mnext = iq;
    -
    -	/*
    -	 * Fix up the head pointer if it points to the inode being deleted.
    -	 */
    -	if (mp->m_inodes == ip) {
    -		if (ip == iq) {
    -			mp->m_inodes = NULL;
    -		} else {
    -			mp->m_inodes = iq;
    -		}
    -	}
    -
    -	/* Deal with the deleted inodes list */
    -#ifdef RMC
    -	list_del_init(&ip->i_reclaim);
    -#endif
    -
    -	mp->m_ireclaims++;
    -	XFS_MOUNT_IUNLOCK(mp);
    -}
    -
    -/*
    - * This is a wrapper routine around the xfs_ilock() routine
    - * used to centralize some grungy code.  It is used in places
    - * that wish to lock the inode solely for reading the extents.
    - * The reason these places can't just call xfs_ilock(SHARED)
    - * is that the inode lock also guards to bringing in of the
    - * extents from disk for a file in b-tree format.  If the inode
    - * is in b-tree format, then we need to lock the inode exclusively
    - * until the extents are read in.  Locking it exclusively all
    - * the time would limit our parallelism unnecessarily, though.
    - * What we do instead is check to see if the extents have been
    - * read in yet, and only lock the inode exclusively if they
    - * have not.
    - *
    - * The function returns a value which should be given to the
    - * corresponding xfs_iunlock_map_shared().  This value is
    - * the mode in which the lock was actually taken.
    - */
    -uint
    -xfs_ilock_map_shared(
    -	xfs_inode_t	*ip)
    -{
    -	uint	lock_mode;
    -
    -	if ((ip->i_d.di_format == XFS_DINODE_FMT_BTREE) &&
    -	    ((ip->i_df.if_flags & XFS_IFEXTENTS) == 0)) {
    -		lock_mode = XFS_ILOCK_EXCL;
    -	} else {
    -		lock_mode = XFS_ILOCK_SHARED;
    -	}
    -
    -	xfs_ilock(ip, lock_mode);
    -
    -	return lock_mode;
    -}
    -
    -/*
    - * This is simply the unlock routine to go with xfs_ilock_map_shared().
    - * All it does is call xfs_iunlock() with the given lock_mode.
    - */
    -void
    -xfs_iunlock_map_shared(
    -	xfs_inode_t	*ip,
    -	unsigned int	lock_mode)
    -{
    -	xfs_iunlock(ip, lock_mode);
    -}
    -
    -/*
    - * The xfs inode contains 2 locks: a multi-reader lock called the
    - * i_iolock and a multi-reader lock called the i_lock.  This routine
    - * allows either or both of the locks to be obtained.
    - *
    - * The 2 locks should always be ordered so that the IO lock is
    - * obtained first in order to prevent deadlock.
    - *
    - * ip -- the inode being locked
    - * lock_flags -- this parameter indicates the inode's locks
    - *       to be locked.  It can be:
    - *		XFS_IOLOCK_SHARED,
    - *		XFS_IOLOCK_EXCL,
    - *		XFS_ILOCK_SHARED,
    - *		XFS_ILOCK_EXCL,
    - *		XFS_IOLOCK_SHARED | XFS_ILOCK_SHARED,
    - *		XFS_IOLOCK_SHARED | XFS_ILOCK_EXCL,
    - *		XFS_IOLOCK_EXCL | XFS_ILOCK_SHARED,
    - *		XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL
    - */
    -void
    -xfs_ilock(xfs_inode_t	*ip,
    -	  uint		lock_flags)
    -{
    -	/*
    -	 * You can't set both SHARED and EXCL for the same lock,
    -	 * and only XFS_IOLOCK_SHARED, XFS_IOLOCK_EXCL, XFS_ILOCK_SHARED,
    -	 * and XFS_ILOCK_EXCL are valid values to set in lock_flags.
    -	 */
    -	ASSERT((lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) !=
    -	       (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL));
    -	ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) !=
    -	       (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
    -	ASSERT((lock_flags & ~XFS_LOCK_MASK) == 0);
    -
    -	if (lock_flags & XFS_IOLOCK_EXCL) {
    -		mrupdate(&ip->i_iolock);
    -	} else if (lock_flags & XFS_IOLOCK_SHARED) {
    -		mraccess(&ip->i_iolock);
    -	}
    -	if (lock_flags & XFS_ILOCK_EXCL) {
    -		mrupdate(&ip->i_lock);
    -	} else if (lock_flags & XFS_ILOCK_SHARED) {
    -		mraccess(&ip->i_lock);
    -	}
    -	xfs_ilock_trace(ip, 1, lock_flags, (inst_t *)__return_address);
    -}
    -
    -/*
    - * This is just like xfs_ilock(), except that the caller
    - * is guaranteed not to sleep.  It returns 1 if it gets
    - * the requested locks and 0 otherwise.  If the IO lock is
    - * obtained but the inode lock cannot be, then the IO lock
    - * is dropped before returning.
    - *
    - * ip -- the inode being locked
    - * lock_flags -- this parameter indicates the inode's locks to be
    - *       to be locked.  See the comment for xfs_ilock() for a list
    - *	 of valid values.
    - *
    - */
    -int
    -xfs_ilock_nowait(xfs_inode_t	*ip,
    -		 uint		lock_flags)
    -{
    -	int	iolocked;
    -	int	ilocked;
    -
    -	/*
    -	 * You can't set both SHARED and EXCL for the same lock,
    -	 * and only XFS_IOLOCK_SHARED, XFS_IOLOCK_EXCL, XFS_ILOCK_SHARED,
    -	 * and XFS_ILOCK_EXCL are valid values to set in lock_flags.
    -	 */
    -	ASSERT((lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) !=
    -	       (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL));
    -	ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) !=
    -	       (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
    -	ASSERT((lock_flags & ~XFS_LOCK_MASK) == 0);
    -
    -	iolocked = 0;
    -	if (lock_flags & XFS_IOLOCK_EXCL) {
    -		iolocked = mrtryupdate(&ip->i_iolock);
    -		if (!iolocked) {
    -			return 0;
    -		}
    -	} else if (lock_flags & XFS_IOLOCK_SHARED) {
    -		iolocked = mrtryaccess(&ip->i_iolock);
    -		if (!iolocked) {
    -			return 0;
    -		}
    -	}
    -	if (lock_flags & XFS_ILOCK_EXCL) {
    -		ilocked = mrtryupdate(&ip->i_lock);
    -		if (!ilocked) {
    -			if (iolocked) {
    -				mrunlock(&ip->i_iolock);
    -			}
    -			return 0;
    -		}
    -	} else if (lock_flags & XFS_ILOCK_SHARED) {
    -		ilocked = mrtryaccess(&ip->i_lock);
    -		if (!ilocked) {
    -			if (iolocked) {
    -				mrunlock(&ip->i_iolock);
    -			}
    -			return 0;
    -		}
    -	}
    -	xfs_ilock_trace(ip, 2, lock_flags, (inst_t *)__return_address);
    -	return 1;
    -}
    -
    -/*
    - * xfs_iunlock() is used to drop the inode locks acquired with
    - * xfs_ilock() and xfs_ilock_nowait().  The caller must pass
    - * in the flags given to xfs_ilock() or xfs_ilock_nowait() so
    - * that we know which locks to drop.
    - *
    - * ip -- the inode being unlocked
    - * lock_flags -- this parameter indicates the inode's locks to be
    - *       to be unlocked.  See the comment for xfs_ilock() for a list
    - *	 of valid values for this parameter.
    - *
    - */
    -void
    -xfs_iunlock(xfs_inode_t	*ip,
    -	    uint	lock_flags)
    -{
    -	/*
    -	 * You can't set both SHARED and EXCL for the same lock,
    -	 * and only XFS_IOLOCK_SHARED, XFS_IOLOCK_EXCL, XFS_ILOCK_SHARED,
    -	 * and XFS_ILOCK_EXCL are valid values to set in lock_flags.
    -	 */
    -	ASSERT((lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) !=
    -	       (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL));
    -	ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) !=
    -	       (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
    -	ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_IUNLOCK_NONOTIFY)) == 0);
    -	ASSERT(lock_flags != 0);
    -
    -	if (lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) {
    -		ASSERT(!(lock_flags & XFS_IOLOCK_SHARED) ||
    -		       (ismrlocked(&ip->i_iolock, MR_ACCESS)));
    -		ASSERT(!(lock_flags & XFS_IOLOCK_EXCL) ||
    -		       (ismrlocked(&ip->i_iolock, MR_UPDATE)));
    -		mrunlock(&ip->i_iolock);
    -	}
    -
    -	if (lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) {
    -		ASSERT(!(lock_flags & XFS_ILOCK_SHARED) ||
    -		       (ismrlocked(&ip->i_lock, MR_ACCESS)));
    -		ASSERT(!(lock_flags & XFS_ILOCK_EXCL) ||
    -		       (ismrlocked(&ip->i_lock, MR_UPDATE)));
    -		mrunlock(&ip->i_lock);
    -
    -		/*
    -		 * Let the AIL know that this item has been unlocked in case
    -		 * it is in the AIL and anyone is waiting on it.  Don't do
    -		 * this if the caller has asked us not to.
    -		 */
    -		if (!(lock_flags & XFS_IUNLOCK_NONOTIFY) &&
    -		     ip->i_itemp != NULL) {
    -			xfs_trans_unlocked_item(ip->i_mount,
    -						(xfs_log_item_t*)(ip->i_itemp));
    -		}
    -	}
    -	xfs_ilock_trace(ip, 3, lock_flags, (inst_t *)__return_address);
    -}
    -
    -/*
    - * give up write locks.  the i/o lock cannot be held nested
    - * if it is being demoted.
    - */
    -void
    -xfs_ilock_demote(xfs_inode_t	*ip,
    -		 uint		lock_flags)
    -{
    -	ASSERT(lock_flags & (XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL));
    -	ASSERT((lock_flags & ~(XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL)) == 0);
    -
    -	if (lock_flags & XFS_ILOCK_EXCL) {
    -		ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
    -		mrdemote(&ip->i_lock);
    -	}
    -	if (lock_flags & XFS_IOLOCK_EXCL) {
    -		ASSERT(ismrlocked(&ip->i_iolock, MR_UPDATE));
    -		mrdemote(&ip->i_iolock);
    -	}
    -}
    -
    -/*
    - * The following three routines simply manage the i_flock
    - * semaphore embedded in the inode.  This semaphore synchronizes
    - * processes attempting to flush the in-core inode back to disk.
    - */
    -void
    -xfs_iflock(xfs_inode_t *ip)
    -{
    -	psema(&(ip->i_flock), PINOD|PLTWAIT);
    -}
    -
    -int
    -xfs_iflock_nowait(xfs_inode_t *ip)
    -{
    -	return (cpsema(&(ip->i_flock)));
    -}
    -
    -void
    -xfs_ifunlock(xfs_inode_t *ip)
    -{
    -	ASSERT(valusema(&(ip->i_flock)) <= 0);
    -	vsema(&(ip->i_flock));
    -}
    diff --git a/sys/gnu/fs/xfs/xfs_imap.h b/sys/gnu/fs/xfs/xfs_imap.h
    deleted file mode 100644
    index d3645000398..00000000000
    --- a/sys/gnu/fs/xfs/xfs_imap.h
    +++ /dev/null
    @@ -1,40 +0,0 @@
    -/*
    - * Copyright (c) 2000,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_IMAP_H__
    -#define	__XFS_IMAP_H__
    -
    -/*
    - * This is the structure passed to xfs_imap() to map
    - * an inode number to its on disk location.
    - */
    -typedef struct xfs_imap {
    -	xfs_daddr_t	im_blkno;	/* starting BB of inode chunk */
    -	uint		im_len;		/* length in BBs of inode chunk */
    -	xfs_agblock_t	im_agblkno;	/* logical block of inode chunk in ag */
    -	ushort		im_ioffset;	/* inode offset in block in "inodes" */
    -	ushort		im_boffset;	/* inode offset in block in bytes */
    -} xfs_imap_t;
    -
    -#ifdef __KERNEL__
    -struct xfs_mount;
    -struct xfs_trans;
    -int	xfs_imap(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
    -		 xfs_imap_t *, uint);
    -#endif
    -
    -#endif	/* __XFS_IMAP_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_inode.c b/sys/gnu/fs/xfs/xfs_inode.c
    deleted file mode 100644
    index 53d46f00bf2..00000000000
    --- a/sys/gnu/fs/xfs/xfs_inode.c
    +++ /dev/null
    @@ -1,4796 +0,0 @@
    -/*
    - * Copyright (c) 2000-2006 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_imap.h"
    -#include "xfs_trans.h"
    -#include "xfs_trans_priv.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_buf_item.h"
    -#include "xfs_inode_item.h"
    -#include "xfs_btree.h"
    -#include "xfs_alloc.h"
    -#include "xfs_ialloc.h"
    -#include "xfs_bmap.h"
    -#include "xfs_rw.h"
    -#include "xfs_error.h"
    -#include "xfs_utils.h"
    -#include "xfs_dir2_trace.h"
    -#include "xfs_quota.h"
    -#include "xfs_mac.h"
    -#include "xfs_acl.h"
    -
    -
    -kmem_zone_t *xfs_ifork_zone;
    -kmem_zone_t *xfs_inode_zone;
    -kmem_zone_t *xfs_chashlist_zone;
    -
    -/*
    - * Used in xfs_itruncate().  This is the maximum number of extents
    - * freed from a file in a single transaction.
    - */
    -#define	XFS_ITRUNC_MAX_EXTENTS	2
    -
    -STATIC int xfs_iflush_int(xfs_inode_t *, xfs_buf_t *);
    -STATIC int xfs_iformat_local(xfs_inode_t *, xfs_dinode_t *, int, int);
    -STATIC int xfs_iformat_extents(xfs_inode_t *, xfs_dinode_t *, int);
    -STATIC int xfs_iformat_btree(xfs_inode_t *, xfs_dinode_t *, int);
    -
    -#ifdef DEBUG
    -/*
    - * Make sure that the extents in the given memory buffer
    - * are valid.
    - */
    -STATIC void
    -xfs_validate_extents(
    -	xfs_ifork_t		*ifp,
    -	int			nrecs,
    -	int			disk,
    -	xfs_exntfmt_t		fmt)
    -{
    -	xfs_bmbt_rec_t		*ep;
    -	xfs_bmbt_irec_t		irec;
    -	xfs_bmbt_rec_t		rec;
    -	int			i;
    -
    -	for (i = 0; i < nrecs; i++) {
    -		ep = xfs_iext_get_ext(ifp, i);
    -		rec.l0 = get_unaligned((__uint64_t*)&ep->l0);
    -		rec.l1 = get_unaligned((__uint64_t*)&ep->l1);
    -		if (disk)
    -			xfs_bmbt_disk_get_all(&rec, &irec);
    -		else
    -			xfs_bmbt_get_all(&rec, &irec);
    -		if (fmt == XFS_EXTFMT_NOSTATE)
    -			ASSERT(irec.br_state == XFS_EXT_NORM);
    -	}
    -}
    -#else /* DEBUG */
    -#define xfs_validate_extents(ifp, nrecs, disk, fmt)
    -#endif /* DEBUG */
    -
    -/*
    - * Check that none of the inode's in the buffer have a next
    - * unlinked field of 0.
    - */
    -#if defined(DEBUG)
    -void
    -xfs_inobp_check(
    -	xfs_mount_t	*mp,
    -	xfs_buf_t	*bp)
    -{
    -	int		i;
    -	int		j;
    -	xfs_dinode_t	*dip;
    -
    -	j = mp->m_inode_cluster_size >> mp->m_sb.sb_inodelog;
    -
    -	for (i = 0; i < j; i++) {
    -		dip = (xfs_dinode_t *)xfs_buf_offset(bp,
    -					i * mp->m_sb.sb_inodesize);
    -		if (!dip->di_next_unlinked)  {
    -			xfs_fs_cmn_err(CE_ALERT, mp,
    -				"Detected a bogus zero next_unlinked field in incore inode buffer 0x%p.  About to pop an ASSERT.",
    -				bp);
    -			ASSERT(dip->di_next_unlinked);
    -		}
    -	}
    -}
    -#endif
    -
    -/*
    - * This routine is called to map an inode number within a file
    - * system to the buffer containing the on-disk version of the
    - * inode.  It returns a pointer to the buffer containing the
    - * on-disk inode in the bpp parameter, and in the dip parameter
    - * it returns a pointer to the on-disk inode within that buffer.
    - *
    - * If a non-zero error is returned, then the contents of bpp and
    - * dipp are undefined.
    - *
    - * Use xfs_imap() to determine the size and location of the
    - * buffer to read from disk.
    - */
    -STATIC int
    -xfs_inotobp(
    -	xfs_mount_t	*mp,
    -	xfs_trans_t	*tp,
    -	xfs_ino_t	ino,
    -	xfs_dinode_t	**dipp,
    -	xfs_buf_t	**bpp,
    -	int		*offset)
    -{
    -	int		di_ok;
    -	xfs_imap_t	imap;
    -	xfs_buf_t	*bp;
    -	int		error;
    -	xfs_dinode_t	*dip;
    -
    -	/*
    -	 * Call the space management code to find the location of the
    -	 * inode on disk.
    -	 */
    -	imap.im_blkno = 0;
    -	error = xfs_imap(mp, tp, ino, &imap, XFS_IMAP_LOOKUP);
    -	if (error != 0) {
    -		cmn_err(CE_WARN,
    -	"xfs_inotobp: xfs_imap()  returned an "
    -	"error %d on %s.  Returning error.", error, mp->m_fsname);
    -		return error;
    -	}
    -
    -	/*
    -	 * If the inode number maps to a block outside the bounds of the
    -	 * file system then return NULL rather than calling read_buf
    -	 * and panicing when we get an error from the driver.
    -	 */
    -	if ((imap.im_blkno + imap.im_len) >
    -	    XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks)) {
    -		cmn_err(CE_WARN,
    -	"xfs_inotobp: inode number (%llu + %d) maps to a block outside the bounds "
    -	"of the file system %s.  Returning EINVAL.",
    -			(unsigned long long)imap.im_blkno,
    -			imap.im_len, mp->m_fsname);
    -		return XFS_ERROR(EINVAL);
    -	}
    -
    -	/*
    -	 * Read in the buffer.  If tp is NULL, xfs_trans_read_buf() will
    -	 * default to just a read_buf() call.
    -	 */
    -	error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, imap.im_blkno,
    -				   (int)imap.im_len, XFS_BUF_LOCK, &bp);
    -
    -	if (error) {
    -		cmn_err(CE_WARN,
    -	"xfs_inotobp: xfs_trans_read_buf()  returned an "
    -	"error %d on %s.  Returning error.", error, mp->m_fsname);
    -		return error;
    -	}
    -	dip = (xfs_dinode_t *)xfs_buf_offset(bp, 0);
    -	di_ok =
    -		INT_GET(dip->di_core.di_magic, ARCH_CONVERT) == XFS_DINODE_MAGIC &&
    -		XFS_DINODE_GOOD_VERSION(INT_GET(dip->di_core.di_version, ARCH_CONVERT));
    -	if (unlikely(XFS_TEST_ERROR(!di_ok, mp, XFS_ERRTAG_ITOBP_INOTOBP,
    -			XFS_RANDOM_ITOBP_INOTOBP))) {
    -		XFS_CORRUPTION_ERROR("xfs_inotobp", XFS_ERRLEVEL_LOW, mp, dip);
    -		xfs_trans_brelse(tp, bp);
    -		cmn_err(CE_WARN,
    -	"xfs_inotobp: XFS_TEST_ERROR()  returned an "
    -	"error on %s.  Returning EFSCORRUPTED.",  mp->m_fsname);
    -		return XFS_ERROR(EFSCORRUPTED);
    -	}
    -
    -	xfs_inobp_check(mp, bp);
    -
    -	/*
    -	 * Set *dipp to point to the on-disk inode in the buffer.
    -	 */
    -	*dipp = (xfs_dinode_t *)xfs_buf_offset(bp, imap.im_boffset);
    -	*bpp = bp;
    -	*offset = imap.im_boffset;
    -	return 0;
    -}
    -
    -
    -/*
    - * This routine is called to map an inode to the buffer containing
    - * the on-disk version of the inode.  It returns a pointer to the
    - * buffer containing the on-disk inode in the bpp parameter, and in
    - * the dip parameter it returns a pointer to the on-disk inode within
    - * that buffer.
    - *
    - * If a non-zero error is returned, then the contents of bpp and
    - * dipp are undefined.
    - *
    - * If the inode is new and has not yet been initialized, use xfs_imap()
    - * to determine the size and location of the buffer to read from disk.
    - * If the inode has already been mapped to its buffer and read in once,
    - * then use the mapping information stored in the inode rather than
    - * calling xfs_imap().  This allows us to avoid the overhead of looking
    - * at the inode btree for small block file systems (see xfs_dilocate()).
    - * We can tell whether the inode has been mapped in before by comparing
    - * its disk block address to 0.  Only uninitialized inodes will have
    - * 0 for the disk block address.
    - */
    -int
    -xfs_itobp(
    -	xfs_mount_t	*mp,
    -	xfs_trans_t	*tp,
    -	xfs_inode_t	*ip,
    -	xfs_dinode_t	**dipp,
    -	xfs_buf_t	**bpp,
    -	xfs_daddr_t	bno,
    -	uint		imap_flags)
    -{
    -	xfs_buf_t	*bp;
    -	int		error;
    -	xfs_imap_t	imap;
    -#ifdef __KERNEL__
    -	int		i;
    -	int		ni;
    -#endif
    -
    -	if (ip->i_blkno == (xfs_daddr_t)0) {
    -		/*
    -		 * Call the space management code to find the location of the
    -		 * inode on disk.
    -		 */
    -		imap.im_blkno = bno;
    -		if ((error = xfs_imap(mp, tp, ip->i_ino, &imap,
    -					XFS_IMAP_LOOKUP | imap_flags)))
    -			return error;
    -
    -		/*
    -		 * If the inode number maps to a block outside the bounds
    -		 * of the file system then return NULL rather than calling
    -		 * read_buf and panicing when we get an error from the
    -		 * driver.
    -		 */
    -		if ((imap.im_blkno + imap.im_len) >
    -		    XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks)) {
    -#ifdef DEBUG
    -			xfs_fs_cmn_err(CE_ALERT, mp, "xfs_itobp: "
    -					"(imap.im_blkno (0x%llx) "
    -					"+ imap.im_len (0x%llx)) > "
    -					" XFS_FSB_TO_BB(mp, "
    -					"mp->m_sb.sb_dblocks) (0x%llx)",
    -					(unsigned long long) imap.im_blkno,
    -					(unsigned long long) imap.im_len,
    -					XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks));
    -#endif /* DEBUG */
    -			return XFS_ERROR(EINVAL);
    -		}
    -
    -		/*
    -		 * Fill in the fields in the inode that will be used to
    -		 * map the inode to its buffer from now on.
    -		 */
    -		ip->i_blkno = imap.im_blkno;
    -		ip->i_len = imap.im_len;
    -		ip->i_boffset = imap.im_boffset;
    -	} else {
    -		/*
    -		 * We've already mapped the inode once, so just use the
    -		 * mapping that we saved the first time.
    -		 */
    -		imap.im_blkno = ip->i_blkno;
    -		imap.im_len = ip->i_len;
    -		imap.im_boffset = ip->i_boffset;
    -	}
    -	ASSERT(bno == 0 || bno == imap.im_blkno);
    -
    -	/*
    -	 * Read in the buffer.  If tp is NULL, xfs_trans_read_buf() will
    -	 * default to just a read_buf() call.
    -	 */
    -	error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, imap.im_blkno,
    -				   (int)imap.im_len, XFS_BUF_LOCK, &bp);
    -
    -	if (error) {
    -#ifdef DEBUG
    -		xfs_fs_cmn_err(CE_ALERT, mp, "xfs_itobp: "
    -				"xfs_trans_read_buf() returned error %d, "
    -				"imap.im_blkno 0x%llx, imap.im_len 0x%llx",
    -				error, (unsigned long long) imap.im_blkno,
    -				(unsigned long long) imap.im_len);
    -#endif /* DEBUG */
    -		return error;
    -	}
    -#ifdef __KERNEL__
    -	/*
    -	 * Validate the magic number and version of every inode in the buffer
    -	 * (if DEBUG kernel) or the first inode in the buffer, otherwise.
    -	 */
    -#ifdef DEBUG
    -	ni = (imap_flags & XFS_IMAP_BULKSTAT) ? 0 :
    -		(BBTOB(imap.im_len) >> mp->m_sb.sb_inodelog);
    -#else
    -	ni = (imap_flags & XFS_IMAP_BULKSTAT) ? 0 : 1;
    -#endif
    -	for (i = 0; i < ni; i++) {
    -		int		di_ok;
    -		xfs_dinode_t	*dip;
    -
    -		dip = (xfs_dinode_t *)xfs_buf_offset(bp,
    -					(i << mp->m_sb.sb_inodelog));
    -		di_ok = INT_GET(dip->di_core.di_magic, ARCH_CONVERT) == XFS_DINODE_MAGIC &&
    -			    XFS_DINODE_GOOD_VERSION(INT_GET(dip->di_core.di_version, ARCH_CONVERT));
    -		if (unlikely(XFS_TEST_ERROR(!di_ok, mp, XFS_ERRTAG_ITOBP_INOTOBP,
    -				 XFS_RANDOM_ITOBP_INOTOBP))) {
    -#ifdef DEBUG
    -			prdev("bad inode magic/vsn daddr %lld #%d (magic=%x)",
    -				mp->m_ddev_targp,
    -				(unsigned long long)imap.im_blkno, i,
    -				INT_GET(dip->di_core.di_magic, ARCH_CONVERT));
    -#endif
    -			XFS_CORRUPTION_ERROR("xfs_itobp", XFS_ERRLEVEL_HIGH,
    -					     mp, dip);
    -			xfs_trans_brelse(tp, bp);
    -			return XFS_ERROR(EFSCORRUPTED);
    -		}
    -	}
    -#endif	/* __KERNEL__ */
    -
    -	xfs_inobp_check(mp, bp);
    -
    -	/*
    -	 * Mark the buffer as an inode buffer now that it looks good
    -	 */
    -	XFS_BUF_SET_VTYPE(bp, B_FS_INO);
    -
    -	/*
    -	 * Set *dipp to point to the on-disk inode in the buffer.
    -	 */
    -	*dipp = (xfs_dinode_t *)xfs_buf_offset(bp, imap.im_boffset);
    -	*bpp = bp;
    -	return 0;
    -}
    -
    -/*
    - * Move inode type and inode format specific information from the
    - * on-disk inode to the in-core inode.  For fifos, devs, and sockets
    - * this means set if_rdev to the proper value.  For files, directories,
    - * and symlinks this means to bring in the in-line data or extent
    - * pointers.  For a file in B-tree format, only the root is immediately
    - * brought in-core.  The rest will be in-lined in if_extents when it
    - * is first referenced (see xfs_iread_extents()).
    - */
    -STATIC int
    -xfs_iformat(
    -	xfs_inode_t		*ip,
    -	xfs_dinode_t		*dip)
    -{
    -	xfs_attr_shortform_t	*atp;
    -	int			size;
    -	int			error;
    -	xfs_fsize_t             di_size;
    -	ip->i_df.if_ext_max =
    -		XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t);
    -	error = 0;
    -
    -	if (unlikely(
    -	    INT_GET(dip->di_core.di_nextents, ARCH_CONVERT) +
    -		INT_GET(dip->di_core.di_anextents, ARCH_CONVERT) >
    -	    INT_GET(dip->di_core.di_nblocks, ARCH_CONVERT))) {
    -		xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
    -			"corrupt dinode %Lu, extent total = %d, nblocks = %Lu.",
    -			(unsigned long long)ip->i_ino,
    -			(int)(INT_GET(dip->di_core.di_nextents, ARCH_CONVERT)
    -			    + INT_GET(dip->di_core.di_anextents, ARCH_CONVERT)),
    -			(unsigned long long)
    -			INT_GET(dip->di_core.di_nblocks, ARCH_CONVERT));
    -		XFS_CORRUPTION_ERROR("xfs_iformat(1)", XFS_ERRLEVEL_LOW,
    -				     ip->i_mount, dip);
    -		return XFS_ERROR(EFSCORRUPTED);
    -	}
    -
    -	if (unlikely(INT_GET(dip->di_core.di_forkoff, ARCH_CONVERT) > ip->i_mount->m_sb.sb_inodesize)) {
    -		xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
    -			"corrupt dinode %Lu, forkoff = 0x%x.",
    -			(unsigned long long)ip->i_ino,
    -			(int)(INT_GET(dip->di_core.di_forkoff, ARCH_CONVERT)));
    -		XFS_CORRUPTION_ERROR("xfs_iformat(2)", XFS_ERRLEVEL_LOW,
    -				     ip->i_mount, dip);
    -		return XFS_ERROR(EFSCORRUPTED);
    -	}
    -
    -	switch (ip->i_d.di_mode & S_IFMT) {
    -	case S_IFIFO:
    -	case S_IFCHR:
    -	case S_IFBLK:
    -	case S_IFSOCK:
    -		if (unlikely(INT_GET(dip->di_core.di_format, ARCH_CONVERT) != XFS_DINODE_FMT_DEV)) {
    -			XFS_CORRUPTION_ERROR("xfs_iformat(3)", XFS_ERRLEVEL_LOW,
    -					      ip->i_mount, dip);
    -			return XFS_ERROR(EFSCORRUPTED);
    -		}
    -		ip->i_d.di_size = 0;
    -		ip->i_df.if_u2.if_rdev = INT_GET(dip->di_u.di_dev, ARCH_CONVERT);
    -		break;
    -
    -	case S_IFREG:
    -	case S_IFLNK:
    -	case S_IFDIR:
    -		switch (INT_GET(dip->di_core.di_format, ARCH_CONVERT)) {
    -		case XFS_DINODE_FMT_LOCAL:
    -			/*
    -			 * no local regular files yet
    -			 */
    -			if (unlikely((INT_GET(dip->di_core.di_mode, ARCH_CONVERT) & S_IFMT) == S_IFREG)) {
    -				xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
    -					"corrupt inode %Lu "
    -					"(local format for regular file).",
    -					(unsigned long long) ip->i_ino);
    -				XFS_CORRUPTION_ERROR("xfs_iformat(4)",
    -						     XFS_ERRLEVEL_LOW,
    -						     ip->i_mount, dip);
    -				return XFS_ERROR(EFSCORRUPTED);
    -			}
    -
    -			di_size = INT_GET(dip->di_core.di_size, ARCH_CONVERT);
    -			if (unlikely(di_size > XFS_DFORK_DSIZE(dip, ip->i_mount))) {
    -				xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
    -					"corrupt inode %Lu "
    -					"(bad size %Ld for local inode).",
    -					(unsigned long long) ip->i_ino,
    -					(long long) di_size);
    -				XFS_CORRUPTION_ERROR("xfs_iformat(5)",
    -						     XFS_ERRLEVEL_LOW,
    -						     ip->i_mount, dip);
    -				return XFS_ERROR(EFSCORRUPTED);
    -			}
    -
    -			size = (int)di_size;
    -			error = xfs_iformat_local(ip, dip, XFS_DATA_FORK, size);
    -			break;
    -		case XFS_DINODE_FMT_EXTENTS:
    -			error = xfs_iformat_extents(ip, dip, XFS_DATA_FORK);
    -			break;
    -		case XFS_DINODE_FMT_BTREE:
    -			error = xfs_iformat_btree(ip, dip, XFS_DATA_FORK);
    -			break;
    -		default:
    -			XFS_ERROR_REPORT("xfs_iformat(6)", XFS_ERRLEVEL_LOW,
    -					 ip->i_mount);
    -			return XFS_ERROR(EFSCORRUPTED);
    -		}
    -		break;
    -
    -	default:
    -		XFS_ERROR_REPORT("xfs_iformat(7)", XFS_ERRLEVEL_LOW, ip->i_mount);
    -		return XFS_ERROR(EFSCORRUPTED);
    -	}
    -	if (error) {
    -		return error;
    -	}
    -	if (!XFS_DFORK_Q(dip))
    -		return 0;
    -	ASSERT(ip->i_afp == NULL);
    -	ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_SLEEP);
    -	ip->i_afp->if_ext_max =
    -		XFS_IFORK_ASIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t);
    -	switch (INT_GET(dip->di_core.di_aformat, ARCH_CONVERT)) {
    -	case XFS_DINODE_FMT_LOCAL:
    -		atp = (xfs_attr_shortform_t *)XFS_DFORK_APTR(dip);
    -		size = be16_to_cpu(atp->hdr.totsize);
    -		error = xfs_iformat_local(ip, dip, XFS_ATTR_FORK, size);
    -		break;
    -	case XFS_DINODE_FMT_EXTENTS:
    -		error = xfs_iformat_extents(ip, dip, XFS_ATTR_FORK);
    -		break;
    -	case XFS_DINODE_FMT_BTREE:
    -		error = xfs_iformat_btree(ip, dip, XFS_ATTR_FORK);
    -		break;
    -	default:
    -		error = XFS_ERROR(EFSCORRUPTED);
    -		break;
    -	}
    -	if (error) {
    -		kmem_zone_free(xfs_ifork_zone, ip->i_afp);
    -		ip->i_afp = NULL;
    -		xfs_idestroy_fork(ip, XFS_DATA_FORK);
    -	}
    -	return error;
    -}
    -
    -/*
    - * The file is in-lined in the on-disk inode.
    - * If it fits into if_inline_data, then copy
    - * it there, otherwise allocate a buffer for it
    - * and copy the data there.  Either way, set
    - * if_data to point at the data.
    - * If we allocate a buffer for the data, make
    - * sure that its size is a multiple of 4 and
    - * record the real size in i_real_bytes.
    - */
    -STATIC int
    -xfs_iformat_local(
    -	xfs_inode_t	*ip,
    -	xfs_dinode_t	*dip,
    -	int		whichfork,
    -	int		size)
    -{
    -	xfs_ifork_t	*ifp;
    -	int		real_size;
    -
    -	/*
    -	 * If the size is unreasonable, then something
    -	 * is wrong and we just bail out rather than crash in
    -	 * kmem_alloc() or memcpy() below.
    -	 */
    -	if (unlikely(size > XFS_DFORK_SIZE(dip, ip->i_mount, whichfork))) {
    -		xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
    -			"corrupt inode %Lu "
    -			"(bad size %d for local fork, size = %d).",
    -			(unsigned long long) ip->i_ino, size,
    -			XFS_DFORK_SIZE(dip, ip->i_mount, whichfork));
    -		XFS_CORRUPTION_ERROR("xfs_iformat_local", XFS_ERRLEVEL_LOW,
    -				     ip->i_mount, dip);
    -		return XFS_ERROR(EFSCORRUPTED);
    -	}
    -	ifp = XFS_IFORK_PTR(ip, whichfork);
    -	real_size = 0;
    -	if (size == 0)
    -		ifp->if_u1.if_data = NULL;
    -	else if (size <= sizeof(ifp->if_u2.if_inline_data))
    -		ifp->if_u1.if_data = ifp->if_u2.if_inline_data;
    -	else {
    -		real_size = roundup(size, 4);
    -		ifp->if_u1.if_data = kmem_alloc(real_size, KM_SLEEP);
    -	}
    -	ifp->if_bytes = size;
    -	ifp->if_real_bytes = real_size;
    -	if (size)
    -		memcpy(ifp->if_u1.if_data, XFS_DFORK_PTR(dip, whichfork), size);
    -	ifp->if_flags &= ~XFS_IFEXTENTS;
    -	ifp->if_flags |= XFS_IFINLINE;
    -	return 0;
    -}
    -
    -/*
    - * The file consists of a set of extents all
    - * of which fit into the on-disk inode.
    - * If there are few enough extents to fit into
    - * the if_inline_ext, then copy them there.
    - * Otherwise allocate a buffer for them and copy
    - * them into it.  Either way, set if_extents
    - * to point at the extents.
    - */
    -STATIC int
    -xfs_iformat_extents(
    -	xfs_inode_t	*ip,
    -	xfs_dinode_t	*dip,
    -	int		whichfork)
    -{
    -	xfs_bmbt_rec_t	*ep, *dp;
    -	xfs_ifork_t	*ifp;
    -	int		nex;
    -	int		size;
    -	int		i;
    -
    -	ifp = XFS_IFORK_PTR(ip, whichfork);
    -	nex = XFS_DFORK_NEXTENTS(dip, whichfork);
    -	size = nex * (uint)sizeof(xfs_bmbt_rec_t);
    -
    -	/*
    -	 * If the number of extents is unreasonable, then something
    -	 * is wrong and we just bail out rather than crash in
    -	 * kmem_alloc() or memcpy() below.
    -	 */
    -	if (unlikely(size < 0 || size > XFS_DFORK_SIZE(dip, ip->i_mount, whichfork))) {
    -		xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
    -			"corrupt inode %Lu ((a)extents = %d).",
    -			(unsigned long long) ip->i_ino, nex);
    -		XFS_CORRUPTION_ERROR("xfs_iformat_extents(1)", XFS_ERRLEVEL_LOW,
    -				     ip->i_mount, dip);
    -		return XFS_ERROR(EFSCORRUPTED);
    -	}
    -
    -	ifp->if_real_bytes = 0;
    -	if (nex == 0)
    -		ifp->if_u1.if_extents = NULL;
    -	else if (nex <= XFS_INLINE_EXTS)
    -		ifp->if_u1.if_extents = ifp->if_u2.if_inline_ext;
    -	else
    -		xfs_iext_add(ifp, 0, nex);
    -
    -	ifp->if_bytes = size;
    -	if (size) {
    -		dp = (xfs_bmbt_rec_t *) XFS_DFORK_PTR(dip, whichfork);
    -		xfs_validate_extents(ifp, nex, 1, XFS_EXTFMT_INODE(ip));
    -		for (i = 0; i < nex; i++, dp++) {
    -			ep = xfs_iext_get_ext(ifp, i);
    -			ep->l0 = INT_GET(get_unaligned((__uint64_t*)&dp->l0),
    -								ARCH_CONVERT);
    -			ep->l1 = INT_GET(get_unaligned((__uint64_t*)&dp->l1),
    -								ARCH_CONVERT);
    -		}
    -		xfs_bmap_trace_exlist("xfs_iformat_extents", ip, nex,
    -			whichfork);
    -		if (whichfork != XFS_DATA_FORK ||
    -			XFS_EXTFMT_INODE(ip) == XFS_EXTFMT_NOSTATE)
    -				if (unlikely(xfs_check_nostate_extents(
    -				    ifp, 0, nex))) {
    -					XFS_ERROR_REPORT("xfs_iformat_extents(2)",
    -							 XFS_ERRLEVEL_LOW,
    -							 ip->i_mount);
    -					return XFS_ERROR(EFSCORRUPTED);
    -				}
    -	}
    -	ifp->if_flags |= XFS_IFEXTENTS;
    -	return 0;
    -}
    -
    -/*
    - * The file has too many extents to fit into
    - * the inode, so they are in B-tree format.
    - * Allocate a buffer for the root of the B-tree
    - * and copy the root into it.  The i_extents
    - * field will remain NULL until all of the
    - * extents are read in (when they are needed).
    - */
    -STATIC int
    -xfs_iformat_btree(
    -	xfs_inode_t		*ip,
    -	xfs_dinode_t		*dip,
    -	int			whichfork)
    -{
    -	xfs_bmdr_block_t	*dfp;
    -	xfs_ifork_t		*ifp;
    -	/* REFERENCED */
    -	int			nrecs;
    -	int			size;
    -
    -	ifp = XFS_IFORK_PTR(ip, whichfork);
    -	dfp = (xfs_bmdr_block_t *)XFS_DFORK_PTR(dip, whichfork);
    -	size = XFS_BMAP_BROOT_SPACE(dfp);
    -	nrecs = XFS_BMAP_BROOT_NUMRECS(dfp);
    -
    -	/*
    -	 * blow out if -- fork has less extents than can fit in
    -	 * fork (fork shouldn't be a btree format), root btree
    -	 * block has more records than can fit into the fork,
    -	 * or the number of extents is greater than the number of
    -	 * blocks.
    -	 */
    -	if (unlikely(XFS_IFORK_NEXTENTS(ip, whichfork) <= ifp->if_ext_max
    -	    || XFS_BMDR_SPACE_CALC(nrecs) >
    -			XFS_DFORK_SIZE(dip, ip->i_mount, whichfork)
    -	    || XFS_IFORK_NEXTENTS(ip, whichfork) > ip->i_d.di_nblocks)) {
    -		xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
    -			"corrupt inode %Lu (btree).",
    -			(unsigned long long) ip->i_ino);
    -		XFS_ERROR_REPORT("xfs_iformat_btree", XFS_ERRLEVEL_LOW,
    -				 ip->i_mount);
    -		return XFS_ERROR(EFSCORRUPTED);
    -	}
    -
    -	ifp->if_broot_bytes = size;
    -	ifp->if_broot = kmem_alloc(size, KM_SLEEP);
    -	ASSERT(ifp->if_broot != NULL);
    -	/*
    -	 * Copy and convert from the on-disk structure
    -	 * to the in-memory structure.
    -	 */
    -	xfs_bmdr_to_bmbt(dfp, XFS_DFORK_SIZE(dip, ip->i_mount, whichfork),
    -		ifp->if_broot, size);
    -	ifp->if_flags &= ~XFS_IFEXTENTS;
    -	ifp->if_flags |= XFS_IFBROOT;
    -
    -	return 0;
    -}
    -
    -/*
    - * xfs_xlate_dinode_core - translate an xfs_inode_core_t between ondisk
    - * and native format
    - *
    - * buf  = on-disk representation
    - * dip  = native representation
    - * dir  = direction - +ve -> disk to native
    - *                    -ve -> native to disk
    - */
    -void
    -xfs_xlate_dinode_core(
    -	xfs_caddr_t		buf,
    -	xfs_dinode_core_t	*dip,
    -	int			dir)
    -{
    -	xfs_dinode_core_t	*buf_core = (xfs_dinode_core_t *)buf;
    -	xfs_dinode_core_t	*mem_core = (xfs_dinode_core_t *)dip;
    -	xfs_arch_t		arch = ARCH_CONVERT;
    -
    -	ASSERT(dir);
    -
    -	INT_XLATE(buf_core->di_magic, mem_core->di_magic, dir, arch);
    -	INT_XLATE(buf_core->di_mode, mem_core->di_mode, dir, arch);
    -	INT_XLATE(buf_core->di_version,	mem_core->di_version, dir, arch);
    -	INT_XLATE(buf_core->di_format, mem_core->di_format, dir, arch);
    -	INT_XLATE(buf_core->di_onlink, mem_core->di_onlink, dir, arch);
    -	INT_XLATE(buf_core->di_uid, mem_core->di_uid, dir, arch);
    -	INT_XLATE(buf_core->di_gid, mem_core->di_gid, dir, arch);
    -	INT_XLATE(buf_core->di_nlink, mem_core->di_nlink, dir, arch);
    -	INT_XLATE(buf_core->di_projid, mem_core->di_projid, dir, arch);
    -
    -	if (dir > 0) {
    -		memcpy(mem_core->di_pad, buf_core->di_pad,
    -			sizeof(buf_core->di_pad));
    -	} else {
    -		memcpy(buf_core->di_pad, mem_core->di_pad,
    -			sizeof(buf_core->di_pad));
    -	}
    -
    -	INT_XLATE(buf_core->di_flushiter, mem_core->di_flushiter, dir, arch);
    -
    -	INT_XLATE(buf_core->di_atime.t_sec, mem_core->di_atime.t_sec,
    -			dir, arch);
    -	INT_XLATE(buf_core->di_atime.t_nsec, mem_core->di_atime.t_nsec,
    -			dir, arch);
    -	INT_XLATE(buf_core->di_mtime.t_sec, mem_core->di_mtime.t_sec,
    -			dir, arch);
    -	INT_XLATE(buf_core->di_mtime.t_nsec, mem_core->di_mtime.t_nsec,
    -			dir, arch);
    -	INT_XLATE(buf_core->di_ctime.t_sec, mem_core->di_ctime.t_sec,
    -			dir, arch);
    -	INT_XLATE(buf_core->di_ctime.t_nsec, mem_core->di_ctime.t_nsec,
    -			dir, arch);
    -	INT_XLATE(buf_core->di_size, mem_core->di_size, dir, arch);
    -	INT_XLATE(buf_core->di_nblocks, mem_core->di_nblocks, dir, arch);
    -	INT_XLATE(buf_core->di_extsize, mem_core->di_extsize, dir, arch);
    -	INT_XLATE(buf_core->di_nextents, mem_core->di_nextents, dir, arch);
    -	INT_XLATE(buf_core->di_anextents, mem_core->di_anextents, dir, arch);
    -	INT_XLATE(buf_core->di_forkoff, mem_core->di_forkoff, dir, arch);
    -	INT_XLATE(buf_core->di_aformat, mem_core->di_aformat, dir, arch);
    -	INT_XLATE(buf_core->di_dmevmask, mem_core->di_dmevmask, dir, arch);
    -	INT_XLATE(buf_core->di_dmstate, mem_core->di_dmstate, dir, arch);
    -	INT_XLATE(buf_core->di_flags, mem_core->di_flags, dir, arch);
    -	INT_XLATE(buf_core->di_gen, mem_core->di_gen, dir, arch);
    -}
    -
    -STATIC uint
    -_xfs_dic2xflags(
    -	xfs_dinode_core_t	*dic,
    -	__uint16_t		di_flags)
    -{
    -	uint			flags = 0;
    -
    -	if (di_flags & XFS_DIFLAG_ANY) {
    -		if (di_flags & XFS_DIFLAG_REALTIME)
    -			flags |= XFS_XFLAG_REALTIME;
    -		if (di_flags & XFS_DIFLAG_PREALLOC)
    -			flags |= XFS_XFLAG_PREALLOC;
    -		if (di_flags & XFS_DIFLAG_IMMUTABLE)
    -			flags |= XFS_XFLAG_IMMUTABLE;
    -		if (di_flags & XFS_DIFLAG_APPEND)
    -			flags |= XFS_XFLAG_APPEND;
    -		if (di_flags & XFS_DIFLAG_SYNC)
    -			flags |= XFS_XFLAG_SYNC;
    -		if (di_flags & XFS_DIFLAG_NOATIME)
    -			flags |= XFS_XFLAG_NOATIME;
    -		if (di_flags & XFS_DIFLAG_NODUMP)
    -			flags |= XFS_XFLAG_NODUMP;
    -		if (di_flags & XFS_DIFLAG_RTINHERIT)
    -			flags |= XFS_XFLAG_RTINHERIT;
    -		if (di_flags & XFS_DIFLAG_PROJINHERIT)
    -			flags |= XFS_XFLAG_PROJINHERIT;
    -		if (di_flags & XFS_DIFLAG_NOSYMLINKS)
    -			flags |= XFS_XFLAG_NOSYMLINKS;
    -		if (di_flags & XFS_DIFLAG_EXTSIZE)
    -			flags |= XFS_XFLAG_EXTSIZE;
    -		if (di_flags & XFS_DIFLAG_EXTSZINHERIT)
    -			flags |= XFS_XFLAG_EXTSZINHERIT;
    -	}
    -
    -	return flags;
    -}
    -
    -uint
    -xfs_ip2xflags(
    -	xfs_inode_t		*ip)
    -{
    -	xfs_dinode_core_t	*dic = &ip->i_d;
    -
    -	return _xfs_dic2xflags(dic, dic->di_flags) |
    -		(XFS_CFORK_Q(dic) ? XFS_XFLAG_HASATTR : 0);
    -}
    -
    -uint
    -xfs_dic2xflags(
    -	xfs_dinode_core_t	*dic)
    -{
    -	return _xfs_dic2xflags(dic, INT_GET(dic->di_flags, ARCH_CONVERT)) |
    -		(XFS_CFORK_Q_DISK(dic) ? XFS_XFLAG_HASATTR : 0);
    -}
    -
    -/*
    - * Given a mount structure and an inode number, return a pointer
    - * to a newly allocated in-core inode corresponding to the given
    - * inode number.
    - *
    - * Initialize the inode's attributes and extent pointers if it
    - * already has them (it will not if the inode has no links).
    - */
    -int
    -xfs_iread(
    -	xfs_mount_t	*mp,
    -	xfs_trans_t	*tp,
    -	xfs_ino_t	ino,
    -	xfs_inode_t	**ipp,
    -	xfs_daddr_t	bno)
    -{
    -	xfs_buf_t	*bp;
    -	xfs_dinode_t	*dip;
    -	xfs_inode_t	*ip;
    -	int		error;
    -
    -	ASSERT(xfs_inode_zone != NULL);
    -
    -	ip = kmem_zone_zalloc(xfs_inode_zone, KM_SLEEP);
    -	ip->i_ino = ino;
    -	ip->i_mount = mp;
    -
    -	/*
    -	 * Get pointer's to the on-disk inode and the buffer containing it.
    -	 * If the inode number refers to a block outside the file system
    -	 * then xfs_itobp() will return NULL.  In this case we should
    -	 * return NULL as well.  Set i_blkno to 0 so that xfs_itobp() will
    -	 * know that this is a new incore inode.
    -	 */
    -	error = xfs_itobp(mp, tp, ip, &dip, &bp, bno, 0);
    -	if (error) {
    -		kmem_zone_free(xfs_inode_zone, ip);
    -		return error;
    -	}
    -
    -	/*
    -	 * Initialize inode's trace buffers.
    -	 * Do this before xfs_iformat in case it adds entries.
    -	 */
    -#ifdef XFS_BMAP_TRACE
    -	ip->i_xtrace = ktrace_alloc(XFS_BMAP_KTRACE_SIZE, KM_SLEEP);
    -#endif
    -#ifdef XFS_BMBT_TRACE
    -	ip->i_btrace = ktrace_alloc(XFS_BMBT_KTRACE_SIZE, KM_SLEEP);
    -#endif
    -#ifdef XFS_RW_TRACE
    -	ip->i_rwtrace = ktrace_alloc(XFS_RW_KTRACE_SIZE, KM_SLEEP);
    -#endif
    -#ifdef XFS_ILOCK_TRACE
    -	ip->i_lock_trace = ktrace_alloc(XFS_ILOCK_KTRACE_SIZE, KM_SLEEP);
    -#endif
    -#ifdef XFS_DIR2_TRACE
    -	ip->i_dir_trace = ktrace_alloc(XFS_DIR2_KTRACE_SIZE, KM_SLEEP);
    -#endif
    -
    -	/*
    -	 * If we got something that isn't an inode it means someone
    -	 * (nfs or dmi) has a stale handle.
    -	 */
    -	if (INT_GET(dip->di_core.di_magic, ARCH_CONVERT) != XFS_DINODE_MAGIC) {
    -		kmem_zone_free(xfs_inode_zone, ip);
    -		xfs_trans_brelse(tp, bp);
    -#ifdef DEBUG
    -		xfs_fs_cmn_err(CE_ALERT, mp, "xfs_iread: "
    -				"dip->di_core.di_magic (0x%x) != "
    -				"XFS_DINODE_MAGIC (0x%x)",
    -				INT_GET(dip->di_core.di_magic, ARCH_CONVERT),
    -				XFS_DINODE_MAGIC);
    -#endif /* DEBUG */
    -		return XFS_ERROR(EINVAL);
    -	}
    -
    -	/*
    -	 * If the on-disk inode is already linked to a directory
    -	 * entry, copy all of the inode into the in-core inode.
    -	 * xfs_iformat() handles copying in the inode format
    -	 * specific information.
    -	 * Otherwise, just get the truly permanent information.
    -	 */
    -	if (dip->di_core.di_mode) {
    -		xfs_xlate_dinode_core((xfs_caddr_t)&dip->di_core,
    -		     &(ip->i_d), 1);
    -		error = xfs_iformat(ip, dip);
    -		if (error)  {
    -			kmem_zone_free(xfs_inode_zone, ip);
    -			xfs_trans_brelse(tp, bp);
    -#ifdef DEBUG
    -			xfs_fs_cmn_err(CE_ALERT, mp, "xfs_iread: "
    -					"xfs_iformat() returned error %d",
    -					error);
    -#endif /* DEBUG */
    -			return error;
    -		}
    -	} else {
    -		ip->i_d.di_magic = INT_GET(dip->di_core.di_magic, ARCH_CONVERT);
    -		ip->i_d.di_version = INT_GET(dip->di_core.di_version, ARCH_CONVERT);
    -		ip->i_d.di_gen = INT_GET(dip->di_core.di_gen, ARCH_CONVERT);
    -		ip->i_d.di_flushiter = INT_GET(dip->di_core.di_flushiter, ARCH_CONVERT);
    -		/*
    -		 * Make sure to pull in the mode here as well in
    -		 * case the inode is released without being used.
    -		 * This ensures that xfs_inactive() will see that
    -		 * the inode is already free and not try to mess
    -		 * with the uninitialized part of it.
    -		 */
    -		ip->i_d.di_mode = 0;
    -		/*
    -		 * Initialize the per-fork minima and maxima for a new
    -		 * inode here.  xfs_iformat will do it for old inodes.
    -		 */
    -		ip->i_df.if_ext_max =
    -			XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t);
    -	}
    -
    -#ifdef RMC
    -	INIT_LIST_HEAD(&ip->i_reclaim);
    -#else
    -	bzero(&ip->i_reclaim,sizeof(ip->i_reclaim));
    -#endif
    -
    -
    -	/*
    -	 * The inode format changed when we moved the link count and
    -	 * made it 32 bits long.  If this is an old format inode,
    -	 * convert it in memory to look like a new one.  If it gets
    -	 * flushed to disk we will convert back before flushing or
    -	 * logging it.  We zero out the new projid field and the old link
    -	 * count field.  We'll handle clearing the pad field (the remains
    -	 * of the old uuid field) when we actually convert the inode to
    -	 * the new format. We don't change the version number so that we
    -	 * can distinguish this from a real new format inode.
    -	 */
    -	if (ip->i_d.di_version == XFS_DINODE_VERSION_1) {
    -		ip->i_d.di_nlink = ip->i_d.di_onlink;
    -		ip->i_d.di_onlink = 0;
    -		ip->i_d.di_projid = 0;
    -	}
    -
    -	ip->i_delayed_blks = 0;
    -
    -	/*
    -	 * Mark the buffer containing the inode as something to keep
    -	 * around for a while.  This helps to keep recently accessed
    -	 * meta-data in-core longer.
    -	 */
    -	 XFS_BUF_SET_REF(bp, XFS_INO_REF);
    -
    -	/*
    -	 * Use xfs_trans_brelse() to release the buffer containing the
    -	 * on-disk inode, because it was acquired with xfs_trans_read_buf()
    -	 * in xfs_itobp() above.  If tp is NULL, this is just a normal
    -	 * brelse().  If we're within a transaction, then xfs_trans_brelse()
    -	 * will only release the buffer if it is not dirty within the
    -	 * transaction.  It will be OK to release the buffer in this case,
    -	 * because inodes on disk are never destroyed and we will be
    -	 * locking the new in-core inode before putting it in the hash
    -	 * table where other processes can find it.  Thus we don't have
    -	 * to worry about the inode being changed just because we released
    -	 * the buffer.
    -	 */
    -	xfs_trans_brelse(tp, bp);
    -	*ipp = ip;
    -	return 0;
    -}
    -
    -/*
    - * Read in extents from a btree-format inode.
    - * Allocate and fill in if_extents.  Real work is done in xfs_bmap.c.
    - */
    -int
    -xfs_iread_extents(
    -	xfs_trans_t	*tp,
    -	xfs_inode_t	*ip,
    -	int		whichfork)
    -{
    -	int		error;
    -	xfs_ifork_t	*ifp;
    -	xfs_extnum_t	nextents;
    -	size_t		size;
    -
    -	if (unlikely(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)) {
    -		XFS_ERROR_REPORT("xfs_iread_extents", XFS_ERRLEVEL_LOW,
    -				 ip->i_mount);
    -		return XFS_ERROR(EFSCORRUPTED);
    -	}
    -	nextents = XFS_IFORK_NEXTENTS(ip, whichfork);
    -	size = nextents * sizeof(xfs_bmbt_rec_t);
    -	ifp = XFS_IFORK_PTR(ip, whichfork);
    -
    -	/*
    -	 * We know that the size is valid (it's checked in iformat_btree)
    -	 */
    -	ifp->if_lastex = NULLEXTNUM;
    -	ifp->if_bytes = ifp->if_real_bytes = 0;
    -	ifp->if_flags |= XFS_IFEXTENTS;
    -	xfs_iext_add(ifp, 0, nextents);
    -	error = xfs_bmap_read_extents(tp, ip, whichfork);
    -	if (error) {
    -		xfs_iext_destroy(ifp);
    -		ifp->if_flags &= ~XFS_IFEXTENTS;
    -		return error;
    -	}
    -	xfs_validate_extents(ifp, nextents, 0, XFS_EXTFMT_INODE(ip));
    -	return 0;
    -}
    -
    -/*
    - * Allocate an inode on disk and return a copy of its in-core version.
    - * The in-core inode is locked exclusively.  Set mode, nlink, and rdev
    - * appropriately within the inode.  The uid and gid for the inode are
    - * set according to the contents of the given cred structure.
    - *
    - * Use xfs_dialloc() to allocate the on-disk inode. If xfs_dialloc()
    - * has a free inode available, call xfs_iget()
    - * to obtain the in-core version of the allocated inode.  Finally,
    - * fill in the inode and log its initial contents.  In this case,
    - * ialloc_context would be set to NULL and call_again set to false.
    - *
    - * If xfs_dialloc() does not have an available inode,
    - * it will replenish its supply by doing an allocation. Since we can
    - * only do one allocation within a transaction without deadlocks, we
    - * must commit the current transaction before returning the inode itself.
    - * In this case, therefore, we will set call_again to true and return.
    - * The caller should then commit the current transaction, start a new
    - * transaction, and call xfs_ialloc() again to actually get the inode.
    - *
    - * To ensure that some other process does not grab the inode that
    - * was allocated during the first call to xfs_ialloc(), this routine
    - * also returns the [locked] bp pointing to the head of the freelist
    - * as ialloc_context.  The caller should hold this buffer across
    - * the commit and pass it back into this routine on the second call.
    - */
    -int
    -xfs_ialloc(
    -	xfs_trans_t	*tp,
    -	xfs_inode_t	*pip,
    -	mode_t		mode,
    -	xfs_nlink_t	nlink,
    -	xfs_dev_t	rdev,
    -	cred_t		*cr,
    -	xfs_prid_t	prid,
    -	int		okalloc,
    -	xfs_buf_t	**ialloc_context,
    -	boolean_t	*call_again,
    -	xfs_inode_t	**ipp)
    -{
    -	xfs_ino_t	ino;
    -	xfs_inode_t	*ip;
    -	xfs_vnode_t	*vp;
    -	uint		flags;
    -	int		error;
    -
    -	/*
    -	 * Call the space management code to pick
    -	 * the on-disk inode to be allocated.
    -	 */
    -	error = xfs_dialloc(tp, pip->i_ino, mode, okalloc,
    -			    ialloc_context, call_again, &ino);
    -	if (error != 0) {
    -		return error;
    -	}
    -	if (*call_again || ino == NULLFSINO) {
    -		*ipp = NULL;
    -		return 0;
    -	}
    -	ASSERT(*ialloc_context == NULL);
    -
    -	/*
    -	 * Get the in-core inode with the lock held exclusively.
    -	 * This is because we're setting fields here we need
    -	 * to prevent others from looking at until we're done.
    -	 */
    -	error = xfs_trans_iget(tp->t_mountp, tp, ino,
    -			IGET_CREATE, XFS_ILOCK_EXCL, &ip);
    -	if (error != 0) {
    -		return error;
    -	}
    -	ASSERT(ip != NULL);
    -
    -	vp = XFS_ITOV(ip);
    -	ip->i_d.di_mode = (__uint16_t)mode;
    -	ip->i_d.di_onlink = 0;
    -	ip->i_d.di_nlink = nlink;
    -	ASSERT(ip->i_d.di_nlink == nlink);
    -	ip->i_d.di_uid = curthread->td_ucred->cr_uid;
    -	ip->i_d.di_gid = curthread->td_ucred->cr_groups[0];
    -	ip->i_d.di_projid = prid;
    -	memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
    -
    -	/*
    -	 * If the superblock version is up to where we support new format
    -	 * inodes and this is currently an old format inode, then change
    -	 * the inode version number now.  This way we only do the conversion
    -	 * here rather than here and in the flush/logging code.
    -	 */
    -	if (XFS_SB_VERSION_HASNLINK(&tp->t_mountp->m_sb) &&
    -	    ip->i_d.di_version == XFS_DINODE_VERSION_1) {
    -		ip->i_d.di_version = XFS_DINODE_VERSION_2;
    -		/*
    -		 * We've already zeroed the old link count, the projid field,
    -		 * and the pad field.
    -		 */
    -	}
    -
    -	/*
    -	 * Project ids won't be stored on disk if we are using a version 1 inode.
    -	 */
    -	if ( (prid != 0) && (ip->i_d.di_version == XFS_DINODE_VERSION_1))
    -		xfs_bump_ino_vers2(tp, ip);
    -
    -	if (XFS_INHERIT_GID(pip, vp->v_vfsp)) {
    -		ip->i_d.di_gid = pip->i_d.di_gid;
    -		if ((pip->i_d.di_mode & S_ISGID) && (mode & S_IFMT) == S_IFDIR) {
    -			ip->i_d.di_mode |= S_ISGID;
    -		}
    -	}
    -
    -	/*
    -	 * If the group ID of the new file does not match the effective group
    -	 * ID or one of the supplementary group IDs, the S_ISGID bit is cleared
    -	 * (and only if the irix_sgid_inherit compatibility variable is set).
    -	 */
    -	if ((irix_sgid_inherit) &&
    -	    (ip->i_d.di_mode & S_ISGID) &&
    -	    (!groupmember((gid_t)ip->i_d.di_gid, curthread->td_ucred))) {
    -		ip->i_d.di_mode &= ~S_ISGID;
    -	}
    -
    -	ip->i_d.di_size = 0;
    -	ip->i_d.di_nextents = 0;
    -	ASSERT(ip->i_d.di_nblocks == 0);
    -	xfs_ichgtime(ip, XFS_ICHGTIME_CHG|XFS_ICHGTIME_ACC|XFS_ICHGTIME_MOD);
    -	/*
    -	 * di_gen will have been taken care of in xfs_iread.
    -	 */
    -	ip->i_d.di_extsize = 0;
    -	ip->i_d.di_dmevmask = 0;
    -	ip->i_d.di_dmstate = 0;
    -	ip->i_d.di_flags = 0;
    -	flags = XFS_ILOG_CORE;
    -	switch (mode & S_IFMT) {
    -	case S_IFIFO:
    -	case S_IFCHR:
    -	case S_IFBLK:
    -	case S_IFSOCK:
    -		ip->i_d.di_format = XFS_DINODE_FMT_DEV;
    -		ip->i_df.if_u2.if_rdev = rdev;
    -		ip->i_df.if_flags = 0;
    -		flags |= XFS_ILOG_DEV;
    -		break;
    -	case S_IFREG:
    -	case S_IFDIR:
    -		if (unlikely(pip->i_d.di_flags & XFS_DIFLAG_ANY)) {
    -			uint	di_flags = 0;
    -
    -			if ((mode & S_IFMT) == S_IFDIR) {
    -				if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT)
    -					di_flags |= XFS_DIFLAG_RTINHERIT;
    -				if (pip->i_d.di_flags & XFS_DIFLAG_EXTSZINHERIT) {
    -					di_flags |= XFS_DIFLAG_EXTSZINHERIT;
    -					ip->i_d.di_extsize = pip->i_d.di_extsize;
    -				}
    -			} else if ((mode & S_IFMT) == S_IFREG) {
    -				if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT) {
    -					di_flags |= XFS_DIFLAG_REALTIME;
    -					ip->i_iocore.io_flags |= XFS_IOCORE_RT;
    -				}
    -				if (pip->i_d.di_flags & XFS_DIFLAG_EXTSZINHERIT) {
    -					di_flags |= XFS_DIFLAG_EXTSIZE;
    -					ip->i_d.di_extsize = pip->i_d.di_extsize;
    -				}
    -			}
    -			if ((pip->i_d.di_flags & XFS_DIFLAG_NOATIME) &&
    -			    xfs_inherit_noatime)
    -				di_flags |= XFS_DIFLAG_NOATIME;
    -			if ((pip->i_d.di_flags & XFS_DIFLAG_NODUMP) &&
    -			    xfs_inherit_nodump)
    -				di_flags |= XFS_DIFLAG_NODUMP;
    -			if ((pip->i_d.di_flags & XFS_DIFLAG_SYNC) &&
    -			    xfs_inherit_sync)
    -				di_flags |= XFS_DIFLAG_SYNC;
    -			if ((pip->i_d.di_flags & XFS_DIFLAG_NOSYMLINKS) &&
    -			    xfs_inherit_nosymlinks)
    -				di_flags |= XFS_DIFLAG_NOSYMLINKS;
    -			if (pip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
    -				di_flags |= XFS_DIFLAG_PROJINHERIT;
    -			ip->i_d.di_flags |= di_flags;
    -		}
    -		/* FALLTHROUGH */
    -	case S_IFLNK:
    -		ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS;
    -		ip->i_df.if_flags = XFS_IFEXTENTS;
    -		ip->i_df.if_bytes = ip->i_df.if_real_bytes = 0;
    -		ip->i_df.if_u1.if_extents = NULL;
    -		break;
    -	default:
    -		ASSERT(0);
    -	}
    -	/*
    -	 * Attribute fork settings for new inode.
    -	 */
    -	ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
    -	ip->i_d.di_anextents = 0;
    -
    -	/*
    -	 * Log the new values stuffed into the inode.
    -	 */
    -	xfs_trans_log_inode(tp, ip, flags);
    -
    -	/* now that we have an i_mode  we can set Linux inode ops (& unlock) */
    -	XVFS_INIT_VNODE(XFS_MTOVFS(tp->t_mountp), vp, XFS_ITOBHV(ip), 1);
    -
    -	*ipp = ip;
    -	return 0;
    -}
    -
    -/*
    - * Check to make sure that there are no blocks allocated to the
    - * file beyond the size of the file.  We don't check this for
    - * files with fixed size extents or real time extents, but we
    - * at least do it for regular files.
    - */
    -#ifdef DEBUG
    -void
    -xfs_isize_check(
    -	xfs_mount_t	*mp,
    -	xfs_inode_t	*ip,
    -	xfs_fsize_t	isize)
    -{
    -	xfs_fileoff_t	map_first;
    -	int		nimaps;
    -	xfs_bmbt_irec_t	imaps[2];
    -
    -	if ((ip->i_d.di_mode & S_IFMT) != S_IFREG)
    -		return;
    -
    -	if (ip->i_d.di_flags & (XFS_DIFLAG_REALTIME | XFS_DIFLAG_EXTSIZE))
    -		return;
    -
    -	nimaps = 2;
    -	map_first = XFS_B_TO_FSB(mp, (xfs_ufsize_t)isize);
    -	/*
    -	 * The filesystem could be shutting down, so bmapi may return
    -	 * an error.
    -	 */
    -	if (xfs_bmapi(NULL, ip, map_first,
    -			 (XFS_B_TO_FSB(mp,
    -				       (xfs_ufsize_t)XFS_MAXIOFFSET(mp)) -
    -			  map_first),
    -			 XFS_BMAPI_ENTIRE, NULL, 0, imaps, &nimaps,
    -			 NULL, NULL))
    -	    return;
    -	ASSERT(nimaps == 1);
    -	ASSERT(imaps[0].br_startblock == HOLESTARTBLOCK);
    -}
    -#endif	/* DEBUG */
    -
    -/*
    - * Calculate the last possible buffered byte in a file.  This must
    - * include data that was buffered beyond the EOF by the write code.
    - * This also needs to deal with overflowing the xfs_fsize_t type
    - * which can happen for sizes near the limit.
    - *
    - * We also need to take into account any blocks beyond the EOF.  It
    - * may be the case that they were buffered by a write which failed.
    - * In that case the pages will still be in memory, but the inode size
    - * will never have been updated.
    - */
    -xfs_fsize_t
    -xfs_file_last_byte(
    -	xfs_inode_t	*ip)
    -{
    -	xfs_mount_t	*mp;
    -	xfs_fsize_t	last_byte;
    -	xfs_fileoff_t	last_block;
    -	xfs_fileoff_t	size_last_block;
    -	int		error;
    -
    -	ASSERT(ismrlocked(&(ip->i_iolock), MR_UPDATE | MR_ACCESS));
    -
    -	mp = ip->i_mount;
    -	/*
    -	 * Only check for blocks beyond the EOF if the extents have
    -	 * been read in.  This eliminates the need for the inode lock,
    -	 * and it also saves us from looking when it really isn't
    -	 * necessary.
    -	 */
    -	if (ip->i_df.if_flags & XFS_IFEXTENTS) {
    -		error = xfs_bmap_last_offset(NULL, ip, &last_block,
    -			XFS_DATA_FORK);
    -		if (error) {
    -			last_block = 0;
    -		}
    -	} else {
    -		last_block = 0;
    -	}
    -	size_last_block = XFS_B_TO_FSB(mp, (xfs_ufsize_t)ip->i_d.di_size);
    -	last_block = XFS_FILEOFF_MAX(last_block, size_last_block);
    -
    -	last_byte = XFS_FSB_TO_B(mp, last_block);
    -	if (last_byte < 0) {
    -		return XFS_MAXIOFFSET(mp);
    -	}
    -	last_byte += (1 << mp->m_writeio_log);
    -	if (last_byte < 0) {
    -		return XFS_MAXIOFFSET(mp);
    -	}
    -	return last_byte;
    -}
    -
    -#if defined(XFS_RW_TRACE)
    -STATIC void
    -xfs_itrunc_trace(
    -	int		tag,
    -	xfs_inode_t	*ip,
    -	int		flag,
    -	xfs_fsize_t	new_size,
    -	xfs_off_t	toss_start,
    -	xfs_off_t	toss_finish)
    -{
    -	if (ip->i_rwtrace == NULL) {
    -		return;
    -	}
    -
    -	ktrace_enter(ip->i_rwtrace,
    -		     (void*)((long)tag),
    -		     (void*)ip,
    -		     (void*)(unsigned long)((ip->i_d.di_size >> 32) & 0xffffffff),
    -		     (void*)(unsigned long)(ip->i_d.di_size & 0xffffffff),
    -		     (void*)((long)flag),
    -		     (void*)(unsigned long)((new_size >> 32) & 0xffffffff),
    -		     (void*)(unsigned long)(new_size & 0xffffffff),
    -		     (void*)(unsigned long)((toss_start >> 32) & 0xffffffff),
    -		     (void*)(unsigned long)(toss_start & 0xffffffff),
    -		     (void*)(unsigned long)((toss_finish >> 32) & 0xffffffff),
    -		     (void*)(unsigned long)(toss_finish & 0xffffffff),
    -		     (void*)(unsigned long)current_cpu(),
    -		     (void*)(unsigned long)current_pid(),
    -		     (void*)NULL,
    -		     (void*)NULL,
    -		     (void*)NULL);
    -}
    -#else
    -#define	xfs_itrunc_trace(tag, ip, flag, new_size, toss_start, toss_finish)
    -#endif
    -
    -/*
    - * Start the truncation of the file to new_size.  The new size
    - * must be smaller than the current size.  This routine will
    - * clear the buffer and page caches of file data in the removed
    - * range, and xfs_itruncate_finish() will remove the underlying
    - * disk blocks.
    - *
    - * The inode must have its I/O lock locked EXCLUSIVELY, and it
    - * must NOT have the inode lock held at all.  This is because we're
    - * calling into the buffer/page cache code and we can't hold the
    - * inode lock when we do so.
    - *
    - * We need to wait for any direct I/Os in flight to complete before we
    - * proceed with the truncate. This is needed to prevent the extents
    - * being read or written by the direct I/Os from being removed while the
    - * I/O is in flight as there is no other method of synchronising
    - * direct I/O with the truncate operation.  Also, because we hold
    - * the IOLOCK in exclusive mode, we prevent new direct I/Os from being
    - * started until the truncate completes and drops the lock. Essentially,
    - * the vn_iowait() call forms an I/O barrier that provides strict ordering
    - * between direct I/Os and the truncate operation.
    - *
    - * The flags parameter can have either the value XFS_ITRUNC_DEFINITE
    - * or XFS_ITRUNC_MAYBE.  The XFS_ITRUNC_MAYBE value should be used
    - * in the case that the caller is locking things out of order and
    - * may not be able to call xfs_itruncate_finish() with the inode lock
    - * held without dropping the I/O lock.  If the caller must drop the
    - * I/O lock before calling xfs_itruncate_finish(), then xfs_itruncate_start()
    - * must be called again with all the same restrictions as the initial
    - * call.
    - */
    -void
    -xfs_itruncate_start(
    -	xfs_inode_t	*ip,
    -	uint		flags,
    -	xfs_fsize_t	new_size)
    -{
    -	xfs_fsize_t	last_byte;
    -	xfs_off_t	toss_start;
    -	xfs_mount_t	*mp;
    -	xfs_vnode_t	*vp;
    -
    -	ASSERT(ismrlocked(&ip->i_iolock, MR_UPDATE) != 0);
    -	ASSERT((new_size == 0) || (new_size <= ip->i_d.di_size));
    -	ASSERT((flags == XFS_ITRUNC_DEFINITE) ||
    -	       (flags == XFS_ITRUNC_MAYBE));
    -
    -	mp = ip->i_mount;
    -	vp = XFS_ITOV(ip);
    -
    -	vn_iowait(vp);  /* wait for the completion of any pending DIOs */
    -
    -	/*
    -	 * Call VOP_TOSS_PAGES() or VOP_FLUSHINVAL_PAGES() to get rid of pages and buffers
    -	 * overlapping the region being removed.  We have to use
    -	 * the less efficient VOP_FLUSHINVAL_PAGES() in the case that the
    -	 * caller may not be able to finish the truncate without
    -	 * dropping the inode's I/O lock.  Make sure
    -	 * to catch any pages brought in by buffers overlapping
    -	 * the EOF by searching out beyond the isize by our
    -	 * block size. We round new_size up to a block boundary
    -	 * so that we don't toss things on the same block as
    -	 * new_size but before it.
    -	 *
    -	 * Before calling VOP_TOSS_PAGES() or VOP_FLUSHINVAL_PAGES(), make sure to
    -	 * call remapf() over the same region if the file is mapped.
    -	 * This frees up mapped file references to the pages in the
    -	 * given range and for the VOP_FLUSHINVAL_PAGES() case it ensures
    -	 * that we get the latest mapped changes flushed out.
    -	 */
    -	toss_start = XFS_B_TO_FSB(mp, (xfs_ufsize_t)new_size);
    -	toss_start = XFS_FSB_TO_B(mp, toss_start);
    -	if (toss_start < 0) {
    -		/*
    -		 * The place to start tossing is beyond our maximum
    -		 * file size, so there is no way that the data extended
    -		 * out there.
    -		 */
    -		return;
    -	}
    -	last_byte = xfs_file_last_byte(ip);
    -	xfs_itrunc_trace(XFS_ITRUNC_START, ip, flags, new_size, toss_start,
    -			 last_byte);
    -	if (last_byte > toss_start) {
    -		if (flags & XFS_ITRUNC_DEFINITE) {
    -			XVOP_TOSS_PAGES(vp, toss_start, -1, FI_REMAPF_LOCKED);
    -		} else {
    -			XVOP_FLUSHINVAL_PAGES(vp, toss_start, -1, FI_REMAPF_LOCKED);
    -		}
    -	}
    -
    -#ifdef DEBUG
    -	if (new_size == 0) {
    -		ASSERT(VN_CACHED(vp) == 0);
    -	}
    -#endif
    -}
    -
    -/*
    - * Shrink the file to the given new_size.  The new
    - * size must be smaller than the current size.
    - * This will free up the underlying blocks
    - * in the removed range after a call to xfs_itruncate_start()
    - * or xfs_atruncate_start().
    - *
    - * The transaction passed to this routine must have made
    - * a permanent log reservation of at least XFS_ITRUNCATE_LOG_RES.
    - * This routine may commit the given transaction and
    - * start new ones, so make sure everything involved in
    - * the transaction is tidy before calling here.
    - * Some transaction will be returned to the caller to be
    - * committed.  The incoming transaction must already include
    - * the inode, and both inode locks must be held exclusively.
    - * The inode must also be "held" within the transaction.  On
    - * return the inode will be "held" within the returned transaction.
    - * This routine does NOT require any disk space to be reserved
    - * for it within the transaction.
    - *
    - * The fork parameter must be either xfs_attr_fork or xfs_data_fork,
    - * and it indicates the fork which is to be truncated.  For the
    - * attribute fork we only support truncation to size 0.
    - *
    - * We use the sync parameter to indicate whether or not the first
    - * transaction we perform might have to be synchronous.  For the attr fork,
    - * it needs to be so if the unlink of the inode is not yet known to be
    - * permanent in the log.  This keeps us from freeing and reusing the
    - * blocks of the attribute fork before the unlink of the inode becomes
    - * permanent.
    - *
    - * For the data fork, we normally have to run synchronously if we're
    - * being called out of the inactive path or we're being called
    - * out of the create path where we're truncating an existing file.
    - * Either way, the truncate needs to be sync so blocks don't reappear
    - * in the file with altered data in case of a crash.  wsync filesystems
    - * can run the first case async because anything that shrinks the inode
    - * has to run sync so by the time we're called here from inactive, the
    - * inode size is permanently set to 0.
    - *
    - * Calls from the truncate path always need to be sync unless we're
    - * in a wsync filesystem and the file has already been unlinked.
    - *
    - * The caller is responsible for correctly setting the sync parameter.
    - * It gets too hard for us to guess here which path we're being called
    - * out of just based on inode state.
    - */
    -int
    -xfs_itruncate_finish(
    -	xfs_trans_t	**tp,
    -	xfs_inode_t	*ip,
    -	xfs_fsize_t	new_size,
    -	int		fork,
    -	int		sync)
    -{
    -	xfs_fsblock_t	first_block;
    -	xfs_fileoff_t	first_unmap_block;
    -	xfs_fileoff_t	last_block;
    -	xfs_filblks_t	unmap_len=0;
    -	xfs_mount_t	*mp;
    -	xfs_trans_t	*ntp;
    -	int		done;
    -	int		committed;
    -	xfs_bmap_free_t	free_list;
    -	int		error;
    -
    -	ASSERT(ismrlocked(&ip->i_iolock, MR_UPDATE) != 0);
    -	ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE) != 0);
    -	ASSERT((new_size == 0) || (new_size <= ip->i_d.di_size));
    -	ASSERT(*tp != NULL);
    -	ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES);
    -	ASSERT(ip->i_transp == *tp);
    -	ASSERT(ip->i_itemp != NULL);
    -	ASSERT(ip->i_itemp->ili_flags & XFS_ILI_HOLD);
    -
    -
    -	ntp = *tp;
    -	mp = (ntp)->t_mountp;
    -	ASSERT(! XFS_NOT_DQATTACHED(mp, ip));
    -
    -	/*
    -	 * We only support truncating the entire attribute fork.
    -	 */
    -	if (fork == XFS_ATTR_FORK) {
    -		new_size = 0LL;
    -	}
    -	first_unmap_block = XFS_B_TO_FSB(mp, (xfs_ufsize_t)new_size);
    -	xfs_itrunc_trace(XFS_ITRUNC_FINISH1, ip, 0, new_size, 0, 0);
    -	/*
    -	 * The first thing we do is set the size to new_size permanently
    -	 * on disk.  This way we don't have to worry about anyone ever
    -	 * being able to look at the data being freed even in the face
    -	 * of a crash.  What we're getting around here is the case where
    -	 * we free a block, it is allocated to another file, it is written
    -	 * to, and then we crash.  If the new data gets written to the
    -	 * file but the log buffers containing the free and reallocation
    -	 * don't, then we'd end up with garbage in the blocks being freed.
    -	 * As long as we make the new_size permanent before actually
    -	 * freeing any blocks it doesn't matter if they get writtten to.
    -	 *
    -	 * The callers must signal into us whether or not the size
    -	 * setting here must be synchronous.  There are a few cases
    -	 * where it doesn't have to be synchronous.  Those cases
    -	 * occur if the file is unlinked and we know the unlink is
    -	 * permanent or if the blocks being truncated are guaranteed
    -	 * to be beyond the inode eof (regardless of the link count)
    -	 * and the eof value is permanent.  Both of these cases occur
    -	 * only on wsync-mounted filesystems.  In those cases, we're
    -	 * guaranteed that no user will ever see the data in the blocks
    -	 * that are being truncated so the truncate can run async.
    -	 * In the free beyond eof case, the file may wind up with
    -	 * more blocks allocated to it than it needs if we crash
    -	 * and that won't get fixed until the next time the file
    -	 * is re-opened and closed but that's ok as that shouldn't
    -	 * be too many blocks.
    -	 *
    -	 * However, we can't just make all wsync xactions run async
    -	 * because there's one call out of the create path that needs
    -	 * to run sync where it's truncating an existing file to size
    -	 * 0 whose size is > 0.
    -	 *
    -	 * It's probably possible to come up with a test in this
    -	 * routine that would correctly distinguish all the above
    -	 * cases from the values of the function parameters and the
    -	 * inode state but for sanity's sake, I've decided to let the
    -	 * layers above just tell us.  It's simpler to correctly figure
    -	 * out in the layer above exactly under what conditions we
    -	 * can run async and I think it's easier for others read and
    -	 * follow the logic in case something has to be changed.
    -	 * cscope is your friend -- rcc.
    -	 *
    -	 * The attribute fork is much simpler.
    -	 *
    -	 * For the attribute fork we allow the caller to tell us whether
    -	 * the unlink of the inode that led to this call is yet permanent
    -	 * in the on disk log.  If it is not and we will be freeing extents
    -	 * in this inode then we make the first transaction synchronous
    -	 * to make sure that the unlink is permanent by the time we free
    -	 * the blocks.
    -	 */
    -	if (fork == XFS_DATA_FORK) {
    -		if (ip->i_d.di_nextents > 0) {
    -			ip->i_d.di_size = new_size;
    -			xfs_trans_log_inode(ntp, ip, XFS_ILOG_CORE);
    -		}
    -	} else if (sync) {
    -		ASSERT(!(mp->m_flags & XFS_MOUNT_WSYNC));
    -		if (ip->i_d.di_anextents > 0)
    -			xfs_trans_set_sync(ntp);
    -	}
    -	ASSERT(fork == XFS_DATA_FORK ||
    -		(fork == XFS_ATTR_FORK &&
    -			((sync && !(mp->m_flags & XFS_MOUNT_WSYNC)) ||
    -			 (sync == 0 && (mp->m_flags & XFS_MOUNT_WSYNC)))));
    -
    -	/*
    -	 * Since it is possible for space to become allocated beyond
    -	 * the end of the file (in a crash where the space is allocated
    -	 * but the inode size is not yet updated), simply remove any
    -	 * blocks which show up between the new EOF and the maximum
    -	 * possible file size.  If the first block to be removed is
    -	 * beyond the maximum file size (ie it is the same as last_block),
    -	 * then there is nothing to do.
    -	 */
    -	last_block = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp));
    -	ASSERT(first_unmap_block <= last_block);
    -	done = 0;
    -	if (last_block == first_unmap_block) {
    -		done = 1;
    -	} else {
    -		unmap_len = last_block - first_unmap_block + 1;
    -	}
    -	while (!done) {
    -		/*
    -		 * Free up up to XFS_ITRUNC_MAX_EXTENTS.  xfs_bunmapi()
    -		 * will tell us whether it freed the entire range or
    -		 * not.  If this is a synchronous mount (wsync),
    -		 * then we can tell bunmapi to keep all the
    -		 * transactions asynchronous since the unlink
    -		 * transaction that made this inode inactive has
    -		 * already hit the disk.  There's no danger of
    -		 * the freed blocks being reused, there being a
    -		 * crash, and the reused blocks suddenly reappearing
    -		 * in this file with garbage in them once recovery
    -		 * runs.
    -		 */
    -		XFS_BMAP_INIT(&free_list, &first_block);
    -		error = XFS_BUNMAPI(mp, ntp, &ip->i_iocore,
    -				    first_unmap_block, unmap_len,
    -				    XFS_BMAPI_AFLAG(fork) |
    -				      (sync ? 0 : XFS_BMAPI_ASYNC),
    -				    XFS_ITRUNC_MAX_EXTENTS,
    -				    &first_block, &free_list,
    -				    NULL, &done);
    -		if (error) {
    -			/*
    -			 * If the bunmapi call encounters an error,
    -			 * return to the caller where the transaction
    -			 * can be properly aborted.  We just need to
    -			 * make sure we're not holding any resources
    -			 * that we were not when we came in.
    -			 */
    -			xfs_bmap_cancel(&free_list);
    -			return error;
    -		}
    -
    -		/*
    -		 * Duplicate the transaction that has the permanent
    -		 * reservation and commit the old transaction.
    -		 */
    -		error = xfs_bmap_finish(tp, &free_list, first_block,
    -					&committed);
    -		ntp = *tp;
    -		if (error) {
    -			/*
    -			 * If the bmap finish call encounters an error,
    -			 * return to the caller where the transaction
    -			 * can be properly aborted.  We just need to
    -			 * make sure we're not holding any resources
    -			 * that we were not when we came in.
    -			 *
    -			 * Aborting from this point might lose some
    -			 * blocks in the file system, but oh well.
    -			 */
    -			xfs_bmap_cancel(&free_list);
    -			if (committed) {
    -				/*
    -				 * If the passed in transaction committed
    -				 * in xfs_bmap_finish(), then we want to
    -				 * add the inode to this one before returning.
    -				 * This keeps things simple for the higher
    -				 * level code, because it always knows that
    -				 * the inode is locked and held in the
    -				 * transaction that returns to it whether
    -				 * errors occur or not.  We don't mark the
    -				 * inode dirty so that this transaction can
    -				 * be easily aborted if possible.
    -				 */
    -				xfs_trans_ijoin(ntp, ip,
    -					XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
    -				xfs_trans_ihold(ntp, ip);
    -			}
    -			return error;
    -		}
    -
    -		if (committed) {
    -			/*
    -			 * The first xact was committed,
    -			 * so add the inode to the new one.
    -			 * Mark it dirty so it will be logged
    -			 * and moved forward in the log as
    -			 * part of every commit.
    -			 */
    -			xfs_trans_ijoin(ntp, ip,
    -					XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
    -			xfs_trans_ihold(ntp, ip);
    -			xfs_trans_log_inode(ntp, ip, XFS_ILOG_CORE);
    -		}
    -		ntp = xfs_trans_dup(ntp);
    -		(void) xfs_trans_commit(*tp, 0, NULL);
    -		*tp = ntp;
    -		error = xfs_trans_reserve(ntp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0,
    -					  XFS_TRANS_PERM_LOG_RES,
    -					  XFS_ITRUNCATE_LOG_COUNT);
    -		/*
    -		 * Add the inode being truncated to the next chained
    -		 * transaction.
    -		 */
    -		xfs_trans_ijoin(ntp, ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
    -		xfs_trans_ihold(ntp, ip);
    -		if (error)
    -			return (error);
    -	}
    -	/*
    -	 * Only update the size in the case of the data fork, but
    -	 * always re-log the inode so that our permanent transaction
    -	 * can keep on rolling it forward in the log.
    -	 */
    -	if (fork == XFS_DATA_FORK) {
    -		xfs_isize_check(mp, ip, new_size);
    -		ip->i_d.di_size = new_size;
    -	}
    -	xfs_trans_log_inode(ntp, ip, XFS_ILOG_CORE);
    -	ASSERT((new_size != 0) ||
    -	       (fork == XFS_ATTR_FORK) ||
    -	       (ip->i_delayed_blks == 0));
    -	ASSERT((new_size != 0) ||
    -	       (fork == XFS_ATTR_FORK) ||
    -	       (ip->i_d.di_nextents == 0));
    -	xfs_itrunc_trace(XFS_ITRUNC_FINISH2, ip, 0, new_size, 0, 0);
    -	return 0;
    -}
    -
    -
    -/*
    - * xfs_igrow_start
    - *
    - * Do the first part of growing a file: zero any data in the last
    - * block that is beyond the old EOF.  We need to do this before
    - * the inode is joined to the transaction to modify the i_size.
    - * That way we can drop the inode lock and call into the buffer
    - * cache to get the buffer mapping the EOF.
    - */
    -int
    -xfs_igrow_start(
    -	xfs_inode_t	*ip,
    -	xfs_fsize_t	new_size,
    -	cred_t		*credp)
    -{
    -	int		error;
    -
    -	ASSERT(ismrlocked(&(ip->i_lock), MR_UPDATE) != 0);
    -	ASSERT(ismrlocked(&(ip->i_iolock), MR_UPDATE) != 0);
    -	ASSERT(new_size > ip->i_d.di_size);
    -
    -	/*
    -	 * Zero any pages that may have been created by
    -	 * xfs_write_file() beyond the end of the file
    -	 * and any blocks between the old and new file sizes.
    -	 */
    -	error = xfs_zero_eof(XFS_ITOV(ip), &ip->i_iocore, new_size,
    -			     ip->i_d.di_size, new_size);
    -	return error;
    -}
    -
    -/*
    - * xfs_igrow_finish
    - *
    - * This routine is called to extend the size of a file.
    - * The inode must have both the iolock and the ilock locked
    - * for update and it must be a part of the current transaction.
    - * The xfs_igrow_start() function must have been called previously.
    - * If the change_flag is not zero, the inode change timestamp will
    - * be updated.
    - */
    -void
    -xfs_igrow_finish(
    -	xfs_trans_t	*tp,
    -	xfs_inode_t	*ip,
    -	xfs_fsize_t	new_size,
    -	int		change_flag)
    -{
    -	ASSERT(ismrlocked(&(ip->i_lock), MR_UPDATE) != 0);
    -	ASSERT(ismrlocked(&(ip->i_iolock), MR_UPDATE) != 0);
    -	ASSERT(ip->i_transp == tp);
    -	ASSERT(new_size > ip->i_d.di_size);
    -
    -	/*
    -	 * Update the file size.  Update the inode change timestamp
    -	 * if change_flag set.
    -	 */
    -	ip->i_d.di_size = new_size;
    -	if (change_flag)
    -		xfs_ichgtime(ip, XFS_ICHGTIME_CHG);
    -	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
    -
    -}
    -
    -
    -/*
    - * This is called when the inode's link count goes to 0.
    - * We place the on-disk inode on a list in the AGI.  It
    - * will be pulled from this list when the inode is freed.
    - */
    -int
    -xfs_iunlink(
    -	xfs_trans_t	*tp,
    -	xfs_inode_t	*ip)
    -{
    -	xfs_mount_t	*mp;
    -	xfs_agi_t	*agi;
    -	xfs_dinode_t	*dip;
    -	xfs_buf_t	*agibp;
    -	xfs_buf_t	*ibp;
    -	xfs_agnumber_t	agno;
    -	xfs_daddr_t	agdaddr;
    -	xfs_agino_t	agino;
    -	short		bucket_index;
    -	int		offset;
    -	int		error;
    -	int		agi_ok;
    -
    -	ASSERT(ip->i_d.di_nlink == 0);
    -	ASSERT(ip->i_d.di_mode != 0);
    -	ASSERT(ip->i_transp == tp);
    -
    -	mp = tp->t_mountp;
    -
    -	agno = XFS_INO_TO_AGNO(mp, ip->i_ino);
    -	agdaddr = XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp));
    -
    -	/*
    -	 * Get the agi buffer first.  It ensures lock ordering
    -	 * on the list.
    -	 */
    -	error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, agdaddr,
    -				   XFS_FSS_TO_BB(mp, 1), 0, &agibp);
    -	if (error) {
    -		return error;
    -	}
    -	/*
    -	 * Validate the magic number of the agi block.
    -	 */
    -	agi = XFS_BUF_TO_AGI(agibp);
    -	agi_ok =
    -		be32_to_cpu(agi->agi_magicnum) == XFS_AGI_MAGIC &&
    -		XFS_AGI_GOOD_VERSION(be32_to_cpu(agi->agi_versionnum));
    -	if (unlikely(XFS_TEST_ERROR(!agi_ok, mp, XFS_ERRTAG_IUNLINK,
    -			XFS_RANDOM_IUNLINK))) {
    -		XFS_CORRUPTION_ERROR("xfs_iunlink", XFS_ERRLEVEL_LOW, mp, agi);
    -		xfs_trans_brelse(tp, agibp);
    -		return XFS_ERROR(EFSCORRUPTED);
    -	}
    -	/*
    -	 * Get the index into the agi hash table for the
    -	 * list this inode will go on.
    -	 */
    -	agino = XFS_INO_TO_AGINO(mp, ip->i_ino);
    -	ASSERT(agino != 0);
    -	bucket_index = agino % XFS_AGI_UNLINKED_BUCKETS;
    -	ASSERT(agi->agi_unlinked[bucket_index]);
    -	ASSERT(be32_to_cpu(agi->agi_unlinked[bucket_index]) != agino);
    -
    -	if (be32_to_cpu(agi->agi_unlinked[bucket_index]) != NULLAGINO) {
    -		/*
    -		 * There is already another inode in the bucket we need
    -		 * to add ourselves to.  Add us at the front of the list.
    -		 * Here we put the head pointer into our next pointer,
    -		 * and then we fall through to point the head at us.
    -		 */
    -		error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0);
    -		if (error) {
    -			return error;
    -		}
    -		ASSERT(INT_GET(dip->di_next_unlinked, ARCH_CONVERT) == NULLAGINO);
    -		ASSERT(dip->di_next_unlinked);
    -		/* both on-disk, don't endian flip twice */
    -		dip->di_next_unlinked = agi->agi_unlinked[bucket_index];
    -		offset = ip->i_boffset +
    -			offsetof(xfs_dinode_t, di_next_unlinked);
    -		xfs_trans_inode_buf(tp, ibp);
    -		xfs_trans_log_buf(tp, ibp, offset,
    -				  (offset + sizeof(xfs_agino_t) - 1));
    -		xfs_inobp_check(mp, ibp);
    -	}
    -
    -	/*
    -	 * Point the bucket head pointer at the inode being inserted.
    -	 */
    -	ASSERT(agino != 0);
    -	agi->agi_unlinked[bucket_index] = cpu_to_be32(agino);
    -	offset = offsetof(xfs_agi_t, agi_unlinked) +
    -		(sizeof(xfs_agino_t) * bucket_index);
    -	xfs_trans_log_buf(tp, agibp, offset,
    -			  (offset + sizeof(xfs_agino_t) - 1));
    -	return 0;
    -}
    -
    -/*
    - * Pull the on-disk inode from the AGI unlinked list.
    - */
    -STATIC int
    -xfs_iunlink_remove(
    -	xfs_trans_t	*tp,
    -	xfs_inode_t	*ip)
    -{
    -	xfs_ino_t	next_ino;
    -	xfs_mount_t	*mp;
    -	xfs_agi_t	*agi;
    -	xfs_dinode_t	*dip;
    -	xfs_buf_t	*agibp;
    -	xfs_buf_t	*ibp;
    -	xfs_agnumber_t	agno;
    -	xfs_daddr_t	agdaddr;
    -	xfs_agino_t	agino;
    -	xfs_agino_t	next_agino;
    -	xfs_buf_t	*last_ibp;
    -	xfs_dinode_t	*last_dip = NULL;
    -	short		bucket_index;
    -	int		offset, last_offset = 0;
    -	int		error;
    -	int		agi_ok;
    -
    -	/*
    -	 * First pull the on-disk inode from the AGI unlinked list.
    -	 */
    -	mp = tp->t_mountp;
    -
    -	agno = XFS_INO_TO_AGNO(mp, ip->i_ino);
    -	agdaddr = XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp));
    -
    -	/*
    -	 * Get the agi buffer first.  It ensures lock ordering
    -	 * on the list.
    -	 */
    -	error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, agdaddr,
    -				   XFS_FSS_TO_BB(mp, 1), 0, &agibp);
    -	if (error) {
    -		cmn_err(CE_WARN,
    -			"xfs_iunlink_remove: xfs_trans_read_buf()  returned an error %d on %s.  Returning error.",
    -			error, mp->m_fsname);
    -		return error;
    -	}
    -	/*
    -	 * Validate the magic number of the agi block.
    -	 */
    -	agi = XFS_BUF_TO_AGI(agibp);
    -	agi_ok =
    -		be32_to_cpu(agi->agi_magicnum) == XFS_AGI_MAGIC &&
    -		XFS_AGI_GOOD_VERSION(be32_to_cpu(agi->agi_versionnum));
    -	if (unlikely(XFS_TEST_ERROR(!agi_ok, mp, XFS_ERRTAG_IUNLINK_REMOVE,
    -			XFS_RANDOM_IUNLINK_REMOVE))) {
    -		XFS_CORRUPTION_ERROR("xfs_iunlink_remove", XFS_ERRLEVEL_LOW,
    -				     mp, agi);
    -		xfs_trans_brelse(tp, agibp);
    -		cmn_err(CE_WARN,
    -			"xfs_iunlink_remove: XFS_TEST_ERROR()  returned an error on %s.  Returning EFSCORRUPTED.",
    -			 mp->m_fsname);
    -		return XFS_ERROR(EFSCORRUPTED);
    -	}
    -	/*
    -	 * Get the index into the agi hash table for the
    -	 * list this inode will go on.
    -	 */
    -	agino = XFS_INO_TO_AGINO(mp, ip->i_ino);
    -	ASSERT(agino != 0);
    -	bucket_index = agino % XFS_AGI_UNLINKED_BUCKETS;
    -	ASSERT(be32_to_cpu(agi->agi_unlinked[bucket_index]) != NULLAGINO);
    -	ASSERT(agi->agi_unlinked[bucket_index]);
    -
    -	if (be32_to_cpu(agi->agi_unlinked[bucket_index]) == agino) {
    -		/*
    -		 * We're at the head of the list.  Get the inode's
    -		 * on-disk buffer to see if there is anyone after us
    -		 * on the list.  Only modify our next pointer if it
    -		 * is not already NULLAGINO.  This saves us the overhead
    -		 * of dealing with the buffer when there is no need to
    -		 * change it.
    -		 */
    -		error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0);
    -		if (error) {
    -			cmn_err(CE_WARN,
    -				"xfs_iunlink_remove: xfs_itobp()  returned an error %d on %s.  Returning error.",
    -				error, mp->m_fsname);
    -			return error;
    -		}
    -		next_agino = INT_GET(dip->di_next_unlinked, ARCH_CONVERT);
    -		ASSERT(next_agino != 0);
    -		if (next_agino != NULLAGINO) {
    -			INT_SET(dip->di_next_unlinked, ARCH_CONVERT, NULLAGINO);
    -			offset = ip->i_boffset +
    -				offsetof(xfs_dinode_t, di_next_unlinked);
    -			xfs_trans_inode_buf(tp, ibp);
    -			xfs_trans_log_buf(tp, ibp, offset,
    -					  (offset + sizeof(xfs_agino_t) - 1));
    -			xfs_inobp_check(mp, ibp);
    -		} else {
    -			xfs_trans_brelse(tp, ibp);
    -		}
    -		/*
    -		 * Point the bucket head pointer at the next inode.
    -		 */
    -		ASSERT(next_agino != 0);
    -		ASSERT(next_agino != agino);
    -		agi->agi_unlinked[bucket_index] = cpu_to_be32(next_agino);
    -		offset = offsetof(xfs_agi_t, agi_unlinked) +
    -			(sizeof(xfs_agino_t) * bucket_index);
    -		xfs_trans_log_buf(tp, agibp, offset,
    -				  (offset + sizeof(xfs_agino_t) - 1));
    -	} else {
    -		/*
    -		 * We need to search the list for the inode being freed.
    -		 */
    -		next_agino = be32_to_cpu(agi->agi_unlinked[bucket_index]);
    -		last_ibp = NULL;
    -		while (next_agino != agino) {
    -			/*
    -			 * If the last inode wasn't the one pointing to
    -			 * us, then release its buffer since we're not
    -			 * going to do anything with it.
    -			 */
    -			if (last_ibp != NULL) {
    -				xfs_trans_brelse(tp, last_ibp);
    -			}
    -			next_ino = XFS_AGINO_TO_INO(mp, agno, next_agino);
    -			error = xfs_inotobp(mp, tp, next_ino, &last_dip,
    -					    &last_ibp, &last_offset);
    -			if (error) {
    -				cmn_err(CE_WARN,
    -			"xfs_iunlink_remove: xfs_inotobp()  returned an error %d on %s.  Returning error.",
    -					error, mp->m_fsname);
    -				return error;
    -			}
    -			next_agino = INT_GET(last_dip->di_next_unlinked, ARCH_CONVERT);
    -			ASSERT(next_agino != NULLAGINO);
    -			ASSERT(next_agino != 0);
    -		}
    -		/*
    -		 * Now last_ibp points to the buffer previous to us on
    -		 * the unlinked list.  Pull us from the list.
    -		 */
    -		error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0);
    -		if (error) {
    -			cmn_err(CE_WARN,
    -				"xfs_iunlink_remove: xfs_itobp()  returned an error %d on %s.  Returning error.",
    -				error, mp->m_fsname);
    -			return error;
    -		}
    -		next_agino = INT_GET(dip->di_next_unlinked, ARCH_CONVERT);
    -		ASSERT(next_agino != 0);
    -		ASSERT(next_agino != agino);
    -		if (next_agino != NULLAGINO) {
    -			INT_SET(dip->di_next_unlinked, ARCH_CONVERT, NULLAGINO);
    -			offset = ip->i_boffset +
    -				offsetof(xfs_dinode_t, di_next_unlinked);
    -			xfs_trans_inode_buf(tp, ibp);
    -			xfs_trans_log_buf(tp, ibp, offset,
    -					  (offset + sizeof(xfs_agino_t) - 1));
    -			xfs_inobp_check(mp, ibp);
    -		} else {
    -			xfs_trans_brelse(tp, ibp);
    -		}
    -		/*
    -		 * Point the previous inode on the list to the next inode.
    -		 */
    -		INT_SET(last_dip->di_next_unlinked, ARCH_CONVERT, next_agino);
    -		ASSERT(next_agino != 0);
    -		offset = last_offset + offsetof(xfs_dinode_t, di_next_unlinked);
    -		xfs_trans_inode_buf(tp, last_ibp);
    -		xfs_trans_log_buf(tp, last_ibp, offset,
    -				  (offset + sizeof(xfs_agino_t) - 1));
    -		xfs_inobp_check(mp, last_ibp);
    -	}
    -	return 0;
    -}
    -
    -static __inline__ int xfs_inode_clean(xfs_inode_t *ip)
    -{
    -	return (((ip->i_itemp == NULL) ||
    -		!(ip->i_itemp->ili_format.ilf_fields & XFS_ILOG_ALL)) &&
    -		(ip->i_update_core == 0));
    -}
    -
    -STATIC void
    -xfs_ifree_cluster(
    -	xfs_inode_t	*free_ip,
    -	xfs_trans_t	*tp,
    -	xfs_ino_t	inum)
    -{
    -	xfs_mount_t		*mp = free_ip->i_mount;
    -	int			blks_per_cluster;
    -	int			nbufs;
    -	int			ninodes;
    -	int			i, j, found, pre_flushed;
    -	xfs_daddr_t		blkno;
    -	xfs_buf_t		*bp;
    -	xfs_ihash_t		*ih;
    -	xfs_inode_t		*ip, **ip_found;
    -	xfs_inode_log_item_t	*iip;
    -	xfs_log_item_t		*lip;
    -	SPLDECL(s);
    -
    -	if (mp->m_sb.sb_blocksize >= XFS_INODE_CLUSTER_SIZE(mp)) {
    -		blks_per_cluster = 1;
    -		ninodes = mp->m_sb.sb_inopblock;
    -		nbufs = XFS_IALLOC_BLOCKS(mp);
    -	} else {
    -		blks_per_cluster = XFS_INODE_CLUSTER_SIZE(mp) /
    -					mp->m_sb.sb_blocksize;
    -		ninodes = blks_per_cluster * mp->m_sb.sb_inopblock;
    -		nbufs = XFS_IALLOC_BLOCKS(mp) / blks_per_cluster;
    -	}
    -
    -	ip_found = kmem_alloc(ninodes * sizeof(xfs_inode_t *), KM_NOFS);
    -
    -	for (j = 0; j < nbufs; j++, inum += ninodes) {
    -		blkno = XFS_AGB_TO_DADDR(mp, XFS_INO_TO_AGNO(mp, inum),
    -					 XFS_INO_TO_AGBNO(mp, inum));
    -
    -
    -		/*
    -		 * Look for each inode in memory and attempt to lock it,
    -		 * we can be racing with flush and tail pushing here.
    -		 * any inode we get the locks on, add to an array of
    -		 * inode items to process later.
    -		 *
    -		 * The get the buffer lock, we could beat a flush
    -		 * or tail pushing thread to the lock here, in which
    -		 * case they will go looking for the inode buffer
    -		 * and fail, we need some other form of interlock
    -		 * here.
    -		 */
    -		found = 0;
    -		for (i = 0; i < ninodes; i++) {
    -			ih = XFS_IHASH(mp, inum + i);
    -			read_lock(&ih->ih_lock);
    -			for (ip = ih->ih_next; ip != NULL; ip = ip->i_next) {
    -				if (ip->i_ino == inum + i)
    -					break;
    -			}
    -
    -			/* Inode not in memory or we found it already,
    -			 * nothing to do
    -			 */
    -			if (!ip || (ip->i_flags & XFS_ISTALE)) {
    -				read_unlock(&ih->ih_lock);
    -				continue;
    -			}
    -
    -			if (xfs_inode_clean(ip)) {
    -				read_unlock(&ih->ih_lock);
    -				continue;
    -			}
    -
    -			/* If we can get the locks then add it to the
    -			 * list, otherwise by the time we get the bp lock
    -			 * below it will already be attached to the
    -			 * inode buffer.
    -			 */
    -
    -			/* This inode will already be locked - by us, lets
    -			 * keep it that way.
    -			 */
    -
    -			if (ip == free_ip) {
    -				if (xfs_iflock_nowait(ip)) {
    -					ip->i_flags |= XFS_ISTALE;
    -
    -					if (xfs_inode_clean(ip)) {
    -						xfs_ifunlock(ip);
    -					} else {
    -						ip_found[found++] = ip;
    -					}
    -				}
    -				read_unlock(&ih->ih_lock);
    -				continue;
    -			}
    -
    -			if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) {
    -				if (xfs_iflock_nowait(ip)) {
    -					ip->i_flags |= XFS_ISTALE;
    -
    -					if (xfs_inode_clean(ip)) {
    -						xfs_ifunlock(ip);
    -						xfs_iunlock(ip, XFS_ILOCK_EXCL);
    -					} else {
    -						ip_found[found++] = ip;
    -					}
    -				} else {
    -					xfs_iunlock(ip, XFS_ILOCK_EXCL);
    -				}
    -			}
    -
    -			read_unlock(&ih->ih_lock);
    -		}
    -
    -		bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, blkno, 
    -					mp->m_bsize * blks_per_cluster,
    -					XFS_BUF_LOCK);
    -
    -		pre_flushed = 0;
    -		lip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *);
    -		while (lip) {
    -			if (lip->li_type == XFS_LI_INODE) {
    -				iip = (xfs_inode_log_item_t *)lip;
    -				ASSERT(iip->ili_logged == 1);
    -				lip->li_cb = (void(*)(xfs_buf_t*,xfs_log_item_t*)) xfs_istale_done;
    -				AIL_LOCK(mp,s);
    -				iip->ili_flush_lsn = iip->ili_item.li_lsn;
    -				AIL_UNLOCK(mp, s);
    -				iip->ili_inode->i_flags |= XFS_ISTALE;
    -				pre_flushed++;
    -			}
    -			lip = lip->li_bio_list;
    -		}
    -
    -		for (i = 0; i < found; i++) {
    -			ip = ip_found[i];
    -			iip = ip->i_itemp;
    -
    -			if (!iip) {
    -				ip->i_update_core = 0;
    -				xfs_ifunlock(ip);
    -				xfs_iunlock(ip, XFS_ILOCK_EXCL);
    -				continue;
    -			}
    -
    -			iip->ili_last_fields = iip->ili_format.ilf_fields;
    -			iip->ili_format.ilf_fields = 0;
    -			iip->ili_logged = 1;
    -			AIL_LOCK(mp,s);
    -			iip->ili_flush_lsn = iip->ili_item.li_lsn;
    -			AIL_UNLOCK(mp, s);
    -
    -			xfs_buf_attach_iodone(bp,
    -				(void(*)(xfs_buf_t*,xfs_log_item_t*))
    -				xfs_istale_done, (xfs_log_item_t *)iip);
    -			if (ip != free_ip) {
    -				xfs_iunlock(ip, XFS_ILOCK_EXCL);
    -			}
    -		}
    -
    -		if (found || pre_flushed)
    -			xfs_trans_stale_inode_buf(tp, bp);
    -		xfs_trans_binval(tp, bp);
    -	}
    -
    -	kmem_free(ip_found, ninodes * sizeof(xfs_inode_t *));
    -}
    -
    -/*
    - * This is called to return an inode to the inode free list.
    - * The inode should already be truncated to 0 length and have
    - * no pages associated with it.  This routine also assumes that
    - * the inode is already a part of the transaction.
    - *
    - * The on-disk copy of the inode will have been added to the list
    - * of unlinked inodes in the AGI. We need to remove the inode from
    - * that list atomically with respect to freeing it here.
    - */
    -int
    -xfs_ifree(
    -	xfs_trans_t	*tp,
    -	xfs_inode_t	*ip,
    -	xfs_bmap_free_t	*flist)
    -{
    -	int			error;
    -	int			delete;
    -	xfs_ino_t		first_ino;
    -
    -	ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
    -	ASSERT(ip->i_transp == tp);
    -	ASSERT(ip->i_d.di_nlink == 0);
    -	ASSERT(ip->i_d.di_nextents == 0);
    -	ASSERT(ip->i_d.di_anextents == 0);
    -	ASSERT((ip->i_d.di_size == 0) ||
    -	       ((ip->i_d.di_mode & S_IFMT) != S_IFREG));
    -	ASSERT(ip->i_d.di_nblocks == 0);
    -
    -	/*
    -	 * Pull the on-disk inode from the AGI unlinked list.
    -	 */
    -	error = xfs_iunlink_remove(tp, ip);
    -	if (error != 0) {
    -		return error;
    -	}
    -
    -	error = xfs_difree(tp, ip->i_ino, flist, &delete, &first_ino);
    -	if (error != 0) {
    -		return error;
    -	}
    -	ip->i_d.di_mode = 0;		/* mark incore inode as free */
    -	ip->i_d.di_flags = 0;
    -	ip->i_d.di_dmevmask = 0;
    -	ip->i_d.di_forkoff = 0;		/* mark the attr fork not in use */
    -	ip->i_df.if_ext_max =
    -		XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t);
    -	ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS;
    -	ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
    -	/*
    -	 * Bump the generation count so no one will be confused
    -	 * by reincarnations of this inode.
    -	 */
    -	ip->i_d.di_gen++;
    -	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
    -
    -	if (delete) {
    -		xfs_ifree_cluster(ip, tp, first_ino);
    -	}
    -
    -	return 0;
    -}
    -
    -/*
    - * Reallocate the space for if_broot based on the number of records
    - * being added or deleted as indicated in rec_diff.  Move the records
    - * and pointers in if_broot to fit the new size.  When shrinking this
    - * will eliminate holes between the records and pointers created by
    - * the caller.  When growing this will create holes to be filled in
    - * by the caller.
    - *
    - * The caller must not request to add more records than would fit in
    - * the on-disk inode root.  If the if_broot is currently NULL, then
    - * if we adding records one will be allocated.  The caller must also
    - * not request that the number of records go below zero, although
    - * it can go to zero.
    - *
    - * ip -- the inode whose if_broot area is changing
    - * ext_diff -- the change in the number of records, positive or negative,
    - *	 requested for the if_broot array.
    - */
    -void
    -xfs_iroot_realloc(
    -	xfs_inode_t		*ip,
    -	int			rec_diff,
    -	int			whichfork)
    -{
    -	int			cur_max;
    -	xfs_ifork_t		*ifp;
    -	xfs_bmbt_block_t	*new_broot;
    -	int			new_max;
    -	size_t			new_size;
    -	char			*np;
    -	char			*op;
    -
    -	/*
    -	 * Handle the degenerate case quietly.
    -	 */
    -	if (rec_diff == 0) {
    -		return;
    -	}
    -
    -	ifp = XFS_IFORK_PTR(ip, whichfork);
    -	if (rec_diff > 0) {
    -		/*
    -		 * If there wasn't any memory allocated before, just
    -		 * allocate it now and get out.
    -		 */
    -		if (ifp->if_broot_bytes == 0) {
    -			new_size = (size_t)XFS_BMAP_BROOT_SPACE_CALC(rec_diff);
    -			ifp->if_broot = (xfs_bmbt_block_t*)kmem_alloc(new_size,
    -								     KM_SLEEP);
    -			ifp->if_broot_bytes = (int)new_size;
    -			return;
    -		}
    -
    -		/*
    -		 * If there is already an existing if_broot, then we need
    -		 * to realloc() it and shift the pointers to their new
    -		 * location.  The records don't change location because
    -		 * they are kept butted up against the btree block header.
    -		 */
    -		cur_max = XFS_BMAP_BROOT_MAXRECS(ifp->if_broot_bytes);
    -		new_max = cur_max + rec_diff;
    -		new_size = (size_t)XFS_BMAP_BROOT_SPACE_CALC(new_max);
    -		ifp->if_broot = (xfs_bmbt_block_t *)
    -		  kmem_realloc(ifp->if_broot,
    -				new_size,
    -				(size_t)XFS_BMAP_BROOT_SPACE_CALC(cur_max), /* old size */
    -				KM_SLEEP);
    -		op = (char *)XFS_BMAP_BROOT_PTR_ADDR(ifp->if_broot, 1,
    -						      ifp->if_broot_bytes);
    -		np = (char *)XFS_BMAP_BROOT_PTR_ADDR(ifp->if_broot, 1,
    -						      (int)new_size);
    -		ifp->if_broot_bytes = (int)new_size;
    -		ASSERT(ifp->if_broot_bytes <=
    -			XFS_IFORK_SIZE(ip, whichfork) + XFS_BROOT_SIZE_ADJ);
    -		memmove(np, op, cur_max * (uint)sizeof(xfs_dfsbno_t));
    -		return;
    -	}
    -
    -	/*
    -	 * rec_diff is less than 0.  In this case, we are shrinking the
    -	 * if_broot buffer.  It must already exist.  If we go to zero
    -	 * records, just get rid of the root and clear the status bit.
    -	 */
    -	ASSERT((ifp->if_broot != NULL) && (ifp->if_broot_bytes > 0));
    -	cur_max = XFS_BMAP_BROOT_MAXRECS(ifp->if_broot_bytes);
    -	new_max = cur_max + rec_diff;
    -	ASSERT(new_max >= 0);
    -	if (new_max > 0)
    -		new_size = (size_t)XFS_BMAP_BROOT_SPACE_CALC(new_max);
    -	else
    -		new_size = 0;
    -	if (new_size > 0) {
    -		new_broot = (xfs_bmbt_block_t *)kmem_alloc(new_size, KM_SLEEP);
    -		/*
    -		 * First copy over the btree block header.
    -		 */
    -		memcpy(new_broot, ifp->if_broot, sizeof(xfs_bmbt_block_t));
    -	} else {
    -		new_broot = NULL;
    -		ifp->if_flags &= ~XFS_IFBROOT;
    -	}
    -
    -	/*
    -	 * Only copy the records and pointers if there are any.
    -	 */
    -	if (new_max > 0) {
    -		/*
    -		 * First copy the records.
    -		 */
    -		op = (char *)XFS_BMAP_BROOT_REC_ADDR(ifp->if_broot, 1,
    -						     ifp->if_broot_bytes);
    -		np = (char *)XFS_BMAP_BROOT_REC_ADDR(new_broot, 1,
    -						     (int)new_size);
    -		memcpy(np, op, new_max * (uint)sizeof(xfs_bmbt_rec_t));
    -
    -		/*
    -		 * Then copy the pointers.
    -		 */
    -		op = (char *)XFS_BMAP_BROOT_PTR_ADDR(ifp->if_broot, 1,
    -						     ifp->if_broot_bytes);
    -		np = (char *)XFS_BMAP_BROOT_PTR_ADDR(new_broot, 1,
    -						     (int)new_size);
    -		memcpy(np, op, new_max * (uint)sizeof(xfs_dfsbno_t));
    -	}
    -	kmem_free(ifp->if_broot, ifp->if_broot_bytes);
    -	ifp->if_broot = new_broot;
    -	ifp->if_broot_bytes = (int)new_size;
    -	ASSERT(ifp->if_broot_bytes <=
    -		XFS_IFORK_SIZE(ip, whichfork) + XFS_BROOT_SIZE_ADJ);
    -	return;
    -}
    -
    -
    -/*
    - * This is called when the amount of space needed for if_data
    - * is increased or decreased.  The change in size is indicated by
    - * the number of bytes that need to be added or deleted in the
    - * byte_diff parameter.
    - *
    - * If the amount of space needed has decreased below the size of the
    - * inline buffer, then switch to using the inline buffer.  Otherwise,
    - * use kmem_realloc() or kmem_alloc() to adjust the size of the buffer
    - * to what is needed.
    - *
    - * ip -- the inode whose if_data area is changing
    - * byte_diff -- the change in the number of bytes, positive or negative,
    - *	 requested for the if_data array.
    - */
    -void
    -xfs_idata_realloc(
    -	xfs_inode_t	*ip,
    -	int		byte_diff,
    -	int		whichfork)
    -{
    -	xfs_ifork_t	*ifp;
    -	int		new_size;
    -	int		real_size;
    -
    -	if (byte_diff == 0) {
    -		return;
    -	}
    -
    -	ifp = XFS_IFORK_PTR(ip, whichfork);
    -	new_size = (int)ifp->if_bytes + byte_diff;
    -	ASSERT(new_size >= 0);
    -
    -	if (new_size == 0) {
    -		if (ifp->if_u1.if_data != ifp->if_u2.if_inline_data) {
    -			kmem_free(ifp->if_u1.if_data, ifp->if_real_bytes);
    -		}
    -		ifp->if_u1.if_data = NULL;
    -		real_size = 0;
    -	} else if (new_size <= sizeof(ifp->if_u2.if_inline_data)) {
    -		/*
    -		 * If the valid extents/data can fit in if_inline_ext/data,
    -		 * copy them from the malloc'd vector and free it.
    -		 */
    -		if (ifp->if_u1.if_data == NULL) {
    -			ifp->if_u1.if_data = ifp->if_u2.if_inline_data;
    -		} else if (ifp->if_u1.if_data != ifp->if_u2.if_inline_data) {
    -			ASSERT(ifp->if_real_bytes != 0);
    -			memcpy(ifp->if_u2.if_inline_data, ifp->if_u1.if_data,
    -			      new_size);
    -			kmem_free(ifp->if_u1.if_data, ifp->if_real_bytes);
    -			ifp->if_u1.if_data = ifp->if_u2.if_inline_data;
    -		}
    -		real_size = 0;
    -	} else {
    -		/*
    -		 * Stuck with malloc/realloc.
    -		 * For inline data, the underlying buffer must be
    -		 * a multiple of 4 bytes in size so that it can be
    -		 * logged and stay on word boundaries.  We enforce
    -		 * that here.
    -		 */
    -		real_size = roundup(new_size, 4);
    -		if (ifp->if_u1.if_data == NULL) {
    -			ASSERT(ifp->if_real_bytes == 0);
    -			ifp->if_u1.if_data = kmem_alloc(real_size, KM_SLEEP);
    -		} else if (ifp->if_u1.if_data != ifp->if_u2.if_inline_data) {
    -			/*
    -			 * Only do the realloc if the underlying size
    -			 * is really changing.
    -			 */
    -			if (ifp->if_real_bytes != real_size) {
    -				ifp->if_u1.if_data =
    -					kmem_realloc(ifp->if_u1.if_data,
    -							real_size,
    -							ifp->if_real_bytes,
    -							KM_SLEEP);
    -			}
    -		} else {
    -			ASSERT(ifp->if_real_bytes == 0);
    -			ifp->if_u1.if_data = kmem_alloc(real_size, KM_SLEEP);
    -			memcpy(ifp->if_u1.if_data, ifp->if_u2.if_inline_data,
    -				ifp->if_bytes);
    -		}
    -	}
    -	ifp->if_real_bytes = real_size;
    -	ifp->if_bytes = new_size;
    -	ASSERT(ifp->if_bytes <= XFS_IFORK_SIZE(ip, whichfork));
    -}
    -
    -
    -
    -
    -/*
    - * Map inode to disk block and offset.
    - *
    - * mp -- the mount point structure for the current file system
    - * tp -- the current transaction
    - * ino -- the inode number of the inode to be located
    - * imap -- this structure is filled in with the information necessary
    - *	 to retrieve the given inode from disk
    - * flags -- flags to pass to xfs_dilocate indicating whether or not
    - *	 lookups in the inode btree were OK or not
    - */
    -int
    -xfs_imap(
    -	xfs_mount_t	*mp,
    -	xfs_trans_t	*tp,
    -	xfs_ino_t	ino,
    -	xfs_imap_t	*imap,
    -	uint		flags)
    -{
    -	xfs_fsblock_t	fsbno;
    -	int		len;
    -	int		off;
    -	int		error;
    -
    -	fsbno = imap->im_blkno ?
    -		XFS_DADDR_TO_FSB(mp, imap->im_blkno) : NULLFSBLOCK;
    -	error = xfs_dilocate(mp, tp, ino, &fsbno, &len, &off, flags);
    -	if (error != 0) {
    -		return error;
    -	}
    -	imap->im_blkno = XFS_FSB_TO_DADDR(mp, fsbno);
    -	imap->im_len = XFS_FSB_TO_BB(mp, len);
    -	imap->im_agblkno = XFS_FSB_TO_AGBNO(mp, fsbno);
    -	imap->im_ioffset = (ushort)off;
    -	imap->im_boffset = (ushort)(off << mp->m_sb.sb_inodelog);
    -	return 0;
    -}
    -
    -void
    -xfs_idestroy_fork(
    -	xfs_inode_t	*ip,
    -	int		whichfork)
    -{
    -	xfs_ifork_t	*ifp;
    -
    -	ifp = XFS_IFORK_PTR(ip, whichfork);
    -	if (ifp->if_broot != NULL) {
    -		kmem_free(ifp->if_broot, ifp->if_broot_bytes);
    -		ifp->if_broot = NULL;
    -	}
    -
    -	/*
    -	 * If the format is local, then we can't have an extents
    -	 * array so just look for an inline data array.  If we're
    -	 * not local then we may or may not have an extents list,
    -	 * so check and free it up if we do.
    -	 */
    -	if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
    -		if ((ifp->if_u1.if_data != ifp->if_u2.if_inline_data) &&
    -		    (ifp->if_u1.if_data != NULL)) {
    -			ASSERT(ifp->if_real_bytes != 0);
    -			kmem_free(ifp->if_u1.if_data, ifp->if_real_bytes);
    -			ifp->if_u1.if_data = NULL;
    -			ifp->if_real_bytes = 0;
    -		}
    -	} else if ((ifp->if_flags & XFS_IFEXTENTS) &&
    -		   ((ifp->if_flags & XFS_IFEXTIREC) ||
    -		    ((ifp->if_u1.if_extents != NULL) &&
    -		     (ifp->if_u1.if_extents != ifp->if_u2.if_inline_ext)))) {
    -		ASSERT(ifp->if_real_bytes != 0);
    -		xfs_iext_destroy(ifp);
    -	}
    -	ASSERT(ifp->if_u1.if_extents == NULL ||
    -	       ifp->if_u1.if_extents == ifp->if_u2.if_inline_ext);
    -	ASSERT(ifp->if_real_bytes == 0);
    -	if (whichfork == XFS_ATTR_FORK) {
    -		kmem_zone_free(xfs_ifork_zone, ip->i_afp);
    -		ip->i_afp = NULL;
    -	}
    -}
    -
    -/*
    - * This is called free all the memory associated with an inode.
    - * It must free the inode itself and any buffers allocated for
    - * if_extents/if_data and if_broot.  It must also free the lock
    - * associated with the inode.
    - */
    -void
    -xfs_idestroy(
    -	xfs_inode_t	*ip)
    -{
    -
    -	switch (ip->i_d.di_mode & S_IFMT) {
    -	case S_IFREG:
    -	case S_IFDIR:
    -	case S_IFLNK:
    -		xfs_idestroy_fork(ip, XFS_DATA_FORK);
    -		break;
    -	}
    -	if (ip->i_afp)
    -		xfs_idestroy_fork(ip, XFS_ATTR_FORK);
    -	mrfree(&ip->i_lock);
    -	mrfree(&ip->i_iolock);
    -	freesema(&ip->i_flock);
    -#ifdef XFS_BMAP_TRACE
    -	ktrace_free(ip->i_xtrace);
    -#endif
    -#ifdef XFS_BMBT_TRACE
    -	ktrace_free(ip->i_btrace);
    -#endif
    -#ifdef XFS_RW_TRACE
    -	ktrace_free(ip->i_rwtrace);
    -#endif
    -#ifdef XFS_ILOCK_TRACE
    -	ktrace_free(ip->i_lock_trace);
    -#endif
    -#ifdef XFS_DIR2_TRACE
    -	ktrace_free(ip->i_dir_trace);
    -#endif
    -	if (ip->i_itemp) {
    -		/* XXXdpd should be able to assert this but shutdown
    -		 * is leaving the AIL behind. */
    -		ASSERT(((ip->i_itemp->ili_item.li_flags & XFS_LI_IN_AIL) == 0) ||
    -		       XFS_FORCED_SHUTDOWN(ip->i_mount));
    -		xfs_inode_item_destroy(ip);
    -	}
    -	kmem_zone_free(xfs_inode_zone, ip);
    -}
    -
    -
    -/*
    - * Increment the pin count of the given buffer.
    - * This value is protected by ipinlock spinlock in the mount structure.
    - */
    -void
    -xfs_ipin(
    -	xfs_inode_t	*ip)
    -{
    -	ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
    -
    -	atomic_inc(&ip->i_pincount);
    -}
    -
    -/*
    - * Decrement the pin count of the given inode, and wake up
    - * anyone in xfs_iwait_unpin() if the count goes to 0.  The
    - * inode must have been previously pinned with a call to xfs_ipin().
    - */
    -void
    -xfs_iunpin(
    -	xfs_inode_t	*ip)
    -{
    -	ASSERT(atomic_read(&ip->i_pincount) > 0);
    -
    -	if (atomic_dec_and_test(&ip->i_pincount)) {
    -		/*
    -		 * If the inode is currently being reclaimed, the
    -		 * linux inode _and_ the xfs vnode may have been
    -		 * freed so we cannot reference either of them safely.
    -		 * Hence we should not try to do anything to them
    -		 * if the xfs inode is currently in the reclaim
    -		 * path.
    -		 *
    -		 * However, we still need to issue the unpin wakeup
    -		 * call as the inode reclaim may be blocked waiting for
    -		 * the inode to become unpinned.
    -		 */
    -		if (!(ip->i_flags & (XFS_IRECLAIM|XFS_IRECLAIMABLE))) {
    -			/*
    -			 * Should I mark FreeBSD vnode as dirty here?
    -			 */
    -			printf("xfs_iunpin: REC RECABLE ip %p\n",ip);
    -#ifdef RMC
    -			xfs_vnode_t	*vp = XFS_ITOV_NULL(ip);
    -
    -			/* make sync come back and flush this inode */
    -			if (vp) {
    -				struct inode	*inode = vn_to_inode(vp);
    -
    -				if (!(inode->i_state & I_NEW))
    -					mark_inode_dirty_sync(inode);
    -			}
    -#endif
    -		}
    -		wakeup(&ip->i_ipin_wait);
    -	}
    -}
    -
    -/*
    - * This is called to wait for the given inode to be unpinned.
    - * It will sleep until this happens.  The caller must have the
    - * inode locked in at least shared mode so that the buffer cannot
    - * be subsequently pinned once someone is waiting for it to be
    - * unpinned.
    - */
    -STATIC void
    -xfs_iunpin_wait(
    -	xfs_inode_t	*ip)
    -{
    -	xfs_inode_log_item_t	*iip;
    -	xfs_lsn_t	lsn;
    -
    -	ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE | MR_ACCESS));
    -
    -	if (atomic_read(&ip->i_pincount) == 0) {
    -		return;
    -	}
    -
    -	iip = ip->i_itemp;
    -	if (iip && iip->ili_last_lsn) {
    -		lsn = iip->ili_last_lsn;
    -	} else {
    -		lsn = (xfs_lsn_t)0;
    -	}
    -
    -	/*
    -	 * Give the log a push so we don't wait here too long.
    -	 */
    -	xfs_log_force(ip->i_mount, lsn, XFS_LOG_FORCE);
    -
    -	/*
    -	 * XXXKAN: xfs_iunpin is not locking inode
    -	 * at all?
    -	 */
    -	while(atomic_read(&ip->i_pincount) != 0)
    -		tsleep(&ip->i_ipin_wait, PRIBIO, "iunpin", 0);
    -}
    -
    -
    -/*
    - * xfs_iextents_copy()
    - *
    - * This is called to copy the REAL extents (as opposed to the delayed
    - * allocation extents) from the inode into the given buffer.  It
    - * returns the number of bytes copied into the buffer.
    - *
    - * If there are no delayed allocation extents, then we can just
    - * memcpy() the extents into the buffer.  Otherwise, we need to
    - * examine each extent in turn and skip those which are delayed.
    - */
    -int
    -xfs_iextents_copy(
    -	xfs_inode_t		*ip,
    -	xfs_bmbt_rec_t		*buffer,
    -	int			whichfork)
    -{
    -	int			copied;
    -	xfs_bmbt_rec_t		*dest_ep;
    -	xfs_bmbt_rec_t		*ep;
    -#ifdef XFS_BMAP_TRACE
    -	static char		fname[] = "xfs_iextents_copy";
    -#endif
    -	int			i;
    -	xfs_ifork_t		*ifp;
    -	int			nrecs;
    -	xfs_fsblock_t		start_block;
    -
    -	ifp = XFS_IFORK_PTR(ip, whichfork);
    -	ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE|MR_ACCESS));
    -	ASSERT(ifp->if_bytes > 0);
    -
    -	nrecs = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
    -	xfs_bmap_trace_exlist(fname, ip, nrecs, whichfork);
    -	ASSERT(nrecs > 0);
    -
    -	/*
    -	 * There are some delayed allocation extents in the
    -	 * inode, so copy the extents one at a time and skip
    -	 * the delayed ones.  There must be at least one
    -	 * non-delayed extent.
    -	 */
    -	dest_ep = buffer;
    -	copied = 0;
    -	for (i = 0; i < nrecs; i++) {
    -		ep = xfs_iext_get_ext(ifp, i);
    -		start_block = xfs_bmbt_get_startblock(ep);
    -		if (ISNULLSTARTBLOCK(start_block)) {
    -			/*
    -			 * It's a delayed allocation extent, so skip it.
    -			 */
    -			continue;
    -		}
    -
    -		/* Translate to on disk format */
    -		put_unaligned(INT_GET(ep->l0, ARCH_CONVERT),
    -			      (__uint64_t*)&dest_ep->l0);
    -		put_unaligned(INT_GET(ep->l1, ARCH_CONVERT),
    -			      (__uint64_t*)&dest_ep->l1);
    -		dest_ep++;
    -		copied++;
    -	}
    -	ASSERT(copied != 0);
    -	xfs_validate_extents(ifp, copied, 1, XFS_EXTFMT_INODE(ip));
    -
    -	return (copied * (uint)sizeof(xfs_bmbt_rec_t));
    -}
    -
    -/*
    - * Each of the following cases stores data into the same region
    - * of the on-disk inode, so only one of them can be valid at
    - * any given time. While it is possible to have conflicting formats
    - * and log flags, e.g. having XFS_ILOG_?DATA set when the fork is
    - * in EXTENTS format, this can only happen when the fork has
    - * changed formats after being modified but before being flushed.
    - * In these cases, the format always takes precedence, because the
    - * format indicates the current state of the fork.
    - */
    -/*ARGSUSED*/
    -STATIC int
    -xfs_iflush_fork(
    -	xfs_inode_t		*ip,
    -	xfs_dinode_t		*dip,
    -	xfs_inode_log_item_t	*iip,
    -	int			whichfork,
    -	xfs_buf_t		*bp)
    -{
    -	char			*cp;
    -	xfs_ifork_t		*ifp;
    -	xfs_mount_t		*mp;
    -#ifdef XFS_TRANS_DEBUG
    -	int			first;
    -#endif
    -	static const short	brootflag[2] =
    -		{ XFS_ILOG_DBROOT, XFS_ILOG_ABROOT };
    -	static const short	dataflag[2] =
    -		{ XFS_ILOG_DDATA, XFS_ILOG_ADATA };
    -	static const short	extflag[2] =
    -		{ XFS_ILOG_DEXT, XFS_ILOG_AEXT };
    -
    -	if (iip == NULL)
    -		return 0;
    -	ifp = XFS_IFORK_PTR(ip, whichfork);
    -	/*
    -	 * This can happen if we gave up in iformat in an error path,
    -	 * for the attribute fork.
    -	 */
    -	if (ifp == NULL) {
    -		ASSERT(whichfork == XFS_ATTR_FORK);
    -		return 0;
    -	}
    -	cp = XFS_DFORK_PTR(dip, whichfork);
    -	mp = ip->i_mount;
    -	switch (XFS_IFORK_FORMAT(ip, whichfork)) {
    -	case XFS_DINODE_FMT_LOCAL:
    -		if ((iip->ili_format.ilf_fields & dataflag[whichfork]) &&
    -		    (ifp->if_bytes > 0)) {
    -			ASSERT(ifp->if_u1.if_data != NULL);
    -			ASSERT(ifp->if_bytes <= XFS_IFORK_SIZE(ip, whichfork));
    -			memcpy(cp, ifp->if_u1.if_data, ifp->if_bytes);
    -		}
    -		if (whichfork == XFS_DATA_FORK) {
    -			if (unlikely(XFS_DIR_SHORTFORM_VALIDATE_ONDISK(mp, dip))) {
    -				XFS_ERROR_REPORT("xfs_iflush_fork",
    -						 XFS_ERRLEVEL_LOW, mp);
    -				return XFS_ERROR(EFSCORRUPTED);
    -			}
    -		}
    -		break;
    -
    -	case XFS_DINODE_FMT_EXTENTS:
    -		ASSERT((ifp->if_flags & XFS_IFEXTENTS) ||
    -		       !(iip->ili_format.ilf_fields & extflag[whichfork]));
    -		ASSERT((xfs_iext_get_ext(ifp, 0) != NULL) ||
    -			(ifp->if_bytes == 0));
    -		ASSERT((xfs_iext_get_ext(ifp, 0) == NULL) ||
    -			(ifp->if_bytes > 0));
    -		if ((iip->ili_format.ilf_fields & extflag[whichfork]) &&
    -		    (ifp->if_bytes > 0)) {
    -			ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) > 0);
    -			(void)xfs_iextents_copy(ip, (xfs_bmbt_rec_t *)cp,
    -				whichfork);
    -		}
    -		break;
    -
    -	case XFS_DINODE_FMT_BTREE:
    -		if ((iip->ili_format.ilf_fields & brootflag[whichfork]) &&
    -		    (ifp->if_broot_bytes > 0)) {
    -			ASSERT(ifp->if_broot != NULL);
    -			ASSERT(ifp->if_broot_bytes <=
    -			       (XFS_IFORK_SIZE(ip, whichfork) +
    -				XFS_BROOT_SIZE_ADJ));
    -			xfs_bmbt_to_bmdr(ifp->if_broot, ifp->if_broot_bytes,
    -				(xfs_bmdr_block_t *)cp,
    -				XFS_DFORK_SIZE(dip, mp, whichfork));
    -		}
    -		break;
    -
    -	case XFS_DINODE_FMT_DEV:
    -		if (iip->ili_format.ilf_fields & XFS_ILOG_DEV) {
    -			ASSERT(whichfork == XFS_DATA_FORK);
    -			INT_SET(dip->di_u.di_dev, ARCH_CONVERT, ip->i_df.if_u2.if_rdev);
    -		}
    -		break;
    -
    -	case XFS_DINODE_FMT_UUID:
    -		if (iip->ili_format.ilf_fields & XFS_ILOG_UUID) {
    -			ASSERT(whichfork == XFS_DATA_FORK);
    -			memcpy(&dip->di_u.di_muuid, &ip->i_df.if_u2.if_uuid,
    -				sizeof(uuid_t));
    -		}
    -		break;
    -
    -	default:
    -		ASSERT(0);
    -		break;
    -	}
    -
    -	return 0;
    -}
    -
    -/*
    - * xfs_iflush() will write a modified inode's changes out to the
    - * inode's on disk home.  The caller must have the inode lock held
    - * in at least shared mode and the inode flush semaphore must be
    - * held as well.  The inode lock will still be held upon return from
    - * the call and the caller is free to unlock it.
    - * The inode flush lock will be unlocked when the inode reaches the disk.
    - * The flags indicate how the inode's buffer should be written out.
    - */
    -int
    -xfs_iflush(
    -	xfs_inode_t		*ip,
    -	uint			flags)
    -{
    -	xfs_inode_log_item_t	*iip;
    -	xfs_buf_t		*bp;
    -	xfs_dinode_t		*dip;
    -	xfs_mount_t		*mp;
    -	int			error;
    -	/* REFERENCED */
    -	xfs_chash_t		*ch;
    -	xfs_inode_t		*iq;
    -	int			clcount;	/* count of inodes clustered */
    -	int			bufwasdelwri;
    -	enum { INT_DELWRI = (1 << 0), INT_ASYNC = (1 << 1) };
    -	SPLDECL(s);
    -
    -	XFS_STATS_INC(xs_iflush_count);
    -
    -
    -	printf("xfs_iflush: ip %p i_ino %lld\n",ip,ip->i_ino);
    -	ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE|MR_ACCESS));
    -	ASSERT(valusema(&ip->i_flock) <= 0);
    -	ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
    -	       ip->i_d.di_nextents > ip->i_df.if_ext_max);
    -
    -	iip = ip->i_itemp;
    -	mp = ip->i_mount;
    -
    -	/*
    -	 * If the inode isn't dirty, then just release the inode
    -	 * flush lock and do nothing.
    -	 */
    -	if ((ip->i_update_core == 0) &&
    -	    ((iip == NULL) || !(iip->ili_format.ilf_fields & XFS_ILOG_ALL))) {
    -		ASSERT((iip != NULL) ?
    -			 !(iip->ili_item.li_flags & XFS_LI_IN_AIL) : 1);
    -		xfs_ifunlock(ip);
    -		return 0;
    -	}
    -
    -	/*
    -	 * We can't flush the inode until it is unpinned, so
    -	 * wait for it.  We know noone new can pin it, because
    -	 * we are holding the inode lock shared and you need
    -	 * to hold it exclusively to pin the inode.
    -	 */
    -	xfs_iunpin_wait(ip);
    -
    -	/*
    -	 * This may have been unpinned because the filesystem is shutting
    -	 * down forcibly. If that's the case we must not write this inode
    -	 * to disk, because the log record didn't make it to disk!
    -	 */
    -	if (XFS_FORCED_SHUTDOWN(mp)) {
    -		ip->i_update_core = 0;
    -		if (iip)
    -			iip->ili_format.ilf_fields = 0;
    -		xfs_ifunlock(ip);
    -		return XFS_ERROR(EIO);
    -	}
    -
    -	/*
    -	 * Get the buffer containing the on-disk inode.
    -	 */
    -	error = xfs_itobp(mp, NULL, ip, &dip, &bp, 0, 0);
    -	if (error) {
    -		xfs_ifunlock(ip);
    -		return error;
    -	}
    -
    -	/*
    -	 * Decide how buffer will be flushed out.  This is done before
    -	 * the call to xfs_iflush_int because this field is zeroed by it.
    -	 */
    -	if (iip != NULL && iip->ili_format.ilf_fields != 0) {
    -		/*
    -		 * Flush out the inode buffer according to the directions
    -		 * of the caller.  In the cases where the caller has given
    -		 * us a choice choose the non-delwri case.  This is because
    -		 * the inode is in the AIL and we need to get it out soon.
    -		 */
    -		switch (flags) {
    -		case XFS_IFLUSH_SYNC:
    -		case XFS_IFLUSH_DELWRI_ELSE_SYNC:
    -			flags = 0;
    -			break;
    -		case XFS_IFLUSH_ASYNC:
    -		case XFS_IFLUSH_DELWRI_ELSE_ASYNC:
    -			flags = INT_ASYNC;
    -			break;
    -		case XFS_IFLUSH_DELWRI:
    -			flags = INT_DELWRI;
    -			break;
    -		default:
    -			ASSERT(0);
    -			flags = 0;
    -			break;
    -		}
    -	} else {
    -		switch (flags) {
    -		case XFS_IFLUSH_DELWRI_ELSE_SYNC:
    -		case XFS_IFLUSH_DELWRI_ELSE_ASYNC:
    -		case XFS_IFLUSH_DELWRI:
    -			flags = INT_DELWRI;
    -			break;
    -		case XFS_IFLUSH_ASYNC:
    -			flags = INT_ASYNC;
    -			break;
    -		case XFS_IFLUSH_SYNC:
    -			flags = 0;
    -			break;
    -		default:
    -			ASSERT(0);
    -			flags = 0;
    -			break;
    -		}
    -	}
    -
    -	/*
    -	 * First flush out the inode that xfs_iflush was called with.
    -	 */
    -	error = xfs_iflush_int(ip, bp);
    -	if (error) {
    -		goto corrupt_out;
    -	}
    -
    -	/*
    -	 * inode clustering:
    -	 * see if other inodes can be gathered into this write
    -	 */
    -
    -	ip->i_chash->chl_buf = bp;
    -
    -	ch = XFS_CHASH(mp, ip->i_blkno);
    -	s = mutex_spinlock(&ch->ch_lock);
    -
    -	clcount = 0;
    -	for (iq = ip->i_cnext; iq != ip; iq = iq->i_cnext) {
    -		/*
    -		 * Do an un-protected check to see if the inode is dirty and
    -		 * is a candidate for flushing.  These checks will be repeated
    -		 * later after the appropriate locks are acquired.
    -		 */
    -		iip = iq->i_itemp;
    -		if ((iq->i_update_core == 0) &&
    -		    ((iip == NULL) ||
    -		     !(iip->ili_format.ilf_fields & XFS_ILOG_ALL)) &&
    -		      xfs_ipincount(iq) == 0) {
    -			continue;
    -		}
    -
    -		/*
    -		 * Try to get locks.  If any are unavailable,
    -		 * then this inode cannot be flushed and is skipped.
    -		 */
    -
    -		/* get inode locks (just i_lock) */
    -		if (xfs_ilock_nowait(iq, XFS_ILOCK_SHARED)) {
    -			/* get inode flush lock */
    -			if (xfs_iflock_nowait(iq)) {
    -				/* check if pinned */
    -				if (xfs_ipincount(iq) == 0) {
    -					/* arriving here means that
    -					 * this inode can be flushed.
    -					 * first re-check that it's
    -					 * dirty
    -					 */
    -					iip = iq->i_itemp;
    -					if ((iq->i_update_core != 0)||
    -					    ((iip != NULL) &&
    -					     (iip->ili_format.ilf_fields & XFS_ILOG_ALL))) {
    -						clcount++;
    -						error = xfs_iflush_int(iq, bp);
    -						if (error) {
    -							xfs_iunlock(iq,
    -								    XFS_ILOCK_SHARED);
    -							goto cluster_corrupt_out;
    -						}
    -					} else {
    -						xfs_ifunlock(iq);
    -					}
    -				} else {
    -					xfs_ifunlock(iq);
    -				}
    -			}
    -			xfs_iunlock(iq, XFS_ILOCK_SHARED);
    -		}
    -	}
    -	mutex_spinunlock(&ch->ch_lock, s);
    -
    -	if (clcount) {
    -		XFS_STATS_INC(xs_icluster_flushcnt);
    -		XFS_STATS_ADD(xs_icluster_flushinode, clcount);
    -	}
    -
    -	/*
    -	 * If the buffer is pinned then push on the log so we won't
    -	 * get stuck waiting in the write for too long.
    -	 */
    -	if (XFS_BUF_ISPINNED(bp)){
    -		xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE);
    -	}
    -
    -	if (flags & INT_DELWRI) {
    -		xfs_bdwrite(mp, bp);
    -	} else if (flags & INT_ASYNC) {
    -		xfs_bawrite(mp, bp);
    -	} else {
    -		error = xfs_bwrite(mp, bp);
    -	}
    -	return error;
    -
    -corrupt_out:
    -	xfs_buf_relse(bp);
    -	xfs_force_shutdown(mp, XFS_CORRUPT_INCORE);
    -	xfs_iflush_abort(ip);
    -	/*
    -	 * Unlocks the flush lock
    -	 */
    -	return XFS_ERROR(EFSCORRUPTED);
    -
    -cluster_corrupt_out:
    -	/* Corruption detected in the clustering loop.  Invalidate the
    -	 * inode buffer and shut down the filesystem.
    -	 */
    -	mutex_spinunlock(&ch->ch_lock, s);
    -
    -	/*
    -	 * Clean up the buffer.  If it was B_DELWRI, just release it --
    -	 * brelse can handle it with no problems.  If not, shut down the
    -	 * filesystem before releasing the buffer.
    -	 */
    -	if ((bufwasdelwri= XFS_BUF_ISDELAYWRITE(bp))) {
    -		xfs_buf_relse(bp);
    -	}
    -
    -	xfs_force_shutdown(mp, XFS_CORRUPT_INCORE);
    -
    -	if(!bufwasdelwri)  {
    -		/*
    -		 * Just like incore_relse: if we have b_iodone functions,
    -		 * mark the buffer as an error and call them.  Otherwise
    -		 * mark it as stale and brelse.
    -		 */
    -		if (XFS_BUF_IODONE_FUNC(bp)) {
    -			XFS_BUF_CLR_BDSTRAT_FUNC(bp);
    -			XFS_BUF_UNDONE(bp);
    -			XFS_BUF_STALE(bp);
    -			XFS_BUF_SHUT(bp);
    -			XFS_BUF_ERROR(bp,EIO);
    -			xfs_biodone(bp);
    -		} else {
    -			XFS_BUF_STALE(bp);
    -			xfs_buf_relse(bp);
    -		}
    -	}
    -
    -	xfs_iflush_abort(iq);
    -	/*
    -	 * Unlocks the flush lock
    -	 */
    -	return XFS_ERROR(EFSCORRUPTED);
    -}
    -
    -
    -STATIC int
    -xfs_iflush_int(
    -	xfs_inode_t		*ip,
    -	xfs_buf_t		*bp)
    -{
    -	xfs_inode_log_item_t	*iip;
    -	xfs_dinode_t		*dip;
    -	xfs_mount_t		*mp;
    -#ifdef XFS_TRANS_DEBUG
    -	// int			first;
    -#endif
    -	SPLDECL(s);
    -
    -	ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE|MR_ACCESS));
    -	ASSERT(valusema(&ip->i_flock) <= 0);
    -	ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
    -	       ip->i_d.di_nextents > ip->i_df.if_ext_max);
    -
    -	iip = ip->i_itemp;
    -	mp = ip->i_mount;
    -
    -
    -	/*
    -	 * If the inode isn't dirty, then just release the inode
    -	 * flush lock and do nothing.
    -	 */
    -	if ((ip->i_update_core == 0) &&
    -	    ((iip == NULL) || !(iip->ili_format.ilf_fields & XFS_ILOG_ALL))) {
    -		xfs_ifunlock(ip);
    -		return 0;
    -	}
    -
    -	/* set *dip = inode's place in the buffer */
    -	dip = (xfs_dinode_t *)xfs_buf_offset(bp, ip->i_boffset);
    -
    -	/*
    -	 * Clear i_update_core before copying out the data.
    -	 * This is for coordination with our timestamp updates
    -	 * that don't hold the inode lock. They will always
    -	 * update the timestamps BEFORE setting i_update_core,
    -	 * so if we clear i_update_core after they set it we
    -	 * are guaranteed to see their updates to the timestamps.
    -	 * I believe that this depends on strongly ordered memory
    -	 * semantics, but we have that.  We use the SYNCHRONIZE
    -	 * macro to make sure that the compiler does not reorder
    -	 * the i_update_core access below the data copy below.
    -	 */
    -	ip->i_update_core = 0;
    -	SYNCHRONIZE();
    -
    -	/*
    -	 * Make sure to get the latest atime from the Linux inode.
    -	 */
    -	xfs_synchronize_atime(ip);
    -
    -	if (XFS_TEST_ERROR(INT_GET(dip->di_core.di_magic,ARCH_CONVERT) != XFS_DINODE_MAGIC,
    -			       mp, XFS_ERRTAG_IFLUSH_1, XFS_RANDOM_IFLUSH_1)) {
    -		xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp,
    -		    "xfs_iflush: Bad inode %Lu magic number 0x%x, ptr 0x%p",
    -			ip->i_ino, (int) INT_GET(dip->di_core.di_magic, ARCH_CONVERT), dip);
    -		goto corrupt_out;
    -	}
    -	if (XFS_TEST_ERROR(ip->i_d.di_magic != XFS_DINODE_MAGIC,
    -				mp, XFS_ERRTAG_IFLUSH_2, XFS_RANDOM_IFLUSH_2)) {
    -		xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp,
    -			"xfs_iflush: Bad inode %Lu, ptr 0x%p, magic number 0x%x",
    -			ip->i_ino, ip, ip->i_d.di_magic);
    -		goto corrupt_out;
    -	}
    -	if ((ip->i_d.di_mode & S_IFMT) == S_IFREG) {
    -		if (XFS_TEST_ERROR(
    -		    (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS) &&
    -		    (ip->i_d.di_format != XFS_DINODE_FMT_BTREE),
    -		    mp, XFS_ERRTAG_IFLUSH_3, XFS_RANDOM_IFLUSH_3)) {
    -			xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp,
    -				"xfs_iflush: Bad regular inode %Lu, ptr 0x%p",
    -				ip->i_ino, ip);
    -			goto corrupt_out;
    -		}
    -	} else if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
    -		if (XFS_TEST_ERROR(
    -		    (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS) &&
    -		    (ip->i_d.di_format != XFS_DINODE_FMT_BTREE) &&
    -		    (ip->i_d.di_format != XFS_DINODE_FMT_LOCAL),
    -		    mp, XFS_ERRTAG_IFLUSH_4, XFS_RANDOM_IFLUSH_4)) {
    -			xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp,
    -				"xfs_iflush: Bad directory inode %Lu, ptr 0x%p",
    -				ip->i_ino, ip);
    -			goto corrupt_out;
    -		}
    -	}
    -	if (XFS_TEST_ERROR(ip->i_d.di_nextents + ip->i_d.di_anextents >
    -				ip->i_d.di_nblocks, mp, XFS_ERRTAG_IFLUSH_5,
    -				XFS_RANDOM_IFLUSH_5)) {
    -		xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp,
    -			"xfs_iflush: detected corrupt incore inode %Lu, total extents = %d, nblocks = %Ld, ptr 0x%p",
    -			ip->i_ino,
    -			ip->i_d.di_nextents + ip->i_d.di_anextents,
    -			ip->i_d.di_nblocks,
    -			ip);
    -		goto corrupt_out;
    -	}
    -	if (XFS_TEST_ERROR(ip->i_d.di_forkoff > mp->m_sb.sb_inodesize,
    -				mp, XFS_ERRTAG_IFLUSH_6, XFS_RANDOM_IFLUSH_6)) {
    -		xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp,
    -			"xfs_iflush: bad inode %Lu, forkoff 0x%x, ptr 0x%p",
    -			ip->i_ino, ip->i_d.di_forkoff, ip);
    -		goto corrupt_out;
    -	}
    -	/*
    -	 * bump the flush iteration count, used to detect flushes which
    -	 * postdate a log record during recovery.
    -	 */
    -
    -	ip->i_d.di_flushiter++;
    -
    -	/*
    -	 * Copy the dirty parts of the inode into the on-disk
    -	 * inode.  We always copy out the core of the inode,
    -	 * because if the inode is dirty at all the core must
    -	 * be.
    -	 */
    -	xfs_xlate_dinode_core((xfs_caddr_t)&(dip->di_core), &(ip->i_d), -1);
    -
    -	/* Wrap, we never let the log put out DI_MAX_FLUSH */
    -	if (ip->i_d.di_flushiter == DI_MAX_FLUSH)
    -		ip->i_d.di_flushiter = 0;
    -
    -	/*
    -	 * If this is really an old format inode and the superblock version
    -	 * has not been updated to support only new format inodes, then
    -	 * convert back to the old inode format.  If the superblock version
    -	 * has been updated, then make the conversion permanent.
    -	 */
    -	ASSERT(ip->i_d.di_version == XFS_DINODE_VERSION_1 ||
    -	       XFS_SB_VERSION_HASNLINK(&mp->m_sb));
    -	if (ip->i_d.di_version == XFS_DINODE_VERSION_1) {
    -		if (!XFS_SB_VERSION_HASNLINK(&mp->m_sb)) {
    -			/*
    -			 * Convert it back.
    -			 */
    -			ASSERT(ip->i_d.di_nlink <= XFS_MAXLINK_1);
    -			INT_SET(dip->di_core.di_onlink, ARCH_CONVERT, ip->i_d.di_nlink);
    -		} else {
    -			/*
    -			 * The superblock version has already been bumped,
    -			 * so just make the conversion to the new inode
    -			 * format permanent.
    -			 */
    -			ip->i_d.di_version = XFS_DINODE_VERSION_2;
    -			INT_SET(dip->di_core.di_version, ARCH_CONVERT, XFS_DINODE_VERSION_2);
    -			ip->i_d.di_onlink = 0;
    -			dip->di_core.di_onlink = 0;
    -			memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
    -			memset(&(dip->di_core.di_pad[0]), 0,
    -			      sizeof(dip->di_core.di_pad));
    -			ASSERT(ip->i_d.di_projid == 0);
    -		}
    -	}
    -
    -	if (xfs_iflush_fork(ip, dip, iip, XFS_DATA_FORK, bp) == EFSCORRUPTED) {
    -		goto corrupt_out;
    -	}
    -
    -	if (XFS_IFORK_Q(ip)) {
    -		/*
    -		 * The only error from xfs_iflush_fork is on the data fork.
    -		 */
    -		(void) xfs_iflush_fork(ip, dip, iip, XFS_ATTR_FORK, bp);
    -	}
    -	xfs_inobp_check(mp, bp);
    -
    -	/*
    -	 * We've recorded everything logged in the inode, so we'd
    -	 * like to clear the ilf_fields bits so we don't log and
    -	 * flush things unnecessarily.  However, we can't stop
    -	 * logging all this information until the data we've copied
    -	 * into the disk buffer is written to disk.  If we did we might
    -	 * overwrite the copy of the inode in the log with all the
    -	 * data after re-logging only part of it, and in the face of
    -	 * a crash we wouldn't have all the data we need to recover.
    -	 *
    -	 * What we do is move the bits to the ili_last_fields field.
    -	 * When logging the inode, these bits are moved back to the
    -	 * ilf_fields field.  In the xfs_iflush_done() routine we
    -	 * clear ili_last_fields, since we know that the information
    -	 * those bits represent is permanently on disk.  As long as
    -	 * the flush completes before the inode is logged again, then
    -	 * both ilf_fields and ili_last_fields will be cleared.
    -	 *
    -	 * We can play with the ilf_fields bits here, because the inode
    -	 * lock must be held exclusively in order to set bits there
    -	 * and the flush lock protects the ili_last_fields bits.
    -	 * Set ili_logged so the flush done
    -	 * routine can tell whether or not to look in the AIL.
    -	 * Also, store the current LSN of the inode so that we can tell
    -	 * whether the item has moved in the AIL from xfs_iflush_done().
    -	 * In order to read the lsn we need the AIL lock, because
    -	 * it is a 64 bit value that cannot be read atomically.
    -	 */
    -	if (iip != NULL && iip->ili_format.ilf_fields != 0) {
    -		iip->ili_last_fields = iip->ili_format.ilf_fields;
    -		iip->ili_format.ilf_fields = 0;
    -		iip->ili_logged = 1;
    -
    -		ASSERT(sizeof(xfs_lsn_t) == 8);	/* don't lock if it shrinks */
    -		AIL_LOCK(mp,s);
    -		iip->ili_flush_lsn = iip->ili_item.li_lsn;
    -		AIL_UNLOCK(mp, s);
    -
    -		/*
    -		 * Attach the function xfs_iflush_done to the inode's
    -		 * buffer.  This will remove the inode from the AIL
    -		 * and unlock the inode's flush lock when the inode is
    -		 * completely written to disk.
    -		 */
    -		xfs_buf_attach_iodone(bp, (void(*)(xfs_buf_t*,xfs_log_item_t*))
    -				      xfs_iflush_done, (xfs_log_item_t *)iip);
    -
    -		ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL);
    -		ASSERT(XFS_BUF_IODONE_FUNC(bp) != NULL);
    -	} else {
    -		/*
    -		 * We're flushing an inode which is not in the AIL and has
    -		 * not been logged but has i_update_core set.  For this
    -		 * case we can use a B_DELWRI flush and immediately drop
    -		 * the inode flush lock because we can avoid the whole
    -		 * AIL state thing.  It's OK to drop the flush lock now,
    -		 * because we've already locked the buffer and to do anything
    -		 * you really need both.
    -		 */
    -		if (iip != NULL) {
    -			ASSERT(iip->ili_logged == 0);
    -			ASSERT(iip->ili_last_fields == 0);
    -			ASSERT((iip->ili_item.li_flags & XFS_LI_IN_AIL) == 0);
    -		}
    -		xfs_ifunlock(ip);
    -	}
    -
    -	return 0;
    -
    -corrupt_out:
    -	return XFS_ERROR(EFSCORRUPTED);
    -}
    -
    -
    -/*
    - * Flush all inactive inodes in mp.
    - */
    -void
    -xfs_iflush_all(
    -	xfs_mount_t	*mp)
    -{
    -	int		done;
    -	int		purged;
    -	xfs_inode_t	*ip;
    -	xfs_vnode_t	*vp;
    -
    -	done = 0;
    -	while (!done) {
    -		purged = 0;
    -		XFS_MOUNT_ILOCK(mp);
    -		ip = mp->m_inodes;
    -		if (ip == NULL) {
    -			break;
    -		}
    -		do {
    -			/* Make sure we skip markers inserted by sync */
    -			if (ip->i_mount == NULL) {
    -				ip = ip->i_mnext;
    -				continue;
    -			}
    -
    -			/*
    -			 * It's up to our caller to purge the root
    -			 * and quota vnodes later.
    -			 */
    -			vp = XFS_ITOV_NULL(ip);
    -
    -			if (!vp) {
    -				XFS_MOUNT_IUNLOCK(mp);
    -				xfs_finish_reclaim(ip, 0, XFS_IFLUSH_ASYNC);
    -				purged = 1;
    -				break;
    -			}
    -
    -			if (vn_count(vp) != 0) {
    -				if (vn_count(vp) == 1 &&
    -				    (ip == mp->m_rootip ||
    -				     (mp->m_quotainfo &&
    -				      (ip->i_ino == mp->m_sb.sb_uquotino ||
    -				       ip->i_ino == mp->m_sb.sb_gquotino)))) {
    -					ip = ip->i_mnext;
    -					continue;
    -				}
    -				/*
    -				 * Ignore busy inodes but continue flushing
    -				 * others.
    -				 */
    -				ip = ip->i_mnext;
    -				continue;
    -			}
    -			/*
    -			 * Sample vp mapping while holding mp locked on MP
    -			 * systems, so we don't purge a reclaimed or
    -			 * nonexistent vnode.  We break from the loop
    -			 * since we know that we modify
    -			 * it by pulling ourselves from it in xfs_reclaim()
    -			 * called via vn_purge() below.  Set ip to the next
    -			 * entry in the list anyway so we'll know below
    -			 * whether we reached the end or not.
    -			 */
    -
    -			XFS_MOUNT_IUNLOCK(mp);
    -			vn_purge(vp);
    -			purged = 1;
    -			break;
    -		} while (ip != mp->m_inodes);
    -		/*
    -		 * We need to distinguish between when we exit the loop
    -		 * after a purge and when we simply hit the end of the
    -		 * list.  We can't use the (ip == mp->m_inodes) test,
    -		 * because when we purge an inode at the start of the list
    -		 * the next inode on the list becomes mp->m_inodes.  That
    -		 * would cause such a test to bail out early.  The purged
    -		 * variable tells us how we got out of the loop.
    -		 */
    -		if (!purged) {
    -			done = 1;
    -		}
    -	}
    -	XFS_MOUNT_IUNLOCK(mp);
    -}
    -
    -/*
    - * xfs_iaccess: check accessibility of inode for mode.
    - * This function is quite linuxy now
    - * probably should be move to a os specfic location
    - */
    -int
    -xfs_iaccess(
    -	xfs_inode_t	*ip,
    -	accmode_t	accmode,
    -	cred_t		*cr)
    -{
    -	xfs_vnode_t	*vp;
    -	int		error;
    -
    -	mode_t		imode;
    -
    -	vp = XFS_ITOV(ip);
    -	/* FreeBSD local change here */
    -	imode = (ip->i_d.di_mode & MODEMASK) | VTTOIF(vp->v_vnode->v_type);
    -	/*
    -	 * Verify that the MAC policy allows the requested access.
    -	 */
    -	if ((error = _MAC_XFS_IACCESS(ip, accmode, cr)))
    -		return XFS_ERROR(error);
    -
    -	if (accmode & VWRITE) {
    -		xfs_mount_t	*mp = ip->i_mount;
    -
    -		if ((XVFSTOMNT(XFS_MTOVFS(mp))->mnt_flag & MNT_RDONLY) &&
    -		    (S_ISREG(imode) || S_ISDIR(imode) || S_ISLNK(imode)))
    -			return XFS_ERROR(EROFS);
    -
    -#ifdef XXXKAN
    -		if (IS_IMMUTABLE(inode))
    -			return XFS_ERROR(EACCES);
    -#endif
    -	}
    -
    -	/*
    -	 * If there's an Access Control List it's used instead of
    -	 * the mode bits.
    -	 */
    -	if ((error = _ACL_XFS_IACCESS(ip, accmode, cr)) != -1)
    -		return error ? XFS_ERROR(error) : 0;
    -
    -
    -	/* FreeBSD local change here */
    -	error = vaccess(vp->v_vnode->v_type, imode, ip->i_d.di_uid, ip->i_d.di_gid,
    -	    accmode, cr, NULL);
    -
    -	return (error);
    -}
    -
    -/*
    - * xfs_iroundup: round up argument to next power of two
    - */
    -uint
    -xfs_iroundup(
    -	uint	v)
    -{
    -	int i;
    -	uint m;
    -
    -	if ((v & (v - 1)) == 0)
    -		return v;
    -	ASSERT((v & 0x80000000) == 0);
    -	if ((v & (v + 1)) == 0)
    -		return v + 1;
    -	for (i = 0, m = 1; i < 31; i++, m <<= 1) {
    -		if (v & m)
    -			continue;
    -		v |= m;
    -		if ((v & (v + 1)) == 0)
    -			return v + 1;
    -	}
    -	ASSERT(0);
    -	return( 0 );
    -}
    -
    -#ifdef XFS_ILOCK_TRACE
    -ktrace_t	*xfs_ilock_trace_buf;
    -
    -void
    -xfs_ilock_trace(xfs_inode_t *ip, int lock, unsigned int lockflags, inst_t *ra)
    -{
    -	ktrace_enter(ip->i_lock_trace,
    -		     (void *)ip,
    -		     (void *)(unsigned long)lock, /* 1 = LOCK, 3=UNLOCK, etc */
    -		     (void *)(unsigned long)lockflags, /* XFS_ILOCK_EXCL etc */
    -		     (void *)ra,		/* caller of ilock */
    -		     (void *)(unsigned long)current_cpu(),
    -		     (void *)(unsigned long)current_pid(),
    -		     NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
    -}
    -#endif
    -
    -/*
    - * Return a pointer to the extent record at file index idx.
    - */
    -xfs_bmbt_rec_t *
    -xfs_iext_get_ext(
    -	xfs_ifork_t	*ifp,		/* inode fork pointer */
    -	xfs_extnum_t	idx)		/* index of target extent */
    -{
    -	ASSERT(idx >= 0);
    -	if ((ifp->if_flags & XFS_IFEXTIREC) && (idx == 0)) {
    -		return ifp->if_u1.if_ext_irec->er_extbuf;
    -	} else if (ifp->if_flags & XFS_IFEXTIREC) {
    -		xfs_ext_irec_t	*erp;		/* irec pointer */
    -		int		erp_idx = 0;	/* irec index */
    -		xfs_extnum_t	page_idx = idx;	/* ext index in target list */
    -
    -		erp = xfs_iext_idx_to_irec(ifp, &page_idx, &erp_idx, 0);
    -		return &erp->er_extbuf[page_idx];
    -	} else if (ifp->if_bytes) {
    -		return &ifp->if_u1.if_extents[idx];
    -	} else {
    -		return NULL;
    -	}
    -}
    -
    -/*
    - * Insert new item(s) into the extent records for incore inode
    - * fork 'ifp'.  'count' new items are inserted at index 'idx'.
    - */
    -void
    -xfs_iext_insert(
    -	xfs_ifork_t	*ifp,		/* inode fork pointer */
    -	xfs_extnum_t	idx,		/* starting index of new items */
    -	xfs_extnum_t	count,		/* number of inserted items */
    -	xfs_bmbt_irec_t	*new)		/* items to insert */
    -{
    -	xfs_bmbt_rec_t	*ep;		/* extent record pointer */
    -	xfs_extnum_t	i;		/* extent record index */
    -
    -	ASSERT(ifp->if_flags & XFS_IFEXTENTS);
    -	xfs_iext_add(ifp, idx, count);
    -	for (i = idx; i < idx + count; i++, new++) {
    -		ep = xfs_iext_get_ext(ifp, i);
    -		xfs_bmbt_set_all(ep, new);
    -	}
    -}
    -
    -/*
    - * This is called when the amount of space required for incore file
    - * extents needs to be increased. The ext_diff parameter stores the
    - * number of new extents being added and the idx parameter contains
    - * the extent index where the new extents will be added. If the new
    - * extents are being appended, then we just need to (re)allocate and
    - * initialize the space. Otherwise, if the new extents are being
    - * inserted into the middle of the existing entries, a bit more work
    - * is required to make room for the new extents to be inserted. The
    - * caller is responsible for filling in the new extent entries upon
    - * return.
    - */
    -void
    -xfs_iext_add(
    -	xfs_ifork_t	*ifp,		/* inode fork pointer */
    -	xfs_extnum_t	idx,		/* index to begin adding exts */
    -	int		ext_diff)	/* number of extents to add */
    -{
    -	int		byte_diff;	/* new bytes being added */
    -	int		new_size;	/* size of extents after adding */
    -	xfs_extnum_t	nextents;	/* number of extents in file */
    -
    -	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
    -	ASSERT((idx >= 0) && (idx <= nextents));
    -	byte_diff = ext_diff * sizeof(xfs_bmbt_rec_t);
    -	new_size = ifp->if_bytes + byte_diff;
    -	/*
    -	 * If the new number of extents (nextents + ext_diff)
    -	 * fits inside the inode, then continue to use the inline
    -	 * extent buffer.
    -	 */
    -	if (nextents + ext_diff <= XFS_INLINE_EXTS) {
    -		if (idx < nextents) {
    -			memmove(&ifp->if_u2.if_inline_ext[idx + ext_diff],
    -				&ifp->if_u2.if_inline_ext[idx],
    -				(nextents - idx) * sizeof(xfs_bmbt_rec_t));
    -			memset(&ifp->if_u2.if_inline_ext[idx], 0, byte_diff);
    -		}
    -		ifp->if_u1.if_extents = ifp->if_u2.if_inline_ext;
    -		ifp->if_real_bytes = 0;
    -		ifp->if_lastex = nextents + ext_diff;
    -	}
    -	/*
    -	 * Otherwise use a linear (direct) extent list.
    -	 * If the extents are currently inside the inode,
    -	 * xfs_iext_realloc_direct will switch us from
    -	 * inline to direct extent allocation mode.
    -	 */
    -	else if (nextents + ext_diff <= XFS_LINEAR_EXTS) {
    -		xfs_iext_realloc_direct(ifp, new_size);
    -		if (idx < nextents) {
    -			memmove(&ifp->if_u1.if_extents[idx + ext_diff],
    -				&ifp->if_u1.if_extents[idx],
    -				(nextents - idx) * sizeof(xfs_bmbt_rec_t));
    -			memset(&ifp->if_u1.if_extents[idx], 0, byte_diff);
    -		}
    -	}
    -	/* Indirection array */
    -	else {
    -		xfs_ext_irec_t	*erp;
    -		int		erp_idx = 0;
    -		int		page_idx = idx;
    -
    -		ASSERT(nextents + ext_diff > XFS_LINEAR_EXTS);
    -		if (ifp->if_flags & XFS_IFEXTIREC) {
    -			erp = xfs_iext_idx_to_irec(ifp, &page_idx, &erp_idx, 1);
    -		} else {
    -			xfs_iext_irec_init(ifp);
    -			ASSERT(ifp->if_flags & XFS_IFEXTIREC);
    -			erp = ifp->if_u1.if_ext_irec;
    -		}
    -		/* Extents fit in target extent page */
    -		if (erp && erp->er_extcount + ext_diff <= XFS_LINEAR_EXTS) {
    -			if (page_idx < erp->er_extcount) {
    -				memmove(&erp->er_extbuf[page_idx + ext_diff],
    -					&erp->er_extbuf[page_idx],
    -					(erp->er_extcount - page_idx) *
    -					sizeof(xfs_bmbt_rec_t));
    -				memset(&erp->er_extbuf[page_idx], 0, byte_diff);
    -			}
    -			erp->er_extcount += ext_diff;
    -			xfs_iext_irec_update_extoffs(ifp, erp_idx + 1, ext_diff);
    -		}
    -		/* Insert a new extent page */
    -		else if (erp) {
    -			xfs_iext_add_indirect_multi(ifp,
    -				erp_idx, page_idx, ext_diff);
    -		}
    -		/*
    -		 * If extent(s) are being appended to the last page in
    -		 * the indirection array and the new extent(s) don't fit
    -		 * in the page, then erp is NULL and erp_idx is set to
    -		 * the next index needed in the indirection array.
    -		 */
    -		else {
    -			int	count = ext_diff;
    -
    -			while (count) {
    -				erp = xfs_iext_irec_new(ifp, erp_idx);
    -				erp->er_extcount = count;
    -				count -= MIN(count, (int)XFS_LINEAR_EXTS);
    -				if (count) {
    -					erp_idx++;
    -				}
    -			}
    -		}
    -	}
    -	ifp->if_bytes = new_size;
    -}
    -
    -/*
    - * This is called when incore extents are being added to the indirection
    - * array and the new extents do not fit in the target extent list. The
    - * erp_idx parameter contains the irec index for the target extent list
    - * in the indirection array, and the idx parameter contains the extent
    - * index within the list. The number of extents being added is stored
    - * in the count parameter.
    - *
    - *    |-------|   |-------|
    - *    |       |   |       |    idx - number of extents before idx
    - *    |  idx  |   | count |
    - *    |       |   |       |    count - number of extents being inserted at idx
    - *    |-------|   |-------|
    - *    | count |   | nex2  |    nex2 - number of extents after idx + count
    - *    |-------|   |-------|
    - */
    -void
    -xfs_iext_add_indirect_multi(
    -	xfs_ifork_t	*ifp,			/* inode fork pointer */
    -	int		erp_idx,		/* target extent irec index */
    -	xfs_extnum_t	idx,			/* index within target list */
    -	int		count)			/* new extents being added */
    -{
    -	int		byte_diff;		/* new bytes being added */
    -	xfs_ext_irec_t	*erp;			/* pointer to irec entry */
    -	xfs_extnum_t	ext_diff;		/* number of extents to add */
    -	xfs_extnum_t	ext_cnt;		/* new extents still needed */
    -	xfs_extnum_t	nex2;			/* extents after idx + count */
    -	xfs_bmbt_rec_t	*nex2_ep = NULL;	/* temp list for nex2 extents */
    -	int		nlists;			/* number of irec's (lists) */
    -
    -	ASSERT(ifp->if_flags & XFS_IFEXTIREC);
    -	erp = &ifp->if_u1.if_ext_irec[erp_idx];
    -	nex2 = erp->er_extcount - idx;
    -	nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ;
    -
    -	/*
    -	 * Save second part of target extent list
    -	 * (all extents past */
    -	if (nex2) {
    -		byte_diff = nex2 * sizeof(xfs_bmbt_rec_t);
    -		nex2_ep = (xfs_bmbt_rec_t *) kmem_alloc(byte_diff, KM_SLEEP);
    -		memmove(nex2_ep, &erp->er_extbuf[idx], byte_diff);
    -		erp->er_extcount -= nex2;
    -		xfs_iext_irec_update_extoffs(ifp, erp_idx + 1, -nex2);
    -		memset(&erp->er_extbuf[idx], 0, byte_diff);
    -	}
    -
    -	/*
    -	 * Add the new extents to the end of the target
    -	 * list, then allocate new irec record(s) and
    -	 * extent buffer(s) as needed to store the rest
    -	 * of the new extents.
    -	 */
    -	ext_cnt = count;
    -	ext_diff = MIN(ext_cnt, (int)XFS_LINEAR_EXTS - erp->er_extcount);
    -	if (ext_diff) {
    -		erp->er_extcount += ext_diff;
    -		xfs_iext_irec_update_extoffs(ifp, erp_idx + 1, ext_diff);
    -		ext_cnt -= ext_diff;
    -	}
    -	while (ext_cnt) {
    -		erp_idx++;
    -		erp = xfs_iext_irec_new(ifp, erp_idx);
    -		ext_diff = MIN(ext_cnt, (int)XFS_LINEAR_EXTS);
    -		erp->er_extcount = ext_diff;
    -		xfs_iext_irec_update_extoffs(ifp, erp_idx + 1, ext_diff);
    -		ext_cnt -= ext_diff;
    -	}
    -
    -	/* Add nex2 extents back to indirection array */
    -	if (nex2) {
    -		xfs_extnum_t	ext_avail;
    -		int		i;
    -
    -		byte_diff = nex2 * sizeof(xfs_bmbt_rec_t);
    -		ext_avail = XFS_LINEAR_EXTS - erp->er_extcount;
    -		i = 0;
    -		/*
    -		 * If nex2 extents fit in the current page, append
    -		 * nex2_ep after the new extents.
    -		 */
    -		if (nex2 <= ext_avail) {
    -			i = erp->er_extcount;
    -		}
    -		/*
    -		 * Otherwise, check if space is available in the
    -		 * next page.
    -		 */
    -		else if ((erp_idx < nlists - 1) &&
    -			 (nex2 <= (ext_avail = XFS_LINEAR_EXTS -
    -			  ifp->if_u1.if_ext_irec[erp_idx+1].er_extcount))) {
    -			erp_idx++;
    -			erp++;
    -			/* Create a hole for nex2 extents */
    -			memmove(&erp->er_extbuf[nex2], erp->er_extbuf,
    -				erp->er_extcount * sizeof(xfs_bmbt_rec_t));
    -		}
    -		/*
    -		 * Final choice, create a new extent page for
    -		 * nex2 extents.
    -		 */
    -		else {
    -			erp_idx++;
    -			erp = xfs_iext_irec_new(ifp, erp_idx);
    -		}
    -		memmove(&erp->er_extbuf[i], nex2_ep, byte_diff);
    -		kmem_free(nex2_ep, byte_diff);
    -		erp->er_extcount += nex2;
    -		xfs_iext_irec_update_extoffs(ifp, erp_idx + 1, nex2);
    -	}
    -}
    -
    -/*
    - * This is called when the amount of space required for incore file
    - * extents needs to be decreased. The ext_diff parameter stores the
    - * number of extents to be removed and the idx parameter contains
    - * the extent index where the extents will be removed from.
    - *
    - * If the amount of space needed has decreased below the linear
    - * limit, XFS_IEXT_BUFSZ, then switch to using the contiguous
    - * extent array.  Otherwise, use kmem_realloc() to adjust the
    - * size to what is needed.
    - */
    -void
    -xfs_iext_remove(
    -	xfs_ifork_t	*ifp,		/* inode fork pointer */
    -	xfs_extnum_t	idx,		/* index to begin removing exts */
    -	int		ext_diff)	/* number of extents to remove */
    -{
    -	xfs_extnum_t	nextents;	/* number of extents in file */
    -	int		new_size;	/* size of extents after removal */
    -
    -	ASSERT(ext_diff > 0);
    -	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
    -	new_size = (nextents - ext_diff) * sizeof(xfs_bmbt_rec_t);
    -
    -	if (new_size == 0) {
    -		xfs_iext_destroy(ifp);
    -	} else if (ifp->if_flags & XFS_IFEXTIREC) {
    -		xfs_iext_remove_indirect(ifp, idx, ext_diff);
    -	} else if (ifp->if_real_bytes) {
    -		xfs_iext_remove_direct(ifp, idx, ext_diff);
    -	} else {
    -		xfs_iext_remove_inline(ifp, idx, ext_diff);
    -	}
    -	ifp->if_bytes = new_size;
    -}
    -
    -/*
    - * This removes ext_diff extents from the inline buffer, beginning
    - * at extent index idx.
    - */
    -void
    -xfs_iext_remove_inline(
    -	xfs_ifork_t	*ifp,		/* inode fork pointer */
    -	xfs_extnum_t	idx,		/* index to begin removing exts */
    -	int		ext_diff)	/* number of extents to remove */
    -{
    -	int		nextents;	/* number of extents in file */
    -
    -	ASSERT(!(ifp->if_flags & XFS_IFEXTIREC));
    -	ASSERT(idx < XFS_INLINE_EXTS);
    -	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
    -	ASSERT(((nextents - ext_diff) > 0) &&
    -		(nextents - ext_diff) < XFS_INLINE_EXTS);
    -
    -	if (idx + ext_diff < nextents) {
    -		memmove(&ifp->if_u2.if_inline_ext[idx],
    -			&ifp->if_u2.if_inline_ext[idx + ext_diff],
    -			(nextents - (idx + ext_diff)) *
    -			 sizeof(xfs_bmbt_rec_t));
    -		memset(&ifp->if_u2.if_inline_ext[nextents - ext_diff],
    -			0, ext_diff * sizeof(xfs_bmbt_rec_t));
    -	} else {
    -		memset(&ifp->if_u2.if_inline_ext[idx], 0,
    -			ext_diff * sizeof(xfs_bmbt_rec_t));
    -	}
    -}
    -
    -/*
    - * This removes ext_diff extents from a linear (direct) extent list,
    - * beginning at extent index idx. If the extents are being removed
    - * from the end of the list (ie. truncate) then we just need to re-
    - * allocate the list to remove the extra space. Otherwise, if the
    - * extents are being removed from the middle of the existing extent
    - * entries, then we first need to move the extent records beginning
    - * at idx + ext_diff up in the list to overwrite the records being
    - * removed, then remove the extra space via kmem_realloc.
    - */
    -void
    -xfs_iext_remove_direct(
    -	xfs_ifork_t	*ifp,		/* inode fork pointer */
    -	xfs_extnum_t	idx,		/* index to begin removing exts */
    -	int		ext_diff)	/* number of extents to remove */
    -{
    -	xfs_extnum_t	nextents;	/* number of extents in file */
    -	int		new_size;	/* size of extents after removal */
    -
    -	ASSERT(!(ifp->if_flags & XFS_IFEXTIREC));
    -	new_size = ifp->if_bytes -
    -		(ext_diff * sizeof(xfs_bmbt_rec_t));
    -	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
    -
    -	if (new_size == 0) {
    -		xfs_iext_destroy(ifp);
    -		return;
    -	}
    -	/* Move extents up in the list (if needed) */
    -	if (idx + ext_diff < nextents) {
    -		memmove(&ifp->if_u1.if_extents[idx],
    -			&ifp->if_u1.if_extents[idx + ext_diff],
    -			(nextents - (idx + ext_diff)) *
    -			 sizeof(xfs_bmbt_rec_t));
    -	}
    -	memset(&ifp->if_u1.if_extents[nextents - ext_diff],
    -		0, ext_diff * sizeof(xfs_bmbt_rec_t));
    -	/*
    -	 * Reallocate the direct extent list. If the extents
    -	 * will fit inside the inode then xfs_iext_realloc_direct
    -	 * will switch from direct to inline extent allocation
    -	 * mode for us.
    -	 */
    -	xfs_iext_realloc_direct(ifp, new_size);
    -	ifp->if_bytes = new_size;
    -}
    -
    -/*
    - * This is called when incore extents are being removed from the
    - * indirection array and the extents being removed span multiple extent
    - * buffers. The idx parameter contains the file extent index where we
    - * want to begin removing extents, and the count parameter contains
    - * how many extents need to be removed.
    - *
    - *    |-------|   |-------|
    - *    | nex1  |   |       |    nex1 - number of extents before idx
    - *    |-------|   | count |
    - *    |       |   |       |    count - number of extents being removed at idx
    - *    | count |   |-------|
    - *    |       |   | nex2  |    nex2 - number of extents after idx + count
    - *    |-------|   |-------|
    - */
    -void
    -xfs_iext_remove_indirect(
    -	xfs_ifork_t	*ifp,		/* inode fork pointer */
    -	xfs_extnum_t	idx,		/* index to begin removing extents */
    -	int		count)		/* number of extents to remove */
    -{
    -	xfs_ext_irec_t	*erp;		/* indirection array pointer */
    -	int		erp_idx = 0;	/* indirection array index */
    -	xfs_extnum_t	ext_cnt;	/* extents left to remove */
    -	xfs_extnum_t	ext_diff;	/* extents to remove in current list */
    -	xfs_extnum_t	nex1;		/* number of extents before idx */
    -	xfs_extnum_t	nex2;		/* extents after idx + count */
    -	int		nlists;		/* entries in indirection array */
    -	int		page_idx = idx;	/* index in target extent list */
    -
    -	ASSERT(ifp->if_flags & XFS_IFEXTIREC);
    -	erp = xfs_iext_idx_to_irec(ifp,  &page_idx, &erp_idx, 0);
    -	ASSERT(erp != NULL);
    -	nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ;
    -	nex1 = page_idx;
    -	ext_cnt = count;
    -	while (ext_cnt) {
    -		nex2 = MAX((erp->er_extcount - (nex1 + ext_cnt)), 0);
    -		ext_diff = MIN(ext_cnt, (erp->er_extcount - nex1));
    -		/*
    -		 * Check for deletion of entire list;
    -		 * xfs_iext_irec_remove() updates extent offsets.
    -		 */
    -		if (ext_diff == erp->er_extcount) {
    -			xfs_iext_irec_remove(ifp, erp_idx);
    -			ext_cnt -= ext_diff;
    -			nex1 = 0;
    -			if (ext_cnt) {
    -				ASSERT(erp_idx < ifp->if_real_bytes /
    -					XFS_IEXT_BUFSZ);
    -				erp = &ifp->if_u1.if_ext_irec[erp_idx];
    -				nex1 = 0;
    -				continue;
    -			} else {
    -				break;
    -			}
    -		}
    -		/* Move extents up (if needed) */
    -		if (nex2) {
    -			memmove(&erp->er_extbuf[nex1],
    -				&erp->er_extbuf[nex1 + ext_diff],
    -				nex2 * sizeof(xfs_bmbt_rec_t));
    -		}
    -		/* Zero out rest of page */
    -		memset(&erp->er_extbuf[nex1 + nex2], 0, (XFS_IEXT_BUFSZ -
    -			((nex1 + nex2) * sizeof(xfs_bmbt_rec_t))));
    -		/* Update remaining counters */
    -		erp->er_extcount -= ext_diff;
    -		xfs_iext_irec_update_extoffs(ifp, erp_idx + 1, -ext_diff);
    -		ext_cnt -= ext_diff;
    -		nex1 = 0;
    -		erp_idx++;
    -		erp++;
    -	}
    -	ifp->if_bytes -= count * sizeof(xfs_bmbt_rec_t);
    -	xfs_iext_irec_compact(ifp);
    -}
    -
    -/*
    - * Create, destroy, or resize a linear (direct) block of extents.
    - */
    -void
    -xfs_iext_realloc_direct(
    -	xfs_ifork_t	*ifp,		/* inode fork pointer */
    -	int		new_size)	/* new size of extents */
    -{
    -	int		rnew_size;	/* real new size of extents */
    -
    -	rnew_size = new_size;
    -
    -	ASSERT(!(ifp->if_flags & XFS_IFEXTIREC) ||
    -		((new_size >= 0) && (new_size <= XFS_IEXT_BUFSZ) &&
    -		 (new_size != ifp->if_real_bytes)));
    -
    -	/* Free extent records */
    -	if (new_size == 0) {
    -		xfs_iext_destroy(ifp);
    -	}
    -	/* Resize direct extent list and zero any new bytes */
    -	else if (ifp->if_real_bytes) {
    -		/* Check if extents will fit inside the inode */
    -		if (new_size <= XFS_INLINE_EXTS * sizeof(xfs_bmbt_rec_t)) {
    -			xfs_iext_direct_to_inline(ifp, new_size /
    -				(uint)sizeof(xfs_bmbt_rec_t));
    -			ifp->if_bytes = new_size;
    -			return;
    -		}
    -		if ((new_size & (new_size - 1)) != 0) {
    -			rnew_size = xfs_iroundup(new_size);
    -		}
    -		if (rnew_size != ifp->if_real_bytes) {
    -			ifp->if_u1.if_extents = (xfs_bmbt_rec_t *)
    -				kmem_realloc(ifp->if_u1.if_extents,
    -						rnew_size,
    -						ifp->if_real_bytes,
    -						KM_SLEEP);
    -		}
    -		if (rnew_size > ifp->if_real_bytes) {
    -			memset(&ifp->if_u1.if_extents[ifp->if_bytes /
    -				(uint)sizeof(xfs_bmbt_rec_t)], 0,
    -				rnew_size - ifp->if_real_bytes);
    -		}
    -	}
    -	/*
    -	 * Switch from the inline extent buffer to a direct
    -	 * extent list. Be sure to include the inline extent
    -	 * bytes in new_size.
    -	 */
    -	else {
    -		new_size += ifp->if_bytes;
    -		if ((new_size & (new_size - 1)) != 0) {
    -			rnew_size = xfs_iroundup(new_size);
    -		}
    -		xfs_iext_inline_to_direct(ifp, rnew_size);
    -	}
    -	ifp->if_real_bytes = rnew_size;
    -	ifp->if_bytes = new_size;
    -}
    -
    -/*
    - * Switch from linear (direct) extent records to inline buffer.
    - */
    -void
    -xfs_iext_direct_to_inline(
    -	xfs_ifork_t	*ifp,		/* inode fork pointer */
    -	xfs_extnum_t	nextents)	/* number of extents in file */
    -{
    -	ASSERT(ifp->if_flags & XFS_IFEXTENTS);
    -	ASSERT(nextents <= XFS_INLINE_EXTS);
    -	/*
    -	 * The inline buffer was zeroed when we switched
    -	 * from inline to direct extent allocation mode,
    -	 * so we don't need to clear it here.
    -	 */
    -	memcpy(ifp->if_u2.if_inline_ext, ifp->if_u1.if_extents,
    -		nextents * sizeof(xfs_bmbt_rec_t));
    -	kmem_free(ifp->if_u1.if_extents, KM_SLEEP);
    -	ifp->if_u1.if_extents = ifp->if_u2.if_inline_ext;
    -	ifp->if_real_bytes = 0;
    -}
    -
    -/*
    - * Switch from inline buffer to linear (direct) extent records.
    - * new_size should already be rounded up to the next power of 2
    - * by the caller (when appropriate), so use new_size as it is.
    - * However, since new_size may be rounded up, we can't update
    - * if_bytes here. It is the caller's responsibility to update
    - * if_bytes upon return.
    - */
    -void
    -xfs_iext_inline_to_direct(
    -	xfs_ifork_t	*ifp,		/* inode fork pointer */
    -	int		new_size)	/* number of extents in file */
    -{
    -	ifp->if_u1.if_extents = (xfs_bmbt_rec_t *)
    -		kmem_alloc(new_size, KM_SLEEP);
    -	memset(ifp->if_u1.if_extents, 0, new_size);
    -	if (ifp->if_bytes) {
    -		memcpy(ifp->if_u1.if_extents, ifp->if_u2.if_inline_ext,
    -			ifp->if_bytes);
    -		memset(ifp->if_u2.if_inline_ext, 0, XFS_INLINE_EXTS *
    -			sizeof(xfs_bmbt_rec_t));
    -	}
    -	ifp->if_real_bytes = new_size;
    -}
    -
    -/*
    - * Resize an extent indirection array to new_size bytes.
    - */
    -void
    -xfs_iext_realloc_indirect(
    -	xfs_ifork_t	*ifp,		/* inode fork pointer */
    -	int		new_size)	/* new indirection array size */
    -{
    -	int		nlists;		/* number of irec's (ex lists) */
    -	int		size;		/* current indirection array size */
    -
    -	ASSERT(ifp->if_flags & XFS_IFEXTIREC);
    -	nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ;
    -	size = nlists * sizeof(xfs_ext_irec_t);
    -	ASSERT(ifp->if_real_bytes);
    -	ASSERT((new_size >= 0) && (new_size != size));
    -	if (new_size == 0) {
    -		xfs_iext_destroy(ifp);
    -	} else {
    -		ifp->if_u1.if_ext_irec = (xfs_ext_irec_t *)
    -			kmem_realloc(ifp->if_u1.if_ext_irec,
    -				new_size, size, KM_SLEEP);
    -	}
    -}
    -
    -/*
    - * Switch from indirection array to linear (direct) extent allocations.
    - */
    -void
    -xfs_iext_indirect_to_direct(
    -	 xfs_ifork_t	*ifp)		/* inode fork pointer */
    -{
    -	xfs_bmbt_rec_t	*ep;		/* extent record pointer */
    -	xfs_extnum_t	nextents;	/* number of extents in file */
    -	int		size;		/* size of file extents */
    -
    -	ASSERT(ifp->if_flags & XFS_IFEXTIREC);
    -	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
    -	ASSERT(nextents <= XFS_LINEAR_EXTS);
    -	size = nextents * sizeof(xfs_bmbt_rec_t);
    -
    -	xfs_iext_irec_compact_full(ifp);
    -	ASSERT(ifp->if_real_bytes == XFS_IEXT_BUFSZ);
    -
    -	ep = ifp->if_u1.if_ext_irec->er_extbuf;
    -	kmem_free(ifp->if_u1.if_ext_irec, sizeof(xfs_ext_irec_t));
    -	ifp->if_flags &= ~XFS_IFEXTIREC;
    -	ifp->if_u1.if_extents = ep;
    -	ifp->if_bytes = size;
    -	if (nextents < XFS_LINEAR_EXTS) {
    -		xfs_iext_realloc_direct(ifp, size);
    -	}
    -}
    -
    -/*
    - * Free incore file extents.
    - */
    -void
    -xfs_iext_destroy(
    -	xfs_ifork_t	*ifp)		/* inode fork pointer */
    -{
    -	if (ifp->if_flags & XFS_IFEXTIREC) {
    -		int	erp_idx;
    -		int	nlists;
    -
    -		nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ;
    -		for (erp_idx = nlists - 1; erp_idx >= 0 ; erp_idx--) {
    -			xfs_iext_irec_remove(ifp, erp_idx);
    -		}
    -		ifp->if_flags &= ~XFS_IFEXTIREC;
    -	} else if (ifp->if_real_bytes) {
    -		kmem_free(ifp->if_u1.if_extents, ifp->if_real_bytes);
    -	} else if (ifp->if_bytes) {
    -		memset(ifp->if_u2.if_inline_ext, 0, XFS_INLINE_EXTS *
    -			sizeof(xfs_bmbt_rec_t));
    -	}
    -	ifp->if_u1.if_extents = NULL;
    -	ifp->if_real_bytes = 0;
    -	ifp->if_bytes = 0;
    -}
    -
    -/*
    - * Return a pointer to the extent record for file system block bno.
    - */
    -xfs_bmbt_rec_t *			/* pointer to found extent record */
    -xfs_iext_bno_to_ext(
    -	xfs_ifork_t	*ifp,		/* inode fork pointer */
    -	xfs_fileoff_t	bno,		/* block number to search for */
    -	xfs_extnum_t	*idxp)		/* index of target extent */
    -{
    -	xfs_bmbt_rec_t	*base;		/* pointer to first extent */
    -	xfs_filblks_t	blockcount = 0;	/* number of blocks in extent */
    -	xfs_bmbt_rec_t	*ep = NULL;	/* pointer to target extent */
    -	xfs_ext_irec_t	*erp = NULL;	/* indirection array pointer */
    -	int		high;		/* upper boundary in search */
    -	xfs_extnum_t	idx = 0;	/* index of target extent */
    -	int		low;		/* lower boundary in search */
    -	xfs_extnum_t	nextents;	/* number of file extents */
    -	xfs_fileoff_t	startoff = 0;	/* start offset of extent */
    -
    -	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
    -	if (nextents == 0) {
    -		*idxp = 0;
    -		return NULL;
    -	}
    -	low = 0;
    -	if (ifp->if_flags & XFS_IFEXTIREC) {
    -		/* Find target extent list */
    -		int	erp_idx = 0;
    -		erp = xfs_iext_bno_to_irec(ifp, bno, &erp_idx);
    -		base = erp->er_extbuf;
    -		high = erp->er_extcount - 1;
    -	} else {
    -		base = ifp->if_u1.if_extents;
    -		high = nextents - 1;
    -	}
    -	/* Binary search extent records */
    -	while (low <= high) {
    -		idx = (low + high) >> 1;
    -		ep = base + idx;
    -		startoff = xfs_bmbt_get_startoff(ep);
    -		blockcount = xfs_bmbt_get_blockcount(ep);
    -		if (bno < startoff) {
    -			high = idx - 1;
    -		} else if (bno >= startoff + blockcount) {
    -			low = idx + 1;
    -		} else {
    -			/* Convert back to file-based extent index */
    -			if (ifp->if_flags & XFS_IFEXTIREC) {
    -				idx += erp->er_extoff;
    -			}
    -			*idxp = idx;
    -			return ep;
    -		}
    -	}
    -	/* Convert back to file-based extent index */
    -	if (ifp->if_flags & XFS_IFEXTIREC) {
    -		idx += erp->er_extoff;
    -	}
    -	if (bno >= startoff + blockcount) {
    -		if (++idx == nextents) {
    -			ep = NULL;
    -		} else {
    -			ep = xfs_iext_get_ext(ifp, idx);
    -		}
    -	}
    -	*idxp = idx;
    -	return ep;
    -}
    -
    -/*
    - * Return a pointer to the indirection array entry containing the
    - * extent record for filesystem block bno. Store the index of the
    - * target irec in *erp_idxp.
    - */
    -xfs_ext_irec_t *			/* pointer to found extent record */
    -xfs_iext_bno_to_irec(
    -	xfs_ifork_t	*ifp,		/* inode fork pointer */
    -	xfs_fileoff_t	bno,		/* block number to search for */
    -	int		*erp_idxp)	/* irec index of target ext list */
    -{
    -	xfs_ext_irec_t	*erp = NULL;	/* indirection array pointer */
    -	xfs_ext_irec_t	*erp_next;	/* next indirection array entry */
    -	int		erp_idx;	/* indirection array index */
    -	int		nlists;		/* number of extent irec's (lists) */
    -	int		high;		/* binary search upper limit */
    -	int		low;		/* binary search lower limit */
    -
    -	ASSERT(ifp->if_flags & XFS_IFEXTIREC);
    -	nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ;
    -	erp_idx = 0;
    -	low = 0;
    -	high = nlists - 1;
    -	while (low <= high) {
    -		erp_idx = (low + high) >> 1;
    -		erp = &ifp->if_u1.if_ext_irec[erp_idx];
    -		erp_next = erp_idx < nlists - 1 ? erp + 1 : NULL;
    -		if (bno < xfs_bmbt_get_startoff(erp->er_extbuf)) {
    -			high = erp_idx - 1;
    -		} else if (erp_next && bno >=
    -			   xfs_bmbt_get_startoff(erp_next->er_extbuf)) {
    -			low = erp_idx + 1;
    -		} else {
    -			break;
    -		}
    -	}
    -	*erp_idxp = erp_idx;
    -	return erp;
    -}
    -
    -/*
    - * Return a pointer to the indirection array entry containing the
    - * extent record at file extent index *idxp. Store the index of the
    - * target irec in *erp_idxp and store the page index of the target
    - * extent record in *idxp.
    - */
    -xfs_ext_irec_t *
    -xfs_iext_idx_to_irec(
    -	xfs_ifork_t	*ifp,		/* inode fork pointer */
    -	xfs_extnum_t	*idxp,		/* extent index (file -> page) */
    -	int		*erp_idxp,	/* pointer to target irec */
    -	int		realloc)	/* new bytes were just added */
    -{
    -	xfs_ext_irec_t	*prev;		/* pointer to previous irec */
    -	xfs_ext_irec_t	*erp = NULL;	/* pointer to current irec */
    -	int		erp_idx;	/* indirection array index */
    -	int		nlists;		/* number of irec's (ex lists) */
    -	int		high;		/* binary search upper limit */
    -	int		low;		/* binary search lower limit */
    -	xfs_extnum_t	page_idx = *idxp; /* extent index in target list */
    -
    -	ASSERT(ifp->if_flags & XFS_IFEXTIREC);
    -	ASSERT(page_idx >= 0 && page_idx <=
    -		ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t));
    -	nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ;
    -	erp_idx = 0;
    -	low = 0;
    -	high = nlists - 1;
    -
    -	/* Binary search extent irec's */
    -	while (low <= high) {
    -		erp_idx = (low + high) >> 1;
    -		erp = &ifp->if_u1.if_ext_irec[erp_idx];
    -		prev = erp_idx > 0 ? erp - 1 : NULL;
    -		if (page_idx < erp->er_extoff || (page_idx == erp->er_extoff &&
    -		     realloc && prev && prev->er_extcount < XFS_LINEAR_EXTS)) {
    -			high = erp_idx - 1;
    -		} else if (page_idx > erp->er_extoff + erp->er_extcount ||
    -			   (page_idx == erp->er_extoff + erp->er_extcount &&
    -			    !realloc)) {
    -			low = erp_idx + 1;
    -		} else if (page_idx == erp->er_extoff + erp->er_extcount &&
    -			   erp->er_extcount == XFS_LINEAR_EXTS) {
    -			ASSERT(realloc);
    -			page_idx = 0;
    -			erp_idx++;
    -			erp = erp_idx < nlists ? erp + 1 : NULL;
    -			break;
    -		} else {
    -			page_idx -= erp->er_extoff;
    -			break;
    -		}
    -	}
    -	*idxp = page_idx;
    -	*erp_idxp = erp_idx;
    -	return(erp);
    -}
    -
    -/*
    - * Allocate and initialize an indirection array once the space needed
    - * for incore extents increases above XFS_IEXT_BUFSZ.
    - */
    -void
    -xfs_iext_irec_init(
    -	xfs_ifork_t	*ifp)		/* inode fork pointer */
    -{
    -	xfs_ext_irec_t	*erp;		/* indirection array pointer */
    -	xfs_extnum_t	nextents;	/* number of extents in file */
    -
    -	ASSERT(!(ifp->if_flags & XFS_IFEXTIREC));
    -	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
    -	ASSERT(nextents <= XFS_LINEAR_EXTS);
    -
    -	erp = (xfs_ext_irec_t *)
    -		kmem_alloc(sizeof(xfs_ext_irec_t), KM_SLEEP);
    -
    -	if (nextents == 0) {
    -		ifp->if_u1.if_extents = (xfs_bmbt_rec_t *)
    -			kmem_alloc(XFS_IEXT_BUFSZ, KM_SLEEP);
    -	} else if (!ifp->if_real_bytes) {
    -		xfs_iext_inline_to_direct(ifp, XFS_IEXT_BUFSZ);
    -	} else if (ifp->if_real_bytes < XFS_IEXT_BUFSZ) {
    -		xfs_iext_realloc_direct(ifp, XFS_IEXT_BUFSZ);
    -	}
    -	erp->er_extbuf = ifp->if_u1.if_extents;
    -	erp->er_extcount = nextents;
    -	erp->er_extoff = 0;
    -
    -	ifp->if_flags |= XFS_IFEXTIREC;
    -	ifp->if_real_bytes = XFS_IEXT_BUFSZ;
    -	ifp->if_bytes = nextents * sizeof(xfs_bmbt_rec_t);
    -	ifp->if_u1.if_ext_irec = erp;
    -
    -	return;
    -}
    -
    -/*
    - * Allocate and initialize a new entry in the indirection array.
    - */
    -xfs_ext_irec_t *
    -xfs_iext_irec_new(
    -	xfs_ifork_t	*ifp,		/* inode fork pointer */
    -	int		erp_idx)	/* index for new irec */
    -{
    -	xfs_ext_irec_t	*erp;		/* indirection array pointer */
    -	int		i;		/* loop counter */
    -	int		nlists;		/* number of irec's (ex lists) */
    -
    -	ASSERT(ifp->if_flags & XFS_IFEXTIREC);
    -	nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ;
    -
    -	/* Resize indirection array */
    -	xfs_iext_realloc_indirect(ifp, ++nlists *
    -				  sizeof(xfs_ext_irec_t));
    -	/*
    -	 * Move records down in the array so the
    -	 * new page can use erp_idx.
    -	 */
    -	erp = ifp->if_u1.if_ext_irec;
    -	for (i = nlists - 1; i > erp_idx; i--) {
    -		memmove(&erp[i], &erp[i-1], sizeof(xfs_ext_irec_t));
    -	}
    -	ASSERT(i == erp_idx);
    -
    -	/* Initialize new extent record */
    -	erp = ifp->if_u1.if_ext_irec;
    -	erp[erp_idx].er_extbuf = (xfs_bmbt_rec_t *)
    -		kmem_alloc(XFS_IEXT_BUFSZ, KM_SLEEP);
    -	ifp->if_real_bytes = nlists * XFS_IEXT_BUFSZ;
    -	memset(erp[erp_idx].er_extbuf, 0, XFS_IEXT_BUFSZ);
    -	erp[erp_idx].er_extcount = 0;
    -	erp[erp_idx].er_extoff = erp_idx > 0 ?
    -		erp[erp_idx-1].er_extoff + erp[erp_idx-1].er_extcount : 0;
    -	return (&erp[erp_idx]);
    -}
    -
    -/*
    - * Remove a record from the indirection array.
    - */
    -void
    -xfs_iext_irec_remove(
    -	xfs_ifork_t	*ifp,		/* inode fork pointer */
    -	int		erp_idx)	/* irec index to remove */
    -{
    -	xfs_ext_irec_t	*erp;		/* indirection array pointer */
    -	int		i;		/* loop counter */
    -	int		nlists;		/* number of irec's (ex lists) */
    -
    -	ASSERT(ifp->if_flags & XFS_IFEXTIREC);
    -	nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ;
    -	erp = &ifp->if_u1.if_ext_irec[erp_idx];
    -	if (erp->er_extbuf) {
    -		xfs_iext_irec_update_extoffs(ifp, erp_idx + 1,
    -			-erp->er_extcount);
    -		kmem_free(erp->er_extbuf, XFS_IEXT_BUFSZ);
    -	}
    -	/* Compact extent records */
    -	erp = ifp->if_u1.if_ext_irec;
    -	for (i = erp_idx; i < nlists - 1; i++) {
    -		memmove(&erp[i], &erp[i+1], sizeof(xfs_ext_irec_t));
    -	}
    -	/*
    -	 * Manually free the last extent record from the indirection
    -	 * array.  A call to xfs_iext_realloc_indirect() with a size
    -	 * of zero would result in a call to xfs_iext_destroy() which
    -	 * would in turn call this function again, creating a nasty
    -	 * infinite loop.
    -	 */
    -	if (--nlists) {
    -		xfs_iext_realloc_indirect(ifp,
    -			nlists * sizeof(xfs_ext_irec_t));
    -	} else {
    -		kmem_free(ifp->if_u1.if_ext_irec,
    -			sizeof(xfs_ext_irec_t));
    -	}
    -	ifp->if_real_bytes = nlists * XFS_IEXT_BUFSZ;
    -}
    -
    -/*
    - * This is called to clean up large amounts of unused memory allocated
    - * by the indirection array.  Before compacting anything though, verify
    - * that the indirection array is still needed and switch back to the
    - * linear extent list (or even the inline buffer) if possible.  The
    - * compaction policy is as follows:
    - *
    - *    Full Compaction: Extents fit into a single page (or inline buffer)
    - *    Full Compaction: Extents occupy less than 10% of allocated space
    - * Partial Compaction: Extents occupy > 10% and < 50% of allocated space
    - *      No Compaction: Extents occupy at least 50% of allocated space
    - */
    -void
    -xfs_iext_irec_compact(
    -	xfs_ifork_t	*ifp)		/* inode fork pointer */
    -{
    -	xfs_extnum_t	nextents;	/* number of extents in file */
    -	int		nlists;		/* number of irec's (ex lists) */
    -
    -	ASSERT(ifp->if_flags & XFS_IFEXTIREC);
    -	nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ;
    -	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
    -
    -	if (nextents == 0) {
    -		xfs_iext_destroy(ifp);
    -	} else if (nextents <= XFS_INLINE_EXTS) {
    -		xfs_iext_indirect_to_direct(ifp);
    -		xfs_iext_direct_to_inline(ifp, nextents);
    -	} else if (nextents <= XFS_LINEAR_EXTS) {
    -		xfs_iext_indirect_to_direct(ifp);
    -	} else if (nextents < (nlists * XFS_LINEAR_EXTS) >> 3) {
    -		xfs_iext_irec_compact_full(ifp);
    -	} else if (nextents < (nlists * XFS_LINEAR_EXTS) >> 1) {
    -		xfs_iext_irec_compact_pages(ifp);
    -	}
    -}
    -
    -/*
    - * Combine extents from neighboring extent pages.
    - */
    -void
    -xfs_iext_irec_compact_pages(
    -	xfs_ifork_t	*ifp)		/* inode fork pointer */
    -{
    -	xfs_ext_irec_t	*erp, *erp_next;/* pointers to irec entries */
    -	int		erp_idx = 0;	/* indirection array index */
    -	int		nlists;		/* number of irec's (ex lists) */
    -
    -	ASSERT(ifp->if_flags & XFS_IFEXTIREC);
    -	nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ;
    -	while (erp_idx < nlists - 1) {
    -		erp = &ifp->if_u1.if_ext_irec[erp_idx];
    -		erp_next = erp + 1;
    -		if (erp_next->er_extcount <=
    -		    (XFS_LINEAR_EXTS - erp->er_extcount)) {
    -			memmove(&erp->er_extbuf[erp->er_extcount],
    -				erp_next->er_extbuf, erp_next->er_extcount *
    -				sizeof(xfs_bmbt_rec_t));
    -			erp->er_extcount += erp_next->er_extcount;
    -			/*
    -			 * Free page before removing extent record
    -			 * so er_extoffs don't get modified in
    -			 * xfs_iext_irec_remove.
    -			 */
    -			kmem_free(erp_next->er_extbuf, XFS_IEXT_BUFSZ);
    -			erp_next->er_extbuf = NULL;
    -			xfs_iext_irec_remove(ifp, erp_idx + 1);
    -			nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ;
    -		} else {
    -			erp_idx++;
    -		}
    -	}
    -}
    -
    -/*
    - * Fully compact the extent records managed by the indirection array.
    - */
    -void
    -xfs_iext_irec_compact_full(
    -	xfs_ifork_t	*ifp)			/* inode fork pointer */
    -{
    -	xfs_bmbt_rec_t	*ep, *ep_next;		/* extent record pointers */
    -	xfs_ext_irec_t	*erp, *erp_next;	/* extent irec pointers */
    -	int		erp_idx = 0;		/* extent irec index */
    -	int		ext_avail;		/* empty entries in ex list */
    -	int		ext_diff;		/* number of exts to add */
    -	int		nlists;			/* number of irec's (ex lists) */
    -
    -	ASSERT(ifp->if_flags & XFS_IFEXTIREC);
    -	nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ;
    -	erp = ifp->if_u1.if_ext_irec;
    -	ep = &erp->er_extbuf[erp->er_extcount];
    -	erp_next = erp + 1;
    -	ep_next = erp_next->er_extbuf;
    -	while (erp_idx < nlists - 1) {
    -		ext_avail = XFS_LINEAR_EXTS - erp->er_extcount;
    -		ext_diff = MIN(ext_avail, erp_next->er_extcount);
    -		memcpy(ep, ep_next, ext_diff * sizeof(xfs_bmbt_rec_t));
    -		erp->er_extcount += ext_diff;
    -		erp_next->er_extcount -= ext_diff;
    -		/* Remove next page */
    -		if (erp_next->er_extcount == 0) {
    -			/*
    -			 * Free page before removing extent record
    -			 * so er_extoffs don't get modified in
    -			 * xfs_iext_irec_remove.
    -			 */
    -			kmem_free(erp_next->er_extbuf,
    -				erp_next->er_extcount * sizeof(xfs_bmbt_rec_t));
    -			erp_next->er_extbuf = NULL;
    -			xfs_iext_irec_remove(ifp, erp_idx + 1);
    -			erp = &ifp->if_u1.if_ext_irec[erp_idx];
    -			nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ;
    -		/* Update next page */
    -		} else {
    -			/* Move rest of page up to become next new page */
    -			memmove(erp_next->er_extbuf, ep_next,
    -				erp_next->er_extcount * sizeof(xfs_bmbt_rec_t));
    -			ep_next = erp_next->er_extbuf;
    -			memset(&ep_next[erp_next->er_extcount], 0,
    -				(XFS_LINEAR_EXTS - erp_next->er_extcount) *
    -				sizeof(xfs_bmbt_rec_t));
    -		}
    -		if (erp->er_extcount == XFS_LINEAR_EXTS) {
    -			erp_idx++;
    -			if (erp_idx < nlists)
    -				erp = &ifp->if_u1.if_ext_irec[erp_idx];
    -			else
    -				break;
    -		}
    -		ep = &erp->er_extbuf[erp->er_extcount];
    -		erp_next = erp + 1;
    -		ep_next = erp_next->er_extbuf;
    -	}
    -}
    -
    -/*
    - * This is called to update the er_extoff field in the indirection
    - * array when extents have been added or removed from one of the
    - * extent lists. erp_idx contains the irec index to begin updating
    - * at and ext_diff contains the number of extents that were added
    - * or removed.
    - */
    -void
    -xfs_iext_irec_update_extoffs(
    -	xfs_ifork_t	*ifp,		/* inode fork pointer */
    -	int		erp_idx,	/* irec index to update */
    -	int		ext_diff)	/* number of new extents */
    -{
    -	int		i;		/* loop counter */
    -	int		nlists;		/* number of irec's (ex lists */
    -
    -	ASSERT(ifp->if_flags & XFS_IFEXTIREC);
    -	nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ;
    -	for (i = erp_idx; i < nlists; i++) {
    -		ifp->if_u1.if_ext_irec[i].er_extoff += ext_diff;
    -	}
    -}
    diff --git a/sys/gnu/fs/xfs/xfs_inode.h b/sys/gnu/fs/xfs/xfs_inode.h
    deleted file mode 100644
    index 3b773813141..00000000000
    --- a/sys/gnu/fs/xfs/xfs_inode.h
    +++ /dev/null
    @@ -1,516 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef	__XFS_INODE_H__
    -#define	__XFS_INODE_H__
    -
    -/*
    - * Fork identifiers.
    - */
    -#define	XFS_DATA_FORK	0
    -#define	XFS_ATTR_FORK	1
    -
    -/*
    - * The following xfs_ext_irec_t struct introduces a second (top) level
    - * to the in-core extent allocation scheme. These structs are allocated
    - * in a contiguous block, creating an indirection array where each entry
    - * (irec) contains a pointer to a buffer of in-core extent records which
    - * it manages. Each extent buffer is 4k in size, since 4k is the system
    - * page size on Linux i386 and systems with larger page sizes don't seem
    - * to gain much, if anything, by using their native page size as the
    - * extent buffer size. Also, using 4k extent buffers everywhere provides
    - * a consistent interface for CXFS across different platforms.
    - *
    - * There is currently no limit on the number of irec's (extent lists)
    - * allowed, so heavily fragmented files may require an indirection array
    - * which spans multiple system pages of memory. The number of extents
    - * which would require this amount of contiguous memory is very large
    - * and should not cause problems in the foreseeable future. However,
    - * if the memory needed for the contiguous array ever becomes a problem,
    - * it is possible that a third level of indirection may be required.
    - */
    -typedef struct xfs_ext_irec {
    -	xfs_bmbt_rec_t	*er_extbuf;	/* block of extent records */
    -	xfs_extnum_t	er_extoff;	/* extent offset in file */
    -	xfs_extnum_t	er_extcount;	/* number of extents in page/block */
    -} xfs_ext_irec_t;
    -
    -/*
    - * File incore extent information, present for each of data & attr forks.
    - */
    -#define	XFS_IEXT_BUFSZ		4096
    -#define	XFS_LINEAR_EXTS		(XFS_IEXT_BUFSZ / (uint)sizeof(xfs_bmbt_rec_t))
    -#define	XFS_INLINE_EXTS		2
    -#define	XFS_INLINE_DATA		32
    -typedef struct xfs_ifork {
    -	int			if_bytes;	/* bytes in if_u1 */
    -	int			if_real_bytes;	/* bytes allocated in if_u1 */
    -	xfs_bmbt_block_t	*if_broot;	/* file's incore btree root */
    -	short			if_broot_bytes;	/* bytes allocated for root */
    -	unsigned char		if_flags;	/* per-fork flags */
    -	unsigned char		if_ext_max;	/* max # of extent records */
    -	xfs_extnum_t		if_lastex;	/* last if_extents used */
    -	union {
    -		xfs_bmbt_rec_t	*if_extents;	/* linear map file exts */
    -		xfs_ext_irec_t	*if_ext_irec;	/* irec map file exts */
    -		char		*if_data;	/* inline file data */
    -	} if_u1;
    -	union {
    -		xfs_bmbt_rec_t	if_inline_ext[XFS_INLINE_EXTS];
    -						/* very small file extents */
    -		char		if_inline_data[XFS_INLINE_DATA];
    -						/* very small file data */
    -		xfs_dev_t	if_rdev;	/* dev number if special */
    -		uuid_t		if_uuid;	/* mount point value */
    -	} if_u2;
    -} xfs_ifork_t;
    -
    -/*
    - * Flags for xfs_ichgtime().
    - */
    -#define	XFS_ICHGTIME_MOD	0x1	/* data fork modification timestamp */
    -#define	XFS_ICHGTIME_ACC	0x2	/* data fork access timestamp */
    -#define	XFS_ICHGTIME_CHG	0x4	/* inode field change timestamp */
    -
    -/*
    - * Per-fork incore inode flags.
    - */
    -#define	XFS_IFINLINE	0x01	/* Inline data is read in */
    -#define	XFS_IFEXTENTS	0x02	/* All extent pointers are read in */
    -#define	XFS_IFBROOT	0x04	/* i_broot points to the bmap b-tree root */
    -#define	XFS_IFEXTIREC	0x08	/* Indirection array of extent blocks */
    -
    -/*
    - * Flags for xfs_itobp(), xfs_imap() and xfs_dilocate().
    - */
    -#define XFS_IMAP_LOOKUP		0x1
    -#define XFS_IMAP_BULKSTAT	0x2
    -
    -#ifdef __KERNEL__
    -struct bhv_desc;
    -struct cred;
    -struct ktrace;
    -struct xfs_vnode;
    -struct xfs_buf;
    -struct xfs_bmap_free;
    -struct xfs_bmbt_irec;
    -struct xfs_bmbt_block;
    -struct xfs_inode;
    -struct xfs_inode_log_item;
    -struct xfs_mount;
    -struct xfs_trans;
    -struct xfs_dquot;
    -
    -#if defined(XFS_ILOCK_TRACE)
    -#define XFS_ILOCK_KTRACE_SIZE	32
    -extern ktrace_t *xfs_ilock_trace_buf;
    -extern void xfs_ilock_trace(struct xfs_inode *, int, unsigned int, inst_t *);
    -#else
    -#define	xfs_ilock_trace(i,n,f,ra)
    -#endif
    -
    -typedef struct dm_attrs_s {
    -	__uint32_t	da_dmevmask;	/* DMIG event mask */
    -	__uint16_t	da_dmstate;	/* DMIG state info */
    -	__uint16_t	da_pad;		/* DMIG extra padding */
    -} dm_attrs_t;
    -
    -typedef struct xfs_iocore {
    -	void			*io_obj;	/* pointer to container
    -						 * inode or dcxvn structure */
    -	struct xfs_mount	*io_mount;	/* fs mount struct ptr */
    -#ifdef DEBUG
    -	mrlock_t		*io_lock;	/* inode IO lock */
    -	mrlock_t		*io_iolock;	/* inode IO lock */
    -#endif
    -
    -	/* I/O state */
    -	xfs_fsize_t		io_new_size;	/* sz when write completes */
    -
    -	/* Miscellaneous state. */
    -	unsigned int		io_flags;	/* IO related flags */
    -
    -	/* DMAPI state */
    -	dm_attrs_t		io_dmattrs;
    -
    -} xfs_iocore_t;
    -
    -#define        io_dmevmask     io_dmattrs.da_dmevmask
    -#define        io_dmstate      io_dmattrs.da_dmstate
    -
    -#define XFS_IO_INODE(io)	((xfs_inode_t *) ((io)->io_obj))
    -#define XFS_IO_DCXVN(io)	((dcxvn_t *) ((io)->io_obj))
    -
    -/*
    - * Flags in the flags field
    - */
    -
    -#define XFS_IOCORE_RT		0x1
    -
    -/*
    - * xfs_iocore prototypes
    - */
    -
    -extern void xfs_iocore_inode_init(struct xfs_inode *);
    -extern void xfs_iocore_inode_reinit(struct xfs_inode *);
    -
    -
    -/*
    - * This is the type used in the xfs inode hash table.
    - * An array of these is allocated for each mounted
    - * file system to hash the inodes for that file system.
    - */
    -typedef struct xfs_ihash {
    -	struct xfs_inode	*ih_next;
    -	rwlock_t		ih_lock;
    -	uint			ih_version;
    -} xfs_ihash_t;
    -
    -#define XFS_IHASH(mp,ino) ((mp)->m_ihash + (((uint)(ino)) % (mp)->m_ihsize))
    -
    -/*
    - * This is the xfs inode cluster hash.  This hash is used by xfs_iflush to
    - * find inodes that share a cluster and can be flushed to disk at the same
    - * time.
    - */
    -typedef struct xfs_chashlist {
    -	struct xfs_chashlist	*chl_next;
    -	struct xfs_chashlist	*chl_prev;
    -	struct xfs_inode	*chl_ip;
    -	xfs_daddr_t		chl_blkno;	/* starting block number of
    -						 * the cluster */
    -	struct xfs_buf		*chl_buf;	/* the inode buffer */
    -} xfs_chashlist_t;
    -
    -typedef struct xfs_chash {
    -	xfs_chashlist_t		*ch_list;
    -	lock_t			ch_lock;
    -} xfs_chash_t;
    -
    -#define XFS_CHASH(mp,blk) ((mp)->m_chash + (((uint)blk) % (mp)->m_chsize))
    -
    -
    -/*
    - * This is the xfs in-core inode structure.
    - * Most of the on-disk inode is embedded in the i_d field.
    - *
    - * The extent pointers/inline file space, however, are managed
    - * separately.  The memory for this information is pointed to by
    - * the if_u1 unions depending on the type of the data.
    - * This is used to linearize the array of extents for fast in-core
    - * access.  This is used until the file's number of extents
    - * surpasses XFS_MAX_INCORE_EXTENTS, at which point all extent pointers
    - * are accessed through the buffer cache.
    - *
    - * Other state kept in the in-core inode is used for identification,
    - * locking, transactional updating, etc of the inode.
    - *
    - * Generally, we do not want to hold the i_rlock while holding the
    - * i_ilock. Hierarchy is i_iolock followed by i_rlock.
    - *
    - * xfs_iptr_t contains all the inode fields upto and including the
    - * i_mnext and i_mprev fields, it is used as a marker in the inode
    - * chain off the mount structure by xfs_sync calls.
    - */
    -
    -typedef struct {
    -	struct xfs_ihash	*ip_hash;	/* pointer to hash header */
    -	struct xfs_inode	*ip_next;	/* inode hash link forw */
    -	struct xfs_inode	*ip_mnext;	/* next inode in mount list */
    -	struct xfs_inode	*ip_mprev;	/* ptr to prev inode */
    -	struct xfs_inode	**ip_prevp;	/* ptr to prev i_next */
    -	struct xfs_mount	*ip_mount;	/* fs mount struct ptr */
    -} xfs_iptr_t;
    -
    -typedef struct xfs_inode {
    -	/* Inode linking and identification information. */
    -	struct xfs_ihash	*i_hash;	/* pointer to hash header */
    -	struct xfs_inode	*i_next;	/* inode hash link forw */
    -	struct xfs_inode	*i_mnext;	/* next inode in mount list */
    -	struct xfs_inode	*i_mprev;	/* ptr to prev inode */
    -	struct xfs_inode	**i_prevp;	/* ptr to prev i_next */
    -	struct xfs_mount	*i_mount;	/* fs mount struct ptr */
    -	TAILQ_ENTRY(xfs_inode)	i_reclaim;	/* reclaim list */
    -	struct bhv_desc		i_bhv_desc;	/* inode behavior descriptor*/
    -	struct xfs_dquot	*i_udquot;	/* user dquot */
    -	struct xfs_dquot	*i_gdquot;	/* group dquot */
    -
    -	/* Inode location stuff */
    -	xfs_ino_t		i_ino;		/* inode number (agno/agino)*/
    -	xfs_daddr_t		i_blkno;	/* blkno of inode buffer */
    -	ushort			i_len;		/* len of inode buffer */
    -	ushort			i_boffset;	/* off of inode in buffer */
    -
    -	/* Extent information. */
    -	xfs_ifork_t		*i_afp;		/* attribute fork pointer */
    -	xfs_ifork_t		i_df;		/* data fork */
    -
    -	/* Transaction and locking information. */
    -	struct xfs_trans	*i_transp;	/* ptr to owning transaction*/
    -	struct xfs_inode_log_item *i_itemp;	/* logging information */
    -	mrlock_t		i_lock;		/* inode lock */
    -	mrlock_t		i_iolock;	/* inode IO lock */
    -	sema_t			i_flock;	/* inode flush lock */
    -	atomic_t		i_pincount;	/* inode pin count */
    -	wait_queue_head_t	i_ipin_wait;	/* inode pinning wait queue */
    -#ifdef HAVE_REFCACHE
    -	struct xfs_inode	**i_refcache;	/* ptr to entry in ref cache */
    -	struct xfs_inode	*i_release;	/* inode to unref */
    -#endif
    -	/* I/O state */
    -	xfs_iocore_t		i_iocore;	/* I/O core */
    -
    -	/* Miscellaneous state. */
    -	unsigned short		i_flags;	/* see defined flags below */
    -	unsigned char		i_update_core;	/* timestamps/size is dirty */
    -	unsigned char		i_update_size;	/* di_size field is dirty */
    -	unsigned int		i_gen;		/* generation count */
    -	unsigned int		i_delayed_blks;	/* count of delay alloc blks */
    -
    -	xfs_dinode_core_t	i_d;		/* most of ondisk inode */
    -	xfs_chashlist_t		*i_chash;	/* cluster hash list header */
    -	struct xfs_inode	*i_cnext;	/* cluster hash link forward */
    -	struct xfs_inode	*i_cprev;	/* cluster hash link backward */
    -
    -	/* Trace buffers per inode. */
    -#ifdef XFS_BMAP_TRACE
    -	struct ktrace		*i_xtrace;	/* inode extent list trace */
    -#endif
    -#ifdef XFS_BMBT_TRACE
    -	struct ktrace		*i_btrace;	/* inode bmap btree trace */
    -#endif
    -#ifdef XFS_RW_TRACE
    -	struct ktrace		*i_rwtrace;	/* inode read/write trace */
    -#endif
    -#ifdef XFS_ILOCK_TRACE
    -	struct ktrace		*i_lock_trace;	/* inode lock/unlock trace */
    -#endif
    -#ifdef XFS_DIR2_TRACE
    -	struct ktrace		*i_dir_trace;	/* inode directory trace */
    -#endif
    -} xfs_inode_t;
    -
    -#endif	/* __KERNEL__ */
    -
    -
    -/*
    - * Fork handling.
    - */
    -#define	XFS_IFORK_PTR(ip,w)		\
    -	((w) == XFS_DATA_FORK ? &(ip)->i_df : (ip)->i_afp)
    -#define	XFS_IFORK_Q(ip)			XFS_CFORK_Q(&(ip)->i_d)
    -#define	XFS_IFORK_DSIZE(ip)		XFS_CFORK_DSIZE(&ip->i_d, ip->i_mount)
    -#define	XFS_IFORK_ASIZE(ip)		XFS_CFORK_ASIZE(&ip->i_d, ip->i_mount)
    -#define	XFS_IFORK_SIZE(ip,w)		XFS_CFORK_SIZE(&ip->i_d, ip->i_mount, w)
    -#define	XFS_IFORK_FORMAT(ip,w)		XFS_CFORK_FORMAT(&ip->i_d, w)
    -#define	XFS_IFORK_FMT_SET(ip,w,n)	XFS_CFORK_FMT_SET(&ip->i_d, w, n)
    -#define	XFS_IFORK_NEXTENTS(ip,w)	XFS_CFORK_NEXTENTS(&ip->i_d, w)
    -#define	XFS_IFORK_NEXT_SET(ip,w,n)	XFS_CFORK_NEXT_SET(&ip->i_d, w, n)
    -
    -
    -#ifdef __KERNEL__
    -
    -/*
    - * In-core inode flags.
    - */
    -#define XFS_IGRIO	0x0001  /* inode used for guaranteed rate i/o */
    -#define XFS_IUIOSZ	0x0002  /* inode i/o sizes have been explicitly set */
    -#define XFS_IQUIESCE    0x0004  /* we have started quiescing for this inode */
    -#define XFS_IRECLAIM    0x0008  /* we have started reclaiming this inode    */
    -#define XFS_ISTALE	0x0010	/* inode has been staled */
    -#define XFS_IRECLAIMABLE 0x0020 /* inode can be reclaimed */
    -#define XFS_INEW	0x0040
    -
    -/*
    - * Flags for inode locking.
    - */
    -#define	XFS_IOLOCK_EXCL		0x001
    -#define	XFS_IOLOCK_SHARED	0x002
    -#define	XFS_ILOCK_EXCL		0x004
    -#define	XFS_ILOCK_SHARED	0x008
    -#define	XFS_IUNLOCK_NONOTIFY	0x010
    -/*	XFS_IOLOCK_NESTED	0x020 */
    -#define XFS_EXTENT_TOKEN_RD	0x040
    -#define XFS_SIZE_TOKEN_RD	0x080
    -#define XFS_EXTSIZE_RD		(XFS_EXTENT_TOKEN_RD|XFS_SIZE_TOKEN_RD)
    -#define XFS_WILLLEND		0x100	/* Always acquire tokens for lending */
    -#define XFS_EXTENT_TOKEN_WR	(XFS_EXTENT_TOKEN_RD | XFS_WILLLEND)
    -#define XFS_SIZE_TOKEN_WR       (XFS_SIZE_TOKEN_RD | XFS_WILLLEND)
    -#define XFS_EXTSIZE_WR		(XFS_EXTSIZE_RD | XFS_WILLLEND)
    -/*	XFS_SIZE_TOKEN_WANT	0x200 */
    -
    -#define XFS_LOCK_MASK	\
    -	(XFS_IOLOCK_EXCL | XFS_IOLOCK_SHARED | XFS_ILOCK_EXCL | \
    -	 XFS_ILOCK_SHARED | XFS_EXTENT_TOKEN_RD | XFS_SIZE_TOKEN_RD | \
    -	 XFS_WILLLEND)
    -
    -/*
    - * Flags for xfs_iflush()
    - */
    -#define	XFS_IFLUSH_DELWRI_ELSE_SYNC	1
    -#define	XFS_IFLUSH_DELWRI_ELSE_ASYNC	2
    -#define	XFS_IFLUSH_SYNC			3
    -#define	XFS_IFLUSH_ASYNC		4
    -#define	XFS_IFLUSH_DELWRI		5
    -
    -/*
    - * Flags for xfs_itruncate_start().
    - */
    -#define	XFS_ITRUNC_DEFINITE	0x1
    -#define	XFS_ITRUNC_MAYBE	0x2
    -
    -#define	XFS_ITOV(ip)		BHV_TO_VNODE(XFS_ITOBHV(ip))
    -#define	XFS_ITOV_NULL(ip)	BHV_TO_VNODE_NULL(XFS_ITOBHV(ip))
    -#define	XFS_ITOBHV(ip)		((struct bhv_desc *)(&((ip)->i_bhv_desc)))
    -#define	XFS_BHVTOI(bhvp)	((xfs_inode_t *)((char *)(bhvp) - \
    -				(char *)&(((xfs_inode_t *)0)->i_bhv_desc)))
    -#define BHV_IS_XFS(bdp)		(BHV_OPS(bdp) == &xfs_vnodeops)
    -
    -/*
    - * For multiple groups support: if S_ISGID bit is set in the parent
    - * directory, group of new file is set to that of the parent, and
    - * new subdirectory gets S_ISGID bit from parent.
    - */
    -#define XFS_INHERIT_GID(pip, vfsp)	\
    -	(((vfsp)->vfs_flag & VFS_GRPID) || ((pip)->i_d.di_mode & S_ISGID))
    -
    -/*
    - * xfs_iget.c prototypes.
    - */
    -
    -#define IGET_CREATE	1
    -
    -void		xfs_ihash_init(struct xfs_mount *);
    -void		xfs_ihash_free(struct xfs_mount *);
    -void		xfs_chash_init(struct xfs_mount *);
    -void		xfs_chash_free(struct xfs_mount *);
    -xfs_inode_t	*xfs_inode_incore(struct xfs_mount *, xfs_ino_t,
    -				  struct xfs_trans *);
    -void            xfs_inode_lock_init(xfs_inode_t *, struct xfs_vnode *);
    -int		xfs_iget(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
    -			 uint, uint, xfs_inode_t **, xfs_daddr_t);
    -void		xfs_iput(xfs_inode_t *, uint);
    -void		xfs_iput_new(xfs_inode_t *, uint);
    -void		xfs_ilock(xfs_inode_t *, uint);
    -int		xfs_ilock_nowait(xfs_inode_t *, uint);
    -void		xfs_iunlock(xfs_inode_t *, uint);
    -void		xfs_ilock_demote(xfs_inode_t *, uint);
    -void		xfs_iflock(xfs_inode_t *);
    -int		xfs_iflock_nowait(xfs_inode_t *);
    -uint		xfs_ilock_map_shared(xfs_inode_t *);
    -void		xfs_iunlock_map_shared(xfs_inode_t *, uint);
    -void		xfs_ifunlock(xfs_inode_t *);
    -void		xfs_ireclaim(xfs_inode_t *);
    -int		xfs_finish_reclaim(xfs_inode_t *, int, int);
    -int		xfs_finish_reclaim_all(struct xfs_mount *, int);
    -
    -/*
    - * xfs_inode.c prototypes.
    - */
    -int		xfs_itobp(struct xfs_mount *, struct xfs_trans *,
    -			  xfs_inode_t *, xfs_dinode_t **, struct xfs_buf **,
    -			  xfs_daddr_t, uint);
    -int		xfs_iread(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
    -			  xfs_inode_t **, xfs_daddr_t);
    -int		xfs_iread_extents(struct xfs_trans *, xfs_inode_t *, int);
    -int		xfs_ialloc(struct xfs_trans *, xfs_inode_t *, mode_t,
    -			   xfs_nlink_t, xfs_dev_t, struct cred *, xfs_prid_t,
    -			   int, struct xfs_buf **, boolean_t *, xfs_inode_t **);
    -void		xfs_xlate_dinode_core(xfs_caddr_t, struct xfs_dinode_core *,
    -					int);
    -uint		xfs_ip2xflags(struct xfs_inode *);
    -uint		xfs_dic2xflags(struct xfs_dinode_core *);
    -int		xfs_ifree(struct xfs_trans *, xfs_inode_t *,
    -			   struct xfs_bmap_free *);
    -void		xfs_itruncate_start(xfs_inode_t *, uint, xfs_fsize_t);
    -int		xfs_itruncate_finish(struct xfs_trans **, xfs_inode_t *,
    -				     xfs_fsize_t, int, int);
    -int		xfs_iunlink(struct xfs_trans *, xfs_inode_t *);
    -int		xfs_igrow_start(xfs_inode_t *, xfs_fsize_t, struct cred *);
    -void		xfs_igrow_finish(struct xfs_trans *, xfs_inode_t *,
    -				 xfs_fsize_t, int);
    -
    -void		xfs_idestroy_fork(xfs_inode_t *, int);
    -void		xfs_idestroy(xfs_inode_t *);
    -void		xfs_idata_realloc(xfs_inode_t *, int, int);
    -void		xfs_iextract(xfs_inode_t *);
    -void		xfs_iext_realloc(xfs_inode_t *, int, int);
    -void		xfs_iroot_realloc(xfs_inode_t *, int, int);
    -void		xfs_ipin(xfs_inode_t *);
    -void		xfs_iunpin(xfs_inode_t *);
    -int		xfs_iextents_copy(xfs_inode_t *, xfs_bmbt_rec_t *, int);
    -int		xfs_iflush(xfs_inode_t *, uint);
    -void		xfs_iflush_all(struct xfs_mount *);
    -int		xfs_iaccess(xfs_inode_t *, accmode_t, cred_t *);
    -uint		xfs_iroundup(uint);
    -void		xfs_ichgtime(xfs_inode_t *, int);
    -xfs_fsize_t	xfs_file_last_byte(xfs_inode_t *);
    -void		xfs_lock_inodes(xfs_inode_t **, int, int, uint);
    -
    -xfs_inode_t	*xfs_vtoi(struct xfs_vnode *vp);
    -
    -void		xfs_synchronize_atime(xfs_inode_t *);
    -
    -xfs_bmbt_rec_t	*xfs_iext_get_ext(xfs_ifork_t *, xfs_extnum_t);
    -void		xfs_iext_insert(xfs_ifork_t *, xfs_extnum_t, xfs_extnum_t,
    -				xfs_bmbt_irec_t *);
    -void		xfs_iext_add(xfs_ifork_t *, xfs_extnum_t, int);
    -void		xfs_iext_add_indirect_multi(xfs_ifork_t *, int, xfs_extnum_t, int);
    -void		xfs_iext_remove(xfs_ifork_t *, xfs_extnum_t, int);
    -void		xfs_iext_remove_inline(xfs_ifork_t *, xfs_extnum_t, int);
    -void		xfs_iext_remove_direct(xfs_ifork_t *, xfs_extnum_t, int);
    -void		xfs_iext_remove_indirect(xfs_ifork_t *, xfs_extnum_t, int);
    -void		xfs_iext_realloc_direct(xfs_ifork_t *, int);
    -void		xfs_iext_realloc_indirect(xfs_ifork_t *, int);
    -void		xfs_iext_indirect_to_direct(xfs_ifork_t *);
    -void		xfs_iext_direct_to_inline(xfs_ifork_t *, xfs_extnum_t);
    -void		xfs_iext_inline_to_direct(xfs_ifork_t *, int);
    -void		xfs_iext_destroy(xfs_ifork_t *);
    -xfs_bmbt_rec_t	*xfs_iext_bno_to_ext(xfs_ifork_t *, xfs_fileoff_t, int *);
    -xfs_ext_irec_t	*xfs_iext_bno_to_irec(xfs_ifork_t *, xfs_fileoff_t, int *);
    -xfs_ext_irec_t	*xfs_iext_idx_to_irec(xfs_ifork_t *, xfs_extnum_t *, int *, int);
    -void		xfs_iext_irec_init(xfs_ifork_t *);
    -xfs_ext_irec_t *xfs_iext_irec_new(xfs_ifork_t *, int);
    -void		xfs_iext_irec_remove(xfs_ifork_t *, int);
    -void		xfs_iext_irec_compact(xfs_ifork_t *);
    -void		xfs_iext_irec_compact_pages(xfs_ifork_t *);
    -void		xfs_iext_irec_compact_full(xfs_ifork_t *);
    -void		xfs_iext_irec_update_extoffs(xfs_ifork_t *, int, int);
    -
    -#define xfs_ipincount(ip)	((unsigned int) atomic_read(&ip->i_pincount))
    -
    -#ifdef DEBUG
    -void		xfs_isize_check(struct xfs_mount *, xfs_inode_t *, xfs_fsize_t);
    -#else	/* DEBUG */
    -#define xfs_isize_check(mp, ip, isize)
    -#endif	/* DEBUG */
    -
    -#if defined(DEBUG)
    -void		xfs_inobp_check(struct xfs_mount *, struct xfs_buf *);
    -#else
    -#define	xfs_inobp_check(mp, bp)
    -#endif /* DEBUG */
    -
    -extern struct kmem_zone	*xfs_chashlist_zone;
    -extern struct kmem_zone	*xfs_ifork_zone;
    -extern struct kmem_zone	*xfs_inode_zone;
    -extern struct kmem_zone	*xfs_ili_zone;
    -
    -#endif	/* __KERNEL__ */
    -
    -#endif	/* __XFS_INODE_H__ */
    -
    diff --git a/sys/gnu/fs/xfs/xfs_inode_item.c b/sys/gnu/fs/xfs/xfs_inode_item.c
    deleted file mode 100644
    index 7497a481b2f..00000000000
    --- a/sys/gnu/fs/xfs/xfs_inode_item.c
    +++ /dev/null
    @@ -1,1086 +0,0 @@
    -/*
    - * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_buf_item.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_trans_priv.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_inode_item.h"
    -#include "xfs_btree.h"
    -#include "xfs_ialloc.h"
    -#include "xfs_rw.h"
    -
    -
    -kmem_zone_t	*xfs_ili_zone;		/* inode log item zone */
    -
    -/*
    - * This returns the number of iovecs needed to log the given inode item.
    - *
    - * We need one iovec for the inode log format structure, one for the
    - * inode core, and possibly one for the inode data/extents/b-tree root
    - * and one for the inode attribute data/extents/b-tree root.
    - */
    -STATIC uint
    -xfs_inode_item_size(
    -	xfs_inode_log_item_t	*iip)
    -{
    -	uint		nvecs;
    -	xfs_inode_t	*ip;
    -
    -	ip = iip->ili_inode;
    -	nvecs = 2;
    -
    -	/*
    -	 * Only log the data/extents/b-tree root if there is something
    -	 * left to log.
    -	 */
    -	iip->ili_format.ilf_fields |= XFS_ILOG_CORE;
    -
    -	switch (ip->i_d.di_format) {
    -	case XFS_DINODE_FMT_EXTENTS:
    -		iip->ili_format.ilf_fields &=
    -			~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT |
    -			  XFS_ILOG_DEV | XFS_ILOG_UUID);
    -		if ((iip->ili_format.ilf_fields & XFS_ILOG_DEXT) &&
    -		    (ip->i_d.di_nextents > 0) &&
    -		    (ip->i_df.if_bytes > 0)) {
    -			ASSERT(ip->i_df.if_u1.if_extents != NULL);
    -			nvecs++;
    -		} else {
    -			iip->ili_format.ilf_fields &= ~XFS_ILOG_DEXT;
    -		}
    -		break;
    -
    -	case XFS_DINODE_FMT_BTREE:
    -		ASSERT(ip->i_df.if_ext_max ==
    -		       XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t));
    -		iip->ili_format.ilf_fields &=
    -			~(XFS_ILOG_DDATA | XFS_ILOG_DEXT |
    -			  XFS_ILOG_DEV | XFS_ILOG_UUID);
    -		if ((iip->ili_format.ilf_fields & XFS_ILOG_DBROOT) &&
    -		    (ip->i_df.if_broot_bytes > 0)) {
    -			ASSERT(ip->i_df.if_broot != NULL);
    -			nvecs++;
    -		} else {
    -			ASSERT(!(iip->ili_format.ilf_fields &
    -				 XFS_ILOG_DBROOT));
    -#ifdef XFS_TRANS_DEBUG
    -			if (iip->ili_root_size > 0) {
    -				ASSERT(iip->ili_root_size ==
    -				       ip->i_df.if_broot_bytes);
    -				ASSERT(memcmp(iip->ili_orig_root,
    -					    ip->i_df.if_broot,
    -					    iip->ili_root_size) == 0);
    -			} else {
    -				ASSERT(ip->i_df.if_broot_bytes == 0);
    -			}
    -#endif
    -			iip->ili_format.ilf_fields &= ~XFS_ILOG_DBROOT;
    -		}
    -		break;
    -
    -	case XFS_DINODE_FMT_LOCAL:
    -		iip->ili_format.ilf_fields &=
    -			~(XFS_ILOG_DEXT | XFS_ILOG_DBROOT |
    -			  XFS_ILOG_DEV | XFS_ILOG_UUID);
    -		if ((iip->ili_format.ilf_fields & XFS_ILOG_DDATA) &&
    -		    (ip->i_df.if_bytes > 0)) {
    -			ASSERT(ip->i_df.if_u1.if_data != NULL);
    -			ASSERT(ip->i_d.di_size > 0);
    -			nvecs++;
    -		} else {
    -			iip->ili_format.ilf_fields &= ~XFS_ILOG_DDATA;
    -		}
    -		break;
    -
    -	case XFS_DINODE_FMT_DEV:
    -		iip->ili_format.ilf_fields &=
    -			~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT |
    -			  XFS_ILOG_DEXT | XFS_ILOG_UUID);
    -		break;
    -
    -	case XFS_DINODE_FMT_UUID:
    -		iip->ili_format.ilf_fields &=
    -			~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT |
    -			  XFS_ILOG_DEXT | XFS_ILOG_DEV);
    -		break;
    -
    -	default:
    -		ASSERT(0);
    -		break;
    -	}
    -
    -	/*
    -	 * If there are no attributes associated with this file,
    -	 * then there cannot be anything more to log.
    -	 * Clear all attribute-related log flags.
    -	 */
    -	if (!XFS_IFORK_Q(ip)) {
    -		iip->ili_format.ilf_fields &=
    -			~(XFS_ILOG_ADATA | XFS_ILOG_ABROOT | XFS_ILOG_AEXT);
    -		return nvecs;
    -	}
    -
    -	/*
    -	 * Log any necessary attribute data.
    -	 */
    -	switch (ip->i_d.di_aformat) {
    -	case XFS_DINODE_FMT_EXTENTS:
    -		iip->ili_format.ilf_fields &=
    -			~(XFS_ILOG_ADATA | XFS_ILOG_ABROOT);
    -		if ((iip->ili_format.ilf_fields & XFS_ILOG_AEXT) &&
    -		    (ip->i_d.di_anextents > 0) &&
    -		    (ip->i_afp->if_bytes > 0)) {
    -			ASSERT(ip->i_afp->if_u1.if_extents != NULL);
    -			nvecs++;
    -		} else {
    -			iip->ili_format.ilf_fields &= ~XFS_ILOG_AEXT;
    -		}
    -		break;
    -
    -	case XFS_DINODE_FMT_BTREE:
    -		iip->ili_format.ilf_fields &=
    -			~(XFS_ILOG_ADATA | XFS_ILOG_AEXT);
    -		if ((iip->ili_format.ilf_fields & XFS_ILOG_ABROOT) &&
    -		    (ip->i_afp->if_broot_bytes > 0)) {
    -			ASSERT(ip->i_afp->if_broot != NULL);
    -			nvecs++;
    -		} else {
    -			iip->ili_format.ilf_fields &= ~XFS_ILOG_ABROOT;
    -		}
    -		break;
    -
    -	case XFS_DINODE_FMT_LOCAL:
    -		iip->ili_format.ilf_fields &=
    -			~(XFS_ILOG_AEXT | XFS_ILOG_ABROOT);
    -		if ((iip->ili_format.ilf_fields & XFS_ILOG_ADATA) &&
    -		    (ip->i_afp->if_bytes > 0)) {
    -			ASSERT(ip->i_afp->if_u1.if_data != NULL);
    -			nvecs++;
    -		} else {
    -			iip->ili_format.ilf_fields &= ~XFS_ILOG_ADATA;
    -		}
    -		break;
    -
    -	default:
    -		ASSERT(0);
    -		break;
    -	}
    -
    -	return nvecs;
    -}
    -
    -/*
    - * This is called to fill in the vector of log iovecs for the
    - * given inode log item.  It fills the first item with an inode
    - * log format structure, the second with the on-disk inode structure,
    - * and a possible third and/or fourth with the inode data/extents/b-tree
    - * root and inode attributes data/extents/b-tree root.
    - */
    -STATIC void
    -xfs_inode_item_format(
    -	xfs_inode_log_item_t	*iip,
    -	xfs_log_iovec_t		*log_vector)
    -{
    -	uint			nvecs;
    -	xfs_log_iovec_t		*vecp;
    -	xfs_inode_t		*ip;
    -	size_t			data_bytes;
    -	xfs_bmbt_rec_t		*ext_buffer;
    -	int			nrecs;
    -	xfs_mount_t		*mp;
    -
    -	ip = iip->ili_inode;
    -	vecp = log_vector;
    -
    -	vecp->i_addr = (xfs_caddr_t)&iip->ili_format;
    -	vecp->i_len  = sizeof(xfs_inode_log_format_t);
    -	XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_IFORMAT);
    -	vecp++;
    -	nvecs	     = 1;
    -
    -	/*
    -	 * Clear i_update_core if the timestamps (or any other
    -	 * non-transactional modification) need flushing/logging
    -	 * and we're about to log them with the rest of the core.
    -	 *
    -	 * This is the same logic as xfs_iflush() but this code can't
    -	 * run at the same time as xfs_iflush because we're in commit
    -	 * processing here and so we have the inode lock held in
    -	 * exclusive mode.  Although it doesn't really matter
    -	 * for the timestamps if both routines were to grab the
    -	 * timestamps or not.  That would be ok.
    -	 *
    -	 * We clear i_update_core before copying out the data.
    -	 * This is for coordination with our timestamp updates
    -	 * that don't hold the inode lock. They will always
    -	 * update the timestamps BEFORE setting i_update_core,
    -	 * so if we clear i_update_core after they set it we
    -	 * are guaranteed to see their updates to the timestamps
    -	 * either here.  Likewise, if they set it after we clear it
    -	 * here, we'll see it either on the next commit of this
    -	 * inode or the next time the inode gets flushed via
    -	 * xfs_iflush().  This depends on strongly ordered memory
    -	 * semantics, but we have that.  We use the SYNCHRONIZE
    -	 * macro to make sure that the compiler does not reorder
    -	 * the i_update_core access below the data copy below.
    -	 */
    -	if (ip->i_update_core)  {
    -		ip->i_update_core = 0;
    -		SYNCHRONIZE();
    -	}
    -
    -	/*
    -	 * We don't have to worry about re-ordering here because
    -	 * the update_size field is protected by the inode lock
    -	 * and we have that held in exclusive mode.
    -	 */
    -	if (ip->i_update_size)
    -		ip->i_update_size = 0;
    -
    -	/*
    -	 * Make sure to get the latest atime from the Linux inode.
    -	 */
    -	xfs_synchronize_atime(ip);
    -
    -	vecp->i_addr = (xfs_caddr_t)&ip->i_d;
    -	vecp->i_len  = sizeof(xfs_dinode_core_t);
    -	XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_ICORE);
    -	vecp++;
    -	nvecs++;
    -	iip->ili_format.ilf_fields |= XFS_ILOG_CORE;
    -
    -	/*
    -	 * If this is really an old format inode, then we need to
    -	 * log it as such.  This means that we have to copy the link
    -	 * count from the new field to the old.  We don't have to worry
    -	 * about the new fields, because nothing trusts them as long as
    -	 * the old inode version number is there.  If the superblock already
    -	 * has a new version number, then we don't bother converting back.
    -	 */
    -	mp = ip->i_mount;
    -	ASSERT(ip->i_d.di_version == XFS_DINODE_VERSION_1 ||
    -	       XFS_SB_VERSION_HASNLINK(&mp->m_sb));
    -	if (ip->i_d.di_version == XFS_DINODE_VERSION_1) {
    -		if (!XFS_SB_VERSION_HASNLINK(&mp->m_sb)) {
    -			/*
    -			 * Convert it back.
    -			 */
    -			ASSERT(ip->i_d.di_nlink <= XFS_MAXLINK_1);
    -			ip->i_d.di_onlink = ip->i_d.di_nlink;
    -		} else {
    -			/*
    -			 * The superblock version has already been bumped,
    -			 * so just make the conversion to the new inode
    -			 * format permanent.
    -			 */
    -			ip->i_d.di_version = XFS_DINODE_VERSION_2;
    -			ip->i_d.di_onlink = 0;
    -			memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
    -		}
    -	}
    -
    -	switch (ip->i_d.di_format) {
    -	case XFS_DINODE_FMT_EXTENTS:
    -		ASSERT(!(iip->ili_format.ilf_fields &
    -			 (XFS_ILOG_DDATA | XFS_ILOG_DBROOT |
    -			  XFS_ILOG_DEV | XFS_ILOG_UUID)));
    -		if (iip->ili_format.ilf_fields & XFS_ILOG_DEXT) {
    -			ASSERT(ip->i_df.if_bytes > 0);
    -			ASSERT(ip->i_df.if_u1.if_extents != NULL);
    -			ASSERT(ip->i_d.di_nextents > 0);
    -			ASSERT(iip->ili_extents_buf == NULL);
    -			nrecs = ip->i_df.if_bytes /
    -				(uint)sizeof(xfs_bmbt_rec_t);
    -			ASSERT(nrecs > 0);
    -#ifdef XFS_NATIVE_HOST
    -			if (nrecs == ip->i_d.di_nextents) {
    -				/*
    -				 * There are no delayed allocation
    -				 * extents, so just point to the
    -				 * real extents array.
    -				 */
    -				vecp->i_addr =
    -					(char *)(ip->i_df.if_u1.if_extents);
    -				vecp->i_len = ip->i_df.if_bytes;
    -				XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_IEXT);
    -			} else
    -#endif
    -			{
    -				/*
    -				 * There are delayed allocation extents
    -				 * in the inode, or we need to convert
    -				 * the extents to on disk format.
    -				 * Use xfs_iextents_copy()
    -				 * to copy only the real extents into
    -				 * a separate buffer.  We'll free the
    -				 * buffer in the unlock routine.
    -				 */
    -				ext_buffer = kmem_alloc(ip->i_df.if_bytes,
    -					KM_SLEEP);
    -				iip->ili_extents_buf = ext_buffer;
    -				vecp->i_addr = (xfs_caddr_t)ext_buffer;
    -				vecp->i_len = xfs_iextents_copy(ip, ext_buffer,
    -						XFS_DATA_FORK);
    -				XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_IEXT);
    -			}
    -			ASSERT(vecp->i_len <= ip->i_df.if_bytes);
    -			iip->ili_format.ilf_dsize = vecp->i_len;
    -			vecp++;
    -			nvecs++;
    -		}
    -		break;
    -
    -	case XFS_DINODE_FMT_BTREE:
    -		ASSERT(!(iip->ili_format.ilf_fields &
    -			 (XFS_ILOG_DDATA | XFS_ILOG_DEXT |
    -			  XFS_ILOG_DEV | XFS_ILOG_UUID)));
    -		if (iip->ili_format.ilf_fields & XFS_ILOG_DBROOT) {
    -			ASSERT(ip->i_df.if_broot_bytes > 0);
    -			ASSERT(ip->i_df.if_broot != NULL);
    -			vecp->i_addr = (xfs_caddr_t)ip->i_df.if_broot;
    -			vecp->i_len = ip->i_df.if_broot_bytes;
    -			XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_IBROOT);
    -			vecp++;
    -			nvecs++;
    -			iip->ili_format.ilf_dsize = ip->i_df.if_broot_bytes;
    -		}
    -		break;
    -
    -	case XFS_DINODE_FMT_LOCAL:
    -		ASSERT(!(iip->ili_format.ilf_fields &
    -			 (XFS_ILOG_DBROOT | XFS_ILOG_DEXT |
    -			  XFS_ILOG_DEV | XFS_ILOG_UUID)));
    -		if (iip->ili_format.ilf_fields & XFS_ILOG_DDATA) {
    -			ASSERT(ip->i_df.if_bytes > 0);
    -			ASSERT(ip->i_df.if_u1.if_data != NULL);
    -			ASSERT(ip->i_d.di_size > 0);
    -
    -			vecp->i_addr = (xfs_caddr_t)ip->i_df.if_u1.if_data;
    -			/*
    -			 * Round i_bytes up to a word boundary.
    -			 * The underlying memory is guaranteed to
    -			 * to be there by xfs_idata_realloc().
    -			 */
    -			data_bytes = roundup(ip->i_df.if_bytes, 4);
    -			ASSERT((ip->i_df.if_real_bytes == 0) ||
    -			       (ip->i_df.if_real_bytes == data_bytes));
    -			vecp->i_len = (int)data_bytes;
    -			XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_ILOCAL);
    -			vecp++;
    -			nvecs++;
    -			iip->ili_format.ilf_dsize = (unsigned)data_bytes;
    -		}
    -		break;
    -
    -	case XFS_DINODE_FMT_DEV:
    -		ASSERT(!(iip->ili_format.ilf_fields &
    -			 (XFS_ILOG_DBROOT | XFS_ILOG_DEXT |
    -			  XFS_ILOG_DDATA | XFS_ILOG_UUID)));
    -		if (iip->ili_format.ilf_fields & XFS_ILOG_DEV) {
    -			iip->ili_format.ilf_u.ilfu_rdev =
    -				ip->i_df.if_u2.if_rdev;
    -		}
    -		break;
    -
    -	case XFS_DINODE_FMT_UUID:
    -		ASSERT(!(iip->ili_format.ilf_fields &
    -			 (XFS_ILOG_DBROOT | XFS_ILOG_DEXT |
    -			  XFS_ILOG_DDATA | XFS_ILOG_DEV)));
    -		if (iip->ili_format.ilf_fields & XFS_ILOG_UUID) {
    -			iip->ili_format.ilf_u.ilfu_uuid =
    -				ip->i_df.if_u2.if_uuid;
    -		}
    -		break;
    -
    -	default:
    -		ASSERT(0);
    -		break;
    -	}
    -
    -	/*
    -	 * If there are no attributes associated with the file,
    -	 * then we're done.
    -	 * Assert that no attribute-related log flags are set.
    -	 */
    -	if (!XFS_IFORK_Q(ip)) {
    -		ASSERT(nvecs == iip->ili_item.li_desc->lid_size);
    -		iip->ili_format.ilf_size = nvecs;
    -		ASSERT(!(iip->ili_format.ilf_fields &
    -			 (XFS_ILOG_ADATA | XFS_ILOG_ABROOT | XFS_ILOG_AEXT)));
    -		return;
    -	}
    -
    -	switch (ip->i_d.di_aformat) {
    -	case XFS_DINODE_FMT_EXTENTS:
    -		ASSERT(!(iip->ili_format.ilf_fields &
    -			 (XFS_ILOG_ADATA | XFS_ILOG_ABROOT)));
    -		if (iip->ili_format.ilf_fields & XFS_ILOG_AEXT) {
    -			ASSERT(ip->i_afp->if_bytes > 0);
    -			ASSERT(ip->i_afp->if_u1.if_extents != NULL);
    -			ASSERT(ip->i_d.di_anextents > 0);
    -#ifdef DEBUG
    -			nrecs = ip->i_afp->if_bytes /
    -				(uint)sizeof(xfs_bmbt_rec_t);
    -#endif
    -			ASSERT(nrecs > 0);
    -			ASSERT(nrecs == ip->i_d.di_anextents);
    -#ifdef XFS_NATIVE_HOST
    -			/*
    -			 * There are not delayed allocation extents
    -			 * for attributes, so just point at the array.
    -			 */
    -			vecp->i_addr = (char *)(ip->i_afp->if_u1.if_extents);
    -			vecp->i_len = ip->i_afp->if_bytes;
    -#else
    -			ASSERT(iip->ili_aextents_buf == NULL);
    -			/*
    -			 * Need to endian flip before logging
    -			 */
    -			ext_buffer = kmem_alloc(ip->i_afp->if_bytes,
    -				KM_SLEEP);
    -			iip->ili_aextents_buf = ext_buffer;
    -			vecp->i_addr = (xfs_caddr_t)ext_buffer;
    -			vecp->i_len = xfs_iextents_copy(ip, ext_buffer,
    -					XFS_ATTR_FORK);
    -#endif
    -			XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_IATTR_EXT);
    -			iip->ili_format.ilf_asize = vecp->i_len;
    -			vecp++;
    -			nvecs++;
    -		}
    -		break;
    -
    -	case XFS_DINODE_FMT_BTREE:
    -		ASSERT(!(iip->ili_format.ilf_fields &
    -			 (XFS_ILOG_ADATA | XFS_ILOG_AEXT)));
    -		if (iip->ili_format.ilf_fields & XFS_ILOG_ABROOT) {
    -			ASSERT(ip->i_afp->if_broot_bytes > 0);
    -			ASSERT(ip->i_afp->if_broot != NULL);
    -			vecp->i_addr = (xfs_caddr_t)ip->i_afp->if_broot;
    -			vecp->i_len = ip->i_afp->if_broot_bytes;
    -			XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_IATTR_BROOT);
    -			vecp++;
    -			nvecs++;
    -			iip->ili_format.ilf_asize = ip->i_afp->if_broot_bytes;
    -		}
    -		break;
    -
    -	case XFS_DINODE_FMT_LOCAL:
    -		ASSERT(!(iip->ili_format.ilf_fields &
    -			 (XFS_ILOG_ABROOT | XFS_ILOG_AEXT)));
    -		if (iip->ili_format.ilf_fields & XFS_ILOG_ADATA) {
    -			ASSERT(ip->i_afp->if_bytes > 0);
    -			ASSERT(ip->i_afp->if_u1.if_data != NULL);
    -
    -			vecp->i_addr = (xfs_caddr_t)ip->i_afp->if_u1.if_data;
    -			/*
    -			 * Round i_bytes up to a word boundary.
    -			 * The underlying memory is guaranteed to
    -			 * to be there by xfs_idata_realloc().
    -			 */
    -			data_bytes = roundup(ip->i_afp->if_bytes, 4);
    -			ASSERT((ip->i_afp->if_real_bytes == 0) ||
    -			       (ip->i_afp->if_real_bytes == data_bytes));
    -			vecp->i_len = (int)data_bytes;
    -			XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_IATTR_LOCAL);
    -			vecp++;
    -			nvecs++;
    -			iip->ili_format.ilf_asize = (unsigned)data_bytes;
    -		}
    -		break;
    -
    -	default:
    -		ASSERT(0);
    -		break;
    -	}
    -
    -	ASSERT(nvecs == iip->ili_item.li_desc->lid_size);
    -	iip->ili_format.ilf_size = nvecs;
    -}
    -
    -
    -/*
    - * This is called to pin the inode associated with the inode log
    - * item in memory so it cannot be written out.  Do this by calling
    - * xfs_ipin() to bump the pin count in the inode while holding the
    - * inode pin lock.
    - */
    -STATIC void
    -xfs_inode_item_pin(
    -	xfs_inode_log_item_t	*iip)
    -{
    -	ASSERT(ismrlocked(&(iip->ili_inode->i_lock), MR_UPDATE));
    -	xfs_ipin(iip->ili_inode);
    -}
    -
    -
    -/*
    - * This is called to unpin the inode associated with the inode log
    - * item which was previously pinned with a call to xfs_inode_item_pin().
    - * Just call xfs_iunpin() on the inode to do this.
    - */
    -/* ARGSUSED */
    -STATIC void
    -xfs_inode_item_unpin(
    -	xfs_inode_log_item_t	*iip,
    -	int			stale)
    -{
    -	xfs_iunpin(iip->ili_inode);
    -}
    -
    -/* ARGSUSED */
    -STATIC void
    -xfs_inode_item_unpin_remove(
    -	xfs_inode_log_item_t	*iip,
    -	xfs_trans_t		*tp)
    -{
    -	xfs_iunpin(iip->ili_inode);
    -}
    -
    -/*
    - * This is called to attempt to lock the inode associated with this
    - * inode log item, in preparation for the push routine which does the actual
    - * iflush.  Don't sleep on the inode lock or the flush lock.
    - *
    - * If the flush lock is already held, indicating that the inode has
    - * been or is in the process of being flushed, then (ideally) we'd like to
    - * see if the inode's buffer is still incore, and if so give it a nudge.
    - * We delay doing so until the pushbuf routine, though, to avoid holding
    - * the AIL lock across a call to the blackhole which is the buffer cache.
    - * Also we don't want to sleep in any device strategy routines, which can happen
    - * if we do the subsequent bawrite in here.
    - */
    -STATIC uint
    -xfs_inode_item_trylock(
    -	xfs_inode_log_item_t	*iip)
    -{
    -	register xfs_inode_t	*ip;
    -
    -	ip = iip->ili_inode;
    -
    -	if (xfs_ipincount(ip) > 0) {
    -		return XFS_ITEM_PINNED;
    -	}
    -
    -	if (!xfs_ilock_nowait(ip, XFS_ILOCK_SHARED)) {
    -		return XFS_ITEM_LOCKED;
    -	}
    -
    -	if (!xfs_iflock_nowait(ip)) {
    -		/*
    -		 * If someone else isn't already trying to push the inode
    -		 * buffer, we get to do it.
    -		 */
    -		if (iip->ili_pushbuf_flag == 0) {
    -			iip->ili_pushbuf_flag = 1;
    -#ifdef DEBUG
    -			iip->ili_push_owner = current_pid();
    -#endif
    -			/*
    -			 * Inode is left locked in shared mode.
    -			 * Pushbuf routine gets to unlock it.
    -			 */
    -			return XFS_ITEM_PUSHBUF;
    -		} else {
    -			/*
    -			 * We hold the AIL_LOCK, so we must specify the
    -			 * NONOTIFY flag so that we won't double trip.
    -			 */
    -			xfs_iunlock(ip, XFS_ILOCK_SHARED|XFS_IUNLOCK_NONOTIFY);
    -			return XFS_ITEM_FLUSHING;
    -		}
    -		/* NOTREACHED */
    -	}
    -
    -	/* Stale items should force out the iclog */
    -	if (ip->i_flags & XFS_ISTALE) {
    -		xfs_ifunlock(ip);
    -		xfs_iunlock(ip, XFS_ILOCK_SHARED|XFS_IUNLOCK_NONOTIFY);
    -		return XFS_ITEM_PINNED;
    -	}
    -
    -#ifdef DEBUG
    -	if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) {
    -		ASSERT(iip->ili_format.ilf_fields != 0);
    -		ASSERT(iip->ili_logged == 0);
    -		ASSERT(iip->ili_item.li_flags & XFS_LI_IN_AIL);
    -	}
    -#endif
    -	return XFS_ITEM_SUCCESS;
    -}
    -
    -/*
    - * Unlock the inode associated with the inode log item.
    - * Clear the fields of the inode and inode log item that
    - * are specific to the current transaction.  If the
    - * hold flags is set, do not unlock the inode.
    - */
    -STATIC void
    -xfs_inode_item_unlock(
    -	xfs_inode_log_item_t	*iip)
    -{
    -	uint		hold;
    -	uint		iolocked;
    -	uint		lock_flags;
    -	xfs_inode_t	*ip;
    -
    -	ASSERT(iip != NULL);
    -	ASSERT(iip->ili_inode->i_itemp != NULL);
    -	ASSERT(ismrlocked(&(iip->ili_inode->i_lock), MR_UPDATE));
    -	ASSERT((!(iip->ili_inode->i_itemp->ili_flags &
    -		  XFS_ILI_IOLOCKED_EXCL)) ||
    -	       ismrlocked(&(iip->ili_inode->i_iolock), MR_UPDATE));
    -	ASSERT((!(iip->ili_inode->i_itemp->ili_flags &
    -		  XFS_ILI_IOLOCKED_SHARED)) ||
    -	       ismrlocked(&(iip->ili_inode->i_iolock), MR_ACCESS));
    -	/*
    -	 * Clear the transaction pointer in the inode.
    -	 */
    -	ip = iip->ili_inode;
    -	ip->i_transp = NULL;
    -
    -	/*
    -	 * If the inode needed a separate buffer with which to log
    -	 * its extents, then free it now.
    -	 */
    -	if (iip->ili_extents_buf != NULL) {
    -		ASSERT(ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS);
    -		ASSERT(ip->i_d.di_nextents > 0);
    -		ASSERT(iip->ili_format.ilf_fields & XFS_ILOG_DEXT);
    -		ASSERT(ip->i_df.if_bytes > 0);
    -		kmem_free(iip->ili_extents_buf, ip->i_df.if_bytes);
    -		iip->ili_extents_buf = NULL;
    -	}
    -	if (iip->ili_aextents_buf != NULL) {
    -		ASSERT(ip->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS);
    -		ASSERT(ip->i_d.di_anextents > 0);
    -		ASSERT(iip->ili_format.ilf_fields & XFS_ILOG_AEXT);
    -		ASSERT(ip->i_afp->if_bytes > 0);
    -		kmem_free(iip->ili_aextents_buf, ip->i_afp->if_bytes);
    -		iip->ili_aextents_buf = NULL;
    -	}
    -
    -	/*
    -	 * Figure out if we should unlock the inode or not.
    -	 */
    -	hold = iip->ili_flags & XFS_ILI_HOLD;
    -
    -	/*
    -	 * Before clearing out the flags, remember whether we
    -	 * are holding the inode's IO lock.
    -	 */
    -	iolocked = iip->ili_flags & XFS_ILI_IOLOCKED_ANY;
    -
    -	/*
    -	 * Clear out the fields of the inode log item particular
    -	 * to the current transaction.
    -	 */
    -	iip->ili_ilock_recur = 0;
    -	iip->ili_iolock_recur = 0;
    -	iip->ili_flags = 0;
    -
    -	/*
    -	 * Unlock the inode if XFS_ILI_HOLD was not set.
    -	 */
    -	if (!hold) {
    -		lock_flags = XFS_ILOCK_EXCL;
    -		if (iolocked & XFS_ILI_IOLOCKED_EXCL) {
    -			lock_flags |= XFS_IOLOCK_EXCL;
    -		} else if (iolocked & XFS_ILI_IOLOCKED_SHARED) {
    -			lock_flags |= XFS_IOLOCK_SHARED;
    -		}
    -		xfs_iput(iip->ili_inode, lock_flags);
    -	}
    -}
    -
    -/*
    - * This is called to find out where the oldest active copy of the
    - * inode log item in the on disk log resides now that the last log
    - * write of it completed at the given lsn.  Since we always re-log
    - * all dirty data in an inode, the latest copy in the on disk log
    - * is the only one that matters.  Therefore, simply return the
    - * given lsn.
    - */
    -/*ARGSUSED*/
    -STATIC xfs_lsn_t
    -xfs_inode_item_committed(
    -	xfs_inode_log_item_t	*iip,
    -	xfs_lsn_t		lsn)
    -{
    -	return (lsn);
    -}
    -
    -/*
    - * The transaction with the inode locked has aborted.  The inode
    - * must not be dirty within the transaction (unless we're forcibly
    - * shutting down).  We simply unlock just as if the transaction
    - * had been cancelled.
    - */
    -STATIC void
    -xfs_inode_item_abort(
    -	xfs_inode_log_item_t	*iip)
    -{
    -	xfs_inode_item_unlock(iip);
    -	return;
    -}
    -
    -
    -/*
    - * This gets called by xfs_trans_push_ail(), when IOP_TRYLOCK
    - * failed to get the inode flush lock but did get the inode locked SHARED.
    - * Here we're trying to see if the inode buffer is incore, and if so whether it's
    - * marked delayed write. If that's the case, we'll initiate a bawrite on that
    - * buffer to expedite the process.
    - *
    - * We aren't holding the AIL_LOCK (or the flush lock) when this gets called,
    - * so it is inherently race-y.
    - */
    -STATIC void
    -xfs_inode_item_pushbuf(
    -	xfs_inode_log_item_t	*iip)
    -{
    -	xfs_inode_t	*ip;
    -	xfs_mount_t	*mp;
    -	xfs_buf_t	*bp;
    -	uint		dopush;
    -
    -	ip = iip->ili_inode;
    -
    -	ASSERT(ismrlocked(&(ip->i_lock), MR_ACCESS));
    -
    -	/*
    -	 * The ili_pushbuf_flag keeps others from
    -	 * trying to duplicate our effort.
    -	 */
    -	ASSERT(iip->ili_pushbuf_flag != 0);
    -	ASSERT(iip->ili_push_owner == current_pid());
    -
    -	/*
    -	 * If flushlock isn't locked anymore, chances are that the
    -	 * inode flush completed and the inode was taken off the AIL.
    -	 * So, just get out.
    -	 */
    -	if ((valusema(&(ip->i_flock)) > 0)  ||
    -	    ((iip->ili_item.li_flags & XFS_LI_IN_AIL) == 0)) {
    -		iip->ili_pushbuf_flag = 0;
    -		xfs_iunlock(ip, XFS_ILOCK_SHARED);
    -		return;
    -	}
    -
    -	mp = ip->i_mount;
    -	bp = xfs_incore(mp->m_ddev_targp, iip->ili_format.ilf_blkno,
    -		    iip->ili_format.ilf_len, XFS_INCORE_TRYLOCK);
    -
    -	if (bp != NULL) {
    -		if (XFS_BUF_ISDELAYWRITE(bp)) {
    -			/*
    -			 * We were racing with iflush because we don't hold
    -			 * the AIL_LOCK or the flush lock. However, at this point,
    -			 * we have the buffer, and we know that it's dirty.
    -			 * So, it's possible that iflush raced with us, and
    -			 * this item is already taken off the AIL.
    -			 * If not, we can flush it async.
    -			 */
    -			dopush = ((iip->ili_item.li_flags & XFS_LI_IN_AIL) &&
    -				  (valusema(&(ip->i_flock)) <= 0));
    -			iip->ili_pushbuf_flag = 0;
    -			xfs_iunlock(ip, XFS_ILOCK_SHARED);
    -			xfs_buftrace("INODE ITEM PUSH", bp);
    -			if (XFS_BUF_ISPINNED(bp)) {
    -				xfs_log_force(mp, (xfs_lsn_t)0,
    -					      XFS_LOG_FORCE);
    -			}
    -			if (dopush) {
    -				xfs_bawrite(mp, bp);
    -			} else {
    -				xfs_buf_relse(bp);
    -			}
    -		} else {
    -			iip->ili_pushbuf_flag = 0;
    -			xfs_iunlock(ip, XFS_ILOCK_SHARED);
    -			xfs_buf_relse(bp);
    -		}
    -		return;
    -	}
    -	/*
    -	 * We have to be careful about resetting pushbuf flag too early (above).
    -	 * Even though in theory we can do it as soon as we have the buflock,
    -	 * we don't want others to be doing work needlessly. They'll come to
    -	 * this function thinking that pushing the buffer is their
    -	 * responsibility only to find that the buffer is still locked by
    -	 * another doing the same thing
    -	 */
    -	iip->ili_pushbuf_flag = 0;
    -	xfs_iunlock(ip, XFS_ILOCK_SHARED);
    -	return;
    -}
    -
    -
    -/*
    - * This is called to asynchronously write the inode associated with this
    - * inode log item out to disk. The inode will already have been locked by
    - * a successful call to xfs_inode_item_trylock().
    - */
    -STATIC void
    -xfs_inode_item_push(
    -	xfs_inode_log_item_t	*iip)
    -{
    -	xfs_inode_t	*ip;
    -
    -	ip = iip->ili_inode;
    -
    -	ASSERT(ismrlocked(&(ip->i_lock), MR_ACCESS));
    -	ASSERT(valusema(&(ip->i_flock)) <= 0);
    -	/*
    -	 * Since we were able to lock the inode's flush lock and
    -	 * we found it on the AIL, the inode must be dirty.  This
    -	 * is because the inode is removed from the AIL while still
    -	 * holding the flush lock in xfs_iflush_done().  Thus, if
    -	 * we found it in the AIL and were able to obtain the flush
    -	 * lock without sleeping, then there must not have been
    -	 * anyone in the process of flushing the inode.
    -	 */
    -	ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) ||
    -	       iip->ili_format.ilf_fields != 0);
    -
    -	/*
    -	 * Write out the inode.  The completion routine ('iflush_done') will
    -	 * pull it from the AIL, mark it clean, unlock the flush lock.
    -	 */
    -	(void) xfs_iflush(ip, XFS_IFLUSH_ASYNC);
    -	xfs_iunlock(ip, XFS_ILOCK_SHARED);
    -
    -	return;
    -}
    -
    -/*
    - * XXX rcc - this one really has to do something.  Probably needs
    - * to stamp in a new field in the incore inode.
    - */
    -/* ARGSUSED */
    -STATIC void
    -xfs_inode_item_committing(
    -	xfs_inode_log_item_t	*iip,
    -	xfs_lsn_t		lsn)
    -{
    -	iip->ili_last_lsn = lsn;
    -	return;
    -}
    -
    -/*
    - * This is the ops vector shared by all buf log items.
    - */
    -STATIC struct xfs_item_ops xfs_inode_item_ops = {
    -	.iop_size	= (uint(*)(xfs_log_item_t*))xfs_inode_item_size,
    -	.iop_format	= (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
    -					xfs_inode_item_format,
    -	.iop_pin	= (void(*)(xfs_log_item_t*))xfs_inode_item_pin,
    -	.iop_unpin	= (void(*)(xfs_log_item_t*, int))xfs_inode_item_unpin,
    -	.iop_unpin_remove = (void(*)(xfs_log_item_t*, xfs_trans_t*))
    -					xfs_inode_item_unpin_remove,
    -	.iop_trylock	= (uint(*)(xfs_log_item_t*))xfs_inode_item_trylock,
    -	.iop_unlock	= (void(*)(xfs_log_item_t*))xfs_inode_item_unlock,
    -	.iop_committed	= (xfs_lsn_t(*)(xfs_log_item_t*, xfs_lsn_t))
    -					xfs_inode_item_committed,
    -	.iop_push	= (void(*)(xfs_log_item_t*))xfs_inode_item_push,
    -	.iop_abort	= (void(*)(xfs_log_item_t*))xfs_inode_item_abort,
    -	.iop_pushbuf	= (void(*)(xfs_log_item_t*))xfs_inode_item_pushbuf,
    -	.iop_committing = (void(*)(xfs_log_item_t*, xfs_lsn_t))
    -					xfs_inode_item_committing
    -};
    -
    -
    -/*
    - * Initialize the inode log item for a newly allocated (in-core) inode.
    - */
    -void
    -xfs_inode_item_init(
    -	xfs_inode_t	*ip,
    -	xfs_mount_t	*mp)
    -{
    -	xfs_inode_log_item_t	*iip;
    -
    -	ASSERT(ip->i_itemp == NULL);
    -	iip = ip->i_itemp = kmem_zone_zalloc(xfs_ili_zone, KM_SLEEP);
    -
    -	iip->ili_item.li_type = XFS_LI_INODE;
    -	iip->ili_item.li_ops = &xfs_inode_item_ops;
    -	iip->ili_item.li_mountp = mp;
    -	iip->ili_inode = ip;
    -
    -	/*
    -	   We have zeroed memory. No need ...
    -	   iip->ili_extents_buf = NULL;
    -	   iip->ili_pushbuf_flag = 0;
    -	 */
    -
    -	iip->ili_format.ilf_type = XFS_LI_INODE;
    -	iip->ili_format.ilf_ino = ip->i_ino;
    -	iip->ili_format.ilf_blkno = ip->i_blkno;
    -	iip->ili_format.ilf_len = ip->i_len;
    -	iip->ili_format.ilf_boffset = ip->i_boffset;
    -}
    -
    -/*
    - * Free the inode log item and any memory hanging off of it.
    - */
    -void
    -xfs_inode_item_destroy(
    -	xfs_inode_t	*ip)
    -{
    -#ifdef XFS_TRANS_DEBUG
    -	if (ip->i_itemp->ili_root_size != 0) {
    -		kmem_free(ip->i_itemp->ili_orig_root,
    -			  ip->i_itemp->ili_root_size);
    -	}
    -#endif
    -	kmem_zone_free(xfs_ili_zone, ip->i_itemp);
    -}
    -
    -
    -/*
    - * This is the inode flushing I/O completion routine.  It is called
    - * from interrupt level when the buffer containing the inode is
    - * flushed to disk.  It is responsible for removing the inode item
    - * from the AIL if it has not been re-logged, and unlocking the inode's
    - * flush lock.
    - */
    -/*ARGSUSED*/
    -void
    -xfs_iflush_done(
    -	xfs_buf_t		*bp,
    -	xfs_inode_log_item_t	*iip)
    -{
    -	xfs_inode_t	*ip;
    -	SPLDECL(s);
    -
    -	ip = iip->ili_inode;
    -
    -	/*
    -	 * We only want to pull the item from the AIL if it is
    -	 * actually there and its location in the log has not
    -	 * changed since we started the flush.  Thus, we only bother
    -	 * if the ili_logged flag is set and the inode's lsn has not
    -	 * changed.  First we check the lsn outside
    -	 * the lock since it's cheaper, and then we recheck while
    -	 * holding the lock before removing the inode from the AIL.
    -	 */
    -	if (iip->ili_logged &&
    -	    (iip->ili_item.li_lsn == iip->ili_flush_lsn)) {
    -		AIL_LOCK(ip->i_mount, s);
    -		if (iip->ili_item.li_lsn == iip->ili_flush_lsn) {
    -			/*
    -			 * xfs_trans_delete_ail() drops the AIL lock.
    -			 */
    -			xfs_trans_delete_ail(ip->i_mount,
    -					     (xfs_log_item_t*)iip, s);
    -		} else {
    -			AIL_UNLOCK(ip->i_mount, s);
    -		}
    -	}
    -
    -	iip->ili_logged = 0;
    -
    -	/*
    -	 * Clear the ili_last_fields bits now that we know that the
    -	 * data corresponding to them is safely on disk.
    -	 */
    -	iip->ili_last_fields = 0;
    -
    -	/*
    -	 * Release the inode's flush lock since we're done with it.
    -	 */
    -	xfs_ifunlock(ip);
    -
    -	return;
    -}
    -
    -/*
    - * This is the inode flushing abort routine.  It is called
    - * from xfs_iflush when the filesystem is shutting down to clean
    - * up the inode state.
    - * It is responsible for removing the inode item
    - * from the AIL if it has not been re-logged, and unlocking the inode's
    - * flush lock.
    - */
    -void
    -xfs_iflush_abort(
    -	xfs_inode_t		*ip)
    -{
    -	xfs_inode_log_item_t	*iip;
    -	xfs_mount_t		*mp;
    -	SPLDECL(s);
    -
    -	iip = ip->i_itemp;
    -	mp = ip->i_mount;
    -	if (iip) {
    -		if (iip->ili_item.li_flags & XFS_LI_IN_AIL) {
    -			AIL_LOCK(mp, s);
    -			if (iip->ili_item.li_flags & XFS_LI_IN_AIL) {
    -				/*
    -				 * xfs_trans_delete_ail() drops the AIL lock.
    -				 */
    -				xfs_trans_delete_ail(mp, (xfs_log_item_t *)iip,
    -					s);
    -			} else
    -				AIL_UNLOCK(mp, s);
    -		}
    -		iip->ili_logged = 0;
    -		/*
    -		 * Clear the ili_last_fields bits now that we know that the
    -		 * data corresponding to them is safely on disk.
    -		 */
    -		iip->ili_last_fields = 0;
    -		/*
    -		 * Clear the inode logging fields so no more flushes are
    -		 * attempted.
    -		 */
    -		iip->ili_format.ilf_fields = 0;
    -	}
    -	/*
    -	 * Release the inode's flush lock since we're done with it.
    -	 */
    -	xfs_ifunlock(ip);
    -}
    -
    -void
    -xfs_istale_done(
    -	xfs_buf_t		*bp,
    -	xfs_inode_log_item_t	*iip)
    -{
    -	xfs_iflush_abort(iip->ili_inode);
    -}
    diff --git a/sys/gnu/fs/xfs/xfs_inode_item.h b/sys/gnu/fs/xfs/xfs_inode_item.h
    deleted file mode 100644
    index c5dbf93b666..00000000000
    --- a/sys/gnu/fs/xfs/xfs_inode_item.h
    +++ /dev/null
    @@ -1,178 +0,0 @@
    -/*
    - * Copyright (c) 2000,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef	__XFS_INODE_ITEM_H__
    -#define	__XFS_INODE_ITEM_H__
    -
    -/*
    - * This is the structure used to lay out an inode log item in the
    - * log.  The size of the inline data/extents/b-tree root to be logged
    - * (if any) is indicated in the ilf_dsize field.  Changes to this structure
    - * must be added on to the end.
    - *
    - * Convention for naming inode log item versions :  The current version
    - * is always named XFS_LI_INODE.  When an inode log item gets superseded,
    - * add the latest version of IRIX that will generate logs with that item
    - * to the version name.
    - *
    - * -Version 1 of this structure (XFS_LI_5_3_INODE) included up to the first
    - *	union (ilf_u) field.  This was released with IRIX 5.3-XFS.
    - * -Version 2 of this structure (XFS_LI_6_1_INODE) is currently the entire
    - *	structure.  This was released with IRIX 6.0.1-XFS and IRIX 6.1.
    - * -Version 3 of this structure (XFS_LI_INODE) is the same as version 2
    - *	so a new structure definition wasn't necessary.  However, we had
    - *	to add a new type because the inode cluster size changed from 4K
    - *	to 8K and the version number had to be rev'ved to keep older kernels
    - *	from trying to recover logs with the 8K buffers in them.  The logging
    - *	code can handle recovery on different-sized clusters now so hopefully
    - *	this'll be the last time we need to change the inode log item just
    - *	for a change in the inode cluster size.  This new version was
    - *	released with IRIX 6.2.
    - */
    -typedef struct xfs_inode_log_format {
    -	unsigned short		ilf_type;	/* inode log item type */
    -	unsigned short		ilf_size;	/* size of this item */
    -	uint			ilf_fields;	/* flags for fields logged */
    -	ushort			ilf_asize;	/* size of attr d/ext/root */
    -	ushort			ilf_dsize;	/* size of data/ext/root */
    -	xfs_ino_t		ilf_ino;	/* inode number */
    -	union {
    -		xfs_dev_t	ilfu_rdev;	/* rdev value for dev inode*/
    -		uuid_t		ilfu_uuid;	/* mount point value */
    -	} ilf_u;
    -	__int64_t		ilf_blkno;	/* blkno of inode buffer */
    -	int			ilf_len;	/* len of inode buffer */
    -	int			ilf_boffset;	/* off of inode in buffer */
    -} xfs_inode_log_format_t;
    -
    -/* Initial version shipped with IRIX 5.3-XFS */
    -typedef struct xfs_inode_log_format_v1 {
    -	unsigned short		ilf_type;	/* inode log item type */
    -	unsigned short		ilf_size;	/* size of this item */
    -	uint			ilf_fields;	/* flags for fields logged */
    -	uint			ilf_dsize;	/* size of data/ext/root */
    -	xfs_ino_t		ilf_ino;	/* inode number */
    -	union {
    -		xfs_dev_t	ilfu_rdev;	/* rdev value for dev inode*/
    -		uuid_t		ilfu_uuid;	/* mount point value */
    -	} ilf_u;
    -} xfs_inode_log_format_t_v1;
    -
    -/*
    - * Flags for xfs_trans_log_inode flags field.
    - */
    -#define	XFS_ILOG_CORE	0x001	/* log standard inode fields */
    -#define	XFS_ILOG_DDATA	0x002	/* log i_df.if_data */
    -#define	XFS_ILOG_DEXT	0x004	/* log i_df.if_extents */
    -#define	XFS_ILOG_DBROOT	0x008	/* log i_df.i_broot */
    -#define	XFS_ILOG_DEV	0x010	/* log the dev field */
    -#define	XFS_ILOG_UUID	0x020	/* log the uuid field */
    -#define	XFS_ILOG_ADATA	0x040	/* log i_af.if_data */
    -#define	XFS_ILOG_AEXT	0x080	/* log i_af.if_extents */
    -#define	XFS_ILOG_ABROOT	0x100	/* log i_af.i_broot */
    -
    -#define	XFS_ILOG_NONCORE	(XFS_ILOG_DDATA | XFS_ILOG_DEXT | \
    -				 XFS_ILOG_DBROOT | XFS_ILOG_DEV | \
    -				 XFS_ILOG_UUID | XFS_ILOG_ADATA | \
    -				 XFS_ILOG_AEXT | XFS_ILOG_ABROOT)
    -
    -#define	XFS_ILOG_DFORK		(XFS_ILOG_DDATA | XFS_ILOG_DEXT | \
    -				 XFS_ILOG_DBROOT)
    -
    -#define	XFS_ILOG_AFORK		(XFS_ILOG_ADATA | XFS_ILOG_AEXT | \
    -				 XFS_ILOG_ABROOT)
    -
    -#define	XFS_ILOG_ALL		(XFS_ILOG_CORE | XFS_ILOG_DDATA | \
    -				 XFS_ILOG_DEXT | XFS_ILOG_DBROOT | \
    -				 XFS_ILOG_DEV | XFS_ILOG_UUID | \
    -				 XFS_ILOG_ADATA | XFS_ILOG_AEXT | \
    -				 XFS_ILOG_ABROOT)
    -
    -#define	XFS_ILI_HOLD		0x1
    -#define	XFS_ILI_IOLOCKED_EXCL	0x2
    -#define	XFS_ILI_IOLOCKED_SHARED	0x4
    -
    -#define	XFS_ILI_IOLOCKED_ANY   (XFS_ILI_IOLOCKED_EXCL | XFS_ILI_IOLOCKED_SHARED)
    -
    -
    -#ifdef __KERNEL__
    -
    -struct xfs_buf;
    -struct xfs_bmbt_rec_64;
    -struct xfs_inode;
    -struct xfs_mount;
    -
    -
    -typedef struct xfs_inode_log_item {
    -	xfs_log_item_t		ili_item;	   /* common portion */
    -	struct xfs_inode	*ili_inode;	   /* inode ptr */
    -	xfs_lsn_t		ili_flush_lsn;	   /* lsn at last flush */
    -	xfs_lsn_t		ili_last_lsn;	   /* lsn at last transaction */
    -	unsigned short		ili_ilock_recur;   /* lock recursion count */
    -	unsigned short		ili_iolock_recur;  /* lock recursion count */
    -	unsigned short		ili_flags;	   /* misc flags */
    -	unsigned short		ili_logged;	   /* flushed logged data */
    -	unsigned int		ili_last_fields;   /* fields when flushed */
    -	struct xfs_bmbt_rec_64	*ili_extents_buf;  /* array of logged
    -						      data exts */
    -	struct xfs_bmbt_rec_64	*ili_aextents_buf; /* array of logged
    -						      attr exts */
    -	unsigned int            ili_pushbuf_flag;  /* one bit used in push_ail */
    -
    -#ifdef DEBUG
    -	uint64_t                ili_push_owner;    /* one who sets pushbuf_flag
    -						      above gets to push the buf */
    -#endif
    -#ifdef XFS_TRANS_DEBUG
    -	int			ili_root_size;
    -	char			*ili_orig_root;
    -#endif
    -	xfs_inode_log_format_t	ili_format;	   /* logged structure */
    -} xfs_inode_log_item_t;
    -
    -
    -#define	XFS_ILOG_FDATA(w)	xfs_ilog_fdata(w)
    -static inline int xfs_ilog_fdata(int w)
    -{
    -	return (w == XFS_DATA_FORK ? XFS_ILOG_DDATA : XFS_ILOG_ADATA);
    -}
    -
    -#endif	/* __KERNEL__ */
    -
    -#define	XFS_ILOG_FBROOT(w)	xfs_ilog_fbroot(w)
    -static inline int xfs_ilog_fbroot(int w)
    -{
    -	return (w == XFS_DATA_FORK ? XFS_ILOG_DBROOT : XFS_ILOG_ABROOT);
    -}
    -
    -#define	XFS_ILOG_FEXT(w)	xfs_ilog_fext(w)
    -static inline int xfs_ilog_fext(int w)
    -{
    -	return (w == XFS_DATA_FORK ? XFS_ILOG_DEXT : XFS_ILOG_AEXT);
    -}
    -
    -#ifdef __KERNEL__
    -
    -extern void xfs_inode_item_init(struct xfs_inode *, struct xfs_mount *);
    -extern void xfs_inode_item_destroy(struct xfs_inode *);
    -extern void xfs_iflush_done(struct xfs_buf *, xfs_inode_log_item_t *);
    -extern void xfs_istale_done(struct xfs_buf *, xfs_inode_log_item_t *);
    -extern void xfs_iflush_abort(struct xfs_inode *);
    -
    -#endif	/* __KERNEL__ */
    -
    -#endif	/* __XFS_INODE_ITEM_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_inum.h b/sys/gnu/fs/xfs/xfs_inum.h
    deleted file mode 100644
    index 7a28191cb0d..00000000000
    --- a/sys/gnu/fs/xfs/xfs_inum.h
    +++ /dev/null
    @@ -1,81 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_INUM_H__
    -#define	__XFS_INUM_H__
    -
    -/*
    - * Inode number format:
    - * low inopblog bits - offset in block
    - * next agblklog bits - block number in ag
    - * next agno_log bits - ag number
    - * high agno_log-agblklog-inopblog bits - 0
    - */
    -
    -typedef	__uint32_t	xfs_agino_t;	/* within allocation grp inode number */
    -
    -/*
    - * Useful inode bits for this kernel.
    - * Used in some places where having 64-bits in the 32-bit kernels
    - * costs too much.
    - */
    -#if XFS_BIG_INUMS
    -typedef	xfs_ino_t	xfs_intino_t;
    -#else
    -typedef	__uint32_t	xfs_intino_t;
    -#endif
    -
    -#define	NULLFSINO	((xfs_ino_t)-1)
    -#define	NULLAGINO	((xfs_agino_t)-1)
    -
    -struct xfs_mount;
    -
    -#define	XFS_INO_MASK(k)			(__uint32_t)((1ULL << (k)) - 1)
    -#define	XFS_INO_OFFSET_BITS(mp)		(mp)->m_sb.sb_inopblog
    -#define	XFS_INO_AGBNO_BITS(mp)		(mp)->m_sb.sb_agblklog
    -#define	XFS_INO_AGINO_BITS(mp)		(mp)->m_agino_log
    -#define	XFS_INO_AGNO_BITS(mp)		(mp)->m_agno_log
    -#define	XFS_INO_BITS(mp)		\
    -	XFS_INO_AGNO_BITS(mp) + XFS_INO_AGINO_BITS(mp)
    -#define	XFS_INO_TO_AGNO(mp,i)		\
    -	((xfs_agnumber_t)((i) >> XFS_INO_AGINO_BITS(mp)))
    -#define	XFS_INO_TO_AGINO(mp,i)		\
    -	((xfs_agino_t)(i) & XFS_INO_MASK(XFS_INO_AGINO_BITS(mp)))
    -#define	XFS_INO_TO_AGBNO(mp,i)		\
    -	(((xfs_agblock_t)(i) >> XFS_INO_OFFSET_BITS(mp)) & \
    -		XFS_INO_MASK(XFS_INO_AGBNO_BITS(mp)))
    -#define	XFS_INO_TO_OFFSET(mp,i)		\
    -	((int)(i) & XFS_INO_MASK(XFS_INO_OFFSET_BITS(mp)))
    -#define	XFS_INO_TO_FSB(mp,i)		\
    -	XFS_AGB_TO_FSB(mp, XFS_INO_TO_AGNO(mp,i), XFS_INO_TO_AGBNO(mp,i))
    -#define	XFS_AGINO_TO_INO(mp,a,i)	\
    -	(((xfs_ino_t)(a) << XFS_INO_AGINO_BITS(mp)) | (i))
    -#define	XFS_AGINO_TO_AGBNO(mp,i)	((i) >> XFS_INO_OFFSET_BITS(mp))
    -#define	XFS_AGINO_TO_OFFSET(mp,i)	\
    -	((i) & XFS_INO_MASK(XFS_INO_OFFSET_BITS(mp)))
    -#define	XFS_OFFBNO_TO_AGINO(mp,b,o)	\
    -	((xfs_agino_t)(((b) << XFS_INO_OFFSET_BITS(mp)) | (o)))
    -
    -#if XFS_BIG_INUMS
    -#define	XFS_MAXINUMBER		((xfs_ino_t)((1ULL << 56) - 1ULL))
    -#define	XFS_INO64_OFFSET	((xfs_ino_t)(1ULL << 32))
    -#else
    -#define	XFS_MAXINUMBER		((xfs_ino_t)((1ULL << 32) - 1ULL))
    -#endif
    -#define	XFS_MAXINUMBER_32	((xfs_ino_t)((1ULL << 32) - 1ULL))
    -
    -#endif	/* __XFS_INUM_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_iocore.c b/sys/gnu/fs/xfs/xfs_iocore.c
    deleted file mode 100644
    index 19e4f782461..00000000000
    --- a/sys/gnu/fs/xfs/xfs_iocore.c
    +++ /dev/null
    @@ -1,123 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dfrag.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_inode_item.h"
    -#include "xfs_itable.h"
    -#include "xfs_btree.h"
    -#include "xfs_alloc.h"
    -#include "xfs_ialloc.h"
    -#include "xfs_bmap.h"
    -#include "xfs_error.h"
    -#include "xfs_rw.h"
    -#include "xfs_quota.h"
    -#include "xfs_trans_space.h"
    -#include "xfs_iomap.h"
    -
    -
    -
    -STATIC xfs_fsize_t
    -xfs_size_fn(
    -	xfs_inode_t		*ip)
    -{
    -	return (ip->i_d.di_size);
    -}
    -
    -STATIC int
    -xfs_ioinit(
    -	struct xfs_vfs		*vfsp,
    -	struct xfs_mount_args	*mntargs,
    -	int			flags)
    -{
    -	return xfs_mountfs(vfsp, XFS_VFSTOM(vfsp), flags);
    -}
    -
    -xfs_ioops_t	xfs_iocore_xfs = {
    -	.xfs_ioinit		= (xfs_ioinit_t) xfs_ioinit,
    -	.xfs_bmapi_func		= (xfs_bmapi_t) xfs_bmapi,
    -	.xfs_bunmapi_func	= (xfs_bunmapi_t) xfs_bunmapi,
    -	.xfs_bmap_eof_func	= (xfs_bmap_eof_t) xfs_bmap_eof,
    -	.xfs_iomap_write_direct =
    -			(xfs_iomap_write_direct_t) xfs_iomap_write_direct,
    -	.xfs_iomap_write_delay =
    -			(xfs_iomap_write_delay_t) xfs_iomap_write_delay,
    -	.xfs_iomap_write_allocate =
    -			(xfs_iomap_write_allocate_t) xfs_iomap_write_allocate,
    -	.xfs_iomap_write_unwritten =
    -			(xfs_iomap_write_unwritten_t) xfs_iomap_write_unwritten,
    -	.xfs_ilock		= (xfs_lock_t) xfs_ilock,
    -	.xfs_lck_map_shared	= (xfs_lck_map_shared_t) xfs_ilock_map_shared,
    -	.xfs_ilock_demote	= (xfs_lock_demote_t) xfs_ilock_demote,
    -	.xfs_ilock_nowait	= (xfs_lock_nowait_t) xfs_ilock_nowait,
    -	.xfs_unlock		= (xfs_unlk_t) xfs_iunlock,
    -	.xfs_size_func		= (xfs_size_t) xfs_size_fn,
    -	.xfs_iodone		= (xfs_iodone_t) fs_noerr,
    -	.xfs_swap_extents_func	= (xfs_swap_extents_t) xfs_swap_extents,
    -};
    -
    -void
    -xfs_iocore_inode_reinit(
    -	xfs_inode_t	*ip)
    -{
    -	xfs_iocore_t	*io = &ip->i_iocore;
    -
    -	io->io_flags = 0;
    -	if (ip->i_d.di_flags & XFS_DIFLAG_REALTIME)
    -		io->io_flags |= XFS_IOCORE_RT;
    -	io->io_dmevmask = ip->i_d.di_dmevmask;
    -	io->io_dmstate = ip->i_d.di_dmstate;
    -}
    -
    -void
    -xfs_iocore_inode_init(
    -	xfs_inode_t	*ip)
    -{
    -	xfs_iocore_t	*io = &ip->i_iocore;
    -	xfs_mount_t	*mp = ip->i_mount;
    -
    -	io->io_mount = mp;
    -#ifdef DEBUG
    -	io->io_lock = &ip->i_lock;
    -	io->io_iolock = &ip->i_iolock;
    -#endif
    -
    -	io->io_obj = (void *)ip;
    -
    -	xfs_iocore_inode_reinit(ip);
    -}
    -
    diff --git a/sys/gnu/fs/xfs/xfs_iomap.c b/sys/gnu/fs/xfs/xfs_iomap.c
    deleted file mode 100644
    index 2727e633b7d..00000000000
    --- a/sys/gnu/fs/xfs/xfs_iomap.c
    +++ /dev/null
    @@ -1,1006 +0,0 @@
    -/*
    - * Copyright (c) 2000-2006 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_alloc.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_quota.h"
    -#include "xfs_mount.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_ialloc.h"
    -#include "xfs_btree.h"
    -#include "xfs_bmap.h"
    -#include "xfs_rtalloc.h"
    -#include "xfs_error.h"
    -#include "xfs_itable.h"
    -#include "xfs_rw.h"
    -#include "xfs_acl.h"
    -#include "xfs_cap.h"
    -#include "xfs_mac.h"
    -#include "xfs_attr.h"
    -#include "xfs_buf_item.h"
    -#include "xfs_trans_space.h"
    -#include "xfs_utils.h"
    -#include "xfs_iomap.h"
    -
    -#if defined(XFS_RW_TRACE)
    -void
    -xfs_iomap_enter_trace(
    -	int		tag,
    -	xfs_iocore_t	*io,
    -	xfs_off_t	offset,
    -	ssize_t		count)
    -{
    -	xfs_inode_t	*ip = XFS_IO_INODE(io);
    -
    -	if (!ip->i_rwtrace)
    -		return;
    -
    -	ktrace_enter(ip->i_rwtrace,
    -		(void *)((unsigned long)tag),
    -		(void *)ip,
    -		(void *)((unsigned long)((ip->i_d.di_size >> 32) & 0xffffffff)),
    -		(void *)((unsigned long)(ip->i_d.di_size & 0xffffffff)),
    -		(void *)((unsigned long)((offset >> 32) & 0xffffffff)),
    -		(void *)((unsigned long)(offset & 0xffffffff)),
    -		(void *)((unsigned long)count),
    -		(void *)((unsigned long)((io->io_new_size >> 32) & 0xffffffff)),
    -		(void *)((unsigned long)(io->io_new_size & 0xffffffff)),
    -		(void *)((unsigned long)current_pid()),
    -		(void *)NULL,
    -		(void *)NULL,
    -		(void *)NULL,
    -		(void *)NULL,
    -		(void *)NULL,
    -		(void *)NULL);
    -}
    -
    -void
    -xfs_iomap_map_trace(
    -	int		tag,
    -	xfs_iocore_t	*io,
    -	xfs_off_t	offset,
    -	ssize_t		count,
    -	xfs_iomap_t	*iomapp,
    -	xfs_bmbt_irec_t	*imapp,
    -	int		flags)
    -{
    -	xfs_inode_t	*ip = XFS_IO_INODE(io);
    -
    -	if (!ip->i_rwtrace)
    -		return;
    -
    -	ktrace_enter(ip->i_rwtrace,
    -		(void *)((unsigned long)tag),
    -		(void *)ip,
    -		(void *)((unsigned long)((ip->i_d.di_size >> 32) & 0xffffffff)),
    -		(void *)((unsigned long)(ip->i_d.di_size & 0xffffffff)),
    -		(void *)((unsigned long)((offset >> 32) & 0xffffffff)),
    -		(void *)((unsigned long)(offset & 0xffffffff)),
    -		(void *)((unsigned long)count),
    -		(void *)((unsigned long)flags),
    -		(void *)((unsigned long)((iomapp->iomap_offset >> 32) & 0xffffffff)),
    -		(void *)((unsigned long)(iomapp->iomap_offset & 0xffffffff)),
    -		(void *)((unsigned long)(iomapp->iomap_delta)),
    -		(void *)((unsigned long)(iomapp->iomap_bsize)),
    -		(void *)((unsigned long)(iomapp->iomap_bn)),
    -		(void *)(__psint_t)(imapp->br_startoff),
    -		(void *)((unsigned long)(imapp->br_blockcount)),
    -		(void *)(__psint_t)(imapp->br_startblock));
    -}
    -#else
    -#define xfs_iomap_enter_trace(tag, io, offset, count)
    -#define xfs_iomap_map_trace(tag, io, offset, count, iomapp, imapp, flags)
    -#endif
    -
    -#define XFS_WRITEIO_ALIGN(mp,off)	(((off) >> mp->m_writeio_log) \
    -						<< mp->m_writeio_log)
    -#define XFS_STRAT_WRITE_IMAPS	2
    -#define XFS_WRITE_IMAPS		XFS_BMAP_MAX_NMAP
    -
    -STATIC int
    -xfs_imap_to_bmap(
    -	xfs_iocore_t	*io,
    -	xfs_off_t	offset,
    -	xfs_bmbt_irec_t *imap,
    -	xfs_iomap_t	*iomapp,
    -	int		imaps,			/* Number of imap entries */
    -	int		iomaps,			/* Number of iomap entries */
    -	int		flags)
    -{
    -	xfs_mount_t	*mp;
    -	xfs_fsize_t	nisize;
    -	int		pbm;
    -	xfs_fsblock_t	start_block;
    -
    -	mp = io->io_mount;
    -	nisize = XFS_SIZE(mp, io);
    -	if (io->io_new_size > nisize)
    -		nisize = io->io_new_size;
    -
    -	for (pbm = 0; imaps && pbm < iomaps; imaps--, iomapp++, imap++, pbm++) {
    -		iomapp->iomap_offset = XFS_FSB_TO_B(mp, imap->br_startoff);
    -		iomapp->iomap_delta = offset - iomapp->iomap_offset;
    -		iomapp->iomap_bsize = XFS_FSB_TO_B(mp, imap->br_blockcount);
    -		iomapp->iomap_flags = flags;
    -
    -		if (io->io_flags & XFS_IOCORE_RT) {
    -			iomapp->iomap_flags |= IOMAP_REALTIME;
    -			iomapp->iomap_target = mp->m_rtdev_targp;
    -		} else {
    -			iomapp->iomap_target = mp->m_ddev_targp;
    -		}
    -		start_block = imap->br_startblock;
    -		if (start_block == HOLESTARTBLOCK) {
    -			iomapp->iomap_bn = IOMAP_DADDR_NULL;
    -			iomapp->iomap_flags |= IOMAP_HOLE;
    -		} else if (start_block == DELAYSTARTBLOCK) {
    -			iomapp->iomap_bn = IOMAP_DADDR_NULL;
    -			iomapp->iomap_flags |= IOMAP_DELAY;
    -		} else {
    -			iomapp->iomap_bn = XFS_FSB_TO_DB_IO(io, start_block);
    -			if (ISUNWRITTEN(imap))
    -				iomapp->iomap_flags |= IOMAP_UNWRITTEN;
    -		}
    -
    -		if ((iomapp->iomap_offset + iomapp->iomap_bsize) >= nisize) {
    -			iomapp->iomap_flags |= IOMAP_EOF;
    -		}
    -
    -		offset += iomapp->iomap_bsize - iomapp->iomap_delta;
    -	}
    -	return pbm;	/* Return the number filled */
    -}
    -
    -int
    -xfs_iomap(
    -	xfs_iocore_t	*io,
    -	xfs_off_t	offset,
    -	ssize_t		count,
    -	int		flags,
    -	xfs_iomap_t	*iomapp,
    -	int		*niomaps)
    -{
    -	xfs_mount_t	*mp = io->io_mount;
    -	xfs_fileoff_t	offset_fsb, end_fsb;
    -	int		error = 0;
    -	int		lockmode = 0;
    -	xfs_bmbt_irec_t	imap;
    -	int		nimaps = 1;
    -	int		bmapi_flags = 0;
    -	int		iomap_flags = 0;
    -
    -	if (XFS_FORCED_SHUTDOWN(mp))
    -		return XFS_ERROR(EIO);
    -
    -	switch (flags &
    -		(BMAPI_READ | BMAPI_WRITE | BMAPI_ALLOCATE |
    -		 BMAPI_UNWRITTEN | BMAPI_DEVICE)) {
    -	case BMAPI_READ:
    -		xfs_iomap_enter_trace(XFS_IOMAP_READ_ENTER, io, offset, count);
    -		lockmode = XFS_LCK_MAP_SHARED(mp, io);
    -		bmapi_flags = XFS_BMAPI_ENTIRE;
    -		break;
    -	case BMAPI_WRITE:
    -		xfs_iomap_enter_trace(XFS_IOMAP_WRITE_ENTER, io, offset, count);
    -		lockmode = XFS_ILOCK_EXCL|XFS_EXTSIZE_WR;
    -		if (flags & BMAPI_IGNSTATE)
    -			bmapi_flags |= XFS_BMAPI_IGSTATE|XFS_BMAPI_ENTIRE;
    -		XFS_ILOCK(mp, io, lockmode);
    -		break;
    -	case BMAPI_ALLOCATE:
    -		xfs_iomap_enter_trace(XFS_IOMAP_ALLOC_ENTER, io, offset, count);
    -		lockmode = XFS_ILOCK_SHARED|XFS_EXTSIZE_RD;
    -		bmapi_flags = XFS_BMAPI_ENTIRE;
    -		/* Attempt non-blocking lock */
    -		if (flags & BMAPI_TRYLOCK) {
    -			if (!XFS_ILOCK_NOWAIT(mp, io, lockmode))
    -				return XFS_ERROR(EAGAIN);
    -		} else {
    -			XFS_ILOCK(mp, io, lockmode);
    -		}
    -		break;
    -	case BMAPI_UNWRITTEN:
    -		goto phase2;
    -	case BMAPI_DEVICE:
    -		lockmode = XFS_LCK_MAP_SHARED(mp, io);
    -		iomapp->iomap_target = io->io_flags & XFS_IOCORE_RT ?
    -			mp->m_rtdev_targp : mp->m_ddev_targp;
    -		error = 0;
    -		*niomaps = 1;
    -		goto out;
    -	default:
    -		panic("unrecognized bmapi flags");
    -	}
    -
    -	ASSERT(offset <= mp->m_maxioffset);
    -	if ((xfs_fsize_t)offset + count > mp->m_maxioffset)
    -		count = mp->m_maxioffset - offset;
    -	end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count);
    -	offset_fsb = XFS_B_TO_FSBT(mp, offset);
    -
    -	error = XFS_BMAPI(mp, NULL, io, offset_fsb,
    -			(xfs_filblks_t)(end_fsb - offset_fsb),
    -			bmapi_flags,  NULL, 0, &imap,
    -			&nimaps, NULL, NULL);
    -
    -	if (error)
    -		goto out;
    -
    -phase2:
    -	switch (flags & (BMAPI_WRITE|BMAPI_ALLOCATE|BMAPI_UNWRITTEN)) {
    -	case BMAPI_WRITE:
    -		/* If we found an extent, return it */
    -		if (nimaps &&
    -		    (imap.br_startblock != HOLESTARTBLOCK) &&
    -		    (imap.br_startblock != DELAYSTARTBLOCK)) {
    -			xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, io,
    -					offset, count, iomapp, &imap, flags);
    -			break;
    -		}
    -
    -		if (flags & (BMAPI_DIRECT|BMAPI_MMAP)) {
    -			error = XFS_IOMAP_WRITE_DIRECT(mp, io, offset,
    -					count, flags, &imap, &nimaps, nimaps);
    -		} else {
    -			error = XFS_IOMAP_WRITE_DELAY(mp, io, offset, count,
    -					flags, &imap, &nimaps);
    -		}
    -		if (!error) {
    -			xfs_iomap_map_trace(XFS_IOMAP_ALLOC_MAP, io,
    -					offset, count, iomapp, &imap, flags);
    -		}
    -		iomap_flags = IOMAP_NEW;
    -		break;
    -	case BMAPI_ALLOCATE:
    -		/* If we found an extent, return it */
    -		XFS_IUNLOCK(mp, io, lockmode);
    -		lockmode = 0;
    -
    -		if (nimaps && !ISNULLSTARTBLOCK(imap.br_startblock)) {
    -			xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, io,
    -					offset, count, iomapp, &imap, flags);
    -			break;
    -		}
    -
    -		error = XFS_IOMAP_WRITE_ALLOCATE(mp, io, offset, count,
    -						 &imap, &nimaps);
    -		break;
    -	case BMAPI_UNWRITTEN:
    -		lockmode = 0;
    -		error = XFS_IOMAP_WRITE_UNWRITTEN(mp, io, offset, count);
    -		nimaps = 0;
    -		break;
    -	}
    -
    -	if (nimaps) {
    -		*niomaps = xfs_imap_to_bmap(io, offset, &imap,
    -					    iomapp, nimaps, *niomaps, iomap_flags);
    -	} else if (niomaps) {
    -		*niomaps = 0;
    -	}
    -
    -out:
    -	if (lockmode)
    -		XFS_IUNLOCK(mp, io, lockmode);
    -	return XFS_ERROR(error);
    -}
    -
    -STATIC int
    -xfs_iomap_eof_align_last_fsb(
    -	xfs_mount_t	*mp,
    -	xfs_iocore_t	*io,
    -	xfs_fsize_t	isize,
    -	xfs_extlen_t	extsize,
    -	xfs_fileoff_t	*last_fsb)
    -{
    -	xfs_fileoff_t	new_last_fsb = 0;
    -	xfs_extlen_t	align;
    -	int		eof, error;
    -
    -	if (io->io_flags & XFS_IOCORE_RT)
    -		;
    -	/*
    -	 * If mounted with the "-o swalloc" option, roundup the allocation
    -	 * request to a stripe width boundary if the file size is >=
    -	 * stripe width and we are allocating past the allocation eof.
    -	 */
    -	else if (mp->m_swidth && (mp->m_flags & XFS_MOUNT_SWALLOC) &&
    -	        (isize >= XFS_FSB_TO_B(mp, mp->m_swidth)))
    -		new_last_fsb = roundup_64(*last_fsb, mp->m_swidth);
    -	/*
    -	 * Roundup the allocation request to a stripe unit (m_dalign) boundary
    -	 * if the file size is >= stripe unit size, and we are allocating past
    -	 * the allocation eof.
    -	 */
    -	else if (mp->m_dalign && (isize >= XFS_FSB_TO_B(mp, mp->m_dalign)))
    -		new_last_fsb = roundup_64(*last_fsb, mp->m_dalign);
    -
    -	/*
    -	 * Always round up the allocation request to an extent boundary
    -	 * (when file on a real-time subvolume or has di_extsize hint).
    -	 */
    -	if (extsize) {
    -		if (new_last_fsb)
    -			align = roundup_64(new_last_fsb, extsize);
    -		else
    -			align = extsize;
    -		new_last_fsb = roundup_64(*last_fsb, align);
    -	}
    -
    -	if (new_last_fsb) {
    -		error = XFS_BMAP_EOF(mp, io, new_last_fsb, XFS_DATA_FORK, &eof);
    -		if (error)
    -			return error;
    -		if (eof)
    -			*last_fsb = new_last_fsb;
    -	}
    -	return 0;
    -}
    -
    -STATIC int
    -xfs_flush_space(
    -	xfs_inode_t	*ip,
    -	int		*fsynced,
    -	int		*ioflags)
    -{
    -	switch (*fsynced) {
    -	case 0:
    -		if (ip->i_delayed_blks) {
    -			xfs_iunlock(ip, XFS_ILOCK_EXCL);
    -			xfs_flush_inode(ip);
    -			xfs_ilock(ip, XFS_ILOCK_EXCL);
    -			*fsynced = 1;
    -		} else {
    -			*ioflags |= BMAPI_SYNC;
    -			*fsynced = 2;
    -		}
    -		return 0;
    -	case 1:
    -		*fsynced = 2;
    -		*ioflags |= BMAPI_SYNC;
    -		return 0;
    -	case 2:
    -		xfs_iunlock(ip, XFS_ILOCK_EXCL);
    -		xfs_flush_device(ip);
    -		xfs_ilock(ip, XFS_ILOCK_EXCL);
    -		*fsynced = 3;
    -		return 0;
    -	}
    -	return 1;
    -}
    -
    -int
    -xfs_iomap_write_direct(
    -	xfs_inode_t	*ip,
    -	xfs_off_t	offset,
    -	size_t		count,
    -	int		flags,
    -	xfs_bmbt_irec_t *ret_imap,
    -	int		*nmaps,
    -	int		found)
    -{
    -	xfs_mount_t	*mp = ip->i_mount;
    -	xfs_iocore_t	*io = &ip->i_iocore;
    -	xfs_fileoff_t	offset_fsb;
    -	xfs_fileoff_t	last_fsb;
    -	xfs_filblks_t	count_fsb, resaligned;
    -	xfs_fsblock_t	firstfsb;
    -	xfs_extlen_t	extsz, temp;
    -	xfs_fsize_t	isize;
    -	int		nimaps;
    -	int		bmapi_flag;
    -	int		quota_flag;
    -	int		rt;
    -	xfs_trans_t	*tp;
    -	xfs_bmbt_irec_t imap;
    -	xfs_bmap_free_t free_list;
    -	uint		qblocks, resblks, resrtextents;
    -	int		committed;
    -	int		error;
    -
    -	/*
    -	 * Make sure that the dquots are there. This doesn't hold
    -	 * the ilock across a disk read.
    -	 */
    -	error = XFS_QM_DQATTACH(ip->i_mount, ip, XFS_QMOPT_ILOCKED);
    -	if (error)
    -		return XFS_ERROR(error);
    -
    -	rt = XFS_IS_REALTIME_INODE(ip);
    -	if (unlikely(rt)) {
    -		if (!(extsz = ip->i_d.di_extsize))
    -			extsz = mp->m_sb.sb_rextsize;
    -	} else {
    -		extsz = ip->i_d.di_extsize;
    -	}
    -
    -	isize = ip->i_d.di_size;
    -	if (io->io_new_size > isize)
    -		isize = io->io_new_size;
    -
    -  	offset_fsb = XFS_B_TO_FSBT(mp, offset);
    -  	last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count)));
    -	if ((offset + count) > isize) {
    -		error = xfs_iomap_eof_align_last_fsb(mp, io, isize, extsz,
    -							&last_fsb);
    -		if (error)
    -			goto error_out;
    -	} else {
    -		if (found && (ret_imap->br_startblock == HOLESTARTBLOCK))
    -			last_fsb = MIN(last_fsb, (xfs_fileoff_t)
    -					ret_imap->br_blockcount +
    -					ret_imap->br_startoff);
    -	}
    -	count_fsb = last_fsb - offset_fsb;
    -	ASSERT(count_fsb > 0);
    -
    -	resaligned = count_fsb;
    -	if (unlikely(extsz)) {
    -		if ((temp = do_mod(offset_fsb, extsz)))
    -			resaligned += temp;
    -		if ((temp = do_mod(resaligned, extsz)))
    -			resaligned += extsz - temp;
    -	}
    -
    -	if (unlikely(rt)) {
    -		resrtextents = qblocks = resaligned;
    -		resrtextents /= mp->m_sb.sb_rextsize;
    -  		resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
    -  		quota_flag = XFS_QMOPT_RES_RTBLKS;
    -  	} else {
    -  		resrtextents = 0;
    -		resblks = qblocks = XFS_DIOSTRAT_SPACE_RES(mp, resaligned);
    -  		quota_flag = XFS_QMOPT_RES_REGBLKS;
    -  	}
    -
    -	/*
    -	 * Allocate and setup the transaction
    -	 */
    -	xfs_iunlock(ip, XFS_ILOCK_EXCL);
    -	tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT);
    -	error = xfs_trans_reserve(tp, resblks,
    -			XFS_WRITE_LOG_RES(mp), resrtextents,
    -			XFS_TRANS_PERM_LOG_RES,
    -			XFS_WRITE_LOG_COUNT);
    -	/*
    -	 * Check for running out of space, note: need lock to return
    -	 */
    -	if (error)
    -		xfs_trans_cancel(tp, 0);
    -	xfs_ilock(ip, XFS_ILOCK_EXCL);
    -	if (error)
    -		goto error_out;
    -
    -	error = XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip,
    -					      qblocks, 0, quota_flag);
    -	if (error)
    -		goto error1;
    -
    -	xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
    -	xfs_trans_ihold(tp, ip);
    -
    -	bmapi_flag = XFS_BMAPI_WRITE;
    -	if ((flags & BMAPI_DIRECT) && (offset < ip->i_d.di_size || extsz))
    -		bmapi_flag |= XFS_BMAPI_PREALLOC;
    -
    -	/*
    -	 * Issue the xfs_bmapi() call to allocate the blocks
    -	 */
    -	XFS_BMAP_INIT(&free_list, &firstfsb);
    -	nimaps = 1;
    -	error = XFS_BMAPI(mp, tp, io, offset_fsb, count_fsb, bmapi_flag,
    -		&firstfsb, 0, &imap, &nimaps, &free_list, NULL);
    -	if (error)
    -		goto error0;
    -
    -	/*
    -	 * Complete the transaction
    -	 */
    -	error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed);
    -	if (error)
    -		goto error0;
    -	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
    -	if (error)
    -		goto error_out;
    -
    -	/*
    -	 * Copy any maps to caller's array and return any error.
    -	 */
    -	if (nimaps == 0) {
    -		error = (ENOSPC);
    -		goto error_out;
    -	}
    -
    -	*ret_imap = imap;
    -	*nmaps = 1;
    -	if ( !(io->io_flags & XFS_IOCORE_RT)  && !ret_imap->br_startblock) {
    -                cmn_err(CE_PANIC,"Access to block zero:  fs <%s> inode: %lld "
    -                        "start_block : %llx start_off : %llx blkcnt : %llx "
    -                        "extent-state : %x \n",
    -                        (ip->i_mount)->m_fsname,
    -                        (long long)ip->i_ino,
    -                        (unsigned long long)ret_imap->br_startblock,
    -			(unsigned long long)ret_imap->br_startoff,
    -                        (unsigned long long)ret_imap->br_blockcount,
    -			ret_imap->br_state);
    -        }
    -	return 0;
    -
    -error0:	/* Cancel bmap, unlock inode, unreserve quota blocks, cancel trans */
    -	xfs_bmap_cancel(&free_list);
    -	XFS_TRANS_UNRESERVE_QUOTA_NBLKS(mp, tp, ip, qblocks, 0, quota_flag);
    -
    -error1:	/* Just cancel transaction */
    -	xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
    -	*nmaps = 0;	/* nothing set-up here */
    -
    -error_out:
    -	return XFS_ERROR(error);
    -}
    -
    -/*
    - * If the caller is doing a write at the end of the file,
    - * then extend the allocation out to the file system's write
    - * iosize.  We clean up any extra space left over when the
    - * file is closed in xfs_inactive().
    - *
    - * For sync writes, we are flushing delayed allocate space to
    - * try to make additional space available for allocation near
    - * the filesystem full boundary - preallocation hurts in that
    - * situation, of course.
    - */
    -STATIC int
    -xfs_iomap_eof_want_preallocate(
    -	xfs_mount_t	*mp,
    -	xfs_iocore_t	*io,
    -	xfs_fsize_t	isize,
    -	xfs_off_t	offset,
    -	size_t		count,
    -	int		ioflag,
    -	xfs_bmbt_irec_t *imap,
    -	int		nimaps,
    -	int		*prealloc)
    -{
    -	xfs_fileoff_t   start_fsb;
    -	xfs_filblks_t   count_fsb;
    -	xfs_fsblock_t	firstblock;
    -	int		n, error, imaps;
    -
    -	*prealloc = 0;
    -	if ((ioflag & BMAPI_SYNC) || (offset + count) <= isize)
    -		return 0;
    -
    -	/*
    -	 * If there are any real blocks past eof, then don't
    -	 * do any speculative allocation.
    -	 */
    -	start_fsb = XFS_B_TO_FSBT(mp, ((xfs_ufsize_t)(offset + count - 1)));
    -	count_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp));
    -	while (count_fsb > 0) {
    -		imaps = nimaps;
    -		firstblock = NULLFSBLOCK;
    -		error = XFS_BMAPI(mp, NULL, io, start_fsb, count_fsb, 0,
    -				  &firstblock, 0, imap, &imaps, NULL, NULL);
    -		if (error)
    -			return error;
    -		for (n = 0; n < imaps; n++) {
    -			if ((imap[n].br_startblock != HOLESTARTBLOCK) &&
    -			    (imap[n].br_startblock != DELAYSTARTBLOCK))
    -				return 0;
    -			start_fsb += imap[n].br_blockcount;
    -			count_fsb -= imap[n].br_blockcount;
    -		}
    -	}
    -	*prealloc = 1;
    -	return 0;
    -}
    -
    -int
    -xfs_iomap_write_delay(
    -	xfs_inode_t	*ip,
    -	xfs_off_t	offset,
    -	size_t		count,
    -	int		ioflag,
    -	xfs_bmbt_irec_t *ret_imap,
    -	int		*nmaps)
    -{
    -	xfs_mount_t	*mp = ip->i_mount;
    -	xfs_iocore_t	*io = &ip->i_iocore;
    -	xfs_fileoff_t	offset_fsb;
    -	xfs_fileoff_t	last_fsb;
    -	xfs_off_t	aligned_offset;
    -	xfs_fileoff_t	ioalign;
    -	xfs_fsblock_t	firstblock;
    -	xfs_extlen_t	extsz;
    -	xfs_fsize_t	isize;
    -	int		nimaps;
    -	xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS];
    -	int		prealloc, fsynced = 0;
    -	int		error;
    -
    -	ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE) != 0);
    -
    -	/*
    -	 * Make sure that the dquots are there. This doesn't hold
    -	 * the ilock across a disk read.
    -	 */
    -	error = XFS_QM_DQATTACH(mp, ip, XFS_QMOPT_ILOCKED);
    -	if (error)
    -		return XFS_ERROR(error);
    -
    -	if (XFS_IS_REALTIME_INODE(ip)) {
    -		if (!(extsz = ip->i_d.di_extsize))
    -			extsz = mp->m_sb.sb_rextsize;
    -	} else {
    -		extsz = ip->i_d.di_extsize;
    -	}
    -
    -	offset_fsb = XFS_B_TO_FSBT(mp, offset);
    -
    -retry:
    -	isize = ip->i_d.di_size;
    -	if (io->io_new_size > isize)
    -		isize = io->io_new_size;
    -
    -	error = xfs_iomap_eof_want_preallocate(mp, io, isize, offset, count,
    -				ioflag, imap, XFS_WRITE_IMAPS, &prealloc);
    -	if (error)
    -		return error;
    -
    -	if (prealloc) {
    -		aligned_offset = XFS_WRITEIO_ALIGN(mp, (offset + count - 1));
    -		ioalign = XFS_B_TO_FSBT(mp, aligned_offset);
    -		last_fsb = ioalign + mp->m_writeio_blocks;
    -	} else {
    -		last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count)));
    -	}
    -
    -	if (prealloc || extsz) {
    -		error = xfs_iomap_eof_align_last_fsb(mp, io, isize, extsz,
    -							&last_fsb);
    -		if (error)
    -			return error;
    -	}
    -
    -	nimaps = XFS_WRITE_IMAPS;
    -	firstblock = NULLFSBLOCK;
    -	error = XFS_BMAPI(mp, NULL, io, offset_fsb,
    -			  (xfs_filblks_t)(last_fsb - offset_fsb),
    -			  XFS_BMAPI_DELAY | XFS_BMAPI_WRITE |
    -			  XFS_BMAPI_ENTIRE, &firstblock, 1, imap,
    -			  &nimaps, NULL, NULL);
    -	if (error && (error != ENOSPC))
    -		return XFS_ERROR(error);
    -
    -	/*
    -	 * If bmapi returned us nothing, and if we didn't get back EDQUOT,
    -	 * then we must have run out of space - flush delalloc, and retry..
    -	 */
    -	if (nimaps == 0) {
    -		xfs_iomap_enter_trace(XFS_IOMAP_WRITE_NOSPACE,
    -					io, offset, count);
    -		if (xfs_flush_space(ip, &fsynced, &ioflag))
    -			return XFS_ERROR(ENOSPC);
    -
    -		error = 0;
    -		goto retry;
    -	}
    -
    -	if (!(io->io_flags & XFS_IOCORE_RT)  && !ret_imap->br_startblock) {
    -		cmn_err(CE_PANIC,"Access to block zero:  fs <%s> inode: %lld "
    -                        "start_block : %llx start_off : %llx blkcnt : %llx "
    -                        "extent-state : %x \n",
    -                        (ip->i_mount)->m_fsname,
    -                        (long long)ip->i_ino,
    -                        (unsigned long long)ret_imap->br_startblock,
    -			(unsigned long long)ret_imap->br_startoff,
    -                        (unsigned long long)ret_imap->br_blockcount,
    -			ret_imap->br_state);
    -	}
    -
    -	*ret_imap = imap[0];
    -	*nmaps = 1;
    -
    -	return 0;
    -}
    -
    -/*
    - * Pass in a delayed allocate extent, convert it to real extents;
    - * return to the caller the extent we create which maps on top of
    - * the originating callers request.
    - *
    - * Called without a lock on the inode.
    - */
    -int
    -xfs_iomap_write_allocate(
    -	xfs_inode_t	*ip,
    -	xfs_off_t	offset,
    -	size_t		count,
    -	xfs_bmbt_irec_t *map,
    -	int		*retmap)
    -{
    -	xfs_mount_t	*mp = ip->i_mount;
    -	xfs_iocore_t    *io = &ip->i_iocore;
    -	xfs_fileoff_t	offset_fsb, last_block;
    -	xfs_fileoff_t	end_fsb, map_start_fsb;
    -	xfs_fsblock_t	first_block;
    -	xfs_bmap_free_t	free_list;
    -	xfs_filblks_t	count_fsb;
    -	xfs_bmbt_irec_t	imap[XFS_STRAT_WRITE_IMAPS];
    -	xfs_trans_t	*tp;
    -	int		i, nimaps, committed;
    -	int		error = 0;
    -	int		nres;
    -
    -	*retmap = 0;
    -
    -	/*
    -	 * Make sure that the dquots are there.
    -	 */
    -	if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
    -		return XFS_ERROR(error);
    -
    -	offset_fsb = XFS_B_TO_FSBT(mp, offset);
    -	count_fsb = map->br_blockcount;
    -	map_start_fsb = map->br_startoff;
    -
    -	XFS_STATS_ADD(xs_xstrat_bytes, XFS_FSB_TO_B(mp, count_fsb));
    -
    -	while (count_fsb != 0) {
    -		/*
    -		 * Set up a transaction with which to allocate the
    -		 * backing store for the file.  Do allocations in a
    -		 * loop until we get some space in the range we are
    -		 * interested in.  The other space that might be allocated
    -		 * is in the delayed allocation extent on which we sit
    -		 * but before our buffer starts.
    -		 */
    -
    -		nimaps = 0;
    -		while (nimaps == 0) {
    -			tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE);
    -			nres = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK);
    -			error = xfs_trans_reserve(tp, nres,
    -					XFS_WRITE_LOG_RES(mp),
    -					0, XFS_TRANS_PERM_LOG_RES,
    -					XFS_WRITE_LOG_COUNT);
    -			if (error == ENOSPC) {
    -				error = xfs_trans_reserve(tp, 0,
    -						XFS_WRITE_LOG_RES(mp),
    -						0,
    -						XFS_TRANS_PERM_LOG_RES,
    -						XFS_WRITE_LOG_COUNT);
    -			}
    -			if (error) {
    -				xfs_trans_cancel(tp, 0);
    -				return XFS_ERROR(error);
    -			}
    -			xfs_ilock(ip, XFS_ILOCK_EXCL);
    -			xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
    -			xfs_trans_ihold(tp, ip);
    -
    -			XFS_BMAP_INIT(&free_list, &first_block);
    -
    -			nimaps = XFS_STRAT_WRITE_IMAPS;
    -			/*
    -			 * Ensure we don't go beyond eof - it is possible
    -			 * the extents changed since we did the read call,
    -			 * we dropped the ilock in the interim.
    -			 */
    -
    -			end_fsb = XFS_B_TO_FSB(mp, ip->i_d.di_size);
    -			xfs_bmap_last_offset(NULL, ip, &last_block,
    -				XFS_DATA_FORK);
    -			last_block = XFS_FILEOFF_MAX(last_block, end_fsb);
    -			if ((map_start_fsb + count_fsb) > last_block) {
    -				count_fsb = last_block - map_start_fsb;
    -				if (count_fsb == 0) {
    -					error = EAGAIN;
    -					goto trans_cancel;
    -				}
    -			}
    -
    -			/* Go get the actual blocks */
    -			error = XFS_BMAPI(mp, tp, io, map_start_fsb, count_fsb,
    -					XFS_BMAPI_WRITE, &first_block, 1,
    -					imap, &nimaps, &free_list, NULL);
    -			if (error)
    -				goto trans_cancel;
    -
    -			error = xfs_bmap_finish(&tp, &free_list,
    -					first_block, &committed);
    -			if (error)
    -				goto trans_cancel;
    -
    -			error = xfs_trans_commit(tp,
    -					XFS_TRANS_RELEASE_LOG_RES, NULL);
    -			if (error)
    -				goto error0;
    -
    -			xfs_iunlock(ip, XFS_ILOCK_EXCL);
    -		}
    -
    -		/*
    -		 * See if we were able to allocate an extent that
    -		 * covers at least part of the callers request
    -		 */
    -
    -		for (i = 0; i < nimaps; i++) {
    -			if (!(io->io_flags & XFS_IOCORE_RT)  &&
    -			    !imap[i].br_startblock) {
    -				cmn_err(CE_PANIC,"Access to block zero:  "
    -					"fs <%s> inode: %lld "
    -					"start_block : %llx start_off : %llx "
    -					"blkcnt : %llx extent-state : %x \n",
    -					(ip->i_mount)->m_fsname,
    -					(long long)ip->i_ino,
    -					(unsigned long long)
    -						imap[i].br_startblock,
    -					(unsigned long long)
    -						imap[i].br_startoff,
    -					(unsigned long long)
    -				        	imap[i].br_blockcount,
    -					imap[i].br_state);
    -                        }
    -			if ((offset_fsb >= imap[i].br_startoff) &&
    -			    (offset_fsb < (imap[i].br_startoff +
    -					   imap[i].br_blockcount))) {
    -				*map = imap[i];
    -				*retmap = 1;
    -				XFS_STATS_INC(xs_xstrat_quick);
    -				return 0;
    -			}
    -			count_fsb -= imap[i].br_blockcount;
    -		}
    -
    -		/* So far we have not mapped the requested part of the
    -		 * file, just surrounding data, try again.
    -		 */
    -		nimaps--;
    -		map_start_fsb = imap[nimaps].br_startoff +
    -				imap[nimaps].br_blockcount;
    -	}
    -
    -trans_cancel:
    -	xfs_bmap_cancel(&free_list);
    -	xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
    -error0:
    -	xfs_iunlock(ip, XFS_ILOCK_EXCL);
    -	return XFS_ERROR(error);
    -}
    -
    -int
    -xfs_iomap_write_unwritten(
    -	xfs_inode_t	*ip,
    -	xfs_off_t	offset,
    -	size_t		count)
    -{
    -	xfs_mount_t	*mp = ip->i_mount;
    -	xfs_iocore_t    *io = &ip->i_iocore;
    -	xfs_fileoff_t	offset_fsb;
    -	xfs_filblks_t	count_fsb;
    -	xfs_filblks_t	numblks_fsb;
    -	xfs_fsblock_t	firstfsb;
    -	int		nimaps;
    -	xfs_trans_t	*tp;
    -	xfs_bmbt_irec_t imap;
    -	xfs_bmap_free_t free_list;
    -	uint		resblks;
    -	int		committed;
    -	int		error;
    -
    -	xfs_iomap_enter_trace(XFS_IOMAP_UNWRITTEN,
    -				&ip->i_iocore, offset, count);
    -
    -	offset_fsb = XFS_B_TO_FSBT(mp, offset);
    -	count_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count);
    -	count_fsb = (xfs_filblks_t)(count_fsb - offset_fsb);
    -
    -	resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0) << 1;
    -
    -	do {
    -		/*
    -		 * set up a transaction to convert the range of extents
    -		 * from unwritten to real. Do allocations in a loop until
    -		 * we have covered the range passed in.
    -		 */
    -
    -		tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE);
    -		error = xfs_trans_reserve(tp, resblks,
    -				XFS_WRITE_LOG_RES(mp), 0,
    -				XFS_TRANS_PERM_LOG_RES,
    -				XFS_WRITE_LOG_COUNT);
    -		if (error) {
    -			xfs_trans_cancel(tp, 0);
    -			goto error0;
    -		}
    -
    -		xfs_ilock(ip, XFS_ILOCK_EXCL);
    -		xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
    -		xfs_trans_ihold(tp, ip);
    -
    -		/*
    -		 * Modify the unwritten extent state of the buffer.
    -		 */
    -		XFS_BMAP_INIT(&free_list, &firstfsb);
    -		nimaps = 1;
    -		error = XFS_BMAPI(mp, tp, io, offset_fsb, count_fsb,
    -				  XFS_BMAPI_WRITE|XFS_BMAPI_CONVERT, &firstfsb,
    -				  1, &imap, &nimaps, &free_list, NULL);
    -		if (error)
    -			goto error_on_bmapi_transaction;
    -
    -		error = xfs_bmap_finish(&(tp), &(free_list),
    -				firstfsb, &committed);
    -		if (error)
    -			goto error_on_bmapi_transaction;
    -
    -		error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
    -		xfs_iunlock(ip, XFS_ILOCK_EXCL);
    -		if (error)
    -			goto error0;
    -
    -		if ( !(io->io_flags & XFS_IOCORE_RT)  && !imap.br_startblock) {
    -			cmn_err(CE_PANIC,"Access to block zero:  fs <%s> "
    -				"inode: %lld start_block : %llx start_off : "
    -				"%llx blkcnt : %llx extent-state : %x \n",
    -				(ip->i_mount)->m_fsname,
    -				(long long)ip->i_ino,
    -				(unsigned long long)imap.br_startblock,
    -				(unsigned long long)imap.br_startoff,
    -				(unsigned long long)imap.br_blockcount,
    -				imap.br_state);
    -        	}
    -
    -		if ((numblks_fsb = imap.br_blockcount) == 0) {
    -			/*
    -			 * The numblks_fsb value should always get
    -			 * smaller, otherwise the loop is stuck.
    -			 */
    -			ASSERT(imap.br_blockcount);
    -			break;
    -		}
    -		offset_fsb += numblks_fsb;
    -		count_fsb -= numblks_fsb;
    -	} while (count_fsb > 0);
    -
    -	return 0;
    -
    -error_on_bmapi_transaction:
    -	xfs_bmap_cancel(&free_list);
    -	xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT));
    -	xfs_iunlock(ip, XFS_ILOCK_EXCL);
    -error0:
    -	return XFS_ERROR(error);
    -}
    diff --git a/sys/gnu/fs/xfs/xfs_iomap.h b/sys/gnu/fs/xfs/xfs_iomap.h
    deleted file mode 100644
    index 3ce204a524b..00000000000
    --- a/sys/gnu/fs/xfs/xfs_iomap.h
    +++ /dev/null
    @@ -1,90 +0,0 @@
    -/*
    - * Copyright (c) 2003-2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_IOMAP_H__
    -#define __XFS_IOMAP_H__
    -
    -#define IOMAP_DADDR_NULL ((xfs_daddr_t) (-1LL))
    -
    -
    -typedef enum {				/* iomap_flags values */
    -	IOMAP_EOF =		0x01,	/* mapping contains EOF   */
    -	IOMAP_HOLE =		0x02,	/* mapping covers a hole  */
    -	IOMAP_DELAY =		0x04,	/* mapping covers delalloc region  */
    -	IOMAP_REALTIME =	0x10,	/* mapping on the realtime device  */
    -	IOMAP_UNWRITTEN =	0x20,	/* mapping covers allocated */
    -					/* but uninitialized file data  */
    -	IOMAP_NEW =		0x40	/* just allocate */
    -} iomap_flags_t;
    -
    -typedef enum {
    -	/* base extent manipulation calls */
    -	BMAPI_READ = (1 << 0),		/* read extents */
    -	BMAPI_WRITE = (1 << 1),		/* create extents */
    -	BMAPI_ALLOCATE = (1 << 2),	/* delayed allocate to real extents */
    -	BMAPI_UNWRITTEN  = (1 << 3),	/* unwritten extents to real extents */
    -	/* modifiers */
    -	BMAPI_IGNSTATE = (1 << 4),	/* ignore unwritten state on read */
    -	BMAPI_DIRECT = (1 << 5),	/* direct instead of buffered write */
    -	BMAPI_MMAP = (1 << 6),		/* allocate for mmap write */
    -	BMAPI_SYNC = (1 << 7),		/* sync write to flush delalloc space */
    -	BMAPI_TRYLOCK = (1 << 8),	/* non-blocking request */
    -	BMAPI_DEVICE = (1 << 9),	/* we only want to know the device */
    -} bmapi_flags_t;
    -
    -
    -/*
    - * xfs_iomap_t:  File system I/O map
    - *
    - * The iomap_bn field is expressed in 512-byte blocks, and is where the
    - * mapping starts on disk.
    - *
    - * The iomap_offset, iomap_bsize and iomap_delta fields are in bytes.
    - * iomap_offset is the offset of the mapping in the file itself.
    - * iomap_bsize is the size of the mapping,  iomap_delta is the
    - * desired data's offset into the mapping, given the offset supplied
    - * to the file I/O map routine.
    - *
    - * When a request is made to read beyond the logical end of the object,
    - * iomap_size may be set to 0, but iomap_offset and iomap_length should be set
    - * to the actual amount of underlying storage that has been allocated, if any.
    - */
    -
    -typedef struct xfs_iomap {
    -	xfs_daddr_t		iomap_bn;	/* first 512b blk of mapping */
    -	xfs_buftarg_t		*iomap_target;
    -	xfs_off_t		iomap_offset;	/* offset of mapping, bytes */
    -	xfs_off_t		iomap_bsize;	/* size of mapping, bytes */
    -	xfs_off_t		iomap_delta;	/* offset into mapping, bytes */
    -	iomap_flags_t		iomap_flags;
    -} xfs_iomap_t;
    -
    -struct xfs_iocore;
    -struct xfs_inode;
    -struct xfs_bmbt_irec;
    -
    -extern int xfs_iomap(struct xfs_iocore *, xfs_off_t, ssize_t, int,
    -		     struct xfs_iomap *, int *);
    -extern int xfs_iomap_write_direct(struct xfs_inode *, xfs_off_t, size_t,
    -				  int, struct xfs_bmbt_irec *, int *, int);
    -extern int xfs_iomap_write_delay(struct xfs_inode *, xfs_off_t, size_t, int,
    -				 struct xfs_bmbt_irec *, int *);
    -extern int xfs_iomap_write_allocate(struct xfs_inode *, xfs_off_t, size_t,
    -				struct xfs_bmbt_irec *, int *);
    -extern int xfs_iomap_write_unwritten(struct xfs_inode *, xfs_off_t, size_t);
    -
    -#endif /* __XFS_IOMAP_H__*/
    diff --git a/sys/gnu/fs/xfs/xfs_itable.c b/sys/gnu/fs/xfs/xfs_itable.c
    deleted file mode 100644
    index b8f9f6f5f1c..00000000000
    --- a/sys/gnu/fs/xfs/xfs_itable.c
    +++ /dev/null
    @@ -1,848 +0,0 @@
    -/*
    - * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_ialloc.h"
    -#include "xfs_itable.h"
    -#include "xfs_error.h"
    -#include "xfs_btree.h"
    -
    -#ifndef HAVE_USERACC
    -#define useracc(ubuffer, size, flags, foo) (0)
    -#define unuseracc(ubuffer, size, flags)
    -#endif
    -
    -STATIC int
    -xfs_bulkstat_one_iget(
    -	xfs_mount_t	*mp,		/* mount point for filesystem */
    -	xfs_ino_t	ino,		/* inode number to get data for */
    -	xfs_daddr_t	bno,		/* starting bno of inode cluster */
    -	xfs_bstat_t	*buf,		/* return buffer */
    -	int		*stat)		/* BULKSTAT_RV_... */
    -{
    -	xfs_dinode_core_t *dic;		/* dinode core info pointer */
    -	xfs_inode_t	*ip;		/* incore inode pointer */
    -	xfs_vnode_t	*vp;
    -	int		error;
    -
    -	error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, bno);
    -	if (error) {
    -		*stat = BULKSTAT_RV_NOTHING;
    -		return error;
    -	}
    -
    -	ASSERT(ip != NULL);
    -	ASSERT(ip->i_blkno != (xfs_daddr_t)0);
    -	if (ip->i_d.di_mode == 0) {
    -		*stat = BULKSTAT_RV_NOTHING;
    -		error = XFS_ERROR(ENOENT);
    -		goto out_iput;
    -	}
    -
    -	vp = XFS_ITOV(ip);
    -	dic = &ip->i_d;
    -
    -	/* xfs_iget returns the following without needing
    -	 * further change.
    -	 */
    -	buf->bs_nlink = dic->di_nlink;
    -	buf->bs_projid = dic->di_projid;
    -	buf->bs_ino = ino;
    -	buf->bs_mode = dic->di_mode;
    -	buf->bs_uid = dic->di_uid;
    -	buf->bs_gid = dic->di_gid;
    -	buf->bs_size = dic->di_size;
    -	vn_atime_to_bstime(vp, &buf->bs_atime);
    -	buf->bs_mtime.tv_sec = dic->di_mtime.t_sec;
    -	buf->bs_mtime.tv_nsec = dic->di_mtime.t_nsec;
    -	buf->bs_ctime.tv_sec = dic->di_ctime.t_sec;
    -	buf->bs_ctime.tv_nsec = dic->di_ctime.t_nsec;
    -	buf->bs_xflags = xfs_ip2xflags(ip);
    -	buf->bs_extsize = dic->di_extsize << mp->m_sb.sb_blocklog;
    -	buf->bs_extents = dic->di_nextents;
    -	buf->bs_gen = dic->di_gen;
    -	memset(buf->bs_pad, 0, sizeof(buf->bs_pad));
    -	buf->bs_dmevmask = dic->di_dmevmask;
    -	buf->bs_dmstate = dic->di_dmstate;
    -	buf->bs_aextents = dic->di_anextents;
    -
    -	switch (dic->di_format) {
    -	case XFS_DINODE_FMT_DEV:
    -		buf->bs_rdev = ip->i_df.if_u2.if_rdev;
    -		buf->bs_blksize = BLKDEV_IOSIZE;
    -		buf->bs_blocks = 0;
    -		break;
    -	case XFS_DINODE_FMT_LOCAL:
    -	case XFS_DINODE_FMT_UUID:
    -		buf->bs_rdev = 0;
    -		buf->bs_blksize = mp->m_sb.sb_blocksize;
    -		buf->bs_blocks = 0;
    -		break;
    -	case XFS_DINODE_FMT_EXTENTS:
    -	case XFS_DINODE_FMT_BTREE:
    -		buf->bs_rdev = 0;
    -		buf->bs_blksize = mp->m_sb.sb_blocksize;
    -		buf->bs_blocks = dic->di_nblocks + ip->i_delayed_blks;
    -		break;
    -	}
    -
    - out_iput:
    -	xfs_iput(ip, XFS_ILOCK_SHARED);
    -	return error;
    -}
    -
    -STATIC int
    -xfs_bulkstat_one_dinode(
    -	xfs_mount_t	*mp,		/* mount point for filesystem */
    -	xfs_ino_t	ino,		/* inode number to get data for */
    -	xfs_dinode_t	*dip,		/* dinode inode pointer */
    -	xfs_bstat_t	*buf)		/* return buffer */
    -{
    -	xfs_dinode_core_t *dic;		/* dinode core info pointer */
    -
    -	dic = &dip->di_core;
    -
    -	/*
    -	 * The inode format changed when we moved the link count and
    -	 * made it 32 bits long.  If this is an old format inode,
    -	 * convert it in memory to look like a new one.  If it gets
    -	 * flushed to disk we will convert back before flushing or
    -	 * logging it.  We zero out the new projid field and the old link
    -	 * count field.  We'll handle clearing the pad field (the remains
    -	 * of the old uuid field) when we actually convert the inode to
    -	 * the new format. We don't change the version number so that we
    -	 * can distinguish this from a real new format inode.
    -	 */
    -	if (INT_GET(dic->di_version, ARCH_CONVERT) == XFS_DINODE_VERSION_1) {
    -		buf->bs_nlink = INT_GET(dic->di_onlink, ARCH_CONVERT);
    -		buf->bs_projid = 0;
    -	} else {
    -		buf->bs_nlink = INT_GET(dic->di_nlink, ARCH_CONVERT);
    -		buf->bs_projid = INT_GET(dic->di_projid, ARCH_CONVERT);
    -	}
    -
    -	buf->bs_ino = ino;
    -	buf->bs_mode = INT_GET(dic->di_mode, ARCH_CONVERT);
    -	buf->bs_uid = INT_GET(dic->di_uid, ARCH_CONVERT);
    -	buf->bs_gid = INT_GET(dic->di_gid, ARCH_CONVERT);
    -	buf->bs_size = INT_GET(dic->di_size, ARCH_CONVERT);
    -	buf->bs_atime.tv_sec = INT_GET(dic->di_atime.t_sec, ARCH_CONVERT);
    -	buf->bs_atime.tv_nsec = INT_GET(dic->di_atime.t_nsec, ARCH_CONVERT);
    -	buf->bs_mtime.tv_sec = INT_GET(dic->di_mtime.t_sec, ARCH_CONVERT);
    -	buf->bs_mtime.tv_nsec = INT_GET(dic->di_mtime.t_nsec, ARCH_CONVERT);
    -	buf->bs_ctime.tv_sec = INT_GET(dic->di_ctime.t_sec, ARCH_CONVERT);
    -	buf->bs_ctime.tv_nsec = INT_GET(dic->di_ctime.t_nsec, ARCH_CONVERT);
    -	buf->bs_xflags = xfs_dic2xflags(dic);
    -	buf->bs_extsize = INT_GET(dic->di_extsize, ARCH_CONVERT) << mp->m_sb.sb_blocklog;
    -	buf->bs_extents = INT_GET(dic->di_nextents, ARCH_CONVERT);
    -	buf->bs_gen = INT_GET(dic->di_gen, ARCH_CONVERT);
    -	memset(buf->bs_pad, 0, sizeof(buf->bs_pad));
    -	buf->bs_dmevmask = INT_GET(dic->di_dmevmask, ARCH_CONVERT);
    -	buf->bs_dmstate = INT_GET(dic->di_dmstate, ARCH_CONVERT);
    -	buf->bs_aextents = INT_GET(dic->di_anextents, ARCH_CONVERT);
    -
    -	switch (INT_GET(dic->di_format, ARCH_CONVERT)) {
    -	case XFS_DINODE_FMT_DEV:
    -		buf->bs_rdev = INT_GET(dip->di_u.di_dev, ARCH_CONVERT);
    -		buf->bs_blksize = BLKDEV_IOSIZE;
    -		buf->bs_blocks = 0;
    -		break;
    -	case XFS_DINODE_FMT_LOCAL:
    -	case XFS_DINODE_FMT_UUID:
    -		buf->bs_rdev = 0;
    -		buf->bs_blksize = mp->m_sb.sb_blocksize;
    -		buf->bs_blocks = 0;
    -		break;
    -	case XFS_DINODE_FMT_EXTENTS:
    -	case XFS_DINODE_FMT_BTREE:
    -		buf->bs_rdev = 0;
    -		buf->bs_blksize = mp->m_sb.sb_blocksize;
    -		buf->bs_blocks = INT_GET(dic->di_nblocks, ARCH_CONVERT);
    -		break;
    -	}
    -
    -	return 0;
    -}
    -
    -/*
    - * Return stat information for one inode.
    - * Return 0 if ok, else errno.
    - */
    -int		       		/* error status */
    -xfs_bulkstat_one(
    -	xfs_mount_t	*mp,		/* mount point for filesystem */
    -	xfs_ino_t	ino,		/* inode number to get data for */
    -	void		__user *buffer,	/* buffer to place output in */
    -	int		ubsize,		/* size of buffer */
    -	void		*private_data,	/* my private data */
    -	xfs_daddr_t	bno,		/* starting bno of inode cluster */
    -	int		*ubused,	/* bytes used by me */
    -	void		*dibuff,	/* on-disk inode buffer */
    -	int		*stat)		/* BULKSTAT_RV_... */
    -{
    -	xfs_bstat_t	*buf;		/* return buffer */
    -	int		error = 0;	/* error value */
    -	xfs_dinode_t	*dip;		/* dinode inode pointer */
    -
    -	dip = (xfs_dinode_t *)dibuff;
    -
    -	if (!buffer || ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino ||
    -	    (XFS_SB_VERSION_HASQUOTA(&mp->m_sb) &&
    -	     (ino == mp->m_sb.sb_uquotino || ino == mp->m_sb.sb_gquotino))) {
    -		*stat = BULKSTAT_RV_NOTHING;
    -		return XFS_ERROR(EINVAL);
    -	}
    -	if (ubsize < sizeof(*buf)) {
    -		*stat = BULKSTAT_RV_NOTHING;
    -		return XFS_ERROR(ENOMEM);
    -	}
    -
    -	buf = kmem_alloc(sizeof(*buf), KM_SLEEP);
    -
    -	if (dip == NULL) {
    -		/* We're not being passed a pointer to a dinode.  This happens
    -		 * if BULKSTAT_FG_IGET is selected.  Do the iget.
    -		 */
    -		error = xfs_bulkstat_one_iget(mp, ino, bno, buf, stat);
    -		if (error)
    -			goto out_free;
    -	} else {
    -		xfs_bulkstat_one_dinode(mp, ino, dip, buf);
    -	}
    -
    -	if (copy_to_user(buffer, buf, sizeof(*buf)))  {
    -		*stat = BULKSTAT_RV_NOTHING;
    -		error =  EFAULT;
    -		goto out_free;
    -	}
    -
    -	*stat = BULKSTAT_RV_DIDONE;
    -	if (ubused)
    -		*ubused = sizeof(*buf);
    -
    - out_free:
    -	kmem_free(buf, sizeof(*buf));
    -	return error;
    -}
    -
    -/*
    - * Return stat information in bulk (by-inode) for the filesystem.
    - */
    -int					/* error status */
    -xfs_bulkstat(
    -	xfs_mount_t		*mp,	/* mount point for filesystem */
    -	xfs_ino_t		*lastinop, /* last inode returned */
    -	int			*ubcountp, /* size of buffer/count returned */
    -	bulkstat_one_pf		formatter, /* func that'd fill a single buf */
    -	void			*private_data,/* private data for formatter */
    -	size_t			statstruct_size, /* sizeof struct filling */
    -	char			__user *ubuffer, /* buffer with inode stats */
    -	int			flags,	/* defined in xfs_itable.h */
    -	int			*done)	/* 1 if there are more stats to get */
    -{
    -	xfs_agblock_t		agbno=0;/* allocation group block number */
    -	xfs_buf_t		*agbp;	/* agi header buffer */
    -	xfs_agi_t		*agi;	/* agi header data */
    -	xfs_agino_t		agino;	/* inode # in allocation group */
    -	xfs_agnumber_t		agno;	/* allocation group number */
    -	xfs_daddr_t		bno;	/* inode cluster start daddr */
    -	int			chunkidx; /* current index into inode chunk */
    -	int			clustidx; /* current index into inode cluster */
    -	xfs_btree_cur_t		*cur;	/* btree cursor for ialloc btree */
    -	int			end_of_ag; /* set if we've seen the ag end */
    -	int			error;	/* error code */
    -	int                     fmterror;/* bulkstat formatter result */
    -	__int32_t		gcnt;	/* current btree rec's count */
    -	xfs_inofree_t		gfree;	/* current btree rec's free mask */
    -	xfs_agino_t		gino;	/* current btree rec's start inode */
    -	int			i;	/* loop index */
    -	int			icount;	/* count of inodes good in irbuf */
    -	xfs_ino_t		ino;	/* inode number (filesystem) */
    -	xfs_inobt_rec_t		*irbp;	/* current irec buffer pointer */
    -	xfs_inobt_rec_t		*irbuf;	/* start of irec buffer */
    -	xfs_inobt_rec_t		*irbufend; /* end of good irec buffer entries */
    -	xfs_ino_t		lastino=0; /* last inode number returned */
    -	int			nbcluster; /* # of blocks in a cluster */
    -	int			nicluster; /* # of inodes in a cluster */
    -	int			nimask;	/* mask for inode clusters */
    -	int			nirbuf;	/* size of irbuf */
    -	int			rval;	/* return value error code */
    -	int			tmp;	/* result value from btree calls */
    -	int			ubcount; /* size of user's buffer */
    -	int			ubleft;	/* bytes left in user's buffer */
    -	char			__user *ubufp;	/* pointer into user's buffer */
    -	int			ubelem;	/* spaces used in user's buffer */
    -	int			ubused;	/* bytes used by formatter */
    -	xfs_buf_t		*bp;	/* ptr to on-disk inode cluster buf */
    -	xfs_dinode_t		*dip;	/* ptr into bp for specific inode */
    -	xfs_inode_t		*ip;	/* ptr to in-core inode struct */
    -
    -	/*
    -	 * Get the last inode value, see if there's nothing to do.
    -	 */
    -	ino = (xfs_ino_t)*lastinop;
    -	dip = NULL;
    -	agno = XFS_INO_TO_AGNO(mp, ino);
    -	agino = XFS_INO_TO_AGINO(mp, ino);
    -	if (agno >= mp->m_sb.sb_agcount ||
    -	    ino != XFS_AGINO_TO_INO(mp, agno, agino)) {
    -		*done = 1;
    -		*ubcountp = 0;
    -		return 0;
    -	}
    -	ubcount = *ubcountp; /* statstruct's */
    -	ubleft = ubcount * statstruct_size; /* bytes */
    -	*ubcountp = ubelem = 0;
    -	*done = 0;
    -	fmterror = 0;
    -	ubufp = ubuffer;
    -	nicluster = mp->m_sb.sb_blocksize >= XFS_INODE_CLUSTER_SIZE(mp) ?
    -		mp->m_sb.sb_inopblock :
    -		(XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog);
    -	nimask = ~(nicluster - 1);
    -	nbcluster = nicluster >> mp->m_sb.sb_inopblog;
    -	/*
    -	 * Lock down the user's buffer. If a buffer was not sent, as in the case
    -	 * disk quota code calls here, we skip this.
    -	 */
    -	if (ubuffer &&
    -	    (error = useracc(ubuffer, ubcount * statstruct_size,
    -			(B_READ|B_PHYS), NULL))) {
    -		return error;
    -	}
    -	/*
    -	 * Allocate a page-sized buffer for inode btree records.
    -	 * We could try allocating something smaller, but for normal
    -	 * calls we'll always (potentially) need the whole page.
    -	 */
    -	irbuf = kmem_alloc(NBPC, KM_SLEEP);
    -	nirbuf = NBPC / sizeof(*irbuf);
    -	/*
    -	 * Loop over the allocation groups, starting from the last
    -	 * inode returned; 0 means start of the allocation group.
    -	 */
    -	rval = 0;
    -	while (ubleft >= statstruct_size && agno < mp->m_sb.sb_agcount) {
    -		bp = NULL;
    -		down_read(&mp->m_peraglock);
    -		error = xfs_ialloc_read_agi(mp, NULL, agno, &agbp);
    -		up_read(&mp->m_peraglock);
    -		if (error) {
    -			/*
    -			 * Skip this allocation group and go to the next one.
    -			 */
    -			agno++;
    -			agino = 0;
    -			continue;
    -		}
    -		agi = XFS_BUF_TO_AGI(agbp);
    -		/*
    -		 * Allocate and initialize a btree cursor for ialloc btree.
    -		 */
    -		cur = xfs_btree_init_cursor(mp, NULL, agbp, agno, XFS_BTNUM_INO,
    -			(xfs_inode_t *)0, 0);
    -		irbp = irbuf;
    -		irbufend = irbuf + nirbuf;
    -		end_of_ag = 0;
    -		/*
    -		 * If we're returning in the middle of an allocation group,
    -		 * we need to get the remainder of the chunk we're in.
    -		 */
    -		if (agino > 0) {
    -			/*
    -			 * Lookup the inode chunk that this inode lives in.
    -			 */
    -			error = xfs_inobt_lookup_le(cur, agino, 0, 0, &tmp);
    -			if (!error &&	/* no I/O error */
    -			    tmp &&	/* lookup succeeded */
    -					/* got the record, should always work */
    -			    !(error = xfs_inobt_get_rec(cur, &gino, &gcnt,
    -				    &gfree, &i)) &&
    -			    i == 1 &&
    -					/* this is the right chunk */
    -			    agino < gino + XFS_INODES_PER_CHUNK &&
    -					/* lastino was not last in chunk */
    -			    (chunkidx = agino - gino + 1) <
    -				    XFS_INODES_PER_CHUNK &&
    -					/* there are some left allocated */
    -			    XFS_INOBT_MASKN(chunkidx,
    -				    XFS_INODES_PER_CHUNK - chunkidx) & ~gfree) {
    -				/*
    -				 * Grab the chunk record.  Mark all the
    -				 * uninteresting inodes (because they're
    -				 * before our start point) free.
    -				 */
    -				for (i = 0; i < chunkidx; i++) {
    -					if (XFS_INOBT_MASK(i) & ~gfree)
    -						gcnt++;
    -				}
    -				gfree |= XFS_INOBT_MASKN(0, chunkidx);
    -				INT_SET(irbp->ir_startino, ARCH_CONVERT, gino);
    -				INT_SET(irbp->ir_freecount, ARCH_CONVERT, gcnt);
    -				INT_SET(irbp->ir_free, ARCH_CONVERT, gfree);
    -				irbp++;
    -				agino = gino + XFS_INODES_PER_CHUNK;
    -				icount = XFS_INODES_PER_CHUNK - gcnt;
    -			} else {
    -				/*
    -				 * If any of those tests failed, bump the
    -				 * inode number (just in case).
    -				 */
    -				agino++;
    -				icount = 0;
    -			}
    -			/*
    -			 * In any case, increment to the next record.
    -			 */
    -			if (!error)
    -				error = xfs_inobt_increment(cur, 0, &tmp);
    -		} else {
    -			/*
    -			 * Start of ag.  Lookup the first inode chunk.
    -			 */
    -			error = xfs_inobt_lookup_ge(cur, 0, 0, 0, &tmp);
    -			icount = 0;
    -		}
    -		/*
    -		 * Loop through inode btree records in this ag,
    -		 * until we run out of inodes or space in the buffer.
    -		 */
    -		while (irbp < irbufend && icount < ubcount) {
    -			/*
    -			 * Loop as long as we're unable to read the
    -			 * inode btree.
    -			 */
    -			while (error) {
    -				agino += XFS_INODES_PER_CHUNK;
    -				if (XFS_AGINO_TO_AGBNO(mp, agino) >=
    -						be32_to_cpu(agi->agi_length))
    -					break;
    -				error = xfs_inobt_lookup_ge(cur, agino, 0, 0,
    -							    &tmp);
    -			}
    -			/*
    -			 * If ran off the end of the ag either with an error,
    -			 * or the normal way, set end and stop collecting.
    -			 */
    -			if (error ||
    -			    (error = xfs_inobt_get_rec(cur, &gino, &gcnt,
    -				    &gfree, &i)) ||
    -			    i == 0) {
    -				end_of_ag = 1;
    -				break;
    -			}
    -			/*
    -			 * If this chunk has any allocated inodes, save it.
    -			 */
    -			if (gcnt < XFS_INODES_PER_CHUNK) {
    -				INT_SET(irbp->ir_startino, ARCH_CONVERT, gino);
    -				INT_SET(irbp->ir_freecount, ARCH_CONVERT, gcnt);
    -				INT_SET(irbp->ir_free, ARCH_CONVERT, gfree);
    -				irbp++;
    -				icount += XFS_INODES_PER_CHUNK - gcnt;
    -			}
    -			/*
    -			 * Set agino to after this chunk and bump the cursor.
    -			 */
    -			agino = gino + XFS_INODES_PER_CHUNK;
    -			error = xfs_inobt_increment(cur, 0, &tmp);
    -		}
    -		/*
    -		 * Drop the btree buffers and the agi buffer.
    -		 * We can't hold any of the locks these represent
    -		 * when calling iget.
    -		 */
    -		xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
    -		xfs_buf_relse(agbp);
    -		/*
    -		 * Now format all the good inodes into the user's buffer.
    -		 */
    -		irbufend = irbp;
    -		for (irbp = irbuf;
    -		     irbp < irbufend && ubleft >= statstruct_size; irbp++) {
    -			/*
    -			 * Read-ahead the next chunk's worth of inodes.
    -			 */
    -			if (&irbp[1] < irbufend) {
    -				/*
    -				 * Loop over all clusters in the next chunk.
    -				 * Do a readahead if there are any allocated
    -				 * inodes in that cluster.
    -				 */
    -				for (agbno = XFS_AGINO_TO_AGBNO(mp,
    -							INT_GET(irbp[1].ir_startino, ARCH_CONVERT)),
    -				     chunkidx = 0;
    -				     chunkidx < XFS_INODES_PER_CHUNK;
    -				     chunkidx += nicluster,
    -				     agbno += nbcluster) {
    -					if (XFS_INOBT_MASKN(chunkidx,
    -							    nicluster) &
    -					    ~(INT_GET(irbp[1].ir_free, ARCH_CONVERT)))
    -						xfs_btree_reada_bufs(mp, agno,
    -							agbno, nbcluster);
    -				}
    -			}
    -			/*
    -			 * Now process this chunk of inodes.
    -			 */
    -			for (agino = INT_GET(irbp->ir_startino, ARCH_CONVERT), chunkidx = 0, clustidx = 0;
    -			     ubleft > 0 &&
    -				INT_GET(irbp->ir_freecount, ARCH_CONVERT) < XFS_INODES_PER_CHUNK;
    -			     chunkidx++, clustidx++, agino++) {
    -				ASSERT(chunkidx < XFS_INODES_PER_CHUNK);
    -				/*
    -				 * Recompute agbno if this is the
    -				 * first inode of the cluster.
    -				 *
    -				 * Careful with clustidx.   There can be
    -				 * multple clusters per chunk, a single
    -				 * cluster per chunk or a cluster that has
    -				 * inodes represented from several different
    -				 * chunks (if blocksize is large).
    -				 *
    -				 * Because of this, the starting clustidx is
    -				 * initialized to zero in this loop but must
    -				 * later be reset after reading in the cluster
    -				 * buffer.
    -				 */
    -				if ((chunkidx & (nicluster - 1)) == 0) {
    -					agbno = XFS_AGINO_TO_AGBNO(mp,
    -							INT_GET(irbp->ir_startino, ARCH_CONVERT)) +
    -						((chunkidx & nimask) >>
    -						 mp->m_sb.sb_inopblog);
    -
    -					if (flags & BULKSTAT_FG_QUICK) {
    -						ino = XFS_AGINO_TO_INO(mp, agno,
    -								       agino);
    -						bno = XFS_AGB_TO_DADDR(mp, agno,
    -								       agbno);
    -
    -						/*
    -						 * Get the inode cluster buffer
    -						 */
    -						ASSERT(xfs_inode_zone != NULL);
    -						ip = kmem_zone_zalloc(xfs_inode_zone,
    -								      KM_SLEEP);
    -						ip->i_ino = ino;
    -						ip->i_mount = mp;
    -						if (bp)
    -							xfs_buf_relse(bp);
    -						error = xfs_itobp(mp, NULL, ip,
    -								&dip, &bp, bno,
    -								XFS_IMAP_BULKSTAT);
    -						if (!error)
    -							clustidx = ip->i_boffset / mp->m_sb.sb_inodesize;
    -						kmem_zone_free(xfs_inode_zone, ip);
    -						if (XFS_TEST_ERROR(error != 0,
    -								   mp, XFS_ERRTAG_BULKSTAT_READ_CHUNK,
    -								   XFS_RANDOM_BULKSTAT_READ_CHUNK)) {
    -							bp = NULL;
    -							ubleft = 0;
    -							rval = error;
    -							break;
    -						}
    -					}
    -				}
    -				/*
    -				 * Skip if this inode is free.
    -				 */
    -				if (XFS_INOBT_MASK(chunkidx) & INT_GET(irbp->ir_free, ARCH_CONVERT))
    -					continue;
    -				/*
    -				 * Count used inodes as free so we can tell
    -				 * when the chunk is used up.
    -				 */
    -				INT_MOD(irbp->ir_freecount, ARCH_CONVERT, +1);
    -				ino = XFS_AGINO_TO_INO(mp, agno, agino);
    -				bno = XFS_AGB_TO_DADDR(mp, agno, agbno);
    -				if (flags & BULKSTAT_FG_QUICK) {
    -					dip = (xfs_dinode_t *)xfs_buf_offset(bp,
    -					      (clustidx << mp->m_sb.sb_inodelog));
    -
    -					if (INT_GET(dip->di_core.di_magic, ARCH_CONVERT)
    -						    != XFS_DINODE_MAGIC
    -					    || !XFS_DINODE_GOOD_VERSION(
    -						    INT_GET(dip->di_core.di_version, ARCH_CONVERT)))
    -						continue;
    -				}
    -
    -				/*
    -				 * Get the inode and fill in a single buffer.
    -				 * BULKSTAT_FG_QUICK uses dip to fill it in.
    -				 * BULKSTAT_FG_IGET uses igets.
    -				 * See: xfs_bulkstat_one & xfs_dm_bulkstat_one.
    -				 * This is also used to count inodes/blks, etc
    -				 * in xfs_qm_quotacheck.
    -				 */
    -				ubused = statstruct_size;
    -				error = formatter(mp, ino, ubufp,
    -						ubleft, private_data,
    -						bno, &ubused, dip, &fmterror);
    -				if (fmterror == BULKSTAT_RV_NOTHING) {
    -					if (error == ENOMEM)
    -						ubleft = 0;
    -					continue;
    -				}
    -				if (fmterror == BULKSTAT_RV_GIVEUP) {
    -					ubleft = 0;
    -					ASSERT(error);
    -					rval = error;
    -					break;
    -				}
    -				if (ubufp)
    -					ubufp += ubused;
    -				ubleft -= ubused;
    -				ubelem++;
    -				lastino = ino;
    -			}
    -		}
    -
    -		if (bp)
    -			xfs_buf_relse(bp);
    -
    -		/*
    -		 * Set up for the next loop iteration.
    -		 */
    -		if (ubleft > 0) {
    -			if (end_of_ag) {
    -				agno++;
    -				agino = 0;
    -			} else
    -				agino = XFS_INO_TO_AGINO(mp, lastino);
    -		} else
    -			break;
    -	}
    -	/*
    -	 * Done, we're either out of filesystem or space to put the data.
    -	 */
    -	kmem_free(irbuf, NBPC);
    -	if (ubuffer)
    -		unuseracc(ubuffer, ubcount * statstruct_size, (B_READ|B_PHYS));
    -	*ubcountp = ubelem;
    -	if (agno >= mp->m_sb.sb_agcount) {
    -		/*
    -		 * If we ran out of filesystem, mark lastino as off
    -		 * the end of the filesystem, so the next call
    -		 * will return immediately.
    -		 */
    -		*lastinop = (xfs_ino_t)XFS_AGINO_TO_INO(mp, agno, 0);
    -		*done = 1;
    -	} else
    -		*lastinop = (xfs_ino_t)lastino;
    -
    -	return rval;
    -}
    -
    -/*
    - * Return stat information in bulk (by-inode) for the filesystem.
    - * Special case for non-sequential one inode bulkstat.
    - */
    -int					/* error status */
    -xfs_bulkstat_single(
    -	xfs_mount_t		*mp,	/* mount point for filesystem */
    -	xfs_ino_t		*lastinop, /* inode to return */
    -	char			__user *buffer, /* buffer with inode stats */
    -	int			*done)	/* 1 if there are more stats to get */
    -{
    -	int			count;	/* count value for bulkstat call */
    -	int			error;	/* return value */
    -	xfs_ino_t		ino;	/* filesystem inode number */
    -	int			res;	/* result from bs1 */
    -
    -	/*
    -	 * note that requesting valid inode numbers which are not allocated
    -	 * to inodes will most likely cause xfs_itobp to generate warning
    -	 * messages about bad magic numbers. This is ok. The fact that
    -	 * the inode isn't actually an inode is handled by the
    -	 * error check below. Done this way to make the usual case faster
    -	 * at the expense of the error case.
    -	 */
    -
    -	ino = (xfs_ino_t)*lastinop;
    -	error = xfs_bulkstat_one(mp, ino, buffer, sizeof(xfs_bstat_t),
    -				 NULL, 0, NULL, NULL, &res);
    -	if (error) {
    -		/*
    -		 * Special case way failed, do it the "long" way
    -		 * to see if that works.
    -		 */
    -		(*lastinop)--;
    -		count = 1;
    -		if (xfs_bulkstat(mp, lastinop, &count, xfs_bulkstat_one,
    -				NULL, sizeof(xfs_bstat_t), buffer,
    -				BULKSTAT_FG_IGET, done))
    -			return error;
    -		if (count == 0 || (xfs_ino_t)*lastinop != ino)
    -			return error == EFSCORRUPTED ?
    -				XFS_ERROR(EINVAL) : error;
    -		else
    -			return 0;
    -	}
    -	*done = 0;
    -	return 0;
    -}
    -
    -/*
    - * Return inode number table for the filesystem.
    - */
    -int					/* error status */
    -xfs_inumbers(
    -	xfs_mount_t	*mp,		/* mount point for filesystem */
    -	xfs_ino_t	*lastino,	/* last inode returned */
    -	int		*count,		/* size of buffer/count returned */
    -	xfs_inogrp_t	__user *ubuffer)/* buffer with inode descriptions */
    -{
    -	xfs_buf_t	*agbp;
    -	xfs_agino_t	agino;
    -	xfs_agnumber_t	agno;
    -	int		bcount;
    -	xfs_inogrp_t	*buffer;
    -	int		bufidx;
    -	xfs_btree_cur_t	*cur;
    -	int		error;
    -	__int32_t	gcnt;
    -	xfs_inofree_t	gfree;
    -	xfs_agino_t	gino;
    -	int		i;
    -	xfs_ino_t	ino;
    -	int		left;
    -	int		tmp;
    -
    -	ino = (xfs_ino_t)*lastino;
    -	agno = XFS_INO_TO_AGNO(mp, ino);
    -	agino = XFS_INO_TO_AGINO(mp, ino);
    -	left = *count;
    -	*count = 0;
    -	bcount = MIN(left, (int)(NBPP / sizeof(*buffer)));
    -	buffer = kmem_alloc(bcount * sizeof(*buffer), KM_SLEEP);
    -	error = bufidx = 0;
    -	cur = NULL;
    -	agbp = NULL;
    -	while (left > 0 && agno < mp->m_sb.sb_agcount) {
    -		if (agbp == NULL) {
    -			down_read(&mp->m_peraglock);
    -			error = xfs_ialloc_read_agi(mp, NULL, agno, &agbp);
    -			up_read(&mp->m_peraglock);
    -			if (error) {
    -				/*
    -				 * If we can't read the AGI of this ag,
    -				 * then just skip to the next one.
    -				 */
    -				ASSERT(cur == NULL);
    -				agbp = NULL;
    -				agno++;
    -				agino = 0;
    -				continue;
    -			}
    -			cur = xfs_btree_init_cursor(mp, NULL, agbp, agno,
    -				XFS_BTNUM_INO, (xfs_inode_t *)0, 0);
    -			error = xfs_inobt_lookup_ge(cur, agino, 0, 0, &tmp);
    -			if (error) {
    -				xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
    -				cur = NULL;
    -				xfs_buf_relse(agbp);
    -				agbp = NULL;
    -				/*
    -				 * Move up the last inode in the current
    -				 * chunk.  The lookup_ge will always get
    -				 * us the first inode in the next chunk.
    -				 */
    -				agino += XFS_INODES_PER_CHUNK - 1;
    -				continue;
    -			}
    -		}
    -		if ((error = xfs_inobt_get_rec(cur, &gino, &gcnt, &gfree,
    -			&i)) ||
    -		    i == 0) {
    -			xfs_buf_relse(agbp);
    -			agbp = NULL;
    -			xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
    -			cur = NULL;
    -			agno++;
    -			agino = 0;
    -			continue;
    -		}
    -		agino = gino + XFS_INODES_PER_CHUNK - 1;
    -		buffer[bufidx].xi_startino = XFS_AGINO_TO_INO(mp, agno, gino);
    -		buffer[bufidx].xi_alloccount = XFS_INODES_PER_CHUNK - gcnt;
    -		buffer[bufidx].xi_allocmask = ~gfree;
    -		bufidx++;
    -		left--;
    -		if (bufidx == bcount) {
    -			if (copy_to_user(ubuffer, buffer,
    -					bufidx * sizeof(*buffer))) {
    -				error = XFS_ERROR(EFAULT);
    -				break;
    -			}
    -			ubuffer += bufidx;
    -			*count += bufidx;
    -			bufidx = 0;
    -		}
    -		if (left) {
    -			error = xfs_inobt_increment(cur, 0, &tmp);
    -			if (error) {
    -				xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
    -				cur = NULL;
    -				xfs_buf_relse(agbp);
    -				agbp = NULL;
    -				/*
    -				 * The agino value has already been bumped.
    -				 * Just try to skip up to it.
    -				 */
    -				agino += XFS_INODES_PER_CHUNK;
    -				continue;
    -			}
    -		}
    -	}
    -	if (!error) {
    -		if (bufidx) {
    -			if (copy_to_user(ubuffer, buffer,
    -					bufidx * sizeof(*buffer)))
    -				error = XFS_ERROR(EFAULT);
    -			else
    -				*count += bufidx;
    -		}
    -		*lastino = XFS_AGINO_TO_INO(mp, agno, agino);
    -	}
    -	kmem_free(buffer, bcount * sizeof(*buffer));
    -	if (cur)
    -		xfs_btree_del_cursor(cur, (error ? XFS_BTREE_ERROR :
    -					   XFS_BTREE_NOERROR));
    -	if (agbp)
    -		xfs_buf_relse(agbp);
    -	return error;
    -}
    diff --git a/sys/gnu/fs/xfs/xfs_itable.h b/sys/gnu/fs/xfs/xfs_itable.h
    deleted file mode 100644
    index 11eb4e1b18c..00000000000
    --- a/sys/gnu/fs/xfs/xfs_itable.h
    +++ /dev/null
    @@ -1,91 +0,0 @@
    -/*
    - * Copyright (c) 2000-2001 Silicon Graphics, Inc.  All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_ITABLE_H__
    -#define	__XFS_ITABLE_H__
    -
    -/*
    - * xfs_bulkstat() is used to fill in xfs_bstat structures as well as dm_stat
    - * structures (by the dmi library). This is a pointer to a formatter function
    - * that will iget the inode and fill in the appropriate structure.
    - * see xfs_bulkstat_one() and xfs_dm_bulkstat_one() in dmapi_xfs.c
    - */
    -typedef int (*bulkstat_one_pf)(struct xfs_mount	*mp,
    -			       xfs_ino_t	ino,
    -			       void		__user *buffer,
    -			       int		ubsize,
    -			       void		*private_data,
    -			       xfs_daddr_t	bno,
    -			       int		*ubused,
    -			       void		*dip,
    -			       int		*stat);
    -
    -/*
    - * Values for stat return value.
    - */
    -#define	BULKSTAT_RV_NOTHING	0
    -#define	BULKSTAT_RV_DIDONE	1
    -#define	BULKSTAT_RV_GIVEUP	2
    -
    -/*
    - * Values for bulkstat flag argument.
    - */
    -#define	BULKSTAT_FG_IGET	0x1	/* Go through the buffer cache */
    -#define	BULKSTAT_FG_QUICK	0x2	/* No iget, walk the dinode cluster */
    -#define BULKSTAT_FG_VFSLOCKED	0x4	/* Already have vfs lock */
    -
    -/*
    - * Return stat information in bulk (by-inode) for the filesystem.
    - */
    -int					/* error status */
    -xfs_bulkstat(
    -	xfs_mount_t	*mp,		/* mount point for filesystem */
    -	xfs_ino_t	*lastino,	/* last inode returned */
    -	int		*count,		/* size of buffer/count returned */
    -	bulkstat_one_pf formatter,	/* func that'd fill a single buf */
    -	void		*private_data,	/* private data for formatter */
    -	size_t		statstruct_size,/* sizeof struct that we're filling */
    -	char		__user *ubuffer,/* buffer with inode stats */
    -	int		flags,		/* flag to control access method */
    -	int		*done);		/* 1 if there are more stats to get */
    -
    -int
    -xfs_bulkstat_single(
    -	xfs_mount_t		*mp,
    -	xfs_ino_t		*lastinop,
    -	char			__user *buffer,
    -	int			*done);
    -
    -int
    -xfs_bulkstat_one(
    -	xfs_mount_t		*mp,
    -	xfs_ino_t		ino,
    -	void			__user *buffer,
    -	int			ubsize,
    -	void			*private_data,
    -	xfs_daddr_t		bno,
    -	int			*ubused,
    -	void			*dibuff,
    -	int			*stat);
    -
    -int					/* error status */
    -xfs_inumbers(
    -	xfs_mount_t		*mp,	/* mount point for filesystem */
    -	xfs_ino_t		*last,	/* last inode returned */
    -	int			*count,	/* size of buffer/count returned */
    -	xfs_inogrp_t		__user *buffer);/* buffer with inode info */
    -
    -#endif	/* __XFS_ITABLE_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_log.c b/sys/gnu/fs/xfs/xfs_log.c
    deleted file mode 100644
    index 46c0d3dede3..00000000000
    --- a/sys/gnu/fs/xfs/xfs_log.c
    +++ /dev/null
    @@ -1,3708 +0,0 @@
    -/*
    - * Copyright (c) 2000-2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_error.h"
    -#include "xfs_log_priv.h"
    -#include "xfs_buf_item.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_log_recover.h"
    -#include "xfs_trans_priv.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_rw.h"
    -
    -
    -#define xlog_write_adv_cnt(ptr, len, off, bytes) \
    -	{ (ptr) += (bytes); \
    -	  (len) -= (bytes); \
    -	  (off) += (bytes);}
    -
    -/* Local miscellaneous function prototypes */
    -STATIC int	 xlog_bdstrat_cb(struct xfs_buf *);
    -STATIC int	 xlog_commit_record(xfs_mount_t *mp, xlog_ticket_t *ticket,
    -				    xlog_in_core_t **, xfs_lsn_t *);
    -STATIC xlog_t *  xlog_alloc_log(xfs_mount_t	*mp,
    -				xfs_buftarg_t	*log_target,
    -				xfs_daddr_t	blk_offset,
    -				int		num_bblks);
    -STATIC int	 xlog_space_left(xlog_t *log, int cycle, int bytes);
    -STATIC int	 xlog_sync(xlog_t *log, xlog_in_core_t *iclog);
    -STATIC void	 xlog_dealloc_log(xlog_t *log);
    -STATIC int	 xlog_write(xfs_mount_t *mp, xfs_log_iovec_t region[],
    -			    int nentries, xfs_log_ticket_t tic,
    -			    xfs_lsn_t *start_lsn,
    -			    xlog_in_core_t **commit_iclog,
    -			    uint flags);
    -
    -/* local state machine functions */
    -STATIC void xlog_state_done_syncing(xlog_in_core_t *iclog, int);
    -STATIC void xlog_state_do_callback(xlog_t *log,int aborted, xlog_in_core_t *iclog);
    -STATIC int  xlog_state_get_iclog_space(xlog_t		*log,
    -				       int		len,
    -				       xlog_in_core_t	**iclog,
    -				       xlog_ticket_t	*ticket,
    -				       int		*continued_write,
    -				       int		*logoffsetp);
    -STATIC void xlog_state_put_ticket(xlog_t	*log,
    -				  xlog_ticket_t *tic);
    -STATIC int  xlog_state_release_iclog(xlog_t		*log,
    -				     xlog_in_core_t	*iclog);
    -STATIC void xlog_state_switch_iclogs(xlog_t		*log,
    -				     xlog_in_core_t *iclog,
    -				     int		eventual_size);
    -STATIC int  xlog_state_sync(xlog_t			*log,
    -			    xfs_lsn_t 			lsn,
    -			    uint			flags,
    -			    int				*log_flushed);
    -STATIC int  xlog_state_sync_all(xlog_t *log, uint flags, int *log_flushed);
    -STATIC void xlog_state_want_sync(xlog_t	*log, xlog_in_core_t *iclog);
    -
    -/* local functions to manipulate grant head */
    -STATIC int  xlog_grant_log_space(xlog_t		*log,
    -				 xlog_ticket_t	*xtic);
    -STATIC void xlog_grant_push_ail(xfs_mount_t	*mp,
    -				int		need_bytes);
    -STATIC void xlog_regrant_reserve_log_space(xlog_t	 *log,
    -					   xlog_ticket_t *ticket);
    -STATIC int xlog_regrant_write_log_space(xlog_t		*log,
    -					 xlog_ticket_t  *ticket);
    -STATIC void xlog_ungrant_log_space(xlog_t	 *log,
    -				   xlog_ticket_t *ticket);
    -
    -
    -/* local ticket functions */
    -STATIC void		xlog_state_ticket_alloc(xlog_t *log);
    -STATIC xlog_ticket_t	*xlog_ticket_get(xlog_t *log,
    -					 int	unit_bytes,
    -					 int	count,
    -					 char	clientid,
    -					 uint	flags);
    -STATIC void		xlog_ticket_put(xlog_t *log, xlog_ticket_t *ticket);
    -
    -#if defined(DEBUG)
    -STATIC void	xlog_verify_dest_ptr(xlog_t *log, __psint_t ptr);
    -STATIC void	xlog_verify_grant_head(xlog_t *log, int equals);
    -STATIC void	xlog_verify_iclog(xlog_t *log, xlog_in_core_t *iclog,
    -				  int count, boolean_t syncing);
    -STATIC void	xlog_verify_tail_lsn(xlog_t *log, xlog_in_core_t *iclog,
    -				     xfs_lsn_t tail_lsn);
    -#else
    -#define xlog_verify_dest_ptr(a,b)
    -#define xlog_verify_grant_head(a,b)
    -#define xlog_verify_iclog(a,b,c,d)
    -#define xlog_verify_tail_lsn(a,b,c)
    -#endif
    -
    -STATIC int	xlog_iclogs_empty(xlog_t *log);
    -
    -#if defined(XFS_LOG_TRACE)
    -void
    -xlog_trace_loggrant(xlog_t *log, xlog_ticket_t *tic, xfs_caddr_t string)
    -{
    -	unsigned long cnts;
    -
    -	if (!log->l_grant_trace) {
    -		log->l_grant_trace = ktrace_alloc(2048, KM_NOSLEEP);
    -		if (!log->l_grant_trace)
    -			return;
    -	}
    -	/* ticket counts are 1 byte each */
    -	cnts = ((unsigned long)tic->t_ocnt) | ((unsigned long)tic->t_cnt) << 8;
    -
    -	ktrace_enter(log->l_grant_trace,
    -		     (void *)tic,
    -		     (void *)log->l_reserve_headq,
    -		     (void *)log->l_write_headq,
    -		     (void *)((unsigned long)log->l_grant_reserve_cycle),
    -		     (void *)((unsigned long)log->l_grant_reserve_bytes),
    -		     (void *)((unsigned long)log->l_grant_write_cycle),
    -		     (void *)((unsigned long)log->l_grant_write_bytes),
    -		     (void *)((unsigned long)log->l_curr_cycle),
    -		     (void *)((unsigned long)log->l_curr_block),
    -		     (void *)((unsigned long)CYCLE_LSN(log->l_tail_lsn)),
    -		     (void *)((unsigned long)BLOCK_LSN(log->l_tail_lsn)),
    -		     (void *)string,
    -		     (void *)((unsigned long)tic->t_trans_type),
    -		     (void *)cnts,
    -		     (void *)((unsigned long)tic->t_curr_res),
    -		     (void *)((unsigned long)tic->t_unit_res));
    -}
    -
    -void
    -xlog_trace_iclog(xlog_in_core_t *iclog, uint state)
    -{
    -	if (!iclog->ic_trace)
    -		iclog->ic_trace = ktrace_alloc(256, KM_SLEEP);
    -	ktrace_enter(iclog->ic_trace,
    -		     (void *)((unsigned long)state),
    -		     (void *)((unsigned long)current_pid()),
    -		     (void *)NULL, (void *)NULL, (void *)NULL, (void *)NULL,
    -		     (void *)NULL, (void *)NULL, (void *)NULL, (void *)NULL,
    -		     (void *)NULL, (void *)NULL, (void *)NULL, (void *)NULL,
    -		     (void *)NULL, (void *)NULL);
    -}
    -#else
    -#define	xlog_trace_loggrant(log,tic,string)
    -#define	xlog_trace_iclog(iclog,state)
    -#endif /* XFS_LOG_TRACE */
    -
    -
    -static void
    -xlog_ins_ticketq(struct xlog_ticket **qp, struct xlog_ticket *tic)
    -{
    -	if (*qp) {
    -		tic->t_next	    = (*qp);
    -		tic->t_prev	    = (*qp)->t_prev;
    -		(*qp)->t_prev->t_next = tic;
    -		(*qp)->t_prev	    = tic;
    -	} else {
    -		tic->t_prev = tic->t_next = tic;
    -		*qp = tic;
    -	}
    -
    -	tic->t_flags |= XLOG_TIC_IN_Q;
    -}
    -
    -static void
    -xlog_del_ticketq(struct xlog_ticket **qp, struct xlog_ticket *tic)
    -{
    -	if (tic == tic->t_next) {
    -		*qp = NULL;
    -	} else {
    -		*qp = tic->t_next;
    -		tic->t_next->t_prev = tic->t_prev;
    -		tic->t_prev->t_next = tic->t_next;
    -	}
    -
    -	tic->t_next = tic->t_prev = NULL;
    -	tic->t_flags &= ~XLOG_TIC_IN_Q;
    -}
    -
    -static void
    -xlog_grant_sub_space(struct log *log, int bytes)
    -{
    -	log->l_grant_write_bytes -= bytes;
    -	if (log->l_grant_write_bytes < 0) {
    -		log->l_grant_write_bytes += log->l_logsize;
    -		log->l_grant_write_cycle--;
    -	}
    -
    -	log->l_grant_reserve_bytes -= bytes;
    -	if ((log)->l_grant_reserve_bytes < 0) {
    -		log->l_grant_reserve_bytes += log->l_logsize;
    -		log->l_grant_reserve_cycle--;
    -	}
    -
    -}
    -
    -static void
    -xlog_grant_add_space_write(struct log *log, int bytes)
    -{
    -	log->l_grant_write_bytes += bytes;
    -	if (log->l_grant_write_bytes > log->l_logsize) {
    -		log->l_grant_write_bytes -= log->l_logsize;
    -		log->l_grant_write_cycle++;
    -	}
    -}
    -
    -static void
    -xlog_grant_add_space_reserve(struct log *log, int bytes)
    -{
    -	log->l_grant_reserve_bytes += bytes;
    -	if (log->l_grant_reserve_bytes > log->l_logsize) {
    -		log->l_grant_reserve_bytes -= log->l_logsize;
    -		log->l_grant_reserve_cycle++;
    -	}
    -}
    -
    -static inline void
    -xlog_grant_add_space(struct log *log, int bytes)
    -{
    -	xlog_grant_add_space_write(log, bytes);
    -	xlog_grant_add_space_reserve(log, bytes);
    -}
    -
    -
    -/*
    - * NOTES:
    - *
    - *	1. currblock field gets updated at startup and after in-core logs
    - *		marked as with WANT_SYNC.
    - */
    -
    -/*
    - * This routine is called when a user of a log manager ticket is done with
    - * the reservation.  If the ticket was ever used, then a commit record for
    - * the associated transaction is written out as a log operation header with
    - * no data.  The flag XLOG_TIC_INITED is set when the first write occurs with
    - * a given ticket.  If the ticket was one with a permanent reservation, then
    - * a few operations are done differently.  Permanent reservation tickets by
    - * default don't release the reservation.  They just commit the current
    - * transaction with the belief that the reservation is still needed.  A flag
    - * must be passed in before permanent reservations are actually released.
    - * When these type of tickets are not released, they need to be set into
    - * the inited state again.  By doing this, a start record will be written
    - * out when the next write occurs.
    - */
    -xfs_lsn_t
    -xfs_log_done(xfs_mount_t	*mp,
    -	     xfs_log_ticket_t	xtic,
    -	     void		**iclog,
    -	     uint		flags)
    -{
    -	xlog_t		*log    = mp->m_log;
    -	xlog_ticket_t	*ticket = (xfs_log_ticket_t) xtic;
    -	xfs_lsn_t	lsn	= 0;
    -
    -	if (XLOG_FORCED_SHUTDOWN(log) ||
    -	    /*
    -	     * If nothing was ever written, don't write out commit record.
    -	     * If we get an error, just continue and give back the log ticket.
    -	     */
    -	    (((ticket->t_flags & XLOG_TIC_INITED) == 0) &&
    -	     (xlog_commit_record(mp, ticket,
    -				 (xlog_in_core_t **)iclog, &lsn)))) {
    -		lsn = (xfs_lsn_t) -1;
    -		if (ticket->t_flags & XLOG_TIC_PERM_RESERV) {
    -			flags |= XFS_LOG_REL_PERM_RESERV;
    -		}
    -	}
    -
    -
    -	if ((ticket->t_flags & XLOG_TIC_PERM_RESERV) == 0 ||
    -	    (flags & XFS_LOG_REL_PERM_RESERV)) {
    -		/*
    -		 * Release ticket if not permanent reservation or a specific
    -		 * request has been made to release a permanent reservation.
    -		 */
    -		xlog_trace_loggrant(log, ticket, "xfs_log_done: (non-permanent)");
    -		xlog_ungrant_log_space(log, ticket);
    -		xlog_state_put_ticket(log, ticket);
    -	} else {
    -		xlog_trace_loggrant(log, ticket, "xfs_log_done: (permanent)");
    -		xlog_regrant_reserve_log_space(log, ticket);
    -	}
    -
    -	/* If this ticket was a permanent reservation and we aren't
    -	 * trying to release it, reset the inited flags; so next time
    -	 * we write, a start record will be written out.
    -	 */
    -	if ((ticket->t_flags & XLOG_TIC_PERM_RESERV) &&
    -	    (flags & XFS_LOG_REL_PERM_RESERV) == 0)
    -		ticket->t_flags |= XLOG_TIC_INITED;
    -
    -	return lsn;
    -}	/* xfs_log_done */
    -
    -
    -/*
    - * Force the in-core log to disk.  If flags == XFS_LOG_SYNC,
    - *	the force is done synchronously.
    - *
    - * Asynchronous forces are implemented by setting the WANT_SYNC
    - * bit in the appropriate in-core log and then returning.
    - *
    - * Synchronous forces are implemented with a semaphore.  All callers
    - * to force a given lsn to disk will wait on a semaphore attached to the
    - * specific in-core log.  When given in-core log finally completes its
    - * write to disk, that thread will wake up all threads waiting on the
    - * semaphore.
    - */
    -int
    -_xfs_log_force(
    -	xfs_mount_t	*mp,
    -	xfs_lsn_t	lsn,
    -	uint		flags,
    -	int		*log_flushed)
    -{
    -	xlog_t		*log = mp->m_log;
    -	int		dummy;
    -
    -	if (!log_flushed)
    -		log_flushed = &dummy;
    -
    -	ASSERT(flags & XFS_LOG_FORCE);
    -
    -	XFS_STATS_INC(xs_log_force);
    -
    -	if (log->l_flags & XLOG_IO_ERROR)
    -		return XFS_ERROR(EIO);
    -	if (lsn == 0)
    -		return xlog_state_sync_all(log, flags, log_flushed);
    -	else
    -		return xlog_state_sync(log, lsn, flags, log_flushed);
    -}	/* xfs_log_force */
    -
    -/*
    - * Attaches a new iclog I/O completion callback routine during
    - * transaction commit.  If the log is in error state, a non-zero
    - * return code is handed back and the caller is responsible for
    - * executing the callback at an appropriate time.
    - */
    -int
    -xfs_log_notify(xfs_mount_t	  *mp,		/* mount of partition */
    -	       void		  *iclog_hndl,	/* iclog to hang callback off */
    -	       xfs_log_callback_t *cb)
    -{
    -	xlog_t *log = mp->m_log;
    -	xlog_in_core_t	  *iclog = (xlog_in_core_t *)iclog_hndl;
    -	int	abortflg, spl;
    -
    -	cb->cb_next = NULL;
    -	spl = LOG_LOCK(log);
    -	abortflg = (iclog->ic_state & XLOG_STATE_IOERROR);
    -	if (!abortflg) {
    -		ASSERT_ALWAYS((iclog->ic_state == XLOG_STATE_ACTIVE) ||
    -			      (iclog->ic_state == XLOG_STATE_WANT_SYNC));
    -		cb->cb_next = NULL;
    -		*(iclog->ic_callback_tail) = cb;
    -		iclog->ic_callback_tail = &(cb->cb_next);
    -	}
    -	LOG_UNLOCK(log, spl);
    -	return abortflg;
    -}	/* xfs_log_notify */
    -
    -int
    -xfs_log_release_iclog(xfs_mount_t *mp,
    -		      void	  *iclog_hndl)
    -{
    -	xlog_t *log = mp->m_log;
    -	xlog_in_core_t	  *iclog = (xlog_in_core_t *)iclog_hndl;
    -
    -	if (xlog_state_release_iclog(log, iclog)) {
    -		xfs_force_shutdown(mp, XFS_LOG_IO_ERROR);
    -		return EIO;
    -	}
    -
    -	return 0;
    -}
    -
    -/*
    - *  1. Reserve an amount of on-disk log space and return a ticket corresponding
    - *	to the reservation.
    - *  2. Potentially, push buffers at tail of log to disk.
    - *
    - * Each reservation is going to reserve extra space for a log record header.
    - * When writes happen to the on-disk log, we don't subtract the length of the
    - * log record header from any reservation.  By wasting space in each
    - * reservation, we prevent over allocation problems.
    - */
    -int
    -xfs_log_reserve(xfs_mount_t	 *mp,
    -		int		 unit_bytes,
    -		int		 cnt,
    -		xfs_log_ticket_t *ticket,
    -		__uint8_t	 client,
    -		uint		 flags,
    -		uint		 t_type)
    -{
    -	xlog_t		*log = mp->m_log;
    -	xlog_ticket_t	*internal_ticket;
    -	int		retval = 0;
    -
    -	ASSERT(client == XFS_TRANSACTION || client == XFS_LOG);
    -	ASSERT((flags & XFS_LOG_NOSLEEP) == 0);
    -
    -	if (XLOG_FORCED_SHUTDOWN(log))
    -		return XFS_ERROR(EIO);
    -
    -	XFS_STATS_INC(xs_try_logspace);
    -
    -	if (*ticket != NULL) {
    -		ASSERT(flags & XFS_LOG_PERM_RESERV);
    -		internal_ticket = (xlog_ticket_t *)*ticket;
    -		xlog_trace_loggrant(log, internal_ticket, "xfs_log_reserve: existing ticket (permanent trans)");
    -		xlog_grant_push_ail(mp, internal_ticket->t_unit_res);
    -		retval = xlog_regrant_write_log_space(log, internal_ticket);
    -	} else {
    -		/* may sleep if need to allocate more tickets */
    -		internal_ticket = xlog_ticket_get(log, unit_bytes, cnt,
    -						  client, flags);
    -		internal_ticket->t_trans_type = t_type;
    -		*ticket = internal_ticket;
    -		xlog_trace_loggrant(log, internal_ticket, 
    -			(internal_ticket->t_flags & XLOG_TIC_PERM_RESERV) ?
    -			"xfs_log_reserve: create new ticket (permanent trans)" :
    -			"xfs_log_reserve: create new ticket");
    -		xlog_grant_push_ail(mp,
    -				    (internal_ticket->t_unit_res *
    -				     internal_ticket->t_cnt));
    -		retval = xlog_grant_log_space(log, internal_ticket);
    -	}
    -
    -	return retval;
    -}	/* xfs_log_reserve */
    -
    -
    -/*
    - * Mount a log filesystem
    - *
    - * mp		- ubiquitous xfs mount point structure
    - * log_target	- buftarg of on-disk log device
    - * blk_offset	- Start block # where block size is 512 bytes (BBSIZE)
    - * num_bblocks	- Number of BBSIZE blocks in on-disk log
    - *
    - * Return error or zero.
    - */
    -int
    -xfs_log_mount(xfs_mount_t	*mp,
    -	      xfs_buftarg_t	*log_target,
    -	      xfs_daddr_t	blk_offset,
    -	      int		num_bblks)
    -{
    -	if (!(mp->m_flags & XFS_MOUNT_NORECOVERY))
    -		cmn_err(CE_NOTE, "XFS mounting filesystem %s", mp->m_fsname);
    -	else {
    -		cmn_err(CE_NOTE,
    -			"!Mounting filesystem \"%s\" in no-recovery mode.  Filesystem will be inconsistent.",
    -			mp->m_fsname);
    -		ASSERT(XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY);
    -	}
    -
    -	mp->m_log = xlog_alloc_log(mp, log_target, blk_offset, num_bblks);
    -
    -	/*
    -	 * skip log recovery on a norecovery mount.  pretend it all
    -	 * just worked.
    -	 */
    -	if (!(mp->m_flags & XFS_MOUNT_NORECOVERY)) {
    -		int		error;
    -		xfs_vfs_t	*vfsp = XFS_MTOVFS(mp);
    -		int		readonly = (vfsp->vfs_flag & VFS_RDONLY);
    -
    -		if (readonly)
    -			vfsp->vfs_flag &= ~VFS_RDONLY;
    -
    -		error = xlog_recover(mp->m_log);
    -
    -		if (readonly)
    -			vfsp->vfs_flag |= VFS_RDONLY;
    -		if (error) {
    -			cmn_err(CE_WARN, "XFS: log mount/recovery failed: error %d", error);
    -			xlog_dealloc_log(mp->m_log);
    -			return error;
    -		}
    -	}
    -
    -	/* Normal transactions can now occur */
    -	mp->m_log->l_flags &= ~XLOG_ACTIVE_RECOVERY;
    -
    -	/* End mounting message in xfs_log_mount_finish */
    -	return 0;
    -}	/* xfs_log_mount */
    -
    -/*
    - * Finish the recovery of the file system.  This is separate from
    - * the xfs_log_mount() call, because it depends on the code in
    - * xfs_mountfs() to read in the root and real-time bitmap inodes
    - * between calling xfs_log_mount() and here.
    - *
    - * mp		- ubiquitous xfs mount point structure
    - */
    -int
    -xfs_log_mount_finish(xfs_mount_t *mp, int mfsi_flags)
    -{
    -	int	error;
    -
    -	if (!(mp->m_flags & XFS_MOUNT_NORECOVERY))
    -		error = xlog_recover_finish(mp->m_log, mfsi_flags);
    -	else {
    -		error = 0;
    -		ASSERT(XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY);
    -	}
    -
    -	return error;
    -}
    -
    -/*
    - * Unmount processing for the log.
    - */
    -int
    -xfs_log_unmount(xfs_mount_t *mp)
    -{
    -	int		error;
    -
    -	error = xfs_log_unmount_write(mp);
    -	xfs_log_unmount_dealloc(mp);
    -	return error;
    -}
    -
    -/*
    - * Final log writes as part of unmount.
    - *
    - * Mark the filesystem clean as unmount happens.  Note that during relocation
    - * this routine needs to be executed as part of source-bag while the
    - * deallocation must not be done until source-end.
    - */
    -
    -/*
    - * Unmount record used to have a string "Unmount filesystem--" in the
    - * data section where the "Un" was really a magic number (XLOG_UNMOUNT_TYPE).
    - * We just write the magic number now since that particular field isn't
    - * currently architecture converted and "nUmount" is a bit foo.
    - * As far as I know, there weren't any dependencies on the old behaviour.
    - */
    -
    -int
    -xfs_log_unmount_write(xfs_mount_t *mp)
    -{
    -	xlog_t		 *log = mp->m_log;
    -	xlog_in_core_t	 *iclog;
    -#ifdef DEBUG
    -	xlog_in_core_t	 *first_iclog;
    -#endif
    -	xfs_log_iovec_t  reg[1];
    -	xfs_log_ticket_t tic = NULL;
    -	xfs_lsn_t	 lsn;
    -	int		 error;
    -	SPLDECL(s);
    -
    -	/* the data section must be 32 bit size aligned */
    -	struct {
    -	    __uint16_t magic;
    -	    __uint16_t pad1;
    -	    __uint32_t pad2; /* may as well make it 64 bits */
    -	} magic = { XLOG_UNMOUNT_TYPE, 0, 0 };
    -
    -	/*
    -	 * Don't write out unmount record on read-only mounts.
    -	 * Or, if we are doing a forced umount (typically because of IO errors).
    -	 */
    -	if (XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY)
    -		return 0;
    -
    -	xfs_log_force(mp, 0, XFS_LOG_FORCE|XFS_LOG_SYNC);
    -
    -#ifdef DEBUG
    -	first_iclog = iclog = log->l_iclog;
    -	do {
    -		if (!(iclog->ic_state & XLOG_STATE_IOERROR)) {
    -			ASSERT(iclog->ic_state & XLOG_STATE_ACTIVE);
    -			ASSERT(iclog->ic_offset == 0);
    -		}
    -		iclog = iclog->ic_next;
    -	} while (iclog != first_iclog);
    -#endif
    -	if (! (XLOG_FORCED_SHUTDOWN(log))) {
    -		reg[0].i_addr = (void*)&magic;
    -		reg[0].i_len  = sizeof(magic);
    -		XLOG_VEC_SET_TYPE(®[0], XLOG_REG_TYPE_UNMOUNT);
    -
    -		error = xfs_log_reserve(mp, 600, 1, &tic, XFS_LOG, 0, 0);
    -		if (!error) {
    -			/* remove inited flag */
    -			((xlog_ticket_t *)tic)->t_flags = 0;
    -			error = xlog_write(mp, reg, 1, tic, &lsn,
    -					   NULL, XLOG_UNMOUNT_TRANS);
    -			/*
    -			 * At this point, we're umounting anyway,
    -			 * so there's no point in transitioning log state
    -			 * to IOERROR. Just continue...
    -			 */
    -		}
    -
    -		if (error) {
    -			xfs_fs_cmn_err(CE_ALERT, mp,
    -				"xfs_log_unmount: unmount record failed");
    -		}
    -
    -
    -		s = LOG_LOCK(log);
    -		iclog = log->l_iclog;
    -		iclog->ic_refcnt++;
    -		LOG_UNLOCK(log, s);
    -		xlog_state_want_sync(log, iclog);
    -		(void) xlog_state_release_iclog(log, iclog);
    -
    -		s = LOG_LOCK(log);
    -		if (!(iclog->ic_state == XLOG_STATE_ACTIVE ||
    -		      iclog->ic_state == XLOG_STATE_DIRTY)) {
    -			if (!XLOG_FORCED_SHUTDOWN(log)) {
    -				sv_wait(&iclog->ic_forcesema, PMEM,
    -					&log->l_icloglock, s);
    -			} else {
    -				LOG_UNLOCK(log, s);
    -			}
    -		} else {
    -			LOG_UNLOCK(log, s);
    -		}
    -		if (tic)
    -			xlog_state_put_ticket(log, tic);
    -	} else {
    -		/*
    -		 * We're already in forced_shutdown mode, couldn't
    -		 * even attempt to write out the unmount transaction.
    -		 *
    -		 * Go through the motions of sync'ing and releasing
    -		 * the iclog, even though no I/O will actually happen,
    -		 * we need to wait for other log I/Os that may already
    -		 * be in progress.  Do this as a separate section of
    -		 * code so we'll know if we ever get stuck here that
    -		 * we're in this odd situation of trying to unmount
    -		 * a file system that went into forced_shutdown as
    -		 * the result of an unmount..
    -		 */
    -		s = LOG_LOCK(log);
    -		iclog = log->l_iclog;
    -		iclog->ic_refcnt++;
    -		LOG_UNLOCK(log, s);
    -
    -		xlog_state_want_sync(log, iclog);
    -		(void) xlog_state_release_iclog(log, iclog);
    -
    -		s = LOG_LOCK(log);
    -
    -		if ( ! (   iclog->ic_state == XLOG_STATE_ACTIVE
    -			|| iclog->ic_state == XLOG_STATE_DIRTY
    -			|| iclog->ic_state == XLOG_STATE_IOERROR) ) {
    -
    -				sv_wait(&iclog->ic_forcesema, PMEM,
    -					&log->l_icloglock, s);
    -		} else {
    -			LOG_UNLOCK(log, s);
    -		}
    -	}
    -
    -	return 0;
    -}	/* xfs_log_unmount_write */
    -
    -/*
    - * Deallocate log structures for unmount/relocation.
    - */
    -void
    -xfs_log_unmount_dealloc(xfs_mount_t *mp)
    -{
    -	xlog_dealloc_log(mp->m_log);
    -}
    -
    -/*
    - * Write region vectors to log.  The write happens using the space reservation
    - * of the ticket (tic).  It is not a requirement that all writes for a given
    - * transaction occur with one call to xfs_log_write().
    - */
    -int
    -xfs_log_write(xfs_mount_t *	mp,
    -	      xfs_log_iovec_t	reg[],
    -	      int		nentries,
    -	      xfs_log_ticket_t	tic,
    -	      xfs_lsn_t		*start_lsn)
    -{
    -	int	error;
    -	xlog_t *log = mp->m_log;
    -
    -	if (XLOG_FORCED_SHUTDOWN(log))
    -		return XFS_ERROR(EIO);
    -
    -	if ((error = xlog_write(mp, reg, nentries, tic, start_lsn, NULL, 0))) {
    -		xfs_force_shutdown(mp, XFS_LOG_IO_ERROR);
    -	}
    -	return error;
    -}	/* xfs_log_write */
    -
    -
    -void
    -xfs_log_move_tail(xfs_mount_t	*mp,
    -		  xfs_lsn_t	tail_lsn)
    -{
    -	xlog_ticket_t	*tic;
    -	xlog_t		*log = mp->m_log;
    -	int		need_bytes, free_bytes, cycle, bytes;
    -	SPLDECL(s);
    -
    -	if (XLOG_FORCED_SHUTDOWN(log))
    -		return;
    -	ASSERT(!XFS_FORCED_SHUTDOWN(mp));
    -
    -	if (tail_lsn == 0) {
    -		/* needed since sync_lsn is 64 bits */
    -		s = LOG_LOCK(log);
    -		tail_lsn = log->l_last_sync_lsn;
    -		LOG_UNLOCK(log, s);
    -	}
    -
    -	s = GRANT_LOCK(log);
    -
    -	/* Also an invalid lsn.  1 implies that we aren't passing in a valid
    -	 * tail_lsn.
    -	 */
    -	if (tail_lsn != 1) {
    -		log->l_tail_lsn = tail_lsn;
    -	}
    -
    -	if ((tic = log->l_write_headq)) {
    -#ifdef DEBUG
    -		if (log->l_flags & XLOG_ACTIVE_RECOVERY)
    -			panic("Recovery problem");
    -#endif
    -		cycle = log->l_grant_write_cycle;
    -		bytes = log->l_grant_write_bytes;
    -		free_bytes = xlog_space_left(log, cycle, bytes);
    -		do {
    -			ASSERT(tic->t_flags & XLOG_TIC_PERM_RESERV);
    -
    -			if (free_bytes < tic->t_unit_res && tail_lsn != 1)
    -				break;
    -			tail_lsn = 0;
    -			free_bytes -= tic->t_unit_res;
    -			sv_signal(&tic->t_sema);
    -			tic = tic->t_next;
    -		} while (tic != log->l_write_headq);
    -	}
    -	if ((tic = log->l_reserve_headq)) {
    -#ifdef DEBUG
    -		if (log->l_flags & XLOG_ACTIVE_RECOVERY)
    -			panic("Recovery problem");
    -#endif
    -		cycle = log->l_grant_reserve_cycle;
    -		bytes = log->l_grant_reserve_bytes;
    -		free_bytes = xlog_space_left(log, cycle, bytes);
    -		do {
    -			if (tic->t_flags & XLOG_TIC_PERM_RESERV)
    -				need_bytes = tic->t_unit_res*tic->t_cnt;
    -			else
    -				need_bytes = tic->t_unit_res;
    -			if (free_bytes < need_bytes && tail_lsn != 1)
    -				break;
    -			tail_lsn = 0;
    -			free_bytes -= need_bytes;
    -			sv_signal(&tic->t_sema);
    -			tic = tic->t_next;
    -		} while (tic != log->l_reserve_headq);
    -	}
    -	GRANT_UNLOCK(log, s);
    -}	/* xfs_log_move_tail */
    -
    -/*
    - * Determine if we have a transaction that has gone to disk
    - * that needs to be covered. Log activity needs to be idle (no AIL and
    - * nothing in the iclogs). And, we need to be in the right state indicating
    - * something has gone out.
    - */
    -int
    -xfs_log_need_covered(xfs_mount_t *mp)
    -{
    -	SPLDECL(s);
    -	int		needed = 0, gen;
    -	xlog_t		*log = mp->m_log;
    -	xfs_vfs_t	*vfsp = XFS_MTOVFS(mp);
    -
    -	if (/* fs_frozen(vfsp) RMC */ 0 || XFS_FORCED_SHUTDOWN(mp) ||
    -	    (vfsp->vfs_flag & VFS_RDONLY))
    -		return 0;
    -
    -	s = LOG_LOCK(log);
    -	if (((log->l_covered_state == XLOG_STATE_COVER_NEED) ||
    -		(log->l_covered_state == XLOG_STATE_COVER_NEED2))
    -			&& !xfs_trans_first_ail(mp, &gen)
    -			&& xlog_iclogs_empty(log)) {
    -		if (log->l_covered_state == XLOG_STATE_COVER_NEED)
    -			log->l_covered_state = XLOG_STATE_COVER_DONE;
    -		else {
    -			ASSERT(log->l_covered_state == XLOG_STATE_COVER_NEED2);
    -			log->l_covered_state = XLOG_STATE_COVER_DONE2;
    -		}
    -		needed = 1;
    -	}
    -	LOG_UNLOCK(log, s);
    -	return needed;
    -}
    -
    -/******************************************************************************
    - *
    - *	local routines
    - *
    - ******************************************************************************
    - */
    -
    -/* xfs_trans_tail_ail returns 0 when there is nothing in the list.
    - * The log manager must keep track of the last LR which was committed
    - * to disk.  The lsn of this LR will become the new tail_lsn whenever
    - * xfs_trans_tail_ail returns 0.  If we don't do this, we run into
    - * the situation where stuff could be written into the log but nothing
    - * was ever in the AIL when asked.  Eventually, we panic since the
    - * tail hits the head.
    - *
    - * We may be holding the log iclog lock upon entering this routine.
    - */
    -xfs_lsn_t
    -xlog_assign_tail_lsn(xfs_mount_t *mp)
    -{
    -	xfs_lsn_t tail_lsn;
    -	SPLDECL(s);
    -	xlog_t	  *log = mp->m_log;
    -
    -	tail_lsn = xfs_trans_tail_ail(mp);
    -	s = GRANT_LOCK(log);
    -	if (tail_lsn != 0) {
    -		log->l_tail_lsn = tail_lsn;
    -	} else {
    -		tail_lsn = log->l_tail_lsn = log->l_last_sync_lsn;
    -	}
    -	GRANT_UNLOCK(log, s);
    -
    -	return tail_lsn;
    -}	/* xlog_assign_tail_lsn */
    -
    -
    -/*
    - * Return the space in the log between the tail and the head.  The head
    - * is passed in the cycle/bytes formal parms.  In the special case where
    - * the reserve head has wrapped passed the tail, this calculation is no
    - * longer valid.  In this case, just return 0 which means there is no space
    - * in the log.  This works for all places where this function is called
    - * with the reserve head.  Of course, if the write head were to ever
    - * wrap the tail, we should blow up.  Rather than catch this case here,
    - * we depend on other ASSERTions in other parts of the code.   XXXmiken
    - *
    - * This code also handles the case where the reservation head is behind
    - * the tail.  The details of this case are described below, but the end
    - * result is that we return the size of the log as the amount of space left.
    - */
    -int
    -xlog_space_left(xlog_t *log, int cycle, int bytes)
    -{
    -	int free_bytes;
    -	int tail_bytes;
    -	int tail_cycle;
    -
    -	tail_bytes = BBTOB(BLOCK_LSN(log->l_tail_lsn));
    -	tail_cycle = CYCLE_LSN(log->l_tail_lsn);
    -	if ((tail_cycle == cycle) && (bytes >= tail_bytes)) {
    -		free_bytes = log->l_logsize - (bytes - tail_bytes);
    -	} else if ((tail_cycle + 1) < cycle) {
    -		return 0;
    -	} else if (tail_cycle < cycle) {
    -		ASSERT(tail_cycle == (cycle - 1));
    -		free_bytes = tail_bytes - bytes;
    -	} else {
    -		/*
    -		 * The reservation head is behind the tail.
    -		 * In this case we just want to return the size of the
    -		 * log as the amount of space left.
    -		 */
    -		xfs_fs_cmn_err(CE_ALERT, log->l_mp,
    -			"xlog_space_left: head behind tail\n"
    -			"  tail_cycle = %d, tail_bytes = %d\n"
    -			"  GH   cycle = %d, GH   bytes = %d",
    -			tail_cycle, tail_bytes, cycle, bytes);
    -		ASSERT(0);
    -		free_bytes = log->l_logsize;
    -	}
    -	return free_bytes;
    -}	/* xlog_space_left */
    -
    -
    -/*
    - * Log function which is called when an io completes.
    - *
    - * The log manager needs its own routine, in order to control what
    - * happens with the buffer after the write completes.
    - */
    -void
    -xlog_iodone(xfs_buf_t *bp)
    -{
    -	xlog_in_core_t	*iclog;
    -	xlog_t		*l;
    -	int		aborted;
    -
    -	iclog = XFS_BUF_FSPRIVATE(bp, xlog_in_core_t *);
    -	ASSERT(XFS_BUF_FSPRIVATE2(bp, unsigned long) == (unsigned long) 2);
    -	XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)1);
    -	aborted = 0;
    -
    -	/*
    -	 * Some versions of cpp barf on the recursive definition of
    -	 * ic_log -> hic_fields.ic_log and expand ic_log twice when
    -	 * it is passed through two macros.  Workaround broken cpp.
    -	 */
    -	l = iclog->ic_log;
    -
    -	/*
    -	 * Race to shutdown the filesystem if we see an error.
    -	 */
    -	if (XFS_TEST_ERROR((XFS_BUF_GETERROR(bp)), l->l_mp,
    -			XFS_ERRTAG_IODONE_IOERR, XFS_RANDOM_IODONE_IOERR)) {
    -		xfs_ioerror_alert("xlog_iodone", l->l_mp, bp, XFS_BUF_ADDR(bp));
    -		XFS_BUF_STALE(bp);
    -		xfs_force_shutdown(l->l_mp, XFS_LOG_IO_ERROR);
    -		/*
    -		 * This flag will be propagated to the trans-committed
    -		 * callback routines to let them know that the log-commit
    -		 * didn't succeed.
    -		 */
    -		aborted = XFS_LI_ABORTED;
    -	} else if (iclog->ic_state & XLOG_STATE_IOERROR) {
    -		aborted = XFS_LI_ABORTED;
    -	}
    -	xlog_state_done_syncing(iclog, aborted);
    -	if (!(XFS_BUF_ISASYNC(bp))) {
    -		/*
    -		 * Corresponding psema() will be done in bwrite().  If we don't
    -		 * vsema() here, panic.
    -		 */
    -		XFS_BUF_V_IODONESEMA(bp);
    -	} else
    -		XFS_BUF_VSEMA(bp);
    -}	/* xlog_iodone */
    -
    -/*
    - * The bdstrat callback function for log bufs. This gives us a central
    - * place to trap bufs in case we get hit by a log I/O error and need to
    - * shutdown. Actually, in practice, even when we didn't get a log error,
    - * we transition the iclogs to IOERROR state *after* flushing all existing
    - * iclogs to disk. This is because we don't want anymore new transactions to be
    - * started or completed afterwards.
    - */
    -STATIC int
    -xlog_bdstrat_cb(struct xfs_buf *bp)
    -{
    -	xlog_in_core_t *iclog;
    -
    -	iclog = XFS_BUF_FSPRIVATE(bp, xlog_in_core_t *);
    -
    -	if ((iclog->ic_state & XLOG_STATE_IOERROR) == 0) {
    -	  /* note for irix bstrat will need  struct bdevsw passed
    -	   * Fix the following macro if the code ever is merged
    -	   */
    -	    XFS_bdstrat(bp);
    -		return 0;
    -	}
    -
    -	xfs_buftrace("XLOG__BDSTRAT IOERROR", bp);
    -	XFS_BUF_ERROR(bp, EIO);
    -	XFS_BUF_STALE(bp);
    -	xfs_biodone(bp);
    -	return XFS_ERROR(EIO);
    -
    -
    -}
    -
    -/*
    - * Return size of each in-core log record buffer.
    - *
    - * Low memory machines only get 2 16KB buffers.  We don't want to waste
    - * memory here.  However, all other machines get at least 2 32KB buffers.
    - * The number is hard coded because we don't care about the minimum
    - * memory size, just 32MB systems.
    - *
    - * If the filesystem blocksize is too large, we may need to choose a
    - * larger size since the directory code currently logs entire blocks.
    - */
    -
    -STATIC void
    -xlog_get_iclog_buffer_size(xfs_mount_t	*mp,
    -			   xlog_t	*log)
    -{
    -	int size;
    -	int xhdrs;
    -
    -	if (mp->m_logbufs <= 0) {
    -		if (xfs_physmem <= btoc(128*1024*1024)) {
    -			log->l_iclog_bufs = XLOG_MIN_ICLOGS;
    -		} else if (xfs_physmem <= btoc(400*1024*1024)) {
    -			log->l_iclog_bufs = XLOG_MED_ICLOGS;
    -		} else {	/* 256K with 32K bufs */
    -			log->l_iclog_bufs = XLOG_MAX_ICLOGS;
    -		}
    -	} else {
    -		log->l_iclog_bufs = mp->m_logbufs;
    -	}
    -
    -	/*
    -	 * Buffer size passed in from mount system call.
    -	 */
    -	if (mp->m_logbsize > 0) {
    -		size = log->l_iclog_size = mp->m_logbsize;
    -		log->l_iclog_size_log = 0;
    -		while (size != 1) {
    -			log->l_iclog_size_log++;
    -			size >>= 1;
    -		}
    -
    -		if (XFS_SB_VERSION_HASLOGV2(&mp->m_sb)) {
    -			/* # headers = size / 32K
    -			 * one header holds cycles from 32K of data
    -			 */
    -
    -			xhdrs = mp->m_logbsize / XLOG_HEADER_CYCLE_SIZE;
    -			if (mp->m_logbsize % XLOG_HEADER_CYCLE_SIZE)
    -				xhdrs++;
    -			log->l_iclog_hsize = xhdrs << BBSHIFT;
    -			log->l_iclog_heads = xhdrs;
    -		} else {
    -			ASSERT(mp->m_logbsize <= XLOG_BIG_RECORD_BSIZE);
    -			log->l_iclog_hsize = BBSIZE;
    -			log->l_iclog_heads = 1;
    -		}
    -		goto done;
    -	}
    -
    -	/*
    -	 * Special case machines that have less than 32MB of memory.
    -	 * All machines with more memory use 32KB buffers.
    -	 */
    -	if (xfs_physmem <= btoc(32*1024*1024)) {
    -		/* Don't change; min configuration */
    -		log->l_iclog_size = XLOG_RECORD_BSIZE;		/* 16k */
    -		log->l_iclog_size_log = XLOG_RECORD_BSHIFT;
    -	} else {
    -		log->l_iclog_size = XLOG_BIG_RECORD_BSIZE;	/* 32k */
    -		log->l_iclog_size_log = XLOG_BIG_RECORD_BSHIFT;
    -	}
    -
    -	/* the default log size is 16k or 32k which is one header sector */
    -	log->l_iclog_hsize = BBSIZE;
    -	log->l_iclog_heads = 1;
    -
    -	/*
    -	 * For 16KB, we use 3 32KB buffers.  For 32KB block sizes, we use
    -	 * 4 32KB buffers.  For 64KB block sizes, we use 8 32KB buffers.
    -	 */
    -	if (mp->m_sb.sb_blocksize >= 16*1024) {
    -		log->l_iclog_size = XLOG_BIG_RECORD_BSIZE;
    -		log->l_iclog_size_log = XLOG_BIG_RECORD_BSHIFT;
    -		if (mp->m_logbufs <= 0) {
    -			switch (mp->m_sb.sb_blocksize) {
    -			    case 16*1024:			/* 16 KB */
    -				log->l_iclog_bufs = 3;
    -				break;
    -			    case 32*1024:			/* 32 KB */
    -				log->l_iclog_bufs = 4;
    -				break;
    -			    case 64*1024:			/* 64 KB */
    -				log->l_iclog_bufs = 8;
    -				break;
    -			    default:
    -				xlog_panic("XFS: Invalid blocksize");
    -				break;
    -			}
    -		}
    -	}
    -
    -done:	/* are we being asked to make the sizes selected above visible? */
    -	if (mp->m_logbufs == 0)
    -		mp->m_logbufs = log->l_iclog_bufs;
    -	if (mp->m_logbsize == 0)
    -		mp->m_logbsize = log->l_iclog_size;
    -}	/* xlog_get_iclog_buffer_size */
    -
    -
    -/*
    - * This routine initializes some of the log structure for a given mount point.
    - * Its primary purpose is to fill in enough, so recovery can occur.  However,
    - * some other stuff may be filled in too.
    - */
    -STATIC xlog_t *
    -xlog_alloc_log(xfs_mount_t	*mp,
    -	       xfs_buftarg_t	*log_target,
    -	       xfs_daddr_t	blk_offset,
    -	       int		num_bblks)
    -{
    -	xlog_t			*log;
    -	xlog_rec_header_t	*head;
    -	xlog_in_core_t		**iclogp;
    -	xlog_in_core_t		*iclog, *prev_iclog=NULL;
    -	xfs_buf_t		*bp;
    -	int			i;
    -	int			iclogsize;
    -
    -	log = (xlog_t *)kmem_zalloc(sizeof(xlog_t), KM_SLEEP);
    -
    -	log->l_mp	   = mp;
    -	log->l_targ	   = log_target;
    -	log->l_logsize     = BBTOB(num_bblks);
    -	log->l_logBBstart  = blk_offset;
    -	log->l_logBBsize   = num_bblks;
    -	log->l_covered_state = XLOG_STATE_COVER_IDLE;
    -	log->l_flags	   |= XLOG_ACTIVE_RECOVERY;
    -
    -	log->l_prev_block  = -1;
    -	ASSIGN_ANY_LSN_HOST(log->l_tail_lsn, 1, 0);
    -	/* log->l_tail_lsn = 0x100000000LL; cycle = 1; current block = 0 */
    -	log->l_last_sync_lsn = log->l_tail_lsn;
    -	log->l_curr_cycle  = 1;	    /* 0 is bad since this is initial value */
    -	log->l_grant_reserve_cycle = 1;
    -	log->l_grant_write_cycle = 1;
    -
    -	if (XFS_SB_VERSION_HASSECTOR(&mp->m_sb)) {
    -		log->l_sectbb_log = mp->m_sb.sb_logsectlog - BBSHIFT;
    -		ASSERT(log->l_sectbb_log <= mp->m_sectbb_log);
    -		/* for larger sector sizes, must have v2 or external log */
    -		ASSERT(log->l_sectbb_log == 0 ||
    -			log->l_logBBstart == 0 ||
    -			XFS_SB_VERSION_HASLOGV2(&mp->m_sb));
    -		ASSERT(mp->m_sb.sb_logsectlog >= BBSHIFT);
    -	}
    -	log->l_sectbb_mask = (1 << log->l_sectbb_log) - 1;
    -
    -	xlog_get_iclog_buffer_size(mp, log);
    -
    -	bp = xfs_buf_get_empty(log->l_iclog_size, mp->m_logdev_targp);
    -	XFS_BUF_SET_IODONE_FUNC(bp, xlog_iodone);
    -	XFS_BUF_SET_BDSTRAT_FUNC(bp, xlog_bdstrat_cb);
    -	XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)1);
    -	ASSERT(XFS_BUF_ISBUSY(bp));
    -	ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);
    -	XFS_BUF_VSEMA(bp);
    -	log->l_xbuf = bp;
    -
    -	spinlock_init(&log->l_icloglock, "iclog");
    -	spinlock_init(&log->l_grant_lock, "grhead_iclog");
    -	initnsema(&log->l_flushsema, 0, "ic-flush");
    -	xlog_state_ticket_alloc(log);  /* wait until after icloglock inited */
    -
    -	/* log record size must be multiple of BBSIZE; see xlog_rec_header_t */
    -	ASSERT((XFS_BUF_SIZE(bp) & BBMASK) == 0);
    -
    -	iclogp = &log->l_iclog;
    -	/*
    -	 * The amount of memory to allocate for the iclog structure is
    -	 * rather funky due to the way the structure is defined.  It is
    -	 * done this way so that we can use different sizes for machines
    -	 * with different amounts of memory.  See the definition of
    -	 * xlog_in_core_t in xfs_log_priv.h for details.
    -	 */
    -	iclogsize = log->l_iclog_size;
    -	ASSERT(log->l_iclog_size >= 4096);
    -	for (i=0; i < log->l_iclog_bufs; i++) {
    -		*iclogp = (xlog_in_core_t *)
    -			  kmem_zalloc(sizeof(xlog_in_core_t), KM_SLEEP);
    -		iclog = *iclogp;
    -		iclog->hic_data = (xlog_in_core_2_t *)
    -			  kmem_zalloc(iclogsize, KM_SLEEP);
    -
    -		iclog->ic_prev = prev_iclog;
    -		prev_iclog = iclog;
    -		log->l_iclog_bak[i] = (xfs_caddr_t)&(iclog->ic_header);
    -
    -		head = &iclog->ic_header;
    -		memset(head, 0, sizeof(xlog_rec_header_t));
    -		INT_SET(head->h_magicno, ARCH_CONVERT, XLOG_HEADER_MAGIC_NUM);
    -		INT_SET(head->h_version, ARCH_CONVERT,
    -			XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb) ? 2 : 1);
    -		INT_SET(head->h_size, ARCH_CONVERT, log->l_iclog_size);
    -		/* new fields */
    -		INT_SET(head->h_fmt, ARCH_CONVERT, XLOG_FMT);
    -		memcpy(&head->h_fs_uuid, &mp->m_sb.sb_uuid, sizeof(uuid_t));
    -
    -		bp = xfs_buf_get_empty(log->l_iclog_size, mp->m_logdev_targp);
    -		XFS_BUF_SET_IODONE_FUNC(bp, xlog_iodone);
    -		XFS_BUF_SET_BDSTRAT_FUNC(bp, xlog_bdstrat_cb);
    -		XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)1);
    -		iclog->ic_bp = bp;
    -
    -		iclog->ic_size = XFS_BUF_SIZE(bp) - log->l_iclog_hsize;
    -		iclog->ic_state = XLOG_STATE_ACTIVE;
    -		iclog->ic_log = log;
    -		iclog->ic_callback_tail = &(iclog->ic_callback);
    -		iclog->ic_datap = (char *)iclog->hic_data + log->l_iclog_hsize;
    -
    -		ASSERT(XFS_BUF_ISBUSY(iclog->ic_bp));
    -		ASSERT(XFS_BUF_VALUSEMA(iclog->ic_bp) <= 0);
    -		XFS_BUF_VSEMA(iclog->ic_bp);
    -		sv_init(&iclog->ic_forcesema, SV_DEFAULT, "iclog-force");
    -		sv_init(&iclog->ic_writesema, SV_DEFAULT, "iclog-write");
    -
    -		iclogp = &iclog->ic_next;
    -	}
    -	*iclogp = log->l_iclog;			/* complete ring */
    -	log->l_iclog->ic_prev = prev_iclog;	/* re-write 1st prev ptr */
    -
    -	return log;
    -}	/* xlog_alloc_log */
    -
    -
    -/*
    - * Write out the commit record of a transaction associated with the given
    - * ticket.  Return the lsn of the commit record.
    - */
    -STATIC int
    -xlog_commit_record(xfs_mount_t  *mp,
    -		   xlog_ticket_t *ticket,
    -		   xlog_in_core_t **iclog,
    -		   xfs_lsn_t	*commitlsnp)
    -{
    -	int		error;
    -	xfs_log_iovec_t	reg[1];
    -
    -	reg[0].i_addr = NULL;
    -	reg[0].i_len = 0;
    -	XLOG_VEC_SET_TYPE(®[0], XLOG_REG_TYPE_COMMIT);
    -
    -	ASSERT_ALWAYS(iclog);
    -	if ((error = xlog_write(mp, reg, 1, ticket, commitlsnp,
    -			       iclog, XLOG_COMMIT_TRANS))) {
    -		xfs_force_shutdown(mp, XFS_LOG_IO_ERROR);
    -	}
    -	return error;
    -}	/* xlog_commit_record */
    -
    -
    -/*
    - * Push on the buffer cache code if we ever use more than 75% of the on-disk
    - * log space.  This code pushes on the lsn which would supposedly free up
    - * the 25% which we want to leave free.  We may need to adopt a policy which
    - * pushes on an lsn which is further along in the log once we reach the high
    - * water mark.  In this manner, we would be creating a low water mark.
    - */
    -void
    -xlog_grant_push_ail(xfs_mount_t	*mp,
    -		    int		need_bytes)
    -{
    -    xlog_t	*log = mp->m_log;	/* pointer to the log */
    -    xfs_lsn_t	tail_lsn;		/* lsn of the log tail */
    -    xfs_lsn_t	threshold_lsn = 0;	/* lsn we'd like to be at */
    -    int		free_blocks;		/* free blocks left to write to */
    -    int		free_bytes;		/* free bytes left to write to */
    -    int		threshold_block;	/* block in lsn we'd like to be at */
    -    int		threshold_cycle;	/* lsn cycle we'd like to be at */
    -    int		free_threshold;
    -    SPLDECL(s);
    -
    -    ASSERT(BTOBB(need_bytes) < log->l_logBBsize);
    -
    -    s = GRANT_LOCK(log);
    -    free_bytes = xlog_space_left(log,
    -				 log->l_grant_reserve_cycle,
    -				 log->l_grant_reserve_bytes);
    -    tail_lsn = log->l_tail_lsn;
    -    free_blocks = BTOBBT(free_bytes);
    -
    -    /*
    -     * Set the threshold for the minimum number of free blocks in the
    -     * log to the maximum of what the caller needs, one quarter of the
    -     * log, and 256 blocks.
    -     */
    -    free_threshold = BTOBB(need_bytes);
    -    free_threshold = MAX(free_threshold, (log->l_logBBsize >> 2));
    -    free_threshold = MAX(free_threshold, 256);
    -    if (free_blocks < free_threshold) {
    -	threshold_block = BLOCK_LSN(tail_lsn) + free_threshold;
    -	threshold_cycle = CYCLE_LSN(tail_lsn);
    -	if (threshold_block >= log->l_logBBsize) {
    -	    threshold_block -= log->l_logBBsize;
    -	    threshold_cycle += 1;
    -	}
    -	ASSIGN_ANY_LSN_HOST(threshold_lsn, threshold_cycle,
    -		       threshold_block);
    -
    -	/* Don't pass in an lsn greater than the lsn of the last
    -	 * log record known to be on disk.
    -	 */
    -	if (XFS_LSN_CMP(threshold_lsn, log->l_last_sync_lsn) > 0)
    -	    threshold_lsn = log->l_last_sync_lsn;
    -    }
    -    GRANT_UNLOCK(log, s);
    -
    -    /*
    -     * Get the transaction layer to kick the dirty buffers out to
    -     * disk asynchronously. No point in trying to do this if
    -     * the filesystem is shutting down.
    -     */
    -    if (threshold_lsn &&
    -	!XLOG_FORCED_SHUTDOWN(log))
    -	    xfs_trans_push_ail(mp, threshold_lsn);
    -}	/* xlog_grant_push_ail */
    -
    -
    -/*
    - * Flush out the in-core log (iclog) to the on-disk log in an asynchronous 
    - * fashion.  Previously, we should have moved the current iclog
    - * ptr in the log to point to the next available iclog.  This allows further
    - * write to continue while this code syncs out an iclog ready to go.
    - * Before an in-core log can be written out, the data section must be scanned
    - * to save away the 1st word of each BBSIZE block into the header.  We replace
    - * it with the current cycle count.  Each BBSIZE block is tagged with the
    - * cycle count because there in an implicit assumption that drives will
    - * guarantee that entire 512 byte blocks get written at once.  In other words,
    - * we can't have part of a 512 byte block written and part not written.  By
    - * tagging each block, we will know which blocks are valid when recovering
    - * after an unclean shutdown.
    - *
    - * This routine is single threaded on the iclog.  No other thread can be in
    - * this routine with the same iclog.  Changing contents of iclog can there-
    - * fore be done without grabbing the state machine lock.  Updating the global
    - * log will require grabbing the lock though.
    - *
    - * The entire log manager uses a logical block numbering scheme.  Only
    - * log_sync (and then only bwrite()) know about the fact that the log may
    - * not start with block zero on a given device.  The log block start offset
    - * is added immediately before calling bwrite().
    - */
    -
    -int
    -xlog_sync(xlog_t		*log,
    -	  xlog_in_core_t	*iclog)
    -{
    -	xfs_caddr_t	dptr;		/* pointer to byte sized element */
    -	xfs_buf_t	*bp;
    -	int		i, ops;
    -	uint		count;		/* byte count of bwrite */
    -	uint		count_init;	/* initial count before roundup */
    -	int		roundoff;       /* roundoff to BB or stripe */
    -	int		split = 0;	/* split write into two regions */
    -	int		error;
    -	SPLDECL(s);
    -	int		v2 = XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb);
    -
    -	XFS_STATS_INC(xs_log_writes);
    -	ASSERT(iclog->ic_refcnt == 0);
    -
    -	/* Add for LR header */
    -	count_init = log->l_iclog_hsize + iclog->ic_offset;
    -
    -	/* Round out the log write size */
    -	if (v2 && log->l_mp->m_sb.sb_logsunit > 1) {
    -		/* we have a v2 stripe unit to use */
    -		count = XLOG_LSUNITTOB(log, XLOG_BTOLSUNIT(log, count_init));
    -	} else {
    -		count = BBTOB(BTOBB(count_init));
    -	}
    -	roundoff = count - count_init;
    -	ASSERT(roundoff >= 0);
    -	ASSERT((v2 && log->l_mp->m_sb.sb_logsunit > 1 && 
    -                roundoff < log->l_mp->m_sb.sb_logsunit)
    -		|| 
    -		(log->l_mp->m_sb.sb_logsunit <= 1 && 
    -		 roundoff < BBTOB(1)));
    -
    -	/* move grant heads by roundoff in sync */
    -	s = GRANT_LOCK(log);
    -	xlog_grant_add_space(log, roundoff);
    -	GRANT_UNLOCK(log, s);
    -
    -	/* put cycle number in every block */
    -	xlog_pack_data(log, iclog, roundoff); 
    -
    -	/* real byte length */
    -	if (v2) {
    -		INT_SET(iclog->ic_header.h_len, 
    -			ARCH_CONVERT,
    -			iclog->ic_offset + roundoff);
    -	} else {
    -		INT_SET(iclog->ic_header.h_len, ARCH_CONVERT, iclog->ic_offset);
    -	}
    -
    -	/* put ops count in correct order */
    -	ops = iclog->ic_header.h_num_logops;
    -	INT_SET(iclog->ic_header.h_num_logops, ARCH_CONVERT, ops);
    -
    -	bp	    = iclog->ic_bp;
    -	XFS_BUF_PSEMA(bp, PRIBIO);
    -	ASSERT(XFS_BUF_FSPRIVATE2(bp, unsigned long) == (unsigned long)1);
    -	XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)2);
    -	XFS_BUF_SET_ADDR(bp, BLOCK_LSN(INT_GET(iclog->ic_header.h_lsn, ARCH_CONVERT)));
    -
    -	XFS_STATS_ADD(xs_log_blocks, BTOBB(count));
    -
    -	/* Do we need to split this write into 2 parts? */
    -	if (XFS_BUF_ADDR(bp) + BTOBB(count) > log->l_logBBsize) {
    -		split = count - (BBTOB(log->l_logBBsize - XFS_BUF_ADDR(bp)));
    -		count = BBTOB(log->l_logBBsize - XFS_BUF_ADDR(bp));
    -		iclog->ic_bwritecnt = 2;	/* split into 2 writes */
    -	} else {
    -		iclog->ic_bwritecnt = 1;
    -	}
    -	XFS_BUF_SET_PTR(bp, (xfs_caddr_t) &(iclog->ic_header), count);
    -	XFS_BUF_SET_FSPRIVATE(bp, iclog);	/* save for later */
    -	XFS_BUF_BUSY(bp);
    -	XFS_BUF_ASYNC(bp);
    -	XFS_BUF_SET_IODONE_FUNC(bp, xlog_iodone);
    -	/*
    -	 * Do an ordered write for the log block.
    -	 *
    -	 * It may not be needed to flush the first split block in the log wrap
    -	 * case, but do it anyways to be safe -AK
    -	 */
    -	if (log->l_mp->m_flags & XFS_MOUNT_BARRIER)
    -		XFS_BUF_ORDERED(bp);
    -
    -	ASSERT(XFS_BUF_ADDR(bp) <= log->l_logBBsize-1);
    -	ASSERT(XFS_BUF_ADDR(bp) + BTOBB(count) <= log->l_logBBsize);
    -
    -	xlog_verify_iclog(log, iclog, count, B_TRUE);
    -
    -	/* account for log which doesn't start at block #0 */
    -	XFS_BUF_SET_ADDR(bp, XFS_BUF_ADDR(bp) + log->l_logBBstart);
    -	/*
    -	 * Don't call xfs_bwrite here. We do log-syncs even when the filesystem
    -	 * is shutting down.
    -	 */
    -	XFS_BUF_WRITE(bp);
    -
    -	if ((error = XFS_bwrite(bp))) {
    -		xfs_ioerror_alert("xlog_sync", log->l_mp, bp,
    -				  XFS_BUF_ADDR(bp));
    -		return error;
    -	}
    -	if (split) {
    -		bp		= iclog->ic_log->l_xbuf;
    -		ASSERT(XFS_BUF_FSPRIVATE2(bp, unsigned long) ==
    -							(unsigned long)1);
    -		XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)2);
    -		XFS_BUF_SET_ADDR(bp, 0);	     /* logical 0 */
    -		XFS_BUF_SET_PTR(bp, (xfs_caddr_t)((__psint_t)&(iclog->ic_header)+
    -					    (__psint_t)count), split);
    -		XFS_BUF_SET_FSPRIVATE(bp, iclog);
    -		XFS_BUF_BUSY(bp);
    -		XFS_BUF_ASYNC(bp);
    -		XFS_BUF_SET_IODONE_FUNC(bp, xlog_iodone);
    -		if (log->l_mp->m_flags & XFS_MOUNT_BARRIER)
    -			XFS_BUF_ORDERED(bp);
    -		dptr = XFS_BUF_PTR(bp);
    -		/*
    -		 * Bump the cycle numbers at the start of each block
    -		 * since this part of the buffer is at the start of
    -		 * a new cycle.  Watch out for the header magic number
    -		 * case, though.
    -		 */
    -		for (i=0; il_logBBsize-1);
    -		ASSERT(XFS_BUF_ADDR(bp) + BTOBB(count) <= log->l_logBBsize);
    -
    -		/* account for internal log which doesn't start at block #0 */
    -		XFS_BUF_SET_ADDR(bp, XFS_BUF_ADDR(bp) + log->l_logBBstart);
    -		XFS_BUF_WRITE(bp);
    -		if ((error = XFS_bwrite(bp))) {
    -			xfs_ioerror_alert("xlog_sync (split)", log->l_mp,
    -					  bp, XFS_BUF_ADDR(bp));
    -			return error;
    -		}
    -	}
    -	return 0;
    -}	/* xlog_sync */
    -
    -
    -/*
    - * Deallocate a log structure
    - */
    -void
    -xlog_dealloc_log(xlog_t *log)
    -{
    -	xlog_in_core_t	*iclog, *next_iclog;
    -	xlog_ticket_t	*tic, *next_tic;
    -	int		i;
    -
    -
    -	iclog = log->l_iclog;
    -	for (i=0; il_iclog_bufs; i++) {
    -		sv_destroy(&iclog->ic_forcesema);
    -		sv_destroy(&iclog->ic_writesema);
    -		XFS_BUF_PSEMA(iclog->ic_bp, PRIBIO);
    -		xfs_buf_free(iclog->ic_bp);
    -#ifdef XFS_LOG_TRACE
    -		if (iclog->ic_trace != NULL) {
    -			ktrace_free(iclog->ic_trace);
    -		}
    -#endif
    -		next_iclog = iclog->ic_next;
    -		kmem_free(iclog->hic_data, log->l_iclog_size);
    -		kmem_free(iclog, sizeof(xlog_in_core_t));
    -		iclog = next_iclog;
    -	}
    -	freesema(&log->l_flushsema);
    -	spinlock_destroy(&log->l_icloglock);
    -	spinlock_destroy(&log->l_grant_lock);
    -
    -	/* XXXsup take a look at this again. */
    -	if ((log->l_ticket_cnt != log->l_ticket_tcnt)  &&
    -	    !XLOG_FORCED_SHUTDOWN(log)) {
    -		xfs_fs_cmn_err(CE_WARN, log->l_mp,
    -			"xlog_dealloc_log: (cnt: %d, total: %d)",
    -			log->l_ticket_cnt, log->l_ticket_tcnt);
    -		/* ASSERT(log->l_ticket_cnt == log->l_ticket_tcnt); */
    -
    -	} else {
    -		tic = log->l_unmount_free;
    -		while (tic) {
    -			next_tic = tic->t_next;
    -			kmem_free(tic, NBPP);
    -			tic = next_tic;
    -		}
    -	}
    -	XFS_BUF_PSEMA(log->l_xbuf, PRIBIO);
    -	xfs_buf_free(log->l_xbuf);
    -#ifdef XFS_LOG_TRACE
    -	if (log->l_trace != NULL) {
    -		ktrace_free(log->l_trace);
    -	}
    -	if (log->l_grant_trace != NULL) {
    -		ktrace_free(log->l_grant_trace);
    -	}
    -#endif
    -	log->l_mp->m_log = NULL;
    -	kmem_free(log, sizeof(xlog_t));
    -}	/* xlog_dealloc_log */
    -
    -/*
    - * Update counters atomically now that memcpy is done.
    - */
    -/* ARGSUSED */
    -static inline void
    -xlog_state_finish_copy(xlog_t		*log,
    -		       xlog_in_core_t	*iclog,
    -		       int		record_cnt,
    -		       int		copy_bytes)
    -{
    -	SPLDECL(s);
    -
    -	s = LOG_LOCK(log);
    -
    -	iclog->ic_header.h_num_logops += record_cnt;
    -	iclog->ic_offset += copy_bytes;
    -
    -	LOG_UNLOCK(log, s);
    -}	/* xlog_state_finish_copy */
    -
    -
    -
    -
    -/*
    - * print out info relating to regions written which consume
    - * the reservation
    - */
    -STATIC void
    -xlog_print_tic_res(xfs_mount_t *mp, xlog_ticket_t *ticket)
    -{
    -	uint i;
    -	uint ophdr_spc = ticket->t_res_num_ophdrs * (uint)sizeof(xlog_op_header_t);
    -
    -	/* match with XLOG_REG_TYPE_* in xfs_log.h */
    -	static char *res_type_str[XLOG_REG_TYPE_MAX] = {
    -	    "bformat",
    -	    "bchunk",
    -	    "efi_format",
    -	    "efd_format",
    -	    "iformat",
    -	    "icore",
    -	    "iext",
    -	    "ibroot",
    -	    "ilocal",
    -	    "iattr_ext",
    -	    "iattr_broot",
    -	    "iattr_local",
    -	    "qformat",
    -	    "dquot",
    -	    "quotaoff",
    -	    "LR header",
    -	    "unmount",
    -	    "commit",
    -	    "trans header"
    -	};
    -	static char *trans_type_str[XFS_TRANS_TYPE_MAX] = {
    -	    "SETATTR_NOT_SIZE",
    -	    "SETATTR_SIZE",
    -	    "INACTIVE",
    -	    "CREATE",
    -	    "CREATE_TRUNC",
    -	    "TRUNCATE_FILE",
    -	    "REMOVE",
    -	    "LINK",
    -	    "RENAME",
    -	    "MKDIR",
    -	    "RMDIR",
    -	    "SYMLINK",
    -	    "SET_DMATTRS",
    -	    "GROWFS",
    -	    "STRAT_WRITE",
    -	    "DIOSTRAT",
    -	    "WRITE_SYNC",
    -	    "WRITEID",
    -	    "ADDAFORK",
    -	    "ATTRINVAL",
    -	    "ATRUNCATE",
    -	    "ATTR_SET",
    -	    "ATTR_RM",
    -	    "ATTR_FLAG",
    -	    "CLEAR_AGI_BUCKET",
    -	    "QM_SBCHANGE",
    -	    "DUMMY1",
    -	    "DUMMY2",
    -	    "QM_QUOTAOFF",
    -	    "QM_DQALLOC",
    -	    "QM_SETQLIM",
    -	    "QM_DQCLUSTER",
    -	    "QM_QINOCREATE",
    -	    "QM_QUOTAOFF_END",
    -	    "SB_UNIT",
    -	    "FSYNC_TS",
    -	    "GROWFSRT_ALLOC",
    -	    "GROWFSRT_ZERO",
    -	    "GROWFSRT_FREE",
    -	    "SWAPEXT"
    -	};
    -
    -	xfs_fs_cmn_err(CE_WARN, mp,
    -			"xfs_log_write: reservation summary:\n"
    -			"  trans type  = %s (%u)\n"
    -			"  unit res    = %d bytes\n"
    -			"  current res = %d bytes\n"
    -			"  total reg   = %u bytes (o/flow = %u bytes)\n"
    -			"  ophdrs      = %u (ophdr space = %u bytes)\n"
    -			"  ophdr + reg = %u bytes\n"
    -			"  num regions = %u\n",
    -			((ticket->t_trans_type <= 0 ||
    -			  ticket->t_trans_type > XFS_TRANS_TYPE_MAX) ?
    -			  "bad-trans-type" : trans_type_str[ticket->t_trans_type-1]),
    -			ticket->t_trans_type,
    -			ticket->t_unit_res,
    -			ticket->t_curr_res,
    -			ticket->t_res_arr_sum, ticket->t_res_o_flow,
    -			ticket->t_res_num_ophdrs, ophdr_spc,
    -			ticket->t_res_arr_sum + 
    -			ticket->t_res_o_flow + ophdr_spc,
    -			ticket->t_res_num);
    -
    -	for (i = 0; i < ticket->t_res_num; i++) {
    -		uint r_type = ticket->t_res_arr[i].r_type; 
    -		cmn_err(CE_WARN,
    -			    "region[%u]: %s - %u bytes\n",
    -			    i, 
    -			    ((r_type <= 0 || r_type > XLOG_REG_TYPE_MAX) ?
    -			    "bad-rtype" : res_type_str[r_type-1]),
    -			    ticket->t_res_arr[i].r_len);
    -	}
    -}
    -
    -/*
    - * Write some region out to in-core log
    - *
    - * This will be called when writing externally provided regions or when
    - * writing out a commit record for a given transaction.
    - *
    - * General algorithm:
    - *	1. Find total length of this write.  This may include adding to the
    - *		lengths passed in.
    - *	2. Check whether we violate the tickets reservation.
    - *	3. While writing to this iclog
    - *	    A. Reserve as much space in this iclog as can get
    - *	    B. If this is first write, save away start lsn
    - *	    C. While writing this region:
    - *		1. If first write of transaction, write start record
    - *		2. Write log operation header (header per region)
    - *		3. Find out if we can fit entire region into this iclog
    - *		4. Potentially, verify destination memcpy ptr
    - *		5. Memcpy (partial) region
    - *		6. If partial copy, release iclog; otherwise, continue
    - *			copying more regions into current iclog
    - *	4. Mark want sync bit (in simulation mode)
    - *	5. Release iclog for potential flush to on-disk log.
    - *
    - * ERRORS:
    - * 1.	Panic if reservation is overrun.  This should never happen since
    - *	reservation amounts are generated internal to the filesystem.
    - * NOTES:
    - * 1. Tickets are single threaded data structures.
    - * 2. The XLOG_END_TRANS & XLOG_CONTINUE_TRANS flags are passed down to the
    - *	syncing routine.  When a single log_write region needs to span
    - *	multiple in-core logs, the XLOG_CONTINUE_TRANS bit should be set
    - *	on all log operation writes which don't contain the end of the
    - *	region.  The XLOG_END_TRANS bit is used for the in-core log
    - *	operation which contains the end of the continued log_write region.
    - * 3. When xlog_state_get_iclog_space() grabs the rest of the current iclog,
    - *	we don't really know exactly how much space will be used.  As a result,
    - *	we don't update ic_offset until the end when we know exactly how many
    - *	bytes have been written out.
    - */
    -int
    -xlog_write(xfs_mount_t *	mp,
    -	   xfs_log_iovec_t	reg[],
    -	   int			nentries,
    -	   xfs_log_ticket_t	tic,
    -	   xfs_lsn_t		*start_lsn,
    -	   xlog_in_core_t	**commit_iclog,
    -	   uint			flags)
    -{
    -    xlog_t	     *log    = mp->m_log;
    -    xlog_ticket_t    *ticket = (xlog_ticket_t *)tic;
    -    xlog_op_header_t *logop_head;    /* ptr to log operation header */
    -    xlog_in_core_t   *iclog = NULL;  /* ptr to current in-core log */
    -    __psint_t	     ptr;	     /* copy address into data region */
    -    int		     len;	     /* # xlog_write() bytes 2 still copy */
    -    int		     index;	     /* region index currently copying */
    -    int		     log_offset = 0; /* offset (from 0) into data region */
    -    int		     start_rec_copy; /* # bytes to copy for start record */
    -    int		     partial_copy;   /* did we split a region? */
    -    int		     partial_copy_len;/* # bytes copied if split region */
    -    int		     need_copy;	     /* # bytes need to memcpy this region */
    -    int		     copy_len;	     /* # bytes actually memcpy'ing */
    -    int		     copy_off;	     /* # bytes from entry start */
    -    int		     contwr;	     /* continued write of in-core log? */
    -    int		     error;
    -    int		     record_cnt = 0, data_cnt = 0;
    -
    -    partial_copy_len = partial_copy = 0;
    -
    -    /* Calculate potential maximum space.  Each region gets its own
    -     * xlog_op_header_t and may need to be double word aligned.
    -     */
    -    len = 0;
    -    if (ticket->t_flags & XLOG_TIC_INITED) {    /* acct for start rec of xact */
    -	len += sizeof(xlog_op_header_t);
    -	XLOG_TIC_ADD_OPHDR(ticket);
    -    }
    -
    -    for (index = 0; index < nentries; index++) {
    -	len += sizeof(xlog_op_header_t);	    /* each region gets >= 1 */
    -	XLOG_TIC_ADD_OPHDR(ticket);
    -	len += reg[index].i_len;
    -	XLOG_TIC_ADD_REGION(ticket, reg[index].i_len, reg[index].i_type);
    -    }
    -    contwr = *start_lsn = 0;
    -
    -    if (ticket->t_curr_res < len) {
    -	xlog_print_tic_res(mp, ticket);
    -#ifdef DEBUG
    -	xlog_panic(
    -		"xfs_log_write: reservation ran out. Need to up reservation");
    -#else
    -	/* Customer configurable panic */
    -	xfs_cmn_err(XFS_PTAG_LOGRES, CE_ALERT, mp,
    -		"xfs_log_write: reservation ran out. Need to up reservation");
    -	/* If we did not panic, shutdown the filesystem */
    -	xfs_force_shutdown(mp, XFS_CORRUPT_INCORE);
    -#endif
    -    } else
    -	ticket->t_curr_res -= len;
    -
    -    for (index = 0; index < nentries; ) {
    -	if ((error = xlog_state_get_iclog_space(log, len, &iclog, ticket,
    -					       &contwr, &log_offset)))
    -		return error;
    -
    -	ASSERT(log_offset <= iclog->ic_size - 1);
    -	ptr = (__psint_t) ((char *)iclog->ic_datap+log_offset);
    -
    -	/* start_lsn is the first lsn written to. That's all we need. */
    -	if (! *start_lsn)
    -	    *start_lsn = INT_GET(iclog->ic_header.h_lsn, ARCH_CONVERT);
    -
    -	/* This loop writes out as many regions as can fit in the amount
    -	 * of space which was allocated by xlog_state_get_iclog_space().
    -	 */
    -	while (index < nentries) {
    -	    ASSERT(reg[index].i_len % sizeof(__int32_t) == 0);
    -	    ASSERT((__psint_t)ptr % sizeof(__int32_t) == 0);
    -	    start_rec_copy = 0;
    -
    -	    /* If first write for transaction, insert start record.
    -	     * We can't be trying to commit if we are inited.  We can't
    -	     * have any "partial_copy" if we are inited.
    -	     */
    -	    if (ticket->t_flags & XLOG_TIC_INITED) {
    -		logop_head		= (xlog_op_header_t *)ptr;
    -		INT_SET(logop_head->oh_tid, ARCH_CONVERT, ticket->t_tid);
    -		logop_head->oh_clientid = ticket->t_clientid;
    -		logop_head->oh_len	= 0;
    -		logop_head->oh_flags    = XLOG_START_TRANS;
    -		logop_head->oh_res2	= 0;
    -		ticket->t_flags		&= ~XLOG_TIC_INITED;	/* clear bit */
    -		record_cnt++;
    -
    -		start_rec_copy = sizeof(xlog_op_header_t);
    -		xlog_write_adv_cnt(ptr, len, log_offset, start_rec_copy);
    -	    }
    -
    -	    /* Copy log operation header directly into data section */
    -	    logop_head			= (xlog_op_header_t *)ptr;
    -	    INT_SET(logop_head->oh_tid, ARCH_CONVERT, ticket->t_tid);
    -	    logop_head->oh_clientid	= ticket->t_clientid;
    -	    logop_head->oh_res2		= 0;
    -
    -	    /* header copied directly */
    -	    xlog_write_adv_cnt(ptr, len, log_offset, sizeof(xlog_op_header_t));
    -
    -	    /* are we copying a commit or unmount record? */
    -	    logop_head->oh_flags = flags;
    -
    -	    /*
    -	     * We've seen logs corrupted with bad transaction client
    -	     * ids.  This makes sure that XFS doesn't generate them on.
    -	     * Turn this into an EIO and shut down the filesystem.
    -	     */
    -	    switch (logop_head->oh_clientid)  {
    -	    case XFS_TRANSACTION:
    -	    case XFS_VOLUME:
    -	    case XFS_LOG:
    -		break;
    -	    default:
    -		xfs_fs_cmn_err(CE_WARN, mp,
    -		    "Bad XFS transaction clientid 0x%x in ticket 0x%p",
    -		    logop_head->oh_clientid, tic);
    -		return XFS_ERROR(EIO);
    -	    }
    -
    -	    /* Partial write last time? => (partial_copy != 0)
    -	     * need_copy is the amount we'd like to copy if everything could
    -	     * fit in the current memcpy.
    -	     */
    -	    need_copy =	reg[index].i_len - partial_copy_len;
    -
    -	    copy_off = partial_copy_len;
    -	    if (need_copy <= iclog->ic_size - log_offset) { /*complete write */
    -		INT_SET(logop_head->oh_len, ARCH_CONVERT, copy_len = need_copy);
    -		if (partial_copy)
    -		    logop_head->oh_flags|= (XLOG_END_TRANS|XLOG_WAS_CONT_TRANS);
    -		partial_copy_len = partial_copy = 0;
    -	    } else {					    /* partial write */
    -		copy_len = iclog->ic_size - log_offset;
    -		INT_SET(logop_head->oh_len, ARCH_CONVERT, copy_len);
    -		logop_head->oh_flags |= XLOG_CONTINUE_TRANS;
    -		if (partial_copy)
    -			logop_head->oh_flags |= XLOG_WAS_CONT_TRANS;
    -		partial_copy_len += copy_len;
    -		partial_copy++;
    -		len += sizeof(xlog_op_header_t); /* from splitting of region */
    -		/* account for new log op header */
    -		ticket->t_curr_res -= sizeof(xlog_op_header_t);
    -		XLOG_TIC_ADD_OPHDR(ticket);
    -	    }
    -	    xlog_verify_dest_ptr(log, ptr);
    -
    -	    /* copy region */
    -	    ASSERT(copy_len >= 0);
    -	    memcpy((xfs_caddr_t)ptr, reg[index].i_addr + copy_off, copy_len);
    -	    xlog_write_adv_cnt(ptr, len, log_offset, copy_len);
    -
    -	    /* make copy_len total bytes copied, including headers */
    -	    copy_len += start_rec_copy + sizeof(xlog_op_header_t);
    -	    record_cnt++;
    -	    data_cnt += contwr ? copy_len : 0;
    -	    if (partial_copy) {			/* copied partial region */
    -		    /* already marked WANT_SYNC by xlog_state_get_iclog_space */
    -		    xlog_state_finish_copy(log, iclog, record_cnt, data_cnt);
    -		    record_cnt = data_cnt = 0;
    -		    if ((error = xlog_state_release_iclog(log, iclog)))
    -			    return error;
    -		    break;			/* don't increment index */
    -	    } else {				/* copied entire region */
    -		index++;
    -		partial_copy_len = partial_copy = 0;
    -
    -		if (iclog->ic_size - log_offset <= sizeof(xlog_op_header_t)) {
    -		    xlog_state_finish_copy(log, iclog, record_cnt, data_cnt);
    -		    record_cnt = data_cnt = 0;
    -		    xlog_state_want_sync(log, iclog);
    -		    if (commit_iclog) {
    -			ASSERT(flags & XLOG_COMMIT_TRANS);
    -			*commit_iclog = iclog;
    -		    } else if ((error = xlog_state_release_iclog(log, iclog)))
    -			   return error;
    -		    if (index == nentries)
    -			    return 0;		/* we are done */
    -		    else
    -			    break;
    -		}
    -	    } /* if (partial_copy) */
    -	} /* while (index < nentries) */
    -    } /* for (index = 0; index < nentries; ) */
    -    ASSERT(len == 0);
    -
    -    xlog_state_finish_copy(log, iclog, record_cnt, data_cnt);
    -    if (commit_iclog) {
    -	ASSERT(flags & XLOG_COMMIT_TRANS);
    -	*commit_iclog = iclog;
    -	return 0;
    -    }
    -    return xlog_state_release_iclog(log, iclog);
    -}	/* xlog_write */
    -
    -
    -/*****************************************************************************
    - *
    - *		State Machine functions
    - *
    - *****************************************************************************
    - */
    -
    -/* Clean iclogs starting from the head.  This ordering must be
    - * maintained, so an iclog doesn't become ACTIVE beyond one that
    - * is SYNCING.  This is also required to maintain the notion that we use
    - * a counting semaphore to hold off would be writers to the log when every
    - * iclog is trying to sync to disk.
    - *
    - * State Change: DIRTY -> ACTIVE
    - */
    -STATIC void
    -xlog_state_clean_log(xlog_t *log)
    -{
    -	xlog_in_core_t	*iclog;
    -	int changed = 0;
    -
    -	iclog = log->l_iclog;
    -	do {
    -		if (iclog->ic_state == XLOG_STATE_DIRTY) {
    -			iclog->ic_state	= XLOG_STATE_ACTIVE;
    -			iclog->ic_offset       = 0;
    -			iclog->ic_callback	= NULL;   /* don't need to free */
    -			/*
    -			 * If the number of ops in this iclog indicate it just
    -			 * contains the dummy transaction, we can
    -			 * change state into IDLE (the second time around).
    -			 * Otherwise we should change the state into
    -			 * NEED a dummy.
    -			 * We don't need to cover the dummy.
    -			 */
    -			if (!changed &&
    -			   (INT_GET(iclog->ic_header.h_num_logops, ARCH_CONVERT) == XLOG_COVER_OPS)) {
    -				changed = 1;
    -			} else {
    -				/*
    -				 * We have two dirty iclogs so start over
    -				 * This could also be num of ops indicates
    -				 * this is not the dummy going out.
    -				 */
    -				changed = 2;
    -			}
    -			iclog->ic_header.h_num_logops = 0;
    -			memset(iclog->ic_header.h_cycle_data, 0,
    -			      sizeof(iclog->ic_header.h_cycle_data));
    -			iclog->ic_header.h_lsn = 0;
    -		} else if (iclog->ic_state == XLOG_STATE_ACTIVE)
    -			/* do nothing */;
    -		else
    -			break;	/* stop cleaning */
    -		iclog = iclog->ic_next;
    -	} while (iclog != log->l_iclog);
    -
    -	/* log is locked when we are called */
    -	/*
    -	 * Change state for the dummy log recording.
    -	 * We usually go to NEED. But we go to NEED2 if the changed indicates
    -	 * we are done writing the dummy record.
    -	 * If we are done with the second dummy recored (DONE2), then
    -	 * we go to IDLE.
    -	 */
    -	if (changed) {
    -		switch (log->l_covered_state) {
    -		case XLOG_STATE_COVER_IDLE:
    -		case XLOG_STATE_COVER_NEED:
    -		case XLOG_STATE_COVER_NEED2:
    -			log->l_covered_state = XLOG_STATE_COVER_NEED;
    -			break;
    -
    -		case XLOG_STATE_COVER_DONE:
    -			if (changed == 1)
    -				log->l_covered_state = XLOG_STATE_COVER_NEED2;
    -			else
    -				log->l_covered_state = XLOG_STATE_COVER_NEED;
    -			break;
    -
    -		case XLOG_STATE_COVER_DONE2:
    -			if (changed == 1)
    -				log->l_covered_state = XLOG_STATE_COVER_IDLE;
    -			else
    -				log->l_covered_state = XLOG_STATE_COVER_NEED;
    -			break;
    -
    -		default:
    -			ASSERT(0);
    -		}
    -	}
    -}	/* xlog_state_clean_log */
    -
    -STATIC xfs_lsn_t
    -xlog_get_lowest_lsn(
    -	xlog_t		*log)
    -{
    -	xlog_in_core_t  *lsn_log;
    -	xfs_lsn_t	lowest_lsn, lsn;
    -
    -	lsn_log = log->l_iclog;
    -	lowest_lsn = 0;
    -	do {
    -	    if (!(lsn_log->ic_state & (XLOG_STATE_ACTIVE|XLOG_STATE_DIRTY))) {
    -		lsn = INT_GET(lsn_log->ic_header.h_lsn, ARCH_CONVERT);
    -		if ((lsn && !lowest_lsn) ||
    -		    (XFS_LSN_CMP(lsn, lowest_lsn) < 0)) {
    -			lowest_lsn = lsn;
    -		}
    -	    }
    -	    lsn_log = lsn_log->ic_next;
    -	} while (lsn_log != log->l_iclog);
    -	return lowest_lsn;
    -}
    -
    -
    -STATIC void
    -xlog_state_do_callback(
    -	xlog_t		*log,
    -	int		aborted,
    -	xlog_in_core_t	*ciclog)
    -{
    -	xlog_in_core_t	   *iclog;
    -	xlog_in_core_t	   *first_iclog;	/* used to know when we've
    -						 * processed all iclogs once */
    -	xfs_log_callback_t *cb, *cb_next;
    -	int		   flushcnt = 0;
    -	xfs_lsn_t	   lowest_lsn;
    -	int		   ioerrors;	/* counter: iclogs with errors */
    -	int		   loopdidcallbacks; /* flag: inner loop did callbacks*/
    -	int		   funcdidcallbacks; /* flag: function did callbacks */
    -	int		   repeats;	/* for issuing console warnings if
    -					 * looping too many times */
    -	SPLDECL(s);
    -
    -	s = LOG_LOCK(log);
    -	first_iclog = iclog = log->l_iclog;
    -	ioerrors = 0;
    -	funcdidcallbacks = 0;
    -	repeats = 0;
    -
    -	do {
    -		/*
    -		 * Scan all iclogs starting with the one pointed to by the
    -		 * log.  Reset this starting point each time the log is
    -		 * unlocked (during callbacks).
    -		 *
    -		 * Keep looping through iclogs until one full pass is made
    -		 * without running any callbacks.
    -		 */
    -		first_iclog = log->l_iclog;
    -		iclog = log->l_iclog;
    -		loopdidcallbacks = 0;
    -		repeats++;
    -
    -		do {
    -
    -			/* skip all iclogs in the ACTIVE & DIRTY states */
    -			if (iclog->ic_state &
    -			    (XLOG_STATE_ACTIVE|XLOG_STATE_DIRTY)) {
    -				iclog = iclog->ic_next;
    -				continue;
    -			}
    -
    -			/*
    -			 * Between marking a filesystem SHUTDOWN and stopping
    -			 * the log, we do flush all iclogs to disk (if there
    -			 * wasn't a log I/O error). So, we do want things to
    -			 * go smoothly in case of just a SHUTDOWN  w/o a
    -			 * LOG_IO_ERROR.
    -			 */
    -			if (!(iclog->ic_state & XLOG_STATE_IOERROR)) {
    -				/*
    -				 * Can only perform callbacks in order.  Since
    -				 * this iclog is not in the DONE_SYNC/
    -				 * DO_CALLBACK state, we skip the rest and
    -				 * just try to clean up.  If we set our iclog
    -				 * to DO_CALLBACK, we will not process it when
    -				 * we retry since a previous iclog is in the
    -				 * CALLBACK and the state cannot change since
    -				 * we are holding the LOG_LOCK.
    -				 */
    -				if (!(iclog->ic_state &
    -					(XLOG_STATE_DONE_SYNC |
    -						 XLOG_STATE_DO_CALLBACK))) {
    -					if (ciclog && (ciclog->ic_state ==
    -							XLOG_STATE_DONE_SYNC)) {
    -						ciclog->ic_state = XLOG_STATE_DO_CALLBACK;
    -					}
    -					break;
    -				}
    -				/*
    -				 * We now have an iclog that is in either the
    -				 * DO_CALLBACK or DONE_SYNC states. The other
    -				 * states (WANT_SYNC, SYNCING, or CALLBACK were
    -				 * caught by the above if and are going to
    -				 * clean (i.e. we aren't doing their callbacks)
    -				 * see the above if.
    -				 */
    -
    -				/*
    -				 * We will do one more check here to see if we
    -				 * have chased our tail around.
    -				 */
    -
    -				lowest_lsn = xlog_get_lowest_lsn(log);
    -				if (lowest_lsn && (
    -					XFS_LSN_CMP(
    -						lowest_lsn,
    -						INT_GET(iclog->ic_header.h_lsn, ARCH_CONVERT)
    -					)<0)) {
    -					iclog = iclog->ic_next;
    -					continue; /* Leave this iclog for
    -						   * another thread */
    -				}
    -
    -				iclog->ic_state = XLOG_STATE_CALLBACK;
    -
    -				LOG_UNLOCK(log, s);
    -
    -				/* l_last_sync_lsn field protected by
    -				 * GRANT_LOCK. Don't worry about iclog's lsn.
    -				 * No one else can be here except us.
    -				 */
    -				s = GRANT_LOCK(log);
    -				ASSERT(XFS_LSN_CMP(
    -						log->l_last_sync_lsn,
    -						INT_GET(iclog->ic_header.h_lsn, ARCH_CONVERT)
    -					)<=0);
    -				log->l_last_sync_lsn = INT_GET(iclog->ic_header.h_lsn, ARCH_CONVERT);
    -				GRANT_UNLOCK(log, s);
    -
    -				/*
    -				 * Keep processing entries in the callback list
    -				 * until we come around and it is empty.  We
    -				 * need to atomically see that the list is
    -				 * empty and change the state to DIRTY so that
    -				 * we don't miss any more callbacks being added.
    -				 */
    -				s = LOG_LOCK(log);
    -			} else {
    -				ioerrors++;
    -			}
    -			cb = iclog->ic_callback;
    -
    -			while (cb != 0) {
    -				iclog->ic_callback_tail = &(iclog->ic_callback);
    -				iclog->ic_callback = NULL;
    -				LOG_UNLOCK(log, s);
    -
    -				/* perform callbacks in the order given */
    -				for (; cb != 0; cb = cb_next) {
    -					cb_next = cb->cb_next;
    -					cb->cb_func(cb->cb_arg, aborted);
    -				}
    -				s = LOG_LOCK(log);
    -				cb = iclog->ic_callback;
    -			}
    -
    -			loopdidcallbacks++;
    -			funcdidcallbacks++;
    -
    -			ASSERT(iclog->ic_callback == 0);
    -			if (!(iclog->ic_state & XLOG_STATE_IOERROR))
    -				iclog->ic_state = XLOG_STATE_DIRTY;
    -
    -			/*
    -			 * Transition from DIRTY to ACTIVE if applicable.
    -			 * NOP if STATE_IOERROR.
    -			 */
    -			xlog_state_clean_log(log);
    -
    -			/* wake up threads waiting in xfs_log_force() */
    -			sv_broadcast(&iclog->ic_forcesema);
    -
    -			iclog = iclog->ic_next;
    -		} while (first_iclog != iclog);
    -		if (repeats && (repeats % 10) == 0) {
    -			xfs_fs_cmn_err(CE_WARN, log->l_mp,
    -				"xlog_state_do_callback: looping %d", repeats);
    -		}
    -	} while (!ioerrors && loopdidcallbacks);
    -
    -	/*
    -	 * make one last gasp attempt to see if iclogs are being left in
    -	 * limbo..
    -	 */
    -#ifdef DEBUG
    -	if (funcdidcallbacks) {
    -		first_iclog = iclog = log->l_iclog;
    -		do {
    -			ASSERT(iclog->ic_state != XLOG_STATE_DO_CALLBACK);
    -			/*
    -			 * Terminate the loop if iclogs are found in states
    -			 * which will cause other threads to clean up iclogs.
    -			 *
    -			 * SYNCING - i/o completion will go through logs
    -			 * DONE_SYNC - interrupt thread should be waiting for
    -			 *              LOG_LOCK
    -			 * IOERROR - give up hope all ye who enter here
    -			 */
    -			if (iclog->ic_state == XLOG_STATE_WANT_SYNC ||
    -			    iclog->ic_state == XLOG_STATE_SYNCING ||
    -			    iclog->ic_state == XLOG_STATE_DONE_SYNC ||
    -			    iclog->ic_state == XLOG_STATE_IOERROR )
    -				break;
    -			iclog = iclog->ic_next;
    -		} while (first_iclog != iclog);
    -	}
    -#endif
    -
    -	if (log->l_iclog->ic_state & (XLOG_STATE_ACTIVE|XLOG_STATE_IOERROR)) {
    -		flushcnt = log->l_flushcnt;
    -		log->l_flushcnt = 0;
    -	}
    -	LOG_UNLOCK(log, s);
    -	while (flushcnt--)
    -		vsema(&log->l_flushsema);
    -}	/* xlog_state_do_callback */
    -
    -
    -/*
    - * Finish transitioning this iclog to the dirty state.
    - *
    - * Make sure that we completely execute this routine only when this is
    - * the last call to the iclog.  There is a good chance that iclog flushes,
    - * when we reach the end of the physical log, get turned into 2 separate
    - * calls to bwrite.  Hence, one iclog flush could generate two calls to this
    - * routine.  By using the reference count bwritecnt, we guarantee that only
    - * the second completion goes through.
    - *
    - * Callbacks could take time, so they are done outside the scope of the
    - * global state machine log lock.  Assume that the calls to cvsema won't
    - * take a long time.  At least we know it won't sleep.
    - */
    -void
    -xlog_state_done_syncing(
    -	xlog_in_core_t	*iclog,
    -	int		aborted)
    -{
    -	xlog_t		   *log = iclog->ic_log;
    -	SPLDECL(s);
    -
    -	s = LOG_LOCK(log);
    -
    -	ASSERT(iclog->ic_state == XLOG_STATE_SYNCING ||
    -	       iclog->ic_state == XLOG_STATE_IOERROR);
    -	ASSERT(iclog->ic_refcnt == 0);
    -	ASSERT(iclog->ic_bwritecnt == 1 || iclog->ic_bwritecnt == 2);
    -
    -
    -	/*
    -	 * If we got an error, either on the first buffer, or in the case of
    -	 * split log writes, on the second, we mark ALL iclogs STATE_IOERROR,
    -	 * and none should ever be attempted to be written to disk
    -	 * again.
    -	 */
    -	if (iclog->ic_state != XLOG_STATE_IOERROR) {
    -		if (--iclog->ic_bwritecnt == 1) {
    -			LOG_UNLOCK(log, s);
    -			return;
    -		}
    -		iclog->ic_state = XLOG_STATE_DONE_SYNC;
    -	}
    -
    -	/*
    -	 * Someone could be sleeping prior to writing out the next
    -	 * iclog buffer, we wake them all, one will get to do the
    -	 * I/O, the others get to wait for the result.
    -	 */
    -	sv_broadcast(&iclog->ic_writesema);
    -	LOG_UNLOCK(log, s);
    -	xlog_state_do_callback(log, aborted, iclog);	/* also cleans log */
    -}	/* xlog_state_done_syncing */
    -
    -
    -/*
    - * If the head of the in-core log ring is not (ACTIVE or DIRTY), then we must
    - * sleep.  The flush semaphore is set to the number of in-core buffers and
    - * decremented around disk syncing.  Therefore, if all buffers are syncing,
    - * this semaphore will cause new writes to sleep until a sync completes.
    - * Otherwise, this code just does p() followed by v().  This approximates
    - * a sleep/wakeup except we can't race.
    - *
    - * The in-core logs are used in a circular fashion. They are not used
    - * out-of-order even when an iclog past the head is free.
    - *
    - * return:
    - *	* log_offset where xlog_write() can start writing into the in-core
    - *		log's data space.
    - *	* in-core log pointer to which xlog_write() should write.
    - *	* boolean indicating this is a continued write to an in-core log.
    - *		If this is the last write, then the in-core log's offset field
    - *		needs to be incremented, depending on the amount of data which
    - *		is copied.
    - */
    -int
    -xlog_state_get_iclog_space(xlog_t	  *log,
    -			   int		  len,
    -			   xlog_in_core_t **iclogp,
    -			   xlog_ticket_t  *ticket,
    -			   int		  *continued_write,
    -			   int		  *logoffsetp)
    -{
    -	SPLDECL(s);
    -	int		  log_offset;
    -	xlog_rec_header_t *head;
    -	xlog_in_core_t	  *iclog;
    -	int		  error;
    -
    -restart:
    -	s = LOG_LOCK(log);
    -	if (XLOG_FORCED_SHUTDOWN(log)) {
    -		LOG_UNLOCK(log, s);
    -		return XFS_ERROR(EIO);
    -	}
    -
    -	iclog = log->l_iclog;
    -	if (! (iclog->ic_state == XLOG_STATE_ACTIVE)) {
    -		log->l_flushcnt++;
    -		LOG_UNLOCK(log, s);
    -		xlog_trace_iclog(iclog, XLOG_TRACE_SLEEP_FLUSH);
    -		XFS_STATS_INC(xs_log_noiclogs);
    -		/* Ensure that log writes happen */
    -		psema(&log->l_flushsema, PINOD);
    -		goto restart;
    -	}
    -	ASSERT(iclog->ic_state == XLOG_STATE_ACTIVE);
    -	head = &iclog->ic_header;
    -
    -	iclog->ic_refcnt++;			/* prevents sync */
    -	log_offset = iclog->ic_offset;
    -
    -	/* On the 1st write to an iclog, figure out lsn.  This works
    -	 * if iclogs marked XLOG_STATE_WANT_SYNC always write out what they are
    -	 * committing to.  If the offset is set, that's how many blocks
    -	 * must be written.
    -	 */
    -	if (log_offset == 0) {
    -		ticket->t_curr_res -= log->l_iclog_hsize;
    -		XLOG_TIC_ADD_REGION(ticket,
    -				    log->l_iclog_hsize,
    -				    XLOG_REG_TYPE_LRHEADER);
    -		INT_SET(head->h_cycle, ARCH_CONVERT, log->l_curr_cycle);
    -		ASSIGN_LSN(head->h_lsn, log);
    -		ASSERT(log->l_curr_block >= 0);
    -	}
    -
    -	/* If there is enough room to write everything, then do it.  Otherwise,
    -	 * claim the rest of the region and make sure the XLOG_STATE_WANT_SYNC
    -	 * bit is on, so this will get flushed out.  Don't update ic_offset
    -	 * until you know exactly how many bytes get copied.  Therefore, wait
    -	 * until later to update ic_offset.
    -	 *
    -	 * xlog_write() algorithm assumes that at least 2 xlog_op_header_t's
    -	 * can fit into remaining data section.
    -	 */
    -	if (iclog->ic_size - iclog->ic_offset < 2*sizeof(xlog_op_header_t)) {
    -		xlog_state_switch_iclogs(log, iclog, iclog->ic_size);
    -
    -		/* If I'm the only one writing to this iclog, sync it to disk */
    -		if (iclog->ic_refcnt == 1) {
    -			LOG_UNLOCK(log, s);
    -			if ((error = xlog_state_release_iclog(log, iclog)))
    -				return error;
    -		} else {
    -			iclog->ic_refcnt--;
    -			LOG_UNLOCK(log, s);
    -		}
    -		goto restart;
    -	}
    -
    -	/* Do we have enough room to write the full amount in the remainder
    -	 * of this iclog?  Or must we continue a write on the next iclog and
    -	 * mark this iclog as completely taken?  In the case where we switch
    -	 * iclogs (to mark it taken), this particular iclog will release/sync
    -	 * to disk in xlog_write().
    -	 */
    -	if (len <= iclog->ic_size - iclog->ic_offset) {
    -		*continued_write = 0;
    -		iclog->ic_offset += len;
    -	} else {
    -		*continued_write = 1;
    -		xlog_state_switch_iclogs(log, iclog, iclog->ic_size);
    -	}
    -	*iclogp = iclog;
    -
    -	ASSERT(iclog->ic_offset <= iclog->ic_size);
    -	LOG_UNLOCK(log, s);
    -
    -	*logoffsetp = log_offset;
    -	return 0;
    -}	/* xlog_state_get_iclog_space */
    -
    -/*
    - * Atomically get the log space required for a log ticket.
    - *
    - * Once a ticket gets put onto the reserveq, it will only return after
    - * the needed reservation is satisfied.
    - */
    -STATIC int
    -xlog_grant_log_space(xlog_t	   *log,
    -		     xlog_ticket_t *tic)
    -{
    -	int		 free_bytes;
    -	int		 need_bytes;
    -	SPLDECL(s);
    -#ifdef DEBUG
    -	xfs_lsn_t	 tail_lsn;
    -#endif
    -
    -
    -#ifdef DEBUG
    -	if (log->l_flags & XLOG_ACTIVE_RECOVERY)
    -		panic("grant Recovery problem");
    -#endif
    -
    -	/* Is there space or do we need to sleep? */
    -	s = GRANT_LOCK(log);
    -	xlog_trace_loggrant(log, tic, "xlog_grant_log_space: enter");
    -
    -	/* something is already sleeping; insert new transaction at end */
    -	if (log->l_reserve_headq) {
    -		xlog_ins_ticketq(&log->l_reserve_headq, tic);
    -		xlog_trace_loggrant(log, tic,
    -				    "xlog_grant_log_space: sleep 1");
    -		/*
    -		 * Gotta check this before going to sleep, while we're
    -		 * holding the grant lock.
    -		 */
    -		if (XLOG_FORCED_SHUTDOWN(log))
    -			goto error_return;
    -
    -		XFS_STATS_INC(xs_sleep_logspace);
    -		sv_wait(&tic->t_sema, PINOD|PLTWAIT, &log->l_grant_lock, s);
    -		/*
    -		 * If we got an error, and the filesystem is shutting down,
    -		 * we'll catch it down below. So just continue...
    -		 */
    -		xlog_trace_loggrant(log, tic,
    -				    "xlog_grant_log_space: wake 1");
    -		s = GRANT_LOCK(log);
    -	}
    -	if (tic->t_flags & XFS_LOG_PERM_RESERV)
    -		need_bytes = tic->t_unit_res*tic->t_ocnt;
    -	else
    -		need_bytes = tic->t_unit_res;
    -
    -redo:
    -	if (XLOG_FORCED_SHUTDOWN(log))
    -		goto error_return;
    -
    -	free_bytes = xlog_space_left(log, log->l_grant_reserve_cycle,
    -				     log->l_grant_reserve_bytes);
    -	if (free_bytes < need_bytes) {
    -		if ((tic->t_flags & XLOG_TIC_IN_Q) == 0)
    -			xlog_ins_ticketq(&log->l_reserve_headq, tic);
    -		xlog_trace_loggrant(log, tic,
    -				    "xlog_grant_log_space: sleep 2");
    -		XFS_STATS_INC(xs_sleep_logspace);
    -		sv_wait(&tic->t_sema, PINOD|PLTWAIT, &log->l_grant_lock, s);
    -
    -		if (XLOG_FORCED_SHUTDOWN(log)) {
    -			s = GRANT_LOCK(log);
    -			goto error_return;
    -		}
    -
    -		xlog_trace_loggrant(log, tic,
    -				    "xlog_grant_log_space: wake 2");
    -		xlog_grant_push_ail(log->l_mp, need_bytes);
    -		s = GRANT_LOCK(log);
    -		goto redo;
    -	} else if (tic->t_flags & XLOG_TIC_IN_Q)
    -		xlog_del_ticketq(&log->l_reserve_headq, tic);
    -
    -	/* we've got enough space */
    -	xlog_grant_add_space(log, need_bytes);
    -#ifdef DEBUG
    -	tail_lsn = log->l_tail_lsn;
    -	/*
    -	 * Check to make sure the grant write head didn't just over lap the
    -	 * tail.  If the cycles are the same, we can't be overlapping.
    -	 * Otherwise, make sure that the cycles differ by exactly one and
    -	 * check the byte count.
    -	 */
    -	if (CYCLE_LSN(tail_lsn) != log->l_grant_write_cycle) {
    -		ASSERT(log->l_grant_write_cycle-1 == CYCLE_LSN(tail_lsn));
    -		ASSERT(log->l_grant_write_bytes <= BBTOB(BLOCK_LSN(tail_lsn)));
    -	}
    -#endif
    -	xlog_trace_loggrant(log, tic, "xlog_grant_log_space: exit");
    -	xlog_verify_grant_head(log, 1);
    -	GRANT_UNLOCK(log, s);
    -	return 0;
    -
    - error_return:
    -	if (tic->t_flags & XLOG_TIC_IN_Q)
    -		xlog_del_ticketq(&log->l_reserve_headq, tic);
    -	xlog_trace_loggrant(log, tic, "xlog_grant_log_space: err_ret");
    -	/*
    -	 * If we are failing, make sure the ticket doesn't have any
    -	 * current reservations. We don't want to add this back when
    -	 * the ticket/transaction gets cancelled.
    -	 */
    -	tic->t_curr_res = 0;
    -	tic->t_cnt = 0; /* ungrant will give back unit_res * t_cnt. */
    -	GRANT_UNLOCK(log, s);
    -	return XFS_ERROR(EIO);
    -}	/* xlog_grant_log_space */
    -
    -
    -/*
    - * Replenish the byte reservation required by moving the grant write head.
    - *
    - *
    - */
    -STATIC int
    -xlog_regrant_write_log_space(xlog_t	   *log,
    -			     xlog_ticket_t *tic)
    -{
    -	SPLDECL(s);
    -	int		free_bytes, need_bytes;
    -	xlog_ticket_t	*ntic;
    -#ifdef DEBUG
    -	xfs_lsn_t	tail_lsn;
    -#endif
    -
    -	tic->t_curr_res = tic->t_unit_res;
    -	XLOG_TIC_RESET_RES(tic);
    -
    -	if (tic->t_cnt > 0)
    -		return 0;
    -
    -#ifdef DEBUG
    -	if (log->l_flags & XLOG_ACTIVE_RECOVERY)
    -		panic("regrant Recovery problem");
    -#endif
    -
    -	s = GRANT_LOCK(log);
    -	xlog_trace_loggrant(log, tic, "xlog_regrant_write_log_space: enter");
    -
    -	if (XLOG_FORCED_SHUTDOWN(log))
    -		goto error_return;
    -
    -	/* If there are other waiters on the queue then give them a
    -	 * chance at logspace before us. Wake up the first waiters,
    -	 * if we do not wake up all the waiters then go to sleep waiting
    -	 * for more free space, otherwise try to get some space for
    -	 * this transaction.
    -	 */
    -
    -	if ((ntic = log->l_write_headq)) {
    -		free_bytes = xlog_space_left(log, log->l_grant_write_cycle,
    -					     log->l_grant_write_bytes);
    -		do {
    -			ASSERT(ntic->t_flags & XLOG_TIC_PERM_RESERV);
    -
    -			if (free_bytes < ntic->t_unit_res)
    -				break;
    -			free_bytes -= ntic->t_unit_res;
    -			sv_signal(&ntic->t_sema);
    -			ntic = ntic->t_next;
    -		} while (ntic != log->l_write_headq);
    -
    -		if (ntic != log->l_write_headq) {
    -			if ((tic->t_flags & XLOG_TIC_IN_Q) == 0)
    -				xlog_ins_ticketq(&log->l_write_headq, tic);
    -
    -			xlog_trace_loggrant(log, tic,
    -				    "xlog_regrant_write_log_space: sleep 1");
    -			XFS_STATS_INC(xs_sleep_logspace);
    -			sv_wait(&tic->t_sema, PINOD|PLTWAIT,
    -				&log->l_grant_lock, s);
    -
    -			/* If we're shutting down, this tic is already
    -			 * off the queue */
    -			if (XLOG_FORCED_SHUTDOWN(log)) {
    -				s = GRANT_LOCK(log);
    -				goto error_return;
    -			}
    -
    -			xlog_trace_loggrant(log, tic,
    -				    "xlog_regrant_write_log_space: wake 1");
    -			xlog_grant_push_ail(log->l_mp, tic->t_unit_res);
    -			s = GRANT_LOCK(log);
    -		}
    -	}
    -
    -	need_bytes = tic->t_unit_res;
    -
    -redo:
    -	if (XLOG_FORCED_SHUTDOWN(log))
    -		goto error_return;
    -
    -	free_bytes = xlog_space_left(log, log->l_grant_write_cycle,
    -				     log->l_grant_write_bytes);
    -	if (free_bytes < need_bytes) {
    -		if ((tic->t_flags & XLOG_TIC_IN_Q) == 0)
    -			xlog_ins_ticketq(&log->l_write_headq, tic);
    -		XFS_STATS_INC(xs_sleep_logspace);
    -		sv_wait(&tic->t_sema, PINOD|PLTWAIT, &log->l_grant_lock, s);
    -
    -		/* If we're shutting down, this tic is already off the queue */
    -		if (XLOG_FORCED_SHUTDOWN(log)) {
    -			s = GRANT_LOCK(log);
    -			goto error_return;
    -		}
    -
    -		xlog_trace_loggrant(log, tic,
    -				    "xlog_regrant_write_log_space: wake 2");
    -		xlog_grant_push_ail(log->l_mp, need_bytes);
    -		s = GRANT_LOCK(log);
    -		goto redo;
    -	} else if (tic->t_flags & XLOG_TIC_IN_Q)
    -		xlog_del_ticketq(&log->l_write_headq, tic);
    -
    -	/* we've got enough space */
    -	xlog_grant_add_space_write(log, need_bytes);
    -#ifdef DEBUG
    -	tail_lsn = log->l_tail_lsn;
    -	if (CYCLE_LSN(tail_lsn) != log->l_grant_write_cycle) {
    -		ASSERT(log->l_grant_write_cycle-1 == CYCLE_LSN(tail_lsn));
    -		ASSERT(log->l_grant_write_bytes <= BBTOB(BLOCK_LSN(tail_lsn)));
    -	}
    -#endif
    -
    -	xlog_trace_loggrant(log, tic, "xlog_regrant_write_log_space: exit");
    -	xlog_verify_grant_head(log, 1);
    -	GRANT_UNLOCK(log, s);
    -	return 0;
    -
    -
    - error_return:
    -	if (tic->t_flags & XLOG_TIC_IN_Q)
    -		xlog_del_ticketq(&log->l_reserve_headq, tic);
    -	xlog_trace_loggrant(log, tic, "xlog_regrant_write_log_space: err_ret");
    -	/*
    -	 * If we are failing, make sure the ticket doesn't have any
    -	 * current reservations. We don't want to add this back when
    -	 * the ticket/transaction gets cancelled.
    -	 */
    -	tic->t_curr_res = 0;
    -	tic->t_cnt = 0; /* ungrant will give back unit_res * t_cnt. */
    -	GRANT_UNLOCK(log, s);
    -	return XFS_ERROR(EIO);
    -}	/* xlog_regrant_write_log_space */
    -
    -
    -/* The first cnt-1 times through here we don't need to
    - * move the grant write head because the permanent
    - * reservation has reserved cnt times the unit amount.
    - * Release part of current permanent unit reservation and
    - * reset current reservation to be one units worth.  Also
    - * move grant reservation head forward.
    - */
    -STATIC void
    -xlog_regrant_reserve_log_space(xlog_t	     *log,
    -			       xlog_ticket_t *ticket)
    -{
    -	SPLDECL(s);
    -
    -	xlog_trace_loggrant(log, ticket,
    -			    "xlog_regrant_reserve_log_space: enter");
    -	if (ticket->t_cnt > 0)
    -		ticket->t_cnt--;
    -
    -	s = GRANT_LOCK(log);
    -	xlog_grant_sub_space(log, ticket->t_curr_res);
    -	ticket->t_curr_res = ticket->t_unit_res;
    -	XLOG_TIC_RESET_RES(ticket);
    -	xlog_trace_loggrant(log, ticket,
    -			    "xlog_regrant_reserve_log_space: sub current res");
    -	xlog_verify_grant_head(log, 1);
    -
    -	/* just return if we still have some of the pre-reserved space */
    -	if (ticket->t_cnt > 0) {
    -		GRANT_UNLOCK(log, s);
    -		return;
    -	}
    -
    -	xlog_grant_add_space_reserve(log, ticket->t_unit_res);
    -	xlog_trace_loggrant(log, ticket,
    -			    "xlog_regrant_reserve_log_space: exit");
    -	xlog_verify_grant_head(log, 0);
    -	GRANT_UNLOCK(log, s);
    -	ticket->t_curr_res = ticket->t_unit_res;
    -	XLOG_TIC_RESET_RES(ticket);
    -}	/* xlog_regrant_reserve_log_space */
    -
    -
    -/*
    - * Give back the space left from a reservation.
    - *
    - * All the information we need to make a correct determination of space left
    - * is present.  For non-permanent reservations, things are quite easy.  The
    - * count should have been decremented to zero.  We only need to deal with the
    - * space remaining in the current reservation part of the ticket.  If the
    - * ticket contains a permanent reservation, there may be left over space which
    - * needs to be released.  A count of N means that N-1 refills of the current
    - * reservation can be done before we need to ask for more space.  The first
    - * one goes to fill up the first current reservation.  Once we run out of
    - * space, the count will stay at zero and the only space remaining will be
    - * in the current reservation field.
    - */
    -STATIC void
    -xlog_ungrant_log_space(xlog_t	     *log,
    -		       xlog_ticket_t *ticket)
    -{
    -	SPLDECL(s);
    -
    -	if (ticket->t_cnt > 0)
    -		ticket->t_cnt--;
    -
    -	s = GRANT_LOCK(log);
    -	xlog_trace_loggrant(log, ticket, "xlog_ungrant_log_space: enter");
    -
    -	xlog_grant_sub_space(log, ticket->t_curr_res);
    -
    -	xlog_trace_loggrant(log, ticket, "xlog_ungrant_log_space: sub current");
    -
    -	/* If this is a permanent reservation ticket, we may be able to free
    -	 * up more space based on the remaining count.
    -	 */
    -	if (ticket->t_cnt > 0) {
    -		ASSERT(ticket->t_flags & XLOG_TIC_PERM_RESERV);
    -		xlog_grant_sub_space(log, ticket->t_unit_res*ticket->t_cnt);
    -	}
    -
    -	xlog_trace_loggrant(log, ticket, "xlog_ungrant_log_space: exit");
    -	xlog_verify_grant_head(log, 1);
    -	GRANT_UNLOCK(log, s);
    -	xfs_log_move_tail(log->l_mp, 1);
    -}	/* xlog_ungrant_log_space */
    -
    -
    -/*
    - * Atomically put back used ticket.
    - */
    -void
    -xlog_state_put_ticket(xlog_t	    *log,
    -		      xlog_ticket_t *tic)
    -{
    -	unsigned long s;
    -
    -	s = LOG_LOCK(log);
    -	xlog_ticket_put(log, tic);
    -	LOG_UNLOCK(log, s);
    -}	/* xlog_state_put_ticket */
    -
    -/*
    - * Flush iclog to disk if this is the last reference to the given iclog and
    - * the WANT_SYNC bit is set.
    - *
    - * When this function is entered, the iclog is not necessarily in the
    - * WANT_SYNC state.  It may be sitting around waiting to get filled.
    - *
    - *
    - */
    -int
    -xlog_state_release_iclog(xlog_t		*log,
    -			 xlog_in_core_t	*iclog)
    -{
    -	SPLDECL(s);
    -	int		sync = 0;	/* do we sync? */
    -
    -	xlog_assign_tail_lsn(log->l_mp);
    -
    -	s = LOG_LOCK(log);
    -
    -	if (iclog->ic_state & XLOG_STATE_IOERROR) {
    -		LOG_UNLOCK(log, s);
    -		return XFS_ERROR(EIO);
    -	}
    -
    -	ASSERT(iclog->ic_refcnt > 0);
    -	ASSERT(iclog->ic_state == XLOG_STATE_ACTIVE ||
    -	       iclog->ic_state == XLOG_STATE_WANT_SYNC);
    -
    -	if (--iclog->ic_refcnt == 0 &&
    -	    iclog->ic_state == XLOG_STATE_WANT_SYNC) {
    -		sync++;
    -		iclog->ic_state = XLOG_STATE_SYNCING;
    -		INT_SET(iclog->ic_header.h_tail_lsn, ARCH_CONVERT, log->l_tail_lsn);
    -		xlog_verify_tail_lsn(log, iclog, log->l_tail_lsn);
    -		/* cycle incremented when incrementing curr_block */
    -	}
    -
    -	LOG_UNLOCK(log, s);
    -
    -	/*
    -	 * We let the log lock go, so it's possible that we hit a log I/O
    -	 * error or some other SHUTDOWN condition that marks the iclog
    -	 * as XLOG_STATE_IOERROR before the bwrite. However, we know that
    -	 * this iclog has consistent data, so we ignore IOERROR
    -	 * flags after this point.
    -	 */
    -	if (sync) {
    -		return xlog_sync(log, iclog);
    -	}
    -	return 0;
    -
    -}	/* xlog_state_release_iclog */
    -
    -
    -/*
    - * This routine will mark the current iclog in the ring as WANT_SYNC
    - * and move the current iclog pointer to the next iclog in the ring.
    - * When this routine is called from xlog_state_get_iclog_space(), the
    - * exact size of the iclog has not yet been determined.  All we know is
    - * that every data block.  We have run out of space in this log record.
    - */
    -STATIC void
    -xlog_state_switch_iclogs(xlog_t		*log,
    -			 xlog_in_core_t *iclog,
    -			 int		eventual_size)
    -{
    -	ASSERT(iclog->ic_state == XLOG_STATE_ACTIVE);
    -	if (!eventual_size)
    -		eventual_size = iclog->ic_offset;
    -	iclog->ic_state = XLOG_STATE_WANT_SYNC;
    -	INT_SET(iclog->ic_header.h_prev_block, ARCH_CONVERT, log->l_prev_block);
    -	log->l_prev_block = log->l_curr_block;
    -	log->l_prev_cycle = log->l_curr_cycle;
    -
    -	/* roll log?: ic_offset changed later */
    -	log->l_curr_block += BTOBB(eventual_size)+BTOBB(log->l_iclog_hsize);
    -
    -	/* Round up to next log-sunit */
    -	if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb) &&
    -	    log->l_mp->m_sb.sb_logsunit > 1) {
    -		__uint32_t sunit_bb = BTOBB(log->l_mp->m_sb.sb_logsunit);
    -		log->l_curr_block = roundup(log->l_curr_block, sunit_bb);
    -	}
    -
    -	if (log->l_curr_block >= log->l_logBBsize) {
    -		log->l_curr_cycle++;
    -		if (log->l_curr_cycle == XLOG_HEADER_MAGIC_NUM)
    -			log->l_curr_cycle++;
    -		log->l_curr_block -= log->l_logBBsize;
    -		ASSERT(log->l_curr_block >= 0);
    -	}
    -	ASSERT(iclog == log->l_iclog);
    -	log->l_iclog = iclog->ic_next;
    -}	/* xlog_state_switch_iclogs */
    -
    -
    -/*
    - * Write out all data in the in-core log as of this exact moment in time.
    - *
    - * Data may be written to the in-core log during this call.  However,
    - * we don't guarantee this data will be written out.  A change from past
    - * implementation means this routine will *not* write out zero length LRs.
    - *
    - * Basically, we try and perform an intelligent scan of the in-core logs.
    - * If we determine there is no flushable data, we just return.  There is no
    - * flushable data if:
    - *
    - *	1. the current iclog is active and has no data; the previous iclog
    - *		is in the active or dirty state.
    - *	2. the current iclog is drity, and the previous iclog is in the
    - *		active or dirty state.
    - *
    - * We may sleep (call psema) if:
    - *
    - *	1. the current iclog is not in the active nor dirty state.
    - *	2. the current iclog dirty, and the previous iclog is not in the
    - *		active nor dirty state.
    - *	3. the current iclog is active, and there is another thread writing
    - *		to this particular iclog.
    - *	4. a) the current iclog is active and has no other writers
    - *	   b) when we return from flushing out this iclog, it is still
    - *		not in the active nor dirty state.
    - */
    -STATIC int
    -xlog_state_sync_all(xlog_t *log, uint flags, int *log_flushed)
    -{
    -	xlog_in_core_t	*iclog;
    -	xfs_lsn_t	lsn;
    -	SPLDECL(s);
    -
    -	s = LOG_LOCK(log);
    -
    -	iclog = log->l_iclog;
    -	if (iclog->ic_state & XLOG_STATE_IOERROR) {
    -		LOG_UNLOCK(log, s);
    -		return XFS_ERROR(EIO);
    -	}
    -
    -	/* If the head iclog is not active nor dirty, we just attach
    -	 * ourselves to the head and go to sleep.
    -	 */
    -	if (iclog->ic_state == XLOG_STATE_ACTIVE ||
    -	    iclog->ic_state == XLOG_STATE_DIRTY) {
    -		/*
    -		 * If the head is dirty or (active and empty), then
    -		 * we need to look at the previous iclog.  If the previous
    -		 * iclog is active or dirty we are done.  There is nothing
    -		 * to sync out.  Otherwise, we attach ourselves to the
    -		 * previous iclog and go to sleep.
    -		 */
    -		if (iclog->ic_state == XLOG_STATE_DIRTY ||
    -		    (iclog->ic_refcnt == 0 && iclog->ic_offset == 0)) {
    -			iclog = iclog->ic_prev;
    -			if (iclog->ic_state == XLOG_STATE_ACTIVE ||
    -			    iclog->ic_state == XLOG_STATE_DIRTY)
    -				goto no_sleep;
    -			else
    -				goto maybe_sleep;
    -		} else {
    -			if (iclog->ic_refcnt == 0) {
    -				/* We are the only one with access to this
    -				 * iclog.  Flush it out now.  There should
    -				 * be a roundoff of zero to show that someone
    -				 * has already taken care of the roundoff from
    -				 * the previous sync.
    -				 */
    -				iclog->ic_refcnt++;
    -				lsn = INT_GET(iclog->ic_header.h_lsn, ARCH_CONVERT);
    -				xlog_state_switch_iclogs(log, iclog, 0);
    -				LOG_UNLOCK(log, s);
    -
    -				if (xlog_state_release_iclog(log, iclog))
    -					return XFS_ERROR(EIO);
    -				*log_flushed = 1;
    -				s = LOG_LOCK(log);
    -				if (INT_GET(iclog->ic_header.h_lsn, ARCH_CONVERT) == lsn &&
    -				    iclog->ic_state != XLOG_STATE_DIRTY)
    -					goto maybe_sleep;
    -				else
    -					goto no_sleep;
    -			} else {
    -				/* Someone else is writing to this iclog.
    -				 * Use its call to flush out the data.  However,
    -				 * the other thread may not force out this LR,
    -				 * so we mark it WANT_SYNC.
    -				 */
    -				xlog_state_switch_iclogs(log, iclog, 0);
    -				goto maybe_sleep;
    -			}
    -		}
    -	}
    -
    -	/* By the time we come around again, the iclog could've been filled
    -	 * which would give it another lsn.  If we have a new lsn, just
    -	 * return because the relevant data has been flushed.
    -	 */
    -maybe_sleep:
    -	if (flags & XFS_LOG_SYNC) {
    -		/*
    -		 * We must check if we're shutting down here, before
    -		 * we wait, while we're holding the LOG_LOCK.
    -		 * Then we check again after waking up, in case our
    -		 * sleep was disturbed by a bad news.
    -		 */
    -		if (iclog->ic_state & XLOG_STATE_IOERROR) {
    -			LOG_UNLOCK(log, s);
    -			return XFS_ERROR(EIO);
    -		}
    -		XFS_STATS_INC(xs_log_force_sleep);
    -		sv_wait(&iclog->ic_forcesema, PINOD, &log->l_icloglock, s);
    -		/*
    -		 * No need to grab the log lock here since we're
    -		 * only deciding whether or not to return EIO
    -		 * and the memory read should be atomic.
    -		 */
    -		if (iclog->ic_state & XLOG_STATE_IOERROR)
    -			return XFS_ERROR(EIO);
    -		*log_flushed = 1;
    -
    -	} else {
    -
    -no_sleep:
    -		LOG_UNLOCK(log, s);
    -	}
    -	return 0;
    -}	/* xlog_state_sync_all */
    -
    -
    -/*
    - * Used by code which implements synchronous log forces.
    - *
    - * Find in-core log with lsn.
    - *	If it is in the DIRTY state, just return.
    - *	If it is in the ACTIVE state, move the in-core log into the WANT_SYNC
    - *		state and go to sleep or return.
    - *	If it is in any other state, go to sleep or return.
    - *
    - * If filesystem activity goes to zero, the iclog will get flushed only by
    - * bdflush().
    - */
    -int
    -xlog_state_sync(xlog_t	  *log,
    -		xfs_lsn_t lsn,
    -		uint	  flags,
    -		int	  *log_flushed)
    -{
    -    xlog_in_core_t	*iclog;
    -    int			already_slept = 0;
    -    SPLDECL(s);
    -
    -
    -try_again:
    -    s = LOG_LOCK(log);
    -    iclog = log->l_iclog;
    -
    -    if (iclog->ic_state & XLOG_STATE_IOERROR) {
    -	    LOG_UNLOCK(log, s);
    -	    return XFS_ERROR(EIO);
    -    }
    -
    -    do {
    -	if (INT_GET(iclog->ic_header.h_lsn, ARCH_CONVERT) != lsn) {
    -	    iclog = iclog->ic_next;
    -	    continue;
    -	}
    -
    -	if (iclog->ic_state == XLOG_STATE_DIRTY) {
    -		LOG_UNLOCK(log, s);
    -		return 0;
    -	}
    -
    -	if (iclog->ic_state == XLOG_STATE_ACTIVE) {
    -		/*
    -		 * We sleep here if we haven't already slept (e.g.
    -		 * this is the first time we've looked at the correct
    -		 * iclog buf) and the buffer before us is going to
    -		 * be sync'ed. The reason for this is that if we
    -		 * are doing sync transactions here, by waiting for
    -		 * the previous I/O to complete, we can allow a few
    -		 * more transactions into this iclog before we close
    -		 * it down.
    -		 *
    -		 * Otherwise, we mark the buffer WANT_SYNC, and bump
    -		 * up the refcnt so we can release the log (which drops
    -		 * the ref count).  The state switch keeps new transaction
    -		 * commits from using this buffer.  When the current commits
    -		 * finish writing into the buffer, the refcount will drop to
    -		 * zero and the buffer will go out then.
    -		 */
    -		if (!already_slept &&
    -		    (iclog->ic_prev->ic_state & (XLOG_STATE_WANT_SYNC |
    -						 XLOG_STATE_SYNCING))) {
    -			ASSERT(!(iclog->ic_state & XLOG_STATE_IOERROR));
    -			XFS_STATS_INC(xs_log_force_sleep);
    -			sv_wait(&iclog->ic_prev->ic_writesema, PSWP,
    -				&log->l_icloglock, s);
    -			*log_flushed = 1;
    -			already_slept = 1;
    -			goto try_again;
    -		} else {
    -			iclog->ic_refcnt++;
    -			xlog_state_switch_iclogs(log, iclog, 0);
    -			LOG_UNLOCK(log, s);
    -			if (xlog_state_release_iclog(log, iclog))
    -				return XFS_ERROR(EIO);
    -			*log_flushed = 1;
    -			s = LOG_LOCK(log);
    -		}
    -	}
    -
    -	if ((flags & XFS_LOG_SYNC) && /* sleep */
    -	    !(iclog->ic_state & (XLOG_STATE_ACTIVE | XLOG_STATE_DIRTY))) {
    -
    -		/*
    -		 * Don't wait on the forcesema if we know that we've
    -		 * gotten a log write error.
    -		 */
    -		if (iclog->ic_state & XLOG_STATE_IOERROR) {
    -			LOG_UNLOCK(log, s);
    -			return XFS_ERROR(EIO);
    -		}
    -		XFS_STATS_INC(xs_log_force_sleep);
    -		sv_wait(&iclog->ic_forcesema, PSWP, &log->l_icloglock, s);
    -		/*
    -		 * No need to grab the log lock here since we're
    -		 * only deciding whether or not to return EIO
    -		 * and the memory read should be atomic.
    -		 */
    -		if (iclog->ic_state & XLOG_STATE_IOERROR)
    -			return XFS_ERROR(EIO);
    -		*log_flushed = 1;
    -	} else {		/* just return */
    -		LOG_UNLOCK(log, s);
    -	}
    -	return 0;
    -
    -    } while (iclog != log->l_iclog);
    -
    -    LOG_UNLOCK(log, s);
    -    return 0;
    -}	/* xlog_state_sync */
    -
    -
    -/*
    - * Called when we want to mark the current iclog as being ready to sync to
    - * disk.
    - */
    -void
    -xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog)
    -{
    -	SPLDECL(s);
    -
    -	s = LOG_LOCK(log);
    -
    -	if (iclog->ic_state == XLOG_STATE_ACTIVE) {
    -		xlog_state_switch_iclogs(log, iclog, 0);
    -	} else {
    -		ASSERT(iclog->ic_state &
    -			(XLOG_STATE_WANT_SYNC|XLOG_STATE_IOERROR));
    -	}
    -
    -	LOG_UNLOCK(log, s);
    -}	/* xlog_state_want_sync */
    -
    -
    -
    -/*****************************************************************************
    - *
    - *		TICKET functions
    - *
    - *****************************************************************************
    - */
    -
    -/*
    - *	Algorithm doesn't take into account page size. ;-(
    - */
    -STATIC void
    -xlog_state_ticket_alloc(xlog_t *log)
    -{
    -	xlog_ticket_t	*t_list;
    -	xlog_ticket_t	*next;
    -	xfs_caddr_t	buf;
    -	uint		i = (NBPP / sizeof(xlog_ticket_t)) - 2;
    -	SPLDECL(s);
    -
    -	/*
    -	 * The kmem_zalloc may sleep, so we shouldn't be holding the
    -	 * global lock.  XXXmiken: may want to use zone allocator.
    -	 */
    -	buf = (xfs_caddr_t) kmem_zalloc(NBPP, KM_SLEEP);
    -
    -	s = LOG_LOCK(log);
    -
    -	/* Attach 1st ticket to Q, so we can keep track of allocated memory */
    -	t_list = (xlog_ticket_t *)buf;
    -	t_list->t_next = log->l_unmount_free;
    -	log->l_unmount_free = t_list++;
    -	log->l_ticket_cnt++;
    -	log->l_ticket_tcnt++;
    -
    -	/* Next ticket becomes first ticket attached to ticket free list */
    -	if (log->l_freelist != NULL) {
    -		ASSERT(log->l_tail != NULL);
    -		log->l_tail->t_next = t_list;
    -	} else {
    -		log->l_freelist = t_list;
    -	}
    -	log->l_ticket_cnt++;
    -	log->l_ticket_tcnt++;
    -
    -	/* Cycle through rest of alloc'ed memory, building up free Q */
    -	for ( ; i > 0; i--) {
    -		next = t_list + 1;
    -		t_list->t_next = next;
    -		t_list = next;
    -		log->l_ticket_cnt++;
    -		log->l_ticket_tcnt++;
    -	}
    -	t_list->t_next = NULL;
    -	log->l_tail = t_list;
    -	LOG_UNLOCK(log, s);
    -}	/* xlog_state_ticket_alloc */
    -
    -
    -/*
    - * Put ticket into free list
    - *
    - * Assumption: log lock is held around this call.
    - */
    -STATIC void
    -xlog_ticket_put(xlog_t		*log,
    -		xlog_ticket_t	*ticket)
    -{
    -	sv_destroy(&ticket->t_sema);
    -
    -	/*
    -	 * Don't think caching will make that much difference.  It's
    -	 * more important to make debug easier.
    -	 */
    -#if 0
    -	/* real code will want to use LIFO for caching */
    -	ticket->t_next = log->l_freelist;
    -	log->l_freelist = ticket;
    -	/* no need to clear fields */
    -#else
    -	/* When we debug, it is easier if tickets are cycled */
    -	ticket->t_next     = NULL;
    -	if (log->l_tail != 0) {
    -		log->l_tail->t_next = ticket;
    -	} else {
    -		ASSERT(log->l_freelist == 0);
    -		log->l_freelist = ticket;
    -	}
    -	log->l_tail	    = ticket;
    -#endif /* DEBUG */
    -	log->l_ticket_cnt++;
    -}	/* xlog_ticket_put */
    -
    -
    -/*
    - * Grab ticket off freelist or allocation some more
    - */
    -xlog_ticket_t *
    -xlog_ticket_get(xlog_t		*log,
    -		int		unit_bytes,
    -		int		cnt,
    -		char		client,
    -		uint		xflags)
    -{
    -	xlog_ticket_t	*tic;
    -	uint		num_headers;
    -	SPLDECL(s);
    -
    - alloc:
    -	if (log->l_freelist == NULL)
    -		xlog_state_ticket_alloc(log);		/* potentially sleep */
    -
    -	s = LOG_LOCK(log);
    -	if (log->l_freelist == NULL) {
    -		LOG_UNLOCK(log, s);
    -		goto alloc;
    -	}
    -	tic		= log->l_freelist;
    -	log->l_freelist	= tic->t_next;
    -	if (log->l_freelist == NULL)
    -		log->l_tail = NULL;
    -	log->l_ticket_cnt--;
    -	LOG_UNLOCK(log, s);
    -
    -	/*
    -	 * Permanent reservations have up to 'cnt'-1 active log operations
    -	 * in the log.  A unit in this case is the amount of space for one
    -	 * of these log operations.  Normal reservations have a cnt of 1
    -	 * and their unit amount is the total amount of space required.
    -	 *
    -	 * The following lines of code account for non-transaction data
    -	 * which occupy space in the on-disk log.
    -	 *
    -	 * Normal form of a transaction is:
    -	 * ...
    -	 * and then there are LR hdrs, split-recs and roundoff at end of syncs.
    -	 *
    -	 * We need to account for all the leadup data and trailer data
    -	 * around the transaction data.
    -	 * And then we need to account for the worst case in terms of using
    -	 * more space.
    -	 * The worst case will happen if:
    -	 * - the placement of the transaction happens to be such that the
    -	 *   roundoff is at its maximum
    -	 * - the transaction data is synced before the commit record is synced
    -	 *   i.e.  | 
    -	 *   Therefore the commit record is in its own Log Record.
    -	 *   This can happen as the commit record is called with its
    -	 *   own region to xlog_write().
    -	 *   This then means that in the worst case, roundoff can happen for
    -	 *   the commit-rec as well.
    -	 *   The commit-rec is smaller than padding in this scenario and so it is
    -	 *   not added separately.
    -	 */
    -
    -	/* for trans header */
    -	unit_bytes += sizeof(xlog_op_header_t);
    -	unit_bytes += sizeof(xfs_trans_header_t);
    -
    -	/* for start-rec */
    -	unit_bytes += sizeof(xlog_op_header_t);
    -
    -	/* for LR headers */
    -	num_headers = ((unit_bytes + log->l_iclog_size-1) >> log->l_iclog_size_log);
    -	unit_bytes += log->l_iclog_hsize * num_headers;
    -
    -	/* for commit-rec LR header - note: padding will subsume the ophdr */
    -	unit_bytes += log->l_iclog_hsize;
    -
    -	/* for split-recs - ophdrs added when data split over LRs */
    -	unit_bytes += sizeof(xlog_op_header_t) * num_headers;
    -
    -	/* for roundoff padding for transaction data and one for commit record */
    -	if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb) &&
    -	    log->l_mp->m_sb.sb_logsunit > 1) {
    -		/* log su roundoff */
    -		unit_bytes += 2*log->l_mp->m_sb.sb_logsunit;
    -	} else {
    -		/* BB roundoff */
    -		unit_bytes += 2*BBSIZE;
    -        }
    -
    -	tic->t_unit_res		= unit_bytes;
    -	tic->t_curr_res		= unit_bytes;
    -	tic->t_cnt		= cnt;
    -	tic->t_ocnt		= cnt;
    -	tic->t_tid		= (xlog_tid_t)((__psint_t)tic & 0xffffffff);
    -	tic->t_clientid		= client;
    -	tic->t_flags		= XLOG_TIC_INITED;
    -	tic->t_trans_type	= 0;
    -	if (xflags & XFS_LOG_PERM_RESERV)
    -		tic->t_flags |= XLOG_TIC_PERM_RESERV;
    -	sv_init(&(tic->t_sema), SV_DEFAULT, "logtick");
    -
    -	XLOG_TIC_RESET_RES(tic);
    -
    -	return tic;
    -}	/* xlog_ticket_get */
    -
    -
    -/******************************************************************************
    - *
    - *		Log debug routines
    - *
    - ******************************************************************************
    - */
    -#if defined(DEBUG)
    -/*
    - * Make sure that the destination ptr is within the valid data region of
    - * one of the iclogs.  This uses backup pointers stored in a different
    - * part of the log in case we trash the log structure.
    - */
    -void
    -xlog_verify_dest_ptr(xlog_t     *log,
    -		     __psint_t  ptr)
    -{
    -	int i;
    -	int good_ptr = 0;
    -
    -	for (i=0; i < log->l_iclog_bufs; i++) {
    -		if (ptr >= (__psint_t)log->l_iclog_bak[i] &&
    -		    ptr <= (__psint_t)log->l_iclog_bak[i]+log->l_iclog_size)
    -			good_ptr++;
    -	}
    -	if (! good_ptr)
    -		xlog_panic("xlog_verify_dest_ptr: invalid ptr");
    -}	/* xlog_verify_dest_ptr */
    -
    -STATIC void
    -xlog_verify_grant_head(xlog_t *log, int equals)
    -{
    -    if (log->l_grant_reserve_cycle == log->l_grant_write_cycle) {
    -	if (equals)
    -	    ASSERT(log->l_grant_reserve_bytes >= log->l_grant_write_bytes);
    -	else
    -	    ASSERT(log->l_grant_reserve_bytes > log->l_grant_write_bytes);
    -    } else {
    -	ASSERT(log->l_grant_reserve_cycle-1 == log->l_grant_write_cycle);
    -	ASSERT(log->l_grant_write_bytes >= log->l_grant_reserve_bytes);
    -    }
    -}	/* xlog_verify_grant_head */
    -
    -/* check if it will fit */
    -STATIC void
    -xlog_verify_tail_lsn(xlog_t	    *log,
    -		     xlog_in_core_t *iclog,
    -		     xfs_lsn_t	    tail_lsn)
    -{
    -    int blocks;
    -
    -    if (CYCLE_LSN(tail_lsn) == log->l_prev_cycle) {
    -	blocks =
    -	    log->l_logBBsize - (log->l_prev_block - BLOCK_LSN(tail_lsn));
    -	if (blocks < BTOBB(iclog->ic_offset)+BTOBB(log->l_iclog_hsize))
    -	    xlog_panic("xlog_verify_tail_lsn: ran out of log space");
    -    } else {
    -	ASSERT(CYCLE_LSN(tail_lsn)+1 == log->l_prev_cycle);
    -
    -	if (BLOCK_LSN(tail_lsn) == log->l_prev_block)
    -	    xlog_panic("xlog_verify_tail_lsn: tail wrapped");
    -
    -	blocks = BLOCK_LSN(tail_lsn) - log->l_prev_block;
    -	if (blocks < BTOBB(iclog->ic_offset) + 1)
    -	    xlog_panic("xlog_verify_tail_lsn: ran out of log space");
    -    }
    -}	/* xlog_verify_tail_lsn */
    -
    -/*
    - * Perform a number of checks on the iclog before writing to disk.
    - *
    - * 1. Make sure the iclogs are still circular
    - * 2. Make sure we have a good magic number
    - * 3. Make sure we don't have magic numbers in the data
    - * 4. Check fields of each log operation header for:
    - *	A. Valid client identifier
    - *	B. tid ptr value falls in valid ptr space (user space code)
    - *	C. Length in log record header is correct according to the
    - *		individual operation headers within record.
    - * 5. When a bwrite will occur within 5 blocks of the front of the physical
    - *	log, check the preceding blocks of the physical log to make sure all
    - *	the cycle numbers agree with the current cycle number.
    - */
    -STATIC void
    -xlog_verify_iclog(xlog_t	 *log,
    -		  xlog_in_core_t *iclog,
    -		  int		 count,
    -		  boolean_t	 syncing)
    -{
    -	xlog_op_header_t	*ophead;
    -	xlog_in_core_t		*icptr;
    -	xlog_in_core_2_t	*xhdr;
    -	xfs_caddr_t		ptr;
    -	xfs_caddr_t		base_ptr;
    -	__psint_t		field_offset;
    -	__uint8_t		clientid;
    -	int			len, i, j, k, op_len;
    -	int			idx;
    -	SPLDECL(s);
    -
    -	/* check validity of iclog pointers */
    -	s = LOG_LOCK(log);
    -	icptr = log->l_iclog;
    -	for (i=0; i < log->l_iclog_bufs; i++) {
    -		if (icptr == 0)
    -			xlog_panic("xlog_verify_iclog: invalid ptr");
    -		icptr = icptr->ic_next;
    -	}
    -	if (icptr != log->l_iclog)
    -		xlog_panic("xlog_verify_iclog: corrupt iclog ring");
    -	LOG_UNLOCK(log, s);
    -
    -	/* check log magic numbers */
    -	ptr = (xfs_caddr_t) &(iclog->ic_header);
    -	if (INT_GET(*(uint *)ptr, ARCH_CONVERT) != XLOG_HEADER_MAGIC_NUM)
    -		xlog_panic("xlog_verify_iclog: invalid magic num");
    -
    -	for (ptr += BBSIZE; ptr < ((xfs_caddr_t)&(iclog->ic_header))+count;
    -	     ptr += BBSIZE) {
    -		if (INT_GET(*(uint *)ptr, ARCH_CONVERT) == XLOG_HEADER_MAGIC_NUM)
    -			xlog_panic("xlog_verify_iclog: unexpected magic num");
    -	}
    -
    -	/* check fields */
    -	len = INT_GET(iclog->ic_header.h_num_logops, ARCH_CONVERT);
    -	ptr = iclog->ic_datap;
    -	base_ptr = ptr;
    -	ophead = (xlog_op_header_t *)ptr;
    -	xhdr = (xlog_in_core_2_t *)&iclog->ic_header;
    -	for (i = 0; i < len; i++) {
    -		ophead = (xlog_op_header_t *)ptr;
    -
    -		/* clientid is only 1 byte */
    -		field_offset = (__psint_t)
    -			       ((xfs_caddr_t)&(ophead->oh_clientid) - base_ptr);
    -		if (syncing == B_FALSE || (field_offset & 0x1ff)) {
    -			clientid = ophead->oh_clientid;
    -		} else {
    -			idx = BTOBBT((xfs_caddr_t)&(ophead->oh_clientid) - iclog->ic_datap);
    -			if (idx >= (XLOG_HEADER_CYCLE_SIZE / BBSIZE)) {
    -				j = idx / (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
    -				k = idx % (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
    -				clientid = GET_CLIENT_ID(xhdr[j].hic_xheader.xh_cycle_data[k], ARCH_CONVERT);
    -			} else {
    -				clientid = GET_CLIENT_ID(iclog->ic_header.h_cycle_data[idx], ARCH_CONVERT);
    -			}
    -		}
    -		if (clientid != XFS_TRANSACTION && clientid != XFS_LOG)
    -			cmn_err(CE_WARN, "xlog_verify_iclog: "
    -				"invalid clientid %d op 0x%p offset 0x%lx",
    -				clientid, ophead, (unsigned long)field_offset);
    -
    -		/* check length */
    -		field_offset = (__psint_t)
    -			       ((xfs_caddr_t)&(ophead->oh_len) - base_ptr);
    -		if (syncing == B_FALSE || (field_offset & 0x1ff)) {
    -			op_len = INT_GET(ophead->oh_len, ARCH_CONVERT);
    -		} else {
    -			idx = BTOBBT((__psint_t)&ophead->oh_len -
    -				    (__psint_t)iclog->ic_datap);
    -			if (idx >= (XLOG_HEADER_CYCLE_SIZE / BBSIZE)) {
    -				j = idx / (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
    -				k = idx % (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
    -				op_len = INT_GET(xhdr[j].hic_xheader.xh_cycle_data[k], ARCH_CONVERT);
    -			} else {
    -				op_len = INT_GET(iclog->ic_header.h_cycle_data[idx], ARCH_CONVERT);
    -			}
    -		}
    -		ptr += sizeof(xlog_op_header_t) + op_len;
    -	}
    -}	/* xlog_verify_iclog */
    -#endif
    -
    -/*
    - * Mark all iclogs IOERROR. LOG_LOCK is held by the caller.
    - */
    -STATIC int
    -xlog_state_ioerror(
    -	xlog_t	*log)
    -{
    -	xlog_in_core_t	*iclog, *ic;
    -
    -	iclog = log->l_iclog;
    -	if (! (iclog->ic_state & XLOG_STATE_IOERROR)) {
    -		/*
    -		 * Mark all the incore logs IOERROR.
    -		 * From now on, no log flushes will result.
    -		 */
    -		ic = iclog;
    -		do {
    -			ic->ic_state = XLOG_STATE_IOERROR;
    -			ic = ic->ic_next;
    -		} while (ic != iclog);
    -		return 0;
    -	}
    -	/*
    -	 * Return non-zero, if state transition has already happened.
    -	 */
    -	return 1;
    -}
    -
    -/*
    - * This is called from xfs_force_shutdown, when we're forcibly
    - * shutting down the filesystem, typically because of an IO error.
    - * Our main objectives here are to make sure that:
    - *	a. the filesystem gets marked 'SHUTDOWN' for all interested
    - *	   parties to find out, 'atomically'.
    - *	b. those who're sleeping on log reservations, pinned objects and
    - *	    other resources get woken up, and be told the bad news.
    - *	c. nothing new gets queued up after (a) and (b) are done.
    - *	d. if !logerror, flush the iclogs to disk, then seal them off
    - *	   for business.
    - */
    -int
    -xfs_log_force_umount(
    -	struct xfs_mount	*mp,
    -	int			logerror)
    -{
    -	xlog_ticket_t	*tic;
    -	xlog_t		*log;
    -	int		retval;
    -	int		dummy;
    -	SPLDECL(s);
    -	SPLDECL(s2);
    -
    -	log = mp->m_log;
    -
    -	/*
    -	 * If this happens during log recovery, don't worry about
    -	 * locking; the log isn't open for business yet.
    -	 */
    -	if (!log ||
    -	    log->l_flags & XLOG_ACTIVE_RECOVERY) {
    -		mp->m_flags |= XFS_MOUNT_FS_SHUTDOWN;
    -		XFS_BUF_DONE(mp->m_sb_bp);
    -		return 0;
    -	}
    -
    -	/*
    -	 * Somebody could've already done the hard work for us.
    -	 * No need to get locks for this.
    -	 */
    -	if (logerror && log->l_iclog->ic_state & XLOG_STATE_IOERROR) {
    -		ASSERT(XLOG_FORCED_SHUTDOWN(log));
    -		return 1;
    -	}
    -	retval = 0;
    -	/*
    -	 * We must hold both the GRANT lock and the LOG lock,
    -	 * before we mark the filesystem SHUTDOWN and wake
    -	 * everybody up to tell the bad news.
    -	 */
    -	s = GRANT_LOCK(log);
    -	s2 = LOG_LOCK(log);
    -	mp->m_flags |= XFS_MOUNT_FS_SHUTDOWN;
    -	XFS_BUF_DONE(mp->m_sb_bp);
    -	/*
    -	 * This flag is sort of redundant because of the mount flag, but
    -	 * it's good to maintain the separation between the log and the rest
    -	 * of XFS.
    -	 */
    -	log->l_flags |= XLOG_IO_ERROR;
    -
    -	/*
    -	 * If we hit a log error, we want to mark all the iclogs IOERROR
    -	 * while we're still holding the loglock.
    -	 */
    -	if (logerror)
    -		retval = xlog_state_ioerror(log);
    -	LOG_UNLOCK(log, s2);
    -
    -	/*
    -	 * We don't want anybody waiting for log reservations
    -	 * after this. That means we have to wake up everybody
    -	 * queued up on reserve_headq as well as write_headq.
    -	 * In addition, we make sure in xlog_{re}grant_log_space
    -	 * that we don't enqueue anything once the SHUTDOWN flag
    -	 * is set, and this action is protected by the GRANTLOCK.
    -	 */
    -	if ((tic = log->l_reserve_headq)) {
    -		do {
    -			sv_signal(&tic->t_sema);
    -			tic = tic->t_next;
    -		} while (tic != log->l_reserve_headq);
    -	}
    -
    -	if ((tic = log->l_write_headq)) {
    -		do {
    -			sv_signal(&tic->t_sema);
    -			tic = tic->t_next;
    -		} while (tic != log->l_write_headq);
    -	}
    -	GRANT_UNLOCK(log, s);
    -
    -	if (! (log->l_iclog->ic_state & XLOG_STATE_IOERROR)) {
    -		ASSERT(!logerror);
    -		/*
    -		 * Force the incore logs to disk before shutting the
    -		 * log down completely.
    -		 */
    -		xlog_state_sync_all(log, XFS_LOG_FORCE|XFS_LOG_SYNC, &dummy);
    -		s2 = LOG_LOCK(log);
    -		retval = xlog_state_ioerror(log);
    -		LOG_UNLOCK(log, s2);
    -	}
    -	/*
    -	 * Wake up everybody waiting on xfs_log_force.
    -	 * Callback all log item committed functions as if the
    -	 * log writes were completed.
    -	 */
    -	xlog_state_do_callback(log, XFS_LI_ABORTED, NULL);
    -
    -#ifdef XFSERRORDEBUG
    -	{
    -		xlog_in_core_t	*iclog;
    -
    -		s = LOG_LOCK(log);
    -		iclog = log->l_iclog;
    -		do {
    -			ASSERT(iclog->ic_callback == 0);
    -			iclog = iclog->ic_next;
    -		} while (iclog != log->l_iclog);
    -		LOG_UNLOCK(log, s);
    -	}
    -#endif
    -	/* return non-zero if log IOERROR transition had already happened */
    -	return retval;
    -}
    -
    -STATIC int
    -xlog_iclogs_empty(xlog_t *log)
    -{
    -	xlog_in_core_t	*iclog;
    -
    -	iclog = log->l_iclog;
    -	do {
    -		/* endianness does not matter here, zero is zero in
    -		 * any language.
    -		 */
    -		if (iclog->ic_header.h_num_logops)
    -			return 0;
    -		iclog = iclog->ic_next;
    -	} while (iclog != log->l_iclog);
    -	return 1;
    -}
    -
    diff --git a/sys/gnu/fs/xfs/xfs_log.h b/sys/gnu/fs/xfs/xfs_log.h
    deleted file mode 100644
    index eacb3d4987f..00000000000
    --- a/sys/gnu/fs/xfs/xfs_log.h
    +++ /dev/null
    @@ -1,192 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef	__XFS_LOG_H__
    -#define __XFS_LOG_H__
    -
    -/* get lsn fields */
    -
    -#define CYCLE_LSN(lsn) ((uint)((lsn)>>32))
    -#define BLOCK_LSN(lsn) ((uint)(lsn))
    -/* this is used in a spot where we might otherwise double-endian-flip */
    -#define CYCLE_LSN_DISK(lsn) (((uint *)&(lsn))[0])
    -
    -#ifdef __KERNEL__
    -/*
    - * By comparing each component, we don't have to worry about extra
    - * endian issues in treating two 32 bit numbers as one 64 bit number
    - */
    -static inline xfs_lsn_t	_lsn_cmp(xfs_lsn_t lsn1, xfs_lsn_t lsn2)
    -{
    -	if (CYCLE_LSN(lsn1) != CYCLE_LSN(lsn2))
    -		return (CYCLE_LSN(lsn1)i_type = (t))
    -
    -typedef struct xfs_log_iovec {
    -	xfs_caddr_t		i_addr;		/* beginning address of region */
    -	int		i_len;		/* length in bytes of region */
    -	uint		i_type;		/* type of region */
    -} xfs_log_iovec_t;
    -
    -typedef void* xfs_log_ticket_t;
    -
    -/*
    - * Structure used to pass callback function and the function's argument
    - * to the log manager.
    - */
    -typedef struct xfs_log_callback {
    -	struct xfs_log_callback	*cb_next;
    -	void			(*cb_func)(void *, int);
    -	void			*cb_arg;
    -} xfs_log_callback_t;
    -
    -
    -#ifdef __KERNEL__
    -/* Log manager interfaces */
    -struct xfs_mount;
    -xfs_lsn_t xfs_log_done(struct xfs_mount *mp,
    -		       xfs_log_ticket_t ticket,
    -		       void		**iclog,
    -		       uint		flags);
    -int	  _xfs_log_force(struct xfs_mount *mp,
    -			 xfs_lsn_t	lsn,
    -			 uint		flags,
    -			 int		*log_forced);
    -#define xfs_log_force(mp, lsn, flags) \
    -	_xfs_log_force(mp, lsn, flags, NULL);
    -int	  xfs_log_mount(struct xfs_mount	*mp,
    -			struct xfs_buftarg	*log_target,
    -			xfs_daddr_t		start_block,
    -			int		 	num_bblocks);
    -int	  xfs_log_mount_finish(struct xfs_mount *mp, int);
    -void	  xfs_log_move_tail(struct xfs_mount	*mp,
    -			    xfs_lsn_t		tail_lsn);
    -int	  xfs_log_notify(struct xfs_mount	*mp,
    -			 void			*iclog,
    -			 xfs_log_callback_t	*callback_entry);
    -int	  xfs_log_release_iclog(struct xfs_mount *mp,
    -			 void			 *iclog_hndl);
    -int	  xfs_log_reserve(struct xfs_mount *mp,
    -			  int		   length,
    -			  int		   count,
    -			  xfs_log_ticket_t *ticket,
    -			  __uint8_t	   clientid,
    -			  uint		   flags,
    -			  uint		   t_type);
    -int	  xfs_log_write(struct xfs_mount *mp,
    -			xfs_log_iovec_t  region[],
    -			int		 nentries,
    -			xfs_log_ticket_t ticket,
    -			xfs_lsn_t	 *start_lsn);
    -int	  xfs_log_unmount(struct xfs_mount *mp);
    -int	  xfs_log_unmount_write(struct xfs_mount *mp);
    -void      xfs_log_unmount_dealloc(struct xfs_mount *mp);
    -int	  xfs_log_force_umount(struct xfs_mount *mp, int logerror);
    -int	  xfs_log_need_covered(struct xfs_mount *mp);
    -
    -void	  xlog_iodone(struct xfs_buf *);
    -
    -#endif
    -
    -
    -extern int xlog_debug;		/* set to 1 to enable real log */
    -
    -
    -#endif	/* __XFS_LOG_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_log_priv.h b/sys/gnu/fs/xfs/xfs_log_priv.h
    deleted file mode 100644
    index 34bcbf50789..00000000000
    --- a/sys/gnu/fs/xfs/xfs_log_priv.h
    +++ /dev/null
    @@ -1,511 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef	__XFS_LOG_PRIV_H__
    -#define __XFS_LOG_PRIV_H__
    -
    -struct xfs_buf;
    -struct ktrace;
    -struct log;
    -struct xlog_ticket;
    -struct xfs_buf_cancel;
    -struct xfs_mount;
    -
    -/*
    - * Macros, structures, prototypes for internal log manager use.
    - */
    -
    -#define XLOG_MIN_ICLOGS		2
    -#define XLOG_MED_ICLOGS		4
    -#define XLOG_MAX_ICLOGS		8
    -#define XLOG_CALLBACK_SIZE	10
    -#define XLOG_HEADER_MAGIC_NUM	0xFEEDbabe	/* Invalid cycle number */
    -#define XLOG_VERSION_1		1
    -#define XLOG_VERSION_2		2		/* Large IClogs, Log sunit */
    -#define XLOG_VERSION_OKBITS	(XLOG_VERSION_1 | XLOG_VERSION_2)
    -#define XLOG_RECORD_BSIZE	(16*1024)	/* eventually 32k */
    -#define XLOG_BIG_RECORD_BSIZE	(32*1024)	/* 32k buffers */
    -#define XLOG_MAX_RECORD_BSIZE	(256*1024)
    -#define XLOG_HEADER_CYCLE_SIZE	(32*1024)	/* cycle data in header */
    -#define XLOG_RECORD_BSHIFT	14		/* 16384 == 1 << 14 */
    -#define XLOG_BIG_RECORD_BSHIFT	15		/* 32k == 1 << 15 */
    -#define XLOG_MAX_RECORD_BSHIFT	18		/* 256k == 1 << 18 */
    -#define XLOG_BTOLSUNIT(log, b)  (((b)+(log)->l_mp->m_sb.sb_logsunit-1) / \
    -                                 (log)->l_mp->m_sb.sb_logsunit)
    -#define XLOG_LSUNITTOB(log, su) ((su) * (log)->l_mp->m_sb.sb_logsunit)
    -
    -#define XLOG_HEADER_SIZE	512
    -
    -#define XLOG_REC_SHIFT(log) \
    -	BTOBB(1 << (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb) ? \
    -	 XLOG_MAX_RECORD_BSHIFT : XLOG_BIG_RECORD_BSHIFT))
    -#define XLOG_TOTAL_REC_SHIFT(log) \
    -	BTOBB(XLOG_MAX_ICLOGS << (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb) ? \
    -	 XLOG_MAX_RECORD_BSHIFT : XLOG_BIG_RECORD_BSHIFT))
    -
    -/*
    - *  set lsns
    - */
    -
    -#define ASSIGN_ANY_LSN_HOST(lsn,cycle,block)  \
    -    { \
    -	(lsn) = ((xfs_lsn_t)(cycle)<<32)|(block); \
    -    }
    -#define ASSIGN_ANY_LSN_DISK(lsn,cycle,block)  \
    -    { \
    -	INT_SET(((uint *)&(lsn))[0], ARCH_CONVERT, (cycle)); \
    -	INT_SET(((uint *)&(lsn))[1], ARCH_CONVERT, (block)); \
    -    }
    -#define ASSIGN_LSN(lsn,log) \
    -    ASSIGN_ANY_LSN_DISK(lsn,(log)->l_curr_cycle,(log)->l_curr_block);
    -
    -#define XLOG_SET(f,b)		(((f) & (b)) == (b))
    -
    -#define GET_CYCLE(ptr, arch) \
    -    (INT_GET(*(uint *)(ptr), arch) == XLOG_HEADER_MAGIC_NUM ? \
    -	 INT_GET(*((uint *)(ptr)+1), arch) : \
    -	 INT_GET(*(uint *)(ptr), arch) \
    -    )
    -
    -#define BLK_AVG(blk1, blk2)	((blk1+blk2) >> 1)
    -
    -
    -#ifdef __KERNEL__
    -
    -/*
    - * get client id from packed copy.
    - *
    - * this hack is here because the xlog_pack code copies four bytes
    - * of xlog_op_header containing the fields oh_clientid, oh_flags
    - * and oh_res2 into the packed copy.
    - *
    - * later on this four byte chunk is treated as an int and the
    - * client id is pulled out.
    - *
    - * this has endian issues, of course.
    - */
    -
    -#ifndef XFS_NATIVE_HOST
    -#define GET_CLIENT_ID(i,arch) \
    -    ((i) & 0xff)
    -#else
    -#define GET_CLIENT_ID(i,arch) \
    -    ((i) >> 24)
    -#endif
    -
    -#define GRANT_LOCK(log)		mutex_spinlock(&(log)->l_grant_lock)
    -#define GRANT_UNLOCK(log, s)	mutex_spinunlock(&(log)->l_grant_lock, s)
    -#define LOG_LOCK(log)		mutex_spinlock(&(log)->l_icloglock)
    -#define LOG_UNLOCK(log, s)	mutex_spinunlock(&(log)->l_icloglock, s)
    -
    -#define xlog_panic(args...)	cmn_err(CE_PANIC, ## args)
    -#define xlog_exit(args...)	cmn_err(CE_PANIC, ## args)
    -#define xlog_warn(args...)	cmn_err(CE_WARN, ## args)
    -
    -/*
    - * In core log state
    - */
    -#define XLOG_STATE_ACTIVE    0x0001 /* Current IC log being written to */
    -#define XLOG_STATE_WANT_SYNC 0x0002 /* Want to sync this iclog; no more writes */
    -#define XLOG_STATE_SYNCING   0x0004 /* This IC log is syncing */
    -#define XLOG_STATE_DONE_SYNC 0x0008 /* Done syncing to disk */
    -#define XLOG_STATE_DO_CALLBACK \
    -			     0x0010 /* Process callback functions */
    -#define XLOG_STATE_CALLBACK  0x0020 /* Callback functions now */
    -#define XLOG_STATE_DIRTY     0x0040 /* Dirty IC log, not ready for ACTIVE status*/
    -#define XLOG_STATE_IOERROR   0x0080 /* IO error happened in sync'ing log */
    -#define XLOG_STATE_ALL	     0x7FFF /* All possible valid flags */
    -#define XLOG_STATE_NOTUSED   0x8000 /* This IC log not being used */
    -#endif	/* __KERNEL__ */
    -
    -/*
    - * Flags to log operation header
    - *
    - * The first write of a new transaction will be preceded with a start
    - * record, XLOG_START_TRANS.  Once a transaction is committed, a commit
    - * record is written, XLOG_COMMIT_TRANS.  If a single region can not fit into
    - * the remainder of the current active in-core log, it is split up into
    - * multiple regions.  Each partial region will be marked with a
    - * XLOG_CONTINUE_TRANS until the last one, which gets marked with XLOG_END_TRANS.
    - *
    - */
    -#define XLOG_START_TRANS	0x01	/* Start a new transaction */
    -#define XLOG_COMMIT_TRANS	0x02	/* Commit this transaction */
    -#define XLOG_CONTINUE_TRANS	0x04	/* Cont this trans into new region */
    -#define XLOG_WAS_CONT_TRANS	0x08	/* Cont this trans into new region */
    -#define XLOG_END_TRANS		0x10	/* End a continued transaction */
    -#define XLOG_UNMOUNT_TRANS	0x20	/* Unmount a filesystem transaction */
    -#define XLOG_SKIP_TRANS		(XLOG_COMMIT_TRANS | XLOG_CONTINUE_TRANS | \
    -				 XLOG_WAS_CONT_TRANS | XLOG_END_TRANS | \
    -				 XLOG_UNMOUNT_TRANS)
    -
    -#ifdef __KERNEL__
    -/*
    - * Flags to log ticket
    - */
    -#define XLOG_TIC_INITED		0x1	/* has been initialized */
    -#define XLOG_TIC_PERM_RESERV	0x2	/* permanent reservation */
    -#define XLOG_TIC_IN_Q		0x4
    -#endif	/* __KERNEL__ */
    -
    -#define XLOG_UNMOUNT_TYPE	0x556e	/* Un for Unmount */
    -
    -/*
    - * Flags for log structure
    - */
    -#define XLOG_CHKSUM_MISMATCH	0x1	/* used only during recovery */
    -#define XLOG_ACTIVE_RECOVERY	0x2	/* in the middle of recovery */
    -#define	XLOG_RECOVERY_NEEDED	0x4	/* log was recovered */
    -#define XLOG_IO_ERROR		0x8	/* log hit an I/O error, and being
    -					   shutdown */
    -typedef __uint32_t xlog_tid_t;
    -
    -
    -#ifdef __KERNEL__
    -/*
    - * Below are states for covering allocation transactions.
    - * By covering, we mean changing the h_tail_lsn in the last on-disk
    - * log write such that no allocation transactions will be re-done during
    - * recovery after a system crash. Recovery starts at the last on-disk
    - * log write.
    - *
    - * These states are used to insert dummy log entries to cover
    - * space allocation transactions which can undo non-transactional changes
    - * after a crash. Writes to a file with space
    - * already allocated do not result in any transactions. Allocations
    - * might include space beyond the EOF. So if we just push the EOF a
    - * little, the last transaction for the file could contain the wrong
    - * size. If there is no file system activity, after an allocation
    - * transaction, and the system crashes, the allocation transaction
    - * will get replayed and the file will be truncated. This could
    - * be hours/days/... after the allocation occurred.
    - *
    - * The fix for this is to do two dummy transactions when the
    - * system is idle. We need two dummy transaction because the h_tail_lsn
    - * in the log record header needs to point beyond the last possible
    - * non-dummy transaction. The first dummy changes the h_tail_lsn to
    - * the first transaction before the dummy. The second dummy causes
    - * h_tail_lsn to point to the first dummy. Recovery starts at h_tail_lsn.
    - *
    - * These dummy transactions get committed when everything
    - * is idle (after there has been some activity).
    - *
    - * There are 5 states used to control this.
    - *
    - *  IDLE -- no logging has been done on the file system or
    - *		we are done covering previous transactions.
    - *  NEED -- logging has occurred and we need a dummy transaction
    - *		when the log becomes idle.
    - *  DONE -- we were in the NEED state and have committed a dummy
    - *		transaction.
    - *  NEED2 -- we detected that a dummy transaction has gone to the
    - *		on disk log with no other transactions.
    - *  DONE2 -- we committed a dummy transaction when in the NEED2 state.
    - *
    - * There are two places where we switch states:
    - *
    - * 1.) In xfs_sync, when we detect an idle log and are in NEED or NEED2.
    - *	We commit the dummy transaction and switch to DONE or DONE2,
    - *	respectively. In all other states, we don't do anything.
    - *
    - * 2.) When we finish writing the on-disk log (xlog_state_clean_log).
    - *
    - *	No matter what state we are in, if this isn't the dummy
    - *	transaction going out, the next state is NEED.
    - *	So, if we aren't in the DONE or DONE2 states, the next state
    - *	is NEED. We can't be finishing a write of the dummy record
    - *	unless it was committed and the state switched to DONE or DONE2.
    - *
    - *	If we are in the DONE state and this was a write of the
    - *		dummy transaction, we move to NEED2.
    - *
    - *	If we are in the DONE2 state and this was a write of the
    - *		dummy transaction, we move to IDLE.
    - *
    - *
    - * Writing only one dummy transaction can get appended to
    - * one file space allocation. When this happens, the log recovery
    - * code replays the space allocation and a file could be truncated.
    - * This is why we have the NEED2 and DONE2 states before going idle.
    - */
    -
    -#define XLOG_STATE_COVER_IDLE	0
    -#define XLOG_STATE_COVER_NEED	1
    -#define XLOG_STATE_COVER_DONE	2
    -#define XLOG_STATE_COVER_NEED2	3
    -#define XLOG_STATE_COVER_DONE2	4
    -
    -#define XLOG_COVER_OPS		5
    -
    -
    -/* Ticket reservation region accounting */ 
    -#define XLOG_TIC_LEN_MAX	15
    -#define XLOG_TIC_RESET_RES(t) ((t)->t_res_num = \
    -				(t)->t_res_arr_sum = (t)->t_res_num_ophdrs = 0)
    -#define XLOG_TIC_ADD_OPHDR(t) ((t)->t_res_num_ophdrs++)
    -#define XLOG_TIC_ADD_REGION(t, len, type)				\
    -	do {								\
    -		if ((t)->t_res_num == XLOG_TIC_LEN_MAX) { 		\
    -			/* add to overflow and start again */		\
    -			(t)->t_res_o_flow += (t)->t_res_arr_sum;	\
    -			(t)->t_res_num = 0;				\
    -			(t)->t_res_arr_sum = 0;				\
    -		}							\
    -		(t)->t_res_arr[(t)->t_res_num].r_len = (len);		\
    -		(t)->t_res_arr[(t)->t_res_num].r_type = (type);		\
    -		(t)->t_res_arr_sum += (len);				\
    -		(t)->t_res_num++;					\
    -	} while (0)
    -
    -/*
    - * Reservation region
    - * As would be stored in xfs_log_iovec but without the i_addr which
    - * we don't care about.
    - */
    -typedef struct xlog_res {
    -	uint	r_len;	/* region length		:4 */
    -	uint	r_type;	/* region's transaction type	:4 */
    -} xlog_res_t;
    -
    -typedef struct xlog_ticket {
    -	sv_t		   t_sema;	 /* sleep on this semaphore      : 20 */
    - 	struct xlog_ticket *t_next;	 /*			         :4|8 */
    -	struct xlog_ticket *t_prev;	 /*				 :4|8 */
    -	xlog_tid_t	   t_tid;	 /* transaction identifier	 : 4  */
    -	int		   t_curr_res;	 /* current reservation in bytes : 4  */
    -	int		   t_unit_res;	 /* unit reservation in bytes    : 4  */
    -	char		   t_ocnt;	 /* original count		 : 1  */
    -	char		   t_cnt;	 /* current count		 : 1  */
    -	char		   t_clientid;	 /* who does this belong to;	 : 1  */
    -	char		   t_flags;	 /* properties of reservation	 : 1  */
    -	uint		   t_trans_type; /* transaction type             : 4  */
    -
    -        /* reservation array fields */
    -	uint		   t_res_num;                    /* num in array : 4 */
    -	uint		   t_res_num_ophdrs;		 /* num op hdrs  : 4 */
    -	uint		   t_res_arr_sum;		 /* array sum    : 4 */
    -	uint		   t_res_o_flow;		 /* sum overflow : 4 */
    -	xlog_res_t	   t_res_arr[XLOG_TIC_LEN_MAX];  /* array of res : 8 * 15 */ 
    -} xlog_ticket_t;
    -
    -#endif
    -
    -
    -typedef struct xlog_op_header {
    -	xlog_tid_t oh_tid;	/* transaction id of operation	:  4 b */
    -	int	   oh_len;	/* bytes in data region		:  4 b */
    -	__uint8_t  oh_clientid;	/* who sent me this		:  1 b */
    -	__uint8_t  oh_flags;	/*				:  1 b */
    -	ushort	   oh_res2;	/* 32 bit align			:  2 b */
    -} xlog_op_header_t;
    -
    -
    -/* valid values for h_fmt */
    -#define XLOG_FMT_UNKNOWN  0
    -#define XLOG_FMT_LINUX_LE 1
    -#define XLOG_FMT_LINUX_BE 2
    -#define XLOG_FMT_IRIX_BE  3
    -
    -/* our fmt */
    -#ifdef XFS_NATIVE_HOST
    -#define XLOG_FMT XLOG_FMT_LINUX_BE
    -#else
    -#define XLOG_FMT XLOG_FMT_LINUX_LE
    -#endif
    -
    -typedef struct xlog_rec_header {
    -	uint	  h_magicno;	/* log record (LR) identifier		:  4 */
    -	uint	  h_cycle;	/* write cycle of log			:  4 */
    -	int	  h_version;	/* LR version				:  4 */
    -	int	  h_len;	/* len in bytes; should be 64-bit aligned: 4 */
    -	xfs_lsn_t h_lsn;	/* lsn of this LR			:  8 */
    -	xfs_lsn_t h_tail_lsn;	/* lsn of 1st LR w/ buffers not committed: 8 */
    -	uint	  h_chksum;	/* may not be used; non-zero if used	:  4 */
    -	int	  h_prev_block; /* block number to previous LR		:  4 */
    -	int	  h_num_logops;	/* number of log operations in this LR	:  4 */
    -	uint	  h_cycle_data[XLOG_HEADER_CYCLE_SIZE / BBSIZE];
    -	/* new fields */
    -	int       h_fmt;        /* format of log record                 :  4 */
    -	uuid_t    h_fs_uuid;    /* uuid of FS                           : 16 */
    -	int       h_size;	/* iclog size				:  4 */
    -} xlog_rec_header_t;
    -
    -typedef struct xlog_rec_ext_header {
    -	uint	  xh_cycle;	/* write cycle of log			: 4 */
    -	uint	  xh_cycle_data[XLOG_HEADER_CYCLE_SIZE / BBSIZE]; /*	: 256 */
    -} xlog_rec_ext_header_t;
    -
    -#ifdef __KERNEL__
    -/*
    - * - A log record header is 512 bytes.  There is plenty of room to grow the
    - *	xlog_rec_header_t into the reserved space.
    - * - ic_data follows, so a write to disk can start at the beginning of
    - *	the iclog.
    - * - ic_forcesema is used to implement synchronous forcing of the iclog to disk.
    - * - ic_next is the pointer to the next iclog in the ring.
    - * - ic_bp is a pointer to the buffer used to write this incore log to disk.
    - * - ic_log is a pointer back to the global log structure.
    - * - ic_callback is a linked list of callback function/argument pairs to be
    - *	called after an iclog finishes writing.
    - * - ic_size is the full size of the header plus data.
    - * - ic_offset is the current number of bytes written to in this iclog.
    - * - ic_refcnt is bumped when someone is writing to the log.
    - * - ic_state is the state of the iclog.
    - */
    -typedef struct xlog_iclog_fields {
    -	sv_t			ic_forcesema;
    -	sv_t			ic_writesema;
    -	struct xlog_in_core	*ic_next;
    -	struct xlog_in_core	*ic_prev;
    -	struct xfs_buf		*ic_bp;
    -	struct log		*ic_log;
    -	xfs_log_callback_t	*ic_callback;
    -	xfs_log_callback_t	**ic_callback_tail;
    -#ifdef XFS_LOG_TRACE
    -	struct ktrace		*ic_trace;
    -#endif
    -	int			ic_size;
    -	int			ic_offset;
    -	int			ic_refcnt;
    -	int			ic_bwritecnt;
    -	ushort_t		ic_state;
    -	char			*ic_datap;	/* pointer to iclog data */
    -} xlog_iclog_fields_t;
    -
    -typedef union xlog_in_core2 {
    -	xlog_rec_header_t	hic_header;
    -	xlog_rec_ext_header_t	hic_xheader;
    -	char			hic_sector[XLOG_HEADER_SIZE];
    -} xlog_in_core_2_t;
    -
    -typedef struct xlog_in_core {
    -	xlog_iclog_fields_t	hic_fields;
    -	xlog_in_core_2_t	*hic_data;
    -} xlog_in_core_t;
    -
    -/*
    - * Defines to save our code from this glop.
    - */
    -#define	ic_forcesema	hic_fields.ic_forcesema
    -#define ic_writesema	hic_fields.ic_writesema
    -#define	ic_next		hic_fields.ic_next
    -#define	ic_prev		hic_fields.ic_prev
    -#define	ic_bp		hic_fields.ic_bp
    -#define	ic_log		hic_fields.ic_log
    -#define	ic_callback	hic_fields.ic_callback
    -#define	ic_callback_tail hic_fields.ic_callback_tail
    -#define	ic_trace	hic_fields.ic_trace
    -#define	ic_size		hic_fields.ic_size
    -#define	ic_offset	hic_fields.ic_offset
    -#define	ic_refcnt	hic_fields.ic_refcnt
    -#define	ic_bwritecnt	hic_fields.ic_bwritecnt
    -#define	ic_state	hic_fields.ic_state
    -#define ic_datap	hic_fields.ic_datap
    -#define ic_header	hic_data->hic_header
    -
    -/*
    - * The reservation head lsn is not made up of a cycle number and block number.
    - * Instead, it uses a cycle number and byte number.  Logs don't expect to
    - * overflow 31 bits worth of byte offset, so using a byte number will mean
    - * that round off problems won't occur when releasing partial reservations.
    - */
    -typedef struct log {
    -	/* The following block of fields are changed while holding icloglock */
    -	sema_t			l_flushsema;    /* iclog flushing semaphore */
    -	int			l_flushcnt;	/* # of procs waiting on this
    -						 * sema */
    -	int			l_ticket_cnt;	/* free ticket count */
    -	int			l_ticket_tcnt;	/* total ticket count */
    -	int			l_covered_state;/* state of "covering disk
    -						 * log entries" */
    -	xlog_ticket_t		*l_freelist;    /* free list of tickets */
    -	xlog_ticket_t		*l_unmount_free;/* kmem_free these addresses */
    -	xlog_ticket_t		*l_tail;        /* free list of tickets */
    -	xlog_in_core_t		*l_iclog;       /* head log queue	*/
    -	lock_t			l_icloglock;    /* grab to change iclog state */
    -	xfs_lsn_t		l_tail_lsn;     /* lsn of 1st LR with unflushed
    -						 * buffers */
    -	xfs_lsn_t		l_last_sync_lsn;/* lsn of last LR on disk */
    -	struct xfs_mount	*l_mp;	        /* mount point */
    -	struct xfs_buf		*l_xbuf;        /* extra buffer for log
    -						 * wrapping */
    -	struct xfs_buftarg	*l_targ;        /* buftarg of log */
    -	xfs_daddr_t		l_logBBstart;   /* start block of log */
    -	int			l_logsize;      /* size of log in bytes */
    -	int			l_logBBsize;    /* size of log in BB chunks */
    -	int			l_curr_cycle;   /* Cycle number of log writes */
    -	int			l_prev_cycle;   /* Cycle number before last
    -						 * block increment */
    -	int			l_curr_block;   /* current logical log block */
    -	int			l_prev_block;   /* previous logical log block */
    -	int			l_iclog_size;	/* size of log in bytes */
    -	int			l_iclog_size_log; /* log power size of log */
    -	int			l_iclog_bufs;	/* number of iclog buffers */
    -
    -	/* The following field are used for debugging; need to hold icloglock */
    -	char			*l_iclog_bak[XLOG_MAX_ICLOGS];
    -
    -	/* The following block of fields are changed while holding grant_lock */
    -	lock_t			l_grant_lock;
    -	xlog_ticket_t		*l_reserve_headq;
    -	xlog_ticket_t		*l_write_headq;
    -	int			l_grant_reserve_cycle;
    -	int			l_grant_reserve_bytes;
    -	int			l_grant_write_cycle;
    -	int			l_grant_write_bytes;
    -
    -	/* The following fields don't need locking */
    -#ifdef XFS_LOG_TRACE
    -	struct ktrace		*l_trace;
    -	struct ktrace		*l_grant_trace;
    -#endif
    -	uint			l_flags;
    -	uint			l_quotaoffs_flag; /* XFS_DQ_*, for QUOTAOFFs */
    -	struct xfs_buf_cancel	**l_buf_cancel_table;
    -	int			l_iclog_hsize;  /* size of iclog header */
    -	int			l_iclog_heads;  /* # of iclog header sectors */
    -	uint			l_sectbb_log;   /* log2 of sector size in BBs */
    -	uint			l_sectbb_mask;  /* sector size (in BBs)
    -						 * alignment mask */
    -} xlog_t;
    -
    -#define XLOG_FORCED_SHUTDOWN(log)	((log)->l_flags & XLOG_IO_ERROR)
    -
    -
    -/* common routines */
    -extern xfs_lsn_t xlog_assign_tail_lsn(struct xfs_mount *mp);
    -extern int	 xlog_find_tail(xlog_t	*log,
    -				xfs_daddr_t *head_blk,
    -				xfs_daddr_t *tail_blk);
    -extern int	 xlog_recover(xlog_t *log);
    -extern int	 xlog_recover_finish(xlog_t *log, int mfsi_flags);
    -extern void	 xlog_pack_data(xlog_t *log, xlog_in_core_t *iclog, int);
    -extern void	 xlog_recover_process_iunlinks(xlog_t *log);
    -
    -extern struct xfs_buf *xlog_get_bp(xlog_t *, int);
    -extern void	 xlog_put_bp(struct xfs_buf *);
    -extern int	 xlog_bread(xlog_t *, xfs_daddr_t, int, struct xfs_buf *);
    -
    -/* iclog tracing */
    -#define XLOG_TRACE_GRAB_FLUSH  1
    -#define XLOG_TRACE_REL_FLUSH   2
    -#define XLOG_TRACE_SLEEP_FLUSH 3
    -#define XLOG_TRACE_WAKE_FLUSH  4
    -
    -#endif	/* __KERNEL__ */
    -
    -#endif	/* __XFS_LOG_PRIV_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_log_recover.c b/sys/gnu/fs/xfs/xfs_log_recover.c
    deleted file mode 100644
    index c0e035ba9fc..00000000000
    --- a/sys/gnu/fs/xfs/xfs_log_recover.c
    +++ /dev/null
    @@ -1,4078 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_error.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_inode_item.h"
    -#include "xfs_imap.h"
    -#include "xfs_alloc.h"
    -#include "xfs_ialloc.h"
    -#include "xfs_log_priv.h"
    -#include "xfs_buf_item.h"
    -#include "xfs_log_recover.h"
    -#include "xfs_extfree_item.h"
    -#include "xfs_trans_priv.h"
    -#include "xfs_quota.h"
    -#include "xfs_rw.h"
    -
    -STATIC int	xlog_find_zeroed(xlog_t *, xfs_daddr_t *);
    -STATIC int	xlog_clear_stale_blocks(xlog_t *, xfs_lsn_t);
    -STATIC void	xlog_recover_insert_item_backq(xlog_recover_item_t **q,
    -					       xlog_recover_item_t *item);
    -#if defined(DEBUG)
    -STATIC void	xlog_recover_check_summary(xlog_t *);
    -STATIC void	xlog_recover_check_ail(xfs_mount_t *, xfs_log_item_t *, int);
    -#else
    -#define	xlog_recover_check_summary(log)
    -#define	xlog_recover_check_ail(mp, lip, gen)
    -#endif
    -
    -
    -/*
    - * Sector aligned buffer routines for buffer create/read/write/access
    - */
    -
    -#define XLOG_SECTOR_ROUNDUP_BBCOUNT(log, bbs)	\
    -	( ((log)->l_sectbb_mask && (bbs & (log)->l_sectbb_mask)) ? \
    -	((bbs + (log)->l_sectbb_mask + 1) & ~(log)->l_sectbb_mask) : (bbs) )
    -#define XLOG_SECTOR_ROUNDDOWN_BLKNO(log, bno)	((bno) & ~(log)->l_sectbb_mask)
    -
    -xfs_buf_t *
    -xlog_get_bp(
    -	xlog_t		*log,
    -	int		num_bblks)
    -{
    -	ASSERT(num_bblks > 0);
    -
    -	if (log->l_sectbb_log) {
    -		if (num_bblks > 1)
    -			num_bblks += XLOG_SECTOR_ROUNDUP_BBCOUNT(log, 1);
    -		num_bblks = XLOG_SECTOR_ROUNDUP_BBCOUNT(log, num_bblks);
    -	}
    -	return xfs_buf_get_noaddr(BBTOB(num_bblks), log->l_mp->m_logdev_targp);
    -}
    -
    -void
    -xlog_put_bp(
    -	xfs_buf_t	*bp)
    -{
    -	xfs_buf_free(bp);
    -}
    -
    -
    -/*
    - * nbblks should be uint, but oh well.  Just want to catch that 32-bit length.
    - */
    -int
    -xlog_bread(
    -	xlog_t		*log,
    -	xfs_daddr_t	blk_no,
    -	int		nbblks,
    -	xfs_buf_t	*bp)
    -{
    -	int		error;
    -
    -	if (log->l_sectbb_log) {
    -		blk_no = XLOG_SECTOR_ROUNDDOWN_BLKNO(log, blk_no);
    -		nbblks = XLOG_SECTOR_ROUNDUP_BBCOUNT(log, nbblks);
    -	}
    -
    -	ASSERT(nbblks > 0);
    -	ASSERT(BBTOB(nbblks) <= XFS_BUF_SIZE(bp));
    -	ASSERT(bp);
    -
    -	XFS_BUF_SET_ADDR(bp, log->l_logBBstart + blk_no);
    -	XFS_BUF_READ(bp);
    -	XFS_BUF_BUSY(bp);
    -	XFS_BUF_SET_COUNT(bp, BBTOB(nbblks));
    -	XFS_BUF_SET_TARGET(bp, log->l_mp->m_logdev_targp);
    -
    -	xfsbdstrat(log->l_mp, bp);
    -	if ((error = xfs_iowait(bp)))
    -		xfs_ioerror_alert("xlog_bread", log->l_mp,
    -				  bp, XFS_BUF_ADDR(bp));
    -	return error;
    -}
    -
    -/*
    - * Write out the buffer at the given block for the given number of blocks.
    - * The buffer is kept locked across the write and is returned locked.
    - * This can only be used for synchronous log writes.
    - */
    -STATIC int
    -xlog_bwrite(
    -	xlog_t		*log,
    -	xfs_daddr_t	blk_no,
    -	int		nbblks,
    -	xfs_buf_t	*bp)
    -{
    -	int		error;
    -
    -	if (log->l_sectbb_log) {
    -		blk_no = XLOG_SECTOR_ROUNDDOWN_BLKNO(log, blk_no);
    -		nbblks = XLOG_SECTOR_ROUNDUP_BBCOUNT(log, nbblks);
    -	}
    -
    -	ASSERT(nbblks > 0);
    -	ASSERT(BBTOB(nbblks) <= XFS_BUF_SIZE(bp));
    -
    -	XFS_BUF_SET_ADDR(bp, log->l_logBBstart + blk_no);
    -	XFS_BUF_ZEROFLAGS(bp);
    -	XFS_BUF_BUSY(bp);
    -	XFS_BUF_HOLD(bp);
    -	XFS_BUF_PSEMA(bp, PRIBIO);
    -	XFS_BUF_SET_COUNT(bp, BBTOB(nbblks));
    -	XFS_BUF_SET_TARGET(bp, log->l_mp->m_logdev_targp);
    -
    -	if ((error = xfs_bwrite(log->l_mp, bp)))
    -		xfs_ioerror_alert("xlog_bwrite", log->l_mp,
    -				  bp, XFS_BUF_ADDR(bp));
    -	return error;
    -}
    -
    -STATIC xfs_caddr_t
    -xlog_align(
    -	xlog_t		*log,
    -	xfs_daddr_t	blk_no,
    -	int		nbblks,
    -	xfs_buf_t	*bp)
    -{
    -	xfs_caddr_t	ptr;
    -
    -	if (!log->l_sectbb_log)
    -		return XFS_BUF_PTR(bp);
    -
    -	ptr = XFS_BUF_PTR(bp) + BBTOB((int)blk_no & log->l_sectbb_mask);
    -	ASSERT(XFS_BUF_SIZE(bp) >=
    -		BBTOB(nbblks + (blk_no & log->l_sectbb_mask)));
    -	return ptr;
    -}
    -
    -#ifdef DEBUG
    -/*
    - * dump debug superblock and log record information
    - */
    -STATIC void
    -xlog_header_check_dump(
    -	xfs_mount_t		*mp,
    -	xlog_rec_header_t	*head)
    -{
    -	int			b;
    -
    -	printk("%s:  SB : uuid = ", __FUNCTION__);
    -	for (b = 0; b < 16; b++)
    -		printk("%02x",((unsigned char *)&mp->m_sb.sb_uuid)[b]);
    -	printk(", fmt = %d\n", XLOG_FMT);
    -	printk("    log : uuid = ");
    -	for (b = 0; b < 16; b++)
    -		printk("%02x",((unsigned char *)&head->h_fs_uuid)[b]);
    -	printk(", fmt = %d\n", INT_GET(head->h_fmt, ARCH_CONVERT));
    -}
    -#else
    -#define xlog_header_check_dump(mp, head)
    -#endif
    -
    -/*
    - * check log record header for recovery
    - */
    -STATIC int
    -xlog_header_check_recover(
    -	xfs_mount_t		*mp,
    -	xlog_rec_header_t	*head)
    -{
    -	ASSERT(INT_GET(head->h_magicno, ARCH_CONVERT) == XLOG_HEADER_MAGIC_NUM);
    -
    -	/*
    -	 * IRIX doesn't write the h_fmt field and leaves it zeroed
    -	 * (XLOG_FMT_UNKNOWN). This stops us from trying to recover
    -	 * a dirty log created in IRIX.
    -	 */
    -	if (unlikely(INT_GET(head->h_fmt, ARCH_CONVERT) != XLOG_FMT)) {
    -		xlog_warn(
    -	"XFS: dirty log written in incompatible format - can't recover");
    -		xlog_header_check_dump(mp, head);
    -		XFS_ERROR_REPORT("xlog_header_check_recover(1)",
    -				 XFS_ERRLEVEL_HIGH, mp);
    -		return XFS_ERROR(EFSCORRUPTED);
    -	} else if (unlikely(!uuid_equal(&mp->m_sb.sb_uuid, &head->h_fs_uuid))) {
    -		xlog_warn(
    -	"XFS: dirty log entry has mismatched uuid - can't recover");
    -		xlog_header_check_dump(mp, head);
    -		XFS_ERROR_REPORT("xlog_header_check_recover(2)",
    -				 XFS_ERRLEVEL_HIGH, mp);
    -		return XFS_ERROR(EFSCORRUPTED);
    -	}
    -	return 0;
    -}
    -
    -/*
    - * read the head block of the log and check the header
    - */
    -STATIC int
    -xlog_header_check_mount(
    -	xfs_mount_t		*mp,
    -	xlog_rec_header_t	*head)
    -{
    -	ASSERT(INT_GET(head->h_magicno, ARCH_CONVERT) == XLOG_HEADER_MAGIC_NUM);
    -
    -	if (uuid_is_nil(&head->h_fs_uuid)) {
    -		/*
    -		 * IRIX doesn't write the h_fs_uuid or h_fmt fields. If
    -		 * h_fs_uuid is nil, we assume this log was last mounted
    -		 * by IRIX and continue.
    -		 */
    -		xlog_warn("XFS: nil uuid in log - IRIX style log");
    -	} else if (unlikely(!uuid_equal(&mp->m_sb.sb_uuid, &head->h_fs_uuid))) {
    -		xlog_warn("XFS: log has mismatched uuid - can't recover");
    -		xlog_header_check_dump(mp, head);
    -		XFS_ERROR_REPORT("xlog_header_check_mount",
    -				 XFS_ERRLEVEL_HIGH, mp);
    -		return XFS_ERROR(EFSCORRUPTED);
    -	}
    -	return 0;
    -}
    -
    -STATIC void
    -xlog_recover_iodone(
    -	struct xfs_buf	*bp)
    -{
    -	xfs_mount_t	*mp;
    -
    -	ASSERT(XFS_BUF_FSPRIVATE(bp, void *));
    -
    -	if (XFS_BUF_GETERROR(bp)) {
    -		/*
    -		 * We're not going to bother about retrying
    -		 * this during recovery. One strike!
    -		 */
    -		mp = XFS_BUF_FSPRIVATE(bp, xfs_mount_t *);
    -		xfs_ioerror_alert("xlog_recover_iodone",
    -				  mp, bp, XFS_BUF_ADDR(bp));
    -		xfs_force_shutdown(mp, XFS_METADATA_IO_ERROR);
    -	}
    -	XFS_BUF_SET_FSPRIVATE(bp, NULL);
    -	XFS_BUF_CLR_IODONE_FUNC(bp);
    -	xfs_biodone(bp);
    -}
    -
    -/*
    - * This routine finds (to an approximation) the first block in the physical
    - * log which contains the given cycle.  It uses a binary search algorithm.
    - * Note that the algorithm can not be perfect because the disk will not
    - * necessarily be perfect.
    - */
    -STATIC int
    -xlog_find_cycle_start(
    -	xlog_t		*log,
    -	xfs_buf_t	*bp,
    -	xfs_daddr_t	first_blk,
    -	xfs_daddr_t	*last_blk,
    -	uint		cycle)
    -{
    -	xfs_caddr_t	offset;
    -	xfs_daddr_t	mid_blk;
    -	uint		mid_cycle;
    -	int		error;
    -
    -	mid_blk = BLK_AVG(first_blk, *last_blk);
    -	while (mid_blk != first_blk && mid_blk != *last_blk) {
    -		if ((error = xlog_bread(log, mid_blk, 1, bp)))
    -			return error;
    -		offset = xlog_align(log, mid_blk, 1, bp);
    -		mid_cycle = GET_CYCLE(offset, ARCH_CONVERT);
    -		if (mid_cycle == cycle) {
    -			*last_blk = mid_blk;
    -			/* last_half_cycle == mid_cycle */
    -		} else {
    -			first_blk = mid_blk;
    -			/* first_half_cycle == mid_cycle */
    -		}
    -		mid_blk = BLK_AVG(first_blk, *last_blk);
    -	}
    -	ASSERT((mid_blk == first_blk && mid_blk+1 == *last_blk) ||
    -	       (mid_blk == *last_blk && mid_blk-1 == first_blk));
    -
    -	return 0;
    -}
    -
    -/*
    - * Check that the range of blocks does not contain the cycle number
    - * given.  The scan needs to occur from front to back and the ptr into the
    - * region must be updated since a later routine will need to perform another
    - * test.  If the region is completely good, we end up returning the same
    - * last block number.
    - *
    - * Set blkno to -1 if we encounter no errors.  This is an invalid block number
    - * since we don't ever expect logs to get this large.
    - */
    -STATIC int
    -xlog_find_verify_cycle(
    -	xlog_t		*log,
    -	xfs_daddr_t	start_blk,
    -	int		nbblks,
    -	uint		stop_on_cycle_no,
    -	xfs_daddr_t	*new_blk)
    -{
    -	xfs_daddr_t	i, j;
    -	uint		cycle;
    -	xfs_buf_t	*bp;
    -	xfs_daddr_t	bufblks;
    -	xfs_caddr_t	buf = NULL;
    -	int		error = 0;
    -
    -	bufblks = 1 << ffs(nbblks);
    -
    -	while (!(bp = xlog_get_bp(log, bufblks))) {
    -		/* can't get enough memory to do everything in one big buffer */
    -		bufblks >>= 1;
    -		if (bufblks <= log->l_sectbb_log)
    -			return ENOMEM;
    -	}
    -
    -	for (i = start_blk; i < start_blk + nbblks; i += bufblks) {
    -		int	bcount;
    -
    -		bcount = min(bufblks, (start_blk + nbblks - i));
    -
    -		if ((error = xlog_bread(log, i, bcount, bp)))
    -			goto out;
    -
    -		buf = xlog_align(log, i, bcount, bp);
    -		for (j = 0; j < bcount; j++) {
    -			cycle = GET_CYCLE(buf, ARCH_CONVERT);
    -			if (cycle == stop_on_cycle_no) {
    -				*new_blk = i+j;
    -				goto out;
    -			}
    -
    -			buf += BBSIZE;
    -		}
    -	}
    -
    -	*new_blk = -1;
    -
    -out:
    -	xlog_put_bp(bp);
    -	return error;
    -}
    -
    -/*
    - * Potentially backup over partial log record write.
    - *
    - * In the typical case, last_blk is the number of the block directly after
    - * a good log record.  Therefore, we subtract one to get the block number
    - * of the last block in the given buffer.  extra_bblks contains the number
    - * of blocks we would have read on a previous read.  This happens when the
    - * last log record is split over the end of the physical log.
    - *
    - * extra_bblks is the number of blocks potentially verified on a previous
    - * call to this routine.
    - */
    -STATIC int
    -xlog_find_verify_log_record(
    -	xlog_t			*log,
    -	xfs_daddr_t		start_blk,
    -	xfs_daddr_t		*last_blk,
    -	int			extra_bblks)
    -{
    -	xfs_daddr_t		i;
    -	xfs_buf_t		*bp;
    -	xfs_caddr_t		offset = NULL;
    -	xlog_rec_header_t	*head = NULL;
    -	int			error = 0;
    -	int			smallmem = 0;
    -	int			num_blks = *last_blk - start_blk;
    -	int			xhdrs;
    -
    -	ASSERT(start_blk != 0 || *last_blk != start_blk);
    -
    -	if (!(bp = xlog_get_bp(log, num_blks))) {
    -		if (!(bp = xlog_get_bp(log, 1)))
    -			return ENOMEM;
    -		smallmem = 1;
    -	} else {
    -		if ((error = xlog_bread(log, start_blk, num_blks, bp)))
    -			goto out;
    -		offset = xlog_align(log, start_blk, num_blks, bp);
    -		offset += ((num_blks - 1) << BBSHIFT);
    -	}
    -
    -	for (i = (*last_blk) - 1; i >= 0; i--) {
    -		if (i < start_blk) {
    -			/* valid log record not found */
    -			xlog_warn(
    -		"XFS: Log inconsistent (didn't find previous header)");
    -			ASSERT(0);
    -			error = XFS_ERROR(EIO);
    -			goto out;
    -		}
    -
    -		if (smallmem) {
    -			if ((error = xlog_bread(log, i, 1, bp)))
    -				goto out;
    -			offset = xlog_align(log, i, 1, bp);
    -		}
    -
    -		head = (xlog_rec_header_t *)offset;
    -
    -		if (XLOG_HEADER_MAGIC_NUM ==
    -		    INT_GET(head->h_magicno, ARCH_CONVERT))
    -			break;
    -
    -		if (!smallmem)
    -			offset -= BBSIZE;
    -	}
    -
    -	/*
    -	 * We hit the beginning of the physical log & still no header.  Return
    -	 * to caller.  If caller can handle a return of -1, then this routine
    -	 * will be called again for the end of the physical log.
    -	 */
    -	if (i == -1) {
    -		error = -1;
    -		goto out;
    -	}
    -
    -	/*
    -	 * We have the final block of the good log (the first block
    -	 * of the log record _before_ the head. So we check the uuid.
    -	 */
    -	if ((error = xlog_header_check_mount(log->l_mp, head)))
    -		goto out;
    -
    -	/*
    -	 * We may have found a log record header before we expected one.
    -	 * last_blk will be the 1st block # with a given cycle #.  We may end
    -	 * up reading an entire log record.  In this case, we don't want to
    -	 * reset last_blk.  Only when last_blk points in the middle of a log
    -	 * record do we update last_blk.
    -	 */
    -	if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) {
    -		uint	h_size = INT_GET(head->h_size, ARCH_CONVERT);
    -
    -		xhdrs = h_size / XLOG_HEADER_CYCLE_SIZE;
    -		if (h_size % XLOG_HEADER_CYCLE_SIZE)
    -			xhdrs++;
    -	} else {
    -		xhdrs = 1;
    -	}
    -
    -	if (*last_blk - i + extra_bblks
    -			!= BTOBB(INT_GET(head->h_len, ARCH_CONVERT)) + xhdrs)
    -		*last_blk = i;
    -
    -out:
    -	xlog_put_bp(bp);
    -	return error;
    -}
    -
    -/*
    - * Head is defined to be the point of the log where the next log write
    - * write could go.  This means that incomplete LR writes at the end are
    - * eliminated when calculating the head.  We aren't guaranteed that previous
    - * LR have complete transactions.  We only know that a cycle number of
    - * current cycle number -1 won't be present in the log if we start writing
    - * from our current block number.
    - *
    - * last_blk contains the block number of the first block with a given
    - * cycle number.
    - *
    - * Return: zero if normal, non-zero if error.
    - */
    -STATIC int
    -xlog_find_head(
    -	xlog_t 		*log,
    -	xfs_daddr_t	*return_head_blk)
    -{
    -	xfs_buf_t	*bp;
    -	xfs_caddr_t	offset;
    -	xfs_daddr_t	new_blk, first_blk = 0, start_blk, last_blk, head_blk;
    -	int		num_scan_bblks;
    -	uint		first_half_cycle, last_half_cycle;
    -	uint		stop_on_cycle;
    -	int		error, log_bbnum = log->l_logBBsize;
    -
    -	/* Is the end of the log device zeroed? */
    -	if ((error = xlog_find_zeroed(log, &first_blk)) == -1) {
    -		*return_head_blk = first_blk;
    -
    -		/* Is the whole lot zeroed? */
    -		if (!first_blk) {
    -			/* Linux XFS shouldn't generate totally zeroed logs -
    -			 * mkfs etc write a dummy unmount record to a fresh
    -			 * log so we can store the uuid in there
    -			 */
    -			xlog_warn("XFS: totally zeroed log");
    -		}
    -
    -		return 0;
    -	} else if (error) {
    -		xlog_warn("XFS: empty log check failed");
    -		return error;
    -	}
    -
    -	first_blk = 0;			/* get cycle # of 1st block */
    -	bp = xlog_get_bp(log, 1);
    -	if (!bp)
    -		return ENOMEM;
    -	if ((error = xlog_bread(log, 0, 1, bp)))
    -		goto bp_err;
    -	offset = xlog_align(log, 0, 1, bp);
    -	first_half_cycle = GET_CYCLE(offset, ARCH_CONVERT);
    -
    -	last_blk = head_blk = log_bbnum - 1;	/* get cycle # of last block */
    -	if ((error = xlog_bread(log, last_blk, 1, bp)))
    -		goto bp_err;
    -	offset = xlog_align(log, last_blk, 1, bp);
    -	last_half_cycle = GET_CYCLE(offset, ARCH_CONVERT);
    -	ASSERT(last_half_cycle != 0);
    -
    -	/*
    -	 * If the 1st half cycle number is equal to the last half cycle number,
    -	 * then the entire log is stamped with the same cycle number.  In this
    -	 * case, head_blk can't be set to zero (which makes sense).  The below
    -	 * math doesn't work out properly with head_blk equal to zero.  Instead,
    -	 * we set it to log_bbnum which is an invalid block number, but this
    -	 * value makes the math correct.  If head_blk doesn't changed through
    -	 * all the tests below, *head_blk is set to zero at the very end rather
    -	 * than log_bbnum.  In a sense, log_bbnum and zero are the same block
    -	 * in a circular file.
    -	 */
    -	if (first_half_cycle == last_half_cycle) {
    -		/*
    -		 * In this case we believe that the entire log should have
    -		 * cycle number last_half_cycle.  We need to scan backwards
    -		 * from the end verifying that there are no holes still
    -		 * containing last_half_cycle - 1.  If we find such a hole,
    -		 * then the start of that hole will be the new head.  The
    -		 * simple case looks like
    -		 *        x | x ... | x - 1 | x
    -		 * Another case that fits this picture would be
    -		 *        x | x + 1 | x ... | x
    -		 * In this case the head really is somewhere at the end of the
    -		 * log, as one of the latest writes at the beginning was
    -		 * incomplete.
    -		 * One more case is
    -		 *        x | x + 1 | x ... | x - 1 | x
    -		 * This is really the combination of the above two cases, and
    -		 * the head has to end up at the start of the x-1 hole at the
    -		 * end of the log.
    -		 *
    -		 * In the 256k log case, we will read from the beginning to the
    -		 * end of the log and search for cycle numbers equal to x-1.
    -		 * We don't worry about the x+1 blocks that we encounter,
    -		 * because we know that they cannot be the head since the log
    -		 * started with x.
    -		 */
    -		head_blk = log_bbnum;
    -		stop_on_cycle = last_half_cycle - 1;
    -	} else {
    -		/*
    -		 * In this case we want to find the first block with cycle
    -		 * number matching last_half_cycle.  We expect the log to be
    -		 * some variation on
    -		 *        x + 1 ... | x ...
    -		 * The first block with cycle number x (last_half_cycle) will
    -		 * be where the new head belongs.  First we do a binary search
    -		 * for the first occurrence of last_half_cycle.  The binary
    -		 * search may not be totally accurate, so then we scan back
    -		 * from there looking for occurrences of last_half_cycle before
    -		 * us.  If that backwards scan wraps around the beginning of
    -		 * the log, then we look for occurrences of last_half_cycle - 1
    -		 * at the end of the log.  The cases we're looking for look
    -		 * like
    -		 *        x + 1 ... | x | x + 1 | x ...
    -		 *                               ^ binary search stopped here
    -		 * or
    -		 *        x + 1 ... | x ... | x - 1 | x
    -		 *        <---------> less than scan distance
    -		 */
    -		stop_on_cycle = last_half_cycle;
    -		if ((error = xlog_find_cycle_start(log, bp, first_blk,
    -						&head_blk, last_half_cycle)))
    -			goto bp_err;
    -	}
    -
    -	/*
    -	 * Now validate the answer.  Scan back some number of maximum possible
    -	 * blocks and make sure each one has the expected cycle number.  The
    -	 * maximum is determined by the total possible amount of buffering
    -	 * in the in-core log.  The following number can be made tighter if
    -	 * we actually look at the block size of the filesystem.
    -	 */
    -	num_scan_bblks = XLOG_TOTAL_REC_SHIFT(log);
    -	if (head_blk >= num_scan_bblks) {
    -		/*
    -		 * We are guaranteed that the entire check can be performed
    -		 * in one buffer.
    -		 */
    -		start_blk = head_blk - num_scan_bblks;
    -		if ((error = xlog_find_verify_cycle(log,
    -						start_blk, num_scan_bblks,
    -						stop_on_cycle, &new_blk)))
    -			goto bp_err;
    -		if (new_blk != -1)
    -			head_blk = new_blk;
    -	} else {		/* need to read 2 parts of log */
    -		/*
    -		 * We are going to scan backwards in the log in two parts.
    -		 * First we scan the physical end of the log.  In this part
    -		 * of the log, we are looking for blocks with cycle number
    -		 * last_half_cycle - 1.
    -		 * If we find one, then we know that the log starts there, as
    -		 * we've found a hole that didn't get written in going around
    -		 * the end of the physical log.  The simple case for this is
    -		 *        x + 1 ... | x ... | x - 1 | x
    -		 *        <---------> less than scan distance
    -		 * If all of the blocks at the end of the log have cycle number
    -		 * last_half_cycle, then we check the blocks at the start of
    -		 * the log looking for occurrences of last_half_cycle.  If we
    -		 * find one, then our current estimate for the location of the
    -		 * first occurrence of last_half_cycle is wrong and we move
    -		 * back to the hole we've found.  This case looks like
    -		 *        x + 1 ... | x | x + 1 | x ...
    -		 *                               ^ binary search stopped here
    -		 * Another case we need to handle that only occurs in 256k
    -		 * logs is
    -		 *        x + 1 ... | x ... | x+1 | x ...
    -		 *                   ^ binary search stops here
    -		 * In a 256k log, the scan at the end of the log will see the
    -		 * x + 1 blocks.  We need to skip past those since that is
    -		 * certainly not the head of the log.  By searching for
    -		 * last_half_cycle-1 we accomplish that.
    -		 */
    -		start_blk = log_bbnum - num_scan_bblks + head_blk;
    -		ASSERT(head_blk <= INT_MAX &&
    -			(xfs_daddr_t) num_scan_bblks - head_blk >= 0);
    -		if ((error = xlog_find_verify_cycle(log, start_blk,
    -					num_scan_bblks - (int)head_blk,
    -					(stop_on_cycle - 1), &new_blk)))
    -			goto bp_err;
    -		if (new_blk != -1) {
    -			head_blk = new_blk;
    -			goto bad_blk;
    -		}
    -
    -		/*
    -		 * Scan beginning of log now.  The last part of the physical
    -		 * log is good.  This scan needs to verify that it doesn't find
    -		 * the last_half_cycle.
    -		 */
    -		start_blk = 0;
    -		ASSERT(head_blk <= INT_MAX);
    -		if ((error = xlog_find_verify_cycle(log,
    -					start_blk, (int)head_blk,
    -					stop_on_cycle, &new_blk)))
    -			goto bp_err;
    -		if (new_blk != -1)
    -			head_blk = new_blk;
    -	}
    -
    - bad_blk:
    -	/*
    -	 * Now we need to make sure head_blk is not pointing to a block in
    -	 * the middle of a log record.
    -	 */
    -	num_scan_bblks = XLOG_REC_SHIFT(log);
    -	if (head_blk >= num_scan_bblks) {
    -		start_blk = head_blk - num_scan_bblks; /* don't read head_blk */
    -
    -		/* start ptr at last block ptr before head_blk */
    -		if ((error = xlog_find_verify_log_record(log, start_blk,
    -							&head_blk, 0)) == -1) {
    -			error = XFS_ERROR(EIO);
    -			goto bp_err;
    -		} else if (error)
    -			goto bp_err;
    -	} else {
    -		start_blk = 0;
    -		ASSERT(head_blk <= INT_MAX);
    -		if ((error = xlog_find_verify_log_record(log, start_blk,
    -							&head_blk, 0)) == -1) {
    -			/* We hit the beginning of the log during our search */
    -			start_blk = log_bbnum - num_scan_bblks + head_blk;
    -			new_blk = log_bbnum;
    -			ASSERT(start_blk <= INT_MAX &&
    -				(xfs_daddr_t) log_bbnum-start_blk >= 0);
    -			ASSERT(head_blk <= INT_MAX);
    -			if ((error = xlog_find_verify_log_record(log,
    -							start_blk, &new_blk,
    -							(int)head_blk)) == -1) {
    -				error = XFS_ERROR(EIO);
    -				goto bp_err;
    -			} else if (error)
    -				goto bp_err;
    -			if (new_blk != log_bbnum)
    -				head_blk = new_blk;
    -		} else if (error)
    -			goto bp_err;
    -	}
    -
    -	xlog_put_bp(bp);
    -	if (head_blk == log_bbnum)
    -		*return_head_blk = 0;
    -	else
    -		*return_head_blk = head_blk;
    -	/*
    -	 * When returning here, we have a good block number.  Bad block
    -	 * means that during a previous crash, we didn't have a clean break
    -	 * from cycle number N to cycle number N-1.  In this case, we need
    -	 * to find the first block with cycle number N-1.
    -	 */
    -	return 0;
    -
    - bp_err:
    -	xlog_put_bp(bp);
    -
    -	if (error)
    -	    xlog_warn("XFS: failed to find log head");
    -	return error;
    -}
    -
    -/*
    - * Find the sync block number or the tail of the log.
    - *
    - * This will be the block number of the last record to have its
    - * associated buffers synced to disk.  Every log record header has
    - * a sync lsn embedded in it.  LSNs hold block numbers, so it is easy
    - * to get a sync block number.  The only concern is to figure out which
    - * log record header to believe.
    - *
    - * The following algorithm uses the log record header with the largest
    - * lsn.  The entire log record does not need to be valid.  We only care
    - * that the header is valid.
    - *
    - * We could speed up search by using current head_blk buffer, but it is not
    - * available.
    - */
    -int
    -xlog_find_tail(
    -	xlog_t			*log,
    -	xfs_daddr_t		*head_blk,
    -	xfs_daddr_t		*tail_blk)
    -{
    -	xlog_rec_header_t	*rhead;
    -	xlog_op_header_t	*op_head;
    -	xfs_caddr_t		offset = NULL;
    -	xfs_buf_t		*bp;
    -	int			error, i, found;
    -	xfs_daddr_t		umount_data_blk;
    -	xfs_daddr_t		after_umount_blk;
    -	xfs_lsn_t		tail_lsn;
    -	int			hblks;
    -
    -	found = 0;
    -
    -	/*
    -	 * Find previous log record
    -	 */
    -	if ((error = xlog_find_head(log, head_blk)))
    -		return error;
    -
    -	bp = xlog_get_bp(log, 1);
    -	if (!bp)
    -		return ENOMEM;
    -	if (*head_blk == 0) {				/* special case */
    -		if ((error = xlog_bread(log, 0, 1, bp)))
    -			goto bread_err;
    -		offset = xlog_align(log, 0, 1, bp);
    -		if (GET_CYCLE(offset, ARCH_CONVERT) == 0) {
    -			*tail_blk = 0;
    -			/* leave all other log inited values alone */
    -			goto exit;
    -		}
    -	}
    -
    -	/*
    -	 * Search backwards looking for log record header block
    -	 */
    -	ASSERT(*head_blk < INT_MAX);
    -	for (i = (int)(*head_blk) - 1; i >= 0; i--) {
    -		if ((error = xlog_bread(log, i, 1, bp)))
    -			goto bread_err;
    -		offset = xlog_align(log, i, 1, bp);
    -		if (XLOG_HEADER_MAGIC_NUM ==
    -		    INT_GET(*(uint *)offset, ARCH_CONVERT)) {
    -			found = 1;
    -			break;
    -		}
    -	}
    -	/*
    -	 * If we haven't found the log record header block, start looking
    -	 * again from the end of the physical log.  XXXmiken: There should be
    -	 * a check here to make sure we didn't search more than N blocks in
    -	 * the previous code.
    -	 */
    -	if (!found) {
    -		for (i = log->l_logBBsize - 1; i >= (int)(*head_blk); i--) {
    -			if ((error = xlog_bread(log, i, 1, bp)))
    -				goto bread_err;
    -			offset = xlog_align(log, i, 1, bp);
    -			if (XLOG_HEADER_MAGIC_NUM ==
    -			    INT_GET(*(uint*)offset, ARCH_CONVERT)) {
    -				found = 2;
    -				break;
    -			}
    -		}
    -	}
    -	if (!found) {
    -		xlog_warn("XFS: xlog_find_tail: couldn't find sync record");
    -		ASSERT(0);
    -		return XFS_ERROR(EIO);
    -	}
    -
    -	/* find blk_no of tail of log */
    -	rhead = (xlog_rec_header_t *)offset;
    -	*tail_blk = BLOCK_LSN(INT_GET(rhead->h_tail_lsn, ARCH_CONVERT));
    -
    -	/*
    -	 * Reset log values according to the state of the log when we
    -	 * crashed.  In the case where head_blk == 0, we bump curr_cycle
    -	 * one because the next write starts a new cycle rather than
    -	 * continuing the cycle of the last good log record.  At this
    -	 * point we have guaranteed that all partial log records have been
    -	 * accounted for.  Therefore, we know that the last good log record
    -	 * written was complete and ended exactly on the end boundary
    -	 * of the physical log.
    -	 */
    -	log->l_prev_block = i;
    -	log->l_curr_block = (int)*head_blk;
    -	log->l_curr_cycle = INT_GET(rhead->h_cycle, ARCH_CONVERT);
    -	if (found == 2)
    -		log->l_curr_cycle++;
    -	log->l_tail_lsn = INT_GET(rhead->h_tail_lsn, ARCH_CONVERT);
    -	log->l_last_sync_lsn = INT_GET(rhead->h_lsn, ARCH_CONVERT);
    -	log->l_grant_reserve_cycle = log->l_curr_cycle;
    -	log->l_grant_reserve_bytes = BBTOB(log->l_curr_block);
    -	log->l_grant_write_cycle = log->l_curr_cycle;
    -	log->l_grant_write_bytes = BBTOB(log->l_curr_block);
    -
    -	/*
    -	 * Look for unmount record.  If we find it, then we know there
    -	 * was a clean unmount.  Since 'i' could be the last block in
    -	 * the physical log, we convert to a log block before comparing
    -	 * to the head_blk.
    -	 *
    -	 * Save the current tail lsn to use to pass to
    -	 * xlog_clear_stale_blocks() below.  We won't want to clear the
    -	 * unmount record if there is one, so we pass the lsn of the
    -	 * unmount record rather than the block after it.
    -	 */
    -	if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) {
    -		int	h_size = INT_GET(rhead->h_size, ARCH_CONVERT);
    -		int	h_version = INT_GET(rhead->h_version, ARCH_CONVERT);
    -
    -		if ((h_version & XLOG_VERSION_2) &&
    -		    (h_size > XLOG_HEADER_CYCLE_SIZE)) {
    -			hblks = h_size / XLOG_HEADER_CYCLE_SIZE;
    -			if (h_size % XLOG_HEADER_CYCLE_SIZE)
    -				hblks++;
    -		} else {
    -			hblks = 1;
    -		}
    -	} else {
    -		hblks = 1;
    -	}
    -	after_umount_blk = (i + hblks + (int)
    -		BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT))) % log->l_logBBsize;
    -	tail_lsn = log->l_tail_lsn;
    -	if (*head_blk == after_umount_blk &&
    -	    INT_GET(rhead->h_num_logops, ARCH_CONVERT) == 1) {
    -		umount_data_blk = (i + hblks) % log->l_logBBsize;
    -		if ((error = xlog_bread(log, umount_data_blk, 1, bp))) {
    -			goto bread_err;
    -		}
    -		offset = xlog_align(log, umount_data_blk, 1, bp);
    -		op_head = (xlog_op_header_t *)offset;
    -		if (op_head->oh_flags & XLOG_UNMOUNT_TRANS) {
    -			/*
    -			 * Set tail and last sync so that newly written
    -			 * log records will point recovery to after the
    -			 * current unmount record.
    -			 */
    -			ASSIGN_ANY_LSN_HOST(log->l_tail_lsn, log->l_curr_cycle,
    -					after_umount_blk);
    -			ASSIGN_ANY_LSN_HOST(log->l_last_sync_lsn, log->l_curr_cycle,
    -					after_umount_blk);
    -			*tail_blk = after_umount_blk;
    -		}
    -	}
    -
    -	/*
    -	 * Make sure that there are no blocks in front of the head
    -	 * with the same cycle number as the head.  This can happen
    -	 * because we allow multiple outstanding log writes concurrently,
    -	 * and the later writes might make it out before earlier ones.
    -	 *
    -	 * We use the lsn from before modifying it so that we'll never
    -	 * overwrite the unmount record after a clean unmount.
    -	 *
    -	 * Do this only if we are going to recover the filesystem
    -	 *
    -	 * NOTE: This used to say "if (!readonly)"
    -	 * However on Linux, we can & do recover a read-only filesystem.
    -	 * We only skip recovery if NORECOVERY is specified on mount,
    -	 * in which case we would not be here.
    -	 *
    -	 * But... if the -device- itself is readonly, just skip this.
    -	 * We can't recover this device anyway, so it won't matter.
    -	 */
    -	if (!xfs_readonly_buftarg(log->l_mp->m_logdev_targp)) {
    -		error = xlog_clear_stale_blocks(log, tail_lsn);
    -	}
    -
    -bread_err:
    -exit:
    -	xlog_put_bp(bp);
    -
    -	if (error)
    -		xlog_warn("XFS: failed to locate log tail");
    -	return error;
    -}
    -
    -/*
    - * Is the log zeroed at all?
    - *
    - * The last binary search should be changed to perform an X block read
    - * once X becomes small enough.  You can then search linearly through
    - * the X blocks.  This will cut down on the number of reads we need to do.
    - *
    - * If the log is partially zeroed, this routine will pass back the blkno
    - * of the first block with cycle number 0.  It won't have a complete LR
    - * preceding it.
    - *
    - * Return:
    - *	0  => the log is completely written to
    - *	-1 => use *blk_no as the first block of the log
    - *	>0 => error has occurred
    - */
    -int
    -xlog_find_zeroed(
    -	xlog_t		*log,
    -	xfs_daddr_t	*blk_no)
    -{
    -	xfs_buf_t	*bp;
    -	xfs_caddr_t	offset;
    -	uint	        first_cycle, last_cycle;
    -	xfs_daddr_t	new_blk, last_blk, start_blk;
    -	xfs_daddr_t     num_scan_bblks;
    -	int	        error, log_bbnum = log->l_logBBsize;
    -
    -	/* check totally zeroed log */
    -	bp = xlog_get_bp(log, 1);
    -	if (!bp)
    -		return ENOMEM;
    -	if ((error = xlog_bread(log, 0, 1, bp)))
    -		goto bp_err;
    -	offset = xlog_align(log, 0, 1, bp);
    -	first_cycle = GET_CYCLE(offset, ARCH_CONVERT);
    -	if (first_cycle == 0) {		/* completely zeroed log */
    -		*blk_no = 0;
    -		xlog_put_bp(bp);
    -		return -1;
    -	}
    -
    -	/* check partially zeroed log */
    -	if ((error = xlog_bread(log, log_bbnum-1, 1, bp)))
    -		goto bp_err;
    -	offset = xlog_align(log, log_bbnum-1, 1, bp);
    -	last_cycle = GET_CYCLE(offset, ARCH_CONVERT);
    -	if (last_cycle != 0) {		/* log completely written to */
    -		xlog_put_bp(bp);
    -		return 0;
    -	} else if (first_cycle != 1) {
    -		/*
    -		 * If the cycle of the last block is zero, the cycle of
    -		 * the first block must be 1. If it's not, maybe we're
    -		 * not looking at a log... Bail out.
    -		 */
    -		xlog_warn("XFS: Log inconsistent or not a log (last==0, first!=1)");
    -		return XFS_ERROR(EINVAL);
    -	}
    -
    -	/* we have a partially zeroed log */
    -	last_blk = log_bbnum-1;
    -	if ((error = xlog_find_cycle_start(log, bp, 0, &last_blk, 0)))
    -		goto bp_err;
    -
    -	/*
    -	 * Validate the answer.  Because there is no way to guarantee that
    -	 * the entire log is made up of log records which are the same size,
    -	 * we scan over the defined maximum blocks.  At this point, the maximum
    -	 * is not chosen to mean anything special.   XXXmiken
    -	 */
    -	num_scan_bblks = XLOG_TOTAL_REC_SHIFT(log);
    -	ASSERT(num_scan_bblks <= INT_MAX);
    -
    -	if (last_blk < num_scan_bblks)
    -		num_scan_bblks = last_blk;
    -	start_blk = last_blk - num_scan_bblks;
    -
    -	/*
    -	 * We search for any instances of cycle number 0 that occur before
    -	 * our current estimate of the head.  What we're trying to detect is
    -	 *        1 ... | 0 | 1 | 0...
    -	 *                       ^ binary search ends here
    -	 */
    -	if ((error = xlog_find_verify_cycle(log, start_blk,
    -					 (int)num_scan_bblks, 0, &new_blk)))
    -		goto bp_err;
    -	if (new_blk != -1)
    -		last_blk = new_blk;
    -
    -	/*
    -	 * Potentially backup over partial log record write.  We don't need
    -	 * to search the end of the log because we know it is zero.
    -	 */
    -	if ((error = xlog_find_verify_log_record(log, start_blk,
    -				&last_blk, 0)) == -1) {
    -	    error = XFS_ERROR(EIO);
    -	    goto bp_err;
    -	} else if (error)
    -	    goto bp_err;
    -
    -	*blk_no = last_blk;
    -bp_err:
    -	xlog_put_bp(bp);
    -	if (error)
    -		return error;
    -	return -1;
    -}
    -
    -/*
    - * These are simple subroutines used by xlog_clear_stale_blocks() below
    - * to initialize a buffer full of empty log record headers and write
    - * them into the log.
    - */
    -STATIC void
    -xlog_add_record(
    -	xlog_t			*log,
    -	xfs_caddr_t		buf,
    -	int			cycle,
    -	int			block,
    -	int			tail_cycle,
    -	int			tail_block)
    -{
    -	xlog_rec_header_t	*recp = (xlog_rec_header_t *)buf;
    -
    -	memset(buf, 0, BBSIZE);
    -	INT_SET(recp->h_magicno, ARCH_CONVERT, XLOG_HEADER_MAGIC_NUM);
    -	INT_SET(recp->h_cycle, ARCH_CONVERT, cycle);
    -	INT_SET(recp->h_version, ARCH_CONVERT,
    -			XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb) ? 2 : 1);
    -	ASSIGN_ANY_LSN_DISK(recp->h_lsn, cycle, block);
    -	ASSIGN_ANY_LSN_DISK(recp->h_tail_lsn, tail_cycle, tail_block);
    -	INT_SET(recp->h_fmt, ARCH_CONVERT, XLOG_FMT);
    -	memcpy(&recp->h_fs_uuid, &log->l_mp->m_sb.sb_uuid, sizeof(uuid_t));
    -}
    -
    -STATIC int
    -xlog_write_log_records(
    -	xlog_t		*log,
    -	int		cycle,
    -	int		start_block,
    -	int		blocks,
    -	int		tail_cycle,
    -	int		tail_block)
    -{
    -	xfs_caddr_t	offset;
    -	xfs_buf_t	*bp;
    -	int		balign, ealign;
    -	int		sectbb = XLOG_SECTOR_ROUNDUP_BBCOUNT(log, 1);
    -	int		end_block = start_block + blocks;
    -	int		bufblks;
    -	int		error = 0;
    -	int		i, j = 0;
    -
    -	bufblks = 1 << ffs(blocks);
    -	while (!(bp = xlog_get_bp(log, bufblks))) {
    -		bufblks >>= 1;
    -		if (bufblks <= log->l_sectbb_log)
    -			return ENOMEM;
    -	}
    -
    -	/* We may need to do a read at the start to fill in part of
    -	 * the buffer in the starting sector not covered by the first
    -	 * write below.
    -	 */
    -	balign = XLOG_SECTOR_ROUNDDOWN_BLKNO(log, start_block);
    -	if (balign != start_block) {
    -		if ((error = xlog_bread(log, start_block, 1, bp))) {
    -			xlog_put_bp(bp);
    -			return error;
    -		}
    -		j = start_block - balign;
    -	}
    -
    -	for (i = start_block; i < end_block; i += bufblks) {
    -		int		bcount, endcount;
    -
    -		bcount = min(bufblks, end_block - start_block);
    -		endcount = bcount - j;
    -
    -		/* We may need to do a read at the end to fill in part of
    -		 * the buffer in the final sector not covered by the write.
    -		 * If this is the same sector as the above read, skip it.
    -		 */
    -		ealign = XLOG_SECTOR_ROUNDDOWN_BLKNO(log, end_block);
    -		if (j == 0 && (start_block + endcount > ealign)) {
    -			offset = XFS_BUF_PTR(bp);
    -			balign = BBTOB(ealign - start_block);
    -			XFS_BUF_SET_PTR(bp, offset + balign, BBTOB(sectbb));
    -			if ((error = xlog_bread(log, ealign, sectbb, bp)))
    -				break;
    -			XFS_BUF_SET_PTR(bp, offset, bufblks);
    -		}
    -
    -		offset = xlog_align(log, start_block, endcount, bp);
    -		for (; j < endcount; j++) {
    -			xlog_add_record(log, offset, cycle, i+j,
    -					tail_cycle, tail_block);
    -			offset += BBSIZE;
    -		}
    -		error = xlog_bwrite(log, start_block, endcount, bp);
    -		if (error)
    -			break;
    -		start_block += endcount;
    -		j = 0;
    -	}
    -	xlog_put_bp(bp);
    -	return error;
    -}
    -
    -/*
    - * This routine is called to blow away any incomplete log writes out
    - * in front of the log head.  We do this so that we won't become confused
    - * if we come up, write only a little bit more, and then crash again.
    - * If we leave the partial log records out there, this situation could
    - * cause us to think those partial writes are valid blocks since they
    - * have the current cycle number.  We get rid of them by overwriting them
    - * with empty log records with the old cycle number rather than the
    - * current one.
    - *
    - * The tail lsn is passed in rather than taken from
    - * the log so that we will not write over the unmount record after a
    - * clean unmount in a 512 block log.  Doing so would leave the log without
    - * any valid log records in it until a new one was written.  If we crashed
    - * during that time we would not be able to recover.
    - */
    -STATIC int
    -xlog_clear_stale_blocks(
    -	xlog_t		*log,
    -	xfs_lsn_t	tail_lsn)
    -{
    -	int		tail_cycle, head_cycle;
    -	int		tail_block, head_block;
    -	int		tail_distance, max_distance;
    -	int		distance;
    -	int		error;
    -
    -	tail_cycle = CYCLE_LSN(tail_lsn);
    -	tail_block = BLOCK_LSN(tail_lsn);
    -	head_cycle = log->l_curr_cycle;
    -	head_block = log->l_curr_block;
    -
    -	/*
    -	 * Figure out the distance between the new head of the log
    -	 * and the tail.  We want to write over any blocks beyond the
    -	 * head that we may have written just before the crash, but
    -	 * we don't want to overwrite the tail of the log.
    -	 */
    -	if (head_cycle == tail_cycle) {
    -		/*
    -		 * The tail is behind the head in the physical log,
    -		 * so the distance from the head to the tail is the
    -		 * distance from the head to the end of the log plus
    -		 * the distance from the beginning of the log to the
    -		 * tail.
    -		 */
    -		if (unlikely(head_block < tail_block || head_block >= log->l_logBBsize)) {
    -			XFS_ERROR_REPORT("xlog_clear_stale_blocks(1)",
    -					 XFS_ERRLEVEL_LOW, log->l_mp);
    -			return XFS_ERROR(EFSCORRUPTED);
    -		}
    -		tail_distance = tail_block + (log->l_logBBsize - head_block);
    -	} else {
    -		/*
    -		 * The head is behind the tail in the physical log,
    -		 * so the distance from the head to the tail is just
    -		 * the tail block minus the head block.
    -		 */
    -		if (unlikely(head_block >= tail_block || head_cycle != (tail_cycle + 1))){
    -			XFS_ERROR_REPORT("xlog_clear_stale_blocks(2)",
    -					 XFS_ERRLEVEL_LOW, log->l_mp);
    -			return XFS_ERROR(EFSCORRUPTED);
    -		}
    -		tail_distance = tail_block - head_block;
    -	}
    -
    -	/*
    -	 * If the head is right up against the tail, we can't clear
    -	 * anything.
    -	 */
    -	if (tail_distance <= 0) {
    -		ASSERT(tail_distance == 0);
    -		return 0;
    -	}
    -
    -	max_distance = XLOG_TOTAL_REC_SHIFT(log);
    -	/*
    -	 * Take the smaller of the maximum amount of outstanding I/O
    -	 * we could have and the distance to the tail to clear out.
    -	 * We take the smaller so that we don't overwrite the tail and
    -	 * we don't waste all day writing from the head to the tail
    -	 * for no reason.
    -	 */
    -	max_distance = MIN(max_distance, tail_distance);
    -
    -	if ((head_block + max_distance) <= log->l_logBBsize) {
    -		/*
    -		 * We can stomp all the blocks we need to without
    -		 * wrapping around the end of the log.  Just do it
    -		 * in a single write.  Use the cycle number of the
    -		 * current cycle minus one so that the log will look like:
    -		 *     n ... | n - 1 ...
    -		 */
    -		error = xlog_write_log_records(log, (head_cycle - 1),
    -				head_block, max_distance, tail_cycle,
    -				tail_block);
    -		if (error)
    -			return error;
    -	} else {
    -		/*
    -		 * We need to wrap around the end of the physical log in
    -		 * order to clear all the blocks.  Do it in two separate
    -		 * I/Os.  The first write should be from the head to the
    -		 * end of the physical log, and it should use the current
    -		 * cycle number minus one just like above.
    -		 */
    -		distance = log->l_logBBsize - head_block;
    -		error = xlog_write_log_records(log, (head_cycle - 1),
    -				head_block, distance, tail_cycle,
    -				tail_block);
    -
    -		if (error)
    -			return error;
    -
    -		/*
    -		 * Now write the blocks at the start of the physical log.
    -		 * This writes the remainder of the blocks we want to clear.
    -		 * It uses the current cycle number since we're now on the
    -		 * same cycle as the head so that we get:
    -		 *    n ... n ... | n - 1 ...
    -		 *    ^^^^^ blocks we're writing
    -		 */
    -		distance = max_distance - (log->l_logBBsize - head_block);
    -		error = xlog_write_log_records(log, head_cycle, 0, distance,
    -				tail_cycle, tail_block);
    -		if (error)
    -			return error;
    -	}
    -
    -	return 0;
    -}
    -
    -/******************************************************************************
    - *
    - *		Log recover routines
    - *
    - ******************************************************************************
    - */
    -
    -STATIC xlog_recover_t *
    -xlog_recover_find_tid(
    -	xlog_recover_t		*q,
    -	xlog_tid_t		tid)
    -{
    -	xlog_recover_t		*p = q;
    -
    -	while (p != NULL) {
    -		if (p->r_log_tid == tid)
    -		    break;
    -		p = p->r_next;
    -	}
    -	return p;
    -}
    -
    -STATIC void
    -xlog_recover_put_hashq(
    -	xlog_recover_t		**q,
    -	xlog_recover_t		*trans)
    -{
    -	trans->r_next = *q;
    -	*q = trans;
    -}
    -
    -STATIC void
    -xlog_recover_add_item(
    -	xlog_recover_item_t	**itemq)
    -{
    -	xlog_recover_item_t	*item;
    -
    -	item = kmem_zalloc(sizeof(xlog_recover_item_t), KM_SLEEP);
    -	xlog_recover_insert_item_backq(itemq, item);
    -}
    -
    -STATIC int
    -xlog_recover_add_to_cont_trans(
    -	xlog_recover_t		*trans,
    -	xfs_caddr_t		dp,
    -	int			len)
    -{
    -	xlog_recover_item_t	*item;
    -	xfs_caddr_t		ptr, old_ptr;
    -	int			old_len;
    -
    -	item = trans->r_itemq;
    -	if (item == 0) {
    -		/* finish copying rest of trans header */
    -		xlog_recover_add_item(&trans->r_itemq);
    -		ptr = (xfs_caddr_t) &trans->r_theader +
    -				sizeof(xfs_trans_header_t) - len;
    -		memcpy(ptr, dp, len); /* d, s, l */
    -		return 0;
    -	}
    -	item = item->ri_prev;
    -
    -	old_ptr = item->ri_buf[item->ri_cnt-1].i_addr;
    -	old_len = item->ri_buf[item->ri_cnt-1].i_len;
    -
    -	ptr = kmem_realloc(old_ptr, len+old_len, old_len, 0u);
    -	memcpy(&ptr[old_len], dp, len); /* d, s, l */
    -	item->ri_buf[item->ri_cnt-1].i_len += len;
    -	item->ri_buf[item->ri_cnt-1].i_addr = ptr;
    -	return 0;
    -}
    -
    -/*
    - * The next region to add is the start of a new region.  It could be
    - * a whole region or it could be the first part of a new region.  Because
    - * of this, the assumption here is that the type and size fields of all
    - * format structures fit into the first 32 bits of the structure.
    - *
    - * This works because all regions must be 32 bit aligned.  Therefore, we
    - * either have both fields or we have neither field.  In the case we have
    - * neither field, the data part of the region is zero length.  We only have
    - * a log_op_header and can throw away the header since a new one will appear
    - * later.  If we have at least 4 bytes, then we can determine how many regions
    - * will appear in the current log item.
    - */
    -STATIC int
    -xlog_recover_add_to_trans(
    -	xlog_recover_t		*trans,
    -	xfs_caddr_t		dp,
    -	int			len)
    -{
    -	xfs_inode_log_format_t	*in_f;			/* any will do */
    -	xlog_recover_item_t	*item;
    -	xfs_caddr_t		ptr;
    -
    -	if (!len)
    -		return 0;
    -	item = trans->r_itemq;
    -	if (item == 0) {
    -		ASSERT(*(uint *)dp == XFS_TRANS_HEADER_MAGIC);
    -		if (len == sizeof(xfs_trans_header_t))
    -			xlog_recover_add_item(&trans->r_itemq);
    -		memcpy(&trans->r_theader, dp, len); /* d, s, l */
    -		return 0;
    -	}
    -
    -	ptr = kmem_alloc(len, KM_SLEEP);
    -	memcpy(ptr, dp, len);
    -	in_f = (xfs_inode_log_format_t *)ptr;
    -
    -	if (item->ri_prev->ri_total != 0 &&
    -	     item->ri_prev->ri_total == item->ri_prev->ri_cnt) {
    -		xlog_recover_add_item(&trans->r_itemq);
    -	}
    -	item = trans->r_itemq;
    -	item = item->ri_prev;
    -
    -	if (item->ri_total == 0) {		/* first region to be added */
    -		item->ri_total	= in_f->ilf_size;
    -		ASSERT(item->ri_total <= XLOG_MAX_REGIONS_IN_ITEM);
    -		item->ri_buf = kmem_zalloc((item->ri_total *
    -					    sizeof(xfs_log_iovec_t)), KM_SLEEP);
    -	}
    -	ASSERT(item->ri_total > item->ri_cnt);
    -	/* Description region is ri_buf[0] */
    -	item->ri_buf[item->ri_cnt].i_addr = ptr;
    -	item->ri_buf[item->ri_cnt].i_len  = len;
    -	item->ri_cnt++;
    -	return 0;
    -}
    -
    -STATIC void
    -xlog_recover_new_tid(
    -	xlog_recover_t		**q,
    -	xlog_tid_t		tid,
    -	xfs_lsn_t		lsn)
    -{
    -	xlog_recover_t		*trans;
    -
    -	trans = kmem_zalloc(sizeof(xlog_recover_t), KM_SLEEP);
    -	trans->r_log_tid   = tid;
    -	trans->r_lsn	   = lsn;
    -	xlog_recover_put_hashq(q, trans);
    -}
    -
    -STATIC int
    -xlog_recover_unlink_tid(
    -	xlog_recover_t		**q,
    -	xlog_recover_t		*trans)
    -{
    -	xlog_recover_t		*tp;
    -	int			found = 0;
    -
    -	ASSERT(trans != 0);
    -	if (trans == *q) {
    -		*q = (*q)->r_next;
    -	} else {
    -		tp = *q;
    -		while (tp != 0) {
    -			if (tp->r_next == trans) {
    -				found = 1;
    -				break;
    -			}
    -			tp = tp->r_next;
    -		}
    -		if (!found) {
    -			xlog_warn(
    -			     "XFS: xlog_recover_unlink_tid: trans not found");
    -			ASSERT(0);
    -			return XFS_ERROR(EIO);
    -		}
    -		tp->r_next = tp->r_next->r_next;
    -	}
    -	return 0;
    -}
    -
    -STATIC void
    -xlog_recover_insert_item_backq(
    -	xlog_recover_item_t	**q,
    -	xlog_recover_item_t	*item)
    -{
    -	if (*q == 0) {
    -		item->ri_prev = item->ri_next = item;
    -		*q = item;
    -	} else {
    -		item->ri_next		= *q;
    -		item->ri_prev		= (*q)->ri_prev;
    -		(*q)->ri_prev		= item;
    -		item->ri_prev->ri_next	= item;
    -	}
    -}
    -
    -STATIC void
    -xlog_recover_insert_item_frontq(
    -	xlog_recover_item_t	**q,
    -	xlog_recover_item_t	*item)
    -{
    -	xlog_recover_insert_item_backq(q, item);
    -	*q = item;
    -}
    -
    -STATIC int
    -xlog_recover_reorder_trans(
    -	xlog_t			*log,
    -	xlog_recover_t		*trans)
    -{
    -	xlog_recover_item_t	*first_item, *itemq, *itemq_next;
    -	xfs_buf_log_format_t	*buf_f;
    -	xfs_buf_log_format_v1_t	*obuf_f;
    -	ushort			flags = 0;
    -
    -	first_item = itemq = trans->r_itemq;
    -	trans->r_itemq = NULL;
    -	do {
    -		itemq_next = itemq->ri_next;
    -		buf_f = (xfs_buf_log_format_t *)itemq->ri_buf[0].i_addr;
    -		switch (ITEM_TYPE(itemq)) {
    -		case XFS_LI_BUF:
    -			flags = buf_f->blf_flags;
    -			break;
    -		case XFS_LI_6_1_BUF:
    -		case XFS_LI_5_3_BUF:
    -			obuf_f = (xfs_buf_log_format_v1_t*)buf_f;
    -			flags = obuf_f->blf_flags;
    -			break;
    -		}
    -
    -		switch (ITEM_TYPE(itemq)) {
    -		case XFS_LI_BUF:
    -		case XFS_LI_6_1_BUF:
    -		case XFS_LI_5_3_BUF:
    -			if (!(flags & XFS_BLI_CANCEL)) {
    -				xlog_recover_insert_item_frontq(&trans->r_itemq,
    -								itemq);
    -				break;
    -			}
    -		case XFS_LI_INODE:
    -		case XFS_LI_6_1_INODE:
    -		case XFS_LI_5_3_INODE:
    -		case XFS_LI_DQUOT:
    -		case XFS_LI_QUOTAOFF:
    -		case XFS_LI_EFD:
    -		case XFS_LI_EFI:
    -			xlog_recover_insert_item_backq(&trans->r_itemq, itemq);
    -			break;
    -		default:
    -			xlog_warn(
    -	"XFS: xlog_recover_reorder_trans: unrecognized type of log operation");
    -			ASSERT(0);
    -			return XFS_ERROR(EIO);
    -		}
    -		itemq = itemq_next;
    -	} while (first_item != itemq);
    -	return 0;
    -}
    -
    -/*
    - * Build up the table of buf cancel records so that we don't replay
    - * cancelled data in the second pass.  For buffer records that are
    - * not cancel records, there is nothing to do here so we just return.
    - *
    - * If we get a cancel record which is already in the table, this indicates
    - * that the buffer was cancelled multiple times.  In order to ensure
    - * that during pass 2 we keep the record in the table until we reach its
    - * last occurrence in the log, we keep a reference count in the cancel
    - * record in the table to tell us how many times we expect to see this
    - * record during the second pass.
    - */
    -STATIC void
    -xlog_recover_do_buffer_pass1(
    -	xlog_t			*log,
    -	xfs_buf_log_format_t	*buf_f)
    -{
    -	xfs_buf_cancel_t	*bcp;
    -	xfs_buf_cancel_t	*nextp;
    -	xfs_buf_cancel_t	*prevp;
    -	xfs_buf_cancel_t	**bucket;
    -	xfs_buf_log_format_v1_t	*obuf_f;
    -	xfs_daddr_t		blkno = 0;
    -	uint			len = 0;
    -	ushort			flags = 0;
    -
    -	switch (buf_f->blf_type) {
    -	case XFS_LI_BUF:
    -		blkno = buf_f->blf_blkno;
    -		len = buf_f->blf_len;
    -		flags = buf_f->blf_flags;
    -		break;
    -	case XFS_LI_6_1_BUF:
    -	case XFS_LI_5_3_BUF:
    -		obuf_f = (xfs_buf_log_format_v1_t*)buf_f;
    -		blkno = (xfs_daddr_t) obuf_f->blf_blkno;
    -		len = obuf_f->blf_len;
    -		flags = obuf_f->blf_flags;
    -		break;
    -	}
    -
    -	/*
    -	 * If this isn't a cancel buffer item, then just return.
    -	 */
    -	if (!(flags & XFS_BLI_CANCEL))
    -		return;
    -
    -	/*
    -	 * Insert an xfs_buf_cancel record into the hash table of
    -	 * them.  If there is already an identical record, bump
    -	 * its reference count.
    -	 */
    -	bucket = &log->l_buf_cancel_table[(__uint64_t)blkno %
    -					  XLOG_BC_TABLE_SIZE];
    -	/*
    -	 * If the hash bucket is empty then just insert a new record into
    -	 * the bucket.
    -	 */
    -	if (*bucket == NULL) {
    -		bcp = (xfs_buf_cancel_t *)kmem_alloc(sizeof(xfs_buf_cancel_t),
    -						     KM_SLEEP);
    -		bcp->bc_blkno = blkno;
    -		bcp->bc_len = len;
    -		bcp->bc_refcount = 1;
    -		bcp->bc_next = NULL;
    -		*bucket = bcp;
    -		return;
    -	}
    -
    -	/*
    -	 * The hash bucket is not empty, so search for duplicates of our
    -	 * record.  If we find one them just bump its refcount.  If not
    -	 * then add us at the end of the list.
    -	 */
    -	prevp = NULL;
    -	nextp = *bucket;
    -	while (nextp != NULL) {
    -		if (nextp->bc_blkno == blkno && nextp->bc_len == len) {
    -			nextp->bc_refcount++;
    -			return;
    -		}
    -		prevp = nextp;
    -		nextp = nextp->bc_next;
    -	}
    -	ASSERT(prevp != NULL);
    -	bcp = (xfs_buf_cancel_t *)kmem_alloc(sizeof(xfs_buf_cancel_t),
    -					     KM_SLEEP);
    -	bcp->bc_blkno = blkno;
    -	bcp->bc_len = len;
    -	bcp->bc_refcount = 1;
    -	bcp->bc_next = NULL;
    -	prevp->bc_next = bcp;
    -}
    -
    -/*
    - * Check to see whether the buffer being recovered has a corresponding
    - * entry in the buffer cancel record table.  If it does then return 1
    - * so that it will be cancelled, otherwise return 0.  If the buffer is
    - * actually a buffer cancel item (XFS_BLI_CANCEL is set), then decrement
    - * the refcount on the entry in the table and remove it from the table
    - * if this is the last reference.
    - *
    - * We remove the cancel record from the table when we encounter its
    - * last occurrence in the log so that if the same buffer is re-used
    - * again after its last cancellation we actually replay the changes
    - * made at that point.
    - */
    -STATIC int
    -xlog_check_buffer_cancelled(
    -	xlog_t			*log,
    -	xfs_daddr_t		blkno,
    -	uint			len,
    -	ushort			flags)
    -{
    -	xfs_buf_cancel_t	*bcp;
    -	xfs_buf_cancel_t	*prevp;
    -	xfs_buf_cancel_t	**bucket;
    -
    -	if (log->l_buf_cancel_table == NULL) {
    -		/*
    -		 * There is nothing in the table built in pass one,
    -		 * so this buffer must not be cancelled.
    -		 */
    -		ASSERT(!(flags & XFS_BLI_CANCEL));
    -		return 0;
    -	}
    -
    -	bucket = &log->l_buf_cancel_table[(__uint64_t)blkno %
    -					  XLOG_BC_TABLE_SIZE];
    -	bcp = *bucket;
    -	if (bcp == NULL) {
    -		/*
    -		 * There is no corresponding entry in the table built
    -		 * in pass one, so this buffer has not been cancelled.
    -		 */
    -		ASSERT(!(flags & XFS_BLI_CANCEL));
    -		return 0;
    -	}
    -
    -	/*
    -	 * Search for an entry in the buffer cancel table that
    -	 * matches our buffer.
    -	 */
    -	prevp = NULL;
    -	while (bcp != NULL) {
    -		if (bcp->bc_blkno == blkno && bcp->bc_len == len) {
    -			/*
    -			 * We've go a match, so return 1 so that the
    -			 * recovery of this buffer is cancelled.
    -			 * If this buffer is actually a buffer cancel
    -			 * log item, then decrement the refcount on the
    -			 * one in the table and remove it if this is the
    -			 * last reference.
    -			 */
    -			if (flags & XFS_BLI_CANCEL) {
    -				bcp->bc_refcount--;
    -				if (bcp->bc_refcount == 0) {
    -					if (prevp == NULL) {
    -						*bucket = bcp->bc_next;
    -					} else {
    -						prevp->bc_next = bcp->bc_next;
    -					}
    -					kmem_free(bcp,
    -						  sizeof(xfs_buf_cancel_t));
    -				}
    -			}
    -			return 1;
    -		}
    -		prevp = bcp;
    -		bcp = bcp->bc_next;
    -	}
    -	/*
    -	 * We didn't find a corresponding entry in the table, so
    -	 * return 0 so that the buffer is NOT cancelled.
    -	 */
    -	ASSERT(!(flags & XFS_BLI_CANCEL));
    -	return 0;
    -}
    -
    -STATIC int
    -xlog_recover_do_buffer_pass2(
    -	xlog_t			*log,
    -	xfs_buf_log_format_t	*buf_f)
    -{
    -	xfs_buf_log_format_v1_t	*obuf_f;
    -	xfs_daddr_t		blkno = 0;
    -	ushort			flags = 0;
    -	uint			len = 0;
    -
    -	switch (buf_f->blf_type) {
    -	case XFS_LI_BUF:
    -		blkno = buf_f->blf_blkno;
    -		flags = buf_f->blf_flags;
    -		len = buf_f->blf_len;
    -		break;
    -	case XFS_LI_6_1_BUF:
    -	case XFS_LI_5_3_BUF:
    -		obuf_f = (xfs_buf_log_format_v1_t*)buf_f;
    -		blkno = (xfs_daddr_t) obuf_f->blf_blkno;
    -		flags = obuf_f->blf_flags;
    -		len = (xfs_daddr_t) obuf_f->blf_len;
    -		break;
    -	}
    -
    -	return xlog_check_buffer_cancelled(log, blkno, len, flags);
    -}
    -
    -/*
    - * Perform recovery for a buffer full of inodes.  In these buffers,
    - * the only data which should be recovered is that which corresponds
    - * to the di_next_unlinked pointers in the on disk inode structures.
    - * The rest of the data for the inodes is always logged through the
    - * inodes themselves rather than the inode buffer and is recovered
    - * in xlog_recover_do_inode_trans().
    - *
    - * The only time when buffers full of inodes are fully recovered is
    - * when the buffer is full of newly allocated inodes.  In this case
    - * the buffer will not be marked as an inode buffer and so will be
    - * sent to xlog_recover_do_reg_buffer() below during recovery.
    - */
    -STATIC int
    -xlog_recover_do_inode_buffer(
    -	xfs_mount_t		*mp,
    -	xlog_recover_item_t	*item,
    -	xfs_buf_t		*bp,
    -	xfs_buf_log_format_t	*buf_f)
    -{
    -	int			i;
    -	int			item_index;
    -	int			bit;
    -	int			nbits;
    -	int			reg_buf_offset;
    -	int			reg_buf_bytes;
    -	int			next_unlinked_offset;
    -	int			inodes_per_buf;
    -	xfs_agino_t		*logged_nextp;
    -	xfs_agino_t		*buffer_nextp;
    -	xfs_buf_log_format_v1_t	*obuf_f;
    -	unsigned int		*data_map = NULL;
    -	unsigned int		map_size = 0;
    -
    -	switch (buf_f->blf_type) {
    -	case XFS_LI_BUF:
    -		data_map = buf_f->blf_data_map;
    -		map_size = buf_f->blf_map_size;
    -		break;
    -	case XFS_LI_6_1_BUF:
    -	case XFS_LI_5_3_BUF:
    -		obuf_f = (xfs_buf_log_format_v1_t*)buf_f;
    -		data_map = obuf_f->blf_data_map;
    -		map_size = obuf_f->blf_map_size;
    -		break;
    -	}
    -	/*
    -	 * Set the variables corresponding to the current region to
    -	 * 0 so that we'll initialize them on the first pass through
    -	 * the loop.
    -	 */
    -	reg_buf_offset = 0;
    -	reg_buf_bytes = 0;
    -	bit = 0;
    -	nbits = 0;
    -	item_index = 0;
    -	inodes_per_buf = XFS_BUF_COUNT(bp) >> mp->m_sb.sb_inodelog;
    -	for (i = 0; i < inodes_per_buf; i++) {
    -		next_unlinked_offset = (i * mp->m_sb.sb_inodesize) +
    -			offsetof(xfs_dinode_t, di_next_unlinked);
    -
    -		while (next_unlinked_offset >=
    -		       (reg_buf_offset + reg_buf_bytes)) {
    -			/*
    -			 * The next di_next_unlinked field is beyond
    -			 * the current logged region.  Find the next
    -			 * logged region that contains or is beyond
    -			 * the current di_next_unlinked field.
    -			 */
    -			bit += nbits;
    -			bit = xfs_next_bit(data_map, map_size, bit);
    -
    -			/*
    -			 * If there are no more logged regions in the
    -			 * buffer, then we're done.
    -			 */
    -			if (bit == -1) {
    -				return 0;
    -			}
    -
    -			nbits = xfs_contig_bits(data_map, map_size,
    -							 bit);
    -			ASSERT(nbits > 0);
    -			reg_buf_offset = bit << XFS_BLI_SHIFT;
    -			reg_buf_bytes = nbits << XFS_BLI_SHIFT;
    -			item_index++;
    -		}
    -
    -		/*
    -		 * If the current logged region starts after the current
    -		 * di_next_unlinked field, then move on to the next
    -		 * di_next_unlinked field.
    -		 */
    -		if (next_unlinked_offset < reg_buf_offset) {
    -			continue;
    -		}
    -
    -		ASSERT(item->ri_buf[item_index].i_addr != NULL);
    -		ASSERT((item->ri_buf[item_index].i_len % XFS_BLI_CHUNK) == 0);
    -		ASSERT((reg_buf_offset + reg_buf_bytes) <= XFS_BUF_COUNT(bp));
    -
    -		/*
    -		 * The current logged region contains a copy of the
    -		 * current di_next_unlinked field.  Extract its value
    -		 * and copy it to the buffer copy.
    -		 */
    -		logged_nextp = (xfs_agino_t *)
    -			       ((char *)(item->ri_buf[item_index].i_addr) +
    -				(next_unlinked_offset - reg_buf_offset));
    -		if (unlikely(*logged_nextp == 0)) {
    -			xfs_fs_cmn_err(CE_ALERT, mp,
    -				"bad inode buffer log record (ptr = 0x%p, bp = 0x%p).  XFS trying to replay bad (0) inode di_next_unlinked field",
    -				item, bp);
    -			XFS_ERROR_REPORT("xlog_recover_do_inode_buf",
    -					 XFS_ERRLEVEL_LOW, mp);
    -			return XFS_ERROR(EFSCORRUPTED);
    -		}
    -
    -		buffer_nextp = (xfs_agino_t *)xfs_buf_offset(bp,
    -					      next_unlinked_offset);
    -		INT_SET(*buffer_nextp, ARCH_CONVERT, *logged_nextp);
    -	}
    -
    -	return 0;
    -}
    -
    -/*
    - * Perform a 'normal' buffer recovery.  Each logged region of the
    - * buffer should be copied over the corresponding region in the
    - * given buffer.  The bitmap in the buf log format structure indicates
    - * where to place the logged data.
    - */
    -/*ARGSUSED*/
    -STATIC void
    -xlog_recover_do_reg_buffer(
    -	xfs_mount_t		*mp,
    -	xlog_recover_item_t	*item,
    -	xfs_buf_t		*bp,
    -	xfs_buf_log_format_t	*buf_f)
    -{
    -	int			i;
    -	int			bit;
    -	int			nbits;
    -	xfs_buf_log_format_v1_t	*obuf_f;
    -	unsigned int		*data_map = NULL;
    -	unsigned int		map_size = 0;
    -	int                     error;
    -
    -	switch (buf_f->blf_type) {
    -	case XFS_LI_BUF:
    -		data_map = buf_f->blf_data_map;
    -		map_size = buf_f->blf_map_size;
    -		break;
    -	case XFS_LI_6_1_BUF:
    -	case XFS_LI_5_3_BUF:
    -		obuf_f = (xfs_buf_log_format_v1_t*)buf_f;
    -		data_map = obuf_f->blf_data_map;
    -		map_size = obuf_f->blf_map_size;
    -		break;
    -	}
    -	bit = 0;
    -	i = 1;  /* 0 is the buf format structure */
    -	while (1) {
    -		bit = xfs_next_bit(data_map, map_size, bit);
    -		if (bit == -1)
    -			break;
    -		nbits = xfs_contig_bits(data_map, map_size, bit);
    -		ASSERT(nbits > 0);
    -		ASSERT(item->ri_buf[i].i_addr != 0);
    -		ASSERT(item->ri_buf[i].i_len % XFS_BLI_CHUNK == 0);
    -		ASSERT(XFS_BUF_COUNT(bp) >=
    -		       ((uint)bit << XFS_BLI_SHIFT)+(nbits<blf_flags &
    -		   (XFS_BLI_UDQUOT_BUF|XFS_BLI_PDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) {
    -			error = xfs_qm_dqcheck((xfs_disk_dquot_t *)
    -					       item->ri_buf[i].i_addr,
    -					       -1, 0, XFS_QMOPT_DOWARN,
    -					       "dquot_buf_recover");
    -		}
    -		if (!error)
    -			memcpy(xfs_buf_offset(bp,
    -				(uint)bit << XFS_BLI_SHIFT),	/* dest */
    -				item->ri_buf[i].i_addr,		/* source */
    -				nbits<ri_total);
    -}
    -
    -/*
    - * Do some primitive error checking on ondisk dquot data structures.
    - */
    -int
    -xfs_qm_dqcheck(
    -	xfs_disk_dquot_t *ddq,
    -	xfs_dqid_t	 id,
    -	uint		 type,	  /* used only when IO_dorepair is true */
    -	uint		 flags,
    -	char		 *str)
    -{
    -	xfs_dqblk_t	 *d = (xfs_dqblk_t *)ddq;
    -	int		errs = 0;
    -
    -	/*
    -	 * We can encounter an uninitialized dquot buffer for 2 reasons:
    -	 * 1. If we crash while deleting the quotainode(s), and those blks got
    -	 *    used for user data. This is because we take the path of regular
    -	 *    file deletion; however, the size field of quotainodes is never
    -	 *    updated, so all the tricks that we play in itruncate_finish
    -	 *    don't quite matter.
    -	 *
    -	 * 2. We don't play the quota buffers when there's a quotaoff logitem.
    -	 *    But the allocation will be replayed so we'll end up with an
    -	 *    uninitialized quota block.
    -	 *
    -	 * This is all fine; things are still consistent, and we haven't lost
    -	 * any quota information. Just don't complain about bad dquot blks.
    -	 */
    -	if (be16_to_cpu(ddq->d_magic) != XFS_DQUOT_MAGIC) {
    -		if (flags & XFS_QMOPT_DOWARN)
    -			cmn_err(CE_ALERT,
    -			"%s : XFS dquot ID 0x%x, magic 0x%x != 0x%x",
    -			str, id, be16_to_cpu(ddq->d_magic), XFS_DQUOT_MAGIC);
    -		errs++;
    -	}
    -	if (ddq->d_version != XFS_DQUOT_VERSION) {
    -		if (flags & XFS_QMOPT_DOWARN)
    -			cmn_err(CE_ALERT,
    -			"%s : XFS dquot ID 0x%x, version 0x%x != 0x%x",
    -			str, id, ddq->d_version, XFS_DQUOT_VERSION);
    -		errs++;
    -	}
    -
    -	if (ddq->d_flags != XFS_DQ_USER &&
    -	    ddq->d_flags != XFS_DQ_PROJ &&
    -	    ddq->d_flags != XFS_DQ_GROUP) {
    -		if (flags & XFS_QMOPT_DOWARN)
    -			cmn_err(CE_ALERT,
    -			"%s : XFS dquot ID 0x%x, unknown flags 0x%x",
    -			str, id, ddq->d_flags);
    -		errs++;
    -	}
    -
    -	if (id != -1 && id != be32_to_cpu(ddq->d_id)) {
    -		if (flags & XFS_QMOPT_DOWARN)
    -			cmn_err(CE_ALERT,
    -			"%s : ondisk-dquot 0x%p, ID mismatch: "
    -			"0x%x expected, found id 0x%x",
    -			str, ddq, id, be32_to_cpu(ddq->d_id));
    -		errs++;
    -	}
    -
    -	if (!errs && ddq->d_id) {
    -		if (ddq->d_blk_softlimit &&
    -		    be64_to_cpu(ddq->d_bcount) >=
    -				be64_to_cpu(ddq->d_blk_softlimit)) {
    -			if (!ddq->d_btimer) {
    -				if (flags & XFS_QMOPT_DOWARN)
    -					cmn_err(CE_ALERT,
    -					"%s : Dquot ID 0x%x (0x%p) "
    -					"BLK TIMER NOT STARTED",
    -					str, (int)be32_to_cpu(ddq->d_id), ddq);
    -				errs++;
    -			}
    -		}
    -		if (ddq->d_ino_softlimit &&
    -		    be64_to_cpu(ddq->d_icount) >=
    -				be64_to_cpu(ddq->d_ino_softlimit)) {
    -			if (!ddq->d_itimer) {
    -				if (flags & XFS_QMOPT_DOWARN)
    -					cmn_err(CE_ALERT,
    -					"%s : Dquot ID 0x%x (0x%p) "
    -					"INODE TIMER NOT STARTED",
    -					str, (int)be32_to_cpu(ddq->d_id), ddq);
    -				errs++;
    -			}
    -		}
    -		if (ddq->d_rtb_softlimit &&
    -		    be64_to_cpu(ddq->d_rtbcount) >=
    -				be64_to_cpu(ddq->d_rtb_softlimit)) {
    -			if (!ddq->d_rtbtimer) {
    -				if (flags & XFS_QMOPT_DOWARN)
    -					cmn_err(CE_ALERT,
    -					"%s : Dquot ID 0x%x (0x%p) "
    -					"RTBLK TIMER NOT STARTED",
    -					str, (int)be32_to_cpu(ddq->d_id), ddq);
    -				errs++;
    -			}
    -		}
    -	}
    -
    -	if (!errs || !(flags & XFS_QMOPT_DQREPAIR))
    -		return errs;
    -
    -	if (flags & XFS_QMOPT_DOWARN)
    -		cmn_err(CE_NOTE, "Re-initializing dquot ID 0x%x", id);
    -
    -	/*
    -	 * Typically, a repair is only requested by quotacheck.
    -	 */
    -	ASSERT(id != -1);
    -	ASSERT(flags & XFS_QMOPT_DQREPAIR);
    -	memset(d, 0, sizeof(xfs_dqblk_t));
    -
    -	d->dd_diskdq.d_magic = cpu_to_be16(XFS_DQUOT_MAGIC);
    -	d->dd_diskdq.d_version = XFS_DQUOT_VERSION;
    -	d->dd_diskdq.d_flags = type;
    -	d->dd_diskdq.d_id = cpu_to_be32(id);
    -
    -	return errs;
    -}
    -
    -/*
    - * Perform a dquot buffer recovery.
    - * Simple algorithm: if we have found a QUOTAOFF logitem of the same type
    - * (ie. USR or GRP), then just toss this buffer away; don't recover it.
    - * Else, treat it as a regular buffer and do recovery.
    - */
    -STATIC void
    -xlog_recover_do_dquot_buffer(
    -	xfs_mount_t		*mp,
    -	xlog_t			*log,
    -	xlog_recover_item_t	*item,
    -	xfs_buf_t		*bp,
    -	xfs_buf_log_format_t	*buf_f)
    -{
    -	uint			type;
    -
    -	/*
    -	 * Filesystems are required to send in quota flags at mount time.
    -	 */
    -	if (mp->m_qflags == 0) {
    -		return;
    -	}
    -
    -	type = 0;
    -	if (buf_f->blf_flags & XFS_BLI_UDQUOT_BUF)
    -		type |= XFS_DQ_USER;
    -	if (buf_f->blf_flags & XFS_BLI_PDQUOT_BUF)
    -		type |= XFS_DQ_PROJ;
    -	if (buf_f->blf_flags & XFS_BLI_GDQUOT_BUF)
    -		type |= XFS_DQ_GROUP;
    -	/*
    -	 * This type of quotas was turned off, so ignore this buffer
    -	 */
    -	if (log->l_quotaoffs_flag & type)
    -		return;
    -
    -	xlog_recover_do_reg_buffer(mp, item, bp, buf_f);
    -}
    -
    -/*
    - * This routine replays a modification made to a buffer at runtime.
    - * There are actually two types of buffer, regular and inode, which
    - * are handled differently.  Inode buffers are handled differently
    - * in that we only recover a specific set of data from them, namely
    - * the inode di_next_unlinked fields.  This is because all other inode
    - * data is actually logged via inode records and any data we replay
    - * here which overlaps that may be stale.
    - *
    - * When meta-data buffers are freed at run time we log a buffer item
    - * with the XFS_BLI_CANCEL bit set to indicate that previous copies
    - * of the buffer in the log should not be replayed at recovery time.
    - * This is so that if the blocks covered by the buffer are reused for
    - * file data before we crash we don't end up replaying old, freed
    - * meta-data into a user's file.
    - *
    - * To handle the cancellation of buffer log items, we make two passes
    - * over the log during recovery.  During the first we build a table of
    - * those buffers which have been cancelled, and during the second we
    - * only replay those buffers which do not have corresponding cancel
    - * records in the table.  See xlog_recover_do_buffer_pass[1,2] above
    - * for more details on the implementation of the table of cancel records.
    - */
    -STATIC int
    -xlog_recover_do_buffer_trans(
    -	xlog_t			*log,
    -	xlog_recover_item_t	*item,
    -	int			pass)
    -{
    -	xfs_buf_log_format_t	*buf_f;
    -	xfs_buf_log_format_v1_t	*obuf_f;
    -	xfs_mount_t		*mp;
    -	xfs_buf_t		*bp;
    -	int			error;
    -	int			cancel;
    -	xfs_daddr_t		blkno;
    -	int			len;
    -	ushort			flags;
    -
    -	buf_f = (xfs_buf_log_format_t *)item->ri_buf[0].i_addr;
    -
    -	if (pass == XLOG_RECOVER_PASS1) {
    -		/*
    -		 * In this pass we're only looking for buf items
    -		 * with the XFS_BLI_CANCEL bit set.
    -		 */
    -		xlog_recover_do_buffer_pass1(log, buf_f);
    -		return 0;
    -	} else {
    -		/*
    -		 * In this pass we want to recover all the buffers
    -		 * which have not been cancelled and are not
    -		 * cancellation buffers themselves.  The routine
    -		 * we call here will tell us whether or not to
    -		 * continue with the replay of this buffer.
    -		 */
    -		cancel = xlog_recover_do_buffer_pass2(log, buf_f);
    -		if (cancel) {
    -			return 0;
    -		}
    -	}
    -	switch (buf_f->blf_type) {
    -	case XFS_LI_BUF:
    -		blkno = buf_f->blf_blkno;
    -		len = buf_f->blf_len;
    -		flags = buf_f->blf_flags;
    -		break;
    -	case XFS_LI_6_1_BUF:
    -	case XFS_LI_5_3_BUF:
    -		obuf_f = (xfs_buf_log_format_v1_t*)buf_f;
    -		blkno = obuf_f->blf_blkno;
    -		len = obuf_f->blf_len;
    -		flags = obuf_f->blf_flags;
    -		break;
    -	default:
    -		xfs_fs_cmn_err(CE_ALERT, log->l_mp,
    -			"xfs_log_recover: unknown buffer type 0x%x, logdev %s",
    -			buf_f->blf_type, log->l_mp->m_logname ?
    -			log->l_mp->m_logname : "internal");
    -		XFS_ERROR_REPORT("xlog_recover_do_buffer_trans",
    -				 XFS_ERRLEVEL_LOW, log->l_mp);
    -		return XFS_ERROR(EFSCORRUPTED);
    -	}
    -
    -	mp = log->l_mp;
    -	if (flags & XFS_BLI_INODE_BUF) {
    -		bp = xfs_buf_read_flags(mp->m_ddev_targp, blkno, len,
    -								XFS_BUF_LOCK);
    -	} else {
    -		bp = xfs_buf_read(mp->m_ddev_targp, blkno, len, 0);
    -	}
    -	if (XFS_BUF_ISERROR(bp)) {
    -		xfs_ioerror_alert("xlog_recover_do..(read#1)", log->l_mp,
    -				  bp, blkno);
    -		error = XFS_BUF_GETERROR(bp);
    -		xfs_buf_relse(bp);
    -		return error;
    -	}
    -
    -	error = 0;
    -	if (flags & XFS_BLI_INODE_BUF) {
    -		error = xlog_recover_do_inode_buffer(mp, item, bp, buf_f);
    -	} else if (flags &
    -		  (XFS_BLI_UDQUOT_BUF|XFS_BLI_PDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) {
    -		xlog_recover_do_dquot_buffer(mp, log, item, bp, buf_f);
    -	} else {
    -		xlog_recover_do_reg_buffer(mp, item, bp, buf_f);
    -	}
    -	if (error)
    -		return XFS_ERROR(error);
    -
    -	/*
    -	 * Perform delayed write on the buffer.  Asynchronous writes will be
    -	 * slower when taking into account all the buffers to be flushed.
    -	 *
    -	 * Also make sure that only inode buffers with good sizes stay in
    -	 * the buffer cache.  The kernel moves inodes in buffers of 1 block
    -	 * or XFS_INODE_CLUSTER_SIZE bytes, whichever is bigger.  The inode
    -	 * buffers in the log can be a different size if the log was generated
    -	 * by an older kernel using unclustered inode buffers or a newer kernel
    -	 * running with a different inode cluster size.  Regardless, if the
    -	 * the inode buffer size isn't MAX(blocksize, XFS_INODE_CLUSTER_SIZE)
    -	 * for *our* value of XFS_INODE_CLUSTER_SIZE, then we need to keep
    -	 * the buffer out of the buffer cache so that the buffer won't
    -	 * overlap with future reads of those inodes.
    -	 */
    -	if (XFS_DINODE_MAGIC ==
    -	    INT_GET(*((__uint16_t *)(xfs_buf_offset(bp, 0))), ARCH_CONVERT) &&
    -	    (XFS_BUF_COUNT(bp) != MAX(log->l_mp->m_sb.sb_blocksize,
    -			(__uint32_t)XFS_INODE_CLUSTER_SIZE(log->l_mp)))) {
    -		XFS_BUF_STALE(bp);
    -		error = xfs_bwrite(mp, bp);
    -	} else {
    -		ASSERT(XFS_BUF_FSPRIVATE(bp, void *) == NULL ||
    -		       XFS_BUF_FSPRIVATE(bp, xfs_mount_t *) == mp);
    -		XFS_BUF_SET_FSPRIVATE(bp, mp);
    -		XFS_BUF_SET_IODONE_FUNC(bp, xlog_recover_iodone);
    -		xfs_bdwrite(mp, bp);
    -	}
    -
    -	return (error);
    -}
    -
    -STATIC int
    -xlog_recover_do_inode_trans(
    -	xlog_t			*log,
    -	xlog_recover_item_t	*item,
    -	int			pass)
    -{
    -	xfs_inode_log_format_t	*in_f;
    -	xfs_mount_t		*mp;
    -	xfs_buf_t		*bp;
    -	xfs_imap_t		imap;
    -	xfs_dinode_t		*dip;
    -	xfs_ino_t		ino;
    -	int			len;
    -	xfs_caddr_t		src;
    -	xfs_caddr_t		dest;
    -	int			error;
    -	int			attr_index;
    -	uint			fields;
    -	xfs_dinode_core_t	*dicp;
    -
    -	if (pass == XLOG_RECOVER_PASS1) {
    -		return 0;
    -	}
    -
    -	in_f = (xfs_inode_log_format_t *)item->ri_buf[0].i_addr;
    -	ino = in_f->ilf_ino;
    -	mp = log->l_mp;
    -	if (ITEM_TYPE(item) == XFS_LI_INODE) {
    -		imap.im_blkno = (xfs_daddr_t)in_f->ilf_blkno;
    -		imap.im_len = in_f->ilf_len;
    -		imap.im_boffset = in_f->ilf_boffset;
    -	} else {
    -		/*
    -		 * It's an old inode format record.  We don't know where
    -		 * its cluster is located on disk, and we can't allow
    -		 * xfs_imap() to figure it out because the inode btrees
    -		 * are not ready to be used.  Therefore do not pass the
    -		 * XFS_IMAP_LOOKUP flag to xfs_imap().  This will give
    -		 * us only the single block in which the inode lives
    -		 * rather than its cluster, so we must make sure to
    -		 * invalidate the buffer when we write it out below.
    -		 */
    -		imap.im_blkno = 0;
    -		xfs_imap(log->l_mp, NULL, ino, &imap, 0);
    -	}
    -
    -	/*
    -	 * Inode buffers can be freed, look out for it,
    -	 * and do not replay the inode.
    -	 */
    -	if (xlog_check_buffer_cancelled(log, imap.im_blkno, imap.im_len, 0))
    -		return 0;
    -
    -	bp = xfs_buf_read_flags(mp->m_ddev_targp, imap.im_blkno, imap.im_len,
    -								XFS_BUF_LOCK);
    -	if (XFS_BUF_ISERROR(bp)) {
    -		xfs_ioerror_alert("xlog_recover_do..(read#2)", mp,
    -				  bp, imap.im_blkno);
    -		error = XFS_BUF_GETERROR(bp);
    -		xfs_buf_relse(bp);
    -		return error;
    -	}
    -	error = 0;
    -	ASSERT(in_f->ilf_fields & XFS_ILOG_CORE);
    -	dip = (xfs_dinode_t *)xfs_buf_offset(bp, imap.im_boffset);
    -
    -	/*
    -	 * Make sure the place we're flushing out to really looks
    -	 * like an inode!
    -	 */
    -	if (unlikely(INT_GET(dip->di_core.di_magic, ARCH_CONVERT) != XFS_DINODE_MAGIC)) {
    -		xfs_buf_relse(bp);
    -		xfs_fs_cmn_err(CE_ALERT, mp,
    -			"xfs_inode_recover: Bad inode magic number, dino ptr = 0x%p, dino bp = 0x%p, ino = %Ld",
    -			dip, bp, ino);
    -		XFS_ERROR_REPORT("xlog_recover_do_inode_trans(1)",
    -				 XFS_ERRLEVEL_LOW, mp);
    -		return XFS_ERROR(EFSCORRUPTED);
    -	}
    -	dicp = (xfs_dinode_core_t*)(item->ri_buf[1].i_addr);
    -	if (unlikely(dicp->di_magic != XFS_DINODE_MAGIC)) {
    -		xfs_buf_relse(bp);
    -		xfs_fs_cmn_err(CE_ALERT, mp,
    -			"xfs_inode_recover: Bad inode log record, rec ptr 0x%p, ino %Ld",
    -			item, ino);
    -		XFS_ERROR_REPORT("xlog_recover_do_inode_trans(2)",
    -				 XFS_ERRLEVEL_LOW, mp);
    -		return XFS_ERROR(EFSCORRUPTED);
    -	}
    -
    -	/* Skip replay when the on disk inode is newer than the log one */
    -	if (dicp->di_flushiter <
    -	    INT_GET(dip->di_core.di_flushiter, ARCH_CONVERT)) {
    -		/*
    -		 * Deal with the wrap case, DI_MAX_FLUSH is less
    -		 * than smaller numbers
    -		 */
    -		if ((INT_GET(dip->di_core.di_flushiter, ARCH_CONVERT)
    -							== DI_MAX_FLUSH) &&
    -		    (dicp->di_flushiter < (DI_MAX_FLUSH>>1))) {
    -			/* do nothing */
    -		} else {
    -			xfs_buf_relse(bp);
    -			return 0;
    -		}
    -	}
    -	/* Take the opportunity to reset the flush iteration count */
    -	dicp->di_flushiter = 0;
    -
    -	if (unlikely((dicp->di_mode & S_IFMT) == S_IFREG)) {
    -		if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) &&
    -		    (dicp->di_format != XFS_DINODE_FMT_BTREE)) {
    -			XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(3)",
    -					 XFS_ERRLEVEL_LOW, mp, dicp);
    -			xfs_buf_relse(bp);
    -			xfs_fs_cmn_err(CE_ALERT, mp,
    -				"xfs_inode_recover: Bad regular inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld",
    -				item, dip, bp, ino);
    -			return XFS_ERROR(EFSCORRUPTED);
    -		}
    -	} else if (unlikely((dicp->di_mode & S_IFMT) == S_IFDIR)) {
    -		if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) &&
    -		    (dicp->di_format != XFS_DINODE_FMT_BTREE) &&
    -		    (dicp->di_format != XFS_DINODE_FMT_LOCAL)) {
    -			XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(4)",
    -					     XFS_ERRLEVEL_LOW, mp, dicp);
    -			xfs_buf_relse(bp);
    -			xfs_fs_cmn_err(CE_ALERT, mp,
    -				"xfs_inode_recover: Bad dir inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld",
    -				item, dip, bp, ino);
    -			return XFS_ERROR(EFSCORRUPTED);
    -		}
    -	}
    -	if (unlikely(dicp->di_nextents + dicp->di_anextents > dicp->di_nblocks)){
    -		XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(5)",
    -				     XFS_ERRLEVEL_LOW, mp, dicp);
    -		xfs_buf_relse(bp);
    -		xfs_fs_cmn_err(CE_ALERT, mp,
    -			"xfs_inode_recover: Bad inode log record, rec ptr 0x%p, dino ptr 0x%p, dino bp 0x%p, ino %Ld, total extents = %d, nblocks = %Ld",
    -			item, dip, bp, ino,
    -			dicp->di_nextents + dicp->di_anextents,
    -			dicp->di_nblocks);
    -		return XFS_ERROR(EFSCORRUPTED);
    -	}
    -	if (unlikely(dicp->di_forkoff > mp->m_sb.sb_inodesize)) {
    -		XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(6)",
    -				     XFS_ERRLEVEL_LOW, mp, dicp);
    -		xfs_buf_relse(bp);
    -		xfs_fs_cmn_err(CE_ALERT, mp,
    -			"xfs_inode_recover: Bad inode log rec ptr 0x%p, dino ptr 0x%p, dino bp 0x%p, ino %Ld, forkoff 0x%x",
    -			item, dip, bp, ino, dicp->di_forkoff);
    -		return XFS_ERROR(EFSCORRUPTED);
    -	}
    -	if (unlikely(item->ri_buf[1].i_len > sizeof(xfs_dinode_core_t))) {
    -		XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(7)",
    -				     XFS_ERRLEVEL_LOW, mp, dicp);
    -		xfs_buf_relse(bp);
    -		xfs_fs_cmn_err(CE_ALERT, mp,
    -			"xfs_inode_recover: Bad inode log record length %d, rec ptr 0x%p",
    -			item->ri_buf[1].i_len, item);
    -		return XFS_ERROR(EFSCORRUPTED);
    -	}
    -
    -	/* The core is in in-core format */
    -	xfs_xlate_dinode_core((xfs_caddr_t)&dip->di_core,
    -			      (xfs_dinode_core_t*)item->ri_buf[1].i_addr, -1);
    -
    -	/* the rest is in on-disk format */
    -	if (item->ri_buf[1].i_len > sizeof(xfs_dinode_core_t)) {
    -		memcpy((xfs_caddr_t) dip + sizeof(xfs_dinode_core_t),
    -			item->ri_buf[1].i_addr + sizeof(xfs_dinode_core_t),
    -			item->ri_buf[1].i_len  - sizeof(xfs_dinode_core_t));
    -	}
    -
    -	fields = in_f->ilf_fields;
    -	switch (fields & (XFS_ILOG_DEV | XFS_ILOG_UUID)) {
    -	case XFS_ILOG_DEV:
    -		INT_SET(dip->di_u.di_dev, ARCH_CONVERT, in_f->ilf_u.ilfu_rdev);
    -
    -		break;
    -	case XFS_ILOG_UUID:
    -		dip->di_u.di_muuid = in_f->ilf_u.ilfu_uuid;
    -		break;
    -	}
    -
    -	if (in_f->ilf_size == 2)
    -		goto write_inode_buffer;
    -	len = item->ri_buf[2].i_len;
    -	src = item->ri_buf[2].i_addr;
    -	ASSERT(in_f->ilf_size <= 4);
    -	ASSERT((in_f->ilf_size == 3) || (fields & XFS_ILOG_AFORK));
    -	ASSERT(!(fields & XFS_ILOG_DFORK) ||
    -	       (len == in_f->ilf_dsize));
    -
    -	switch (fields & XFS_ILOG_DFORK) {
    -	case XFS_ILOG_DDATA:
    -	case XFS_ILOG_DEXT:
    -		memcpy(&dip->di_u, src, len);
    -		break;
    -
    -	case XFS_ILOG_DBROOT:
    -		xfs_bmbt_to_bmdr((xfs_bmbt_block_t *)src, len,
    -				 &(dip->di_u.di_bmbt),
    -				 XFS_DFORK_DSIZE(dip, mp));
    -		break;
    -
    -	default:
    -		/*
    -		 * There are no data fork flags set.
    -		 */
    -		ASSERT((fields & XFS_ILOG_DFORK) == 0);
    -		break;
    -	}
    -
    -	/*
    -	 * If we logged any attribute data, recover it.  There may or
    -	 * may not have been any other non-core data logged in this
    -	 * transaction.
    -	 */
    -	if (in_f->ilf_fields & XFS_ILOG_AFORK) {
    -		if (in_f->ilf_fields & XFS_ILOG_DFORK) {
    -			attr_index = 3;
    -		} else {
    -			attr_index = 2;
    -		}
    -		len = item->ri_buf[attr_index].i_len;
    -		src = item->ri_buf[attr_index].i_addr;
    -		ASSERT(len == in_f->ilf_asize);
    -
    -		switch (in_f->ilf_fields & XFS_ILOG_AFORK) {
    -		case XFS_ILOG_ADATA:
    -		case XFS_ILOG_AEXT:
    -			dest = XFS_DFORK_APTR(dip);
    -			ASSERT(len <= XFS_DFORK_ASIZE(dip, mp));
    -			memcpy(dest, src, len);
    -			break;
    -
    -		case XFS_ILOG_ABROOT:
    -			dest = XFS_DFORK_APTR(dip);
    -			xfs_bmbt_to_bmdr((xfs_bmbt_block_t *)src, len,
    -					 (xfs_bmdr_block_t*)dest,
    -					 XFS_DFORK_ASIZE(dip, mp));
    -			break;
    -
    -		default:
    -			xlog_warn("XFS: xlog_recover_do_inode_trans: Invalid flag");
    -			ASSERT(0);
    -			xfs_buf_relse(bp);
    -			return XFS_ERROR(EIO);
    -		}
    -	}
    -
    -write_inode_buffer:
    -	if (ITEM_TYPE(item) == XFS_LI_INODE) {
    -		ASSERT(XFS_BUF_FSPRIVATE(bp, void *) == NULL ||
    -		       XFS_BUF_FSPRIVATE(bp, xfs_mount_t *) == mp);
    -		XFS_BUF_SET_FSPRIVATE(bp, mp);
    -		XFS_BUF_SET_IODONE_FUNC(bp, xlog_recover_iodone);
    -		xfs_bdwrite(mp, bp);
    -	} else {
    -		XFS_BUF_STALE(bp);
    -		error = xfs_bwrite(mp, bp);
    -	}
    -
    -	return (error);
    -}
    -
    -/*
    - * Recover QUOTAOFF records. We simply make a note of it in the xlog_t
    - * structure, so that we know not to do any dquot item or dquot buffer recovery,
    - * of that type.
    - */
    -STATIC int
    -xlog_recover_do_quotaoff_trans(
    -	xlog_t			*log,
    -	xlog_recover_item_t	*item,
    -	int			pass)
    -{
    -	xfs_qoff_logformat_t	*qoff_f;
    -
    -	if (pass == XLOG_RECOVER_PASS2) {
    -		return (0);
    -	}
    -
    -	qoff_f = (xfs_qoff_logformat_t *)item->ri_buf[0].i_addr;
    -	ASSERT(qoff_f);
    -
    -	/*
    -	 * The logitem format's flag tells us if this was user quotaoff,
    -	 * group/project quotaoff or both.
    -	 */
    -	if (qoff_f->qf_flags & XFS_UQUOTA_ACCT)
    -		log->l_quotaoffs_flag |= XFS_DQ_USER;
    -	if (qoff_f->qf_flags & XFS_PQUOTA_ACCT)
    -		log->l_quotaoffs_flag |= XFS_DQ_PROJ;
    -	if (qoff_f->qf_flags & XFS_GQUOTA_ACCT)
    -		log->l_quotaoffs_flag |= XFS_DQ_GROUP;
    -
    -	return (0);
    -}
    -
    -/*
    - * Recover a dquot record
    - */
    -STATIC int
    -xlog_recover_do_dquot_trans(
    -	xlog_t			*log,
    -	xlog_recover_item_t	*item,
    -	int			pass)
    -{
    -	xfs_mount_t		*mp;
    -	xfs_buf_t		*bp;
    -	struct xfs_disk_dquot	*ddq, *recddq;
    -	int			error;
    -	xfs_dq_logformat_t	*dq_f;
    -	uint			type;
    -
    -	if (pass == XLOG_RECOVER_PASS1) {
    -		return 0;
    -	}
    -	mp = log->l_mp;
    -
    -	/*
    -	 * Filesystems are required to send in quota flags at mount time.
    -	 */
    -	if (mp->m_qflags == 0)
    -		return (0);
    -
    -	recddq = (xfs_disk_dquot_t *)item->ri_buf[1].i_addr;
    -	ASSERT(recddq);
    -	/*
    -	 * This type of quotas was turned off, so ignore this record.
    -	 */
    -	type = INT_GET(recddq->d_flags, ARCH_CONVERT) &
    -			(XFS_DQ_USER | XFS_DQ_PROJ | XFS_DQ_GROUP);
    -	ASSERT(type);
    -	if (log->l_quotaoffs_flag & type)
    -		return (0);
    -
    -	/*
    -	 * At this point we know that quota was _not_ turned off.
    -	 * Since the mount flags are not indicating to us otherwise, this
    -	 * must mean that quota is on, and the dquot needs to be replayed.
    -	 * Remember that we may not have fully recovered the superblock yet,
    -	 * so we can't do the usual trick of looking at the SB quota bits.
    -	 *
    -	 * The other possibility, of course, is that the quota subsystem was
    -	 * removed since the last mount - ENOSYS.
    -	 */
    -	dq_f = (xfs_dq_logformat_t *)item->ri_buf[0].i_addr;
    -	ASSERT(dq_f);
    -	if ((error = xfs_qm_dqcheck(recddq,
    -			   dq_f->qlf_id,
    -			   0, XFS_QMOPT_DOWARN,
    -			   "xlog_recover_do_dquot_trans (log copy)"))) {
    -		return XFS_ERROR(EIO);
    -	}
    -	ASSERT(dq_f->qlf_len == 1);
    -
    -	error = xfs_read_buf(mp, mp->m_ddev_targp,
    -			     dq_f->qlf_blkno,
    -			     XFS_FSB_TO_BB(mp, dq_f->qlf_len),
    -			     0, &bp);
    -	if (error) {
    -		xfs_ioerror_alert("xlog_recover_do..(read#3)", mp,
    -				  bp, dq_f->qlf_blkno);
    -		return error;
    -	}
    -	ASSERT(bp);
    -	ddq = (xfs_disk_dquot_t *)xfs_buf_offset(bp, dq_f->qlf_boffset);
    -
    -	/*
    -	 * At least the magic num portion should be on disk because this
    -	 * was among a chunk of dquots created earlier, and we did some
    -	 * minimal initialization then.
    -	 */
    -	if (xfs_qm_dqcheck(ddq, dq_f->qlf_id, 0, XFS_QMOPT_DOWARN,
    -			   "xlog_recover_do_dquot_trans")) {
    -		xfs_buf_relse(bp);
    -		return XFS_ERROR(EIO);
    -	}
    -
    -	memcpy(ddq, recddq, item->ri_buf[1].i_len);
    -
    -	ASSERT(dq_f->qlf_size == 2);
    -	ASSERT(XFS_BUF_FSPRIVATE(bp, void *) == NULL ||
    -	       XFS_BUF_FSPRIVATE(bp, xfs_mount_t *) == mp);
    -	XFS_BUF_SET_FSPRIVATE(bp, mp);
    -	XFS_BUF_SET_IODONE_FUNC(bp, xlog_recover_iodone);
    -	xfs_bdwrite(mp, bp);
    -
    -	return (0);
    -}
    -
    -/*
    - * This routine is called to create an in-core extent free intent
    - * item from the efi format structure which was logged on disk.
    - * It allocates an in-core efi, copies the extents from the format
    - * structure into it, and adds the efi to the AIL with the given
    - * LSN.
    - */
    -STATIC void
    -xlog_recover_do_efi_trans(
    -	xlog_t			*log,
    -	xlog_recover_item_t	*item,
    -	xfs_lsn_t		lsn,
    -	int			pass)
    -{
    -	xfs_mount_t		*mp;
    -	xfs_efi_log_item_t	*efip;
    -	xfs_efi_log_format_t	*efi_formatp;
    -	SPLDECL(s);
    -
    -	if (pass == XLOG_RECOVER_PASS1) {
    -		return;
    -	}
    -
    -	efi_formatp = (xfs_efi_log_format_t *)item->ri_buf[0].i_addr;
    -	ASSERT(item->ri_buf[0].i_len ==
    -	       (sizeof(xfs_efi_log_format_t) +
    -		((efi_formatp->efi_nextents - 1) * sizeof(xfs_extent_t))));
    -
    -	mp = log->l_mp;
    -	efip = xfs_efi_init(mp, efi_formatp->efi_nextents);
    -	memcpy((char *)&(efip->efi_format), (char *)efi_formatp,
    -	      sizeof(xfs_efi_log_format_t) +
    -	      ((efi_formatp->efi_nextents - 1) * sizeof(xfs_extent_t)));
    -	efip->efi_next_extent = efi_formatp->efi_nextents;
    -	efip->efi_flags |= XFS_EFI_COMMITTED;
    -
    -	AIL_LOCK(mp,s);
    -	/*
    -	 * xfs_trans_update_ail() drops the AIL lock.
    -	 */
    -	xfs_trans_update_ail(mp, (xfs_log_item_t *)efip, lsn, s);
    -}
    -
    -
    -/*
    - * This routine is called when an efd format structure is found in
    - * a committed transaction in the log.  It's purpose is to cancel
    - * the corresponding efi if it was still in the log.  To do this
    - * it searches the AIL for the efi with an id equal to that in the
    - * efd format structure.  If we find it, we remove the efi from the
    - * AIL and free it.
    - */
    -STATIC void
    -xlog_recover_do_efd_trans(
    -	xlog_t			*log,
    -	xlog_recover_item_t	*item,
    -	int			pass)
    -{
    -	xfs_mount_t		*mp;
    -	xfs_efd_log_format_t	*efd_formatp;
    -	xfs_efi_log_item_t	*efip = NULL;
    -	xfs_log_item_t		*lip;
    -	int			gen;
    -	__uint64_t		efi_id;
    -	SPLDECL(s);
    -
    -	if (pass == XLOG_RECOVER_PASS1) {
    -		return;
    -	}
    -
    -	efd_formatp = (xfs_efd_log_format_t *)item->ri_buf[0].i_addr;
    -	ASSERT(item->ri_buf[0].i_len ==
    -	       (sizeof(xfs_efd_log_format_t) +
    -		((efd_formatp->efd_nextents - 1) * sizeof(xfs_extent_t))));
    -	efi_id = efd_formatp->efd_efi_id;
    -
    -	/*
    -	 * Search for the efi with the id in the efd format structure
    -	 * in the AIL.
    -	 */
    -	mp = log->l_mp;
    -	AIL_LOCK(mp,s);
    -	lip = xfs_trans_first_ail(mp, &gen);
    -	while (lip != NULL) {
    -		if (lip->li_type == XFS_LI_EFI) {
    -			efip = (xfs_efi_log_item_t *)lip;
    -			if (efip->efi_format.efi_id == efi_id) {
    -				/*
    -				 * xfs_trans_delete_ail() drops the
    -				 * AIL lock.
    -				 */
    -				xfs_trans_delete_ail(mp, lip, s);
    -				break;
    -			}
    -		}
    -		lip = xfs_trans_next_ail(mp, lip, &gen, NULL);
    -	}
    -
    -	/*
    -	 * If we found it, then free it up.  If it wasn't there, it
    -	 * must have been overwritten in the log.  Oh well.
    -	 */
    -	if (lip != NULL) {
    -		xfs_efi_item_free(efip);
    -	} else {
    -		AIL_UNLOCK(mp, s);
    -	}
    -}
    -
    -/*
    - * Perform the transaction
    - *
    - * If the transaction modifies a buffer or inode, do it now.  Otherwise,
    - * EFIs and EFDs get queued up by adding entries into the AIL for them.
    - */
    -STATIC int
    -xlog_recover_do_trans(
    -	xlog_t			*log,
    -	xlog_recover_t		*trans,
    -	int			pass)
    -{
    -	int			error = 0;
    -	xlog_recover_item_t	*item, *first_item;
    -
    -	if ((error = xlog_recover_reorder_trans(log, trans)))
    -		return error;
    -	first_item = item = trans->r_itemq;
    -	do {
    -		/*
    -		 * we don't need to worry about the block number being
    -		 * truncated in > 1 TB buffers because in user-land,
    -		 * we're now n32 or 64-bit so xfs_daddr_t is 64-bits so
    -		 * the blknos will get through the user-mode buffer
    -		 * cache properly.  The only bad case is o32 kernels
    -		 * where xfs_daddr_t is 32-bits but mount will warn us
    -		 * off a > 1 TB filesystem before we get here.
    -		 */
    -		if ((ITEM_TYPE(item) == XFS_LI_BUF) ||
    -		    (ITEM_TYPE(item) == XFS_LI_6_1_BUF) ||
    -		    (ITEM_TYPE(item) == XFS_LI_5_3_BUF)) {
    -			if  ((error = xlog_recover_do_buffer_trans(log, item,
    -								 pass)))
    -				break;
    -		} else if ((ITEM_TYPE(item) == XFS_LI_INODE) ||
    -			   (ITEM_TYPE(item) == XFS_LI_6_1_INODE) ||
    -			   (ITEM_TYPE(item) == XFS_LI_5_3_INODE)) {
    -			if ((error = xlog_recover_do_inode_trans(log, item,
    -								pass)))
    -				break;
    -		} else if (ITEM_TYPE(item) == XFS_LI_EFI) {
    -			xlog_recover_do_efi_trans(log, item, trans->r_lsn,
    -						  pass);
    -		} else if (ITEM_TYPE(item) == XFS_LI_EFD) {
    -			xlog_recover_do_efd_trans(log, item, pass);
    -		} else if (ITEM_TYPE(item) == XFS_LI_DQUOT) {
    -			if ((error = xlog_recover_do_dquot_trans(log, item,
    -								   pass)))
    -					break;
    -		} else if ((ITEM_TYPE(item) == XFS_LI_QUOTAOFF)) {
    -			if ((error = xlog_recover_do_quotaoff_trans(log, item,
    -								   pass)))
    -					break;
    -		} else {
    -			xlog_warn("XFS: xlog_recover_do_trans");
    -			ASSERT(0);
    -			error = XFS_ERROR(EIO);
    -			break;
    -		}
    -		item = item->ri_next;
    -	} while (first_item != item);
    -
    -	return error;
    -}
    -
    -/*
    - * Free up any resources allocated by the transaction
    - *
    - * Remember that EFIs, EFDs, and IUNLINKs are handled later.
    - */
    -STATIC void
    -xlog_recover_free_trans(
    -	xlog_recover_t		*trans)
    -{
    -	xlog_recover_item_t	*first_item, *item, *free_item;
    -	int			i;
    -
    -	item = first_item = trans->r_itemq;
    -	do {
    -		free_item = item;
    -		item = item->ri_next;
    -		 /* Free the regions in the item. */
    -		for (i = 0; i < free_item->ri_cnt; i++) {
    -			kmem_free(free_item->ri_buf[i].i_addr,
    -				  free_item->ri_buf[i].i_len);
    -		}
    -		/* Free the item itself */
    -		kmem_free(free_item->ri_buf,
    -			  (free_item->ri_total * sizeof(xfs_log_iovec_t)));
    -		kmem_free(free_item, sizeof(xlog_recover_item_t));
    -	} while (first_item != item);
    -	/* Free the transaction recover structure */
    -	kmem_free(trans, sizeof(xlog_recover_t));
    -}
    -
    -STATIC int
    -xlog_recover_commit_trans(
    -	xlog_t			*log,
    -	xlog_recover_t		**q,
    -	xlog_recover_t		*trans,
    -	int			pass)
    -{
    -	int			error;
    -
    -	if ((error = xlog_recover_unlink_tid(q, trans)))
    -		return error;
    -	if ((error = xlog_recover_do_trans(log, trans, pass)))
    -		return error;
    -	xlog_recover_free_trans(trans);			/* no error */
    -	return 0;
    -}
    -
    -STATIC int
    -xlog_recover_unmount_trans(
    -	xlog_recover_t		*trans)
    -{
    -	/* Do nothing now */
    -	xlog_warn("XFS: xlog_recover_unmount_trans: Unmount LR");
    -	return 0;
    -}
    -
    -/*
    - * There are two valid states of the r_state field.  0 indicates that the
    - * transaction structure is in a normal state.  We have either seen the
    - * start of the transaction or the last operation we added was not a partial
    - * operation.  If the last operation we added to the transaction was a
    - * partial operation, we need to mark r_state with XLOG_WAS_CONT_TRANS.
    - *
    - * NOTE: skip LRs with 0 data length.
    - */
    -STATIC int
    -xlog_recover_process_data(
    -	xlog_t			*log,
    -	xlog_recover_t		*rhash[],
    -	xlog_rec_header_t	*rhead,
    -	xfs_caddr_t		dp,
    -	int			pass)
    -{
    -	xfs_caddr_t		lp;
    -	int			num_logops;
    -	xlog_op_header_t	*ohead;
    -	xlog_recover_t		*trans;
    -	xlog_tid_t		tid;
    -	int			error;
    -	unsigned long		hash;
    -	uint			flags;
    -
    -	lp = dp + INT_GET(rhead->h_len, ARCH_CONVERT);
    -	num_logops = INT_GET(rhead->h_num_logops, ARCH_CONVERT);
    -
    -	/* check the log format matches our own - else we can't recover */
    -	if (xlog_header_check_recover(log->l_mp, rhead))
    -		return (XFS_ERROR(EIO));
    -
    -	while ((dp < lp) && num_logops) {
    -		ASSERT(dp + sizeof(xlog_op_header_t) <= lp);
    -		ohead = (xlog_op_header_t *)dp;
    -		dp += sizeof(xlog_op_header_t);
    -		if (ohead->oh_clientid != XFS_TRANSACTION &&
    -		    ohead->oh_clientid != XFS_LOG) {
    -			xlog_warn(
    -		"XFS: xlog_recover_process_data: bad clientid");
    -			ASSERT(0);
    -			return (XFS_ERROR(EIO));
    -		}
    -		tid = INT_GET(ohead->oh_tid, ARCH_CONVERT);
    -		hash = XLOG_RHASH(tid);
    -		trans = xlog_recover_find_tid(rhash[hash], tid);
    -		if (trans == NULL) {		   /* not found; add new tid */
    -			if (ohead->oh_flags & XLOG_START_TRANS)
    -				xlog_recover_new_tid(&rhash[hash], tid,
    -					INT_GET(rhead->h_lsn, ARCH_CONVERT));
    -		} else {
    -			ASSERT(dp+INT_GET(ohead->oh_len, ARCH_CONVERT) <= lp);
    -			flags = ohead->oh_flags & ~XLOG_END_TRANS;
    -			if (flags & XLOG_WAS_CONT_TRANS)
    -				flags &= ~XLOG_CONTINUE_TRANS;
    -			switch (flags) {
    -			case XLOG_COMMIT_TRANS:
    -				error = xlog_recover_commit_trans(log,
    -						&rhash[hash], trans, pass);
    -				break;
    -			case XLOG_UNMOUNT_TRANS:
    -				error = xlog_recover_unmount_trans(trans);
    -				break;
    -			case XLOG_WAS_CONT_TRANS:
    -				error = xlog_recover_add_to_cont_trans(trans,
    -						dp, INT_GET(ohead->oh_len,
    -							ARCH_CONVERT));
    -				break;
    -			case XLOG_START_TRANS:
    -				xlog_warn(
    -			"XFS: xlog_recover_process_data: bad transaction");
    -				ASSERT(0);
    -				error = XFS_ERROR(EIO);
    -				break;
    -			case 0:
    -			case XLOG_CONTINUE_TRANS:
    -				error = xlog_recover_add_to_trans(trans,
    -						dp, INT_GET(ohead->oh_len,
    -							ARCH_CONVERT));
    -				break;
    -			default:
    -				xlog_warn(
    -			"XFS: xlog_recover_process_data: bad flag");
    -				ASSERT(0);
    -				error = XFS_ERROR(EIO);
    -				break;
    -			}
    -			if (error)
    -				return error;
    -		}
    -		dp += INT_GET(ohead->oh_len, ARCH_CONVERT);
    -		num_logops--;
    -	}
    -	return 0;
    -}
    -
    -/*
    - * Process an extent free intent item that was recovered from
    - * the log.  We need to free the extents that it describes.
    - */
    -STATIC void
    -xlog_recover_process_efi(
    -	xfs_mount_t		*mp,
    -	xfs_efi_log_item_t	*efip)
    -{
    -	xfs_efd_log_item_t	*efdp;
    -	xfs_trans_t		*tp;
    -	int			i;
    -	xfs_extent_t		*extp;
    -	xfs_fsblock_t		startblock_fsb;
    -
    -	ASSERT(!(efip->efi_flags & XFS_EFI_RECOVERED));
    -
    -	/*
    -	 * First check the validity of the extents described by the
    -	 * EFI.  If any are bad, then assume that all are bad and
    -	 * just toss the EFI.
    -	 */
    -	for (i = 0; i < efip->efi_format.efi_nextents; i++) {
    -		extp = &(efip->efi_format.efi_extents[i]);
    -		startblock_fsb = XFS_BB_TO_FSB(mp,
    -				   XFS_FSB_TO_DADDR(mp, extp->ext_start));
    -		if ((startblock_fsb == 0) ||
    -		    (extp->ext_len == 0) ||
    -		    (startblock_fsb >= mp->m_sb.sb_dblocks) ||
    -		    (extp->ext_len >= mp->m_sb.sb_agblocks)) {
    -			/*
    -			 * This will pull the EFI from the AIL and
    -			 * free the memory associated with it.
    -			 */
    -			xfs_efi_release(efip, efip->efi_format.efi_nextents);
    -			return;
    -		}
    -	}
    -
    -	tp = xfs_trans_alloc(mp, 0);
    -	xfs_trans_reserve(tp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0, 0, 0);
    -	efdp = xfs_trans_get_efd(tp, efip, efip->efi_format.efi_nextents);
    -
    -	for (i = 0; i < efip->efi_format.efi_nextents; i++) {
    -		extp = &(efip->efi_format.efi_extents[i]);
    -		xfs_free_extent(tp, extp->ext_start, extp->ext_len);
    -		xfs_trans_log_efd_extent(tp, efdp, extp->ext_start,
    -					 extp->ext_len);
    -	}
    -
    -	efip->efi_flags |= XFS_EFI_RECOVERED;
    -	xfs_trans_commit(tp, 0, NULL);
    -}
    -
    -/*
    - * Verify that once we've encountered something other than an EFI
    - * in the AIL that there are no more EFIs in the AIL.
    - */
    -#if defined(DEBUG)
    -STATIC void
    -xlog_recover_check_ail(
    -	xfs_mount_t		*mp,
    -	xfs_log_item_t		*lip,
    -	int			gen)
    -{
    -	int			orig_gen = gen;
    -
    -	do {
    -		ASSERT(lip->li_type != XFS_LI_EFI);
    -		lip = xfs_trans_next_ail(mp, lip, &gen, NULL);
    -		/*
    -		 * The check will be bogus if we restart from the
    -		 * beginning of the AIL, so ASSERT that we don't.
    -		 * We never should since we're holding the AIL lock
    -		 * the entire time.
    -		 */
    -		ASSERT(gen == orig_gen);
    -	} while (lip != NULL);
    -}
    -#endif	/* DEBUG */
    -
    -/*
    - * When this is called, all of the EFIs which did not have
    - * corresponding EFDs should be in the AIL.  What we do now
    - * is free the extents associated with each one.
    - *
    - * Since we process the EFIs in normal transactions, they
    - * will be removed at some point after the commit.  This prevents
    - * us from just walking down the list processing each one.
    - * We'll use a flag in the EFI to skip those that we've already
    - * processed and use the AIL iteration mechanism's generation
    - * count to try to speed this up at least a bit.
    - *
    - * When we start, we know that the EFIs are the only things in
    - * the AIL.  As we process them, however, other items are added
    - * to the AIL.  Since everything added to the AIL must come after
    - * everything already in the AIL, we stop processing as soon as
    - * we see something other than an EFI in the AIL.
    - */
    -STATIC void
    -xlog_recover_process_efis(
    -	xlog_t			*log)
    -{
    -	xfs_log_item_t		*lip;
    -	xfs_efi_log_item_t	*efip;
    -	int			gen;
    -	xfs_mount_t		*mp;
    -	SPLDECL(s);
    -
    -	mp = log->l_mp;
    -	AIL_LOCK(mp,s);
    -
    -	lip = xfs_trans_first_ail(mp, &gen);
    -	while (lip != NULL) {
    -		/*
    -		 * We're done when we see something other than an EFI.
    -		 */
    -		if (lip->li_type != XFS_LI_EFI) {
    -			xlog_recover_check_ail(mp, lip, gen);
    -			break;
    -		}
    -
    -		/*
    -		 * Skip EFIs that we've already processed.
    -		 */
    -		efip = (xfs_efi_log_item_t *)lip;
    -		if (efip->efi_flags & XFS_EFI_RECOVERED) {
    -			lip = xfs_trans_next_ail(mp, lip, &gen, NULL);
    -			continue;
    -		}
    -
    -		AIL_UNLOCK(mp, s);
    -		xlog_recover_process_efi(mp, efip);
    -		AIL_LOCK(mp,s);
    -		lip = xfs_trans_next_ail(mp, lip, &gen, NULL);
    -	}
    -	AIL_UNLOCK(mp, s);
    -}
    -
    -/*
    - * This routine performs a transaction to null out a bad inode pointer
    - * in an agi unlinked inode hash bucket.
    - */
    -STATIC void
    -xlog_recover_clear_agi_bucket(
    -	xfs_mount_t	*mp,
    -	xfs_agnumber_t	agno,
    -	int		bucket)
    -{
    -	xfs_trans_t	*tp;
    -	xfs_agi_t	*agi;
    -	xfs_buf_t	*agibp;
    -	int		offset;
    -	int		error;
    -
    -	tp = xfs_trans_alloc(mp, XFS_TRANS_CLEAR_AGI_BUCKET);
    -	xfs_trans_reserve(tp, 0, XFS_CLEAR_AGI_BUCKET_LOG_RES(mp), 0, 0, 0);
    -
    -	error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
    -				   XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
    -				   XFS_FSS_TO_BB(mp, 1), 0, &agibp);
    -	if (error) {
    -		xfs_trans_cancel(tp, XFS_TRANS_ABORT);
    -		return;
    -	}
    -
    -	agi = XFS_BUF_TO_AGI(agibp);
    -	if (be32_to_cpu(agi->agi_magicnum) != XFS_AGI_MAGIC) {
    -		xfs_trans_cancel(tp, XFS_TRANS_ABORT);
    -		return;
    -	}
    -
    -	agi->agi_unlinked[bucket] = cpu_to_be32(NULLAGINO);
    -	offset = offsetof(xfs_agi_t, agi_unlinked) +
    -		 (sizeof(xfs_agino_t) * bucket);
    -	xfs_trans_log_buf(tp, agibp, offset,
    -			  (offset + sizeof(xfs_agino_t) - 1));
    -
    -	(void) xfs_trans_commit(tp, 0, NULL);
    -}
    -
    -/*
    - * xlog_iunlink_recover
    - *
    - * This is called during recovery to process any inodes which
    - * we unlinked but not freed when the system crashed.  These
    - * inodes will be on the lists in the AGI blocks.  What we do
    - * here is scan all the AGIs and fully truncate and free any
    - * inodes found on the lists.  Each inode is removed from the
    - * lists when it has been fully truncated and is freed.  The
    - * freeing of the inode and its removal from the list must be
    - * atomic.
    - */
    -void
    -xlog_recover_process_iunlinks(
    -	xlog_t		*log)
    -{
    -	xfs_mount_t	*mp;
    -	xfs_agnumber_t	agno;
    -	xfs_agi_t	*agi;
    -	xfs_buf_t	*agibp;
    -	xfs_buf_t	*ibp;
    -	xfs_dinode_t	*dip;
    -	xfs_inode_t	*ip;
    -	xfs_agino_t	agino;
    -	xfs_ino_t	ino;
    -	int		bucket;
    -	int		error;
    -	uint		mp_dmevmask;
    -
    -	mp = log->l_mp;
    -
    -	/*
    -	 * Prevent any DMAPI event from being sent while in this function.
    -	 */
    -	mp_dmevmask = mp->m_dmevmask;
    -	mp->m_dmevmask = 0;
    -
    -	for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
    -		/*
    -		 * Find the agi for this ag.
    -		 */
    -		agibp = xfs_buf_read(mp->m_ddev_targp,
    -				XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
    -				XFS_FSS_TO_BB(mp, 1), 0);
    -		if (XFS_BUF_ISERROR(agibp)) {
    -			xfs_ioerror_alert("xlog_recover_process_iunlinks(#1)",
    -				log->l_mp, agibp,
    -				XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)));
    -		}
    -		agi = XFS_BUF_TO_AGI(agibp);
    -		ASSERT(XFS_AGI_MAGIC == be32_to_cpu(agi->agi_magicnum));
    -
    -		for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++) {
    -
    -			agino = be32_to_cpu(agi->agi_unlinked[bucket]);
    -			while (agino != NULLAGINO) {
    -
    -				/*
    -				 * Release the agi buffer so that it can
    -				 * be acquired in the normal course of the
    -				 * transaction to truncate and free the inode.
    -				 */
    -				xfs_buf_relse(agibp);
    -
    -				ino = XFS_AGINO_TO_INO(mp, agno, agino);
    -				error = xfs_iget(mp, NULL, ino, 0, 0, &ip, 0);
    -				ASSERT(error || (ip != NULL));
    -
    -				if (!error) {
    -					/*
    -					 * Get the on disk inode to find the
    -					 * next inode in the bucket.
    -					 */
    -					error = xfs_itobp(mp, NULL, ip, &dip,
    -							&ibp, 0, 0);
    -					ASSERT(error || (dip != NULL));
    -				}
    -
    -				if (!error) {
    -					ASSERT(ip->i_d.di_nlink == 0);
    -
    -					/* setup for the next pass */
    -					agino = INT_GET(dip->di_next_unlinked,
    -							ARCH_CONVERT);
    -					xfs_buf_relse(ibp);
    -					/*
    -					 * Prevent any DMAPI event from
    -					 * being sent when the
    -					 * reference on the inode is
    -					 * dropped.
    -					 */
    -					ip->i_d.di_dmevmask = 0;
    -
    -					/*
    -					 * If this is a new inode, handle
    -					 * it specially.  Otherwise,
    -					 * just drop our reference to the
    -					 * inode.  If there are no
    -					 * other references, this will
    -					 * send the inode to
    -					 * xfs_inactive() which will
    -					 * truncate the file and free
    -					 * the inode.
    -					 */
    -					if (ip->i_d.di_mode == 0)
    -						xfs_iput_new(ip, 0);
    -					else
    -						VN_RELE(XFS_ITOV(ip));
    -				} else {
    -					/*
    -					 * We can't read in the inode
    -					 * this bucket points to, or
    -					 * this inode is messed up.  Just
    -					 * ditch this bucket of inodes.  We
    -					 * will lose some inodes and space,
    -					 * but at least we won't hang.  Call
    -					 * xlog_recover_clear_agi_bucket()
    -					 * to perform a transaction to clear
    -					 * the inode pointer in the bucket.
    -					 */
    -					xlog_recover_clear_agi_bucket(mp, agno,
    -							bucket);
    -
    -					agino = NULLAGINO;
    -				}
    -
    -				/*
    -				 * Reacquire the agibuffer and continue around
    -				 * the loop.
    -				 */
    -				agibp = xfs_buf_read(mp->m_ddev_targp,
    -						XFS_AG_DADDR(mp, agno,
    -							XFS_AGI_DADDR(mp)),
    -						XFS_FSS_TO_BB(mp, 1), 0);
    -				if (XFS_BUF_ISERROR(agibp)) {
    -					xfs_ioerror_alert(
    -				"xlog_recover_process_iunlinks(#2)",
    -						log->l_mp, agibp,
    -						XFS_AG_DADDR(mp, agno,
    -							XFS_AGI_DADDR(mp)));
    -				}
    -				agi = XFS_BUF_TO_AGI(agibp);
    -				ASSERT(XFS_AGI_MAGIC == be32_to_cpu(
    -					agi->agi_magicnum));
    -			}
    -		}
    -
    -		/*
    -		 * Release the buffer for the current agi so we can
    -		 * go on to the next one.
    -		 */
    -		xfs_buf_relse(agibp);
    -	}
    -
    -	mp->m_dmevmask = mp_dmevmask;
    -}
    -
    -
    -#ifdef DEBUG
    -STATIC void
    -xlog_pack_data_checksum(
    -	xlog_t		*log,
    -	xlog_in_core_t	*iclog,
    -	int		size)
    -{
    -	int		i;
    -	uint		*up;
    -	uint		chksum = 0;
    -
    -	up = (uint *)iclog->ic_datap;
    -	/* divide length by 4 to get # words */
    -	for (i = 0; i < (size >> 2); i++) {
    -		chksum ^= INT_GET(*up, ARCH_CONVERT);
    -		up++;
    -	}
    -	INT_SET(iclog->ic_header.h_chksum, ARCH_CONVERT, chksum);
    -}
    -#else
    -#define xlog_pack_data_checksum(log, iclog, size)
    -#endif
    -
    -/*
    - * Stamp cycle number in every block
    - */
    -void
    -xlog_pack_data(
    -	xlog_t			*log,
    -	xlog_in_core_t		*iclog,
    -	int			roundoff)
    -{
    -	int			i, j, k;
    -	int			size = iclog->ic_offset + roundoff;
    -	uint			cycle_lsn;
    -	xfs_caddr_t		dp;
    -	xlog_in_core_2_t	*xhdr;
    -
    -	xlog_pack_data_checksum(log, iclog, size);
    -
    -	cycle_lsn = CYCLE_LSN_DISK(iclog->ic_header.h_lsn);
    -
    -	dp = iclog->ic_datap;
    -	for (i = 0; i < BTOBB(size) &&
    -		i < (XLOG_HEADER_CYCLE_SIZE / BBSIZE); i++) {
    -		iclog->ic_header.h_cycle_data[i] = *(uint *)dp;
    -		*(uint *)dp = cycle_lsn;
    -		dp += BBSIZE;
    -	}
    -
    -	if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) {
    -		xhdr = (xlog_in_core_2_t *)&iclog->ic_header;
    -		for ( ; i < BTOBB(size); i++) {
    -			j = i / (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
    -			k = i % (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
    -			xhdr[j].hic_xheader.xh_cycle_data[k] = *(uint *)dp;
    -			*(uint *)dp = cycle_lsn;
    -			dp += BBSIZE;
    -		}
    -
    -		for (i = 1; i < log->l_iclog_heads; i++) {
    -			xhdr[i].hic_xheader.xh_cycle = cycle_lsn;
    -		}
    -	}
    -}
    -
    -#if defined(DEBUG) && defined(XFS_LOUD_RECOVERY)
    -STATIC void
    -xlog_unpack_data_checksum(
    -	xlog_rec_header_t	*rhead,
    -	xfs_caddr_t		dp,
    -	xlog_t			*log)
    -{
    -	uint			*up = (uint *)dp;
    -	uint			chksum = 0;
    -	int			i;
    -
    -	/* divide length by 4 to get # words */
    -	for (i=0; i < INT_GET(rhead->h_len, ARCH_CONVERT) >> 2; i++) {
    -		chksum ^= INT_GET(*up, ARCH_CONVERT);
    -		up++;
    -	}
    -	if (chksum != INT_GET(rhead->h_chksum, ARCH_CONVERT)) {
    -	    if (rhead->h_chksum ||
    -		((log->l_flags & XLOG_CHKSUM_MISMATCH) == 0)) {
    -		    cmn_err(CE_DEBUG,
    -			"XFS: LogR chksum mismatch: was (0x%x) is (0x%x)",
    -			    INT_GET(rhead->h_chksum, ARCH_CONVERT), chksum);
    -		    cmn_err(CE_DEBUG,
    -"XFS: Disregard message if filesystem was created with non-DEBUG kernel");
    -		    if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) {
    -			    cmn_err(CE_DEBUG,
    -				"XFS: LogR this is a LogV2 filesystem");
    -		    }
    -		    log->l_flags |= XLOG_CHKSUM_MISMATCH;
    -	    }
    -	}
    -}
    -#else
    -#define xlog_unpack_data_checksum(rhead, dp, log)
    -#endif
    -
    -STATIC void
    -xlog_unpack_data(
    -	xlog_rec_header_t	*rhead,
    -	xfs_caddr_t		dp,
    -	xlog_t			*log)
    -{
    -	int			i, j, k;
    -	xlog_in_core_2_t	*xhdr;
    -
    -	for (i = 0; i < BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT)) &&
    -		  i < (XLOG_HEADER_CYCLE_SIZE / BBSIZE); i++) {
    -		*(uint *)dp = *(uint *)&rhead->h_cycle_data[i];
    -		dp += BBSIZE;
    -	}
    -
    -	if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) {
    -		xhdr = (xlog_in_core_2_t *)rhead;
    -		for ( ; i < BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT)); i++) {
    -			j = i / (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
    -			k = i % (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
    -			*(uint *)dp = xhdr[j].hic_xheader.xh_cycle_data[k];
    -			dp += BBSIZE;
    -		}
    -	}
    -
    -	xlog_unpack_data_checksum(rhead, dp, log);
    -}
    -
    -STATIC int
    -xlog_valid_rec_header(
    -	xlog_t			*log,
    -	xlog_rec_header_t	*rhead,
    -	xfs_daddr_t		blkno)
    -{
    -	int			hlen;
    -
    -	if (unlikely(
    -	    (INT_GET(rhead->h_magicno, ARCH_CONVERT) !=
    -			XLOG_HEADER_MAGIC_NUM))) {
    -		XFS_ERROR_REPORT("xlog_valid_rec_header(1)",
    -				XFS_ERRLEVEL_LOW, log->l_mp);
    -		return XFS_ERROR(EFSCORRUPTED);
    -	}
    -	if (unlikely(
    -	    (!rhead->h_version ||
    -	    (INT_GET(rhead->h_version, ARCH_CONVERT) &
    -			(~XLOG_VERSION_OKBITS)) != 0))) {
    -		xlog_warn("XFS: %s: unrecognised log version (%d).",
    -			__FUNCTION__, INT_GET(rhead->h_version, ARCH_CONVERT));
    -		return XFS_ERROR(EIO);
    -	}
    -
    -	/* LR body must have data or it wouldn't have been written */
    -	hlen = INT_GET(rhead->h_len, ARCH_CONVERT);
    -	if (unlikely( hlen <= 0 || hlen > INT_MAX )) {
    -		XFS_ERROR_REPORT("xlog_valid_rec_header(2)",
    -				XFS_ERRLEVEL_LOW, log->l_mp);
    -		return XFS_ERROR(EFSCORRUPTED);
    -	}
    -	if (unlikely( blkno > log->l_logBBsize || blkno > INT_MAX )) {
    -		XFS_ERROR_REPORT("xlog_valid_rec_header(3)",
    -				XFS_ERRLEVEL_LOW, log->l_mp);
    -		return XFS_ERROR(EFSCORRUPTED);
    -	}
    -	return 0;
    -}
    -
    -/*
    - * Read the log from tail to head and process the log records found.
    - * Handle the two cases where the tail and head are in the same cycle
    - * and where the active portion of the log wraps around the end of
    - * the physical log separately.  The pass parameter is passed through
    - * to the routines called to process the data and is not looked at
    - * here.
    - */
    -STATIC int
    -xlog_do_recovery_pass(
    -	xlog_t			*log,
    -	xfs_daddr_t		head_blk,
    -	xfs_daddr_t		tail_blk,
    -	int			pass)
    -{
    -	xlog_rec_header_t	*rhead;
    -	xfs_daddr_t		blk_no;
    -	xfs_caddr_t		bufaddr, offset;
    -	xfs_buf_t		*hbp, *dbp;
    -	int			error = 0, h_size;
    -	int			bblks, split_bblks;
    -	int			hblks, split_hblks, wrapped_hblks;
    -	xlog_recover_t		*rhash[XLOG_RHASH_SIZE];
    -
    -	ASSERT(head_blk != tail_blk);
    -
    -	/*
    -	 * Read the header of the tail block and get the iclog buffer size from
    -	 * h_size.  Use this to tell how many sectors make up the log header.
    -	 */
    -	if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) {
    -		/*
    -		 * When using variable length iclogs, read first sector of
    -		 * iclog header and extract the header size from it.  Get a
    -		 * new hbp that is the correct size.
    -		 */
    -		hbp = xlog_get_bp(log, 1);
    -		if (!hbp)
    -			return ENOMEM;
    -		if ((error = xlog_bread(log, tail_blk, 1, hbp)))
    -			goto bread_err1;
    -		offset = xlog_align(log, tail_blk, 1, hbp);
    -		rhead = (xlog_rec_header_t *)offset;
    -		error = xlog_valid_rec_header(log, rhead, tail_blk);
    -		if (error)
    -			goto bread_err1;
    -		h_size = INT_GET(rhead->h_size, ARCH_CONVERT);
    -		if ((INT_GET(rhead->h_version, ARCH_CONVERT)
    -				& XLOG_VERSION_2) &&
    -		    (h_size > XLOG_HEADER_CYCLE_SIZE)) {
    -			hblks = h_size / XLOG_HEADER_CYCLE_SIZE;
    -			if (h_size % XLOG_HEADER_CYCLE_SIZE)
    -				hblks++;
    -			xlog_put_bp(hbp);
    -			hbp = xlog_get_bp(log, hblks);
    -		} else {
    -			hblks = 1;
    -		}
    -	} else {
    -		ASSERT(log->l_sectbb_log == 0);
    -		hblks = 1;
    -		hbp = xlog_get_bp(log, 1);
    -		h_size = XLOG_BIG_RECORD_BSIZE;
    -	}
    -
    -	if (!hbp)
    -		return ENOMEM;
    -	dbp = xlog_get_bp(log, BTOBB(h_size));
    -	if (!dbp) {
    -		xlog_put_bp(hbp);
    -		return ENOMEM;
    -	}
    -
    -	memset(rhash, 0, sizeof(rhash));
    -	if (tail_blk <= head_blk) {
    -		for (blk_no = tail_blk; blk_no < head_blk; ) {
    -			if ((error = xlog_bread(log, blk_no, hblks, hbp)))
    -				goto bread_err2;
    -			offset = xlog_align(log, blk_no, hblks, hbp);
    -			rhead = (xlog_rec_header_t *)offset;
    -			error = xlog_valid_rec_header(log, rhead, blk_no);
    -			if (error)
    -				goto bread_err2;
    -
    -			/* blocks in data section */
    -			bblks = (int)BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT));
    -			error = xlog_bread(log, blk_no + hblks, bblks, dbp);
    -			if (error)
    -				goto bread_err2;
    -			offset = xlog_align(log, blk_no + hblks, bblks, dbp);
    -			xlog_unpack_data(rhead, offset, log);
    -			if ((error = xlog_recover_process_data(log,
    -						rhash, rhead, offset, pass)))
    -				goto bread_err2;
    -			blk_no += bblks + hblks;
    -		}
    -	} else {
    -		/*
    -		 * Perform recovery around the end of the physical log.
    -		 * When the head is not on the same cycle number as the tail,
    -		 * we can't do a sequential recovery as above.
    -		 */
    -		blk_no = tail_blk;
    -		while (blk_no < log->l_logBBsize) {
    -			/*
    -			 * Check for header wrapping around physical end-of-log
    -			 */
    -			offset = NULL;
    -			split_hblks = 0;
    -			wrapped_hblks = 0;
    -			if (blk_no + hblks <= log->l_logBBsize) {
    -				/* Read header in one read */
    -				error = xlog_bread(log, blk_no, hblks, hbp);
    -				if (error)
    -					goto bread_err2;
    -				offset = xlog_align(log, blk_no, hblks, hbp);
    -			} else {
    -				/* This LR is split across physical log end */
    -				if (blk_no != log->l_logBBsize) {
    -					/* some data before physical log end */
    -					ASSERT(blk_no <= INT_MAX);
    -					split_hblks = log->l_logBBsize - (int)blk_no;
    -					ASSERT(split_hblks > 0);
    -					if ((error = xlog_bread(log, blk_no,
    -							split_hblks, hbp)))
    -						goto bread_err2;
    -					offset = xlog_align(log, blk_no,
    -							split_hblks, hbp);
    -				}
    -				/*
    -				 * Note: this black magic still works with
    -				 * large sector sizes (non-512) only because:
    -				 * - we increased the buffer size originally
    -				 *   by 1 sector giving us enough extra space
    -				 *   for the second read;
    -				 * - the log start is guaranteed to be sector
    -				 *   aligned;
    -				 * - we read the log end (LR header start)
    -				 *   _first_, then the log start (LR header end)
    -				 *   - order is important.
    -				 */
    -				bufaddr = XFS_BUF_PTR(hbp);
    -				XFS_BUF_SET_PTR(hbp,
    -						bufaddr + BBTOB(split_hblks),
    -						BBTOB(hblks - split_hblks));
    -				wrapped_hblks = hblks - split_hblks;
    -				error = xlog_bread(log, 0, wrapped_hblks, hbp);
    -				if (error)
    -					goto bread_err2;
    -				XFS_BUF_SET_PTR(hbp, bufaddr, BBTOB(hblks));
    -				if (!offset)
    -					offset = xlog_align(log, 0,
    -							wrapped_hblks, hbp);
    -			}
    -			rhead = (xlog_rec_header_t *)offset;
    -			error = xlog_valid_rec_header(log, rhead,
    -						split_hblks ? blk_no : 0);
    -			if (error)
    -				goto bread_err2;
    -
    -			bblks = (int)BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT));
    -			blk_no += hblks;
    -
    -			/* Read in data for log record */
    -			if (blk_no + bblks <= log->l_logBBsize) {
    -				error = xlog_bread(log, blk_no, bblks, dbp);
    -				if (error)
    -					goto bread_err2;
    -				offset = xlog_align(log, blk_no, bblks, dbp);
    -			} else {
    -				/* This log record is split across the
    -				 * physical end of log */
    -				offset = NULL;
    -				split_bblks = 0;
    -				if (blk_no != log->l_logBBsize) {
    -					/* some data is before the physical
    -					 * end of log */
    -					ASSERT(!wrapped_hblks);
    -					ASSERT(blk_no <= INT_MAX);
    -					split_bblks =
    -						log->l_logBBsize - (int)blk_no;
    -					ASSERT(split_bblks > 0);
    -					if ((error = xlog_bread(log, blk_no,
    -							split_bblks, dbp)))
    -						goto bread_err2;
    -					offset = xlog_align(log, blk_no,
    -							split_bblks, dbp);
    -				}
    -				/*
    -				 * Note: this black magic still works with
    -				 * large sector sizes (non-512) only because:
    -				 * - we increased the buffer size originally
    -				 *   by 1 sector giving us enough extra space
    -				 *   for the second read;
    -				 * - the log start is guaranteed to be sector
    -				 *   aligned;
    -				 * - we read the log end (LR header start)
    -				 *   _first_, then the log start (LR header end)
    -				 *   - order is important.
    -				 */
    -				bufaddr = XFS_BUF_PTR(dbp);
    -				XFS_BUF_SET_PTR(dbp,
    -						bufaddr + BBTOB(split_bblks),
    -						BBTOB(bblks - split_bblks));
    -				if ((error = xlog_bread(log, wrapped_hblks,
    -						bblks - split_bblks, dbp)))
    -					goto bread_err2;
    -				XFS_BUF_SET_PTR(dbp, bufaddr, h_size);
    -				if (!offset)
    -					offset = xlog_align(log, wrapped_hblks,
    -						bblks - split_bblks, dbp);
    -			}
    -			xlog_unpack_data(rhead, offset, log);
    -			if ((error = xlog_recover_process_data(log, rhash,
    -							rhead, offset, pass)))
    -				goto bread_err2;
    -			blk_no += bblks;
    -		}
    -
    -		ASSERT(blk_no >= log->l_logBBsize);
    -		blk_no -= log->l_logBBsize;
    -
    -		/* read first part of physical log */
    -		while (blk_no < head_blk) {
    -			if ((error = xlog_bread(log, blk_no, hblks, hbp)))
    -				goto bread_err2;
    -			offset = xlog_align(log, blk_no, hblks, hbp);
    -			rhead = (xlog_rec_header_t *)offset;
    -			error = xlog_valid_rec_header(log, rhead, blk_no);
    -			if (error)
    -				goto bread_err2;
    -			bblks = (int)BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT));
    -			if ((error = xlog_bread(log, blk_no+hblks, bblks, dbp)))
    -				goto bread_err2;
    -			offset = xlog_align(log, blk_no+hblks, bblks, dbp);
    -			xlog_unpack_data(rhead, offset, log);
    -			if ((error = xlog_recover_process_data(log, rhash,
    -							rhead, offset, pass)))
    -				goto bread_err2;
    -			blk_no += bblks + hblks;
    -		}
    -	}
    -
    - bread_err2:
    -	xlog_put_bp(dbp);
    - bread_err1:
    -	xlog_put_bp(hbp);
    -	return error;
    -}
    -
    -/*
    - * Do the recovery of the log.  We actually do this in two phases.
    - * The two passes are necessary in order to implement the function
    - * of cancelling a record written into the log.  The first pass
    - * determines those things which have been cancelled, and the
    - * second pass replays log items normally except for those which
    - * have been cancelled.  The handling of the replay and cancellations
    - * takes place in the log item type specific routines.
    - *
    - * The table of items which have cancel records in the log is allocated
    - * and freed at this level, since only here do we know when all of
    - * the log recovery has been completed.
    - */
    -STATIC int
    -xlog_do_log_recovery(
    -	xlog_t		*log,
    -	xfs_daddr_t	head_blk,
    -	xfs_daddr_t	tail_blk)
    -{
    -	int		error;
    -
    -	ASSERT(head_blk != tail_blk);
    -
    -	/*
    -	 * First do a pass to find all of the cancelled buf log items.
    -	 * Store them in the buf_cancel_table for use in the second pass.
    -	 */
    -	log->l_buf_cancel_table =
    -		(xfs_buf_cancel_t **)kmem_zalloc(XLOG_BC_TABLE_SIZE *
    -						 sizeof(xfs_buf_cancel_t*),
    -						 KM_SLEEP);
    -	error = xlog_do_recovery_pass(log, head_blk, tail_blk,
    -				      XLOG_RECOVER_PASS1);
    -	if (error != 0) {
    -		kmem_free(log->l_buf_cancel_table,
    -			  XLOG_BC_TABLE_SIZE * sizeof(xfs_buf_cancel_t*));
    -		log->l_buf_cancel_table = NULL;
    -		return error;
    -	}
    -	/*
    -	 * Then do a second pass to actually recover the items in the log.
    -	 * When it is complete free the table of buf cancel items.
    -	 */
    -	error = xlog_do_recovery_pass(log, head_blk, tail_blk,
    -				      XLOG_RECOVER_PASS2);
    -#ifdef DEBUG
    -	{
    -		int	i;
    -
    -		for (i = 0; i < XLOG_BC_TABLE_SIZE; i++)
    -			ASSERT(log->l_buf_cancel_table[i] == NULL);
    -	}
    -#endif	/* DEBUG */
    -
    -	kmem_free(log->l_buf_cancel_table,
    -		  XLOG_BC_TABLE_SIZE * sizeof(xfs_buf_cancel_t*));
    -	log->l_buf_cancel_table = NULL;
    -
    -	return error;
    -}
    -
    -/*
    - * Do the actual recovery
    - */
    -STATIC int
    -xlog_do_recover(
    -	xlog_t		*log,
    -	xfs_daddr_t	head_blk,
    -	xfs_daddr_t	tail_blk)
    -{
    -	int		error;
    -	xfs_buf_t	*bp;
    -	xfs_sb_t	*sbp;
    -
    -	/*
    -	 * XXX: Disable log recovery for now, until we fix panics.
    -	 */
    -	printf("XFS log recovery disabled.\n");
    -	return (EOPNOTSUPP);
    -	/*
    -	 * First replay the images in the log.
    -	 */
    -	error = xlog_do_log_recovery(log, head_blk, tail_blk);
    -	if (error) {
    -		return error;
    -	}
    -
    -	XFS_bflush(log->l_mp->m_ddev_targp);
    -
    -	/*
    -	 * If IO errors happened during recovery, bail out.
    -	 */
    -	if (XFS_FORCED_SHUTDOWN(log->l_mp)) {
    -		return (EIO);
    -	}
    -
    -	/*
    -	 * We now update the tail_lsn since much of the recovery has completed
    -	 * and there may be space available to use.  If there were no extent
    -	 * or iunlinks, we can free up the entire log and set the tail_lsn to
    -	 * be the last_sync_lsn.  This was set in xlog_find_tail to be the
    -	 * lsn of the last known good LR on disk.  If there are extent frees
    -	 * or iunlinks they will have some entries in the AIL; so we look at
    -	 * the AIL to determine how to set the tail_lsn.
    -	 */
    -	xlog_assign_tail_lsn(log->l_mp);
    -
    -	/*
    -	 * Now that we've finished replaying all buffer and inode
    -	 * updates, re-read in the superblock.
    -	 */
    -	bp = xfs_getsb(log->l_mp, 0);
    -	XFS_BUF_UNDONE(bp);
    -	XFS_BUF_READ(bp);
    -	xfsbdstrat(log->l_mp, bp);
    -	if ((error = xfs_iowait(bp))) {
    -		xfs_ioerror_alert("xlog_do_recover",
    -				  log->l_mp, bp, XFS_BUF_ADDR(bp));
    -		ASSERT(0);
    -		xfs_buf_relse(bp);
    -		return error;
    -	}
    -
    -	/* Convert superblock from on-disk format */
    -	sbp = &log->l_mp->m_sb;
    -	xfs_xlatesb(XFS_BUF_TO_SBP(bp), sbp, 1, XFS_SB_ALL_BITS);
    -	ASSERT(sbp->sb_magicnum == XFS_SB_MAGIC);
    -	ASSERT(XFS_SB_GOOD_VERSION(sbp));
    -	xfs_buf_relse(bp);
    -
    -	xlog_recover_check_summary(log);
    -
    -	/* Normal transactions can now occur */
    -	log->l_flags &= ~XLOG_ACTIVE_RECOVERY;
    -	return 0;
    -}
    -
    -/*
    - * Perform recovery and re-initialize some log variables in xlog_find_tail.
    - *
    - * Return error or zero.
    - */
    -int
    -xlog_recover(
    -	xlog_t		*log)
    -{
    -	xfs_daddr_t	head_blk, tail_blk;
    -	int		error;
    -
    -	/* find the tail of the log */
    -	if ((error = xlog_find_tail(log, &head_blk, &tail_blk)))
    -		return error;
    -
    -	if (tail_blk != head_blk) {
    -		/* There used to be a comment here:
    -		 *
    -		 * disallow recovery on read-only mounts.  note -- mount
    -		 * checks for ENOSPC and turns it into an intelligent
    -		 * error message.
    -		 * ...but this is no longer true.  Now, unless you specify
    -		 * NORECOVERY (in which case this function would never be
    -		 * called), we just go ahead and recover.  We do this all
    -		 * under the vfs layer, so we can get away with it unless
    -		 * the device itself is read-only, in which case we fail.
    -		 */
    -		if ((error = xfs_dev_is_read_only(log->l_mp,
    -						"recovery required"))) {
    -			return error;
    -		}
    -
    -		cmn_err(CE_NOTE,
    -			"Starting XFS recovery on filesystem: %s (logdev: %s)",
    -			log->l_mp->m_fsname, log->l_mp->m_logname ?
    -			log->l_mp->m_logname : "internal");
    -
    -		error = xlog_do_recover(log, head_blk, tail_blk);
    -		log->l_flags |= XLOG_RECOVERY_NEEDED;
    -	}
    -	return error;
    -}
    -
    -/*
    - * In the first part of recovery we replay inodes and buffers and build
    - * up the list of extent free items which need to be processed.  Here
    - * we process the extent free items and clean up the on disk unlinked
    - * inode lists.  This is separated from the first part of recovery so
    - * that the root and real-time bitmap inodes can be read in from disk in
    - * between the two stages.  This is necessary so that we can free space
    - * in the real-time portion of the file system.
    - */
    -int
    -xlog_recover_finish(
    -	xlog_t		*log,
    -	int		mfsi_flags)
    -{
    -	/*
    -	 * Now we're ready to do the transactions needed for the
    -	 * rest of recovery.  Start with completing all the extent
    -	 * free intent records and then process the unlinked inode
    -	 * lists.  At this point, we essentially run in normal mode
    -	 * except that we're still performing recovery actions
    -	 * rather than accepting new requests.
    -	 */
    -	if (log->l_flags & XLOG_RECOVERY_NEEDED) {
    -		xlog_recover_process_efis(log);
    -		/*
    -		 * Sync the log to get all the EFIs out of the AIL.
    -		 * This isn't absolutely necessary, but it helps in
    -		 * case the unlink transactions would have problems
    -		 * pushing the EFIs out of the way.
    -		 */
    -		xfs_log_force(log->l_mp, (xfs_lsn_t)0,
    -			      (XFS_LOG_FORCE | XFS_LOG_SYNC));
    -
    -		if ( (mfsi_flags & XFS_MFSI_NOUNLINK) == 0 ) {
    -			xlog_recover_process_iunlinks(log);
    -		}
    -
    -		xlog_recover_check_summary(log);
    -
    -		cmn_err(CE_NOTE,
    -			"Ending XFS recovery on filesystem: %s (logdev: %s)",
    -			log->l_mp->m_fsname, log->l_mp->m_logname ?
    -			log->l_mp->m_logname : "internal");
    -		log->l_flags &= ~XLOG_RECOVERY_NEEDED;
    -	} else {
    -		cmn_err(CE_DEBUG,
    -			"!Ending clean XFS mount for filesystem: %s",
    -			log->l_mp->m_fsname);
    -	}
    -	return 0;
    -}
    -
    -
    -#if defined(DEBUG)
    -/*
    - * Read all of the agf and agi counters and check that they
    - * are consistent with the superblock counters.
    - */
    -void
    -xlog_recover_check_summary(
    -	xlog_t		*log)
    -{
    -	xfs_mount_t	*mp;
    -	xfs_agf_t	*agfp;
    -	xfs_agi_t	*agip;
    -	xfs_buf_t	*agfbp;
    -	xfs_buf_t	*agibp;
    -	xfs_daddr_t	agfdaddr;
    -	xfs_daddr_t	agidaddr;
    -	xfs_buf_t	*sbbp;
    -#ifdef XFS_LOUD_RECOVERY
    -	xfs_sb_t	*sbp;
    -#endif
    -	xfs_agnumber_t	agno;
    -	__uint64_t	freeblks;
    -	__uint64_t	itotal;
    -	__uint64_t	ifree;
    -
    -	mp = log->l_mp;
    -
    -	freeblks = 0LL;
    -	itotal = 0LL;
    -	ifree = 0LL;
    -	for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
    -		agfdaddr = XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp));
    -		agfbp = xfs_buf_read(mp->m_ddev_targp, agfdaddr,
    -				XFS_FSS_TO_BB(mp, 1), 0);
    -		if (XFS_BUF_ISERROR(agfbp)) {
    -			xfs_ioerror_alert("xlog_recover_check_summary(agf)",
    -						mp, agfbp, agfdaddr);
    -		}
    -		agfp = XFS_BUF_TO_AGF(agfbp);
    -		ASSERT(XFS_AGF_MAGIC == be32_to_cpu(agfp->agf_magicnum));
    -		ASSERT(XFS_AGF_GOOD_VERSION(be32_to_cpu(agfp->agf_versionnum)));
    -		ASSERT(be32_to_cpu(agfp->agf_seqno) == agno);
    -
    -		freeblks += be32_to_cpu(agfp->agf_freeblks) +
    -			    be32_to_cpu(agfp->agf_flcount);
    -		xfs_buf_relse(agfbp);
    -
    -		agidaddr = XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp));
    -		agibp = xfs_buf_read(mp->m_ddev_targp, agidaddr,
    -				XFS_FSS_TO_BB(mp, 1), 0);
    -		if (XFS_BUF_ISERROR(agibp)) {
    -			xfs_ioerror_alert("xlog_recover_check_summary(agi)",
    -					  mp, agibp, agidaddr);
    -		}
    -		agip = XFS_BUF_TO_AGI(agibp);
    -		ASSERT(XFS_AGI_MAGIC == be32_to_cpu(agip->agi_magicnum));
    -		ASSERT(XFS_AGI_GOOD_VERSION(be32_to_cpu(agip->agi_versionnum)));
    -		ASSERT(be32_to_cpu(agip->agi_seqno) == agno);
    -
    -		itotal += be32_to_cpu(agip->agi_count);
    -		ifree += be32_to_cpu(agip->agi_freecount);
    -		xfs_buf_relse(agibp);
    -	}
    -
    -	sbbp = xfs_getsb(mp, 0);
    -#ifdef XFS_LOUD_RECOVERY
    -	sbp = &mp->m_sb;
    -	xfs_xlatesb(XFS_BUF_TO_SBP(sbbp), sbp, 1, XFS_SB_ALL_BITS);
    -	cmn_err(CE_NOTE,
    -		"xlog_recover_check_summary: sb_icount %Lu itotal %Lu",
    -		sbp->sb_icount, itotal);
    -	cmn_err(CE_NOTE,
    -		"xlog_recover_check_summary: sb_ifree %Lu itotal %Lu",
    -		sbp->sb_ifree, ifree);
    -	cmn_err(CE_NOTE,
    -		"xlog_recover_check_summary: sb_fdblocks %Lu freeblks %Lu",
    -		sbp->sb_fdblocks, freeblks);
    -#if 0
    -	/*
    -	 * This is turned off until I account for the allocation
    -	 * btree blocks which live in free space.
    -	 */
    -	ASSERT(sbp->sb_icount == itotal);
    -	ASSERT(sbp->sb_ifree == ifree);
    -	ASSERT(sbp->sb_fdblocks == freeblks);
    -#endif
    -#endif
    -	xfs_buf_relse(sbbp);
    -}
    -#endif /* DEBUG */
    diff --git a/sys/gnu/fs/xfs/xfs_log_recover.h b/sys/gnu/fs/xfs/xfs_log_recover.h
    deleted file mode 100644
    index b2254555530..00000000000
    --- a/sys/gnu/fs/xfs/xfs_log_recover.h
    +++ /dev/null
    @@ -1,67 +0,0 @@
    -/*
    - * Copyright (c) 2000,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef	__XFS_LOG_RECOVER_H__
    -#define __XFS_LOG_RECOVER_H__
    -
    -/*
    - * Macros, structures, prototypes for internal log manager use.
    - */
    -
    -#define XLOG_RHASH_BITS  4
    -#define XLOG_RHASH_SIZE	16
    -#define XLOG_RHASH_SHIFT 2
    -#define XLOG_RHASH(tid)	\
    -	((((__uint32_t)tid)>>XLOG_RHASH_SHIFT) & (XLOG_RHASH_SIZE-1))
    -
    -#define XLOG_MAX_REGIONS_IN_ITEM   (XFS_MAX_BLOCKSIZE / XFS_BLI_CHUNK / 2 + 1)
    -
    -
    -/*
    - * item headers are in ri_buf[0].  Additional buffers follow.
    - */
    -typedef struct xlog_recover_item {
    -	struct xlog_recover_item *ri_next;
    -	struct xlog_recover_item *ri_prev;
    -	int			 ri_type;
    -	int			 ri_cnt;	/* count of regions found */
    -	int			 ri_total;	/* total regions */
    -	xfs_log_iovec_t		 *ri_buf;	/* ptr to regions buffer */
    -} xlog_recover_item_t;
    -
    -struct xlog_tid;
    -typedef struct xlog_recover {
    -	struct xlog_recover *r_next;
    -	xlog_tid_t	    r_log_tid;		/* log's transaction id */
    -	xfs_trans_header_t  r_theader;		/* trans header for partial */
    -	int		    r_state;		/* not needed */
    -	xfs_lsn_t	    r_lsn;		/* xact lsn */
    -	xlog_recover_item_t *r_itemq;		/* q for items */
    -} xlog_recover_t;
    -
    -#define ITEM_TYPE(i)	(*(ushort *)(i)->ri_buf[0].i_addr)
    -
    -/*
    - * This is the number of entries in the l_buf_cancel_table used during
    - * recovery.
    - */
    -#define	XLOG_BC_TABLE_SIZE	64
    -
    -#define	XLOG_RECOVER_PASS1	1
    -#define	XLOG_RECOVER_PASS2	2
    -
    -#endif	/* __XFS_LOG_RECOVER_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_mac.c b/sys/gnu/fs/xfs/xfs_mac.c
    deleted file mode 100644
    index a31a5240ac6..00000000000
    --- a/sys/gnu/fs/xfs/xfs_mac.c
    +++ /dev/null
    @@ -1,72 +0,0 @@
    -/*
    - * Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or modify it
    - * under the terms of version 2 of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful, but
    - * WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    - *
    - * Further, this software is distributed without any warranty that it is
    - * free of the rightful claim of any third person regarding infringement
    - * or the like.  Any license provided herein, whether implied or
    - * otherwise, applies only to this software file.  Patent licenses, if
    - * any, provided herein do not apply to combinations of this program with
    - * other software, or any other product whatsoever.
    - *
    - * You should have received a copy of the GNU General Public License along
    - * with this program; if not, write the Free Software Foundation, Inc., 59
    - * Temple Place - Suite 330, Boston MA 02111-1307, USA.
    - *
    - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
    - * Mountain View, CA  94043, or:
    - *
    - * http://www.sgi.com
    - *
    - * For further information regarding this notice, see:
    - *
    - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
    - */
    -
    -#include "xfs.h"
    -
    -static xfs_mac_label_t *mac_low_high_lp;
    -static xfs_mac_label_t *mac_high_low_lp;
    -static xfs_mac_label_t *mac_admin_high_lp;
    -static xfs_mac_label_t *mac_equal_equal_lp;
    -
    -/*
    - * Test for the existence of a MAC label as efficiently as possible.
    - */
    -int
    -xfs_mac_vhaslabel(
    -	xfs_vnode_t	*vp)
    -{
    -	int		error;
    -	int		len = sizeof(xfs_mac_label_t);
    -	int		flags = ATTR_KERNOVAL|ATTR_ROOT;
    -
    -	XVOP_ATTR_GET(vp, SGI_MAC_FILE, NULL, &len, flags, sys_cred, error);
    -	return (error == 0);
    -}
    -
    -int
    -xfs_mac_iaccess(xfs_inode_t *ip, mode_t mode, struct cred *cr)
    -{
    -	xfs_mac_label_t mac;
    -	xfs_mac_label_t *mp = mac_high_low_lp;
    -
    -	if (cr == NULL || sys_cred == NULL ) {
    -		return EACCES;
    -	}
    -
    -	if (xfs_attr_fetch(ip, SGI_MAC_FILE, (char *)&mac, sizeof(mac)) == 0) {
    -		if ((mp = mac_add_label(&mac)) == NULL) {
    -			return mac_access(mac_high_low_lp, cr, mode);
    -		}
    -	}
    -
    -	return mac_access(mp, cr, mode);
    -}
    diff --git a/sys/gnu/fs/xfs/xfs_mac.h b/sys/gnu/fs/xfs/xfs_mac.h
    deleted file mode 100644
    index 18e0e98e03d..00000000000
    --- a/sys/gnu/fs/xfs/xfs_mac.h
    +++ /dev/null
    @@ -1,106 +0,0 @@
    -/*
    - * Copyright (c) 2001-2002,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_MAC_H__
    -#define __XFS_MAC_H__
    -
    -/*
    - * Mandatory Access Control
    - *
    - * Layout of a composite MAC label:
    - * ml_list contains the list of categories (MSEN) followed by the list of
    - * divisions (MINT). This is actually a header for the data structure which
    - * will have an ml_list with more than one element.
    - *
    - *      -------------------------------
    - *      | ml_msen_type | ml_mint_type |
    - *      -------------------------------
    - *      | ml_level     | ml_grade     |
    - *      -------------------------------
    - *      | ml_catcount                 |
    - *      -------------------------------
    - *      | ml_divcount                 |
    - *      -------------------------------
    - *      | category 1                  |
    - *      | . . .                       |
    - *      | category N                  | (where N = ml_catcount)
    - *      -------------------------------
    - *      | division 1                  |
    - *      | . . .                       |
    - *      | division M                  | (where M = ml_divcount)
    - *      -------------------------------
    - */
    -#define XFS_MAC_MAX_SETS	250
    -typedef struct xfs_mac_label {
    -	__uint8_t	ml_msen_type;	/* MSEN label type */
    -	__uint8_t	ml_mint_type;	/* MINT label type */
    -	__uint8_t	ml_level;	/* Hierarchical level */
    -	__uint8_t	ml_grade;	/* Hierarchical grade */
    -	__uint16_t	ml_catcount;	/* Category count */
    -	__uint16_t	ml_divcount;	/* Division count */
    -					/* Category set, then Division set */
    -	__uint16_t	ml_list[XFS_MAC_MAX_SETS];
    -} xfs_mac_label_t;
    -
    -/* MSEN label type names. Choose an upper case ASCII character.  */
    -#define XFS_MSEN_ADMIN_LABEL	'A'	/* Admin: lowm_flags |= XFS_MOUNT_NO_PERCPU_SB;
    -	}
    -
    -	AIL_LOCKINIT(&mp->m_ail_lock, "xfs_ail");
    -	spinlock_init(&mp->m_sb_lock, "xfs_sb");
    -	/* FreeBSD specfic */
    -	sx_init(&mp->m_ilock, "xfs_mnt");
    -	initnsema(&mp->m_growlock, 1, "xfs_grow");
    -	/*
    -	 * Initialize the AIL.
    -	 */
    -	xfs_trans_ail_init(mp);
    -
    -	atomic_set(&mp->m_active_trans, 0);
    -
    -	return mp;
    -}
    -
    -/*
    - * Free up the resources associated with a mount structure.  Assume that
    - * the structure was initially zeroed, so we can tell which fields got
    - * initialized.
    - */
    -void
    -xfs_mount_free(
    -	xfs_mount_t	*mp,
    -	int		remove_bhv)
    -{
    -	if (mp->m_ihash)
    -		xfs_ihash_free(mp);
    -	if (mp->m_chash)
    -		xfs_chash_free(mp);
    -
    -	if (mp->m_perag) {
    -		int	agno;
    -
    -		for (agno = 0; agno < mp->m_maxagi; agno++)
    -			if (mp->m_perag[agno].pagb_list)
    -				kmem_free(mp->m_perag[agno].pagb_list,
    -						sizeof(xfs_perag_busy_t) *
    -							XFS_PAGB_NUM_SLOTS);
    -		kmem_free(mp->m_perag,
    -			  sizeof(xfs_perag_t) * mp->m_sb.sb_agcount);
    -	}
    -
    -	AIL_LOCK_DESTROY(&mp->m_ail_lock);
    -	spinlock_destroy(&mp->m_sb_lock);
    -	/* FreeBSD specfic */
    -	sx_destroy(&mp->m_ilock);
    -	freesema(&mp->m_growlock);
    -	if (mp->m_quotainfo)
    -		XFS_QM_DONE(mp);
    -
    -	if (mp->m_fsname != NULL)
    -		kmem_free(mp->m_fsname, mp->m_fsname_len);
    -	if (mp->m_rtname != NULL)
    -		kmem_free(mp->m_rtname, strlen(mp->m_rtname) + 1);
    -	if (mp->m_logname != NULL)
    -		kmem_free(mp->m_logname, strlen(mp->m_logname) + 1);
    -
    -	if (remove_bhv) {
    -		xfs_vfs_t	*vfsp = XFS_MTOVFS(mp);
    -
    -		bhv_remove_all_vfsops(vfsp, 0);
    -		VFS_REMOVEBHV(vfsp, &mp->m_bhv);
    -	}
    -
    -	xfs_icsb_destroy_counters(mp);
    -	kmem_free(mp, sizeof(xfs_mount_t));
    -}
    -
    -
    -/*
    - * Check the validity of the SB found.
    - */
    -STATIC int
    -xfs_mount_validate_sb(
    -	xfs_mount_t	*mp,
    -	xfs_sb_t	*sbp,
    -	int		flags)
    -{
    -	/*
    -	 * If the log device and data device have the
    -	 * same device number, the log is internal.
    -	 * Consequently, the sb_logstart should be non-zero.  If
    -	 * we have a zero sb_logstart in this case, we may be trying to mount
    -	 * a volume filesystem in a non-volume manner.
    -	 */
    -	if (sbp->sb_magicnum != XFS_SB_MAGIC) {
    -		xfs_fs_mount_cmn_err(flags, "bad magic number");
    -		return XFS_ERROR(EWRONGFS);
    -	}
    -
    -	if (!XFS_SB_GOOD_VERSION(sbp)) {
    -		xfs_fs_mount_cmn_err(flags, "bad version");
    -		return XFS_ERROR(EWRONGFS);
    -	}
    -
    -	if (unlikely(
    -	    sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) {
    -		xfs_fs_mount_cmn_err(flags,
    -			"filesystem is marked as having an external log; "
    -			"specify logdev on the\nmount command line.");
    -		return XFS_ERROR(EINVAL);
    -	}
    -
    -	if (unlikely(
    -	    sbp->sb_logstart != 0 && mp->m_logdev_targp != mp->m_ddev_targp)) {
    -		xfs_fs_mount_cmn_err(flags,
    -			"filesystem is marked as having an internal log; "
    -			"do not specify logdev on\nthe mount command line.");
    -		return XFS_ERROR(EINVAL);
    -	}
    -
    -	/*
    -	 * More sanity checking. These were stolen directly from
    -	 * xfs_repair.
    -	 */
    -	if (unlikely(
    -	    sbp->sb_agcount <= 0					||
    -	    sbp->sb_sectsize < XFS_MIN_SECTORSIZE			||
    -	    sbp->sb_sectsize > XFS_MAX_SECTORSIZE			||
    -	    sbp->sb_sectlog < XFS_MIN_SECTORSIZE_LOG			||
    -	    sbp->sb_sectlog > XFS_MAX_SECTORSIZE_LOG			||
    -	    sbp->sb_blocksize < XFS_MIN_BLOCKSIZE			||
    -	    sbp->sb_blocksize > XFS_MAX_BLOCKSIZE			||
    -	    sbp->sb_blocklog < XFS_MIN_BLOCKSIZE_LOG			||
    -	    sbp->sb_blocklog > XFS_MAX_BLOCKSIZE_LOG			||
    -	    sbp->sb_inodesize < XFS_DINODE_MIN_SIZE			||
    -	    sbp->sb_inodesize > XFS_DINODE_MAX_SIZE			||
    -	    sbp->sb_inodelog < XFS_DINODE_MIN_LOG			||
    -	    sbp->sb_inodelog > XFS_DINODE_MAX_LOG			||
    -	    (sbp->sb_blocklog - sbp->sb_inodelog != sbp->sb_inopblog)	||
    -	    (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE)	||
    -	    (sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE)	||
    -	    (sbp->sb_imax_pct > 100 /* zero sb_imax_pct is valid */))) {
    -		xfs_fs_mount_cmn_err(flags, "SB sanity check 1 failed");
    -		return XFS_ERROR(EFSCORRUPTED);
    -	}
    -
    -	/*
    -	 * Sanity check AG count, size fields against data size field
    -	 */
    -	if (unlikely(
    -	    sbp->sb_dblocks == 0 ||
    -	    sbp->sb_dblocks >
    -	     (xfs_drfsbno_t)sbp->sb_agcount * sbp->sb_agblocks ||
    -	    sbp->sb_dblocks < (xfs_drfsbno_t)(sbp->sb_agcount - 1) *
    -			      sbp->sb_agblocks + XFS_MIN_AG_BLOCKS)) {
    -		xfs_fs_mount_cmn_err(flags, "SB sanity check 2 failed");
    -		return XFS_ERROR(EFSCORRUPTED);
    -	}
    -
    -	ASSERT(PAGE_SHIFT >= sbp->sb_blocklog);
    -	ASSERT(sbp->sb_blocklog >= BBSHIFT);
    -
    -#if XFS_BIG_BLKNOS     /* Limited by ULONG_MAX of page cache index */
    -	if (unlikely(
    -	    (sbp->sb_dblocks >> (PAGE_SHIFT - sbp->sb_blocklog)) > ULONG_MAX ||
    -	    (sbp->sb_rblocks >> (PAGE_SHIFT - sbp->sb_blocklog)) > ULONG_MAX)) {
    -#else                  /* Limited by UINT_MAX of sectors */
    -	if (unlikely(
    -	    (sbp->sb_dblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX ||
    -	    (sbp->sb_rblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX)) {
    -#endif
    -		xfs_fs_mount_cmn_err(flags,
    -			"file system too large to be mounted on this system.");
    -		return XFS_ERROR(E2BIG);
    -	}
    -
    -	if (unlikely(sbp->sb_inprogress)) {
    -		xfs_fs_mount_cmn_err(flags, "file system busy");
    -		return XFS_ERROR(EFSCORRUPTED);
    -	}
    -
    -	/*
    -	 * Version 1 directory format has never worked on Linux.
    -	 */
    -	if (unlikely(!XFS_SB_VERSION_HASDIRV2(sbp))) {
    -		xfs_fs_mount_cmn_err(flags,
    -			"file system using version 1 directory format");
    -		return XFS_ERROR(ENOSYS);
    -	}
    -
    -	/*
    -	 * Until this is fixed only page-sized or smaller data blocks work.
    -	 */
    -	if (unlikely(sbp->sb_blocksize > PAGE_SIZE)) {
    -		xfs_fs_mount_cmn_err(flags,
    -			"file system with blocksize %d bytes",
    -			sbp->sb_blocksize);
    -		xfs_fs_mount_cmn_err(flags,
    -			"only pagesize (%ld) or less will currently work.",
    -			PAGE_SIZE);
    -		return XFS_ERROR(ENOSYS);
    -	}
    -
    -	return 0;
    -}
    -
    -xfs_agnumber_t
    -xfs_initialize_perag(
    -	struct xfs_vfs	*vfs,
    -	xfs_mount_t	*mp,
    -	xfs_agnumber_t	agcount)
    -{
    -	xfs_agnumber_t	index, max_metadata;
    -	xfs_perag_t	*pag;
    -	xfs_agino_t	agino;
    -	xfs_ino_t	ino;
    -	xfs_sb_t	*sbp = &mp->m_sb;
    -	xfs_ino_t	max_inum = XFS_MAXINUMBER_32;
    -
    -	/* Check to see if the filesystem can overflow 32 bit inodes */
    -	agino = XFS_OFFBNO_TO_AGINO(mp, sbp->sb_agblocks - 1, 0);
    -	ino = XFS_AGINO_TO_INO(mp, agcount - 1, agino);
    -
    -	/* Clear the mount flag if no inode can overflow 32 bits
    -	 * on this filesystem, or if specifically requested..
    -	 */
    -	if ((vfs->vfs_flag & VFS_32BITINODES) && ino > max_inum) {
    -		mp->m_flags |= XFS_MOUNT_32BITINODES;
    -	} else {
    -		mp->m_flags &= ~XFS_MOUNT_32BITINODES;
    -	}
    -
    -	/* If we can overflow then setup the ag headers accordingly */
    -	if (mp->m_flags & XFS_MOUNT_32BITINODES) {
    -		/* Calculate how much should be reserved for inodes to
    -		 * meet the max inode percentage.
    -		 */
    -		if (mp->m_maxicount) {
    -			__uint64_t	icount;
    -
    -			icount = sbp->sb_dblocks * sbp->sb_imax_pct;
    -			do_div(icount, 100);
    -			icount += sbp->sb_agblocks - 1;
    -			do_div(icount, sbp->sb_agblocks);
    -			max_metadata = icount;
    -		} else {
    -			max_metadata = agcount;
    -		}
    -		for (index = 0; index < agcount; index++) {
    -			ino = XFS_AGINO_TO_INO(mp, index, agino);
    -			if (ino > max_inum) {
    -				index++;
    -				break;
    -			}
    -
    -			/* This ag is preferred for inodes */
    -			pag = &mp->m_perag[index];
    -			pag->pagi_inodeok = 1;
    -			if (index < max_metadata)
    -				pag->pagf_metadata = 1;
    -		}
    -	} else {
    -		/* Setup default behavior for smaller filesystems */
    -		for (index = 0; index < agcount; index++) {
    -			pag = &mp->m_perag[index];
    -			pag->pagi_inodeok = 1;
    -		}
    -	}
    -	return index;
    -}
    -
    -/*
    - * xfs_xlatesb
    - *
    - *     data       - on disk version of sb
    - *     sb         - a superblock
    - *     dir        - conversion direction: <0 - convert sb to buf
    - *                                        >0 - convert buf to sb
    - *     fields     - which fields to copy (bitmask)
    - */
    -void
    -xfs_xlatesb(
    -	void		*data,
    -	xfs_sb_t	*sb,
    -	int		dir,
    -	__int64_t	fields)
    -{
    -	xfs_caddr_t	buf_ptr;
    -	xfs_caddr_t	mem_ptr;
    -	xfs_sb_field_t	f;
    -	int		first;
    -	int		size;
    -
    -	ASSERT(dir);
    -	ASSERT(fields);
    -
    -	if (!fields)
    -		return;
    -
    -	buf_ptr = (xfs_caddr_t)data;
    -	mem_ptr = (xfs_caddr_t)sb;
    -
    -	while (fields) {
    -		f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields);
    -		first = xfs_sb_info[f].offset;
    -		size = xfs_sb_info[f + 1].offset - first;
    -
    -		ASSERT(xfs_sb_info[f].type == 0 || xfs_sb_info[f].type == 1);
    -
    -		if (size == 1 || xfs_sb_info[f].type == 1) {
    -			if (dir > 0) {
    -				memcpy(mem_ptr + first, buf_ptr + first, size);
    -			} else {
    -				memcpy(buf_ptr + first, mem_ptr + first, size);
    -			}
    -		} else {
    -			switch (size) {
    -			case 2:
    -				INT_XLATE(*(__uint16_t*)(buf_ptr+first),
    -					  *(__uint16_t*)(mem_ptr+first),
    -					  dir, ARCH_CONVERT);
    -				break;
    -			case 4:
    -				INT_XLATE(*(__uint32_t*)(buf_ptr+first),
    -					  *(__uint32_t*)(mem_ptr+first),
    -					  dir, ARCH_CONVERT);
    -				break;
    -			case 8:
    -				INT_XLATE(*(__uint64_t*)(buf_ptr+first),
    -					  *(__uint64_t*)(mem_ptr+first), dir, ARCH_CONVERT);
    -				break;
    -			default:
    -				ASSERT(0);
    -			}
    -		}
    -
    -		fields &= ~(1LL << f);
    -	}
    -}
    -
    -/*
    - * xfs_readsb
    - *
    - * Does the initial read of the superblock.
    - */
    -int
    -xfs_readsb(xfs_mount_t *mp, int flags)
    -{
    -	unsigned int	sector_size;
    -	unsigned int	extra_flags;
    -	xfs_buf_t	*bp;
    -	xfs_sb_t	*sbp;
    -	int		error;
    -
    -	ASSERT(mp->m_sb_bp == NULL);
    -	ASSERT(mp->m_ddev_targp != NULL);
    -
    -	/*
    -	 * Allocate a (locked) buffer to hold the superblock.
    -	 * This will be kept around at all times to optimize
    -	 * access to the superblock.
    -	 */
    -	sector_size = xfs_getsize_buftarg(mp->m_ddev_targp);
    -        extra_flags = XFS_BUF_LOCK | XFS_BUF_MANAGE | XFS_BUF_MAPPED;
    -
    -	bp = xfs_getsb(mp,0);
    -
    -	if (!bp || XFS_BUF_ISERROR(bp)) {
    -		xfs_fs_mount_cmn_err(flags, "SB read failed");
    -		error = bp ? XFS_BUF_GETERROR(bp) : ENOMEM;
    -		goto fail;
    -	}
    -	ASSERT(XFS_BUF_ISBUSY(bp));
    -	ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);
    -
    -	/*
    -	 * Initialize the mount structure from the superblock.
    -	 * But first do some basic consistency checking.
    -	 */
    -	sbp = XFS_BUF_TO_SBP(bp);
    -	xfs_xlatesb(XFS_BUF_PTR(bp), &(mp->m_sb), 1, XFS_SB_ALL_BITS);
    -
    -	error = xfs_mount_validate_sb(mp, &(mp->m_sb), flags);
    -	if (error) {
    -		xfs_fs_mount_cmn_err(flags, "SB validate failed");
    -		goto fail;
    -	}
    -
    -	/*
    -	 * We must be able to do sector-sized and sector-aligned IO.
    -	 */
    -	if (sector_size > mp->m_sb.sb_sectsize) {
    -		xfs_fs_mount_cmn_err(flags,
    -			"device supports only %u byte sectors (not %u)",
    -			sector_size, mp->m_sb.sb_sectsize);
    -		error = ENOSYS;
    -		goto fail;
    -	}
    -
    -	/*
    -	 * If device sector size is smaller than the superblock size,
    -	 * re-read the superblock so the buffer is correctly sized.
    -	 */
    -	if (sector_size < mp->m_sb.sb_sectsize) {
    -		XFS_BUF_UNMANAGE(bp);
    -		xfs_buf_relse(bp);
    -		sector_size = mp->m_sb.sb_sectsize;
    -		bp = xfs_buf_read_flags(mp->m_ddev_targp, XFS_SB_DADDR,
    -					BTOBB(sector_size), extra_flags);
    -		if (!bp || XFS_BUF_ISERROR(bp)) {
    -			xfs_fs_mount_cmn_err(flags, "SB re-read failed");
    -			error = bp ? XFS_BUF_GETERROR(bp) : ENOMEM;
    -			goto fail;
    -		}
    -		ASSERT(XFS_BUF_ISBUSY(bp));
    -		ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);
    -	}
    -
    -	xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0);
    -	xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0);
    -	xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
    -
    -	mp->m_sb_bp = bp;
    -	xfs_buf_relse(bp);
    -	ASSERT(XFS_BUF_VALUSEMA(bp) > 0);
    -	return 0;
    -
    - fail:
    -	if (bp) {
    -		XFS_BUF_UNMANAGE(bp);
    -		xfs_buf_relse(bp);
    -	}
    -	return error;
    -}
    -
    -
    -/*
    - * xfs_mount_common
    - *
    - * Mount initialization code establishing various mount
    - * fields from the superblock associated with the given
    - * mount structure
    - */
    -STATIC void
    -xfs_mount_common(xfs_mount_t *mp, xfs_sb_t *sbp)
    -{
    -	int	i;
    -
    -	mp->m_agfrotor = mp->m_agirotor = 0;
    -	spinlock_init(&mp->m_agirotor_lock, "m_agirotor_lock");
    -	mp->m_maxagi = mp->m_sb.sb_agcount;
    -	mp->m_blkbit_log = sbp->sb_blocklog + XFS_NBBYLOG;
    -	mp->m_blkbb_log = sbp->sb_blocklog - BBSHIFT;
    -	mp->m_sectbb_log = sbp->sb_sectlog - BBSHIFT;
    -	mp->m_agno_log = xfs_highbit32(sbp->sb_agcount - 1) + 1;
    -	mp->m_agino_log = sbp->sb_inopblog + sbp->sb_agblklog;
    -	mp->m_litino = sbp->sb_inodesize -
    -		((uint)sizeof(xfs_dinode_core_t) + (uint)sizeof(xfs_agino_t));
    -	mp->m_blockmask = sbp->sb_blocksize - 1;
    -	mp->m_blockwsize = sbp->sb_blocksize >> XFS_WORDLOG;
    -	mp->m_blockwmask = mp->m_blockwsize - 1;
    -#ifdef RMC
    -	INIT_LIST_HEAD(&mp->m_del_inodes);
    -#endif
    -	TAILQ_INIT(&mp->m_del_inodes);
    -
    -	/*
    -	 * Setup for attributes, in case they get created.
    -	 * This value is for inodes getting attributes for the first time,
    -	 * the per-inode value is for old attribute values.
    -	 */
    -	ASSERT(sbp->sb_inodesize >= 256 && sbp->sb_inodesize <= 2048);
    -	switch (sbp->sb_inodesize) {
    -	case 256:
    -		mp->m_attroffset = XFS_LITINO(mp) -
    -				   XFS_BMDR_SPACE_CALC(MINABTPTRS);
    -		break;
    -	case 512:
    -	case 1024:
    -	case 2048:
    -		mp->m_attroffset = XFS_BMDR_SPACE_CALC(6 * MINABTPTRS);
    -		break;
    -	default:
    -		ASSERT(0);
    -	}
    -	ASSERT(mp->m_attroffset < XFS_LITINO(mp));
    -
    -	for (i = 0; i < 2; i++) {
    -		mp->m_alloc_mxr[i] = XFS_BTREE_BLOCK_MAXRECS(sbp->sb_blocksize,
    -			xfs_alloc, i == 0);
    -		mp->m_alloc_mnr[i] = XFS_BTREE_BLOCK_MINRECS(sbp->sb_blocksize,
    -			xfs_alloc, i == 0);
    -	}
    -	for (i = 0; i < 2; i++) {
    -		mp->m_bmap_dmxr[i] = XFS_BTREE_BLOCK_MAXRECS(sbp->sb_blocksize,
    -			xfs_bmbt, i == 0);
    -		mp->m_bmap_dmnr[i] = XFS_BTREE_BLOCK_MINRECS(sbp->sb_blocksize,
    -			xfs_bmbt, i == 0);
    -	}
    -	for (i = 0; i < 2; i++) {
    -		mp->m_inobt_mxr[i] = XFS_BTREE_BLOCK_MAXRECS(sbp->sb_blocksize,
    -			xfs_inobt, i == 0);
    -		mp->m_inobt_mnr[i] = XFS_BTREE_BLOCK_MINRECS(sbp->sb_blocksize,
    -			xfs_inobt, i == 0);
    -	}
    -
    -	mp->m_bsize = XFS_FSB_TO_BB(mp, 1);
    -	mp->m_ialloc_inos = (int)MAX((__uint16_t)XFS_INODES_PER_CHUNK,
    -					sbp->sb_inopblock);
    -	mp->m_ialloc_blks = mp->m_ialloc_inos >> sbp->sb_inopblog;
    -}
    -/*
    - * xfs_mountfs
    - *
    - * This function does the following on an initial mount of a file system:
    - *	- reads the superblock from disk and init the mount struct
    - *	- if we're a 32-bit kernel, do a size check on the superblock
    - *		so we don't mount terabyte filesystems
    - *	- init mount struct realtime fields
    - *	- allocate inode hash table for fs
    - *	- init directory manager
    - *	- perform recovery and init the log manager
    - */
    -int
    -xfs_mountfs(
    -	xfs_vfs_t	*vfsp,
    -	xfs_mount_t	*mp,
    -	int		mfsi_flags)
    -{
    -	xfs_buf_t	*bp;
    -	xfs_sb_t	*sbp = &(mp->m_sb);
    -	xfs_inode_t	*rip;
    -	xfs_vnode_t	*rvp = NULL;
    -	int		readio_log, writeio_log;
    -	xfs_daddr_t	d;
    -	__uint64_t	ret64;
    -	__int64_t	update_flags;
    -	uint		quotamount, quotaflags;
    -	int		agno;
    -	int		uuid_mounted = 0;
    -	int		error = 0;
    -
    -	if (mp->m_sb_bp == NULL) {
    -		if ((error = xfs_readsb(mp, mfsi_flags))) {
    -			return error;
    -		}
    -	}
    -	xfs_mount_common(mp, sbp);
    -
    -	/*
    -	 * Check if sb_agblocks is aligned at stripe boundary
    -	 * If sb_agblocks is NOT aligned turn off m_dalign since
    -	 * allocator alignment is within an ag, therefore ag has
    -	 * to be aligned at stripe boundary.
    -	 */
    -	update_flags = 0LL;
    -	if (mp->m_dalign && !(mfsi_flags & XFS_MFSI_SECOND)) {
    -		/*
    -		 * If stripe unit and stripe width are not multiples
    -		 * of the fs blocksize turn off alignment.
    -		 */
    -		if ((BBTOB(mp->m_dalign) & mp->m_blockmask) ||
    -		    (BBTOB(mp->m_swidth) & mp->m_blockmask)) {
    -			if (mp->m_flags & XFS_MOUNT_RETERR) {
    -				cmn_err(CE_WARN,
    -					"XFS: alignment check 1 failed");
    -				error = XFS_ERROR(EINVAL);
    -				goto error1;
    -			}
    -			mp->m_dalign = mp->m_swidth = 0;
    -		} else {
    -			/*
    -			 * Convert the stripe unit and width to FSBs.
    -			 */
    -			mp->m_dalign = XFS_BB_TO_FSBT(mp, mp->m_dalign);
    -			if (mp->m_dalign && (sbp->sb_agblocks % mp->m_dalign)) {
    -				if (mp->m_flags & XFS_MOUNT_RETERR) {
    -					error = XFS_ERROR(EINVAL);
    -					goto error1;
    -				}
    -				xfs_fs_cmn_err(CE_WARN, mp,
    -"stripe alignment turned off: sunit(%d)/swidth(%d) incompatible with agsize(%d)",
    -					mp->m_dalign, mp->m_swidth,
    -					sbp->sb_agblocks);
    -
    -				mp->m_dalign = 0;
    -				mp->m_swidth = 0;
    -			} else if (mp->m_dalign) {
    -				mp->m_swidth = XFS_BB_TO_FSBT(mp, mp->m_swidth);
    -			} else {
    -				if (mp->m_flags & XFS_MOUNT_RETERR) {
    -					xfs_fs_cmn_err(CE_WARN, mp,
    -"stripe alignment turned off: sunit(%d) less than bsize(%d)",
    -                                        	mp->m_dalign,
    -						mp->m_blockmask +1);
    -					error = XFS_ERROR(EINVAL);
    -					goto error1;
    -				}
    -				mp->m_swidth = 0;
    -			}
    -		}
    -
    -		/*
    -		 * Update superblock with new values
    -		 * and log changes
    -		 */
    -		if (XFS_SB_VERSION_HASDALIGN(sbp)) {
    -			if (sbp->sb_unit != mp->m_dalign) {
    -				sbp->sb_unit = mp->m_dalign;
    -				update_flags |= XFS_SB_UNIT;
    -			}
    -			if (sbp->sb_width != mp->m_swidth) {
    -				sbp->sb_width = mp->m_swidth;
    -				update_flags |= XFS_SB_WIDTH;
    -			}
    -		}
    -	} else if ((mp->m_flags & XFS_MOUNT_NOALIGN) != XFS_MOUNT_NOALIGN &&
    -		    XFS_SB_VERSION_HASDALIGN(&mp->m_sb)) {
    -			mp->m_dalign = sbp->sb_unit;
    -			mp->m_swidth = sbp->sb_width;
    -	}
    -
    -	xfs_alloc_compute_maxlevels(mp);
    -	xfs_bmap_compute_maxlevels(mp, XFS_DATA_FORK);
    -	xfs_bmap_compute_maxlevels(mp, XFS_ATTR_FORK);
    -	xfs_ialloc_compute_maxlevels(mp);
    -
    -	if (sbp->sb_imax_pct) {
    -		__uint64_t	icount;
    -
    -		/* Make sure the maximum inode count is a multiple of the
    -		 * units we allocate inodes in.
    -		 */
    -
    -		icount = sbp->sb_dblocks * sbp->sb_imax_pct;
    -		do_div(icount, 100);
    -		do_div(icount, mp->m_ialloc_blks);
    -		mp->m_maxicount = (icount * mp->m_ialloc_blks)  <<
    -				   sbp->sb_inopblog;
    -	} else
    -		mp->m_maxicount = 0;
    -
    -	mp->m_maxioffset = xfs_max_file_offset(sbp->sb_blocklog);
    -
    -	/*
    -	 * XFS uses the uuid from the superblock as the unique
    -	 * identifier for fsid.  We can not use the uuid from the volume
    -	 * since a single partition filesystem is identical to a single
    -	 * partition volume/filesystem.
    -	 */
    -	if ((mfsi_flags & XFS_MFSI_SECOND) == 0 &&
    -	    (mp->m_flags & XFS_MOUNT_NOUUID) == 0) {
    -		if (xfs_uuid_mount(mp)) {
    -			error = XFS_ERROR(EINVAL);
    -			goto error1;
    -		}
    -		uuid_mounted=1;
    -		ret64 = uuid_hash64(&sbp->sb_uuid);
    -		memcpy(&vfsp->vfs_fsid, &ret64, sizeof(ret64));
    -	}
    -
    -	/*
    -	 * Set the default minimum read and write sizes unless
    -	 * already specified in a mount option.
    -	 * We use smaller I/O sizes when the file system
    -	 * is being used for NFS service (wsync mount option).
    -	 */
    -	if (!(mp->m_flags & XFS_MOUNT_DFLT_IOSIZE)) {
    -		if (mp->m_flags & XFS_MOUNT_WSYNC) {
    -			readio_log = XFS_WSYNC_READIO_LOG;
    -			writeio_log = XFS_WSYNC_WRITEIO_LOG;
    -		} else {
    -			readio_log = XFS_READIO_LOG_LARGE;
    -			writeio_log = XFS_WRITEIO_LOG_LARGE;
    -		}
    -	} else {
    -		readio_log = mp->m_readio_log;
    -		writeio_log = mp->m_writeio_log;
    -	}
    -
    -	/*
    -	 * Set the number of readahead buffers to use based on
    -	 * physical memory size.
    -	 */
    -	if (xfs_physmem <= 4096)		/* <= 16MB */
    -		mp->m_nreadaheads = XFS_RW_NREADAHEAD_16MB;
    -	else if (xfs_physmem <= 8192)	/* <= 32MB */
    -		mp->m_nreadaheads = XFS_RW_NREADAHEAD_32MB;
    -	else
    -		mp->m_nreadaheads = XFS_RW_NREADAHEAD_K32;
    -	if (sbp->sb_blocklog > readio_log) {
    -		mp->m_readio_log = sbp->sb_blocklog;
    -	} else {
    -		mp->m_readio_log = readio_log;
    -	}
    -	mp->m_readio_blocks = 1 << (mp->m_readio_log - sbp->sb_blocklog);
    -	if (sbp->sb_blocklog > writeio_log) {
    -		mp->m_writeio_log = sbp->sb_blocklog;
    -	} else {
    -		mp->m_writeio_log = writeio_log;
    -	}
    -	mp->m_writeio_blocks = 1 << (mp->m_writeio_log - sbp->sb_blocklog);
    -
    -	/*
    -	 * Set the inode cluster size based on the physical memory
    -	 * size.  This may still be overridden by the file system
    -	 * block size if it is larger than the chosen cluster size.
    -	 */
    -	if (xfs_physmem <= btoc(32 * 1024 * 1024)) { /* <= 32 MB */
    -		mp->m_inode_cluster_size = XFS_INODE_SMALL_CLUSTER_SIZE;
    -	} else {
    -		mp->m_inode_cluster_size = XFS_INODE_BIG_CLUSTER_SIZE;
    -	}
    -	/*
    -	 * Set whether we're using inode alignment.
    -	 */
    -	if (XFS_SB_VERSION_HASALIGN(&mp->m_sb) &&
    -	    mp->m_sb.sb_inoalignmt >=
    -	    XFS_B_TO_FSBT(mp, mp->m_inode_cluster_size))
    -		mp->m_inoalign_mask = mp->m_sb.sb_inoalignmt - 1;
    -	else
    -		mp->m_inoalign_mask = 0;
    -	/*
    -	 * If we are using stripe alignment, check whether
    -	 * the stripe unit is a multiple of the inode alignment
    -	 */
    -	if (mp->m_dalign && mp->m_inoalign_mask &&
    -	    !(mp->m_dalign & mp->m_inoalign_mask))
    -		mp->m_sinoalign = mp->m_dalign;
    -	else
    -		mp->m_sinoalign = 0;
    -	/*
    -	 * Check that the data (and log if separate) are an ok size.
    -	 */
    -	d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks);
    -	if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_dblocks) {
    -		cmn_err(CE_WARN, "XFS: size check 1 failed");
    -		error = XFS_ERROR(E2BIG);
    -		goto error1;
    -	}
    -	error = xfs_read_buf(mp, mp->m_ddev_targp,
    -			     d - XFS_FSS_TO_BB(mp, 1),
    -			     XFS_FSS_TO_BB(mp, 1), 0, &bp);
    -	if (!error) {
    -		xfs_buf_relse(bp);
    -	} else {
    -		cmn_err(CE_WARN, "XFS: size check 2 failed");
    -		if (error == ENOSPC) {
    -			error = XFS_ERROR(E2BIG);
    -		}
    -		goto error1;
    -	}
    -
    -	if (((mfsi_flags & XFS_MFSI_CLIENT) == 0) &&
    -	    mp->m_logdev_targp != mp->m_ddev_targp) {
    -		d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks);
    -		if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_logblocks) {
    -			cmn_err(CE_WARN, "XFS: size check 3 failed");
    -			error = XFS_ERROR(E2BIG);
    -			goto error1;
    -		}
    -		error = xfs_read_buf(mp, mp->m_logdev_targp,
    -				     d - XFS_FSB_TO_BB(mp, 1),
    -				     XFS_FSB_TO_BB(mp, 1), 0, &bp);
    -		if (!error) {
    -			xfs_buf_relse(bp);
    -		} else {
    -			cmn_err(CE_WARN, "XFS: size check 3 failed");
    -			if (error == ENOSPC) {
    -				error = XFS_ERROR(E2BIG);
    -			}
    -			goto error1;
    -		}
    -	}
    -
    -	/*
    -	 * Initialize realtime fields in the mount structure
    -	 */
    -	if ((error = xfs_rtmount_init(mp))) {
    -		cmn_err(CE_WARN, "XFS: RT mount failed");
    -		goto error1;
    -	}
    -
    -	/*
    -	 * For client case we are done now
    -	 */
    -	if (mfsi_flags & XFS_MFSI_CLIENT) {
    -		return 0;
    -	}
    -
    -	/*
    -	 *  Copies the low order bits of the timestamp and the randomly
    -	 *  set "sequence" number out of a UUID.
    -	 */
    -	uuid_getnodeuniq(&sbp->sb_uuid, mp->m_fixedfsid);
    -
    -	/*
    -	 *  The vfs structure needs to have a file system independent
    -	 *  way of checking for the invariant file system ID.  Since it
    -	 *  can't look at mount structures it has a pointer to the data
    -	 *  in the mount structure.
    -	 *
    -	 *  File systems that don't support user level file handles (i.e.
    -	 *  all of them except for XFS) will leave vfs_altfsid as NULL.
    -	 */
    -	vfsp->vfs_altfsid = (xfs_fsid_t *)mp->m_fixedfsid;
    -	mp->m_dmevmask = 0;	/* not persistent; set after each mount */
    -
    -	/*
    -	 * Select the right directory manager.
    -	 */
    -	mp->m_dirops =
    -		XFS_SB_VERSION_HASDIRV2(&mp->m_sb) ?
    -			xfsv2_dirops :
    -			xfsv1_dirops;
    -
    -	/*
    -	 * Initialize directory manager's entries.
    -	 */
    -	XFS_DIR_MOUNT(mp);
    -
    -	/*
    -	 * Initialize the attribute manager's entries.
    -	 */
    -	mp->m_attr_magicpct = (mp->m_sb.sb_blocksize * 37) / 100;
    -
    -	/*
    -	 * Initialize the precomputed transaction reservations values.
    -	 */
    -	xfs_trans_init(mp);
    -
    -	/*
    -	 * Allocate and initialize the inode hash table for this
    -	 * file system.
    -	 */
    -	xfs_ihash_init(mp);
    -	xfs_chash_init(mp);
    -
    -	/*
    -	 * Allocate and initialize the per-ag data.
    -	 */
    -	init_rwsem(&mp->m_peraglock);
    -	mp->m_perag =
    -		kmem_zalloc(sbp->sb_agcount * sizeof(xfs_perag_t), KM_SLEEP);
    -
    -	mp->m_maxagi = xfs_initialize_perag(vfsp, mp, sbp->sb_agcount);
    -
    -	/*
    -	 * log's mount-time initialization. Perform 1st part recovery if needed
    -	 */
    -	if (likely(sbp->sb_logblocks > 0)) {	/* check for volume case */
    -		error = xfs_log_mount(mp, mp->m_logdev_targp,
    -				      XFS_FSB_TO_DADDR(mp, sbp->sb_logstart),
    -				      XFS_FSB_TO_BB(mp, sbp->sb_logblocks));
    -		if (error) {
    -			cmn_err(CE_WARN, "XFS: log mount failed");
    -			goto error2;
    -		}
    -	} else {	/* No log has been defined */
    -		cmn_err(CE_WARN, "XFS: no log defined");
    -		XFS_ERROR_REPORT("xfs_mountfs_int(1)", XFS_ERRLEVEL_LOW, mp);
    -		error = XFS_ERROR(EFSCORRUPTED);
    -		goto error2;
    -	}
    -
    -	/*
    -	 * Get and sanity-check the root inode.
    -	 * Save the pointer to it in the mount structure.
    -	 */
    -	error = xfs_iget(mp, NULL, sbp->sb_rootino, 0, XFS_ILOCK_EXCL, &rip, 0);
    -	if (error) {
    -		cmn_err(CE_WARN, "XFS: failed to read root inode");
    -		goto error3;
    -	}
    -
    -	ASSERT(rip != NULL);
    -	rvp = XFS_ITOV(rip);
    -
    -	if (unlikely((rip->i_d.di_mode & S_IFMT) != S_IFDIR)) {
    -		cmn_err(CE_WARN, "XFS: corrupted root inode");
    -		printf("Root inode %p is not a directory: %llu",
    -		       mp->m_ddev_targp, (unsigned long long)rip->i_ino);
    -		xfs_iunlock(rip, XFS_ILOCK_EXCL);
    -		XFS_ERROR_REPORT("xfs_mountfs_int(2)", XFS_ERRLEVEL_LOW,
    -				 mp);
    -		error = XFS_ERROR(EFSCORRUPTED);
    -		goto error4;
    -	}
    -	mp->m_rootip = rip;	/* save it */
    -
    -	xfs_iunlock(rip, XFS_ILOCK_EXCL);
    -
    -	/*
    -	 * Initialize realtime inode pointers in the mount structure
    -	 */
    -	if ((error = xfs_rtmount_inodes(mp))) {
    -		/*
    -		 * Free up the root inode.
    -		 */
    -		cmn_err(CE_WARN, "XFS: failed to read RT inodes");
    -		goto error4;
    -	}
    -
    -	/*
    -	 * If fs is not mounted readonly, then update the superblock
    -	 * unit and width changes.
    -	 */
    -	if (update_flags && !(vfsp->vfs_flag & VFS_RDONLY))
    -		xfs_mount_log_sbunit(mp, update_flags);
    -
    -	/*
    -	 * Initialise the XFS quota management subsystem for this mount
    -	 */
    -	if ((error = XFS_QM_INIT(mp, "amount, "aflags)))
    -		goto error4;
    -
    -	/*
    -	 * Finish recovering the file system.  This part needed to be
    -	 * delayed until after the root and real-time bitmap inodes
    -	 * were consistently read in.
    -	 */
    -	error = xfs_log_mount_finish(mp, mfsi_flags);
    -	if (error) {
    -		cmn_err(CE_WARN, "XFS: log mount finish failed");
    -		goto error4;
    -	}
    -
    -	/*
    -	 * Complete the quota initialisation, post-log-replay component.
    -	 */
    -	if ((error = XFS_QM_MOUNT(mp, quotamount, quotaflags, mfsi_flags)))
    -		goto error4;
    -
    -	return 0;
    -
    - error4:
    -	/*
    -	 * Free up the root inode.
    -	 */
    -	VN_RELE(rvp);
    - error3:
    -	xfs_log_unmount_dealloc(mp);
    - error2:
    -	xfs_ihash_free(mp);
    -	xfs_chash_free(mp);
    -	for (agno = 0; agno < sbp->sb_agcount; agno++)
    -		if (mp->m_perag[agno].pagb_list)
    -			kmem_free(mp->m_perag[agno].pagb_list,
    -			  sizeof(xfs_perag_busy_t) * XFS_PAGB_NUM_SLOTS);
    -	kmem_free(mp->m_perag, sbp->sb_agcount * sizeof(xfs_perag_t));
    -	mp->m_perag = NULL;
    -	/* FALLTHROUGH */
    - error1:
    -	if (uuid_mounted)
    -		xfs_uuid_unmount(mp);
    -	xfs_freesb(mp);
    -	return error;
    -}
    -
    -/*
    - * xfs_unmountfs
    - *
    - * This flushes out the inodes,dquots and the superblock, unmounts the
    - * log and makes sure that incore structures are freed.
    - */
    -int
    -xfs_unmountfs(xfs_mount_t *mp, struct cred *cr)
    -{
    -	struct xfs_vfs	*vfsp = XFS_MTOVFS(mp);
    -#if defined(DEBUG) || defined(INDUCE_IO_ERROR)
    -	int64_t		fsid;
    -#endif
    -
    -	xfs_iflush_all(mp);
    -
    -	XFS_QM_DQPURGEALL(mp, XFS_QMOPT_QUOTALL | XFS_QMOPT_UMOUNTING);
    -
    -	/*
    -	 * Flush out the log synchronously so that we know for sure
    -	 * that nothing is pinned.  This is important because bflush()
    -	 * will skip pinned buffers.
    -	 */
    -	xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE | XFS_LOG_SYNC);
    -
    -	xfs_binval(mp->m_ddev_targp);
    -	if (mp->m_rtdev_targp) {
    -		xfs_binval(mp->m_rtdev_targp);
    -	}
    -
    -	xfs_unmountfs_writesb(mp);
    -
    -	xfs_unmountfs_wait(mp); 		/* wait for async bufs */
    -
    -	xfs_log_unmount(mp);			/* Done! No more fs ops. */
    -
    -	xfs_freesb(mp);
    -
    -	/*
    -	 * All inodes from this mount point should be freed.
    -	 */
    -	//ASSERT(mp->m_inodes == NULL);
    -	if (mp->m_inodes != NULL ) {
    -		printf("WRONG: mp->m_ireclaims: %d\n", mp->m_ireclaims);
    -		printf("WRONG: mp->m_inodes: %p\n", mp->m_inodes);
    -	}
    -
    -	xfs_unmountfs_close(mp, cr);
    -	if ((mp->m_flags & XFS_MOUNT_NOUUID) == 0)
    -		xfs_uuid_unmount(mp);
    -
    -#if defined(DEBUG) || defined(INDUCE_IO_ERROR)
    -	/*
    -	 * clear all error tags on this filesystem
    -	 */
    -	memcpy(&fsid, &vfsp->vfs_fsid, sizeof(int64_t));
    -	xfs_errortag_clearall_umount(fsid, mp->m_fsname, 0);
    -#endif
    -	XFS_IODONE(vfsp);
    -	xfs_mount_free(mp, 1);
    -	return 0;
    -}
    -
    -void
    -xfs_unmountfs_close(xfs_mount_t *mp, struct cred *cr)
    -{
    -	if (mp->m_logdev_targp != mp->m_ddev_targp)
    -		xfs_free_buftarg(mp->m_logdev_targp, 1);
    -	if (mp->m_rtdev_targp)
    -		xfs_free_buftarg(mp->m_rtdev_targp, 1);
    -	xfs_free_buftarg(mp->m_ddev_targp, 0);
    -}
    -
    -STATIC void
    -xfs_unmountfs_wait(xfs_mount_t *mp)
    -{
    -	if (mp->m_logdev_targp != mp->m_ddev_targp)
    -		xfs_wait_buftarg(mp->m_logdev_targp);
    -	if (mp->m_rtdev_targp)
    -		xfs_wait_buftarg(mp->m_rtdev_targp);
    -	xfs_wait_buftarg(mp->m_ddev_targp);
    -}
    -
    -int
    -xfs_unmountfs_writesb(xfs_mount_t *mp)
    -{
    -	xfs_buf_t	*sbp;
    -	xfs_sb_t	*sb;
    -	int		error = 0;
    -
    -	/*
    -	 * skip superblock write if fs is read-only, or
    -	 * if we are doing a forced umount.
    -	 */
    -	sbp = xfs_getsb(mp, 0);
    -	if (!(XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY ||
    -		XFS_FORCED_SHUTDOWN(mp))) {
    -
    -		xfs_icsb_sync_counters(mp);
    -
    -		/*
    -		 * mark shared-readonly if desired
    -		 */
    -		sb = XFS_BUF_TO_SBP(sbp);
    -		if (mp->m_mk_sharedro) {
    -			if (!(sb->sb_flags & XFS_SBF_READONLY))
    -				sb->sb_flags |= XFS_SBF_READONLY;
    -			if (!XFS_SB_VERSION_HASSHARED(sb))
    -				XFS_SB_VERSION_ADDSHARED(sb);
    -			xfs_fs_cmn_err(CE_NOTE, mp,
    -				"Unmounting, marking shared read-only");
    -		}
    -		XFS_BUF_UNDONE(sbp);
    -		XFS_BUF_UNREAD(sbp);
    -		XFS_BUF_UNDELAYWRITE(sbp);
    -		XFS_BUF_WRITE(sbp);
    -		XFS_BUF_UNASYNC(sbp);
    -		ASSERT(XFS_BUF_TARGET(sbp) == mp->m_ddev_targp);
    -		xfsbdstrat(mp, sbp);
    -		/* Nevermind errors we might get here. */
    -		error = xfs_iowait(sbp);
    -		if (error)
    -			xfs_ioerror_alert("xfs_unmountfs_writesb",
    -					  mp, sbp, XFS_BUF_ADDR(sbp));
    -		if (error && mp->m_mk_sharedro)
    -			xfs_fs_cmn_err(CE_ALERT, mp, "Superblock write error detected while unmounting.  Filesystem may not be marked shared readonly");
    -	}
    -	xfs_buf_relse(sbp);
    -	return error;
    -}
    -
    -/*
    - * xfs_mod_sb() can be used to copy arbitrary changes to the
    - * in-core superblock into the superblock buffer to be logged.
    - * It does not provide the higher level of locking that is
    - * needed to protect the in-core superblock from concurrent
    - * access.
    - */
    -void
    -xfs_mod_sb(xfs_trans_t *tp, __int64_t fields)
    -{
    -	xfs_buf_t	*bp;
    -	int		first;
    -	int		last;
    -	xfs_mount_t	*mp;
    -	xfs_sb_t	*sbp;
    -	xfs_sb_field_t	f;
    -
    -	ASSERT(fields);
    -	if (!fields)
    -		return;
    -	mp = tp->t_mountp;
    -	bp = xfs_trans_getsb(tp, mp, 0);
    -	sbp = XFS_BUF_TO_SBP(bp);
    -	first = sizeof(xfs_sb_t);
    -	last = 0;
    -
    -	/* translate/copy */
    -
    -	xfs_xlatesb(XFS_BUF_PTR(bp), &(mp->m_sb), -1, fields);
    -
    -	/* find modified range */
    -
    -	f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields);
    -	ASSERT((1LL << f) & XFS_SB_MOD_BITS);
    -	first = xfs_sb_info[f].offset;
    -
    -	f = (xfs_sb_field_t)xfs_highbit64((__uint64_t)fields);
    -	ASSERT((1LL << f) & XFS_SB_MOD_BITS);
    -	last = xfs_sb_info[f + 1].offset - 1;
    -
    -	xfs_trans_log_buf(tp, bp, first, last);
    -}
    -/*
    - * xfs_mod_incore_sb_unlocked() is a utility routine common used to apply
    - * a delta to a specified field in the in-core superblock.  Simply
    - * switch on the field indicated and apply the delta to that field.
    - * Fields are not allowed to dip below zero, so if the delta would
    - * do this do not apply it and return EINVAL.
    - *
    - * The SB_LOCK must be held when this routine is called.
    - */
    -int
    -xfs_mod_incore_sb_unlocked(xfs_mount_t *mp, xfs_sb_field_t field,
    -			int delta, int rsvd)
    -{
    -	int		scounter;	/* short counter for 32 bit fields */
    -	long long	lcounter;	/* long counter for 64 bit fields */
    -	long long	res_used, rem;
    -
    -	/*
    -	 * With the in-core superblock spin lock held, switch
    -	 * on the indicated field.  Apply the delta to the
    -	 * proper field.  If the fields value would dip below
    -	 * 0, then do not apply the delta and return EINVAL.
    -	 */
    -	switch (field) {
    -	case XFS_SBS_ICOUNT:
    -		lcounter = (long long)mp->m_sb.sb_icount;
    -		lcounter += delta;
    -		if (lcounter < 0) {
    -			ASSERT(0);
    -			return XFS_ERROR(EINVAL);
    -		}
    -		mp->m_sb.sb_icount = lcounter;
    -		return 0;
    -	case XFS_SBS_IFREE:
    -		lcounter = (long long)mp->m_sb.sb_ifree;
    -		lcounter += delta;
    -		if (lcounter < 0) {
    -			ASSERT(0);
    -			return XFS_ERROR(EINVAL);
    -		}
    -		mp->m_sb.sb_ifree = lcounter;
    -		return 0;
    -	case XFS_SBS_FDBLOCKS:
    -
    -		lcounter = (long long)mp->m_sb.sb_fdblocks;
    -		res_used = (long long)(mp->m_resblks - mp->m_resblks_avail);
    -
    -		if (delta > 0) {		/* Putting blocks back */
    -			if (res_used > delta) {
    -				mp->m_resblks_avail += delta;
    -			} else {
    -				rem = delta - res_used;
    -				mp->m_resblks_avail = mp->m_resblks;
    -				lcounter += rem;
    -			}
    -		} else {				/* Taking blocks away */
    -
    -			lcounter += delta;
    -
    -		/*
    -		 * If were out of blocks, use any available reserved blocks if
    -		 * were allowed to.
    -		 */
    -
    -			if (lcounter < 0) {
    -				if (rsvd) {
    -					lcounter = (long long)mp->m_resblks_avail + delta;
    -					if (lcounter < 0) {
    -						return XFS_ERROR(ENOSPC);
    -					}
    -					mp->m_resblks_avail = lcounter;
    -					return 0;
    -				} else {	/* not reserved */
    -					return XFS_ERROR(ENOSPC);
    -				}
    -			}
    -		}
    -
    -		mp->m_sb.sb_fdblocks = lcounter;
    -		return 0;
    -	case XFS_SBS_FREXTENTS:
    -		lcounter = (long long)mp->m_sb.sb_frextents;
    -		lcounter += delta;
    -		if (lcounter < 0) {
    -			return XFS_ERROR(ENOSPC);
    -		}
    -		mp->m_sb.sb_frextents = lcounter;
    -		return 0;
    -	case XFS_SBS_DBLOCKS:
    -		lcounter = (long long)mp->m_sb.sb_dblocks;
    -		lcounter += delta;
    -		if (lcounter < 0) {
    -			ASSERT(0);
    -			return XFS_ERROR(EINVAL);
    -		}
    -		mp->m_sb.sb_dblocks = lcounter;
    -		return 0;
    -	case XFS_SBS_AGCOUNT:
    -		scounter = mp->m_sb.sb_agcount;
    -		scounter += delta;
    -		if (scounter < 0) {
    -			ASSERT(0);
    -			return XFS_ERROR(EINVAL);
    -		}
    -		mp->m_sb.sb_agcount = scounter;
    -		return 0;
    -	case XFS_SBS_IMAX_PCT:
    -		scounter = mp->m_sb.sb_imax_pct;
    -		scounter += delta;
    -		if (scounter < 0) {
    -			ASSERT(0);
    -			return XFS_ERROR(EINVAL);
    -		}
    -		mp->m_sb.sb_imax_pct = scounter;
    -		return 0;
    -	case XFS_SBS_REXTSIZE:
    -		scounter = mp->m_sb.sb_rextsize;
    -		scounter += delta;
    -		if (scounter < 0) {
    -			ASSERT(0);
    -			return XFS_ERROR(EINVAL);
    -		}
    -		mp->m_sb.sb_rextsize = scounter;
    -		return 0;
    -	case XFS_SBS_RBMBLOCKS:
    -		scounter = mp->m_sb.sb_rbmblocks;
    -		scounter += delta;
    -		if (scounter < 0) {
    -			ASSERT(0);
    -			return XFS_ERROR(EINVAL);
    -		}
    -		mp->m_sb.sb_rbmblocks = scounter;
    -		return 0;
    -	case XFS_SBS_RBLOCKS:
    -		lcounter = (long long)mp->m_sb.sb_rblocks;
    -		lcounter += delta;
    -		if (lcounter < 0) {
    -			ASSERT(0);
    -			return XFS_ERROR(EINVAL);
    -		}
    -		mp->m_sb.sb_rblocks = lcounter;
    -		return 0;
    -	case XFS_SBS_REXTENTS:
    -		lcounter = (long long)mp->m_sb.sb_rextents;
    -		lcounter += delta;
    -		if (lcounter < 0) {
    -			ASSERT(0);
    -			return XFS_ERROR(EINVAL);
    -		}
    -		mp->m_sb.sb_rextents = lcounter;
    -		return 0;
    -	case XFS_SBS_REXTSLOG:
    -		scounter = mp->m_sb.sb_rextslog;
    -		scounter += delta;
    -		if (scounter < 0) {
    -			ASSERT(0);
    -			return XFS_ERROR(EINVAL);
    -		}
    -		mp->m_sb.sb_rextslog = scounter;
    -		return 0;
    -	default:
    -		ASSERT(0);
    -		return XFS_ERROR(EINVAL);
    -	}
    -}
    -
    -/*
    - * xfs_mod_incore_sb() is used to change a field in the in-core
    - * superblock structure by the specified delta.  This modification
    - * is protected by the SB_LOCK.  Just use the xfs_mod_incore_sb_unlocked()
    - * routine to do the work.
    - */
    -int
    -xfs_mod_incore_sb(xfs_mount_t *mp, xfs_sb_field_t field, int delta, int rsvd)
    -{
    -	unsigned long	s;
    -	int	status;
    -
    -	/* check for per-cpu counters */
    -	switch (field) {
    -#ifdef HAVE_PERCPU_SB
    -	case XFS_SBS_ICOUNT:
    -	case XFS_SBS_IFREE:
    -	case XFS_SBS_FDBLOCKS:
    -		if (!(mp->m_flags & XFS_MOUNT_NO_PERCPU_SB)) {
    -			status = xfs_icsb_modify_counters(mp, field,
    -							delta, rsvd);
    -			break;
    -		}
    -		/* FALLTHROUGH */
    -#endif
    -	default:
    -		s = XFS_SB_LOCK(mp);
    -		status = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd);
    -		XFS_SB_UNLOCK(mp, s);
    -		break;
    -	}
    -
    -	return status;
    -}
    -
    -/*
    - * xfs_mod_incore_sb_batch() is used to change more than one field
    - * in the in-core superblock structure at a time.  This modification
    - * is protected by a lock internal to this module.  The fields and
    - * changes to those fields are specified in the array of xfs_mod_sb
    - * structures passed in.
    - *
    - * Either all of the specified deltas will be applied or none of
    - * them will.  If any modified field dips below 0, then all modifications
    - * will be backed out and EINVAL will be returned.
    - */
    -int
    -xfs_mod_incore_sb_batch(xfs_mount_t *mp, xfs_mod_sb_t *msb, uint nmsb, int rsvd)
    -{
    -	unsigned long	s;
    -	int		status=0;
    -	xfs_mod_sb_t	*msbp;
    -
    -	/*
    -	 * Loop through the array of mod structures and apply each
    -	 * individually.  If any fail, then back out all those
    -	 * which have already been applied.  Do all of this within
    -	 * the scope of the SB_LOCK so that all of the changes will
    -	 * be atomic.
    -	 */
    -	s = XFS_SB_LOCK(mp);
    -	msbp = &msb[0];
    -	for (msbp = &msbp[0]; msbp < (msb + nmsb); msbp++) {
    -		/*
    -		 * Apply the delta at index n.  If it fails, break
    -		 * from the loop so we'll fall into the undo loop
    -		 * below.
    -		 */
    -		switch (msbp->msb_field) {
    -#ifdef HAVE_PERCPU_SB
    -		case XFS_SBS_ICOUNT:
    -		case XFS_SBS_IFREE:
    -		case XFS_SBS_FDBLOCKS:
    -			if (!(mp->m_flags & XFS_MOUNT_NO_PERCPU_SB)) {
    -				status = xfs_icsb_modify_counters_locked(mp,
    -							msbp->msb_field,
    -							msbp->msb_delta, rsvd);
    -				break;
    -			}
    -			/* FALLTHROUGH */
    -#endif
    -		default:
    -			status = xfs_mod_incore_sb_unlocked(mp,
    -						msbp->msb_field,
    -						msbp->msb_delta, rsvd);
    -			break;
    -		}
    -
    -		if (status != 0) {
    -			break;
    -		}
    -	}
    -
    -	/*
    -	 * If we didn't complete the loop above, then back out
    -	 * any changes made to the superblock.  If you add code
    -	 * between the loop above and here, make sure that you
    -	 * preserve the value of status. Loop back until
    -	 * we step below the beginning of the array.  Make sure
    -	 * we don't touch anything back there.
    -	 */
    -	if (status != 0) {
    -		msbp--;
    -		while (msbp >= msb) {
    -			switch (msbp->msb_field) {
    -#ifdef HAVE_PERCPU_SB
    -			case XFS_SBS_ICOUNT:
    -			case XFS_SBS_IFREE:
    -			case XFS_SBS_FDBLOCKS:
    -				if (!(mp->m_flags & XFS_MOUNT_NO_PERCPU_SB)) {
    -					status =
    -					    xfs_icsb_modify_counters_locked(mp,
    -							msbp->msb_field,
    -							-(msbp->msb_delta),
    -							rsvd);
    -					break;
    -				}
    -				/* FALLTHROUGH */
    -#endif
    -			default:
    -				status = xfs_mod_incore_sb_unlocked(mp,
    -							msbp->msb_field,
    -							-(msbp->msb_delta),
    -							rsvd);
    -				break;
    -			}
    -			ASSERT(status == 0);
    -			msbp--;
    -		}
    -	}
    -	XFS_SB_UNLOCK(mp, s);
    -	return status;
    -}
    -
    -/*
    - * xfs_getsb() is called to obtain the buffer for the superblock.
    - * The buffer is returned locked and read in from disk.
    - * The buffer should be released with a call to xfs_brelse().
    - *
    - * If the flags parameter is BUF_TRYLOCK, then we'll only return
    - * the superblock buffer if it can be locked without sleeping.
    - * If it can't then we'll return NULL.
    - */
    -xfs_buf_t *
    -xfs_getsb(
    -	xfs_mount_t	*mp,
    -	int		flags)
    -{
    -	xfs_buf_t	*bp;
    -	int		extra_flags = 0;
    -	unsigned int	sector_size;
    -
    -
    -	bp = mp->m_sb_bp;
    -	sector_size = xfs_getsize_buftarg(mp->m_ddev_targp);
    -#ifdef NOT
    -	/* MANAGED buf's appear broken in FreeBSD
    -	 * but it's unclear if we need a persistant superblock?
    -	 * since we now translate the ondisk superblock to
    -	 * a separate translated structure and then translate that
    -	 * structure back when we want to write the superblock
    -	 */
    -	extra_flags = XFS_BUF_LOCK | XFS_BUF_MANAGE | XFS_BUF_MAPPED;
    -	extra_flags = XFS_BUF_MANAGE;
    -#endif
    -
    -	mp->m_sb_bp = bp
    -	  = xfs_buf_read_flags(mp->m_ddev_targp,
    -			       XFS_SB_DADDR,
    -			       BTOBB(sector_size),
    -			       extra_flags);
    -
    -	XFS_BUF_HOLD(bp);
    -	ASSERT(XFS_BUF_ISDONE(bp));
    -	if (!XFS_BUF_ISDONE(bp)){
    -		printf("xfs_getsb: %p bp flags 0x%x\n",bp,bp->b_flags);
    -	}
    -	return bp;
    -}
    -
    -/*
    - * Used to free the superblock along various error paths.
    - */
    -void
    -xfs_freesb(
    -	xfs_mount_t	*mp)
    -{
    -	xfs_buf_t	*bp;
    -
    -	/*
    -	 * Use xfs_getsb() so that the buffer will be locked
    -	 * when we call xfs_buf_relse().
    -	 */
    -	bp = xfs_getsb(mp, 0);
    -	XFS_BUF_UNMANAGE(bp);
    -	xfs_buf_relse(bp);
    -	mp->m_sb_bp = NULL;
    -}
    -
    -/*
    - * See if the UUID is unique among mounted XFS filesystems.
    - * Mount fails if UUID is nil or a FS with the same UUID is already mounted.
    - */
    -STATIC int
    -xfs_uuid_mount(
    -	xfs_mount_t	*mp)
    -{
    -	if (uuid_is_nil(&mp->m_sb.sb_uuid)) {
    -		cmn_err(CE_WARN,
    -			"XFS: Filesystem %s has nil UUID - can't mount",
    -			mp->m_fsname);
    -		return -1;
    -	}
    -	if (!uuid_table_insert(&mp->m_sb.sb_uuid)) {
    -		cmn_err(CE_WARN,
    -			"XFS: Filesystem %s has duplicate UUID - can't mount",
    -			mp->m_fsname);
    -		return -1;
    -	}
    -	return 0;
    -}
    -
    -/*
    - * Remove filesystem from the UUID table.
    - */
    -STATIC void
    -xfs_uuid_unmount(
    -	xfs_mount_t	*mp)
    -{
    -	uuid_table_remove(&mp->m_sb.sb_uuid);
    -}
    -
    -/*
    - * Used to log changes to the superblock unit and width fields which could
    - * be altered by the mount options. Only the first superblock is updated.
    - */
    -STATIC void
    -xfs_mount_log_sbunit(
    -	xfs_mount_t	*mp,
    -	__int64_t	fields)
    -{
    -	xfs_trans_t	*tp;
    -
    -	ASSERT(fields & (XFS_SB_UNIT|XFS_SB_WIDTH|XFS_SB_UUID));
    -
    -	tp = xfs_trans_alloc(mp, XFS_TRANS_SB_UNIT);
    -	if (xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0,
    -				XFS_DEFAULT_LOG_COUNT)) {
    -		xfs_trans_cancel(tp, 0);
    -		return;
    -	}
    -	xfs_mod_sb(tp, fields);
    -	xfs_trans_commit(tp, 0, NULL);
    -}
    -
    -
    -#ifdef HAVE_PERCPU_SB
    -/*
    - * Per-cpu incore superblock counters
    - *
    - * Simple concept, difficult implementation
    - *
    - * Basically, replace the incore superblock counters with a distributed per cpu
    - * counter for contended fields (e.g.  free block count).
    - *
    - * Difficulties arise in that the incore sb is used for ENOSPC checking, and
    - * hence needs to be accurately read when we are running low on space. Hence
    - * there is a method to enable and disable the per-cpu counters based on how
    - * much "stuff" is available in them.
    - *
    - * Basically, a counter is enabled if there is enough free resource to justify
    - * running a per-cpu fast-path. If the per-cpu counter runs out (i.e. a local
    - * ENOSPC), then we disable the counters to synchronise all callers and
    - * re-distribute the available resources.
    - *
    - * If, once we redistributed the available resources, we still get a failure,
    - * we disable the per-cpu counter and go through the slow path.
    - *
    - * The slow path is the current xfs_mod_incore_sb() function.  This means that
    - * when we disable a per-cpu counter, we need to drain it's resources back to
    - * the global superblock. We do this after disabling the counter to prevent
    - * more threads from queueing up on the counter.
    - *
    - * Essentially, this means that we still need a lock in the fast path to enable
    - * synchronisation between the global counters and the per-cpu counters. This
    - * is not a problem because the lock will be local to a CPU almost all the time
    - * and have little contention except when we get to ENOSPC conditions.
    - *
    - * Basically, this lock becomes a barrier that enables us to lock out the fast
    - * path while we do things like enabling and disabling counters and
    - * synchronising the counters.
    - *
    - * Locking rules:
    - *
    - * 	1. XFS_SB_LOCK() before picking up per-cpu locks
    - * 	2. per-cpu locks always picked up via for_each_online_cpu() order
    - * 	3. accurate counter sync requires XFS_SB_LOCK + per cpu locks
    - * 	4. modifying per-cpu counters requires holding per-cpu lock
    - * 	5. modifying global counters requires holding XFS_SB_LOCK
    - *	6. enabling or disabling a counter requires holding the XFS_SB_LOCK
    - *	   and _none_ of the per-cpu locks.
    - *
    - * Disabled counters are only ever re-enabled by a balance operation
    - * that results in more free resources per CPU than a given threshold.
    - * To ensure counters don't remain disabled, they are rebalanced when
    - * the global resource goes above a higher threshold (i.e. some hysteresis
    - * is present to prevent thrashing).
    - */
    -
    -/*
    - * hot-plug CPU notifier support.
    - *
    - * We cannot use the hotcpu_register() function because it does
    - * not allow notifier instances. We need a notifier per filesystem
    - * as we need to be able to identify the filesystem to balance
    - * the counters out. This is achieved by having a notifier block
    - * embedded in the xfs_mount_t and doing pointer magic to get the
    - * mount pointer from the notifier block address.
    - */
    -STATIC int
    -xfs_icsb_cpu_notify(
    -	struct notifier_block *nfb,
    -	unsigned long action,
    -	void *hcpu)
    -{
    -	xfs_icsb_cnts_t *cntp;
    -	xfs_mount_t	*mp;
    -	int		s;
    -
    -	mp = (xfs_mount_t *)container_of(nfb, xfs_mount_t, m_icsb_notifier);
    -	cntp = (xfs_icsb_cnts_t *)
    -			per_cpu_ptr(mp->m_sb_cnts, (unsigned long)hcpu);
    -	switch (action) {
    -	case CPU_UP_PREPARE:
    -		/* Easy Case - initialize the area and locks, and
    -		 * then rebalance when online does everything else for us. */
    -		memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
    -		break;
    -	case CPU_ONLINE:
    -		xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0);
    -		xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0);
    -		xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
    -		break;
    -	case CPU_DEAD:
    -		/* Disable all the counters, then fold the dead cpu's
    -		 * count into the total on the global superblock and
    -		 * re-enable the counters. */
    -		s = XFS_SB_LOCK(mp);
    -		xfs_icsb_disable_counter(mp, XFS_SBS_ICOUNT);
    -		xfs_icsb_disable_counter(mp, XFS_SBS_IFREE);
    -		xfs_icsb_disable_counter(mp, XFS_SBS_FDBLOCKS);
    -
    -		mp->m_sb.sb_icount += cntp->icsb_icount;
    -		mp->m_sb.sb_ifree += cntp->icsb_ifree;
    -		mp->m_sb.sb_fdblocks += cntp->icsb_fdblocks;
    -
    -		memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
    -
    -		xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, XFS_ICSB_SB_LOCKED);
    -		xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, XFS_ICSB_SB_LOCKED);
    -		xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, XFS_ICSB_SB_LOCKED);
    -		XFS_SB_UNLOCK(mp, s);
    -		break;
    -	}
    -
    -	return NOTIFY_OK;
    -}
    -
    -int
    -xfs_icsb_init_counters(
    -	xfs_mount_t	*mp)
    -{
    -	xfs_icsb_cnts_t *cntp;
    -	int		i;
    -
    -	mp->m_sb_cnts = alloc_percpu(xfs_icsb_cnts_t);
    -	if (mp->m_sb_cnts == NULL)
    -		return -ENOMEM;
    -
    -	mp->m_icsb_notifier.notifier_call = xfs_icsb_cpu_notify;
    -	mp->m_icsb_notifier.priority = 0;
    -	register_cpu_notifier(&mp->m_icsb_notifier);
    -
    -	for_each_online_cpu(i) {
    -		cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
    -		memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
    -	}
    -	/*
    -	 * start with all counters disabled so that the
    -	 * initial balance kicks us off correctly
    -	 */
    -	mp->m_icsb_counters = -1;
    -	return 0;
    -}
    -
    -STATIC void
    -xfs_icsb_destroy_counters(
    -	xfs_mount_t	*mp)
    -{
    -	if (mp->m_sb_cnts) {
    -		unregister_cpu_notifier(&mp->m_icsb_notifier);
    -		free_percpu(mp->m_sb_cnts);
    -	}
    -}
    -
    -STATIC inline void
    -xfs_icsb_lock_cntr(
    -	xfs_icsb_cnts_t	*icsbp)
    -{
    -	while (test_and_set_bit(XFS_ICSB_FLAG_LOCK, &icsbp->icsb_flags)) {
    -		ndelay(1000);
    -	}
    -}
    -
    -STATIC inline void
    -xfs_icsb_unlock_cntr(
    -	xfs_icsb_cnts_t	*icsbp)
    -{
    -	clear_bit(XFS_ICSB_FLAG_LOCK, &icsbp->icsb_flags);
    -}
    -
    -
    -STATIC inline void
    -xfs_icsb_lock_all_counters(
    -	xfs_mount_t	*mp)
    -{
    -	xfs_icsb_cnts_t *cntp;
    -	int		i;
    -
    -	for_each_online_cpu(i) {
    -		cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
    -		xfs_icsb_lock_cntr(cntp);
    -	}
    -}
    -
    -STATIC inline void
    -xfs_icsb_unlock_all_counters(
    -	xfs_mount_t	*mp)
    -{
    -	xfs_icsb_cnts_t *cntp;
    -	int		i;
    -
    -	for_each_online_cpu(i) {
    -		cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
    -		xfs_icsb_unlock_cntr(cntp);
    -	}
    -}
    -
    -STATIC void
    -xfs_icsb_count(
    -	xfs_mount_t	*mp,
    -	xfs_icsb_cnts_t	*cnt,
    -	int		flags)
    -{
    -	xfs_icsb_cnts_t *cntp;
    -	int		i;
    -
    -	memset(cnt, 0, sizeof(xfs_icsb_cnts_t));
    -
    -	if (!(flags & XFS_ICSB_LAZY_COUNT))
    -		xfs_icsb_lock_all_counters(mp);
    -
    -	for_each_online_cpu(i) {
    -		cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
    -		cnt->icsb_icount += cntp->icsb_icount;
    -		cnt->icsb_ifree += cntp->icsb_ifree;
    -		cnt->icsb_fdblocks += cntp->icsb_fdblocks;
    -	}
    -
    -	if (!(flags & XFS_ICSB_LAZY_COUNT))
    -		xfs_icsb_unlock_all_counters(mp);
    -}
    -
    -STATIC int
    -xfs_icsb_counter_disabled(
    -	xfs_mount_t	*mp,
    -	xfs_sb_field_t	field)
    -{
    -	ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS));
    -	return test_bit(field, &mp->m_icsb_counters);
    -}
    -
    -STATIC int
    -xfs_icsb_disable_counter(
    -	xfs_mount_t	*mp,
    -	xfs_sb_field_t	field)
    -{
    -	xfs_icsb_cnts_t	cnt;
    -
    -	ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS));
    -
    -	xfs_icsb_lock_all_counters(mp);
    -	if (!test_and_set_bit(field, &mp->m_icsb_counters)) {
    -		/* drain back to superblock */
    -
    -		xfs_icsb_count(mp, &cnt, XFS_ICSB_SB_LOCKED|XFS_ICSB_LAZY_COUNT);
    -		switch(field) {
    -		case XFS_SBS_ICOUNT:
    -			mp->m_sb.sb_icount = cnt.icsb_icount;
    -			break;
    -		case XFS_SBS_IFREE:
    -			mp->m_sb.sb_ifree = cnt.icsb_ifree;
    -			break;
    -		case XFS_SBS_FDBLOCKS:
    -			mp->m_sb.sb_fdblocks = cnt.icsb_fdblocks;
    -			break;
    -		default:
    -			BUG();
    -		}
    -	}
    -
    -	xfs_icsb_unlock_all_counters(mp);
    -
    -	return 0;
    -}
    -
    -STATIC void
    -xfs_icsb_enable_counter(
    -	xfs_mount_t	*mp,
    -	xfs_sb_field_t	field,
    -	uint64_t	count,
    -	uint64_t	resid)
    -{
    -	xfs_icsb_cnts_t	*cntp;
    -	int		i;
    -
    -	ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS));
    -
    -	xfs_icsb_lock_all_counters(mp);
    -	for_each_online_cpu(i) {
    -		cntp = per_cpu_ptr(mp->m_sb_cnts, i);
    -		switch (field) {
    -		case XFS_SBS_ICOUNT:
    -			cntp->icsb_icount = count + resid;
    -			break;
    -		case XFS_SBS_IFREE:
    -			cntp->icsb_ifree = count + resid;
    -			break;
    -		case XFS_SBS_FDBLOCKS:
    -			cntp->icsb_fdblocks = count + resid;
    -			break;
    -		default:
    -			BUG();
    -			break;
    -		}
    -		resid = 0;
    -	}
    -	clear_bit(field, &mp->m_icsb_counters);
    -	xfs_icsb_unlock_all_counters(mp);
    -}
    -
    -STATIC void
    -xfs_icsb_sync_counters_int(
    -	xfs_mount_t	*mp,
    -	int		flags)
    -{
    -	xfs_icsb_cnts_t	cnt;
    -	int		s;
    -
    -	/* Pass 1: lock all counters */
    -	if ((flags & XFS_ICSB_SB_LOCKED) == 0)
    -		s = XFS_SB_LOCK(mp);
    -
    -	xfs_icsb_count(mp, &cnt, flags);
    -
    -	/* Step 3: update mp->m_sb fields */
    -	if (!xfs_icsb_counter_disabled(mp, XFS_SBS_ICOUNT))
    -		mp->m_sb.sb_icount = cnt.icsb_icount;
    -	if (!xfs_icsb_counter_disabled(mp, XFS_SBS_IFREE))
    -		mp->m_sb.sb_ifree = cnt.icsb_ifree;
    -	if (!xfs_icsb_counter_disabled(mp, XFS_SBS_FDBLOCKS))
    -		mp->m_sb.sb_fdblocks = cnt.icsb_fdblocks;
    -
    -	if ((flags & XFS_ICSB_SB_LOCKED) == 0)
    -		XFS_SB_UNLOCK(mp, s);
    -}
    -
    -/*
    - * Accurate update of per-cpu counters to incore superblock
    - */
    -STATIC void
    -xfs_icsb_sync_counters(
    -	xfs_mount_t	*mp)
    -{
    -	xfs_icsb_sync_counters_int(mp, 0);
    -}
    -
    -/*
    - * lazy addition used for things like df, background sb syncs, etc
    - */
    -void
    -xfs_icsb_sync_counters_lazy(
    -	xfs_mount_t	*mp)
    -{
    -	xfs_icsb_sync_counters_int(mp, XFS_ICSB_LAZY_COUNT);
    -}
    -
    -/*
    - * Balance and enable/disable counters as necessary.
    - *
    - * Thresholds for re-enabling counters are somewhat magic.
    - * inode counts are chosen to be the same number as single
    - * on disk allocation chunk per CPU, and free blocks is
    - * something far enough zero that we aren't going thrash
    - * when we get near ENOSPC.
    - */
    -#define XFS_ICSB_INO_CNTR_REENABLE	64
    -#define XFS_ICSB_FDBLK_CNTR_REENABLE	512
    -STATIC void
    -xfs_icsb_balance_counter(
    -	xfs_mount_t	*mp,
    -	xfs_sb_field_t  field,
    -	int		flags)
    -{
    -	uint64_t	count, resid = 0;
    -	int		weight = num_online_cpus();
    -	int		s;
    -
    -	if (!(flags & XFS_ICSB_SB_LOCKED))
    -		s = XFS_SB_LOCK(mp);
    -
    -	/* disable counter and sync counter */
    -	xfs_icsb_disable_counter(mp, field);
    -
    -	/* update counters  - first CPU gets residual*/
    -	switch (field) {
    -	case XFS_SBS_ICOUNT:
    -		count = mp->m_sb.sb_icount;
    -		resid = do_div(count, weight);
    -		if (count < XFS_ICSB_INO_CNTR_REENABLE)
    -			goto out;
    -		break;
    -	case XFS_SBS_IFREE:
    -		count = mp->m_sb.sb_ifree;
    -		resid = do_div(count, weight);
    -		if (count < XFS_ICSB_INO_CNTR_REENABLE)
    -			goto out;
    -		break;
    -	case XFS_SBS_FDBLOCKS:
    -		count = mp->m_sb.sb_fdblocks;
    -		resid = do_div(count, weight);
    -		if (count < XFS_ICSB_FDBLK_CNTR_REENABLE)
    -			goto out;
    -		break;
    -	default:
    -		BUG();
    -		break;
    -	}
    -
    -	xfs_icsb_enable_counter(mp, field, count, resid);
    -out:
    -	if (!(flags & XFS_ICSB_SB_LOCKED))
    -		XFS_SB_UNLOCK(mp, s);
    -}
    -
    -STATIC int
    -xfs_icsb_modify_counters_int(
    -	xfs_mount_t	*mp,
    -	xfs_sb_field_t	field,
    -	int		delta,
    -	int		rsvd,
    -	int		flags)
    -{
    -	xfs_icsb_cnts_t	*icsbp;
    -	long long	lcounter;	/* long counter for 64 bit fields */
    -	int		cpu, s, locked = 0;
    -	int		ret = 0, balance_done = 0;
    -
    -again:
    -	cpu = get_cpu();
    -	icsbp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, cpu),
    -	xfs_icsb_lock_cntr(icsbp);
    -	if (unlikely(xfs_icsb_counter_disabled(mp, field)))
    -		goto slow_path;
    -
    -	switch (field) {
    -	case XFS_SBS_ICOUNT:
    -		lcounter = icsbp->icsb_icount;
    -		lcounter += delta;
    -		if (unlikely(lcounter < 0))
    -			goto slow_path;
    -		icsbp->icsb_icount = lcounter;
    -		break;
    -
    -	case XFS_SBS_IFREE:
    -		lcounter = icsbp->icsb_ifree;
    -		lcounter += delta;
    -		if (unlikely(lcounter < 0))
    -			goto slow_path;
    -		icsbp->icsb_ifree = lcounter;
    -		break;
    -
    -	case XFS_SBS_FDBLOCKS:
    -		BUG_ON((mp->m_resblks - mp->m_resblks_avail) != 0);
    -
    -		lcounter = icsbp->icsb_fdblocks;
    -		lcounter += delta;
    -		if (unlikely(lcounter < 0))
    -			goto slow_path;
    -		icsbp->icsb_fdblocks = lcounter;
    -		break;
    -	default:
    -		BUG();
    -		break;
    -	}
    -	xfs_icsb_unlock_cntr(icsbp);
    -	put_cpu();
    -	if (locked)
    -		XFS_SB_UNLOCK(mp, s);
    -	return 0;
    -
    -	/*
    -	 * The slow path needs to be run with the SBLOCK
    -	 * held so that we prevent other threads from
    -	 * attempting to run this path at the same time.
    -	 * this provides exclusion for the balancing code,
    -	 * and exclusive fallback if the balance does not
    -	 * provide enough resources to continue in an unlocked
    -	 * manner.
    -	 */
    -slow_path:
    -	xfs_icsb_unlock_cntr(icsbp);
    -	put_cpu();
    -
    -	/* need to hold superblock incase we need
    -	 * to disable a counter */
    -	if (!(flags & XFS_ICSB_SB_LOCKED)) {
    -		s = XFS_SB_LOCK(mp);
    -		locked = 1;
    -		flags |= XFS_ICSB_SB_LOCKED;
    -	}
    -	if (!balance_done) {
    -		xfs_icsb_balance_counter(mp, field, flags);
    -		balance_done = 1;
    -		goto again;
    -	} else {
    -		/*
    -		 * we might not have enough on this local
    -		 * cpu to allocate for a bulk request.
    -		 * We need to drain this field from all CPUs
    -		 * and disable the counter fastpath
    -		 */
    -		xfs_icsb_disable_counter(mp, field);
    -	}
    -
    -	ret = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd);
    -
    -	if (locked)
    -		XFS_SB_UNLOCK(mp, s);
    -	return ret;
    -}
    -
    -STATIC int
    -xfs_icsb_modify_counters(
    -	xfs_mount_t	*mp,
    -	xfs_sb_field_t	field,
    -	int		delta,
    -	int		rsvd)
    -{
    -	return xfs_icsb_modify_counters_int(mp, field, delta, rsvd, 0);
    -}
    -
    -/*
    - * Called when superblock is already locked
    - */
    -STATIC int
    -xfs_icsb_modify_counters_locked(
    -	xfs_mount_t	*mp,
    -	xfs_sb_field_t	field,
    -	int		delta,
    -	int		rsvd)
    -{
    -	return xfs_icsb_modify_counters_int(mp, field, delta,
    -						rsvd, XFS_ICSB_SB_LOCKED);
    -}
    -#endif
    diff --git a/sys/gnu/fs/xfs/xfs_mount.h b/sys/gnu/fs/xfs/xfs_mount.h
    deleted file mode 100644
    index 02ad298c7d1..00000000000
    --- a/sys/gnu/fs/xfs/xfs_mount.h
    +++ /dev/null
    @@ -1,626 +0,0 @@
    -/*
    - * Copyright (c) 2000-2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_MOUNT_H__
    -#define	__XFS_MOUNT_H__
    -
    -typedef struct xfs_trans_reservations {
    -	uint	tr_write;	/* extent alloc trans */
    -	uint	tr_itruncate;	/* truncate trans */
    -	uint	tr_rename;	/* rename trans */
    -	uint	tr_link;	/* link trans */
    -	uint	tr_remove;	/* unlink trans */
    -	uint	tr_symlink;	/* symlink trans */
    -	uint	tr_create;	/* create trans */
    -	uint	tr_mkdir;	/* mkdir trans */
    -	uint	tr_ifree;	/* inode free trans */
    -	uint	tr_ichange;	/* inode update trans */
    -	uint	tr_growdata;	/* fs data section grow trans */
    -	uint	tr_swrite;	/* sync write inode trans */
    -	uint	tr_addafork;	/* cvt inode to attributed trans */
    -	uint	tr_writeid;	/* write setuid/setgid file */
    -	uint	tr_attrinval;	/* attr fork buffer invalidation */
    -	uint	tr_attrset;	/* set/create an attribute */
    -	uint	tr_attrrm;	/* remove an attribute */
    -	uint	tr_clearagi;	/* clear bad agi unlinked ino bucket */
    -	uint	tr_growrtalloc;	/* grow realtime allocations */
    -	uint	tr_growrtzero;	/* grow realtime zeroing */
    -	uint	tr_growrtfree;	/* grow realtime freeing */
    -} xfs_trans_reservations_t;
    -
    -#ifndef __KERNEL__
    -/*
    - * Moved here from xfs_ag.h to avoid reordering header files
    - */
    -#define XFS_DADDR_TO_AGNO(mp,d) \
    -	((xfs_agnumber_t)(XFS_BB_TO_FSBT(mp, d) / (mp)->m_sb.sb_agblocks))
    -#define XFS_DADDR_TO_AGBNO(mp,d) \
    -	((xfs_agblock_t)(XFS_BB_TO_FSBT(mp, d) % (mp)->m_sb.sb_agblocks))
    -#else
    -struct cred;
    -struct log;
    -struct xfs_vfs;
    -struct xfs_vnode;
    -struct xfs_mount_args;
    -struct xfs_ihash;
    -struct xfs_chash;
    -struct xfs_inode;
    -struct xfs_perag;
    -struct xfs_iocore;
    -struct xfs_bmbt_irec;
    -struct xfs_bmap_free;
    -struct xfs_extdelta;
    -struct xfs_swapext;
    -
    -extern struct xvfsops xfs_vfsops;
    -//extern struct xvnodeops xfs_vnodeops;
    -
    -#define	AIL_LOCK_T		lock_t
    -#define	AIL_LOCKINIT(x,y)	spinlock_init(x,y)
    -#define	AIL_LOCK_DESTROY(x)	spinlock_destroy(x)
    -#define	AIL_LOCK(mp,s)		s=mutex_spinlock(&(mp)->m_ail_lock)
    -#define	AIL_UNLOCK(mp,s)	mutex_spinunlock(&(mp)->m_ail_lock, s)
    -
    -
    -/*
    - * Prototypes and functions for the Data Migration subsystem.
    - */
    -
    -typedef int	(*xfs_send_data_t)(int, struct xfs_vnode *,
    -			xfs_off_t, size_t, int, vrwlock_t *);
    -typedef int	(*xfs_send_mmap_t)(void*, uint);
    -typedef int	(*xfs_send_destroy_t)(struct xfs_vnode *, dm_right_t);
    -typedef int	(*xfs_send_namesp_t)(dm_eventtype_t, struct xfs_vfs *,
    -			struct xfs_vnode *,
    -			dm_right_t, struct xfs_vnode *, dm_right_t,
    -			char *, char *, mode_t, int, int);
    -typedef void	(*xfs_send_unmount_t)(struct xfs_vfs *, struct xfs_vnode *,
    -			dm_right_t, mode_t, int, int);
    -
    -typedef struct xfs_dmops {
    -	xfs_send_data_t		xfs_send_data;
    -	xfs_send_mmap_t		xfs_send_mmap;
    -	xfs_send_destroy_t	xfs_send_destroy;
    -	xfs_send_namesp_t	xfs_send_namesp;
    -	xfs_send_unmount_t	xfs_send_unmount;
    -} xfs_dmops_t;
    -
    -#define XFS_SEND_DATA(mp, ev,vp,off,len,fl,lock) \
    -	(*(mp)->m_dm_ops.xfs_send_data)(ev,vp,off,len,fl,lock)
    -#define XFS_SEND_MMAP(mp, vma,fl) \
    -	(*(mp)->m_dm_ops.xfs_send_mmap)(vma,fl)
    -#define XFS_SEND_DESTROY(mp, vp,right) \
    -	(*(mp)->m_dm_ops.xfs_send_destroy)(vp,right)
    -#define XFS_SEND_NAMESP(mp, ev,b1,r1,b2,r2,n1,n2,mode,rval,fl) \
    -	(*(mp)->m_dm_ops.xfs_send_namesp)(ev,NULL,b1,r1,b2,r2,n1,n2,mode,rval,fl)
    -#define XFS_SEND_PREUNMOUNT(mp, vfs,b1,r1,b2,r2,n1,n2,mode,rval,fl) \
    -	(*(mp)->m_dm_ops.xfs_send_namesp)(DM_EVENT_PREUNMOUNT,vfs,b1,r1,b2,r2,n1,n2,mode,rval,fl)
    -#define XFS_SEND_UNMOUNT(mp, vfsp,vp,right,mode,rval,fl) \
    -	(*(mp)->m_dm_ops.xfs_send_unmount)(vfsp,vp,right,mode,rval,fl)
    -
    -
    -/*
    - * Prototypes and functions for the Quota Management subsystem.
    - */
    -
    -struct xfs_dquot;
    -struct xfs_dqtrxops;
    -struct xfs_quotainfo;
    -
    -typedef int	(*xfs_qminit_t)(struct xfs_mount *, uint *, uint *);
    -typedef int	(*xfs_qmmount_t)(struct xfs_mount *, uint, uint, int);
    -typedef int	(*xfs_qmunmount_t)(struct xfs_mount *);
    -typedef void	(*xfs_qmdone_t)(struct xfs_mount *);
    -typedef void	(*xfs_dqrele_t)(struct xfs_dquot *);
    -typedef int	(*xfs_dqattach_t)(struct xfs_inode *, uint);
    -typedef void	(*xfs_dqdetach_t)(struct xfs_inode *);
    -typedef int	(*xfs_dqpurgeall_t)(struct xfs_mount *, uint);
    -typedef int	(*xfs_dqvopalloc_t)(struct xfs_mount *,
    -			struct xfs_inode *, uid_t, gid_t, prid_t, uint,
    -			struct xfs_dquot **, struct xfs_dquot **);
    -typedef void	(*xfs_dqvopcreate_t)(struct xfs_trans *, struct xfs_inode *,
    -			struct xfs_dquot *, struct xfs_dquot *);
    -typedef int	(*xfs_dqvoprename_t)(struct xfs_inode **);
    -typedef struct xfs_dquot * (*xfs_dqvopchown_t)(
    -			struct xfs_trans *, struct xfs_inode *,
    -			struct xfs_dquot **, struct xfs_dquot *);
    -typedef int	(*xfs_dqvopchownresv_t)(struct xfs_trans *, struct xfs_inode *,
    -			struct xfs_dquot *, struct xfs_dquot *, uint);
    -
    -typedef struct xfs_qmops {
    -	xfs_qminit_t		xfs_qminit;
    -	xfs_qmdone_t		xfs_qmdone;
    -	xfs_qmmount_t		xfs_qmmount;
    -	xfs_qmunmount_t		xfs_qmunmount;
    -	xfs_dqrele_t		xfs_dqrele;
    -	xfs_dqattach_t		xfs_dqattach;
    -	xfs_dqdetach_t		xfs_dqdetach;
    -	xfs_dqpurgeall_t	xfs_dqpurgeall;
    -	xfs_dqvopalloc_t	xfs_dqvopalloc;
    -	xfs_dqvopcreate_t	xfs_dqvopcreate;
    -	xfs_dqvoprename_t	xfs_dqvoprename;
    -	xfs_dqvopchown_t	xfs_dqvopchown;
    -	xfs_dqvopchownresv_t	xfs_dqvopchownresv;
    -	struct xfs_dqtrxops	*xfs_dqtrxops;
    -} xfs_qmops_t;
    -
    -#define XFS_QM_INIT(mp, mnt, fl) \
    -	(*(mp)->m_qm_ops.xfs_qminit)(mp, mnt, fl)
    -#define XFS_QM_MOUNT(mp, mnt, fl, mfsi_flags) \
    -	(*(mp)->m_qm_ops.xfs_qmmount)(mp, mnt, fl, mfsi_flags)
    -#define XFS_QM_UNMOUNT(mp) \
    -	(*(mp)->m_qm_ops.xfs_qmunmount)(mp)
    -#define XFS_QM_DONE(mp) \
    -	(*(mp)->m_qm_ops.xfs_qmdone)(mp)
    -#define XFS_QM_DQRELE(mp, dq) \
    -	(*(mp)->m_qm_ops.xfs_dqrele)(dq)
    -#define XFS_QM_DQATTACH(mp, ip, fl) \
    -	(*(mp)->m_qm_ops.xfs_dqattach)(ip, fl)
    -#define XFS_QM_DQDETACH(mp, ip) \
    -	(*(mp)->m_qm_ops.xfs_dqdetach)(ip)
    -#define XFS_QM_DQPURGEALL(mp, fl) \
    -	(*(mp)->m_qm_ops.xfs_dqpurgeall)(mp, fl)
    -#define XFS_QM_DQVOPALLOC(mp, ip, uid, gid, prid, fl, dq1, dq2) \
    -	(*(mp)->m_qm_ops.xfs_dqvopalloc)(mp, ip, uid, gid, prid, fl, dq1, dq2)
    -#define XFS_QM_DQVOPCREATE(mp, tp, ip, dq1, dq2) \
    -	(*(mp)->m_qm_ops.xfs_dqvopcreate)(tp, ip, dq1, dq2)
    -#define XFS_QM_DQVOPRENAME(mp, ip) \
    -	(*(mp)->m_qm_ops.xfs_dqvoprename)(ip)
    -#define XFS_QM_DQVOPCHOWN(mp, tp, ip, dqp, dq) \
    -	(*(mp)->m_qm_ops.xfs_dqvopchown)(tp, ip, dqp, dq)
    -#define XFS_QM_DQVOPCHOWNRESV(mp, tp, ip, dq1, dq2, fl) \
    -	(*(mp)->m_qm_ops.xfs_dqvopchownresv)(tp, ip, dq1, dq2, fl)
    -
    -
    -/*
    - * Prototypes and functions for I/O core modularization.
    - */
    -
    -typedef int		(*xfs_ioinit_t)(struct xfs_vfs *,
    -				struct xfs_mount_args *, int);
    -typedef int		(*xfs_bmapi_t)(struct xfs_trans *, void *,
    -				xfs_fileoff_t, xfs_filblks_t, int,
    -				xfs_fsblock_t *, xfs_extlen_t,
    -				struct xfs_bmbt_irec *, int *,
    -				struct xfs_bmap_free *, struct xfs_extdelta *);
    -typedef int		(*xfs_bunmapi_t)(struct xfs_trans *,
    -				void *, xfs_fileoff_t,
    -				xfs_filblks_t, int, xfs_extnum_t,
    -				xfs_fsblock_t *, struct xfs_bmap_free *,
    -				struct xfs_extdelta *, int *);
    -typedef int		(*xfs_bmap_eof_t)(void *, xfs_fileoff_t, int, int *);
    -typedef int		(*xfs_iomap_write_direct_t)(
    -				void *, xfs_off_t, size_t, int,
    -				struct xfs_bmbt_irec *, int *, int);
    -typedef int		(*xfs_iomap_write_delay_t)(
    -				void *, xfs_off_t, size_t, int,
    -				struct xfs_bmbt_irec *, int *);
    -typedef int		(*xfs_iomap_write_allocate_t)(
    -				void *, xfs_off_t, size_t,
    -				struct xfs_bmbt_irec *, int *);
    -typedef int		(*xfs_iomap_write_unwritten_t)(
    -				void *, xfs_off_t, size_t);
    -typedef uint		(*xfs_lck_map_shared_t)(void *);
    -typedef void		(*xfs_lock_t)(void *, uint);
    -typedef void		(*xfs_lock_demote_t)(void *, uint);
    -typedef int		(*xfs_lock_nowait_t)(void *, uint);
    -typedef void		(*xfs_unlk_t)(void *, unsigned int);
    -typedef xfs_fsize_t	(*xfs_size_t)(void *);
    -typedef xfs_fsize_t	(*xfs_iodone_t)(struct xfs_vfs *);
    -typedef int		(*xfs_swap_extents_t)(void *, void *,
    -				struct xfs_swapext*);
    -
    -typedef struct xfs_ioops {
    -	xfs_ioinit_t			xfs_ioinit;
    -	xfs_bmapi_t			xfs_bmapi_func;
    -	xfs_bunmapi_t			xfs_bunmapi_func;
    -	xfs_bmap_eof_t			xfs_bmap_eof_func;
    -	xfs_iomap_write_direct_t	xfs_iomap_write_direct;
    -	xfs_iomap_write_delay_t		xfs_iomap_write_delay;
    -	xfs_iomap_write_allocate_t	xfs_iomap_write_allocate;
    -	xfs_iomap_write_unwritten_t	xfs_iomap_write_unwritten;
    -	xfs_lock_t			xfs_ilock;
    -	xfs_lck_map_shared_t		xfs_lck_map_shared;
    -	xfs_lock_demote_t		xfs_ilock_demote;
    -	xfs_lock_nowait_t		xfs_ilock_nowait;
    -	xfs_unlk_t			xfs_unlock;
    -	xfs_size_t			xfs_size_func;
    -	xfs_iodone_t			xfs_iodone;
    -	xfs_swap_extents_t		xfs_swap_extents_func;
    -} xfs_ioops_t;
    -
    -#define XFS_IOINIT(vfsp, args, flags) \
    -	(*(mp)->m_io_ops.xfs_ioinit)(vfsp, args, flags)
    -#define XFS_BMAPI(mp, trans,io,bno,len,f,first,tot,mval,nmap,flist,delta) \
    -	(*(mp)->m_io_ops.xfs_bmapi_func) \
    -		(trans,(io)->io_obj,bno,len,f,first,tot,mval,nmap,flist,delta)
    -#define XFS_BUNMAPI(mp, trans,io,bno,len,f,nexts,first,flist,delta,done) \
    -	(*(mp)->m_io_ops.xfs_bunmapi_func) \
    -		(trans,(io)->io_obj,bno,len,f,nexts,first,flist,delta,done)
    -#define XFS_BMAP_EOF(mp, io, endoff, whichfork, eof) \
    -	(*(mp)->m_io_ops.xfs_bmap_eof_func) \
    -		((io)->io_obj, endoff, whichfork, eof)
    -#define XFS_IOMAP_WRITE_DIRECT(mp, io, offset, count, flags, mval, nmap, found)\
    -	(*(mp)->m_io_ops.xfs_iomap_write_direct) \
    -		((io)->io_obj, offset, count, flags, mval, nmap, found)
    -#define XFS_IOMAP_WRITE_DELAY(mp, io, offset, count, flags, mval, nmap) \
    -	(*(mp)->m_io_ops.xfs_iomap_write_delay) \
    -		((io)->io_obj, offset, count, flags, mval, nmap)
    -#define XFS_IOMAP_WRITE_ALLOCATE(mp, io, offset, count, mval, nmap) \
    -	(*(mp)->m_io_ops.xfs_iomap_write_allocate) \
    -		((io)->io_obj, offset, count, mval, nmap)
    -#define XFS_IOMAP_WRITE_UNWRITTEN(mp, io, offset, count) \
    -	(*(mp)->m_io_ops.xfs_iomap_write_unwritten) \
    -		((io)->io_obj, offset, count)
    -#define XFS_LCK_MAP_SHARED(mp, io) \
    -	(*(mp)->m_io_ops.xfs_lck_map_shared)((io)->io_obj)
    -#define XFS_ILOCK(mp, io, mode) \
    -	(*(mp)->m_io_ops.xfs_ilock)((io)->io_obj, mode)
    -#define XFS_ILOCK_NOWAIT(mp, io, mode) \
    -	(*(mp)->m_io_ops.xfs_ilock_nowait)((io)->io_obj, mode)
    -#define XFS_IUNLOCK(mp, io, mode) \
    -	(*(mp)->m_io_ops.xfs_unlock)((io)->io_obj, mode)
    -#define XFS_ILOCK_DEMOTE(mp, io, mode) \
    -	(*(mp)->m_io_ops.xfs_ilock_demote)((io)->io_obj, mode)
    -#define XFS_SIZE(mp, io) \
    -	(*(mp)->m_io_ops.xfs_size_func)((io)->io_obj)
    -#define XFS_IODONE(vfsp) \
    -	(*(mp)->m_io_ops.xfs_iodone)(vfsp)
    -#define XFS_SWAP_EXTENTS(mp, io, tio, sxp) \
    -	(*(mp)->m_io_ops.xfs_swap_extents_func) \
    -		((io)->io_obj, (tio)->io_obj, sxp)
    -
    -#ifdef HAVE_PERCPU_SB
    -
    -/*
    - * Valid per-cpu incore superblock counters. Note that if you add new counters,
    - * you may need to define new counter disabled bit field descriptors as there
    - * are more possible fields in the superblock that can fit in a bitfield on a
    - * 32 bit platform. The XFS_SBS_* values for the current current counters just
    - * fit.
    - */
    -typedef struct xfs_icsb_cnts {
    -	uint64_t	icsb_fdblocks;
    -	uint64_t	icsb_ifree;
    -	uint64_t	icsb_icount;
    -	unsigned long	icsb_flags;
    -} xfs_icsb_cnts_t;
    -
    -#define XFS_ICSB_FLAG_LOCK	(1 << 0)	/* counter lock bit */
    -
    -#define XFS_ICSB_SB_LOCKED	(1 << 0)	/* sb already locked */
    -#define XFS_ICSB_LAZY_COUNT	(1 << 1)	/* accuracy not needed */
    -
    -extern int	xfs_icsb_init_counters(struct xfs_mount *);
    -extern void	xfs_icsb_sync_counters_lazy(struct xfs_mount *);
    -
    -#else
    -#define xfs_icsb_init_counters(mp)	(0)
    -#define xfs_icsb_sync_counters_lazy(mp)	do { } while (0)
    -#endif
    -
    -typedef struct xfs_mount {
    -	bhv_desc_t		m_bhv;		/* vfs xfs behavior */
    -	xfs_tid_t		m_tid;		/* next unused tid for fs */
    -	AIL_LOCK_T		m_ail_lock;	/* fs AIL mutex */
    -	xfs_ail_entry_t		m_ail;		/* fs active log item list */
    -	uint			m_ail_gen;	/* fs AIL generation count */
    -	xfs_sb_t		m_sb;		/* copy of fs superblock */
    -	lock_t			m_sb_lock;	/* sb counter mutex */
    -	struct xfs_buf		*m_sb_bp;	/* buffer for superblock */
    -	char			*m_fsname;	/* filesystem name */
    -	int			m_fsname_len;	/* strlen of fs name */
    -	char			*m_rtname;	/* realtime device name */
    -	char			*m_logname;	/* external log device name */
    -	int			m_bsize;	/* fs logical block size */
    -	xfs_agnumber_t		m_agfrotor;	/* last ag where space found */
    -	xfs_agnumber_t		m_agirotor;	/* last ag dir inode alloced */
    -	lock_t			m_agirotor_lock;/* .. and lock protecting it */
    -	xfs_agnumber_t		m_maxagi;	/* highest inode alloc group */
    -	uint			m_ihsize;	/* size of next field */
    -	struct xfs_ihash	*m_ihash;	/* fs private inode hash table*/
    -	struct xfs_inode	*m_inodes;	/* active inode list */
    -	TAILQ_HEAD(,xfs_inode)	m_del_inodes;	/* inodes to reclaim */
    -  //	xfs_mutex_t		m_ilock;	/* inode list mutex */
    -	/* FreeBSD specfic */
    -  	struct sx		m_ilock;	/* inode list mutex */
    -	uint			m_ireclaims;	/* count of calls to reclaim*/
    -	uint			m_readio_log;	/* min read size log bytes */
    -	uint			m_readio_blocks; /* min read size blocks */
    -	uint			m_writeio_log;	/* min write size log bytes */
    -	uint			m_writeio_blocks; /* min write size blocks */
    -	struct log		*m_log;		/* log specific stuff */
    -	int			m_logbufs;	/* number of log buffers */
    -	int			m_logbsize;	/* size of each log buffer */
    -	uint			m_rsumlevels;	/* rt summary levels */
    -	uint			m_rsumsize;	/* size of rt summary, bytes */
    -	struct xfs_inode	*m_rbmip;	/* pointer to bitmap inode */
    -	struct xfs_inode	*m_rsumip;	/* pointer to summary inode */
    -	struct xfs_inode	*m_rootip;	/* pointer to root directory */
    -	struct xfs_quotainfo	*m_quotainfo;	/* disk quota information */
    -	xfs_buftarg_t		*m_ddev_targp;	/* saves taking the address */
    -	xfs_buftarg_t		*m_logdev_targp;/* ptr to log device */
    -	xfs_buftarg_t		*m_rtdev_targp;	/* ptr to rt device */
    -	__uint8_t		m_dircook_elog;	/* log d-cookie entry bits */
    -	__uint8_t		m_blkbit_log;	/* blocklog + NBBY */
    -	__uint8_t		m_blkbb_log;	/* blocklog - BBSHIFT */
    -	__uint8_t		m_agno_log;	/* log #ag's */
    -	__uint8_t		m_agino_log;	/* #bits for agino in inum */
    -	__uint8_t		m_nreadaheads;	/* #readahead buffers */
    -	__uint16_t		m_inode_cluster_size;/* min inode buf size */
    -	uint			m_blockmask;	/* sb_blocksize-1 */
    -	uint			m_blockwsize;	/* sb_blocksize in words */
    -	uint			m_blockwmask;	/* blockwsize-1 */
    -	uint			m_alloc_mxr[2];	/* XFS_ALLOC_BLOCK_MAXRECS */
    -	uint			m_alloc_mnr[2];	/* XFS_ALLOC_BLOCK_MINRECS */
    -	uint			m_bmap_dmxr[2];	/* XFS_BMAP_BLOCK_DMAXRECS */
    -	uint			m_bmap_dmnr[2];	/* XFS_BMAP_BLOCK_DMINRECS */
    -	uint			m_inobt_mxr[2];	/* XFS_INOBT_BLOCK_MAXRECS */
    -	uint			m_inobt_mnr[2];	/* XFS_INOBT_BLOCK_MINRECS */
    -	uint			m_ag_maxlevels;	/* XFS_AG_MAXLEVELS */
    -	uint			m_bm_maxlevels[2]; /* XFS_BM_MAXLEVELS */
    -	uint			m_in_maxlevels;	/* XFS_IN_MAXLEVELS */
    -	struct xfs_perag	*m_perag;	/* per-ag accounting info */
    -	struct rw_semaphore	m_peraglock;	/* lock for m_perag (pointer) */
    -	sema_t			m_growlock;	/* growfs mutex */
    -	int			m_fixedfsid[2];	/* unchanged for life of FS */
    -	uint			m_dmevmask;	/* DMI events for this FS */
    -	__uint64_t		m_flags;	/* global mount flags */
    -	uint			m_attroffset;	/* inode attribute offset */
    -	uint			m_dir_node_ents; /* #entries in a dir danode */
    -	uint			m_attr_node_ents; /* #entries in attr danode */
    -	int			m_ialloc_inos;	/* inodes in inode allocation */
    -	int			m_ialloc_blks;	/* blocks in inode allocation */
    -	int			m_litino;	/* size of inode union area */
    -	int			m_inoalign_mask;/* mask sb_inoalignmt if used */
    -	uint			m_qflags;	/* quota status flags */
    -	xfs_trans_reservations_t m_reservations;/* precomputed res values */
    -	__uint64_t		m_maxicount;	/* maximum inode count */
    -	__uint64_t		m_maxioffset;	/* maximum inode offset */
    -	__uint64_t		m_resblks;	/* total reserved blocks */
    -	__uint64_t		m_resblks_avail;/* available reserved blocks */
    -#if XFS_BIG_INUMS
    -	xfs_ino_t		m_inoadd;	/* add value for ino64_offset */
    -#endif
    -	int			m_dalign;	/* stripe unit */
    -	int			m_swidth;	/* stripe width */
    -	int			m_sinoalign;	/* stripe unit inode alignment */
    -	int			m_attr_magicpct;/* 37% of the blocksize */
    -	int			m_dir_magicpct;	/* 37% of the dir blocksize */
    -	__uint8_t		m_mk_sharedro;	/* mark shared ro on unmount */
    -	__uint8_t		m_inode_quiesce;/* call quiesce on new inodes.
    -						   field governed by m_ilock */
    -	__uint8_t		m_sectbb_log;	/* sectlog - BBSHIFT */
    -	__uint8_t		m_dirversion;	/* 1 or 2 */
    -	xfs_dirops_t		m_dirops;	/* table of dir funcs */
    -	int			m_dirblksize;	/* directory block sz--bytes */
    -	int			m_dirblkfsbs;	/* directory block sz--fsbs */
    -	xfs_dablk_t		m_dirdatablk;	/* blockno of dir data v2 */
    -	xfs_dablk_t		m_dirleafblk;	/* blockno of dir non-data v2 */
    -	xfs_dablk_t		m_dirfreeblk;	/* blockno of dirfreeindex v2 */
    -	uint			m_chsize;	/* size of next field */
    -	struct xfs_chash	*m_chash;	/* fs private inode per-cluster
    -						 * hash table */
    -	struct xfs_dmops	m_dm_ops;	/* vector of DMI ops */
    -	struct xfs_qmops	m_qm_ops;	/* vector of XQM ops */
    -	struct xfs_ioops	m_io_ops;	/* vector of I/O ops */
    -	atomic_t		m_active_trans;	/* number trans frozen */
    -#ifdef HAVE_PERCPU_SB
    -	xfs_icsb_cnts_t		*m_sb_cnts;	/* per-cpu superblock counters */
    -	unsigned long		m_icsb_counters; /* disabled per-cpu counters */
    -	struct notifier_block	m_icsb_notifier; /* hotplug cpu notifier */
    -#endif
    -} xfs_mount_t;
    -
    -/*
    - * Flags for m_flags.
    - */
    -#define	XFS_MOUNT_WSYNC		(1ULL << 0)	/* for nfs - all metadata ops
    -						   must be synchronous except
    -						   for space allocations */
    -#define	XFS_MOUNT_INO64		(1ULL << 1)
    -			     /* (1ULL << 2)	-- currently unused */
    -			     /* (1ULL << 3)	-- currently unused */
    -#define XFS_MOUNT_FS_SHUTDOWN	(1ULL << 4)	/* atomic stop of all filesystem
    -						   operations, typically for
    -						   disk errors in metadata */
    -#define XFS_MOUNT_RETERR	(1ULL << 6)     /* return alignment errors to
    -						   user */
    -#define XFS_MOUNT_NOALIGN	(1ULL << 7)	/* turn off stripe alignment
    -						   allocations */
    -#define XFS_MOUNT_ATTR2		(1ULL << 8)	/* allow use of attr2 format */
    -			     /*	(1ULL << 9)	-- currently unused */
    -#define XFS_MOUNT_NORECOVERY	(1ULL << 10)	/* no recovery - dirty fs */
    -#define XFS_MOUNT_SHARED	(1ULL << 11)	/* shared mount */
    -#define XFS_MOUNT_DFLT_IOSIZE	(1ULL << 12)	/* set default i/o size */
    -#define XFS_MOUNT_OSYNCISOSYNC	(1ULL << 13)	/* o_sync is REALLY o_sync */
    -						/* osyncisdsync is now default*/
    -#define XFS_MOUNT_32BITINODES	(1ULL << 14)	/* do not create inodes above
    -						 * 32 bits in size */
    -			     /* (1ULL << 15)	-- currently unused */
    -#define XFS_MOUNT_NOUUID	(1ULL << 16)	/* ignore uuid during mount */
    -#define XFS_MOUNT_BARRIER	(1ULL << 17)
    -#define XFS_MOUNT_IDELETE	(1ULL << 18)	/* delete empty inode clusters*/
    -#define XFS_MOUNT_SWALLOC	(1ULL << 19)	/* turn on stripe width
    -						 * allocation */
    -#define XFS_MOUNT_IHASHSIZE	(1ULL << 20)	/* inode hash table size */
    -#define XFS_MOUNT_DIRSYNC	(1ULL << 21)	/* synchronous directory ops */
    -#define XFS_MOUNT_COMPAT_IOSIZE	(1ULL << 22)	/* don't report large preferred
    -						 * I/O size in stat() */
    -#define XFS_MOUNT_NO_PERCPU_SB	(1ULL << 23)	/* don't use per-cpu superblock
    -						   counters */
    -
    -
    -/*
    - * Default minimum read and write sizes.
    - */
    -#define XFS_READIO_LOG_LARGE	16
    -#define XFS_WRITEIO_LOG_LARGE	16
    -
    -/*
    - * Max and min values for mount-option defined I/O
    - * preallocation sizes.
    - */
    -#define XFS_MAX_IO_LOG		30	/* 1G */
    -#define XFS_MIN_IO_LOG		PAGE_SHIFT
    -
    -/*
    - * Synchronous read and write sizes.  This should be
    - * better for NFSv2 wsync filesystems.
    - */
    -#define	XFS_WSYNC_READIO_LOG	15	/* 32K */
    -#define	XFS_WSYNC_WRITEIO_LOG	14	/* 16K */
    -
    -/*
    - * Allow large block sizes to be reported to userspace programs if the
    - * "largeio" mount option is used. 
    - *
    - * If compatibility mode is specified, simply return the basic unit of caching
    - * so that we don't get inefficient read/modify/write I/O from user apps.
    - * Otherwise....
    - *
    - * If the underlying volume is a stripe, then return the stripe width in bytes
    - * as the recommended I/O size. It is not a stripe and we've set a default
    - * buffered I/O size, return that, otherwise return the compat default.
    - */
    -static inline unsigned long
    -xfs_preferred_iosize(xfs_mount_t *mp)
    -{
    -	if (mp->m_flags & XFS_MOUNT_COMPAT_IOSIZE)
    -		return PAGE_CACHE_SIZE;
    -	return (mp->m_swidth ?
    -		(mp->m_swidth << mp->m_sb.sb_blocklog) :
    -		((mp->m_flags & XFS_MOUNT_DFLT_IOSIZE) ?
    -			(1 << (int)MAX(mp->m_readio_log, mp->m_writeio_log)) :
    -			PAGE_CACHE_SIZE));
    -}
    -
    -#define XFS_MAXIOFFSET(mp)	((mp)->m_maxioffset)
    -
    -#define XFS_FORCED_SHUTDOWN(mp)	((mp)->m_flags & XFS_MOUNT_FS_SHUTDOWN)
    -#define xfs_force_shutdown(m,f)	\
    -	XVFS_FORCE_SHUTDOWN((XFS_MTOVFS(m)), f, __FILE__, __LINE__)
    -
    -/*
    - * Flags sent to xfs_force_shutdown.
    - */
    -#define XFS_METADATA_IO_ERROR	0x1
    -#define XFS_LOG_IO_ERROR	0x2
    -#define XFS_FORCE_UMOUNT	0x4
    -#define XFS_CORRUPT_INCORE	0x8	/* Corrupt in-memory data structures */
    -#define XFS_SHUTDOWN_REMOTE_REQ 0x10	/* Shutdown came from remote cell */
    -
    -/*
    - * Flags for xfs_mountfs
    - */
    -#define XFS_MFSI_SECOND		0x01	/* Secondary mount -- skip stuff */
    -#define XFS_MFSI_CLIENT		0x02	/* Is a client -- skip lots of stuff */
    -/*	XFS_MFSI_RRINODES	*/
    -#define XFS_MFSI_NOUNLINK	0x08	/* Skip unlinked inode processing in */
    -					/* log recovery */
    -#define XFS_MFSI_NO_QUOTACHECK	0x10	/* Skip quotacheck processing */
    -/*	XFS_MFSI_CONVERT_SUNIT	*/
    -#define XFS_MFSI_QUIET		0x40	/* Be silent if mount errors found */
    -
    -/*
    - * Macros for getting from mount to vfs and back.
    - */
    -#define	XFS_MTOVFS(mp)		xfs_mtovfs(mp)
    -static inline xfs_vfs_t *xfs_mtovfs(xfs_mount_t *mp)
    -{
    -	return bhvtovfs(&mp->m_bhv);
    -}
    -
    -#define	XFS_BHVTOM(bdp)	xfs_bhvtom(bdp)
    -static inline xfs_mount_t *xfs_bhvtom(bhv_desc_t *bdp)
    -{
    -	return (xfs_mount_t *)BHV_PDATA(bdp);
    -}
    -
    -#define XFS_VFSTOM(vfs) xfs_vfstom(vfs)
    -static inline xfs_mount_t *xfs_vfstom(xfs_vfs_t *vfs)
    -{
    -	return XFS_BHVTOM(bhv_lookup(VFS_BHVHEAD(vfs), &xfs_vfsops));
    -}
    -
    -#define XFS_DADDR_TO_AGNO(mp,d)         xfs_daddr_to_agno(mp,d)
    -static inline xfs_agnumber_t
    -xfs_daddr_to_agno(struct xfs_mount *mp, xfs_daddr_t d)
    -{
    -	xfs_daddr_t ld = XFS_BB_TO_FSBT(mp, d);
    -	do_div(ld, mp->m_sb.sb_agblocks);
    -	return (xfs_agnumber_t) ld;
    -}
    -
    -#define XFS_DADDR_TO_AGBNO(mp,d)        xfs_daddr_to_agbno(mp,d)
    -static inline xfs_agblock_t
    -xfs_daddr_to_agbno(struct xfs_mount *mp, xfs_daddr_t d)
    -{
    -	xfs_daddr_t ld = XFS_BB_TO_FSBT(mp, d);
    -	return (xfs_agblock_t) do_div(ld, mp->m_sb.sb_agblocks);
    -}
    -
    -/*
    - * This structure is for use by the xfs_mod_incore_sb_batch() routine.
    - */
    -typedef struct xfs_mod_sb {
    -	xfs_sb_field_t	msb_field;	/* Field to modify, see below */
    -	int		msb_delta;	/* Change to make to specified field */
    -} xfs_mod_sb_t;
    -
    -/* FreeBSD specfic */
    -#define	XFS_MOUNT_ILOCK(mp)	sx_xlock(&((mp)->m_ilock))
    -#define	XFS_MOUNT_IUNLOCK(mp)	sx_xunlock(&((mp)->m_ilock))
    -
    -#define	XFS_SB_LOCK(mp)		mutex_spinlock(&(mp)->m_sb_lock)
    -#define	XFS_SB_UNLOCK(mp,s)	mutex_spinunlock(&(mp)->m_sb_lock,(s))
    -
    -extern xfs_mount_t *xfs_mount_init(void);
    -extern void	xfs_mod_sb(xfs_trans_t *, __int64_t);
    -extern void	xfs_mount_free(xfs_mount_t *mp, int remove_bhv);
    -extern int	xfs_mountfs(struct xfs_vfs *, xfs_mount_t *mp, int);
    -extern void	xfs_mountfs_check_barriers(xfs_mount_t *mp);
    -
    -extern int	xfs_unmountfs(xfs_mount_t *, struct cred *);
    -extern void	xfs_unmountfs_close(xfs_mount_t *, struct cred *);
    -extern int	xfs_unmountfs_writesb(xfs_mount_t *);
    -extern int	xfs_unmount_flush(xfs_mount_t *, int);
    -extern int	xfs_mod_incore_sb(xfs_mount_t *, xfs_sb_field_t, int, int);
    -extern int	xfs_mod_incore_sb_unlocked(xfs_mount_t *, xfs_sb_field_t,
    -			int, int);
    -extern int	xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *,
    -			uint, int);
    -extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int);
    -extern int	xfs_readsb(xfs_mount_t *, int);
    -extern void	xfs_freesb(xfs_mount_t *);
    -extern void	xfs_do_force_shutdown(bhv_desc_t *, int, char *, int);
    -extern int	xfs_syncsub(xfs_mount_t *, int, int, int *);
    -extern int	xfs_sync_inodes(xfs_mount_t *, int, int, int *);
    -extern xfs_agnumber_t	xfs_initialize_perag(struct xfs_vfs *, xfs_mount_t *,
    -						xfs_agnumber_t);
    -extern void	xfs_xlatesb(void *, struct xfs_sb *, int, __int64_t);
    -
    -extern struct xfs_dmops xfs_dmcore_stub;
    -extern struct xfs_qmops xfs_qmcore_stub;
    -extern struct xfs_ioops xfs_iocore_xfs;
    -
    -extern int	xfs_init(void);
    -extern void	xfs_cleanup(void);
    -
    -#endif	/* __KERNEL__ */
    -
    -#endif	/* __XFS_MOUNT_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_qmops.c b/sys/gnu/fs/xfs/xfs_qmops.c
    deleted file mode 100644
    index 1408a32eef8..00000000000
    --- a/sys/gnu/fs/xfs/xfs_qmops.c
    +++ /dev/null
    @@ -1,128 +0,0 @@
    -/*
    - * Copyright (c) 2000-2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_quota.h"
    -#include "xfs_error.h"
    -
    -STATIC struct xfs_dquot *
    -xfs_dqvopchown_default(
    -	struct xfs_trans	*tp,
    -	struct xfs_inode	*ip,
    -	struct xfs_dquot	**dqp,
    -	struct xfs_dquot	*dq)
    -{
    -	return NULL;
    -}
    -
    -/*
    - * Clear the quotaflags in memory and in the superblock.
    - */
    -int
    -xfs_mount_reset_sbqflags(xfs_mount_t *mp)
    -{
    -	int			error;
    -	xfs_trans_t		*tp;
    -	unsigned long		s;
    -
    -	mp->m_qflags = 0;
    -	/*
    -	 * It is OK to look at sb_qflags here in mount path,
    -	 * without SB_LOCK.
    -	 */
    -	if (mp->m_sb.sb_qflags == 0)
    -		return 0;
    -	s = XFS_SB_LOCK(mp);
    -	mp->m_sb.sb_qflags = 0;
    -	XFS_SB_UNLOCK(mp, s);
    -
    -	/*
    -	 * if the fs is readonly, let the incore superblock run
    -	 * with quotas off but don't flush the update out to disk
    -	 */
    -	if (XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY)
    -		return 0;
    -#ifdef QUOTADEBUG
    -	xfs_fs_cmn_err(CE_NOTE, mp, "Writing superblock quota changes");
    -#endif
    -	tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SBCHANGE);
    -	if ((error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0,
    -				      XFS_DEFAULT_LOG_COUNT))) {
    -		xfs_trans_cancel(tp, 0);
    -		xfs_fs_cmn_err(CE_ALERT, mp,
    -			"xfs_mount_reset_sbqflags: Superblock update failed!");
    -		return error;
    -	}
    -	xfs_mod_sb(tp, XFS_SB_QFLAGS);
    -	error = xfs_trans_commit(tp, 0, NULL);
    -	return error;
    -}
    -
    -STATIC int
    -xfs_noquota_init(
    -	xfs_mount_t	*mp,
    -	uint		*needquotamount,
    -	uint		*quotaflags)
    -{
    -	int		error = 0;
    -
    -	*quotaflags = 0;
    -	*needquotamount = B_FALSE;
    -
    -	ASSERT(!XFS_IS_QUOTA_ON(mp));
    -
    -	/*
    -	 * If a file system had quotas running earlier, but decided to
    -	 * mount without -o uquota/pquota/gquota options, revoke the
    -	 * quotachecked license.
    -	 */
    -	if (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_ACCT) {
    -		cmn_err(CE_NOTE,
    -                        "XFS resetting qflags for filesystem %s",
    -                        mp->m_fsname);
    -
    -		error = xfs_mount_reset_sbqflags(mp);
    -	}
    -	return error;
    -}
    -
    -xfs_qmops_t	xfs_qmcore_stub = {
    -	.xfs_qminit		= (xfs_qminit_t) xfs_noquota_init,
    -	.xfs_qmdone		= (xfs_qmdone_t) fs_noerr,
    -	.xfs_qmmount		= (xfs_qmmount_t) fs_noerr,
    -	.xfs_qmunmount		= (xfs_qmunmount_t) fs_noerr,
    -	.xfs_dqrele		= (xfs_dqrele_t) fs_noerr,
    -	.xfs_dqattach		= (xfs_dqattach_t) fs_noerr,
    -	.xfs_dqdetach		= (xfs_dqdetach_t) fs_noerr,
    -	.xfs_dqpurgeall		= (xfs_dqpurgeall_t) fs_noerr,
    -	.xfs_dqvopalloc		= (xfs_dqvopalloc_t) fs_noerr,
    -	.xfs_dqvopcreate	= (xfs_dqvopcreate_t) fs_noerr,
    -	.xfs_dqvoprename	= (xfs_dqvoprename_t) fs_noerr,
    -	.xfs_dqvopchown		= xfs_dqvopchown_default,
    -	.xfs_dqvopchownresv	= (xfs_dqvopchownresv_t) fs_noerr,
    -};
    diff --git a/sys/gnu/fs/xfs/xfs_quota.h b/sys/gnu/fs/xfs/xfs_quota.h
    deleted file mode 100644
    index 7fbef974bce..00000000000
    --- a/sys/gnu/fs/xfs/xfs_quota.h
    +++ /dev/null
    @@ -1,372 +0,0 @@
    -/*
    - * Copyright (c) 2000-2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_QUOTA_H__
    -#define __XFS_QUOTA_H__
    -
    -/*
    - * The ondisk form of a dquot structure.
    - */
    -#define XFS_DQUOT_MAGIC		0x4451		/* 'DQ' */
    -#define XFS_DQUOT_VERSION	(u_int8_t)0x01	/* latest version number */
    -
    -/*
    - * uid_t and gid_t are hard-coded to 32 bits in the inode.
    - * Hence, an 'id' in a dquot is 32 bits..
    - */
    -typedef __uint32_t	xfs_dqid_t;
    -
    -/*
    - * Even though users may not have quota limits occupying all 64-bits,
    - * they may need 64-bit accounting. Hence, 64-bit quota-counters,
    - * and quota-limits. This is a waste in the common case, but hey ...
    - */
    -typedef __uint64_t	xfs_qcnt_t;
    -typedef __uint16_t	xfs_qwarncnt_t;
    -
    -/*
    - * This is the main portion of the on-disk representation of quota
    - * information for a user. This is the q_core of the xfs_dquot_t that
    - * is kept in kernel memory. We pad this with some more expansion room
    - * to construct the on disk structure.
    - */
    -typedef struct	xfs_disk_dquot {
    -	__be16		d_magic;	/* dquot magic = XFS_DQUOT_MAGIC */
    -	__u8		d_version;	/* dquot version */
    -	__u8		d_flags;	/* XFS_DQ_USER/PROJ/GROUP */
    -	__be32		d_id;		/* user,project,group id */
    -	__be64		d_blk_hardlimit;/* absolute limit on disk blks */
    -	__be64		d_blk_softlimit;/* preferred limit on disk blks */
    -	__be64		d_ino_hardlimit;/* maximum # allocated inodes */
    -	__be64		d_ino_softlimit;/* preferred inode limit */
    -	__be64		d_bcount;	/* disk blocks owned by the user */
    -	__be64		d_icount;	/* inodes owned by the user */
    -	__be32		d_itimer;	/* zero if within inode limits if not,
    -					   this is when we refuse service */
    -	__be32		d_btimer;	/* similar to above; for disk blocks */
    -	__be16		d_iwarns;	/* warnings issued wrt num inodes */
    -	__be16		d_bwarns;	/* warnings issued wrt disk blocks */
    -	__be32		d_pad0;		/* 64 bit align */
    -	__be64		d_rtb_hardlimit;/* absolute limit on realtime blks */
    -	__be64		d_rtb_softlimit;/* preferred limit on RT disk blks */
    -	__be64		d_rtbcount;	/* realtime blocks owned */
    -	__be32		d_rtbtimer;	/* similar to above; for RT disk blocks */
    -	__be16		d_rtbwarns;	/* warnings issued wrt RT disk blocks */
    -	__be16		d_pad;
    -} xfs_disk_dquot_t;
    -
    -/*
    - * This is what goes on disk. This is separated from the xfs_disk_dquot because
    - * carrying the unnecessary padding would be a waste of memory.
    - */
    -typedef struct xfs_dqblk {
    -	xfs_disk_dquot_t  dd_diskdq;	/* portion that lives incore as well */
    -	char		  dd_fill[32];	/* filling for posterity */
    -} xfs_dqblk_t;
    -
    -/*
    - * flags for q_flags field in the dquot.
    - */
    -#define XFS_DQ_USER		0x0001		/* a user quota */
    -#define XFS_DQ_PROJ		0x0002		/* project quota */
    -#define XFS_DQ_GROUP		0x0004		/* a group quota */
    -#define XFS_DQ_FLOCKED		0x0008		/* flush lock taken */
    -#define XFS_DQ_DIRTY		0x0010		/* dquot is dirty */
    -#define XFS_DQ_WANT		0x0020		/* for lookup/reclaim race */
    -#define XFS_DQ_INACTIVE		0x0040		/* dq off mplist & hashlist */
    -#define XFS_DQ_MARKER		0x0080		/* sentinel */
    -
    -#define XFS_DQ_ALLTYPES		(XFS_DQ_USER|XFS_DQ_PROJ|XFS_DQ_GROUP)
    -
    -/*
    - * In the worst case, when both user and group quotas are on,
    - * we can have a max of three dquots changing in a single transaction.
    - */
    -#define XFS_DQUOT_LOGRES(mp)	(sizeof(xfs_disk_dquot_t) * 3)
    -
    -
    -/*
    - * These are the structures used to lay out dquots and quotaoff
    - * records on the log. Quite similar to those of inodes.
    - */
    -
    -/*
    - * log format struct for dquots.
    - * The first two fields must be the type and size fitting into
    - * 32 bits : log_recovery code assumes that.
    - */
    -typedef struct xfs_dq_logformat {
    -	__uint16_t		qlf_type;      /* dquot log item type */
    -	__uint16_t		qlf_size;      /* size of this item */
    -	xfs_dqid_t		qlf_id;	       /* usr/grp/proj id : 32 bits */
    -	__int64_t		qlf_blkno;     /* blkno of dquot buffer */
    -	__int32_t		qlf_len;       /* len of dquot buffer */
    -	__uint32_t		qlf_boffset;   /* off of dquot in buffer */
    -} xfs_dq_logformat_t;
    -
    -/*
    - * log format struct for QUOTAOFF records.
    - * The first two fields must be the type and size fitting into
    - * 32 bits : log_recovery code assumes that.
    - * We write two LI_QUOTAOFF logitems per quotaoff, the last one keeps a pointer
    - * to the first and ensures that the first logitem is taken out of the AIL
    - * only when the last one is securely committed.
    - */
    -typedef struct xfs_qoff_logformat {
    -	unsigned short		qf_type;	/* quotaoff log item type */
    -	unsigned short		qf_size;	/* size of this item */
    -	unsigned int		qf_flags;	/* USR and/or GRP */
    -	char			qf_pad[12];	/* padding for future */
    -} xfs_qoff_logformat_t;
    -
    -
    -/*
    - * Disk quotas status in m_qflags, and also sb_qflags. 16 bits.
    - */
    -#define XFS_UQUOTA_ACCT	0x0001  /* user quota accounting ON */
    -#define XFS_UQUOTA_ENFD	0x0002  /* user quota limits enforced */
    -#define XFS_UQUOTA_CHKD	0x0004  /* quotacheck run on usr quotas */
    -#define XFS_PQUOTA_ACCT	0x0008  /* project quota accounting ON */
    -#define XFS_OQUOTA_ENFD	0x0010  /* other (grp/prj) quota limits enforced */
    -#define XFS_OQUOTA_CHKD	0x0020  /* quotacheck run on other (grp/prj) quotas */
    -#define XFS_GQUOTA_ACCT	0x0040  /* group quota accounting ON */
    -
    -/*
    - * Quota Accounting/Enforcement flags
    - */
    -#define XFS_ALL_QUOTA_ACCT	\
    -		(XFS_UQUOTA_ACCT | XFS_GQUOTA_ACCT | XFS_PQUOTA_ACCT)
    -#define XFS_ALL_QUOTA_ENFD	(XFS_UQUOTA_ENFD | XFS_OQUOTA_ENFD)
    -#define XFS_ALL_QUOTA_CHKD	(XFS_UQUOTA_CHKD | XFS_OQUOTA_CHKD)
    -
    -#define XFS_IS_QUOTA_RUNNING(mp)	((mp)->m_qflags & XFS_ALL_QUOTA_ACCT)
    -#define XFS_IS_QUOTA_ENFORCED(mp)	((mp)->m_qflags & XFS_ALL_QUOTA_ENFD)
    -#define XFS_IS_UQUOTA_RUNNING(mp)	((mp)->m_qflags & XFS_UQUOTA_ACCT)
    -#define XFS_IS_PQUOTA_RUNNING(mp)	((mp)->m_qflags & XFS_PQUOTA_ACCT)
    -#define XFS_IS_GQUOTA_RUNNING(mp)	((mp)->m_qflags & XFS_GQUOTA_ACCT)
    -
    -/*
    - * Incore only flags for quotaoff - these bits get cleared when quota(s)
    - * are in the process of getting turned off. These flags are in m_qflags but
    - * never in sb_qflags.
    - */
    -#define XFS_UQUOTA_ACTIVE	0x0100  /* uquotas are being turned off */
    -#define XFS_PQUOTA_ACTIVE	0x0200  /* pquotas are being turned off */
    -#define XFS_GQUOTA_ACTIVE	0x0400  /* gquotas are being turned off */
    -
    -/*
    - * Checking XFS_IS_*QUOTA_ON() while holding any inode lock guarantees
    - * quota will be not be switched off as long as that inode lock is held.
    - */
    -#define XFS_IS_QUOTA_ON(mp)	((mp)->m_qflags & (XFS_UQUOTA_ACTIVE | \
    -						   XFS_GQUOTA_ACTIVE | \
    -						   XFS_PQUOTA_ACTIVE))
    -#define XFS_IS_OQUOTA_ON(mp)	((mp)->m_qflags & (XFS_GQUOTA_ACTIVE | \
    -						   XFS_PQUOTA_ACTIVE))
    -#define XFS_IS_UQUOTA_ON(mp)	((mp)->m_qflags & XFS_UQUOTA_ACTIVE)
    -#define XFS_IS_GQUOTA_ON(mp)	((mp)->m_qflags & XFS_GQUOTA_ACTIVE)
    -#define XFS_IS_PQUOTA_ON(mp)	((mp)->m_qflags & XFS_PQUOTA_ACTIVE)
    -
    -/*
    - * Flags to tell various functions what to do. Not all of these are meaningful
    - * to a single function. None of these XFS_QMOPT_* flags are meant to have
    - * persistent values (ie. their values can and will change between versions)
    - */
    -#define XFS_QMOPT_DQLOCK	0x0000001 /* dqlock */
    -#define XFS_QMOPT_DQALLOC	0x0000002 /* alloc dquot ondisk if needed */
    -#define XFS_QMOPT_UQUOTA	0x0000004 /* user dquot requested */
    -#define XFS_QMOPT_PQUOTA	0x0000008 /* project dquot requested */
    -#define XFS_QMOPT_FORCE_RES	0x0000010 /* ignore quota limits */
    -#define XFS_QMOPT_DQSUSER	0x0000020 /* don't cache super users dquot */
    -#define XFS_QMOPT_SBVERSION	0x0000040 /* change superblock version num */
    -#define XFS_QMOPT_QUOTAOFF	0x0000080 /* quotas are being turned off */
    -#define XFS_QMOPT_UMOUNTING	0x0000100 /* filesys is being unmounted */
    -#define XFS_QMOPT_DOLOG		0x0000200 /* log buf changes (in quotacheck) */
    -#define XFS_QMOPT_DOWARN        0x0000400 /* increase warning cnt if needed */
    -#define XFS_QMOPT_ILOCKED	0x0000800 /* inode is already locked (excl) */
    -#define XFS_QMOPT_DQREPAIR	0x0001000 /* repair dquot if damaged */
    -#define XFS_QMOPT_GQUOTA	0x0002000 /* group dquot requested */
    -#define XFS_QMOPT_ENOSPC	0x0004000 /* enospc instead of edquot (prj) */
    -
    -/*
    - * flags to xfs_trans_mod_dquot to indicate which field needs to be
    - * modified.
    - */
    -#define XFS_QMOPT_RES_REGBLKS	0x0010000
    -#define XFS_QMOPT_RES_RTBLKS	0x0020000
    -#define XFS_QMOPT_BCOUNT	0x0040000
    -#define XFS_QMOPT_ICOUNT	0x0080000
    -#define XFS_QMOPT_RTBCOUNT	0x0100000
    -#define XFS_QMOPT_DELBCOUNT	0x0200000
    -#define XFS_QMOPT_DELRTBCOUNT	0x0400000
    -#define XFS_QMOPT_RES_INOS	0x0800000
    -
    -/*
    - * flags for dqflush and dqflush_all.
    - */
    -#define XFS_QMOPT_SYNC		0x1000000
    -#define XFS_QMOPT_ASYNC		0x2000000
    -#define XFS_QMOPT_DELWRI	0x4000000
    -
    -/*
    - * flags for dqalloc.
    - */
    -#define XFS_QMOPT_INHERIT	0x8000000
    -
    -/*
    - * flags to xfs_trans_mod_dquot.
    - */
    -#define XFS_TRANS_DQ_RES_BLKS	XFS_QMOPT_RES_REGBLKS
    -#define XFS_TRANS_DQ_RES_RTBLKS	XFS_QMOPT_RES_RTBLKS
    -#define XFS_TRANS_DQ_RES_INOS	XFS_QMOPT_RES_INOS
    -#define XFS_TRANS_DQ_BCOUNT	XFS_QMOPT_BCOUNT
    -#define XFS_TRANS_DQ_DELBCOUNT	XFS_QMOPT_DELBCOUNT
    -#define XFS_TRANS_DQ_ICOUNT	XFS_QMOPT_ICOUNT
    -#define XFS_TRANS_DQ_RTBCOUNT	XFS_QMOPT_RTBCOUNT
    -#define XFS_TRANS_DQ_DELRTBCOUNT XFS_QMOPT_DELRTBCOUNT
    -
    -
    -#define XFS_QMOPT_QUOTALL	\
    -		(XFS_QMOPT_UQUOTA | XFS_QMOPT_PQUOTA | XFS_QMOPT_GQUOTA)
    -#define XFS_QMOPT_RESBLK_MASK	(XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_RES_RTBLKS)
    -
    -#ifdef __KERNEL__
    -/*
    - * This check is done typically without holding the inode lock;
    - * that may seem racy, but it is harmless in the context that it is used.
    - * The inode cannot go inactive as long a reference is kept, and
    - * therefore if dquot(s) were attached, they'll stay consistent.
    - * If, for example, the ownership of the inode changes while
    - * we didn't have the inode locked, the appropriate dquot(s) will be
    - * attached atomically.
    - */
    -#define XFS_NOT_DQATTACHED(mp, ip) ((XFS_IS_UQUOTA_ON(mp) &&\
    -				     (ip)->i_udquot == NULL) || \
    -				    (XFS_IS_OQUOTA_ON(mp) && \
    -				     (ip)->i_gdquot == NULL))
    -
    -#define XFS_QM_NEED_QUOTACHECK(mp) \
    -	((XFS_IS_UQUOTA_ON(mp) && \
    -		(mp->m_sb.sb_qflags & XFS_UQUOTA_CHKD) == 0) || \
    -	 (XFS_IS_GQUOTA_ON(mp) && \
    -		((mp->m_sb.sb_qflags & XFS_OQUOTA_CHKD) == 0 || \
    -		 (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT))) || \
    -	 (XFS_IS_PQUOTA_ON(mp) && \
    -		((mp->m_sb.sb_qflags & XFS_OQUOTA_CHKD) == 0 || \
    -		 (mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT))))
    -
    -#define XFS_MOUNT_QUOTA_SET1	(XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
    -				 XFS_UQUOTA_CHKD|XFS_PQUOTA_ACCT|\
    -				 XFS_OQUOTA_ENFD|XFS_OQUOTA_CHKD)
    -
    -#define XFS_MOUNT_QUOTA_SET2	(XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
    -				 XFS_UQUOTA_CHKD|XFS_GQUOTA_ACCT|\
    -				 XFS_OQUOTA_ENFD|XFS_OQUOTA_CHKD)
    -
    -#define XFS_MOUNT_QUOTA_ALL	(XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
    -				 XFS_UQUOTA_CHKD|XFS_PQUOTA_ACCT|\
    -				 XFS_OQUOTA_ENFD|XFS_OQUOTA_CHKD|\
    -				 XFS_GQUOTA_ACCT)
    -#define XFS_MOUNT_QUOTA_MASK	(XFS_MOUNT_QUOTA_ALL | XFS_UQUOTA_ACTIVE | \
    -				 XFS_GQUOTA_ACTIVE | XFS_PQUOTA_ACTIVE)
    -
    -
    -/*
    - * The structure kept inside the xfs_trans_t keep track of dquot changes
    - * within a transaction and apply them later.
    - */
    -typedef struct xfs_dqtrx {
    -	struct xfs_dquot *qt_dquot;	  /* the dquot this refers to */
    -	ulong		qt_blk_res;	  /* blks reserved on a dquot */
    -	ulong		qt_blk_res_used;  /* blks used from the reservation */
    -	ulong		qt_ino_res;	  /* inode reserved on a dquot */
    -	ulong		qt_ino_res_used;  /* inodes used from the reservation */
    -	long		qt_bcount_delta;  /* dquot blk count changes */
    -	long		qt_delbcnt_delta; /* delayed dquot blk count changes */
    -	long		qt_icount_delta;  /* dquot inode count changes */
    -	ulong		qt_rtblk_res;	  /* # blks reserved on a dquot */
    -	ulong		qt_rtblk_res_used;/* # blks used from reservation */
    -	long		qt_rtbcount_delta;/* dquot realtime blk changes */
    -	long		qt_delrtb_delta;  /* delayed RT blk count changes */
    -} xfs_dqtrx_t;
    -
    -/*
    - * Dquot transaction functions, used if quota is enabled.
    - */
    -typedef void	(*qo_dup_dqinfo_t)(struct xfs_trans *, struct xfs_trans *);
    -typedef void	(*qo_mod_dquot_byino_t)(struct xfs_trans *,
    -				struct xfs_inode *, uint, long);
    -typedef void	(*qo_free_dqinfo_t)(struct xfs_trans *);
    -typedef void	(*qo_apply_dquot_deltas_t)(struct xfs_trans *);
    -typedef void	(*qo_unreserve_and_mod_dquots_t)(struct xfs_trans *);
    -typedef int	(*qo_reserve_quota_nblks_t)(
    -				struct xfs_trans *, struct xfs_mount *,
    -				struct xfs_inode *, long, long, uint);
    -typedef int	(*qo_reserve_quota_bydquots_t)(
    -				struct xfs_trans *, struct xfs_mount *,
    -				struct xfs_dquot *, struct xfs_dquot *,
    -				long, long, uint);
    -typedef struct xfs_dqtrxops {
    -	qo_dup_dqinfo_t			qo_dup_dqinfo;
    -	qo_free_dqinfo_t		qo_free_dqinfo;
    -	qo_mod_dquot_byino_t		qo_mod_dquot_byino;
    -	qo_apply_dquot_deltas_t		qo_apply_dquot_deltas;
    -	qo_reserve_quota_nblks_t	qo_reserve_quota_nblks;
    -	qo_reserve_quota_bydquots_t	qo_reserve_quota_bydquots;
    -	qo_unreserve_and_mod_dquots_t	qo_unreserve_and_mod_dquots;
    -} xfs_dqtrxops_t;
    -
    -#define XFS_DQTRXOP(mp, tp, op, args...) \
    -		((mp)->m_qm_ops.xfs_dqtrxops ? \
    -		((mp)->m_qm_ops.xfs_dqtrxops->op)(tp, ## args) : 0)
    -
    -#define XFS_DQTRXOP_VOID(mp, tp, op, args...) \
    -		((mp)->m_qm_ops.xfs_dqtrxops ? \
    -		((mp)->m_qm_ops.xfs_dqtrxops->op)(tp, ## args) : (void)0)
    -
    -#define XFS_TRANS_DUP_DQINFO(mp, otp, ntp) \
    -	XFS_DQTRXOP_VOID(mp, otp, qo_dup_dqinfo, ntp)
    -#define XFS_TRANS_FREE_DQINFO(mp, tp) \
    -	XFS_DQTRXOP_VOID(mp, tp, qo_free_dqinfo)
    -#define XFS_TRANS_MOD_DQUOT_BYINO(mp, tp, ip, field, delta) \
    -	XFS_DQTRXOP_VOID(mp, tp, qo_mod_dquot_byino, ip, field, delta)
    -#define XFS_TRANS_APPLY_DQUOT_DELTAS(mp, tp) \
    -	XFS_DQTRXOP_VOID(mp, tp, qo_apply_dquot_deltas)
    -#define XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, nblks, ninos, fl) \
    -	XFS_DQTRXOP(mp, tp, qo_reserve_quota_nblks, mp, ip, nblks, ninos, fl)
    -#define XFS_TRANS_RESERVE_QUOTA_BYDQUOTS(mp, tp, ud, gd, nb, ni, fl) \
    -	XFS_DQTRXOP(mp, tp, qo_reserve_quota_bydquots, mp, ud, gd, nb, ni, fl)
    -#define XFS_TRANS_UNRESERVE_AND_MOD_DQUOTS(mp, tp) \
    -	XFS_DQTRXOP_VOID(mp, tp, qo_unreserve_and_mod_dquots)
    -
    -#define XFS_TRANS_UNRESERVE_QUOTA_NBLKS(mp, tp, ip, nblks, ninos, flags) \
    -	XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, -(nblks), -(ninos), flags)
    -#define XFS_TRANS_RESERVE_QUOTA(mp, tp, ud, gd, nb, ni, f) \
    -	XFS_TRANS_RESERVE_QUOTA_BYDQUOTS(mp, tp, ud, gd, nb, ni, \
    -				f | XFS_QMOPT_RES_REGBLKS)
    -#define XFS_TRANS_UNRESERVE_QUOTA(mp, tp, ud, gd, nb, ni, f) \
    -	XFS_TRANS_RESERVE_QUOTA_BYDQUOTS(mp, tp, ud, gd, -(nb), -(ni), \
    -				f | XFS_QMOPT_RES_REGBLKS)
    -
    -extern int xfs_qm_dqcheck(xfs_disk_dquot_t *, xfs_dqid_t, uint, uint, char *);
    -extern int xfs_mount_reset_sbqflags(struct xfs_mount *);
    -
    -extern struct bhv_vfsops xfs_qmops;
    -
    -#endif	/* __KERNEL__ */
    -
    -#endif	/* __XFS_QUOTA_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_refcache.c b/sys/gnu/fs/xfs/xfs_refcache.c
    deleted file mode 100644
    index 09918b5daa9..00000000000
    --- a/sys/gnu/fs/xfs/xfs_refcache.c
    +++ /dev/null
    @@ -1,431 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_inode_item.h"
    -#include "xfs_itable.h"
    -#include "xfs_btree.h"
    -#include "xfs_alloc.h"
    -#include "xfs_ialloc.h"
    -#include "xfs_bmap.h"
    -#include "xfs_attr.h"
    -#include "xfs_error.h"
    -#include "xfs_buf_item.h"
    -#include "xfs_refcache.h"
    -
    -STATIC lock_t		xfs_refcache_lock;
    -STATIC xfs_inode_t	**xfs_refcache;
    -STATIC int		xfs_refcache_index;
    -STATIC int		xfs_refcache_busy;
    -STATIC int		xfs_refcache_count;
    -
    -void
    -xfs_refcache_init(void)
    -{
    -	spinlock_init(&xfs_refcache_lock, "xfs_refcache");
    -}
    -/*
    - * Insert the given inode into the reference cache.
    - */
    -void
    -xfs_refcache_insert(
    -	xfs_inode_t	*ip)
    -{
    -	vnode_t		*vp;
    -	xfs_inode_t	*release_ip;
    -	xfs_inode_t	**refcache;
    -
    -	ASSERT(ismrlocked(&(ip->i_iolock), MR_UPDATE));
    -
    -	/*
    -	 * If an unmount is busy blowing entries out of the cache,
    -	 * then don't bother.
    -	 */
    -	if (xfs_refcache_busy) {
    -		return;
    -	}
    -
    -	/*
    -	 * If we tuned the refcache down to zero, don't do anything.
    -	 */
    -	 if (!xfs_refcache_size) {
    -		return;
    -	}
    -
    -	/*
    -	 * The inode is already in the refcache, so don't bother
    -	 * with it.
    -	 */
    -	if (ip->i_refcache != NULL) {
    -		return;
    -	}
    -
    -	vp = XFS_ITOV(ip);
    -	/* ASSERT(vp->v_count > 0); */
    -	VN_HOLD(vp);
    -
    -	/*
    -	 * We allocate the reference cache on use so that we don't
    -	 * waste the memory on systems not being used as NFS servers.
    -	 */
    -	if (xfs_refcache == NULL) {
    -		refcache = (xfs_inode_t **)kmem_zalloc(XFS_REFCACHE_SIZE_MAX *
    -						       sizeof(xfs_inode_t *),
    -						       KM_SLEEP);
    -	} else {
    -		refcache = NULL;
    -	}
    -
    -	spin_lock(&xfs_refcache_lock);
    -
    -	/*
    -	 * If we allocated memory for the refcache above and it still
    -	 * needs it, then use the memory we allocated.  Otherwise we'll
    -	 * free the memory below.
    -	 */
    -	if (refcache != NULL) {
    -		if (xfs_refcache == NULL) {
    -			xfs_refcache = refcache;
    -			refcache = NULL;
    -		}
    -	}
    -
    -	/*
    -	 * If an unmount is busy clearing out the cache, don't add new
    -	 * entries to it.
    -	 */
    -	if (xfs_refcache_busy) {
    -		spin_unlock(&xfs_refcache_lock);
    -		VN_RELE(vp);
    -		/*
    -		 * If we allocated memory for the refcache above but someone
    -		 * else beat us to using it, then free the memory now.
    -		 */
    -		if (refcache != NULL) {
    -			kmem_free(refcache,
    -				  XFS_REFCACHE_SIZE_MAX * sizeof(xfs_inode_t *));
    -		}
    -		return;
    -	}
    -	release_ip = xfs_refcache[xfs_refcache_index];
    -	if (release_ip != NULL) {
    -		release_ip->i_refcache = NULL;
    -		xfs_refcache_count--;
    -		ASSERT(xfs_refcache_count >= 0);
    -	}
    -	xfs_refcache[xfs_refcache_index] = ip;
    -	ASSERT(ip->i_refcache == NULL);
    -	ip->i_refcache = &(xfs_refcache[xfs_refcache_index]);
    -	xfs_refcache_count++;
    -	ASSERT(xfs_refcache_count <= xfs_refcache_size);
    -	xfs_refcache_index++;
    -	if (xfs_refcache_index == xfs_refcache_size) {
    -		xfs_refcache_index = 0;
    -	}
    -	spin_unlock(&xfs_refcache_lock);
    -
    -	/*
    -	 * Save the pointer to the inode to be released so that we can
    -	 * VN_RELE it once we've dropped our inode locks in xfs_rwunlock().
    -	 * The pointer may be NULL, but that's OK.
    -	 */
    -	ip->i_release = release_ip;
    -
    -	/*
    -	 * If we allocated memory for the refcache above but someone
    -	 * else beat us to using it, then free the memory now.
    -	 */
    -	if (refcache != NULL) {
    -		kmem_free(refcache,
    -			  XFS_REFCACHE_SIZE_MAX * sizeof(xfs_inode_t *));
    -	}
    -}
    -
    -
    -/*
    - * If the given inode is in the reference cache, purge its entry and
    - * release the reference on the vnode.
    - */
    -void
    -xfs_refcache_purge_ip(
    -	xfs_inode_t	*ip)
    -{
    -	vnode_t	*vp;
    -	int	error;
    -
    -	/*
    -	 * If we're not pointing to our entry in the cache, then
    -	 * we must not be in the cache.
    -	 */
    -	if (ip->i_refcache == NULL) {
    -		return;
    -	}
    -
    -	spin_lock(&xfs_refcache_lock);
    -	if (ip->i_refcache == NULL) {
    -		spin_unlock(&xfs_refcache_lock);
    -		return;
    -	}
    -
    -	/*
    -	 * Clear both our pointer to the cache entry and its pointer
    -	 * back to us.
    -	 */
    -	ASSERT(*(ip->i_refcache) == ip);
    -	*(ip->i_refcache) = NULL;
    -	ip->i_refcache = NULL;
    -	xfs_refcache_count--;
    -	ASSERT(xfs_refcache_count >= 0);
    -	spin_unlock(&xfs_refcache_lock);
    -
    -	vp = XFS_ITOV(ip);
    -	/* ASSERT(vp->v_count > 1); */
    -	VOP_RELEASE(vp, error);
    -	VN_RELE(vp);
    -}
    -
    -
    -/*
    - * This is called from the XFS unmount code to purge all entries for the
    - * given mount from the cache.  It uses the refcache busy counter to
    - * make sure that new entries are not added to the cache as we purge them.
    - */
    -void
    -xfs_refcache_purge_mp(
    -	xfs_mount_t	*mp)
    -{
    -	vnode_t		*vp;
    -	int		error, i;
    -	xfs_inode_t	*ip;
    -
    -	if (xfs_refcache == NULL) {
    -		return;
    -	}
    -
    -	spin_lock(&xfs_refcache_lock);
    -	/*
    -	 * Bumping the busy counter keeps new entries from being added
    -	 * to the cache.  We use a counter since multiple unmounts could
    -	 * be in here simultaneously.
    -	 */
    -	xfs_refcache_busy++;
    -
    -	for (i = 0; i < xfs_refcache_size; i++) {
    -		ip = xfs_refcache[i];
    -		if ((ip != NULL) && (ip->i_mount == mp)) {
    -			xfs_refcache[i] = NULL;
    -			ip->i_refcache = NULL;
    -			xfs_refcache_count--;
    -			ASSERT(xfs_refcache_count >= 0);
    -			spin_unlock(&xfs_refcache_lock);
    -			vp = XFS_ITOV(ip);
    -			VOP_RELEASE(vp, error);
    -			VN_RELE(vp);
    -			spin_lock(&xfs_refcache_lock);
    -		}
    -	}
    -
    -	xfs_refcache_busy--;
    -	ASSERT(xfs_refcache_busy >= 0);
    -	spin_unlock(&xfs_refcache_lock);
    -}
    -
    -
    -/*
    - * This is called from the XFS sync code to ensure that the refcache
    - * is emptied out over time.  We purge a small number of entries with
    - * each call.
    - */
    -void
    -xfs_refcache_purge_some(xfs_mount_t *mp)
    -{
    -	int		error, i;
    -	xfs_inode_t	*ip;
    -	int		iplist_index;
    -	xfs_inode_t	**iplist;
    -
    -	if ((xfs_refcache == NULL) || (xfs_refcache_count == 0)) {
    -		return;
    -	}
    -
    -	iplist_index = 0;
    -	iplist = (xfs_inode_t **)kmem_zalloc(xfs_refcache_purge_count *
    -					  sizeof(xfs_inode_t *), KM_SLEEP);
    -
    -	spin_lock(&xfs_refcache_lock);
    -
    -	/*
    -	 * Store any inodes we find in the next several entries
    -	 * into the iplist array to be released after dropping
    -	 * the spinlock.  We always start looking from the currently
    -	 * oldest place in the cache.  We move the refcache index
    -	 * forward as we go so that we are sure to eventually clear
    -	 * out the entire cache when the system goes idle.
    -	 */
    -	for (i = 0; i < xfs_refcache_purge_count; i++) {
    -		ip = xfs_refcache[xfs_refcache_index];
    -		if (ip != NULL) {
    -			xfs_refcache[xfs_refcache_index] = NULL;
    -			ip->i_refcache = NULL;
    -			xfs_refcache_count--;
    -			ASSERT(xfs_refcache_count >= 0);
    -			iplist[iplist_index] = ip;
    -			iplist_index++;
    -		}
    -		xfs_refcache_index++;
    -		if (xfs_refcache_index == xfs_refcache_size) {
    -			xfs_refcache_index = 0;
    -		}
    -	}
    -
    -	spin_unlock(&xfs_refcache_lock);
    -
    -	/*
    -	 * Now drop the inodes we collected.
    -	 */
    -	for (i = 0; i < iplist_index; i++) {
    -		VOP_RELEASE(XFS_ITOV(iplist[i]), error);
    -		VN_RELE(XFS_ITOV(iplist[i]));
    -	}
    -
    -	kmem_free(iplist, xfs_refcache_purge_count *
    -			  sizeof(xfs_inode_t *));
    -}
    -
    -/*
    - * This is called when the refcache is dynamically resized
    - * via a sysctl.
    - *
    - * If the new size is smaller than the old size, purge all
    - * entries in slots greater than the new size, and move
    - * the index if necessary.
    - *
    - * If the refcache hasn't even been allocated yet, or the
    - * new size is larger than the old size, just set the value
    - * of xfs_refcache_size.
    - */
    -
    -void
    -xfs_refcache_resize(int xfs_refcache_new_size)
    -{
    -	int		i;
    -	xfs_inode_t	*ip;
    -	int		iplist_index = 0;
    -	xfs_inode_t	**iplist;
    -	int		error;
    -
    -	/*
    -	 * If the new size is smaller than the current size,
    -	 * purge entries to create smaller cache, and
    -	 * reposition index if necessary.
    -	 * Don't bother if no refcache yet.
    -	 */
    -	if (xfs_refcache && (xfs_refcache_new_size < xfs_refcache_size)) {
    -
    -		iplist = (xfs_inode_t **)kmem_zalloc(XFS_REFCACHE_SIZE_MAX *
    -				sizeof(xfs_inode_t *), KM_SLEEP);
    -
    -		spin_lock(&xfs_refcache_lock);
    -
    -		for (i = xfs_refcache_new_size; i < xfs_refcache_size; i++) {
    -			ip = xfs_refcache[i];
    -			if (ip != NULL) {
    -				xfs_refcache[i] = NULL;
    -				ip->i_refcache = NULL;
    -				xfs_refcache_count--;
    -				ASSERT(xfs_refcache_count >= 0);
    -				iplist[iplist_index] = ip;
    -				iplist_index++;
    -			}
    -		}
    -
    -		xfs_refcache_size = xfs_refcache_new_size;
    -
    -		/*
    -		 * Move index to beginning of cache if it's now past the end
    -		 */
    -		if (xfs_refcache_index >= xfs_refcache_new_size)
    -			xfs_refcache_index = 0;
    -
    -		spin_unlock(&xfs_refcache_lock);
    -
    -		/*
    -		 * Now drop the inodes we collected.
    -		 */
    -		for (i = 0; i < iplist_index; i++) {
    -			VOP_RELEASE(XFS_ITOV(iplist[i]), error);
    -			VN_RELE(XFS_ITOV(iplist[i]));
    -		}
    -
    -		kmem_free(iplist, XFS_REFCACHE_SIZE_MAX *
    -				  sizeof(xfs_inode_t *));
    -	} else {
    -		spin_lock(&xfs_refcache_lock);
    -		xfs_refcache_size = xfs_refcache_new_size;
    -		spin_unlock(&xfs_refcache_lock);
    -	}
    -}
    -
    -void
    -xfs_refcache_iunlock(
    -	xfs_inode_t	*ip,
    -	uint		lock_flags)
    -{
    -	xfs_inode_t	*release_ip;
    -	int		error;
    -
    -	release_ip = ip->i_release;
    -	ip->i_release = NULL;
    -
    -	xfs_iunlock(ip, lock_flags);
    -
    -	if (release_ip != NULL) {
    -		VOP_RELEASE(XFS_ITOV(release_ip), error);
    -		VN_RELE(XFS_ITOV(release_ip));
    -	}
    -}
    -
    -void
    -xfs_refcache_destroy(void)
    -{
    -	if (xfs_refcache) {
    -		kmem_free(xfs_refcache,
    -			XFS_REFCACHE_SIZE_MAX * sizeof(xfs_inode_t *));
    -		xfs_refcache = NULL;
    -	}
    -	spinlock_destroy(&xfs_refcache_lock);
    -}
    diff --git a/sys/gnu/fs/xfs/xfs_refcache.h b/sys/gnu/fs/xfs/xfs_refcache.h
    deleted file mode 100644
    index a0a592fcce9..00000000000
    --- a/sys/gnu/fs/xfs/xfs_refcache.h
    +++ /dev/null
    @@ -1,54 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_REFCACHE_H__
    -#define __XFS_REFCACHE_H__
    -
    -#ifdef HAVE_REFCACHE
    -/*
    - * Maximum size (in inodes) for the NFS reference cache
    - */
    -#define XFS_REFCACHE_SIZE_MAX	512
    -
    -struct xfs_inode;
    -struct xfs_mount;
    -
    -extern void xfs_refcache_init(void);
    -extern void xfs_refcache_insert(struct xfs_inode *);
    -extern void xfs_refcache_purge_ip(struct xfs_inode *);
    -extern void xfs_refcache_purge_mp(struct xfs_mount *);
    -extern void xfs_refcache_purge_some(struct xfs_mount *);
    -extern void xfs_refcache_resize(int);
    -extern void xfs_refcache_destroy(void);
    -
    -extern void xfs_refcache_iunlock(struct xfs_inode *, uint);
    -
    -#else
    -
    -#define xfs_refcache_init()		do { } while (0)
    -#define xfs_refcache_insert(ip)		do { } while (0)
    -#define xfs_refcache_purge_ip(ip)	do { } while (0)
    -#define xfs_refcache_purge_mp(mp)	do { } while (0)
    -#define xfs_refcache_purge_some(mp)	do { } while (0)
    -#define xfs_refcache_resize(size)	do { } while (0)
    -#define xfs_refcache_destroy()		do { } while (0)
    -
    -#define xfs_refcache_iunlock(ip, flags)	xfs_iunlock(ip, flags)
    -
    -#endif
    -
    -#endif	/* __XFS_REFCACHE_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_rename.c b/sys/gnu/fs/xfs/xfs_rename.c
    deleted file mode 100644
    index 995a4ecbe0d..00000000000
    --- a/sys/gnu/fs/xfs/xfs_rename.c
    +++ /dev/null
    @@ -1,636 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_da_btree.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_inode_item.h"
    -#include "xfs_bmap.h"
    -#include "xfs_error.h"
    -#include "xfs_quota.h"
    -#include "xfs_refcache.h"
    -#include "xfs_utils.h"
    -#include "xfs_trans_space.h"
    -#include "xfs_dir_leaf.h"
    -
    -
    -/*
    - * Given an array of up to 4 inode pointers, unlock the pointed to inodes.
    - * If there are fewer than 4 entries in the array, the empty entries will
    - * be at the end and will have NULL pointers in them.
    - */
    -STATIC void
    -xfs_rename_unlock4(
    -	xfs_inode_t	**i_tab,
    -	uint		lock_mode)
    -{
    -	int	i;
    -
    -	xfs_iunlock(i_tab[0], lock_mode);
    -	for (i = 1; i < 4; i++) {
    -		if (i_tab[i] == NULL) {
    -			break;
    -		}
    -		/*
    -		 * Watch out for duplicate entries in the table.
    -		 */
    -		if (i_tab[i] != i_tab[i-1]) {
    -			xfs_iunlock(i_tab[i], lock_mode);
    -		}
    -	}
    -}
    -
    -#ifdef DEBUG
    -int xfs_rename_skip, xfs_rename_nskip;
    -#endif
    -
    -/*
    - * The following routine will acquire the locks required for a rename
    - * operation. The code understands the semantics of renames and will
    - * validate that name1 exists under dp1 & that name2 may or may not
    - * exist under dp2.
    - *
    - * We are renaming dp1/name1 to dp2/name2.
    - *
    - * Return ENOENT if dp1 does not exist, other lookup errors, or 0 for success.
    - */
    -STATIC int
    -xfs_lock_for_rename(
    -	xfs_inode_t	*dp1,	/* old (source) directory inode */
    -	xfs_inode_t	*dp2,	/* new (target) directory inode */
    -	vname_t		*vname1,/* old entry name */
    -	vname_t		*vname2,/* new entry name */
    -	xfs_inode_t	**ipp1,	/* inode of old entry */
    -	xfs_inode_t	**ipp2,	/* inode of new entry, if it
    -				   already exists, NULL otherwise. */
    -	xfs_inode_t	**i_tab,/* array of inode returned, sorted */
    -	int		*num_inodes)  /* number of inodes in array */
    -{
    -	xfs_inode_t		*ip1, *ip2, *temp;
    -	xfs_ino_t		inum1, inum2;
    -	int			error;
    -	int			i, j;
    -	uint			lock_mode;
    -	int			diff_dirs = (dp1 != dp2);
    -
    -	ip2 = NULL;
    -
    -	/*
    -	 * First, find out the current inums of the entries so that we
    -	 * can determine the initial locking order.  We'll have to
    -	 * sanity check stuff after all the locks have been acquired
    -	 * to see if we still have the right inodes, directories, etc.
    -	 */
    -	lock_mode = xfs_ilock_map_shared(dp1);
    -	error = xfs_get_dir_entry(vname1, &ip1);
    -	if (error) {
    -		xfs_iunlock_map_shared(dp1, lock_mode);
    -		return error;
    -	}
    -
    -	inum1 = ip1->i_ino;
    -
    -	ASSERT(ip1);
    -	ITRACE(ip1);
    -
    -	/*
    -	 * Unlock dp1 and lock dp2 if they are different.
    -	 */
    -
    -	if (diff_dirs) {
    -		xfs_iunlock_map_shared(dp1, lock_mode);
    -		lock_mode = xfs_ilock_map_shared(dp2);
    -	}
    -
    -	error = xfs_dir_lookup_int(XFS_ITOBHV(dp2), lock_mode,
    -				   vname2, &inum2, &ip2);
    -	if (error == ENOENT) {		/* target does not need to exist. */
    -		inum2 = 0;
    -	} else if (error) {
    -		/*
    -		 * If dp2 and dp1 are the same, the next line unlocks dp1.
    -		 * Got it?
    -		 */
    -		xfs_iunlock_map_shared(dp2, lock_mode);
    -		IRELE (ip1);
    -		return error;
    -	} else {
    -		ITRACE(ip2);
    -	}
    -
    -	/*
    -	 * i_tab contains a list of pointers to inodes.  We initialize
    -	 * the table here & we'll sort it.  We will then use it to
    -	 * order the acquisition of the inode locks.
    -	 *
    -	 * Note that the table may contain duplicates.  e.g., dp1 == dp2.
    -	 */
    -	i_tab[0] = dp1;
    -	i_tab[1] = dp2;
    -	i_tab[2] = ip1;
    -	if (inum2 == 0) {
    -		*num_inodes = 3;
    -		i_tab[3] = NULL;
    -	} else {
    -		*num_inodes = 4;
    -		i_tab[3] = ip2;
    -	}
    -
    -	/*
    -	 * Sort the elements via bubble sort.  (Remember, there are at
    -	 * most 4 elements to sort, so this is adequate.)
    -	 */
    -	for (i=0; i < *num_inodes; i++) {
    -		for (j=1; j < *num_inodes; j++) {
    -			if (i_tab[j]->i_ino < i_tab[j-1]->i_ino) {
    -				temp = i_tab[j];
    -				i_tab[j] = i_tab[j-1];
    -				i_tab[j-1] = temp;
    -			}
    -		}
    -	}
    -
    -	/*
    -	 * We have dp2 locked. If it isn't first, unlock it.
    -	 * If it is first, tell xfs_lock_inodes so it can skip it
    -	 * when locking. if dp1 == dp2, xfs_lock_inodes will skip both
    -	 * since they are equal. xfs_lock_inodes needs all these inodes
    -	 * so that it can unlock and retry if there might be a dead-lock
    -	 * potential with the log.
    -	 */
    -
    -	if (i_tab[0] == dp2 && lock_mode == XFS_ILOCK_SHARED) {
    -#ifdef DEBUG
    -		xfs_rename_skip++;
    -#endif
    -		xfs_lock_inodes(i_tab, *num_inodes, 1, XFS_ILOCK_SHARED);
    -	} else {
    -#ifdef DEBUG
    -		xfs_rename_nskip++;
    -#endif
    -		xfs_iunlock_map_shared(dp2, lock_mode);
    -		xfs_lock_inodes(i_tab, *num_inodes, 0, XFS_ILOCK_SHARED);
    -	}
    -
    -	/*
    -	 * Set the return value. Null out any unused entries in i_tab.
    -	 */
    -	*ipp1 = *ipp2 = NULL;
    -	for (i=0; i < *num_inodes; i++) {
    -		if (i_tab[i]->i_ino == inum1) {
    -			*ipp1 = i_tab[i];
    -		}
    -		if (i_tab[i]->i_ino == inum2) {
    -			*ipp2 = i_tab[i];
    -		}
    -	}
    -	for (;i < 4; i++) {
    -		i_tab[i] = NULL;
    -	}
    -	return 0;
    -}
    -
    -/*
    - * xfs_rename
    - */
    -int
    -xfs_rename(
    -	bhv_desc_t	*src_dir_bdp,
    -	vname_t		*src_vname,
    -	xfs_vnode_t	*target_dir_vp,
    -	vname_t		*target_vname,
    -	cred_t		*credp)
    -{
    -	xfs_trans_t	*tp;
    -	xfs_inode_t	*src_dp, *target_dp, *src_ip, *target_ip;
    -	xfs_mount_t	*mp;
    -	int		new_parent;		/* moving to a new dir */
    -	int		src_is_directory;	/* src_name is a directory */
    -	int		error;
    -	xfs_bmap_free_t free_list;
    -	xfs_fsblock_t   first_block;
    -	int		cancel_flags;
    -	int		committed;
    -	xfs_inode_t	*inodes[4];
    -	int		target_ip_dropped = 0;	/* dropped target_ip link? */
    -	xfs_vnode_t	*src_dir_vp;
    -	int		spaceres;
    -	int		target_link_zero = 0;
    -	int		num_inodes;
    -	char		*src_name = VNAME(src_vname);
    -	char		*target_name = VNAME(target_vname);
    -	int		src_namelen = VNAMELEN(src_vname);
    -	int		target_namelen = VNAMELEN(target_vname);
    -
    -	src_dir_vp = BHV_TO_VNODE(src_dir_bdp);
    -	vn_trace_entry(src_dir_vp, "xfs_rename", (inst_t *)__return_address);
    -	vn_trace_entry(target_dir_vp, "xfs_rename", (inst_t *)__return_address);
    -
    -	/*
    -	 * Find the XFS behavior descriptor for the target directory
    -	 * vnode since it was not handed to us.
    -	 */
    -	target_dp = xfs_vtoi(target_dir_vp);
    -	if (target_dp == NULL) {
    -		return XFS_ERROR(EXDEV);
    -	}
    -
    -	src_dp = XFS_BHVTOI(src_dir_bdp);
    -	mp = src_dp->i_mount;
    -
    -	if (DM_EVENT_ENABLED(src_dir_vp->v_vfsp, src_dp, DM_EVENT_RENAME) ||
    -	    DM_EVENT_ENABLED(target_dir_vp->v_vfsp,
    -				target_dp, DM_EVENT_RENAME)) {
    -		error = XFS_SEND_NAMESP(mp, DM_EVENT_RENAME,
    -					src_dir_vp, DM_RIGHT_NULL,
    -					target_dir_vp, DM_RIGHT_NULL,
    -					src_name, target_name,
    -					0, 0, 0);
    -		if (error) {
    -			return error;
    -		}
    -	}
    -	/* Return through std_return after this point. */
    -
    -	/*
    -	 * Lock all the participating inodes. Depending upon whether
    -	 * the target_name exists in the target directory, and
    -	 * whether the target directory is the same as the source
    -	 * directory, we can lock from 2 to 4 inodes.
    -	 * xfs_lock_for_rename() will return ENOENT if src_name
    -	 * does not exist in the source directory.
    -	 */
    -	tp = NULL;
    -	error = xfs_lock_for_rename(src_dp, target_dp, src_vname,
    -			target_vname, &src_ip, &target_ip, inodes,
    -			&num_inodes);
    -
    -	if (error) {
    -		/*
    -		 * We have nothing locked, no inode references, and
    -		 * no transaction, so just get out.
    -		 */
    -		goto std_return;
    -	}
    -
    -	ASSERT(src_ip != NULL);
    -
    -	if ((src_ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
    -		/*
    -		 * Check for link count overflow on target_dp
    -		 */
    -		if (target_ip == NULL && (src_dp != target_dp) &&
    -		    target_dp->i_d.di_nlink >= XFS_MAXLINK) {
    -			error = XFS_ERROR(EMLINK);
    -			xfs_rename_unlock4(inodes, XFS_ILOCK_SHARED);
    -			goto rele_return;
    -		}
    -	}
    -
    -	new_parent = (src_dp != target_dp);
    -	src_is_directory = ((src_ip->i_d.di_mode & S_IFMT) == S_IFDIR);
    -
    -	/*
    -	 * Drop the locks on our inodes so that we can start the transaction.
    -	 */
    -	xfs_rename_unlock4(inodes, XFS_ILOCK_SHARED);
    -
    -	XFS_BMAP_INIT(&free_list, &first_block);
    -	tp = xfs_trans_alloc(mp, XFS_TRANS_RENAME);
    -	cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
    -	spaceres = XFS_RENAME_SPACE_RES(mp, target_namelen);
    -	error = xfs_trans_reserve(tp, spaceres, XFS_RENAME_LOG_RES(mp), 0,
    -			XFS_TRANS_PERM_LOG_RES, XFS_RENAME_LOG_COUNT);
    -	if (error == ENOSPC) {
    -		spaceres = 0;
    -		error = xfs_trans_reserve(tp, 0, XFS_RENAME_LOG_RES(mp), 0,
    -				XFS_TRANS_PERM_LOG_RES, XFS_RENAME_LOG_COUNT);
    -	}
    -	if (error) {
    -		xfs_trans_cancel(tp, 0);
    -		goto rele_return;
    -	}
    -
    -	/*
    -	 * Attach the dquots to the inodes
    -	 */
    -	if ((error = XFS_QM_DQVOPRENAME(mp, inodes))) {
    -		xfs_trans_cancel(tp, cancel_flags);
    -		goto rele_return;
    -	}
    -
    -	/*
    -	 * Reacquire the inode locks we dropped above.
    -	 */
    -	xfs_lock_inodes(inodes, num_inodes, 0, XFS_ILOCK_EXCL);
    -
    -	/*
    -	 * Join all the inodes to the transaction. From this point on,
    -	 * we can rely on either trans_commit or trans_cancel to unlock
    -	 * them.  Note that we need to add a vnode reference to the
    -	 * directories since trans_commit & trans_cancel will decrement
    -	 * them when they unlock the inodes.  Also, we need to be careful
    -	 * not to add an inode to the transaction more than once.
    -	 */
    -	VN_HOLD(src_dir_vp);
    -	xfs_trans_ijoin(tp, src_dp, XFS_ILOCK_EXCL);
    -	if (new_parent) {
    -		VN_HOLD(target_dir_vp);
    -		xfs_trans_ijoin(tp, target_dp, XFS_ILOCK_EXCL);
    -	}
    -	if ((src_ip != src_dp) && (src_ip != target_dp)) {
    -		xfs_trans_ijoin(tp, src_ip, XFS_ILOCK_EXCL);
    -	}
    -	if ((target_ip != NULL) &&
    -	    (target_ip != src_ip) &&
    -	    (target_ip != src_dp) &&
    -	    (target_ip != target_dp)) {
    -		xfs_trans_ijoin(tp, target_ip, XFS_ILOCK_EXCL);
    -	}
    -
    -	/*
    -	 * Set up the target.
    -	 */
    -	if (target_ip == NULL) {
    -		/*
    -		 * If there's no space reservation, check the entry will
    -		 * fit before actually inserting it.
    -		 */
    -		if (spaceres == 0 &&
    -		    (error = XFS_DIR_CANENTER(mp, tp, target_dp, target_name,
    -				target_namelen))) {
    -			goto error_return;
    -		}
    -		/*
    -		 * If target does not exist and the rename crosses
    -		 * directories, adjust the target directory link count
    -		 * to account for the ".." reference from the new entry.
    -		 */
    -		error = XFS_DIR_CREATENAME(mp, tp, target_dp, target_name,
    -					   target_namelen, src_ip->i_ino,
    -					   &first_block, &free_list, spaceres);
    -		if (error == ENOSPC) {
    -			goto error_return;
    -		}
    -		if (error) {
    -			goto abort_return;
    -		}
    -		xfs_ichgtime(target_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
    -
    -		if (new_parent && src_is_directory) {
    -			error = xfs_bumplink(tp, target_dp);
    -			if (error) {
    -				goto abort_return;
    -			}
    -		}
    -	} else { /* target_ip != NULL */
    -
    -		/*
    -		 * If target exists and it's a directory, check that both
    -		 * target and source are directories and that target can be
    -		 * destroyed, or that neither is a directory.
    -		 */
    -		if ((target_ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
    -			/*
    -			 * Make sure target dir is empty.
    -			 */
    -			if (!(XFS_DIR_ISEMPTY(target_ip->i_mount, target_ip)) ||
    -			    (target_ip->i_d.di_nlink > 2)) {
    -				error = XFS_ERROR(EEXIST);
    -				goto error_return;
    -			}
    -		}
    -
    -		/*
    -		 * Link the source inode under the target name.
    -		 * If the source inode is a directory and we are moving
    -		 * it across directories, its ".." entry will be
    -		 * inconsistent until we replace that down below.
    -		 *
    -		 * In case there is already an entry with the same
    -		 * name at the destination directory, remove it first.
    -		 */
    -		error = XFS_DIR_REPLACE(mp, tp, target_dp, target_name,
    -			target_namelen, src_ip->i_ino, &first_block,
    -			&free_list, spaceres);
    -		if (error) {
    -			goto abort_return;
    -		}
    -		xfs_ichgtime(target_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
    -
    -		/*
    -		 * Decrement the link count on the target since the target
    -		 * dir no longer points to it.
    -		 */
    -		error = xfs_droplink(tp, target_ip);
    -		if (error) {
    -			goto abort_return;
    -		}
    -		target_ip_dropped = 1;
    -
    -		if (src_is_directory) {
    -			/*
    -			 * Drop the link from the old "." entry.
    -			 */
    -			error = xfs_droplink(tp, target_ip);
    -			if (error) {
    -				goto abort_return;
    -			}
    -		}
    -
    -		/* Do this test while we still hold the locks */
    -		target_link_zero = (target_ip)->i_d.di_nlink==0;
    -
    -	} /* target_ip != NULL */
    -
    -	/*
    -	 * Remove the source.
    -	 */
    -	if (new_parent && src_is_directory) {
    -
    -		/*
    -		 * Rewrite the ".." entry to point to the new
    -		 * directory.
    -		 */
    -		error = XFS_DIR_REPLACE(mp, tp, src_ip, "..", 2,
    -					target_dp->i_ino, &first_block,
    -					&free_list, spaceres);
    -		ASSERT(error != EEXIST);
    -		if (error) {
    -			goto abort_return;
    -		}
    -		xfs_ichgtime(src_ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
    -
    -	} else {
    -		/*
    -		 * We always want to hit the ctime on the source inode.
    -		 * We do it in the if clause above for the 'new_parent &&
    -		 * src_is_directory' case, and here we get all the other
    -		 * cases.  This isn't strictly required by the standards
    -		 * since the source inode isn't really being changed,
    -		 * but old unix file systems did it and some incremental
    -		 * backup programs won't work without it.
    -		 */
    -		xfs_ichgtime(src_ip, XFS_ICHGTIME_CHG);
    -	}
    -
    -	/*
    -	 * Adjust the link count on src_dp.  This is necessary when
    -	 * renaming a directory, either within one parent when
    -	 * the target existed, or across two parent directories.
    -	 */
    -	if (src_is_directory && (new_parent || target_ip != NULL)) {
    -
    -		/*
    -		 * Decrement link count on src_directory since the
    -		 * entry that's moved no longer points to it.
    -		 */
    -		error = xfs_droplink(tp, src_dp);
    -		if (error) {
    -			goto abort_return;
    -		}
    -	}
    -
    -	error = XFS_DIR_REMOVENAME(mp, tp, src_dp, src_name, src_namelen,
    -			src_ip->i_ino, &first_block, &free_list, spaceres);
    -	if (error) {
    -		goto abort_return;
    -	}
    -	xfs_ichgtime(src_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
    -
    -	/*
    -	 * Update the generation counts on all the directory inodes
    -	 * that we're modifying.
    -	 */
    -	src_dp->i_gen++;
    -	xfs_trans_log_inode(tp, src_dp, XFS_ILOG_CORE);
    -
    -	if (new_parent) {
    -		target_dp->i_gen++;
    -		xfs_trans_log_inode(tp, target_dp, XFS_ILOG_CORE);
    -	}
    -
    -	/*
    -	 * If there was a target inode, take an extra reference on
    -	 * it here so that it doesn't go to xfs_inactive() from
    -	 * within the commit.
    -	 */
    -	if (target_ip != NULL) {
    -		IHOLD(target_ip);
    -	}
    -
    -	/*
    -	 * If this is a synchronous mount, make sure that the
    -	 * rename transaction goes to disk before returning to
    -	 * the user.
    -	 */
    -	if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
    -		xfs_trans_set_sync(tp);
    -	}
    -
    -	/*
    -	 * Take refs. for vop_link_removed calls below.  No need to worry
    -	 * about directory refs. because the caller holds them.
    -	 *
    -	 * Do holds before the xfs_bmap_finish since it might rele them down
    -	 * to zero.
    -	 */
    -
    -	if (target_ip_dropped)
    -		IHOLD(target_ip);
    -	IHOLD(src_ip);
    -
    -	error = xfs_bmap_finish(&tp, &free_list, first_block, &committed);
    -	if (error) {
    -		xfs_bmap_cancel(&free_list);
    -		xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES |
    -				 XFS_TRANS_ABORT));
    -		if (target_ip != NULL) {
    -			IRELE(target_ip);
    -		}
    -		if (target_ip_dropped) {
    -			IRELE(target_ip);
    -		}
    -		IRELE(src_ip);
    -		goto std_return;
    -	}
    -
    -	/*
    -	 * trans_commit will unlock src_ip, target_ip & decrement
    -	 * the vnode references.
    -	 */
    -	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
    -	if (target_ip != NULL) {
    -		xfs_refcache_purge_ip(target_ip);
    -		IRELE(target_ip);
    -	}
    -	/*
    -	 * Let interposed file systems know about removed links.
    -	 */
    -	if (target_ip_dropped) {
    -		XVOP_LINK_REMOVED(XFS_ITOV(target_ip), target_dir_vp,
    -					target_link_zero);
    -		IRELE(target_ip);
    -	}
    -
    -	IRELE(src_ip);
    -
    -	/* Fall through to std_return with error = 0 or errno from
    -	 * xfs_trans_commit	 */
    -std_return:
    -	if (DM_EVENT_ENABLED(src_dir_vp->v_vfsp, src_dp, DM_EVENT_POSTRENAME) ||
    -	    DM_EVENT_ENABLED(target_dir_vp->v_vfsp,
    -				target_dp, DM_EVENT_POSTRENAME)) {
    -		(void) XFS_SEND_NAMESP (mp, DM_EVENT_POSTRENAME,
    -					src_dir_vp, DM_RIGHT_NULL,
    -					target_dir_vp, DM_RIGHT_NULL,
    -					src_name, target_name,
    -					0, error, 0);
    -	}
    -	return error;
    -
    - abort_return:
    -	cancel_flags |= XFS_TRANS_ABORT;
    -	/* FALLTHROUGH */
    - error_return:
    -	xfs_bmap_cancel(&free_list);
    -	xfs_trans_cancel(tp, cancel_flags);
    -	goto std_return;
    -
    - rele_return:
    -	IRELE(src_ip);
    -	if (target_ip != NULL) {
    -		IRELE(target_ip);
    -	}
    -	goto std_return;
    -}
    -
    diff --git a/sys/gnu/fs/xfs/xfs_rtalloc.c b/sys/gnu/fs/xfs/xfs_rtalloc.c
    deleted file mode 100644
    index f5944c8b378..00000000000
    --- a/sys/gnu/fs/xfs/xfs_rtalloc.c
    +++ /dev/null
    @@ -1,2449 +0,0 @@
    -/*
    - * Copyright (c) 2000-2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_btree.h"
    -#include "xfs_ialloc.h"
    -#include "xfs_alloc.h"
    -#include "xfs_bmap.h"
    -#include "xfs_rtalloc.h"
    -#include "xfs_fsops.h"
    -#include "xfs_error.h"
    -#include "xfs_rw.h"
    -#include "xfs_inode_item.h"
    -#include "xfs_trans_space.h"
    -
    -
    -/*
    - * Prototypes for internal functions.
    - */
    -
    -
    -STATIC int xfs_rtallocate_range(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,
    -		xfs_extlen_t, xfs_buf_t **, xfs_fsblock_t *);
    -STATIC int xfs_rtany_summary(xfs_mount_t *, xfs_trans_t *, int, int,
    -		xfs_rtblock_t, xfs_buf_t **, xfs_fsblock_t *, int *);
    -STATIC int xfs_rtcheck_range(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,
    -		xfs_extlen_t, int, xfs_rtblock_t *, int *);
    -STATIC int xfs_rtfind_back(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,
    -		xfs_rtblock_t, xfs_rtblock_t *);
    -STATIC int xfs_rtfind_forw(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,
    -		xfs_rtblock_t, xfs_rtblock_t *);
    -STATIC int xfs_rtget_summary( xfs_mount_t *, xfs_trans_t *, int,
    -		xfs_rtblock_t, xfs_buf_t **, xfs_fsblock_t *, xfs_suminfo_t *);
    -STATIC int xfs_rtmodify_range(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t,
    -		xfs_extlen_t, int);
    -STATIC int xfs_rtmodify_summary(xfs_mount_t *, xfs_trans_t *, int,
    -		xfs_rtblock_t, int, xfs_buf_t **, xfs_fsblock_t *);
    -
    -/*
    - * Internal functions.
    - */
    -
    -/*
    - * xfs_lowbit32: get low bit set out of 32-bit argument, -1 if none set.
    - */
    -STATIC int
    -xfs_lowbit32(
    -	__uint32_t	v)
    -{
    -	if (v)
    -		return ffs(v) - 1;
    -	return -1;
    -}
    -
    -/*
    - * Allocate space to the bitmap or summary file, and zero it, for growfs.
    - */
    -STATIC int				/* error */
    -xfs_growfs_rt_alloc(
    -	xfs_mount_t	*mp,		/* file system mount point */
    -	xfs_extlen_t	oblocks,	/* old count of blocks */
    -	xfs_extlen_t	nblocks,	/* new count of blocks */
    -	xfs_ino_t	ino)		/* inode number (bitmap/summary) */
    -{
    -	xfs_fileoff_t	bno;		/* block number in file */
    -	xfs_buf_t	*bp;		/* temporary buffer for zeroing */
    -	int		cancelflags;	/* flags for xfs_trans_cancel */
    -	int		committed;	/* transaction committed flag */
    -	xfs_daddr_t	d;		/* disk block address */
    -	int		error;		/* error return value */
    -	xfs_fsblock_t	firstblock;	/* first block allocated in xaction */
    -	xfs_bmap_free_t	flist;		/* list of freed blocks */
    -	xfs_fsblock_t	fsbno;		/* filesystem block for bno */
    -	xfs_inode_t	*ip;		/* pointer to incore inode */
    -	xfs_bmbt_irec_t	map;		/* block map output */
    -	int		nmap;		/* number of block maps */
    -	int		resblks;	/* space reservation */
    -	xfs_trans_t	*tp;		/* transaction pointer */
    -
    -	/*
    -	 * Allocate space to the file, as necessary.
    -	 */
    -	while (oblocks < nblocks) {
    -		tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_ALLOC);
    -		resblks = XFS_GROWFSRT_SPACE_RES(mp, nblocks - oblocks);
    -		cancelflags = 0;
    -		/*
    -		 * Reserve space & log for one extent added to the file.
    -		 */
    -		if ((error = xfs_trans_reserve(tp, resblks,
    -				XFS_GROWRTALLOC_LOG_RES(mp), 0,
    -				XFS_TRANS_PERM_LOG_RES,
    -				XFS_DEFAULT_PERM_LOG_COUNT)))
    -			goto error_exit;
    -		cancelflags = XFS_TRANS_RELEASE_LOG_RES;
    -		/*
    -		 * Lock the inode.
    -		 */
    -		if ((error = xfs_trans_iget(mp, tp, ino, 0,
    -						XFS_ILOCK_EXCL, &ip)))
    -			goto error_exit;
    -		XFS_BMAP_INIT(&flist, &firstblock);
    -		/*
    -		 * Allocate blocks to the bitmap file.
    -		 */
    -		nmap = 1;
    -		cancelflags |= XFS_TRANS_ABORT;
    -		error = xfs_bmapi(tp, ip, oblocks, nblocks - oblocks,
    -			XFS_BMAPI_WRITE | XFS_BMAPI_METADATA, &firstblock,
    -			resblks, &map, &nmap, &flist, NULL);
    -		if (!error && nmap < 1)
    -			error = XFS_ERROR(ENOSPC);
    -		if (error)
    -			goto error_exit;
    -		/*
    -		 * Free any blocks freed up in the transaction, then commit.
    -		 */
    -		error = xfs_bmap_finish(&tp, &flist, firstblock, &committed);
    -		if (error)
    -			goto error_exit;
    -		xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
    -		/*
    -		 * Now we need to clear the allocated blocks.
    -		 * Do this one block per transaction, to keep it simple.
    -		 */
    -		cancelflags = 0;
    -		for (bno = map.br_startoff, fsbno = map.br_startblock;
    -		     bno < map.br_startoff + map.br_blockcount;
    -		     bno++, fsbno++) {
    -			tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_ZERO);
    -			/*
    -			 * Reserve log for one block zeroing.
    -			 */
    -			if ((error = xfs_trans_reserve(tp, 0,
    -					XFS_GROWRTZERO_LOG_RES(mp), 0, 0, 0)))
    -				goto error_exit;
    -			/*
    -			 * Lock the bitmap inode.
    -			 */
    -			if ((error = xfs_trans_iget(mp, tp, ino, 0,
    -							XFS_ILOCK_EXCL, &ip)))
    -				goto error_exit;
    -			/*
    -			 * Get a buffer for the block.
    -			 */
    -			d = XFS_FSB_TO_DADDR(mp, fsbno);
    -			bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
    -				mp->m_bsize, 0);
    -			if (bp == NULL) {
    -				error = XFS_ERROR(EIO);
    -				goto error_exit;
    -			}
    -			memset(XFS_BUF_PTR(bp), 0, mp->m_sb.sb_blocksize);
    -			xfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);
    -			/*
    -			 * Commit the transaction.
    -			 */
    -			xfs_trans_commit(tp, 0, NULL);
    -		}
    -		/*
    -		 * Go on to the next extent, if any.
    -		 */
    -		oblocks = map.br_startoff + map.br_blockcount;
    -	}
    -	return 0;
    -error_exit:
    -	xfs_trans_cancel(tp, cancelflags);
    -	return error;
    -}
    -
    -/*
    - * Attempt to allocate an extent minlen<=len<=maxlen starting from
    - * bitmap block bbno.  If we don't get maxlen then use prod to trim
    - * the length, if given.  Returns error; returns starting block in *rtblock.
    - * The lengths are all in rtextents.
    - */
    -STATIC int				/* error */
    -xfs_rtallocate_extent_block(
    -	xfs_mount_t	*mp,		/* file system mount point */
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_rtblock_t	bbno,		/* bitmap block number */
    -	xfs_extlen_t	minlen,		/* minimum length to allocate */
    -	xfs_extlen_t	maxlen,		/* maximum length to allocate */
    -	xfs_extlen_t	*len,		/* out: actual length allocated */
    -	xfs_rtblock_t	*nextp,		/* out: next block to try */
    -	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */
    -	xfs_fsblock_t	*rsb,		/* in/out: summary block number */
    -	xfs_extlen_t	prod,		/* extent product factor */
    -	xfs_rtblock_t	*rtblock)	/* out: start block allocated */
    -{
    -	xfs_rtblock_t	besti;		/* best rtblock found so far */
    -	xfs_rtblock_t	bestlen;	/* best length found so far */
    -	xfs_rtblock_t	end;		/* last rtblock in chunk */
    -	int		error;		/* error value */
    -	xfs_rtblock_t	i;		/* current rtblock trying */
    -	xfs_rtblock_t	next;		/* next rtblock to try */
    -	int		stat;		/* status from internal calls */
    -
    -	/*
    -	 * Loop over all the extents starting in this bitmap block,
    -	 * looking for one that's long enough.
    -	 */
    -	for (i = XFS_BLOCKTOBIT(mp, bbno), besti = -1, bestlen = 0,
    -		end = XFS_BLOCKTOBIT(mp, bbno + 1) - 1;
    -	     i <= end;
    -	     i++) {
    -		/*
    -		 * See if there's a free extent of maxlen starting at i.
    -		 * If it's not so then next will contain the first non-free.
    -		 */
    -		error = xfs_rtcheck_range(mp, tp, i, maxlen, 1, &next, &stat);
    -		if (error) {
    -			return error;
    -		}
    -		if (stat) {
    -			/*
    -			 * i for maxlen is all free, allocate and return that.
    -			 */
    -			error = xfs_rtallocate_range(mp, tp, i, maxlen, rbpp,
    -				rsb);
    -			if (error) {
    -				return error;
    -			}
    -			*len = maxlen;
    -			*rtblock = i;
    -			return 0;
    -		}
    -		/*
    -		 * In the case where we have a variable-sized allocation
    -		 * request, figure out how big this free piece is,
    -		 * and if it's big enough for the minimum, and the best
    -		 * so far, remember it.
    -		 */
    -		if (minlen < maxlen) {
    -			xfs_rtblock_t	thislen;	/* this extent size */
    -
    -			thislen = next - i;
    -			if (thislen >= minlen && thislen > bestlen) {
    -				besti = i;
    -				bestlen = thislen;
    -			}
    -		}
    -		/*
    -		 * If not done yet, find the start of the next free space.
    -		 */
    -		if (next < end) {
    -			error = xfs_rtfind_forw(mp, tp, next, end, &i);
    -			if (error) {
    -				return error;
    -			}
    -		} else
    -			break;
    -	}
    -	/*
    -	 * Searched the whole thing & didn't find a maxlen free extent.
    -	 */
    -	if (minlen < maxlen && besti != -1) {
    -		xfs_extlen_t	p;	/* amount to trim length by */
    -
    -		/*
    -		 * If size should be a multiple of prod, make that so.
    -		 */
    -		if (prod > 1 && (p = do_mod(bestlen, prod)))
    -			bestlen -= p;
    -		/*
    -		 * Allocate besti for bestlen & return that.
    -		 */
    -		error = xfs_rtallocate_range(mp, tp, besti, bestlen, rbpp, rsb);
    -		if (error) {
    -			return error;
    -		}
    -		*len = bestlen;
    -		*rtblock = besti;
    -		return 0;
    -	}
    -	/*
    -	 * Allocation failed.  Set *nextp to the next block to try.
    -	 */
    -	*nextp = next;
    -	*rtblock = NULLRTBLOCK;
    -	return 0;
    -}
    -
    -/*
    - * Allocate an extent of length minlen<=len<=maxlen, starting at block
    - * bno.  If we don't get maxlen then use prod to trim the length, if given.
    - * Returns error; returns starting block in *rtblock.
    - * The lengths are all in rtextents.
    - */
    -STATIC int				/* error */
    -xfs_rtallocate_extent_exact(
    -	xfs_mount_t	*mp,		/* file system mount point */
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_rtblock_t	bno,		/* starting block number to allocate */
    -	xfs_extlen_t	minlen,		/* minimum length to allocate */
    -	xfs_extlen_t	maxlen,		/* maximum length to allocate */
    -	xfs_extlen_t	*len,		/* out: actual length allocated */
    -	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */
    -	xfs_fsblock_t	*rsb,		/* in/out: summary block number */
    -	xfs_extlen_t	prod,		/* extent product factor */
    -	xfs_rtblock_t	*rtblock)	/* out: start block allocated */
    -{
    -	int		error;		/* error value */
    -	xfs_extlen_t	i;		/* extent length trimmed due to prod */
    -	int		isfree;		/* extent is free */
    -	xfs_rtblock_t	next;		/* next block to try (dummy) */
    -
    -	ASSERT(minlen % prod == 0 && maxlen % prod == 0);
    -	/*
    -	 * Check if the range in question (for maxlen) is free.
    -	 */
    -	error = xfs_rtcheck_range(mp, tp, bno, maxlen, 1, &next, &isfree);
    -	if (error) {
    -		return error;
    -	}
    -	if (isfree) {
    -		/*
    -		 * If it is, allocate it and return success.
    -		 */
    -		error = xfs_rtallocate_range(mp, tp, bno, maxlen, rbpp, rsb);
    -		if (error) {
    -			return error;
    -		}
    -		*len = maxlen;
    -		*rtblock = bno;
    -		return 0;
    -	}
    -	/*
    -	 * If not, allocate what there is, if it's at least minlen.
    -	 */
    -	maxlen = next - bno;
    -	if (maxlen < minlen) {
    -		/*
    -		 * Failed, return failure status.
    -		 */
    -		*rtblock = NULLRTBLOCK;
    -		return 0;
    -	}
    -	/*
    -	 * Trim off tail of extent, if prod is specified.
    -	 */
    -	if (prod > 1 && (i = maxlen % prod)) {
    -		maxlen -= i;
    -		if (maxlen < minlen) {
    -			/*
    -			 * Now we can't do it, return failure status.
    -			 */
    -			*rtblock = NULLRTBLOCK;
    -			return 0;
    -		}
    -	}
    -	/*
    -	 * Allocate what we can and return it.
    -	 */
    -	error = xfs_rtallocate_range(mp, tp, bno, maxlen, rbpp, rsb);
    -	if (error) {
    -		return error;
    -	}
    -	*len = maxlen;
    -	*rtblock = bno;
    -	return 0;
    -}
    -
    -/*
    - * Allocate an extent of length minlen<=len<=maxlen, starting as near
    - * to bno as possible.  If we don't get maxlen then use prod to trim
    - * the length, if given.  The lengths are all in rtextents.
    - */
    -STATIC int				/* error */
    -xfs_rtallocate_extent_near(
    -	xfs_mount_t	*mp,		/* file system mount point */
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_rtblock_t	bno,		/* starting block number to allocate */
    -	xfs_extlen_t	minlen,		/* minimum length to allocate */
    -	xfs_extlen_t	maxlen,		/* maximum length to allocate */
    -	xfs_extlen_t	*len,		/* out: actual length allocated */
    -	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */
    -	xfs_fsblock_t	*rsb,		/* in/out: summary block number */
    -	xfs_extlen_t	prod,		/* extent product factor */
    -	xfs_rtblock_t	*rtblock)	/* out: start block allocated */
    -{
    -	int		any;		/* any useful extents from summary */
    -	xfs_rtblock_t	bbno;		/* bitmap block number */
    -	int		error;		/* error value */
    -	int		i;		/* bitmap block offset (loop control) */
    -	int		j;		/* secondary loop control */
    -	int		log2len;	/* log2 of minlen */
    -	xfs_rtblock_t	n;		/* next block to try */
    -	xfs_rtblock_t	r;		/* result block */
    -
    -	ASSERT(minlen % prod == 0 && maxlen % prod == 0);
    -	/*
    -	 * If the block number given is off the end, silently set it to
    -	 * the last block.
    -	 */
    -	if (bno >= mp->m_sb.sb_rextents)
    -		bno = mp->m_sb.sb_rextents - 1;
    -	/*
    -	 * Try the exact allocation first.
    -	 */
    -	error = xfs_rtallocate_extent_exact(mp, tp, bno, minlen, maxlen, len,
    -		rbpp, rsb, prod, &r);
    -	if (error) {
    -		return error;
    -	}
    -	/*
    -	 * If the exact allocation worked, return that.
    -	 */
    -	if (r != NULLRTBLOCK) {
    -		*rtblock = r;
    -		return 0;
    -	}
    -	bbno = XFS_BITTOBLOCK(mp, bno);
    -	i = 0;
    -	log2len = xfs_highbit32(minlen);
    -	/*
    -	 * Loop over all bitmap blocks (bbno + i is current block).
    -	 */
    -	for (;;) {
    -		/*
    -		 * Get summary information of extents of all useful levels
    -		 * starting in this bitmap block.
    -		 */
    -		error = xfs_rtany_summary(mp, tp, log2len, mp->m_rsumlevels - 1,
    -			bbno + i, rbpp, rsb, &any);
    -		if (error) {
    -			return error;
    -		}
    -		/*
    -		 * If there are any useful extents starting here, try
    -		 * allocating one.
    -		 */
    -		if (any) {
    -			/*
    -			 * On the positive side of the starting location.
    -			 */
    -			if (i >= 0) {
    -				/*
    -				 * Try to allocate an extent starting in
    -				 * this block.
    -				 */
    -				error = xfs_rtallocate_extent_block(mp, tp,
    -					bbno + i, minlen, maxlen, len, &n, rbpp,
    -					rsb, prod, &r);
    -				if (error) {
    -					return error;
    -				}
    -				/*
    -				 * If it worked, return it.
    -				 */
    -				if (r != NULLRTBLOCK) {
    -					*rtblock = r;
    -					return 0;
    -				}
    -			}
    -			/*
    -			 * On the negative side of the starting location.
    -			 */
    -			else {		/* i < 0 */
    -				/*
    -				 * Loop backwards through the bitmap blocks from
    -				 * the starting point-1 up to where we are now.
    -				 * There should be an extent which ends in this
    -				 * bitmap block and is long enough.
    -				 */
    -				for (j = -1; j > i; j--) {
    -					/*
    -					 * Grab the summary information for
    -					 * this bitmap block.
    -					 */
    -					error = xfs_rtany_summary(mp, tp,
    -						log2len, mp->m_rsumlevels - 1,
    -						bbno + j, rbpp, rsb, &any);
    -					if (error) {
    -						return error;
    -					}
    -					/*
    -					 * If there's no extent given in the
    -					 * summary that means the extent we
    -					 * found must carry over from an
    -					 * earlier block.  If there is an
    -					 * extent given, we've already tried
    -					 * that allocation, don't do it again.
    -					 */
    -					if (any)
    -						continue;
    -					error = xfs_rtallocate_extent_block(mp,
    -						tp, bbno + j, minlen, maxlen,
    -						len, &n, rbpp, rsb, prod, &r);
    -					if (error) {
    -						return error;
    -					}
    -					/*
    -					 * If it works, return the extent.
    -					 */
    -					if (r != NULLRTBLOCK) {
    -						*rtblock = r;
    -						return 0;
    -					}
    -				}
    -				/*
    -				 * There weren't intervening bitmap blocks
    -				 * with a long enough extent, or the
    -				 * allocation didn't work for some reason
    -				 * (i.e. it's a little * too short).
    -				 * Try to allocate from the summary block
    -				 * that we found.
    -				 */
    -				error = xfs_rtallocate_extent_block(mp, tp,
    -					bbno + i, minlen, maxlen, len, &n, rbpp,
    -					rsb, prod, &r);
    -				if (error) {
    -					return error;
    -				}
    -				/*
    -				 * If it works, return the extent.
    -				 */
    -				if (r != NULLRTBLOCK) {
    -					*rtblock = r;
    -					return 0;
    -				}
    -			}
    -		}
    -		/*
    -		 * Loop control.  If we were on the positive side, and there's
    -		 * still more blocks on the negative side, go there.
    -		 */
    -		if (i > 0 && (int)bbno - i >= 0)
    -			i = -i;
    -		/*
    -		 * If positive, and no more negative, but there are more
    -		 * positive, go there.
    -		 */
    -		else if (i > 0 && (int)bbno + i < mp->m_sb.sb_rbmblocks - 1)
    -			i++;
    -		/*
    -		 * If negative or 0 (just started), and there are positive
    -		 * blocks to go, go there.  The 0 case moves to block 1.
    -		 */
    -		else if (i <= 0 && (int)bbno - i < mp->m_sb.sb_rbmblocks - 1)
    -			i = 1 - i;
    -		/*
    -		 * If negative or 0 and there are more negative blocks,
    -		 * go there.
    -		 */
    -		else if (i <= 0 && (int)bbno + i > 0)
    -			i--;
    -		/*
    -		 * Must be done.  Return failure.
    -		 */
    -		else
    -			break;
    -	}
    -	*rtblock = NULLRTBLOCK;
    -	return 0;
    -}
    -
    -/*
    - * Allocate an extent of length minlen<=len<=maxlen, with no position
    - * specified.  If we don't get maxlen then use prod to trim
    - * the length, if given.  The lengths are all in rtextents.
    - */
    -STATIC int				/* error */
    -xfs_rtallocate_extent_size(
    -	xfs_mount_t	*mp,		/* file system mount point */
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_extlen_t	minlen,		/* minimum length to allocate */
    -	xfs_extlen_t	maxlen,		/* maximum length to allocate */
    -	xfs_extlen_t	*len,		/* out: actual length allocated */
    -	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */
    -	xfs_fsblock_t	*rsb,		/* in/out: summary block number */
    -	xfs_extlen_t	prod,		/* extent product factor */
    -	xfs_rtblock_t	*rtblock)	/* out: start block allocated */
    -{
    -	int		error;		/* error value */
    -	int		i;		/* bitmap block number */
    -	int		l;		/* level number (loop control) */
    -	xfs_rtblock_t	n;		/* next block to be tried */
    -	xfs_rtblock_t	r;		/* result block number */
    -	xfs_suminfo_t	sum;		/* summary information for extents */
    -
    -	ASSERT(minlen % prod == 0 && maxlen % prod == 0);
    -	/*
    -	 * Loop over all the levels starting with maxlen.
    -	 * At each level, look at all the bitmap blocks, to see if there
    -	 * are extents starting there that are long enough (>= maxlen).
    -	 * Note, only on the initial level can the allocation fail if
    -	 * the summary says there's an extent.
    -	 */
    -	for (l = xfs_highbit32(maxlen); l < mp->m_rsumlevels; l++) {
    -		/*
    -		 * Loop over all the bitmap blocks.
    -		 */
    -		for (i = 0; i < mp->m_sb.sb_rbmblocks; i++) {
    -			/*
    -			 * Get the summary for this level/block.
    -			 */
    -			error = xfs_rtget_summary(mp, tp, l, i, rbpp, rsb,
    -				&sum);
    -			if (error) {
    -				return error;
    -			}
    -			/*
    -			 * Nothing there, on to the next block.
    -			 */
    -			if (!sum)
    -				continue;
    -			/*
    -			 * Try allocating the extent.
    -			 */
    -			error = xfs_rtallocate_extent_block(mp, tp, i, maxlen,
    -				maxlen, len, &n, rbpp, rsb, prod, &r);
    -			if (error) {
    -				return error;
    -			}
    -			/*
    -			 * If it worked, return that.
    -			 */
    -			if (r != NULLRTBLOCK) {
    -				*rtblock = r;
    -				return 0;
    -			}
    -			/*
    -			 * If the "next block to try" returned from the
    -			 * allocator is beyond the next bitmap block,
    -			 * skip to that bitmap block.
    -			 */
    -			if (XFS_BITTOBLOCK(mp, n) > i + 1)
    -				i = XFS_BITTOBLOCK(mp, n) - 1;
    -		}
    -	}
    -	/*
    -	 * Didn't find any maxlen blocks.  Try smaller ones, unless
    -	 * we're asking for a fixed size extent.
    -	 */
    -	if (minlen > --maxlen) {
    -		*rtblock = NULLRTBLOCK;
    -		return 0;
    -	}
    -	/*
    -	 * Loop over sizes, from maxlen down to minlen.
    -	 * This time, when we do the allocations, allow smaller ones
    -	 * to succeed.
    -	 */
    -	for (l = xfs_highbit32(maxlen); l >= xfs_highbit32(minlen); l--) {
    -		/*
    -		 * Loop over all the bitmap blocks, try an allocation
    -		 * starting in that block.
    -		 */
    -		for (i = 0; i < mp->m_sb.sb_rbmblocks; i++) {
    -			/*
    -			 * Get the summary information for this level/block.
    -			 */
    -			error =	xfs_rtget_summary(mp, tp, l, i, rbpp, rsb,
    -						  &sum);
    -			if (error) {
    -				return error;
    -			}
    -			/*
    -			 * If nothing there, go on to next.
    -			 */
    -			if (!sum)
    -				continue;
    -			/*
    -			 * Try the allocation.  Make sure the specified
    -			 * minlen/maxlen are in the possible range for
    -			 * this summary level.
    -			 */
    -			error = xfs_rtallocate_extent_block(mp, tp, i,
    -					XFS_RTMAX(minlen, 1 << l),
    -					XFS_RTMIN(maxlen, (1 << (l + 1)) - 1),
    -					len, &n, rbpp, rsb, prod, &r);
    -			if (error) {
    -				return error;
    -			}
    -			/*
    -			 * If it worked, return that extent.
    -			 */
    -			if (r != NULLRTBLOCK) {
    -				*rtblock = r;
    -				return 0;
    -			}
    -			/*
    -			 * If the "next block to try" returned from the
    -			 * allocator is beyond the next bitmap block,
    -			 * skip to that bitmap block.
    -			 */
    -			if (XFS_BITTOBLOCK(mp, n) > i + 1)
    -				i = XFS_BITTOBLOCK(mp, n) - 1;
    -		}
    -	}
    -	/*
    -	 * Got nothing, return failure.
    -	 */
    -	*rtblock = NULLRTBLOCK;
    -	return 0;
    -}
    -
    -/*
    - * Mark an extent specified by start and len allocated.
    - * Updates all the summary information as well as the bitmap.
    - */
    -STATIC int				/* error */
    -xfs_rtallocate_range(
    -	xfs_mount_t	*mp,		/* file system mount point */
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_rtblock_t	start,		/* start block to allocate */
    -	xfs_extlen_t	len,		/* length to allocate */
    -	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */
    -	xfs_fsblock_t	*rsb)		/* in/out: summary block number */
    -{
    -	xfs_rtblock_t	end;		/* end of the allocated extent */
    -	int		error;		/* error value */
    -	xfs_rtblock_t	postblock;	/* first block allocated > end */
    -	xfs_rtblock_t	preblock;	/* first block allocated < start */
    -
    -	end = start + len - 1;
    -	/*
    -	 * Assume we're allocating out of the middle of a free extent.
    -	 * We need to find the beginning and end of the extent so we can
    -	 * properly update the summary.
    -	 */
    -	error = xfs_rtfind_back(mp, tp, start, 0, &preblock);
    -	if (error) {
    -		return error;
    -	}
    -	/*
    -	 * Find the next allocated block (end of free extent).
    -	 */
    -	error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1,
    -		&postblock);
    -	if (error) {
    -		return error;
    -	}
    -	/*
    -	 * Decrement the summary information corresponding to the entire
    -	 * (old) free extent.
    -	 */
    -	error = xfs_rtmodify_summary(mp, tp,
    -		XFS_RTBLOCKLOG(postblock + 1 - preblock),
    -		XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb);
    -	if (error) {
    -		return error;
    -	}
    -	/*
    -	 * If there are blocks not being allocated at the front of the
    -	 * old extent, add summary data for them to be free.
    -	 */
    -	if (preblock < start) {
    -		error = xfs_rtmodify_summary(mp, tp,
    -			XFS_RTBLOCKLOG(start - preblock),
    -			XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb);
    -		if (error) {
    -			return error;
    -		}
    -	}
    -	/*
    -	 * If there are blocks not being allocated at the end of the
    -	 * old extent, add summary data for them to be free.
    -	 */
    -	if (postblock > end) {
    -		error = xfs_rtmodify_summary(mp, tp,
    -			XFS_RTBLOCKLOG(postblock - end),
    -			XFS_BITTOBLOCK(mp, end + 1), 1, rbpp, rsb);
    -		if (error) {
    -			return error;
    -		}
    -	}
    -	/*
    -	 * Modify the bitmap to mark this extent allocated.
    -	 */
    -	error = xfs_rtmodify_range(mp, tp, start, len, 0);
    -	return error;
    -}
    -
    -/*
    - * Return whether there are any free extents in the size range given
    - * by low and high, for the bitmap block bbno.
    - */
    -STATIC int				/* error */
    -xfs_rtany_summary(
    -	xfs_mount_t	*mp,		/* file system mount structure */
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	int		low,		/* low log2 extent size */
    -	int		high,		/* high log2 extent size */
    -	xfs_rtblock_t	bbno,		/* bitmap block number */
    -	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */
    -	xfs_fsblock_t	*rsb,		/* in/out: summary block number */
    -	int		*stat)		/* out: any good extents here? */
    -{
    -	int		error;		/* error value */
    -	int		log;		/* loop counter, log2 of ext. size */
    -	xfs_suminfo_t	sum;		/* summary data */
    -
    -	/*
    -	 * Loop over logs of extent sizes.  Order is irrelevant.
    -	 */
    -	for (log = low; log <= high; log++) {
    -		/*
    -		 * Get one summary datum.
    -		 */
    -		error = xfs_rtget_summary(mp, tp, log, bbno, rbpp, rsb, &sum);
    -		if (error) {
    -			return error;
    -		}
    -		/*
    -		 * If there are any, return success.
    -		 */
    -		if (sum) {
    -			*stat = 1;
    -			return 0;
    -		}
    -	}
    -	/*
    -	 * Found nothing, return failure.
    -	 */
    -	*stat = 0;
    -	return 0;
    -}
    -
    -/*
    - * Get a buffer for the bitmap or summary file block specified.
    - * The buffer is returned read and locked.
    - */
    -STATIC int				/* error */
    -xfs_rtbuf_get(
    -	xfs_mount_t	*mp,		/* file system mount structure */
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_rtblock_t	block,		/* block number in bitmap or summary */
    -	int		issum,		/* is summary not bitmap */
    -	xfs_buf_t	**bpp)		/* output: buffer for the block */
    -{
    -	xfs_buf_t	*bp;		/* block buffer, result */
    -	xfs_daddr_t	d;		/* disk addr of block */
    -	int		error;		/* error value */
    -	xfs_fsblock_t	fsb;		/* fs block number for block */
    -	xfs_inode_t	*ip;		/* bitmap or summary inode */
    -
    -	ip = issum ? mp->m_rsumip : mp->m_rbmip;
    -	/*
    -	 * Map from the file offset (block) and inode number to the
    -	 * file system block.
    -	 */
    -	error = xfs_bmapi_single(tp, ip, XFS_DATA_FORK, &fsb, block);
    -	if (error) {
    -		return error;
    -	}
    -	ASSERT(fsb != NULLFSBLOCK);
    -	/*
    -	 * Convert to disk address for buffer cache.
    -	 */
    -	d = XFS_FSB_TO_DADDR(mp, fsb);
    -	/*
    -	 * Read the buffer.
    -	 */
    -	error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, d,
    -				   mp->m_bsize, 0, &bp);
    -	if (error) {
    -		return error;
    -	}
    -	ASSERT(bp && !XFS_BUF_GETERROR(bp));
    -	*bpp = bp;
    -	return 0;
    -}
    -
    -#ifdef DEBUG
    -/*
    - * Check that the given extent (block range) is allocated already.
    - */
    -STATIC int				/* error */
    -xfs_rtcheck_alloc_range(
    -	xfs_mount_t	*mp,		/* file system mount point */
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_rtblock_t	bno,		/* starting block number of extent */
    -	xfs_extlen_t	len,		/* length of extent */
    -	int		*stat)		/* out: 1 for allocated, 0 for not */
    -{
    -	xfs_rtblock_t	new;		/* dummy for xfs_rtcheck_range */
    -
    -	return xfs_rtcheck_range(mp, tp, bno, len, 0, &new, stat);
    -}
    -#endif
    -
    -#ifdef DEBUG
    -/*
    - * Check whether the given block in the bitmap has the given value.
    - */
    -STATIC int				/* 1 for matches, 0 for not */
    -xfs_rtcheck_bit(
    -	xfs_mount_t	*mp,		/* file system mount structure */
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_rtblock_t	start,		/* bit (block) to check */
    -	int		val)		/* 1 for free, 0 for allocated */
    -{
    -	int		bit;		/* bit number in the word */
    -	xfs_rtblock_t	block;		/* bitmap block number */
    -	xfs_buf_t	*bp;		/* buf for the block */
    -	xfs_rtword_t	*bufp;		/* pointer into the buffer */
    -	/* REFERENCED */
    -	int		error;		/* error value */
    -	xfs_rtword_t	wdiff;		/* difference between bit & expected */
    -	int		word;		/* word number in the buffer */
    -	xfs_rtword_t	wval;		/* word value from buffer */
    -
    -	block = XFS_BITTOBLOCK(mp, start);
    -	error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
    -	bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
    -	word = XFS_BITTOWORD(mp, start);
    -	bit = (int)(start & (XFS_NBWORD - 1));
    -	wval = bufp[word];
    -	xfs_trans_brelse(tp, bp);
    -	wdiff = (wval ^ -val) & ((xfs_rtword_t)1 << bit);
    -	return !wdiff;
    -}
    -#endif	/* DEBUG */
    -
    -#if 0
    -/*
    - * Check that the given extent (block range) is free already.
    - */
    -STATIC int				/* error */
    -xfs_rtcheck_free_range(
    -	xfs_mount_t	*mp,		/* file system mount point */
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_rtblock_t	bno,		/* starting block number of extent */
    -	xfs_extlen_t	len,		/* length of extent */
    -	int		*stat)		/* out: 1 for free, 0 for not */
    -{
    -	xfs_rtblock_t	new;		/* dummy for xfs_rtcheck_range */
    -
    -	return xfs_rtcheck_range(mp, tp, bno, len, 1, &new, stat);
    -}
    -#endif
    -
    -/*
    - * Check that the given range is either all allocated (val = 0) or
    - * all free (val = 1).
    - */
    -STATIC int				/* error */
    -xfs_rtcheck_range(
    -	xfs_mount_t	*mp,		/* file system mount point */
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_rtblock_t	start,		/* starting block number of extent */
    -	xfs_extlen_t	len,		/* length of extent */
    -	int		val,		/* 1 for free, 0 for allocated */
    -	xfs_rtblock_t	*new,		/* out: first block not matching */
    -	int		*stat)		/* out: 1 for matches, 0 for not */
    -{
    -	xfs_rtword_t	*b;		/* current word in buffer */
    -	int		bit;		/* bit number in the word */
    -	xfs_rtblock_t	block;		/* bitmap block number */
    -	xfs_buf_t	*bp;		/* buf for the block */
    -	xfs_rtword_t	*bufp;		/* starting word in buffer */
    -	int		error;		/* error value */
    -	xfs_rtblock_t	i;		/* current bit number rel. to start */
    -	xfs_rtblock_t	lastbit;	/* last useful bit in word */
    -	xfs_rtword_t	mask;		/* mask of relevant bits for value */
    -	xfs_rtword_t	wdiff;		/* difference from wanted value */
    -	int		word;		/* word number in the buffer */
    -
    -	/*
    -	 * Compute starting bitmap block number
    -	 */
    -	block = XFS_BITTOBLOCK(mp, start);
    -	/*
    -	 * Read the bitmap block.
    -	 */
    -	error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
    -	if (error) {
    -		return error;
    -	}
    -	bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
    -	/*
    -	 * Compute the starting word's address, and starting bit.
    -	 */
    -	word = XFS_BITTOWORD(mp, start);
    -	b = &bufp[word];
    -	bit = (int)(start & (XFS_NBWORD - 1));
    -	/*
    -	 * 0 (allocated) => all zero's; 1 (free) => all one's.
    -	 */
    -	val = -val;
    -	/*
    -	 * If not starting on a word boundary, deal with the first
    -	 * (partial) word.
    -	 */
    -	if (bit) {
    -		/*
    -		 * Compute first bit not examined.
    -		 */
    -		lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
    -		/*
    -		 * Mask of relevant bits.
    -		 */
    -		mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
    -		/*
    -		 * Compute difference between actual and desired value.
    -		 */
    -		if ((wdiff = (*b ^ val) & mask)) {
    -			/*
    -			 * Different, compute first wrong bit and return.
    -			 */
    -			xfs_trans_brelse(tp, bp);
    -			i = XFS_RTLOBIT(wdiff) - bit;
    -			*new = start + i;
    -			*stat = 0;
    -			return 0;
    -		}
    -		i = lastbit - bit;
    -		/*
    -		 * Go on to next block if that's where the next word is
    -		 * and we need the next word.
    -		 */
    -		if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
    -			/*
    -			 * If done with this block, get the next one.
    -			 */
    -			xfs_trans_brelse(tp, bp);
    -			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
    -			if (error) {
    -				return error;
    -			}
    -			b = bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
    -			word = 0;
    -		} else {
    -			/*
    -			 * Go on to the next word in the buffer.
    -			 */
    -			b++;
    -		}
    -	} else {
    -		/*
    -		 * Starting on a word boundary, no partial word.
    -		 */
    -		i = 0;
    -	}
    -	/*
    -	 * Loop over whole words in buffers.  When we use up one buffer
    -	 * we move on to the next one.
    -	 */
    -	while (len - i >= XFS_NBWORD) {
    -		/*
    -		 * Compute difference between actual and desired value.
    -		 */
    -		if ((wdiff = *b ^ val)) {
    -			/*
    -			 * Different, compute first wrong bit and return.
    -			 */
    -			xfs_trans_brelse(tp, bp);
    -			i += XFS_RTLOBIT(wdiff);
    -			*new = start + i;
    -			*stat = 0;
    -			return 0;
    -		}
    -		i += XFS_NBWORD;
    -		/*
    -		 * Go on to next block if that's where the next word is
    -		 * and we need the next word.
    -		 */
    -		if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
    -			/*
    -			 * If done with this block, get the next one.
    -			 */
    -			xfs_trans_brelse(tp, bp);
    -			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
    -			if (error) {
    -				return error;
    -			}
    -			b = bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
    -			word = 0;
    -		} else {
    -			/*
    -			 * Go on to the next word in the buffer.
    -			 */
    -			b++;
    -		}
    -	}
    -	/*
    -	 * If not ending on a word boundary, deal with the last
    -	 * (partial) word.
    -	 */
    -	if ((lastbit = len - i)) {
    -		/*
    -		 * Mask of relevant bits.
    -		 */
    -		mask = ((xfs_rtword_t)1 << lastbit) - 1;
    -		/*
    -		 * Compute difference between actual and desired value.
    -		 */
    -		if ((wdiff = (*b ^ val) & mask)) {
    -			/*
    -			 * Different, compute first wrong bit and return.
    -			 */
    -			xfs_trans_brelse(tp, bp);
    -			i += XFS_RTLOBIT(wdiff);
    -			*new = start + i;
    -			*stat = 0;
    -			return 0;
    -		} else
    -			i = len;
    -	}
    -	/*
    -	 * Successful, return.
    -	 */
    -	xfs_trans_brelse(tp, bp);
    -	*new = start + i;
    -	*stat = 1;
    -	return 0;
    -}
    -
    -/*
    - * Copy and transform the summary file, given the old and new
    - * parameters in the mount structures.
    - */
    -STATIC int				/* error */
    -xfs_rtcopy_summary(
    -	xfs_mount_t	*omp,		/* old file system mount point */
    -	xfs_mount_t	*nmp,		/* new file system mount point */
    -	xfs_trans_t	*tp)		/* transaction pointer */
    -{
    -	xfs_rtblock_t	bbno;		/* bitmap block number */
    -	xfs_buf_t	*bp;		/* summary buffer */
    -	int		error;		/* error return value */
    -	int		log;		/* summary level number (log length) */
    -	xfs_suminfo_t	sum;		/* summary data */
    -	xfs_fsblock_t	sumbno;		/* summary block number */
    -
    -	bp = NULL;
    -	for (log = omp->m_rsumlevels - 1; log >= 0; log--) {
    -		for (bbno = omp->m_sb.sb_rbmblocks - 1;
    -		     (xfs_srtblock_t)bbno >= 0;
    -		     bbno--) {
    -			error = xfs_rtget_summary(omp, tp, log, bbno, &bp,
    -				&sumbno, &sum);
    -			if (error)
    -				return error;
    -			if (sum == 0)
    -				continue;
    -			error = xfs_rtmodify_summary(omp, tp, log, bbno, -sum,
    -				&bp, &sumbno);
    -			if (error)
    -				return error;
    -			error = xfs_rtmodify_summary(nmp, tp, log, bbno, sum,
    -				&bp, &sumbno);
    -			if (error)
    -				return error;
    -			ASSERT(sum > 0);
    -		}
    -	}
    -	return 0;
    -}
    -
    -/*
    - * Searching backward from start to limit, find the first block whose
    - * allocated/free state is different from start's.
    - */
    -STATIC int				/* error */
    -xfs_rtfind_back(
    -	xfs_mount_t	*mp,		/* file system mount point */
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_rtblock_t	start,		/* starting block to look at */
    -	xfs_rtblock_t	limit,		/* last block to look at */
    -	xfs_rtblock_t	*rtblock)	/* out: start block found */
    -{
    -	xfs_rtword_t	*b;		/* current word in buffer */
    -	int		bit;		/* bit number in the word */
    -	xfs_rtblock_t	block;		/* bitmap block number */
    -	xfs_buf_t	*bp;		/* buf for the block */
    -	xfs_rtword_t	*bufp;		/* starting word in buffer */
    -	int		error;		/* error value */
    -	xfs_rtblock_t	firstbit;	/* first useful bit in the word */
    -	xfs_rtblock_t	i;		/* current bit number rel. to start */
    -	xfs_rtblock_t	len;		/* length of inspected area */
    -	xfs_rtword_t	mask;		/* mask of relevant bits for value */
    -	xfs_rtword_t	want;		/* mask for "good" values */
    -	xfs_rtword_t	wdiff;		/* difference from wanted value */
    -	int		word;		/* word number in the buffer */
    -
    -	/*
    -	 * Compute and read in starting bitmap block for starting block.
    -	 */
    -	block = XFS_BITTOBLOCK(mp, start);
    -	error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
    -	if (error) {
    -		return error;
    -	}
    -	bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
    -	/*
    -	 * Get the first word's index & point to it.
    -	 */
    -	word = XFS_BITTOWORD(mp, start);
    -	b = &bufp[word];
    -	bit = (int)(start & (XFS_NBWORD - 1));
    -	len = start - limit + 1;
    -	/*
    -	 * Compute match value, based on the bit at start: if 1 (free)
    -	 * then all-ones, else all-zeroes.
    -	 */
    -	want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
    -	/*
    -	 * If the starting position is not word-aligned, deal with the
    -	 * partial word.
    -	 */
    -	if (bit < XFS_NBWORD - 1) {
    -		/*
    -		 * Calculate first (leftmost) bit number to look at,
    -		 * and mask for all the relevant bits in this word.
    -		 */
    -		firstbit = XFS_RTMAX((xfs_srtblock_t)(bit - len + 1), 0);
    -		mask = (((xfs_rtword_t)1 << (bit - firstbit + 1)) - 1) <<
    -			firstbit;
    -		/*
    -		 * Calculate the difference between the value there
    -		 * and what we're looking for.
    -		 */
    -		if ((wdiff = (*b ^ want) & mask)) {
    -			/*
    -			 * Different.  Mark where we are and return.
    -			 */
    -			xfs_trans_brelse(tp, bp);
    -			i = bit - XFS_RTHIBIT(wdiff);
    -			*rtblock = start - i + 1;
    -			return 0;
    -		}
    -		i = bit - firstbit + 1;
    -		/*
    -		 * Go on to previous block if that's where the previous word is
    -		 * and we need the previous word.
    -		 */
    -		if (--word == -1 && i < len) {
    -			/*
    -			 * If done with this block, get the previous one.
    -			 */
    -			xfs_trans_brelse(tp, bp);
    -			error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
    -			if (error) {
    -				return error;
    -			}
    -			bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
    -			word = XFS_BLOCKWMASK(mp);
    -			b = &bufp[word];
    -		} else {
    -			/*
    -			 * Go on to the previous word in the buffer.
    -			 */
    -			b--;
    -		}
    -	} else {
    -		/*
    -		 * Starting on a word boundary, no partial word.
    -		 */
    -		i = 0;
    -	}
    -	/*
    -	 * Loop over whole words in buffers.  When we use up one buffer
    -	 * we move on to the previous one.
    -	 */
    -	while (len - i >= XFS_NBWORD) {
    -		/*
    -		 * Compute difference between actual and desired value.
    -		 */
    -		if ((wdiff = *b ^ want)) {
    -			/*
    -			 * Different, mark where we are and return.
    -			 */
    -			xfs_trans_brelse(tp, bp);
    -			i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
    -			*rtblock = start - i + 1;
    -			return 0;
    -		}
    -		i += XFS_NBWORD;
    -		/*
    -		 * Go on to previous block if that's where the previous word is
    -		 * and we need the previous word.
    -		 */
    -		if (--word == -1 && i < len) {
    -			/*
    -			 * If done with this block, get the previous one.
    -			 */
    -			xfs_trans_brelse(tp, bp);
    -			error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
    -			if (error) {
    -				return error;
    -			}
    -			bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
    -			word = XFS_BLOCKWMASK(mp);
    -			b = &bufp[word];
    -		} else {
    -			/*
    -			 * Go on to the previous word in the buffer.
    -			 */
    -			b--;
    -		}
    -	}
    -	/*
    -	 * If not ending on a word boundary, deal with the last
    -	 * (partial) word.
    -	 */
    -	if (len - i) {
    -		/*
    -		 * Calculate first (leftmost) bit number to look at,
    -		 * and mask for all the relevant bits in this word.
    -		 */
    -		firstbit = XFS_NBWORD - (len - i);
    -		mask = (((xfs_rtword_t)1 << (len - i)) - 1) << firstbit;
    -		/*
    -		 * Compute difference between actual and desired value.
    -		 */
    -		if ((wdiff = (*b ^ want) & mask)) {
    -			/*
    -			 * Different, mark where we are and return.
    -			 */
    -			xfs_trans_brelse(tp, bp);
    -			i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
    -			*rtblock = start - i + 1;
    -			return 0;
    -		} else
    -			i = len;
    -	}
    -	/*
    -	 * No match, return that we scanned the whole area.
    -	 */
    -	xfs_trans_brelse(tp, bp);
    -	*rtblock = start - i + 1;
    -	return 0;
    -}
    -
    -/*
    - * Searching forward from start to limit, find the first block whose
    - * allocated/free state is different from start's.
    - */
    -STATIC int				/* error */
    -xfs_rtfind_forw(
    -	xfs_mount_t	*mp,		/* file system mount point */
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_rtblock_t	start,		/* starting block to look at */
    -	xfs_rtblock_t	limit,		/* last block to look at */
    -	xfs_rtblock_t	*rtblock)	/* out: start block found */
    -{
    -	xfs_rtword_t	*b;		/* current word in buffer */
    -	int		bit;		/* bit number in the word */
    -	xfs_rtblock_t	block;		/* bitmap block number */
    -	xfs_buf_t	*bp;		/* buf for the block */
    -	xfs_rtword_t	*bufp;		/* starting word in buffer */
    -	int		error;		/* error value */
    -	xfs_rtblock_t	i;		/* current bit number rel. to start */
    -	xfs_rtblock_t	lastbit;	/* last useful bit in the word */
    -	xfs_rtblock_t	len;		/* length of inspected area */
    -	xfs_rtword_t	mask;		/* mask of relevant bits for value */
    -	xfs_rtword_t	want;		/* mask for "good" values */
    -	xfs_rtword_t	wdiff;		/* difference from wanted value */
    -	int		word;		/* word number in the buffer */
    -
    -	/*
    -	 * Compute and read in starting bitmap block for starting block.
    -	 */
    -	block = XFS_BITTOBLOCK(mp, start);
    -	error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
    -	if (error) {
    -		return error;
    -	}
    -	bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
    -	/*
    -	 * Get the first word's index & point to it.
    -	 */
    -	word = XFS_BITTOWORD(mp, start);
    -	b = &bufp[word];
    -	bit = (int)(start & (XFS_NBWORD - 1));
    -	len = limit - start + 1;
    -	/*
    -	 * Compute match value, based on the bit at start: if 1 (free)
    -	 * then all-ones, else all-zeroes.
    -	 */
    -	want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
    -	/*
    -	 * If the starting position is not word-aligned, deal with the
    -	 * partial word.
    -	 */
    -	if (bit) {
    -		/*
    -		 * Calculate last (rightmost) bit number to look at,
    -		 * and mask for all the relevant bits in this word.
    -		 */
    -		lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
    -		mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
    -		/*
    -		 * Calculate the difference between the value there
    -		 * and what we're looking for.
    -		 */
    -		if ((wdiff = (*b ^ want) & mask)) {
    -			/*
    -			 * Different.  Mark where we are and return.
    -			 */
    -			xfs_trans_brelse(tp, bp);
    -			i = XFS_RTLOBIT(wdiff) - bit;
    -			*rtblock = start + i - 1;
    -			return 0;
    -		}
    -		i = lastbit - bit;
    -		/*
    -		 * Go on to next block if that's where the next word is
    -		 * and we need the next word.
    -		 */
    -		if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
    -			/*
    -			 * If done with this block, get the previous one.
    -			 */
    -			xfs_trans_brelse(tp, bp);
    -			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
    -			if (error) {
    -				return error;
    -			}
    -			b = bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
    -			word = 0;
    -		} else {
    -			/*
    -			 * Go on to the previous word in the buffer.
    -			 */
    -			b++;
    -		}
    -	} else {
    -		/*
    -		 * Starting on a word boundary, no partial word.
    -		 */
    -		i = 0;
    -	}
    -	/*
    -	 * Loop over whole words in buffers.  When we use up one buffer
    -	 * we move on to the next one.
    -	 */
    -	while (len - i >= XFS_NBWORD) {
    -		/*
    -		 * Compute difference between actual and desired value.
    -		 */
    -		if ((wdiff = *b ^ want)) {
    -			/*
    -			 * Different, mark where we are and return.
    -			 */
    -			xfs_trans_brelse(tp, bp);
    -			i += XFS_RTLOBIT(wdiff);
    -			*rtblock = start + i - 1;
    -			return 0;
    -		}
    -		i += XFS_NBWORD;
    -		/*
    -		 * Go on to next block if that's where the next word is
    -		 * and we need the next word.
    -		 */
    -		if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
    -			/*
    -			 * If done with this block, get the next one.
    -			 */
    -			xfs_trans_brelse(tp, bp);
    -			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
    -			if (error) {
    -				return error;
    -			}
    -			b = bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
    -			word = 0;
    -		} else {
    -			/*
    -			 * Go on to the next word in the buffer.
    -			 */
    -			b++;
    -		}
    -	}
    -	/*
    -	 * If not ending on a word boundary, deal with the last
    -	 * (partial) word.
    -	 */
    -	if ((lastbit = len - i)) {
    -		/*
    -		 * Calculate mask for all the relevant bits in this word.
    -		 */
    -		mask = ((xfs_rtword_t)1 << lastbit) - 1;
    -		/*
    -		 * Compute difference between actual and desired value.
    -		 */
    -		if ((wdiff = (*b ^ want) & mask)) {
    -			/*
    -			 * Different, mark where we are and return.
    -			 */
    -			xfs_trans_brelse(tp, bp);
    -			i += XFS_RTLOBIT(wdiff);
    -			*rtblock = start + i - 1;
    -			return 0;
    -		} else
    -			i = len;
    -	}
    -	/*
    -	 * No match, return that we scanned the whole area.
    -	 */
    -	xfs_trans_brelse(tp, bp);
    -	*rtblock = start + i - 1;
    -	return 0;
    -}
    -
    -/*
    - * Mark an extent specified by start and len freed.
    - * Updates all the summary information as well as the bitmap.
    - */
    -STATIC int				/* error */
    -xfs_rtfree_range(
    -	xfs_mount_t	*mp,		/* file system mount point */
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_rtblock_t	start,		/* starting block to free */
    -	xfs_extlen_t	len,		/* length to free */
    -	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */
    -	xfs_fsblock_t	*rsb)		/* in/out: summary block number */
    -{
    -	xfs_rtblock_t	end;		/* end of the freed extent */
    -	int		error;		/* error value */
    -	xfs_rtblock_t	postblock;	/* first block freed > end */
    -	xfs_rtblock_t	preblock;	/* first block freed < start */
    -
    -	end = start + len - 1;
    -	/*
    -	 * Modify the bitmap to mark this extent freed.
    -	 */
    -	error = xfs_rtmodify_range(mp, tp, start, len, 1);
    -	if (error) {
    -		return error;
    -	}
    -	/*
    -	 * Assume we're freeing out of the middle of an allocated extent.
    -	 * We need to find the beginning and end of the extent so we can
    -	 * properly update the summary.
    -	 */
    -	error = xfs_rtfind_back(mp, tp, start, 0, &preblock);
    -	if (error) {
    -		return error;
    -	}
    -	/*
    -	 * Find the next allocated block (end of allocated extent).
    -	 */
    -	error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1,
    -		&postblock);
    -	/*
    -	 * If there are blocks not being freed at the front of the
    -	 * old extent, add summary data for them to be allocated.
    -	 */
    -	if (preblock < start) {
    -		error = xfs_rtmodify_summary(mp, tp,
    -			XFS_RTBLOCKLOG(start - preblock),
    -			XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb);
    -		if (error) {
    -			return error;
    -		}
    -	}
    -	/*
    -	 * If there are blocks not being freed at the end of the
    -	 * old extent, add summary data for them to be allocated.
    -	 */
    -	if (postblock > end) {
    -		error = xfs_rtmodify_summary(mp, tp,
    -			XFS_RTBLOCKLOG(postblock - end),
    -			XFS_BITTOBLOCK(mp, end + 1), -1, rbpp, rsb);
    -		if (error) {
    -			return error;
    -		}
    -	}
    -	/*
    -	 * Increment the summary information corresponding to the entire
    -	 * (new) free extent.
    -	 */
    -	error = xfs_rtmodify_summary(mp, tp,
    -		XFS_RTBLOCKLOG(postblock + 1 - preblock),
    -		XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb);
    -	return error;
    -}
    -
    -/*
    - * Read and return the summary information for a given extent size,
    - * bitmap block combination.
    - * Keeps track of a current summary block, so we don't keep reading
    - * it from the buffer cache.
    - */
    -STATIC int				/* error */
    -xfs_rtget_summary(
    -	xfs_mount_t	*mp,		/* file system mount structure */
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	int		log,		/* log2 of extent size */
    -	xfs_rtblock_t	bbno,		/* bitmap block number */
    -	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */
    -	xfs_fsblock_t	*rsb,		/* in/out: summary block number */
    -	xfs_suminfo_t	*sum)		/* out: summary info for this block */
    -{
    -	xfs_buf_t	*bp;		/* buffer for summary block */
    -	int		error;		/* error value */
    -	xfs_fsblock_t	sb;		/* summary fsblock */
    -	int		so;		/* index into the summary file */
    -	xfs_suminfo_t	*sp;		/* pointer to returned data */
    -
    -	/*
    -	 * Compute entry number in the summary file.
    -	 */
    -	so = XFS_SUMOFFS(mp, log, bbno);
    -	/*
    -	 * Compute the block number in the summary file.
    -	 */
    -	sb = XFS_SUMOFFSTOBLOCK(mp, so);
    -	/*
    -	 * If we have an old buffer, and the block number matches, use that.
    -	 */
    -	if (rbpp && *rbpp && *rsb == sb)
    -		bp = *rbpp;
    -	/*
    -	 * Otherwise we have to get the buffer.
    -	 */
    -	else {
    -		/*
    -		 * If there was an old one, get rid of it first.
    -		 */
    -		if (rbpp && *rbpp)
    -			xfs_trans_brelse(tp, *rbpp);
    -		error = xfs_rtbuf_get(mp, tp, sb, 1, &bp);
    -		if (error) {
    -			return error;
    -		}
    -		/*
    -		 * Remember this buffer and block for the next call.
    -		 */
    -		if (rbpp) {
    -			*rbpp = bp;
    -			*rsb = sb;
    -		}
    -	}
    -	/*
    -	 * Point to the summary information & copy it out.
    -	 */
    -	sp = XFS_SUMPTR(mp, bp, so);
    -	*sum = *sp;
    -	/*
    -	 * Drop the buffer if we're not asked to remember it.
    -	 */
    -	if (!rbpp)
    -		xfs_trans_brelse(tp, bp);
    -	return 0;
    -}
    -
    -/*
    - * Set the given range of bitmap bits to the given value.
    - * Do whatever I/O and logging is required.
    - */
    -STATIC int				/* error */
    -xfs_rtmodify_range(
    -	xfs_mount_t	*mp,		/* file system mount point */
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_rtblock_t	start,		/* starting block to modify */
    -	xfs_extlen_t	len,		/* length of extent to modify */
    -	int		val)		/* 1 for free, 0 for allocated */
    -{
    -	xfs_rtword_t	*b;		/* current word in buffer */
    -	int		bit;		/* bit number in the word */
    -	xfs_rtblock_t	block;		/* bitmap block number */
    -	xfs_buf_t	*bp;		/* buf for the block */
    -	xfs_rtword_t	*bufp;		/* starting word in buffer */
    -	int		error;		/* error value */
    -	xfs_rtword_t	*first;		/* first used word in the buffer */
    -	int		i;		/* current bit number rel. to start */
    -	int		lastbit;	/* last useful bit in word */
    -	xfs_rtword_t	mask;		/* mask o frelevant bits for value */
    -	int		word;		/* word number in the buffer */
    -
    -	/*
    -	 * Compute starting bitmap block number.
    -	 */
    -	block = XFS_BITTOBLOCK(mp, start);
    -	/*
    -	 * Read the bitmap block, and point to its data.
    -	 */
    -	error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
    -	if (error) {
    -		return error;
    -	}
    -	bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
    -	/*
    -	 * Compute the starting word's address, and starting bit.
    -	 */
    -	word = XFS_BITTOWORD(mp, start);
    -	first = b = &bufp[word];
    -	bit = (int)(start & (XFS_NBWORD - 1));
    -	/*
    -	 * 0 (allocated) => all zeroes; 1 (free) => all ones.
    -	 */
    -	val = -val;
    -	/*
    -	 * If not starting on a word boundary, deal with the first
    -	 * (partial) word.
    -	 */
    -	if (bit) {
    -		/*
    -		 * Compute first bit not changed and mask of relevant bits.
    -		 */
    -		lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
    -		mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
    -		/*
    -		 * Set/clear the active bits.
    -		 */
    -		if (val)
    -			*b |= mask;
    -		else
    -			*b &= ~mask;
    -		i = lastbit - bit;
    -		/*
    -		 * Go on to the next block if that's where the next word is
    -		 * and we need the next word.
    -		 */
    -		if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
    -			/*
    -			 * Log the changed part of this block.
    -			 * Get the next one.
    -			 */
    -			xfs_trans_log_buf(tp, bp,
    -				(uint)((char *)first - (char *)bufp),
    -				(uint)((char *)b - (char *)bufp));
    -			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
    -			if (error) {
    -				return error;
    -			}
    -			first = b = bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
    -			word = 0;
    -		} else {
    -			/*
    -			 * Go on to the next word in the buffer
    -			 */
    -			b++;
    -		}
    -	} else {
    -		/*
    -		 * Starting on a word boundary, no partial word.
    -		 */
    -		i = 0;
    -	}
    -	/*
    -	 * Loop over whole words in buffers.  When we use up one buffer
    -	 * we move on to the next one.
    -	 */
    -	while (len - i >= XFS_NBWORD) {
    -		/*
    -		 * Set the word value correctly.
    -		 */
    -		*b = val;
    -		i += XFS_NBWORD;
    -		/*
    -		 * Go on to the next block if that's where the next word is
    -		 * and we need the next word.
    -		 */
    -		if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
    -			/*
    -			 * Log the changed part of this block.
    -			 * Get the next one.
    -			 */
    -			xfs_trans_log_buf(tp, bp,
    -				(uint)((char *)first - (char *)bufp),
    -				(uint)((char *)b - (char *)bufp));
    -			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
    -			if (error) {
    -				return error;
    -			}
    -			first = b = bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
    -			word = 0;
    -		} else {
    -			/*
    -			 * Go on to the next word in the buffer
    -			 */
    -			b++;
    -		}
    -	}
    -	/*
    -	 * If not ending on a word boundary, deal with the last
    -	 * (partial) word.
    -	 */
    -	if ((lastbit = len - i)) {
    -		/*
    -		 * Compute a mask of relevant bits.
    -		 */
    -		bit = 0;
    -		mask = ((xfs_rtword_t)1 << lastbit) - 1;
    -		/*
    -		 * Set/clear the active bits.
    -		 */
    -		if (val)
    -			*b |= mask;
    -		else
    -			*b &= ~mask;
    -		b++;
    -	}
    -	/*
    -	 * Log any remaining changed bytes.
    -	 */
    -	if (b > first)
    -		xfs_trans_log_buf(tp, bp, (uint)((char *)first - (char *)bufp),
    -			(uint)((char *)b - (char *)bufp - 1));
    -	return 0;
    -}
    -
    -/*
    - * Read and modify the summary information for a given extent size,
    - * bitmap block combination.
    - * Keeps track of a current summary block, so we don't keep reading
    - * it from the buffer cache.
    - */
    -STATIC int				/* error */
    -xfs_rtmodify_summary(
    -	xfs_mount_t	*mp,		/* file system mount point */
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	int		log,		/* log2 of extent size */
    -	xfs_rtblock_t	bbno,		/* bitmap block number */
    -	int		delta,		/* change to make to summary info */
    -	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */
    -	xfs_fsblock_t	*rsb)		/* in/out: summary block number */
    -{
    -	xfs_buf_t	*bp;		/* buffer for the summary block */
    -	int		error;		/* error value */
    -	xfs_fsblock_t	sb;		/* summary fsblock */
    -	int		so;		/* index into the summary file */
    -	xfs_suminfo_t	*sp;		/* pointer to returned data */
    -
    -	/*
    -	 * Compute entry number in the summary file.
    -	 */
    -	so = XFS_SUMOFFS(mp, log, bbno);
    -	/*
    -	 * Compute the block number in the summary file.
    -	 */
    -	sb = XFS_SUMOFFSTOBLOCK(mp, so);
    -	/*
    -	 * If we have an old buffer, and the block number matches, use that.
    -	 */
    -	if (rbpp && *rbpp && *rsb == sb)
    -		bp = *rbpp;
    -	/*
    -	 * Otherwise we have to get the buffer.
    -	 */
    -	else {
    -		/*
    -		 * If there was an old one, get rid of it first.
    -		 */
    -		if (rbpp && *rbpp)
    -			xfs_trans_brelse(tp, *rbpp);
    -		error = xfs_rtbuf_get(mp, tp, sb, 1, &bp);
    -		if (error) {
    -			return error;
    -		}
    -		/*
    -		 * Remember this buffer and block for the next call.
    -		 */
    -		if (rbpp) {
    -			*rbpp = bp;
    -			*rsb = sb;
    -		}
    -	}
    -	/*
    -	 * Point to the summary information, modify and log it.
    -	 */
    -	sp = XFS_SUMPTR(mp, bp, so);
    -	*sp += delta;
    -	xfs_trans_log_buf(tp, bp, (uint)((char *)sp - (char *)XFS_BUF_PTR(bp)),
    -		(uint)((char *)sp - (char *)XFS_BUF_PTR(bp) + sizeof(*sp) - 1));
    -	return 0;
    -}
    -
    -/*
    - * Visible (exported) functions.
    - */
    -
    -/*
    - * Grow the realtime area of the filesystem.
    - */
    -int
    -xfs_growfs_rt(
    -	xfs_mount_t	*mp,		/* mount point for filesystem */
    -	xfs_growfs_rt_t	*in)		/* growfs rt input struct */
    -{
    -	xfs_rtblock_t	bmbno;		/* bitmap block number */
    -	xfs_buf_t	*bp;		/* temporary buffer */
    -	int		cancelflags;	/* flags for xfs_trans_cancel */
    -	int		error;		/* error return value */
    -	xfs_inode_t	*ip;		/* bitmap inode, used as lock */
    -	xfs_mount_t	*nmp;		/* new (fake) mount structure */
    -	xfs_drfsbno_t	nrblocks;	/* new number of realtime blocks */
    -	xfs_extlen_t	nrbmblocks;	/* new number of rt bitmap blocks */
    -	xfs_drtbno_t	nrextents;	/* new number of realtime extents */
    -	uint8_t		nrextslog;	/* new log2 of sb_rextents */
    -	xfs_extlen_t	nrsumblocks;	/* new number of summary blocks */
    -	uint		nrsumlevels;	/* new rt summary levels */
    -	uint		nrsumsize;	/* new size of rt summary, bytes */
    -	xfs_sb_t	*nsbp;		/* new superblock */
    -	xfs_extlen_t	rbmblocks;	/* current number of rt bitmap blocks */
    -	xfs_extlen_t	rsumblocks;	/* current number of rt summary blks */
    -	xfs_sb_t	*sbp;		/* old superblock */
    -	xfs_fsblock_t	sumbno;		/* summary block number */
    -	xfs_trans_t	*tp;		/* transaction pointer */
    -
    -	sbp = &mp->m_sb;
    -	/*
    -	 * Initial error checking.
    -	 */
    -	if (mp->m_rtdev_targp || mp->m_rbmip == NULL ||
    -	    (nrblocks = in->newblocks) <= sbp->sb_rblocks ||
    -	    (sbp->sb_rblocks && (in->extsize != sbp->sb_rextsize)))
    -		return XFS_ERROR(EINVAL);
    -	/*
    -	 * Read in the last block of the device, make sure it exists.
    -	 */
    -	error = xfs_read_buf(mp, mp->m_rtdev_targp,
    -			XFS_FSB_TO_BB(mp, in->newblocks - 1),
    -			XFS_FSB_TO_BB(mp, 1), 0, &bp);
    -	if (error)
    -		return error;
    -	ASSERT(bp);
    -	xfs_buf_relse(bp);
    -	/*
    -	 * Calculate new parameters.  These are the final values to be reached.
    -	 */
    -	nrextents = nrblocks;
    -	do_div(nrextents, in->extsize);
    -	nrbmblocks = roundup_64(nrextents, NBBY * sbp->sb_blocksize);
    -	nrextslog = xfs_highbit32(nrextents);
    -	nrsumlevels = nrextslog + 1;
    -	nrsumsize = (uint)sizeof(xfs_suminfo_t) * nrsumlevels * nrbmblocks;
    -	nrsumblocks = XFS_B_TO_FSB(mp, nrsumsize);
    -	nrsumsize = XFS_FSB_TO_B(mp, nrsumblocks);
    -	/*
    -	 * New summary size can't be more than half the size of
    -	 * the log.  This prevents us from getting a log overflow,
    -	 * since we'll log basically the whole summary file at once.
    -	 */
    -	if (nrsumblocks > (mp->m_sb.sb_logblocks >> 1))
    -		return XFS_ERROR(EINVAL);
    -	/*
    -	 * Get the old block counts for bitmap and summary inodes.
    -	 * These can't change since other growfs callers are locked out.
    -	 */
    -	rbmblocks = XFS_B_TO_FSB(mp, mp->m_rbmip->i_d.di_size);
    -	rsumblocks = XFS_B_TO_FSB(mp, mp->m_rsumip->i_d.di_size);
    -	/*
    -	 * Allocate space to the bitmap and summary files, as necessary.
    -	 */
    -	if ((error = xfs_growfs_rt_alloc(mp, rbmblocks, nrbmblocks,
    -			mp->m_sb.sb_rbmino)))
    -		return error;
    -	if ((error = xfs_growfs_rt_alloc(mp, rsumblocks, nrsumblocks,
    -			mp->m_sb.sb_rsumino)))
    -		return error;
    -	nmp = NULL;
    -	/*
    -	 * Loop over the bitmap blocks.
    -	 * We will do everything one bitmap block at a time.
    -	 * Skip the current block if it is exactly full.
    -	 * This also deals with the case where there were no rtextents before.
    -	 */
    -	for (bmbno = sbp->sb_rbmblocks -
    -		     ((sbp->sb_rextents & ((1 << mp->m_blkbit_log) - 1)) != 0);
    -	     bmbno < nrbmblocks;
    -	     bmbno++) {
    -		/*
    -		 * Allocate a new (fake) mount/sb.
    -		 */
    -		nmp = kmem_alloc(sizeof(*nmp), KM_SLEEP);
    -		*nmp = *mp;
    -		nsbp = &nmp->m_sb;
    -		/*
    -		 * Calculate new sb and mount fields for this round.
    -		 */
    -		nsbp->sb_rextsize = in->extsize;
    -		nsbp->sb_rbmblocks = bmbno + 1;
    -		nsbp->sb_rblocks =
    -			XFS_RTMIN(nrblocks,
    -				  nsbp->sb_rbmblocks * NBBY *
    -				  nsbp->sb_blocksize * nsbp->sb_rextsize);
    -		nsbp->sb_rextents = nsbp->sb_rblocks;
    -		do_div(nsbp->sb_rextents, nsbp->sb_rextsize);
    -		nsbp->sb_rextslog = xfs_highbit32(nsbp->sb_rextents);
    -		nrsumlevels = nmp->m_rsumlevels = nsbp->sb_rextslog + 1;
    -		nrsumsize =
    -			(uint)sizeof(xfs_suminfo_t) * nrsumlevels *
    -			nsbp->sb_rbmblocks;
    -		nrsumblocks = XFS_B_TO_FSB(mp, nrsumsize);
    -		nmp->m_rsumsize = nrsumsize = XFS_FSB_TO_B(mp, nrsumblocks);
    -		/*
    -		 * Start a transaction, get the log reservation.
    -		 */
    -		tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_FREE);
    -		cancelflags = 0;
    -		if ((error = xfs_trans_reserve(tp, 0,
    -				XFS_GROWRTFREE_LOG_RES(nmp), 0, 0, 0)))
    -			goto error_exit;
    -		/*
    -		 * Lock out other callers by grabbing the bitmap inode lock.
    -		 */
    -		if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0,
    -						XFS_ILOCK_EXCL, &ip)))
    -			goto error_exit;
    -		ASSERT(ip == mp->m_rbmip);
    -		/*
    -		 * Update the bitmap inode's size.
    -		 */
    -		mp->m_rbmip->i_d.di_size =
    -			nsbp->sb_rbmblocks * nsbp->sb_blocksize;
    -		xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
    -		cancelflags |= XFS_TRANS_ABORT;
    -		/*
    -		 * Get the summary inode into the transaction.
    -		 */
    -		if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rsumino, 0,
    -						XFS_ILOCK_EXCL, &ip)))
    -			goto error_exit;
    -		ASSERT(ip == mp->m_rsumip);
    -		/*
    -		 * Update the summary inode's size.
    -		 */
    -		mp->m_rsumip->i_d.di_size = nmp->m_rsumsize;
    -		xfs_trans_log_inode(tp, mp->m_rsumip, XFS_ILOG_CORE);
    -		/*
    -		 * Copy summary data from old to new sizes.
    -		 * Do this when the real size (not block-aligned) changes.
    -		 */
    -		if (sbp->sb_rbmblocks != nsbp->sb_rbmblocks ||
    -		    mp->m_rsumlevels != nmp->m_rsumlevels) {
    -			error = xfs_rtcopy_summary(mp, nmp, tp);
    -			if (error)
    -				goto error_exit;
    -		}
    -		/*
    -		 * Update superblock fields.
    -		 */
    -		if (nsbp->sb_rextsize != sbp->sb_rextsize)
    -			xfs_trans_mod_sb(tp, XFS_TRANS_SB_REXTSIZE,
    -				nsbp->sb_rextsize - sbp->sb_rextsize);
    -		if (nsbp->sb_rbmblocks != sbp->sb_rbmblocks)
    -			xfs_trans_mod_sb(tp, XFS_TRANS_SB_RBMBLOCKS,
    -				nsbp->sb_rbmblocks - sbp->sb_rbmblocks);
    -		if (nsbp->sb_rblocks != sbp->sb_rblocks)
    -			xfs_trans_mod_sb(tp, XFS_TRANS_SB_RBLOCKS,
    -				nsbp->sb_rblocks - sbp->sb_rblocks);
    -		if (nsbp->sb_rextents != sbp->sb_rextents)
    -			xfs_trans_mod_sb(tp, XFS_TRANS_SB_REXTENTS,
    -				nsbp->sb_rextents - sbp->sb_rextents);
    -		if (nsbp->sb_rextslog != sbp->sb_rextslog)
    -			xfs_trans_mod_sb(tp, XFS_TRANS_SB_REXTSLOG,
    -				nsbp->sb_rextslog - sbp->sb_rextslog);
    -		/*
    -		 * Free new extent.
    -		 */
    -		bp = NULL;
    -		error = xfs_rtfree_range(nmp, tp, sbp->sb_rextents,
    -			nsbp->sb_rextents - sbp->sb_rextents, &bp, &sumbno);
    -		if (error)
    -			goto error_exit;
    -		/*
    -		 * Mark more blocks free in the superblock.
    -		 */
    -		xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS,
    -			nsbp->sb_rextents - sbp->sb_rextents);
    -		/*
    -		 * Free the fake mp structure.
    -		 */
    -		kmem_free(nmp, sizeof(*nmp));
    -		nmp = NULL;
    -		/*
    -		 * Update mp values into the real mp structure.
    -		 */
    -		mp->m_rsumlevels = nrsumlevels;
    -		mp->m_rsumsize = nrsumsize;
    -		/*
    -		 * Commit the transaction.
    -		 */
    -		xfs_trans_commit(tp, 0, NULL);
    -	}
    -	return 0;
    -
    -	/*
    -	 * Error paths come here.
    -	 */
    -error_exit:
    -	if (nmp)
    -		kmem_free(nmp, sizeof(*nmp));
    -	xfs_trans_cancel(tp, cancelflags);
    -	return error;
    -}
    -
    -/*
    - * Allocate an extent in the realtime subvolume, with the usual allocation
    - * parameters.  The length units are all in realtime extents, as is the
    - * result block number.
    - */
    -int					/* error */
    -xfs_rtallocate_extent(
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_rtblock_t	bno,		/* starting block number to allocate */
    -	xfs_extlen_t	minlen,		/* minimum length to allocate */
    -	xfs_extlen_t	maxlen,		/* maximum length to allocate */
    -	xfs_extlen_t	*len,		/* out: actual length allocated */
    -	xfs_alloctype_t	type,		/* allocation type XFS_ALLOCTYPE... */
    -	int		wasdel,		/* was a delayed allocation extent */
    -	xfs_extlen_t	prod,		/* extent product factor */
    -	xfs_rtblock_t	*rtblock)	/* out: start block allocated */
    -{
    -	int		error;		/* error value */
    -	xfs_inode_t	*ip;		/* inode for bitmap file */
    -	xfs_mount_t	*mp;		/* file system mount structure */
    -	xfs_rtblock_t	r;		/* result allocated block */
    -	xfs_fsblock_t	sb;		/* summary file block number */
    -	xfs_buf_t	*sumbp;		/* summary file block buffer */
    -
    -	ASSERT(minlen > 0 && minlen <= maxlen);
    -	mp = tp->t_mountp;
    -	/*
    -	 * If prod is set then figure out what to do to minlen and maxlen.
    -	 */
    -	if (prod > 1) {
    -		xfs_extlen_t	i;
    -
    -		if ((i = maxlen % prod))
    -			maxlen -= i;
    -		if ((i = minlen % prod))
    -			minlen += prod - i;
    -		if (maxlen < minlen) {
    -			*rtblock = NULLRTBLOCK;
    -			return 0;
    -		}
    -	}
    -	/*
    -	 * Lock out other callers by grabbing the bitmap inode lock.
    -	 */
    -	if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0,
    -					XFS_ILOCK_EXCL, &ip)))
    -		return error;
    -	sumbp = NULL;
    -	/*
    -	 * Allocate by size, or near another block, or exactly at some block.
    -	 */
    -	switch (type) {
    -	case XFS_ALLOCTYPE_ANY_AG:
    -		error = xfs_rtallocate_extent_size(mp, tp, minlen, maxlen, len,
    -				&sumbp,	&sb, prod, &r);
    -		break;
    -	case XFS_ALLOCTYPE_NEAR_BNO:
    -		error = xfs_rtallocate_extent_near(mp, tp, bno, minlen, maxlen,
    -				len, &sumbp, &sb, prod, &r);
    -		break;
    -	case XFS_ALLOCTYPE_THIS_BNO:
    -		error = xfs_rtallocate_extent_exact(mp, tp, bno, minlen, maxlen,
    -				len, &sumbp, &sb, prod, &r);
    -		break;
    -	default:
    -		ASSERT(0);
    -	}
    -	if (error) {
    -		return error;
    -	}
    -	/*
    -	 * If it worked, update the superblock.
    -	 */
    -	if (r != NULLRTBLOCK) {
    -		long	slen = (long)*len;
    -
    -		ASSERT(*len >= minlen && *len <= maxlen);
    -		if (wasdel)
    -			xfs_trans_mod_sb(tp, XFS_TRANS_SB_RES_FREXTENTS, -slen);
    -		else
    -			xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, -slen);
    -	}
    -	*rtblock = r;
    -	return 0;
    -}
    -
    -/*
    - * Free an extent in the realtime subvolume.  Length is expressed in
    - * realtime extents, as is the block number.
    - */
    -int					/* error */
    -xfs_rtfree_extent(
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_rtblock_t	bno,		/* starting block number to free */
    -	xfs_extlen_t	len)		/* length of extent freed */
    -{
    -	int		error;		/* error value */
    -	xfs_inode_t	*ip;		/* bitmap file inode */
    -	xfs_mount_t	*mp;		/* file system mount structure */
    -	xfs_fsblock_t	sb;		/* summary file block number */
    -	xfs_buf_t	*sumbp;		/* summary file block buffer */
    -
    -	mp = tp->t_mountp;
    -	/*
    -	 * Synchronize by locking the bitmap inode.
    -	 */
    -	if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0,
    -					XFS_ILOCK_EXCL, &ip)))
    -		return error;
    -#if defined(__KERNEL__) && defined(DEBUG)
    -	/*
    -	 * Check to see that this whole range is currently allocated.
    -	 */
    -	{
    -		int	stat;		/* result from checking range */
    -
    -		error = xfs_rtcheck_alloc_range(mp, tp, bno, len, &stat);
    -		if (error) {
    -			return error;
    -		}
    -		ASSERT(stat);
    -	}
    -#endif
    -	sumbp = NULL;
    -	/*
    -	 * Free the range of realtime blocks.
    -	 */
    -	error = xfs_rtfree_range(mp, tp, bno, len, &sumbp, &sb);
    -	if (error) {
    -		return error;
    -	}
    -	/*
    -	 * Mark more blocks free in the superblock.
    -	 */
    -	xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, (long)len);
    -	/*
    -	 * If we've now freed all the blocks, reset the file sequence
    -	 * number to 0.
    -	 */
    -	if (tp->t_frextents_delta + mp->m_sb.sb_frextents ==
    -	    mp->m_sb.sb_rextents) {
    -		if (!(ip->i_d.di_flags & XFS_DIFLAG_NEWRTBM))
    -			ip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
    -		*(__uint64_t *)&ip->i_d.di_atime = 0;
    -		xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
    -	}
    -	return 0;
    -}
    -
    -/*
    - * Initialize realtime fields in the mount structure.
    - */
    -int				/* error */
    -xfs_rtmount_init(
    -	xfs_mount_t	*mp)	/* file system mount structure */
    -{
    -	xfs_buf_t	*bp;	/* buffer for last block of subvolume */
    -	xfs_daddr_t	d;	/* address of last block of subvolume */
    -	int		error;	/* error return value */
    -	xfs_sb_t	*sbp;	/* filesystem superblock copy in mount */
    -
    -	sbp = &mp->m_sb;
    -	if (sbp->sb_rblocks == 0)
    -		return 0;
    -	if (mp->m_rtdev_targp == NULL) {
    -		cmn_err(CE_WARN,
    -	"XFS: This filesystem has a realtime volume, use rtdev=device option");
    -		return XFS_ERROR(ENODEV);
    -	}
    -	mp->m_rsumlevels = sbp->sb_rextslog + 1;
    -	mp->m_rsumsize =
    -		(uint)sizeof(xfs_suminfo_t) * mp->m_rsumlevels *
    -		sbp->sb_rbmblocks;
    -	mp->m_rsumsize = roundup(mp->m_rsumsize, sbp->sb_blocksize);
    -	mp->m_rbmip = mp->m_rsumip = NULL;
    -	/*
    -	 * Check that the realtime section is an ok size.
    -	 */
    -	d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_rblocks);
    -	if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_rblocks) {
    -		cmn_err(CE_WARN, "XFS: realtime mount -- %llu != %llu",
    -			(unsigned long long) XFS_BB_TO_FSB(mp, d),
    -			(unsigned long long) mp->m_sb.sb_rblocks);
    -		return XFS_ERROR(E2BIG);
    -	}
    -	error = xfs_read_buf(mp, mp->m_rtdev_targp,
    -				d - XFS_FSB_TO_BB(mp, 1),
    -				XFS_FSB_TO_BB(mp, 1), 0, &bp);
    -	if (error) {
    -		cmn_err(CE_WARN,
    -	"XFS: realtime mount -- xfs_read_buf failed, returned %d", error);
    -		if (error == ENOSPC)
    -			return XFS_ERROR(E2BIG);
    -		return error;
    -	}
    -	xfs_buf_relse(bp);
    -	return 0;
    -}
    -
    -/*
    - * Get the bitmap and summary inodes into the mount structure
    - * at mount time.
    - */
    -int					/* error */
    -xfs_rtmount_inodes(
    -	xfs_mount_t	*mp)		/* file system mount structure */
    -{
    -	int		error;		/* error return value */
    -	xfs_sb_t	*sbp;
    -
    -	sbp = &mp->m_sb;
    -	if (sbp->sb_rbmino == NULLFSINO)
    -		return 0;
    -	error = xfs_iget(mp, NULL, sbp->sb_rbmino, 0, 0, &mp->m_rbmip, 0);
    -	if (error)
    -		return error;
    -	ASSERT(mp->m_rbmip != NULL);
    -	ASSERT(sbp->sb_rsumino != NULLFSINO);
    -	error = xfs_iget(mp, NULL, sbp->sb_rsumino, 0, 0, &mp->m_rsumip, 0);
    -	if (error) {
    -		VN_RELE(XFS_ITOV(mp->m_rbmip));
    -		return error;
    -	}
    -	ASSERT(mp->m_rsumip != NULL);
    -	return 0;
    -}
    -
    -/*
    - * Pick an extent for allocation at the start of a new realtime file.
    - * Use the sequence number stored in the atime field of the bitmap inode.
    - * Translate this to a fraction of the rtextents, and return the product
    - * of rtextents and the fraction.
    - * The fraction sequence is 0, 1/2, 1/4, 3/4, 1/8, ..., 7/8, 1/16, ...
    - */
    -int					/* error */
    -xfs_rtpick_extent(
    -	xfs_mount_t	*mp,		/* file system mount point */
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_extlen_t	len,		/* allocation length (rtextents) */
    -	xfs_rtblock_t	*pick)		/* result rt extent */
    -{
    -	xfs_rtblock_t	b;		/* result block */
    -	int		error;		/* error return value */
    -	xfs_inode_t	*ip;		/* bitmap incore inode */
    -	int		log2;		/* log of sequence number */
    -	__uint64_t	resid;		/* residual after log removed */
    -	__uint64_t	seq;		/* sequence number of file creation */
    -	__uint64_t	*seqp;		/* pointer to seqno in inode */
    -
    -	if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0,
    -					XFS_ILOCK_EXCL, &ip)))
    -		return error;
    -	ASSERT(ip == mp->m_rbmip);
    -	seqp = (__uint64_t *)&ip->i_d.di_atime;
    -	if (!(ip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) {
    -		ip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
    -		*seqp = 0;
    -	}
    -	seq = *seqp;
    -	if ((log2 = xfs_highbit64(seq)) == -1)
    -		b = 0;
    -	else {
    -		resid = seq - (1ULL << log2);
    -		b = (mp->m_sb.sb_rextents * ((resid << 1) + 1ULL)) >>
    -		    (log2 + 1);
    -		if (b >= mp->m_sb.sb_rextents)
    -			b = do_mod(b, mp->m_sb.sb_rextents);
    -		if (b + len > mp->m_sb.sb_rextents)
    -			b = mp->m_sb.sb_rextents - len;
    -	}
    -	*seqp = seq + 1;
    -	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
    -	*pick = b;
    -	return 0;
    -}
    -
    -#ifdef DEBUG
    -/*
    - * Debug code: print out the value of a range in the bitmap.
    - */
    -void
    -xfs_rtprint_range(
    -	xfs_mount_t	*mp,		/* file system mount structure */
    -	xfs_trans_t	*tp,		/* transaction pointer */
    -	xfs_rtblock_t	start,		/* starting block to print */
    -	xfs_extlen_t	len)		/* length to print */
    -{
    -	xfs_extlen_t	i;		/* block number in the extent */
    -
    -	printk("%Ld: ", (long long)start);
    -	for (i = 0; i < len; i++)
    -		printk("%d", xfs_rtcheck_bit(mp, tp, start + i, 1));
    -	printk("\n");
    -}
    -
    -/*
    - * Debug code: print the summary file.
    - */
    -void
    -xfs_rtprint_summary(
    -	xfs_mount_t	*mp,		/* file system mount structure */
    -	xfs_trans_t	*tp)		/* transaction pointer */
    -{
    -	xfs_suminfo_t	c;		/* summary data */
    -	xfs_rtblock_t	i;		/* bitmap block number */
    -	int		l;		/* summary information level */
    -	int		p;		/* flag for printed anything */
    -	xfs_fsblock_t	sb;		/* summary block number */
    -	xfs_buf_t	*sumbp;		/* summary block buffer */
    -
    -	sumbp = NULL;
    -	for (l = 0; l < mp->m_rsumlevels; l++) {
    -		for (p = 0, i = 0; i < mp->m_sb.sb_rbmblocks; i++) {
    -			(void)xfs_rtget_summary(mp, tp, l, i, &sumbp, &sb, &c);
    -			if (c) {
    -				if (!p) {
    -					printk("%Ld-%Ld:", 1LL << l,
    -						XFS_RTMIN((1LL << l) +
    -							  ((1LL << l) - 1LL),
    -							 mp->m_sb.sb_rextents));
    -					p = 1;
    -				}
    -				printk(" %Ld:%d", (long long)i, c);
    -			}
    -		}
    -		if (p)
    -			printk("\n");
    -	}
    -	if (sumbp)
    -		xfs_trans_brelse(tp, sumbp);
    -}
    -#endif	/* DEBUG */
    diff --git a/sys/gnu/fs/xfs/xfs_rtalloc.h b/sys/gnu/fs/xfs/xfs_rtalloc.h
    deleted file mode 100644
    index 89297a069c0..00000000000
    --- a/sys/gnu/fs/xfs/xfs_rtalloc.h
    +++ /dev/null
    @@ -1,173 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_RTALLOC_H__
    -#define	__XFS_RTALLOC_H__
    -
    -struct xfs_mount;
    -struct xfs_trans;
    -
    -#define XFS_IS_REALTIME_INODE(ip) ((ip)->i_d.di_flags & XFS_DIFLAG_REALTIME)
    -
    -/* Min and max rt extent sizes, specified in bytes */
    -#define	XFS_MAX_RTEXTSIZE	(1024 * 1024 * 1024)	/* 1GB */
    -#define	XFS_DFL_RTEXTSIZE	(64 * 1024)	        /* 64KB */
    -#define	XFS_MIN_RTEXTSIZE	(4 * 1024)		/* 4KB */
    -
    -/*
    - * Constants for bit manipulations.
    - */
    -#define	XFS_NBBYLOG	3		/* log2(NBBY) */
    -#define	XFS_WORDLOG	2		/* log2(sizeof(xfs_rtword_t)) */
    -#define	XFS_NBWORDLOG	(XFS_NBBYLOG + XFS_WORDLOG)
    -#define	XFS_NBWORD	(1 << XFS_NBWORDLOG)
    -#define	XFS_WORDMASK	((1 << XFS_WORDLOG) - 1)
    -
    -#define	XFS_BLOCKSIZE(mp)	((mp)->m_sb.sb_blocksize)
    -#define	XFS_BLOCKMASK(mp)	((mp)->m_blockmask)
    -#define	XFS_BLOCKWSIZE(mp)	((mp)->m_blockwsize)
    -#define	XFS_BLOCKWMASK(mp)	((mp)->m_blockwmask)
    -
    -/*
    - * Summary and bit manipulation macros.
    - */
    -#define	XFS_SUMOFFS(mp,ls,bb)	((int)((ls) * (mp)->m_sb.sb_rbmblocks + (bb)))
    -#define	XFS_SUMOFFSTOBLOCK(mp,s)	\
    -	(((s) * (uint)sizeof(xfs_suminfo_t)) >> (mp)->m_sb.sb_blocklog)
    -#define	XFS_SUMPTR(mp,bp,so)	\
    -	((xfs_suminfo_t *)((char *)XFS_BUF_PTR(bp) + \
    -		(((so) * (uint)sizeof(xfs_suminfo_t)) & XFS_BLOCKMASK(mp))))
    -
    -#define	XFS_BITTOBLOCK(mp,bi)	((bi) >> (mp)->m_blkbit_log)
    -#define	XFS_BLOCKTOBIT(mp,bb)	((bb) << (mp)->m_blkbit_log)
    -#define	XFS_BITTOWORD(mp,bi)	\
    -	((int)(((bi) >> XFS_NBWORDLOG) & XFS_BLOCKWMASK(mp)))
    -
    -#define	XFS_RTMIN(a,b)	((a) < (b) ? (a) : (b))
    -#define	XFS_RTMAX(a,b)	((a) > (b) ? (a) : (b))
    -
    -#define	XFS_RTLOBIT(w)	xfs_lowbit32(w)
    -#define	XFS_RTHIBIT(w)	xfs_highbit32(w)
    -
    -#if XFS_BIG_BLKNOS
    -#define	XFS_RTBLOCKLOG(b)	xfs_highbit64(b)
    -#else
    -#define	XFS_RTBLOCKLOG(b)	xfs_highbit32(b)
    -#endif
    -
    -
    -#ifdef __KERNEL__
    -
    -#ifdef CONFIG_XFS_RT
    -/*
    - * Function prototypes for exported functions.
    - */
    -
    -/*
    - * Allocate an extent in the realtime subvolume, with the usual allocation
    - * parameters.  The length units are all in realtime extents, as is the
    - * result block number.
    - */
    -int					/* error */
    -xfs_rtallocate_extent(
    -	struct xfs_trans	*tp,	/* transaction pointer */
    -	xfs_rtblock_t		bno,	/* starting block number to allocate */
    -	xfs_extlen_t		minlen,	/* minimum length to allocate */
    -	xfs_extlen_t		maxlen,	/* maximum length to allocate */
    -	xfs_extlen_t		*len,	/* out: actual length allocated */
    -	xfs_alloctype_t		type,	/* allocation type XFS_ALLOCTYPE... */
    -	int			wasdel,	/* was a delayed allocation extent */
    -	xfs_extlen_t		prod,	/* extent product factor */
    -	xfs_rtblock_t		*rtblock); /* out: start block allocated */
    -
    -/*
    - * Free an extent in the realtime subvolume.  Length is expressed in
    - * realtime extents, as is the block number.
    - */
    -int					/* error */
    -xfs_rtfree_extent(
    -	struct xfs_trans	*tp,	/* transaction pointer */
    -	xfs_rtblock_t		bno,	/* starting block number to free */
    -	xfs_extlen_t		len);	/* length of extent freed */
    -
    -/*
    - * Initialize realtime fields in the mount structure.
    - */
    -int					/* error */
    -xfs_rtmount_init(
    -	struct xfs_mount	*mp);	/* file system mount structure */
    -
    -/*
    - * Get the bitmap and summary inodes into the mount structure
    - * at mount time.
    - */
    -int					/* error */
    -xfs_rtmount_inodes(
    -	struct xfs_mount	*mp);	/* file system mount structure */
    -
    -/*
    - * Pick an extent for allocation at the start of a new realtime file.
    - * Use the sequence number stored in the atime field of the bitmap inode.
    - * Translate this to a fraction of the rtextents, and return the product
    - * of rtextents and the fraction.
    - * The fraction sequence is 0, 1/2, 1/4, 3/4, 1/8, ..., 7/8, 1/16, ...
    - */
    -int					/* error */
    -xfs_rtpick_extent(
    -	struct xfs_mount	*mp,	/* file system mount point */
    -	struct xfs_trans	*tp,	/* transaction pointer */
    -	xfs_extlen_t		len,	/* allocation length (rtextents) */
    -	xfs_rtblock_t		*pick);	/* result rt extent */
    -
    -/*
    - * Debug code: print out the value of a range in the bitmap.
    - */
    -void
    -xfs_rtprint_range(
    -	struct xfs_mount	*mp,	/* file system mount structure */
    -	struct xfs_trans	*tp,	/* transaction pointer */
    -	xfs_rtblock_t		start,	/* starting block to print */
    -	xfs_extlen_t		len);	/* length to print */
    -
    -/*
    - * Debug code: print the summary file.
    - */
    -void
    -xfs_rtprint_summary(
    -	struct xfs_mount	*mp,	/* file system mount structure */
    -	struct xfs_trans	*tp);	/* transaction pointer */
    -
    -/*
    - * Grow the realtime area of the filesystem.
    - */
    -int
    -xfs_growfs_rt(
    -	struct xfs_mount	*mp,	/* file system mount structure */
    -	xfs_growfs_rt_t		*in);	/* user supplied growfs struct */
    -
    -#else
    -# define xfs_rtallocate_extent(t,b,min,max,l,a,f,p,rb)  (ENOSYS)
    -# define xfs_rtfree_extent(t,b,l)                       (ENOSYS)
    -# define xfs_rtpick_extent(m,t,l,rb)                    ((*rb = 0), ENOSYS)
    -# define xfs_growfs_rt(mp,in)                           (ENOSYS)
    -# define xfs_rtmount_init(m)    (((mp)->m_sb.sb_rblocks == 0)? 0 : (ENOSYS))
    -# define xfs_rtmount_inodes(m)  (((mp)->m_sb.sb_rblocks == 0)? 0 : (ENOSYS))
    -#endif	/* CONFIG_XFS_RT */
    -
    -#endif	/* __KERNEL__ */
    -
    -#endif	/* __XFS_RTALLOC_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_rw.c b/sys/gnu/fs/xfs/xfs_rw.c
    deleted file mode 100644
    index a59c102cf21..00000000000
    --- a/sys/gnu/fs/xfs/xfs_rw.c
    +++ /dev/null
    @@ -1,341 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_inode_item.h"
    -#include "xfs_itable.h"
    -#include "xfs_btree.h"
    -#include "xfs_alloc.h"
    -#include "xfs_ialloc.h"
    -#include "xfs_attr.h"
    -#include "xfs_bmap.h"
    -#include "xfs_acl.h"
    -#include "xfs_mac.h"
    -#include "xfs_error.h"
    -#include "xfs_buf_item.h"
    -#include "xfs_rw.h"
    -
    -/*
    - * This is a subroutine for xfs_write() and other writers (xfs_ioctl)
    - * which clears the setuid and setgid bits when a file is written.
    - */
    -int
    -xfs_write_clear_setuid(
    -	xfs_inode_t	*ip)
    -{
    -	xfs_mount_t	*mp;
    -	xfs_trans_t	*tp;
    -	int		error;
    -
    -	mp = ip->i_mount;
    -	tp = xfs_trans_alloc(mp, XFS_TRANS_WRITEID);
    -	if ((error = xfs_trans_reserve(tp, 0,
    -				      XFS_WRITEID_LOG_RES(mp),
    -				      0, 0, 0))) {
    -		xfs_trans_cancel(tp, 0);
    -		return error;
    -	}
    -	xfs_ilock(ip, XFS_ILOCK_EXCL);
    -	xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
    -	xfs_trans_ihold(tp, ip);
    -	ip->i_d.di_mode &= ~S_ISUID;
    -
    -	/*
    -	 * Note that we don't have to worry about mandatory
    -	 * file locking being disabled here because we only
    -	 * clear the S_ISGID bit if the Group execute bit is
    -	 * on, but if it was on then mandatory locking wouldn't
    -	 * have been enabled.
    -	 */
    -	if (ip->i_d.di_mode & S_IXGRP) {
    -		ip->i_d.di_mode &= ~S_ISGID;
    -	}
    -	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
    -	xfs_trans_set_sync(tp);
    -	error = xfs_trans_commit(tp, 0, NULL);
    -	xfs_iunlock(ip, XFS_ILOCK_EXCL);
    -	return 0;
    -}
    -
    -/*
    - * Force a shutdown of the filesystem instantly while keeping
    - * the filesystem consistent. We don't do an unmount here; just shutdown
    - * the shop, make sure that absolutely nothing persistent happens to
    - * this filesystem after this point.
    - */
    -
    -void
    -xfs_do_force_shutdown(
    -	bhv_desc_t	*bdp,
    -	int		flags,
    -	char		*fname,
    -	int		lnnum)
    -{
    -	int		logerror;
    -	xfs_mount_t	*mp;
    -
    -	mp = XFS_BHVTOM(bdp);
    -	logerror = flags & XFS_LOG_IO_ERROR;
    -
    -	if (!(flags & XFS_FORCE_UMOUNT)) {
    -		cmn_err(CE_NOTE,
    -		"xfs_force_shutdown(%s,0x%x) called from line %d of file %s.  Return address = 0x%p",
    -			mp->m_fsname,flags,lnnum,fname,__return_address);
    -	}
    -	/*
    -	 * No need to duplicate efforts.
    -	 */
    -	if (XFS_FORCED_SHUTDOWN(mp) && !logerror)
    -		return;
    -
    -	/*
    -	 * This flags XFS_MOUNT_FS_SHUTDOWN, makes sure that we don't
    -	 * queue up anybody new on the log reservations, and wakes up
    -	 * everybody who's sleeping on log reservations and tells
    -	 * them the bad news.
    -	 */
    -	if (xfs_log_force_umount(mp, logerror))
    -		return;
    -
    -	if (flags & XFS_CORRUPT_INCORE) {
    -		xfs_cmn_err(XFS_PTAG_SHUTDOWN_CORRUPT, CE_ALERT, mp,
    -    "Corruption of in-memory data detected.  Shutting down filesystem: %s",
    -			mp->m_fsname);
    -		if (XFS_ERRLEVEL_HIGH <= xfs_error_level) {
    -			xfs_stack_trace();
    -		}
    -	} else if (!(flags & XFS_FORCE_UMOUNT)) {
    -		if (logerror) {
    -			xfs_cmn_err(XFS_PTAG_SHUTDOWN_LOGERROR, CE_ALERT, mp,
    -			"Log I/O Error Detected.  Shutting down filesystem: %s",
    -				mp->m_fsname);
    -		} else if (!(flags & XFS_SHUTDOWN_REMOTE_REQ)) {
    -			xfs_cmn_err(XFS_PTAG_SHUTDOWN_IOERROR, CE_ALERT, mp,
    -				"I/O Error Detected.  Shutting down filesystem: %s",
    -				mp->m_fsname);
    -		}
    -	}
    -	if (!(flags & XFS_FORCE_UMOUNT)) {
    -		cmn_err(CE_ALERT,
    -		"Please umount the filesystem, and rectify the problem(s)");
    -	}
    -}
    -
    -
    -/*
    - * Called when we want to stop a buffer from getting written or read.
    - * We attach the EIO error, muck with its flags, and call biodone
    - * so that the proper iodone callbacks get called.
    - */
    -int
    -xfs_bioerror(
    -	xfs_buf_t *bp)
    -{
    -
    -#ifdef XFSERRORDEBUG
    -	ASSERT(XFS_BUF_ISREAD(bp) || bp->b_iodone);
    -#endif
    -
    -	/*
    -	 * No need to wait until the buffer is unpinned.
    -	 * We aren't flushing it.
    -	 */
    -	xfs_buftrace("XFS IOERROR", bp);
    -	XFS_BUF_ERROR(bp, EIO);
    -	/*
    -	 * We're calling biodone, so delete B_DONE flag. Either way
    -	 * we have to call the iodone callback, and calling biodone
    -	 * probably is the best way since it takes care of
    -	 * GRIO as well.
    -	 */
    -	XFS_BUF_UNREAD(bp);
    -	XFS_BUF_UNDELAYWRITE(bp);
    -	XFS_BUF_UNDONE(bp);
    -	XFS_BUF_STALE(bp);
    -
    -	XFS_BUF_CLR_BDSTRAT_FUNC(bp);
    -	xfs_biodone(bp);
    -
    -	return (EIO);
    -}
    -
    -/*
    - * Same as xfs_bioerror, except that we are releasing the buffer
    - * here ourselves, and avoiding the biodone call.
    - * This is meant for userdata errors; metadata bufs come with
    - * iodone functions attached, so that we can track down errors.
    - */
    -int
    -xfs_bioerror_relse(
    -	xfs_buf_t *bp)
    -{
    -	int64_t fl;
    -
    -	ASSERT(XFS_BUF_IODONE_FUNC(bp) != xfs_buf_iodone_callbacks);
    -	ASSERT(XFS_BUF_IODONE_FUNC(bp) != xlog_iodone);
    -
    -	xfs_buftrace("XFS IOERRELSE", bp);
    -	fl = XFS_BUF_BFLAGS(bp);
    -	/*
    -	 * No need to wait until the buffer is unpinned.
    -	 * We aren't flushing it.
    -	 *
    -	 * chunkhold expects B_DONE to be set, whether
    -	 * we actually finish the I/O or not. We don't want to
    -	 * change that interface.
    -	 */
    -	XFS_BUF_UNREAD(bp);
    -	XFS_BUF_UNDELAYWRITE(bp);
    -	XFS_BUF_DONE(bp);
    -	XFS_BUF_STALE(bp);
    -	XFS_BUF_CLR_IODONE_FUNC(bp);
    -	XFS_BUF_CLR_BDSTRAT_FUNC(bp);
    -	if (!(fl & XFS_B_ASYNC)) {
    -		/*
    -		 * Mark b_error and B_ERROR _both_.
    -		 * Lot's of chunkcache code assumes that.
    -		 * There's no reason to mark error for
    -		 * ASYNC buffers.
    -		 */
    -		XFS_BUF_ERROR(bp, EIO);
    -		XFS_BUF_V_IODONESEMA(bp);
    -	} else {
    -		xfs_buf_relse(bp);
    -	}
    -	return (EIO);
    -}
    -
    -/*
    - * Prints out an ALERT message about I/O error.
    - */
    -void
    -xfs_ioerror_alert(
    -	char			*func,
    -	struct xfs_mount	*mp,
    -	xfs_buf_t		*bp,
    -	xfs_daddr_t		blkno)
    -{
    -	cmn_err(CE_ALERT,
    - "I/O error in filesystem (\"%s\") meta-data dev %s block 0x%llx"
    - "       (\"%s\") error %d buf count %zd",
    -		(!mp || !mp->m_fsname) ? "(fs name not set)" : mp->m_fsname,
    -		XFS_BUFTARG_NAME(XFS_BUF_TARGET(bp)),
    -		(__uint64_t)blkno, func,
    -		XFS_BUF_GETERROR(bp), XFS_BUF_COUNT(bp));
    -}
    -
    -/*
    - * This isn't an absolute requirement, but it is
    - * just a good idea to call xfs_read_buf instead of
    - * directly doing a read_buf call. For one, we shouldn't
    - * be doing this disk read if we are in SHUTDOWN state anyway,
    - * so this stops that from happening. Secondly, this does all
    - * the error checking stuff and the brelse if appropriate for
    - * the caller, so the code can be a little leaner.
    - */
    -
    -int
    -xfs_read_buf(
    -	struct xfs_mount *mp,
    -	xfs_buftarg_t	 *target,
    -	xfs_daddr_t	 blkno,
    -	int              len,
    -	uint             flags,
    -	xfs_buf_t	 **bpp)
    -{
    -	xfs_buf_t	 *bp;
    -	int		 error;
    -
    -	if (flags)
    -		bp = xfs_buf_read_flags(target, blkno, len, flags);
    -	else
    -		bp = xfs_buf_read(target, blkno, len, flags);
    -	if (!bp)
    -		return XFS_ERROR(EIO);
    -	error = XFS_BUF_GETERROR(bp);
    -	if (bp && !error && !XFS_FORCED_SHUTDOWN(mp)) {
    -		*bpp = bp;
    -	} else {
    -		*bpp = NULL;
    -		if (error) {
    -			xfs_ioerror_alert("xfs_read_buf", mp, bp, XFS_BUF_ADDR(bp));
    -		} else {
    -			error = XFS_ERROR(EIO);
    -		}
    -		if (bp) {
    -			XFS_BUF_UNDONE(bp);
    -			XFS_BUF_UNDELAYWRITE(bp);
    -			XFS_BUF_STALE(bp);
    -			/*
    -			 * brelse clears B_ERROR and b_error
    -			 */
    -			xfs_buf_relse(bp);
    -		}
    -	}
    -	return (error);
    -}
    -
    -/*
    - * Wrapper around bwrite() so that we can trap
    - * write errors, and act accordingly.
    - */
    -int
    -xfs_bwrite(
    -	struct xfs_mount *mp,
    -	struct xfs_buf	 *bp)
    -{
    -	int	error;
    -
    -	/*
    -	 * XXXsup how does this work for quotas.
    -	 */
    -	XFS_BUF_SET_BDSTRAT_FUNC(bp, xfs_bdstrat_cb);
    -	XFS_BUF_SET_FSPRIVATE3(bp, mp);
    -	XFS_BUF_WRITE(bp);
    -
    -	if ((error = XFS_bwrite(bp))) {
    -		ASSERT(mp);
    -		/*
    -		 * Cannot put a buftrace here since if the buffer is not
    -		 * B_HOLD then we will brelse() the buffer before returning
    -		 * from bwrite and we could be tracing a buffer that has
    -		 * been reused.
    -		 */
    -		xfs_force_shutdown(mp, XFS_METADATA_IO_ERROR);
    -	}
    -	return (error);
    -}
    diff --git a/sys/gnu/fs/xfs/xfs_rw.h b/sys/gnu/fs/xfs/xfs_rw.h
    deleted file mode 100644
    index 34994b93bba..00000000000
    --- a/sys/gnu/fs/xfs/xfs_rw.h
    +++ /dev/null
    @@ -1,98 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef	__XFS_RW_H__
    -#define	__XFS_RW_H__
    -
    -struct xfs_buf;
    -struct xfs_inode;
    -struct xfs_mount;
    -
    -/*
    - * Maximum count of bmaps used by read and write paths.
    - */
    -#define	XFS_MAX_RW_NBMAPS	4
    -
    -/*
    - * Counts of readahead buffers to use based on physical memory size.
    - * None of these should be more than XFS_MAX_RW_NBMAPS.
    - */
    -#define	XFS_RW_NREADAHEAD_16MB	2
    -#define	XFS_RW_NREADAHEAD_32MB	3
    -#define	XFS_RW_NREADAHEAD_K32	4
    -#define	XFS_RW_NREADAHEAD_K64	4
    -
    -/*
    - * Maximum size of a buffer that we\'ll map.  Making this
    - * too big will degrade performance due to the number of
    - * pages which need to be gathered.  Making it too small
    - * will prevent us from doing large I/O\'s to hardware that
    - * needs it.
    - *
    - * This is currently set to 512 KB.
    - */
    -#define	XFS_MAX_BMAP_LEN_BB	1024
    -#define	XFS_MAX_BMAP_LEN_BYTES	524288
    -
    -/*
    - * Convert the given file system block to a disk block.
    - * We have to treat it differently based on whether the
    - * file is a real time file or not, because the bmap code
    - * does.
    - */
    -#define	XFS_FSB_TO_DB(ip,fsb)	xfs_fsb_to_db(ip,fsb)
    -static inline xfs_daddr_t
    -xfs_fsb_to_db(struct xfs_inode *ip, xfs_fsblock_t fsb)
    -{
    -	return (((ip)->i_d.di_flags & XFS_DIFLAG_REALTIME) ? \
    -		 (xfs_daddr_t)XFS_FSB_TO_BB((ip)->i_mount, (fsb)) : \
    -		 XFS_FSB_TO_DADDR((ip)->i_mount, (fsb)));
    -}
    -#define XFS_FSB_TO_DB_IO(io,fsb) xfs_fsb_to_db_io(io,fsb)
    -static inline xfs_daddr_t
    -xfs_fsb_to_db_io(struct xfs_iocore *io, xfs_fsblock_t fsb)
    -{
    -	return (((io)->io_flags & XFS_IOCORE_RT) ? \
    -		 XFS_FSB_TO_BB((io)->io_mount, (fsb)) : \
    -		 XFS_FSB_TO_DADDR((io)->io_mount, (fsb)));
    -}
    -
    -/*
    - * Prototypes for functions in xfs_rw.c.
    - */
    -extern int xfs_write_clear_setuid(struct xfs_inode *ip);
    -extern int xfs_bwrite(struct xfs_mount *mp, struct xfs_buf *bp);
    -extern int xfs_bioerror(struct xfs_buf *bp);
    -extern int xfs_bioerror_relse(struct xfs_buf *bp);
    -extern int xfs_read_buf(struct xfs_mount *mp, xfs_buftarg_t *btp,
    -			xfs_daddr_t blkno, int len, uint flags,
    -			struct xfs_buf **bpp);
    -extern void xfs_ioerror_alert(char *func, struct xfs_mount *mp,
    -				xfs_buf_t *bp, xfs_daddr_t blkno);
    -
    -/*
    - * Prototypes for functions in xfs_vnodeops.c.
    - */
    -extern int xfs_rwlock(bhv_desc_t *bdp, vrwlock_t write_lock);
    -extern void xfs_rwunlock(bhv_desc_t *bdp, vrwlock_t write_lock);
    -extern int xfs_setattr(bhv_desc_t *bdp, xfs_vattr_t *vap, int flags, cred_t *credp);
    -extern int xfs_change_file_space(bhv_desc_t *bdp, u_long cmd, xfs_flock64_t *bf,
    -				 xfs_off_t offset, cred_t *credp, int flags);
    -extern int xfs_set_dmattrs(bhv_desc_t *bdp, u_int evmask, u_int16_t state,
    -			   cred_t *credp);
    -
    -#endif /* __XFS_RW_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_sb.h b/sys/gnu/fs/xfs/xfs_sb.h
    deleted file mode 100644
    index bf168a91ddb..00000000000
    --- a/sys/gnu/fs/xfs/xfs_sb.h
    +++ /dev/null
    @@ -1,492 +0,0 @@
    -/*
    - * Copyright (c) 2000-2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_SB_H__
    -#define	__XFS_SB_H__
    -
    -/*
    - * Super block
    - * Fits into a sector-sized buffer at address 0 of each allocation group.
    - * Only the first of these is ever updated except during growfs.
    - */
    -
    -struct xfs_buf;
    -struct xfs_mount;
    -
    -#define	XFS_SB_MAGIC		0x58465342	/* 'XFSB' */
    -#define	XFS_SB_VERSION_1	1		/* 5.3, 6.0.1, 6.1 */
    -#define	XFS_SB_VERSION_2	2		/* 6.2 - attributes */
    -#define	XFS_SB_VERSION_3	3		/* 6.2 - new inode version */
    -#define	XFS_SB_VERSION_4	4		/* 6.2+ - bitmask version */
    -#define	XFS_SB_VERSION_NUMBITS		0x000f
    -#define	XFS_SB_VERSION_ALLFBITS		0xfff0
    -#define	XFS_SB_VERSION_SASHFBITS	0xf000
    -#define	XFS_SB_VERSION_REALFBITS	0x0ff0
    -#define	XFS_SB_VERSION_ATTRBIT		0x0010
    -#define	XFS_SB_VERSION_NLINKBIT		0x0020
    -#define	XFS_SB_VERSION_QUOTABIT		0x0040
    -#define	XFS_SB_VERSION_ALIGNBIT		0x0080
    -#define	XFS_SB_VERSION_DALIGNBIT	0x0100
    -#define	XFS_SB_VERSION_SHAREDBIT	0x0200
    -#define XFS_SB_VERSION_LOGV2BIT		0x0400
    -#define XFS_SB_VERSION_SECTORBIT	0x0800
    -#define	XFS_SB_VERSION_EXTFLGBIT	0x1000
    -#define	XFS_SB_VERSION_DIRV2BIT		0x2000
    -#define	XFS_SB_VERSION_MOREBITSBIT	0x8000
    -#define	XFS_SB_VERSION_OKSASHFBITS	\
    -	(XFS_SB_VERSION_EXTFLGBIT | \
    -	 XFS_SB_VERSION_DIRV2BIT)
    -#define	XFS_SB_VERSION_OKREALFBITS	\
    -	(XFS_SB_VERSION_ATTRBIT | \
    -	 XFS_SB_VERSION_NLINKBIT | \
    -	 XFS_SB_VERSION_QUOTABIT | \
    -	 XFS_SB_VERSION_ALIGNBIT | \
    -	 XFS_SB_VERSION_DALIGNBIT | \
    -	 XFS_SB_VERSION_SHAREDBIT | \
    -	 XFS_SB_VERSION_LOGV2BIT | \
    -	 XFS_SB_VERSION_SECTORBIT | \
    -	 XFS_SB_VERSION_MOREBITSBIT)
    -#define	XFS_SB_VERSION_OKSASHBITS	\
    -	(XFS_SB_VERSION_NUMBITS | \
    -	 XFS_SB_VERSION_REALFBITS | \
    -	 XFS_SB_VERSION_OKSASHFBITS)
    -#define	XFS_SB_VERSION_OKREALBITS	\
    -	(XFS_SB_VERSION_NUMBITS | \
    -	 XFS_SB_VERSION_OKREALFBITS | \
    -	 XFS_SB_VERSION_OKSASHFBITS)
    -
    -/*
    - * There are two words to hold XFS "feature" bits: the original
    - * word, sb_versionnum, and sb_features2.  Whenever a bit is set in
    - * sb_features2, the feature bit XFS_SB_VERSION_MOREBITSBIT must be set.
    - *
    - * These defines represent bits in sb_features2.
    - */
    -#define XFS_SB_VERSION2_REALFBITS	0x00ffffff	/* Mask: features */
    -#define XFS_SB_VERSION2_RESERVED1BIT	0x00000001
    -#define XFS_SB_VERSION2_RESERVED2BIT	0x00000002
    -#define XFS_SB_VERSION2_RESERVED4BIT	0x00000004
    -#define XFS_SB_VERSION2_ATTR2BIT	0x00000008	/* Inline attr rework */
    -#define XFS_SB_VERSION2_SASHFBITS	0xff000000	/* Mask: features that
    -							   require changing
    -							   PROM and SASH */
    -
    -#define	XFS_SB_VERSION2_OKREALFBITS	\
    -	(XFS_SB_VERSION2_ATTR2BIT)
    -#define	XFS_SB_VERSION2_OKSASHFBITS	\
    -	(0)
    -#define XFS_SB_VERSION2_OKREALBITS	\
    -	(XFS_SB_VERSION2_OKREALFBITS |	\
    -	 XFS_SB_VERSION2_OKSASHFBITS )
    -
    -typedef struct xfs_sb
    -{
    -	__uint32_t	sb_magicnum;	/* magic number == XFS_SB_MAGIC */
    -	__uint32_t	sb_blocksize;	/* logical block size, bytes */
    -	xfs_drfsbno_t	sb_dblocks;	/* number of data blocks */
    -	xfs_drfsbno_t	sb_rblocks;	/* number of realtime blocks */
    -	xfs_drtbno_t	sb_rextents;	/* number of realtime extents */
    -	uuid_t		sb_uuid;	/* file system unique id */
    -	xfs_dfsbno_t	sb_logstart;	/* starting block of log if internal */
    -	xfs_ino_t	sb_rootino;	/* root inode number */
    -	xfs_ino_t	sb_rbmino;	/* bitmap inode for realtime extents */
    -	xfs_ino_t	sb_rsumino;	/* summary inode for rt bitmap */
    -	xfs_agblock_t	sb_rextsize;	/* realtime extent size, blocks */
    -	xfs_agblock_t	sb_agblocks;	/* size of an allocation group */
    -	xfs_agnumber_t	sb_agcount;	/* number of allocation groups */
    -	xfs_extlen_t	sb_rbmblocks;	/* number of rt bitmap blocks */
    -	xfs_extlen_t	sb_logblocks;	/* number of log blocks */
    -	__uint16_t	sb_versionnum;	/* header version == XFS_SB_VERSION */
    -	__uint16_t	sb_sectsize;	/* volume sector size, bytes */
    -	__uint16_t	sb_inodesize;	/* inode size, bytes */
    -	__uint16_t	sb_inopblock;	/* inodes per block */
    -	char		sb_fname[12];	/* file system name */
    -	__uint8_t	sb_blocklog;	/* log2 of sb_blocksize */
    -	__uint8_t	sb_sectlog;	/* log2 of sb_sectsize */
    -	__uint8_t	sb_inodelog;	/* log2 of sb_inodesize */
    -	__uint8_t	sb_inopblog;	/* log2 of sb_inopblock */
    -	__uint8_t	sb_agblklog;	/* log2 of sb_agblocks (rounded up) */
    -	__uint8_t	sb_rextslog;	/* log2 of sb_rextents */
    -	__uint8_t	sb_inprogress;	/* mkfs is in progress, don't mount */
    -	__uint8_t	sb_imax_pct;	/* max % of fs for inode space */
    -					/* statistics */
    -	/*
    -	 * These fields must remain contiguous.  If you really
    -	 * want to change their layout, make sure you fix the
    -	 * code in xfs_trans_apply_sb_deltas().
    -	 */
    -	__uint64_t	sb_icount;	/* allocated inodes */
    -	__uint64_t	sb_ifree;	/* free inodes */
    -	__uint64_t	sb_fdblocks;	/* free data blocks */
    -	__uint64_t	sb_frextents;	/* free realtime extents */
    -	/*
    -	 * End contiguous fields.
    -	 */
    -	xfs_ino_t	sb_uquotino;	/* user quota inode */
    -	xfs_ino_t	sb_gquotino;	/* group quota inode */
    -	__uint16_t	sb_qflags;	/* quota flags */
    -	__uint8_t	sb_flags;	/* misc. flags */
    -	__uint8_t	sb_shared_vn;	/* shared version number */
    -	xfs_extlen_t	sb_inoalignmt;	/* inode chunk alignment, fsblocks */
    -	__uint32_t	sb_unit;	/* stripe or raid unit */
    -	__uint32_t	sb_width;	/* stripe or raid width */
    -	__uint8_t	sb_dirblklog;	/* log2 of dir block size (fsbs) */
    -	__uint8_t	sb_logsectlog;	/* log2 of the log sector size */
    -	__uint16_t	sb_logsectsize;	/* sector size for the log, bytes */
    -	__uint32_t	sb_logsunit;	/* stripe unit size for the log */
    -	__uint32_t	sb_features2;	/* additional feature bits */
    -} xfs_sb_t;
    -
    -/*
    - * Sequence number values for the fields.
    - */
    -typedef enum {
    -	XFS_SBS_MAGICNUM, XFS_SBS_BLOCKSIZE, XFS_SBS_DBLOCKS, XFS_SBS_RBLOCKS,
    -	XFS_SBS_REXTENTS, XFS_SBS_UUID, XFS_SBS_LOGSTART, XFS_SBS_ROOTINO,
    -	XFS_SBS_RBMINO, XFS_SBS_RSUMINO, XFS_SBS_REXTSIZE, XFS_SBS_AGBLOCKS,
    -	XFS_SBS_AGCOUNT, XFS_SBS_RBMBLOCKS, XFS_SBS_LOGBLOCKS,
    -	XFS_SBS_VERSIONNUM, XFS_SBS_SECTSIZE, XFS_SBS_INODESIZE,
    -	XFS_SBS_INOPBLOCK, XFS_SBS_FNAME, XFS_SBS_BLOCKLOG,
    -	XFS_SBS_SECTLOG, XFS_SBS_INODELOG, XFS_SBS_INOPBLOG, XFS_SBS_AGBLKLOG,
    -	XFS_SBS_REXTSLOG, XFS_SBS_INPROGRESS, XFS_SBS_IMAX_PCT, XFS_SBS_ICOUNT,
    -	XFS_SBS_IFREE, XFS_SBS_FDBLOCKS, XFS_SBS_FREXTENTS, XFS_SBS_UQUOTINO,
    -	XFS_SBS_GQUOTINO, XFS_SBS_QFLAGS, XFS_SBS_FLAGS, XFS_SBS_SHARED_VN,
    -	XFS_SBS_INOALIGNMT, XFS_SBS_UNIT, XFS_SBS_WIDTH, XFS_SBS_DIRBLKLOG,
    -	XFS_SBS_LOGSECTLOG, XFS_SBS_LOGSECTSIZE, XFS_SBS_LOGSUNIT,
    -	XFS_SBS_FEATURES2,
    -	XFS_SBS_FIELDCOUNT
    -} xfs_sb_field_t;
    -
    -/*
    - * Mask values, defined based on the xfs_sb_field_t values.
    - * Only define the ones we're using.
    - */
    -#define	XFS_SB_MVAL(x)		(1LL << XFS_SBS_ ## x)
    -#define	XFS_SB_UUID		XFS_SB_MVAL(UUID)
    -#define	XFS_SB_FNAME		XFS_SB_MVAL(FNAME)
    -#define	XFS_SB_ROOTINO		XFS_SB_MVAL(ROOTINO)
    -#define	XFS_SB_RBMINO		XFS_SB_MVAL(RBMINO)
    -#define	XFS_SB_RSUMINO		XFS_SB_MVAL(RSUMINO)
    -#define	XFS_SB_VERSIONNUM	XFS_SB_MVAL(VERSIONNUM)
    -#define XFS_SB_UQUOTINO		XFS_SB_MVAL(UQUOTINO)
    -#define XFS_SB_GQUOTINO		XFS_SB_MVAL(GQUOTINO)
    -#define XFS_SB_QFLAGS		XFS_SB_MVAL(QFLAGS)
    -#define XFS_SB_SHARED_VN	XFS_SB_MVAL(SHARED_VN)
    -#define XFS_SB_UNIT		XFS_SB_MVAL(UNIT)
    -#define XFS_SB_WIDTH		XFS_SB_MVAL(WIDTH)
    -#define XFS_SB_FEATURES2	XFS_SB_MVAL(FEATURES2)
    -#define	XFS_SB_NUM_BITS		((int)XFS_SBS_FIELDCOUNT)
    -#define	XFS_SB_ALL_BITS		((1LL << XFS_SB_NUM_BITS) - 1)
    -#define	XFS_SB_MOD_BITS		\
    -	(XFS_SB_UUID | XFS_SB_ROOTINO | XFS_SB_RBMINO | XFS_SB_RSUMINO | \
    -	 XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO | XFS_SB_GQUOTINO | \
    -	 XFS_SB_QFLAGS | XFS_SB_SHARED_VN | XFS_SB_UNIT | XFS_SB_WIDTH | \
    -	 XFS_SB_FEATURES2)
    -
    -
    -/*
    - * Misc. Flags - warning - these will be cleared by xfs_repair unless
    - * a feature bit is set when the flag is used.
    - */
    -#define XFS_SBF_NOFLAGS		0x00	/* no flags set */
    -#define XFS_SBF_READONLY	0x01	/* only read-only mounts allowed */
    -
    -/*
    - * define max. shared version we can interoperate with
    - */
    -#define XFS_SB_MAX_SHARED_VN	0
    -
    -#define	XFS_SB_VERSION_NUM(sbp)	((sbp)->sb_versionnum & XFS_SB_VERSION_NUMBITS)
    -
    -#define	XFS_SB_GOOD_VERSION(sbp)	xfs_sb_good_version(sbp)
    -#ifdef __KERNEL__
    -static inline int xfs_sb_good_version(xfs_sb_t *sbp)
    -{
    -	return (((sbp->sb_versionnum >= XFS_SB_VERSION_1) && \
    -		  (sbp->sb_versionnum <= XFS_SB_VERSION_3)) || \
    -		   ((XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \
    -		    !((sbp->sb_versionnum & ~XFS_SB_VERSION_OKREALBITS) || \
    -		      ((sbp->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT) && \
    -		       (sbp->sb_features2 & ~XFS_SB_VERSION2_OKREALBITS))) && \
    -	  	    (sbp->sb_shared_vn <= XFS_SB_MAX_SHARED_VN)));
    -}
    -#else
    -static inline int xfs_sb_good_version(xfs_sb_t *sbp)
    -{
    -	return (((sbp->sb_versionnum >= XFS_SB_VERSION_1) && \
    -		  (sbp->sb_versionnum <= XFS_SB_VERSION_3)) || \
    -		   ((XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \
    -		    !((sbp->sb_versionnum & ~XFS_SB_VERSION_OKREALBITS) || \
    -		      ((sbp->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT) && \
    -		       (sbp->sb_features2 & ~XFS_SB_VERSION2_OKREALBITS))) && \
    -		  (!(sbp->sb_versionnum & XFS_SB_VERSION_SHAREDBIT) || \
    -		   (sbp->sb_shared_vn <= XFS_SB_MAX_SHARED_VN))));
    -}
    -#endif /* __KERNEL__ */
    -
    -#define	XFS_SB_GOOD_SASH_VERSION(sbp)	\
    -	((((sbp)->sb_versionnum >= XFS_SB_VERSION_1) && \
    -	  ((sbp)->sb_versionnum <= XFS_SB_VERSION_3)) || \
    -	 ((XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \
    -	  !((sbp)->sb_versionnum & ~XFS_SB_VERSION_OKSASHBITS)))
    -
    -#define	XFS_SB_VERSION_TONEW(v)	xfs_sb_version_tonew(v)
    -static inline unsigned xfs_sb_version_tonew(unsigned v)
    -{
    -	return ((((v) == XFS_SB_VERSION_1) ? \
    -		0 : \
    -		(((v) == XFS_SB_VERSION_2) ? \
    -			XFS_SB_VERSION_ATTRBIT : \
    -			(XFS_SB_VERSION_ATTRBIT | XFS_SB_VERSION_NLINKBIT))) | \
    -		XFS_SB_VERSION_4);
    -}
    -
    -#define	XFS_SB_VERSION_TOOLD(v)	xfs_sb_version_toold(v)
    -static inline unsigned xfs_sb_version_toold(unsigned v)
    -{
    -	return (((v) & (XFS_SB_VERSION_QUOTABIT | XFS_SB_VERSION_ALIGNBIT)) ? \
    -		0 : \
    -		(((v) & XFS_SB_VERSION_NLINKBIT) ? \
    -			XFS_SB_VERSION_3 : \
    -			(((v) & XFS_SB_VERSION_ATTRBIT) ?  \
    -				XFS_SB_VERSION_2 : \
    -				XFS_SB_VERSION_1)));
    -}
    -
    -#define	XFS_SB_VERSION_HASATTR(sbp)	xfs_sb_version_hasattr(sbp)
    -static inline int xfs_sb_version_hasattr(xfs_sb_t *sbp)
    -{
    -	return ((sbp)->sb_versionnum == XFS_SB_VERSION_2) || \
    -		 ((sbp)->sb_versionnum == XFS_SB_VERSION_3) || \
    -		 ((XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \
    -		  ((sbp)->sb_versionnum & XFS_SB_VERSION_ATTRBIT));
    -}
    -
    -#define	XFS_SB_VERSION_ADDATTR(sbp)	xfs_sb_version_addattr(sbp)
    -static inline void xfs_sb_version_addattr(xfs_sb_t *sbp)
    -{
    -	(sbp)->sb_versionnum = (((sbp)->sb_versionnum == XFS_SB_VERSION_1) ? \
    -		XFS_SB_VERSION_2 : \
    -		((XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) ? \
    -			((sbp)->sb_versionnum | XFS_SB_VERSION_ATTRBIT) : \
    -			(XFS_SB_VERSION_4 | XFS_SB_VERSION_ATTRBIT)));
    -}
    -
    -#define	XFS_SB_VERSION_HASNLINK(sbp)	xfs_sb_version_hasnlink(sbp)
    -static inline int xfs_sb_version_hasnlink(xfs_sb_t *sbp)
    -{
    -	return ((sbp)->sb_versionnum == XFS_SB_VERSION_3) || \
    -		 ((XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \
    -		  ((sbp)->sb_versionnum & XFS_SB_VERSION_NLINKBIT));
    -}
    -
    -#define	XFS_SB_VERSION_ADDNLINK(sbp)	xfs_sb_version_addnlink(sbp)
    -static inline void xfs_sb_version_addnlink(xfs_sb_t *sbp)
    -{
    -	(sbp)->sb_versionnum = ((sbp)->sb_versionnum <= XFS_SB_VERSION_2 ? \
    -		XFS_SB_VERSION_3 : \
    -		((sbp)->sb_versionnum | XFS_SB_VERSION_NLINKBIT));
    -}
    -
    -#define	XFS_SB_VERSION_HASQUOTA(sbp)	xfs_sb_version_hasquota(sbp)
    -static inline int xfs_sb_version_hasquota(xfs_sb_t *sbp)
    -{
    -	return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \
    -		((sbp)->sb_versionnum & XFS_SB_VERSION_QUOTABIT);
    -}
    -
    -#define	XFS_SB_VERSION_ADDQUOTA(sbp)	xfs_sb_version_addquota(sbp)
    -static inline void xfs_sb_version_addquota(xfs_sb_t *sbp)
    -{
    -	(sbp)->sb_versionnum = \
    -		 (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4 ? \
    -			((sbp)->sb_versionnum | XFS_SB_VERSION_QUOTABIT) : \
    -			(XFS_SB_VERSION_TONEW((sbp)->sb_versionnum) | \
    -			 XFS_SB_VERSION_QUOTABIT));
    -}
    -
    -#define	XFS_SB_VERSION_HASALIGN(sbp)	xfs_sb_version_hasalign(sbp)
    -static inline int xfs_sb_version_hasalign(xfs_sb_t *sbp)
    -{
    -	return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \
    -		((sbp)->sb_versionnum & XFS_SB_VERSION_ALIGNBIT);
    -}
    -
    -#define	XFS_SB_VERSION_SUBALIGN(sbp)	xfs_sb_version_subalign(sbp)
    -static inline void xfs_sb_version_subalign(xfs_sb_t *sbp)
    -{
    -	(sbp)->sb_versionnum = \
    -	 XFS_SB_VERSION_TOOLD((sbp)->sb_versionnum & ~XFS_SB_VERSION_ALIGNBIT);
    -}
    -
    -#define XFS_SB_VERSION_HASDALIGN(sbp)	xfs_sb_version_hasdalign(sbp)
    -static inline int xfs_sb_version_hasdalign(xfs_sb_t *sbp)
    -{
    -	return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \
    -		((sbp)->sb_versionnum & XFS_SB_VERSION_DALIGNBIT);
    -}
    -
    -#define XFS_SB_VERSION_ADDDALIGN(sbp)	xfs_sb_version_adddalign(sbp)
    -static inline int xfs_sb_version_adddalign(xfs_sb_t *sbp)
    -{
    -	return (sbp)->sb_versionnum = \
    -		((sbp)->sb_versionnum | XFS_SB_VERSION_DALIGNBIT);
    -}
    -
    -#define XFS_SB_VERSION_HASSHARED(sbp)	xfs_sb_version_hasshared(sbp)
    -static inline int xfs_sb_version_hasshared(xfs_sb_t *sbp)
    -{
    -	return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \
    -		((sbp)->sb_versionnum & XFS_SB_VERSION_SHAREDBIT);
    -}
    -
    -#define XFS_SB_VERSION_ADDSHARED(sbp)	xfs_sb_version_addshared(sbp)
    -static inline int xfs_sb_version_addshared(xfs_sb_t *sbp)
    -{
    -	return (sbp)->sb_versionnum = \
    -		((sbp)->sb_versionnum | XFS_SB_VERSION_SHAREDBIT);
    -}
    -
    -#define XFS_SB_VERSION_SUBSHARED(sbp)	xfs_sb_version_subshared(sbp)
    -static inline int xfs_sb_version_subshared(xfs_sb_t *sbp)
    -{
    -	return (sbp)->sb_versionnum = \
    -		((sbp)->sb_versionnum & ~XFS_SB_VERSION_SHAREDBIT);
    -}
    -
    -#define XFS_SB_VERSION_HASDIRV2(sbp)	xfs_sb_version_hasdirv2(sbp)
    -static inline int xfs_sb_version_hasdirv2(xfs_sb_t *sbp)
    -{
    -	return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \
    -		((sbp)->sb_versionnum & XFS_SB_VERSION_DIRV2BIT);
    -}
    -
    -#define XFS_SB_VERSION_HASLOGV2(sbp)   xfs_sb_version_haslogv2(sbp)
    -static inline int xfs_sb_version_haslogv2(xfs_sb_t *sbp)
    -{
    -	return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \
    -		((sbp)->sb_versionnum & XFS_SB_VERSION_LOGV2BIT);
    -}
    -
    -#define XFS_SB_VERSION_HASEXTFLGBIT(sbp)	xfs_sb_version_hasextflgbit(sbp)
    -static inline int xfs_sb_version_hasextflgbit(xfs_sb_t *sbp)
    -{
    -	return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \
    -		((sbp)->sb_versionnum & XFS_SB_VERSION_EXTFLGBIT);
    -}
    -
    -#define XFS_SB_VERSION_ADDEXTFLGBIT(sbp)	xfs_sb_version_addextflgbit(sbp)
    -static inline int xfs_sb_version_addextflgbit(xfs_sb_t *sbp)
    -{
    -	return (sbp)->sb_versionnum = \
    -		((sbp)->sb_versionnum | XFS_SB_VERSION_EXTFLGBIT);
    -}
    -
    -#define XFS_SB_VERSION_SUBEXTFLGBIT(sbp)	xfs_sb_version_subextflgbit(sbp)
    -static inline int xfs_sb_version_subextflgbit(xfs_sb_t *sbp)
    -{
    -	return (sbp)->sb_versionnum = \
    -		((sbp)->sb_versionnum & ~XFS_SB_VERSION_EXTFLGBIT);
    -}
    -
    -#define XFS_SB_VERSION_HASSECTOR(sbp)   xfs_sb_version_hassector(sbp)
    -static inline int xfs_sb_version_hassector(xfs_sb_t *sbp)
    -{
    -	return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \
    -		((sbp)->sb_versionnum & XFS_SB_VERSION_SECTORBIT);
    -}
    -
    -#define XFS_SB_VERSION_HASMOREBITS(sbp)	xfs_sb_version_hasmorebits(sbp)
    -static inline int xfs_sb_version_hasmorebits(xfs_sb_t *sbp)
    -{
    -	return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \
    -		((sbp)->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT);
    -}
    -
    -/*
    - * sb_features2 bit version macros.
    - *
    - * For example, for a bit defined as XFS_SB_VERSION2_FUNBIT, has a macro:
    - *
    - * SB_VERSION_HASFUNBIT(xfs_sb_t *sbp)
    - *	((XFS_SB_VERSION_HASMOREBITS(sbp) &&
    - *	 ((sbp)->sb_features2 & XFS_SB_VERSION2_FUNBIT)
    - */
    -
    -#define XFS_SB_VERSION_HASATTR2(sbp)	xfs_sb_version_hasattr2(sbp)
    -static inline int xfs_sb_version_hasattr2(xfs_sb_t *sbp)
    -{
    -	return (XFS_SB_VERSION_HASMOREBITS(sbp)) &&	\
    -		((sbp)->sb_features2 & XFS_SB_VERSION2_ATTR2BIT);
    -}
    -
    -#define XFS_SB_VERSION_ADDATTR2(sbp)	xfs_sb_version_addattr2(sbp)
    -static inline void xfs_sb_version_addattr2(xfs_sb_t *sbp)
    -{
    -	((sbp)->sb_versionnum =	\
    -		((sbp)->sb_versionnum | XFS_SB_VERSION_MOREBITSBIT),	\
    -	((sbp)->sb_features2 =	\
    -		((sbp)->sb_features2 | XFS_SB_VERSION2_ATTR2BIT)));
    -}
    -
    -/*
    - * end of superblock version macros
    - */
    -
    -#define XFS_SB_DADDR		((xfs_daddr_t)0) /* daddr in filesystem/ag */
    -#define	XFS_SB_BLOCK(mp)	XFS_HDR_BLOCK(mp, XFS_SB_DADDR)
    -#define XFS_BUF_TO_SBP(bp)	((xfs_sb_t *)XFS_BUF_PTR(bp))
    -
    -#define	XFS_HDR_BLOCK(mp,d)	((xfs_agblock_t)XFS_BB_TO_FSBT(mp,d))
    -#define	XFS_DADDR_TO_FSB(mp,d)	XFS_AGB_TO_FSB(mp, \
    -			XFS_DADDR_TO_AGNO(mp,d), XFS_DADDR_TO_AGBNO(mp,d))
    -#define	XFS_FSB_TO_DADDR(mp,fsbno)	XFS_AGB_TO_DADDR(mp, \
    -			XFS_FSB_TO_AGNO(mp,fsbno), XFS_FSB_TO_AGBNO(mp,fsbno))
    -
    -/*
    - * File system sector to basic block conversions.
    - */
    -#define XFS_FSS_TO_BB(mp,sec)	((sec) << (mp)->m_sectbb_log)
    -#define XFS_BB_TO_FSS(mp,bb)	\
    -	(((bb) + (XFS_FSS_TO_BB(mp,1) - 1)) >> (mp)->m_sectbb_log)
    -#define XFS_BB_TO_FSST(mp,bb)	((bb) >> (mp)->m_sectbb_log)
    -
    -/*
    - * File system sector to byte conversions.
    - */
    -#define XFS_FSS_TO_B(mp,sectno)	((xfs_fsize_t)(sectno) << (mp)->m_sb.sb_sectlog)
    -#define XFS_B_TO_FSST(mp,b)	(((__uint64_t)(b)) >> (mp)->m_sb.sb_sectlog)
    -
    -/*
    - * File system block to basic block conversions.
    - */
    -#define	XFS_FSB_TO_BB(mp,fsbno)	((fsbno) << (mp)->m_blkbb_log)
    -#define	XFS_BB_TO_FSB(mp,bb)	\
    -	(((bb) + (XFS_FSB_TO_BB(mp,1) - 1)) >> (mp)->m_blkbb_log)
    -#define	XFS_BB_TO_FSBT(mp,bb)	((bb) >> (mp)->m_blkbb_log)
    -#define	XFS_BB_FSB_OFFSET(mp,bb) ((bb) & ((mp)->m_bsize - 1))
    -
    -/*
    - * File system block to byte conversions.
    - */
    -#define XFS_FSB_TO_B(mp,fsbno)	((xfs_fsize_t)(fsbno) << (mp)->m_sb.sb_blocklog)
    -#define XFS_B_TO_FSB(mp,b)	\
    -	((((__uint64_t)(b)) + (mp)->m_blockmask) >> (mp)->m_sb.sb_blocklog)
    -#define XFS_B_TO_FSBT(mp,b)	(((__uint64_t)(b)) >> (mp)->m_sb.sb_blocklog)
    -#define XFS_B_FSB_OFFSET(mp,b)	((b) & (mp)->m_blockmask)
    -
    -#endif	/* __XFS_SB_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_trans.c b/sys/gnu/fs/xfs/xfs_trans.c
    deleted file mode 100644
    index 75cbade4e5e..00000000000
    --- a/sys/gnu/fs/xfs/xfs_trans.c
    +++ /dev/null
    @@ -1,1382 +0,0 @@
    -/*
    - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_error.h"
    -#include "xfs_da_btree.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_btree.h"
    -#include "xfs_ialloc.h"
    -#include "xfs_alloc.h"
    -#include "xfs_bmap.h"
    -#include "xfs_quota.h"
    -#include "xfs_trans_priv.h"
    -#include "xfs_trans_space.h"
    -
    -
    -STATIC void	xfs_trans_apply_sb_deltas(xfs_trans_t *);
    -STATIC uint	xfs_trans_count_vecs(xfs_trans_t *);
    -STATIC void	xfs_trans_fill_vecs(xfs_trans_t *, xfs_log_iovec_t *);
    -STATIC void	xfs_trans_uncommit(xfs_trans_t *, uint);
    -STATIC void	xfs_trans_committed(xfs_trans_t *, int);
    -STATIC void	xfs_trans_chunk_committed(xfs_log_item_chunk_t *, xfs_lsn_t, int);
    -STATIC void	xfs_trans_free(xfs_trans_t *);
    -
    -kmem_zone_t	*xfs_trans_zone;
    -
    -
    -/*
    - * Reservation functions here avoid a huge stack in xfs_trans_init
    - * due to register overflow from temporaries in the calculations.
    - */
    -
    -STATIC uint
    -xfs_calc_write_reservation(xfs_mount_t *mp)
    -{
    -	return XFS_CALC_WRITE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
    -}
    -
    -STATIC uint
    -xfs_calc_itruncate_reservation(xfs_mount_t *mp)
    -{
    -	return XFS_CALC_ITRUNCATE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
    -}
    -
    -STATIC uint
    -xfs_calc_rename_reservation(xfs_mount_t *mp)
    -{
    -	return XFS_CALC_RENAME_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
    -}
    -
    -STATIC uint
    -xfs_calc_link_reservation(xfs_mount_t *mp)
    -{
    -	return XFS_CALC_LINK_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
    -}
    -
    -STATIC uint
    -xfs_calc_remove_reservation(xfs_mount_t *mp)
    -{
    -	return XFS_CALC_REMOVE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
    -}
    -
    -STATIC uint
    -xfs_calc_symlink_reservation(xfs_mount_t *mp)
    -{
    -	return XFS_CALC_SYMLINK_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
    -}
    -
    -STATIC uint
    -xfs_calc_create_reservation(xfs_mount_t *mp)
    -{
    -	return XFS_CALC_CREATE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
    -}
    -
    -STATIC uint
    -xfs_calc_mkdir_reservation(xfs_mount_t *mp)
    -{
    -	return XFS_CALC_MKDIR_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
    -}
    -
    -STATIC uint
    -xfs_calc_ifree_reservation(xfs_mount_t *mp)
    -{
    -	return XFS_CALC_IFREE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
    -}
    -
    -STATIC uint
    -xfs_calc_ichange_reservation(xfs_mount_t *mp)
    -{
    -	return XFS_CALC_ICHANGE_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
    -}
    -
    -STATIC uint
    -xfs_calc_growdata_reservation(xfs_mount_t *mp)
    -{
    -	return XFS_CALC_GROWDATA_LOG_RES(mp);
    -}
    -
    -STATIC uint
    -xfs_calc_growrtalloc_reservation(xfs_mount_t *mp)
    -{
    -	return XFS_CALC_GROWRTALLOC_LOG_RES(mp);
    -}
    -
    -STATIC uint
    -xfs_calc_growrtzero_reservation(xfs_mount_t *mp)
    -{
    -	return XFS_CALC_GROWRTZERO_LOG_RES(mp);
    -}
    -
    -STATIC uint
    -xfs_calc_growrtfree_reservation(xfs_mount_t *mp)
    -{
    -	return XFS_CALC_GROWRTFREE_LOG_RES(mp);
    -}
    -
    -STATIC uint
    -xfs_calc_swrite_reservation(xfs_mount_t *mp)
    -{
    -	return XFS_CALC_SWRITE_LOG_RES(mp);
    -}
    -
    -STATIC uint
    -xfs_calc_writeid_reservation(xfs_mount_t *mp)
    -{
    -	return XFS_CALC_WRITEID_LOG_RES(mp);
    -}
    -
    -STATIC uint
    -xfs_calc_addafork_reservation(xfs_mount_t *mp)
    -{
    -	return XFS_CALC_ADDAFORK_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
    -}
    -
    -STATIC uint
    -xfs_calc_attrinval_reservation(xfs_mount_t *mp)
    -{
    -	return XFS_CALC_ATTRINVAL_LOG_RES(mp);
    -}
    -
    -STATIC uint
    -xfs_calc_attrset_reservation(xfs_mount_t *mp)
    -{
    -	return XFS_CALC_ATTRSET_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
    -}
    -
    -STATIC uint
    -xfs_calc_attrrm_reservation(xfs_mount_t *mp)
    -{
    -	return XFS_CALC_ATTRRM_LOG_RES(mp) + XFS_DQUOT_LOGRES(mp);
    -}
    -
    -STATIC uint
    -xfs_calc_clear_agi_bucket_reservation(xfs_mount_t *mp)
    -{
    -	return XFS_CALC_CLEAR_AGI_BUCKET_LOG_RES(mp);
    -}
    -
    -/*
    - * Initialize the precomputed transaction reservation values
    - * in the mount structure.
    - */
    -void
    -xfs_trans_init(
    -	xfs_mount_t	*mp)
    -{
    -	xfs_trans_reservations_t	*resp;
    -
    -	resp = &(mp->m_reservations);
    -	resp->tr_write = xfs_calc_write_reservation(mp);
    -	resp->tr_itruncate = xfs_calc_itruncate_reservation(mp);
    -	resp->tr_rename = xfs_calc_rename_reservation(mp);
    -	resp->tr_link = xfs_calc_link_reservation(mp);
    -	resp->tr_remove = xfs_calc_remove_reservation(mp);
    -	resp->tr_symlink = xfs_calc_symlink_reservation(mp);
    -	resp->tr_create = xfs_calc_create_reservation(mp);
    -	resp->tr_mkdir = xfs_calc_mkdir_reservation(mp);
    -	resp->tr_ifree = xfs_calc_ifree_reservation(mp);
    -	resp->tr_ichange = xfs_calc_ichange_reservation(mp);
    -	resp->tr_growdata = xfs_calc_growdata_reservation(mp);
    -	resp->tr_swrite = xfs_calc_swrite_reservation(mp);
    -	resp->tr_writeid = xfs_calc_writeid_reservation(mp);
    -	resp->tr_addafork = xfs_calc_addafork_reservation(mp);
    -	resp->tr_attrinval = xfs_calc_attrinval_reservation(mp);
    -	resp->tr_attrset = xfs_calc_attrset_reservation(mp);
    -	resp->tr_attrrm = xfs_calc_attrrm_reservation(mp);
    -	resp->tr_clearagi = xfs_calc_clear_agi_bucket_reservation(mp);
    -	resp->tr_growrtalloc = xfs_calc_growrtalloc_reservation(mp);
    -	resp->tr_growrtzero = xfs_calc_growrtzero_reservation(mp);
    -	resp->tr_growrtfree = xfs_calc_growrtfree_reservation(mp);
    -}
    -
    -/*
    - * This routine is called to allocate a transaction structure.
    - * The type parameter indicates the type of the transaction.  These
    - * are enumerated in xfs_trans.h.
    - *
    - * Dynamically allocate the transaction structure from the transaction
    - * zone, initialize it, and return it to the caller.
    - */
    -xfs_trans_t *
    -xfs_trans_alloc(
    -	xfs_mount_t	*mp,
    -	uint		type)
    -{
    -#ifdef RMC
    -	fs_check_frozen(XFS_MTOVFS(mp), SB_FREEZE_TRANS);
    -#endif
    -	atomic_inc(&mp->m_active_trans);
    -
    -	return (_xfs_trans_alloc(mp, type));
    -
    -}
    -
    -xfs_trans_t *
    -_xfs_trans_alloc(
    -	xfs_mount_t	*mp,
    -	uint		type)
    -{
    -	xfs_trans_t	*tp;
    -
    -	ASSERT(xfs_trans_zone != NULL);
    -	tp = kmem_zone_zalloc(xfs_trans_zone, KM_SLEEP);
    -
    -	/*
    -	 * Initialize the transaction structure.
    -	 */
    -	tp->t_magic = XFS_TRANS_MAGIC;
    -	tp->t_type = type;
    -	tp->t_mountp = mp;
    -	tp->t_items_free = XFS_LIC_NUM_SLOTS;
    -	tp->t_busy_free = XFS_LBC_NUM_SLOTS;
    -	XFS_LIC_INIT(&(tp->t_items));
    -	XFS_LBC_INIT(&(tp->t_busy));
    -
    -	return (tp);
    -}
    -
    -/*
    - * This is called to create a new transaction which will share the
    - * permanent log reservation of the given transaction.  The remaining
    - * unused block and rt extent reservations are also inherited.  This
    - * implies that the original transaction is no longer allowed to allocate
    - * blocks.  Locks and log items, however, are no inherited.  They must
    - * be added to the new transaction explicitly.
    - */
    -xfs_trans_t *
    -xfs_trans_dup(
    -	xfs_trans_t	*tp)
    -{
    -	xfs_trans_t	*ntp;
    -
    -	ntp = kmem_zone_zalloc(xfs_trans_zone, KM_SLEEP);
    -
    -	/*
    -	 * Initialize the new transaction structure.
    -	 */
    -	ntp->t_magic = XFS_TRANS_MAGIC;
    -	ntp->t_type = tp->t_type;
    -	ntp->t_mountp = tp->t_mountp;
    -	ntp->t_items_free = XFS_LIC_NUM_SLOTS;
    -	ntp->t_busy_free = XFS_LBC_NUM_SLOTS;
    -	XFS_LIC_INIT(&(ntp->t_items));
    -	XFS_LBC_INIT(&(ntp->t_busy));
    -
    -	ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);
    -	ASSERT(tp->t_ticket != NULL);
    -
    -	ntp->t_flags = XFS_TRANS_PERM_LOG_RES | (tp->t_flags & XFS_TRANS_RESERVE);
    -	ntp->t_ticket = tp->t_ticket;
    -	ntp->t_blk_res = tp->t_blk_res - tp->t_blk_res_used;
    -	tp->t_blk_res = tp->t_blk_res_used;
    -	ntp->t_rtx_res = tp->t_rtx_res - tp->t_rtx_res_used;
    -	tp->t_rtx_res = tp->t_rtx_res_used;
    -	PFLAGS_DUP(&tp->t_pflags, &ntp->t_pflags);
    -
    -	XFS_TRANS_DUP_DQINFO(tp->t_mountp, tp, ntp);
    -
    -	atomic_inc(&tp->t_mountp->m_active_trans);
    -	return ntp;
    -}
    -
    -/*
    - * This is called to reserve free disk blocks and log space for the
    - * given transaction.  This must be done before allocating any resources
    - * within the transaction.
    - *
    - * This will return ENOSPC if there are not enough blocks available.
    - * It will sleep waiting for available log space.
    - * The only valid value for the flags parameter is XFS_RES_LOG_PERM, which
    - * is used by long running transactions.  If any one of the reservations
    - * fails then they will all be backed out.
    - *
    - * This does not do quota reservations. That typically is done by the
    - * caller afterwards.
    - */
    -int
    -xfs_trans_reserve(
    -	xfs_trans_t	*tp,
    -	uint		blocks,
    -	uint		logspace,
    -	uint		rtextents,
    -	uint		flags,
    -	uint		logcount)
    -{
    -	int		log_flags;
    -	int		error;
    -	int	rsvd;
    -
    -	error = 0;
    -	rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
    -
    -	/* Mark this thread as being in a transaction */
    -        PFLAGS_SET_FSTRANS(&tp->t_pflags);
    -
    -
    -	/*
    -	 * Attempt to reserve the needed disk blocks by decrementing
    -	 * the number needed from the number available.  This will
    -	 * fail if the count would go below zero.
    -	 */
    -	if (blocks > 0) {
    -		error = xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FDBLOCKS,
    -					  -blocks, rsvd);
    -		if (error != 0) {
    -                        PFLAGS_RESTORE_FSTRANS(&tp->t_pflags);
    -			return (XFS_ERROR(ENOSPC));
    -		}
    -		tp->t_blk_res += blocks;
    -	}
    -
    -	/*
    -	 * Reserve the log space needed for this transaction.
    -	 */
    -	if (logspace > 0) {
    -		ASSERT((tp->t_log_res == 0) || (tp->t_log_res == logspace));
    -		ASSERT((tp->t_log_count == 0) ||
    -			(tp->t_log_count == logcount));
    -		if (flags & XFS_TRANS_PERM_LOG_RES) {
    -			log_flags = XFS_LOG_PERM_RESERV;
    -			tp->t_flags |= XFS_TRANS_PERM_LOG_RES;
    -		} else {
    -			ASSERT(tp->t_ticket == NULL);
    -			ASSERT(!(tp->t_flags & XFS_TRANS_PERM_LOG_RES));
    -			log_flags = 0;
    -		}
    -
    -		error = xfs_log_reserve(tp->t_mountp, logspace, logcount,
    -					&tp->t_ticket,
    -					XFS_TRANSACTION, log_flags, tp->t_type);
    -		if (error) {
    -			goto undo_blocks;
    -		}
    -		tp->t_log_res = logspace;
    -		tp->t_log_count = logcount;
    -	}
    -
    -	/*
    -	 * Attempt to reserve the needed realtime extents by decrementing
    -	 * the number needed from the number available.  This will
    -	 * fail if the count would go below zero.
    -	 */
    -	if (rtextents > 0) {
    -		error = xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FREXTENTS,
    -					  -rtextents, rsvd);
    -		if (error) {
    -			error = XFS_ERROR(ENOSPC);
    -			goto undo_log;
    -		}
    -		tp->t_rtx_res += rtextents;
    -	}
    -
    -	return 0;
    -
    -	/*
    -	 * Error cases jump to one of these labels to undo any
    -	 * reservations which have already been performed.
    -	 */
    -undo_log:
    -	if (logspace > 0) {
    -		if (flags & XFS_TRANS_PERM_LOG_RES) {
    -			log_flags = XFS_LOG_REL_PERM_RESERV;
    -		} else {
    -			log_flags = 0;
    -		}
    -		xfs_log_done(tp->t_mountp, tp->t_ticket, NULL, log_flags);
    -		tp->t_ticket = NULL;
    -		tp->t_log_res = 0;
    -		tp->t_flags &= ~XFS_TRANS_PERM_LOG_RES;
    -	}
    -
    -undo_blocks:
    -	if (blocks > 0) {
    -		(void) xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FDBLOCKS,
    -					 blocks, rsvd);
    -		tp->t_blk_res = 0;
    -	}
    -
    -        PFLAGS_RESTORE_FSTRANS(&tp->t_pflags);
    -
    -	return (error);
    -}
    -
    -
    -/*
    - * Record the indicated change to the given field for application
    - * to the file system's superblock when the transaction commits.
    - * For now, just store the change in the transaction structure.
    - *
    - * Mark the transaction structure to indicate that the superblock
    - * needs to be updated before committing.
    - */
    -void
    -xfs_trans_mod_sb(
    -	xfs_trans_t	*tp,
    -	uint		field,
    -	long		delta)
    -{
    -
    -	switch (field) {
    -	case XFS_TRANS_SB_ICOUNT:
    -		tp->t_icount_delta += delta;
    -		break;
    -	case XFS_TRANS_SB_IFREE:
    -		tp->t_ifree_delta += delta;
    -		break;
    -	case XFS_TRANS_SB_FDBLOCKS:
    -		/*
    -		 * Track the number of blocks allocated in the
    -		 * transaction.  Make sure it does not exceed the
    -		 * number reserved.
    -		 */
    -		if (delta < 0) {
    -			tp->t_blk_res_used += (uint)-delta;
    -			ASSERT(tp->t_blk_res_used <= tp->t_blk_res);
    -		}
    -		tp->t_fdblocks_delta += delta;
    -		break;
    -	case XFS_TRANS_SB_RES_FDBLOCKS:
    -		/*
    -		 * The allocation has already been applied to the
    -		 * in-core superblock's counter.  This should only
    -		 * be applied to the on-disk superblock.
    -		 */
    -		ASSERT(delta < 0);
    -		tp->t_res_fdblocks_delta += delta;
    -		break;
    -	case XFS_TRANS_SB_FREXTENTS:
    -		/*
    -		 * Track the number of blocks allocated in the
    -		 * transaction.  Make sure it does not exceed the
    -		 * number reserved.
    -		 */
    -		if (delta < 0) {
    -			tp->t_rtx_res_used += (uint)-delta;
    -			ASSERT(tp->t_rtx_res_used <= tp->t_rtx_res);
    -		}
    -		tp->t_frextents_delta += delta;
    -		break;
    -	case XFS_TRANS_SB_RES_FREXTENTS:
    -		/*
    -		 * The allocation has already been applied to the
    -		 * in-core superblock's counter.  This should only
    -		 * be applied to the on-disk superblock.
    -		 */
    -		ASSERT(delta < 0);
    -		tp->t_res_frextents_delta += delta;
    -		break;
    -	case XFS_TRANS_SB_DBLOCKS:
    -		ASSERT(delta > 0);
    -		tp->t_dblocks_delta += delta;
    -		break;
    -	case XFS_TRANS_SB_AGCOUNT:
    -		ASSERT(delta > 0);
    -		tp->t_agcount_delta += delta;
    -		break;
    -	case XFS_TRANS_SB_IMAXPCT:
    -		tp->t_imaxpct_delta += delta;
    -		break;
    -	case XFS_TRANS_SB_REXTSIZE:
    -		tp->t_rextsize_delta += delta;
    -		break;
    -	case XFS_TRANS_SB_RBMBLOCKS:
    -		tp->t_rbmblocks_delta += delta;
    -		break;
    -	case XFS_TRANS_SB_RBLOCKS:
    -		tp->t_rblocks_delta += delta;
    -		break;
    -	case XFS_TRANS_SB_REXTENTS:
    -		tp->t_rextents_delta += delta;
    -		break;
    -	case XFS_TRANS_SB_REXTSLOG:
    -		tp->t_rextslog_delta += delta;
    -		break;
    -	default:
    -		ASSERT(0);
    -		return;
    -	}
    -
    -	tp->t_flags |= (XFS_TRANS_SB_DIRTY | XFS_TRANS_DIRTY);
    -}
    -
    -/*
    - * xfs_trans_apply_sb_deltas() is called from the commit code
    - * to bring the superblock buffer into the current transaction
    - * and modify it as requested by earlier calls to xfs_trans_mod_sb().
    - *
    - * For now we just look at each field allowed to change and change
    - * it if necessary.
    - */
    -STATIC void
    -xfs_trans_apply_sb_deltas(
    -	xfs_trans_t	*tp)
    -{
    -	xfs_sb_t	*sbp;
    -	xfs_buf_t	*bp;
    -	int		whole = 0;
    -
    -	bp = xfs_trans_getsb(tp, tp->t_mountp, 0);
    -	sbp = XFS_BUF_TO_SBP(bp);
    -
    -	/*
    -	 * Check that superblock mods match the mods made to AGF counters.
    -	 */
    -	ASSERT((tp->t_fdblocks_delta + tp->t_res_fdblocks_delta) ==
    -	       (tp->t_ag_freeblks_delta + tp->t_ag_flist_delta +
    -		tp->t_ag_btree_delta));
    -
    -	if (tp->t_icount_delta != 0) {
    -		INT_MOD(sbp->sb_icount, ARCH_CONVERT, tp->t_icount_delta);
    -	}
    -	if (tp->t_ifree_delta != 0) {
    -		INT_MOD(sbp->sb_ifree, ARCH_CONVERT, tp->t_ifree_delta);
    -	}
    -
    -	if (tp->t_fdblocks_delta != 0) {
    -		INT_MOD(sbp->sb_fdblocks, ARCH_CONVERT, tp->t_fdblocks_delta);
    -	}
    -	if (tp->t_res_fdblocks_delta != 0) {
    -		INT_MOD(sbp->sb_fdblocks, ARCH_CONVERT, tp->t_res_fdblocks_delta);
    -	}
    -
    -	if (tp->t_frextents_delta != 0) {
    -		INT_MOD(sbp->sb_frextents, ARCH_CONVERT, tp->t_frextents_delta);
    -	}
    -	if (tp->t_res_frextents_delta != 0) {
    -		INT_MOD(sbp->sb_frextents, ARCH_CONVERT, tp->t_res_frextents_delta);
    -	}
    -	if (tp->t_dblocks_delta != 0) {
    -		INT_MOD(sbp->sb_dblocks, ARCH_CONVERT, tp->t_dblocks_delta);
    -		whole = 1;
    -	}
    -	if (tp->t_agcount_delta != 0) {
    -		INT_MOD(sbp->sb_agcount, ARCH_CONVERT, tp->t_agcount_delta);
    -		whole = 1;
    -	}
    -	if (tp->t_imaxpct_delta != 0) {
    -		INT_MOD(sbp->sb_imax_pct, ARCH_CONVERT, tp->t_imaxpct_delta);
    -		whole = 1;
    -	}
    -	if (tp->t_rextsize_delta != 0) {
    -		INT_MOD(sbp->sb_rextsize, ARCH_CONVERT, tp->t_rextsize_delta);
    -		whole = 1;
    -	}
    -	if (tp->t_rbmblocks_delta != 0) {
    -		INT_MOD(sbp->sb_rbmblocks, ARCH_CONVERT, tp->t_rbmblocks_delta);
    -		whole = 1;
    -	}
    -	if (tp->t_rblocks_delta != 0) {
    -		INT_MOD(sbp->sb_rblocks, ARCH_CONVERT, tp->t_rblocks_delta);
    -		whole = 1;
    -	}
    -	if (tp->t_rextents_delta != 0) {
    -		INT_MOD(sbp->sb_rextents, ARCH_CONVERT, tp->t_rextents_delta);
    -		whole = 1;
    -	}
    -	if (tp->t_rextslog_delta != 0) {
    -		INT_MOD(sbp->sb_rextslog, ARCH_CONVERT, tp->t_rextslog_delta);
    -		whole = 1;
    -	}
    -
    -	if (whole)
    -		/*
    -		 * Log the whole thing, the fields are noncontiguous.
    -		 */
    -		xfs_trans_log_buf(tp, bp, 0, sizeof(xfs_sb_t) - 1);
    -	else
    -		/*
    -		 * Since all the modifiable fields are contiguous, we
    -		 * can get away with this.
    -		 */
    -		xfs_trans_log_buf(tp, bp, offsetof(xfs_sb_t, sb_icount),
    -				  offsetof(xfs_sb_t, sb_frextents) +
    -				  sizeof(sbp->sb_frextents) - 1);
    -
    -#ifdef XXXKAN
    -	XFS_MTOVFS(tp->t_mountp)->vfs_super->s_dirt = 1;
    -#endif
    -}
    -
    -/*
    - * xfs_trans_unreserve_and_mod_sb() is called to release unused
    - * reservations and apply superblock counter changes to the in-core
    - * superblock.
    - *
    - * This is done efficiently with a single call to xfs_mod_incore_sb_batch().
    - */
    -STATIC void
    -xfs_trans_unreserve_and_mod_sb(
    -	xfs_trans_t	*tp)
    -{
    -	xfs_mod_sb_t	msb[14];	/* If you add cases, add entries */
    -	xfs_mod_sb_t	*msbp;
    -	/* REFERENCED */
    -	int		error;
    -	int		rsvd;
    -
    -	msbp = msb;
    -	rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
    -
    -	/*
    -	 * Release any reserved blocks.  Any that were allocated
    -	 * will be taken back again by fdblocks_delta below.
    -	 */
    -	if (tp->t_blk_res > 0) {
    -		msbp->msb_field = XFS_SBS_FDBLOCKS;
    -		msbp->msb_delta = tp->t_blk_res;
    -		msbp++;
    -	}
    -
    -	/*
    -	 * Release any reserved real time extents .  Any that were
    -	 * allocated will be taken back again by frextents_delta below.
    -	 */
    -	if (tp->t_rtx_res > 0) {
    -		msbp->msb_field = XFS_SBS_FREXTENTS;
    -		msbp->msb_delta = tp->t_rtx_res;
    -		msbp++;
    -	}
    -
    -	/*
    -	 * Apply any superblock modifications to the in-core version.
    -	 * The t_res_fdblocks_delta and t_res_frextents_delta fields are
    -	 * explicitly NOT applied to the in-core superblock.
    -	 * The idea is that that has already been done.
    -	 */
    -	if (tp->t_flags & XFS_TRANS_SB_DIRTY) {
    -		if (tp->t_icount_delta != 0) {
    -			msbp->msb_field = XFS_SBS_ICOUNT;
    -			msbp->msb_delta = (int)tp->t_icount_delta;
    -			msbp++;
    -		}
    -		if (tp->t_ifree_delta != 0) {
    -			msbp->msb_field = XFS_SBS_IFREE;
    -			msbp->msb_delta = (int)tp->t_ifree_delta;
    -			msbp++;
    -		}
    -		if (tp->t_fdblocks_delta != 0) {
    -			msbp->msb_field = XFS_SBS_FDBLOCKS;
    -			msbp->msb_delta = (int)tp->t_fdblocks_delta;
    -			msbp++;
    -		}
    -		if (tp->t_frextents_delta != 0) {
    -			msbp->msb_field = XFS_SBS_FREXTENTS;
    -			msbp->msb_delta = (int)tp->t_frextents_delta;
    -			msbp++;
    -		}
    -		if (tp->t_dblocks_delta != 0) {
    -			msbp->msb_field = XFS_SBS_DBLOCKS;
    -			msbp->msb_delta = (int)tp->t_dblocks_delta;
    -			msbp++;
    -		}
    -		if (tp->t_agcount_delta != 0) {
    -			msbp->msb_field = XFS_SBS_AGCOUNT;
    -			msbp->msb_delta = (int)tp->t_agcount_delta;
    -			msbp++;
    -		}
    -		if (tp->t_imaxpct_delta != 0) {
    -			msbp->msb_field = XFS_SBS_IMAX_PCT;
    -			msbp->msb_delta = (int)tp->t_imaxpct_delta;
    -			msbp++;
    -		}
    -		if (tp->t_rextsize_delta != 0) {
    -			msbp->msb_field = XFS_SBS_REXTSIZE;
    -			msbp->msb_delta = (int)tp->t_rextsize_delta;
    -			msbp++;
    -		}
    -		if (tp->t_rbmblocks_delta != 0) {
    -			msbp->msb_field = XFS_SBS_RBMBLOCKS;
    -			msbp->msb_delta = (int)tp->t_rbmblocks_delta;
    -			msbp++;
    -		}
    -		if (tp->t_rblocks_delta != 0) {
    -			msbp->msb_field = XFS_SBS_RBLOCKS;
    -			msbp->msb_delta = (int)tp->t_rblocks_delta;
    -			msbp++;
    -		}
    -		if (tp->t_rextents_delta != 0) {
    -			msbp->msb_field = XFS_SBS_REXTENTS;
    -			msbp->msb_delta = (int)tp->t_rextents_delta;
    -			msbp++;
    -		}
    -		if (tp->t_rextslog_delta != 0) {
    -			msbp->msb_field = XFS_SBS_REXTSLOG;
    -			msbp->msb_delta = (int)tp->t_rextslog_delta;
    -			msbp++;
    -		}
    -	}
    -
    -	/*
    -	 * If we need to change anything, do it.
    -	 */
    -	if (msbp > msb) {
    -		error = xfs_mod_incore_sb_batch(tp->t_mountp, msb,
    -			(uint)(msbp - msb), rsvd);
    -		ASSERT(error == 0);
    -	}
    -}
    -
    -
    -/*
    - * xfs_trans_commit
    - *
    - * Commit the given transaction to the log a/synchronously.
    - *
    - * XFS disk error handling mechanism is not based on a typical
    - * transaction abort mechanism. Logically after the filesystem
    - * gets marked 'SHUTDOWN', we can't let any new transactions
    - * be durable - ie. committed to disk - because some metadata might
    - * be inconsistent. In such cases, this returns an error, and the
    - * caller may assume that all locked objects joined to the transaction
    - * have already been unlocked as if the commit had succeeded.
    - * Do not reference the transaction structure after this call.
    - */
    - /*ARGSUSED*/
    -int
    -_xfs_trans_commit(
    -	xfs_trans_t	*tp,
    -	uint		flags,
    -	xfs_lsn_t	*commit_lsn_p,
    -	int		*log_flushed)
    -{
    -	xfs_log_iovec_t		*log_vector;
    -	int			nvec;
    -	xfs_mount_t		*mp;
    -	xfs_lsn_t		commit_lsn;
    -	/* REFERENCED */
    -	int			error;
    -	int			log_flags;
    -	int			sync;
    -#define	XFS_TRANS_LOGVEC_COUNT	16
    -	xfs_log_iovec_t		log_vector_fast[XFS_TRANS_LOGVEC_COUNT];
    -	void			*commit_iclog;
    -	int			shutdown;
    -
    -	commit_lsn = -1;
    -
    -	/*
    -	 * Determine whether this commit is releasing a permanent
    -	 * log reservation or not.
    -	 */
    -	if (flags & XFS_TRANS_RELEASE_LOG_RES) {
    -		ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);
    -		log_flags = XFS_LOG_REL_PERM_RESERV;
    -	} else {
    -		log_flags = 0;
    -	}
    -	mp = tp->t_mountp;
    -
    -	/*
    -	 * If there is nothing to be logged by the transaction,
    -	 * then unlock all of the items associated with the
    -	 * transaction and free the transaction structure.
    -	 * Also make sure to return any reserved blocks to
    -	 * the free pool.
    -	 */
    -shut_us_down:
    -	shutdown = XFS_FORCED_SHUTDOWN(mp) ? EIO : 0;
    -	if (!(tp->t_flags & XFS_TRANS_DIRTY) || shutdown) {
    -		xfs_trans_unreserve_and_mod_sb(tp);
    -		/*
    -		 * It is indeed possible for the transaction to be
    -		 * not dirty but the dqinfo portion to be. All that
    -		 * means is that we have some (non-persistent) quota
    -		 * reservations that need to be unreserved.
    -		 */
    -		XFS_TRANS_UNRESERVE_AND_MOD_DQUOTS(mp, tp);
    -		if (tp->t_ticket) {
    -			commit_lsn = xfs_log_done(mp, tp->t_ticket,
    -							NULL, log_flags);
    -			if (commit_lsn == -1 && !shutdown)
    -				shutdown = XFS_ERROR(EIO);
    -		}
    -                PFLAGS_RESTORE_FSTRANS(&tp->t_pflags);
    -		xfs_trans_free_items(tp, shutdown? XFS_TRANS_ABORT : 0);
    -		xfs_trans_free_busy(tp);
    -		xfs_trans_free(tp);
    -		XFS_STATS_INC(xs_trans_empty);
    -		if (commit_lsn_p)
    -			*commit_lsn_p = commit_lsn;
    -		return (shutdown);
    -	}
    -	ASSERT(tp->t_ticket != NULL);
    -
    -	/*
    -	 * If we need to update the superblock, then do it now.
    -	 */
    -	if (tp->t_flags & XFS_TRANS_SB_DIRTY) {
    -		xfs_trans_apply_sb_deltas(tp);
    -	}
    -	XFS_TRANS_APPLY_DQUOT_DELTAS(mp, tp);
    -
    -	/*
    -	 * Ask each log item how many log_vector entries it will
    -	 * need so we can figure out how many to allocate.
    -	 * Try to avoid the kmem_alloc() call in the common case
    -	 * by using a vector from the stack when it fits.
    -	 */
    -	nvec = xfs_trans_count_vecs(tp);
    -	if (nvec == 0) {
    -		xfs_force_shutdown(mp, XFS_LOG_IO_ERROR);
    -		goto shut_us_down;
    -	} else if (nvec <= XFS_TRANS_LOGVEC_COUNT) {
    -		log_vector = log_vector_fast;
    -	} else {
    -		log_vector = (xfs_log_iovec_t *)kmem_alloc(nvec *
    -						   sizeof(xfs_log_iovec_t),
    -						   KM_SLEEP);
    -	}
    -
    -	/*
    -	 * Fill in the log_vector and pin the logged items, and
    -	 * then write the transaction to the log.
    -	 */
    -	xfs_trans_fill_vecs(tp, log_vector);
    -
    -	error = xfs_log_write(mp, log_vector, nvec, tp->t_ticket, &(tp->t_lsn));
    -
    -	/*
    -	 * The transaction is committed incore here, and can go out to disk
    -	 * at any time after this call.  However, all the items associated
    -	 * with the transaction are still locked and pinned in memory.
    -	 */
    -	commit_lsn = xfs_log_done(mp, tp->t_ticket, &commit_iclog, log_flags);
    -
    -	tp->t_commit_lsn = commit_lsn;
    -	if (nvec > XFS_TRANS_LOGVEC_COUNT) {
    -		kmem_free(log_vector, nvec * sizeof(xfs_log_iovec_t));
    -	}
    -
    -	if (commit_lsn_p)
    -		*commit_lsn_p = commit_lsn;
    -
    -	/*
    -	 * If we got a log write error. Unpin the logitems that we
    -	 * had pinned, clean up, free trans structure, and return error.
    -	 */
    -	if (error || commit_lsn == -1) {
    -                PFLAGS_RESTORE_FSTRANS(&tp->t_pflags);
    -		xfs_trans_uncommit(tp, flags|XFS_TRANS_ABORT);
    -		return XFS_ERROR(EIO);
    -	}
    -
    -	/*
    -	 * Once the transaction has committed, unused
    -	 * reservations need to be released and changes to
    -	 * the superblock need to be reflected in the in-core
    -	 * version.  Do that now.
    -	 */
    -	xfs_trans_unreserve_and_mod_sb(tp);
    -
    -	sync = tp->t_flags & XFS_TRANS_SYNC;
    -
    -	/*
    -	 * Tell the LM to call the transaction completion routine
    -	 * when the log write with LSN commit_lsn completes (e.g.
    -	 * when the transaction commit really hits the on-disk log).
    -	 * After this call we cannot reference tp, because the call
    -	 * can happen at any time and the call will free the transaction
    -	 * structure pointed to by tp.  The only case where we call
    -	 * the completion routine (xfs_trans_committed) directly is
    -	 * if the log is turned off on a debug kernel or we're
    -	 * running in simulation mode (the log is explicitly turned
    -	 * off).
    -	 */
    -	tp->t_logcb.cb_func = (void(*)(void*, int))xfs_trans_committed;
    -	tp->t_logcb.cb_arg = tp;
    -
    -	/*
    -	 * We need to pass the iclog buffer which was used for the
    -	 * transaction commit record into this function, and attach
    -	 * the callback to it. The callback must be attached before
    -	 * the items are unlocked to avoid racing with other threads
    -	 * waiting for an item to unlock.
    -	 */
    -	shutdown = xfs_log_notify(mp, commit_iclog, &(tp->t_logcb));
    -
    -	/*
    -	 * Mark this thread as no longer being in a transaction
    -	 */
    -	PFLAGS_RESTORE_FSTRANS(&tp->t_pflags);
    -
    -	/*
    -	 * Once all the items of the transaction have been copied
    -	 * to the in core log and the callback is attached, the
    -	 * items can be unlocked.
    -	 *
    -	 * This will free descriptors pointing to items which were
    -	 * not logged since there is nothing more to do with them.
    -	 * For items which were logged, we will keep pointers to them
    -	 * so they can be unpinned after the transaction commits to disk.
    -	 * This will also stamp each modified meta-data item with
    -	 * the commit lsn of this transaction for dependency tracking
    -	 * purposes.
    -	 */
    -	xfs_trans_unlock_items(tp, commit_lsn);
    -
    -	/*
    -	 * If we detected a log error earlier, finish committing
    -	 * the transaction now (unpin log items, etc).
    -	 *
    -	 * Order is critical here, to avoid using the transaction
    -	 * pointer after its been freed (by xfs_trans_committed
    -	 * either here now, or as a callback).  We cannot do this
    -	 * step inside xfs_log_notify as was done earlier because
    -	 * of this issue.
    -	 */
    -	if (shutdown)
    -		xfs_trans_committed(tp, XFS_LI_ABORTED);
    -
    -	/*
    -	 * Now that the xfs_trans_committed callback has been attached,
    -	 * and the items are released we can finally allow the iclog to
    -	 * go to disk.
    -	 */
    -	error = xfs_log_release_iclog(mp, commit_iclog);
    -
    -	/*
    -	 * If the transaction needs to be synchronous, then force the
    -	 * log out now and wait for it.
    -	 */
    -	if (sync) {
    -		if (!error) {
    -			error = _xfs_log_force(mp, commit_lsn,
    -				      XFS_LOG_FORCE | XFS_LOG_SYNC,
    -				      log_flushed);
    -		}
    -		XFS_STATS_INC(xs_trans_sync);
    -	} else {
    -		XFS_STATS_INC(xs_trans_async);
    -	}
    -
    -	return (error);
    -}
    -
    -
    -/*
    - * Total up the number of log iovecs needed to commit this
    - * transaction.  The transaction itself needs one for the
    - * transaction header.  Ask each dirty item in turn how many
    - * it needs to get the total.
    - */
    -STATIC uint
    -xfs_trans_count_vecs(
    -	xfs_trans_t	*tp)
    -{
    -	int			nvecs;
    -	xfs_log_item_desc_t	*lidp;
    -
    -	nvecs = 1;
    -	lidp = xfs_trans_first_item(tp);
    -	ASSERT(lidp != NULL);
    -
    -	/* In the non-debug case we need to start bailing out if we
    -	 * didn't find a log_item here, return zero and let trans_commit
    -	 * deal with it.
    -	 */
    -	if (lidp == NULL)
    -		return 0;
    -
    -	while (lidp != NULL) {
    -		/*
    -		 * Skip items which aren't dirty in this transaction.
    -		 */
    -		if (!(lidp->lid_flags & XFS_LID_DIRTY)) {
    -			lidp = xfs_trans_next_item(tp, lidp);
    -			continue;
    -		}
    -		lidp->lid_size = IOP_SIZE(lidp->lid_item);
    -		nvecs += lidp->lid_size;
    -		lidp = xfs_trans_next_item(tp, lidp);
    -	}
    -
    -	return nvecs;
    -}
    -
    -/*
    - * Called from the trans_commit code when we notice that
    - * the filesystem is in the middle of a forced shutdown.
    - */
    -STATIC void
    -xfs_trans_uncommit(
    -	xfs_trans_t	*tp,
    -	uint		flags)
    -{
    -	xfs_log_item_desc_t	*lidp;
    -
    -	for (lidp = xfs_trans_first_item(tp);
    -	     lidp != NULL;
    -	     lidp = xfs_trans_next_item(tp, lidp)) {
    -		/*
    -		 * Unpin all but those that aren't dirty.
    -		 */
    -		if (lidp->lid_flags & XFS_LID_DIRTY)
    -			IOP_UNPIN_REMOVE(lidp->lid_item, tp);
    -	}
    -
    -	xfs_trans_unreserve_and_mod_sb(tp);
    -	XFS_TRANS_UNRESERVE_AND_MOD_DQUOTS(tp->t_mountp, tp);
    -
    -	xfs_trans_free_items(tp, flags);
    -	xfs_trans_free_busy(tp);
    -	xfs_trans_free(tp);
    -}
    -
    -/*
    - * Fill in the vector with pointers to data to be logged
    - * by this transaction.  The transaction header takes
    - * the first vector, and then each dirty item takes the
    - * number of vectors it indicated it needed in xfs_trans_count_vecs().
    - *
    - * As each item fills in the entries it needs, also pin the item
    - * so that it cannot be flushed out until the log write completes.
    - */
    -STATIC void
    -xfs_trans_fill_vecs(
    -	xfs_trans_t		*tp,
    -	xfs_log_iovec_t		*log_vector)
    -{
    -	xfs_log_item_desc_t	*lidp;
    -	xfs_log_iovec_t		*vecp;
    -	uint			nitems;
    -
    -	/*
    -	 * Skip over the entry for the transaction header, we'll
    -	 * fill that in at the end.
    -	 */
    -	vecp = log_vector + 1;		/* pointer arithmetic */
    -
    -	nitems = 0;
    -	lidp = xfs_trans_first_item(tp);
    -	ASSERT(lidp != NULL);
    -	while (lidp != NULL) {
    -		/*
    -		 * Skip items which aren't dirty in this transaction.
    -		 */
    -		if (!(lidp->lid_flags & XFS_LID_DIRTY)) {
    -			lidp = xfs_trans_next_item(tp, lidp);
    -			continue;
    -		}
    -		/*
    -		 * The item may be marked dirty but not log anything.
    -		 * This can be used to get called when a transaction
    -		 * is committed.
    -		 */
    -		if (lidp->lid_size) {
    -			nitems++;
    -		}
    -		IOP_FORMAT(lidp->lid_item, vecp);
    -		vecp += lidp->lid_size;		/* pointer arithmetic */
    -		IOP_PIN(lidp->lid_item);
    -		lidp = xfs_trans_next_item(tp, lidp);
    -	}
    -
    -	/*
    -	 * Now that we've counted the number of items in this
    -	 * transaction, fill in the transaction header.
    -	 */
    -	tp->t_header.th_magic = XFS_TRANS_HEADER_MAGIC;
    -	tp->t_header.th_type = tp->t_type;
    -	tp->t_header.th_num_items = nitems;
    -	log_vector->i_addr = (xfs_caddr_t)&tp->t_header;
    -	log_vector->i_len = sizeof(xfs_trans_header_t);
    -	XLOG_VEC_SET_TYPE(log_vector, XLOG_REG_TYPE_TRANSHDR);
    -}
    -
    -
    -/*
    - * Unlock all of the transaction's items and free the transaction.
    - * The transaction must not have modified any of its items, because
    - * there is no way to restore them to their previous state.
    - *
    - * If the transaction has made a log reservation, make sure to release
    - * it as well.
    - */
    -void
    -xfs_trans_cancel(
    -	xfs_trans_t		*tp,
    -	int			flags)
    -{
    -	int			log_flags;
    -#ifdef DEBUG
    -	xfs_log_item_chunk_t	*licp;
    -	xfs_log_item_desc_t	*lidp;
    -	xfs_log_item_t		*lip;
    -	int			i;
    -#endif
    -	xfs_mount_t		*mp = tp->t_mountp;
    -
    -	/*
    -	 * See if the caller is being too lazy to figure out if
    -	 * the transaction really needs an abort.
    -	 */
    -	if ((flags & XFS_TRANS_ABORT) && !(tp->t_flags & XFS_TRANS_DIRTY))
    -		flags &= ~XFS_TRANS_ABORT;
    -	/*
    -	 * See if the caller is relying on us to shut down the
    -	 * filesystem.  This happens in paths where we detect
    -	 * corruption and decide to give up.
    -	 */
    -	if ((tp->t_flags & XFS_TRANS_DIRTY) && !XFS_FORCED_SHUTDOWN(mp)) {
    -		XFS_ERROR_REPORT("xfs_trans_cancel", XFS_ERRLEVEL_LOW, mp);
    -		xfs_force_shutdown(mp, XFS_CORRUPT_INCORE);
    -	}
    -#ifdef DEBUG
    -	if (!(flags & XFS_TRANS_ABORT)) {
    -		licp = &(tp->t_items);
    -		while (licp != NULL) {
    -			lidp = licp->lic_descs;
    -			for (i = 0; i < licp->lic_unused; i++, lidp++) {
    -				if (XFS_LIC_ISFREE(licp, i)) {
    -					continue;
    -				}
    -
    -				lip = lidp->lid_item;
    -				if (!XFS_FORCED_SHUTDOWN(mp))
    -					ASSERT(!(lip->li_type == XFS_LI_EFD));
    -			}
    -			licp = licp->lic_next;
    -		}
    -	}
    -#endif
    -	xfs_trans_unreserve_and_mod_sb(tp);
    -	XFS_TRANS_UNRESERVE_AND_MOD_DQUOTS(mp, tp);
    -
    -	if (tp->t_ticket) {
    -		if (flags & XFS_TRANS_RELEASE_LOG_RES) {
    -			ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);
    -			log_flags = XFS_LOG_REL_PERM_RESERV;
    -		} else {
    -			log_flags = 0;
    -		}
    -		xfs_log_done(mp, tp->t_ticket, NULL, log_flags);
    -	}
    -
    -	/* mark this thread as no longer being in a transaction */
    -        PFLAGS_RESTORE_FSTRANS(&tp->t_pflags);
    -
    -	xfs_trans_free_items(tp, flags);
    -	xfs_trans_free_busy(tp);
    -	xfs_trans_free(tp);
    -}
    -
    -
    -/*
    - * Free the transaction structure.  If there is more clean up
    - * to do when the structure is freed, add it here.
    - */
    -STATIC void
    -xfs_trans_free(
    -	xfs_trans_t	*tp)
    -{
    -	atomic_dec(&tp->t_mountp->m_active_trans);
    -	XFS_TRANS_FREE_DQINFO(tp->t_mountp, tp);
    -	kmem_zone_free(xfs_trans_zone, tp);
    -}
    -
    -
    -/*
    - * THIS SHOULD BE REWRITTEN TO USE xfs_trans_next_item().
    - *
    - * This is typically called by the LM when a transaction has been fully
    - * committed to disk.  It needs to unpin the items which have
    - * been logged by the transaction and update their positions
    - * in the AIL if necessary.
    - * This also gets called when the transactions didn't get written out
    - * because of an I/O error. Abortflag & XFS_LI_ABORTED is set then.
    - *
    - * Call xfs_trans_chunk_committed() to process the items in
    - * each chunk.
    - */
    -STATIC void
    -xfs_trans_committed(
    -	xfs_trans_t	*tp,
    -	int		abortflag)
    -{
    -	xfs_log_item_chunk_t	*licp;
    -	xfs_log_item_chunk_t	*next_licp;
    -	xfs_log_busy_chunk_t	*lbcp;
    -	xfs_log_busy_slot_t	*lbsp;
    -	int			i;
    -
    -	/*
    -	 * Call the transaction's completion callback if there
    -	 * is one.
    -	 */
    -	if (tp->t_callback != NULL) {
    -		tp->t_callback(tp, tp->t_callarg);
    -	}
    -
    -	/*
    -	 * Special case the chunk embedded in the transaction.
    -	 */
    -	licp = &(tp->t_items);
    -	if (!(XFS_LIC_ARE_ALL_FREE(licp))) {
    -		xfs_trans_chunk_committed(licp, tp->t_lsn, abortflag);
    -	}
    -
    -	/*
    -	 * Process the items in each chunk in turn.
    -	 */
    -	licp = licp->lic_next;
    -	while (licp != NULL) {
    -		ASSERT(!XFS_LIC_ARE_ALL_FREE(licp));
    -		xfs_trans_chunk_committed(licp, tp->t_lsn, abortflag);
    -		next_licp = licp->lic_next;
    -		kmem_free(licp, sizeof(xfs_log_item_chunk_t));
    -		licp = next_licp;
    -	}
    -
    -	/*
    -	 * Clear all the per-AG busy list items listed in this transaction
    -	 */
    -	lbcp = &tp->t_busy;
    -	while (lbcp != NULL) {
    -		for (i = 0, lbsp = lbcp->lbc_busy; i < lbcp->lbc_unused; i++, lbsp++) {
    -			if (!XFS_LBC_ISFREE(lbcp, i)) {
    -				xfs_alloc_clear_busy(tp, lbsp->lbc_ag,
    -						     lbsp->lbc_idx);
    -			}
    -		}
    -		lbcp = lbcp->lbc_next;
    -	}
    -	xfs_trans_free_busy(tp);
    -
    -	/*
    -	 * That's it for the transaction structure.  Free it.
    -	 */
    -	xfs_trans_free(tp);
    -}
    -
    -/*
    - * This is called to perform the commit processing for each
    - * item described by the given chunk.
    - *
    - * The commit processing consists of unlocking items which were
    - * held locked with the SYNC_UNLOCK attribute, calling the committed
    - * routine of each logged item, updating the item's position in the AIL
    - * if necessary, and unpinning each item.  If the committed routine
    - * returns -1, then do nothing further with the item because it
    - * may have been freed.
    - *
    - * Since items are unlocked when they are copied to the incore
    - * log, it is possible for two transactions to be completing
    - * and manipulating the same item simultaneously.  The AIL lock
    - * will protect the lsn field of each item.  The value of this
    - * field can never go backwards.
    - *
    - * We unpin the items after repositioning them in the AIL, because
    - * otherwise they could be immediately flushed and we'd have to race
    - * with the flusher trying to pull the item from the AIL as we add it.
    - */
    -STATIC void
    -xfs_trans_chunk_committed(
    -	xfs_log_item_chunk_t	*licp,
    -	xfs_lsn_t		lsn,
    -	int			aborted)
    -{
    -	xfs_log_item_desc_t	*lidp;
    -	xfs_log_item_t		*lip;
    -	xfs_lsn_t		item_lsn;
    -	struct xfs_mount	*mp;
    -	int			i;
    -	SPLDECL(s);
    -
    -	lidp = licp->lic_descs;
    -	for (i = 0; i < licp->lic_unused; i++, lidp++) {
    -		if (XFS_LIC_ISFREE(licp, i)) {
    -			continue;
    -		}
    -
    -		lip = lidp->lid_item;
    -		if (aborted)
    -			lip->li_flags |= XFS_LI_ABORTED;
    -
    -		/*
    -		 * Send in the ABORTED flag to the COMMITTED routine
    -		 * so that it knows whether the transaction was aborted
    -		 * or not.
    -		 */
    -		item_lsn = IOP_COMMITTED(lip, lsn);
    -
    -		/*
    -		 * If the committed routine returns -1, make
    -		 * no more references to the item.
    -		 */
    -		if (XFS_LSN_CMP(item_lsn, (xfs_lsn_t)-1) == 0) {
    -			continue;
    -		}
    -
    -		/*
    -		 * If the returned lsn is greater than what it
    -		 * contained before, update the location of the
    -		 * item in the AIL.  If it is not, then do nothing.
    -		 * Items can never move backwards in the AIL.
    -		 *
    -		 * While the new lsn should usually be greater, it
    -		 * is possible that a later transaction completing
    -		 * simultaneously with an earlier one using the
    -		 * same item could complete first with a higher lsn.
    -		 * This would cause the earlier transaction to fail
    -		 * the test below.
    -		 */
    -		mp = lip->li_mountp;
    -		AIL_LOCK(mp,s);
    -		if (XFS_LSN_CMP(item_lsn, lip->li_lsn) > 0) {
    -			/*
    -			 * This will set the item's lsn to item_lsn
    -			 * and update the position of the item in
    -			 * the AIL.
    -			 *
    -			 * xfs_trans_update_ail() drops the AIL lock.
    -			 */
    -			xfs_trans_update_ail(mp, lip, item_lsn, s);
    -		} else {
    -			AIL_UNLOCK(mp, s);
    -		}
    -
    -		/*
    -		 * Now that we've repositioned the item in the AIL,
    -		 * unpin it so it can be flushed. Pass information
    -		 * about buffer stale state down from the log item
    -		 * flags, if anyone else stales the buffer we do not
    -		 * want to pay any attention to it.
    -		 */
    -		IOP_UNPIN(lip, lidp->lid_flags & XFS_LID_BUF_STALE);
    -	}
    -}
    -
    diff --git a/sys/gnu/fs/xfs/xfs_trans.h b/sys/gnu/fs/xfs/xfs_trans.h
    deleted file mode 100644
    index 100d9a4b38e..00000000000
    --- a/sys/gnu/fs/xfs/xfs_trans.h
    +++ /dev/null
    @@ -1,1016 +0,0 @@
    -/*
    - * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef	__XFS_TRANS_H__
    -#define	__XFS_TRANS_H__
    -
    -/*
    - * This is the structure written in the log at the head of
    - * every transaction. It identifies the type and id of the
    - * transaction, and contains the number of items logged by
    - * the transaction so we know how many to expect during recovery.
    - *
    - * Do not change the below structure without redoing the code in
    - * xlog_recover_add_to_trans() and xlog_recover_add_to_cont_trans().
    - */
    -typedef struct xfs_trans_header {
    -	uint		th_magic;		/* magic number */
    -	uint		th_type;		/* transaction type */
    -	__int32_t	th_tid;			/* transaction id (unused) */
    -	uint		th_num_items;		/* num items logged by trans */
    -} xfs_trans_header_t;
    -
    -#define	XFS_TRANS_HEADER_MAGIC	0x5452414e	/* TRAN */
    -
    -/*
    - * Log item types.
    - */
    -#define	XFS_LI_5_3_BUF		0x1234	/* v1 bufs, 1-block inode buffers */
    -#define	XFS_LI_5_3_INODE	0x1235	/* 1-block inode buffers */
    -#define	XFS_LI_EFI		0x1236
    -#define	XFS_LI_EFD		0x1237
    -#define	XFS_LI_IUNLINK		0x1238
    -#define	XFS_LI_6_1_INODE	0x1239	/* 4K non-aligned inode bufs */
    -#define	XFS_LI_6_1_BUF		0x123a	/* v1, 4K inode buffers */
    -#define	XFS_LI_INODE		0x123b	/* aligned ino chunks, var-size ibufs */
    -#define	XFS_LI_BUF		0x123c	/* v2 bufs, variable sized inode bufs */
    -#define	XFS_LI_DQUOT		0x123d
    -#define	XFS_LI_QUOTAOFF		0x123e
    -
    -/*
    - * Transaction types.  Used to distinguish types of buffers.
    - */
    -#define XFS_TRANS_SETATTR_NOT_SIZE	1
    -#define XFS_TRANS_SETATTR_SIZE		2
    -#define XFS_TRANS_INACTIVE		3
    -#define XFS_TRANS_CREATE		4
    -#define XFS_TRANS_CREATE_TRUNC		5
    -#define XFS_TRANS_TRUNCATE_FILE		6
    -#define XFS_TRANS_REMOVE		7
    -#define XFS_TRANS_LINK			8
    -#define XFS_TRANS_RENAME		9
    -#define XFS_TRANS_MKDIR			10
    -#define XFS_TRANS_RMDIR			11
    -#define XFS_TRANS_SYMLINK		12
    -#define XFS_TRANS_SET_DMATTRS		13
    -#define XFS_TRANS_GROWFS		14
    -#define XFS_TRANS_STRAT_WRITE		15
    -#define XFS_TRANS_DIOSTRAT		16
    -#define	XFS_TRANS_WRITE_SYNC		17
    -#define	XFS_TRANS_WRITEID		18
    -#define	XFS_TRANS_ADDAFORK		19
    -#define	XFS_TRANS_ATTRINVAL		20
    -#define	XFS_TRANS_ATRUNCATE		21
    -#define	XFS_TRANS_ATTR_SET		22
    -#define	XFS_TRANS_ATTR_RM		23
    -#define	XFS_TRANS_ATTR_FLAG		24
    -#define	XFS_TRANS_CLEAR_AGI_BUCKET	25
    -#define XFS_TRANS_QM_SBCHANGE		26
    -/*
    - * Dummy entries since we use the transaction type to index into the
    - * trans_type[] in xlog_recover_print_trans_head()
    - */
    -#define XFS_TRANS_DUMMY1		27
    -#define XFS_TRANS_DUMMY2		28
    -#define XFS_TRANS_QM_QUOTAOFF		29
    -#define XFS_TRANS_QM_DQALLOC		30
    -#define XFS_TRANS_QM_SETQLIM		31
    -#define XFS_TRANS_QM_DQCLUSTER		32
    -#define XFS_TRANS_QM_QINOCREATE		33
    -#define XFS_TRANS_QM_QUOTAOFF_END	34
    -#define XFS_TRANS_SB_UNIT		35
    -#define XFS_TRANS_FSYNC_TS		36
    -#define	XFS_TRANS_GROWFSRT_ALLOC	37
    -#define	XFS_TRANS_GROWFSRT_ZERO		38
    -#define	XFS_TRANS_GROWFSRT_FREE		39
    -#define	XFS_TRANS_SWAPEXT		40
    -#define	XFS_TRANS_TYPE_MAX		40
    -/* new transaction types need to be reflected in xfs_logprint(8) */
    -
    -
    -#ifdef __KERNEL__
    -struct xfs_buf;
    -struct xfs_buftarg;
    -struct xfs_efd_log_item;
    -struct xfs_efi_log_item;
    -struct xfs_inode;
    -struct xfs_item_ops;
    -struct xfs_log_iovec;
    -struct xfs_log_item;
    -struct xfs_log_item_desc;
    -struct xfs_mount;
    -struct xfs_trans;
    -struct xfs_dquot_acct;
    -
    -typedef struct xfs_ail_entry {
    -	struct xfs_log_item	*ail_forw;	/* AIL forw pointer */
    -	struct xfs_log_item	*ail_back;	/* AIL back pointer */
    -} xfs_ail_entry_t;
    -
    -typedef struct xfs_log_item {
    -	xfs_ail_entry_t			li_ail;		/* AIL pointers */
    -	xfs_lsn_t			li_lsn;		/* last on-disk lsn */
    -	struct xfs_log_item_desc	*li_desc;	/* ptr to current desc*/
    -	struct xfs_mount		*li_mountp;	/* ptr to fs mount */
    -	uint				li_type;	/* item type */
    -	uint				li_flags;	/* misc flags */
    -	struct xfs_log_item		*li_bio_list;	/* buffer item list */
    -	void				(*li_cb)(struct xfs_buf *,
    -						 struct xfs_log_item *);
    -							/* buffer item iodone */
    -							/* callback func */
    -	struct xfs_item_ops		*li_ops;	/* function list */
    -} xfs_log_item_t;
    -
    -#define	XFS_LI_IN_AIL	0x1
    -#define XFS_LI_ABORTED	0x2
    -
    -typedef struct xfs_item_ops {
    -	uint (*iop_size)(xfs_log_item_t *);
    -	void (*iop_format)(xfs_log_item_t *, struct xfs_log_iovec *);
    -	void (*iop_pin)(xfs_log_item_t *);
    -	void (*iop_unpin)(xfs_log_item_t *, int);
    -	void (*iop_unpin_remove)(xfs_log_item_t *, struct xfs_trans *);
    -	uint (*iop_trylock)(xfs_log_item_t *);
    -	void (*iop_unlock)(xfs_log_item_t *);
    -	xfs_lsn_t (*iop_committed)(xfs_log_item_t *, xfs_lsn_t);
    -	void (*iop_push)(xfs_log_item_t *);
    -	void (*iop_abort)(xfs_log_item_t *);
    -	void (*iop_pushbuf)(xfs_log_item_t *);
    -	void (*iop_committing)(xfs_log_item_t *, xfs_lsn_t);
    -} xfs_item_ops_t;
    -
    -#define IOP_SIZE(ip)		(*(ip)->li_ops->iop_size)(ip)
    -#define IOP_FORMAT(ip,vp)	(*(ip)->li_ops->iop_format)(ip, vp)
    -#define IOP_PIN(ip)		(*(ip)->li_ops->iop_pin)(ip)
    -#define IOP_UNPIN(ip, flags)	(*(ip)->li_ops->iop_unpin)(ip, flags)
    -#define IOP_UNPIN_REMOVE(ip,tp) (*(ip)->li_ops->iop_unpin_remove)(ip, tp)
    -#define IOP_TRYLOCK(ip)		(*(ip)->li_ops->iop_trylock)(ip)
    -#define IOP_UNLOCK(ip)		(*(ip)->li_ops->iop_unlock)(ip)
    -#define IOP_COMMITTED(ip, lsn)	(*(ip)->li_ops->iop_committed)(ip, lsn)
    -#define IOP_PUSH(ip)		(*(ip)->li_ops->iop_push)(ip)
    -#define IOP_ABORT(ip)		(*(ip)->li_ops->iop_abort)(ip)
    -#define IOP_PUSHBUF(ip)		(*(ip)->li_ops->iop_pushbuf)(ip)
    -#define IOP_COMMITTING(ip, lsn) (*(ip)->li_ops->iop_committing)(ip, lsn)
    -
    -/*
    - * Return values for the IOP_TRYLOCK() routines.
    - */
    -#define	XFS_ITEM_SUCCESS	0
    -#define	XFS_ITEM_PINNED		1
    -#define	XFS_ITEM_LOCKED		2
    -#define	XFS_ITEM_FLUSHING	3
    -#define XFS_ITEM_PUSHBUF	4
    -
    -#endif	/* __KERNEL__ */
    -
    -/*
    - * This structure is used to track log items associated with
    - * a transaction.  It points to the log item and keeps some
    - * flags to track the state of the log item.  It also tracks
    - * the amount of space needed to log the item it describes
    - * once we get to commit processing (see xfs_trans_commit()).
    - */
    -typedef struct xfs_log_item_desc {
    -	xfs_log_item_t	*lid_item;
    -	ushort		lid_size;
    -	unsigned char	lid_flags;
    -	unsigned char	lid_index;
    -} xfs_log_item_desc_t;
    -
    -#define XFS_LID_DIRTY		0x1
    -#define XFS_LID_PINNED		0x2
    -#define XFS_LID_BUF_STALE	0x8
    -
    -/*
    - * This structure is used to maintain a chunk list of log_item_desc
    - * structures. The free field is a bitmask indicating which descriptors
    - * in this chunk's array are free.  The unused field is the first value
    - * not used since this chunk was allocated.
    - */
    -#define	XFS_LIC_NUM_SLOTS	15
    -typedef struct xfs_log_item_chunk {
    -	struct xfs_log_item_chunk	*lic_next;
    -	ushort				lic_free;
    -	ushort				lic_unused;
    -	xfs_log_item_desc_t		lic_descs[XFS_LIC_NUM_SLOTS];
    -} xfs_log_item_chunk_t;
    -
    -#define	XFS_LIC_MAX_SLOT	(XFS_LIC_NUM_SLOTS - 1)
    -#define	XFS_LIC_FREEMASK	((1 << XFS_LIC_NUM_SLOTS) - 1)
    -
    -
    -/*
    - * Initialize the given chunk.  Set the chunk's free descriptor mask
    - * to indicate that all descriptors are free.  The caller gets to set
    - * lic_unused to the right value (0 matches all free).  The
    - * lic_descs.lid_index values are set up as each desc is allocated.
    - */
    -#define	XFS_LIC_INIT(cp)	xfs_lic_init(cp)
    -static inline void xfs_lic_init(xfs_log_item_chunk_t *cp)
    -{
    -	cp->lic_free = XFS_LIC_FREEMASK;
    -}
    -
    -#define	XFS_LIC_INIT_SLOT(cp,slot)	xfs_lic_init_slot(cp, slot)
    -static inline void xfs_lic_init_slot(xfs_log_item_chunk_t *cp, int slot)
    -{
    -	cp->lic_descs[slot].lid_index = (unsigned char)(slot);
    -}
    -
    -#define	XFS_LIC_VACANCY(cp)		xfs_lic_vacancy(cp)
    -static inline int xfs_lic_vacancy(xfs_log_item_chunk_t *cp)
    -{
    -	return cp->lic_free & XFS_LIC_FREEMASK;
    -}
    -
    -#define	XFS_LIC_ALL_FREE(cp)		xfs_lic_all_free(cp)
    -static inline void xfs_lic_all_free(xfs_log_item_chunk_t *cp)
    -{
    -	cp->lic_free = XFS_LIC_FREEMASK;
    -}
    -
    -#define	XFS_LIC_ARE_ALL_FREE(cp)	xfs_lic_are_all_free(cp)
    -static inline int xfs_lic_are_all_free(xfs_log_item_chunk_t *cp)
    -{
    -	return ((cp->lic_free & XFS_LIC_FREEMASK) == XFS_LIC_FREEMASK);
    -}
    -
    -#define	XFS_LIC_ISFREE(cp,slot)	xfs_lic_isfree(cp,slot)
    -static inline int xfs_lic_isfree(xfs_log_item_chunk_t *cp, int slot)
    -{
    -	return (cp->lic_free & (1 << slot));
    -}
    -
    -#define	XFS_LIC_CLAIM(cp,slot)		xfs_lic_claim(cp,slot)
    -static inline void xfs_lic_claim(xfs_log_item_chunk_t *cp, int slot)
    -{
    -	cp->lic_free &= ~(1 << slot);
    -}
    -
    -#define	XFS_LIC_RELSE(cp,slot)		xfs_lic_relse(cp,slot)
    -static inline void xfs_lic_relse(xfs_log_item_chunk_t *cp, int slot)
    -{
    -	cp->lic_free |= 1 << slot;
    -}
    -
    -#define	XFS_LIC_SLOT(cp,slot)		xfs_lic_slot(cp,slot)
    -static inline xfs_log_item_desc_t *
    -xfs_lic_slot(xfs_log_item_chunk_t *cp, int slot)
    -{
    -	return &(cp->lic_descs[slot]);
    -}
    -
    -#define	XFS_LIC_DESC_TO_SLOT(dp)	xfs_lic_desc_to_slot(dp)
    -static inline int xfs_lic_desc_to_slot(xfs_log_item_desc_t *dp)
    -{
    -	return (uint)dp->lid_index;
    -}
    -
    -/*
    - * Calculate the address of a chunk given a descriptor pointer:
    - * dp - dp->lid_index give the address of the start of the lic_descs array.
    - * From this we subtract the offset of the lic_descs field in a chunk.
    - * All of this yields the address of the chunk, which is
    - * cast to a chunk pointer.
    - */
    -#define	XFS_LIC_DESC_TO_CHUNK(dp)	xfs_lic_desc_to_chunk(dp)
    -static inline xfs_log_item_chunk_t *
    -xfs_lic_desc_to_chunk(xfs_log_item_desc_t *dp)
    -{
    -	return (xfs_log_item_chunk_t*) \
    -		(((xfs_caddr_t)((dp) - (dp)->lid_index)) - \
    -		(xfs_caddr_t)(((xfs_log_item_chunk_t*)0)->lic_descs));
    -}
    -
    -#ifdef __KERNEL__
    -/*
    - * This structure is used to maintain a list of block ranges that have been
    - * freed in the transaction.  The ranges are listed in the perag[] busy list
    - * between when they're freed and the transaction is committed to disk.
    - */
    -
    -typedef struct xfs_log_busy_slot {
    -	xfs_agnumber_t		lbc_ag;
    -	ushort			lbc_idx;	/* index in perag.busy[] */
    -} xfs_log_busy_slot_t;
    -
    -#define XFS_LBC_NUM_SLOTS	31
    -typedef struct xfs_log_busy_chunk {
    -	struct xfs_log_busy_chunk	*lbc_next;
    -	uint				lbc_free;	/* free slots bitmask */
    -	ushort				lbc_unused;	/* first unused */
    -	xfs_log_busy_slot_t		lbc_busy[XFS_LBC_NUM_SLOTS];
    -} xfs_log_busy_chunk_t;
    -
    -#define	XFS_LBC_MAX_SLOT	(XFS_LBC_NUM_SLOTS - 1)
    -#define	XFS_LBC_FREEMASK	((1U << XFS_LBC_NUM_SLOTS) - 1)
    -
    -#define	XFS_LBC_INIT(cp)	((cp)->lbc_free = XFS_LBC_FREEMASK)
    -#define	XFS_LBC_CLAIM(cp, slot)	((cp)->lbc_free &= ~(1 << (slot)))
    -#define	XFS_LBC_SLOT(cp, slot)	(&((cp)->lbc_busy[(slot)]))
    -#define	XFS_LBC_VACANCY(cp)	(((cp)->lbc_free) & XFS_LBC_FREEMASK)
    -#define	XFS_LBC_ISFREE(cp, slot) ((cp)->lbc_free & (1 << (slot)))
    -
    -/*
    - * This is the type of function which can be given to xfs_trans_callback()
    - * to be called upon the transaction's commit to disk.
    - */
    -typedef void (*xfs_trans_callback_t)(struct xfs_trans *, void *);
    -
    -/*
    - * This is the structure maintained for every active transaction.
    - */
    -typedef struct xfs_trans {
    -	unsigned int		t_magic;	/* magic number */
    -	xfs_log_callback_t	t_logcb;	/* log callback struct */
    -	struct xfs_trans	*t_forw;	/* async list pointers */
    -	struct xfs_trans	*t_back;	/* async list pointers */
    -	unsigned int		t_type;		/* transaction type */
    -	unsigned int		t_log_res;	/* amt of log space resvd */
    -	unsigned int		t_log_count;	/* count for perm log res */
    -	unsigned int		t_blk_res;	/* # of blocks resvd */
    -	unsigned int		t_blk_res_used;	/* # of resvd blocks used */
    -	unsigned int		t_rtx_res;	/* # of rt extents resvd */
    -	unsigned int		t_rtx_res_used;	/* # of resvd rt extents used */
    -	xfs_log_ticket_t	t_ticket;	/* log mgr ticket */
    -	sema_t			t_sema;		/* sema for commit completion */
    -	xfs_lsn_t		t_lsn;		/* log seq num of start of
    -						 * transaction. */
    -	xfs_lsn_t		t_commit_lsn;	/* log seq num of end of
    -						 * transaction. */
    -	struct xfs_mount	*t_mountp;	/* ptr to fs mount struct */
    -	struct xfs_dquot_acct   *t_dqinfo;	/* acctg info for dquots */
    -	xfs_trans_callback_t	t_callback;	/* transaction callback */
    -	void			*t_callarg;	/* callback arg */
    -	unsigned int		t_flags;	/* misc flags */
    -	long			t_icount_delta;	/* superblock icount change */
    -	long			t_ifree_delta;	/* superblock ifree change */
    -	long			t_fdblocks_delta; /* superblock fdblocks chg */
    -	long			t_res_fdblocks_delta; /* on-disk only chg */
    -	long			t_frextents_delta;/* superblock freextents chg*/
    -	long			t_res_frextents_delta; /* on-disk only chg */
    -	long			t_ag_freeblks_delta; /* debugging counter */
    -	long			t_ag_flist_delta; /* debugging counter */
    -	long			t_ag_btree_delta; /* debugging counter */
    -	long			t_dblocks_delta;/* superblock dblocks change */
    -	long			t_agcount_delta;/* superblock agcount change */
    -	long			t_imaxpct_delta;/* superblock imaxpct change */
    -	long			t_rextsize_delta;/* superblock rextsize chg */
    -	long			t_rbmblocks_delta;/* superblock rbmblocks chg */
    -	long			t_rblocks_delta;/* superblock rblocks change */
    -	long			t_rextents_delta;/* superblocks rextents chg */
    -	long			t_rextslog_delta;/* superblocks rextslog chg */
    -	unsigned int		t_items_free;	/* log item descs free */
    -	xfs_log_item_chunk_t	t_items;	/* first log item desc chunk */
    -	xfs_trans_header_t	t_header;	/* header for in-log trans */
    -	unsigned int		t_busy_free;	/* busy descs free */
    -	xfs_log_busy_chunk_t	t_busy;		/* busy/async free blocks */
    -	unsigned long		t_pflags;	/* saved process flags state */
    -} xfs_trans_t;
    -
    -#endif	/* __KERNEL__ */
    -
    -
    -#define	XFS_TRANS_MAGIC		0x5452414E	/* 'TRAN' */
    -/*
    - * Values for t_flags.
    - */
    -#define	XFS_TRANS_DIRTY		0x01	/* something needs to be logged */
    -#define	XFS_TRANS_SB_DIRTY	0x02	/* superblock is modified */
    -#define	XFS_TRANS_PERM_LOG_RES	0x04	/* xact took a permanent log res */
    -#define	XFS_TRANS_SYNC		0x08	/* make commit synchronous */
    -#define XFS_TRANS_DQ_DIRTY	0x10	/* at least one dquot in trx dirty */
    -#define XFS_TRANS_RESERVE	0x20    /* OK to use reserved data blocks */
    -
    -/*
    - * Values for call flags parameter.
    - */
    -#define	XFS_TRANS_NOSLEEP		0x1
    -#define	XFS_TRANS_WAIT			0x2
    -#define	XFS_TRANS_RELEASE_LOG_RES	0x4
    -#define	XFS_TRANS_ABORT			0x8
    -
    -/*
    - * Field values for xfs_trans_mod_sb.
    - */
    -#define	XFS_TRANS_SB_ICOUNT		0x00000001
    -#define	XFS_TRANS_SB_IFREE		0x00000002
    -#define	XFS_TRANS_SB_FDBLOCKS		0x00000004
    -#define	XFS_TRANS_SB_RES_FDBLOCKS	0x00000008
    -#define	XFS_TRANS_SB_FREXTENTS		0x00000010
    -#define	XFS_TRANS_SB_RES_FREXTENTS	0x00000020
    -#define	XFS_TRANS_SB_DBLOCKS		0x00000040
    -#define	XFS_TRANS_SB_AGCOUNT		0x00000080
    -#define	XFS_TRANS_SB_IMAXPCT		0x00000100
    -#define	XFS_TRANS_SB_REXTSIZE		0x00000200
    -#define	XFS_TRANS_SB_RBMBLOCKS		0x00000400
    -#define	XFS_TRANS_SB_RBLOCKS		0x00000800
    -#define	XFS_TRANS_SB_REXTENTS		0x00001000
    -#define	XFS_TRANS_SB_REXTSLOG		0x00002000
    -
    -
    -/*
    - * Various log reservation values.
    - * These are based on the size of the file system block
    - * because that is what most transactions manipulate.
    - * Each adds in an additional 128 bytes per item logged to
    - * try to account for the overhead of the transaction mechanism.
    - *
    - * Note:
    - * Most of the reservations underestimate the number of allocation
    - * groups into which they could free extents in the xfs_bmap_finish()
    - * call.  This is because the number in the worst case is quite high
    - * and quite unusual.  In order to fix this we need to change
    - * xfs_bmap_finish() to free extents in only a single AG at a time.
    - * This will require changes to the EFI code as well, however, so that
    - * the EFI for the extents not freed is logged again in each transaction.
    - * See bug 261917.
    - */
    -
    -/*
    - * Per-extent log reservation for the allocation btree changes
    - * involved in freeing or allocating an extent.
    - * 2 trees * (2 blocks/level * max depth - 1) * block size
    - */
    -#define	XFS_ALLOCFREE_LOG_RES(mp,nx) \
    -	((nx) * (2 * XFS_FSB_TO_B((mp), 2 * XFS_AG_MAXLEVELS(mp) - 1)))
    -#define	XFS_ALLOCFREE_LOG_COUNT(mp,nx) \
    -	((nx) * (2 * (2 * XFS_AG_MAXLEVELS(mp) - 1)))
    -
    -/*
    - * Per-directory log reservation for any directory change.
    - * dir blocks: (1 btree block per level + data block + free block) * dblock size
    - * bmap btree: (levels + 2) * max depth * block size
    - * v2 directory blocks can be fragmented below the dirblksize down to the fsb
    - * size, so account for that in the DAENTER macros.
    - */
    -#define	XFS_DIROP_LOG_RES(mp)	\
    -	(XFS_FSB_TO_B(mp, XFS_DAENTER_BLOCKS(mp, XFS_DATA_FORK)) + \
    -	 (XFS_FSB_TO_B(mp, XFS_DAENTER_BMAPS(mp, XFS_DATA_FORK) + 1)))
    -#define	XFS_DIROP_LOG_COUNT(mp)	\
    -	(XFS_DAENTER_BLOCKS(mp, XFS_DATA_FORK) + \
    -	 XFS_DAENTER_BMAPS(mp, XFS_DATA_FORK) + 1)
    -
    -/*
    - * In a write transaction we can allocate a maximum of 2
    - * extents.  This gives:
    - *    the inode getting the new extents: inode size
    - *    the inode\'s bmap btree: max depth * block size
    - *    the agfs of the ags from which the extents are allocated: 2 * sector
    - *    the superblock free block counter: sector size
    - *    the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
    - * And the bmap_finish transaction can free bmap blocks in a join:
    - *    the agfs of the ags containing the blocks: 2 * sector size
    - *    the agfls of the ags containing the blocks: 2 * sector size
    - *    the super block free block counter: sector size
    - *    the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
    - */
    -#define XFS_CALC_WRITE_LOG_RES(mp) \
    -	(MAX( \
    -	 ((mp)->m_sb.sb_inodesize + \
    -	  XFS_FSB_TO_B((mp), XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK)) + \
    -	  (2 * (mp)->m_sb.sb_sectsize) + \
    -	  (mp)->m_sb.sb_sectsize + \
    -	  XFS_ALLOCFREE_LOG_RES(mp, 2) + \
    -	  (128 * (4 + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + XFS_ALLOCFREE_LOG_COUNT(mp, 2)))),\
    -	 ((2 * (mp)->m_sb.sb_sectsize) + \
    -	  (2 * (mp)->m_sb.sb_sectsize) + \
    -	  (mp)->m_sb.sb_sectsize + \
    -	  XFS_ALLOCFREE_LOG_RES(mp, 2) + \
    -	  (128 * (5 + XFS_ALLOCFREE_LOG_COUNT(mp, 2))))))
    -
    -#define	XFS_WRITE_LOG_RES(mp)	((mp)->m_reservations.tr_write)
    -
    -/*
    - * In truncating a file we free up to two extents at once.  We can modify:
    - *    the inode being truncated: inode size
    - *    the inode\'s bmap btree: (max depth + 1) * block size
    - * And the bmap_finish transaction can free the blocks and bmap blocks:
    - *    the agf for each of the ags: 4 * sector size
    - *    the agfl for each of the ags: 4 * sector size
    - *    the super block to reflect the freed blocks: sector size
    - *    worst case split in allocation btrees per extent assuming 4 extents:
    - *		4 exts * 2 trees * (2 * max depth - 1) * block size
    - *    the inode btree: max depth * blocksize
    - *    the allocation btrees: 2 trees * (max depth - 1) * block size
    - */
    -#define	XFS_CALC_ITRUNCATE_LOG_RES(mp) \
    -	(MAX( \
    -	 ((mp)->m_sb.sb_inodesize + \
    -	  XFS_FSB_TO_B((mp), XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + 1) + \
    -	  (128 * (2 + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK)))), \
    -	 ((4 * (mp)->m_sb.sb_sectsize) + \
    -	  (4 * (mp)->m_sb.sb_sectsize) + \
    -	  (mp)->m_sb.sb_sectsize + \
    -	  XFS_ALLOCFREE_LOG_RES(mp, 4) + \
    -	  (128 * (9 + XFS_ALLOCFREE_LOG_COUNT(mp, 4))) + \
    -	  (128 * 5) + \
    -	  XFS_ALLOCFREE_LOG_RES(mp, 1) + \
    -	   (128 * (2 + XFS_IALLOC_BLOCKS(mp) + XFS_IN_MAXLEVELS(mp) + \
    -	    XFS_ALLOCFREE_LOG_COUNT(mp, 1))))))
    -
    -#define	XFS_ITRUNCATE_LOG_RES(mp)   ((mp)->m_reservations.tr_itruncate)
    -
    -/*
    - * In renaming a files we can modify:
    - *    the four inodes involved: 4 * inode size
    - *    the two directory btrees: 2 * (max depth + v2) * dir block size
    - *    the two directory bmap btrees: 2 * max depth * block size
    - * And the bmap_finish transaction can free dir and bmap blocks (two sets
    - *	of bmap blocks) giving:
    - *    the agf for the ags in which the blocks live: 3 * sector size
    - *    the agfl for the ags in which the blocks live: 3 * sector size
    - *    the superblock for the free block count: sector size
    - *    the allocation btrees: 3 exts * 2 trees * (2 * max depth - 1) * block size
    - */
    -#define	XFS_CALC_RENAME_LOG_RES(mp) \
    -	(MAX( \
    -	 ((4 * (mp)->m_sb.sb_inodesize) + \
    -	  (2 * XFS_DIROP_LOG_RES(mp)) + \
    -	  (128 * (4 + 2 * XFS_DIROP_LOG_COUNT(mp)))), \
    -	 ((3 * (mp)->m_sb.sb_sectsize) + \
    -	  (3 * (mp)->m_sb.sb_sectsize) + \
    -	  (mp)->m_sb.sb_sectsize + \
    -	  XFS_ALLOCFREE_LOG_RES(mp, 3) + \
    -	  (128 * (7 + XFS_ALLOCFREE_LOG_COUNT(mp, 3))))))
    -
    -#define	XFS_RENAME_LOG_RES(mp)	((mp)->m_reservations.tr_rename)
    -
    -/*
    - * For creating a link to an inode:
    - *    the parent directory inode: inode size
    - *    the linked inode: inode size
    - *    the directory btree could split: (max depth + v2) * dir block size
    - *    the directory bmap btree could join or split: (max depth + v2) * blocksize
    - * And the bmap_finish transaction can free some bmap blocks giving:
    - *    the agf for the ag in which the blocks live: sector size
    - *    the agfl for the ag in which the blocks live: sector size
    - *    the superblock for the free block count: sector size
    - *    the allocation btrees: 2 trees * (2 * max depth - 1) * block size
    - */
    -#define	XFS_CALC_LINK_LOG_RES(mp) \
    -	(MAX( \
    -	 ((mp)->m_sb.sb_inodesize + \
    -	  (mp)->m_sb.sb_inodesize + \
    -	  XFS_DIROP_LOG_RES(mp) + \
    -	  (128 * (2 + XFS_DIROP_LOG_COUNT(mp)))), \
    -	 ((mp)->m_sb.sb_sectsize + \
    -	  (mp)->m_sb.sb_sectsize + \
    -	  (mp)->m_sb.sb_sectsize + \
    -	  XFS_ALLOCFREE_LOG_RES(mp, 1) + \
    -	  (128 * (3 + XFS_ALLOCFREE_LOG_COUNT(mp, 1))))))
    -
    -#define	XFS_LINK_LOG_RES(mp)	((mp)->m_reservations.tr_link)
    -
    -/*
    - * For removing a directory entry we can modify:
    - *    the parent directory inode: inode size
    - *    the removed inode: inode size
    - *    the directory btree could join: (max depth + v2) * dir block size
    - *    the directory bmap btree could join or split: (max depth + v2) * blocksize
    - * And the bmap_finish transaction can free the dir and bmap blocks giving:
    - *    the agf for the ag in which the blocks live: 2 * sector size
    - *    the agfl for the ag in which the blocks live: 2 * sector size
    - *    the superblock for the free block count: sector size
    - *    the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
    - */
    -#define	XFS_CALC_REMOVE_LOG_RES(mp)	\
    -	(MAX( \
    -	 ((mp)->m_sb.sb_inodesize + \
    -	  (mp)->m_sb.sb_inodesize + \
    -	  XFS_DIROP_LOG_RES(mp) + \
    -	  (128 * (2 + XFS_DIROP_LOG_COUNT(mp)))), \
    -	 ((2 * (mp)->m_sb.sb_sectsize) + \
    -	  (2 * (mp)->m_sb.sb_sectsize) + \
    -	  (mp)->m_sb.sb_sectsize + \
    -	  XFS_ALLOCFREE_LOG_RES(mp, 2) + \
    -	  (128 * (5 + XFS_ALLOCFREE_LOG_COUNT(mp, 2))))))
    -
    -#define	XFS_REMOVE_LOG_RES(mp)	((mp)->m_reservations.tr_remove)
    -
    -/*
    - * For symlink we can modify:
    - *    the parent directory inode: inode size
    - *    the new inode: inode size
    - *    the inode btree entry: 1 block
    - *    the directory btree: (max depth + v2) * dir block size
    - *    the directory inode\'s bmap btree: (max depth + v2) * block size
    - *    the blocks for the symlink: 1 KB
    - * Or in the first xact we allocate some inodes giving:
    - *    the agi and agf of the ag getting the new inodes: 2 * sectorsize
    - *    the inode blocks allocated: XFS_IALLOC_BLOCKS * blocksize
    - *    the inode btree: max depth * blocksize
    - *    the allocation btrees: 2 trees * (2 * max depth - 1) * block size
    - */
    -#define	XFS_CALC_SYMLINK_LOG_RES(mp)		\
    -	(MAX( \
    -	 ((mp)->m_sb.sb_inodesize + \
    -	  (mp)->m_sb.sb_inodesize + \
    -	  XFS_FSB_TO_B(mp, 1) + \
    -	  XFS_DIROP_LOG_RES(mp) + \
    -	  1024 + \
    -	  (128 * (4 + XFS_DIROP_LOG_COUNT(mp)))), \
    -	 (2 * (mp)->m_sb.sb_sectsize + \
    -	  XFS_FSB_TO_B((mp), XFS_IALLOC_BLOCKS((mp))) + \
    -	  XFS_FSB_TO_B((mp), XFS_IN_MAXLEVELS(mp)) + \
    -	  XFS_ALLOCFREE_LOG_RES(mp, 1) + \
    -	  (128 * (2 + XFS_IALLOC_BLOCKS(mp) + XFS_IN_MAXLEVELS(mp) + \
    -	   XFS_ALLOCFREE_LOG_COUNT(mp, 1))))))
    -
    -#define	XFS_SYMLINK_LOG_RES(mp)	((mp)->m_reservations.tr_symlink)
    -
    -/*
    - * For create we can modify:
    - *    the parent directory inode: inode size
    - *    the new inode: inode size
    - *    the inode btree entry: block size
    - *    the superblock for the nlink flag: sector size
    - *    the directory btree: (max depth + v2) * dir block size
    - *    the directory inode\'s bmap btree: (max depth + v2) * block size
    - * Or in the first xact we allocate some inodes giving:
    - *    the agi and agf of the ag getting the new inodes: 2 * sectorsize
    - *    the superblock for the nlink flag: sector size
    - *    the inode blocks allocated: XFS_IALLOC_BLOCKS * blocksize
    - *    the inode btree: max depth * blocksize
    - *    the allocation btrees: 2 trees * (max depth - 1) * block size
    - */
    -#define	XFS_CALC_CREATE_LOG_RES(mp)		\
    -	(MAX( \
    -	 ((mp)->m_sb.sb_inodesize + \
    -	  (mp)->m_sb.sb_inodesize + \
    -	  (mp)->m_sb.sb_sectsize + \
    -	  XFS_FSB_TO_B(mp, 1) + \
    -	  XFS_DIROP_LOG_RES(mp) + \
    -	  (128 * (3 + XFS_DIROP_LOG_COUNT(mp)))), \
    -	 (3 * (mp)->m_sb.sb_sectsize + \
    -	  XFS_FSB_TO_B((mp), XFS_IALLOC_BLOCKS((mp))) + \
    -	  XFS_FSB_TO_B((mp), XFS_IN_MAXLEVELS(mp)) + \
    -	  XFS_ALLOCFREE_LOG_RES(mp, 1) + \
    -	  (128 * (2 + XFS_IALLOC_BLOCKS(mp) + XFS_IN_MAXLEVELS(mp) + \
    -	   XFS_ALLOCFREE_LOG_COUNT(mp, 1))))))
    -
    -#define	XFS_CREATE_LOG_RES(mp)	((mp)->m_reservations.tr_create)
    -
    -/*
    - * Making a new directory is the same as creating a new file.
    - */
    -#define	XFS_CALC_MKDIR_LOG_RES(mp)	XFS_CALC_CREATE_LOG_RES(mp)
    -
    -#define	XFS_MKDIR_LOG_RES(mp)	((mp)->m_reservations.tr_mkdir)
    -
    -/*
    - * In freeing an inode we can modify:
    - *    the inode being freed: inode size
    - *    the super block free inode counter: sector size
    - *    the agi hash list and counters: sector size
    - *    the inode btree entry: block size
    - *    the on disk inode before ours in the agi hash list: inode cluster size
    - *    the inode btree: max depth * blocksize
    - *    the allocation btrees: 2 trees * (max depth - 1) * block size
    - */
    -#define	XFS_CALC_IFREE_LOG_RES(mp) \
    -	((mp)->m_sb.sb_inodesize + \
    -	 (mp)->m_sb.sb_sectsize + \
    -	 (mp)->m_sb.sb_sectsize + \
    -	 XFS_FSB_TO_B((mp), 1) + \
    -	 MAX((__uint16_t)XFS_FSB_TO_B((mp), 1), XFS_INODE_CLUSTER_SIZE(mp)) + \
    -	 (128 * 5) + \
    -	  XFS_ALLOCFREE_LOG_RES(mp, 1) + \
    -	  (128 * (2 + XFS_IALLOC_BLOCKS(mp) + XFS_IN_MAXLEVELS(mp) + \
    -	   XFS_ALLOCFREE_LOG_COUNT(mp, 1))))
    -
    -
    -#define	XFS_IFREE_LOG_RES(mp)	((mp)->m_reservations.tr_ifree)
    -
    -/*
    - * When only changing the inode we log the inode and possibly the superblock
    - * We also add a bit of slop for the transaction stuff.
    - */
    -#define	XFS_CALC_ICHANGE_LOG_RES(mp)	((mp)->m_sb.sb_inodesize + \
    -					 (mp)->m_sb.sb_sectsize + 512)
    -
    -#define	XFS_ICHANGE_LOG_RES(mp)	((mp)->m_reservations.tr_ichange)
    -
    -/*
    - * Growing the data section of the filesystem.
    - *	superblock
    - *	agi and agf
    - *	allocation btrees
    - */
    -#define	XFS_CALC_GROWDATA_LOG_RES(mp) \
    -	((mp)->m_sb.sb_sectsize * 3 + \
    -	 XFS_ALLOCFREE_LOG_RES(mp, 1) + \
    -	 (128 * (3 + XFS_ALLOCFREE_LOG_COUNT(mp, 1))))
    -
    -#define	XFS_GROWDATA_LOG_RES(mp)    ((mp)->m_reservations.tr_growdata)
    -
    -/*
    - * Growing the rt section of the filesystem.
    - * In the first set of transactions (ALLOC) we allocate space to the
    - * bitmap or summary files.
    - *	superblock: sector size
    - *	agf of the ag from which the extent is allocated: sector size
    - *	bmap btree for bitmap/summary inode: max depth * blocksize
    - *	bitmap/summary inode: inode size
    - *	allocation btrees for 1 block alloc: 2 * (2 * maxdepth - 1) * blocksize
    - */
    -#define	XFS_CALC_GROWRTALLOC_LOG_RES(mp) \
    -	(2 * (mp)->m_sb.sb_sectsize + \
    -	 XFS_FSB_TO_B((mp), XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK)) + \
    -	 (mp)->m_sb.sb_inodesize + \
    -	 XFS_ALLOCFREE_LOG_RES(mp, 1) + \
    -	 (128 * \
    -	  (3 + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + \
    -	   XFS_ALLOCFREE_LOG_COUNT(mp, 1))))
    -
    -#define	XFS_GROWRTALLOC_LOG_RES(mp)	((mp)->m_reservations.tr_growrtalloc)
    -
    -/*
    - * Growing the rt section of the filesystem.
    - * In the second set of transactions (ZERO) we zero the new metadata blocks.
    - *	one bitmap/summary block: blocksize
    - */
    -#define	XFS_CALC_GROWRTZERO_LOG_RES(mp) \
    -	((mp)->m_sb.sb_blocksize + 128)
    -
    -#define	XFS_GROWRTZERO_LOG_RES(mp)	((mp)->m_reservations.tr_growrtzero)
    -
    -/*
    - * Growing the rt section of the filesystem.
    - * In the third set of transactions (FREE) we update metadata without
    - * allocating any new blocks.
    - *	superblock: sector size
    - *	bitmap inode: inode size
    - *	summary inode: inode size
    - *	one bitmap block: blocksize
    - *	summary blocks: new summary size
    - */
    -#define	XFS_CALC_GROWRTFREE_LOG_RES(mp) \
    -	((mp)->m_sb.sb_sectsize + \
    -	 2 * (mp)->m_sb.sb_inodesize + \
    -	 (mp)->m_sb.sb_blocksize + \
    -	 (mp)->m_rsumsize + \
    -	 (128 * 5))
    -
    -#define	XFS_GROWRTFREE_LOG_RES(mp)	((mp)->m_reservations.tr_growrtfree)
    -
    -/*
    - * Logging the inode modification timestamp on a synchronous write.
    - *	inode
    - */
    -#define	XFS_CALC_SWRITE_LOG_RES(mp) \
    -	((mp)->m_sb.sb_inodesize + 128)
    -
    -#define	XFS_SWRITE_LOG_RES(mp)	((mp)->m_reservations.tr_swrite)
    -
    -/*
    - * Logging the inode timestamps on an fsync -- same as SWRITE
    - * as long as SWRITE logs the entire inode core
    - */
    -#define XFS_FSYNC_TS_LOG_RES(mp)        ((mp)->m_reservations.tr_swrite)
    -
    -/*
    - * Logging the inode mode bits when writing a setuid/setgid file
    - *	inode
    - */
    -#define	XFS_CALC_WRITEID_LOG_RES(mp) \
    -	((mp)->m_sb.sb_inodesize + 128)
    -
    -#define	XFS_WRITEID_LOG_RES(mp)	((mp)->m_reservations.tr_swrite)
    -
    -/*
    - * Converting the inode from non-attributed to attributed.
    - *	the inode being converted: inode size
    - *	agf block and superblock (for block allocation)
    - *	the new block (directory sized)
    - *	bmap blocks for the new directory block
    - *	allocation btrees
    - */
    -#define	XFS_CALC_ADDAFORK_LOG_RES(mp)	\
    -	((mp)->m_sb.sb_inodesize + \
    -	 (mp)->m_sb.sb_sectsize * 2 + \
    -	 (mp)->m_dirblksize + \
    -	 (XFS_DIR_IS_V1(mp) ? 0 : \
    -	    XFS_FSB_TO_B(mp, (XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1))) + \
    -	 XFS_ALLOCFREE_LOG_RES(mp, 1) + \
    -	 (128 * (4 + \
    -		 (XFS_DIR_IS_V1(mp) ? 0 : \
    -			 XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1) + \
    -		 XFS_ALLOCFREE_LOG_COUNT(mp, 1))))
    -
    -#define	XFS_ADDAFORK_LOG_RES(mp)	((mp)->m_reservations.tr_addafork)
    -
    -/*
    - * Removing the attribute fork of a file
    - *    the inode being truncated: inode size
    - *    the inode\'s bmap btree: max depth * block size
    - * And the bmap_finish transaction can free the blocks and bmap blocks:
    - *    the agf for each of the ags: 4 * sector size
    - *    the agfl for each of the ags: 4 * sector size
    - *    the super block to reflect the freed blocks: sector size
    - *    worst case split in allocation btrees per extent assuming 4 extents:
    - *		4 exts * 2 trees * (2 * max depth - 1) * block size
    - */
    -#define	XFS_CALC_ATTRINVAL_LOG_RES(mp)	\
    -	(MAX( \
    -	 ((mp)->m_sb.sb_inodesize + \
    -	  XFS_FSB_TO_B((mp), XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) + \
    -	  (128 * (1 + XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)))), \
    -	 ((4 * (mp)->m_sb.sb_sectsize) + \
    -	  (4 * (mp)->m_sb.sb_sectsize) + \
    -	  (mp)->m_sb.sb_sectsize + \
    -	  XFS_ALLOCFREE_LOG_RES(mp, 4) + \
    -	  (128 * (9 + XFS_ALLOCFREE_LOG_COUNT(mp, 4))))))
    -
    -#define	XFS_ATTRINVAL_LOG_RES(mp)	((mp)->m_reservations.tr_attrinval)
    -
    -/*
    - * Setting an attribute.
    - *	the inode getting the attribute
    - *	the superblock for allocations
    - *	the agfs extents are allocated from
    - *	the attribute btree * max depth
    - *	the inode allocation btree
    - * Since attribute transaction space is dependent on the size of the attribute,
    - * the calculation is done partially at mount time and partially at runtime.
    - */
    -#define	XFS_CALC_ATTRSET_LOG_RES(mp)	\
    -	((mp)->m_sb.sb_inodesize + \
    -	 (mp)->m_sb.sb_sectsize + \
    -	  XFS_FSB_TO_B((mp), XFS_DA_NODE_MAXDEPTH) + \
    -	  (128 * (2 + XFS_DA_NODE_MAXDEPTH)))
    -
    -#define	XFS_ATTRSET_LOG_RES(mp, ext)	\
    -	((mp)->m_reservations.tr_attrset + \
    -	 (ext * (mp)->m_sb.sb_sectsize) + \
    -	 (ext * XFS_FSB_TO_B((mp), XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK))) + \
    -	 (128 * (ext + (ext * XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)))))
    -
    -/*
    - * Removing an attribute.
    - *    the inode: inode size
    - *    the attribute btree could join: max depth * block size
    - *    the inode bmap btree could join or split: max depth * block size
    - * And the bmap_finish transaction can free the attr blocks freed giving:
    - *    the agf for the ag in which the blocks live: 2 * sector size
    - *    the agfl for the ag in which the blocks live: 2 * sector size
    - *    the superblock for the free block count: sector size
    - *    the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
    - */
    -#define	XFS_CALC_ATTRRM_LOG_RES(mp)	\
    -	(MAX( \
    -	  ((mp)->m_sb.sb_inodesize + \
    -	  XFS_FSB_TO_B((mp), XFS_DA_NODE_MAXDEPTH) + \
    -	  XFS_FSB_TO_B((mp), XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) + \
    -	  (128 * (1 + XFS_DA_NODE_MAXDEPTH + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK)))), \
    -	 ((2 * (mp)->m_sb.sb_sectsize) + \
    -	  (2 * (mp)->m_sb.sb_sectsize) + \
    -	  (mp)->m_sb.sb_sectsize + \
    -	  XFS_ALLOCFREE_LOG_RES(mp, 2) + \
    -	  (128 * (5 + XFS_ALLOCFREE_LOG_COUNT(mp, 2))))))
    -
    -#define	XFS_ATTRRM_LOG_RES(mp)	((mp)->m_reservations.tr_attrrm)
    -
    -/*
    - * Clearing a bad agino number in an agi hash bucket.
    - */
    -#define	XFS_CALC_CLEAR_AGI_BUCKET_LOG_RES(mp) \
    -	((mp)->m_sb.sb_sectsize + 128)
    -
    -#define	XFS_CLEAR_AGI_BUCKET_LOG_RES(mp)  ((mp)->m_reservations.tr_clearagi)
    -
    -
    -/*
    - * Various log count values.
    - */
    -#define	XFS_DEFAULT_LOG_COUNT		1
    -#define	XFS_DEFAULT_PERM_LOG_COUNT	2
    -#define	XFS_ITRUNCATE_LOG_COUNT		2
    -#define XFS_INACTIVE_LOG_COUNT		2
    -#define	XFS_CREATE_LOG_COUNT		2
    -#define	XFS_MKDIR_LOG_COUNT		3
    -#define	XFS_SYMLINK_LOG_COUNT		3
    -#define	XFS_REMOVE_LOG_COUNT		2
    -#define	XFS_LINK_LOG_COUNT		2
    -#define	XFS_RENAME_LOG_COUNT		2
    -#define	XFS_WRITE_LOG_COUNT		2
    -#define	XFS_ADDAFORK_LOG_COUNT		2
    -#define	XFS_ATTRINVAL_LOG_COUNT		1
    -#define	XFS_ATTRSET_LOG_COUNT		3
    -#define	XFS_ATTRRM_LOG_COUNT		3
    -
    -/*
    - * Here we centralize the specification of XFS meta-data buffer
    - * reference count values.  This determine how hard the buffer
    - * cache tries to hold onto the buffer.
    - */
    -#define	XFS_AGF_REF		4
    -#define	XFS_AGI_REF		4
    -#define	XFS_AGFL_REF		3
    -#define	XFS_INO_BTREE_REF	3
    -#define	XFS_ALLOC_BTREE_REF	2
    -#define	XFS_BMAP_BTREE_REF	2
    -#define	XFS_DIR_BTREE_REF	2
    -#define	XFS_ATTR_BTREE_REF	1
    -#define	XFS_INO_REF		1
    -#define	XFS_DQUOT_REF		1
    -
    -#ifdef __KERNEL__
    -/*
    - * XFS transaction mechanism exported interfaces that are
    - * actually macros.
    - */
    -#define	xfs_trans_get_log_res(tp)	((tp)->t_log_res)
    -#define	xfs_trans_get_log_count(tp)	((tp)->t_log_count)
    -#define	xfs_trans_get_block_res(tp)	((tp)->t_blk_res)
    -#define	xfs_trans_set_sync(tp)		((tp)->t_flags |= XFS_TRANS_SYNC)
    -
    -#ifdef DEBUG
    -#define	xfs_trans_agblocks_delta(tp, d)	((tp)->t_ag_freeblks_delta += (long)d)
    -#define	xfs_trans_agflist_delta(tp, d)	((tp)->t_ag_flist_delta += (long)d)
    -#define	xfs_trans_agbtree_delta(tp, d)	((tp)->t_ag_btree_delta += (long)d)
    -#else
    -#define	xfs_trans_agblocks_delta(tp, d)
    -#define	xfs_trans_agflist_delta(tp, d)
    -#define	xfs_trans_agbtree_delta(tp, d)
    -#endif
    -
    -/*
    - * XFS transaction mechanism exported interfaces.
    - */
    -void		xfs_trans_init(struct xfs_mount *);
    -xfs_trans_t	*xfs_trans_alloc(struct xfs_mount *, uint);
    -xfs_trans_t	*_xfs_trans_alloc(struct xfs_mount *, uint);
    -xfs_trans_t	*xfs_trans_dup(xfs_trans_t *);
    -int		xfs_trans_reserve(xfs_trans_t *, uint, uint, uint,
    -				  uint, uint);
    -void		xfs_trans_mod_sb(xfs_trans_t *, uint, long);
    -struct xfs_buf	*xfs_trans_get_buf(xfs_trans_t *, struct xfs_buftarg *, xfs_daddr_t,
    -				   int, uint);
    -int		xfs_trans_read_buf(struct xfs_mount *, xfs_trans_t *,
    -				   struct xfs_buftarg *, xfs_daddr_t, int, uint,
    -				   struct xfs_buf **);
    -struct xfs_buf	*xfs_trans_getsb(xfs_trans_t *, struct xfs_mount *, int);
    -
    -void		xfs_trans_brelse(xfs_trans_t *, struct xfs_buf *);
    -void		xfs_trans_bjoin(xfs_trans_t *, struct xfs_buf *);
    -void		xfs_trans_bhold(xfs_trans_t *, struct xfs_buf *);
    -void		xfs_trans_bhold_release(xfs_trans_t *, struct xfs_buf *);
    -void		xfs_trans_binval(xfs_trans_t *, struct xfs_buf *);
    -void		xfs_trans_inode_buf(xfs_trans_t *, struct xfs_buf *);
    -void		xfs_trans_stale_inode_buf(xfs_trans_t *, struct xfs_buf *);
    -void		xfs_trans_dquot_buf(xfs_trans_t *, struct xfs_buf *, uint);
    -void		xfs_trans_inode_alloc_buf(xfs_trans_t *, struct xfs_buf *);
    -int		xfs_trans_iget(struct xfs_mount *, xfs_trans_t *,
    -			       xfs_ino_t , uint, uint, struct xfs_inode **);
    -void		xfs_trans_ijoin(xfs_trans_t *, struct xfs_inode *, uint);
    -void		xfs_trans_ihold(xfs_trans_t *, struct xfs_inode *);
    -void		xfs_trans_log_buf(xfs_trans_t *, struct xfs_buf *, uint, uint);
    -void		xfs_trans_log_inode(xfs_trans_t *, struct xfs_inode *, uint);
    -struct xfs_efi_log_item	*xfs_trans_get_efi(xfs_trans_t *, uint);
    -void		xfs_efi_release(struct xfs_efi_log_item *, uint);
    -void		xfs_trans_log_efi_extent(xfs_trans_t *,
    -					 struct xfs_efi_log_item *,
    -					 xfs_fsblock_t,
    -					 xfs_extlen_t);
    -struct xfs_efd_log_item	*xfs_trans_get_efd(xfs_trans_t *,
    -				  struct xfs_efi_log_item *,
    -				  uint);
    -void		xfs_trans_log_efd_extent(xfs_trans_t *,
    -					 struct xfs_efd_log_item *,
    -					 xfs_fsblock_t,
    -					 xfs_extlen_t);
    -int		_xfs_trans_commit(xfs_trans_t *,
    -				  uint flags,
    -				  xfs_lsn_t *,
    -				  int *);
    -#define xfs_trans_commit(tp, flags, lsn) \
    -	_xfs_trans_commit(tp, flags, lsn, NULL)
    -void		xfs_trans_cancel(xfs_trans_t *, int);
    -void		xfs_trans_ail_init(struct xfs_mount *);
    -xfs_lsn_t	xfs_trans_push_ail(struct xfs_mount *, xfs_lsn_t);
    -xfs_lsn_t	xfs_trans_tail_ail(struct xfs_mount *);
    -void		xfs_trans_unlocked_item(struct xfs_mount *,
    -					xfs_log_item_t *);
    -xfs_log_busy_slot_t *xfs_trans_add_busy(xfs_trans_t *tp,
    -					xfs_agnumber_t ag,
    -					xfs_extlen_t idx);
    -
    -#endif	/* __KERNEL__ */
    -
    -#endif	/* __XFS_TRANS_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_trans_ail.c b/sys/gnu/fs/xfs/xfs_trans_ail.c
    deleted file mode 100644
    index 19ab24af1c1..00000000000
    --- a/sys/gnu/fs/xfs/xfs_trans_ail.c
    +++ /dev/null
    @@ -1,581 +0,0 @@
    -/*
    - * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_dir.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_trans_priv.h"
    -#include "xfs_error.h"
    -
    -STATIC void xfs_ail_insert(xfs_ail_entry_t *, xfs_log_item_t *);
    -STATIC xfs_log_item_t * xfs_ail_delete(xfs_ail_entry_t *, xfs_log_item_t *);
    -STATIC xfs_log_item_t * xfs_ail_min(xfs_ail_entry_t *);
    -STATIC xfs_log_item_t * xfs_ail_next(xfs_ail_entry_t *, xfs_log_item_t *);
    -
    -#ifdef DEBUG
    -STATIC void xfs_ail_check(xfs_ail_entry_t *);
    -#else
    -#define	xfs_ail_check(a)
    -#endif /* DEBUG */
    -
    -
    -/*
    - * This is called by the log manager code to determine the LSN
    - * of the tail of the log.  This is exactly the LSN of the first
    - * item in the AIL.  If the AIL is empty, then this function
    - * returns 0.
    - *
    - * We need the AIL lock in order to get a coherent read of the
    - * lsn of the last item in the AIL.
    - */
    -xfs_lsn_t
    -xfs_trans_tail_ail(
    -	xfs_mount_t	*mp)
    -{
    -	xfs_lsn_t	lsn;
    -	xfs_log_item_t	*lip;
    -	SPLDECL(s);
    -
    -	AIL_LOCK(mp,s);
    -	lip = xfs_ail_min(&(mp->m_ail));
    -	if (lip == NULL) {
    -		lsn = (xfs_lsn_t)0;
    -	} else {
    -		lsn = lip->li_lsn;
    -	}
    -	AIL_UNLOCK(mp, s);
    -
    -	return lsn;
    -}
    -
    -/*
    - * xfs_trans_push_ail
    - *
    - * This routine is called to move the tail of the AIL
    - * forward.  It does this by trying to flush items in the AIL
    - * whose lsns are below the given threshold_lsn.
    - *
    - * The routine returns the lsn of the tail of the log.
    - */
    -xfs_lsn_t
    -xfs_trans_push_ail(
    -	xfs_mount_t		*mp,
    -	xfs_lsn_t		threshold_lsn)
    -{
    -	xfs_lsn_t		lsn;
    -	xfs_log_item_t		*lip;
    -	int			gen;
    -	int			restarts;
    -	int			lock_result;
    -	int			flush_log;
    -	SPLDECL(s);
    -
    -#define	XFS_TRANS_PUSH_AIL_RESTARTS	10
    -
    -	AIL_LOCK(mp,s);
    -	lip = xfs_trans_first_ail(mp, &gen);
    -	if (lip == NULL || XFS_FORCED_SHUTDOWN(mp)) {
    -		/*
    -		 * Just return if the AIL is empty.
    -		 */
    -		AIL_UNLOCK(mp, s);
    -		return (xfs_lsn_t)0;
    -	}
    -
    -	XFS_STATS_INC(xs_push_ail);
    -
    -	/*
    -	 * While the item we are looking at is below the given threshold
    -	 * try to flush it out.  Make sure to limit the number of times
    -	 * we allow xfs_trans_next_ail() to restart scanning from the
    -	 * beginning of the list.  We'd like not to stop until we've at least
    -	 * tried to push on everything in the AIL with an LSN less than
    -	 * the given threshold. However, we may give up before that if
    -	 * we realize that we've been holding the AIL_LOCK for 'too long',
    -	 * blocking interrupts. Currently, too long is < 500us roughly.
    -	 */
    -	flush_log = 0;
    -	restarts = 0;
    -	while (((restarts < XFS_TRANS_PUSH_AIL_RESTARTS) &&
    -		(XFS_LSN_CMP(lip->li_lsn, threshold_lsn) < 0))) {
    -		/*
    -		 * If we can lock the item without sleeping, unlock
    -		 * the AIL lock and flush the item.  Then re-grab the
    -		 * AIL lock so we can look for the next item on the
    -		 * AIL.  Since we unlock the AIL while we flush the
    -		 * item, the next routine may start over again at the
    -		 * the beginning of the list if anything has changed.
    -		 * That is what the generation count is for.
    -		 *
    -		 * If we can't lock the item, either its holder will flush
    -		 * it or it is already being flushed or it is being relogged.
    -		 * In any of these case it is being taken care of and we
    -		 * can just skip to the next item in the list.
    -		 */
    -		lock_result = IOP_TRYLOCK(lip);
    -		switch (lock_result) {
    -		      case XFS_ITEM_SUCCESS:
    -			AIL_UNLOCK(mp, s);
    -			XFS_STATS_INC(xs_push_ail_success);
    -			IOP_PUSH(lip);
    -			AIL_LOCK(mp,s);
    -			break;
    -
    -		      case XFS_ITEM_PUSHBUF:
    -			AIL_UNLOCK(mp, s);
    -			XFS_STATS_INC(xs_push_ail_pushbuf);
    -#ifdef XFSRACEDEBUG
    -			delay_for_intr();
    -			delay(300);
    -#endif
    -			ASSERT(lip->li_ops->iop_pushbuf);
    -			ASSERT(lip);
    -			IOP_PUSHBUF(lip);
    -			AIL_LOCK(mp,s);
    -			break;
    -
    -		      case XFS_ITEM_PINNED:
    -			XFS_STATS_INC(xs_push_ail_pinned);
    -			flush_log = 1;
    -			break;
    -
    -		      case XFS_ITEM_LOCKED:
    -			XFS_STATS_INC(xs_push_ail_locked);
    -			break;
    -
    -		      case XFS_ITEM_FLUSHING:
    -			XFS_STATS_INC(xs_push_ail_flushing);
    -			break;
    -
    -		      default:
    -			ASSERT(0);
    -			break;
    -		}
    -
    -		lip = xfs_trans_next_ail(mp, lip, &gen, &restarts);
    -		if (lip == NULL) {
    -			break;
    -		}
    -		if (XFS_FORCED_SHUTDOWN(mp)) {
    -			/*
    -			 * Just return if we shut down during the last try.
    -			 */
    -			AIL_UNLOCK(mp, s);
    -			return (xfs_lsn_t)0;
    -		}
    -
    -	}
    -
    -	if (flush_log) {
    -		/*
    -		 * If something we need to push out was pinned, then
    -		 * push out the log so it will become unpinned and
    -		 * move forward in the AIL.
    -		 */
    -		AIL_UNLOCK(mp, s);
    -		XFS_STATS_INC(xs_push_ail_flush);
    -		xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE);
    -		AIL_LOCK(mp, s);
    -	}
    -
    -	lip = xfs_ail_min(&(mp->m_ail));
    -	if (lip == NULL) {
    -		lsn = (xfs_lsn_t)0;
    -	} else {
    -		lsn = lip->li_lsn;
    -	}
    -
    -	AIL_UNLOCK(mp, s);
    -	return lsn;
    -}	/* xfs_trans_push_ail */
    -
    -
    -/*
    - * This is to be called when an item is unlocked that may have
    - * been in the AIL.  It will wake up the first member of the AIL
    - * wait list if this item's unlocking might allow it to progress.
    - * If the item is in the AIL, then we need to get the AIL lock
    - * while doing our checking so we don't race with someone going
    - * to sleep waiting for this event in xfs_trans_push_ail().
    - */
    -void
    -xfs_trans_unlocked_item(
    -	xfs_mount_t	*mp,
    -	xfs_log_item_t	*lip)
    -{
    -	xfs_log_item_t	*min_lip;
    -
    -	/*
    -	 * If we're forcibly shutting down, we may have
    -	 * unlocked log items arbitrarily. The last thing
    -	 * we want to do is to move the tail of the log
    -	 * over some potentially valid data.
    -	 */
    -	if (!(lip->li_flags & XFS_LI_IN_AIL) ||
    -	    XFS_FORCED_SHUTDOWN(mp)) {
    -		return;
    -	}
    -
    -	/*
    -	 * This is the one case where we can call into xfs_ail_min()
    -	 * without holding the AIL lock because we only care about the
    -	 * case where we are at the tail of the AIL.  If the object isn't
    -	 * at the tail, it doesn't matter what result we get back.  This
    -	 * is slightly racy because since we were just unlocked, we could
    -	 * go to sleep between the call to xfs_ail_min and the call to
    -	 * xfs_log_move_tail, have someone else lock us, commit to us disk,
    -	 * move us out of the tail of the AIL, and then we wake up.  However,
    -	 * the call to xfs_log_move_tail() doesn't do anything if there's
    -	 * not enough free space to wake people up so we're safe calling it.
    -	 */
    -	min_lip = xfs_ail_min(&mp->m_ail);
    -
    -	if (min_lip == lip)
    -		xfs_log_move_tail(mp, 1);
    -}	/* xfs_trans_unlocked_item */
    -
    -
    -/*
    - * Update the position of the item in the AIL with the new
    - * lsn.  If it is not yet in the AIL, add it.  Otherwise, move
    - * it to its new position by removing it and re-adding it.
    - *
    - * Wakeup anyone with an lsn less than the item's lsn.  If the item
    - * we move in the AIL is the minimum one, update the tail lsn in the
    - * log manager.
    - *
    - * Increment the AIL's generation count to indicate that the tree
    - * has changed.
    - *
    - * This function must be called with the AIL lock held.  The lock
    - * is dropped before returning, so the caller must pass in the
    - * cookie returned by AIL_LOCK.
    - */
    -void
    -xfs_trans_update_ail(
    -	xfs_mount_t	*mp,
    -	xfs_log_item_t	*lip,
    -	xfs_lsn_t	lsn,
    -	unsigned long	s)
    -{
    -	xfs_ail_entry_t		*ailp;
    -	xfs_log_item_t		*dlip=NULL;
    -	xfs_log_item_t		*mlip;	/* ptr to minimum lip */
    -
    -	ailp = &(mp->m_ail);
    -	mlip = xfs_ail_min(ailp);
    -
    -	if (lip->li_flags & XFS_LI_IN_AIL) {
    -		dlip = xfs_ail_delete(ailp, lip);
    -		ASSERT(dlip == lip);
    -	} else {
    -		lip->li_flags |= XFS_LI_IN_AIL;
    -	}
    -
    -	lip->li_lsn = lsn;
    -
    -	xfs_ail_insert(ailp, lip);
    -	mp->m_ail_gen++;
    -
    -	if (mlip == dlip) {
    -		mlip = xfs_ail_min(&(mp->m_ail));
    -		AIL_UNLOCK(mp, s);
    -		xfs_log_move_tail(mp, mlip->li_lsn);
    -	} else {
    -		AIL_UNLOCK(mp, s);
    -	}
    -
    -
    -}	/* xfs_trans_update_ail */
    -
    -/*
    - * Delete the given item from the AIL.  It must already be in
    - * the AIL.
    - *
    - * Wakeup anyone with an lsn less than item's lsn.    If the item
    - * we delete in the AIL is the minimum one, update the tail lsn in the
    - * log manager.
    - *
    - * Clear the IN_AIL flag from the item, reset its lsn to 0, and
    - * bump the AIL's generation count to indicate that the tree
    - * has changed.
    - *
    - * This function must be called with the AIL lock held.  The lock
    - * is dropped before returning, so the caller must pass in the
    - * cookie returned by AIL_LOCK.
    - */
    -void
    -xfs_trans_delete_ail(
    -	xfs_mount_t	*mp,
    -	xfs_log_item_t	*lip,
    -	unsigned long	s)
    -{
    -	xfs_ail_entry_t		*ailp;
    -	xfs_log_item_t		*dlip;
    -	xfs_log_item_t		*mlip;
    -
    -	if (lip->li_flags & XFS_LI_IN_AIL) {
    -		ailp = &(mp->m_ail);
    -		mlip = xfs_ail_min(ailp);
    -		dlip = xfs_ail_delete(ailp, lip);
    -		ASSERT(dlip == lip);
    -
    -
    -		lip->li_flags &= ~XFS_LI_IN_AIL;
    -		lip->li_lsn = 0;
    -		mp->m_ail_gen++;
    -
    -		if (mlip == dlip) {
    -			mlip = xfs_ail_min(&(mp->m_ail));
    -			AIL_UNLOCK(mp, s);
    -			xfs_log_move_tail(mp, (mlip ? mlip->li_lsn : 0));
    -		} else {
    -			AIL_UNLOCK(mp, s);
    -		}
    -	}
    -	else {
    -		/*
    -		 * If the file system is not being shutdown, we are in
    -		 * serious trouble if we get to this stage.
    -		 */
    -		if (XFS_FORCED_SHUTDOWN(mp))
    -			AIL_UNLOCK(mp, s);
    -		else {
    -			xfs_cmn_err(XFS_PTAG_AILDELETE, CE_ALERT, mp,
    -				"xfs_trans_delete_ail: attempting to delete a log item that is not in the AIL");
    -			AIL_UNLOCK(mp, s);
    -			xfs_force_shutdown(mp, XFS_CORRUPT_INCORE);
    -		}
    -	}
    -}
    -
    -
    -
    -/*
    - * Return the item in the AIL with the smallest lsn.
    - * Return the current tree generation number for use
    - * in calls to xfs_trans_next_ail().
    - */
    -xfs_log_item_t *
    -xfs_trans_first_ail(
    -	xfs_mount_t	*mp,
    -	int		*gen)
    -{
    -	xfs_log_item_t	*lip;
    -
    -	lip = xfs_ail_min(&(mp->m_ail));
    -	*gen = (int)mp->m_ail_gen;
    -
    -	return (lip);
    -}
    -
    -/*
    - * If the generation count of the tree has not changed since the
    - * caller last took something from the AIL, then return the elmt
    - * in the tree which follows the one given.  If the count has changed,
    - * then return the minimum elmt of the AIL and bump the restarts counter
    - * if one is given.
    - */
    -xfs_log_item_t *
    -xfs_trans_next_ail(
    -	xfs_mount_t	*mp,
    -	xfs_log_item_t	*lip,
    -	int		*gen,
    -	int		*restarts)
    -{
    -	xfs_log_item_t	*nlip;
    -
    -	ASSERT(mp && lip && gen);
    -	if (mp->m_ail_gen == *gen) {
    -		nlip = xfs_ail_next(&(mp->m_ail), lip);
    -	} else {
    -		nlip = xfs_ail_min(&(mp->m_ail));
    -		*gen = (int)mp->m_ail_gen;
    -		if (restarts != NULL) {
    -			XFS_STATS_INC(xs_push_ail_restarts);
    -			(*restarts)++;
    -		}
    -	}
    -
    -	return (nlip);
    -}
    -
    -
    -/*
    - * The active item list (AIL) is a doubly linked list of log
    - * items sorted by ascending lsn.  The base of the list is
    - * a forw/back pointer pair embedded in the xfs mount structure.
    - * The base is initialized with both pointers pointing to the
    - * base.  This case always needs to be distinguished, because
    - * the base has no lsn to look at.  We almost always insert
    - * at the end of the list, so on inserts we search from the
    - * end of the list to find where the new item belongs.
    - */
    -
    -/*
    - * Initialize the doubly linked list to point only to itself.
    - */
    -void
    -xfs_trans_ail_init(
    -	xfs_mount_t	*mp)
    -{
    -	mp->m_ail.ail_forw = (xfs_log_item_t*)&(mp->m_ail);
    -	mp->m_ail.ail_back = (xfs_log_item_t*)&(mp->m_ail);
    -}
    -
    -/*
    - * Insert the given log item into the AIL.
    - * We almost always insert at the end of the list, so on inserts
    - * we search from the end of the list to find where the
    - * new item belongs.
    - */
    -STATIC void
    -xfs_ail_insert(
    -	xfs_ail_entry_t	*base,
    -	xfs_log_item_t	*lip)
    -/* ARGSUSED */
    -{
    -	xfs_log_item_t	*next_lip;
    -
    -	/*
    -	 * If the list is empty, just insert the item.
    -	 */
    -	if (base->ail_back == (xfs_log_item_t*)base) {
    -		base->ail_forw = lip;
    -		base->ail_back = lip;
    -		lip->li_ail.ail_forw = (xfs_log_item_t*)base;
    -		lip->li_ail.ail_back = (xfs_log_item_t*)base;
    -		return;
    -	}
    -
    -	next_lip = base->ail_back;
    -	while ((next_lip != (xfs_log_item_t*)base) &&
    -	       (XFS_LSN_CMP(next_lip->li_lsn, lip->li_lsn) > 0)) {
    -		next_lip = next_lip->li_ail.ail_back;
    -	}
    -	ASSERT((next_lip == (xfs_log_item_t*)base) ||
    -	       (XFS_LSN_CMP(next_lip->li_lsn, lip->li_lsn) <= 0));
    -	lip->li_ail.ail_forw = next_lip->li_ail.ail_forw;
    -	lip->li_ail.ail_back = next_lip;
    -	next_lip->li_ail.ail_forw = lip;
    -	lip->li_ail.ail_forw->li_ail.ail_back = lip;
    -
    -	xfs_ail_check(base);
    -	return;
    -}
    -
    -/*
    - * Delete the given item from the AIL.  Return a pointer to the item.
    - */
    -/*ARGSUSED*/
    -STATIC xfs_log_item_t *
    -xfs_ail_delete(
    -	xfs_ail_entry_t	*base,
    -	xfs_log_item_t	*lip)
    -/* ARGSUSED */
    -{
    -	lip->li_ail.ail_forw->li_ail.ail_back = lip->li_ail.ail_back;
    -	lip->li_ail.ail_back->li_ail.ail_forw = lip->li_ail.ail_forw;
    -	lip->li_ail.ail_forw = NULL;
    -	lip->li_ail.ail_back = NULL;
    -
    -	xfs_ail_check(base);
    -	return lip;
    -}
    -
    -/*
    - * Return a pointer to the first item in the AIL.
    - * If the AIL is empty, then return NULL.
    - */
    -STATIC xfs_log_item_t *
    -xfs_ail_min(
    -	xfs_ail_entry_t	*base)
    -/* ARGSUSED */
    -{
    -	register xfs_log_item_t *forw = base->ail_forw;
    -	if (forw == (xfs_log_item_t*)base) {
    -		return NULL;
    -	}
    -	return forw;
    -}
    -
    -/*
    - * Return a pointer to the item which follows
    - * the given item in the AIL.  If the given item
    - * is the last item in the list, then return NULL.
    - */
    -STATIC xfs_log_item_t *
    -xfs_ail_next(
    -	xfs_ail_entry_t	*base,
    -	xfs_log_item_t	*lip)
    -/* ARGSUSED */
    -{
    -	if (lip->li_ail.ail_forw == (xfs_log_item_t*)base) {
    -		return NULL;
    -	}
    -	return lip->li_ail.ail_forw;
    -
    -}
    -
    -#ifdef DEBUG
    -/*
    - * Check that the list is sorted as it should be.
    - */
    -STATIC void
    -xfs_ail_check(
    -	xfs_ail_entry_t *base)
    -{
    -	xfs_log_item_t	*lip;
    -	xfs_log_item_t	*prev_lip;
    -
    -	lip = base->ail_forw;
    -	if (lip == (xfs_log_item_t*)base) {
    -		/*
    -		 * Make sure the pointers are correct when the list
    -		 * is empty.
    -		 */
    -		ASSERT(base->ail_back == (xfs_log_item_t*)base);
    -		return;
    -	}
    -
    -	/*
    -	 * Walk the list checking forward and backward pointers,
    -	 * lsn ordering, and that every entry has the XFS_LI_IN_AIL
    -	 * flag set.
    -	 */
    -	prev_lip = (xfs_log_item_t*)base;
    -	while (lip != (xfs_log_item_t*)base) {
    -		if (prev_lip != (xfs_log_item_t*)base) {
    -			ASSERT(prev_lip->li_ail.ail_forw == lip);
    -			ASSERT(XFS_LSN_CMP(prev_lip->li_lsn, lip->li_lsn) <= 0);
    -		}
    -		ASSERT(lip->li_ail.ail_back == prev_lip);
    -		ASSERT((lip->li_flags & XFS_LI_IN_AIL) != 0);
    -		prev_lip = lip;
    -		lip = lip->li_ail.ail_forw;
    -	}
    -	ASSERT(lip == (xfs_log_item_t*)base);
    -	ASSERT(base->ail_back == prev_lip);
    -}
    -#endif /* DEBUG */
    diff --git a/sys/gnu/fs/xfs/xfs_trans_buf.c b/sys/gnu/fs/xfs/xfs_trans_buf.c
    deleted file mode 100644
    index 0ed8d3f1e69..00000000000
    --- a/sys/gnu/fs/xfs/xfs_trans_buf.c
    +++ /dev/null
    @@ -1,1113 +0,0 @@
    -/*
    - * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_buf_item.h"
    -#include "xfs_trans_priv.h"
    -#include "xfs_error.h"
    -#include "xfs_rw.h"
    -
    -
    -STATIC xfs_buf_t *xfs_trans_buf_item_match(xfs_trans_t *, xfs_buftarg_t *,
    -		xfs_daddr_t, int);
    -STATIC xfs_buf_t *xfs_trans_buf_item_match_all(xfs_trans_t *, xfs_buftarg_t *,
    -		xfs_daddr_t, int);
    -
    -
    -/*
    - * Get and lock the buffer for the caller if it is not already
    - * locked within the given transaction.  If it is already locked
    - * within the transaction, just increment its lock recursion count
    - * and return a pointer to it.
    - *
    - * Use the fast path function xfs_trans_buf_item_match() or the buffer
    - * cache routine incore_match() to find the buffer
    - * if it is already owned by this transaction.
    - *
    - * If we don't already own the buffer, use get_buf() to get it.
    - * If it doesn't yet have an associated xfs_buf_log_item structure,
    - * then allocate one and add the item to this transaction.
    - *
    - * If the transaction pointer is NULL, make this just a normal
    - * get_buf() call.
    - */
    -xfs_buf_t *
    -xfs_trans_get_buf(xfs_trans_t	*tp,
    -		  xfs_buftarg_t	*target_dev,
    -		  xfs_daddr_t	blkno,
    -		  int		len,
    -		  uint		flags)
    -{
    -	xfs_buf_t		*bp;
    -	xfs_buf_log_item_t	*bip;
    -
    -	if (flags == 0)
    -		flags = XFS_BUF_LOCK | XFS_BUF_MAPPED;
    -
    -	/*
    -	 * Default to a normal get_buf() call if the tp is NULL.
    -	 */
    -	if (tp == NULL) {
    -		bp = xfs_buf_get_flags(target_dev, blkno, len,
    -							flags | BUF_BUSY);
    -		return(bp);
    -	}
    -
    -	/*
    -	 * If we find the buffer in the cache with this transaction
    -	 * pointer in its b_fsprivate2 field, then we know we already
    -	 * have it locked.  In this case we just increment the lock
    -	 * recursion count and return the buffer to the caller.
    -	 */
    -	if (tp->t_items.lic_next == NULL) {
    -		bp = xfs_trans_buf_item_match(tp, target_dev, blkno, len);
    -	} else {
    -		bp  = xfs_trans_buf_item_match_all(tp, target_dev, blkno, len);
    -	}
    -	if (bp != NULL) {
    -		ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);
    -		if (XFS_FORCED_SHUTDOWN(tp->t_mountp)) {
    -			xfs_buftrace("TRANS GET RECUR SHUT", bp);
    -			XFS_BUF_SUPER_STALE(bp);
    -		}
    -		/*
    -		 * If the buffer is stale then it was binval'ed
    -		 * since last read.  This doesn't matter since the
    -		 * caller isn't allowed to use the data anyway.
    -		 */
    -		else if (XFS_BUF_ISSTALE(bp)) {
    -			xfs_buftrace("TRANS GET RECUR STALE", bp);
    -			ASSERT(!XFS_BUF_ISDELAYWRITE(bp));
    -		}
    -		ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp);
    -		bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
    -		ASSERT(bip != NULL);
    -		ASSERT(atomic_read(&bip->bli_refcount) > 0);
    -		bip->bli_recur++;
    -		xfs_buftrace("TRANS GET RECUR", bp);
    -		xfs_buf_item_trace("GET RECUR", bip);
    -		return (bp);
    -	}
    -
    -	/*
    -	 * We always specify the BUF_BUSY flag within a transaction so
    -	 * that get_buf does not try to push out a delayed write buffer
    -	 * which might cause another transaction to take place (if the
    -	 * buffer was delayed alloc).  Such recursive transactions can
    -	 * easily deadlock with our current transaction as well as cause
    -	 * us to run out of stack space.
    -	 */
    -	bp = xfs_buf_get_flags(target_dev, blkno, len, flags | BUF_BUSY);
    -	if (bp == NULL) {
    -		return NULL;
    -	}
    -
    -	ASSERT(!XFS_BUF_GETERROR(bp));
    -
    -	/*
    -	 * The xfs_buf_log_item pointer is stored in b_fsprivate.  If
    -	 * it doesn't have one yet, then allocate one and initialize it.
    -	 * The checks to see if one is there are in xfs_buf_item_init().
    -	 */
    -	xfs_buf_item_init(bp, tp->t_mountp);
    -
    -	/*
    -	 * Set the recursion count for the buffer within this transaction
    -	 * to 0.
    -	 */
    -	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*);
    -	ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
    -	ASSERT(!(bip->bli_format.blf_flags & XFS_BLI_CANCEL));
    -	ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED));
    -	bip->bli_recur = 0;
    -
    -	/*
    -	 * Take a reference for this transaction on the buf item.
    -	 */
    -	atomic_inc(&bip->bli_refcount);
    -
    -	/*
    -	 * Get a log_item_desc to point at the new item.
    -	 */
    -	(void) xfs_trans_add_item(tp, (xfs_log_item_t*)bip);
    -
    -	/*
    -	 * Initialize b_fsprivate2 so we can find it with incore_match()
    -	 * above.
    -	 */
    -	XFS_BUF_SET_FSPRIVATE2(bp, tp);
    -
    -	xfs_buftrace("TRANS GET", bp);
    -	xfs_buf_item_trace("GET", bip);
    -	return (bp);
    -}
    -
    -/*
    - * Get and lock the superblock buffer of this file system for the
    - * given transaction.
    - *
    - * We don't need to use incore_match() here, because the superblock
    - * buffer is a private buffer which we keep a pointer to in the
    - * mount structure.
    - */
    -xfs_buf_t *
    -xfs_trans_getsb(xfs_trans_t	*tp,
    -		struct xfs_mount *mp,
    -		int		flags)
    -{
    -	xfs_buf_t		*bp;
    -	xfs_buf_log_item_t	*bip;
    -
    -	/*
    -	 * Default to just trying to lock the superblock buffer
    -	 * if tp is NULL.
    -	 */
    -	if (tp == NULL) {
    -		return (xfs_getsb(mp, flags));
    -	}
    -
    -	/*
    -	 * If the superblock buffer already has this transaction
    -	 * pointer in its b_fsprivate2 field, then we know we already
    -	 * have it locked.  In this case we just increment the lock
    -	 * recursion count and return the buffer to the caller.
    -	 */
    -	bp = mp->m_sb_bp;
    -	if (XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp) {
    -		bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*);
    -		ASSERT(bip != NULL);
    -		ASSERT(atomic_read(&bip->bli_refcount) > 0);
    -		bip->bli_recur++;
    -		xfs_buf_item_trace("GETSB RECUR", bip);
    -		return (bp);
    -	}
    -
    -	bp = xfs_getsb(mp, flags);
    -	if (bp == NULL) {
    -		return NULL;
    -	}
    -
    -	/*
    -	 * The xfs_buf_log_item pointer is stored in b_fsprivate.  If
    -	 * it doesn't have one yet, then allocate one and initialize it.
    -	 * The checks to see if one is there are in xfs_buf_item_init().
    -	 */
    -	xfs_buf_item_init(bp, mp);
    -
    -	/*
    -	 * Set the recursion count for the buffer within this transaction
    -	 * to 0.
    -	 */
    -	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*);
    -	ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
    -	ASSERT(!(bip->bli_format.blf_flags & XFS_BLI_CANCEL));
    -	ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED));
    -	bip->bli_recur = 0;
    -
    -	/*
    -	 * Take a reference for this transaction on the buf item.
    -	 */
    -	atomic_inc(&bip->bli_refcount);
    -
    -	/*
    -	 * Get a log_item_desc to point at the new item.
    -	 */
    -	(void) xfs_trans_add_item(tp, (xfs_log_item_t*)bip);
    -
    -	/*
    -	 * Initialize b_fsprivate2 so we can find it with incore_match()
    -	 * above.
    -	 */
    -	XFS_BUF_SET_FSPRIVATE2(bp, tp);
    -
    -	xfs_buf_item_trace("GETSB", bip);
    -	return (bp);
    -}
    -
    -#ifdef DEBUG
    -xfs_buftarg_t *xfs_error_target;
    -int	xfs_do_error;
    -int	xfs_req_num;
    -int	xfs_error_mod = 33;
    -#endif
    -
    -/*
    - * Get and lock the buffer for the caller if it is not already
    - * locked within the given transaction.  If it has not yet been
    - * read in, read it from disk. If it is already locked
    - * within the transaction and already read in, just increment its
    - * lock recursion count and return a pointer to it.
    - *
    - * Use the fast path function xfs_trans_buf_item_match() or the buffer
    - * cache routine incore_match() to find the buffer
    - * if it is already owned by this transaction.
    - *
    - * If we don't already own the buffer, use read_buf() to get it.
    - * If it doesn't yet have an associated xfs_buf_log_item structure,
    - * then allocate one and add the item to this transaction.
    - *
    - * If the transaction pointer is NULL, make this just a normal
    - * read_buf() call.
    - */
    -int
    -xfs_trans_read_buf(
    -	xfs_mount_t	*mp,
    -	xfs_trans_t	*tp,
    -	xfs_buftarg_t	*target,
    -	xfs_daddr_t	blkno,
    -	int		len,
    -	uint		flags,
    -	xfs_buf_t	**bpp)
    -{
    -	xfs_buf_t		*bp;
    -	xfs_buf_log_item_t	*bip;
    -	int			error;
    -
    -	if (flags == 0)
    -		flags = XFS_BUF_LOCK | XFS_BUF_MAPPED;
    -
    -	/*
    -	 * Default to a normal get_buf() call if the tp is NULL.
    -	 */
    -	if (tp == NULL) {
    -		bp = xfs_buf_read_flags(target, blkno, len, flags | BUF_BUSY);
    -		if (!bp)
    -			return XFS_ERROR(ENOMEM);
    -
    -		if ((bp != NULL) && (XFS_BUF_GETERROR(bp) != 0)) {
    -			xfs_ioerror_alert("xfs_trans_read_buf", mp,
    -					  bp, blkno);
    -			error = XFS_BUF_GETERROR(bp);
    -			xfs_buf_relse(bp);
    -			return error;
    -		}
    -#ifdef DEBUG
    -		if (xfs_do_error && (bp != NULL)) {
    -			if (xfs_error_target == target) {
    -				if (((xfs_req_num++) % xfs_error_mod) == 0) {
    -					xfs_buf_relse(bp);
    -					printk("Returning error!\n");
    -					return XFS_ERROR(EIO);
    -				}
    -			}
    -		}
    -#endif
    -		if (XFS_FORCED_SHUTDOWN(mp))
    -			goto shutdown_abort;
    -		*bpp = bp;
    -		return 0;
    -	}
    -
    -	/*
    -	 * If we find the buffer in the cache with this transaction
    -	 * pointer in its b_fsprivate2 field, then we know we already
    -	 * have it locked.  If it is already read in we just increment
    -	 * the lock recursion count and return the buffer to the caller.
    -	 * If the buffer is not yet read in, then we read it in, increment
    -	 * the lock recursion count, and return it to the caller.
    -	 */
    -	if (tp->t_items.lic_next == NULL) {
    -		bp = xfs_trans_buf_item_match(tp, target, blkno, len);
    -	} else {
    -		bp = xfs_trans_buf_item_match_all(tp, target, blkno, len);
    -	}
    -	if (bp != NULL) {
    -		ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);
    -		ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp);
    -		ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL);
    -		ASSERT((XFS_BUF_ISERROR(bp)) == 0);
    -		if (!(XFS_BUF_ISDONE(bp))) {
    -			xfs_buftrace("READ_BUF_INCORE !DONE", bp);
    -			ASSERT(!XFS_BUF_ISASYNC(bp));
    -			XFS_BUF_READ(bp);
    -			xfsbdstrat(tp->t_mountp, bp);
    -			xfs_iowait(bp);
    -			if (XFS_BUF_GETERROR(bp) != 0) {
    -				xfs_ioerror_alert("xfs_trans_read_buf", mp,
    -						  bp, blkno);
    -				error = XFS_BUF_GETERROR(bp);
    -				xfs_buf_relse(bp);
    -				/*
    -				 * We can gracefully recover from most
    -				 * read errors. Ones we can't are those
    -				 * that happen after the transaction's
    -				 * already dirty.
    -				 */
    -				if (tp->t_flags & XFS_TRANS_DIRTY)
    -					xfs_force_shutdown(tp->t_mountp,
    -							   XFS_METADATA_IO_ERROR);
    -				return error;
    -			}
    -		}
    -		/*
    -		 * We never locked this buf ourselves, so we shouldn't
    -		 * brelse it either. Just get out.
    -		 */
    -		if (XFS_FORCED_SHUTDOWN(mp)) {
    -			xfs_buftrace("READ_BUF_INCORE XFSSHUTDN", bp);
    -			*bpp = NULL;
    -			return XFS_ERROR(EIO);
    -		}
    -
    -
    -		bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*);
    -		bip->bli_recur++;
    -
    -		ASSERT(atomic_read(&bip->bli_refcount) > 0);
    -		xfs_buf_item_trace("READ RECUR", bip);
    -		*bpp = bp;
    -		return 0;
    -	}
    -
    -	/*
    -	 * We always specify the BUF_BUSY flag within a transaction so
    -	 * that get_buf does not try to push out a delayed write buffer
    -	 * which might cause another transaction to take place (if the
    -	 * buffer was delayed alloc).  Such recursive transactions can
    -	 * easily deadlock with our current transaction as well as cause
    -	 * us to run out of stack space.
    -	 */
    -	bp = xfs_buf_read_flags(target, blkno, len, flags | BUF_BUSY);
    -	if (bp == NULL) {
    -		*bpp = NULL;
    -		return 0;
    -	}
    -	if (XFS_BUF_GETERROR(bp) != 0) {
    -	    XFS_BUF_SUPER_STALE(bp);
    -		xfs_buftrace("READ ERROR", bp);
    -		error = XFS_BUF_GETERROR(bp);
    -
    -		xfs_ioerror_alert("xfs_trans_read_buf", mp,
    -				  bp, blkno);
    -		if (tp->t_flags & XFS_TRANS_DIRTY)
    -			xfs_force_shutdown(tp->t_mountp, XFS_METADATA_IO_ERROR);
    -		xfs_buf_relse(bp);
    -		return error;
    -	}
    -#ifdef DEBUG
    -	if (xfs_do_error && !(tp->t_flags & XFS_TRANS_DIRTY)) {
    -		if (xfs_error_target == target) {
    -			if (((xfs_req_num++) % xfs_error_mod) == 0) {
    -				xfs_force_shutdown(tp->t_mountp,
    -						   XFS_METADATA_IO_ERROR);
    -				xfs_buf_relse(bp);
    -				printk("Returning error in trans!\n");
    -				return XFS_ERROR(EIO);
    -			}
    -		}
    -	}
    -#endif
    -	if (XFS_FORCED_SHUTDOWN(mp))
    -		goto shutdown_abort;
    -
    -	/*
    -	 * The xfs_buf_log_item pointer is stored in b_fsprivate.  If
    -	 * it doesn't have one yet, then allocate one and initialize it.
    -	 * The checks to see if one is there are in xfs_buf_item_init().
    -	 */
    -	xfs_buf_item_init(bp, tp->t_mountp);
    -
    -	/*
    -	 * Set the recursion count for the buffer within this transaction
    -	 * to 0.
    -	 */
    -	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*);
    -	ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
    -	ASSERT(!(bip->bli_format.blf_flags & XFS_BLI_CANCEL));
    -	ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED));
    -	bip->bli_recur = 0;
    -
    -	/*
    -	 * Take a reference for this transaction on the buf item.
    -	 */
    -	atomic_inc(&bip->bli_refcount);
    -
    -	/*
    -	 * Get a log_item_desc to point at the new item.
    -	 */
    -	(void) xfs_trans_add_item(tp, (xfs_log_item_t*)bip);
    -
    -	/*
    -	 * Initialize b_fsprivate2 so we can find it with incore_match()
    -	 * above.
    -	 */
    -	XFS_BUF_SET_FSPRIVATE2(bp, tp);
    -
    -	xfs_buftrace("TRANS READ", bp);
    -	xfs_buf_item_trace("READ", bip);
    -	*bpp = bp;
    -	return 0;
    -
    -shutdown_abort:
    -	/*
    -	 * the theory here is that buffer is good but we're
    -	 * bailing out because the filesystem is being forcibly
    -	 * shut down.  So we should leave the b_flags alone since
    -	 * the buffer's not staled and just get out.
    -	 */
    -#if defined(DEBUG)
    -	if (XFS_BUF_ISSTALE(bp) && XFS_BUF_ISDELAYWRITE(bp))
    -		cmn_err(CE_NOTE, "about to pop assert, bp == 0x%p", bp);
    -#endif
    -	ASSERT((XFS_BUF_BFLAGS(bp) & (XFS_B_STALE|XFS_B_DELWRI)) !=
    -						(XFS_B_STALE|XFS_B_DELWRI));
    -
    -	xfs_buftrace("READ_BUF XFSSHUTDN", bp);
    -	xfs_buf_relse(bp);
    -	*bpp = NULL;
    -	return XFS_ERROR(EIO);
    -}
    -
    -
    -/*
    - * Release the buffer bp which was previously acquired with one of the
    - * xfs_trans_... buffer allocation routines if the buffer has not
    - * been modified within this transaction.  If the buffer is modified
    - * within this transaction, do decrement the recursion count but do
    - * not release the buffer even if the count goes to 0.  If the buffer is not
    - * modified within the transaction, decrement the recursion count and
    - * release the buffer if the recursion count goes to 0.
    - *
    - * If the buffer is to be released and it was not modified before
    - * this transaction began, then free the buf_log_item associated with it.
    - *
    - * If the transaction pointer is NULL, make this just a normal
    - * brelse() call.
    - */
    -void
    -xfs_trans_brelse(xfs_trans_t	*tp,
    -		 xfs_buf_t	*bp)
    -{
    -	xfs_buf_log_item_t	*bip;
    -	xfs_log_item_t		*lip;
    -	xfs_log_item_desc_t	*lidp;
    -
    -	/*
    -	 * Default to a normal brelse() call if the tp is NULL.
    -	 */
    -	if (tp == NULL) {
    -		ASSERT(XFS_BUF_FSPRIVATE2(bp, void *) == NULL);
    -		/*
    -		 * If there's a buf log item attached to the buffer,
    -		 * then let the AIL know that the buffer is being
    -		 * unlocked.
    -		 */
    -		if (XFS_BUF_FSPRIVATE(bp, void *) != NULL) {
    -			lip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *);
    -			if (lip->li_type == XFS_LI_BUF) {
    -				bip = XFS_BUF_FSPRIVATE(bp,xfs_buf_log_item_t*);
    -				xfs_trans_unlocked_item(
    -						bip->bli_item.li_mountp,
    -						lip);
    -			}
    -		}
    -		xfs_buf_relse(bp);
    -		return;
    -	}
    -
    -	ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp);
    -	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
    -	ASSERT(bip->bli_item.li_type == XFS_LI_BUF);
    -	ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
    -	ASSERT(!(bip->bli_format.blf_flags & XFS_BLI_CANCEL));
    -	ASSERT(atomic_read(&bip->bli_refcount) > 0);
    -
    -	/*
    -	 * Find the item descriptor pointing to this buffer's
    -	 * log item.  It must be there.
    -	 */
    -	lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)bip);
    -	ASSERT(lidp != NULL);
    -
    -	/*
    -	 * If the release is just for a recursive lock,
    -	 * then decrement the count and return.
    -	 */
    -	if (bip->bli_recur > 0) {
    -		bip->bli_recur--;
    -		xfs_buf_item_trace("RELSE RECUR", bip);
    -		return;
    -	}
    -
    -	/*
    -	 * If the buffer is dirty within this transaction, we can't
    -	 * release it until we commit.
    -	 */
    -	if (lidp->lid_flags & XFS_LID_DIRTY) {
    -		xfs_buf_item_trace("RELSE DIRTY", bip);
    -		return;
    -	}
    -
    -	/*
    -	 * If the buffer has been invalidated, then we can't release
    -	 * it until the transaction commits to disk unless it is re-dirtied
    -	 * as part of this transaction.  This prevents us from pulling
    -	 * the item from the AIL before we should.
    -	 */
    -	if (bip->bli_flags & XFS_BLI_STALE) {
    -		xfs_buf_item_trace("RELSE STALE", bip);
    -		return;
    -	}
    -
    -	ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED));
    -	xfs_buf_item_trace("RELSE", bip);
    -
    -	/*
    -	 * Free up the log item descriptor tracking the released item.
    -	 */
    -	xfs_trans_free_item(tp, lidp);
    -
    -	/*
    -	 * Clear the hold flag in the buf log item if it is set.
    -	 * We wouldn't want the next user of the buffer to
    -	 * get confused.
    -	 */
    -	if (bip->bli_flags & XFS_BLI_HOLD) {
    -		bip->bli_flags &= ~XFS_BLI_HOLD;
    -	}
    -
    -	/*
    -	 * Drop our reference to the buf log item.
    -	 */
    -	atomic_dec(&bip->bli_refcount);
    -
    -	/*
    -	 * If the buf item is not tracking data in the log, then
    -	 * we must free it before releasing the buffer back to the
    -	 * free pool.  Before releasing the buffer to the free pool,
    -	 * clear the transaction pointer in b_fsprivate2 to dissolve
    -	 * its relation to this transaction.
    -	 */
    -	if (!xfs_buf_item_dirty(bip)) {
    -/***
    -		ASSERT(bp->b_pincount == 0);
    -***/
    -		ASSERT(atomic_read(&bip->bli_refcount) == 0);
    -		ASSERT(!(bip->bli_item.li_flags & XFS_LI_IN_AIL));
    -		ASSERT(!(bip->bli_flags & XFS_BLI_INODE_ALLOC_BUF));
    -		xfs_buf_item_relse(bp);
    -		bip = NULL;
    -	}
    -	XFS_BUF_SET_FSPRIVATE2(bp, NULL);
    -
    -	/*
    -	 * If we've still got a buf log item on the buffer, then
    -	 * tell the AIL that the buffer is being unlocked.
    -	 */
    -	if (bip != NULL) {
    -		xfs_trans_unlocked_item(bip->bli_item.li_mountp,
    -					(xfs_log_item_t*)bip);
    -	}
    -
    -	xfs_buf_relse(bp);
    -	return;
    -}
    -
    -/*
    - * Add the locked buffer to the transaction.
    - * The buffer must be locked, and it cannot be associated with any
    - * transaction.
    - *
    - * If the buffer does not yet have a buf log item associated with it,
    - * then allocate one for it.  Then add the buf item to the transaction.
    - */
    -void
    -xfs_trans_bjoin(xfs_trans_t	*tp,
    -		xfs_buf_t	*bp)
    -{
    -	xfs_buf_log_item_t	*bip;
    -
    -	ASSERT(XFS_BUF_ISBUSY(bp));
    -	ASSERT(XFS_BUF_FSPRIVATE2(bp, void *) == NULL);
    -
    -	/*
    -	 * The xfs_buf_log_item pointer is stored in b_fsprivate.  If
    -	 * it doesn't have one yet, then allocate one and initialize it.
    -	 * The checks to see if one is there are in xfs_buf_item_init().
    -	 */
    -	xfs_buf_item_init(bp, tp->t_mountp);
    -	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
    -	ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
    -	ASSERT(!(bip->bli_format.blf_flags & XFS_BLI_CANCEL));
    -	ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED));
    -
    -	/*
    -	 * Take a reference for this transaction on the buf item.
    -	 */
    -	atomic_inc(&bip->bli_refcount);
    -
    -	/*
    -	 * Get a log_item_desc to point at the new item.
    -	 */
    -	(void) xfs_trans_add_item(tp, (xfs_log_item_t *)bip);
    -
    -	/*
    -	 * Initialize b_fsprivate2 so we can find it with incore_match()
    -	 * in xfs_trans_get_buf() and friends above.
    -	 */
    -	XFS_BUF_SET_FSPRIVATE2(bp, tp);
    -
    -	xfs_buf_item_trace("BJOIN", bip);
    -}
    -
    -/*
    - * Mark the buffer as not needing to be unlocked when the buf item's
    - * IOP_UNLOCK() routine is called.  The buffer must already be locked
    - * and associated with the given transaction.
    - */
    -/* ARGSUSED */
    -void
    -xfs_trans_bhold(xfs_trans_t	*tp,
    -		xfs_buf_t	*bp)
    -{
    -	xfs_buf_log_item_t	*bip;
    -
    -	ASSERT(XFS_BUF_ISBUSY(bp));
    -	ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp);
    -	ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL);
    -
    -	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
    -	ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
    -	ASSERT(!(bip->bli_format.blf_flags & XFS_BLI_CANCEL));
    -	ASSERT(atomic_read(&bip->bli_refcount) > 0);
    -	bip->bli_flags |= XFS_BLI_HOLD;
    -	xfs_buf_item_trace("BHOLD", bip);
    -}
    -
    -/*
    - * Cancel the previous buffer hold request made on this buffer
    - * for this transaction.
    - */
    -void
    -xfs_trans_bhold_release(xfs_trans_t	*tp,
    -			xfs_buf_t	*bp)
    -{
    -	xfs_buf_log_item_t	*bip;
    -
    -	ASSERT(XFS_BUF_ISBUSY(bp));
    -	ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp);
    -	ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL);
    -
    -	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
    -	ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
    -	ASSERT(!(bip->bli_format.blf_flags & XFS_BLI_CANCEL));
    -	ASSERT(atomic_read(&bip->bli_refcount) > 0);
    -	ASSERT(bip->bli_flags & XFS_BLI_HOLD);
    -	bip->bli_flags &= ~XFS_BLI_HOLD;
    -	xfs_buf_item_trace("BHOLD RELEASE", bip);
    -}
    -
    -/*
    - * This is called to mark bytes first through last inclusive of the given
    - * buffer as needing to be logged when the transaction is committed.
    - * The buffer must already be associated with the given transaction.
    - *
    - * First and last are numbers relative to the beginning of this buffer,
    - * so the first byte in the buffer is numbered 0 regardless of the
    - * value of b_blkno.
    - */
    -void
    -xfs_trans_log_buf(xfs_trans_t	*tp,
    -		  xfs_buf_t	*bp,
    -		  uint		first,
    -		  uint		last)
    -{
    -	xfs_buf_log_item_t	*bip;
    -	xfs_log_item_desc_t	*lidp;
    -
    -	ASSERT(XFS_BUF_ISBUSY(bp));
    -	ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp);
    -	ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL);
    -	ASSERT((first <= last) && (last < XFS_BUF_COUNT(bp)));
    -	ASSERT((XFS_BUF_IODONE_FUNC(bp) == NULL) ||
    -	       (XFS_BUF_IODONE_FUNC(bp) == xfs_buf_iodone_callbacks));
    -
    -	/*
    -	 * Mark the buffer as needing to be written out eventually,
    -	 * and set its iodone function to remove the buffer's buf log
    -	 * item from the AIL and free it when the buffer is flushed
    -	 * to disk.  See xfs_buf_attach_iodone() for more details
    -	 * on li_cb and xfs_buf_iodone_callbacks().
    -	 * If we end up aborting this transaction, we trap this buffer
    -	 * inside the b_bdstrat callback so that this won't get written to
    -	 * disk.
    -	 */
    -	XFS_BUF_DELAYWRITE(bp);
    -	XFS_BUF_DONE(bp);
    -
    -	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
    -	ASSERT(atomic_read(&bip->bli_refcount) > 0);
    -	XFS_BUF_SET_IODONE_FUNC(bp, xfs_buf_iodone_callbacks);
    -	bip->bli_item.li_cb = (void(*)(xfs_buf_t*,xfs_log_item_t*))xfs_buf_iodone;
    -
    -	/*
    -	 * If we invalidated the buffer within this transaction, then
    -	 * cancel the invalidation now that we're dirtying the buffer
    -	 * again.  There are no races with the code in xfs_buf_item_unpin(),
    -	 * because we have a reference to the buffer this entire time.
    -	 */
    -	if (bip->bli_flags & XFS_BLI_STALE) {
    -		xfs_buf_item_trace("BLOG UNSTALE", bip);
    -		bip->bli_flags &= ~XFS_BLI_STALE;
    -		ASSERT(XFS_BUF_ISSTALE(bp));
    -		XFS_BUF_UNSTALE(bp);
    -		bip->bli_format.blf_flags &= ~XFS_BLI_CANCEL;
    -	}
    -
    -	lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)bip);
    -	ASSERT(lidp != NULL);
    -
    -	tp->t_flags |= XFS_TRANS_DIRTY;
    -	lidp->lid_flags |= XFS_LID_DIRTY;
    -	lidp->lid_flags &= ~XFS_LID_BUF_STALE;
    -	bip->bli_flags |= XFS_BLI_LOGGED;
    -	xfs_buf_item_log(bip, first, last);
    -	xfs_buf_item_trace("BLOG", bip);
    -}
    -
    -
    -/*
    - * This called to invalidate a buffer that is being used within
    - * a transaction.  Typically this is because the blocks in the
    - * buffer are being freed, so we need to prevent it from being
    - * written out when we're done.  Allowing it to be written again
    - * might overwrite data in the free blocks if they are reallocated
    - * to a file.
    - *
    - * We prevent the buffer from being written out by clearing the
    - * B_DELWRI flag.  We can't always
    - * get rid of the buf log item at this point, though, because
    - * the buffer may still be pinned by another transaction.  If that
    - * is the case, then we'll wait until the buffer is committed to
    - * disk for the last time (we can tell by the ref count) and
    - * free it in xfs_buf_item_unpin().  Until it is cleaned up we
    - * will keep the buffer locked so that the buffer and buf log item
    - * are not reused.
    - */
    -void
    -xfs_trans_binval(
    -	xfs_trans_t	*tp,
    -	xfs_buf_t	*bp)
    -{
    -	xfs_log_item_desc_t	*lidp;
    -	xfs_buf_log_item_t	*bip;
    -
    -	ASSERT(XFS_BUF_ISBUSY(bp));
    -	ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp);
    -	ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL);
    -
    -	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
    -	lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)bip);
    -	ASSERT(lidp != NULL);
    -	ASSERT(atomic_read(&bip->bli_refcount) > 0);
    -
    -	if (bip->bli_flags & XFS_BLI_STALE) {
    -		/*
    -		 * If the buffer is already invalidated, then
    -		 * just return.
    -		 */
    -		ASSERT(!(XFS_BUF_ISDELAYWRITE(bp)));
    -		ASSERT(XFS_BUF_ISSTALE(bp));
    -		ASSERT(!(bip->bli_flags & (XFS_BLI_LOGGED | XFS_BLI_DIRTY)));
    -		ASSERT(!(bip->bli_format.blf_flags & XFS_BLI_INODE_BUF));
    -		ASSERT(bip->bli_format.blf_flags & XFS_BLI_CANCEL);
    -		ASSERT(lidp->lid_flags & XFS_LID_DIRTY);
    -		ASSERT(tp->t_flags & XFS_TRANS_DIRTY);
    -		xfs_buftrace("XFS_BINVAL RECUR", bp);
    -		xfs_buf_item_trace("BINVAL RECUR", bip);
    -		return;
    -	}
    -
    -	/*
    -	 * Clear the dirty bit in the buffer and set the STALE flag
    -	 * in the buf log item.  The STALE flag will be used in
    -	 * xfs_buf_item_unpin() to determine if it should clean up
    -	 * when the last reference to the buf item is given up.
    -	 * We set the XFS_BLI_CANCEL flag in the buf log format structure
    -	 * and log the buf item.  This will be used at recovery time
    -	 * to determine that copies of the buffer in the log before
    -	 * this should not be replayed.
    -	 * We mark the item descriptor and the transaction dirty so
    -	 * that we'll hold the buffer until after the commit.
    -	 *
    -	 * Since we're invalidating the buffer, we also clear the state
    -	 * about which parts of the buffer have been logged.  We also
    -	 * clear the flag indicating that this is an inode buffer since
    -	 * the data in the buffer will no longer be valid.
    -	 *
    -	 * We set the stale bit in the buffer as well since we're getting
    -	 * rid of it.
    -	 */
    -	XFS_BUF_UNDELAYWRITE(bp);
    -	XFS_BUF_STALE(bp);
    -	bip->bli_flags |= XFS_BLI_STALE;
    -	bip->bli_flags &= ~(XFS_BLI_LOGGED | XFS_BLI_DIRTY);
    -	bip->bli_format.blf_flags &= ~XFS_BLI_INODE_BUF;
    -	bip->bli_format.blf_flags |= XFS_BLI_CANCEL;
    -	memset((char *)(bip->bli_format.blf_data_map), 0,
    -	      (bip->bli_format.blf_map_size * sizeof(uint)));
    -	lidp->lid_flags |= XFS_LID_DIRTY|XFS_LID_BUF_STALE;
    -	tp->t_flags |= XFS_TRANS_DIRTY;
    -	xfs_buftrace("XFS_BINVAL", bp);
    -	xfs_buf_item_trace("BINVAL", bip);
    -}
    -
    -/*
    - * This call is used to indicate that the buffer contains on-disk
    - * inodes which must be handled specially during recovery.  They
    - * require special handling because only the di_next_unlinked from
    - * the inodes in the buffer should be recovered.  The rest of the
    - * data in the buffer is logged via the inodes themselves.
    - *
    - * All we do is set the XFS_BLI_INODE_BUF flag in the buffer's log
    - * format structure so that we'll know what to do at recovery time.
    - */
    -/* ARGSUSED */
    -void
    -xfs_trans_inode_buf(
    -	xfs_trans_t	*tp,
    -	xfs_buf_t	*bp)
    -{
    -	xfs_buf_log_item_t	*bip;
    -
    -	ASSERT(XFS_BUF_ISBUSY(bp));
    -	ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp);
    -	ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL);
    -
    -	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
    -	ASSERT(atomic_read(&bip->bli_refcount) > 0);
    -
    -	bip->bli_format.blf_flags |= XFS_BLI_INODE_BUF;
    -}
    -
    -/*
    - * This call is used to indicate that the buffer is going to
    - * be staled and was an inode buffer. This means it gets
    - * special processing during unpin - where any inodes 
    - * associated with the buffer should be removed from ail.
    - * There is also special processing during recovery,
    - * any replay of the inodes in the buffer needs to be
    - * prevented as the buffer may have been reused.
    - */
    -void
    -xfs_trans_stale_inode_buf(
    -	xfs_trans_t	*tp,
    -	xfs_buf_t	*bp)
    -{
    -	xfs_buf_log_item_t	*bip;
    -
    -	ASSERT(XFS_BUF_ISBUSY(bp));
    -	ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp);
    -	ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL);
    -
    -	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
    -	ASSERT(atomic_read(&bip->bli_refcount) > 0);
    -
    -	bip->bli_flags |= XFS_BLI_STALE_INODE;
    -	bip->bli_item.li_cb = (void(*)(xfs_buf_t*,xfs_log_item_t*))
    -		xfs_buf_iodone;
    -}
    -
    -
    -
    -/*
    - * Mark the buffer as being one which contains newly allocated
    - * inodes.  We need to make sure that even if this buffer is
    - * relogged as an 'inode buf' we still recover all of the inode
    - * images in the face of a crash.  This works in coordination with
    - * xfs_buf_item_committed() to ensure that the buffer remains in the
    - * AIL at its original location even after it has been relogged.
    - */
    -/* ARGSUSED */
    -void
    -xfs_trans_inode_alloc_buf(
    -	xfs_trans_t	*tp,
    -	xfs_buf_t	*bp)
    -{
    -	xfs_buf_log_item_t	*bip;
    -
    -	ASSERT(XFS_BUF_ISBUSY(bp));
    -	ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp);
    -	ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL);
    -
    -	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
    -	ASSERT(atomic_read(&bip->bli_refcount) > 0);
    -
    -	bip->bli_flags |= XFS_BLI_INODE_ALLOC_BUF;
    -}
    -
    -
    -/*
    - * Similar to xfs_trans_inode_buf(), this marks the buffer as a cluster of
    - * dquots. However, unlike in inode buffer recovery, dquot buffers get
    - * recovered in their entirety. (Hence, no XFS_BLI_DQUOT_ALLOC_BUF flag).
    - * The only thing that makes dquot buffers different from regular
    - * buffers is that we must not replay dquot bufs when recovering
    - * if a _corresponding_ quotaoff has happened. We also have to distinguish
    - * between usr dquot bufs and grp dquot bufs, because usr and grp quotas
    - * can be turned off independently.
    - */
    -/* ARGSUSED */
    -void
    -xfs_trans_dquot_buf(
    -	xfs_trans_t	*tp,
    -	xfs_buf_t	*bp,
    -	uint		type)
    -{
    -	xfs_buf_log_item_t	*bip;
    -
    -	ASSERT(XFS_BUF_ISBUSY(bp));
    -	ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp);
    -	ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL);
    -	ASSERT(type == XFS_BLI_UDQUOT_BUF ||
    -	       type == XFS_BLI_PDQUOT_BUF ||
    -	       type == XFS_BLI_GDQUOT_BUF);
    -
    -	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
    -	ASSERT(atomic_read(&bip->bli_refcount) > 0);
    -
    -	bip->bli_format.blf_flags |= type;
    -}
    -
    -/*
    - * Check to see if a buffer matching the given parameters is already
    - * a part of the given transaction.  Only check the first, embedded
    - * chunk, since we don't want to spend all day scanning large transactions.
    - */
    -STATIC xfs_buf_t *
    -xfs_trans_buf_item_match(
    -	xfs_trans_t	*tp,
    -	xfs_buftarg_t	*target,
    -	xfs_daddr_t	blkno,
    -	int		len)
    -{
    -	xfs_log_item_chunk_t	*licp;
    -	xfs_log_item_desc_t	*lidp;
    -	xfs_buf_log_item_t	*blip;
    -	xfs_buf_t		*bp;
    -	int			i;
    -
    -	bp = NULL;
    -	len = BBTOB(len);
    -	licp = &tp->t_items;
    -	if (!XFS_LIC_ARE_ALL_FREE(licp)) {
    -		for (i = 0; i < licp->lic_unused; i++) {
    -			/*
    -			 * Skip unoccupied slots.
    -			 */
    -			if (XFS_LIC_ISFREE(licp, i)) {
    -				continue;
    -			}
    -
    -			lidp = XFS_LIC_SLOT(licp, i);
    -			blip = (xfs_buf_log_item_t *)lidp->lid_item;
    -			if (blip->bli_item.li_type != XFS_LI_BUF) {
    -				continue;
    -			}
    -
    -			bp = blip->bli_buf;
    -			if ((XFS_BUF_TARGET(bp) == target) &&
    -			    (XFS_BUF_ADDR(bp) == blkno) &&
    -			    (XFS_BUF_COUNT(bp) == len)) {
    -				/*
    -				 * We found it.  Break out and
    -				 * return the pointer to the buffer.
    -				 */
    -				break;
    -			} else {
    -				bp = NULL;
    -			}
    -		}
    -	}
    -	return bp;
    -}
    -
    -/*
    - * Check to see if a buffer matching the given parameters is already
    - * a part of the given transaction.  Check all the chunks, we
    - * want to be thorough.
    - */
    -STATIC xfs_buf_t *
    -xfs_trans_buf_item_match_all(
    -	xfs_trans_t	*tp,
    -	xfs_buftarg_t	*target,
    -	xfs_daddr_t	blkno,
    -	int		len)
    -{
    -	xfs_log_item_chunk_t	*licp;
    -	xfs_log_item_desc_t	*lidp;
    -	xfs_buf_log_item_t	*blip;
    -	xfs_buf_t		*bp;
    -	int			i;
    -
    -	bp = NULL;
    -	len = BBTOB(len);
    -	for (licp = &tp->t_items; licp != NULL; licp = licp->lic_next) {
    -		if (XFS_LIC_ARE_ALL_FREE(licp)) {
    -			ASSERT(licp == &tp->t_items);
    -			ASSERT(licp->lic_next == NULL);
    -			return NULL;
    -		}
    -		for (i = 0; i < licp->lic_unused; i++) {
    -			/*
    -			 * Skip unoccupied slots.
    -			 */
    -			if (XFS_LIC_ISFREE(licp, i)) {
    -				continue;
    -			}
    -
    -			lidp = XFS_LIC_SLOT(licp, i);
    -			blip = (xfs_buf_log_item_t *)lidp->lid_item;
    -			if (blip->bli_item.li_type != XFS_LI_BUF) {
    -				continue;
    -			}
    -
    -			bp = blip->bli_buf;
    -			if ((XFS_BUF_TARGET(bp) == target) &&
    -			    (XFS_BUF_ADDR(bp) == blkno) &&
    -			    (XFS_BUF_COUNT(bp) == len)) {
    -				/*
    -				 * We found it.  Break out and
    -				 * return the pointer to the buffer.
    -				 */
    -				return bp;
    -			}
    -		}
    -	}
    -	return NULL;
    -}
    -
    diff --git a/sys/gnu/fs/xfs/xfs_trans_extfree.c b/sys/gnu/fs/xfs/xfs_trans_extfree.c
    deleted file mode 100644
    index 7d7d627f25d..00000000000
    --- a/sys/gnu/fs/xfs/xfs_trans_extfree.c
    +++ /dev/null
    @@ -1,141 +0,0 @@
    -/*
    - * Copyright (c) 2000,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_dir.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_trans_priv.h"
    -#include "xfs_extfree_item.h"
    -
    -/*
    - * This routine is called to allocate an "extent free intention"
    - * log item that will hold nextents worth of extents.  The
    - * caller must use all nextents extents, because we are not
    - * flexible about this at all.
    - */
    -xfs_efi_log_item_t *
    -xfs_trans_get_efi(xfs_trans_t	*tp,
    -		  uint		nextents)
    -{
    -	xfs_efi_log_item_t	*efip;
    -
    -	ASSERT(tp != NULL);
    -	ASSERT(nextents > 0);
    -
    -	efip = xfs_efi_init(tp->t_mountp, nextents);
    -	ASSERT(efip != NULL);
    -
    -	/*
    -	 * Get a log_item_desc to point at the new item.
    -	 */
    -	(void) xfs_trans_add_item(tp, (xfs_log_item_t*)efip);
    -
    -	return (efip);
    -}
    -
    -/*
    - * This routine is called to indicate that the described
    - * extent is to be logged as needing to be freed.  It should
    - * be called once for each extent to be freed.
    - */
    -void
    -xfs_trans_log_efi_extent(xfs_trans_t		*tp,
    -			 xfs_efi_log_item_t	*efip,
    -			 xfs_fsblock_t		start_block,
    -			 xfs_extlen_t		ext_len)
    -{
    -	xfs_log_item_desc_t	*lidp;
    -	uint			next_extent;
    -	xfs_extent_t		*extp;
    -
    -	lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)efip);
    -	ASSERT(lidp != NULL);
    -
    -	tp->t_flags |= XFS_TRANS_DIRTY;
    -	lidp->lid_flags |= XFS_LID_DIRTY;
    -
    -	next_extent = efip->efi_next_extent;
    -	ASSERT(next_extent < efip->efi_format.efi_nextents);
    -	extp = &(efip->efi_format.efi_extents[next_extent]);
    -	extp->ext_start = start_block;
    -	extp->ext_len = ext_len;
    -	efip->efi_next_extent++;
    -}
    -
    -
    -/*
    - * This routine is called to allocate an "extent free done"
    - * log item that will hold nextents worth of extents.  The
    - * caller must use all nextents extents, because we are not
    - * flexible about this at all.
    - */
    -xfs_efd_log_item_t *
    -xfs_trans_get_efd(xfs_trans_t		*tp,
    -		  xfs_efi_log_item_t	*efip,
    -		  uint			nextents)
    -{
    -	xfs_efd_log_item_t	*efdp;
    -
    -	ASSERT(tp != NULL);
    -	ASSERT(nextents > 0);
    -
    -	efdp = xfs_efd_init(tp->t_mountp, efip, nextents);
    -	ASSERT(efdp != NULL);
    -
    -	/*
    -	 * Get a log_item_desc to point at the new item.
    -	 */
    -	(void) xfs_trans_add_item(tp, (xfs_log_item_t*)efdp);
    -
    -	return (efdp);
    -}
    -
    -/*
    - * This routine is called to indicate that the described
    - * extent is to be logged as having been freed.  It should
    - * be called once for each extent freed.
    - */
    -void
    -xfs_trans_log_efd_extent(xfs_trans_t		*tp,
    -			 xfs_efd_log_item_t	*efdp,
    -			 xfs_fsblock_t		start_block,
    -			 xfs_extlen_t		ext_len)
    -{
    -	xfs_log_item_desc_t	*lidp;
    -	uint			next_extent;
    -	xfs_extent_t		*extp;
    -
    -	lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)efdp);
    -	ASSERT(lidp != NULL);
    -
    -	tp->t_flags |= XFS_TRANS_DIRTY;
    -	lidp->lid_flags |= XFS_LID_DIRTY;
    -
    -	next_extent = efdp->efd_next_extent;
    -	ASSERT(next_extent < efdp->efd_format.efd_nextents);
    -	extp = &(efdp->efd_format.efd_extents[next_extent]);
    -	extp->ext_start = start_block;
    -	extp->ext_len = ext_len;
    -	efdp->efd_next_extent++;
    -}
    diff --git a/sys/gnu/fs/xfs/xfs_trans_inode.c b/sys/gnu/fs/xfs/xfs_trans_inode.c
    deleted file mode 100644
    index 7c5894d59f8..00000000000
    --- a/sys/gnu/fs/xfs/xfs_trans_inode.c
    +++ /dev/null
    @@ -1,310 +0,0 @@
    -/*
    - * Copyright (c) 2000,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_btree.h"
    -#include "xfs_ialloc.h"
    -#include "xfs_trans_priv.h"
    -#include "xfs_inode_item.h"
    -
    -#ifdef XFS_TRANS_DEBUG
    -STATIC void
    -xfs_trans_inode_broot_debug(
    -	xfs_inode_t	*ip);
    -#else
    -#define	xfs_trans_inode_broot_debug(ip)
    -#endif
    -
    -
    -/*
    - * Get and lock the inode for the caller if it is not already
    - * locked within the given transaction.  If it is already locked
    - * within the transaction, just increment its lock recursion count
    - * and return a pointer to it.
    - *
    - * For an inode to be locked in a transaction, the inode lock, as
    - * opposed to the io lock, must be taken exclusively.  This ensures
    - * that the inode can be involved in only 1 transaction at a time.
    - * Lock recursion is handled on the io lock, but only for lock modes
    - * of equal or lesser strength.  That is, you can recur on the io lock
    - * held EXCL with a SHARED request but not vice versa.  Also, if
    - * the inode is already a part of the transaction then you cannot
    - * go from not holding the io lock to having it EXCL or SHARED.
    - *
    - * Use the inode cache routine xfs_inode_incore() to find the inode
    - * if it is already owned by this transaction.
    - *
    - * If we don't already own the inode, use xfs_iget() to get it.
    - * Since the inode log item structure is embedded in the incore
    - * inode structure and is initialized when the inode is brought
    - * into memory, there is nothing to do with it here.
    - *
    - * If the given transaction pointer is NULL, just call xfs_iget().
    - * This simplifies code which must handle both cases.
    - */
    -int
    -xfs_trans_iget(
    -	xfs_mount_t	*mp,
    -	xfs_trans_t	*tp,
    -	xfs_ino_t	ino,
    -	uint		flags,
    -	uint		lock_flags,
    -	xfs_inode_t	**ipp)
    -{
    -	int			error;
    -	xfs_inode_t		*ip;
    -	xfs_inode_log_item_t	*iip;
    -
    -	/*
    -	 * If the transaction pointer is NULL, just call the normal
    -	 * xfs_iget().
    -	 */
    -	if (tp == NULL)
    -		return xfs_iget(mp, NULL, ino, flags, lock_flags, ipp, 0);
    -
    -	/*
    -	 * If we find the inode in core with this transaction
    -	 * pointer in its i_transp field, then we know we already
    -	 * have it locked.  In this case we just increment the lock
    -	 * recursion count and return the inode to the caller.
    -	 * Assert that the inode is already locked in the mode requested
    -	 * by the caller.  We cannot do lock promotions yet, so
    -	 * die if someone gets this wrong.
    -	 */
    -	if ((ip = xfs_inode_incore(tp->t_mountp, ino, tp)) != NULL) {
    -		/*
    -		 * Make sure that the inode lock is held EXCL and
    -		 * that the io lock is never upgraded when the inode
    -		 * is already a part of the transaction.
    -		 */
    -		ASSERT(ip->i_itemp != NULL);
    -		ASSERT(lock_flags & XFS_ILOCK_EXCL);
    -		ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
    -		ASSERT((!(lock_flags & XFS_IOLOCK_EXCL)) ||
    -		       ismrlocked(&ip->i_iolock, MR_UPDATE));
    -		ASSERT((!(lock_flags & XFS_IOLOCK_EXCL)) ||
    -		       (ip->i_itemp->ili_flags & XFS_ILI_IOLOCKED_EXCL));
    -		ASSERT((!(lock_flags & XFS_IOLOCK_SHARED)) ||
    -		       ismrlocked(&ip->i_iolock, (MR_UPDATE | MR_ACCESS)));
    -		ASSERT((!(lock_flags & XFS_IOLOCK_SHARED)) ||
    -		       (ip->i_itemp->ili_flags & XFS_ILI_IOLOCKED_ANY));
    -
    -		if (lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) {
    -			ip->i_itemp->ili_iolock_recur++;
    -		}
    -		if (lock_flags & XFS_ILOCK_EXCL) {
    -			ip->i_itemp->ili_ilock_recur++;
    -		}
    -		*ipp = ip;
    -		return 0;
    -	}
    -
    -	ASSERT(lock_flags & XFS_ILOCK_EXCL);
    -	error = xfs_iget(tp->t_mountp, tp, ino, flags, lock_flags, &ip, 0);
    -	if (error) {
    -		return error;
    -	}
    -	ASSERT(ip != NULL);
    -
    -	/*
    -	 * Get a log_item_desc to point at the new item.
    -	 */
    -	if (ip->i_itemp == NULL)
    -		xfs_inode_item_init(ip, mp);
    -	iip = ip->i_itemp;
    -	(void) xfs_trans_add_item(tp, (xfs_log_item_t *)(iip));
    -
    -	xfs_trans_inode_broot_debug(ip);
    -
    -	/*
    -	 * If the IO lock has been acquired, mark that in
    -	 * the inode log item so we'll know to unlock it
    -	 * when the transaction commits.
    -	 */
    -	ASSERT(iip->ili_flags == 0);
    -	if (lock_flags & XFS_IOLOCK_EXCL) {
    -		iip->ili_flags |= XFS_ILI_IOLOCKED_EXCL;
    -	} else if (lock_flags & XFS_IOLOCK_SHARED) {
    -		iip->ili_flags |= XFS_ILI_IOLOCKED_SHARED;
    -	}
    -
    -	/*
    -	 * Initialize i_transp so we can find it with xfs_inode_incore()
    -	 * above.
    -	 */
    -	ip->i_transp = tp;
    -
    -	*ipp = ip;
    -	return 0;
    -}
    -
    -/*
    - * Add the locked inode to the transaction.
    - * The inode must be locked, and it cannot be associated with any
    - * transaction.  The caller must specify the locks already held
    - * on the inode.
    - */
    -void
    -xfs_trans_ijoin(
    -	xfs_trans_t	*tp,
    -	xfs_inode_t	*ip,
    -	uint		lock_flags)
    -{
    -	xfs_inode_log_item_t	*iip;
    -
    -	ASSERT(ip->i_transp == NULL);
    -	ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
    -	ASSERT(lock_flags & XFS_ILOCK_EXCL);
    -	if (ip->i_itemp == NULL)
    -		xfs_inode_item_init(ip, ip->i_mount);
    -	iip = ip->i_itemp;
    -	ASSERT(iip->ili_flags == 0);
    -	ASSERT(iip->ili_ilock_recur == 0);
    -	ASSERT(iip->ili_iolock_recur == 0);
    -
    -	/*
    -	 * Get a log_item_desc to point at the new item.
    -	 */
    -	(void) xfs_trans_add_item(tp, (xfs_log_item_t*)(iip));
    -
    -	xfs_trans_inode_broot_debug(ip);
    -
    -	/*
    -	 * If the IO lock is already held, mark that in the inode log item.
    -	 */
    -	if (lock_flags & XFS_IOLOCK_EXCL) {
    -		iip->ili_flags |= XFS_ILI_IOLOCKED_EXCL;
    -	} else if (lock_flags & XFS_IOLOCK_SHARED) {
    -		iip->ili_flags |= XFS_ILI_IOLOCKED_SHARED;
    -	}
    -
    -	/*
    -	 * Initialize i_transp so we can find it with xfs_inode_incore()
    -	 * in xfs_trans_iget() above.
    -	 */
    -	ip->i_transp = tp;
    -}
    -
    -
    -
    -/*
    - * Mark the inode as not needing to be unlocked when the inode item's
    - * IOP_UNLOCK() routine is called.  The inode must already be locked
    - * and associated with the given transaction.
    - */
    -/*ARGSUSED*/
    -void
    -xfs_trans_ihold(
    -	xfs_trans_t	*tp,
    -	xfs_inode_t	*ip)
    -{
    -	ASSERT(ip->i_transp == tp);
    -	ASSERT(ip->i_itemp != NULL);
    -	ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
    -
    -	ip->i_itemp->ili_flags |= XFS_ILI_HOLD;
    -}
    -
    -
    -/*
    - * This is called to mark the fields indicated in fieldmask as needing
    - * to be logged when the transaction is committed.  The inode must
    - * already be associated with the given transaction.
    - *
    - * The values for fieldmask are defined in xfs_inode_item.h.  We always
    - * log all of the core inode if any of it has changed, and we always log
    - * all of the inline data/extents/b-tree root if any of them has changed.
    - */
    -void
    -xfs_trans_log_inode(
    -	xfs_trans_t	*tp,
    -	xfs_inode_t	*ip,
    -	uint		flags)
    -{
    -	xfs_log_item_desc_t	*lidp;
    -
    -	ASSERT(ip->i_transp == tp);
    -	ASSERT(ip->i_itemp != NULL);
    -	ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
    -
    -	lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)(ip->i_itemp));
    -	ASSERT(lidp != NULL);
    -
    -	tp->t_flags |= XFS_TRANS_DIRTY;
    -	lidp->lid_flags |= XFS_LID_DIRTY;
    -
    -	/*
    -	 * Always OR in the bits from the ili_last_fields field.
    -	 * This is to coordinate with the xfs_iflush() and xfs_iflush_done()
    -	 * routines in the eventual clearing of the ilf_fields bits.
    -	 * See the big comment in xfs_iflush() for an explanation of
    -	 * this coordination mechanism.
    -	 */
    -	flags |= ip->i_itemp->ili_last_fields;
    -	ip->i_itemp->ili_format.ilf_fields |= flags;
    -}
    -
    -#ifdef XFS_TRANS_DEBUG
    -/*
    - * Keep track of the state of the inode btree root to make sure we
    - * log it properly.
    - */
    -STATIC void
    -xfs_trans_inode_broot_debug(
    -	xfs_inode_t	*ip)
    -{
    -	xfs_inode_log_item_t	*iip;
    -
    -	ASSERT(ip->i_itemp != NULL);
    -	iip = ip->i_itemp;
    -	if (iip->ili_root_size != 0) {
    -		ASSERT(iip->ili_orig_root != NULL);
    -		kmem_free(iip->ili_orig_root, iip->ili_root_size);
    -		iip->ili_root_size = 0;
    -		iip->ili_orig_root = NULL;
    -	}
    -	if (ip->i_d.di_format == XFS_DINODE_FMT_BTREE) {
    -		ASSERT((ip->i_df.if_broot != NULL) &&
    -		       (ip->i_df.if_broot_bytes > 0));
    -		iip->ili_root_size = ip->i_df.if_broot_bytes;
    -		iip->ili_orig_root =
    -			(char*)kmem_alloc(iip->ili_root_size, KM_SLEEP);
    -		memcpy(iip->ili_orig_root, (char*)(ip->i_df.if_broot),
    -		      iip->ili_root_size);
    -	}
    -}
    -#endif
    diff --git a/sys/gnu/fs/xfs/xfs_trans_item.c b/sys/gnu/fs/xfs/xfs_trans_item.c
    deleted file mode 100644
    index 925fb3a8e6d..00000000000
    --- a/sys/gnu/fs/xfs/xfs_trans_item.c
    +++ /dev/null
    @@ -1,539 +0,0 @@
    -/*
    - * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_trans_priv.h"
    -
    -STATIC int	xfs_trans_unlock_chunk(xfs_log_item_chunk_t *,
    -					int, int, xfs_lsn_t);
    -
    -/*
    - * This is called to add the given log item to the transaction's
    - * list of log items.  It must find a free log item descriptor
    - * or allocate a new one and add the item to that descriptor.
    - * The function returns a pointer to item descriptor used to point
    - * to the new item.  The log item will now point to its new descriptor
    - * with its li_desc field.
    - */
    -xfs_log_item_desc_t *
    -xfs_trans_add_item(xfs_trans_t *tp, xfs_log_item_t *lip)
    -{
    -	xfs_log_item_desc_t	*lidp;
    -	xfs_log_item_chunk_t	*licp;
    -	int			i=0;
    -
    -	/*
    -	 * If there are no free descriptors, allocate a new chunk
    -	 * of them and put it at the front of the chunk list.
    -	 */
    -	if (tp->t_items_free == 0) {
    -		licp = (xfs_log_item_chunk_t*)
    -		       kmem_alloc(sizeof(xfs_log_item_chunk_t), KM_SLEEP);
    -		ASSERT(licp != NULL);
    -		/*
    -		 * Initialize the chunk, and then
    -		 * claim the first slot in the newly allocated chunk.
    -		 */
    -		XFS_LIC_INIT(licp);
    -		XFS_LIC_CLAIM(licp, 0);
    -		licp->lic_unused = 1;
    -		XFS_LIC_INIT_SLOT(licp, 0);
    -		lidp = XFS_LIC_SLOT(licp, 0);
    -
    -		/*
    -		 * Link in the new chunk and update the free count.
    -		 */
    -		licp->lic_next = tp->t_items.lic_next;
    -		tp->t_items.lic_next = licp;
    -		tp->t_items_free = XFS_LIC_NUM_SLOTS - 1;
    -
    -		/*
    -		 * Initialize the descriptor and the generic portion
    -		 * of the log item.
    -		 *
    -		 * Point the new slot at this item and return it.
    -		 * Also point the log item at its currently active
    -		 * descriptor and set the item's mount pointer.
    -		 */
    -		lidp->lid_item = lip;
    -		lidp->lid_flags = 0;
    -		lidp->lid_size = 0;
    -		lip->li_desc = lidp;
    -		lip->li_mountp = tp->t_mountp;
    -		return lidp;
    -	}
    -
    -	/*
    -	 * Find the free descriptor. It is somewhere in the chunklist
    -	 * of descriptors.
    -	 */
    -	licp = &tp->t_items;
    -	while (licp != NULL) {
    -		if (XFS_LIC_VACANCY(licp)) {
    -			if (licp->lic_unused <= XFS_LIC_MAX_SLOT) {
    -				i = licp->lic_unused;
    -				ASSERT(XFS_LIC_ISFREE(licp, i));
    -				break;
    -			}
    -			for (i = 0; i <= XFS_LIC_MAX_SLOT; i++) {
    -				if (XFS_LIC_ISFREE(licp, i))
    -					break;
    -			}
    -			ASSERT(i <= XFS_LIC_MAX_SLOT);
    -			break;
    -		}
    -		licp = licp->lic_next;
    -	}
    -	ASSERT(licp != NULL);
    -	/*
    -	 * If we find a free descriptor, claim it,
    -	 * initialize it, and return it.
    -	 */
    -	XFS_LIC_CLAIM(licp, i);
    -	if (licp->lic_unused <= i) {
    -		licp->lic_unused = i + 1;
    -		XFS_LIC_INIT_SLOT(licp, i);
    -	}
    -	lidp = XFS_LIC_SLOT(licp, i);
    -	tp->t_items_free--;
    -	lidp->lid_item = lip;
    -	lidp->lid_flags = 0;
    -	lidp->lid_size = 0;
    -	lip->li_desc = lidp;
    -	lip->li_mountp = tp->t_mountp;
    -	return lidp;
    -}
    -
    -/*
    - * Free the given descriptor.
    - *
    - * This requires setting the bit in the chunk's free mask corresponding
    - * to the given slot.
    - */
    -void
    -xfs_trans_free_item(xfs_trans_t	*tp, xfs_log_item_desc_t *lidp)
    -{
    -	uint			slot;
    -	xfs_log_item_chunk_t	*licp;
    -	xfs_log_item_chunk_t	**licpp;
    -
    -	slot = XFS_LIC_DESC_TO_SLOT(lidp);
    -	licp = XFS_LIC_DESC_TO_CHUNK(lidp);
    -	XFS_LIC_RELSE(licp, slot);
    -	lidp->lid_item->li_desc = NULL;
    -	tp->t_items_free++;
    -
    -	/*
    -	 * If there are no more used items in the chunk and this is not
    -	 * the chunk embedded in the transaction structure, then free
    -	 * the chunk. First pull it from the chunk list and then
    -	 * free it back to the heap.  We didn't bother with a doubly
    -	 * linked list here because the lists should be very short
    -	 * and this is not a performance path.  It's better to save
    -	 * the memory of the extra pointer.
    -	 *
    -	 * Also decrement the transaction structure's count of free items
    -	 * by the number in a chunk since we are freeing an empty chunk.
    -	 */
    -	if (XFS_LIC_ARE_ALL_FREE(licp) && (licp != &(tp->t_items))) {
    -		licpp = &(tp->t_items.lic_next);
    -		while (*licpp != licp) {
    -			ASSERT(*licpp != NULL);
    -			licpp = &((*licpp)->lic_next);
    -		}
    -		*licpp = licp->lic_next;
    -		kmem_free(licp, sizeof(xfs_log_item_chunk_t));
    -		tp->t_items_free -= XFS_LIC_NUM_SLOTS;
    -	}
    -}
    -
    -/*
    - * This is called to find the descriptor corresponding to the given
    - * log item.  It returns a pointer to the descriptor.
    - * The log item MUST have a corresponding descriptor in the given
    - * transaction.  This routine does not return NULL, it panics.
    - *
    - * The descriptor pointer is kept in the log item's li_desc field.
    - * Just return it.
    - */
    -/*ARGSUSED*/
    -xfs_log_item_desc_t *
    -xfs_trans_find_item(xfs_trans_t	*tp, xfs_log_item_t *lip)
    -{
    -	ASSERT(lip->li_desc != NULL);
    -
    -	return lip->li_desc;
    -}
    -
    -
    -/*
    - * Return a pointer to the first descriptor in the chunk list.
    - * This does not return NULL if there are none, it panics.
    - *
    - * The first descriptor must be in either the first or second chunk.
    - * This is because the only chunk allowed to be empty is the first.
    - * All others are freed when they become empty.
    - *
    - * At some point this and xfs_trans_next_item() should be optimized
    - * to quickly look at the mask to determine if there is anything to
    - * look at.
    - */
    -xfs_log_item_desc_t *
    -xfs_trans_first_item(xfs_trans_t *tp)
    -{
    -	xfs_log_item_chunk_t	*licp;
    -	int			i;
    -
    -	licp = &tp->t_items;
    -	/*
    -	 * If it's not in the first chunk, skip to the second.
    -	 */
    -	if (XFS_LIC_ARE_ALL_FREE(licp)) {
    -		licp = licp->lic_next;
    -	}
    -
    -	/*
    -	 * Return the first non-free descriptor in the chunk.
    -	 */
    -	ASSERT(!XFS_LIC_ARE_ALL_FREE(licp));
    -	for (i = 0; i < licp->lic_unused; i++) {
    -		if (XFS_LIC_ISFREE(licp, i)) {
    -			continue;
    -		}
    -
    -		return XFS_LIC_SLOT(licp, i);
    -	}
    -	cmn_err(CE_WARN, "xfs_trans_first_item() -- no first item");
    -	return NULL;
    -}
    -
    -
    -/*
    - * Given a descriptor, return the next descriptor in the chunk list.
    - * This returns NULL if there are no more used descriptors in the list.
    - *
    - * We do this by first locating the chunk in which the descriptor resides,
    - * and then scanning forward in the chunk and the list for the next
    - * used descriptor.
    - */
    -/*ARGSUSED*/
    -xfs_log_item_desc_t *
    -xfs_trans_next_item(xfs_trans_t *tp, xfs_log_item_desc_t *lidp)
    -{
    -	xfs_log_item_chunk_t	*licp;
    -	int			i;
    -
    -	licp = XFS_LIC_DESC_TO_CHUNK(lidp);
    -
    -	/*
    -	 * First search the rest of the chunk. The for loop keeps us
    -	 * from referencing things beyond the end of the chunk.
    -	 */
    -	for (i = (int)XFS_LIC_DESC_TO_SLOT(lidp) + 1; i < licp->lic_unused; i++) {
    -		if (XFS_LIC_ISFREE(licp, i)) {
    -			continue;
    -		}
    -
    -		return XFS_LIC_SLOT(licp, i);
    -	}
    -
    -	/*
    -	 * Now search the next chunk.  It must be there, because the
    -	 * next chunk would have been freed if it were empty.
    -	 * If there is no next chunk, return NULL.
    -	 */
    -	if (licp->lic_next == NULL) {
    -		return NULL;
    -	}
    -
    -	licp = licp->lic_next;
    -	ASSERT(!XFS_LIC_ARE_ALL_FREE(licp));
    -	for (i = 0; i < licp->lic_unused; i++) {
    -		if (XFS_LIC_ISFREE(licp, i)) {
    -			continue;
    -		}
    -
    -		return XFS_LIC_SLOT(licp, i);
    -	}
    -	ASSERT(0);
    -	/* NOTREACHED */
    -	return NULL; /* keep gcc quite */
    -}
    -
    -/*
    - * This is called to unlock all of the items of a transaction and to free
    - * all the descriptors of that transaction.
    - *
    - * It walks the list of descriptors and unlocks each item.  It frees
    - * each chunk except that embedded in the transaction as it goes along.
    - */
    -void
    -xfs_trans_free_items(
    -	xfs_trans_t	*tp,
    -	int		flags)
    -{
    -	xfs_log_item_chunk_t	*licp;
    -	xfs_log_item_chunk_t	*next_licp;
    -	int			abort;
    -
    -	abort = flags & XFS_TRANS_ABORT;
    -	licp = &tp->t_items;
    -	/*
    -	 * Special case the embedded chunk so we don't free it below.
    -	 */
    -	if (!XFS_LIC_ARE_ALL_FREE(licp)) {
    -		(void) xfs_trans_unlock_chunk(licp, 1, abort, NULLCOMMITLSN);
    -		XFS_LIC_ALL_FREE(licp);
    -		licp->lic_unused = 0;
    -	}
    -	licp = licp->lic_next;
    -
    -	/*
    -	 * Unlock each item in each chunk and free the chunks.
    -	 */
    -	while (licp != NULL) {
    -		ASSERT(!XFS_LIC_ARE_ALL_FREE(licp));
    -		(void) xfs_trans_unlock_chunk(licp, 1, abort, NULLCOMMITLSN);
    -		next_licp = licp->lic_next;
    -		kmem_free(licp, sizeof(xfs_log_item_chunk_t));
    -		licp = next_licp;
    -	}
    -
    -	/*
    -	 * Reset the transaction structure's free item count.
    -	 */
    -	tp->t_items_free = XFS_LIC_NUM_SLOTS;
    -	tp->t_items.lic_next = NULL;
    -}
    -
    -
    -
    -/*
    - * This is called to unlock the items associated with a transaction.
    - * Items which were not logged should be freed.
    - * Those which were logged must still be tracked so they can be unpinned
    - * when the transaction commits.
    - */
    -void
    -xfs_trans_unlock_items(xfs_trans_t *tp, xfs_lsn_t commit_lsn)
    -{
    -	xfs_log_item_chunk_t	*licp;
    -	xfs_log_item_chunk_t	*next_licp;
    -	xfs_log_item_chunk_t	**licpp;
    -	int			freed;
    -
    -	freed = 0;
    -	licp = &tp->t_items;
    -
    -	/*
    -	 * Special case the embedded chunk so we don't free.
    -	 */
    -	if (!XFS_LIC_ARE_ALL_FREE(licp)) {
    -		freed = xfs_trans_unlock_chunk(licp, 0, 0, commit_lsn);
    -	}
    -	licpp = &(tp->t_items.lic_next);
    -	licp = licp->lic_next;
    -
    -	/*
    -	 * Unlock each item in each chunk, free non-dirty descriptors,
    -	 * and free empty chunks.
    -	 */
    -	while (licp != NULL) {
    -		ASSERT(!XFS_LIC_ARE_ALL_FREE(licp));
    -		freed += xfs_trans_unlock_chunk(licp, 0, 0, commit_lsn);
    -		next_licp = licp->lic_next;
    -		if (XFS_LIC_ARE_ALL_FREE(licp)) {
    -			*licpp = next_licp;
    -			kmem_free(licp, sizeof(xfs_log_item_chunk_t));
    -			freed -= XFS_LIC_NUM_SLOTS;
    -		} else {
    -			licpp = &(licp->lic_next);
    -		}
    -		ASSERT(*licpp == next_licp);
    -		licp = next_licp;
    -	}
    -
    -	/*
    -	 * Fix the free descriptor count in the transaction.
    -	 */
    -	tp->t_items_free += freed;
    -}
    -
    -/*
    - * Unlock each item pointed to by a descriptor in the given chunk.
    - * Stamp the commit lsn into each item if necessary.
    - * Free descriptors pointing to items which are not dirty if freeing_chunk
    - * is zero. If freeing_chunk is non-zero, then we need to unlock all
    - * items in the chunk.
    - * 
    - * Return the number of descriptors freed.
    - */
    -STATIC int
    -xfs_trans_unlock_chunk(
    -	xfs_log_item_chunk_t	*licp,
    -	int			freeing_chunk,
    -	int			abort,
    -	xfs_lsn_t		commit_lsn)
    -{
    -	xfs_log_item_desc_t	*lidp;
    -	xfs_log_item_t		*lip;
    -	int			i;
    -	int			freed;
    -
    -	freed = 0;
    -	lidp = licp->lic_descs;
    -	for (i = 0; i < licp->lic_unused; i++, lidp++) {
    -		if (XFS_LIC_ISFREE(licp, i)) {
    -			continue;
    -		}
    -		lip = lidp->lid_item;
    -		lip->li_desc = NULL;
    -
    -		if (commit_lsn != NULLCOMMITLSN)
    -			IOP_COMMITTING(lip, commit_lsn);
    -		if (abort)
    -			lip->li_flags |= XFS_LI_ABORTED;
    -		IOP_UNLOCK(lip);
    -
    -		/*
    -		 * Free the descriptor if the item is not dirty
    -		 * within this transaction and the caller is not
    -		 * going to just free the entire thing regardless.
    -		 */
    -		if (!(freeing_chunk) &&
    -		    (!(lidp->lid_flags & XFS_LID_DIRTY) || abort)) {
    -			XFS_LIC_RELSE(licp, i);
    -			freed++;
    -		}
    -	}
    -
    -	return freed;
    -}
    -
    -
    -/*
    - * This is called to add the given busy item to the transaction's
    - * list of busy items.  It must find a free busy item descriptor
    - * or allocate a new one and add the item to that descriptor.
    - * The function returns a pointer to busy descriptor used to point
    - * to the new busy entry.  The log busy entry will now point to its new
    - * descriptor with its ???? field.
    - */
    -xfs_log_busy_slot_t *
    -xfs_trans_add_busy(xfs_trans_t *tp, xfs_agnumber_t ag, xfs_extlen_t idx)
    -{
    -	xfs_log_busy_chunk_t	*lbcp;
    -	xfs_log_busy_slot_t	*lbsp;
    -	int			i=0;
    -
    -	/*
    -	 * If there are no free descriptors, allocate a new chunk
    -	 * of them and put it at the front of the chunk list.
    -	 */
    -	if (tp->t_busy_free == 0) {
    -		lbcp = (xfs_log_busy_chunk_t*)
    -		       kmem_alloc(sizeof(xfs_log_busy_chunk_t), KM_SLEEP);
    -		ASSERT(lbcp != NULL);
    -		/*
    -		 * Initialize the chunk, and then
    -		 * claim the first slot in the newly allocated chunk.
    -		 */
    -		XFS_LBC_INIT(lbcp);
    -		XFS_LBC_CLAIM(lbcp, 0);
    -		lbcp->lbc_unused = 1;
    -		lbsp = XFS_LBC_SLOT(lbcp, 0);
    -
    -		/*
    -		 * Link in the new chunk and update the free count.
    -		 */
    -		lbcp->lbc_next = tp->t_busy.lbc_next;
    -		tp->t_busy.lbc_next = lbcp;
    -		tp->t_busy_free = XFS_LIC_NUM_SLOTS - 1;
    -
    -		/*
    -		 * Initialize the descriptor and the generic portion
    -		 * of the log item.
    -		 *
    -		 * Point the new slot at this item and return it.
    -		 * Also point the log item at its currently active
    -		 * descriptor and set the item's mount pointer.
    -		 */
    -		lbsp->lbc_ag = ag;
    -		lbsp->lbc_idx = idx;
    -		return lbsp;
    -	}
    -
    -	/*
    -	 * Find the free descriptor. It is somewhere in the chunklist
    -	 * of descriptors.
    -	 */
    -	lbcp = &tp->t_busy;
    -	while (lbcp != NULL) {
    -		if (XFS_LBC_VACANCY(lbcp)) {
    -			if (lbcp->lbc_unused <= XFS_LBC_MAX_SLOT) {
    -				i = lbcp->lbc_unused;
    -				break;
    -			} else {
    -				/* out-of-order vacancy */
    -				printk("OOO vacancy lbcp 0x%p\n", lbcp);
    -				ASSERT(0);
    -			}
    -		}
    -		lbcp = lbcp->lbc_next;
    -	}
    -	ASSERT(lbcp != NULL);
    -	/*
    -	 * If we find a free descriptor, claim it,
    -	 * initialize it, and return it.
    -	 */
    -	XFS_LBC_CLAIM(lbcp, i);
    -	if (lbcp->lbc_unused <= i) {
    -		lbcp->lbc_unused = i + 1;
    -	}
    -	lbsp = XFS_LBC_SLOT(lbcp, i);
    -	tp->t_busy_free--;
    -	lbsp->lbc_ag = ag;
    -	lbsp->lbc_idx = idx;
    -	return lbsp;
    -}
    -
    -
    -/*
    - * xfs_trans_free_busy
    - * Free all of the busy lists from a transaction
    - */
    -void
    -xfs_trans_free_busy(xfs_trans_t *tp)
    -{
    -	xfs_log_busy_chunk_t	*lbcp;
    -	xfs_log_busy_chunk_t	*lbcq;
    -
    -	lbcp = tp->t_busy.lbc_next;
    -	while (lbcp != NULL) {
    -		lbcq = lbcp->lbc_next;
    -		kmem_free(lbcp, sizeof(xfs_log_busy_chunk_t));
    -		lbcp = lbcq;
    -	}
    -
    -	XFS_LBC_INIT(&tp->t_busy);
    -	tp->t_busy.lbc_unused = 0;
    -}
    diff --git a/sys/gnu/fs/xfs/xfs_trans_priv.h b/sys/gnu/fs/xfs/xfs_trans_priv.h
    deleted file mode 100644
    index f68856a7ef6..00000000000
    --- a/sys/gnu/fs/xfs/xfs_trans_priv.h
    +++ /dev/null
    @@ -1,61 +0,0 @@
    -/*
    - * Copyright (c) 2000,2002,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_TRANS_PRIV_H__
    -#define	__XFS_TRANS_PRIV_H__
    -
    -struct xfs_log_item;
    -struct xfs_log_item_desc;
    -struct xfs_mount;
    -struct xfs_trans;
    -
    -/*
    - * From xfs_trans_item.c
    - */
    -struct xfs_log_item_desc	*xfs_trans_add_item(struct xfs_trans *,
    -					    struct xfs_log_item *);
    -void				xfs_trans_free_item(struct xfs_trans *,
    -					    struct xfs_log_item_desc *);
    -struct xfs_log_item_desc	*xfs_trans_find_item(struct xfs_trans *,
    -					     struct xfs_log_item *);
    -struct xfs_log_item_desc	*xfs_trans_first_item(struct xfs_trans *);
    -struct xfs_log_item_desc	*xfs_trans_next_item(struct xfs_trans *,
    -					     struct xfs_log_item_desc *);
    -void				xfs_trans_free_items(struct xfs_trans *, int);
    -void				xfs_trans_unlock_items(struct xfs_trans *,
    -							xfs_lsn_t);
    -void				xfs_trans_free_busy(xfs_trans_t *tp);
    -#if 0
    -xfs_log_busy_slot_t		*xfs_trans_add_busy(xfs_trans_t *tp,
    -						    xfs_agnumber_t ag,
    -						    xfs_extlen_t idx);
    -#endif
    -
    -/*
    - * From xfs_trans_ail.c
    - */
    -void			xfs_trans_update_ail(struct xfs_mount *,
    -				     struct xfs_log_item *, xfs_lsn_t,
    -				     unsigned long);
    -void			xfs_trans_delete_ail(struct xfs_mount *,
    -				     struct xfs_log_item *, unsigned long);
    -struct xfs_log_item	*xfs_trans_first_ail(struct xfs_mount *, int *);
    -struct xfs_log_item	*xfs_trans_next_ail(struct xfs_mount *,
    -				     struct xfs_log_item *, int *, int *);
    -
    -
    -#endif	/* __XFS_TRANS_PRIV_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_trans_space.h b/sys/gnu/fs/xfs/xfs_trans_space.h
    deleted file mode 100644
    index 7fe3792b18d..00000000000
    --- a/sys/gnu/fs/xfs/xfs_trans_space.h
    +++ /dev/null
    @@ -1,91 +0,0 @@
    -/*
    - * Copyright (c) 2000,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_TRANS_SPACE_H__
    -#define __XFS_TRANS_SPACE_H__
    -
    -/*
    - * Components of space reservations.
    - */
    -#define XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp)    \
    -		(((mp)->m_alloc_mxr[0]) - ((mp)->m_alloc_mnr[0]))
    -#define	XFS_EXTENTADD_SPACE_RES(mp,w)	(XFS_BM_MAXLEVELS(mp,w) - 1)
    -#define XFS_NEXTENTADD_SPACE_RES(mp,b,w)\
    -	(((b + XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp) - 1) / \
    -	  XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp)) * \
    -	  XFS_EXTENTADD_SPACE_RES(mp,w))
    -#define	XFS_DAENTER_1B(mp,w)	((w) == XFS_DATA_FORK ? (mp)->m_dirblkfsbs : 1)
    -#define	XFS_DAENTER_DBS(mp,w)	\
    -	(XFS_DA_NODE_MAXDEPTH + \
    -	 ((XFS_DIR_IS_V2(mp) && (w) == XFS_DATA_FORK) ? 2 : 0))
    -#define	XFS_DAENTER_BLOCKS(mp,w)	\
    -	(XFS_DAENTER_1B(mp,w) * XFS_DAENTER_DBS(mp,w))
    -#define	XFS_DAENTER_BMAP1B(mp,w)	\
    -	XFS_NEXTENTADD_SPACE_RES(mp, XFS_DAENTER_1B(mp, w), w)
    -#define	XFS_DAENTER_BMAPS(mp,w)		\
    -	(XFS_DAENTER_DBS(mp,w) * XFS_DAENTER_BMAP1B(mp,w))
    -#define	XFS_DAENTER_SPACE_RES(mp,w)	\
    -	(XFS_DAENTER_BLOCKS(mp,w) + XFS_DAENTER_BMAPS(mp,w))
    -#define	XFS_DAREMOVE_SPACE_RES(mp,w)	XFS_DAENTER_BMAPS(mp,w)
    -#define	XFS_DIRENTER_MAX_SPLIT(mp,nl)	\
    -	(((mp)->m_sb.sb_blocksize == 512 && \
    -	  XFS_DIR_IS_V1(mp) && \
    -	  (nl) >= XFS_DIR_LEAF_CAN_DOUBLE_SPLIT_LEN) ? 2 : 1)
    -#define	XFS_DIRENTER_SPACE_RES(mp,nl)	\
    -	(XFS_DAENTER_SPACE_RES(mp, XFS_DATA_FORK) * \
    -	 XFS_DIRENTER_MAX_SPLIT(mp,nl))
    -#define	XFS_DIRREMOVE_SPACE_RES(mp)	\
    -	XFS_DAREMOVE_SPACE_RES(mp, XFS_DATA_FORK)
    -#define	XFS_IALLOC_SPACE_RES(mp)	\
    -	(XFS_IALLOC_BLOCKS(mp) + XFS_IN_MAXLEVELS(mp)-1)
    -
    -/*
    - * Space reservation values for various transactions.
    - */
    -#define	XFS_ADDAFORK_SPACE_RES(mp)	\
    -	((mp)->m_dirblkfsbs + \
    -	 (XFS_DIR_IS_V1(mp) ? 0 : XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK)))
    -#define	XFS_ATTRRM_SPACE_RES(mp)	\
    -	XFS_DAREMOVE_SPACE_RES(mp, XFS_ATTR_FORK)
    -/* This macro is not used - see inline code in xfs_attr_set */
    -#define	XFS_ATTRSET_SPACE_RES(mp, v)	\
    -	(XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK) + XFS_B_TO_FSB(mp, v))
    -#define	XFS_CREATE_SPACE_RES(mp,nl)	\
    -	(XFS_IALLOC_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl))
    -#define	XFS_DIOSTRAT_SPACE_RES(mp, v)	\
    -	(XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK) + (v))
    -#define	XFS_GROWFS_SPACE_RES(mp)	\
    -	(2 * XFS_AG_MAXLEVELS(mp))
    -#define	XFS_GROWFSRT_SPACE_RES(mp,b)	\
    -	((b) + XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK))
    -#define	XFS_LINK_SPACE_RES(mp,nl)	\
    -	XFS_DIRENTER_SPACE_RES(mp,nl)
    -#define	XFS_MKDIR_SPACE_RES(mp,nl)	\
    -	(XFS_IALLOC_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl))
    -#define	XFS_QM_DQALLOC_SPACE_RES(mp)	\
    -	(XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK) + \
    -	 XFS_DQUOT_CLUSTER_SIZE_FSB)
    -#define	XFS_QM_QINOCREATE_SPACE_RES(mp)	\
    -	XFS_IALLOC_SPACE_RES(mp)
    -#define	XFS_REMOVE_SPACE_RES(mp)	\
    -	XFS_DIRREMOVE_SPACE_RES(mp)
    -#define	XFS_RENAME_SPACE_RES(mp,nl)	\
    -	(XFS_DIRREMOVE_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl))
    -#define	XFS_SYMLINK_SPACE_RES(mp,nl,b)	\
    -	(XFS_IALLOC_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl) + (b))
    -
    -#endif	/* __XFS_TRANS_SPACE_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_types.h b/sys/gnu/fs/xfs/xfs_types.h
    deleted file mode 100644
    index cce9a5f43e5..00000000000
    --- a/sys/gnu/fs/xfs/xfs_types.h
    +++ /dev/null
    @@ -1,179 +0,0 @@
    -/*
    - * Copyright (c) 2000-2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_TYPES_H__
    -#define	__XFS_TYPES_H__
    -
    -#ifdef __KERNEL__
    -
    -/*
    - * POSIX Extensions
    - */
    -typedef unsigned char		uchar_t;
    -typedef unsigned short		ushort_t;
    -typedef unsigned int		uint_t;
    -typedef unsigned long		ulong_t;
    -
    -/*
    - * Additional type declarations for XFS
    - */
    -#ifndef __FreeBSD__
    -typedef signed char		__int8_t;
    -typedef unsigned char		__uint8_t;
    -typedef signed short int	__int16_t;
    -typedef unsigned short int	__uint16_t;
    -typedef signed int		__int32_t;
    -typedef unsigned int		__uint32_t;
    -typedef signed long long int	__int64_t;
    -typedef unsigned long long int	__uint64_t;
    -
    -typedef enum { B_FALSE,B_TRUE }	boolean_t;
    -#endif 
    -
    -typedef __uint32_t		prid_t;		/* project ID */
    -typedef __uint32_t		inst_t;		/* an instruction */
    -
    -typedef __s64			xfs_off_t;	/*  type */
    -typedef __u64			xfs_ino_t;	/*  type */
    -typedef __s64			xfs_daddr_t;	/*  type */
    -typedef char *			xfs_caddr_t;	/*  type */
    -typedef __u32			xfs_dev_t;
    -typedef __u32			xfs_nlink_t;
    -
    -/* __psint_t is the same size as a pointer */
    -#if (BITS_PER_LONG == 32)
    -typedef __int32_t __psint_t;
    -typedef __uint32_t __psunsigned_t;
    -#elif (BITS_PER_LONG == 64)
    -typedef __int64_t __psint_t;
    -typedef __uint64_t __psunsigned_t;
    -#else
    -#error BITS_PER_LONG must be 32 or 64
    -#endif
    -
    -#endif	/* __KERNEL__ */
    -
    -typedef __uint32_t	xfs_agblock_t;	/* blockno in alloc. group */
    -typedef	__uint32_t	xfs_extlen_t;	/* extent length in blocks */
    -typedef	__uint32_t	xfs_agnumber_t;	/* allocation group number */
    -typedef __int32_t	xfs_extnum_t;	/* # of extents in a file */
    -typedef __int16_t	xfs_aextnum_t;	/* # extents in an attribute fork */
    -typedef	__int64_t	xfs_fsize_t;	/* bytes in a file */
    -typedef __uint64_t	xfs_ufsize_t;	/* unsigned bytes in a file */
    -
    -typedef	__int32_t	xfs_suminfo_t;	/* type of bitmap summary info */
    -typedef	__int32_t	xfs_rtword_t;	/* word type for bitmap manipulations */
    -
    -typedef	__int64_t	xfs_lsn_t;	/* log sequence number */
    -typedef	__int32_t	xfs_tid_t;	/* transaction identifier */
    -
    -typedef	__uint32_t	xfs_dablk_t;	/* dir/attr block number (in file) */
    -typedef	__uint32_t	xfs_dahash_t;	/* dir/attr hash value */
    -
    -typedef __uint16_t	xfs_prid_t;	/* prid_t truncated to 16bits in XFS */
    -
    -/*
    - * These types are 64 bits on disk but are either 32 or 64 bits in memory.
    - * Disk based types:
    - */
    -typedef __uint64_t	xfs_dfsbno_t;	/* blockno in filesystem (agno|agbno) */
    -typedef __uint64_t	xfs_drfsbno_t;	/* blockno in filesystem (raw) */
    -typedef	__uint64_t	xfs_drtbno_t;	/* extent (block) in realtime area */
    -typedef	__uint64_t	xfs_dfiloff_t;	/* block number in a file */
    -typedef	__uint64_t	xfs_dfilblks_t;	/* number of blocks in a file */
    -
    -/*
    - * Memory based types are conditional.
    - */
    -#if XFS_BIG_BLKNOS
    -typedef	__uint64_t	xfs_fsblock_t;	/* blockno in filesystem (agno|agbno) */
    -typedef __uint64_t	xfs_rfsblock_t;	/* blockno in filesystem (raw) */
    -typedef __uint64_t	xfs_rtblock_t;	/* extent (block) in realtime area */
    -typedef	__int64_t	xfs_srtblock_t;	/* signed version of xfs_rtblock_t */
    -#else
    -typedef	__uint32_t	xfs_fsblock_t;	/* blockno in filesystem (agno|agbno) */
    -typedef __uint32_t	xfs_rfsblock_t;	/* blockno in filesystem (raw) */
    -typedef __uint32_t	xfs_rtblock_t;	/* extent (block) in realtime area */
    -typedef	__int32_t	xfs_srtblock_t;	/* signed version of xfs_rtblock_t */
    -#endif
    -typedef __uint64_t	xfs_fileoff_t;	/* block number in a file */
    -typedef __int64_t	xfs_sfiloff_t;	/* signed block number in a file */
    -typedef __uint64_t	xfs_filblks_t;	/* number of blocks in a file */
    -
    -typedef __uint8_t	xfs_arch_t;	/* architecture of an xfs fs */
    -
    -/*
    - * Null values for the types.
    - */
    -#define	NULLDFSBNO	((xfs_dfsbno_t)-1)
    -#define	NULLDRFSBNO	((xfs_drfsbno_t)-1)
    -#define	NULLDRTBNO	((xfs_drtbno_t)-1)
    -#define	NULLDFILOFF	((xfs_dfiloff_t)-1)
    -
    -#define	NULLFSBLOCK	((xfs_fsblock_t)-1)
    -#define	NULLRFSBLOCK	((xfs_rfsblock_t)-1)
    -#define	NULLRTBLOCK	((xfs_rtblock_t)-1)
    -#define	NULLFILEOFF	((xfs_fileoff_t)-1)
    -
    -#define	NULLAGBLOCK	((xfs_agblock_t)-1)
    -#define	NULLAGNUMBER	((xfs_agnumber_t)-1)
    -#define	NULLEXTNUM	((xfs_extnum_t)-1)
    -
    -#define NULLCOMMITLSN	((xfs_lsn_t)-1)
    -
    -/*
    - * Max values for extlen, extnum, aextnum.
    - */
    -#define	MAXEXTLEN	((xfs_extlen_t)0x001fffff)	/* 21 bits */
    -#define	MAXEXTNUM	((xfs_extnum_t)0x7fffffff)	/* signed int */
    -#define	MAXAEXTNUM	((xfs_aextnum_t)0x7fff)		/* signed short */
    -
    -/*
    - * Min numbers of data/attr fork btree root pointers.
    - */
    -#define MINDBTPTRS	3
    -#define MINABTPTRS	2
    -
    -/*
    - * MAXNAMELEN is the length (including the terminating null) of
    - * the longest permissible file (component) name.
    - */
    -#define MAXNAMELEN	256
    -
    -typedef struct xfs_dirent {		/* data from readdir() */
    -	xfs_ino_t	d_ino;		/* inode number of entry */
    -	xfs_off_t	d_off;		/* offset of disk directory entry */
    -	unsigned short	d_reclen;	/* length of this record */
    -	char		d_name[1];	/* name of file */
    -} xfs_dirent_t;
    -
    -#define DIRENTBASESIZE		(((xfs_dirent_t *)0)->d_name - (char *)0)
    -#define DIRENTSIZE(namelen)	\
    -	((DIRENTBASESIZE + (namelen) + \
    -		sizeof(xfs_off_t)) & ~(sizeof(xfs_off_t) - 1))
    -
    -typedef enum {
    -	XFS_LOOKUP_EQi, XFS_LOOKUP_LEi, XFS_LOOKUP_GEi
    -} xfs_lookup_t;
    -
    -typedef enum {
    -	XFS_BTNUM_BNOi, XFS_BTNUM_CNTi, XFS_BTNUM_BMAPi, XFS_BTNUM_INOi,
    -	XFS_BTNUM_MAX
    -} xfs_btnum_t;
    -
    -#endif	/* __XFS_TYPES_H__ */
    -
    diff --git a/sys/gnu/fs/xfs/xfs_utils.c b/sys/gnu/fs/xfs/xfs_utils.c
    deleted file mode 100644
    index 3feec7845db..00000000000
    --- a/sys/gnu/fs/xfs/xfs_utils.c
    +++ /dev/null
    @@ -1,472 +0,0 @@
    -/*
    - * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_inode_item.h"
    -#include "xfs_bmap.h"
    -#include "xfs_error.h"
    -#include "xfs_quota.h"
    -#include "xfs_rw.h"
    -#include "xfs_itable.h"
    -#include "xfs_utils.h"
    -
    -/*
    - * xfs_get_dir_entry is used to get a reference to an inode given
    - * its parent directory inode and the name of the file.	 It does
    - * not lock the child inode, and it unlocks the directory before
    - * returning.  The directory's generation number is returned for
    - * use by a later call to xfs_lock_dir_and_entry.
    - */
    -int
    -xfs_get_dir_entry(
    -	vname_t		*dentry,
    -	xfs_inode_t	**ipp)
    -{
    -	xfs_vnode_t	*vp;
    -
    -	vp = VNAME_TO_VNODE(dentry);
    -
    -	*ipp = xfs_vtoi(vp);
    -	if (!*ipp)
    -		return XFS_ERROR(ENOENT);
    -	VN_HOLD(vp);
    -	return 0;
    -}
    -
    -int
    -xfs_dir_lookup_int(
    -	bhv_desc_t	*dir_bdp,
    -	uint		lock_mode,
    -	vname_t		*dentry,
    -	xfs_ino_t	*inum,
    -	xfs_inode_t	**ipp)
    -{
    -	xfs_vnode_t	*dir_vp;
    -	xfs_inode_t	*dp;
    -	int		error;
    -
    -	dir_vp = BHV_TO_VNODE(dir_bdp);
    -	vn_trace_entry(dir_vp, __FUNCTION__, (inst_t *)__return_address);
    -
    -	dp = XFS_BHVTOI(dir_bdp);
    -
    -	error = XFS_DIR_LOOKUP(dp->i_mount, NULL, dp,
    -				VNAME(dentry), VNAMELEN(dentry), inum);
    -	if (!error) {
    -		/*
    -		 * Unlock the directory. We do this because we can't
    -		 * hold the directory lock while doing the vn_get()
    -		 * in xfs_iget().  Doing so could cause us to hold
    -		 * a lock while waiting for the inode to finish
    -		 * being inactive while it's waiting for a log
    -		 * reservation in the inactive routine.
    -		 */
    -		xfs_iunlock(dp, lock_mode);
    -		error = xfs_iget(dp->i_mount, NULL, *inum, 0, 0, ipp, 0);
    -		xfs_ilock(dp, lock_mode);
    -
    -		if (error) {
    -			*ipp = NULL;
    -		} else if ((*ipp)->i_d.di_mode == 0) {
    -			/*
    -			 * The inode has been freed.  Something is
    -			 * wrong so just get out of here.
    -			 */
    -			xfs_iunlock(dp, lock_mode);
    -			xfs_iput_new(*ipp, 0);
    -			*ipp = NULL;
    -			xfs_ilock(dp, lock_mode);
    -			error = XFS_ERROR(ENOENT);
    -		}
    -	}
    -	return error;
    -}
    -
    -/*
    - * Allocates a new inode from disk and return a pointer to the
    - * incore copy. This routine will internally commit the current
    - * transaction and allocate a new one if the Space Manager needed
    - * to do an allocation to replenish the inode free-list.
    - *
    - * This routine is designed to be called from xfs_create and
    - * xfs_create_dir.
    - *
    - */
    -int
    -xfs_dir_ialloc(
    -	xfs_trans_t	**tpp,		/* input: current transaction;
    -					   output: may be a new transaction. */
    -	xfs_inode_t	*dp,		/* directory within whose allocate
    -					   the inode. */
    -	mode_t		mode,
    -	xfs_nlink_t	nlink,
    -	xfs_dev_t	rdev,
    -	cred_t		*credp,
    -	prid_t		prid,		/* project id */
    -	int		okalloc,	/* ok to allocate new space */
    -	xfs_inode_t	**ipp,		/* pointer to inode; it will be
    -					   locked. */
    -	int		*committed)
    -
    -{
    -	xfs_trans_t	*tp;
    -	xfs_trans_t	*ntp;
    -	xfs_inode_t	*ip;
    -	xfs_buf_t	*ialloc_context = NULL;
    -	boolean_t	call_again = B_FALSE;
    -	int		code;
    -	uint		log_res;
    -	uint		log_count;
    -	void		*dqinfo;
    -	uint		tflags;
    -
    -	tp = *tpp;
    -	ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);
    -
    -	/*
    -	 * xfs_ialloc will return a pointer to an incore inode if
    -	 * the Space Manager has an available inode on the free
    -	 * list. Otherwise, it will do an allocation and replenish
    -	 * the freelist.  Since we can only do one allocation per
    -	 * transaction without deadlocks, we will need to commit the
    -	 * current transaction and start a new one.  We will then
    -	 * need to call xfs_ialloc again to get the inode.
    -	 *
    -	 * If xfs_ialloc did an allocation to replenish the freelist,
    -	 * it returns the bp containing the head of the freelist as
    -	 * ialloc_context. We will hold a lock on it across the
    -	 * transaction commit so that no other process can steal
    -	 * the inode(s) that we've just allocated.
    -	 */
    -	code = xfs_ialloc(tp, dp, mode, nlink, rdev, credp, prid, okalloc,
    -			  &ialloc_context, &call_again, &ip);
    -
    -	/*
    -	 * Return an error if we were unable to allocate a new inode.
    -	 * This should only happen if we run out of space on disk or
    -	 * encounter a disk error.
    -	 */
    -	if (code) {
    -		*ipp = NULL;
    -		return code;
    -	}
    -	if (!call_again && (ip == NULL)) {
    -		*ipp = NULL;
    -		return XFS_ERROR(ENOSPC);
    -	}
    -
    -	/*
    -	 * If call_again is set, then we were unable to get an
    -	 * inode in one operation.  We need to commit the current
    -	 * transaction and call xfs_ialloc() again.  It is guaranteed
    -	 * to succeed the second time.
    -	 */
    -	if (call_again) {
    -
    -		/*
    -		 * Normally, xfs_trans_commit releases all the locks.
    -		 * We call bhold to hang on to the ialloc_context across
    -		 * the commit.  Holding this buffer prevents any other
    -		 * processes from doing any allocations in this
    -		 * allocation group.
    -		 */
    -		xfs_trans_bhold(tp, ialloc_context);
    -		/*
    -		 * Save the log reservation so we can use
    -		 * them in the next transaction.
    -		 */
    -		log_res = xfs_trans_get_log_res(tp);
    -		log_count = xfs_trans_get_log_count(tp);
    -
    -		/*
    -		 * We want the quota changes to be associated with the next
    -		 * transaction, NOT this one. So, detach the dqinfo from this
    -		 * and attach it to the next transaction.
    -		 */
    -		dqinfo = NULL;
    -		tflags = 0;
    -		if (tp->t_dqinfo) {
    -			dqinfo = (void *)tp->t_dqinfo;
    -			tp->t_dqinfo = NULL;
    -			tflags = tp->t_flags & XFS_TRANS_DQ_DIRTY;
    -			tp->t_flags &= ~(XFS_TRANS_DQ_DIRTY);
    -		}
    -
    -		ntp = xfs_trans_dup(tp);
    -		code = xfs_trans_commit(tp, 0, NULL);
    -		tp = ntp;
    -		if (committed != NULL) {
    -			*committed = 1;
    -		}
    -		/*
    -		 * If we get an error during the commit processing,
    -		 * release the buffer that is still held and return
    -		 * to the caller.
    -		 */
    -		if (code) {
    -			xfs_buf_relse(ialloc_context);
    -			if (dqinfo) {
    -				tp->t_dqinfo = dqinfo;
    -				XFS_TRANS_FREE_DQINFO(tp->t_mountp, tp);
    -			}
    -			*tpp = ntp;
    -			*ipp = NULL;
    -			return code;
    -		}
    -		code = xfs_trans_reserve(tp, 0, log_res, 0,
    -					 XFS_TRANS_PERM_LOG_RES, log_count);
    -		/*
    -		 * Re-attach the quota info that we detached from prev trx.
    -		 */
    -		if (dqinfo) {
    -			tp->t_dqinfo = dqinfo;
    -			tp->t_flags |= tflags;
    -		}
    -
    -		if (code) {
    -			xfs_buf_relse(ialloc_context);
    -			*tpp = ntp;
    -			*ipp = NULL;
    -			return code;
    -		}
    -		xfs_trans_bjoin(tp, ialloc_context);
    -
    -		/*
    -		 * Call ialloc again. Since we've locked out all
    -		 * other allocations in this allocation group,
    -		 * this call should always succeed.
    -		 */
    -		code = xfs_ialloc(tp, dp, mode, nlink, rdev, credp, prid,
    -				  okalloc, &ialloc_context, &call_again, &ip);
    -
    -		/*
    -		 * If we get an error at this point, return to the caller
    -		 * so that the current transaction can be aborted.
    -		 */
    -		if (code) {
    -			*tpp = tp;
    -			*ipp = NULL;
    -			return code;
    -		}
    -		ASSERT ((!call_again) && (ip != NULL));
    -
    -	} else {
    -		if (committed != NULL) {
    -			*committed = 0;
    -		}
    -	}
    -
    -	*ipp = ip;
    -	*tpp = tp;
    -
    -	return 0;
    -}
    -
    -/*
    - * Decrement the link count on an inode & log the change.
    - * If this causes the link count to go to zero, initiate the
    - * logging activity required to truncate a file.
    - */
    -int				/* error */
    -xfs_droplink(
    -	xfs_trans_t *tp,
    -	xfs_inode_t *ip)
    -{
    -	int	error;
    -
    -	xfs_ichgtime(ip, XFS_ICHGTIME_CHG);
    -
    -	ASSERT (ip->i_d.di_nlink > 0);
    -	ip->i_d.di_nlink--;
    -	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
    -
    -	error = 0;
    -	if (ip->i_d.di_nlink == 0) {
    -		/*
    -		 * We're dropping the last link to this file.
    -		 * Move the on-disk inode to the AGI unlinked list.
    -		 * From xfs_inactive() we will pull the inode from
    -		 * the list and free it.
    -		 */
    -		error = xfs_iunlink(tp, ip);
    -	}
    -	return error;
    -}
    -
    -/*
    - * This gets called when the inode's version needs to be changed from 1 to 2.
    - * Currently this happens when the nlink field overflows the old 16-bit value
    - * or when chproj is called to change the project for the first time.
    - * As a side effect the superblock version will also get rev'd
    - * to contain the NLINK bit.
    - */
    -void
    -xfs_bump_ino_vers2(
    -	xfs_trans_t	*tp,
    -	xfs_inode_t	*ip)
    -{
    -	xfs_mount_t	*mp;
    -	unsigned long		s;
    -
    -	ASSERT(ismrlocked (&ip->i_lock, MR_UPDATE));
    -	ASSERT(ip->i_d.di_version == XFS_DINODE_VERSION_1);
    -
    -	ip->i_d.di_version = XFS_DINODE_VERSION_2;
    -	ip->i_d.di_onlink = 0;
    -	memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
    -	mp = tp->t_mountp;
    -	if (!XFS_SB_VERSION_HASNLINK(&mp->m_sb)) {
    -		s = XFS_SB_LOCK(mp);
    -		if (!XFS_SB_VERSION_HASNLINK(&mp->m_sb)) {
    -			XFS_SB_VERSION_ADDNLINK(&mp->m_sb);
    -			XFS_SB_UNLOCK(mp, s);
    -			xfs_mod_sb(tp, XFS_SB_VERSIONNUM);
    -		} else {
    -			XFS_SB_UNLOCK(mp, s);
    -		}
    -	}
    -	/* Caller must log the inode */
    -}
    -
    -/*
    - * Increment the link count on an inode & log the change.
    - */
    -int
    -xfs_bumplink(
    -	xfs_trans_t *tp,
    -	xfs_inode_t *ip)
    -{
    -	if (ip->i_d.di_nlink >= XFS_MAXLINK)
    -		return XFS_ERROR(EMLINK);
    -	xfs_ichgtime(ip, XFS_ICHGTIME_CHG);
    -
    -	ASSERT(ip->i_d.di_nlink > 0);
    -	ip->i_d.di_nlink++;
    -	if ((ip->i_d.di_version == XFS_DINODE_VERSION_1) &&
    -	    (ip->i_d.di_nlink > XFS_MAXLINK_1)) {
    -		/*
    -		 * The inode has increased its number of links beyond
    -		 * what can fit in an old format inode.  It now needs
    -		 * to be converted to a version 2 inode with a 32 bit
    -		 * link count.  If this is the first inode in the file
    -		 * system to do this, then we need to bump the superblock
    -		 * version number as well.
    -		 */
    -		xfs_bump_ino_vers2(tp, ip);
    -	}
    -
    -	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
    -	return 0;
    -}
    -
    -/*
    - * Try to truncate the given file to 0 length.  Currently called
    - * only out of xfs_remove when it has to truncate a file to free
    - * up space for the remove to proceed.
    - */
    -int
    -xfs_truncate_file(
    -	xfs_mount_t	*mp,
    -	xfs_inode_t	*ip)
    -{
    -	xfs_trans_t	*tp;
    -	int		error;
    -
    -#ifdef QUOTADEBUG
    -	/*
    -	 * This is called to truncate the quotainodes too.
    -	 */
    -	if (XFS_IS_UQUOTA_ON(mp)) {
    -		if (ip->i_ino != mp->m_sb.sb_uquotino)
    -			ASSERT(ip->i_udquot);
    -	}
    -	if (XFS_IS_OQUOTA_ON(mp)) {
    -		if (ip->i_ino != mp->m_sb.sb_gquotino)
    -			ASSERT(ip->i_gdquot);
    -	}
    -#endif
    -	/*
    -	 * Make the call to xfs_itruncate_start before starting the
    -	 * transaction, because we cannot make the call while we're
    -	 * in a transaction.
    -	 */
    -	xfs_ilock(ip, XFS_IOLOCK_EXCL);
    -	xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE, (xfs_fsize_t)0);
    -
    -	tp = xfs_trans_alloc(mp, XFS_TRANS_TRUNCATE_FILE);
    -	if ((error = xfs_trans_reserve(tp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0,
    -				      XFS_TRANS_PERM_LOG_RES,
    -				      XFS_ITRUNCATE_LOG_COUNT))) {
    -		xfs_trans_cancel(tp, 0);
    -		xfs_iunlock(ip, XFS_IOLOCK_EXCL);
    -		return error;
    -	}
    -
    -	/*
    -	 * Follow the normal truncate locking protocol.  Since we
    -	 * hold the inode in the transaction, we know that it's number
    -	 * of references will stay constant.
    -	 */
    -	xfs_ilock(ip, XFS_ILOCK_EXCL);
    -	xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
    -	xfs_trans_ihold(tp, ip);
    -	/*
    -	 * Signal a sync xaction.  The only case where that isn't
    -	 * the case is if we're truncating an already unlinked file
    -	 * on a wsync fs.  In that case, we know the blocks can't
    -	 * reappear in the file because the links to file are
    -	 * permanently toast.  Currently, we're always going to
    -	 * want a sync transaction because this code is being
    -	 * called from places where nlink is guaranteed to be 1
    -	 * but I'm leaving the tests in to protect against future
    -	 * changes -- rcc.
    -	 */
    -	error = xfs_itruncate_finish(&tp, ip, (xfs_fsize_t)0,
    -				     XFS_DATA_FORK,
    -				     ((ip->i_d.di_nlink != 0 ||
    -				       !(mp->m_flags & XFS_MOUNT_WSYNC))
    -				      ? 1 : 0));
    -	if (error) {
    -		xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES |
    -				 XFS_TRANS_ABORT);
    -	} else {
    -		xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
    -		error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES,
    -					 NULL);
    -	}
    -	xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
    -
    -	return error;
    -}
    diff --git a/sys/gnu/fs/xfs/xfs_utils.h b/sys/gnu/fs/xfs/xfs_utils.h
    deleted file mode 100644
    index 2178ad1ca2b..00000000000
    --- a/sys/gnu/fs/xfs/xfs_utils.h
    +++ /dev/null
    @@ -1,38 +0,0 @@
    -/*
    - * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#ifndef __XFS_UTILS_H__
    -#define __XFS_UTILS_H__
    -
    -#define IRELE(ip)	VN_RELE(XFS_ITOV(ip))
    -#define IHOLD(ip)	VN_HOLD(XFS_ITOV(ip))
    -#define	ITRACE(ip)	vn_trace_ref(XFS_ITOV(ip), __FILE__, __LINE__, \
    -				(inst_t *)__return_address)
    -
    -extern int xfs_rename (bhv_desc_t *, vname_t *, xfs_vnode_t *, vname_t *, cred_t *);
    -extern int xfs_get_dir_entry (vname_t *, xfs_inode_t **);
    -extern int xfs_dir_lookup_int (bhv_desc_t *, uint, vname_t *, xfs_ino_t *,
    -				xfs_inode_t **);
    -extern int xfs_truncate_file (xfs_mount_t *, xfs_inode_t *);
    -extern int xfs_dir_ialloc (xfs_trans_t **, xfs_inode_t *, mode_t, xfs_nlink_t,
    -				xfs_dev_t, cred_t *, prid_t, int,
    -				xfs_inode_t **, int *);
    -extern int xfs_droplink (xfs_trans_t *, xfs_inode_t *);
    -extern int xfs_bumplink (xfs_trans_t *, xfs_inode_t *);
    -extern void xfs_bump_ino_vers2 (xfs_trans_t *, xfs_inode_t *);
    -
    -#endif	/* __XFS_UTILS_H__ */
    diff --git a/sys/gnu/fs/xfs/xfs_vfsops.c b/sys/gnu/fs/xfs/xfs_vfsops.c
    deleted file mode 100644
    index b073a8e2a5d..00000000000
    --- a/sys/gnu/fs/xfs/xfs_vfsops.c
    +++ /dev/null
    @@ -1,2030 +0,0 @@
    -/*
    - * Copyright (c) 2000-2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_da_btree.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_inode_item.h"
    -#include "xfs_btree.h"
    -#include "xfs_alloc.h"
    -#include "xfs_ialloc.h"
    -#include "xfs_quota.h"
    -#include "xfs_error.h"
    -#include "xfs_bmap.h"
    -#include "xfs_rw.h"
    -#include "xfs_refcache.h"
    -#include "xfs_buf_item.h"
    -#include "xfs_log_priv.h"
    -#include "xfs_dir2_trace.h"
    -#include "xfs_extfree_item.h"
    -#include "xfs_acl.h"
    -#include "xfs_attr.h"
    -#include "xfs_clnt.h"
    -#include "xfs_fsops.h"
    -#include "xfs_vnode.h"
    -
    -STATIC int	xfs_sync(bhv_desc_t *, int, cred_t *);
    -
    -	extern kmem_zone_t	*xfs_bmap_free_item_zone;
    -	extern kmem_zone_t	*xfs_btree_cur_zone;
    -	extern kmem_zone_t	*xfs_trans_zone;
    -	extern kmem_zone_t	*xfs_dabuf_zone;
    -	extern kmem_zone_t	*xfs_buf_item_zone;
    -
    -#ifdef XFS_DABUF_DEBUG
    -	extern lock_t	        xfs_dabuf_global_lock;
    -#endif
    -
    -int
    -xfs_init(void)
    -{
    -#if 0
    -	extern kmem_zone_t	*xfs_bmap_free_item_zone;
    -	extern kmem_zone_t	*xfs_btree_cur_zone;
    -	extern kmem_zone_t	*xfs_trans_zone;
    -	extern kmem_zone_t	*xfs_buf_item_zone;
    -	extern kmem_zone_t	*xfs_dabuf_zone;
    -#endif
    -#ifdef XFS_DABUF_DEBUG
    -	spinlock_init(&xfs_dabuf_global_lock, "xfsda");
    -#endif
    -	/*
    -	 * Initialize all of the zone allocators we use.
    -	 */
    -	xfs_bmap_free_item_zone = kmem_zone_init(sizeof(xfs_bmap_free_item_t),
    -						 "xfs_bmap_free_item");
    -	xfs_btree_cur_zone = kmem_zone_init(sizeof(xfs_btree_cur_t),
    -					    "xfs_btree_cur");
    -	xfs_trans_zone = kmem_zone_init(sizeof(xfs_trans_t), "xfs_trans");
    -	xfs_da_state_zone =
    -		kmem_zone_init(sizeof(xfs_da_state_t), "xfs_da_state");
    -	xfs_dabuf_zone = kmem_zone_init(sizeof(xfs_dabuf_t), "xfs_dabuf");
    -	xfs_ifork_zone = kmem_zone_init(sizeof(xfs_ifork_t), "xfs_ifork");
    -	xfs_acl_zone_init(xfs_acl_zone, "xfs_acl");
    -
    -	/*
    -	 * The size of the zone allocated buf log item is the maximum
    -	 * size possible under XFS.  This wastes a little bit of memory,
    -	 * but it is much faster.
    -	 */
    -	xfs_buf_item_zone =
    -		kmem_zone_init((sizeof(xfs_buf_log_item_t) +
    -				(((XFS_MAX_BLOCKSIZE / XFS_BLI_CHUNK) /
    -				  NBWORD) * sizeof(int))),
    -			       "xfs_buf_item");
    -	xfs_efd_zone =
    -		kmem_zone_init((sizeof(xfs_efd_log_item_t) +
    -			       ((XFS_EFD_MAX_FAST_EXTENTS - 1) *
    -				 sizeof(xfs_extent_t))),
    -				      "xfs_efd_item");
    -	xfs_efi_zone =
    -		kmem_zone_init((sizeof(xfs_efi_log_item_t) +
    -			       ((XFS_EFI_MAX_FAST_EXTENTS - 1) *
    -				 sizeof(xfs_extent_t))),
    -				      "xfs_efi_item");
    -
    -	/*
    -	 * These zones warrant special memory allocator hints
    -	 */
    -	xfs_inode_zone =
    -		kmem_zone_init_flags(sizeof(xfs_inode_t), "xfs_inode",
    -					KM_ZONE_HWALIGN | KM_ZONE_RECLAIM |
    -					KM_ZONE_SPREAD, NULL);
    -	xfs_ili_zone =
    -		kmem_zone_init_flags(sizeof(xfs_inode_log_item_t), "xfs_ili",
    -					KM_ZONE_SPREAD, NULL);
    -	xfs_chashlist_zone =
    -		kmem_zone_init_flags(sizeof(xfs_chashlist_t), "xfs_chashlist",
    -					KM_ZONE_SPREAD, NULL);
    -
    -	/*
    -	 * Allocate global trace buffers.
    -	 */
    -#ifdef XFS_ALLOC_TRACE
    -	xfs_alloc_trace_buf = ktrace_alloc(XFS_ALLOC_TRACE_SIZE, KM_SLEEP);
    -#endif
    -#ifdef XFS_BMAP_TRACE
    -	xfs_bmap_trace_buf = ktrace_alloc(XFS_BMAP_TRACE_SIZE, KM_SLEEP);
    -#endif
    -#ifdef XFS_BMBT_TRACE
    -	xfs_bmbt_trace_buf = ktrace_alloc(XFS_BMBT_TRACE_SIZE, KM_SLEEP);
    -#endif
    -#ifdef XFS_DIR_TRACE
    -	xfs_dir_trace_buf = ktrace_alloc(XFS_DIR_TRACE_SIZE, KM_SLEEP);
    -#endif
    -#ifdef XFS_ATTR_TRACE
    -	xfs_attr_trace_buf = ktrace_alloc(XFS_ATTR_TRACE_SIZE, KM_SLEEP);
    -#endif
    -#ifdef XFS_DIR2_TRACE
    -	xfs_dir2_trace_buf = ktrace_alloc(XFS_DIR2_GTRACE_SIZE, KM_SLEEP);
    -#endif
    -
    -	xfs_dir_startup();
    -
    -#if (defined(DEBUG) || defined(INDUCE_IO_ERROR))
    -	xfs_error_test_init();
    -#endif /* DEBUG || INDUCE_IO_ERROR */
    -
    -	xfs_refcache_init();
    -	xfs_init_procfs();
    -	xfs_sysctl_register();
    -	return 0;
    -}
    -
    -void
    -xfs_cleanup(void)
    -{
    -#if 0
    -	extern kmem_zone_t	*xfs_bmap_free_item_zone;
    -	extern kmem_zone_t	*xfs_btree_cur_zone;
    -	extern kmem_zone_t	*xfs_inode_zone;
    -	extern kmem_zone_t	*xfs_trans_zone;
    -	extern kmem_zone_t	*xfs_da_state_zone;
    -	extern kmem_zone_t	*xfs_dabuf_zone;
    -	extern kmem_zone_t	*xfs_efd_zone;
    -	extern kmem_zone_t	*xfs_efi_zone;
    -	extern kmem_zone_t	*xfs_buf_item_zone;
    -	extern kmem_zone_t	*xfs_chashlist_zone;
    -#endif
    -
    -	xfs_cleanup_procfs();
    -	xfs_sysctl_unregister();
    -	xfs_refcache_destroy();
    -	xfs_acl_zone_destroy(xfs_acl_zone);
    -
    -#ifdef XFS_DIR2_TRACE
    -	ktrace_free(xfs_dir2_trace_buf);
    -#endif
    -#ifdef XFS_ATTR_TRACE
    -	ktrace_free(xfs_attr_trace_buf);
    -#endif
    -#ifdef XFS_DIR_TRACE
    -	ktrace_free(xfs_dir_trace_buf);
    -#endif
    -#ifdef XFS_BMBT_TRACE
    -	ktrace_free(xfs_bmbt_trace_buf);
    -#endif
    -#ifdef XFS_BMAP_TRACE
    -	ktrace_free(xfs_bmap_trace_buf);
    -#endif
    -#ifdef XFS_ALLOC_TRACE
    -	ktrace_free(xfs_alloc_trace_buf);
    -#endif
    -
    -	kmem_zone_destroy(xfs_bmap_free_item_zone);
    -	kmem_zone_destroy(xfs_btree_cur_zone);
    -	kmem_zone_destroy(xfs_inode_zone);
    -	kmem_zone_destroy(xfs_trans_zone);
    -	kmem_zone_destroy(xfs_da_state_zone);
    -	kmem_zone_destroy(xfs_dabuf_zone);
    -	kmem_zone_destroy(xfs_buf_item_zone);
    -	kmem_zone_destroy(xfs_efd_zone);
    -	kmem_zone_destroy(xfs_efi_zone);
    -	kmem_zone_destroy(xfs_ifork_zone);
    -	kmem_zone_destroy(xfs_ili_zone);
    -	kmem_zone_destroy(xfs_chashlist_zone);
    -}
    -
    -/*
    - * xfs_start_flags
    - *
    - * This function fills in xfs_mount_t fields based on mount args.
    - * Note: the superblock has _not_ yet been read in.
    - */
    -STATIC int
    -xfs_start_flags(
    -	struct xfs_vfs		*vfs,
    -	struct xfs_mount_args	*ap,
    -	struct xfs_mount	*mp)
    -{
    -	/* Values are in BBs */
    -	if ((ap->flags & XFSMNT_NOALIGN) != XFSMNT_NOALIGN) {
    -		/*
    -		 * At this point the superblock has not been read
    -		 * in, therefore we do not know the block size.
    -		 * Before the mount call ends we will convert
    -		 * these to FSBs.
    -		 */
    -		mp->m_dalign = ap->sunit;
    -		mp->m_swidth = ap->swidth;
    -	}
    -
    -	if (ap->logbufs != -1 &&
    -	    ap->logbufs != 0 &&
    -	    (ap->logbufs < XLOG_MIN_ICLOGS ||
    -	     ap->logbufs > XLOG_MAX_ICLOGS)) {
    -		cmn_err(CE_WARN,
    -			"XFS: invalid logbufs value: %d [not %d-%d]",
    -			ap->logbufs, XLOG_MIN_ICLOGS, XLOG_MAX_ICLOGS);
    -		return XFS_ERROR(EINVAL);
    -	}
    -	mp->m_logbufs = ap->logbufs;
    -	if (ap->logbufsize != -1 &&
    -	    ap->logbufsize !=  0 &&
    -	    ap->logbufsize != 16 * 1024 &&
    -	    ap->logbufsize != 32 * 1024 &&
    -	    ap->logbufsize != 64 * 1024 &&
    -	    ap->logbufsize != 128 * 1024 &&
    -	    ap->logbufsize != 256 * 1024) {
    -		cmn_err(CE_WARN,
    -	"XFS: invalid logbufsize: %d [not 16k,32k,64k,128k or 256k]",
    -			ap->logbufsize);
    -		return XFS_ERROR(EINVAL);
    -	}
    -	mp->m_ihsize = ap->ihashsize;
    -	mp->m_logbsize = ap->logbufsize;
    -	mp->m_fsname_len = strlen(ap->fsname) + 1;
    -	mp->m_fsname = kmem_alloc(mp->m_fsname_len, KM_SLEEP);
    -	strcpy(mp->m_fsname, ap->fsname);
    -	if (ap->rtname[0]) {
    -		mp->m_rtname = kmem_alloc(strlen(ap->rtname) + 1, KM_SLEEP);
    -		strcpy(mp->m_rtname, ap->rtname);
    -	}
    -	if (ap->logname[0]) {
    -		mp->m_logname = kmem_alloc(strlen(ap->logname) + 1, KM_SLEEP);
    -		strcpy(mp->m_logname, ap->logname);
    -	}
    -
    -	if (ap->flags & XFSMNT_WSYNC)
    -		mp->m_flags |= XFS_MOUNT_WSYNC;
    -#if XFS_BIG_INUMS
    -	if (ap->flags & XFSMNT_INO64) {
    -		mp->m_flags |= XFS_MOUNT_INO64;
    -		mp->m_inoadd = XFS_INO64_OFFSET;
    -	}
    -#endif
    -	if (ap->flags & XFSMNT_RETERR)
    -		mp->m_flags |= XFS_MOUNT_RETERR;
    -	if (ap->flags & XFSMNT_NOALIGN)
    -		mp->m_flags |= XFS_MOUNT_NOALIGN;
    -	if (ap->flags & XFSMNT_SWALLOC)
    -		mp->m_flags |= XFS_MOUNT_SWALLOC;
    -	if (ap->flags & XFSMNT_OSYNCISOSYNC)
    -		mp->m_flags |= XFS_MOUNT_OSYNCISOSYNC;
    -	if (ap->flags & XFSMNT_32BITINODES)
    -		mp->m_flags |= XFS_MOUNT_32BITINODES;
    -
    -	if (ap->flags & XFSMNT_IOSIZE) {
    -		if (ap->iosizelog > XFS_MAX_IO_LOG ||
    -		    ap->iosizelog < XFS_MIN_IO_LOG) {
    -			cmn_err(CE_WARN,
    -		"XFS: invalid log iosize: %d [not %d-%d]",
    -				ap->iosizelog, XFS_MIN_IO_LOG,
    -				XFS_MAX_IO_LOG);
    -			return XFS_ERROR(EINVAL);
    -		}
    -
    -		mp->m_flags |= XFS_MOUNT_DFLT_IOSIZE;
    -		mp->m_readio_log = mp->m_writeio_log = ap->iosizelog;
    -	}
    -
    -	if (ap->flags & XFSMNT_IHASHSIZE)
    -		mp->m_flags |= XFS_MOUNT_IHASHSIZE;
    -	if (ap->flags & XFSMNT_IDELETE)
    -		mp->m_flags |= XFS_MOUNT_IDELETE;
    -	if (ap->flags & XFSMNT_DIRSYNC)
    -		mp->m_flags |= XFS_MOUNT_DIRSYNC;
    -	if (ap->flags & XFSMNT_ATTR2)
    -		mp->m_flags |= XFS_MOUNT_ATTR2;
    -
    -	if (ap->flags2 & XFSMNT2_COMPAT_IOSIZE)
    -		mp->m_flags |= XFS_MOUNT_COMPAT_IOSIZE;
    -
    -	/*
    -	 * no recovery flag requires a read-only mount
    -	 */
    -	if (ap->flags & XFSMNT_NORECOVERY) {
    -		if (!(vfs->vfs_flag & VFS_RDONLY)) {
    -			cmn_err(CE_WARN,
    -	"XFS: tried to mount a FS read-write without recovery!");
    -			return XFS_ERROR(EINVAL);
    -		}
    -		mp->m_flags |= XFS_MOUNT_NORECOVERY;
    -	}
    -
    -	if (ap->flags & XFSMNT_NOUUID)
    -		mp->m_flags |= XFS_MOUNT_NOUUID;
    -	if (ap->flags & XFSMNT_BARRIER)
    -		mp->m_flags |= XFS_MOUNT_BARRIER;
    -	else
    -		mp->m_flags &= ~XFS_MOUNT_BARRIER;
    -
    -	return 0;
    -}
    -
    -/*
    - * This function fills in xfs_mount_t fields based on mount args.
    - * Note: the superblock _has_ now been read in.
    - */
    -STATIC int
    -xfs_finish_flags(
    -	struct xfs_vfs		*vfs,
    -	struct xfs_mount_args	*ap,
    -	struct xfs_mount	*mp)
    -{
    -	int			ronly = (vfs->vfs_flag & VFS_RDONLY);
    -
    -	/* Fail a mount where the logbuf is smaller then the log stripe */
    -	if (XFS_SB_VERSION_HASLOGV2(&mp->m_sb)) {
    -		if ((ap->logbufsize <= 0) &&
    -		    (mp->m_sb.sb_logsunit > XLOG_BIG_RECORD_BSIZE)) {
    -			mp->m_logbsize = mp->m_sb.sb_logsunit;
    -		} else if (ap->logbufsize > 0 &&
    -			   ap->logbufsize < mp->m_sb.sb_logsunit) {
    -			cmn_err(CE_WARN,
    -	"XFS: logbuf size must be greater than or equal to log stripe size");
    -			return XFS_ERROR(EINVAL);
    -		}
    -	} else {
    -		/* Fail a mount if the logbuf is larger than 32K */
    -		if (ap->logbufsize > XLOG_BIG_RECORD_BSIZE) {
    -			cmn_err(CE_WARN,
    -	"XFS: logbuf size for version 1 logs must be 16K or 32K");
    -			return XFS_ERROR(EINVAL);
    -		}
    -	}
    -
    -	if (XFS_SB_VERSION_HASATTR2(&mp->m_sb)) {
    -		mp->m_flags |= XFS_MOUNT_ATTR2;
    -	}
    -
    -	/*
    -	 * prohibit r/w mounts of read-only filesystems
    -	 */
    -	if ((mp->m_sb.sb_flags & XFS_SBF_READONLY) && !ronly) {
    -		cmn_err(CE_WARN,
    -	"XFS: cannot mount a read-only filesystem as read-write");
    -		return XFS_ERROR(EROFS);
    -	}
    -
    -	/*
    -	 * check for shared mount.
    -	 */
    -	if (ap->flags & XFSMNT_SHARED) {
    -		if (!XFS_SB_VERSION_HASSHARED(&mp->m_sb))
    -			return XFS_ERROR(EINVAL);
    -
    -		/*
    -		 * For IRIX 6.5, shared mounts must have the shared
    -		 * version bit set, have the persistent readonly
    -		 * field set, must be version 0 and can only be mounted
    -		 * read-only.
    -		 */
    -		if (!ronly || !(mp->m_sb.sb_flags & XFS_SBF_READONLY) ||
    -		     (mp->m_sb.sb_shared_vn != 0))
    -			return XFS_ERROR(EINVAL);
    -
    -		mp->m_flags |= XFS_MOUNT_SHARED;
    -
    -		/*
    -		 * Shared XFS V0 can't deal with DMI.  Return EINVAL.
    -		 */
    -		if (mp->m_sb.sb_shared_vn == 0 && (ap->flags & XFSMNT_DMAPI))
    -			return XFS_ERROR(EINVAL);
    -	}
    -
    -	return 0;
    -}
    -
    -/*
    - * xfs_mount
    - *
    - * The file system configurations are:
    - *	(1) device (partition) with data and internal log
    - *	(2) logical volume with data and log subvolumes.
    - *	(3) logical volume with data, log, and realtime subvolumes.
    - *
    - * We only have to handle opening the log and realtime volumes here if
    - * they are present.  The data subvolume has already been opened by
    - * get_sb_bdev() and is stored in vfsp->vfs_super->s_bdev.
    - */
    -STATIC int
    -xfs_mount(
    -	struct bhv_desc		*bhvp,
    -	struct xfs_mount_args	*args,
    -	cred_t			*credp)
    -{
    -	struct xfs_vfs		*vfsp = bhvtovfs(bhvp);
    -	struct bhv_desc		*p;
    -	struct xfs_mount	*mp = XFS_BHVTOM(bhvp);
    -	struct vnode		*ddev, *logdev, *rtdev;
    -	int			flags = 0, error;
    -
    -	ddev = logdev = rtdev = NULL;
    -
    -	error = xfs_blkdev_get(mp, args->fsname, &ddev);
    -	if (error)
    -		return error;
    -
    -	/*
    -	 * Setup xfs_mount function vectors from available behaviors
    -	 */
    -	p = vfs_bhv_lookup(vfsp, VFS_POSITION_DM);
    -	mp->m_dm_ops = p ? *(xfs_dmops_t *) vfs_bhv_custom(p) : xfs_dmcore_stub;
    -	p = vfs_bhv_lookup(vfsp, VFS_POSITION_QM);
    -	mp->m_qm_ops = p ? *(xfs_qmops_t *) vfs_bhv_custom(p) : xfs_qmcore_stub;
    -	p = vfs_bhv_lookup(vfsp, VFS_POSITION_IO);
    -	mp->m_io_ops = p ? *(xfs_ioops_t *) vfs_bhv_custom(p) : xfs_iocore_xfs;
    -
    -	if (args->flags & XFSMNT_QUIET)
    -		flags |= XFS_MFSI_QUIET;
    -
    -	/*
    -	 * Open real time and log devices - order is important.
    -	 */
    -	if (args->logname[0]) {
    -		error = xfs_blkdev_get(mp, args->logname, &logdev);
    -		if (error) {
    -			xfs_blkdev_put(ddev);
    -			return error;
    -		}
    -	}
    -	if (args->rtname[0]) {
    -		error = xfs_blkdev_get(mp, args->rtname, &rtdev);
    -		if (error) {
    -			xfs_blkdev_put(logdev);
    -			xfs_blkdev_put(ddev);
    -			return error;
    -		}
    -
    -		if (rtdev == ddev || rtdev == logdev) {
    -			cmn_err(CE_WARN,
    -	"XFS: Cannot mount filesystem with identical rtdev and ddev/logdev.");
    -			xfs_blkdev_put(logdev);
    -			xfs_blkdev_put(rtdev);
    -			xfs_blkdev_put(ddev);
    -			return EINVAL;
    -		}
    -	}
    -
    -	/*
    -	 * Setup xfs_mount buffer target pointers
    -	 */
    -	error = ENOMEM;
    -	mp->m_ddev_targp = xfs_alloc_buftarg(ddev, 0);
    -	if (!mp->m_ddev_targp) {
    -		xfs_blkdev_put(logdev);
    -		xfs_blkdev_put(rtdev);
    -		return error;
    -	}
    -	if (rtdev) {
    -		mp->m_rtdev_targp = xfs_alloc_buftarg(rtdev, 1);
    -		if (!mp->m_rtdev_targp)
    -			goto error0;
    -	}
    -	mp->m_logdev_targp = (logdev && logdev != ddev) ?
    -				xfs_alloc_buftarg(logdev, 1) : mp->m_ddev_targp;
    -	if (!mp->m_logdev_targp)
    -		goto error0;
    -
    -	/*
    -	 * Setup flags based on mount(2) options and then the superblock
    -	 */
    -	error = xfs_start_flags(vfsp, args, mp);
    -	if (error)
    -		goto error1;
    -	error = xfs_readsb(mp, flags);
    -	if (error)
    -		goto error1;
    -	error = xfs_finish_flags(vfsp, args, mp);
    -	if (error)
    -		goto error2;
    -
    -	/*
    -	 * Setup xfs_mount buffer target pointers based on superblock
    -	 */
    -	error = xfs_setsize_buftarg(mp->m_ddev_targp, mp->m_sb.sb_blocksize,
    -				    mp->m_sb.sb_sectsize);
    -	if (!error && logdev && logdev != ddev) {
    -		unsigned int	log_sector_size = BBSIZE;
    -
    -		if (XFS_SB_VERSION_HASSECTOR(&mp->m_sb))
    -			log_sector_size = mp->m_sb.sb_logsectsize;
    -		error = xfs_setsize_buftarg(mp->m_logdev_targp,
    -					    mp->m_sb.sb_blocksize,
    -					    log_sector_size);
    -	}
    -	if (!error && rtdev)
    -		error = xfs_setsize_buftarg(mp->m_rtdev_targp,
    -					    mp->m_sb.sb_blocksize,
    -					    mp->m_sb.sb_sectsize);
    -	if (error)
    -		goto error2;
    -
    -	if ((mp->m_flags & XFS_MOUNT_BARRIER) && !(vfsp->vfs_flag & VFS_RDONLY))
    -		xfs_mountfs_check_barriers(mp);
    -
    -	error = XFS_IOINIT(vfsp, args, flags);
    -	if (error)
    -		goto error2;
    -
    -	return 0;
    -
    -error2:
    -	if (mp->m_sb_bp)
    -		xfs_freesb(mp);
    -error1:
    -	xfs_binval(mp->m_ddev_targp);
    -	if (logdev && logdev != ddev)
    -		xfs_binval(mp->m_logdev_targp);
    -	if (rtdev)
    -		xfs_binval(mp->m_rtdev_targp);
    -error0:
    -	xfs_unmountfs_close(mp, credp);
    -	return error;
    -}
    -
    -STATIC int
    -xfs_unmount(
    -	bhv_desc_t	*bdp,
    -	int		flags,
    -	cred_t		*credp)
    -{
    -	struct xfs_vfs	*vfsp = bhvtovfs(bdp);
    -	xfs_mount_t	*mp = XFS_BHVTOM(bdp);
    -	xfs_inode_t	*rip;
    -	xfs_vnode_t	*rvp;
    -	int		unmount_event_wanted = 0;
    -	int		unmount_event_flags = 0;
    -	int		xfs_unmountfs_needed = 0;
    -	int		error;
    -
    -	rip = mp->m_rootip;
    -	rvp = XFS_ITOV(rip);
    -
    -	if (vfsp->vfs_flag & VFS_DMI) {
    -		error = XFS_SEND_PREUNMOUNT(mp, vfsp,
    -				rvp, DM_RIGHT_NULL, rvp, DM_RIGHT_NULL,
    -				NULL, NULL, 0, 0,
    -				(mp->m_dmevmask & (1<m_dmevmask & (1<m_ddev_targp);
    -	error = xfs_unmount_flush(mp, 0);
    -	if (error)
    -		goto out;
    -
    -	ASSERT(vn_count(rvp) == 1);
    -
    -	/*
    -	 * Drop the reference count
    -	 */
    -	VN_RELE(rvp);
    -
    -	/*
    -	 * If we're forcing a shutdown, typically because of a media error,
    -	 * we want to make sure we invalidate dirty pages that belong to
    -	 * referenced vnodes as well.
    -	 */
    -	if (XFS_FORCED_SHUTDOWN(mp)) {
    -		error = xfs_sync(&mp->m_bhv,
    -			 (SYNC_WAIT | SYNC_CLOSE), credp);
    -		ASSERT(error != EFSCORRUPTED);
    -	}
    -	xfs_unmountfs_needed = 1;
    -
    -out:
    -	/*	Send DMAPI event, if required.
    -	 *	Then do xfs_unmountfs() if needed.
    -	 *	Then return error (or zero).
    -	 */
    -	if (unmount_event_wanted) {
    -		/* Note: mp structure must still exist for
    -		 * XFS_SEND_UNMOUNT() call.
    -		 */
    -		XFS_SEND_UNMOUNT(mp, vfsp, error == 0 ? rvp : NULL,
    -			DM_RIGHT_NULL, 0, error, unmount_event_flags);
    -	}
    -	if (xfs_unmountfs_needed) {
    -		/*
    -		 * Call common unmount function to flush to disk
    -		 * and free the super block buffer & mount structures.
    -		 */
    -		xfs_unmountfs(mp, credp);
    -	}
    -
    -	return XFS_ERROR(error);
    -}
    -
    -STATIC int
    -xfs_quiesce_fs(
    -	xfs_mount_t		*mp)
    -{
    -	int			count = 0, pincount;
    -
    -	xfs_refcache_purge_mp(mp);
    -	xfs_flush_buftarg(mp->m_ddev_targp, 0);
    -	xfs_finish_reclaim_all(mp, 0);
    -
    -	/* This loop must run at least twice.
    -	 * The first instance of the loop will flush
    -	 * most meta data but that will generate more
    -	 * meta data (typically directory updates).
    -	 * Which then must be flushed and logged before
    -	 * we can write the unmount record.
    -	 */
    -	do {
    -		xfs_syncsub(mp, SYNC_REMOUNT|SYNC_ATTR|SYNC_WAIT, 0, NULL);
    -		pincount = xfs_flush_buftarg(mp->m_ddev_targp, 1);
    -		if (!pincount) {
    -			delay(50);
    -			count++;
    -		}
    -	} while (count < 2);
    -
    -	return 0;
    -}
    -
    -/* XXXKAN */
    -#define pagebuf_delwri_flush(a,b,c)			\
    -	do {						\
    -		printf("pagebuf_delwri_flush NI\n");	\
    -		if (c) *((int *)(c)) = 0;		\
    -	} while(0)
    -
    -STATIC int
    -xfs_mntupdate(
    -	bhv_desc_t			*bdp,
    -	int				*flags,
    -	struct xfs_mount_args		*args)
    -{
    -	struct xfs_vfs	*vfsp = bhvtovfs(bdp);
    -	xfs_mount_t	*mp = XFS_BHVTOM(bdp);
    -	int		error;
    -
    -#ifdef RMC
    -	if (!(*flags & MS_RDONLY)) {			/* rw/ro -> rw */
    -#endif
    -	  if (!(*flags & VFS_RDONLY)) {			/* rw/ro -> rw */
    -		if (vfsp->vfs_flag & VFS_RDONLY)
    -			vfsp->vfs_flag &= ~VFS_RDONLY;
    -		if (args->flags & XFSMNT_BARRIER) {
    -			mp->m_flags |= XFS_MOUNT_BARRIER;
    -			xfs_mountfs_check_barriers(mp);
    -		} else {
    -			mp->m_flags &= ~XFS_MOUNT_BARRIER;
    -		}
    -	} else if (!(vfsp->vfs_flag & VFS_RDONLY)) {	/* rw -> ro */
    -		XVFS_SYNC(vfsp, SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR, NULL, error);
    -		xfs_quiesce_fs(mp);
    -		xfs_log_unmount_write(mp);
    -		xfs_unmountfs_writesb(mp);
    -		vfsp->vfs_flag |= VFS_RDONLY;
    -	}
    -	return 0;
    -}
    -
    -/*
    - * xfs_unmount_flush implements a set of flush operation on special
    - * inodes, which are needed as a separate set of operations so that
    - * they can be called as part of relocation process.
    - */
    -int
    -xfs_unmount_flush(
    -	xfs_mount_t	*mp,		/* Mount structure we are getting
    -					   rid of. */
    -	int             relocation)	/* Called from vfs relocation. */
    -{
    -	xfs_inode_t	*rip = mp->m_rootip;
    -	xfs_inode_t	*rbmip;
    -	xfs_inode_t	*rsumip = NULL;
    -	xfs_vnode_t	*rvp = XFS_ITOV_NULL(rip);
    -	int		error;
    -
    -	if (rvp == NULL)
    -		return (0);
    -	xfs_ilock(rip, XFS_ILOCK_EXCL);
    -	xfs_iflock(rip);
    -
    -	/*
    -	 * Flush out the real time inodes.
    -	 */
    -	if ((rbmip = mp->m_rbmip) != NULL) {
    -		xfs_ilock(rbmip, XFS_ILOCK_EXCL);
    -		xfs_iflock(rbmip);
    -		error = xfs_iflush(rbmip, XFS_IFLUSH_SYNC);
    -		xfs_iunlock(rbmip, XFS_ILOCK_EXCL);
    -
    -		if (error == EFSCORRUPTED)
    -			goto fscorrupt_out;
    -
    -		ASSERT(vn_count(XFS_ITOV(rbmip)) == 1);
    -
    -		rsumip = mp->m_rsumip;
    -		xfs_ilock(rsumip, XFS_ILOCK_EXCL);
    -		xfs_iflock(rsumip);
    -		error = xfs_iflush(rsumip, XFS_IFLUSH_SYNC);
    -		xfs_iunlock(rsumip, XFS_ILOCK_EXCL);
    -
    -		if (error == EFSCORRUPTED)
    -			goto fscorrupt_out;
    -
    -		ASSERT(vn_count(XFS_ITOV(rsumip)) == 1);
    -	}
    -
    -	/*
    -	 * Synchronously flush root inode to disk
    -	 */
    -	error = xfs_iflush(rip, XFS_IFLUSH_SYNC);
    -	if (error == EFSCORRUPTED)
    -		goto fscorrupt_out2;
    -
    -	if (vn_count(rvp) != 1 && !relocation) {
    -		xfs_iunlock(rip, XFS_ILOCK_EXCL);
    -		return XFS_ERROR(EBUSY);
    -	}
    -
    -	/*
    -	 * Release dquot that rootinode, rbmino and rsumino might be holding,
    -	 * flush and purge the quota inodes.
    -	 */
    -	error = XFS_QM_UNMOUNT(mp);
    -	if (error == EFSCORRUPTED)
    -		goto fscorrupt_out2;
    -
    -	if (rbmip) {
    -		VN_RELE(XFS_ITOV(rbmip));
    -		VN_RELE(XFS_ITOV(rsumip));
    -	}
    -
    -	xfs_iunlock(rip, XFS_ILOCK_EXCL);
    -	return 0;
    -
    -fscorrupt_out:
    -	xfs_ifunlock(rip);
    -
    -fscorrupt_out2:
    -	xfs_iunlock(rip, XFS_ILOCK_EXCL);
    -
    -	return XFS_ERROR(EFSCORRUPTED);
    -}
    -
    -/*
    - * xfs_root extracts the root vnode from a vfs.
    - *
    - * vfsp -- the vfs struct for the desired file system
    - * vpp  -- address of the caller's vnode pointer which should be
    - *         set to the desired fs root vnode
    - */
    -STATIC int
    -xfs_root(
    -	bhv_desc_t	*bdp,
    -	xfs_vnode_t	**vpp)
    -{
    -	xfs_vnode_t	*vp;
    -
    -	vp = XFS_ITOV((XFS_BHVTOM(bdp))->m_rootip);
    -	VN_HOLD(vp);
    -	*vpp = vp;
    -	return 0;
    -}
    -
    -/*
    - * xfs_statvfs
    - *
    - * Fill in the statvfs structure for the given file system.  We use
    - * the superblock lock in the mount structure to ensure a consistent
    - * snapshot of the counters returned.
    - */
    -STATIC int
    -xfs_statvfs(
    -	bhv_desc_t	*bdp,
    -	xfs_statfs_t	*statp,
    -	xfs_vnode_t	*vp)
    -{
    -	__uint64_t	fakeinos;
    -	xfs_extlen_t	lsize;
    -	xfs_mount_t	*mp;
    -	xfs_sb_t	*sbp;
    -	unsigned long	s;
    -
    -	mp = XFS_BHVTOM(bdp);
    -	sbp = &(mp->m_sb);
    -
    -	statp->f_type = XFS_SB_MAGIC;
    -
    -	xfs_icsb_sync_counters_lazy(mp);
    -	s = XFS_SB_LOCK(mp);
    -	statp->f_bsize = sbp->sb_blocksize;
    -	lsize = sbp->sb_logstart ? sbp->sb_logblocks : 0;
    -	statp->f_blocks = sbp->sb_dblocks - lsize;
    -	statp->f_bfree = statp->f_bavail = sbp->sb_fdblocks;
    -	fakeinos = statp->f_bfree << sbp->sb_inopblog;
    -#if XFS_BIG_INUMS
    -	fakeinos += mp->m_inoadd;
    -#endif
    -	statp->f_files =
    -	    MIN(sbp->sb_icount + fakeinos, (__uint64_t)XFS_MAXINUMBER);
    -	if (mp->m_maxicount)
    -#if XFS_BIG_INUMS
    -		if (!mp->m_inoadd)
    -#endif
    -			statp->f_files = min_t(typeof(statp->f_files),
    -						statp->f_files,
    -						mp->m_maxicount);
    -	statp->f_ffree = statp->f_files - (sbp->sb_icount - sbp->sb_ifree);
    -	XFS_SB_UNLOCK(mp, s);
    -
    -	xfs_statvfs_fsid(statp, mp);
    -	return 0;
    -}
    -
    -
    -/*
    - * xfs_sync flushes any pending I/O to file system vfsp.
    - *
    - * This routine is called by vfs_sync() to make sure that things make it
    - * out to disk eventually, on sync() system calls to flush out everything,
    - * and when the file system is unmounted.  For the vfs_sync() case, all
    - * we really need to do is sync out the log to make all of our meta-data
    - * updates permanent (except for timestamps).  For calls from pflushd(),
    - * dirty pages are kept moving by calling pdflush() on the inodes
    - * containing them.  We also flush the inodes that we can lock without
    - * sleeping and the superblock if we can lock it without sleeping from
    - * vfs_sync() so that items at the tail of the log are always moving out.
    - *
    - * Flags:
    - *      SYNC_BDFLUSH - We're being called from vfs_sync() so we don't want
    - *		       to sleep if we can help it.  All we really need
    - *		       to do is ensure that the log is synced at least
    - *		       periodically.  We also push the inodes and
    - *		       superblock if we can lock them without sleeping
    - *			and they are not pinned.
    - *      SYNC_ATTR    - We need to flush the inodes.  If SYNC_BDFLUSH is not
    - *		       set, then we really want to lock each inode and flush
    - *		       it.
    - *      SYNC_WAIT    - All the flushes that take place in this call should
    - *		       be synchronous.
    - *      SYNC_DELWRI  - This tells us to push dirty pages associated with
    - *		       inodes.  SYNC_WAIT and SYNC_BDFLUSH are used to
    - *		       determine if they should be flushed sync, async, or
    - *		       delwri.
    - *      SYNC_CLOSE   - This flag is passed when the system is being
    - *		       unmounted.  We should sync and invalidate everything.
    - *      SYNC_FSDATA  - This indicates that the caller would like to make
    - *		       sure the superblock is safe on disk.  We can ensure
    - *		       this by simply making sure the log gets flushed
    - *		       if SYNC_BDFLUSH is set, and by actually writing it
    - *		       out otherwise.
    - *
    - */
    -/*ARGSUSED*/
    -STATIC int
    -xfs_sync(
    -	bhv_desc_t	*bdp,
    -	int		flags,
    -	cred_t		*credp)
    -{
    -	xfs_mount_t	*mp = XFS_BHVTOM(bdp);
    -
    -	if (unlikely(flags == SYNC_QUIESCE))
    -		return xfs_quiesce_fs(mp);
    -	else
    -		return xfs_syncsub(mp, flags, 0, NULL);
    -}
    -
    -/*
    - * xfs sync routine for internal use
    - *
    - * This routine supports all of the flags defined for the generic VFS_SYNC
    - * interface as explained above under xfs_sync.  In the interests of not
    - * changing interfaces within the 6.5 family, additional internally-
    - * required functions are specified within a separate xflags parameter,
    - * only available by calling this routine.
    - *
    - */
    -int
    -xfs_sync_inodes(
    -	xfs_mount_t	*mp,
    -	int		flags,
    -	int             xflags,
    -	int             *bypassed)
    -{
    -	xfs_inode_t	*ip = NULL;
    -	xfs_inode_t	*ip_next;
    -	xfs_buf_t	*bp;
    -	xfs_vnode_t	*vp = NULL;
    -	int		error;
    -	int		last_error;
    -	uint64_t	fflag;
    -	uint		lock_flags;
    -	uint		base_lock_flags;
    -	boolean_t	mount_locked;
    -	boolean_t	vnode_refed;
    -	int		preempt;
    -	xfs_dinode_t	*dip;
    -	xfs_iptr_t	*ipointer;
    -#ifdef DEBUG
    -	boolean_t	ipointer_in = B_FALSE;
    -
    -#define IPOINTER_SET	ipointer_in = B_TRUE
    -#define IPOINTER_CLR	ipointer_in = B_FALSE
    -#else
    -#define IPOINTER_SET
    -#define IPOINTER_CLR
    -#endif
    -
    -
    -/* Insert a marker record into the inode list after inode ip. The list
    - * must be locked when this is called. After the call the list will no
    - * longer be locked.
    - */
    -#define IPOINTER_INSERT(ip, mp)	{ \
    -		ASSERT(ipointer_in == B_FALSE); \
    -		ipointer->ip_mnext = ip->i_mnext; \
    -		ipointer->ip_mprev = ip; \
    -		ip->i_mnext = (xfs_inode_t *)ipointer; \
    -		ipointer->ip_mnext->i_mprev = (xfs_inode_t *)ipointer; \
    -		preempt = 0; \
    -		XFS_MOUNT_IUNLOCK(mp); \
    -		mount_locked = B_FALSE; \
    -		IPOINTER_SET; \
    -	}
    -
    -/* Remove the marker from the inode list. If the marker was the only item
    - * in the list then there are no remaining inodes and we should zero out
    - * the whole list. If we are the current head of the list then move the head
    - * past us.
    - */
    -#define IPOINTER_REMOVE(ip, mp)	{ \
    -		ASSERT(ipointer_in == B_TRUE); \
    -		if (ipointer->ip_mnext != (xfs_inode_t *)ipointer) { \
    -			ip = ipointer->ip_mnext; \
    -			ip->i_mprev = ipointer->ip_mprev; \
    -			ipointer->ip_mprev->i_mnext = ip; \
    -			if (mp->m_inodes == (xfs_inode_t *)ipointer) { \
    -				mp->m_inodes = ip; \
    -			} \
    -		} else { \
    -			ASSERT(mp->m_inodes == (xfs_inode_t *)ipointer); \
    -			mp->m_inodes = NULL; \
    -			ip = NULL; \
    -		} \
    -		IPOINTER_CLR; \
    -	}
    -
    -#define XFS_PREEMPT_MASK	0x7f
    -
    -	if (bypassed)
    -		*bypassed = 0;
    -	if (XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY)
    -		return 0;
    -	error = 0;
    -	last_error = 0;
    -	preempt = 0;
    -
    -	/* Allocate a reference marker */
    -	ipointer = (xfs_iptr_t *)kmem_zalloc(sizeof(xfs_iptr_t), KM_SLEEP);
    -
    -	fflag = XFS_B_ASYNC;		/* default is don't wait */
    -	if (flags & (SYNC_BDFLUSH | SYNC_DELWRI))
    -		fflag = XFS_B_DELWRI;
    -	if (flags & SYNC_WAIT)
    -		fflag = 0;		/* synchronous overrides all */
    -
    -	base_lock_flags = XFS_ILOCK_SHARED;
    -	if (flags & (SYNC_DELWRI | SYNC_CLOSE)) {
    -		/*
    -		 * We need the I/O lock if we're going to call any of
    -		 * the flush/inval routines.
    -		 */
    -		base_lock_flags |= XFS_IOLOCK_SHARED;
    -	}
    -
    -	XFS_MOUNT_ILOCK(mp);
    -
    -	ip = mp->m_inodes;
    -
    -	mount_locked = B_TRUE;
    -	vnode_refed  = B_FALSE;
    -
    -	IPOINTER_CLR;
    -
    -	do {
    -		ASSERT(ipointer_in == B_FALSE);
    -		ASSERT(vnode_refed == B_FALSE);
    -
    -		lock_flags = base_lock_flags;
    -
    -		/*
    -		 * There were no inodes in the list, just break out
    -		 * of the loop.
    -		 */
    -		if (ip == NULL) {
    -			break;
    -		}
    -
    -		/*
    -		 * We found another sync thread marker - skip it
    -		 */
    -		if (ip->i_mount == NULL) {
    -			ip = ip->i_mnext;
    -			continue;
    -		}
    -
    -		vp = XFS_ITOV_NULL(ip);
    -
    -		/*
    -		 * If the vnode is gone then this is being torn down,
    -		 * call reclaim if it is flushed, else let regular flush
    -		 * code deal with it later in the loop.
    -		 */
    -
    -		if (vp == NULL) {
    -			/* Skip ones already in reclaim */
    -			if (ip->i_flags & XFS_IRECLAIM) {
    -				ip = ip->i_mnext;
    -				continue;
    -			}
    -			if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL) == 0) {
    -				ip = ip->i_mnext;
    -			} else if ((xfs_ipincount(ip) == 0) &&
    -				    xfs_iflock_nowait(ip)) {
    -				IPOINTER_INSERT(ip, mp);
    -
    -				xfs_finish_reclaim(ip, 1,
    -						XFS_IFLUSH_DELWRI_ELSE_ASYNC);
    -
    -				XFS_MOUNT_ILOCK(mp);
    -				mount_locked = B_TRUE;
    -				IPOINTER_REMOVE(ip, mp);
    -			} else {
    -				xfs_iunlock(ip, XFS_ILOCK_EXCL);
    -				ip = ip->i_mnext;
    -			}
    -			continue;
    -		}
    -
    -		if (VN_BAD(vp)) {
    -			ip = ip->i_mnext;
    -			continue;
    -		}
    -
    -		if (XFS_FORCED_SHUTDOWN(mp) && !(flags & SYNC_CLOSE)) {
    -			XFS_MOUNT_IUNLOCK(mp);
    -			kmem_free(ipointer, sizeof(xfs_iptr_t));
    -			return 0;
    -		}
    -
    -		/*
    -		 * If this is just vfs_sync() or pflushd() calling
    -		 * then we can skip inodes for which it looks like
    -		 * there is nothing to do.  Since we don't have the
    -		 * inode locked this is racy, but these are periodic
    -		 * calls so it doesn't matter.  For the others we want
    -		 * to know for sure, so we at least try to lock them.
    -		 */
    -		if (flags & SYNC_BDFLUSH) {
    -			if (((ip->i_itemp == NULL) ||
    -			     !(ip->i_itemp->ili_format.ilf_fields &
    -			       XFS_ILOG_ALL)) &&
    -			    (ip->i_update_core == 0)) {
    -				ip = ip->i_mnext;
    -				continue;
    -			}
    -		}
    -
    -		/*
    -		 * Try to lock without sleeping.  We're out of order with
    -		 * the inode list lock here, so if we fail we need to drop
    -		 * the mount lock and try again.  If we're called from
    -		 * bdflush() here, then don't bother.
    -		 *
    -		 * The inode lock here actually coordinates with the
    -		 * almost spurious inode lock in xfs_ireclaim() to prevent
    -		 * the vnode we handle here without a reference from
    -		 * being freed while we reference it.  If we lock the inode
    -		 * while it's on the mount list here, then the spurious inode
    -		 * lock in xfs_ireclaim() after the inode is pulled from
    -		 * the mount list will sleep until we release it here.
    -		 * This keeps the vnode from being freed while we reference
    -		 * it.
    -		 */
    -		if (xfs_ilock_nowait(ip, lock_flags) == 0) {
    -			if ((flags & SYNC_BDFLUSH) || (vp == NULL)) {
    -				ip = ip->i_mnext;
    -				continue;
    -			}
    -
    -			vp = vn_grab(vp);
    -			if (vp == NULL) {
    -				ip = ip->i_mnext;
    -				continue;
    -			}
    -
    -			IPOINTER_INSERT(ip, mp);
    -			xfs_ilock(ip, lock_flags);
    -
    -			ASSERT(vp == XFS_ITOV(ip));
    -			ASSERT(ip->i_mount == mp);
    -
    -			vnode_refed = B_TRUE;
    -		}
    -
    -		/* From here on in the loop we may have a marker record
    -		 * in the inode list.
    -		 */
    -
    -		if ((flags & SYNC_CLOSE)  && (vp != NULL)) {
    -			/*
    -			 * This is the shutdown case.  We just need to
    -			 * flush and invalidate all the pages associated
    -			 * with the inode.  Drop the inode lock since
    -			 * we can't hold it across calls to the buffer
    -			 * cache.
    -			 *
    -			 * We don't set the VREMAPPING bit in the vnode
    -			 * here, because we don't hold the vnode lock
    -			 * exclusively.  It doesn't really matter, though,
    -			 * because we only come here when we're shutting
    -			 * down anyway.
    -			 */
    -			xfs_iunlock(ip, XFS_ILOCK_SHARED);
    -
    -			if (XFS_FORCED_SHUTDOWN(mp)) {
    -				XVOP_TOSS_PAGES(vp, 0, -1, FI_REMAPF);
    -			} else {
    -				XVOP_FLUSHINVAL_PAGES(vp, 0, -1, FI_REMAPF);
    -			}
    -
    -			xfs_ilock(ip, XFS_ILOCK_SHARED);
    -
    -		} else if ((flags & SYNC_DELWRI) && (vp != NULL)) {
    -			if (VN_DIRTY(vp)) {
    -				/* We need to have dropped the lock here,
    -				 * so insert a marker if we have not already
    -				 * done so.
    -				 */
    -				if (mount_locked) {
    -					IPOINTER_INSERT(ip, mp);
    -				}
    -
    -				/*
    -				 * Drop the inode lock since we can't hold it
    -				 * across calls to the buffer cache.
    -				 */
    -				xfs_iunlock(ip, XFS_ILOCK_SHARED);
    -				XVOP_FLUSH_PAGES(vp, (xfs_off_t)0, -1,
    -							fflag, FI_NONE, error);
    -				xfs_ilock(ip, XFS_ILOCK_SHARED);
    -			}
    -
    -		}
    -
    -		if (flags & SYNC_BDFLUSH) {
    -			if ((flags & SYNC_ATTR) &&
    -			    ((ip->i_update_core) ||
    -			     ((ip->i_itemp != NULL) &&
    -			      (ip->i_itemp->ili_format.ilf_fields != 0)))) {
    -
    -				/* Insert marker and drop lock if not already
    -				 * done.
    -				 */
    -				if (mount_locked) {
    -					IPOINTER_INSERT(ip, mp);
    -				}
    -
    -				/*
    -				 * We don't want the periodic flushing of the
    -				 * inodes by vfs_sync() to interfere with
    -				 * I/O to the file, especially read I/O
    -				 * where it is only the access time stamp
    -				 * that is being flushed out.  To prevent
    -				 * long periods where we have both inode
    -				 * locks held shared here while reading the
    -				 * inode's buffer in from disk, we drop the
    -				 * inode lock while reading in the inode
    -				 * buffer.  We have to release the buffer
    -				 * and reacquire the inode lock so that they
    -				 * are acquired in the proper order (inode
    -				 * locks first).  The buffer will go at the
    -				 * end of the lru chain, though, so we can
    -				 * expect it to still be there when we go
    -				 * for it again in xfs_iflush().
    -				 */
    -				if ((xfs_ipincount(ip) == 0) &&
    -				    xfs_iflock_nowait(ip)) {
    -
    -					xfs_ifunlock(ip);
    -					xfs_iunlock(ip, XFS_ILOCK_SHARED);
    -
    -					error = xfs_itobp(mp, NULL, ip,
    -							  &dip, &bp, 0, 0);
    -					if (!error) {
    -						xfs_buf_relse(bp);
    -					} else {
    -						/* Bailing out, remove the
    -						 * marker and free it.
    -						 */
    -						XFS_MOUNT_ILOCK(mp);
    -
    -						IPOINTER_REMOVE(ip, mp);
    -
    -						XFS_MOUNT_IUNLOCK(mp);
    -
    -						ASSERT(!(lock_flags &
    -							XFS_IOLOCK_SHARED));
    -
    -						kmem_free(ipointer,
    -							sizeof(xfs_iptr_t));
    -						return (0);
    -					}
    -
    -					/*
    -					 * Since we dropped the inode lock,
    -					 * the inode may have been reclaimed.
    -					 * Therefore, we reacquire the mount
    -					 * lock and check to see if we were the
    -					 * inode reclaimed. If this happened
    -					 * then the ipointer marker will no
    -					 * longer point back at us. In this
    -					 * case, move ip along to the inode
    -					 * after the marker, remove the marker
    -					 * and continue.
    -					 */
    -					XFS_MOUNT_ILOCK(mp);
    -					mount_locked = B_TRUE;
    -
    -					if (ip != ipointer->ip_mprev) {
    -						IPOINTER_REMOVE(ip, mp);
    -
    -						ASSERT(!vnode_refed);
    -						ASSERT(!(lock_flags &
    -							XFS_IOLOCK_SHARED));
    -						continue;
    -					}
    -
    -					ASSERT(ip->i_mount == mp);
    -
    -					if (xfs_ilock_nowait(ip,
    -						    XFS_ILOCK_SHARED) == 0) {
    -						ASSERT(ip->i_mount == mp);
    -						/*
    -						 * We failed to reacquire
    -						 * the inode lock without
    -						 * sleeping, so just skip
    -						 * the inode for now.  We
    -						 * clear the ILOCK bit from
    -						 * the lock_flags so that we
    -						 * won't try to drop a lock
    -						 * we don't hold below.
    -						 */
    -						lock_flags &= ~XFS_ILOCK_SHARED;
    -						IPOINTER_REMOVE(ip_next, mp);
    -					} else if ((xfs_ipincount(ip) == 0) &&
    -						   xfs_iflock_nowait(ip)) {
    -						ASSERT(ip->i_mount == mp);
    -						/*
    -						 * Since this is vfs_sync()
    -						 * calling we only flush the
    -						 * inode out if we can lock
    -						 * it without sleeping and
    -						 * it is not pinned.  Drop
    -						 * the mount lock here so
    -						 * that we don't hold it for
    -						 * too long. We already have
    -						 * a marker in the list here.
    -						 */
    -						XFS_MOUNT_IUNLOCK(mp);
    -						mount_locked = B_FALSE;
    -						error = xfs_iflush(ip,
    -							   XFS_IFLUSH_DELWRI);
    -					} else {
    -						ASSERT(ip->i_mount == mp);
    -						IPOINTER_REMOVE(ip_next, mp);
    -					}
    -				}
    -
    -			}
    -
    -		} else {
    -			if ((flags & SYNC_ATTR) &&
    -			    ((ip->i_update_core) ||
    -			     ((ip->i_itemp != NULL) &&
    -			      (ip->i_itemp->ili_format.ilf_fields != 0)))) {
    -				if (mount_locked) {
    -					IPOINTER_INSERT(ip, mp);
    -				}
    -
    -				if (flags & SYNC_WAIT) {
    -					xfs_iflock(ip);
    -					error = xfs_iflush(ip,
    -							   XFS_IFLUSH_SYNC);
    -				} else {
    -					/*
    -					 * If we can't acquire the flush
    -					 * lock, then the inode is already
    -					 * being flushed so don't bother
    -					 * waiting.  If we can lock it then
    -					 * do a delwri flush so we can
    -					 * combine multiple inode flushes
    -					 * in each disk write.
    -					 */
    -					if (xfs_iflock_nowait(ip)) {
    -						error = xfs_iflush(ip,
    -							   XFS_IFLUSH_DELWRI);
    -					}
    -					else if (bypassed)
    -						(*bypassed)++;
    -				}
    -			}
    -		}
    -
    -		if (lock_flags != 0) {
    -			xfs_iunlock(ip, lock_flags);
    -		}
    -
    -		if (vnode_refed) {
    -			/*
    -			 * If we had to take a reference on the vnode
    -			 * above, then wait until after we've unlocked
    -			 * the inode to release the reference.  This is
    -			 * because we can be already holding the inode
    -			 * lock when VN_RELE() calls xfs_inactive().
    -			 *
    -			 * Make sure to drop the mount lock before calling
    -			 * VN_RELE() so that we don't trip over ourselves if
    -			 * we have to go for the mount lock again in the
    -			 * inactive code.
    -			 */
    -			if (mount_locked) {
    -				IPOINTER_INSERT(ip, mp);
    -			}
    -
    -			VN_RELE(vp);
    -
    -			vnode_refed = B_FALSE;
    -		}
    -
    -		if (error) {
    -			last_error = error;
    -		}
    -
    -		/*
    -		 * bail out if the filesystem is corrupted.
    -		 */
    -		if (error == EFSCORRUPTED)  {
    -			if (!mount_locked) {
    -				XFS_MOUNT_ILOCK(mp);
    -				IPOINTER_REMOVE(ip, mp);
    -			}
    -			XFS_MOUNT_IUNLOCK(mp);
    -			ASSERT(ipointer_in == B_FALSE);
    -			kmem_free(ipointer, sizeof(xfs_iptr_t));
    -			return XFS_ERROR(error);
    -		}
    -
    -		/* Let other threads have a chance at the mount lock
    -		 * if we have looped many times without dropping the
    -		 * lock.
    -		 */
    -		if ((++preempt & XFS_PREEMPT_MASK) == 0) {
    -			if (mount_locked) {
    -				IPOINTER_INSERT(ip, mp);
    -			}
    -		}
    -
    -		if (mount_locked == B_FALSE) {
    -			XFS_MOUNT_ILOCK(mp);
    -			mount_locked = B_TRUE;
    -			IPOINTER_REMOVE(ip, mp);
    -			continue;
    -		}
    -
    -		ASSERT(ipointer_in == B_FALSE);
    -		ip = ip->i_mnext;
    -
    -	} while (ip != mp->m_inodes);
    -
    -	XFS_MOUNT_IUNLOCK(mp);
    -
    -	ASSERT(ipointer_in == B_FALSE);
    -
    -	kmem_free(ipointer, sizeof(xfs_iptr_t));
    -	return XFS_ERROR(last_error);
    -}
    -
    -/*
    - * xfs sync routine for internal use
    - *
    - * This routine supports all of the flags defined for the generic VFS_SYNC
    - * interface as explained above under xfs_sync.  In the interests of not
    - * changing interfaces within the 6.5 family, additional internally-
    - * required functions are specified within a separate xflags parameter,
    - * only available by calling this routine.
    - *
    - */
    -int
    -xfs_syncsub(
    -	xfs_mount_t	*mp,
    -	int		flags,
    -	int             xflags,
    -	int             *bypassed)
    -{
    -	int		error = 0;
    -	int		last_error = 0;
    -	uint		log_flags = XFS_LOG_FORCE;
    -	xfs_buf_t	*bp;
    -	xfs_buf_log_item_t	*bip;
    -
    -	/*
    -	 * Sync out the log.  This ensures that the log is periodically
    -	 * flushed even if there is not enough activity to fill it up.
    -	 */
    -	if (flags & SYNC_WAIT)
    -		log_flags |= XFS_LOG_SYNC;
    -
    -	xfs_log_force(mp, (xfs_lsn_t)0, log_flags);
    -
    -	if (flags & (SYNC_ATTR|SYNC_DELWRI)) {
    -		if (flags & SYNC_BDFLUSH)
    -			xfs_finish_reclaim_all(mp, 1);
    -		else
    -			error = xfs_sync_inodes(mp, flags, xflags, bypassed);
    -	}
    -
    -	/*
    -	 * Flushing out dirty data above probably generated more
    -	 * log activity, so if this isn't vfs_sync() then flush
    -	 * the log again.
    -	 */
    -	if (flags & SYNC_DELWRI) {
    -		xfs_log_force(mp, (xfs_lsn_t)0, log_flags);
    -	}
    -
    -	if (flags & SYNC_FSDATA) {
    -		/*
    -		 * If this is vfs_sync() then only sync the superblock
    -		 * if we can lock it without sleeping and it is not pinned.
    -		 */
    -		if (flags & SYNC_BDFLUSH) {
    -			bp = xfs_getsb(mp, XFS_BUF_TRYLOCK);
    -			if (bp != NULL) {
    -				bip = XFS_BUF_FSPRIVATE(bp,xfs_buf_log_item_t*);
    -				if ((bip != NULL) &&
    -				    xfs_buf_item_dirty(bip)) {
    -					if (!(XFS_BUF_ISPINNED(bp))) {
    -						XFS_BUF_ASYNC(bp);
    -						error = xfs_bwrite(mp, bp);
    -					} else {
    -						xfs_buf_relse(bp);
    -					}
    -				} else {
    -					xfs_buf_relse(bp);
    -				}
    -			}
    -		} else {
    -			bp = xfs_getsb(mp, 0);
    -			/*
    -			 * If the buffer is pinned then push on the log so
    -			 * we won't get stuck waiting in the write for
    -			 * someone, maybe ourselves, to flush the log.
    -			 * Even though we just pushed the log above, we
    -			 * did not have the superblock buffer locked at
    -			 * that point so it can become pinned in between
    -			 * there and here.
    -			 */
    -			if (XFS_BUF_ISPINNED(bp))
    -				xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE);
    -			if (flags & SYNC_WAIT)
    -				XFS_BUF_UNASYNC(bp);
    -			else
    -				XFS_BUF_ASYNC(bp);
    -			error = xfs_bwrite(mp, bp);
    -		}
    -		if (error) {
    -			last_error = error;
    -		}
    -	}
    -
    -	/*
    -	 * If this is the periodic sync, then kick some entries out of
    -	 * the reference cache.  This ensures that idle entries are
    -	 * eventually kicked out of the cache.
    -	 */
    -	if (flags & SYNC_REFCACHE) {
    -		if (flags & SYNC_WAIT)
    -			xfs_refcache_purge_mp(mp);
    -		else
    -			xfs_refcache_purge_some(mp);
    -	}
    -
    -	/*
    -	 * Now check to see if the log needs a "dummy" transaction.
    -	 */
    -
    -	if (!(flags & SYNC_REMOUNT) && xfs_log_need_covered(mp)) {
    -		xfs_trans_t *tp;
    -		xfs_inode_t *ip;
    -
    -		/*
    -		 * Put a dummy transaction in the log to tell
    -		 * recovery that all others are OK.
    -		 */
    -		tp = xfs_trans_alloc(mp, XFS_TRANS_DUMMY1);
    -		if ((error = xfs_trans_reserve(tp, 0,
    -				XFS_ICHANGE_LOG_RES(mp),
    -				0, 0, 0)))  {
    -			xfs_trans_cancel(tp, 0);
    -			return error;
    -		}
    -
    -		ip = mp->m_rootip;
    -		xfs_ilock(ip, XFS_ILOCK_EXCL);
    -
    -		xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
    -		xfs_trans_ihold(tp, ip);
    -		xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
    -		error = xfs_trans_commit(tp, 0, NULL);
    -		xfs_iunlock(ip, XFS_ILOCK_EXCL);
    -		xfs_log_force(mp, (xfs_lsn_t)0, log_flags);
    -	}
    -
    -	/*
    -	 * When shutting down, we need to insure that the AIL is pushed
    -	 * to disk or the filesystem can appear corrupt from the PROM.
    -	 */
    -	if ((flags & (SYNC_CLOSE|SYNC_WAIT)) == (SYNC_CLOSE|SYNC_WAIT)) {
    -		XFS_bflush(mp->m_ddev_targp);
    -		if (mp->m_rtdev_targp) {
    -			XFS_bflush(mp->m_rtdev_targp);
    -		}
    -	}
    -
    -	return XFS_ERROR(last_error);
    -}
    -
    -/*
    - * xfs_vget - called by DMAPI and NFSD to get vnode from file handle
    - */
    -STATIC int
    -xfs_vget(
    -	bhv_desc_t	*bdp,
    -	xfs_vnode_t	**vpp,
    -	fid_t		*fidp)
    -{
    -	xfs_mount_t	*mp = XFS_BHVTOM(bdp);
    -	xfs_fid_t	*xfid = (struct xfs_fid *)fidp;
    -	xfs_inode_t	*ip;
    -	int		error;
    -	xfs_ino_t	ino;
    -	unsigned int	igen;
    -
    -	/*
    -	 * Invalid.  Since handles can be created in user space and passed in
    -	 * via gethandle(), this is not cause for a panic.
    -	 */
    -	if (xfid->xfs_fid_len != sizeof(*xfid) - sizeof(xfid->xfs_fid_len))
    -		return XFS_ERROR(EINVAL);
    -
    -	ino  = xfid->xfs_fid_ino;
    -	igen = xfid->xfs_fid_gen;
    -
    -	/*
    -	 * NFS can sometimes send requests for ino 0.  Fail them gracefully.
    -	 */
    -	if (ino == 0)
    -		return XFS_ERROR(ESTALE);
    -
    -	error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, 0);
    -	if (error) {
    -		*vpp = NULL;
    -		return error;
    -	}
    -
    -	if (ip == NULL) {
    -		*vpp = NULL;
    -		return XFS_ERROR(EIO);
    -	}
    -
    -	if (ip->i_d.di_mode == 0 || ip->i_d.di_gen != igen) {
    -		xfs_iput_new(ip, XFS_ILOCK_SHARED);
    -		*vpp = NULL;
    -		return XFS_ERROR(ENOENT);
    -	}
    -
    -	*vpp = XFS_ITOV(ip);
    -	xfs_iunlock(ip, XFS_ILOCK_SHARED);
    -	return 0;
    -}
    -
    -
    -#define MNTOPT_LOGBUFS		"logbufs"	/* number of XFS log buffers */
    -#define MNTOPT_LOGBSIZE		"logbsize"	/* size of XFS log buffers */
    -#define MNTOPT_LOGDEV		"logdev"	/* log device */
    -#define MNTOPT_RTDEV		"rtdev"		/* realtime I/O device */
    -#define MNTOPT_BIOSIZE		"biosize"	/* log2 of preferred buffered io size */
    -#define MNTOPT_WSYNC		"wsync"		/* safe-mode nfs compatible mount */
    -#define MNTOPT_INO64		"ino64"		/* force inodes into 64-bit range */
    -#define MNTOPT_NOALIGN		"noalign"	/* turn off stripe alignment */
    -#define MNTOPT_SWALLOC		"swalloc"	/* turn on stripe width allocation */
    -#define MNTOPT_SUNIT		"sunit"		/* data volume stripe unit */
    -#define MNTOPT_SWIDTH		"swidth"	/* data volume stripe width */
    -#define MNTOPT_NOUUID		"nouuid"	/* ignore filesystem UUID */
    -#define MNTOPT_MTPT		"mtpt"		/* filesystem mount point */
    -#define MNTOPT_GRPID		"grpid"		/* group-ID from parent directory */
    -#define MNTOPT_NOGRPID		"nogrpid"	/* group-ID from current process */
    -#define MNTOPT_BSDGROUPS	"bsdgroups"    /* group-ID from parent directory */
    -#define MNTOPT_SYSVGROUPS	"sysvgroups"   /* group-ID from current process */
    -#define MNTOPT_ALLOCSIZE	"allocsize"    /* preferred allocation size */
    -#define MNTOPT_IHASHSIZE	"ihashsize"    /* size of inode hash table */
    -#define MNTOPT_NORECOVERY	"norecovery"   /* don't run XFS recovery */
    -#define MNTOPT_BARRIER		"barrier"	/* use writer barriers for log write and
    -					 * unwritten extent conversion */
    -#define MNTOPT_NOBARRIER	"nobarrier"	/* .. disable */
    -#define MNTOPT_OSYNCISOSYNC	"osyncisosync" /* o_sync is REALLY o_sync */
    -#define MNTOPT_64BITINODE	"inode64"	/* inodes can be allocated anywhere */
    -#define MNTOPT_IKEEP		"ikeep"		/* do not free empty inode clusters */
    -#define MNTOPT_NOIKEEP		"noikeep"	/* free empty inode clusters */
    -#define MNTOPT_LARGEIO		"largeio"	/* report large I/O sizes in stat() */
    -#define MNTOPT_NOLARGEIO	"nolargeio"	/* do not report large I/O sizes
    -					 * in stat(). */
    -#define MNTOPT_ATTR2		"attr2"		/* do use attr2 attribute format */
    -#define MNTOPT_NOATTR2		"noattr2"	/* do not use attr2 attribute format */
    -#define simple_strtoul		strtoul
    -
    -STATIC unsigned long
    -suffix_strtoul(char *cp, char **endp, unsigned int base)
    -{
    -	int	last, shift_left_factor = 0;
    -	char	*value = (char *)cp;
    -
    -	last = strlen(value) - 1;
    -	if (value[last] == 'K' || value[last] == 'k') {
    -		shift_left_factor = 10;
    -		value[last] = '\0';
    -	}
    -	if (value[last] == 'M' || value[last] == 'm') {
    -		shift_left_factor = 20;
    -		value[last] = '\0';
    -	}
    -	if (value[last] == 'G' || value[last] == 'g') {
    -		shift_left_factor = 30;
    -		value[last] = '\0';
    -	}
    -
    -	return simple_strtoul(cp, endp, base) << shift_left_factor;
    -}
    -
    -
    -STATIC int
    -xfs_parseargs(
    -	struct bhv_desc		*bhv,
    -	char			*options,
    -	struct xfs_mount_args	*args,
    -	int			update)
    -{
    -	struct xfs_vfs		*vfsp = bhvtovfs(bhv);
    -	char			*this_char, *value, *eov;
    -	int			dsunit, dswidth, vol_dsunit, vol_dswidth;
    -	int			iosize;
    -
    -	args->flags |= XFSMNT_IDELETE;
    -	args->flags |= XFSMNT_BARRIER;
    -	args->flags2 |= XFSMNT2_COMPAT_IOSIZE;
    -
    -	if (!options)
    -		goto done;
    -
    -	iosize = dsunit = dswidth = vol_dsunit = vol_dswidth = 0;
    -
    -	while ((this_char = strsep(&options, ",")) != NULL) {
    -		if (!*this_char)
    -			continue;
    -		if ((value = strchr(this_char, '=')) != NULL)
    -			*value++ = 0;
    -
    -		if (!strcmp(this_char, MNTOPT_LOGBUFS)) {
    -			if (!value || !*value) {
    -				printf("XFS: %s option requires an argument\n",
    -					this_char);
    -				return EINVAL;
    -			}
    -			args->logbufs = simple_strtoul(value, &eov, 10);
    -		} else if (!strcmp(this_char, MNTOPT_LOGBSIZE)) {
    -			if (!value || !*value) {
    -				printf("XFS: %s option requires an argument\n",
    -					this_char);
    -				return EINVAL;
    -			}
    -			args->logbufsize = suffix_strtoul(value, &eov, 10);
    -		} else if (!strcmp(this_char, MNTOPT_LOGDEV)) {
    -			if (!value || !*value) {
    -				printf("XFS: %s option requires an argument\n",
    -					this_char);
    -				return EINVAL;
    -			}
    -			strncpy(args->logname, value, MAXNAMELEN);
    -		} else if (!strcmp(this_char, MNTOPT_MTPT)) {
    -			if (!value || !*value) {
    -				printf("XFS: %s option requires an argument\n",
    -					this_char);
    -				return EINVAL;
    -			}
    -			strncpy(args->mtpt, value, MAXNAMELEN);
    -		} else if (!strcmp(this_char, MNTOPT_RTDEV)) {
    -			if (!value || !*value) {
    -				printf("XFS: %s option requires an argument\n",
    -					this_char);
    -				return EINVAL;
    -			}
    -			strncpy(args->rtname, value, MAXNAMELEN);
    -		} else if (!strcmp(this_char, MNTOPT_BIOSIZE)) {
    -			if (!value || !*value) {
    -				printf("XFS: %s option requires an argument\n",
    -					this_char);
    -				return EINVAL;
    -			}
    -			iosize = simple_strtoul(value, &eov, 10);
    -			args->flags |= XFSMNT_IOSIZE;
    -			args->iosizelog = (uint8_t) iosize;
    -		} else if (!strcmp(this_char, MNTOPT_ALLOCSIZE)) {
    -			if (!value || !*value) {
    -				printk("XFS: %s option requires an argument\n",
    -					this_char);
    -				return EINVAL;
    -			}
    -			iosize = suffix_strtoul(value, &eov, 10);
    -			args->flags |= XFSMNT_IOSIZE;
    -			args->iosizelog = ffs(iosize) - 1;
    -		} else if (!strcmp(this_char, MNTOPT_IHASHSIZE)) {
    -			if (!value || !*value) {
    -				printk("XFS: %s option requires an argument\n",
    -					this_char);
    -				return EINVAL;
    -			}
    -			args->flags |= XFSMNT_IHASHSIZE;
    -			args->ihashsize = simple_strtoul(value, &eov, 10);
    -		} else if (!strcmp(this_char, MNTOPT_GRPID) ||
    -			   !strcmp(this_char, MNTOPT_BSDGROUPS)) {
    -			vfsp->vfs_flag |= VFS_GRPID;
    -		} else if (!strcmp(this_char, MNTOPT_NOGRPID) ||
    -			   !strcmp(this_char, MNTOPT_SYSVGROUPS)) {
    -			vfsp->vfs_flag &= ~VFS_GRPID;
    -		} else if (!strcmp(this_char, MNTOPT_WSYNC)) {
    -			args->flags |= XFSMNT_WSYNC;
    -		} else if (!strcmp(this_char, MNTOPT_OSYNCISOSYNC)) {
    -			args->flags |= XFSMNT_OSYNCISOSYNC;
    -		} else if (!strcmp(this_char, MNTOPT_NORECOVERY)) {
    -			args->flags |= XFSMNT_NORECOVERY;
    -		} else if (!strcmp(this_char, MNTOPT_INO64)) {
    -			args->flags |= XFSMNT_INO64;
    -#if !XFS_BIG_INUMS
    -
    -			printf("XFS: %s option not allowed on this system\n",
    -				this_char);
    -			return EINVAL;
    -#endif
    -		} else if (!strcmp(this_char, MNTOPT_NOALIGN)) {
    -			args->flags |= XFSMNT_NOALIGN;
    -		} else if (!strcmp(this_char, MNTOPT_SWALLOC)) {
    -			args->flags |= XFSMNT_SWALLOC;
    -		} else if (!strcmp(this_char, MNTOPT_SUNIT)) {
    -			if (!value || !*value) {
    -				printf("XFS: %s option requires an argument\n",
    -					this_char);
    -				return EINVAL;
    -			}
    -			dsunit = simple_strtoul(value, &eov, 10);
    -		} else if (!strcmp(this_char, MNTOPT_SWIDTH)) {
    -			if (!value || !*value) {
    -				printf("XFS: %s option requires an argument\n",
    -					this_char);
    -				return EINVAL;
    -			}
    -			dswidth = simple_strtoul(value, &eov, 10);
    -		} else if (!strcmp(this_char, MNTOPT_64BITINODE)) {
    -			args->flags &= ~XFSMNT_32BITINODES;
    -#if !XFS_BIG_INUMS
    -
    -			printf("XFS: %s option not allowed on this system\n",
    -				this_char);
    -			return EINVAL;
    -#endif
    -		} else if (!strcmp(this_char, MNTOPT_NOUUID)) {
    -			args->flags |= XFSMNT_NOUUID;
    -		} else if (!strcmp(this_char, MNTOPT_BARRIER)) {
    -			args->flags |= XFSMNT_BARRIER;
    -		} else if (!strcmp(this_char, MNTOPT_NOBARRIER)) {
    -			args->flags &= ~XFSMNT_BARRIER;
    -		} else if (!strcmp(this_char, MNTOPT_IKEEP)) {
    -			args->flags &= ~XFSMNT_IDELETE;
    -		} else if (!strcmp(this_char, MNTOPT_NOIKEEP)) {
    -			args->flags |= XFSMNT_IDELETE;
    -		} else if (!strcmp(this_char, MNTOPT_LARGEIO)) {
    -			args->flags2 &= ~XFSMNT2_COMPAT_IOSIZE;
    -		} else if (!strcmp(this_char, MNTOPT_NOLARGEIO)) {
    -			args->flags2 |= XFSMNT2_COMPAT_IOSIZE;
    -		} else if (!strcmp(this_char, MNTOPT_ATTR2)) {
    -			args->flags |= XFSMNT_ATTR2;
    -		} else if (!strcmp(this_char, MNTOPT_NOATTR2)) {
    -			args->flags &= ~XFSMNT_ATTR2;
    -		} else if (!strcmp(this_char, "osyncisdsync")) {
    -			/* no-op, this is now the default */
    -printf("XFS: osyncisdsync is now the default, option is deprecated.\n");
    -		} else if (!strcmp(this_char, "irixsgid")) {
    -printf("XFS: irixsgid is now a sysctl(2) variable, option is deprecated.\n");
    -		} else {
    -			printf("XFS: unknown mount option [%s].\n", this_char);
    -			return EINVAL;
    -		}
    -	}
    -
    -	if (args->flags & XFSMNT_NORECOVERY) {
    -		if ((vfsp->vfs_flag & VFS_RDONLY) == 0) {
    -			printf("XFS: no-recovery mounts must be read-only.\n");
    -			return EINVAL;
    -		}
    -	}
    -
    -	if ((args->flags & XFSMNT_NOALIGN) && (dsunit || dswidth)) {
    -		printf(
    -	"XFS: sunit and swidth options incompatible with the noalign option\n");
    -		return EINVAL;
    -	}
    -
    -	if ((dsunit && !dswidth) || (!dsunit && dswidth)) {
    -		printf("XFS: sunit and swidth must be specified together\n");
    -		return EINVAL;
    -	}
    -
    -	if (dsunit && (dswidth % dsunit != 0)) {
    -		printf(
    -	"XFS: stripe width (%d) must be a multiple of the stripe unit (%d)\n",
    -			dswidth, dsunit);
    -		return EINVAL;
    -	}
    -
    -	if ((args->flags & XFSMNT_NOALIGN) != XFSMNT_NOALIGN) {
    -		if (dsunit) {
    -			args->sunit = dsunit;
    -			args->flags |= XFSMNT_RETERR;
    -		} else {
    -			args->sunit = vol_dsunit;
    -		}
    -		dswidth ? (args->swidth = dswidth) :
    -			  (args->swidth = vol_dswidth);
    -	} else {
    -		args->sunit = args->swidth = 0;
    -	}
    -
    -done:
    -	if (args->flags & XFSMNT_32BITINODES)
    -		vfsp->vfs_flag |= VFS_32BITINODES;
    -	if (args->flags2)
    -		args->flags |= XFSMNT_FLAGS2;
    -	return 0;
    -}
    -
    -#define seq_printf sbuf_printf
    -STATIC int
    -xfs_showargs(
    -	struct bhv_desc		*bhv,
    -	struct sbuf		*m)
    -{
    -	static struct proc_xfs_info {
    -		int	flag;
    -		char	*str;
    -	} xfs_info[] = {
    -		/* the few simple ones we can get from the mount struct */
    -		{ XFS_MOUNT_WSYNC,		"," MNTOPT_WSYNC },
    -		{ XFS_MOUNT_INO64,		"," MNTOPT_INO64 },
    -		{ XFS_MOUNT_NOALIGN,		"," MNTOPT_NOALIGN },
    -		{ XFS_MOUNT_SWALLOC,		"," MNTOPT_SWALLOC },
    -		{ XFS_MOUNT_NOUUID,		"," MNTOPT_NOUUID },
    -		{ XFS_MOUNT_NORECOVERY,		"," MNTOPT_NORECOVERY },
    -		{ XFS_MOUNT_OSYNCISOSYNC,	"," MNTOPT_OSYNCISOSYNC },
    -		{ 0, NULL }
    -	};
    -	struct proc_xfs_info	*xfs_infop;
    -	struct xfs_mount	*mp = XFS_BHVTOM(bhv);
    -	struct xfs_vfs		*vfsp = XFS_MTOVFS(mp);
    -
    -	for (xfs_infop = xfs_info; xfs_infop->flag; xfs_infop++) {
    -		if (mp->m_flags & xfs_infop->flag)
    -			sbuf_printf(m, "%s", xfs_infop->str);
    -	}
    -
    -	if (mp->m_flags & XFS_MOUNT_IHASHSIZE)
    -		seq_printf(m, "," MNTOPT_IHASHSIZE "=%d", mp->m_ihsize);
    -
    -	if (mp->m_flags & XFS_MOUNT_DFLT_IOSIZE)
    -		seq_printf(m, "," MNTOPT_ALLOCSIZE "=%dk",
    -				(int)(1 << mp->m_writeio_log) >> 10);
    -
    -	if (mp->m_logbufs > 0)
    -		sbuf_printf(m, "," MNTOPT_LOGBUFS "=%d", mp->m_logbufs);
    -	if (mp->m_logbsize > 0)
    -		seq_printf(m, "," MNTOPT_LOGBSIZE "=%dk", mp->m_logbsize >> 10);
    -
    -	if (mp->m_logname)
    -		seq_printf(m, "," MNTOPT_LOGDEV "=%s", mp->m_logname);
    -	if (mp->m_rtname)
    -		seq_printf(m, "," MNTOPT_RTDEV "=%s", mp->m_rtname);
    -
    -	if (mp->m_dalign > 0)
    -		sbuf_printf(m, "," MNTOPT_SUNIT "=%d",
    -				(int)XFS_FSB_TO_BB(mp, mp->m_dalign));
    -	if (mp->m_swidth > 0)
    -		sbuf_printf(m, "," MNTOPT_SWIDTH "=%d",
    -				(int)XFS_FSB_TO_BB(mp, mp->m_swidth));
    -
    -	if (!(mp->m_flags & XFS_MOUNT_IDELETE))
    -		seq_printf(m, "," MNTOPT_IKEEP);
    -	if (!(mp->m_flags & XFS_MOUNT_COMPAT_IOSIZE))
    -		seq_printf(m, "," MNTOPT_LARGEIO);
    -
    -	if (!(vfsp->vfs_flag & VFS_32BITINODES))
    -		sbuf_printf(m, "," MNTOPT_64BITINODE);
    -	if (vfsp->vfs_flag & VFS_GRPID)
    -		seq_printf(m, "," MNTOPT_GRPID);
    -
    -	return 0;
    -}
    -
    -STATIC void
    -xfs_freeze(
    -	bhv_desc_t	*bdp)
    -{
    -	xfs_mount_t	*mp = XFS_BHVTOM(bdp);
    -
    -	while (atomic_read(&mp->m_active_trans) > 0)
    -		delay(100);
    -
    -	/* Push the superblock and write an unmount record */
    -	xfs_log_unmount_write(mp);
    -	xfs_unmountfs_writesb(mp);
    -	xfs_fs_log_dummy(mp);
    -}
    -
    -
    -xvfsops_t xfs_vfsops = {
    -	BHV_IDENTITY_INIT(VFS_BHV_XFS,VFS_POSITION_XFS),
    -	.xvfs_parseargs		= xfs_parseargs,
    -	.xvfs_showargs		= xfs_showargs,
    -	.xvfs_mount		= xfs_mount,
    -	.xvfs_unmount		= xfs_unmount,
    -	.xvfs_mntupdate		= xfs_mntupdate,
    -	.xvfs_root		= xfs_root,
    -	.xvfs_statvfs		= xfs_statvfs,
    -	.xvfs_sync		= xfs_sync,
    -	.xvfs_vget		= xfs_vget,
    -	.xvfs_dmapiops		= (xvfs_dmapiops_t)fs_nosys,
    -	.xvfs_quotactl		= (xvfs_quotactl_t)fs_nosys,
    -	.xvfs_get_inode		= (xvfs_get_inode_t)fs_nosys,
    -	.xvfs_init_vnode	= xfs_initialize_vnode,
    -	.xvfs_force_shutdown	= xfs_do_force_shutdown,
    -	.xvfs_freeze		= xfs_freeze,
    -};
    diff --git a/sys/gnu/fs/xfs/xfs_vnodeops.c b/sys/gnu/fs/xfs/xfs_vnodeops.c
    deleted file mode 100644
    index 4743cc7cdff..00000000000
    --- a/sys/gnu/fs/xfs/xfs_vnodeops.c
    +++ /dev/null
    @@ -1,4719 +0,0 @@
    -/*
    - * Copyright (c) 2000-2006 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -
    -#include "xfs.h"
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_da_btree.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_inode_item.h"
    -#include "xfs_dir_leaf.h"
    -#include "xfs_itable.h"
    -#include "xfs_btree.h"
    -#include "xfs_ialloc.h"
    -#include "xfs_alloc.h"
    -#include "xfs_bmap.h"
    -#include "xfs_attr.h"
    -#include "xfs_rw.h"
    -#include "xfs_error.h"
    -#include "xfs_quota.h"
    -#include "xfs_utils.h"
    -#include "xfs_rtalloc.h"
    -#include "xfs_refcache.h"
    -#include "xfs_trans_space.h"
    -#include "xfs_log_priv.h"
    -#include "xfs_mac.h"
    -
    -#include "xfs_fs.h"
    -
    -/*
    - * The maximum pathlen is 1024 bytes. Since the minimum file system
    - * blocksize is 512 bytes, we can get a max of 2 extents back from
    - * bmapi.
    - */
    -#define SYMLINK_MAPS 2
    -
    -/*
    - * For xfs, we check that the file isn't too big to be opened by this kernel.
    - * No other open action is required for regular files.  Devices are handled
    - * through the specfs file system, pipes through fifofs.  Device and
    - * fifo vnodes are "wrapped" by specfs and fifofs vnodes, respectively,
    - * when a new vnode is first looked up or created.
    - */
    -STATIC int
    -xfs_open(
    -	bhv_desc_t	*bdp,
    -	cred_t		*credp)
    -{
    -	int		mode;
    -	xfs_vnode_t	*vp;
    -	xfs_inode_t	*ip;
    -
    -	vp = BHV_TO_VNODE(bdp);
    -	ip = XFS_BHVTOI(bdp);
    -
    -	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
    -		return XFS_ERROR(EIO);
    -
    -	/*
    -	 * If it's a directory with any blocks, read-ahead block 0
    -	 * as we're almost certain to have the next operation be a read there.
    -	 */
    -	if (VN_ISDIR(vp) && ip->i_d.di_nextents > 0) {
    -		mode = xfs_ilock_map_shared(ip);
    -		if (ip->i_d.di_nextents > 0)
    -			(void)xfs_da_reada_buf(NULL, ip, 0, XFS_DATA_FORK);
    -		xfs_iunlock(ip, mode);
    -	}
    -	return 0;
    -}
    -
    -
    -/*
    - * xfs_getattr
    - */
    -STATIC int
    -xfs_getattr(
    -	bhv_desc_t	*bdp,
    -	xfs_vattr_t	*vap,
    -	int		flags,
    -	cred_t		*credp)
    -{
    -	xfs_inode_t	*ip;
    -	xfs_mount_t	*mp;
    -	xfs_vnode_t	*vp;
    -
    -	vp  = BHV_TO_VNODE(bdp);
    -	vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
    -
    -	ip = XFS_BHVTOI(bdp);
    -	mp = ip->i_mount;
    -
    -	if (XFS_FORCED_SHUTDOWN(mp))
    -		return XFS_ERROR(EIO);
    -
    -	if (!(flags & ATTR_LAZY))
    -		xfs_ilock(ip, XFS_ILOCK_SHARED);
    -
    -	vap->va_size = ip->i_d.di_size;
    -	if (vap->va_mask == XFS_AT_SIZE)
    -		goto all_done;
    -
    -	vap->va_nblocks =
    -		XFS_FSB_TO_BB(mp, ip->i_d.di_nblocks + ip->i_delayed_blks);
    -	vap->va_nodeid = ip->i_ino;
    -#if XFS_BIG_INUMS
    -	vap->va_nodeid += mp->m_inoadd;
    -#endif
    -	vap->va_nlink = ip->i_d.di_nlink;
    -
    -	/*
    -	 * Quick exit for non-stat callers
    -	 */
    -	if ((vap->va_mask &
    -	    ~(XFS_AT_SIZE|XFS_AT_FSID|XFS_AT_NODEID|
    -	      XFS_AT_NLINK|XFS_AT_BLKSIZE)) == 0)
    -		goto all_done;
    -
    -	/*
    -	 * Copy from in-core inode.
    -	 */
    -	vap->va_mode = ip->i_d.di_mode;
    -	vap->va_uid = ip->i_d.di_uid;
    -	vap->va_gid = ip->i_d.di_gid;
    -	vap->va_projid = ip->i_d.di_projid;
    -
    -	/*
    -	 * Check vnode type block/char vs. everything else.
    -	 */
    -	switch (ip->i_d.di_mode & S_IFMT) {
    -	case S_IFBLK:
    -	case S_IFCHR:
    -		vap->va_rdev = ip->i_df.if_u2.if_rdev;
    -		vap->va_blocksize = BLKDEV_IOSIZE;
    -		break;
    -	default:
    -		vap->va_rdev = 0;
    -
    -		if (!(ip->i_d.di_flags & XFS_DIFLAG_REALTIME)) {
    -			vap->va_blocksize = xfs_preferred_iosize(mp);
    -		} else {
    -
    -			/*
    -			 * If the file blocks are being allocated from a
    -			 * realtime partition, then return the inode's
    -			 * realtime extent size or the realtime volume's
    -			 * extent size.
    -			 */
    -			vap->va_blocksize = ip->i_d.di_extsize ?
    -				(ip->i_d.di_extsize << mp->m_sb.sb_blocklog) :
    -				(mp->m_sb.sb_rextsize << mp->m_sb.sb_blocklog);
    -		}
    -		break;
    -	}
    -
    -	vn_atime_to_timespec(vp, &vap->va_atime);
    -	vap->va_mtime.tv_sec = ip->i_d.di_mtime.t_sec;
    -	vap->va_mtime.tv_nsec = ip->i_d.di_mtime.t_nsec;
    -	vap->va_ctime.tv_sec = ip->i_d.di_ctime.t_sec;
    -	vap->va_ctime.tv_nsec = ip->i_d.di_ctime.t_nsec;
    -
    -	/*
    -	 * Exit for stat callers.  See if any of the rest of the fields
    -	 * to be filled in are needed.
    -	 */
    -	if ((vap->va_mask &
    -	     (XFS_AT_XFLAGS|XFS_AT_EXTSIZE|XFS_AT_NEXTENTS|XFS_AT_ANEXTENTS|
    -	      XFS_AT_GENCOUNT|XFS_AT_VCODE)) == 0)
    -		goto all_done;
    -
    -	/*
    -	 * Convert di_flags to xflags.
    -	 */
    -	vap->va_xflags = xfs_ip2xflags(ip);
    -
    -	/*
    -	 * Exit for inode revalidate.  See if any of the rest of
    -	 * the fields to be filled in are needed.
    -	 */
    -	if ((vap->va_mask &
    -	     (XFS_AT_EXTSIZE|XFS_AT_NEXTENTS|XFS_AT_ANEXTENTS|
    -	      XFS_AT_GENCOUNT|XFS_AT_VCODE)) == 0)
    -		goto all_done;
    -
    -	vap->va_extsize = ip->i_d.di_extsize << mp->m_sb.sb_blocklog;
    -	vap->va_nextents =
    -		(ip->i_df.if_flags & XFS_IFEXTENTS) ?
    -			ip->i_df.if_bytes / sizeof(xfs_bmbt_rec_t) :
    -			ip->i_d.di_nextents;
    -	if (ip->i_afp)
    -		vap->va_anextents =
    -			(ip->i_afp->if_flags & XFS_IFEXTENTS) ?
    -				ip->i_afp->if_bytes / sizeof(xfs_bmbt_rec_t) :
    -				 ip->i_d.di_anextents;
    -	else
    -		vap->va_anextents = 0;
    -	vap->va_gen = ip->i_d.di_gen;
    -
    - all_done:
    -	if (!(flags & ATTR_LAZY))
    -		xfs_iunlock(ip, XFS_ILOCK_SHARED);
    -	return 0;
    -}
    -
    -
    -/*
    - * xfs_setattr
    - */
    -int
    -xfs_setattr(
    -	bhv_desc_t		*bdp,
    -	xfs_vattr_t		*vap,
    -	int			flags,
    -	cred_t			*credp)
    -{
    -	xfs_inode_t		*ip;
    -	xfs_trans_t		*tp;
    -	xfs_mount_t		*mp;
    -	int			mask;
    -	int			code;
    -	uint			lock_flags;
    -	uint			commit_flags=0;
    -	uid_t			uid=0, iuid=0;
    -	gid_t			gid=0, igid=0;
    -	int			timeflags = 0;
    -	xfs_vnode_t		*vp;
    -	xfs_prid_t		projid=0, iprojid=0;
    -	int			mandlock_before, mandlock_after;
    -	struct xfs_dquot	*udqp, *gdqp, *olddquot1, *olddquot2;
    -	int			file_owner;
    -	int			need_iolock = 1;
    -
    -	vp = BHV_TO_VNODE(bdp);
    -	vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
    -
    -	if (vp->v_vfsp->vfs_flag & VFS_RDONLY)
    -		return XFS_ERROR(EROFS);
    -
    -	/*
    -	 * Cannot set certain attributes.
    -	 */
    -	mask = vap->va_mask;
    -	if (mask & XFS_AT_NOSET) {
    -		return XFS_ERROR(EINVAL);
    -	}
    -
    -	ip = XFS_BHVTOI(bdp);
    -	mp = ip->i_mount;
    -
    -	if (XFS_FORCED_SHUTDOWN(mp))
    -		return XFS_ERROR(EIO);
    -
    -	/*
    -	 * Timestamps do not need to be logged and hence do not
    -	 * need to be done within a transaction.
    -	 */
    -	if (mask & XFS_AT_UPDTIMES) {
    -		ASSERT((mask & ~XFS_AT_UPDTIMES) == 0);
    -		timeflags = ((mask & XFS_AT_UPDATIME) ? XFS_ICHGTIME_ACC : 0) |
    -			    ((mask & XFS_AT_UPDCTIME) ? XFS_ICHGTIME_CHG : 0) |
    -			    ((mask & XFS_AT_UPDMTIME) ? XFS_ICHGTIME_MOD : 0);
    -		xfs_ichgtime(ip, timeflags);
    -		return 0;
    -	}
    -
    -	olddquot1 = olddquot2 = NULL;
    -	udqp = gdqp = NULL;
    -
    -	/*
    -	 * If disk quotas is on, we make sure that the dquots do exist on disk,
    -	 * before we start any other transactions. Trying to do this later
    -	 * is messy. We don't care to take a readlock to look at the ids
    -	 * in inode here, because we can't hold it across the trans_reserve.
    -	 * If the IDs do change before we take the ilock, we're covered
    -	 * because the i_*dquot fields will get updated anyway.
    -	 */
    -	if (XFS_IS_QUOTA_ON(mp) &&
    -	    (mask & (XFS_AT_UID|XFS_AT_GID|XFS_AT_PROJID))) {
    -		uint	qflags = 0;
    -
    -		if ((mask & XFS_AT_UID) && XFS_IS_UQUOTA_ON(mp)) {
    -			uid = vap->va_uid;
    -			qflags |= XFS_QMOPT_UQUOTA;
    -		} else {
    -			uid = ip->i_d.di_uid;
    -		}
    -		if ((mask & XFS_AT_GID) && XFS_IS_GQUOTA_ON(mp)) {
    -			gid = vap->va_gid;
    -			qflags |= XFS_QMOPT_GQUOTA;
    -		}  else {
    -			gid = ip->i_d.di_gid;
    -		}
    -		if ((mask & XFS_AT_PROJID) && XFS_IS_PQUOTA_ON(mp)) {
    -			projid = vap->va_projid;
    -			qflags |= XFS_QMOPT_PQUOTA;
    -		}  else {
    -			projid = ip->i_d.di_projid;
    -		}
    -		/*
    -		 * We take a reference when we initialize udqp and gdqp,
    -		 * so it is important that we never blindly double trip on
    -		 * the same variable. See xfs_create() for an example.
    -		 */
    -		ASSERT(udqp == NULL);
    -		ASSERT(gdqp == NULL);
    -		code = XFS_QM_DQVOPALLOC(mp, ip, uid, gid, projid, qflags,
    -					 &udqp, &gdqp);
    -		if (code)
    -			return code;
    -	}
    -
    -	/*
    -	 * For the other attributes, we acquire the inode lock and
    -	 * first do an error checking pass.
    -	 */
    -	tp = NULL;
    -	lock_flags = XFS_ILOCK_EXCL;
    -	ASSERT(flags & ATTR_NOLOCK ? flags & ATTR_DMI : 1);
    -	if (flags & ATTR_NOLOCK)
    -		need_iolock = 0;
    -	if (!(mask & XFS_AT_SIZE)) {
    -		if ((mask != (XFS_AT_CTIME|XFS_AT_ATIME|XFS_AT_MTIME)) ||
    -		    (mp->m_flags & XFS_MOUNT_WSYNC)) {
    -			tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_NOT_SIZE);
    -			commit_flags = 0;
    -			if ((code = xfs_trans_reserve(tp, 0,
    -						     XFS_ICHANGE_LOG_RES(mp), 0,
    -						     0, 0))) {
    -				lock_flags = 0;
    -				goto error_return;
    -			}
    -		}
    -	} else {
    -		if (DM_EVENT_ENABLED (vp->v_vfsp, ip, DM_EVENT_TRUNCATE) &&
    -		    !(flags & ATTR_DMI)) {
    -			int dmflags = AT_DELAY_FLAG(flags) | DM_SEM_FLAG_WR;
    -			code = XFS_SEND_DATA(mp, DM_EVENT_TRUNCATE, vp,
    -				vap->va_size, 0, dmflags, NULL);
    -			if (code) {
    -				lock_flags = 0;
    -				goto error_return;
    -			}
    -		}
    -		if (need_iolock)
    -			lock_flags |= XFS_IOLOCK_EXCL;
    -	}
    -
    -	xfs_ilock(ip, lock_flags);
    -
    -	/* boolean: are we the file owner? */
    -#if 0
    -	file_owner = (current_fsuid(credp) == ip->i_d.di_uid);
    -#else
    -	file_owner = (credp->cr_uid == ip->i_d.di_uid);
    -#endif
    -
    -	/*
    -	 * Change various properties of a file.
    -	 * Only the owner or users with CAP_FOWNER
    -	 * capability may do these things.
    -	 */
    -	if (mask &
    -	    (XFS_AT_MODE|XFS_AT_XFLAGS|XFS_AT_EXTSIZE|XFS_AT_UID|
    -	     XFS_AT_GID|XFS_AT_PROJID)) {
    -		/*
    -		 * CAP_FOWNER overrides the following restrictions:
    -		 *
    -		 * The user ID of the calling process must be equal
    -		 * to the file owner ID, except in cases where the
    -		 * CAP_FSETID capability is applicable.
    -		 */
    -		if (!file_owner && !capable(CAP_FOWNER)) {
    -			code = XFS_ERROR(EPERM);
    -			goto error_return;
    -		}
    -
    -		/*
    -		 * CAP_FSETID overrides the following restrictions:
    -		 *
    -		 * The effective user ID of the calling process shall match
    -		 * the file owner when setting the set-user-ID and
    -		 * set-group-ID bits on that file.
    -		 *
    -		 * The effective group ID or one of the supplementary group
    -		 * IDs of the calling process shall match the group owner of
    -		 * the file when setting the set-group-ID bit on that file
    -		 */
    -		if (mask & XFS_AT_MODE) {
    -			mode_t m = 0;
    -
    -			if ((vap->va_mode & S_ISUID) && !file_owner)
    -				m |= S_ISUID;
    -			if ((vap->va_mode & S_ISGID) &&
    -			    !groupmember((gid_t)ip->i_d.di_gid, credp))
    -				m |= S_ISGID;
    -#if 1
    -			/* Linux allows this, Irix doesn't. */
    -			if ((vap->va_mode & S_ISVTX) && !VN_ISDIR(vp))
    -				m |= S_ISVTX;
    -#endif
    -			if (m && !capable(CAP_FSETID))
    -				vap->va_mode &= ~m;
    -		}
    -	}
    -
    -	/*
    -	 * Change file ownership.  Must be the owner or privileged.
    -	 * If the system was configured with the "restricted_chown"
    -	 * option, the owner is not permitted to give away the file,
    -	 * and can change the group id only to a group of which he
    -	 * or she is a member.
    -	 */
    -	if (mask & (XFS_AT_UID|XFS_AT_GID|XFS_AT_PROJID)) {
    -		/*
    -		 * These IDs could have changed since we last looked at them.
    -		 * But, we're assured that if the ownership did change
    -		 * while we didn't have the inode locked, inode's dquot(s)
    -		 * would have changed also.
    -		 */
    -		iuid = ip->i_d.di_uid;
    -		iprojid = ip->i_d.di_projid;
    -		igid = ip->i_d.di_gid;
    -		gid = (mask & XFS_AT_GID) ? vap->va_gid : igid;
    -		uid = (mask & XFS_AT_UID) ? vap->va_uid : iuid;
    -
    -		projid = (mask & XFS_AT_PROJID) ? (xfs_prid_t)vap->va_projid :
    -			 iprojid;
    -
    -		/*
    -		 * CAP_CHOWN overrides the following restrictions:
    -		 *
    -		 * If _POSIX_CHOWN_RESTRICTED is defined, this capability
    -		 * shall override the restriction that a process cannot
    -		 * change the user ID of a file it owns and the restriction
    -		 * that the group ID supplied to the chown() function
    -		 * shall be equal to either the group ID or one of the
    -		 * supplementary group IDs of the calling process.
    -		 */
    -		if (restricted_chown &&
    -		    (iuid != uid || (igid != gid &&
    -				     !groupmember((gid_t)gid, credp))) &&
    -		    !capable(CAP_CHOWN)) {
    -			code = XFS_ERROR(EPERM);
    -			goto error_return;
    -		}
    -		/*
    -		 * Do a quota reservation only if uid/projid/gid is actually
    -		 * going to change.
    -		 */
    -		if ((XFS_IS_UQUOTA_ON(mp) && iuid != uid) ||
    -		    (XFS_IS_PQUOTA_ON(mp) && iprojid != projid) ||
    -		    (XFS_IS_GQUOTA_ON(mp) && igid != gid)) {
    -			ASSERT(tp);
    -			code = XFS_QM_DQVOPCHOWNRESV(mp, tp, ip, udqp, gdqp,
    -						capable(CAP_FOWNER) ?
    -						XFS_QMOPT_FORCE_RES : 0);
    -			if (code)	/* out of quota */
    -				goto error_return;
    -		}
    -	}
    -
    -	/*
    -	 * Truncate file.  Must have write permission and not be a directory.
    -	 */
    -	if (mask & XFS_AT_SIZE) {
    -		/* Short circuit the truncate case for zero length files */
    -		if ((vap->va_size == 0) &&
    -		   (ip->i_d.di_size == 0) && (ip->i_d.di_nextents == 0)) {
    -			xfs_iunlock(ip, XFS_ILOCK_EXCL);
    -			lock_flags &= ~XFS_ILOCK_EXCL;
    -			if (mask & XFS_AT_CTIME)
    -				xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
    -			code = 0;
    -			goto error_return;
    -		}
    -
    -		if (VN_ISDIR(vp)) {
    -			code = XFS_ERROR(EISDIR);
    -			goto error_return;
    -		} else if (!VN_ISREG(vp)) {
    -			code = XFS_ERROR(EINVAL);
    -			goto error_return;
    -		}
    -		/*
    -		 * Make sure that the dquots are attached to the inode.
    -		 */
    -		if ((code = XFS_QM_DQATTACH(mp, ip, XFS_QMOPT_ILOCKED)))
    -			goto error_return;
    -	}
    -
    -	/*
    -	 * Change file access or modified times.
    -	 */
    -	if (mask & (XFS_AT_ATIME|XFS_AT_MTIME)) {
    -		if (!file_owner) {
    -			if ((flags & ATTR_UTIME) &&
    -			    !capable(CAP_FOWNER)) {
    -				code = XFS_ERROR(EPERM);
    -				goto error_return;
    -			}
    -		}
    -	}
    -
    -	/*
    -	 * Change extent size or realtime flag.
    -	 */
    -	if (mask & (XFS_AT_EXTSIZE|XFS_AT_XFLAGS)) {
    -		/*
    -		 * Can't change extent size if any extents are allocated.
    -		 */
    -		if (ip->i_d.di_nextents && (mask & XFS_AT_EXTSIZE) &&
    -		    ((ip->i_d.di_extsize << mp->m_sb.sb_blocklog) !=
    -		     vap->va_extsize) ) {
    -			code = XFS_ERROR(EINVAL);	/* EFBIG? */
    -			goto error_return;
    -		}
    -		/*
    -		 * Can't change realtime flag if any extents are allocated.
    -		 */
    -		if ((ip->i_d.di_nextents || ip->i_delayed_blks) &&
    -		    (mask & XFS_AT_XFLAGS) &&
    -		    (ip->i_d.di_flags & XFS_DIFLAG_REALTIME) !=
    -		    (vap->va_xflags & XFS_XFLAG_REALTIME)) {
    -			code = XFS_ERROR(EINVAL);	/* EFBIG? */
    -			goto error_return;
    -		}
    -
    -		/*
    -		 * Extent size must be a multiple of the appropriate block
    -		 * size, if set at all.
    -		 */
    -		if ((mask & XFS_AT_EXTSIZE) && vap->va_extsize != 0) {
    -			xfs_extlen_t	size;
    -
    -			if ((ip->i_d.di_flags & XFS_DIFLAG_REALTIME) ||
    -			    ((mask & XFS_AT_XFLAGS) &&
    -			    (vap->va_xflags & XFS_XFLAG_REALTIME))) {
    -				size = mp->m_sb.sb_rextsize <<
    -				       mp->m_sb.sb_blocklog;
    -			} else {
    -				size = mp->m_sb.sb_blocksize;
    -			}
    -			if (vap->va_extsize % size) {
    -				code = XFS_ERROR(EINVAL);
    -				goto error_return;
    -			}
    -		}
    -		/*
    -		 * If realtime flag is set then must have realtime data.
    -		 */
    -		if ((mask & XFS_AT_XFLAGS) &&
    -		    (vap->va_xflags & XFS_XFLAG_REALTIME)) {
    -			if ((mp->m_sb.sb_rblocks == 0) ||
    -			    (mp->m_sb.sb_rextsize == 0) ||
    -			    (ip->i_d.di_extsize % mp->m_sb.sb_rextsize)) {
    -				code = XFS_ERROR(EINVAL);
    -				goto error_return;
    -			}
    -		}
    -
    -		/*
    -		 * Can't modify an immutable/append-only file unless
    -		 * we have appropriate permission.
    -		 */
    -		if ((mask & XFS_AT_XFLAGS) &&
    -		    (ip->i_d.di_flags &
    -				(XFS_DIFLAG_IMMUTABLE|XFS_DIFLAG_APPEND) ||
    -		     (vap->va_xflags &
    -				(XFS_XFLAG_IMMUTABLE | XFS_XFLAG_APPEND))) &&
    -		    !capable(CAP_LINUX_IMMUTABLE)) {
    -			code = XFS_ERROR(EPERM);
    -			goto error_return;
    -		}
    -	}
    -
    -	/*
    -	 * Now we can make the changes.  Before we join the inode
    -	 * to the transaction, if XFS_AT_SIZE is set then take care of
    -	 * the part of the truncation that must be done without the
    -	 * inode lock.  This needs to be done before joining the inode
    -	 * to the transaction, because the inode cannot be unlocked
    -	 * once it is a part of the transaction.
    -	 */
    -	if (mask & XFS_AT_SIZE) {
    -		code = 0;
    -		if ((vap->va_size > ip->i_d.di_size) &&
    -		    (flags & ATTR_NOSIZETOK) == 0) {
    -			code = xfs_igrow_start(ip, vap->va_size, credp);
    -		}
    -		xfs_iunlock(ip, XFS_ILOCK_EXCL);
    -		vn_iowait(vp); /* wait for the completion of any pending DIOs */
    -		if (!code)
    -			code = xfs_itruncate_data(ip, vap->va_size);
    -		if (code) {
    -			ASSERT(tp == NULL);
    -			lock_flags &= ~XFS_ILOCK_EXCL;
    -			ASSERT(lock_flags == XFS_IOLOCK_EXCL);
    -			goto error_return;
    -		}
    -		tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_SIZE);
    -		if ((code = xfs_trans_reserve(tp, 0,
    -					     XFS_ITRUNCATE_LOG_RES(mp), 0,
    -					     XFS_TRANS_PERM_LOG_RES,
    -					     XFS_ITRUNCATE_LOG_COUNT))) {
    -			xfs_trans_cancel(tp, 0);
    -			if (need_iolock)
    -				xfs_iunlock(ip, XFS_IOLOCK_EXCL);
    -			return code;
    -		}
    -		commit_flags = XFS_TRANS_RELEASE_LOG_RES;
    -		xfs_ilock(ip, XFS_ILOCK_EXCL);
    -	}
    -
    -	if (tp) {
    -		xfs_trans_ijoin(tp, ip, lock_flags);
    -		xfs_trans_ihold(tp, ip);
    -	}
    -
    -	/* determine whether mandatory locking mode changes */
    -	mandlock_before = MANDLOCK(vp, ip->i_d.di_mode);
    -
    -	/*
    -	 * Truncate file.  Must have write permission and not be a directory.
    -	 */
    -	if (mask & XFS_AT_SIZE) {
    -		if (vap->va_size > ip->i_d.di_size) {
    -			xfs_igrow_finish(tp, ip, vap->va_size,
    -			    !(flags & ATTR_DMI));
    -		} else if ((vap->va_size <= ip->i_d.di_size) ||
    -			   ((vap->va_size == 0) && ip->i_d.di_nextents)) {
    -			/*
    -			 * signal a sync transaction unless
    -			 * we're truncating an already unlinked
    -			 * file on a wsync filesystem
    -			 */
    -			code = xfs_itruncate_finish(&tp, ip,
    -					    (xfs_fsize_t)vap->va_size,
    -					    XFS_DATA_FORK,
    -					    ((ip->i_d.di_nlink != 0 ||
    -					      !(mp->m_flags & XFS_MOUNT_WSYNC))
    -					     ? 1 : 0));
    -			if (code) {
    -				goto abort_return;
    -			}
    -		}
    -		/*
    -		 * Have to do this even if the file's size doesn't change.
    -		 */
    -		timeflags |= XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG;
    -	}
    -
    -	/*
    -	 * Change file access modes.
    -	 */
    -	if (mask & XFS_AT_MODE) {
    -		ip->i_d.di_mode &= S_IFMT;
    -		ip->i_d.di_mode |= vap->va_mode & ~S_IFMT;
    -
    -		xfs_trans_log_inode (tp, ip, XFS_ILOG_CORE);
    -		timeflags |= XFS_ICHGTIME_CHG;
    -	}
    -
    -	/*
    -	 * Change file ownership.  Must be the owner or privileged.
    -	 * If the system was configured with the "restricted_chown"
    -	 * option, the owner is not permitted to give away the file,
    -	 * and can change the group id only to a group of which he
    -	 * or she is a member.
    -	 */
    -	if (mask & (XFS_AT_UID|XFS_AT_GID|XFS_AT_PROJID)) {
    -		/*
    -		 * CAP_FSETID overrides the following restrictions:
    -		 *
    -		 * The set-user-ID and set-group-ID bits of a file will be
    -		 * cleared upon successful return from chown()
    -		 */
    -		if ((ip->i_d.di_mode & (S_ISUID|S_ISGID)) &&
    -		    !capable(CAP_FSETID)) {
    -			ip->i_d.di_mode &= ~(S_ISUID|S_ISGID);
    -		}
    -
    -		/*
    -		 * Change the ownerships and register quota modifications
    -		 * in the transaction.
    -		 */
    -		if (iuid != uid) {
    -			if (XFS_IS_UQUOTA_ON(mp)) {
    -				ASSERT(mask & XFS_AT_UID);
    -				ASSERT(udqp);
    -				olddquot1 = XFS_QM_DQVOPCHOWN(mp, tp, ip,
    -							&ip->i_udquot, udqp);
    -			}
    -			ip->i_d.di_uid = uid;
    -		}
    -		if (igid != gid) {
    -			if (XFS_IS_GQUOTA_ON(mp)) {
    -				ASSERT(!XFS_IS_PQUOTA_ON(mp));
    -				ASSERT(mask & XFS_AT_GID);
    -				ASSERT(gdqp);
    -				olddquot2 = XFS_QM_DQVOPCHOWN(mp, tp, ip,
    -							&ip->i_gdquot, gdqp);
    -			}
    -			ip->i_d.di_gid = gid;
    -		}
    -		if (iprojid != projid) {
    -			if (XFS_IS_PQUOTA_ON(mp)) {
    -				ASSERT(!XFS_IS_GQUOTA_ON(mp));
    -				ASSERT(mask & XFS_AT_PROJID);
    -				ASSERT(gdqp);
    -				olddquot2 = XFS_QM_DQVOPCHOWN(mp, tp, ip,
    -							&ip->i_gdquot, gdqp);
    -			}
    -			ip->i_d.di_projid = projid;
    -			/*
    -			 * We may have to rev the inode as well as
    -			 * the superblock version number since projids didn't
    -			 * exist before DINODE_VERSION_2 and SB_VERSION_NLINK.
    -			 */
    -			if (ip->i_d.di_version == XFS_DINODE_VERSION_1)
    -				xfs_bump_ino_vers2(tp, ip);
    -		}
    -
    -		xfs_trans_log_inode (tp, ip, XFS_ILOG_CORE);
    -		timeflags |= XFS_ICHGTIME_CHG;
    -	}
    -
    -
    -	/*
    -	 * Change file access or modified times.
    -	 */
    -	if (mask & (XFS_AT_ATIME|XFS_AT_MTIME)) {
    -		if (mask & XFS_AT_ATIME) {
    -			ip->i_d.di_atime.t_sec = vap->va_atime.tv_sec;
    -			ip->i_d.di_atime.t_nsec = vap->va_atime.tv_nsec;
    -			ip->i_update_core = 1;
    -			//timeflags &= ~XFS_ICHGTIME_ACC;
    -		}
    -		if (mask & XFS_AT_MTIME) {
    -			ip->i_d.di_mtime.t_sec = vap->va_mtime.tv_sec;
    -			ip->i_d.di_mtime.t_nsec = vap->va_mtime.tv_nsec;
    -			timeflags &= ~XFS_ICHGTIME_MOD;
    -			timeflags |= XFS_ICHGTIME_CHG;
    -		}
    -		if (tp && (flags & ATTR_UTIME))
    -			xfs_trans_log_inode (tp, ip, XFS_ILOG_CORE);
    -	}
    -
    -	/*
    -	 * Change XFS-added attributes.
    -	 */
    -	if (mask & (XFS_AT_EXTSIZE|XFS_AT_XFLAGS)) {
    -		if (mask & XFS_AT_EXTSIZE) {
    -			/*
    -			 * Converting bytes to fs blocks.
    -			 */
    -			ip->i_d.di_extsize = vap->va_extsize >>
    -				mp->m_sb.sb_blocklog;
    -		}
    -		if (mask & XFS_AT_XFLAGS) {
    -			uint	di_flags;
    -
    -			/* can't set PREALLOC this way, just preserve it */
    -			di_flags = (ip->i_d.di_flags & XFS_DIFLAG_PREALLOC);
    -			if (vap->va_xflags & XFS_XFLAG_IMMUTABLE)
    -				di_flags |= XFS_DIFLAG_IMMUTABLE;
    -			if (vap->va_xflags & XFS_XFLAG_APPEND)
    -				di_flags |= XFS_DIFLAG_APPEND;
    -			if (vap->va_xflags & XFS_XFLAG_SYNC)
    -				di_flags |= XFS_DIFLAG_SYNC;
    -			if (vap->va_xflags & XFS_XFLAG_NOATIME)
    -				di_flags |= XFS_DIFLAG_NOATIME;
    -			if (vap->va_xflags & XFS_XFLAG_NODUMP)
    -				di_flags |= XFS_DIFLAG_NODUMP;
    -			if (vap->va_xflags & XFS_XFLAG_PROJINHERIT)
    -				di_flags |= XFS_DIFLAG_PROJINHERIT;
    -			if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
    -				if (vap->va_xflags & XFS_XFLAG_RTINHERIT)
    -					di_flags |= XFS_DIFLAG_RTINHERIT;
    -				if (vap->va_xflags & XFS_XFLAG_NOSYMLINKS)
    -					di_flags |= XFS_DIFLAG_NOSYMLINKS;
    -				if (vap->va_xflags & XFS_XFLAG_EXTSZINHERIT)
    -					di_flags |= XFS_DIFLAG_EXTSZINHERIT;
    -			} else if ((ip->i_d.di_mode & S_IFMT) == S_IFREG) {
    -				if (vap->va_xflags & XFS_XFLAG_REALTIME) {
    -					di_flags |= XFS_DIFLAG_REALTIME;
    -					ip->i_iocore.io_flags |= XFS_IOCORE_RT;
    -				} else {
    -					ip->i_iocore.io_flags &= ~XFS_IOCORE_RT;
    -				}
    -				if (vap->va_xflags & XFS_XFLAG_EXTSIZE)
    -					di_flags |= XFS_DIFLAG_EXTSIZE;
    -			}
    -			ip->i_d.di_flags = di_flags;
    -		}
    -		xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
    -		timeflags |= XFS_ICHGTIME_CHG;
    -	}
    -
    -	/*
    -	 * Change file inode change time only if XFS_AT_CTIME set
    -	 * AND we have been called by a DMI function.
    -	 */
    -
    -	if ( (flags & ATTR_DMI) && (mask & XFS_AT_CTIME) ) {
    -		ip->i_d.di_ctime.t_sec = vap->va_ctime.tv_sec;
    -		ip->i_d.di_ctime.t_nsec = vap->va_ctime.tv_nsec;
    -		ip->i_update_core = 1;
    -		timeflags &= ~XFS_ICHGTIME_CHG;
    -	}
    -
    -	/*
    -	 * Send out timestamp changes that need to be set to the
    -	 * current time.  Not done when called by a DMI function.
    -	 */
    -	if (timeflags && !(flags & ATTR_DMI))
    -		xfs_ichgtime(ip, timeflags);
    -
    -	XFS_STATS_INC(xs_ig_attrchg);
    -
    -	/*
    -	 * If this is a synchronous mount, make sure that the
    -	 * transaction goes to disk before returning to the user.
    -	 * This is slightly sub-optimal in that truncates require
    -	 * two sync transactions instead of one for wsync filesystems.
    -	 * One for the truncate and one for the timestamps since we
    -	 * don't want to change the timestamps unless we're sure the
    -	 * truncate worked.  Truncates are less than 1% of the laddis
    -	 * mix so this probably isn't worth the trouble to optimize.
    -	 */
    -	code = 0;
    -	if (tp) {
    -		if (mp->m_flags & XFS_MOUNT_WSYNC)
    -			xfs_trans_set_sync(tp);
    -
    -		code = xfs_trans_commit(tp, commit_flags, NULL);
    -	}
    -
    -	/*
    -	 * If the (regular) file's mandatory locking mode changed, then
    -	 * notify the vnode.  We do this under the inode lock to prevent
    -	 * racing calls to vop_vnode_change.
    -	 */
    -	mandlock_after = MANDLOCK(vp, ip->i_d.di_mode);
    -	if (mandlock_before != mandlock_after) {
    -		XVOP_VNODE_CHANGE(vp, VCHANGE_FLAGS_ENF_LOCKING,
    -				 mandlock_after);
    -	}
    -
    -	xfs_iunlock(ip, lock_flags);
    -
    -	/*
    -	 * Release any dquot(s) the inode had kept before chown.
    -	 */
    -	XFS_QM_DQRELE(mp, olddquot1);
    -	XFS_QM_DQRELE(mp, olddquot2);
    -	XFS_QM_DQRELE(mp, udqp);
    -	XFS_QM_DQRELE(mp, gdqp);
    -
    -	if (code) {
    -		return code;
    -	}
    -
    -	if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_ATTRIBUTE) &&
    -	    !(flags & ATTR_DMI)) {
    -		(void) XFS_SEND_NAMESP(mp, DM_EVENT_ATTRIBUTE, vp, DM_RIGHT_NULL,
    -					NULL, DM_RIGHT_NULL, NULL, NULL,
    -					0, 0, AT_DELAY_FLAG(flags));
    -	}
    -	return 0;
    -
    - abort_return:
    -	commit_flags |= XFS_TRANS_ABORT;
    -	/* FALLTHROUGH */
    - error_return:
    -	XFS_QM_DQRELE(mp, udqp);
    -	XFS_QM_DQRELE(mp, gdqp);
    -	if (tp) {
    -		xfs_trans_cancel(tp, commit_flags);
    -	}
    -	if (lock_flags != 0) {
    -		xfs_iunlock(ip, lock_flags);
    -	}
    -	return code;
    -}
    -
    -
    -/*
    - * xfs_access
    - * Null conversion from vnode mode bits to inode mode bits, as in efs.
    - */
    -STATIC int
    -xfs_access(
    -	bhv_desc_t	*bdp,
    -	accmode_t	accmode,
    -	cred_t		*credp)
    -{
    -	xfs_inode_t	*ip;
    -	int		error;
    -
    -	vn_trace_entry(BHV_TO_VNODE(bdp), __FUNCTION__,
    -					       (inst_t *)__return_address);
    -
    -	ip = XFS_BHVTOI(bdp);
    -	xfs_ilock(ip, XFS_ILOCK_SHARED);
    -	error = xfs_iaccess(ip, accmode, credp);
    -	xfs_iunlock(ip, XFS_ILOCK_SHARED);
    -	return error;
    -}
    -
    -
    -/*
    - * xfs_readlink
    - *
    - */
    -STATIC int
    -xfs_readlink(
    -	bhv_desc_t	*bdp,
    -	uio_t		*uiop,
    -	int		ioflags,
    -	cred_t		*credp)
    -{
    -	xfs_inode_t     *ip;
    -	int		count;
    -	xfs_off_t	offset;
    -	int		pathlen;
    -	xfs_vnode_t	*vp;
    -	int		error = 0;
    -	xfs_mount_t	*mp;
    -	int             nmaps;
    -	xfs_bmbt_irec_t mval[SYMLINK_MAPS];
    -	xfs_daddr_t	d;
    -	int		byte_cnt;
    -	int		n;
    -	xfs_buf_t	*bp;
    -
    -	vp = BHV_TO_VNODE(bdp);
    -	vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
    -
    -	ip = XFS_BHVTOI(bdp);
    -	mp = ip->i_mount;
    -
    -	if (XFS_FORCED_SHUTDOWN(mp))
    -		return XFS_ERROR(EIO);
    -
    -	xfs_ilock(ip, XFS_ILOCK_SHARED);
    -
    -	ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFLNK);
    -
    -	offset = uiop->uio_offset;
    -	count = uiop->uio_resid;
    -
    -	if (offset < 0) {
    -		error = XFS_ERROR(EINVAL);
    -		goto error_return;
    -	}
    -	if (count <= 0) {
    -		error = 0;
    -		goto error_return;
    -	}
    -
    -	/*
    -	 * See if the symlink is stored inline.
    -	 */
    -	pathlen = (int)ip->i_d.di_size;
    -
    -	if (ip->i_df.if_flags & XFS_IFINLINE) {
    -		error = uio_read(ip->i_df.if_u1.if_data, pathlen, uiop);
    -	}
    -	else {
    -		/*
    -		 * Symlink not inline.  Call bmap to get it in.
    -		 */
    -		nmaps = SYMLINK_MAPS;
    -
    -		error = xfs_bmapi(NULL, ip, 0, XFS_B_TO_FSB(mp, pathlen),
    -				  0, NULL, 0, mval, &nmaps, NULL, NULL);
    -
    -		if (error) {
    -			goto error_return;
    -		}
    -
    -		for (n = 0; n < nmaps; n++) {
    -			d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
    -			byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
    -			bp = xfs_buf_read(mp->m_ddev_targp, d,
    -				      BTOBB(byte_cnt), 0);
    -			error = XFS_BUF_GETERROR(bp);
    -			if (error) {
    -				xfs_ioerror_alert("xfs_readlink",
    -					  ip->i_mount, bp, XFS_BUF_ADDR(bp));
    -				xfs_buf_relse(bp);
    -				goto error_return;
    -			}
    -			if (pathlen < byte_cnt)
    -				byte_cnt = pathlen;
    -			pathlen -= byte_cnt;
    -
    -			error = uio_read(XFS_BUF_PTR(bp), byte_cnt, uiop);
    -			xfs_buf_relse (bp);
    -		}
    -
    -	}
    -
    -error_return:
    -	xfs_iunlock(ip, XFS_ILOCK_SHARED);
    -	return error;
    -}
    -
    -
    -/*
    - * xfs_fsync
    - *
    - * This is called to sync the inode and its data out to disk.
    - * We need to hold the I/O lock while flushing the data, and
    - * the inode lock while flushing the inode.  The inode lock CANNOT
    - * be held while flushing the data, so acquire after we're done
    - * with that.
    - */
    -STATIC int
    -xfs_fsync(
    -	bhv_desc_t	*bdp,
    -	int		flag,
    -	cred_t		*credp,
    -	xfs_off_t	start,
    -	xfs_off_t	stop)
    -{
    -	xfs_inode_t	*ip;
    -	xfs_trans_t	*tp;
    -	int		error;
    -	int		log_flushed = 0, changed = 1;
    -
    -	vn_trace_entry(BHV_TO_VNODE(bdp),
    -			__FUNCTION__, (inst_t *)__return_address);
    -
    -	ip = XFS_BHVTOI(bdp);
    -
    -	ASSERT(start >= 0 && stop >= -1);
    -
    -	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
    -		return XFS_ERROR(EIO);
    -
    -	/*
    -	 * We always need to make sure that the required inode state
    -	 * is safe on disk.  The vnode might be clean but because
    -	 * of committed transactions that haven't hit the disk yet.
    -	 * Likewise, there could be unflushed non-transactional
    -	 * changes to the inode core that have to go to disk.
    -	 *
    -	 * The following code depends on one assumption:  that
    -	 * any transaction that changes an inode logs the core
    -	 * because it has to change some field in the inode core
    -	 * (typically nextents or nblocks).  That assumption
    -	 * implies that any transactions against an inode will
    -	 * catch any non-transactional updates.  If inode-altering
    -	 * transactions exist that violate this assumption, the
    -	 * code breaks.  Right now, it figures that if the involved
    -	 * update_* field is clear and the inode is unpinned, the
    -	 * inode is clean.  Either it's been flushed or it's been
    -	 * committed and the commit has hit the disk unpinning the inode.
    -	 * (Note that xfs_inode_item_format() called at commit clears
    -	 * the update_* fields.)
    -	 */
    -	xfs_ilock(ip, XFS_ILOCK_SHARED);
    -
    -	/* If we are flushing data then we care about update_size
    -	 * being set, otherwise we care about update_core
    -	 */
    -	if ((flag & FSYNC_DATA) ?
    -			(ip->i_update_size == 0) :
    -			(ip->i_update_core == 0)) {
    -		/*
    -		 * Timestamps/size haven't changed since last inode
    -		 * flush or inode transaction commit.  That means
    -		 * either nothing got written or a transaction
    -		 * committed which caught the updates.	If the
    -		 * latter happened and the transaction hasn't
    -		 * hit the disk yet, the inode will be still
    -		 * be pinned.  If it is, force the log.
    -		 */
    -
    -		xfs_iunlock(ip, XFS_ILOCK_SHARED);
    -
    -		if (xfs_ipincount(ip)) {
    -			_xfs_log_force(ip->i_mount, (xfs_lsn_t)0,
    -				      XFS_LOG_FORCE |
    -				      ((flag & FSYNC_WAIT)
    -				       ? XFS_LOG_SYNC : 0),
    -				      &log_flushed);
    -		} else {
    -			/*
    -			 * If the inode is not pinned and nothing
    -			 * has changed we don't need to flush the
    -			 * cache.
    -			 */
    -			changed = 0;
    -		}
    -		error = 0;
    -	} else	{
    -		/*
    -		 * Kick off a transaction to log the inode
    -		 * core to get the updates.  Make it
    -		 * sync if FSYNC_WAIT is passed in (which
    -		 * is done by everybody but specfs).  The
    -		 * sync transaction will also force the log.
    -		 */
    -		xfs_iunlock(ip, XFS_ILOCK_SHARED);
    -		tp = xfs_trans_alloc(ip->i_mount, XFS_TRANS_FSYNC_TS);
    -		if ((error = xfs_trans_reserve(tp, 0,
    -				XFS_FSYNC_TS_LOG_RES(ip->i_mount),
    -				0, 0, 0)))  {
    -			xfs_trans_cancel(tp, 0);
    -			return error;
    -		}
    -		xfs_ilock(ip, XFS_ILOCK_EXCL);
    -
    -		/*
    -		 * Note - it's possible that we might have pushed
    -		 * ourselves out of the way during trans_reserve
    -		 * which would flush the inode.	 But there's no
    -		 * guarantee that the inode buffer has actually
    -		 * gone out yet (it's delwri).	Plus the buffer
    -		 * could be pinned anyway if it's part of an
    -		 * inode in another recent transaction.	 So we
    -		 * play it safe and fire off the transaction anyway.
    -		 */
    -		xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
    -		xfs_trans_ihold(tp, ip);
    -		xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
    -		if (flag & FSYNC_WAIT)
    -			xfs_trans_set_sync(tp);
    -		error = _xfs_trans_commit(tp, 0, NULL, &log_flushed);
    -
    -		xfs_iunlock(ip, XFS_ILOCK_EXCL);
    -	}
    -
    -	if ((ip->i_mount->m_flags & XFS_MOUNT_BARRIER) && changed) {
    -		/*
    -		 * If the log write didn't issue an ordered tag we need
    -		 * to flush the disk cache for the data device now.
    -		 */
    -		if (!log_flushed)
    -			xfs_blkdev_issue_flush(ip->i_mount->m_ddev_targp);
    -
    -		/*
    -		 * If this inode is on the RT dev we need to flush that
    -		 * cache as well.
    -		 */
    -		if (ip->i_d.di_flags & XFS_DIFLAG_REALTIME)
    -			xfs_blkdev_issue_flush(ip->i_mount->m_rtdev_targp);
    -	}
    -
    -	return error;
    -}
    -
    -/*
    - * This is called by xfs_inactive to free any blocks beyond eof,
    - * when the link count isn't zero.
    - */
    -STATIC int
    -xfs_inactive_free_eofblocks(
    -	xfs_mount_t	*mp,
    -	xfs_inode_t	*ip)
    -{
    -	xfs_trans_t	*tp;
    -	int		error;
    -	xfs_fileoff_t	end_fsb;
    -	xfs_fileoff_t	last_fsb;
    -	xfs_filblks_t	map_len;
    -	int		nimaps;
    -	xfs_bmbt_irec_t	imap;
    -
    -	/*
    -	 * Figure out if there are any blocks beyond the end
    -	 * of the file.  If not, then there is nothing to do.
    -	 */
    -	end_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)ip->i_d.di_size));
    -	last_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp));
    -	map_len = last_fsb - end_fsb;
    -	if (map_len <= 0)
    -		return 0;
    -
    -	nimaps = 1;
    -	xfs_ilock(ip, XFS_ILOCK_SHARED);
    -	error = XFS_BMAPI(mp, NULL, &ip->i_iocore, end_fsb, map_len, 0,
    -			  NULL, 0, &imap, &nimaps, NULL, NULL);
    -	xfs_iunlock(ip, XFS_ILOCK_SHARED);
    -
    -	if (!error && (nimaps != 0) &&
    -	    (imap.br_startblock != HOLESTARTBLOCK ||
    -	     ip->i_delayed_blks)) {
    -		/*
    -		 * Attach the dquots to the inode up front.
    -		 */
    -		if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
    -			return error;
    -
    -		/*
    -		 * There are blocks after the end of file.
    -		 * Free them up now by truncating the file to
    -		 * its current size.
    -		 */
    -		tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
    -
    -		/*
    -		 * Do the xfs_itruncate_start() call before
    -		 * reserving any log space because
    -		 * itruncate_start will call into the buffer
    -		 * cache and we can't
    -		 * do that within a transaction.
    -		 */
    -		xfs_ilock(ip, XFS_IOLOCK_EXCL);
    -		xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE,
    -				    ip->i_d.di_size);
    -
    -		error = xfs_trans_reserve(tp, 0,
    -					  XFS_ITRUNCATE_LOG_RES(mp),
    -					  0, XFS_TRANS_PERM_LOG_RES,
    -					  XFS_ITRUNCATE_LOG_COUNT);
    -		if (error) {
    -			ASSERT(XFS_FORCED_SHUTDOWN(mp));
    -			xfs_trans_cancel(tp, 0);
    -			xfs_iunlock(ip, XFS_IOLOCK_EXCL);
    -			return error;
    -		}
    -
    -		xfs_ilock(ip, XFS_ILOCK_EXCL);
    -		xfs_trans_ijoin(tp, ip,
    -				XFS_IOLOCK_EXCL |
    -				XFS_ILOCK_EXCL);
    -		xfs_trans_ihold(tp, ip);
    -
    -		error = xfs_itruncate_finish(&tp, ip,
    -					     ip->i_d.di_size,
    -					     XFS_DATA_FORK,
    -					     0);
    -		/*
    -		 * If we get an error at this point we
    -		 * simply don't bother truncating the file.
    -		 */
    -		if (error) {
    -			xfs_trans_cancel(tp,
    -					 (XFS_TRANS_RELEASE_LOG_RES |
    -					  XFS_TRANS_ABORT));
    -		} else {
    -			error = xfs_trans_commit(tp,
    -						XFS_TRANS_RELEASE_LOG_RES,
    -						NULL);
    -		}
    -		xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
    -	}
    -	return error;
    -}
    -
    -/*
    - * Free a symlink that has blocks associated with it.
    - */
    -STATIC int
    -xfs_inactive_symlink_rmt(
    -	xfs_inode_t	*ip,
    -	xfs_trans_t	**tpp)
    -{
    -	xfs_buf_t	*bp;
    -	int		committed;
    -	int		done;
    -	int		error;
    -	xfs_fsblock_t	first_block;
    -	xfs_bmap_free_t	free_list;
    -	int		i;
    -	xfs_mount_t	*mp;
    -	xfs_bmbt_irec_t	mval[SYMLINK_MAPS];
    -	int		nmaps;
    -	xfs_trans_t	*ntp;
    -	int		size;
    -	xfs_trans_t	*tp;
    -
    -	tp = *tpp;
    -	mp = ip->i_mount;
    -	ASSERT(ip->i_d.di_size > XFS_IFORK_DSIZE(ip));
    -	/*
    -	 * We're freeing a symlink that has some
    -	 * blocks allocated to it.  Free the
    -	 * blocks here.  We know that we've got
    -	 * either 1 or 2 extents and that we can
    -	 * free them all in one bunmapi call.
    -	 */
    -	ASSERT(ip->i_d.di_nextents > 0 && ip->i_d.di_nextents <= 2);
    -	if ((error = xfs_trans_reserve(tp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0,
    -			XFS_TRANS_PERM_LOG_RES, XFS_ITRUNCATE_LOG_COUNT))) {
    -		ASSERT(XFS_FORCED_SHUTDOWN(mp));
    -		xfs_trans_cancel(tp, 0);
    -		*tpp = NULL;
    -		return error;
    -	}
    -	/*
    -	 * Lock the inode, fix the size, and join it to the transaction.
    -	 * Hold it so in the normal path, we still have it locked for
    -	 * the second transaction.  In the error paths we need it
    -	 * held so the cancel won't rele it, see below.
    -	 */
    -	xfs_ilock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
    -	size = (int)ip->i_d.di_size;
    -	ip->i_d.di_size = 0;
    -	xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
    -	xfs_trans_ihold(tp, ip);
    -	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
    -	/*
    -	 * Find the block(s) so we can inval and unmap them.
    -	 */
    -	done = 0;
    -	XFS_BMAP_INIT(&free_list, &first_block);
    -	nmaps = sizeof(mval) / sizeof(mval[0]);
    -	if ((error = xfs_bmapi(tp, ip, 0, XFS_B_TO_FSB(mp, size),
    -			XFS_BMAPI_METADATA, &first_block, 0, mval, &nmaps,
    -			&free_list, NULL)))
    -		goto error0;
    -	/*
    -	 * Invalidate the block(s).
    -	 */
    -	for (i = 0; i < nmaps; i++) {
    -		bp = xfs_trans_get_buf(tp, mp->m_ddev_targp,
    -			XFS_FSB_TO_DADDR(mp, mval[i].br_startblock),
    -			XFS_FSB_TO_BB(mp, mval[i].br_blockcount), 0);
    -		xfs_trans_binval(tp, bp);
    -	}
    -	/*
    -	 * Unmap the dead block(s) to the free_list.
    -	 */
    -	if ((error = xfs_bunmapi(tp, ip, 0, size, XFS_BMAPI_METADATA, nmaps,
    -			&first_block, &free_list, NULL, &done)))
    -		goto error1;
    -	ASSERT(done);
    -	/*
    -	 * Commit the first transaction.  This logs the EFI and the inode.
    -	 */
    -	if ((error = xfs_bmap_finish(&tp, &free_list, first_block, &committed)))
    -		goto error1;
    -	/*
    -	 * The transaction must have been committed, since there were
    -	 * actually extents freed by xfs_bunmapi.  See xfs_bmap_finish.
    -	 * The new tp has the extent freeing and EFDs.
    -	 */
    -	ASSERT(committed);
    -	/*
    -	 * The first xact was committed, so add the inode to the new one.
    -	 * Mark it dirty so it will be logged and moved forward in the log as
    -	 * part of every commit.
    -	 */
    -	xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
    -	xfs_trans_ihold(tp, ip);
    -	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
    -	/*
    -	 * Get a new, empty transaction to return to our caller.
    -	 */
    -	ntp = xfs_trans_dup(tp);
    -	/*
    -	 * Commit the transaction containing extent freeing and EFDs.
    -	 * If we get an error on the commit here or on the reserve below,
    -	 * we need to unlock the inode since the new transaction doesn't
    -	 * have the inode attached.
    -	 */
    -	error = xfs_trans_commit(tp, 0, NULL);
    -	tp = ntp;
    -	if (error) {
    -		ASSERT(XFS_FORCED_SHUTDOWN(mp));
    -		goto error0;
    -	}
    -	/*
    -	 * Remove the memory for extent descriptions (just bookkeeping).
    -	 */
    -	if (ip->i_df.if_bytes)
    -		xfs_idata_realloc(ip, -ip->i_df.if_bytes, XFS_DATA_FORK);
    -	ASSERT(ip->i_df.if_bytes == 0);
    -	/*
    -	 * Put an itruncate log reservation in the new transaction
    -	 * for our caller.
    -	 */
    -	if ((error = xfs_trans_reserve(tp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0,
    -			XFS_TRANS_PERM_LOG_RES, XFS_ITRUNCATE_LOG_COUNT))) {
    -		ASSERT(XFS_FORCED_SHUTDOWN(mp));
    -		goto error0;
    -	}
    -	/*
    -	 * Return with the inode locked but not joined to the transaction.
    -	 */
    -	*tpp = tp;
    -	return 0;
    -
    - error1:
    -	xfs_bmap_cancel(&free_list);
    - error0:
    -	/*
    -	 * Have to come here with the inode locked and either
    -	 * (held and in the transaction) or (not in the transaction).
    -	 * If the inode isn't held then cancel would iput it, but
    -	 * that's wrong since this is inactive and the vnode ref
    -	 * count is 0 already.
    -	 * Cancel won't do anything to the inode if held, but it still
    -	 * needs to be locked until the cancel is done, if it was
    -	 * joined to the transaction.
    -	 */
    -	xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
    -	xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
    -	*tpp = NULL;
    -	return error;
    -
    -}
    -
    -STATIC int
    -xfs_inactive_symlink_local(
    -	xfs_inode_t	*ip,
    -	xfs_trans_t	**tpp)
    -{
    -	int		error;
    -
    -	ASSERT(ip->i_d.di_size <= XFS_IFORK_DSIZE(ip));
    -	/*
    -	 * We're freeing a symlink which fit into
    -	 * the inode.  Just free the memory used
    -	 * to hold the old symlink.
    -	 */
    -	error = xfs_trans_reserve(*tpp, 0,
    -				  XFS_ITRUNCATE_LOG_RES(ip->i_mount),
    -				  0, XFS_TRANS_PERM_LOG_RES,
    -				  XFS_ITRUNCATE_LOG_COUNT);
    -
    -	if (error) {
    -		xfs_trans_cancel(*tpp, 0);
    -		*tpp = NULL;
    -		return error;
    -	}
    -	xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
    -
    -	/*
    -	 * Zero length symlinks _can_ exist.
    -	 */
    -	if (ip->i_df.if_bytes > 0) {
    -		xfs_idata_realloc(ip,
    -				  -(ip->i_df.if_bytes),
    -				  XFS_DATA_FORK);
    -		ASSERT(ip->i_df.if_bytes == 0);
    -	}
    -	return 0;
    -}
    -
    -/*
    - *
    - */
    -STATIC int
    -xfs_inactive_attrs(
    -	xfs_inode_t	*ip,
    -	xfs_trans_t	**tpp)
    -{
    -	xfs_trans_t	*tp;
    -	int		error;
    -	xfs_mount_t	*mp;
    -
    -	ASSERT(ismrlocked(&ip->i_iolock, MR_UPDATE));
    -	tp = *tpp;
    -	mp = ip->i_mount;
    -	ASSERT(ip->i_d.di_forkoff != 0);
    -	xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
    -	xfs_iunlock(ip, XFS_ILOCK_EXCL);
    -
    -	error = xfs_attr_inactive(ip);
    -	if (error) {
    -		*tpp = NULL;
    -		xfs_iunlock(ip, XFS_IOLOCK_EXCL);
    -		return error; /* goto out */
    -	}
    -
    -	tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
    -	error = xfs_trans_reserve(tp, 0,
    -				  XFS_IFREE_LOG_RES(mp),
    -				  0, XFS_TRANS_PERM_LOG_RES,
    -				  XFS_INACTIVE_LOG_COUNT);
    -	if (error) {
    -		ASSERT(XFS_FORCED_SHUTDOWN(mp));
    -		xfs_trans_cancel(tp, 0);
    -		*tpp = NULL;
    -		xfs_iunlock(ip, XFS_IOLOCK_EXCL);
    -		return error;
    -	}
    -
    -	xfs_ilock(ip, XFS_ILOCK_EXCL);
    -	xfs_trans_ijoin(tp, ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
    -	xfs_trans_ihold(tp, ip);
    -	xfs_idestroy_fork(ip, XFS_ATTR_FORK);
    -
    -	ASSERT(ip->i_d.di_anextents == 0);
    -
    -	*tpp = tp;
    -	return 0;
    -}
    -
    -STATIC int
    -xfs_release(
    -	bhv_desc_t	*bdp)
    -{
    -	xfs_inode_t	*ip;
    -	xfs_vnode_t	*vp;
    -	xfs_mount_t	*mp;
    -	int		error;
    -
    -	vp = BHV_TO_VNODE(bdp);
    -	ip = XFS_BHVTOI(bdp);
    -
    -	if (!VN_ISREG(vp) || (ip->i_d.di_mode == 0)) {
    -		return 0;
    -	}
    -
    -	/* If this is a read-only mount, don't do this (would generate I/O) */
    -	if (vp->v_vfsp->vfs_flag & VFS_RDONLY)
    -		return 0;
    -
    -#ifdef HAVE_REFCACHE
    -	/* If we are in the NFS reference cache then don't do this now */
    -	if (ip->i_refcache)
    -		return 0;
    -#endif
    -
    -	mp = ip->i_mount;
    -
    -	if (ip->i_d.di_nlink != 0) {
    -		if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) &&
    -		     ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0 ||
    -		       ip->i_delayed_blks > 0)) &&
    -		     (ip->i_df.if_flags & XFS_IFEXTENTS))  &&
    -		    (!(ip->i_d.di_flags &
    -				(XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)))) {
    -			if ((error = xfs_inactive_free_eofblocks(mp, ip)))
    -				return error;
    -
    -#ifdef RMC			/* Update linux inode block count after free above */
    -			vn_to_inode(vp)->i_blocks = XFS_FSB_TO_BB(mp,
    -				ip->i_d.di_nblocks + ip->i_delayed_blks);
    -#endif
    -		}
    -	}
    -
    -	return 0;
    -}
    -
    -/*
    - * xfs_inactive
    - *
    - * This is called when the vnode reference count for the vnode
    - * goes to zero.  If the file has been unlinked, then it must
    - * now be truncated.  Also, we clear all of the read-ahead state
    - * kept for the inode here since the file is now closed.
    - */
    -STATIC int
    -xfs_inactive(
    -	bhv_desc_t	*bdp,
    -	cred_t		*credp)
    -{
    -	xfs_inode_t	*ip;
    -	xfs_vnode_t	*vp;
    -
    -	xfs_bmap_free_t	free_list; 
    -	xfs_fsblock_t	first_block;
    -	int		committed;
    -	xfs_trans_t	*tp;
    -	xfs_mount_t	*mp;
    -	int		error;
    -	int		truncate;
    -
    -	vp = BHV_TO_VNODE(bdp);
    -	vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
    -
    -	ip = XFS_BHVTOI(bdp);
    -
    -	/*
    -	 * If the inode is already free, then there can be nothing
    -	 * to clean up here.
    -	 */
    -	if (ip->i_d.di_mode == 0 || VN_BAD(vp)) {
    -		ASSERT(ip->i_df.if_real_bytes == 0);
    -		ASSERT(ip->i_df.if_broot_bytes == 0);
    -		return VN_INACTIVE_CACHE;
    -	}
    -
    -	/*
    -	 * Only do a truncate if it's a regular file with
    -	 * some actual space in it.  It's OK to look at the
    -	 * inode's fields without the lock because we're the
    -	 * only one with a reference to the inode.
    -	 */
    -	truncate = ((ip->i_d.di_nlink == 0) &&
    -            ((ip->i_d.di_size != 0) || (ip->i_d.di_nextents > 0) ||
    -             (ip->i_delayed_blks > 0)) &&
    -	    ((ip->i_d.di_mode & S_IFMT) == S_IFREG));
    -
    -	mp = ip->i_mount;
    -
    -	if (ip->i_d.di_nlink == 0 &&
    -	    DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_DESTROY)) {
    -		(void) XFS_SEND_DESTROY(mp, vp, DM_RIGHT_NULL);
    -	}
    -
    -	error = 0;
    -
    -	/* If this is a read-only mount, don't do this (would generate I/O) */
    -	if (vp->v_vfsp->vfs_flag & VFS_RDONLY)
    -		goto out;
    -
    -	if (ip->i_d.di_nlink != 0) {
    -		if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) &&
    -                     ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0 ||
    -                       ip->i_delayed_blks > 0)) &&
    -		      (ip->i_df.if_flags & XFS_IFEXTENTS) &&
    -		     (!(ip->i_d.di_flags &
    -				(XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) ||
    -		      (ip->i_delayed_blks != 0)))) {
    -			if ((error = xfs_inactive_free_eofblocks(mp, ip)))
    -				return VN_INACTIVE_CACHE;
    -#ifdef RMC
    -			/* Update linux inode block count after free above */
    -			vn_to_inode(vp)->i_blocks = XFS_FSB_TO_BB(mp,
    -				ip->i_d.di_nblocks + ip->i_delayed_blks);
    -#endif
    -		}
    -		goto out;
    -	}
    -
    -	ASSERT(ip->i_d.di_nlink == 0);
    -
    -	if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
    -		return VN_INACTIVE_CACHE;
    -
    -	tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
    -	if (truncate) {
    -		/*
    -		 * Do the xfs_itruncate_start() call before
    -		 * reserving any log space because itruncate_start
    -		 * will call into the buffer cache and we can't
    -		 * do that within a transaction.
    -		 */
    -		xfs_ilock(ip, XFS_IOLOCK_EXCL);
    -
    -		xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE, 0);
    -
    -		error = xfs_trans_reserve(tp, 0,
    -					  XFS_ITRUNCATE_LOG_RES(mp),
    -					  0, XFS_TRANS_PERM_LOG_RES,
    -					  XFS_ITRUNCATE_LOG_COUNT);
    -		if (error) {
    -			/* Don't call itruncate_cleanup */
    -			ASSERT(XFS_FORCED_SHUTDOWN(mp));
    -			xfs_trans_cancel(tp, 0);
    -			xfs_iunlock(ip, XFS_IOLOCK_EXCL);
    -			return VN_INACTIVE_CACHE;
    -		}
    -
    -		xfs_ilock(ip, XFS_ILOCK_EXCL);
    -		xfs_trans_ijoin(tp, ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
    -		xfs_trans_ihold(tp, ip);
    -
    -		/*
    -		 * normally, we have to run xfs_itruncate_finish sync.
    -		 * But if filesystem is wsync and we're in the inactive
    -		 * path, then we know that nlink == 0, and that the
    -		 * xaction that made nlink == 0 is permanently committed
    -		 * since xfs_remove runs as a synchronous transaction.
    -		 */
    -		error = xfs_itruncate_finish(&tp, ip, 0, XFS_DATA_FORK,
    -				(!(mp->m_flags & XFS_MOUNT_WSYNC) ? 1 : 0));
    -
    -		if (error) {
    -			xfs_trans_cancel(tp,
    -				XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
    -			xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
    -			return VN_INACTIVE_CACHE;
    -		}
    -	} else if ((ip->i_d.di_mode & S_IFMT) == S_IFLNK) {
    -
    -		/*
    -		 * If we get an error while cleaning up a
    -		 * symlink we bail out.
    -		 */
    -		error = (ip->i_d.di_size > XFS_IFORK_DSIZE(ip)) ?
    -			xfs_inactive_symlink_rmt(ip, &tp) :
    -			xfs_inactive_symlink_local(ip, &tp);
    -
    -		if (error) {
    -			ASSERT(tp == NULL);
    -			return VN_INACTIVE_CACHE;
    -		}
    -
    -		xfs_trans_ijoin(tp, ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
    -		xfs_trans_ihold(tp, ip);
    -	} else {
    -		error = xfs_trans_reserve(tp, 0,
    -					  XFS_IFREE_LOG_RES(mp),
    -					  0, XFS_TRANS_PERM_LOG_RES,
    -					  XFS_INACTIVE_LOG_COUNT);
    -		if (error) {
    -			ASSERT(XFS_FORCED_SHUTDOWN(mp));
    -			xfs_trans_cancel(tp, 0);
    -			return VN_INACTIVE_CACHE;
    -		}
    -
    -		xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
    -		xfs_trans_ijoin(tp, ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
    -		xfs_trans_ihold(tp, ip);
    -	}
    -
    -	/*
    -	 * If there are attributes associated with the file
    -	 * then blow them away now.  The code calls a routine
    -	 * that recursively deconstructs the attribute fork.
    -	 * We need to just commit the current transaction
    -	 * because we can't use it for xfs_attr_inactive().
    -	 */
    -	if (ip->i_d.di_anextents > 0) {
    -		error = xfs_inactive_attrs(ip, &tp);
    -		/*
    -		 * If we got an error, the transaction is already
    -		 * cancelled, and the inode is unlocked. Just get out.
    -		 */
    -		 if (error)
    -			 return VN_INACTIVE_CACHE;
    -	} else if (ip->i_afp) {
    -		xfs_idestroy_fork(ip, XFS_ATTR_FORK);
    -	}
    -
    -	/*
    -	 * Free the inode.
    -	 */
    -	XFS_BMAP_INIT(&free_list, &first_block);
    -	error = xfs_ifree(tp, ip, &free_list);
    -	if (error) {
    -		/*
    -		 * If we fail to free the inode, shut down.  The cancel
    -		 * might do that, we need to make sure.  Otherwise the
    -		 * inode might be lost for a long time or forever.
    -		 */
    -		if (!XFS_FORCED_SHUTDOWN(mp)) {
    -			cmn_err(CE_NOTE,
    -		"xfs_inactive:	xfs_ifree() returned an error = %d on %s",
    -				error, mp->m_fsname);
    -			xfs_force_shutdown(mp, XFS_METADATA_IO_ERROR);
    -		}
    -		xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
    -	} else {
    -		/*
    -		 * Credit the quota account(s). The inode is gone.
    -		 */
    -		XFS_TRANS_MOD_DQUOT_BYINO(mp, tp, ip, XFS_TRANS_DQ_ICOUNT, -1);
    -
    -		/*
    -		 * Just ignore errors at this point.  There is
    -		 * nothing we can do except to try to keep going.
    -		 */
    -		(void) xfs_bmap_finish(&tp,  &free_list, first_block,
    -				       &committed);
    -		(void) xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
    -	}
    -	/*
    -	 * Release the dquots held by inode, if any.
    -	 */
    -	XFS_QM_DQDETACH(mp, ip);
    -
    -	xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
    -
    - out:
    -	return VN_INACTIVE_CACHE;
    -}
    -
    -
    -/*
    - * xfs_lookup
    - */
    -STATIC int
    -xfs_lookup(
    -	bhv_desc_t		*dir_bdp,
    -	vname_t			*dentry,
    -	xfs_vnode_t		**vpp,
    -	int			flags,
    -	xfs_vnode_t		*rdir,
    -	cred_t			*credp)
    -{
    -	xfs_inode_t		*dp, *ip;
    -	xfs_ino_t		e_inum;
    -	int			error;
    -	uint			lock_mode;
    -	xfs_vnode_t		*dir_vp;
    -
    -	dir_vp = BHV_TO_VNODE(dir_bdp);
    -	vn_trace_entry(dir_vp, __FUNCTION__, (inst_t *)__return_address);
    -
    -	dp = XFS_BHVTOI(dir_bdp);
    -
    -	if (XFS_FORCED_SHUTDOWN(dp->i_mount))
    -		return XFS_ERROR(EIO);
    -
    -	lock_mode = xfs_ilock_map_shared(dp);
    -	error = xfs_dir_lookup_int(dir_bdp, lock_mode, dentry, &e_inum, &ip);
    -	if (!error) {
    -		*vpp = XFS_ITOV(ip);
    -		ITRACE(ip);
    -	}
    -	xfs_iunlock_map_shared(dp, lock_mode);
    -	return error;
    -}
    -
    -
    -/*
    - * xfs_create (create a new file).
    - */
    -STATIC int
    -xfs_create(
    -	bhv_desc_t		*dir_bdp,
    -	vname_t			*dentry,
    -	xfs_vattr_t		*vap,
    -	xfs_vnode_t		**vpp,
    -	cred_t			*credp)
    -{
    -	char			*name = VNAME(dentry);
    -	xfs_vnode_t		*dir_vp;
    -	xfs_inode_t		*dp, *ip;
    -	xfs_vnode_t	        *vp=NULL;
    -	xfs_trans_t		*tp;
    -	xfs_mount_t	        *mp;
    -	xfs_dev_t		rdev;
    -	int                     error;
    -	xfs_bmap_free_t		free_list;
    -	xfs_fsblock_t		first_block;
    -	boolean_t		dp_joined_to_trans;
    -	int			dm_event_sent = 0;
    -	uint			cancel_flags;
    -	int			committed;
    -	xfs_prid_t		prid;
    -	struct xfs_dquot	*udqp, *gdqp;
    -	uint			resblks;
    -	int			dm_di_mode;
    -	int			namelen;
    -
    -	ASSERT(!*vpp);
    -	dir_vp = BHV_TO_VNODE(dir_bdp);
    -	vn_trace_entry(dir_vp, __FUNCTION__, (inst_t *)__return_address);
    -
    -	dp = XFS_BHVTOI(dir_bdp);
    -	mp = dp->i_mount;
    -
    -	dm_di_mode = vap->va_mode;
    -	namelen = VNAMELEN(dentry);
    -
    -	if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_CREATE)) {
    -		error = XFS_SEND_NAMESP(mp, DM_EVENT_CREATE,
    -				dir_vp, DM_RIGHT_NULL, NULL,
    -				DM_RIGHT_NULL, name, NULL,
    -				dm_di_mode, 0, 0);
    -
    -		if (error)
    -			return error;
    -		dm_event_sent = 1;
    -	}
    -
    -	if (XFS_FORCED_SHUTDOWN(mp))
    -		return XFS_ERROR(EIO);
    -
    -	/* Return through std_return after this point. */
    -
    -	udqp = gdqp = NULL;
    -
    -	if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
    -		prid = dp->i_d.di_projid;
    -	else if (vap->va_mask & XFS_AT_PROJID)
    -		prid = (xfs_prid_t)vap->va_projid;
    -	else
    -		prid = (xfs_prid_t)dfltprid;
    -
    -	/*
    -	 * Make sure that we have allocated dquot(s) on disk.
    -	 */
    -	error = XFS_QM_DQVOPALLOC(mp, dp,
    -			current_fsuid(credp), current_fsgid(credp), prid,
    -			XFS_QMOPT_QUOTALL|XFS_QMOPT_INHERIT, &udqp, &gdqp);
    -	if (error)
    -		goto std_return;
    -
    -	ip = NULL;
    -	dp_joined_to_trans = B_FALSE;
    -
    -	tp = xfs_trans_alloc(mp, XFS_TRANS_CREATE);
    -	cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
    -	resblks = XFS_CREATE_SPACE_RES(mp, namelen);
    -	/*
    -	 * Initially assume that the file does not exist and
    -	 * reserve the resources for that case.  If that is not
    -	 * the case we'll drop the one we have and get a more
    -	 * appropriate transaction later.
    -	 */
    -	error = xfs_trans_reserve(tp, resblks, XFS_CREATE_LOG_RES(mp), 0,
    -			XFS_TRANS_PERM_LOG_RES, XFS_CREATE_LOG_COUNT);
    -	if (error == ENOSPC) {
    -		resblks = 0;
    -		error = xfs_trans_reserve(tp, 0, XFS_CREATE_LOG_RES(mp), 0,
    -				XFS_TRANS_PERM_LOG_RES, XFS_CREATE_LOG_COUNT);
    -	}
    -	if (error) {
    -		cancel_flags = 0;
    -		dp = NULL;
    -		goto error_return;
    -	}
    -
    -	xfs_ilock(dp, XFS_ILOCK_EXCL);
    -
    -	XFS_BMAP_INIT(&free_list, &first_block);
    -
    -	ASSERT(ip == NULL);
    -
    -	/*
    -	 * Reserve disk quota and the inode.
    -	 */
    -	error = XFS_TRANS_RESERVE_QUOTA(mp, tp, udqp, gdqp, resblks, 1, 0);
    -	if (error)
    -		goto error_return;
    -
    -	if (resblks == 0 &&
    -	    (error = XFS_DIR_CANENTER(mp, tp, dp, name, namelen)))
    -		goto error_return;
    -	rdev = (vap->va_mask & XFS_AT_RDEV) ? vap->va_rdev : 0;
    -	error = xfs_dir_ialloc(&tp, dp, vap->va_mode, 1,
    -			rdev, credp, prid, resblks > 0,
    -			&ip, &committed);
    -	if (error) {
    -		if (error == ENOSPC)
    -			goto error_return;
    -		goto abort_return;
    -	}
    -	ITRACE(ip);
    -
    -	/*
    -	 * At this point, we've gotten a newly allocated inode.
    -	 * It is locked (and joined to the transaction).
    -	 */
    -
    -	ASSERT(ismrlocked (&ip->i_lock, MR_UPDATE));
    -
    -	/*
    -	 * Now we join the directory inode to the transaction.
    -	 * We do not do it earlier because xfs_dir_ialloc
    -	 * might commit the previous transaction (and release
    -	 * all the locks).
    -	 */
    -
    -	VN_HOLD(dir_vp);
    -	xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
    -	dp_joined_to_trans = B_TRUE;
    -
    -	error = XFS_DIR_CREATENAME(mp, tp, dp, name, namelen, ip->i_ino,
    -		&first_block, &free_list,
    -		resblks ? resblks - XFS_IALLOC_SPACE_RES(mp) : 0);
    -	if (error) {
    -		ASSERT(error != ENOSPC);
    -		goto abort_return;
    -	}
    -	xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
    -	xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
    -
    -	/*
    -	 * If this is a synchronous mount, make sure that the
    -	 * create transaction goes to disk before returning to
    -	 * the user.
    -	 */
    -	if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
    -		xfs_trans_set_sync(tp);
    -	}
    -
    -	dp->i_gen++;
    -
    -	/*
    -	 * Attach the dquot(s) to the inodes and modify them incore.
    -	 * These ids of the inode couldn't have changed since the new
    -	 * inode has been locked ever since it was created.
    -	 */
    -	XFS_QM_DQVOPCREATE(mp, tp, ip, udqp, gdqp);
    -
    -	/*
    -	 * xfs_trans_commit normally decrements the vnode ref count
    -	 * when it unlocks the inode. Since we want to return the
    -	 * vnode to the caller, we bump the vnode ref count now.
    -	 */
    -	IHOLD(ip);
    -	vp = XFS_ITOV(ip);
    -
    -	error = xfs_bmap_finish(&tp, &free_list, first_block, &committed);
    -	if (error) {
    -		xfs_bmap_cancel(&free_list);
    -		goto abort_rele;
    -	}
    -
    -	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
    -	if (error) {
    -		IRELE(ip);
    -		tp = NULL;
    -		goto error_return;
    -	}
    -
    -	XFS_QM_DQRELE(mp, udqp);
    -	XFS_QM_DQRELE(mp, gdqp);
    -
    -	/*
    -	 * Propagate the fact that the vnode changed after the
    -	 * xfs_inode locks have been released.
    -	 */
    -	XVOP_VNODE_CHANGE(vp, VCHANGE_FLAGS_TRUNCATED, 3);
    -
    -	*vpp = vp;
    -
    -	/* Fallthrough to std_return with error = 0  */
    -
    -std_return:
    -	if ( (*vpp || (error != 0 && dm_event_sent != 0)) &&
    -			DM_EVENT_ENABLED(dir_vp->v_vfsp, XFS_BHVTOI(dir_bdp),
    -							DM_EVENT_POSTCREATE)) {
    -		(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTCREATE,
    -			dir_vp, DM_RIGHT_NULL,
    -			*vpp ? vp:NULL,
    -			DM_RIGHT_NULL, name, NULL,
    -			dm_di_mode, error, 0);
    -	}
    -	return error;
    -
    - abort_return:
    -	cancel_flags |= XFS_TRANS_ABORT;
    -	/* FALLTHROUGH */
    -
    - error_return:
    -	if (tp != NULL)
    -		xfs_trans_cancel(tp, cancel_flags);
    -
    -	if (!dp_joined_to_trans && (dp != NULL))
    -		xfs_iunlock(dp, XFS_ILOCK_EXCL);
    -	XFS_QM_DQRELE(mp, udqp);
    -	XFS_QM_DQRELE(mp, gdqp);
    -
    -	goto std_return;
    -
    - abort_rele:
    -	/*
    -	 * Wait until after the current transaction is aborted to
    -	 * release the inode.  This prevents recursive transactions
    -	 * and deadlocks from xfs_inactive.
    -	 */
    -	cancel_flags |= XFS_TRANS_ABORT;
    -	xfs_trans_cancel(tp, cancel_flags);
    -	IRELE(ip);
    -
    -	XFS_QM_DQRELE(mp, udqp);
    -	XFS_QM_DQRELE(mp, gdqp);
    -
    -	goto std_return;
    -}
    -
    -#ifdef DEBUG
    -/*
    - * Some counters to see if (and how often) we are hitting some deadlock
    - * prevention code paths.
    - */
    -
    -int xfs_rm_locks;
    -int xfs_rm_lock_delays;
    -int xfs_rm_attempts;
    -#endif
    -
    -/*
    - * The following routine will lock the inodes associated with the
    - * directory and the named entry in the directory. The locks are
    - * acquired in increasing inode number.
    - *
    - * If the entry is "..", then only the directory is locked. The
    - * vnode ref count will still include that from the .. entry in
    - * this case.
    - *
    - * There is a deadlock we need to worry about. If the locked directory is
    - * in the AIL, it might be blocking up the log. The next inode we lock
    - * could be already locked by another thread waiting for log space (e.g
    - * a permanent log reservation with a long running transaction (see
    - * xfs_itruncate_finish)). To solve this, we must check if the directory
    - * is in the ail and use lock_nowait. If we can't lock, we need to
    - * drop the inode lock on the directory and try again. xfs_iunlock will
    - * potentially push the tail if we were holding up the log.
    - */
    -STATIC int
    -xfs_lock_dir_and_entry(
    -	xfs_inode_t	*dp,
    -	vname_t		*dentry,
    -	xfs_inode_t	*ip)	/* inode of entry 'name' */
    -{
    -	int		attempts;
    -	xfs_ino_t	e_inum;
    -	xfs_inode_t	*ips[2];
    -	xfs_log_item_t	*lp;
    -
    -#ifdef DEBUG
    -	xfs_rm_locks++;
    -#endif
    -	attempts = 0;
    -
    -again:
    -	xfs_ilock(dp, XFS_ILOCK_EXCL);
    -
    -	e_inum = ip->i_ino;
    -
    -	ITRACE(ip);
    -
    -	/*
    -	 * We want to lock in increasing inum. Since we've already
    -	 * acquired the lock on the directory, we may need to release
    -	 * if if the inum of the entry turns out to be less.
    -	 */
    -	if (e_inum > dp->i_ino) {
    -		/*
    -		 * We are already in the right order, so just
    -		 * lock on the inode of the entry.
    -		 * We need to use nowait if dp is in the AIL.
    -		 */
    -
    -		lp = (xfs_log_item_t *)dp->i_itemp;
    -		if (lp && (lp->li_flags & XFS_LI_IN_AIL)) {
    -			if (!xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) {
    -				attempts++;
    -#ifdef DEBUG
    -				xfs_rm_attempts++;
    -#endif
    -
    -				/*
    -				 * Unlock dp and try again.
    -				 * xfs_iunlock will try to push the tail
    -				 * if the inode is in the AIL.
    -				 */
    -
    -				xfs_iunlock(dp, XFS_ILOCK_EXCL);
    -
    -				if ((attempts % 5) == 0) {
    -					delay(1); /* Don't just spin the CPU */
    -#ifdef DEBUG
    -					xfs_rm_lock_delays++;
    -#endif
    -				}
    -				goto again;
    -			}
    -		} else {
    -			xfs_ilock(ip, XFS_ILOCK_EXCL);
    -		}
    -	} else if (e_inum < dp->i_ino) {
    -		xfs_iunlock(dp, XFS_ILOCK_EXCL);
    -
    -		ips[0] = ip;
    -		ips[1] = dp;
    -		xfs_lock_inodes(ips, 2, 0, XFS_ILOCK_EXCL);
    -	}
    -	/* else	 e_inum == dp->i_ino */
    -	/*     This can happen if we're asked to lock /x/..
    -	 *     the entry is "..", which is also the parent directory.
    -	 */
    -
    -	return 0;
    -}
    -
    -#ifdef DEBUG
    -int xfs_locked_n;
    -int xfs_small_retries;
    -int xfs_middle_retries;
    -int xfs_lots_retries;
    -int xfs_lock_delays;
    -#endif
    -
    -/*
    - * The following routine will lock n inodes in exclusive mode.
    - * We assume the caller calls us with the inodes in i_ino order.
    - *
    - * We need to detect deadlock where an inode that we lock
    - * is in the AIL and we start waiting for another inode that is locked
    - * by a thread in a long running transaction (such as truncate). This can
    - * result in deadlock since the long running trans might need to wait
    - * for the inode we just locked in order to push the tail and free space
    - * in the log.
    - */
    -void
    -xfs_lock_inodes(
    -	xfs_inode_t	**ips,
    -	int		inodes,
    -	int		first_locked,
    -	uint		lock_mode)
    -{
    -	int		attempts = 0, i, j, try_lock;
    -	xfs_log_item_t	*lp;
    -
    -	ASSERT(ips && (inodes >= 2)); /* we need at least two */
    -
    -	if (first_locked) {
    -		try_lock = 1;
    -		i = 1;
    -	} else {
    -		try_lock = 0;
    -		i = 0;
    -	}
    -
    -again:
    -	for (; i < inodes; i++) {
    -		ASSERT(ips[i]);
    -
    -		if (i && (ips[i] == ips[i-1]))	/* Already locked */
    -			continue;
    -
    -		/*
    -		 * If try_lock is not set yet, make sure all locked inodes
    -		 * are not in the AIL.
    -		 * If any are, set try_lock to be used later.
    -		 */
    -
    -		if (!try_lock) {
    -			for (j = (i - 1); j >= 0 && !try_lock; j--) {
    -				lp = (xfs_log_item_t *)ips[j]->i_itemp;
    -				if (lp && (lp->li_flags & XFS_LI_IN_AIL)) {
    -					try_lock++;
    -				}
    -			}
    -		}
    -
    -		/*
    -		 * If any of the previous locks we have locked is in the AIL,
    -		 * we must TRY to get the second and subsequent locks. If
    -		 * we can't get any, we must release all we have
    -		 * and try again.
    -		 */
    -
    -		if (try_lock) {
    -			/* try_lock must be 0 if i is 0. */
    -			/*
    -			 * try_lock means we have an inode locked
    -			 * that is in the AIL.
    -			 */
    -			ASSERT(i != 0);
    -			if (!xfs_ilock_nowait(ips[i], lock_mode)) {
    -				attempts++;
    -
    -				/*
    -				 * Unlock all previous guys and try again.
    -				 * xfs_iunlock will try to push the tail
    -				 * if the inode is in the AIL.
    -				 */
    -
    -				for(j = i - 1; j >= 0; j--) {
    -
    -					/*
    -					 * Check to see if we've already
    -					 * unlocked this one.
    -					 * Not the first one going back,
    -					 * and the inode ptr is the same.
    -					 */
    -					if ((j != (i - 1)) && ips[j] ==
    -								ips[j+1])
    -						continue;
    -
    -					xfs_iunlock(ips[j], lock_mode);
    -				}
    -
    -				if ((attempts % 5) == 0) {
    -					delay(1); /* Don't just spin the CPU */
    -#ifdef DEBUG
    -					xfs_lock_delays++;
    -#endif
    -				}
    -				i = 0;
    -				try_lock = 0;
    -				goto again;
    -			}
    -		} else {
    -			xfs_ilock(ips[i], lock_mode);
    -		}
    -	}
    -
    -#ifdef DEBUG
    -	if (attempts) {
    -		if (attempts < 5) xfs_small_retries++;
    -		else if (attempts < 100) xfs_middle_retries++;
    -		else xfs_lots_retries++;
    -	} else {
    -		xfs_locked_n++;
    -	}
    -#endif
    -}
    -
    -#ifdef	DEBUG
    -#define	REMOVE_DEBUG_TRACE(x)	{remove_which_error_return = (x);}
    -int remove_which_error_return = 0;
    -#else /* ! DEBUG */
    -#define	REMOVE_DEBUG_TRACE(x)
    -#endif	/* ! DEBUG */
    -
    -extern int xfs_remove(bhv_desc_t *, bhv_desc_t *, vname_t *, cred_t *);
    -/*
    - * xfs_remove
    - *
    - */
    -int
    -xfs_remove(
    -	bhv_desc_t		*dir_bdp,
    -	bhv_desc_t		*vp_bdp,
    -	vname_t			*dentry,
    -	cred_t			*credp)
    -{
    -	xfs_vnode_t		*dir_vp;
    -	xfs_vnode_t		*xvp;
    -	char			*name = VNAME(dentry);
    -	xfs_inode_t             *dp, *ip;
    -	xfs_trans_t             *tp = NULL;
    -	xfs_mount_t		*mp;
    -	int                     error = 0;
    -	xfs_bmap_free_t         free_list;
    -	xfs_fsblock_t           first_block;
    -	int			cancel_flags;
    -	int			committed;
    -	int			dm_di_mode = 0;
    -	int			link_zero;
    -	uint			resblks;
    -	int			namelen;
    -
    -	dir_vp = BHV_TO_VNODE(dir_bdp);
    -	xvp = BHV_TO_VNODE(vp_bdp);
    -
    -	printf("xfs_remove: dvp %p vp %p\n",dir_vp,xvp);
    -	vn_trace_entry(dir_vp, __FUNCTION__, (inst_t *)__return_address);
    -
    -	dp = XFS_BHVTOI(dir_bdp);
    -	mp = dp->i_mount;
    -
    -	if (XFS_FORCED_SHUTDOWN(mp))
    -		return XFS_ERROR(EIO);
    -
    -	namelen = VNAMELEN(dentry);
    -
    -	if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_REMOVE)) {
    -		error = XFS_SEND_NAMESP(mp, DM_EVENT_REMOVE, dir_vp,
    -					DM_RIGHT_NULL, NULL, DM_RIGHT_NULL,
    -					name, NULL, 0, 0, 0);
    -		if (error)
    -			return error;
    -	}
    -
    -	/* From this point on, return through std_return */
    -	ip = NULL;
    -
    -	/*
    -	 * We need to get a reference to ip before we get our log
    -	 * reservation. The reason for this is that we cannot call
    -	 * xfs_iget for an inode for which we do not have a reference
    -	 * once we've acquired a log reservation. This is because the
    -	 * inode we are trying to get might be in xfs_inactive going
    -	 * for a log reservation. Since we'll have to wait for the
    -	 * inactive code to complete before returning from xfs_iget,
    -	 * we need to make sure that we don't have log space reserved
    -	 * when we call xfs_iget.  Instead we get an unlocked reference
    -	 * to the inode before getting our log reservation.
    -	 */
    -#ifdef RMC
    -	error = xfs_get_dir_entry(dentry, &ip);
    -#endif
    -	/* FreeBSD has already done the lookup */
    -	ip = xvp->v_inode;
    -	VN_HOLD(xvp);
    -
    -	if (error) {
    -		REMOVE_DEBUG_TRACE(__LINE__);
    -		goto std_return;
    -	}
    -
    -	dm_di_mode = ip->i_d.di_mode;
    -
    -	vn_trace_entry(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address);
    -
    -	ITRACE(ip);
    -
    -	error = XFS_QM_DQATTACH(mp, dp, 0);
    -	if (!error && dp != ip)
    -		error = XFS_QM_DQATTACH(mp, ip, 0);
    -	if (error) {
    -		REMOVE_DEBUG_TRACE(__LINE__);
    -		IRELE(ip);
    -		goto std_return;
    -	}
    -
    -	tp = xfs_trans_alloc(mp, XFS_TRANS_REMOVE);
    -	cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
    -	/*
    -	 * We try to get the real space reservation first,
    -	 * allowing for directory btree deletion(s) implying
    -	 * possible bmap insert(s).  If we can't get the space
    -	 * reservation then we use 0 instead, and avoid the bmap
    -	 * btree insert(s) in the directory code by, if the bmap
    -	 * insert tries to happen, instead trimming the LAST
    -	 * block from the directory.
    -	 */
    -	resblks = XFS_REMOVE_SPACE_RES(mp);
    -	error = xfs_trans_reserve(tp, resblks, XFS_REMOVE_LOG_RES(mp), 0,
    -			XFS_TRANS_PERM_LOG_RES, XFS_REMOVE_LOG_COUNT);
    -	if (error == ENOSPC) {
    -		resblks = 0;
    -		error = xfs_trans_reserve(tp, 0, XFS_REMOVE_LOG_RES(mp), 0,
    -				XFS_TRANS_PERM_LOG_RES, XFS_REMOVE_LOG_COUNT);
    -	}
    -	if (error) {
    -		ASSERT(error != ENOSPC);
    -		REMOVE_DEBUG_TRACE(__LINE__);
    -		xfs_trans_cancel(tp, 0);
    -		IRELE(ip);
    -		return error;
    -	}
    -
    -	error = xfs_lock_dir_and_entry(dp, dentry, ip);
    -	if (error) {
    -		REMOVE_DEBUG_TRACE(__LINE__);
    -		xfs_trans_cancel(tp, cancel_flags);
    -		IRELE(ip);
    -		goto std_return;
    -	}
    -
    -	/*
    -	 * At this point, we've gotten both the directory and the entry
    -	 * inodes locked.
    -	 */
    -	xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
    -	if (dp != ip) {
    -		/*
    -		 * Increment vnode ref count only in this case since
    -		 * there's an extra vnode reference in the case where
    -		 * dp == ip.
    -		 */
    -		IHOLD(dp);
    -		xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
    -	}
    -
    -	/*
    -	 * Entry must exist since we did a lookup in xfs_lock_dir_and_entry.
    -	 */
    -	XFS_BMAP_INIT(&free_list, &first_block);
    -	error = XFS_DIR_REMOVENAME(mp, tp, dp, name, namelen, ip->i_ino,
    -		&first_block, &free_list, 0);
    -	if (error) {
    -		ASSERT(error != ENOENT);
    -		REMOVE_DEBUG_TRACE(__LINE__);
    -		goto error1;
    -	}
    -	xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
    -
    -	dp->i_gen++;
    -	xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
    -
    -	error = xfs_droplink(tp, ip);
    -	if (error) {
    -		REMOVE_DEBUG_TRACE(__LINE__);
    -		goto error1;
    -	}
    -
    -	/* Determine if this is the last link while
    -	 * we are in the transaction.
    -	 */
    -	link_zero = (ip)->i_d.di_nlink==0;
    -
    -	/*
    -	 * Take an extra ref on the inode so that it doesn't
    -	 * go to xfs_inactive() from within the commit.
    -	 */
    -	IHOLD(ip);
    -
    -	/*
    -	 * If this is a synchronous mount, make sure that the
    -	 * remove transaction goes to disk before returning to
    -	 * the user.
    -	 */
    -	if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
    -		xfs_trans_set_sync(tp);
    -	}
    -
    -	error = xfs_bmap_finish(&tp, &free_list, first_block, &committed);
    -	if (error) {
    -		REMOVE_DEBUG_TRACE(__LINE__);
    -		goto error_rele;
    -	}
    -
    -	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
    -	if (error) {
    -		IRELE(ip);
    -		goto std_return;
    -	}
    -
    -	/*
    -	 * Before we drop our extra reference to the inode, purge it
    -	 * from the refcache if it is there.  By waiting until afterwards
    -	 * to do the IRELE, we ensure that we won't go inactive in the
    -	 * xfs_refcache_purge_ip routine (although that would be OK).
    -	 */
    -	xfs_refcache_purge_ip(ip);
    -
    -	vn_trace_exit(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address);
    -
    -	/*
    -	 * Let interposed file systems know about removed links.
    -	 */
    -	XVOP_LINK_REMOVED(XFS_ITOV(ip), dir_vp, link_zero);
    -
    -	IRELE(ip);
    -
    -/*	Fall through to std_return with error = 0 */
    - std_return:
    -	if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp,
    -						DM_EVENT_POSTREMOVE)) {
    -		(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE,
    -				dir_vp, DM_RIGHT_NULL,
    -				NULL, DM_RIGHT_NULL,
    -				name, NULL, dm_di_mode, error, 0);
    -	}
    -	return error;
    -
    - error1:
    -	xfs_bmap_cancel(&free_list);
    -	cancel_flags |= XFS_TRANS_ABORT;
    -	xfs_trans_cancel(tp, cancel_flags);
    -	goto std_return;
    -
    - error_rele:
    -	/*
    -	 * In this case make sure to not release the inode until after
    -	 * the current transaction is aborted.  Releasing it beforehand
    -	 * can cause us to go to xfs_inactive and start a recursive
    -	 * transaction which can easily deadlock with the current one.
    -	 */
    -	xfs_bmap_cancel(&free_list);
    -	cancel_flags |= XFS_TRANS_ABORT;
    -	xfs_trans_cancel(tp, cancel_flags);
    -
    -	/*
    -	 * Before we drop our extra reference to the inode, purge it
    -	 * from the refcache if it is there.  By waiting until afterwards
    -	 * to do the IRELE, we ensure that we won't go inactive in the
    -	 * xfs_refcache_purge_ip routine (although that would be OK).
    -	 */
    -	xfs_refcache_purge_ip(ip);
    -
    -	IRELE(ip);
    -
    -	goto std_return;
    -}
    -
    -
    -/*
    - * xfs_link
    - *
    - */
    -STATIC int
    -xfs_link(
    -	bhv_desc_t		*target_dir_bdp,
    -	xfs_vnode_t		*src_vp,
    -	vname_t			*dentry,
    -	cred_t			*credp)
    -{
    -	xfs_inode_t		*tdp, *sip;
    -	xfs_trans_t		*tp;
    -	xfs_mount_t		*mp;
    -	xfs_inode_t		*ips[2];
    -	int			error;
    -	xfs_bmap_free_t         free_list;
    -	xfs_fsblock_t           first_block;
    -	int			cancel_flags;
    -	int			committed;
    -	xfs_vnode_t		*target_dir_vp;
    -	int			resblks;
    -	char			*target_name = VNAME(dentry);
    -	int			target_namelen;
    -
    -	target_dir_vp = BHV_TO_VNODE(target_dir_bdp);
    -	vn_trace_entry(target_dir_vp, __FUNCTION__, (inst_t *)__return_address);
    -	vn_trace_entry(src_vp, __FUNCTION__, (inst_t *)__return_address);
    -
    -	target_namelen = VNAMELEN(dentry);
    -	if (VN_ISDIR(src_vp))
    -		return XFS_ERROR(EPERM);
    -
    -	sip = xfs_vtoi(src_vp);
    -	tdp = XFS_BHVTOI(target_dir_bdp);
    -	mp = tdp->i_mount;
    -	if (XFS_FORCED_SHUTDOWN(mp))
    -		return XFS_ERROR(EIO);
    -
    -	if (DM_EVENT_ENABLED(src_vp->v_vfsp, tdp, DM_EVENT_LINK)) {
    -		error = XFS_SEND_NAMESP(mp, DM_EVENT_LINK,
    -					target_dir_vp, DM_RIGHT_NULL,
    -					src_vp, DM_RIGHT_NULL,
    -					target_name, NULL, 0, 0, 0);
    -		if (error)
    -			return error;
    -	}
    -
    -	/* Return through std_return after this point. */
    -
    -	error = XFS_QM_DQATTACH(mp, sip, 0);
    -	if (!error && sip != tdp)
    -		error = XFS_QM_DQATTACH(mp, tdp, 0);
    -	if (error)
    -		goto std_return;
    -
    -	tp = xfs_trans_alloc(mp, XFS_TRANS_LINK);
    -	cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
    -	resblks = XFS_LINK_SPACE_RES(mp, target_namelen);
    -	error = xfs_trans_reserve(tp, resblks, XFS_LINK_LOG_RES(mp), 0,
    -			XFS_TRANS_PERM_LOG_RES, XFS_LINK_LOG_COUNT);
    -	if (error == ENOSPC) {
    -		resblks = 0;
    -		error = xfs_trans_reserve(tp, 0, XFS_LINK_LOG_RES(mp), 0,
    -				XFS_TRANS_PERM_LOG_RES, XFS_LINK_LOG_COUNT);
    -	}
    -	if (error) {
    -		cancel_flags = 0;
    -		goto error_return;
    -	}
    -
    -	if (sip->i_ino < tdp->i_ino) {
    -		ips[0] = sip;
    -		ips[1] = tdp;
    -	} else {
    -		ips[0] = tdp;
    -		ips[1] = sip;
    -	}
    -
    -	xfs_lock_inodes(ips, 2, 0, XFS_ILOCK_EXCL);
    -
    -	/*
    -	 * Increment vnode ref counts since xfs_trans_commit &
    -	 * xfs_trans_cancel will both unlock the inodes and
    -	 * decrement the associated ref counts.
    -	 */
    -	VN_HOLD(src_vp);
    -	VN_HOLD(target_dir_vp);
    -	xfs_trans_ijoin(tp, sip, XFS_ILOCK_EXCL);
    -	xfs_trans_ijoin(tp, tdp, XFS_ILOCK_EXCL);
    -
    -	/*
    -	 * If the source has too many links, we can't make any more to it.
    -	 */
    -	if (sip->i_d.di_nlink >= XFS_MAXLINK) {
    -		error = XFS_ERROR(EMLINK);
    -		goto error_return;
    -	}
    -
    -	/*
    -	 * If we are using project inheritance, we only allow hard link
    -	 * creation in our tree when the project IDs are the same; else
    -	 * the tree quota mechanism could be circumvented.
    -	 */
    -	if (unlikely((tdp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) &&
    -		     (tdp->i_d.di_projid != sip->i_d.di_projid))) {
    -		error = XFS_ERROR(EPERM);
    -		goto error_return;
    -	}
    -
    -	if (resblks == 0 &&
    -	    (error = XFS_DIR_CANENTER(mp, tp, tdp, target_name,
    -			target_namelen)))
    -		goto error_return;
    -
    -	XFS_BMAP_INIT(&free_list, &first_block);
    -
    -	error = XFS_DIR_CREATENAME(mp, tp, tdp, target_name, target_namelen,
    -				   sip->i_ino, &first_block, &free_list,
    -				   resblks);
    -	if (error)
    -		goto abort_return;
    -	xfs_ichgtime(tdp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
    -	tdp->i_gen++;
    -	xfs_trans_log_inode(tp, tdp, XFS_ILOG_CORE);
    -
    -	error = xfs_bumplink(tp, sip);
    -	if (error) {
    -		goto abort_return;
    -	}
    -
    -	/*
    -	 * If this is a synchronous mount, make sure that the
    -	 * link transaction goes to disk before returning to
    -	 * the user.
    -	 */
    -	if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
    -		xfs_trans_set_sync(tp);
    -	}
    -
    -	error = xfs_bmap_finish (&tp, &free_list, first_block, &committed);
    -	if (error) {
    -		xfs_bmap_cancel(&free_list);
    -		goto abort_return;
    -	}
    -
    -	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
    -	if (error) {
    -		goto std_return;
    -	}
    -
    -	/* Fall through to std_return with error = 0. */
    -std_return:
    -	if (DM_EVENT_ENABLED(src_vp->v_vfsp, sip,
    -						DM_EVENT_POSTLINK)) {
    -		(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTLINK,
    -				target_dir_vp, DM_RIGHT_NULL,
    -				src_vp, DM_RIGHT_NULL,
    -				target_name, NULL, 0, error, 0);
    -	}
    -	return error;
    -
    - abort_return:
    -	cancel_flags |= XFS_TRANS_ABORT;
    -	/* FALLTHROUGH */
    -
    - error_return:
    -	xfs_trans_cancel(tp, cancel_flags);
    -	goto std_return;
    -}
    -/*
    - * xfs_mkdir
    - *
    - */
    -STATIC int
    -xfs_mkdir(
    -	bhv_desc_t		*dir_bdp,
    -	vname_t			*dentry,
    -	xfs_vattr_t		*vap,
    -	xfs_vnode_t		**vpp,
    -	cred_t			*credp)
    -{
    -	char			*dir_name = VNAME(dentry);
    -	xfs_inode_t             *dp;
    -	xfs_inode_t		*cdp;	/* inode of created dir */
    -	xfs_vnode_t		*cvp;	/* vnode of created dir */
    -	xfs_trans_t		*tp;
    -	xfs_mount_t		*mp;
    -	int			cancel_flags;
    -	int			error;
    -	int			committed;
    -	xfs_bmap_free_t         free_list;
    -	xfs_fsblock_t           first_block;
    -	xfs_vnode_t		*dir_vp;
    -	boolean_t		dp_joined_to_trans;
    -	boolean_t		created = B_FALSE;
    -	int			dm_event_sent = 0;
    -	xfs_prid_t		prid;
    -	struct xfs_dquot	*udqp, *gdqp;
    -	uint			resblks;
    -	int			dm_di_mode;
    -	int			dir_namelen;
    -
    -	dir_vp = BHV_TO_VNODE(dir_bdp);
    -	dp = XFS_BHVTOI(dir_bdp);
    -	mp = dp->i_mount;
    -
    -	if (XFS_FORCED_SHUTDOWN(mp))
    -		return XFS_ERROR(EIO);
    -
    -	dir_namelen = VNAMELEN(dentry);
    -
    -	tp = NULL;
    -	dp_joined_to_trans = B_FALSE;
    -	dm_di_mode = vap->va_mode;
    -
    -	if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_CREATE)) {
    -		error = XFS_SEND_NAMESP(mp, DM_EVENT_CREATE,
    -					dir_vp, DM_RIGHT_NULL, NULL,
    -					DM_RIGHT_NULL, dir_name, NULL,
    -					dm_di_mode, 0, 0);
    -		if (error)
    -			return error;
    -		dm_event_sent = 1;
    -	}
    -
    -	/* Return through std_return after this point. */
    -
    -	vn_trace_entry(dir_vp, __FUNCTION__, (inst_t *)__return_address);
    -
    -	mp = dp->i_mount;
    -	udqp = gdqp = NULL;
    -
    -	if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
    -		prid = dp->i_d.di_projid;
    -	else if (vap->va_mask & XFS_AT_PROJID)
    -		prid = (xfs_prid_t)vap->va_projid;
    -	else
    -		prid = (xfs_prid_t)dfltprid;
    -
    -	/*
    -	 * Make sure that we have allocated dquot(s) on disk.
    -	 */
    -	error = XFS_QM_DQVOPALLOC(mp, dp,
    -			current_fsuid(credp), current_fsgid(credp), prid,
    -			XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp);
    -	if (error)
    -		goto std_return;
    -
    -	tp = xfs_trans_alloc(mp, XFS_TRANS_MKDIR);
    -	cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
    -	resblks = XFS_MKDIR_SPACE_RES(mp, dir_namelen);
    -	error = xfs_trans_reserve(tp, resblks, XFS_MKDIR_LOG_RES(mp), 0,
    -				  XFS_TRANS_PERM_LOG_RES, XFS_MKDIR_LOG_COUNT);
    -	if (error == ENOSPC) {
    -		resblks = 0;
    -		error = xfs_trans_reserve(tp, 0, XFS_MKDIR_LOG_RES(mp), 0,
    -					  XFS_TRANS_PERM_LOG_RES,
    -					  XFS_MKDIR_LOG_COUNT);
    -	}
    -	if (error) {
    -		cancel_flags = 0;
    -		dp = NULL;
    -		goto error_return;
    -	}
    -
    -	xfs_ilock(dp, XFS_ILOCK_EXCL);
    -
    -	/*
    -	 * Check for directory link count overflow.
    -	 */
    -	if (dp->i_d.di_nlink >= XFS_MAXLINK) {
    -		error = XFS_ERROR(EMLINK);
    -		goto error_return;
    -	}
    -
    -	/*
    -	 * Reserve disk quota and the inode.
    -	 */
    -	error = XFS_TRANS_RESERVE_QUOTA(mp, tp, udqp, gdqp, resblks, 1, 0);
    -	if (error)
    -		goto error_return;
    -
    -	if (resblks == 0 &&
    -	    (error = XFS_DIR_CANENTER(mp, tp, dp, dir_name, dir_namelen)))
    -		goto error_return;
    -	/*
    -	 * create the directory inode.
    -	 */
    -	error = xfs_dir_ialloc(&tp, dp, vap->va_mode, 2,
    -			0, credp, prid, resblks > 0,
    -		&cdp, NULL);
    -	if (error) {
    -		if (error == ENOSPC)
    -			goto error_return;
    -		goto abort_return;
    -	}
    -	ITRACE(cdp);
    -
    -	/*
    -	 * Now we add the directory inode to the transaction.
    -	 * We waited until now since xfs_dir_ialloc might start
    -	 * a new transaction.  Had we joined the transaction
    -	 * earlier, the locks might have gotten released.
    -	 */
    -	VN_HOLD(dir_vp);
    -	xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
    -	dp_joined_to_trans = B_TRUE;
    -
    -	XFS_BMAP_INIT(&free_list, &first_block);
    -
    -	error = XFS_DIR_CREATENAME(mp, tp, dp, dir_name, dir_namelen,
    -			cdp->i_ino, &first_block, &free_list,
    -			resblks ? resblks - XFS_IALLOC_SPACE_RES(mp) : 0);
    -	if (error) {
    -		ASSERT(error != ENOSPC);
    -		goto error1;
    -	}
    -	xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
    -
    -	/*
    -	 * Bump the in memory version number of the parent directory
    -	 * so that other processes accessing it will recognize that
    -	 * the directory has changed.
    -	 */
    -	dp->i_gen++;
    -
    -	error = XFS_DIR_INIT(mp, tp, cdp, dp);
    -	if (error) {
    -		goto error2;
    -	}
    -
    -	cdp->i_gen = 1;
    -	error = xfs_bumplink(tp, dp);
    -	if (error) {
    -		goto error2;
    -	}
    -
    -	cvp = XFS_ITOV(cdp);
    -
    -	created = B_TRUE;
    -
    -	*vpp = cvp;
    -	IHOLD(cdp);
    -
    -	/*
    -	 * Attach the dquots to the new inode and modify the icount incore.
    -	 */
    -	XFS_QM_DQVOPCREATE(mp, tp, cdp, udqp, gdqp);
    -
    -	/*
    -	 * If this is a synchronous mount, make sure that the
    -	 * mkdir transaction goes to disk before returning to
    -	 * the user.
    -	 */
    -	if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
    -		xfs_trans_set_sync(tp);
    -	}
    -
    -	error = xfs_bmap_finish(&tp, &free_list, first_block, &committed);
    -	if (error) {
    -		IRELE(cdp);
    -		goto error2;
    -	}
    -
    -	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
    -	XFS_QM_DQRELE(mp, udqp);
    -	XFS_QM_DQRELE(mp, gdqp);
    -	if (error) {
    -		IRELE(cdp);
    -	}
    -
    -	/* Fall through to std_return with error = 0 or errno from
    -	 * xfs_trans_commit. */
    -
    -std_return:
    -	if ( (created || (error != 0 && dm_event_sent != 0)) &&
    -			DM_EVENT_ENABLED(dir_vp->v_vfsp, XFS_BHVTOI(dir_bdp),
    -						DM_EVENT_POSTCREATE)) {
    -		(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTCREATE,
    -					dir_vp, DM_RIGHT_NULL,
    -					created ? XFS_ITOV(cdp):NULL,
    -					DM_RIGHT_NULL,
    -					dir_name, NULL,
    -					dm_di_mode, error, 0);
    -	}
    -	return error;
    -
    - error2:
    - error1:
    -	xfs_bmap_cancel(&free_list);
    - abort_return:
    -	cancel_flags |= XFS_TRANS_ABORT;
    - error_return:
    -	xfs_trans_cancel(tp, cancel_flags);
    -	XFS_QM_DQRELE(mp, udqp);
    -	XFS_QM_DQRELE(mp, gdqp);
    -
    -	if (!dp_joined_to_trans && (dp != NULL)) {
    -		xfs_iunlock(dp, XFS_ILOCK_EXCL);
    -	}
    -
    -	goto std_return;
    -}
    -
    -
    -/*
    - * xfs_rmdir
    - *
    - */
    -STATIC int
    -xfs_rmdir(
    -	bhv_desc_t		*dir_bdp,
    -	vname_t			*dentry,
    -	cred_t			*credp)
    -{
    -	char			*name = VNAME(dentry);
    -	xfs_inode_t             *dp;
    -	xfs_inode_t             *cdp;   /* child directory */
    -	xfs_trans_t             *tp;
    -	xfs_mount_t		*mp;
    -	int                     error;
    -	xfs_bmap_free_t         free_list;
    -	xfs_fsblock_t           first_block;
    -	int			cancel_flags;
    -	int			committed;
    -	xfs_vnode_t		*dir_vp;
    -	int			dm_di_mode = 0;
    -	int			last_cdp_link;
    -	int			namelen;
    -	uint			resblks;
    -
    -	dir_vp = BHV_TO_VNODE(dir_bdp);
    -	dp = XFS_BHVTOI(dir_bdp);
    -	mp = dp->i_mount;
    -
    -	vn_trace_entry(dir_vp, __FUNCTION__, (inst_t *)__return_address);
    -
    -	if (XFS_FORCED_SHUTDOWN(XFS_BHVTOI(dir_bdp)->i_mount))
    -		return XFS_ERROR(EIO);
    -	namelen = VNAMELEN(dentry);
    -
    -	if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_REMOVE)) {
    -		error = XFS_SEND_NAMESP(mp, DM_EVENT_REMOVE,
    -					dir_vp, DM_RIGHT_NULL,
    -					NULL, DM_RIGHT_NULL,
    -					name, NULL, 0, 0, 0);
    -		if (error)
    -			return XFS_ERROR(error);
    -	}
    -
    -	/* Return through std_return after this point. */
    -
    -	cdp = NULL;
    -
    -	/*
    -	 * We need to get a reference to cdp before we get our log
    -	 * reservation.  The reason for this is that we cannot call
    -	 * xfs_iget for an inode for which we do not have a reference
    -	 * once we've acquired a log reservation.  This is because the
    -	 * inode we are trying to get might be in xfs_inactive going
    -	 * for a log reservation.  Since we'll have to wait for the
    -	 * inactive code to complete before returning from xfs_iget,
    -	 * we need to make sure that we don't have log space reserved
    -	 * when we call xfs_iget.  Instead we get an unlocked reference
    -	 * to the inode before getting our log reservation.
    -	 */
    -	error = xfs_get_dir_entry(dentry, &cdp);
    -	if (error) {
    -		REMOVE_DEBUG_TRACE(__LINE__);
    -		goto std_return;
    -	}
    -	mp = dp->i_mount;
    -	dm_di_mode = cdp->i_d.di_mode;
    -
    -	/*
    -	 * Get the dquots for the inodes.
    -	 */
    -	error = XFS_QM_DQATTACH(mp, dp, 0);
    -	if (!error && dp != cdp)
    -		error = XFS_QM_DQATTACH(mp, cdp, 0);
    -	if (error) {
    -		IRELE(cdp);
    -		REMOVE_DEBUG_TRACE(__LINE__);
    -		goto std_return;
    -	}
    -
    -	tp = xfs_trans_alloc(mp, XFS_TRANS_RMDIR);
    -	cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
    -	/*
    -	 * We try to get the real space reservation first,
    -	 * allowing for directory btree deletion(s) implying
    -	 * possible bmap insert(s).  If we can't get the space
    -	 * reservation then we use 0 instead, and avoid the bmap
    -	 * btree insert(s) in the directory code by, if the bmap
    -	 * insert tries to happen, instead trimming the LAST
    -	 * block from the directory.
    -	 */
    -	resblks = XFS_REMOVE_SPACE_RES(mp);
    -	error = xfs_trans_reserve(tp, resblks, XFS_REMOVE_LOG_RES(mp), 0,
    -			XFS_TRANS_PERM_LOG_RES, XFS_DEFAULT_LOG_COUNT);
    -	if (error == ENOSPC) {
    -		resblks = 0;
    -		error = xfs_trans_reserve(tp, 0, XFS_REMOVE_LOG_RES(mp), 0,
    -				XFS_TRANS_PERM_LOG_RES, XFS_DEFAULT_LOG_COUNT);
    -	}
    -	if (error) {
    -		ASSERT(error != ENOSPC);
    -		cancel_flags = 0;
    -		IRELE(cdp);
    -		goto error_return;
    -	}
    -	XFS_BMAP_INIT(&free_list, &first_block);
    -
    -	/*
    -	 * Now lock the child directory inode and the parent directory
    -	 * inode in the proper order.  This will take care of validating
    -	 * that the directory entry for the child directory inode has
    -	 * not changed while we were obtaining a log reservation.
    -	 */
    -	error = xfs_lock_dir_and_entry(dp, dentry, cdp);
    -	if (error) {
    -		xfs_trans_cancel(tp, cancel_flags);
    -		IRELE(cdp);
    -		goto std_return;
    -	}
    -
    -	xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
    -	if (dp != cdp) {
    -		/*
    -		 * Only increment the parent directory vnode count if
    -		 * we didn't bump it in looking up cdp.  The only time
    -		 * we don't bump it is when we're looking up ".".
    -		 */
    -		VN_HOLD(dir_vp);
    -	}
    -
    -	ITRACE(cdp);
    -	xfs_trans_ijoin(tp, cdp, XFS_ILOCK_EXCL);
    -
    -	ASSERT(cdp->i_d.di_nlink >= 2);
    -	if (cdp->i_d.di_nlink != 2) {
    -		error = XFS_ERROR(ENOTEMPTY);
    -		goto error_return;
    -	}
    -	if (!XFS_DIR_ISEMPTY(mp, cdp)) {
    -		error = XFS_ERROR(ENOTEMPTY);
    -		goto error_return;
    -	}
    -
    -	error = XFS_DIR_REMOVENAME(mp, tp, dp, name, namelen, cdp->i_ino,
    -		&first_block, &free_list, resblks);
    -	if (error) {
    -		goto error1;
    -	}
    -
    -	xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
    -
    -	/*
    -	 * Bump the in memory generation count on the parent
    -	 * directory so that other can know that it has changed.
    -	 */
    -	dp->i_gen++;
    -
    -	/*
    -	 * Drop the link from cdp's "..".
    -	 */
    -	error = xfs_droplink(tp, dp);
    -	if (error) {
    -		goto error1;
    -	}
    -
    -	/*
    -	 * Drop the link from dp to cdp.
    -	 */
    -	error = xfs_droplink(tp, cdp);
    -	if (error) {
    -		goto error1;
    -	}
    -
    -	/*
    -	 * Drop the "." link from cdp to self.
    -	 */
    -	error = xfs_droplink(tp, cdp);
    -	if (error) {
    -		goto error1;
    -	}
    -
    -	/* Determine these before committing transaction */
    -	last_cdp_link = (cdp)->i_d.di_nlink==0;
    -
    -	/*
    -	 * Take an extra ref on the child vnode so that it
    -	 * does not go to xfs_inactive() from within the commit.
    -	 */
    -	IHOLD(cdp);
    -
    -	/*
    -	 * If this is a synchronous mount, make sure that the
    -	 * rmdir transaction goes to disk before returning to
    -	 * the user.
    -	 */
    -	if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
    -		xfs_trans_set_sync(tp);
    -	}
    -
    -	error = xfs_bmap_finish (&tp, &free_list, first_block, &committed);
    -	if (error) {
    -		xfs_bmap_cancel(&free_list);
    -		xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES |
    -				 XFS_TRANS_ABORT));
    -		IRELE(cdp);
    -		goto std_return;
    -	}
    -
    -	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
    -	if (error) {
    -		IRELE(cdp);
    -		goto std_return;
    -	}
    -
    -
    -	/*
    -	 * Let interposed file systems know about removed links.
    -	 */
    -	XVOP_LINK_REMOVED(XFS_ITOV(cdp), dir_vp, last_cdp_link);
    -
    -	IRELE(cdp);
    -
    -	/* Fall through to std_return with error = 0 or the errno
    -	 * from xfs_trans_commit. */
    - std_return:
    -	if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_POSTREMOVE)) {
    -		(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE,
    -					dir_vp, DM_RIGHT_NULL,
    -					NULL, DM_RIGHT_NULL,
    -					name, NULL, dm_di_mode,
    -					error, 0);
    -	}
    -	return error;
    -
    - error1:
    -	xfs_bmap_cancel(&free_list);
    -	cancel_flags |= XFS_TRANS_ABORT;
    -	/* FALLTHROUGH */
    -
    - error_return:
    -	xfs_trans_cancel(tp, cancel_flags);
    -	goto std_return;
    -}
    -
    -
    -/*
    - * xfs_readdir
    - *
    - * Read dp's entries starting at uiop->uio_offset and translate them into
    - * bufsize bytes worth of struct dirents starting at bufbase.
    - */
    -STATIC int
    -xfs_readdir(
    -	bhv_desc_t	*dir_bdp,
    -	uio_t		*uiop,
    -	cred_t		*credp,
    -	int		*eofp)
    -{
    -	xfs_inode_t	*dp;
    -	xfs_trans_t	*tp = NULL;
    -	int		error = 0;
    -	uint		lock_mode;
    -
    -	vn_trace_entry(BHV_TO_VNODE(dir_bdp), __FUNCTION__,
    -					       (inst_t *)__return_address);
    -	dp = XFS_BHVTOI(dir_bdp);
    -
    -	if (XFS_FORCED_SHUTDOWN(dp->i_mount)) {
    -		return XFS_ERROR(EIO);
    -	}
    -
    -	lock_mode = xfs_ilock_map_shared(dp);
    -	error = XFS_DIR_GETDENTS(dp->i_mount, tp, dp, uiop, eofp);
    -	xfs_iunlock_map_shared(dp, lock_mode);
    -	return error;
    -}
    -
    -
    -/*
    - * xfs_symlink
    - *
    - */
    -STATIC int
    -xfs_symlink(
    -	bhv_desc_t		*dir_bdp,
    -	vname_t			*dentry,
    -	xfs_vattr_t		*vap,
    -	char			*target_path,
    -	xfs_vnode_t		**vpp,
    -	cred_t			*credp)
    -{
    -	xfs_trans_t		*tp;
    -	xfs_mount_t		*mp;
    -	xfs_inode_t		*dp;
    -	xfs_inode_t		*ip;
    -	int			error;
    -	int			pathlen;
    -	xfs_bmap_free_t		free_list;
    -	xfs_fsblock_t		first_block;
    -	boolean_t		dp_joined_to_trans;
    -	xfs_vnode_t		*dir_vp;
    -	uint			cancel_flags;
    -	int			committed;
    -	xfs_fileoff_t		first_fsb;
    -	xfs_filblks_t		fs_blocks;
    -	int			nmaps;
    -	xfs_bmbt_irec_t		mval[SYMLINK_MAPS];
    -	xfs_daddr_t		d;
    -	char			*cur_chunk;
    -	int			byte_cnt;
    -	int			n;
    -	xfs_buf_t		*bp;
    -	xfs_prid_t		prid;
    -	struct xfs_dquot	*udqp, *gdqp;
    -	uint			resblks;
    -	char			*link_name = VNAME(dentry);
    -	int			link_namelen;
    -	struct	thread 		*current = curthread;
    -
    -	*vpp = NULL;
    -	dir_vp = BHV_TO_VNODE(dir_bdp);
    -	dp = XFS_BHVTOI(dir_bdp);
    -	dp_joined_to_trans = B_FALSE;
    -	error = 0;
    -	ip = NULL;
    -	tp = NULL;
    -
    -	vn_trace_entry(dir_vp, __FUNCTION__, (inst_t *)__return_address);
    -
    -	mp = dp->i_mount;
    -
    -	if (XFS_FORCED_SHUTDOWN(mp))
    -		return XFS_ERROR(EIO);
    -
    -	link_namelen = VNAMELEN(dentry);
    -
    -	/*
    -	 * Check component lengths of the target path name.
    -	 */
    -	pathlen = strlen(target_path);
    -	if (pathlen >= MAXPATHLEN)      /* total string too long */
    -		return XFS_ERROR(ENAMETOOLONG);
    -	if (pathlen >= MAXNAMELEN) {    /* is any component too long? */
    -		int len, total;
    -		char *path;
    -
    -		for(total = 0, path = target_path; total < pathlen;) {
    -			/*
    -			 * Skip any slashes.
    -			 */
    -			while(*path == '/') {
    -				total++;
    -				path++;
    -			}
    -
    -			/*
    -			 * Count up to the next slash or end of path.
    -			 * Error out if the component is bigger than MAXNAMELEN.
    -			 */
    -			for(len = 0; *path != '/' && total < pathlen;total++, path++) {
    -				if (++len >= MAXNAMELEN) {
    -					error = ENAMETOOLONG;
    -					return error;
    -				}
    -			}
    -		}
    -	}
    -
    -	if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_SYMLINK)) {
    -		error = XFS_SEND_NAMESP(mp, DM_EVENT_SYMLINK, dir_vp,
    -					DM_RIGHT_NULL, NULL, DM_RIGHT_NULL,
    -					link_name, target_path, 0, 0, 0);
    -		if (error)
    -			return error;
    -	}
    -
    -	/* Return through std_return after this point. */
    -
    -	udqp = gdqp = NULL;
    -
    -#ifdef XXXKAN
    -	if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
    -		prid = dp->i_d.di_projid;
    -	else if (vap->va_mask & XFS_AT_PROJID)
    -		prid = (xfs_prid_t)vap->va_projid;
    -	else
    -#endif
    -		prid = (xfs_prid_t)dfltprid;
    -
    -	/*
    -	 * Make sure that we have allocated dquot(s) on disk.
    -	 */
    -	error = XFS_QM_DQVOPALLOC(mp, dp,
    -				  current->td_ucred->cr_uid,
    -				  current->td_ucred->cr_groups[0],
    -				  prid,
    -				  XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp);
    -	if (error)
    -		goto std_return;
    -
    -	tp = xfs_trans_alloc(mp, XFS_TRANS_SYMLINK);
    -	cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
    -	/*
    -	 * The symlink will fit into the inode data fork?
    -	 * There can't be any attributes so we get the whole variable part.
    -	 */
    -	if (pathlen <= XFS_LITINO(mp))
    -		fs_blocks = 0;
    -	else
    -		fs_blocks = XFS_B_TO_FSB(mp, pathlen);
    -	resblks = XFS_SYMLINK_SPACE_RES(mp, link_namelen, fs_blocks);
    -	error = xfs_trans_reserve(tp, resblks, XFS_SYMLINK_LOG_RES(mp), 0,
    -			XFS_TRANS_PERM_LOG_RES, XFS_SYMLINK_LOG_COUNT);
    -	if (error == ENOSPC && fs_blocks == 0) {
    -		resblks = 0;
    -		error = xfs_trans_reserve(tp, 0, XFS_SYMLINK_LOG_RES(mp), 0,
    -				XFS_TRANS_PERM_LOG_RES, XFS_SYMLINK_LOG_COUNT);
    -	}
    -	if (error) {
    -		cancel_flags = 0;
    -		dp = NULL;
    -		goto error_return;
    -	}
    -
    -	xfs_ilock(dp, XFS_ILOCK_EXCL);
    -
    -	/*
    -	 * Check whether the directory allows new symlinks or not.
    -	 */
    -	if (dp->i_d.di_flags & XFS_DIFLAG_NOSYMLINKS) {
    -		error = XFS_ERROR(EPERM);
    -		goto error_return;
    -	}
    -
    -	/*
    -	 * Reserve disk quota : blocks and inode.
    -	 */
    -	error = XFS_TRANS_RESERVE_QUOTA(mp, tp, udqp, gdqp, resblks, 1, 0);
    -	if (error)
    -		goto error_return;
    -
    -	/*
    -	 * Check for ability to enter directory entry, if no space reserved.
    -	 */
    -	if (resblks == 0 &&
    -	    (error = XFS_DIR_CANENTER(mp, tp, dp, link_name, link_namelen)))
    -		goto error_return;
    -	/*
    -	 * Initialize the bmap freelist prior to calling either
    -	 * bmapi or the directory create code.
    -	 */
    -	XFS_BMAP_INIT(&free_list, &first_block);
    -
    -	/*
    -	 * Allocate an inode for the symlink.
    -	 */
    -	error = xfs_dir_ialloc(&tp, dp, S_IFLNK | (vap->va_mode&~S_IFMT),
    -			       1, 0, credp, prid, resblks > 0, &ip, NULL);
    -	if (error) {
    -		if (error == ENOSPC)
    -			goto error_return;
    -		goto error1;
    -	}
    -	ITRACE(ip);
    -
    -	VN_HOLD(dir_vp);
    -	xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
    -	dp_joined_to_trans = B_TRUE;
    -
    -	/*
    -	 * Also attach the dquot(s) to it, if applicable.
    -	 */
    -	XFS_QM_DQVOPCREATE(mp, tp, ip, udqp, gdqp);
    -
    -	if (resblks)
    -		resblks -= XFS_IALLOC_SPACE_RES(mp);
    -	/*
    -	 * If the symlink will fit into the inode, write it inline.
    -	 */
    -	if (pathlen <= XFS_IFORK_DSIZE(ip)) {
    -		xfs_idata_realloc(ip, pathlen, XFS_DATA_FORK);
    -		memcpy(ip->i_df.if_u1.if_data, target_path, pathlen);
    -		ip->i_d.di_size = pathlen;
    -
    -		/*
    -		 * The inode was initially created in extent format.
    -		 */
    -		ip->i_df.if_flags &= ~(XFS_IFEXTENTS | XFS_IFBROOT);
    -		ip->i_df.if_flags |= XFS_IFINLINE;
    -
    -		ip->i_d.di_format = XFS_DINODE_FMT_LOCAL;
    -		xfs_trans_log_inode(tp, ip, XFS_ILOG_DDATA | XFS_ILOG_CORE);
    -
    -	} else {
    -		first_fsb = 0;
    -		nmaps = SYMLINK_MAPS;
    -
    -		error = xfs_bmapi(tp, ip, first_fsb, fs_blocks,
    -				  XFS_BMAPI_WRITE | XFS_BMAPI_METADATA,
    -				  &first_block, resblks, mval, &nmaps,
    -				  &free_list, NULL);
    -		if (error) {
    -			goto error1;
    -		}
    -
    -		if (resblks)
    -			resblks -= fs_blocks;
    -		ip->i_d.di_size = pathlen;
    -		xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
    -
    -		cur_chunk = target_path;
    -		for (n = 0; n < nmaps; n++) {
    -			d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
    -			byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
    -			bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
    -					       BTOBB(byte_cnt), 0);
    -			ASSERT(bp && !XFS_BUF_GETERROR(bp));
    -			if (pathlen < byte_cnt) {
    -				byte_cnt = pathlen;
    -			}
    -			pathlen -= byte_cnt;
    -
    -			memcpy(XFS_BUF_PTR(bp), cur_chunk, byte_cnt);
    -			cur_chunk += byte_cnt;
    -
    -			xfs_trans_log_buf(tp, bp, 0, byte_cnt - 1);
    -		}
    -	}
    -
    -	/*
    -	 * Create the directory entry for the symlink.
    -	 */
    -	error = XFS_DIR_CREATENAME(mp, tp, dp, link_name, link_namelen,
    -			ip->i_ino, &first_block, &free_list, resblks);
    -	if (error) {
    -		goto error1;
    -	}
    -	xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
    -	xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
    -
    -	/*
    -	 * Bump the in memory version number of the parent directory
    -	 * so that other processes accessing it will recognize that
    -	 * the directory has changed.
    -	 */
    -	dp->i_gen++;
    -
    -	/*
    -	 * If this is a synchronous mount, make sure that the
    -	 * symlink transaction goes to disk before returning to
    -	 * the user.
    -	 */
    -	if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
    -		xfs_trans_set_sync(tp);
    -	}
    -
    -	/*
    -	 * xfs_trans_commit normally decrements the vnode ref count
    -	 * when it unlocks the inode. Since we want to return the
    -	 * vnode to the caller, we bump the vnode ref count now.
    -	 */
    -	IHOLD(ip);
    -
    -	error = xfs_bmap_finish(&tp, &free_list, first_block, &committed);
    -	if (error) {
    -		goto error2;
    -	}
    -	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
    -	XFS_QM_DQRELE(mp, udqp);
    -	XFS_QM_DQRELE(mp, gdqp);
    -
    -	/* Fall through to std_return with error = 0 or errno from
    -	 * xfs_trans_commit	*/
    -std_return:
    -	if (DM_EVENT_ENABLED(dir_vp->v_vfsp, XFS_BHVTOI(dir_bdp),
    -			     DM_EVENT_POSTSYMLINK)) {
    -		(void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTSYMLINK,
    -					dir_vp, DM_RIGHT_NULL,
    -					error ? NULL : XFS_ITOV(ip),
    -					DM_RIGHT_NULL, link_name, target_path,
    -					0, error, 0);
    -	}
    -
    -	if (!error) {
    -		xfs_vnode_t *vp;
    -
    -		ASSERT(ip);
    -		vp = XFS_ITOV(ip);
    -		*vpp = vp;
    -	}
    -	return error;
    -
    - error2:
    -	IRELE(ip);
    - error1:
    -	xfs_bmap_cancel(&free_list);
    -	cancel_flags |= XFS_TRANS_ABORT;
    - error_return:
    -	xfs_trans_cancel(tp, cancel_flags);
    -	XFS_QM_DQRELE(mp, udqp);
    -	XFS_QM_DQRELE(mp, gdqp);
    -
    -	if (!dp_joined_to_trans && (dp != NULL)) {
    -		xfs_iunlock(dp, XFS_ILOCK_EXCL);
    -	}
    -
    -	goto std_return;
    -}
    -
    -
    -/*
    - * xfs_fid2
    - *
    - * A fid routine that takes a pointer to a previously allocated
    - * fid structure (like xfs_fast_fid) but uses a 64 bit inode number.
    - */
    -STATIC int
    -xfs_fid2(
    -	bhv_desc_t	*bdp,
    -	fid_t		*fidp)
    -{
    -	xfs_inode_t	*ip;
    -	xfs_fid2_t	*xfid;
    -
    -	vn_trace_entry(BHV_TO_VNODE(bdp), __FUNCTION__,
    -				       (inst_t *)__return_address);
    -	ASSERT(sizeof(xfs_fid_t) >= sizeof(xfs_fid2_t));
    -
    -	xfid = (xfs_fid2_t *)fidp;
    -	ip = XFS_BHVTOI(bdp);
    -	xfid->fid_len = sizeof(xfs_fid2_t) - sizeof(xfid->fid_len);
    -	xfid->fid_pad = 0;
    -	/*
    -	 * use memcpy because the inode is a long long and there's no
    -	 * assurance that xfid->fid_ino is properly aligned.
    -	 */
    -	memcpy(&xfid->fid_ino, &ip->i_ino, sizeof(xfid->fid_ino));
    -	xfid->fid_gen = ip->i_d.di_gen;
    -
    -	return 0;
    -}
    -
    -
    -/*
    - * xfs_rwlock
    - */
    -int
    -xfs_rwlock(
    -	bhv_desc_t	*bdp,
    -	vrwlock_t	locktype)
    -{
    -	xfs_inode_t	*ip;
    -	xfs_vnode_t	*vp;
    -
    -	vp = BHV_TO_VNODE(bdp);
    -	if (VN_ISDIR(vp))
    -		return 1;
    -	ip = XFS_BHVTOI(bdp);
    -	if (locktype == VRWLOCK_WRITE) {
    -		xfs_ilock(ip, XFS_IOLOCK_EXCL);
    -	} else if (locktype == VRWLOCK_TRY_READ) {
    -		return xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED);
    -	} else if (locktype == VRWLOCK_TRY_WRITE) {
    -		return xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL);
    -	} else {
    -		ASSERT((locktype == VRWLOCK_READ) ||
    -		       (locktype == VRWLOCK_WRITE_DIRECT));
    -		xfs_ilock(ip, XFS_IOLOCK_SHARED);
    -	}
    -
    -	return 1;
    -}
    -
    -
    -/*
    - * xfs_rwunlock
    - */
    -void
    -xfs_rwunlock(
    -	bhv_desc_t	*bdp,
    -	vrwlock_t	locktype)
    -{
    -	xfs_inode_t     *ip;
    -	xfs_vnode_t	*vp;
    -
    -	vp = BHV_TO_VNODE(bdp);
    -	if (VN_ISDIR(vp))
    -		return;
    -	ip = XFS_BHVTOI(bdp);
    -	if (locktype == VRWLOCK_WRITE) {
    -		/*
    -		 * In the write case, we may have added a new entry to
    -		 * the reference cache.  This might store a pointer to
    -		 * an inode to be released in this inode.  If it is there,
    -		 * clear the pointer and release the inode after unlocking
    -		 * this one.
    -		 */
    -		xfs_refcache_iunlock(ip, XFS_IOLOCK_EXCL);
    -	} else {
    -		ASSERT((locktype == VRWLOCK_READ) ||
    -		       (locktype == VRWLOCK_WRITE_DIRECT));
    -		xfs_iunlock(ip, XFS_IOLOCK_SHARED);
    -	}
    -	return;
    -}
    -
    -STATIC int
    -xfs_inode_flush(
    -	bhv_desc_t	*bdp,
    -	int		flags)
    -{
    -	xfs_inode_t	*ip;
    -	xfs_mount_t	*mp;
    -	xfs_inode_log_item_t *iip;
    -	int		error = 0;
    -
    -	ip = XFS_BHVTOI(bdp);
    -	mp = ip->i_mount;
    -	iip = ip->i_itemp;
    -
    -	if (XFS_FORCED_SHUTDOWN(mp))
    -		return XFS_ERROR(EIO);
    -
    -	/*
    -	 * Bypass inodes which have already been cleaned by
    -	 * the inode flush clustering code inside xfs_iflush
    -	 */
    -	if ((ip->i_update_core == 0) &&
    -	    ((iip == NULL) || !(iip->ili_format.ilf_fields & XFS_ILOG_ALL)))
    -		return 0;
    -
    -	if (flags & FLUSH_LOG) {
    -		if (iip && iip->ili_last_lsn) {
    -			xlog_t		*log = mp->m_log;
    -			xfs_lsn_t	sync_lsn;
    -			int		s, log_flags = XFS_LOG_FORCE;
    -
    -			s = GRANT_LOCK(log);
    -			sync_lsn = log->l_last_sync_lsn;
    -			GRANT_UNLOCK(log, s);
    -
    -			if ((XFS_LSN_CMP(iip->ili_last_lsn, sync_lsn) <= 0))
    -				return 0;
    -
    -			if (flags & FLUSH_SYNC)
    -				log_flags |= XFS_LOG_SYNC;
    -			return xfs_log_force(mp, iip->ili_last_lsn, log_flags);
    -		}
    -	}
    -
    -	/*
    -	 * We make this non-blocking if the inode is contended,
    -	 * return EAGAIN to indicate to the caller that they
    -	 * did not succeed. This prevents the flush path from
    -	 * blocking on inodes inside another operation right
    -	 * now, they get caught later by xfs_sync.
    -	 */
    -	if (flags & FLUSH_INODE) {
    -		int	flush_flags;
    -
    -		if (xfs_ipincount(ip))
    -			return EAGAIN;
    -
    -		if (flags & FLUSH_SYNC) {
    -			xfs_ilock(ip, XFS_ILOCK_SHARED);
    -			xfs_iflock(ip);
    -		} else if (xfs_ilock_nowait(ip, XFS_ILOCK_SHARED)) {
    -			if (xfs_ipincount(ip) || !xfs_iflock_nowait(ip)) {
    -				xfs_iunlock(ip, XFS_ILOCK_SHARED);
    -				return EAGAIN;
    -			}
    -		} else {
    -			return EAGAIN;
    -		}
    -
    -		if (flags & FLUSH_SYNC)
    -			flush_flags = XFS_IFLUSH_SYNC;
    -		else
    -			flush_flags = XFS_IFLUSH_ASYNC;
    -
    -		error = xfs_iflush(ip, flush_flags);
    -		xfs_iunlock(ip, XFS_ILOCK_SHARED);
    -	}
    -
    -	return error;
    -}
    -
    -
    -int
    -xfs_set_dmattrs (
    -	bhv_desc_t	*bdp,
    -	u_int		evmask,
    -	u_int16_t	state,
    -	cred_t		*credp)
    -{
    -	xfs_inode_t     *ip;
    -	xfs_trans_t	*tp;
    -	xfs_mount_t	*mp;
    -	int		error;
    -
    -	if (!capable(CAP_SYS_ADMIN))
    -		return XFS_ERROR(EPERM);
    -
    -	ip = XFS_BHVTOI(bdp);
    -	mp = ip->i_mount;
    -
    -	if (XFS_FORCED_SHUTDOWN(mp))
    -		return XFS_ERROR(EIO);
    -
    -	tp = xfs_trans_alloc(mp, XFS_TRANS_SET_DMATTRS);
    -	error = xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES (mp), 0, 0, 0);
    -	if (error) {
    -		xfs_trans_cancel(tp, 0);
    -		return error;
    -	}
    -	xfs_ilock(ip, XFS_ILOCK_EXCL);
    -	xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
    -
    -	ip->i_iocore.io_dmevmask = ip->i_d.di_dmevmask = evmask;
    -	ip->i_iocore.io_dmstate  = ip->i_d.di_dmstate  = state;
    -
    -	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
    -	IHOLD(ip);
    -	error = xfs_trans_commit(tp, 0, NULL);
    -
    -	return error;
    -}
    -
    -
    -/*
    - * xfs_reclaim
    - */
    -STATIC int
    -xfs_reclaim(
    -	bhv_desc_t	*bdp)
    -{
    -	xfs_inode_t	*ip;
    -	xfs_vnode_t	*vp;
    -
    -	vp = BHV_TO_VNODE(bdp);
    -	ip = XFS_BHVTOI(bdp);
    -
    -	vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
    -
    -	ASSERT(!VN_MAPPED(vp));
    -
    -	/* bad inode, get out here ASAP */
    -	if (VN_BAD(vp)) {
    -		xfs_ireclaim(ip);
    -		return 0;
    -	}
    -
    -	vn_iowait(vp);
    -
    -	ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0);
    -
    -	/*
    -	 * Make sure the atime in the XFS inode is correct before freeing the
    -	 * Linux inode.
    -	 */
    -	xfs_synchronize_atime(ip);
    -
    -	vnode_destroy_vobject(vp->v_vnode);
    -
    -	/* If we have nothing to flush with this inode then complete the
    -	 * teardown now, otherwise break the link between the xfs inode
    -	 * and the linux inode and clean up the xfs inode later. This
    -	 * avoids flushing the inode to disk during the delete operation
    -	 * itself.
    -	 */
    -	if (!ip->i_update_core && (ip->i_itemp == NULL)) {
    -		xfs_ilock(ip, XFS_ILOCK_EXCL);
    -		xfs_iflock(ip);
    -		return xfs_finish_reclaim(ip, 1, XFS_IFLUSH_DELWRI_ELSE_SYNC);
    -	} else {
    -		xfs_mount_t	*mp = ip->i_mount;
    -
    -		/* Protect sync from us */
    -		XFS_MOUNT_ILOCK(mp);
    -		vn_bhv_remove(VN_BHV_HEAD(vp), XFS_ITOBHV(ip));
    -		TAILQ_INSERT_TAIL(&mp->m_del_inodes, ip, i_reclaim);
    -		ip->i_flags |= XFS_IRECLAIMABLE;
    -		XFS_MOUNT_IUNLOCK(mp);
    -	}
    -	return 0;
    -}
    -
    -int
    -xfs_finish_reclaim(
    -	xfs_inode_t	*ip,
    -	int		locked,
    -	int		sync_mode)
    -{
    -	xfs_ihash_t	*ih = ip->i_hash;
    -	xfs_vnode_t	*vp = XFS_ITOV_NULL(ip);
    -	int		error;
    -
    -	if (vp && VN_BAD(vp))
    -		goto reclaim;
    -
    -	/* The hash lock here protects a thread in xfs_iget_core from
    -	 * racing with us on linking the inode back with a vnode.
    -	 * Once we have the XFS_IRECLAIM flag set it will not touch
    -	 * us.
    -	 */
    -	write_lock(&ih->ih_lock);
    -	if ((ip->i_flags & XFS_IRECLAIM) ||
    -	    (!(ip->i_flags & XFS_IRECLAIMABLE) && vp == NULL)) {
    -		write_unlock(&ih->ih_lock);
    -		if (locked) {
    -			xfs_ifunlock(ip);
    -			xfs_iunlock(ip, XFS_ILOCK_EXCL);
    -		}
    -		return 1;
    -	}
    -	ip->i_flags |= XFS_IRECLAIM;
    -	write_unlock(&ih->ih_lock);
    -
    -	/*
    -	 * If the inode is still dirty, then flush it out.  If the inode
    -	 * is not in the AIL, then it will be OK to flush it delwri as
    -	 * long as xfs_iflush() does not keep any references to the inode.
    -	 * We leave that decision up to xfs_iflush() since it has the
    -	 * knowledge of whether it's OK to simply do a delwri flush of
    -	 * the inode or whether we need to wait until the inode is
    -	 * pulled from the AIL.
    -	 * We get the flush lock regardless, though, just to make sure
    -	 * we don't free it while it is being flushed.
    -	 */
    -	if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) {
    -		if (!locked) {
    -			xfs_ilock(ip, XFS_ILOCK_EXCL);
    -			xfs_iflock(ip);
    -		}
    -
    -		if (ip->i_update_core ||
    -		    ((ip->i_itemp != NULL) &&
    -		     (ip->i_itemp->ili_format.ilf_fields != 0))) {
    -			error = xfs_iflush(ip, sync_mode);
    -			/*
    -			 * If we hit an error, typically because of filesystem
    -			 * shutdown, we don't need to let vn_reclaim to know
    -			 * because we're gonna reclaim the inode anyway.
    -			 */
    -			if (error) {
    -				xfs_iunlock(ip, XFS_ILOCK_EXCL);
    -				goto reclaim;
    -			}
    -			xfs_iflock(ip); /* synchronize with xfs_iflush_done */
    -		}
    -
    -		ASSERT(ip->i_update_core == 0);
    -		ASSERT(ip->i_itemp == NULL ||
    -		       ip->i_itemp->ili_format.ilf_fields == 0);
    -		xfs_iunlock(ip, XFS_ILOCK_EXCL);
    -	} else if (locked) {
    -		/*
    -		 * We are not interested in doing an iflush if we're
    -		 * in the process of shutting down the filesystem forcibly.
    -		 * So, just reclaim the inode.
    -		 */
    -		xfs_ifunlock(ip);
    -		xfs_iunlock(ip, XFS_ILOCK_EXCL);
    -	}
    -
    - reclaim:
    -	xfs_ireclaim(ip);
    -	return 0;
    -}
    -
    -int
    -xfs_finish_reclaim_all(xfs_mount_t *mp, int noblock)
    -{
    -#ifdef RMC
    -	int		purged;
    -	xfs_inode_t	*ip, *n;
    -	int		done = 0;
    -
    -	while (!done) {
    -		purged = 0;
    -		XFS_MOUNT_ILOCK(mp);
    -		TAILQ_FOREACH_SAFE(curr, &mp->m_del_inodes, i_reclaim, next) {
    -			ip = curr;
    -			if (noblock) {
    -				if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL) == 0)
    -					continue;
    -				if (xfs_ipincount(ip) ||
    -				    !xfs_iflock_nowait(ip)) {
    -					xfs_iunlock(ip, XFS_ILOCK_EXCL);
    -					continue;
    -				}
    -			}
    -			XFS_MOUNT_IUNLOCK(mp);
    -			if (xfs_finish_reclaim(ip, noblock,
    -					XFS_IFLUSH_DELWRI_ELSE_ASYNC))
    -				delay(1);
    -			purged = 1;
    -			break;
    -		}
    -
    -		done = !purged;
    -	}
    -
    -	XFS_MOUNT_IUNLOCK(mp);
    -#endif
    -	return 0;
    -}
    -
    -/*
    - * xfs_alloc_file_space()
    - *      This routine allocates disk space for the given file.
    - *
    - *	If alloc_type == 0, this request is for an ALLOCSP type
    - *	request which will change the file size.  In this case, no
    - *	DMAPI event will be generated by the call.  A TRUNCATE event
    - *	will be generated later by xfs_setattr.
    - *
    - *	If alloc_type != 0, this request is for a RESVSP type
    - *	request, and a DMAPI DM_EVENT_WRITE will be generated if the
    - *	lower block boundary byte address is less than the file's
    - *	length.
    - *
    - * RETURNS:
    - *       0 on success
    - *      errno on error
    - *
    - */
    -STATIC int
    -xfs_alloc_file_space(
    -	xfs_inode_t		*ip,
    -	xfs_off_t		offset,
    -	xfs_off_t		len,
    -	int			alloc_type,
    -	int			attr_flags)
    -{
    -	xfs_mount_t		*mp = ip->i_mount;
    -	xfs_off_t		count;
    -	xfs_filblks_t		allocated_fsb;
    -	xfs_filblks_t		allocatesize_fsb;
    -	xfs_extlen_t		extsz, temp;
    -	xfs_fileoff_t		startoffset_fsb;
    -	xfs_fsblock_t		firstfsb;
    -	int			nimaps;
    -	int			bmapi_flag;
    -	int			quota_flag;
    -	int			rt;
    -	xfs_trans_t		*tp;
    -	xfs_bmbt_irec_t		imaps[1], *imapp;
    -	xfs_bmap_free_t		free_list;
    -	uint			qblocks, resblks, resrtextents;
    -	int			committed;
    -	int			error;
    -
    -	vn_trace_entry(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address);
    -
    -	if (XFS_FORCED_SHUTDOWN(mp))
    -		return XFS_ERROR(EIO);
    -
    -	rt = XFS_IS_REALTIME_INODE(ip);
    -	if (unlikely(rt)) {
    -		if (!(extsz = ip->i_d.di_extsize))
    -			extsz = mp->m_sb.sb_rextsize;
    -	} else {
    -		extsz = ip->i_d.di_extsize;
    -	}
    -
    -	if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
    -		return error;
    -
    -	if (len <= 0)
    -		return XFS_ERROR(EINVAL);
    -
    -	count = len;
    -	error = 0;
    -	imapp = &imaps[0];
    -	nimaps = 1;
    -	bmapi_flag = XFS_BMAPI_WRITE | (alloc_type ? XFS_BMAPI_PREALLOC : 0);
    -	startoffset_fsb	= XFS_B_TO_FSBT(mp, offset);
    -	allocatesize_fsb = XFS_B_TO_FSB(mp, count);
    -
    -	/*	Generate a DMAPI event if needed.	*/
    -	if (alloc_type != 0 && offset < ip->i_d.di_size &&
    -			(attr_flags&ATTR_DMI) == 0  &&
    -			DM_EVENT_ENABLED(XFS_MTOVFS(mp), ip, DM_EVENT_WRITE)) {
    -		xfs_off_t           end_dmi_offset;
    -
    -		end_dmi_offset = offset+len;
    -		if (end_dmi_offset > ip->i_d.di_size)
    -			end_dmi_offset = ip->i_d.di_size;
    -		error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, XFS_ITOV(ip),
    -			offset, end_dmi_offset - offset,
    -			0, NULL);
    -		if (error)
    -			return error;
    -	}
    -
    -	/*
    -	 * Allocate file space until done or until there is an error
    -	 */
    -retry:
    -	while (allocatesize_fsb && !error) {
    -		xfs_fileoff_t	s, e;
    -
    -		/*
    -		 * Determine space reservations for data/realtime.
    -		 */
    -		if (unlikely(extsz)) {
    -			s = startoffset_fsb;
    -			do_div(s, extsz);
    -			s *= extsz;
    -			e = startoffset_fsb + allocatesize_fsb;
    -			if ((temp = do_mod(startoffset_fsb, extsz)))
    -				e += temp;
    -			if ((temp = do_mod(e, extsz)))
    -				e += extsz - temp;
    -		} else {
    -			s = 0;
    -			e = allocatesize_fsb;
    -		}
    -
    -		if (unlikely(rt)) {
    -			resrtextents = qblocks = (uint)(e - s);
    -			resrtextents /= mp->m_sb.sb_rextsize;
    -			resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
    -			quota_flag = XFS_QMOPT_RES_RTBLKS;
    -		} else {
    -			resrtextents = 0;
    -			resblks = qblocks = \
    -				XFS_DIOSTRAT_SPACE_RES(mp, (uint)(e - s));
    -			quota_flag = XFS_QMOPT_RES_REGBLKS;
    -		}
    -
    -		/*
    -		 * Allocate and setup the transaction.
    -		 */
    -		tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT);
    -		error = xfs_trans_reserve(tp, resblks,
    -					  XFS_WRITE_LOG_RES(mp), resrtextents,
    -					  XFS_TRANS_PERM_LOG_RES,
    -					  XFS_WRITE_LOG_COUNT);
    -		/*
    -		 * Check for running out of space
    -		 */
    -		if (error) {
    -			/*
    -			 * Free the transaction structure.
    -			 */
    -			ASSERT(error == ENOSPC || XFS_FORCED_SHUTDOWN(mp));
    -			xfs_trans_cancel(tp, 0);
    -			break;
    -		}
    -		xfs_ilock(ip, XFS_ILOCK_EXCL);
    -		error = XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip,
    -						      qblocks, 0, quota_flag);
    -		if (error)
    -			goto error1;
    -
    -		xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
    -		xfs_trans_ihold(tp, ip);
    -
    -		/*
    -		 * Issue the xfs_bmapi() call to allocate the blocks
    -		 */
    -		XFS_BMAP_INIT(&free_list, &firstfsb);
    -		error = XFS_BMAPI(mp, tp, &ip->i_iocore, startoffset_fsb,
    -				  allocatesize_fsb, bmapi_flag,
    -				  &firstfsb, 0, imapp, &nimaps,
    -				  &free_list, NULL);
    -		if (error) {
    -			goto error0;
    -		}
    -
    -		/*
    -		 * Complete the transaction
    -		 */
    -		error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed);
    -		if (error) {
    -			goto error0;
    -		}
    -
    -		error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
    -		xfs_iunlock(ip, XFS_ILOCK_EXCL);
    -		if (error) {
    -			break;
    -		}
    -
    -		allocated_fsb = imapp->br_blockcount;
    -
    -		if (nimaps == 0) {
    -			error = XFS_ERROR(ENOSPC);
    -			break;
    -		}
    -
    -		startoffset_fsb += allocated_fsb;
    -		allocatesize_fsb -= allocated_fsb;
    -	}
    -dmapi_enospc_check:
    -	if (error == ENOSPC && (attr_flags&ATTR_DMI) == 0 &&
    -	    DM_EVENT_ENABLED(XFS_MTOVFS(mp), ip, DM_EVENT_NOSPACE)) {
    -
    -		error = XFS_SEND_NAMESP(mp, DM_EVENT_NOSPACE,
    -				XFS_ITOV(ip), DM_RIGHT_NULL,
    -				XFS_ITOV(ip), DM_RIGHT_NULL,
    -				NULL, NULL, 0, 0, 0); /* Delay flag intentionally unused */
    -		if (error == 0)
    -			goto retry;	/* Maybe DMAPI app. has made space */
    -		/* else fall through with error from XFS_SEND_DATA */
    -	}
    -
    -	return error;
    -
    -error0:	/* Cancel bmap, unlock inode, unreserve quota blocks, cancel trans */
    -	xfs_bmap_cancel(&free_list);
    -	XFS_TRANS_UNRESERVE_QUOTA_NBLKS(mp, tp, ip, qblocks, 0, quota_flag);
    -
    -error1:	/* Just cancel transaction */
    -	xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
    -	xfs_iunlock(ip, XFS_ILOCK_EXCL);
    -	goto dmapi_enospc_check;
    -}
    -
    -/*
    - * Zero file bytes between startoff and endoff inclusive.
    - * The iolock is held exclusive and no blocks are buffered.
    - */
    -STATIC int
    -xfs_zero_remaining_bytes(
    -	xfs_inode_t		*ip,
    -	xfs_off_t		startoff,
    -	xfs_off_t		endoff)
    -{
    -	xfs_bmbt_irec_t		imap;
    -	xfs_fileoff_t		offset_fsb;
    -	xfs_off_t		lastoffset;
    -	xfs_off_t		offset;
    -	xfs_buf_t		*bp;
    -	xfs_mount_t		*mp = ip->i_mount;
    -	int			nimap;
    -	int			error = 0;
    -
    -	bp = xfs_buf_get_noaddr(mp->m_sb.sb_blocksize,
    -				ip->i_d.di_flags & XFS_DIFLAG_REALTIME ?
    -				mp->m_rtdev_targp : mp->m_ddev_targp);
    -
    -	for (offset = startoff; offset <= endoff; offset = lastoffset + 1) {
    -		offset_fsb = XFS_B_TO_FSBT(mp, offset);
    -		nimap = 1;
    -		error = XFS_BMAPI(mp, NULL, &ip->i_iocore, offset_fsb, 1, 0,
    -			NULL, 0, &imap, &nimap, NULL, NULL);
    -		if (error || nimap < 1)
    -			break;
    -		ASSERT(imap.br_blockcount >= 1);
    -		ASSERT(imap.br_startoff == offset_fsb);
    -		lastoffset = XFS_FSB_TO_B(mp, imap.br_startoff + 1) - 1;
    -		if (lastoffset > endoff)
    -			lastoffset = endoff;
    -		if (imap.br_startblock == HOLESTARTBLOCK)
    -			continue;
    -		ASSERT(imap.br_startblock != DELAYSTARTBLOCK);
    -		if (imap.br_state == XFS_EXT_UNWRITTEN)
    -			continue;
    -		XFS_BUF_UNDONE(bp);
    -		XFS_BUF_UNWRITE(bp);
    -		XFS_BUF_READ(bp);
    -		XFS_BUF_SET_ADDR(bp, XFS_FSB_TO_DB(ip, imap.br_startblock));
    -		xfsbdstrat(mp, bp);
    -		if ((error = xfs_iowait(bp))) {
    -			xfs_ioerror_alert("xfs_zero_remaining_bytes(read)",
    -					  mp, bp, XFS_BUF_ADDR(bp));
    -			break;
    -		}
    -		memset(XFS_BUF_PTR(bp) +
    -			(offset - XFS_FSB_TO_B(mp, imap.br_startoff)),
    -		      0, lastoffset - offset + 1);
    -		XFS_BUF_UNDONE(bp);
    -		XFS_BUF_UNREAD(bp);
    -		XFS_BUF_WRITE(bp);
    -		xfsbdstrat(mp, bp);
    -		if ((error = xfs_iowait(bp))) {
    -			xfs_ioerror_alert("xfs_zero_remaining_bytes(write)",
    -					  mp, bp, XFS_BUF_ADDR(bp));
    -			break;
    -		}
    -	}
    -	xfs_buf_free(bp);
    -	return error;
    -}
    -
    -/*
    - * xfs_free_file_space()
    - *      This routine frees disk space for the given file.
    - *
    - *	This routine is only called by xfs_change_file_space
    - *	for an UNRESVSP type call.
    - *
    - * RETURNS:
    - *       0 on success
    - *      errno on error
    - *
    - */
    -STATIC int
    -xfs_free_file_space(
    -	xfs_inode_t		*ip,
    -	xfs_off_t		offset,
    -	xfs_off_t		len,
    -	int			attr_flags)
    -{
    -	xfs_vnode_t		*vp;
    -	int			committed;
    -	int			done;
    -	xfs_off_t		end_dmi_offset;
    -	xfs_fileoff_t		endoffset_fsb;
    -	int			error;
    -	xfs_fsblock_t		firstfsb;
    -	xfs_bmap_free_t		free_list;
    -	xfs_off_t		ilen;
    -	xfs_bmbt_irec_t		imap;
    -	xfs_off_t		ioffset;
    -	xfs_extlen_t		mod=0;
    -	xfs_mount_t		*mp;
    -	int			nimap;
    -	uint			resblks;
    -	int			rounding;
    -	int			rt;
    -	xfs_fileoff_t		startoffset_fsb;
    -	xfs_trans_t		*tp;
    -	int			need_iolock = 1;
    -
    -	vp = XFS_ITOV(ip);
    -	mp = ip->i_mount;
    -
    -	vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
    -
    -	if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
    -		return error;
    -
    -	error = 0;
    -	if (len <= 0)	/* if nothing being freed */
    -		return error;
    -	rt = (ip->i_d.di_flags & XFS_DIFLAG_REALTIME);
    -	startoffset_fsb	= XFS_B_TO_FSB(mp, offset);
    -	end_dmi_offset = offset + len;
    -	endoffset_fsb = XFS_B_TO_FSBT(mp, end_dmi_offset);
    -
    -	if (offset < ip->i_d.di_size &&
    -	    (attr_flags & ATTR_DMI) == 0 &&
    -	    DM_EVENT_ENABLED(XFS_MTOVFS(mp), ip, DM_EVENT_WRITE)) {
    -		if (end_dmi_offset > ip->i_d.di_size)
    -			end_dmi_offset = ip->i_d.di_size;
    -		error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, vp,
    -				offset, end_dmi_offset - offset,
    -				AT_DELAY_FLAG(attr_flags), NULL);
    -		if (error)
    -			return error;
    -	}
    -
    -	ASSERT(attr_flags & ATTR_NOLOCK ? attr_flags & ATTR_DMI : 1);
    -	if (attr_flags & ATTR_NOLOCK)
    -		need_iolock = 0;
    -	if (need_iolock) {
    -		xfs_ilock(ip, XFS_IOLOCK_EXCL);
    -		vn_iowait(vp);	/* wait for the completion of any pending DIOs */
    -	}
    -
    -	rounding = MAX((__uint8_t)(1 << mp->m_sb.sb_blocklog),
    -			(__uint8_t)NBPP);
    -	ilen = len + (offset & (rounding - 1));
    -	ioffset = offset & ~(rounding - 1);
    -	if (ilen & (rounding - 1))
    -		ilen = (ilen + rounding) & ~(rounding - 1);
    -
    -	if (VN_CACHED(vp) != 0) {
    -		xfs_inval_cached_trace(&ip->i_iocore, ioffset, -1,
    -				ctooff(offtoct(ioffset)), -1);
    -		XVOP_FLUSHINVAL_PAGES(vp, ctooff(offtoct(ioffset)),
    -				-1, FI_REMAPF_LOCKED);
    -	}
    -
    -	/*
    -	 * Need to zero the stuff we're not freeing, on disk.
    -	 * If its a realtime file & can't use unwritten extents then we
    -	 * actually need to zero the extent edges.  Otherwise xfs_bunmapi
    -	 * will take care of it for us.
    -	 */
    -	if (rt && !XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb)) {
    -		nimap = 1;
    -		error = XFS_BMAPI(mp, NULL, &ip->i_iocore, startoffset_fsb,
    -			1, 0, NULL, 0, &imap, &nimap, NULL, NULL);
    -		if (error)
    -			goto out_unlock_iolock;
    -		ASSERT(nimap == 0 || nimap == 1);
    -		if (nimap && imap.br_startblock != HOLESTARTBLOCK) {
    -			xfs_daddr_t	block;
    -
    -			ASSERT(imap.br_startblock != DELAYSTARTBLOCK);
    -			block = imap.br_startblock;
    -			mod = do_div(block, mp->m_sb.sb_rextsize);
    -			if (mod)
    -				startoffset_fsb += mp->m_sb.sb_rextsize - mod;
    -		}
    -		nimap = 1;
    -		error = XFS_BMAPI(mp, NULL, &ip->i_iocore, endoffset_fsb - 1,
    -			1, 0, NULL, 0, &imap, &nimap, NULL, NULL);
    -		if (error)
    -			goto out_unlock_iolock;
    -		ASSERT(nimap == 0 || nimap == 1);
    -		if (nimap && imap.br_startblock != HOLESTARTBLOCK) {
    -			ASSERT(imap.br_startblock != DELAYSTARTBLOCK);
    -			mod++;
    -			if (mod && (mod != mp->m_sb.sb_rextsize))
    -				endoffset_fsb -= mod;
    -		}
    -	}
    -	if ((done = (endoffset_fsb <= startoffset_fsb)))
    -		/*
    -		 * One contiguous piece to clear
    -		 */
    -		error = xfs_zero_remaining_bytes(ip, offset, offset + len - 1);
    -	else {
    -		/*
    -		 * Some full blocks, possibly two pieces to clear
    -		 */
    -		if (offset < XFS_FSB_TO_B(mp, startoffset_fsb))
    -			error = xfs_zero_remaining_bytes(ip, offset,
    -				XFS_FSB_TO_B(mp, startoffset_fsb) - 1);
    -		if (!error &&
    -		    XFS_FSB_TO_B(mp, endoffset_fsb) < offset + len)
    -			error = xfs_zero_remaining_bytes(ip,
    -				XFS_FSB_TO_B(mp, endoffset_fsb),
    -				offset + len - 1);
    -	}
    -
    -	/*
    -	 * free file space until done or until there is an error
    -	 */
    -	resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
    -	while (!error && !done) {
    -
    -		/*
    -		 * allocate and setup the transaction
    -		 */
    -		tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT);
    -		error = xfs_trans_reserve(tp,
    -					  resblks,
    -					  XFS_WRITE_LOG_RES(mp),
    -					  0,
    -					  XFS_TRANS_PERM_LOG_RES,
    -					  XFS_WRITE_LOG_COUNT);
    -
    -		/*
    -		 * check for running out of space
    -		 */
    -		if (error) {
    -			/*
    -			 * Free the transaction structure.
    -			 */
    -			ASSERT(error == ENOSPC || XFS_FORCED_SHUTDOWN(mp));
    -			xfs_trans_cancel(tp, 0);
    -			break;
    -		}
    -		xfs_ilock(ip, XFS_ILOCK_EXCL);
    -		error = XFS_TRANS_RESERVE_QUOTA(mp, tp,
    -				ip->i_udquot, ip->i_gdquot, resblks, 0,
    -				XFS_QMOPT_RES_REGBLKS);
    -		if (error)
    -			goto error1;
    -
    -		xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
    -		xfs_trans_ihold(tp, ip);
    -
    -		/*
    -		 * issue the bunmapi() call to free the blocks
    -		 */
    -		XFS_BMAP_INIT(&free_list, &firstfsb);
    -		error = XFS_BUNMAPI(mp, tp, &ip->i_iocore, startoffset_fsb,
    -				  endoffset_fsb - startoffset_fsb,
    -				  0, 2, &firstfsb, &free_list, NULL, &done);
    -		if (error) {
    -			goto error0;
    -		}
    -
    -		/*
    -		 * complete the transaction
    -		 */
    -		error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed);
    -		if (error) {
    -			goto error0;
    -		}
    -
    -		error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
    -		xfs_iunlock(ip, XFS_ILOCK_EXCL);
    -	}
    -
    - out_unlock_iolock:
    -	if (need_iolock)
    -		xfs_iunlock(ip, XFS_IOLOCK_EXCL);
    -	return error;
    -
    - error0:
    -	xfs_bmap_cancel(&free_list);
    - error1:
    -	xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
    -	xfs_iunlock(ip, need_iolock ? (XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL) :
    -		    XFS_ILOCK_EXCL);
    -	return error;
    -}
    -
    -/*
    - * xfs_change_file_space()
    - *      This routine allocates or frees disk space for the given file.
    - *      The user specified parameters are checked for alignment and size
    - *      limitations.
    - *
    - * RETURNS:
    - *       0 on success
    - *      errno on error
    - *
    - */
    -int
    -xfs_change_file_space(
    -	bhv_desc_t	*bdp,
    -	u_long		cmd,
    -	xfs_flock64_t	*bf,
    -	xfs_off_t	offset,
    -	cred_t		*credp,
    -	int		attr_flags)
    -{
    -	int		clrprealloc;
    -	int		error;
    -	xfs_fsize_t	fsize;
    -	xfs_inode_t	*ip;
    -	xfs_mount_t	*mp;
    -	int		setprealloc;
    -	xfs_off_t	startoffset;
    -	xfs_off_t	llen;
    -	xfs_trans_t	*tp;
    -	xfs_vattr_t	va;
    -	xfs_vnode_t	*vp;
    -
    -	vp = BHV_TO_VNODE(bdp);
    -	vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
    -
    -	ip = XFS_BHVTOI(bdp);
    -	mp = ip->i_mount;
    -
    -	/*
    -	 * must be a regular file and have write permission
    -	 */
    -	if (!VN_ISREG(vp))
    -		return XFS_ERROR(EINVAL);
    -
    -	xfs_ilock(ip, XFS_ILOCK_SHARED);
    -
    -	if ((error = xfs_iaccess(ip, VWRITE, credp))) {
    -		xfs_iunlock(ip, XFS_ILOCK_SHARED);
    -		return error;
    -	}
    -
    -	xfs_iunlock(ip, XFS_ILOCK_SHARED);
    -
    -	switch (bf->l_whence) {
    -	case 0: /*SEEK_SET*/
    -		break;
    -	case 1: /*SEEK_CUR*/
    -		bf->l_start += offset;
    -		break;
    -	case 2: /*SEEK_END*/
    -		bf->l_start += ip->i_d.di_size;
    -		break;
    -	default:
    -		return XFS_ERROR(EINVAL);
    -	}
    -
    -	llen = bf->l_len > 0 ? bf->l_len - 1 : bf->l_len;
    -
    -	if (   (bf->l_start < 0)
    -	    || (bf->l_start > XFS_MAXIOFFSET(mp))
    -	    || (bf->l_start + llen < 0)
    -	    || (bf->l_start + llen > XFS_MAXIOFFSET(mp)))
    -		return XFS_ERROR(EINVAL);
    -
    -	bf->l_whence = 0;
    -
    -	startoffset = bf->l_start;
    -	fsize = ip->i_d.di_size;
    -
    -	/*
    -	 * XFS_IOC_RESVSP and XFS_IOC_UNRESVSP will reserve or unreserve
    -	 * file space.
    -	 * These calls do NOT zero the data space allocated to the file,
    -	 * nor do they change the file size.
    -	 *
    -	 * XFS_IOC_ALLOCSP and XFS_IOC_FREESP will allocate and free file
    -	 * space.
    -	 * These calls cause the new file data to be zeroed and the file
    -	 * size to be changed.
    -	 */
    -	setprealloc = clrprealloc = 0;
    -
    -	switch (cmd) {
    -	case XFS_IOC_RESVSP:
    -	case XFS_IOC_RESVSP64:
    -		error = xfs_alloc_file_space(ip, startoffset, bf->l_len,
    -								1, attr_flags);
    -		if (error)
    -			return error;
    -		setprealloc = 1;
    -		break;
    -
    -	case XFS_IOC_UNRESVSP:
    -	case XFS_IOC_UNRESVSP64:
    -		if ((error = xfs_free_file_space(ip, startoffset, bf->l_len,
    -								attr_flags)))
    -			return error;
    -		break;
    -
    -	case XFS_IOC_ALLOCSP:
    -	case XFS_IOC_ALLOCSP64:
    -	case XFS_IOC_FREESP:
    -	case XFS_IOC_FREESP64:
    -		if (startoffset > fsize) {
    -			error = xfs_alloc_file_space(ip, fsize,
    -					startoffset - fsize, 0, attr_flags);
    -			if (error)
    -				break;
    -		}
    -
    -		va.va_mask = XFS_AT_SIZE;
    -		va.va_size = startoffset;
    -
    -		error = xfs_setattr(bdp, &va, attr_flags, credp);
    -
    -		if (error)
    -			return error;
    -
    -		clrprealloc = 1;
    -		break;
    -
    -	default:
    -		ASSERT(0);
    -		return XFS_ERROR(EINVAL);
    -	}
    -
    -	/*
    -	 * update the inode timestamp, mode, and prealloc flag bits
    -	 */
    -	tp = xfs_trans_alloc(mp, XFS_TRANS_WRITEID);
    -
    -	if ((error = xfs_trans_reserve(tp, 0, XFS_WRITEID_LOG_RES(mp),
    -				      0, 0, 0))) {
    -		/* ASSERT(0); */
    -		xfs_trans_cancel(tp, 0);
    -		return error;
    -	}
    -
    -	xfs_ilock(ip, XFS_ILOCK_EXCL);
    -
    -	xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
    -	xfs_trans_ihold(tp, ip);
    -
    -	if ((attr_flags & ATTR_DMI) == 0) {
    -		ip->i_d.di_mode &= ~S_ISUID;
    -
    -		/*
    -		 * Note that we don't have to worry about mandatory
    -		 * file locking being disabled here because we only
    -		 * clear the S_ISGID bit if the Group execute bit is
    -		 * on, but if it was on then mandatory locking wouldn't
    -		 * have been enabled.
    -		 */
    -		if (ip->i_d.di_mode & S_IXGRP)
    -			ip->i_d.di_mode &= ~S_ISGID;
    -
    -		xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
    -	}
    -	if (setprealloc)
    -		ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC;
    -	else if (clrprealloc)
    -		ip->i_d.di_flags &= ~XFS_DIFLAG_PREALLOC;
    -
    -	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
    -	xfs_trans_set_sync(tp);
    -
    -	error = xfs_trans_commit(tp, 0, NULL);
    -
    -	xfs_iunlock(ip, XFS_ILOCK_EXCL);
    -
    -	return error;
    -}
    -
    -
    -xfs_vnodeops_t xfs_vnodeops = {
    -	BHV_IDENTITY_INIT(VN_BHV_XFS,VNODE_POSITION_XFS),
    -	.vop_open		= xfs_open,
    -	.vop_read		= xfs_read,
    -#ifdef HAVE_SENDFILE
    -	.vop_sendfile		= xfs_sendfile,
    -#endif
    -	.vop_write		= xfs_write,
    -	.vop_ioctl		= xfs_ioctl,
    -	.vop_getattr		= xfs_getattr,
    -	.vop_setattr		= xfs_setattr,
    -	.vop_access		= xfs_access,
    -	.vop_lookup		= xfs_lookup,
    -	.vop_create		= xfs_create,
    -	.vop_remove		= xfs_remove,
    -	.vop_link		= xfs_link,
    -	.vop_rename		= xfs_rename,
    -	.vop_mkdir		= xfs_mkdir,
    -	.vop_rmdir		= xfs_rmdir,
    -	.vop_readdir		= xfs_readdir,
    -	.vop_symlink		= xfs_symlink,
    -	.vop_readlink		= xfs_readlink,
    -	.vop_fsync		= xfs_fsync,
    -	.vop_inactive		= xfs_inactive,
    -	.vop_fid2		= xfs_fid2,
    -	.vop_rwlock		= xfs_rwlock,
    -	.vop_rwunlock		= xfs_rwunlock,
    -	.vop_bmap		= xfs_bmap,
    -	.vop_reclaim		= xfs_reclaim,
    -	.vop_attr_get		= xfs_attr_get,
    -	.vop_attr_set		= xfs_attr_set,
    -	.vop_attr_remove	= xfs_attr_remove,
    -	.vop_attr_list		= xfs_attr_list,
    -	.vop_link_removed	= (xfs_vop_link_removed_t)fs_noval,
    -	.vop_vnode_change	= (xfs_vop_vnode_change_t)fs_noval,
    -	.vop_tosspages		= fs_tosspages,
    -	.vop_flushinval_pages	= fs_flushinval_pages,
    -	.vop_flush_pages	= fs_flush_pages,
    -	.vop_release		= xfs_release,
    -	.vop_iflush		= xfs_inode_flush,
    -};
    diff --git a/sys/gnu/fs/xfs/xfsidbg.c b/sys/gnu/fs/xfs/xfsidbg.c
    deleted file mode 100644
    index e0fc2f60228..00000000000
    --- a/sys/gnu/fs/xfs/xfsidbg.c
    +++ /dev/null
    @@ -1,7769 +0,0 @@
    -/*
    - * Copyright (c) 2000-2005 Silicon Graphics, Inc.
    - * All Rights Reserved.
    - *
    - * This program is free software; you can redistribute it and/or
    - * modify it under the terms of the GNU General Public License as
    - * published by the Free Software Foundation.
    - *
    - * This program is distributed in the hope that it would be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write the Free Software Foundation,
    - * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    - */
    -#include "xfs.h"
    -
    -#include "xfs_fs.h"
    -#include "xfs_types.h"
    -#include "xfs_bit.h"
    -#include "xfs_log.h"
    -#include "xfs_inum.h"
    -#include "xfs_trans.h"
    -#include "xfs_sb.h"
    -#include "xfs_ag.h"
    -#include "xfs_dir.h"
    -#include "xfs_dir2.h"
    -#include "xfs_dmapi.h"
    -#include "xfs_mount.h"
    -#include "xfs_alloc.h"
    -#include "xfs_da_btree.h"
    -#include "xfs_alloc_btree.h"
    -#include "xfs_bmap_btree.h"
    -#include "xfs_ialloc_btree.h"
    -#include "xfs_dir_sf.h"
    -#include "xfs_dir2_sf.h"
    -#include "xfs_attr_sf.h"
    -#include "xfs_dinode.h"
    -#include "xfs_inode.h"
    -#include "xfs_btree.h"
    -#include "xfs_buf_item.h"
    -#include "xfs_inode_item.h"
    -#include "xfs_extfree_item.h"
    -#include "xfs_rw.h"
    -#include "xfs_bmap.h"
    -#include "xfs_attr.h"
    -#include "xfs_attr_leaf.h"
    -#include "xfs_dir_leaf.h"
    -#include "xfs_dir2_data.h"
    -#include "xfs_dir2_leaf.h"
    -#include "xfs_dir2_block.h"
    -#include "xfs_dir2_node.h"
    -#include "xfs_dir2_trace.h"
    -#include "xfs_log_priv.h"
    -#include "xfs_log_recover.h"
    -#include "xfs_quota.h"
    -#include "quota/xfs_qm.h"
    -#include "xfs_iomap.h"
    -
    -#include 
    -
    -#define qprintf	kdb_printf
    -
    -/*
    - * Command table functions. (tracing)
    - */
    -#ifdef XFS_ALLOC_TRACE
    -static void	xfsidbg_xalatrace(int);
    -static void	xfsidbg_xalbtrace(xfs_agblock_t);
    -static void	xfsidbg_xalgtrace(xfs_agnumber_t);
    -static void	xfsidbg_xalmtrace(xfs_mount_t *);
    -static void	xfsidbg_xalttrace(int);
    -#endif
    -#ifdef XFS_ATTR_TRACE
    -static void	xfsidbg_xattrtrace(int);
    -#endif
    -#ifdef XFS_BLI_TRACE
    -static void	xfsidbg_xblitrace(xfs_buf_log_item_t *);
    -#endif
    -#ifdef XFS_BMAP_TRACE
    -static void	xfsidbg_xbmatrace(int);
    -static void	xfsidbg_xbmitrace(xfs_inode_t *);
    -static void	xfsidbg_xbmstrace(xfs_inode_t *);
    -static void	xfsidbg_xbxatrace(int);
    -static void	xfsidbg_xbxitrace(xfs_inode_t *);
    -static void	xfsidbg_xbxstrace(xfs_inode_t *);
    -#endif
    -#ifdef XFS_ILOCK_TRACE
    -static void	xfsidbg_xilock_trace(xfs_inode_t *);
    -static void	xfsidbg_xailock_trace(int);
    -#endif
    -#ifdef XFS_DIR_TRACE
    -static void	xfsidbg_xdirtrace(int);
    -#endif
    -#ifdef XFS_DIR2_TRACE
    -static void	xfsidbg_xdir2atrace(int);
    -static void	xfsidbg_xdir2itrace(xfs_inode_t *);
    -#endif
    -#ifdef XFS_LOG_TRACE
    -static void	xfsidbg_xiclogtrace(xlog_in_core_t *);
    -static void	xfsidbg_xlog_granttrace(xlog_t *);
    -#endif
    -#ifdef XFS_DQUOT_TRACE
    -static void	xfsidbg_xqm_dqtrace(xfs_dquot_t *);
    -#endif
    -
    -
    -/*
    - * Command table functions.
    - */
    -static void	xfsidbg_xagf(xfs_agf_t *);
    -static void	xfsidbg_xagi(xfs_agi_t *);
    -static void	xfsidbg_xaildump(xfs_mount_t *);
    -static void	xfsidbg_xalloc(xfs_alloc_arg_t *);
    -static void	xfsidbg_xattrcontext(xfs_attr_list_context_t *);
    -static void	xfsidbg_xattrleaf(xfs_attr_leafblock_t *);
    -static void	xfsidbg_xattrsf(xfs_attr_shortform_t *);
    -static void	xfsidbg_xbirec(xfs_bmbt_irec_t *r);
    -static void	xfsidbg_xbmalla(xfs_bmalloca_t *);
    -static void	xfsidbg_xbrec(xfs_bmbt_rec_64_t *);
    -static void	xfsidbg_xbroot(xfs_inode_t *);
    -static void	xfsidbg_xbroota(xfs_inode_t *);
    -static void	xfsidbg_xbtcur(xfs_btree_cur_t *);
    -static void	xfsidbg_xbuf(xfs_buf_t *);
    -static void	xfsidbg_xbuf_real(xfs_buf_t *, int);
    -static void	xfsidbg_xarg(int);
    -static void	xfsidbg_xchksum(uint *);
    -static void	xfsidbg_xchash(xfs_mount_t *mp);
    -static void	xfsidbg_xchashlist(xfs_chashlist_t *chl);
    -static void	xfsidbg_xdaargs(xfs_da_args_t *);
    -static void	xfsidbg_xdabuf(xfs_dabuf_t *);
    -static void	xfsidbg_xdanode(xfs_da_intnode_t *);
    -static void	xfsidbg_xdastate(xfs_da_state_t *);
    -static void	xfsidbg_xdirleaf(xfs_dir_leafblock_t *);
    -static void	xfsidbg_xdirsf(xfs_dir_shortform_t *);
    -static void	xfsidbg_xdir2free(xfs_dir2_free_t *);
    -static void	xfsidbg_xdir2sf(xfs_dir2_sf_t *);
    -static void	xfsidbg_xexlist(xfs_inode_t *);
    -static void	xfsidbg_xflist(xfs_bmap_free_t *);
    -static void	xfsidbg_xhelp(void);
    -static void	xfsidbg_xiclog(xlog_in_core_t *);
    -static void	xfsidbg_xiclogall(xlog_in_core_t *);
    -static void	xfsidbg_xiclogcb(xlog_in_core_t *);
    -static void	xfsidbg_xihash(xfs_mount_t *mp);
    -static void	xfsidbg_xinodes(xfs_mount_t *);
    -static void	xfsidbg_delayed_blocks(xfs_mount_t *);
    -static void	xfsidbg_xinodes_quiesce(xfs_mount_t *);
    -static void	xfsidbg_xlog(xlog_t *);
    -static void	xfsidbg_xlog_ritem(xlog_recover_item_t *);
    -static void	xfsidbg_xlog_rtrans(xlog_recover_t *);
    -static void	xfsidbg_xlog_rtrans_entire(xlog_recover_t *);
    -static void	xfsidbg_xlog_tic(xlog_ticket_t *);
    -static void	xfsidbg_xlogitem(xfs_log_item_t *);
    -static void	xfsidbg_xmount(xfs_mount_t *);
    -static void	xfsidbg_xnode(xfs_inode_t *ip);
    -static void	xfsidbg_xcore(xfs_iocore_t *io);
    -static void	xfsidbg_xperag(xfs_mount_t *);
    -static void	xfsidbg_xqm_diskdq(xfs_disk_dquot_t *);
    -static void	xfsidbg_xqm_dqattached_inos(xfs_mount_t *);
    -static void	xfsidbg_xqm_dquot(xfs_dquot_t *);
    -static void	xfsidbg_xqm_mplist(xfs_mount_t *);
    -static void	xfsidbg_xqm_qinfo(xfs_mount_t *mp);
    -static void	xfsidbg_xqm_tpdqinfo(xfs_trans_t *tp);
    -static void	xfsidbg_xsb(xfs_sb_t *);
    -static void	xfsidbg_xsb_convert(xfs_sb_t *);
    -static void	xfsidbg_xtp(xfs_trans_t *);
    -static void	xfsidbg_xtrans_res(xfs_mount_t *);
    -#ifdef CONFIG_XFS_QUOTA
    -static void	xfsidbg_xqm(void);
    -static void	xfsidbg_xqm_htab(void);
    -static void	xfsidbg_xqm_freelist_print(xfs_frlist_t *qlist, char *title);
    -static void	xfsidbg_xqm_freelist(void);
    -#endif
    -
    -#ifdef XFS_BMAP_TRACE
    -static void	xfs_convert_extent(xfs_bmbt_rec_32_t *, xfs_dfiloff_t *,
    -				xfs_dfsbno_t *, xfs_dfilblks_t *, int *);
    -#endif
    -
    -/*
    - * Prototypes for static functions.
    - */
    -#ifdef XFS_ALLOC_TRACE
    -static int	xfs_alloc_trace_entry(ktrace_entry_t *ktep);
    -#endif
    -#ifdef XFS_ATTR_TRACE
    -static int	xfs_attr_trace_entry(ktrace_entry_t *ktep);
    -#endif
    -#ifdef XFS_BMAP_TRACE
    -static int	xfs_bmap_trace_entry(ktrace_entry_t *ktep);
    -#endif
    -#ifdef XFS_BMAP_TRACE
    -static int	xfs_bmbt_trace_entry(ktrace_entry_t *ktep);
    -#endif
    -#ifdef XFS_DIR_TRACE
    -static int	xfs_dir_trace_entry(ktrace_entry_t *ktep);
    -#endif
    -#ifdef XFS_DIR2_TRACE
    -static int	xfs_dir2_trace_entry(ktrace_entry_t *ktep);
    -#endif
    -#ifdef XFS_RW_TRACE
    -static void	xfs_bunmap_trace_entry(ktrace_entry_t   *ktep);
    -static void	xfs_rw_enter_trace_entry(ktrace_entry_t *ktep);
    -static void	xfs_page_trace_entry(ktrace_entry_t *ktep);
    -static int	xfs_rw_trace_entry(ktrace_entry_t *ktep);
    -#endif
    -static void	xfs_broot(xfs_inode_t *ip, xfs_ifork_t *f);
    -static void	xfs_btalloc(xfs_alloc_block_t *bt, int bsz);
    -static void	xfs_btbmap(xfs_bmbt_block_t *bt, int bsz);
    -static void	xfs_btino(xfs_inobt_block_t *bt, int bsz);
    -static void	xfs_buf_item_print(xfs_buf_log_item_t *blip, int summary);
    -static void	xfs_dastate_path(xfs_da_state_path_t *p);
    -static void	xfs_dir2data(void *addr, int size);
    -static void	xfs_dir2leaf(xfs_dir2_leaf_t *leaf, int size);
    -static void	xfs_dquot_item_print(xfs_dq_logitem_t *lip, int summary);
    -static void	xfs_efd_item_print(xfs_efd_log_item_t *efdp, int summary);
    -static void	xfs_efi_item_print(xfs_efi_log_item_t *efip, int summary);
    -static char *	xfs_fmtformat(xfs_dinode_fmt_t f);
    -char *		xfs_fmtfsblock(xfs_fsblock_t bno, xfs_mount_t *mp);
    -static char *	xfs_fmtino(xfs_ino_t ino, xfs_mount_t *mp);
    -static char *	xfs_fmtlsn(xfs_lsn_t *lsnp);
    -static char *	xfs_fmtmode(int m);
    -static char *	xfs_fmtsize(size_t i);
    -static char *	xfs_fmtuuid(uuid_t *);
    -static void	xfs_inode_item_print(xfs_inode_log_item_t *ilip, int summary);
    -static void	xfs_inodebuf(xfs_buf_t *bp);
    -static void	xfs_prdinode_core(xfs_dinode_core_t *dip);
    -static void	xfs_qoff_item_print(xfs_qoff_logitem_t *lip, int summary);
    -static void	xfs_xexlist_fork(xfs_inode_t *ip, int whichfork);
    -static void	xfs_xnode_fork(char *name, xfs_ifork_t *f);
    -
    -
    -/* kdb wrappers */
    -
    -static int	kdbm_xfs_xagf(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xagf((xfs_agf_t *)addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xagi(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xagi((xfs_agi_t *)addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xaildump(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xaildump((xfs_mount_t *) addr);
    -	return 0;
    -}
    -
    -#ifdef XFS_ALLOC_TRACE
    -static int	kdbm_xfs_xalatrace(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -	
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xalatrace((int) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xalbtrace(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xalbtrace((xfs_agblock_t) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xalgtrace(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xalgtrace((xfs_agnumber_t) addr);
    -	return 0;
    -}
    -#endif
    -
    -#ifdef XFS_ATTR_TRACE
    -static int	kdbm_xfs_xattrtrace(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xattrtrace((int) addr);
    -	return 0;
    -}
    -#endif
    -
    -#ifdef XFS_BLI_TRACE
    -static int	kdbm_xfs_xblitrace(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xblitrace((xfs_buf_log_item_t *) addr);
    -	return 0;
    -}
    -#endif
    -
    -#ifdef XFS_BMAP_TRACE
    -static int	kdbm_xfs_xbmatrace(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xbmatrace((int) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xbmitrace(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xbmitrace((xfs_inode_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xbmstrace(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xbmstrace((xfs_inode_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xbxatrace(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xbxatrace((int) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xbxitrace(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xbxitrace((xfs_inode_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xbxstrace(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xbxstrace((xfs_inode_t *) addr);
    -	return 0;
    -}
    -#endif
    -
    -#ifdef XFS_DIR2_TRACE
    -static int	kdbm_xfs_xdir2atrace(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xdir2atrace((int) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xdir2itrace(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xdir2itrace((xfs_inode_t *) addr);
    -	return 0;
    -}
    -#endif
    -
    -#ifdef XFS_DIR_TRACE
    -static int	kdbm_xfs_xdirtrace(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xdirtrace((int) addr);
    -	return 0;
    -}
    -#endif
    -
    -#ifdef XFS_LOG_TRACE
    -static int	kdbm_xfs_xiclogtrace(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xiclogtrace((xlog_in_core_t *) addr);
    -	return 0;
    -}
    -#endif
    -
    -#ifdef XFS_ILOCK_TRACE
    -static int	kdbm_xfs_xilock_trace(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xilock_trace((xfs_inode_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xailock_trace(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xailock_trace((int) addr);
    -	return 0;
    -}
    -#endif
    -
    -#ifdef XFS_LOG_TRACE
    -static int	kdbm_xfs_xlog_granttrace(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xlog_granttrace((xlog_t *) addr);
    -	return 0;
    -}
    -#endif
    -
    -#ifdef XFS_DQUOT_TRACE
    -static int	kdbm_xfs_xqm_dqtrace(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xqm_dqtrace((xfs_dquot_t *) addr);
    -	return 0;
    -}
    -#endif
    -
    -#ifdef XFS_RW_TRACE
    -static int	kdbm_xfs_xrwtrace(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long	addr;
    -	int		nextarg = 1;
    -	long 		offset = 0;
    -	int 		diag;
    -	ktrace_entry_t	*ktep;
    -	ktrace_snap_t	kts;
    -	xfs_inode_t	*ip;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	ip = (xfs_inode_t *) addr;
    -	if (ip->i_rwtrace == NULL) {
    -		qprintf("The inode trace buffer is not initialized\n");
    -		return 0;
    -	}
    -	qprintf("i_rwtrace = 0x%p\n", ip->i_rwtrace);
    -	ktep = ktrace_first(ip->i_rwtrace, &kts);
    -	while (ktep != NULL) {
    -		if (xfs_rw_trace_entry(ktep))
    -			qprintf("\n");
    -		ktep = ktrace_next(ip->i_rwtrace, &kts);
    -	}
    -	return 0;
    -}
    -#endif
    -
    -static int	kdbm_xfs_xalloc(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xalloc((xfs_alloc_arg_t *) addr);
    -	return 0;
    -}
    -
    -#ifdef XFS_ALLOC_TRACE
    -static int	kdbm_xfs_xalmtrace(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xalmtrace((xfs_mount_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xalttrace(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xalttrace((int) addr);
    -	return 0;
    -}
    -#endif /* XFS_ALLOC_TRACE */
    -
    -static int	kdbm_xfs_xattrcontext(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xattrcontext((xfs_attr_list_context_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xattrleaf(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xattrleaf((xfs_attr_leafblock_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xattrsf(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xattrsf((xfs_attr_shortform_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xbirec(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xbirec((xfs_bmbt_irec_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xbmalla(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xbmalla((xfs_bmalloca_t *)addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xbrec(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xbrec((xfs_bmbt_rec_64_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xbroot(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xbroot((xfs_inode_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xbroota(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xbroota((xfs_inode_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xbtcur(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xbtcur((xfs_btree_cur_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xbuf(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xbuf((xfs_buf_t *) addr);
    -	return 0;
    -}
    -
    -
    -static int	kdbm_xfs_xarg(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xarg((int) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xchksum(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xchksum((uint *) addr);
    -	return 0;
    -}
    -
    -
    -static int	kdbm_xfs_xchash(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xchash((xfs_mount_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xchashlist(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xchashlist((xfs_chashlist_t *) addr);
    -	return 0;
    -}
    -
    -
    -static int	kdbm_xfs_xdaargs(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xdaargs((xfs_da_args_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xdabuf(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xdabuf((xfs_dabuf_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xdanode(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xdanode((xfs_da_intnode_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xdastate(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xdastate((xfs_da_state_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xdirleaf(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xdirleaf((xfs_dir_leafblock_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xdirsf(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xdirsf((xfs_dir_shortform_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xdir2free(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xdir2free((xfs_dir2_free_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xdir2sf(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xdir2sf((xfs_dir2_sf_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xexlist(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xexlist((xfs_inode_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xflist(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xflist((xfs_bmap_free_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xhelp(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	if (argc != 0)
    -		return KDB_ARGCOUNT;
    -
    -	xfsidbg_xhelp();
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xiclog(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xiclog((xlog_in_core_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xiclogall(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xiclogall((xlog_in_core_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xiclogcb(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xiclogcb((xlog_in_core_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xihash(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xihash((xfs_mount_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xinodes(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xinodes((xfs_mount_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_delayed_blocks(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_delayed_blocks((xfs_mount_t *) addr);
    -	return 0;
    -}
    -
    -
    -static int	kdbm_xfs_xinodes_quiesce(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xinodes_quiesce((xfs_mount_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xlog(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xlog((xlog_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xlog_ritem(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xlog_ritem((xlog_recover_item_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xlog_rtrans(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xlog_rtrans((xlog_recover_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xlog_rtrans_entire(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xlog_rtrans_entire((xlog_recover_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xlog_tic(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xlog_tic((xlog_ticket_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xlogitem(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xlogitem((xfs_log_item_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xmount(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xmount((xfs_mount_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xnode(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xnode((xfs_inode_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xcore(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xcore((xfs_iocore_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xperag(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xperag((xfs_mount_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xqm_diskdq(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xqm_diskdq((xfs_disk_dquot_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xqm_dqattached_inos(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xqm_dqattached_inos((xfs_mount_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xqm_dquot(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xqm_dquot((xfs_dquot_t *) addr);
    -	return 0;
    -}
    -
    -#ifdef	CONFIG_XFS_QUOTA
    -static int	kdbm_xfs_xqm(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	if (argc != 0)
    -		return KDB_ARGCOUNT;
    -
    -	xfsidbg_xqm();
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xqm_freelist(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	if (argc != 0)
    -		return KDB_ARGCOUNT;
    -
    -	xfsidbg_xqm_freelist();
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xqm_htab(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	if (argc != 0)
    -		return KDB_ARGCOUNT;
    -
    -	xfsidbg_xqm_htab();
    -	return 0;
    -}
    -#endif
    -
    -static int	kdbm_xfs_xqm_mplist(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xqm_mplist((xfs_mount_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xqm_qinfo(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xqm_qinfo((xfs_mount_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xqm_tpdqinfo(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xqm_tpdqinfo((xfs_trans_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xsb(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	unsigned long convert=0;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1 && argc!=2)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -	if (argc==2) {
    -	    /* extra argument - conversion flag */
    -	    diag = kdbgetaddrarg(argc, argv, &nextarg, &convert, &offset, NULL, regs);
    -	    if (diag)
    -		    return diag;
    -	}
    -
    -	if (convert)
    -		xfsidbg_xsb_convert((xfs_sb_t *) addr);
    -	else
    -		xfsidbg_xsb((xfs_sb_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xtp(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xtp((xfs_trans_t *) addr);
    -	return 0;
    -}
    -
    -static int	kdbm_xfs_xtrans_res(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	xfsidbg_xtrans_res((xfs_mount_t *) addr);
    -	return 0;
    -}
    -
    -/*
    - * Vnode descriptor dump.
    - * This table is a string version of all the flags defined in vnode.h.
    - */
    -char *tab_vflags[] = {
    -	/* local only flags */
    -	"VINACT",		/*	 0x01 */
    -	"VRECLM",		/*	 0x02 */
    -	"VWAIT",		/*	 0x04 */
    -	"VMODIFIED",		/*	 0x08 */
    -	"INVALID0x10",		/*	 0x10 */
    -	"INVALID0x20",		/*	 0x20 */
    -	"INVALID0x40",		/*	 0x40 */
    -	"INVALID0x80",		/*	 0x80 */
    -	"INVALID0x100",		/*	0x100 */
    -	"INVALID0x200",		/*	0x200 */
    -	"INVALID0x400",		/*	0x400 */
    -	"INVALID0x800",		/*	0x800 */
    -	"INVALID0x1000",	/*     0x1000 */
    -	"INVALID0x2000",	/*     0x2000 */
    -	"INVALID0x4000",	/*     0x4000 */
    -	"INVALID0x8000",	/*     0x8000 */
    -	"INVALID0x10000",	/*    0x10000 */
    -	"INVALID0x20000",	/*    0x20000 */
    -	"INVALID0x40000",	/*    0x40000 */
    -	"INVALID0x80000",	/*    0x80000 */
    -	"VROOT",		/*   0x100000 */
    -	"INVALID0x200000",	/*   0x200000 */
    -	"INVALID00x400000",	/*   0x400000 */
    -	"INVALID0x800000",	/*   0x800000 */
    -	"INVALID0x1000000",	/*  0x1000000 */
    -	"INVALID0x2000000",	/*  0x2000000 */
    -	"VSHARE",		/*  0x4000000 */
    -	"INVALID0x8000000",     /*  0x8000000 */
    -	"VENF_LOCKING",		/* 0x10000000 */
    -	"VOPLOCK",		/* 0x20000000 */
    -	"VPURGE",		/* 0x40000000 */
    -	"INVALID0x80000000",	/* 0x80000000 */
    -	NULL
    -};
    -
    -static void
    -printflags(register uint64_t flags,
    -	register char **strings,
    -	register char *name)
    -{
    -	register uint64_t mask = 1;
    -
    -	if (name)
    -		kdb_printf("%s 0x%llx <", name, (unsigned long long)flags);
    -
    -	while (flags != 0 && *strings) {
    -		if (mask & flags) {
    -			kdb_printf("%s ", *strings);
    -			flags &= ~mask;
    -		}
    -		mask <<= 1;
    -		strings++;
    -	}
    -
    -	if (name)
    -		kdb_printf("> ");
    -
    -	return;
    -}
    -
    -
    -static void printbhv(bhv_desc_t *bdp)
    -{
    -	int maxbhv = 20; /* if you get 20 bhvs you're in trouble already */
    -	kdb_symtab_t	 symtab;
    -
    -	if (bdp == NULL) {
    -		kdb_printf("NULL bhv\n");
    -		return;
    -	}
    -
    -	kdb_printf("bhv at 0x%p\n", bdp);
    -	while (bdp && maxbhv--) {
    -		if (kdbnearsym((unsigned long)bdp->bd_ops, &symtab))
    -			kdb_printf("  ops %s", symtab.sym_name);
    -		else
    -			kdb_printf("  ops %s/0x%p", "???", (void *)bdp->bd_ops);
    -
    -		kdb_printf(" vobj 0x%p pdata 0x%p next 0x%p\n",
    -			   bdp->bd_vobj, bdp->bd_pdata, bdp->bd_next);
    -
    -		bdp = bdp->bd_next;
    -	}
    -}
    -
    -
    -static void	printvnode(xfs_vnode_t *vp, unsigned long addr)
    -{
    -	kdb_printf("vnode: 0x%lx\n", addr);
    -	kdb_printf(" v_bh 0x%p\n", &vp->v_bh);
    -
    -	printbhv(vp->v_fbhv);
    -
    -	printflags((__psunsigned_t)vp->v_flag, tab_vflags, "flag =");
    -	kdb_printf("\n");
    -
    -#ifdef	XFS_VNODE_TRACE
    -	kdb_printf("   v_trace 0x%p\n", vp->v_trace);
    -#endif	/* XFS_VNODE_TRACE */
    -
    -	kdb_printf("   v_vfsp 0x%p v_number 0x%llx\n",
    -		vp->v_vfsp, (unsigned long long)vp->v_number);
    -}
    -
    -static int	kdbm_vnode(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -	xfs_vnode_t	vp;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -
    -	if (diag)
    -		return diag;
    -
    -	if ((diag = kdb_getarea(vp, addr)))
    -		return diag;
    -
    -	printvnode(&vp, addr);
    -
    -	return 0;
    -}
    -
    -static void
    -print_vfs(xfs_vfs_t	*vfs, unsigned long addr)
    -{
    -	kdb_printf("vfsp at 0x%lx", addr);
    -	kdb_printf(" vfs_flag 0x%x\n", vfs->vfs_flag);
    -	kdb_printf(" vfs_mp 0x%p", vfs->vfs_mp);
    -	kdb_printf(" vfs_bh 0x%p\n", &vfs->vfs_bh);
    -
    -	printbhv(vfs->vfs_fbhv);
    -}
    -
    -static int	kdbm_bhv(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -	bhv_desc_t	*bh;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -
    -	if (diag)
    -		return diag;
    -
    -	bh = (bhv_desc_t *)addr;
    -
    -	printbhv(bh);
    -
    -	return 0;
    -}
    -
    -static int	kdbm_vfs(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long addr;
    -	int nextarg = 1;
    -	long offset = 0;
    -	int diag;
    -	xfs_vfs_t		vfs;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -
    -	if (diag)
    -		return diag;
    -
    -	if ((diag = kdb_getarea(vfs, addr)))
    -		return diag;
    -
    -	print_vfs(&vfs, addr);
    -
    -	return 0;
    -}
    -
    -
    -#ifdef	XFS_VNODE_TRACE
    -/*
    - * Print a vnode trace entry.
    - */
    -static int
    -vn_trace_pr_entry(ktrace_entry_t *ktep)
    -{
    -	char		funcname[128];
    -	kdb_symtab_t	symtab;
    -
    -
    -	if ((__psint_t)ktep->val[0] == 0)
    -		return 0;
    -
    -	if (kdbnearsym((unsigned int)ktep->val[8], &symtab)) {
    -		unsigned long offval;
    -
    -		offval = (unsigned int)ktep->val[8] - symtab.sym_start;
    -
    -		if (offval)
    -			sprintf(funcname, "%s+0x%lx", symtab.sym_name, offval);
    -		else
    -			sprintf(funcname, "%s", symtab.sym_name);
    -	} else
    -		funcname[0] = '\0';
    -
    -
    -	switch ((__psint_t)ktep->val[0]) {
    -	case VNODE_KTRACE_ENTRY:
    -		kdb_printf("entry to %s i_count = %d",
    -						(char *)ktep->val[1],
    -						(__psint_t)ktep->val[3]);
    -		break;
    -
    -	case VNODE_KTRACE_EXIT:
    -		kdb_printf("exit from %s i_count = %d",
    -						(char *)ktep->val[1],
    -						(__psint_t)ktep->val[3]);
    -		break;
    -
    -	case VNODE_KTRACE_HOLD:
    -		if ((__psint_t)ktep->val[3] != 1)
    -			kdb_printf("hold @%s:%d(%s) i_count %d => %d ",
    -						(char *)ktep->val[1],
    -						(__psint_t)ktep->val[2],
    -						funcname,
    -						(__psint_t)ktep->val[3] - 1,
    -						(__psint_t)ktep->val[3]);
    -		else
    -			kdb_printf("get @%s:%d(%s) i_count = %d",
    -						(char *)ktep->val[1],
    -						(__psint_t)ktep->val[2],
    -						funcname,
    -						(__psint_t)ktep->val[3]);
    -		break;
    -
    -	case VNODE_KTRACE_REF:
    -		kdb_printf("ref @%s:%d(%s) i_count = %d",
    -						(char *)ktep->val[1],
    -						(__psint_t)ktep->val[2],
    -						funcname,
    -						(__psint_t)ktep->val[3]);
    -		break;
    -
    -	case VNODE_KTRACE_RELE:
    -		if ((__psint_t)ktep->val[3] != 1)
    -			kdb_printf("rele @%s:%d(%s) i_count %d => %d ",
    -						(char *)ktep->val[1],
    -						(__psint_t)ktep->val[2],
    -						funcname,
    -						(__psint_t)ktep->val[3],
    -						(__psint_t)ktep->val[3] - 1);
    -		else
    -			kdb_printf("free @%s:%d(%s) i_count = %d",
    -						(char *)ktep->val[1],
    -						(__psint_t)ktep->val[2],
    -						funcname,
    -						(__psint_t)ktep->val[3]);
    -		break;
    -
    -	default:
    -		kdb_printf("unknown vntrace record\n");
    -		return 1;
    -	}
    -
    -	kdb_printf("\n");
    -
    -	kdb_printf("  cpu = %d pid = %d ",
    -			(__psint_t)ktep->val[6], (pid_t)ktep->val[7]);
    -
    -	printflags((__psunsigned_t)ktep->val[5], tab_vflags, "flag =");
    -
    -	if (kdbnearsym((unsigned int)ktep->val[4], &symtab)) {
    -		unsigned long offval;
    -
    -		offval = (unsigned int)ktep->val[4] - symtab.sym_start;
    -
    -		if (offval)
    -			kdb_printf("  ra = %s+0x%lx", symtab.sym_name, offval);
    -		else
    -			kdb_printf("  ra = %s", symtab.sym_name);
    -	} else
    -		kdb_printf("  ra = ?? 0x%p", (void *)ktep->val[4]);
    -
    -	return 1;
    -}
    -
    -
    -/*
    - * Print out the trace buffer attached to the given vnode.
    - */
    -static int	kdbm_vntrace(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	int		diag;
    -	int		nextarg = 1;
    -	long		offset = 0;
    -	unsigned long	addr;
    -	xfs_vnode_t	*vp;
    -	ktrace_entry_t	*ktep;
    -	ktrace_snap_t	kts;
    -
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -
    -	if (diag)
    -		return diag;
    -
    -	vp = (xfs_vnode_t *)addr;
    -
    -	if (vp->v_trace == NULL) {
    -		kdb_printf("The vnode trace buffer is not initialized\n");
    -
    -		return 0;
    -	}
    -
    -	kdb_printf("vntrace vp 0x%p\n", vp);
    -
    -	ktep = ktrace_first(vp->v_trace, &kts);
    -
    -	while (ktep != NULL) {
    -		if (vn_trace_pr_entry(ktep))
    -			kdb_printf("\n");
    -
    -		ktep = ktrace_next(vp->v_trace, &kts);
    -	}
    -
    -	return 0;
    -}
    -/*
    - * Print out the trace buffer attached to the given vnode.
    - */
    -static int	kdbm_vntraceaddr(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	int		diag;
    -	int		nextarg = 1;
    -	long		offset = 0;
    -	unsigned long	addr;
    -	struct ktrace	*kt;
    -	ktrace_entry_t	*ktep;
    -	ktrace_snap_t	kts;
    -
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -
    -	if (diag)
    -		return diag;
    -
    -	kt = (struct ktrace *)addr;
    -
    -	kdb_printf("vntraceaddr kt 0x%p\n", kt);
    -
    -	ktep = ktrace_first(kt, &kts);
    -
    -	while (ktep != NULL) {
    -		if (vn_trace_pr_entry(ktep))
    -			kdb_printf("\n");
    -
    -		ktep = ktrace_next(kt, &kts);
    -	}
    -
    -	return 0;
    -}
    -#endif	/* XFS_VNODE_TRACE */
    -
    -#ifdef __linux__
    -static void	printinode(struct inode *ip)
    -{
    -	unsigned long	addr;
    -
    -
    -	if (ip == NULL)
    -		return;
    -
    -	kdb_printf(" i_ino = %lu i_count = %u i_size %Ld\n",
    -					ip->i_ino, atomic_read(&ip->i_count),
    -					ip->i_size);
    -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
    -	kdb_printf(
    -		" i_mode = 0x%x  i_nlink = %d  i_rdev = 0x%x i_state = 0x%lx\n",
    -					ip->i_mode, ip->i_nlink,
    -					kdev_t_to_nr(ip->i_rdev), ip->i_state);
    -	kdb_printf(" i_hash.nxt = 0x%p i_hash.pprv = 0x%p\n",
    -                                        ip->i_hash.next, ip->i_hash.prev);
    -#else
    -	kdb_printf(
    -		" i_mode = 0x%x  i_nlink = %d  i_rdev = 0x%x i_state = 0x%lx\n",
    -					ip->i_mode, ip->i_nlink,
    -					ip->i_rdev, ip->i_state);
    -	kdb_printf(" i_hash.nxt = 0x%p i_hash.pprv = 0x%p\n",
    -                                        ip->i_hash.next, ip->i_hash.pprev);
    -#endif
    -	kdb_printf(" i_list.nxt = 0x%p i_list.prv = 0x%p\n",
    -					ip->i_list.next, ip->i_list.prev);
    -	kdb_printf(" i_dentry.nxt = 0x%p i_dentry.prv = 0x%p\n",
    -					ip->i_dentry.next,
    -					ip->i_dentry.prev);
    -
    -	addr = (unsigned long)ip;
    -
    -	kdb_printf(" i_sb = 0x%p i_op = 0x%p i_data = 0x%lx nrpages = %lu\n",
    -					ip->i_sb, ip->i_op,
    -					addr + offsetof(struct inode, i_data),
    -					ip->i_data.nrpages);
    -
    -	kdb_printf("  vnode ptr 0x%p\n", vn_from_inode(ip));
    -}
    -
    -#endif
    -
    -
    -static int	kdbm_vn(
    -	int	argc,
    -	const char **argv,
    -	const char **envp,
    -	struct pt_regs *regs)
    -{
    -	int		diag;
    -	int		nextarg = 1;
    -	long		offset = 0;
    -	unsigned long	addr;
    -#ifdef __linux__
    -	struct inode	*ip;
    -#endif
    -	xfs_vnode_t	vp;
    -#ifdef	XFS_VNODE_TRACE
    -	ktrace_entry_t	*ktep;
    -	ktrace_snap_t	kts;
    -#endif
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -
    -	diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs);
    -	if (diag)
    -		return diag;
    -
    -	if ((diag = kdb_getarea(vp, addr)))
    -		return diag;
    -
    -#ifdef __linux__
    -	ip = vn_to_inode((vnode_t *)addr);
    -	kdb_printf("--> Inode @ 0x%p\n", ip);
    -	printinode(ip);
    -#endif
    -
    -	kdb_printf("--> Vnode @ 0x%lx\n", addr);
    -	printvnode(&vp, addr);
    -
    -#ifdef	XFS_VNODE_TRACE
    -	kdb_printf("--> Vntrace @ 0x%lx/0x%p\n", addr, vp.v_trace);
    -	if (vp.v_trace == NULL)
    -		return 0;
    -	ktep = ktrace_first(vp.v_trace, &kts);
    -	while (ktep != NULL) {
    -		if (vn_trace_pr_entry(ktep))
    -			kdb_printf("\n");
    -
    -		ktep = ktrace_next(vp.v_trace, &kts);
    -	}
    -#endif	/* XFS_VNODE_TRACE */
    -	return 0;
    -}
    -
    -
    -#ifdef __linux__
    -
    -static char	*bp_flag_vals[] = {
    -/*  0 */ "READ", "WRITE", "MAPPED", "PARTIAL", "ASYNC",
    -/*  5 */ "NONE", "DELWRI",  "STALE", "FS_MANAGED", "FS_DATAIOD",
    -/* 10 */ "FORCEIO", "FLUSH", "READ_AHEAD", "DIRECTIO", "LOCK",
    -/* 15 */ "TRYLOCK", "DONT_BLOCK", "PAGE_CACHE", "KMEM_ALLOC", "RUN_QUEUES",
    -/* 20 */ "PRIVATE_BH", "DELWRI_Q",
    -	 NULL };
    -
    -#endif
    -
    -static char	*iomap_flag_vals[] = {
    -	"EOF", "HOLE", "DELAY", "INVALID0x08",
    -	"INVALID0x10", "UNWRITTEN", "NEW", "INVALID0x80",
    -	NULL };
    -
    -
    -static char	*map_flags(unsigned long flags, char *mapping[])
    -{
    -	static	char	buffer[256];
    -	int	index;
    -	int	offset = 12;
    -
    -	buffer[0] = '\0';
    -
    -	for (index = 0; flags && mapping[index]; flags >>= 1, index++) {
    -		if (flags & 1) {
    -			if ((offset + strlen(mapping[index]) + 1) >= 80) {
    -				strcat(buffer, "\n	    ");
    -				offset = 12;
    -			} else if (offset > 12) {
    -				strcat(buffer, " ");
    -				offset++;
    -			}
    -			strcat(buffer, mapping[index]);
    -			offset += strlen(mapping[index]);
    -		}
    -	}
    -
    -	return (buffer);
    -}
    -
    -#ifdef __linux__
    -
    -static char	*bp_flags(xfs_buf_flags_t bp_flag)
    -{
    -	return(map_flags((unsigned long) bp_flag, bp_flag_vals));
    -}
    -
    -static int
    -kdbm_bp_flags(int argc, const char **argv, const char **envp, struct pt_regs *regs)
    -{
    -	unsigned long flags;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -
    -	diag = kdbgetularg(argv[1], &flags);
    -	if (diag)
    -		return diag;
    -
    -	kdb_printf("bp flags 0x%lx = %s\n", flags, bp_flags(flags));
    -
    -	return 0;
    -}
    -
    -static void
    -print_xfs_buf(
    -	xfs_buf_t	*bp,
    -	unsigned long	addr)
    -{
    -	unsigned long	age = (xfs_buf_age_centisecs * HZ) / 100;
    -
    -	kdb_printf("xfs_buf_t at 0x%lx\n", addr);
    -	kdb_printf("  b_flags %s\n", bp_flags(bp->b_flags));
    -	kdb_printf("  b_target 0x%p b_hold %d b_next 0x%p b_prev 0x%p\n",
    -		   bp->b_target, bp->b_hold.counter,
    -		   list_entry(bp->b_list.next, xfs_buf_t, b_list),
    -		   list_entry(bp->b_list.prev, xfs_buf_t, b_list));
    -	kdb_printf("  b_hash 0x%p b_hash_next 0x%p b_hash_prev 0x%p\n",
    -		   bp->b_hash,
    -		   list_entry(bp->b_hash_list.next, xfs_buf_t, b_hash_list),
    -		   list_entry(bp->b_hash_list.prev, xfs_buf_t, b_hash_list));
    -	kdb_printf("  b_file_offset 0x%llx b_buffer_length 0x%llx b_addr 0x%p\n",
    -		   (unsigned long long) bp->b_file_offset,
    -		   (unsigned long long) bp->b_buffer_length,
    -		   bp->b_addr);
    -	kdb_printf("  b_bn 0x%llx b_count_desired 0x%lx b_locked %d\n",
    -		   (unsigned long long)bp->b_bn,
    -		   (unsigned long) bp->b_count_desired, (int)bp->b_locked);
    -	kdb_printf("  b_queuetime %ld (now=%ld/age=%ld) b_io_remaining %d\n",
    -		   bp->b_queuetime, jiffies, bp->b_queuetime + age,
    -		   bp->b_io_remaining.counter);
    -	kdb_printf("  b_page_count %u b_offset 0x%x b_pages 0x%p b_error %u\n",
    -		   bp->b_page_count, bp->b_offset,
    -		   bp->b_pages, bp->b_error);
    -	kdb_printf("  b_iodonesema (%d,%d) b_sema (%d,%d) b_pincount (%d)\n",
    -		   bp->b_iodonesema.count.counter,
    -		   bp->b_iodonesema.sleepers,
    -		   bp->b_sema.count.counter, bp->b_sema.sleepers,
    -		   bp->b_pin_count.counter);
    -#ifdef XFS_BUF_LOCK_TRACKING
    -	kdb_printf("  last holder %d\n", bp->b_last_holder);
    -#endif
    -	if (bp->b_fspriv || bp->b_fspriv2) {
    -		kdb_printf(  "  b_fspriv 0x%p b_fspriv2 0x%p\n",
    -			   bp->b_fspriv, bp->b_fspriv2);
    -	}
    -}
    -
    -static int
    -kdbm_bp(int argc, const char **argv, const char **envp, struct pt_regs *regs)
    -{
    -	xfs_buf_t bp;
    -	unsigned long addr;
    -	long	offset=0;
    -	int nextarg;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -
    -	nextarg = 1;
    -	if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs)) ||
    -	    (diag = kdb_getarea(bp, addr)))
    -		return diag;
    -
    -	print_xfs_buf(&bp, addr);
    -
    -	return 0;
    -}
    -
    -static int
    -kdbm_bpdelay(int argc, const char **argv, const char **envp,
    -	struct pt_regs *regs)
    -{
    -#ifdef DEBUG
    -	extern struct list_head xfs_buftarg_list;
    -	struct list_head	*curr, *next;
    -	xfs_buftarg_t		*tp, *n;
    -	xfs_buf_t		bp;
    -	unsigned long		addr, verbose = 0;
    -	int			diag, count = 0;
    -
    -	if (argc > 1)
    -		return KDB_ARGCOUNT;
    -
    -	if (argc == 1) {
    -		if ((diag = kdbgetularg(argv[1], &verbose))) {
    -			return diag;
    -		}
    -	}
    -
    -	if (!verbose) {
    -		kdb_printf("index bp       pin   queuetime\n");
    -	}
    -
    -
    -	list_for_each_entry_safe(tp, n, &xfs_buftarg_list, bt_list) {
    -		list_for_each_safe(curr, next, &tp->bt_delwrite_queue) {
    -			addr = (unsigned long)list_entry(curr, xfs_buf_t, b_list);
    -			if ((diag = kdb_getarea(bp, addr)))
    -				return diag;
    -
    -			if (verbose) {
    -				print_xfs_buf(&bp, addr);
    -			} else {
    -				kdb_printf("%4d  0x%lx   %d   %ld\n",
    -					count++, addr,
    -					bp.b_pin_count.counter,
    -					bp.b_queuetime);
    -			}
    -		}
    -	}
    -#else
    -	kdb_printf("bt_delwrite_queue inaccessible (non-debug)\n");
    -#endif
    -	return 0;
    -}
    -#endif
    -
    -static int
    -kdbm_iomap(int argc, const char **argv, const char **envp,
    -	struct pt_regs *regs)
    -{
    -	xfs_iomap_t iomap;
    -	unsigned long addr;
    -	long offset=0;
    -	int nextarg;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -
    -	nextarg = 1;
    -	if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs)))
    -		return diag;
    -	if ((diag = kdb_getarea(iomap, addr)))
    -		return diag;
    -
    -	kdb_printf("iomap_t at 0x%lx\n", addr);
    -	kdb_printf("  bn 0x%llx offset 0x%Lx delta 0x%lx bsize 0x%llx\n",
    -		(long long) iomap.iomap_bn, iomap.iomap_offset,
    -		(unsigned long)iomap.iomap_delta, (long long)iomap.iomap_bsize);
    -	kdb_printf("  iomap_flags %s\n",
    -		map_flags(iomap.iomap_flags, iomap_flag_vals));
    -
    -	return 0;
    -}
    -
    -static int
    -kdbm_i2vnode(int argc, const char **argv, const char **envp,
    -	struct pt_regs *regs)
    -{
    -	struct vnode vp;
    -	struct inode *ip;
    -	unsigned long addr;
    -	long offset=0;
    -	int nextarg;
    -	int diag;
    -
    -	if (argc != 1)
    -		return KDB_ARGCOUNT;
    -
    -	nextarg = 1;
    -	if ((diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs)))
    -		return diag;
    -	ip = (struct inode *)addr;
    -	if ((diag = kdb_getarea(vp, (unsigned long)vn_from_inode(ip))))
    -		return diag;
    -
    -	kdb_printf("--> Inode @ 0x%p\n", ip);
    -	printinode(ip);
    -
    -	kdb_printf("--> Vnode @ 0x%p\n", vn_from_inode(ip));
    -	printvnode(&vp, (unsigned long)vn_from_inode(ip));
    -
    -	return 0;
    -}
    -
    -#ifdef XFS_BUF_TRACE
    -static int xfs_buf_trace_entry(ktrace_entry_t *ktep)
    -{
    -	unsigned long long daddr;
    -
    -	daddr = ((unsigned long long)(unsigned long)ktep->val[8] << 32)
    -		| ((unsigned long long)(unsigned long)ktep->val[9]);
    -
    -	kdb_printf("bp 0x%p [%s] (hold %lu lock %ld) data 0x%p",
    -		ktep->val[0],
    -		(char *)ktep->val[1],
    -		(unsigned long)ktep->val[3],
    -		(long)ktep->val[4],
    -		ktep->val[6]);
    -	kdb_symbol_print((unsigned long)ktep->val[7], NULL,
    -		KDB_SP_SPACEB|KDB_SP_PAREN|KDB_SP_NEWLINE);
    -	kdb_printf("    offset 0x%llx size 0x%lx task 0x%p\n",
    -		daddr, (long)ktep->val[10], ktep->val[5]);
    -	kdb_printf("    flags: %s\n", bp_flags((int)(long)ktep->val[2]));
    -	return 1;
    -}
    -
    -static int
    -kdbm_bptrace_offset(int argc, const char **argv, const char **envp,
    -	struct pt_regs *regs)
    -{
    -	long		mask = 0;
    -	unsigned long	got_offset = 0, offset = 0;
    -	int		diag;
    -	ktrace_entry_t	*ktep;
    -	ktrace_snap_t	kts;
    -
    -	if (argc > 2)
    -		return KDB_ARGCOUNT;
    -
    -	if (argc > 0) {
    -		diag = kdbgetularg(argv[1], &offset);
    -		if (diag)
    -			return diag;
    -		got_offset = 1;		/* allows tracing offset zero */
    -	}
    -
    -	if (argc > 1) {
    -		diag = kdbgetularg(argv[1], &mask);	/* sign extent mask */
    -		if (diag)
    -			return diag;
    -	}
    -
    -	ktep = ktrace_first(xfs_buf_trace_buf, &kts);
    -	do {
    -		unsigned long long daddr;
    -
    -		if (ktep == NULL)
    -			break;
    -		daddr = ((unsigned long long)(unsigned long)ktep->val[8] << 32)
    -			| ((unsigned long long)(unsigned long)ktep->val[9]);
    -		if (got_offset && ((daddr & ~mask) != offset))
    -			continue;
    -		if (xfs_buf_trace_entry(ktep))
    -			kdb_printf("\n");
    -	} while ((ktep = ktrace_next(xfs_buf_trace_buf, &kts)) != NULL);
    -	return 0;
    -}
    -
    -static int
    -kdbm_bptrace(int argc, const char **argv, const char **envp,
    -	struct pt_regs *regs)
    -{
    -	unsigned long	addr = 0;
    -	int		diag, nextarg;
    -	long		offset = 0;
    -	char		*event_match = NULL;
    -	ktrace_entry_t	*ktep;
    -	ktrace_snap_t	kts;
    -
    -	if (argc > 1)
    -		return KDB_ARGCOUNT;
    -
    -	if (argc == 1) {
    -		if (isupper(argv[1][0]) || islower(argv[1][0])) {
    -			event_match = (char *)argv[1];
    -			kdb_printf("event match on \"%s\"\n", event_match);
    -			argc = 0;
    -		} else {
    -			nextarg = 1;
    -			diag = kdbgetaddrarg(argc, argv,
    -					&nextarg, &addr, &offset, NULL, regs);
    -			if (diag) {
    -				kdb_printf("non-numeric arg: %s\n", argv[1]);
    -				return diag;
    -			}
    -		}
    -	}
    -
    -	ktep = ktrace_first(xfs_buf_trace_buf, &kts);
    -	do {
    -		if (ktep == NULL)
    -			break;
    -		if (addr && (ktep->val[0] != (void *)addr))
    -			continue;
    -		if (event_match && strcmp((char *)ktep->val[1], event_match))
    -			continue;
    -		if (xfs_buf_trace_entry(ktep))
    -			qprintf("\n");
    -	} while ((ktep = ktrace_next(xfs_buf_trace_buf, &kts)) != NULL);
    -
    -	return 0;
    -}
    -#endif
    -
    -struct xif {
    -	char	*name;
    -	int	(*func)(int, const char **, const char **, struct pt_regs *);
    -	char	*args;
    -	char	*help;
    -};
    -
    -static struct xif xfsidbg_funcs[] = {
    -  {  "bhv",	kdbm_bhv,	"", "Dump bhv chain"},
    -  {  "vn",	kdbm_vn,	"", "Dump inode/vnode/trace"},
    -  {  "vnode",	kdbm_vnode,	"", "Dump vnode"},
    -  {  "vfs",	kdbm_vfs,	"", "Dump vfs"},
    -#ifdef XFS_VNODE_TRACE
    -  {  "vntrace",	kdbm_vntrace,	"", "Dump vnode Trace"},
    -  {  "vntraceaddr",	kdbm_vntraceaddr, "",
    -				"Dump vnode Trace by Address"},
    -#endif
    -  {  "xagf",	kdbm_xfs_xagf,	"",
    -				"Dump XFS allocation group freespace" },
    -  {  "xagi",	kdbm_xfs_xagi,	"",
    -				"Dump XFS allocation group inode" },
    -  {  "xail",	kdbm_xfs_xaildump,	"",
    -				"Dump XFS AIL for a mountpoint" },
    -#ifdef XFS_ALLOC_TRACE
    -  {  "xalatrc",	kdbm_xfs_xalatrace,	"",
    -				"Dump XFS alloc count trace" },
    -  {  "xalbtrc",	kdbm_xfs_xalbtrace,	"",
    -				"Dump XFS alloc block trace" },
    -  {  "xalgtrc",	kdbm_xfs_xalgtrace,	"",
    -				"Dump XFS alloc alloc-group trace" },
    -#endif
    -
    -  {  "xalloc",	kdbm_xfs_xalloc,	"",
    -				"Dump XFS allocation args structure" },
    -#ifdef XFS_ALLOC_TRACE
    -  {  "xalmtrc",	kdbm_xfs_xalmtrace,	"",
    -				"Dump XFS alloc mount-point trace" },
    -  {  "xalttrc",	kdbm_xfs_xalttrace,	"",
    -				"Dump XFS alloc trace by tag number" },
    -#endif
    -  {  "xarg",	kdbm_xfs_xarg,		"",
    -				"Input XFS argument for next function" },
    -  {  "xattrcx",	kdbm_xfs_xattrcontext,	"",
    -				"Dump XFS attr_list context struct"},
    -  {  "xattrlf",	kdbm_xfs_xattrleaf,	"",
    -				"Dump XFS attribute leaf block"},
    -  {  "xattrsf",	kdbm_xfs_xattrsf,	"",
    -				"Dump XFS attribute shortform"},
    -#ifdef XFS_ATTR_TRACE
    -  {  "xattrtr",	kdbm_xfs_xattrtrace,	"",
    -				"Dump XFS attribute attr_list() trace" },
    -#endif
    -  {  "xbirec",	kdbm_xfs_xbirec,	"",
    -				"Dump XFS buf log item trace" },
    -#endif
    -  {  "xbmalla",	kdbm_xfs_xbmalla,	"",
    -				"Dump XFS bmalloc args structure"},
    -#ifdef XFS_BMAP_TRACE
    -  {  "xbmatrc",	kdbm_xfs_xbmatrace,	"",
    -				"Dump XFS bmap btree count trace" },
    -  {  "xbmitrc",	kdbm_xfs_xbmitrace,	"",
    -				"Dump XFS bmap btree per-inode trace" },
    -  {  "xbmstrc",	kdbm_xfs_xbmstrace,	"",
    -				"Dump XFS bmap btree inode trace" },
    -#endif
    -  {  "xbrec",	kdbm_xfs_xbrec,		"",
    -				"Dump XFS bmap record"},
    -  {  "xbroot",	kdbm_xfs_xbroot,	"",
    -				"Dump XFS bmap btree root (data)"},
    -  {  "xbroota",	kdbm_xfs_xbroota,	"",
    -				"Dump XFS bmap btree root (attr)"},
    -  {  "xbtcur",	kdbm_xfs_xbtcur,	"",
    -				"Dump XFS btree cursor"},
    -  {  "xbuf",	kdbm_xfs_xbuf,		"",
    -				"Dump XFS data from a buffer"},
    -#ifdef XFS_BMAP_TRACE
    -  {  "xbxatrc",	kdbm_xfs_xbxatrace,	"",
    -				"Dump XFS bmap extent count trace" },
    -  {  "xbxitrc",	kdbm_xfs_xbxitrace,	"",
    -				"Dump XFS bmap extent per-inode trace" },
    -  {  "xbxstrc",	kdbm_xfs_xbxstrace,	"",
    -				"Dump XFS bmap extent inode trace" },
    -#endif
    -  {  "xchash",	kdbm_xfs_xchash,	"",
    -				"Dump XFS cluster hash"},
    -  {  "xchlist",	kdbm_xfs_xchashlist,	"",
    -				"Dump XFS cluster hash list"},
    -  {  "xchksum",	kdbm_xfs_xchksum,	"", "Dump chksum" },
    -#ifdef XFS_DIR2_TRACE
    -  {  "xd2atrc",	kdbm_xfs_xdir2atrace,	"",
    -				"Dump XFS directory v2 count trace" },
    -#endif
    -  {  "xd2free",	kdbm_xfs_xdir2free,	"",
    -				"Dump XFS directory v2 freemap"},
    -#ifdef XFS_DIR2_TRACE
    -  {  "xd2itrc",	kdbm_xfs_xdir2itrace,	"",
    -				"Dump XFS directory v2 per-inode trace" },
    -#endif
    -  {  "xdaargs",	kdbm_xfs_xdaargs,	"",
    -				"Dump XFS dir/attr args structure"},
    -  {  "xdabuf",	kdbm_xfs_xdabuf,	"",
    -				"Dump XFS dir/attr buf structure"},
    -  {  "xdanode",	kdbm_xfs_xdanode,	"",
    -				"Dump XFS dir/attr node block"},
    -  {  "xdastat",	kdbm_xfs_xdastate,	"",
    -				"Dump XFS dir/attr state_blk struct"},
    -  {  "xdelay",	kdbm_xfs_delayed_blocks,	"",
    -				"Dump delayed block totals"},
    -  {  "xdirlf",	kdbm_xfs_xdirleaf,	"",
    -				"Dump XFS directory leaf block"},
    -  {  "xdirsf",	kdbm_xfs_xdirsf,	"",
    -				"Dump XFS directory shortform"},
    -  {  "xdir2sf",	kdbm_xfs_xdir2sf,	"",
    -				"Dump XFS directory v2 shortform"},
    -#ifdef XFS_DIR_TRACE
    -  {  "xdirtrc",	kdbm_xfs_xdirtrace,	"",
    -				"Dump XFS directory getdents() trace" },
    -#endif
    -  {  "xdiskdq",	kdbm_xfs_xqm_diskdq,	"",
    -				"Dump XFS ondisk dquot (quota) struct"},
    -  {  "xdqatt",	kdbm_xfs_xqm_dqattached_inos,	"",
    -				 "All incore inodes with dquots"},
    -  {  "xdqinfo",	kdbm_xfs_xqm_tpdqinfo,	"",
    -				"Dump dqinfo structure of a trans"},
    -#ifdef XFS_DQUOT_TRACE
    -  {  "xdqtrace",kdbm_xfs_xqm_dqtrace,	"",
    -				"Dump trace of a given dquot" },
    -#endif
    -  {  "xdquot",	kdbm_xfs_xqm_dquot,	"",
    -				"Dump XFS dquot (quota) structure"},
    -  {  "xexlist",	kdbm_xfs_xexlist,	"",
    -				"Dump XFS bmap extents in inode"},
    -  {  "xflist",	kdbm_xfs_xflist,	"",
    -				"Dump XFS to-be-freed extent records"},
    -  {  "xhelp",	kdbm_xfs_xhelp,		"",
    -				"Print idbg-xfs help"},
    -  {  "xicall",	kdbm_xfs_xiclogall,	"",
    -				"Dump All XFS in-core logs"},
    -  {  "xiclog",	kdbm_xfs_xiclog,	"",
    -				"Dump XFS in-core log"},
    -#ifdef XFS_LOG_TRACE
    -  {  "xictrc",	kdbm_xfs_xiclogtrace,	"",
    -				"Dump XFS in-core log trace" },
    -#endif
    -  {  "xihash",	kdbm_xfs_xihash,	"",
    -				"Dump XFS inode hash statistics"},
    -#ifdef XFS_ILOCK_TRACE
    -  {  "xilocktrc",kdbm_xfs_xilock_trace,	"",
    -				"Dump XFS ilock trace" },
    -  {  "xailcktrc",kdbm_xfs_xailock_trace,"",
    -				"Dump XFS global ilock trace" },
    -#endif
    -  {  "xinodes",	kdbm_xfs_xinodes,	"",
    -				"Dump XFS inodes per mount"},
    -  {  "xquiesce",kdbm_xfs_xinodes_quiesce, "",
    -				"Dump non-quiesced XFS inodes per mount"},
    -#ifdef XFS_LOG_TRACE
    -  {  "xl_grtr",	kdbm_xfs_xlog_granttrace,	"",
    -				"Dump XFS log grant trace" },
    -#endif
    -  {  "xl_rcit",	kdbm_xfs_xlog_ritem,	"",
    -				"Dump XFS recovery item"},
    -  {  "xl_rctr",	kdbm_xfs_xlog_rtrans,	"",
    -				"Dump XFS recovery transaction"},
    -  {  "xl_rctr2",kdbm_xfs_xlog_rtrans_entire,	"",
    -				"Dump entire recovery transaction"},
    -  {  "xl_tic",	kdbm_xfs_xlog_tic,	"",
    -				"Dump XFS log ticket"},
    -  {  "xlog",	kdbm_xfs_xlog,	"",
    -				"Dump XFS log"},
    -  {  "xlogcb",	kdbm_xfs_xiclogcb,	"",
    -				"Dump XFS in-core log callbacks"},
    -  {  "xlogitm",	kdbm_xfs_xlogitem,	"",
    -				"Dump XFS log item structure"},
    -  {  "xmount",	kdbm_xfs_xmount,	"",
    -				"Dump XFS mount structure"},
    -  {  "xnode",	kdbm_xfs_xnode,		"",
    -				"Dump XFS inode"},
    -  {  "xiocore",	kdbm_xfs_xcore,		"",
    -				"Dump XFS iocore"},
    -  {  "xperag",	kdbm_xfs_xperag,	"",
    -				"Dump XFS per-allocation group data"},
    -  {  "xqinfo",  kdbm_xfs_xqm_qinfo,	"",
    -				"Dump mount->m_quotainfo structure"},
    -#ifdef	CONFIG_XFS_QUOTA
    -  {  "xqm",	kdbm_xfs_xqm,		"",
    -				"Dump XFS quota manager structure"},
    -  {  "xqmfree",	kdbm_xfs_xqm_freelist,	"",
    -				"Dump XFS global freelist of dquots"},
    -  {  "xqmhtab",	kdbm_xfs_xqm_htab,	"",
    -				"Dump XFS hashtable of dquots"},
    -#endif	/* CONFIG_XFS_QUOTA */
    -  {  "xqmplist",kdbm_xfs_xqm_mplist,	"",
    -				"Dump XFS all dquots of a f/s"},
    -#ifdef XFS_RW_TRACE
    -  {  "xrwtrc",	kdbm_xfs_xrwtrace,	"",
    -				"Dump XFS inode read/write trace" },
    -#endif
    -  {  "xsb",	kdbm_xfs_xsb,		" ",
    -				"Dump XFS superblock"},
    -  {  "xtp",	kdbm_xfs_xtp,		"",
    -				"Dump XFS transaction structure"},
    -  {  "xtrres",	kdbm_xfs_xtrans_res,	"",
    -				"Dump XFS reservation values"},
    -  {  NULL,		NULL,	NULL }
    -};
    -
    -static struct xif xfsbuf_funcs[] = {
    -  {  "bp",	kdbm_bp,	"",	"Display xfs_buf_t" },
    -  {  "bpflags",	kdbm_bp_flags,	"",	"Display xfs_buf flags" },
    -  {  "xiomap",	kdbm_iomap,	"",	"Display IOmap" },
    -  {  "i2vnode",	kdbm_i2vnode,	"",	"Display Vnode" },
    -  {  "bpdelay",	kdbm_bpdelay,	"0|1",		"Display delwri buffers" },
    -#ifdef XFS_BUF_TRACE
    -  {  "bptrace",	kdbm_bptrace,	"|",	"xfs_buf_t trace" },
    -  {  "bpoffset",kdbm_bptrace_offset, " []","xfs_buf_t trace" },
    -#endif
    -  {  NULL,		NULL,	NULL }
    -};
    -
    -static int
    -xfsidbg_init(void)
    -{
    -	struct xif	*p;
    -
    -	for (p = xfsidbg_funcs; p->name; p++)
    -		kdb_register(p->name, p->func, p->args, p->help, 0);
    -	for (p = xfsbuf_funcs; p->name; p++)
    -		kdb_register(p->name, p->func, p->args, p->help, 0);
    -	return 0;
    -}
    -
    -static void
    -xfsidbg_exit(void)
    -{
    -	struct xif	*p;
    -
    -	for (p = xfsidbg_funcs; p->name; p++)
    -		kdb_unregister(p->name);
    -	for (p = xfsbuf_funcs; p->name; p++)
    -		kdb_unregister(p->name);
    -}
    -
    -/*
    - * Argument to xfs_alloc routines, for allocation type.
    - */
    -static char *xfs_alloctype[] = {
    -	"any_ag", "first_ag", "start_ag", "this_ag",
    -	"start_bno", "near_bno", "this_bno"
    -};
    -
    -/*
    - * Static functions.
    - */
    -
    -#ifdef XFS_ALLOC_TRACE
    -/*
    - * Print xfs alloc trace buffer entry.
    - */
    -static int
    -xfs_alloc_trace_entry(ktrace_entry_t *ktep)
    -{
    -	static char *modagf_flags[] = {
    -		"magicnum",
    -		"versionnum",
    -		"seqno",
    -		"length",
    -		"roots",
    -		"levels",
    -		"flfirst",
    -		"fllast",
    -		"flcount",
    -		"freeblks",
    -		"longest",
    -		NULL
    -	};
    -
    -	if (((__psint_t)ktep->val[0] & 0xffff) == 0)
    -		return 0;
    -	switch ((long)ktep->val[0] & 0xffffL) {
    -	case XFS_ALLOC_KTRACE_ALLOC:
    -		kdb_printf("alloc %s[%s %ld] mp 0x%p\n",
    -			(char *)ktep->val[1],
    -			ktep->val[2] ? (char *)ktep->val[2] : "",
    -			(long)ktep->val[0] >> 16,
    -			(xfs_mount_t *)ktep->val[3]);
    -		kdb_printf(
    -	"agno %ld agbno %ld minlen %ld maxlen %ld mod %ld prod %ld minleft %ld\n",
    -			(long)ktep->val[4],
    -			(long)ktep->val[5],
    -			(long)ktep->val[6],
    -			(long)ktep->val[7],
    -			(long)ktep->val[8],
    -			(long)ktep->val[9],
    -			(long)ktep->val[10]);
    -		kdb_printf("total %ld alignment %ld len %ld type %s otype %s\n",
    -			(long)ktep->val[11],
    -			(long)ktep->val[12],
    -			(long)ktep->val[13],
    -			xfs_alloctype[((__psint_t)ktep->val[14]) >> 16],
    -			xfs_alloctype[((__psint_t)ktep->val[14]) & 0xffff]);
    -		kdb_printf("wasdel %d wasfromfl %d isfl %d userdata %d\n",
    -			((__psint_t)ktep->val[15] & (1 << 3)) != 0,
    -			((__psint_t)ktep->val[15] & (1 << 2)) != 0,
    -			((__psint_t)ktep->val[15] & (1 << 1)) != 0,
    -			((__psint_t)ktep->val[15] & (1 << 0)) != 0);
    -		break;
    -	case XFS_ALLOC_KTRACE_FREE:
    -		kdb_printf("free %s[%s %ld] mp 0x%p\n",
    -			(char *)ktep->val[1],
    -			ktep->val[2] ? (char *)ktep->val[2] : "",
    -			(long)ktep->val[0] >> 16,
    -			(xfs_mount_t *)ktep->val[3]);
    -		kdb_printf("agno %ld agbno %ld len %ld isfl %d\n",
    -			(long)ktep->val[4],
    -			(long)ktep->val[5],
    -			(long)ktep->val[6],
    -			(__psint_t)ktep->val[7] != 0);
    -		break;
    -	case XFS_ALLOC_KTRACE_MODAGF:
    -		kdb_printf("modagf %s[%s %ld] mp 0x%p\n",
    -			(char *)ktep->val[1],
    -			ktep->val[2] ? (char *)ktep->val[2] : "",
    -			(long)ktep->val[0] >> 16,
    -			(xfs_mount_t *)ktep->val[3]);
    -		printflags((__psint_t)ktep->val[4], modagf_flags, "modified");
    -		kdb_printf("seqno %lu length %lu roots b %lu c %lu\n",
    -			(unsigned long)ktep->val[5],
    -			(unsigned long)ktep->val[6],
    -			(unsigned long)ktep->val[7],
    -			(unsigned long)ktep->val[8]);
    -		kdb_printf("levels b %lu c %lu flfirst %lu fllast %lu flcount %lu\n",
    -			(unsigned long)ktep->val[9],
    -			(unsigned long)ktep->val[10],
    -			(unsigned long)ktep->val[11],
    -			(unsigned long)ktep->val[12],
    -			(unsigned long)ktep->val[13]);
    -		kdb_printf("freeblks %lu longest %lu\n",
    -			(unsigned long)ktep->val[14],
    -			(unsigned long)ktep->val[15]);
    -		break;
    -
    -	case XFS_ALLOC_KTRACE_UNBUSY:
    -		kdb_printf("unbusy %s [%s %ld] mp 0x%p\n",
    -			(char *)ktep->val[1],
    -			ktep->val[2] ? (char *)ktep->val[2] : "",
    -			(long)ktep->val[0] >> 16,
    -			(xfs_mount_t *)ktep->val[3]);
    -		kdb_printf("      agno %lu slot %lu tp 0x%p\n",
    -			(unsigned long)ktep->val[4],
    -			(unsigned long)ktep->val[7],
    -			(xfs_trans_t *)ktep->val[8]);
    -		break;
    -	case XFS_ALLOC_KTRACE_BUSY:
    -		kdb_printf("busy %s [%s %ld] mp 0x%p\n",
    -			(char *)ktep->val[1],
    -			ktep->val[2] ? (char *)ktep->val[2] : "",
    -			(long)ktep->val[0] >> 16,
    -			(xfs_mount_t *)ktep->val[3]);
    -		kdb_printf("      agno %lu agbno %lu len %lu slot %lu tp 0x%p\n",
    -			(unsigned long)ktep->val[4],
    -			(unsigned long)ktep->val[5],
    -			(unsigned long)ktep->val[6],
    -			(unsigned long)ktep->val[7],
    -			(xfs_trans_t *)ktep->val[8]);
    -		break;
    -	case XFS_ALLOC_KTRACE_BUSYSEARCH:
    -		kdb_printf("busy-search %s [%s %ld] mp 0x%p\n",
    -			(char *)ktep->val[1],
    -			ktep->val[2] ? (char *)ktep->val[2] : "",
    -			(long)ktep->val[0] >> 16,
    -			(xfs_mount_t *)ktep->val[3]);
    -		kdb_printf("      agno %ld agbno %ld len %ld slot %ld tp 0x%p\n",
    -			(unsigned long)ktep->val[4],
    -			(unsigned long)ktep->val[5],
    -			(unsigned long)ktep->val[6],
    -			(unsigned long)ktep->val[7],
    -			(xfs_trans_t *)ktep->val[8]);
    -		break;
    -	default:
    -		kdb_printf("unknown alloc trace record\n");
    -		break;
    -	}
    -	return 1;
    -}
    -#endif /* XFS_ALLOC_TRACE */
    -
    -#ifdef XFS_ATTR_TRACE
    -/*
    - * Print an attribute trace buffer entry.
    - */
    -static int
    -xfs_attr_trace_entry(ktrace_entry_t *ktep)
    -{
    -	static char *attr_arg_flags[] = {
    -		"DONTFOLLOW",	/* 0x0001 */
    -		"ROOT",		/* 0x0002 */
    -		"TRUSTED",	/* 0x0004 */
    -		"SECURE",	/* 0x0008 */
    -		"CREATE",	/* 0x0010 */
    -		"REPLACE",	/* 0x0020 */
    -		"?",		/* 0x0040 */
    -		"?",		/* 0x0080 */
    -		"SYSTEM",	/* 0x0100 */
    -		"?",		/* 0x0200 */
    -		"?",		/* 0x0400 */
    -		"?",		/* 0x0800 */
    -		"KERNOTIME",	/* 0x1000 */
    -		"KERNOVAL",	/* 0x2000 */
    -		"KERNAMELS",	/* 0x4000 */
    -		"KERNFULLS",	/* 0x8000 */
    -		NULL
    -	};
    -
    -	if (!ktep->val[0])
    -		return 0;
    -
    -	qprintf("-- %s: cursor h/b/o 0x%lx/0x%lx/%lu, dupcnt %lu, dp 0x%p\n",
    -		 (char *)ktep->val[1],
    -		 (unsigned long)ktep->val[3],
    -		 (unsigned long)ktep->val[4],
    -		 (unsigned long)ktep->val[5],
    -		 (unsigned long)ktep->val[11],
    -		 (xfs_inode_t *)ktep->val[2]);
    -	qprintf("   alist 0x%p, size %lu, count %lu, firstu %lu, Llen %lu",
    -		 (attrlist_t *)ktep->val[6],
    -		 (unsigned long)ktep->val[7],
    -		 (unsigned long)ktep->val[8],
    -		 (unsigned long)ktep->val[9],
    -		 (unsigned long)ktep->val[10]);
    -	printflags((__psunsigned_t)(ktep->val[12]), attr_arg_flags, ", flags");
    -	qprintf("\n");
    -
    -	switch ((__psint_t)ktep->val[0]) {
    -	case XFS_ATTR_KTRACE_L_C:
    -		break;
    -	case XFS_ATTR_KTRACE_L_CN:
    -		qprintf("   node: count %lu, 1st hash 0x%lx, last hash 0x%lx\n",
    -			 (unsigned long)ktep->val[13],
    -			 (unsigned long)ktep->val[14],
    -			 (unsigned long)ktep->val[15]);
    -		break;
    -	case XFS_ATTR_KTRACE_L_CB:
    -		qprintf("   btree: hash 0x%lx, blkno 0x%lx\n",
    -			 (unsigned long)ktep->val[13],
    -			 (unsigned long)ktep->val[14]);
    -		break;
    -	case XFS_ATTR_KTRACE_L_CL:
    -		qprintf("   leaf: count %ld, 1st hash 0x%lx, last hash 0x%lx\n",
    -			 (unsigned long)ktep->val[13],
    -			 (unsigned long)ktep->val[14],
    -			 (unsigned long)ktep->val[15]);
    -		break;
    -	default:
    -		qprintf("   unknown attr trace record format\n");
    -		break;
    -	}
    -	return 1;
    -}
    -#endif /* XFS_ATTR_TRACE */
    -
    -#ifdef XFS_BMAP_TRACE
    -/*
    - * Print xfs bmap extent trace buffer entry.
    - */
    -static int
    -xfs_bmap_trace_entry(ktrace_entry_t *ktep)
    -{
    -	xfs_dfsbno_t	    b;
    -	xfs_dfilblks_t	  c;
    -	xfs_inode_t	     *ip;
    -	xfs_ino_t	       ino;
    -	xfs_dfiloff_t	   o;
    -	int		     flag;
    -	int		     opcode;
    -	static char	     *ops[] = { "del", "ins", "pre", "post" };
    -	xfs_bmbt_rec_32_t       r;
    -	int		     whichfork;
    -
    -	opcode = ((__psint_t)ktep->val[0]) & 0xffff;
    -	if (opcode == 0)
    -		return 0;
    -	whichfork = ((__psint_t)ktep->val[0]) >> 16;
    -	ip = (xfs_inode_t *)ktep->val[3];
    -	ino = ((xfs_ino_t)(unsigned long)ktep->val[6] << 32) |
    -		((xfs_ino_t)(unsigned long)ktep->val[7]);
    -	qprintf("%s %s:%s ip %p ino %s %cf\n",
    -		ops[opcode - 1], (char *)ktep->val[1],
    -		(char *)ktep->val[2], ip, xfs_fmtino(ino, ip->i_mount),
    -		"da"[whichfork]);
    -	r.l0 = (xfs_bmbt_rec_base_t)(unsigned long)ktep->val[8];
    -	r.l1 = (xfs_bmbt_rec_base_t)(unsigned long)ktep->val[9];
    -	r.l2 = (xfs_bmbt_rec_base_t)(unsigned long)ktep->val[10];
    -	r.l3 = (xfs_bmbt_rec_base_t)(unsigned long)ktep->val[11];
    -	xfs_convert_extent(&r, &o, &b, &c, &flag);
    -	qprintf(" idx %ld offset %lld block %s",
    -		(long)ktep->val[4], o,
    -		xfs_fmtfsblock((xfs_fsblock_t)b, ip->i_mount));
    -	qprintf(" count %lld flag %d\n", c, flag);
    -	if ((__psint_t)ktep->val[5] != 2)
    -		return 1;
    -	r.l0 = (xfs_bmbt_rec_base_t)(unsigned long)ktep->val[12];
    -	r.l1 = (xfs_bmbt_rec_base_t)(unsigned long)ktep->val[13];
    -	r.l2 = (xfs_bmbt_rec_base_t)(unsigned long)ktep->val[14];
    -	r.l3 = (xfs_bmbt_rec_base_t)(unsigned long)ktep->val[15];
    -	xfs_convert_extent(&r, &o, &b, &c, &flag);
    -	qprintf(" offset %lld block %s", o,
    -		xfs_fmtfsblock((xfs_fsblock_t)b, ip->i_mount));
    -	qprintf(" count %lld flag %d\n", c, flag);
    -	return 1;
    -}
    -
    -/*
    - * Print xfs bmap btree trace buffer entry.
    - */
    -static int
    -xfs_bmbt_trace_entry(
    -	ktrace_entry_t	  *ktep)
    -{
    -	int			line;
    -	xfs_bmbt_rec_32_t	r;
    -	xfs_bmbt_irec_t		s;
    -	int			type;
    -	int			whichfork;
    -
    -	type = (__psint_t)ktep->val[0] & 0xff;
    -	if (type == 0)
    -		return 0;
    -	whichfork = ((__psint_t)ktep->val[0] >> 8) & 0xff;
    -	line = ((__psint_t)ktep->val[0] >> 16) & 0xffff;
    -	qprintf("%s[%s@%d] ip 0x%p %cf cur 0x%p\n",
    -		(char *)ktep->val[1],
    -		(char *)ktep->val[2],
    -		line,
    -		(xfs_inode_t *)ktep->val[3],
    -		"da"[whichfork],
    -		(xfs_btree_cur_t *)ktep->val[4]);
    -	switch (type) {
    -	case XFS_BMBT_KTRACE_ARGBI:
    -		qprintf(" buf 0x%p i %ld\n",
    -			(xfs_buf_t *)ktep->val[5],
    -			(long)ktep->val[6]);
    -		break;
    -	case XFS_BMBT_KTRACE_ARGBII:
    -		qprintf(" buf 0x%p i0 %ld i1 %ld\n",
    -			(xfs_buf_t *)ktep->val[5],
    -			(long)ktep->val[6],
    -			(long)ktep->val[7]);
    -		break;
    -	case XFS_BMBT_KTRACE_ARGFFFI:
    -		qprintf(" o 0x%x%08x b 0x%x%08x i 0x%x%08x j %ld\n",
    -			(unsigned int)(long)ktep->val[5],
    -			(unsigned int)(long)ktep->val[6],
    -			(unsigned int)(long)ktep->val[7],
    -			(unsigned int)(long)ktep->val[8],
    -			(unsigned int)(long)ktep->val[9],
    -			(unsigned int)(long)ktep->val[10],
    -			(long)ktep->val[11]);
    -		break;
    -	case XFS_BMBT_KTRACE_ARGI:
    -		qprintf(" i 0x%lx\n",
    -			(long)ktep->val[5]);
    -		break;
    -	case XFS_BMBT_KTRACE_ARGIFK:
    -		qprintf(" i 0x%lx f 0x%x%08x o 0x%x%08x\n",
    -			(long)ktep->val[5],
    -			(unsigned int)(long)ktep->val[6],
    -			(unsigned int)(long)ktep->val[7],
    -			(unsigned int)(long)ktep->val[8],
    -			(unsigned int)(long)ktep->val[9]);
    -		break;
    -	case XFS_BMBT_KTRACE_ARGIFR:
    -		qprintf(" i 0x%lx f 0x%x%08x ",
    -			(long)ktep->val[5],
    -			(unsigned int)(long)ktep->val[6],
    -			(unsigned int)(long)ktep->val[7]);
    -		s.br_startoff = (xfs_fileoff_t)
    -			(((xfs_dfiloff_t)(unsigned long)ktep->val[8] << 32) |
    -				(xfs_dfiloff_t)(unsigned long)ktep->val[9]);
    -		s.br_startblock = (xfs_fsblock_t)
    -			(((xfs_dfsbno_t)(unsigned long)ktep->val[10] << 32) |
    -				(xfs_dfsbno_t)(unsigned long)ktep->val[11]);
    -		s.br_blockcount = (xfs_filblks_t)
    -			(((xfs_dfilblks_t)(unsigned long)ktep->val[12] << 32) |
    -				(xfs_dfilblks_t)(unsigned long)ktep->val[13]);
    -		xfsidbg_xbirec(&s);
    -		break;
    -	case XFS_BMBT_KTRACE_ARGIK:
    -		qprintf(" i 0x%lx o 0x%x%08x\n",
    -			(long)ktep->val[5],
    -			(unsigned int)(long)ktep->val[6],
    -			(unsigned int)(long)ktep->val[7]);
    -		break;
    -	case XFS_BMBT_KTRACE_CUR:
    -		qprintf(" nlevels %ld flags %ld allocated %ld ",
    -			((long)ktep->val[5] >> 24) & 0xff,
    -			((long)ktep->val[5] >> 16) & 0xff,
    -			(long)ktep->val[5] & 0xffff);
    -		r.l0 = (xfs_bmbt_rec_base_t)(unsigned long)ktep->val[6];
    -		r.l1 = (xfs_bmbt_rec_base_t)(unsigned long)ktep->val[7];
    -		r.l2 = (xfs_bmbt_rec_base_t)(unsigned long)ktep->val[8];
    -		r.l3 = (xfs_bmbt_rec_base_t)(unsigned long)ktep->val[9];
    -		xfsidbg_xbrec((xfs_bmbt_rec_64_t *)&r);
    -		qprintf(" bufs 0x%p 0x%p 0x%p 0x%p ",
    -			(xfs_buf_t *)ktep->val[10],
    -			(xfs_buf_t *)ktep->val[11],
    -			(xfs_buf_t *)ktep->val[12],
    -			(xfs_buf_t *)ktep->val[13]);
    -		qprintf("ptrs %ld %ld %ld %ld\n",
    -			(long)ktep->val[14] >> 16,
    -			(long)ktep->val[14] & 0xffff,
    -			(long)ktep->val[15] >> 16,
    -			(long)ktep->val[15] & 0xffff);
    -		break;
    -	default:
    -		qprintf("unknown bmbt trace record\n");
    -		break;
    -	}
    -	return 1;
    -}
    -#endif
    -
    -/*
    - * Print an xfs in-inode bmap btree root.
    - */
    -static void
    -xfs_broot(xfs_inode_t *ip, xfs_ifork_t *f)
    -{
    -	xfs_bmbt_block_t	*broot;
    -	int			format;
    -	int			i;
    -	xfs_bmbt_key_t		*kp;
    -	xfs_bmbt_ptr_t		*pp;
    -
    -	format = f == &ip->i_df ? ip->i_d.di_format : ip->i_d.di_aformat;
    -	if ((f->if_flags & XFS_IFBROOT) == 0 ||
    -	    format != XFS_DINODE_FMT_BTREE) {
    -		kdb_printf("inode 0x%p not btree format\n", ip);
    -		return;
    -	}
    -	broot = f->if_broot;
    -	kdb_printf("block @0x%p magic %x level %d numrecs %d\n",
    -		broot,
    -		be32_to_cpu(broot->bb_magic),
    -		be16_to_cpu(broot->bb_level),
    -		be16_to_cpu(broot->bb_numrecs));
    -	kp = XFS_BMAP_BROOT_KEY_ADDR(broot, 1, f->if_broot_bytes);
    -	pp = XFS_BMAP_BROOT_PTR_ADDR(broot, 1, f->if_broot_bytes);
    -	for (i = 1; i <= be16_to_cpu(broot->bb_numrecs); i++)
    -		kdb_printf("\t%d: startoff %Ld ptr %Lx %s\n",
    -			i, INT_GET(kp[i - 1].br_startoff, ARCH_CONVERT), INT_GET(pp[i - 1], ARCH_CONVERT),
    -			xfs_fmtfsblock(INT_GET(pp[i - 1], ARCH_CONVERT), ip->i_mount));
    -}
    -
    -/*
    - * Print allocation btree block.
    - */
    -static void
    -xfs_btalloc(xfs_alloc_block_t *bt, int bsz)
    -{
    -	int i;
    -
    -	kdb_printf("magic 0x%x level %d numrecs %d leftsib 0x%x rightsib 0x%x\n",
    -		be32_to_cpu(bt->bb_magic),
    -		be16_to_cpu(bt->bb_level),
    -		be16_to_cpu(bt->bb_numrecs),
    -		be32_to_cpu(bt->bb_leftsib),
    -		be32_to_cpu(bt->bb_rightsib));
    -	if (!bt->bb_level) {
    -		for (i = 1; i <= be16_to_cpu(bt->bb_numrecs); i++) {
    -			xfs_alloc_rec_t *r;
    -
    -			r = XFS_BTREE_REC_ADDR(bsz, xfs_alloc, bt, i, 0);
    -			kdb_printf("rec %d startblock 0x%x blockcount %d\n",
    -				i,
    -				be32_to_cpu(r->ar_startblock),
    -				be32_to_cpu(r->ar_blockcount));
    -		}
    -	} else {
    -		int mxr;
    -
    -		mxr = XFS_BTREE_BLOCK_MAXRECS(bsz, xfs_alloc, 0);
    -		for (i = 1; i <= be16_to_cpu(bt->bb_numrecs); i++) {
    -			xfs_alloc_key_t *k;
    -			xfs_alloc_ptr_t *p;
    -
    -			k = XFS_BTREE_KEY_ADDR(bsz, xfs_alloc, bt, i, mxr);
    -			p = XFS_BTREE_PTR_ADDR(bsz, xfs_alloc, bt, i, mxr);
    -			kdb_printf("key %d startblock 0x%x blockcount %d ptr 0x%x\n",
    -				i,
    -				be32_to_cpu(k->ar_startblock),
    -				be32_to_cpu(k->ar_blockcount),
    -				be32_to_cpu(*p));
    -		}
    -	}
    -}
    -
    -/*
    - * Print a bmap btree block.
    - */
    -static void
    -xfs_btbmap(xfs_bmbt_block_t *bt, int bsz)
    -{
    -	int i;
    -
    -	kdb_printf("magic 0x%x level %d numrecs %d leftsib %Lx rightsib %Lx\n",
    -		be32_to_cpu(bt->bb_magic),
    -		be16_to_cpu(bt->bb_level),
    -		be16_to_cpu(bt->bb_numrecs),
    -		be64_to_cpu(bt->bb_leftsib),
    -		be64_to_cpu(bt->bb_rightsib));
    -	if (!bt->bb_level) {
    -		for (i = 1; i <= be16_to_cpu(bt->bb_numrecs); i++) {
    -			xfs_bmbt_rec_t *r;
    -			xfs_bmbt_irec_t	irec;
    -
    -			r = (xfs_bmbt_rec_t *)XFS_BTREE_REC_ADDR(bsz,
    -				xfs_bmbt, bt, i, 0);
    -
    -			xfs_bmbt_disk_get_all((xfs_bmbt_rec_t *)r, &irec);
    -			kdb_printf("rec %d startoff %Ld startblock %Lx blockcount %Ld flag %d\n",
    -				i, irec.br_startoff,
    -				(__uint64_t)irec.br_startblock,
    -				irec.br_blockcount, irec.br_state);
    -		}
    -	} else {
    -		int mxr;
    -
    -		mxr = XFS_BTREE_BLOCK_MAXRECS(bsz, xfs_bmbt, 0);
    -		for (i = 1; i <= be16_to_cpu(bt->bb_numrecs); i++) {
    -			xfs_bmbt_key_t *k;
    -			xfs_bmbt_ptr_t *p;
    -
    -			k = XFS_BTREE_KEY_ADDR(bsz, xfs_bmbt, bt, i, mxr);
    -			p = XFS_BTREE_PTR_ADDR(bsz, xfs_bmbt, bt, i, mxr);
    -			kdb_printf("key %d startoff %Ld ",
    -				i, INT_GET(k->br_startoff, ARCH_CONVERT));
    -			kdb_printf("ptr %Lx\n", INT_GET(*p, ARCH_CONVERT));
    -		}
    -	}
    -}
    -
    -/*
    - * Print an inode btree block.
    - */
    -static void
    -xfs_btino(xfs_inobt_block_t *bt, int bsz)
    -{
    -	int i;
    -
    -	kdb_printf("magic 0x%x level %d numrecs %d leftsib 0x%x rightsib 0x%x\n",
    -		be32_to_cpu(bt->bb_magic),
    -		be16_to_cpu(bt->bb_level),
    -		be16_to_cpu(bt->bb_numrecs),
    -		be32_to_cpu(bt->bb_leftsib),
    -		be32_to_cpu(bt->bb_rightsib));
    -	if (!bt->bb_level) {
    -		for (i = 1; i <= be16_to_cpu(bt->bb_numrecs); i++) {
    -			xfs_inobt_rec_t *r;
    -
    -			r = XFS_BTREE_REC_ADDR(bsz, xfs_inobt, bt, i, 0);
    -			kdb_printf("rec %d startino 0x%x freecount %d, free %Lx\n",
    -				i, INT_GET(r->ir_startino, ARCH_CONVERT),
    -				INT_GET(r->ir_freecount, ARCH_CONVERT),
    -				INT_GET(r->ir_free, ARCH_CONVERT));
    -		}
    -	} else {
    -		int mxr;
    -
    -		mxr = XFS_BTREE_BLOCK_MAXRECS(bsz, xfs_inobt, 0);
    -		for (i = 1; i <= be16_to_cpu(bt->bb_numrecs); i++) {
    -			xfs_inobt_key_t *k;
    -			xfs_inobt_ptr_t *p;
    -
    -			k = XFS_BTREE_KEY_ADDR(bsz, xfs_inobt, bt, i, mxr);
    -			p = XFS_BTREE_PTR_ADDR(bsz, xfs_inobt, bt, i, mxr);
    -			kdb_printf("key %d startino 0x%x ptr 0x%x\n",
    -				i, INT_GET(k->ir_startino, ARCH_CONVERT),
    -				be32_to_cpu(*p));
    -		}
    -	}
    -}
    -
    -/*
    - * Print a buf log item.
    - */
    -static void
    -xfs_buf_item_print(xfs_buf_log_item_t *blip, int summary)
    -{
    -	static char *bli_flags[] = {
    -		"hold",		/* 0x1 */
    -		"dirty",	/* 0x2 */
    -		"stale",	/* 0x4 */
    -		"logged",	/* 0x8 */
    -		"ialloc",	/* 0x10 */
    -		"inode_stale",  /* 0x20 */
    -		NULL
    -		};
    -	static char *blf_flags[] = {
    -		"inode",	/* 0x1 */
    -		"cancel",	/* 0x2 */
    -		NULL
    -		};
    -
    -	if (summary) {
    -		kdb_printf("buf 0x%p blkno 0x%Lx ", blip->bli_buf,
    -			     blip->bli_format.blf_blkno);
    -		printflags(blip->bli_flags, bli_flags, "flags:");
    -		kdb_printf("\n   ");
    -		xfsidbg_xbuf_real(blip->bli_buf, 1);
    -		return;
    -	}
    -	kdb_printf("buf 0x%p recur %d refcount %d flags:",
    -		blip->bli_buf, blip->bli_recur,
    -		atomic_read(&blip->bli_refcount));
    -	printflags(blip->bli_flags, bli_flags, NULL);
    -	kdb_printf("\n");
    -	kdb_printf("size %d blkno 0x%Lx len 0x%x map size %d map 0x%p\n",
    -		blip->bli_format.blf_size, blip->bli_format.blf_blkno,
    -		(uint) blip->bli_format.blf_len, blip->bli_format.blf_map_size,
    -		&(blip->bli_format.blf_data_map[0]));
    -	kdb_printf("blf flags: ");
    -	printflags((uint)blip->bli_format.blf_flags, blf_flags, NULL);
    -#ifdef XFS_TRANS_DEBUG
    -	kdb_printf("orig 0x%x logged 0x%x",
    -		blip->bli_orig, blip->bli_logged);
    -#endif
    -	kdb_printf("\n");
    -}
    -
    -#ifdef XFS_BMAP_TRACE
    -/*
    - * Convert an external extent descriptor to internal form.
    - */
    -static void
    -xfs_convert_extent(xfs_bmbt_rec_32_t *rp, xfs_dfiloff_t *op, xfs_dfsbno_t *sp,
    -		   xfs_dfilblks_t *cp, int *fp)
    -{
    -	xfs_dfiloff_t o;
    -	xfs_dfsbno_t s;
    -	xfs_dfilblks_t c;
    -	int flag;
    -
    -	flag = (((xfs_dfiloff_t)rp->l0) >> 31) & 1;
    -	o = ((((xfs_dfiloff_t)rp->l0) & 0x7fffffff) << 23) |
    -	    (((xfs_dfiloff_t)rp->l1) >> 9);
    -	s = (((xfs_dfsbno_t)(rp->l1 & 0x000001ff)) << 43) |
    -	    (((xfs_dfsbno_t)rp->l2) << 11) |
    -	    (((xfs_dfsbno_t)rp->l3) >> 21);
    -	c = (xfs_dfilblks_t)(rp->l3 & 0x001fffff);
    -	*op = o;
    -	*sp = s;
    -	*cp = c;
    -	*fp = flag;
    -}
    -#endif
    -
    -#ifdef XFS_RW_TRACE
    -/*
    - * Print itrunc entry trace.
    - */
    -static void
    -xfs_ctrunc_trace_entry(ktrace_entry_t	*ktep)
    -{
    -	qprintf("ip 0x%p cpu %ld\n",
    -		(xfs_inode_t *)(unsigned long)ktep->val[1], (long)ktep->val[2]);
    -}
    -#endif
    -
    -/*
    - * Print an xfs_da_state_path structure.
    - */
    -static void
    -xfs_dastate_path(xfs_da_state_path_t *p)
    -{
    -	int i;
    -
    -	kdb_printf("active %d\n", p->active);
    -	for (i = 0; i < XFS_DA_NODE_MAXDEPTH; i++) {
    -		kdb_printf(" blk %d bp 0x%p blkno 0x%x",
    -			i, p->blk[i].bp, p->blk[i].blkno);
    -		kdb_printf(" index %d hashval 0x%x ",
    -			p->blk[i].index, (uint_t)p->blk[i].hashval);
    -		switch(p->blk[i].magic) {
    -		case XFS_DA_NODE_MAGIC:		kdb_printf("NODE\n");	break;
    -		case XFS_DIR_LEAF_MAGIC:	kdb_printf("DIR\n");	break;
    -		case XFS_ATTR_LEAF_MAGIC:	kdb_printf("ATTR\n");	break;
    -		case XFS_DIR2_LEAFN_MAGIC:	kdb_printf("DIR2\n");	break;
    -		default:			kdb_printf("type ?\n");	break;
    -		}
    -	}
    -}
    -
    -#ifdef XFS_DIR_TRACE
    -/*
    - * Print a xfs directory trace buffer entry.
    - */
    -static int
    -xfs_dir_trace_entry(ktrace_entry_t *ktep)
    -{
    -	xfs_mount_t *mp;
    -	__uint32_t hash;
    -	xfs_off_t cookie;
    -
    -	if (!ktep->val[0] || !ktep->val[1])
    -		return 0;
    -
    -	mp = (xfs_mount_t *)ktep->val[3];
    -	cookie = (__psunsigned_t)ktep->val[4];
    -	cookie <<= 32;
    -	cookie |= (__psunsigned_t)ktep->val[5];
    -	qprintf("%s -- dp=0x%p b/e/h=%ld/%ld/0x%08lx resid=0x%lx ",
    -		    (char *)ktep->val[1],
    -		    (xfs_inode_t *)ktep->val[2],
    -		    (long)XFS_DA_COOKIE_BNO(mp, cookie),
    -		    (long)XFS_DA_COOKIE_ENTRY(mp, cookie),
    -		    (unsigned long)XFS_DA_COOKIE_HASH(mp, cookie),
    -		    (long)ktep->val[6]);
    -
    -	switch ((__psint_t)ktep->val[0]) {
    -	case XFS_DIR_KTRACE_G_DU:
    -		break;
    -	case XFS_DIR_KTRACE_G_DUB:
    -		qprintf("bno=%ld", (long)ktep->val[7]);
    -		break;
    -	case XFS_DIR_KTRACE_G_DUN:
    -		qprintf("forw=%ld, cnt=%ld, 0x%08lx - 0x%08lx",
    -			      (long)ktep->val[7],
    -			      (long)ktep->val[8],
    -			      (unsigned long)ktep->val[9],
    -			      (unsigned long)ktep->val[10]);
    -		break;
    -	case XFS_DIR_KTRACE_G_DUL:
    -		qprintf("forw=%ld, cnt=%ld, 0x%08lx - 0x%08lx",
    -			      (long)ktep->val[7],
    -			      (long)ktep->val[8],
    -			      (unsigned long)ktep->val[9],
    -			      (unsigned long)ktep->val[10]);
    -		break;
    -	case XFS_DIR_KTRACE_G_DUE:
    -		qprintf("entry hashval 0x%08lx", (unsigned long)ktep->val[7]);
    -		break;
    -	case XFS_DIR_KTRACE_G_DUC:
    -		cookie = (__psunsigned_t)ktep->val[7];
    -		cookie <<= 32;
    -		cookie |= (__psunsigned_t)ktep->val[8];
    -		hash = XFS_DA_COOKIE_HASH(mp, cookie);
    -		qprintf("b/e/h=%ld/%ld/0x%08x",
    -		    (long)XFS_DA_COOKIE_BNO(mp, cookie),
    -		    (long)XFS_DA_COOKIE_ENTRY(mp, cookie),
    -		    hash);
    -		break;
    -	default:
    -		qprintf("unknown dir trace record format");
    -		break;
    -	}
    -	return 1;
    -}
    -#endif
    -
    -#ifdef XFS_DIR2_TRACE
    -/*
    - * Print a xfs v2 directory trace buffer entry.
    - */
    -static int
    -xfs_dir2_trace_entry(ktrace_entry_t *ktep)
    -{
    -	char	    *cp;
    -	int	     i;
    -	int	     len;
    -
    -	if (!ktep->val[0])
    -		return 0;
    -	cp = (char *)&ktep->val[10];
    -	qprintf("%s: '", (char *)ktep->val[1]);
    -	len = min((__psint_t)ktep->val[9], (__psint_t)sizeof(ktep->val[10])*6);
    -	for (i = 0; i < len; i++)
    -		qprintf("%c", cp[i]);
    -	qprintf("'(%ld)", (long)ktep->val[9]);
    -	if ((__psunsigned_t)ktep->val[0] != XFS_DIR2_KTRACE_ARGS_BIBII)
    -		qprintf(" hashval 0x%llx inumber %lld dp 0x%p tp 0x%p check %d",
    -			(__uint64_t)(unsigned long)ktep->val[2],
    -			(__int64_t)(unsigned long)ktep->val[3],
    -			ktep->val[4], ktep->val[5],
    -			(int)(__psint_t)ktep->val[6]);
    -	switch ((__psunsigned_t)ktep->val[0]) {
    -	case XFS_DIR2_KTRACE_ARGS:
    -		break;
    -	case XFS_DIR2_KTRACE_ARGS_B:
    -		qprintf(" bp 0x%p", ktep->val[7]);
    -		break;
    -	case XFS_DIR2_KTRACE_ARGS_BB:
    -		qprintf(" lbp 0x%p dbp 0x%p", ktep->val[7], ktep->val[8]);
    -		break;
    -	case XFS_DIR2_KTRACE_ARGS_BIBII:
    -		qprintf(" dp 0x%p tp 0x%p srcbp 0x%p srci %d dstbp 0x%p dsti %d count %d",
    -			ktep->val[2], ktep->val[3], ktep->val[4],
    -			(int)(__psint_t)ktep->val[5], ktep->val[6],
    -			(int)(__psint_t)ktep->val[7],
    -			(int)(__psint_t)ktep->val[8]);
    -		break;
    -	case XFS_DIR2_KTRACE_ARGS_DB:
    -		qprintf(" db 0x%x bp 0x%p",
    -			(xfs_dir2_db_t)(unsigned long)ktep->val[7],
    -			ktep->val[8]);
    -		break;
    -	case XFS_DIR2_KTRACE_ARGS_I:
    -		qprintf(" i 0x%lx", (unsigned long)ktep->val[7]);
    -		break;
    -	case XFS_DIR2_KTRACE_ARGS_S:
    -		qprintf(" s 0x%x", (int)(__psint_t)ktep->val[7]);
    -		break;
    -	case XFS_DIR2_KTRACE_ARGS_SB:
    -		qprintf(" s 0x%x bp 0x%p", (int)(__psint_t)ktep->val[7],
    -			ktep->val[8]);
    -		break;
    -	default:
    -		qprintf("unknown dirv2 trace record format");
    -		break;
    -	}
    -	return 1;
    -}
    -#endif
    -
    -/*
    - * Print an efd log item.
    - */
    -static void
    -xfs_efd_item_print(xfs_efd_log_item_t *efdp, int summary)
    -{
    -	int		i;
    -	xfs_extent_t	*ep;
    -
    -	if (summary) {
    -		kdb_printf("Extent Free Done: ID 0x%Lx nextents %d (at 0x%p)\n",
    -				efdp->efd_format.efd_efi_id,
    -				efdp->efd_format.efd_nextents, efdp);
    -		return;
    -	}
    -	kdb_printf("size %d nextents %d next extent %d efip 0x%p\n",
    -		efdp->efd_format.efd_size, efdp->efd_format.efd_nextents,
    -		efdp->efd_next_extent, efdp->efd_efip);
    -	kdb_printf("efi_id 0x%Lx\n", efdp->efd_format.efd_efi_id);
    -	kdb_printf("efd extents:\n");
    -	ep = &(efdp->efd_format.efd_extents[0]);
    -	for (i = 0; i < efdp->efd_next_extent; i++, ep++) {
    -		kdb_printf("    block %Lx len %d\n",
    -			ep->ext_start, ep->ext_len);
    -	}
    -}
    -
    -/*
    - * Print an efi log item.
    - */
    -static void
    -xfs_efi_item_print(xfs_efi_log_item_t *efip, int summary)
    -{
    -	int		i;
    -	xfs_extent_t	*ep;
    -	static char *efi_flags[] = {
    -		"recovered",	/* 0x1 */
    -		"committed",	/* 0x2 */
    -		"cancelled",	/* 0x4 */
    -		NULL,
    -		};
    -
    -	if (summary) {
    -		kdb_printf("Extent Free Intention: ID 0x%Lx nextents %d (at 0x%p)\n",
    -				efip->efi_format.efi_id,
    -				efip->efi_format.efi_nextents, efip);
    -		return;
    -	}
    -	kdb_printf("size %d nextents %d next extent %d\n",
    -		efip->efi_format.efi_size, efip->efi_format.efi_nextents,
    -		efip->efi_next_extent);
    -	kdb_printf("id %Lx", efip->efi_format.efi_id);
    -	printflags(efip->efi_flags, efi_flags, "flags :");
    -	kdb_printf("\n");
    -	kdb_printf("efi extents:\n");
    -	ep = &(efip->efi_format.efi_extents[0]);
    -	for (i = 0; i < efip->efi_next_extent; i++, ep++) {
    -		kdb_printf("    block %Lx len %d\n",
    -			ep->ext_start, ep->ext_len);
    -	}
    -}
    -
    -/*
    - * Format inode "format" into a static buffer & return it.
    - */
    -static char *
    -xfs_fmtformat(xfs_dinode_fmt_t f)
    -{
    -	static char *t[] = {
    -		"dev",
    -		"local",
    -		"extents",
    -		"btree",
    -		"uuid"
    -	};
    -
    -	return t[f];
    -}
    -
    -/*
    - * Format fsblock number into a static buffer & return it.
    - */
    -char *
    -xfs_fmtfsblock(xfs_fsblock_t bno, xfs_mount_t *mp)
    -{
    -	static char rval[50];
    -
    -	if (bno == NULLFSBLOCK)
    -		sprintf(rval, "NULLFSBLOCK");
    -	else if (ISNULLSTARTBLOCK(bno))
    -		sprintf(rval, "NULLSTARTBLOCK(%Ld)", STARTBLOCKVAL(bno));
    -	else if (mp)
    -		sprintf(rval, "%Ld[%x:%x]", (xfs_dfsbno_t)bno,
    -			XFS_FSB_TO_AGNO(mp, bno), XFS_FSB_TO_AGBNO(mp, bno));
    -	else
    -		sprintf(rval, "%Ld", (xfs_dfsbno_t)bno);
    -	return rval;
    -}
    -
    -/*
    - * Format inode number into a static buffer & return it.
    - */
    -static char *
    -xfs_fmtino(xfs_ino_t ino, xfs_mount_t *mp)
    -{
    -	static char rval[50];
    -
    -	if (mp)
    -		sprintf(rval, "%llu[%x:%x:%x]",
    -			(unsigned long long) ino,
    -			XFS_INO_TO_AGNO(mp, ino),
    -			XFS_INO_TO_AGBNO(mp, ino),
    -			XFS_INO_TO_OFFSET(mp, ino));
    -	else
    -		sprintf(rval, "%llu", (unsigned long long) ino);
    -	return rval;
    -}
    -
    -/*
    - * Format an lsn for printing into a static buffer & return it.
    - */
    -static char *
    -xfs_fmtlsn(xfs_lsn_t *lsnp)
    -{
    -	uint		*wordp;
    -	uint		*word2p;
    -	static char	buf[20];
    -
    -	wordp = (uint *)lsnp;
    -	word2p = wordp++;
    -	sprintf(buf, "[%u:%u]", *wordp, *word2p);
    -
    -	return buf;
    -}
    -
    -/*
    - * Format file mode into a static buffer & return it.
    - */
    -static char *
    -xfs_fmtmode(int m)
    -{
    -	static char rval[16];
    -
    -	sprintf(rval, "%c%c%c%c%c%c%c%c%c%c%c%c%c",
    -		"?fc?dxb?r?l?S?m?"[(m & S_IFMT) >> 12],
    -		m & S_ISUID ? 'u' : '-',
    -		m & S_ISGID ? 'g' : '-',
    -		m & S_ISVTX ? 'v' : '-',
    -		m & S_IRUSR ? 'r' : '-',
    -		m & S_IWUSR ? 'w' : '-',
    -		m & S_IXUSR ? 'x' : '-',
    -		m & S_IRGRP ? 'r' : '-',
    -		m & S_IWGRP ? 'w' : '-',
    -		m & S_IXGRP ? 'x' : '-',
    -		m & S_IROTH ? 'r' : '-',
    -		m & S_IWOTH ? 'w' : '-',
    -		m & S_IXOTH ? 'x' : '-');
    -	return rval;
    -}
    -
    -/*
    - * Format a size into a static buffer & return it.
    - */
    -static char *
    -xfs_fmtsize(size_t i)
    -{
    -	static char rval[20];
    -
    -	/* size_t is 32 bits in 32-bit kernel, 64 bits in 64-bit kernel */
    -	sprintf(rval, "0x%lx", (unsigned long) i);
    -	return rval;
    -}
    -
    -/*
    - * Format a uuid into a static buffer & return it.
    - */
    -static char *
    -xfs_fmtuuid(uuid_t *uu)
    -{
    -	static char rval[40];
    -	char	*o	  = rval;
    -	char	*i	  = (unsigned char*)uu;
    -	int	 b;
    -
    -	for (b=0;b<16;b++) {
    -	    o+=sprintf(o, "%02x", *i++);
    -	    if (b==3||b==5||b==7||b==9) *o++='-';
    -	}
    -	*o='\0';
    -
    -	return rval;
    -}
    -
    -/*
    - * Print an inode log item.
    - */
    -static void
    -xfs_inode_item_print(xfs_inode_log_item_t *ilip, int summary)
    -{
    -	static char *ili_flags[] = {
    -		"hold",		/* 0x1 */
    -		"iolock excl",	/* 0x2 */
    -		"iolock shrd",	/* 0x4 */
    -		NULL
    -		};
    -	static char *ilf_fields[] = {
    -		"core",		/* 0x001 */
    -		"ddata",	/* 0x002 */
    -		"dexts",	/* 0x004 */
    -		"dbroot",	/* 0x008 */
    -		"dev",		/* 0x010 */
    -		"uuid",		/* 0x020 */
    -		"adata",	/* 0x040 */
    -		"aext",		/* 0x080 */
    -		"abroot",	/* 0x100 */
    -		NULL
    -		};
    -
    -	if (summary) {
    -		kdb_printf("inode 0x%p logged %d ",
    -			ilip->ili_inode, ilip->ili_logged);
    -		printflags(ilip->ili_flags, ili_flags, "flags:");
    -		printflags(ilip->ili_format.ilf_fields, ilf_fields, "format:");
    -		printflags(ilip->ili_last_fields, ilf_fields, "lastfield:");
    -		kdb_printf("\n");
    -		return;
    -	}
    -	kdb_printf("inode 0x%p ino 0x%llu pushbuf %d logged %d flags: ",
    -		ilip->ili_inode, (unsigned long long) ilip->ili_format.ilf_ino,
    -		ilip->ili_pushbuf_flag, ilip->ili_logged);
    -	printflags(ilip->ili_flags, ili_flags, NULL);
    -	kdb_printf("\n");
    -	kdb_printf("ilock recur %d iolock recur %d ext buf 0x%p\n",
    -		ilip->ili_ilock_recur, ilip->ili_iolock_recur,
    -		ilip->ili_extents_buf);
    -#ifdef XFS_TRANS_DEBUG
    -	kdb_printf("root bytes %d root orig 0x%x\n",
    -		ilip->ili_root_size, ilip->ili_orig_root);
    -#endif
    -	kdb_printf("size %d ", ilip->ili_format.ilf_size);
    -	printflags(ilip->ili_format.ilf_fields, ilf_fields, "fields:");
    -	printflags(ilip->ili_last_fields, ilf_fields, " last fields: ");
    -	kdb_printf("\n");
    -	kdb_printf(" flush lsn %s last lsn %s\n",
    -		xfs_fmtlsn(&(ilip->ili_flush_lsn)),
    -		xfs_fmtlsn(&(ilip->ili_last_lsn)));
    -	kdb_printf("dsize %d, asize %d, rdev 0x%x\n",
    -		ilip->ili_format.ilf_dsize,
    -		ilip->ili_format.ilf_asize,
    -		ilip->ili_format.ilf_u.ilfu_rdev);
    -	kdb_printf("blkno 0x%Lx len 0x%x boffset 0x%x\n",
    -		ilip->ili_format.ilf_blkno,
    -		ilip->ili_format.ilf_len,
    -		ilip->ili_format.ilf_boffset);
    -}
    -
    -/*
    - * Print a dquot log item.
    - */
    -/* ARGSUSED */
    -static void
    -xfs_dquot_item_print(xfs_dq_logitem_t *lip, int summary)
    -{
    -	kdb_printf("dquot 0x%p\n",
    -		lip->qli_dquot);
    -
    -}
    -
    -/*
    - * Print a quotaoff log item.
    - */
    -/* ARGSUSED */
    -static void
    -xfs_qoff_item_print(xfs_qoff_logitem_t *lip, int summary)
    -{
    -	kdb_printf("start qoff item 0x%p flags 0x%x\n",
    -		lip->qql_start_lip, lip->qql_format.qf_flags);
    -
    -}
    -
    -/*
    - * Print buffer full of inodes.
    - */
    -static void
    -xfs_inodebuf(xfs_buf_t *bp)
    -{
    -	xfs_dinode_t *di;
    -	xfs_dinode_core_t dic;
    -	int n, i;
    -
    -	n = XFS_BUF_COUNT(bp) >> 8;
    -	for (i = 0; i < n; i++) {
    -		di = (xfs_dinode_t *)xfs_buf_offset(bp,
    -					i * 256);
    -
    -		xfs_xlate_dinode_core((xfs_caddr_t)&di->di_core, &dic, 1);
    -		xfs_prdinode_core(&dic);
    -		kdb_printf("next_unlinked 0x%x u@0x%p\n",
    -			   INT_GET(di->di_next_unlinked, ARCH_CONVERT),
    -			   &di->di_u);
    -	}
    -}
    -
    -#ifdef XFS_RW_TRACE
    -/*
    - * Print iomap entry trace.
    - */
    -static void
    -xfs_iomap_enter_trace_entry(ktrace_entry_t *ktep)
    -{
    -	qprintf("ip 0x%p size 0x%x%x offset 0x%x%x count 0x%x\n",
    -		ktep->val[1],
    -		(unsigned int)(long)ktep->val[2],
    -		(unsigned int)(long)ktep->val[3],
    -		(unsigned int)(long)ktep->val[4],
    -		(unsigned int)(long)ktep->val[5],
    -		(unsigned int)(long)ktep->val[6]);
    -	qprintf("io new size 0x%x%x pid=%d\n",
    -		(unsigned int)(long)ktep->val[7],
    -		(unsigned int)(long)ktep->val[8],
    -		(unsigned int)(long)ktep->val[9]);
    -}
    -
    -/*
    - * Print iomap map trace.
    - */
    -static void
    -xfs_iomap_map_trace_entry(ktrace_entry_t *ktep)
    -{
    -	static char *bmapi_flags[] = {
    -		"read",		/* BMAPI_READ */
    -		"write",	/* BMAPI_WRITE */
    -		"allocate",	/* BMAPI_ALLOCATE */
    -		"unwritten",	/* BMAPI_UNWRITTEN */
    -		"ignstate",	/* BMAPI_IGNSTATE */
    -		"direct",	/* BMAPI_DIRECT */
    -		"mmap",		/* BMAPI_MMAP */
    -		"sync",		/* BMAPI_SYNC */
    -		"trylock",	/* BMAPI_TRYLOCK */
    -		"device",	/* BMAPI_DEVICE */
    -		NULL
    -	};
    -
    -	qprintf("ip 0x%p size 0x%x%x offset 0x%x%x count 0x%x\n",
    -		ktep->val[1],
    -		(unsigned int)(long)ktep->val[2],
    -		(unsigned int)(long)ktep->val[3],
    -		(unsigned int)(long)ktep->val[4],
    -		(unsigned int)(long)ktep->val[5],
    -		(unsigned int)(long)ktep->val[6]);
    -	printflags((__psint_t)ktep->val[7], bmapi_flags, "bmapi flags");
    -	qprintf("iomap off 0x%x%x delta 0x%x bsize 0x%x bno 0x%x\n",
    -		(unsigned int)(long)ktep->val[8],
    -		(unsigned int)(long)ktep->val[9],
    -		(unsigned int)(long)ktep->val[10],
    -		(unsigned int)(long)ktep->val[11],
    -		(unsigned int)(long)ktep->val[12]);
    -	qprintf("imap off 0x%x count 0x%x block 0x%x\n",
    -		(unsigned int)(long)ktep->val[13],
    -		(unsigned int)(long)ktep->val[14],
    -		(unsigned int)(long)ktep->val[15]);
    -}
    -
    -/*
    - * Print itrunc entry trace.
    - */
    -static void
    -xfs_itrunc_trace_entry(ktrace_entry_t   *ktep)
    -{
    -	qprintf("ip 0x%p size 0x%x%x flag %ld new size 0x%x%x\n",
    -		ktep->val[1],
    -		(unsigned int)(long)ktep->val[2],
    -		(unsigned int)(long)ktep->val[3],
    -		(long)ktep->val[4],
    -		(unsigned int)(long)ktep->val[5],
    -		(unsigned int)(long)ktep->val[6]);
    -	qprintf("toss start 0x%x%x toss finish 0x%x%x cpu id %ld pid %d\n",
    -		(unsigned int)(long)ktep->val[7],
    -		(unsigned int)(long)ktep->val[8],
    -		(unsigned int)(long)ktep->val[9],
    -		(unsigned int)(long)ktep->val[10],
    -		(long)ktep->val[11],
    -		(unsigned int)(long)ktep->val[12]);
    -}
    -
    -/*
    - * Print bunmap entry trace.
    - */
    -static void
    -xfs_bunmap_trace_entry(ktrace_entry_t   *ktep)
    -{
    -	static char *bunmapi_flags[] = {
    -		"write",	/* 0x01 */
    -		"delay",	/* 0x02 */
    -		"entire",       /* 0x04 */
    -		"metadata",     /* 0x08 */
    -		"exact",	/* 0x10 */
    -		"attrfork",     /* 0x20 */
    -		"async",	/* 0x40 */
    -		"rsvblocks",    /* 0x80 */
    -		NULL
    -	};
    -
    -	qprintf("ip 0x%p size 0x%x%x bno 0x%x%x len 0x%x cpu id %ld\n",
    -		ktep->val[1],
    -		(unsigned int)(long)ktep->val[2],
    -		(unsigned int)(long)ktep->val[3],
    -		(unsigned int)(long)ktep->val[4],
    -		(unsigned int)(long)ktep->val[5],
    -		(unsigned int)(long)ktep->val[6],
    -		(long)ktep->val[8]);
    -	qprintf("ra 0x%p pid %d ", ktep->val[9], (int)(long)ktep->val[10]);
    -	printflags((__psint_t)ktep->val[7], bunmapi_flags, "flags");
    -}
    -
    -/*
    - * Print inval_cached_pages entry trace.
    - */
    -static void
    -xfs_inval_cached_trace_entry(ktrace_entry_t     *ktep)
    -{
    -	qprintf("ip 0x%p offset 0x%x%x len 0x%x%x first 0x%x%x last 0x%x%x pid %d\n",
    -		ktep->val[1],
    -		(unsigned int)(long)ktep->val[2],
    -		(unsigned int)(long)ktep->val[3],
    -		(unsigned int)(long)ktep->val[4],
    -		(unsigned int)(long)ktep->val[5],
    -		(unsigned int)(long)ktep->val[6],
    -		(unsigned int)(long)ktep->val[7],
    -		(unsigned int)(long)ktep->val[8],
    -		(unsigned int)(long)ktep->val[9],
    -		(unsigned int)(long)ktep->val[10]);
    -}
    -#endif
    -
    -
    -/*
    - * Print disk inode core.
    - */
    -static void
    -xfs_prdinode_core(xfs_dinode_core_t *dip)
    -{
    -	static char *diflags[] = {
    -		"realtime",		/* XFS_DIFLAG_REALTIME */
    -		"prealloc",		/* XFS_DIFLAG_PREALLOC */
    -		"newrtbm",		/* XFS_DIFLAG_NEWRTBM */
    -		"immutable",		/* XFS_DIFLAG_IMMUTABLE */
    -		"append",		/* XFS_DIFLAG_APPEND */
    -		"sync",			/* XFS_DIFLAG_SYNC */
    -		"noatime",		/* XFS_DIFLAG_NOATIME */
    -		"nodump",		/* XFS_DIFLAG_NODUMP */
    -		"rtinherit",		/* XFS_DIFLAG_RTINHERIT */
    -		"projinherit",		/* XFS_DIFLAG_PROJINHERIT */
    -		"nosymlinks",		/* XFS_DIFLAG_NOSYMLINKS */
    -		"extsize",		/* XFS_DIFLAG_EXTSIZE */
    -		"extszinherit",		/* XFS_DIFLAG_EXTSZINHERIT */
    -		NULL
    -	};
    -
    -	kdb_printf("magic 0x%x mode 0%o (%s) version 0x%x format 0x%x (%s)\n",
    -		dip->di_magic, dip->di_mode,
    -		xfs_fmtmode(dip->di_mode),
    -		dip->di_version, dip->di_format,
    -		xfs_fmtformat((xfs_dinode_fmt_t)dip->di_format));
    -	kdb_printf("nlink %d uid %d gid %d projid %d flushiter %u\n",
    -		dip->di_nlink,
    -		dip->di_uid,
    -		dip->di_gid,
    -		(uint)dip->di_projid,
    -		(uint)dip->di_flushiter);
    -	kdb_printf("atime %u:%u mtime %ud:%u ctime %u:%u\n",
    -		dip->di_atime.t_sec, dip->di_atime.t_nsec,
    -		dip->di_mtime.t_sec, dip->di_mtime.t_nsec,
    -		dip->di_ctime.t_sec, dip->di_ctime.t_nsec);
    -	kdb_printf("size %Ld ", dip->di_size);
    -	kdb_printf("nblocks %Ld extsize 0x%x nextents 0x%x anextents 0x%x\n",
    -		dip->di_nblocks, dip->di_extsize, dip->di_nextents,
    -		dip->di_anextents);
    -	kdb_printf("forkoff %d aformat 0x%x (%s) dmevmask 0x%x dmstate 0x%x ",
    -		dip->di_forkoff, dip->di_aformat,
    -		xfs_fmtformat((xfs_dinode_fmt_t)dip->di_aformat),
    -		dip->di_dmevmask, dip->di_dmstate);
    -	printflags(dip->di_flags, diflags, "flags");
    -	kdb_printf("gen 0x%x\n", dip->di_gen);
    -}
    -
    -#ifdef XFS_RW_TRACE
    -/*
    - * Print read/write entry trace.
    - */
    -static void
    -xfs_rw_enter_trace_entry(ktrace_entry_t *ktep)
    -{
    -	qprintf("ip 0x%p size 0x%x%x ptr 0x%p size %lu\n",
    -		ktep->val[1],
    -		(unsigned int)(long)ktep->val[2],
    -		(unsigned int)(long)ktep->val[3],
    -		ktep->val[4],
    -		(unsigned long)ktep->val[5]);
    -	qprintf("io offset 0x%x%x ioflags 0x%x new size 0x%x%x pid %d\n",
    -		(unsigned int)(long)ktep->val[6],
    -		(unsigned int)(long)ktep->val[7],
    -		(unsigned int)(long)ktep->val[8],
    -		(unsigned int)(long)ktep->val[9],
    -		(unsigned int)(long)ktep->val[10],
    -		(unsigned int)(long)ktep->val[11]);
    -}
    -
    -/*
    - * Print page write/release trace.
    - */
    -static void
    -xfs_page_trace_entry(ktrace_entry_t *ktep)
    -{
    -	qprintf("ip 0x%p inode 0x%p page 0x%p\n",
    -		ktep->val[1], ktep->val[2], ktep->val[3]);
    -	qprintf("mask 0x%x di_size 0x%x%x isize 0x%x%x offset 0x%x%x\n",
    -		(unsigned int)(long)ktep->val[4],
    -		(unsigned int)(long)ktep->val[5],
    -		(unsigned int)(long)ktep->val[6],
    -		(unsigned int)(long)ktep->val[7],
    -		(unsigned int)(long)ktep->val[8],
    -		(unsigned int)(long)ktep->val[9],
    -		(unsigned int)(long)ktep->val[10]);
    -	qprintf("delalloc %d unmapped %d unwritten %d pid %d\n",
    -		(unsigned int)(long)ktep->val[11],
    -		(unsigned int)(long)ktep->val[12],
    -		(unsigned int)(long)ktep->val[13],
    -		(unsigned int)(long)ktep->val[14]);
    -}
    -
    -/*
    - * Print read/write trace entry.
    - */
    -static int
    -xfs_rw_trace_entry(ktrace_entry_t *ktep)
    -{
    -	switch ( (long)ktep->val[0] ) {
    -	case XFS_READ_ENTER:
    -		qprintf("READ ENTER:\n");
    -		xfs_rw_enter_trace_entry(ktep);
    -		break;
    -	case XFS_WRITE_ENTER:
    -		qprintf("WRITE ENTER:\n");
    -		xfs_rw_enter_trace_entry(ktep);
    -		break;
    -	case XFS_SENDFILE_ENTER:
    -		qprintf("SENDFILE ENTER:\n");
    -		xfs_rw_enter_trace_entry(ktep);
    -		break;
    -	case XFS_IOMAP_READ_ENTER:
    -		qprintf("IOMAP READ ENTER:\n");
    -		xfs_iomap_enter_trace_entry(ktep);
    -		break;
    -	case XFS_IOMAP_WRITE_ENTER:
    -		qprintf("IOMAP WRITE ENTER:\n");
    -		xfs_iomap_enter_trace_entry(ktep);
    -		break;
    -	case XFS_IOMAP_WRITE_NOSPACE:
    -		qprintf("IOMAP WRITE NOSPACE:\n");
    -		xfs_iomap_enter_trace_entry(ktep);
    -		break;
    -	case XFS_IOMAP_READ_MAP:
    -		qprintf("IOMAP READ MAP:\n");
    -		xfs_iomap_map_trace_entry(ktep);
    -		break;
    -	case XFS_IOMAP_WRITE_MAP:
    -		qprintf("IOMAP WRITE MAP:\n");
    -		xfs_iomap_map_trace_entry(ktep);
    -		break;
    -	case XFS_ITRUNC_START:
    -		qprintf("ITRUNC START:\n");
    -		xfs_itrunc_trace_entry(ktep);
    -		break;
    -	case XFS_ITRUNC_FINISH1:
    -		qprintf("ITRUNC FINISH1:\n");
    -		xfs_itrunc_trace_entry(ktep);
    -		break;
    -	case XFS_ITRUNC_FINISH2:
    -		qprintf("ITRUNC FINISH2:\n");
    -		xfs_itrunc_trace_entry(ktep);
    -		break;
    -	case XFS_CTRUNC1:
    -		qprintf("CTRUNC1:\n");
    -		xfs_ctrunc_trace_entry(ktep);
    -		break;
    -	case XFS_CTRUNC2:
    -		qprintf("CTRUNC2:\n");
    -		xfs_ctrunc_trace_entry(ktep);
    -		break;
    -	case XFS_CTRUNC3:
    -		qprintf("CTRUNC3:\n");
    -		xfs_ctrunc_trace_entry(ktep);
    -		break;
    -	case XFS_CTRUNC4:
    -		qprintf("CTRUNC4:\n");
    -		xfs_ctrunc_trace_entry(ktep);
    -		break;
    -	case XFS_CTRUNC5:
    -		qprintf("CTRUNC5:\n");
    -		xfs_ctrunc_trace_entry(ktep);
    -		break;
    -	case XFS_CTRUNC6:
    -		qprintf("CTRUNC6:\n");
    -		xfs_ctrunc_trace_entry(ktep);
    -		break;
    -	case XFS_BUNMAP:
    -		qprintf("BUNMAP:\n");
    -		xfs_bunmap_trace_entry(ktep);
    -		break;
    -	case XFS_INVAL_CACHED:
    -		qprintf("INVAL CACHED:\n");
    -		xfs_inval_cached_trace_entry(ktep);
    -		break;
    -	case XFS_DIORD_ENTER:
    -		qprintf("DIORD ENTER:\n");
    -		xfs_rw_enter_trace_entry(ktep);
    -		break;
    -	case XFS_DIOWR_ENTER:
    -		qprintf("DIOWR ENTER:\n");
    -		xfs_rw_enter_trace_entry(ktep);
    -		break;
    -	case XFS_WRITEPAGE_ENTER:
    -		qprintf("PAGE WRITE:\n");
    -		xfs_page_trace_entry(ktep);
    -		break;
    -	case XFS_RELEASEPAGE_ENTER:
    -		qprintf("PAGE RELEASE:\n");
    -		xfs_page_trace_entry(ktep);
    -		break;
    -	case XFS_INVALIDPAGE_ENTER:
    -		qprintf("PAGE INVALIDATE:\n");
    -		xfs_page_trace_entry(ktep);
    -		break;
    -	case XFS_IOMAP_ALLOC_ENTER:
    -		qprintf("ALLOC ENTER:\n");
    -		xfs_iomap_enter_trace_entry(ktep);
    -		break;
    -	case XFS_IOMAP_ALLOC_MAP:
    -		qprintf("ALLOC MAP:\n");
    -		xfs_iomap_map_trace_entry(ktep);
    -		break;
    -	case XFS_IOMAP_UNWRITTEN:
    -		qprintf("UNWRITTEN:\n");
    -		xfs_iomap_enter_trace_entry(ktep);
    -		break;
    -
    -	default:
    -		qprintf("UNKNOWN RW TRACE\n");
    -		return 0;
    -	}
    -
    -	return 1;
    -}
    -#endif
    -
    -/*
    - * Print xfs extent records for a fork.
    - */
    -static void
    -xfs_xexlist_fork(xfs_inode_t *ip, int whichfork)
    -{
    -	int nextents, i;
    -	xfs_ifork_t *ifp;
    -	xfs_bmbt_irec_t irec;
    -
    -	ifp = XFS_IFORK_PTR(ip, whichfork);
    -	if (ifp->if_flags & XFS_IFEXTENTS) {
    -		nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
    -		kdb_printf("inode 0x%p %cf extents 0x%p nextents 0x%x\n",
    -			ip, "da"[whichfork], xfs_iext_get_ext(ifp, 0),
    -			nextents);
    -		for (i = 0; i < nextents; i++) {
    -			xfs_bmbt_get_all(xfs_iext_get_ext(ifp, i), &irec);
    -			kdb_printf(
    -		"%d: startoff %Ld startblock %s blockcount %Ld flag %d\n",
    -			i, irec.br_startoff,
    -			xfs_fmtfsblock(irec.br_startblock, ip->i_mount),
    -			irec.br_blockcount, irec.br_state);
    -		}
    -	}
    -}
    -
    -static void
    -xfs_xnode_fork(char *name, xfs_ifork_t *f)
    -{
    -	static char *tab_flags[] = {
    -		"inline",	/* XFS_IFINLINE */
    -		"extents",	/* XFS_IFEXTENTS */
    -		"broot",	/* XFS_IFBROOT */
    -		NULL
    -	};
    -	int *p;
    -
    -	kdb_printf("%s fork", name);
    -	if (f == NULL) {
    -		kdb_printf(" empty\n");
    -		return;
    -	} else
    -		kdb_printf("\n");
    -	kdb_printf(" bytes %s ", xfs_fmtsize(f->if_bytes));
    -	kdb_printf("real_bytes %s lastex 0x%x u1:%s 0x%p\n",
    -		xfs_fmtsize(f->if_real_bytes), f->if_lastex,
    -		f->if_flags & XFS_IFINLINE ? "data" : "extents",
    -		f->if_flags & XFS_IFINLINE ?
    -			f->if_u1.if_data :
    -			(char *)f->if_u1.if_extents);
    -	kdb_printf(" broot 0x%p broot_bytes %s ext_max %d ",
    -		f->if_broot, xfs_fmtsize(f->if_broot_bytes), f->if_ext_max);
    -	printflags(f->if_flags, tab_flags, "flags");
    -	kdb_printf("\n");
    -	kdb_printf(" u2");
    -	for (p = (int *)&f->if_u2;
    -	     p < (int *)((char *)&f->if_u2 + XFS_INLINE_DATA);
    -	     p++)
    -		kdb_printf(" 0x%x", *p);
    -	kdb_printf("\n");
    -}
    -
    -/*
    - * Command-level xfs-idbg functions.
    - */
    -
    -/*
    - * Print xfs allocation group freespace header.
    - */
    -static void
    -xfsidbg_xagf(xfs_agf_t *agf)
    -{
    -	kdb_printf("magicnum 0x%x versionnum 0x%x seqno 0x%x length 0x%x\n",
    -		be32_to_cpu(agf->agf_magicnum),
    -		be32_to_cpu(agf->agf_versionnum),
    -		be32_to_cpu(agf->agf_seqno),
    -		be32_to_cpu(agf->agf_length));
    -	kdb_printf("roots b 0x%x c 0x%x levels b %d c %d\n",
    -		be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNO]),
    -		be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNT]),
    -		be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]),
    -		be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]));
    -	kdb_printf("flfirst %d fllast %d flcount %d freeblks %d longest %d\n",
    -		be32_to_cpu(agf->agf_flfirst),
    -		be32_to_cpu(agf->agf_fllast),
    -		be32_to_cpu(agf->agf_flcount),
    -		be32_to_cpu(agf->agf_freeblks),
    -		be32_to_cpu(agf->agf_longest));
    -}
    -
    -/*
    - * Print xfs allocation group inode header.
    - */
    -static void
    -xfsidbg_xagi(xfs_agi_t *agi)
    -{
    -	int	i;
    -	int	j;
    -
    -	kdb_printf("magicnum 0x%x versionnum 0x%x seqno 0x%x length 0x%x\n",
    -		be32_to_cpu(agi->agi_magicnum),
    -		be32_to_cpu(agi->agi_versionnum),
    -		be32_to_cpu(agi->agi_seqno),
    -		be32_to_cpu(agi->agi_length));
    -	kdb_printf("count 0x%x root 0x%x level 0x%x\n",
    -		be32_to_cpu(agi->agi_count),
    -		be32_to_cpu(agi->agi_root),
    -		be32_to_cpu(agi->agi_level));
    -	kdb_printf("freecount 0x%x newino 0x%x dirino 0x%x\n",
    -		be32_to_cpu(agi->agi_freecount),
    -		be32_to_cpu(agi->agi_newino),
    -		be32_to_cpu(agi->agi_dirino));
    -
    -	kdb_printf("unlinked buckets\n");
    -	for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++) {
    -		for (j = 0; j < 4; j++, i++) {
    -			kdb_printf("0x%08x ",
    -				be32_to_cpu(agi->agi_unlinked[i]));
    -		}
    -		kdb_printf("\n");
    -	}
    -}
    -
    -#ifdef XFS_ALLOC_TRACE
    -/*
    - * Print out the last "count" entries in the allocation trace buffer.
    - */
    -static void
    -xfsidbg_xalatrace(int count)
    -{
    -	ktrace_entry_t  *ktep;
    -	ktrace_snap_t   kts;
    -	int	     nentries;
    -	int	     skip_entries;
    -
    -	if (xfs_alloc_trace_buf == NULL) {
    -		qprintf("The xfs alloc trace buffer is not initialized\n");
    -		return;
    -	}
    -	nentries = ktrace_nentries(xfs_alloc_trace_buf);
    -	if (count == -1) {
    -		count = nentries;
    -	}
    -	if ((count <= 0) || (count > nentries)) {
    -		qprintf("Invalid count.  There are %d entries.\n", nentries);
    -		return;
    -	}
    -
    -	ktep = ktrace_first(xfs_alloc_trace_buf, &kts);
    -	if (count != nentries) {
    -		/*
    -		 * Skip the total minus the number to look at minus one
    -		 * for the entry returned by ktrace_first().
    -		 */
    -		skip_entries = nentries - count - 1;
    -		ktep = ktrace_skip(xfs_alloc_trace_buf, skip_entries, &kts);
    -		if (ktep == NULL) {
    -			qprintf("Skipped them all\n");
    -			return;
    -		}
    -	}
    -	while (ktep != NULL) {
    -		if (xfs_alloc_trace_entry(ktep))
    -			qprintf("\n");
    -		ktep = ktrace_next(xfs_alloc_trace_buf, &kts);
    -	}
    -}
    -
    -/*
    - * Print out all the entries in the alloc trace buf corresponding
    - * to the given block number.
    - */
    -static void
    -xfsidbg_xalbtrace(xfs_agblock_t bno)
    -{
    -	ktrace_entry_t  *ktep;
    -	ktrace_snap_t   kts;
    -
    -	if (xfs_alloc_trace_buf == NULL) {
    -		qprintf("The xfs alloc trace buffer is not initialized\n");
    -		return;
    -	}
    -
    -	ktep = ktrace_first(xfs_alloc_trace_buf, &kts);
    -	while (ktep != NULL) {
    -		switch ((__psint_t)ktep->val[0]) {
    -		case XFS_ALLOC_KTRACE_ALLOC:
    -		case XFS_ALLOC_KTRACE_FREE:
    -			if (bno >= (xfs_agblock_t)((__psint_t)ktep->val[5]) &&
    -			    bno < (xfs_agblock_t)((__psint_t)ktep->val[5]) +
    -				  (xfs_extlen_t)((__psint_t)ktep->val[13])) {
    -				(void)xfs_alloc_trace_entry(ktep);
    -				qprintf("\n");
    -			}
    -			break;
    -		}
    -		ktep = ktrace_next(xfs_alloc_trace_buf, &kts);
    -	}
    -}
    -
    -/*
    - * Print out all the entries in the alloc trace buf corresponding
    - * to the given allocation group.
    - */
    -static void
    -xfsidbg_xalgtrace(xfs_agnumber_t agno)
    -{
    -	ktrace_entry_t  *ktep;
    -	ktrace_snap_t   kts;
    -
    -	if (xfs_alloc_trace_buf == NULL) {
    -		qprintf("The xfs alloc trace buffer is not initialized\n");
    -		return;
    -	}
    -
    -	ktep = ktrace_first(xfs_alloc_trace_buf, &kts);
    -	while (ktep != NULL) {
    -		if (  (__psint_t)ktep->val[0] &&
    -		      ((xfs_agnumber_t)((__psint_t)ktep->val[4])) == agno ) {
    -			(void)xfs_alloc_trace_entry(ktep);
    -			qprintf("\n");
    -		}
    -		ktep = ktrace_next(xfs_alloc_trace_buf, &kts);
    -	}
    -}
    -#endif
    -
    -/*
    - * Print an allocation argument structure for XFS.
    - */
    -static void
    -xfsidbg_xalloc(xfs_alloc_arg_t *args)
    -{
    -	kdb_printf("tp 0x%p mp 0x%p agbp 0x%p pag 0x%p fsbno %s\n",
    -		args->tp, args->mp, args->agbp, args->pag,
    -		xfs_fmtfsblock(args->fsbno, args->mp));
    -	kdb_printf("agno 0x%x agbno 0x%x minlen 0x%x maxlen 0x%x mod 0x%x\n",
    -		args->agno, args->agbno, args->minlen, args->maxlen, args->mod);
    -	kdb_printf("prod 0x%x minleft 0x%x total 0x%x alignment 0x%x\n",
    -		args->prod, args->minleft, args->total, args->alignment);
    -	kdb_printf("minalignslop 0x%x len 0x%x type %s otype %s wasdel %d\n",
    -		args->minalignslop, args->len, xfs_alloctype[args->type],
    -		xfs_alloctype[args->otype], args->wasdel);
    -	kdb_printf("wasfromfl %d isfl %d userdata %d\n",
    -		args->wasfromfl, args->isfl, args->userdata);
    -}
    -
    -#ifdef XFS_ALLOC_TRACE
    -/*
    - * Print out all the entries in the alloc trace buf corresponding
    - * to the given mount point.
    - */
    -static void
    -xfsidbg_xalmtrace(xfs_mount_t *mp)
    -{
    -	ktrace_entry_t	*ktep;
    -	ktrace_snap_t	kts;
    -
    -	if (xfs_alloc_trace_buf == NULL) {
    -		kdb_printf("The xfs alloc trace buffer is not initialized\n");
    -		return;
    -	}
    -
    -	ktep = ktrace_first(xfs_alloc_trace_buf, &kts);
    -	while (ktep != NULL) {
    -		if ((__psint_t)ktep->val[0] &&
    -		    (xfs_mount_t *)ktep->val[3] == mp) {
    -			(void)xfs_alloc_trace_entry(ktep);
    -			kdb_printf("\n");
    -		}
    -		ktep = ktrace_next(xfs_alloc_trace_buf, &kts);
    -	}
    -}
    -
    -/*
    - * Print out all the entries in the alloc trace buf corresponding
    - * to the given entry type.
    - */
    -static void
    -xfsidbg_xalttrace(int tag)
    -{
    -	ktrace_entry_t  *ktep;
    -	ktrace_snap_t   kts;
    -
    -	if (xfs_alloc_trace_buf == NULL) {
    -		qprintf("The xfs alloc trace buffer is not initialized\n");
    -		return;
    -	}
    -
    -	ktep = ktrace_first(xfs_alloc_trace_buf, &kts);
    -	while (ktep != NULL) {
    -		if ((__psint_t)ktep->val[0] &&
    -		    ((long)ktep->val[0] & 0xffffL) == (long)tag) {
    -			(void)xfs_alloc_trace_entry(ktep);
    -			qprintf("\n");
    -		}
    -		ktep = ktrace_next(xfs_alloc_trace_buf, &kts);
    -	}
    -}
    -#endif
    -
    -static int xargument = 0;
    -
    -/*
    - * Set xtra argument, used by xchksum.
    - */
    -static void
    -xfsidbg_xarg(int xarg)
    -{
    -	if (xarg == -1)
    -		qprintf("xargument: %d\n", xargument);
    -	else
    -		xargument = xarg;
    -}       /* xfsidbg_xarg */
    -
    -/*
    - * Print an attr_list() context structure.
    - */
    -static void
    -xfsidbg_xattrcontext(xfs_attr_list_context_t *context)
    -{
    -	static char *attr_arg_flags[] = {
    -		"DONTFOLLOW",	/* 0x0001 */
    -		"?",		/* 0x0002 */
    -		"?",		/* 0x0004 */
    -		"?",		/* 0x0008 */
    -		"CREATE",	/* 0x0010 */
    -		"?",		/* 0x0020 */
    -		"?",		/* 0x0040 */
    -		"?",		/* 0x0080 */
    -		"?",		/* 0x0100 */
    -		"?",		/* 0x0200 */
    -		"?",		/* 0x0400 */
    -		"?",		/* 0x0800 */
    -		"KERNOTIME",	/* 0x1000 */
    -		NULL
    -	};
    -
    -	kdb_printf("dp 0x%p, dupcnt %d, resynch %d",
    -		    context->dp, context->dupcnt, context->resynch);
    -	printflags((__psunsigned_t)context->flags, attr_arg_flags, ", flags");
    -	kdb_printf("\ncursor h/b/o 0x%x/0x%x/%d -- p/p/i 0x%x/0x%x/0x%x\n",
    -			  context->cursor->hashval, context->cursor->blkno,
    -			  context->cursor->offset, context->cursor->pad1,
    -			  context->cursor->pad2, context->cursor->initted);
    -	kdb_printf("alist 0x%p, bufsize 0x%x, count %d, firstu 0x%x\n",
    -		       context->alist, context->bufsize, context->count,
    -		       context->firstu);
    -}
    -
    -/*
    - * Print attribute leaf block.
    - */
    -static void
    -xfsidbg_xattrleaf(xfs_attr_leafblock_t *leaf)
    -{
    -	xfs_attr_leaf_hdr_t *h;
    -	xfs_da_blkinfo_t *i;
    -	xfs_attr_leaf_map_t *m;
    -	xfs_attr_leaf_entry_t *e;
    -	xfs_attr_leaf_name_local_t *l;
    -	xfs_attr_leaf_name_remote_t *r;
    -	int j, k;
    -
    -	h = &leaf->hdr;
    -	i = &h->info;
    -	kdb_printf("hdr info forw 0x%x back 0x%x magic 0x%x\n",
    -		i->forw, i->back, i->magic);
    -	kdb_printf("hdr count %d usedbytes %d firstused %d holes %d\n",
    -		INT_GET(h->count, ARCH_CONVERT),
    -		INT_GET(h->usedbytes, ARCH_CONVERT),
    -		INT_GET(h->firstused, ARCH_CONVERT), h->holes);
    -	for (j = 0, m = h->freemap; j < XFS_ATTR_LEAF_MAPSIZE; j++, m++) {
    -		kdb_printf("hdr freemap %d base %d size %d\n",
    -			j, INT_GET(m->base, ARCH_CONVERT),
    -			INT_GET(m->size, ARCH_CONVERT));
    -	}
    -	for (j = 0, e = leaf->entries; j < INT_GET(h->count, ARCH_CONVERT); j++, e++) {
    -		kdb_printf("[%2d] hash 0x%x nameidx %d flags 0x%x",
    -			j, INT_GET(e->hashval, ARCH_CONVERT),
    -			INT_GET(e->nameidx, ARCH_CONVERT), e->flags);
    -		if (e->flags & XFS_ATTR_LOCAL)
    -			kdb_printf("LOCAL ");
    -		if (e->flags & XFS_ATTR_ROOT)
    -			kdb_printf("ROOT ");
    -		if (e->flags & XFS_ATTR_SECURE)
    -			kdb_printf("SECURE ");
    -		if (e->flags & XFS_ATTR_INCOMPLETE)
    -			kdb_printf("INCOMPLETE ");
    -		k = ~(XFS_ATTR_LOCAL | XFS_ATTR_ROOT |
    -			XFS_ATTR_SECURE | XFS_ATTR_INCOMPLETE);
    -		if ((e->flags & k) != 0)
    -			kdb_printf("0x%x", e->flags & k);
    -		kdb_printf(">\n     name \"");
    -		if (e->flags & XFS_ATTR_LOCAL) {
    -			l = XFS_ATTR_LEAF_NAME_LOCAL(leaf, j);
    -			for (k = 0; k < l->namelen; k++)
    -				kdb_printf("%c", l->nameval[k]);
    -			kdb_printf("\"(%d) value \"", l->namelen);
    -			for (k = 0; (k < INT_GET(l->valuelen, ARCH_CONVERT)) && (k < 32); k++)
    -				kdb_printf("%c", l->nameval[l->namelen + k]);
    -			if (k == 32)
    -				kdb_printf("...");
    -			kdb_printf("\"(%d)\n",
    -				INT_GET(l->valuelen, ARCH_CONVERT));
    -		} else {
    -			r = XFS_ATTR_LEAF_NAME_REMOTE(leaf, j);
    -			for (k = 0; k < r->namelen; k++)
    -				kdb_printf("%c", r->name[k]);
    -			kdb_printf("\"(%d) value blk 0x%x len %d\n",
    -				    r->namelen,
    -				    INT_GET(r->valueblk, ARCH_CONVERT),
    -				    INT_GET(r->valuelen, ARCH_CONVERT));
    -		}
    -	}
    -}
    -
    -/*
    - * Print a shortform attribute list.
    - */
    -static void
    -xfsidbg_xattrsf(xfs_attr_shortform_t *s)
    -{
    -	xfs_attr_sf_hdr_t *sfh;
    -	xfs_attr_sf_entry_t *sfe;
    -	int i, j;
    -
    -	sfh = &s->hdr;
    -	kdb_printf("hdr count %d\n", INT_GET(sfh->count, ARCH_CONVERT));
    -	for (i = 0, sfe = s->list; i < INT_GET(sfh->count, ARCH_CONVERT); i++) {
    -		kdb_printf("entry %d namelen %d name \"", i, sfe->namelen);
    -		for (j = 0; j < sfe->namelen; j++)
    -			kdb_printf("%c", sfe->nameval[j]);
    -		kdb_printf("\" valuelen %d value \"", INT_GET(sfe->valuelen, ARCH_CONVERT));
    -		for (j = 0; (j < INT_GET(sfe->valuelen, ARCH_CONVERT)) && (j < 32); j++)
    -			kdb_printf("%c", sfe->nameval[sfe->namelen + j]);
    -		if (j == 32)
    -			kdb_printf("...");
    -		kdb_printf("\"\n");
    -		sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
    -	}
    -}
    -
    -#ifdef XFS_ATTR_TRACE
    -/*
    - * Print out the last "count" entries in the attribute trace buffer.
    - */
    -static void
    -xfsidbg_xattrtrace(int count)
    -{
    -	ktrace_entry_t  *ktep;
    -	ktrace_snap_t   kts;
    -	int	     nentries;
    -	int	     skip_entries;
    -
    -	if (xfs_attr_trace_buf == NULL) {
    -		qprintf("The xfs attribute trace buffer is not initialized\n");
    -		return;
    -	}
    -	nentries = ktrace_nentries(xfs_attr_trace_buf);
    -	if (count == -1) {
    -		count = nentries;
    -	}
    -	if ((count <= 0) || (count > nentries)) {
    -		qprintf("Invalid count.  There are %d entries.\n", nentries);
    -		return;
    -	}
    -
    -	ktep = ktrace_first(xfs_attr_trace_buf, &kts);
    -	if (count != nentries) {
    -		/*
    -		 * Skip the total minus the number to look at minus one
    -		 * for the entry returned by ktrace_first().
    -		 */
    -		skip_entries = nentries - count - 1;
    -		ktep = ktrace_skip(xfs_attr_trace_buf, skip_entries, &kts);
    -		if (ktep == NULL) {
    -			qprintf("Skipped them all\n");
    -			return;
    -		}
    -	}
    -	while (ktep != NULL) {
    -		xfs_attr_trace_entry(ktep);
    -		ktep = ktrace_next(xfs_attr_trace_buf, &kts);
    -	}
    -}
    -#endif
    -
    -/*
    - * Print xfs bmap internal record
    - */
    -static void
    -xfsidbg_xbirec(xfs_bmbt_irec_t *r)
    -{
    -	kdb_printf(
    -	"startoff %Ld startblock %Lx blockcount %Ld state %Ld\n",
    -		(__uint64_t)r->br_startoff,
    -		(__uint64_t)r->br_startblock,
    -		(__uint64_t)r->br_blockcount,
    -		(__uint64_t)r->br_state);
    -}
    -
    -#ifdef XFS_BLI_TRACE
    -/*
    - * Print out the buf log item trace for the given buf log item.
    - */
    -static void
    -xfsidbg_xblitrace(xfs_buf_log_item_t *bip)
    -{
    -	ktrace_entry_t  *ktep;
    -	ktrace_snap_t   kts;
    -	uint64_t	flags;
    -	static char *xbli_flags[] = {
    -		"hold",		/* 0x01 */
    -		"dirty",	/* 0x02 */
    -		"stale",	/* 0x04 */
    -		"logged",	/* 0x08 */
    -		NULL
    -		};
    -	static char *xli_flags[] = {
    -		"in ail",       /* 0x1 */
    -		NULL
    -		};
    -
    -	if (bip->bli_trace == NULL) {
    -		qprintf("The bli trace buffer is not initialized\n");
    -		return;
    -	}
    -
    -	ktep = ktrace_first(bip->bli_trace, &kts);
    -	while (ktep != NULL) {
    -		qprintf("%s bp 0x%p flags ",
    -			(char *)ktep->val[0], ktep->val[1]);
    -		printflags((__psint_t)(ktep->val[2]), xbli_flags, "xbli");
    -		qprintf("\n");
    -		qprintf("recur %ld refcount %ld blkno 0x%lx bcount 0x%lx\n",
    -			(long)ktep->val[3], (long)ktep->val[4],
    -			(unsigned long)ktep->val[5],
    -			(unsigned long)ktep->val[6]);
    -		flags = (((uint64_t)(unsigned long)ktep->val[7] << 32) &
    -					0xFFFFFFFF00000000ULL) |
    -			(((uint64_t)(unsigned long)ktep->val[8]) &
    -					0x00000000FFFFFFFFULL);
    -		qprintf("bp flags ");
    -		printflags(flags, bp_flag_vals, NULL);
    -		qprintf("\n");
    -		qprintf("fspriv 0x%p fspriv2 0x%p pincount %ld iodone 0x%p\n",
    -			ktep->val[9], ktep->val[10],
    -			(long)ktep->val[11], ktep->val[12]);
    -		qprintf("lockval %ld lid 0x%lx log item flags ",
    -			(long)ktep->val[13], (unsigned long)ktep->val[14]);
    -		printflags((__psint_t)(ktep->val[15]), xli_flags, "xli");
    -		qprintf("\n");
    -
    -		ktep = ktrace_next(bip->bli_trace, &kts);
    -	}
    -}
    -#endif
    -
    -/*
    - * Print a bmap alloc argument structure for XFS.
    - */
    -static void
    -xfsidbg_xbmalla(xfs_bmalloca_t *a)
    -{
    -	kdb_printf("tp 0x%p ip 0x%p eof %d prevp 0x%p\n",
    -		a->tp, a->ip, a->eof, a->prevp);
    -	kdb_printf("gotp 0x%p firstblock %s alen %d total %d\n",
    -		a->gotp, xfs_fmtfsblock(a->firstblock, a->ip->i_mount),
    -		a->alen, a->total);
    -	kdb_printf("off %s wasdel %d userdata %d minlen %d\n",
    -		xfs_fmtfsblock(a->off, a->ip->i_mount), a->wasdel,
    -		a->userdata, a->minlen);
    -	kdb_printf("minleft %d low %d rval %s aeof %d conv %d\n",
    -		a->minleft, a->low, xfs_fmtfsblock(a->rval, a->ip->i_mount),
    -		a->aeof, a->conv);
    -}
    -
    -#ifdef XFS_BMAP_TRACE
    -/*
    - * Print out the last "count" entries in the bmap btree trace buffer.
    - * The "a" is for "all" inodes.
    - */
    -static void
    -xfsidbg_xbmatrace(int count)
    -{
    -	ktrace_entry_t  *ktep;
    -	ktrace_snap_t   kts;
    -	int	     nentries;
    -	int	     skip_entries;
    -
    -	if (xfs_bmbt_trace_buf == NULL) {
    -		qprintf("The xfs bmap btree trace buffer is not initialized\n");		return;
    -	}
    -	nentries = ktrace_nentries(xfs_bmbt_trace_buf);
    -	if (count == -1) {
    -		count = nentries;
    -	}
    -	if ((count <= 0) || (count > nentries)) {
    -		qprintf("Invalid count.  There are %d entries.\n", nentries);
    -		return;
    -	}
    -
    -	ktep = ktrace_first(xfs_bmbt_trace_buf, &kts);
    -	if (count != nentries) {
    -		/*
    -		 * Skip the total minus the number to look at minus one
    -		 * for the entry returned by ktrace_first().
    -		 */
    -		skip_entries = nentries - count - 1;
    -		ktep = ktrace_skip(xfs_bmbt_trace_buf, skip_entries, &kts);
    -		if (ktep == NULL) {
    -			qprintf("Skipped them all\n");
    -			return;
    -		}
    -	}
    -	while (ktep != NULL) {
    -		if (xfs_bmbt_trace_entry(ktep))
    -			qprintf("\n");
    -		ktep = ktrace_next(xfs_bmbt_trace_buf, &kts);
    -	}
    -}
    -
    -/*
    - * Print out the bmap btree trace buffer attached to the given inode.
    - */
    -static void
    -xfsidbg_xbmitrace(xfs_inode_t *ip)
    -{
    -	ktrace_entry_t  *ktep;
    -	ktrace_snap_t   kts;
    -
    -	if (ip->i_btrace == NULL) {
    -		qprintf("The inode trace buffer is not initialized\n");
    -		return;
    -	}
    -
    -	ktep = ktrace_first(ip->i_btrace, &kts);
    -	while (ktep != NULL) {
    -		if (xfs_bmbt_trace_entry(ktep))
    -			qprintf("\n");
    -		ktep = ktrace_next(ip->i_btrace, &kts);
    -	}
    -}
    -
    -/*
    - * Print out all the entries in the bmap btree trace buf corresponding
    - * to the given inode.  The "s" is for "single" inode.
    - */
    -static void
    -xfsidbg_xbmstrace(xfs_inode_t *ip)
    -{
    -	ktrace_entry_t  *ktep;
    -	ktrace_snap_t   kts;
    -
    -	if (xfs_bmbt_trace_buf == NULL) {
    -		qprintf("The xfs bmap btree trace buffer is not initialized\n");		return;
    -	}
    -
    -	ktep = ktrace_first(xfs_bmbt_trace_buf, &kts);
    -	while (ktep != NULL) {
    -		if ((xfs_inode_t *)(ktep->val[2]) == ip) {
    -			if (xfs_bmbt_trace_entry(ktep))
    -				qprintf("\n");
    -		}
    -		ktep = ktrace_next(xfs_bmbt_trace_buf, &kts);
    -	}
    -}
    -#endif
    -
    -/*
    - * Print xfs bmap record
    - */
    -static void
    -xfsidbg_xbrec(xfs_bmbt_rec_64_t *r)
    -{
    -	xfs_bmbt_irec_t	irec;
    -
    -	xfs_bmbt_get_all((xfs_bmbt_rec_t *)r, &irec);
    -	kdb_printf("startoff %Ld startblock %Lx blockcount %Ld flag %d\n",
    -		irec.br_startoff, (__uint64_t)irec.br_startblock,
    -		irec.br_blockcount, irec.br_state);
    -}
    -
    -/*
    - * Print an xfs in-inode bmap btree root (data fork).
    - */
    -static void
    -xfsidbg_xbroot(xfs_inode_t *ip)
    -{
    -	xfs_broot(ip, &ip->i_df);
    -}
    -
    -/*
    - * Print an xfs in-inode bmap btree root (attribute fork).
    - */
    -static void
    -xfsidbg_xbroota(xfs_inode_t *ip)
    -{
    -	if (ip->i_afp)
    -		xfs_broot(ip, ip->i_afp);
    -}
    -
    -/*
    - * Print xfs btree cursor.
    - */
    -static void
    -xfsidbg_xbtcur(xfs_btree_cur_t *c)
    -{
    -	int l;
    -
    -	kdb_printf("tp 0x%p mp 0x%p\n",
    -		c->bc_tp,
    -		c->bc_mp);
    -	if (c->bc_btnum == XFS_BTNUM_BMAP) {
    -		kdb_printf("rec.b ");
    -		xfsidbg_xbirec(&c->bc_rec.b);
    -	} else if (c->bc_btnum == XFS_BTNUM_INO) {
    -		kdb_printf("rec.i startino 0x%x freecount 0x%x free %Lx\n",
    -			c->bc_rec.i.ir_startino, c->bc_rec.i.ir_freecount,
    -			c->bc_rec.i.ir_free);
    -	} else {
    -		kdb_printf("rec.a startblock 0x%x blockcount 0x%x\n",
    -			c->bc_rec.a.ar_startblock,
    -			c->bc_rec.a.ar_blockcount);
    -	}
    -	kdb_printf("bufs");
    -	for (l = 0; l < c->bc_nlevels; l++)
    -		kdb_printf(" 0x%p", c->bc_bufs[l]);
    -	kdb_printf("\n");
    -	kdb_printf("ptrs");
    -	for (l = 0; l < c->bc_nlevels; l++)
    -		kdb_printf(" 0x%x", c->bc_ptrs[l]);
    -	kdb_printf("  ra");
    -	for (l = 0; l < c->bc_nlevels; l++)
    -		kdb_printf(" %d", c->bc_ra[l]);
    -	kdb_printf("\n");
    -	kdb_printf("nlevels %d btnum %s blocklog %d\n",
    -		c->bc_nlevels,
    -		c->bc_btnum == XFS_BTNUM_BNO ? "bno" :
    -		(c->bc_btnum == XFS_BTNUM_CNT ? "cnt" :
    -		 (c->bc_btnum == XFS_BTNUM_BMAP ? "bmap" : "ino")),
    -		c->bc_blocklog);
    -	if (c->bc_btnum == XFS_BTNUM_BMAP) {
    -		kdb_printf("private forksize 0x%x whichfork %d ip 0x%p flags %d\n",
    -			c->bc_private.b.forksize,
    -			c->bc_private.b.whichfork,
    -			c->bc_private.b.ip,
    -			c->bc_private.b.flags);
    -		kdb_printf("private firstblock %s flist 0x%p allocated 0x%x\n",
    -			xfs_fmtfsblock(c->bc_private.b.firstblock, c->bc_mp),
    -			c->bc_private.b.flist,
    -			c->bc_private.b.allocated);
    -	} else if (c->bc_btnum == XFS_BTNUM_INO) {
    -		kdb_printf("private agbp 0x%p agno 0x%x\n",
    -			c->bc_private.i.agbp,
    -			c->bc_private.i.agno);
    -	} else {
    -		kdb_printf("private agbp 0x%p agno 0x%x\n",
    -			c->bc_private.a.agbp,
    -			c->bc_private.a.agno);
    -	}
    -}
    -
    -/*
    - * Figure out what kind of xfs block the buffer contains,
    - * and invoke a print routine.
    - */
    -static void
    -xfsidbg_xbuf(xfs_buf_t *bp)
    -{
    -	xfsidbg_xbuf_real(bp, 0);
    -}
    -
    -/*
    - * Figure out what kind of xfs block the buffer contains,
    - * and invoke a print routine (if asked to).
    - */
    -static void
    -xfsidbg_xbuf_real(xfs_buf_t *bp, int summary)
    -{
    -	void *d;
    -	xfs_agf_t *agf;
    -	xfs_agi_t *agi;
    -	xfs_sb_t *sb;
    -	xfs_alloc_block_t *bta;
    -	xfs_bmbt_block_t *btb;
    -	xfs_inobt_block_t *bti;
    -	xfs_attr_leafblock_t *aleaf;
    -	xfs_dir_leafblock_t *dleaf;
    -	xfs_da_intnode_t *node;
    -	xfs_dinode_t *di;
    -	xfs_disk_dquot_t *dqb;
    -	xfs_dir2_block_t *d2block;
    -	xfs_dir2_data_t *d2data;
    -	xfs_dir2_leaf_t *d2leaf;
    -	xfs_dir2_free_t *d2free;
    -
    -	d = XFS_BUF_PTR(bp);
    -	if (be32_to_cpu((agf = d)->agf_magicnum) == XFS_AGF_MAGIC) {
    -		if (summary) {
    -			kdb_printf("freespace hdr for AG %d (at 0x%p)\n",
    -				be32_to_cpu(agf->agf_seqno), agf);
    -		} else {
    -			kdb_printf("buf 0x%p agf 0x%p\n", bp, agf);
    -			xfsidbg_xagf(agf);
    -		}
    -	} else if (be32_to_cpu((agi = d)->agi_magicnum) == XFS_AGI_MAGIC) {
    -		if (summary) {
    -			kdb_printf("Inode hdr for AG %d (at 0x%p)\n",
    -			       be32_to_cpu(agi->agi_seqno), agi);
    -		} else {
    -			kdb_printf("buf 0x%p agi 0x%p\n", bp, agi);
    -			xfsidbg_xagi(agi);
    -		}
    -	} else if (be32_to_cpu((bta = d)->bb_magic) == XFS_ABTB_MAGIC) {
    -		if (summary) {
    -			kdb_printf("Alloc BNO Btree blk, level %d (at 0x%p)\n",
    -				       be16_to_cpu(bta->bb_level), bta);
    -		} else {
    -			kdb_printf("buf 0x%p abtbno 0x%p\n", bp, bta);
    -			xfs_btalloc(bta, XFS_BUF_COUNT(bp));
    -		}
    -	} else if (be32_to_cpu((bta = d)->bb_magic) == XFS_ABTC_MAGIC) {
    -		if (summary) {
    -			kdb_printf("Alloc COUNT Btree blk, level %d (at 0x%p)\n",
    -				       be16_to_cpu(bta->bb_level), bta);
    -		} else {
    -			kdb_printf("buf 0x%p abtcnt 0x%p\n", bp, bta);
    -			xfs_btalloc(bta, XFS_BUF_COUNT(bp));
    -		}
    -	} else if (be32_to_cpu((btb = d)->bb_magic) == XFS_BMAP_MAGIC) {
    -		if (summary) {
    -			kdb_printf("Bmap Btree blk, level %d (at 0x%p)\n",
    -				      be16_to_cpu(btb->bb_level), btb);
    -		} else {
    -			kdb_printf("buf 0x%p bmapbt 0x%p\n", bp, btb);
    -			xfs_btbmap(btb, XFS_BUF_COUNT(bp));
    -		}
    -	} else if (be32_to_cpu((bti = d)->bb_magic) == XFS_IBT_MAGIC) {
    -		if (summary) {
    -			kdb_printf("Inode Btree blk, level %d (at 0x%p)\n",
    -				       be16_to_cpu(bti->bb_level), bti);
    -		} else {
    -			kdb_printf("buf 0x%p inobt 0x%p\n", bp, bti);
    -			xfs_btino(bti, XFS_BUF_COUNT(bp));
    -		}
    -	} else if (INT_GET((aleaf = d)->hdr.info.magic, ARCH_CONVERT) == XFS_ATTR_LEAF_MAGIC) {
    -		if (summary) {
    -			kdb_printf("Attr Leaf, 1st hash 0x%x (at 0x%p)\n",
    -				      INT_GET(aleaf->entries[0].hashval, ARCH_CONVERT), aleaf);
    -		} else {
    -			kdb_printf("buf 0x%p attr leaf 0x%p\n", bp, aleaf);
    -			xfsidbg_xattrleaf(aleaf);
    -		}
    -	} else if (INT_GET((dleaf = d)->hdr.info.magic, ARCH_CONVERT) == XFS_DIR_LEAF_MAGIC) {
    -		if (summary) {
    -			kdb_printf("Dir Leaf, 1st hash 0x%x (at 0x%p)\n",
    -				     dleaf->entries[0].hashval, dleaf);
    -		} else {
    -			kdb_printf("buf 0x%p dir leaf 0x%p\n", bp, dleaf);
    -			xfsidbg_xdirleaf(dleaf);
    -		}
    -	} else if (INT_GET((node = d)->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC) {
    -		if (summary) {
    -			kdb_printf("Dir/Attr Node, level %d, 1st hash 0x%x (at 0x%p)\n",
    -			      node->hdr.level, node->btree[0].hashval, node);
    -		} else {
    -			kdb_printf("buf 0x%p dir/attr node 0x%p\n", bp, node);
    -			xfsidbg_xdanode(node);
    -		}
    -	} else if (INT_GET((di = d)->di_core.di_magic, ARCH_CONVERT) == XFS_DINODE_MAGIC) {
    -		if (summary) {
    -			kdb_printf("Disk Inode (at 0x%p)\n", di);
    -		} else {
    -			kdb_printf("buf 0x%p dinode 0x%p\n", bp, di);
    -			xfs_inodebuf(bp);
    -		}
    -	} else if (INT_GET((sb = d)->sb_magicnum, ARCH_CONVERT) == XFS_SB_MAGIC) {
    -		if (summary) {
    -			kdb_printf("Superblock (at 0x%p)\n", sb);
    -		} else {
    -			kdb_printf("buf 0x%p sb 0x%p\n", bp, sb);
    -			/* SB in a buffer - we need to convert */
    -			xfsidbg_xsb_convert(sb);
    -		}
    -	} else if ((dqb = d)->d_magic == cpu_to_be16(XFS_DQUOT_MAGIC)) {
    -#define XFSIDBG_DQTYPESTR(d)     \
    -	(((d)->d_flags & XFS_DQ_USER) ? "USR" : \
    -	(((d)->d_flags & XFS_DQ_GROUP) ? "GRP" : \
    -	(((d)->d_flags & XFS_DQ_PROJ) ? "PRJ" : "???")))
    -		kdb_printf("Quota blk starting ID [%d], type %s at 0x%p\n",
    -			be32_to_cpu(dqb->d_id), XFSIDBG_DQTYPESTR(dqb), dqb);
    -
    -	} else if (INT_GET((d2block = d)->hdr.magic, ARCH_CONVERT) == XFS_DIR2_BLOCK_MAGIC) {
    -		if (summary) {
    -			kdb_printf("Dir2 block (at 0x%p)\n", d2block);
    -		} else {
    -			kdb_printf("buf 0x%p dir2 block 0x%p\n", bp, d2block);
    -			xfs_dir2data((void *)d2block, XFS_BUF_COUNT(bp));
    -		}
    -	} else if (INT_GET((d2data = d)->hdr.magic, ARCH_CONVERT) == XFS_DIR2_DATA_MAGIC) {
    -		if (summary) {
    -			kdb_printf("Dir2 data (at 0x%p)\n", d2data);
    -		} else {
    -			kdb_printf("buf 0x%p dir2 data 0x%p\n", bp, d2data);
    -			xfs_dir2data((void *)d2data, XFS_BUF_COUNT(bp));
    -		}
    -	} else if (INT_GET((d2leaf = d)->hdr.info.magic, ARCH_CONVERT) == XFS_DIR2_LEAF1_MAGIC) {
    -		if (summary) {
    -			kdb_printf("Dir2 leaf(1) (at 0x%p)\n", d2leaf);
    -		} else {
    -			kdb_printf("buf 0x%p dir2 leaf 0x%p\n", bp, d2leaf);
    -			xfs_dir2leaf(d2leaf, XFS_BUF_COUNT(bp));
    -		}
    -	} else if (INT_GET(d2leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR2_LEAFN_MAGIC) {
    -		if (summary) {
    -			kdb_printf("Dir2 leaf(n) (at 0x%p)\n", d2leaf);
    -		} else {
    -			kdb_printf("buf 0x%p dir2 leaf 0x%p\n", bp, d2leaf);
    -			xfs_dir2leaf(d2leaf, XFS_BUF_COUNT(bp));
    -		}
    -	} else if (INT_GET((d2free = d)->hdr.magic, ARCH_CONVERT) == XFS_DIR2_FREE_MAGIC) {
    -		if (summary) {
    -			kdb_printf("Dir2 free (at 0x%p)\n", d2free);
    -		} else {
    -			kdb_printf("buf 0x%p dir2 free 0x%p\n", bp, d2free);
    -			xfsidbg_xdir2free(d2free);
    -		}
    -	} else {
    -		kdb_printf("buf 0x%p unknown 0x%p\n", bp, d);
    -	}
    -}
    -
    -#ifdef XFS_BMAP_TRACE
    -/*
    - * Print out the last "count" entries in the bmap extent trace buffer.
    - * The "a" is for "all" inodes.
    - */
    -static void
    -xfsidbg_xbxatrace(int count)
    -{
    -	ktrace_entry_t  *ktep;
    -	ktrace_snap_t   kts;
    -	int	     nentries;
    -	int	     skip_entries;
    -
    -	if (xfs_bmap_trace_buf == NULL) {
    -		qprintf("The xfs bmap extent trace buffer is not initialized\n");
    -		return;
    -	}
    -	nentries = ktrace_nentries(xfs_bmap_trace_buf);
    -	if (count == -1) {
    -		count = nentries;
    -	}
    -	if ((count <= 0) || (count > nentries)) {
    -		qprintf("Invalid count.  There are %d entries.\n", nentries);
    -		return;
    -	}
    -
    -	ktep = ktrace_first(xfs_bmap_trace_buf, &kts);
    -	if (count != nentries) {
    -		/*
    -		 * Skip the total minus the number to look at minus one
    -		 * for the entry returned by ktrace_first().
    -		 */
    -		skip_entries = nentries - count - 1;
    -		ktep = ktrace_skip(xfs_bmap_trace_buf, skip_entries, &kts);
    -		if (ktep == NULL) {
    -			qprintf("Skipped them all\n");
    -			return;
    -		}
    -	}
    -	while (ktep != NULL) {
    -		if (xfs_bmap_trace_entry(ktep))
    -			qprintf("\n");
    -		ktep = ktrace_next(xfs_bmap_trace_buf, &kts);
    -	}
    -}
    -
    -/*
    - * Print out the bmap extent trace buffer attached to the given inode.
    - */
    -static void
    -xfsidbg_xbxitrace(xfs_inode_t *ip)
    -{
    -	ktrace_entry_t  *ktep;
    -	ktrace_snap_t   kts;
    -	if (ip->i_xtrace == NULL) {
    -		qprintf("The inode trace buffer is not initialized\n");
    -		return;
    -	}
    -
    -	ktep = ktrace_first(ip->i_xtrace, &kts);
    -	while (ktep != NULL) {
    -		if (xfs_bmap_trace_entry(ktep))
    -			qprintf("\n");
    -		ktep = ktrace_next(ip->i_xtrace, &kts);
    -	}
    -}
    -
    -/*
    - * Print out all the entries in the bmap extent trace buf corresponding
    - * to the given inode.  The "s" is for "single" inode.
    - */
    -static void
    -xfsidbg_xbxstrace(xfs_inode_t *ip)
    -{
    -	ktrace_entry_t  *ktep;
    -	ktrace_snap_t   kts;
    -
    -	if (xfs_bmap_trace_buf == NULL) {
    -		qprintf("The xfs bmap extent trace buffer is not initialized\n");
    -		return;
    -	}
    -
    -	ktep = ktrace_first(xfs_bmap_trace_buf, &kts);
    -	while (ktep != NULL) {
    -		if ((xfs_inode_t *)(ktep->val[3]) == ip) {
    -			if (xfs_bmap_trace_entry(ktep))
    -				qprintf("\n");
    -		}
    -		ktep = ktrace_next(xfs_bmap_trace_buf, &kts);
    -	}
    -}
    -#endif
    -
    -#ifdef XFS_ILOCK_TRACE
    -/*
    - * Print out the ilock trace buffer attached to the given inode.
    - */
    -static void
    -xfsidbg_xilock_trace_entry(ktrace_entry_t *ktep)
    -{
    -	static char	*xiflags[] = {
    -		"IOLOCK_EXCL",
    -		"IOLOCK_SHAR",
    -		"ILOCK_EXCL",
    -		"ILOCK_SHAR",
    -		"IUNLK_NONOT",
    -		NULL
    -	};
    -
    -	if ((__psint_t)ktep->val[0] &&
    -	     (__psint_t)ktep->val[7] == 0) {
    -		 printflags((__psint_t)ktep->val[2], xiflags,"Flags ");
    -		if ((__psint_t)ktep->val[1] == 1)
    -			 qprintf("LOCK\n");
    -		else if ((__psint_t)ktep->val[1] == 2)
    -			 qprintf("LOCK SHARED\n");
    -		else if ((__psint_t)ktep->val[1] == 3)
    -			 qprintf("UNLOCK\n");
    -		qprintf("ip 0x%p %llx %ld\n",
    -			ktep->val[0],
    -			(unsigned long long)((xfs_inode_t*)ktep->val[0])->i_ino,
    -			(long)ktep->val[6]);
    -		qprintf("raddr 0x%p\n", ktep->val[3]);
    -		qprintf("  Pid %ld, cpu %ld\n",
    -			 (long)ktep->val[5],
    -			 (long)ktep->val[4]);
    -		qprintf("-----------------------\n");
    -
    -	} else if ((__psint_t)ktep->val[7] == 1) {
    -		if ((__psint_t)ktep->val[1] == 1)
    -			qprintf("FlushLOCK ");
    -		else if ((__psint_t)ktep->val[1] == 2)
    -			qprintf("FlushTRYLOCK %ld ",
    -				(long)ktep->val[2]);
    -		else if ((__psint_t)ktep->val[1] == 3)
    -			qprintf("FlushUNLOCK ");
    -		else if ((__psint_t)ktep->val[1] == 4)
    -			qprintf("FlushInode 0x%p",
    -				ktep->val[2]);
    -		else if ((__psint_t)ktep->val[1] == 5)
    -			qprintf("FlushInodeInt ");
    -		else     qprintf("FlushUNKNOWN ");
    -		qprintf("ip 0x%p ino %llx @ %ld\n",
    -			ktep->val[0],
    -			(unsigned long long)((xfs_inode_t*)ktep->val[0])->i_ino,
    -			(long)ktep->val[6]);
    -		qprintf("raddr 0x%p\n", ktep->val[3]);
    -		qprintf("  Pid %ld, cpu %ld\n",
    -			(long)ktep->val[5],
    -			(long)ktep->val[4]);
    -		qprintf("-----------------------\n");
    -	}
    -}
    -
    -static void
    -xfsidbg_xilock_trace(xfs_inode_t *ip)
    -{
    -	static char *xiflags[] = {
    -		"IOLOCK_EXCL",
    -		"IOLOCK_SHAR",
    -		"ILOCK_EXCL",
    -		"ILOCK_SHAR",
    -		"IUNLK_NONOT",
    -		NULL
    -	};
    -
    -	ktrace_entry_t  *ktep;
    -	ktrace_snap_t   kts;
    -	if (ip->i_lock_trace == NULL) {
    -		qprintf("The inode ilock trace buffer is not initialized\n");
    -		return;
    -	}
    -
    -	ktep = ktrace_first(ip->i_lock_trace, &kts);
    -	while (ktep != NULL) {
    -		 if ((__psint_t)ktep->val[0] &&
    -		     (__psint_t)ktep->val[7] == 0) {
    -			 printflags((__psint_t)ktep->val[2], xiflags,"Flags ");
    -			 if ((__psint_t)ktep->val[1] == 1)
    -				 qprintf("LOCK\n");
    -			 else if ((__psint_t)ktep->val[1] == 2)
    -				 qprintf("LOCK SHARED\n");
    -			 else if ((__psint_t)ktep->val[1] == 3)
    -				 qprintf("UNLOCK\n");
    -			qprintf("ip 0x%p %lld %ld\n",
    -				ktep->val[0], (unsigned long long)
    -				((xfs_inode_t*)ktep->val[0])->i_ino,
    -				(long)ktep->val[6]);
    -			 qprintf("raddr 0x%p\n", ktep->val[3]);
    -			 qprintf("  Pid %ld, cpu %ld\n",
    -				 (long)ktep->val[5],
    -				 (long)ktep->val[4]);
    -			 qprintf("-----------------------\n");
    -		 } else if ((__psint_t)ktep->val[7] == 1) {
    -			if ((__psint_t)ktep->val[1] == 1)
    -				qprintf("LOCK ");
    -			else if ((__psint_t)ktep->val[1] == 2)
    -				qprintf("TRYLOCK %ld ",
    -					(long)ktep->val[2]);
    -			else if ((__psint_t)ktep->val[1] == 3)
    -				qprintf("UNLOCK ");
    -			else     qprintf("UNKNOWN ");
    -			qprintf("ip 0x%p %lld %ld\n",
    -				ktep->val[0], (unsigned long long)
    -				((xfs_inode_t*)ktep->val[0])->i_ino,
    -				(long)ktep->val[6]);
    -			qprintf("raddr 0x%p\n", ktep->val[3]);
    -			qprintf("  Pid %ld, cpu %ld\n",
    -				(long)ktep->val[5],
    -				(long)ktep->val[4]);
    -			qprintf("-----------------------\n");
    -		 }
    -
    -		 ktep = ktrace_next(ip->i_lock_trace, &kts);
    -	}
    -}
    -
    -/*
    - * Print out the last "count" entries in the inode lock trace buffer.
    - * The "a" is for "all" entries.
    - */
    -static void
    -xfsidbg_xailock_trace(int count)
    -{
    -	ktrace_entry_t  *ktep;
    -	ktrace_snap_t   kts;
    -	int	     nentries;
    -	int	     skip_entries;
    -
    -	if (xfs_ilock_trace_buf == NULL) {
    -		qprintf("The xfs inode lock trace buffer is not initialized\n");		return;
    -	}
    -	nentries = ktrace_nentries(xfs_ilock_trace_buf);
    -	if (count == -1) {
    -		count = nentries;
    -	}
    -	if ((count <= 0) || (count > nentries)) {
    -		qprintf("Invalid count.  There are %d entries.\n", nentries);
    -		return;
    -	}
    -
    -	ktep = ktrace_first(xfs_ilock_trace_buf, &kts);
    -	if (count != nentries) {
    -		/*
    -		 * Skip the total minus the number to look at minus one
    -		 * for the entry returned by ktrace_first().
    -		 */
    -		skip_entries = nentries - count - 1;
    -		ktep = ktrace_skip(xfs_ilock_trace_buf, skip_entries, &kts);
    -		if (ktep == NULL) {
    -			qprintf("Skipped them all\n");
    -			return;
    -		}
    -	}
    -	while (ktep != NULL) {
    -		xfsidbg_xilock_trace_entry(ktep);
    -		ktep = ktrace_next(xfs_ilock_trace_buf, &kts);
    -	}
    -}
    -#endif
    -
    -/*
    - * Compute & print buffer's checksum.
    - */
    -static void
    -xfsidbg_xchksum(uint *addr)
    -{
    -	uint i, chksum = 0;
    -
    -	if (((__psint_t)addr) == ((__psint_t)-1)) {
    -		qprintf("USAGE xchksum 
    \n"); - qprintf(" length is set with xarg\n"); - } else { - for (i=0; inamelen; i++) { - kdb_printf("%c", n->name[i]); - } - kdb_printf("\"(%d) value ", n->namelen); - if (n->value) { - kdb_printf("\""); - ch = n->value; - for (i = 0; (i < n->valuelen) && (i < 32); ch++, i++) { - switch(*ch) { - case '\n': kdb_printf("\n"); break; - case '\b': kdb_printf("\b"); break; - case '\t': kdb_printf("\t"); break; - default: kdb_printf("%c", *ch); break; - } - } - if (i == 32) - kdb_printf("..."); - kdb_printf("\"(%d)\n", n->valuelen); - } else { - kdb_printf("(NULL)(%d)\n", n->valuelen); - } - kdb_printf(" hashval 0x%x whichfork %d flags <", - (uint_t)n->hashval, n->whichfork); - if (n->flags & ATTR_ROOT) - kdb_printf("ROOT "); - if (n->flags & ATTR_SECURE) - kdb_printf("SECURE "); - if (n->flags & ATTR_CREATE) - kdb_printf("CREATE "); - if (n->flags & ATTR_REPLACE) - kdb_printf("REPLACE "); - if (n->flags & XFS_ATTR_INCOMPLETE) - kdb_printf("INCOMPLETE "); - i = ~(ATTR_ROOT | ATTR_SECURE | - ATTR_CREATE | ATTR_REPLACE | XFS_ATTR_INCOMPLETE); - if ((n->flags & i) != 0) - kdb_printf("0x%x", n->flags & i); - kdb_printf(">\n"); - kdb_printf(" rename %d justcheck %d addname %d oknoent %d\n", - n->rename, n->justcheck, n->addname, n->oknoent); - kdb_printf(" leaf: blkno %d index %d rmtblkno %d rmtblkcnt %d\n", - n->blkno, n->index, n->rmtblkno, n->rmtblkcnt); - kdb_printf(" leaf2: blkno %d index %d rmtblkno %d rmtblkcnt %d\n", - n->blkno2, n->index2, n->rmtblkno2, n->rmtblkcnt2); - kdb_printf(" inumber %llu dp 0x%p firstblock 0x%p flist 0x%p\n", - (unsigned long long) n->inumber, - n->dp, n->firstblock, n->flist); - kdb_printf(" trans 0x%p total %d\n", - n->trans, n->total); -} - -/* - * Print a da buffer structure. - */ -static void -xfsidbg_xdabuf(xfs_dabuf_t *dabuf) -{ - int i; - - kdb_printf("nbuf %d dirty %d bbcount %d data 0x%p bps", - dabuf->nbuf, dabuf->dirty, dabuf->bbcount, dabuf->data); - for (i = 0; i < dabuf->nbuf; i++) - kdb_printf(" %d:0x%p", i, dabuf->bps[i]); - kdb_printf("\n"); -#ifdef XFS_DABUF_DEBUG - kdb_printf(" ra 0x%x prev 0x%x next 0x%x dev 0x%x blkno 0x%x\n", - dabuf->ra, dabuf->prev, dabuf->next, dabuf->dev, dabuf->blkno); -#endif -} - -/* - * Print a directory/attribute internal node block. - */ -static void -xfsidbg_xdanode(xfs_da_intnode_t *node) -{ - xfs_da_node_hdr_t *h; - xfs_da_blkinfo_t *i; - xfs_da_node_entry_t *e; - int j; - - h = &node->hdr; - i = &h->info; - kdb_printf("hdr info forw 0x%x back 0x%x magic 0x%x\n", - INT_GET(i->forw, ARCH_CONVERT), INT_GET(i->back, ARCH_CONVERT), INT_GET(i->magic, ARCH_CONVERT)); - kdb_printf("hdr count %d level %d\n", - INT_GET(h->count, ARCH_CONVERT), INT_GET(h->level, ARCH_CONVERT)); - for (j = 0, e = node->btree; j < INT_GET(h->count, ARCH_CONVERT); j++, e++) { - kdb_printf("btree %d hashval 0x%x before 0x%x\n", - j, (uint_t)INT_GET(e->hashval, ARCH_CONVERT), INT_GET(e->before, ARCH_CONVERT)); - } -} - -/* - * Print an xfs_da_state_blk structure. - */ -static void -xfsidbg_xdastate(xfs_da_state_t *s) -{ - xfs_da_state_blk_t *eblk; - - kdb_printf("args 0x%p mp 0x%p blocksize %u node_ents %u inleaf %u\n", - s->args, s->mp, s->blocksize, s->node_ents, s->inleaf); - if (s->args) - xfsidbg_xdaargs(s->args); - - kdb_printf("path: "); - xfs_dastate_path(&s->path); - - kdb_printf("altpath: "); - xfs_dastate_path(&s->altpath); - - eblk = &s->extrablk; - kdb_printf("extra: valid %d, after %d\n", s->extravalid, s->extraafter); - kdb_printf(" bp 0x%p blkno 0x%x ", eblk->bp, eblk->blkno); - kdb_printf("index %d hashval 0x%x\n", eblk->index, (uint_t)eblk->hashval); -} - -/* - * Print a directory leaf block. - */ -static void -xfsidbg_xdirleaf(xfs_dir_leafblock_t *leaf) -{ - xfs_dir_leaf_hdr_t *h; - xfs_da_blkinfo_t *i; - xfs_dir_leaf_map_t *m; - xfs_dir_leaf_entry_t *e; - xfs_dir_leaf_name_t *n; - int j, k; - xfs_ino_t ino; - - h = &leaf->hdr; - i = &h->info; - kdb_printf("hdr info forw 0x%x back 0x%x magic 0x%x\n", - INT_GET(i->forw, ARCH_CONVERT), INT_GET(i->back, ARCH_CONVERT), INT_GET(i->magic, ARCH_CONVERT)); - kdb_printf("hdr count %d namebytes %d firstused %d holes %d\n", - INT_GET(h->count, ARCH_CONVERT), INT_GET(h->namebytes, ARCH_CONVERT), INT_GET(h->firstused, ARCH_CONVERT), h->holes); - for (j = 0, m = h->freemap; j < XFS_DIR_LEAF_MAPSIZE; j++, m++) { - kdb_printf("hdr freemap %d base %d size %d\n", - j, INT_GET(m->base, ARCH_CONVERT), INT_GET(m->size, ARCH_CONVERT)); - } - for (j = 0, e = leaf->entries; j < INT_GET(h->count, ARCH_CONVERT); j++, e++) { - n = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(e->nameidx, ARCH_CONVERT)); - XFS_DIR_SF_GET_DIRINO(&n->inumber, &ino); - kdb_printf("leaf %d hashval 0x%x nameidx %d inumber %llu ", - j, (uint_t)INT_GET(e->hashval, ARCH_CONVERT), - INT_GET(e->nameidx, ARCH_CONVERT), - (unsigned long long)ino); - kdb_printf("namelen %d name \"", e->namelen); - for (k = 0; k < e->namelen; k++) - kdb_printf("%c", n->name[k]); - kdb_printf("\"\n"); - } -} - -/* - * Print a directory v2 data block, single or multiple. - */ -static void -xfs_dir2data(void *addr, int size) -{ - xfs_dir2_data_t *db; - xfs_dir2_block_t *bb; - xfs_dir2_data_hdr_t *h; - xfs_dir2_data_free_t *m; - xfs_dir2_data_entry_t *e; - xfs_dir2_data_unused_t *u; - xfs_dir2_leaf_entry_t *l=NULL; - int j, k; - char *p; - char *t; - xfs_dir2_block_tail_t *tail=NULL; - - db = (xfs_dir2_data_t *)addr; - bb = (xfs_dir2_block_t *)addr; - h = &db->hdr; - kdb_printf("hdr magic 0x%x (%s)\nhdr bestfree", INT_GET(h->magic, ARCH_CONVERT), - INT_GET(h->magic, ARCH_CONVERT) == XFS_DIR2_DATA_MAGIC ? "DATA" : - (INT_GET(h->magic, ARCH_CONVERT) == XFS_DIR2_BLOCK_MAGIC ? "BLOCK" : "")); - for (j = 0, m = h->bestfree; j < XFS_DIR2_DATA_FD_COUNT; j++, m++) { - kdb_printf(" %d: 0x%x@0x%x", j, INT_GET(m->length, ARCH_CONVERT), INT_GET(m->offset, ARCH_CONVERT)); - } - kdb_printf("\n"); - if (INT_GET(h->magic, ARCH_CONVERT) == XFS_DIR2_DATA_MAGIC) - t = (char *)db + size; - else { - /* XFS_DIR2_BLOCK_TAIL_P */ - tail = (xfs_dir2_block_tail_t *) - ((char *)bb + size - sizeof(xfs_dir2_block_tail_t)); - l = XFS_DIR2_BLOCK_LEAF_P(tail); - t = (char *)l; - } - for (p = (char *)(h + 1); p < t; ) { - u = (xfs_dir2_data_unused_t *)p; - if (u->freetag == XFS_DIR2_DATA_FREE_TAG) { - kdb_printf("0x%lx unused freetag 0x%x length 0x%x tag 0x%x\n", - (unsigned long) (p - (char *)addr), - INT_GET(u->freetag, ARCH_CONVERT), - INT_GET(u->length, ARCH_CONVERT), - INT_GET(*XFS_DIR2_DATA_UNUSED_TAG_P(u), ARCH_CONVERT)); - p += INT_GET(u->length, ARCH_CONVERT); - continue; - } - e = (xfs_dir2_data_entry_t *)p; - kdb_printf("0x%lx entry inumber %llu namelen %d name \"", - (unsigned long) (p - (char *)addr), - (unsigned long long) INT_GET(e->inumber, ARCH_CONVERT), - e->namelen); - for (k = 0; k < e->namelen; k++) - kdb_printf("%c", e->name[k]); - kdb_printf("\" tag 0x%x\n", INT_GET(*XFS_DIR2_DATA_ENTRY_TAG_P(e), ARCH_CONVERT)); - p += XFS_DIR2_DATA_ENTSIZE(e->namelen); - } - if (INT_GET(h->magic, ARCH_CONVERT) == XFS_DIR2_DATA_MAGIC) - return; - for (j = 0; j < INT_GET(tail->count, ARCH_CONVERT); j++, l++) { - kdb_printf("0x%lx leaf %d hashval 0x%x address 0x%x (byte 0x%x)\n", - (unsigned long) ((char *)l - (char *)addr), j, - (uint_t)INT_GET(l->hashval, ARCH_CONVERT), - INT_GET(l->address, ARCH_CONVERT), - /* XFS_DIR2_DATAPTR_TO_BYTE */ - INT_GET(l->address, ARCH_CONVERT) << XFS_DIR2_DATA_ALIGN_LOG); - } - kdb_printf("0x%lx tail count %d\n", - (unsigned long) ((char *)tail - (char *)addr), - INT_GET(tail->count, ARCH_CONVERT)); -} - -static void -xfs_dir2leaf(xfs_dir2_leaf_t *leaf, int size) -{ - xfs_dir2_leaf_hdr_t *h; - xfs_da_blkinfo_t *i; - xfs_dir2_leaf_entry_t *e; - xfs_dir2_data_off_t *b; - xfs_dir2_leaf_tail_t *t; - int j; - - h = &leaf->hdr; - i = &h->info; - e = leaf->ents; - kdb_printf("hdr info forw 0x%x back 0x%x magic 0x%x\n", - INT_GET(i->forw, ARCH_CONVERT), INT_GET(i->back, ARCH_CONVERT), INT_GET(i->magic, ARCH_CONVERT)); - kdb_printf("hdr count %d stale %d\n", INT_GET(h->count, ARCH_CONVERT), INT_GET(h->stale, ARCH_CONVERT)); - for (j = 0; j < INT_GET(h->count, ARCH_CONVERT); j++, e++) { - kdb_printf("0x%lx ent %d hashval 0x%x address 0x%x (byte 0x%x)\n", - (unsigned long) ((char *)e - (char *)leaf), j, - (uint_t)INT_GET(e->hashval, ARCH_CONVERT), - INT_GET(e->address, ARCH_CONVERT), - /* XFS_DIR2_DATAPTR_TO_BYTE */ - INT_GET(e->address, ARCH_CONVERT) << XFS_DIR2_DATA_ALIGN_LOG); - } - if (INT_GET(i->magic, ARCH_CONVERT) == XFS_DIR2_LEAFN_MAGIC) - return; - /* XFS_DIR2_LEAF_TAIL_P */ - t = (xfs_dir2_leaf_tail_t *)((char *)leaf + size - sizeof(*t)); - b = XFS_DIR2_LEAF_BESTS_P(t); - for (j = 0; j < INT_GET(t->bestcount, ARCH_CONVERT); j++, b++) { - kdb_printf("0x%lx best %d 0x%x\n", - (unsigned long) ((char *)b - (char *)leaf), j, - INT_GET(*b, ARCH_CONVERT)); - } - kdb_printf("tail bestcount %d\n", INT_GET(t->bestcount, ARCH_CONVERT)); -} - -/* - * Print a shortform directory. - */ -static void -xfsidbg_xdirsf(xfs_dir_shortform_t *s) -{ - xfs_dir_sf_hdr_t *sfh; - xfs_dir_sf_entry_t *sfe; - xfs_ino_t ino; - int i, j; - - sfh = &s->hdr; - XFS_DIR_SF_GET_DIRINO(&sfh->parent, &ino); - kdb_printf("hdr parent %llu", (unsigned long long)ino); - kdb_printf(" count %d\n", sfh->count); - for (i = 0, sfe = s->list; i < sfh->count; i++) { - XFS_DIR_SF_GET_DIRINO(&sfe->inumber, &ino); - kdb_printf("entry %d inumber %llu", i, (unsigned long long)ino); - kdb_printf(" namelen %d name \"", sfe->namelen); - for (j = 0; j < sfe->namelen; j++) - kdb_printf("%c", sfe->name[j]); - kdb_printf("\"\n"); - sfe = XFS_DIR_SF_NEXTENTRY(sfe); - } -} - -/* - * Print a shortform v2 directory. - */ -static void -xfsidbg_xdir2sf(xfs_dir2_sf_t *s) -{ - xfs_dir2_sf_hdr_t *sfh; - xfs_dir2_sf_entry_t *sfe; - xfs_ino_t ino; - int i, j; - - sfh = &s->hdr; - ino = XFS_DIR2_SF_GET_INUMBER(s, &sfh->parent); - kdb_printf("hdr count %d i8count %d parent %llu\n", - sfh->count, sfh->i8count, (unsigned long long) ino); - for (i = 0, sfe = XFS_DIR2_SF_FIRSTENTRY(s); i < sfh->count; i++) { - ino = XFS_DIR2_SF_GET_INUMBER(s, XFS_DIR2_SF_INUMBERP(sfe)); - kdb_printf("entry %d inumber %llu offset 0x%x namelen %d name \"", - i, (unsigned long long) ino, - XFS_DIR2_SF_GET_OFFSET(sfe), - sfe->namelen); - for (j = 0; j < sfe->namelen; j++) - kdb_printf("%c", sfe->name[j]); - kdb_printf("\"\n"); - sfe = XFS_DIR2_SF_NEXTENTRY(s, sfe); - } -} - -/* - * Print a node-form v2 directory freemap block. - */ -static void -xfsidbg_xdir2free(xfs_dir2_free_t *f) -{ - int i; - - kdb_printf("hdr magic 0x%x firstdb %d nvalid %d nused %d\n", - INT_GET(f->hdr.magic, ARCH_CONVERT), INT_GET(f->hdr.firstdb, ARCH_CONVERT), INT_GET(f->hdr.nvalid, ARCH_CONVERT), INT_GET(f->hdr.nused, ARCH_CONVERT)); - for (i = 0; i < INT_GET(f->hdr.nvalid, ARCH_CONVERT); i++) { - kdb_printf("entry %d db %d count %d\n", - i, i + INT_GET(f->hdr.firstdb, ARCH_CONVERT), INT_GET(f->bests[i], ARCH_CONVERT)); - } -} - -#ifdef XFS_DIR_TRACE -/* - * Print out the last "count" entries in the directory trace buffer. - */ -static void -xfsidbg_xdirtrace(int count) -{ - ktrace_entry_t *ktep; - ktrace_snap_t kts; - int nentries; - int skip_entries; - - if (xfs_dir_trace_buf == NULL) { - qprintf("The xfs directory trace buffer is not initialized\n"); - return; - } - nentries = ktrace_nentries(xfs_dir_trace_buf); - if (count == -1) { - count = nentries; - } - if ((count <= 0) || (count > nentries)) { - qprintf("Invalid count. There are %d entries.\n", nentries); - return; - } - - ktep = ktrace_first(xfs_dir_trace_buf, &kts); - if (count != nentries) { - /* - * Skip the total minus the number to look at minus one - * for the entry returned by ktrace_first(). - */ - skip_entries = nentries - count - 1; - ktep = ktrace_skip(xfs_dir_trace_buf, skip_entries, &kts); - if (ktep == NULL) { - qprintf("Skipped them all\n"); - return; - } - } - while (ktep != NULL) { - if (xfs_dir_trace_entry(ktep)) - qprintf("\n"); - ktep = ktrace_next(xfs_dir_trace_buf, &kts); - } -} -#endif - -#ifdef XFS_DIR2_TRACE -/* - * Print out the last "count" entries in the directory v2 trace buffer. - */ -static void -xfsidbg_xdir2atrace(int count) -{ - ktrace_entry_t *ktep; - ktrace_snap_t kts; - int nentries; - int skip_entries; - - if (xfs_dir2_trace_buf == NULL) { - qprintf("The xfs dirv2 trace buffer is not initialized\n"); - return; - } - nentries = ktrace_nentries(xfs_dir2_trace_buf); - if (count == -1) { - count = nentries; - } - if ((count <= 0) || (count > nentries)) { - qprintf("Invalid count. There are %d entries.\n", nentries); - return; - } - - ktep = ktrace_first(xfs_dir2_trace_buf, &kts); - if (count != nentries) { - /* - * Skip the total minus the number to look at minus one - * for the entry returned by ktrace_first(). - */ - skip_entries = nentries - count - 1; - ktep = ktrace_skip(xfs_dir2_trace_buf, skip_entries, &kts); - if (ktep == NULL) { - qprintf("Skipped them all\n"); - return; - } - } - while (ktep != NULL) { - if (xfs_dir2_trace_entry(ktep)) - qprintf("\n"); - ktep = ktrace_next(xfs_dir2_trace_buf, &kts); - } -} - -/* - * Print out the directory v2 trace buffer attached to the given inode. - */ -static void -xfsidbg_xdir2itrace(xfs_inode_t *ip) -{ - ktrace_entry_t *ktep; - ktrace_snap_t kts; - - if (ip->i_dir_trace == NULL) { - qprintf("The inode trace buffer is not initialized\n"); - return; - } - - ktep = ktrace_first(ip->i_dir_trace, &kts); - while (ktep != NULL) { - if (xfs_dir2_trace_entry(ktep)) - qprintf("\n"); - ktep = ktrace_next(ip->i_dir_trace, &kts); - } -} -#endif - -/* - * Print xfs extent records. - */ -static void -xfsidbg_xexlist(xfs_inode_t *ip) -{ - xfs_xexlist_fork(ip, XFS_DATA_FORK); - if (XFS_IFORK_Q(ip)) - xfs_xexlist_fork(ip, XFS_ATTR_FORK); -} - -/* - * Print an xfs free-extent records. - */ -static void -xfsidbg_xflist(xfs_bmap_free_t *flist) -{ - xfs_bmap_free_item_t *item; - - kdb_printf("flist@0x%p: first 0x%p count %d low %d\n", flist, - flist->xbf_first, flist->xbf_count, flist->xbf_low); - for (item = flist->xbf_first; item; item = item->xbfi_next) { - kdb_printf("item@0x%p: startblock %Lx blockcount %d", item, - (xfs_dfsbno_t)item->xbfi_startblock, - item->xbfi_blockcount); - } -} - -/* - * Print out the help messages for these functions. - */ -static void -xfsidbg_xhelp(void) -{ - struct xif *p; - - for (p = xfsidbg_funcs; p->name; p++) - kdb_printf("%-16s %s %s\n", p->name, p->args, p->help); -} - -/* - * Print out an XFS in-core log structure. - */ -static void -xfsidbg_xiclog(xlog_in_core_t *iclog) -{ - int i; - static char *ic_flags[] = { - "ACTIVE", /* 0x0001 */ - "WANT_SYNC", /* 0x0002 */ - "SYNCING", /* 0X0004 */ - "DONE_SYNC", /* 0X0008 */ - "DO_CALLBACK", /* 0X0010 */ - "CALLBACK", /* 0X0020 */ - "DIRTY", /* 0X0040 */ - "IOERROR", /* 0X0080 */ - "NOTUSED", /* 0X8000 */ - NULL - }; - - kdb_printf("xlog_in_core/header at 0x%p/0x%p\n", - iclog, iclog->hic_data); - kdb_printf("magicno: %x cycle: %d version: %d lsn: 0x%Lx\n", - INT_GET(iclog->ic_header.h_magicno, ARCH_CONVERT), INT_GET(iclog->ic_header.h_cycle, ARCH_CONVERT), - INT_GET(iclog->ic_header.h_version, ARCH_CONVERT), INT_GET(iclog->ic_header.h_lsn, ARCH_CONVERT)); - kdb_printf("tail_lsn: 0x%Lx len: %d prev_block: %d num_ops: %d\n", - INT_GET(iclog->ic_header.h_tail_lsn, ARCH_CONVERT), INT_GET(iclog->ic_header.h_len, ARCH_CONVERT), - INT_GET(iclog->ic_header.h_prev_block, ARCH_CONVERT), INT_GET(iclog->ic_header.h_num_logops, ARCH_CONVERT)); - kdb_printf("cycle_data: "); - for (i=0; i<(iclog->ic_size>>BBSHIFT); i++) { - kdb_printf("%x ", INT_GET(iclog->ic_header.h_cycle_data[i], ARCH_CONVERT)); - } - kdb_printf("\n"); - kdb_printf("size: %d\n", INT_GET(iclog->ic_header.h_size, ARCH_CONVERT)); - kdb_printf("\n"); - kdb_printf("--------------------------------------------------\n"); - kdb_printf("data: 0x%p &forcesema: 0x%p next: 0x%p bp: 0x%p\n", - iclog->ic_datap, &iclog->ic_forcesema, iclog->ic_next, - iclog->ic_bp); - kdb_printf("log: 0x%p callb: 0x%p callb_tail: 0x%p\n", - iclog->ic_log, iclog->ic_callback, iclog->ic_callback_tail); - kdb_printf("size: %d (OFFSET: %d) trace: 0x%p refcnt: %d bwritecnt: %d", - iclog->ic_size, iclog->ic_offset, -#ifdef XFS_LOG_TRACE - iclog->ic_trace, -#else - NULL, -#endif - iclog->ic_refcnt, iclog->ic_bwritecnt); - if (iclog->ic_state & XLOG_STATE_ALL) - printflags(iclog->ic_state, ic_flags, " state:"); - else - kdb_printf(" state: INVALID 0x%x", iclog->ic_state); - kdb_printf("\n"); -} /* xfsidbg_xiclog */ - - -/* - * Print all incore logs. - */ -static void -xfsidbg_xiclogall(xlog_in_core_t *iclog) -{ - xlog_in_core_t *first_iclog = iclog; - - do { - xfsidbg_xiclog(iclog); - kdb_printf("=================================================\n"); - iclog = iclog->ic_next; - } while (iclog != first_iclog); -} /* xfsidbg_xiclogall */ - -/* - * Print out the callback structures attached to an iclog. - */ -static void -xfsidbg_xiclogcb(xlog_in_core_t *iclog) -{ - xfs_log_callback_t *cb; - kdb_symtab_t symtab; - - for (cb = iclog->ic_callback; cb != NULL; cb = cb->cb_next) { - - if (kdbnearsym((unsigned long)cb->cb_func, &symtab)) { - unsigned long offval; - - offval = (unsigned long)cb->cb_func - symtab.sym_start; - - if (offval) - kdb_printf("func = %s+0x%lx", - symtab.sym_name, - offval); - else - kdb_printf("func = %s", symtab.sym_name); - } else - kdb_printf("func = ?? 0x%p", (void *)cb->cb_func); - - kdb_printf(" arg 0x%p next 0x%p\n", cb->cb_arg, cb->cb_next); - } -} - -#ifdef XFS_LOG_TRACE -/* - * Print trace from incore log. - */ -static void -xfsidbg_xiclogtrace(xlog_in_core_t *iclog) -{ - ktrace_entry_t *ktep; - ktrace_snap_t kts; - ktrace_t *kt = iclog->ic_trace; - - qprintf("iclog->ic_trace 0x%p\n", kt); - ktep = ktrace_first(kt, &kts); - while (ktep != NULL) { - switch ((__psint_t)ktep->val[0]) { - case XLOG_TRACE_GRAB_FLUSH: { - qprintf("grabbing semaphore\n"); - break; - } - case XLOG_TRACE_REL_FLUSH: { - qprintf("releasing semaphore\n"); - break; - } - case XLOG_TRACE_SLEEP_FLUSH: { - qprintf("sleeping on semaphore\n"); - break; - } - case XLOG_TRACE_WAKE_FLUSH: { - qprintf("waking up on semaphore\n"); - break; - } - default: { - } - } - ktep = ktrace_next(kt, &kts); - } -} /* xfsidbg_xiclogtrace */ -#endif - -/* - * Print all of the inodes attached to the given mount structure. - */ -static void -xfsidbg_xinodes(xfs_mount_t *mp) -{ - xfs_inode_t *ip; - - kdb_printf("xfs_mount at 0x%p\n", mp); - ip = mp->m_inodes; - if (ip != NULL) { - do { - if (ip->i_mount == NULL) { - ip = ip->i_mnext; - continue; - } - kdb_printf("\n"); - xfsidbg_xnode(ip); - ip = ip->i_mnext; - } while (ip != mp->m_inodes); - } - kdb_printf("\nEnd of Inodes\n"); -} - -static void -xfsidbg_delayed_blocks(xfs_mount_t *mp) -{ - xfs_inode_t *ip; - unsigned int total = 0; - unsigned int icount = 0; - - ip = mp->m_inodes; - if (ip != NULL) { - do { - if (ip->i_mount == NULL) { - ip = ip->i_mnext; - continue; - } - if (ip->i_delayed_blks) { - total += ip->i_delayed_blks; - icount++; - } - ip = ip->i_mnext; - } while (ip != mp->m_inodes); - } - kdb_printf("delayed blocks total: %d in %d inodes\n", total, icount); -} - -static void -xfsidbg_xinodes_quiesce(xfs_mount_t *mp) -{ - xfs_inode_t *ip; - - kdb_printf("xfs_mount at 0x%p\n", mp); - ip = mp->m_inodes; - if (ip != NULL) { - do { - if (ip->i_mount == NULL) { - ip = ip->i_mnext; - continue; - } - if (!(ip->i_flags & XFS_IQUIESCE)) { - kdb_printf("ip 0x%p not quiesced\n", ip); - } - ip = ip->i_mnext; - } while (ip != mp->m_inodes); - } - kdb_printf("\nEnd of Inodes\n"); -} - -static char * -xfsidbg_get_cstate(int state) -{ - switch(state) { - case XLOG_STATE_COVER_IDLE: - return("idle"); - case XLOG_STATE_COVER_NEED: - return("need"); - case XLOG_STATE_COVER_DONE: - return("done"); - case XLOG_STATE_COVER_NEED2: - return("need2"); - case XLOG_STATE_COVER_DONE2: - return("done2"); - default: - return("unknown"); - } -} - -/* - * Print out an XFS log structure. - */ -static void -xfsidbg_xlog(xlog_t *log) -{ - static char *t_flags[] = { - "CHKSUM_MISMATCH", /* 0x01 */ - "ACTIVE_RECOVERY", /* 0x02 */ - "RECOVERY_NEEDED", /* 0x04 */ - "IO_ERROR", /* 0x08 */ - NULL - }; - - kdb_printf("xlog at 0x%p\n", log); - kdb_printf("&flushsm: 0x%p flushcnt: %d tic_cnt: %d tic_tcnt: %d \n", - &log->l_flushsema, log->l_flushcnt, - log->l_ticket_cnt, log->l_ticket_tcnt); - kdb_printf("freelist: 0x%p tail: 0x%p ICLOG: 0x%p \n", - log->l_freelist, log->l_tail, log->l_iclog); - kdb_printf("&icloglock: 0x%p tail_lsn: %s last_sync_lsn: %s \n", - &log->l_icloglock, xfs_fmtlsn(&log->l_tail_lsn), - xfs_fmtlsn(&log->l_last_sync_lsn)); - kdb_printf("mp: 0x%p xbuf: 0x%p l_covered_state: %s \n", - log->l_mp, log->l_xbuf, - xfsidbg_get_cstate(log->l_covered_state)); - kdb_printf("flags: "); - printflags(log->l_flags, t_flags,"log"); - kdb_printf(" logBBstart: %lld logsize: %d logBBsize: %d\n", - (long long) log->l_logBBstart, - log->l_logsize,log->l_logBBsize); - kdb_printf("curr_cycle: %d prev_cycle: %d curr_block: %d prev_block: %d\n", - log->l_curr_cycle, log->l_prev_cycle, log->l_curr_block, - log->l_prev_block); - kdb_printf("iclog_bak: 0x%p iclog_size: 0x%x (%d) num iclogs: %d\n", - log->l_iclog_bak, log->l_iclog_size, log->l_iclog_size, - log->l_iclog_bufs); - kdb_printf("l_iclog_hsize %d l_iclog_heads %d\n", - log->l_iclog_hsize, log->l_iclog_heads); - kdb_printf("l_sectbb_log %u l_sectbb_mask %u\n", - log->l_sectbb_log, log->l_sectbb_mask); - kdb_printf("&grant_lock: 0x%p resHeadQ: 0x%p wrHeadQ: 0x%p\n", - &log->l_grant_lock, log->l_reserve_headq, log->l_write_headq); - kdb_printf("GResCycle: %d GResBytes: %d GWrCycle: %d GWrBytes: %d\n", - log->l_grant_reserve_cycle, log->l_grant_reserve_bytes, - log->l_grant_write_cycle, log->l_grant_write_bytes); - qprintf("GResBlocks: %d GResRemain: %d GWrBlocks: %d GWrRemain: %d\n", - (int)BTOBBT(log->l_grant_reserve_bytes), - log->l_grant_reserve_bytes % BBSIZE, - (int)BTOBBT(log->l_grant_write_bytes), - log->l_grant_write_bytes % BBSIZE); -#ifdef XFS_LOG_TRACE - qprintf("trace: 0x%p grant_trace: use xlog value\n", log->l_trace); -#endif -} /* xfsidbg_xlog */ - -static void -xfsidbg_print_trans_type(unsigned int t_type) -{ - switch (t_type) { - case XFS_TRANS_SETATTR_NOT_SIZE: kdb_printf("SETATTR_NOT_SIZE");break; - case XFS_TRANS_SETATTR_SIZE: kdb_printf("SETATTR_SIZE"); break; - case XFS_TRANS_INACTIVE: kdb_printf("INACTIVE"); break; - case XFS_TRANS_CREATE: kdb_printf("CREATE"); break; - case XFS_TRANS_CREATE_TRUNC: kdb_printf("CREATE_TRUNC"); break; - case XFS_TRANS_TRUNCATE_FILE: kdb_printf("TRUNCATE_FILE"); break; - case XFS_TRANS_REMOVE: kdb_printf("REMOVE"); break; - case XFS_TRANS_LINK: kdb_printf("LINK"); break; - case XFS_TRANS_RENAME: kdb_printf("RENAME"); break; - case XFS_TRANS_MKDIR: kdb_printf("MKDIR"); break; - case XFS_TRANS_RMDIR: kdb_printf("RMDIR"); break; - case XFS_TRANS_SYMLINK: kdb_printf("SYMLINK"); break; - case XFS_TRANS_SET_DMATTRS: kdb_printf("SET_DMATTRS"); break; - case XFS_TRANS_GROWFS: kdb_printf("GROWFS"); break; - case XFS_TRANS_STRAT_WRITE: kdb_printf("STRAT_WRITE"); break; - case XFS_TRANS_DIOSTRAT: kdb_printf("DIOSTRAT"); break; - case XFS_TRANS_WRITE_SYNC: kdb_printf("WRITE_SYNC"); break; - case XFS_TRANS_WRITEID: kdb_printf("WRITEID"); break; - case XFS_TRANS_ADDAFORK: kdb_printf("ADDAFORK"); break; - case XFS_TRANS_ATTRINVAL: kdb_printf("ATTRINVAL"); break; - case XFS_TRANS_ATRUNCATE: kdb_printf("ATRUNCATE"); break; - case XFS_TRANS_ATTR_SET: kdb_printf("ATTR_SET"); break; - case XFS_TRANS_ATTR_RM: kdb_printf("ATTR_RM"); break; - case XFS_TRANS_ATTR_FLAG: kdb_printf("ATTR_FLAG"); break; - case XFS_TRANS_CLEAR_AGI_BUCKET:kdb_printf("CLEAR_AGI_BUCKET"); break; - case XFS_TRANS_QM_SBCHANGE: kdb_printf("QM_SBCHANGE"); break; - case XFS_TRANS_QM_QUOTAOFF: kdb_printf("QM_QUOTAOFF"); break; - case XFS_TRANS_QM_DQALLOC: kdb_printf("QM_DQALLOC"); break; - case XFS_TRANS_QM_SETQLIM: kdb_printf("QM_SETQLIM"); break; - case XFS_TRANS_QM_DQCLUSTER: kdb_printf("QM_DQCLUSTER"); break; - case XFS_TRANS_QM_QINOCREATE: kdb_printf("QM_QINOCREATE"); break; - case XFS_TRANS_QM_QUOTAOFF_END: kdb_printf("QM_QOFF_END"); break; - case XFS_TRANS_SB_UNIT: kdb_printf("SB_UNIT"); break; - case XFS_TRANS_FSYNC_TS: kdb_printf("FSYNC_TS"); break; - case XFS_TRANS_GROWFSRT_ALLOC: kdb_printf("GROWFSRT_ALLOC"); break; - case XFS_TRANS_GROWFSRT_ZERO: kdb_printf("GROWFSRT_ZERO"); break; - case XFS_TRANS_GROWFSRT_FREE: kdb_printf("GROWFSRT_FREE"); break; - default: kdb_printf("unknown(0x%x)", t_type); break; - } -} - -#ifdef XFS_LOG_TRACE -/* - * Print grant trace for a log. - */ -static void -xfsidbg_xlog_granttrace(xlog_t *log) -{ - ktrace_entry_t *ktep; - ktrace_snap_t kts; - ktrace_t *kt; - int i = 0; - unsigned long cnts,t_ocnt, t_cnt; - - if (((__psint_t)log) == ((__psint_t)-1)) { - qprintf("Usage: xl_grtr \n"); - return; - } - if ((kt = log->l_grant_trace)) - qprintf("log->l_grant_trace 0x%p\n", kt); - else { - qprintf("log->l_grant_trace is empty!\n"); - return; - } - ktep = ktrace_first(kt, &kts); - while (ktep != NULL) { - /* split cnts into two parts: cnt and ocnt */ - cnts = (unsigned long)ktep->val[13]; - t_ocnt = 0xff & cnts; - t_cnt = cnts >> 8; - - qprintf("%d: %s [", i++, (char *)ktep->val[11]); - xfsidbg_print_trans_type((unsigned long)ktep->val[12]); - qprintf("]\n"); - qprintf(" t_ocnt = %lu, t_cnt = %lu, t_curr_res = %lu, " - "t_unit_res = %lu\n", - t_ocnt, t_cnt, (unsigned long)ktep->val[14], - (unsigned long)ktep->val[15]); - qprintf(" tic:0x%p resQ:0x%p wrQ:0x%p ", - ktep->val[0], ktep->val[1], ktep->val[2]); - qprintf(" GrResC:%ld GrResB:%ld GrWrC:%ld GrWrB:%ld \n", - (long)ktep->val[3], (long)ktep->val[4], - (long)ktep->val[5], (long)ktep->val[6]); - qprintf(" HeadC:%ld HeadB:%ld TailC:%ld TailB:%ld\n", - (long)ktep->val[7], (long)ktep->val[8], - (long)ktep->val[9], (long)ktep->val[10]); - ktep = ktrace_next(kt, &kts); - } -} /* xfsidbg_xlog_granttrace */ -#endif - -/* - * Print out an XFS recovery transaction - */ -static void -xfsidbg_xlog_ritem(xlog_recover_item_t *item) -{ - int i = XLOG_MAX_REGIONS_IN_ITEM; - - kdb_printf("(xlog_recover_item 0x%p) ", item); - kdb_printf("next: 0x%p prev: 0x%p type: %d cnt: %d ttl: %d\n", - item->ri_next, item->ri_prev, ITEM_TYPE(item), item->ri_cnt, - item->ri_total); - for ( ; i > 0; i--) { - if (!item->ri_buf[XLOG_MAX_REGIONS_IN_ITEM-i].i_addr) - break; - kdb_printf("a: 0x%p l: %d ", - item->ri_buf[XLOG_MAX_REGIONS_IN_ITEM-i].i_addr, - item->ri_buf[XLOG_MAX_REGIONS_IN_ITEM-i].i_len); - } - kdb_printf("\n"); -} /* xfsidbg_xlog_ritem */ - -/* - * Print out an XFS recovery transaction - */ -static void -xfsidbg_xlog_rtrans(xlog_recover_t *trans) -{ - xlog_recover_item_t *rip, *first_rip; - - kdb_printf("(xlog_recover 0x%p) ", trans); - kdb_printf("tid: %x type: %d items: %d ttid: 0x%x ", - trans->r_log_tid, trans->r_theader.th_type, - trans->r_theader.th_num_items, trans->r_theader.th_tid); - kdb_printf("itemq: 0x%p\n", trans->r_itemq); - if (trans->r_itemq) { - rip = first_rip = trans->r_itemq; - do { - kdb_printf("(recovery item: 0x%p) ", rip); - kdb_printf("type: %d cnt: %d total: %d\n", - ITEM_TYPE(rip), rip->ri_cnt, rip->ri_total); - rip = rip->ri_next; - } while (rip != first_rip); - } -} /* xfsidbg_xlog_rtrans */ - -static void -xfsidbg_xlog_buf_logitem(xlog_recover_item_t *item) -{ - xfs_buf_log_format_t *buf_f; - int i, j; - int bit; - int nbits; - unsigned int *data_map; - unsigned int map_size; - int size; - - buf_f = (xfs_buf_log_format_t *)item->ri_buf[0].i_addr; - if (buf_f->blf_flags & XFS_BLI_INODE_BUF) { - kdb_printf("\tINODE BUF \n", - buf_f->blf_blkno, buf_f->blf_len); - } else if (buf_f->blf_flags & - (XFS_BLI_UDQUOT_BUF|XFS_BLI_PDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) { - kdb_printf("\tDQUOT BUF \n", - buf_f->blf_blkno, buf_f->blf_len); - } else { - data_map = buf_f->blf_data_map; - map_size = buf_f->blf_map_size; - kdb_printf("\tREG BUF \n", - buf_f->blf_blkno, buf_f->blf_len, data_map, map_size); - bit = 0; - i = 0; /* 0 is the buf format structure */ - while (1) { - bit = xfs_next_bit(data_map, map_size, bit); - if (bit == -1) - break; - nbits = xfs_contig_bits(data_map, map_size, bit); - size = ((uint)bit << XFS_BLI_SHIFT)+(nbits<ri_buf[i].i_addr, size); - kdb_printf("\t\t\t\""); - for (j=0; j<8 && jri_buf[i].i_addr)[j]); - } - kdb_printf("...\"\n"); - i++; - bit += nbits; - } - - } -} - -/* - * Print out an ENTIRE XFS recovery transaction - */ -static void -xfsidbg_xlog_rtrans_entire(xlog_recover_t *trans) -{ - xlog_recover_item_t *item, *first_rip; - - kdb_printf("(Recovering Xact 0x%p) ", trans); - kdb_printf("tid: %x type: %d nitems: %d ttid: 0x%x ", - trans->r_log_tid, trans->r_theader.th_type, - trans->r_theader.th_num_items, trans->r_theader.th_tid); - kdb_printf("itemq: 0x%p\n", trans->r_itemq); - if (trans->r_itemq) { - item = first_rip = trans->r_itemq; - do { - /* - kdb_printf("(recovery item: 0x%x) ", item); - kdb_printf("type: %d cnt: %d total: %d\n", - item->ri_type, item->ri_cnt, item->ri_total); - */ - if ((ITEM_TYPE(item) == XFS_LI_BUF) || - (ITEM_TYPE(item) == XFS_LI_6_1_BUF) || - (ITEM_TYPE(item) == XFS_LI_5_3_BUF)) { - kdb_printf("BUF:"); - xfsidbg_xlog_buf_logitem(item); - } else if ((ITEM_TYPE(item) == XFS_LI_INODE) || - (ITEM_TYPE(item) == XFS_LI_6_1_INODE) || - (ITEM_TYPE(item) == XFS_LI_5_3_INODE)) { - kdb_printf("INODE:\n"); - } else if (ITEM_TYPE(item) == XFS_LI_EFI) { - kdb_printf("EFI:\n"); - } else if (ITEM_TYPE(item) == XFS_LI_EFD) { - kdb_printf("EFD:\n"); - } else if (ITEM_TYPE(item) == XFS_LI_DQUOT) { - kdb_printf("DQUOT:\n"); - } else if ((ITEM_TYPE(item) == XFS_LI_QUOTAOFF)) { - kdb_printf("QUOTAOFF:\n"); - } else { - kdb_printf("UNKNOWN LOGITEM 0x%x\n", ITEM_TYPE(item)); - } - item = item->ri_next; - } while (item != first_rip); - } -} /* xfsidbg_xlog_rtrans */ - -/* - * Print out an XFS ticket structure. - */ -static void -xfsidbg_xlog_tic(xlog_ticket_t *tic) -{ - static char *t_flags[] = { - "INIT", /* 0x1 */ - "PERM_RES", /* 0x2 */ - "IN_Q", /* 0x4 */ - NULL - }; - - kdb_printf("xlog_ticket at 0x%p\n", tic); - kdb_printf("next: 0x%p prev: 0x%p tid: 0x%x \n", - tic->t_next, tic->t_prev, tic->t_tid); - kdb_printf("curr_res: %d unit_res: %d ocnt: %d cnt: %d\n", - tic->t_curr_res, tic->t_unit_res, (int)tic->t_ocnt, - (int)tic->t_cnt); - kdb_printf("clientid: %c \n", tic->t_clientid); - printflags(tic->t_flags, t_flags,"ticket"); - kdb_printf("\n"); - qprintf("trans type: "); - xfsidbg_print_trans_type(tic->t_trans_type); - qprintf("\n"); -} /* xfsidbg_xlog_tic */ - -/* - * Print out a single log item. - */ -static void -xfsidbg_xlogitem(xfs_log_item_t *lip) -{ - xfs_log_item_t *bio_lip; - static char *lid_type[] = { - "???", /* 0 */ - "5-3-buf", /* 1 */ - "5-3-inode", /* 2 */ - "efi", /* 3 */ - "efd", /* 4 */ - "iunlink", /* 5 */ - "6-1-inode", /* 6 */ - "6-1-buf", /* 7 */ - "inode", /* 8 */ - "buf", /* 9 */ - "dquot", /* 10 */ - NULL - }; - static char *li_flags[] = { - "in ail", /* 0x1 */ - NULL - }; - - kdb_printf("type %s mountp 0x%p flags ", - lid_type[lip->li_type - XFS_LI_5_3_BUF + 1], - lip->li_mountp); - printflags((uint)(lip->li_flags), li_flags,"log"); - kdb_printf("\n"); - kdb_printf("ail forw 0x%p ail back 0x%p lsn %s\ndesc %p ops 0x%p", - lip->li_ail.ail_forw, lip->li_ail.ail_back, - xfs_fmtlsn(&(lip->li_lsn)), lip->li_desc, lip->li_ops); - kdb_printf(" iodonefunc &0x%p\n", lip->li_cb); - if (lip->li_type == XFS_LI_BUF) { - bio_lip = lip->li_bio_list; - if (bio_lip != NULL) { - kdb_printf("iodone list:\n"); - } - while (bio_lip != NULL) { - kdb_printf("item 0x%p func 0x%p\n", - bio_lip, bio_lip->li_cb); - bio_lip = bio_lip->li_bio_list; - } - } - switch (lip->li_type) { - case XFS_LI_BUF: - xfs_buf_item_print((xfs_buf_log_item_t *)lip, 0); - break; - case XFS_LI_INODE: - xfs_inode_item_print((xfs_inode_log_item_t *)lip, 0); - break; - case XFS_LI_EFI: - xfs_efi_item_print((xfs_efi_log_item_t *)lip, 0); - break; - case XFS_LI_EFD: - xfs_efd_item_print((xfs_efd_log_item_t *)lip, 0); - break; - case XFS_LI_DQUOT: - xfs_dquot_item_print((xfs_dq_logitem_t *)lip, 0); - break; - case XFS_LI_QUOTAOFF: - xfs_qoff_item_print((xfs_qoff_logitem_t *)lip, 0); - break; - - default: - kdb_printf("Unknown item type %d\n", lip->li_type); - break; - } -} - -/* - * Print out a summary of the AIL hanging off of a mount struct. - */ -static void -xfsidbg_xaildump(xfs_mount_t *mp) -{ - xfs_log_item_t *lip; - static char *lid_type[] = { - "???", /* 0 */ - "5-3-buf", /* 1 */ - "5-3-inode", /* 2 */ - "efi", /* 3 */ - "efd", /* 4 */ - "iunlink", /* 5 */ - "6-1-inode", /* 6 */ - "6-1-buf", /* 7 */ - "inode", /* 8 */ - "buf", /* 9 */ - "dquot", /* 10 */ - NULL - }; - static char *li_flags[] = { - "in ail", /* 0x1 */ - NULL - }; - int count; - - if ((mp->m_ail.ail_forw == NULL) || - (mp->m_ail.ail_forw == (xfs_log_item_t *)&mp->m_ail)) { - kdb_printf("AIL is empty\n"); - return; - } - kdb_printf("AIL for mp 0x%p, oldest first\n", mp); - lip = (xfs_log_item_t*)mp->m_ail.ail_forw; - for (count = 0; lip; count++) { - kdb_printf("[%d] type %s ", count, - lid_type[lip->li_type - XFS_LI_5_3_BUF + 1]); - printflags((uint)(lip->li_flags), li_flags, "flags:"); - kdb_printf(" lsn %s\n ", xfs_fmtlsn(&(lip->li_lsn))); - switch (lip->li_type) { - case XFS_LI_BUF: - xfs_buf_item_print((xfs_buf_log_item_t *)lip, 1); - break; - case XFS_LI_INODE: - xfs_inode_item_print((xfs_inode_log_item_t *)lip, 1); - break; - case XFS_LI_EFI: - xfs_efi_item_print((xfs_efi_log_item_t *)lip, 1); - break; - case XFS_LI_EFD: - xfs_efd_item_print((xfs_efd_log_item_t *)lip, 1); - break; - case XFS_LI_DQUOT: - xfs_dquot_item_print((xfs_dq_logitem_t *)lip, 1); - break; - case XFS_LI_QUOTAOFF: - xfs_qoff_item_print((xfs_qoff_logitem_t *)lip, 1); - break; - default: - kdb_printf("Unknown item type %d\n", lip->li_type); - break; - } - - if (lip->li_ail.ail_forw == (xfs_log_item_t*)&mp->m_ail) { - lip = NULL; - } else { - lip = lip->li_ail.ail_forw; - } - } -} - -/* - * Print xfs mount structure. - */ -static void -xfsidbg_xmount(xfs_mount_t *mp) -{ - static char *xmount_flags[] = { - "WSYNC", /* 0x0001 */ - "INO64", /* 0x0002 */ - "UNUSED_4", /* 0x0004 */ - "UNUSED_8", /* 0x0008 */ - "FSSHUTDOWN", /* 0x0010 */ - "NOATIME", /* 0x0020 */ - "RETERR", /* 0x0040 */ - "NOALIGN", /* 0x0080 */ - "ATTR2", /* 0x0100 */ - "UNUSED_200", /* 0x0200 */ - "NORECOVERY", /* 0x0400 */ - "SHARED", /* 0x0800 */ - "DFLT_IOSIZE", /* 0x1000 */ - "OSYNCISOSYNC", /* 0x2000 */ - "32BITINODES", /* 0x4000 */ - "32BITINOOPT", /* 0x8000 */ - "NOUUID", /* 0x10000 */ - "BARRIER", /* 0x20000 */ - "IDELETE", /* 0x40000 */ - "SWALLOC", /* 0x80000 */ - "IHASHSIZE", /* 0x100000 */ - "DIRSYNC", /* 0x200000 */ - "COMPAT_IOSIZE",/* 0x400000 */ - NULL - }; - - static char *quota_flags[] = { - "UQ", /* 0x0001 */ - "UQE", /* 0x0002 */ - "UQCHKD", /* 0x0004 */ - "PQ", /* 0x0008 */ - "GQE", /* 0x0010 */ - "GQCHKD", /* 0x0020 */ - "GQ", /* 0x0040 */ - "UQACTV", /* 0x0080 */ - "GQACTV", /* 0x0100 */ - "QMAYBE", /* 0x0200 */ - NULL - }; - - kdb_printf("xfs_mount at 0x%p\n", mp); - kdb_printf("vfsp 0x%p tid 0x%x ail_lock 0x%p &ail 0x%p\n", - XFS_MTOVFS(mp), mp->m_tid, &mp->m_ail_lock, &mp->m_ail); - kdb_printf("ail_gen 0x%x &sb 0x%p\n", - mp->m_ail_gen, &mp->m_sb); - kdb_printf("sb_lock 0x%p sb_bp 0x%p dev 0x%s logdev 0x%s rtdev 0x%s\n", - &mp->m_sb_lock, mp->m_sb_bp, - mp->m_ddev_targp ? devtoname(mp->m_ddev_targp->dev) : 0, - mp->m_logdev_targp ? devtoname(mp->m_logdev_targp->dev) : 0, - mp->m_rtdev_targp ? devtoname(mp->m_rtdev_targp->dev) : 0); - kdb_printf("bsize %d agfrotor %d xfs_rotorstep %d agirotor %d\n", - mp->m_bsize, mp->m_agfrotor, xfs_rotorstep, mp->m_agirotor); - kdb_printf("ihash 0x%p ihsize %d\n", - mp->m_ihash, mp->m_ihsize); - kdb_printf("inodes 0x%p ilock 0x%p ireclaims 0x%x\n", - mp->m_inodes, &mp->m_ilock, mp->m_ireclaims); - kdb_printf("readio_log 0x%x readio_blocks 0x%x ", - mp->m_readio_log, mp->m_readio_blocks); - kdb_printf("writeio_log 0x%x writeio_blocks 0x%x\n", - mp->m_writeio_log, mp->m_writeio_blocks); - kdb_printf("logbufs %d logbsize %d LOG 0x%p\n", mp->m_logbufs, - mp->m_logbsize, mp->m_log); - kdb_printf("rsumlevels 0x%x rsumsize 0x%x rbmip 0x%p rsumip 0x%p\n", - mp->m_rsumlevels, mp->m_rsumsize, mp->m_rbmip, mp->m_rsumip); - kdb_printf("rootip 0x%p\n", mp->m_rootip); - kdb_printf("dircook_elog %d blkbit_log %d blkbb_log %d agno_log %d\n", - mp->m_dircook_elog, mp->m_blkbit_log, mp->m_blkbb_log, - mp->m_agno_log); - kdb_printf("agino_log %d nreadaheads %d inode cluster size %d\n", - mp->m_agino_log, mp->m_nreadaheads, - mp->m_inode_cluster_size); - kdb_printf("blockmask 0x%x blockwsize 0x%x blockwmask 0x%x\n", - mp->m_blockmask, mp->m_blockwsize, mp->m_blockwmask); - kdb_printf("alloc_mxr[lf,nd] %d %d alloc_mnr[lf,nd] %d %d\n", - mp->m_alloc_mxr[0], mp->m_alloc_mxr[1], - mp->m_alloc_mnr[0], mp->m_alloc_mnr[1]); - kdb_printf("bmap_dmxr[lfnr,ndnr] %d %d bmap_dmnr[lfnr,ndnr] %d %d\n", - mp->m_bmap_dmxr[0], mp->m_bmap_dmxr[1], - mp->m_bmap_dmnr[0], mp->m_bmap_dmnr[1]); - kdb_printf("inobt_mxr[lf,nd] %d %d inobt_mnr[lf,nd] %d %d\n", - mp->m_inobt_mxr[0], mp->m_inobt_mxr[1], - mp->m_inobt_mnr[0], mp->m_inobt_mnr[1]); - kdb_printf("ag_maxlevels %d bm_maxlevels[d,a] %d %d in_maxlevels %d\n", - mp->m_ag_maxlevels, mp->m_bm_maxlevels[0], - mp->m_bm_maxlevels[1], mp->m_in_maxlevels); - kdb_printf("perag 0x%p &peraglock 0x%p &growlock 0x%p\n", - mp->m_perag, &mp->m_peraglock, &mp->m_growlock); - printflags(mp->m_flags, xmount_flags,"flags"); - kdb_printf("ialloc_inos %d ialloc_blks %d litino %d\n", - mp->m_ialloc_inos, mp->m_ialloc_blks, mp->m_litino); - kdb_printf("dir_node_ents %u attr_node_ents %u\n", - mp->m_dir_node_ents, mp->m_attr_node_ents); - kdb_printf("attroffset %d maxicount %Ld inoalign_mask %d\n", - mp->m_attroffset, mp->m_maxicount, mp->m_inoalign_mask); - kdb_printf("resblks %Ld resblks_avail %Ld\n", mp->m_resblks, - mp->m_resblks_avail); -#if XFS_BIG_INUMS - kdb_printf(" inoadd %llx\n", (unsigned long long) mp->m_inoadd); -#else - kdb_printf("\n"); -#endif - if (mp->m_quotainfo) - kdb_printf("quotainfo 0x%p (uqip = 0x%p, gqip = 0x%p)\n", - mp->m_quotainfo, - mp->m_quotainfo->qi_uquotaip, - mp->m_quotainfo->qi_gquotaip); - else - kdb_printf("quotainfo NULL\n"); - printflags(mp->m_qflags, quota_flags,"quotaflags"); - kdb_printf("\n"); - kdb_printf("dalign %d swidth %d sinoalign %d attr_magicpct %d dir_magicpct %d\n", - mp->m_dalign, mp->m_swidth, mp->m_sinoalign, - mp->m_attr_magicpct, mp->m_dir_magicpct); - kdb_printf("mk_sharedro %d inode_quiesce %d sectbb_log %d\n", - mp->m_mk_sharedro, mp->m_inode_quiesce, mp->m_sectbb_log); - kdb_printf("dirversion %d dirblkfsbs %d &dirops 0x%p\n", - mp->m_dirversion, mp->m_dirblkfsbs, &mp->m_dirops); - kdb_printf("dirblksize %d dirdatablk 0x%Lx dirleafblk 0x%Lx dirfreeblk 0x%Lx\n", - mp->m_dirblksize, - (xfs_dfiloff_t)mp->m_dirdatablk, - (xfs_dfiloff_t)mp->m_dirleafblk, - (xfs_dfiloff_t)mp->m_dirfreeblk); - kdb_printf("chsize %d chash 0x%p\n", - mp->m_chsize, mp->m_chash); - if (mp->m_fsname != NULL) - kdb_printf("mountpoint \"%s\"\n", mp->m_fsname); - else - kdb_printf("No name!!!\n"); - -} - -static void -xfsidbg_xihash(xfs_mount_t *mp) -{ - xfs_ihash_t *ih; - int i; - int j; - int total; - int numzeros; - xfs_inode_t *ip; - int *hist; - int hist_bytes = mp->m_ihsize * sizeof(int); - int hist2[21]; - - hist = (int *) kmem_alloc(hist_bytes, KM_SLEEP); - - if (hist == NULL) { - kdb_printf("xfsidbg_xihash: kmalloc(%d) failed!\n", - hist_bytes); - return; - } - - for (i = 0; i < mp->m_ihsize; i++) { - ih = mp->m_ihash + i; - j = 0; - for (ip = ih->ih_next; ip != NULL; ip = ip->i_next) - j++; - hist[i] = j; - } - - numzeros = total = 0; - - for (i = 0; i < 21; i++) - hist2[i] = 0; - - for (i = 0; i < mp->m_ihsize; i++) { - kdb_printf("%d ", hist[i]); - total += hist[i]; - numzeros += hist[i] == 0 ? 1 : 0; - if (hist[i] > 20) - j = 20; - else - j = hist[i]; - - if (! (j <= 20)) { - kdb_printf("xfsidbg_xihash: (j > 20)/%d @ line # %d\n", - j, __LINE__); - return; - } - - hist2[j]++; - } - - kdb_printf("\n"); - - kdb_printf("total inodes = %d, average length = %d, adjusted average = %d \n", - total, total / mp->m_ihsize, - total / (mp->m_ihsize - numzeros)); - - for (i = 0; i < 21; i++) { - kdb_printf("%d - %d , ", i, hist2[i]); - } - kdb_printf("\n"); - kmem_free(hist, hist_bytes); -} - -/* - * Command to print xfs inodes: kp xnode - */ -static void -xfsidbg_xnode(xfs_inode_t *ip) -{ - static char *tab_flags[] = { - "grio", /* XFS_IGRIO */ - "uiosize", /* XFS_IUIOSZ */ - "quiesce", /* XFS_IQUIESCE */ - "reclaim", /* XFS_IRECLAIM */ - "stale", /* XFS_ISTALE */ - NULL - }; - - kdb_printf("hash 0x%p next 0x%p prevp 0x%p mount 0x%p\n", - ip->i_hash, - ip->i_next, - ip->i_prevp, - ip->i_mount); - kdb_printf("mnext 0x%p mprev 0x%p vnode 0x%p \n", - ip->i_mnext, - ip->i_mprev, - XFS_ITOV_NULL(ip)); - kdb_printf("dev %s ino %s\n", - devtoname(ip->i_mount->m_dev), - xfs_fmtino(ip->i_ino, ip->i_mount)); - kdb_printf("blkno 0x%llx len 0x%x boffset 0x%x\n", - (long long) ip->i_blkno, - ip->i_len, - ip->i_boffset); - kdb_printf("transp 0x%p &itemp 0x%p\n", - ip->i_transp, - ip->i_itemp); - kdb_printf("&lock 0x%p &iolock 0x%p ", - &ip->i_lock, - &ip->i_iolock); - kdb_printf("&flock 0x%p (%d) pincount 0x%x\n", - &ip->i_flock, valusema(&ip->i_flock), - xfs_ipincount(ip)); - kdb_printf("udquotp 0x%p gdquotp 0x%p\n", - ip->i_udquot, ip->i_gdquot); - kdb_printf("new_size %Ld\n", ip->i_iocore.io_new_size); - printflags((int)ip->i_flags, tab_flags, "flags"); - kdb_printf("\n"); - kdb_printf("update_core %d update size %d\n", - (int)(ip->i_update_core), (int) ip->i_update_size); - kdb_printf("gen 0x%x delayed blks %d", - ip->i_gen, - ip->i_delayed_blks); -#ifdef XFS_BMAP_TRACE - qprintf(" bmap_trace 0x%p\n", ip->i_xtrace); -#endif -#ifdef XFS_BMBT_TRACE - qprintf(" bmbt trace 0x%p\n", ip->i_btrace); -#endif -#ifdef XFS_RW_TRACE - qprintf(" rw trace 0x%p\n", ip->i_rwtrace); -#endif -#ifdef XFS_ILOCK_TRACE - qprintf(" ilock trace 0x%p\n", ip->i_lock_trace); -#endif -#ifdef XFS_DIR2_TRACE - qprintf(" dir trace 0x%p\n", ip->i_dir_trace); -#endif - kdb_printf("\n"); - kdb_printf("chash 0x%p cnext 0x%p cprev 0x%p\n", - ip->i_chash, - ip->i_cnext, - ip->i_cprev); - xfs_xnode_fork("data", &ip->i_df); - xfs_xnode_fork("attr", ip->i_afp); - kdb_printf("\n"); - xfs_prdinode_core(&ip->i_d); -} - -static void -xfsidbg_xcore(xfs_iocore_t *io) -{ - kdb_printf("io_obj 0x%p io_flags 0x%x io_mount 0x%p\n", - io->io_obj, io->io_flags, io->io_mount); - kdb_printf("new_size %Lx\n", io->io_new_size); -} - -/* - * Command to print xfs inode cluster hash table: kp xchash - */ -static void -xfsidbg_xchash(xfs_mount_t *mp) -{ - int i; - xfs_chash_t *ch; - - kdb_printf("m_chash 0x%p size %d\n", - mp->m_chash, mp->m_chsize); - for (i = 0; i < mp->m_chsize; i++) { - ch = mp->m_chash + i; - kdb_printf("[%3d] ch 0x%p chashlist 0x%p\n", i, ch, ch->ch_list); - xfsidbg_xchashlist(ch->ch_list); - } -} - -/* - * Command to print xfs inode cluster hash list: kp xchashlist - */ -static void -xfsidbg_xchashlist(xfs_chashlist_t *chl) -{ - xfs_inode_t *ip; - - while (chl != NULL) { - kdb_printf("hashlist inode 0x%p blkno %lld buf 0x%p", - chl->chl_ip, (long long) chl->chl_blkno, chl->chl_buf); - - kdb_printf("\n"); - - /* print inodes on chashlist */ - ip = chl->chl_ip; - do { - kdb_printf("0x%p ", ip); - ip = ip->i_cnext; - } while (ip != chl->chl_ip); - kdb_printf("\n"); - - chl=chl->chl_next; - } -} - -/* - * Print xfs per-ag data structures for filesystem. - */ -static void -xfsidbg_xperag(xfs_mount_t *mp) -{ - xfs_agnumber_t agno; - xfs_perag_t *pag; - int busy; - - pag = mp->m_perag; - for (agno = 0; agno < mp->m_sb.sb_agcount; agno++, pag++) { - kdb_printf("ag %d f_init %d i_init %d\n", - agno, pag->pagf_init, pag->pagi_init); - if (pag->pagf_init) - kdb_printf( - " f_levels[b,c] %d,%d f_flcount %d f_freeblks %d f_longest %d\n" - " f__metadata %d\n", - pag->pagf_levels[XFS_BTNUM_BNOi], - pag->pagf_levels[XFS_BTNUM_CNTi], - pag->pagf_flcount, pag->pagf_freeblks, - pag->pagf_longest, pag->pagf_metadata); - if (pag->pagi_init) - kdb_printf(" i_freecount %d i_inodeok %d\n", - pag->pagi_freecount, pag->pagi_inodeok); - if (pag->pagf_init) { - for (busy = 0; busy < XFS_PAGB_NUM_SLOTS; busy++) { - if (pag->pagb_list[busy].busy_length != 0) { - kdb_printf( - " %04d: start %d length %d tp 0x%p\n", - busy, - pag->pagb_list[busy].busy_start, - pag->pagb_list[busy].busy_length, - pag->pagb_list[busy].busy_tp); - } - } - } - } -} - -#ifdef CONFIG_XFS_QUOTA -static void -xfsidbg_xqm(void) -{ - if (xfs_Gqm == NULL) { - kdb_printf("NULL XQM!!\n"); - return; - } - - kdb_printf("usrhtab 0x%p grphtab 0x%p ndqfree 0x%x hashmask 0x%x\n", - xfs_Gqm->qm_usr_dqhtable, - xfs_Gqm->qm_grp_dqhtable, - xfs_Gqm->qm_dqfreelist.qh_nelems, - xfs_Gqm->qm_dqhashmask); - kdb_printf("&freelist 0x%p, totaldquots 0x%x nrefs 0x%x\n", - &xfs_Gqm->qm_dqfreelist, - atomic_read(&xfs_Gqm->qm_totaldquots), - xfs_Gqm->qm_nrefs); -} -#endif - -static void -xfsidbg_xqm_diskdq(xfs_disk_dquot_t *d) -{ - kdb_printf("magic 0x%x\tversion 0x%x\tID 0x%x (%d)\t\n", - be16_to_cpu(d->d_magic), d->d_version, - be32_to_cpu(d->d_id), be32_to_cpu(d->d_id)); - kdb_printf("bhard 0x%llx\tbsoft 0x%llx\tihard 0x%llx\tisoft 0x%llx\n", - be64_to_cpu(d->d_blk_hardlimit), - be64_to_cpu(d->d_blk_softlimit), - be64_to_cpu(d->d_ino_hardlimit), - be64_to_cpu(d->d_ino_softlimit)); - kdb_printf("bcount 0x%llx icount 0x%llx\n", - be64_to_cpu(d->d_bcount), - be64_to_cpu(d->d_icount)); - kdb_printf("btimer 0x%x itimer 0x%x \n", - be32_to_cpu(d->d_btimer), - be32_to_cpu(d->d_itimer)); -} - -static char *xdq_flags[] = { - "USER", /* XFS_DQ_USER */ - "PROJ", /* XFS_DQ_PROJ */ - "GROUP", /* XFS_DQ_GROUP */ - "FLKD", /* XFS_DQ_FLOCKED */ - "DIRTY", /* XFS_DQ_DIRTY */ - "WANT", /* XFS_DQ_WANT */ - "INACT", /* XFS_DQ_INACTIVE */ - "MARKER", /* XFS_DQ_MARKER */ - NULL -}; - -static void -xfsidbg_xqm_dquot(xfs_dquot_t *dqp) -{ - kdb_printf("mount 0x%p hash 0x%p gdquotp 0x%p HL_next 0x%p HL_prevp 0x%p\n", - dqp->q_mount, - dqp->q_hash, - dqp->q_gdquot, - dqp->HL_NEXT, - dqp->HL_PREVP); - kdb_printf("MPL_next 0x%p MPL_prevp 0x%p FL_next 0x%p FL_prev 0x%p\n", - dqp->MPL_NEXT, - dqp->MPL_PREVP, - dqp->dq_flnext, - dqp->dq_flprev); - - kdb_printf("nrefs 0x%x blkno 0x%llx boffset 0x%x ", dqp->q_nrefs, - (unsigned long long)dqp->q_blkno, dqp->q_bufoffset); - printflags(dqp->dq_flags, xdq_flags, "flags:"); - kdb_printf("res_bcount %llu res_icount %llu res_rtbcount %llu\n", - (unsigned long long)dqp->q_res_bcount, - (unsigned long long)dqp->q_res_icount, - (unsigned long long)dqp->q_res_rtbcount); - kdb_printf("qlock 0x%p flock 0x%p (%s) pincount 0x%x\n", - &dqp->q_qlock, - &dqp->q_flock, - (valusema(&dqp->q_flock) <= 0) ? "LCK" : "UNLKD", - dqp->q_pincount); -#ifdef XFS_DQUOT_TRACE - qprintf("dqtrace 0x%p\n", dqp->q_trace); -#endif - kdb_printf("disk-dquot 0x%p\n", &dqp->q_core); - xfsidbg_xqm_diskdq(&dqp->q_core); - -} - - -#define XQMIDBG_LIST_PRINT(l, NXT) \ -{ \ - xfs_dquot_t *dqp;\ - int i = 0; \ - kdb_printf("[#%d dquots]\n", (int) (l)->qh_nelems); \ - for (dqp = (l)->qh_next; dqp != NULL; dqp = dqp->NXT) {\ - kdb_printf( \ - "\t%d. [0x%p] \"%d (%s)\"\t blks = %d, inos = %d refs = %d\n", \ - ++i, dqp, (int) be32_to_cpu(dqp->q_core.d_id), \ - DQFLAGTO_TYPESTR(dqp), \ - (int) be64_to_cpu(dqp->q_core.d_bcount), \ - (int) be64_to_cpu(dqp->q_core.d_icount), \ - (int) dqp->q_nrefs); }\ - kdb_printf("\n"); \ -} - -static void -xfsidbg_xqm_dqattached_inos(xfs_mount_t *mp) -{ - xfs_inode_t *ip; - int n = 0; - - ip = mp->m_inodes; - do { - if (ip->i_mount == NULL) { - ip = ip->i_mnext; - continue; - } - if (ip->i_udquot || ip->i_gdquot) { - n++; - kdb_printf("inode = 0x%p, ino %d: udq 0x%p, gdq 0x%p\n", - ip, (int)ip->i_ino, ip->i_udquot, ip->i_gdquot); - } - ip = ip->i_mnext; - } while (ip != mp->m_inodes); - kdb_printf("\nNumber of inodes with dquots attached: %d\n", n); -} - -#ifdef CONFIG_XFS_QUOTA -static void -xfsidbg_xqm_freelist_print(xfs_frlist_t *qlist, char *title) -{ - xfs_dquot_t *dq; - int i = 0; - kdb_printf("%s (#%d)\n", title, (int) qlist->qh_nelems); - FOREACH_DQUOT_IN_FREELIST(dq, qlist) { - kdb_printf("\t%d.\t\"%d (%s:0x%p)\"\t bcnt = %d, icnt = %d " - "refs = %d\n", - ++i, (int) be32_to_cpu(dq->q_core.d_id), - DQFLAGTO_TYPESTR(dq), dq, - (int) be64_to_cpu(dq->q_core.d_bcount), - (int) be64_to_cpu(dq->q_core.d_icount), - (int) dq->q_nrefs); - } -} - -static void -xfsidbg_xqm_freelist(void) -{ - if (xfs_Gqm) { - xfsidbg_xqm_freelist_print(&(xfs_Gqm->qm_dqfreelist), "Freelist"); - } else - kdb_printf("NULL XQM!!\n"); -} - -static void -xfsidbg_xqm_htab(void) -{ - int i; - xfs_dqhash_t *h; - - if (xfs_Gqm == NULL) { - kdb_printf("NULL XQM!!\n"); - return; - } - for (i = 0; i <= xfs_Gqm->qm_dqhashmask; i++) { - h = &xfs_Gqm->qm_usr_dqhtable[i]; - if (h->qh_next) { - kdb_printf("USR %d: ", i); - XQMIDBG_LIST_PRINT(h, HL_NEXT); - } - } - for (i = 0; i <= xfs_Gqm->qm_dqhashmask; i++) { - h = &xfs_Gqm->qm_grp_dqhtable[i]; - if (h->qh_next) { - kdb_printf("GRP/PRJ %d: ", i); - XQMIDBG_LIST_PRINT(h, HL_NEXT); - } - } -} -#endif - -#ifdef XFS_DQUOT_TRACE -static int -xfsidbg_xqm_pr_dqentry(ktrace_entry_t *ktep) -{ - if ((__psint_t)ktep->val[0] == 0) - return 0; - switch ((__psint_t)ktep->val[0]) { - case DQUOT_KTRACE_ENTRY: - qprintf("[%ld] %s\t", - (long)ktep->val[12], /* pid */ - (char *)ktep->val[1]); - printflags((__psint_t)ktep->val[3], xdq_flags,"flgs "); - qprintf("\nnrefs = %u, " - "flags = 0x%x, " - "id = %d, " - "res_bc = 0x%x\n" - "bcnt = 0x%x [0x%x | 0x%x], " - "icnt = 0x%x [0x%x | 0x%x]\n" - "@ %ld\n", - (unsigned int)(long)ktep->val[2], /* nrefs */ - (unsigned int)(long)ktep->val[3], /* flags */ - (unsigned int)(long)ktep->val[11], /* ID */ - (unsigned int)(long)ktep->val[4], /* res_bc */ - (unsigned int)(long)ktep->val[5], /* bcnt */ - (unsigned int)(long)ktep->val[8], /* bsoft */ - (unsigned int)(long)ktep->val[7], /* bhard */ - (unsigned int)(long)ktep->val[6], /* icnt */ - (unsigned int)(long)ktep->val[10], /* isoft */ - (unsigned int)(long)ktep->val[9], /* ihard */ - (long) ktep->val[13] /* time */ - ); - break; - - default: - qprintf("unknown dqtrace record\n"); - break; - } - return (1); -} - -void -xfsidbg_xqm_dqtrace(xfs_dquot_t *dqp) -{ - ktrace_entry_t *ktep; - ktrace_snap_t kts; - - if (dqp->q_trace == NULL) { - qprintf("The xfs dquot trace buffer is not initialized\n"); - return; - } - qprintf("xdqtrace dquot 0x%p\n", dqp); - - ktep = ktrace_first(dqp->q_trace, &kts); - while (ktep != NULL) { - if (xfsidbg_xqm_pr_dqentry(ktep)) - qprintf("---------------------------------\n"); - ktep = ktrace_next(dqp->q_trace, &kts); - } -} -#endif - -static void -xfsidbg_xqm_mplist(xfs_mount_t *mp) -{ - if (mp->m_quotainfo == NULL) { - kdb_printf("NULL quotainfo\n"); - return; - } - - XQMIDBG_LIST_PRINT(&(mp->m_quotainfo->qi_dqlist), MPL_NEXT); - -} - - -static void -xfsidbg_xqm_qinfo(xfs_mount_t *mp) -{ - if (mp == NULL || mp->m_quotainfo == NULL) { - kdb_printf("NULL quotainfo\n"); - return; - } - - kdb_printf("uqip 0x%p, gqip 0x%p, &pinlock 0x%p &dqlist 0x%p\n", - mp->m_quotainfo->qi_uquotaip, - mp->m_quotainfo->qi_gquotaip, - &mp->m_quotainfo->qi_pinlock, - &mp->m_quotainfo->qi_dqlist); - - kdb_printf("btmlimit 0x%x, itmlimit 0x%x, RTbtmlim 0x%x\n", - (int)mp->m_quotainfo->qi_btimelimit, - (int)mp->m_quotainfo->qi_itimelimit, - (int)mp->m_quotainfo->qi_rtbtimelimit); - - kdb_printf("bwarnlim 0x%x, iwarnlim 0x%x, RTbwarnlim 0x%x\n", - (int)mp->m_quotainfo->qi_bwarnlimit, - (int)mp->m_quotainfo->qi_iwarnlimit, - (int)mp->m_quotainfo->qi_rtbwarnlimit); - - kdb_printf("nreclaims %d, &qofflock 0x%p, chunklen 0x%x, dqperchunk 0x%x\n", - (int)mp->m_quotainfo->qi_dqreclaims, - &mp->m_quotainfo->qi_quotaofflock, - (int)mp->m_quotainfo->qi_dqchunklen, - (int)mp->m_quotainfo->qi_dqperchunk); -} - -static void -xfsidbg_xqm_tpdqinfo(xfs_trans_t *tp) -{ - xfs_dqtrx_t *qa, *q; - int i,j; - - kdb_printf("dqinfo 0x%p\n", tp->t_dqinfo); - if (! tp->t_dqinfo) - return; - kdb_printf("USR: \n"); - qa = tp->t_dqinfo->dqa_usrdquots; - for (j = 0; j < 2; j++) { - for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) { - if (qa[i].qt_dquot == NULL) - break; - q = &qa[i]; - kdb_printf( - "\"%d\"[0x%p]: bres %d, bres-used %d, bdelta %d, del-delta %d, icnt-delta %d\n", - (int) be32_to_cpu(q->qt_dquot->q_core.d_id), - q->qt_dquot, - (int) q->qt_blk_res, - (int) q->qt_blk_res_used, - (int) q->qt_bcount_delta, - (int) q->qt_delbcnt_delta, - (int) q->qt_icount_delta); - } - if (j == 0) { - qa = tp->t_dqinfo->dqa_grpdquots; - kdb_printf("GRP/PRJ: \n"); - } - } -} - -/* - * Print xfs superblock. - */ -static void -xfsidbg_xsb(xfs_sb_t *sbp) -{ - kdb_printf("magicnum 0x%x blocksize 0x%x dblocks %Ld rblocks %Ld\n", - sbp->sb_magicnum, sbp->sb_blocksize, - sbp->sb_dblocks, sbp->sb_rblocks); - kdb_printf("rextents %Ld uuid %s logstart %s\n", - sbp->sb_rextents, xfs_fmtuuid(&sbp->sb_uuid), - xfs_fmtfsblock(sbp->sb_logstart, NULL)); - kdb_printf("rootino %s ", xfs_fmtino(sbp->sb_rootino, NULL)); - kdb_printf("rbmino %s ", xfs_fmtino(sbp->sb_rbmino, NULL)); - kdb_printf("rsumino %s\n", xfs_fmtino(sbp->sb_rsumino, NULL)); - kdb_printf("rextsize 0x%x agblocks 0x%x agcount 0x%x rbmblocks 0x%x\n", - sbp->sb_rextsize, sbp->sb_agblocks, sbp->sb_agcount, - sbp->sb_rbmblocks); - kdb_printf("logblocks 0x%x versionnum 0x%x sectsize 0x%x inodesize 0x%x\n", - sbp->sb_logblocks, sbp->sb_versionnum, sbp->sb_sectsize, - sbp->sb_inodesize); - kdb_printf("inopblock 0x%x blocklog 0x%x sectlog 0x%x inodelog 0x%x\n", - sbp->sb_inopblock, sbp->sb_blocklog, sbp->sb_sectlog, - sbp->sb_inodelog); - kdb_printf("inopblog %d agblklog %d rextslog %d inprogress %d imax_pct %d\n", - sbp->sb_inopblog, sbp->sb_agblklog, sbp->sb_rextslog, - sbp->sb_inprogress, sbp->sb_imax_pct); - kdb_printf("icount %Lx ifree %Lx fdblocks %Lx frextents %Lx\n", - sbp->sb_icount, sbp->sb_ifree, - sbp->sb_fdblocks, sbp->sb_frextents); - kdb_printf("uquotino %s ", xfs_fmtino(sbp->sb_uquotino, NULL)); - kdb_printf("gquotino %s ", xfs_fmtino(sbp->sb_gquotino, NULL)); - kdb_printf("qflags 0x%x flags 0x%x shared_vn %d inoaligmt %d\n", - sbp->sb_qflags, sbp->sb_flags, sbp->sb_shared_vn, - sbp->sb_inoalignmt); - kdb_printf("unit %d width %d dirblklog %d\n", - sbp->sb_unit, sbp->sb_width, sbp->sb_dirblklog); - kdb_printf("log sunit %d\n", sbp->sb_logsunit); -} - -static void -xfsidbg_xsb_convert(xfs_sb_t *sbp) -{ - xfs_sb_t sb; - - xfs_xlatesb(sbp, &sb, 1, XFS_SB_ALL_BITS); - - kdb_printf("\n"); - xfsidbg_xsb(&sb); -} - -/* - * Print out an XFS transaction structure. Print summaries for - * each of the items. - */ -static void -xfsidbg_xtp(xfs_trans_t *tp) -{ - xfs_log_item_chunk_t *licp; - xfs_log_item_desc_t *lidp; - xfs_log_busy_chunk_t *lbcp; - int i; - int chunk; - static char *xtp_flags[] = { - "dirty", /* 0x1 */ - "sb_dirty", /* 0x2 */ - "perm_log_res", /* 0x4 */ - "sync", /* 0x08 */ - "dq_dirty", /* 0x10 */ - NULL - }; - static char *lid_flags[] = { - "dirty", /* 0x1 */ - "pinned", /* 0x2 */ - "sync unlock", /* 0x4 */ - "buf stale", /* 0x8 */ - NULL - }; - - kdb_printf("tp 0x%p type ", tp); - xfsidbg_print_trans_type(tp->t_type); - kdb_printf(" mount 0x%p\n", tp->t_mountp); - kdb_printf("flags "); - printflags(tp->t_flags, xtp_flags,"xtp"); - kdb_printf("\n"); - kdb_printf("callback 0x%p forw 0x%p back 0x%p\n", - &tp->t_logcb, tp->t_forw, tp->t_back); - kdb_printf("log res %d block res %d block res used %d\n", - tp->t_log_res, tp->t_blk_res, tp->t_blk_res_used); - kdb_printf("rt res %d rt res used %d\n", tp->t_rtx_res, - tp->t_rtx_res_used); - kdb_printf("ticket 0x%lx lsn %s commit_lsn %s\n", - (unsigned long) tp->t_ticket, - xfs_fmtlsn(&tp->t_lsn), - xfs_fmtlsn(&tp->t_commit_lsn)); - kdb_printf("callback 0x%p callarg 0x%p\n", - tp->t_callback, tp->t_callarg); - kdb_printf("icount delta %ld ifree delta %ld\n", - tp->t_icount_delta, tp->t_ifree_delta); - kdb_printf("blocks delta %ld res blocks delta %ld\n", - tp->t_fdblocks_delta, tp->t_res_fdblocks_delta); - kdb_printf("rt delta %ld res rt delta %ld\n", - tp->t_frextents_delta, tp->t_res_frextents_delta); - kdb_printf("ag freeblks delta %ld ag flist delta %ld ag btree delta %ld\n", - tp->t_ag_freeblks_delta, tp->t_ag_flist_delta, - tp->t_ag_btree_delta); - kdb_printf("dblocks delta %ld agcount delta %ld imaxpct delta %ld\n", - tp->t_dblocks_delta, tp->t_agcount_delta, tp->t_imaxpct_delta); - kdb_printf("rextsize delta %ld rbmblocks delta %ld\n", - tp->t_rextsize_delta, tp->t_rbmblocks_delta); - kdb_printf("rblocks delta %ld rextents delta %ld rextslog delta %ld\n", - tp->t_rblocks_delta, tp->t_rextents_delta, - tp->t_rextslog_delta); - kdb_printf("dqinfo 0x%p\n", tp->t_dqinfo); - kdb_printf("log items:\n"); - licp = &tp->t_items; - chunk = 0; - while (licp != NULL) { - if (XFS_LIC_ARE_ALL_FREE(licp)) { - licp = licp->lic_next; - chunk++; - continue; - } - for (i = 0; i < licp->lic_unused; i++) { - if (XFS_LIC_ISFREE(licp, i)) { - continue; - } - - lidp = XFS_LIC_SLOT(licp, i); - kdb_printf("\n"); - kdb_printf("chunk %d index %d item 0x%p size %d\n", - chunk, i, lidp->lid_item, lidp->lid_size); - kdb_printf("flags "); - printflags(lidp->lid_flags, lid_flags,"lic"); - kdb_printf("\n"); - xfsidbg_xlogitem(lidp->lid_item); - } - chunk++; - licp = licp->lic_next; - } - - kdb_printf("log busy free %d, list:\n", tp->t_busy_free); - lbcp = &tp->t_busy; - chunk = 0; - while (lbcp != NULL) { - kdb_printf("Chunk %d at 0x%p next 0x%p free 0x%08x unused %d\n", - chunk, lbcp, lbcp->lbc_next, lbcp->lbc_free, - lbcp->lbc_unused); - for (i = 0; i < XFS_LBC_NUM_SLOTS; i++) { - kdb_printf(" %02d: ag %d idx %d\n", - i, - lbcp->lbc_busy[i].lbc_ag, - lbcp->lbc_busy[i].lbc_idx); - } - lbcp = lbcp->lbc_next; - } -} - -static void -xfsidbg_xtrans_res( - xfs_mount_t *mp) -{ - xfs_trans_reservations_t *xtrp; - - xtrp = &mp->m_reservations; - kdb_printf("write: %d\ttruncate: %d\trename: %d\n", - xtrp->tr_write, xtrp->tr_itruncate, xtrp->tr_rename); - kdb_printf("link: %d\tremove: %d\tsymlink: %d\n", - xtrp->tr_link, xtrp->tr_remove, xtrp->tr_symlink); - kdb_printf("create: %d\tmkdir: %d\tifree: %d\n", - xtrp->tr_create, xtrp->tr_mkdir, xtrp->tr_ifree); - kdb_printf("ichange: %d\tgrowdata: %d\tswrite: %d\n", - xtrp->tr_ichange, xtrp->tr_growdata, xtrp->tr_swrite); - kdb_printf("addafork: %d\twriteid: %d\tattrinval: %d\n", - xtrp->tr_addafork, xtrp->tr_writeid, xtrp->tr_attrinval); - kdb_printf("attrset: %d\tattrrm: %d\tclearagi: %d\n", - xtrp->tr_attrset, xtrp->tr_attrrm, xtrp->tr_clearagi); - kdb_printf("growrtalloc: %d\tgrowrtzero: %d\tgrowrtfree: %d\n", - xtrp->tr_growrtalloc, xtrp->tr_growrtzero, xtrp->tr_growrtfree); -} diff --git a/sys/modules/xfs/Makefile b/sys/modules/xfs/Makefile deleted file mode 100644 index 1aabcef51e7..00000000000 --- a/sys/modules/xfs/Makefile +++ /dev/null @@ -1,89 +0,0 @@ -# $FreeBSD$ - -.PATH: ${.CURDIR}/../../gnu/fs/xfs \ - ${.CURDIR}/../../gnu/fs/xfs/FreeBSD \ - ${.CURDIR}/../../gnu/fs/xfs/FreeBSD/support - -KMOD= xfs - -SRCS = vnode_if.h \ - xfs_alloc.c \ - xfs_alloc_btree.c \ - xfs_bit.c \ - xfs_bmap.c \ - xfs_bmap_btree.c \ - xfs_btree.c \ - xfs_buf_item.c \ - xfs_da_btree.c \ - xfs_dir.c \ - xfs_dir2.c \ - xfs_dir2_block.c \ - xfs_dir2_data.c \ - xfs_dir2_leaf.c \ - xfs_dir2_node.c \ - xfs_dir2_sf.c \ - xfs_dir2_trace.c \ - xfs_dir_leaf.c \ - xfs_error.c \ - xfs_extfree_item.c \ - xfs_freebsd_iget.c \ - xfs_fsops.c \ - xfs_ialloc.c \ - xfs_ialloc_btree.c \ - xfs_inode.c \ - xfs_inode_item.c \ - xfs_iocore.c \ - xfs_itable.c \ - xfs_dfrag.c \ - xfs_log.c \ - xfs_log_recover.c \ - xfs_mount.c \ - xfs_rename.c \ - xfs_trans.c \ - xfs_trans_ail.c \ - xfs_trans_buf.c \ - xfs_trans_extfree.c \ - xfs_trans_inode.c \ - xfs_trans_item.c \ - xfs_utils.c \ - xfs_vfsops.c \ - xfs_vnodeops.c \ - xfs_rw.c \ - xfs_iget.c \ - xfs_attr_leaf.c \ - xfs_attr.c \ - xfs_dmops.c \ - xfs_qmops.c \ - xfs_mountops.c \ - xfs_vnops.c \ - xfs_frw.c \ - xfs_iomap.c \ - xfs_buf.c \ - xfs_globals.c \ - xfs_dmistubs.c \ - xfs_behavior.c \ - xfs_super.c \ - xfs_stats.c \ - xfs_sysctl.c \ - xfs_vfs.c \ - xfs_vnode.c \ - xfs_fs_subr.c \ - xfs_ioctl.c \ - debug.c \ - ktrace.c \ - mrlock.c \ - uuid.c \ - kmem.c \ - kdb.c - -SRCS+= opt_ddb.h - -.include - -CFLAGS+= -I${.CURDIR}/../../gnu/fs/xfs/FreeBSD \ - -I${.CURDIR}/../../gnu/fs/xfs/FreeBSD/support \ - -I${.CURDIR}/../../gnu/fs/xfs - -CWARNFLAGS.xfs_dir2_block.c= ${NO_WARRAY_BOUNDS} -CWARNFLAGS.xfs_dir2_sf.c= ${NO_WARRAY_BOUNDS} -CWARNFLAGS+= ${CWARNFLAGS.${.IMPSRC:T}} From 4495286fb2e4f152780992541ee09b377354f4dd Mon Sep 17 00:00:00 2001 From: Marius Strobl Date: Sat, 2 Mar 2013 15:54:02 +0000 Subject: [PATCH 0537/1476] - Complete r231621 by also blacklisting the bridge used by VMware for PCIe devices. While at it, update the comment now that we know that MSI-X doesn't work with ESXi 5.1 for Intel 82576 either and the underlying issue is a bug in the MSI-X allocation code of the hypervisor. Reported by: Harald Schmalzbauer - Make the nomatch table const. MFC after: 1 week --- sys/dev/pci/pci.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index 649a494bf4d..79d5e570096 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -234,10 +234,11 @@ static const struct pci_quirk pci_quirks[] = { { 0x74501022, PCI_QUIRK_DISABLE_MSI, 0, 0 }, /* - * MSI-X doesn't work with at least LSI SAS1068E passed through by - * VMware. + * MSI-X allocation doesn't work properly for devices passed through + * by VMware up to at least ESXi 5.1. */ - { 0x079015ad, PCI_QUIRK_DISABLE_MSI, 0, 0 }, + { 0x079015ad, PCI_QUIRK_DISABLE_MSI, 0, 0 }, /* PCI/PCI-X */ + { 0x07a015ad, PCI_QUIRK_DISABLE_MSI, 0, 0 }, /* PCIe */ /* * Some virtualization environments emulate an older chipset @@ -3643,11 +3644,11 @@ pci_print_child(device_t dev, device_t child) return (retval); } -static struct +static const struct { - int class; - int subclass; - char *desc; + int class; + int subclass; + const char *desc; } pci_nomatch_tab[] = { {PCIC_OLD, -1, "old"}, {PCIC_OLD, PCIS_OLD_NONVGA, "non-VGA display device"}, @@ -3739,8 +3740,9 @@ static struct void pci_probe_nomatch(device_t dev, device_t child) { - int i; - char *cp, *scp, *device; + int i; + const char *cp, *scp; + char *device; /* * Look for a listing for this device in a loaded device database. @@ -3773,7 +3775,6 @@ pci_probe_nomatch(device_t dev, device_t child) printf(" at device %d.%d (no driver attached)\n", pci_get_slot(child), pci_get_function(child)); pci_cfg_save(child, device_get_ivars(child), 1); - return; } /* From f51fb785336a7b05e5382efd86358ac0c80f5a5d Mon Sep 17 00:00:00 2001 From: Attilio Rao Date: Sat, 2 Mar 2013 16:30:18 +0000 Subject: [PATCH 0538/1476] Garbage collect CODAFS bits which are now completely disconnected from the tree since few months. This patch is not targeted for MFC. --- ObsoleteFiles.inc | 2 + share/man/man4/coda.4 | 82 -- sys/fs/coda/README | 62 -- sys/fs/coda/TODO | 16 - sys/fs/coda/cnode.h | 206 ----- sys/fs/coda/coda.h | 838 ----------------- sys/fs/coda/coda_fbsd.c | 148 --- sys/fs/coda/coda_io.h | 73 -- sys/fs/coda/coda_opstats.h | 130 --- sys/fs/coda/coda_pioctl.h | 69 -- sys/fs/coda/coda_psdev.c | 675 -------------- sys/fs/coda/coda_psdev.h | 46 - sys/fs/coda/coda_subr.c | 628 ------------- sys/fs/coda/coda_subr.h | 49 - sys/fs/coda/coda_venus.c | 705 --------------- sys/fs/coda/coda_venus.h | 83 -- sys/fs/coda/coda_vfsops.c | 446 --------- sys/fs/coda/coda_vfsops.h | 60 -- sys/fs/coda/coda_vnops.c | 1738 ------------------------------------ sys/fs/coda/coda_vnops.h | 84 -- sys/modules/coda/Makefile | 10 - sys/modules/coda5/Makefile | 13 - 22 files changed, 2 insertions(+), 6161 deletions(-) delete mode 100644 share/man/man4/coda.4 delete mode 100644 sys/fs/coda/README delete mode 100644 sys/fs/coda/TODO delete mode 100644 sys/fs/coda/cnode.h delete mode 100644 sys/fs/coda/coda.h delete mode 100644 sys/fs/coda/coda_fbsd.c delete mode 100644 sys/fs/coda/coda_io.h delete mode 100644 sys/fs/coda/coda_opstats.h delete mode 100644 sys/fs/coda/coda_pioctl.h delete mode 100644 sys/fs/coda/coda_psdev.c delete mode 100644 sys/fs/coda/coda_psdev.h delete mode 100644 sys/fs/coda/coda_subr.c delete mode 100644 sys/fs/coda/coda_subr.h delete mode 100644 sys/fs/coda/coda_venus.c delete mode 100644 sys/fs/coda/coda_venus.h delete mode 100644 sys/fs/coda/coda_vfsops.c delete mode 100644 sys/fs/coda/coda_vfsops.h delete mode 100644 sys/fs/coda/coda_vnops.c delete mode 100644 sys/fs/coda/coda_vnops.h delete mode 100644 sys/modules/coda/Makefile delete mode 100644 sys/modules/coda5/Makefile diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index 93d50fe9498..d42b2dc0233 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -38,6 +38,8 @@ # xargs -n1 | sort | uniq -d; # done +# 20130302: CODAFS support removed +OLD_FILES+=usr/share/man/man4/coda.4.gz # 20130302: XFS support removed OLD_FILES+=usr/share/man/man5/xfs.5.gz # 20130116: removed long unused directories for .1aout section manpages diff --git a/share/man/man4/coda.4 b/share/man/man4/coda.4 deleted file mode 100644 index e1799ef419a..00000000000 --- a/share/man/man4/coda.4 +++ /dev/null @@ -1,82 +0,0 @@ -.\" Copyright (c) 2008 Robert N. M. Watson -.\" 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 AUTHORS 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 AUTHORS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" $FreeBSD$ -.\" -.Dd January 21, 2008 -.Dt CODA 4 -.Os -.Sh NAME -.Nm coda -.Nd Coda Distributed File System -.Sh SYNOPSIS -To compile this driver into the kernel, -place the following lines in your -kernel configuration file: -.Bd -ragged -offset indent -.Cd "options CODA" -.Ed -.Pp -Alternatively, to load the driver as a -module at boot time, place the following line in -.Xr loader.conf 5 : -.Bd -literal -offset indent -coda_load="YES" -.Ed -.Pp -To load as a kernel loadable module after boot: -.Pp -.Dl "kldload coda" -.Sh DESCRIPTION -The -.Nm -kernel module allows the experimental, third-party Coda distributed file -system client to be used with -.Fx . -The module allows the userspace Coda client daemon, Venus, to present the -Coda distributed file system namespace via the local -.Pa /coda -file system mountpoint via the -.Pa /dev/cfs0 -special device. -.Pp -To use Coda, the Coda client software package must also be installed; more -information on Coda may be found in the Coda documentation distributed with -that package. -.Sh SEE ALSO -.Xr loader.conf 5 , -.Xr kldload 8 -.Sh HISTORY -Support for -.Nm -first appeared in -.Fx 3.0 . -.Sh AUTHORS -This manual page was written by -.An Robert Watson Aq rwatson@FreeBSD.org . -.Sh BUGS -The -Coda distributed file system is considered experimental, and production -deployment should occur only after careful consideration of the risks of -deploying experimental software. diff --git a/sys/fs/coda/README b/sys/fs/coda/README deleted file mode 100644 index 19de799c0ea..00000000000 --- a/sys/fs/coda/README +++ /dev/null @@ -1,62 +0,0 @@ -$FreeBSD$ - - Announcing the Availability of the - Coda Distributed - Filesystem - for - BSD Unix Systems - - Coda is a distributed filesystem like NFS and AFS. It is -freely available, like NFS. But it functions much like AFS in being a -"stateful" filesystem. Coda and AFS cache files on your local -machine to improve performance. But Coda goes a step further than AFS -by letting you access the cached files when there is no available -network, viz. disconnected laptops and network outages. In Coda, both -the client and server are outside the kernel which makes them easier -to experiment with. - -To get more information on Coda, I would like to refer people to - http://www.coda.cs.cmu.edu -There is a wealth of documents, papers, and theses there. There is -also a good introduction to the Coda File System in - http://www.coda.cs.cmu.edu/ljpaper/lj.html - -Coda was originally developed as an academic prototype/testbed. It is -being polished and rewritten where necessary. Coda is a work in -progress and does have bugs. It is, though, very usable. Our -interest is in making Coda available to as many people as possible and -to have Coda evolve and flourish. - -The bulk of the Coda filesystem code supports the Coda client -program, the Coda server program and the utilities needed by both. -All these programs are unix programs and can run equally well on any -Unix platform. Our main development thrust is improving these -programs. There is a small part of Coda that deals with the kernel to -filesystem interface. This code is OS specific (but should not be -platform specific). - -Coda is currently available for several OS's and platforms: - Freebsd-2.2.5: i386 - Freebsd-2.2.6: i386 - Freebsd -current: i386 - linux 2.0: i386 & sparc - linux 2.1: i386 & sparc - NetBSD 1.3: i386 - NetBSD -current: i386 -The relevant sources, binaries, and docs can be found in - ftp://ftp.coda.cs.cmu.edu/pub/coda/ - -We intend to come out with new Coda releases often, not daily. We -don't want to slight any OS/platform not mentioned above. We are just -limited in our resources as to what we can support internally. We -will be happy to integrate OpenBSD support as well as other OS -support. Also, adding platform support should be relatively easy and -we can discuss this. The only difficulty is that Coda has a light weight -process package. It does some manipulations in assembler which would -have to be redone for a different platform. - -There are several mailing lists @coda.cs.cmu.edu that discuss coda: -coda-announce and linux-coda. We are going to revise linux-coda to be -OS neutral, since it is mainly Coda we want to discuss. We appreciate -comments, feedback, bug reports, bug fixes, enhancements, etc. - diff --git a/sys/fs/coda/TODO b/sys/fs/coda/TODO deleted file mode 100644 index a0a618a7371..00000000000 --- a/sys/fs/coda/TODO +++ /dev/null @@ -1,16 +0,0 @@ -OOPS: - FreeBSD does not fsync!!! - -Near term: - Fix bug in executing/mapping new files. - cfs_mount bug: interaction with cfs_inactive no cfs_unsave. - vref/vn_lock == vget except no VXWANT which may be on. - Review locks: vn_lock/VOP_UNLOCK/lockmgr ... - -Medium term: - Add missing VFS methods. - Do performance profile. - Tune hash algorithm used in cfs_subr. - Make MPSAFE - -$FreeBSD$ diff --git a/sys/fs/coda/cnode.h b/sys/fs/coda/cnode.h deleted file mode 100644 index 27531a4f6b2..00000000000 --- a/sys/fs/coda/cnode.h +++ /dev/null @@ -1,206 +0,0 @@ -/*- - * - * Coda: an Experimental Distributed File System - * Release 3.1 - * - * Copyright (c) 1987-1998 Carnegie Mellon University - * All Rights Reserved - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation, and - * that credit is given to Carnegie Mellon University in all documents - * and publicity pertaining to direct or indirect use of this code or its - * derivatives. - * - * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, - * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS - * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON - * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER - * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF - * ANY DERIVATIVE WORK. - * - * Carnegie Mellon encourages users of this software to return any - * improvements or extensions that they make, and to grant Carnegie - * Mellon the rights to redistribute these changes without encumbrance. - * - * @(#) src/sys/coda/cnode.h,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ - * $FreeBSD$ - * - */ - -/*- - * Mach Operating System - * Copyright (c) 1990 Carnegie-Mellon University - * Copyright (c) 1989 Carnegie-Mellon University - * All rights reserved. The CMU software License Agreement specifies - * the terms and conditions for use and redistribution. - */ - -/* - * This code was written for the Coda filesystem at Carnegie Mellon University. - * Contributers include David Steere, James Kistler, and M. Satyanarayanan. - */ - -#ifndef _CNODE_H_ -#define _CNODE_H_ - -#include -#include - -MALLOC_DECLARE(M_CODA); - -/* - * Cnode lookup stuff. - * - * NOTE: CODA_CACHESIZE must be a power of 2 for cfshash to work! - */ -#define CODA_CACHESIZE 512 - -#define CODA_ALLOC(ptr, cast, size) do { \ - ptr = (cast)malloc((unsigned long) size, M_CODA, M_WAITOK); \ - if (ptr == NULL) \ - panic("kernel malloc returns 0 at %s:%d\n", __FILE__, \ - __LINE__); \ -} while (0) - -#define CODA_FREE(ptr, size) free((ptr), M_CODA) - -/* - * Used to select debugging statements throughout the cfs code. - */ -extern int codadebug; -extern int coda_printf_delay; -extern int coda_vnop_print_entry; -extern int coda_psdev_print_entry; -extern int coda_vfsop_print_entry; - -#define CODADBGMSK(N) (1 << N) - -#define CODADEBUG(N, STMT) do { \ - if (codadebug & CODADBGMSK(N)) { \ - STMT \ - } \ -} while (0) - -#define myprintf(args) do { \ - if (coda_printf_delay) \ - DELAY(coda_printf_delay); \ - printf args ; \ -} while (0) - -struct cnode { - struct vnode *c_vnode; - u_short c_flags; /* flags (see below) */ - struct CodaFid c_fid; /* file handle */ - struct vnode *c_ovp; /* open vnode pointer */ - u_short c_ocount; /* count of openers */ - u_short c_owrite; /* count of open for write */ - struct vattr c_vattr; /* attributes */ - char *c_symlink; /* pointer to symbolic link */ - u_short c_symlen; /* length of symbolic link */ - uid_t c_cached_uid; /* cached uid */ - accmode_t c_cached_mode; /* cached access mode */ - struct cnode *c_next; /* links if on FreeBSD machine */ -}; -#define VTOC(vp) ((struct cnode *)(vp)->v_data) -#define CTOV(cp) ((struct vnode *)((cp)->c_vnode)) - -/* flags */ -#define C_VATTR 0x01 /* Validity of vattr in the cnode */ -#define C_SYMLINK 0x02 /* Validity of symlink pointer in the Code */ -#define C_ACCCACHE 0x04 /* Validity of access cache */ -#define C_WANTED 0x08 /* Set if lock wanted */ -#define C_LOCKED 0x10 /* Set if lock held */ -#define C_UNMOUNTING 0X20 /* Set if unmounting */ -#define C_PURGING 0x40 /* Set if purging a fid */ - -#define VALID_VATTR(cp) ((cp->c_flags) & C_VATTR) -#define VALID_SYMLINK(cp) ((cp->c_flags) & C_SYMLINK) -#define VALID_ACCCACHE(cp) ((cp->c_flags) & C_ACCCACHE) -#define IS_UNMOUNTING(cp) ((cp)->c_flags & C_UNMOUNTING) - -struct vcomm { - u_long vc_seq; - struct selinfo vc_selproc; - TAILQ_HEAD(, vmsg) vc_requests; - TAILQ_HEAD(, vmsg) vc_replies; - int vc_open; -}; - -#define VC_OPEN(vcp) ((vcp)->vc_open == 1) -#define MARK_VC_CLOSED(vcp) (vcp)->vc_open = 0 -#define MARK_VC_OPEN(vcp) (vcp)->vc_open = 1 - -struct coda_clstat { - int ncalls; /* client requests */ - int nbadcalls; /* upcall failures */ - int reqs[CODA_NCALLS]; /* count of each request */ -}; -extern struct coda_clstat coda_clstat; - -/* - * CODA structure to hold mount/filesystem information. - */ -struct coda_mntinfo { - struct vnode *mi_rootvp; - struct mount *mi_vfsp; - struct vcomm mi_vcomm; - struct cdev *dev; - int mi_started; - LIST_ENTRY(coda_mntinfo) mi_list; -}; -struct coda_mntinfo *dev2coda_mntinfo(struct cdev *dev); - -/* - * vfs pointer to mount info. - */ -#define vftomi(vfsp) ((struct coda_mntinfo *)(vfsp->mnt_data)) -#define CODA_MOUNTED(vfsp) (vftomi((vfsp)) != NULL) - -/* - * vnode pointer to mount info. - */ -#define vtomi(vp) ((struct coda_mntinfo *)(vp->v_mount->mnt_data)) - -/* - * Used for identifying usage of "Control" object. - */ -extern struct vnode *coda_ctlvp; -#define IS_CTL_VP(vp) ((vp) == coda_ctlvp) -#define IS_CTL_NAME(vp, name, l) ((l == CODA_CONTROLLEN) \ - && ((vp) == vtomi((vp))->mi_rootvp) && \ - strncmp(name, CODA_CONTROL, l) == 0) - -/* - * An enum to tell us whether something that will remove a reference to a - * cnode was a downcall or not. - */ -enum dc_status { - IS_DOWNCALL = 6, - NOT_DOWNCALL = 7 -}; - -/* cfs_psdev.h */ -int coda_call(struct coda_mntinfo *mntinfo, int inSize, int *outSize, - caddr_t buffer); - -extern int coda_kernel_version; - -/* cfs_subr.h */ -int handleDownCall(struct coda_mntinfo *mnt, int opcode, - union outputArgs *out); -void coda_unmounting(struct mount *whoIam); -int coda_vmflush(struct cnode *cp); - -/* cfs_vnodeops.h */ -struct cnode *make_coda_node(struct CodaFid *fid, struct mount *vfsp, - short type); -int coda_vnodeopstats_init(void); - -/* sigh */ -#define CODA_RDWR ((u_long) 31) - -#endif /* _CNODE_H_ */ diff --git a/sys/fs/coda/coda.h b/sys/fs/coda/coda.h deleted file mode 100644 index 2cfb71211c3..00000000000 --- a/sys/fs/coda/coda.h +++ /dev/null @@ -1,838 +0,0 @@ -/*- - * - * Coda: an Experimental Distributed File System - * Release 3.1 - * - * Copyright (c) 1987-1998 Carnegie Mellon University - * All Rights Reserved - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation, and - * that credit is given to Carnegie Mellon University in all documents - * and publicity pertaining to direct or indirect use of this code or its - * derivatives. - * - * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, - * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS - * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON - * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER - * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF - * ANY DERIVATIVE WORK. - * - * Carnegie Mellon encourages users of this software to return any - * improvements or extensions that they make, and to grant Carnegie - * Mellon the rights to redistribute these changes without encumbrance. - * - * @(#) src/sys/coda/coda.h,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ - * $FreeBSD$ - * - */ - - -/* - * - * Based on cfs.h from Mach, but revamped for increased simplicity. - * Linux modifications by Peter Braam, Aug 1996 - */ - -#ifndef _CODA_HEADER_ -#define _CODA_HEADER_ - -#ifdef _KERNEL -#include "opt_coda.h" /* for CODA_COMPAT_5 option */ -#endif - -/* Avoid CODA_COMPAT_5 redefinition in coda5 module */ -#if defined (CODA5_MODULE) && !defined(CODA_COMPAT_5) -#define CODA_COMPAT_5 -#endif - -/* Catch new _KERNEL defn for NetBSD */ -#ifdef __NetBSD__ -#include -#endif - -#ifndef CODA_MAXSYMLINKS -#define CODA_MAXSYMLINKS 10 -#endif - -#if defined(DJGPP) || defined(__CYGWIN32__) -#ifdef _KERNEL -typedef unsigned long u_long; -typedef unsigned int u_int; -typedef unsigned short u_short; -typedef u_long ino_t; -typedef u_long struct cdev *; -typedef void * caddr_t; -#ifdef DOS -typedef unsigned __int64 u_quad_t; -#else -typedef unsigned long long u_quad_t; -#endif - -#define inline - -struct timespec { - long ts_sec; - long ts_nsec; -}; -#else /* DJGPP but not _KERNEL */ -#include -#include -typedef unsigned long long u_quad_t; -#endif /* !_KERNEL */ -#endif /* !DJGPP */ - - -#if defined(__linux__) -#define cdev_t u_quad_t -#if !defined(_UQUAD_T_) && (!defined(__GLIBC__) || __GLIBC__ < 2) -#define _UQUAD_T_ 1 -typedef unsigned long long u_quad_t; -#endif -#else -#define cdev_t dev_t -#endif - -#ifdef __CYGWIN32__ -typedef unsigned char u_int8_t; -struct timespec { - time_t tv_sec; /* seconds */ - long tv_nsec; /* nanoseconds */ -}; -#endif - -typedef u_int32_t cuid_t; -typedef u_int32_t cgid_t; - -/* - * Cfs constants - */ -#define CODA_MAXNAMLEN 255 -#define CODA_MAXPATHLEN 1024 -#define CODA_MAXSYMLINK 10 - -/* these are Coda's version of O_RDONLY etc combinations - * to deal with VFS open modes - */ -#define C_O_READ 0x001 -#define C_O_WRITE 0x002 -#define C_O_TRUNC 0x010 -#define C_O_EXCL 0x100 -#define C_O_CREAT 0x200 - -/* these are to find mode bits in Venus */ -#define C_M_READ 00400 -#define C_M_WRITE 00200 - -/* for access Venus will use */ -#define C_A_C_OK 8 /* Test for writing upon create. */ -#define C_A_R_OK 4 /* Test for read permission. */ -#define C_A_W_OK 2 /* Test for write permission. */ -#define C_A_X_OK 1 /* Test for execute permission. */ -#define C_A_F_OK 0 /* Test for existence. */ - - -#ifndef _VENUS_DIRENT_T_ -#define _VENUS_DIRENT_T_ 1 -struct venus_dirent { - unsigned int d_fileno; /* file number of entry */ - unsigned short d_reclen; /* length of this record */ - unsigned char d_type; /* file type, see below */ - unsigned char d_namlen; /* length of string in d_name */ - char d_name[CODA_MAXNAMLEN + 1];/* name must be no longer than this */ -}; -#undef DIRSIZ -#define DIRSIZ(dp) ((sizeof (struct venus_dirent) - (CODA_MAXNAMLEN+1)) + \ - (((dp)->d_namlen+1 + 3) &~ 3)) - -/* - * File types - */ -#define CDT_UNKNOWN 0 -#define CDT_FIFO 1 -#define CDT_CHR 2 -#define CDT_DIR 4 -#define CDT_BLK 6 -#define CDT_REG 8 -#define CDT_LNK 10 -#define CDT_SOCK 12 -#define CDT_WHT 14 - -/* - * Convert between stat structure types and directory types. - */ -#define IFTOCDT(mode) (((mode) & 0170000) >> 12) -#define CDTTOIF(dirtype) ((dirtype) << 12) - -#endif - -#ifdef CODA_COMPAT_5 - -struct CodaFid { - u_long Volume; - u_long Vnode; - u_long Unique; -}; - -static __inline__ ino_t coda_f2i(struct CodaFid *fid) -{ - if (!fid) return 0; - return (fid->Unique + (fid->Vnode<<10) + (fid->Volume<<20)); -} - -static __inline__ char * coda_f2s(struct CodaFid *fid) -{ - static char fid_str [35]; - snprintf (fid_str, 35, "[%lx.%lx.%lx]", fid->Volume, - fid->Vnode, fid->Unique); - return fid_str; -} - -static __inline__ int coda_fid_eq (struct CodaFid *fid1, struct CodaFid *fid2) -{ - return (fid1->Volume == fid2->Volume && - fid1->Vnode == fid2->Vnode && - fid1->Unique == fid2->Unique); -} - -struct coda_cred { - u_int32_t cr_uid, cr_euid, cr_suid, cr_fsuid; /* Real, efftve, set, fs uid*/ - u_int32_t cr_groupid, cr_egid, cr_sgid, cr_fsgid; /* same for groups */ -}; - -#else /* CODA_COMPAT_5 */ - -struct CodaFid { - u_int32_t opaque[4]; -}; - -static __inline__ ino_t coda_f2i(struct CodaFid *fid) -{ - if ( ! fid ) - return 0; - return (fid->opaque[3] ^ (fid->opaque[2]<<10) ^ (fid->opaque[1]<<20) ^ fid->opaque[0]); -} - -static __inline__ char * coda_f2s(struct CodaFid *fid) - { - static char fid_str [35]; - snprintf (fid_str, 35, "[%x.%x.%x.%x]", fid->opaque[0], - fid->opaque[1], fid->opaque[2], fid->opaque[3]); - return fid_str; - } - -static __inline__ int coda_fid_eq (struct CodaFid *fid1, struct CodaFid *fid2) -{ - return (fid1->opaque[0] == fid2->opaque[0] && - fid1->opaque[1] == fid2->opaque[1] && - fid1->opaque[2] == fid2->opaque[2] && - fid1->opaque[3] == fid2->opaque[3]); -} - -#endif /* CODA_COMPAT_5 */ - -#ifndef _VENUS_VATTR_T_ -#define _VENUS_VATTR_T_ -/* - * Vnode types. VNON means no type. - */ -enum coda_vtype { C_VNON, C_VREG, C_VDIR, C_VBLK, C_VCHR, C_VLNK, C_VSOCK, C_VFIFO, C_VBAD }; - -struct coda_vattr { - long va_type; /* vnode type (for create) */ - u_short va_mode; /* files access mode and type */ - short va_nlink; /* number of references to file */ - cuid_t va_uid; /* owner user id */ - cgid_t va_gid; /* owner group id */ - long va_fileid; /* file id */ - u_quad_t va_size; /* file size in bytes */ - long va_blocksize; /* blocksize preferred for i/o */ - struct timespec va_atime; /* time of last access */ - struct timespec va_mtime; /* time of last modification */ - struct timespec va_ctime; /* time file changed */ - u_long va_gen; /* generation number of file */ - u_long va_flags; /* flags defined for file */ - cdev_t va_rdev; /* device special file represents */ - u_quad_t va_bytes; /* bytes of disk space held by file */ - u_quad_t va_filerev; /* file modification number */ -}; - -#endif - -/* structure used by CODA_STATFS for getting cache information from venus */ -struct coda_statfs { - int32_t f_blocks; - int32_t f_bfree; - int32_t f_bavail; - int32_t f_files; - int32_t f_ffree; -}; - -/* - * Kernel <--> Venus communications. - */ - -#define CODA_ROOT 2 -#define CODA_OPEN_BY_FD 3 -#define CODA_OPEN 4 -#define CODA_CLOSE 5 -#define CODA_IOCTL 6 -#define CODA_GETATTR 7 -#define CODA_SETATTR 8 -#define CODA_ACCESS 9 -#define CODA_LOOKUP 10 -#define CODA_CREATE 11 -#define CODA_REMOVE 12 -#define CODA_LINK 13 -#define CODA_RENAME 14 -#define CODA_MKDIR 15 -#define CODA_RMDIR 16 -#define CODA_READDIR 17 -#define CODA_SYMLINK 18 -#define CODA_READLINK 19 -#define CODA_FSYNC 20 -#define CODA_INACTIVE 21 -#define CODA_VGET 22 -#define CODA_SIGNAL 23 -#define CODA_REPLACE 24 -#define CODA_FLUSH 25 -#define CODA_PURGEUSER 26 -#define CODA_ZAPFILE 27 -#define CODA_ZAPDIR 28 -#define CODA_PURGEFID 30 -#define CODA_OPEN_BY_PATH 31 -#define CODA_RESOLVE 32 -#define CODA_REINTEGRATE 33 -#define CODA_STATFS 34 -#define CODA_NCALLS 35 - -#define DOWNCALL(opcode) (opcode >= CODA_REPLACE && opcode <= CODA_PURGEFID) - -#define VC_MAXDATASIZE 8192 -#define VC_MAXMSGSIZE sizeof(union inputArgs)+sizeof(union outputArgs) +\ - VC_MAXDATASIZE - -#define CIOC_KERNEL_VERSION _IOWR('c', 10, int) -#if 0 - /* don't care about kernel version number */ -#define CODA_KERNEL_VERSION 0 - /* The old venus 4.6 compatible interface */ -#define CODA_KERNEL_VERSION 1 -#endif /* realms/cells */ -#ifdef CODA_COMPAT_5 - /* venus_lookup gets an extra parameter to aid windows.*/ -#define CODA_KERNEL_VERSION 2 -#else - /* 128-bit fids for realms */ -#define CODA_KERNEL_VERSION 3 -#endif - -/* - * Venus <-> Coda RPC arguments - */ -#ifdef CODA_COMPAT_5 -struct coda_in_hdr { - unsigned long opcode; - unsigned long unique; /* Keep multiple outstanding msgs distinct */ - u_short pid; /* Common to all */ - u_short pgid; /* Common to all */ - u_short sid; /* Common to all */ - struct coda_cred cred; /* Common to all */ -}; -#else -struct coda_in_hdr { - u_int32_t opcode; - u_int32_t unique; /* Keep multiple outstanding msgs distinct */ - pid_t pid; - pid_t pgid; - cuid_t uid; -}; -#endif - -/* Really important that opcode and unique are 1st two fields! */ -struct coda_out_hdr { - u_int32_t opcode; - u_int32_t unique; - u_int32_t result; -}; - -/* coda_root: NO_IN */ -struct coda_root_out { - struct coda_out_hdr oh; - struct CodaFid Fid; -}; - -struct coda_root_in { - struct coda_in_hdr in; -}; - -/* coda_sync: */ -/* Nothing needed for coda_sync */ - -/* coda_open: */ -struct coda_open_in { - struct coda_in_hdr ih; - struct CodaFid Fid; - int flags; -}; - -struct coda_open_out { - struct coda_out_hdr oh; - cdev_t dev; - ino_t inode; -}; - - -/* coda_close: */ -struct coda_close_in { - struct coda_in_hdr ih; - struct CodaFid Fid; - int flags; -}; - -struct coda_close_out { - struct coda_out_hdr out; -}; - -/* coda_ioctl: */ -struct coda_ioctl_in { - struct coda_in_hdr ih; - struct CodaFid Fid; - int cmd; - int len; - int rwflag; - char *data; /* Place holder for data. */ -}; - -struct coda_ioctl_out { - struct coda_out_hdr oh; - int len; - caddr_t data; /* Place holder for data. */ -}; - - -/* coda_getattr: */ -struct coda_getattr_in { - struct coda_in_hdr ih; - struct CodaFid Fid; -}; - -struct coda_getattr_out { - struct coda_out_hdr oh; - struct coda_vattr attr; -}; - - -/* coda_setattr: NO_OUT */ -struct coda_setattr_in { - struct coda_in_hdr ih; - struct CodaFid Fid; - struct coda_vattr attr; -}; - -struct coda_setattr_out { - struct coda_out_hdr out; -}; - -/* coda_access: NO_OUT */ -struct coda_access_in { - struct coda_in_hdr ih; - struct CodaFid Fid; - int flags; -}; - -struct coda_access_out { - struct coda_out_hdr out; -}; - - -/* lookup flags */ -#define CLU_CASE_SENSITIVE 0x01 -#define CLU_CASE_INSENSITIVE 0x02 - -/* coda_lookup: */ -struct coda_lookup_in { - struct coda_in_hdr ih; - struct CodaFid Fid; - int name; /* Place holder for data. */ - int flags; -}; - -struct coda_lookup_out { - struct coda_out_hdr oh; - struct CodaFid Fid; - int vtype; -}; - - -/* coda_create: */ -struct coda_create_in { - struct coda_in_hdr ih; - struct CodaFid Fid; - struct coda_vattr attr; - int excl; - int mode; - int name; /* Place holder for data. */ -}; - -struct coda_create_out { - struct coda_out_hdr oh; - struct CodaFid Fid; - struct coda_vattr attr; -}; - - -/* coda_remove: NO_OUT */ -struct coda_remove_in { - struct coda_in_hdr ih; - struct CodaFid Fid; - int name; /* Place holder for data. */ -}; - -struct coda_remove_out { - struct coda_out_hdr out; -}; - -/* coda_link: NO_OUT */ -struct coda_link_in { - struct coda_in_hdr ih; - struct CodaFid sourceFid; /* cnode to link *to* */ - struct CodaFid destFid; /* Directory in which to place link */ - int tname; /* Place holder for data. */ -}; - -struct coda_link_out { - struct coda_out_hdr out; -}; - - -/* coda_rename: NO_OUT */ -struct coda_rename_in { - struct coda_in_hdr ih; - struct CodaFid sourceFid; - int srcname; - struct CodaFid destFid; - int destname; -}; - -struct coda_rename_out { - struct coda_out_hdr out; -}; - -/* coda_mkdir: */ -struct coda_mkdir_in { - struct coda_in_hdr ih; - struct CodaFid Fid; - struct coda_vattr attr; - int name; /* Place holder for data. */ -}; - -struct coda_mkdir_out { - struct coda_out_hdr oh; - struct CodaFid Fid; - struct coda_vattr attr; -}; - - -/* coda_rmdir: NO_OUT */ -struct coda_rmdir_in { - struct coda_in_hdr ih; - struct CodaFid Fid; - int name; /* Place holder for data. */ -}; - -struct coda_rmdir_out { - struct coda_out_hdr out; -}; - -/* coda_readdir: */ -struct coda_readdir_in { - struct coda_in_hdr ih; - struct CodaFid Fid; - int count; - int offset; -}; - -struct coda_readdir_out { - struct coda_out_hdr oh; - int size; - caddr_t data; /* Place holder for data. */ -}; - -/* coda_symlink: NO_OUT */ -struct coda_symlink_in { - struct coda_in_hdr ih; - struct CodaFid Fid; /* Directory to put symlink in */ - int srcname; - struct coda_vattr attr; - int tname; -}; - -struct coda_symlink_out { - struct coda_out_hdr out; -}; - -/* coda_readlink: */ -struct coda_readlink_in { - struct coda_in_hdr ih; - struct CodaFid Fid; -}; - -struct coda_readlink_out { - struct coda_out_hdr oh; - int count; - caddr_t data; /* Place holder for data. */ -}; - - -/* coda_fsync: NO_OUT */ -struct coda_fsync_in { - struct coda_in_hdr ih; - struct CodaFid Fid; -}; - -struct coda_fsync_out { - struct coda_out_hdr out; -}; - -/* coda_inactive: NO_OUT */ -struct coda_inactive_in { - struct coda_in_hdr ih; - struct CodaFid Fid; -}; - -/* coda_vget: */ -struct coda_vget_in { - struct coda_in_hdr ih; - struct CodaFid Fid; -}; - -struct coda_vget_out { - struct coda_out_hdr oh; - struct CodaFid Fid; - int vtype; -}; - - -/* CODA_SIGNAL is out-of-band, doesn't need data. */ -/* CODA_INVALIDATE is a venus->kernel call */ -/* CODA_FLUSH is a venus->kernel call */ - -/* coda_purgeuser: */ -/* CODA_PURGEUSER is a venus->kernel call */ -struct coda_purgeuser_out { - struct coda_out_hdr oh; -#ifdef CODA_COMPAT_5 - struct coda_cred cred; -#else - cuid_t uid; -#endif -}; - -/* coda_zapfile: */ -/* CODA_ZAPFILE is a venus->kernel call */ -struct coda_zapfile_out { - struct coda_out_hdr oh; - struct CodaFid Fid; -}; - -/* coda_zapdir: */ -/* CODA_ZAPDIR is a venus->kernel call */ -struct coda_zapdir_out { - struct coda_out_hdr oh; - struct CodaFid Fid; -}; - -/* coda_zapnode: */ -/* CODA_ZAPVNODE is a venus->kernel call */ -struct coda_zapvnode_out { - struct coda_out_hdr oh; -#ifdef CODA_COMPAT_5 - struct coda_cred cred; -#endif - struct CodaFid Fid; -}; - -/* coda_purgefid: */ -/* CODA_PURGEFID is a venus->kernel call */ -struct coda_purgefid_out { - struct coda_out_hdr oh; - struct CodaFid Fid; -}; - -/* coda_replace: */ -/* CODA_REPLACE is a venus->kernel call */ -struct coda_replace_out { /* coda_replace is a venus->kernel call */ - struct coda_out_hdr oh; - struct CodaFid NewFid; - struct CodaFid OldFid; -}; - -/* coda_open_by_fd: */ -struct coda_open_by_fd_in { - struct coda_in_hdr ih; - struct CodaFid Fid; - int flags; -}; - -struct coda_open_by_fd_out { - struct coda_out_hdr oh; - int fd; -#ifdef _KERNEL - /* not passed from userspace but used in-kernel only */ - struct vnode *vp; -#endif -}; - -/* coda_open_by_path: */ -struct coda_open_by_path_in { - struct coda_in_hdr ih; - struct CodaFid Fid; - int flags; -}; - -struct coda_open_by_path_out { - struct coda_out_hdr oh; - int path; -}; - -/* coda_statfs: NO_IN */ -struct coda_statfs_in { - struct coda_in_hdr ih; -}; - -struct coda_statfs_out { - struct coda_out_hdr oh; - struct coda_statfs stat; -}; - -/* - * Occasionally, we don't cache the fid returned by CODA_LOOKUP. - * For instance, if the fid is inconsistent. - * This case is handled by setting the top bit of the type result parameter. - */ -#define CODA_NOCACHE 0x80000000 - -union inputArgs { - struct coda_in_hdr ih; /* NB: every struct below begins with an ih */ - struct coda_open_in coda_open; - struct coda_close_in coda_close; - struct coda_ioctl_in coda_ioctl; - struct coda_getattr_in coda_getattr; - struct coda_setattr_in coda_setattr; - struct coda_access_in coda_access; - struct coda_lookup_in coda_lookup; - struct coda_create_in coda_create; - struct coda_remove_in coda_remove; - struct coda_link_in coda_link; - struct coda_rename_in coda_rename; - struct coda_mkdir_in coda_mkdir; - struct coda_rmdir_in coda_rmdir; - struct coda_readdir_in coda_readdir; - struct coda_symlink_in coda_symlink; - struct coda_readlink_in coda_readlink; - struct coda_fsync_in coda_fsync; - struct coda_vget_in coda_vget; - struct coda_open_by_fd_in coda_open_by_fd; - struct coda_open_by_path_in coda_open_by_path; - struct coda_statfs_in coda_statfs; -}; - -union outputArgs { - struct coda_out_hdr oh; /* NB: every struct below begins with an oh */ - struct coda_root_out coda_root; - struct coda_open_out coda_open; - struct coda_ioctl_out coda_ioctl; - struct coda_getattr_out coda_getattr; - struct coda_lookup_out coda_lookup; - struct coda_create_out coda_create; - struct coda_mkdir_out coda_mkdir; - struct coda_readdir_out coda_readdir; - struct coda_readlink_out coda_readlink; - struct coda_vget_out coda_vget; - struct coda_purgeuser_out coda_purgeuser; - struct coda_zapfile_out coda_zapfile; - struct coda_zapdir_out coda_zapdir; - struct coda_zapvnode_out coda_zapvnode; - struct coda_purgefid_out coda_purgefid; - struct coda_replace_out coda_replace; - struct coda_open_by_fd_out coda_open_by_fd; - struct coda_open_by_path_out coda_open_by_path; - struct coda_statfs_out coda_statfs; -}; - -union coda_downcalls { - /* CODA_INVALIDATE is a venus->kernel call */ - /* CODA_FLUSH is a venus->kernel call */ - struct coda_purgeuser_out purgeuser; - struct coda_zapfile_out zapfile; - struct coda_zapdir_out zapdir; - struct coda_zapvnode_out zapvnode; - struct coda_purgefid_out purgefid; - struct coda_replace_out replace; -}; - - -/* - * Used for identifying usage of "Control" and pioctls - */ - -#define PIOCPARM_MASK 0x0000ffff -struct ViceIoctl { - caddr_t in, out; /* Data to be transferred in, or out */ - unsigned short in_size; /* Size of input buffer <= 8K */ - unsigned short out_size; /* Maximum size of output buffer, <= 8K */ -}; - -#if defined(__CYGWIN32__) || defined(DJGPP) -struct PioctlData { - unsigned long cmd; - const char *path; - int follow; - struct ViceIoctl vi; -}; -#else -struct PioctlData { - const char *path; - int follow; - struct ViceIoctl vi; -}; -#endif - -#define CODA_CONTROL ".CONTROL" -#define CODA_CONTROLLEN 8 -#define CTL_VOL -1 -#define CTL_VNO -1 -#define CTL_UNI -1 -#define CTL_INO -1 -#define CTL_FILE "/coda/.CONTROL" - -#ifdef CODA_COMPAT_5 -#define CTL_FID { -1, -1, -1 } -#define IS_CTL_FID(fidp) ((fidp)->Volume == -1 &&\ - (fidp)->Vnode == -1 &&\ - (fidp)->Unique == -1) -#define INVAL_FID { 0, 0, 0 } -#else -#define CTL_FID { { -1, -1, -1, -1 } } -#define IS_CTL_FID(fidp) ((fidp)->opaque[1] == CTL_VOL && \ - (fidp)->opaque[2] == CTL_VNO && \ - (fidp)->opaque[3] == CTL_UNI) -#define INVAL_FID { { 0, 0, 0, 0 } } -#endif - -/* Data passed to mount */ - -#define CODA_MOUNT_VERSION 1 - -struct coda_mount_data { - int version; - int fd; /* Opened device */ -}; - -#endif - diff --git a/sys/fs/coda/coda_fbsd.c b/sys/fs/coda/coda_fbsd.c deleted file mode 100644 index 62d085723aa..00000000000 --- a/sys/fs/coda/coda_fbsd.c +++ /dev/null @@ -1,148 +0,0 @@ -/*- - * Coda: an Experimental Distributed File System - * Release 3.1 - * - * Copyright (c) 1987-1998 Carnegie Mellon University - * All Rights Reserved - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation, and - * that credit is given to Carnegie Mellon University in all documents - * and publicity pertaining to direct or indirect use of this code or its - * derivatives. - * - * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, - * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS - * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON - * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER - * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF - * ANY DERIVATIVE WORK. - * - * Carnegie Mellon encourages users of this software to return any - * improvements or extensions that they make, and to grant Carnegie - * Mellon the rights to redistribute these changes without encumbrance. - * - * @(#) src/sys/coda/coda_fbsd.cr,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -static struct cdevsw codadevsw = { - .d_version = D_VERSION, - .d_flags = D_NEEDGIANT, - .d_open = vc_open, - .d_close = vc_close, - .d_read = vc_read, - .d_write = vc_write, - .d_ioctl = vc_ioctl, - .d_poll = vc_poll, - .d_name = "coda", -}; - -static eventhandler_tag clonetag; - -static LIST_HEAD(, coda_mntinfo) coda_mnttbl; - -/* - * For DEVFS, using bpf & tun drivers as examples. - * - * XXX: Why use a cloned interface, aren't we really just interested in - * having a single /dev/cfs0? It's not clear the coda module knows what to - * do with more than one. - */ -static void coda_fbsd_clone(void *arg, struct ucred *cred, char *name, - int namelen, struct cdev **dev); - -static int -codadev_modevent(module_t mod, int type, void *data) -{ - struct coda_mntinfo *mnt; - - switch (type) { - case MOD_LOAD: - LIST_INIT(&coda_mnttbl); - clonetag = EVENTHANDLER_REGISTER(dev_clone, coda_fbsd_clone, - 0, 1000); - break; - - case MOD_UNLOAD: - /* - * XXXRW: At the very least, a busy check should occur here - * to prevent untimely unload. Much more serious collection - * of allocated memory needs to take place; right now we leak - * like a sieve. - */ - EVENTHANDLER_DEREGISTER(dev_clone, clonetag); - while ((mnt = LIST_FIRST(&coda_mnttbl)) != NULL) { - LIST_REMOVE(mnt, mi_list); - destroy_dev(mnt->dev); - free(mnt, M_CODA); - } - break; - - default: - return (EOPNOTSUPP); - } - return (0); -} - -static moduledata_t codadev_mod = { - "codadev", - codadev_modevent, - NULL -}; -DECLARE_MODULE(codadev, codadev_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); - -static void -coda_fbsd_clone(void *arg, struct ucred *cred, char *name, int namelen, - struct cdev **dev) -{ - struct coda_mntinfo *mnt; - int u; - - if (*dev != NULL) - return; - if (dev_stdclone(name, NULL, "cfs", &u) != 1) - return; - *dev = make_dev(&codadevsw, u, UID_ROOT, GID_WHEEL, 0600, - "cfs%d", u); - dev_ref(*dev); - mnt = malloc(sizeof(struct coda_mntinfo), M_CODA, M_WAITOK|M_ZERO); - LIST_INSERT_HEAD(&coda_mnttbl, mnt, mi_list); - mnt->dev = *dev; -} - -struct coda_mntinfo * -dev2coda_mntinfo(struct cdev *dev) -{ - struct coda_mntinfo *mnt; - - LIST_FOREACH(mnt, &coda_mnttbl, mi_list) { - if (mnt->dev == dev) - return (mnt); - } - return (NULL); -} diff --git a/sys/fs/coda/coda_io.h b/sys/fs/coda/coda_io.h deleted file mode 100644 index 6058cf024da..00000000000 --- a/sys/fs/coda/coda_io.h +++ /dev/null @@ -1,73 +0,0 @@ -/*- - * - * Coda: an Experimental Distributed File System - * Release 3.1 - * - * Copyright (c) 1987-1998 Carnegie Mellon University - * All Rights Reserved - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation, and - * that credit is given to Carnegie Mellon University in all documents - * and publicity pertaining to direct or indirect use of this code or its - * derivatives. - * - * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, - * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS - * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON - * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER - * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF - * ANY DERIVATIVE WORK. - * - * Carnegie Mellon encourages users of this software to return any - * improvements or extensions that they make, and to grant Carnegie - * Mellon the rights to redistribute these changes without encumbrance. - * - * @(#) src/sys/coda/coda_io.h,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ - * $FreeBSD$ - * - */ - -/*- - * Mach Operating System - * Copyright (c) 1990 Carnegie-Mellon University - * Copyright (c) 1989 Carnegie-Mellon University - * All rights reserved. The CMU software License Agreement specifies - * the terms and conditions for use and redistribution. - */ - -/* - * This code was written for the Coda filesystem at Carnegie Mellon University. - * Contributers include David Steere, James Kistler, and M. Satyanarayanan. - */ - -#ifndef _CODAIO_H_ -#define _CODAIO_H_ - -/* - * Define ioctl commands for vcioctl, /dev/cfs. - * - * Resize Coda namecache. - */ -#define CODARESIZE _IOW('c', 1, struct coda_resize) - -/* - * Collect statistics. - */ -#define CODASTATS _IO('c', 2) - -/* - * Print cache. - */ -#define CODAPRINT _IO('c', 3) -#define CODATEST _IO('c', 4) - -struct coda_resize { - int hashsize; - int heapsize; -}; - -#endif /* !_CODAIO_H_ */ diff --git a/sys/fs/coda/coda_opstats.h b/sys/fs/coda/coda_opstats.h deleted file mode 100644 index 36805e8c006..00000000000 --- a/sys/fs/coda/coda_opstats.h +++ /dev/null @@ -1,130 +0,0 @@ -/*- - * - * Coda: an Experimental Distributed File System - * Release 3.1 - * - * Copyright (c) 1987-1998 Carnegie Mellon University - * All Rights Reserved - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation, and - * that credit is given to Carnegie Mellon University in all documents - * and publicity pertaining to direct or indirect use of this code or its - * derivatives. - * - * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, - * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS - * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON - * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER - * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF - * ANY DERIVATIVE WORK. - * - * Carnegie Mellon encourages users of this software to return any - * improvements or extensions that they make, and to grant Carnegie - * Mellon the rights to redistribute these changes without encumbrance. - * - * @(#) src/sys/coda/coda_opstats.h,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ - * $FreeBSD$ - * - */ - -#ifndef _CODA_OPSTATS_H_ -#define _CODA_OPSTATS_H_ - -/* - * Operation stats: what the minicache can intercept that *isn't* seen by - * venus. These stats are kept to augment the stats maintained by the - * Volume-Session mechanism. - */ - -/*- - * vfsops: - * mount: not currently bounced to Venus - * umount: nope - * root: only first call, rest is cached. - * statfs: none (bogus) - * sync: none (bogus) - * vget: all - */ -#define CODA_MOUNT_STATS 0 -#define CODA_UMOUNT_STATS 1 -#define CODA_ROOT_STATS 2 -#define CODA_STATFS_STATS 3 -#define CODA_SYNC_STATS 4 -#define CODA_VGET_STATS 5 -#define CODA_VFSOPS_SIZE 6 - -/*- - * vnodeops: - * open: all to venus - * close: all to venus - * rdrw: bogus. Maybe redirected to UFS. - * May call open/close for internal opens/closes - * (Does exec not call open?) - * ioctl: causes a lookupname - * passes through - * select: can't get there from here. - * getattr: can be satsified by cache - * setattr: all go through - * access: can be satisfied by cache - * readlink: can be satisfied by cache - * fsync: passes through - * inactive: passes through - * lookup: can be satisfied by cache - * create: passes through - * remove: passes through - * link: passes through - * rename: passes through - * mkdir: passes through - * rmdir: passes through - * symlink: passes through - * readdir: may be redirected to UFS - * may cause an "internal" open/close - */ -#define CODA_OPEN_STATS 0 -#define CODA_CLOSE_STATS 1 -#define CODA_RDWR_STATS 2 -#define CODA_IOCTL_STATS 3 -#define CODA_SELECT_STATS 4 -#define CODA_GETATTR_STATS 5 -#define CODA_SETATTR_STATS 6 -#define CODA_ACCESS_STATS 7 -#define CODA_READLINK_STATS 8 -#define CODA_FSYNC_STATS 9 -#define CODA_INACTIVE_STATS 10 -#define CODA_LOOKUP_STATS 11 -#define CODA_CREATE_STATS 12 -#define CODA_REMOVE_STATS 13 -#define CODA_LINK_STATS 14 -#define CODA_RENAME_STATS 15 -#define CODA_MKDIR_STATS 16 -#define CODA_RMDIR_STATS 17 -#define CODA_SYMLINK_STATS 18 -#define CODA_READDIR_STATS 19 -#define CODA_VNODEOPS_SIZE 20 - -/* - * I propose the following structres: - */ -struct coda_op_stats { - int opcode; /* vfs opcode */ - long entries; /* number of times call attempted */ - long sat_intrn; /* number of times call satisfied by cache */ - long unsat_intrn; /* number of times call failed in cache, but */ - /* was not bounced to venus proper. */ - long gen_intrn; /* number of times call generated internally */ - /* (do we need that?) */ -}; - -/* - * With each call to the minicache, we'll bump the counters whenver a call is - * satisfied internally (through the cache or through a redirect), and - * whenever an operation is caused internally. Then, we can add the total - * operations caught by the minicache to the world-wide totals, and leave a - * caveat for the specific graphs later. - */ - -#endif /* !_CODA_OPSTATS_H_ */ diff --git a/sys/fs/coda/coda_pioctl.h b/sys/fs/coda/coda_pioctl.h deleted file mode 100644 index 3c9d0c65e0d..00000000000 --- a/sys/fs/coda/coda_pioctl.h +++ /dev/null @@ -1,69 +0,0 @@ -/*- - * - * Coda: an Experimental Distributed File System - * Release 3.1 - * - * Copyright (c) 1987-1998 Carnegie Mellon University - * All Rights Reserved - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation, and - * that credit is given to Carnegie Mellon University in all documents - * and publicity pertaining to direct or indirect use of this code or its - * derivatives. - * - * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, - * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS - * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON - * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER - * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF - * ANY DERIVATIVE WORK. - * - * Carnegie Mellon encourages users of this software to return any - * improvements or extensions that they make, and to grant Carnegie - * Mellon the rights to redistribute these changes without encumbrance. - * - * @(#) src/sys/coda/coda_pioctl.h,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ - * $FreeBSD$ - * - */ - -/*- - * Mach Operating System - * Copyright (c) 1989 Carnegie-Mellon University - * Copyright (c) 1988 Carnegie-Mellon University - * Copyright (c) 1987 Carnegie-Mellon University - * All rights reserved. The CMU software License Agreement specifies - * the terms and conditions for use and redistribution. - */ - -/* - * ITC Remote filesystem - vice ioctl interface module - * - * TODO: Find /usr/local/include/viceioctl.h. - */ - -#ifndef _SYS_PIOCTL_H_ -#define _SYS_PIOCTL_H_ - -/* - * The 2K limits above are a consequence of the size of the kernel buffer - * used to buffer requests from the user to venus--2*MAXPATHLEN. The buffer - * pointers may be null, or the counts may be 0 if there are no input or - * output parameters. - */ -#define _VICEIOCTL(id) ((unsigned int )_IOW('V', id, struct ViceIoctl)) - -/* - * Use this macro to define up to 256 vice ioctl's. These ioctl's all - * potentially have in/out parameters--this depends upon the values in the - * ViceIoctl structure. This structure is itself passed into the kernel by - * the normal ioctl parameter passing mechanism. - */ -#define _VALIDVICEIOCTL(com) (com >= _VICEIOCTL(0) && \ - com <= _VICEIOCTL(255)) - -#endif /* !_SYS_PIOCTL_H_ */ diff --git a/sys/fs/coda/coda_psdev.c b/sys/fs/coda/coda_psdev.c deleted file mode 100644 index e982a2c467e..00000000000 --- a/sys/fs/coda/coda_psdev.c +++ /dev/null @@ -1,675 +0,0 @@ -/*- - * Coda: an Experimental Distributed File System - * Release 3.1 - * - * Copyright (c) 1987-1998 Carnegie Mellon University - * All Rights Reserved - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation, and - * that credit is given to Carnegie Mellon University in all documents - * and publicity pertaining to direct or indirect use of this code or its - * derivatives. - * - * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, - * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS - * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON - * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER - * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF - * ANY DERIVATIVE WORK. - * - * Carnegie Mellon encourages users of this software to return any - * improvements or extensions that they make, and to grant Carnegie - * Mellon the rights to redistribute these changes without encumbrance. - * - * @(#) src/sys/coda/coda_psdev.c,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ - */ -/*- - * Mach Operating System - * Copyright (c) 1989 Carnegie-Mellon University - * All rights reserved. The CMU software License Agreement specifies - * the terms and conditions for use and redistribution. - */ - -/* - * This code was written for the Coda filesystem at Carnegie Mellon - * University. Contributers include David Steere, James Kistler, and - * M. Satyanarayanan. */ - -/* - * These routines define the psuedo device for communication between Coda's - * Venus and Minicache in Mach 2.6. They used to be in cfs_subr.c, but I - * moved them to make it easier to port the Minicache without porting coda. - * -- DCS 10/12/94 - */ - -/* - * These routines are the device entry points for Venus. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include /* must come after sys/malloc.h */ -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -/* - * Variables to determine how Coda sleeps and whether or not it is - * interruptible when it does sleep waiting for Venus. - */ -/* #define CTL_C */ - -#ifdef CTL_C -#include -#endif - -int coda_psdev_print_entry = 0; -static int outstanding_upcalls = 0; -int coda_call_sleep = PZERO - 1; -#ifdef CTL_C -int coda_pcatch = PCATCH; -#else -#endif - -#define ENTRY do { \ - if (coda_psdev_print_entry) \ - myprintf(("Entered %s\n", __func__)); \ -} while (0) - -struct vmsg { - TAILQ_ENTRY(vmsg) vm_chain; - caddr_t vm_data; - u_short vm_flags; - u_short vm_inSize; /* Size is at most 5000 bytes */ - u_short vm_outSize; - u_short vm_opcode; /* Copied from data to save ptr deref */ - int vm_unique; - caddr_t vm_sleep; /* Not used by Mach. */ -}; - -#define VM_READ 1 -#define VM_WRITE 2 -#define VM_INTR 4 /* Unused. */ - -int -vc_open(struct cdev *dev, int flag, int mode, struct thread *td) -{ - struct vcomm *vcp; - struct coda_mntinfo *mnt; - - ENTRY; - mnt = dev2coda_mntinfo(dev); - KASSERT(mnt, ("Coda: tried to open uninitialized cfs device")); - vcp = &mnt->mi_vcomm; - if (VC_OPEN(vcp)) - return (EBUSY); - bzero(&(vcp->vc_selproc), sizeof (struct selinfo)); - TAILQ_INIT(&vcp->vc_requests); - TAILQ_INIT(&vcp->vc_replies); - MARK_VC_OPEN(vcp); - mnt->mi_vfsp = NULL; - mnt->mi_rootvp = NULL; - return (0); -} - -int -vc_close(struct cdev *dev, int flag, int mode, struct thread *td) -{ - struct vcomm *vcp; - struct vmsg *vmp, *nvmp = NULL; - struct coda_mntinfo *mi; - int err; - - ENTRY; - mi = dev2coda_mntinfo(dev); - KASSERT(mi, ("Coda: closing unknown cfs device")); - vcp = &mi->mi_vcomm; - KASSERT(VC_OPEN(vcp), ("Coda: closing unopened cfs device")); - - /* - * Prevent future operations on this vfs from succeeding by - * auto-unmounting any vfs mounted via this device. This frees user - * or sysadm from having to remember where all mount points are - * located. Put this before WAKEUPs to avoid queuing new messages - * between the WAKEUP and the unmount (which can happen if we're - * unlucky). - */ - if (mi->mi_rootvp == NULL) { - /* - * Just a simple open/close with no mount. - */ - MARK_VC_CLOSED(vcp); - return (0); - } - - /* - * Let unmount know this is for real. - */ - VTOC(mi->mi_rootvp)->c_flags |= C_UNMOUNTING; - coda_unmounting(mi->mi_vfsp); - - /* - * Wakeup clients so they can return. - */ - outstanding_upcalls = 0; - TAILQ_FOREACH_SAFE(vmp, &vcp->vc_requests, vm_chain, nvmp) { - /* - * Free signal request messages and don't wakeup cause no one - * is waiting. - */ - if (vmp->vm_opcode == CODA_SIGNAL) { - CODA_FREE((caddr_t)vmp->vm_data, - (u_int)VC_IN_NO_DATA); - CODA_FREE((caddr_t)vmp, (u_int)sizeof(struct vmsg)); - continue; - } - outstanding_upcalls++; - wakeup(&vmp->vm_sleep); - } - TAILQ_FOREACH(vmp, &vcp->vc_replies, vm_chain) { - outstanding_upcalls++; - wakeup(&vmp->vm_sleep); - } - MARK_VC_CLOSED(vcp); - if (outstanding_upcalls) { -#ifdef CODA_VERBOSE - printf("presleep: outstanding_upcalls = %d\n", - outstanding_upcalls); -#endif - (void) tsleep(&outstanding_upcalls, coda_call_sleep, - "coda_umount", 0); -#ifdef CODA_VERBOSE - printf("postsleep: outstanding_upcalls = %d\n", - outstanding_upcalls); -#endif - } - err = dounmount(mi->mi_vfsp, flag, td); - if (err) - myprintf(("Error %d unmounting vfs in vcclose(%s)\n", err, - devtoname(dev))); - return (0); -} - -int -vc_read(struct cdev *dev, struct uio *uiop, int flag) -{ - struct vcomm *vcp; - struct vmsg *vmp; - int error = 0; - - ENTRY; - vcp = &dev2coda_mntinfo(dev)->mi_vcomm; - - /* - * Get message at head of request queue. - */ - vmp = TAILQ_FIRST(&vcp->vc_requests); - if (vmp == NULL) - return (0); /* Nothing to read */ - - /* - * Move the input args into userspace. - * - * XXXRW: This is not safe in the presence of >1 reader, as vmp is - * still on the head of the list. - */ - uiop->uio_rw = UIO_READ; - error = uiomove(vmp->vm_data, vmp->vm_inSize, uiop); - if (error) { - myprintf(("vcread: error (%d) on uiomove\n", error)); - error = EINVAL; - } - TAILQ_REMOVE(&vcp->vc_requests, vmp, vm_chain); - - /* - * If request was a signal, free up the message and don't enqueue it - * in the reply queue. - */ - if (vmp->vm_opcode == CODA_SIGNAL) { - if (codadebug) - myprintf(("vcread: signal msg (%d, %d)\n", - vmp->vm_opcode, vmp->vm_unique)); - CODA_FREE((caddr_t)vmp->vm_data, (u_int)VC_IN_NO_DATA); - CODA_FREE((caddr_t)vmp, (u_int)sizeof(struct vmsg)); - return (error); - } - vmp->vm_flags |= VM_READ; - TAILQ_INSERT_TAIL(&vcp->vc_replies, vmp, vm_chain); - return (error); -} - -int -vc_write(struct cdev *dev, struct uio *uiop, int flag) -{ - struct vcomm *vcp; - struct vmsg *vmp; - struct coda_out_hdr *out; - u_long seq; - u_long opcode; - int buf[2]; - int error = 0; - - ENTRY; - vcp = &dev2coda_mntinfo(dev)->mi_vcomm; - - /* - * Peek at the opcode, unique without transfering the data. - */ - uiop->uio_rw = UIO_WRITE; - error = uiomove((caddr_t)buf, sizeof(int) * 2, uiop); - if (error) { - myprintf(("vcwrite: error (%d) on uiomove\n", error)); - return (EINVAL); - } - opcode = buf[0]; - seq = buf[1]; - if (codadebug) - myprintf(("vcwrite got a call for %ld.%ld\n", opcode, seq)); - if (DOWNCALL(opcode)) { - union outputArgs pbuf; - - /* - * Get the rest of the data. - */ - uiop->uio_rw = UIO_WRITE; - error = uiomove((caddr_t)&pbuf.coda_purgeuser.oh.result, - sizeof(pbuf) - (sizeof(int)*2), uiop); - if (error) { - myprintf(("vcwrite: error (%d) on uiomove (Op %ld " - "seq %ld)\n", error, opcode, seq)); - return (EINVAL); - } - return (handleDownCall(dev2coda_mntinfo(dev), opcode, &pbuf)); - } - - /* - * Look for the message on the (waiting for) reply queue. - */ - TAILQ_FOREACH(vmp, &vcp->vc_replies, vm_chain) { - if (vmp->vm_unique == seq) - break; - } - if (vmp == NULL) { - if (codadebug) - myprintf(("vcwrite: msg (%ld, %ld) not found\n", - opcode, seq)); - return (ESRCH); - } - - /* - * Remove the message from the reply queue. - */ - TAILQ_REMOVE(&vcp->vc_replies, vmp, vm_chain); - - /* - * Move data into response buffer. - */ - out = (struct coda_out_hdr *)vmp->vm_data; - - /* - * Don't need to copy opcode and uniquifier. - * - * Get the rest of the data. - */ - if (vmp->vm_outSize < uiop->uio_resid) { - myprintf(("vcwrite: more data than asked for (%d < %zd)\n", - vmp->vm_outSize, uiop->uio_resid)); - - /* - * Notify caller of the error. - */ - wakeup(&vmp->vm_sleep); - return (EINVAL); - } - - /* - * Save the value. - */ - buf[0] = uiop->uio_resid; - uiop->uio_rw = UIO_WRITE; - error = uiomove((caddr_t) &out->result, vmp->vm_outSize - - (sizeof(int) * 2), uiop); - if (error) { - myprintf(("vcwrite: error (%d) on uiomove (op %ld seq %ld)\n", - error, opcode, seq)); - return (EINVAL); - } - - /* - * I don't think these are used, but just in case. - * - * XXX - aren't these two already correct? -bnoble - */ - out->opcode = opcode; - out->unique = seq; - vmp->vm_outSize = buf[0]; /* Amount of data transferred? */ - vmp->vm_flags |= VM_WRITE; - error = 0; - if (opcode == CODA_OPEN_BY_FD) { - struct coda_open_by_fd_out *tmp = - (struct coda_open_by_fd_out *)out; - struct file *fp; - struct vnode *vp = NULL; - - if (tmp->oh.result == 0) { - error = getvnode(uiop->uio_td->td_proc->p_fd, CAP_WRITE, - tmp->fd, &fp); - if (!error) { - /* - * XXX: Since the whole driver runs with - * Giant, don't actually need to acquire it - * explicitly here yet. - */ - mtx_lock(&Giant); - vp = fp->f_vnode; - VREF(vp); - fdrop(fp, uiop->uio_td); - mtx_unlock(&Giant); - } - } - tmp->vp = vp; - } - wakeup(&vmp->vm_sleep); - return (error); -} - -int -vc_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, - struct thread *t) -{ - - ENTRY; - switch(cmd) { - case CODARESIZE: - return (ENODEV); - - case CODASTATS: - return (ENODEV); - - case CODAPRINT: - return (ENODEV); - - case CIOC_KERNEL_VERSION: - switch (*(u_int *)addr) { - case 0: - *(u_int *)addr = coda_kernel_version; - return (0); - - case 1: - case 2: - if (coda_kernel_version != *(u_int *)addr) - return (ENOENT); - else - return (0); - - default: - return (ENOENT); - } - - default: - return (EINVAL); - } -} - -int -vc_poll(struct cdev *dev, int events, struct thread *td) -{ - struct vcomm *vcp; - int event_msk = 0; - - ENTRY; - vcp = &dev2coda_mntinfo(dev)->mi_vcomm; - event_msk = events & (POLLIN|POLLRDNORM); - if (!event_msk) - return (0); - if (!TAILQ_EMPTY(&vcp->vc_requests)) - return (events & (POLLIN|POLLRDNORM)); - selrecord(td, &(vcp->vc_selproc)); - return (0); -} - -/* - * Statistics. - */ -struct coda_clstat coda_clstat; - -/* - * Key question: whether to sleep interuptably or uninteruptably when waiting - * for Venus. The former seems better (cause you can ^C a job), but then - * GNU-EMACS completion breaks. Use tsleep with no timeout, and no longjmp - * happens. But, when sleeping "uninterruptibly", we don't get told if it - * returns abnormally (e.g. kill -9). - */ -int -coda_call(struct coda_mntinfo *mntinfo, int inSize, int *outSize, - caddr_t buffer) -{ - struct vcomm *vcp; - struct vmsg *vmp; - int error; -#ifdef CTL_C - struct thread *td = curthread; - struct proc *p = td->td_proc; - sigset_t psig_omask; - sigset_t tempset; - int i; -#endif - - /* - * Unlikely, but could be a race condition with a dying warden. - */ - if (mntinfo == NULL) - return ENODEV; - vcp = &(mntinfo->mi_vcomm); - coda_clstat.ncalls++; - coda_clstat.reqs[((struct coda_in_hdr *)buffer)->opcode]++; - if (!VC_OPEN(vcp)) - return (ENODEV); - CODA_ALLOC(vmp,struct vmsg *,sizeof(struct vmsg)); - - /* - * Format the request message. - */ - vmp->vm_data = buffer; - vmp->vm_flags = 0; - vmp->vm_inSize = inSize; - vmp->vm_outSize - = *outSize ? *outSize : inSize; /* |buffer| >= inSize */ - vmp->vm_opcode = ((struct coda_in_hdr *)buffer)->opcode; - vmp->vm_unique = ++vcp->vc_seq; - if (codadebug) - myprintf(("Doing a call for %d.%d\n", vmp->vm_opcode, - vmp->vm_unique)); - - /* - * Fill in the common input args. - */ - ((struct coda_in_hdr *)buffer)->unique = vmp->vm_unique; - - /* - * Append msg to request queue and poke Venus. - */ - TAILQ_INSERT_TAIL(&vcp->vc_requests, vmp, vm_chain); - selwakeuppri(&(vcp->vc_selproc), coda_call_sleep); - - /* - * We can be interrupted while we wait for Venus to process our - * request. If the interrupt occurs before Venus has read the - * request, we dequeue and return. If it occurs after the read but - * before the reply, we dequeue, send a signal message, and return. - * If it occurs after the reply we ignore it. In no case do we want - * to restart the syscall. If it was interrupted by a venus shutdown - * (vcclose), return ENODEV. - * - * Ignore return, we have to check anyway. - */ -#ifdef CTL_C - /* - * This is work in progress. Setting coda_pcatch lets tsleep - * reawaken on a ^c or ^z. The problem is that emacs sets certain - * interrupts as SA_RESTART. This means that we should exit sleep - * handle the "signal" and then go to sleep again. Mostly this is - * done by letting the syscall complete and be restarted. We are not - * idempotent and can not do this. A better solution is necessary. - */ - i = 0; - PROC_LOCK(p); - psig_omask = td->td_sigmask; - do { - error = msleep(&vmp->vm_sleep, &p->p_mtx, - (coda_call_sleep|coda_pcatch), "coda_call", hz*2); - if (error == 0) - break; - else if (error == EWOULDBLOCK) { -#ifdef CODA_VERBOSE - printf("coda_call: tsleep TIMEOUT %d sec\n", 2+2*i); -#endif - } - else { - SIGEMPTYSET(tempset); - SIGADDSET(tempset, SIGIO); - if (SIGSETEQ(td->td_siglist, tempset)) { - SIGADDSET(td->td_sigmask, SIGIO); -#ifdef CODA_VERBOSE - printf("coda_call: tsleep returns %d SIGIO, " - "cnt %d\n", error, i); -#endif - } else { - SIGDELSET(tempset, SIGIO); - SIGADDSET(tempset, SIGALRM); - if (SIGSETEQ(td->td_siglist, tempset)) { - SIGADDSET(td->td_sigmask, SIGALRM); -#ifdef CODA_VERBOSE - printf("coda_call: tsleep returns " - "%d SIGALRM, cnt %d\n", error, i); -#endif - } else { -#ifdef CODA_VERBOSE - printf("coda_call: tsleep returns " - "%d, cnt %d\n", error, i); -#endif - -#ifdef notyet - tempset = td->td_siglist; - SIGSETNAND(tempset, td->td_sigmask); - printf("coda_call: siglist = %p, " - "sigmask = %p, mask %p\n", - td->td_siglist, td->td_sigmask, - tempset); - break; - SIGSETOR(td->td_sigmask, td->td_siglist); - tempset = td->td_siglist; - SIGSETNAND(tempset, td->td_sigmask); - printf("coda_call: new mask, " - "siglist = %p, sigmask = %p, " - "mask %p\n", td->td_siglist, - td->td_sigmask, tempset); -#endif - } - } - } - } while (error && i++ < 128 && VC_OPEN(vcp)); - td->td_sigmask = psig_omask; - signotify(td); - PROC_UNLOCK(p); -#else - (void)tsleep(&vmp->vm_sleep, coda_call_sleep, "coda_call", 0); -#endif - if (VC_OPEN(vcp)) { - /* - * Venus is still alive. - * - * Op went through, interrupt or not... - */ - if (vmp->vm_flags & VM_WRITE) { - error = 0; - *outSize = vmp->vm_outSize; - } else if (!(vmp->vm_flags & VM_READ)) { - /* Interrupted before venus read it. */ -#ifdef CODA_VERBOSE - if (1) -#else - if (codadebug) -#endif - myprintf(("interrupted before read: op = " - "%d.%d, flags = %x\n", vmp->vm_opcode, - vmp->vm_unique, vmp->vm_flags)); - TAILQ_REMOVE(&vcp->vc_requests, vmp, vm_chain); - error = EINTR; - } else { - /* - * (!(vmp->vm_flags & VM_WRITE)) means interrupted - * after upcall started. - * - * Interrupted after start of upcall, send venus a - * signal. - */ - struct coda_in_hdr *dog; - struct vmsg *svmp; - -#ifdef CODA_VERBOSE - if (1) -#else - if (codadebug) -#endif - myprintf(("Sending Venus a signal: op = " - "%d.%d, flags = %x\n", vmp->vm_opcode, - vmp->vm_unique, vmp->vm_flags)); - TAILQ_REMOVE(&vcp->vc_requests, vmp, vm_chain); - error = EINTR; - CODA_ALLOC(svmp, struct vmsg *, sizeof(struct vmsg)); - CODA_ALLOC((svmp->vm_data), char *, - sizeof(struct coda_in_hdr)); - dog = (struct coda_in_hdr *)svmp->vm_data; - svmp->vm_flags = 0; - dog->opcode = svmp->vm_opcode = CODA_SIGNAL; - dog->unique = svmp->vm_unique = vmp->vm_unique; - svmp->vm_inSize = sizeof (struct coda_in_hdr); -/*??? rvb */ svmp->vm_outSize = sizeof (struct coda_in_hdr); - if (codadebug) - myprintf(("coda_call: enqueing signal msg " - "(%d, %d)\n", svmp->vm_opcode, - svmp->vm_unique)); - - /* - * Insert at head of queue! - * - * XXXRW: Actually, the tail. - */ - TAILQ_INSERT_TAIL(&vcp->vc_requests, svmp, vm_chain); - selwakeuppri(&(vcp->vc_selproc), coda_call_sleep); - } - } else { - /* If venus died (!VC_OPEN(vcp)) */ - if (codadebug) - myprintf(("vcclose woke op %d.%d flags %d\n", - vmp->vm_opcode, vmp->vm_unique, vmp->vm_flags)); - error = ENODEV; - } - CODA_FREE(vmp, sizeof(struct vmsg)); - if (outstanding_upcalls > 0 && (--outstanding_upcalls == 0)) - wakeup(&outstanding_upcalls); - if (!error) - error = ((struct coda_out_hdr *)buffer)->result; - return (error); -} diff --git a/sys/fs/coda/coda_psdev.h b/sys/fs/coda/coda_psdev.h deleted file mode 100644 index 021456beb24..00000000000 --- a/sys/fs/coda/coda_psdev.h +++ /dev/null @@ -1,46 +0,0 @@ -/*- - * - * Coda: an Experimental Distributed File System - * Release 3.1 - * - * Copyright (c) 1998 Carnegie Mellon University - * All Rights Reserved - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation, and - * that credit is given to Carnegie Mellon University in all documents - * and publicity pertaining to direct or indirect use of this code or its - * derivatives. - * - * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, - * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS - * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON - * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER - * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF - * ANY DERIVATIVE WORK. - * - * Carnegie Mellon encourages users of this software to return any - * improvements or extensions that they make, and to grant Carnegie - * Mellon the rights to redistribute these changes without encumbrance. - * - * @(#) src/sys/coda/coda_psdev.c,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ - * $FreeBSD$ - */ - -#ifndef _CODA_PSDEV_H_ -#define _CODA_PSDEV_H_ - -/* - * Prototypes for cfs device operations. - */ -d_open_t vc_open; -d_close_t vc_close; -d_read_t vc_read; -d_write_t vc_write; -d_ioctl_t vc_ioctl; -d_poll_t vc_poll; - -#endif /* !_CODA_PSDEV_H_ */ diff --git a/sys/fs/coda/coda_subr.c b/sys/fs/coda/coda_subr.c deleted file mode 100644 index a7ae3549aac..00000000000 --- a/sys/fs/coda/coda_subr.c +++ /dev/null @@ -1,628 +0,0 @@ -/*- - * Coda: an Experimental Distributed File System - * Release 3.1 - * - * Copyright (c) 1987-1998 Carnegie Mellon University - * All Rights Reserved - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation, and - * that credit is given to Carnegie Mellon University in all documents - * and publicity pertaining to direct or indirect use of this code or its - * derivatives. - * - * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, - * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS - * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON - * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER - * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF - * ANY DERIVATIVE WORK. - * - * Carnegie Mellon encourages users of this software to return any - * improvements or extensions that they make, and to grant Carnegie - * Mellon the rights to redistribute these changes without encumbrance. - * - * @(#) src/sys/coda/coda_subr.c,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ - */ - -/*- - * Mach Operating System - * Copyright (c) 1989 Carnegie-Mellon University - * All rights reserved. The CMU software License Agreement specifies - * the terms and conditions for use and redistribution. - */ - -/* - * This code was written for the Coda filesystem at Carnegie Mellon - * University. Contributers include David Steere, James Kistler, and - * M. Satyanarayanan. - */ - -/*- - * NOTES: rvb - * 1. Added coda_unmounting to mark all cnodes as being UNMOUNTING. This - * has to be done before dounmount is called. Because some of the - * routines that dounmount calls before coda_unmounted might try to - * force flushes to venus. The vnode pager does this. - * 2. coda_unmounting marks all cnodes scanning coda_cache. - * 3. cfs_checkunmounting (under DEBUG) checks all cnodes by chasing the - * vnodes under the /coda mount point. - * 4. coda_cacheprint (under DEBUG) prints names with vnode/cnode address. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -static int coda_active = 0; -static int coda_reuse = 0; -static int coda_new = 0; - -static struct cnode *coda_freelist = NULL; -static struct cnode *coda_cache[CODA_CACHESIZE]; - -#define CNODE_NEXT(cp) ((cp)->c_next) - -#ifdef CODA_COMPAT_5 -#define coda_hash(fid) (((fid)->Volume + (fid)->Vnode) & (CODA_CACHESIZE-1)) -#define IS_DIR(cnode) (cnode.Vnode & 0x1) -#else -#define coda_hash(fid) (coda_f2i(fid) & (CODA_CACHESIZE-1)) -#define IS_DIR(cnode) (cnode.opaque[2] & 0x1) -#endif - -/* - * Allocate a cnode. - */ -struct cnode * -coda_alloc(void) -{ - struct cnode *cp; - - if (coda_freelist != NULL) { - cp = coda_freelist; - coda_freelist = CNODE_NEXT(cp); - coda_reuse++; - } else { - CODA_ALLOC(cp, struct cnode *, sizeof(struct cnode)); - - /* - * FreeBSD vnodes don't have any Pager info in them ('cause - * there are no external pagers, duh!). - */ -#define VNODE_VM_INFO_INIT(vp) /* MT */ - VNODE_VM_INFO_INIT(CTOV(cp)); - coda_new++; - } - bzero(cp, sizeof (struct cnode)); - return (cp); -} - -/* - * Deallocate a cnode. - */ -void -coda_free(struct cnode *cp) -{ - - CNODE_NEXT(cp) = coda_freelist; - coda_freelist = cp; -} - -/* - * Put a cnode in the hash table. - */ -void -coda_save(struct cnode *cp) -{ - - CNODE_NEXT(cp) = coda_cache[coda_hash(&cp->c_fid)]; - coda_cache[coda_hash(&cp->c_fid)] = cp; -} - -/* - * Remove a cnode from the hash table. - */ -void -coda_unsave(struct cnode *cp) -{ - struct cnode *ptr; - struct cnode *ptrprev = NULL; - - ptr = coda_cache[coda_hash(&cp->c_fid)]; - while (ptr != NULL) { - if (ptr == cp) { - if (ptrprev == NULL) - coda_cache[coda_hash(&cp->c_fid)] = - CNODE_NEXT(ptr); - else - CNODE_NEXT(ptrprev) = CNODE_NEXT(ptr); - CNODE_NEXT(cp) = (struct cnode *)NULL; - return; - } - ptrprev = ptr; - ptr = CNODE_NEXT(ptr); - } -} - -/* - * Lookup a cnode by fid. If the cnode is dying, it is bogus so skip it. - * - * NOTE: this allows multiple cnodes with same fid -- dcs 1/25/95 - */ -struct cnode * -coda_find(struct CodaFid *fid) -{ - struct cnode *cp; - - cp = coda_cache[coda_hash(fid)]; - while (cp) { - if (coda_fid_eq(&(cp->c_fid), fid) && (!IS_UNMOUNTING(cp))) { - coda_active++; - return (cp); - } - cp = CNODE_NEXT(cp); - } - return (NULL); -} - -/* - * Clear all cached access control decisions from Coda. - */ -static void -coda_acccache_purge(struct mount *mnt) -{ - struct cnode *cp; - int hash; - - for (hash = 0; hash < CODA_CACHESIZE; hash++) { - for (cp = coda_cache[hash]; cp != NULL; - cp = CNODE_NEXT(cp)) { - if (CTOV(cp)->v_mount == mnt && VALID_ACCCACHE(cp)) { - CODADEBUG(CODA_FLUSH, myprintf(("acccache " - "purge fid %s uid %d mode 0x%x\n", - coda_f2s(&cp->c_fid), cp->c_cached_uid, - (int)cp->c_cached_mode));); - cp->c_flags &= ~C_ACCCACHE; - } - } - } -} - -/* - * When a user loses their tokens (or other related events), we invalidate - * any cached access rights in the access cache. In the Linux version of - * Coda, we maintain a global epoch and simply bump it to invalidate all - * cached results generated in the epoch. For now, we walk all cnodes and - * manually invalidate just that uid in FreeBSD. - */ -static void -coda_acccache_purgeuser(struct mount *mnt, uid_t uid) -{ - struct cnode *cp; - int hash; - - for (hash = 0; hash < CODA_CACHESIZE; hash++) { - for (cp = coda_cache[hash]; cp != NULL; - cp = CNODE_NEXT(cp)) { - if (CTOV(cp)->v_mount == mnt && - VALID_ACCCACHE(cp) && (cp->c_cached_uid == uid)) { - CODADEBUG(CODA_PURGEUSER, myprintf(( - "acccache purgeuser fid %s uid %d mode " - "0x%x\n", coda_f2s(&cp->c_fid), - cp->c_cached_uid, (int)cp->c_cached_mode));); - cp->c_flags &= ~C_ACCCACHE; - } - } - } -} - -/* - * coda_kill is called as a side effect to vcopen. To prevent any cnodes - * left around from an earlier run of a venus or warden from causing problems - * with the new instance, mark any outstanding cnodes as dying. Future - * operations on these cnodes should fail (excepting coda_inactive of - * course!). Since multiple venii/wardens can be running, only kill the - * cnodes for a particular entry in the coda_mnttbl. -- DCS 12/1/94 - * - * XXX: I don't believe any special behavior is required with respect to the - * global namecache here, as /coda will have unmounted and hence cache_flush - * will have run...? - */ -int -coda_kill(struct mount *whoIam, enum dc_status dcstat) -{ - int hash, count = 0; - struct cnode *cp; - - /*- - * Algorithm is as follows: - * Second, flush whatever vnodes we can from the name cache. - * - * Finally, step through whatever is left and mark them dying. - * This prevents any operation at all. - * - * This is slightly overkill, but should work. Eventually it'd be - * nice to only flush those entries from the namecache that reference - * a vnode in this vfs. - * - * XXXRW: Perhaps we no longer need to purge the name cache when - * using the VFS name cache, as unmount will do that. - */ - cache_purgevfs(whoIam); - for (hash = 0; hash < CODA_CACHESIZE; hash++) { - for (cp = coda_cache[hash];cp != NULL; - cp = CNODE_NEXT(cp)) { - if (CTOV(cp)->v_mount == whoIam) { -#ifdef DEBUG - printf("coda_kill: vp %p, cp %p\n", CTOV(cp), - cp); -#endif - count++; - CODADEBUG(CODA_FLUSH, myprintf(("Live cnode " - "fid %s flags %d count %d\n", - coda_f2s(&cp->c_fid), cp->c_flags, - vrefcnt(CTOV(cp))));); - } - } - } - return (count); -} - -/* - * There are two reasons why a cnode may be in use, it may be in the name - * cache or it may be executing. - */ -void -coda_flush(struct coda_mntinfo *mnt, enum dc_status dcstat) -{ - int hash; - struct cnode *cp; - - coda_clstat.ncalls++; - coda_clstat.reqs[CODA_FLUSH]++; - - coda_acccache_purge(mnt->mi_vfsp); - cache_purgevfs(mnt->mi_vfsp); - for (hash = 0; hash < CODA_CACHESIZE; hash++) { - for (cp = coda_cache[hash]; cp != NULL; - cp = CNODE_NEXT(cp)) { - /* - * Only files that can be executed need to be flushed - * from the VM. - * - * NOTE: Currently this doesn't do anything, but - * perhaps it should? - */ - if (!IS_DIR(cp->c_fid)) - coda_vmflush(cp); - } - } -} - -/* - * As a debugging measure, print out any cnodes that lived through a name - * cache flush. - */ -void -coda_testflush(void) -{ - int hash; - struct cnode *cp; - - for (hash = 0; hash < CODA_CACHESIZE; hash++) { - for (cp = coda_cache[hash]; cp != NULL; - cp = CNODE_NEXT(cp)) - myprintf(("Live cnode fid %s count %d\n", - coda_f2s(&cp->c_fid), CTOV(cp)->v_usecount)); - } -} - -/* - * First, step through all cnodes and mark them unmounting. FreeBSD kernels - * may try to fsync them now that venus is dead, which would be a bad thing. - */ -void -coda_unmounting(struct mount *whoIam) -{ - int hash; - struct cnode *cp; - - for (hash = 0; hash < CODA_CACHESIZE; hash++) { - for (cp = coda_cache[hash]; cp != NULL; - cp = CNODE_NEXT(cp)) { - if (CTOV(cp)->v_mount == whoIam) { - if (cp->c_flags & (C_LOCKED|C_WANTED)) { - printf("coda_unmounting: Unlocking " - "%p\n", cp); - cp->c_flags &= ~(C_LOCKED|C_WANTED); - wakeup((caddr_t) cp); - } - cp->c_flags |= C_UNMOUNTING; - } - } - } -} - -#ifdef DEBUG -void -coda_checkunmounting(struct mount *mp) -{ - struct vnode *vp, *nvp; - struct cnode *cp; - int count = 0, bad = 0; - - MNT_VNODE_FOREACH_ALL(vp, mp, nvp) { - cp = VTOC(vp); - count++; - if (!(cp->c_flags & C_UNMOUNTING)) { - bad++; - printf("vp %p, cp %p missed\n", vp, cp); - cp->c_flags |= C_UNMOUNTING; - } - VI_UNLOCK(vp); - } -} - -void -coda_cacheprint(struct mount *whoIam) -{ - int hash; - struct cnode *cp; - int count = 0; - - printf("coda_cacheprint: coda_ctlvp %p, cp %p", coda_ctlvp, - VTOC(coda_ctlvp)); - -#if 0 - coda_nc_name(VTOC(coda_ctlvp)); -#endif - printf("\n"); - for (hash = 0; hash < CODA_CACHESIZE; hash++) { - for (cp = coda_cache[hash]; cp != NULL; - cp = CNODE_NEXT(cp)) { - if (CTOV(cp)->v_mount == whoIam) { - printf("coda_cacheprint: vp %p, cp %p", - CTOV(cp), cp); -#if 0 - coda_nc_name(cp); -#endif - printf("\n"); - count++; - } - } - } - printf("coda_cacheprint: count %d\n", count); -} -#endif - -/*- - * There are 6 cases where invalidations occur. The semantics of each is - * listed here: - * - * CODA_FLUSH -- Flush all entries from the name cache and the cnode - * cache. - * - * CODA_PURGEUSER -- Flush all entries from the name cache for a specific - * user. This call is a result of token expiration. - * - * The next two are the result of callbacks on a file or directory: - * - * CODA_ZAPDIR -- Flush the attributes for the dir from its cnode. Zap - * all children of this directory from the namecache. - * - * CODA_ZAPFILE -- Flush the attributes for a file. - * - * The fifth is a result of Venus detecting an inconsistent file: - * - * CODA_PURGEFID -- Flush the attribute for the file; if it is a dir (odd - * vnode), purge its children from the namecache; remove - * the file from the namecache. - * - * The sixth allows Venus to replace local fids with global ones during - * reintegration. - * - * CODA_REPLACE -- Replace one CodaFid with another throughout the name - * cache. - */ -int -handleDownCall(struct coda_mntinfo *mnt, int opcode, union outputArgs *out) -{ - int error; - - /* - * Handle invalidate requests. - */ - switch (opcode) { - case CODA_FLUSH: { - coda_flush(mnt, IS_DOWNCALL); - - /* Print any remaining cnodes. */ - CODADEBUG(CODA_FLUSH, coda_testflush();); - return (0); - } - - case CODA_PURGEUSER: { - coda_clstat.ncalls++; - coda_clstat.reqs[CODA_PURGEUSER]++; - - /* XXX - need to prevent fsync's. */ - - /* - * Purge any access cache entries for the uid. - */ -#ifdef CODA_COMPAT_5 - coda_acccache_purgeuser(mnt->mi_vfsp, - out->coda_purgeuser.cred.cr_uid); -#else - coda_acccache_purgeuser(mnt->mi_vfsp, - out->coda_purgeuser.uid); -#endif - return (0); - } - - case CODA_ZAPFILE: { - struct cnode *cp; - - error = 0; - coda_clstat.ncalls++; - coda_clstat.reqs[CODA_ZAPFILE]++; - cp = coda_find(&out->coda_zapfile.Fid); - if (cp != NULL) { - vref(CTOV(cp)); - cache_purge(CTOV(cp)); - cp->c_flags &= ~(C_VATTR | C_ACCCACHE); - ASSERT_VOP_LOCKED(CTOV(cp), "coda HandleDownCall"); - if (VOP_IS_TEXT(CTOV(cp))) - error = coda_vmflush(cp); - CODADEBUG(CODA_ZAPFILE, - myprintf(("zapfile: fid = %s, refcnt = %d, error = " - "%d\n", coda_f2s(&cp->c_fid), - CTOV(cp)->v_usecount - 1, error));); - if (vrefcnt(CTOV(cp)) == 1) - cp->c_flags |= C_PURGING; - vrele(CTOV(cp)); - } - return (error); - } - - case CODA_ZAPDIR: { - struct cnode *cp; - - coda_clstat.ncalls++; - coda_clstat.reqs[CODA_ZAPDIR]++; - cp = coda_find(&out->coda_zapdir.Fid); - if (cp != NULL) { - vref(CTOV(cp)); - cache_purge(CTOV(cp)); - cp->c_flags &= ~(C_VATTR | C_ACCCACHE); - CODADEBUG(CODA_ZAPDIR, myprintf(("zapdir: fid = %s, " - "refcnt = %d\n", coda_f2s(&cp->c_fid), - CTOV(cp)->v_usecount - 1));); - if (vrefcnt(CTOV(cp)) == 1) - cp->c_flags |= C_PURGING; - vrele(CTOV(cp)); - } - return (0); - } - - case CODA_PURGEFID: { - struct cnode *cp; - - error = 0; - coda_clstat.ncalls++; - coda_clstat.reqs[CODA_PURGEFID]++; - cp = coda_find(&out->coda_purgefid.Fid); - if (cp != NULL) { - vref(CTOV(cp)); - cache_purge(CTOV(cp)); - cp->c_flags &= ~(C_VATTR | C_ACCCACHE); - ASSERT_VOP_LOCKED(CTOV(cp), "coda HandleDownCall"); - if (!(IS_DIR(out->coda_purgefid.Fid)) - && VOP_IS_TEXT(CTOV(cp))) - error = coda_vmflush(cp); - CODADEBUG(CODA_PURGEFID, myprintf(("purgefid: fid " - "= %s, refcnt = %d, error = %d\n", - coda_f2s(&cp->c_fid), - CTOV(cp)->v_usecount - 1, error));); - if (vrefcnt(CTOV(cp)) == 1) - cp->c_flags |= C_PURGING; - vrele(CTOV(cp)); - } - return (error); - } - - case CODA_REPLACE: { - struct cnode *cp = NULL; - - coda_clstat.ncalls++; - coda_clstat.reqs[CODA_REPLACE]++; - cp = coda_find(&out->coda_replace.OldFid); - if (cp != NULL) { - /* - * Remove the cnode from the hash table, replace the - * fid, and reinsert. Clear the attribute cache as - * the "inode number" may have changed (it's just a - * hash of the fid, and the fid is changing). - */ - vref(CTOV(cp)); - coda_unsave(cp); - cp->c_fid = out->coda_replace.NewFid; - cp->c_flags &= ~C_VATTR; - coda_save(cp); - CODADEBUG(CODA_REPLACE, myprintf(("replace: oldfid " - "= %s, newfid = %s, cp = %p\n", - coda_f2s(&out->coda_replace.OldFid), - coda_f2s(&cp->c_fid), cp));); - vrele(CTOV(cp)); - } - return (0); - } - default: - myprintf(("handleDownCall: unknown opcode %d\n", opcode)); - return (EINVAL); - } -} - -int -coda_vmflush(struct cnode *cp) -{ - - return (0); -} - -/* - * Kernel-internal debugging switches. - */ -void -coda_debugon(void) -{ - - codadebug = -1; - coda_vnop_print_entry = 1; - coda_psdev_print_entry = 1; - coda_vfsop_print_entry = 1; -} - -void -coda_debugoff(void) -{ - - codadebug = 0; - coda_vnop_print_entry = 0; - coda_psdev_print_entry = 0; - coda_vfsop_print_entry = 0; -} - -/*- - * Utilities used by both client and server - * Standard levels: - * 0) no debugging - * 1) hard failures - * 2) soft failures - * 3) current test software - * 4) main procedure entry points - * 5) main procedure exit points - * 6) utility procedure entry points - * 7) utility procedure exit points - * 8) obscure procedure entry points - * 9) obscure procedure exit points - * 10) random stuff - * 11) all <= 1 - * 12) all <= 2 - * 13) all <= 3 - * ... - */ diff --git a/sys/fs/coda/coda_subr.h b/sys/fs/coda/coda_subr.h deleted file mode 100644 index b8edfd3f085..00000000000 --- a/sys/fs/coda/coda_subr.h +++ /dev/null @@ -1,49 +0,0 @@ -/*- - * - * Coda: an Experimental Distributed File System - * Release 3.1 - * - * Copyright (c) 1987-1998 Carnegie Mellon University - * All Rights Reserved - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation, and - * that credit is given to Carnegie Mellon University in all documents - * and publicity pertaining to direct or indirect use of this code or its - * derivatives. - * - * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, - * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS - * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON - * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER - * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF - * ANY DERIVATIVE WORK. - * - * Carnegie Mellon encourages users of this software to return any - * improvements or extensions that they make, and to grant Carnegie - * Mellon the rights to redistribute these changes without encumbrance. - * - * @(#) src/sys/coda/coda_subr.h,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ - * $FreeBSD$ - */ - -#ifndef _CODA_SUBR_H_ -#define _CODA_SUBR_H_ - -struct cnode *coda_alloc(void); -void coda_free(struct cnode *cp); -struct cnode *coda_find(struct CodaFid *fid); -void coda_flush(struct coda_mntinfo *mnt, enum dc_status dcstat); -void coda_testflush(void); -void coda_checkunmounting(struct mount *mp); -void coda_cacheprint(struct mount *whoIam); -void coda_debugon(void); -void coda_debugoff(void); -int coda_kill(struct mount *whoIam, enum dc_status dcstat); -void coda_save(struct cnode *cp); -void coda_unsave(struct cnode *cp); - -#endif /* !_CODA_SUBR_H_ */ diff --git a/sys/fs/coda/coda_venus.c b/sys/fs/coda/coda_venus.c deleted file mode 100644 index 9d012dd2c90..00000000000 --- a/sys/fs/coda/coda_venus.c +++ /dev/null @@ -1,705 +0,0 @@ -/*- - * Coda: an Experimental Distributed File System - * Release 3.1 - * - * Copyright (c) 1987-1998 Carnegie Mellon University - * All Rights Reserved - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation, and - * that credit is given to Carnegie Mellon University in all documents - * and publicity pertaining to direct or indirect use of this code or its - * derivatives. - * - * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, - * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS - * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON - * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER - * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF - * ANY DERIVATIVE WORK. - * - * Carnegie Mellon encourages users of this software to return any - * improvements or extensions that they make, and to grant Carnegie - * Mellon the rights to redistribute these changes without encumbrance. - * - * @(#) src/sys/cfs/coda_venus.c,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#define DECL_NO_IN(name) \ - struct coda_in_hdr *inp; \ - struct name ## _out *outp; \ - int name ## _size = sizeof (struct coda_in_hdr); \ - int Isize = sizeof (struct coda_in_hdr); \ - int Osize = sizeof (struct name ## _out); \ - int error - -#define DECL(name) \ - struct name ## _in *inp; \ - struct name ## _out *outp; \ - int name ## _size = sizeof (struct name ## _in); \ - int Isize = sizeof (struct name ## _in); \ - int Osize = sizeof (struct name ## _out); \ - int error - -#define DECL_NO_OUT(name) \ - struct name ## _in *inp; \ - struct coda_out_hdr *outp; \ - int name ## _size = sizeof (struct name ## _in); \ - int Isize = sizeof (struct name ## _in); \ - int Osize = sizeof (struct coda_out_hdr); \ - int error - -#define ALLOC_NO_IN(name) \ - if (Osize > name ## _size) \ - name ## _size = Osize; \ - CODA_ALLOC(inp, struct coda_in_hdr *, name ## _size); \ - outp = (struct name ## _out *) inp - -#define ALLOC(name) \ - if (Osize > name ## _size) \ - name ## _size = Osize; \ - CODA_ALLOC(inp, struct name ## _in *, name ## _size); \ - outp = (struct name ## _out *) inp - -#define ALLOC_NO_OUT(name) \ - if (Osize > name ## _size) \ - name ## _size = Osize; \ - CODA_ALLOC(inp, struct name ## _in *, name ## _size); \ - outp = (struct coda_out_hdr *) inp - -#define STRCPY(struc, name, len) \ - bcopy(name, (char *)inp + (int)inp->struc, len); \ - ((char*)inp + (int)inp->struc)[len++] = 0; \ - Isize += len - -#ifdef CODA_COMPAT_5 -#define INIT_IN(in, op, ident, p) do { \ - (in)->opcode = (op); \ - sx_slock(&proctree_lock); \ - (in)->pid = p ? p->p_pid : -1; \ - (in)->pgid = p ? p->p_pgid : -1; \ - (in)->sid = (p && p->p_session && p->p_session->s_leader) ? \ - (p->p_session->s_leader->p_pid) : -1; \ - sx_sunlock(&proctree_lock); \ - if (ident != NOCRED) { \ - (in)->cred.cr_uid = ident->cr_uid; \ - (in)->cred.cr_groupid = ident->cr_gid; \ - } else { \ - bzero(&((in)->cred),sizeof(struct coda_cred)); \ - (in)->cred.cr_uid = -1; \ - (in)->cred.cr_groupid = -1; \ - } \ -} while (0) -#else -#define INIT_IN(in, op, ident, p) do { \ - (in)->opcode = (op); \ - (in)->pid = p ? p->p_pid : -1; \ - (in)->pgid = p ? p->p_pgid : -1; \ - if (ident != NOCRED) \ - (in)->uid = ident->cr_uid; \ - else \ - (in)->uid = -1; \ -} while (0) -#endif - -#define CNV_OFLAG(to, from) do { \ - to = 0; \ - if (from & FREAD) to |= C_O_READ; \ - if (from & FWRITE) to |= C_O_WRITE; \ - if (from & O_TRUNC) to |= C_O_TRUNC; \ - if (from & O_EXCL) to |= C_O_EXCL; \ - if (from & O_CREAT) to |= C_O_CREAT; \ -} while (0) - -#define CNV_VV2V_ATTR(top, fromp) do { \ - (top)->va_type = (fromp)->va_type; \ - (top)->va_mode = (fromp)->va_mode; \ - (top)->va_nlink = (fromp)->va_nlink; \ - (top)->va_uid = (fromp)->va_uid; \ - (top)->va_gid = (fromp)->va_gid; \ - (top)->va_fsid = VNOVAL; \ - (top)->va_fileid = (fromp)->va_fileid; \ - (top)->va_size = (fromp)->va_size; \ - (top)->va_blocksize = (fromp)->va_blocksize; \ - (top)->va_atime = (fromp)->va_atime; \ - (top)->va_mtime = (fromp)->va_mtime; \ - (top)->va_ctime = (fromp)->va_ctime; \ - (top)->va_gen = (fromp)->va_gen; \ - (top)->va_flags = (fromp)->va_flags; \ - (top)->va_rdev = (fromp)->va_rdev; \ - (top)->va_bytes = (fromp)->va_bytes; \ - (top)->va_filerev = (fromp)->va_filerev; \ - (top)->va_vaflags = VNOVAL; \ - (top)->va_spare = VNOVAL; \ -} while (0) - -#define CNV_V2VV_ATTR(top, fromp) do { \ - (top)->va_type = (fromp)->va_type; \ - (top)->va_mode = (fromp)->va_mode; \ - (top)->va_nlink = (fromp)->va_nlink; \ - (top)->va_uid = (fromp)->va_uid; \ - (top)->va_gid = (fromp)->va_gid; \ - (top)->va_fileid = (fromp)->va_fileid; \ - (top)->va_size = (fromp)->va_size; \ - (top)->va_blocksize = (fromp)->va_blocksize; \ - (top)->va_atime = (fromp)->va_atime; \ - (top)->va_mtime = (fromp)->va_mtime; \ - (top)->va_ctime = (fromp)->va_ctime; \ - (top)->va_gen = (fromp)->va_gen; \ - (top)->va_flags = (fromp)->va_flags; \ - (top)->va_rdev = (fromp)->va_rdev; \ - (top)->va_bytes = (fromp)->va_bytes; \ - (top)->va_filerev = (fromp)->va_filerev; \ -} while (0) - -int coda_kernel_version = CODA_KERNEL_VERSION; - -int -venus_root(void *mdp, struct ucred *cred, struct proc *p, - /*out*/ struct CodaFid *VFid) -{ - DECL_NO_IN(coda_root); /* sets Isize & Osize */ - ALLOC_NO_IN(coda_root); /* sets inp & outp */ - - /* send the open to venus. */ - INIT_IN(inp, CODA_ROOT, cred, p); - - error = coda_call(mdp, Isize, &Osize, (char *)inp); - if (!error) - *VFid = outp->Fid; - - CODA_FREE(inp, coda_root_size); - return (error); -} - -int -venus_open(void *mdp, struct CodaFid *fid, int flag, struct ucred *cred, - struct proc *p, /*out*/ struct vnode **vp) -{ - int cflag; - DECL(coda_open_by_fd); /* sets Isize & Osize */ - ALLOC(coda_open_by_fd); /* sets inp & outp */ - - /* send the open to venus. */ - INIT_IN(&inp->ih, CODA_OPEN_BY_FD, cred, p); - inp->Fid = *fid; - CNV_OFLAG(cflag, flag); - inp->flags = cflag; - - error = coda_call(mdp, Isize, &Osize, (char *)inp); - *vp = error ? NULL : outp->vp; - - CODA_FREE(inp, coda_open_by_fd_size); - return (error); -} - -int -venus_close(void *mdp, struct CodaFid *fid, int flag, struct ucred *cred, - struct proc *p) -{ - int cflag; - DECL_NO_OUT(coda_close); /* sets Isize & Osize */ - ALLOC_NO_OUT(coda_close); /* sets inp & outp */ - - INIT_IN(&inp->ih, CODA_CLOSE, cred, p); - inp->Fid = *fid; - CNV_OFLAG(cflag, flag); - inp->flags = cflag; - - error = coda_call(mdp, Isize, &Osize, (char *)inp); - - CODA_FREE(inp, coda_close_size); - return (error); -} - -/* - * These two calls will not exist!!! The container file is read/written - * directly. - */ -void -venus_read(void) -{ -} - -void -venus_write(void) -{ -} - -/* - * This is a bit sad too. the ioctl's are for the control file, not for - * normal files. - */ -int -venus_ioctl(void *mdp, struct CodaFid *fid, int com, int flag, caddr_t data, - struct ucred *cred, struct proc *p) -{ - DECL(coda_ioctl); /* sets Isize & Osize */ - struct PioctlData *iap = (struct PioctlData *)data; - int tmp; - - coda_ioctl_size = VC_MAXMSGSIZE; - ALLOC(coda_ioctl); /* sets inp & outp */ - - INIT_IN(&inp->ih, CODA_IOCTL, cred, p); - inp->Fid = *fid; - - /* - * Command was mutated by increasing its size field to reflect the - * path and follow args. we need to subtract that out before sending - * the command to venus. - */ - inp->cmd = (com & ~(IOCPARM_MASK << 16)); - tmp = ((com >> 16) & IOCPARM_MASK) - sizeof (char *) - sizeof (int); - inp->cmd |= (tmp & IOCPARM_MASK) << 16; - - if (iap->vi.in_size > VC_MAXMSGSIZE || - iap->vi.out_size > VC_MAXMSGSIZE) { - CODA_FREE(inp, coda_ioctl_size); - return (EINVAL); - } - - inp->rwflag = flag; - inp->len = iap->vi.in_size; - inp->data = (char *)(sizeof (struct coda_ioctl_in)); - - error = copyin(iap->vi.in, (char*)inp + (long)inp->data, - iap->vi.in_size); - if (error) { - CODA_FREE(inp, coda_ioctl_size); - return (error); - } - - Osize = VC_MAXMSGSIZE; - error = coda_call(mdp, Isize + iap->vi.in_size, &Osize, (char *)inp); - - /* - * Copy out the out buffer. - */ - if (!error) { - if (outp->len > iap->vi.out_size) - error = EINVAL; - else - error = copyout((char *)outp + (long)outp->data, - iap->vi.out, iap->vi.out_size); - } - - CODA_FREE(inp, coda_ioctl_size); - return (error); -} - -int -venus_getattr(void *mdp, struct CodaFid *fid, struct ucred *cred, - struct vattr *vap) -{ - struct proc *p; - DECL(coda_getattr); /* sets Isize & Osize */ - ALLOC(coda_getattr); /* sets inp & outp */ - - /* - * Send the open to venus. - */ - p = curthread->td_proc; - INIT_IN(&inp->ih, CODA_GETATTR, cred, p); - inp->Fid = *fid; - - error = coda_call(mdp, Isize, &Osize, (char *)inp); - if (!error) - CNV_VV2V_ATTR(vap, &outp->attr); - - CODA_FREE(inp, coda_getattr_size); - return (error); -} - -int -venus_setattr(void *mdp, struct CodaFid *fid, struct vattr *vap, - struct ucred *cred) -{ - struct proc *p; - DECL_NO_OUT(coda_setattr); /* sets Isize & Osize */ - ALLOC_NO_OUT(coda_setattr); /* sets inp & outp */ - - /* - * Send the open to venus. - */ - p = curthread->td_proc; - INIT_IN(&inp->ih, CODA_SETATTR, cred, p); - inp->Fid = *fid; - CNV_V2VV_ATTR(&inp->attr, vap); - - error = coda_call(mdp, Isize, &Osize, (char *)inp); - - CODA_FREE(inp, coda_setattr_size); - return (error); -} - -int -venus_access(void *mdp, struct CodaFid *fid, accmode_t accmode, - struct ucred *cred, struct proc *p) -{ - DECL_NO_OUT(coda_access); /* sets Isize & Osize */ - ALLOC_NO_OUT(coda_access); /* sets inp & outp */ - - /* - * Send the open to venus. - */ - INIT_IN(&inp->ih, CODA_ACCESS, cred, p); - inp->Fid = *fid; - - /* - * NOTE: FreeBSD and Venus internals use the "data" in the low 3 - * bits. Hence, the conversion. - * - * XXX: We cast accmode_t variable into an int. - */ - inp->flags = (int)accmode>>6; - - error = coda_call(mdp, Isize, &Osize, (char *)inp); - - CODA_FREE(inp, coda_access_size); - return (error); -} - -int -venus_readlink(void *mdp, struct CodaFid *fid, struct ucred *cred, - struct proc *p, /*out*/ char **str, int *len) -{ - DECL(coda_readlink); /* sets Isize & Osize */ - coda_readlink_size += CODA_MAXPATHLEN; - ALLOC(coda_readlink); /* sets inp & outp */ - - /* - * Send the open to venus. - */ - INIT_IN(&inp->ih, CODA_READLINK, cred, p); - inp->Fid = *fid; - - Osize += CODA_MAXPATHLEN; - error = coda_call(mdp, Isize, &Osize, (char *)inp); - if (!error) { - CODA_ALLOC(*str, char *, outp->count); - *len = outp->count; - bcopy((char *)outp + (long)outp->data, *str, *len); - } - - CODA_FREE(inp, coda_readlink_size); - return (error); -} - -int -venus_fsync(void *mdp, struct CodaFid *fid, struct proc *p) -{ - DECL_NO_OUT(coda_fsync); /* sets Isize & Osize */ - ALLOC_NO_OUT(coda_fsync); /* sets inp & outp */ - - /* - * Send the open to venus. - * - * XXX: should be cached mount cred. - */ - INIT_IN(&inp->ih, CODA_FSYNC, NOCRED, p); - inp->Fid = *fid; - - error = coda_call(mdp, Isize, &Osize, (char *)inp); - - CODA_FREE(inp, coda_fsync_size); - return (error); -} - -int -venus_lookup(void *mdp, struct CodaFid *fid, const char *nm, int len, - struct ucred *cred, struct proc *p, /*out*/ struct CodaFid *VFid, - int *vtype) -{ - DECL(coda_lookup); /* sets Isize & Osize */ - coda_lookup_size += len + 1; - ALLOC(coda_lookup); /* sets inp & outp */ - - /* - * Send the open to venus. - */ - INIT_IN(&inp->ih, CODA_LOOKUP, cred, p); - inp->Fid = *fid; - - /* - * NOTE: Between version 1 and version 2 we have added an extra flag - * field to this structure. But because the string was at the end - * and because of the wierd way we represent strings by having the - * slot point to where the string characters are in the "heap", we - * can just slip the flag parameter in after the string slot pointer - * and veni that don't know better won't see this new flag field ... - * Otherwise we'd need two different venus_lookup functions. - */ - inp->name = Isize; - inp->flags = CLU_CASE_SENSITIVE; /* doesn't really matter for BSD */ - STRCPY(name, nm, len); /* increments Isize */ - - error = coda_call(mdp, Isize, &Osize, (char *)inp); - if (!error) { - *VFid = outp->Fid; - *vtype = outp->vtype; - } - - CODA_FREE(inp, coda_lookup_size); - return (error); -} - -int -venus_create(void *mdp, struct CodaFid *fid, const char *nm, int len, - int exclusive, int mode, struct vattr *va, struct ucred *cred, - struct proc *p, /*out*/ struct CodaFid *VFid, struct vattr *attr) -{ - DECL(coda_create); /* sets Isize & Osize */ - coda_create_size += len + 1; - ALLOC(coda_create); /* sets inp & outp */ - - /* - * Send the open to venus. - */ - INIT_IN(&inp->ih, CODA_CREATE, cred, p); - inp->Fid = *fid; - inp->excl = exclusive ? C_O_EXCL : 0; - inp->mode = mode; - CNV_V2VV_ATTR(&inp->attr, va); - - inp->name = Isize; - STRCPY(name, nm, len); /* increments Isize */ - - error = coda_call(mdp, Isize, &Osize, (char *)inp); - if (!error) { - *VFid = outp->Fid; - CNV_VV2V_ATTR(attr, &outp->attr); - } - - CODA_FREE(inp, coda_create_size); - return (error); -} - -int -venus_remove(void *mdp, struct CodaFid *fid, const char *nm, int len, - struct ucred *cred, struct proc *p) -{ - DECL_NO_OUT(coda_remove); /* sets Isize & Osize */ - coda_remove_size += len + 1; - ALLOC_NO_OUT(coda_remove); /* sets inp & outp */ - - /* - * Send the open to venus. - */ - INIT_IN(&inp->ih, CODA_REMOVE, cred, p); - inp->Fid = *fid; - - inp->name = Isize; - STRCPY(name, nm, len); /* increments Isize */ - - error = coda_call(mdp, Isize, &Osize, (char *)inp); - - CODA_FREE(inp, coda_remove_size); - return (error); -} - -int -venus_link(void *mdp, struct CodaFid *fid, struct CodaFid *tfid, - const char *nm, int len, struct ucred *cred, struct proc *p) -{ - DECL_NO_OUT(coda_link); /* sets Isize & Osize */ - coda_link_size += len + 1; - ALLOC_NO_OUT(coda_link); /* sets inp & outp */ - - /* - * Send the open to venus. - */ - INIT_IN(&inp->ih, CODA_LINK, cred, p); - inp->sourceFid = *fid; - inp->destFid = *tfid; - - inp->tname = Isize; - STRCPY(tname, nm, len); /* increments Isize */ - - error = coda_call(mdp, Isize, &Osize, (char *)inp); - - CODA_FREE(inp, coda_link_size); - return (error); -} - -int -venus_rename(void *mdp, struct CodaFid *fid, struct CodaFid *tfid, - const char *nm, int len, const char *tnm, int tlen, struct ucred *cred, - struct proc *p) -{ - DECL_NO_OUT(coda_rename); /* sets Isize & Osize */ - coda_rename_size += len + 1 + tlen + 1; - ALLOC_NO_OUT(coda_rename); /* sets inp & outp */ - - /* - * Send the open to venus. - */ - INIT_IN(&inp->ih, CODA_RENAME, cred, p); - inp->sourceFid = *fid; - inp->destFid = *tfid; - - inp->srcname = Isize; - STRCPY(srcname, nm, len); /* increments Isize */ - - inp->destname = Isize; - STRCPY(destname, tnm, tlen); /* increments Isize */ - - error = coda_call(mdp, Isize, &Osize, (char *)inp); - - CODA_FREE(inp, coda_rename_size); - return (error); -} - -int -venus_mkdir(void *mdp, struct CodaFid *fid, const char *nm, int len, - struct vattr *va, struct ucred *cred, struct proc *p, - /*out*/ struct CodaFid *VFid, struct vattr *ova) -{ - DECL(coda_mkdir); /* sets Isize & Osize */ - coda_mkdir_size += len + 1; - ALLOC(coda_mkdir); /* sets inp & outp */ - - /* - * Send the open to venus. - */ - INIT_IN(&inp->ih, CODA_MKDIR, cred, p); - inp->Fid = *fid; - CNV_V2VV_ATTR(&inp->attr, va); - - inp->name = Isize; - STRCPY(name, nm, len); /* increments Isize */ - - error = coda_call(mdp, Isize, &Osize, (char *)inp); - if (!error) { - *VFid = outp->Fid; - CNV_VV2V_ATTR(ova, &outp->attr); - } - - CODA_FREE(inp, coda_mkdir_size); - return (error); -} - -int -venus_rmdir(void *mdp, struct CodaFid *fid, const char *nm, int len, - struct ucred *cred, struct proc *p) -{ - DECL_NO_OUT(coda_rmdir); /* sets Isize & Osize */ - coda_rmdir_size += len + 1; - ALLOC_NO_OUT(coda_rmdir); /* sets inp & outp */ - - /* - * Send the open to venus. - */ - INIT_IN(&inp->ih, CODA_RMDIR, cred, p); - inp->Fid = *fid; - - inp->name = Isize; - STRCPY(name, nm, len); /* increments Isize */ - - error = coda_call(mdp, Isize, &Osize, (char *)inp); - - CODA_FREE(inp, coda_rmdir_size); - return (error); -} - -int -venus_symlink(void *mdp, struct CodaFid *fid, const char *lnm, int llen, - const char *nm, int len, struct vattr *va, struct ucred *cred, - struct proc *p) -{ - DECL_NO_OUT(coda_symlink); /* sets Isize & Osize */ - coda_symlink_size += llen + 1 + len + 1; - ALLOC_NO_OUT(coda_symlink); /* sets inp & outp */ - - /* - * Send the open to venus. - */ - INIT_IN(&inp->ih, CODA_SYMLINK, cred, p); - inp->Fid = *fid; - CNV_V2VV_ATTR(&inp->attr, va); - - inp->srcname = Isize; - STRCPY(srcname, lnm, llen); /* increments Isize */ - - inp->tname = Isize; - STRCPY(tname, nm, len); /* increments Isize */ - - error = coda_call(mdp, Isize, &Osize, (char *)inp); - - CODA_FREE(inp, coda_symlink_size); - return (error); -} - -/* - * XXX: Unused. - */ -int -venus_readdir(void *mdp, struct CodaFid *fid, int count, int offset, - struct ucred *cred, struct proc *p, /*out*/ char *buffer, int *len) -{ - DECL(coda_readdir); /* sets Isize & Osize */ - coda_readdir_size = VC_MAXMSGSIZE; - ALLOC(coda_readdir); /* sets inp & outp */ - - /* - * Send the open to venus. - */ - INIT_IN(&inp->ih, CODA_READDIR, cred, p); - inp->Fid = *fid; - inp->count = count; - inp->offset = offset; - - Osize = VC_MAXMSGSIZE; - error = coda_call(mdp, Isize, &Osize, (char *)inp); - if (!error) { - bcopy((char *)outp + (long)outp->data, buffer, outp->size); - *len = outp->size; - } - - CODA_FREE(inp, coda_readdir_size); - return (error); -} - -int -venus_fhtovp(void *mdp, struct CodaFid *fid, struct ucred *cred, - struct proc *p, /*out*/ struct CodaFid *VFid, int *vtype) -{ - DECL(coda_vget); /* sets Isize & Osize */ - ALLOC(coda_vget); /* sets inp & outp */ - - /* - * Send the open to Venus. - */ - INIT_IN(&inp->ih, CODA_VGET, cred, p); - inp->Fid = *fid; - - error = coda_call(mdp, Isize, &Osize, (char *)inp); - if (!error) { - *VFid = outp->Fid; - *vtype = outp->vtype; - } - - CODA_FREE(inp, coda_vget_size); - return (error); -} diff --git a/sys/fs/coda/coda_venus.h b/sys/fs/coda/coda_venus.h deleted file mode 100644 index 95f1c576438..00000000000 --- a/sys/fs/coda/coda_venus.h +++ /dev/null @@ -1,83 +0,0 @@ -/*- - * - * Coda: an Experimental Distributed File System - * Release 3.1 - * - * Copyright (c) 1987-1998 Carnegie Mellon University - * All Rights Reserved - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation, and - * that credit is given to Carnegie Mellon University in all documents - * and publicity pertaining to direct or indirect use of this code or its - * derivatives. - * - * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, - * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS - * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON - * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER - * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF - * ANY DERIVATIVE WORK. - * - * Carnegie Mellon encourages users of this software to return any - * improvements or extensions that they make, and to grant Carnegie - * Mellon the rights to redistribute these changes without encumbrance. - * - * @(#) src/sys/coda/coda_venus.h,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ - * $FreeBSD$ - */ - -#ifndef _CODA_VENUS_H_ -#define _CODA_VENUS_H_ - -int venus_root(void *mdp, struct ucred *cred, struct proc *p, - /*out*/ struct CodaFid *VFid); -int venus_open(void *mdp, struct CodaFid *fid, int flag, - struct ucred *cred, struct proc *p, /*out*/ struct vnode **vp); -int venus_close(void *mdp, struct CodaFid *fid, int flag, - struct ucred *cred, struct proc *p); -void venus_read(void); -void venus_write(void); -int venus_ioctl(void *mdp, struct CodaFid *fid, int com, int flag, - caddr_t data, struct ucred *cred, struct proc *p); -int venus_getattr(void *mdp, struct CodaFid *fid, struct ucred *cred, - struct vattr *vap); -int venus_setattr(void *mdp, struct CodaFid *fid, struct vattr *vap, - struct ucred *cred); -int venus_access(void *mdp, struct CodaFid *fid, int mode, - struct ucred *cred, struct proc *p); -int venus_readlink(void *mdp, struct CodaFid *fid, struct ucred *cred, - struct proc *p, /*out*/ char **str, int *len); -int venus_fsync(void *mdp, struct CodaFid *fid, struct proc *p); -int venus_lookup(void *mdp, struct CodaFid *fid, const char *nm, int len, - struct ucred *cred, struct proc *p, /*out*/ struct CodaFid *VFid, - int *vtype); -int venus_create(void *mdp, struct CodaFid *fid, const char *nm, int len, - int exclusive, int mode, struct vattr *va, struct ucred *cred, - struct proc *p, /*out*/ struct CodaFid *VFid, - struct vattr *attr); -int venus_remove(void *mdp, struct CodaFid *fid, const char *nm, int len, - struct ucred *cred, struct proc *p); -int venus_link(void *mdp, struct CodaFid *fid, struct CodaFid *tfid, - const char *nm, int len, struct ucred *cred, struct proc *p); -int venus_rename(void *mdp, struct CodaFid *fid, struct CodaFid *tfid, - const char *nm, int len, const char *tnm, int tlen, - struct ucred *cred, struct proc *p); -int venus_mkdir(void *mdp, struct CodaFid *fid, const char *nm, int len, - struct vattr *va, struct ucred *cred, struct proc *p, - /*out*/ struct CodaFid *VFid, struct vattr *ova); -int venus_rmdir(void *mdp, struct CodaFid *fid, const char *nm, int len, - struct ucred *cred, struct proc *p); -int venus_symlink(void *mdp, struct CodaFid *fid, const char *lnm, - int llen, const char *nm, int len, struct vattr *va, - struct ucred *cred, struct proc *p); -int venus_readdir(void *mdp, struct CodaFid *fid, int count, int offset, - struct ucred *cred, struct proc *p, /*out*/ char *buffer, - int *len); -int venus_fhtovp(void *mdp, struct CodaFid *fid, struct ucred *cred, - struct proc *p, /*out*/ struct CodaFid *VFid, int *vtype); - -#endif /* !_CODA_VENUS_H_ */ diff --git a/sys/fs/coda/coda_vfsops.c b/sys/fs/coda/coda_vfsops.c deleted file mode 100644 index 90660c622a2..00000000000 --- a/sys/fs/coda/coda_vfsops.c +++ /dev/null @@ -1,446 +0,0 @@ -/*- - * Coda: an Experimental Distributed File System - * Release 3.1 - * - * Copyright (c) 1987-1998 Carnegie Mellon University - * All Rights Reserved - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation, and - * that credit is given to Carnegie Mellon University in all documents - * and publicity pertaining to direct or indirect use of this code or its - * derivatives. - * - * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, - * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS - * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON - * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER - * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF - * ANY DERIVATIVE WORK. - * - * Carnegie Mellon encourages users of this software to return any - * improvements or extensions that they make, and to grant Carnegie - * Mellon the rights to redistribute these changes without encumbrance. - * - * @(#) src/sys/cfs/coda_vfsops.c,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ - */ - -/*- - * Mach Operating System - * Copyright (c) 1989 Carnegie-Mellon University - * All rights reserved. The CMU software License Agreement specifies - * the terms and conditions for use and redistribution. - */ - -/* - * This code was written for the Coda filesystem at Carnegie Mellon - * University. Contributers include David Steere, James Kistler, and - * M. Satyanarayanan. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -MALLOC_DEFINE(M_CODA, "coda", "Various Coda Structures"); - -int codadebug = 0; -int coda_vfsop_print_entry = 0; -#define ENTRY do { \ - if (coda_vfsop_print_entry) \ - myprintf(("Entered %s\n", __func__)); \ -} while (0) - -struct vnode *coda_ctlvp; - -/* - * Structure to keep statistics of internally generated/satisfied calls. - */ -static struct coda_op_stats coda_vfsopstats[CODA_VFSOPS_SIZE]; - -#define MARK_ENTRY(op) (coda_vfsopstats[op].entries++) -#define MARK_INT_SAT(op) (coda_vfsopstats[op].sat_intrn++) -#define MARK_INT_FAIL(op) (coda_vfsopstats[op].unsat_intrn++) -#define MARK_INT_GEN(op) (coda_vfsopstats[op].gen_intrn++) - -int -coda_vfsopstats_init(void) -{ - int i; - - for (i=0; imnt_optnew, coda_opts)) - return (EINVAL); - from = vfs_getopts(vfsp->mnt_optnew, "from", &error); - if (error) - return (error); - coda_vfsopstats_init(); - coda_vnodeopstats_init(); - MARK_ENTRY(CODA_MOUNT_STATS); - if (CODA_MOUNTED(vfsp)) { - MARK_INT_FAIL(CODA_MOUNT_STATS); - return (EBUSY); - } - - /* - * Validate mount device. Similar to getmdev(). - */ - NDINIT(&ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, from, curthread); - error = namei(&ndp); - dvp = ndp.ni_vp; - if (error) { - MARK_INT_FAIL(CODA_MOUNT_STATS); - return (error); - } - if (dvp->v_type != VCHR) { - MARK_INT_FAIL(CODA_MOUNT_STATS); - vrele(dvp); - NDFREE(&ndp, NDF_ONLY_PNBUF); - return (ENXIO); - } - dev = dvp->v_rdev; - vrele(dvp); - NDFREE(&ndp, NDF_ONLY_PNBUF); - - /* - * Initialize the mount record and link it to the vfs struct. - */ - mi = dev2coda_mntinfo(dev); - if (!mi) { - MARK_INT_FAIL(CODA_MOUNT_STATS); - printf("Coda mount: %s is not a cfs device\n", from); - return (ENXIO); - } - if (!VC_OPEN(&mi->mi_vcomm)) { - MARK_INT_FAIL(CODA_MOUNT_STATS); - return (ENODEV); - } - - /* - * No initialization (here) of mi_vcomm! - */ - vfsp->mnt_data = mi; - vfs_getnewfsid (vfsp); - mi->mi_vfsp = vfsp; - mi->mi_started = 0; /* XXX See coda_root() */ - - /* - * Make a root vnode to placate the Vnode interface, but don't - * actually make the CODA_ROOT call to venus until the first call to - * coda_root in case a server is down while venus is starting. - */ - cp = make_coda_node(&rootfid, vfsp, VDIR); - rootvp = CTOV(cp); - rootvp->v_vflag |= VV_ROOT; - cp = make_coda_node(&ctlfid, vfsp, VREG); - coda_ctlvp = CTOV(cp); - - /* - * Add vfs and rootvp to chain of vfs hanging off mntinfo. - */ - mi->mi_vfsp = vfsp; - mi->mi_rootvp = rootvp; - vfs_mountedfrom(vfsp, from); - - /* - * Error is currently guaranteed to be zero, but in case some code - * changes... - */ - CODADEBUG(1, myprintf(("coda_mount returned %d\n", error));); - if (error) - MARK_INT_FAIL(CODA_MOUNT_STATS); - else - MARK_INT_SAT(CODA_MOUNT_STATS); - return (error); -} - -int -coda_unmount(struct mount *vfsp, int mntflags) -{ - struct coda_mntinfo *mi = vftomi(vfsp); - int active, error = 0; - - ENTRY; - MARK_ENTRY(CODA_UMOUNT_STATS); - if (!CODA_MOUNTED(vfsp)) { - MARK_INT_FAIL(CODA_UMOUNT_STATS); - return (EINVAL); - } - if (mi->mi_vfsp == vfsp) { - /* - * We found the victim. - */ - if (!IS_UNMOUNTING(VTOC(mi->mi_rootvp))) - return (EBUSY); /* Venus is still running */ -#ifdef DEBUG - printf("coda_unmount: ROOT: vp %p, cp %p\n", mi->mi_rootvp, - VTOC(mi->mi_rootvp)); -#endif - vrele(mi->mi_rootvp); - mi->mi_rootvp = NULL; - vrele(coda_ctlvp); - coda_ctlvp = NULL; - active = coda_kill(vfsp, NOT_DOWNCALL); - error = vflush(mi->mi_vfsp, 0, FORCECLOSE, curthread); -#ifdef CODA_VERBOSE - printf("coda_unmount: active = %d, vflush active %d\n", - active, error); -#endif - error = 0; - /* - * I'm going to take this out to allow lookups to go through. - * I'm not sure it's important anyway. -- DCS 2/2/94 - */ - /* vfsp->VFS_DATA = NULL; */ - - /* - * No more vfsp's to hold onto. - */ - mi->mi_vfsp = NULL; - - if (error) - MARK_INT_FAIL(CODA_UMOUNT_STATS); - else - MARK_INT_SAT(CODA_UMOUNT_STATS); - return (error); - } - return (EINVAL); -} - -/* - * Find root of cfs. - */ -int -coda_root(struct mount *vfsp, int flags, struct vnode **vpp) -{ - struct coda_mntinfo *mi = vftomi(vfsp); - int error; - struct proc *p; - struct thread *td; - struct CodaFid VFid; - static const struct CodaFid invalfid = INVAL_FID; - - td = curthread; - p = td->td_proc; - ENTRY; - MARK_ENTRY(CODA_ROOT_STATS); - if (vfsp == mi->mi_vfsp) { - /* - * Cache the root across calls. We only need to pass the - * request on to Venus if the root vnode is the dummy we - * installed in coda_mount() with all c_fid members zeroed. - * - * XXX In addition, we assume that the first call to - * coda_root() is from vfs_mount() (before the call to - * checkdirs()) and return the dummy root node to avoid a - * deadlock. This bug is fixed in the Coda CVS repository - * but not in any released versions as of 6 Mar 2003. - */ - if (memcmp(&VTOC(mi->mi_rootvp)->c_fid, &invalfid, - sizeof(struct CodaFid)) != 0 || mi->mi_started == 0) { - /* - * Found valid root. - */ - *vpp = mi->mi_rootvp; - mi->mi_started = 1; - - /* - * On Mach, this is vref. On FreeBSD, vref + - * vn_lock. - */ - vref(*vpp); - vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY); - MARK_INT_SAT(CODA_ROOT_STATS); - return (0); - } - } - - error = venus_root(vftomi(vfsp), td->td_ucred, p, &VFid); - if (!error) { - /* - * Save the new rootfid in the cnode, and rehash the cnode - * into the cnode hash with the new fid key. - */ - coda_unsave(VTOC(mi->mi_rootvp)); - VTOC(mi->mi_rootvp)->c_fid = VFid; - coda_save(VTOC(mi->mi_rootvp)); - *vpp = mi->mi_rootvp; - vref(*vpp); - vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY); - MARK_INT_SAT(CODA_ROOT_STATS); - } else if (error == ENODEV || error == EINTR) { - /* - * Gross hack here! - * - * If Venus fails to respond to the CODA_ROOT call, coda_call - * returns ENODEV. Return the uninitialized root vnode to - * allow vfs operations such as unmount to continue. Without - * this hack, there is no way to do an unmount if Venus dies - * before a successful CODA_ROOT call is done. All vnode - * operations will fail. - */ - *vpp = mi->mi_rootvp; - vref(*vpp); - vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY); - MARK_INT_FAIL(CODA_ROOT_STATS); - error = 0; - } else { - CODADEBUG(CODA_ROOT, myprintf(("error %d in CODA_ROOT\n", - error));); - MARK_INT_FAIL(CODA_ROOT_STATS); - } - return (error); -} - -/* - * Get filesystem statistics. - */ -int -coda_statfs(struct mount *vfsp, struct statfs *sbp) -{ - - ENTRY; - MARK_ENTRY(CODA_STATFS_STATS); - if (!CODA_MOUNTED(vfsp)) { - MARK_INT_FAIL(CODA_STATFS_STATS); - return (EINVAL); - } - - /* - * XXX - what to do about f_flags, others? --bnoble - * - * We just make up free space counts that are sufficiently large. - */ - sbp->f_flags = 0; - sbp->f_bsize = 8192; /* XXX */ - sbp->f_iosize = 8192; /* XXX */ -#define CODA_SFS_SIZ 0x8AB75D - sbp->f_blocks = CODA_SFS_SIZ; - sbp->f_bfree = CODA_SFS_SIZ; - sbp->f_bavail = CODA_SFS_SIZ; - sbp->f_files = CODA_SFS_SIZ; - sbp->f_ffree = CODA_SFS_SIZ; - MARK_INT_SAT(CODA_STATFS_STATS); - return (0); -} - -/* - * Flush any pending I/O. - */ -int -coda_sync(struct mount *vfsp, int waitfor) -{ - - ENTRY; - MARK_ENTRY(CODA_SYNC_STATS); - MARK_INT_SAT(CODA_SYNC_STATS); - return (0); -} - -/* - * fhtovp is now what vget used to be in 4.3-derived systems. For some silly - * reason, vget is now keyed by a 32 bit ino_t, rather than a type-specific - * fid. - * - * XXX: coda_fhtovp is currently not hooked up, so no NFS export for Coda. - * We leave it here in the hopes that someone will find it someday and hook - * it up. Among other things, it will need some reworking to match the - * vfs_fhtovp_t prototype. - */ -int -coda_fhtovp(struct mount *vfsp, struct fid *fhp, struct mbuf *nam, - struct vnode **vpp, int *exflagsp, struct ucred **creadanonp) -{ - struct cfid *cfid = (struct cfid *)fhp; - struct cnode *cp = NULL; - int error; - struct thread *td = curthread; /* XXX -mach */ - struct proc *p = td->td_proc; - struct CodaFid VFid; - int vtype; - - ENTRY; - MARK_ENTRY(CODA_VGET_STATS); - - /* - * Check for vget of control object. - */ - if (IS_CTL_FID(&cfid->cfid_fid)) { - *vpp = coda_ctlvp; - vref(coda_ctlvp); - MARK_INT_SAT(CODA_VGET_STATS); - return (0); - } - error = venus_fhtovp(vftomi(vfsp), &cfid->cfid_fid, td->td_ucred, p, - &VFid, &vtype); - if (error) { - CODADEBUG(CODA_VGET, myprintf(("vget error %d\n",error));); - *vpp = NULL; - } else { - CODADEBUG(CODA_VGET, myprintf(("vget: %s type %d result " - "%d\n", coda_f2s(&VFid), vtype, error));); - cp = make_coda_node(&VFid, vfsp, vtype); - *vpp = CTOV(cp); - } - return (error); -} - -struct vfsops coda_vfsops = { - .vfs_mount = coda_mount, - .vfs_root = coda_root, - .vfs_statfs = coda_statfs, - .vfs_sync = coda_sync, - .vfs_unmount = coda_unmount, -}; -VFS_SET(coda_vfsops, coda, VFCF_NETWORK); diff --git a/sys/fs/coda/coda_vfsops.h b/sys/fs/coda/coda_vfsops.h deleted file mode 100644 index e5b3a11b644..00000000000 --- a/sys/fs/coda/coda_vfsops.h +++ /dev/null @@ -1,60 +0,0 @@ -/*- - * - * Coda: an Experimental Distributed File System - * Release 3.1 - * - * Copyright (c) 1987-1998 Carnegie Mellon University - * All Rights Reserved - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation, and - * that credit is given to Carnegie Mellon University in all documents - * and publicity pertaining to direct or indirect use of this code or its - * derivatives. - * - * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, - * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS - * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON - * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER - * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF - * ANY DERIVATIVE WORK. - * - * Carnegie Mellon encourages users of this software to return any - * improvements or extensions that they make, and to grant Carnegie - * Mellon the rights to redistribute these changes without encumbrance. - * - * @(#) src/sys/cfs/coda_vfsops.h,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ - * $FreeBSD$ - */ - -#ifndef _CODA_VFSOPS_H_ -#define _CODA_VFSOPS_H_ - -/* - * cfid structure: - * - * This overlays the fid structure (see vfs.h); only used below and will - * probably go away. - */ -struct cfid { - u_short cfid_len; - u_short padding; - struct CodaFid cfid_fid; -}; - -struct mbuf; -struct mount; -int coda_vfsopstats_init(void); -int coda_fhtovp(struct mount *, struct fid *, struct mbuf *, - struct vnode **, int *, struct ucred **); - -vfs_mount_t coda_mount; -vfs_unmount_t coda_unmount; -vfs_root_t coda_root; -vfs_statfs_t coda_statfs; -vfs_sync_t coda_sync; - -#endif /* !_CODA_VFSOPS_H_ */ diff --git a/sys/fs/coda/coda_vnops.c b/sys/fs/coda/coda_vnops.c deleted file mode 100644 index 51fb307a0c4..00000000000 --- a/sys/fs/coda/coda_vnops.c +++ /dev/null @@ -1,1738 +0,0 @@ -/*- - * Coda: an Experimental Distributed File System - * Release 3.1 - * - * Copyright (c) 1987-1998 Carnegie Mellon University - * All Rights Reserved - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation, and - * that credit is given to Carnegie Mellon University in all documents - * and publicity pertaining to direct or indirect use of this code or its - * derivatives. - * - * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, - * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS - * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON - * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER - * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF - * ANY DERIVATIVE WORK. - * - * Carnegie Mellon encourages users of this software to return any - * improvements or extensions that they make, and to grant Carnegie - * Mellon the rights to redistribute these changes without encumbrance. - * - * @(#) src/sys/coda/coda_vnops.c,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ - */ -/* - * Mach Operating System - * Copyright (c) 1990 Carnegie-Mellon University - * Copyright (c) 1989 Carnegie-Mellon University - * All rights reserved. The CMU software License Agreement specifies - * the terms and conditions for use and redistribution. - */ - -/* - * This code was written for the Coda filesystem at Carnegie Mellon - * University. Contributers include David Steere, James Kistler, and - * M. Satyanarayanan. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include /* Must come after sys/malloc.h */ -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -/* - * These flags select various performance enhancements. - */ -static int coda_attr_cache = 1; /* Set to cache attributes. */ -static int coda_symlink_cache = 1; /* Set to cache symbolic links. */ -static int coda_access_cache = 1; /* Set to cache some access checks. */ - -/* - * Structure to keep track of vfs calls. - */ -static struct coda_op_stats coda_vnodeopstats[CODA_VNODEOPS_SIZE]; - -#define MARK_ENTRY(op) (coda_vnodeopstats[op].entries++) -#define MARK_INT_SAT(op) (coda_vnodeopstats[op].sat_intrn++) -#define MARK_INT_FAIL(op) (coda_vnodeopstats[op].unsat_intrn++) -#define MARK_INT_GEN(op) (coda_vnodeopstats[op].gen_intrn++) - -/* - * What we are delaying for in printf. - */ -int coda_printf_delay = 0; /* In microseconds */ -int coda_vnop_print_entry = 0; -static int coda_lockdebug = 0; - -/* - * Some FreeBSD details: - * - * codadev_modevent is called at boot time or module load time. - */ -#define ENTRY do { \ - if (coda_vnop_print_entry) \ - myprintf(("Entered %s\n", __func__)); \ -} while (0) - -/* - * Definition of the vnode operation vector. - */ -struct vop_vector coda_vnodeops = { - .vop_default = &default_vnodeops, - .vop_cachedlookup = coda_lookup, /* uncached lookup */ - .vop_lookup = vfs_cache_lookup, /* namecache lookup */ - .vop_create = coda_create, /* create */ - .vop_open = coda_open, /* open */ - .vop_close = coda_close, /* close */ - .vop_access = coda_access, /* access */ - .vop_getattr = coda_getattr, /* getattr */ - .vop_setattr = coda_setattr, /* setattr */ - .vop_read = coda_read, /* read */ - .vop_write = coda_write, /* write */ - .vop_ioctl = coda_ioctl, /* ioctl */ - .vop_fsync = coda_fsync, /* fsync */ - .vop_remove = coda_remove, /* remove */ - .vop_link = coda_link, /* link */ - .vop_rename = coda_rename, /* rename */ - .vop_mkdir = coda_mkdir, /* mkdir */ - .vop_rmdir = coda_rmdir, /* rmdir */ - .vop_symlink = coda_symlink, /* symlink */ - .vop_readdir = coda_readdir, /* readdir */ - .vop_readlink = coda_readlink, /* readlink */ - .vop_inactive = coda_inactive, /* inactive */ - .vop_reclaim = coda_reclaim, /* reclaim */ - .vop_lock1 = coda_lock, /* lock */ - .vop_unlock = coda_unlock, /* unlock */ - .vop_bmap = VOP_EOPNOTSUPP, /* bmap */ - .vop_print = VOP_NULL, /* print */ - .vop_islocked = coda_islocked, /* islocked */ - .vop_pathconf = coda_pathconf, /* pathconf */ - .vop_poll = vop_stdpoll, - .vop_getpages = vop_stdgetpages, /* pager intf.*/ - .vop_putpages = vop_stdputpages, /* pager intf.*/ - .vop_getwritemount = vop_stdgetwritemount, -#if 0 - /* missing */ - .vop_cachedlookup = ufs_lookup, - .vop_whiteout = ufs_whiteout, -#endif - -}; - -static void coda_print_vattr(struct vattr *attr); - -int -coda_vnodeopstats_init(void) -{ - int i; - - for(i=0; ia_vp); - struct cnode *cp = VTOC(*vpp); - int flag = ap->a_mode & (~O_EXCL); - struct ucred *cred = ap->a_cred; - struct thread *td = ap->a_td; - /* locals */ - int error; - struct vnode *vp; - - MARK_ENTRY(CODA_OPEN_STATS); - - /* - * Check for open of control file. - */ - if (IS_CTL_VP(*vpp)) { - /* XXX */ - /* if (WRITEABLE(flag)) */ - if (flag & (FWRITE | O_TRUNC | O_CREAT | O_EXCL)) { - MARK_INT_FAIL(CODA_OPEN_STATS); - return (EACCES); - } - MARK_INT_SAT(CODA_OPEN_STATS); - return (0); - } - error = venus_open(vtomi((*vpp)), &cp->c_fid, flag, cred, - td->td_proc, &vp); - if (error) - return (error); - CODADEBUG(CODA_OPEN, myprintf(("open: vp %p result %d\n", vp, - error));); - - /* - * Save the vnode pointer for the cache file. - */ - if (cp->c_ovp == NULL) { - cp->c_ovp = vp; - } else { - if (cp->c_ovp != vp) - panic("coda_open: cp->c_ovp != ITOV(ip)"); - } - cp->c_ocount++; - - /* - * Flush the attribute cached if writing the file. - */ - if (flag & FWRITE) { - cp->c_owrite++; - cp->c_flags &= ~C_VATTR; - } - - /* - * Open the cache file. - */ - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); - error = VOP_OPEN(vp, flag, cred, td, NULL); - if (error) { - VOP_UNLOCK(vp, 0); - printf("coda_open: VOP_OPEN on container failed %d\n", error); - return (error); - } - (*vpp)->v_object = vp->v_object; - VOP_UNLOCK(vp, 0); - return (0); -} - -/* - * Close the cache file used for I/O and notify Venus. - */ -int -coda_close(struct vop_close_args *ap) -{ - /* true args */ - struct vnode *vp = ap->a_vp; - struct cnode *cp = VTOC(vp); - int flag = ap->a_fflag; - struct ucred *cred = ap->a_cred; - struct thread *td = ap->a_td; - /* locals */ - int error; - - MARK_ENTRY(CODA_CLOSE_STATS); - - /* - * Check for close of control file. - */ - if (IS_CTL_VP(vp)) { - MARK_INT_SAT(CODA_CLOSE_STATS); - return (0); - } - if (cp->c_ovp) { - vn_lock(cp->c_ovp, LK_EXCLUSIVE | LK_RETRY); - /* Do errors matter here? */ - VOP_CLOSE(cp->c_ovp, flag, cred, td); - vput(cp->c_ovp); - } -#ifdef CODA_VERBOSE - else - printf("coda_close: NO container vp %p/cp %p\n", vp, cp); -#endif - if (--cp->c_ocount == 0) - cp->c_ovp = NULL; - - /* - * File was opened for write. - */ - if (flag & FWRITE) - --cp->c_owrite; - if (!IS_UNMOUNTING(cp)) - error = venus_close(vtomi(vp), &cp->c_fid, flag, cred, - td->td_proc); - else - error = ENODEV; - CODADEBUG(CODA_CLOSE, myprintf(("close: result %d\n",error));); - return (error); -} - -int -coda_read(struct vop_read_args *ap) -{ - - ENTRY; - return (coda_rdwr(ap->a_vp, ap->a_uio, UIO_READ, ap->a_ioflag, - ap->a_cred, ap->a_uio->uio_td)); -} - -int -coda_write(struct vop_write_args *ap) -{ - - ENTRY; - return (coda_rdwr(ap->a_vp, ap->a_uio, UIO_WRITE, ap->a_ioflag, - ap->a_cred, ap->a_uio->uio_td)); -} - -int -coda_rdwr(struct vnode *vp, struct uio *uiop, enum uio_rw rw, int ioflag, - struct ucred *cred, struct thread *td) -{ - /* upcall decl */ - /* NOTE: container file operation!!! */ - /* locals */ - struct cnode *cp = VTOC(vp); - struct vnode *cfvp = cp->c_ovp; - int opened_internally = 0; - int error = 0; - - MARK_ENTRY(CODA_RDWR_STATS); - CODADEBUG(CODA_RDWR, myprintf(("coda_rdwr(%d, %p, %zd, %lld, %d)\n", - rw, (void *)uiop->uio_iov->iov_base, uiop->uio_resid, - (long long)uiop->uio_offset, uiop->uio_segflg));); - - /* - * Check for rdwr of control object. - */ - if (IS_CTL_VP(vp)) { - MARK_INT_FAIL(CODA_RDWR_STATS); - return (EINVAL); - } - - /* - * If file is not already open this must be a page {read,write} - * request and we should open it internally. - */ - if (cfvp == NULL) { - opened_internally = 1; - MARK_INT_GEN(CODA_OPEN_STATS); - error = VOP_OPEN(vp, (rw == UIO_READ ? FREAD : FWRITE), cred, - td, NULL); -#ifdef CODA_VERBOSE - printf("coda_rdwr: Internally Opening %p\n", vp); -#endif - if (error) { - printf("coda_rdwr: VOP_OPEN on container failed " - "%d\n", error); - return (error); - } - cfvp = cp->c_ovp; - } - - /* - * Have UFS handle the call. - */ - CODADEBUG(CODA_RDWR, myprintf(("indirect rdwr: fid = %s, refcnt = " - "%d\n", coda_f2s(&cp->c_fid), CTOV(cp)->v_usecount));); - vn_lock(cfvp, LK_EXCLUSIVE | LK_RETRY); - if (rw == UIO_READ) { - error = VOP_READ(cfvp, uiop, ioflag, cred); - } else { - error = VOP_WRITE(cfvp, uiop, ioflag, cred); - /* - * ufs_write updates the vnode_pager_setsize for the - * vnode/object. - * - * XXX: Since we now share vm objects between layers, this is - * probably unnecessary. - */ - { - struct vattr attr; - if (VOP_GETATTR(cfvp, &attr, cred) == 0) - vnode_pager_setsize(vp, attr.va_size); - } - } - VOP_UNLOCK(cfvp, 0); - if (error) - MARK_INT_FAIL(CODA_RDWR_STATS); - else - MARK_INT_SAT(CODA_RDWR_STATS); - - /* - * Do an internal close if necessary. - */ - if (opened_internally) { - MARK_INT_GEN(CODA_CLOSE_STATS); - (void)VOP_CLOSE(vp, (rw == UIO_READ ? FREAD : FWRITE), cred, - td); - } - - /* - * Invalidate cached attributes if writing. - */ - if (rw == UIO_WRITE) - cp->c_flags &= ~C_VATTR; - return (error); -} - -int -coda_ioctl(struct vop_ioctl_args *ap) -{ - /* true args */ - struct vnode *vp = ap->a_vp; - int com = ap->a_command; - caddr_t data = ap->a_data; - int flag = ap->a_fflag; - struct ucred *cred = ap->a_cred; - struct thread *td = ap->a_td; - /* locals */ - int error; - struct vnode *tvp; - struct nameidata ndp; - struct PioctlData *iap = (struct PioctlData *)data; - - MARK_ENTRY(CODA_IOCTL_STATS); - CODADEBUG(CODA_IOCTL, myprintf(("in coda_ioctl on %s\n", iap->path));); - - /* - * Don't check for operation on a dying object, for ctlvp it - * shouldn't matter. - * - * Must be control object to succeed. - */ - if (!IS_CTL_VP(vp)) { - MARK_INT_FAIL(CODA_IOCTL_STATS); - CODADEBUG(CODA_IOCTL, myprintf(("coda_ioctl error: vp != " - "ctlvp"));); - return (EOPNOTSUPP); - } - - /* - * Look up the pathname. - * - * Should we use the name cache here? It would get it from lookupname - * sooner or later anyway, right? - */ - NDINIT(&ndp, LOOKUP, (iap->follow ? FOLLOW : NOFOLLOW), - UIO_USERSPACE, iap->path, td); - error = namei(&ndp); - tvp = ndp.ni_vp; - if (error) { - MARK_INT_FAIL(CODA_IOCTL_STATS); - CODADEBUG(CODA_IOCTL, myprintf(("coda_ioctl error: lookup " - "returns %d\n", error));); - return (error); - } - - /* - * Make sure this is a coda style cnode, but it may be a different - * vfsp. - */ - if (tvp->v_op != &coda_vnodeops) { - vrele(tvp); - NDFREE(&ndp, NDF_ONLY_PNBUF); - MARK_INT_FAIL(CODA_IOCTL_STATS); - CODADEBUG(CODA_IOCTL, - myprintf(("coda_ioctl error: %s not a coda object\n", - iap->path));); - return (EINVAL); - } - if (iap->vi.in_size > VC_MAXDATASIZE || - iap->vi.out_size > VC_MAXDATASIZE) { - NDFREE(&ndp, 0); - return (EINVAL); - } - error = venus_ioctl(vtomi(tvp), &((VTOC(tvp))->c_fid), com, flag, - data, cred, td->td_proc); - if (error) - MARK_INT_FAIL(CODA_IOCTL_STATS); - else - CODADEBUG(CODA_IOCTL, myprintf(("Ioctl returns %d \n", - error));); - vrele(tvp); - NDFREE(&ndp, NDF_ONLY_PNBUF); - return (error); -} - -/* - * To reduce the cost of a user-level venus;we cache attributes in the - * kernel. Each cnode has storage allocated for an attribute. If c_vattr is - * valid, return a reference to it. Otherwise, get the attributes from venus - * and store them in the cnode. There is some question if this method is a - * security leak. But I think that in order to make this call, the user must - * have done a lookup and opened the file, and therefore should already have - * access. - */ -int -coda_getattr(struct vop_getattr_args *ap) -{ - /* true args */ - struct vnode *vp = ap->a_vp; - struct cnode *cp = VTOC(vp); - struct vattr *vap = ap->a_vap; - struct ucred *cred = ap->a_cred; - /* locals */ - struct vnode *convp; - int error, size; - - MARK_ENTRY(CODA_GETATTR_STATS); - if (IS_UNMOUNTING(cp)) - return (ENODEV); - - /* - * Check for getattr of control object. - */ - if (IS_CTL_VP(vp)) { - MARK_INT_FAIL(CODA_GETATTR_STATS); - return (ENOENT); - } - - /* - * Check to see if the attributes have already been cached. - */ - if (VALID_VATTR(cp)) { - CODADEBUG(CODA_GETATTR, myprintf(("attr cache hit: %s\n", - coda_f2s(&cp->c_fid)));); - CODADEBUG(CODA_GETATTR, if (!(codadebug & ~CODA_GETATTR)) - coda_print_vattr(&cp->c_vattr);); - *vap = cp->c_vattr; - MARK_INT_SAT(CODA_GETATTR_STATS); - return (0); - } - error = venus_getattr(vtomi(vp), &cp->c_fid, cred, vap); - if (!error) { - CODADEBUG(CODA_GETATTR, myprintf(("getattr miss %s: result " - "%d\n", coda_f2s(&cp->c_fid), error));); - CODADEBUG(CODA_GETATTR, if (!(codadebug & ~CODA_GETATTR)) - coda_print_vattr(vap);); - - /* - * XXX: Since we now share vm objects between layers, this is - * probably unnecessary. - */ - size = vap->va_size; - convp = cp->c_ovp; - if (convp != NULL) - vnode_pager_setsize(convp, size); - - /* - * If not open for write, store attributes in cnode. - */ - if ((cp->c_owrite == 0) && (coda_attr_cache)) { - cp->c_vattr = *vap; - cp->c_flags |= C_VATTR; - } - } - return (error); -} - -int -coda_setattr(struct vop_setattr_args *ap) -{ - /* true args */ - struct vnode *vp = ap->a_vp; - struct cnode *cp = VTOC(vp); - struct vattr *vap = ap->a_vap; - struct ucred *cred = ap->a_cred; - /* locals */ - struct vnode *convp; - int error, size; - - MARK_ENTRY(CODA_SETATTR_STATS); - - /* - * Check for setattr of control object. - */ - if (IS_CTL_VP(vp)) { - MARK_INT_FAIL(CODA_SETATTR_STATS); - return (ENOENT); - } - if (codadebug & CODADBGMSK(CODA_SETATTR)) - coda_print_vattr(vap); - error = venus_setattr(vtomi(vp), &cp->c_fid, vap, cred); - if (!error) - cp->c_flags &= ~(C_VATTR | C_ACCCACHE); - - /* - * XXX: Since we now share vm objects between layers, this is - * probably unnecessary. - * - * XXX: Shouldn't we only be doing this "set" if C_VATTR remains - * valid after venus_setattr()? - */ - size = vap->va_size; - convp = cp->c_ovp; - if (size != VNOVAL && convp != NULL) - vnode_pager_setsize(convp, size); - CODADEBUG(CODA_SETATTR, myprintf(("setattr %d\n", error));); - return (error); -} - -int -coda_access(struct vop_access_args *ap) -{ - /* true args */ - struct vnode *vp = ap->a_vp; - struct cnode *cp = VTOC(vp); - accmode_t accmode = ap->a_accmode; - struct ucred *cred = ap->a_cred; - struct thread *td = ap->a_td; - /* locals */ - int error; - - MARK_ENTRY(CODA_ACCESS_STATS); - - /* - * Check for access of control object. Only read access is allowed - * on it. - */ - if (IS_CTL_VP(vp)) { - /* - * Bogus hack - all will be marked as successes. - */ - MARK_INT_SAT(CODA_ACCESS_STATS); - return (((accmode & VREAD) && !(accmode & (VWRITE | VEXEC))) - ? 0 : EACCES); - } - - /* - * We maintain a one-entry LRU positive access cache with each cnode. - * In principle we could also track negative results, and for more - * than one uid, but we don't yet. Venus is responsible for - * invalidating this cache as required. - */ - if (coda_access_cache && VALID_ACCCACHE(cp) && - (cred->cr_uid == cp->c_cached_uid) && - (accmode & cp->c_cached_mode) == accmode) { - MARK_INT_SAT(CODA_ACCESS_STATS); - return (0); - } - error = venus_access(vtomi(vp), &cp->c_fid, accmode, cred, td->td_proc); - if (error == 0 && coda_access_cache) { - /*- - * When we have a new successful request, we consider three - * cases: - * - * - No initialized access cache, in which case cache the - * result. - * - Cached result for a different user, in which case we - * replace the entry. - * - Cached result for the same user, in which case we add - * any newly granted rights to the cached mode. - * - * XXXRW: If we ever move to something more interesting than - * uid-based token lookup, we'll need to change this. - */ - cp->c_flags |= C_ACCCACHE; - if (cp->c_cached_uid != cred->cr_uid) { - cp->c_cached_mode = accmode; - cp->c_cached_uid = cred->cr_uid; - } else - cp->c_cached_mode |= accmode; - } - return (error); -} - -int -coda_readlink(struct vop_readlink_args *ap) -{ - /* true args */ - struct vnode *vp = ap->a_vp; - struct cnode *cp = VTOC(vp); - struct uio *uiop = ap->a_uio; - struct ucred *cred = ap->a_cred; - struct thread *td = ap->a_uio->uio_td; - /* locals */ - int error; - char *str; - int len; - - MARK_ENTRY(CODA_READLINK_STATS); - - /* - * Check for readlink of control object. - */ - if (IS_CTL_VP(vp)) { - MARK_INT_FAIL(CODA_READLINK_STATS); - return (ENOENT); - } - if ((coda_symlink_cache) && (VALID_SYMLINK(cp))) { - /* - * Symlink was cached. - */ - uiop->uio_rw = UIO_READ; - error = uiomove(cp->c_symlink, (int)cp->c_symlen, uiop); - if (error) - MARK_INT_FAIL(CODA_READLINK_STATS); - else - MARK_INT_SAT(CODA_READLINK_STATS); - return (error); - } - error = venus_readlink(vtomi(vp), &cp->c_fid, cred, td != NULL ? - td->td_proc : NULL, &str, &len); - if (!error) { - uiop->uio_rw = UIO_READ; - error = uiomove(str, len, uiop); - if (coda_symlink_cache) { - cp->c_symlink = str; - cp->c_symlen = len; - cp->c_flags |= C_SYMLINK; - } else - CODA_FREE(str, len); - } - CODADEBUG(CODA_READLINK, myprintf(("in readlink result %d\n", - error));); - return (error); -} - -int -coda_fsync(struct vop_fsync_args *ap) -{ - /* true args */ - struct vnode *vp = ap->a_vp; - struct cnode *cp = VTOC(vp); - struct thread *td = ap->a_td; - /* locals */ - struct vnode *convp = cp->c_ovp; - int error; - - MARK_ENTRY(CODA_FSYNC_STATS); - - /* - * Check for fsync on an unmounting object. - * - * XXX: Is this comment true on FreeBSD? It seems likely, since - * unmounting is fairly non-atomic. - * - * The NetBSD kernel, in it's infinite wisdom, can try to fsync after - * an unmount has been initiated. This is a Bad Thing, which we have - * to avoid. Not a legitimate failure for stats. - */ - if (IS_UNMOUNTING(cp)) - return (ENODEV); - - /* - * Check for fsync of control object. - */ - if (IS_CTL_VP(vp)) { - MARK_INT_SAT(CODA_FSYNC_STATS); - return (0); - } - if (convp != NULL) { - vn_lock(convp, LK_EXCLUSIVE | LK_RETRY); - VOP_FSYNC(convp, MNT_WAIT, td); - VOP_UNLOCK(convp, 0); - } - - /* - * We see fsyncs with usecount == 1 then usecount == 0. For now we - * ignore them. - */ -#if 0 - VI_LOCK(vp); - if (!vp->v_usecount) { - printf("coda_fsync on vnode %p with %d usecount. " - "c_flags = %x (%x)\n", vp, vp->v_usecount, cp->c_flags, - cp->c_flags&C_PURGING); - } - VI_UNLOCK(vp); -#endif - - /* - * We can expect fsync on any vnode at all if venus is purging it. - * Venus can't very well answer the fsync request, now can it? - * Hopefully, it won't have to, because hopefully, venus preserves - * the (possibly untrue) invariant that it never purges an open - * vnode. Hopefully. - */ - if (cp->c_flags & C_PURGING) - return (0); - - /* XXX: needs research */ - return (0); - error = venus_fsync(vtomi(vp), &cp->c_fid, td->td_proc); - CODADEBUG(CODA_FSYNC, myprintf(("in fsync result %d\n", error));); - return (error); -} - -int -coda_inactive(struct vop_inactive_args *ap) -{ - /* - * XXX - at the moment, inactive doesn't look at cred, and doesn't - * have a proc pointer. Oops. - */ - /* true args */ - struct vnode *vp = ap->a_vp; - struct cnode *cp = VTOC(vp); - struct ucred *cred __attribute__((unused)) = NULL; - struct thread *td __attribute__((unused)) = curthread; - /* upcall decl */ - /* locals */ - - /* - * We don't need to send inactive to venus - DCS. - */ - MARK_ENTRY(CODA_INACTIVE_STATS); - CODADEBUG(CODA_INACTIVE, myprintf(("in inactive, %s, vfsp %p\n", - coda_f2s(&cp->c_fid), vp->v_mount));); - vp->v_object = NULL; - - /* - * If an array has been allocated to hold the symlink, deallocate it. - */ - if ((coda_symlink_cache) && (VALID_SYMLINK(cp))) { - if (cp->c_symlink == NULL) - panic("coda_inactive: null symlink pointer in cnode"); - CODA_FREE(cp->c_symlink, cp->c_symlen); - cp->c_flags &= ~C_SYMLINK; - cp->c_symlen = 0; - } - - /* - * Remove it from the table so it can't be found. - */ - coda_unsave(cp); - if ((struct coda_mntinfo *)(vp->v_mount->mnt_data) == NULL) { - myprintf(("Help! vfsp->vfs_data was NULL, but vnode %p " - "wasn't dying\n", vp)); - panic("badness in coda_inactive\n"); - } - if (IS_UNMOUNTING(cp)) { -#ifdef DEBUG - printf("coda_inactive: IS_UNMOUNTING use %d: vp %p, cp %p\n", - vrefcnt(vp), vp, cp); - if (cp->c_ovp != NULL) - printf("coda_inactive: cp->ovp != NULL use %d: vp " - "%p, cp %p\n", vrefcnt(vp), vp, cp); -#endif - } else - vgone(vp); - MARK_INT_SAT(CODA_INACTIVE_STATS); - return (0); -} - -/* - * Remote filesystem operations having to do with directory manipulation. - */ - -/* - * In FreeBSD, lookup returns the vnode locked. - */ -int -coda_lookup(struct vop_cachedlookup_args *ap) -{ - /* true args */ - struct vnode *dvp = ap->a_dvp; - struct cnode *dcp = VTOC(dvp); - struct vnode **vpp = ap->a_vpp; - /* - * It looks as though ap->a_cnp->ni_cnd->cn_nameptr holds the rest of - * the string to xlate, and that we must try to get at least - * ap->a_cnp->ni_cnd->cn_namelen of those characters to macth. I - * could be wrong. - */ - struct componentname *cnp = ap->a_cnp; - struct ucred *cred = cnp->cn_cred; - struct thread *td = cnp->cn_thread; - /* locals */ - struct cnode *cp; - const char *nm = cnp->cn_nameptr; - int len = cnp->cn_namelen; - struct CodaFid VFid; - int vtype; - int error = 0; - - MARK_ENTRY(CODA_LOOKUP_STATS); - CODADEBUG(CODA_LOOKUP, myprintf(("lookup: %s in %s\n", nm, - coda_f2s(&dcp->c_fid)));); - - /* - * Check for lookup of control object. - */ - if (IS_CTL_NAME(dvp, nm, len)) { - *vpp = coda_ctlvp; - vref(*vpp); - MARK_INT_SAT(CODA_LOOKUP_STATS); - goto exit; - } - if (len+1 > CODA_MAXNAMLEN) { - MARK_INT_FAIL(CODA_LOOKUP_STATS); - CODADEBUG(CODA_LOOKUP, myprintf(("name too long: lookup, " - "%s (%s)\n", coda_f2s(&dcp->c_fid), nm));); - *vpp = NULL; - error = EINVAL; - goto exit; - } - - error = venus_lookup(vtomi(dvp), &dcp->c_fid, nm, len, cred, - td->td_proc, &VFid, &vtype); - if (error) { - MARK_INT_FAIL(CODA_LOOKUP_STATS); - CODADEBUG(CODA_LOOKUP, myprintf(("lookup error on %s " - "(%s)%d\n", coda_f2s(&dcp->c_fid), nm, error));); - *vpp = NULL; - } else { - MARK_INT_SAT(CODA_LOOKUP_STATS); - CODADEBUG(CODA_LOOKUP, myprintf(("lookup: %s type %o " - "result %d\n", coda_f2s(&VFid), vtype, error));); - cp = make_coda_node(&VFid, dvp->v_mount, vtype); - *vpp = CTOV(cp); - - /* - * Enter the new vnode in the namecache only if the top bit - * isn't set. - * - * And don't enter a new vnode for an invalid one! - */ - if (!(vtype & CODA_NOCACHE) && (cnp->cn_flags & MAKEENTRY)) - cache_enter(dvp, *vpp, cnp); - } -exit: - /* - * If we are creating, and this was the last name to be looked up, - * and the error was ENOENT, then there really shouldn't be an error - * and we can make the leaf NULL and return success. Since this is - * supposed to work under Mach as well as FreeBSD, we're leaving this - * fn wrapped. We also must tell lookup/namei that we need to save - * the last component of the name. (Create will have to free the - * name buffer later...lucky us...). - */ - if (((cnp->cn_nameiop == CREATE) || (cnp->cn_nameiop == RENAME)) - && (cnp->cn_flags & ISLASTCN) && (error == ENOENT)) { - error = EJUSTRETURN; - cnp->cn_flags |= SAVENAME; - *ap->a_vpp = NULL; - } - - /* - * If we are removing, and we are at the last element, and we found - * it, then we need to keep the name around so that the removal will - * go ahead as planned. Unfortunately, this will probably also lock - * the to-be-removed vnode, which may or may not be a good idea. - * I'll have to look at the bits of coda_remove to make sure. We'll - * only save the name if we did in fact find the name, otherwise - * coda_remove won't have a chance to free the pathname. - */ - if ((cnp->cn_nameiop == DELETE) && (cnp->cn_flags & ISLASTCN) - && !error) - cnp->cn_flags |= SAVENAME; - - /* - * If the lookup went well, we need to (potentially?) unlock the - * parent, and lock the child. We are only responsible for checking - * to see if the parent is supposed to be unlocked before we return. - * We must always lock the child (provided there is one, and (the - * parent isn't locked or it isn't the same as the parent.) Simple, - * huh? We can never leave the parent locked unless we are ISLASTCN. - */ - if (!error || (error == EJUSTRETURN)) { - if (cnp->cn_flags & ISDOTDOT) { - VOP_UNLOCK(dvp, 0); - /* - * The parent is unlocked. As long as there is a - * child, lock it without bothering to check anything - * else. - */ - if (*ap->a_vpp) - vn_lock(*ap->a_vpp, LK_EXCLUSIVE | LK_RETRY); - vn_lock(dvp, LK_RETRY|LK_EXCLUSIVE); - } else { - /* - * The parent is locked, and may be the same as the - * child. If different, go ahead and lock it. - */ - if (*ap->a_vpp && (*ap->a_vpp != dvp)) - vn_lock(*ap->a_vpp, LK_EXCLUSIVE | LK_RETRY); - } - } else { - /* - * If the lookup failed, we need to ensure that the leaf is - * NULL. - * - * Don't change any locking? - */ - *ap->a_vpp = NULL; - } - return (error); -} - -/*ARGSUSED*/ -int -coda_create(struct vop_create_args *ap) -{ - /* true args */ - struct vnode *dvp = ap->a_dvp; - struct cnode *dcp = VTOC(dvp); - struct vattr *va = ap->a_vap; - int exclusive = 1; - int mode = ap->a_vap->va_mode; - struct vnode **vpp = ap->a_vpp; - struct componentname *cnp = ap->a_cnp; - struct ucred *cred = cnp->cn_cred; - struct thread *td = cnp->cn_thread; - /* locals */ - int error; - struct cnode *cp; - const char *nm = cnp->cn_nameptr; - int len = cnp->cn_namelen; - struct CodaFid VFid; - struct vattr attr; - - MARK_ENTRY(CODA_CREATE_STATS); - - /* - * All creates are exclusive XXX. - * - * I'm assuming the 'mode' argument is the file mode bits XXX. - * - * Check for create of control object. - */ - if (IS_CTL_NAME(dvp, nm, len)) { - *vpp = (struct vnode *)0; - MARK_INT_FAIL(CODA_CREATE_STATS); - return (EACCES); - } - error = venus_create(vtomi(dvp), &dcp->c_fid, nm, len, exclusive, - mode, va, cred, td->td_proc, &VFid, &attr); - if (!error) { - /* - * If this is an exclusive create, panic if the file already - * exists. - * - * Venus should have detected the file and reported EEXIST. - */ - if ((exclusive == 1) && (coda_find(&VFid) != NULL)) - panic("cnode existed for newly created file!"); - cp = make_coda_node(&VFid, dvp->v_mount, attr.va_type); - *vpp = CTOV(cp); - - /* - * Update va to reflect the new attributes. - */ - (*va) = attr; - - /* - * Update the attribute cache and mark it as valid. - */ - if (coda_attr_cache) { - VTOC(*vpp)->c_vattr = attr; - VTOC(*vpp)->c_flags |= C_VATTR; - } - - /* - * Invalidate the parent's attr cache, the modification time - * has changed. - */ - VTOC(dvp)->c_flags &= ~C_VATTR; - cache_enter(dvp, *vpp, cnp); - CODADEBUG(CODA_CREATE, myprintf(("create: %s, result %d\n", - coda_f2s(&VFid), error));); - } else { - *vpp = (struct vnode *)0; - CODADEBUG(CODA_CREATE, myprintf(("create error %d\n", - error));); - } - if (!error) { - if (cnp->cn_flags & MAKEENTRY) - cache_enter(dvp, *vpp, cnp); - if (cnp->cn_flags & LOCKLEAF) - vn_lock(*ap->a_vpp, LK_EXCLUSIVE | LK_RETRY); - } else if (error == ENOENT) { - /* - * XXXRW: We only enter a negative entry if ENOENT is - * returned, not other errors. But will Venus invalidate dvp - * properly in all cases when new files appear via the - * network rather than a local operation? - */ - if (cnp->cn_flags & MAKEENTRY) - cache_enter(dvp, NULL, cnp); - } - return (error); -} - -int -coda_remove(struct vop_remove_args *ap) -{ - /* true args */ - struct vnode *vp = ap->a_vp; - struct vnode *dvp = ap->a_dvp; - struct cnode *cp = VTOC(dvp); - struct componentname *cnp = ap->a_cnp; - struct ucred *cred = cnp->cn_cred; - struct thread *td = cnp->cn_thread; - /* locals */ - int error; - const char *nm = cnp->cn_nameptr; - int len = cnp->cn_namelen; -#if 0 - struct cnode *tp; -#endif - - MARK_ENTRY(CODA_REMOVE_STATS); - CODADEBUG(CODA_REMOVE, myprintf(("remove: %s in %s\n", nm, - coda_f2s(&cp->c_fid)));); - - /* - * Check for remove of control object. - */ - if (IS_CTL_NAME(dvp, nm, len)) { - MARK_INT_FAIL(CODA_REMOVE_STATS); - return (ENOENT); - } - - /* - * Invalidate the parent's attr cache, the modification time has - * changed. We don't yet know if the last reference to the file is - * being removed, but we do know the reference count on the child has - * changed, so invalidate its attr cache also. - */ - VTOC(dvp)->c_flags &= ~C_VATTR; - VTOC(vp)->c_flags &= ~(C_VATTR | C_ACCCACHE); - error = venus_remove(vtomi(dvp), &cp->c_fid, nm, len, cred, - td->td_proc); - cache_purge(vp); - CODADEBUG(CODA_REMOVE, myprintf(("in remove result %d\n",error));); - return (error); -} - -int -coda_link(struct vop_link_args *ap) -{ - /* true args */ - struct vnode *vp = ap->a_vp; - struct cnode *cp = VTOC(vp); - struct vnode *tdvp = ap->a_tdvp; - struct cnode *tdcp = VTOC(tdvp); - struct componentname *cnp = ap->a_cnp; - struct ucred *cred = cnp->cn_cred; - struct thread *td = cnp->cn_thread; - /* locals */ - int error; - const char *nm = cnp->cn_nameptr; - int len = cnp->cn_namelen; - - MARK_ENTRY(CODA_LINK_STATS); - - if (codadebug & CODADBGMSK(CODA_LINK)) { - myprintf(("nb_link: vp fid: %s\n", coda_f2s(&cp->c_fid))); - myprintf(("nb_link: tdvp fid: %s)\n", - coda_f2s(&tdcp->c_fid))); - } - if (codadebug & CODADBGMSK(CODA_LINK)) { - myprintf(("link: vp fid: %s\n", coda_f2s(&cp->c_fid))); - myprintf(("link: tdvp fid: %s\n", coda_f2s(&tdcp->c_fid))); - } - - /* - * Check for link to/from control object. - */ - if (IS_CTL_NAME(tdvp, nm, len) || IS_CTL_VP(vp)) { - MARK_INT_FAIL(CODA_LINK_STATS); - return (EACCES); - } - error = venus_link(vtomi(vp), &cp->c_fid, &tdcp->c_fid, nm, len, - cred, td->td_proc); - - /* - * Invalidate the parent's attr cache, the modification time has - * changed. - */ - VTOC(tdvp)->c_flags &= ~C_VATTR; - VTOC(vp)->c_flags &= ~C_VATTR; - CODADEBUG(CODA_LINK, myprintf(("in link result %d\n",error));); - return (error); -} - -int -coda_rename(struct vop_rename_args *ap) -{ - /* true args */ - struct vnode *fvp = ap->a_fvp; - struct vnode *tvp = ap->a_tvp; - struct vnode *odvp = ap->a_fdvp; - struct cnode *odcp = VTOC(odvp); - struct componentname *fcnp = ap->a_fcnp; - struct vnode *ndvp = ap->a_tdvp; - struct cnode *ndcp = VTOC(ndvp); - struct componentname *tcnp = ap->a_tcnp; - struct ucred *cred = fcnp->cn_cred; - struct thread *td = fcnp->cn_thread; - /* true args */ - int error; - const char *fnm = fcnp->cn_nameptr; - int flen = fcnp->cn_namelen; - const char *tnm = tcnp->cn_nameptr; - int tlen = tcnp->cn_namelen; - - MARK_ENTRY(CODA_RENAME_STATS); - - /* - * Check for rename involving control object. - */ - if (IS_CTL_NAME(odvp, fnm, flen) || IS_CTL_NAME(ndvp, tnm, tlen)) { - MARK_INT_FAIL(CODA_RENAME_STATS); - return (EACCES); - } - - /* - * Remove the entries for both source and target directories, which - * should catch references to the children. Perhaps we could purge - * less? - */ - cache_purge(odvp); - cache_purge(ndvp); - - /* - * Invalidate parent directories as modification times have changed. - * Invalidate access cache on renamed file as rights may have - * changed. - */ - VTOC(odvp)->c_flags &= ~C_VATTR; - VTOC(ndvp)->c_flags &= ~C_VATTR; - VTOC(fvp)->c_flags &= ~C_ACCCACHE; - if (flen+1 > CODA_MAXNAMLEN) { - MARK_INT_FAIL(CODA_RENAME_STATS); - error = EINVAL; - goto exit; - } - if (tlen+1 > CODA_MAXNAMLEN) { - MARK_INT_FAIL(CODA_RENAME_STATS); - error = EINVAL; - goto exit; - } - error = venus_rename(vtomi(odvp), &odcp->c_fid, &ndcp->c_fid, fnm, - flen, tnm, tlen, cred, td->td_proc); -exit: - CODADEBUG(CODA_RENAME, myprintf(("in rename result %d\n",error));); - - /* - * Update namecache to reflect that the names of various objects may - * have changed (or gone away entirely). - */ - cache_purge(fvp); - cache_purge(tvp); - - /* - * Release parents first, then children. - */ - vrele(odvp); - if (tvp) { - if (tvp == ndvp) - vrele(ndvp); - else - vput(ndvp); - vput(tvp); - } else - vput(ndvp); - vrele(fvp); - return (error); -} - -int -coda_mkdir(struct vop_mkdir_args *ap) -{ - /* true args */ - struct vnode *dvp = ap->a_dvp; - struct cnode *dcp = VTOC(dvp); - struct componentname *cnp = ap->a_cnp; - struct vattr *va = ap->a_vap; - struct vnode **vpp = ap->a_vpp; - struct ucred *cred = cnp->cn_cred; - struct thread *td = cnp->cn_thread; - /* locals */ - int error; - const char *nm = cnp->cn_nameptr; - int len = cnp->cn_namelen; - struct cnode *cp; - struct CodaFid VFid; - struct vattr ova; - - MARK_ENTRY(CODA_MKDIR_STATS); - - /* - * Check for mkdir of target object. - */ - if (IS_CTL_NAME(dvp, nm, len)) { - *vpp = (struct vnode *)0; - MARK_INT_FAIL(CODA_MKDIR_STATS); - return (EACCES); - } - if (len+1 > CODA_MAXNAMLEN) { - *vpp = (struct vnode *)0; - MARK_INT_FAIL(CODA_MKDIR_STATS); - return (EACCES); - } - error = venus_mkdir(vtomi(dvp), &dcp->c_fid, nm, len, va, cred, - td->td_proc, &VFid, &ova); - if (!error) { - if (coda_find(&VFid) != NULL) - panic("cnode existed for newly created directory!"); - cp = make_coda_node(&VFid, dvp->v_mount, va->va_type); - *vpp = CTOV(cp); - - /* - * Enter the new vnode in the Name Cache. - */ - if (cnp->cn_flags & MAKEENTRY) - cache_enter(dvp, *vpp, cnp); - - /* - * Update the attr cache and mark as valid. - */ - if (coda_attr_cache) { - VTOC(*vpp)->c_vattr = ova; - VTOC(*vpp)->c_flags |= C_VATTR; - } - - /* - * Invalidate the parent's attr cache, the modification time - * has changed. - */ - VTOC(dvp)->c_flags &= ~C_VATTR; - vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY); - CODADEBUG( CODA_MKDIR, myprintf(("mkdir: %s result %d\n", - coda_f2s(&VFid), error));); - } else { - *vpp = NULL; - CODADEBUG(CODA_MKDIR, myprintf(("mkdir error %d\n",error));); - } - return (error); -} - -int -coda_rmdir(struct vop_rmdir_args *ap) -{ - /* true args */ - struct vnode *vp = ap->a_vp; - struct vnode *dvp = ap->a_dvp; - struct cnode *dcp = VTOC(dvp); - struct componentname *cnp = ap->a_cnp; - struct ucred *cred = cnp->cn_cred; - struct thread *td = cnp->cn_thread; - /* true args */ - int error; - const char *nm = cnp->cn_nameptr; - int len = cnp->cn_namelen; -#if 0 - struct cnode *cp; -#endif - - MARK_ENTRY(CODA_RMDIR_STATS); - - /* - * Check for rmdir of control object. - */ - if (IS_CTL_NAME(dvp, nm, len)) { - MARK_INT_FAIL(CODA_RMDIR_STATS); - return (ENOENT); - } - - /* - * Possibly somewhat conservative purging, perhaps we just need to - * purge vp? - */ - cache_purge(dvp); - cache_purge(vp); - - /* - * Invalidate the parent's attr cache, the modification time has - * changed. - */ - dcp->c_flags &= ~C_VATTR; - error = venus_rmdir(vtomi(dvp), &dcp->c_fid, nm, len, cred, - td->td_proc); - CODADEBUG(CODA_RMDIR, myprintf(("in rmdir result %d\n", error));); - return (error); -} - -int -coda_symlink(struct vop_symlink_args *ap) -{ - /* true args */ - struct vnode *tdvp = ap->a_dvp; - struct cnode *tdcp = VTOC(tdvp); - struct componentname *cnp = ap->a_cnp; - struct vattr *tva = ap->a_vap; - char *path = ap->a_target; - struct ucred *cred = cnp->cn_cred; - struct thread *td = cnp->cn_thread; - struct vnode **vpp = ap->a_vpp; - /* locals */ - int error; - - /*- - * XXX I'm assuming the following things about coda_symlink's - * arguments: - * t(foo) is the new name/parent/etc being created. - * lname is the contents of the new symlink. - */ - char *nm = cnp->cn_nameptr; - int len = cnp->cn_namelen; - int plen = strlen(path); - - /* - * Here's the strategy for the moment: perform the symlink, then do a - * lookup to grab the resulting vnode. I know this requires two - * communications with Venus for a new sybolic link, but that's the - * way the ball bounces. I don't yet want to change the way the Mach - * symlink works. When Mach support is deprecated, we should change - * symlink so that the common case returns the resultant vnode in a - * vpp argument. - */ - MARK_ENTRY(CODA_SYMLINK_STATS); - - /* - * Check for symlink of control object. - */ - if (IS_CTL_NAME(tdvp, nm, len)) { - MARK_INT_FAIL(CODA_SYMLINK_STATS); - return (EACCES); - } - if (plen+1 > CODA_MAXPATHLEN) { - MARK_INT_FAIL(CODA_SYMLINK_STATS); - return (EINVAL); - } - if (len+1 > CODA_MAXNAMLEN) { - MARK_INT_FAIL(CODA_SYMLINK_STATS); - error = EINVAL; - goto exit; - } - error = venus_symlink(vtomi(tdvp), &tdcp->c_fid, path, plen, nm, len, - tva, cred, td->td_proc); - - /* - * Invalidate the parent's attr cache, the modification time has - * changed. - */ - tdcp->c_flags &= ~C_VATTR; - if (error == 0) - error = VOP_LOOKUP(tdvp, vpp, cnp); -exit: - CODADEBUG(CODA_SYMLINK, myprintf(("in symlink result %d\n",error));); - return (error); -} - -/* - * Read directory entries. - * - * XXX: This forwards the operator straight to the cache vnode using - * VOP_READDIR(), rather than calling venus_readdir(). Why? - */ -int -coda_readdir(struct vop_readdir_args *ap) -{ - /* true args */ - struct vnode *vp = ap->a_vp; - struct cnode *cp = VTOC(vp); - struct uio *uiop = ap->a_uio; - struct ucred *cred = ap->a_cred; - int *eofflag = ap->a_eofflag; - u_long **cookies = ap->a_cookies; - int *ncookies = ap->a_ncookies; - struct thread *td = ap->a_uio->uio_td; - /* upcall decl */ - /* locals */ - int error = 0; - int opened_internally = 0; - - MARK_ENTRY(CODA_READDIR_STATS); - CODADEBUG(CODA_READDIR, myprintf(("coda_readdir(%p, %zd, %lld, %d)\n", - (void *)uiop->uio_iov->iov_base, uiop->uio_resid, - (long long)uiop->uio_offset, uiop->uio_segflg));); - - /* - * Check for readdir of control object. - */ - if (IS_CTL_VP(vp)) { - MARK_INT_FAIL(CODA_READDIR_STATS); - return (ENOENT); - } - - /* - * If directory is not already open do an "internal open" on it. - * - * XXX: Why would this happen? For files, there's memory mapping, - * execution, and other kernel access paths such as ktrace. For - * directories, it is less clear. - */ - if (cp->c_ovp == NULL) { - opened_internally = 1; - MARK_INT_GEN(CODA_OPEN_STATS); - error = VOP_OPEN(vp, FREAD, cred, td, NULL); - printf("coda_readdir: Internally Opening %p\n", vp); - if (error) { - printf("coda_readdir: VOP_OPEN on container failed " - "%d\n", error); - return (error); - } - } - - /* - * Have UFS handle the call. - */ - CODADEBUG(CODA_READDIR, myprintf(("indirect readdir: fid = %s, " - "refcnt = %d\n", coda_f2s(&cp->c_fid), vp->v_usecount));); - vn_lock(cp->c_ovp, LK_SHARED | LK_RETRY); - error = VOP_READDIR(cp->c_ovp, uiop, cred, eofflag, ncookies, - cookies); - VOP_UNLOCK(cp->c_ovp, 0); - if (error) - MARK_INT_FAIL(CODA_READDIR_STATS); - else - MARK_INT_SAT(CODA_READDIR_STATS); - - /* - * Do an "internal close" if necessary. - */ - if (opened_internally) { - MARK_INT_GEN(CODA_CLOSE_STATS); - (void)VOP_CLOSE(vp, FREAD, cred, td); - } - return (error); -} - -int -coda_reclaim(struct vop_reclaim_args *ap) -{ - /* true args */ - struct vnode *vp = ap->a_vp; - struct cnode *cp = VTOC(vp); - /* upcall decl */ - /* locals */ - - /* - * Forced unmount/flush will let vnodes with non-zero use be - * destroyed! - */ - ENTRY; - - if (IS_UNMOUNTING(cp)) { -#ifdef DEBUG - if (VTOC(vp)->c_ovp) { - if (IS_UNMOUNTING(cp)) - printf("coda_reclaim: c_ovp not void: vp " - "%p, cp %p\n", vp, cp); - } -#endif - } - cache_purge(vp); - coda_free(VTOC(vp)); - vp->v_data = NULL; - vp->v_object = NULL; - return (0); -} - -int -coda_lock(struct vop_lock1_args *ap) -{ - /* true args */ - struct vnode *vp = ap->a_vp; - struct cnode *cp = VTOC(vp); - /* upcall decl */ - /* locals */ - - ENTRY; - if ((ap->a_flags & LK_INTERLOCK) == 0) { - VI_LOCK(vp); - ap->a_flags |= LK_INTERLOCK; - } - if (coda_lockdebug) - myprintf(("Attempting lock on %s\n", coda_f2s(&cp->c_fid))); - return (vop_stdlock(ap)); -} - -int -coda_unlock(struct vop_unlock_args *ap) -{ - /* true args */ - struct vnode *vp = ap->a_vp; - struct cnode *cp = VTOC(vp); - /* upcall decl */ - /* locals */ - - ENTRY; - if (coda_lockdebug) - myprintf(("Attempting unlock on %s\n", - coda_f2s(&cp->c_fid))); - return (vop_stdunlock(ap)); -} - -int -coda_islocked(struct vop_islocked_args *ap) -{ - /* true args */ - - ENTRY; - return (vop_stdislocked(ap)); -} - -static void -coda_print_vattr(struct vattr *attr) -{ - char *typestr; - - switch (attr->va_type) { - case VNON: - typestr = "VNON"; - break; - - case VREG: - typestr = "VREG"; - break; - - case VDIR: - typestr = "VDIR"; - break; - - case VBLK: - typestr = "VBLK"; - break; - - case VCHR: - typestr = "VCHR"; - break; - - case VLNK: - typestr = "VLNK"; - break; - - case VSOCK: - typestr = "VSCK"; - break; - - case VFIFO: - typestr = "VFFO"; - break; - - case VBAD: - typestr = "VBAD"; - break; - - default: - typestr = "????"; - break; - } - myprintf(("attr: type %s mode %d uid %d gid %d fsid %d rdev %d\n", - typestr, (int)attr->va_mode, (int)attr->va_uid, - (int)attr->va_gid, (int)attr->va_fsid, (int)attr->va_rdev)); - myprintf((" fileid %d nlink %d size %d blocksize %d bytes %d\n", - (int)attr->va_fileid, (int)attr->va_nlink, (int)attr->va_size, - (int)attr->va_blocksize,(int)attr->va_bytes)); - myprintf((" gen %ld flags %ld vaflags %d\n", attr->va_gen, - attr->va_flags, attr->va_vaflags)); - myprintf((" atime sec %d nsec %d\n", (int)attr->va_atime.tv_sec, - (int)attr->va_atime.tv_nsec)); - myprintf((" mtime sec %d nsec %d\n", (int)attr->va_mtime.tv_sec, - (int)attr->va_mtime.tv_nsec)); - myprintf((" ctime sec %d nsec %d\n", (int)attr->va_ctime.tv_sec, - (int)attr->va_ctime.tv_nsec)); -} - -/* - * How to print a ucred. - */ -void -coda_print_cred(struct ucred *cred) -{ - int i; - - myprintf(("ref %d\tuid %d\n",cred->cr_ref,cred->cr_uid)); - for (i=0; i < cred->cr_ngroups; i++) - myprintf(("\tgroup %d: (%d)\n",i,cred->cr_groups[i])); - myprintf(("\n")); -} - -/* - * Return a vnode for the given fid. If no cnode exists for this fid create - * one and put it in a table hashed by coda_f2i(). If the cnode for this fid - * is already in the table return it (ref count is incremented by coda_find. - * The cnode will be flushed from the table when coda_inactive calls - * coda_unsave. - */ -struct cnode * -make_coda_node(struct CodaFid *fid, struct mount *vfsp, short type) -{ - struct cnode *cp; - struct vnode *vp; - int err; - - /* - * XXXRW: This really needs a moderate amount of reworking. We need - * to properly tolerate failures of getnewvnode() and insmntque(), - * and callers need to be able to accept an error back from - * make_coda_node. There may also be more general issues in how we - * handle forced unmount. Finally, if/when Coda loses its dependency - * on Giant, the ordering of this needs rethinking. - */ - cp = coda_find(fid); - if (cp != NULL) { - vref(CTOV(cp)); - return (cp); - } - cp = coda_alloc(); - cp->c_fid = *fid; - err = getnewvnode("coda", vfsp, &coda_vnodeops, &vp); - if (err) - panic("coda: getnewvnode returned error %d\n", err); - vp->v_data = cp; - vp->v_type = type; - cp->c_vnode = vp; - coda_save(cp); - err = insmntque(vp, vfsp); - if (err != 0) - printf("coda: insmntque failed: error %d", err); - return (cp); -} - -int -coda_pathconf(struct vop_pathconf_args *ap) -{ - - switch (ap->a_name) { - case _PC_NAME_MAX: - *ap->a_retval = CODA_MAXNAMLEN; - return (0); - - case _PC_PATH_MAX: - *ap->a_retval = CODA_MAXPATHLEN; - return (0); - - default: - return (vop_stdpathconf(ap)); - } -} diff --git a/sys/fs/coda/coda_vnops.h b/sys/fs/coda/coda_vnops.h deleted file mode 100644 index e43b09fb9b9..00000000000 --- a/sys/fs/coda/coda_vnops.h +++ /dev/null @@ -1,84 +0,0 @@ -/*- - * - * Coda: an Experimental Distributed File System - * Release 3.1 - * - * Copyright (c) 1987-1998 Carnegie Mellon University - * All Rights Reserved - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation, and - * that credit is given to Carnegie Mellon University in all documents - * and publicity pertaining to direct or indirect use of this code or its - * derivatives. - * - * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, - * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS - * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON - * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER - * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF - * ANY DERIVATIVE WORK. - * - * Carnegie Mellon encourages users of this software to return any - * improvements or extensions that they make, and to grant Carnegie - * Mellon the rights to redistribute these changes without encumbrance. - * - * @(#) src/sys/coda/coda_vnops.h,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $ - * $FreeBSD$ - */ - -/* - * Mach Operating System - * Copyright (c) 1990 Carnegie-Mellon University - * Copyright (c) 1989 Carnegie-Mellon University - * All rights reserved. The CMU software License Agreement specifies - * the terms and conditions for use and redistribution. - */ - -/* - * This code was written for the Coda filesystem at Carnegie Mellon - * University. Contributers include David Steere, James Kistler, and - * M. Satyanarayanan. - */ - -#ifndef _CODA_VNOPS_H_ -#define _CODA_VNOPS_H_ - -/* - * FreeBSD interfaces to the vnodeops. - */ -vop_open_t coda_open; -vop_close_t coda_close; -vop_read_t coda_read; -vop_write_t coda_write; -vop_ioctl_t coda_ioctl; -vop_getattr_t coda_getattr; -vop_setattr_t coda_setattr; -vop_access_t coda_access; -vop_readlink_t coda_readlink; -vop_fsync_t coda_fsync; -vop_inactive_t coda_inactive; -vop_cachedlookup_t coda_lookup; -vop_create_t coda_create; -vop_remove_t coda_remove; -vop_link_t coda_link; -vop_rename_t coda_rename; -vop_mkdir_t coda_mkdir; -vop_rmdir_t coda_rmdir; -vop_symlink_t coda_symlink; -vop_readdir_t coda_readdir; -vop_strategy_t coda_strategy; -vop_reclaim_t coda_reclaim; -vop_lock1_t coda_lock; -vop_unlock_t coda_unlock; -vop_islocked_t coda_islocked; -vop_pathconf_t coda_pathconf; - -int coda_rdwr(struct vnode *vp, struct uio *uiop, enum uio_rw rw, - int ioflag, struct ucred *cred, struct thread *td); -void coda_print_cred(struct ucred *cred); - -#endif /* !_CODA_VNOPS_H_ */ diff --git a/sys/modules/coda/Makefile b/sys/modules/coda/Makefile deleted file mode 100644 index ebcb39c2055..00000000000 --- a/sys/modules/coda/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# $FreeBSD$ - -.PATH: ${.CURDIR}/../../fs/coda - -KMOD= coda -SRCS= vnode_if.h \ - coda_fbsd.c coda_psdev.c coda_subr.c coda_venus.c coda_vfsops.c \ - coda_vnops.c opt_coda.h - -.include diff --git a/sys/modules/coda5/Makefile b/sys/modules/coda5/Makefile deleted file mode 100644 index f9aea097a7f..00000000000 --- a/sys/modules/coda5/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# $FreeBSD$ - -.PATH: ${.CURDIR}/../../fs/coda - -KMOD= coda5 -SRCS= vnode_if.h \ - coda_fbsd.c coda_psdev.c coda_subr.c \ - coda_venus.c coda_vfsops.c coda_vnops.c \ - opt_coda.h - -CFLAGS+= -DCODA5_MODULE - -.include From 4eb0218ace065ab5b8311bab49533b62d50fd3f5 Mon Sep 17 00:00:00 2001 From: Attilio Rao Date: Sat, 2 Mar 2013 16:43:28 +0000 Subject: [PATCH 0539/1476] Garbage collect PORTALFS bits which are now completely disconnected from the tree since few months. This patch is not targeted for MFC. --- ObsoleteFiles.inc | 7 + share/examples/portal/README | 65 --- share/examples/portal/portal.conf | 3 - sys/fs/portalfs/portal.h | 67 --- sys/fs/portalfs/portal_vfsops.c | 263 ---------- sys/fs/portalfs/portal_vnops.c | 586 ----------------------- sys/modules/portalfs/Makefile | 10 - usr.sbin/mount_portalfs/Makefile | 15 - usr.sbin/mount_portalfs/activate.c | 195 -------- usr.sbin/mount_portalfs/conf.c | 318 ------------ usr.sbin/mount_portalfs/cred.c | 75 --- usr.sbin/mount_portalfs/mount_portalfs.8 | 216 --------- usr.sbin/mount_portalfs/mount_portalfs.c | 281 ----------- usr.sbin/mount_portalfs/pathnames.h | 40 -- usr.sbin/mount_portalfs/portal.conf | 7 - usr.sbin/mount_portalfs/portald.h | 86 ---- usr.sbin/mount_portalfs/pt_conf.c | 50 -- usr.sbin/mount_portalfs/pt_exec.c | 50 -- usr.sbin/mount_portalfs/pt_file.c | 91 ---- usr.sbin/mount_portalfs/pt_pipe.c | 229 --------- usr.sbin/mount_portalfs/pt_tcp.c | 157 ------ usr.sbin/mount_portalfs/pt_tcplisten.c | 201 -------- 22 files changed, 7 insertions(+), 3005 deletions(-) delete mode 100644 share/examples/portal/README delete mode 100644 share/examples/portal/portal.conf delete mode 100644 sys/fs/portalfs/portal.h delete mode 100644 sys/fs/portalfs/portal_vfsops.c delete mode 100644 sys/fs/portalfs/portal_vnops.c delete mode 100644 sys/modules/portalfs/Makefile delete mode 100644 usr.sbin/mount_portalfs/Makefile delete mode 100644 usr.sbin/mount_portalfs/activate.c delete mode 100644 usr.sbin/mount_portalfs/conf.c delete mode 100644 usr.sbin/mount_portalfs/cred.c delete mode 100644 usr.sbin/mount_portalfs/mount_portalfs.8 delete mode 100644 usr.sbin/mount_portalfs/mount_portalfs.c delete mode 100644 usr.sbin/mount_portalfs/pathnames.h delete mode 100644 usr.sbin/mount_portalfs/portal.conf delete mode 100644 usr.sbin/mount_portalfs/portald.h delete mode 100644 usr.sbin/mount_portalfs/pt_conf.c delete mode 100644 usr.sbin/mount_portalfs/pt_exec.c delete mode 100644 usr.sbin/mount_portalfs/pt_file.c delete mode 100644 usr.sbin/mount_portalfs/pt_pipe.c delete mode 100644 usr.sbin/mount_portalfs/pt_tcp.c delete mode 100644 usr.sbin/mount_portalfs/pt_tcplisten.c diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index d42b2dc0233..540ae930617 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -38,6 +38,13 @@ # xargs -n1 | sort | uniq -d; # done +# 20130302: PORTALFS support removed +OLD_FILES+=usr/include/fs/portalfs/portal.h +OLD_DIRS+=usr/include/fs/portalfs +OLD_FILES+=usr/share/examples/portal/README +OLD_FILES+=usr/share/examples/portal/portal.conf +OLD_DIRS+=usr/share/examples/portal +OLD_FILES+=usr/share/man/man8/mount_portalfs.8.gz # 20130302: CODAFS support removed OLD_FILES+=usr/share/man/man4/coda.4.gz # 20130302: XFS support removed diff --git a/share/examples/portal/README b/share/examples/portal/README deleted file mode 100644 index d8dc1fc6aee..00000000000 --- a/share/examples/portal/README +++ /dev/null @@ -1,65 +0,0 @@ -$FreeBSD$ - -This contains a couple of examples for using the portal filing system. - -The portal file system provides a way of obtaining a file descriptor -to a filesystem object (i.e. something that is accessed by open(2), -pipe(2), socket(2) or socketpair(2)) via the filesystem namespace. -At present the only file descriptor supported are TCP sockets and -files. - -NOTE!!!! The portal file system is experimental in nature and should -not be considered secure, use with caution. - -First off mount the filesystem using something like: - -# mount_portalfs /usr/share/examples/portal/portal.conf /p - -Then you should be able to do things like -# cat /p/tcp/localhost/daytime -Sun Nov 22 17:50:09 1998 -(assuming inetd is running the daytime service, by default it is off) - -Welcome to FreeBSD! - -# mkdir -p /tmp/root -# cd /tmp/root -# mkdir bin p -# cp /bin/sh /bin/cat bin -# mount_portalfs /usr/share/examples/portal/portal.conf /tmp/root/p -# chroot /tmp/root -# pwd -/ -# echo * -bin p -# cat /etc/motd -cat: /etc/motd: No such file or directory -# cat /p/fs/etc/motd -FreeBSD 2.2.6-RELEASE (COMPUTER) #0: Sat Aug 22 17:11:37 BST 1998 - -Welcome to FreeBSD! - -Finally, a very simple example of the listening server is available, -fire up two xterms. In the first - -xterm-1$ cat /p/tcplisten/ANY/6666 -(the ANY is a wildcard just like using INADDR_ANY, any resolvable host -can be used). - -In the second xterm -xterm-2$ echo "hello there" >/p/tcp/localhost/6666 - -You should see the "hello there" string appear on the first terminal. - -Unprivilged users can't create servers on privalged ports. -xterm-1$ cat /p/tcplisten/ANY/666 -cat: /p/tcplisten/ANY/666: Operation not permitted - -but root can -xterm-1# cat /p/tcplisten/ANY/666 - -In the second -xterm-2$ echo "hello there" >/p/tcp/localhost/666 -should produce the expected response. - -You can also swap the client/server read and write commands etc. diff --git a/share/examples/portal/portal.conf b/share/examples/portal/portal.conf deleted file mode 100644 index aa7e282d59c..00000000000 --- a/share/examples/portal/portal.conf +++ /dev/null @@ -1,3 +0,0 @@ -tcp/ tcp tcp/ -tcplisten/ tcplisten tcplisten/ -fs/ file fs/ diff --git a/sys/fs/portalfs/portal.h b/sys/fs/portalfs/portal.h deleted file mode 100644 index 1fd2d99a01a..00000000000 --- a/sys/fs/portalfs/portal.h +++ /dev/null @@ -1,67 +0,0 @@ -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software donated to Berkeley by - * Jan-Simon Pendry. - * - * 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. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)portal.h 8.4 (Berkeley) 1/21/94 - * - * $FreeBSD$ - */ - -struct portal_args { - char *pa_config; /* Config file */ - int pa_socket; /* Socket to server */ -}; - -struct portal_cred { - int pcr_flag; /* File open mode */ - uid_t pcr_uid; /* From ucred */ - short pcr_ngroups; /* From ucred */ - gid_t pcr_groups[XU_NGROUPS]; /* From ucred */ -}; - -#ifdef _KERNEL -struct portalmount { - struct vnode *pm_root; /* Root node */ - struct file *pm_server; /* Held reference to server socket */ -}; - -struct portalnode { - int pt_size; /* Length of Arg */ - char *pt_arg; /* Arg to send to server */ - int pt_fileid; /* cookie */ -}; - -#define VFSTOPORTAL(mp) ((struct portalmount *)((mp)->mnt_data)) -#define VTOPORTAL(vp) ((struct portalnode *)(vp)->v_data) - -#define PORTAL_ROOTFILEID 2 - -extern struct vop_vector portal_vnodeops; -#endif /* _KERNEL */ diff --git a/sys/fs/portalfs/portal_vfsops.c b/sys/fs/portalfs/portal_vfsops.c deleted file mode 100644 index 62131dc65cc..00000000000 --- a/sys/fs/portalfs/portal_vfsops.c +++ /dev/null @@ -1,263 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1995 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software donated to Berkeley by - * Jan-Simon Pendry. - * - * 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. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)portal_vfsops.c 8.11 (Berkeley) 5/14/95 - * - * $FreeBSD$ - */ - -/* - * Portal Filesystem - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* Must come after sys/malloc.h */ -#include -#include -#include -#include -#include -#include - -#include - -static MALLOC_DEFINE(M_PORTALFSMNT, "portal_mount", "PORTAL mount structure"); - -static vfs_unmount_t portal_unmount; -static vfs_root_t portal_root; -static vfs_statfs_t portal_statfs; - -static const char *portal_opts[] = { - "socket", "config", - NULL -}; - -static int -portal_cmount(struct mntarg *ma, void *data, uint64_t flags) -{ - struct portal_args args; - int error; - - if (data == NULL) - return (EINVAL); - error = copyin(data, &args, sizeof args); - if (error) - return (error); - - ma = mount_argf(ma, "socket", "%d", args.pa_socket); - ma = mount_argsu(ma, "config", args.pa_config, MAXPATHLEN); - error = kernel_mount(ma, flags); - - return (error); -} - -/* - * Mount the per-process file descriptors (/dev/fd) - */ -static int -portal_mount(struct mount *mp) -{ - struct file *fp; - struct portalmount *fmp; - struct socket *so; - struct vnode *rvp; - struct thread *td; - struct portalnode *pn; - int error, v; - char *p; - - td = curthread; - if (vfs_filteropt(mp->mnt_optnew, portal_opts)) - return (EINVAL); - - error = vfs_scanopt(mp->mnt_optnew, "socket", "%d", &v); - if (error != 1) - return (EINVAL); - error = vfs_getopt(mp->mnt_optnew, "config", (void **)&p, NULL); - if (error) - return (error); - - /* - * Capsicum is not incompatible with portalfs, but we don't really - * know what rights are required. In the spirit of "better safe than - * sorry", pretend that all rights are required for now. - */ - if ((error = fget(td, v, CAP_MASK_VALID, &fp)) != 0) - return (error); - if (fp->f_type != DTYPE_SOCKET) { - fdrop(fp, td); - return(ENOTSOCK); - } - so = fp->f_data; /* XXX race against userland */ - if (so->so_proto->pr_domain->dom_family != AF_UNIX) { - fdrop(fp, td); - return (ESOCKTNOSUPPORT); - } - - pn = malloc(sizeof(struct portalnode), - M_TEMP, M_WAITOK); - - fmp = malloc(sizeof(struct portalmount), - M_PORTALFSMNT, M_WAITOK); /* XXX */ - - error = getnewvnode("portal", mp, &portal_vnodeops, &rvp); /* XXX */ - if (error) { - free(fmp, M_PORTALFSMNT); - free(pn, M_TEMP); - fdrop(fp, td); - return (error); - } - - error = insmntque(rvp, mp); /* XXX: Too early for mpsafe fs */ - if (error != 0) { - free(fmp, M_PORTALFSMNT); - free(pn, M_TEMP); - fdrop(fp, td); - return (error); - } - rvp->v_data = pn; - rvp->v_type = VDIR; - rvp->v_vflag |= VV_ROOT; - VTOPORTAL(rvp)->pt_arg = 0; - VTOPORTAL(rvp)->pt_size = 0; - VTOPORTAL(rvp)->pt_fileid = PORTAL_ROOTFILEID; - fmp->pm_root = rvp; - fhold(fp); - fmp->pm_server = fp; - - MNT_ILOCK(mp); - mp->mnt_flag |= MNT_LOCAL; - MNT_IUNLOCK(mp); - mp->mnt_data = fmp; - vfs_getnewfsid(mp); - - vfs_mountedfrom(mp, p); - fdrop(fp, td); - return (0); -} - -static int -portal_unmount(mp, mntflags) - struct mount *mp; - int mntflags; -{ - int error, flags = 0; - - - if (mntflags & MNT_FORCE) - flags |= FORCECLOSE; - - /* - * Clear out buffer cache. I don't think we - * ever get anything cached at this level at the - * moment, but who knows... - */ -#ifdef notyet - mntflushbuf(mp, 0); - if (mntinvalbuf(mp, 1)) - return (EBUSY); -#endif - /* There is 1 extra root vnode reference (pm_root). */ - error = vflush(mp, 1, flags, curthread); - if (error) - return (error); - - /* - * Shutdown the socket. This will cause the select in the - * daemon to wake up, and then the accept will get ECONNABORTED - * which it interprets as a request to go and bury itself. - */ - soshutdown(VFSTOPORTAL(mp)->pm_server->f_data, 2); - /* - * Discard reference to underlying file. Must call closef because - * this may be the last reference. - */ - closef(VFSTOPORTAL(mp)->pm_server, (struct thread *) 0); - /* - * Finally, throw away the portalmount structure - */ - free(mp->mnt_data, M_PORTALFSMNT); /* XXX */ - mp->mnt_data = NULL; - return (0); -} - -static int -portal_root(mp, flags, vpp) - struct mount *mp; - int flags; - struct vnode **vpp; -{ - struct vnode *vp; - - /* - * Return locked reference to root. - */ - vp = VFSTOPORTAL(mp)->pm_root; - VREF(vp); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); - *vpp = vp; - return (0); -} - -static int -portal_statfs(mp, sbp) - struct mount *mp; - struct statfs *sbp; -{ - - sbp->f_flags = 0; - sbp->f_bsize = DEV_BSIZE; - sbp->f_iosize = DEV_BSIZE; - sbp->f_blocks = 2; /* 1K to keep df happy */ - sbp->f_bfree = 0; - sbp->f_bavail = 0; - sbp->f_files = 1; /* Allow for "." */ - sbp->f_ffree = 0; /* See comments above */ - return (0); -} - -static struct vfsops portal_vfsops = { - .vfs_cmount = portal_cmount, - .vfs_mount = portal_mount, - .vfs_root = portal_root, - .vfs_statfs = portal_statfs, - .vfs_unmount = portal_unmount, -}; - -VFS_SET(portal_vfsops, portalfs, VFCF_SYNTHETIC); diff --git a/sys/fs/portalfs/portal_vnops.c b/sys/fs/portalfs/portal_vnops.c deleted file mode 100644 index 6b70daefa58..00000000000 --- a/sys/fs/portalfs/portal_vnops.c +++ /dev/null @@ -1,586 +0,0 @@ -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software donated to Berkeley by - * Jan-Simon Pendry. - * - * 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. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)portal_vnops.c 8.14 (Berkeley) 5/21/95 - * - * $FreeBSD$ - */ - -/* - * Portal Filesystem - */ - -#include "opt_capsicum.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -static int portal_fileid = PORTAL_ROOTFILEID+1; - -static void portal_closefd(struct thread *td, int fd); -static int portal_connect(struct socket *so, struct socket *so2); -static vop_getattr_t portal_getattr; -static vop_lookup_t portal_lookup; -static vop_open_t portal_open; -static vop_readdir_t portal_readdir; -static vop_reclaim_t portal_reclaim; -static vop_setattr_t portal_setattr; - -static void -portal_closefd(td, fd) - struct thread *td; - int fd; -{ - int error; - - error = kern_close(td, fd); - /* - * We should never get an error, and there isn't anything - * we could do if we got one, so just print a message. - */ - if (error) - printf("portal_closefd: error = %d\n", error); -} - -/* - * vp is the current namei directory - * cnp is the name to locate in that directory... - */ -static int -portal_lookup(ap) - struct vop_lookup_args /* { - struct vnode * a_dvp; - struct vnode ** a_vpp; - struct componentname * a_cnp; - } */ *ap; -{ - struct componentname *cnp = ap->a_cnp; - struct vnode **vpp = ap->a_vpp; - struct vnode *dvp = ap->a_dvp; - char *pname = cnp->cn_nameptr; - struct portalnode *pt; - int error; - struct vnode *fvp = NULL; - char *path; - int size; - - *vpp = NULLVP; - - if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) - return (EROFS); - - if (cnp->cn_namelen == 1 && *pname == '.') { - *vpp = dvp; - VREF(dvp); - return (0); - } - KASSERT((cnp->cn_flags & ISDOTDOT) == 0, - ("portal_lookup: Can not handle dotdot lookups.")); - - /* - * Do the MALLOC before the getnewvnode since doing so afterward - * might cause a bogus v_data pointer to get dereferenced - * elsewhere if MALLOC should block. - */ - pt = malloc(sizeof(struct portalnode), - M_TEMP, M_WAITOK); - - error = getnewvnode("portal", dvp->v_mount, &portal_vnodeops, &fvp); - if (error) { - free(pt, M_TEMP); - goto bad; - } - fvp->v_type = VREG; - fvp->v_data = pt; - /* - * Save all of the remaining pathname and - * advance the namei next pointer to the end - * of the string. - */ - for (size = 0, path = pname; *path; path++) - size++; - cnp->cn_consume = size - cnp->cn_namelen; - - pt->pt_arg = malloc(size+1, M_TEMP, M_WAITOK); - pt->pt_size = size+1; - bcopy(pname, pt->pt_arg, pt->pt_size); - pt->pt_fileid = portal_fileid++; - - *vpp = fvp; - vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY); - error = insmntque(fvp, dvp->v_mount); - if (error != 0) { - *vpp = NULLVP; - return (error); - } - return (0); - -bad:; - if (fvp) - vrele(fvp); - return (error); -} - -static int -portal_connect(so, so2) - struct socket *so; - struct socket *so2; -{ - /* from unp_connect, bypassing the namei stuff... */ - struct socket *so3; - struct unpcb *unp2; - struct unpcb *unp3; - - if (so2 == 0) - return (ECONNREFUSED); - - if (so->so_type != so2->so_type) - return (EPROTOTYPE); - - if ((so2->so_options & SO_ACCEPTCONN) == 0) - return (ECONNREFUSED); - - CURVNET_SET(so2->so_vnet); - if ((so3 = sonewconn(so2, 0)) == 0) { - CURVNET_RESTORE(); - return (ECONNREFUSED); - } - CURVNET_RESTORE(); - - unp2 = sotounpcb(so2); - unp3 = sotounpcb(so3); - if (unp2->unp_addr) - unp3->unp_addr = (struct sockaddr_un *) - sodupsockaddr((struct sockaddr *)unp2->unp_addr, - M_NOWAIT); - so2 = so3; - - return (soconnect2(so, so2)); -} - -static int -portal_open(ap) - struct vop_open_args /* { - struct vnode *a_vp; - int a_mode; - struct ucred *a_cred; - struct thread *a_td; - } */ *ap; -{ - struct socket *so = NULL; - struct portalnode *pt; - struct thread *td = ap->a_td; - struct vnode *vp = ap->a_vp; - struct uio auio; - struct iovec aiov[2]; - int res; - struct mbuf *cm = NULL; - struct cmsghdr *cmsg; - int newfds; - int *ip; - int fd; - int error; - int len; - struct portalmount *fmp; - struct file *fp; - struct portal_cred pcred; - -#ifdef CAPABILITY_MODE - /* - * This may require access to a global namespace (e.g. an IP address); - * disallow it entirely, as we do open(2). - */ - if (IN_CAPABILITY_MODE(td)) { -#ifdef KTRACE - if (KTRPOINT(td, KTR_CAPFAIL)) - ktrcapfail(CAPFAIL_SYSCALL, 0, 0); -#endif - return (ECAPMODE); - } -#endif - - /* - * Nothing to do when opening the root node. - */ - if (vp->v_vflag & VV_ROOT) - return (0); - - /* - * Can't be opened unless the caller is set up - * to deal with the side effects. Check for this - * by testing whether td_dupfd has been set. - */ - if (td->td_dupfd >= 0) - return (ENODEV); - - pt = VTOPORTAL(vp); - fmp = VFSTOPORTAL(vp->v_mount); - - /* - * Create a new socket. - */ - error = socreate(AF_UNIX, &so, SOCK_STREAM, 0, ap->a_cred, - ap->a_td); - if (error) - goto bad; - - /* - * Reserve some buffer space - */ - res = pt->pt_size + sizeof(pcred) + 512; /* XXX */ - error = soreserve(so, res, res); - if (error) - goto bad; - - /* - * Kick off connection - */ - error = portal_connect(so, fmp->pm_server->f_data); - if (error) - goto bad; - - /* - * Wait for connection to complete - */ - /* - * XXX: Since the mount point is holding a reference on the - * underlying server socket, it is not easy to find out whether - * the server process is still running. To handle this problem - * we loop waiting for the new socket to be connected (something - * which will only happen if the server is still running) or for - * the reference count on the server socket to drop to 1, which - * will happen if the server dies. Sleep for 5 second intervals - * and keep polling the reference count. XXX. - */ - SOCK_LOCK(so); - while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { - if (fmp->pm_server->f_count == 1) { - SOCK_UNLOCK(so); - error = ECONNREFUSED; - goto bad; - } - (void) msleep((caddr_t) &so->so_timeo, SOCK_MTX(so), PSOCK, - "portalcon", 5 * hz); - } - SOCK_UNLOCK(so); - - if (so->so_error) { - error = so->so_error; - goto bad; - } - - /* - * Set miscellaneous flags - */ - SOCKBUF_LOCK(&so->so_rcv); - so->so_rcv.sb_timeo = 0; - so->so_rcv.sb_flags |= SB_NOINTR; - SOCKBUF_UNLOCK(&so->so_rcv); - SOCKBUF_LOCK(&so->so_snd); - so->so_snd.sb_timeo = 0; - so->so_snd.sb_flags |= SB_NOINTR; - SOCKBUF_UNLOCK(&so->so_snd); - - - pcred.pcr_flag = ap->a_mode; - pcred.pcr_uid = ap->a_cred->cr_uid; - pcred.pcr_ngroups = MIN(ap->a_cred->cr_ngroups, XU_NGROUPS); - bcopy(ap->a_cred->cr_groups, pcred.pcr_groups, - pcred.pcr_ngroups * sizeof(gid_t)); - aiov[0].iov_base = (caddr_t) &pcred; - aiov[0].iov_len = sizeof(pcred); - aiov[1].iov_base = pt->pt_arg; - aiov[1].iov_len = pt->pt_size; - auio.uio_iov = aiov; - auio.uio_iovcnt = 2; - auio.uio_rw = UIO_WRITE; - auio.uio_segflg = UIO_SYSSPACE; - auio.uio_td = td; - auio.uio_offset = 0; - auio.uio_resid = aiov[0].iov_len + aiov[1].iov_len; - - error = sosend(so, (struct sockaddr *) 0, &auio, - (struct mbuf *) 0, (struct mbuf *) 0, 0 , td); - if (error) - goto bad; - - len = auio.uio_resid = sizeof(int); - do { - struct mbuf *m = NULL; - int flags = MSG_WAITALL; - error = soreceive(so, (struct sockaddr **) 0, &auio, - &m, &cm, &flags); - if (error) - goto bad; - - /* - * Grab an error code from the mbuf. - */ - if (m) { - m = m_pullup(m, sizeof(int)); /* Needed? */ - if (m) { - error = *(mtod(m, int *)); - m_freem(m); - } else { - error = EINVAL; - } - } else { - if (cm == 0) { - error = ECONNRESET; /* XXX */ -#ifdef notdef - break; -#endif - } - } - } while (cm == 0 && auio.uio_resid == len && !error); - - if (cm == 0) - goto bad; - - if (auio.uio_resid) { - error = 0; -#ifdef notdef - error = EMSGSIZE; - goto bad; -#endif - } - - /* - * XXX: Break apart the control message, and retrieve the - * received file descriptor. Note that more than one descriptor - * may have been received, or that the rights chain may have more - * than a single mbuf in it. What to do? - */ - cmsg = mtod(cm, struct cmsghdr *); - newfds = (cmsg->cmsg_len - sizeof(*cmsg)) / sizeof (int); - if (newfds == 0) { - error = ECONNREFUSED; - goto bad; - } - /* - * At this point the rights message consists of a control message - * header, followed by a data region containing a vector of - * integer file descriptors. The fds were allocated by the action - * of receiving the control message. - */ - ip = (int *) (cmsg + 1); - fd = *ip++; - if (newfds > 1) { - /* - * Close extra fds. - */ - int i; - printf("portal_open: %d extra fds\n", newfds - 1); - for (i = 1; i < newfds; i++) { - portal_closefd(td, *ip); - ip++; - } - } - - /* - * Check that the mode the file is being opened for is a subset - * of the mode of the existing descriptor. - */ - if ((error = fget(td, fd, 0, &fp)) != 0) - goto bad; - if (((ap->a_mode & (FREAD|FWRITE)) | fp->f_flag) != fp->f_flag) { - fdrop(fp, td); - portal_closefd(td, fd); - error = EACCES; - goto bad; - } - fdrop(fp, td); - - /* - * Save the dup fd in the proc structure then return the - * special error code (ENXIO) which causes magic things to - * happen in vn_open. The whole concept is, well, hmmm. - */ - td->td_dupfd = fd; - error = ENXIO; - -bad:; - /* - * And discard the control message. - */ - if (cm) { - m_freem(cm); - } - - if (so) { - soshutdown(so, 2); - soclose(so); - } - return (error); -} - -static int -portal_getattr(ap) - struct vop_getattr_args /* { - struct vnode *a_vp; - struct vattr *a_vap; - struct ucred *a_cred; - } */ *ap; -{ - struct vnode *vp = ap->a_vp; - struct vattr *vap = ap->a_vap; - - vap->va_uid = 0; - vap->va_gid = 0; - vap->va_size = DEV_BSIZE; - vap->va_blocksize = DEV_BSIZE; - nanotime(&vap->va_atime); - vap->va_mtime = vap->va_atime; - vap->va_ctime = vap->va_mtime; - vap->va_gen = 0; - vap->va_flags = 0; - vap->va_rdev = NODEV; - /* vap->va_qbytes = 0; */ - vap->va_bytes = 0; - vap->va_filerev = 0; - /* vap->va_qsize = 0; */ - if (vp->v_vflag & VV_ROOT) { - vap->va_type = VDIR; - vap->va_mode = S_IRUSR|S_IWUSR|S_IXUSR| - S_IRGRP|S_IWGRP|S_IXGRP| - S_IROTH|S_IWOTH|S_IXOTH; - vap->va_nlink = 2; - vap->va_fileid = 2; - } else { - vap->va_type = VREG; - vap->va_mode = S_IRUSR|S_IWUSR| - S_IRGRP|S_IWGRP| - S_IROTH|S_IWOTH; - vap->va_nlink = 1; - vap->va_fileid = VTOPORTAL(vp)->pt_fileid; - } - return (0); -} - -static int -portal_setattr(ap) - struct vop_setattr_args /* { - struct vnode *a_vp; - struct vattr *a_vap; - struct ucred *a_cred; - } */ *ap; -{ - - /* - * Can't mess with the root vnode - */ - if (ap->a_vp->v_vflag & VV_ROOT) - return (EACCES); - - if (ap->a_vap->va_flags != VNOVAL) - return (EOPNOTSUPP); - - return (0); -} - -/* - * Fake readdir, just return empty directory. - * It is hard to deal with '.' and '..' so don't bother. - */ -static int -portal_readdir(ap) - struct vop_readdir_args /* { - struct vnode *a_vp; - struct uio *a_uio; - struct ucred *a_cred; - int *a_eofflag; - u_long *a_cookies; - int a_ncookies; - } */ *ap; -{ - - /* - * We don't allow exporting portal mounts, and currently local - * requests do not need cookies. - */ - if (ap->a_ncookies) - panic("portal_readdir: not hungry"); - - return (0); -} - -static int -portal_reclaim(ap) - struct vop_reclaim_args /* { - struct vnode *a_vp; - } */ *ap; -{ - struct portalnode *pt = VTOPORTAL(ap->a_vp); - - if (pt->pt_arg) { - free((caddr_t) pt->pt_arg, M_TEMP); - pt->pt_arg = 0; - } - free(ap->a_vp->v_data, M_TEMP); - ap->a_vp->v_data = 0; - - return (0); -} - -struct vop_vector portal_vnodeops = { - .vop_default = &default_vnodeops, - - .vop_access = VOP_NULL, - .vop_getattr = portal_getattr, - .vop_lookup = portal_lookup, - .vop_open = portal_open, - .vop_pathconf = vop_stdpathconf, - .vop_readdir = portal_readdir, - .vop_reclaim = portal_reclaim, - .vop_setattr = portal_setattr, -}; diff --git a/sys/modules/portalfs/Makefile b/sys/modules/portalfs/Makefile deleted file mode 100644 index dcd5966c26a..00000000000 --- a/sys/modules/portalfs/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# $FreeBSD$ - -.PATH: ${.CURDIR}/../../fs/portalfs - -KMOD= portalfs -SRCS= vnode_if.h \ - portal_vfsops.c portal_vnops.c \ - opt_capsicum.h - -.include diff --git a/usr.sbin/mount_portalfs/Makefile b/usr.sbin/mount_portalfs/Makefile deleted file mode 100644 index 991a36f3e54..00000000000 --- a/usr.sbin/mount_portalfs/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# From: @(#)Makefile 8.3 (Berkeley) 3/27/94 -# $FreeBSD$ - -PROG= mount_portalfs -SRCS= mount_portalfs.c activate.c conf.c cred.c getmntopts.c pt_conf.c \ - pt_exec.c pt_file.c pt_pipe.c pt_tcp.c pt_tcplisten.c -MAN= mount_portalfs.8 - -MOUNT= ${.CURDIR}/../../sbin/mount -CFLAGS+=-I${MOUNT} -WARNS?= 3 - -.PATH: ${MOUNT} - -.include diff --git a/usr.sbin/mount_portalfs/activate.c b/usr.sbin/mount_portalfs/activate.c deleted file mode 100644 index 7d35d488752..00000000000 --- a/usr.sbin/mount_portalfs/activate.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * All rights reserved. - * - * This code is derived from software donated to Berkeley by - * Jan-Simon Pendry. - * - * 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. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)activate.c 8.3 (Berkeley) 4/28/95 - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "portald.h" - -/* - * Scan the providers list and call the - * appropriate function. - */ -static int activate_argv(struct portal_cred *pcr, char *key, char **v, int so, - int *fdp) -{ - provider *pr; - - for (pr = providers; pr->pr_match; pr++) - if (strcmp(v[0], pr->pr_match) == 0) - return ((*pr->pr_func)(pcr, key, v, so, fdp)); - - return (ENOENT); -} - -static int get_request(int so, struct portal_cred *pcr, char *key, int klen) -{ - struct iovec iov[2]; - struct msghdr msg; - int n; - - iov[0].iov_base = (caddr_t) pcr; - iov[0].iov_len = sizeof(*pcr); - iov[1].iov_base = key; - iov[1].iov_len = klen; - - memset(&msg, 0, sizeof(msg)); - msg.msg_iov = iov; - msg.msg_iovlen = 2; - - n = recvmsg(so, &msg, 0); - if (n < 0) - return (errno); - - if (n <= (int)sizeof(*pcr)) - return (EINVAL); - - n -= sizeof(*pcr); - key[n] = '\0'; - - return (0); -} - -static void send_reply(int so, int fd, int error) -{ - int n; - struct iovec iov; - struct msghdr msg; - union { - struct cmsghdr cmsg; - char control[CMSG_SPACE(sizeof(int))]; - } ctl; - - /* - * Line up error code. Don't worry about byte ordering - * because we must be sending to the local machine. - */ - iov.iov_base = (caddr_t) &error; - iov.iov_len = sizeof(error); - - /* - * Build a msghdr - */ - memset(&msg, 0, sizeof(msg)); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - - /* - * If there is a file descriptor to send then - * construct a suitable rights control message. - */ - if (fd >= 0) { - ctl.cmsg.cmsg_len = CMSG_LEN(sizeof(int)); - ctl.cmsg.cmsg_level = SOL_SOCKET; - ctl.cmsg.cmsg_type = SCM_RIGHTS; - *((int *)CMSG_DATA(&ctl.cmsg)) = fd; - msg.msg_control = (caddr_t) &ctl; - msg.msg_controllen = ctl.cmsg.cmsg_len; - } - - /* - * Send to kernel... - */ - if ((n = sendmsg(so, &msg, 0)) < 0) - syslog(LOG_ERR, "send: %s", strerror(errno)); -#ifdef DEBUG - fprintf(stderr, "sent %d bytes\n", n); -#endif - sleep(1); /*XXX*/ -#ifdef notdef - if (shutdown(so, SHUT_RDWR) < 0) - syslog(LOG_ERR, "shutdown: %s", strerror(errno)); -#endif - /* - * Throw away the open file descriptor - */ - (void) close(fd); -} - -void activate(qelem *q, int so) -{ - struct portal_cred pcred; - char key[MAXPATHLEN+1]; - int error; - char **v; - int fd = -1; - - /* - * Read the key from the socket - */ - error = get_request(so, &pcred, key, sizeof(key)); - if (error) { - syslog(LOG_ERR, "activate: recvmsg: %s", strerror(error)); - goto drop; - } - -#ifdef DEBUG - fprintf(stderr, "lookup key %s\n", key); -#endif - - /* - * Find a match in the configuration file - */ - v = conf_match(q, key); - - /* - * If a match existed, then find an appropriate portal - * otherwise simply return ENOENT. - */ - if (v) { - error = activate_argv(&pcred, key, v, so, &fd); - if (error) - fd = -1; - else if (fd < 0) - error = -1; - } else { - error = ENOENT; - } - - if (error >= 0) - send_reply(so, fd, error); - -drop:; - close(so); -} diff --git a/usr.sbin/mount_portalfs/conf.c b/usr.sbin/mount_portalfs/conf.c deleted file mode 100644 index f6b34bd39f4..00000000000 --- a/usr.sbin/mount_portalfs/conf.c +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * All rights reserved. - * - * This code is derived from software donated to Berkeley by - * Jan-Simon Pendry. - * - * 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. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)conf.c 8.2 (Berkeley) 3/27/94 - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "portald.h" - -#define ALLOC(ty) (xmalloc(sizeof(ty))) - -typedef struct path path; -struct path { - qelem p_q; /* 2-way linked list */ - int p_lno; /* Line number of this record */ - char *p_args; /* copy of arg string (malloc) */ - char *p_key; /* Pathname to match (also p_argv[0]) */ - regex_t p_rx; /* RE to match against pathname () */ - int p_rxvalid; /* non-zero if valid regular expression */ - int p_argc; /* number of elements in arg string */ - char **p_argv; /* argv[] pointers into arg string (malloc) */ -}; - -static char *conf_file; /* XXX for regerror */ -static path *curp; /* XXX for regerror */ - -/* - * Add an element to a 2-way list, - * just after (pred) - */ -static void ins_que(qelem *elem, qelem *pred) -{ - qelem *p = pred->q_forw; - elem->q_back = pred; - elem->q_forw = p; - pred->q_forw = elem; - p->q_back = elem; -} - -/* - * Remove an element from a 2-way list - */ -static void rem_que(qelem *elem) -{ - qelem *p = elem->q_forw; - qelem *p2 = elem->q_back; - p2->q_forw = p; - p->q_back = p2; -} - -/* - * Error checking malloc - */ -static void *xmalloc(unsigned siz) -{ - void *p = malloc(siz); - if (p) - return (p); - syslog(LOG_ALERT, "malloc: failed to get %d bytes", siz); - exit(1); -} - -/* - * Insert the path in the list. - * If there is already an element with the same key then - * the *second* one is ignored (return 0). If the key is - * not found then the path is added to the end of the list - * and 1 is returned. - */ -static int pinsert(path *p0, qelem *q0) -{ - qelem *q; - - if (p0->p_argc == 0) - return (0); - - for (q = q0->q_forw; q != q0; q = q->q_forw) { - path *p = (path *) q; - if (strcmp(p->p_key, p0->p_key) == 0) - return (0); - } - ins_que(&p0->p_q, q0->q_back); - return (1); - -} - -static path *palloc(char *cline, int lno) -{ - int c; - char *s; - char *key; - path *p; - char **ap; - - /* - * Implement comment chars - */ - s = strchr(cline, '#'); - if (s) - *s = 0; - - /* - * Do a pass through the string to count the number - * of arguments - */ - c = 0; - key = strdup(cline); - for (s = key; s != NULL; ) { - char *val; - while ((val = strsep(&s, " \t\n")) != NULL && *val == '\0') - ; - if (val) - c++; - } - c++; - free(key); - - if (c <= 1) - return (0); - - /* - * Now do another pass and generate a new path structure - */ - p = ALLOC(path); - p->p_argc = 0; - p->p_argv = xmalloc(c * sizeof(char *)); - p->p_args = strdup(cline); - ap = p->p_argv; - for (s = p->p_args; s != NULL; ) { - char *val; - while ((val = strsep(&s, " \t\n")) != NULL && *val == '\0') - ; - if (val) { - *ap++ = val; - p->p_argc++; - } - } - *ap = 0; - -#ifdef DEBUG - for (c = 0; c < p->p_argc; c++) - printf("%sv[%d] = %s\n", c?"\t":"", c, p->p_argv[c]); -#endif - - p->p_key = p->p_argv[0]; - if (strpbrk(p->p_key, RE_CHARS)) { - int val; - - curp = p; /* XXX */ - val = regcomp(&p->p_rx, p->p_key, REG_EXTENDED | REG_NOSUB); - if (val) { - char errbuf[_POSIX2_LINE_MAX]; - regerror(val, &p->p_rx, errbuf, sizeof errbuf); - syslog(LOG_ERR, "%s:%d: regcomp %s: %s", - conf_file, curp->p_lno, curp->p_key, errbuf); - regfree(&p->p_rx); - p->p_rxvalid = 0; - } else { - p->p_rxvalid = 1; - } - curp = 0; /* XXX */ - } else { - p->p_rxvalid = 0; - } - p->p_lno = lno; - - return (p); -} - -/* - * Free a path structure - */ -static void pfree(path *p) -{ - free(p->p_args); - if (p->p_rxvalid) { - regfree(&p->p_rx); - } - free((char *) p->p_argv); - free((char *) p); -} - -/* - * Discard all currently held path structures on q0. - * and add all the ones on xq. - */ -static void preplace(qelem *q0, qelem *xq) -{ - /* - * While the list is not empty, - * take the first element off the list - * and free it. - */ - while (q0->q_forw != q0) { - qelem *q = q0->q_forw; - rem_que(q); - pfree((path *) q); - } - while (xq->q_forw != xq) { - qelem *q = xq->q_forw; - rem_que(q); - ins_que(q, q0); - } -} - -/* - * Read the lines from the configuration file and - * add them to the list of paths. - */ -static void readfp(qelem *q0, FILE *fp) -{ - char cline[LINE_MAX]; - int nread = 0; - qelem q; - - /* - * Make a new empty list. - */ - q.q_forw = q.q_back = &q; - - /* - * Read the lines from the configuration file. - */ - while (fgets(cline, sizeof(cline), fp)) { - path *p = palloc(cline, nread+1); - if (p && !pinsert(p, &q)) - pfree(p); - nread++; - } - - /* - * If some records were read, then throw - * away the old list and replace with the - * new one. - */ - if (nread) - preplace(q0, &q); -} - -/* - * Read the configuration file (conf) and replace - * the existing path list with the new version. - * If the file is not readable, then no changes take place - */ -void conf_read(qelem *q, char *conf) -{ - FILE *fp = fopen(conf, "r"); - if (fp) { - conf_file = conf; /* XXX */ - readfp(q, fp); - conf_file = 0; /* XXX */ - (void) fclose(fp); - } else { - syslog(LOG_ERR, "open config file \"%s\": %s", conf, strerror(errno)); - } -} - - -char **conf_match(qelem *q0, char *key) -{ - qelem *q; - - for (q = q0->q_forw; q != q0; q = q->q_forw) { - path *p = (path *) q; - if (p->p_rxvalid) { - if (!regexec(&p->p_rx, key, 0, 0, 0)) { - return p->p_argv + 1; - } - } else { - if (strncmp(p->p_key, key, strlen(p->p_key)) == 0) - return (p->p_argv+1); - } - } - - return (0); -} diff --git a/usr.sbin/mount_portalfs/cred.c b/usr.sbin/mount_portalfs/cred.c deleted file mode 100644 index 2bd3623d2cd..00000000000 --- a/usr.sbin/mount_portalfs/cred.c +++ /dev/null @@ -1,75 +0,0 @@ -/*- - * Copyright (C) 2005 Diomidis Spinellis. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include - -#include -#include -#include - -#include "portald.h" - -/* - * Set the process's credentials to those specified in user, - * saving the existing ones in save. - * Return 0 on success, -1 (with errno set) on error. - */ -int -set_user_credentials(struct portal_cred *user, struct portal_cred *save) -{ - save->pcr_uid = geteuid(); - if ((save->pcr_ngroups = getgroups(NGROUPS_MAX, save->pcr_groups)) < 0) - return (-1); - if (setgroups(user->pcr_ngroups, user->pcr_groups) < 0) - return (-1); - if (seteuid(user->pcr_uid) < 0) - return (-1); - return (0); -} - -/* - * Restore the process's credentials to the ones specified in save. - * Log failures using LOG_ERR. - * Return 0 on success, -1 (with errno set) on error. - */ -int -restore_credentials(struct portal_cred *save) -{ - if (seteuid(save->pcr_uid) < 0) { - syslog(LOG_ERR, "seteuid: %m"); - return (-1); - } - if (setgroups(save->pcr_ngroups, save->pcr_groups) < 0) { - syslog(LOG_ERR, "setgroups: %m"); - return (-1); - } - return (0); -} diff --git a/usr.sbin/mount_portalfs/mount_portalfs.8 b/usr.sbin/mount_portalfs/mount_portalfs.8 deleted file mode 100644 index b6ca9cc7065..00000000000 --- a/usr.sbin/mount_portalfs/mount_portalfs.8 +++ /dev/null @@ -1,216 +0,0 @@ -.\" -.\" Copyright (c) 1993, 1994 -.\" The Regents of the University of California. All rights reserved. -.\" All rights reserved. -.\" -.\" This code is derived from software donated to Berkeley by -.\" Jan-Simon Pendry. -.\" -.\" 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. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)mount_portal.8 8.3 (Berkeley) 3/27/94 -.\" $FreeBSD$ -.\" -.Dd March 11, 2005 -.Dt MOUNT_PORTALFS 8 -.Os -.Sh NAME -.Nm mount_portalfs -.Nd mount the portal daemon -.Sh SYNOPSIS -.Nm -.Op Fl o Ar options -.Ar /etc/portal.conf -.Ar mount_point -.Sh DESCRIPTION -The -.Nm -utility attaches an instance of the portal daemon -to the global file system namespace. -The conventional mount point is -.Pa /p . -.\" .PA /dev . -This command is normally executed by -.Xr mount 8 -at boot time. -.Pp -The options are as follows: -.Bl -tag -width indent -.It Fl o -Options are specified with a -.Fl o -flag followed by a comma separated string of options. -See the -.Xr mount 8 -man page for possible options and their meanings. -.El -.Pp -The portal daemon provides an -.Em open -service. -Objects opened under the portal mount point are -dynamically created by the portal daemon according -to rules specified in the named configuration file. -Using this mechanism allows descriptors such as sockets -to be made available in the file system namespace. -.Pp -The portal daemon works by being passed the full pathname -of the object being opened. -The daemon creates an appropriate descriptor according -to the rules in the configuration file, and then passes the descriptor back -to the calling process as the result of the open system call. -.Sh NAMESPACE -By convention, the portal daemon divides the namespace into sub-namespaces, -each of which handles objects of a particular type. -.Pp -The following sub-namespaces are currently implemented: -.Pa fs , -.Pa pipe , -.Pa tcp , -and -.Pa tcplisten . -.Pp -The -.Pa fs -namespace opens the named file, starting back at the root directory. -This can be used to provide a controlled escape path from -a chrooted environment. -.Pp -The -.Pa pipe -namespace executes the named command, starting back at the root directory. -The command's arguments can be provided after the command's name, -by separating them with spaces or tabs. -Files opened for reading in the -.Pa pipe -namespace will receive their input from the command's standard output; -files opened for writing will send the data of write operations -to the command's standard input. -.Pp -The -.Pa tcp -namespace takes a slash separated hostname and a port and -creates an open TCP/IP connection. -.Pp -The -.Pa tcplisten -namespace takes a slash separated hostname and port and creates a TCP/IP -socket bound to the given hostname-port pair. -The hostname may be -specified as "ANY" to allow any other host to connect to the socket. -A -port number of 0 will dynamically allocate a port, this can be -discovered by calling -.Xr getsockname 2 -with the returned file descriptor. -Privileged ports can only be bound to -by the super-user. -.Sh "CONFIGURATION FILE" -The configuration file contains a list of rules. -Each rule takes one line and consists of two or more -whitespace separated fields. -A hash (``#'') character causes the remainder of a line to -be ignored. -Blank lines are ignored. -.Pp -The first field is a pathname prefix to match -against the requested pathname. -If a match is found, the second field -tells the daemon what type of object to create. -Subsequent fields are passed to the creation function. -.Bd -literal -# @(#)portal.conf 5.1 (Berkeley) 7/13/92 -tcplisten/ tcplisten tcplisten/ -tcp/ tcp tcp/ -fs/ file fs/ -pipe/ pipe pipe/ -.Ed -.Sh FILES -.Bl -tag -width /p/* -compact -.It Pa /p/* -.El -.Sh EXAMPLES -Display the greeting of the -.Fx -.Tn SMTP -server. -.Pp -.Dl "head -1 /p/tcp/mx1.freebsd.org/smtp" -.Pp -Implement a (single-threaded) echo server: -.Bd -literal -offset indent -while : -do - (exec 3<>/p/tcplisten/ANY/echo && cat -u <&3 >&3) -done -.Ed -.Pp -Gather data from two sources. -Verify that two remote files are identical: -.Bd -literal -offset indent -diff -q '/p/pipe/usr/bin/fetch -o - \\ - ftp://ftp1.freebsd.org/pub/FreeBSD/README.TXT' \\ - '/p/pipe/usr/bin/fetch -o - \\ - ftp://ftp2.freebsd.org/pub/FreeBSD/README.TXT' -.Ed -.Pp -Scatter data to two sinks. -Record a remote -.Tn CD -.Tn ISO -image and calculate its checksum: -.Bd -literal -offset indent -fetch -o - ftp://ftp5.freebsd.org/.../disc.iso | -tee '/p/pipe/usr/local/bin/cdrecord -' | -md5 -.Ed -.Pp -Create an -.Tn XML -view of the password file: -.Bd -literal -offset indent -ln -s '/p/pipe/usr/local/bin/passwd2xml /etc/passwd' \\ - /etc/passwd.xml" -.Ed -.Sh SEE ALSO -.Xr mount 2 , -.Xr unmount 2 , -.Xr fstab 5 , -.Xr mount 8 -.Rs -.%A "W. Richard Stevens" -.%A "Jan-Simon Pendry" -.%T "Portals in 4.4BSD" -.%B "USENIX 1995 Technical Conference Proceedings" -.%O "Berkeley, CA" -.%I "Peter Honeyman" -.Re -.Sh HISTORY -The -.Nm -utility first appeared in -.Bx 4.4 . -.Sh CAVEATS -This file system may not be NFS-exported. diff --git a/usr.sbin/mount_portalfs/mount_portalfs.c b/usr.sbin/mount_portalfs/mount_portalfs.c deleted file mode 100644 index 3bffbb1d56e..00000000000 --- a/usr.sbin/mount_portalfs/mount_portalfs.c +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software donated to Berkeley by - * Jan-Simon Pendry. - * - * 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. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static const char copyright[] = -"@(#) Copyright (c) 1992, 1993, 1994\n\ - The Regents of the University of California. All rights reserved.\n"; -#endif /* not lint */ - -#if 0 -static char sccsid[] = "@(#)mount_portal.c 8.6 (Berkeley) 4/26/95"; -#endif - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "mntopts.h" -#include "pathnames.h" -#include "portald.h" - -struct mntopt mopts[] = { - MOPT_STDOPTS, - MOPT_END -}; - -static void usage(void) __dead2; - -static volatile sig_atomic_t readcf; /* Set when SIGHUP received */ - -static void sighup(int sig __unused) -{ - readcf ++; -} - -static void sigchld(int sig __unused) -{ - pid_t pid; - - while ((pid = waitpid((pid_t) -1, (int *) 0, WNOHANG)) > 0) - ; - /* wrtp - waitpid _doesn't_ return 0 when no children! */ -#ifdef notdef - if (pid < 0 && errno != ECHILD) - syslog(LOG_WARNING, "waitpid: %s", strerror(errno)); -#endif -} - -int -main(int argc, char *argv[]) -{ - struct portal_args args; - struct sockaddr_un un; - char *conf; - char mountpt[MAXPATHLEN]; - int mntflags = 0; - char tag[32]; - mode_t um; - - qelem q; - int rc; - int so; - int error = 0; - - /* - * Crack command line args - */ - int ch; - - while ((ch = getopt(argc, argv, "o:")) != -1) { - switch (ch) { - case 'o': - getmntopts(optarg, mopts, &mntflags, 0); - break; - default: - error = 1; - break; - } - } - - if (optind != (argc - 2)) - error = 1; - - if (error) - usage(); - - /* - * Get config file and mount point - */ - conf = argv[optind]; - if (conf[0] != '/') { - (void)fprintf(stderr, - "The configuration file must be specified" - "through an absolute file path.\n"); - exit(EX_USAGE); - } - - /* resolve the mountpoint with realpath(3) */ - if (checkpath(argv[optind+1], mountpt) != 0) - err(EX_USAGE, "%s", mountpt); - - /* - * Construct the listening socket - */ - un.sun_family = AF_UNIX; - if (sizeof(_PATH_TMPPORTAL) >= sizeof(un.sun_path)) { - errx(EX_SOFTWARE, "portal socket name too long"); - } - strcpy(un.sun_path, _PATH_TMPPORTAL); - mktemp(un.sun_path); - un.sun_len = strlen(un.sun_path); - - so = socket(AF_UNIX, SOCK_STREAM, 0); - if (so < 0) { - err(EX_OSERR, "socket"); - } - um = umask(077); - (void) unlink(un.sun_path); - if (bind(so, (struct sockaddr *) &un, sizeof(un)) < 0) - err(1, NULL); - - (void) unlink(un.sun_path); - (void) umask(um); - - (void) listen(so, 5); - - args.pa_socket = so; - sprintf(tag, "portal:%d", getpid()); - args.pa_config = tag; - - rc = mount("portalfs", mountpt, mntflags, &args); - if (rc < 0) - err(1, NULL); - - /* - * Everything is ready to go - now is a good time to fork - */ -#ifndef DEBUG - daemon(0, 0); -#endif - - /* - * Start logging (and change name) - */ - openlog("portald", LOG_CONS|LOG_PID, LOG_DAEMON); - - q.q_forw = q.q_back = &q; - readcf = 1; - - signal(SIGCHLD, sigchld); - signal(SIGHUP, sighup); - - /* - * Just loop waiting for new connections and activating them - */ - for (;;) { - struct sockaddr_un un2; - int len2 = sizeof(un2); - int so2; - pid_t pid; - fd_set fdset; - - /* - * Check whether we need to re-read the configuration file - */ - if (readcf) { -#ifdef DEBUG - printf ("re-reading configuration file\n"); -#endif - readcf = 0; - conf_read(&q, conf); - continue; - } - - /* - * Accept a new connection - * Will get EINTR if a signal has arrived, so just - * ignore that error code - */ - FD_ZERO(&fdset); - FD_SET(so, &fdset); - rc = select(so+1, &fdset, (fd_set *) 0, (fd_set *) 0, (struct timeval *) 0); - if (rc < 0) { - if (errno == EINTR) - continue; - syslog(LOG_ERR, "select: %s", strerror(errno)); - exit(EX_OSERR); - } - if (rc == 0) - break; - so2 = accept(so, (struct sockaddr *) &un2, &len2); - if (so2 < 0) { - /* - * The unmount function does a shutdown on the socket - * which will generated ECONNABORTED on the accept. - */ - if (errno == ECONNABORTED) - break; - if (errno != EINTR) { - syslog(LOG_ERR, "accept: %s", strerror(errno)); - exit(EX_OSERR); - } - continue; - } - - /* - * Now fork a new child to deal with the connection - */ - eagain:; - switch (pid = fork()) { - case -1: - if (errno == EAGAIN) { - sleep(1); - goto eagain; - } - syslog(LOG_ERR, "fork: %s", strerror(errno)); - break; - case 0: - (void) close(so); - activate(&q, so2); - exit(0); - default: - (void) close(so2); - break; - } - } - syslog(LOG_INFO, "%s unmounted", mountpt); - exit(0); -} - -static void -usage(void) -{ - (void)fprintf(stderr, - "usage: mount_portalfs [-o options] config mount-point\n"); - exit(EX_USAGE); -} diff --git a/usr.sbin/mount_portalfs/pathnames.h b/usr.sbin/mount_portalfs/pathnames.h deleted file mode 100644 index 9373c7d75de..00000000000 --- a/usr.sbin/mount_portalfs/pathnames.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * All rights reserved. - * - * This code is derived from software donated to Berkeley by - * Jan-Simon Pendry. - * - * 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. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)pathnames.h 8.1 (Berkeley) 6/5/93 - * - * $FreeBSD$ - */ - -#include - -#define _PATH_TMPPORTAL "/tmp/portalXXXXXXXXXX" /* Scratch socket name */ diff --git a/usr.sbin/mount_portalfs/portal.conf b/usr.sbin/mount_portalfs/portal.conf deleted file mode 100644 index 398cfb29936..00000000000 --- a/usr.sbin/mount_portalfs/portal.conf +++ /dev/null @@ -1,7 +0,0 @@ -# @(#)portal.conf 8.1 (Berkeley) 6/5/93 -# $FreeBSD$ -tcplisten/ tcplisten tcplisten/ -tcp/ tcp tcp/ -fs/ file fs/ -pipe/ pipe pipe/ -foo/ exec ./bar bar baz diff --git a/usr.sbin/mount_portalfs/portald.h b/usr.sbin/mount_portalfs/portald.h deleted file mode 100644 index 99cd5d7e0fc..00000000000 --- a/usr.sbin/mount_portalfs/portald.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * All rights reserved. - * - * This code is derived from software donated to Berkeley by - * Jan-Simon Pendry. - * - * 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. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)portald.h 8.1 (Berkeley) 6/5/93 - * - * $FreeBSD$ - */ - -#include -#include -#include - -/* - * Meta-chars in an RE. Paths in the config file containing - * any of these characters will be matched using regexec, other - * paths will be prefix-matched. - */ -#define RE_CHARS ".|()[]*+?\\^$" - -typedef struct qelem qelem; - -struct qelem { - qelem *q_forw; - qelem *q_back; -}; - -typedef struct provider provider; -struct provider { - const char *pr_match; - int (*pr_func)(struct portal_cred *, - char *key, char **v, int so, int *fdp); -}; -extern provider providers[]; - -/* - * Portal providers - */ -extern int portal_exec(struct portal_cred *, - char *key, char **v, int so, int *fdp); -extern int portal_file(struct portal_cred *, - char *key, char **v, int so, int *fdp); -extern int portal_pipe(struct portal_cred *, - char *key, char **v, int so, int *fdp); -extern int portal_tcp(struct portal_cred *, - char *key, char **v, int so, int *fdp); -extern int portal_tcplisten(struct portal_cred *, - char *key, char **v, int so, int *fdp); - -/* - * Global functions - */ -extern void activate(qelem *q, int so); -extern char **conf_match(qelem *q, char *key); -extern void conf_read(qelem *q, char *conf); -extern int set_user_credentials(struct portal_cred *user, - struct portal_cred *save_area); -extern int restore_credentials(struct portal_cred *save_area); diff --git a/usr.sbin/mount_portalfs/pt_conf.c b/usr.sbin/mount_portalfs/pt_conf.c deleted file mode 100644 index 7f1e8175eab..00000000000 --- a/usr.sbin/mount_portalfs/pt_conf.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * All rights reserved. - * - * This code is derived from software donated to Berkeley by - * Jan-Simon Pendry. - * - * 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. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)pt_conf.c 8.1 (Berkeley) 6/5/93 - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include "portald.h" - -provider providers[] = { - { "exec", portal_exec }, - { "file", portal_file }, - { "pipe", portal_pipe }, - { "tcp", portal_tcp }, - { "tcplisten", portal_tcplisten }, - { 0, 0 } -}; diff --git a/usr.sbin/mount_portalfs/pt_exec.c b/usr.sbin/mount_portalfs/pt_exec.c deleted file mode 100644 index 86a47e9619c..00000000000 --- a/usr.sbin/mount_portalfs/pt_exec.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * All rights reserved. - * - * This code is derived from software donated to Berkeley by - * Jan-Simon Pendry. - * - * 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. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)pt_exec.c 8.1 (Berkeley) 6/5/93 - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include - -#include "portald.h" - -int portal_exec(struct portal_cred *pcr __unused, char *key __unused, - char **v __unused, int so __unused, int *fdp __unused) -{ - return (ENOEXEC); -} - diff --git a/usr.sbin/mount_portalfs/pt_file.c b/usr.sbin/mount_portalfs/pt_file.c deleted file mode 100644 index 270f8123e6f..00000000000 --- a/usr.sbin/mount_portalfs/pt_file.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * All rights reserved. - * - * This code is derived from software donated to Berkeley by - * Jan-Simon Pendry. - * - * 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. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)pt_file.c 8.3 (Berkeley) 7/3/94 - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include - -#include "portald.h" - -int portal_file(struct portal_cred *pcr, - char *key, char **v, int so __unused, int *fdp) -{ - int fd; - char pbuf[MAXPATHLEN]; - int error; - struct portal_cred save_area; - - pbuf[0] = '/'; - strcpy(pbuf+1, key + (v[1] ? strlen(v[1]) : 0)); - -#ifdef DEBUG - printf("path = %s, uid = %d, gid = %d\n", pbuf, pcr->pcr_uid, pcr->pcr_groups[0]); - printf ("fflag = %x, oflag = %x\n", pcr->pcr_flag, (pcr->pcr_flag)-1); -#endif - - if (set_user_credentials(pcr, &save_area) < 0) - return (errno); - - /* dmb convert kernel flags to oflags, see */ - fd = open(pbuf, (pcr->pcr_flag)-1, 0777); - if (fd < 0) - error = errno; - else - error = 0; - - if (restore_credentials(&save_area) < 0) { - error = errno; - if (fd >= 0) { - (void) close(fd); - fd = -1; - } - } - - if (error == 0) - *fdp = fd; - -#ifdef DEBUG - fprintf(stderr, "pt_file returns *fdp = %d, error = %d\n", *fdp, error); -#endif - - return (error); -} diff --git a/usr.sbin/mount_portalfs/pt_pipe.c b/usr.sbin/mount_portalfs/pt_pipe.c deleted file mode 100644 index 84ee6e494e4..00000000000 --- a/usr.sbin/mount_portalfs/pt_pipe.c +++ /dev/null @@ -1,229 +0,0 @@ -/*- - * Copyright (C) 2005 Diomidis Spinellis. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "portald.h" - -/* Usage conventions for the pipe's endpoints. */ -#define READ_END 0 -#define WRITE_END 1 - -static int errlog(void); -static int parse_argv(char *args, char **argv); - -int portal_pipe(struct portal_cred *pcr, char *key, char **v, - int kso __unused, int *fdp) -{ - int fd[2]; /* Pipe endpoints. */ - int caller_end; /* The pipe end we will use. */ - int process_end; /* The pipe end the spawned process will use. */ - int redirect_fd; /* The fd to redirect on the spawned process. */ - char pbuf[MAXPATHLEN]; - int error = 0; - int i; - char **argv; - int argc; - struct portal_cred save_area; - - /* Validate open mode, and assign roles. */ - if ((pcr->pcr_flag & FWRITE) && (pcr->pcr_flag & FREAD)) - /* Don't allow both on a single fd. */ - return (EINVAL); - else if (pcr->pcr_flag & FREAD) { - /* - * The caller reads from the pipe, - * the spawned process writes to it. - */ - caller_end = READ_END; - process_end = WRITE_END; - redirect_fd = STDOUT_FILENO; - } else if (pcr->pcr_flag & FWRITE) { - /* - * The caller writes to the pipe, - * the spawned process reads from it. - */ - caller_end = WRITE_END; - process_end = READ_END; - redirect_fd = STDIN_FILENO; - } else - return (EINVAL); - - /* Get and check command line. */ - pbuf[0] = '/'; - strcpy(pbuf+1, key + (v[1] ? strlen(v[1]) : 0)); - argc = parse_argv(pbuf, NULL); - if (argc == 0) - return (ENOENT); - - /* Swap privileges. */ - if (set_user_credentials(pcr, &save_area) < 0) - return (errno); - - /* Redirect and spawn the specified process. */ - fd[READ_END] = fd[WRITE_END] = -1; - if (pipe(fd) < 0) { - error = errno; - goto done; - } - switch (fork()) { - case -1: /* Error */ - error = errno; - break; - default: /* Parent */ - (void)close(fd[process_end]); - break; - case 0: /* Child */ - argv = (char **)malloc((argc + 1) * sizeof(char *)); - if (argv == 0) { - syslog(LOG_ALERT, - "malloc: failed to get space for %d pointers", - argc + 1); - exit(EXIT_FAILURE); - } - parse_argv(pbuf, argv); - - if (dup2(fd[process_end], redirect_fd) < 0) { - syslog(LOG_ERR, "dup2: %m"); - exit(EXIT_FAILURE); - } - (void)close(fd[caller_end]); - (void)close(fd[process_end]); - if (errlog() < 0) { - syslog(LOG_ERR, "errlog: %m"); - exit(EXIT_FAILURE); - } - if (execv(argv[0], argv) < 0) { - syslog(LOG_ERR, "execv(%s): %m", argv[0]); - exit(EXIT_FAILURE); - } - /* NOTREACHED */ - } - -done: - /* Re-establish our privileges. */ - if (restore_credentials(&save_area) < 0) - error = errno; - - /* Set return fd value. */ - if (error == 0) - *fdp = fd[caller_end]; - else { - for (i = 0; i < 2; i++) - if (fd[i] >= 0) - (void)close(fd[i]); - *fdp = -1; - } - - return (error); -} - -/* - * Redirect stderr to the system log. - * Return 0 if ok. - * Return -1 with errno set on error. - */ -static int -errlog(void) -{ - int fd[2]; - char buff[1024]; - FILE *f; - int ret = 0; - - if (pipe(fd) < 0) - return (-1); - switch (fork()) { - case -1: /* Error */ - return (-1); - case 0: /* Child */ - if ((f = fdopen(fd[READ_END], "r")) == NULL) { - syslog(LOG_ERR, "fdopen: %m"); - exit(EXIT_FAILURE); - } - (void)close(fd[WRITE_END]); - while (fgets(buff, sizeof(buff), f) != NULL) - syslog(LOG_ERR, "exec: %s", buff); - exit(EXIT_SUCCESS); - /* NOTREACHED */ - default: /* Parent */ - if (dup2(fd[WRITE_END], STDERR_FILENO) < 0) - ret = -1; - (void)close(fd[READ_END]); - (void)close(fd[WRITE_END]); - break; - } - return (ret); -} - -/* - * Parse the args string as a space-separated argument vector. - * If argv is not NULL, split the string into its constituent - * components, and set argv to point to the beginning of each - * string component; NULL-terminating argv. - * Return the number of string components. - */ -static int -parse_argv(char *args, char **argv) -{ - int count = 0; - char *p; - enum {WORD, SPACE} state = SPACE; - - for (p = args; *p; p++) - switch (state) { - case WORD: - if (isspace(*p)) { - if (argv) - *p = '\0'; - state = SPACE; - } - break; - case SPACE: - if (!isspace(*p)) { - if (argv) - argv[count] = p; - count++; - state = WORD; - } - } - if (argv) - argv[count] = NULL; - return (count); -} diff --git a/usr.sbin/mount_portalfs/pt_tcp.c b/usr.sbin/mount_portalfs/pt_tcp.c deleted file mode 100644 index d9a2a1eef71..00000000000 --- a/usr.sbin/mount_portalfs/pt_tcp.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * All rights reserved. - * - * This code is derived from software donated to Berkeley by - * Jan-Simon Pendry. - * - * 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. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)pt_tcp.c 8.5 (Berkeley) 4/28/95 - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "portald.h" - -/* - * Key will be tcp/host/port[/"priv"] - * Create a TCP socket connected to the - * requested host and port. - * Some trailing suffix values have special meanings. - * An unrecognized suffix is an error. - */ -int portal_tcp(struct portal_cred *pcr, char *key, char **v, - int kso __unused, int *fdp) -{ - char host[MAXHOSTNAMELEN]; - char port[MAXHOSTNAMELEN]; - char *p = key + (v[1] ? strlen(v[1]) : 0); - char *q; - struct hostent *hp; - struct servent *sp; - struct in_addr **ipp; - struct in_addr *ip[2]; - struct in_addr ina; - u_short s_port; - int priv = 0; - struct sockaddr_in sain; - - q = strchr(p, '/'); - if (q == 0 || q - p >= (int)sizeof(host)) - return (EINVAL); - *q = '\0'; - strcpy(host, p); - p = q + 1; - - q = strchr(p, '/'); - if (q) - *q = '\0'; - if (strlen(p) >= sizeof(port)) - return (EINVAL); - strcpy(port, p); - if (q) { - p = q + 1; - if (strcmp(p, "priv") == 0) { - if (pcr->pcr_uid == 0) - priv = 1; - else - return (EPERM); - } else { - return (EINVAL); - } - } - - hp = gethostbyname(host); - if (hp != 0) { - ipp = (struct in_addr **) hp->h_addr_list; - } else { - ina.s_addr = inet_addr(host); - if (ina.s_addr == INADDR_NONE) - return (EINVAL); - ip[0] = &ina; - ip[1] = 0; - ipp = ip; - } -#ifdef DEBUG - printf ("inet address for %s is %s\n", host, inet_ntoa(*ipp[0])); -#endif - - sp = getservbyname(port, "tcp"); - if (sp != NULL) { - s_port = (u_short)sp->s_port; - } else { - s_port = strtoul(port, &p, 0); - if (s_port == 0 || *p != '\0') - return (EINVAL); - s_port = htons(s_port); - } -#ifdef DEBUG - printf ("port number for %s is %d\n", port, (int)ntohs(s_port)); -#endif - - memset(&sain, 0, sizeof(sain)); - sain.sin_len = sizeof(sain); - sain.sin_family = AF_INET; - sain.sin_port = s_port; - - while (ipp[0]) { - int so; - - if (priv) - so = rresvport((int *) 0); - else - so = socket(AF_INET, SOCK_STREAM, 0); - if (so < 0) { - syslog(LOG_ERR, "socket: %m"); - return (errno); - } - - sain.sin_addr = *ipp[0]; - if (connect(so, (struct sockaddr *) &sain, sizeof(sain)) == 0) { - *fdp = so; - return (0); - } - (void) close(so); - - ipp++; - } - - return (errno); -} diff --git a/usr.sbin/mount_portalfs/pt_tcplisten.c b/usr.sbin/mount_portalfs/pt_tcplisten.c deleted file mode 100644 index 3bd29c1bc1a..00000000000 --- a/usr.sbin/mount_portalfs/pt_tcplisten.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * All rights reserved. - * - * This code is derived from software donated to Berkeley by - * Jan-Simon Pendry. - * - * Modified by Duncan Barclay. - * - * 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. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)pt_tcp.c 8.3 (Berkeley) 3/27/94 - * - * pt_tcp.c,v 1.1.1.1 1994/05/26 06:34:34 rgrimes Exp - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "portald.h" - -/* - * Key will be tcplisten/host/port - * - * Create a TCP socket bound to the requested host and port. - * If the host is "ANY" the receiving address will be set to INADDR_ANY. - * If the port is 0 the caller must find out the returned port number - * using a call to getsockname. - * - * XXX! The owner of the socket will be root rather then the user. This - * may cause remote auth (identd) to return unexpected results. - * - */ -int portal_tcplisten(struct portal_cred *pcr, char *key, char **v, - int kso __unused, int *fdp) -{ - char host[MAXHOSTNAMELEN]; - char port[MAXHOSTNAMELEN]; - char *p = key + (v[1] ? strlen(v[1]) : 0); - char *q; - struct hostent *hp; - struct servent *sp; - struct in_addr **ipp = NULL; - struct in_addr *ip[2]; - struct in_addr ina; - u_short s_port; - int any = 0; - struct sockaddr_in sain; - - q = strchr(p, '/'); - if (q == 0 || q - p >= (int)sizeof(host)) - return (EINVAL); - *q = '\0'; - snprintf(host, sizeof(host), "%s", p); - p = q + 1; - - q = strchr(p, '/'); - if (q) - *q = '\0'; - if (strlen(p) >= sizeof(port)) - return (EINVAL); - snprintf(port, sizeof(port), "%s", p); - - if (strcmp(host, "ANY") == 0) { - any = 1; - } else { - hp = gethostbyname(host); - if (hp != 0) { - ipp = (struct in_addr **) hp->h_addr_list; - } else { - ina.s_addr = inet_addr(host); - if (ina.s_addr == INADDR_NONE) - return (EINVAL); - ip[0] = &ina; - ip[1] = 0; - ipp = ip; - } - } -#ifdef DEBUG - if (any) - printf("INADDR_ANY to be used for hostname\n"); - else - printf("inet address for %s is %s\n", host, inet_ntoa(*ipp[0])); -#endif - - sp = getservbyname(port, "tcp"); - if (sp != NULL) { - s_port = (u_short) sp->s_port; - } else { - s_port = strtoul(port, &p, 0); - if (*p != '\0') - return (EINVAL); - s_port = htons(s_port); - } - if ((ntohs(s_port) != 0) && - (ntohs(s_port) <= IPPORT_RESERVED) && - (pcr->pcr_uid != 0)) - return (EPERM); -#ifdef DEBUG - printf("port number for %s is %d\n", port, ntohs(s_port)); -#endif - - memset(&sain, 0, sizeof(sain)); - sain.sin_len = sizeof(sain); - sain.sin_family = AF_INET; - sain.sin_port = s_port; - - if (any) { - int so; - int sock; - - so = socket(AF_INET, SOCK_STREAM, 0); - if (so < 0) { - syslog(LOG_ERR, "socket: %m"); - return (errno); - } - - sain.sin_addr.s_addr = INADDR_ANY; - if (bind(so, (struct sockaddr *) &sain, sizeof(sain)) == 0) { - listen(so, 1); - if ((sock = accept(so, (struct sockaddr *)0, (int *)0)) == -1) { - syslog(LOG_ERR, "accept: %m"); - (void) close(so); - return (errno); - } - *fdp = sock; - (void) close(so); - return (0); - } - syslog(LOG_ERR, "bind: %m"); - (void) close(so); - return (errno); - } - - while (ipp[0]) { - int so; - int sock; - - so = socket(AF_INET, SOCK_STREAM, 0); - if (so < 0) { - syslog(LOG_ERR, "socket: %m"); - return (errno); - } - - sain.sin_addr = *ipp[0]; - if (bind(so, (struct sockaddr *) &sain, sizeof(sain)) == 0) { - listen(so, 1); - if ((sock = accept(so, (struct sockaddr *)0, (int *)0)) == -1) { - syslog(LOG_ERR, "accept: %m"); - (void) close(so); - return (errno); - } - *fdp = sock; - (void) close(so); - return (0); - } - (void) close(so); - - ipp++; - } - - syslog(LOG_ERR, "bind: %m"); - return (errno); - -} From 55f33f2cafb5e13adb0bd0092322fe0ef445fc61 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Sat, 2 Mar 2013 18:07:29 +0000 Subject: [PATCH 0540/1476] The value held by the vm object's field pg_color is only considered valid if the flag OBJ_COLORED is set. Since _vm_object_allocate() doesn't set this flag, it needn't initialize pg_color. Sponsored by: EMC / Isilon Storage Division --- sys/vm/vm_object.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c index 28d6d0c9e8c..738cec640c2 100644 --- a/sys/vm/vm_object.c +++ b/sys/vm/vm_object.c @@ -241,7 +241,6 @@ _vm_object_allocate(objtype_t type, vm_pindex_t size, vm_object_t object) object->memattr = VM_MEMATTR_DEFAULT; object->cred = NULL; object->charge = 0; - object->pg_color = 0; object->handle = NULL; object->backing_object = NULL; object->backing_object_offset = (vm_ooffset_t) 0; From 5e1a43a84f1fa4638a328c008376ce5adbbd294e Mon Sep 17 00:00:00 2001 From: Jens Schweikhardt Date: Sat, 2 Mar 2013 18:08:03 +0000 Subject: [PATCH 0541/1476] Comment cosmetics: capitalize SCSI Fix some hard tabs in the wrong place. MFC after: 2 weeks --- etc/devd.conf | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/etc/devd.conf b/etc/devd.conf index d379ab0472f..5339bae18a2 100644 --- a/etc/devd.conf +++ b/etc/devd.conf @@ -34,7 +34,7 @@ options { # NB: DETACH events are ignored; the kernel should handle all cleanup # (routes, arp cache). Beware of races against immediate create # of a device with the same name; e.g. -# ifconfig bridge0 destroy; ifconfig bridge0 create +# ifconfig bridge0 destroy; ifconfig bridge0 create # notify 0 { match "system" "IFNET"; @@ -165,7 +165,7 @@ notify 100 { }; # -# Rescan scsi device-names on attach, but not detach. However, it is +# Rescan SCSI device-names on attach, but not detach. However, it is # disabled by default due to reports of problems. # attach 0 { @@ -305,13 +305,13 @@ detach 10 { # events. See the ACPI specification for more information about # notifies. Here is the information returned for each subsystem: # -# ACAD: AC line state (0 is offline, 1 is online) -# Button: Button pressed (0 for power, 1 for sleep) -# CMBAT: ACPI battery events -# Lid: Lid state (0 is closed, 1 is open) -# RCTL: Resource limits +# ACAD: AC line state (0 is offline, 1 is online) +# Button: Button pressed (0 for power, 1 for sleep) +# CMBAT: ACPI battery events +# Lid: Lid state (0 is closed, 1 is open) +# RCTL: Resource limits # Suspend, Resume: Suspend and resume notification -# Thermal: ACPI thermal zone events +# Thermal: ACPI thermal zone events # # This example calls a script when the AC state changes, passing the # notify value as the first argument. If the state is 0x00, it might From 0f90e981cb2504aad8a9afaf6320635e948f3136 Mon Sep 17 00:00:00 2001 From: Attilio Rao Date: Sat, 2 Mar 2013 18:23:59 +0000 Subject: [PATCH 0542/1476] Remove ntfs headers dependency for g_label_ntfs.c by redefining the used structs and values. This patch is not targeted for MFC. --- sys/geom/label/g_label_ntfs.c | 79 ++++++++++++++++++++++++++++------- 1 file changed, 65 insertions(+), 14 deletions(-) diff --git a/sys/geom/label/g_label_ntfs.c b/sys/geom/label/g_label_ntfs.c index 1ee3f797f26..f00669edcb5 100644 --- a/sys/geom/label/g_label_ntfs.c +++ b/sys/geom/label/g_label_ntfs.c @@ -32,21 +32,72 @@ __FBSDID("$FreeBSD$"); #include #include -#include - #include #include +#define NTFS_A_VOLUMENAME 0x60 +#define NTFS_FILEMAGIC ((uint32_t)(0x454C4946)) +#define NTFS_VOLUMEINO 3 + #define G_LABEL_NTFS_DIR "ntfs" +struct ntfs_attr { + uint32_t a_type; + uint32_t reclen; + uint8_t a_flag; + uint8_t a_namelen; + uint8_t a_nameoff; + uint8_t reserved1; + uint8_t a_compression; + uint8_t reserved2; + uint16_t a_index; + uint16_t a_datalen; + uint16_t reserved3; + uint16_t a_dataoff; + uint16_t a_indexed; +}; + +struct ntfs_filerec { + uint32_t fr_hdrmagic; + uint16_t fr_hdrfoff; + uint16_t fr_hdrfnum; + uint8_t reserved[8]; + uint16_t fr_seqnum; + uint16_t fr_nlink; + uint16_t fr_attroff; + uint16_t fr_flags; + uint32_t fr_size; + uint32_t fr_allocated; + uint64_t fr_mainrec; + uint16_t fr_attrnum; +}; + +struct ntfs_bootfile { + uint8_t reserved1[3]; + uint8_t bf_sysid[8]; + uint16_t bf_bps; + uint8_t bf_spc; + uint8_t reserved2[7]; + uint8_t bf_media; + uint8_t reserved3[2]; + uint16_t bf_spt; + uint16_t bf_heads; + uint8_t reserver4[12]; + uint64_t bf_spv; + uint64_t bf_mftcn; + uint64_t bf_mftmirrcn; + uint8_t bf_mftrecsz; + uint32_t bf_ibsz; + uint32_t bf_volsn; +}; static void g_label_ntfs_taste(struct g_consumer *cp, char *label, size_t size) { struct g_provider *pp; - struct bootfile *bf; - struct filerec *fr; - struct attr *atr; + struct ntfs_bootfile *bf; + struct ntfs_filerec *fr; + struct ntfs_attr *atr; off_t voloff; char *filerecp, *ap; char mftrecsz, vnchar; @@ -58,7 +109,7 @@ g_label_ntfs_taste(struct g_consumer *cp, char *label, size_t size) pp = cp->provider; filerecp = NULL; - bf = (struct bootfile *)g_read_data(cp, 0, pp->sectorsize, NULL); + bf = (struct ntfs_bootfile *)g_read_data(cp, 0, pp->sectorsize, NULL); if (bf == NULL || strncmp(bf->bf_sysid, "NTFS ", 8) != 0) goto done; @@ -75,16 +126,16 @@ g_label_ntfs_taste(struct g_consumer *cp, char *label, size_t size) filerecp = g_read_data(cp, voloff, recsize, NULL); if (filerecp == NULL) goto done; - fr = (struct filerec *)filerecp; + fr = (struct ntfs_filerec *)filerecp; - if (fr->fr_fixup.fh_magic != NTFS_FILEMAGIC) + if (fr->fr_hdrmagic != NTFS_FILEMAGIC) goto done; for (ap = filerecp + fr->fr_attroff; - atr = (struct attr *)ap, atr->a_hdr.a_type != -1; - ap += atr->a_hdr.reclen) { - if (atr->a_hdr.a_type == NTFS_A_VOLUMENAME) { - if(atr->a_r.a_datalen >= size *2){ + atr = (struct ntfs_attr *)ap, atr->a_type != -1; + ap += atr->reclen) { + if (atr->a_type == NTFS_A_VOLUMENAME) { + if(atr->a_datalen >= size *2){ label[0] = 0; goto done; } @@ -92,8 +143,8 @@ g_label_ntfs_taste(struct g_consumer *cp, char *label, size_t size) *UNICODE to ASCII. * Should we need to use iconv(9)? */ - for (j = 0; j < atr->a_r.a_datalen; j++) { - vnchar = *(ap + atr->a_r.a_dataoff + j); + for (j = 0; j < atr->a_datalen; j++) { + vnchar = *(ap + atr->a_dataoff + j); if (j & 1) { if (vnchar) { label[0] = 0; From 737a61a1ee3dd3971cac78a4803a82ef9be62c4c Mon Sep 17 00:00:00 2001 From: Attilio Rao Date: Sat, 2 Mar 2013 18:40:04 +0000 Subject: [PATCH 0543/1476] Garbage collect NTFS bits which are now completely disconnected from the tree since few months. This patch is not targeted for MFC. --- ObsoleteFiles.inc | 10 + lib/libprocstat/ntfs.c | 71 -- sbin/mount_ntfs/Makefile | 20 - sbin/mount_ntfs/mount_ntfs.8 | 173 --- sbin/mount_ntfs/mount_ntfs.c | 280 ----- sys/fs/ntfs/ntfs.h | 308 ----- sys/fs/ntfs/ntfs_compr.c | 111 -- sys/fs/ntfs/ntfs_compr.h | 35 - sys/fs/ntfs/ntfs_iconv.c | 36 - sys/fs/ntfs/ntfs_ihash.c | 130 -- sys/fs/ntfs/ntfs_ihash.h | 37 - sys/fs/ntfs/ntfs_inode.h | 101 -- sys/fs/ntfs/ntfs_subr.c | 2029 ------------------------------- sys/fs/ntfs/ntfs_subr.h | 120 -- sys/fs/ntfs/ntfs_vfsops.c | 780 ------------ sys/fs/ntfs/ntfs_vfsops.h | 43 - sys/fs/ntfs/ntfs_vnops.c | 687 ----------- sys/fs/ntfs/ntfsmount.h | 44 - sys/modules/ntfs/Makefile | 11 - sys/modules/ntfs_iconv/Makefile | 7 - 20 files changed, 10 insertions(+), 5023 deletions(-) delete mode 100644 lib/libprocstat/ntfs.c delete mode 100644 sbin/mount_ntfs/Makefile delete mode 100644 sbin/mount_ntfs/mount_ntfs.8 delete mode 100644 sbin/mount_ntfs/mount_ntfs.c delete mode 100644 sys/fs/ntfs/ntfs.h delete mode 100644 sys/fs/ntfs/ntfs_compr.c delete mode 100644 sys/fs/ntfs/ntfs_compr.h delete mode 100644 sys/fs/ntfs/ntfs_iconv.c delete mode 100644 sys/fs/ntfs/ntfs_ihash.c delete mode 100644 sys/fs/ntfs/ntfs_ihash.h delete mode 100644 sys/fs/ntfs/ntfs_inode.h delete mode 100644 sys/fs/ntfs/ntfs_subr.c delete mode 100644 sys/fs/ntfs/ntfs_subr.h delete mode 100644 sys/fs/ntfs/ntfs_vfsops.c delete mode 100644 sys/fs/ntfs/ntfs_vfsops.h delete mode 100644 sys/fs/ntfs/ntfs_vnops.c delete mode 100644 sys/fs/ntfs/ntfsmount.h delete mode 100644 sys/modules/ntfs/Makefile delete mode 100644 sys/modules/ntfs_iconv/Makefile diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index 540ae930617..068882d74d7 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -38,6 +38,16 @@ # xargs -n1 | sort | uniq -d; # done +# 20130302: NTFS support removed +OLD_FILES+=usr/include/fs/ntfs/ntfs.h +OLD_FILES+=usr/include/fs/ntfs/ntfs_compr.h +OLD_FILES+=usr/include/fs/ntfs/ntfs_ihash.h +OLD_FILES+=usr/include/fs/ntfs/ntfs_inode.h +OLD_FILES+=usr/include/fs/ntfs/ntfs_subr.h +OLD_FILES+=usr/include/fs/ntfs/ntfs_vfsops.h +OLD_FILES+=usr/include/fs/ntfs/ntfsmount.h +OLD_DIRS+=usr/include/fs/ntfs +OLD_FILES+=usr/share/man/man8/mount_ntfs.8.gz # 20130302: PORTALFS support removed OLD_FILES+=usr/include/fs/portalfs/portal.h OLD_DIRS+=usr/include/fs/portalfs diff --git a/lib/libprocstat/ntfs.c b/lib/libprocstat/ntfs.c deleted file mode 100644 index 888e6cd845e..00000000000 --- a/lib/libprocstat/ntfs.c +++ /dev/null @@ -1,71 +0,0 @@ -/*- - * Copyright (c) 2005-2009 Stanislav Sedov - * 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 -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include -#include - -#include "libprocstat.h" -#include "common_kvm.h" - -int -ntfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn) -{ - struct fnode fnod; - struct ntnode node; - int error; - - assert(kd); - assert(vn); - error = kvm_read_all(kd, (unsigned long)VTOF(vp), &fnod, sizeof(fnod)); - if (error != 0) { - warnx("can't read ntfs fnode at %p", (void *)VTOF(vp)); - return (1); - } - error = kvm_read_all(kd, (unsigned long)FTONT(&fnod), &node, - sizeof(node)); - if (error != 0) { - warnx("can't read ntfs node at %p", (void *)FTONT(&fnod)); - return (1); - } - vn->vn_fileid = node.i_number; - vn->vn_fsid = dev2udev(kd, node.i_dev); - return (0); -} diff --git a/sbin/mount_ntfs/Makefile b/sbin/mount_ntfs/Makefile deleted file mode 100644 index 416f1ac8ab2..00000000000 --- a/sbin/mount_ntfs/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# -# $FreeBSD$ -# - -PROG= mount_ntfs -SRCS= mount_ntfs.c getmntopts.c -MAN= mount_ntfs.8 -DPADD= ${LIBKICONV} -LDADD= -lkiconv - -MOUNT= ${.CURDIR}/../mount -CFLAGS+= -I${MOUNT} - -# Needs to be dynamically linked for optional dlopen() access to -# userland libiconv -NO_SHARED?= NO - -.PATH: ${MOUNT} - -.include diff --git a/sbin/mount_ntfs/mount_ntfs.8 b/sbin/mount_ntfs/mount_ntfs.8 deleted file mode 100644 index eb8ba690cb5..00000000000 --- a/sbin/mount_ntfs/mount_ntfs.8 +++ /dev/null @@ -1,173 +0,0 @@ -.\" -.\" Copyright (c) 1993,1994 Christopher G. Demetriou -.\" Copyright (c) 1999 Semen Ustimenko -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgment: -.\" This product includes software developed by Christopher G. Demetriou. -.\" 3. The name of the author may not be used to endorse or promote products -.\" derived from this software without specific prior written permission -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -.\" -.\" $FreeBSD$ -.\" -.Dd November 17, 2007 -.Dt MOUNT_NTFS 8 -.Os -.Sh NAME -.Nm mount_ntfs -.Nd mount an NTFS file system -.Sh SYNOPSIS -.Nm -.Op Fl a -.Op Fl i -.Op Fl u Ar user -.Op Fl g Ar group -.Op Fl m Ar mask -.Op Fl C Ar charset -.Op Fl W Ar u2wtable -.Pa special -.Pa node -.Sh DESCRIPTION -The -.Nm -utility attaches the NTFS file system residing on the device -.Pa special -to the global file system namespace at the location -indicated by -.Pa node . -This command is normally executed by -.Xr mount 8 -at boot time, but can be used by any user to mount an -NTFS file system on any directory that they own (provided, -of course, that they have appropriate access to the device that -contains the file system). -.Pp -The options are as follows: -.Bl -tag -width Ds -.It Fl a -Force behaviour to return MS-DOS 8.3 names also on -.Fn readdir . -.It Fl i -Make name lookup case insensitive for all names except POSIX names. -.It Fl u Ar user -Set the owner of the files in the file system to -.Ar user . -The default owner is the owner of the directory -on which the file system is being mounted. -.It Fl g Ar group -Set the group of the files in the file system to -.Ar group . -The default group is the group of the directory -on which the file system is being mounted. -.It Fl m Ar mask -Specify the maximum file permissions for files -in the file system. -Only the nine low-order bits of -.Ar mask -are used. -.It Fl C Ar charset -Specify local -.Ar charset -to convert Unicode file names. -Currently only reading is supported, thus the file system is to be -mounted read-only. -.It Fl W Ar u2wtable -Specify -.Ux -to -.Tn Unicode -translation table. -See -.Xr mount_msdosfs 8 -for the description of this option. -.Bf Em -This option is preserved for backward compatibility purpose only, -and will be removed in the future. -Please do not use this option. -.Ef -.El -.Sh FEATURES -NTFS file attributes are accessed in following way: -.Bd -literal -offset indent -foo[[:ATTRTYPE]:ATTRNAME] -.Ed -.Pp -.Sq ATTRTYPE -is one of the identifiers listed in $AttrDef file of -volume. -Default is $DATA. -.Sq ATTRNAME -is an attribute name. -Default is none. -.Sh EXAMPLES -To mount an NTFS volume located in -.Pa /dev/ad1s1 : -.Pp -.Dl "mount_ntfs /dev/ad1s1 /mnt" -.Pp -To get the volume name (in Unicode): -.Pp -.Dl "cat /mnt/\e$Volume:\e$VOLUME_NAME" -.Pp -To read directory raw data: -.Pp -.Dl "cat /mnt/foodir:\e$INDEX_ROOT:\e$I30" -.Pp -To mount a Japanese NTFS volume located in -.Pa /dev/ad0s1 : -.Pp -.Dl "mount_ntfs -C eucJP /dev/ad0s1 /mnt" -.Sh WRITING -There is limited writing ability. -Limitations: file must be nonresident -and must not contain any sparces (uninitialized areas); compressed -files are also not supported. -The file name must not contain multibyte characters. -.Sh SEE ALSO -.Xr mount 2 , -.Xr unmount 2 , -.Xr fstab 5 , -.Xr mount 8 , -.Xr mount_msdosfs 8 -.Sh HISTORY -The -.Nm -utility first appeared in -.Fx 3.0 . -.Pp -The Unicode conversion routine was added by -.An Ryuichiro Imura Aq imura@ryu16.org -in 2003. -.Sh AUTHORS -The NTFS kernel implementation, -.Nm -utility, and manual were written by -.An Semen Ustimenko Aq semenu@FreeBSD.org . -.Sh CAVEATS -This utility is primarily used for read access to an NTFS volume. -See the -.Sx WRITING -section for details about writing to an NTFS volume. -.Pp -For a full read-write NTFS support consider sysutils/fusefs-ntfs -port/package. diff --git a/sbin/mount_ntfs/mount_ntfs.c b/sbin/mount_ntfs/mount_ntfs.c deleted file mode 100644 index e46ac21d5d5..00000000000 --- a/sbin/mount_ntfs/mount_ntfs.c +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright (c) 1994 Christopher G. Demetriou - * Copyright (c) 1999 Semen Ustimenko - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Christopher G. Demetriou. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - * - */ - -#include -#include -#define NTFS -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mntopts.h" - -#define TRANSITION_PERIOD_HACK - -static struct mntopt mopts[] = { - MOPT_STDOPTS, - MOPT_END -}; - -static gid_t a_gid(char *); -static uid_t a_uid(char *); -static mode_t a_mask(char *); -static void usage(void) __dead2; - -static int set_charset(struct ntfs_args *); - -int -main(int argc, char *argv[]) -{ - struct ntfs_args args; - struct stat sb; - int c, mntflags, set_gid, set_uid, set_mask; - char *dev, *dir, mntpath[MAXPATHLEN]; - - mntflags = set_gid = set_uid = set_mask = 0; - (void)memset(&args, '\0', sizeof(args)); - args.cs_ntfs = NULL; - args.cs_local = NULL; - -#ifdef TRANSITION_PERIOD_HACK - while ((c = getopt(argc, argv, "aiu:g:m:o:C:W:")) != -1) { -#else - while ((c = getopt(argc, argv, "aiu:g:m:o:C:")) != -1) { -#endif - switch (c) { - case 'u': - args.uid = a_uid(optarg); - set_uid = 1; - break; - case 'g': - args.gid = a_gid(optarg); - set_gid = 1; - break; - case 'm': - args.mode = a_mask(optarg); - set_mask = 1; - break; - case 'i': - args.flag |= NTFS_MFLAG_CASEINS; - break; - case 'a': - args.flag |= NTFS_MFLAG_ALLNAMES; - break; - case 'o': - getmntopts(optarg, mopts, &mntflags, 0); - break; - case 'C': - args.cs_local = malloc(ICONV_CSNMAXLEN); - if (args.cs_local == NULL) - err(EX_OSERR, "malloc()"); - strncpy(args.cs_local, - kiconv_quirkcs(optarg, KICONV_VENDOR_MICSFT), - ICONV_CSNMAXLEN); - break; -#ifdef TRANSITION_PERIOD_HACK - case 'W': - args.cs_local = malloc(ICONV_CSNMAXLEN); - if (args.cs_local == NULL) - err(EX_OSERR, "malloc()"); - if (strcmp(optarg, "iso22dos") == 0) { - strcpy(args.cs_local, "ISO8859-2"); - } else if (strcmp(optarg, "iso72dos") == 0) { - strcpy(args.cs_local, "ISO8859-7"); - } else if (strcmp(optarg, "koi2dos") == 0) { - strcpy(args.cs_local, "KOI8-R"); - } else if (strcmp(optarg, "koi8u2dos") == 0) { - strcpy(args.cs_local, "KOI8-U"); - } else { - err(EX_NOINPUT, "%s", optarg); - } - break; -#endif /* TRANSITION_PERIOD_HACK */ - case '?': - default: - usage(); - break; - } - } - - if (optind + 2 != argc) - usage(); - - dev = argv[optind]; - dir = argv[optind + 1]; - - if (args.cs_local) { - if (set_charset(&args) == -1) - err(EX_OSERR, "ntfs_iconv"); - args.flag |= NTFS_MFLAG_KICONV; - /* - * XXX - * Force to be MNT_RDONLY, - * since only reading is supported right now, - */ - mntflags |= MNT_RDONLY; - } - - /* - * Resolve the mountpoint with realpath(3) and remove unnecessary - * slashes from the devicename if there are any. - */ - if (checkpath(dir, mntpath) != 0) - err(EX_USAGE, "%s", mntpath); - (void)rmslashes(dev, dev); - - args.fspec = dev; - args.export.ex_root = 65534; /* unchecked anyway on DOS fs */ - if (mntflags & MNT_RDONLY) - args.export.ex_flags = MNT_EXRDONLY; - else - args.export.ex_flags = 0; - if (!set_gid || !set_uid || !set_mask) { - if (stat(mntpath, &sb) == -1) - err(EX_OSERR, "stat %s", mntpath); - - if (!set_uid) - args.uid = sb.st_uid; - if (!set_gid) - args.gid = sb.st_gid; - if (!set_mask) - args.mode = sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); - } - - if (mount("ntfs", mntpath, mntflags, &args) < 0) - err(EX_OSERR, "%s", dev); - - exit (0); -} - -gid_t -a_gid(char *s) -{ - struct group *gr; - char *gname; - gid_t gid; - - if ((gr = getgrnam(s)) != NULL) - gid = gr->gr_gid; - else { - for (gname = s; *s && isdigit(*s); ++s); - if (!*s) - gid = atoi(gname); - else - errx(EX_NOUSER, "unknown group id: %s", gname); - } - return (gid); -} - -uid_t -a_uid(char *s) -{ - struct passwd *pw; - char *uname; - uid_t uid; - - if ((pw = getpwnam(s)) != NULL) - uid = pw->pw_uid; - else { - for (uname = s; *s && isdigit(*s); ++s); - if (!*s) - uid = atoi(uname); - else - errx(EX_NOUSER, "unknown user id: %s", uname); - } - return (uid); -} - -mode_t -a_mask(char *s) -{ - int done, rv=0; - char *ep; - - done = 0; - if (*s >= '0' && *s <= '7') { - done = 1; - rv = strtol(optarg, &ep, 8); - } - if (!done || rv < 0 || *ep) - errx(EX_USAGE, "invalid file mode: %s", s); - return (rv); -} - -void -usage(void) -{ -#ifdef TRANSITION_PERIOD_HACK - fprintf(stderr, "%s\n%s\n", - "usage: mount_ntfs [-a] [-i] [-u user] [-g group] [-m mask]", - " [-C charset] [-W u2wtable] special node"); -#else - fprintf(stderr, "usage: mount_ntfs [-a] [-i] [-u user] [-g group] [-m mask] [-C charset] special node\n"); -#endif - exit(EX_USAGE); -} - -int -set_charset(struct ntfs_args *pargs) -{ - int error; - - if (modfind("ntfs_iconv") < 0) - if (kldload("ntfs_iconv") < 0 || modfind("ntfs_iconv") < 0) { - warnx( "cannot find or load \"ntfs_iconv\" kernel module"); - return (-1); - } - - if ((pargs->cs_ntfs = malloc(ICONV_CSNMAXLEN)) == NULL) - return (-1); - strncpy(pargs->cs_ntfs, ENCODING_UNICODE, ICONV_CSNMAXLEN); - error = kiconv_add_xlat16_cspairs(pargs->cs_ntfs, pargs->cs_local); - if (error) - return (-1); - - return (0); -} diff --git a/sys/fs/ntfs/ntfs.h b/sys/fs/ntfs/ntfs.h deleted file mode 100644 index 26e86a952ff..00000000000 --- a/sys/fs/ntfs/ntfs.h +++ /dev/null @@ -1,308 +0,0 @@ -/* $NetBSD: ntfs.h,v 1.9 1999/10/31 19:45:26 jdolecek Exp $ */ - -/*- - * Copyright (c) 1998, 1999 Semen Ustimenko - * 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$ - */ - -/*#define NTFS_DEBUG 1*/ - -typedef uint64_t cn_t; -typedef uint16_t wchar; - -#pragma pack(1) -#define BBSIZE 1024 -#define BBOFF ((off_t)(0)) -#define BBLOCK 0 -#define NTFS_MFTINO 0 -#define NTFS_VOLUMEINO 3 -#define NTFS_ATTRDEFINO 4 -#define NTFS_ROOTINO 5 -#define NTFS_BITMAPINO 6 -#define NTFS_BOOTINO 7 -#define NTFS_BADCLUSINO 8 -#define NTFS_UPCASEINO 10 -#define NTFS_MAXFILENAME 255 - -struct fixuphdr { - uint32_t fh_magic; - uint16_t fh_foff; - uint16_t fh_fnum; -}; - -#define NTFS_AF_INRUN 0x00000001 -struct attrhdr { - uint32_t a_type; - uint32_t reclen; - uint8_t a_flag; - uint8_t a_namelen; - uint8_t a_nameoff; - uint8_t reserved1; - uint8_t a_compression; - uint8_t reserved2; - uint16_t a_index; -}; -#define NTFS_A_STD 0x10 -#define NTFS_A_ATTRLIST 0x20 -#define NTFS_A_NAME 0x30 -#define NTFS_A_VOLUMENAME 0x60 -#define NTFS_A_DATA 0x80 -#define NTFS_A_INDXROOT 0x90 -#define NTFS_A_INDX 0xA0 -#define NTFS_A_INDXBITMAP 0xB0 - -#define NTFS_MAXATTRNAME 255 -struct attr { - struct attrhdr a_hdr; - union { - struct { - uint16_t a_datalen; - uint16_t reserved1; - uint16_t a_dataoff; - uint16_t a_indexed; - } a_S_r; - struct { - cn_t a_vcnstart; - cn_t a_vcnend; - uint16_t a_dataoff; - uint16_t a_compressalg; - uint32_t reserved1; - uint64_t a_allocated; - uint64_t a_datalen; - uint64_t a_initialized; - } a_S_nr; - } a_S; -}; -#define a_r a_S.a_S_r -#define a_nr a_S.a_S_nr - -typedef struct { - uint64_t t_create; - uint64_t t_write; - uint64_t t_mftwrite; - uint64_t t_access; -} ntfs_times_t; - -#define NTFS_FFLAG_RDONLY 0x01LL -#define NTFS_FFLAG_HIDDEN 0x02LL -#define NTFS_FFLAG_SYSTEM 0x04LL -#define NTFS_FFLAG_ARCHIVE 0x20LL -#define NTFS_FFLAG_COMPRESSED 0x0800LL -#define NTFS_FFLAG_DIR 0x10000000LL - -struct attr_name { - uint32_t n_pnumber; /* Parent ntnode */ - uint32_t reserved; - ntfs_times_t n_times; - uint64_t n_size; - uint64_t n_attrsz; - uint64_t n_flag; - uint8_t n_namelen; - uint8_t n_nametype; - uint16_t n_name[1]; -}; - -#define NTFS_IRFLAG_INDXALLOC 0x00000001 -struct attr_indexroot { - uint32_t ir_unkn1; /* always 0x30 */ - uint32_t ir_unkn2; /* always 0x1 */ - uint32_t ir_size;/* ??? */ - uint32_t ir_unkn3; /* number of cluster */ - uint32_t ir_unkn4; /* always 0x10 */ - uint32_t ir_datalen; /* sizeof simething */ - uint32_t ir_allocated; /* same as above */ - uint16_t ir_flag;/* ?? always 1 */ - uint16_t ir_unkn7; -}; - -struct attr_attrlist { - uint32_t al_type; /* Attribute type */ - uint16_t reclen; /* length of this entry */ - uint8_t al_namelen; /* Attribute name len */ - uint8_t al_nameoff; /* Name offset from entry start */ - uint64_t al_vcnstart; /* VCN number */ - uint32_t al_inumber; /* Parent ntnode */ - uint32_t reserved; - uint16_t al_index; /* Attribute index in MFT record */ - uint16_t al_name[1]; /* Name */ -}; - -#define NTFS_INDXMAGIC (uint32_t)(0x58444E49) -struct attr_indexalloc { - struct fixuphdr ia_fixup; - uint64_t unknown1; - cn_t ia_bufcn; - uint16_t ia_hdrsize; - uint16_t unknown2; - uint32_t ia_inuse; - uint32_t ia_allocated; -}; - -#define NTFS_IEFLAG_SUBNODE 0x00000001 -#define NTFS_IEFLAG_LAST 0x00000002 - -struct attr_indexentry { - uint32_t ie_number; - uint32_t unknown1; - uint16_t reclen; - uint16_t ie_size; - uint32_t ie_flag; /* 1 - has subnodes, 2 - last */ - uint32_t ie_fpnumber; - uint32_t unknown2; - ntfs_times_t ie_ftimes; - uint64_t ie_fallocated; - uint64_t ie_fsize; - uint64_t ie_fflag; - uint8_t ie_fnamelen; - uint8_t ie_fnametype; - wchar ie_fname[NTFS_MAXFILENAME]; - /* cn_t ie_bufcn; buffer with subnodes */ -}; - -#define NTFS_FILEMAGIC (uint32_t)(0x454C4946) -#define NTFS_BLOCK_SIZE 512 -#define NTFS_FRFLAG_DIR 0x0002 -struct filerec { - struct fixuphdr fr_fixup; - uint8_t reserved[8]; - uint16_t fr_seqnum; /* Sequence number */ - uint16_t fr_nlink; - uint16_t fr_attroff; /* offset to attributes */ - uint16_t fr_flags; /* 1-nonresident attr, 2-directory */ - uint32_t fr_size;/* hdr + attributes */ - uint32_t fr_allocated; /* allocated length of record */ - uint64_t fr_mainrec; /* main record */ - uint16_t fr_attrnum; /* maximum attr number + 1 ??? */ -}; - -#define NTFS_ATTRNAME_MAXLEN 0x40 -#define NTFS_ADFLAG_NONRES 0x0080 /* Attrib can be non resident */ -#define NTFS_ADFLAG_INDEX 0x0002 /* Attrib can be indexed */ -struct attrdef { - wchar ad_name[NTFS_ATTRNAME_MAXLEN]; - uint32_t ad_type; - uint32_t reserved1[2]; - uint32_t ad_flag; - uint64_t ad_minlen; - uint64_t ad_maxlen; /* -1 for nonlimited */ -}; - -struct ntvattrdef { - char ad_name[0x40]; - int ad_namelen; - uint32_t ad_type; -}; - -#define NTFS_BBID "NTFS " -#define NTFS_BBIDLEN 8 -struct bootfile { - uint8_t reserved1[3]; /* asm jmp near ... */ - uint8_t bf_sysid[8]; /* 'NTFS ' */ - uint16_t bf_bps; /* bytes per sector */ - uint8_t bf_spc; /* sectors per cluster */ - uint8_t reserved2[7]; /* unused (zeroed) */ - uint8_t bf_media; /* media desc. (0xF8) */ - uint8_t reserved3[2]; - uint16_t bf_spt; /* sectors per track */ - uint16_t bf_heads; /* number of heads */ - uint8_t reserver4[12]; - uint64_t bf_spv; /* sectors per volume */ - cn_t bf_mftcn; /* $MFT cluster number */ - cn_t bf_mftmirrcn; /* $MFTMirr cn */ - uint8_t bf_mftrecsz; /* MFT record size (clust) */ - /* 0xF6 inducates 1/4 */ - uint32_t bf_ibsz; /* index buffer size */ - uint32_t bf_volsn; /* volume ser. num. */ -}; - -#define NTFS_SYSNODESNUM 0x0B -struct ntfsmount { - struct mount *ntm_mountp; /* filesystem vfs structure */ - struct bootfile ntm_bootfile; - struct g_consumer *ntm_cp; - struct bufobj *ntm_bo; - struct vnode *ntm_devvp; /* block device mounted vnode */ - struct vnode *ntm_sysvn[NTFS_SYSNODESNUM]; - uint32_t ntm_bpmftrec; - uid_t ntm_uid; - gid_t ntm_gid; - mode_t ntm_mode; - uint64_t ntm_flag; - cn_t ntm_cfree; - struct ntvattrdef *ntm_ad; - int ntm_adnum; - wchar * ntm_82u; /* 8bit to Unicode */ - char ** ntm_u28; /* Unicode to 8 bit */ - void * ntm_ic_l2u; /* Local to Unicode (iconv) */ - void * ntm_ic_u2l; /* Unicode to Local (iconv) */ - uint8_t ntm_multiplier; /* NTFS blockno to DEV_BSIZE sectorno */ -}; - -#define ntm_mftcn ntm_bootfile.bf_mftcn -#define ntm_mftmirrcn ntm_bootfile.bf_mftmirrcn -#define ntm_mftrecsz ntm_bootfile.bf_mftrecsz -#define ntm_spc ntm_bootfile.bf_spc -#define ntm_bps ntm_bootfile.bf_bps - -#pragma pack() - -#define NTFS_NEXTREC(s, type) ((type)(((caddr_t) s) + (s)->reclen)) - -/* Convert mount ptr to ntfsmount ptr. */ -#define VFSTONTFS(mp) ((struct ntfsmount *)((mp)->mnt_data)) -#define VTONT(v) FTONT(VTOF(v)) -#define VTOF(v) ((struct fnode *)((v)->v_data)) -#define FTOV(f) ((f)->f_vp) -#define FTONT(f) ((f)->f_ip) -#define ntfs_cntobn(cn) (daddr_t)((cn) * (ntmp->ntm_spc)) -#define ntfs_cntob(cn) (off_t)((cn) * (ntmp)->ntm_spc * (ntmp)->ntm_bps) -#define ntfs_btocn(off) (cn_t)((off) / ((ntmp)->ntm_spc * (ntmp)->ntm_bps)) -#define ntfs_btocl(off) (cn_t)((off + ntfs_cntob(1) - 1) / ((ntmp)->ntm_spc * (ntmp)->ntm_bps)) -#define ntfs_btocnoff(off) (off_t)((off) % ((ntmp)->ntm_spc * (ntmp)->ntm_bps)) -#define ntfs_bntob(bn) (daddr_t)((bn) * (ntmp)->ntm_bps) - -#define ntfs_bpbl (daddr_t)((ntmp)->ntm_bps) - -#ifdef MALLOC_DECLARE -MALLOC_DECLARE(M_NTFSNTNODE); -MALLOC_DECLARE(M_NTFSFNODE); -MALLOC_DECLARE(M_NTFSDIR); -MALLOC_DECLARE(M_NTFSNTHASH); -#endif - -#if defined(NTFS_DEBUG) -#define dprintf(a) printf a -#if NTFS_DEBUG > 1 -#define ddprintf(a) printf a -#else -#define ddprintf(a) (void)0 -#endif -#else -#define dprintf(a) (void)0 -#define ddprintf(a) (void)0 -#endif - -extern struct vop_vector ntfs_vnodeops; diff --git a/sys/fs/ntfs/ntfs_compr.c b/sys/fs/ntfs/ntfs_compr.c deleted file mode 100644 index dcc82a356ae..00000000000 --- a/sys/fs/ntfs/ntfs_compr.c +++ /dev/null @@ -1,111 +0,0 @@ -/* $NetBSD: ntfs_compr.c,v 1.3 1999/07/26 14:02:31 jdolecek Exp $ */ - -/*- - * Copyright (c) 1998, 1999 Semen Ustimenko - * 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 -#include -#include -#include -#include -#include - -#include -#include - -#define GET_UINT16(addr) (*((u_int16_t *)(addr))) - -int -ntfs_uncompblock( - u_int8_t * dbuf, - u_int8_t * cbuf) -{ - u_int32_t ctag; - int len, dshift, lmask; - int blen, boff; - int i, j; - int pos, cpos; - - len = GET_UINT16(cbuf) & 0xFFF; - dprintf(("ntfs_uncompblock: block length: %d + 3, 0x%x,0x%04x\n", - len, len, GET_UINT16(cbuf))); - - if (!(GET_UINT16(cbuf) & 0x8000)) { - if ((len + 1) != NTFS_COMPBLOCK_SIZE) { - dprintf(("ntfs_uncompblock: len: %x instead of %d\n", - len, 0xfff)); - } - memcpy(dbuf, cbuf + 2, len + 1); - memset(dbuf + len + 1, 0, NTFS_COMPBLOCK_SIZE - 1 - len); - return len + 3; - } - cpos = 2; - pos = 0; - while ((cpos < len + 3) && (pos < NTFS_COMPBLOCK_SIZE)) { - ctag = cbuf[cpos++]; - for (i = 0; (i < 8) && (pos < NTFS_COMPBLOCK_SIZE); i++) { - if (ctag & 1) { - for (j = pos - 1, lmask = 0xFFF, dshift = 12; - j >= 0x10; j >>= 1) { - dshift--; - lmask >>= 1; - } - boff = -1 - (GET_UINT16(cbuf + cpos) >> dshift); - blen = 3 + (GET_UINT16(cbuf + cpos) & lmask); - for (j = 0; (j < blen) && (pos < NTFS_COMPBLOCK_SIZE); j++) { - dbuf[pos] = dbuf[pos + boff]; - pos++; - } - cpos += 2; - } else { - dbuf[pos++] = cbuf[cpos++]; - } - ctag >>= 1; - } - } - return len + 3; -} - -int -ntfs_uncompunit( - struct ntfsmount * ntmp, - u_int8_t * uup, - u_int8_t * cup) -{ - int i; - int off = 0; - int new; - - for (i = 0; i * NTFS_COMPBLOCK_SIZE < ntfs_cntob(NTFS_COMPUNIT_CL); i++) { - new = ntfs_uncompblock(uup + i * NTFS_COMPBLOCK_SIZE, cup + off); - if (new == 0) - return (EINVAL); - off += new; - } - return (0); -} diff --git a/sys/fs/ntfs/ntfs_compr.h b/sys/fs/ntfs/ntfs_compr.h deleted file mode 100644 index e51bc09f2fd..00000000000 --- a/sys/fs/ntfs/ntfs_compr.h +++ /dev/null @@ -1,35 +0,0 @@ -/* $NetBSD: ntfs_compr.h,v 1.3 1999/07/26 14:02:31 jdolecek Exp $ */ - -/*- - * Copyright (c) 1998, 1999 Semen Ustimenko - * 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$ - */ - -#define NTFS_COMPBLOCK_SIZE 0x1000 -#define NTFS_COMPUNIT_CL 16 - -int ntfs_uncompblock(u_int8_t *, u_int8_t *); -int ntfs_uncompunit(struct ntfsmount *, u_int8_t *, u_int8_t *); diff --git a/sys/fs/ntfs/ntfs_iconv.c b/sys/fs/ntfs/ntfs_iconv.c deleted file mode 100644 index 347306e8853..00000000000 --- a/sys/fs/ntfs/ntfs_iconv.c +++ /dev/null @@ -1,36 +0,0 @@ -/*- - * Copyright (c) 2003 Ryuichiro Imura - * 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 -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include - -VFS_DECLARE_ICONV(ntfs); diff --git a/sys/fs/ntfs/ntfs_ihash.c b/sys/fs/ntfs/ntfs_ihash.c deleted file mode 100644 index bb40d5c2ac8..00000000000 --- a/sys/fs/ntfs/ntfs_ihash.c +++ /dev/null @@ -1,130 +0,0 @@ -/* $NetBSD: ntfs_ihash.c,v 1.5 1999/09/30 16:56:40 jdolecek Exp $ */ - -/*- - * Copyright (c) 1982, 1986, 1989, 1991, 1993, 1995 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)ufs_ihash.c 8.7 (Berkeley) 5/17/95 - * $FreeBSD$ - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -MALLOC_DEFINE(M_NTFSNTHASH, "ntfs_nthash", "NTFS ntnode hash tables"); - -/* - * Structures associated with inode cacheing. - */ -static LIST_HEAD(nthashhead, ntnode) *ntfs_nthashtbl; -static u_long ntfs_nthash; /* size of hash table - 1 */ -#define NTNOHASH(inum) (&ntfs_nthashtbl[(inum) & ntfs_nthash]) -static struct mtx ntfs_nthash_mtx; -struct lock ntfs_hashlock; - -/* - * Initialize inode hash table. - */ -void -ntfs_nthashinit() -{ - lockinit(&ntfs_hashlock, PINOD, "ntfs_nthashlock", 0, 0); - ntfs_nthashtbl = hashinit(desiredvnodes, M_NTFSNTHASH, &ntfs_nthash); - mtx_init(&ntfs_nthash_mtx, "ntfs nthash", NULL, MTX_DEF); -} - -/* - * Destroy inode hash table. - */ -void -ntfs_nthashdestroy(void) -{ - hashdestroy(ntfs_nthashtbl, M_NTFSNTHASH, ntfs_nthash); - lockdestroy(&ntfs_hashlock); - mtx_destroy(&ntfs_nthash_mtx); -} - -/* - * Use the device/inum pair to find the incore inode, and return a pointer - * to it. If it is in core, return it, even if it is locked. - */ -struct ntnode * -ntfs_nthashlookup(dev, inum) - struct cdev *dev; - ino_t inum; -{ - struct ntnode *ip; - - mtx_lock(&ntfs_nthash_mtx); - LIST_FOREACH(ip, NTNOHASH(inum), i_hash) - if (inum == ip->i_number && dev == ip->i_dev) - break; - mtx_unlock(&ntfs_nthash_mtx); - - return (ip); -} - -/* - * Insert the ntnode into the hash table. - */ -void -ntfs_nthashins(ip) - struct ntnode *ip; -{ - struct nthashhead *ipp; - - mtx_lock(&ntfs_nthash_mtx); - ipp = NTNOHASH(ip->i_number); - LIST_INSERT_HEAD(ipp, ip, i_hash); - ip->i_flag |= IN_HASHED; - mtx_unlock(&ntfs_nthash_mtx); -} - -/* - * Remove the inode from the hash table. - */ -void -ntfs_nthashrem(ip) - struct ntnode *ip; -{ - mtx_lock(&ntfs_nthash_mtx); - if (ip->i_flag & IN_HASHED) { - ip->i_flag &= ~IN_HASHED; - LIST_REMOVE(ip, i_hash); - } - mtx_unlock(&ntfs_nthash_mtx); -} diff --git a/sys/fs/ntfs/ntfs_ihash.h b/sys/fs/ntfs/ntfs_ihash.h deleted file mode 100644 index 7df7495c770..00000000000 --- a/sys/fs/ntfs/ntfs_ihash.h +++ /dev/null @@ -1,37 +0,0 @@ -/* $NetBSD: ntfs_ihash.h,v 1.4 1999/09/30 16:56:40 jdolecek Exp $ */ - -/*- - * Copyright (c) 1998, 1999 Semen Ustimenko - * 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$ - */ - -extern struct lock ntfs_hashlock; -void ntfs_nthashinit(void); -void ntfs_nthashdestroy(void); -struct ntnode *ntfs_nthashlookup(struct cdev *, ino_t); -struct ntnode *ntfs_nthashget(struct cdev *, ino_t); -void ntfs_nthashins(struct ntnode *); -void ntfs_nthashrem(register struct ntnode *); diff --git a/sys/fs/ntfs/ntfs_inode.h b/sys/fs/ntfs/ntfs_inode.h deleted file mode 100644 index c11cfa1f631..00000000000 --- a/sys/fs/ntfs/ntfs_inode.h +++ /dev/null @@ -1,101 +0,0 @@ -/* $NetBSD: ntfs_inode.h,v 1.8 1999/10/31 19:45:26 jdolecek Exp $ */ - -/*- - * Copyright (c) 1998, 1999 Semen Ustimenko - * 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$ - */ - -/* These flags are kept in i_flag. */ -#define IN_ACCESS 0x0001 /* Access time update request. */ -#define IN_CHANGE 0x0002 /* Inode change time update request. */ -#define IN_UPDATE 0x0004 /* Modification time update request. */ -#define IN_MODIFIED 0x0008 /* Inode has been modified. */ -#define IN_RENAME 0x0010 /* Inode is being renamed. */ -#define IN_SHLOCK 0x0020 /* File has shared lock. */ -#define IN_EXLOCK 0x0040 /* File has exclusive lock. */ -#define IN_LAZYMOD 0x0080 /* Modified, but don't write yet. */ -#define IN_HASHED 0x0800 /* Inode is on hash list */ -#define IN_LOADED 0x8000 /* ntvattrs loaded */ -#define IN_PRELOADED 0x4000 /* loaded from directory entry */ - -struct ntnode { - struct vnode *i_devvp; /* vnode of blk dev we live on */ - struct cdev *i_dev; /* Device associated with the inode. */ - - LIST_ENTRY(ntnode) i_hash; - struct ntnode *i_next; - struct ntnode **i_prev; - struct ntfsmount *i_mp; - ino_t i_number; - u_int32_t i_flag; - - /* locking */ - struct lock i_lock; - struct mtx i_interlock; - int i_usecount; - - LIST_HEAD(,fnode) i_fnlist; - LIST_HEAD(,ntvattr) i_valist; - - long i_nlink; /* MFR */ - ino_t i_mainrec; /* MFR */ - u_int32_t i_frflag; /* MFR */ -}; - -#define FN_PRELOADED 0x0001 -#define FN_VALID 0x0002 -#define FN_AATTRNAME 0x0004 /* space allocated for f_attrname */ -struct fnode { - LIST_ENTRY(fnode) f_fnlist; - struct vnode *f_vp; /* Associatied vnode */ - struct ntnode *f_ip; /* Associated ntnode */ - u_long f_flag; - - ntfs_times_t f_times; /* $NAME/dirinfo */ - ino_t f_pnumber; /* $NAME/dirinfo */ - u_int32_t f_fflag; /* $NAME/dirinfo */ - u_int64_t f_size; /* defattr/dirinfo: */ - u_int64_t f_allocated; /* defattr/dirinfo */ - - u_int32_t f_attrtype; - char *f_attrname; - - /* for ntreaddir */ - u_int32_t f_lastdattr; - u_int32_t f_lastdblnum; - u_int32_t f_lastdoff; - u_int32_t f_lastdnum; - caddr_t f_dirblbuf; - u_int32_t f_dirblsz; -}; - -/* This overlays the fid structure (see ) */ -struct ntfid { - u_int16_t ntfid_len; /* Length of structure. */ - u_int16_t ntfid_pad; /* Force 32-bit alignment. */ - ino_t ntfid_ino; /* File number (ino). */ - int32_t ntfid_gen; /* Generation number. */ -}; diff --git a/sys/fs/ntfs/ntfs_subr.c b/sys/fs/ntfs/ntfs_subr.c deleted file mode 100644 index dae77776c4f..00000000000 --- a/sys/fs/ntfs/ntfs_subr.c +++ /dev/null @@ -1,2029 +0,0 @@ -/* $NetBSD: ntfs_subr.c,v 1.23 1999/10/31 19:45:26 jdolecek Exp $ */ - -/*- - * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@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$ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* #define NTFS_DEBUG 1 */ -#include -#include -#include -#include -#include -#include -#include - -static MALLOC_DEFINE(M_NTFSNTVATTR, "ntfs_vattr", - "NTFS file attribute information"); -static MALLOC_DEFINE(M_NTFSRDATA, "ntfsd_resdata", "NTFS resident data"); -static MALLOC_DEFINE(M_NTFSRUN, "ntfs_vrun", "NTFS vrun storage"); -static MALLOC_DEFINE(M_NTFSDECOMP, "ntfs_decomp", - "NTFS decompression temporary"); - -static int ntfs_ntlookupattr(struct ntfsmount *, const char *, int, int *, char **); -static int ntfs_findvattr(struct ntfsmount *, struct ntnode *, struct ntvattr **, struct ntvattr **, u_int32_t, const char *, size_t, cn_t); -static int ntfs_uastricmp(struct ntfsmount *, const wchar *, size_t, const char *, size_t); -static int ntfs_uastrcmp(struct ntfsmount *, const wchar *, size_t, const char *, size_t); - -/* table for mapping Unicode chars into uppercase; it's filled upon first - * ntfs mount, freed upon last ntfs umount */ -static wchar *ntfs_toupper_tab; -#define NTFS_TOUPPER(ch) (ntfs_toupper_tab[(ch)]) -static struct lock ntfs_toupper_lock; -static signed int ntfs_toupper_usecount; - -struct iconv_functions *ntfs_iconv = NULL; - -/* support macro for ntfs_ntvattrget() */ -#define NTFS_AALPCMP(aalp,type,name,namelen) ( \ - (aalp->al_type == type) && (aalp->al_namelen == namelen) && \ - !NTFS_UASTRCMP(aalp->al_name,aalp->al_namelen,name,namelen) ) - -/* - * - */ -int -ntfs_ntvattrrele(vap) - struct ntvattr * vap; -{ - dprintf(("ntfs_ntvattrrele: ino: %ju, type: 0x%x\n", - (uintmax_t)vap->va_ip->i_number, vap->va_type)); - - ntfs_ntrele(vap->va_ip); - - return (0); -} - -/* - * find the attribute in the ntnode - */ -static int -ntfs_findvattr(ntmp, ip, lvapp, vapp, type, name, namelen, vcn) - struct ntfsmount *ntmp; - struct ntnode *ip; - struct ntvattr **lvapp, **vapp; - u_int32_t type; - const char *name; - size_t namelen; - cn_t vcn; -{ - int error; - struct ntvattr *vap; - - if((ip->i_flag & IN_LOADED) == 0) { - dprintf(("ntfs_findvattr: node not loaded, ino: %ju\n", - (uintmax_t)ip->i_number)); - error = ntfs_loadntnode(ntmp,ip); - if (error) { - printf("ntfs_findvattr: FAILED TO LOAD INO: %ju\n", - (uintmax_t)ip->i_number); - return (error); - } - } - - *lvapp = NULL; - *vapp = NULL; - LIST_FOREACH(vap, &ip->i_valist, va_list) { - ddprintf(("ntfs_findvattr: type: 0x%x, vcn: %d - %d\n", \ - vap->va_type, (u_int32_t) vap->va_vcnstart, \ - (u_int32_t) vap->va_vcnend)); - if ((vap->va_type == type) && - (vap->va_vcnstart <= vcn) && (vap->va_vcnend >= vcn) && - (vap->va_namelen == namelen) && - (strncmp(name, vap->va_name, namelen) == 0)) { - *vapp = vap; - ntfs_ntref(vap->va_ip); - return (0); - } - if (vap->va_type == NTFS_A_ATTRLIST) - *lvapp = vap; - } - - return (-1); -} - -/* - * Search attribute specifed in ntnode (load ntnode if nessecary). - * If not found but ATTR_A_ATTRLIST present, read it in and search throught. - * VOP_VGET node needed, and lookup througth it's ntnode (load if nessesary). - * - * ntnode should be locked - */ -int -ntfs_ntvattrget( - struct ntfsmount * ntmp, - struct ntnode * ip, - u_int32_t type, - const char *name, - cn_t vcn, - struct ntvattr ** vapp) -{ - struct ntvattr *lvap = NULL; - struct attr_attrlist *aalp; - struct attr_attrlist *nextaalp; - struct vnode *newvp; - struct ntnode *newip; - caddr_t alpool; - size_t namelen, len; - int error; - - *vapp = NULL; - - if (name) { - dprintf(("ntfs_ntvattrget: " \ - "ino: %ju, type: 0x%x, name: %s, vcn: %d\n", \ - (uintmax_t)ip->i_number, type, name, (uint32_t)vcn)); - namelen = strlen(name); - } else { - dprintf(("ntfs_ntvattrget: " \ - "ino: %ju, type: 0x%x, vcn: %d\n", \ - (uintmax_t)ip->i_number, type, (uint32_t)vcn)); - name = ""; - namelen = 0; - } - - error = ntfs_findvattr(ntmp, ip, &lvap, vapp, type, name, namelen, vcn); - if (error >= 0) - return (error); - - if (!lvap) { - dprintf(("ntfs_ntvattrget: UNEXISTED ATTRIBUTE: " \ - "ino: %ju, type: 0x%x, name: %s, vcn: %d\n", \ - (uintmax_t)ip->i_number, type, name, (uint32_t)vcn)); - return (ENOENT); - } - /* Scan $ATTRIBUTE_LIST for requested attribute */ - len = lvap->va_datalen; - alpool = malloc(len, M_TEMP, M_WAITOK); - error = ntfs_readntvattr_plain(ntmp, ip, lvap, 0, len, alpool, &len, - NULL); - if (error) - goto out; - - aalp = (struct attr_attrlist *) alpool; - nextaalp = NULL; - - for(; len > 0; aalp = nextaalp) { - dprintf(("ntfs_ntvattrget: " \ - "attrlist: ino: %ju, attr: 0x%x, vcn: %d\n", \ - (uintmax_t)aalp->al_inumber, aalp->al_type, \ - (uint32_t)aalp->al_vcnstart)); - - if (len > aalp->reclen) { - nextaalp = NTFS_NEXTREC(aalp, struct attr_attrlist *); - } else { - nextaalp = NULL; - } - len -= aalp->reclen; - - if (!NTFS_AALPCMP(aalp, type, name, namelen) || - (nextaalp && (nextaalp->al_vcnstart <= vcn) && - NTFS_AALPCMP(nextaalp, type, name, namelen))) - continue; - - dprintf(("ntfs_ntvattrget: attribute in ino: %ju\n", - (uintmax_t)aalp->al_inumber)); - - /* this is not a main record, so we can't use just plain - vget() */ - error = ntfs_vgetex(ntmp->ntm_mountp, aalp->al_inumber, - NTFS_A_DATA, NULL, LK_EXCLUSIVE, - VG_EXT, curthread, &newvp); - if (error) { - printf("ntfs_ntvattrget: CAN'T VGET INO: %ju\n", - (uintmax_t)aalp->al_inumber); - goto out; - } - newip = VTONT(newvp); - /* XXX have to lock ntnode */ - error = ntfs_findvattr(ntmp, newip, &lvap, vapp, - type, name, namelen, vcn); - vput(newvp); - if (error == 0) - goto out; - printf("ntfs_ntvattrget: ATTRLIST ERROR.\n"); - break; - } - error = ENOENT; - - dprintf(("ntfs_ntvattrget: UNEXISTED ATTRIBUTE: " \ - "ino: %ju, type: 0x%x, name: %.*s, vcn: %d\n", \ - (uintmax_t)ip->i_number, type, (int)namelen, name, (uint32_t)vcn)); -out: - free(alpool, M_TEMP); - return (error); -} - -/* - * Read ntnode from disk, make ntvattr list. - * - * ntnode should be locked - */ -int -ntfs_loadntnode( - struct ntfsmount * ntmp, - struct ntnode * ip) -{ - struct filerec *mfrp; - daddr_t bn; - int error,off; - struct attr *ap; - struct ntvattr *nvap; - - dprintf(("ntfs_loadntnode: loading ino: %ju\n", - (uintmax_t)ip->i_number)); - - mfrp = malloc(ntfs_bntob(ntmp->ntm_bpmftrec), - M_TEMP, M_WAITOK); - - if (ip->i_number < NTFS_SYSNODESNUM) { - struct buf *bp; - - dprintf(("ntfs_loadntnode: read system node\n")); - - bn = ntfs_cntobn(ntmp->ntm_mftcn) + - ntmp->ntm_bpmftrec * ip->i_number; - bn *= ntmp->ntm_multiplier; - - error = bread(ntmp->ntm_devvp, - bn, ntfs_bntob(ntmp->ntm_bpmftrec), - NOCRED, &bp); - if (error) { - printf("ntfs_loadntnode: BREAD FAILED\n"); - brelse(bp); - goto out; - } - memcpy(mfrp, bp->b_data, ntfs_bntob(ntmp->ntm_bpmftrec)); - bqrelse(bp); - } else { - struct vnode *vp; - - vp = ntmp->ntm_sysvn[NTFS_MFTINO]; - error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL, - ip->i_number * ntfs_bntob(ntmp->ntm_bpmftrec), - ntfs_bntob(ntmp->ntm_bpmftrec), mfrp, NULL); - if (error) { - printf("ntfs_loadntnode: ntfs_readattr failed\n"); - goto out; - } - } - - /* Check if magic and fixups are correct */ - error = ntfs_procfixups(ntmp, NTFS_FILEMAGIC, (caddr_t)mfrp, - ntfs_bntob(ntmp->ntm_bpmftrec)); - if (error) { - printf("ntfs_loadntnode: BAD MFT RECORD %ju\n", - (uintmax_t)ip->i_number); - goto out; - } - - dprintf(("ntfs_loadntnode: load attrs for ino: %ju\n", - (uintmax_t)ip->i_number)); - off = mfrp->fr_attroff; - ap = (struct attr *) ((caddr_t)mfrp + off); - - LIST_INIT(&ip->i_valist); - - while (ap->a_hdr.a_type != -1) { - error = ntfs_attrtontvattr(ntmp, &nvap, ap); - if (error) - break; - nvap->va_ip = ip; - - LIST_INSERT_HEAD(&ip->i_valist, nvap, va_list); - - off += ap->a_hdr.reclen; - ap = (struct attr *) ((caddr_t)mfrp + off); - } - if (error) { - printf("ntfs_loadntnode: failed to load attr ino: %ju\n", - (uintmax_t)ip->i_number); - goto out; - } - - ip->i_mainrec = mfrp->fr_mainrec; - ip->i_nlink = mfrp->fr_nlink; - ip->i_frflag = mfrp->fr_flags; - - ip->i_flag |= IN_LOADED; - -out: - free(mfrp, M_TEMP); - return (error); -} - -/* - * Routine locks ntnode and increase usecount, just opposite of - * ntfs_ntput(). - */ -int -ntfs_ntget(ip) - struct ntnode *ip; -{ - dprintf(("ntfs_ntget: get ntnode %ju: %p, usecount: %d\n", - (uintmax_t)ip->i_number, ip, ip->i_usecount)); - - mtx_lock(&ip->i_interlock); - ip->i_usecount++; - lockmgr(&ip->i_lock, LK_EXCLUSIVE | LK_INTERLOCK, &ip->i_interlock); - - return 0; -} - -/* - * Routine search ntnode in hash, if found: lock, inc usecount and return. - * If not in hash allocate structure for ntnode, prefill it, lock, - * inc count and return. - * - * ntnode returned locked - */ -int -ntfs_ntlookup( - struct ntfsmount * ntmp, - ino_t ino, - struct ntnode ** ipp) -{ - struct ntnode *ip; - - dprintf(("ntfs_ntlookup: looking for ntnode %d\n", ino)); - - do { - ip = ntfs_nthashlookup(ntmp->ntm_devvp->v_rdev, ino); - if (ip != NULL) { - ntfs_ntget(ip); - dprintf(("ntfs_ntlookup: ntnode %d: %p, usecount: %d\n", - ino, ip, ip->i_usecount)); - *ipp = ip; - return (0); - } - } while (lockmgr(&ntfs_hashlock, LK_EXCLUSIVE | LK_SLEEPFAIL, NULL)); - - ip = malloc(sizeof(struct ntnode), M_NTFSNTNODE, - M_WAITOK | M_ZERO); - ddprintf(("ntfs_ntlookup: allocating ntnode: %d: %p\n", ino, ip)); - - /* Generic initialization */ - ip->i_devvp = ntmp->ntm_devvp; - ip->i_dev = ntmp->ntm_devvp->v_rdev; - ip->i_number = ino; - ip->i_mp = ntmp; - - LIST_INIT(&ip->i_fnlist); - VREF(ip->i_devvp); - - /* init lock and lock the newborn ntnode */ - lockinit(&ip->i_lock, PINOD, "ntnode", 0, 0); - mtx_init(&ip->i_interlock, "ntnode interlock", NULL, MTX_DEF); - ntfs_ntget(ip); - - ntfs_nthashins(ip); - - lockmgr(&ntfs_hashlock, LK_RELEASE, NULL); - - *ipp = ip; - - dprintf(("ntfs_ntlookup: ntnode %d: %p, usecount: %d\n", - ino, ip, ip->i_usecount)); - - return (0); -} - -/* - * Decrement usecount of ntnode and unlock it, if usecount reach zero, - * deallocate ntnode. - * - * ntnode should be locked on entry, and unlocked on return. - */ -void -ntfs_ntput(ip) - struct ntnode *ip; -{ - struct ntvattr *vap; - - dprintf(("ntfs_ntput: rele ntnode %ju: %p, usecount: %d\n", - (uintmax_t)ip->i_number, ip, ip->i_usecount)); - - mtx_lock(&ip->i_interlock); - ip->i_usecount--; - -#ifdef DIAGNOSTIC - if (ip->i_usecount < 0) { - panic("ntfs_ntput: ino: %ju usecount: %d \n", - (uintmax_t)ip->i_number, ip->i_usecount); - } -#endif - - if (ip->i_usecount > 0) { - lockmgr(&ip->i_lock, LK_RELEASE|LK_INTERLOCK, &ip->i_interlock); - return; - } - - dprintf(("ntfs_ntput: deallocating ntnode: %ju\n", - (uintmax_t)ip->i_number)); - - if (LIST_FIRST(&ip->i_fnlist)) - panic("ntfs_ntput: ntnode has fnodes\n"); - - ntfs_nthashrem(ip); - - while ((vap = LIST_FIRST(&ip->i_valist)) != NULL) { - LIST_REMOVE(vap,va_list); - ntfs_freentvattr(vap); - } - lockmgr(&ip->i_lock, LK_RELEASE | LK_INTERLOCK, &ip->i_interlock); - mtx_destroy(&ip->i_interlock); - lockdestroy(&ip->i_lock); - vrele(ip->i_devvp); - free(ip, M_NTFSNTNODE); -} - -/* - * increment usecount of ntnode - */ -void -ntfs_ntref(ip) - struct ntnode *ip; -{ - mtx_lock(&ip->i_interlock); - ip->i_usecount++; - mtx_unlock(&ip->i_interlock); - - dprintf(("ntfs_ntref: ino %ju, usecount: %d\n", - (uintmax_t)ip->i_number, ip->i_usecount)); -} - -/* - * Decrement usecount of ntnode. - */ -void -ntfs_ntrele(ip) - struct ntnode *ip; -{ - dprintf(("ntfs_ntrele: rele ntnode %ju: %p, usecount: %d\n", - (uintmax_t)ip->i_number, ip, ip->i_usecount)); - - mtx_lock(&ip->i_interlock); - ip->i_usecount--; - - if (ip->i_usecount < 0) - panic("ntfs_ntrele: ino: %ju usecount: %d \n", - (uintmax_t)ip->i_number, ip->i_usecount); - mtx_unlock(&ip->i_interlock); -} - -/* - * Deallocate all memory allocated for ntvattr - */ -void -ntfs_freentvattr(vap) - struct ntvattr * vap; -{ - if (vap->va_flag & NTFS_AF_INRUN) { - if (vap->va_vruncn) - free(vap->va_vruncn, M_NTFSRUN); - if (vap->va_vruncl) - free(vap->va_vruncl, M_NTFSRUN); - } else { - if (vap->va_datap) - free(vap->va_datap, M_NTFSRDATA); - } - free(vap, M_NTFSNTVATTR); -} - -/* - * Convert disk image of attribute into ntvattr structure, - * runs are expanded also. - */ -int -ntfs_attrtontvattr( - struct ntfsmount * ntmp, - struct ntvattr ** rvapp, - struct attr * rap) -{ - int error, i; - struct ntvattr *vap; - - error = 0; - *rvapp = NULL; - - vap = malloc(sizeof(struct ntvattr), - M_NTFSNTVATTR, M_WAITOK | M_ZERO); - vap->va_ip = NULL; - vap->va_flag = rap->a_hdr.a_flag; - vap->va_type = rap->a_hdr.a_type; - vap->va_compression = rap->a_hdr.a_compression; - vap->va_index = rap->a_hdr.a_index; - - ddprintf(("type: 0x%x, index: %d", vap->va_type, vap->va_index)); - - vap->va_namelen = rap->a_hdr.a_namelen; - if (rap->a_hdr.a_namelen) { - wchar *unp = (wchar *) ((caddr_t) rap + rap->a_hdr.a_nameoff); - ddprintf((", name:[")); - for (i = 0; i < vap->va_namelen; i++) { - vap->va_name[i] = unp[i]; - ddprintf(("%c", vap->va_name[i])); - } - ddprintf(("]")); - } - if (vap->va_flag & NTFS_AF_INRUN) { - ddprintf((", nonres.")); - vap->va_datalen = rap->a_nr.a_datalen; - vap->va_allocated = rap->a_nr.a_allocated; - vap->va_vcnstart = rap->a_nr.a_vcnstart; - vap->va_vcnend = rap->a_nr.a_vcnend; - vap->va_compressalg = rap->a_nr.a_compressalg; - error = ntfs_runtovrun(&(vap->va_vruncn), &(vap->va_vruncl), - &(vap->va_vruncnt), - (caddr_t) rap + rap->a_nr.a_dataoff); - } else { - vap->va_compressalg = 0; - ddprintf((", res.")); - vap->va_datalen = rap->a_r.a_datalen; - vap->va_allocated = rap->a_r.a_datalen; - vap->va_vcnstart = 0; - vap->va_vcnend = ntfs_btocn(vap->va_allocated); - vap->va_datap = malloc(vap->va_datalen, - M_NTFSRDATA, M_WAITOK); - memcpy(vap->va_datap, (caddr_t) rap + rap->a_r.a_dataoff, - rap->a_r.a_datalen); - } - ddprintf((", len: %lld", vap->va_datalen)); - - if (error) - free(vap, M_NTFSNTVATTR); - else - *rvapp = vap; - - ddprintf(("\n")); - - return (error); -} - -/* - * Expand run into more utilizable and more memory eating format. - */ -int -ntfs_runtovrun( - cn_t ** rcnp, - cn_t ** rclp, - u_long * rcntp, - u_int8_t * run) -{ - u_int32_t off; - u_int32_t sz, i; - cn_t *cn; - cn_t *cl; - u_long cnt; - cn_t prev; - cn_t tmp; - - off = 0; - cnt = 0; - i = 0; - while (run[off]) { - off += (run[off] & 0xF) + ((run[off] >> 4) & 0xF) + 1; - cnt++; - } - cn = malloc(cnt * sizeof(cn_t), M_NTFSRUN, M_WAITOK); - cl = malloc(cnt * sizeof(cn_t), M_NTFSRUN, M_WAITOK); - - off = 0; - cnt = 0; - prev = 0; - while (run[off]) { - - sz = run[off++]; - cl[cnt] = 0; - - for (i = 0; i < (sz & 0xF); i++) - cl[cnt] += (u_int32_t) run[off++] << (i << 3); - - sz >>= 4; - if (run[off + sz - 1] & 0x80) { - tmp = ((u_int64_t) - 1) << (sz << 3); - for (i = 0; i < sz; i++) - tmp |= (u_int64_t) run[off++] << (i << 3); - } else { - tmp = 0; - for (i = 0; i < sz; i++) - tmp |= (u_int64_t) run[off++] << (i << 3); - } - if (tmp) - prev = cn[cnt] = prev + tmp; - else - cn[cnt] = tmp; - - cnt++; - } - *rcnp = cn; - *rclp = cl; - *rcntp = cnt; - return (0); -} - -/* - * Compare unicode and ascii string case insens. - */ -static int -ntfs_uastricmp(ntmp, ustr, ustrlen, astr, astrlen) - struct ntfsmount *ntmp; - const wchar *ustr; - size_t ustrlen; - const char *astr; - size_t astrlen; -{ - const char *astrp = astr; - char tmpbuf[5]; - int len, res; - size_t i, j, mbstrlen = astrlen; - - if (ntmp->ntm_ic_l2u) { - for (i = 0, j = 0; i < ustrlen && j < astrlen; i++) { - len = 4; - res = ((int) NTFS_TOUPPER(ustr[i])) - - ((int)NTFS_TOUPPER(NTFS_82U(astrp, &len))); - astrp += len; - j += len; - mbstrlen -= len - 1; - - if (res) - return res; - } - } else { - /* - * We use NTFS_82U(NTFS_U28(c)) to get rid of unicode - * symbols not covered by translation table - */ - for (i = 0; i < ustrlen && i < astrlen; i++) { - res = ((int) NTFS_TOUPPER(NTFS_82U(NTFS_U28(ustr[i]), &len))) - - ((int)NTFS_TOUPPER(NTFS_82U(astrp, &len))); - astrp++; - if (res) - return res; - } - } - return (ustrlen - mbstrlen); -} - -/* - * Compare unicode and ascii string case sens. - */ -static int -ntfs_uastrcmp(ntmp, ustr, ustrlen, astr, astrlen) - struct ntfsmount *ntmp; - const wchar *ustr; - size_t ustrlen; - const char *astr; - size_t astrlen; -{ - char *c, tmpbuf[5]; - size_t i, j, mbstrlen = astrlen; - int res; - - for (i = 0, j = 0; (i < ustrlen) && (j < astrlen); i++, mbstrlen++) { - c = NTFS_U28(ustr[i]); - while (*c != '\0') { - res = (int) (*c++ - astr[j++]); - if (res) - return res; - mbstrlen--; - } - } - return (ustrlen - mbstrlen); -} - -/* - * Search fnode in ntnode, if not found allocate and preinitialize. - * - * ntnode should be locked on entry. - */ -int -ntfs_fget( - struct ntfsmount *ntmp, - struct ntnode *ip, - int attrtype, - char *attrname, - struct fnode **fpp) -{ - struct fnode *fp; - - dprintf(("ntfs_fget: ino: %ju, attrtype: 0x%x, attrname: %s\n", - (uintmax_t)ip->i_number, attrtype, attrname ? attrname : "")); - *fpp = NULL; - LIST_FOREACH(fp, &ip->i_fnlist, f_fnlist){ - dprintf(("ntfs_fget: fnode: attrtype: %d, attrname: %s\n", - fp->f_attrtype, fp->f_attrname?fp->f_attrname:"")); - - if ((attrtype == fp->f_attrtype) && - ((!attrname && !fp->f_attrname) || - (attrname && fp->f_attrname && - !strcmp(attrname,fp->f_attrname)))){ - dprintf(("ntfs_fget: found existed: %p\n",fp)); - *fpp = fp; - } - } - - if (*fpp) - return (0); - - fp = malloc(sizeof(struct fnode), M_NTFSFNODE, - M_WAITOK | M_ZERO); - dprintf(("ntfs_fget: allocating fnode: %p\n",fp)); - - fp->f_ip = ip; - if (attrname) { - fp->f_flag |= FN_AATTRNAME; - fp->f_attrname = malloc(strlen(attrname)+1, M_TEMP, M_WAITOK); - strcpy(fp->f_attrname, attrname); - } else - fp->f_attrname = NULL; - fp->f_attrtype = attrtype; - - ntfs_ntref(ip); - - LIST_INSERT_HEAD(&ip->i_fnlist, fp, f_fnlist); - - *fpp = fp; - - return (0); -} - -/* - * Deallocate fnode, remove it from ntnode's fnode list. - * - * ntnode should be locked. - */ -void -ntfs_frele( - struct fnode *fp) -{ - struct ntnode *ip = FTONT(fp); - - dprintf(("ntfs_frele: fnode: %p for %ju: %p\n", - fp, (uintmax_t)ip->i_number, ip)); - - dprintf(("ntfs_frele: deallocating fnode\n")); - LIST_REMOVE(fp,f_fnlist); - if (fp->f_flag & FN_AATTRNAME) - free(fp->f_attrname, M_TEMP); - if (fp->f_dirblbuf) - free(fp->f_dirblbuf, M_NTFSDIR); - free(fp, M_NTFSFNODE); - ntfs_ntrele(ip); -} - -/* - * Lookup attribute name in format: [[:$ATTR_TYPE]:$ATTR_NAME], - * $ATTR_TYPE is searched in attrdefs read from $AttrDefs. - * If $ATTR_TYPE nott specifed, ATTR_A_DATA assumed. - */ -static int -ntfs_ntlookupattr( - struct ntfsmount * ntmp, - const char * name, - int namelen, - int *attrtype, - char **attrname) -{ - const char *sys; - size_t syslen, i; - struct ntvattrdef *adp; - - if (namelen == 0) - return (0); - - if (name[0] == '$') { - sys = name; - for (syslen = 0; syslen < namelen; syslen++) { - if(sys[syslen] == ':') { - name++; - namelen--; - break; - } - } - name += syslen; - namelen -= syslen; - - adp = ntmp->ntm_ad; - for (i = 0; i < ntmp->ntm_adnum; i++, adp++){ - if (syslen != adp->ad_namelen || - strncmp(sys, adp->ad_name, syslen) != 0) - continue; - - *attrtype = adp->ad_type; - goto out; - } - return (ENOENT); - } else - *attrtype = NTFS_A_DATA; - - out: - if (namelen) { - (*attrname) = malloc(namelen, M_TEMP, M_WAITOK); - memcpy((*attrname), name, namelen); - (*attrname)[namelen] = '\0'; - } - - return (0); -} - -/* - * Lookup specifed node for filename, matching cnp, - * return fnode filled. - */ -int -ntfs_ntlookupfile( - struct ntfsmount * ntmp, - struct vnode * vp, - struct componentname * cnp, - struct vnode ** vpp) -{ - struct fnode *fp = VTOF(vp); - struct ntnode *ip = FTONT(fp); - struct ntvattr *vap; /* Root attribute */ - cn_t cn; /* VCN in current attribute */ - caddr_t rdbuf; /* Buffer to read directory's blocks */ - u_int32_t blsize; - u_int64_t rdsize; /* Length of data to read from current block */ - struct attr_indexentry *iep; - int error, res, anamelen, fnamelen; - const char *fname,*aname; - u_int32_t aoff; - int attrtype = NTFS_A_DATA; - char *attrname = NULL; - struct fnode *nfp; - struct vnode *nvp; - enum vtype f_type; - - error = ntfs_ntget(ip); - if (error) - return (error); - - error = ntfs_ntvattrget(ntmp, ip, NTFS_A_INDXROOT, "$I30", 0, &vap); - if (error || (vap->va_flag & NTFS_AF_INRUN)) - return (ENOTDIR); - - blsize = vap->va_a_iroot->ir_size; - rdsize = vap->va_datalen; - - /* - * Divide file name into: foofilefoofilefoofile[:attrspec] - * Store like this: fname:fnamelen [aname:anamelen] - */ - fname = cnp->cn_nameptr; - aname = NULL; - anamelen = 0; - for (fnamelen = 0; fnamelen < cnp->cn_namelen; fnamelen++) - if(fname[fnamelen] == ':') { - aname = fname + fnamelen + 1; - anamelen = cnp->cn_namelen - fnamelen - 1; - dprintf(("ntfs_ntlookupfile: %s (%d), attr: %s (%d)\n", - fname, fnamelen, aname, anamelen)); - break; - } - - dprintf(("ntfs_ntlookupfile: blksz: %d, rdsz: %jd\n", blsize, rdsize)); - - rdbuf = malloc(blsize, M_TEMP, M_WAITOK); - - error = ntfs_readattr(ntmp, ip, NTFS_A_INDXROOT, "$I30", - 0, rdsize, rdbuf, NULL); - if (error) - goto fail; - - aoff = sizeof(struct attr_indexroot); - - do { - iep = (struct attr_indexentry *) (rdbuf + aoff); - - for (; !(iep->ie_flag & NTFS_IEFLAG_LAST) && (rdsize > aoff); - aoff += iep->reclen, - iep = (struct attr_indexentry *) (rdbuf + aoff)) - { - ddprintf(("scan: %d, %d\n", - (u_int32_t) iep->ie_number, - (u_int32_t) iep->ie_fnametype)); - - /* check the name - the case-insensitible check - * has to come first, to break from this for loop - * if needed, so we can dive correctly */ - res = NTFS_UASTRICMP(iep->ie_fname, iep->ie_fnamelen, - fname, fnamelen); - if (res > 0) break; - if (res < 0) continue; - - if (iep->ie_fnametype == 0 || - !(ntmp->ntm_flag & NTFS_MFLAG_CASEINS)) - { - res = NTFS_UASTRCMP(iep->ie_fname, - iep->ie_fnamelen, fname, fnamelen); - if (res != 0) continue; - } - - if (aname) { - error = ntfs_ntlookupattr(ntmp, - aname, anamelen, - &attrtype, &attrname); - if (error) - goto fail; - } - - /* Check if we've found ourself */ - if ((iep->ie_number == ip->i_number) && - (attrtype == fp->f_attrtype) && - ((!attrname && !fp->f_attrname) || - (attrname && fp->f_attrname && - !strcmp(attrname, fp->f_attrname)))) - { - VREF(vp); - *vpp = vp; - error = 0; - goto fail; - } - - /* vget node, but don't load it */ - error = ntfs_vgetex(ntmp->ntm_mountp, - iep->ie_number, attrtype, attrname, - LK_EXCLUSIVE, VG_DONTLOADIN | VG_DONTVALIDFN, - curthread, &nvp); - - /* free the buffer returned by ntfs_ntlookupattr() */ - if (attrname) { - free(attrname, M_TEMP); - attrname = NULL; - } - - if (error) - goto fail; - - nfp = VTOF(nvp); - - if (nfp->f_flag & FN_VALID) { - *vpp = nvp; - goto fail; - } - - nfp->f_fflag = iep->ie_fflag; - nfp->f_pnumber = iep->ie_fpnumber; - nfp->f_times = iep->ie_ftimes; - - if((nfp->f_fflag & NTFS_FFLAG_DIR) && - (nfp->f_attrtype == NTFS_A_DATA) && - (nfp->f_attrname == NULL)) - f_type = VDIR; - else - f_type = VREG; - - nvp->v_type = f_type; - - if ((nfp->f_attrtype == NTFS_A_DATA) && - (nfp->f_attrname == NULL)) - { - /* Opening default attribute */ - nfp->f_size = iep->ie_fsize; - nfp->f_allocated = iep->ie_fallocated; - nfp->f_flag |= FN_PRELOADED; - } else { - error = ntfs_filesize(ntmp, nfp, - &nfp->f_size, &nfp->f_allocated); - if (error) { - vput(nvp); - goto fail; - } - } - - nfp->f_flag &= ~FN_VALID; - *vpp = nvp; - goto fail; - } - - /* Dive if possible */ - if (iep->ie_flag & NTFS_IEFLAG_SUBNODE) { - dprintf(("ntfs_ntlookupfile: diving\n")); - - cn = *(cn_t *) (rdbuf + aoff + - iep->reclen - sizeof(cn_t)); - rdsize = blsize; - - error = ntfs_readattr(ntmp, ip, NTFS_A_INDX, "$I30", - ntfs_cntob(cn), rdsize, rdbuf, NULL); - if (error) - goto fail; - - error = ntfs_procfixups(ntmp, NTFS_INDXMAGIC, - rdbuf, rdsize); - if (error) - goto fail; - - aoff = (((struct attr_indexalloc *) rdbuf)->ia_hdrsize + - 0x18); - } else { - dprintf(("ntfs_ntlookupfile: nowhere to dive :-(\n")); - error = ENOENT; - break; - } - } while (1); - - dprintf(("finish\n")); - -fail: - if (attrname) free(attrname, M_TEMP); - ntfs_ntvattrrele(vap); - ntfs_ntput(ip); - free(rdbuf, M_TEMP); - return (error); -} - -/* - * Check if name type is permitted to show. - */ -int -ntfs_isnamepermitted( - struct ntfsmount * ntmp, - struct attr_indexentry * iep) -{ - if (ntmp->ntm_flag & NTFS_MFLAG_ALLNAMES) - return 1; - - switch (iep->ie_fnametype) { - case 2: - ddprintf(("ntfs_isnamepermitted: skipped DOS name\n")); - return 0; - case 0: case 1: case 3: - return 1; - default: - printf("ntfs_isnamepermitted: " \ - "WARNING! Unknown file name type: %d\n", - iep->ie_fnametype); - break; - } - return 0; -} - -/* - * Read ntfs dir like stream of attr_indexentry, not like btree of them. - * This is done by scaning $BITMAP:$I30 for busy clusters and reading them. - * Ofcouse $INDEX_ROOT:$I30 is read before. Last read values are stored in - * fnode, so we can skip toward record number num almost immediatly. - * Anyway this is rather slow routine. The problem is that we don't know - * how many records are there in $INDEX_ALLOCATION:$I30 block. - */ -int -ntfs_ntreaddir( - struct ntfsmount * ntmp, - struct fnode * fp, - u_int32_t num, - struct attr_indexentry ** riepp) -{ - struct ntnode *ip = FTONT(fp); - struct ntvattr *vap = NULL; /* IndexRoot attribute */ - struct ntvattr *bmvap = NULL; /* BitMap attribute */ - struct ntvattr *iavap = NULL; /* IndexAllocation attribute */ - caddr_t rdbuf; /* Buffer to read directory's blocks */ - u_int8_t *bmp = NULL; /* Bitmap */ - u_int32_t blsize; /* Index allocation size (2048) */ - u_int32_t rdsize; /* Length of data to read */ - u_int32_t attrnum; /* Current attribute type */ - u_int32_t cpbl = 1; /* Clusters per directory block */ - u_int32_t blnum; - struct attr_indexentry *iep; - int error = ENOENT; - u_int32_t aoff, cnum; - - dprintf(("ntfs_ntreaddir: read ino: %ju, num: %d\n", - (uintmax_t)ip->i_number, num)); - error = ntfs_ntget(ip); - if (error) - return (error); - - error = ntfs_ntvattrget(ntmp, ip, NTFS_A_INDXROOT, "$I30", 0, &vap); - if (error) - return (ENOTDIR); - - if (fp->f_dirblbuf == NULL) { - fp->f_dirblsz = vap->va_a_iroot->ir_size; - fp->f_dirblbuf = malloc(max(vap->va_datalen,fp->f_dirblsz), - M_NTFSDIR, M_WAITOK); - } - - blsize = fp->f_dirblsz; - rdbuf = fp->f_dirblbuf; - - dprintf(("ntfs_ntreaddir: rdbuf: %p, blsize: %d\n", rdbuf, blsize)); - - if (vap->va_a_iroot->ir_flag & NTFS_IRFLAG_INDXALLOC) { - error = ntfs_ntvattrget(ntmp, ip, NTFS_A_INDXBITMAP, "$I30", - 0, &bmvap); - if (error) { - error = ENOTDIR; - goto fail; - } - bmp = malloc(bmvap->va_datalen, M_TEMP, M_WAITOK); - error = ntfs_readattr(ntmp, ip, NTFS_A_INDXBITMAP, "$I30", 0, - bmvap->va_datalen, bmp, NULL); - if (error) - goto fail; - - error = ntfs_ntvattrget(ntmp, ip, NTFS_A_INDX, "$I30", - 0, &iavap); - if (error) { - error = ENOTDIR; - goto fail; - } - cpbl = ntfs_btocn(blsize + ntfs_cntob(1) - 1); - dprintf(("ntfs_ntreaddir: indexalloc: %jd, cpbl: %d\n", - iavap->va_datalen, cpbl)); - } else { - dprintf(("ntfs_ntreadidir: w/o BitMap and IndexAllocation\n")); - iavap = bmvap = NULL; - bmp = NULL; - } - - /* Try use previous values */ - if ((fp->f_lastdnum < num) && (fp->f_lastdnum != 0)) { - attrnum = fp->f_lastdattr; - aoff = fp->f_lastdoff; - blnum = fp->f_lastdblnum; - cnum = fp->f_lastdnum; - } else { - attrnum = NTFS_A_INDXROOT; - aoff = sizeof(struct attr_indexroot); - blnum = 0; - cnum = 0; - } - - do { - dprintf(("ntfs_ntreaddir: scan: 0x%x, %d, %d, %d, %d\n", - attrnum, (u_int32_t) blnum, cnum, num, aoff)); - rdsize = (attrnum == NTFS_A_INDXROOT) ? vap->va_datalen : blsize; - error = ntfs_readattr(ntmp, ip, attrnum, "$I30", - ntfs_cntob(blnum * cpbl), rdsize, rdbuf, NULL); - if (error) - goto fail; - - if (attrnum == NTFS_A_INDX) { - error = ntfs_procfixups(ntmp, NTFS_INDXMAGIC, - rdbuf, rdsize); - if (error) - goto fail; - } - if (aoff == 0) - aoff = (attrnum == NTFS_A_INDX) ? - (0x18 + ((struct attr_indexalloc *) rdbuf)->ia_hdrsize) : - sizeof(struct attr_indexroot); - - iep = (struct attr_indexentry *) (rdbuf + aoff); - for (; !(iep->ie_flag & NTFS_IEFLAG_LAST) && (rdsize > aoff); - aoff += iep->reclen, - iep = (struct attr_indexentry *) (rdbuf + aoff)) - { - if (!ntfs_isnamepermitted(ntmp, iep)) continue; - - if (cnum >= num) { - fp->f_lastdnum = cnum; - fp->f_lastdoff = aoff; - fp->f_lastdblnum = blnum; - fp->f_lastdattr = attrnum; - - *riepp = iep; - - error = 0; - goto fail; - } - cnum++; - } - - if (iavap) { - if (attrnum == NTFS_A_INDXROOT) - blnum = 0; - else - blnum++; - - while (ntfs_cntob(blnum * cpbl) < iavap->va_datalen) { - if (bmp[blnum >> 3] & (1 << (blnum & 7))) - break; - blnum++; - } - - attrnum = NTFS_A_INDX; - aoff = 0; - if (ntfs_cntob(blnum * cpbl) >= iavap->va_datalen) - break; - dprintf(("ntfs_ntreaddir: blnum: %d\n", (u_int32_t) blnum)); - } - } while (iavap); - - *riepp = NULL; - fp->f_lastdnum = 0; - -fail: - if (vap) - ntfs_ntvattrrele(vap); - if (bmvap) - ntfs_ntvattrrele(bmvap); - if (iavap) - ntfs_ntvattrrele(iavap); - if (bmp) - free(bmp, M_TEMP); - ntfs_ntput(ip); - return (error); -} - -/* - * Convert NTFS times that are in 100 ns units and begins from - * 1601 Jan 1 into unix times. - */ -struct timespec -ntfs_nttimetounix( - u_int64_t nt) -{ - struct timespec t; - - /* WindowNT times are in 100 ns and from 1601 Jan 1 */ - t.tv_nsec = (nt % (1000 * 1000 * 10)) * 100; - t.tv_sec = nt / (1000 * 1000 * 10) - - 369LL * 365LL * 24LL * 60LL * 60LL - - 89LL * 1LL * 24LL * 60LL * 60LL; - return (t); -} - -/* - * Get file times from NTFS_A_NAME attribute. - */ -int -ntfs_times( - struct ntfsmount * ntmp, - struct ntnode * ip, - ntfs_times_t * tm) -{ - struct ntvattr *vap; - int error; - - dprintf(("ntfs_times: ino: %ju...\n", (uintmax_t)ip->i_number)); - - error = ntfs_ntget(ip); - if (error) - return (error); - - error = ntfs_ntvattrget(ntmp, ip, NTFS_A_NAME, NULL, 0, &vap); - if (error) { - ntfs_ntput(ip); - return (error); - } - *tm = vap->va_a_name->n_times; - ntfs_ntvattrrele(vap); - ntfs_ntput(ip); - - return (0); -} - -/* - * Get file sizes from corresponding attribute. - * - * ntnode under fnode should be locked. - */ -int -ntfs_filesize( - struct ntfsmount * ntmp, - struct fnode * fp, - u_int64_t * size, - u_int64_t * bytes) -{ - struct ntvattr *vap; - struct ntnode *ip = FTONT(fp); - u_int64_t sz, bn; - int error; - - dprintf(("ntfs_filesize: ino: %ju\n", (uintmax_t)ip->i_number)); - - error = ntfs_ntvattrget(ntmp, ip, - fp->f_attrtype, fp->f_attrname, 0, &vap); - if (error) - return (error); - - bn = vap->va_allocated; - sz = vap->va_datalen; - - dprintf(("ntfs_filesize: %d bytes (%d bytes allocated)\n", - (u_int32_t) sz, (u_int32_t) bn)); - - if (size) - *size = sz; - if (bytes) - *bytes = bn; - - ntfs_ntvattrrele(vap); - - return (0); -} - -/* - * This is one of read routines. - * - * ntnode should be locked. - */ -int -ntfs_readntvattr_plain( - struct ntfsmount * ntmp, - struct ntnode * ip, - struct ntvattr * vap, - off_t roff, - size_t rsize, - void *rdata, - size_t * initp, - struct uio *uio) -{ - int error = 0; - off_t off; - - *initp = 0; - if (vap->va_flag & NTFS_AF_INRUN) { - int cnt; - cn_t ccn, ccl, cn, left, cl; - caddr_t data = rdata; - struct buf *bp; - size_t tocopy; - - ddprintf(("ntfs_readntvattr_plain: data in run: %ld chains\n", - vap->va_vruncnt)); - - off = roff; - left = rsize; - ccl = 0; - ccn = 0; - cnt = 0; - while (left && (cnt < vap->va_vruncnt)) { - ccn = vap->va_vruncn[cnt]; - ccl = vap->va_vruncl[cnt]; - - ddprintf(("ntfs_readntvattr_plain: " \ - "left %d, cn: 0x%x, cl: %d, off: %d\n", \ - (u_int32_t) left, (u_int32_t) ccn, \ - (u_int32_t) ccl, (u_int32_t) off)); - - if (ntfs_cntob(ccl) < off) { - off -= ntfs_cntob(ccl); - cnt++; - continue; - } - if (ccn || ip->i_number == NTFS_BOOTINO) { - ccl -= ntfs_btocn(off); - cn = ccn + ntfs_btocn(off); - off = ntfs_btocnoff(off); - - while (left && ccl) { - /* - * Always read single clusters at a - * time - we need to avoid reading - * differently-sized blocks at the - * same disk offsets to avoid - * confusing the buffer cache. - */ - tocopy = MIN(left, - ntfs_cntob(1) - off); - cl = ntfs_btocl(tocopy + off); - KASSERT(cl == 1 && - tocopy <= ntfs_cntob(1), - ("single cluster limit mistake")); - - ddprintf(("ntfs_readntvattr_plain: " \ - "read: cn: 0x%x cl: %d, " \ - "off: %d len: %d, left: %d\n", - (u_int32_t) cn, - (u_int32_t) cl, - (u_int32_t) off, - (u_int32_t) tocopy, - (u_int32_t) left)); - error = bread(ntmp->ntm_devvp, - ntfs_cntobn(cn) - * ntmp->ntm_multiplier, - ntfs_cntob(cl), - NOCRED, &bp); - if (error) { - brelse(bp); - return (error); - } - if (uio) { - uiomove(bp->b_data + off, - tocopy, uio); - } else { - memcpy(data, bp->b_data + off, - tocopy); - } - brelse(bp); - data = data + tocopy; - *initp += tocopy; - off = 0; - left -= tocopy; - cn += cl; - ccl -= cl; - } - } else { - tocopy = MIN(left, ntfs_cntob(ccl) - off); - ddprintf(("ntfs_readntvattr_plain: " - "hole: ccn: 0x%x ccl: %d, off: %d, " \ - " len: %d, left: %d\n", - (u_int32_t) ccn, (u_int32_t) ccl, - (u_int32_t) off, (u_int32_t) tocopy, - (u_int32_t) left)); - left -= tocopy; - off = 0; - if (uio) { - size_t remains = tocopy; - for(; remains; remains--) - uiomove("", 1, uio); - } else - memset(data, 0, tocopy); - data = data + tocopy; - } - cnt++; - } - if (left) { - printf("ntfs_readntvattr_plain: POSSIBLE RUN ERROR\n"); - error = E2BIG; - } - } else { - ddprintf(("ntfs_readnvattr_plain: data is in mft record\n")); - if (uio) - uiomove(vap->va_datap + roff, rsize, uio); - else - memcpy(rdata, vap->va_datap + roff, rsize); - *initp += rsize; - } - - return (error); -} - -/* - * This is one of read routines. - */ -int -ntfs_readattr_plain( - struct ntfsmount * ntmp, - struct ntnode * ip, - u_int32_t attrnum, - char *attrname, - off_t roff, - size_t rsize, - void *rdata, - size_t * initp, - struct uio *uio) -{ - size_t init; - int error = 0; - off_t off = roff, left = rsize, toread; - caddr_t data = rdata; - struct ntvattr *vap; - *initp = 0; - - while (left) { - error = ntfs_ntvattrget(ntmp, ip, attrnum, attrname, - ntfs_btocn(off), &vap); - if (error) - return (error); - toread = MIN(left, ntfs_cntob(vap->va_vcnend + 1) - off); - ddprintf(("ntfs_readattr_plain: o: %d, s: %d (%d - %d)\n", - (u_int32_t) off, (u_int32_t) toread, - (u_int32_t) vap->va_vcnstart, - (u_int32_t) vap->va_vcnend)); - error = ntfs_readntvattr_plain(ntmp, ip, vap, - off - ntfs_cntob(vap->va_vcnstart), - toread, data, &init, uio); - if (error) { - printf("ntfs_readattr_plain: " \ - "ntfs_readntvattr_plain failed: o: %d, s: %d\n", - (u_int32_t) off, (u_int32_t) toread); - printf("ntfs_readattr_plain: attrib: %d - %d\n", - (u_int32_t) vap->va_vcnstart, - (u_int32_t) vap->va_vcnend); - ntfs_ntvattrrele(vap); - break; - } - ntfs_ntvattrrele(vap); - left -= toread; - off += toread; - data = data + toread; - *initp += init; - } - - return (error); -} - -/* - * This is one of read routines. - */ -int -ntfs_readattr( - struct ntfsmount * ntmp, - struct ntnode * ip, - u_int32_t attrnum, - char *attrname, - off_t roff, - size_t rsize, - void *rdata, - struct uio *uio) -{ - int error = 0; - struct ntvattr *vap; - size_t init; - - ddprintf(("ntfs_readattr: reading %ju: 0x%x, from %jd size %zu bytes\n", - (uintmax_t)ip->i_number, attrnum, (intmax_t)roff, rsize)); - - error = ntfs_ntvattrget(ntmp, ip, attrnum, attrname, 0, &vap); - if (error) - return (error); - - if ((roff > vap->va_datalen) || - (roff + rsize > vap->va_datalen)) { - ddprintf(("ntfs_readattr: offset too big\n")); - ntfs_ntvattrrele(vap); - return (E2BIG); - } - if (vap->va_compression && vap->va_compressalg) { - u_int8_t *cup; - u_int8_t *uup; - off_t off = roff, left = rsize, tocopy; - caddr_t data = rdata; - cn_t cn; - - ddprintf(("ntfs_ntreadattr: compression: %d\n", - vap->va_compressalg)); - - cup = malloc(ntfs_cntob(NTFS_COMPUNIT_CL), - M_NTFSDECOMP, M_WAITOK); - uup = malloc(ntfs_cntob(NTFS_COMPUNIT_CL), - M_NTFSDECOMP, M_WAITOK); - - cn = (ntfs_btocn(roff)) & (~(NTFS_COMPUNIT_CL - 1)); - off = roff - ntfs_cntob(cn); - - while (left) { - error = ntfs_readattr_plain(ntmp, ip, attrnum, - attrname, ntfs_cntob(cn), - ntfs_cntob(NTFS_COMPUNIT_CL), - cup, &init, NULL); - if (error) - break; - - tocopy = MIN(left, ntfs_cntob(NTFS_COMPUNIT_CL) - off); - - if (init == ntfs_cntob(NTFS_COMPUNIT_CL)) { - if (uio) - uiomove(cup + off, tocopy, uio); - else - memcpy(data, cup + off, tocopy); - } else if (init == 0) { - if (uio) { - size_t remains = tocopy; - for(; remains; remains--) - uiomove("", 1, uio); - } - else - memset(data, 0, tocopy); - } else { - error = ntfs_uncompunit(ntmp, uup, cup); - if (error) - break; - if (uio) - uiomove(uup + off, tocopy, uio); - else - memcpy(data, uup + off, tocopy); - } - - left -= tocopy; - data = data + tocopy; - off += tocopy - ntfs_cntob(NTFS_COMPUNIT_CL); - cn += NTFS_COMPUNIT_CL; - } - - free(uup, M_NTFSDECOMP); - free(cup, M_NTFSDECOMP); - } else - error = ntfs_readattr_plain(ntmp, ip, attrnum, attrname, - roff, rsize, rdata, &init, uio); - ntfs_ntvattrrele(vap); - return (error); -} - -#if 0 -int -ntfs_parserun( - cn_t * cn, - cn_t * cl, - u_int8_t * run, - u_long len, - u_long *off) -{ - u_int8_t sz; - int i; - - if (NULL == run) { - printf("ntfs_parsetun: run == NULL\n"); - return (EINVAL); - } - sz = run[(*off)++]; - if (0 == sz) { - printf("ntfs_parserun: trying to go out of run\n"); - return (E2BIG); - } - *cl = 0; - if ((sz & 0xF) > 8 || (*off) + (sz & 0xF) > len) { - printf("ntfs_parserun: " \ - "bad run: length too big: sz: 0x%02x (%ld < %ld + sz)\n", - sz, len, *off); - return (EINVAL); - } - for (i = 0; i < (sz & 0xF); i++) - *cl += (u_int32_t) run[(*off)++] << (i << 3); - - sz >>= 4; - if ((sz & 0xF) > 8 || (*off) + (sz & 0xF) > len) { - printf("ntfs_parserun: " \ - "bad run: length too big: sz: 0x%02x (%ld < %ld + sz)\n", - sz, len, *off); - return (EINVAL); - } - for (i = 0; i < (sz & 0xF); i++) - *cn += (u_int32_t) run[(*off)++] << (i << 3); - - return (0); -} -#endif - -/* - * Process fixup routine on given buffer. - */ -int -ntfs_procfixups( - struct ntfsmount * ntmp, - u_int32_t magic, - caddr_t buf, - size_t len) -{ - struct fixuphdr *fhp = (struct fixuphdr *) buf; - int i; - u_int16_t fixup; - u_int16_t *fxp; - u_int16_t *cfxp; - - if (fhp->fh_magic != magic) { - printf("ntfs_procfixups: magic doesn't match: %08x != %08x\n", - fhp->fh_magic, magic); - return (EINVAL); - } - if ((fhp->fh_fnum - 1) * NTFS_BLOCK_SIZE != len) { - printf("ntfs_procfixups: " \ - "bad fixups number: %d for %ld bytes block\n", - fhp->fh_fnum, (long)len); /* XXX printf kludge */ - return (EINVAL); - } - if (fhp->fh_foff >= ntmp->ntm_spc * ntmp->ntm_mftrecsz * ntmp->ntm_bps) { - printf("ntfs_procfixups: invalid offset: %x", fhp->fh_foff); - return (EINVAL); - } - fxp = (u_int16_t *) (buf + fhp->fh_foff); - cfxp = (u_int16_t *) (buf + NTFS_BLOCK_SIZE - 2); - fixup = *fxp++; - for (i = 1; i < fhp->fh_fnum; i++, fxp++) { - if (*cfxp != fixup) { - printf("ntfs_procfixups: fixup %d doesn't match\n", i); - return (EINVAL); - } - *cfxp = *fxp; - cfxp = (u_int16_t *) ((caddr_t) cfxp + NTFS_BLOCK_SIZE); - } - return (0); -} - -#if 0 -int -ntfs_runtocn( - cn_t * cn, - struct ntfsmount * ntmp, - u_int8_t * run, - u_long len, - cn_t vcn) -{ - cn_t ccn = 0; - cn_t ccl = 0; - u_long off = 0; - int error = 0; - -#if NTFS_DEBUG - int i; - printf("ntfs_runtocn: run: %p, %ld bytes, vcn:%ld\n", - run, len, (u_long) vcn); - printf("ntfs_runtocn: run: "); - for (i = 0; i < len; i++) - printf("0x%02x ", run[i]); - printf("\n"); -#endif - - if (NULL == run) { - printf("ntfs_runtocn: run == NULL\n"); - return (EINVAL); - } - do { - if (run[off] == 0) { - printf("ntfs_runtocn: vcn too big\n"); - return (E2BIG); - } - vcn -= ccl; - error = ntfs_parserun(&ccn, &ccl, run, len, &off); - if (error) { - printf("ntfs_runtocn: ntfs_parserun failed\n"); - return (error); - } - } while (ccl <= vcn); - *cn = ccn + vcn; - return (0); -} -#endif - -/* - * this initializes toupper table & dependant variables to be ready for - * later work - */ -void -ntfs_toupper_init() -{ - ntfs_toupper_tab = (wchar *) NULL; - lockinit(&ntfs_toupper_lock, PVFS, "ntfs_toupper", 0, 0); - ntfs_toupper_usecount = 0; -} - -void -ntfs_toupper_destroy(void) -{ - - lockdestroy(&ntfs_toupper_lock); -} - -/* - * if the ntfs_toupper_tab[] is filled already, just raise use count; - * otherwise read the data from the filesystem we are currently mounting - */ -int -ntfs_toupper_use(mp, ntmp) - struct mount *mp; - struct ntfsmount *ntmp; -{ - int error = 0; - struct vnode *vp; - - /* get exclusive access */ - lockmgr(&ntfs_toupper_lock, LK_EXCLUSIVE, NULL); - - /* only read the translation data from a file if it hasn't been - * read already */ - if (ntfs_toupper_tab) - goto out; - - /* - * Read in Unicode lowercase -> uppercase translation file. - * XXX for now, just the first 256 entries are used anyway, - * so don't bother reading more - */ - ntfs_toupper_tab = malloc(65536 * sizeof(wchar), - M_NTFSRDATA, M_WAITOK); - - if ((error = VFS_VGET(mp, NTFS_UPCASEINO, LK_EXCLUSIVE, &vp))) - goto out; - error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL, - 0, 65536*sizeof(wchar), (char *) ntfs_toupper_tab, NULL); - vput(vp); - - out: - ntfs_toupper_usecount++; - lockmgr(&ntfs_toupper_lock, LK_RELEASE, NULL); - return (error); -} - -/* - * lower the use count and if it reaches zero, free the memory - * tied by toupper table - */ -void -ntfs_toupper_unuse() -{ - /* get exclusive access */ - lockmgr(&ntfs_toupper_lock, LK_EXCLUSIVE, NULL); - - ntfs_toupper_usecount--; - if (ntfs_toupper_usecount == 0) { - free(ntfs_toupper_tab, M_NTFSRDATA); - ntfs_toupper_tab = NULL; - } -#ifdef DIAGNOSTIC - else if (ntfs_toupper_usecount < 0) { - panic("ntfs_toupper_unuse(): use count negative: %d\n", - ntfs_toupper_usecount); - } -#endif - - /* release the lock */ - lockmgr(&ntfs_toupper_lock, LK_RELEASE, NULL); -} - -int -ntfs_u28_init( - struct ntfsmount *ntmp, - wchar *u2w, - char *cs_local, - char *cs_ntfs) -{ - char ** u28; - int i, j, h, l; - - if (ntfs_iconv && cs_local) { - ntfs_iconv->open(cs_local, cs_ntfs, &ntmp->ntm_ic_u2l); - return (0); - } - - u28 = malloc(256 * sizeof(char*), M_TEMP, M_WAITOK | M_ZERO); - - for (i=0; i<256; i++) { - h = (u2w[i] >> 8) & 0xFF; - l = (u2w[i]) &0xFF; - - if (u28[h] == NULL) { - u28[h] = malloc(256 * sizeof(char), M_TEMP, M_WAITOK); - for (j=0; j<256; j++) - u28[h][j] = '_'; - } - - u28[h][l] = i & 0xFF; - } - - ntmp->ntm_u28 = u28; - - return (0); -} - -int -ntfs_u28_uninit(struct ntfsmount *ntmp) -{ - char ** u28; - int i; - - if (ntmp->ntm_u28 == NULL) { - if (ntfs_iconv && ntmp->ntm_ic_u2l) { - ntfs_iconv->close(ntmp->ntm_ic_u2l); - } - return (0); - } - - u28 = ntmp->ntm_u28; - - for (i=0; i<256; i++) - if (u28[i] != NULL) - free(u28[i], M_TEMP); - - free(u28, M_TEMP); - - return (0); -} - -int -ntfs_82u_init( - struct ntfsmount *ntmp, - char *cs_local, - char *cs_ntfs) -{ - wchar * _82u; - int i; - - if (ntfs_iconv && cs_local) { - ntfs_iconv->open(cs_ntfs, cs_local, &ntmp->ntm_ic_l2u); - return (0); - } - - _82u = malloc(256 * sizeof(wchar), M_TEMP, M_WAITOK); - - for (i=0; i<256; i++) - _82u[i] = i; - - ntmp->ntm_82u = _82u; - - return (0); -} - -int -ntfs_82u_uninit(struct ntfsmount *ntmp) -{ - - if (ntmp->ntm_82u == NULL) { - if (ntfs_iconv && ntmp->ntm_ic_l2u) { - ntfs_iconv->close(ntmp->ntm_ic_l2u); - } - return (0); - } - - free(ntmp->ntm_82u, M_TEMP); - return (0); -} - -/* - * maps the Unicode char to local character - */ -char * -ntfs_u28( - char *outbuf, - struct ntfsmount *ntmp, - wchar wc) -{ - char *p, *outp, inbuf[3]; - size_t ilen, olen; - - outp = outbuf; - if (ntfs_iconv && ntmp->ntm_ic_u2l) { - ilen = 2; - olen = 4; - - inbuf[0] = (char)(wc>>8); - inbuf[1] = (char)wc; - inbuf[2] = '\0'; - p = inbuf; - ntfs_iconv->convchr(ntmp->ntm_ic_u2l, (const char **)&p, &ilen, - &outp, &olen); - if (olen == 4) - *outp++ = '?'; - *outp = '\0'; - outp = outbuf; - return (outp); - } - - p = ntmp->ntm_u28[(wc>>8)&0xFF]; - outbuf[0] = (p == NULL) ? '_' : p[wc&0xFF] & 0xFF; - outbuf[1] = '\0'; - return (outp); -} - -wchar -ntfs_82u( - struct ntfsmount *ntmp, - const char *c, - int *len) -{ - char *outp, outbuf[3]; - wchar uc; - size_t ilen, olen; - - if (ntfs_iconv && ntmp->ntm_ic_l2u) { - ilen = (size_t)*len; - olen = 2; - - outp = outbuf; - ntfs_iconv->convchr(ntmp->ntm_ic_l2u, &c, &ilen, &outp, &olen); - *len -= (int)ilen; - uc = (wchar)((outbuf[0]<<8) | (outbuf[1]&0xFF)); - - return (uc); - } - - if (ntmp->ntm_82u != NULL) - return (ntmp->ntm_82u[*c&0xFF]); - - return ('?'); -} - diff --git a/sys/fs/ntfs/ntfs_subr.h b/sys/fs/ntfs/ntfs_subr.h deleted file mode 100644 index 9ccbb420643..00000000000 --- a/sys/fs/ntfs/ntfs_subr.h +++ /dev/null @@ -1,120 +0,0 @@ -/* $NetBSD: ntfs_subr.h,v 1.8 1999/10/10 14:48:37 jdolecek Exp $ */ - -/*- - * Copyright (c) 1998, 1999 Semen Ustimenko - * 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$ - */ - -#define VA_LOADED 0x0001 -#define VA_PRELOADED 0x0002 - -struct ntvattr { - LIST_ENTRY(ntvattr) va_list; - - u_int32_t va_vflag; - struct vnode *va_vp; - struct ntnode *va_ip; - - u_int32_t va_flag; - u_int32_t va_type; - u_int8_t va_namelen; - char va_name[NTFS_MAXATTRNAME]; - - u_int32_t va_compression; - u_int32_t va_compressalg; - u_int64_t va_datalen; - u_int64_t va_allocated; - cn_t va_vcnstart; - cn_t va_vcnend; - u_int16_t va_index; - union { - struct { - cn_t * cn; - cn_t * cl; - u_long cnt; - } vrun; - caddr_t datap; - struct attr_name *name; - struct attr_indexroot *iroot; - struct attr_indexalloc *ialloc; - } va_d; -}; -#define va_vruncn va_d.vrun.cn -#define va_vruncl va_d.vrun.cl -#define va_vruncnt va_d.vrun.cnt -#define va_datap va_d.datap -#define va_a_name va_d.name -#define va_a_iroot va_d.iroot -#define va_a_ialloc va_d.ialloc - -struct componentname; -struct fnode; -struct uio; - -int ntfs_procfixups( struct ntfsmount *, u_int32_t, caddr_t, size_t ); -int ntfs_parserun( cn_t *, cn_t *, u_int8_t *, u_long, u_long *); -int ntfs_runtocn( cn_t *, struct ntfsmount *, u_int8_t *, u_long, cn_t); -int ntfs_readntvattr_plain( struct ntfsmount *, struct ntnode *, struct ntvattr *, off_t, size_t, void *,size_t *, struct uio *); -int ntfs_readattr_plain( struct ntfsmount *, struct ntnode *, u_int32_t, char *, off_t, size_t, void *,size_t *, struct uio *); -int ntfs_readattr( struct ntfsmount *, struct ntnode *, u_int32_t, char *, off_t, size_t, void *, struct uio *); -int ntfs_filesize( struct ntfsmount *, struct fnode *, u_int64_t *, u_int64_t *); -int ntfs_times( struct ntfsmount *, struct ntnode *, ntfs_times_t *); -struct timespec ntfs_nttimetounix( u_int64_t ); -int ntfs_ntreaddir( struct ntfsmount *, struct fnode *, u_int32_t, struct attr_indexentry **); -int ntfs_runtovrun( cn_t **, cn_t **, u_long *, u_int8_t *); -int ntfs_attrtontvattr( struct ntfsmount *, struct ntvattr **, struct attr * ); -void ntfs_freentvattr( struct ntvattr * ); -int ntfs_loadntvattrs( struct ntfsmount *, struct vnode *, caddr_t, struct ntvattr **); -struct ntvattr * ntfs_findntvattr( struct ntfsmount *, struct ntnode *, u_int32_t, cn_t ); -int ntfs_ntlookupfile(struct ntfsmount *, struct vnode *, struct componentname *, struct vnode **); -int ntfs_isnamepermitted(struct ntfsmount *, struct attr_indexentry * ); -int ntfs_ntvattrrele(struct ntvattr * ); -int ntfs_ntvattrget(struct ntfsmount *, struct ntnode *, u_int32_t, const char *, cn_t , struct ntvattr **); -int ntfs_ntlookup(struct ntfsmount *, ino_t, struct ntnode **); -int ntfs_ntget(struct ntnode *); -void ntfs_ntref(struct ntnode *); -void ntfs_ntrele(struct ntnode *); -void ntfs_ntput(struct ntnode *); -int ntfs_loadntnode( struct ntfsmount *, struct ntnode * ); -void ntfs_toupper_init(void); -void ntfs_toupper_destroy(void); -int ntfs_toupper_use(struct mount *, struct ntfsmount *); -void ntfs_toupper_unuse(void); -int ntfs_fget(struct ntfsmount *, struct ntnode *, int, char *, struct fnode **); -void ntfs_frele(struct fnode *); - -int ntfs_u28_init(struct ntfsmount *ntmp, wchar *u2w, char *cs_local, char *cs_ntfs); -int ntfs_u28_uninit(struct ntfsmount *ntmp); -int ntfs_82u_init(struct ntfsmount *ntmp, char *cs_local, char *cs_ntfs); -int ntfs_82u_uninit(struct ntfsmount *ntmp); -char * ntfs_u28(char *outbuf, struct ntfsmount *ntmp, wchar wc); -wchar ntfs_82u(struct ntfsmount *ntmp, const char *c, int *len); -#define NTFS_U28(ch) ntfs_u28(tmpbuf, ntmp, (ch)) -#define NTFS_82U(ch, len) ntfs_82u(ntmp, (ch), len) -#define NTFS_UASTRCMP(ustr, ustrlen, astr, astrlen) \ - ntfs_uastrcmp(ntmp, (ustr), (ustrlen), (astr), (astrlen)) -#define NTFS_UASTRICMP(ustr, ustrlen, astr, astrlen) \ - ntfs_uastricmp(ntmp, (ustr), (ustrlen), (astr), (astrlen)) diff --git a/sys/fs/ntfs/ntfs_vfsops.c b/sys/fs/ntfs/ntfs_vfsops.c deleted file mode 100644 index c0408dd155f..00000000000 --- a/sys/fs/ntfs/ntfs_vfsops.c +++ /dev/null @@ -1,780 +0,0 @@ -/* $NetBSD: ntfs_vfsops.c,v 1.23 1999/11/15 19:38:14 jdolecek Exp $ */ - -/*- - * Copyright (c) 1998, 1999 Semen Ustimenko - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -/*#define NTFS_DEBUG 1*/ -#include -#include -#include -#include -#include -#include - -static MALLOC_DEFINE(M_NTFSMNT, "ntfs_mount", "NTFS mount structure"); -MALLOC_DEFINE(M_NTFSNTNODE,"ntfs_ntnode", "NTFS ntnode information"); -MALLOC_DEFINE(M_NTFSFNODE,"ntfs_fnode", "NTFS fnode information"); -MALLOC_DEFINE(M_NTFSDIR,"ntfs_dir", "NTFS dir buffer"); - -static int ntfs_mountfs(register struct vnode *, struct mount *, - struct thread *); -static int ntfs_calccfree(struct ntfsmount *ntmp, cn_t *cfreep); - -static vfs_init_t ntfs_init; -static vfs_uninit_t ntfs_uninit; -static vfs_vget_t ntfs_vget; -static vfs_fhtovp_t ntfs_fhtovp; -static vfs_cmount_t ntfs_cmount; -static vfs_mount_t ntfs_mount; -static vfs_root_t ntfs_root; -static vfs_statfs_t ntfs_statfs; -static vfs_unmount_t ntfs_unmount; - -static b_strategy_t ntfs_bufstrategy; - -/* - * Buffer operations for NTFS vnodes. - * We punt on VOP_BMAP, so we need to do - * strategy on the file's vnode rather - * than the underlying device's - */ -static struct buf_ops ntfs_vnbufops = { - .bop_name = "NTFS", - .bop_strategy = ntfs_bufstrategy, -}; - -static int -ntfs_init ( - struct vfsconf *vcp ) -{ - ntfs_nthashinit(); - ntfs_toupper_init(); - return 0; -} - -static int -ntfs_uninit ( - struct vfsconf *vcp ) -{ - ntfs_toupper_destroy(); - ntfs_nthashdestroy(); - return 0; -} - -static int -ntfs_cmount ( - struct mntarg *ma, - void *data, - uint64_t flags) -{ - struct ntfs_args args; - struct export_args exp; - int error; - - error = copyin(data, &args, sizeof(args)); - if (error) - return (error); - vfs_oexport_conv(&args.export, &exp); - ma = mount_argsu(ma, "from", args.fspec, MAXPATHLEN); - ma = mount_arg(ma, "export", &exp, sizeof(exp)); - ma = mount_argf(ma, "uid", "%d", args.uid); - ma = mount_argf(ma, "gid", "%d", args.gid); - ma = mount_argf(ma, "mode", "%d", args.mode); - ma = mount_argb(ma, args.flag & NTFS_MFLAG_CASEINS, "nocaseins"); - ma = mount_argb(ma, args.flag & NTFS_MFLAG_ALLNAMES, "noallnames"); - if (args.flag & NTFS_MFLAG_KICONV) { - ma = mount_argsu(ma, "cs_ntfs", args.cs_ntfs, 64); - ma = mount_argsu(ma, "cs_local", args.cs_local, 64); - } - - error = kernel_mount(ma, flags); - - return (error); -} - -static const char *ntfs_opts[] = { - "from", "export", "uid", "gid", "mode", "caseins", "allnames", - "kiconv", "cs_ntfs", "cs_local", NULL -}; - -static int -ntfs_mount(struct mount *mp) -{ - int err = 0, error; - struct vnode *devvp; - struct nameidata ndp; - struct thread *td; - char *from; - - td = curthread; - if (vfs_filteropt(mp->mnt_optnew, ntfs_opts)) - return (EINVAL); - - /* Force mount as read-only. */ - MNT_ILOCK(mp); - mp->mnt_flag |= MNT_RDONLY; - MNT_IUNLOCK(mp); - - from = vfs_getopts(mp->mnt_optnew, "from", &error); - if (error) - return (error); - - /* - * If updating, check whether changing from read-only to - * read/write. - */ - if (mp->mnt_flag & MNT_UPDATE) { - if (vfs_flagopt(mp->mnt_optnew, "export", NULL, 0)) { - /* Process export requests in vfs_mount.c */ - return (0); - } else { - printf("ntfs_mount(): MNT_UPDATE not supported\n"); - return (EINVAL); - } - } - - /* - * Not an update, or updating the name: look up the name - * and verify that it refers to a sensible block device. - */ - NDINIT(&ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, from, td); - err = namei(&ndp); - if (err) - return (err); - NDFREE(&ndp, NDF_ONLY_PNBUF); - devvp = ndp.ni_vp; - - if (!vn_isdisk(devvp, &err)) { - vput(devvp); - return (err); - } - - /* - * If mount by non-root, then verify that user has necessary - * permissions on the device. - */ - err = VOP_ACCESS(devvp, VREAD, td->td_ucred, td); - if (err) - err = priv_check(td, PRIV_VFS_MOUNT_PERM); - if (err) { - vput(devvp); - return (err); - } - - - /* - * Since this is a new mount, we want the names for the device and - * the mount point copied in. If an error occurs, the mountpoint is - * discarded by the upper level code. Note that vfs_mount() handles - * copying the mountpoint f_mntonname for us, so we don't have to do - * it here unless we want to set it to something other than "path" - * for some rason. - */ - - err = ntfs_mountfs(devvp, mp, td); - if (err == 0) { - - /* Save "mounted from" info for mount point. */ - vfs_mountedfrom(mp, from); - } else - vrele(devvp); - return (err); -} - -/* - * Common code for mount and mountroot - */ -int -ntfs_mountfs(devvp, mp, td) - register struct vnode *devvp; - struct mount *mp; - struct thread *td; -{ - struct buf *bp; - struct ntfsmount *ntmp; - struct cdev *dev = devvp->v_rdev; - int error, i, v; - struct vnode *vp; - struct g_consumer *cp; - struct g_provider *pp; - char *cs_ntfs, *cs_local; - - DROP_GIANT(); - g_topology_lock(); - - /* - * XXX: Do not allow more than one consumer to open a device - * associated with a particular GEOM provider. - * This disables multiple read-only mounts of a device, - * but it gets rid of panics in vget() when you try to - * mount the same device more than once. - */ - pp = g_dev_getprovider(devvp->v_rdev); - if ((pp != NULL) && ((pp->acr | pp->acw | pp->ace ) != 0)) - error = EPERM; - else - error = g_vfs_open(devvp, &cp, "ntfs", 0); - - g_topology_unlock(); - PICKUP_GIANT(); - VOP_UNLOCK(devvp, 0); - if (error) - return (error); - - bp = NULL; - - error = bread(devvp, BBLOCK, BBSIZE, NOCRED, &bp); - if (error) - goto out; - ntmp = malloc( sizeof *ntmp, M_NTFSMNT, M_WAITOK | M_ZERO); - bcopy( bp->b_data, &ntmp->ntm_bootfile, sizeof(struct bootfile) ); - /* - * We must not cache the boot block if its size is not exactly - * one cluster in order to avoid confusing the buffer cache when - * the boot file is read later by ntfs_readntvattr_plain(), which - * reads a cluster at a time. - */ - if (ntfs_cntob(1) != BBSIZE) - bp->b_flags |= B_NOCACHE; - brelse( bp ); - bp = NULL; - - if (strncmp((const char *)ntmp->ntm_bootfile.bf_sysid, NTFS_BBID, NTFS_BBIDLEN)) { - error = EINVAL; - dprintf(("ntfs_mountfs: invalid boot block\n")); - goto out; - } - - { - int8_t cpr = ntmp->ntm_mftrecsz; - if( cpr > 0 ) - ntmp->ntm_bpmftrec = ntmp->ntm_spc * cpr; - else - ntmp->ntm_bpmftrec = (1 << (-cpr)) / ntmp->ntm_bps; - } - ntmp->ntm_multiplier = ntmp->ntm_bps / DEV_BSIZE; - - dprintf(("ntfs_mountfs(): bps: %d, spc: %d, media: %x, mftrecsz: %d (%d sects)\n", - ntmp->ntm_bps,ntmp->ntm_spc,ntmp->ntm_bootfile.bf_media, - ntmp->ntm_mftrecsz,ntmp->ntm_bpmftrec)); - dprintf(("ntfs_mountfs(): mftcn: 0x%x|0x%x\n", - (u_int32_t)ntmp->ntm_mftcn,(u_int32_t)ntmp->ntm_mftmirrcn)); - - ntmp->ntm_mountp = mp; - ntmp->ntm_devvp = devvp; - if (vfs_scanopt(mp->mnt_optnew, "uid", "%d", &v) == 1) - ntmp->ntm_uid = v; - if (vfs_scanopt(mp->mnt_optnew, "gid", "%d", &v) == 1) - ntmp->ntm_gid = v; - if (vfs_scanopt(mp->mnt_optnew, "mode", "%d", &v) == 1) - ntmp->ntm_mode = v & ACCESSPERMS; - vfs_flagopt(mp->mnt_optnew, - "caseins", &ntmp->ntm_flag, NTFS_MFLAG_CASEINS); - vfs_flagopt(mp->mnt_optnew, - "allnames", &ntmp->ntm_flag, NTFS_MFLAG_ALLNAMES); - ntmp->ntm_cp = cp; - ntmp->ntm_bo = &devvp->v_bufobj; - - cs_local = vfs_getopts(mp->mnt_optnew, "cs_local", &error); - if (error && error != ENOENT) - goto out; - cs_ntfs = vfs_getopts(mp->mnt_optnew, "cs_ntfs", &error); - if (error && error != ENOENT) - goto out; - /* Copy in the 8-bit to Unicode conversion table */ - /* Initialize Unicode to 8-bit table from 8toU table */ - ntfs_82u_init(ntmp, cs_local, cs_ntfs); - if (cs_local != NULL && cs_ntfs != NULL) - ntfs_u28_init(ntmp, NULL, cs_local, cs_ntfs); - else - ntfs_u28_init(ntmp, ntmp->ntm_82u, cs_local, cs_ntfs); - - mp->mnt_data = ntmp; - - dprintf(("ntfs_mountfs(): case-%s,%s uid: %d, gid: %d, mode: %o\n", - (ntmp->ntm_flag & NTFS_MFLAG_CASEINS)?"insens.":"sens.", - (ntmp->ntm_flag & NTFS_MFLAG_ALLNAMES)?" allnames,":"", - ntmp->ntm_uid, ntmp->ntm_gid, ntmp->ntm_mode)); - - /* - * We read in some system nodes to do not allow - * reclaim them and to have everytime access to them. - */ - { - int pi[3] = { NTFS_MFTINO, NTFS_ROOTINO, NTFS_BITMAPINO }; - for (i=0; i<3; i++) { - error = VFS_VGET(mp, pi[i], LK_EXCLUSIVE, - &(ntmp->ntm_sysvn[pi[i]])); - if(error) - goto out1; - ntmp->ntm_sysvn[pi[i]]->v_vflag |= VV_SYSTEM; - VREF(ntmp->ntm_sysvn[pi[i]]); - vput(ntmp->ntm_sysvn[pi[i]]); - } - } - - /* read the Unicode lowercase --> uppercase translation table, - * if necessary */ - if ((error = ntfs_toupper_use(mp, ntmp))) - goto out1; - - /* - * Scan $BitMap and count free clusters - */ - error = ntfs_calccfree(ntmp, &ntmp->ntm_cfree); - if(error) - goto out1; - - /* - * Read and translate to internal format attribute - * definition file. - */ - { - int num,j; - struct attrdef ad; - - /* Open $AttrDef */ - error = VFS_VGET(mp, NTFS_ATTRDEFINO, LK_EXCLUSIVE, &vp ); - if(error) - goto out1; - - /* Count valid entries */ - for(num=0;;num++) { - error = ntfs_readattr(ntmp, VTONT(vp), - NTFS_A_DATA, NULL, - num * sizeof(ad), sizeof(ad), - &ad, NULL); - if (error) - goto out1; - if (ad.ad_name[0] == 0) - break; - } - - /* Alloc memory for attribute definitions */ - ntmp->ntm_ad = malloc(num * sizeof(struct ntvattrdef), - M_NTFSMNT, M_WAITOK); - - ntmp->ntm_adnum = num; - - /* Read them and translate */ - for(i=0;intm_ad[i].ad_name[j] = ad.ad_name[j]; - } while(ad.ad_name[j++]); - ntmp->ntm_ad[i].ad_namelen = j - 1; - ntmp->ntm_ad[i].ad_type = ad.ad_type; - } - - vput(vp); - } - - mp->mnt_stat.f_fsid.val[0] = dev2udev(dev); - mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum; - mp->mnt_maxsymlinklen = 0; - MNT_ILOCK(mp); - mp->mnt_flag |= MNT_LOCAL; - MNT_IUNLOCK(mp); - return (0); - -out1: - for(i=0;intm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]); - - if (vflush(mp, 0, 0, td)) - dprintf(("ntfs_mountfs: vflush failed\n")); - -out: - if (bp) - brelse(bp); - - DROP_GIANT(); - g_topology_lock(); - g_vfs_close(cp); - g_topology_unlock(); - PICKUP_GIANT(); - - return (error); -} - -static int -ntfs_unmount( - struct mount *mp, - int mntflags) -{ - struct thread *td; - struct ntfsmount *ntmp; - int error, flags, i; - - dprintf(("ntfs_unmount: unmounting...\n")); - td = curthread; - ntmp = VFSTONTFS(mp); - - flags = 0; - if(mntflags & MNT_FORCE) - flags |= FORCECLOSE; - - dprintf(("ntfs_unmount: vflushing...\n")); - error = vflush(mp, 0, flags | SKIPSYSTEM, td); - if (error) { - printf("ntfs_unmount: vflush failed: %d\n",error); - return (error); - } - - /* Check if only system vnodes are rest */ - for(i=0;intm_sysvn[i]) && - (vrefcnt(ntmp->ntm_sysvn[i]) > 1)) return (EBUSY); - - /* Dereference all system vnodes */ - for(i=0;intm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]); - - /* vflush system vnodes */ - error = vflush(mp, 0, flags, td); - if (error) - printf("ntfs_unmount: vflush failed(sysnodes): %d\n",error); - - vinvalbuf(ntmp->ntm_devvp, V_SAVE, 0, 0); - - DROP_GIANT(); - g_topology_lock(); - g_vfs_close(ntmp->ntm_cp); - g_topology_unlock(); - PICKUP_GIANT(); - - vrele(ntmp->ntm_devvp); - - /* free the toupper table, if this has been last mounted ntfs volume */ - ntfs_toupper_unuse(); - - dprintf(("ntfs_umount: freeing memory...\n")); - ntfs_u28_uninit(ntmp); - ntfs_82u_uninit(ntmp); - mp->mnt_data = NULL; - MNT_ILOCK(mp); - mp->mnt_flag &= ~MNT_LOCAL; - MNT_IUNLOCK(mp); - free(ntmp->ntm_ad, M_NTFSMNT); - free(ntmp, M_NTFSMNT); - return (error); -} - -static int -ntfs_root( - struct mount *mp, - int flags, - struct vnode **vpp) -{ - struct vnode *nvp; - int error = 0; - - dprintf(("ntfs_root(): sysvn: %p\n", - VFSTONTFS(mp)->ntm_sysvn[NTFS_ROOTINO])); - error = VFS_VGET(mp, (ino_t)NTFS_ROOTINO, LK_EXCLUSIVE, &nvp); - if(error) { - printf("ntfs_root: VFS_VGET failed: %d\n",error); - return (error); - } - - *vpp = nvp; - return (0); -} - -static int -ntfs_calccfree( - struct ntfsmount *ntmp, - cn_t *cfreep) -{ - struct vnode *vp; - u_int8_t *tmp; - int j, error; - long cfree = 0; - size_t bmsize, i; - - vp = ntmp->ntm_sysvn[NTFS_BITMAPINO]; - - bmsize = VTOF(vp)->f_size; - - tmp = malloc(bmsize, M_TEMP, M_WAITOK); - - error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL, - 0, bmsize, tmp, NULL); - if (error) - goto out; - - for(i=0;intm_sysvn[NTFS_MFTINO])->f_size; - mftallocated = VTOF(ntmp->ntm_sysvn[NTFS_MFTINO])->f_allocated; - - sbp->f_type = mp->mnt_vfc->vfc_typenum; - sbp->f_bsize = ntmp->ntm_bps; - sbp->f_iosize = ntmp->ntm_bps * ntmp->ntm_spc; - sbp->f_blocks = ntmp->ntm_bootfile.bf_spv; - sbp->f_bfree = sbp->f_bavail = ntfs_cntobn(ntmp->ntm_cfree); - sbp->f_ffree = sbp->f_bfree / ntmp->ntm_bpmftrec; - sbp->f_files = mftallocated / ntfs_bntob(ntmp->ntm_bpmftrec) + - sbp->f_ffree; - sbp->f_flags = mp->mnt_flag; - - return (0); -} - -/*ARGSUSED*/ -static int -ntfs_fhtovp( - struct mount *mp, - struct fid *fhp, - int flags, - struct vnode **vpp) -{ - struct vnode *nvp; - struct ntfid *ntfhp = (struct ntfid *)fhp; - int error; - - ddprintf(("ntfs_fhtovp(): %d\n", ntfhp->ntfid_ino)); - - if ((error = VFS_VGET(mp, ntfhp->ntfid_ino, LK_EXCLUSIVE, &nvp)) != 0) { - *vpp = NULLVP; - return (error); - } - /* XXX as unlink/rmdir/mkdir/creat are not currently possible - * with NTFS, we don't need to check anything else for now */ - *vpp = nvp; - vnode_create_vobject(nvp, VTOF(nvp)->f_size, curthread); - return (0); -} - -int -ntfs_vgetex( - struct mount *mp, - ino_t ino, - u_int32_t attrtype, - char *attrname, - u_long lkflags, - u_long flags, - struct thread *td, - struct vnode **vpp) -{ - int error; - register struct ntfsmount *ntmp; - struct ntnode *ip; - struct fnode *fp; - struct vnode *vp; - enum vtype f_type; - - dprintf(("ntfs_vgetex: ino: %ju, attr: 0x%x:%s, lkf: 0x%lx, f: 0x%lx\n", - (uintmax_t)ino, attrtype, attrname ? attrname : "", lkflags, - (u_long)flags)); - - ntmp = VFSTONTFS(mp); - *vpp = NULL; - - /* Get ntnode */ - error = ntfs_ntlookup(ntmp, ino, &ip); - if (error) { - printf("ntfs_vget: ntfs_ntget failed\n"); - return (error); - } - - /* It may be not initialized fully, so force load it */ - if (!(flags & VG_DONTLOADIN) && !(ip->i_flag & IN_LOADED)) { - error = ntfs_loadntnode(ntmp, ip); - if(error) { - printf("ntfs_vget: CAN'T LOAD ATTRIBUTES FOR INO: %ju\n", - (uintmax_t)ip->i_number); - ntfs_ntput(ip); - return (error); - } - } - - error = ntfs_fget(ntmp, ip, attrtype, attrname, &fp); - if (error) { - printf("ntfs_vget: ntfs_fget failed\n"); - ntfs_ntput(ip); - return (error); - } - - f_type = VNON; - if (!(flags & VG_DONTVALIDFN) && !(fp->f_flag & FN_VALID)) { - if ((ip->i_frflag & NTFS_FRFLAG_DIR) && - (fp->f_attrtype == NTFS_A_DATA && fp->f_attrname == NULL)) { - f_type = VDIR; - } else if (flags & VG_EXT) { - f_type = VNON; - fp->f_size = fp->f_allocated = 0; - } else { - f_type = VREG; - - error = ntfs_filesize(ntmp, fp, - &fp->f_size, &fp->f_allocated); - if (error) { - ntfs_ntput(ip); - return (error); - } - } - - fp->f_flag |= FN_VALID; - } - - if (FTOV(fp)) { - vget(FTOV(fp), lkflags, td); - *vpp = FTOV(fp); - ntfs_ntput(ip); - return (0); - } - - error = getnewvnode("ntfs", ntmp->ntm_mountp, &ntfs_vnodeops, &vp); - if(error) { - ntfs_frele(fp); - ntfs_ntput(ip); - return (error); - } - /* XXX: Too early for mpsafe fs, lacks vnode lock */ - error = insmntque(vp, ntmp->ntm_mountp); - if (error) { - ntfs_frele(fp); - ntfs_ntput(ip); - return (error); - } - dprintf(("ntfs_vget: vnode: %p for ntnode: %ju\n", vp, (uintmax_t)ino)); - - fp->f_vp = vp; - vp->v_data = fp; - vp->v_type = f_type; - - vp->v_bufobj.bo_ops = &ntfs_vnbufops; - vp->v_bufobj.bo_private = vp; - - if (ino == NTFS_ROOTINO) - vp->v_vflag |= VV_ROOT; - - ntfs_ntput(ip); - - if (lkflags & LK_TYPE_MASK) { - error = vn_lock(vp, lkflags); - if (error) { - vput(vp); - return (error); - } - } - - *vpp = vp; - return (0); - -} - -static int -ntfs_vget( - struct mount *mp, - ino_t ino, - int lkflags, - struct vnode **vpp) -{ - return ntfs_vgetex(mp, ino, NTFS_A_DATA, NULL, lkflags, 0, - curthread, vpp); -} - -static void -ntfs_bufstrategy(struct bufobj *bo, struct buf *bp) -{ - struct vnode *vp; - int rc; - - vp = bo->bo_private; - KASSERT(bo == &vp->v_bufobj, ("BO/VP mismatch: vp %p bo %p != %p", - vp, &vp->v_bufobj, bo)); - rc = VOP_STRATEGY(vp, bp); - KASSERT(rc == 0, ("NTFS VOP_STRATEGY failed: bp=%p, " - "vp=%p, rc=%d", bp, vp, rc)); -} - -static struct vfsops ntfs_vfsops = { - .vfs_fhtovp = ntfs_fhtovp, - .vfs_init = ntfs_init, - .vfs_cmount = ntfs_cmount, - .vfs_mount = ntfs_mount, - .vfs_root = ntfs_root, - .vfs_statfs = ntfs_statfs, - .vfs_uninit = ntfs_uninit, - .vfs_unmount = ntfs_unmount, - .vfs_vget = ntfs_vget, -}; -VFS_SET(ntfs_vfsops, ntfs, VFCF_READONLY); -MODULE_VERSION(ntfs, 1); diff --git a/sys/fs/ntfs/ntfs_vfsops.h b/sys/fs/ntfs/ntfs_vfsops.h deleted file mode 100644 index adb737d4e54..00000000000 --- a/sys/fs/ntfs/ntfs_vfsops.h +++ /dev/null @@ -1,43 +0,0 @@ -/* $NetBSD: ntfs_vfsops.h,v 1.4 1999/10/10 14:20:33 jdolecek Exp $ */ - -/*- - * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@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$ - */ -#define VG_DONTLOADIN 0x0001 /* Tells ntfs_vgetex to do not call */ - /* ntfs_loadntnode() on ntnode, even if */ - /* ntnode not loaded */ -#define VG_DONTVALIDFN 0x0002 /* Tells ntfs_vgetex to do not validate */ - /* fnode */ -#define VG_EXT 0x0004 /* This is not main record */ - -struct mount; -struct ntfsmount; -struct thread; -struct vnode; - -int ntfs_vgetex(struct mount *, ino_t, u_int32_t, char *, u_long, u_long, - struct thread *, struct vnode **); diff --git a/sys/fs/ntfs/ntfs_vnops.c b/sys/fs/ntfs/ntfs_vnops.c deleted file mode 100644 index e78dcef81a3..00000000000 --- a/sys/fs/ntfs/ntfs_vnops.c +++ /dev/null @@ -1,687 +0,0 @@ -/* $NetBSD: ntfs_vnops.c,v 1.23 1999/10/31 19:45:27 jdolecek Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * John Heidemann of the UCLA Ficus project. - * - * 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. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -/*#define NTFS_DEBUG 1*/ -#include -#include -#include - -#include /* for pathconf(2) constants */ - -static vop_read_t ntfs_read; -static vop_getattr_t ntfs_getattr; -static vop_inactive_t ntfs_inactive; -static vop_reclaim_t ntfs_reclaim; -static vop_bmap_t ntfs_bmap; -static vop_strategy_t ntfs_strategy; -static vop_access_t ntfs_access; -static vop_open_t ntfs_open; -static vop_close_t ntfs_close; -static vop_readdir_t ntfs_readdir; -static vop_cachedlookup_t ntfs_lookup; -static vop_pathconf_t ntfs_pathconf; -static vop_vptofh_t ntfs_vptofh; - -/* - * This is a noop, simply returning what one has been given. - */ -int -ntfs_bmap(ap) - struct vop_bmap_args /* { - struct vnode *a_vp; - daddr_t a_bn; - struct bufobj **a_bop; - daddr_t *a_bnp; - int *a_runp; - int *a_runb; - } */ *ap; -{ - struct vnode *vp = ap->a_vp; - - dprintf(("ntfs_bmap: vn: %p, blk: %d\n", ap->a_vp,(u_int32_t)ap->a_bn)); - if (ap->a_bop != NULL) - *ap->a_bop = &vp->v_bufobj; - if (ap->a_bnp != NULL) - *ap->a_bnp = ap->a_bn; - if (ap->a_runp != NULL) - *ap->a_runp = 0; - if (ap->a_runb != NULL) - *ap->a_runb = 0; - return (0); -} - -static int -ntfs_read(ap) - struct vop_read_args /* { - struct vnode *a_vp; - struct uio *a_uio; - int a_ioflag; - struct ucred *a_cred; - } */ *ap; -{ - register struct vnode *vp = ap->a_vp; - register struct fnode *fp = VTOF(vp); - register struct ntnode *ip = FTONT(fp); - struct uio *uio = ap->a_uio; - struct ntfsmount *ntmp = ip->i_mp; - struct buf *bp; - daddr_t cn; - int resid, off, toread; - int error; - - dprintf(("ntfs_read: ino: %ju, off: %jd resid: %d, segflg: %d\n", - (uintmax_t)ip->i_number, (intmax_t)uio->uio_offset, - uio->uio_resid, uio->uio_segflg)); - - dprintf(("ntfs_read: filesize: %d",(u_int32_t)fp->f_size)); - - /* don't allow reading after end of file */ - if (uio->uio_offset > fp->f_size) - return (0); - - resid = MIN(uio->uio_resid, fp->f_size - uio->uio_offset); - - dprintf((", resid: %d\n", resid)); - - error = 0; - while (resid) { - cn = ntfs_btocn(uio->uio_offset); - off = ntfs_btocnoff(uio->uio_offset); - - toread = MIN(off + resid, ntfs_cntob(1)); - - error = bread(vp, cn, ntfs_cntob(1), NOCRED, &bp); - if (error) { - brelse(bp); - break; - } - - error = uiomove(bp->b_data + off, toread - off, uio); - if(error) { - brelse(bp); - break; - } - brelse(bp); - - resid -= toread - off; - } - - return (error); -} - -static int -ntfs_getattr(ap) - struct vop_getattr_args /* { - struct vnode *a_vp; - struct vattr *a_vap; - struct ucred *a_cred; - struct thread *a_td; - } */ *ap; -{ - register struct vnode *vp = ap->a_vp; - register struct fnode *fp = VTOF(vp); - register struct ntnode *ip = FTONT(fp); - register struct vattr *vap = ap->a_vap; - - dprintf(("ntfs_getattr: %ju, flags: %d\n", - (uintmax_t)ip->i_number, ip->i_flag)); - - vap->va_fsid = dev2udev(ip->i_dev); - vap->va_fileid = ip->i_number; - vap->va_mode = ip->i_mp->ntm_mode; - vap->va_nlink = (ip->i_nlink || ip->i_flag & IN_LOADED ? ip->i_nlink : 1); - vap->va_uid = ip->i_mp->ntm_uid; - vap->va_gid = ip->i_mp->ntm_gid; - vap->va_rdev = NODEV; - vap->va_size = fp->f_size; - vap->va_bytes = fp->f_allocated; - vap->va_atime = ntfs_nttimetounix(fp->f_times.t_access); - vap->va_mtime = ntfs_nttimetounix(fp->f_times.t_write); - vap->va_ctime = ntfs_nttimetounix(fp->f_times.t_create); - vap->va_flags = ip->i_flag; - vap->va_gen = 0; - vap->va_blocksize = ip->i_mp->ntm_spc * ip->i_mp->ntm_bps; - vap->va_type = vp->v_type; - vap->va_filerev = 0; - return (0); -} - -/* - * Last reference to an ntnode. If necessary, write or delete it. - */ -int -ntfs_inactive(ap) - struct vop_inactive_args /* { - struct vnode *a_vp; - } */ *ap; -{ -#ifdef NTFS_DEBUG - register struct ntnode *ip = VTONT(ap->a_vp); -#endif - - dprintf(("ntfs_inactive: vnode: %p, ntnode: %ju\n", ap->a_vp, - (uintmax_t)ip->i_number)); - - /* XXX since we don't support any filesystem changes - * right now, nothing more needs to be done - */ - return (0); -} - -/* - * Reclaim an fnode/ntnode so that it can be used for other purposes. - */ -int -ntfs_reclaim(ap) - struct vop_reclaim_args /* { - struct vnode *a_vp; - } */ *ap; -{ - register struct vnode *vp = ap->a_vp; - register struct fnode *fp = VTOF(vp); - register struct ntnode *ip = FTONT(fp); - int error; - - dprintf(("ntfs_reclaim: vnode: %p, ntnode: %ju\n", - vp, (uintmax_t)ip->i_number)); - - /* - * Destroy the vm object and flush associated pages. - */ - vnode_destroy_vobject(vp); - - if ((error = ntfs_ntget(ip)) != 0) - return (error); - - /* Purge old data structures associated with the inode. */ - ntfs_frele(fp); - ntfs_ntput(ip); - vp->v_data = NULL; - - return (0); -} - -/* - * Calculate the logical to physical mapping if not done already, - * then call the device strategy routine. - */ -int -ntfs_strategy(ap) - struct vop_strategy_args /* { - struct buf *a_bp; - } */ *ap; -{ - register struct buf *bp = ap->a_bp; - register struct vnode *vp = ap->a_vp; - register struct fnode *fp = VTOF(vp); - register struct ntnode *ip = FTONT(fp); - struct ntfsmount *ntmp = ip->i_mp; - u_int32_t toread; - int error; - - dprintf(("ntfs_strategy: offset: %d, blkno: %d, lblkno: %d\n", - (u_int32_t)bp->b_offset,(u_int32_t)bp->b_blkno, - (u_int32_t)bp->b_lblkno)); - - dprintf(("strategy: bcount: %d flags: 0x%x\n", - (u_int32_t)bp->b_bcount,bp->b_flags)); - - KASSERT(bp->b_iocmd == BIO_READ, ("Invalid buffer\n")); - - if (ntfs_cntob(bp->b_blkno) >= fp->f_size) { - clrbuf(bp); - error = 0; - } else { - toread = MIN(bp->b_bcount, - fp->f_size-ntfs_cntob(bp->b_blkno)); - dprintf(("ntfs_strategy: toread: %d, fsize: %d\n", - toread,(u_int32_t)fp->f_size)); - - error = ntfs_readattr(ntmp, ip, fp->f_attrtype, - fp->f_attrname, ntfs_cntob(bp->b_blkno), - toread, bp->b_data, NULL); - - if (error) { - printf("ntfs_strategy: ntfs_readattr failed\n"); - bp->b_error = error; - bp->b_ioflags |= BIO_ERROR; - } - - bzero(bp->b_data + toread, bp->b_bcount - toread); - } - bufdone(bp); - return (0); -} - -int -ntfs_access(ap) - struct vop_access_args /* { - struct vnode *a_vp; - accmode_t a_accmode; - struct ucred *a_cred; - struct thread *a_td; - } */ *ap; -{ - struct vnode *vp = ap->a_vp; - struct ntnode *ip = VTONT(vp); - accmode_t accmode = ap->a_accmode; - - dprintf(("ntfs_access: %d\n",ip->i_number)); - - /* - * Disallow write attempts as we assume read-only filesystems; - * unless the file is a socket, fifo, or a block or - * character device resident on the filesystem. - */ - if (accmode & VWRITE) { - switch ((int)vp->v_type) { - case VDIR: - case VLNK: - case VREG: - return (EROFS); - default: - break; - } - } - - return (vaccess(vp->v_type, ip->i_mp->ntm_mode, ip->i_mp->ntm_uid, - ip->i_mp->ntm_gid, ap->a_accmode, ap->a_cred, NULL)); -} - -/* - * Open called. - * - * Nothing to do. - */ -/* ARGSUSED */ -static int -ntfs_open(ap) - struct vop_open_args /* { - struct vnode *a_vp; - int a_mode; - struct ucred *a_cred; - struct thread *a_td; - } */ *ap; -{ -#ifdef NTFS_DEBUG - register struct vnode *vp = ap->a_vp; - register struct ntnode *ip = VTONT(vp); - - printf("ntfs_open: %d\n",ip->i_number); -#endif - - vnode_create_vobject(ap->a_vp, VTOF(ap->a_vp)->f_size, ap->a_td); - - /* - * Files marked append-only must be opened for appending. - */ - - return (0); -} - -/* - * Close called. - * - * Update the times on the inode. - */ -/* ARGSUSED */ -static int -ntfs_close(ap) - struct vop_close_args /* { - struct vnode *a_vp; - int a_fflag; - struct ucred *a_cred; - struct thread *a_td; - } */ *ap; -{ -#ifdef NTFS_DEBUG - register struct vnode *vp = ap->a_vp; - register struct ntnode *ip = VTONT(vp); - - printf("ntfs_close: %d\n",ip->i_number); -#endif - - return (0); -} - -int -ntfs_readdir(ap) - struct vop_readdir_args /* { - struct vnode *a_vp; - struct uio *a_uio; - struct ucred *a_cred; - int *a_ncookies; - u_int **cookies; - } */ *ap; -{ - register struct vnode *vp = ap->a_vp; - register struct fnode *fp = VTOF(vp); - register struct ntnode *ip = FTONT(fp); - struct uio *uio = ap->a_uio; - struct ntfsmount *ntmp = ip->i_mp; - int i, j, error = 0; - char *c, tmpbuf[5]; - u_int32_t faked = 0, num; - int ncookies = 0; - struct dirent cde; - off_t off; - - dprintf(("ntfs_readdir %d off: %d resid: %d\n",ip->i_number,(u_int32_t)uio->uio_offset,uio->uio_resid)); - - off = uio->uio_offset; - - /* Simulate . in every dir except ROOT */ - if( ip->i_number != NTFS_ROOTINO ) { - struct dirent dot = { - .d_fileno = NTFS_ROOTINO, - .d_reclen = sizeof(struct dirent), - .d_type = DT_DIR, - .d_namlen = 1, - .d_name = "." - }; - - if( uio->uio_offset < sizeof(struct dirent) ) { - dot.d_fileno = ip->i_number; - error = uiomove((char *)&dot,sizeof(struct dirent),uio); - if(error) - return (error); - - ncookies ++; - } - } - - /* Simulate .. in every dir including ROOT */ - if( uio->uio_offset < 2 * sizeof(struct dirent) ) { - struct dirent dotdot = { - .d_fileno = NTFS_ROOTINO, - .d_reclen = sizeof(struct dirent), - .d_type = DT_DIR, - .d_namlen = 2, - .d_name = ".." - }; - - error = uiomove((char *)&dotdot,sizeof(struct dirent),uio); - if(error) - return (error); - - ncookies ++; - } - - faked = (ip->i_number == NTFS_ROOTINO) ? 1 : 2; - num = uio->uio_offset / sizeof(struct dirent) - faked; - - while( uio->uio_resid >= sizeof(struct dirent) ) { - struct attr_indexentry *iep; - - error = ntfs_ntreaddir(ntmp, fp, num, &iep); - - if(error) - return (error); - - if( NULL == iep ) - break; - - for(; !(iep->ie_flag & NTFS_IEFLAG_LAST) && (uio->uio_resid >= sizeof(struct dirent)); - iep = NTFS_NEXTREC(iep, struct attr_indexentry *)) - { - if(!ntfs_isnamepermitted(ntmp,iep)) - continue; - - for(i=0, j=0; iie_fnamelen; i++) { - c = NTFS_U28(iep->ie_fname[i]); - while (*c != '\0') - cde.d_name[j++] = *c++; - } - cde.d_name[j] = '\0'; - dprintf(("ntfs_readdir: elem: %d, fname:[%s] type: %d, flag: %d, ", - num, cde.d_name, iep->ie_fnametype, - iep->ie_flag)); - cde.d_namlen = j; - cde.d_fileno = iep->ie_number; - cde.d_type = (iep->ie_fflag & NTFS_FFLAG_DIR) ? DT_DIR : DT_REG; - cde.d_reclen = sizeof(struct dirent); - dprintf(("%s\n", (cde.d_type == DT_DIR) ? "dir":"reg")); - - error = uiomove((char *)&cde, sizeof(struct dirent), uio); - if(error) - return (error); - - ncookies++; - num++; - } - } - - dprintf(("ntfs_readdir: %d entries (%d bytes) read\n", - ncookies,(u_int)(uio->uio_offset - off))); - dprintf(("ntfs_readdir: off: %d resid: %d\n", - (u_int32_t)uio->uio_offset,uio->uio_resid)); - - if (!error && ap->a_ncookies != NULL) { - struct dirent* dpStart; - struct dirent* dp; - u_long *cookies; - u_long *cookiep; - - ddprintf(("ntfs_readdir: %d cookies\n",ncookies)); - if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) - panic("ntfs_readdir: unexpected uio from NFS server"); - dpStart = (struct dirent *) - ((caddr_t)uio->uio_iov->iov_base - - (uio->uio_offset - off)); - cookies = malloc(ncookies * sizeof(u_long), - M_TEMP, M_WAITOK); - for (dp = dpStart, cookiep = cookies, i=0; - i < ncookies; - dp = (struct dirent *)((caddr_t) dp + dp->d_reclen), i++) { - off += dp->d_reclen; - *cookiep++ = (u_int) off; - } - *ap->a_ncookies = ncookies; - *ap->a_cookies = cookies; - } -/* - if (ap->a_eofflag) - *ap->a_eofflag = VTONT(ap->a_vp)->i_size <= uio->uio_offset; -*/ - return (error); -} - -int -ntfs_lookup(ap) - struct vop_cachedlookup_args /* { - struct vnode *a_dvp; - struct vnode **a_vpp; - struct componentname *a_cnp; - } */ *ap; -{ - register struct vnode *dvp = ap->a_dvp; - register struct ntnode *dip = VTONT(dvp); - struct ntfsmount *ntmp = dip->i_mp; - struct componentname *cnp = ap->a_cnp; - struct ucred *cred = cnp->cn_cred; - int error; - dprintf(("ntfs_lookup: \"%.*s\" (%ld bytes) in %d\n", - (int)cnp->cn_namelen, cnp->cn_nameptr, cnp->cn_namelen, - dip->i_number)); - - error = VOP_ACCESS(dvp, VEXEC, cred, cnp->cn_thread); - if(error) - return (error); - - if ((cnp->cn_flags & ISLASTCN) && - (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) - return (EROFS); - - if(cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') { - dprintf(("ntfs_lookup: faking . directory in %d\n", - dip->i_number)); - - VREF(dvp); - *ap->a_vpp = dvp; - error = 0; - } else if (cnp->cn_flags & ISDOTDOT) { - struct ntvattr *vap; - - dprintf(("ntfs_lookup: faking .. directory in %d\n", - dip->i_number)); - - error = ntfs_ntvattrget(ntmp, dip, NTFS_A_NAME, NULL, 0, &vap); - if(error) - return (error); - - VOP_UNLOCK(dvp,0); - dprintf(("ntfs_lookup: parentdir: %d\n", - vap->va_a_name->n_pnumber)); - error = VFS_VGET(ntmp->ntm_mountp, vap->va_a_name->n_pnumber, - LK_EXCLUSIVE, ap->a_vpp); - ntfs_ntvattrrele(vap); - if (error) { - vn_lock(dvp,LK_EXCLUSIVE|LK_RETRY); - return (error); - } - } else { - error = ntfs_ntlookupfile(ntmp, dvp, cnp, ap->a_vpp); - if (error) { - dprintf(("ntfs_ntlookupfile: returned %d\n", error)); - return (error); - } - - dprintf(("ntfs_lookup: found ino: %ju\n", - (uintmax_t)VTONT(*ap->a_vpp)->i_number)); - } - - if (cnp->cn_flags & MAKEENTRY) - cache_enter(dvp, *ap->a_vpp, cnp); - - return (error); -} - -/* - * Return POSIX pathconf information applicable to NTFS filesystem - */ -int -ntfs_pathconf(ap) - struct vop_pathconf_args *ap; -{ - - switch (ap->a_name) { - case _PC_LINK_MAX: - *ap->a_retval = 1; - return (0); - case _PC_NAME_MAX: - *ap->a_retval = NTFS_MAXFILENAME; - return (0); - case _PC_PATH_MAX: - *ap->a_retval = PATH_MAX; - return (0); - case _PC_CHOWN_RESTRICTED: - *ap->a_retval = 1; - return (0); - case _PC_NO_TRUNC: - *ap->a_retval = 0; - return (0); - default: - return (EINVAL); - } - /* NOTREACHED */ -} - -int -ntfs_vptofh(ap) - struct vop_vptofh_args /* { - struct vnode *a_vp; - struct fid *a_fhp; - } */ *ap; -{ - register struct ntnode *ntp; - register struct ntfid *ntfhp; - - ddprintf(("ntfs_fhtovp(): %p\n", ap->a_vp)); - - ntp = VTONT(ap->a_vp); - ntfhp = (struct ntfid *)ap->a_fhp; - ntfhp->ntfid_len = sizeof(struct ntfid); - ntfhp->ntfid_ino = ntp->i_number; - /* ntfhp->ntfid_gen = ntp->i_gen; */ - return (0); -} - -/* - * Global vfs data structures - */ -struct vop_vector ntfs_vnodeops = { - .vop_default = &default_vnodeops, - - .vop_access = ntfs_access, - .vop_bmap = ntfs_bmap, - .vop_cachedlookup = ntfs_lookup, - .vop_close = ntfs_close, - .vop_getattr = ntfs_getattr, - .vop_inactive = ntfs_inactive, - .vop_lookup = vfs_cache_lookup, - .vop_open = ntfs_open, - .vop_pathconf = ntfs_pathconf, - .vop_read = ntfs_read, - .vop_readdir = ntfs_readdir, - .vop_reclaim = ntfs_reclaim, - .vop_strategy = ntfs_strategy, - .vop_vptofh = ntfs_vptofh, -}; diff --git a/sys/fs/ntfs/ntfsmount.h b/sys/fs/ntfs/ntfsmount.h deleted file mode 100644 index f64652c4725..00000000000 --- a/sys/fs/ntfs/ntfsmount.h +++ /dev/null @@ -1,44 +0,0 @@ -/* $NetBSD: ntfsmount.h,v 1.3 1999/07/26 14:02:32 jdolecek Exp $ */ - -/*- - * Copyright (c) 1998, 1999 Semen Ustimenko - * 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$ - */ - -#define NTFS_MFLAG_CASEINS 0x00000001 -#define NTFS_MFLAG_ALLNAMES 0x00000002 -#define NTFS_MFLAG_KICONV 0x00000004 - -struct ntfs_args { - char *fspec; /* block special device to mount */ - struct oexport_args export; /* network export information */ - uid_t uid; /* uid that owns ntfs files */ - gid_t gid; /* gid that owns ntfs files */ - mode_t mode; /* mask to be applied for ntfs perms */ - u_long flag; /* additional flags */ - char *cs_ntfs; /* NTFS Charset */ - char *cs_local; /* Local Charset */ -}; diff --git a/sys/modules/ntfs/Makefile b/sys/modules/ntfs/Makefile deleted file mode 100644 index 367af98792d..00000000000 --- a/sys/modules/ntfs/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# $FreeBSD$ - -.PATH: ${.CURDIR}/../../fs/ntfs - -KMOD= ntfs -SRCS= vnode_if.h \ - ntfs_vfsops.c ntfs_vnops.c ntfs_subr.c ntfs_ihash.c \ - ntfs_compr.c -EXPORT_SYMS= ntfs_iconv - -.include diff --git a/sys/modules/ntfs_iconv/Makefile b/sys/modules/ntfs_iconv/Makefile deleted file mode 100644 index 33e6d42a155..00000000000 --- a/sys/modules/ntfs_iconv/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# $FreeBSD$ - -.PATH: ${.CURDIR}/../../fs/ntfs -KMOD= ntfs_iconv -SRCS= ntfs_iconv.c - -.include From 136b1ada11e4b3ec91b4b15562ba803e5ab66c10 Mon Sep 17 00:00:00 2001 From: "Alexander V. Chernikov" Date: Sat, 2 Mar 2013 18:51:26 +0000 Subject: [PATCH 0544/1476] Fix ipfw table argument parsing/printing. Fix style. PR: kern/175909 Submitted by: Daniel Hagerty MFC after: 2 weeks --- sbin/ipfw/ipfw2.c | 146 +++++++++++++++++++++++++++++----------------- 1 file changed, 92 insertions(+), 54 deletions(-) diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c index 530f3195a1f..71b9e06142e 100644 --- a/sbin/ipfw/ipfw2.c +++ b/sbin/ipfw/ipfw2.c @@ -3912,6 +3912,7 @@ ipfw_flush(int force) static void table_list(uint16_t num, int need_header); +static void table_fill_xentry(char *arg, ipfw_table_xentry *xent); /* * This one handles all table-related commands @@ -3927,8 +3928,7 @@ ipfw_table_handler(int ac, char *av[]) int do_add; int is_all; size_t len; - char *p; - uint32_t a, type, mask, addrlen; + uint32_t a, mask; uint32_t tables_max; mask = 0; // XXX uninitialized ? @@ -3965,57 +3965,8 @@ ipfw_table_handler(int ac, char *av[]) ac--; av++; if (!ac) errx(EX_USAGE, "address required"); - /* - * Let's try to guess type by agrument. - * Possible types: - * 1) IPv4[/mask] - * 2) IPv6[/mask] - * 3) interface name - * 4) port ? - */ - type = 0; - if (ishexnumber(*av[0])) { - /* Remove / if exists */ - if ((p = strchr(*av, '/')) != NULL) { - *p = '\0'; - mask = atoi(p + 1); - } - if (inet_pton(AF_INET, *av, &xent.k.addr6) == 1) { - type = IPFW_TABLE_CIDR; - if ((p != NULL) && (mask > 32)) - errx(EX_DATAERR, "bad IPv4 mask width: %s", p + 1); - xent.masklen = p ? mask : 32; - addrlen = sizeof(struct in_addr); - } else if (inet_pton(AF_INET6, *av, &xent.k.addr6) == 1) { - type = IPFW_TABLE_CIDR; - if ((p != NULL) && (mask > 128)) - errx(EX_DATAERR, "bad IPv6 mask width: %s", p + 1); - xent.masklen = p ? mask : 128; - addrlen = sizeof(struct in6_addr); - } - } - - if ((type == 0) && (strchr(*av, '.') == NULL)) { - /* Assume interface name. Copy significant data only */ - mask = MIN(strlen(*av), IF_NAMESIZE - 1); - memcpy(xent.k.iface, *av, mask); - /* Set mask to exact match */ - xent.masklen = 8 * IF_NAMESIZE; - type = IPFW_TABLE_INTERFACE; - addrlen = IF_NAMESIZE; - } - - if (type == 0) { - if (lookup_host(*av, (struct in_addr *)&xent.k.addr6) != 0) - errx(EX_NOHOST, "hostname ``%s'' unknown", *av); - xent.masklen = 32; - type = IPFW_TABLE_CIDR; - addrlen = sizeof(struct in_addr); - } - - xent.type = type; - xent.len = offsetof(ipfw_table_xentry, k) + addrlen; + table_fill_xentry(*av, &xent); ac--; av++; if (do_add && ac) { @@ -4064,6 +4015,93 @@ ipfw_table_handler(int ac, char *av[]) errx(EX_USAGE, "invalid table command %s", *av); } +static void +table_fill_xentry(char *arg, ipfw_table_xentry *xent) +{ + int addrlen, mask, masklen, type; + struct in6_addr *paddr; + uint32_t *pkey; + char *p; + uint32_t key; + + mask = 0; + type = 0; + addrlen = 0; + masklen = 0; + + /* + * Let's try to guess type by agrument. + * Possible types: + * 1) IPv4[/mask] + * 2) IPv6[/mask] + * 3) interface name + * 4) port, uid/gid or other u32 key (base 10 format) + * 5) hostname + */ + paddr = &xent->k.addr6; + if (ishexnumber(*arg) != 0 || *arg == ':') { + /* Remove / if exists */ + if ((p = strchr(arg, '/')) != NULL) { + *p = '\0'; + mask = atoi(p + 1); + } + + if (inet_pton(AF_INET, arg, paddr) == 1) { + if (p != NULL && mask > 32) + errx(EX_DATAERR, "bad IPv4 mask width: %s", + p + 1); + + type = IPFW_TABLE_CIDR; + masklen = p ? mask : 32; + addrlen = sizeof(struct in_addr); + } else if (inet_pton(AF_INET6, arg, paddr) == 1) { + if (IN6_IS_ADDR_V4COMPAT(paddr)) + errx(EX_DATAERR, + "Use IPv4 instead of v4-compatible"); + if (p != NULL && mask > 128) + errx(EX_DATAERR, "bad IPv6 mask width: %s", + p + 1); + + type = IPFW_TABLE_CIDR; + masklen = p ? mask : 128; + addrlen = sizeof(struct in6_addr); + } else { + /* Port or any other key */ + key = strtol(arg, &p, 10); + /* Skip non-base 10 entries like 'fa1' */ + if (p != arg) { + pkey = (uint32_t *)paddr; + *pkey = htonl(key); + type = IPFW_TABLE_CIDR; + addrlen = sizeof(uint32_t); + } + } + } + + if (type == 0 && strchr(arg, '.') == NULL) { + /* Assume interface name. Copy significant data only */ + mask = MIN(strlen(arg), IF_NAMESIZE - 1); + memcpy(xent->k.iface, arg, mask); + /* Set mask to exact match */ + masklen = 8 * IF_NAMESIZE; + type = IPFW_TABLE_INTERFACE; + addrlen = IF_NAMESIZE; + } + + if (type == 0) { + if (lookup_host(arg, (struct in_addr *)paddr) != 0) + errx(EX_NOHOST, "hostname ``%s'' unknown", arg); + + masklen = 32; + type = IPFW_TABLE_CIDR; + addrlen = sizeof(struct in_addr); + } + + xent->type = type; + xent->masklen = masklen; + xent->len = offsetof(ipfw_table_xentry, k) + addrlen; +} + static void table_list(uint16_t num, int need_header) { @@ -4107,8 +4145,8 @@ table_list(uint16_t num, int need_header) tval = xent->value; addr6 = &xent->k.addr6; - if ((addr6->s6_addr32[0] == 0) && (addr6->s6_addr32[1] == 0) && - (addr6->s6_addr32[2] == 0)) { + + if (IN6_IS_ADDR_V4COMPAT(addr6)) { /* IPv4 address */ inet_ntop(AF_INET, &addr6->s6_addr32[3], tbuf, sizeof(tbuf)); } else { From 7493f24ee6846df33931904c87493b08400df5bd Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sat, 2 Mar 2013 21:11:30 +0000 Subject: [PATCH 0545/1476] - Implement two new system calls: int bindat(int fd, int s, const struct sockaddr *addr, socklen_t addrlen); int connectat(int fd, int s, const struct sockaddr *name, socklen_t namelen); which allow to bind and connect respectively to a UNIX domain socket with a path relative to the directory associated with the given file descriptor 'fd'. - Add manual pages for the new syscalls. - Make the new syscalls available for processes in capability mode sandbox. - Add capability rights CAP_BINDAT and CAP_CONNECTAT that has to be present on the directory descriptor for the syscalls to work. - Update audit(4) to support those two new syscalls and to handle path in sockaddr_un structure relative to the given directory descriptor. - Update procstat(1) to recognize the new capability rights. - Document the new capability rights in cap_rights_limit(2). Sponsored by: The FreeBSD Foundation Discussed with: rwatson, jilles, kib, des --- contrib/openbsm/etc/audit_event | 2 + lib/libc/sys/Makefile.inc | 2 + lib/libc/sys/Symbol.map | 2 + lib/libc/sys/bindat.2 | 109 +++++++++++++++++++++++++ lib/libc/sys/cap_rights_limit.2 | 10 +++ lib/libc/sys/connectat.2 | 109 +++++++++++++++++++++++++ sys/bsm/audit_kevents.h | 2 + sys/compat/freebsd32/syscalls.master | 4 + sys/kern/capabilities.conf | 12 +-- sys/kern/syscalls.master | 4 + sys/kern/uipc_domain.c | 2 + sys/kern/uipc_socket.c | 46 ++++++++++- sys/kern/uipc_syscalls.c | 117 ++++++++++++++++++++------- sys/kern/uipc_usrreq.c | 47 +++++++++-- sys/security/audit/audit.h | 8 +- sys/security/audit/audit_arg.c | 6 +- sys/security/audit/audit_bsm.c | 15 ++++ sys/sys/capability.h | 11 ++- sys/sys/protosw.h | 8 ++ sys/sys/socket.h | 2 + sys/sys/socketvar.h | 4 + usr.bin/procstat/procstat_files.c | 7 ++ 22 files changed, 475 insertions(+), 54 deletions(-) create mode 100644 lib/libc/sys/bindat.2 create mode 100644 lib/libc/sys/connectat.2 diff --git a/contrib/openbsm/etc/audit_event b/contrib/openbsm/etc/audit_event index f82841ae773..49b5f9d26d7 100644 --- a/contrib/openbsm/etc/audit_event +++ b/contrib/openbsm/etc/audit_event @@ -568,6 +568,8 @@ 43204:AUE_CAP_IOCTLS_GET:cap_ioctls_get(2):fm 43205:AUE_CAP_FCNTLS_LIMIT:cap_fcntls_limit(2):fm 43206:AUE_CAP_FCNTLS_GET:cap_fcntls_get(2):fm +43207:AUE_BINDAT:bindat(2):nt +43208:AUE_CONNECTAT:connectat(2):nt # # Solaris userspace events. # diff --git a/lib/libc/sys/Makefile.inc b/lib/libc/sys/Makefile.inc index 03c00900e22..62aab6c96e1 100644 --- a/lib/libc/sys/Makefile.inc +++ b/lib/libc/sys/Makefile.inc @@ -91,6 +91,7 @@ MAN+= abort2.2 \ aio_waitcomplete.2 \ aio_write.2 \ bind.2 \ + bindat.2 \ brk.2 \ cap_enter.2 \ cap_fcntls_limit.2 \ @@ -105,6 +106,7 @@ MAN+= abort2.2 \ close.2 \ closefrom.2 \ connect.2 \ + connectat.2 \ cpuset.2 \ cpuset_getaffinity.2 \ dup.2 \ diff --git a/lib/libc/sys/Symbol.map b/lib/libc/sys/Symbol.map index 7738e46d8c8..fc000641ad0 100644 --- a/lib/libc/sys/Symbol.map +++ b/lib/libc/sys/Symbol.map @@ -378,6 +378,7 @@ FBSD_1.2 { }; FBSD_1.3 { + bindat; cap_fcntls_get; cap_fcntls_limit; cap_ioctls_get; @@ -386,6 +387,7 @@ FBSD_1.3 { cap_rights_limit; cap_sandboxed; clock_getcpuclockid2; + connectat; ffclock_getcounter; ffclock_getestimate; ffclock_setestimate; diff --git a/lib/libc/sys/bindat.2 b/lib/libc/sys/bindat.2 new file mode 100644 index 00000000000..9274679374a --- /dev/null +++ b/lib/libc/sys/bindat.2 @@ -0,0 +1,109 @@ +.\" Copyright (c) 2013 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This documentation was written by Pawel Jakub Dawidek under sponsorship from +.\" the FreeBSD Foundation. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd February 13, 2013 +.Dt BINDAT 2 +.Os +.Sh NAME +.Nm bindat +.Nd assign a local protocol address to a socket +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In sys/types.h +.In sys/socket.h +.Pp +.In fcntl.h +.Ft int +.Fn bindat "int fd" "int s" "const struct sockaddr *addr" "socklen_t addrlen" +.Sh DESCRIPTION +The +.Fn bindat +system call assigns the local protocol address to a socket. +It works just like the +.Xr bind 2 +system call with two exceptions: +.Pp +.Bl -enum -offset indent -compact +.It +It is limited to sockets in the PF_LOCAL domain. +.Pp +.It +If the file path stored in the +.Fa sun_path +field of the sockaddr_un structure is a relative path, it is located relative +to the directory associated with the file descriptor +.Fa fd . +If +.Fn bindat +is passed the special value +.Dv AT_FDCWD +in the +.Fa fd +parameter, the current working directory is used and the behavior is identical +to a call to +.Xr bind 2 . +.El +.Sh RETURN VALUES +.Rv -std bindat +.Sh ERRORS +The +.Fn bindat +system call may fail with the same errors as the +.Xr bind 2 +system call for a UNIX domain socket or with the following errors: +.Bl -tag -width Er +.It Bq Er EBADF +The +.Fa sun_path +field does not specify an absolute path and the +.Fa fd +argument is neither +.Dv AT_FDCWD +nor a valid file descriptor. +.It Bq Er ENOTDIR +The +.Fa sun_path +field is not an absolute path and +.Fa fd +is neither +.Dv AT_FDCWD +nor a file descriptor associated with a directory. +.El +.Sh SEE ALSO +.Xr bind 2 , +.Xr connectat 2 , +.Xr socket 2 , +.Xr unix 4 +.Sh AUTHORS +The +.Nm +was developed by +.An Pawel Jakub Dawidek Aq pawel@dawidek.net +under sponsorship from the FreeBSD Foundation. diff --git a/lib/libc/sys/cap_rights_limit.2 b/lib/libc/sys/cap_rights_limit.2 index 0c527aad775..d0605af1e02 100644 --- a/lib/libc/sys/cap_rights_limit.2 +++ b/lib/libc/sys/cap_rights_limit.2 @@ -104,12 +104,20 @@ or and that socket options set with .Xr setsockopt 2 may also affect binding behavior. +.It Dv CAP_BINDAT +Permit +.Xr bindat 2 . +This right has to be present on the directory descriptor. .It Dv CAP_CONNECT Permit .Xr connect 2 ; also required for .Xr sendto 2 with a non-NULL destination address. +.It Dv CAP_CONNECTAT +Permit +.Xr connectat 2 . +This right has to be present on the directory descriptor. .It Dv CAP_CREATE Permit .Xr openat 2 @@ -511,11 +519,13 @@ argument points at an invalid address. .Xr aio_read 2 , .Xr aio_write 2 , .Xr bind 2 , +.Xr bindat 2 , .Xr cap_enter 2 , .Xr cap_fcntls_limit 2 , .Xr cap_ioctls_limit 2 , .Xr cap_rights_limit 2 , .Xr connect 2 , +.Xr connectat 2 , .Xr dup 2 , .Xr dup2 2 , .Xr extattr_delete_fd 2 , diff --git a/lib/libc/sys/connectat.2 b/lib/libc/sys/connectat.2 new file mode 100644 index 00000000000..8cebf98372e --- /dev/null +++ b/lib/libc/sys/connectat.2 @@ -0,0 +1,109 @@ +.\" Copyright (c) 2013 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This documentation was written by Pawel Jakub Dawidek under sponsorship from +.\" the FreeBSD Foundation. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd February 13, 2013 +.Dt CONNECTAT 2 +.Os +.Sh NAME +.Nm connectat +.Nd initiate a connection on a socket +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In sys/types.h +.In sys/socket.h +.Pp +.In fcntl.h +.Ft int +.Fn connectat "int fd" "int s" "const struct sockaddr *name" "socklen_t namelen" +.Sh DESCRIPTION +The +.Fn connectat +system call initiates a connection on a socket. +It works just like the +.Xr connect 2 +system call with two exceptions: +.Pp +.Bl -enum -offset indent -compact +.It +It is limited to sockets in the PF_LOCAL domain. +.Pp +.It +If the file path stored in the +.Fa sun_path +field of the sockaddr_un structure is a relative path, it is located relative +to the directory associated with the file descriptor +.Fa fd . +If +.Fn connectat +is passed the special value +.Dv AT_FDCWD +in the +.Fa fd +parameter, the current working directory is used and the behavior is identical +to a call to +.Xr connect 2 . +.El +.Sh RETURN VALUES +.Rv -std connectat +.Sh ERRORS +The +.Fn connectat +system call may fail with the same errors as the +.Xr connect 2 +system call for a UNIX domain socket or with the following errors: +.Bl -tag -width Er +.It Bq Er EBADF +The +.Fa sun_path +field does not specify an absolute path and the +.Fa fd +argument is neither +.Dv AT_FDCWD +nor a valid file descriptor. +.It Bq Er ENOTDIR +The +.Fa sun_path +field is not an absolute path and +.Fa fd +is neither +.Dv AT_FDCWD +nor a file descriptor associated with a directory. +.El +.Sh SEE ALSO +.Xr bindat 2 , +.Xr connect 2 , +.Xr socket 2 , +.Xr unix 4 +.Sh AUTHORS +The +.Nm +was developed by +.An Pawel Jakub Dawidek Aq pawel@dawidek.net +under sponsorship from the FreeBSD Foundation. diff --git a/sys/bsm/audit_kevents.h b/sys/bsm/audit_kevents.h index 9d71fa28335..d56a96b4e68 100644 --- a/sys/bsm/audit_kevents.h +++ b/sys/bsm/audit_kevents.h @@ -608,6 +608,8 @@ #define AUE_CAP_IOCTLS_GET 43204 /* TrustedBSD. */ #define AUE_CAP_FCNTLS_LIMIT 43205 /* TrustedBSD. */ #define AUE_CAP_FCNTLS_GET 43206 /* TrustedBSD. */ +#define AUE_BINDAT 43207 /* TrustedBSD. */ +#define AUE_CONNECTAT 43208 /* TrustedBSD. */ /* * Darwin BSM uses a number of AUE_O_* definitions, which are aliased to the diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master index 6552d137e5a..655296c779e 100644 --- a/sys/compat/freebsd32/syscalls.master +++ b/sys/compat/freebsd32/syscalls.master @@ -1015,3 +1015,7 @@ uint32_t fcntlrights); } 537 AUE_CAP_FCNTLS_GET NOPROTO { int cap_fcntls_get(int fd, \ uint32_t *fcntlrightsp); } +538 AUE_BINDAT NOPROTO { int bindat(int fd, int s, caddr_t name, \ + int namelen); } +539 AUE_CONNECTAT NOPROTO { int connectat(int fd, int s, caddr_t name, \ + int namelen); } diff --git a/sys/kern/capabilities.conf b/sys/kern/capabilities.conf index 3c087827d8b..71c22bf2264 100644 --- a/sys/kern/capabilities.conf +++ b/sys/kern/capabilities.conf @@ -100,11 +100,9 @@ aio_write #audit ## -## Disllow bind(2) for now, even though we support CAP_BIND. +## Allow bindat(2). ## -## XXXRW: Revisit this. -## -#bind +bindat ## ## Allow capability mode and capability system calls. @@ -132,11 +130,9 @@ close closefrom ## -## Disallow connect(2) for now, despite CAP_CONNECT. +## Allow connectat(2). ## -## XXXRW: Revisit this. -## -#connect +connectat ## ## cpuset(2) and related calls require scoping by process, but should diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index 1a890104c56..9c22f2ba9e9 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -965,5 +965,9 @@ uint32_t fcntlrights); } 537 AUE_CAP_FCNTLS_GET STD { int cap_fcntls_get(int fd, \ uint32_t *fcntlrightsp); } +538 AUE_BINDAT STD { int bindat(int fd, int s, caddr_t name, \ + int namelen); } +539 AUE_CONNECTAT STD { int connectat(int fd, int s, caddr_t name, \ + int namelen); } ; Please copy any additions and changes to the following compatability tables: ; sys/compat/freebsd32/syscalls.master diff --git a/sys/kern/uipc_domain.c b/sys/kern/uipc_domain.c index c1462328ed7..709cc0eb056 100644 --- a/sys/kern/uipc_domain.c +++ b/sys/kern/uipc_domain.c @@ -136,8 +136,10 @@ protosw_init(struct protosw *pr) #define DEFAULT(foo, bar) if ((foo) == NULL) (foo) = (bar) DEFAULT(pu->pru_accept, pru_accept_notsupp); DEFAULT(pu->pru_bind, pru_bind_notsupp); + DEFAULT(pu->pru_bindat, pru_bindat_notsupp); DEFAULT(pu->pru_connect, pru_connect_notsupp); DEFAULT(pu->pru_connect2, pru_connect2_notsupp); + DEFAULT(pu->pru_connectat, pru_connectat_notsupp); DEFAULT(pu->pru_control, pru_control_notsupp); DEFAULT(pu->pru_disconnect, pru_disconnect_notsupp); DEFAULT(pu->pru_listen, pru_listen_notsupp); diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index de8ae5a7243..7fcac1ceef3 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -615,7 +615,18 @@ sobind(struct socket *so, struct sockaddr *nam, struct thread *td) CURVNET_SET(so->so_vnet); error = (*so->so_proto->pr_usrreqs->pru_bind)(so, nam, td); CURVNET_RESTORE(); - return error; + return (error); +} + +int +sobindat(int fd, struct socket *so, struct sockaddr *nam, struct thread *td) +{ + int error; + + CURVNET_SET(so->so_vnet); + error = (*so->so_proto->pr_usrreqs->pru_bindat)(fd, so, nam, td); + CURVNET_RESTORE(); + return (error); } /* @@ -638,7 +649,7 @@ solisten(struct socket *so, int backlog, struct thread *td) CURVNET_SET(so->so_vnet); error = (*so->so_proto->pr_usrreqs->pru_listen)(so, backlog, td); CURVNET_RESTORE(); - return error; + return (error); } int @@ -895,6 +906,13 @@ soaccept(struct socket *so, struct sockaddr **nam) int soconnect(struct socket *so, struct sockaddr *nam, struct thread *td) +{ + + return (soconnectat(AT_FDCWD, so, nam, td)); +} + +int +soconnectat(int fd, struct socket *so, struct sockaddr *nam, struct thread *td) { int error; @@ -917,7 +935,13 @@ soconnect(struct socket *so, struct sockaddr *nam, struct thread *td) * biting us. */ so->so_error = 0; - error = (*so->so_proto->pr_usrreqs->pru_connect)(so, nam, td); + if (fd == AT_FDCWD) { + error = (*so->so_proto->pr_usrreqs->pru_connect)(so, + nam, td); + } else { + error = (*so->so_proto->pr_usrreqs->pru_connectat)(fd, + so, nam, td); + } } CURVNET_RESTORE(); @@ -3140,6 +3164,14 @@ pru_bind_notsupp(struct socket *so, struct sockaddr *nam, struct thread *td) return EOPNOTSUPP; } +int +pru_bindat_notsupp(int fd, struct socket *so, struct sockaddr *nam, + struct thread *td) +{ + + return EOPNOTSUPP; +} + int pru_connect_notsupp(struct socket *so, struct sockaddr *nam, struct thread *td) { @@ -3147,6 +3179,14 @@ pru_connect_notsupp(struct socket *so, struct sockaddr *nam, struct thread *td) return EOPNOTSUPP; } +int +pru_connectat_notsupp(int fd, struct socket *so, struct sockaddr *nam, + struct thread *td) +{ + + return EOPNOTSUPP; +} + int pru_connect2_notsupp(struct socket *so1, struct socket *so2) { diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index 847db35b503..cd37a4d24db 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -201,26 +201,23 @@ sys_bind(td, uap) struct sockaddr *sa; int error; - if ((error = getsockaddr(&sa, uap->name, uap->namelen)) != 0) - return (error); - - error = kern_bind(td, uap->s, sa); - free(sa, M_SONAME); + error = getsockaddr(&sa, uap->name, uap->namelen); + if (error == 0) { + error = kern_bind(td, uap->s, sa); + free(sa, M_SONAME); + } return (error); } -int -kern_bind(td, fd, sa) - struct thread *td; - int fd; - struct sockaddr *sa; +static int +kern_bindat(struct thread *td, int dirfd, int fd, struct sockaddr *sa) { struct socket *so; struct file *fp; int error; AUDIT_ARG_FD(fd); - AUDIT_ARG_SOCKADDR(td, sa); + AUDIT_ARG_SOCKADDR(td, dirfd, sa); error = getsock_cap(td->td_proc->p_fd, fd, CAP_BIND, &fp, NULL); if (error) return (error); @@ -231,13 +228,48 @@ kern_bind(td, fd, sa) #endif #ifdef MAC error = mac_socket_check_bind(td->td_ucred, so, sa); - if (error == 0) + if (error == 0) { +#endif + if (dirfd == AT_FDCWD) + error = sobind(so, sa, td); + else + error = sobindat(dirfd, so, sa, td); +#ifdef MAC + } #endif - error = sobind(so, sa, td); fdrop(fp, td); return (error); } +int +kern_bind(struct thread *td, int fd, struct sockaddr *sa) +{ + + return (kern_bindat(td, AT_FDCWD, fd, sa)); +} + +/* ARGSUSED */ +int +sys_bindat(td, uap) + struct thread *td; + struct bindat_args /* { + int fd; + int s; + caddr_t name; + int namelen; + } */ *uap; +{ + struct sockaddr *sa; + int error; + + error = getsockaddr(&sa, uap->name, uap->namelen); + if (error == 0) { + error = kern_bindat(td, uap->fd, uap->s, sa); + free(sa, M_SONAME); + } + return (error); +} + /* ARGSUSED */ int sys_listen(td, uap) @@ -435,7 +467,7 @@ kern_accept(struct thread *td, int s, struct sockaddr **name, *namelen = 0; goto done; } - AUDIT_ARG_SOCKADDR(td, sa); + AUDIT_ARG_SOCKADDR(td, AT_FDCWD, sa); if (name) { /* check sa_len before it is destroyed */ if (*namelen > sa->sa_len) @@ -510,20 +542,15 @@ sys_connect(td, uap) int error; error = getsockaddr(&sa, uap->name, uap->namelen); - if (error) - return (error); - - error = kern_connect(td, uap->s, sa); - free(sa, M_SONAME); + if (error == 0) { + error = kern_connect(td, uap->s, sa); + free(sa, M_SONAME); + } return (error); } - -int -kern_connect(td, fd, sa) - struct thread *td; - int fd; - struct sockaddr *sa; +static int +kern_connectat(struct thread *td, int dirfd, int fd, struct sockaddr *sa) { struct socket *so; struct file *fp; @@ -531,7 +558,7 @@ kern_connect(td, fd, sa) int interrupted = 0; AUDIT_ARG_FD(fd); - AUDIT_ARG_SOCKADDR(td, sa); + AUDIT_ARG_SOCKADDR(td, dirfd, sa); error = getsock_cap(td->td_proc->p_fd, fd, CAP_CONNECT, &fp, NULL); if (error) return (error); @@ -549,7 +576,10 @@ kern_connect(td, fd, sa) if (error) goto bad; #endif - error = soconnect(so, sa, td); + if (dirfd == AT_FDCWD) + error = soconnect(so, sa, td); + else + error = soconnectat(dirfd, so, sa, td); if (error) goto bad; if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) { @@ -581,6 +611,35 @@ done1: return (error); } +int +kern_connect(struct thread *td, int fd, struct sockaddr *sa) +{ + + return (kern_connectat(td, AT_FDCWD, fd, sa)); +} + +/* ARGSUSED */ +int +sys_connectat(td, uap) + struct thread *td; + struct connectat_args /* { + int fd; + int s; + caddr_t name; + int namelen; + } */ *uap; +{ + struct sockaddr *sa; + int error; + + error = getsockaddr(&sa, uap->name, uap->namelen); + if (error == 0) { + error = kern_connectat(td, uap->fd, uap->s, sa); + free(sa, M_SONAME); + } + return (error); +} + int kern_socketpair(struct thread *td, int domain, int type, int protocol, int *rsv) @@ -749,7 +808,7 @@ kern_sendit(td, s, mp, flags, control, segflg) AUDIT_ARG_FD(s); rights = CAP_SEND; if (mp->msg_name != NULL) { - AUDIT_ARG_SOCKADDR(td, mp->msg_name); + AUDIT_ARG_SOCKADDR(td, AT_FDCWD, mp->msg_name); rights |= CAP_CONNECT; } error = getsock_cap(td->td_proc->p_fd, s, rights, &fp, NULL); @@ -997,7 +1056,7 @@ kern_recvit(td, s, mp, fromseg, controlp) error = 0; } if (fromsa != NULL) - AUDIT_ARG_SOCKADDR(td, fromsa); + AUDIT_ARG_SOCKADDR(td, AT_FDCWD, fromsa); #ifdef KTRACE if (ktruio != NULL) { ktruio->uio_resid = len - auio.uio_resid; diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index dcfd009d62a..1da80e0cedb 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$"); #include "opt_ddb.h" #include +#include #include #include #include /* XXX must be before */ @@ -271,6 +272,8 @@ static int uipc_connect2(struct socket *, struct socket *); static int uipc_ctloutput(struct socket *, struct sockopt *); static int unp_connect(struct socket *, struct sockaddr *, struct thread *); +static int unp_connectat(int, struct socket *, struct sockaddr *, + struct thread *); static int unp_connect2(struct socket *so, struct socket *so2, int); static void unp_disconnect(struct unpcb *unp, struct unpcb *unp2); static void unp_dispose(struct mbuf *); @@ -450,7 +453,7 @@ uipc_attach(struct socket *so, int proto, struct thread *td) } static int -uipc_bind(struct socket *so, struct sockaddr *nam, struct thread *td) +uipc_bindat(int fd, struct socket *so, struct sockaddr *nam, struct thread *td) { struct sockaddr_un *soun = (struct sockaddr_un *)nam; struct vattr vattr; @@ -496,8 +499,8 @@ uipc_bind(struct socket *so, struct sockaddr *nam, struct thread *td) buf[namelen] = 0; restart: - NDINIT(&nd, CREATE, NOFOLLOW | LOCKPARENT | SAVENAME, - UIO_SYSSPACE, buf, td); + NDINIT_ATRIGHTS(&nd, CREATE, NOFOLLOW | LOCKPARENT | SAVENAME, + UIO_SYSSPACE, buf, fd, CAP_BINDAT, td); /* SHOULD BE ABLE TO ADOPT EXISTING AND wakeup() ALA FIFO's */ error = namei(&nd); if (error) @@ -559,6 +562,13 @@ error: return (error); } +static int +uipc_bind(struct socket *so, struct sockaddr *nam, struct thread *td) +{ + + return (uipc_bindat(AT_FDCWD, so, nam, td)); +} + static int uipc_connect(struct socket *so, struct sockaddr *nam, struct thread *td) { @@ -571,6 +581,19 @@ uipc_connect(struct socket *so, struct sockaddr *nam, struct thread *td) return (error); } +static int +uipc_connectat(int fd, struct socket *so, struct sockaddr *nam, + struct thread *td) +{ + int error; + + KASSERT(td == curthread, ("uipc_connectat: td != curthread")); + UNP_LINK_WLOCK(); + error = unp_connectat(fd, so, nam, td); + UNP_LINK_WUNLOCK(); + return (error); +} + static void uipc_close(struct socket *so) { @@ -1081,7 +1104,9 @@ static struct pr_usrreqs uipc_usrreqs_dgram = { .pru_accept = uipc_accept, .pru_attach = uipc_attach, .pru_bind = uipc_bind, + .pru_bindat = uipc_bindat, .pru_connect = uipc_connect, + .pru_connectat = uipc_connectat, .pru_connect2 = uipc_connect2, .pru_detach = uipc_detach, .pru_disconnect = uipc_disconnect, @@ -1101,7 +1126,9 @@ static struct pr_usrreqs uipc_usrreqs_seqpacket = { .pru_accept = uipc_accept, .pru_attach = uipc_attach, .pru_bind = uipc_bind, + .pru_bindat = uipc_bindat, .pru_connect = uipc_connect, + .pru_connectat = uipc_connectat, .pru_connect2 = uipc_connect2, .pru_detach = uipc_detach, .pru_disconnect = uipc_disconnect, @@ -1121,7 +1148,9 @@ static struct pr_usrreqs uipc_usrreqs_stream = { .pru_accept = uipc_accept, .pru_attach = uipc_attach, .pru_bind = uipc_bind, + .pru_bindat = uipc_bindat, .pru_connect = uipc_connect, + .pru_connectat = uipc_connectat, .pru_connect2 = uipc_connect2, .pru_detach = uipc_detach, .pru_disconnect = uipc_disconnect, @@ -1232,6 +1261,14 @@ uipc_ctloutput(struct socket *so, struct sockopt *sopt) static int unp_connect(struct socket *so, struct sockaddr *nam, struct thread *td) +{ + + return (unp_connectat(AT_FDCWD, so, nam, td)); +} + +static int +unp_connectat(int fd, struct socket *so, struct sockaddr *nam, + struct thread *td) { struct sockaddr_un *soun = (struct sockaddr_un *)nam; struct vnode *vp; @@ -1265,8 +1302,8 @@ unp_connect(struct socket *so, struct sockaddr *nam, struct thread *td) UNP_PCB_UNLOCK(unp); sa = malloc(sizeof(struct sockaddr_un), M_SONAME, M_WAITOK); - NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF, - UIO_SYSSPACE, buf, td); + NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF, + UIO_SYSSPACE, buf, fd, CAP_CONNECTAT, td); error = namei(&nd); if (error) vp = NULL; diff --git a/sys/security/audit/audit.h b/sys/security/audit/audit.h index 733a3c79166..dd55875be5b 100644 --- a/sys/security/audit/audit.h +++ b/sys/security/audit/audit.h @@ -95,7 +95,7 @@ void audit_arg_pid(pid_t pid); void audit_arg_process(struct proc *p); void audit_arg_signum(u_int signum); void audit_arg_socket(int sodomain, int sotype, int soprotocol); -void audit_arg_sockaddr(struct thread *td, struct sockaddr *sa); +void audit_arg_sockaddr(struct thread *td, int dirfd, struct sockaddr *sa); void audit_arg_auid(uid_t auid); void audit_arg_auditinfo(struct auditinfo *au_info); void audit_arg_auditinfo_addr(struct auditinfo_addr *au_info); @@ -267,9 +267,9 @@ void audit_thread_free(struct thread *td); audit_arg_socket((sodomain), (sotype), (soprotocol)); \ } while (0) -#define AUDIT_ARG_SOCKADDR(td, sa) do { \ +#define AUDIT_ARG_SOCKADDR(td, dirfd, sa) do { \ if (AUDITING_TD(curthread)) \ - audit_arg_sockaddr((td), (sa)); \ + audit_arg_sockaddr((td), (dirfd), (sa)); \ } while (0) #define AUDIT_ARG_SUID(suid) do { \ @@ -365,7 +365,7 @@ void audit_thread_free(struct thread *td); #define AUDIT_ARG_SIGNUM(signum) #define AUDIT_ARG_SGID(sgid) #define AUDIT_ARG_SOCKET(sodomain, sotype, soprotocol) -#define AUDIT_ARG_SOCKADDR(td, sa) +#define AUDIT_ARG_SOCKADDR(td, dirfd, sa) #define AUDIT_ARG_SUID(suid) #define AUDIT_ARG_TEXT(text) #define AUDIT_ARG_UID(uid) diff --git a/sys/security/audit/audit_arg.c b/sys/security/audit/audit_arg.c index ec04b8bef7b..4927be0d134 100644 --- a/sys/security/audit/audit_arg.c +++ b/sys/security/audit/audit_arg.c @@ -441,7 +441,7 @@ audit_arg_socket(int sodomain, int sotype, int soprotocol) } void -audit_arg_sockaddr(struct thread *td, struct sockaddr *sa) +audit_arg_sockaddr(struct thread *td, int dirfd, struct sockaddr *sa) { struct kaudit_record *ar; @@ -463,7 +463,9 @@ audit_arg_sockaddr(struct thread *td, struct sockaddr *sa) break; case AF_UNIX: - audit_arg_upath1(td, AT_FDCWD, + if (dirfd != AT_FDCWD) + audit_arg_atfd1(dirfd); + audit_arg_upath1(td, dirfd, ((struct sockaddr_un *)sa)->sun_path); ARG_SET_VALID(ar, ARG_SADDRUNIX); break; diff --git a/sys/security/audit/audit_bsm.c b/sys/security/audit/audit_bsm.c index 9c69b1e040d..03b3c23e5c4 100644 --- a/sys/security/audit/audit_bsm.c +++ b/sys/security/audit/audit_bsm.c @@ -554,6 +554,21 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau) /* XXX Need to handle ARG_SADDRINET6 */ break; + case AUE_BINDAT: + case AUE_CONNECTAT: + ATFD1_TOKENS(1); + if (ARG_IS_VALID(kar, ARG_FD)) { + tok = au_to_arg32(2, "fd", ar->ar_arg_fd); + kau_write(rec, tok); + } + if (ARG_IS_VALID(kar, ARG_SADDRUNIX)) { + tok = au_to_sock_unix((struct sockaddr_un *) + &ar->ar_arg_sockaddr); + kau_write(rec, tok); + UPATH1_TOKENS; + } + break; + case AUE_SOCKET: case AUE_SOCKETPAIR: if (ARG_IS_VALID(kar, ARG_SOCKINFO)) { diff --git a/sys/sys/capability.h b/sys/sys/capability.h index 27e56c2952e..0d1ea5c16ac 100644 --- a/sys/sys/capability.h +++ b/sys/sys/capability.h @@ -182,13 +182,18 @@ #define CAP_PDWAIT 0x0020000000000000ULL #define CAP_PDKILL 0x0040000000000000ULL +/* + * Rights that allow to use bindat(2) and connectat(2) syscalls on a + * directory descriptor. + */ +#define CAP_BINDAT 0x0400000000000000ULL +#define CAP_CONNECTAT 0x0800000000000000ULL + /* The mask of all valid method rights. */ -#define CAP_MASK_VALID 0x03ffffffffffffffULL +#define CAP_MASK_VALID 0x0fffffffffffffffULL #define CAP_ALL CAP_MASK_VALID /* Available bits. */ -#define CAP_UNUSED5 0x0400000000000000ULL -#define CAP_UNUSED4 0x0800000000000000ULL #define CAP_UNUSED3 0x1000000000000000ULL #define CAP_UNUSED2 0x2000000000000000ULL #define CAP_UNUSED1 0x4000000000000000ULL diff --git a/sys/sys/protosw.h b/sys/sys/protosw.h index 78d6e069a05..8553bafdff1 100644 --- a/sys/sys/protosw.h +++ b/sys/sys/protosw.h @@ -223,6 +223,10 @@ struct pr_usrreqs { struct ucred *cred, struct thread *td); void (*pru_sosetlabel)(struct socket *so); void (*pru_close)(struct socket *so); + int (*pru_bindat)(int fd, struct socket *so, struct sockaddr *nam, + struct thread *td); + int (*pru_connectat)(int fd, struct socket *so, + struct sockaddr *nam, struct thread *td); }; /* @@ -232,8 +236,12 @@ int pru_accept_notsupp(struct socket *so, struct sockaddr **nam); int pru_attach_notsupp(struct socket *so, int proto, struct thread *td); int pru_bind_notsupp(struct socket *so, struct sockaddr *nam, struct thread *td); +int pru_bindat_notsupp(int fd, struct socket *so, struct sockaddr *nam, + struct thread *td); int pru_connect_notsupp(struct socket *so, struct sockaddr *nam, struct thread *td); +int pru_connectat_notsupp(int fd, struct socket *so, struct sockaddr *nam, + struct thread *td); int pru_connect2_notsupp(struct socket *so1, struct socket *so2); int pru_control_notsupp(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp, struct thread *td); diff --git a/sys/sys/socket.h b/sys/sys/socket.h index c29a689b591..632dae4bc88 100644 --- a/sys/sys/socket.h +++ b/sys/sys/socket.h @@ -620,7 +620,9 @@ struct sf_hdtr { __BEGIN_DECLS int accept(int, struct sockaddr * __restrict, socklen_t * __restrict); int bind(int, const struct sockaddr *, socklen_t); +int bindat(int, int, const struct sockaddr *, socklen_t); int connect(int, const struct sockaddr *, socklen_t); +int connectat(int, int, const struct sockaddr *, socklen_t); int getpeername(int, struct sockaddr * __restrict, socklen_t * __restrict); int getsockname(int, struct sockaddr * __restrict, socklen_t * __restrict); int getsockopt(int, int, int, void * __restrict, socklen_t * __restrict); diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h index 9012f24065e..77f31df336a 100644 --- a/sys/sys/socketvar.h +++ b/sys/sys/socketvar.h @@ -318,8 +318,12 @@ void soabort(struct socket *so); int soaccept(struct socket *so, struct sockaddr **nam); int socheckuid(struct socket *so, uid_t uid); int sobind(struct socket *so, struct sockaddr *nam, struct thread *td); +int sobindat(int fd, struct socket *so, struct sockaddr *nam, + struct thread *td); int soclose(struct socket *so); int soconnect(struct socket *so, struct sockaddr *nam, struct thread *td); +int soconnectat(int fd, struct socket *so, struct sockaddr *nam, + struct thread *td); int soconnect2(struct socket *so1, struct socket *so2); int socow_setup(struct mbuf *m0, struct uio *uio); int socreate(int dom, struct socket **aso, int type, int proto, diff --git a/usr.bin/procstat/procstat_files.c b/usr.bin/procstat/procstat_files.c index 030bba138f4..a3137db0852 100644 --- a/usr.bin/procstat/procstat_files.c +++ b/usr.bin/procstat/procstat_files.c @@ -215,6 +215,13 @@ static struct cap_desc { { CAP_PDWAIT, "pw" }, { CAP_PDKILL, "pk" }, + /* + * Rights that allow to use bindat(2) and connectat(2) syscalls on a + * directory descriptor. + */ + { CAP_BINDAT, "ba" }, + { CAP_CONNECTAT, "ca" }, + /* Aliases and defines that combine multiple rights. */ { CAP_PREAD, "prd" }, { CAP_PWRITE, "pwr" }, From 378a73d1bd1b9ae3e762511ac6a69f31b2e34e1c Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sat, 2 Mar 2013 21:12:54 +0000 Subject: [PATCH 0546/1476] Regen after r247667. --- sys/compat/freebsd32/freebsd32_proto.h | 2 +- sys/compat/freebsd32/freebsd32_syscall.h | 6 +- sys/compat/freebsd32/freebsd32_syscalls.c | 4 +- sys/compat/freebsd32/freebsd32_sysent.c | 4 +- .../freebsd32/freebsd32_systrace_args.c | 68 +++++++++++++++++++ sys/kern/init_sysent.c | 4 +- sys/kern/syscalls.c | 4 +- sys/kern/systrace_args.c | 68 +++++++++++++++++++ sys/sys/syscall.h | 6 +- sys/sys/syscall.mk | 6 +- sys/sys/sysproto.h | 18 ++++- 11 files changed, 178 insertions(+), 12 deletions(-) diff --git a/sys/compat/freebsd32/freebsd32_proto.h b/sys/compat/freebsd32/freebsd32_proto.h index 52156bd8f06..0e5d3f73c4e 100644 --- a/sys/compat/freebsd32/freebsd32_proto.h +++ b/sys/compat/freebsd32/freebsd32_proto.h @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 247602 2013-03-02 00:53:12Z pjd + * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 247667 2013-03-02 21:11:30Z pjd */ #ifndef _FREEBSD32_SYSPROTO_H_ diff --git a/sys/compat/freebsd32/freebsd32_syscall.h b/sys/compat/freebsd32/freebsd32_syscall.h index 4b689d35495..4f1549e5881 100644 --- a/sys/compat/freebsd32/freebsd32_syscall.h +++ b/sys/compat/freebsd32/freebsd32_syscall.h @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 247602 2013-03-02 00:53:12Z pjd + * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 247667 2013-03-02 21:11:30Z pjd */ #define FREEBSD32_SYS_syscall 0 @@ -435,4 +435,6 @@ #define FREEBSD32_SYS_cap_ioctls_get 535 #define FREEBSD32_SYS_cap_fcntls_limit 536 #define FREEBSD32_SYS_cap_fcntls_get 537 -#define FREEBSD32_SYS_MAXSYSCALL 538 +#define FREEBSD32_SYS_bindat 538 +#define FREEBSD32_SYS_connectat 539 +#define FREEBSD32_SYS_MAXSYSCALL 540 diff --git a/sys/compat/freebsd32/freebsd32_syscalls.c b/sys/compat/freebsd32/freebsd32_syscalls.c index 4878b20020a..0f7a7c32b58 100644 --- a/sys/compat/freebsd32/freebsd32_syscalls.c +++ b/sys/compat/freebsd32/freebsd32_syscalls.c @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 247602 2013-03-02 00:53:12Z pjd + * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 247667 2013-03-02 21:11:30Z pjd */ const char *freebsd32_syscallnames[] = { @@ -561,4 +561,6 @@ const char *freebsd32_syscallnames[] = { "cap_ioctls_get", /* 535 = cap_ioctls_get */ "cap_fcntls_limit", /* 536 = cap_fcntls_limit */ "cap_fcntls_get", /* 537 = cap_fcntls_get */ + "bindat", /* 538 = bindat */ + "connectat", /* 539 = connectat */ }; diff --git a/sys/compat/freebsd32/freebsd32_sysent.c b/sys/compat/freebsd32/freebsd32_sysent.c index 65da2c7612c..2a47edb9e9f 100644 --- a/sys/compat/freebsd32/freebsd32_sysent.c +++ b/sys/compat/freebsd32/freebsd32_sysent.c @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 247602 2013-03-02 00:53:12Z pjd + * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 247667 2013-03-02 21:11:30Z pjd */ #include "opt_compat.h" @@ -598,4 +598,6 @@ struct sysent freebsd32_sysent[] = { { AS(cap_ioctls_get_args), (sy_call_t *)sys_cap_ioctls_get, AUE_CAP_IOCTLS_GET, NULL, 0, 0, 0, SY_THR_STATIC }, /* 535 = cap_ioctls_get */ { AS(cap_fcntls_limit_args), (sy_call_t *)sys_cap_fcntls_limit, AUE_CAP_FCNTLS_LIMIT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 536 = cap_fcntls_limit */ { AS(cap_fcntls_get_args), (sy_call_t *)sys_cap_fcntls_get, AUE_CAP_FCNTLS_GET, NULL, 0, 0, 0, SY_THR_STATIC }, /* 537 = cap_fcntls_get */ + { AS(bindat_args), (sy_call_t *)sys_bindat, AUE_BINDAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 538 = bindat */ + { AS(connectat_args), (sy_call_t *)sys_connectat, AUE_CONNECTAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 539 = connectat */ }; diff --git a/sys/compat/freebsd32/freebsd32_systrace_args.c b/sys/compat/freebsd32/freebsd32_systrace_args.c index e2d7adb676e..d23974a86ad 100644 --- a/sys/compat/freebsd32/freebsd32_systrace_args.c +++ b/sys/compat/freebsd32/freebsd32_systrace_args.c @@ -3130,6 +3130,26 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args) *n_args = 2; break; } + /* bindat */ + case 538: { + struct bindat_args *p = params; + iarg[0] = p->fd; /* int */ + iarg[1] = p->s; /* int */ + uarg[2] = (intptr_t) p->name; /* caddr_t */ + iarg[3] = p->namelen; /* int */ + *n_args = 4; + break; + } + /* connectat */ + case 539: { + struct connectat_args *p = params; + iarg[0] = p->fd; /* int */ + iarg[1] = p->s; /* int */ + uarg[2] = (intptr_t) p->name; /* caddr_t */ + iarg[3] = p->namelen; /* int */ + *n_args = 4; + break; + } default: *n_args = 0; break; @@ -8356,6 +8376,44 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) break; }; break; + /* bindat */ + case 538: + switch(ndx) { + case 0: + p = "int"; + break; + case 1: + p = "int"; + break; + case 2: + p = "caddr_t"; + break; + case 3: + p = "int"; + break; + default: + break; + }; + break; + /* connectat */ + case 539: + switch(ndx) { + case 0: + p = "int"; + break; + case 1: + p = "int"; + break; + case 2: + p = "caddr_t"; + break; + case 3: + p = "int"; + break; + default: + break; + }; + break; default: break; }; @@ -10143,6 +10201,16 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) if (ndx == 0 || ndx == 1) p = "int"; break; + /* bindat */ + case 538: + if (ndx == 0 || ndx == 1) + p = "int"; + break; + /* connectat */ + case 539: + if (ndx == 0 || ndx == 1) + p = "int"; + break; default: break; }; diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c index b5ed57be6a7..e7041d20dc9 100644 --- a/sys/kern/init_sysent.c +++ b/sys/kern/init_sysent.c @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/kern/syscalls.master 247602 2013-03-02 00:53:12Z pjd + * created from FreeBSD: head/sys/kern/syscalls.master 247667 2013-03-02 21:11:30Z pjd */ #include "opt_compat.h" @@ -572,4 +572,6 @@ struct sysent sysent[] = { { AS(cap_ioctls_get_args), (sy_call_t *)sys_cap_ioctls_get, AUE_CAP_IOCTLS_GET, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 535 = cap_ioctls_get */ { AS(cap_fcntls_limit_args), (sy_call_t *)sys_cap_fcntls_limit, AUE_CAP_FCNTLS_LIMIT, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 536 = cap_fcntls_limit */ { AS(cap_fcntls_get_args), (sy_call_t *)sys_cap_fcntls_get, AUE_CAP_FCNTLS_GET, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 537 = cap_fcntls_get */ + { AS(bindat_args), (sy_call_t *)sys_bindat, AUE_BINDAT, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 538 = bindat */ + { AS(connectat_args), (sy_call_t *)sys_connectat, AUE_CONNECTAT, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 539 = connectat */ }; diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index e0660142a75..3b6a1113336 100644 --- a/sys/kern/syscalls.c +++ b/sys/kern/syscalls.c @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/kern/syscalls.master 247602 2013-03-02 00:53:12Z pjd + * created from FreeBSD: head/sys/kern/syscalls.master 247667 2013-03-02 21:11:30Z pjd */ const char *syscallnames[] = { @@ -545,4 +545,6 @@ const char *syscallnames[] = { "cap_ioctls_get", /* 535 = cap_ioctls_get */ "cap_fcntls_limit", /* 536 = cap_fcntls_limit */ "cap_fcntls_get", /* 537 = cap_fcntls_get */ + "bindat", /* 538 = bindat */ + "connectat", /* 539 = connectat */ }; diff --git a/sys/kern/systrace_args.c b/sys/kern/systrace_args.c index d811da2f346..0ff91efa191 100644 --- a/sys/kern/systrace_args.c +++ b/sys/kern/systrace_args.c @@ -3328,6 +3328,26 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args) *n_args = 2; break; } + /* bindat */ + case 538: { + struct bindat_args *p = params; + iarg[0] = p->fd; /* int */ + iarg[1] = p->s; /* int */ + uarg[2] = (intptr_t) p->name; /* caddr_t */ + iarg[3] = p->namelen; /* int */ + *n_args = 4; + break; + } + /* connectat */ + case 539: { + struct connectat_args *p = params; + iarg[0] = p->fd; /* int */ + iarg[1] = p->s; /* int */ + uarg[2] = (intptr_t) p->name; /* caddr_t */ + iarg[3] = p->namelen; /* int */ + *n_args = 4; + break; + } default: *n_args = 0; break; @@ -8858,6 +8878,44 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) break; }; break; + /* bindat */ + case 538: + switch(ndx) { + case 0: + p = "int"; + break; + case 1: + p = "int"; + break; + case 2: + p = "caddr_t"; + break; + case 3: + p = "int"; + break; + default: + break; + }; + break; + /* connectat */ + case 539: + switch(ndx) { + case 0: + p = "int"; + break; + case 1: + p = "int"; + break; + case 2: + p = "caddr_t"; + break; + case 3: + p = "int"; + break; + default: + break; + }; + break; default: break; }; @@ -10776,6 +10834,16 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) if (ndx == 0 || ndx == 1) p = "int"; break; + /* bindat */ + case 538: + if (ndx == 0 || ndx == 1) + p = "int"; + break; + /* connectat */ + case 539: + if (ndx == 0 || ndx == 1) + p = "int"; + break; default: break; }; diff --git a/sys/sys/syscall.h b/sys/sys/syscall.h index 5a2a1f6cf6e..4537d88d548 100644 --- a/sys/sys/syscall.h +++ b/sys/sys/syscall.h @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/kern/syscalls.master 247602 2013-03-02 00:53:12Z pjd + * created from FreeBSD: head/sys/kern/syscalls.master 247667 2013-03-02 21:11:30Z pjd */ #define SYS_syscall 0 @@ -457,4 +457,6 @@ #define SYS_cap_ioctls_get 535 #define SYS_cap_fcntls_limit 536 #define SYS_cap_fcntls_get 537 -#define SYS_MAXSYSCALL 538 +#define SYS_bindat 538 +#define SYS_connectat 539 +#define SYS_MAXSYSCALL 540 diff --git a/sys/sys/syscall.mk b/sys/sys/syscall.mk index 3e2a3d4f831..68334503b77 100644 --- a/sys/sys/syscall.mk +++ b/sys/sys/syscall.mk @@ -1,7 +1,7 @@ # FreeBSD system call names. # DO NOT EDIT-- this file is automatically generated. # $FreeBSD$ -# created from FreeBSD: head/sys/kern/syscalls.master 247602 2013-03-02 00:53:12Z pjd +# created from FreeBSD: head/sys/kern/syscalls.master 247667 2013-03-02 21:11:30Z pjd MIASM = \ syscall.o \ exit.o \ @@ -405,4 +405,6 @@ MIASM = \ cap_ioctls_limit.o \ cap_ioctls_get.o \ cap_fcntls_limit.o \ - cap_fcntls_get.o + cap_fcntls_get.o \ + bindat.o \ + connectat.o diff --git a/sys/sys/sysproto.h b/sys/sys/sysproto.h index 8ef408079b9..ff94b35ef35 100644 --- a/sys/sys/sysproto.h +++ b/sys/sys/sysproto.h @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: head/sys/kern/syscalls.master 247602 2013-03-02 00:53:12Z pjd + * created from FreeBSD: head/sys/kern/syscalls.master 247667 2013-03-02 21:11:30Z pjd */ #ifndef _SYS_SYSPROTO_H_ @@ -1784,6 +1784,18 @@ struct cap_fcntls_get_args { char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; char fcntlrightsp_l_[PADL_(uint32_t *)]; uint32_t * fcntlrightsp; char fcntlrightsp_r_[PADR_(uint32_t *)]; }; +struct bindat_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; + char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)]; + char name_l_[PADL_(caddr_t)]; caddr_t name; char name_r_[PADR_(caddr_t)]; + char namelen_l_[PADL_(int)]; int namelen; char namelen_r_[PADR_(int)]; +}; +struct connectat_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; + char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)]; + char name_l_[PADL_(caddr_t)]; caddr_t name; char name_r_[PADR_(caddr_t)]; + char namelen_l_[PADL_(int)]; int namelen; char namelen_r_[PADR_(int)]; +}; int nosys(struct thread *, struct nosys_args *); void sys_sys_exit(struct thread *, struct sys_exit_args *); int sys_fork(struct thread *, struct fork_args *); @@ -2171,6 +2183,8 @@ int sys_cap_ioctls_limit(struct thread *, struct cap_ioctls_limit_args *); int sys_cap_ioctls_get(struct thread *, struct cap_ioctls_get_args *); int sys_cap_fcntls_limit(struct thread *, struct cap_fcntls_limit_args *); int sys_cap_fcntls_get(struct thread *, struct cap_fcntls_get_args *); +int sys_bindat(struct thread *, struct bindat_args *); +int sys_connectat(struct thread *, struct connectat_args *); #ifdef COMPAT_43 @@ -2872,6 +2886,8 @@ int freebsd7_shmctl(struct thread *, struct freebsd7_shmctl_args *); #define SYS_AUE_cap_ioctls_get AUE_CAP_IOCTLS_GET #define SYS_AUE_cap_fcntls_limit AUE_CAP_FCNTLS_LIMIT #define SYS_AUE_cap_fcntls_get AUE_CAP_FCNTLS_GET +#define SYS_AUE_bindat AUE_BINDAT +#define SYS_AUE_connectat AUE_CONNECTAT #undef PAD_ #undef PADL_ From 7099ae5f3d3188ac25191dd580125f4dcff26d7e Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sat, 2 Mar 2013 21:16:40 +0000 Subject: [PATCH 0547/1476] Add support for bindat(2) and connectat(2). Sponsored by: The FreeBSD Foundation --- tools/regression/pjdfstest/Makefile | 2 +- tools/regression/pjdfstest/pjdfstest.c | 44 ++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/tools/regression/pjdfstest/Makefile b/tools/regression/pjdfstest/Makefile index ca789fe80b2..eec813ac58c 100644 --- a/tools/regression/pjdfstest/Makefile +++ b/tools/regression/pjdfstest/Makefile @@ -6,7 +6,7 @@ ${PROG}: ${PROG}.c @OSTYPE=`uname`; \ CFLAGS=-D__OS_$${OSTYPE}__; \ if [ $$OSTYPE = "FreeBSD" ]; then \ - CFLAGS="$$CFLAGS -DHAS_LCHMOD -DHAS_CHFLAGS -DHAS_FCHFLAGS -DHAS_LCHFLAGS -DHAS_FREEBSD_ACL"; \ + CFLAGS="$$CFLAGS -DHAS_LCHMOD -DHAS_CHFLAGS -DHAS_FCHFLAGS -DHAS_LCHFLAGS -DHAS_FREEBSD_ACL -DHAS_BINDAT -DHAS_CONNECTAT"; \ elif [ $$OSTYPE = "SunOS" ]; then \ CFLAGS="$$CFLAGS -DHAS_TRUNCATE64 -DHAS_STAT64"; \ CFLAGS="$$CFLAGS -lsocket"; \ diff --git a/tools/regression/pjdfstest/pjdfstest.c b/tools/regression/pjdfstest/pjdfstest.c index c08fafdfdfd..6eafc8c7204 100644 --- a/tools/regression/pjdfstest/pjdfstest.c +++ b/tools/regression/pjdfstest/pjdfstest.c @@ -82,7 +82,13 @@ enum action { ACTION_MKNOD, ACTION_MKNODAT, ACTION_BIND, +#ifdef HAS_BINDAT + ACTION_BINDAT, +#endif ACTION_CONNECT, +#ifdef HAS_CONNECTAT + ACTION_CONNECTAT, +#endif ACTION_CHMOD, ACTION_FCHMOD, #ifdef HAS_LCHMOD @@ -154,7 +160,13 @@ static struct syscall_desc syscalls[] = { { "mknod", ACTION_MKNOD, { TYPE_STRING, TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE} }, { "mknodat", ACTION_MKNODAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE} }, { "bind", ACTION_BIND, { TYPE_STRING, TYPE_NONE } }, +#ifdef HAS_BINDAT + { "bindat", ACTION_BINDAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } }, +#endif { "connect", ACTION_CONNECT, { TYPE_STRING, TYPE_NONE } }, +#ifdef HAS_CONNECTAT + { "connectat", ACTION_CONNECTAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } }, +#endif { "chmod", ACTION_CHMOD, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } }, { "fchmod", ACTION_FCHMOD, { TYPE_DESCRIPTOR, TYPE_NUMBER, TYPE_NONE } }, #ifdef HAS_LCHMOD @@ -732,6 +744,22 @@ call_syscall(struct syscall_desc *scall, char *argv[]) rval = bind(rval, (struct sockaddr *)&sunx, sizeof(sunx)); break; } +#ifdef HAS_BINDAT + case ACTION_BINDAT: + { + struct sockaddr_un sunx; + + sunx.sun_family = AF_UNIX; + strncpy(sunx.sun_path, STR(1), sizeof(sunx.sun_path) - 1); + sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0'; + rval = socket(AF_UNIX, SOCK_STREAM, 0); + if (rval < 0) + break; + rval = bindat(NUM(0), rval, (struct sockaddr *)&sunx, + sizeof(sunx)); + break; + } +#endif case ACTION_CONNECT: { struct sockaddr_un sunx; @@ -745,6 +773,22 @@ call_syscall(struct syscall_desc *scall, char *argv[]) rval = connect(rval, (struct sockaddr *)&sunx, sizeof(sunx)); break; } +#ifdef HAS_CONNECTAT + case ACTION_CONNECTAT: + { + struct sockaddr_un sunx; + + sunx.sun_family = AF_UNIX; + strncpy(sunx.sun_path, STR(1), sizeof(sunx.sun_path) - 1); + sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0'; + rval = socket(AF_UNIX, SOCK_STREAM, 0); + if (rval < 0) + break; + rval = connectat(NUM(0), rval, (struct sockaddr *)&sunx, + sizeof(sunx)); + break; + } +#endif case ACTION_CHMOD: rval = chmod(STR(0), (mode_t)NUM(1)); break; From d4d29475e68a1aecf27956ca37a2ba96ff3b211f Mon Sep 17 00:00:00 2001 From: Alexander Motin Date: Sat, 2 Mar 2013 22:19:17 +0000 Subject: [PATCH 0548/1476] MFcalloutng: Give OFED Linux wrapper own "expires" field instead of abusing callout's c_time, which will change its type and units with calloutng commit. --- sys/ofed/include/linux/timer.h | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/sys/ofed/include/linux/timer.h b/sys/ofed/include/linux/timer.h index ed4ed4a5627..3a32131c24a 100644 --- a/sys/ofed/include/linux/timer.h +++ b/sys/ofed/include/linux/timer.h @@ -37,11 +37,10 @@ struct timer_list { struct callout timer_callout; void (*function)(unsigned long); - unsigned long data; + unsigned long data; + unsigned long expires; }; -#define expires timer_callout.c_time - static inline void _timer_fn(void *context) { @@ -65,13 +64,16 @@ do { \ callout_init(&(timer)->timer_callout, CALLOUT_MPSAFE); \ } while (0) -#define mod_timer(timer, expire) \ - callout_reset(&(timer)->timer_callout, (expire) - jiffies, \ - _timer_fn, (timer)) +#define mod_timer(timer, exp) \ +do { \ + (timer)->expires = exp; \ + callout_reset(&(timer)->timer_callout, (exp) - jiffies, \ + _timer_fn, (timer)); \ +} while (0) #define add_timer(timer) \ callout_reset(&(timer)->timer_callout, \ - (timer)->timer_callout.c_time - jiffies, _timer_fn, (timer)) + (timer)->expires - jiffies, _timer_fn, (timer)) #define del_timer(timer) callout_stop(&(timer)->timer_callout) #define del_timer_sync(timer) callout_drain(&(timer)->timer_callout) From 25e533d3e57cb6f0c2f4c2b41f188dcdce7d59b5 Mon Sep 17 00:00:00 2001 From: Alexander Motin Date: Sat, 2 Mar 2013 22:28:20 +0000 Subject: [PATCH 0549/1476] Polish few spaces/tabs. --- sys/sys/time.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/sys/time.h b/sys/sys/time.h index 555c37ef5cf..a735ad80f7d 100644 --- a/sys/sys/time.h +++ b/sys/sys/time.h @@ -113,7 +113,7 @@ bintime_mul(struct bintime *bt, u_int x) #define SBT_1M (SBT_1S * 60) #define SBT_1MS (SBT_1S / 1000) #define SBT_1US (SBT_1S / 1000000) -#define SBT_1NS (SBT_1S / 1000000000) +#define SBT_1NS (SBT_1S / 1000000000) static __inline int sbintime_getsec(sbintime_t sbt) @@ -133,7 +133,7 @@ static __inline struct bintime sbttobt(sbintime_t sbt) { struct bintime bt; - + bt.sec = sbt >> 32; bt.frac = sbt << 32; return (bt); From 27eae7e9ad39739ed37a68299bbc5b2b9c4e9931 Mon Sep 17 00:00:00 2001 From: Alexander Motin Date: Sat, 2 Mar 2013 22:41:06 +0000 Subject: [PATCH 0550/1476] Add protective parentheses for macro argument, missed in r247671. --- sys/ofed/include/linux/timer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/ofed/include/linux/timer.h b/sys/ofed/include/linux/timer.h index 3a32131c24a..a497334d8e3 100644 --- a/sys/ofed/include/linux/timer.h +++ b/sys/ofed/include/linux/timer.h @@ -66,7 +66,7 @@ do { \ #define mod_timer(timer, exp) \ do { \ - (timer)->expires = exp; \ + (timer)->expires = (exp); \ callout_reset(&(timer)->timer_callout, (exp) - jiffies, \ _timer_fn, (timer)); \ } while (0) From 2328a74aa866010025fb4faa3cb53d174e610e48 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sat, 2 Mar 2013 23:40:42 +0000 Subject: [PATCH 0551/1476] If all ioctls are allowed, cap_ioctls_get(2) will return CAP_IOCTLS_ALL. Update regression tests. --- tools/regression/capsicum/syscalls/cap_ioctls_limit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/regression/capsicum/syscalls/cap_ioctls_limit.c b/tools/regression/capsicum/syscalls/cap_ioctls_limit.c index 3a08fac4ac7..753aa7158c7 100644 --- a/tools/regression/capsicum/syscalls/cap_ioctls_limit.c +++ b/tools/regression/capsicum/syscalls/cap_ioctls_limit.c @@ -51,7 +51,7 @@ ioctl_tests_0(int fd) { unsigned long cmds[2]; - CHECK(cap_ioctls_get(fd, NULL, 0) == INT_MAX); + CHECK(cap_ioctls_get(fd, NULL, 0) == CAP_IOCTLS_ALL); CHECK(fcntl(fd, F_GETFD) == 0); CHECK(ioctl(fd, FIOCLEX) == 0); @@ -241,7 +241,7 @@ ioctl_tests_recv_0(int sock) CHECK(descriptor_recv(sock, &fd) == 0); - CHECK(cap_ioctls_get(fd, NULL, 0) == INT_MAX); + CHECK(cap_ioctls_get(fd, NULL, 0) == CAP_IOCTLS_ALL); CHECK(fcntl(fd, F_GETFD) == 0); CHECK(ioctl(fd, FIOCLEX) == 0); From 03e78eac37e2765a9f2994ee296560fc6118370e Mon Sep 17 00:00:00 2001 From: Attilio Rao Date: Sun, 3 Mar 2013 01:02:57 +0000 Subject: [PATCH 0552/1476] Fix-up r247622 by also renaming pv_list iterator into the xen pmap verbatim copy. Sponsored by: EMC / Isilon storage division Reported by: tinderbox --- sys/i386/xen/pmap.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/sys/i386/xen/pmap.c b/sys/i386/xen/pmap.c index 4989e07e7ef..74a3be75979 100644 --- a/sys/i386/xen/pmap.c +++ b/sys/i386/xen/pmap.c @@ -2038,7 +2038,7 @@ pmap_pv_reclaim(pmap_t locked_pmap) vm_page_dirty(m); if ((tpte & PG_A) != 0) vm_page_aflag_set(m, PGA_REFERENCED); - TAILQ_REMOVE(&m->md.pv_list, pv, pv_list); + TAILQ_REMOVE(&m->md.pv_list, pv, pv_next); if (TAILQ_EMPTY(&m->md.pv_list)) vm_page_aflag_clear(m, PGA_WRITEABLE); pc->pc_map[field] |= 1UL << bit; @@ -2239,9 +2239,9 @@ pmap_pvh_remove(struct md_page *pvh, pmap_t pmap, vm_offset_t va) pv_entry_t pv; rw_assert(&pvh_global_lock, RA_WLOCKED); - TAILQ_FOREACH(pv, &pvh->pv_list, pv_list) { + TAILQ_FOREACH(pv, &pvh->pv_list, pv_next) { if (pmap == PV_PMAP(pv) && va == pv->pv_va) { - TAILQ_REMOVE(&pvh->pv_list, pv, pv_list); + TAILQ_REMOVE(&pvh->pv_list, pv, pv_next); break; } } @@ -2281,7 +2281,7 @@ pmap_try_insert_pv_entry(pmap_t pmap, vm_offset_t va, vm_page_t m) if (pv_entry_count < pv_entry_high_water && (pv = get_pv_entry(pmap, TRUE)) != NULL) { pv->pv_va = va; - TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_list); + TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next); return (TRUE); } else return (FALSE); @@ -2503,7 +2503,7 @@ pmap_remove_all(vm_page_t m) vm_page_dirty(m); pmap_unuse_pt(pmap, pv->pv_va, &free); pmap_invalidate_page(pmap, pv->pv_va); - TAILQ_REMOVE(&m->md.pv_list, pv, pv_list); + TAILQ_REMOVE(&m->md.pv_list, pv, pv_next); free_pv_entry(pmap, pv); PMAP_UNLOCK(pmap); } @@ -2770,7 +2770,7 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_prot_t access, vm_page_t m, if (pv == NULL) pv = get_pv_entry(pmap, FALSE); pv->pv_va = va; - TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_list); + TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next); pa |= PG_MANAGED; } else if (pv != NULL) free_pv_entry(pmap, pv); @@ -3465,7 +3465,7 @@ pmap_page_exists_quick(pmap_t pmap, vm_page_t m) ("pmap_page_exists_quick: page %p is not managed", m)); rv = FALSE; rw_wlock(&pvh_global_lock); - TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) { + TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) { if (PV_PMAP(pv) == pmap) { rv = TRUE; break; @@ -3497,7 +3497,7 @@ pmap_page_wired_mappings(vm_page_t m) return (count); rw_wlock(&pvh_global_lock); sched_pin(); - TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) { + TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) { pmap = PV_PMAP(pv); PMAP_LOCK(pmap); pte = pmap_pte_quick(pmap, pv->pv_va); @@ -3602,7 +3602,7 @@ pmap_remove_pages(pmap_t pmap) if (tpte & PG_M) vm_page_dirty(m); - TAILQ_REMOVE(&m->md.pv_list, pv, pv_list); + TAILQ_REMOVE(&m->md.pv_list, pv, pv_next); if (TAILQ_EMPTY(&m->md.pv_list)) vm_page_aflag_clear(m, PGA_WRITEABLE); @@ -3662,7 +3662,7 @@ pmap_is_modified(vm_page_t m) return (rv); rw_wlock(&pvh_global_lock); sched_pin(); - TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) { + TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) { pmap = PV_PMAP(pv); PMAP_LOCK(pmap); pte = pmap_pte_quick(pmap, pv->pv_va); @@ -3723,7 +3723,7 @@ pmap_is_referenced(vm_page_t m) rv = FALSE; rw_wlock(&pvh_global_lock); sched_pin(); - TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) { + TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) { pmap = PV_PMAP(pv); PMAP_LOCK(pmap); pte = pmap_pte_quick(pmap, pv->pv_va); @@ -3793,7 +3793,7 @@ pmap_remove_write(vm_page_t m) return; rw_wlock(&pvh_global_lock); sched_pin(); - TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) { + TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) { pmap = PV_PMAP(pv); PMAP_LOCK(pmap); pte = pmap_pte_quick(pmap, pv->pv_va); @@ -3852,9 +3852,9 @@ pmap_ts_referenced(vm_page_t m) if ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) { pvf = pv; do { - pvn = TAILQ_NEXT(pv, pv_list); - TAILQ_REMOVE(&m->md.pv_list, pv, pv_list); - TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_list); + pvn = TAILQ_NEXT(pv, pv_next); + TAILQ_REMOVE(&m->md.pv_list, pv, pv_next); + TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next); pmap = PV_PMAP(pv); PMAP_LOCK(pmap); pte = pmap_pte_quick(pmap, pv->pv_va); @@ -3901,7 +3901,7 @@ pmap_clear_modify(vm_page_t m) return; rw_wlock(&pvh_global_lock); sched_pin(); - TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) { + TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) { pmap = PV_PMAP(pv); PMAP_LOCK(pmap); pte = pmap_pte_quick(pmap, pv->pv_va); @@ -3936,7 +3936,7 @@ pmap_clear_reference(vm_page_t m) ("pmap_clear_reference: page %p is not managed", m)); rw_wlock(&pvh_global_lock); sched_pin(); - TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) { + TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) { pmap = PV_PMAP(pv); PMAP_LOCK(pmap); pte = pmap_pte_quick(pmap, pv->pv_va); @@ -4418,7 +4418,7 @@ pmap_pvdump(vm_paddr_t pa) printf("pa %x", pa); m = PHYS_TO_VM_PAGE(pa); - TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) { + TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) { pmap = PV_PMAP(pv); printf(" -> pmap %p, va %x", (void *)pmap, pv->pv_va); pads(pmap); From 0b62a022698b0d2d0d4ed87d53238c2cecd73831 Mon Sep 17 00:00:00 2001 From: "Pedro F. Giffuni" Date: Sun, 3 Mar 2013 02:11:03 +0000 Subject: [PATCH 0553/1476] libedit does not need to be linked with ncurses libedit uses the terminfo headers but doesn't really need to be linked with ncurses. Discussed with: christos@NetBSD MFC after; 3 days --- lib/libedit/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/libedit/Makefile b/lib/libedit/Makefile index d8ae6468196..1c6e52c3816 100644 --- a/lib/libedit/Makefile +++ b/lib/libedit/Makefile @@ -11,7 +11,6 @@ OSRCS= chared.c common.c el.c emacs.c fcns.c filecomplete.c help.c \ parse.c prompt.c read.c refresh.c search.c sig.c term.c tty.c vi.c DPADD= ${LIBNCURSES} -LDADD= -lncurses MAN= editline.3 editrc.5 From e0dffa2de2d1a19bdf5848f4d1d1b6116771a178 Mon Sep 17 00:00:00 2001 From: Rui Paulo Date: Sun, 3 Mar 2013 06:42:36 +0000 Subject: [PATCH 0554/1476] Remove the extra parenthesis from the cv_init() macro. They are not necessary because we already use parenthesis in zfs_cv_init(). This fixes a long standing bug where there would be an extra ")" at the end of the string. This extra parenthesis would show up in the WCHAN of the process (top, stty status, etc.). --- sys/cddl/compat/opensolaris/sys/kcondvar.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/cddl/compat/opensolaris/sys/kcondvar.h b/sys/cddl/compat/opensolaris/sys/kcondvar.h index 0422ba0791c..7c6884249a5 100644 --- a/sys/cddl/compat/opensolaris/sys/kcondvar.h +++ b/sys/cddl/compat/opensolaris/sys/kcondvar.h @@ -55,7 +55,7 @@ typedef enum { _name = #cv; \ cv_init((cv), _name); \ } while (0) -#define cv_init(cv, name, type, arg) zfs_cv_init((cv), (name), (type), (arg)) +#define cv_init(cv, name, type, arg) zfs_cv_init(cv, name, type, arg) #endif /* _KERNEL */ From 4514d6fa1897929d8dc9c4cfdf8895d83fbb5f57 Mon Sep 17 00:00:00 2001 From: Alexander Motin Date: Sun, 3 Mar 2013 09:11:24 +0000 Subject: [PATCH 0555/1476] MFcalloutng: Some whitespace fixes. --- sys/kern/kern_timeout.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/kern/kern_timeout.c b/sys/kern/kern_timeout.c index 9cdc39b3809..69851e66e54 100644 --- a/sys/kern/kern_timeout.c +++ b/sys/kern/kern_timeout.c @@ -205,7 +205,7 @@ cc_cme_migrating(struct callout_cpu *cc) } /* - * kern_timeout_callwheel_alloc() - kernel low level callwheel initialization + * kern_timeout_callwheel_alloc() - kernel low level callwheel initialization * * This code is called very early in the kernel initialization sequence, * and may be called more then once. @@ -704,7 +704,7 @@ softclock(void *arg) * Initialize a handle so that using it with untimeout is benign. * * See AT&T BCI Driver Reference Manual for specification. This - * implementation differs from that one in that although an + * implementation differs from that one in that although an * identification value is returned from timeout, the original * arguments to timeout as well as the identifier are used to * identify entries for untimeout. From b771592d97724360696be8019ad64149857ad59e Mon Sep 17 00:00:00 2001 From: Josh Paetzel Date: Sun, 3 Mar 2013 09:47:47 +0000 Subject: [PATCH 0556/1476] Fix a bug extracting files from dist scheme Obtained from: PC-BSD --- .../backend/functions-extractimage.sh | 141 +++++++++++++++--- .../pc-sysinstall/backend/functions-parse.sh | 2 +- usr.sbin/pc-sysinstall/backend/parseconfig.sh | 2 +- usr.sbin/pc-sysinstall/examples/README | 11 +- 4 files changed, 131 insertions(+), 25 deletions(-) diff --git a/usr.sbin/pc-sysinstall/backend/functions-extractimage.sh b/usr.sbin/pc-sysinstall/backend/functions-extractimage.sh index 5d32466e6a5..fd6556d7fc1 100755 --- a/usr.sbin/pc-sysinstall/backend/functions-extractimage.sh +++ b/usr.sbin/pc-sysinstall/backend/functions-extractimage.sh @@ -29,23 +29,60 @@ . ${BACKEND}/functions-mountoptical.sh +# Performs the extraction of data to disk from FreeBSD dist files +start_extract_dist() +{ + if [ -z "$1" ] ; then exit_err "Called dist extraction with no directory set!"; fi + if [ -z "$INSFILE" ]; then exit_err "Called extraction with no install file set!"; fi + local DDIR="$1" + + # Check if we are doing an upgrade, and if so use our exclude list + if [ "${INSTALLMODE}" = "upgrade" ]; then + TAROPTS="-X ${PROGDIR}/conf/exclude-from-upgrade" + else + TAROPTS="" + fi + + # Loop though and extract dist files + for di in $INSFILE + do + # Check the MANIFEST see if we have an archive size / count + if [ -e "${DDIR}/MANIFEST" ]; then + count=`grep "^${di}.txz" ${DDIR}/MANIFEST | awk '{print $3}'` + if [ ! -z "$count" ] ; then + echo "INSTALLCOUNT: $count" + fi + fi + echo_log "pc-sysinstall: Starting Extraction (${di})" + tar -xpv -C ${FSMNT} -f ${DDIR}/${di}.txz ${TAROPTS} >&1 2>&1 + if [ $? -ne 0 ]; then + exit_err "ERROR: Failed extracting the dist file: $di" + fi + done + + # Check if this was a FTP download and clean it up now + if [ "${INSTALLMEDIUM}" = "ftp" ]; then + echo_log "Cleaning up downloaded archives" + rm -rf ${DDIR} + fi + + echo_log "pc-sysinstall: Extraction Finished" +} + # Performs the extraction of data to disk from a uzip or tar archive start_extract_uzip_tar() { - if [ -z "$INSFILE" ] - then + if [ -z "$INSFILE" ]; then exit_err "ERROR: Called extraction with no install file set!" fi # Check if we have a .count file, and echo it out for a front-end to use in progress bars - if [ -e "${INSFILE}.count" ] - then + if [ -e "${INSFILE}.count" ]; then echo "INSTALLCOUNT: `cat ${INSFILE}.count`" fi # Check if we are doing an upgrade, and if so use our exclude list - if [ "${INSTALLMODE}" = "upgrade" ] - then + if [ "${INSTALLMODE}" = "upgrade" ]; then TAROPTS="-X ${PROGDIR}/conf/exclude-from-upgrade" else TAROPTS="" @@ -87,9 +124,8 @@ start_extract_uzip_tar() mdconfig -d -u ${MDDEVICE} ;; tar) - tar -xpv -C ${FSMNT} -f ${INSFILE} ${TAROPTS} >&1 2>&1 - if [ $? -ne 0 ] - then + tar -xpv -C ${FSMNT} -f ${INSFILE} ${TAROPTS} >&1 2>&1 + if [ $? -ne 0 ]; then exit_err "ERROR: Failed extracting the tar image" fi ;; @@ -176,6 +212,38 @@ start_extract_split() echo_log "pc-sysinstall: Extraction Finished" }; +# Function which will attempt to fetch the dist file(s) before we start +fetch_dist_file() +{ + get_value_from_cfg ftpPath + if [ -z "$VAL" ] + then + exit_err "ERROR: Install medium was set to ftp, but no ftpPath was provided!" + fi + + FTPPATH="${VAL}" + + # Check if we have a /usr partition to save the download + if [ -d "${FSMNT}/usr" ] + then + DLDIR="${FSMNT}/usr/.fetch.$$" + else + DLDIR="${FSMNT}/.fetch.$$" + fi + mkdir -p ${DLDIR} + + # Do the fetch of the dist archive(s) now + for di in $INSFILE + do + fetch_file "${FTPPATH}/${di}.txz" "${DLDIR}/${di}.txz" "1" + done + + # Check to see if there is a MANIFEST file for this install + fetch_file "${FTPPATH}/MANIFEST" "${DLDIR}/MANIFEST" "0" + + export DLDIR +}; + # Function which will attempt to fetch the install file before we start # the install fetch_install_file() @@ -390,6 +458,13 @@ init_extraction() case $PACKAGETYPE in uzip) INSFILE="${FBSD_UZIP_FILE}" ;; tar) INSFILE="${FBSD_TAR_FILE}" ;; + dist) + get_value_from_cfg_with_spaces distFiles + if [ -z "$VAL" ] ; then + exit_err "No dist files specified!" + fi + INSFILE="${VAL}" + ;; split) INSDIR="${FBSD_BRANCH_DIR}" @@ -401,6 +476,13 @@ init_extraction() case $PACKAGETYPE in uzip) INSFILE="${UZIP_FILE}" ;; tar) INSFILE="${TAR_FILE}" ;; + dist) + get_value_from_cfg_with_spaces distFiles + if [ -z "$VAL" ] ; then + exit_err "No dist files specified!" + fi + INSFILE="${VAL}" + ;; esac fi export INSFILE @@ -417,22 +499,32 @@ init_extraction() start_extract_split else - INSFILE="${CDMNT}/${INSFILE}" ; export INSFILE - start_extract_uzip_tar + if [ "$PACKAGETYPE" = "dist" ] ; then + start_extract_dist "${CDMNT}/usr/freebsd-dist" + else + INSFILE="${CDMNT}/${INSFILE}" ; export INSFILE + start_extract_uzip_tar + fi fi ;; ftp) - if [ "$PACKAGETYPE" = "split" ] - then - fetch_split_files + case $PACKAGETYPE in + split) + fetch_split_files - INSDIR="${INSFILE}" ; export INSDIR - start_extract_split - else - fetch_install_file - start_extract_uzip_tar - fi + INSDIR="${INSFILE}" ; export INSDIR + start_extract_split + ;; + dist) + fetch_dist_file + start_extract_dist "$DLDIR" + ;; + *) + fetch_install_file + start_extract_uzip_tar + ;; + esac ;; sftp) ;; @@ -446,8 +538,13 @@ init_extraction() exit_err "Install medium was set to local, but no localPath was provided!" fi LOCALPATH=$VAL - INSFILE="${LOCALPATH}/${INSFILE}" ; export INSFILE - start_extract_uzip_tar + if [ "$PACKAGETYPE" = "dist" ] ; then + INSFILE="${INSFILE}" ; export INSFILE + start_extract_dist "$LOCALPATH" + else + INSFILE="${LOCALPATH}/${INSFILE}" ; export INSFILE + start_extract_uzip_tar + fi ;; *) exit_err "ERROR: Unknown install medium" ;; esac diff --git a/usr.sbin/pc-sysinstall/backend/functions-parse.sh b/usr.sbin/pc-sysinstall/backend/functions-parse.sh index ed0a3e681a6..fb7cdd2e57f 100755 --- a/usr.sbin/pc-sysinstall/backend/functions-parse.sh +++ b/usr.sbin/pc-sysinstall/backend/functions-parse.sh @@ -45,7 +45,7 @@ get_value_from_cfg_with_spaces() { if [ -n "${1}" ] then - export VAL=`grep "^${1}=" ${CFGF} | head -n 1 | cut -d '=' -f 2-` + export VAL="`grep ^${1}= ${CFGF} | head -n 1 | cut -d '=' -f 2-`" else exit_err "Error: Did we forgot to supply a setting to grab?" fi diff --git a/usr.sbin/pc-sysinstall/backend/parseconfig.sh b/usr.sbin/pc-sysinstall/backend/parseconfig.sh index c852cea74f2..f3d89fc7cb5 100755 --- a/usr.sbin/pc-sysinstall/backend/parseconfig.sh +++ b/usr.sbin/pc-sysinstall/backend/parseconfig.sh @@ -69,7 +69,7 @@ file_sanity_check "installMode installType installMedium packageType" check_value installMode "fresh upgrade extract" check_value installType "PCBSD FreeBSD" check_value installMedium "dvd usb ftp rsync image local" -check_value packageType "uzip tar rsync split" +check_value packageType "uzip tar rsync split dist" if_check_value_exists mirrorbal "load prefer round-robin split" # We passed all sanity checks! Yay, lets start the install diff --git a/usr.sbin/pc-sysinstall/examples/README b/usr.sbin/pc-sysinstall/examples/README index cc269a22978..1e8d32d4359 100644 --- a/usr.sbin/pc-sysinstall/examples/README +++ b/usr.sbin/pc-sysinstall/examples/README @@ -243,11 +243,16 @@ Set installMedium= to the source type we will be using for this install. Available Types: dvd - Search for and mount the DVD which contains the install archive +local - Pull files directly from a local directory usb - Search for and mount the USB drive which contains the install archive ftp - The install archive will be fetched from a FTP / HTTP server before install rsync - Pull the system data from a ssh + rsync server, specified with variables below image - Install system from an image +# localPath=/usr/freebsd-dist + +Location of the directory we will be pulling installation files from + # installType=(PCBSD, FreeBSD) Set the type of system we are installing, PCBSD or FreeBSD @@ -256,10 +261,14 @@ Set the type of system we are installing, PCBSD or FreeBSD The installer archive, if not using the defaults specified in conf/pc-sysinstall.conf -# packageType=(tar, uzip, split) +# packageType=(tar, uzip, split, dist) The archive type we are extracting from when using dvd, usb or ftp +# distFiles=base src kernel + +List of dist files to install when packageType=dist + # ftpPath=ftp://ftp.pcbsd.org/pub/8.0/netinstall Location of the installer archive when using a installMedium=ftp From ae6c506346ad76d7c4482b5e69a4e1134a4a4593 Mon Sep 17 00:00:00 2001 From: Antoine Brodin Date: Sun, 3 Mar 2013 11:09:55 +0000 Subject: [PATCH 0557/1476] Add more obsolete files. --- ObsoleteFiles.inc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index 068882d74d7..cfa085f9a5d 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -39,6 +39,8 @@ # done # 20130302: NTFS support removed +OLD_FILES+=rescue/mount_ntfs +OLD_FILES+=sbin/mount_ntfs OLD_FILES+=usr/include/fs/ntfs/ntfs.h OLD_FILES+=usr/include/fs/ntfs/ntfs_compr.h OLD_FILES+=usr/include/fs/ntfs/ntfs_ihash.h @@ -51,6 +53,7 @@ OLD_FILES+=usr/share/man/man8/mount_ntfs.8.gz # 20130302: PORTALFS support removed OLD_FILES+=usr/include/fs/portalfs/portal.h OLD_DIRS+=usr/include/fs/portalfs +OLD_FILES+=usr/sbin/mount_portalfs OLD_FILES+=usr/share/examples/portal/README OLD_FILES+=usr/share/examples/portal/portal.conf OLD_DIRS+=usr/share/examples/portal @@ -79,9 +82,10 @@ OLD_DIRS+=var/remote # 20121114: zpool-features manual page moved from section 5 to 7 OLD_FILES+=usr/share/man/man5/zpool-features.5.gz # 20121022: remove harp, hfa and idt man page -OLD_FILES+=share/man/man4/harp.4 -OLD_FILES+=share/man/man4/hfa.4 -OLD_FILES+=share/man/man4/idt.4 +OLD_FILES+=usr/share/man/man4/harp.4.gz +OLD_FILES+=usr/share/man/man4/hfa.4.gz +OLD_FILES+=usr/share/man/man4/idt.4.gz +OLD_FILES+=usr/share/man/man4/if_idt.4.gz # 20121022: VFS_LOCK_GIANT elimination OLD_FILES+=usr/share/man/man9/VFS_LOCK_GIANT.9.gz OLD_FILES+=usr/share/man/man9/VFS_UNLOCK_GIANT.9.gz From 579ed7bd05dd91ca380ed92bc02143cbb2e3cf7f Mon Sep 17 00:00:00 2001 From: "Alexander V. Chernikov" Date: Sun, 3 Mar 2013 14:05:03 +0000 Subject: [PATCH 0558/1476] Implement buffer size checking in ipfw(8) add cmd. PR: bin/65961 Submitted by: Eugene Grosbein MFC after: 2 weeks --- sbin/ipfw/ipfw2.c | 154 +++++++++++++++++++++++++++++++--------------- sbin/ipfw/ipfw2.h | 8 +-- sbin/ipfw/ipv6.c | 25 +++++--- 3 files changed, 125 insertions(+), 62 deletions(-) diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c index 71b9e06142e..5d79eced4fe 100644 --- a/sbin/ipfw/ipfw2.c +++ b/sbin/ipfw/ipfw2.c @@ -64,6 +64,22 @@ int ipfw_socket = -1; #define s6_addr32 __u6_addr.__u6_addr32 #endif +#define CHECK_LENGTH(v, len) do { \ + if ((v) < (len)) \ + errx(EX_DATAERR, "Rule too long"); \ + } while (0) +/* + * Check if we have enough space in cmd buffer. Note that since + * first 8? u32 words are reserved by reserved header, full cmd + * buffer can't be used, so we need to protect from buffer overrun + * only. At the beginnig, cblen is less than actual buffer size by + * size of ipfw_insn_u32 instruction + 1 u32 work. This eliminates need + * for checking small instructions fitting in given range. + * We also (ab)use the fact that ipfw_insn is always the first field + * for any custom instruction. + */ +#define CHECK_CMDLEN CHECK_LENGTH(cblen, F_LEN((ipfw_insn *)cmd)) + #define GET_UINT_ARG(arg, min, max, tok, s_x) do { \ if (!av[0]) \ errx(EX_USAGE, "%s: missing argument", match_value(s_x, tok)); \ @@ -653,7 +669,7 @@ strtoport(char *s, char **end, int base, int proto) * Fill the body of the command with the list of port ranges. */ static int -fill_newports(ipfw_insn_u16 *cmd, char *av, int proto) +fill_newports(ipfw_insn_u16 *cmd, char *av, int proto, int cblen) { uint16_t a, b, *p = cmd->ports; int i = 0; @@ -664,6 +680,8 @@ fill_newports(ipfw_insn_u16 *cmd, char *av, int proto) if (s == av) /* empty or invalid argument */ return (0); + CHECK_LENGTH(cblen, i + 2); + switch (*s) { case '-': /* a range */ av = s + 1; @@ -2068,7 +2086,7 @@ lookup_host (char *host, struct in_addr *ipaddr) * We can have multiple comma-separated address/mask entries. */ static void -fill_ip(ipfw_insn_ip *cmd, char *av) +fill_ip(ipfw_insn_ip *cmd, char *av, int cblen) { int len = 0; uint32_t *d = ((ipfw_insn_u32 *)cmd)->d; @@ -2108,6 +2126,8 @@ fill_ip(ipfw_insn_ip *cmd, char *av) int masklen; char md, nd = '\0'; + CHECK_LENGTH(cblen, F_INSN_SIZE(ipfw_insn) + 2 + len); + if (p) { md = *p; *p++ = '\0'; @@ -2366,11 +2386,13 @@ ipfw_delete(char *av[]) * patterns which match interfaces. */ static void -fill_iface(ipfw_insn_if *cmd, char *arg) +fill_iface(ipfw_insn_if *cmd, char *arg, int cblen) { cmd->name[0] = '\0'; cmd->o.len |= F_INSN_SIZE(ipfw_insn_if); + CHECK_CMDLEN; + /* Parse the interface or address */ if (strcmp(arg, "any") == 0) cmd->o.len = 0; /* effectively ignore this command */ @@ -2441,8 +2463,10 @@ get_mac_addr_mask(const char *p, uint8_t *addr, uint8_t *mask) * the new command in case it has been clobbered before. */ static ipfw_insn * -next_cmd(ipfw_insn *cmd) +next_cmd(ipfw_insn *cmd, int *len) { + *len -= F_LEN(cmd); + CHECK_LENGTH(*len, 0); cmd += F_LEN(cmd); bzero(cmd, sizeof(*cmd)); return cmd; @@ -2452,7 +2476,7 @@ next_cmd(ipfw_insn *cmd) * Takes arguments and copies them into a comment */ static void -fill_comment(ipfw_insn *cmd, char **av) +fill_comment(ipfw_insn *cmd, char **av, int cblen) { int i, l; char *p = (char *)(cmd + 1); @@ -2470,6 +2494,8 @@ fill_comment(ipfw_insn *cmd, char **av) "comment too long (max 80 chars)"); l = 1 + (l+3)/4; cmd->len = (cmd->len & (F_NOT | F_OR)) | l; + CHECK_CMDLEN; + for (i = 0; av[i] != NULL; i++) { strcpy(p, av[i]); p += strlen(av[i]); @@ -2495,7 +2521,7 @@ fill_cmd(ipfw_insn *cmd, enum ipfw_opcodes opcode, int flags, uint16_t arg) * two microinstructions, and returns the pointer to the last one. */ static ipfw_insn * -add_mac(ipfw_insn *cmd, char *av[]) +add_mac(ipfw_insn *cmd, char *av[], int cblen) { ipfw_insn_mac *mac; @@ -2504,6 +2530,7 @@ add_mac(ipfw_insn *cmd, char *av[]) cmd->opcode = O_MACADDR2; cmd->len = (cmd->len & (F_NOT | F_OR)) | F_INSN_SIZE(ipfw_insn_mac); + CHECK_CMDLEN; mac = (ipfw_insn_mac *)cmd; get_mac_addr_mask(av[0], mac->addr, mac->mask); /* dst */ @@ -2513,12 +2540,13 @@ add_mac(ipfw_insn *cmd, char *av[]) } static ipfw_insn * -add_mactype(ipfw_insn *cmd, char *av) +add_mactype(ipfw_insn *cmd, char *av, int cblen) { if (!av) errx(EX_DATAERR, "missing MAC type"); if (strcmp(av, "any") != 0) { /* we have a non-null type */ - fill_newports((ipfw_insn_u16 *)cmd, av, IPPROTO_ETHERTYPE); + fill_newports((ipfw_insn_u16 *)cmd, av, IPPROTO_ETHERTYPE, + cblen); cmd->opcode = O_MAC_TYPE; return cmd; } else @@ -2587,9 +2615,9 @@ add_proto_compat(ipfw_insn *cmd, char *av, u_char *protop) } static ipfw_insn * -add_srcip(ipfw_insn *cmd, char *av) +add_srcip(ipfw_insn *cmd, char *av, int cblen) { - fill_ip((ipfw_insn_ip *)cmd, av); + fill_ip((ipfw_insn_ip *)cmd, av, cblen); if (cmd->opcode == O_IP_DST_SET) /* set */ cmd->opcode = O_IP_SRC_SET; else if (cmd->opcode == O_IP_DST_LOOKUP) /* table */ @@ -2604,9 +2632,9 @@ add_srcip(ipfw_insn *cmd, char *av) } static ipfw_insn * -add_dstip(ipfw_insn *cmd, char *av) +add_dstip(ipfw_insn *cmd, char *av, int cblen) { - fill_ip((ipfw_insn_ip *)cmd, av); + fill_ip((ipfw_insn_ip *)cmd, av, cblen); if (cmd->opcode == O_IP_DST_SET) /* set */ ; else if (cmd->opcode == O_IP_DST_LOOKUP) /* table */ @@ -2621,12 +2649,12 @@ add_dstip(ipfw_insn *cmd, char *av) } static ipfw_insn * -add_ports(ipfw_insn *cmd, char *av, u_char proto, int opcode) +add_ports(ipfw_insn *cmd, char *av, u_char proto, int opcode, int cblen) { /* XXX "any" is trapped before. Perhaps "to" */ if (_substrcmp(av, "any") == 0) { return NULL; - } else if (fill_newports((ipfw_insn_u16 *)cmd, av, proto)) { + } else if (fill_newports((ipfw_insn_u16 *)cmd, av, proto, cblen)) { /* XXX todo: check that we have a protocol with ports */ cmd->opcode = opcode; return cmd; @@ -2635,7 +2663,7 @@ add_ports(ipfw_insn *cmd, char *av, u_char proto, int opcode) } static ipfw_insn * -add_src(ipfw_insn *cmd, char *av, u_char proto) +add_src(ipfw_insn *cmd, char *av, u_char proto, int cblen) { struct in6_addr a; char *host, *ch; @@ -2648,11 +2676,11 @@ add_src(ipfw_insn *cmd, char *av, u_char proto) if (proto == IPPROTO_IPV6 || strcmp(av, "me6") == 0 || inet_pton(AF_INET6, host, &a) == 1) - ret = add_srcip6(cmd, av); + ret = add_srcip6(cmd, av, cblen); /* XXX: should check for IPv4, not !IPv6 */ if (ret == NULL && (proto == IPPROTO_IP || strcmp(av, "me") == 0 || inet_pton(AF_INET6, host, &a) != 1)) - ret = add_srcip(cmd, av); + ret = add_srcip(cmd, av, cblen); if (ret == NULL && strcmp(av, "any") != 0) ret = cmd; @@ -2661,7 +2689,7 @@ add_src(ipfw_insn *cmd, char *av, u_char proto) } static ipfw_insn * -add_dst(ipfw_insn *cmd, char *av, u_char proto) +add_dst(ipfw_insn *cmd, char *av, u_char proto, int cblen) { struct in6_addr a; char *host, *ch; @@ -2674,11 +2702,11 @@ add_dst(ipfw_insn *cmd, char *av, u_char proto) if (proto == IPPROTO_IPV6 || strcmp(av, "me6") == 0 || inet_pton(AF_INET6, host, &a) == 1) - ret = add_dstip6(cmd, av); + ret = add_dstip6(cmd, av, cblen); /* XXX: should check for IPv4, not !IPv6 */ if (ret == NULL && (proto == IPPROTO_IP || strcmp(av, "me") == 0 || inet_pton(AF_INET6, host, &a) != 1)) - ret = add_dstip(cmd, av); + ret = add_dstip(cmd, av, cblen); if (ret == NULL && strcmp(av, "any") != 0) ret = cmd; @@ -2708,6 +2736,7 @@ ipfw_add(char *av[]) * go into actbuf[]. */ static uint32_t rulebuf[255], actbuf[255], cmdbuf[255]; + int rblen, ablen, cblen; ipfw_insn *src, *dst, *cmd, *action, *prev=NULL; ipfw_insn *first_cmd; /* first match pattern */ @@ -2738,6 +2767,15 @@ ipfw_add(char *av[]) cmd = (ipfw_insn *)cmdbuf; action = (ipfw_insn *)actbuf; + rblen = sizeof(rulebuf) / sizeof(rulebuf[0]); + rblen -= offsetof(struct ip_fw, cmd) / sizeof(rulebuf[0]); + ablen = sizeof(actbuf) / sizeof(actbuf[0]); + cblen = sizeof(cmdbuf) / sizeof(cmdbuf[0]); + cblen -= F_INSN_SIZE(ipfw_insn_u32) + 1; + +#define CHECK_RBUFLEN(len) { CHECK_LENGTH(rblen, len); rblen -= len; } +#define CHECK_ACTLEN CHECK_LENGTH(ablen, action->len) + av++; /* [rule N] -- Rule number optional */ @@ -2769,6 +2807,7 @@ ipfw_add(char *av[]) i = match_token(rule_actions, *av); av++; action->len = 1; /* default */ + CHECK_ACTLEN; switch(i) { case TOK_CHECKSTATE: have_state = action; @@ -2820,6 +2859,7 @@ ipfw_add(char *av[]) case TOK_NAT: action->opcode = O_NAT; action->len = F_INSN_SIZE(ipfw_insn_nat); + CHECK_ACTLEN; if (_substrcmp(*av, "global") == 0) { action->arg1 = 0; av++; @@ -2936,6 +2976,7 @@ chkarg: action->opcode = O_FORWARD_IP; action->len = F_INSN_SIZE(ipfw_insn_sa); + CHECK_ACTLEN; /* * In the kernel we assume AF_INET and use only @@ -2952,6 +2993,7 @@ chkarg: action->opcode = O_FORWARD_IP6; action->len = F_INSN_SIZE(ipfw_insn_sa6); + CHECK_ACTLEN; p->sa.sin6_len = sizeof(struct sockaddr_in6); p->sa.sin6_family = AF_INET6; @@ -3005,7 +3047,7 @@ chkarg: default: errx(EX_DATAERR, "invalid action %s\n", av[-1]); } - action = next_cmd(action); + action = next_cmd(action, &ablen); /* * [altq queuename] -- altq tag, optional @@ -3027,6 +3069,7 @@ chkarg: "log cannot be specified more than once"); have_log = (ipfw_insn *)c; cmd->len = F_INSN_SIZE(ipfw_insn_log); + CHECK_CMDLEN; cmd->opcode = O_LOG; if (av[0] && _substrcmp(*av, "logamount") == 0) { av++; @@ -3058,6 +3101,7 @@ chkarg: "altq cannot be specified more than once"); have_altq = (ipfw_insn *)a; cmd->len = F_INSN_SIZE(ipfw_insn_altq); + CHECK_CMDLEN; cmd->opcode = O_ALTQ; a->qid = altq_name_to_qid(*av); av++; @@ -3083,7 +3127,7 @@ chkarg: default: abort(); } - cmd = next_cmd(cmd); + cmd = next_cmd(cmd, &cblen); } if (have_state) /* must be a check-state, we are done */ @@ -3168,7 +3212,7 @@ chkarg: av++; if (F_LEN(cmd) != 0) { prev = cmd; - cmd = next_cmd(cmd); + cmd = next_cmd(cmd, &cblen); } } else if (first_cmd != cmd) { errx(EX_DATAERR, "invalid protocol ``%s''", *av); @@ -3189,11 +3233,11 @@ chkarg: OR_START(source_ip); NOT_BLOCK; /* optional "not" */ NEED1("missing source address"); - if (add_src(cmd, *av, proto)) { + if (add_src(cmd, *av, proto, cblen)) { av++; if (F_LEN(cmd) != 0) { /* ! any */ prev = cmd; - cmd = next_cmd(cmd); + cmd = next_cmd(cmd, &cblen); } } else errx(EX_USAGE, "bad source address %s", *av); @@ -3205,10 +3249,10 @@ chkarg: NOT_BLOCK; /* optional "not" */ if ( av[0] != NULL ) { if (_substrcmp(*av, "any") == 0 || - add_ports(cmd, *av, proto, O_IP_SRCPORT)) { + add_ports(cmd, *av, proto, O_IP_SRCPORT, cblen)) { av++; if (F_LEN(cmd) != 0) - cmd = next_cmd(cmd); + cmd = next_cmd(cmd, &cblen); } } @@ -3225,11 +3269,11 @@ chkarg: OR_START(dest_ip); NOT_BLOCK; /* optional "not" */ NEED1("missing dst address"); - if (add_dst(cmd, *av, proto)) { + if (add_dst(cmd, *av, proto, cblen)) { av++; if (F_LEN(cmd) != 0) { /* ! any */ prev = cmd; - cmd = next_cmd(cmd); + cmd = next_cmd(cmd, &cblen); } } else errx( EX_USAGE, "bad destination address %s", *av); @@ -3241,10 +3285,10 @@ chkarg: NOT_BLOCK; /* optional "not" */ if (av[0]) { if (_substrcmp(*av, "any") == 0 || - add_ports(cmd, *av, proto, O_IP_DSTPORT)) { + add_ports(cmd, *av, proto, O_IP_DSTPORT, cblen)) { av++; if (F_LEN(cmd) != 0) - cmd = next_cmd(cmd); + cmd = next_cmd(cmd, &cblen); } } @@ -3332,7 +3376,7 @@ read_options: case TOK_VIA: NEED1("recv, xmit, via require interface name" " or address"); - fill_iface((ipfw_insn_if *)cmd, av[0]); + fill_iface((ipfw_insn_if *)cmd, av[0], cblen); av++; if (F_LEN(cmd) == 0) /* not a valid address */ break; @@ -3352,14 +3396,14 @@ read_options: case TOK_ICMP6TYPES: NEED1("icmptypes requires list of types"); - fill_icmp6types((ipfw_insn_icmp6 *)cmd, *av); + fill_icmp6types((ipfw_insn_icmp6 *)cmd, *av, cblen); av++; break; case TOK_IPTTL: NEED1("ipttl requires TTL"); if (strpbrk(*av, "-,")) { - if (!add_ports(cmd, *av, 0, O_IPTTL)) + if (!add_ports(cmd, *av, 0, O_IPTTL, cblen)) errx(EX_DATAERR, "invalid ipttl %s", *av); } else fill_cmd(cmd, O_IPTTL, 0, strtoul(*av, NULL, 0)); @@ -3369,7 +3413,7 @@ read_options: case TOK_IPID: NEED1("ipid requires id"); if (strpbrk(*av, "-,")) { - if (!add_ports(cmd, *av, 0, O_IPID)) + if (!add_ports(cmd, *av, 0, O_IPID, cblen)) errx(EX_DATAERR, "invalid ipid %s", *av); } else fill_cmd(cmd, O_IPID, 0, strtoul(*av, NULL, 0)); @@ -3379,7 +3423,7 @@ read_options: case TOK_IPLEN: NEED1("iplen requires length"); if (strpbrk(*av, "-,")) { - if (!add_ports(cmd, *av, 0, O_IPLEN)) + if (!add_ports(cmd, *av, 0, O_IPLEN, cblen)) errx(EX_DATAERR, "invalid ip len %s", *av); } else fill_cmd(cmd, O_IPLEN, 0, strtoul(*av, NULL, 0)); @@ -3475,7 +3519,7 @@ read_options: case TOK_TCPDATALEN: NEED1("tcpdatalen requires length"); if (strpbrk(*av, "-,")) { - if (!add_ports(cmd, *av, 0, O_TCPDATALEN)) + if (!add_ports(cmd, *av, 0, O_TCPDATALEN, cblen)) errx(EX_DATAERR, "invalid tcpdata len %s", *av); } else fill_cmd(cmd, O_TCPDATALEN, 0, @@ -3501,7 +3545,7 @@ read_options: case TOK_TCPWIN: NEED1("tcpwin requires length"); if (strpbrk(*av, "-,")) { - if (!add_ports(cmd, *av, 0, O_TCPWIN)) + if (!add_ports(cmd, *av, 0, O_TCPWIN, cblen)) errx(EX_DATAERR, "invalid tcpwin len %s", *av); } else fill_cmd(cmd, O_TCPWIN, 0, @@ -3540,6 +3584,7 @@ read_options: have_state = cmd; cmd->len = F_INSN_SIZE(ipfw_insn_limit); + CHECK_CMDLEN; cmd->opcode = O_LIMIT; c->limit_mask = c->conn_limit = 0; @@ -3571,28 +3616,28 @@ read_options: case TOK_SRCIP: NEED1("missing source IP"); - if (add_srcip(cmd, *av)) { + if (add_srcip(cmd, *av, cblen)) { av++; } break; case TOK_DSTIP: NEED1("missing destination IP"); - if (add_dstip(cmd, *av)) { + if (add_dstip(cmd, *av, cblen)) { av++; } break; case TOK_SRCIP6: NEED1("missing source IP6"); - if (add_srcip6(cmd, *av)) { + if (add_srcip6(cmd, *av, cblen)) { av++; } break; case TOK_DSTIP6: NEED1("missing destination IP6"); - if (add_dstip6(cmd, *av)) { + if (add_dstip6(cmd, *av, cblen)) { av++; } break; @@ -3600,7 +3645,7 @@ read_options: case TOK_SRCPORT: NEED1("missing source port"); if (_substrcmp(*av, "any") == 0 || - add_ports(cmd, *av, proto, O_IP_SRCPORT)) { + add_ports(cmd, *av, proto, O_IP_SRCPORT, cblen)) { av++; } else errx(EX_DATAERR, "invalid source port %s", *av); @@ -3609,7 +3654,7 @@ read_options: case TOK_DSTPORT: NEED1("missing destination port"); if (_substrcmp(*av, "any") == 0 || - add_ports(cmd, *av, proto, O_IP_DSTPORT)) { + add_ports(cmd, *av, proto, O_IP_DSTPORT, cblen)) { av++; } else errx(EX_DATAERR, "invalid destination port %s", @@ -3617,13 +3662,13 @@ read_options: break; case TOK_MAC: - if (add_mac(cmd, av)) + if (add_mac(cmd, av, cblen)) av += 2; break; case TOK_MACTYPE: NEED1("missing mac type"); - if (!add_mactype(cmd, *av)) + if (!add_mactype(cmd, *av, cblen)) errx(EX_DATAERR, "invalid mac type %s", *av); av++; break; @@ -3661,18 +3706,18 @@ read_options: if (proto != IPPROTO_IPV6 ) errx( EX_USAGE, "flow-id filter is active " "only for ipv6 protocol\n"); - fill_flow6( (ipfw_insn_u32 *) cmd, *av ); + fill_flow6( (ipfw_insn_u32 *) cmd, *av, cblen); av++; break; case TOK_COMMENT: - fill_comment(cmd, av); + fill_comment(cmd, av, cblen); av[0]=NULL; break; case TOK_TAGGED: if (av[0] && strpbrk(*av, "-,")) { - if (!add_ports(cmd, *av, 0, O_TAGGED)) + if (!add_ports(cmd, *av, 0, O_TAGGED, cblen)) errx(EX_DATAERR, "tagged: invalid tag" " list: %s", *av); } @@ -3725,7 +3770,7 @@ read_options: } if (F_LEN(cmd) > 0) { /* prepare to advance */ prev = cmd; - cmd = next_cmd(cmd); + cmd = next_cmd(cmd, &cblen); } } @@ -3754,12 +3799,13 @@ done: */ if (have_state && have_state->opcode != O_CHECK_STATE) { fill_cmd(dst, O_PROBE_STATE, 0, 0); - dst = next_cmd(dst); + dst = next_cmd(dst, &rblen); } /* copy all commands but O_LOG, O_KEEP_STATE, O_LIMIT, O_ALTQ, O_TAG */ for (src = (ipfw_insn *)cmdbuf; src != cmd; src += i) { i = F_LEN(src); + CHECK_RBUFLEN(i); switch (src->opcode) { case O_LOG: @@ -3779,6 +3825,7 @@ done: */ if (have_state && have_state->opcode != O_CHECK_STATE) { i = F_LEN(have_state); + CHECK_RBUFLEN(i); bcopy(have_state, dst, i * sizeof(uint32_t)); dst += i; } @@ -3790,24 +3837,29 @@ done: /* put back O_LOG, O_ALTQ, O_TAG if necessary */ if (have_log) { i = F_LEN(have_log); + CHECK_RBUFLEN(i); bcopy(have_log, dst, i * sizeof(uint32_t)); dst += i; } if (have_altq) { i = F_LEN(have_altq); + CHECK_RBUFLEN(i); bcopy(have_altq, dst, i * sizeof(uint32_t)); dst += i; } if (have_tag) { i = F_LEN(have_tag); + CHECK_RBUFLEN(i); bcopy(have_tag, dst, i * sizeof(uint32_t)); dst += i; } + /* * copy all other actions */ for (src = (ipfw_insn *)actbuf; src != action; src += i) { i = F_LEN(src); + CHECK_RBUFLEN(i); bcopy(src, dst, i * sizeof(uint32_t)); dst += i; } diff --git a/sbin/ipfw/ipfw2.h b/sbin/ipfw/ipfw2.h index bade0dda652..81e0ba8aa29 100644 --- a/sbin/ipfw/ipfw2.h +++ b/sbin/ipfw/ipfw2.h @@ -283,10 +283,10 @@ void print_flow6id(struct _ipfw_insn_u32 *cmd); void print_icmp6types(struct _ipfw_insn_u32 *cmd); void print_ext6hdr(struct _ipfw_insn *cmd ); -struct _ipfw_insn *add_srcip6(struct _ipfw_insn *cmd, char *av); -struct _ipfw_insn *add_dstip6(struct _ipfw_insn *cmd, char *av); +struct _ipfw_insn *add_srcip6(struct _ipfw_insn *cmd, char *av, int cblen); +struct _ipfw_insn *add_dstip6(struct _ipfw_insn *cmd, char *av, int cblen); -void fill_flow6(struct _ipfw_insn_u32 *cmd, char *av ); +void fill_flow6(struct _ipfw_insn_u32 *cmd, char *av, int cblen); void fill_unreach6_code(u_short *codep, char *str); -void fill_icmp6types(struct _ipfw_insn_icmp6 *cmd, char *av); +void fill_icmp6types(struct _ipfw_insn_icmp6 *cmd, char *av, int cblen); int fill_ext6hdr(struct _ipfw_insn *cmd, char *av); diff --git a/sbin/ipfw/ipv6.c b/sbin/ipfw/ipv6.c index 6326590a46a..ee9bb623f3a 100644 --- a/sbin/ipfw/ipv6.c +++ b/sbin/ipfw/ipv6.c @@ -42,6 +42,11 @@ #include #include +#define CHECK_LENGTH(v, len) do { \ + if ((v) < (len)) \ + errx(EX_DATAERR, "Rule too long"); \ + } while (0) + static struct _s_x icmp6codes[] = { { "no-route", ICMP6_DST_UNREACH_NOROUTE }, { "admin-prohib", ICMP6_DST_UNREACH_ADMIN }, @@ -131,10 +136,12 @@ print_ip6(ipfw_insn_ip6 *cmd, char const *s) } void -fill_icmp6types(ipfw_insn_icmp6 *cmd, char *av) +fill_icmp6types(ipfw_insn_icmp6 *cmd, char *av, int cblen) { uint8_t type; + CHECK_LENGTH(cblen, F_INSN_SIZE(ipfw_insn_icmp6)); + bzero(cmd, sizeof(*cmd)); while (*av) { if (*av == ',') @@ -327,7 +334,7 @@ lookup_host6 (char *host, struct in6_addr *ip6addr) * Return 1 on success, 0 on failure. */ static int -fill_ip6(ipfw_insn_ip6 *cmd, char *av) +fill_ip6(ipfw_insn_ip6 *cmd, char *av, int cblen) { int len = 0; struct in6_addr *d = &(cmd->addr6); @@ -379,6 +386,8 @@ fill_ip6(ipfw_insn_ip6 *cmd, char *av) int masklen; char md = '\0'; + CHECK_LENGTH(cblen, 1 + len + 2 * F_INSN_SIZE(struct in6_addr)); + if ((p = strpbrk(av, "/,")) ) { md = *p; /* save the separator */ *p = '\0'; /* terminate address string */ @@ -453,7 +462,7 @@ fill_ip6(ipfw_insn_ip6 *cmd, char *av) * additional flow-id we want to filter, the basic is 1 */ void -fill_flow6( ipfw_insn_u32 *cmd, char *av ) +fill_flow6( ipfw_insn_u32 *cmd, char *av, int cblen) { u_int32_t type; /* Current flow number */ u_int16_t nflow = 0; /* Current flow index */ @@ -461,6 +470,8 @@ fill_flow6( ipfw_insn_u32 *cmd, char *av ) cmd->d[0] = 0; /* Initializing the base number*/ while (s) { + CHECK_LENGTH(cblen, F_INSN_SIZE(ipfw_insn_u32) + nflow + 1); + av = strsep( &s, ",") ; type = strtoul(av, &av, 0); if (*av != ',' && *av != '\0') @@ -481,10 +492,10 @@ fill_flow6( ipfw_insn_u32 *cmd, char *av ) } ipfw_insn * -add_srcip6(ipfw_insn *cmd, char *av) +add_srcip6(ipfw_insn *cmd, char *av, int cblen) { - fill_ip6((ipfw_insn_ip6 *)cmd, av); + fill_ip6((ipfw_insn_ip6 *)cmd, av, cblen); if (cmd->opcode == O_IP_DST_SET) /* set */ cmd->opcode = O_IP_SRC_SET; else if (cmd->opcode == O_IP_DST_LOOKUP) /* table */ @@ -503,10 +514,10 @@ add_srcip6(ipfw_insn *cmd, char *av) } ipfw_insn * -add_dstip6(ipfw_insn *cmd, char *av) +add_dstip6(ipfw_insn *cmd, char *av, int cblen) { - fill_ip6((ipfw_insn_ip6 *)cmd, av); + fill_ip6((ipfw_insn_ip6 *)cmd, av, cblen); if (cmd->opcode == O_IP_DST_SET) /* set */ ; else if (cmd->opcode == O_IP_DST_LOOKUP) /* table */ From 2dea247f6bc464e336798a17d20eebad15f7f5e0 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Sun, 3 Mar 2013 14:42:15 +0000 Subject: [PATCH 0559/1476] libedit: Revert r247683 to fix buildworld. I think r247683 is wrong because libedit.so actually uses symbols from libcurses.so. Since it breaks the build, revert it now. --- lib/libedit/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/libedit/Makefile b/lib/libedit/Makefile index 1c6e52c3816..d8ae6468196 100644 --- a/lib/libedit/Makefile +++ b/lib/libedit/Makefile @@ -11,6 +11,7 @@ OSRCS= chared.c common.c el.c emacs.c fcns.c filecomplete.c help.c \ parse.c prompt.c read.c refresh.c search.c sig.c term.c tty.c vi.c DPADD= ${LIBNCURSES} +LDADD= -lncurses MAN= editline.3 editrc.5 From 0fb285b716ece51d665259a6bb32bd06abdca87e Mon Sep 17 00:00:00 2001 From: Davide Italiano Date: Sun, 3 Mar 2013 14:47:02 +0000 Subject: [PATCH 0560/1476] Remove a couple of unused include. --- sys/kern/kern_timeout.c | 1 - sys/sys/systm.h | 1 - 2 files changed, 2 deletions(-) diff --git a/sys/kern/kern_timeout.c b/sys/kern/kern_timeout.c index 69851e66e54..cd83acbe6b6 100644 --- a/sys/kern/kern_timeout.c +++ b/sys/kern/kern_timeout.c @@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include diff --git a/sys/sys/systm.h b/sys/sys/systm.h index 2bf805605b3..11a9cf942b9 100644 --- a/sys/sys/systm.h +++ b/sys/sys/systm.h @@ -44,7 +44,6 @@ #include #include #include /* for people using printf mainly */ -#include extern int cold; /* nonzero if we are doing a cold boot */ extern int rebooting; /* kern_reboot() has been called. */ From 3f555c45eb3798106a1504db79ed53a70b7d8e46 Mon Sep 17 00:00:00 2001 From: Davide Italiano Date: Sun, 3 Mar 2013 15:01:33 +0000 Subject: [PATCH 0561/1476] callwheelmask and callwheelsize are always greater than zero. Switch their type to u_int. --- sys/kern/kern_timeout.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/kern/kern_timeout.c b/sys/kern/kern_timeout.c index cd83acbe6b6..a217db17f5f 100644 --- a/sys/kern/kern_timeout.c +++ b/sys/kern/kern_timeout.c @@ -83,7 +83,7 @@ SYSCTL_INT(_debug, OID_AUTO, to_avg_mpcalls, CTLFLAG_RD, &avg_mpcalls, 0, * TODO: * allocate more timeout table slots when table overflows. */ -int callwheelsize, callwheelmask; +u_int callwheelsize, callwheelmask; /* * The callout cpu migration entity represents informations necessary for From ac232dc74756b2866202bf71a9f9ccb2726bdf7c Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Sun, 3 Mar 2013 15:02:56 +0000 Subject: [PATCH 0562/1476] MAINTAINERS: Document my maintainership of sh(1). --- MAINTAINERS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 7df973a132d..41142d2d697 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -124,3 +124,6 @@ isci(4) jimharris Pre-commit review requested. cmx daniel@roe.ch Pre-commit review preferred. filemon obrien Pre-commit review preferred. sysdoc trhodes Pre-commit review preferred. +sh(1) jilles Pre-commit review requested. This also applies + to kill(1), printf(1) and test(1) which are + compiled in as builtins. From 21e0559cbcdf275377da88dec0d7a98e85f00f80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulrich=20Sp=C3=B6rlein?= Date: Sun, 3 Mar 2013 16:17:09 +0000 Subject: [PATCH 0563/1476] Fix 'make depend' --- sys/modules/mqueue/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/modules/mqueue/Makefile b/sys/modules/mqueue/Makefile index 1a2955633c2..f86c78bc756 100644 --- a/sys/modules/mqueue/Makefile +++ b/sys/modules/mqueue/Makefile @@ -5,6 +5,6 @@ KMOD= mqueuefs SRCS= uipc_mqueue.c \ vnode_if.h \ - opt_posix.h opt_compat.h + opt_posix.h opt_compat.h opt_capsicum.h .include From 3fe1119f9804d9252b8ace5aa151c781be138512 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Sun, 3 Mar 2013 17:33:59 +0000 Subject: [PATCH 0564/1476] sh: When executing a trap, keep exit status along with evalskip. This ensures 'return' in a trap returns the correct status to the caller. If evalskip is not set or if it is overridden by a previous evalskip, keep the old behaviour of restoring the exit status from before the trap. --- bin/sh/trap.c | 5 +++-- tools/regression/bin/sh/builtins/trap12.0 | 10 ++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 tools/regression/bin/sh/builtins/trap12.0 diff --git a/bin/sh/trap.c b/bin/sh/trap.c index 0a9eb60f5fb..6c4cbbeec8e 100644 --- a/bin/sh/trap.c +++ b/bin/sh/trap.c @@ -455,7 +455,6 @@ dotrap(void) last_trapsig = i; savestatus = exitstatus; evalstring(trap[i], 0); - exitstatus = savestatus; /* * If such a command was not @@ -464,9 +463,11 @@ dotrap(void) * trap action to have an effect * outside of it. */ - if (prev_evalskip != 0) { + if (evalskip == 0 || + prev_evalskip != 0) { evalskip = prev_evalskip; skipcount = prev_skipcount; + exitstatus = savestatus; } if (i == SIGCHLD) diff --git a/tools/regression/bin/sh/builtins/trap12.0 b/tools/regression/bin/sh/builtins/trap12.0 new file mode 100644 index 00000000000..8c62ffd2b57 --- /dev/null +++ b/tools/regression/bin/sh/builtins/trap12.0 @@ -0,0 +1,10 @@ +# $FreeBSD$ + +f() { + trap 'return 42' USR1 + kill -USR1 $$ + return 3 +} +f +r=$? +[ "$r" = 42 ] From b6bc5f51faf75e6433e51ba31d47015eefd8d8de Mon Sep 17 00:00:00 2001 From: Alexander Motin Date: Sun, 3 Mar 2013 19:10:28 +0000 Subject: [PATCH 0565/1476] Fix typos in hint names. MFC after: 1 week --- share/man/man4/mvs.4 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/share/man/man4/mvs.4 b/share/man/man4/mvs.4 index 5c8d8ccd1df..be8c3eab913 100644 --- a/share/man/man4/mvs.4 +++ b/share/man/man4/mvs.4 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 27, 2010 +.Dd March 3, 2013 .Dt MVS 4 .Os .Sh NAME @@ -62,7 +62,7 @@ command latency. .It Va hint.mvs. Ns Ar X Ns Va .cccc defines number of completed commands for CCC, which trigger interrupt without waiting for specified coalescing timeout. -.It Va hint.mvs. Ns Ar X Ns Va .pm_level +.It Va hint.mvsch. Ns Ar X Ns Va .pm_level controls SATA interface Power Management for the specified channel, allowing some power to be saved at the cost of additional command latency. @@ -82,7 +82,7 @@ driver initiates SLUMBER PM state transition 125ms after port becomes idle. Note that interface Power Management is not compatible with device presence detection. A manual bus reset is needed on device hot-plug. -.It Va hint.mvs. Ns Ar X Ns Va .sata_rev +.It Va hint.mvsch. Ns Ar X Ns Va .sata_rev setting to nonzero value limits maximum SATA revision (speed). Values 1, 2 and 3 are respectively 1.5, 3 and 6Gbps. .El From 9ed0c92c91e9a8459462774b33c368b56e2c7ced Mon Sep 17 00:00:00 2001 From: David Malone Date: Sun, 3 Mar 2013 20:10:56 +0000 Subject: [PATCH 0566/1476] Add an option for finding sparse files. Reviewed by: iedowse MFC after: 3 weeks --- usr.bin/find/extern.h | 2 ++ usr.bin/find/find.1 | 6 +++++- usr.bin/find/function.c | 23 +++++++++++++++++++++++ usr.bin/find/option.c | 1 + 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/usr.bin/find/extern.h b/usr.bin/find/extern.h index 6fa25d2debe..90b9b29d265 100644 --- a/usr.bin/find/extern.h +++ b/usr.bin/find/extern.h @@ -73,6 +73,7 @@ creat_f c_regex; creat_f c_samefile; creat_f c_simple; creat_f c_size; +creat_f c_sparse; creat_f c_type; creat_f c_user; creat_f c_xdev; @@ -109,6 +110,7 @@ exec_f f_prune; exec_f f_quit; exec_f f_regex; exec_f f_size; +exec_f f_sparse; exec_f f_type; exec_f f_user; diff --git a/usr.bin/find/find.1 b/usr.bin/find/find.1 index 47c40d81842..cffeacf7ef5 100644 --- a/usr.bin/find/find.1 +++ b/usr.bin/find/find.1 @@ -816,6 +816,10 @@ terabytes (1024 gigabytes) .It Cm P petabytes (1024 terabytes) .El +.It Ic -sparse +True if the current file is sparse, +i.e. has fewer blocks allocated than expected based on its size in bytes. +This might also match files that have been compressed by the filesystem. .It Ic -type Ar t True if the file is of the specified type. Possible file types are as follows: @@ -997,7 +1001,7 @@ and as well as .Ic -amin , -anewer , -cmin , -cnewer , -delete , -empty , -fstype , .Ic -iname , -inum , -iregex , -ls , -maxdepth , -mindepth , -mmin , -.Ic -path , -print0 , -regex +.Ic -path , -print0 , -regex, -sparse and all of the .Ic -B* birthtime related primaries are extensions to diff --git a/usr.bin/find/function.c b/usr.bin/find/function.c index cad6eb15fc8..61d61cb4907 100644 --- a/usr.bin/find/function.c +++ b/usr.bin/find/function.c @@ -1496,6 +1496,29 @@ c_size(OPTION *option, char ***argvp) return new; } +/* + * -sparse functions -- + * + * Check if a file is sparse by finding if it occupies fewer blocks + * than we expect based on its size. + */ +int +f_sparse(PLAN *plan __unused, FTSENT *entry) +{ + off_t expected_blocks; + + expected_blocks = (entry->fts_statp->st_size + 511) / 512; + return entry->fts_statp->st_blocks < expected_blocks; +} + +PLAN * +c_sparse(OPTION *option, char ***argvp __unused) +{ + ftsoptions &= ~FTS_NOSTAT; + + return palloc(option); +} + /* * -type c functions -- * diff --git a/usr.bin/find/option.c b/usr.bin/find/option.c index b89420cbf0c..4fc63b6c756 100644 --- a/usr.bin/find/option.c +++ b/usr.bin/find/option.c @@ -145,6 +145,7 @@ static OPTION const options[] = { { "-regex", c_regex, f_regex, 0 }, { "-samefile", c_samefile, f_inum, 0 }, { "-size", c_size, f_size, 0 }, + { "-sparse", c_sparse, f_sparse, 0 }, { "-true", c_simple, f_always_true, 0 }, { "-type", c_type, f_type, 0 }, { "-uid", c_user, f_user, 0 }, From 9090eb778e6206d49a7c9b145ff6f1f7e6af77d4 Mon Sep 17 00:00:00 2001 From: Josh Paetzel Date: Sun, 3 Mar 2013 23:01:46 +0000 Subject: [PATCH 0567/1476] Improves and enhances using the "installPackages=" variable. Adds "pkgExt=" variable to set if pkgs are .tbz or .txz or other. Auto-detects if packages are PKGNG or old PKG format. Auto-bootstrap of PKGNG for the new installed environment. Fixes issues with installing packages from local media, such as DVD/USB. Switch to using a space-delimiter for installPackages, since a number of packages use a "," in their version string. Fix pc-sysinstall to ignore install scripts, and not hang on user interaction prompts when installing pkgs. Add pkg2ng command as apart of pkgng bootstrap process. Obtained from: PC-BSD --- .../backend/functions-installpackages.sh | 129 ++++++++++++----- .../backend/functions-packages.sh | 137 +++++++++++------- 2 files changed, 184 insertions(+), 82 deletions(-) diff --git a/usr.sbin/pc-sysinstall/backend/functions-installpackages.sh b/usr.sbin/pc-sysinstall/backend/functions-installpackages.sh index 7572efb61f6..c1a879ae966 100755 --- a/usr.sbin/pc-sysinstall/backend/functions-installpackages.sh +++ b/usr.sbin/pc-sysinstall/backend/functions-installpackages.sh @@ -76,50 +76,113 @@ fetch_package_dependencies() # Check for any packages specified, and begin loading them install_packages() { + echo "Checking for packages to install..." + sleep 2 + # First, lets check and see if we even have any packages to install get_value_from_cfg installPackages - if [ -n "${VAL}" ] - then - HERE=`pwd` - rc_nohalt "mkdir -p ${FSMNT}/${PKGTMPDIR}" - rc_nohalt "cd ${FSMNT}/${PKGTMPDIR}" - if [ ! -f "${CONFDIR}/INDEX" ] + # Nothing to do? + if [ -z "${VAL}" ]; then return; fi + + echo "Installing packages..." + sleep 3 + + local PKGPTH + + HERE=`pwd` + rc_halt "mkdir -p ${FSMNT}${PKGTMPDIR}" + + # Determine the directory we will install packages from + get_package_location + rc_halt "cd ${PKGDLDIR}" + + # Set the location of the INDEXFILE + INDEXFILE="${TMPDIR}/INDEX" + + if [ ! -f "${INDEXFILE}" ]; then + get_package_index + fi + + if [ ! -f "${TMPDIR}/INDEX.parsed" -a "$INSTALLMEDIUM" = "ftp" ]; then + parse_package_index + fi + + # What extension are we using for pkgs? + PKGEXT="txz" + get_value_from_cfg pkgExt + if [ -n "${VAL}" ]; then + strip_white_space ${VAL} + PKGEXT="$VAL" + fi + export PKGEXT + + # We dont want to be bothered with scripts asking questions + PACKAGE_BUILDING=yes + export PACKAGE_BUILDING + + # Lets start by cleaning up the string and getting it ready to parse + get_value_from_cfg_with_spaces installPackages + PACKAGES="${VAL}" + echo_log "Packages to install: `echo $PACKAGES | wc -w | awk '{print $1}'`" + for i in $PACKAGES + do + if ! get_package_name "${i}" then - get_package_index + echo_log "Unable to locate package ${i}" + continue fi - if [ ! -f "${CONFDIR}/INDEX.parsed" ] - then - parse_package_index + PKGNAME="${VAL}" + + # Fetch package + deps, but skip if installing from local media + if [ "${INSTALLMEDIUM}" = "ftp" ] ; then + DEPFILE="${FSMNT}/${PKGTMPDIR}/.${PKGNAME}.deps" + rc_nohalt "touch ${DEPFILE}" + determine_package_dependencies "${PKGNAME}" "${DEPFILE}" + fetch_package_dependencies "${DEPFILE}" "${FSMNT}/${PKGTMPDIR}" fi - # Lets start by cleaning up the string and getting it ready to parse - strip_white_space ${VAL} - PACKAGES=`echo ${VAL} | sed -e "s|,| |g"` - for i in $PACKAGES - do - if get_package_name "${i}" - then - PKGNAME="${VAL}" - DEPFILE="${FSMNT}/${PKGTMPDIR}/.${PKGNAME}.deps" + # Set package location + case "${INSTALLMEDIUM}" in + usb|dvd|local) PKGPTH="${PKGTMPDIR}/All/${PKGNAME}" ;; + *) PKGPTH="${PKGTMPDIR}/${PKGNAME}" ;; + esac - rc_nohalt "touch ${DEPFILE}" - determine_package_dependencies "${PKGNAME}" "${DEPFILE}" - fetch_package_dependencies "${DEPFILE}" "${FSMNT}/${PKGTMPDIR}" - - # If the package is not already installed, install it! - if ! run_chroot_cmd "pkg_info -e ${PKGNAME}" - then - rc_nohalt "pkg_add -C ${FSMNT} ${PKGTMPDIR}/${PKGNAME}.tbz" - fi - - rc_nohalt "rm ${DEPFILE}" + # See if we need to determine the package format we are working with + if [ -z "${PKGINFO}" ] ; then + tar tqf "${FSMNT}${PKGPTH}" '+MANIFEST' >/dev/null 2>/dev/null + if [ $? -ne 0 ] ; then + PKGADD="pkg_add -C ${FSMNT}" + PKGINFO="pkg_info" + else + PKGADD="pkg -c ${FSMNT} add" + PKGINFO="pkg info" + bootstrap_pkgng fi + fi - rc_nohalt "cd ${HERE}" - done + # If the package is not already installed, install it! + if ! run_chroot_cmd "${PKGINFO} -e ${PKGNAME}" >/dev/null 2>/dev/null + then + echo_log "Installing package: ${PKGNAME}" + rc_nohalt "${PKGADD} ${PKGPTH}" + fi - rm -rf "${FSMNT}/${PKGTMPDIR}" + if [ "${INSTALLMEDIUM}" = "ftp" ] ; then + rc_nohalt "rm ${DEPFILE}" + fi + + done + + echo_log "Package installation complete!" + + # Cleanup after ourselves + rc_halt "cd ${HERE}" + if [ "${INSTALLMEDIUM}" = "ftp" ] ; then + rc_halt "rm -rf ${FSMNT}${PKGTMPDIR}" >/dev/null 2>/dev/null + else + rc_halt "umount ${FSMNT}${PKGTMPDIR}" >/dev/null 2>/dev/null + rc_halt "rmdir ${FSMNT}${PKGTMPDIR}" >/dev/null 2>/dev/null fi }; diff --git a/usr.sbin/pc-sysinstall/backend/functions-packages.sh b/usr.sbin/pc-sysinstall/backend/functions-packages.sh index c426778289c..ee4192870d7 100755 --- a/usr.sbin/pc-sysinstall/backend/functions-packages.sh +++ b/usr.sbin/pc-sysinstall/backend/functions-packages.sh @@ -45,9 +45,11 @@ get_package_index_by_ftp() then INDEX_FILE="${INDEX_FILE}.bz2" USE_BZIP2=1 + INDEX_PATH="${INDEXFILE}.bz2" + else + INDEX_PATH="${INDEXFILE}" fi - INDEX_PATH="${CONFDIR}/${INDEX_FILE}" fetch_file "${FTP_SERVER}/${INDEX_FILE}" "${INDEX_PATH}" "1" if [ -f "${INDEX_PATH}" ] && [ "${USE_BZIP2}" -eq "1" ] then @@ -57,17 +59,18 @@ get_package_index_by_ftp() get_package_index_by_fs() { - local INDEX_FILE - - INDEX_FILE="${CDMNT}/packages/INDEX" - fetch_file "${INDEX_FILE}" "${CONFDIR}/" "0" + if [ "$INSTALLMEDIUM" = "local" ] ; then + INDEXFILE="${LOCALPATH}/packages/INDEX" + else + INDEXFILE="${CDMNT}/packages/INDEX" + fi }; get_package_index_size() { - if [ -f "${CONFDIR}/INDEX" ] + if [ -f "${INDEXFILE}" ] then - SIZE=`ls -l ${CONFDIR}/INDEX | awk '{ print $5 }'` + SIZE=`ls -l ${INDEXFILE} | awk '{ print $5 }'` else get_ftp_mirror FTPHOST="${VAL}" @@ -94,28 +97,24 @@ get_package_index() get_package_index_by_ftp "${FTPPATH}" else - get_value_from_cfg ftpHost - if [ -z "$VAL" ] - then - exit_err "ERROR: Install medium was set to ftp, but no ftpHost was provided!" - fi - - FTPHOST="${VAL}" - - get_value_from_cfg ftpDir - if [ -z "$VAL" ] - then - exit_err "ERROR: Install medium was set to ftp, but no ftpDir was provided!" - fi - - FTPDIR="${VAL}" - FTPPATH="ftp://${FTPHOST}${FTPDIR}" case "${INSTALLMEDIUM}" in - usb|dvd) get_package_index_by_fs ;; - ftp) get_package_index_by_ftp "${FTPPATH}" ;; - sftp) ;; - *) RES=1 ;; + usb|dvd|local) get_package_index_by_fs ;; + ftp) get_value_from_cfg ftpHost + if [ -z "$VAL" ]; then + exit_err "ERROR: Install medium was set to ftp, but no ftpHost was provided!" + fi + FTPHOST="${VAL}" + + get_value_from_cfg ftpDir + if [ -z "$VAL" ]; then + exit_err "ERROR: Install medium was set to ftp, but no ftpDir was provided!" + fi + FTPDIR="${VAL}" + FTPPATH="ftp://${FTPHOST}${FTPDIR}" + get_package_index_by_ftp "${FTPPATH}" ;; + sftp) ;; + *) RES=1 ;; esac fi @@ -125,10 +124,11 @@ get_package_index() parse_package_index() { + echo_log "Building package dep list.. Please wait.." INDEX_FILE="${PKGDIR}/INDEX" exec 3<&0 - exec 0<"${INDEX_FILE}" + exec 0<"${INDEXFILE}" while read -r line do @@ -257,20 +257,38 @@ get_package_name() { PACKAGE="${1}" RES=0 + local PKGPTH - INDEX_FILE="${PKGDIR}/INDEX.deps" - REGEX="^${PACKAGE}|" + # If we are on a local medium, we can parse the Latest/ directory + if [ "${INSTALLMEDIUM}" != "ftp" ] ; then + case "${INSTALLMEDIUM}" in + usb|dvd) PKGPTH="${CDMNT}/packages" ;; + *) PKGPTH="${LOCALPATH}/packages" ;; + esac + + # Check the /Latest dir for generic names, then look for specific version in All/ + if [ -e "${PKGPTH}/Latest/${PACKAGE}.${PKGEXT}" ] ; then + NAME=`ls -al ${PKGPTH}/Latest/${PACKAGE}.${PKGEXT} 2>/dev/null | cut -d '>' -f 2 | rev | cut -f1 -d'/' | rev | tr -s ' '` + else + NAME=`ls -al ${PKGPTH}/All/${PACKAGE}.${PKGEXT} 2>/dev/null | cut -d '>' -f 2 | rev | cut -f1 -d'/' | rev | tr -s ' '` + fi + export VAL="${NAME}" + else + # Doing remote fetch, we we will look up, but some generic names like + # "perl" wont work, since we don't know the default version + INDEX_FILE="${PKGDIR}/INDEX.deps" + REGEX="^${PACKAGE}|" - LINE=`grep "${REGEX}" "${INDEX_FILE}" 2>/dev/null` - NAME=`echo "${LINE}"|cut -f2 -d'|'` + LINE=`grep "${REGEX}" "${INDEX_FILE}" 2>/dev/null` + NAME=`echo "${LINE}"|cut -f2 -d'|'` - export VAL="${NAME}" + export VAL="${NAME}" + fi if [ -z "${VAL}" ] then RES=1 fi - return ${RES} }; @@ -334,7 +352,7 @@ fetch_package_by_ftp() fi FTPDIR="${VAL}" - PACKAGE="${PACKAGE}.tbz" + PACKAGE="${PACKAGE}.${PKGEXT}" FTP_SERVER="ftp://${FTPHOST}${FTPDIR}" if [ ! -f "${SAVEDIR}/${PACKAGE}" ] @@ -345,28 +363,49 @@ fetch_package_by_ftp() fi }; -fetch_package_by_fs() -{ - CATEGORY="${1}" - PACKAGE="${2}" - SAVEDIR="${3}" - - PACKAGE="${PACKAGE}.tbz" - if [ ! -f "${SAVEDIR}/${PACKAGE}" ] - then - fetch_file "${CDMNT}/packages/${CATEGORY}/${PACKAGE}" "${SAVEDIR}/" "0" - fi -}; - fetch_package() { CATEGORY="${1}" PACKAGE="${2}" SAVEDIR="${3}" + # Fetch package, but skip if installing from local media case "${INSTALLMEDIUM}" in - usb|dvd) fetch_package_by_fs "${CATEGORY}" "${PACKAGE}" "${SAVEDIR}" ;; + usb|dvd|local) return ;; ftp) fetch_package_by_ftp "${CATEGORY}" "${PACKAGE}" "${SAVEDIR}" ;; sftp) ;; esac }; + +bootstrap_pkgng() +{ + # Check if we need to boot-strap pkgng + if run_chroot_cmd "which pkg-static" >/dev/null 2>/dev/null + then + return + fi + local PKGPTH + + # Ok, lets boot-strap this sucker + echo_log "Bootstraping pkgng.." + fetch_package "Latest" "pkg" "${PKGDLDIR}" + + # Figure out real location of "pkg" package + case "${INSTALLMEDIUM}" in + usb|dvd|local) PKGPTH="${PKGTMPDIR}/Latest/pkg.${PKGEXT}" ;; + *) PKGPTH="${PKGTMPDIR}/pkg.${PKGEXT}" ;; + esac + rc_halt "pkg -c ${FSMNT} add ${PKGPTH}" ; run_chroot_cmd "pkg2ng" +} + +get_package_location() +{ + case "${INSTALLMEDIUM}" in + usb|dvd) rc_halt "mount_nullfs ${CDMNT}/packages ${FSMNT}${PKGTMPDIR}" + PKGDLDIR="${FSMNT}${PKGTMPDIR}/All" ;; + local) rc_halt "mount_nullfs ${LOCALPATH}/packages ${FSMNT}${PKGTMPDIR}" + PKGDLDIR="${FSMNT}${PKGTMPDIR}/All" ;; + *) PKGDLDIR="${FSMNT}${PKGTMPDIR}" ;; + esac + export PKGDLDIR +} From 4a99f3fcc14bedb4ec6181c2d2f76c4f4b16e296 Mon Sep 17 00:00:00 2001 From: Josh Paetzel Date: Sun, 3 Mar 2013 23:07:27 +0000 Subject: [PATCH 0568/1476] Use GNOP to force ZFS pools to 4k. Obtained from: PC-BSD --- .../backend/functions-bsdlabel.sh | 13 +++++- .../pc-sysinstall/backend/functions-disk.sh | 1 + .../backend/functions-mountdisk.sh | 8 ++-- .../pc-sysinstall/backend/functions-newfs.sh | 44 +++++++++++++++++-- usr.sbin/pc-sysinstall/backend/functions.sh | 6 ++- .../pc-sysinstall/conf/pc-sysinstall.conf | 8 ++-- 6 files changed, 66 insertions(+), 14 deletions(-) diff --git a/usr.sbin/pc-sysinstall/backend/functions-bsdlabel.sh b/usr.sbin/pc-sysinstall/backend/functions-bsdlabel.sh index 0eedfad02bf..37353d7c82c 100755 --- a/usr.sbin/pc-sysinstall/backend/functions-bsdlabel.sh +++ b/usr.sbin/pc-sysinstall/backend/functions-bsdlabel.sh @@ -62,7 +62,18 @@ get_fs_line_xvars() echo $ZFSVARS | grep -qE "^(disk|file|mirror|raidz(1|2|3)?|spare|log|cache):" 2>/dev/null if [ $? -eq 0 ] ; then ZTYPE=`echo $ZFSVARS | cut -f1 -d:` - ZFSVARS=`echo $ZFSVARS | sed "s|$ZTYPE: ||g" | sed "s|$ZTYPE:||g"` + tmpVars=`echo $ZFSVARS | sed "s|$ZTYPE: ||g" | sed "s|$ZTYPE:||g"` + ZFSVARS="" + # make sure we have a '/dev' in front of the extra devices + for i in $tmpVars + do + echo $i | grep -q '/dev/' + if [ $? -ne 0 ] ; then + ZFSVARS="$ZFSVARS /dev/${i}" + else + ZFSVARS="$ZFSVARS $i" + fi + done fi # Return the ZFS options diff --git a/usr.sbin/pc-sysinstall/backend/functions-disk.sh b/usr.sbin/pc-sysinstall/backend/functions-disk.sh index b1b815d7d93..eac10d962ad 100755 --- a/usr.sbin/pc-sysinstall/backend/functions-disk.sh +++ b/usr.sbin/pc-sysinstall/backend/functions-disk.sh @@ -33,6 +33,7 @@ is_disk() for _dsk in `sysctl -n kern.disks` do [ "$_dsk" = "${1}" ] && return 0 + [ "/dev/$_dsk" = "${1}" ] && return 0 done return 1 diff --git a/usr.sbin/pc-sysinstall/backend/functions-mountdisk.sh b/usr.sbin/pc-sysinstall/backend/functions-mountdisk.sh index c90c0580d56..e9eb148a2b4 100755 --- a/usr.sbin/pc-sysinstall/backend/functions-mountdisk.sh +++ b/usr.sbin/pc-sysinstall/backend/functions-mountdisk.sh @@ -149,12 +149,12 @@ mount_all_filesystems() for PART in `ls ${PARTDIR}` do PARTDEV=`echo $PART | sed 's|-|/|g'` - if [ ! -e "${PARTDEV}" ] + PARTFS="`cat ${PARTDIR}/${PART} | cut -d '#' -f 1`" + if [ ! -e "${PARTDEV}" -a "${PARTFS}" != "ZFS" ] then exit_err "ERROR: The partition ${PARTDEV} does not exist. Failure in bsdlabel?" fi - PARTFS="`cat ${PARTDIR}/${PART} | cut -d '#' -f 1`" PARTMNT="`cat ${PARTDIR}/${PART} | cut -d '#' -f 2`" PARTENC="`cat ${PARTDIR}/${PART} | cut -d '#' -f 3`" @@ -186,12 +186,12 @@ mount_all_filesystems() for PART in `ls ${PARTDIR}` do PARTDEV=`echo $PART | sed 's|-|/|g'` - if [ ! -e "${PARTDEV}" ] + PARTFS="`cat ${PARTDIR}/${PART} | cut -d '#' -f 1`" + if [ ! -e "${PARTDEV}" -a "${PARTFS}" != "ZFS" ] then exit_err "ERROR: The partition ${PARTDEV} does not exist. Failure in bsdlabel?" fi - PARTFS="`cat ${PARTDIR}/${PART} | cut -d '#' -f 1`" PARTMNT="`cat ${PARTDIR}/${PART} | cut -d '#' -f 2`" PARTENC="`cat ${PARTDIR}/${PART} | cut -d '#' -f 3`" diff --git a/usr.sbin/pc-sysinstall/backend/functions-newfs.sh b/usr.sbin/pc-sysinstall/backend/functions-newfs.sh index 2ab4a832802..f8664f05f4b 100755 --- a/usr.sbin/pc-sysinstall/backend/functions-newfs.sh +++ b/usr.sbin/pc-sysinstall/backend/functions-newfs.sh @@ -60,18 +60,56 @@ setup_zfs_filesystem() fi done - # Check if we have some custom zpool arguments and use them if so if [ ! -z "${ZPOOLOPTS}" ] ; then - rc_halt "zpool create -m none -f ${ZPOOLNAME} ${ZPOOLOPTS}" + # Sort through devices and run gnop on them + local gnopDev="" + local newOpts="" + for i in $ZPOOLOPTS + do + echo "$i" | grep -q '/dev/' + if [ $? -eq 0 ] ; then + rc_halt "gnop create -S 4096 ${i}" + gnopDev="$gnopDev $i" + newOpts="$newOpts ${i}.nop" + else + newOpts="$newOpts $i" + fi + done + + echo_log "Creating zpool ${ZPOOLNAME} with $newOpts" + rc_halt "zpool create -m none -f ${ZPOOLNAME} ${newOpts}" + + # Export the pool + rc_halt "zpool export ${ZPOOLNAME}" + + # Destroy the gnop devices + for i in $gnopDev + do + rc_halt "gnop destroy ${i}.nop" + done + + # And lastly re-import the pool + rc_halt "zpool import ${ZPOOLNAME}" else + # Lets do our pseudo-4k drive + rc_halt "gnop create -S 4096 ${PART}${EXT}" + # No zpool options, create pool on single device - rc_halt "zpool create -m none -f ${ZPOOLNAME} ${PART}${EXT}" + echo_log "Creating zpool ${ZPOOLNAME} on ${PART}${EXT}" + rc_halt "zpool create -m none -f ${ZPOOLNAME} ${PART}${EXT}.nop" + + # Finish up the gnop 4k trickery + rc_halt "zpool export ${ZPOOLNAME}" + rc_halt "gnop destroy ${PART}${EXT}.nop" + rc_halt "zpool import ${ZPOOLNAME}" fi # Disable atime for this zfs partition, speed increase rc_nohalt "zfs set atime=off ${ZPOOLNAME}" + + }; # Runs newfs on all the partiions which we've setup with bsdlabel diff --git a/usr.sbin/pc-sysinstall/backend/functions.sh b/usr.sbin/pc-sysinstall/backend/functions.sh index 33d0005e408..a2d039b5342 100755 --- a/usr.sbin/pc-sysinstall/backend/functions.sh +++ b/usr.sbin/pc-sysinstall/backend/functions.sh @@ -277,7 +277,11 @@ get_zpool_name() while : do NEWNAME="${BASENAME}${NUM}" - zpool import | grep -qw "${NEWNAME}" || break + zpool list | grep -qw "${NEWNAME}" + local chk1=$? + zpool import | grep -qw "${NEWNAME}" + local chk2=$? + if [ $chk1 -eq 1 -a $chk2 -eq 1 ] ; then break ; fi NUM=$((NUM+1)) done diff --git a/usr.sbin/pc-sysinstall/conf/pc-sysinstall.conf b/usr.sbin/pc-sysinstall/conf/pc-sysinstall.conf index 5d682dc4643..9c01e315c21 100644 --- a/usr.sbin/pc-sysinstall/conf/pc-sysinstall.conf +++ b/usr.sbin/pc-sysinstall/conf/pc-sysinstall.conf @@ -5,11 +5,9 @@ TMPDIR="/tmp/.pc-sysinstall" export TMPDIR -if [ ! -d "${TMPDIR}" ] -then - mkdir -p ${TMPDIR} - chmod 777 ${TMPDIR} -fi +# Create a fresh TMPDIR +if [ -d "${TMPDIR}" -a "$TMPDIR" != '/' ]; then rm -rf ${TMPDIR}; fi +mkdir -p ${TMPDIR} # Set our temp directory for storing partition information PARTDIR="${TMPDIR}/part-info" From a6157c3d612b2cad42fdc14f5112a0ca4d814455 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sun, 3 Mar 2013 23:23:35 +0000 Subject: [PATCH 0569/1476] Plug memory leaks in file descriptors passing. --- sys/kern/kern_descrip.c | 2 +- sys/kern/uipc_usrreq.c | 3 ++- sys/sys/filedesc.h | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index b146bab5ac7..704f0f33bde 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -1397,7 +1397,7 @@ filecaps_copy(const struct filecaps *src, struct filecaps *dst) /* * Move filecaps structure to the new place and clear the old place. */ -static void +void filecaps_move(struct filecaps *src, struct filecaps *dst) { diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index 1da80e0cedb..e36cffdbc5c 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -1686,6 +1686,7 @@ unp_freerights(struct filedescent *fde, int fdcount) for (i = 0; i < fdcount; i++, fde++) { fp = fde->fde_file; + filecaps_free(&fdep->fde_caps); bzero(fde, sizeof(*fde)); unp_discard(fp); } @@ -1760,7 +1761,7 @@ unp_externalize(struct mbuf *control, struct mbuf **controlp) panic("unp_externalize fdalloc failed"); fde = &fdesc->fd_ofiles[f]; fde->fde_file = fdep->fde_file; - filecaps_copy(&fdep->fde_caps, &fde->fde_caps); + filecaps_move(&fdep->fde_caps, &fde->fde_caps); unp_externalize_fp(fde->fde_file); *fdp = f; } diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h index f3e3a0976b7..d9fe0e0d8b4 100644 --- a/sys/sys/filedesc.h +++ b/sys/sys/filedesc.h @@ -136,6 +136,7 @@ struct thread; void filecaps_init(struct filecaps *fcaps); void filecaps_copy(const struct filecaps *src, struct filecaps *dst); +void filecaps_move(struct filecaps *src, struct filecaps *dst); void filecaps_free(struct filecaps *fcaps); int closef(struct file *fp, struct thread *td); From 5f39e565811aef14238d3782c8ea9ffe27e08f73 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Sun, 3 Mar 2013 23:25:45 +0000 Subject: [PATCH 0570/1476] Use dedicated malloc type for filecaps-related data, so we can detect any memory leaks easier. --- sys/kern/kern_descrip.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index 704f0f33bde..1475ea33444 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -104,6 +104,7 @@ static MALLOC_DEFINE(M_FILEDESC, "filedesc", "Open file descriptor table"); static MALLOC_DEFINE(M_FILEDESC_TO_LEADER, "filedesc_to_leader", "file desc to leader structures"); static MALLOC_DEFINE(M_SIGIO, "sigio", "sigio structures"); +MALLOC_DEFINE(M_FILECAPS, "filecaps", "descriptor capabilities"); MALLOC_DECLARE(M_FADVISE); @@ -1389,7 +1390,7 @@ filecaps_copy(const struct filecaps *src, struct filecaps *dst) ("fc_ioctls != NULL, but fc_nioctls=%hd", src->fc_nioctls)); size = sizeof(src->fc_ioctls[0]) * src->fc_nioctls; - dst->fc_ioctls = malloc(size, M_TEMP, M_WAITOK); + dst->fc_ioctls = malloc(size, M_FILECAPS, M_WAITOK); bcopy(src->fc_ioctls, dst->fc_ioctls, size); } } @@ -1425,7 +1426,7 @@ void filecaps_free(struct filecaps *fcaps) { - free(fcaps->fc_ioctls, M_TEMP); + free(fcaps->fc_ioctls, M_FILECAPS); bzero(fcaps, sizeof(*fcaps)); } From 02a50482f806730d8afb6c2c0cc60e3c661b1ea4 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Sun, 3 Mar 2013 23:26:17 +0000 Subject: [PATCH 0571/1476] Import libyaml 0.1.4 into vendor --- LICENSE | 19 + Makefile.am | 18 + Makefile.in | 782 + README | 27 + aclocal.m4 | 8917 +++++++++++ config.h.in | 80 + config/config.guess | 1502 ++ config/config.sub | 1714 ++ config/depcomp | 630 + config/install-sh | 520 + config/ltmain.sh | 8413 ++++++++++ config/missing | 376 + configure | 13149 ++++++++++++++++ configure.ac | 73 + doc/doxygen.cfg | 222 + doc/html/annotated.html | 51 + doc/html/bc_s.png | Bin 0 -> 677 bytes doc/html/classes.html | 41 + doc/html/closed.png | Bin 0 -> 126 bytes doc/html/doxygen.css | 656 + doc/html/doxygen.png | Bin 0 -> 3942 bytes doc/html/files.html | 40 + doc/html/functions.html | 91 + doc/html/functions_0x62.html | 84 + doc/html/functions_0x63.html | 87 + doc/html/functions_0x64.html | 83 + doc/html/functions_0x65.html | 110 + doc/html/functions_0x66.html | 79 + doc/html/functions_0x68.html | 80 + doc/html/functions_0x69.html | 92 + doc/html/functions_0x6b.html | 71 + doc/html/functions_0x6c.html | 88 + doc/html/functions_0x6d.html | 96 + doc/html/functions_0x6e.html | 71 + doc/html/functions_0x6f.html | 80 + doc/html/functions_0x70.html | 100 + doc/html/functions_0x71.html | 71 + doc/html/functions_0x72.html | 87 + doc/html/functions_0x73.html | 163 + doc/html/functions_0x74.html | 115 + doc/html/functions_0x75.html | 71 + doc/html/functions_0x76.html | 80 + doc/html/functions_0x77.html | 77 + doc/html/functions_vars.html | 91 + doc/html/functions_vars_0x62.html | 84 + doc/html/functions_vars_0x63.html | 87 + doc/html/functions_vars_0x64.html | 83 + doc/html/functions_vars_0x65.html | 110 + doc/html/functions_vars_0x66.html | 79 + doc/html/functions_vars_0x68.html | 80 + doc/html/functions_vars_0x69.html | 92 + doc/html/functions_vars_0x6b.html | 71 + doc/html/functions_vars_0x6c.html | 88 + doc/html/functions_vars_0x6d.html | 96 + doc/html/functions_vars_0x6e.html | 71 + doc/html/functions_vars_0x6f.html | 80 + doc/html/functions_vars_0x70.html | 100 + doc/html/functions_vars_0x71.html | 71 + doc/html/functions_vars_0x72.html | 87 + doc/html/functions_vars_0x73.html | 163 + doc/html/functions_vars_0x74.html | 115 + doc/html/functions_vars_0x75.html | 71 + doc/html/functions_vars_0x76.html | 80 + doc/html/functions_vars_0x77.html | 77 + doc/html/globals.html | 667 + doc/html/globals_defs.html | 81 + doc/html/globals_enum.html | 78 + doc/html/globals_eval.html | 373 + doc/html/globals_func.html | 196 + doc/html/globals_type.html | 126 + doc/html/group__basic.html | 320 + doc/html/group__emitter.html | 819 + doc/html/group__events.html | 664 + doc/html/group__export.html | 60 + doc/html/group__nodes.html | 795 + doc/html/group__parser.html | 606 + doc/html/group__styles.html | 222 + doc/html/group__tokens.html | 246 + doc/html/group__version.html | 106 + doc/html/index.html | 31 + doc/html/modules.html | 42 + doc/html/nav_f.png | Bin 0 -> 159 bytes doc/html/nav_h.png | Bin 0 -> 97 bytes doc/html/open.png | Bin 0 -> 118 bytes doc/html/structyaml__alias__data__s.html | 108 + doc/html/structyaml__document__s.html | 235 + doc/html/structyaml__emitter__s.html | 1300 ++ doc/html/structyaml__event__s.html | 496 + doc/html/structyaml__mark__s.html | 108 + doc/html/structyaml__node__pair__s.html | 91 + doc/html/structyaml__node__s.html | 420 + doc/html/structyaml__parser__s.html | 1229 ++ doc/html/structyaml__simple__key__s.html | 97 + doc/html/structyaml__tag__directive__s.html | 91 + doc/html/structyaml__token__s.html | 413 + .../structyaml__version__directive__s.html | 91 + doc/html/tab_a.png | Bin 0 -> 140 bytes doc/html/tab_b.png | Bin 0 -> 178 bytes doc/html/tab_h.png | Bin 0 -> 192 bytes doc/html/tab_s.png | Bin 0 -> 189 bytes doc/html/tabs.css | 59 + doc/html/yaml_8h.html | 525 + include/Makefile.am | 17 + include/Makefile.in | 470 + include/yaml.h | 1971 +++ src/Makefile.am | 4 + src/Makefile.in | 529 + src/api.c | 1392 ++ src/dumper.c | 394 + src/emitter.c | 2329 +++ src/loader.c | 432 + src/parser.c | 1374 ++ src/reader.c | 465 + src/scanner.c | 3570 +++++ src/writer.c | 141 + src/yaml_private.h | 640 + tests/Makefile.am | 8 + tests/Makefile.in | 672 + tests/example-deconstructor-alt.c | 800 + tests/example-deconstructor.c | 1130 ++ tests/example-reformatter-alt.c | 217 + tests/example-reformatter.c | 202 + tests/run-dumper.c | 311 + tests/run-emitter.c | 327 + tests/run-loader.c | 63 + tests/run-parser.c | 63 + tests/run-scanner.c | 63 + tests/test-reader.c | 354 + tests/test-version.c | 29 + win32/Makefile.am | 24 + win32/Makefile.in | 374 + win32/config.h | 4 + win32/vc6/example_deconstructor.dsp | 102 + win32/vc6/example_deconstructor_alt.dsp | 102 + win32/vc6/example_reformatter.dsp | 102 + win32/vc6/example_reformatter_alt.dsp | 102 + win32/vc6/libyaml.dsw | 206 + win32/vc6/run_dumper.dsp | 102 + win32/vc6/run_emitter.dsp | 102 + win32/vc6/run_loader.dsp | 102 + win32/vc6/run_parser.dsp | 102 + win32/vc6/run_scanner.dsp | 102 + win32/vc6/test_reader.dsp | 102 + win32/vc6/test_version.dsp | 102 + win32/vc6/yaml.dsp | 136 + win32/vc6/yamldll.dsp | 147 + win32/vs2003/example_deconstructor.vcproj | 134 + win32/vs2003/example_deconstructor_alt.vcproj | 134 + win32/vs2003/example_reformatter.vcproj | 134 + win32/vs2003/example_reformatter_alt.vcproj | 134 + win32/vs2003/libyaml.sln | 128 + win32/vs2003/run_dumper.vcproj | 134 + win32/vs2003/run_emitter.vcproj | 134 + win32/vs2003/run_loader.vcproj | 134 + win32/vs2003/run_parser.vcproj | 134 + win32/vs2003/run_scanner.vcproj | 134 + win32/vs2003/test_reader.vcproj | 134 + win32/vs2003/test_version.vcproj | 134 + win32/vs2003/yaml.vcproj | 149 + win32/vs2003/yamldll.vcproj | 166 + win32/vs2008/example_deconstructor.vcproj | 201 + win32/vs2008/example_deconstructor_alt.vcproj | 201 + win32/vs2008/example_reformatter.vcproj | 201 + win32/vs2008/example_reformatter_alt.vcproj | 201 + win32/vs2008/libyaml.sln | 124 + win32/vs2008/run_dumper.vcproj | 201 + win32/vs2008/run_emitter.vcproj | 201 + win32/vs2008/run_loader.vcproj | 201 + win32/vs2008/run_parser.vcproj | 201 + win32/vs2008/run_scanner.vcproj | 201 + win32/vs2008/test_reader.vcproj | 201 + win32/vs2008/test_version.vcproj | 201 + win32/vs2008/yaml.vcproj | 215 + win32/vs2008/yamldll.vcproj | 243 + yaml-0.1.pc.in | 10 + 175 files changed, 76377 insertions(+) create mode 100644 LICENSE create mode 100644 Makefile.am create mode 100644 Makefile.in create mode 100644 README create mode 100644 aclocal.m4 create mode 100644 config.h.in create mode 100755 config/config.guess create mode 100755 config/config.sub create mode 100755 config/depcomp create mode 100755 config/install-sh create mode 100755 config/ltmain.sh create mode 100755 config/missing create mode 100755 configure create mode 100644 configure.ac create mode 100644 doc/doxygen.cfg create mode 100644 doc/html/annotated.html create mode 100644 doc/html/bc_s.png create mode 100644 doc/html/classes.html create mode 100644 doc/html/closed.png create mode 100644 doc/html/doxygen.css create mode 100644 doc/html/doxygen.png create mode 100644 doc/html/files.html create mode 100644 doc/html/functions.html create mode 100644 doc/html/functions_0x62.html create mode 100644 doc/html/functions_0x63.html create mode 100644 doc/html/functions_0x64.html create mode 100644 doc/html/functions_0x65.html create mode 100644 doc/html/functions_0x66.html create mode 100644 doc/html/functions_0x68.html create mode 100644 doc/html/functions_0x69.html create mode 100644 doc/html/functions_0x6b.html create mode 100644 doc/html/functions_0x6c.html create mode 100644 doc/html/functions_0x6d.html create mode 100644 doc/html/functions_0x6e.html create mode 100644 doc/html/functions_0x6f.html create mode 100644 doc/html/functions_0x70.html create mode 100644 doc/html/functions_0x71.html create mode 100644 doc/html/functions_0x72.html create mode 100644 doc/html/functions_0x73.html create mode 100644 doc/html/functions_0x74.html create mode 100644 doc/html/functions_0x75.html create mode 100644 doc/html/functions_0x76.html create mode 100644 doc/html/functions_0x77.html create mode 100644 doc/html/functions_vars.html create mode 100644 doc/html/functions_vars_0x62.html create mode 100644 doc/html/functions_vars_0x63.html create mode 100644 doc/html/functions_vars_0x64.html create mode 100644 doc/html/functions_vars_0x65.html create mode 100644 doc/html/functions_vars_0x66.html create mode 100644 doc/html/functions_vars_0x68.html create mode 100644 doc/html/functions_vars_0x69.html create mode 100644 doc/html/functions_vars_0x6b.html create mode 100644 doc/html/functions_vars_0x6c.html create mode 100644 doc/html/functions_vars_0x6d.html create mode 100644 doc/html/functions_vars_0x6e.html create mode 100644 doc/html/functions_vars_0x6f.html create mode 100644 doc/html/functions_vars_0x70.html create mode 100644 doc/html/functions_vars_0x71.html create mode 100644 doc/html/functions_vars_0x72.html create mode 100644 doc/html/functions_vars_0x73.html create mode 100644 doc/html/functions_vars_0x74.html create mode 100644 doc/html/functions_vars_0x75.html create mode 100644 doc/html/functions_vars_0x76.html create mode 100644 doc/html/functions_vars_0x77.html create mode 100644 doc/html/globals.html create mode 100644 doc/html/globals_defs.html create mode 100644 doc/html/globals_enum.html create mode 100644 doc/html/globals_eval.html create mode 100644 doc/html/globals_func.html create mode 100644 doc/html/globals_type.html create mode 100644 doc/html/group__basic.html create mode 100644 doc/html/group__emitter.html create mode 100644 doc/html/group__events.html create mode 100644 doc/html/group__export.html create mode 100644 doc/html/group__nodes.html create mode 100644 doc/html/group__parser.html create mode 100644 doc/html/group__styles.html create mode 100644 doc/html/group__tokens.html create mode 100644 doc/html/group__version.html create mode 100644 doc/html/index.html create mode 100644 doc/html/modules.html create mode 100644 doc/html/nav_f.png create mode 100644 doc/html/nav_h.png create mode 100644 doc/html/open.png create mode 100644 doc/html/structyaml__alias__data__s.html create mode 100644 doc/html/structyaml__document__s.html create mode 100644 doc/html/structyaml__emitter__s.html create mode 100644 doc/html/structyaml__event__s.html create mode 100644 doc/html/structyaml__mark__s.html create mode 100644 doc/html/structyaml__node__pair__s.html create mode 100644 doc/html/structyaml__node__s.html create mode 100644 doc/html/structyaml__parser__s.html create mode 100644 doc/html/structyaml__simple__key__s.html create mode 100644 doc/html/structyaml__tag__directive__s.html create mode 100644 doc/html/structyaml__token__s.html create mode 100644 doc/html/structyaml__version__directive__s.html create mode 100644 doc/html/tab_a.png create mode 100644 doc/html/tab_b.png create mode 100644 doc/html/tab_h.png create mode 100644 doc/html/tab_s.png create mode 100644 doc/html/tabs.css create mode 100644 doc/html/yaml_8h.html create mode 100644 include/Makefile.am create mode 100644 include/Makefile.in create mode 100644 include/yaml.h create mode 100644 src/Makefile.am create mode 100644 src/Makefile.in create mode 100644 src/api.c create mode 100644 src/dumper.c create mode 100644 src/emitter.c create mode 100644 src/loader.c create mode 100644 src/parser.c create mode 100644 src/reader.c create mode 100644 src/scanner.c create mode 100644 src/writer.c create mode 100644 src/yaml_private.h create mode 100644 tests/Makefile.am create mode 100644 tests/Makefile.in create mode 100644 tests/example-deconstructor-alt.c create mode 100644 tests/example-deconstructor.c create mode 100644 tests/example-reformatter-alt.c create mode 100644 tests/example-reformatter.c create mode 100644 tests/run-dumper.c create mode 100644 tests/run-emitter.c create mode 100644 tests/run-loader.c create mode 100644 tests/run-parser.c create mode 100644 tests/run-scanner.c create mode 100644 tests/test-reader.c create mode 100644 tests/test-version.c create mode 100644 win32/Makefile.am create mode 100644 win32/Makefile.in create mode 100644 win32/config.h create mode 100644 win32/vc6/example_deconstructor.dsp create mode 100644 win32/vc6/example_deconstructor_alt.dsp create mode 100644 win32/vc6/example_reformatter.dsp create mode 100644 win32/vc6/example_reformatter_alt.dsp create mode 100644 win32/vc6/libyaml.dsw create mode 100644 win32/vc6/run_dumper.dsp create mode 100644 win32/vc6/run_emitter.dsp create mode 100644 win32/vc6/run_loader.dsp create mode 100644 win32/vc6/run_parser.dsp create mode 100644 win32/vc6/run_scanner.dsp create mode 100644 win32/vc6/test_reader.dsp create mode 100644 win32/vc6/test_version.dsp create mode 100644 win32/vc6/yaml.dsp create mode 100644 win32/vc6/yamldll.dsp create mode 100644 win32/vs2003/example_deconstructor.vcproj create mode 100644 win32/vs2003/example_deconstructor_alt.vcproj create mode 100644 win32/vs2003/example_reformatter.vcproj create mode 100644 win32/vs2003/example_reformatter_alt.vcproj create mode 100644 win32/vs2003/libyaml.sln create mode 100644 win32/vs2003/run_dumper.vcproj create mode 100644 win32/vs2003/run_emitter.vcproj create mode 100644 win32/vs2003/run_loader.vcproj create mode 100644 win32/vs2003/run_parser.vcproj create mode 100644 win32/vs2003/run_scanner.vcproj create mode 100644 win32/vs2003/test_reader.vcproj create mode 100644 win32/vs2003/test_version.vcproj create mode 100644 win32/vs2003/yaml.vcproj create mode 100644 win32/vs2003/yamldll.vcproj create mode 100644 win32/vs2008/example_deconstructor.vcproj create mode 100644 win32/vs2008/example_deconstructor_alt.vcproj create mode 100644 win32/vs2008/example_reformatter.vcproj create mode 100644 win32/vs2008/example_reformatter_alt.vcproj create mode 100644 win32/vs2008/libyaml.sln create mode 100644 win32/vs2008/run_dumper.vcproj create mode 100644 win32/vs2008/run_emitter.vcproj create mode 100644 win32/vs2008/run_loader.vcproj create mode 100644 win32/vs2008/run_parser.vcproj create mode 100644 win32/vs2008/run_scanner.vcproj create mode 100644 win32/vs2008/test_reader.vcproj create mode 100644 win32/vs2008/test_version.vcproj create mode 100644 win32/vs2008/yaml.vcproj create mode 100644 win32/vs2008/yamldll.vcproj create mode 100644 yaml-0.1.pc.in diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000000..050ced23f68 --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2006 Kirill Simonov + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 00000000000..4111fdb721a --- /dev/null +++ b/Makefile.am @@ -0,0 +1,18 @@ +## Run `./bootstrap` to generate the "Makefile.in" files in this directory and +## the "$SUBDIRS" subdirectories. + +SUBDIRS = include src . tests win32 + +EXTRA_DIST = README LICENSE doc/doxygen.cfg + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = yaml-0.1.pc + +maintainer-clean-local: + -rm -f aclocal.m4 config.h.in configure config/* + -find ${builddir} -name Makefile.in -exec rm -f '{}' ';' + +.PHONY: bootstrap +bootstrap: maintainer-clean + ./bootstrap + diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 00000000000..eec347487f1 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,782 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = . +DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(srcdir)/config.h.in \ + $(srcdir)/yaml-0.1.pc.in $(top_srcdir)/configure \ + config/config.guess config/config.sub config/depcomp \ + config/install-sh config/ltmain.sh config/missing +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = yaml-0.1.pc +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(pkgconfigdir)" +DATA = $(pkgconfig_DATA) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir dist dist-all distcheck +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + { test ! -d "$(distdir)" \ + || { find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -fr "$(distdir)"; }; } +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +DIST_ARCHIVES = $(distdir).tar.gz +GZIP_ENV = --best +distuninstallcheck_listfiles = find . -type f -print +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YAML_LT_AGE = @YAML_LT_AGE@ +YAML_LT_CURRENT = @YAML_LT_CURRENT@ +YAML_LT_RELEASE = @YAML_LT_RELEASE@ +YAML_LT_REVISION = @YAML_LT_REVISION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = include src . tests win32 +EXTRA_DIST = README LICENSE doc/doxygen.cfg +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = yaml-0.1.pc +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +am--refresh: + @: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): + +config.h: stamp-h1 + @if test ! -f $@; then \ + rm -f stamp-h1; \ + $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \ + else :; fi + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h +$(srcdir)/config.h.in: $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 +yaml-0.1.pc: $(top_builddir)/config.status $(srcdir)/yaml-0.1.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $@ + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool config.lt +install-pkgconfigDATA: $(pkgconfig_DATA) + @$(NORMAL_INSTALL) + test -z "$(pkgconfigdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ + done + +uninstall-pkgconfigDATA: + @$(NORMAL_UNINSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(pkgconfigdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(pkgconfigdir)" && rm -f $$files + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 + $(am__remove_distdir) + +dist-lzma: distdir + tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma + $(am__remove_distdir) + +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | xz -c >$(distdir).tar.xz + $(am__remove_distdir) + +dist-tarZ: distdir + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__remove_distdir) + +dist-shar: distdir + shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + $(am__remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__remove_distdir) + +dist dist-all: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lzma*) \ + lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir); chmod a+w $(distdir) + mkdir $(distdir)/_build + mkdir $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build \ + && ../configure --srcdir=.. --prefix="$$dc_install_base" \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @$(am__cd) '$(distuninstallcheck_dir)' \ + && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: check-recursive +all-am: Makefile $(DATA) config.h +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(pkgconfigdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-hdr \ + distclean-libtool distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-pkgconfigDATA + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic \ + maintainer-clean-local + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-pkgconfigDATA + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all \ + ctags-recursive install-am install-strip tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am am--refresh check check-am clean clean-generic \ + clean-libtool ctags ctags-recursive dist dist-all dist-bzip2 \ + dist-gzip dist-lzma dist-shar dist-tarZ dist-xz dist-zip \ + distcheck distclean distclean-generic distclean-hdr \ + distclean-libtool distclean-tags distcleancheck distdir \ + distuninstallcheck dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pkgconfigDATA install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic maintainer-clean-local mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-recursive uninstall uninstall-am \ + uninstall-pkgconfigDATA + + +maintainer-clean-local: + -rm -f aclocal.m4 config.h.in configure config/* + -find ${builddir} -name Makefile.in -exec rm -f '{}' ';' + +.PHONY: bootstrap +bootstrap: maintainer-clean + ./bootstrap + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/README b/README new file mode 100644 index 00000000000..d35ebcc99b4 --- /dev/null +++ b/README @@ -0,0 +1,27 @@ +LibYAML - A C library for parsing and emitting YAML. + +To build and install the library, run: +$ ./configure +$ make +# make install + +If you checked the source code from the Subversion repository, run +$ ./bootstrap +$ ./configure +$ make +# make install + +For more information, check the LibYAML homepage: +'http://pyyaml.org/wiki/LibYAML'. + +Post your questions and opinions to the YAML-Core mailing list: +'http://lists.sourceforge.net/lists/listinfo/yaml-core'. + +Submit bug reports and feature requests to the LibYAML bug tracker: +'http://pyyaml.org/newticket?component=libyaml'. + +LibYAML is written by Kirill Simonov . It is released +under the MIT license. See the file LICENSE for more details. + +This project is developed for Python Software Foundation as a part of +Google Summer of Code under the mentorship of Clark Evans. diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 00000000000..c5edfb145b8 --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,8917 @@ +# generated automatically by aclocal 1.11.1 -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.67],, +[m4_warning([this file was generated for autoconf 2.67. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically `autoreconf'.])]) + +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008 Free Software Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +m4_define([_LT_COPYING], [dnl +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008 Free Software Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is part of GNU Libtool. +# +# GNU Libtool is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, or +# obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +]) + +# serial 56 LT_INIT + + +# LT_PREREQ(VERSION) +# ------------------ +# Complain and exit if this libtool version is less that VERSION. +m4_defun([LT_PREREQ], +[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, + [m4_default([$3], + [m4_fatal([Libtool version $1 or higher is required], + 63)])], + [$2])]) + + +# _LT_CHECK_BUILDDIR +# ------------------ +# Complain if the absolute build directory name contains unusual characters +m4_defun([_LT_CHECK_BUILDDIR], +[case `pwd` in + *\ * | *\ *) + AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; +esac +]) + + +# LT_INIT([OPTIONS]) +# ------------------ +AC_DEFUN([LT_INIT], +[AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT +AC_BEFORE([$0], [LT_LANG])dnl +AC_BEFORE([$0], [LT_OUTPUT])dnl +AC_BEFORE([$0], [LTDL_INIT])dnl +m4_require([_LT_CHECK_BUILDDIR])dnl + +dnl Autoconf doesn't catch unexpanded LT_ macros by default: +m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl +m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl +dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 +dnl unless we require an AC_DEFUNed macro: +AC_REQUIRE([LTOPTIONS_VERSION])dnl +AC_REQUIRE([LTSUGAR_VERSION])dnl +AC_REQUIRE([LTVERSION_VERSION])dnl +AC_REQUIRE([LTOBSOLETE_VERSION])dnl +m4_require([_LT_PROG_LTMAIN])dnl + +dnl Parse OPTIONS +_LT_SET_OPTIONS([$0], [$1]) + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ltmain" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +_LT_SETUP + +# Only expand once: +m4_define([LT_INIT]) +])# LT_INIT + +# Old names: +AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) +AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PROG_LIBTOOL], []) +dnl AC_DEFUN([AM_PROG_LIBTOOL], []) + + +# _LT_CC_BASENAME(CC) +# ------------------- +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +m4_defun([_LT_CC_BASENAME], +[for cc_temp in $1""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` +]) + + +# _LT_FILEUTILS_DEFAULTS +# ---------------------- +# It is okay to use these file commands and assume they have been set +# sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'. +m4_defun([_LT_FILEUTILS_DEFAULTS], +[: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} +])# _LT_FILEUTILS_DEFAULTS + + +# _LT_SETUP +# --------- +m4_defun([_LT_SETUP], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +_LT_DECL([], [host_alias], [0], [The host system])dnl +_LT_DECL([], [host], [0])dnl +_LT_DECL([], [host_os], [0])dnl +dnl +_LT_DECL([], [build_alias], [0], [The build system])dnl +_LT_DECL([], [build], [0])dnl +_LT_DECL([], [build_os], [0])dnl +dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +dnl +AC_REQUIRE([AC_PROG_LN_S])dnl +test -z "$LN_S" && LN_S="ln -s" +_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl +dnl +AC_REQUIRE([LT_CMD_MAX_LEN])dnl +_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl +_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl +dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_CMD_RELOAD])dnl +m4_require([_LT_CHECK_MAGIC_METHOD])dnl +m4_require([_LT_CMD_OLD_ARCHIVE])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl + +_LT_CONFIG_LIBTOOL_INIT([ +# See if we are running on zsh, and set the options which allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi +]) +if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + +_LT_CHECK_OBJDIR + +m4_require([_LT_TAG_COMPILER])dnl +_LT_PROG_ECHO_BACKSLASH + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([["`\\]]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld="$lt_cv_prog_gnu_ld" + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + _LT_PATH_MAGIC + fi + ;; +esac + +# Use C for the default configuration in the libtool script +LT_SUPPORTED_TAG([CC]) +_LT_LANG_C_CONFIG +_LT_LANG_DEFAULT_CONFIG +_LT_CONFIG_COMMANDS +])# _LT_SETUP + + +# _LT_PROG_LTMAIN +# --------------- +# Note that this code is called both from `configure', and `config.status' +# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, +# `config.status' has no value for ac_aux_dir unless we are using Automake, +# so we pass a copy along to make sure it has a sensible value anyway. +m4_defun([_LT_PROG_LTMAIN], +[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl +_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) +ltmain="$ac_aux_dir/ltmain.sh" +])# _LT_PROG_LTMAIN + + + +# So that we can recreate a full libtool script including additional +# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS +# in macros and then make a single call at the end using the `libtool' +# label. + + +# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) +# ---------------------------------------- +# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL_INIT], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_INIT], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_INIT]) + + +# _LT_CONFIG_LIBTOOL([COMMANDS]) +# ------------------------------ +# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) + + +# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) +# ----------------------------------------------------- +m4_defun([_LT_CONFIG_SAVE_COMMANDS], +[_LT_CONFIG_LIBTOOL([$1]) +_LT_CONFIG_LIBTOOL_INIT([$2]) +]) + + +# _LT_FORMAT_COMMENT([COMMENT]) +# ----------------------------- +# Add leading comment marks to the start of each line, and a trailing +# full-stop to the whole comment if one is not present already. +m4_define([_LT_FORMAT_COMMENT], +[m4_ifval([$1], [ +m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], + [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) +)]) + + + + + +# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) +# ------------------------------------------------------------------- +# CONFIGNAME is the name given to the value in the libtool script. +# VARNAME is the (base) name used in the configure script. +# VALUE may be 0, 1 or 2 for a computed quote escaped value based on +# VARNAME. Any other value will be used directly. +m4_define([_LT_DECL], +[lt_if_append_uniq([lt_decl_varnames], [$2], [, ], + [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], + [m4_ifval([$1], [$1], [$2])]) + lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) + m4_ifval([$4], + [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) + lt_dict_add_subkey([lt_decl_dict], [$2], + [tagged?], [m4_ifval([$5], [yes], [no])])]) +]) + + +# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) +# -------------------------------------------------------- +m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) + + +# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_tag_varnames], +[_lt_decl_filter([tagged?], [yes], $@)]) + + +# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) +# --------------------------------------------------------- +m4_define([_lt_decl_filter], +[m4_case([$#], + [0], [m4_fatal([$0: too few arguments: $#])], + [1], [m4_fatal([$0: too few arguments: $#: $1])], + [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], + [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], + [lt_dict_filter([lt_decl_dict], $@)])[]dnl +]) + + +# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) +# -------------------------------------------------- +m4_define([lt_decl_quote_varnames], +[_lt_decl_filter([value], [1], $@)]) + + +# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_dquote_varnames], +[_lt_decl_filter([value], [2], $@)]) + + +# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_varnames_tagged], +[m4_assert([$# <= 2])dnl +_$0(m4_quote(m4_default([$1], [[, ]])), + m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), + m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) +m4_define([_lt_decl_varnames_tagged], +[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) + + +# lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_all_varnames], +[_$0(m4_quote(m4_default([$1], [[, ]])), + m4_if([$2], [], + m4_quote(lt_decl_varnames), + m4_quote(m4_shift($@))))[]dnl +]) +m4_define([_lt_decl_all_varnames], +[lt_join($@, lt_decl_varnames_tagged([$1], + lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl +]) + + +# _LT_CONFIG_STATUS_DECLARE([VARNAME]) +# ------------------------------------ +# Quote a variable value, and forward it to `config.status' so that its +# declaration there will have the same value as in `configure'. VARNAME +# must have a single quote delimited value for this to work. +m4_define([_LT_CONFIG_STATUS_DECLARE], +[$1='`$ECHO "X$][$1" | $Xsed -e "$delay_single_quote_subst"`']) + + +# _LT_CONFIG_STATUS_DECLARATIONS +# ------------------------------ +# We delimit libtool config variables with single quotes, so when +# we write them to config.status, we have to be sure to quote all +# embedded single quotes properly. In configure, this macro expands +# each variable declared with _LT_DECL (and _LT_TAGDECL) into: +# +# ='`$ECHO "X$" | $Xsed -e "$delay_single_quote_subst"`' +m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], +[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), + [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAGS +# ---------------- +# Output comment and list of tags supported by the script +m4_defun([_LT_LIBTOOL_TAGS], +[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl +available_tags="_LT_TAGS"dnl +]) + + +# _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) +# ----------------------------------- +# Extract the dictionary values for VARNAME (optionally with TAG) and +# expand to a commented shell variable setting: +# +# # Some comment about what VAR is for. +# visible_name=$lt_internal_name +m4_define([_LT_LIBTOOL_DECLARE], +[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], + [description])))[]dnl +m4_pushdef([_libtool_name], + m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl +m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), + [0], [_libtool_name=[$]$1], + [1], [_libtool_name=$lt_[]$1], + [2], [_libtool_name=$lt_[]$1], + [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl +m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl +]) + + +# _LT_LIBTOOL_CONFIG_VARS +# ----------------------- +# Produce commented declarations of non-tagged libtool config variables +# suitable for insertion in the LIBTOOL CONFIG section of the `libtool' +# script. Tagged libtool config variables (even for the LIBTOOL CONFIG +# section) are produced by _LT_LIBTOOL_TAG_VARS. +m4_defun([_LT_LIBTOOL_CONFIG_VARS], +[m4_foreach([_lt_var], + m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAG_VARS(TAG) +# ------------------------- +m4_define([_LT_LIBTOOL_TAG_VARS], +[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) + + +# _LT_TAGVAR(VARNAME, [TAGNAME]) +# ------------------------------ +m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) + + +# _LT_CONFIG_COMMANDS +# ------------------- +# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of +# variables for single and double quote escaping we saved from calls +# to _LT_DECL, we can put quote escaped variables declarations +# into `config.status', and then the shell code to quote escape them in +# for loops in `config.status'. Finally, any additional code accumulated +# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. +m4_defun([_LT_CONFIG_COMMANDS], +[AC_PROVIDE_IFELSE([LT_OUTPUT], + dnl If the libtool generation code has been placed in $CONFIG_LT, + dnl instead of duplicating it all over again into config.status, + dnl then we will have config.status run $CONFIG_LT later, so it + dnl needs to know what name is stored there: + [AC_CONFIG_COMMANDS([libtool], + [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], + dnl If the libtool generation code is destined for config.status, + dnl expand the accumulated commands and init code now: + [AC_CONFIG_COMMANDS([libtool], + [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) +])#_LT_CONFIG_COMMANDS + + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], +[ + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +_LT_CONFIG_STATUS_DECLARATIONS +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# Quote evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_quote_varnames); do + case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_dquote_varnames); do + case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Fix-up fallback echo if it was mangled by the above quoting rules. +case \$lt_ECHO in +*'\\\[$]0 --fallback-echo"')dnl " + lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\[$]0 --fallback-echo"\[$]/\[$]0 --fallback-echo"/'\` + ;; +esac + +_LT_OUTPUT_LIBTOOL_INIT +]) + + +# LT_OUTPUT +# --------- +# This macro allows early generation of the libtool script (before +# AC_OUTPUT is called), incase it is used in configure for compilation +# tests. +AC_DEFUN([LT_OUTPUT], +[: ${CONFIG_LT=./config.lt} +AC_MSG_NOTICE([creating $CONFIG_LT]) +cat >"$CONFIG_LT" <<_LTEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate a libtool stub with the current configuration. + +lt_cl_silent=false +SHELL=\${CONFIG_SHELL-$SHELL} +_LTEOF + +cat >>"$CONFIG_LT" <<\_LTEOF +AS_SHELL_SANITIZE +_AS_PREPARE + +exec AS_MESSAGE_FD>&1 +exec AS_MESSAGE_LOG_FD>>config.log +{ + echo + AS_BOX([Running $as_me.]) +} >&AS_MESSAGE_LOG_FD + +lt_cl_help="\ +\`$as_me' creates a local libtool stub from the current configuration, +for use in further configure time tests before the real libtool is +generated. + +Usage: $[0] [[OPTIONS]] + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + +Report bugs to ." + +lt_cl_version="\ +m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl +m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) +configured by $[0], generated by m4_PACKAGE_STRING. + +Copyright (C) 2008 Free Software Foundation, Inc. +This config.lt script is free software; the Free Software Foundation +gives unlimited permision to copy, distribute and modify it." + +while test $[#] != 0 +do + case $[1] in + --version | --v* | -V ) + echo "$lt_cl_version"; exit 0 ;; + --help | --h* | -h ) + echo "$lt_cl_help"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --quiet | --q* | --silent | --s* | -q ) + lt_cl_silent=: ;; + + -*) AC_MSG_ERROR([unrecognized option: $[1] +Try \`$[0] --help' for more information.]) ;; + + *) AC_MSG_ERROR([unrecognized argument: $[1] +Try \`$[0] --help' for more information.]) ;; + esac + shift +done + +if $lt_cl_silent; then + exec AS_MESSAGE_FD>/dev/null +fi +_LTEOF + +cat >>"$CONFIG_LT" <<_LTEOF +_LT_OUTPUT_LIBTOOL_COMMANDS_INIT +_LTEOF + +cat >>"$CONFIG_LT" <<\_LTEOF +AC_MSG_NOTICE([creating $ofile]) +_LT_OUTPUT_LIBTOOL_COMMANDS +AS_EXIT(0) +_LTEOF +chmod +x "$CONFIG_LT" + +# configure is writing to config.log, but config.lt does its own redirection, +# appending to config.log, which fails on DOS, as config.log is still kept +# open by configure. Here we exec the FD to /dev/null, effectively closing +# config.log, so it can be properly (re)opened and appended to by config.lt. +if test "$no_create" != yes; then + lt_cl_success=: + test "$silent" = yes && + lt_config_lt_args="$lt_config_lt_args --quiet" + exec AS_MESSAGE_LOG_FD>/dev/null + $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false + exec AS_MESSAGE_LOG_FD>>config.log + $lt_cl_success || AS_EXIT(1) +fi +])# LT_OUTPUT + + +# _LT_CONFIG(TAG) +# --------------- +# If TAG is the built-in tag, create an initial libtool script with a +# default configuration from the untagged config vars. Otherwise add code +# to config.status for appending the configuration named by TAG from the +# matching tagged config vars. +m4_defun([_LT_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_CONFIG_SAVE_COMMANDS([ + m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl + m4_if(_LT_TAG, [C], [ + # See if we are running on zsh, and set the options which allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + + cfgfile="${ofile}T" + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL + +# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +_LT_COPYING +_LT_LIBTOOL_TAGS + +# ### BEGIN LIBTOOL CONFIG +_LT_LIBTOOL_CONFIG_VARS +_LT_LIBTOOL_TAG_VARS +# ### END LIBTOOL CONFIG + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + _LT_PROG_LTMAIN + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + _LT_PROG_XSI_SHELLFNS + + sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +], +[cat <<_LT_EOF >> "$ofile" + +dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded +dnl in a comment (ie after a #). +# ### BEGIN LIBTOOL TAG CONFIG: $1 +_LT_LIBTOOL_TAG_VARS(_LT_TAG) +# ### END LIBTOOL TAG CONFIG: $1 +_LT_EOF +])dnl /m4_if +], +[m4_if([$1], [], [ + PACKAGE='$PACKAGE' + VERSION='$VERSION' + TIMESTAMP='$TIMESTAMP' + RM='$RM' + ofile='$ofile'], []) +])dnl /_LT_CONFIG_SAVE_COMMANDS +])# _LT_CONFIG + + +# LT_SUPPORTED_TAG(TAG) +# --------------------- +# Trace this macro to discover what tags are supported by the libtool +# --tag option, using: +# autoconf --trace 'LT_SUPPORTED_TAG:$1' +AC_DEFUN([LT_SUPPORTED_TAG], []) + + +# C support is built-in for now +m4_define([_LT_LANG_C_enabled], []) +m4_define([_LT_TAGS], []) + + +# LT_LANG(LANG) +# ------------- +# Enable libtool support for the given language if not already enabled. +AC_DEFUN([LT_LANG], +[AC_BEFORE([$0], [LT_OUTPUT])dnl +m4_case([$1], + [C], [_LT_LANG(C)], + [C++], [_LT_LANG(CXX)], + [Java], [_LT_LANG(GCJ)], + [Fortran 77], [_LT_LANG(F77)], + [Fortran], [_LT_LANG(FC)], + [Windows Resource], [_LT_LANG(RC)], + [m4_ifdef([_LT_LANG_]$1[_CONFIG], + [_LT_LANG($1)], + [m4_fatal([$0: unsupported language: "$1"])])])dnl +])# LT_LANG + + +# _LT_LANG(LANGNAME) +# ------------------ +m4_defun([_LT_LANG], +[m4_ifdef([_LT_LANG_]$1[_enabled], [], + [LT_SUPPORTED_TAG([$1])dnl + m4_append([_LT_TAGS], [$1 ])dnl + m4_define([_LT_LANG_]$1[_enabled], [])dnl + _LT_LANG_$1_CONFIG($1)])dnl +])# _LT_LANG + + +# _LT_LANG_DEFAULT_CONFIG +# ----------------------- +m4_defun([_LT_LANG_DEFAULT_CONFIG], +[AC_PROVIDE_IFELSE([AC_PROG_CXX], + [LT_LANG(CXX)], + [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) + +AC_PROVIDE_IFELSE([AC_PROG_F77], + [LT_LANG(F77)], + [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) + +AC_PROVIDE_IFELSE([AC_PROG_FC], + [LT_LANG(FC)], + [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) + +dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal +dnl pulling things in needlessly. +AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([LT_PROG_GCJ], + [LT_LANG(GCJ)], + [m4_ifdef([AC_PROG_GCJ], + [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([A][M_PROG_GCJ], + [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([LT_PROG_GCJ], + [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) + +AC_PROVIDE_IFELSE([LT_PROG_RC], + [LT_LANG(RC)], + [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) +])# _LT_LANG_DEFAULT_CONFIG + +# Obsolete macros: +AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) +AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) +AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) +AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_CXX], []) +dnl AC_DEFUN([AC_LIBTOOL_F77], []) +dnl AC_DEFUN([AC_LIBTOOL_FC], []) +dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) + + +# _LT_TAG_COMPILER +# ---------------- +m4_defun([_LT_TAG_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl +_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl +_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl +_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_TAG_COMPILER + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +m4_defun([_LT_COMPILER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +m4_defun([_LT_LINKER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* +])# _LT_LINKER_BOILERPLATE + +# _LT_REQUIRED_DARWIN_CHECKS +# ------------------------- +m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ + case $host_os in + rhapsody* | darwin*) + AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) + AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) + AC_CHECK_TOOL([LIPO], [lipo], [:]) + AC_CHECK_TOOL([OTOOL], [otool], [:]) + AC_CHECK_TOOL([OTOOL64], [otool64], [:]) + _LT_DECL([], [DSYMUTIL], [1], + [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) + _LT_DECL([], [NMEDIT], [1], + [Tool to change global to local symbols on Mac OS X]) + _LT_DECL([], [LIPO], [1], + [Tool to manipulate fat objects and archives on Mac OS X]) + _LT_DECL([], [OTOOL], [1], + [ldd/readelf like tool for Mach-O binaries on Mac OS X]) + _LT_DECL([], [OTOOL64], [1], + [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) + + AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], + [lt_cv_apple_cc_single_mod=no + if test -z "${LT_MULTI_MODULE}"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi]) + AC_CACHE_CHECK([for -exported_symbols_list linker flag], + [lt_cv_ld_exported_symbols_list], + [lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [lt_cv_ld_exported_symbols_list=yes], + [lt_cv_ld_exported_symbols_list=no]) + LDFLAGS="$save_LDFLAGS" + ]) + case $host_os in + rhapsody* | darwin1.[[012]]) + _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + 10.[[012]]*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test "$lt_cv_apple_cc_single_mod" = "yes"; then + _lt_dar_single_mod='$single_module' + fi + if test "$lt_cv_ld_exported_symbols_list" = "yes"; then + _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + if test "$DSYMUTIL" != ":"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac +]) + + +# _LT_DARWIN_LINKER_FEATURES +# -------------------------- +# Checks for linker and compiler features on darwin +m4_defun([_LT_DARWIN_LINKER_FEATURES], +[ + m4_require([_LT_REQUIRED_DARWIN_CHECKS]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_automatic, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_TAGVAR(whole_archive_flag_spec, $1)='' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" + case $cc_basename in + ifort*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test "$_lt_dar_can_shared" = "yes"; then + output_verbose_link_cmd=echo + _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + m4_if([$1], [CXX], +[ if test "$lt_cv_apple_cc_single_mod" != "yes"; then + _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" + fi +],[]) + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi +]) + +# _LT_SYS_MODULE_PATH_AIX +# ----------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +m4_defun([_LT_SYS_MODULE_PATH_AIX], +[m4_require([_LT_DECL_SED])dnl +AC_LINK_IFELSE(AC_LANG_PROGRAM,[ +lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\(.*\)$/\1/ + p + } + }' +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +fi],[]) +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi +])# _LT_SYS_MODULE_PATH_AIX + + +# _LT_SHELL_INIT(ARG) +# ------------------- +m4_define([_LT_SHELL_INIT], +[ifdef([AC_DIVERSION_NOTICE], + [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)], + [AC_DIVERT_PUSH(NOTICE)]) +$1 +AC_DIVERT_POP +])# _LT_SHELL_INIT + + +# _LT_PROG_ECHO_BACKSLASH +# ----------------------- +# Add some code to the start of the generated configure script which +# will find an echo command which doesn't interpret backslashes. +m4_defun([_LT_PROG_ECHO_BACKSLASH], +[_LT_SHELL_INIT([ +# Check that we are running under the correct shell. +SHELL=${CONFIG_SHELL-/bin/sh} + +case X$lt_ECHO in +X*--fallback-echo) + # Remove one level of quotation (which was required for Make). + ECHO=`echo "$lt_ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','` + ;; +esac + +ECHO=${lt_ECHO-echo} +if test "X[$]1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X[$]1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then + # Yippee, $ECHO works! + : +else + # Restart under the correct shell. + exec $SHELL "[$]0" --no-reexec ${1+"[$]@"} +fi + +if test "X[$]1" = X--fallback-echo; then + # used as fallback echo + shift + cat <<_LT_EOF +[$]* +_LT_EOF + exit 0 +fi + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +if test -z "$lt_ECHO"; then + if test "X${echo_test_string+set}" != Xset; then + # find a string as large as possible, as long as the shell can cope with it + for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do + # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... + if { echo_test_string=`eval $cmd`; } 2>/dev/null && + { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null + then + break + fi + done + fi + + if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && + echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + : + else + # The Solaris, AIX, and Digital Unix default echo programs unquote + # backslashes. This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # + # So, first we look for a working echo in the user's PATH. + + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for dir in $PATH /usr/ucb; do + IFS="$lt_save_ifs" + if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && + test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + ECHO="$dir/echo" + break + fi + done + IFS="$lt_save_ifs" + + if test "X$ECHO" = Xecho; then + # We didn't find a better echo, so look for alternatives. + if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' && + echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # This shell has a builtin print -r that does the trick. + ECHO='print -r' + elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } && + test "X$CONFIG_SHELL" != X/bin/ksh; then + # If we have ksh, try running configure again with it. + ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} + export ORIGINAL_CONFIG_SHELL + CONFIG_SHELL=/bin/ksh + export CONFIG_SHELL + exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"} + else + # Try using printf. + ECHO='printf %s\n' + if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && + echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # Cool, printf works + : + elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL + export CONFIG_SHELL + SHELL="$CONFIG_SHELL" + export SHELL + ECHO="$CONFIG_SHELL [$]0 --fallback-echo" + elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + ECHO="$CONFIG_SHELL [$]0 --fallback-echo" + else + # maybe with a smaller string... + prev=: + + for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do + if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null + then + break + fi + prev="$cmd" + done + + if test "$prev" != 'sed 50q "[$]0"'; then + echo_test_string=`eval $prev` + export echo_test_string + exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"} + else + # Oops. We lost completely, so just stick with echo. + ECHO=echo + fi + fi + fi + fi + fi +fi + +# Copy echo and quote the copy suitably for passing to libtool from +# the Makefile, instead of quoting the original, which is used later. +lt_ECHO=$ECHO +if test "X$lt_ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then + lt_ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo" +fi + +AC_SUBST(lt_ECHO) +]) +_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) +_LT_DECL([], [ECHO], [1], + [An echo program that does not interpret backslashes]) +])# _LT_PROG_ECHO_BACKSLASH + + +# _LT_ENABLE_LOCK +# --------------- +m4_defun([_LT_ENABLE_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AS_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '[#]line __oline__ "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +sparc*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) LD="${LD-ld} -m elf64_sparc" ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks="$enable_libtool_lock" +])# _LT_ENABLE_LOCK + + +# _LT_CMD_OLD_ARCHIVE +# ------------------- +m4_defun([_LT_CMD_OLD_ARCHIVE], +[AC_CHECK_TOOL(AR, ar, false) +test -z "$AR" && AR=ar +test -z "$AR_FLAGS" && AR_FLAGS=cru +_LT_DECL([], [AR], [1], [The archiver]) +_LT_DECL([], [AR_FLAGS], [1]) + +AC_CHECK_TOOL(STRIP, strip, :) +test -z "$STRIP" && STRIP=: +_LT_DECL([], [STRIP], [1], [A symbol stripping program]) + +AC_CHECK_TOOL(RANLIB, ranlib, :) +test -z "$RANLIB" && RANLIB=: +_LT_DECL([], [RANLIB], [1], + [Commands used to install an old-style archive]) + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi +_LT_DECL([], [old_postinstall_cmds], [2]) +_LT_DECL([], [old_postuninstall_cmds], [2]) +_LT_TAGDECL([], [old_archive_cmds], [2], + [Commands used to build an old-style archive]) +])# _LT_CMD_OLD_ARCHIVE + + +# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([_LT_COMPILER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $RM conftest* +]) + +if test x"[$]$2" = xyes; then + m4_if([$5], , :, [$5]) +else + m4_if([$6], , :, [$6]) +fi +])# _LT_COMPILER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) + + +# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------- +# Check whether the given linker option works +AC_DEFUN([_LT_LINKER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $3" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" +]) + +if test x"[$]$2" = xyes; then + m4_if([$4], , :, [$4]) +else + m4_if([$5], , :, [$5]) +fi +])# _LT_LINKER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) + + +# LT_CMD_MAX_LEN +#--------------- +AC_DEFUN([LT_CMD_MAX_LEN], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8 ; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test "X"`$SHELL [$]0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \ + = "XX$teststring$teststring"; } >/dev/null 2>&1 && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac +]) +if test -n $lt_cv_sys_max_cmd_len ; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +max_cmd_len=$lt_cv_sys_max_cmd_len +_LT_DECL([], [max_cmd_len], [0], + [What is the maximum length of a command?]) +])# LT_CMD_MAX_LEN + +# Old name: +AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) + + +# _LT_HEADER_DLFCN +# ---------------- +m4_defun([_LT_HEADER_DLFCN], +[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl +])# _LT_HEADER_DLFCN + + +# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# ---------------------------------------------------------------- +m4_defun([_LT_TRY_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test "$cross_compiling" = yes; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +[#line __oline__ "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +}] +_LT_EOF + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_TRY_DLOPEN_SELF + + +# LT_SYS_DLOPEN_SELF +# ------------------ +AC_DEFUN([LT_SYS_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen="shl_load"], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen="dlopen"], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +_LT_DECL([dlopen_support], [enable_dlopen], [0], + [Whether dlopen is supported]) +_LT_DECL([dlopen_self], [enable_dlopen_self], [0], + [Whether dlopen of programs is supported]) +_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], + [Whether dlopen of statically linked programs is supported]) +])# LT_SYS_DLOPEN_SELF + +# Old name: +AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) + + +# _LT_COMPILER_C_O([TAGNAME]) +# --------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler. +# This macro does not hard code the compiler like AC_PROG_CC_C_O. +m4_defun([_LT_COMPILER_C_O], +[m4_require([_LT_DECL_SED])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* +]) +_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], + [Does compiler simultaneously support -c and -o options?]) +])# _LT_COMPILER_C_O + + +# _LT_COMPILER_FILE_LOCKS([TAGNAME]) +# ---------------------------------- +# Check to see if we can do hard links to lock some files if needed +m4_defun([_LT_COMPILER_FILE_LOCKS], +[m4_require([_LT_ENABLE_LOCK])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_COMPILER_C_O([$1]) + +hard_links="nottested" +if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test "$hard_links" = no; then + AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) +])# _LT_COMPILER_FILE_LOCKS + + +# _LT_CHECK_OBJDIR +# ---------------- +m4_defun([_LT_CHECK_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +_LT_DECL([], [objdir], [0], + [The name of the directory that contains temporary libtool files])dnl +m4_pattern_allow([LT_OBJDIR])dnl +AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/", + [Define to the sub-directory in which libtool stores uninstalled libraries.]) +])# _LT_CHECK_OBJDIR + + +# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) +# -------------------------------------- +# Check hardcoding attributes. +m4_defun([_LT_LINKER_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || + test -n "$_LT_TAGVAR(runpath_var, $1)" || + test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then + + # We can hardcode non-existent directories. + if test "$_LT_TAGVAR(hardcode_direct, $1)" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no && + test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then + # Linking always hardcodes the temporary library directory. + _LT_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) + +if test "$_LT_TAGVAR(hardcode_action, $1)" = relink || + test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi +_LT_TAGDECL([], [hardcode_action], [0], + [How to hardcode a shared library path into an executable]) +])# _LT_LINKER_HARDCODE_LIBPATH + + +# _LT_CMD_STRIPLIB +# ---------------- +m4_defun([_LT_CMD_STRIPLIB], +[m4_require([_LT_DECL_EGREP]) +striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +_LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) +_LT_DECL([], [striplib], [1]) +])# _LT_CMD_STRIPLIB + + +# _LT_SYS_DYNAMIC_LINKER([TAG]) +# ----------------------------- +# PORTME Fill in your ld.so characteristics +m4_defun([_LT_SYS_DYNAMIC_LINKER], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_OBJDUMP])dnl +m4_require([_LT_DECL_SED])dnl +AC_MSG_CHECKING([dynamic linker characteristics]) +m4_if([$1], + [], [ +if test "$GCC" = yes; then + case $host_os in + darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; + *) lt_awk_arg="/^libraries:/" ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e 's/;/ /g'` + else + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary. + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path/$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" + else + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO $lt_tmp_lt_search_path_spec | awk ' +BEGIN {RS=" "; FS="/|\n";} { + lt_foo=""; + lt_count=0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo="/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[[lt_foo]]++; } + if (lt_freq[[lt_foo]] == 1) { print lt_foo; } +}'` + sys_lib_search_path_spec=`$ECHO $lt_search_path_spec` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix[[4-9]]*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[123]]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix[[3-9]]*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # Some binutils ld are patched to set DT_RUNPATH + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ + LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], + [shlibpath_overrides_runpath=yes])]) + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[[89]] | openbsd2.[[89]].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +fi +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" +fi + +_LT_DECL([], [variables_saved_for_relink], [1], + [Variables whose values should be saved in libtool wrapper scripts and + restored at link time]) +_LT_DECL([], [need_lib_prefix], [0], + [Do we need the "lib" prefix for modules?]) +_LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) +_LT_DECL([], [version_type], [0], [Library versioning type]) +_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) +_LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) +_LT_DECL([], [shlibpath_overrides_runpath], [0], + [Is shlibpath searched before the hard-coded library search path?]) +_LT_DECL([], [libname_spec], [1], [Format of library name prefix]) +_LT_DECL([], [library_names_spec], [1], + [[List of archive names. First name is the real one, the rest are links. + The last name is the one that the linker finds with -lNAME]]) +_LT_DECL([], [soname_spec], [1], + [[The coded name of the library, if different from the real name]]) +_LT_DECL([], [postinstall_cmds], [2], + [Command to use after installation of a shared archive]) +_LT_DECL([], [postuninstall_cmds], [2], + [Command to use after uninstallation of a shared archive]) +_LT_DECL([], [finish_cmds], [2], + [Commands used to finish a libtool library installation in a directory]) +_LT_DECL([], [finish_eval], [1], + [[As "finish_cmds", except a single script fragment to be evaled but + not shown]]) +_LT_DECL([], [hardcode_into_libs], [0], + [Whether we should hardcode library paths into libraries]) +_LT_DECL([], [sys_lib_search_path_spec], [2], + [Compile-time system search path for libraries]) +_LT_DECL([], [sys_lib_dlsearch_path_spec], [2], + [Run-time system search path for libraries]) +])# _LT_SYS_DYNAMIC_LINKER + + +# _LT_PATH_TOOL_PREFIX(TOOL) +# -------------------------- +# find a file program which can recognize shared library +AC_DEFUN([_LT_PATH_TOOL_PREFIX], +[m4_require([_LT_DECL_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="m4_if([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$1; then + lt_cv_path_MAGIC_CMD="$ac_dir/$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac]) +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +_LT_DECL([], [MAGIC_CMD], [0], + [Used to examine libraries when file_magic_cmd begins with "file"])dnl +])# _LT_PATH_TOOL_PREFIX + +# Old name: +AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) + + +# _LT_PATH_MAGIC +# -------------- +# find a file program which can recognize a shared library +m4_defun([_LT_PATH_MAGIC], +[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# _LT_PATH_MAGIC + + +# LT_PATH_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([LT_PATH_LD], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl + +AC_ARG_WITH([gnu-ld], + [AS_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test "$withval" = no || with_gnu_ld=yes], + [with_gnu_ld=no])dnl + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[[3-9]]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + +_LT_DECL([], [deplibs_check_method], [1], + [Method to check whether dependent libraries are shared objects]) +_LT_DECL([], [file_magic_cmd], [1], + [Command to use when deplibs_check_method == "file_magic"]) +])# _LT_CHECK_MAGIC_METHOD + + +# LT_PATH_NM +# ---------- +# find the pathname to a BSD- or MS-compatible name lister +AC_DEFUN([LT_PATH_NM], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + : ${lt_cv_path_NM=no} +fi]) +if test "$lt_cv_path_NM" != "no"; then + NM="$lt_cv_path_NM" +else + # Didn't find any BSD compatible name lister, look for dumpbin. + AC_CHECK_TOOLS(DUMPBIN, ["dumpbin -symbols" "link -dump -symbols"], :) + AC_SUBST([DUMPBIN]) + if test "$DUMPBIN" != ":"; then + NM="$DUMPBIN" + fi +fi +test -z "$NM" && NM=nm +AC_SUBST([NM]) +_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl + +AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], + [lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:__oline__: $ac_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:__oline__: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:__oline__: output\"" >&AS_MESSAGE_LOG_FD) + cat conftest.out >&AS_MESSAGE_LOG_FD + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest*]) +])# LT_PATH_NM + +# Old names: +AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) +AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_PROG_NM], []) +dnl AC_DEFUN([AC_PROG_NM], []) + + +# LT_LIB_M +# -------- +# check for math library +AC_DEFUN([LT_LIB_M], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM="-lm") + ;; +esac +AC_SUBST([LIBM]) +])# LT_LIB_M + +# Old name: +AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_CHECK_LIBM], []) + + +# _LT_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------- +m4_defun([_LT_COMPILER_NO_RTTI], +[m4_require([_LT_TAG_COMPILER])dnl + +_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test "$GCC" = yes; then + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + + _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], + [Compiler flag to turn off builtin functions]) +])# _LT_COMPILER_NO_RTTI + + +# _LT_CMD_GLOBAL_SYMBOLS +# ---------------------- +m4_defun([_LT_CMD_GLOBAL_SYMBOLS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([LT_PATH_NM])dnl +AC_REQUIRE([LT_PATH_LD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_TAG_COMPILER])dnl + +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) + if test "$host_cpu" = ia64; then + symcode='[[ABCDEGRST]]' + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function + # and D for any global variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK ['"\ +" {last_section=section; section=\$ 3};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ +" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ +" s[1]~/^[@?]/{print s[1], s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx]" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + nlist=conftest.nm + if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[[]] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_save_LIBS="$LIBS" + lt_save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS="$lt_save_LIBS" + CFLAGS="$lt_save_CFLAGS" + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi + +_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], + [Take the output of nm and produce a listing of raw symbols and C names]) +_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], + [Transform the output of nm in a proper C declaration]) +_LT_DECL([global_symbol_to_c_name_address], + [lt_cv_sys_global_symbol_to_c_name_address], [1], + [Transform the output of nm in a C name address pair]) +_LT_DECL([global_symbol_to_c_name_address_lib_prefix], + [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], + [Transform the output of nm in a C name address pair when lib prefix is needed]) +]) # _LT_CMD_GLOBAL_SYMBOLS + + +# _LT_COMPILER_PIC([TAGNAME]) +# --------------------------- +m4_defun([_LT_COMPILER_PIC], +[m4_require([_LT_TAG_COMPILER])dnl +_LT_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_TAGVAR(lt_prog_compiler_static, $1)= + +AC_MSG_CHECKING([for $compiler option to produce PIC]) +m4_if([$1], [CXX], [ + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix[[4-9]]*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + if test "$host_cpu" != ia64; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + ecpc* ) + # old Intel C++ for x86_64 which still supported -KPIC. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xlc* | xlC*) + # IBM XL 8.0 on PPC + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd* | netbsdelf*-gnu) + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test "$GCC" = yes; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + + hpux9* | hpux10* | hpux11*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + # old Intel for x86_64 which still supported -KPIC. + ecc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' + _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' + ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xl*) + # IBM XL C 8.0/Fortran 10.1 on PPC + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + *Sun\ F*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='' + ;; + esac + ;; + esac + ;; + + newsos6) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + rdos*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" + ;; +esac +AC_MSG_RESULT([$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) +_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], + [How to pass a linker flag through the compiler]) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], + [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], + [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], + [Additional compiler flags for building library objects]) + +# +# Check to make sure the static flag actually works. +# +wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" +_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) +_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], + [Compiler flag to prevent dynamic linking]) +])# _LT_COMPILER_PIC + + +# _LT_LINKER_SHLIBS([TAGNAME]) +# ---------------------------- +# See if the linker supports building shared libraries. +m4_defun([_LT_LINKER_SHLIBS], +[AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +m4_if([$1], [CXX], [ + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + case $host_os in + aix[[4-9]]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" + ;; + cygwin* | mingw* | cegcc*) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;/^.*[[ ]]__nm__/s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + ;; + linux* | k*bsd*-gnu) + _LT_TAGVAR(link_all_deplibs, $1)=no + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] +], [ + runpath_var= + _LT_TAGVAR(allow_undefined_flag, $1)= + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(archive_cmds, $1)= + _LT_TAGVAR(archive_expsym_cmds, $1)= + _LT_TAGVAR(compiler_needs_object, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(hardcode_automatic, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= + _LT_TAGVAR(hardcode_libdir_separator, $1)= + _LT_TAGVAR(hardcode_minus_L, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_TAGVAR(inherit_rpath, $1)=no + _LT_TAGVAR(link_all_deplibs, $1)=unknown + _LT_TAGVAR(module_cmds, $1)= + _LT_TAGVAR(module_expsym_cmds, $1)= + _LT_TAGVAR(old_archive_from_new_cmds, $1)= + _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_TAGVAR(thread_safe_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. +dnl Note also adjust exclude_expsyms for C++ above. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + linux* | k*bsd*-gnu) + _LT_TAGVAR(link_all_deplibs, $1)=no + ;; + esac + + _LT_TAGVAR(ld_shlibs, $1)=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[[3-9]]*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test "$host_os" = linux-dietlibc; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test "$tmp_diet" = no + then + tmp_addflag= + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + _LT_TAGVAR(whole_archive_flag_spec, $1)= + tmp_sharedflag='--shared' ;; + xl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + xlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' + _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then + runpath_var= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix[[4-9]]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' + + if test "$GCC" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + _LT_TAGVAR(link_all_deplibs, $1)=no + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + bsdi[[45]]*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' + _LT_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + freebsd1*) + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" + AC_LINK_IFELSE(int foo(void) {}, + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' + ) + LDFLAGS="$save_LDFLAGS" + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *nto* | *qnx*) + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + else + case $host_os in + openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + ;; + esac + fi + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' + if test "$GCC" = yes; then + wlarc='${wl}' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='${wl}' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. GCC discards it without `$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test "$GCC" = yes; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + fi + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + if test x$host_vendor = xsni; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym' + ;; + esac + fi + fi +]) +AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) +test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld + +_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl +_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl +_LT_DECL([], [extract_expsyms_cmds], [2], + [The commands to extract the exported symbol list from a shared archive]) + +# +# Do we need to explicitly link libc? +# +case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $_LT_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_MSG_CHECKING([whether -lc should be explicitly linked in]) + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) + _LT_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) + then + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + else + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + AC_MSG_RESULT([$_LT_TAGVAR(archive_cmds_need_lc, $1)]) + ;; + esac + fi + ;; +esac + +_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], + [Whether or not to add -lc for building shared libraries]) +_LT_TAGDECL([allow_libtool_libs_with_static_runtimes], + [enable_shared_with_static_runtimes], [0], + [Whether or not to disallow shared libs when runtime libs are static]) +_LT_TAGDECL([], [export_dynamic_flag_spec], [1], + [Compiler flag to allow reflexive dlopens]) +_LT_TAGDECL([], [whole_archive_flag_spec], [1], + [Compiler flag to generate shared objects directly from archives]) +_LT_TAGDECL([], [compiler_needs_object], [1], + [Whether the compiler copes with passing no objects directly]) +_LT_TAGDECL([], [old_archive_from_new_cmds], [2], + [Create an old-style archive from a shared archive]) +_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], + [Create a temporary old-style archive to link instead of a shared archive]) +_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) +_LT_TAGDECL([], [archive_expsym_cmds], [2]) +_LT_TAGDECL([], [module_cmds], [2], + [Commands used to build a loadable module if different from building + a shared archive.]) +_LT_TAGDECL([], [module_expsym_cmds], [2]) +_LT_TAGDECL([], [with_gnu_ld], [1], + [Whether we are building with GNU ld or not]) +_LT_TAGDECL([], [allow_undefined_flag], [1], + [Flag that allows shared libraries with undefined symbols to be built]) +_LT_TAGDECL([], [no_undefined_flag], [1], + [Flag that enforces no undefined symbols]) +_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], + [Flag to hardcode $libdir into a binary during linking. + This must work even if $libdir does not exist]) +_LT_TAGDECL([], [hardcode_libdir_flag_spec_ld], [1], + [[If ld is used when linking, flag to hardcode $libdir into a binary + during linking. This must work even if $libdir does not exist]]) +_LT_TAGDECL([], [hardcode_libdir_separator], [1], + [Whether we need a single "-rpath" flag with a separated argument]) +_LT_TAGDECL([], [hardcode_direct], [0], + [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes + DIR into the resulting binary]) +_LT_TAGDECL([], [hardcode_direct_absolute], [0], + [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes + DIR into the resulting binary and the resulting library dependency is + "absolute", i.e impossible to change by setting ${shlibpath_var} if the + library is relocated]) +_LT_TAGDECL([], [hardcode_minus_L], [0], + [Set to "yes" if using the -LDIR flag during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_shlibpath_var], [0], + [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_automatic], [0], + [Set to "yes" if building a shared library automatically hardcodes DIR + into the library and all subsequent libraries and executables linked + against it]) +_LT_TAGDECL([], [inherit_rpath], [0], + [Set to yes if linker adds runtime paths of dependent libraries + to runtime path list]) +_LT_TAGDECL([], [link_all_deplibs], [0], + [Whether libtool must link a program against all its dependency libraries]) +_LT_TAGDECL([], [fix_srcfile_path], [1], + [Fix the shell variable $srcfile for the compiler]) +_LT_TAGDECL([], [always_export_symbols], [0], + [Set to "yes" if exported symbols are required]) +_LT_TAGDECL([], [export_symbols_cmds], [2], + [The commands to list exported symbols]) +_LT_TAGDECL([], [exclude_expsyms], [1], + [Symbols that should not be listed in the preloaded symbols]) +_LT_TAGDECL([], [include_expsyms], [1], + [Symbols that must always be exported]) +_LT_TAGDECL([], [prelink_cmds], [2], + [Commands necessary for linking programs (against libraries) with templates]) +_LT_TAGDECL([], [file_list_spec], [1], + [Specify filename containing input files]) +dnl FIXME: Not yet implemented +dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], +dnl [Compiler flag to generate thread safe objects]) +])# _LT_LINKER_SHLIBS + + +# _LT_LANG_C_CONFIG([TAG]) +# ------------------------ +# Ensure that the configuration variables for a C compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to `libtool'. +m4_defun([_LT_LANG_C_CONFIG], +[m4_require([_LT_DECL_EGREP])dnl +lt_save_CC="$CC" +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + +_LT_TAG_COMPILER +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + LT_SYS_DLOPEN_SELF + _LT_CMD_STRIPLIB + + # Report which library types will actually be built + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[[4-9]]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_CONFIG($1) +fi +AC_LANG_POP +CC="$lt_save_CC" +])# _LT_LANG_C_CONFIG + + +# _LT_PROG_CXX +# ------------ +# Since AC_PROG_CXX is broken, in that it returns g++ if there is no c++ +# compiler, we have our own version here. +m4_defun([_LT_PROG_CXX], +[ +pushdef([AC_MSG_ERROR], [_lt_caught_CXX_error=yes]) +AC_PROG_CXX +if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_PROG_CXXCPP +else + _lt_caught_CXX_error=yes +fi +popdef([AC_MSG_ERROR]) +])# _LT_PROG_CXX + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([_LT_PROG_CXX], []) + + +# _LT_LANG_CXX_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a C++ compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to `libtool'. +m4_defun([_LT_LANG_CXX_CONFIG], +[AC_REQUIRE([_LT_PROG_CXX])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl + +AC_LANG_PUSH(C++) +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(compiler_needs_object, $1)=no +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the CXX compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_caught_CXX_error" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests + lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_LD=$LD + lt_save_GCC=$GCC + GCC=$GXX + lt_save_with_gnu_ld=$with_gnu_ld + lt_save_path_LD=$lt_cv_path_LD + if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx + else + $as_unset lt_cv_prog_gnu_ld + fi + if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX + else + $as_unset lt_cv_path_LD + fi + test -z "${LDCXX+set}" || LD=$LDCXX + CC=${CXX-"c++"} + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + # We don't want -fno-exception when compiling C++ code, so set the + # no_builtin_flag separately + if test "$GXX" = yes; then + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + else + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + fi + + if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + LT_PATH_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test "$with_gnu_ld" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | + $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' + + else + GXX=no + with_gnu_ld=no + wlarc= + fi + + # PORTME: fill in a description of your system's C++ link characteristics + AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) + _LT_TAGVAR(ld_shlibs, $1)=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aix[[4-9]]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' + + if test "$GXX" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to + # export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty + # executable. + _LT_SYS_MODULE_PATH_AIX + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared + # libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + freebsd[[12]]*) + # C++ shared libraries reported to be fairly broken before + # switch to ELF + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + freebsd-elf*) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + gnu*) + ;; + + hpux9*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' + ;; + *) + if test "$GXX" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` -o $lib' + fi + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc* | ecpc* ) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + case `$CC -V` in + *pgCC\ [[1-5]]* | *pgcpp\ [[1-5]]*) + _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | $NL2SP`"' + _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | $NL2SP`~ + $RANLIB $oldlib' + _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + ;; + *) # Version 6 will use weak symbols + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' + ;; + xl*) + # IBM XL 8.0 on PPC, with GNU ld + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='echo' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + + lynxos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + m88k*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + + *nto* | *qnx*) + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + openbsd2*) + # C++ shared libraries are fairly broken + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + fi + output_verbose_link_cmd=echo + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + case $host in + osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; + *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; + esac + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + case $host in + osf3*) + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && $ECHO "X${wl}-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + ;; + *) + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~ + $RM $lib.exp' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + case $host in + osf3*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + psos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='echo' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' + if $CC --version | $GREP -v '^2\.7' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' + fi + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + vxworks*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) + test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + + _LT_TAGVAR(GCC, $1)="$GXX" + _LT_TAGVAR(LD, $1)="$LD" + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + CC=$lt_save_CC + LDCXX=$LD + LD=$lt_save_LD + GCC=$lt_save_GCC + with_gnu_ld=$lt_save_with_gnu_ld + lt_cv_path_LDCXX=$lt_cv_path_LD + lt_cv_path_LD=$lt_save_path_LD + lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld + lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +fi # test "$_lt_caught_CXX_error" != yes + +AC_LANG_POP +])# _LT_LANG_CXX_CONFIG + + +# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) +# --------------------------------- +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +m4_defun([_LT_SYS_HIDDEN_LIBDEPS], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +# Dependencies to place before and after the object being linked: +_LT_TAGVAR(predep_objects, $1)= +_LT_TAGVAR(postdep_objects, $1)= +_LT_TAGVAR(predeps, $1)= +_LT_TAGVAR(postdeps, $1)= +_LT_TAGVAR(compiler_lib_search_path, $1)= + +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF +int a; +void foo (void) { a = 0; } +_LT_EOF +], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +_LT_EOF +], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer*4 a + a=0 + return + end +_LT_EOF +], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer a + a=0 + return + end +_LT_EOF +], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF +public class foo { + private int a; + public void bar (void) { + a = 0; + } +}; +_LT_EOF +]) +dnl Parse the compiler output and extract the necessary +dnl objects, libraries and library flags. +if AC_TRY_EVAL(ac_compile); then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + for p in `eval "$output_verbose_link_cmd"`; do + case $p in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test $p = "-L" || + test $p = "-R"; then + prev=$p + continue + else + prev= + fi + + if test "$pre_test_object_deps_done" = no; then + case $p in + -L* | -R*) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then + _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" + else + _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$_LT_TAGVAR(postdeps, $1)"; then + _LT_TAGVAR(postdeps, $1)="${prev}${p}" + else + _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}" + fi + fi + ;; + + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test "$pre_test_object_deps_done" = no; then + if test -z "$_LT_TAGVAR(predep_objects, $1)"; then + _LT_TAGVAR(predep_objects, $1)="$p" + else + _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" + fi + else + if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then + _LT_TAGVAR(postdep_objects, $1)="$p" + else + _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling $1 test program" +fi + +$RM -f confest.$objext + +# PORTME: override above test on systems where it is broken +m4_if([$1], [CXX], +[case $host_os in +interix[[3-9]]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + _LT_TAGVAR(predep_objects,$1)= + _LT_TAGVAR(postdep_objects,$1)= + _LT_TAGVAR(postdeps,$1)= + ;; + +linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + if test "$solaris_use_stlport4" != yes; then + _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' + fi + ;; + esac + ;; + +solaris*) + case $cc_basename in + CC*) + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + # Adding this requires a known-good setup of shared libraries for + # Sun compiler versions before 5.6, else PIC objects from an old + # archive will be linked into the output, leading to subtle bugs. + if test "$solaris_use_stlport4" != yes; then + _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' + fi + ;; + esac + ;; +esac +]) + +case " $_LT_TAGVAR(postdeps, $1) " in +*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; +esac + _LT_TAGVAR(compiler_lib_search_dirs, $1)= +if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then + _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` +fi +_LT_TAGDECL([], [compiler_lib_search_dirs], [1], + [The directories searched by this compiler when creating a shared library]) +_LT_TAGDECL([], [predep_objects], [1], + [Dependencies to place before and after the objects being linked to + create a shared library]) +_LT_TAGDECL([], [postdep_objects], [1]) +_LT_TAGDECL([], [predeps], [1]) +_LT_TAGDECL([], [postdeps], [1]) +_LT_TAGDECL([], [compiler_lib_search_path], [1], + [The library search path used internally by the compiler when linking + a shared library]) +])# _LT_SYS_HIDDEN_LIBDEPS + + +# _LT_PROG_F77 +# ------------ +# Since AC_PROG_F77 is broken, in that it returns the empty string +# if there is no fortran compiler, we have our own version here. +m4_defun([_LT_PROG_F77], +[ +pushdef([AC_MSG_ERROR], [_lt_disable_F77=yes]) +AC_PROG_F77 +if test -z "$F77" || test "X$F77" = "Xno"; then + _lt_disable_F77=yes +fi +popdef([AC_MSG_ERROR]) +])# _LT_PROG_F77 + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([_LT_PROG_F77], []) + + +# _LT_LANG_F77_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a Fortran 77 compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_F77_CONFIG], +[AC_REQUIRE([_LT_PROG_F77])dnl +AC_LANG_PUSH(Fortran 77) + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the F77 compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_disable_F77" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC="$CC" + lt_save_GCC=$GCC + CC=${F77-"f77"} + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + GCC=$G77 + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)="$G77" + _LT_TAGVAR(LD, $1)="$LD" + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC="$lt_save_CC" +fi # test "$_lt_disable_F77" != yes + +AC_LANG_POP +])# _LT_LANG_F77_CONFIG + + +# _LT_PROG_FC +# ----------- +# Since AC_PROG_FC is broken, in that it returns the empty string +# if there is no fortran compiler, we have our own version here. +m4_defun([_LT_PROG_FC], +[ +pushdef([AC_MSG_ERROR], [_lt_disable_FC=yes]) +AC_PROG_FC +if test -z "$FC" || test "X$FC" = "Xno"; then + _lt_disable_FC=yes +fi +popdef([AC_MSG_ERROR]) +])# _LT_PROG_FC + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([_LT_PROG_FC], []) + + +# _LT_LANG_FC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for a Fortran compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_FC_CONFIG], +[AC_REQUIRE([_LT_PROG_FC])dnl +AC_LANG_PUSH(Fortran) + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for fc test sources. +ac_ext=${ac_fc_srcext-f} + +# Object file extension for compiled fc test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the FC compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_disable_FC" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC="$CC" + lt_save_GCC=$GCC + CC=${FC-"f95"} + compiler=$CC + GCC=$ac_cv_fc_compiler_gnu + + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu" + _LT_TAGVAR(LD, $1)="$LD" + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC="$lt_save_CC" +fi # test "$_lt_disable_FC" != yes + +AC_LANG_POP +])# _LT_LANG_FC_CONFIG + + +# _LT_LANG_GCJ_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Java Compiler compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_GCJ_CONFIG], +[AC_REQUIRE([LT_PROG_GCJ])dnl +AC_LANG_SAVE + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +lt_save_GCC=$GCC +GCC=yes +CC=${GCJ-"gcj"} +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)="$LD" +_LT_CC_BASENAME([$compiler]) + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds + +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC="$lt_save_CC" +])# _LT_LANG_GCJ_CONFIG + + +# _LT_LANG_RC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for the Windows resource compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_RC_CONFIG], +[AC_REQUIRE([LT_PROG_RC])dnl +AC_LANG_SAVE + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' + +# Code to be used in simple link tests +lt_simple_link_test_code="$lt_simple_compile_test_code" + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +lt_save_GCC=$GCC +GCC= +CC=${RC-"windres"} +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) +_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + +if test -n "$compiler"; then + : + _LT_CONFIG($1) +fi + +GCC=$lt_save_GCC +AC_LANG_RESTORE +CC="$lt_save_CC" +])# _LT_LANG_RC_CONFIG + + +# LT_PROG_GCJ +# ----------- +AC_DEFUN([LT_PROG_GCJ], +[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], + [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], + [AC_CHECK_TOOL(GCJ, gcj,) + test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS)])])[]dnl +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_GCJ], []) + + +# LT_PROG_RC +# ---------- +AC_DEFUN([LT_PROG_RC], +[AC_CHECK_TOOL(RC, windres,) +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_RC], []) + + +# _LT_DECL_EGREP +# -------------- +# If we don't have a new enough Autoconf to choose the best grep +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_EGREP], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_REQUIRE([AC_PROG_FGREP])dnl +test -z "$GREP" && GREP=grep +_LT_DECL([], [GREP], [1], [A grep program that handles long lines]) +_LT_DECL([], [EGREP], [1], [An ERE matcher]) +_LT_DECL([], [FGREP], [1], [A literal string matcher]) +dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too +AC_SUBST([GREP]) +]) + + +# _LT_DECL_OBJDUMP +# -------------- +# If we don't have a new enough Autoconf to choose the best objdump +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_OBJDUMP], +[AC_CHECK_TOOL(OBJDUMP, objdump, false) +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) +AC_SUBST([OBJDUMP]) +]) + + +# _LT_DECL_SED +# ------------ +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +m4_defun([_LT_DECL_SED], +[AC_PROG_SED +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" +_LT_DECL([], [SED], [1], [A sed program that does not truncate output]) +_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], + [Sed that helps us avoid accidentally triggering echo(1) options like -n]) +])# _LT_DECL_SED + +m4_ifndef([AC_PROG_SED], [ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # + +m4_defun([AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +IFS=$as_save_IFS +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f $lt_ac_sed && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test $lt_ac_count -gt 10 && break + lt_ac_count=`expr $lt_ac_count + 1` + if test $lt_ac_count -gt $lt_ac_max; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_SUBST([SED]) +AC_MSG_RESULT([$SED]) +])#AC_PROG_SED +])#m4_ifndef + +# Old name: +AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_SED], []) + + +# _LT_CHECK_SHELL_FEATURES +# ------------------------ +# Find out whether the shell is Bourne or XSI compatible, +# or has some other useful features. +m4_defun([_LT_CHECK_SHELL_FEATURES], +[AC_MSG_CHECKING([whether the shell understands some XSI constructs]) +# Try some XSI features +xsi_shell=no +( _lt_dummy="a/b/c" + test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \ + = c,a/b,, \ + && eval 'test $(( 1 + 1 )) -eq 2 \ + && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ + && xsi_shell=yes +AC_MSG_RESULT([$xsi_shell]) +_LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell']) + +AC_MSG_CHECKING([whether the shell understands "+="]) +lt_shell_append=no +( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \ + >/dev/null 2>&1 \ + && lt_shell_append=yes +AC_MSG_RESULT([$lt_shell_append]) +_LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append']) + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi +_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac +_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl +_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl +])# _LT_CHECK_SHELL_FEATURES + + +# _LT_PROG_XSI_SHELLFNS +# --------------------- +# Bourne and XSI compatible variants of some useful shell functions. +m4_defun([_LT_PROG_XSI_SHELLFNS], +[case $xsi_shell in + yes) + cat << \_LT_EOF >> "$cfgfile" + +# func_dirname file append nondir_replacement +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +func_dirname () +{ + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac +} + +# func_basename file +func_basename () +{ + func_basename_result="${1##*/}" +} + +# func_dirname_and_basename file append nondir_replacement +# perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# Implementation must be kept synchronized with func_dirname +# and func_basename. For efficiency, we do not delegate to +# those functions but instead duplicate the functionality here. +func_dirname_and_basename () +{ + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac + func_basename_result="${1##*/}" +} + +# func_stripname prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +func_stripname () +{ + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary parameter first. + func_stripname_result=${3} + func_stripname_result=${func_stripname_result#"${1}"} + func_stripname_result=${func_stripname_result%"${2}"} +} + +# func_opt_split +func_opt_split () +{ + func_opt_split_opt=${1%%=*} + func_opt_split_arg=${1#*=} +} + +# func_lo2o object +func_lo2o () +{ + case ${1} in + *.lo) func_lo2o_result=${1%.lo}.${objext} ;; + *) func_lo2o_result=${1} ;; + esac +} + +# func_xform libobj-or-source +func_xform () +{ + func_xform_result=${1%.*}.lo +} + +# func_arith arithmetic-term... +func_arith () +{ + func_arith_result=$(( $[*] )) +} + +# func_len string +# STRING may not start with a hyphen. +func_len () +{ + func_len_result=${#1} +} + +_LT_EOF + ;; + *) # Bourne compatible functions. + cat << \_LT_EOF >> "$cfgfile" + +# func_dirname file append nondir_replacement +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +func_dirname () +{ + # Extract subdirectory from the argument. + func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi +} + +# func_basename file +func_basename () +{ + func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` +} + +dnl func_dirname_and_basename +dnl A portable version of this function is already defined in general.m4sh +dnl so there is no need for it here. + +# func_stripname prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# func_strip_suffix prefix name +func_stripname () +{ + case ${2} in + .*) func_stripname_result=`$ECHO "X${3}" \ + | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "X${3}" \ + | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;; + esac +} + +# sed scripts: +my_sed_long_opt='1s/^\(-[[^=]]*\)=.*/\1/;q' +my_sed_long_arg='1s/^-[[^=]]*=//' + +# func_opt_split +func_opt_split () +{ + func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"` + func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"` +} + +# func_lo2o object +func_lo2o () +{ + func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"` +} + +# func_xform libobj-or-source +func_xform () +{ + func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[[^.]]*$/.lo/'` +} + +# func_arith arithmetic-term... +func_arith () +{ + func_arith_result=`expr "$[@]"` +} + +# func_len string +# STRING may not start with a hyphen. +func_len () +{ + func_len_result=`expr "$[1]" : ".*" 2>/dev/null || echo $max_cmd_len` +} + +_LT_EOF +esac + +case $lt_shell_append in + yes) + cat << \_LT_EOF >> "$cfgfile" + +# func_append var value +# Append VALUE to the end of shell variable VAR. +func_append () +{ + eval "$[1]+=\$[2]" +} +_LT_EOF + ;; + *) + cat << \_LT_EOF >> "$cfgfile" + +# func_append var value +# Append VALUE to the end of shell variable VAR. +func_append () +{ + eval "$[1]=\$$[1]\$[2]" +} + +_LT_EOF + ;; + esac +]) + +# Helper functions for option handling. -*- Autoconf -*- +# +# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 6 ltoptions.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) + + +# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) +# ------------------------------------------ +m4_define([_LT_MANGLE_OPTION], +[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) + + +# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) +# --------------------------------------- +# Set option OPTION-NAME for macro MACRO-NAME, and if there is a +# matching handler defined, dispatch to it. Other OPTION-NAMEs are +# saved as a flag. +m4_define([_LT_SET_OPTION], +[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl +m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), + _LT_MANGLE_DEFUN([$1], [$2]), + [m4_warning([Unknown $1 option `$2'])])[]dnl +]) + + +# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) +# ------------------------------------------------------------ +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +m4_define([_LT_IF_OPTION], +[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) + + +# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) +# ------------------------------------------------------- +# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME +# are set. +m4_define([_LT_UNLESS_OPTIONS], +[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), + [m4_define([$0_found])])])[]dnl +m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 +])[]dnl +]) + + +# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) +# ---------------------------------------- +# OPTION-LIST is a space-separated list of Libtool options associated +# with MACRO-NAME. If any OPTION has a matching handler declared with +# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about +# the unknown option and exit. +m4_defun([_LT_SET_OPTIONS], +[# Set options +m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [_LT_SET_OPTION([$1], _LT_Option)]) + +m4_if([$1],[LT_INIT],[ + dnl + dnl Simply set some default values (i.e off) if boolean options were not + dnl specified: + _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no + ]) + _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no + ]) + dnl + dnl If no reference was made to various pairs of opposing options, then + dnl we run the default mode handler for the pair. For example, if neither + dnl `shared' nor `disable-shared' was passed, we enable building of shared + dnl archives by default: + _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) + _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], + [_LT_ENABLE_FAST_INSTALL]) + ]) +])# _LT_SET_OPTIONS + + + +# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) +# ----------------------------------------- +m4_define([_LT_MANGLE_DEFUN], +[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) + + +# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) +# ----------------------------------------------- +m4_define([LT_OPTION_DEFINE], +[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl +])# LT_OPTION_DEFINE + + +# dlopen +# ------ +LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes +]) + +AU_DEFUN([AC_LIBTOOL_DLOPEN], +[_LT_SET_OPTION([LT_INIT], [dlopen]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the `dlopen' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) + + +# win32-dll +# --------- +# Declare package support for building win32 dll's. +LT_OPTION_DEFINE([LT_INIT], [win32-dll], +[enable_win32_dll=yes + +case $host in +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-cegcc*) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; +esac + +test -z "$AS" && AS=as +_LT_DECL([], [AS], [0], [Assembler program])dnl + +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [0], [DLL creation program])dnl + +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [0], [Object dumper program])dnl +])# win32-dll + +AU_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +_LT_SET_OPTION([LT_INIT], [win32-dll]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the `win32-dll' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) + + +# _LT_ENABLE_SHARED([DEFAULT]) +# ---------------------------- +# implement the --enable-shared flag, and supports the `shared' and +# `disable-shared' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +m4_define([_LT_ENABLE_SHARED], +[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([shared], + [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) + + _LT_DECL([build_libtool_libs], [enable_shared], [0], + [Whether or not to build shared libraries]) +])# _LT_ENABLE_SHARED + +LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) +]) + +AC_DEFUN([AC_DISABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], [disable-shared]) +]) + +AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_SHARED], []) +dnl AC_DEFUN([AM_DISABLE_SHARED], []) + + + +# _LT_ENABLE_STATIC([DEFAULT]) +# ---------------------------- +# implement the --enable-static flag, and support the `static' and +# `disable-static' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +m4_define([_LT_ENABLE_STATIC], +[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([static], + [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_static=]_LT_ENABLE_STATIC_DEFAULT) + + _LT_DECL([build_old_libs], [enable_static], [0], + [Whether or not to build static libraries]) +])# _LT_ENABLE_STATIC + +LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) +]) + +AC_DEFUN([AC_DISABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], [disable-static]) +]) + +AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_STATIC], []) +dnl AC_DEFUN([AM_DISABLE_STATIC], []) + + + +# _LT_ENABLE_FAST_INSTALL([DEFAULT]) +# ---------------------------------- +# implement the --enable-fast-install flag, and support the `fast-install' +# and `disable-fast-install' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +m4_define([_LT_ENABLE_FAST_INSTALL], +[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([fast-install], + [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) + +_LT_DECL([fast_install], [enable_fast_install], [0], + [Whether or not to optimize for fast installation])dnl +])# _LT_ENABLE_FAST_INSTALL + +LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) + +# Old names: +AU_DEFUN([AC_ENABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the `fast-install' option into LT_INIT's first parameter.]) +]) + +AU_DEFUN([AC_DISABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], [disable-fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the `disable-fast-install' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) +dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) + + +# _LT_WITH_PIC([MODE]) +# -------------------- +# implement the --with-pic flag, and support the `pic-only' and `no-pic' +# LT_INIT options. +# MODE is either `yes' or `no'. If omitted, it defaults to `both'. +m4_define([_LT_WITH_PIC], +[AC_ARG_WITH([pic], + [AS_HELP_STRING([--with-pic], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [pic_mode="$withval"], + [pic_mode=default]) + +test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) + +_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl +])# _LT_WITH_PIC + +LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) + +# Old name: +AU_DEFUN([AC_LIBTOOL_PICMODE], +[_LT_SET_OPTION([LT_INIT], [pic-only]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the `pic-only' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) + + +m4_define([_LTDL_MODE], []) +LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], + [m4_define([_LTDL_MODE], [nonrecursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [recursive], + [m4_define([_LTDL_MODE], [recursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [subproject], + [m4_define([_LTDL_MODE], [subproject])]) + +m4_define([_LTDL_TYPE], []) +LT_OPTION_DEFINE([LTDL_INIT], [installable], + [m4_define([_LTDL_TYPE], [installable])]) +LT_OPTION_DEFINE([LTDL_INIT], [convenience], + [m4_define([_LTDL_TYPE], [convenience])]) + +# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- +# +# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 6 ltsugar.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) + + +# lt_join(SEP, ARG1, [ARG2...]) +# ----------------------------- +# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their +# associated separator. +# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier +# versions in m4sugar had bugs. +m4_define([lt_join], +[m4_if([$#], [1], [], + [$#], [2], [[$2]], + [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) +m4_define([_lt_join], +[m4_if([$#$2], [2], [], + [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) + + +# lt_car(LIST) +# lt_cdr(LIST) +# ------------ +# Manipulate m4 lists. +# These macros are necessary as long as will still need to support +# Autoconf-2.59 which quotes differently. +m4_define([lt_car], [[$1]]) +m4_define([lt_cdr], +[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], + [$#], 1, [], + [m4_dquote(m4_shift($@))])]) +m4_define([lt_unquote], $1) + + +# lt_append(MACRO-NAME, STRING, [SEPARATOR]) +# ------------------------------------------ +# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. +# Note that neither SEPARATOR nor STRING are expanded; they are appended +# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). +# No SEPARATOR is output if MACRO-NAME was previously undefined (different +# than defined and empty). +# +# This macro is needed until we can rely on Autoconf 2.62, since earlier +# versions of m4sugar mistakenly expanded SEPARATOR but not STRING. +m4_define([lt_append], +[m4_define([$1], + m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) + + + +# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) +# ---------------------------------------------------------- +# Produce a SEP delimited list of all paired combinations of elements of +# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list +# has the form PREFIXmINFIXSUFFIXn. +# Needed until we can rely on m4_combine added in Autoconf 2.62. +m4_define([lt_combine], +[m4_if(m4_eval([$# > 3]), [1], + [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl +[[m4_foreach([_Lt_prefix], [$2], + [m4_foreach([_Lt_suffix], + ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, + [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) + + +# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) +# ----------------------------------------------------------------------- +# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited +# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. +m4_define([lt_if_append_uniq], +[m4_ifdef([$1], + [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], + [lt_append([$1], [$2], [$3])$4], + [$5])], + [lt_append([$1], [$2], [$3])$4])]) + + +# lt_dict_add(DICT, KEY, VALUE) +# ----------------------------- +m4_define([lt_dict_add], +[m4_define([$1($2)], [$3])]) + + +# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) +# -------------------------------------------- +m4_define([lt_dict_add_subkey], +[m4_define([$1($2:$3)], [$4])]) + + +# lt_dict_fetch(DICT, KEY, [SUBKEY]) +# ---------------------------------- +m4_define([lt_dict_fetch], +[m4_ifval([$3], + m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), + m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) + + +# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) +# ----------------------------------------------------------------- +m4_define([lt_if_dict_fetch], +[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], + [$5], + [$6])]) + + +# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) +# -------------------------------------------------------------- +m4_define([lt_dict_filter], +[m4_if([$5], [], [], + [lt_join(m4_quote(m4_default([$4], [[, ]])), + lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), + [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl +]) + +# ltversion.m4 -- version numbers -*- Autoconf -*- +# +# Copyright (C) 2004 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# Generated from ltversion.in. + +# serial 3017 ltversion.m4 +# This file is part of GNU Libtool + +m4_define([LT_PACKAGE_VERSION], [2.2.6b]) +m4_define([LT_PACKAGE_REVISION], [1.3017]) + +AC_DEFUN([LTVERSION_VERSION], +[macro_version='2.2.6b' +macro_revision='1.3017' +_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) +_LT_DECL(, macro_revision, 0) +]) + +# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- +# +# Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004. +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 4 lt~obsolete.m4 + +# These exist entirely to fool aclocal when bootstrapping libtool. +# +# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) +# which have later been changed to m4_define as they aren't part of the +# exported API, or moved to Autoconf or Automake where they belong. +# +# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN +# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us +# using a macro with the same name in our local m4/libtool.m4 it'll +# pull the old libtool.m4 in (it doesn't see our shiny new m4_define +# and doesn't know about Autoconf macros at all.) +# +# So we provide this file, which has a silly filename so it's always +# included after everything else. This provides aclocal with the +# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything +# because those macros already exist, or will be overwritten later. +# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. +# +# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. +# Yes, that means every name once taken will need to remain here until +# we give up compatibility with versions before 1.7, at which point +# we need to keep only those names which we still refer to. + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) + +m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) +m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) +m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) +m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) +m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) +m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) +m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) +m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) +m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) +m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) +m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) +m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) +m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) +m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) +m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) +m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) +m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) +m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) +m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) +m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) +m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) +m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) +m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) +m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) +m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) +m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) +m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) +m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) +m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) +m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) +m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) +m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) +m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) +m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) +m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) +m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) +m4_ifndef([AC_LIBTOOL_RC], [AC_DEFUN([AC_LIBTOOL_RC])]) +m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) +m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) +m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) +m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) +m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) +m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) +m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) +m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) + +# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.11' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.11.1], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.11.1])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to +# `$srcdir', `$srcdir/..', or `$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is `.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[dnl Rely on autoconf to set up CDPATH properly. +AC_PREREQ([2.50])dnl +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 9 + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ(2.52)dnl + ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 10 + +# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "GCJ", or "OBJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +ifelse([$1], CC, [depcc="$CC" am_compiler_list=], + [$1], CXX, [depcc="$CXX" am_compiler_list=], + [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], UPC, [depcc="$UPC" am_compiler_list=], + [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + am__universal=false + m4_case([$1], [CC], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac], + [CXX], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac]) + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvisualcpp | msvcmsys) + # This compiler won't grok `-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE(dependency-tracking, +[ --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +#serial 5 + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[{ + # Autoconf 2.62 quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each `.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005, 2006, 2008, 2009 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 16 + +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.62])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) + AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) +AM_MISSING_PROG(AUTOCONF, autoconf) +AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) +AM_MISSING_PROG(AUTOHEADER, autoheader) +AM_MISSING_PROG(MAKEINFO, makeinfo) +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl +AC_REQUIRE([AM_PROG_MKDIR_P])dnl +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES(CC)], + [define([AC_PROG_CC], + defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES(CXX)], + [define([AC_PROG_CXX], + defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES(OBJC)], + [define([AC_PROG_OBJC], + defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl +]) +_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl +dnl The `parallel-tests' driver may need to know about EXEEXT, so add the +dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro +dnl is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl +]) + +dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) + + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_arg=$1 +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001, 2003, 2005, 2008 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi +AC_SUBST(install_sh)]) + +# Copyright (C) 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 2 + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 4 + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from `make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi +AC_SUBST([am__include]) +AC_SUBST([am__quote]) +AC_MSG_RESULT([$_am_result]) +rm -f confinc confmf +]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 6 + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it supports --run. +# If it does, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + AC_MSG_WARN([`missing' script is too old or missing]) +fi +]) + +# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_MKDIR_P +# --------------- +# Check for `mkdir -p'. +AC_DEFUN([AM_PROG_MKDIR_P], +[AC_PREREQ([2.60])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, +dnl while keeping a definition of mkdir_p for backward compatibility. +dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. +dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of +dnl Makefile.ins that do not define MKDIR_P, so we do our own +dnl adjustment using top_builddir (which is defined more often than +dnl MKDIR_P). +AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl +case $mkdir_p in + [[\\/$]]* | ?:[[\\/]]*) ;; + */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; +esac +]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003, 2005, 2008 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 4 + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# ------------------------------ +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), 1)]) + +# _AM_SET_OPTIONS(OPTIONS) +# ---------------------------------- +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 5 + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftest.file +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);; +esac + +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + rm -f conftest.file + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT(yes)]) + +# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor `install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in `make install-strip', and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be `maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006, 2008 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 2 + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 2 + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of `v7', `ustar', or `pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. +AM_MISSING_PROG([AMTAR], [tar]) +m4_if([$1], [v7], + [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'], + [m4_case([$1], [ustar],, [pax],, + [m4_fatal([Unknown tar format])]) +AC_MSG_CHECKING([how to create a $1 tar archive]) +# Loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' +_am_tools=${am_cv_prog_tar_$1-$_am_tools} +# Do not fold the above two line into one, because Tru64 sh and +# Solaris sh will not grok spaces in the rhs of `-'. +for _am_tool in $_am_tools +do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; + do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi +done +rm -rf conftest.dir + +AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) +AC_MSG_RESULT([$am_cv_prog_tar_$1])]) +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + diff --git a/config.h.in b/config.h.in new file mode 100644 index 00000000000..183654609e3 --- /dev/null +++ b/config.h.in @@ -0,0 +1,80 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#undef LT_OBJDIR + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Version number of package */ +#undef VERSION + +/* Define the major version number. */ +#undef YAML_VERSION_MAJOR + +/* Define the minor version number. */ +#undef YAML_VERSION_MINOR + +/* Define the patch version number. */ +#undef YAML_VERSION_PATCH + +/* Define the version string. */ +#undef YAML_VERSION_STRING + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to `unsigned int' if does not define. */ +#undef size_t diff --git a/config/config.guess b/config/config.guess new file mode 100755 index 00000000000..c2246a4f7f4 --- /dev/null +++ b/config/config.guess @@ -0,0 +1,1502 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 +# Free Software Foundation, Inc. + +timestamp='2009-12-30' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner. Please send patches (context +# diff format) to and include a ChangeLog +# entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free +Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[456]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + case ${UNAME_MACHINE} in + pc98) + echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + LIBC=gnu + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-gnu + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + i386) + eval $set_cc_for_build + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + UNAME_PROCESSOR="x86_64" + fi + fi ;; + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/config/config.sub b/config/config.sub new file mode 100755 index 00000000000..c2d125724c0 --- /dev/null +++ b/config/config.sub @@ -0,0 +1,1714 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 +# Free Software Foundation, Inc. + +timestamp='2010-01-22' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted GNU ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free +Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ + uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nios | nios2 \ + | ns16k | ns32k \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e \ + | we32k \ + | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12 | picochip) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile-* | tilegx-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze) + basic_machine=microblaze-xilinx + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + # This must be matched before tile*. + tilegx*) + basic_machine=tilegx-unknown + os=-linux-gnu + ;; + tile*) + basic_machine=tile-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/config/depcomp b/config/depcomp new file mode 100755 index 00000000000..df8eea7e4ce --- /dev/null +++ b/config/depcomp @@ -0,0 +1,630 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2009-04-28.21; # UTC + +# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009 Free +# Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +case $1 in + '') + echo "$0: No command. Try \`$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by `PROGRAMS ARGS'. + object Object file output by `PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputing dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +cygpath_u="cygpath -u -f -" +if test "$depmode" = msvcmsys; then + # This is just like msvisualcpp but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u="sed s,\\\\\\\\,/,g" + depmode=msvisualcpp +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. +## Unfortunately, FreeBSD c89 acceptance of flags depends upon +## the command line argument order; so add the flags where they +## appear in depend2.am. Note that the slowdown incurred here +## affects only configure: in makefiles, %FASTDEP% shortcuts this. + for arg + do + case $arg in + -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; + *) set fnord "$@" "$arg" ;; + esac + shift # fnord + shift # $arg + done + "$@" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz +## The second -e expression handles DOS-style file names with drive letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the `deleted header file' problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. + tr ' ' ' +' < "$tmpdepfile" | +## Some versions of gcc put a space before the `:'. On the theory +## that the space means something, we add a space to the output as +## well. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like `#:fec' to the end of the + # dependency line. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ + tr ' +' ' ' >> "$depfile" + echo >> "$depfile" + + # The second pass generates a dummy entry for each header file. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts `$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.u + tmpdepfile2=$base.u + tmpdepfile3=$dir.libs/$base.u + "$@" -Wc,-M + else + tmpdepfile1=$dir$base.u + tmpdepfile2=$dir$base.u + tmpdepfile3=$dir$base.u + "$@" -M + fi + stat=$? + + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + # Each line is of the form `foo.o: dependent.h'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a tab and a space in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +icc) + # Intel's C compiler understands `-MD -MF file'. However on + # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c + # ICC 7.0 will fill foo.d with something like + # foo.o: sub/foo.c + # foo.o: sub/foo.h + # which is wrong. We want: + # sub/foo.o: sub/foo.c + # sub/foo.o: sub/foo.h + # sub/foo.c: + # sub/foo.h: + # ICC 7.1 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using \ : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | + sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp2) + # The "hp" stanza above does not work with aCC (C++) and HP's ia64 + # compilers, which have integrated preprocessors. The correct option + # to use with these is +Maked; it writes dependencies to a file named + # 'foo.d', which lands next to the object file, wherever that + # happens to be. + # Much of this is similar to the tru64 case; see comments there. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir.libs/$base.d + "$@" -Wc,+Maked + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + "$@" +Maked + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" + # Add `dependent.h:' lines. + sed -ne '2,${ + s/^ *// + s/ \\*$// + s/$/:/ + p + }' "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" "$tmpdepfile2" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in `foo.d' instead, so we check for that too. + # Subdirectories are respected. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + + if test "$libtool" = yes; then + # With Tru64 cc, shared objects can also be used to make a + # static library. This mechanism is used in libtool 1.4 series to + # handle both shared and static libraries in a single compilation. + # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. + # + # With libtool 1.5 this exception was removed, and libtool now + # generates 2 separate objects for the 2 libraries. These two + # compilations output dependencies in $dir.libs/$base.o.d and + # in $dir$base.o.d. We have to check for both files, because + # one of the two compilations can be disabled. We should prefer + # $dir$base.o.d over $dir.libs/$base.o.d because the latter is + # automatically cleaned when .libs/ is deleted, while ignoring + # the former would cause a distcleancheck panic. + tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 + tmpdepfile2=$dir$base.o.d # libtool 1.5 + tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 + tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.o.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + tmpdepfile4=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a tab and a space in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for `:' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. + "$@" $dashmflag | + sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tr ' ' ' +' < "$tmpdepfile" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no eat=no + for arg + do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + if test $eat = yes; then + eat=no + continue + fi + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -arch) + eat=yes ;; + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix=`echo "$object" | sed 's/^.*\././'` + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + sed '1,2d' "$tmpdepfile" | tr ' ' ' +' | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E | + sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | + sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + IFS=" " + for arg + do + case "$arg" in + -o) + shift + ;; + $object) + shift + ;; + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E 2>/dev/null | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" + echo " " >> "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvcmsys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/config/install-sh b/config/install-sh new file mode 100755 index 00000000000..6781b987bdb --- /dev/null +++ b/config/install-sh @@ -0,0 +1,520 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2009-04-28.21; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +nl=' +' +IFS=" "" $nl" + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +no_target_directory= + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) dst_arg=$2 + shift;; + + -T) no_target_directory=true;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + trap '(exit $?); exit' 1 2 13 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dst_arg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writeable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + -*) prefix='./';; + *) prefix='';; + esac + + eval "$initialize_posix_glob" + + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir + shift + $posix_glob set +f + IFS=$oIFS + + prefixes= + + for d + do + test -z "$d" && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && + + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/config/ltmain.sh b/config/ltmain.sh new file mode 100755 index 00000000000..7ed280bc952 --- /dev/null +++ b/config/ltmain.sh @@ -0,0 +1,8413 @@ +# Generated from ltmain.m4sh. + +# ltmain.sh (GNU libtool) 2.2.6b +# Written by Gordon Matzigkeit , 1996 + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007 2008 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, +# or obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +# Usage: $progname [OPTION]... [MODE-ARG]... +# +# Provide generalized library-building support services. +# +# --config show all configuration variables +# --debug enable verbose shell tracing +# -n, --dry-run display commands without modifying any files +# --features display basic configuration information and exit +# --mode=MODE use operation mode MODE +# --preserve-dup-deps don't remove duplicate dependency libraries +# --quiet, --silent don't print informational messages +# --tag=TAG use configuration variables from tag TAG +# -v, --verbose print informational messages (default) +# --version print version information +# -h, --help print short or long help message +# +# MODE must be one of the following: +# +# clean remove files from the build directory +# compile compile a source file into a libtool object +# execute automatically set library path, then run a program +# finish complete the installation of libtool libraries +# install install libraries or executables +# link create a library or an executable +# uninstall remove libraries from an installed directory +# +# MODE-ARGS vary depending on the MODE. +# Try `$progname --help --mode=MODE' for a more detailed description of MODE. +# +# When reporting a bug, please describe a test case to reproduce it and +# include the following information: +# +# host-triplet: $host +# shell: $SHELL +# compiler: $LTCC +# compiler flags: $LTCFLAGS +# linker: $LD (gnu? $with_gnu_ld) +# $progname: (GNU libtool) 2.2.6b Debian-2.2.6b-2ubuntu1 +# automake: $automake_version +# autoconf: $autoconf_version +# +# Report bugs to . + +PROGRAM=ltmain.sh +PACKAGE=libtool +VERSION="2.2.6b Debian-2.2.6b-2ubuntu1" +TIMESTAMP="" +package_revision=1.3017 + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# NLS nuisances: We save the old values to restore during execute mode. +# Only set LANG and LC_ALL to C if already set. +# These must not be set unconditionally because not all systems understand +# e.g. LANG=C (notably SCO). +lt_user_locale= +lt_safe_locale= +for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +do + eval "if test \"\${$lt_var+set}\" = set; then + save_$lt_var=\$$lt_var + $lt_var=C + export $lt_var + lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" + lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" + fi" +done + +$lt_unset CDPATH + + + + + +: ${CP="cp -f"} +: ${ECHO="echo"} +: ${EGREP="/bin/grep -E"} +: ${FGREP="/bin/grep -F"} +: ${GREP="/bin/grep"} +: ${LN_S="ln -s"} +: ${MAKE="make"} +: ${MKDIR="mkdir"} +: ${MV="mv -f"} +: ${RM="rm -f"} +: ${SED="/bin/sed"} +: ${SHELL="${CONFIG_SHELL-/bin/sh}"} +: ${Xsed="$SED -e 1s/^X//"} + +# Global variables: +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. + +exit_status=$EXIT_SUCCESS + +# Make sure IFS has a sensible default +lt_nl=' +' +IFS=" $lt_nl" + +dirname="s,/[^/]*$,," +basename="s,^.*/,," + +# func_dirname_and_basename file append nondir_replacement +# perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# Implementation must be kept synchronized with func_dirname +# and func_basename. For efficiency, we do not delegate to +# those functions but instead duplicate the functionality here. +func_dirname_and_basename () +{ + # Extract subdirectory from the argument. + func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi + func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` +} + +# Generated shell functions inserted here. + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath="$0" + +# The name of this program: +# In the unlikely event $progname began with a '-', it would play havoc with +# func_echo (imagine progname=-n), so we prepend ./ in that case: +func_dirname_and_basename "$progpath" +progname=$func_basename_result +case $progname in + -*) progname=./$progname ;; +esac + +# Make sure we have an absolute path for reexecution: +case $progpath in + [\\/]*|[A-Za-z]:\\*) ;; + *[\\/]*) + progdir=$func_dirname_result + progdir=`cd "$progdir" && pwd` + progpath="$progdir/$progname" + ;; + *) + save_IFS="$IFS" + IFS=: + for progdir in $PATH; do + IFS="$save_IFS" + test -x "$progdir/$progname" && break + done + IFS="$save_IFS" + test -n "$progdir" || progdir=`pwd` + progpath="$progdir/$progname" + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed="${SED}"' -e 1s/^X//' +sed_quote_subst='s/\([`"$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Re-`\' parameter expansions in output of double_quote_subst that were +# `\'-ed in input to the same. If an odd number of `\' preceded a '$' +# in input to double_quote_subst, that '$' was protected from expansion. +# Since each input `\' is now two `\'s, look for any number of runs of +# four `\'s followed by two `\'s and then a '$'. `\' that '$'. +bs='\\' +bs2='\\\\' +bs4='\\\\\\\\' +dollar='\$' +sed_double_backslash="\ + s/$bs4/&\\ +/g + s/^$bs2$dollar/$bs&/ + s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g + s/\n//g" + +# Standard options: +opt_dry_run=false +opt_help=false +opt_quiet=false +opt_verbose=false +opt_warning=: + +# func_echo arg... +# Echo program name prefixed message, along with the current mode +# name if it has been set yet. +func_echo () +{ + $ECHO "$progname${mode+: }$mode: $*" +} + +# func_verbose arg... +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $opt_verbose && func_echo ${1+"$@"} + + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} + +# func_error arg... +# Echo program name prefixed message to standard error. +func_error () +{ + $ECHO "$progname${mode+: }$mode: "${1+"$@"} 1>&2 +} + +# func_warning arg... +# Echo program name prefixed warning message to standard error. +func_warning () +{ + $opt_warning && $ECHO "$progname${mode+: }$mode: warning: "${1+"$@"} 1>&2 + + # bash bug again: + : +} + +# func_fatal_error arg... +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + func_error ${1+"$@"} + exit $EXIT_FAILURE +} + +# func_fatal_help arg... +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () +{ + func_error ${1+"$@"} + func_fatal_error "$help" +} +help="Try \`$progname --help' for more information." ## default + + +# func_grep expression filename +# Check whether EXPRESSION matches any line of FILENAME, without output. +func_grep () +{ + $GREP "$1" "$2" >/dev/null 2>&1 +} + + +# func_mkdir_p directory-path +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ + my_directory_path="$1" + my_dir_list= + + if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then + + # Protect directory names starting with `-' + case $my_directory_path in + -*) my_directory_path="./$my_directory_path" ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$my_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + my_dir_list="$my_directory_path:$my_dir_list" + + # If the last portion added has no slash in it, the list is done + case $my_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + my_directory_path=`$ECHO "X$my_directory_path" | $Xsed -e "$dirname"` + done + my_dir_list=`$ECHO "X$my_dir_list" | $Xsed -e 's,:*$,,'` + + save_mkdir_p_IFS="$IFS"; IFS=':' + for my_dir in $my_dir_list; do + IFS="$save_mkdir_p_IFS" + # mkdir can fail with a `File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$my_dir" 2>/dev/null || : + done + IFS="$save_mkdir_p_IFS" + + # Bail out if we (or some other process) failed to create a directory. + test -d "$my_directory_path" || \ + func_fatal_error "Failed to create \`$1'" + fi +} + + +# func_mktempdir [string] +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, STRING is the basename for that directory. +func_mktempdir () +{ + my_template="${TMPDIR-/tmp}/${1-$progname}" + + if test "$opt_dry_run" = ":"; then + # Return a directory name, but don't create it in dry-run mode + my_tmpdir="${my_template}-$$" + else + + # If mktemp works, use that first and foremost + my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` + + if test ! -d "$my_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + my_tmpdir="${my_template}-${RANDOM-0}$$" + + save_mktempdir_umask=`umask` + umask 0077 + $MKDIR "$my_tmpdir" + umask $save_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$my_tmpdir" || \ + func_fatal_error "cannot create temporary directory \`$my_tmpdir'" + fi + + $ECHO "X$my_tmpdir" | $Xsed +} + + +# func_quote_for_eval arg +# Aesthetically quote ARG to be evaled later. +# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT +# is double-quoted, suitable for a subsequent eval, whereas +# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters +# which are still active within double quotes backslashified. +func_quote_for_eval () +{ + case $1 in + *[\\\`\"\$]*) + func_quote_for_eval_unquoted_result=`$ECHO "X$1" | $Xsed -e "$sed_quote_subst"` ;; + *) + func_quote_for_eval_unquoted_result="$1" ;; + esac + + case $func_quote_for_eval_unquoted_result in + # Double-quote args containing shell metacharacters to delay + # word splitting, command substitution and and variable + # expansion for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" + ;; + *) + func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" + esac +} + + +# func_quote_for_expand arg +# Aesthetically quote ARG to be evaled later; same as above, +# but do not quote variable references. +func_quote_for_expand () +{ + case $1 in + *[\\\`\"]*) + my_arg=`$ECHO "X$1" | $Xsed \ + -e "$double_quote_subst" -e "$sed_double_backslash"` ;; + *) + my_arg="$1" ;; + esac + + case $my_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting and command substitution for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + my_arg="\"$my_arg\"" + ;; + esac + + func_quote_for_expand_result="$my_arg" +} + + +# func_show_eval cmd [fail_exp] +# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + my_cmd="$1" + my_fail_exp="${2-:}" + + ${opt_silent-false} || { + func_quote_for_expand "$my_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + if ${opt_dry_run-false}; then :; else + eval "$my_cmd" + my_status=$? + if test "$my_status" -eq 0; then :; else + eval "(exit $my_status); $my_fail_exp" + fi + fi +} + + +# func_show_eval_locale cmd [fail_exp] +# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () +{ + my_cmd="$1" + my_fail_exp="${2-:}" + + ${opt_silent-false} || { + func_quote_for_expand "$my_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + if ${opt_dry_run-false}; then :; else + eval "$lt_user_locale + $my_cmd" + my_status=$? + eval "$lt_safe_locale" + if test "$my_status" -eq 0; then :; else + eval "(exit $my_status); $my_fail_exp" + fi + fi +} + + + + + +# func_version +# Echo version message to standard output and exit. +func_version () +{ + $SED -n '/^# '$PROGRAM' (GNU /,/# warranty; / { + s/^# // + s/^# *$// + s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ + p + }' < "$progpath" + exit $? +} + +# func_usage +# Echo short help message to standard output and exit. +func_usage () +{ + $SED -n '/^# Usage:/,/# -h/ { + s/^# // + s/^# *$// + s/\$progname/'$progname'/ + p + }' < "$progpath" + $ECHO + $ECHO "run \`$progname --help | more' for full usage" + exit $? +} + +# func_help +# Echo long help message to standard output and exit. +func_help () +{ + $SED -n '/^# Usage:/,/# Report bugs to/ { + s/^# // + s/^# *$// + s*\$progname*'$progname'* + s*\$host*'"$host"'* + s*\$SHELL*'"$SHELL"'* + s*\$LTCC*'"$LTCC"'* + s*\$LTCFLAGS*'"$LTCFLAGS"'* + s*\$LD*'"$LD"'* + s/\$with_gnu_ld/'"$with_gnu_ld"'/ + s/\$automake_version/'"`(automake --version) 2>/dev/null |$SED 1q`"'/ + s/\$autoconf_version/'"`(autoconf --version) 2>/dev/null |$SED 1q`"'/ + p + }' < "$progpath" + exit $? +} + +# func_missing_arg argname +# Echo program name prefixed message to standard error and set global +# exit_cmd. +func_missing_arg () +{ + func_error "missing argument for $1" + exit_cmd=exit +} + +exit_cmd=: + + + + + +# Check that we have a working $ECHO. +if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X$1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t'; then + # Yippee, $ECHO works! + : +else + # Restart under the correct shell, and then maybe $ECHO will work. + exec $SHELL "$progpath" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat </dev/null 2>&1; then + taglist="$taglist $tagname" + + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac +} + +# Parse options once, thoroughly. This comes as soon as possible in +# the script to make things like `libtool --version' happen quickly. +{ + + # Shorthand for --mode=foo, only valid as the first argument + case $1 in + clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; + compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; + execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; + finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; + install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; + link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; + uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; + esac + + # Parse non-mode specific arguments: + while test "$#" -gt 0; do + opt="$1" + shift + + case $opt in + --config) func_config ;; + + --debug) preserve_args="$preserve_args $opt" + func_echo "enabling shell trace mode" + opt_debug='set -x' + $opt_debug + ;; + + -dlopen) test "$#" -eq 0 && func_missing_arg "$opt" && break + execute_dlfiles="$execute_dlfiles $1" + shift + ;; + + --dry-run | -n) opt_dry_run=: ;; + --features) func_features ;; + --finish) mode="finish" ;; + + --mode) test "$#" -eq 0 && func_missing_arg "$opt" && break + case $1 in + # Valid mode arguments: + clean) ;; + compile) ;; + execute) ;; + finish) ;; + install) ;; + link) ;; + relink) ;; + uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $opt" + exit_cmd=exit + break + ;; + esac + + mode="$1" + shift + ;; + + --preserve-dup-deps) + opt_duplicate_deps=: ;; + + --quiet|--silent) preserve_args="$preserve_args $opt" + opt_silent=: + ;; + + --verbose| -v) preserve_args="$preserve_args $opt" + opt_silent=false + ;; + + --tag) test "$#" -eq 0 && func_missing_arg "$opt" && break + preserve_args="$preserve_args $opt $1" + func_enable_tag "$1" # tagname is set here + shift + ;; + + # Separate optargs to long options: + -dlopen=*|--mode=*|--tag=*) + func_opt_split "$opt" + set dummy "$func_opt_split_opt" "$func_opt_split_arg" ${1+"$@"} + shift + ;; + + -\?|-h) func_usage ;; + --help) opt_help=: ;; + --version) func_version ;; + + -*) func_fatal_help "unrecognized option \`$opt'" ;; + + *) nonopt="$opt" + break + ;; + esac + done + + + case $host in + *cygwin* | *mingw* | *pw32* | *cegcc*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_duplicate_deps + ;; + esac + + # Having warned about all mis-specified options, bail out if + # anything was wrong. + $exit_cmd $EXIT_FAILURE +} + +# func_check_version_match +# Ensure that we are using m4 macros, and libtool script from the same +# release of libtool. +func_check_version_match () +{ + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from an older release. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + fi + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, +$progname: but the definition of this LT_INIT comes from revision $macro_revision. +$progname: You should recreate aclocal.m4 with macros from revision $package_revision +$progname: of $PACKAGE $VERSION and run autoconf again. +_LT_EOF + fi + + exit $EXIT_MISMATCH + fi +} + + +## ----------- ## +## Main. ## +## ----------- ## + +$opt_help || { + # Sanity checks first: + func_check_version_match + + if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then + func_fatal_configuration "not configured to build any kind of library" + fi + + test -z "$mode" && func_fatal_error "error: you must specify a MODE." + + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$execute_dlfiles" && test "$mode" != execute; then + func_error "unrecognized option \`-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$progname --help --mode=$mode' for more information." +} + + +# func_lalib_p file +# True iff FILE is a libtool `.la' library or `.lo' object file. +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_lalib_p () +{ + test -f "$1" && + $SED -e 4q "$1" 2>/dev/null \ + | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + +# func_lalib_unsafe_p file +# True iff FILE is a libtool `.la' library or `.lo' object file. +# This function implements the same check as func_lalib_p without +# resorting to external programs. To this end, it redirects stdin and +# closes it afterwards, without saving the original file descriptor. +# As a safety measure, use it only where a negative result would be +# fatal anyway. Works if `file' does not exist. +func_lalib_unsafe_p () +{ + lalib_p=no + if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then + for lalib_p_l in 1 2 3 4 + do + read lalib_p_line + case "$lalib_p_line" in + \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; + esac + done + exec 0<&5 5<&- + fi + test "$lalib_p" = yes +} + +# func_ltwrapper_script_p file +# True iff FILE is a libtool wrapper script +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_script_p () +{ + func_lalib_p "$1" +} + +# func_ltwrapper_executable_p file +# True iff FILE is a libtool wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_executable_p () +{ + func_ltwrapper_exec_suffix= + case $1 in + *.exe) ;; + *) func_ltwrapper_exec_suffix=.exe ;; + esac + $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 +} + +# func_ltwrapper_scriptname file +# Assumes file is an ltwrapper_executable +# uses $file to determine the appropriate filename for a +# temporary ltwrapper_script. +func_ltwrapper_scriptname () +{ + func_ltwrapper_scriptname_result="" + if func_ltwrapper_executable_p "$1"; then + func_dirname_and_basename "$1" "" "." + func_stripname '' '.exe' "$func_basename_result" + func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" + fi +} + +# func_ltwrapper_p file +# True iff FILE is a libtool wrapper script or wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_p () +{ + func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" +} + + +# func_execute_cmds commands fail_cmd +# Execute tilde-delimited COMMANDS. +# If FAIL_CMD is given, eval that upon failure. +# FAIL_CMD may read-access the current command in variable CMD! +func_execute_cmds () +{ + $opt_debug + save_ifs=$IFS; IFS='~' + for cmd in $1; do + IFS=$save_ifs + eval cmd=\"$cmd\" + func_show_eval "$cmd" "${2-:}" + done + IFS=$save_ifs +} + + +# func_source file +# Source FILE, adding directory component if necessary. +# Note that it is not necessary on cygwin/mingw to append a dot to +# FILE even if both FILE and FILE.exe exist: automatic-append-.exe +# behavior happens only for exec(3), not for open(2)! Also, sourcing +# `FILE.' does not work on cygwin managed mounts. +func_source () +{ + $opt_debug + case $1 in + */* | *\\*) . "$1" ;; + *) . "./$1" ;; + esac +} + + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + $opt_debug + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + func_quote_for_eval "$arg" + CC_quoted="$CC_quoted $func_quote_for_eval_result" + done + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + func_quote_for_eval "$arg" + CC_quoted="$CC_quoted $func_quote_for_eval_result" + done + case "$@ " in + " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + func_echo "unable to infer tagged configuration" + func_fatal_error "specify a tag with \`--tag'" +# else +# func_verbose "using $tagname tagged configuration" + fi + ;; + esac + fi +} + + + +# func_write_libtool_object output_name pic_name nonpic_name +# Create a libtool object file (analogous to a ".la" file), +# but don't create it if we're doing a dry run. +func_write_libtool_object () +{ + write_libobj=${1} + if test "$build_libtool_libs" = yes; then + write_lobj=\'${2}\' + else + write_lobj=none + fi + + if test "$build_old_libs" = yes; then + write_oldobj=\'${3}\' + else + write_oldobj=none + fi + + $opt_dry_run || { + cat >${write_libobj}T <?"'"'"' &()|`$[]' \ + && func_warning "libobj name \`$libobj' may not contain shell special characters." + func_dirname_and_basename "$obj" "/" "" + objname="$func_basename_result" + xdir="$func_dirname_result" + lobj=${xdir}$objdir/$objname + + test -z "$base_compile" && \ + func_fatal_help "you must specify a compilation command" + + # Delete any leftover library objects. + if test "$build_old_libs" = yes; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2* | cegcc*) + pic_mode=default + ;; + esac + if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test "$compiler_c_o" = no; then + output_obj=`$ECHO "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext} + lockfile="$output_obj.lock" + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test "$need_locks" = yes; then + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + elif test "$need_locks" = warn; then + if test -f "$lockfile"; then + $ECHO "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + removelist="$removelist $output_obj" + $ECHO "$srcfile" > "$lockfile" + fi + + $opt_dry_run || $RM $removelist + removelist="$removelist $lockfile" + trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 + + if test -n "$fix_srcfile_path"; then + eval srcfile=\"$fix_srcfile_path\" + fi + func_quote_for_eval "$srcfile" + qsrcfile=$func_quote_for_eval_result + + # Only build a PIC object if we are building libtool libraries. + if test "$build_libtool_libs" = yes; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test "$pic_mode" != no; then + command="$base_compile $qsrcfile $pic_flag" + else + # Don't build PIC code + command="$base_compile $qsrcfile" + fi + + func_mkdir_p "$xdir$objdir" + + if test -z "$output_obj"; then + # Place PIC objects in $objdir + command="$command -o $lobj" + fi + + func_show_eval_locale "$command" \ + 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' + + if test "$need_locks" = warn && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + func_show_eval '$MV "$output_obj" "$lobj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + + # Allow error messages only from the first compilation. + if test "$suppress_opt" = yes; then + suppress_output=' >/dev/null 2>&1' + fi + fi + + # Only build a position-dependent object if we build old libraries. + if test "$build_old_libs" = yes; then + if test "$pic_mode" != yes; then + # Don't build PIC code + command="$base_compile $qsrcfile$pie_flag" + else + command="$base_compile $qsrcfile $pic_flag" + fi + if test "$compiler_c_o" = yes; then + command="$command -o $obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + command="$command$suppress_output" + func_show_eval_locale "$command" \ + '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' + + if test "$need_locks" = warn && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + func_show_eval '$MV "$output_obj" "$obj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + fi + + $opt_dry_run || { + func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" + + # Unlock the critical section if it was locked + if test "$need_locks" != no; then + removelist=$lockfile + $RM "$lockfile" + fi + } + + exit $EXIT_SUCCESS +} + +$opt_help || { +test "$mode" = compile && func_mode_compile ${1+"$@"} +} + +func_mode_help () +{ + # We need to display help for each of the modes. + case $mode in + "") + # Generic help is extracted from the usage comments + # at the start of this file. + func_help + ;; + + clean) + $ECHO \ +"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + + compile) + $ECHO \ +"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -no-suppress do not suppress compiler output for multiple passes + -prefer-pic try to building PIC objects only + -prefer-non-pic try to building non-PIC objects only + -shared do not build a \`.o' file suitable for static linking + -static only build a \`.o' file suitable for static linking + +COMPILE-COMMAND is a command to be used in creating a \`standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix \`.c' with the +library object suffix, \`.lo'." + ;; + + execute) + $ECHO \ +"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to \`-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + + finish) + $ECHO \ +"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the \`--dry-run' option if you just want to see what would be executed." + ;; + + install) + $ECHO \ +"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the \`install' or \`cp' program. + +The following components of INSTALL-COMMAND are treated specially: + + -inst-prefix PREFIX-DIR Use PREFIX-DIR as a staging area for installation + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + + link) + $ECHO \ +"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE Use a list of object files found in FILE to specify objects + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -shared only do dynamic linking of libtool libraries + -shrext SUFFIX override the standard shared library file extension + -static do not do any dynamic linking of uninstalled libtool libraries + -static-libtool-libs + do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + -weak LIBNAME declare that the target provides the LIBNAME interface + +All other options (arguments beginning with \`-') are ignored. + +Every other argument is treated as a filename. Files ending in \`.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in \`.la', then a libtool library is created, +only library objects (\`.lo' files) may be specified, and \`-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created +using \`ar' and \`ranlib', or on Windows using \`lib'. + +If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file +is created, otherwise an executable program is created." + ;; + + uninstall) + $ECHO \ +"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + + *) + func_fatal_help "invalid operation mode \`$mode'" + ;; + esac + + $ECHO + $ECHO "Try \`$progname --help' for more information about other modes." + + exit $? +} + + # Now that we've collected a possible --mode arg, show help if necessary + $opt_help && func_mode_help + + +# func_mode_execute arg... +func_mode_execute () +{ + $opt_debug + # The first argument is the command name. + cmd="$nonopt" + test -z "$cmd" && \ + func_fatal_help "you must specify a COMMAND" + + # Handle -dlopen flags immediately. + for file in $execute_dlfiles; do + test -f "$file" \ + || func_fatal_help "\`$file' is not a file" + + dir= + case $file in + *.la) + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "\`$lib' is not a valid libtool archive" + + # Read the libtool library. + dlname= + library_names= + func_source "$file" + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && \ + func_warning "\`$file' was not linked with \`-export-dynamic'" + continue + fi + + func_dirname "$file" "" "." + dir="$func_dirname_result" + + if test -f "$dir/$objdir/$dlname"; then + dir="$dir/$objdir" + else + if test ! -f "$dir/$dlname"; then + func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" + fi + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + func_dirname "$file" "" "." + dir="$func_dirname_result" + ;; + + *) + func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir="$absdir" + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic="$magic" + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -*) ;; + *) + # Do a test to see if this is really a libtool program. + if func_ltwrapper_script_p "$file"; then + func_source "$file" + # Transform arg to wrapped name. + file="$progdir/$program" + elif func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + func_source "$func_ltwrapper_scriptname_result" + # Transform arg to wrapped name. + file="$progdir/$program" + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + func_quote_for_eval "$file" + args="$args $func_quote_for_eval_result" + done + + if test "X$opt_dry_run" = Xfalse; then + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + do + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + else + $lt_unset $lt_var + fi" + done + + # Now prepare to actually exec the command. + exec_cmd="\$cmd$args" + else + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + $ECHO "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS + fi +} + +test "$mode" = execute && func_mode_execute ${1+"$@"} + + +# func_mode_finish arg... +func_mode_finish () +{ + $opt_debug + libdirs="$nonopt" + admincmds= + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for dir + do + libdirs="$libdirs $dir" + done + + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + func_execute_cmds "$finish_cmds" 'admincmds="$admincmds +'"$cmd"'"' + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $opt_dry_run || eval "$cmds" || admincmds="$admincmds + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + $opt_silent && exit $EXIT_SUCCESS + + $ECHO "X----------------------------------------------------------------------" | $Xsed + $ECHO "Libraries have been installed in:" + for libdir in $libdirs; do + $ECHO " $libdir" + done + $ECHO + $ECHO "If you ever happen to want to link against installed libraries" + $ECHO "in a given directory, LIBDIR, you must either use libtool, and" + $ECHO "specify the full pathname of the library, or use the \`-LLIBDIR'" + $ECHO "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + $ECHO " - add LIBDIR to the \`$shlibpath_var' environment variable" + $ECHO " during execution" + fi + if test -n "$runpath_var"; then + $ECHO " - add LIBDIR to the \`$runpath_var' environment variable" + $ECHO " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $ECHO " - use the \`$flag' linker flag" + fi + if test -n "$admincmds"; then + $ECHO " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + $ECHO " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + fi + $ECHO + + $ECHO "See any operating system documentation about shared libraries for" + case $host in + solaris2.[6789]|solaris2.1[0-9]) + $ECHO "more information, such as the ld(1), crle(1) and ld.so(8) manual" + $ECHO "pages." + ;; + *) + $ECHO "more information, such as the ld(1) and ld.so(8) manual pages." + ;; + esac + $ECHO "X----------------------------------------------------------------------" | $Xsed + exit $EXIT_SUCCESS +} + +test "$mode" = finish && func_mode_finish ${1+"$@"} + + +# func_mode_install arg... +func_mode_install () +{ + $opt_debug + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || + # Allow the use of GNU shtool's install command. + $ECHO "X$nonopt" | $GREP shtool >/dev/null; then + # Aesthetically quote it. + func_quote_for_eval "$nonopt" + install_prog="$func_quote_for_eval_result " + arg=$1 + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + func_quote_for_eval "$arg" + install_prog="$install_prog$func_quote_for_eval_result" + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=no + stripme= + for arg + do + if test -n "$dest"; then + files="$files $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=yes ;; + -f) + case " $install_prog " in + *[\\\ /]cp\ *) ;; + *) prev=$arg ;; + esac + ;; + -g | -m | -o) + prev=$arg + ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + func_quote_for_eval "$arg" + install_prog="$install_prog $func_quote_for_eval_result" + done + + test -z "$install_prog" && \ + func_fatal_help "you must specify an install program" + + test -n "$prev" && \ + func_fatal_help "the \`$prev' option requires an argument" + + if test -z "$files"; then + if test -z "$dest"; then + func_fatal_help "no file or destination specified" + else + func_fatal_help "you must specify a destination" + fi + fi + + # Strip any trailing slash from the destination. + func_stripname '' '/' "$dest" + dest=$func_stripname_result + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=yes + if test "$isdir" = yes; then + destdir="$dest" + destname= + else + func_dirname_and_basename "$dest" "" "." + destdir="$func_dirname_result" + destname="$func_basename_result" + + # Not a directory, so check to see that there is only one file specified. + set dummy $files; shift + test "$#" -gt 1 && \ + func_fatal_help "\`$dest' is not a directory" + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + func_fatal_help "\`$destdir' must be an absolute directory name" + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + staticlibs="$staticlibs $file" + ;; + + *.la) + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "\`$file' is not a valid libtool archive" + + library_names= + old_library= + relink_command= + func_source "$file" + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) current_libdirs="$current_libdirs $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) future_libdirs="$future_libdirs $libdir" ;; + esac + fi + + func_dirname "$file" "/" "" + dir="$func_dirname_result" + dir="$dir$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$ECHO "X$destdir" | $Xsed -e "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + test "$inst_prefix_dir" = "$destdir" && \ + func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%%"` + fi + + func_warning "relinking \`$file'" + func_show_eval "$relink_command" \ + 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' + fi + + # See the names of the shared library. + set dummy $library_names; shift + if test -n "$1"; then + realname="$1" + shift + + srcname="$realname" + test -n "$relink_command" && srcname="$realname"T + + # Install the shared library and build the symlinks. + func_show_eval "$install_prog $dir/$srcname $destdir/$realname" \ + 'exit $?' + tstripme="$stripme" + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + case $realname in + *.dll.a) + tstripme="" + ;; + esac + ;; + esac + if test -n "$tstripme" && test -n "$striplib"; then + func_show_eval "$striplib $destdir/$realname" 'exit $?' + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try `ln -sf' first, because the `ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + test "$linkname" != "$realname" \ + && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" + done + fi + + # Do each command in the postinstall commands. + lib="$destdir/$realname" + func_execute_cmds "$postinstall_cmds" 'exit $?' + fi + + # Install the pseudo-library for information purposes. + func_basename "$file" + name="$func_basename_result" + instname="$dir/$name"i + func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' + + # Maybe install the static library, too. + test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + func_basename "$file" + destfile="$func_basename_result" + destfile="$destdir/$destfile" + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + func_lo2o "$destfile" + staticdest=$func_lo2o_result + ;; + *.$objext) + staticdest="$destfile" + destfile= + ;; + *) + func_fatal_help "cannot copy a libtool object to \`$destfile'" + ;; + esac + + # Install the libtool object if requested. + test -n "$destfile" && \ + func_show_eval "$install_prog $file $destfile" 'exit $?' + + # Install the old object if enabled. + if test "$build_old_libs" = yes; then + # Deduce the name of the old-style object file. + func_lo2o "$file" + staticobj=$func_lo2o_result + func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + func_basename "$file" + destfile="$func_basename_result" + destfile="$destdir/$destfile" + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext="" + case $file in + *.exe) + if test ! -f "$file"; then + func_stripname '' '.exe' "$file" + file=$func_stripname_result + stripped_ext=".exe" + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin* | *mingw*) + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + wrapper=$func_ltwrapper_scriptname_result + else + func_stripname '' '.exe' "$file" + wrapper=$func_stripname_result + fi + ;; + *) + wrapper=$file + ;; + esac + if func_ltwrapper_script_p "$wrapper"; then + notinst_deplibs= + relink_command= + + func_source "$wrapper" + + # Check the variables that should have been set. + test -z "$generated_by_libtool_version" && \ + func_fatal_error "invalid libtool wrapper script \`$wrapper'" + + finalize=yes + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + func_source "$lib" + fi + libfile="$libdir/"`$ECHO "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test + if test -n "$libdir" && test ! -f "$libfile"; then + func_warning "\`$lib' has not been installed in \`$libdir'" + finalize=no + fi + done + + relink_command= + func_source "$wrapper" + + outputname= + if test "$fast_install" = no && test -n "$relink_command"; then + $opt_dry_run || { + if test "$finalize" = yes; then + tmpdir=`func_mktempdir` + func_basename "$file$stripped_ext" + file="$func_basename_result" + outputname="$tmpdir/$file" + # Replace the output file specification. + relink_command=`$ECHO "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` + + $opt_silent || { + func_quote_for_expand "$relink_command" + eval "func_echo $func_quote_for_expand_result" + } + if eval "$relink_command"; then : + else + func_error "error: relink \`$file' with the above command before installing it" + $opt_dry_run || ${RM}r "$tmpdir" + continue + fi + file="$outputname" + else + func_warning "cannot relink \`$file'" + fi + } + else + # Install the binary that we compiled earlier. + file=`$ECHO "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + func_stripname '' '.exe' "$destfile" + destfile=$func_stripname_result + ;; + esac + ;; + esac + func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' + $opt_dry_run || if test -n "$outputname"; then + ${RM}r "$tmpdir" + fi + ;; + esac + done + + for file in $staticlibs; do + func_basename "$file" + name="$func_basename_result" + + # Set up the ranlib parameters. + oldlib="$destdir/$name" + + func_show_eval "$install_prog \$file \$oldlib" 'exit $?' + + if test -n "$stripme" && test -n "$old_striplib"; then + func_show_eval "$old_striplib $oldlib" 'exit $?' + fi + + # Do each command in the postinstall commands. + func_execute_cmds "$old_postinstall_cmds" 'exit $?' + done + + test -n "$future_libdirs" && \ + func_warning "remember to run \`$progname --finish$future_libdirs'" + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + $opt_dry_run && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi +} + +test "$mode" = install && func_mode_install ${1+"$@"} + + +# func_generate_dlsyms outputname originator pic_p +# Extract symbols from dlprefiles and create ${outputname}S.o with +# a dlpreopen symbol table. +func_generate_dlsyms () +{ + $opt_debug + my_outputname="$1" + my_originator="$2" + my_pic_p="${3-no}" + my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` + my_dlsyms= + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + my_dlsyms="${my_outputname}S.c" + else + func_error "not configured to extract global symbols from dlpreopened files" + fi + fi + + if test -n "$my_dlsyms"; then + case $my_dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist="$output_objdir/${my_outputname}.nm" + + func_show_eval "$RM $nlist ${nlist}S ${nlist}T" + + # Parse the name list into a source file. + func_verbose "creating $output_objdir/$my_dlsyms" + + $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ +/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +/* External symbol declarations for the compiler. */\ +" + + if test "$dlself" = yes; then + func_verbose "generating symbol list for \`$output'" + + $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$ECHO "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + for progfile in $progfiles; do + func_verbose "extracting global C symbols from \`$progfile'" + $opt_dry_run || eval "$NM $progfile | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $opt_dry_run || { + eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + if test -n "$export_symbols_regex"; then + $opt_dry_run || { + eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols="$output_objdir/$outputname.exp" + $opt_dry_run || { + $RM $export_symbols + eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + } + else + $opt_dry_run || { + eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + case $host in + *cygwin | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + } + fi + fi + + for dlprefile in $dlprefiles; do + func_verbose "extracting global C symbols from \`$dlprefile'" + func_basename "$dlprefile" + name="$func_basename_result" + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + eval "$NM $dlprefile 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + done + + $opt_dry_run || { + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $MV "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if $GREP -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + $GREP -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' + else + $ECHO '/* NONE */' >> "$output_objdir/$my_dlsyms" + fi + + $ECHO >> "$output_objdir/$my_dlsyms" "\ + +/* The mapping between symbol names and symbols. */ +typedef struct { + const char *name; + void *address; +} lt_dlsymlist; +" + case $host in + *cygwin* | *mingw* | *cegcc* ) + $ECHO >> "$output_objdir/$my_dlsyms" "\ +/* DATA imports from DLLs on WIN32 con't be const, because + runtime relocations are performed -- see ld's documentation + on pseudo-relocs. */" + lt_dlsym_const= ;; + *osf5*) + echo >> "$output_objdir/$my_dlsyms" "\ +/* This system does not cope well with relocations in const data */" + lt_dlsym_const= ;; + *) + lt_dlsym_const=const ;; + esac + + $ECHO >> "$output_objdir/$my_dlsyms" "\ +extern $lt_dlsym_const lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[]; +$lt_dlsym_const lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[] = +{\ + { \"$my_originator\", (void *) 0 }," + + case $need_lib_prefix in + no) + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + *) + eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + esac + $ECHO >> "$output_objdir/$my_dlsyms" "\ + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_${my_prefix}_LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + } # !$opt_dry_run + + pic_flag_for_symtable= + case "$compile_command " in + *" -static "*) ;; + *) + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; + *-*-hpux*) + pic_flag_for_symtable=" $pic_flag" ;; + *) + if test "X$my_pic_p" != Xno; then + pic_flag_for_symtable=" $pic_flag" + fi + ;; + esac + ;; + esac + symtab_cflags= + for arg in $LTCFLAGS; do + case $arg in + -pie | -fpie | -fPIE) ;; + *) symtab_cflags="$symtab_cflags $arg" ;; + esac + done + + # Now compile the dynamic symbol file. + func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' + + # Clean up the generated files. + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' + + # Transform the symbol file into the correct name. + symfileobj="$output_objdir/${my_outputname}S.$objext" + case $host in + *cygwin* | *mingw* | *cegcc* ) + if test -f "$output_objdir/$my_outputname.def"; then + compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + else + compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` + fi + ;; + *) + compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` + ;; + esac + ;; + *) + func_fatal_error "unknown suffix for \`$my_dlsyms'" + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$ECHO "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` + finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + fi +} + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +func_win32_libid () +{ + $opt_debug + win32_libid_type="unknown" + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | + $EGREP 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then + win32_nmres=`eval $NM -f posix -A $1 | + $SED -n -e ' + 1,100{ + / I /{ + s,.*,import, + p + q + } + }'` + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $ECHO "$win32_libid_type" +} + + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + $opt_debug + f_ex_an_ar_dir="$1"; shift + f_ex_an_ar_oldlib="$1" + func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" 'exit $?' + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" + fi +} + + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + $opt_debug + my_gentop="$1"; shift + my_oldlibs=${1+"$@"} + my_oldobjs="" + my_xlib="" + my_xabs="" + my_xdir="" + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + func_basename "$my_xlib" + my_xlib="$func_basename_result" + my_xlib_u=$my_xlib + while :; do + case " $extracted_archives " in + *" $my_xlib_u "*) + func_arith $extracted_serial + 1 + extracted_serial=$func_arith_result + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac + done + extracted_archives="$extracted_archives $my_xlib_u" + my_xdir="$my_gentop/$my_xlib_u" + + func_mkdir_p "$my_xdir" + + case $host in + *-darwin*) + func_verbose "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + $opt_dry_run || { + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + darwin_base_archive=`basename "$darwin_archive"` + darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` + if test -n "$darwin_arches"; then + darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches ; do + func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" + $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" + cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" + func_extract_an_archive "`pwd`" "${darwin_base_archive}" + cd "$darwin_curdir" + $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" + done # $darwin_arches + ## Okay now we've a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP` + $LIPO -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + $RM -rf unfat-$$ + cd "$darwin_orig_dir" + else + cd $darwin_orig_dir + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + } # !$opt_dry_run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` + done + + func_extract_archives_result="$my_oldobjs" +} + + + +# func_emit_wrapper_part1 [arg=no] +# +# Emit the first part of a libtool wrapper script on stdout. +# For more information, see the description associated with +# func_emit_wrapper(), below. +func_emit_wrapper_part1 () +{ + func_emit_wrapper_part1_arg1=no + if test -n "$1" ; then + func_emit_wrapper_part1_arg1=$1 + fi + + $ECHO "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='${SED} -e 1s/^X//' +sed_quote_subst='$sed_quote_subst' + +# Be Bourne compatible +if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + generated_by_libtool_version='$macro_version' + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$ECHO are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + ECHO=\"$qecho\" + file=\"\$0\" + # Make sure echo works. + if test \"X\$1\" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift + elif test \"X\`{ \$ECHO '\t'; } 2>/dev/null\`\" = 'X\t'; then + # Yippee, \$ECHO works! + : + else + # Restart under the correct shell, and then maybe \$ECHO will work. + exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} + fi + fi\ +" + $ECHO "\ + + # Find the directory that this script lives in. + thisdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$ECHO \"X\$file\" | \$Xsed -e 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\` + done +" +} +# end: func_emit_wrapper_part1 + +# func_emit_wrapper_part2 [arg=no] +# +# Emit the second part of a libtool wrapper script on stdout. +# For more information, see the description associated with +# func_emit_wrapper(), below. +func_emit_wrapper_part2 () +{ + func_emit_wrapper_part2_arg1=no + if test -n "$1" ; then + func_emit_wrapper_part2_arg1=$1 + fi + + $ECHO "\ + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_part2_arg1 + if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then + # special case for '.' + if test \"\$thisdir\" = \".\"; then + thisdir=\`pwd\` + fi + # remove .libs from thisdir + case \"\$thisdir\" in + *[\\\\/]$objdir ) thisdir=\`\$ECHO \"X\$thisdir\" | \$Xsed -e 's%[\\\\/][^\\\\/]*$%%'\` ;; + $objdir ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test "$fast_install" = yes; then + $ECHO "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $MKDIR \"\$progdir\" + else + $RM \"\$progdir/\$file\" + fi" + + $ECHO "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + $ECHO \"\$relink_command_output\" >&2 + $RM \"\$progdir/\$file\" + exit 1 + fi + fi + + $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $RM \"\$progdir/\$program\"; + $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $RM \"\$progdir/\$file\" + fi" + else + $ECHO "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $ECHO "\ + + if test -f \"\$progdir/\$program\"; then" + + # Export our shlibpath_var if we have one. + if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $ECHO "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$ECHO \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` + + export $shlibpath_var +" + fi + + # fixup the dll searchpath if we need to. + if test -n "$dllsearchpath"; then + $ECHO "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + $ECHO "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2* | *-cegcc*) + $ECHO "\ + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $ECHO "\ + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $ECHO "\ + \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 + exit 1 + fi + else + # The program doesn't exist. + \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 + $ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" +} +# end: func_emit_wrapper_part2 + + +# func_emit_wrapper [arg=no] +# +# Emit a libtool wrapper script on stdout. +# Don't directly open a file because we may want to +# incorporate the script contents within a cygwin/mingw +# wrapper executable. Must ONLY be called from within +# func_mode_link because it depends on a number of variables +# set therein. +# +# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR +# variable will take. If 'yes', then the emitted script +# will assume that the directory in which it is stored is +# the $objdir directory. This is a cygwin/mingw-specific +# behavior. +func_emit_wrapper () +{ + func_emit_wrapper_arg1=no + if test -n "$1" ; then + func_emit_wrapper_arg1=$1 + fi + + # split this up so that func_emit_cwrapperexe_src + # can call each part independently. + func_emit_wrapper_part1 "${func_emit_wrapper_arg1}" + func_emit_wrapper_part2 "${func_emit_wrapper_arg1}" +} + + +# func_to_host_path arg +# +# Convert paths to host format when used with build tools. +# Intended for use with "native" mingw (where libtool itself +# is running under the msys shell), or in the following cross- +# build environments: +# $build $host +# mingw (msys) mingw [e.g. native] +# cygwin mingw +# *nix + wine mingw +# where wine is equipped with the `winepath' executable. +# In the native mingw case, the (msys) shell automatically +# converts paths for any non-msys applications it launches, +# but that facility isn't available from inside the cwrapper. +# Similar accommodations are necessary for $host mingw and +# $build cygwin. Calling this function does no harm for other +# $host/$build combinations not listed above. +# +# ARG is the path (on $build) that should be converted to +# the proper representation for $host. The result is stored +# in $func_to_host_path_result. +func_to_host_path () +{ + func_to_host_path_result="$1" + if test -n "$1" ; then + case $host in + *mingw* ) + lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + case $build in + *mingw* ) # actually, msys + # awkward: cmd appends spaces to result + lt_sed_strip_trailing_spaces="s/[ ]*\$//" + func_to_host_path_tmp1=`( cmd //c echo "$1" |\ + $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""` + func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ + $SED -e "$lt_sed_naive_backslashify"` + ;; + *cygwin* ) + func_to_host_path_tmp1=`cygpath -w "$1"` + func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ + $SED -e "$lt_sed_naive_backslashify"` + ;; + * ) + # Unfortunately, winepath does not exit with a non-zero + # error code, so we are forced to check the contents of + # stdout. On the other hand, if the command is not + # found, the shell will set an exit code of 127 and print + # *an error message* to stdout. So we must check for both + # error code of zero AND non-empty stdout, which explains + # the odd construction: + func_to_host_path_tmp1=`winepath -w "$1" 2>/dev/null` + if test "$?" -eq 0 && test -n "${func_to_host_path_tmp1}"; then + func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ + $SED -e "$lt_sed_naive_backslashify"` + else + # Allow warning below. + func_to_host_path_result="" + fi + ;; + esac + if test -z "$func_to_host_path_result" ; then + func_error "Could not determine host path corresponding to" + func_error " '$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback: + func_to_host_path_result="$1" + fi + ;; + esac + fi +} +# end: func_to_host_path + +# func_to_host_pathlist arg +# +# Convert pathlists to host format when used with build tools. +# See func_to_host_path(), above. This function supports the +# following $build/$host combinations (but does no harm for +# combinations not listed here): +# $build $host +# mingw (msys) mingw [e.g. native] +# cygwin mingw +# *nix + wine mingw +# +# Path separators are also converted from $build format to +# $host format. If ARG begins or ends with a path separator +# character, it is preserved (but converted to $host format) +# on output. +# +# ARG is a pathlist (on $build) that should be converted to +# the proper representation on $host. The result is stored +# in $func_to_host_pathlist_result. +func_to_host_pathlist () +{ + func_to_host_pathlist_result="$1" + if test -n "$1" ; then + case $host in + *mingw* ) + lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + # Remove leading and trailing path separator characters from + # ARG. msys behavior is inconsistent here, cygpath turns them + # into '.;' and ';.', and winepath ignores them completely. + func_to_host_pathlist_tmp2="$1" + # Once set for this call, this variable should not be + # reassigned. It is used in tha fallback case. + func_to_host_pathlist_tmp1=`echo "$func_to_host_pathlist_tmp2" |\ + $SED -e 's|^:*||' -e 's|:*$||'` + case $build in + *mingw* ) # Actually, msys. + # Awkward: cmd appends spaces to result. + lt_sed_strip_trailing_spaces="s/[ ]*\$//" + func_to_host_pathlist_tmp2=`( cmd //c echo "$func_to_host_pathlist_tmp1" |\ + $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""` + func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\ + $SED -e "$lt_sed_naive_backslashify"` + ;; + *cygwin* ) + func_to_host_pathlist_tmp2=`cygpath -w -p "$func_to_host_pathlist_tmp1"` + func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\ + $SED -e "$lt_sed_naive_backslashify"` + ;; + * ) + # unfortunately, winepath doesn't convert pathlists + func_to_host_pathlist_result="" + func_to_host_pathlist_oldIFS=$IFS + IFS=: + for func_to_host_pathlist_f in $func_to_host_pathlist_tmp1 ; do + IFS=$func_to_host_pathlist_oldIFS + if test -n "$func_to_host_pathlist_f" ; then + func_to_host_path "$func_to_host_pathlist_f" + if test -n "$func_to_host_path_result" ; then + if test -z "$func_to_host_pathlist_result" ; then + func_to_host_pathlist_result="$func_to_host_path_result" + else + func_to_host_pathlist_result="$func_to_host_pathlist_result;$func_to_host_path_result" + fi + fi + fi + IFS=: + done + IFS=$func_to_host_pathlist_oldIFS + ;; + esac + if test -z "$func_to_host_pathlist_result" ; then + func_error "Could not determine the host path(s) corresponding to" + func_error " '$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback. This may break if $1 contains DOS-style drive + # specifications. The fix is not to complicate the expression + # below, but for the user to provide a working wine installation + # with winepath so that path translation in the cross-to-mingw + # case works properly. + lt_replace_pathsep_nix_to_dos="s|:|;|g" + func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp1" |\ + $SED -e "$lt_replace_pathsep_nix_to_dos"` + fi + # Now, add the leading and trailing path separators back + case "$1" in + :* ) func_to_host_pathlist_result=";$func_to_host_pathlist_result" + ;; + esac + case "$1" in + *: ) func_to_host_pathlist_result="$func_to_host_pathlist_result;" + ;; + esac + ;; + esac + fi +} +# end: func_to_host_pathlist + +# func_emit_cwrapperexe_src +# emit the source code for a wrapper executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_cwrapperexe_src () +{ + cat < +#include +#ifdef _MSC_VER +# include +# include +# include +# define setmode _setmode +#else +# include +# include +# ifdef __CYGWIN__ +# include +# define HAVE_SETENV +# ifdef __STRICT_ANSI__ +char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); +# endif +# endif +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(PATH_MAX) +# define LT_PATHMAX PATH_MAX +#elif defined(MAXPATHLEN) +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef S_IXOTH +# define S_IXOTH 0 +#endif +#ifndef S_IXGRP +# define S_IXGRP 0 +#endif + +#ifdef _MSC_VER +# define S_IXUSR _S_IEXEC +# define stat _stat +# ifndef _INTPTR_T_DEFINED +# define intptr_t int +# endif +#endif + +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ + defined (__OS2__) +# define HAVE_DOS_BASED_FILE_SYSTEM +# define FOPEN_WB "wb" +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#ifdef __CYGWIN__ +# define FOPEN_WB "wb" +#endif + +#ifndef FOPEN_WB +# define FOPEN_WB "w" +#endif +#ifndef _O_BINARY +# define _O_BINARY 0 +#endif + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free ((void *) stale); stale = 0; } \ +} while (0) + +#undef LTWRAPPER_DEBUGPRINTF +#if defined DEBUGWRAPPER +# define LTWRAPPER_DEBUGPRINTF(args) ltwrapper_debugprintf args +static void +ltwrapper_debugprintf (const char *fmt, ...) +{ + va_list args; + va_start (args, fmt); + (void) vfprintf (stderr, fmt, args); + va_end (args); +} +#else +# define LTWRAPPER_DEBUGPRINTF(args) +#endif + +const char *program_name = NULL; + +void *xmalloc (size_t num); +char *xstrdup (const char *string); +const char *base_name (const char *name); +char *find_executable (const char *wrapper); +char *chase_symlinks (const char *pathspec); +int make_executable (const char *path); +int check_executable (const char *path); +char *strendzap (char *str, const char *pat); +void lt_fatal (const char *message, ...); +void lt_setenv (const char *name, const char *value); +char *lt_extend_str (const char *orig_value, const char *add, int to_end); +void lt_opt_process_env_set (const char *arg); +void lt_opt_process_env_prepend (const char *arg); +void lt_opt_process_env_append (const char *arg); +int lt_split_name_value (const char *arg, char** name, char** value); +void lt_update_exe_path (const char *name, const char *value); +void lt_update_lib_path (const char *name, const char *value); + +static const char *script_text_part1 = +EOF + + func_emit_wrapper_part1 yes | + $SED -e 's/\([\\"]\)/\\\1/g' \ + -e 's/^/ "/' -e 's/$/\\n"/' + echo ";" + cat <"))); + for (i = 0; i < newargc; i++) + { + LTWRAPPER_DEBUGPRINTF (("(main) newargz[%d] : %s\n", i, (newargz[i] ? newargz[i] : ""))); + } + +EOF + + case $host_os in + mingw*) + cat <<"EOF" + /* execv doesn't actually work on mingw as expected on unix */ + rval = _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz); + if (rval == -1) + { + /* failed to start process */ + LTWRAPPER_DEBUGPRINTF (("(main) failed to launch target \"%s\": errno = %d\n", lt_argv_zero, errno)); + return 127; + } + return rval; +EOF + ;; + *) + cat <<"EOF" + execv (lt_argv_zero, newargz); + return rval; /* =127, but avoids unused variable warning */ +EOF + ;; + esac + + cat <<"EOF" +} + +void * +xmalloc (size_t num) +{ + void *p = (void *) malloc (num); + if (!p) + lt_fatal ("Memory exhausted"); + + return p; +} + +char * +xstrdup (const char *string) +{ + return string ? strcpy ((char *) xmalloc (strlen (string) + 1), + string) : NULL; +} + +const char * +base_name (const char *name) +{ + const char *base; + +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + /* Skip over the disk name in MSDOS pathnames. */ + if (isalpha ((unsigned char) name[0]) && name[1] == ':') + name += 2; +#endif + + for (base = name; *name; name++) + if (IS_DIR_SEPARATOR (*name)) + base = name + 1; + return base; +} + +int +check_executable (const char *path) +{ + struct stat st; + + LTWRAPPER_DEBUGPRINTF (("(check_executable) : %s\n", + path ? (*path ? path : "EMPTY!") : "NULL!")); + if ((!path) || (!*path)) + return 0; + + if ((stat (path, &st) >= 0) + && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) + return 1; + else + return 0; +} + +int +make_executable (const char *path) +{ + int rval = 0; + struct stat st; + + LTWRAPPER_DEBUGPRINTF (("(make_executable) : %s\n", + path ? (*path ? path : "EMPTY!") : "NULL!")); + if ((!path) || (!*path)) + return 0; + + if (stat (path, &st) >= 0) + { + rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); + } + return rval; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise + Does not chase symlinks, even on platforms that support them. +*/ +char * +find_executable (const char *wrapper) +{ + int has_slash = 0; + const char *p; + const char *p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + int tmp_len; + char *concat_name; + + LTWRAPPER_DEBUGPRINTF (("(find_executable) : %s\n", + wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!")); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char *path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char *q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR (*q)) + break; + p_len = q - p; + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal ("getcwd failed"); + tmp_len = strlen (tmp); + concat_name = + XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = + XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal ("getcwd failed"); + tmp_len = strlen (tmp); + concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + return NULL; +} + +char * +chase_symlinks (const char *pathspec) +{ +#ifndef S_ISLNK + return xstrdup (pathspec); +#else + char buf[LT_PATHMAX]; + struct stat s; + char *tmp_pathspec = xstrdup (pathspec); + char *p; + int has_symlinks = 0; + while (strlen (tmp_pathspec) && !has_symlinks) + { + LTWRAPPER_DEBUGPRINTF (("checking path component for symlinks: %s\n", + tmp_pathspec)); + if (lstat (tmp_pathspec, &s) == 0) + { + if (S_ISLNK (s.st_mode) != 0) + { + has_symlinks = 1; + break; + } + + /* search backwards for last DIR_SEPARATOR */ + p = tmp_pathspec + strlen (tmp_pathspec) - 1; + while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + p--; + if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + { + /* no more DIR_SEPARATORS left */ + break; + } + *p = '\0'; + } + else + { + char *errstr = strerror (errno); + lt_fatal ("Error accessing file %s (%s)", tmp_pathspec, errstr); + } + } + XFREE (tmp_pathspec); + + if (!has_symlinks) + { + return xstrdup (pathspec); + } + + tmp_pathspec = realpath (pathspec, buf); + if (tmp_pathspec == 0) + { + lt_fatal ("Could not follow symlinks for %s", pathspec); + } + return xstrdup (tmp_pathspec); +#endif +} + +char * +strendzap (char *str, const char *pat) +{ + size_t len, patlen; + + assert (str != NULL); + assert (pat != NULL); + + len = strlen (str); + patlen = strlen (pat); + + if (patlen <= len) + { + str += len - patlen; + if (strcmp (str, pat) == 0) + *str = '\0'; + } + return str; +} + +static void +lt_error_core (int exit_status, const char *mode, + const char *message, va_list ap) +{ + fprintf (stderr, "%s: %s: ", program_name, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, "FATAL", message, ap); + va_end (ap); +} + +void +lt_setenv (const char *name, const char *value) +{ + LTWRAPPER_DEBUGPRINTF (("(lt_setenv) setting '%s' to '%s'\n", + (name ? name : ""), + (value ? value : ""))); + { +#ifdef HAVE_SETENV + /* always make a copy, for consistency with !HAVE_SETENV */ + char *str = xstrdup (value); + setenv (name, str, 1); +#else + int len = strlen (name) + 1 + strlen (value) + 1; + char *str = XMALLOC (char, len); + sprintf (str, "%s=%s", name, value); + if (putenv (str) != EXIT_SUCCESS) + { + XFREE (str); + } +#endif + } +} + +char * +lt_extend_str (const char *orig_value, const char *add, int to_end) +{ + char *new_value; + if (orig_value && *orig_value) + { + int orig_value_len = strlen (orig_value); + int add_len = strlen (add); + new_value = XMALLOC (char, add_len + orig_value_len + 1); + if (to_end) + { + strcpy (new_value, orig_value); + strcpy (new_value + orig_value_len, add); + } + else + { + strcpy (new_value, add); + strcpy (new_value + add_len, orig_value); + } + } + else + { + new_value = xstrdup (add); + } + return new_value; +} + +int +lt_split_name_value (const char *arg, char** name, char** value) +{ + const char *p; + int len; + if (!arg || !*arg) + return 1; + + p = strchr (arg, (int)'='); + + if (!p) + return 1; + + *value = xstrdup (++p); + + len = strlen (arg) - strlen (*value); + *name = XMALLOC (char, len); + strncpy (*name, arg, len-1); + (*name)[len - 1] = '\0'; + + return 0; +} + +void +lt_opt_process_env_set (const char *arg) +{ + char *name = NULL; + char *value = NULL; + + if (lt_split_name_value (arg, &name, &value) != 0) + { + XFREE (name); + XFREE (value); + lt_fatal ("bad argument for %s: '%s'", env_set_opt, arg); + } + + lt_setenv (name, value); + XFREE (name); + XFREE (value); +} + +void +lt_opt_process_env_prepend (const char *arg) +{ + char *name = NULL; + char *value = NULL; + char *new_value = NULL; + + if (lt_split_name_value (arg, &name, &value) != 0) + { + XFREE (name); + XFREE (value); + lt_fatal ("bad argument for %s: '%s'", env_prepend_opt, arg); + } + + new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + XFREE (name); + XFREE (value); +} + +void +lt_opt_process_env_append (const char *arg) +{ + char *name = NULL; + char *value = NULL; + char *new_value = NULL; + + if (lt_split_name_value (arg, &name, &value) != 0) + { + XFREE (name); + XFREE (value); + lt_fatal ("bad argument for %s: '%s'", env_append_opt, arg); + } + + new_value = lt_extend_str (getenv (name), value, 1); + lt_setenv (name, new_value); + XFREE (new_value); + XFREE (name); + XFREE (value); +} + +void +lt_update_exe_path (const char *name, const char *value) +{ + LTWRAPPER_DEBUGPRINTF (("(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + (name ? name : ""), + (value ? value : ""))); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + /* some systems can't cope with a ':'-terminated path #' */ + int len = strlen (new_value); + while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) + { + new_value[len-1] = '\0'; + } + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +void +lt_update_lib_path (const char *name, const char *value) +{ + LTWRAPPER_DEBUGPRINTF (("(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + (name ? name : ""), + (value ? value : ""))); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + } +} + + +EOF +} +# end: func_emit_cwrapperexe_src + +# func_mode_link arg... +func_mode_link () +{ + $opt_debug + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # which system we are compiling for in order to pass an extra + # flag for every libtool invocation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll which has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args=$nonopt + base_compile="$nonopt $@" + compile_command=$nonopt + finalize_command=$nonopt + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + new_inherited_linker_flags= + + avoid_version=no + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + non_pic_objects= + precious_files_regex= + prefer_static_libs=no + preload=no + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + vinfo_number=no + weak_libs= + single_module="${wl}-single_module" + func_infer_tag $base_compile + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -shared) + test "$build_libtool_libs" != yes && \ + func_fatal_configuration "can not build a shared library" + build_old_libs=no + break + ;; + -all-static | -static | -static-libtool-libs) + case $arg in + -all-static) + if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then + func_warning "complete static linking is impossible in this configuration" + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + -static) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + ;; + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg="$1" + shift + func_quote_for_eval "$arg" + qarg=$func_quote_for_eval_unquoted_result + func_append libtool_args " $func_quote_for_eval_result" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + func_append compile_command " @OUTPUT@" + func_append finalize_command " @OUTPUT@" + ;; + esac + + case $prev in + dlfiles|dlprefiles) + if test "$preload" = no; then + # Add the symbol object into the linking commands. + func_append compile_command " @SYMFILE@" + func_append finalize_command " @SYMFILE@" + preload=yes + fi + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test "$dlself" = no; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test "$prev" = dlprefiles; then + dlself=yes + elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test "$prev" = dlfiles; then + dlfiles="$dlfiles $arg" + else + dlprefiles="$dlprefiles $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols="$arg" + test -f "$arg" \ + || func_fatal_error "symbol file \`$arg' does not exist" + prev= + continue + ;; + expsyms_regex) + export_symbols_regex="$arg" + prev= + continue + ;; + framework) + case $host in + *-*-darwin*) + case "$deplibs " in + *" $qarg.ltframework "*) ;; + *) deplibs="$deplibs $qarg.ltframework" # this is fixed later + ;; + esac + ;; + esac + prev= + continue + ;; + inst_prefix) + inst_prefix_dir="$arg" + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat "$save_arg"` + do +# moreargs="$moreargs $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test "$pic_object" = none && + test "$non_pic_object" = none; then + func_fatal_error "cannot find name of object for \`$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + dlfiles="$dlfiles $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "\`$arg' is not a valid libtool object" + fi + fi + done + else + func_fatal_error "link input file \`$arg' does not exist" + fi + arg=$save_arg + prev= + continue + ;; + precious_regex) + precious_files_regex="$arg" + prev= + continue + ;; + release) + release="-$arg" + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + if test "$prev" = rpath; then + case "$rpath " in + *" $arg "*) ;; + *) rpath="$rpath $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) xrpath="$xrpath $arg" ;; + esac + fi + prev= + continue + ;; + shrext) + shrext_cmds="$arg" + prev= + continue + ;; + weak) + weak_libs="$weak_libs $arg" + prev= + continue + ;; + xcclinker) + linker_flags="$linker_flags $qarg" + compiler_flags="$compiler_flags $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xcompiler) + compiler_flags="$compiler_flags $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xlinker) + linker_flags="$linker_flags $qarg" + compiler_flags="$compiler_flags $wl$qarg" + prev= + func_append compile_command " $wl$qarg" + func_append finalize_command " $wl$qarg" + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg="$arg" + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + # See comment for -static flag below, for more details. + func_append compile_command " $link_static_flag" + func_append finalize_command " $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + func_fatal_error "\`-allow-undefined' must not be used because it is the default" + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + func_fatal_error "more than one -exported-symbols argument is not allowed" + fi + if test "X$arg" = "X-export-symbols"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework) + prev=framework + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + func_append compile_command " $arg" + func_append finalize_command " $arg" + ;; + esac + continue + ;; + + -L*) + func_stripname '-L' '' "$arg" + dir=$func_stripname_result + if test -z "$dir"; then + if test "$#" -gt 0; then + func_fatal_error "require no space between \`-L' and \`$1'" + else + func_fatal_error "need path for \`-L' option" + fi + fi + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + test -z "$absdir" && \ + func_fatal_error "cannot determine absolute directory name of \`$dir'" + dir="$absdir" + ;; + esac + case "$deplibs " in + *" -L$dir "*) ;; + *) + deplibs="$deplibs -L$dir" + lib_search_path="$lib_search_path $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "X$dir" | $Xsed -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + ::) dllsearchpath=$dir;; + *) dllsearchpath="$dllsearchpath:$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) dllsearchpath="$dllsearchpath:$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test "X$arg" = "X-lc" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + test "X$arg" = "X-lc" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + deplibs="$deplibs System.ltframework" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test "X$arg" = "X-lc" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test "X$arg" = "X-lc" && continue + ;; + esac + elif test "X$arg" = "X-lc_r"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + deplibs="$deplibs $arg" + continue + ;; + + -module) + module=yes + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + # Darwin uses the -arch flag to determine output architecture. + -model|-arch|-isysroot) + compiler_flags="$compiler_flags $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) + compiler_flags="$compiler_flags $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case "$new_inherited_linker_flags " in + *" $arg "*) ;; + * ) new_inherited_linker_flags="$new_inherited_linker_flags $arg" ;; + esac + continue + ;; + + -multi_module) + single_module="${wl}-multi_module" + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) + # The PATH hackery in wrapper scripts is required on Windows + # and Darwin in order for the loader to find any dlls it needs. + func_warning "\`-no-install' is ignored for $host" + func_warning "assuming \`-no-fast-install' instead" + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + func_stripname '-R' '' "$arg" + dir=$func_stripname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + continue + ;; + + -shared) + # The effects of -shared are defined in a previous loop. + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -static | -static-libtool-libs) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -weak) + prev=weak + continue + ;; + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + func_quote_for_eval "$flag" + arg="$arg $wl$func_quote_for_eval_result" + compiler_flags="$compiler_flags $func_quote_for_eval_result" + done + IFS="$save_ifs" + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Wl,*) + func_stripname '-Wl,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + func_quote_for_eval "$flag" + arg="$arg $wl$func_quote_for_eval_result" + compiler_flags="$compiler_flags $wl$func_quote_for_eval_result" + linker_flags="$linker_flags $func_quote_for_eval_result" + done + IFS="$save_ifs" + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # -msg_* for osf cc + -msg_*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + + # -64, -mips[0-9] enable 64-bit mode on the SGI compiler + # -r[0-9][0-9]* specifies the processor on the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler + # +DA*, +DD* enable 64-bit mode on the HP compiler + # -q* pass through compiler args for the IBM compiler + # -m*, -t[45]*, -txscale* pass through architecture-specific + # compiler args for GCC + # -F/path gives path to uninstalled frameworks, gcc on darwin + # -p, -pg, --coverage, -fprofile-* pass through profiling flag for GCC + # @file GCC response files + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + func_append compile_command " $arg" + func_append finalize_command " $arg" + compiler_flags="$compiler_flags $arg" + continue + ;; + + # Some other compiler flag. + -* | +*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + + *.$objext) + # A standard object. + objs="$objs $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test "$pic_object" = none && + test "$non_pic_object" = none; then + func_fatal_error "cannot find name of object for \`$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + dlfiles="$dlfiles $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "\`$arg' is not a valid libtool object" + fi + fi + ;; + + *.$libext) + # An archive. + deplibs="$deplibs $arg" + old_deplibs="$old_deplibs $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + if test "$prev" = dlfiles; then + # This library was specified with -dlopen. + dlfiles="$dlfiles $arg" + prev= + elif test "$prev" = dlprefiles; then + # The library was specified with -dlpreopen. + dlprefiles="$dlprefiles $arg" + prev= + else + deplibs="$deplibs $arg" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + done # argument parsing loop + + test -n "$prev" && \ + func_fatal_help "the \`$prevarg' option requires an argument" + + if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + func_basename "$output" + outputname="$func_basename_result" + libobjs_save="$libobjs" + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$ECHO \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + func_dirname "$output" "/" "" + output_objdir="$func_dirname_result$objdir" + # Create the object directory. + func_mkdir_p "$output_objdir" + + # Determine the type of output + case $output in + "") + func_fatal_help "you must specify an output file" + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if $opt_duplicate_deps ; then + case "$libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + libs="$libs $deplib" + done + + if test "$linkmode" = lib; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if $opt_duplicate_compiler_generated_deps; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;; + esac + pre_post_deps="$pre_post_deps $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + + case $linkmode in + lib) + passes="conv dlpreopen link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=no + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + + for pass in $passes; do + # The preopen pass in lib mode reverses $deplibs; put it back here + # so that -L comes before libs that need it for instance... + if test "$linkmode,$pass" = "lib,link"; then + ## FIXME: Find the place where the list is rebuilt in the wrong + ## order, and fix it there properly + tmp_deplibs= + for deplib in $deplibs; do + tmp_deplibs="$deplib $tmp_deplibs" + done + deplibs="$tmp_deplibs" + fi + + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan"; then + libs="$deplibs" + deplibs= + fi + if test "$linkmode" = prog; then + case $pass in + dlopen) libs="$dlfiles" ;; + dlpreopen) libs="$dlprefiles" ;; + link) + libs="$deplibs %DEPLIBS%" + test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" + ;; + esac + fi + if test "$linkmode,$pass" = "lib,dlpreopen"; then + # Collect and forward deplibs of preopened libtool libs + for lib in $dlprefiles; do + # Ignore non-libtool-libs + dependency_libs= + case $lib in + *.la) func_source "$lib" ;; + esac + + # Collect preopened libtool deplibs, except any this library + # has declared as weak libs + for deplib in $dependency_libs; do + deplib_base=`$ECHO "X$deplib" | $Xsed -e "$basename"` + case " $weak_libs " in + *" $deplib_base "*) ;; + *) deplibs="$deplibs $deplib" ;; + esac + done + done + libs="$dlprefiles" + fi + if test "$pass" = dlopen; then + # Collect dlpreopened libraries + save_deplibs="$deplibs" + deplibs= + fi + + for deplib in $libs; do + lib= + found=no + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + compiler_flags="$compiler_flags $deplib" + if test "$linkmode" = lib ; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;; + esac + fi + fi + continue + ;; + -l*) + if test "$linkmode" != lib && test "$linkmode" != prog; then + func_warning "\`-l' is ignored for archives/objects" + continue + fi + func_stripname '-l' '' "$deplib" + name=$func_stripname_result + if test "$linkmode" = lib; then + searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" + else + searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" + fi + for searchdir in $searchdirs; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib="$searchdir/lib${name}${search_ext}" + if test -f "$lib"; then + if test "$search_ext" = ".la"; then + found=yes + else + found=no + fi + break 2 + fi + done + done + if test "$found" != yes; then + # deplib doesn't seem to be a libtool library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + else # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $deplib "*) + if func_lalib_p "$lib"; then + library_names= + old_library= + func_source "$lib" + for l in $old_library $library_names; do + ll="$l" + done + if test "X$ll" = "X$old_library" ; then # only static version available + found=no + func_dirname "$lib" "" "." + ladir="$func_dirname_result" + lib=$ladir/$old_library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + fi + ;; # -l + *.ltframework) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + if test "$linkmode" = lib ; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;; + esac + fi + fi + continue + ;; + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test "$pass" = conv && continue + newdependency_libs="$deplib $newdependency_libs" + func_stripname '-L' '' "$deplib" + newlib_search_path="$newlib_search_path $func_stripname_result" + ;; + prog) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + if test "$pass" = scan; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + func_stripname '-L' '' "$deplib" + newlib_search_path="$newlib_search_path $func_stripname_result" + ;; + *) + func_warning "\`-L' is ignored for archives/objects" + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test "$pass" = link; then + func_stripname '-R' '' "$deplib" + dir=$func_stripname_result + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) lib="$deplib" ;; + *.$libext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + # Linking convenience modules into shared libraries is allowed, + # but linking other static libraries is non-portable. + case " $dlpreconveniencelibs " in + *" $deplib "*) ;; + *) + valid_a_lib=no + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + if eval "\$ECHO \"X$deplib\"" 2>/dev/null | $Xsed -e 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=yes + fi + ;; + pass_all) + valid_a_lib=yes + ;; + esac + if test "$valid_a_lib" != yes; then + $ECHO + $ECHO "*** Warning: Trying to link with static lib archive $deplib." + $ECHO "*** I have the capability to make that library automatically link in when" + $ECHO "*** you link to this library. But I can only do this if you have a" + $ECHO "*** shared version of the library, which you do not appear to have" + $ECHO "*** because the file extensions .$libext of this argument makes me believe" + $ECHO "*** that it is just a static archive that I should not use here." + else + $ECHO + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + fi + ;; + esac + continue + ;; + prog) + if test "$pass" != link; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + elif test "$linkmode" = prog; then + if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + newdlprefiles="$newdlprefiles $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + newdlfiles="$newdlfiles $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=yes + continue + ;; + esac # case $deplib + + if test "$found" = yes || test -f "$lib"; then : + else + func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" + fi + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$lib" \ + || func_fatal_error "\`$lib' is not a valid libtool archive" + + func_dirname "$lib" "" "." + ladir="$func_dirname_result" + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + inherited_linker_flags= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + func_source "$lib" + + # Convert "-framework foo" to "foo.ltframework" + if test -n "$inherited_linker_flags"; then + tmp_inherited_linker_flags=`$ECHO "X$inherited_linker_flags" | $Xsed -e 's/-framework \([^ $]*\)/\1.ltframework/g'` + for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do + case " $new_inherited_linker_flags " in + *" $tmp_inherited_linker_flag "*) ;; + *) new_inherited_linker_flags="$new_inherited_linker_flags $tmp_inherited_linker_flag";; + esac + done + fi + dependency_libs=`$ECHO "X $dependency_libs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan" || + { test "$linkmode" != prog && test "$linkmode" != lib; }; then + test -n "$dlopen" && dlfiles="$dlfiles $dlopen" + test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen" + fi + + if test "$pass" = conv; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + func_fatal_error "cannot find name of link library for \`$lib'" + fi + # It is a libtool convenience library, so add in its objects. + convenience="$convenience $ladir/$objdir/$old_library" + old_convenience="$old_convenience $ladir/$objdir/$old_library" + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_duplicate_deps ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + elif test "$linkmode" != prog && test "$linkmode" != lib; then + func_fatal_error "\`$lib' is not a convenience library" + fi + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + for l in $old_library $library_names; do + linklib="$l" + done + if test -z "$linklib"; then + func_fatal_error "cannot find name of link library for \`$lib'" + fi + + # This library was specified with -dlopen. + if test "$pass" = dlopen; then + if test -z "$libdir"; then + func_fatal_error "cannot -dlopen a convenience library: \`$lib'" + fi + if test -z "$dlname" || + test "$dlopen_support" != yes || + test "$build_libtool_libs" = no; then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + dlprefiles="$dlprefiles $lib $dependency_libs" + else + newdlfiles="$newdlfiles $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + func_warning "cannot determine absolute directory name of \`$ladir'" + func_warning "passing it literally to the linker, although it might fail" + abs_ladir="$ladir" + fi + ;; + esac + func_basename "$lib" + laname="$func_basename_result" + + # Find the relevant object directory and library name. + if test "X$installed" = Xyes; then + if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + func_warning "library \`$lib' was moved." + dir="$ladir" + absdir="$abs_ladir" + libdir="$abs_ladir" + else + dir="$libdir" + absdir="$libdir" + fi + test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir="$ladir" + absdir="$abs_ladir" + # Remove this search path later + notinst_path="$notinst_path $abs_ladir" + else + dir="$ladir/$objdir" + absdir="$abs_ladir/$objdir" + # Remove this search path later + notinst_path="$notinst_path $abs_ladir" + fi + fi # $installed = yes + func_stripname 'lib' '.la' "$laname" + name=$func_stripname_result + + # This library was specified with -dlpreopen. + if test "$pass" = dlpreopen; then + if test -z "$libdir" && test "$linkmode" = prog; then + func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" + fi + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + newdlprefiles="$newdlprefiles $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + dlpreconveniencelibs="$dlpreconveniencelibs $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + newdlprefiles="$newdlprefiles $dir/$dlname" + else + newdlprefiles="$newdlprefiles $dir/$linklib" + fi + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test "$linkmode" = lib; then + deplibs="$dir/$old_library $deplibs" + elif test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test "$linkmode" = prog && test "$pass" != link; then + newlib_search_path="$newlib_search_path $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=no + if test "$link_all_deplibs" != no || test -z "$library_names" || + test "$build_libtool_libs" = no; then + linkalldeplibs=yes + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + newlib_search_path="$newlib_search_path $func_stripname_result" + ;; + esac + # Need to link against all dependency_libs? + if test "$linkalldeplibs" = yes; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if $opt_duplicate_deps ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test "$linkmode,$pass" = "prog,link"; then + if test -n "$library_names" && + { { test "$prefer_static_libs" = no || + test "$prefer_static_libs,$installed" = "built,yes"; } || + test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then + # Make sure the rpath contains only unique directories. + case "$temp_rpath:" in + *"$absdir:"*) ;; + *) temp_rpath="$temp_rpath$absdir:" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if test "$alldeplibs" = yes && + { test "$deplibs_check_method" = pass_all || + { test "$build_libtool_libs" = yes && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test "$use_static_libs" = built && test "$installed" = yes; then + use_static_libs=no + fi + if test -n "$library_names" && + { test "$use_static_libs" = no || test -z "$old_library"; }; then + case $host in + *cygwin* | *mingw* | *cegcc*) + # No point in relinking DLLs because paths are not encoded + notinst_deplibs="$notinst_deplibs $lib" + need_relink=no + ;; + *) + if test "$installed" = no; then + notinst_deplibs="$notinst_deplibs $lib" + need_relink=yes + fi + ;; + esac + # This is a shared library + + # Warn about portability, can't link against -module's on some + # systems (darwin). Don't bleat about dlopened modules though! + dlopenmodule="" + for dlpremoduletest in $dlprefiles; do + if test "X$dlpremoduletest" = "X$lib"; then + dlopenmodule="$dlpremoduletest" + break + fi + done + if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then + $ECHO + if test "$linkmode" = prog; then + $ECHO "*** Warning: Linking the executable $output against the loadable module" + else + $ECHO "*** Warning: Linking the shared library $output against the loadable module" + fi + $ECHO "*** $linklib is not portable!" + fi + if test "$linkmode" = lib && + test "$hardcode_into_libs" = yes; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + shift + realname="$1" + shift + libname=`eval "\\$ECHO \"$libname_spec\""` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname="$dlname" + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw* | *cegcc*) + func_arith $current - $age + major=$func_arith_result + versuffix="-$major" + ;; + esac + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot="$soname" + func_basename "$soroot" + soname="$func_basename_result" + func_stripname 'lib' '.dll' "$soname" + newlib=libimp-$func_stripname_result.a + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + func_verbose "extracting exported symbol list from \`$soname'" + func_execute_cmds "$extract_expsyms_cmds" 'exit $?' + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + func_verbose "generating import library for \`$soname'" + func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test "$linkmode" = prog || test "$mode" != relink; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test "$hardcode_direct" = no; then + add="$dir/$linklib" + case $host in + *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; + *-*-sysv4*uw2*) add_dir="-L$dir" ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir="-L$dir" ;; + *-*-darwin* ) + # if the lib is a (non-dlopened) module then we can not + # link against it, someone is ignoring the earlier warnings + if /usr/bin/file -L $add 2> /dev/null | + $GREP ": [^:]* bundle" >/dev/null ; then + if test "X$dlopenmodule" != "X$lib"; then + $ECHO "*** Warning: lib $linklib is a module, not a shared library" + if test -z "$old_library" ; then + $ECHO + $ECHO "*** And there doesn't seem to be a static archive available" + $ECHO "*** The link will probably fail, sorry" + else + add="$dir/$old_library" + fi + elif test -n "$old_library"; then + add="$dir/$old_library" + fi + fi + esac + elif test "$hardcode_minus_L" = no; then + case $host in + *-*-sunos*) add_shlibpath="$dir" ;; + esac + add_dir="-L$dir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = no; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + relink) + if test "$hardcode_direct" = yes && + test "$hardcode_direct_absolute" = no; then + add="$dir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$dir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + add_dir="$add_dir -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test "$lib_linked" != yes; then + func_fatal_configuration "unsupported hardcode properties" + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;; + esac + fi + if test "$linkmode" = prog; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test "$hardcode_direct" != yes && + test "$hardcode_minus_L" != yes && + test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + fi + fi + fi + + if test "$linkmode" = prog || test "$mode" = relink; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test "$hardcode_direct" = yes && + test "$hardcode_direct_absolute" = no; then + add="$libdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$libdir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + add="-l$name" + elif test "$hardcode_automatic" = yes; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib" ; then + add="$inst_prefix_dir$libdir/$linklib" + else + add="$libdir/$linklib" + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir="-L$libdir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + add_dir="$add_dir -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + fi + + if test "$linkmode" = prog; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test "$linkmode" = prog; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test "$hardcode_direct" != unsupported; then + test -n "$old_library" && linklib="$old_library" + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test "$build_libtool_libs" = yes; then + # Not a shared library + if test "$deplibs_check_method" != pass_all; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + $ECHO + $ECHO "*** Warning: This system can not link to static lib archive $lib." + $ECHO "*** I have the capability to make that library automatically link in when" + $ECHO "*** you link to this library. But I can only do this if you have a" + $ECHO "*** shared version of the library, which you do not appear to have." + if test "$module" = yes; then + $ECHO "*** But as you try to build a module library, libtool will still create " + $ECHO "*** a static module, that should work as long as the dlopening application" + $ECHO "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + $ECHO + $ECHO "*** However, this would only work if libtool was able to extract symbol" + $ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could" + $ECHO "*** not find such a program. So, this module is probably useless." + $ECHO "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test "$linkmode" = lib; then + if test -n "$dependency_libs" && + { test "$hardcode_into_libs" != yes || + test "$build_old_libs" = yes || + test "$link_static" = yes; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) func_stripname '-R' '' "$libdir" + temp_xrpath=$func_stripname_result + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) xrpath="$xrpath $temp_xrpath";; + esac;; + *) temp_deplibs="$temp_deplibs $libdir";; + esac + done + dependency_libs="$temp_deplibs" + fi + + newlib_search_path="$newlib_search_path $absdir" + # Link against this library + test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + if $opt_duplicate_deps ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + + if test "$link_all_deplibs" != no; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + path= + case $deplib in + -L*) path="$deplib" ;; + *.la) + func_dirname "$deplib" "" "." + dir="$func_dirname_result" + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + func_warning "cannot determine absolute directory name of \`$dir'" + absdir="$dir" + fi + ;; + esac + if $GREP "^installed=no" $deplib > /dev/null; then + case $host in + *-*-darwin*) + depdepl= + eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names" ; then + for tmp in $deplibrary_names ; do + depdepl=$tmp + done + if test -f "$absdir/$objdir/$depdepl" ; then + depdepl="$absdir/$objdir/$depdepl" + darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -z "$darwin_install_name"; then + darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + fi + compiler_flags="$compiler_flags ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" + linker_flags="$linker_flags -dylib_file ${darwin_install_name}:${depdepl}" + path= + fi + fi + ;; + *) + path="-L$absdir/$objdir" + ;; + esac + else + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "\`$deplib' is not a valid libtool archive" + test "$absdir" != "$libdir" && \ + func_warning "\`$deplib' seems to be moved" + + path="-L$absdir" + fi + ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test "$pass" = link; then + if test "$linkmode" = "prog"; then + compile_deplibs="$new_inherited_linker_flags $compile_deplibs" + finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" + else + compiler_flags="$compiler_flags "`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + fi + fi + dependency_libs="$newdependency_libs" + if test "$pass" = dlpreopen; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test "$pass" != dlopen; then + if test "$pass" != conv; then + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) lib_search_path="$lib_search_path $dir" ;; + esac + done + newlib_search_path= + fi + + if test "$linkmode,$pass" != "prog,link"; then + vars="deplibs" + else + vars="compile_deplibs finalize_deplibs" + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs ; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i="" + ;; + esac + if test -n "$i" ; then + tmp_libs="$tmp_libs $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test "$linkmode" = prog; then + dlfiles="$newdlfiles" + fi + if test "$linkmode" = prog || test "$linkmode" = lib; then + dlprefiles="$newdlprefiles" + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + func_warning "\`-dlopen' is ignored for archives" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "\`-l' and \`-L' are ignored for archives" ;; + esac + + test -n "$rpath" && \ + func_warning "\`-rpath' is ignored for archives" + + test -n "$xrpath" && \ + func_warning "\`-R' is ignored for archives" + + test -n "$vinfo" && \ + func_warning "\`-version-info/-version-number' is ignored for archives" + + test -n "$release" && \ + func_warning "\`-release' is ignored for archives" + + test -n "$export_symbols$export_symbols_regex" && \ + func_warning "\`-export-symbols' is ignored for archives" + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs="$output" + objs="$objs$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form `libNAME.la'. + case $outputname in + lib*) + func_stripname 'lib' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + test "$module" = no && \ + func_fatal_help "libtool library \`$output' must begin with \`lib'" + + if test "$need_lib_prefix" != no; then + # Add the "lib" prefix for modules if required + func_stripname '' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + func_stripname '' '.la' "$outputname" + libname=$func_stripname_result + fi + ;; + esac + + if test -n "$objs"; then + if test "$deplibs_check_method" != pass_all; then + func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" + else + $ECHO + $ECHO "*** Warning: Linking the shared library $output against the non-libtool" + $ECHO "*** objects $objs is not portable!" + libobjs="$libobjs $objs" + fi + fi + + test "$dlself" != no && \ + func_warning "\`-dlopen self' is ignored for libtool libraries" + + set dummy $rpath + shift + test "$#" -gt 1 && \ + func_warning "ignoring multiple \`-rpath's for a libtool library" + + install_libdir="$1" + + oldlibs= + if test -z "$rpath"; then + if test "$build_libtool_libs" = yes; then + # Building a libtool convenience library. + # Some compilers have problems with a `.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + test -n "$vinfo" && \ + func_warning "\`-version-info/-version-number' is ignored for convenience libraries" + + test -n "$release" && \ + func_warning "\`-release' is ignored for convenience libraries" + else + + # Parse the version information argument. + save_ifs="$IFS"; IFS=':' + set dummy $vinfo 0 0 0 + shift + IFS="$save_ifs" + + test -n "$7" && \ + func_fatal_help "too many parameters to \`-version-info'" + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major="$1" + number_minor="$2" + number_revision="$3" + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # which has an extra 1 added just for fun + # + case $version_type in + darwin|linux|osf|windows|none) + func_arith $number_major + $number_minor + current=$func_arith_result + age="$number_minor" + revision="$number_revision" + ;; + freebsd-aout|freebsd-elf|sunos) + current="$number_major" + revision="$number_minor" + age="0" + ;; + irix|nonstopux) + func_arith $number_major + $number_minor + current=$func_arith_result + age="$number_minor" + revision="$number_minor" + lt_irix_increment=no + ;; + *) + func_fatal_configuration "$modename: unknown library version type \`$version_type'" + ;; + esac + ;; + no) + current="$1" + revision="$2" + age="$3" + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "CURRENT \`$current' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "REVISION \`$revision' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "AGE \`$age' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + if test "$age" -gt "$current"; then + func_error "AGE \`$age' is greater than the current interface number \`$current'" + func_fatal_error "\`$vinfo' is not valid version information" + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + func_arith $current - $age + major=.$func_arith_result + versuffix="$major.$age.$revision" + # Darwin ld doesn't like 0 for these options... + func_arith $current + 1 + minor_current=$func_arith_result + xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + + freebsd-aout) + major=".$current" + versuffix=".$current.$revision"; + ;; + + freebsd-elf) + major=".$current" + versuffix=".$current" + ;; + + irix | nonstopux) + if test "X$lt_irix_increment" = "Xno"; then + func_arith $current - $age + else + func_arith $current - $age + 1 + fi + major=$func_arith_result + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring="$verstring_prefix$major.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test "$loop" -ne 0; do + func_arith $revision - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring="$verstring_prefix$major.$iface:$verstring" + done + + # Before this point, $major must not contain `.'. + major=.$major + versuffix="$major.$revision" + ;; + + linux) + func_arith $current - $age + major=.$func_arith_result + versuffix="$major.$age.$revision" + ;; + + osf) + func_arith $current - $age + major=.$func_arith_result + versuffix=".$current.$age.$revision" + verstring="$current.$age.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$age + while test "$loop" -ne 0; do + func_arith $current - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring="$verstring:${iface}.0" + done + + # Make executables depend on our current version. + verstring="$verstring:${current}.0" + ;; + + qnx) + major=".$current" + versuffix=".$current" + ;; + + sunos) + major=".$current" + versuffix=".$current.$revision" + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 filesystems. + func_arith $current - $age + major=$func_arith_result + versuffix="-$major" + ;; + + *) + func_fatal_configuration "unknown library version type \`$version_type'" + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring="0.0" + ;; + esac + if test "$need_version" = no; then + versuffix= + else + versuffix=".0.0" + fi + fi + + # Remove version info from name if versioning should be avoided + if test "$avoid_version" = yes && test "$need_version" = no; then + major= + versuffix= + verstring="" + fi + + # Check to see if the archive will have undefined symbols. + if test "$allow_undefined" = yes; then + if test "$allow_undefined_flag" = unsupported; then + func_warning "undefined symbols not allowed in $host shared libraries" + build_libtool_libs=no + build_old_libs=yes + fi + else + # Don't allow undefined symbols. + allow_undefined_flag="$no_undefined_flag" + fi + + fi + + func_generate_dlsyms "$libname" "$libname" "yes" + libobjs="$libobjs $symfileobj" + test "X$libobjs" = "X " && libobjs= + + if test "$mode" != relink; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$ECHO "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext | *.gcno) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) + if test "X$precious_files_regex" != "X"; then + if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + removelist="$removelist $p" + ;; + *) ;; + esac + done + test -n "$removelist" && \ + func_show_eval "${RM}r \$removelist" + fi + + # Now set the variables for building old libraries. + if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then + oldlibs="$oldlibs $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + #for path in $notinst_path; do + # lib_search_path=`$ECHO "X$lib_search_path " | $Xsed -e "s% $path % %g"` + # deplibs=`$ECHO "X$deplibs " | $Xsed -e "s% -L$path % %g"` + # dependency_libs=`$ECHO "X$dependency_libs " | $Xsed -e "s% -L$path % %g"` + #done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + temp_xrpath="$temp_xrpath -R$libdir" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles="$dlfiles" + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) dlfiles="$dlfiles $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles="$dlprefiles" + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) dlprefiles="$dlprefiles $lib" ;; + esac + done + + if test "$build_libtool_libs" = yes; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + deplibs="$deplibs System.ltframework" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test "$build_libtool_need_lc" = "yes"; then + deplibs="$deplibs -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release="" + versuffix="" + major="" + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $opt_dry_run || $RM conftest.c + cat > conftest.c </dev/null` + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null | + $GREP " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib="$potent_lib" + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; + *) potlib=`$ECHO "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | + $SED -e 10q | + $EGREP "$file_magic_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + $ECHO + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + $ECHO "*** I have the capability to make that library automatically link in when" + $ECHO "*** you link to this library. But I can only do this if you have a" + $ECHO "*** shared version of the library, which you do not appear to have" + $ECHO "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $ECHO "*** with $libname but no candidates were found. (...for file magic test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a file magic. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $a_deplib "*) + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + ;; + esac + fi + if test -n "$a_deplib" ; then + libname=`eval "\\$ECHO \"$libname_spec\""` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib="$potent_lib" # see symlink-check above in file_magic test + if eval "\$ECHO \"X$potent_lib\"" 2>/dev/null | $Xsed -e 10q | \ + $EGREP "$match_pattern_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + $ECHO + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + $ECHO "*** I have the capability to make that library automatically link in when" + $ECHO "*** you link to this library. But I can only do this if you have a" + $ECHO "*** shared version of the library, which you do not appear to have" + $ECHO "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a regex pattern. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs="" + tmp_deplibs=`$ECHO "X $deplibs" | $Xsed \ + -e 's/ -lc$//' -e 's/ -[LR][^ ]*//g'` + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + for i in $predeps $postdeps ; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$ECHO "X $tmp_deplibs" | $Xsed -e "s,$i,,"` + done + fi + if $ECHO "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' | + $GREP . >/dev/null; then + $ECHO + if test "X$deplibs_check_method" = "Xnone"; then + $ECHO "*** Warning: inter-library dependencies are not supported in this platform." + else + $ECHO "*** Warning: inter-library dependencies are not known to be supported." + fi + $ECHO "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + fi + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library with the System framework + newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's/ -lc / System.ltframework /'` + ;; + esac + + if test "$droppeddeps" = yes; then + if test "$module" = yes; then + $ECHO + $ECHO "*** Warning: libtool could not satisfy all declared inter-library" + $ECHO "*** dependencies of module $libname. Therefore, libtool will create" + $ECHO "*** a static module, that should work as long as the dlopening" + $ECHO "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + $ECHO + $ECHO "*** However, this would only work if libtool was able to extract symbol" + $ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could" + $ECHO "*** not find such a program. So, this module is probably useless." + $ECHO "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + $ECHO "*** The inter-library dependencies that have been dropped here will be" + $ECHO "*** automatically added whenever a program is linked with this library" + $ECHO "*** or is declared to -dlopen it." + + if test "$allow_undefined" = no; then + $ECHO + $ECHO "*** Since this library must not contain undefined symbols," + $ECHO "*** because either the platform does not support them or" + $ECHO "*** it was explicitly requested with -no-undefined," + $ECHO "*** libtool will only create a static version of it." + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + case $host in + *-*-darwin*) + newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + new_inherited_linker_flags=`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + deplibs=`$ECHO "X $deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + new_libs="$new_libs -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$new_libs $deplib" ;; + esac + ;; + *) new_libs="$new_libs $deplib" ;; + esac + done + deplibs="$new_libs" + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test "$build_libtool_libs" = yes; then + if test "$hardcode_into_libs" = yes; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath="$finalize_rpath" + test "$mode" != relink && rpath="$compile_rpath$rpath" + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + dep_rpath="$dep_rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + if test -n "$hardcode_libdir_flag_spec_ld"; then + eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" + else + eval dep_rpath=\"$hardcode_libdir_flag_spec\" + fi + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath="$finalize_shlibpath" + test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath" + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + shift + realname="$1" + shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib="$output_objdir/$realname" + linknames= + for link + do + linknames="$linknames $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$ECHO "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + test "X$libobjs" = "X " && libobjs= + + delfiles= + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" + export_symbols="$output_objdir/$libname.uexp" + delfiles="$delfiles $export_symbols" + fi + + orig_export_symbols= + case $host_os in + cygwin* | mingw* | cegcc*) + if test -n "$export_symbols" && test -z "$export_symbols_regex"; then + # exporting using user supplied symfile + if test "x`$SED 1q $export_symbols`" != xEXPORTS; then + # and it's NOT already a .def file. Must figure out + # which of the given symbols are data symbols and tag + # them as such. So, trigger use of export_symbols_cmds. + # export_symbols gets reassigned inside the "prepare + # the list of exported symbols" if statement, so the + # include_expsyms logic still works. + orig_export_symbols="$export_symbols" + export_symbols= + always_export_symbols=yes + fi + fi + ;; + esac + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $opt_dry_run || $RM $export_symbols + cmds=$export_symbols_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + func_len " $cmd" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + func_show_eval "$cmd" 'exit $?' + skipped_export=false + else + # The command line is too long to execute in one step. + func_verbose "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS="$save_ifs" + if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols="$export_symbols" + test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"' + fi + + if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + delfiles="$delfiles $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + tmp_deplibs="$tmp_deplibs $test_deplib" + ;; + esac + done + deplibs="$tmp_deplibs" + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec" && + test "$compiler_needs_object" = yes && + test -z "$libobjs"; then + # extract the archives, so we have objects to list. + # TODO: could optimize this to just extract one archive. + whole_archive_flag_spec= + fi + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + else + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $convenience + libobjs="$libobjs $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + fi + + if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + linker_flags="$linker_flags $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test "$mode" = relink; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test "X$skipped_export" != "X:" && + func_len " $test_cmds" && + len=$func_len_result && + test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise + # or, if using GNU ld and skipped_export is not :, use a linker + # script. + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + output_la=`$ECHO "X$output" | $Xsed -e "$basename"` + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + last_robj= + k=1 + + if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then + output=${output_objdir}/${output_la}.lnkscript + func_verbose "creating GNU ld script: $output" + $ECHO 'INPUT (' > $output + for obj in $save_libobjs + do + $ECHO "$obj" >> $output + done + $ECHO ')' >> $output + delfiles="$delfiles $output" + elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then + output=${output_objdir}/${output_la}.lnk + func_verbose "creating linker input file list: $output" + : > $output + set x $save_libobjs + shift + firstobj= + if test "$compiler_needs_object" = yes; then + firstobj="$1 " + shift + fi + for obj + do + $ECHO "$obj" >> $output + done + delfiles="$delfiles $output" + output=$firstobj\"$file_list_spec$output\" + else + if test -n "$save_libobjs"; then + func_verbose "creating reloadable object files..." + output=$output_objdir/$output_la-${k}.$objext + eval test_cmds=\"$reload_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + if test "X$objlist" = X || + test "$len" -lt "$max_cmd_len"; then + func_append objlist " $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test "$k" -eq 1 ; then + # The first file doesn't have a previous command to add. + eval concat_cmds=\"$reload_cmds $objlist $last_robj\" + else + # All subsequent reloadable object files will link in + # the last one created. + eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj~\$RM $last_robj\" + fi + last_robj=$output_objdir/$output_la-${k}.$objext + func_arith $k + 1 + k=$func_arith_result + output=$output_objdir/$output_la-${k}.$objext + objlist=$obj + func_len " $last_robj" + func_arith $len0 + $func_len_result + len=$func_arith_result + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\" + if test -n "$last_robj"; then + eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" + fi + delfiles="$delfiles $output" + + else + output= + fi + + if ${skipped_export-false}; then + func_verbose "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $opt_dry_run || $RM $export_symbols + libobjs=$output + # Append the command to create the export file. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + fi + + test -n "$save_libobjs" && + func_verbose "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs="$IFS"; IFS='~' + for cmd in $concat_cmds; do + IFS="$save_ifs" + $opt_silent || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + if test -n "$export_symbols_regex" && ${skipped_export-false}; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + + if ${skipped_export-false}; then + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols="$export_symbols" + test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"' + fi + + if test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + delfiles="$delfiles $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + fi + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + fi + + if test -n "$delfiles"; then + # Append the command to remove temporary files to $cmds. + eval cmds=\"\$cmds~\$RM $delfiles\" + fi + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $dlprefiles + libobjs="$libobjs $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $opt_silent || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + func_show_eval '${RM}r "$gentop"' + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test "$module" = yes || test "$export_dynamic" = yes; then + # On all known operating systems, these are identical. + dlname="$soname" + fi + fi + ;; + + obj) + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + func_warning "\`-dlopen' is ignored for objects" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "\`-l' and \`-L' are ignored for objects" ;; + esac + + test -n "$rpath" && \ + func_warning "\`-rpath' is ignored for objects" + + test -n "$xrpath" && \ + func_warning "\`-R' is ignored for objects" + + test -n "$vinfo" && \ + func_warning "\`-version-info' is ignored for objects" + + test -n "$release" && \ + func_warning "\`-release' is ignored for objects" + + case $output in + *.lo) + test -n "$objs$old_deplibs" && \ + func_fatal_error "cannot build library object \`$output' from non-libtool objects" + + libobj=$output + func_lo2o "$libobj" + obj=$func_lo2o_result + ;; + *) + libobj= + obj="$output" + ;; + esac + + # Delete the old objects. + $opt_dry_run || $RM $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # reload_cmds runs $LD directly, so let us get rid of + # -Wl from whole_archive_flag_spec and hope we can get by with + # turning comma into space.. + wl= + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" + reload_conv_objs=$reload_objs\ `$ECHO "X$tmp_whole_archive_flags" | $Xsed -e 's|,| |g'` + else + gentop="$output_objdir/${obj}x" + generated="$generated $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # Create the old-style object. + reload_objs="$objs$old_deplibs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test + + output="$obj" + func_execute_cmds "$reload_cmds" 'exit $?' + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + fi + + if test "$build_libtool_libs" != yes; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + fi + + if test -n "$pic_flag" || test "$pic_mode" != default; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output="$libobj" + func_execute_cmds "$reload_cmds" 'exit $?' + fi + + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) func_stripname '' '.exe' "$output" + output=$func_stripname_result.exe;; + esac + test -n "$vinfo" && \ + func_warning "\`-version-info' is ignored for programs" + + test -n "$release" && \ + func_warning "\`-release' is ignored for programs" + + test "$preload" = yes \ + && test "$dlopen_support" = unknown \ + && test "$dlopen_self" = unknown \ + && test "$dlopen_self_static" = unknown && \ + func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'` + finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'` + ;; + esac + + case $host in + *-*-darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + # But is supposedly fixed on 10.4 or later (yay!). + if test "$tagname" = CXX ; then + case ${MACOSX_DEPLOYMENT_TARGET-10.0} in + 10.[0123]) + compile_command="$compile_command ${wl}-bind_at_load" + finalize_command="$finalize_command ${wl}-bind_at_load" + ;; + esac + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + new_libs="$new_libs -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$new_libs $deplib" ;; + esac + ;; + *) new_libs="$new_libs $deplib" ;; + esac + done + compile_deplibs="$new_libs" + + + compile_command="$compile_command $compile_deplibs" + finalize_command="$finalize_command $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + ::) dllsearchpath=$libdir;; + *) dllsearchpath="$dllsearchpath:$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) dllsearchpath="$dllsearchpath:$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath="$rpath" + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath="$rpath" + + if test -n "$libobjs" && test "$build_old_libs" = yes; then + # Transform all the library objects into standard objects. + compile_command=`$ECHO "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + finalize_command=`$ECHO "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + fi + + func_generate_dlsyms "$outputname" "@PROGRAM@" "no" + + # template prelinking step + if test -n "$prelink_cmds"; then + func_execute_cmds "$prelink_cmds" 'exit $?' + fi + + wrappers_required=yes + case $host in + *cygwin* | *mingw* ) + if test "$build_libtool_libs" != yes; then + wrappers_required=no + fi + ;; + *cegcc) + # Disable wrappers for cegcc, we are cross compiling anyway. + wrappers_required=no + ;; + *) + if test "$need_relink" = no || test "$build_libtool_libs" != yes; then + wrappers_required=no + fi + ;; + esac + if test "$wrappers_required" = no; then + # Replace the output file specification. + compile_command=`$ECHO "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + link_command="$compile_command$compile_rpath" + + # We have no uninstalled library dependencies, so finalize right now. + exit_status=0 + func_show_eval "$link_command" 'exit_status=$?' + + # Delete the generated files. + if test -f "$output_objdir/${outputname}S.${objext}"; then + func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' + fi + + exit $exit_status + fi + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + rpath="$rpath$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test "$no_install" = yes; then + # We don't need to create a wrapper script. + link_command="$compile_var$compile_command$compile_rpath" + # Replace the output file specification. + link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $opt_dry_run || $RM $output + # Link the executable and exit + func_show_eval "$link_command" 'exit $?' + exit $EXIT_SUCCESS + fi + + if test "$hardcode_action" = relink; then + # Fast installation is not supported + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + + func_warning "this platform does not like uninstalled shared libraries" + func_warning "\`$output' will be relinked during installation" + else + if test "$fast_install" != no; then + link_command="$finalize_var$compile_command$finalize_rpath" + if test "$fast_install" = yes; then + relink_command=`$ECHO "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` + else + # fast_install is set to needless + relink_command= + fi + else + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + fi + fi + + # Replace the output file specification. + link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname + + func_show_eval "$link_command" 'exit $?' + + # Now create the wrapper script. + func_verbose "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"` + fi + + # Quote $ECHO for shipping. + if test "X$ECHO" = "X$SHELL $progpath --fallback-echo"; then + case $progpath in + [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";; + *) qecho="$SHELL `pwd`/$progpath --fallback-echo";; + esac + qecho=`$ECHO "X$qecho" | $Xsed -e "$sed_quote_subst"` + else + qecho=`$ECHO "X$ECHO" | $Xsed -e "$sed_quote_subst"` + fi + + # Only actually do things if not in dry run mode. + $opt_dry_run || { + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) func_stripname '' '.exe' "$output" + output=$func_stripname_result ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + func_stripname '' '.exe' "$outputname" + outputname=$func_stripname_result ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + func_dirname_and_basename "$output" "" "." + output_name=$func_basename_result + output_path=$func_dirname_result + cwrappersource="$output_path/$objdir/lt-$output_name.c" + cwrapper="$output_path/$output_name.exe" + $RM $cwrappersource $cwrapper + trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + func_emit_cwrapperexe_src > $cwrappersource + + # The wrapper executable is built using the $host compiler, + # because it contains $host paths and files. If cross- + # compiling, it, like the target executable, must be + # executed on the $host or under an emulation environment. + $opt_dry_run || { + $LTCC $LTCFLAGS -o $cwrapper $cwrappersource + $STRIP $cwrapper + } + + # Now, create the wrapper script for func_source use: + func_ltwrapper_scriptname $cwrapper + $RM $func_ltwrapper_scriptname_result + trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 + $opt_dry_run || { + # note: this script will not be executed, so do not chmod. + if test "x$build" = "x$host" ; then + $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result + else + func_emit_wrapper no > $func_ltwrapper_scriptname_result + fi + } + ;; + * ) + $RM $output + trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 + + func_emit_wrapper no > $output + chmod +x $output + ;; + esac + } + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + if test "$build_libtool_libs" = convenience; then + oldobjs="$libobjs_save $symfileobj" + addlibs="$convenience" + build_libtool_libs=no + else + if test "$build_libtool_libs" = module; then + oldobjs="$libobjs_save" + build_libtool_libs=no + else + oldobjs="$old_deplibs $non_pic_objects" + if test "$preload" = yes && test -f "$symfileobj"; then + oldobjs="$oldobjs $symfileobj" + fi + fi + addlibs="$old_convenience" + fi + + if test -n "$addlibs"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $addlibs + oldobjs="$oldobjs $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then + cmds=$old_archive_from_new_cmds + else + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $dlprefiles + oldobjs="$oldobjs $func_extract_archives_result" + fi + + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + func_basename "$obj" + $ECHO "$func_basename_result" + done | sort | sort -uc >/dev/null 2>&1); then + : + else + $ECHO "copying selected object files to avoid basename conflicts..." + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + func_mkdir_p "$gentop" + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + func_basename "$obj" + objbase="$func_basename_result" + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + func_arith $counter + 1 + counter=$func_arith_result + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + oldobjs="$oldobjs $gentop/$newobj" + ;; + *) oldobjs="$oldobjs $obj" ;; + esac + done + fi + eval cmds=\"$old_archive_cmds\" + + func_len " $cmds" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + func_verbose "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + oldobjs= + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + eval test_cmds=\"$old_archive_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + for obj in $save_oldobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + func_append objlist " $obj" + if test "$len" -lt "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj" ; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" + objlist= + len=$len0 + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test "X$oldobjs" = "X" ; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + func_execute_cmds "$cmds" 'exit $?' + done + + test -n "$generated" && \ + func_show_eval "${RM}r$generated" + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test "$build_old_libs" = yes && old_library="$libname.$libext" + func_verbose "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"` + if test "$hardcode_automatic" = yes ; then + relink_command= + fi + + # Only create the output if not a dry run. + $opt_dry_run || { + for installed in no yes; do + if test "$installed" = yes; then + if test -z "$install_libdir"; then + break + fi + output="$output_objdir/$outputname"i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + func_basename "$deplib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "\`$deplib' is not a valid libtool archive" + newdependency_libs="$newdependency_libs $libdir/$name" + ;; + *) newdependency_libs="$newdependency_libs $deplib" ;; + esac + done + dependency_libs="$newdependency_libs" + newdlfiles= + + for lib in $dlfiles; do + case $lib in + *.la) + func_basename "$lib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "\`$lib' is not a valid libtool archive" + newdlfiles="$newdlfiles $libdir/$name" + ;; + *) newdlfiles="$newdlfiles $lib" ;; + esac + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + *.la) + # Only pass preopened files to the pseudo-archive (for + # eventual linking with the app. that links it) if we + # didn't already link the preopened objects directly into + # the library: + func_basename "$lib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "\`$lib' is not a valid libtool archive" + newdlprefiles="$newdlprefiles $libdir/$name" + ;; + esac + done + dlprefiles="$newdlprefiles" + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + newdlfiles="$newdlfiles $abs" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + newdlprefiles="$newdlprefiles $abs" + done + dlprefiles="$newdlprefiles" + fi + $RM $output + # place dlname in correct position for cygwin + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; + esac + $ECHO > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Linker flags that can not go in dependency_libs. +inherited_linker_flags='$new_inherited_linker_flags' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Names of additional weak libraries provided by this library +weak_library_names='$weak_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test "$installed" = no && test "$need_relink" = yes; then + $ECHO >> $output "\ +relink_command=\"$relink_command\"" + fi + done + } + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' + ;; + esac + exit $EXIT_SUCCESS +} + +{ test "$mode" = link || test "$mode" = relink; } && + func_mode_link ${1+"$@"} + + +# func_mode_uninstall arg... +func_mode_uninstall () +{ + $opt_debug + RM="$nonopt" + files= + rmforce= + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + for arg + do + case $arg in + -f) RM="$RM $arg"; rmforce=yes ;; + -*) RM="$RM $arg" ;; + *) files="$files $arg" ;; + esac + done + + test -z "$RM" && \ + func_fatal_help "you must specify an RM program" + + rmdirs= + + origobjdir="$objdir" + for file in $files; do + func_dirname "$file" "" "." + dir="$func_dirname_result" + if test "X$dir" = X.; then + objdir="$origobjdir" + else + objdir="$dir/$origobjdir" + fi + func_basename "$file" + name="$func_basename_result" + test "$mode" = uninstall && objdir="$dir" + + # Remember objdir for removal later, being careful to avoid duplicates + if test "$mode" = clean; then + case " $rmdirs " in + *" $objdir "*) ;; + *) rmdirs="$rmdirs $objdir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if { test -L "$file"; } >/dev/null 2>&1 || + { test -h "$file"; } >/dev/null 2>&1 || + test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif test "$rmforce" = yes; then + continue + fi + + rmfiles="$file" + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if func_lalib_p "$file"; then + func_source $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + rmfiles="$rmfiles $objdir/$n" + done + test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" + + case "$mode" in + clean) + case " $library_names " in + # " " in the beginning catches empty $dlname + *" $dlname "*) ;; + *) rmfiles="$rmfiles $objdir/$dlname" ;; + esac + test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if func_lalib_p "$file"; then + + # Read the .lo file + func_source $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" && + test "$pic_object" != none; then + rmfiles="$rmfiles $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" && + test "$non_pic_object" != none; then + rmfiles="$rmfiles $dir/$non_pic_object" + fi + fi + ;; + + *) + if test "$mode" = clean ; then + noexename=$name + case $file in + *.exe) + func_stripname '' '.exe' "$file" + file=$func_stripname_result + func_stripname '' '.exe' "$name" + noexename=$func_stripname_result + # $file with .exe has already been added to rmfiles, + # add $file without .exe + rmfiles="$rmfiles $file" + ;; + esac + # Do a test to see if this is a libtool program. + if func_ltwrapper_p "$file"; then + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + relink_command= + func_source $func_ltwrapper_scriptname_result + rmfiles="$rmfiles $func_ltwrapper_scriptname_result" + else + relink_command= + func_source $dir/$noexename + fi + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" + if test "$fast_install" = yes && test -n "$relink_command"; then + rmfiles="$rmfiles $objdir/lt-$name" + fi + if test "X$noexename" != "X$name" ; then + rmfiles="$rmfiles $objdir/lt-${noexename}.c" + fi + fi + fi + ;; + esac + func_show_eval "$RM $rmfiles" 'exit_status=1' + done + objdir="$origobjdir" + + # Try to remove the ${objdir}s in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + func_show_eval "rmdir $dir >/dev/null 2>&1" + fi + done + + exit $exit_status +} + +{ test "$mode" = uninstall || test "$mode" = clean; } && + func_mode_uninstall ${1+"$@"} + +test -z "$mode" && { + help="$generic_help" + func_fatal_help "you must specify a MODE" +} + +test -z "$exec_cmd" && \ + func_fatal_help "invalid operation mode \`$mode'" + +if test -n "$exec_cmd"; then + eval exec "$exec_cmd" + exit $EXIT_FAILURE +fi + +exit $exit_status + + +# The TAGs below are defined such that we never get into a situation +# in which we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +build_libtool_libs=no +build_old_libs=yes +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: +# vi:sw=2 + diff --git a/config/missing b/config/missing new file mode 100755 index 00000000000..28055d2ae6f --- /dev/null +++ b/config/missing @@ -0,0 +1,376 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. + +scriptversion=2009-04-28.21; # UTC + +# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006, +# 2008, 2009 Free Software Foundation, Inc. +# Originally by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +run=: +sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' +sed_minuso='s/.* -o \([^ ]*\).*/\1/p' + +# In the cases where this matters, `missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +msg="missing on your system" + +case $1 in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + # Exit code 63 means version mismatch. This often happens + # when the user try to use an ancient version of a tool on + # a file that requires a minimum version. In this case we + # we should proceed has if the program had been absent, or + # if --run hadn't been passed. + if test $? = 63; then + run=: + msg="probably too old" + fi + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + autom4te touch the output file, or create a stub one + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + tar try tar, gnutar, gtar, then tar without non-portable flags + yacc create \`y.tab.[ch]', if possible, from existing .[ch] + +Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and +\`g' are ignored when checking the name. + +Send bug reports to ." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + +esac + +# normalize program name to check for. +program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + +# Now exit if we have it, but it failed. Also exit now if we +# don't have it and --version was passed (most likely to detect +# the program). This is about non-GNU programs, so use $1 not +# $program. +case $1 in + lex*|yacc*) + # Not GNU programs, they don't have --version. + ;; + + tar*) + if test -n "$run"; then + echo 1>&2 "ERROR: \`tar' requires --run" + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + exit 1 + fi + ;; + + *) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + # Could not run --version or --help. This is probably someone + # running `$TOOL --version' or `$TOOL --help' to check whether + # $TOOL exists and not knowing $TOOL uses missing. + exit 1 + fi + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case $program in + aclocal*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acinclude.m4' or \`${configure_ac}'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`${configure_ac}'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acconfig.h' or \`${configure_ac}'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case $f in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + autom4te*) + echo 1>&2 "\ +WARNING: \`$1' is needed, but is $msg. + You might have modified some files without having the + proper tools for further handling them. + You can get \`$1' as part of \`Autoconf' from any GNU + archive site." + + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo "#! /bin/sh" + echo "# Created by GNU Automake missing as a replacement of" + echo "# $ $@" + echo "exit 0" + chmod +x $file + exit 1 + fi + ;; + + bison*|yacc*) + echo 1>&2 "\ +WARNING: \`$1' $msg. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if test $# -ne 1; then + eval LASTARG="\${$#}" + case $LASTARG in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if test ! -f y.tab.h; then + echo >y.tab.h + fi + if test ! -f y.tab.c; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex*|flex*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if test $# -ne 1; then + eval LASTARG="\${$#}" + case $LASTARG in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if test ! -f lex.yy.c; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a dependency of a manual page. You may need the + \`Help2man' package in order for those modifications to take + effect. You can get \`Help2man' from any GNU archive site." + + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit $? + fi + ;; + + makeinfo*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + # The file to touch is that specified with -o ... + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -z "$file"; then + # ... or it is the one specified with @setfilename ... + infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n ' + /^@setfilename/{ + s/.* \([^ ]*\) *$/\1/ + p + q + }' $infile` + # ... or it is derived from the source name (dir/f.texi becomes f.info) + test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info + fi + # If the file does not exist, the user really needs makeinfo; + # let's fail without touching anything. + test -f $file || exit 1 + touch $file + ;; + + tar*) + shift + + # We have already tried tar in the generic part. + # Look for gnutar/gtar before invocation to avoid ugly error + # messages. + if (gnutar --version > /dev/null 2>&1); then + gnutar "$@" && exit 0 + fi + if (gtar --version > /dev/null 2>&1); then + gtar "$@" && exit 0 + fi + firstarg="$1" + if shift; then + case $firstarg in + *o*) + firstarg=`echo "$firstarg" | sed s/o//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + case $firstarg in + *h*) + firstarg=`echo "$firstarg" | sed s/h//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + fi + + echo 1>&2 "\ +WARNING: I can't seem to be able to run \`tar' with the given arguments. + You may want to install GNU tar or Free paxutils, or check the + command line arguments." + exit 1 + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and is $msg. + You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequisites for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/configure b/configure new file mode 100755 index 00000000000..194fa3decbb --- /dev/null +++ b/configure @@ -0,0 +1,13149 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.67 for yaml 0.1.4. +# +# Report bugs to . +# +# +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software +# Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + # We cannot yet assume a decent shell, so we have to provide a + # neutralization value for shells without unset; and this also + # works around shells that cannot unset nonexistent variables. + BASH_ENV=/dev/null + ENV=/dev/null + (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org and http://pyyaml.org/newticket?component=libyaml about +$0: your system, including any error possibly output before +$0: this message. Then install a modern shell, or manually +$0: run the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + + +# Check that we are running under the correct shell. +SHELL=${CONFIG_SHELL-/bin/sh} + +case X$lt_ECHO in +X*--fallback-echo) + # Remove one level of quotation (which was required for Make). + ECHO=`echo "$lt_ECHO" | sed 's,\\\\\$\\$0,'$0','` + ;; +esac + +ECHO=${lt_ECHO-echo} +if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X$1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then + # Yippee, $ECHO works! + : +else + # Restart under the correct shell. + exec $SHELL "$0" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat <<_LT_EOF +$* +_LT_EOF + exit 0 +fi + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +if test -z "$lt_ECHO"; then + if test "X${echo_test_string+set}" != Xset; then + # find a string as large as possible, as long as the shell can cope with it + for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do + # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... + if { echo_test_string=`eval $cmd`; } 2>/dev/null && + { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null + then + break + fi + done + fi + + if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && + echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + : + else + # The Solaris, AIX, and Digital Unix default echo programs unquote + # backslashes. This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # + # So, first we look for a working echo in the user's PATH. + + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for dir in $PATH /usr/ucb; do + IFS="$lt_save_ifs" + if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && + test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + ECHO="$dir/echo" + break + fi + done + IFS="$lt_save_ifs" + + if test "X$ECHO" = Xecho; then + # We didn't find a better echo, so look for alternatives. + if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' && + echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # This shell has a builtin print -r that does the trick. + ECHO='print -r' + elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } && + test "X$CONFIG_SHELL" != X/bin/ksh; then + # If we have ksh, try running configure again with it. + ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} + export ORIGINAL_CONFIG_SHELL + CONFIG_SHELL=/bin/ksh + export CONFIG_SHELL + exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"} + else + # Try using printf. + ECHO='printf %s\n' + if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && + echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # Cool, printf works + : + elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL + export CONFIG_SHELL + SHELL="$CONFIG_SHELL" + export SHELL + ECHO="$CONFIG_SHELL $0 --fallback-echo" + elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + ECHO="$CONFIG_SHELL $0 --fallback-echo" + else + # maybe with a smaller string... + prev=: + + for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do + if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null + then + break + fi + prev="$cmd" + done + + if test "$prev" != 'sed 50q "$0"'; then + echo_test_string=`eval $prev` + export echo_test_string + exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"} + else + # Oops. We lost completely, so just stick with echo. + ECHO=echo + fi + fi + fi + fi + fi +fi + +# Copy echo and quote the copy suitably for passing to libtool from +# the Makefile, instead of quoting the original, which is used later. +lt_ECHO=$ECHO +if test "X$lt_ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then + lt_ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo" +fi + + + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='yaml' +PACKAGE_TARNAME='yaml' +PACKAGE_VERSION='0.1.4' +PACKAGE_STRING='yaml 0.1.4' +PACKAGE_BUGREPORT='http://pyyaml.org/newticket?component=libyaml' +PACKAGE_URL='' + +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='am__EXEEXT_FALSE +am__EXEEXT_TRUE +LTLIBOBJS +LIBOBJS +DOXYGEN_FALSE +DOXYGEN_TRUE +DOXYGEN +OTOOL64 +OTOOL +LIPO +NMEDIT +DSYMUTIL +lt_ECHO +RANLIB +AR +OBJDUMP +NM +ac_ct_DUMPBIN +DUMPBIN +LD +FGREP +EGREP +GREP +SED +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +LIBTOOL +LN_S +CPP +am__fastdepCC_FALSE +am__fastdepCC_TRUE +CCDEPMODE +AMDEPBACKSLASH +AMDEP_FALSE +AMDEP_TRUE +am__quote +am__include +DEPDIR +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +YAML_LT_AGE +YAML_LT_REVISION +YAML_LT_CURRENT +YAML_LT_RELEASE +am__untar +am__tar +AMTAR +am__leading_dot +SET_MAKE +AWK +mkdir_p +MKDIR_P +INSTALL_STRIP_PROGRAM +STRIP +install_sh +MAKEINFO +AUTOHEADER +AUTOMAKE +AUTOCONF +ACLOCAL +VERSION +PACKAGE +CYGPATH_W +am__isrc +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_dependency_tracking +enable_shared +enable_static +with_pic +enable_fast_install +with_gnu_ld +enable_libtool_lock +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used" >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +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 yaml 0.1.4 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/yaml] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of yaml 0.1.4:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors + --enable-shared[=PKGS] build shared libraries [default=yes] + --enable-static[=PKGS] build static libraries [default=yes] + --enable-fast-install[=PKGS] + optimize for fast installation [default=yes] + --disable-libtool-lock avoid locking (might break parallel builds) + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-pic try to use only PIC/non-PIC objects [default=use + both] + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CPP C preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to . +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +yaml configure 0.1.4 +generated by GNU Autoconf 2.67 + +Copyright (C) 2010 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval "test \"\${$3+set}\"" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval "test \"\${$3+set}\"" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* 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 $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + +} # ac_fn_c_check_func + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval "test \"\${$3+set}\"" = set; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval "test \"\${$3+set}\"" = set; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} +( $as_echo "## ------------------------------------------------------------ ## +## Report this to http://pyyaml.org/newticket?component=libyaml ## +## ------------------------------------------------------------ ##" + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval "test \"\${$3+set}\"" = set; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + +} # ac_fn_c_check_header_mongrel + +# ac_fn_c_check_type LINENO TYPE VAR INCLUDES +# ------------------------------------------- +# Tests whether TYPE exists after having included INCLUDES, setting cache +# variable VAR accordingly. +ac_fn_c_check_type () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval "test \"\${$3+set}\"" = set; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof ($2)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof (($2))) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + eval "$3=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + +} # ac_fn_c_check_type +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 yaml $as_me 0.1.4, which was +generated by GNU Autoconf 2.67. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5 ; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +ac_aux_dir= +for ac_dir in config "$srcdir"/config; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in config \"$srcdir\"/config" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +ac_config_headers="$ac_config_headers config.h" + +am__api_version='1.11' + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +$as_echo_n "checking whether build environment is sane... " >&6; } +# Just in case +sleep 1 +echo timestamp > conftest.file +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5 ;; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + as_fn_error $? "unsafe srcdir value: \`$srcdir'" "$LINENO" 5 ;; +esac + +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + rm -f conftest.file + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + as_fn_error $? "ls -t appears to fail. Make sure there is not a broken +alias in your environment" "$LINENO" 5 + fi + + test "$2" = conftest.file + ) +then + # Ok. + : +else + as_fn_error $? "newly created file is older than distributed files! +Check your system clock" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` + +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` + +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`missing' script is too old or missing" >&5 +$as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} +fi + +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_STRIP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 +$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if test "${ac_cv_path_mkdir+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + test -d ./--version && rmdir ./--version + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + MKDIR_P="$ac_install_sh -d" + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +mkdir_p="$MKDIR_P" +case $mkdir_p in + [\\/$]* | ?:[\\/]*) ;; + */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; +esac + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_AWK+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\"" = set; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE='yaml' + VERSION='0.1.4' + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSION "$VERSION" +_ACEOF + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +# Always define AMTAR for backward compatibility. + +AMTAR=${AMTAR-"${am_missing_run}tar"} + +am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' + + + + + + +# Define macro variables for the package version numbers. + +$as_echo "#define YAML_VERSION_MAJOR 0" >>confdefs.h + + +$as_echo "#define YAML_VERSION_MINOR 1" >>confdefs.h + + +$as_echo "#define YAML_VERSION_PATCH 4" >>confdefs.h + + +$as_echo "#define YAML_VERSION_STRING \"0.1.4\"" >>confdefs.h + + +# Define substitutions for the libtool version numbers. +YAML_LT_RELEASE=0 +YAML_LT_CURRENT=2 +YAML_LT_REVISION=2 +YAML_LT_AGE=0 + + + + + +# Note: in order to update checks, run `autoscan` and look through "configure.scan". + +# Checks for programs. +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5 ; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5 ; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5 ; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5 ; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if test "${ac_cv_objext+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5 ; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if test "${ac_cv_c_compiler_gnu+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if test "${ac_cv_prog_cc_g+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if test "${ac_cv_prog_cc_c89+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +DEPDIR="${am__leading_dot}deps" + +ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 +$as_echo_n "checking for style of include used by $am_make... " >&6; } +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from `make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 +$as_echo "$_am_result" >&6; } +rm -f confinc confmf + +# Check whether --enable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then : + enableval=$enable_dependency_tracking; +fi + +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi + if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + + +depcc="$CC" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvisualcpp | msvcmsys) + # This compiler won't grok `-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5 ; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 +$as_echo_n "checking whether ln -s works... " >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 +$as_echo "no, using $LN_S" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\"" = set; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +case `pwd` in + *\ * | *\ *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 +$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; +esac + + + +macro_version='2.2.6b' +macro_revision='1.3017' + + + + + + + + + + + + + +ltmain="$ac_aux_dir/ltmain.sh" + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if test "${ac_cv_build+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5 ;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if test "${ac_cv_host+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5 ;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if test "${ac_cv_path_SED+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_SED" && $as_test_x "$ac_path_SED"; } || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if test "${ac_cv_path_GREP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if test "${ac_cv_path_EGREP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 +$as_echo_n "checking for fgrep... " >&6; } +if test "${ac_cv_path_FGREP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 + then ac_cv_path_FGREP="$GREP -F" + else + if test -z "$FGREP"; then + ac_path_FGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in fgrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_FGREP" && $as_test_x "$ac_path_FGREP"; } || continue +# Check for GNU ac_path_FGREP and select it if it is found. + # Check for GNU $ac_path_FGREP +case `"$ac_path_FGREP" --version 2>&1` in +*GNU*) + ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'FGREP' >> "conftest.nl" + "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_FGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_FGREP="$ac_path_FGREP" + ac_path_FGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_FGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_FGREP"; then + as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_FGREP=$FGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 +$as_echo "$ac_cv_path_FGREP" >&6; } + FGREP="$ac_cv_path_FGREP" + + +test -z "$GREP" && GREP=grep + + + + + + + + + + + + + + + + + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if test "${lt_cv_path_LD+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if test "${lt_cv_prog_gnu_ld+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 +$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } +if test "${lt_cv_path_NM+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + : ${lt_cv_path_NM=no} +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 +$as_echo "$lt_cv_path_NM" >&6; } +if test "$lt_cv_path_NM" != "no"; then + NM="$lt_cv_path_NM" +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$ac_tool_prefix"; then + for ac_prog in "dumpbin -symbols" "link -dump -symbols" + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_DUMPBIN+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DUMPBIN"; then + ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DUMPBIN=$ac_cv_prog_DUMPBIN +if test -n "$DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 +$as_echo "$DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$DUMPBIN" && break + done +fi +if test -z "$DUMPBIN"; then + ac_ct_DUMPBIN=$DUMPBIN + for ac_prog in "dumpbin -symbols" "link -dump -symbols" +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_DUMPBIN+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DUMPBIN"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN +if test -n "$ac_ct_DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 +$as_echo "$ac_ct_DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_DUMPBIN" && break +done + + if test "x$ac_ct_DUMPBIN" = x; then + DUMPBIN=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DUMPBIN=$ac_ct_DUMPBIN + fi +fi + + + if test "$DUMPBIN" != ":"; then + NM="$DUMPBIN" + fi +fi +test -z "$NM" && NM=nm + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 +$as_echo_n "checking the name lister ($NM) interface... " >&6; } +if test "${lt_cv_nm_interface+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:4738: $ac_compile\"" >&5) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&5 + (eval echo "\"\$as_me:4741: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&5 + (eval echo "\"\$as_me:4744: output\"" >&5) + cat conftest.out >&5 + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 +$as_echo "$lt_cv_nm_interface" >&6; } + +# find the maximum length of command line arguments +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 +$as_echo_n "checking the maximum length of command line arguments... " >&6; } +if test "${lt_cv_sys_max_cmd_len+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8 ; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test "X"`$SHELL $0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \ + = "XX$teststring$teststring"; } >/dev/null 2>&1 && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac + +fi + +if test -n $lt_cv_sys_max_cmd_len ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 +$as_echo "$lt_cv_sys_max_cmd_len" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } +fi +max_cmd_len=$lt_cv_sys_max_cmd_len + + + + + + +: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 +$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } +# Try some XSI features +xsi_shell=no +( _lt_dummy="a/b/c" + test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \ + = c,a/b,, \ + && eval 'test $(( 1 + 1 )) -eq 2 \ + && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ + && xsi_shell=yes +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 +$as_echo "$xsi_shell" >&6; } + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 +$as_echo_n "checking whether the shell understands \"+=\"... " >&6; } +lt_shell_append=no +( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ + >/dev/null 2>&1 \ + && lt_shell_append=yes +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 +$as_echo "$lt_shell_append" >&6; } + + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi + + + + + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 +$as_echo_n "checking for $LD option to reload object files... " >&6; } +if test "${lt_cv_ld_reload_flag+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_reload_flag='-r' +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 +$as_echo "$lt_cv_ld_reload_flag" >&6; } +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +case $host_os in + darwin*) + if test "$GCC" = yes; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' + else + reload_cmds='$LD$reload_flag -o $output$reload_objs' + fi + ;; +esac + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_OBJDUMP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_OBJDUMP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + +test -z "$OBJDUMP" && OBJDUMP=objdump + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 +$as_echo_n "checking how to recognize dependent libraries... " >&6; } +if test "${lt_cv_deplibs_check_method+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# `unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# which responds to the $file_magic_cmd with a given extended regex. +# If you have `file' or equivalent on your system and you're not sure +# whether `pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[4-9]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[45]*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + if ( file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]' + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[3-9]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 +$as_echo "$lt_cv_deplibs_check_method" >&6; } +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + + + + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. +set dummy ${ac_tool_prefix}ar; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_AR+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AR="${ac_tool_prefix}ar" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_AR"; then + ac_ct_AR=$AR + # Extract the first word of "ar", so it can be a program name with args. +set dummy ar; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_AR+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_AR="ar" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +else + AR="$ac_cv_prog_AR" +fi + +test -z "$AR" && AR=ar +test -z "$AR_FLAGS" && AR_FLAGS=cru + + + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_STRIP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +test -z "$STRIP" && STRIP=: + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_RANLIB+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +test -z "$RANLIB" && RANLIB=: + + + + + + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 +$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } +if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[ABCDGISTW]' + ;; +hpux*) + if test "$host_cpu" = ia64; then + symcode='[ABCDEGRST]' + fi + ;; +irix* | nonstopux*) + symcode='[BCDEGRST]' + ;; +osf*) + symcode='[BCDEGQRST]' + ;; +solaris*) + symcode='[BDRT]' + ;; +sco3.2v5*) + symcode='[DT]' + ;; +sysv4.2uw2*) + symcode='[DT]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[ABDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function + # and D for any global variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK '"\ +" {last_section=section; section=\$ 3};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ +" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ +" s[1]~/^[@?]/{print s[1], s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Now try to grab the symbols. + nlist=conftest.nm + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\""; } >&5 + (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_save_LIBS="$LIBS" + lt_save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS="$lt_save_LIBS" + CFLAGS="$lt_save_CFLAGS" + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } +fi + + + + + + + + + + + + + + + + + + + + + + + +# Check whether --enable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then : + enableval=$enable_libtool_lock; +fi + +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '#line 5939 "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 +$as_echo_n "checking whether the C compiler needs -belf... " >&6; } +if test "${lt_cv_cc_needs_belf+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_cc_needs_belf=yes +else + lt_cv_cc_needs_belf=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 +$as_echo "$lt_cv_cc_needs_belf" >&6; } + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +sparc*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) LD="${LD-ld} -m elf64_sparc" ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks="$enable_libtool_lock" + + + case $host_os in + rhapsody* | darwin*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. +set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_DSYMUTIL+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DSYMUTIL"; then + ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DSYMUTIL=$ac_cv_prog_DSYMUTIL +if test -n "$DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 +$as_echo "$DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DSYMUTIL"; then + ac_ct_DSYMUTIL=$DSYMUTIL + # Extract the first word of "dsymutil", so it can be a program name with args. +set dummy dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_DSYMUTIL+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DSYMUTIL"; then + ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL +if test -n "$ac_ct_DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 +$as_echo "$ac_ct_DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DSYMUTIL" = x; then + DSYMUTIL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DSYMUTIL=$ac_ct_DSYMUTIL + fi +else + DSYMUTIL="$ac_cv_prog_DSYMUTIL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. +set dummy ${ac_tool_prefix}nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_NMEDIT+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NMEDIT"; then + ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +NMEDIT=$ac_cv_prog_NMEDIT +if test -n "$NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 +$as_echo "$NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_NMEDIT"; then + ac_ct_NMEDIT=$NMEDIT + # Extract the first word of "nmedit", so it can be a program name with args. +set dummy nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_NMEDIT+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_NMEDIT"; then + ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_NMEDIT="nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT +if test -n "$ac_ct_NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 +$as_echo "$ac_ct_NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_NMEDIT" = x; then + NMEDIT=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + NMEDIT=$ac_ct_NMEDIT + fi +else + NMEDIT="$ac_cv_prog_NMEDIT" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. +set dummy ${ac_tool_prefix}lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_LIPO+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LIPO"; then + ac_cv_prog_LIPO="$LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_LIPO="${ac_tool_prefix}lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LIPO=$ac_cv_prog_LIPO +if test -n "$LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 +$as_echo "$LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_LIPO"; then + ac_ct_LIPO=$LIPO + # Extract the first word of "lipo", so it can be a program name with args. +set dummy lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_LIPO+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_LIPO"; then + ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_LIPO="lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO +if test -n "$ac_ct_LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 +$as_echo "$ac_ct_LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_LIPO" = x; then + LIPO=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + LIPO=$ac_ct_LIPO + fi +else + LIPO="$ac_cv_prog_LIPO" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_OTOOL+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL"; then + ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_OTOOL="${ac_tool_prefix}otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL=$ac_cv_prog_OTOOL +if test -n "$OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 +$as_echo "$OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL"; then + ac_ct_OTOOL=$OTOOL + # Extract the first word of "otool", so it can be a program name with args. +set dummy otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_OTOOL+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL"; then + ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_OTOOL="otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL +if test -n "$ac_ct_OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 +$as_echo "$ac_ct_OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL" = x; then + OTOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL=$ac_ct_OTOOL + fi +else + OTOOL="$ac_cv_prog_OTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_OTOOL64+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL64"; then + ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL64=$ac_cv_prog_OTOOL64 +if test -n "$OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 +$as_echo "$OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL64"; then + ac_ct_OTOOL64=$OTOOL64 + # Extract the first word of "otool64", so it can be a program name with args. +set dummy otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_OTOOL64+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL64"; then + ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_OTOOL64="otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 +if test -n "$ac_ct_OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 +$as_echo "$ac_ct_OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL64" = x; then + OTOOL64=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL64=$ac_ct_OTOOL64 + fi +else + OTOOL64="$ac_cv_prog_OTOOL64" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 +$as_echo_n "checking for -single_module linker flag... " >&6; } +if test "${lt_cv_apple_cc_single_mod+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_apple_cc_single_mod=no + if test -z "${LT_MULTI_MODULE}"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&5 + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 +$as_echo "$lt_cv_apple_cc_single_mod" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 +$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } +if test "${lt_cv_ld_exported_symbols_list+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_ld_exported_symbols_list=yes +else + lt_cv_ld_exported_symbols_list=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 +$as_echo "$lt_cv_ld_exported_symbols_list" >&6; } + case $host_os in + rhapsody* | darwin1.[012]) + _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[91]*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + 10.[012]*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test "$lt_cv_apple_cc_single_mod" = "yes"; then + _lt_dar_single_mod='$single_module' + fi + if test "$lt_cv_ld_exported_symbols_list" = "yes"; then + _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + if test "$DSYMUTIL" != ":"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if test "${ac_cv_header_stdc+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + 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 eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in dlfcn.h +do : + ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default +" +if test "x$ac_cv_header_dlfcn_h" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DLFCN_H 1 +_ACEOF + +fi + +done + + + +# Set options + + + + enable_dlopen=no + + + enable_win32_dll=no + + + # Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then : + enableval=$enable_shared; p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_shared=yes +fi + + + + + + + + + + # Check whether --enable-static was given. +if test "${enable_static+set}" = set; then : + enableval=$enable_static; p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_static=yes +fi + + + + + + + + + + +# Check whether --with-pic was given. +if test "${with_pic+set}" = set; then : + withval=$with_pic; pic_mode="$withval" +else + pic_mode=default +fi + + +test -z "$pic_mode" && pic_mode=default + + + + + + + + # Check whether --enable-fast-install was given. +if test "${enable_fast_install+set}" = set; then : + enableval=$enable_fast_install; p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_fast_install=yes +fi + + + + + + + + + + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ltmain" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + + + + + + + + + + + + + + + + + + + + + + + + + +test -z "$LN_S" && LN_S="ln -s" + + + + + + + + + + + + + + +if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 +$as_echo_n "checking for objdir... " >&6; } +if test "${lt_cv_objdir+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 +$as_echo "$lt_cv_objdir" >&6; } +objdir=$lt_cv_objdir + + + + + +cat >>confdefs.h <<_ACEOF +#define LT_OBJDIR "$lt_cv_objdir/" +_ACEOF + + + + + + + + + + + + + + + + + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld="$lt_cv_prog_gnu_ld" + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 +$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } +if test "${lt_cv_path_MAGIC_CMD+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/${ac_tool_prefix}file; then + lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + + +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 +$as_echo_n "checking for file... " >&6; } +if test "${lt_cv_path_MAGIC_CMD+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/file; then + lt_cv_path_MAGIC_CMD="$ac_dir/file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + else + MAGIC_CMD=: + fi +fi + + fi + ;; +esac + +# Use C for the default configuration in the libtool script + +lt_save_CC="$CC" +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +objext=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* + +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* + + +if test -n "$compiler"; then + +lt_prog_compiler_no_builtin_flag= + +if test "$GCC" = yes; then + lt_prog_compiler_no_builtin_flag=' -fno-builtin' + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } +if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:7327: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:7331: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } + +if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then + lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" +else + : +fi + +fi + + + + + + + lt_prog_compiler_wl= +lt_prog_compiler_pic= +lt_prog_compiler_static= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } + + if test "$GCC" = yes; then + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_static='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + lt_prog_compiler_pic='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + ;; + + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic=-Kconform_pic + fi + ;; + + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + else + lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + # old Intel for x86_64 which still supported -KPIC. + ecc*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='--shared' + lt_prog_compiler_static='--static' + ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + xl*) + # IBM XL C 8.0/Fortran 10.1 on PPC + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-qpic' + lt_prog_compiler_static='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C 5.9 + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Wl,' + ;; + *Sun\ F*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='' + ;; + esac + ;; + esac + ;; + + newsos6) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + + rdos*) + lt_prog_compiler_static='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + lt_prog_compiler_wl='-Qoption ld ';; + *) + lt_prog_compiler_wl='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl='-Qoption ld ' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + lt_prog_compiler_pic='-Kconform_pic' + lt_prog_compiler_static='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_can_build_shared=no + ;; + + uts4*) + lt_prog_compiler_pic='-pic' + lt_prog_compiler_static='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared=no + ;; + esac + fi + +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic= + ;; + *) + lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic" >&5 +$as_echo "$lt_prog_compiler_pic" >&6; } + + + + + + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 +$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } +if test "${lt_cv_prog_compiler_pic_works+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_works=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:7666: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:7670: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_pic_works=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 +$as_echo "$lt_cv_prog_compiler_pic_works" >&6; } + +if test x"$lt_cv_prog_compiler_pic_works" = xyes; then + case $lt_prog_compiler_pic in + "" | " "*) ;; + *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; + esac +else + lt_prog_compiler_pic= + lt_prog_compiler_can_build_shared=no +fi + +fi + + + + + + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if test "${lt_cv_prog_compiler_static_works+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_static_works=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_static_works=yes + fi + else + lt_cv_prog_compiler_static_works=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 +$as_echo "$lt_cv_prog_compiler_static_works" >&6; } + +if test x"$lt_cv_prog_compiler_static_works" = xyes; then + : +else + lt_prog_compiler_static= +fi + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if test "${lt_cv_prog_compiler_c_o+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:7771: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:7775: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if test "${lt_cv_prog_compiler_c_o+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:7826: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:7830: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +$as_echo_n "checking if we can lock with hard links... " >&6; } + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +$as_echo "$hard_links" >&6; } + if test "$hard_links" = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + + runpath_var= + allow_undefined_flag= + always_export_symbols=no + archive_cmds= + archive_expsym_cmds= + compiler_needs_object=no + enable_shared_with_static_runtimes=no + export_dynamic_flag_spec= + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + hardcode_automatic=no + hardcode_direct=no + hardcode_direct_absolute=no + hardcode_libdir_flag_spec= + hardcode_libdir_flag_spec_ld= + hardcode_libdir_separator= + hardcode_minus_L=no + hardcode_shlibpath_var=unsupported + inherit_rpath=no + link_all_deplibs=unknown + module_cmds= + module_expsym_cmds= + old_archive_from_new_cmds= + old_archive_from_expsyms_cmds= + thread_safe_flag_spec= + whole_archive_flag_spec= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + linux* | k*bsd*-gnu) + link_all_deplibs=no + ;; + esac + + ld_shlibs=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + export_dynamic_flag_spec='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec= + fi + supports_anon_versioning=no + case `$LD -v 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[3-9]*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + allow_undefined_flag=unsupported + always_export_symbols=no + enable_shared_with_static_runtimes=yes + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs=no + fi + ;; + + interix[3-9]*) + hardcode_direct=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test "$host_os" = linux-dietlibc; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test "$tmp_diet" = no + then + tmp_addflag= + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + whole_archive_flag_spec= + tmp_sharedflag='--shared' ;; + xl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + compiler_needs_object=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test "x$supports_anon_versioning" = xyes; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + xlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' + hardcode_libdir_flag_spec= + hardcode_libdir_flag_spec_ld='-rpath $libdir' + archive_cmds='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + ld_shlibs=no + fi + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test "$ld_shlibs" = no; then + runpath_var= + hardcode_libdir_flag_spec= + export_dynamic_flag_spec= + whole_archive_flag_spec= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix[4-9]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds='' + hardcode_direct=yes + hardcode_direct_absolute=yes + hardcode_libdir_separator=':' + link_all_deplibs=yes + file_list_spec='${wl}-f,' + + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + link_all_deplibs=no + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + export_dynamic_flag_spec='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + +lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\(.*\)$/\1/ + p + } + }' +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag="-z nodefs" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + +lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\(.*\)$/\1/ + p + } + }' +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag=' ${wl}-bernotok' + allow_undefined_flag=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' + archive_cmds_need_lc=yes + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + bsdi[45]*) + export_dynamic_flag_spec=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_from_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' + fix_srcfile_path='`cygpath -w "$srcfile"`' + enable_shared_with_static_runtimes=yes + ;; + + darwin* | rhapsody*) + + + archive_cmds_need_lc=no + hardcode_direct=no + hardcode_automatic=yes + hardcode_shlibpath_var=unsupported + whole_archive_flag_spec='' + link_all_deplibs=yes + allow_undefined_flag="$_lt_dar_allow_undefined" + case $cc_basename in + ifort*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test "$_lt_dar_can_shared" = "yes"; then + output_verbose_link_cmd=echo + archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + + else + ld_shlibs=no + fi + + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + freebsd1*) + ld_shlibs=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + if test "$GCC" = yes; then + archive_cmds='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + export_dynamic_flag_spec='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_flag_spec_ld='+b $libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='${wl}-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct=no + hardcode_shlibpath_var=no + ;; + *) + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int foo(void) {} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + inherit_rpath=yes + link_all_deplibs=yes + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + newsos6) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_shlibpath_var=no + ;; + + *nto* | *qnx*) + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + hardcode_shlibpath_var=no + hardcode_direct_absolute=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + else + case $host_os in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-R$libdir' + ;; + *) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + esac + fi + else + ld_shlibs=no + fi + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + archive_cmds_need_lc='no' + hardcode_libdir_separator=: + ;; + + solaris*) + no_undefined_flag=' -z defs' + if test "$GCC" = yes; then + wlarc='${wl}' + archive_cmds='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='${wl}' + archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. GCC discards it without `$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test "$GCC" = yes; then + whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + else + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' + fi + ;; + esac + link_all_deplibs=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds='$CC -r -o $output$reload_objs' + hardcode_direct=no + ;; + motorola) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag='${wl}-z,text' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag='${wl}-z,text' + allow_undefined_flag='${wl}-z,nodefs' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='${wl}-R,$libdir' + hardcode_libdir_separator=':' + link_all_deplibs=yes + export_dynamic_flag_spec='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac + + if test x$host_vendor = xsni; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + export_dynamic_flag_spec='${wl}-Blargedynsym' + ;; + esac + fi + fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 +$as_echo "$ld_shlibs" >&6; } +test "$ld_shlibs" = no && can_build_shared=no + +with_gnu_ld=$with_gnu_ld + + + + + + + + + + + + + + + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl + pic_flag=$lt_prog_compiler_pic + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + then + archive_cmds_need_lc=no + else + archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $archive_cmds_need_lc" >&5 +$as_echo "$archive_cmds_need_lc" >&6; } + ;; + esac + fi + ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +$as_echo_n "checking dynamic linker characteristics... " >&6; } + +if test "$GCC" = yes; then + case $host_os in + darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; + *) lt_awk_arg="/^libraries:/" ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e 's/;/ /g'` + else + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary. + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path/$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" + else + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO $lt_tmp_lt_search_path_spec | awk ' +BEGIN {RS=" "; FS="/|\n";} { + lt_foo=""; + lt_count=0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo="/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[lt_foo]++; } + if (lt_freq[lt_foo] == 1) { print lt_foo; } +}'` + sys_lib_search_path_spec=`$ECHO $lt_search_path_spec` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix[4-9]*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix[3-9]*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # Some binutils ld are patched to set DT_RUNPATH + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : + shlibpath_overrides_runpath=yes +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +$as_echo "$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +fi +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +$as_echo_n "checking how to hardcode library paths into programs... " >&6; } +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || + test -n "$runpath_var" || + test "X$hardcode_automatic" = "Xyes" ; then + + # We can hardcode non-existent directories. + if test "$hardcode_direct" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && + test "$hardcode_minus_L" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 +$as_echo "$hardcode_action" >&6; } + +if test "$hardcode_action" = relink || + test "$inherit_rpath" = yes; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + + + + + + if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if test "${ac_cv_lib_dl_dlopen+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +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 dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = x""yes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + +fi + + ;; + + *) + ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" +if test "x$ac_cv_func_shl_load" = x""yes; then : + lt_cv_dlopen="shl_load" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 +$as_echo_n "checking for shl_load in -ldld... " >&6; } +if test "${ac_cv_lib_dld_shl_load+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +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 shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_shl_load=yes +else + ac_cv_lib_dld_shl_load=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 +$as_echo "$ac_cv_lib_dld_shl_load" >&6; } +if test "x$ac_cv_lib_dld_shl_load" = x""yes; then : + lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" +else + ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" +if test "x$ac_cv_func_dlopen" = x""yes; then : + lt_cv_dlopen="dlopen" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if test "${ac_cv_lib_dl_dlopen+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +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 dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = x""yes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 +$as_echo_n "checking for dlopen in -lsvld... " >&6; } +if test "${ac_cv_lib_svld_dlopen+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +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 dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_svld_dlopen=yes +else + ac_cv_lib_svld_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 +$as_echo "$ac_cv_lib_svld_dlopen" >&6; } +if test "x$ac_cv_lib_svld_dlopen" = x""yes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 +$as_echo_n "checking for dld_link in -ldld... " >&6; } +if test "${ac_cv_lib_dld_dld_link+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +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 dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_dld_link=yes +else + ac_cv_lib_dld_dld_link=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 +$as_echo "$ac_cv_lib_dld_dld_link" >&6; } +if test "x$ac_cv_lib_dld_dld_link" = x""yes; then : + lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" +fi + + +fi + + +fi + + +fi + + +fi + + +fi + + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 +$as_echo_n "checking whether a program can dlopen itself... " >&6; } +if test "${lt_cv_dlopen_self+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line 10210 "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 +$as_echo "$lt_cv_dlopen_self" >&6; } + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 +$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } +if test "${lt_cv_dlopen_self_static+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self_static=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line 10306 "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self_static=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 +$as_echo "$lt_cv_dlopen_self_static" >&6; } + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + + + + + + + + + + + + + + + + + +striplib= +old_striplib= +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 +$as_echo_n "checking whether stripping libraries is possible... " >&6; } +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + { $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; } + fi + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +fi + + + + + + + + + + + + + # Report which library types will actually be built + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 +$as_echo_n "checking if libtool supports shared libraries... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 +$as_echo "$can_build_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 +$as_echo_n "checking whether to build shared libraries... " >&6; } + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[4-9]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 +$as_echo "$enable_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 +$as_echo_n "checking whether to build static libraries... " >&6; } + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 +$as_echo "$enable_static" >&6; } + + + + +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC="$lt_save_CC" + + + + + + + + + + + + + + ac_config_commands="$ac_config_commands libtool" + + + + +# Only expand once: + + + +# Extract the first word of "doxygen", so it can be a program name with args. +set dummy doxygen; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_DOXYGEN+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DOXYGEN"; then + ac_cv_prog_DOXYGEN="$DOXYGEN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_DOXYGEN="true" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_DOXYGEN" && ac_cv_prog_DOXYGEN="false" +fi +fi +DOXYGEN=$ac_cv_prog_DOXYGEN +if test -n "$DOXYGEN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DOXYGEN" >&5 +$as_echo "$DOXYGEN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "$DOXYGEN" = true; then + DOXYGEN_TRUE= + DOXYGEN_FALSE='#' +else + DOXYGEN_TRUE='#' + DOXYGEN_FALSE= +fi + + +# Checks for header files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if test "${ac_cv_header_stdc+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +for ac_header in stdlib.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" +if test "x$ac_cv_header_stdlib_h" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STDLIB_H 1 +_ACEOF + +fi + +done + + +# Checks for typedefs, structures, and compiler characteristics. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 +$as_echo_n "checking for an ANSI C-conforming const... " >&6; } +if test "${ac_cv_c_const+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +/* FIXME: Include the comments suggested by Paul. */ +#ifndef __cplusplus + /* Ultrix mips cc rejects this. */ + typedef int charset[2]; + const charset cs; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *pcpcc; + char **ppc; + /* NEC SVR4.0.2 mips cc rejects this. */ + struct point {int x, y;}; + static struct point const zero = {0,0}; + /* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in + an arm of an if-expression whose if-part is not a constant + expression */ + const char *g = "string"; + pcpcc = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++pcpcc; + ppc = (char**) pcpcc; + pcpcc = (char const *const *) ppc; + { /* SCO 3.2v4 cc rejects this. */ + char *t; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; + if (s) return 0; + } + { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; + } + { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; + } + { /* AIX XL C 1.02.0.0 rejects this saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; }; + struct s *b; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + if (!foo) return 0; + } + return !cs[0] && !zero.x; +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_const=yes +else + ac_cv_c_const=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_const" >&5 +$as_echo "$ac_cv_c_const" >&6; } +if test $ac_cv_c_const = no; then + +$as_echo "#define const /**/" >>confdefs.h + +fi + +ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" +if test "x$ac_cv_type_size_t" = x""yes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned int +_ACEOF + +fi + + +# Define Makefiles. +ac_config_files="$ac_config_files yaml-0.1.pc include/Makefile src/Makefile Makefile tests/Makefile win32/Makefile" + + +# Generate the "configure" script. +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + test "x$cache_file" != "x/dev/null" && + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + cat confcache >$cache_file + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= +fi + +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + as_fn_error $? "conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${DOXYGEN_TRUE}" && test -z "${DOXYGEN_FALSE}"; then + as_fn_error $? "conditional \"DOXYGEN\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +: ${CONFIG_STATUS=./config.status} +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by yaml $as_me 0.1.4, which was +generated by GNU Autoconf 2.67. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +yaml config.status 0.1.4 +configured by $0, generated by GNU Autoconf 2.67, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2010 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" + + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +macro_version='`$ECHO "X$macro_version" | $Xsed -e "$delay_single_quote_subst"`' +macro_revision='`$ECHO "X$macro_revision" | $Xsed -e "$delay_single_quote_subst"`' +enable_shared='`$ECHO "X$enable_shared" | $Xsed -e "$delay_single_quote_subst"`' +enable_static='`$ECHO "X$enable_static" | $Xsed -e "$delay_single_quote_subst"`' +pic_mode='`$ECHO "X$pic_mode" | $Xsed -e "$delay_single_quote_subst"`' +enable_fast_install='`$ECHO "X$enable_fast_install" | $Xsed -e "$delay_single_quote_subst"`' +host_alias='`$ECHO "X$host_alias" | $Xsed -e "$delay_single_quote_subst"`' +host='`$ECHO "X$host" | $Xsed -e "$delay_single_quote_subst"`' +host_os='`$ECHO "X$host_os" | $Xsed -e "$delay_single_quote_subst"`' +build_alias='`$ECHO "X$build_alias" | $Xsed -e "$delay_single_quote_subst"`' +build='`$ECHO "X$build" | $Xsed -e "$delay_single_quote_subst"`' +build_os='`$ECHO "X$build_os" | $Xsed -e "$delay_single_quote_subst"`' +SED='`$ECHO "X$SED" | $Xsed -e "$delay_single_quote_subst"`' +Xsed='`$ECHO "X$Xsed" | $Xsed -e "$delay_single_quote_subst"`' +GREP='`$ECHO "X$GREP" | $Xsed -e "$delay_single_quote_subst"`' +EGREP='`$ECHO "X$EGREP" | $Xsed -e "$delay_single_quote_subst"`' +FGREP='`$ECHO "X$FGREP" | $Xsed -e "$delay_single_quote_subst"`' +LD='`$ECHO "X$LD" | $Xsed -e "$delay_single_quote_subst"`' +NM='`$ECHO "X$NM" | $Xsed -e "$delay_single_quote_subst"`' +LN_S='`$ECHO "X$LN_S" | $Xsed -e "$delay_single_quote_subst"`' +max_cmd_len='`$ECHO "X$max_cmd_len" | $Xsed -e "$delay_single_quote_subst"`' +ac_objext='`$ECHO "X$ac_objext" | $Xsed -e "$delay_single_quote_subst"`' +exeext='`$ECHO "X$exeext" | $Xsed -e "$delay_single_quote_subst"`' +lt_unset='`$ECHO "X$lt_unset" | $Xsed -e "$delay_single_quote_subst"`' +lt_SP2NL='`$ECHO "X$lt_SP2NL" | $Xsed -e "$delay_single_quote_subst"`' +lt_NL2SP='`$ECHO "X$lt_NL2SP" | $Xsed -e "$delay_single_quote_subst"`' +reload_flag='`$ECHO "X$reload_flag" | $Xsed -e "$delay_single_quote_subst"`' +reload_cmds='`$ECHO "X$reload_cmds" | $Xsed -e "$delay_single_quote_subst"`' +OBJDUMP='`$ECHO "X$OBJDUMP" | $Xsed -e "$delay_single_quote_subst"`' +deplibs_check_method='`$ECHO "X$deplibs_check_method" | $Xsed -e "$delay_single_quote_subst"`' +file_magic_cmd='`$ECHO "X$file_magic_cmd" | $Xsed -e "$delay_single_quote_subst"`' +AR='`$ECHO "X$AR" | $Xsed -e "$delay_single_quote_subst"`' +AR_FLAGS='`$ECHO "X$AR_FLAGS" | $Xsed -e "$delay_single_quote_subst"`' +STRIP='`$ECHO "X$STRIP" | $Xsed -e "$delay_single_quote_subst"`' +RANLIB='`$ECHO "X$RANLIB" | $Xsed -e "$delay_single_quote_subst"`' +old_postinstall_cmds='`$ECHO "X$old_postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' +old_postuninstall_cmds='`$ECHO "X$old_postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' +old_archive_cmds='`$ECHO "X$old_archive_cmds" | $Xsed -e "$delay_single_quote_subst"`' +CC='`$ECHO "X$CC" | $Xsed -e "$delay_single_quote_subst"`' +CFLAGS='`$ECHO "X$CFLAGS" | $Xsed -e "$delay_single_quote_subst"`' +compiler='`$ECHO "X$compiler" | $Xsed -e "$delay_single_quote_subst"`' +GCC='`$ECHO "X$GCC" | $Xsed -e "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_pipe='`$ECHO "X$lt_cv_sys_global_symbol_pipe" | $Xsed -e "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_cdecl='`$ECHO "X$lt_cv_sys_global_symbol_to_cdecl" | $Xsed -e "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address" | $Xsed -e "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`' +objdir='`$ECHO "X$objdir" | $Xsed -e "$delay_single_quote_subst"`' +SHELL='`$ECHO "X$SHELL" | $Xsed -e "$delay_single_quote_subst"`' +ECHO='`$ECHO "X$ECHO" | $Xsed -e "$delay_single_quote_subst"`' +MAGIC_CMD='`$ECHO "X$MAGIC_CMD" | $Xsed -e "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag='`$ECHO "X$lt_prog_compiler_no_builtin_flag" | $Xsed -e "$delay_single_quote_subst"`' +lt_prog_compiler_wl='`$ECHO "X$lt_prog_compiler_wl" | $Xsed -e "$delay_single_quote_subst"`' +lt_prog_compiler_pic='`$ECHO "X$lt_prog_compiler_pic" | $Xsed -e "$delay_single_quote_subst"`' +lt_prog_compiler_static='`$ECHO "X$lt_prog_compiler_static" | $Xsed -e "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o='`$ECHO "X$lt_cv_prog_compiler_c_o" | $Xsed -e "$delay_single_quote_subst"`' +need_locks='`$ECHO "X$need_locks" | $Xsed -e "$delay_single_quote_subst"`' +DSYMUTIL='`$ECHO "X$DSYMUTIL" | $Xsed -e "$delay_single_quote_subst"`' +NMEDIT='`$ECHO "X$NMEDIT" | $Xsed -e "$delay_single_quote_subst"`' +LIPO='`$ECHO "X$LIPO" | $Xsed -e "$delay_single_quote_subst"`' +OTOOL='`$ECHO "X$OTOOL" | $Xsed -e "$delay_single_quote_subst"`' +OTOOL64='`$ECHO "X$OTOOL64" | $Xsed -e "$delay_single_quote_subst"`' +libext='`$ECHO "X$libext" | $Xsed -e "$delay_single_quote_subst"`' +shrext_cmds='`$ECHO "X$shrext_cmds" | $Xsed -e "$delay_single_quote_subst"`' +extract_expsyms_cmds='`$ECHO "X$extract_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`' +archive_cmds_need_lc='`$ECHO "X$archive_cmds_need_lc" | $Xsed -e "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes='`$ECHO "X$enable_shared_with_static_runtimes" | $Xsed -e "$delay_single_quote_subst"`' +export_dynamic_flag_spec='`$ECHO "X$export_dynamic_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' +whole_archive_flag_spec='`$ECHO "X$whole_archive_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' +compiler_needs_object='`$ECHO "X$compiler_needs_object" | $Xsed -e "$delay_single_quote_subst"`' +old_archive_from_new_cmds='`$ECHO "X$old_archive_from_new_cmds" | $Xsed -e "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds='`$ECHO "X$old_archive_from_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`' +archive_cmds='`$ECHO "X$archive_cmds" | $Xsed -e "$delay_single_quote_subst"`' +archive_expsym_cmds='`$ECHO "X$archive_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`' +module_cmds='`$ECHO "X$module_cmds" | $Xsed -e "$delay_single_quote_subst"`' +module_expsym_cmds='`$ECHO "X$module_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`' +with_gnu_ld='`$ECHO "X$with_gnu_ld" | $Xsed -e "$delay_single_quote_subst"`' +allow_undefined_flag='`$ECHO "X$allow_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`' +no_undefined_flag='`$ECHO "X$no_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec='`$ECHO "X$hardcode_libdir_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec_ld='`$ECHO "X$hardcode_libdir_flag_spec_ld" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_libdir_separator='`$ECHO "X$hardcode_libdir_separator" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_direct='`$ECHO "X$hardcode_direct" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_direct_absolute='`$ECHO "X$hardcode_direct_absolute" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_minus_L='`$ECHO "X$hardcode_minus_L" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_shlibpath_var='`$ECHO "X$hardcode_shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_automatic='`$ECHO "X$hardcode_automatic" | $Xsed -e "$delay_single_quote_subst"`' +inherit_rpath='`$ECHO "X$inherit_rpath" | $Xsed -e "$delay_single_quote_subst"`' +link_all_deplibs='`$ECHO "X$link_all_deplibs" | $Xsed -e "$delay_single_quote_subst"`' +fix_srcfile_path='`$ECHO "X$fix_srcfile_path" | $Xsed -e "$delay_single_quote_subst"`' +always_export_symbols='`$ECHO "X$always_export_symbols" | $Xsed -e "$delay_single_quote_subst"`' +export_symbols_cmds='`$ECHO "X$export_symbols_cmds" | $Xsed -e "$delay_single_quote_subst"`' +exclude_expsyms='`$ECHO "X$exclude_expsyms" | $Xsed -e "$delay_single_quote_subst"`' +include_expsyms='`$ECHO "X$include_expsyms" | $Xsed -e "$delay_single_quote_subst"`' +prelink_cmds='`$ECHO "X$prelink_cmds" | $Xsed -e "$delay_single_quote_subst"`' +file_list_spec='`$ECHO "X$file_list_spec" | $Xsed -e "$delay_single_quote_subst"`' +variables_saved_for_relink='`$ECHO "X$variables_saved_for_relink" | $Xsed -e "$delay_single_quote_subst"`' +need_lib_prefix='`$ECHO "X$need_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`' +need_version='`$ECHO "X$need_version" | $Xsed -e "$delay_single_quote_subst"`' +version_type='`$ECHO "X$version_type" | $Xsed -e "$delay_single_quote_subst"`' +runpath_var='`$ECHO "X$runpath_var" | $Xsed -e "$delay_single_quote_subst"`' +shlibpath_var='`$ECHO "X$shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`' +shlibpath_overrides_runpath='`$ECHO "X$shlibpath_overrides_runpath" | $Xsed -e "$delay_single_quote_subst"`' +libname_spec='`$ECHO "X$libname_spec" | $Xsed -e "$delay_single_quote_subst"`' +library_names_spec='`$ECHO "X$library_names_spec" | $Xsed -e "$delay_single_quote_subst"`' +soname_spec='`$ECHO "X$soname_spec" | $Xsed -e "$delay_single_quote_subst"`' +postinstall_cmds='`$ECHO "X$postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' +postuninstall_cmds='`$ECHO "X$postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' +finish_cmds='`$ECHO "X$finish_cmds" | $Xsed -e "$delay_single_quote_subst"`' +finish_eval='`$ECHO "X$finish_eval" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_into_libs='`$ECHO "X$hardcode_into_libs" | $Xsed -e "$delay_single_quote_subst"`' +sys_lib_search_path_spec='`$ECHO "X$sys_lib_search_path_spec" | $Xsed -e "$delay_single_quote_subst"`' +sys_lib_dlsearch_path_spec='`$ECHO "X$sys_lib_dlsearch_path_spec" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_action='`$ECHO "X$hardcode_action" | $Xsed -e "$delay_single_quote_subst"`' +enable_dlopen='`$ECHO "X$enable_dlopen" | $Xsed -e "$delay_single_quote_subst"`' +enable_dlopen_self='`$ECHO "X$enable_dlopen_self" | $Xsed -e "$delay_single_quote_subst"`' +enable_dlopen_self_static='`$ECHO "X$enable_dlopen_self_static" | $Xsed -e "$delay_single_quote_subst"`' +old_striplib='`$ECHO "X$old_striplib" | $Xsed -e "$delay_single_quote_subst"`' +striplib='`$ECHO "X$striplib" | $Xsed -e "$delay_single_quote_subst"`' + +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# Quote evaled strings. +for var in SED \ +GREP \ +EGREP \ +FGREP \ +LD \ +NM \ +LN_S \ +lt_SP2NL \ +lt_NL2SP \ +reload_flag \ +OBJDUMP \ +deplibs_check_method \ +file_magic_cmd \ +AR \ +AR_FLAGS \ +STRIP \ +RANLIB \ +CC \ +CFLAGS \ +compiler \ +lt_cv_sys_global_symbol_pipe \ +lt_cv_sys_global_symbol_to_cdecl \ +lt_cv_sys_global_symbol_to_c_name_address \ +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ +SHELL \ +ECHO \ +lt_prog_compiler_no_builtin_flag \ +lt_prog_compiler_wl \ +lt_prog_compiler_pic \ +lt_prog_compiler_static \ +lt_cv_prog_compiler_c_o \ +need_locks \ +DSYMUTIL \ +NMEDIT \ +LIPO \ +OTOOL \ +OTOOL64 \ +shrext_cmds \ +export_dynamic_flag_spec \ +whole_archive_flag_spec \ +compiler_needs_object \ +with_gnu_ld \ +allow_undefined_flag \ +no_undefined_flag \ +hardcode_libdir_flag_spec \ +hardcode_libdir_flag_spec_ld \ +hardcode_libdir_separator \ +fix_srcfile_path \ +exclude_expsyms \ +include_expsyms \ +file_list_spec \ +variables_saved_for_relink \ +libname_spec \ +library_names_spec \ +soname_spec \ +finish_eval \ +old_striplib \ +striplib; do + case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in reload_cmds \ +old_postinstall_cmds \ +old_postuninstall_cmds \ +old_archive_cmds \ +extract_expsyms_cmds \ +old_archive_from_new_cmds \ +old_archive_from_expsyms_cmds \ +archive_cmds \ +archive_expsym_cmds \ +module_cmds \ +module_expsym_cmds \ +export_symbols_cmds \ +prelink_cmds \ +postinstall_cmds \ +postuninstall_cmds \ +finish_cmds \ +sys_lib_search_path_spec \ +sys_lib_dlsearch_path_spec; do + case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Fix-up fallback echo if it was mangled by the above quoting rules. +case \$lt_ECHO in +*'\\\$0 --fallback-echo"') lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\$0 --fallback-echo"\$/\$0 --fallback-echo"/'\` + ;; +esac + +ac_aux_dir='$ac_aux_dir' +xsi_shell='$xsi_shell' +lt_shell_append='$lt_shell_append' + +# See if we are running on zsh, and set the options which allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + + + PACKAGE='$PACKAGE' + VERSION='$VERSION' + TIMESTAMP='$TIMESTAMP' + RM='$RM' + ofile='$ofile' + + + + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; + "yaml-0.1.pc") CONFIG_FILES="$CONFIG_FILES yaml-0.1.pc" ;; + "include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;; + "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;; + "win32/Makefile") CONFIG_FILES="$CONFIG_FILES win32/Makefile" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5 ;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= + trap 'exit_status=$? + { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_t=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_t"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5 ;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5 ;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$tmp/stdin" + case $ac_file in + -) cat "$tmp/out" && rm -f "$tmp/out";; + *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" + } >"$tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi +# Compute "$ac_file"'s index in $config_headers. +_am_arg="$ac_file" +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || +$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$_am_arg" : 'X\(//\)[^/]' \| \ + X"$_am_arg" : 'X\(//\)$' \| \ + X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$_am_arg" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'`/stamp-h$_am_stamp_count + ;; + + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "depfiles":C) test x"$AMDEP_TRUE" != x"" || { + # Autoconf 2.62 quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`$as_dirname -- "$mf" || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`$as_dirname -- "$file" || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir=$dirpart/$fdir; as_fn_mkdir_p + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} + ;; + "libtool":C) + + # See if we are running on zsh, and set the options which allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + + cfgfile="${ofile}T" + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL + +# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008 Free Software Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is part of GNU Libtool. +# +# GNU Libtool is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, or +# obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +# The names of the tagged configurations supported by this script. +available_tags="" + +# ### BEGIN LIBTOOL CONFIG + +# Which release of libtool.m4 was used? +macro_version=$macro_version +macro_revision=$macro_revision + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# What type of objects to build. +pic_mode=$pic_mode + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="\$SED -e 1s/^X//" + +# A grep program that handles long lines. +GREP=$lt_GREP + +# An ERE matcher. +EGREP=$lt_EGREP + +# A literal string matcher. +FGREP=$lt_FGREP + +# A BSD- or MS-compatible name lister. +NM=$lt_NM + +# Whether we need soft or hard links. +LN_S=$lt_LN_S + +# What is the maximum length of a command? +max_cmd_len=$max_cmd_len + +# Object file suffix (normally "o"). +objext=$ac_objext + +# Executable file suffix (normally ""). +exeext=$exeext + +# whether the shell understands "unset". +lt_unset=$lt_unset + +# turn spaces into newlines. +SP2NL=$lt_lt_SP2NL + +# turn newlines into spaces. +NL2SP=$lt_lt_NL2SP + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# An object symbol dumper. +OBJDUMP=$lt_OBJDUMP + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == "file_magic". +file_magic_cmd=$lt_file_magic_cmd + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A symbol stripping program. +STRIP=$lt_STRIP + +# Commands used to install an old-style archive. +RANLIB=$lt_RANLIB +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# A C compiler. +LTCC=$lt_CC + +# LTCC compiler flags. +LTCFLAGS=$lt_CFLAGS + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration. +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair. +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# Transform the output of nm in a C name address pair when lib prefix is needed. +global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# An echo program that does not interpret backslashes. +ECHO=$lt_ECHO + +# Used to examine libraries when file_magic_cmd begins with "file". +MAGIC_CMD=$MAGIC_CMD + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Tool to manipulate archived DWARF debug symbol files on Mac OS X. +DSYMUTIL=$lt_DSYMUTIL + +# Tool to change global to local symbols on Mac OS X. +NMEDIT=$lt_NMEDIT + +# Tool to manipulate fat objects and archives on Mac OS X. +LIPO=$lt_LIPO + +# ldd/readelf like tool for Mach-O binaries on Mac OS X. +OTOOL=$lt_OTOOL + +# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. +OTOOL64=$lt_OTOOL64 + +# Old archive suffix (normally "a"). +libext=$libext + +# Shared library suffix (normally ".so"). +shrext_cmds=$lt_shrext_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at link time. +variables_saved_for_relink=$lt_variables_saved_for_relink + +# Do we need the "lib" prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Library versioning type. +version_type=$version_type + +# Shared library runtime path variable. +runpath_var=$runpath_var + +# Shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Command to use after installation of a shared archive. +postinstall_cmds=$lt_postinstall_cmds + +# Command to use after uninstallation of a shared archive. +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# As "finish_cmds", except a single script fragment to be evaled but +# not shown. +finish_eval=$lt_finish_eval + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Compile-time system search path for libraries. +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries. +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + + +# The linker used to build libraries. +LD=$lt_LD + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds + +# A language specific compiler. +CC=$lt_compiler + +# Is the compiler the GNU compiler? +with_gcc=$GCC + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds +module_expsym_cmds=$lt_module_expsym_cmds + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec + +# If ld is used when linking, flag to hardcode \$libdir into a binary +# during linking. This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \${shlibpath_var} if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path=$lt_fix_srcfile_path + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# ### END LIBTOOL CONFIG + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + +ltmain="$ac_aux_dir/ltmain.sh" + + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + case $xsi_shell in + yes) + cat << \_LT_EOF >> "$cfgfile" + +# func_dirname file append nondir_replacement +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +func_dirname () +{ + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac +} + +# func_basename file +func_basename () +{ + func_basename_result="${1##*/}" +} + +# func_dirname_and_basename file append nondir_replacement +# perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# Implementation must be kept synchronized with func_dirname +# and func_basename. For efficiency, we do not delegate to +# those functions but instead duplicate the functionality here. +func_dirname_and_basename () +{ + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac + func_basename_result="${1##*/}" +} + +# func_stripname prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +func_stripname () +{ + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary parameter first. + func_stripname_result=${3} + func_stripname_result=${func_stripname_result#"${1}"} + func_stripname_result=${func_stripname_result%"${2}"} +} + +# func_opt_split +func_opt_split () +{ + func_opt_split_opt=${1%%=*} + func_opt_split_arg=${1#*=} +} + +# func_lo2o object +func_lo2o () +{ + case ${1} in + *.lo) func_lo2o_result=${1%.lo}.${objext} ;; + *) func_lo2o_result=${1} ;; + esac +} + +# func_xform libobj-or-source +func_xform () +{ + func_xform_result=${1%.*}.lo +} + +# func_arith arithmetic-term... +func_arith () +{ + func_arith_result=$(( $* )) +} + +# func_len string +# STRING may not start with a hyphen. +func_len () +{ + func_len_result=${#1} +} + +_LT_EOF + ;; + *) # Bourne compatible functions. + cat << \_LT_EOF >> "$cfgfile" + +# func_dirname file append nondir_replacement +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +func_dirname () +{ + # Extract subdirectory from the argument. + func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi +} + +# func_basename file +func_basename () +{ + func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` +} + + +# func_stripname prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# func_strip_suffix prefix name +func_stripname () +{ + case ${2} in + .*) func_stripname_result=`$ECHO "X${3}" \ + | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "X${3}" \ + | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;; + esac +} + +# sed scripts: +my_sed_long_opt='1s/^\(-[^=]*\)=.*/\1/;q' +my_sed_long_arg='1s/^-[^=]*=//' + +# func_opt_split +func_opt_split () +{ + func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"` + func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"` +} + +# func_lo2o object +func_lo2o () +{ + func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"` +} + +# func_xform libobj-or-source +func_xform () +{ + func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[^.]*$/.lo/'` +} + +# func_arith arithmetic-term... +func_arith () +{ + func_arith_result=`expr "$@"` +} + +# func_len string +# STRING may not start with a hyphen. +func_len () +{ + func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` +} + +_LT_EOF +esac + +case $lt_shell_append in + yes) + cat << \_LT_EOF >> "$cfgfile" + +# func_append var value +# Append VALUE to the end of shell variable VAR. +func_append () +{ + eval "$1+=\$2" +} +_LT_EOF + ;; + *) + cat << \_LT_EOF >> "$cfgfile" + +# func_append var value +# Append VALUE to the end of shell variable VAR. +func_append () +{ + eval "$1=\$$1\$2" +} + +_LT_EOF + ;; + esac + + + sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" + + ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + diff --git a/configure.ac b/configure.ac new file mode 100644 index 00000000000..f0fa397e0d9 --- /dev/null +++ b/configure.ac @@ -0,0 +1,73 @@ +# Run `./bootstrap` to generate the "configure" script. + +# Define the package version numbers and the bug reporting link. +m4_define([YAML_MAJOR], 0) +m4_define([YAML_MINOR], 1) +m4_define([YAML_PATCH], 4) +m4_define([YAML_BUGS], [http://pyyaml.org/newticket?component=libyaml]) + +# Define the libtool version numbers; check the Autobook, Section 11.4. +# Bump the libtool version numbers using the following algorithm: +# if (the current interface has not been changed): +# YAML_REVISION += 1 +# else: +# YAML_REVISION = 0 +# YAML_CURRENT += 1 +# if (this release is backward compatible with the previous release): +# YAML_AGE += 1 +# else: +# YAML_AGE = 0 +m4_define([YAML_RELEASE], 0) +m4_define([YAML_CURRENT], 2) +m4_define([YAML_REVISION], 2) +m4_define([YAML_AGE], 0) + +# Initialize autoconf & automake. +AC_PREREQ(2.59) +AC_INIT([yaml], [YAML_MAJOR.YAML_MINOR.YAML_PATCH], [YAML_BUGS]) +AC_CONFIG_AUX_DIR([config]) +AC_CONFIG_HEADERS([config.h]) +AM_INIT_AUTOMAKE([1.9 foreign]) + +# Define macro variables for the package version numbers. +AC_DEFINE(YAML_VERSION_MAJOR, YAML_MAJOR, [Define the major version number.]) +AC_DEFINE(YAML_VERSION_MINOR, YAML_MINOR, [Define the minor version number.]) +AC_DEFINE(YAML_VERSION_PATCH, YAML_PATCH, [Define the patch version number.]) +AC_DEFINE(YAML_VERSION_STRING, "YAML_MAJOR.YAML_MINOR.YAML_PATCH", [Define the version string.]) + +# Define substitutions for the libtool version numbers. +YAML_LT_RELEASE=YAML_RELEASE +YAML_LT_CURRENT=YAML_CURRENT +YAML_LT_REVISION=YAML_REVISION +YAML_LT_AGE=YAML_AGE +AC_SUBST(YAML_LT_RELEASE) +AC_SUBST(YAML_LT_CURRENT) +AC_SUBST(YAML_LT_REVISION) +AC_SUBST(YAML_LT_AGE) + +# Note: in order to update checks, run `autoscan` and look through "configure.scan". + +# Checks for programs. +AC_PROG_CC +AC_PROG_CPP +AC_PROG_INSTALL +AC_PROG_LN_S +AC_PROG_MAKE_SET +AC_PROG_LIBTOOL + +AC_CHECK_PROG(DOXYGEN, [doxygen], [true], [false]) +AM_CONDITIONAL(DOXYGEN, [test "$DOXYGEN" = true]) + +# Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS([stdlib.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_TYPE_SIZE_T + +# Define Makefiles. +AC_CONFIG_FILES([yaml-0.1.pc include/Makefile src/Makefile Makefile tests/Makefile win32/Makefile]) + +# Generate the "configure" script. +AC_OUTPUT diff --git a/doc/doxygen.cfg b/doc/doxygen.cfg new file mode 100644 index 00000000000..a58bb177a4d --- /dev/null +++ b/doc/doxygen.cfg @@ -0,0 +1,222 @@ +# Doxyfile 1.4.4 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +PROJECT_NAME = $(PACKAGE) +PROJECT_NUMBER = $(VERSION) +OUTPUT_DIRECTORY = $(top_builddir)/doc/ +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +USE_WINDOWS_ENCODING = NO +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = YES +MULTILINE_CPP_IS_BRIEF = NO +DETAILS_AT_TOP = NO +INHERIT_DOCS = YES +DISTRIBUTE_GROUP_DOC = NO +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 8 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = YES +OPTIMIZE_OUTPUT_JAVA = NO +SUBGROUPING = YES +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = NO +EXTRACT_LOCAL_METHODS = NO +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = NO +SORT_BRIEF_DOCS = NO +SORT_BY_SCOPE_NAME = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_DIRECTORIES = YES +FILE_VERSION_FILTER = +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = $(top_srcdir)/include/ +FILE_PATTERNS = *.h +RECURSIVE = YES +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = NO +REFERENCES_RELATION = NO +USE_HTAGS = NO +VERBATIM_HEADERS = NO +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = NO +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = NO +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 1 +GENERATE_TREEVIEW = NO +TREEVIEW_WIDTH = 250 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = NO +USE_PDFLATEX = NO +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = YES +EXPAND_ONLY_PREDEF = YES +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = "YAML_DECLARE(type)=type" +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = NO +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = NO +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +MAX_DOT_GRAPH_WIDTH = 1024 +MAX_DOT_GRAPH_HEIGHT = 1024 +MAX_DOT_GRAPH_DEPTH = 0 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO diff --git a/doc/html/annotated.html b/doc/html/annotated.html new file mode 100644 index 00000000000..7cce097ef49 --- /dev/null +++ b/doc/html/annotated.html @@ -0,0 +1,51 @@ + + + + +yaml: Data Structures + + + + + + +
    +
    +

    Data Structures

    +
    +
    +Here are the data structures with brief descriptions: + + + + + + + + + + + + +
    yaml_alias_data_sThis structure holds aliases data
    yaml_document_sThe document structure
    yaml_emitter_sThe emitter structure
    yaml_event_sThe event structure
    yaml_mark_sThe pointer position
    yaml_node_pair_sAn element of a mapping node
    yaml_node_sThe node structure
    yaml_parser_sThe parser structure
    yaml_simple_key_sThis structure holds information about a potential simple key
    yaml_tag_directive_sThe tag directive data
    yaml_token_sThe token structure
    yaml_version_directive_sThe version directive data
    +
    + + + diff --git a/doc/html/bc_s.png b/doc/html/bc_s.png new file mode 100644 index 0000000000000000000000000000000000000000..e4018628b5b45cb4301037485a29d7d74ac22138 GIT binary patch literal 677 zcmV;W0$TlvP)X?0Pv5h+5!wElpi=&YL!gfY!djl#UDdPKy97F|A-deTa@qo3BWh1YQIvzmHR^g zFjV4I6pLB7_*vEZk^%p7c7Bh>0`4r^X#gpJE_Vz9fSHKqclcZaV^k3gX%h+1`u||O zZ+BY?7(R=ayr^kXE=E0Dw=$Ud3VJ?9^Cz@hP?388Cw5>9TloOJ>^KczCgj zns2=|0!a|)Yq3{hjL{xyy7|Tk0N}Pe+g9PUTL!4{#;eUhrNd@!_T<>Vu+35c)h>sq ztgb?(6W3oFLz#%?OMEV@{j#4LuDvjVGZ~6hpQT8li5b0yjvK8c4efl+vSz5)P6 zle78)00_Iv5)&E~hnOdcd}L}i+MU>k+Q8#@KjqJJN`gRj(~)RmNrck9ht@LelPtVO zwp(J;k!T=gC#%o(13-^E+g@aqc()pf{+j|0w)AH*Mq$54UjLv#jV$RYpz3Vjg$$=u z>yjfBQOhL=^@+#4#$l|{~}HZ-?1Yy{lI*$N}*YDC`<{+;>_#gMXZdz4NI00000 LNkvXXu0mjfx86dR literal 0 HcmV?d00001 diff --git a/doc/html/classes.html b/doc/html/classes.html new file mode 100644 index 00000000000..8bcca58c038 --- /dev/null +++ b/doc/html/classes.html @@ -0,0 +1,41 @@ + + + + +yaml: Alphabetical List + + + + + + +
    +
    +

    Data Structure Index

    +
    + + + + diff --git a/doc/html/closed.png b/doc/html/closed.png new file mode 100644 index 0000000000000000000000000000000000000000..b7d4bd9fef2272c74b94762c9e2496177017775e GIT binary patch literal 126 zcmeAS@N?(olHy`uVBq!ia0vp^oFL4>1|%O$WD@{VuAVNAAr*{o?>h22DDp4|bgj*t z)u^AqcA-V@guRYpb17F<&b?_~8HV>~XqWvB;^$!VVSTy0!eQcJp_yD7TIQA>7dijs YXf6~H5cs^Q6KEiVr>mdKI;Vst0NsWqGynhq literal 0 HcmV?d00001 diff --git a/doc/html/doxygen.css b/doc/html/doxygen.css new file mode 100644 index 00000000000..658686fe4e6 --- /dev/null +++ b/doc/html/doxygen.css @@ -0,0 +1,656 @@ +/* The standard CSS for doxygen */ + +body, table, div, p, dl { + font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif; + font-size: 12px; +} + +/* @group Heading Levels */ + +h1 { + font-size: 150%; +} + +h2 { + font-size: 120%; +} + +h3 { + font-size: 100%; +} + +dt { + font-weight: bold; +} + +div.multicol { + -moz-column-gap: 1em; + -webkit-column-gap: 1em; + -moz-column-count: 3; + -webkit-column-count: 3; +} + +p.startli, p.startdd, p.starttd { + margin-top: 2px; +} + +p.endli { + margin-bottom: 0px; +} + +p.enddd { + margin-bottom: 4px; +} + +p.endtd { + margin-bottom: 2px; +} + +/* @end */ + +caption { + font-weight: bold; +} + +span.legend { + font-size: 70%; + text-align: center; +} + +h3.version { + font-size: 90%; + text-align: center; +} + +div.qindex, div.navtab{ + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; + margin: 2px; + padding: 2px; +} + +div.qindex, div.navpath { + width: 100%; + line-height: 140%; +} + +div.navtab { + margin-right: 15px; +} + +/* @group Link Styling */ + +a { + color: #3D578C; + font-weight: normal; + text-decoration: none; +} + +.contents a:visited { + color: #4665A2; +} + +a:hover { + text-decoration: underline; +} + +a.qindex { + font-weight: bold; +} + +a.qindexHL { + font-weight: bold; + background-color: #9CAFD4; + color: #ffffff; + border: 1px double #869DCA; +} + +.contents a.qindexHL:visited { + color: #ffffff; +} + +a.el { + font-weight: bold; +} + +a.elRef { +} + +a.code { + color: #4665A2; +} + +a.codeRef { + color: #4665A2; +} + +/* @end */ + +dl.el { + margin-left: -1cm; +} + +.fragment { + font-family: monospace, fixed; + font-size: 105%; +} + +pre.fragment { + border: 1px solid #C4CFE5; + background-color: #FBFCFD; + padding: 4px 6px; + margin: 4px 8px 4px 2px; + overflow: auto; + word-wrap: break-word; + font-size: 9pt; + line-height: 125%; +} + +div.ah { + background-color: black; + font-weight: bold; + color: #ffffff; + margin-bottom: 3px; + margin-top: 3px; + padding: 0.2em; + border: solid thin #333; + border-radius: 0.5em; + -webkit-border-radius: .5em; + -moz-border-radius: .5em; + -webkit-box-shadow: 2px 2px 3px #999; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444)); + background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000); +} + +div.groupHeader { + margin-left: 16px; + margin-top: 12px; + margin-bottom: 6px; + font-weight: bold; +} + +div.groupText { + margin-left: 16px; + font-style: italic; +} + +body { + background: white; + color: black; + margin: 0; +} + +div.contents { + margin-top: 10px; + margin-left: 10px; + margin-right: 10px; +} + +td.indexkey { + background-color: #EBEFF6; + font-weight: bold; + border: 1px solid #C4CFE5; + margin: 2px 0px 2px 0; + padding: 2px 10px; +} + +td.indexvalue { + background-color: #EBEFF6; + border: 1px solid #C4CFE5; + padding: 2px 10px; + margin: 2px 0px; +} + +tr.memlist { + background-color: #EEF1F7; +} + +p.formulaDsp { + text-align: center; +} + +img.formulaDsp { + +} + +img.formulaInl { + vertical-align: middle; +} + +div.center { + text-align: center; + margin-top: 0px; + margin-bottom: 0px; + padding: 0px; +} + +div.center img { + border: 0px; +} + +address.footer { + text-align: right; + padding-right: 12px; +} + +img.footer { + border: 0px; + vertical-align: middle; +} + +/* @group Code Colorization */ + +span.keyword { + color: #008000 +} + +span.keywordtype { + color: #604020 +} + +span.keywordflow { + color: #e08000 +} + +span.comment { + color: #800000 +} + +span.preprocessor { + color: #806020 +} + +span.stringliteral { + color: #002080 +} + +span.charliteral { + color: #008080 +} + +span.vhdldigit { + color: #ff00ff +} + +span.vhdlchar { + color: #000000 +} + +span.vhdlkeyword { + color: #700070 +} + +span.vhdllogic { + color: #ff0000 +} + +/* @end */ + +/* +.search { + color: #003399; + font-weight: bold; +} + +form.search { + margin-bottom: 0px; + margin-top: 0px; +} + +input.search { + font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #e8eef2; +} +*/ + +td.tiny { + font-size: 75%; +} + +.dirtab { + padding: 4px; + border-collapse: collapse; + border: 1px solid #A3B4D7; +} + +th.dirtab { + background: #EBEFF6; + font-weight: bold; +} + +hr { + height: 0px; + border: none; + border-top: 1px solid #4A6AAA; +} + +hr.footer { + height: 1px; +} + +/* @group Member Descriptions */ + +table.memberdecls { + border-spacing: 0px; + padding: 0px; +} + +.mdescLeft, .mdescRight, +.memItemLeft, .memItemRight, +.memTemplItemLeft, .memTemplItemRight, .memTemplParams { + background-color: #F9FAFC; + border: none; + margin: 4px; + padding: 1px 0 0 8px; +} + +.mdescLeft, .mdescRight { + padding: 0px 8px 4px 8px; + color: #555; +} + +.memItemLeft, .memItemRight, .memTemplParams { + border-top: 1px solid #C4CFE5; +} + +.memItemLeft, .memTemplItemLeft { + white-space: nowrap; +} + +.memTemplParams { + color: #4665A2; + white-space: nowrap; +} + +/* @end */ + +/* @group Member Details */ + +/* Styles for detailed member documentation */ + +.memtemplate { + font-size: 80%; + color: #4665A2; + font-weight: normal; + margin-left: 3px; +} + +.memnav { + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} + +.memitem { + padding: 0; + margin-bottom: 10px; +} + +.memname { + white-space: nowrap; + font-weight: bold; + margin-left: 6px; +} + +.memproto { + border-top: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 0px 6px 0px; + color: #253555; + font-weight: bold; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + /* firefox specific markup */ + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + -moz-border-radius-topright: 8px; + -moz-border-radius-topleft: 8px; + /* webkit specific markup */ + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + -webkit-border-top-right-radius: 8px; + -webkit-border-top-left-radius: 8px; + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + +} + +.memdoc { + border-bottom: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 2px 5px; + background-color: #FBFCFD; + border-top-width: 0; + /* firefox specific markup */ + -moz-border-radius-bottomleft: 8px; + -moz-border-radius-bottomright: 8px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + background-image: -moz-linear-gradient(center top, #FFFFFF 0%, #FFFFFF 60%, #F7F8FB 95%, #EEF1F7); + /* webkit specific markup */ + -webkit-border-bottom-left-radius: 8px; + -webkit-border-bottom-right-radius: 8px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + background-image: -webkit-gradient(linear,center top,center bottom,from(#FFFFFF), color-stop(0.6,#FFFFFF), color-stop(0.60,#FFFFFF), color-stop(0.95,#F7F8FB), to(#EEF1F7)); +} + +.paramkey { + text-align: right; +} + +.paramtype { + white-space: nowrap; +} + +.paramname { + color: #602020; + white-space: nowrap; +} +.paramname em { + font-style: normal; +} + +/* @end */ + +/* @group Directory (tree) */ + +/* for the tree view */ + +.ftvtree { + font-family: sans-serif; + margin: 0px; +} + +/* these are for tree view when used as main index */ + +.directory { + font-size: 9pt; + font-weight: bold; + margin: 5px; +} + +.directory h3 { + margin: 0px; + margin-top: 1em; + font-size: 11pt; +} + +/* +The following two styles can be used to replace the root node title +with an image of your choice. Simply uncomment the next two styles, +specify the name of your image and be sure to set 'height' to the +proper pixel height of your image. +*/ + +/* +.directory h3.swap { + height: 61px; + background-repeat: no-repeat; + background-image: url("yourimage.gif"); +} +.directory h3.swap span { + display: none; +} +*/ + +.directory > h3 { + margin-top: 0; +} + +.directory p { + margin: 0px; + white-space: nowrap; +} + +.directory div { + display: none; + margin: 0px; +} + +.directory img { + vertical-align: -30%; +} + +/* these are for tree view when not used as main index */ + +.directory-alt { + font-size: 100%; + font-weight: bold; +} + +.directory-alt h3 { + margin: 0px; + margin-top: 1em; + font-size: 11pt; +} + +.directory-alt > h3 { + margin-top: 0; +} + +.directory-alt p { + margin: 0px; + white-space: nowrap; +} + +.directory-alt div { + display: none; + margin: 0px; +} + +.directory-alt img { + vertical-align: -30%; +} + +/* @end */ + +div.dynheader { + margin-top: 8px; +} + +address { + font-style: normal; + color: #2A3D61; +} + +table.doxtable { + border-collapse:collapse; +} + +table.doxtable td, table.doxtable th { + border: 1px solid #2D4068; + padding: 3px 7px 2px; +} + +table.doxtable th { + background-color: #374F7F; + color: #FFFFFF; + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; + text-align:left; +} + +.tabsearch { + top: 0px; + left: 10px; + height: 36px; + background-image: url('tab_b.png'); + z-index: 101; + overflow: hidden; + font-size: 13px; +} + +.navpath ul +{ + font-size: 11px; + background-image:url('tab_b.png'); + background-repeat:repeat-x; + height:30px; + line-height:30px; + color:#8AA0CC; + border:solid 1px #C2CDE4; + overflow:hidden; + margin:0px; + padding:0px; +} + +.navpath li +{ + list-style-type:none; + float:left; + padding-left:10px; + padding-right: 15px; + background-image:url('bc_s.png'); + background-repeat:no-repeat; + background-position:right; + color:#364D7C; +} + +.navpath a +{ + height:32px; + display:block; + text-decoration: none; + outline: none; +} + +.navpath a:hover +{ + color:#6884BD; +} + +div.summary +{ + float: right; + font-size: 8pt; + padding-right: 5px; + width: 50%; + text-align: right; +} + +div.summary a +{ + white-space: nowrap; +} + +div.header +{ + background-image:url('nav_h.png'); + background-repeat:repeat-x; + background-color: #F9FAFC; + margin: 0px; + border-bottom: 1px solid #C4CFE5; +} + +div.headertitle +{ + padding: 5px 5px 5px 10px; +} + diff --git a/doc/html/doxygen.png b/doc/html/doxygen.png new file mode 100644 index 0000000000000000000000000000000000000000..635ed52fce7057ac24df92ec7664088a881fa5d0 GIT binary patch literal 3942 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 A+yDRo literal 0 HcmV?d00001 diff --git a/doc/html/files.html b/doc/html/files.html new file mode 100644 index 00000000000..7bd75eeab83 --- /dev/null +++ b/doc/html/files.html @@ -0,0 +1,40 @@ + + + + +yaml: File Index + + + + + + +
    +
    +

    File List

    +
    +
    +Here is a list of all documented files with brief descriptions: + +
    yaml.hPublic interface for libyaml
    +
    + + + diff --git a/doc/html/functions.html b/doc/html/functions.html new file mode 100644 index 00000000000..16e9eda3819 --- /dev/null +++ b/doc/html/functions.html @@ -0,0 +1,91 @@ + + + + +yaml: Data Fields + + + + + + +
    +Here is a list of all documented struct and union fields with links to the struct/union documentation for each field: + +

    - a -

    +
    + + + diff --git a/doc/html/functions_0x62.html b/doc/html/functions_0x62.html new file mode 100644 index 00000000000..902caf267ce --- /dev/null +++ b/doc/html/functions_0x62.html @@ -0,0 +1,84 @@ + + + + +yaml: Data Fields + + + + + + +
    +Here is a list of all documented struct and union fields with links to the struct/union documentation for each field: + +

    - b -

    +
    + + + diff --git a/doc/html/functions_0x63.html b/doc/html/functions_0x63.html new file mode 100644 index 00000000000..fff0416f099 --- /dev/null +++ b/doc/html/functions_0x63.html @@ -0,0 +1,87 @@ + + + + +yaml: Data Fields + + + + + + +
    +Here is a list of all documented struct and union fields with links to the struct/union documentation for each field: + +

    - c -

    +
    + + + diff --git a/doc/html/functions_0x64.html b/doc/html/functions_0x64.html new file mode 100644 index 00000000000..921b4c1a98a --- /dev/null +++ b/doc/html/functions_0x64.html @@ -0,0 +1,83 @@ + + + + +yaml: Data Fields + + + + + + +
    +Here is a list of all documented struct and union fields with links to the struct/union documentation for each field: + +

    - d -

    +
    + + + diff --git a/doc/html/functions_0x65.html b/doc/html/functions_0x65.html new file mode 100644 index 00000000000..d0d3e309f33 --- /dev/null +++ b/doc/html/functions_0x65.html @@ -0,0 +1,110 @@ + + + + +yaml: Data Fields + + + + + + +
    +Here is a list of all documented struct and union fields with links to the struct/union documentation for each field: + +

    - e -

    +
    + + + diff --git a/doc/html/functions_0x66.html b/doc/html/functions_0x66.html new file mode 100644 index 00000000000..e95a19d73f8 --- /dev/null +++ b/doc/html/functions_0x66.html @@ -0,0 +1,79 @@ + + + + +yaml: Data Fields + + + + + + +
    +Here is a list of all documented struct and union fields with links to the struct/union documentation for each field: + +

    - f -

    +
    + + + diff --git a/doc/html/functions_0x68.html b/doc/html/functions_0x68.html new file mode 100644 index 00000000000..5283c33488e --- /dev/null +++ b/doc/html/functions_0x68.html @@ -0,0 +1,80 @@ + + + + +yaml: Data Fields + + + + + + +
    +Here is a list of all documented struct and union fields with links to the struct/union documentation for each field: + +

    - h -

    +
    + + + diff --git a/doc/html/functions_0x69.html b/doc/html/functions_0x69.html new file mode 100644 index 00000000000..1900c9c46b2 --- /dev/null +++ b/doc/html/functions_0x69.html @@ -0,0 +1,92 @@ + + + + +yaml: Data Fields + + + + + + +
    +Here is a list of all documented struct and union fields with links to the struct/union documentation for each field: + +

    - i -

    +
    + + + diff --git a/doc/html/functions_0x6b.html b/doc/html/functions_0x6b.html new file mode 100644 index 00000000000..c9aaa19b485 --- /dev/null +++ b/doc/html/functions_0x6b.html @@ -0,0 +1,71 @@ + + + + +yaml: Data Fields + + + + + + +
    +Here is a list of all documented struct and union fields with links to the struct/union documentation for each field: + +

    - k -

    +
    + + + diff --git a/doc/html/functions_0x6c.html b/doc/html/functions_0x6c.html new file mode 100644 index 00000000000..539a4d23522 --- /dev/null +++ b/doc/html/functions_0x6c.html @@ -0,0 +1,88 @@ + + + + +yaml: Data Fields + + + + + + +
    +Here is a list of all documented struct and union fields with links to the struct/union documentation for each field: + +

    - l -

    +
    + + + diff --git a/doc/html/functions_0x6d.html b/doc/html/functions_0x6d.html new file mode 100644 index 00000000000..858ec44f865 --- /dev/null +++ b/doc/html/functions_0x6d.html @@ -0,0 +1,96 @@ + + + + +yaml: Data Fields + + + + + + +
    +Here is a list of all documented struct and union fields with links to the struct/union documentation for each field: + +

    - m -

    +
    + + + diff --git a/doc/html/functions_0x6e.html b/doc/html/functions_0x6e.html new file mode 100644 index 00000000000..3c30d537614 --- /dev/null +++ b/doc/html/functions_0x6e.html @@ -0,0 +1,71 @@ + + + + +yaml: Data Fields + + + + + + +
    +Here is a list of all documented struct and union fields with links to the struct/union documentation for each field: + +

    - n -

    +
    + + + diff --git a/doc/html/functions_0x6f.html b/doc/html/functions_0x6f.html new file mode 100644 index 00000000000..da9d90132ab --- /dev/null +++ b/doc/html/functions_0x6f.html @@ -0,0 +1,80 @@ + + + + +yaml: Data Fields + + + + + + +
    +Here is a list of all documented struct and union fields with links to the struct/union documentation for each field: + +

    - o -

    +
    + + + diff --git a/doc/html/functions_0x70.html b/doc/html/functions_0x70.html new file mode 100644 index 00000000000..531cfe62191 --- /dev/null +++ b/doc/html/functions_0x70.html @@ -0,0 +1,100 @@ + + + + +yaml: Data Fields + + + + + + +
    +Here is a list of all documented struct and union fields with links to the struct/union documentation for each field: + +

    - p -

    +
    + + + diff --git a/doc/html/functions_0x71.html b/doc/html/functions_0x71.html new file mode 100644 index 00000000000..6cd72b7b604 --- /dev/null +++ b/doc/html/functions_0x71.html @@ -0,0 +1,71 @@ + + + + +yaml: Data Fields + + + + + + +
    +Here is a list of all documented struct and union fields with links to the struct/union documentation for each field: + +

    - q -

    +
    + + + diff --git a/doc/html/functions_0x72.html b/doc/html/functions_0x72.html new file mode 100644 index 00000000000..5409ee67723 --- /dev/null +++ b/doc/html/functions_0x72.html @@ -0,0 +1,87 @@ + + + + +yaml: Data Fields + + + + + + +
    +Here is a list of all documented struct and union fields with links to the struct/union documentation for each field: + +

    - r -

    +
    + + + diff --git a/doc/html/functions_0x73.html b/doc/html/functions_0x73.html new file mode 100644 index 00000000000..8caa39d0d17 --- /dev/null +++ b/doc/html/functions_0x73.html @@ -0,0 +1,163 @@ + + + + +yaml: Data Fields + + + + + + +
    +Here is a list of all documented struct and union fields with links to the struct/union documentation for each field: + +

    - s -

    +
    + + + diff --git a/doc/html/functions_0x74.html b/doc/html/functions_0x74.html new file mode 100644 index 00000000000..6adf45e8834 --- /dev/null +++ b/doc/html/functions_0x74.html @@ -0,0 +1,115 @@ + + + + +yaml: Data Fields + + + + + + +
    +Here is a list of all documented struct and union fields with links to the struct/union documentation for each field: + +

    - t -

    +
    + + + diff --git a/doc/html/functions_0x75.html b/doc/html/functions_0x75.html new file mode 100644 index 00000000000..6d48a8f05bc --- /dev/null +++ b/doc/html/functions_0x75.html @@ -0,0 +1,71 @@ + + + + +yaml: Data Fields + + + + + + +
    +Here is a list of all documented struct and union fields with links to the struct/union documentation for each field: + +

    - u -

    +
    + + + diff --git a/doc/html/functions_0x76.html b/doc/html/functions_0x76.html new file mode 100644 index 00000000000..d510ab80e5b --- /dev/null +++ b/doc/html/functions_0x76.html @@ -0,0 +1,80 @@ + + + + +yaml: Data Fields + + + + + + +
    +Here is a list of all documented struct and union fields with links to the struct/union documentation for each field: + +

    - v -

    +
    + + + diff --git a/doc/html/functions_0x77.html b/doc/html/functions_0x77.html new file mode 100644 index 00000000000..44b8d29a2c0 --- /dev/null +++ b/doc/html/functions_0x77.html @@ -0,0 +1,77 @@ + + + + +yaml: Data Fields + + + + + + +
    +Here is a list of all documented struct and union fields with links to the struct/union documentation for each field: + +

    - w -

    +
    + + + diff --git a/doc/html/functions_vars.html b/doc/html/functions_vars.html new file mode 100644 index 00000000000..c8b5032cb50 --- /dev/null +++ b/doc/html/functions_vars.html @@ -0,0 +1,91 @@ + + + + +yaml: Data Fields - Variables + + + + + + +
    +  + +

    - a -

    +
    + + + diff --git a/doc/html/functions_vars_0x62.html b/doc/html/functions_vars_0x62.html new file mode 100644 index 00000000000..0d04a425313 --- /dev/null +++ b/doc/html/functions_vars_0x62.html @@ -0,0 +1,84 @@ + + + + +yaml: Data Fields - Variables + + + + + + +
    +  + +

    - b -

    +
    + + + diff --git a/doc/html/functions_vars_0x63.html b/doc/html/functions_vars_0x63.html new file mode 100644 index 00000000000..0edc9012eb3 --- /dev/null +++ b/doc/html/functions_vars_0x63.html @@ -0,0 +1,87 @@ + + + + +yaml: Data Fields - Variables + + + + + + +
    +  + +

    - c -

    +
    + + + diff --git a/doc/html/functions_vars_0x64.html b/doc/html/functions_vars_0x64.html new file mode 100644 index 00000000000..8d476e9cf67 --- /dev/null +++ b/doc/html/functions_vars_0x64.html @@ -0,0 +1,83 @@ + + + + +yaml: Data Fields - Variables + + + + + + +
    +  + +

    - d -

    +
    + + + diff --git a/doc/html/functions_vars_0x65.html b/doc/html/functions_vars_0x65.html new file mode 100644 index 00000000000..97f2269c445 --- /dev/null +++ b/doc/html/functions_vars_0x65.html @@ -0,0 +1,110 @@ + + + + +yaml: Data Fields - Variables + + + + + + + + + + diff --git a/doc/html/functions_vars_0x66.html b/doc/html/functions_vars_0x66.html new file mode 100644 index 00000000000..bee0ee01513 --- /dev/null +++ b/doc/html/functions_vars_0x66.html @@ -0,0 +1,79 @@ + + + + +yaml: Data Fields - Variables + + + + + + +
    +  + +

    - f -

    +
    + + + diff --git a/doc/html/functions_vars_0x68.html b/doc/html/functions_vars_0x68.html new file mode 100644 index 00000000000..bda8dc8286b --- /dev/null +++ b/doc/html/functions_vars_0x68.html @@ -0,0 +1,80 @@ + + + + +yaml: Data Fields - Variables + + + + + + +
    +  + +

    - h -

    +
    + + + diff --git a/doc/html/functions_vars_0x69.html b/doc/html/functions_vars_0x69.html new file mode 100644 index 00000000000..92e1376e0ac --- /dev/null +++ b/doc/html/functions_vars_0x69.html @@ -0,0 +1,92 @@ + + + + +yaml: Data Fields - Variables + + + + + + +
    +  + +

    - i -

    +
    + + + diff --git a/doc/html/functions_vars_0x6b.html b/doc/html/functions_vars_0x6b.html new file mode 100644 index 00000000000..14231cea25d --- /dev/null +++ b/doc/html/functions_vars_0x6b.html @@ -0,0 +1,71 @@ + + + + +yaml: Data Fields - Variables + + + + + + +
    +  + +

    - k -

    +
    + + + diff --git a/doc/html/functions_vars_0x6c.html b/doc/html/functions_vars_0x6c.html new file mode 100644 index 00000000000..ae53df573d8 --- /dev/null +++ b/doc/html/functions_vars_0x6c.html @@ -0,0 +1,88 @@ + + + + +yaml: Data Fields - Variables + + + + + + +
    +  + +

    - l -

    +
    + + + diff --git a/doc/html/functions_vars_0x6d.html b/doc/html/functions_vars_0x6d.html new file mode 100644 index 00000000000..63919e13ef0 --- /dev/null +++ b/doc/html/functions_vars_0x6d.html @@ -0,0 +1,96 @@ + + + + +yaml: Data Fields - Variables + + + + + + +
    +  + +

    - m -

    +
    + + + diff --git a/doc/html/functions_vars_0x6e.html b/doc/html/functions_vars_0x6e.html new file mode 100644 index 00000000000..c959180c750 --- /dev/null +++ b/doc/html/functions_vars_0x6e.html @@ -0,0 +1,71 @@ + + + + +yaml: Data Fields - Variables + + + + + + +
    +  + +

    - n -

    +
    + + + diff --git a/doc/html/functions_vars_0x6f.html b/doc/html/functions_vars_0x6f.html new file mode 100644 index 00000000000..8a91fce5c2d --- /dev/null +++ b/doc/html/functions_vars_0x6f.html @@ -0,0 +1,80 @@ + + + + +yaml: Data Fields - Variables + + + + + + +
    +  + +

    - o -

    +
    + + + diff --git a/doc/html/functions_vars_0x70.html b/doc/html/functions_vars_0x70.html new file mode 100644 index 00000000000..abe744c5684 --- /dev/null +++ b/doc/html/functions_vars_0x70.html @@ -0,0 +1,100 @@ + + + + +yaml: Data Fields - Variables + + + + + + +
    +  + +

    - p -

    +
    + + + diff --git a/doc/html/functions_vars_0x71.html b/doc/html/functions_vars_0x71.html new file mode 100644 index 00000000000..002c8f08c2f --- /dev/null +++ b/doc/html/functions_vars_0x71.html @@ -0,0 +1,71 @@ + + + + +yaml: Data Fields - Variables + + + + + + +
    +  + +

    - q -

    +
    + + + diff --git a/doc/html/functions_vars_0x72.html b/doc/html/functions_vars_0x72.html new file mode 100644 index 00000000000..cc9aff5c589 --- /dev/null +++ b/doc/html/functions_vars_0x72.html @@ -0,0 +1,87 @@ + + + + +yaml: Data Fields - Variables + + + + + + +
    +  + +

    - r -

    +
    + + + diff --git a/doc/html/functions_vars_0x73.html b/doc/html/functions_vars_0x73.html new file mode 100644 index 00000000000..2aedfe18564 --- /dev/null +++ b/doc/html/functions_vars_0x73.html @@ -0,0 +1,163 @@ + + + + +yaml: Data Fields - Variables + + + + + + +
    +  + +

    - s -

    +
    + + + diff --git a/doc/html/functions_vars_0x74.html b/doc/html/functions_vars_0x74.html new file mode 100644 index 00000000000..2eb7278f7d2 --- /dev/null +++ b/doc/html/functions_vars_0x74.html @@ -0,0 +1,115 @@ + + + + +yaml: Data Fields - Variables + + + + + + +
    +  + +

    - t -

    +
    + + + diff --git a/doc/html/functions_vars_0x75.html b/doc/html/functions_vars_0x75.html new file mode 100644 index 00000000000..c445f6f7b2e --- /dev/null +++ b/doc/html/functions_vars_0x75.html @@ -0,0 +1,71 @@ + + + + +yaml: Data Fields - Variables + + + + + + +
    +  + +

    - u -

    +
    + + + diff --git a/doc/html/functions_vars_0x76.html b/doc/html/functions_vars_0x76.html new file mode 100644 index 00000000000..4e0d3aee526 --- /dev/null +++ b/doc/html/functions_vars_0x76.html @@ -0,0 +1,80 @@ + + + + +yaml: Data Fields - Variables + + + + + + +
    +  + +

    - v -

    +
    + + + diff --git a/doc/html/functions_vars_0x77.html b/doc/html/functions_vars_0x77.html new file mode 100644 index 00000000000..946db4260e5 --- /dev/null +++ b/doc/html/functions_vars_0x77.html @@ -0,0 +1,77 @@ + + + + +yaml: Data Fields - Variables + + + + + + +
    +  + +

    - w -

    +
    + + + diff --git a/doc/html/globals.html b/doc/html/globals.html new file mode 100644 index 00000000000..eb4fc4e3ff5 --- /dev/null +++ b/doc/html/globals.html @@ -0,0 +1,667 @@ + + + + +yaml: Data Fields + + + + + + +
    +Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation: + +

    - y -

      +
    • yaml_alias_data_t +: yaml.h +
    • +
    • YAML_ALIAS_EVENT +: yaml.h +
    • +
    • yaml_alias_event_initialize() +: yaml.h +
    • +
    • YAML_ALIAS_TOKEN +: yaml.h +
    • +
    • YAML_ANCHOR_TOKEN +: yaml.h +
    • +
    • YAML_ANY_BREAK +: yaml.h +
    • +
    • YAML_ANY_ENCODING +: yaml.h +
    • +
    • YAML_ANY_MAPPING_STYLE +: yaml.h +
    • +
    • YAML_ANY_SCALAR_STYLE +: yaml.h +
    • +
    • YAML_ANY_SEQUENCE_STYLE +: yaml.h +
    • +
    • YAML_BLOCK_END_TOKEN +: yaml.h +
    • +
    • YAML_BLOCK_ENTRY_TOKEN +: yaml.h +
    • +
    • YAML_BLOCK_MAPPING_START_TOKEN +: yaml.h +
    • +
    • YAML_BLOCK_MAPPING_STYLE +: yaml.h +
    • +
    • YAML_BLOCK_SEQUENCE_START_TOKEN +: yaml.h +
    • +
    • YAML_BLOCK_SEQUENCE_STYLE +: yaml.h +
    • +
    • YAML_BOOL_TAG +: yaml.h +
    • +
    • yaml_break_e +: yaml.h +
    • +
    • yaml_break_t +: yaml.h +
    • +
    • yaml_char_t +: yaml.h +
    • +
    • YAML_COMPOSER_ERROR +: yaml.h +
    • +
    • YAML_CR_BREAK +: yaml.h +
    • +
    • YAML_CRLN_BREAK +: yaml.h +
    • +
    • YAML_DECLARE +: yaml.h +
    • +
    • YAML_DEFAULT_MAPPING_TAG +: yaml.h +
    • +
    • YAML_DEFAULT_SCALAR_TAG +: yaml.h +
    • +
    • YAML_DEFAULT_SEQUENCE_TAG +: yaml.h +
    • +
    • yaml_document_add_mapping() +: yaml.h +
    • +
    • yaml_document_add_scalar() +: yaml.h +
    • +
    • yaml_document_add_sequence() +: yaml.h +
    • +
    • yaml_document_append_mapping_pair() +: yaml.h +
    • +
    • yaml_document_append_sequence_item() +: yaml.h +
    • +
    • yaml_document_delete() +: yaml.h +
    • +
    • YAML_DOCUMENT_END_EVENT +: yaml.h +
    • +
    • yaml_document_end_event_initialize() +: yaml.h +
    • +
    • YAML_DOCUMENT_END_TOKEN +: yaml.h +
    • +
    • yaml_document_get_node() +: yaml.h +
    • +
    • yaml_document_get_root_node() +: yaml.h +
    • +
    • yaml_document_initialize() +: yaml.h +
    • +
    • YAML_DOCUMENT_START_EVENT +: yaml.h +
    • +
    • yaml_document_start_event_initialize() +: yaml.h +
    • +
    • YAML_DOCUMENT_START_TOKEN +: yaml.h +
    • +
    • yaml_document_t +: yaml.h +
    • +
    • YAML_DOUBLE_QUOTED_SCALAR_STYLE +: yaml.h +
    • +
    • YAML_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE +: yaml.h +
    • +
    • YAML_EMIT_BLOCK_MAPPING_KEY_STATE +: yaml.h +
    • +
    • YAML_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE +: yaml.h +
    • +
    • YAML_EMIT_BLOCK_MAPPING_VALUE_STATE +: yaml.h +
    • +
    • YAML_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE +: yaml.h +
    • +
    • YAML_EMIT_BLOCK_SEQUENCE_ITEM_STATE +: yaml.h +
    • +
    • YAML_EMIT_DOCUMENT_CONTENT_STATE +: yaml.h +
    • +
    • YAML_EMIT_DOCUMENT_END_STATE +: yaml.h +
    • +
    • YAML_EMIT_DOCUMENT_START_STATE +: yaml.h +
    • +
    • YAML_EMIT_END_STATE +: yaml.h +
    • +
    • YAML_EMIT_FIRST_DOCUMENT_START_STATE +: yaml.h +
    • +
    • YAML_EMIT_FLOW_MAPPING_FIRST_KEY_STATE +: yaml.h +
    • +
    • YAML_EMIT_FLOW_MAPPING_KEY_STATE +: yaml.h +
    • +
    • YAML_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE +: yaml.h +
    • +
    • YAML_EMIT_FLOW_MAPPING_VALUE_STATE +: yaml.h +
    • +
    • YAML_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE +: yaml.h +
    • +
    • YAML_EMIT_FLOW_SEQUENCE_ITEM_STATE +: yaml.h +
    • +
    • YAML_EMIT_STREAM_START_STATE +: yaml.h +
    • +
    • yaml_emitter_close() +: yaml.h +
    • +
    • yaml_emitter_delete() +: yaml.h +
    • +
    • yaml_emitter_dump() +: yaml.h +
    • +
    • yaml_emitter_emit() +: yaml.h +
    • +
    • YAML_EMITTER_ERROR +: yaml.h +
    • +
    • yaml_emitter_flush() +: yaml.h +
    • +
    • yaml_emitter_initialize() +: yaml.h +
    • +
    • yaml_emitter_open() +: yaml.h +
    • +
    • yaml_emitter_set_break() +: yaml.h +
    • +
    • yaml_emitter_set_canonical() +: yaml.h +
    • +
    • yaml_emitter_set_encoding() +: yaml.h +
    • +
    • yaml_emitter_set_indent() +: yaml.h +
    • +
    • yaml_emitter_set_output() +: yaml.h +
    • +
    • yaml_emitter_set_output_file() +: yaml.h +
    • +
    • yaml_emitter_set_output_string() +: yaml.h +
    • +
    • yaml_emitter_set_unicode() +: yaml.h +
    • +
    • yaml_emitter_set_width() +: yaml.h +
    • +
    • yaml_emitter_state_e +: yaml.h +
    • +
    • yaml_emitter_state_t +: yaml.h +
    • +
    • yaml_emitter_t +: yaml.h +
    • +
    • yaml_encoding_e +: yaml.h +
    • +
    • yaml_encoding_t +: yaml.h +
    • +
    • yaml_error_type_e +: yaml.h +
    • +
    • yaml_error_type_t +: yaml.h +
    • +
    • yaml_event_delete() +: yaml.h +
    • +
    • yaml_event_t +: yaml.h +
    • +
    • yaml_event_type_e +: yaml.h +
    • +
    • yaml_event_type_t +: yaml.h +
    • +
    • YAML_FLOAT_TAG +: yaml.h +
    • +
    • YAML_FLOW_ENTRY_TOKEN +: yaml.h +
    • +
    • YAML_FLOW_MAPPING_END_TOKEN +: yaml.h +
    • +
    • YAML_FLOW_MAPPING_START_TOKEN +: yaml.h +
    • +
    • YAML_FLOW_MAPPING_STYLE +: yaml.h +
    • +
    • YAML_FLOW_SEQUENCE_END_TOKEN +: yaml.h +
    • +
    • YAML_FLOW_SEQUENCE_START_TOKEN +: yaml.h +
    • +
    • YAML_FLOW_SEQUENCE_STYLE +: yaml.h +
    • +
    • YAML_FOLDED_SCALAR_STYLE +: yaml.h +
    • +
    • yaml_get_version() +: yaml.h +
    • +
    • yaml_get_version_string() +: yaml.h +
    • +
    • YAML_INT_TAG +: yaml.h +
    • +
    • YAML_KEY_TOKEN +: yaml.h +
    • +
    • YAML_LITERAL_SCALAR_STYLE +: yaml.h +
    • +
    • YAML_LN_BREAK +: yaml.h +
    • +
    • YAML_MAP_TAG +: yaml.h +
    • +
    • YAML_MAPPING_END_EVENT +: yaml.h +
    • +
    • yaml_mapping_end_event_initialize() +: yaml.h +
    • +
    • YAML_MAPPING_NODE +: yaml.h +
    • +
    • YAML_MAPPING_START_EVENT +: yaml.h +
    • +
    • yaml_mapping_start_event_initialize() +: yaml.h +
    • +
    • yaml_mapping_style_e +: yaml.h +
    • +
    • yaml_mapping_style_t +: yaml.h +
    • +
    • yaml_mark_t +: yaml.h +
    • +
    • YAML_MEMORY_ERROR +: yaml.h +
    • +
    • YAML_NO_ERROR +: yaml.h +
    • +
    • YAML_NO_EVENT +: yaml.h +
    • +
    • YAML_NO_NODE +: yaml.h +
    • +
    • YAML_NO_TOKEN +: yaml.h +
    • +
    • yaml_node_item_t +: yaml.h +
    • +
    • yaml_node_pair_t +: yaml.h +
    • +
    • yaml_node_t +: yaml.h +
    • +
    • yaml_node_type_e +: yaml.h +
    • +
    • yaml_node_type_t +: yaml.h +
    • +
    • YAML_NULL_TAG +: yaml.h +
    • +
    • YAML_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE +: yaml.h +
    • +
    • YAML_PARSE_BLOCK_MAPPING_KEY_STATE +: yaml.h +
    • +
    • YAML_PARSE_BLOCK_MAPPING_VALUE_STATE +: yaml.h +
    • +
    • YAML_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE +: yaml.h +
    • +
    • YAML_PARSE_BLOCK_NODE_STATE +: yaml.h +
    • +
    • YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE +: yaml.h +
    • +
    • YAML_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE +: yaml.h +
    • +
    • YAML_PARSE_DOCUMENT_CONTENT_STATE +: yaml.h +
    • +
    • YAML_PARSE_DOCUMENT_END_STATE +: yaml.h +
    • +
    • YAML_PARSE_DOCUMENT_START_STATE +: yaml.h +
    • +
    • YAML_PARSE_END_STATE +: yaml.h +
    • +
    • YAML_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE +: yaml.h +
    • +
    • YAML_PARSE_FLOW_MAPPING_FIRST_KEY_STATE +: yaml.h +
    • +
    • YAML_PARSE_FLOW_MAPPING_KEY_STATE +: yaml.h +
    • +
    • YAML_PARSE_FLOW_MAPPING_VALUE_STATE +: yaml.h +
    • +
    • YAML_PARSE_FLOW_NODE_STATE +: yaml.h +
    • +
    • YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE +: yaml.h +
    • +
    • YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE +: yaml.h +
    • +
    • YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE +: yaml.h +
    • +
    • YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE +: yaml.h +
    • +
    • YAML_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE +: yaml.h +
    • +
    • YAML_PARSE_IMPLICIT_DOCUMENT_START_STATE +: yaml.h +
    • +
    • YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE +: yaml.h +
    • +
    • YAML_PARSE_STREAM_START_STATE +: yaml.h +
    • +
    • yaml_parser_delete() +: yaml.h +
    • +
    • YAML_PARSER_ERROR +: yaml.h +
    • +
    • yaml_parser_initialize() +: yaml.h +
    • +
    • yaml_parser_load() +: yaml.h +
    • +
    • yaml_parser_parse() +: yaml.h +
    • +
    • yaml_parser_scan() +: yaml.h +
    • +
    • yaml_parser_set_encoding() +: yaml.h +
    • +
    • yaml_parser_set_input() +: yaml.h +
    • +
    • yaml_parser_set_input_file() +: yaml.h +
    • +
    • yaml_parser_set_input_string() +: yaml.h +
    • +
    • yaml_parser_state_e +: yaml.h +
    • +
    • yaml_parser_state_t +: yaml.h +
    • +
    • yaml_parser_t +: yaml.h +
    • +
    • YAML_PLAIN_SCALAR_STYLE +: yaml.h +
    • +
    • yaml_read_handler_t +: yaml.h +
    • +
    • YAML_READER_ERROR +: yaml.h +
    • +
    • YAML_SCALAR_EVENT +: yaml.h +
    • +
    • yaml_scalar_event_initialize() +: yaml.h +
    • +
    • YAML_SCALAR_NODE +: yaml.h +
    • +
    • yaml_scalar_style_e +: yaml.h +
    • +
    • yaml_scalar_style_t +: yaml.h +
    • +
    • YAML_SCALAR_TOKEN +: yaml.h +
    • +
    • YAML_SCANNER_ERROR +: yaml.h +
    • +
    • YAML_SEQ_TAG +: yaml.h +
    • +
    • YAML_SEQUENCE_END_EVENT +: yaml.h +
    • +
    • yaml_sequence_end_event_initialize() +: yaml.h +
    • +
    • YAML_SEQUENCE_NODE +: yaml.h +
    • +
    • YAML_SEQUENCE_START_EVENT +: yaml.h +
    • +
    • yaml_sequence_start_event_initialize() +: yaml.h +
    • +
    • yaml_sequence_style_e +: yaml.h +
    • +
    • yaml_sequence_style_t +: yaml.h +
    • +
    • yaml_simple_key_t +: yaml.h +
    • +
    • YAML_SINGLE_QUOTED_SCALAR_STYLE +: yaml.h +
    • +
    • YAML_STR_TAG +: yaml.h +
    • +
    • YAML_STREAM_END_EVENT +: yaml.h +
    • +
    • yaml_stream_end_event_initialize() +: yaml.h +
    • +
    • YAML_STREAM_END_TOKEN +: yaml.h +
    • +
    • YAML_STREAM_START_EVENT +: yaml.h +
    • +
    • yaml_stream_start_event_initialize() +: yaml.h +
    • +
    • YAML_STREAM_START_TOKEN +: yaml.h +
    • +
    • yaml_tag_directive_t +: yaml.h +
    • +
    • YAML_TAG_DIRECTIVE_TOKEN +: yaml.h +
    • +
    • YAML_TAG_TOKEN +: yaml.h +
    • +
    • YAML_TIMESTAMP_TAG +: yaml.h +
    • +
    • yaml_token_delete() +: yaml.h +
    • +
    • yaml_token_t +: yaml.h +
    • +
    • yaml_token_type_e +: yaml.h +
    • +
    • yaml_token_type_t +: yaml.h +
    • +
    • YAML_UTF16BE_ENCODING +: yaml.h +
    • +
    • YAML_UTF16LE_ENCODING +: yaml.h +
    • +
    • YAML_UTF8_ENCODING +: yaml.h +
    • +
    • YAML_VALUE_TOKEN +: yaml.h +
    • +
    • yaml_version_directive_t +: yaml.h +
    • +
    • YAML_VERSION_DIRECTIVE_TOKEN +: yaml.h +
    • +
    • yaml_write_handler_t +: yaml.h +
    • +
    • YAML_WRITER_ERROR +: yaml.h +
    • +
    +
    + + + diff --git a/doc/html/globals_defs.html b/doc/html/globals_defs.html new file mode 100644 index 00000000000..be3b627d3a7 --- /dev/null +++ b/doc/html/globals_defs.html @@ -0,0 +1,81 @@ + + + + +yaml: Data Fields + + + + + + +
      +
    • YAML_BOOL_TAG +: yaml.h +
    • +
    • YAML_DECLARE +: yaml.h +
    • +
    • YAML_DEFAULT_MAPPING_TAG +: yaml.h +
    • +
    • YAML_DEFAULT_SCALAR_TAG +: yaml.h +
    • +
    • YAML_DEFAULT_SEQUENCE_TAG +: yaml.h +
    • +
    • YAML_FLOAT_TAG +: yaml.h +
    • +
    • YAML_INT_TAG +: yaml.h +
    • +
    • YAML_MAP_TAG +: yaml.h +
    • +
    • YAML_NULL_TAG +: yaml.h +
    • +
    • YAML_SEQ_TAG +: yaml.h +
    • +
    • YAML_STR_TAG +: yaml.h +
    • +
    • YAML_TIMESTAMP_TAG +: yaml.h +
    • +
    +
    + + + diff --git a/doc/html/globals_enum.html b/doc/html/globals_enum.html new file mode 100644 index 00000000000..675ee0b26b8 --- /dev/null +++ b/doc/html/globals_enum.html @@ -0,0 +1,78 @@ + + + + +yaml: Data Fields + + + + + + +
      +
    • yaml_break_e +: yaml.h +
    • +
    • yaml_emitter_state_e +: yaml.h +
    • +
    • yaml_encoding_e +: yaml.h +
    • +
    • yaml_error_type_e +: yaml.h +
    • +
    • yaml_event_type_e +: yaml.h +
    • +
    • yaml_mapping_style_e +: yaml.h +
    • +
    • yaml_node_type_e +: yaml.h +
    • +
    • yaml_parser_state_e +: yaml.h +
    • +
    • yaml_scalar_style_e +: yaml.h +
    • +
    • yaml_sequence_style_e +: yaml.h +
    • +
    • yaml_token_type_e +: yaml.h +
    • +
    +
    + + + diff --git a/doc/html/globals_eval.html b/doc/html/globals_eval.html new file mode 100644 index 00000000000..e7c103c9e11 --- /dev/null +++ b/doc/html/globals_eval.html @@ -0,0 +1,373 @@ + + + + +yaml: Data Fields + + + + + + +
    +  + +

    - y -

      +
    • YAML_ALIAS_EVENT +: yaml.h +
    • +
    • YAML_ALIAS_TOKEN +: yaml.h +
    • +
    • YAML_ANCHOR_TOKEN +: yaml.h +
    • +
    • YAML_ANY_BREAK +: yaml.h +
    • +
    • YAML_ANY_ENCODING +: yaml.h +
    • +
    • YAML_ANY_MAPPING_STYLE +: yaml.h +
    • +
    • YAML_ANY_SCALAR_STYLE +: yaml.h +
    • +
    • YAML_ANY_SEQUENCE_STYLE +: yaml.h +
    • +
    • YAML_BLOCK_END_TOKEN +: yaml.h +
    • +
    • YAML_BLOCK_ENTRY_TOKEN +: yaml.h +
    • +
    • YAML_BLOCK_MAPPING_START_TOKEN +: yaml.h +
    • +
    • YAML_BLOCK_MAPPING_STYLE +: yaml.h +
    • +
    • YAML_BLOCK_SEQUENCE_START_TOKEN +: yaml.h +
    • +
    • YAML_BLOCK_SEQUENCE_STYLE +: yaml.h +
    • +
    • YAML_COMPOSER_ERROR +: yaml.h +
    • +
    • YAML_CR_BREAK +: yaml.h +
    • +
    • YAML_CRLN_BREAK +: yaml.h +
    • +
    • YAML_DOCUMENT_END_EVENT +: yaml.h +
    • +
    • YAML_DOCUMENT_END_TOKEN +: yaml.h +
    • +
    • YAML_DOCUMENT_START_EVENT +: yaml.h +
    • +
    • YAML_DOCUMENT_START_TOKEN +: yaml.h +
    • +
    • YAML_DOUBLE_QUOTED_SCALAR_STYLE +: yaml.h +
    • +
    • YAML_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE +: yaml.h +
    • +
    • YAML_EMIT_BLOCK_MAPPING_KEY_STATE +: yaml.h +
    • +
    • YAML_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE +: yaml.h +
    • +
    • YAML_EMIT_BLOCK_MAPPING_VALUE_STATE +: yaml.h +
    • +
    • YAML_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE +: yaml.h +
    • +
    • YAML_EMIT_BLOCK_SEQUENCE_ITEM_STATE +: yaml.h +
    • +
    • YAML_EMIT_DOCUMENT_CONTENT_STATE +: yaml.h +
    • +
    • YAML_EMIT_DOCUMENT_END_STATE +: yaml.h +
    • +
    • YAML_EMIT_DOCUMENT_START_STATE +: yaml.h +
    • +
    • YAML_EMIT_END_STATE +: yaml.h +
    • +
    • YAML_EMIT_FIRST_DOCUMENT_START_STATE +: yaml.h +
    • +
    • YAML_EMIT_FLOW_MAPPING_FIRST_KEY_STATE +: yaml.h +
    • +
    • YAML_EMIT_FLOW_MAPPING_KEY_STATE +: yaml.h +
    • +
    • YAML_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE +: yaml.h +
    • +
    • YAML_EMIT_FLOW_MAPPING_VALUE_STATE +: yaml.h +
    • +
    • YAML_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE +: yaml.h +
    • +
    • YAML_EMIT_FLOW_SEQUENCE_ITEM_STATE +: yaml.h +
    • +
    • YAML_EMIT_STREAM_START_STATE +: yaml.h +
    • +
    • YAML_EMITTER_ERROR +: yaml.h +
    • +
    • YAML_FLOW_ENTRY_TOKEN +: yaml.h +
    • +
    • YAML_FLOW_MAPPING_END_TOKEN +: yaml.h +
    • +
    • YAML_FLOW_MAPPING_START_TOKEN +: yaml.h +
    • +
    • YAML_FLOW_MAPPING_STYLE +: yaml.h +
    • +
    • YAML_FLOW_SEQUENCE_END_TOKEN +: yaml.h +
    • +
    • YAML_FLOW_SEQUENCE_START_TOKEN +: yaml.h +
    • +
    • YAML_FLOW_SEQUENCE_STYLE +: yaml.h +
    • +
    • YAML_FOLDED_SCALAR_STYLE +: yaml.h +
    • +
    • YAML_KEY_TOKEN +: yaml.h +
    • +
    • YAML_LITERAL_SCALAR_STYLE +: yaml.h +
    • +
    • YAML_LN_BREAK +: yaml.h +
    • +
    • YAML_MAPPING_END_EVENT +: yaml.h +
    • +
    • YAML_MAPPING_NODE +: yaml.h +
    • +
    • YAML_MAPPING_START_EVENT +: yaml.h +
    • +
    • YAML_MEMORY_ERROR +: yaml.h +
    • +
    • YAML_NO_ERROR +: yaml.h +
    • +
    • YAML_NO_EVENT +: yaml.h +
    • +
    • YAML_NO_NODE +: yaml.h +
    • +
    • YAML_NO_TOKEN +: yaml.h +
    • +
    • YAML_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE +: yaml.h +
    • +
    • YAML_PARSE_BLOCK_MAPPING_KEY_STATE +: yaml.h +
    • +
    • YAML_PARSE_BLOCK_MAPPING_VALUE_STATE +: yaml.h +
    • +
    • YAML_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE +: yaml.h +
    • +
    • YAML_PARSE_BLOCK_NODE_STATE +: yaml.h +
    • +
    • YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE +: yaml.h +
    • +
    • YAML_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE +: yaml.h +
    • +
    • YAML_PARSE_DOCUMENT_CONTENT_STATE +: yaml.h +
    • +
    • YAML_PARSE_DOCUMENT_END_STATE +: yaml.h +
    • +
    • YAML_PARSE_DOCUMENT_START_STATE +: yaml.h +
    • +
    • YAML_PARSE_END_STATE +: yaml.h +
    • +
    • YAML_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE +: yaml.h +
    • +
    • YAML_PARSE_FLOW_MAPPING_FIRST_KEY_STATE +: yaml.h +
    • +
    • YAML_PARSE_FLOW_MAPPING_KEY_STATE +: yaml.h +
    • +
    • YAML_PARSE_FLOW_MAPPING_VALUE_STATE +: yaml.h +
    • +
    • YAML_PARSE_FLOW_NODE_STATE +: yaml.h +
    • +
    • YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE +: yaml.h +
    • +
    • YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE +: yaml.h +
    • +
    • YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE +: yaml.h +
    • +
    • YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE +: yaml.h +
    • +
    • YAML_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE +: yaml.h +
    • +
    • YAML_PARSE_IMPLICIT_DOCUMENT_START_STATE +: yaml.h +
    • +
    • YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE +: yaml.h +
    • +
    • YAML_PARSE_STREAM_START_STATE +: yaml.h +
    • +
    • YAML_PARSER_ERROR +: yaml.h +
    • +
    • YAML_PLAIN_SCALAR_STYLE +: yaml.h +
    • +
    • YAML_READER_ERROR +: yaml.h +
    • +
    • YAML_SCALAR_EVENT +: yaml.h +
    • +
    • YAML_SCALAR_NODE +: yaml.h +
    • +
    • YAML_SCALAR_TOKEN +: yaml.h +
    • +
    • YAML_SCANNER_ERROR +: yaml.h +
    • +
    • YAML_SEQUENCE_END_EVENT +: yaml.h +
    • +
    • YAML_SEQUENCE_NODE +: yaml.h +
    • +
    • YAML_SEQUENCE_START_EVENT +: yaml.h +
    • +
    • YAML_SINGLE_QUOTED_SCALAR_STYLE +: yaml.h +
    • +
    • YAML_STREAM_END_EVENT +: yaml.h +
    • +
    • YAML_STREAM_END_TOKEN +: yaml.h +
    • +
    • YAML_STREAM_START_EVENT +: yaml.h +
    • +
    • YAML_STREAM_START_TOKEN +: yaml.h +
    • +
    • YAML_TAG_DIRECTIVE_TOKEN +: yaml.h +
    • +
    • YAML_TAG_TOKEN +: yaml.h +
    • +
    • YAML_UTF16BE_ENCODING +: yaml.h +
    • +
    • YAML_UTF16LE_ENCODING +: yaml.h +
    • +
    • YAML_UTF8_ENCODING +: yaml.h +
    • +
    • YAML_VALUE_TOKEN +: yaml.h +
    • +
    • YAML_VERSION_DIRECTIVE_TOKEN +: yaml.h +
    • +
    • YAML_WRITER_ERROR +: yaml.h +
    • +
    +
    + + + diff --git a/doc/html/globals_func.html b/doc/html/globals_func.html new file mode 100644 index 00000000000..5e55c16784e --- /dev/null +++ b/doc/html/globals_func.html @@ -0,0 +1,196 @@ + + + + +yaml: Data Fields + + + + + + +
    +  + +

    - y -

      +
    • yaml_alias_event_initialize() +: yaml.h +
    • +
    • yaml_document_add_mapping() +: yaml.h +
    • +
    • yaml_document_add_scalar() +: yaml.h +
    • +
    • yaml_document_add_sequence() +: yaml.h +
    • +
    • yaml_document_append_mapping_pair() +: yaml.h +
    • +
    • yaml_document_append_sequence_item() +: yaml.h +
    • +
    • yaml_document_delete() +: yaml.h +
    • +
    • yaml_document_end_event_initialize() +: yaml.h +
    • +
    • yaml_document_get_node() +: yaml.h +
    • +
    • yaml_document_get_root_node() +: yaml.h +
    • +
    • yaml_document_initialize() +: yaml.h +
    • +
    • yaml_document_start_event_initialize() +: yaml.h +
    • +
    • yaml_emitter_close() +: yaml.h +
    • +
    • yaml_emitter_delete() +: yaml.h +
    • +
    • yaml_emitter_dump() +: yaml.h +
    • +
    • yaml_emitter_emit() +: yaml.h +
    • +
    • yaml_emitter_flush() +: yaml.h +
    • +
    • yaml_emitter_initialize() +: yaml.h +
    • +
    • yaml_emitter_open() +: yaml.h +
    • +
    • yaml_emitter_set_break() +: yaml.h +
    • +
    • yaml_emitter_set_canonical() +: yaml.h +
    • +
    • yaml_emitter_set_encoding() +: yaml.h +
    • +
    • yaml_emitter_set_indent() +: yaml.h +
    • +
    • yaml_emitter_set_output() +: yaml.h +
    • +
    • yaml_emitter_set_output_file() +: yaml.h +
    • +
    • yaml_emitter_set_output_string() +: yaml.h +
    • +
    • yaml_emitter_set_unicode() +: yaml.h +
    • +
    • yaml_emitter_set_width() +: yaml.h +
    • +
    • yaml_event_delete() +: yaml.h +
    • +
    • yaml_get_version() +: yaml.h +
    • +
    • yaml_get_version_string() +: yaml.h +
    • +
    • yaml_mapping_end_event_initialize() +: yaml.h +
    • +
    • yaml_mapping_start_event_initialize() +: yaml.h +
    • +
    • yaml_parser_delete() +: yaml.h +
    • +
    • yaml_parser_initialize() +: yaml.h +
    • +
    • yaml_parser_load() +: yaml.h +
    • +
    • yaml_parser_parse() +: yaml.h +
    • +
    • yaml_parser_scan() +: yaml.h +
    • +
    • yaml_parser_set_encoding() +: yaml.h +
    • +
    • yaml_parser_set_input() +: yaml.h +
    • +
    • yaml_parser_set_input_file() +: yaml.h +
    • +
    • yaml_parser_set_input_string() +: yaml.h +
    • +
    • yaml_scalar_event_initialize() +: yaml.h +
    • +
    • yaml_sequence_end_event_initialize() +: yaml.h +
    • +
    • yaml_sequence_start_event_initialize() +: yaml.h +
    • +
    • yaml_stream_end_event_initialize() +: yaml.h +
    • +
    • yaml_stream_start_event_initialize() +: yaml.h +
    • +
    • yaml_token_delete() +: yaml.h +
    • +
    +
    + + + diff --git a/doc/html/globals_type.html b/doc/html/globals_type.html new file mode 100644 index 00000000000..854125b5bb3 --- /dev/null +++ b/doc/html/globals_type.html @@ -0,0 +1,126 @@ + + + + +yaml: Data Fields + + + + + + +
      +
    • yaml_alias_data_t +: yaml.h +
    • +
    • yaml_break_t +: yaml.h +
    • +
    • yaml_char_t +: yaml.h +
    • +
    • yaml_document_t +: yaml.h +
    • +
    • yaml_emitter_state_t +: yaml.h +
    • +
    • yaml_emitter_t +: yaml.h +
    • +
    • yaml_encoding_t +: yaml.h +
    • +
    • yaml_error_type_t +: yaml.h +
    • +
    • yaml_event_t +: yaml.h +
    • +
    • yaml_event_type_t +: yaml.h +
    • +
    • yaml_mapping_style_t +: yaml.h +
    • +
    • yaml_mark_t +: yaml.h +
    • +
    • yaml_node_item_t +: yaml.h +
    • +
    • yaml_node_pair_t +: yaml.h +
    • +
    • yaml_node_t +: yaml.h +
    • +
    • yaml_node_type_t +: yaml.h +
    • +
    • yaml_parser_state_t +: yaml.h +
    • +
    • yaml_parser_t +: yaml.h +
    • +
    • yaml_read_handler_t +: yaml.h +
    • +
    • yaml_scalar_style_t +: yaml.h +
    • +
    • yaml_sequence_style_t +: yaml.h +
    • +
    • yaml_simple_key_t +: yaml.h +
    • +
    • yaml_tag_directive_t +: yaml.h +
    • +
    • yaml_token_t +: yaml.h +
    • +
    • yaml_token_type_t +: yaml.h +
    • +
    • yaml_version_directive_t +: yaml.h +
    • +
    • yaml_write_handler_t +: yaml.h +
    • +
    +
    + + + diff --git a/doc/html/group__basic.html b/doc/html/group__basic.html new file mode 100644 index 00000000000..636b7db6c1e --- /dev/null +++ b/doc/html/group__basic.html @@ -0,0 +1,320 @@ + + + + +yaml: Basic Types + + + + + + +
    + +
    +

    Basic Types

    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    +Data Structures

    struct  yaml_version_directive_s
     The version directive data. More...
    struct  yaml_tag_directive_s
     The tag directive data. More...
    struct  yaml_mark_s
     The pointer position. More...

    +Typedefs

    typedef unsigned char yaml_char_t
     The character type (UTF-8 octet).
    typedef struct
    +yaml_version_directive_s 
    yaml_version_directive_t
     The version directive data.
    typedef struct yaml_tag_directive_s yaml_tag_directive_t
     The tag directive data.
    typedef enum yaml_encoding_e yaml_encoding_t
     The stream encoding.
    typedef enum yaml_break_e yaml_break_t
     Line break types.
    typedef enum yaml_error_type_e yaml_error_type_t
     Many bad things could happen with the parser and emitter.
    typedef struct yaml_mark_s yaml_mark_t
     The pointer position.

    +Enumerations

    enum  yaml_encoding_e {
    +  YAML_ANY_ENCODING, +
    +  YAML_UTF8_ENCODING, +
    +  YAML_UTF16LE_ENCODING, +
    +  YAML_UTF16BE_ENCODING +
    + }
     

    The stream encoding.

    + More...
    enum  yaml_break_e {
    +  YAML_ANY_BREAK, +
    +  YAML_CR_BREAK, +
    +  YAML_LN_BREAK, +
    +  YAML_CRLN_BREAK +
    + }
     

    Line break types.

    + More...
    enum  yaml_error_type_e {
    +  YAML_NO_ERROR, +
    +  YAML_MEMORY_ERROR, +
    +  YAML_READER_ERROR, +
    +  YAML_SCANNER_ERROR, +
    +  YAML_PARSER_ERROR, +
    +  YAML_COMPOSER_ERROR, +
    +  YAML_WRITER_ERROR, +
    +  YAML_EMITTER_ERROR +
    + }
     

    Many bad things could happen with the parser and emitter.

    + More...
    +

    Typedef Documentation

    + +
    +
    + + + + +
    typedef unsigned char yaml_char_t
    +
    +
    + +

    The character type (UTF-8 octet).

    + +
    +
    + +
    + +
    + +

    The version directive data.

    + +
    +
    + +
    +
    + + + + +
    typedef struct yaml_tag_directive_s yaml_tag_directive_t
    +
    +
    + +

    The tag directive data.

    + +
    +
    + +
    +
    + + + + +
    typedef enum yaml_encoding_e yaml_encoding_t
    +
    +
    + +

    The stream encoding.

    + +
    +
    + +
    +
    + + + + +
    typedef enum yaml_break_e yaml_break_t
    +
    +
    + +

    Line break types.

    + +
    +
    + +
    +
    + + + + +
    typedef enum yaml_error_type_e yaml_error_type_t
    +
    +
    + +

    Many bad things could happen with the parser and emitter.

    + +
    +
    + +
    +
    + + + + +
    typedef struct yaml_mark_s yaml_mark_t
    +
    +
    + +

    The pointer position.

    + +
    +
    +

    Enumeration Type Documentation

    + +
    +
    + + + + +
    enum yaml_encoding_e
    +
    +
    + +

    The stream encoding.

    +
    Enumerator:
    + + + + +
    YAML_ANY_ENCODING  +

    Let the parser choose the encoding.

    +
    YAML_UTF8_ENCODING  +

    The default UTF-8 encoding.

    +
    YAML_UTF16LE_ENCODING  +

    The UTF-16-LE encoding with BOM.

    +
    YAML_UTF16BE_ENCODING  +

    The UTF-16-BE encoding with BOM.

    +
    +
    +
    + +
    +
    + +
    +
    + + + + +
    enum yaml_break_e
    +
    +
    + +

    Line break types.

    +
    Enumerator:
    + + + + +
    YAML_ANY_BREAK  +

    Let the parser choose the break type.

    +
    YAML_CR_BREAK  +

    Use CR for line breaks (Mac style).

    +
    YAML_LN_BREAK  +

    Use LN for line breaks (Unix style).

    +
    YAML_CRLN_BREAK  +

    Use CR LN for line breaks (DOS style).

    +
    +
    +
    + +
    +
    + +
    +
    + + + + +
    enum yaml_error_type_e
    +
    +
    + +

    Many bad things could happen with the parser and emitter.

    +
    Enumerator:
    + + + + + + + + +
    YAML_NO_ERROR  +

    No error is produced.

    +
    YAML_MEMORY_ERROR  +

    Cannot allocate or reallocate a block of memory.

    +
    YAML_READER_ERROR  +

    Cannot read or decode the input stream.

    +
    YAML_SCANNER_ERROR  +

    Cannot scan the input stream.

    +
    YAML_PARSER_ERROR  +

    Cannot parse the input stream.

    +
    YAML_COMPOSER_ERROR  +

    Cannot compose a YAML document.

    +
    YAML_WRITER_ERROR  +

    Cannot write to the output stream.

    +
    YAML_EMITTER_ERROR  +

    Cannot emit a YAML stream.

    +
    +
    +
    + +
    +
    +
    + + + diff --git a/doc/html/group__emitter.html b/doc/html/group__emitter.html new file mode 100644 index 00000000000..b0f9256ec68 --- /dev/null +++ b/doc/html/group__emitter.html @@ -0,0 +1,819 @@ + + + + +yaml: Emitter Definitions + + + + + + +
    + +
    +

    Emitter Definitions

    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    +Data Structures

    struct  yaml_emitter_s
     The emitter structure. More...

    +Typedefs

    typedef int yaml_write_handler_t (void *data, unsigned char *buffer, size_t size)
     The prototype of a write handler.
    typedef enum yaml_emitter_state_e yaml_emitter_state_t
     The emitter states.
    typedef struct yaml_emitter_s yaml_emitter_t
     The emitter structure.

    +Enumerations

    enum  yaml_emitter_state_e {
    +  YAML_EMIT_STREAM_START_STATE, +
    +  YAML_EMIT_FIRST_DOCUMENT_START_STATE, +
    +  YAML_EMIT_DOCUMENT_START_STATE, +
    +  YAML_EMIT_DOCUMENT_CONTENT_STATE, +
    +  YAML_EMIT_DOCUMENT_END_STATE, +
    +  YAML_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE, +
    +  YAML_EMIT_FLOW_SEQUENCE_ITEM_STATE, +
    +  YAML_EMIT_FLOW_MAPPING_FIRST_KEY_STATE, +
    +  YAML_EMIT_FLOW_MAPPING_KEY_STATE, +
    +  YAML_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE, +
    +  YAML_EMIT_FLOW_MAPPING_VALUE_STATE, +
    +  YAML_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE, +
    +  YAML_EMIT_BLOCK_SEQUENCE_ITEM_STATE, +
    +  YAML_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE, +
    +  YAML_EMIT_BLOCK_MAPPING_KEY_STATE, +
    +  YAML_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE, +
    +  YAML_EMIT_BLOCK_MAPPING_VALUE_STATE, +
    +  YAML_EMIT_END_STATE +
    + }
     

    The emitter states.

    + More...

    +Functions

    int yaml_emitter_initialize (yaml_emitter_t *emitter)
     Initialize an emitter.
    void yaml_emitter_delete (yaml_emitter_t *emitter)
     Destroy an emitter.
    void yaml_emitter_set_output_string (yaml_emitter_t *emitter, unsigned char *output, size_t size, size_t *size_written)
     Set a string output.
    void yaml_emitter_set_output_file (yaml_emitter_t *emitter, FILE *file)
     Set a file output.
    void yaml_emitter_set_output (yaml_emitter_t *emitter, yaml_write_handler_t *handler, void *data)
     Set a generic output handler.
    void yaml_emitter_set_encoding (yaml_emitter_t *emitter, yaml_encoding_t encoding)
     Set the output encoding.
    void yaml_emitter_set_canonical (yaml_emitter_t *emitter, int canonical)
     Set if the output should be in the "canonical" format as in the YAML specification.
    void yaml_emitter_set_indent (yaml_emitter_t *emitter, int indent)
     Set the intendation increment.
    void yaml_emitter_set_width (yaml_emitter_t *emitter, int width)
     Set the preferred line width.
    void yaml_emitter_set_unicode (yaml_emitter_t *emitter, int unicode)
     Set if unescaped non-ASCII characters are allowed.
    void yaml_emitter_set_break (yaml_emitter_t *emitter, yaml_break_t line_break)
     Set the preferred line break.
    int yaml_emitter_emit (yaml_emitter_t *emitter, yaml_event_t *event)
     Emit an event.
    int yaml_emitter_open (yaml_emitter_t *emitter)
     Start a YAML stream.
    int yaml_emitter_close (yaml_emitter_t *emitter)
     Finish a YAML stream.
    int yaml_emitter_dump (yaml_emitter_t *emitter, yaml_document_t *document)
     Emit a YAML document.
    int yaml_emitter_flush (yaml_emitter_t *emitter)
     Flush the accumulated characters to the output.
    +

    Typedef Documentation

    + +
    +
    + + + + +
    typedef int yaml_write_handler_t(void *data, unsigned char *buffer, size_t size)
    +
    +
    + +

    The prototype of a write handler.

    +

    The write handler is called when the emitter needs to flush the accumulated characters to the output. The handler should write size bytes of the buffer to the output.

    +
    Parameters:
    + + + + +
    [in,out] data A pointer to an application data specified by yaml_emitter_set_output().
    [in] buffer The buffer with bytes to be written.
    [in] size The size of the buffer.
    +
    +
    +
    Returns:
    On success, the handler should return 1. If the handler failed, the returned value should be 0.
    + +
    +
    + +
    +
    + + + + +
    typedef enum yaml_emitter_state_e yaml_emitter_state_t
    +
    +
    + +

    The emitter states.

    + +
    +
    + +
    +
    + + + + +
    typedef struct yaml_emitter_s yaml_emitter_t
    +
    +
    + +

    The emitter structure.

    +

    All members are internal. Manage the structure using the yaml_emitter_ family of functions.

    + +
    +
    +

    Enumeration Type Documentation

    + +
    +
    + + + + +
    enum yaml_emitter_state_e
    +
    +
    + +

    The emitter states.

    +
    Enumerator:
    + + + + + + + + + + + + + + + + + + +
    YAML_EMIT_STREAM_START_STATE  +

    Expect STREAM-START.

    +
    YAML_EMIT_FIRST_DOCUMENT_START_STATE  +

    Expect the first DOCUMENT-START or STREAM-END.

    +
    YAML_EMIT_DOCUMENT_START_STATE  +

    Expect DOCUMENT-START or STREAM-END.

    +
    YAML_EMIT_DOCUMENT_CONTENT_STATE  +

    Expect the content of a document.

    +
    YAML_EMIT_DOCUMENT_END_STATE  +

    Expect DOCUMENT-END.

    +
    YAML_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE  +

    Expect the first item of a flow sequence.

    +
    YAML_EMIT_FLOW_SEQUENCE_ITEM_STATE  +

    Expect an item of a flow sequence.

    +
    YAML_EMIT_FLOW_MAPPING_FIRST_KEY_STATE  +

    Expect the first key of a flow mapping.

    +
    YAML_EMIT_FLOW_MAPPING_KEY_STATE  +

    Expect a key of a flow mapping.

    +
    YAML_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE  +

    Expect a value for a simple key of a flow mapping.

    +
    YAML_EMIT_FLOW_MAPPING_VALUE_STATE  +

    Expect a value of a flow mapping.

    +
    YAML_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE  +

    Expect the first item of a block sequence.

    +
    YAML_EMIT_BLOCK_SEQUENCE_ITEM_STATE  +

    Expect an item of a block sequence.

    +
    YAML_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE  +

    Expect the first key of a block mapping.

    +
    YAML_EMIT_BLOCK_MAPPING_KEY_STATE  +

    Expect the key of a block mapping.

    +
    YAML_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE  +

    Expect a value for a simple key of a block mapping.

    +
    YAML_EMIT_BLOCK_MAPPING_VALUE_STATE  +

    Expect a value of a block mapping.

    +
    YAML_EMIT_END_STATE  +

    Expect nothing.

    +
    +
    +
    + +
    +
    +

    Function Documentation

    + +
    +
    + + + + + + + + + +
    int yaml_emitter_initialize (yaml_emitter_t emitter ) 
    +
    +
    + +

    Initialize an emitter.

    +

    This function creates a new emitter object. An application is responsible for destroying the object using the yaml_emitter_delete() function.

    +
    Parameters:
    + + +
    [out] emitter An empty parser object.
    +
    +
    +
    Returns:
    1 if the function succeeded, 0 on error.
    + +
    +
    + +
    +
    + + + + + + + + + +
    void yaml_emitter_delete (yaml_emitter_t emitter ) 
    +
    +
    + +

    Destroy an emitter.

    +
    Parameters:
    + + +
    [in,out] emitter An emitter object.
    +
    +
    + +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    void yaml_emitter_set_output_string (yaml_emitter_t emitter,
    unsigned char *  output,
    size_t  size,
    size_t *  size_written 
    )
    +
    +
    + +

    Set a string output.

    +

    The emitter will write the output characters to the output buffer of the size size. The emitter will set size_written to the number of written bytes. If the buffer is smaller than required, the emitter produces the YAML_WRITE_ERROR error.

    +
    Parameters:
    + + + + + +
    [in,out] emitter An emitter object.
    [in] output An output buffer.
    [in] size The buffer size.
    [in] size_written The pointer to save the number of written bytes.
    +
    +
    + +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + +
    void yaml_emitter_set_output_file (yaml_emitter_t emitter,
    FILE *  file 
    )
    +
    +
    + +

    Set a file output.

    +

    file should be a file object open for writing. The application is responsible for closing the file.

    +
    Parameters:
    + + + +
    [in,out] emitter An emitter object.
    [in] file An open file.
    +
    +
    + +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    void yaml_emitter_set_output (yaml_emitter_t emitter,
    yaml_write_handler_t handler,
    void *  data 
    )
    +
    +
    + +

    Set a generic output handler.

    +
    Parameters:
    + + + + +
    [in,out] emitter An emitter object.
    [in] handler A write handler.
    [in] data Any application data for passing to the write handler.
    +
    +
    + +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + +
    void yaml_emitter_set_encoding (yaml_emitter_t emitter,
    yaml_encoding_t  encoding 
    )
    +
    +
    + +

    Set the output encoding.

    +
    Parameters:
    + + + +
    [in,out] emitter An emitter object.
    [in] encoding The output encoding.
    +
    +
    + +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + +
    void yaml_emitter_set_canonical (yaml_emitter_t emitter,
    int  canonical 
    )
    +
    +
    + +

    Set if the output should be in the "canonical" format as in the YAML specification.

    +
    Parameters:
    + + + +
    [in,out] emitter An emitter object.
    [in] canonical If the output is canonical.
    +
    +
    + +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + +
    void yaml_emitter_set_indent (yaml_emitter_t emitter,
    int  indent 
    )
    +
    +
    + +

    Set the intendation increment.

    +
    Parameters:
    + + + +
    [in,out] emitter An emitter object.
    [in] indent The indentation increment (1 < . < 10).
    +
    +
    + +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + +
    void yaml_emitter_set_width (yaml_emitter_t emitter,
    int  width 
    )
    +
    +
    + +

    Set the preferred line width.

    +

    -1 means unlimited.

    +
    Parameters:
    + + + +
    [in,out] emitter An emitter object.
    [in] width The preferred line width.
    +
    +
    + +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + +
    void yaml_emitter_set_unicode (yaml_emitter_t emitter,
    int  unicode 
    )
    +
    +
    + +

    Set if unescaped non-ASCII characters are allowed.

    +
    Parameters:
    + + + +
    [in,out] emitter An emitter object.
    [in] unicode If unescaped Unicode characters are allowed.
    +
    +
    + +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + +
    void yaml_emitter_set_break (yaml_emitter_t emitter,
    yaml_break_t  line_break 
    )
    +
    +
    + +

    Set the preferred line break.

    +
    Parameters:
    + + + +
    [in,out] emitter An emitter object.
    [in] line_break The preferred line break.
    +
    +
    + +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + +
    int yaml_emitter_emit (yaml_emitter_t emitter,
    yaml_event_t event 
    )
    +
    +
    + +

    Emit an event.

    +

    The event object may be generated using the yaml_parser_parse() function. The emitter takes the responsibility for the event object and destroys its content after it is emitted. The event object is destroyed even if the function fails.

    +
    Parameters:
    + + + +
    [in,out] emitter An emitter object.
    [in,out] event An event object.
    +
    +
    +
    Returns:
    1 if the function succeeded, 0 on error.
    + +
    +
    + +
    +
    + + + + + + + + + +
    int yaml_emitter_open (yaml_emitter_t emitter ) 
    +
    +
    + +

    Start a YAML stream.

    +

    This function should be used before yaml_emitter_dump() is called.

    +
    Parameters:
    + + +
    [in,out] emitter An emitter object.
    +
    +
    +
    Returns:
    1 if the function succeeded, 0 on error.
    + +
    +
    + +
    +
    + + + + + + + + + +
    int yaml_emitter_close (yaml_emitter_t emitter ) 
    +
    +
    + +

    Finish a YAML stream.

    +

    This function should be used after yaml_emitter_dump() is called.

    +
    Parameters:
    + + +
    [in,out] emitter An emitter object.
    +
    +
    +
    Returns:
    1 if the function succeeded, 0 on error.
    + +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + +
    int yaml_emitter_dump (yaml_emitter_t emitter,
    yaml_document_t document 
    )
    +
    +
    + +

    Emit a YAML document.

    +

    The documen object may be generated using the yaml_parser_load() function or the yaml_document_initialize() function. The emitter takes the responsibility for the document object and destoys its content after it is emitted. The document object is destroyedeven if the function fails.

    +
    Parameters:
    + + + +
    [in,out] emitter An emitter object.
    [in,out] document A document object.
    +
    +
    +
    Returns:
    1 if the function succeeded, 0 on error.
    + +
    +
    + +
    +
    + + + + + + + + + +
    int yaml_emitter_flush (yaml_emitter_t emitter ) 
    +
    +
    + +

    Flush the accumulated characters to the output.

    +
    Parameters:
    + + +
    [in,out] emitter An emitter object.
    +
    +
    +
    Returns:
    1 if the function succeeded, 0 on error.
    + +
    +
    +
    + + + diff --git a/doc/html/group__events.html b/doc/html/group__events.html new file mode 100644 index 00000000000..43e81b329dd --- /dev/null +++ b/doc/html/group__events.html @@ -0,0 +1,664 @@ + + + + +yaml: Events + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    +Data Structures

    struct  yaml_event_s
     The event structure. More...

    +Typedefs

    typedef enum yaml_event_type_e yaml_event_type_t
     Event types.
    typedef struct yaml_event_s yaml_event_t
     The event structure.

    +Enumerations

    enum  yaml_event_type_e {
    +  YAML_NO_EVENT, +
    +  YAML_STREAM_START_EVENT, +
    +  YAML_STREAM_END_EVENT, +
    +  YAML_DOCUMENT_START_EVENT, +
    +  YAML_DOCUMENT_END_EVENT, +
    +  YAML_ALIAS_EVENT, +
    +  YAML_SCALAR_EVENT, +
    +  YAML_SEQUENCE_START_EVENT, +
    +  YAML_SEQUENCE_END_EVENT, +
    +  YAML_MAPPING_START_EVENT, +
    +  YAML_MAPPING_END_EVENT +
    + }
     

    Event types.

    + More...

    +Functions

    int yaml_stream_start_event_initialize (yaml_event_t *event, yaml_encoding_t encoding)
     Create the STREAM-START event.
    int yaml_stream_end_event_initialize (yaml_event_t *event)
     Create the STREAM-END event.
    int yaml_document_start_event_initialize (yaml_event_t *event, yaml_version_directive_t *version_directive, yaml_tag_directive_t *tag_directives_start, yaml_tag_directive_t *tag_directives_end, int implicit)
     Create the DOCUMENT-START event.
    int yaml_document_end_event_initialize (yaml_event_t *event, int implicit)
     Create the DOCUMENT-END event.
    int yaml_alias_event_initialize (yaml_event_t *event, yaml_char_t *anchor)
     Create an ALIAS event.
    int yaml_scalar_event_initialize (yaml_event_t *event, yaml_char_t *anchor, yaml_char_t *tag, yaml_char_t *value, int length, int plain_implicit, int quoted_implicit, yaml_scalar_style_t style)
     Create a SCALAR event.
    int yaml_sequence_start_event_initialize (yaml_event_t *event, yaml_char_t *anchor, yaml_char_t *tag, int implicit, yaml_sequence_style_t style)
     Create a SEQUENCE-START event.
    int yaml_sequence_end_event_initialize (yaml_event_t *event)
     Create a SEQUENCE-END event.
    int yaml_mapping_start_event_initialize (yaml_event_t *event, yaml_char_t *anchor, yaml_char_t *tag, int implicit, yaml_mapping_style_t style)
     Create a MAPPING-START event.
    int yaml_mapping_end_event_initialize (yaml_event_t *event)
     Create a MAPPING-END event.
    void yaml_event_delete (yaml_event_t *event)
     Free any memory allocated for an event object.
    +

    Typedef Documentation

    + +
    +
    + + + + +
    typedef enum yaml_event_type_e yaml_event_type_t
    +
    +
    + +

    Event types.

    + +
    +
    + +
    +
    + + + + +
    typedef struct yaml_event_s yaml_event_t
    +
    +
    + +

    The event structure.

    + +
    +
    +

    Enumeration Type Documentation

    + +
    +
    + + + + +
    enum yaml_event_type_e
    +
    +
    + +

    Event types.

    +
    Enumerator:
    + + + + + + + + + + + +
    YAML_NO_EVENT  +

    An empty event.

    +
    YAML_STREAM_START_EVENT  +

    A STREAM-START event.

    +
    YAML_STREAM_END_EVENT  +

    A STREAM-END event.

    +
    YAML_DOCUMENT_START_EVENT  +

    A DOCUMENT-START event.

    +
    YAML_DOCUMENT_END_EVENT  +

    A DOCUMENT-END event.

    +
    YAML_ALIAS_EVENT  +

    An ALIAS event.

    +
    YAML_SCALAR_EVENT  +

    A SCALAR event.

    +
    YAML_SEQUENCE_START_EVENT  +

    A SEQUENCE-START event.

    +
    YAML_SEQUENCE_END_EVENT  +

    A SEQUENCE-END event.

    +
    YAML_MAPPING_START_EVENT  +

    A MAPPING-START event.

    +
    YAML_MAPPING_END_EVENT  +

    A MAPPING-END event.

    +
    +
    +
    + +
    +
    +

    Function Documentation

    + +
    +
    + + + + + + + + + + + + + + + + + + +
    int yaml_stream_start_event_initialize (yaml_event_t event,
    yaml_encoding_t  encoding 
    )
    +
    +
    + +

    Create the STREAM-START event.

    +
    Parameters:
    + + + +
    [out] event An empty event object.
    [in] encoding The stream encoding.
    +
    +
    +
    Returns:
    1 if the function succeeded, 0 on error.
    + +
    +
    + +
    +
    + + + + + + + + + +
    int yaml_stream_end_event_initialize (yaml_event_t event ) 
    +
    +
    + +

    Create the STREAM-END event.

    +
    Parameters:
    + + +
    [out] event An empty event object.
    +
    +
    +
    Returns:
    1 if the function succeeded, 0 on error.
    + +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    int yaml_document_start_event_initialize (yaml_event_t event,
    yaml_version_directive_t version_directive,
    yaml_tag_directive_t tag_directives_start,
    yaml_tag_directive_t tag_directives_end,
    int  implicit 
    )
    +
    +
    + +

    Create the DOCUMENT-START event.

    +

    The implicit argument is considered as a stylistic parameter and may be ignored by the emitter.

    +
    Parameters:
    + + + + + + +
    [out] event An empty event object.
    [in] version_directive The YAML directive value or NULL.
    [in] tag_directives_start The beginning of the TAG directives list.
    [in] tag_directives_end The end of the TAG directives list.
    [in] implicit If the document start indicator is implicit.
    +
    +
    +
    Returns:
    1 if the function succeeded, 0 on error.
    + +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + +
    int yaml_document_end_event_initialize (yaml_event_t event,
    int  implicit 
    )
    +
    +
    + +

    Create the DOCUMENT-END event.

    +

    The implicit argument is considered as a stylistic parameter and may be ignored by the emitter.

    +
    Parameters:
    + + + +
    [out] event An empty event object.
    [in] implicit If the document end indicator is implicit.
    +
    +
    +
    Returns:
    1 if the function succeeded, 0 on error.
    + +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + +
    int yaml_alias_event_initialize (yaml_event_t event,
    yaml_char_t anchor 
    )
    +
    +
    + +

    Create an ALIAS event.

    +
    Parameters:
    + + + +
    [out] event An empty event object.
    [in] anchor The anchor value.
    +
    +
    +
    Returns:
    1 if the function succeeded, 0 on error.
    + +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    int yaml_scalar_event_initialize (yaml_event_t event,
    yaml_char_t anchor,
    yaml_char_t tag,
    yaml_char_t value,
    int  length,
    int  plain_implicit,
    int  quoted_implicit,
    yaml_scalar_style_t  style 
    )
    +
    +
    + +

    Create a SCALAR event.

    +

    The style argument may be ignored by the emitter.

    +

    Either the tag attribute or one of the plain_implicit and quoted_implicit flags must be set.

    +
    Parameters:
    + + + + + + + + + +
    [out] event An empty event object.
    [in] anchor The scalar anchor or NULL.
    [in] tag The scalar tag or NULL.
    [in] value The scalar value.
    [in] length The length of the scalar value.
    [in] plain_implicit If the tag may be omitted for the plain style.
    [in] quoted_implicit If the tag may be omitted for any non-plain style.
    [in] style The scalar style.
    +
    +
    +
    Returns:
    1 if the function succeeded, 0 on error.
    + +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    int yaml_sequence_start_event_initialize (yaml_event_t event,
    yaml_char_t anchor,
    yaml_char_t tag,
    int  implicit,
    yaml_sequence_style_t  style 
    )
    +
    +
    + +

    Create a SEQUENCE-START event.

    +

    The style argument may be ignored by the emitter.

    +

    Either the tag attribute or the implicit flag must be set.

    +
    Parameters:
    + + + + + + +
    [out] event An empty event object.
    [in] anchor The sequence anchor or NULL.
    [in] tag The sequence tag or NULL.
    [in] implicit If the tag may be omitted.
    [in] style The sequence style.
    +
    +
    +
    Returns:
    1 if the function succeeded, 0 on error.
    + +
    +
    + +
    +
    + + + + + + + + + +
    int yaml_sequence_end_event_initialize (yaml_event_t event ) 
    +
    +
    + +

    Create a SEQUENCE-END event.

    +
    Parameters:
    + + +
    [out] event An empty event object.
    +
    +
    +
    Returns:
    1 if the function succeeded, 0 on error.
    + +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    int yaml_mapping_start_event_initialize (yaml_event_t event,
    yaml_char_t anchor,
    yaml_char_t tag,
    int  implicit,
    yaml_mapping_style_t  style 
    )
    +
    +
    + +

    Create a MAPPING-START event.

    +

    The style argument may be ignored by the emitter.

    +

    Either the tag attribute or the implicit flag must be set.

    +
    Parameters:
    + + + + + + +
    [out] event An empty event object.
    [in] anchor The mapping anchor or NULL.
    [in] tag The mapping tag or NULL.
    [in] implicit If the tag may be omitted.
    [in] style The mapping style.
    +
    +
    +
    Returns:
    1 if the function succeeded, 0 on error.
    + +
    +
    + +
    +
    + + + + + + + + + +
    int yaml_mapping_end_event_initialize (yaml_event_t event ) 
    +
    +
    + +

    Create a MAPPING-END event.

    +
    Parameters:
    + + +
    [out] event An empty event object.
    +
    +
    +
    Returns:
    1 if the function succeeded, 0 on error.
    + +
    +
    + +
    +
    + + + + + + + + + +
    void yaml_event_delete (yaml_event_t event ) 
    +
    +
    + +

    Free any memory allocated for an event object.

    +
    Parameters:
    + + +
    [in,out] event An event object.
    +
    +
    + +
    +
    +
    + + + diff --git a/doc/html/group__export.html b/doc/html/group__export.html new file mode 100644 index 00000000000..2a57b6f3dd3 --- /dev/null +++ b/doc/html/group__export.html @@ -0,0 +1,60 @@ + + + + +yaml: Export Definitions + + + + + + +
    + +
    +

    Export Definitions

    +
    +
    + + + + +

    +Defines

    #define YAML_DECLARE(type)   type
     The public API declaration.
    +

    Define Documentation

    + +
    +
    + + + + + + + + + +
    #define YAML_DECLARE( type )    type
    +
    +
    + +

    The public API declaration.

    + +
    +
    +
    + + + diff --git a/doc/html/group__nodes.html b/doc/html/group__nodes.html new file mode 100644 index 00000000000..e0713ccbfd0 --- /dev/null +++ b/doc/html/group__nodes.html @@ -0,0 +1,795 @@ + + + + +yaml: Nodes + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    +Data Structures

    struct  yaml_node_pair_s
     An element of a mapping node. More...
    struct  yaml_node_s
     The node structure. More...
    struct  yaml_document_s
     The document structure. More...

    +Defines

    #define YAML_NULL_TAG   "tag:yaml.org,2002:null"
     The tag !!null with the only possible value: null.
    #define YAML_BOOL_TAG   "tag:yaml.org,2002:bool"
     The tag !!bool with the values: true and falce.
    #define YAML_STR_TAG   "tag:yaml.org,2002:str"
     The tag !!str for string values.
    #define YAML_INT_TAG   "tag:yaml.org,2002:int"
     The tag !!int for integer values.
    #define YAML_FLOAT_TAG   "tag:yaml.org,2002:float"
     The tag !!float for float values.
    #define YAML_TIMESTAMP_TAG   "tag:yaml.org,2002:timestamp"
     The tag !!timestamp for date and time values.
    #define YAML_SEQ_TAG   "tag:yaml.org,2002:seq"
     The tag !!seq is used to denote sequences.
    #define YAML_MAP_TAG   "tag:yaml.org,2002:map"
     The tag !!map is used to denote mapping.
    #define YAML_DEFAULT_SCALAR_TAG   YAML_STR_TAG
     The default scalar tag is !!str.
    #define YAML_DEFAULT_SEQUENCE_TAG   YAML_SEQ_TAG
     The default sequence tag is !!seq.
    #define YAML_DEFAULT_MAPPING_TAG   YAML_MAP_TAG
     The default mapping tag is !!map.

    +Typedefs

    typedef enum yaml_node_type_e yaml_node_type_t
     Node types.
    typedef struct yaml_node_s yaml_node_t
     The forward definition of a document node structure.
    typedef int yaml_node_item_t
     An element of a sequence node.
    typedef struct yaml_node_pair_s yaml_node_pair_t
     An element of a mapping node.
    typedef struct yaml_document_s yaml_document_t
     The document structure.

    +Enumerations

    enum  yaml_node_type_e {
    +  YAML_NO_NODE, +
    +  YAML_SCALAR_NODE, +
    +  YAML_SEQUENCE_NODE, +
    +  YAML_MAPPING_NODE +
    + }
     

    Node types.

    + More...

    +Functions

    int yaml_document_initialize (yaml_document_t *document, yaml_version_directive_t *version_directive, yaml_tag_directive_t *tag_directives_start, yaml_tag_directive_t *tag_directives_end, int start_implicit, int end_implicit)
     Create a YAML document.
    void yaml_document_delete (yaml_document_t *document)
     Delete a YAML document and all its nodes.
    yaml_node_tyaml_document_get_node (yaml_document_t *document, int index)
     Get a node of a YAML document.
    yaml_node_tyaml_document_get_root_node (yaml_document_t *document)
     Get the root of a YAML document node.
    int yaml_document_add_scalar (yaml_document_t *document, yaml_char_t *tag, yaml_char_t *value, int length, yaml_scalar_style_t style)
     Create a SCALAR node and attach it to the document.
    int yaml_document_add_sequence (yaml_document_t *document, yaml_char_t *tag, yaml_sequence_style_t style)
     Create a SEQUENCE node and attach it to the document.
    int yaml_document_add_mapping (yaml_document_t *document, yaml_char_t *tag, yaml_mapping_style_t style)
     Create a MAPPING node and attach it to the document.
    int yaml_document_append_sequence_item (yaml_document_t *document, int sequence, int item)
     Add an item to a SEQUENCE node.
    int yaml_document_append_mapping_pair (yaml_document_t *document, int mapping, int key, int value)
     Add a pair of a key and a value to a MAPPING node.
    +

    Define Documentation

    + +
    +
    + + + + +
    #define YAML_NULL_TAG   "tag:yaml.org,2002:null"
    +
    +
    + +

    The tag !!null with the only possible value: null.

    + +
    +
    + +
    +
    + + + + +
    #define YAML_BOOL_TAG   "tag:yaml.org,2002:bool"
    +
    +
    + +

    The tag !!bool with the values: true and falce.

    + +
    +
    + +
    +
    + + + + +
    #define YAML_STR_TAG   "tag:yaml.org,2002:str"
    +
    +
    + +

    The tag !!str for string values.

    + +
    +
    + +
    +
    + + + + +
    #define YAML_INT_TAG   "tag:yaml.org,2002:int"
    +
    +
    + +

    The tag !!int for integer values.

    + +
    +
    + +
    +
    + + + + +
    #define YAML_FLOAT_TAG   "tag:yaml.org,2002:float"
    +
    +
    + +

    The tag !!float for float values.

    + +
    +
    + +
    +
    + + + + +
    #define YAML_TIMESTAMP_TAG   "tag:yaml.org,2002:timestamp"
    +
    +
    + +

    The tag !!timestamp for date and time values.

    + +
    +
    + +
    +
    + + + + +
    #define YAML_SEQ_TAG   "tag:yaml.org,2002:seq"
    +
    +
    + +

    The tag !!seq is used to denote sequences.

    + +
    +
    + +
    +
    + + + + +
    #define YAML_MAP_TAG   "tag:yaml.org,2002:map"
    +
    +
    + +

    The tag !!map is used to denote mapping.

    + +
    +
    + +
    +
    + + + + +
    #define YAML_DEFAULT_SCALAR_TAG   YAML_STR_TAG
    +
    +
    + +

    The default scalar tag is !!str.

    + +
    +
    + +
    +
    + + + + +
    #define YAML_DEFAULT_SEQUENCE_TAG   YAML_SEQ_TAG
    +
    +
    + +

    The default sequence tag is !!seq.

    + +
    +
    + +
    +
    + + + + +
    #define YAML_DEFAULT_MAPPING_TAG   YAML_MAP_TAG
    +
    +
    + +

    The default mapping tag is !!map.

    + +
    +
    +

    Typedef Documentation

    + +
    +
    + + + + +
    typedef enum yaml_node_type_e yaml_node_type_t
    +
    +
    + +

    Node types.

    + +
    +
    + +
    +
    + + + + +
    typedef struct yaml_node_s yaml_node_t
    +
    +
    + +

    The forward definition of a document node structure.

    + +
    +
    + +
    +
    + + + + +
    typedef int yaml_node_item_t
    +
    +
    + +

    An element of a sequence node.

    + +
    +
    + +
    +
    + + + + +
    typedef struct yaml_node_pair_s yaml_node_pair_t
    +
    +
    + +

    An element of a mapping node.

    + +
    +
    + +
    +
    + + + + +
    typedef struct yaml_document_s yaml_document_t
    +
    +
    + +

    The document structure.

    + +
    +
    +

    Enumeration Type Documentation

    + +
    +
    + + + + +
    enum yaml_node_type_e
    +
    +
    + +

    Node types.

    +
    Enumerator:
    + + + + +
    YAML_NO_NODE  +

    An empty node.

    +
    YAML_SCALAR_NODE  +

    A scalar node.

    +
    YAML_SEQUENCE_NODE  +

    A sequence node.

    +
    YAML_MAPPING_NODE  +

    A mapping node.

    +
    +
    +
    + +
    +
    +

    Function Documentation

    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    int yaml_document_initialize (yaml_document_t document,
    yaml_version_directive_t version_directive,
    yaml_tag_directive_t tag_directives_start,
    yaml_tag_directive_t tag_directives_end,
    int  start_implicit,
    int  end_implicit 
    )
    +
    +
    + +

    Create a YAML document.

    +
    Parameters:
    + + + + + + + +
    [out] document An empty document object.
    [in] version_directive The YAML directive value or NULL.
    [in] tag_directives_start The beginning of the TAG directives list.
    [in] tag_directives_end The end of the TAG directives list.
    [in] start_implicit If the document start indicator is implicit.
    [in] end_implicit If the document end indicator is implicit.
    +
    +
    +
    Returns:
    1 if the function succeeded, 0 on error.
    + +
    +
    + +
    +
    + + + + + + + + + +
    void yaml_document_delete (yaml_document_t document ) 
    +
    +
    + +

    Delete a YAML document and all its nodes.

    +
    Parameters:
    + + +
    [in,out] document A document object.
    +
    +
    + +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + +
    yaml_node_t* yaml_document_get_node (yaml_document_t document,
    int  index 
    )
    +
    +
    + +

    Get a node of a YAML document.

    +

    The pointer returned by this function is valid until any of the functions modifying the documents are called.

    +
    Parameters:
    + + + +
    [in] document A document object.
    [in] index The node id.
    +
    +
    +
    Returns:
    the node objct or NULL if node_id is out of range.
    + +
    +
    + +
    +
    + + + + + + + + + +
    yaml_node_t* yaml_document_get_root_node (yaml_document_t document ) 
    +
    +
    + +

    Get the root of a YAML document node.

    +

    The root object is the first object added to the document.

    +

    The pointer returned by this function is valid until any of the functions modifying the documents are called.

    +

    An empty document produced by the parser signifies the end of a YAML stream.

    +
    Parameters:
    + + +
    [in] document A document object.
    +
    +
    +
    Returns:
    the node object or NULL if the document is empty.
    + +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    int yaml_document_add_scalar (yaml_document_t document,
    yaml_char_t tag,
    yaml_char_t value,
    int  length,
    yaml_scalar_style_t  style 
    )
    +
    +
    + +

    Create a SCALAR node and attach it to the document.

    +

    The style argument may be ignored by the emitter.

    +
    Parameters:
    + + + + + + +
    [in,out] document A document object.
    [in] tag The scalar tag.
    [in] value The scalar value.
    [in] length The length of the scalar value.
    [in] style The scalar style.
    +
    +
    +
    Returns:
    the node id or 0 on error.
    + +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    int yaml_document_add_sequence (yaml_document_t document,
    yaml_char_t tag,
    yaml_sequence_style_t  style 
    )
    +
    +
    + +

    Create a SEQUENCE node and attach it to the document.

    +

    The style argument may be ignored by the emitter.

    +
    Parameters:
    + + + + +
    [in,out] document A document object.
    [in] tag The sequence tag.
    [in] style The sequence style.
    +
    +
    +
    Returns:
    the node id or 0 on error.
    + +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    int yaml_document_add_mapping (yaml_document_t document,
    yaml_char_t tag,
    yaml_mapping_style_t  style 
    )
    +
    +
    + +

    Create a MAPPING node and attach it to the document.

    +

    The style argument may be ignored by the emitter.

    +
    Parameters:
    + + + + +
    [in,out] document A document object.
    [in] tag The sequence tag.
    [in] style The sequence style.
    +
    +
    +
    Returns:
    the node id or 0 on error.
    + +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    int yaml_document_append_sequence_item (yaml_document_t document,
    int  sequence,
    int  item 
    )
    +
    +
    + +

    Add an item to a SEQUENCE node.

    +
    Parameters:
    + + + + +
    [in,out] document A document object.
    [in] sequence The sequence node id.
    [in] item The item node id.
    +
    +
    +
    Returns:
    1 if the function succeeded, 0 on error.
    + +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    int yaml_document_append_mapping_pair (yaml_document_t document,
    int  mapping,
    int  key,
    int  value 
    )
    +
    +
    + +

    Add a pair of a key and a value to a MAPPING node.

    +
    Parameters:
    + + + + + +
    [in,out] document A document object.
    [in] mapping The mapping node id.
    [in] key The key node id.
    [in] value The value node id.
    +
    +
    +
    Returns:
    1 if the function succeeded, 0 on error.
    + +
    +
    +
    + + + diff --git a/doc/html/group__parser.html b/doc/html/group__parser.html new file mode 100644 index 00000000000..dfcfa644523 --- /dev/null +++ b/doc/html/group__parser.html @@ -0,0 +1,606 @@ + + + + +yaml: Parser Definitions + + + + + + +
    + +
    +

    Parser Definitions

    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    +Data Structures

    struct  yaml_simple_key_s
     This structure holds information about a potential simple key. More...
    struct  yaml_alias_data_s
     This structure holds aliases data. More...
    struct  yaml_parser_s
     The parser structure. More...

    +Typedefs

    typedef int yaml_read_handler_t (void *data, unsigned char *buffer, size_t size, size_t *size_read)
     The prototype of a read handler.
    +typedef struct yaml_simple_key_s yaml_simple_key_t
     This structure holds information about a potential simple key.
    +typedef enum yaml_parser_state_e yaml_parser_state_t
     The states of the parser.
    +typedef struct yaml_alias_data_s yaml_alias_data_t
     This structure holds aliases data.
    typedef struct yaml_parser_s yaml_parser_t
     The parser structure.

    +Enumerations

    enum  yaml_parser_state_e {
    +  YAML_PARSE_STREAM_START_STATE, +
    +  YAML_PARSE_IMPLICIT_DOCUMENT_START_STATE, +
    +  YAML_PARSE_DOCUMENT_START_STATE, +
    +  YAML_PARSE_DOCUMENT_CONTENT_STATE, +
    +  YAML_PARSE_DOCUMENT_END_STATE, +
    +  YAML_PARSE_BLOCK_NODE_STATE, +
    +  YAML_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE, +
    +  YAML_PARSE_FLOW_NODE_STATE, +
    +  YAML_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE, +
    +  YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE, +
    +  YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE, +
    +  YAML_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE, +
    +  YAML_PARSE_BLOCK_MAPPING_KEY_STATE, +
    +  YAML_PARSE_BLOCK_MAPPING_VALUE_STATE, +
    +  YAML_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE, +
    +  YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE, +
    +  YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE, +
    +  YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE, +
    +  YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE, +
    +  YAML_PARSE_FLOW_MAPPING_FIRST_KEY_STATE, +
    +  YAML_PARSE_FLOW_MAPPING_KEY_STATE, +
    +  YAML_PARSE_FLOW_MAPPING_VALUE_STATE, +
    +  YAML_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE, +
    +  YAML_PARSE_END_STATE +
    + }
     

    The states of the parser.

    + More...

    +Functions

    int yaml_parser_initialize (yaml_parser_t *parser)
     Initialize a parser.
    void yaml_parser_delete (yaml_parser_t *parser)
     Destroy a parser.
    void yaml_parser_set_input_string (yaml_parser_t *parser, const unsigned char *input, size_t size)
     Set a string input.
    void yaml_parser_set_input_file (yaml_parser_t *parser, FILE *file)
     Set a file input.
    void yaml_parser_set_input (yaml_parser_t *parser, yaml_read_handler_t *handler, void *data)
     Set a generic input handler.
    void yaml_parser_set_encoding (yaml_parser_t *parser, yaml_encoding_t encoding)
     Set the source encoding.
    int yaml_parser_scan (yaml_parser_t *parser, yaml_token_t *token)
     Scan the input stream and produce the next token.
    int yaml_parser_parse (yaml_parser_t *parser, yaml_event_t *event)
     Parse the input stream and produce the next parsing event.
    int yaml_parser_load (yaml_parser_t *parser, yaml_document_t *document)
     Parse the input stream and produce the next YAML document.
    +

    Typedef Documentation

    + +
    +
    + + + + +
    typedef int yaml_read_handler_t(void *data, unsigned char *buffer, size_t size, size_t *size_read)
    +
    +
    + +

    The prototype of a read handler.

    +

    The read handler is called when the parser needs to read more bytes from the source. The handler should write not more than size bytes to the buffer. The number of written bytes should be set to the length variable.

    +
    Parameters:
    + + + + + +
    [in,out] data A pointer to an application data specified by yaml_parser_set_input().
    [out] buffer The buffer to write the data from the source.
    [in] size The size of the buffer.
    [out] size_read The actual number of bytes read from the source.
    +
    +
    +
    Returns:
    On success, the handler should return 1. If the handler failed, the returned value should be 0. On EOF, the handler should set the size_read to 0 and return 1.
    + +
    +
    + +
    +
    + + + + +
    typedef struct yaml_parser_s yaml_parser_t
    +
    +
    + +

    The parser structure.

    +

    All members are internal. Manage the structure using the yaml_parser_ family of functions.

    + +
    +
    +

    Enumeration Type Documentation

    + +
    +
    + + + + +
    enum yaml_parser_state_e
    +
    +
    + +

    The states of the parser.

    +
    Enumerator:
    + + + + + + + + + + + + + + + + + + + + + + + + +
    YAML_PARSE_STREAM_START_STATE  +

    Expect STREAM-START.

    +
    YAML_PARSE_IMPLICIT_DOCUMENT_START_STATE  +

    Expect the beginning of an implicit document.

    +
    YAML_PARSE_DOCUMENT_START_STATE  +

    Expect DOCUMENT-START.

    +
    YAML_PARSE_DOCUMENT_CONTENT_STATE  +

    Expect the content of a document.

    +
    YAML_PARSE_DOCUMENT_END_STATE  +

    Expect DOCUMENT-END.

    +
    YAML_PARSE_BLOCK_NODE_STATE  +

    Expect a block node.

    +
    YAML_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE  +

    Expect a block node or indentless sequence.

    +
    YAML_PARSE_FLOW_NODE_STATE  +

    Expect a flow node.

    +
    YAML_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE  +

    Expect the first entry of a block sequence.

    +
    YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE  +

    Expect an entry of a block sequence.

    +
    YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE  +

    Expect an entry of an indentless sequence.

    +
    YAML_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE  +

    Expect the first key of a block mapping.

    +
    YAML_PARSE_BLOCK_MAPPING_KEY_STATE  +

    Expect a block mapping key.

    +
    YAML_PARSE_BLOCK_MAPPING_VALUE_STATE  +

    Expect a block mapping value.

    +
    YAML_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE  +

    Expect the first entry of a flow sequence.

    +
    YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE  +

    Expect an entry of a flow sequence.

    +
    YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE  +

    Expect a key of an ordered mapping.

    +
    YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE  +

    Expect a value of an ordered mapping.

    +
    YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE  +

    Expect the and of an ordered mapping entry.

    +
    YAML_PARSE_FLOW_MAPPING_FIRST_KEY_STATE  +

    Expect the first key of a flow mapping.

    +
    YAML_PARSE_FLOW_MAPPING_KEY_STATE  +

    Expect a key of a flow mapping.

    +
    YAML_PARSE_FLOW_MAPPING_VALUE_STATE  +

    Expect a value of a flow mapping.

    +
    YAML_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE  +

    Expect an empty value of a flow mapping.

    +
    YAML_PARSE_END_STATE  +

    Expect nothing.

    +
    +
    +
    + +
    +
    +

    Function Documentation

    + +
    +
    + + + + + + + + + +
    int yaml_parser_initialize (yaml_parser_t parser ) 
    +
    +
    + +

    Initialize a parser.

    +

    This function creates a new parser object. An application is responsible for destroying the object using the yaml_parser_delete() function.

    +
    Parameters:
    + + +
    [out] parser An empty parser object.
    +
    +
    +
    Returns:
    1 if the function succeeded, 0 on error.
    + +
    +
    + +
    +
    + + + + + + + + + +
    void yaml_parser_delete (yaml_parser_t parser ) 
    +
    +
    + +

    Destroy a parser.

    +
    Parameters:
    + + +
    [in,out] parser A parser object.
    +
    +
    + +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    void yaml_parser_set_input_string (yaml_parser_t parser,
    const unsigned char *  input,
    size_t  size 
    )
    +
    +
    + +

    Set a string input.

    +

    Note that the input pointer must be valid while the parser object exists. The application is responsible for destroing input after destroying the parser.

    +
    Parameters:
    + + + + +
    [in,out] parser A parser object.
    [in] input A source data.
    [in] size The length of the source data in bytes.
    +
    +
    + +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + +
    void yaml_parser_set_input_file (yaml_parser_t parser,
    FILE *  file 
    )
    +
    +
    + +

    Set a file input.

    +

    file should be a file object open for reading. The application is responsible for closing the file.

    +
    Parameters:
    + + + +
    [in,out] parser A parser object.
    [in] file An open file.
    +
    +
    + +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    void yaml_parser_set_input (yaml_parser_t parser,
    yaml_read_handler_t handler,
    void *  data 
    )
    +
    +
    + +

    Set a generic input handler.

    +
    Parameters:
    + + + + +
    [in,out] parser A parser object.
    [in] handler A read handler.
    [in] data Any application data for passing to the read handler.
    +
    +
    + +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + +
    void yaml_parser_set_encoding (yaml_parser_t parser,
    yaml_encoding_t  encoding 
    )
    +
    +
    + +

    Set the source encoding.

    +
    Parameters:
    + + + +
    [in,out] parser A parser object.
    [in] encoding The source encoding.
    +
    +
    + +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + +
    int yaml_parser_scan (yaml_parser_t parser,
    yaml_token_t token 
    )
    +
    +
    + +

    Scan the input stream and produce the next token.

    +

    Call the function subsequently to produce a sequence of tokens corresponding to the input stream. The initial token has the type YAML_STREAM_START_TOKEN while the ending token has the type YAML_STREAM_END_TOKEN.

    +

    An application is responsible for freeing any buffers associated with the produced token object using the yaml_token_delete function.

    +

    An application must not alternate the calls of yaml_parser_scan() with the calls of yaml_parser_parse() or yaml_parser_load(). Doing this will break the parser.

    +
    Parameters:
    + + + +
    [in,out] parser A parser object.
    [out] token An empty token object.
    +
    +
    +
    Returns:
    1 if the function succeeded, 0 on error.
    + +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + +
    int yaml_parser_parse (yaml_parser_t parser,
    yaml_event_t event 
    )
    +
    +
    + +

    Parse the input stream and produce the next parsing event.

    +

    Call the function subsequently to produce a sequence of events corresponding to the input stream. The initial event has the type YAML_STREAM_START_EVENT while the ending event has the type YAML_STREAM_END_EVENT.

    +

    An application is responsible for freeing any buffers associated with the produced event object using the yaml_event_delete() function.

    +

    An application must not alternate the calls of yaml_parser_parse() with the calls of yaml_parser_scan() or yaml_parser_load(). Doing this will break the parser.

    +
    Parameters:
    + + + +
    [in,out] parser A parser object.
    [out] event An empty event object.
    +
    +
    +
    Returns:
    1 if the function succeeded, 0 on error.
    + +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + +
    int yaml_parser_load (yaml_parser_t parser,
    yaml_document_t document 
    )
    +
    +
    + +

    Parse the input stream and produce the next YAML document.

    +

    Call this function subsequently to produce a sequence of documents constituting the input stream.

    +

    If the produced document has no root node, it means that the document end has been reached.

    +

    An application is responsible for freeing any data associated with the produced document object using the yaml_document_delete() function.

    +

    An application must not alternate the calls of yaml_parser_load() with the calls of yaml_parser_scan() or yaml_parser_parse(). Doing this will break the parser.

    +
    Parameters:
    + + + +
    [in,out] parser A parser object.
    [out] document An empty document object.
    +
    +
    +
    Returns:
    1 if the function succeeded, 0 on error.
    + +
    +
    +
    + + + diff --git a/doc/html/group__styles.html b/doc/html/group__styles.html new file mode 100644 index 00000000000..147f85ebad1 --- /dev/null +++ b/doc/html/group__styles.html @@ -0,0 +1,222 @@ + + + + +yaml: Node Styles + + + + + + +
    + +
    +

    Node Styles

    +
    +
    + + + + + + + + + + + + + + + +

    +Typedefs

    typedef enum yaml_scalar_style_e yaml_scalar_style_t
     Scalar styles.
    typedef enum yaml_sequence_style_e yaml_sequence_style_t
     Sequence styles.
    typedef enum yaml_mapping_style_e yaml_mapping_style_t
     Mapping styles.

    +Enumerations

    enum  yaml_scalar_style_e {
    +  YAML_ANY_SCALAR_STYLE, +
    +  YAML_PLAIN_SCALAR_STYLE, +
    +  YAML_SINGLE_QUOTED_SCALAR_STYLE, +
    +  YAML_DOUBLE_QUOTED_SCALAR_STYLE, +
    +  YAML_LITERAL_SCALAR_STYLE, +
    +  YAML_FOLDED_SCALAR_STYLE +
    + }
     

    Scalar styles.

    + More...
    enum  yaml_sequence_style_e {
    +  YAML_ANY_SEQUENCE_STYLE, +
    +  YAML_BLOCK_SEQUENCE_STYLE, +
    +  YAML_FLOW_SEQUENCE_STYLE +
    + }
     

    Sequence styles.

    + More...
    enum  yaml_mapping_style_e {
    +  YAML_ANY_MAPPING_STYLE, +
    +  YAML_BLOCK_MAPPING_STYLE, +
    +  YAML_FLOW_MAPPING_STYLE +
    + }
     

    Mapping styles.

    + More...
    +

    Typedef Documentation

    + +
    +
    + + + + +
    typedef enum yaml_scalar_style_e yaml_scalar_style_t
    +
    +
    + +

    Scalar styles.

    + +
    +
    + +
    + +
    + +

    Sequence styles.

    + +
    +
    + +
    +
    + + + + +
    typedef enum yaml_mapping_style_e yaml_mapping_style_t
    +
    +
    + +

    Mapping styles.

    + +
    +
    +

    Enumeration Type Documentation

    + +
    +
    + + + + +
    enum yaml_scalar_style_e
    +
    +
    + +

    Scalar styles.

    +
    Enumerator:
    + + + + + + +
    YAML_ANY_SCALAR_STYLE  +

    Let the emitter choose the style.

    +
    YAML_PLAIN_SCALAR_STYLE  +

    The plain scalar style.

    +
    YAML_SINGLE_QUOTED_SCALAR_STYLE  +

    The single-quoted scalar style.

    +
    YAML_DOUBLE_QUOTED_SCALAR_STYLE  +

    The double-quoted scalar style.

    +
    YAML_LITERAL_SCALAR_STYLE  +

    The literal scalar style.

    +
    YAML_FOLDED_SCALAR_STYLE  +

    The folded scalar style.

    +
    +
    +
    + +
    +
    + +
    +
    + + + + +
    enum yaml_sequence_style_e
    +
    +
    + +

    Sequence styles.

    +
    Enumerator:
    + + + +
    YAML_ANY_SEQUENCE_STYLE  +

    Let the emitter choose the style.

    +
    YAML_BLOCK_SEQUENCE_STYLE  +

    The block sequence style.

    +
    YAML_FLOW_SEQUENCE_STYLE  +

    The flow sequence style.

    +
    +
    +
    + +
    +
    + +
    +
    + + + + +
    enum yaml_mapping_style_e
    +
    +
    + +

    Mapping styles.

    +
    Enumerator:
    + + + +
    YAML_ANY_MAPPING_STYLE  +

    Let the emitter choose the style.

    +
    YAML_BLOCK_MAPPING_STYLE  +

    The block mapping style.

    +
    YAML_FLOW_MAPPING_STYLE  +

    The flow mapping style.

    +
    +
    +
    + +
    +
    +
    + + + diff --git a/doc/html/group__tokens.html b/doc/html/group__tokens.html new file mode 100644 index 00000000000..5f2b1679d02 --- /dev/null +++ b/doc/html/group__tokens.html @@ -0,0 +1,246 @@ + + + + +yaml: Tokens + + + + + + + +
    + + + + + + + + + + + + + + + +

    +Data Structures

    struct  yaml_token_s
     The token structure. More...

    +Typedefs

    typedef enum yaml_token_type_e yaml_token_type_t
     Token types.
    typedef struct yaml_token_s yaml_token_t
     The token structure.

    +Enumerations

    enum  yaml_token_type_e {
    +  YAML_NO_TOKEN, +
    +  YAML_STREAM_START_TOKEN, +
    +  YAML_STREAM_END_TOKEN, +
    +  YAML_VERSION_DIRECTIVE_TOKEN, +
    +  YAML_TAG_DIRECTIVE_TOKEN, +
    +  YAML_DOCUMENT_START_TOKEN, +
    +  YAML_DOCUMENT_END_TOKEN, +
    +  YAML_BLOCK_SEQUENCE_START_TOKEN, +
    +  YAML_BLOCK_MAPPING_START_TOKEN, +
    +  YAML_BLOCK_END_TOKEN, +
    +  YAML_FLOW_SEQUENCE_START_TOKEN, +
    +  YAML_FLOW_SEQUENCE_END_TOKEN, +
    +  YAML_FLOW_MAPPING_START_TOKEN, +
    +  YAML_FLOW_MAPPING_END_TOKEN, +
    +  YAML_BLOCK_ENTRY_TOKEN, +
    +  YAML_FLOW_ENTRY_TOKEN, +
    +  YAML_KEY_TOKEN, +
    +  YAML_VALUE_TOKEN, +
    +  YAML_ALIAS_TOKEN, +
    +  YAML_ANCHOR_TOKEN, +
    +  YAML_TAG_TOKEN, +
    +  YAML_SCALAR_TOKEN +
    + }
     

    Token types.

    + More...

    +Functions

    void yaml_token_delete (yaml_token_t *token)
     Free any memory allocated for a token object.
    +

    Typedef Documentation

    + +
    +
    + + + + +
    typedef enum yaml_token_type_e yaml_token_type_t
    +
    +
    + +

    Token types.

    + +
    +
    + +
    +
    + + + + +
    typedef struct yaml_token_s yaml_token_t
    +
    +
    + +

    The token structure.

    + +
    +
    +

    Enumeration Type Documentation

    + +
    +
    + + + + +
    enum yaml_token_type_e
    +
    +
    + +

    Token types.

    +
    Enumerator:
    + + + + + + + + + + + + + + + + + + + + + + +
    YAML_NO_TOKEN  +

    An empty token.

    +
    YAML_STREAM_START_TOKEN  +

    A STREAM-START token.

    +
    YAML_STREAM_END_TOKEN  +

    A STREAM-END token.

    +
    YAML_VERSION_DIRECTIVE_TOKEN  +

    A VERSION-DIRECTIVE token.

    +
    YAML_TAG_DIRECTIVE_TOKEN  +

    A TAG-DIRECTIVE token.

    +
    YAML_DOCUMENT_START_TOKEN  +

    A DOCUMENT-START token.

    +
    YAML_DOCUMENT_END_TOKEN  +

    A DOCUMENT-END token.

    +
    YAML_BLOCK_SEQUENCE_START_TOKEN  +

    A BLOCK-SEQUENCE-START token.

    +
    YAML_BLOCK_MAPPING_START_TOKEN  +

    A BLOCK-SEQUENCE-END token.

    +
    YAML_BLOCK_END_TOKEN  +

    A BLOCK-END token.

    +
    YAML_FLOW_SEQUENCE_START_TOKEN  +

    A FLOW-SEQUENCE-START token.

    +
    YAML_FLOW_SEQUENCE_END_TOKEN  +

    A FLOW-SEQUENCE-END token.

    +
    YAML_FLOW_MAPPING_START_TOKEN  +

    A FLOW-MAPPING-START token.

    +
    YAML_FLOW_MAPPING_END_TOKEN  +

    A FLOW-MAPPING-END token.

    +
    YAML_BLOCK_ENTRY_TOKEN  +

    A BLOCK-ENTRY token.

    +
    YAML_FLOW_ENTRY_TOKEN  +

    A FLOW-ENTRY token.

    +
    YAML_KEY_TOKEN  +

    A KEY token.

    +
    YAML_VALUE_TOKEN  +

    A VALUE token.

    +
    YAML_ALIAS_TOKEN  +

    An ALIAS token.

    +
    YAML_ANCHOR_TOKEN  +

    An ANCHOR token.

    +
    YAML_TAG_TOKEN  +

    A TAG token.

    +
    YAML_SCALAR_TOKEN  +

    A SCALAR token.

    +
    +
    +
    + +
    +
    +

    Function Documentation

    + +
    +
    + + + + + + + + + +
    void yaml_token_delete (yaml_token_t token ) 
    +
    +
    + +

    Free any memory allocated for a token object.

    +
    Parameters:
    + + +
    [in,out] token A token object.
    +
    +
    + +
    +
    +
    + + + diff --git a/doc/html/group__version.html b/doc/html/group__version.html new file mode 100644 index 00000000000..9949f3080f6 --- /dev/null +++ b/doc/html/group__version.html @@ -0,0 +1,106 @@ + + + + +yaml: Version Information + + + + + + +
    + +
    +

    Version Information

    +
    +
    + + + + + + +

    +Functions

    const char * yaml_get_version_string (void)
     Get the library version as a string.
    void yaml_get_version (int *major, int *minor, int *patch)
     Get the library version numbers.
    +

    Function Documentation

    + +
    +
    + + + + + + + + + +
    const char* yaml_get_version_string (void  ) 
    +
    +
    + +

    Get the library version as a string.

    +
    Returns:
    The function returns the pointer to a static string of the form "X.Y.Z", where X is the major version number, Y is a minor version number, and Z is the patch version number.
    + +
    +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    void yaml_get_version (int *  major,
    int *  minor,
    int *  patch 
    )
    +
    +
    + +

    Get the library version numbers.

    +
    Parameters:
    + + + + +
    [out] major Major version number.
    [out] minor Minor version number.
    [out] patch Patch version number.
    +
    +
    + +
    +
    +
    + + + diff --git a/doc/html/index.html b/doc/html/index.html new file mode 100644 index 00000000000..b909ab258a6 --- /dev/null +++ b/doc/html/index.html @@ -0,0 +1,31 @@ + + + + +yaml: Main Page + + + + + + +
    +
    +

    yaml Documentation

    +
    +
    +

    0.1.4

    + + + diff --git a/doc/html/modules.html b/doc/html/modules.html new file mode 100644 index 00000000000..6b48536f2d5 --- /dev/null +++ b/doc/html/modules.html @@ -0,0 +1,42 @@ + + + + +yaml: Module Index + + + + + + +
    +
    +

    Modules

    +
    + + + + diff --git a/doc/html/nav_f.png b/doc/html/nav_f.png new file mode 100644 index 0000000000000000000000000000000000000000..1b07a16207e67c95fe2ee17e7016e6d08ac7ac99 GIT binary patch literal 159 zcmeAS@N?(olHy`uVBq!ia0vp^j6iI`!2~2XGqLUlQfZzpjv*C{Z|{2YIT`Y>1X`Eg z-tTbne1`SITM8Q!Pb(<)UFZ(m>wMzvKZQqKM~~GcZ=A7j<~E6K62>ozFS=cD3)mf8 z9WX0+R&m(l9KUsLdTx4?9~({T__KA%`}olPJ^N;y|F^pHgs_K%!rj~{8>RwnWbkzL Kb6Mw<&;$VTdq1fF literal 0 HcmV?d00001 diff --git a/doc/html/nav_h.png b/doc/html/nav_h.png new file mode 100644 index 0000000000000000000000000000000000000000..01f5fa6a596e36bd12c2d6ceff1b0169fda7e699 GIT binary patch literal 97 zcmeAS@N?(olHy`uVBq!ia0vp^j6lr8!2~3AUOE6t1`SUa$B+ufw|6&kG8phMJMJ~w va4>Y+bZ&9QY?(VEUPY_cGd9nQ`um^ZSUyYpAAuKhL7F^W{an^LB{Ts5DmojT literal 0 HcmV?d00001 diff --git a/doc/html/open.png b/doc/html/open.png new file mode 100644 index 0000000000000000000000000000000000000000..7b35d2c2c389743089632fe24c3104f2173d97af GIT binary patch literal 118 zcmeAS@N?(olHy`uVBq!ia0vp^oFL4>1|%O$WD@{Vww^AIAr*{o=Nbw!DDW^(zOibV zl!F8B0?t?i!vld4k#$~0_AX3zElaokn + + + +yaml: yaml_alias_data_s Struct Reference + + + + + + +
    + +
    +

    yaml_alias_data_s Struct Reference
    + +[Parser Definitions] +

    +
    +
    + +

    This structure holds aliases data. +More...

    + +

    #include <yaml.h>

    + + + + + + + + +

    +Data Fields

    yaml_char_tanchor
     The anchor.
    int index
     The node id.
    yaml_mark_t mark
     The anchor mark.
    +

    Detailed Description

    +

    This structure holds aliases data.

    +

    Field Documentation

    + +
    + +
    + +

    The anchor.

    + +
    +
    + +
    +
    + + + + +
    int yaml_alias_data_s::index
    +
    +
    + +

    The node id.

    + +
    +
    + +
    + +
    + +

    The anchor mark.

    + +
    +
    +
    The documentation for this struct was generated from the following file: +
    + + + diff --git a/doc/html/structyaml__document__s.html b/doc/html/structyaml__document__s.html new file mode 100644 index 00000000000..fe2a65f2e8e --- /dev/null +++ b/doc/html/structyaml__document__s.html @@ -0,0 +1,235 @@ + + + + +yaml: yaml_document_s Struct Reference + + + + + + +
    + +
    +

    yaml_document_s Struct Reference
    + +[Nodes] +

    +
    +
    + +

    The document structure. +More...

    + +

    #include <yaml.h>

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    +Data Fields

    struct {
       yaml_node_t *   start
     The beginning of the stack.
       yaml_node_t *   end
     The end of the stack.
       yaml_node_t *   top
     The top of the stack.
    nodes
     The document nodes.
    yaml_version_directive_tversion_directive
     The version directive.
    struct {
       yaml_tag_directive_t *   start
     The beginning of the tag directives list.
       yaml_tag_directive_t *   end
     The end of the tag directives list.
    tag_directives
     The list of tag directives.
    +int start_implicit
     Is the document start indicator implicit?
    +int end_implicit
     Is the document end indicator implicit?
    yaml_mark_t start_mark
     The beginning of the document.
    yaml_mark_t end_mark
     The end of the document.
    +

    Detailed Description

    +

    The document structure.

    +

    Field Documentation

    + +
    + +
    + +

    The beginning of the stack.

    + +
    +
    + +
    + +
    + +

    The end of the stack.

    + +
    +
    + +
    + +
    + +

    The top of the stack.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_document_s::nodes
    +
    +
    + +

    The document nodes.

    + +
    +
    + +
    + +
    + +

    The version directive.

    + +
    +
    + +
    + +
    + +

    The beginning of the tag directives list.

    + +
    +
    + +
    + +
    + +

    The end of the tag directives list.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_document_s::tag_directives
    +
    +
    + +

    The list of tag directives.

    + +
    +
    + +
    + +
    + +

    The beginning of the document.

    + +
    +
    + +
    + +
    + +

    The end of the document.

    + +
    +
    +
    The documentation for this struct was generated from the following file: +
    + + + diff --git a/doc/html/structyaml__emitter__s.html b/doc/html/structyaml__emitter__s.html new file mode 100644 index 00000000000..2e8a0841f70 --- /dev/null +++ b/doc/html/structyaml__emitter__s.html @@ -0,0 +1,1300 @@ + + + + +yaml: yaml_emitter_s Struct Reference + + + + + + +
    +
    +

    yaml_emitter_s Struct Reference
    + +[Emitter Definitions] +

    +
    +
    + +

    The emitter structure. +More...

    + +

    #include <yaml.h>

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    +Data Fields

    unsigned char * buffer
     The buffer pointer.
    size_t size
     The buffer size.
    size_t * size_written
     The number of written bytes.
    struct {
       unsigned char *   buffer
     The buffer pointer.
       size_t   size
     The buffer size.
       size_t *   size_written
     The number of written bytes.
    string
     String output data.
    FILE * file
     File output data.
    yaml_char_tstart
     The beginning of the buffer.
    yaml_char_tend
     The end of the buffer.
    yaml_char_tpointer
     The current position of the buffer.
    yaml_char_tlast
     The last filled position of the buffer.
    unsigned char * start
     The beginning of the buffer.
    unsigned char * end
     The end of the buffer.
    unsigned char * pointer
     The current position of the buffer.
    unsigned char * last
     The last filled position of the buffer.
    yaml_emitter_state_tstart
     The beginning of the stack.
    yaml_emitter_state_tend
     The end of the stack.
    yaml_emitter_state_ttop
     The top of the stack.
    yaml_event_tstart
     The beginning of the event queue.
    yaml_event_tend
     The end of the event queue.
    yaml_event_thead
     The head of the event queue.
    yaml_event_ttail
     The tail of the event queue.
    int * start
     The beginning of the stack.
    int * end
     The end of the stack.
    int * top
     The top of the stack.
    yaml_tag_directive_tstart
     The beginning of the list.
    yaml_tag_directive_tend
     The end of the list.
    yaml_tag_directive_ttop
     The top of the list.
    yaml_char_tanchor
     The anchor value.
    size_t anchor_length
     The anchor length.
    +int alias
     Is it an alias?
    yaml_char_thandle
     The tag handle.
    size_t handle_length
     The tag handle length.
    yaml_char_tsuffix
     The tag suffix.
    size_t suffix_length
     The tag suffix length.
    yaml_char_tvalue
     The scalar value.
    size_t length
     The scalar length.
    +int multiline
     Does the scalar contain line breaks?
    +int flow_plain_allowed
     Can the scalar be expessed in the flow plain style?
    +int block_plain_allowed
     Can the scalar be expressed in the block plain style?
    +int single_quoted_allowed
     Can the scalar be expressed in the single quoted style?
    +int block_allowed
     Can the scalar be expressed in the literal or folded styles?
    yaml_scalar_style_t style
     The output style.
    int references
     The number of references.
    int anchor
     The anchor id.
    +int serialized
     If the node has been emitted?
    Error handling

    +
    yaml_error_type_t error
     Error type.
    const char * problem
     Error description.
    Writer stuff

    +
    yaml_write_handler_twrite_handler
     Write handler.
    void * write_handler_data
     A pointer for passing to the white handler.
    union {
       struct {
          unsigned char *   buffer
     The buffer pointer.
          size_t   size
     The buffer size.
          size_t *   size_written
     The number of written bytes.
       }   string
     String output data.
       FILE *   file
     File output data.
    output
     Standard (string or file) output data.
    struct {
       yaml_char_t *   start
     The beginning of the buffer.
       yaml_char_t *   end
     The end of the buffer.
       yaml_char_t *   pointer
     The current position of the buffer.
       yaml_char_t *   last
     The last filled position of the buffer.
    buffer
     The working buffer.
    struct {
       unsigned char *   start
     The beginning of the buffer.
       unsigned char *   end
     The end of the buffer.
       unsigned char *   pointer
     The current position of the buffer.
       unsigned char *   last
     The last filled position of the buffer.
    raw_buffer
     The raw buffer.
    yaml_encoding_t encoding
     The stream encoding.
    Emitter stuff

    +
    +int canonical
     If the output is in the canonical style?
    int best_indent
     The number of indentation spaces.
    int best_width
     The preferred width of the output lines.
    +int unicode
     Allow unescaped non-ASCII characters?
    yaml_break_t line_break
     The preferred line break.
    struct {
       yaml_emitter_state_t *   start
     The beginning of the stack.
       yaml_emitter_state_t *   end
     The end of the stack.
       yaml_emitter_state_t *   top
     The top of the stack.
    states
     The stack of states.
    yaml_emitter_state_t state
     The current emitter state.
    struct {
       yaml_event_t *   start
     The beginning of the event queue.
       yaml_event_t *   end
     The end of the event queue.
       yaml_event_t *   head
     The head of the event queue.
       yaml_event_t *   tail
     The tail of the event queue.
    events
     The event queue.
    struct {
       int *   start
     The beginning of the stack.
       int *   end
     The end of the stack.
       int *   top
     The top of the stack.
    indents
     The stack of indentation levels.
    struct {
       yaml_tag_directive_t *   start
     The beginning of the list.
       yaml_tag_directive_t *   end
     The end of the list.
       yaml_tag_directive_t *   top
     The top of the list.
    tag_directives
     The list of tag directives.
    int indent
     The current indentation level.
    int flow_level
     The current flow level.
    +int root_context
     Is it the document root context?
    +int sequence_context
     Is it a sequence context?
    +int mapping_context
     Is it a mapping context?
    +int simple_key_context
     Is it a simple mapping key context?
    int line
     The current line.
    int column
     The current column.
    +int whitespace
     If the last character was a whitespace?
    +int indention
     If the last character was an indentation character (' ', '-', '?', ':')?
    +int open_ended
     If an explicit document end is required?
    struct {
       yaml_char_t *   anchor
     The anchor value.
       size_t   anchor_length
     The anchor length.
       int   alias
     Is it an alias?
    anchor_data
     Anchor analysis.
    struct {
       yaml_char_t *   handle
     The tag handle.
       size_t   handle_length
     The tag handle length.
       yaml_char_t *   suffix
     The tag suffix.
       size_t   suffix_length
     The tag suffix length.
    tag_data
     Tag analysis.
    struct {
       yaml_char_t *   value
     The scalar value.
       size_t   length
     The scalar length.
       int   multiline
     Does the scalar contain line breaks?
       int   flow_plain_allowed
     Can the scalar be expessed in the flow plain style?
       int   block_plain_allowed
     Can the scalar be expressed in the block plain style?
       int   single_quoted_allowed
     Can the scalar be expressed in the single quoted style?
       int   block_allowed
     Can the scalar be expressed in the literal or folded styles?
       yaml_scalar_style_t   style
     The output style.
    scalar_data
     Scalar analysis.
    Dumper stuff

    +
    +int opened
     If the stream was already opened?
    +int closed
     If the stream was already closed?
    struct {
       int   references
     The number of references.
       int   anchor
     The anchor id.
       int   serialized
     If the node has been emitted?
    anchors
     The information associated with the document nodes.
    int last_anchor_id
     The last assigned anchor id.
    yaml_document_tdocument
     The currently emitted document.
    +

    Detailed Description

    +

    The emitter structure.

    +

    All members are internal. Manage the structure using the yaml_emitter_ family of functions.

    +

    Field Documentation

    + +
    + +
    + +

    Error type.

    + +
    +
    + +
    +
    + + + + +
    const char* yaml_emitter_s::problem
    +
    +
    + +

    Error description.

    + +
    +
    + +
    + +
    + +

    Write handler.

    + +
    +
    + +
    + +
    + +

    A pointer for passing to the white handler.

    + +
    +
    + +
    +
    + + + + +
    unsigned char* yaml_emitter_s::buffer
    +
    +
    + +

    The buffer pointer.

    + +
    +
    + +
    +
    + + + + +
    size_t yaml_emitter_s::size
    +
    +
    + +

    The buffer size.

    + +
    +
    + +
    +
    + + + + +
    size_t* yaml_emitter_s::size_written
    +
    +
    + +

    The number of written bytes.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_emitter_s::string
    +
    +
    + +

    String output data.

    + +
    +
    + +
    +
    + + + + +
    FILE* yaml_emitter_s::file
    +
    +
    + +

    File output data.

    + +
    +
    + +
    +
    + + + + +
    union { ... } yaml_emitter_s::output
    +
    +
    + +

    Standard (string or file) output data.

    + +
    +
    + +
    + +
    + +

    The beginning of the buffer.

    + +
    +
    + +
    + +
    + +

    The end of the buffer.

    + +
    +
    + +
    + +
    + +

    The current position of the buffer.

    + +
    +
    + +
    + +
    + +

    The last filled position of the buffer.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_emitter_s::buffer
    +
    +
    + +

    The working buffer.

    + +
    +
    + +
    +
    + + + + +
    unsigned char* yaml_emitter_s::start
    +
    +
    + +

    The beginning of the buffer.

    + +
    +
    + +
    +
    + + + + +
    unsigned char* yaml_emitter_s::end
    +
    +
    + +

    The end of the buffer.

    + +
    +
    + +
    +
    + + + + +
    unsigned char* yaml_emitter_s::pointer
    +
    +
    + +

    The current position of the buffer.

    + +
    +
    + +
    +
    + + + + +
    unsigned char* yaml_emitter_s::last
    +
    +
    + +

    The last filled position of the buffer.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_emitter_s::raw_buffer
    +
    +
    + +

    The raw buffer.

    + +
    +
    + +
    + +
    + +

    The stream encoding.

    + +
    +
    + +
    + +
    + +

    The number of indentation spaces.

    + +
    +
    + +
    + +
    + +

    The preferred width of the output lines.

    + +
    +
    + +
    + +
    + +

    The preferred line break.

    + +
    +
    + +
    + +
    + +

    The beginning of the stack.

    + +
    +
    + +
    + +
    + +

    The end of the stack.

    + +
    +
    + +
    + +
    + +

    The top of the stack.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_emitter_s::states
    +
    +
    + +

    The stack of states.

    + +
    +
    + +
    + +
    + +

    The current emitter state.

    + +
    +
    + +
    + +
    + +

    The beginning of the event queue.

    + +
    +
    + +
    + +
    + +

    The end of the event queue.

    + +
    +
    + +
    + +
    + +

    The head of the event queue.

    + +
    +
    + +
    + +
    + +

    The tail of the event queue.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_emitter_s::events
    +
    +
    + +

    The event queue.

    + +
    +
    + +
    +
    + + + + +
    int* yaml_emitter_s::start
    +
    +
    + +

    The beginning of the stack.

    + +
    +
    + +
    +
    + + + + +
    int* yaml_emitter_s::end
    +
    +
    + +

    The end of the stack.

    + +
    +
    + +
    +
    + + + + +
    int* yaml_emitter_s::top
    +
    +
    + +

    The top of the stack.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_emitter_s::indents
    +
    +
    + +

    The stack of indentation levels.

    + +
    +
    + +
    + +
    + +

    The beginning of the list.

    + +
    +
    + +
    + +
    + +

    The end of the list.

    + +
    +
    + +
    + +
    + +

    The top of the list.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_emitter_s::tag_directives
    +
    +
    + +

    The list of tag directives.

    + +
    +
    + +
    +
    + + + + +
    int yaml_emitter_s::indent
    +
    +
    + +

    The current indentation level.

    + +
    +
    + +
    + +
    + +

    The current flow level.

    + +
    +
    + +
    +
    + + + + +
    int yaml_emitter_s::line
    +
    +
    + +

    The current line.

    + +
    +
    + +
    +
    + + + + +
    int yaml_emitter_s::column
    +
    +
    + +

    The current column.

    + +
    +
    + +
    + +
    + +

    The anchor value.

    + +
    +
    + +
    +
    + + + + +
    size_t yaml_emitter_s::anchor_length
    +
    +
    + +

    The anchor length.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_emitter_s::anchor_data
    +
    +
    + +

    Anchor analysis.

    + +
    +
    + +
    + +
    + +

    The tag handle.

    + +
    +
    + +
    +
    + + + + +
    size_t yaml_emitter_s::handle_length
    +
    +
    + +

    The tag handle length.

    + +
    +
    + +
    + +
    + +

    The tag suffix.

    + +
    +
    + +
    +
    + + + + +
    size_t yaml_emitter_s::suffix_length
    +
    +
    + +

    The tag suffix length.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_emitter_s::tag_data
    +
    +
    + +

    Tag analysis.

    + +
    +
    + +
    + +
    + +

    The scalar value.

    + +
    +
    + +
    +
    + + + + +
    size_t yaml_emitter_s::length
    +
    +
    + +

    The scalar length.

    + +
    +
    + +
    + +
    + +

    The output style.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_emitter_s::scalar_data
    +
    +
    + +

    Scalar analysis.

    + +
    +
    + +
    + +
    + +

    The number of references.

    + +
    +
    + +
    +
    + + + + +
    int yaml_emitter_s::anchor
    +
    +
    + +

    The anchor id.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } * yaml_emitter_s::anchors
    +
    +
    + +

    The information associated with the document nodes.

    + +
    +
    + +
    + +
    + +

    The last assigned anchor id.

    + +
    +
    + +
    + +
    + +

    The currently emitted document.

    + +
    +
    +
    The documentation for this struct was generated from the following file: +
    + + + diff --git a/doc/html/structyaml__event__s.html b/doc/html/structyaml__event__s.html new file mode 100644 index 00000000000..5c21fd452a5 --- /dev/null +++ b/doc/html/structyaml__event__s.html @@ -0,0 +1,496 @@ + + + + +yaml: yaml_event_s Struct Reference + + + + + + +
    + +
    +

    yaml_event_s Struct Reference
    + +[Events] +

    +
    +
    + +

    The event structure. +More...

    + +

    #include <yaml.h>

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    +Data Fields

    yaml_event_type_t type
     The event type.
    union {
       struct {
          yaml_encoding_t   encoding
     The document encoding.
       }   stream_start
     The stream parameters (for YAML_STREAM_START_EVENT).
       struct {
          yaml_version_directive_t *   version_directive
     The version directive.
          struct {
             yaml_tag_directive_t *   start
     The beginning of the tag directives list.
             yaml_tag_directive_t *   end
     The end of the tag directives list.
          }   tag_directives
     The list of tag directives.
          int   implicit
     Is the document indicator implicit?
       }   document_start
     The document parameters (for YAML_DOCUMENT_START_EVENT).
       struct {
          int   implicit
     Is the document end indicator implicit?
       }   document_end
     The document end parameters (for YAML_DOCUMENT_END_EVENT).
       struct {
          yaml_char_t *   anchor
     The anchor.
       }   alias
     The alias parameters (for YAML_ALIAS_EVENT).
       struct {
          yaml_char_t *   anchor
     The anchor.
          yaml_char_t *   tag
     The tag.
          yaml_char_t *   value
     The scalar value.
          size_t   length
     The length of the scalar value.
          int   plain_implicit
     Is the tag optional for the plain style?
          int   quoted_implicit
     Is the tag optional for any non-plain style?
          yaml_scalar_style_t   style
     The scalar style.
       }   scalar
     The scalar parameters (for YAML_SCALAR_EVENT).
       struct {
          yaml_char_t *   anchor
     The anchor.
          yaml_char_t *   tag
     The tag.
          int   implicit
     Is the tag optional?
          yaml_sequence_style_t   style
     The sequence style.
       }   sequence_start
     The sequence parameters (for YAML_SEQUENCE_START_EVENT).
       struct {
          yaml_char_t *   anchor
     The anchor.
          yaml_char_t *   tag
     The tag.
          int   implicit
     Is the tag optional?
          yaml_mapping_style_t   style
     The mapping style.
       }   mapping_start
     The mapping parameters (for YAML_MAPPING_START_EVENT).
    data
     The event data.
    yaml_mark_t start_mark
     The beginning of the event.
    yaml_mark_t end_mark
     The end of the event.
    +

    Detailed Description

    +

    The event structure.

    +

    Field Documentation

    + +
    + +
    + +

    The event type.

    + +
    +
    + +
    + +
    + +

    The document encoding.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_event_s::stream_start
    +
    +
    + +

    The stream parameters (for YAML_STREAM_START_EVENT).

    + +
    +
    + +
    + +
    + +

    The version directive.

    + +
    +
    + +
    + +
    + +

    The beginning of the tag directives list.

    + +
    +
    + +
    + +
    + +

    The end of the tag directives list.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } ::@16 yaml_event_s::tag_directives
    +
    +
    + +

    The list of tag directives.

    + +
    +
    + +
    +
    + + + + +
    int yaml_event_s::implicit
    +
    +
    + +

    Is the document indicator implicit?

    +

    Is the tag optional?

    +

    Is the document end indicator implicit?

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_event_s::document_start
    +
    +
    + +

    The document parameters (for YAML_DOCUMENT_START_EVENT).

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_event_s::document_end
    +
    +
    + +

    The document end parameters (for YAML_DOCUMENT_END_EVENT).

    + +
    +
    + +
    + +
    + +

    The anchor.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_event_s::alias
    +
    +
    + +

    The alias parameters (for YAML_ALIAS_EVENT).

    + +
    +
    + +
    + +
    + +

    The tag.

    + +
    +
    + +
    + +
    + +

    The scalar value.

    + +
    +
    + +
    +
    + + + + +
    size_t yaml_event_s::length
    +
    +
    + +

    The length of the scalar value.

    + +
    +
    + +
    + +
    + +

    The scalar style.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_event_s::scalar
    +
    +
    + +

    The scalar parameters (for YAML_SCALAR_EVENT).

    + +
    +
    + +
    + +
    + +

    The sequence style.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_event_s::sequence_start
    +
    +
    + +

    The sequence parameters (for YAML_SEQUENCE_START_EVENT).

    + +
    +
    + +
    + +
    + +

    The mapping style.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_event_s::mapping_start
    +
    +
    + +

    The mapping parameters (for YAML_MAPPING_START_EVENT).

    + +
    +
    + +
    +
    + + + + +
    union { ... } yaml_event_s::data
    +
    +
    + +

    The event data.

    + +
    +
    + +
    + +
    + +

    The beginning of the event.

    + +
    +
    + +
    + +
    + +

    The end of the event.

    + +
    +
    +
    The documentation for this struct was generated from the following file: +
    + + + diff --git a/doc/html/structyaml__mark__s.html b/doc/html/structyaml__mark__s.html new file mode 100644 index 00000000000..e5f47ab0784 --- /dev/null +++ b/doc/html/structyaml__mark__s.html @@ -0,0 +1,108 @@ + + + + +yaml: yaml_mark_s Struct Reference + + + + + + +
    + +
    +

    yaml_mark_s Struct Reference
    + +[Basic Types] +

    +
    +
    + +

    The pointer position. +More...

    + +

    #include <yaml.h>

    + + + + + + + + +

    +Data Fields

    size_t index
     The position index.
    size_t line
     The position line.
    size_t column
     The position column.
    +

    Detailed Description

    +

    The pointer position.

    +

    Field Documentation

    + +
    +
    + + + + +
    size_t yaml_mark_s::index
    +
    +
    + +

    The position index.

    + +
    +
    + +
    +
    + + + + +
    size_t yaml_mark_s::line
    +
    +
    + +

    The position line.

    + +
    +
    + +
    +
    + + + + +
    size_t yaml_mark_s::column
    +
    +
    + +

    The position column.

    + +
    +
    +
    The documentation for this struct was generated from the following file: +
    + + + diff --git a/doc/html/structyaml__node__pair__s.html b/doc/html/structyaml__node__pair__s.html new file mode 100644 index 00000000000..3e00076711c --- /dev/null +++ b/doc/html/structyaml__node__pair__s.html @@ -0,0 +1,91 @@ + + + + +yaml: yaml_node_pair_s Struct Reference + + + + + + +
    + +
    +

    yaml_node_pair_s Struct Reference
    + +[Nodes] +

    +
    +
    + +

    An element of a mapping node. +More...

    + +

    #include <yaml.h>

    + + + + + + +

    +Data Fields

    int key
     The key of the element.
    int value
     The value of the element.
    +

    Detailed Description

    +

    An element of a mapping node.

    +

    Field Documentation

    + +
    +
    + + + + +
    int yaml_node_pair_s::key
    +
    +
    + +

    The key of the element.

    + +
    +
    + +
    +
    + + + + +
    int yaml_node_pair_s::value
    +
    +
    + +

    The value of the element.

    + +
    +
    +
    The documentation for this struct was generated from the following file: +
    + + + diff --git a/doc/html/structyaml__node__s.html b/doc/html/structyaml__node__s.html new file mode 100644 index 00000000000..46029b7ae03 --- /dev/null +++ b/doc/html/structyaml__node__s.html @@ -0,0 +1,420 @@ + + + + +yaml: yaml_node_s Struct Reference + + + + + + +
    + +
    +

    yaml_node_s Struct Reference
    + +[Nodes] +

    +
    +
    + +

    The node structure. +More...

    + +

    #include <yaml.h>

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    +Data Fields

    yaml_node_type_t type
     The node type.
    yaml_char_ttag
     The node tag.
    union {
       struct {
          yaml_char_t *   value
     The scalar value.
          size_t   length
     The length of the scalar value.
          yaml_scalar_style_t   style
     The scalar style.
       }   scalar
     The scalar parameters (for YAML_SCALAR_NODE).
       struct {
          struct {
             yaml_node_item_t *   start
     The beginning of the stack.
             yaml_node_item_t *   end
     The end of the stack.
             yaml_node_item_t *   top
     The top of the stack.
          }   items
     The stack of sequence items.
          yaml_sequence_style_t   style
     The sequence style.
       }   sequence
     The sequence parameters (for YAML_SEQUENCE_NODE).
       struct {
          struct {
             yaml_node_pair_t *   start
     The beginning of the stack.
             yaml_node_pair_t *   end
     The end of the stack.
             yaml_node_pair_t *   top
     The top of the stack.
          }   pairs
     The stack of mapping pairs (key, value).
          yaml_mapping_style_t   style
     The mapping style.
       }   mapping
     The mapping parameters (for YAML_MAPPING_NODE).
    data
     The node data.
    yaml_mark_t start_mark
     The beginning of the node.
    yaml_mark_t end_mark
     The end of the node.
    +

    Detailed Description

    +

    The node structure.

    +

    Field Documentation

    + +
    + +
    + +

    The node type.

    + +
    +
    + +
    + +
    + +

    The node tag.

    + +
    +
    + +
    + +
    + +

    The scalar value.

    + +
    +
    + +
    +
    + + + + +
    size_t yaml_node_s::length
    +
    +
    + +

    The length of the scalar value.

    + +
    +
    + +
    + +
    + +

    The scalar style.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_node_s::scalar
    +
    +
    + +

    The scalar parameters (for YAML_SCALAR_NODE).

    + +
    +
    + +
    + +
    + +

    The beginning of the stack.

    + +
    +
    + +
    + +
    + +

    The end of the stack.

    + +
    +
    + +
    + +
    + +

    The top of the stack.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } ::@21 yaml_node_s::items
    +
    +
    + +

    The stack of sequence items.

    + +
    +
    + +
    + +
    + +

    The sequence style.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_node_s::sequence
    +
    +
    + +

    The sequence parameters (for YAML_SEQUENCE_NODE).

    + +
    +
    + +
    + +
    + +

    The beginning of the stack.

    + +
    +
    + +
    + +
    + +

    The end of the stack.

    + +
    +
    + +
    + +
    + +

    The top of the stack.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } ::@22 yaml_node_s::pairs
    +
    +
    + +

    The stack of mapping pairs (key, value).

    + +
    +
    + +
    + +
    + +

    The mapping style.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_node_s::mapping
    +
    +
    + +

    The mapping parameters (for YAML_MAPPING_NODE).

    + +
    +
    + +
    +
    + + + + +
    union { ... } yaml_node_s::data
    +
    +
    + +

    The node data.

    + +
    +
    + +
    + +
    + +

    The beginning of the node.

    + +
    +
    + +
    + +
    + +

    The end of the node.

    + +
    +
    +
    The documentation for this struct was generated from the following file: +
    + + + diff --git a/doc/html/structyaml__parser__s.html b/doc/html/structyaml__parser__s.html new file mode 100644 index 00000000000..5402cb2334e --- /dev/null +++ b/doc/html/structyaml__parser__s.html @@ -0,0 +1,1229 @@ + + + + +yaml: yaml_parser_s Struct Reference + + + + + + +
    +
    +

    yaml_parser_s Struct Reference
    + +[Parser Definitions] +

    +
    +
    + +

    The parser structure. +More...

    + +

    #include <yaml.h>

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    +Data Fields

    const unsigned char * start
     The string start pointer.
    const unsigned char * end
     The string end pointer.
    const unsigned char * current
     The string current position.
    struct {
       const unsigned char *   start
     The string start pointer.
       const unsigned char *   end
     The string end pointer.
       const unsigned char *   current
     The string current position.
    string
     String input data.
    FILE * file
     File input data.
    yaml_char_tstart
     The beginning of the buffer.
    yaml_char_tend
     The end of the buffer.
    yaml_char_tpointer
     The current position of the buffer.
    yaml_char_tlast
     The last filled position of the buffer.
    unsigned char * start
     The beginning of the buffer.
    unsigned char * end
     The end of the buffer.
    unsigned char * pointer
     The current position of the buffer.
    unsigned char * last
     The last filled position of the buffer.
    yaml_token_tstart
     The beginning of the tokens queue.
    yaml_token_tend
     The end of the tokens queue.
    yaml_token_thead
     The head of the tokens queue.
    yaml_token_ttail
     The tail of the tokens queue.
    int * start
     The beginning of the stack.
    int * end
     The end of the stack.
    int * top
     The top of the stack.
    yaml_simple_key_tstart
     The beginning of the stack.
    yaml_simple_key_tend
     The end of the stack.
    yaml_simple_key_ttop
     The top of the stack.
    yaml_parser_state_tstart
     The beginning of the stack.
    yaml_parser_state_tend
     The end of the stack.
    yaml_parser_state_ttop
     The top of the stack.
    yaml_mark_tstart
     The beginning of the stack.
    yaml_mark_tend
     The end of the stack.
    yaml_mark_ttop
     The top of the stack.
    yaml_tag_directive_tstart
     The beginning of the list.
    yaml_tag_directive_tend
     The end of the list.
    yaml_tag_directive_ttop
     The top of the list.
    yaml_alias_data_tstart
     The beginning of the list.
    yaml_alias_data_tend
     The end of the list.
    yaml_alias_data_ttop
     The top of the list.
    Error handling

    +
    yaml_error_type_t error
     Error type.
    const char * problem
     Error description.
    size_t problem_offset
     The byte about which the problem occured.
    int problem_value
     The problematic value (-1 is none).
    yaml_mark_t problem_mark
     The problem position.
    const char * context
     The error context.
    yaml_mark_t context_mark
     The context position.
    Reader stuff

    +
    yaml_read_handler_tread_handler
     Read handler.
    void * read_handler_data
     A pointer for passing to the read handler.
    union {
       struct {
          const unsigned char *   start
     The string start pointer.
          const unsigned char *   end
     The string end pointer.
          const unsigned char *   current
     The string current position.
       }   string
     String input data.
       FILE *   file
     File input data.
    input
     Standard (string or file) input data.
    +int eof
     EOF flag.
    struct {
       yaml_char_t *   start
     The beginning of the buffer.
       yaml_char_t *   end
     The end of the buffer.
       yaml_char_t *   pointer
     The current position of the buffer.
       yaml_char_t *   last
     The last filled position of the buffer.
    buffer
     The working buffer.
    +size_t unread
    struct {
       unsigned char *   start
     The beginning of the buffer.
       unsigned char *   end
     The end of the buffer.
       unsigned char *   pointer
     The current position of the buffer.
       unsigned char *   last
     The last filled position of the buffer.
    raw_buffer
     The raw buffer.
    yaml_encoding_t encoding
     The input encoding.
    size_t offset
     The offset of the current position (in bytes).
    yaml_mark_t mark
     The mark of the current position.
    Scanner stuff

    +
    +int stream_start_produced
     Have we started to scan the input stream?
    +int stream_end_produced
     Have we reached the end of the input stream?
    int flow_level
     The number of unclosed '[' and '{' indicators.
    struct {
       yaml_token_t *   start
     The beginning of the tokens queue.
       yaml_token_t *   end
     The end of the tokens queue.
       yaml_token_t *   head
     The head of the tokens queue.
       yaml_token_t *   tail
     The tail of the tokens queue.
    tokens
     The tokens queue.
    size_t tokens_parsed
     The number of tokens fetched from the queue.
    +int token_available
    struct {
       int *   start
     The beginning of the stack.
       int *   end
     The end of the stack.
       int *   top
     The top of the stack.
    indents
     The indentation levels stack.
    int indent
     The current indentation level.
    +int simple_key_allowed
     May a simple key occur at the current position?
    struct {
       yaml_simple_key_t *   start
     The beginning of the stack.
       yaml_simple_key_t *   end
     The end of the stack.
       yaml_simple_key_t *   top
     The top of the stack.
    simple_keys
     The stack of simple keys.
    Parser stuff

    +
    struct {
       yaml_parser_state_t *   start
     The beginning of the stack.
       yaml_parser_state_t *   end
     The end of the stack.
       yaml_parser_state_t *   top
     The top of the stack.
    states
     The parser states stack.
    yaml_parser_state_t state
     The current parser state.
    struct {
       yaml_mark_t *   start
     The beginning of the stack.
       yaml_mark_t *   end
     The end of the stack.
       yaml_mark_t *   top
     The top of the stack.
    marks
     The stack of marks.
    struct {
       yaml_tag_directive_t *   start
     The beginning of the list.
       yaml_tag_directive_t *   end
     The end of the list.
       yaml_tag_directive_t *   top
     The top of the list.
    tag_directives
     The list of TAG directives.
    Dumper stuff

    +
    struct {
       yaml_alias_data_t *   start
     The beginning of the list.
       yaml_alias_data_t *   end
     The end of the list.
       yaml_alias_data_t *   top
     The top of the list.
    aliases
     The alias data.
    yaml_document_tdocument
     The currently parsed document.
    +

    Detailed Description

    +

    The parser structure.

    +

    All members are internal. Manage the structure using the yaml_parser_ family of functions.

    +

    Field Documentation

    + +
    + +
    + +

    Error type.

    + +
    +
    + +
    +
    + + + + +
    const char* yaml_parser_s::problem
    +
    +
    + +

    Error description.

    + +
    +
    + +
    +
    + + + + +
    size_t yaml_parser_s::problem_offset
    +
    +
    + +

    The byte about which the problem occured.

    + +
    +
    + +
    + +
    + +

    The problematic value (-1 is none).

    + +
    +
    + +
    + +
    + +

    The problem position.

    + +
    +
    + +
    +
    + + + + +
    const char* yaml_parser_s::context
    +
    +
    + +

    The error context.

    + +
    +
    + +
    + +
    + +

    The context position.

    + +
    +
    + +
    + +
    + +

    Read handler.

    + +
    +
    + +
    + +
    + +

    A pointer for passing to the read handler.

    + +
    +
    + +
    +
    + + + + +
    const unsigned char* yaml_parser_s::start
    +
    +
    + +

    The string start pointer.

    + +
    +
    + +
    +
    + + + + +
    const unsigned char* yaml_parser_s::end
    +
    +
    + +

    The string end pointer.

    + +
    +
    + +
    +
    + + + + +
    const unsigned char* yaml_parser_s::current
    +
    +
    + +

    The string current position.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_parser_s::string
    +
    +
    + +

    String input data.

    + +
    +
    + +
    +
    + + + + +
    FILE* yaml_parser_s::file
    +
    +
    + +

    File input data.

    + +
    +
    + +
    +
    + + + + +
    union { ... } yaml_parser_s::input
    +
    +
    + +

    Standard (string or file) input data.

    + +
    +
    + +
    + +
    + +

    The beginning of the buffer.

    + +
    +
    + +
    + +
    + +

    The end of the buffer.

    + +
    +
    + +
    + +
    + +

    The current position of the buffer.

    + +
    +
    + +
    + +
    + +

    The last filled position of the buffer.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_parser_s::buffer
    +
    +
    + +

    The working buffer.

    + +
    +
    + +
    +
    + + + + +
    unsigned char* yaml_parser_s::start
    +
    +
    + +

    The beginning of the buffer.

    + +
    +
    + +
    +
    + + + + +
    unsigned char* yaml_parser_s::end
    +
    +
    + +

    The end of the buffer.

    + +
    +
    + +
    +
    + + + + +
    unsigned char* yaml_parser_s::pointer
    +
    +
    + +

    The current position of the buffer.

    + +
    +
    + +
    +
    + + + + +
    unsigned char* yaml_parser_s::last
    +
    +
    + +

    The last filled position of the buffer.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_parser_s::raw_buffer
    +
    +
    + +

    The raw buffer.

    + +
    +
    + +
    + +
    + +

    The input encoding.

    + +
    +
    + +
    +
    + + + + +
    size_t yaml_parser_s::offset
    +
    +
    + +

    The offset of the current position (in bytes).

    + +
    +
    + +
    + +
    + +

    The mark of the current position.

    + +
    +
    + +
    +
    + + + + +
    int yaml_parser_s::flow_level
    +
    +
    + +

    The number of unclosed '[' and '{' indicators.

    + +
    +
    + +
    + +
    + +

    The beginning of the tokens queue.

    + +
    +
    + +
    + +
    + +

    The end of the tokens queue.

    + +
    +
    + +
    + +
    + +

    The head of the tokens queue.

    + +
    +
    + +
    + +
    + +

    The tail of the tokens queue.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_parser_s::tokens
    +
    +
    + +

    The tokens queue.

    + +
    +
    + +
    +
    + + + + +
    size_t yaml_parser_s::tokens_parsed
    +
    +
    + +

    The number of tokens fetched from the queue.

    + +
    +
    + +
    +
    + + + + +
    int* yaml_parser_s::start
    +
    +
    + +

    The beginning of the stack.

    + +
    +
    + +
    +
    + + + + +
    int* yaml_parser_s::end
    +
    +
    + +

    The end of the stack.

    + +
    +
    + +
    +
    + + + + +
    int* yaml_parser_s::top
    +
    +
    + +

    The top of the stack.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_parser_s::indents
    +
    +
    + +

    The indentation levels stack.

    + +
    +
    + +
    +
    + + + + +
    int yaml_parser_s::indent
    +
    +
    + +

    The current indentation level.

    + +
    +
    + +
    + +
    + +

    The beginning of the stack.

    + +
    +
    + +
    + +
    + +

    The end of the stack.

    + +
    +
    + +
    + +
    + +

    The top of the stack.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_parser_s::simple_keys
    +
    +
    + +

    The stack of simple keys.

    + +
    +
    + +
    + +
    + +

    The beginning of the stack.

    + +
    +
    + +
    + +
    + +

    The end of the stack.

    + +
    +
    + +
    + +
    + +

    The top of the stack.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_parser_s::states
    +
    +
    + +

    The parser states stack.

    + +
    +
    + +
    + +
    + +

    The current parser state.

    + +
    +
    + +
    + +
    + +

    The beginning of the stack.

    + +
    +
    + +
    + +
    + +

    The end of the stack.

    + +
    +
    + +
    + +
    + +

    The top of the stack.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_parser_s::marks
    +
    +
    + +

    The stack of marks.

    + +
    +
    + +
    + +
    + +

    The beginning of the list.

    + +
    +
    + +
    + +
    + +

    The end of the list.

    + +
    +
    + +
    + +
    + +

    The top of the list.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_parser_s::tag_directives
    +
    +
    + +

    The list of TAG directives.

    + +
    +
    + +
    + +
    + +

    The beginning of the list.

    + +
    +
    + +
    + +
    + +

    The end of the list.

    + +
    +
    + +
    + +
    + +

    The top of the list.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_parser_s::aliases
    +
    +
    + +

    The alias data.

    + +
    +
    + +
    + +
    + +

    The currently parsed document.

    + +
    +
    +
    The documentation for this struct was generated from the following file: +
    + + + diff --git a/doc/html/structyaml__simple__key__s.html b/doc/html/structyaml__simple__key__s.html new file mode 100644 index 00000000000..d6e2e7a2de7 --- /dev/null +++ b/doc/html/structyaml__simple__key__s.html @@ -0,0 +1,97 @@ + + + + +yaml: yaml_simple_key_s Struct Reference + + + + + + +
    + +
    +

    yaml_simple_key_s Struct Reference
    + +[Parser Definitions] +

    +
    +
    + +

    This structure holds information about a potential simple key. +More...

    + +

    #include <yaml.h>

    + + + + + + + + + + +

    +Data Fields

    +int possible
     Is a simple key possible?
    +int required
     Is a simple key required?
    size_t token_number
     The number of the token.
    yaml_mark_t mark
     The position mark.
    +

    Detailed Description

    +

    This structure holds information about a potential simple key.

    +

    Field Documentation

    + +
    + +
    + +

    The number of the token.

    + +
    +
    + +
    + +
    + +

    The position mark.

    + +
    +
    +
    The documentation for this struct was generated from the following file: +
    + + + diff --git a/doc/html/structyaml__tag__directive__s.html b/doc/html/structyaml__tag__directive__s.html new file mode 100644 index 00000000000..3d75caeb833 --- /dev/null +++ b/doc/html/structyaml__tag__directive__s.html @@ -0,0 +1,91 @@ + + + + +yaml: yaml_tag_directive_s Struct Reference + + + + + + +
    + +
    +

    yaml_tag_directive_s Struct Reference
    + +[Basic Types] +

    +
    +
    + +

    The tag directive data. +More...

    + +

    #include <yaml.h>

    + + + + + + +

    +Data Fields

    yaml_char_thandle
     The tag handle.
    yaml_char_tprefix
     The tag prefix.
    +

    Detailed Description

    +

    The tag directive data.

    +

    Field Documentation

    + +
    + +
    + +

    The tag handle.

    + +
    +
    + +
    + +
    + +

    The tag prefix.

    + +
    +
    +
    The documentation for this struct was generated from the following file: +
    + + + diff --git a/doc/html/structyaml__token__s.html b/doc/html/structyaml__token__s.html new file mode 100644 index 00000000000..95326d43e0c --- /dev/null +++ b/doc/html/structyaml__token__s.html @@ -0,0 +1,413 @@ + + + + +yaml: yaml_token_s Struct Reference + + + + + + +
    + +
    +

    yaml_token_s Struct Reference
    + +[Tokens] +

    +
    +
    + +

    The token structure. +More...

    + +

    #include <yaml.h>

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    +Data Fields

    yaml_token_type_t type
     The token type.
    union {
       struct {
          yaml_encoding_t   encoding
     The stream encoding.
       }   stream_start
     The stream start (for YAML_STREAM_START_TOKEN).
       struct {
          yaml_char_t *   value
     The alias value.
       }   alias
     The alias (for YAML_ALIAS_TOKEN).
       struct {
          yaml_char_t *   value
     The anchor value.
       }   anchor
     The anchor (for YAML_ANCHOR_TOKEN).
       struct {
          yaml_char_t *   handle
     The tag handle.
          yaml_char_t *   suffix
     The tag suffix.
       }   tag
     The tag (for YAML_TAG_TOKEN).
       struct {
          yaml_char_t *   value
     The scalar value.
          size_t   length
     The length of the scalar value.
          yaml_scalar_style_t   style
     The scalar style.
       }   scalar
     The scalar value (for YAML_SCALAR_TOKEN).
       struct {
          int   major
     The major version number.
          int   minor
     The minor version number.
       }   version_directive
     The version directive (for YAML_VERSION_DIRECTIVE_TOKEN).
       struct {
          yaml_char_t *   handle
     The tag handle.
          yaml_char_t *   prefix
     The tag prefix.
       }   tag_directive
     The tag directive (for YAML_TAG_DIRECTIVE_TOKEN).
    data
     The token data.
    yaml_mark_t start_mark
     The beginning of the token.
    yaml_mark_t end_mark
     The end of the token.
    +

    Detailed Description

    +

    The token structure.

    +

    Field Documentation

    + +
    + +
    + +

    The token type.

    + +
    +
    + +
    + +
    + +

    The stream encoding.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_token_s::stream_start
    +
    +
    + +

    The stream start (for YAML_STREAM_START_TOKEN).

    + +
    +
    + +
    + +
    + +

    The alias value.

    +

    The scalar value.

    +

    The anchor value.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_token_s::alias
    +
    +
    + +

    The alias (for YAML_ALIAS_TOKEN).

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_token_s::anchor
    +
    +
    + +

    The anchor (for YAML_ANCHOR_TOKEN).

    + +
    +
    + +
    + +
    + +

    The tag handle.

    + +
    +
    + +
    + +
    + +

    The tag suffix.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_token_s::tag
    +
    +
    + +

    The tag (for YAML_TAG_TOKEN).

    + +
    +
    + +
    +
    + + + + +
    size_t yaml_token_s::length
    +
    +
    + +

    The length of the scalar value.

    + +
    +
    + +
    + +
    + +

    The scalar style.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_token_s::scalar
    +
    +
    + +

    The scalar value (for YAML_SCALAR_TOKEN).

    + +
    +
    + +
    +
    + + + + +
    int yaml_token_s::major
    +
    +
    + +

    The major version number.

    + +
    +
    + +
    +
    + + + + +
    int yaml_token_s::minor
    +
    +
    + +

    The minor version number.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_token_s::version_directive
    +
    +
    + +

    The version directive (for YAML_VERSION_DIRECTIVE_TOKEN).

    + +
    +
    + +
    + +
    + +

    The tag prefix.

    + +
    +
    + +
    +
    + + + + +
    struct { ... } yaml_token_s::tag_directive
    +
    +
    + +

    The tag directive (for YAML_TAG_DIRECTIVE_TOKEN).

    + +
    +
    + +
    +
    + + + + +
    union { ... } yaml_token_s::data
    +
    +
    + +

    The token data.

    + +
    +
    + +
    + +
    + +

    The beginning of the token.

    + +
    +
    + +
    + +
    + +

    The end of the token.

    + +
    +
    +
    The documentation for this struct was generated from the following file: +
    + + + diff --git a/doc/html/structyaml__version__directive__s.html b/doc/html/structyaml__version__directive__s.html new file mode 100644 index 00000000000..e689223273d --- /dev/null +++ b/doc/html/structyaml__version__directive__s.html @@ -0,0 +1,91 @@ + + + + +yaml: yaml_version_directive_s Struct Reference + + + + + + +
    + +
    +

    yaml_version_directive_s Struct Reference
    + +[Basic Types] +

    +
    +
    + +

    The version directive data. +More...

    + +

    #include <yaml.h>

    + + + + + + +

    +Data Fields

    int major
     The major version number.
    int minor
     The minor version number.
    +

    Detailed Description

    +

    The version directive data.

    +

    Field Documentation

    + +
    + +
    + +

    The major version number.

    + +
    +
    + +
    + +
    + +

    The minor version number.

    + +
    +
    +
    The documentation for this struct was generated from the following file: +
    + + + diff --git a/doc/html/tab_a.png b/doc/html/tab_a.png new file mode 100644 index 0000000000000000000000000000000000000000..2d99ef23fed78c7683f0b5aa803d937060d288c4 GIT binary patch literal 140 zcmeAS@N?(olHy`uVBq!ia0vp^j6kfy!2~3aiye;!Qo)`sjv*C{Z|CmjY;X`^DSv)) z;hc^cTF;t%XWXdwWP5+kt?jQ5uhqKtjd^EY`^^-S;M%tFAj_l)EwVTK)E@1LSD0{e q?a6($SGQTzz1#QBzr0NMKf^0WCX-0bi?u-G89ZJ6T-G@yGywp8?ljB* literal 0 HcmV?d00001 diff --git a/doc/html/tab_b.png b/doc/html/tab_b.png new file mode 100644 index 0000000000000000000000000000000000000000..b2c3d2be3c7e518fbca6bb30f571882e72fc506d GIT binary patch literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^j6kfy!2~3aiye;!Qk9-Ajv*C{Z|~mbJ)|JfaM8Xd zIP7xAmLwau9@iXhZTrl-TjWj9jM#?{xt`6uU{<)jb9Suc^QnbhJ(o{ib8=j9u0_mE8M7kgF7f<7W7IEf=8(L_qx|g0H;V7iPxm&Q@G7p8W2Kx&iT|YUM=ITC zY<0Qbr;u&AtXD{o@41wH=7&d8=2Z_{M9Tsa=g*t*@A3H$UOlxZk7?f6RUWpx>Fc_L s#LQ{edY3MpIXkMeV^&YV=9fR%8Jv|Kya=#u06K}m)78&qol`;+0RKEt)&Kwi literal 0 HcmV?d00001 diff --git a/doc/html/tab_s.png b/doc/html/tab_s.png new file mode 100644 index 0000000000000000000000000000000000000000..978943ac807718de0e69e5a585a8f0a1e5999285 GIT binary patch literal 189 zcmeAS@N?(olHy`uVBq!ia0vp^j6kfy!2~3aiye;!QZ1e?jv*C{Z|}b5Yzkm-c<7z3 zq^cq0=~}Z;b(!Zvb5Z%sTRFKGlz1=qOFg;myyu?$r`wZb^irPsN1a)6)TwB0r+)wb zPL25;=adu89?fTK`qDR>$D*)b_WOmdKI;Vst02j(hg8%>k literal 0 HcmV?d00001 diff --git a/doc/html/tabs.css b/doc/html/tabs.css new file mode 100644 index 00000000000..21920562a83 --- /dev/null +++ b/doc/html/tabs.css @@ -0,0 +1,59 @@ +.tabs, .tabs2, .tabs3 { + background-image: url('tab_b.png'); + width: 100%; + z-index: 101; + font-size: 13px; +} + +.tabs2 { + font-size: 10px; +} +.tabs3 { + font-size: 9px; +} + +.tablist { + margin: 0; + padding: 0; + display: table; +} + +.tablist li { + float: left; + display: table-cell; + background-image: url('tab_b.png'); + line-height: 36px; + list-style: none; +} + +.tablist a { + display: block; + padding: 0 20px; + font-weight: bold; + background-image:url('tab_s.png'); + background-repeat:no-repeat; + background-position:right; + color: #283A5D; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + text-decoration: none; + outline: none; +} + +.tabs3 .tablist a { + padding: 0 10px; +} + +.tablist a:hover { + background-image: url('tab_h.png'); + background-repeat:repeat-x; + color: #fff; + text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); + text-decoration: none; +} + +.tablist li.current a { + background-image: url('tab_a.png'); + background-repeat:repeat-x; + color: #fff; + text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); +} diff --git a/doc/html/yaml_8h.html b/doc/html/yaml_8h.html new file mode 100644 index 00000000000..ed9d0b863bc --- /dev/null +++ b/doc/html/yaml_8h.html @@ -0,0 +1,525 @@ + + + + +yaml: yaml.h File Reference + + + + + + +
    + +
    +

    yaml.h File Reference

    +
    +
    + +

    Public interface for libyaml. +More...

    +#include <stdlib.h>
    +#include <stdio.h>
    +#include <string.h>
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    +Data Structures

    struct  yaml_version_directive_s
     The version directive data. More...
    struct  yaml_tag_directive_s
     The tag directive data. More...
    struct  yaml_mark_s
     The pointer position. More...
    struct  yaml_token_s
     The token structure. More...
    struct  yaml_event_s
     The event structure. More...
    struct  yaml_node_pair_s
     An element of a mapping node. More...
    struct  yaml_node_s
     The node structure. More...
    struct  yaml_document_s
     The document structure. More...
    struct  yaml_simple_key_s
     This structure holds information about a potential simple key. More...
    struct  yaml_alias_data_s
     This structure holds aliases data. More...
    struct  yaml_parser_s
     The parser structure. More...
    struct  yaml_emitter_s
     The emitter structure. More...

    +Defines

    #define YAML_DECLARE(type)   type
     The public API declaration.
    #define YAML_NULL_TAG   "tag:yaml.org,2002:null"
     The tag !!null with the only possible value: null.
    #define YAML_BOOL_TAG   "tag:yaml.org,2002:bool"
     The tag !!bool with the values: true and falce.
    #define YAML_STR_TAG   "tag:yaml.org,2002:str"
     The tag !!str for string values.
    #define YAML_INT_TAG   "tag:yaml.org,2002:int"
     The tag !!int for integer values.
    #define YAML_FLOAT_TAG   "tag:yaml.org,2002:float"
     The tag !!float for float values.
    #define YAML_TIMESTAMP_TAG   "tag:yaml.org,2002:timestamp"
     The tag !!timestamp for date and time values.
    #define YAML_SEQ_TAG   "tag:yaml.org,2002:seq"
     The tag !!seq is used to denote sequences.
    #define YAML_MAP_TAG   "tag:yaml.org,2002:map"
     The tag !!map is used to denote mapping.
    #define YAML_DEFAULT_SCALAR_TAG   YAML_STR_TAG
     The default scalar tag is !!str.
    #define YAML_DEFAULT_SEQUENCE_TAG   YAML_SEQ_TAG
     The default sequence tag is !!seq.
    #define YAML_DEFAULT_MAPPING_TAG   YAML_MAP_TAG
     The default mapping tag is !!map.

    +Typedefs

    typedef unsigned char yaml_char_t
     The character type (UTF-8 octet).
    typedef struct
    +yaml_version_directive_s 
    yaml_version_directive_t
     The version directive data.
    typedef struct yaml_tag_directive_s yaml_tag_directive_t
     The tag directive data.
    typedef enum yaml_encoding_e yaml_encoding_t
     The stream encoding.
    typedef enum yaml_break_e yaml_break_t
     Line break types.
    typedef enum yaml_error_type_e yaml_error_type_t
     Many bad things could happen with the parser and emitter.
    typedef struct yaml_mark_s yaml_mark_t
     The pointer position.
    typedef enum yaml_scalar_style_e yaml_scalar_style_t
     Scalar styles.
    typedef enum yaml_sequence_style_e yaml_sequence_style_t
     Sequence styles.
    typedef enum yaml_mapping_style_e yaml_mapping_style_t
     Mapping styles.
    typedef enum yaml_token_type_e yaml_token_type_t
     Token types.
    typedef struct yaml_token_s yaml_token_t
     The token structure.
    typedef enum yaml_event_type_e yaml_event_type_t
     Event types.
    typedef struct yaml_event_s yaml_event_t
     The event structure.
    typedef enum yaml_node_type_e yaml_node_type_t
     Node types.
    typedef struct yaml_node_s yaml_node_t
     The forward definition of a document node structure.
    typedef int yaml_node_item_t
     An element of a sequence node.
    typedef struct yaml_node_pair_s yaml_node_pair_t
     An element of a mapping node.
    typedef struct yaml_document_s yaml_document_t
     The document structure.
    typedef int yaml_read_handler_t (void *data, unsigned char *buffer, size_t size, size_t *size_read)
     The prototype of a read handler.
    +typedef struct yaml_simple_key_s yaml_simple_key_t
     This structure holds information about a potential simple key.
    +typedef enum yaml_parser_state_e yaml_parser_state_t
     The states of the parser.
    +typedef struct yaml_alias_data_s yaml_alias_data_t
     This structure holds aliases data.
    typedef struct yaml_parser_s yaml_parser_t
     The parser structure.
    typedef int yaml_write_handler_t (void *data, unsigned char *buffer, size_t size)
     The prototype of a write handler.
    typedef enum yaml_emitter_state_e yaml_emitter_state_t
     The emitter states.
    typedef struct yaml_emitter_s yaml_emitter_t
     The emitter structure.

    +Enumerations

    enum  yaml_encoding_e {
    +  YAML_ANY_ENCODING, +
    +  YAML_UTF8_ENCODING, +
    +  YAML_UTF16LE_ENCODING, +
    +  YAML_UTF16BE_ENCODING +
    + }
     

    The stream encoding.

    + More...
    enum  yaml_break_e {
    +  YAML_ANY_BREAK, +
    +  YAML_CR_BREAK, +
    +  YAML_LN_BREAK, +
    +  YAML_CRLN_BREAK +
    + }
     

    Line break types.

    + More...
    enum  yaml_error_type_e {
    +  YAML_NO_ERROR, +
    +  YAML_MEMORY_ERROR, +
    +  YAML_READER_ERROR, +
    +  YAML_SCANNER_ERROR, +
    +  YAML_PARSER_ERROR, +
    +  YAML_COMPOSER_ERROR, +
    +  YAML_WRITER_ERROR, +
    +  YAML_EMITTER_ERROR +
    + }
     

    Many bad things could happen with the parser and emitter.

    + More...
    enum  yaml_scalar_style_e {
    +  YAML_ANY_SCALAR_STYLE, +
    +  YAML_PLAIN_SCALAR_STYLE, +
    +  YAML_SINGLE_QUOTED_SCALAR_STYLE, +
    +  YAML_DOUBLE_QUOTED_SCALAR_STYLE, +
    +  YAML_LITERAL_SCALAR_STYLE, +
    +  YAML_FOLDED_SCALAR_STYLE +
    + }
     

    Scalar styles.

    + More...
    enum  yaml_sequence_style_e {
    +  YAML_ANY_SEQUENCE_STYLE, +
    +  YAML_BLOCK_SEQUENCE_STYLE, +
    +  YAML_FLOW_SEQUENCE_STYLE +
    + }
     

    Sequence styles.

    + More...
    enum  yaml_mapping_style_e {
    +  YAML_ANY_MAPPING_STYLE, +
    +  YAML_BLOCK_MAPPING_STYLE, +
    +  YAML_FLOW_MAPPING_STYLE +
    + }
     

    Mapping styles.

    + More...
    enum  yaml_token_type_e {
    +  YAML_NO_TOKEN, +
    +  YAML_STREAM_START_TOKEN, +
    +  YAML_STREAM_END_TOKEN, +
    +  YAML_VERSION_DIRECTIVE_TOKEN, +
    +  YAML_TAG_DIRECTIVE_TOKEN, +
    +  YAML_DOCUMENT_START_TOKEN, +
    +  YAML_DOCUMENT_END_TOKEN, +
    +  YAML_BLOCK_SEQUENCE_START_TOKEN, +
    +  YAML_BLOCK_MAPPING_START_TOKEN, +
    +  YAML_BLOCK_END_TOKEN, +
    +  YAML_FLOW_SEQUENCE_START_TOKEN, +
    +  YAML_FLOW_SEQUENCE_END_TOKEN, +
    +  YAML_FLOW_MAPPING_START_TOKEN, +
    +  YAML_FLOW_MAPPING_END_TOKEN, +
    +  YAML_BLOCK_ENTRY_TOKEN, +
    +  YAML_FLOW_ENTRY_TOKEN, +
    +  YAML_KEY_TOKEN, +
    +  YAML_VALUE_TOKEN, +
    +  YAML_ALIAS_TOKEN, +
    +  YAML_ANCHOR_TOKEN, +
    +  YAML_TAG_TOKEN, +
    +  YAML_SCALAR_TOKEN +
    + }
     

    Token types.

    + More...
    enum  yaml_event_type_e {
    +  YAML_NO_EVENT, +
    +  YAML_STREAM_START_EVENT, +
    +  YAML_STREAM_END_EVENT, +
    +  YAML_DOCUMENT_START_EVENT, +
    +  YAML_DOCUMENT_END_EVENT, +
    +  YAML_ALIAS_EVENT, +
    +  YAML_SCALAR_EVENT, +
    +  YAML_SEQUENCE_START_EVENT, +
    +  YAML_SEQUENCE_END_EVENT, +
    +  YAML_MAPPING_START_EVENT, +
    +  YAML_MAPPING_END_EVENT +
    + }
     

    Event types.

    + More...
    enum  yaml_node_type_e {
    +  YAML_NO_NODE, +
    +  YAML_SCALAR_NODE, +
    +  YAML_SEQUENCE_NODE, +
    +  YAML_MAPPING_NODE +
    + }
     

    Node types.

    + More...
    enum  yaml_parser_state_e {
    +  YAML_PARSE_STREAM_START_STATE, +
    +  YAML_PARSE_IMPLICIT_DOCUMENT_START_STATE, +
    +  YAML_PARSE_DOCUMENT_START_STATE, +
    +  YAML_PARSE_DOCUMENT_CONTENT_STATE, +
    +  YAML_PARSE_DOCUMENT_END_STATE, +
    +  YAML_PARSE_BLOCK_NODE_STATE, +
    +  YAML_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE, +
    +  YAML_PARSE_FLOW_NODE_STATE, +
    +  YAML_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE, +
    +  YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE, +
    +  YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE, +
    +  YAML_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE, +
    +  YAML_PARSE_BLOCK_MAPPING_KEY_STATE, +
    +  YAML_PARSE_BLOCK_MAPPING_VALUE_STATE, +
    +  YAML_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE, +
    +  YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE, +
    +  YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE, +
    +  YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE, +
    +  YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE, +
    +  YAML_PARSE_FLOW_MAPPING_FIRST_KEY_STATE, +
    +  YAML_PARSE_FLOW_MAPPING_KEY_STATE, +
    +  YAML_PARSE_FLOW_MAPPING_VALUE_STATE, +
    +  YAML_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE, +
    +  YAML_PARSE_END_STATE +
    + }
     

    The states of the parser.

    + More...
    enum  yaml_emitter_state_e {
    +  YAML_EMIT_STREAM_START_STATE, +
    +  YAML_EMIT_FIRST_DOCUMENT_START_STATE, +
    +  YAML_EMIT_DOCUMENT_START_STATE, +
    +  YAML_EMIT_DOCUMENT_CONTENT_STATE, +
    +  YAML_EMIT_DOCUMENT_END_STATE, +
    +  YAML_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE, +
    +  YAML_EMIT_FLOW_SEQUENCE_ITEM_STATE, +
    +  YAML_EMIT_FLOW_MAPPING_FIRST_KEY_STATE, +
    +  YAML_EMIT_FLOW_MAPPING_KEY_STATE, +
    +  YAML_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE, +
    +  YAML_EMIT_FLOW_MAPPING_VALUE_STATE, +
    +  YAML_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE, +
    +  YAML_EMIT_BLOCK_SEQUENCE_ITEM_STATE, +
    +  YAML_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE, +
    +  YAML_EMIT_BLOCK_MAPPING_KEY_STATE, +
    +  YAML_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE, +
    +  YAML_EMIT_BLOCK_MAPPING_VALUE_STATE, +
    +  YAML_EMIT_END_STATE +
    + }
     

    The emitter states.

    + More...

    +Functions

    const char * yaml_get_version_string (void)
     Get the library version as a string.
    void yaml_get_version (int *major, int *minor, int *patch)
     Get the library version numbers.
    void yaml_token_delete (yaml_token_t *token)
     Free any memory allocated for a token object.
    int yaml_stream_start_event_initialize (yaml_event_t *event, yaml_encoding_t encoding)
     Create the STREAM-START event.
    int yaml_stream_end_event_initialize (yaml_event_t *event)
     Create the STREAM-END event.
    int yaml_document_start_event_initialize (yaml_event_t *event, yaml_version_directive_t *version_directive, yaml_tag_directive_t *tag_directives_start, yaml_tag_directive_t *tag_directives_end, int implicit)
     Create the DOCUMENT-START event.
    int yaml_document_end_event_initialize (yaml_event_t *event, int implicit)
     Create the DOCUMENT-END event.
    int yaml_alias_event_initialize (yaml_event_t *event, yaml_char_t *anchor)
     Create an ALIAS event.
    int yaml_scalar_event_initialize (yaml_event_t *event, yaml_char_t *anchor, yaml_char_t *tag, yaml_char_t *value, int length, int plain_implicit, int quoted_implicit, yaml_scalar_style_t style)
     Create a SCALAR event.
    int yaml_sequence_start_event_initialize (yaml_event_t *event, yaml_char_t *anchor, yaml_char_t *tag, int implicit, yaml_sequence_style_t style)
     Create a SEQUENCE-START event.
    int yaml_sequence_end_event_initialize (yaml_event_t *event)
     Create a SEQUENCE-END event.
    int yaml_mapping_start_event_initialize (yaml_event_t *event, yaml_char_t *anchor, yaml_char_t *tag, int implicit, yaml_mapping_style_t style)
     Create a MAPPING-START event.
    int yaml_mapping_end_event_initialize (yaml_event_t *event)
     Create a MAPPING-END event.
    void yaml_event_delete (yaml_event_t *event)
     Free any memory allocated for an event object.
    int yaml_document_initialize (yaml_document_t *document, yaml_version_directive_t *version_directive, yaml_tag_directive_t *tag_directives_start, yaml_tag_directive_t *tag_directives_end, int start_implicit, int end_implicit)
     Create a YAML document.
    void yaml_document_delete (yaml_document_t *document)
     Delete a YAML document and all its nodes.
    yaml_node_tyaml_document_get_node (yaml_document_t *document, int index)
     Get a node of a YAML document.
    yaml_node_tyaml_document_get_root_node (yaml_document_t *document)
     Get the root of a YAML document node.
    int yaml_document_add_scalar (yaml_document_t *document, yaml_char_t *tag, yaml_char_t *value, int length, yaml_scalar_style_t style)
     Create a SCALAR node and attach it to the document.
    int yaml_document_add_sequence (yaml_document_t *document, yaml_char_t *tag, yaml_sequence_style_t style)
     Create a SEQUENCE node and attach it to the document.
    int yaml_document_add_mapping (yaml_document_t *document, yaml_char_t *tag, yaml_mapping_style_t style)
     Create a MAPPING node and attach it to the document.
    int yaml_document_append_sequence_item (yaml_document_t *document, int sequence, int item)
     Add an item to a SEQUENCE node.
    int yaml_document_append_mapping_pair (yaml_document_t *document, int mapping, int key, int value)
     Add a pair of a key and a value to a MAPPING node.
    int yaml_parser_initialize (yaml_parser_t *parser)
     Initialize a parser.
    void yaml_parser_delete (yaml_parser_t *parser)
     Destroy a parser.
    void yaml_parser_set_input_string (yaml_parser_t *parser, const unsigned char *input, size_t size)
     Set a string input.
    void yaml_parser_set_input_file (yaml_parser_t *parser, FILE *file)
     Set a file input.
    void yaml_parser_set_input (yaml_parser_t *parser, yaml_read_handler_t *handler, void *data)
     Set a generic input handler.
    void yaml_parser_set_encoding (yaml_parser_t *parser, yaml_encoding_t encoding)
     Set the source encoding.
    int yaml_parser_scan (yaml_parser_t *parser, yaml_token_t *token)
     Scan the input stream and produce the next token.
    int yaml_parser_parse (yaml_parser_t *parser, yaml_event_t *event)
     Parse the input stream and produce the next parsing event.
    int yaml_parser_load (yaml_parser_t *parser, yaml_document_t *document)
     Parse the input stream and produce the next YAML document.
    int yaml_emitter_initialize (yaml_emitter_t *emitter)
     Initialize an emitter.
    void yaml_emitter_delete (yaml_emitter_t *emitter)
     Destroy an emitter.
    void yaml_emitter_set_output_string (yaml_emitter_t *emitter, unsigned char *output, size_t size, size_t *size_written)
     Set a string output.
    void yaml_emitter_set_output_file (yaml_emitter_t *emitter, FILE *file)
     Set a file output.
    void yaml_emitter_set_output (yaml_emitter_t *emitter, yaml_write_handler_t *handler, void *data)
     Set a generic output handler.
    void yaml_emitter_set_encoding (yaml_emitter_t *emitter, yaml_encoding_t encoding)
     Set the output encoding.
    void yaml_emitter_set_canonical (yaml_emitter_t *emitter, int canonical)
     Set if the output should be in the "canonical" format as in the YAML specification.
    void yaml_emitter_set_indent (yaml_emitter_t *emitter, int indent)
     Set the intendation increment.
    void yaml_emitter_set_width (yaml_emitter_t *emitter, int width)
     Set the preferred line width.
    void yaml_emitter_set_unicode (yaml_emitter_t *emitter, int unicode)
     Set if unescaped non-ASCII characters are allowed.
    void yaml_emitter_set_break (yaml_emitter_t *emitter, yaml_break_t line_break)
     Set the preferred line break.
    int yaml_emitter_emit (yaml_emitter_t *emitter, yaml_event_t *event)
     Emit an event.
    int yaml_emitter_open (yaml_emitter_t *emitter)
     Start a YAML stream.
    int yaml_emitter_close (yaml_emitter_t *emitter)
     Finish a YAML stream.
    int yaml_emitter_dump (yaml_emitter_t *emitter, yaml_document_t *document)
     Emit a YAML document.
    int yaml_emitter_flush (yaml_emitter_t *emitter)
     Flush the accumulated characters to the output.
    +

    Detailed Description

    +

    Public interface for libyaml.

    +

    Include the header file with the code:

    +
     #include <yaml.h>
    +
    + + + diff --git a/include/Makefile.am b/include/Makefile.am new file mode 100644 index 00000000000..f81863cbbfe --- /dev/null +++ b/include/Makefile.am @@ -0,0 +1,17 @@ +INCLUDES = yaml.h +DOXYGEN_CFG = $(top_srcdir)/doc/doxygen.cfg + +nobase_include_HEADERS = $(INCLUDES) + +if DOXYGEN + +html: $(INCLUDES) $(DOXYGEN_CFG) + PACKAGE=$(PACKAGE) VERSION=$(VERSION) top_srcdir=$(top_srcdir) top_builddir=$(top_builddir) doxygen $(DOXYGEN_CFG) + +endif + +maintainer-clean-local: + -rm -rf $(top_builddir)/doc/html + +dist-hook: html + cp -a $(top_builddir)/doc/html $(top_distdir)/doc diff --git a/include/Makefile.in b/include/Makefile.in new file mode 100644 index 00000000000..d7fba23cecd --- /dev/null +++ b/include/Makefile.in @@ -0,0 +1,470 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = include +DIST_COMMON = $(nobase_include_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(includedir)" +HEADERS = $(nobase_include_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YAML_LT_AGE = @YAML_LT_AGE@ +YAML_LT_CURRENT = @YAML_LT_CURRENT@ +YAML_LT_RELEASE = @YAML_LT_RELEASE@ +YAML_LT_REVISION = @YAML_LT_REVISION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +INCLUDES = yaml.h +DOXYGEN_CFG = $(top_srcdir)/doc/doxygen.cfg +nobase_include_HEADERS = $(INCLUDES) +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign include/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign include/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-nobase_includeHEADERS: $(nobase_include_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)" + @list='$(nobase_include_HEADERS)'; test -n "$(includedir)" || list=; \ + $(am__nobase_list) | while read dir files; do \ + xfiles=; for file in $$files; do \ + if test -f "$$file"; then xfiles="$$xfiles $$file"; \ + else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ + test -z "$$xfiles" || { \ + test "x$$dir" = x. || { \ + echo "$(MKDIR_P) '$(DESTDIR)$(includedir)/$$dir'"; \ + $(MKDIR_P) "$(DESTDIR)$(includedir)/$$dir"; }; \ + echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(includedir)/$$dir'"; \ + $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(includedir)/$$dir" || exit $$?; }; \ + done + +uninstall-nobase_includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(nobase_include_HEADERS)'; test -n "$(includedir)" || list=; \ + $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(includedir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(includedir)" && rm -f $$files + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" distdir="$(distdir)" \ + dist-hook +check-am: all-am +check: check-am +all-am: Makefile $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(includedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-am + +dvi-am: + +@DOXYGEN_FALSE@html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-nobase_includeHEADERS + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic \ + maintainer-clean-local + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-nobase_includeHEADERS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool ctags dist-hook distclean distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-nobase_includeHEADERS \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic \ + maintainer-clean-local mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \ + uninstall-am uninstall-nobase_includeHEADERS + + +@DOXYGEN_TRUE@html: $(INCLUDES) $(DOXYGEN_CFG) +@DOXYGEN_TRUE@ PACKAGE=$(PACKAGE) VERSION=$(VERSION) top_srcdir=$(top_srcdir) top_builddir=$(top_builddir) doxygen $(DOXYGEN_CFG) + +maintainer-clean-local: + -rm -rf $(top_builddir)/doc/html + +dist-hook: html + cp -a $(top_builddir)/doc/html $(top_distdir)/doc + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/include/yaml.h b/include/yaml.h new file mode 100644 index 00000000000..5a04d36d415 --- /dev/null +++ b/include/yaml.h @@ -0,0 +1,1971 @@ +/** + * @file yaml.h + * @brief Public interface for libyaml. + * + * Include the header file with the code: + * @code + * #include + * @endcode + */ + +#ifndef YAML_H +#define YAML_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +/** + * @defgroup export Export Definitions + * @{ + */ + +/** The public API declaration. */ + +#ifdef _WIN32 +# if defined(YAML_DECLARE_STATIC) +# define YAML_DECLARE(type) type +# elif defined(YAML_DECLARE_EXPORT) +# define YAML_DECLARE(type) __declspec(dllexport) type +# else +# define YAML_DECLARE(type) __declspec(dllimport) type +# endif +#else +# define YAML_DECLARE(type) type +#endif + +/** @} */ + +/** + * @defgroup version Version Information + * @{ + */ + +/** + * Get the library version as a string. + * + * @returns The function returns the pointer to a static string of the form + * @c "X.Y.Z", where @c X is the major version number, @c Y is a minor version + * number, and @c Z is the patch version number. + */ + +YAML_DECLARE(const char *) +yaml_get_version_string(void); + +/** + * Get the library version numbers. + * + * @param[out] major Major version number. + * @param[out] minor Minor version number. + * @param[out] patch Patch version number. + */ + +YAML_DECLARE(void) +yaml_get_version(int *major, int *minor, int *patch); + +/** @} */ + +/** + * @defgroup basic Basic Types + * @{ + */ + +/** The character type (UTF-8 octet). */ +typedef unsigned char yaml_char_t; + +/** The version directive data. */ +typedef struct yaml_version_directive_s { + /** The major version number. */ + int major; + /** The minor version number. */ + int minor; +} yaml_version_directive_t; + +/** The tag directive data. */ +typedef struct yaml_tag_directive_s { + /** The tag handle. */ + yaml_char_t *handle; + /** The tag prefix. */ + yaml_char_t *prefix; +} yaml_tag_directive_t; + +/** The stream encoding. */ +typedef enum yaml_encoding_e { + /** Let the parser choose the encoding. */ + YAML_ANY_ENCODING, + /** The default UTF-8 encoding. */ + YAML_UTF8_ENCODING, + /** The UTF-16-LE encoding with BOM. */ + YAML_UTF16LE_ENCODING, + /** The UTF-16-BE encoding with BOM. */ + YAML_UTF16BE_ENCODING +} yaml_encoding_t; + +/** Line break types. */ + +typedef enum yaml_break_e { + /** Let the parser choose the break type. */ + YAML_ANY_BREAK, + /** Use CR for line breaks (Mac style). */ + YAML_CR_BREAK, + /** Use LN for line breaks (Unix style). */ + YAML_LN_BREAK, + /** Use CR LN for line breaks (DOS style). */ + YAML_CRLN_BREAK +} yaml_break_t; + +/** Many bad things could happen with the parser and emitter. */ +typedef enum yaml_error_type_e { + /** No error is produced. */ + YAML_NO_ERROR, + + /** Cannot allocate or reallocate a block of memory. */ + YAML_MEMORY_ERROR, + + /** Cannot read or decode the input stream. */ + YAML_READER_ERROR, + /** Cannot scan the input stream. */ + YAML_SCANNER_ERROR, + /** Cannot parse the input stream. */ + YAML_PARSER_ERROR, + /** Cannot compose a YAML document. */ + YAML_COMPOSER_ERROR, + + /** Cannot write to the output stream. */ + YAML_WRITER_ERROR, + /** Cannot emit a YAML stream. */ + YAML_EMITTER_ERROR +} yaml_error_type_t; + +/** The pointer position. */ +typedef struct yaml_mark_s { + /** The position index. */ + size_t index; + + /** The position line. */ + size_t line; + + /** The position column. */ + size_t column; +} yaml_mark_t; + +/** @} */ + +/** + * @defgroup styles Node Styles + * @{ + */ + +/** Scalar styles. */ +typedef enum yaml_scalar_style_e { + /** Let the emitter choose the style. */ + YAML_ANY_SCALAR_STYLE, + + /** The plain scalar style. */ + YAML_PLAIN_SCALAR_STYLE, + + /** The single-quoted scalar style. */ + YAML_SINGLE_QUOTED_SCALAR_STYLE, + /** The double-quoted scalar style. */ + YAML_DOUBLE_QUOTED_SCALAR_STYLE, + + /** The literal scalar style. */ + YAML_LITERAL_SCALAR_STYLE, + /** The folded scalar style. */ + YAML_FOLDED_SCALAR_STYLE +} yaml_scalar_style_t; + +/** Sequence styles. */ +typedef enum yaml_sequence_style_e { + /** Let the emitter choose the style. */ + YAML_ANY_SEQUENCE_STYLE, + + /** The block sequence style. */ + YAML_BLOCK_SEQUENCE_STYLE, + /** The flow sequence style. */ + YAML_FLOW_SEQUENCE_STYLE +} yaml_sequence_style_t; + +/** Mapping styles. */ +typedef enum yaml_mapping_style_e { + /** Let the emitter choose the style. */ + YAML_ANY_MAPPING_STYLE, + + /** The block mapping style. */ + YAML_BLOCK_MAPPING_STYLE, + /** The flow mapping style. */ + YAML_FLOW_MAPPING_STYLE +/* YAML_FLOW_SET_MAPPING_STYLE */ +} yaml_mapping_style_t; + +/** @} */ + +/** + * @defgroup tokens Tokens + * @{ + */ + +/** Token types. */ +typedef enum yaml_token_type_e { + /** An empty token. */ + YAML_NO_TOKEN, + + /** A STREAM-START token. */ + YAML_STREAM_START_TOKEN, + /** A STREAM-END token. */ + YAML_STREAM_END_TOKEN, + + /** A VERSION-DIRECTIVE token. */ + YAML_VERSION_DIRECTIVE_TOKEN, + /** A TAG-DIRECTIVE token. */ + YAML_TAG_DIRECTIVE_TOKEN, + /** A DOCUMENT-START token. */ + YAML_DOCUMENT_START_TOKEN, + /** A DOCUMENT-END token. */ + YAML_DOCUMENT_END_TOKEN, + + /** A BLOCK-SEQUENCE-START token. */ + YAML_BLOCK_SEQUENCE_START_TOKEN, + /** A BLOCK-SEQUENCE-END token. */ + YAML_BLOCK_MAPPING_START_TOKEN, + /** A BLOCK-END token. */ + YAML_BLOCK_END_TOKEN, + + /** A FLOW-SEQUENCE-START token. */ + YAML_FLOW_SEQUENCE_START_TOKEN, + /** A FLOW-SEQUENCE-END token. */ + YAML_FLOW_SEQUENCE_END_TOKEN, + /** A FLOW-MAPPING-START token. */ + YAML_FLOW_MAPPING_START_TOKEN, + /** A FLOW-MAPPING-END token. */ + YAML_FLOW_MAPPING_END_TOKEN, + + /** A BLOCK-ENTRY token. */ + YAML_BLOCK_ENTRY_TOKEN, + /** A FLOW-ENTRY token. */ + YAML_FLOW_ENTRY_TOKEN, + /** A KEY token. */ + YAML_KEY_TOKEN, + /** A VALUE token. */ + YAML_VALUE_TOKEN, + + /** An ALIAS token. */ + YAML_ALIAS_TOKEN, + /** An ANCHOR token. */ + YAML_ANCHOR_TOKEN, + /** A TAG token. */ + YAML_TAG_TOKEN, + /** A SCALAR token. */ + YAML_SCALAR_TOKEN +} yaml_token_type_t; + +/** The token structure. */ +typedef struct yaml_token_s { + + /** The token type. */ + yaml_token_type_t type; + + /** The token data. */ + union { + + /** The stream start (for @c YAML_STREAM_START_TOKEN). */ + struct { + /** The stream encoding. */ + yaml_encoding_t encoding; + } stream_start; + + /** The alias (for @c YAML_ALIAS_TOKEN). */ + struct { + /** The alias value. */ + yaml_char_t *value; + } alias; + + /** The anchor (for @c YAML_ANCHOR_TOKEN). */ + struct { + /** The anchor value. */ + yaml_char_t *value; + } anchor; + + /** The tag (for @c YAML_TAG_TOKEN). */ + struct { + /** The tag handle. */ + yaml_char_t *handle; + /** The tag suffix. */ + yaml_char_t *suffix; + } tag; + + /** The scalar value (for @c YAML_SCALAR_TOKEN). */ + struct { + /** The scalar value. */ + yaml_char_t *value; + /** The length of the scalar value. */ + size_t length; + /** The scalar style. */ + yaml_scalar_style_t style; + } scalar; + + /** The version directive (for @c YAML_VERSION_DIRECTIVE_TOKEN). */ + struct { + /** The major version number. */ + int major; + /** The minor version number. */ + int minor; + } version_directive; + + /** The tag directive (for @c YAML_TAG_DIRECTIVE_TOKEN). */ + struct { + /** The tag handle. */ + yaml_char_t *handle; + /** The tag prefix. */ + yaml_char_t *prefix; + } tag_directive; + + } data; + + /** The beginning of the token. */ + yaml_mark_t start_mark; + /** The end of the token. */ + yaml_mark_t end_mark; + +} yaml_token_t; + +/** + * Free any memory allocated for a token object. + * + * @param[in,out] token A token object. + */ + +YAML_DECLARE(void) +yaml_token_delete(yaml_token_t *token); + +/** @} */ + +/** + * @defgroup events Events + * @{ + */ + +/** Event types. */ +typedef enum yaml_event_type_e { + /** An empty event. */ + YAML_NO_EVENT, + + /** A STREAM-START event. */ + YAML_STREAM_START_EVENT, + /** A STREAM-END event. */ + YAML_STREAM_END_EVENT, + + /** A DOCUMENT-START event. */ + YAML_DOCUMENT_START_EVENT, + /** A DOCUMENT-END event. */ + YAML_DOCUMENT_END_EVENT, + + /** An ALIAS event. */ + YAML_ALIAS_EVENT, + /** A SCALAR event. */ + YAML_SCALAR_EVENT, + + /** A SEQUENCE-START event. */ + YAML_SEQUENCE_START_EVENT, + /** A SEQUENCE-END event. */ + YAML_SEQUENCE_END_EVENT, + + /** A MAPPING-START event. */ + YAML_MAPPING_START_EVENT, + /** A MAPPING-END event. */ + YAML_MAPPING_END_EVENT +} yaml_event_type_t; + +/** The event structure. */ +typedef struct yaml_event_s { + + /** The event type. */ + yaml_event_type_t type; + + /** The event data. */ + union { + + /** The stream parameters (for @c YAML_STREAM_START_EVENT). */ + struct { + /** The document encoding. */ + yaml_encoding_t encoding; + } stream_start; + + /** The document parameters (for @c YAML_DOCUMENT_START_EVENT). */ + struct { + /** The version directive. */ + yaml_version_directive_t *version_directive; + + /** The list of tag directives. */ + struct { + /** The beginning of the tag directives list. */ + yaml_tag_directive_t *start; + /** The end of the tag directives list. */ + yaml_tag_directive_t *end; + } tag_directives; + + /** Is the document indicator implicit? */ + int implicit; + } document_start; + + /** The document end parameters (for @c YAML_DOCUMENT_END_EVENT). */ + struct { + /** Is the document end indicator implicit? */ + int implicit; + } document_end; + + /** The alias parameters (for @c YAML_ALIAS_EVENT). */ + struct { + /** The anchor. */ + yaml_char_t *anchor; + } alias; + + /** The scalar parameters (for @c YAML_SCALAR_EVENT). */ + struct { + /** The anchor. */ + yaml_char_t *anchor; + /** The tag. */ + yaml_char_t *tag; + /** The scalar value. */ + yaml_char_t *value; + /** The length of the scalar value. */ + size_t length; + /** Is the tag optional for the plain style? */ + int plain_implicit; + /** Is the tag optional for any non-plain style? */ + int quoted_implicit; + /** The scalar style. */ + yaml_scalar_style_t style; + } scalar; + + /** The sequence parameters (for @c YAML_SEQUENCE_START_EVENT). */ + struct { + /** The anchor. */ + yaml_char_t *anchor; + /** The tag. */ + yaml_char_t *tag; + /** Is the tag optional? */ + int implicit; + /** The sequence style. */ + yaml_sequence_style_t style; + } sequence_start; + + /** The mapping parameters (for @c YAML_MAPPING_START_EVENT). */ + struct { + /** The anchor. */ + yaml_char_t *anchor; + /** The tag. */ + yaml_char_t *tag; + /** Is the tag optional? */ + int implicit; + /** The mapping style. */ + yaml_mapping_style_t style; + } mapping_start; + + } data; + + /** The beginning of the event. */ + yaml_mark_t start_mark; + /** The end of the event. */ + yaml_mark_t end_mark; + +} yaml_event_t; + +/** + * Create the STREAM-START event. + * + * @param[out] event An empty event object. + * @param[in] encoding The stream encoding. + * + * @returns @c 1 if the function succeeded, @c 0 on error. + */ + +YAML_DECLARE(int) +yaml_stream_start_event_initialize(yaml_event_t *event, + yaml_encoding_t encoding); + +/** + * Create the STREAM-END event. + * + * @param[out] event An empty event object. + * + * @returns @c 1 if the function succeeded, @c 0 on error. + */ + +YAML_DECLARE(int) +yaml_stream_end_event_initialize(yaml_event_t *event); + +/** + * Create the DOCUMENT-START event. + * + * The @a implicit argument is considered as a stylistic parameter and may be + * ignored by the emitter. + * + * @param[out] event An empty event object. + * @param[in] version_directive The %YAML directive value or + * @c NULL. + * @param[in] tag_directives_start The beginning of the %TAG + * directives list. + * @param[in] tag_directives_end The end of the %TAG directives + * list. + * @param[in] implicit If the document start indicator is + * implicit. + * + * @returns @c 1 if the function succeeded, @c 0 on error. + */ + +YAML_DECLARE(int) +yaml_document_start_event_initialize(yaml_event_t *event, + yaml_version_directive_t *version_directive, + yaml_tag_directive_t *tag_directives_start, + yaml_tag_directive_t *tag_directives_end, + int implicit); + +/** + * Create the DOCUMENT-END event. + * + * The @a implicit argument is considered as a stylistic parameter and may be + * ignored by the emitter. + * + * @param[out] event An empty event object. + * @param[in] implicit If the document end indicator is implicit. + * + * @returns @c 1 if the function succeeded, @c 0 on error. + */ + +YAML_DECLARE(int) +yaml_document_end_event_initialize(yaml_event_t *event, int implicit); + +/** + * Create an ALIAS event. + * + * @param[out] event An empty event object. + * @param[in] anchor The anchor value. + * + * @returns @c 1 if the function succeeded, @c 0 on error. + */ + +YAML_DECLARE(int) +yaml_alias_event_initialize(yaml_event_t *event, yaml_char_t *anchor); + +/** + * Create a SCALAR event. + * + * The @a style argument may be ignored by the emitter. + * + * Either the @a tag attribute or one of the @a plain_implicit and + * @a quoted_implicit flags must be set. + * + * @param[out] event An empty event object. + * @param[in] anchor The scalar anchor or @c NULL. + * @param[in] tag The scalar tag or @c NULL. + * @param[in] value The scalar value. + * @param[in] length The length of the scalar value. + * @param[in] plain_implicit If the tag may be omitted for the plain + * style. + * @param[in] quoted_implicit If the tag may be omitted for any + * non-plain style. + * @param[in] style The scalar style. + * + * @returns @c 1 if the function succeeded, @c 0 on error. + */ + +YAML_DECLARE(int) +yaml_scalar_event_initialize(yaml_event_t *event, + yaml_char_t *anchor, yaml_char_t *tag, + yaml_char_t *value, int length, + int plain_implicit, int quoted_implicit, + yaml_scalar_style_t style); + +/** + * Create a SEQUENCE-START event. + * + * The @a style argument may be ignored by the emitter. + * + * Either the @a tag attribute or the @a implicit flag must be set. + * + * @param[out] event An empty event object. + * @param[in] anchor The sequence anchor or @c NULL. + * @param[in] tag The sequence tag or @c NULL. + * @param[in] implicit If the tag may be omitted. + * @param[in] style The sequence style. + * + * @returns @c 1 if the function succeeded, @c 0 on error. + */ + +YAML_DECLARE(int) +yaml_sequence_start_event_initialize(yaml_event_t *event, + yaml_char_t *anchor, yaml_char_t *tag, int implicit, + yaml_sequence_style_t style); + +/** + * Create a SEQUENCE-END event. + * + * @param[out] event An empty event object. + * + * @returns @c 1 if the function succeeded, @c 0 on error. + */ + +YAML_DECLARE(int) +yaml_sequence_end_event_initialize(yaml_event_t *event); + +/** + * Create a MAPPING-START event. + * + * The @a style argument may be ignored by the emitter. + * + * Either the @a tag attribute or the @a implicit flag must be set. + * + * @param[out] event An empty event object. + * @param[in] anchor The mapping anchor or @c NULL. + * @param[in] tag The mapping tag or @c NULL. + * @param[in] implicit If the tag may be omitted. + * @param[in] style The mapping style. + * + * @returns @c 1 if the function succeeded, @c 0 on error. + */ + +YAML_DECLARE(int) +yaml_mapping_start_event_initialize(yaml_event_t *event, + yaml_char_t *anchor, yaml_char_t *tag, int implicit, + yaml_mapping_style_t style); + +/** + * Create a MAPPING-END event. + * + * @param[out] event An empty event object. + * + * @returns @c 1 if the function succeeded, @c 0 on error. + */ + +YAML_DECLARE(int) +yaml_mapping_end_event_initialize(yaml_event_t *event); + +/** + * Free any memory allocated for an event object. + * + * @param[in,out] event An event object. + */ + +YAML_DECLARE(void) +yaml_event_delete(yaml_event_t *event); + +/** @} */ + +/** + * @defgroup nodes Nodes + * @{ + */ + +/** The tag @c !!null with the only possible value: @c null. */ +#define YAML_NULL_TAG "tag:yaml.org,2002:null" +/** The tag @c !!bool with the values: @c true and @c falce. */ +#define YAML_BOOL_TAG "tag:yaml.org,2002:bool" +/** The tag @c !!str for string values. */ +#define YAML_STR_TAG "tag:yaml.org,2002:str" +/** The tag @c !!int for integer values. */ +#define YAML_INT_TAG "tag:yaml.org,2002:int" +/** The tag @c !!float for float values. */ +#define YAML_FLOAT_TAG "tag:yaml.org,2002:float" +/** The tag @c !!timestamp for date and time values. */ +#define YAML_TIMESTAMP_TAG "tag:yaml.org,2002:timestamp" + +/** The tag @c !!seq is used to denote sequences. */ +#define YAML_SEQ_TAG "tag:yaml.org,2002:seq" +/** The tag @c !!map is used to denote mapping. */ +#define YAML_MAP_TAG "tag:yaml.org,2002:map" + +/** The default scalar tag is @c !!str. */ +#define YAML_DEFAULT_SCALAR_TAG YAML_STR_TAG +/** The default sequence tag is @c !!seq. */ +#define YAML_DEFAULT_SEQUENCE_TAG YAML_SEQ_TAG +/** The default mapping tag is @c !!map. */ +#define YAML_DEFAULT_MAPPING_TAG YAML_MAP_TAG + +/** Node types. */ +typedef enum yaml_node_type_e { + /** An empty node. */ + YAML_NO_NODE, + + /** A scalar node. */ + YAML_SCALAR_NODE, + /** A sequence node. */ + YAML_SEQUENCE_NODE, + /** A mapping node. */ + YAML_MAPPING_NODE +} yaml_node_type_t; + +/** The forward definition of a document node structure. */ +typedef struct yaml_node_s yaml_node_t; + +/** An element of a sequence node. */ +typedef int yaml_node_item_t; + +/** An element of a mapping node. */ +typedef struct yaml_node_pair_s { + /** The key of the element. */ + int key; + /** The value of the element. */ + int value; +} yaml_node_pair_t; + +/** The node structure. */ +struct yaml_node_s { + + /** The node type. */ + yaml_node_type_t type; + + /** The node tag. */ + yaml_char_t *tag; + + /** The node data. */ + union { + + /** The scalar parameters (for @c YAML_SCALAR_NODE). */ + struct { + /** The scalar value. */ + yaml_char_t *value; + /** The length of the scalar value. */ + size_t length; + /** The scalar style. */ + yaml_scalar_style_t style; + } scalar; + + /** The sequence parameters (for @c YAML_SEQUENCE_NODE). */ + struct { + /** The stack of sequence items. */ + struct { + /** The beginning of the stack. */ + yaml_node_item_t *start; + /** The end of the stack. */ + yaml_node_item_t *end; + /** The top of the stack. */ + yaml_node_item_t *top; + } items; + /** The sequence style. */ + yaml_sequence_style_t style; + } sequence; + + /** The mapping parameters (for @c YAML_MAPPING_NODE). */ + struct { + /** The stack of mapping pairs (key, value). */ + struct { + /** The beginning of the stack. */ + yaml_node_pair_t *start; + /** The end of the stack. */ + yaml_node_pair_t *end; + /** The top of the stack. */ + yaml_node_pair_t *top; + } pairs; + /** The mapping style. */ + yaml_mapping_style_t style; + } mapping; + + } data; + + /** The beginning of the node. */ + yaml_mark_t start_mark; + /** The end of the node. */ + yaml_mark_t end_mark; + +}; + +/** The document structure. */ +typedef struct yaml_document_s { + + /** The document nodes. */ + struct { + /** The beginning of the stack. */ + yaml_node_t *start; + /** The end of the stack. */ + yaml_node_t *end; + /** The top of the stack. */ + yaml_node_t *top; + } nodes; + + /** The version directive. */ + yaml_version_directive_t *version_directive; + + /** The list of tag directives. */ + struct { + /** The beginning of the tag directives list. */ + yaml_tag_directive_t *start; + /** The end of the tag directives list. */ + yaml_tag_directive_t *end; + } tag_directives; + + /** Is the document start indicator implicit? */ + int start_implicit; + /** Is the document end indicator implicit? */ + int end_implicit; + + /** The beginning of the document. */ + yaml_mark_t start_mark; + /** The end of the document. */ + yaml_mark_t end_mark; + +} yaml_document_t; + +/** + * Create a YAML document. + * + * @param[out] document An empty document object. + * @param[in] version_directive The %YAML directive value or + * @c NULL. + * @param[in] tag_directives_start The beginning of the %TAG + * directives list. + * @param[in] tag_directives_end The end of the %TAG directives + * list. + * @param[in] start_implicit If the document start indicator is + * implicit. + * @param[in] end_implicit If the document end indicator is + * implicit. + * + * @returns @c 1 if the function succeeded, @c 0 on error. + */ + +YAML_DECLARE(int) +yaml_document_initialize(yaml_document_t *document, + yaml_version_directive_t *version_directive, + yaml_tag_directive_t *tag_directives_start, + yaml_tag_directive_t *tag_directives_end, + int start_implicit, int end_implicit); + +/** + * Delete a YAML document and all its nodes. + * + * @param[in,out] document A document object. + */ + +YAML_DECLARE(void) +yaml_document_delete(yaml_document_t *document); + +/** + * Get a node of a YAML document. + * + * The pointer returned by this function is valid until any of the functions + * modifying the documents are called. + * + * @param[in] document A document object. + * @param[in] index The node id. + * + * @returns the node objct or @c NULL if @c node_id is out of range. + */ + +YAML_DECLARE(yaml_node_t *) +yaml_document_get_node(yaml_document_t *document, int index); + +/** + * Get the root of a YAML document node. + * + * The root object is the first object added to the document. + * + * The pointer returned by this function is valid until any of the functions + * modifying the documents are called. + * + * An empty document produced by the parser signifies the end of a YAML + * stream. + * + * @param[in] document A document object. + * + * @returns the node object or @c NULL if the document is empty. + */ + +YAML_DECLARE(yaml_node_t *) +yaml_document_get_root_node(yaml_document_t *document); + +/** + * Create a SCALAR node and attach it to the document. + * + * The @a style argument may be ignored by the emitter. + * + * @param[in,out] document A document object. + * @param[in] tag The scalar tag. + * @param[in] value The scalar value. + * @param[in] length The length of the scalar value. + * @param[in] style The scalar style. + * + * @returns the node id or @c 0 on error. + */ + +YAML_DECLARE(int) +yaml_document_add_scalar(yaml_document_t *document, + yaml_char_t *tag, yaml_char_t *value, int length, + yaml_scalar_style_t style); + +/** + * Create a SEQUENCE node and attach it to the document. + * + * The @a style argument may be ignored by the emitter. + * + * @param[in,out] document A document object. + * @param[in] tag The sequence tag. + * @param[in] style The sequence style. + * + * @returns the node id or @c 0 on error. + */ + +YAML_DECLARE(int) +yaml_document_add_sequence(yaml_document_t *document, + yaml_char_t *tag, yaml_sequence_style_t style); + +/** + * Create a MAPPING node and attach it to the document. + * + * The @a style argument may be ignored by the emitter. + * + * @param[in,out] document A document object. + * @param[in] tag The sequence tag. + * @param[in] style The sequence style. + * + * @returns the node id or @c 0 on error. + */ + +YAML_DECLARE(int) +yaml_document_add_mapping(yaml_document_t *document, + yaml_char_t *tag, yaml_mapping_style_t style); + +/** + * Add an item to a SEQUENCE node. + * + * @param[in,out] document A document object. + * @param[in] sequence The sequence node id. + * @param[in] item The item node id. +* + * @returns @c 1 if the function succeeded, @c 0 on error. + */ + +YAML_DECLARE(int) +yaml_document_append_sequence_item(yaml_document_t *document, + int sequence, int item); + +/** + * Add a pair of a key and a value to a MAPPING node. + * + * @param[in,out] document A document object. + * @param[in] mapping The mapping node id. + * @param[in] key The key node id. + * @param[in] value The value node id. +* + * @returns @c 1 if the function succeeded, @c 0 on error. + */ + +YAML_DECLARE(int) +yaml_document_append_mapping_pair(yaml_document_t *document, + int mapping, int key, int value); + +/** @} */ + +/** + * @defgroup parser Parser Definitions + * @{ + */ + +/** + * The prototype of a read handler. + * + * The read handler is called when the parser needs to read more bytes from the + * source. The handler should write not more than @a size bytes to the @a + * buffer. The number of written bytes should be set to the @a length variable. + * + * @param[in,out] data A pointer to an application data specified by + * yaml_parser_set_input(). + * @param[out] buffer The buffer to write the data from the source. + * @param[in] size The size of the buffer. + * @param[out] size_read The actual number of bytes read from the source. + * + * @returns On success, the handler should return @c 1. If the handler failed, + * the returned value should be @c 0. On EOF, the handler should set the + * @a size_read to @c 0 and return @c 1. + */ + +typedef int yaml_read_handler_t(void *data, unsigned char *buffer, size_t size, + size_t *size_read); + +/** + * This structure holds information about a potential simple key. + */ + +typedef struct yaml_simple_key_s { + /** Is a simple key possible? */ + int possible; + + /** Is a simple key required? */ + int required; + + /** The number of the token. */ + size_t token_number; + + /** The position mark. */ + yaml_mark_t mark; +} yaml_simple_key_t; + +/** + * The states of the parser. + */ +typedef enum yaml_parser_state_e { + /** Expect STREAM-START. */ + YAML_PARSE_STREAM_START_STATE, + /** Expect the beginning of an implicit document. */ + YAML_PARSE_IMPLICIT_DOCUMENT_START_STATE, + /** Expect DOCUMENT-START. */ + YAML_PARSE_DOCUMENT_START_STATE, + /** Expect the content of a document. */ + YAML_PARSE_DOCUMENT_CONTENT_STATE, + /** Expect DOCUMENT-END. */ + YAML_PARSE_DOCUMENT_END_STATE, + /** Expect a block node. */ + YAML_PARSE_BLOCK_NODE_STATE, + /** Expect a block node or indentless sequence. */ + YAML_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE, + /** Expect a flow node. */ + YAML_PARSE_FLOW_NODE_STATE, + /** Expect the first entry of a block sequence. */ + YAML_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE, + /** Expect an entry of a block sequence. */ + YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE, + /** Expect an entry of an indentless sequence. */ + YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE, + /** Expect the first key of a block mapping. */ + YAML_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE, + /** Expect a block mapping key. */ + YAML_PARSE_BLOCK_MAPPING_KEY_STATE, + /** Expect a block mapping value. */ + YAML_PARSE_BLOCK_MAPPING_VALUE_STATE, + /** Expect the first entry of a flow sequence. */ + YAML_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE, + /** Expect an entry of a flow sequence. */ + YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE, + /** Expect a key of an ordered mapping. */ + YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE, + /** Expect a value of an ordered mapping. */ + YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE, + /** Expect the and of an ordered mapping entry. */ + YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE, + /** Expect the first key of a flow mapping. */ + YAML_PARSE_FLOW_MAPPING_FIRST_KEY_STATE, + /** Expect a key of a flow mapping. */ + YAML_PARSE_FLOW_MAPPING_KEY_STATE, + /** Expect a value of a flow mapping. */ + YAML_PARSE_FLOW_MAPPING_VALUE_STATE, + /** Expect an empty value of a flow mapping. */ + YAML_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE, + /** Expect nothing. */ + YAML_PARSE_END_STATE +} yaml_parser_state_t; + +/** + * This structure holds aliases data. + */ + +typedef struct yaml_alias_data_s { + /** The anchor. */ + yaml_char_t *anchor; + /** The node id. */ + int index; + /** The anchor mark. */ + yaml_mark_t mark; +} yaml_alias_data_t; + +/** + * The parser structure. + * + * All members are internal. Manage the structure using the @c yaml_parser_ + * family of functions. + */ + +typedef struct yaml_parser_s { + + /** + * @name Error handling + * @{ + */ + + /** Error type. */ + yaml_error_type_t error; + /** Error description. */ + const char *problem; + /** The byte about which the problem occured. */ + size_t problem_offset; + /** The problematic value (@c -1 is none). */ + int problem_value; + /** The problem position. */ + yaml_mark_t problem_mark; + /** The error context. */ + const char *context; + /** The context position. */ + yaml_mark_t context_mark; + + /** + * @} + */ + + /** + * @name Reader stuff + * @{ + */ + + /** Read handler. */ + yaml_read_handler_t *read_handler; + + /** A pointer for passing to the read handler. */ + void *read_handler_data; + + /** Standard (string or file) input data. */ + union { + /** String input data. */ + struct { + /** The string start pointer. */ + const unsigned char *start; + /** The string end pointer. */ + const unsigned char *end; + /** The string current position. */ + const unsigned char *current; + } string; + + /** File input data. */ + FILE *file; + } input; + + /** EOF flag */ + int eof; + + /** The working buffer. */ + struct { + /** The beginning of the buffer. */ + yaml_char_t *start; + /** The end of the buffer. */ + yaml_char_t *end; + /** The current position of the buffer. */ + yaml_char_t *pointer; + /** The last filled position of the buffer. */ + yaml_char_t *last; + } buffer; + + /* The number of unread characters in the buffer. */ + size_t unread; + + /** The raw buffer. */ + struct { + /** The beginning of the buffer. */ + unsigned char *start; + /** The end of the buffer. */ + unsigned char *end; + /** The current position of the buffer. */ + unsigned char *pointer; + /** The last filled position of the buffer. */ + unsigned char *last; + } raw_buffer; + + /** The input encoding. */ + yaml_encoding_t encoding; + + /** The offset of the current position (in bytes). */ + size_t offset; + + /** The mark of the current position. */ + yaml_mark_t mark; + + /** + * @} + */ + + /** + * @name Scanner stuff + * @{ + */ + + /** Have we started to scan the input stream? */ + int stream_start_produced; + + /** Have we reached the end of the input stream? */ + int stream_end_produced; + + /** The number of unclosed '[' and '{' indicators. */ + int flow_level; + + /** The tokens queue. */ + struct { + /** The beginning of the tokens queue. */ + yaml_token_t *start; + /** The end of the tokens queue. */ + yaml_token_t *end; + /** The head of the tokens queue. */ + yaml_token_t *head; + /** The tail of the tokens queue. */ + yaml_token_t *tail; + } tokens; + + /** The number of tokens fetched from the queue. */ + size_t tokens_parsed; + + /* Does the tokens queue contain a token ready for dequeueing. */ + int token_available; + + /** The indentation levels stack. */ + struct { + /** The beginning of the stack. */ + int *start; + /** The end of the stack. */ + int *end; + /** The top of the stack. */ + int *top; + } indents; + + /** The current indentation level. */ + int indent; + + /** May a simple key occur at the current position? */ + int simple_key_allowed; + + /** The stack of simple keys. */ + struct { + /** The beginning of the stack. */ + yaml_simple_key_t *start; + /** The end of the stack. */ + yaml_simple_key_t *end; + /** The top of the stack. */ + yaml_simple_key_t *top; + } simple_keys; + + /** + * @} + */ + + /** + * @name Parser stuff + * @{ + */ + + /** The parser states stack. */ + struct { + /** The beginning of the stack. */ + yaml_parser_state_t *start; + /** The end of the stack. */ + yaml_parser_state_t *end; + /** The top of the stack. */ + yaml_parser_state_t *top; + } states; + + /** The current parser state. */ + yaml_parser_state_t state; + + /** The stack of marks. */ + struct { + /** The beginning of the stack. */ + yaml_mark_t *start; + /** The end of the stack. */ + yaml_mark_t *end; + /** The top of the stack. */ + yaml_mark_t *top; + } marks; + + /** The list of TAG directives. */ + struct { + /** The beginning of the list. */ + yaml_tag_directive_t *start; + /** The end of the list. */ + yaml_tag_directive_t *end; + /** The top of the list. */ + yaml_tag_directive_t *top; + } tag_directives; + + /** + * @} + */ + + /** + * @name Dumper stuff + * @{ + */ + + /** The alias data. */ + struct { + /** The beginning of the list. */ + yaml_alias_data_t *start; + /** The end of the list. */ + yaml_alias_data_t *end; + /** The top of the list. */ + yaml_alias_data_t *top; + } aliases; + + /** The currently parsed document. */ + yaml_document_t *document; + + /** + * @} + */ + +} yaml_parser_t; + +/** + * Initialize a parser. + * + * This function creates a new parser object. An application is responsible + * for destroying the object using the yaml_parser_delete() function. + * + * @param[out] parser An empty parser object. + * + * @returns @c 1 if the function succeeded, @c 0 on error. + */ + +YAML_DECLARE(int) +yaml_parser_initialize(yaml_parser_t *parser); + +/** + * Destroy a parser. + * + * @param[in,out] parser A parser object. + */ + +YAML_DECLARE(void) +yaml_parser_delete(yaml_parser_t *parser); + +/** + * Set a string input. + * + * Note that the @a input pointer must be valid while the @a parser object + * exists. The application is responsible for destroing @a input after + * destroying the @a parser. + * + * @param[in,out] parser A parser object. + * @param[in] input A source data. + * @param[in] size The length of the source data in bytes. + */ + +YAML_DECLARE(void) +yaml_parser_set_input_string(yaml_parser_t *parser, + const unsigned char *input, size_t size); + +/** + * Set a file input. + * + * @a file should be a file object open for reading. The application is + * responsible for closing the @a file. + * + * @param[in,out] parser A parser object. + * @param[in] file An open file. + */ + +YAML_DECLARE(void) +yaml_parser_set_input_file(yaml_parser_t *parser, FILE *file); + +/** + * Set a generic input handler. + * + * @param[in,out] parser A parser object. + * @param[in] handler A read handler. + * @param[in] data Any application data for passing to the read + * handler. + */ + +YAML_DECLARE(void) +yaml_parser_set_input(yaml_parser_t *parser, + yaml_read_handler_t *handler, void *data); + +/** + * Set the source encoding. + * + * @param[in,out] parser A parser object. + * @param[in] encoding The source encoding. + */ + +YAML_DECLARE(void) +yaml_parser_set_encoding(yaml_parser_t *parser, yaml_encoding_t encoding); + +/** + * Scan the input stream and produce the next token. + * + * Call the function subsequently to produce a sequence of tokens corresponding + * to the input stream. The initial token has the type + * @c YAML_STREAM_START_TOKEN while the ending token has the type + * @c YAML_STREAM_END_TOKEN. + * + * An application is responsible for freeing any buffers associated with the + * produced token object using the @c yaml_token_delete function. + * + * An application must not alternate the calls of yaml_parser_scan() with the + * calls of yaml_parser_parse() or yaml_parser_load(). Doing this will break + * the parser. + * + * @param[in,out] parser A parser object. + * @param[out] token An empty token object. + * + * @returns @c 1 if the function succeeded, @c 0 on error. + */ + +YAML_DECLARE(int) +yaml_parser_scan(yaml_parser_t *parser, yaml_token_t *token); + +/** + * Parse the input stream and produce the next parsing event. + * + * Call the function subsequently to produce a sequence of events corresponding + * to the input stream. The initial event has the type + * @c YAML_STREAM_START_EVENT while the ending event has the type + * @c YAML_STREAM_END_EVENT. + * + * An application is responsible for freeing any buffers associated with the + * produced event object using the yaml_event_delete() function. + * + * An application must not alternate the calls of yaml_parser_parse() with the + * calls of yaml_parser_scan() or yaml_parser_load(). Doing this will break the + * parser. + * + * @param[in,out] parser A parser object. + * @param[out] event An empty event object. + * + * @returns @c 1 if the function succeeded, @c 0 on error. + */ + +YAML_DECLARE(int) +yaml_parser_parse(yaml_parser_t *parser, yaml_event_t *event); + +/** + * Parse the input stream and produce the next YAML document. + * + * Call this function subsequently to produce a sequence of documents + * constituting the input stream. + * + * If the produced document has no root node, it means that the document + * end has been reached. + * + * An application is responsible for freeing any data associated with the + * produced document object using the yaml_document_delete() function. + * + * An application must not alternate the calls of yaml_parser_load() with the + * calls of yaml_parser_scan() or yaml_parser_parse(). Doing this will break + * the parser. + * + * @param[in,out] parser A parser object. + * @param[out] document An empty document object. + * + * @return @c 1 if the function succeeded, @c 0 on error. + */ + +YAML_DECLARE(int) +yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document); + +/** @} */ + +/** + * @defgroup emitter Emitter Definitions + * @{ + */ + +/** + * The prototype of a write handler. + * + * The write handler is called when the emitter needs to flush the accumulated + * characters to the output. The handler should write @a size bytes of the + * @a buffer to the output. + * + * @param[in,out] data A pointer to an application data specified by + * yaml_emitter_set_output(). + * @param[in] buffer The buffer with bytes to be written. + * @param[in] size The size of the buffer. + * + * @returns On success, the handler should return @c 1. If the handler failed, + * the returned value should be @c 0. + */ + +typedef int yaml_write_handler_t(void *data, unsigned char *buffer, size_t size); + +/** The emitter states. */ +typedef enum yaml_emitter_state_e { + /** Expect STREAM-START. */ + YAML_EMIT_STREAM_START_STATE, + /** Expect the first DOCUMENT-START or STREAM-END. */ + YAML_EMIT_FIRST_DOCUMENT_START_STATE, + /** Expect DOCUMENT-START or STREAM-END. */ + YAML_EMIT_DOCUMENT_START_STATE, + /** Expect the content of a document. */ + YAML_EMIT_DOCUMENT_CONTENT_STATE, + /** Expect DOCUMENT-END. */ + YAML_EMIT_DOCUMENT_END_STATE, + /** Expect the first item of a flow sequence. */ + YAML_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE, + /** Expect an item of a flow sequence. */ + YAML_EMIT_FLOW_SEQUENCE_ITEM_STATE, + /** Expect the first key of a flow mapping. */ + YAML_EMIT_FLOW_MAPPING_FIRST_KEY_STATE, + /** Expect a key of a flow mapping. */ + YAML_EMIT_FLOW_MAPPING_KEY_STATE, + /** Expect a value for a simple key of a flow mapping. */ + YAML_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE, + /** Expect a value of a flow mapping. */ + YAML_EMIT_FLOW_MAPPING_VALUE_STATE, + /** Expect the first item of a block sequence. */ + YAML_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE, + /** Expect an item of a block sequence. */ + YAML_EMIT_BLOCK_SEQUENCE_ITEM_STATE, + /** Expect the first key of a block mapping. */ + YAML_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE, + /** Expect the key of a block mapping. */ + YAML_EMIT_BLOCK_MAPPING_KEY_STATE, + /** Expect a value for a simple key of a block mapping. */ + YAML_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE, + /** Expect a value of a block mapping. */ + YAML_EMIT_BLOCK_MAPPING_VALUE_STATE, + /** Expect nothing. */ + YAML_EMIT_END_STATE +} yaml_emitter_state_t; + +/** + * The emitter structure. + * + * All members are internal. Manage the structure using the @c yaml_emitter_ + * family of functions. + */ + +typedef struct yaml_emitter_s { + + /** + * @name Error handling + * @{ + */ + + /** Error type. */ + yaml_error_type_t error; + /** Error description. */ + const char *problem; + + /** + * @} + */ + + /** + * @name Writer stuff + * @{ + */ + + /** Write handler. */ + yaml_write_handler_t *write_handler; + + /** A pointer for passing to the white handler. */ + void *write_handler_data; + + /** Standard (string or file) output data. */ + union { + /** String output data. */ + struct { + /** The buffer pointer. */ + unsigned char *buffer; + /** The buffer size. */ + size_t size; + /** The number of written bytes. */ + size_t *size_written; + } string; + + /** File output data. */ + FILE *file; + } output; + + /** The working buffer. */ + struct { + /** The beginning of the buffer. */ + yaml_char_t *start; + /** The end of the buffer. */ + yaml_char_t *end; + /** The current position of the buffer. */ + yaml_char_t *pointer; + /** The last filled position of the buffer. */ + yaml_char_t *last; + } buffer; + + /** The raw buffer. */ + struct { + /** The beginning of the buffer. */ + unsigned char *start; + /** The end of the buffer. */ + unsigned char *end; + /** The current position of the buffer. */ + unsigned char *pointer; + /** The last filled position of the buffer. */ + unsigned char *last; + } raw_buffer; + + /** The stream encoding. */ + yaml_encoding_t encoding; + + /** + * @} + */ + + /** + * @name Emitter stuff + * @{ + */ + + /** If the output is in the canonical style? */ + int canonical; + /** The number of indentation spaces. */ + int best_indent; + /** The preferred width of the output lines. */ + int best_width; + /** Allow unescaped non-ASCII characters? */ + int unicode; + /** The preferred line break. */ + yaml_break_t line_break; + + /** The stack of states. */ + struct { + /** The beginning of the stack. */ + yaml_emitter_state_t *start; + /** The end of the stack. */ + yaml_emitter_state_t *end; + /** The top of the stack. */ + yaml_emitter_state_t *top; + } states; + + /** The current emitter state. */ + yaml_emitter_state_t state; + + /** The event queue. */ + struct { + /** The beginning of the event queue. */ + yaml_event_t *start; + /** The end of the event queue. */ + yaml_event_t *end; + /** The head of the event queue. */ + yaml_event_t *head; + /** The tail of the event queue. */ + yaml_event_t *tail; + } events; + + /** The stack of indentation levels. */ + struct { + /** The beginning of the stack. */ + int *start; + /** The end of the stack. */ + int *end; + /** The top of the stack. */ + int *top; + } indents; + + /** The list of tag directives. */ + struct { + /** The beginning of the list. */ + yaml_tag_directive_t *start; + /** The end of the list. */ + yaml_tag_directive_t *end; + /** The top of the list. */ + yaml_tag_directive_t *top; + } tag_directives; + + /** The current indentation level. */ + int indent; + + /** The current flow level. */ + int flow_level; + + /** Is it the document root context? */ + int root_context; + /** Is it a sequence context? */ + int sequence_context; + /** Is it a mapping context? */ + int mapping_context; + /** Is it a simple mapping key context? */ + int simple_key_context; + + /** The current line. */ + int line; + /** The current column. */ + int column; + /** If the last character was a whitespace? */ + int whitespace; + /** If the last character was an indentation character (' ', '-', '?', ':')? */ + int indention; + /** If an explicit document end is required? */ + int open_ended; + + /** Anchor analysis. */ + struct { + /** The anchor value. */ + yaml_char_t *anchor; + /** The anchor length. */ + size_t anchor_length; + /** Is it an alias? */ + int alias; + } anchor_data; + + /** Tag analysis. */ + struct { + /** The tag handle. */ + yaml_char_t *handle; + /** The tag handle length. */ + size_t handle_length; + /** The tag suffix. */ + yaml_char_t *suffix; + /** The tag suffix length. */ + size_t suffix_length; + } tag_data; + + /** Scalar analysis. */ + struct { + /** The scalar value. */ + yaml_char_t *value; + /** The scalar length. */ + size_t length; + /** Does the scalar contain line breaks? */ + int multiline; + /** Can the scalar be expessed in the flow plain style? */ + int flow_plain_allowed; + /** Can the scalar be expressed in the block plain style? */ + int block_plain_allowed; + /** Can the scalar be expressed in the single quoted style? */ + int single_quoted_allowed; + /** Can the scalar be expressed in the literal or folded styles? */ + int block_allowed; + /** The output style. */ + yaml_scalar_style_t style; + } scalar_data; + + /** + * @} + */ + + /** + * @name Dumper stuff + * @{ + */ + + /** If the stream was already opened? */ + int opened; + /** If the stream was already closed? */ + int closed; + + /** The information associated with the document nodes. */ + struct { + /** The number of references. */ + int references; + /** The anchor id. */ + int anchor; + /** If the node has been emitted? */ + int serialized; + } *anchors; + + /** The last assigned anchor id. */ + int last_anchor_id; + + /** The currently emitted document. */ + yaml_document_t *document; + + /** + * @} + */ + +} yaml_emitter_t; + +/** + * Initialize an emitter. + * + * This function creates a new emitter object. An application is responsible + * for destroying the object using the yaml_emitter_delete() function. + * + * @param[out] emitter An empty parser object. + * + * @returns @c 1 if the function succeeded, @c 0 on error. + */ + +YAML_DECLARE(int) +yaml_emitter_initialize(yaml_emitter_t *emitter); + +/** + * Destroy an emitter. + * + * @param[in,out] emitter An emitter object. + */ + +YAML_DECLARE(void) +yaml_emitter_delete(yaml_emitter_t *emitter); + +/** + * Set a string output. + * + * The emitter will write the output characters to the @a output buffer of the + * size @a size. The emitter will set @a size_written to the number of written + * bytes. If the buffer is smaller than required, the emitter produces the + * YAML_WRITE_ERROR error. + * + * @param[in,out] emitter An emitter object. + * @param[in] output An output buffer. + * @param[in] size The buffer size. + * @param[in] size_written The pointer to save the number of written + * bytes. + */ + +YAML_DECLARE(void) +yaml_emitter_set_output_string(yaml_emitter_t *emitter, + unsigned char *output, size_t size, size_t *size_written); + +/** + * Set a file output. + * + * @a file should be a file object open for writing. The application is + * responsible for closing the @a file. + * + * @param[in,out] emitter An emitter object. + * @param[in] file An open file. + */ + +YAML_DECLARE(void) +yaml_emitter_set_output_file(yaml_emitter_t *emitter, FILE *file); + +/** + * Set a generic output handler. + * + * @param[in,out] emitter An emitter object. + * @param[in] handler A write handler. + * @param[in] data Any application data for passing to the write + * handler. + */ + +YAML_DECLARE(void) +yaml_emitter_set_output(yaml_emitter_t *emitter, + yaml_write_handler_t *handler, void *data); + +/** + * Set the output encoding. + * + * @param[in,out] emitter An emitter object. + * @param[in] encoding The output encoding. + */ + +YAML_DECLARE(void) +yaml_emitter_set_encoding(yaml_emitter_t *emitter, yaml_encoding_t encoding); + +/** + * Set if the output should be in the "canonical" format as in the YAML + * specification. + * + * @param[in,out] emitter An emitter object. + * @param[in] canonical If the output is canonical. + */ + +YAML_DECLARE(void) +yaml_emitter_set_canonical(yaml_emitter_t *emitter, int canonical); + +/** + * Set the intendation increment. + * + * @param[in,out] emitter An emitter object. + * @param[in] indent The indentation increment (1 < . < 10). + */ + +YAML_DECLARE(void) +yaml_emitter_set_indent(yaml_emitter_t *emitter, int indent); + +/** + * Set the preferred line width. @c -1 means unlimited. + * + * @param[in,out] emitter An emitter object. + * @param[in] width The preferred line width. + */ + +YAML_DECLARE(void) +yaml_emitter_set_width(yaml_emitter_t *emitter, int width); + +/** + * Set if unescaped non-ASCII characters are allowed. + * + * @param[in,out] emitter An emitter object. + * @param[in] unicode If unescaped Unicode characters are allowed. + */ + +YAML_DECLARE(void) +yaml_emitter_set_unicode(yaml_emitter_t *emitter, int unicode); + +/** + * Set the preferred line break. + * + * @param[in,out] emitter An emitter object. + * @param[in] line_break The preferred line break. + */ + +YAML_DECLARE(void) +yaml_emitter_set_break(yaml_emitter_t *emitter, yaml_break_t line_break); + +/** + * Emit an event. + * + * The event object may be generated using the yaml_parser_parse() function. + * The emitter takes the responsibility for the event object and destroys its + * content after it is emitted. The event object is destroyed even if the + * function fails. + * + * @param[in,out] emitter An emitter object. + * @param[in,out] event An event object. + * + * @returns @c 1 if the function succeeded, @c 0 on error. + */ + +YAML_DECLARE(int) +yaml_emitter_emit(yaml_emitter_t *emitter, yaml_event_t *event); + +/** + * Start a YAML stream. + * + * This function should be used before yaml_emitter_dump() is called. + * + * @param[in,out] emitter An emitter object. + * + * @returns @c 1 if the function succeeded, @c 0 on error. + */ + +YAML_DECLARE(int) +yaml_emitter_open(yaml_emitter_t *emitter); + +/** + * Finish a YAML stream. + * + * This function should be used after yaml_emitter_dump() is called. + * + * @param[in,out] emitter An emitter object. + * + * @returns @c 1 if the function succeeded, @c 0 on error. + */ + +YAML_DECLARE(int) +yaml_emitter_close(yaml_emitter_t *emitter); + +/** + * Emit a YAML document. + * + * The documen object may be generated using the yaml_parser_load() function + * or the yaml_document_initialize() function. The emitter takes the + * responsibility for the document object and destoys its content after + * it is emitted. The document object is destroyedeven if the function fails. + * + * @param[in,out] emitter An emitter object. + * @param[in,out] document A document object. + * + * @returns @c 1 if the function succeeded, @c 0 on error. + */ + +YAML_DECLARE(int) +yaml_emitter_dump(yaml_emitter_t *emitter, yaml_document_t *document); + +/** + * Flush the accumulated characters to the output. + * + * @param[in,out] emitter An emitter object. + * + * @returns @c 1 if the function succeeded, @c 0 on error. + */ + +YAML_DECLARE(int) +yaml_emitter_flush(yaml_emitter_t *emitter); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef YAML_H */ + diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 00000000000..724a1b2db82 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,4 @@ +AM_CPPFLAGS = -I$(top_srcdir)/include +lib_LTLIBRARIES = libyaml.la +libyaml_la_SOURCES = yaml_private.h api.c reader.c scanner.c parser.c loader.c writer.c emitter.c dumper.c +libyaml_la_LDFLAGS = -release $(YAML_LT_RELEASE) -version-info $(YAML_LT_CURRENT):$(YAML_LT_REVISION):$(YAML_LT_AGE) diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 00000000000..50e37372939 --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,529 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(libdir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +libyaml_la_LIBADD = +am_libyaml_la_OBJECTS = api.lo reader.lo scanner.lo parser.lo \ + loader.lo writer.lo emitter.lo dumper.lo +libyaml_la_OBJECTS = $(am_libyaml_la_OBJECTS) +libyaml_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libyaml_la_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/config/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libyaml_la_SOURCES) +DIST_SOURCES = $(libyaml_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YAML_LT_AGE = @YAML_LT_AGE@ +YAML_LT_CURRENT = @YAML_LT_CURRENT@ +YAML_LT_RELEASE = @YAML_LT_RELEASE@ +YAML_LT_REVISION = @YAML_LT_REVISION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_CPPFLAGS = -I$(top_srcdir)/include +lib_LTLIBRARIES = libyaml.la +libyaml_la_SOURCES = yaml_private.h api.c reader.c scanner.c parser.c loader.c writer.c emitter.c dumper.c +libyaml_la_LDFLAGS = -release $(YAML_LT_RELEASE) -version-info $(YAML_LT_CURRENT):$(YAML_LT_REVISION):$(YAML_LT_AGE) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libyaml.la: $(libyaml_la_OBJECTS) $(libyaml_la_DEPENDENCIES) + $(libyaml_la_LINK) -rpath $(libdir) $(libyaml_la_OBJECTS) $(libyaml_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/api.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dumper.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emitter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/loader.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reader.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scanner.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/writer.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(libdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-libLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libLTLIBRARIES clean-libtool ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am \ + install-libLTLIBRARIES install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-libLTLIBRARIES + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/api.c b/src/api.c new file mode 100644 index 00000000000..0c4732e1520 --- /dev/null +++ b/src/api.c @@ -0,0 +1,1392 @@ + +#include "yaml_private.h" + +/* + * Get the library version. + */ + +YAML_DECLARE(const char *) +yaml_get_version_string(void) +{ + return YAML_VERSION_STRING; +} + +/* + * Get the library version numbers. + */ + +YAML_DECLARE(void) +yaml_get_version(int *major, int *minor, int *patch) +{ + *major = YAML_VERSION_MAJOR; + *minor = YAML_VERSION_MINOR; + *patch = YAML_VERSION_PATCH; +} + +/* + * Allocate a dynamic memory block. + */ + +YAML_DECLARE(void *) +yaml_malloc(size_t size) +{ + return malloc(size ? size : 1); +} + +/* + * Reallocate a dynamic memory block. + */ + +YAML_DECLARE(void *) +yaml_realloc(void *ptr, size_t size) +{ + return ptr ? realloc(ptr, size ? size : 1) : malloc(size ? size : 1); +} + +/* + * Free a dynamic memory block. + */ + +YAML_DECLARE(void) +yaml_free(void *ptr) +{ + if (ptr) free(ptr); +} + +/* + * Duplicate a string. + */ + +YAML_DECLARE(yaml_char_t *) +yaml_strdup(const yaml_char_t *str) +{ + if (!str) + return NULL; + + return (yaml_char_t *)strdup((char *)str); +} + +/* + * Extend a string. + */ + +YAML_DECLARE(int) +yaml_string_extend(yaml_char_t **start, + yaml_char_t **pointer, yaml_char_t **end) +{ + yaml_char_t *new_start = yaml_realloc(*start, (*end - *start)*2); + + if (!new_start) return 0; + + memset(new_start + (*end - *start), 0, *end - *start); + + *pointer = new_start + (*pointer - *start); + *end = new_start + (*end - *start)*2; + *start = new_start; + + return 1; +} + +/* + * Append a string B to a string A. + */ + +YAML_DECLARE(int) +yaml_string_join( + yaml_char_t **a_start, yaml_char_t **a_pointer, yaml_char_t **a_end, + yaml_char_t **b_start, yaml_char_t **b_pointer, yaml_char_t **b_end) +{ + if (*b_start == *b_pointer) + return 1; + + while (*a_end - *a_pointer <= *b_pointer - *b_start) { + if (!yaml_string_extend(a_start, a_pointer, a_end)) + return 0; + } + + memcpy(*a_pointer, *b_start, *b_pointer - *b_start); + *a_pointer += *b_pointer - *b_start; + + return 1; +} + +/* + * Extend a stack. + */ + +YAML_DECLARE(int) +yaml_stack_extend(void **start, void **top, void **end) +{ + void *new_start = yaml_realloc(*start, ((char *)*end - (char *)*start)*2); + + if (!new_start) return 0; + + *top = (char *)new_start + ((char *)*top - (char *)*start); + *end = (char *)new_start + ((char *)*end - (char *)*start)*2; + *start = new_start; + + return 1; +} + +/* + * Extend or move a queue. + */ + +YAML_DECLARE(int) +yaml_queue_extend(void **start, void **head, void **tail, void **end) +{ + /* Check if we need to resize the queue. */ + + if (*start == *head && *tail == *end) { + void *new_start = yaml_realloc(*start, + ((char *)*end - (char *)*start)*2); + + if (!new_start) return 0; + + *head = (char *)new_start + ((char *)*head - (char *)*start); + *tail = (char *)new_start + ((char *)*tail - (char *)*start); + *end = (char *)new_start + ((char *)*end - (char *)*start)*2; + *start = new_start; + } + + /* Check if we need to move the queue at the beginning of the buffer. */ + + if (*tail == *end) { + if (*head != *tail) { + memmove(*start, *head, (char *)*tail - (char *)*head); + } + *tail = (char *)*tail - (char *)*head + (char *)*start; + *head = *start; + } + + return 1; +} + + +/* + * Create a new parser object. + */ + +YAML_DECLARE(int) +yaml_parser_initialize(yaml_parser_t *parser) +{ + assert(parser); /* Non-NULL parser object expected. */ + + memset(parser, 0, sizeof(yaml_parser_t)); + if (!BUFFER_INIT(parser, parser->raw_buffer, INPUT_RAW_BUFFER_SIZE)) + goto error; + if (!BUFFER_INIT(parser, parser->buffer, INPUT_BUFFER_SIZE)) + goto error; + if (!QUEUE_INIT(parser, parser->tokens, INITIAL_QUEUE_SIZE)) + goto error; + if (!STACK_INIT(parser, parser->indents, INITIAL_STACK_SIZE)) + goto error; + if (!STACK_INIT(parser, parser->simple_keys, INITIAL_STACK_SIZE)) + goto error; + if (!STACK_INIT(parser, parser->states, INITIAL_STACK_SIZE)) + goto error; + if (!STACK_INIT(parser, parser->marks, INITIAL_STACK_SIZE)) + goto error; + if (!STACK_INIT(parser, parser->tag_directives, INITIAL_STACK_SIZE)) + goto error; + + return 1; + +error: + + BUFFER_DEL(parser, parser->raw_buffer); + BUFFER_DEL(parser, parser->buffer); + QUEUE_DEL(parser, parser->tokens); + STACK_DEL(parser, parser->indents); + STACK_DEL(parser, parser->simple_keys); + STACK_DEL(parser, parser->states); + STACK_DEL(parser, parser->marks); + STACK_DEL(parser, parser->tag_directives); + + return 0; +} + +/* + * Destroy a parser object. + */ + +YAML_DECLARE(void) +yaml_parser_delete(yaml_parser_t *parser) +{ + assert(parser); /* Non-NULL parser object expected. */ + + BUFFER_DEL(parser, parser->raw_buffer); + BUFFER_DEL(parser, parser->buffer); + while (!QUEUE_EMPTY(parser, parser->tokens)) { + yaml_token_delete(&DEQUEUE(parser, parser->tokens)); + } + QUEUE_DEL(parser, parser->tokens); + STACK_DEL(parser, parser->indents); + STACK_DEL(parser, parser->simple_keys); + STACK_DEL(parser, parser->states); + STACK_DEL(parser, parser->marks); + while (!STACK_EMPTY(parser, parser->tag_directives)) { + yaml_tag_directive_t tag_directive = POP(parser, parser->tag_directives); + yaml_free(tag_directive.handle); + yaml_free(tag_directive.prefix); + } + STACK_DEL(parser, parser->tag_directives); + + memset(parser, 0, sizeof(yaml_parser_t)); +} + +/* + * String read handler. + */ + +static int +yaml_string_read_handler(void *data, unsigned char *buffer, size_t size, + size_t *size_read) +{ + yaml_parser_t *parser = data; + + if (parser->input.string.current == parser->input.string.end) { + *size_read = 0; + return 1; + } + + if (size > (size_t)(parser->input.string.end + - parser->input.string.current)) { + size = parser->input.string.end - parser->input.string.current; + } + + memcpy(buffer, parser->input.string.current, size); + parser->input.string.current += size; + *size_read = size; + return 1; +} + +/* + * File read handler. + */ + +static int +yaml_file_read_handler(void *data, unsigned char *buffer, size_t size, + size_t *size_read) +{ + yaml_parser_t *parser = data; + + *size_read = fread(buffer, 1, size, parser->input.file); + return !ferror(parser->input.file); +} + +/* + * Set a string input. + */ + +YAML_DECLARE(void) +yaml_parser_set_input_string(yaml_parser_t *parser, + const unsigned char *input, size_t size) +{ + assert(parser); /* Non-NULL parser object expected. */ + assert(!parser->read_handler); /* You can set the source only once. */ + assert(input); /* Non-NULL input string expected. */ + + parser->read_handler = yaml_string_read_handler; + parser->read_handler_data = parser; + + parser->input.string.start = input; + parser->input.string.current = input; + parser->input.string.end = input+size; +} + +/* + * Set a file input. + */ + +YAML_DECLARE(void) +yaml_parser_set_input_file(yaml_parser_t *parser, FILE *file) +{ + assert(parser); /* Non-NULL parser object expected. */ + assert(!parser->read_handler); /* You can set the source only once. */ + assert(file); /* Non-NULL file object expected. */ + + parser->read_handler = yaml_file_read_handler; + parser->read_handler_data = parser; + + parser->input.file = file; +} + +/* + * Set a generic input. + */ + +YAML_DECLARE(void) +yaml_parser_set_input(yaml_parser_t *parser, + yaml_read_handler_t *handler, void *data) +{ + assert(parser); /* Non-NULL parser object expected. */ + assert(!parser->read_handler); /* You can set the source only once. */ + assert(handler); /* Non-NULL read handler expected. */ + + parser->read_handler = handler; + parser->read_handler_data = data; +} + +/* + * Set the source encoding. + */ + +YAML_DECLARE(void) +yaml_parser_set_encoding(yaml_parser_t *parser, yaml_encoding_t encoding) +{ + assert(parser); /* Non-NULL parser object expected. */ + assert(!parser->encoding); /* Encoding is already set or detected. */ + + parser->encoding = encoding; +} + +/* + * Create a new emitter object. + */ + +YAML_DECLARE(int) +yaml_emitter_initialize(yaml_emitter_t *emitter) +{ + assert(emitter); /* Non-NULL emitter object expected. */ + + memset(emitter, 0, sizeof(yaml_emitter_t)); + if (!BUFFER_INIT(emitter, emitter->buffer, OUTPUT_BUFFER_SIZE)) + goto error; + if (!BUFFER_INIT(emitter, emitter->raw_buffer, OUTPUT_RAW_BUFFER_SIZE)) + goto error; + if (!STACK_INIT(emitter, emitter->states, INITIAL_STACK_SIZE)) + goto error; + if (!QUEUE_INIT(emitter, emitter->events, INITIAL_QUEUE_SIZE)) + goto error; + if (!STACK_INIT(emitter, emitter->indents, INITIAL_STACK_SIZE)) + goto error; + if (!STACK_INIT(emitter, emitter->tag_directives, INITIAL_STACK_SIZE)) + goto error; + + return 1; + +error: + + BUFFER_DEL(emitter, emitter->buffer); + BUFFER_DEL(emitter, emitter->raw_buffer); + STACK_DEL(emitter, emitter->states); + QUEUE_DEL(emitter, emitter->events); + STACK_DEL(emitter, emitter->indents); + STACK_DEL(emitter, emitter->tag_directives); + + return 0; +} + +/* + * Destroy an emitter object. + */ + +YAML_DECLARE(void) +yaml_emitter_delete(yaml_emitter_t *emitter) +{ + assert(emitter); /* Non-NULL emitter object expected. */ + + BUFFER_DEL(emitter, emitter->buffer); + BUFFER_DEL(emitter, emitter->raw_buffer); + STACK_DEL(emitter, emitter->states); + while (!QUEUE_EMPTY(emitter, emitter->events)) { + yaml_event_delete(&DEQUEUE(emitter, emitter->events)); + } + QUEUE_DEL(emitter, emitter->events); + STACK_DEL(emitter, emitter->indents); + while (!STACK_EMPTY(empty, emitter->tag_directives)) { + yaml_tag_directive_t tag_directive = POP(emitter, emitter->tag_directives); + yaml_free(tag_directive.handle); + yaml_free(tag_directive.prefix); + } + STACK_DEL(emitter, emitter->tag_directives); + yaml_free(emitter->anchors); + + memset(emitter, 0, sizeof(yaml_emitter_t)); +} + +/* + * String write handler. + */ + +static int +yaml_string_write_handler(void *data, unsigned char *buffer, size_t size) +{ + yaml_emitter_t *emitter = data; + + if (emitter->output.string.size + *emitter->output.string.size_written + < size) { + memcpy(emitter->output.string.buffer + + *emitter->output.string.size_written, + buffer, + emitter->output.string.size + - *emitter->output.string.size_written); + *emitter->output.string.size_written = emitter->output.string.size; + return 0; + } + + memcpy(emitter->output.string.buffer + + *emitter->output.string.size_written, buffer, size); + *emitter->output.string.size_written += size; + return 1; +} + +/* + * File write handler. + */ + +static int +yaml_file_write_handler(void *data, unsigned char *buffer, size_t size) +{ + yaml_emitter_t *emitter = data; + + return (fwrite(buffer, 1, size, emitter->output.file) == size); +} +/* + * Set a string output. + */ + +YAML_DECLARE(void) +yaml_emitter_set_output_string(yaml_emitter_t *emitter, + unsigned char *output, size_t size, size_t *size_written) +{ + assert(emitter); /* Non-NULL emitter object expected. */ + assert(!emitter->write_handler); /* You can set the output only once. */ + assert(output); /* Non-NULL output string expected. */ + + emitter->write_handler = yaml_string_write_handler; + emitter->write_handler_data = emitter; + + emitter->output.string.buffer = output; + emitter->output.string.size = size; + emitter->output.string.size_written = size_written; + *size_written = 0; +} + +/* + * Set a file output. + */ + +YAML_DECLARE(void) +yaml_emitter_set_output_file(yaml_emitter_t *emitter, FILE *file) +{ + assert(emitter); /* Non-NULL emitter object expected. */ + assert(!emitter->write_handler); /* You can set the output only once. */ + assert(file); /* Non-NULL file object expected. */ + + emitter->write_handler = yaml_file_write_handler; + emitter->write_handler_data = emitter; + + emitter->output.file = file; +} + +/* + * Set a generic output handler. + */ + +YAML_DECLARE(void) +yaml_emitter_set_output(yaml_emitter_t *emitter, + yaml_write_handler_t *handler, void *data) +{ + assert(emitter); /* Non-NULL emitter object expected. */ + assert(!emitter->write_handler); /* You can set the output only once. */ + assert(handler); /* Non-NULL handler object expected. */ + + emitter->write_handler = handler; + emitter->write_handler_data = data; +} + +/* + * Set the output encoding. + */ + +YAML_DECLARE(void) +yaml_emitter_set_encoding(yaml_emitter_t *emitter, yaml_encoding_t encoding) +{ + assert(emitter); /* Non-NULL emitter object expected. */ + assert(!emitter->encoding); /* You can set encoding only once. */ + + emitter->encoding = encoding; +} + +/* + * Set the canonical output style. + */ + +YAML_DECLARE(void) +yaml_emitter_set_canonical(yaml_emitter_t *emitter, int canonical) +{ + assert(emitter); /* Non-NULL emitter object expected. */ + + emitter->canonical = (canonical != 0); +} + +/* + * Set the indentation increment. + */ + +YAML_DECLARE(void) +yaml_emitter_set_indent(yaml_emitter_t *emitter, int indent) +{ + assert(emitter); /* Non-NULL emitter object expected. */ + + emitter->best_indent = (1 < indent && indent < 10) ? indent : 2; +} + +/* + * Set the preferred line width. + */ + +YAML_DECLARE(void) +yaml_emitter_set_width(yaml_emitter_t *emitter, int width) +{ + assert(emitter); /* Non-NULL emitter object expected. */ + + emitter->best_width = (width >= 0) ? width : -1; +} + +/* + * Set if unescaped non-ASCII characters are allowed. + */ + +YAML_DECLARE(void) +yaml_emitter_set_unicode(yaml_emitter_t *emitter, int unicode) +{ + assert(emitter); /* Non-NULL emitter object expected. */ + + emitter->unicode = (unicode != 0); +} + +/* + * Set the preferred line break character. + */ + +YAML_DECLARE(void) +yaml_emitter_set_break(yaml_emitter_t *emitter, yaml_break_t line_break) +{ + assert(emitter); /* Non-NULL emitter object expected. */ + + emitter->line_break = line_break; +} + +/* + * Destroy a token object. + */ + +YAML_DECLARE(void) +yaml_token_delete(yaml_token_t *token) +{ + assert(token); /* Non-NULL token object expected. */ + + switch (token->type) + { + case YAML_TAG_DIRECTIVE_TOKEN: + yaml_free(token->data.tag_directive.handle); + yaml_free(token->data.tag_directive.prefix); + break; + + case YAML_ALIAS_TOKEN: + yaml_free(token->data.alias.value); + break; + + case YAML_ANCHOR_TOKEN: + yaml_free(token->data.anchor.value); + break; + + case YAML_TAG_TOKEN: + yaml_free(token->data.tag.handle); + yaml_free(token->data.tag.suffix); + break; + + case YAML_SCALAR_TOKEN: + yaml_free(token->data.scalar.value); + break; + + default: + break; + } + + memset(token, 0, sizeof(yaml_token_t)); +} + +/* + * Check if a string is a valid UTF-8 sequence. + * + * Check 'reader.c' for more details on UTF-8 encoding. + */ + +static int +yaml_check_utf8(yaml_char_t *start, size_t length) +{ + yaml_char_t *end = start+length; + yaml_char_t *pointer = start; + + while (pointer < end) { + unsigned char octet; + unsigned int width; + unsigned int value; + size_t k; + + octet = pointer[0]; + width = (octet & 0x80) == 0x00 ? 1 : + (octet & 0xE0) == 0xC0 ? 2 : + (octet & 0xF0) == 0xE0 ? 3 : + (octet & 0xF8) == 0xF0 ? 4 : 0; + value = (octet & 0x80) == 0x00 ? octet & 0x7F : + (octet & 0xE0) == 0xC0 ? octet & 0x1F : + (octet & 0xF0) == 0xE0 ? octet & 0x0F : + (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0; + if (!width) return 0; + if (pointer+width > end) return 0; + for (k = 1; k < width; k ++) { + octet = pointer[k]; + if ((octet & 0xC0) != 0x80) return 0; + value = (value << 6) + (octet & 0x3F); + } + if (!((width == 1) || + (width == 2 && value >= 0x80) || + (width == 3 && value >= 0x800) || + (width == 4 && value >= 0x10000))) return 0; + + pointer += width; + } + + return 1; +} + +/* + * Create STREAM-START. + */ + +YAML_DECLARE(int) +yaml_stream_start_event_initialize(yaml_event_t *event, + yaml_encoding_t encoding) +{ + yaml_mark_t mark = { 0, 0, 0 }; + + assert(event); /* Non-NULL event object is expected. */ + + STREAM_START_EVENT_INIT(*event, encoding, mark, mark); + + return 1; +} + +/* + * Create STREAM-END. + */ + +YAML_DECLARE(int) +yaml_stream_end_event_initialize(yaml_event_t *event) +{ + yaml_mark_t mark = { 0, 0, 0 }; + + assert(event); /* Non-NULL event object is expected. */ + + STREAM_END_EVENT_INIT(*event, mark, mark); + + return 1; +} + +/* + * Create DOCUMENT-START. + */ + +YAML_DECLARE(int) +yaml_document_start_event_initialize(yaml_event_t *event, + yaml_version_directive_t *version_directive, + yaml_tag_directive_t *tag_directives_start, + yaml_tag_directive_t *tag_directives_end, + int implicit) +{ + struct { + yaml_error_type_t error; + } context; + yaml_mark_t mark = { 0, 0, 0 }; + yaml_version_directive_t *version_directive_copy = NULL; + struct { + yaml_tag_directive_t *start; + yaml_tag_directive_t *end; + yaml_tag_directive_t *top; + } tag_directives_copy = { NULL, NULL, NULL }; + yaml_tag_directive_t value = { NULL, NULL }; + + assert(event); /* Non-NULL event object is expected. */ + assert((tag_directives_start && tag_directives_end) || + (tag_directives_start == tag_directives_end)); + /* Valid tag directives are expected. */ + + if (version_directive) { + version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t)); + if (!version_directive_copy) goto error; + version_directive_copy->major = version_directive->major; + version_directive_copy->minor = version_directive->minor; + } + + if (tag_directives_start != tag_directives_end) { + yaml_tag_directive_t *tag_directive; + if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE)) + goto error; + for (tag_directive = tag_directives_start; + tag_directive != tag_directives_end; tag_directive ++) { + assert(tag_directive->handle); + assert(tag_directive->prefix); + if (!yaml_check_utf8(tag_directive->handle, + strlen((char *)tag_directive->handle))) + goto error; + if (!yaml_check_utf8(tag_directive->prefix, + strlen((char *)tag_directive->prefix))) + goto error; + value.handle = yaml_strdup(tag_directive->handle); + value.prefix = yaml_strdup(tag_directive->prefix); + if (!value.handle || !value.prefix) goto error; + if (!PUSH(&context, tag_directives_copy, value)) + goto error; + value.handle = NULL; + value.prefix = NULL; + } + } + + DOCUMENT_START_EVENT_INIT(*event, version_directive_copy, + tag_directives_copy.start, tag_directives_copy.top, + implicit, mark, mark); + + return 1; + +error: + yaml_free(version_directive_copy); + while (!STACK_EMPTY(context, tag_directives_copy)) { + yaml_tag_directive_t value = POP(context, tag_directives_copy); + yaml_free(value.handle); + yaml_free(value.prefix); + } + STACK_DEL(context, tag_directives_copy); + yaml_free(value.handle); + yaml_free(value.prefix); + + return 0; +} + +/* + * Create DOCUMENT-END. + */ + +YAML_DECLARE(int) +yaml_document_end_event_initialize(yaml_event_t *event, int implicit) +{ + yaml_mark_t mark = { 0, 0, 0 }; + + assert(event); /* Non-NULL emitter object is expected. */ + + DOCUMENT_END_EVENT_INIT(*event, implicit, mark, mark); + + return 1; +} + +/* + * Create ALIAS. + */ + +YAML_DECLARE(int) +yaml_alias_event_initialize(yaml_event_t *event, yaml_char_t *anchor) +{ + yaml_mark_t mark = { 0, 0, 0 }; + yaml_char_t *anchor_copy = NULL; + + assert(event); /* Non-NULL event object is expected. */ + assert(anchor); /* Non-NULL anchor is expected. */ + + if (!yaml_check_utf8(anchor, strlen((char *)anchor))) return 0; + + anchor_copy = yaml_strdup(anchor); + if (!anchor_copy) + return 0; + + ALIAS_EVENT_INIT(*event, anchor_copy, mark, mark); + + return 1; +} + +/* + * Create SCALAR. + */ + +YAML_DECLARE(int) +yaml_scalar_event_initialize(yaml_event_t *event, + yaml_char_t *anchor, yaml_char_t *tag, + yaml_char_t *value, int length, + int plain_implicit, int quoted_implicit, + yaml_scalar_style_t style) +{ + yaml_mark_t mark = { 0, 0, 0 }; + yaml_char_t *anchor_copy = NULL; + yaml_char_t *tag_copy = NULL; + yaml_char_t *value_copy = NULL; + + assert(event); /* Non-NULL event object is expected. */ + assert(value); /* Non-NULL anchor is expected. */ + + if (anchor) { + if (!yaml_check_utf8(anchor, strlen((char *)anchor))) goto error; + anchor_copy = yaml_strdup(anchor); + if (!anchor_copy) goto error; + } + + if (tag) { + if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error; + tag_copy = yaml_strdup(tag); + if (!tag_copy) goto error; + } + + if (length < 0) { + length = strlen((char *)value); + } + + if (!yaml_check_utf8(value, length)) goto error; + value_copy = yaml_malloc(length+1); + if (!value_copy) goto error; + memcpy(value_copy, value, length); + value_copy[length] = '\0'; + + SCALAR_EVENT_INIT(*event, anchor_copy, tag_copy, value_copy, length, + plain_implicit, quoted_implicit, style, mark, mark); + + return 1; + +error: + yaml_free(anchor_copy); + yaml_free(tag_copy); + yaml_free(value_copy); + + return 0; +} + +/* + * Create SEQUENCE-START. + */ + +YAML_DECLARE(int) +yaml_sequence_start_event_initialize(yaml_event_t *event, + yaml_char_t *anchor, yaml_char_t *tag, int implicit, + yaml_sequence_style_t style) +{ + yaml_mark_t mark = { 0, 0, 0 }; + yaml_char_t *anchor_copy = NULL; + yaml_char_t *tag_copy = NULL; + + assert(event); /* Non-NULL event object is expected. */ + + if (anchor) { + if (!yaml_check_utf8(anchor, strlen((char *)anchor))) goto error; + anchor_copy = yaml_strdup(anchor); + if (!anchor_copy) goto error; + } + + if (tag) { + if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error; + tag_copy = yaml_strdup(tag); + if (!tag_copy) goto error; + } + + SEQUENCE_START_EVENT_INIT(*event, anchor_copy, tag_copy, + implicit, style, mark, mark); + + return 1; + +error: + yaml_free(anchor_copy); + yaml_free(tag_copy); + + return 0; +} + +/* + * Create SEQUENCE-END. + */ + +YAML_DECLARE(int) +yaml_sequence_end_event_initialize(yaml_event_t *event) +{ + yaml_mark_t mark = { 0, 0, 0 }; + + assert(event); /* Non-NULL event object is expected. */ + + SEQUENCE_END_EVENT_INIT(*event, mark, mark); + + return 1; +} + +/* + * Create MAPPING-START. + */ + +YAML_DECLARE(int) +yaml_mapping_start_event_initialize(yaml_event_t *event, + yaml_char_t *anchor, yaml_char_t *tag, int implicit, + yaml_mapping_style_t style) +{ + yaml_mark_t mark = { 0, 0, 0 }; + yaml_char_t *anchor_copy = NULL; + yaml_char_t *tag_copy = NULL; + + assert(event); /* Non-NULL event object is expected. */ + + if (anchor) { + if (!yaml_check_utf8(anchor, strlen((char *)anchor))) goto error; + anchor_copy = yaml_strdup(anchor); + if (!anchor_copy) goto error; + } + + if (tag) { + if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error; + tag_copy = yaml_strdup(tag); + if (!tag_copy) goto error; + } + + MAPPING_START_EVENT_INIT(*event, anchor_copy, tag_copy, + implicit, style, mark, mark); + + return 1; + +error: + yaml_free(anchor_copy); + yaml_free(tag_copy); + + return 0; +} + +/* + * Create MAPPING-END. + */ + +YAML_DECLARE(int) +yaml_mapping_end_event_initialize(yaml_event_t *event) +{ + yaml_mark_t mark = { 0, 0, 0 }; + + assert(event); /* Non-NULL event object is expected. */ + + MAPPING_END_EVENT_INIT(*event, mark, mark); + + return 1; +} + +/* + * Destroy an event object. + */ + +YAML_DECLARE(void) +yaml_event_delete(yaml_event_t *event) +{ + yaml_tag_directive_t *tag_directive; + + assert(event); /* Non-NULL event object expected. */ + + switch (event->type) + { + case YAML_DOCUMENT_START_EVENT: + yaml_free(event->data.document_start.version_directive); + for (tag_directive = event->data.document_start.tag_directives.start; + tag_directive != event->data.document_start.tag_directives.end; + tag_directive++) { + yaml_free(tag_directive->handle); + yaml_free(tag_directive->prefix); + } + yaml_free(event->data.document_start.tag_directives.start); + break; + + case YAML_ALIAS_EVENT: + yaml_free(event->data.alias.anchor); + break; + + case YAML_SCALAR_EVENT: + yaml_free(event->data.scalar.anchor); + yaml_free(event->data.scalar.tag); + yaml_free(event->data.scalar.value); + break; + + case YAML_SEQUENCE_START_EVENT: + yaml_free(event->data.sequence_start.anchor); + yaml_free(event->data.sequence_start.tag); + break; + + case YAML_MAPPING_START_EVENT: + yaml_free(event->data.mapping_start.anchor); + yaml_free(event->data.mapping_start.tag); + break; + + default: + break; + } + + memset(event, 0, sizeof(yaml_event_t)); +} + +/* + * Create a document object. + */ + +YAML_DECLARE(int) +yaml_document_initialize(yaml_document_t *document, + yaml_version_directive_t *version_directive, + yaml_tag_directive_t *tag_directives_start, + yaml_tag_directive_t *tag_directives_end, + int start_implicit, int end_implicit) +{ + struct { + yaml_error_type_t error; + } context; + struct { + yaml_node_t *start; + yaml_node_t *end; + yaml_node_t *top; + } nodes = { NULL, NULL, NULL }; + yaml_version_directive_t *version_directive_copy = NULL; + struct { + yaml_tag_directive_t *start; + yaml_tag_directive_t *end; + yaml_tag_directive_t *top; + } tag_directives_copy = { NULL, NULL, NULL }; + yaml_tag_directive_t value = { NULL, NULL }; + yaml_mark_t mark = { 0, 0, 0 }; + + assert(document); /* Non-NULL document object is expected. */ + assert((tag_directives_start && tag_directives_end) || + (tag_directives_start == tag_directives_end)); + /* Valid tag directives are expected. */ + + if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error; + + if (version_directive) { + version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t)); + if (!version_directive_copy) goto error; + version_directive_copy->major = version_directive->major; + version_directive_copy->minor = version_directive->minor; + } + + if (tag_directives_start != tag_directives_end) { + yaml_tag_directive_t *tag_directive; + if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE)) + goto error; + for (tag_directive = tag_directives_start; + tag_directive != tag_directives_end; tag_directive ++) { + assert(tag_directive->handle); + assert(tag_directive->prefix); + if (!yaml_check_utf8(tag_directive->handle, + strlen((char *)tag_directive->handle))) + goto error; + if (!yaml_check_utf8(tag_directive->prefix, + strlen((char *)tag_directive->prefix))) + goto error; + value.handle = yaml_strdup(tag_directive->handle); + value.prefix = yaml_strdup(tag_directive->prefix); + if (!value.handle || !value.prefix) goto error; + if (!PUSH(&context, tag_directives_copy, value)) + goto error; + value.handle = NULL; + value.prefix = NULL; + } + } + + DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy, + tag_directives_copy.start, tag_directives_copy.top, + start_implicit, end_implicit, mark, mark); + + return 1; + +error: + STACK_DEL(&context, nodes); + yaml_free(version_directive_copy); + while (!STACK_EMPTY(&context, tag_directives_copy)) { + yaml_tag_directive_t value = POP(&context, tag_directives_copy); + yaml_free(value.handle); + yaml_free(value.prefix); + } + STACK_DEL(&context, tag_directives_copy); + yaml_free(value.handle); + yaml_free(value.prefix); + + return 0; +} + +/* + * Destroy a document object. + */ + +YAML_DECLARE(void) +yaml_document_delete(yaml_document_t *document) +{ + struct { + yaml_error_type_t error; + } context; + yaml_tag_directive_t *tag_directive; + + context.error = YAML_NO_ERROR; /* Eliminate a compliler warning. */ + + assert(document); /* Non-NULL document object is expected. */ + + while (!STACK_EMPTY(&context, document->nodes)) { + yaml_node_t node = POP(&context, document->nodes); + yaml_free(node.tag); + switch (node.type) { + case YAML_SCALAR_NODE: + yaml_free(node.data.scalar.value); + break; + case YAML_SEQUENCE_NODE: + STACK_DEL(&context, node.data.sequence.items); + break; + case YAML_MAPPING_NODE: + STACK_DEL(&context, node.data.mapping.pairs); + break; + default: + assert(0); /* Should not happen. */ + } + } + STACK_DEL(&context, document->nodes); + + yaml_free(document->version_directive); + for (tag_directive = document->tag_directives.start; + tag_directive != document->tag_directives.end; + tag_directive++) { + yaml_free(tag_directive->handle); + yaml_free(tag_directive->prefix); + } + yaml_free(document->tag_directives.start); + + memset(document, 0, sizeof(yaml_document_t)); +} + +/** + * Get a document node. + */ + +YAML_DECLARE(yaml_node_t *) +yaml_document_get_node(yaml_document_t *document, int index) +{ + assert(document); /* Non-NULL document object is expected. */ + + if (index > 0 && document->nodes.start + index <= document->nodes.top) { + return document->nodes.start + index - 1; + } + return NULL; +} + +/** + * Get the root object. + */ + +YAML_DECLARE(yaml_node_t *) +yaml_document_get_root_node(yaml_document_t *document) +{ + assert(document); /* Non-NULL document object is expected. */ + + if (document->nodes.top != document->nodes.start) { + return document->nodes.start; + } + return NULL; +} + +/* + * Add a scalar node to a document. + */ + +YAML_DECLARE(int) +yaml_document_add_scalar(yaml_document_t *document, + yaml_char_t *tag, yaml_char_t *value, int length, + yaml_scalar_style_t style) +{ + struct { + yaml_error_type_t error; + } context; + yaml_mark_t mark = { 0, 0, 0 }; + yaml_char_t *tag_copy = NULL; + yaml_char_t *value_copy = NULL; + yaml_node_t node; + + assert(document); /* Non-NULL document object is expected. */ + assert(value); /* Non-NULL value is expected. */ + + if (!tag) { + tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG; + } + + if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error; + tag_copy = yaml_strdup(tag); + if (!tag_copy) goto error; + + if (length < 0) { + length = strlen((char *)value); + } + + if (!yaml_check_utf8(value, length)) goto error; + value_copy = yaml_malloc(length+1); + if (!value_copy) goto error; + memcpy(value_copy, value, length); + value_copy[length] = '\0'; + + SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark); + if (!PUSH(&context, document->nodes, node)) goto error; + + return document->nodes.top - document->nodes.start; + +error: + yaml_free(tag_copy); + yaml_free(value_copy); + + return 0; +} + +/* + * Add a sequence node to a document. + */ + +YAML_DECLARE(int) +yaml_document_add_sequence(yaml_document_t *document, + yaml_char_t *tag, yaml_sequence_style_t style) +{ + struct { + yaml_error_type_t error; + } context; + yaml_mark_t mark = { 0, 0, 0 }; + yaml_char_t *tag_copy = NULL; + struct { + yaml_node_item_t *start; + yaml_node_item_t *end; + yaml_node_item_t *top; + } items = { NULL, NULL, NULL }; + yaml_node_t node; + + assert(document); /* Non-NULL document object is expected. */ + + if (!tag) { + tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG; + } + + if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error; + tag_copy = yaml_strdup(tag); + if (!tag_copy) goto error; + + if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error; + + SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end, + style, mark, mark); + if (!PUSH(&context, document->nodes, node)) goto error; + + return document->nodes.top - document->nodes.start; + +error: + STACK_DEL(&context, items); + yaml_free(tag_copy); + + return 0; +} + +/* + * Add a mapping node to a document. + */ + +YAML_DECLARE(int) +yaml_document_add_mapping(yaml_document_t *document, + yaml_char_t *tag, yaml_mapping_style_t style) +{ + struct { + yaml_error_type_t error; + } context; + yaml_mark_t mark = { 0, 0, 0 }; + yaml_char_t *tag_copy = NULL; + struct { + yaml_node_pair_t *start; + yaml_node_pair_t *end; + yaml_node_pair_t *top; + } pairs = { NULL, NULL, NULL }; + yaml_node_t node; + + assert(document); /* Non-NULL document object is expected. */ + + if (!tag) { + tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG; + } + + if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error; + tag_copy = yaml_strdup(tag); + if (!tag_copy) goto error; + + if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error; + + MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end, + style, mark, mark); + if (!PUSH(&context, document->nodes, node)) goto error; + + return document->nodes.top - document->nodes.start; + +error: + STACK_DEL(&context, pairs); + yaml_free(tag_copy); + + return 0; +} + +/* + * Append an item to a sequence node. + */ + +YAML_DECLARE(int) +yaml_document_append_sequence_item(yaml_document_t *document, + int sequence, int item) +{ + struct { + yaml_error_type_t error; + } context; + + assert(document); /* Non-NULL document is required. */ + assert(sequence > 0 + && document->nodes.start + sequence <= document->nodes.top); + /* Valid sequence id is required. */ + assert(document->nodes.start[sequence-1].type == YAML_SEQUENCE_NODE); + /* A sequence node is required. */ + assert(item > 0 && document->nodes.start + item <= document->nodes.top); + /* Valid item id is required. */ + + if (!PUSH(&context, + document->nodes.start[sequence-1].data.sequence.items, item)) + return 0; + + return 1; +} + +/* + * Append a pair of a key and a value to a mapping node. + */ + +YAML_DECLARE(int) +yaml_document_append_mapping_pair(yaml_document_t *document, + int mapping, int key, int value) +{ + struct { + yaml_error_type_t error; + } context; + + yaml_node_pair_t pair; + + assert(document); /* Non-NULL document is required. */ + assert(mapping > 0 + && document->nodes.start + mapping <= document->nodes.top); + /* Valid mapping id is required. */ + assert(document->nodes.start[mapping-1].type == YAML_MAPPING_NODE); + /* A mapping node is required. */ + assert(key > 0 && document->nodes.start + key <= document->nodes.top); + /* Valid key id is required. */ + assert(value > 0 && document->nodes.start + value <= document->nodes.top); + /* Valid value id is required. */ + + pair.key = key; + pair.value = value; + + if (!PUSH(&context, + document->nodes.start[mapping-1].data.mapping.pairs, pair)) + return 0; + + return 1; +} + + diff --git a/src/dumper.c b/src/dumper.c new file mode 100644 index 00000000000..203c6a709c3 --- /dev/null +++ b/src/dumper.c @@ -0,0 +1,394 @@ + +#include "yaml_private.h" + +/* + * API functions. + */ + +YAML_DECLARE(int) +yaml_emitter_open(yaml_emitter_t *emitter); + +YAML_DECLARE(int) +yaml_emitter_close(yaml_emitter_t *emitter); + +YAML_DECLARE(int) +yaml_emitter_dump(yaml_emitter_t *emitter, yaml_document_t *document); + +/* + * Clean up functions. + */ + +static void +yaml_emitter_delete_document_and_anchors(yaml_emitter_t *emitter); + +/* + * Anchor functions. + */ + +static void +yaml_emitter_anchor_node(yaml_emitter_t *emitter, int index); + +static yaml_char_t * +yaml_emitter_generate_anchor(yaml_emitter_t *emitter, int anchor_id); + + +/* + * Serialize functions. + */ + +static int +yaml_emitter_dump_node(yaml_emitter_t *emitter, int index); + +static int +yaml_emitter_dump_alias(yaml_emitter_t *emitter, yaml_char_t *anchor); + +static int +yaml_emitter_dump_scalar(yaml_emitter_t *emitter, yaml_node_t *node, + yaml_char_t *anchor); + +static int +yaml_emitter_dump_sequence(yaml_emitter_t *emitter, yaml_node_t *node, + yaml_char_t *anchor); + +static int +yaml_emitter_dump_mapping(yaml_emitter_t *emitter, yaml_node_t *node, + yaml_char_t *anchor); + +/* + * Issue a STREAM-START event. + */ + +YAML_DECLARE(int) +yaml_emitter_open(yaml_emitter_t *emitter) +{ + yaml_event_t event; + yaml_mark_t mark = { 0, 0, 0 }; + + assert(emitter); /* Non-NULL emitter object is required. */ + assert(!emitter->opened); /* Emitter should not be opened yet. */ + + STREAM_START_EVENT_INIT(event, YAML_ANY_ENCODING, mark, mark); + + if (!yaml_emitter_emit(emitter, &event)) { + return 0; + } + + emitter->opened = 1; + + return 1; +} + +/* + * Issue a STREAM-END event. + */ + +YAML_DECLARE(int) +yaml_emitter_close(yaml_emitter_t *emitter) +{ + yaml_event_t event; + yaml_mark_t mark = { 0, 0, 0 }; + + assert(emitter); /* Non-NULL emitter object is required. */ + assert(emitter->opened); /* Emitter should be opened. */ + + if (emitter->closed) return 1; + + STREAM_END_EVENT_INIT(event, mark, mark); + + if (!yaml_emitter_emit(emitter, &event)) { + return 0; + } + + emitter->closed = 1; + + return 1; +} + +/* + * Dump a YAML document. + */ + +YAML_DECLARE(int) +yaml_emitter_dump(yaml_emitter_t *emitter, yaml_document_t *document) +{ + yaml_event_t event; + yaml_mark_t mark = { 0, 0, 0 }; + + assert(emitter); /* Non-NULL emitter object is required. */ + assert(document); /* Non-NULL emitter object is expected. */ + + emitter->document = document; + + if (!emitter->opened) { + if (!yaml_emitter_open(emitter)) goto error; + } + + if (STACK_EMPTY(emitter, document->nodes)) { + if (!yaml_emitter_close(emitter)) goto error; + yaml_emitter_delete_document_and_anchors(emitter); + return 1; + } + + assert(emitter->opened); /* Emitter should be opened. */ + + emitter->anchors = yaml_malloc(sizeof(*(emitter->anchors)) + * (document->nodes.top - document->nodes.start)); + if (!emitter->anchors) goto error; + memset(emitter->anchors, 0, sizeof(*(emitter->anchors)) + * (document->nodes.top - document->nodes.start)); + + DOCUMENT_START_EVENT_INIT(event, document->version_directive, + document->tag_directives.start, document->tag_directives.end, + document->start_implicit, mark, mark); + if (!yaml_emitter_emit(emitter, &event)) goto error; + + yaml_emitter_anchor_node(emitter, 1); + if (!yaml_emitter_dump_node(emitter, 1)) goto error; + + DOCUMENT_END_EVENT_INIT(event, document->end_implicit, mark, mark); + if (!yaml_emitter_emit(emitter, &event)) goto error; + + yaml_emitter_delete_document_and_anchors(emitter); + + return 1; + +error: + + yaml_emitter_delete_document_and_anchors(emitter); + + return 0; +} + +/* + * Clean up the emitter object after a document is dumped. + */ + +static void +yaml_emitter_delete_document_and_anchors(yaml_emitter_t *emitter) +{ + int index; + + if (!emitter->anchors) { + yaml_document_delete(emitter->document); + emitter->document = NULL; + return; + } + + for (index = 0; emitter->document->nodes.start + index + < emitter->document->nodes.top; index ++) { + yaml_node_t node = emitter->document->nodes.start[index]; + if (!emitter->anchors[index].serialized) { + yaml_free(node.tag); + if (node.type == YAML_SCALAR_NODE) { + yaml_free(node.data.scalar.value); + } + } + if (node.type == YAML_SEQUENCE_NODE) { + STACK_DEL(emitter, node.data.sequence.items); + } + if (node.type == YAML_MAPPING_NODE) { + STACK_DEL(emitter, node.data.mapping.pairs); + } + } + + STACK_DEL(emitter, emitter->document->nodes); + yaml_free(emitter->anchors); + + emitter->anchors = NULL; + emitter->last_anchor_id = 0; + emitter->document = NULL; +} + +/* + * Check the references of a node and assign the anchor id if needed. + */ + +static void +yaml_emitter_anchor_node(yaml_emitter_t *emitter, int index) +{ + yaml_node_t *node = emitter->document->nodes.start + index - 1; + yaml_node_item_t *item; + yaml_node_pair_t *pair; + + emitter->anchors[index-1].references ++; + + if (emitter->anchors[index-1].references == 1) { + switch (node->type) { + case YAML_SEQUENCE_NODE: + for (item = node->data.sequence.items.start; + item < node->data.sequence.items.top; item ++) { + yaml_emitter_anchor_node(emitter, *item); + } + break; + case YAML_MAPPING_NODE: + for (pair = node->data.mapping.pairs.start; + pair < node->data.mapping.pairs.top; pair ++) { + yaml_emitter_anchor_node(emitter, pair->key); + yaml_emitter_anchor_node(emitter, pair->value); + } + break; + default: + break; + } + } + + else if (emitter->anchors[index-1].references == 2) { + emitter->anchors[index-1].anchor = (++ emitter->last_anchor_id); + } +} + +/* + * Generate a textual representation for an anchor. + */ + +#define ANCHOR_TEMPLATE "id%03d" +#define ANCHOR_TEMPLATE_LENGTH 16 + +static yaml_char_t * +yaml_emitter_generate_anchor(yaml_emitter_t *emitter, int anchor_id) +{ + yaml_char_t *anchor = yaml_malloc(ANCHOR_TEMPLATE_LENGTH); + + if (!anchor) return NULL; + + sprintf((char *)anchor, ANCHOR_TEMPLATE, anchor_id); + + return anchor; +} + +/* + * Serialize a node. + */ + +static int +yaml_emitter_dump_node(yaml_emitter_t *emitter, int index) +{ + yaml_node_t *node = emitter->document->nodes.start + index - 1; + int anchor_id = emitter->anchors[index-1].anchor; + yaml_char_t *anchor = NULL; + + if (anchor_id) { + anchor = yaml_emitter_generate_anchor(emitter, anchor_id); + if (!anchor) return 0; + } + + if (emitter->anchors[index-1].serialized) { + return yaml_emitter_dump_alias(emitter, anchor); + } + + emitter->anchors[index-1].serialized = 1; + + switch (node->type) { + case YAML_SCALAR_NODE: + return yaml_emitter_dump_scalar(emitter, node, anchor); + case YAML_SEQUENCE_NODE: + return yaml_emitter_dump_sequence(emitter, node, anchor); + case YAML_MAPPING_NODE: + return yaml_emitter_dump_mapping(emitter, node, anchor); + default: + assert(0); /* Could not happen. */ + break; + } + + return 0; /* Could not happen. */ +} + +/* + * Serialize an alias. + */ + +static int +yaml_emitter_dump_alias(yaml_emitter_t *emitter, yaml_char_t *anchor) +{ + yaml_event_t event; + yaml_mark_t mark = { 0, 0, 0 }; + + ALIAS_EVENT_INIT(event, anchor, mark, mark); + + return yaml_emitter_emit(emitter, &event); +} + +/* + * Serialize a scalar. + */ + +static int +yaml_emitter_dump_scalar(yaml_emitter_t *emitter, yaml_node_t *node, + yaml_char_t *anchor) +{ + yaml_event_t event; + yaml_mark_t mark = { 0, 0, 0 }; + + int plain_implicit = (strcmp((char *)node->tag, + YAML_DEFAULT_SCALAR_TAG) == 0); + int quoted_implicit = (strcmp((char *)node->tag, + YAML_DEFAULT_SCALAR_TAG) == 0); + + SCALAR_EVENT_INIT(event, anchor, node->tag, node->data.scalar.value, + node->data.scalar.length, plain_implicit, quoted_implicit, + node->data.scalar.style, mark, mark); + + return yaml_emitter_emit(emitter, &event); +} + +/* + * Serialize a sequence. + */ + +static int +yaml_emitter_dump_sequence(yaml_emitter_t *emitter, yaml_node_t *node, + yaml_char_t *anchor) +{ + yaml_event_t event; + yaml_mark_t mark = { 0, 0, 0 }; + + int implicit = (strcmp((char *)node->tag, YAML_DEFAULT_SEQUENCE_TAG) == 0); + + yaml_node_item_t *item; + + SEQUENCE_START_EVENT_INIT(event, anchor, node->tag, implicit, + node->data.sequence.style, mark, mark); + if (!yaml_emitter_emit(emitter, &event)) return 0; + + for (item = node->data.sequence.items.start; + item < node->data.sequence.items.top; item ++) { + if (!yaml_emitter_dump_node(emitter, *item)) return 0; + } + + SEQUENCE_END_EVENT_INIT(event, mark, mark); + if (!yaml_emitter_emit(emitter, &event)) return 0; + + return 1; +} + +/* + * Serialize a mapping. + */ + +static int +yaml_emitter_dump_mapping(yaml_emitter_t *emitter, yaml_node_t *node, + yaml_char_t *anchor) +{ + yaml_event_t event; + yaml_mark_t mark = { 0, 0, 0 }; + + int implicit = (strcmp((char *)node->tag, YAML_DEFAULT_MAPPING_TAG) == 0); + + yaml_node_pair_t *pair; + + MAPPING_START_EVENT_INIT(event, anchor, node->tag, implicit, + node->data.mapping.style, mark, mark); + if (!yaml_emitter_emit(emitter, &event)) return 0; + + for (pair = node->data.mapping.pairs.start; + pair < node->data.mapping.pairs.top; pair ++) { + if (!yaml_emitter_dump_node(emitter, pair->key)) return 0; + if (!yaml_emitter_dump_node(emitter, pair->value)) return 0; + } + + MAPPING_END_EVENT_INIT(event, mark, mark); + if (!yaml_emitter_emit(emitter, &event)) return 0; + + return 1; +} + diff --git a/src/emitter.c b/src/emitter.c new file mode 100644 index 00000000000..c4b56a26bb5 --- /dev/null +++ b/src/emitter.c @@ -0,0 +1,2329 @@ + +#include "yaml_private.h" + +/* + * Flush the buffer if needed. + */ + +#define FLUSH(emitter) \ + ((emitter->buffer.pointer+5 < emitter->buffer.end) \ + || yaml_emitter_flush(emitter)) + +/* + * Put a character to the output buffer. + */ + +#define PUT(emitter,value) \ + (FLUSH(emitter) \ + && (*(emitter->buffer.pointer++) = (yaml_char_t)(value), \ + emitter->column ++, \ + 1)) + +/* + * Put a line break to the output buffer. + */ + +#define PUT_BREAK(emitter) \ + (FLUSH(emitter) \ + && ((emitter->line_break == YAML_CR_BREAK ? \ + (*(emitter->buffer.pointer++) = (yaml_char_t) '\r') : \ + emitter->line_break == YAML_LN_BREAK ? \ + (*(emitter->buffer.pointer++) = (yaml_char_t) '\n') : \ + emitter->line_break == YAML_CRLN_BREAK ? \ + (*(emitter->buffer.pointer++) = (yaml_char_t) '\r', \ + *(emitter->buffer.pointer++) = (yaml_char_t) '\n') : 0), \ + emitter->column = 0, \ + emitter->line ++, \ + 1)) + +/* + * Copy a character from a string into buffer. + */ + +#define WRITE(emitter,string) \ + (FLUSH(emitter) \ + && (COPY(emitter->buffer,string), \ + emitter->column ++, \ + 1)) + +/* + * Copy a line break character from a string into buffer. + */ + +#define WRITE_BREAK(emitter,string) \ + (FLUSH(emitter) \ + && (CHECK(string,'\n') ? \ + (PUT_BREAK(emitter), \ + string.pointer ++, \ + 1) : \ + (COPY(emitter->buffer,string), \ + emitter->column = 0, \ + emitter->line ++, \ + 1))) + +/* + * API functions. + */ + +YAML_DECLARE(int) +yaml_emitter_emit(yaml_emitter_t *emitter, yaml_event_t *event); + +/* + * Utility functions. + */ + +static int +yaml_emitter_set_emitter_error(yaml_emitter_t *emitter, const char *problem); + +static int +yaml_emitter_need_more_events(yaml_emitter_t *emitter); + +static int +yaml_emitter_append_tag_directive(yaml_emitter_t *emitter, + yaml_tag_directive_t value, int allow_duplicates); + +static int +yaml_emitter_increase_indent(yaml_emitter_t *emitter, + int flow, int indentless); + +/* + * State functions. + */ + +static int +yaml_emitter_state_machine(yaml_emitter_t *emitter, yaml_event_t *event); + +static int +yaml_emitter_emit_stream_start(yaml_emitter_t *emitter, + yaml_event_t *event); + +static int +yaml_emitter_emit_document_start(yaml_emitter_t *emitter, + yaml_event_t *event, int first); + +static int +yaml_emitter_emit_document_content(yaml_emitter_t *emitter, + yaml_event_t *event); + +static int +yaml_emitter_emit_document_end(yaml_emitter_t *emitter, + yaml_event_t *event); + +static int +yaml_emitter_emit_flow_sequence_item(yaml_emitter_t *emitter, + yaml_event_t *event, int first); + +static int +yaml_emitter_emit_flow_mapping_key(yaml_emitter_t *emitter, + yaml_event_t *event, int first); + +static int +yaml_emitter_emit_flow_mapping_value(yaml_emitter_t *emitter, + yaml_event_t *event, int simple); + +static int +yaml_emitter_emit_block_sequence_item(yaml_emitter_t *emitter, + yaml_event_t *event, int first); + +static int +yaml_emitter_emit_block_mapping_key(yaml_emitter_t *emitter, + yaml_event_t *event, int first); + +static int +yaml_emitter_emit_block_mapping_value(yaml_emitter_t *emitter, + yaml_event_t *event, int simple); + +static int +yaml_emitter_emit_node(yaml_emitter_t *emitter, yaml_event_t *event, + int root, int sequence, int mapping, int simple_key); + +static int +yaml_emitter_emit_alias(yaml_emitter_t *emitter, yaml_event_t *event); + +static int +yaml_emitter_emit_scalar(yaml_emitter_t *emitter, yaml_event_t *event); + +static int +yaml_emitter_emit_sequence_start(yaml_emitter_t *emitter, yaml_event_t *event); + +static int +yaml_emitter_emit_mapping_start(yaml_emitter_t *emitter, yaml_event_t *event); + +/* + * Checkers. + */ + +static int +yaml_emitter_check_empty_document(yaml_emitter_t *emitter); + +static int +yaml_emitter_check_empty_sequence(yaml_emitter_t *emitter); + +static int +yaml_emitter_check_empty_mapping(yaml_emitter_t *emitter); + +static int +yaml_emitter_check_simple_key(yaml_emitter_t *emitter); + +static int +yaml_emitter_select_scalar_style(yaml_emitter_t *emitter, yaml_event_t *event); + +/* + * Processors. + */ + +static int +yaml_emitter_process_anchor(yaml_emitter_t *emitter); + +static int +yaml_emitter_process_tag(yaml_emitter_t *emitter); + +static int +yaml_emitter_process_scalar(yaml_emitter_t *emitter); + +/* + * Analyzers. + */ + +static int +yaml_emitter_analyze_version_directive(yaml_emitter_t *emitter, + yaml_version_directive_t version_directive); + +static int +yaml_emitter_analyze_tag_directive(yaml_emitter_t *emitter, + yaml_tag_directive_t tag_directive); + +static int +yaml_emitter_analyze_anchor(yaml_emitter_t *emitter, + yaml_char_t *anchor, int alias); + +static int +yaml_emitter_analyze_tag(yaml_emitter_t *emitter, + yaml_char_t *tag); + +static int +yaml_emitter_analyze_scalar(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length); + +static int +yaml_emitter_analyze_event(yaml_emitter_t *emitter, + yaml_event_t *event); + +/* + * Writers. + */ + +static int +yaml_emitter_write_bom(yaml_emitter_t *emitter); + +static int +yaml_emitter_write_indent(yaml_emitter_t *emitter); + +static int +yaml_emitter_write_indicator(yaml_emitter_t *emitter, + char *indicator, int need_whitespace, + int is_whitespace, int is_indention); + +static int +yaml_emitter_write_anchor(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length); + +static int +yaml_emitter_write_tag_handle(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length); + +static int +yaml_emitter_write_tag_content(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length, int need_whitespace); + +static int +yaml_emitter_write_plain_scalar(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length, int allow_breaks); + +static int +yaml_emitter_write_single_quoted_scalar(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length, int allow_breaks); + +static int +yaml_emitter_write_double_quoted_scalar(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length, int allow_breaks); + +static int +yaml_emitter_write_block_scalar_hints(yaml_emitter_t *emitter, + yaml_string_t string); + +static int +yaml_emitter_write_literal_scalar(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length); + +static int +yaml_emitter_write_folded_scalar(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length); + +/* + * Set an emitter error and return 0. + */ + +static int +yaml_emitter_set_emitter_error(yaml_emitter_t *emitter, const char *problem) +{ + emitter->error = YAML_EMITTER_ERROR; + emitter->problem = problem; + + return 0; +} + +/* + * Emit an event. + */ + +YAML_DECLARE(int) +yaml_emitter_emit(yaml_emitter_t *emitter, yaml_event_t *event) +{ + if (!ENQUEUE(emitter, emitter->events, *event)) { + yaml_event_delete(event); + return 0; + } + + while (!yaml_emitter_need_more_events(emitter)) { + if (!yaml_emitter_analyze_event(emitter, emitter->events.head)) + return 0; + if (!yaml_emitter_state_machine(emitter, emitter->events.head)) + return 0; + yaml_event_delete(&DEQUEUE(emitter, emitter->events)); + } + + return 1; +} + +/* + * Check if we need to accumulate more events before emitting. + * + * We accumulate extra + * - 1 event for DOCUMENT-START + * - 2 events for SEQUENCE-START + * - 3 events for MAPPING-START + */ + +static int +yaml_emitter_need_more_events(yaml_emitter_t *emitter) +{ + int level = 0; + int accumulate = 0; + yaml_event_t *event; + + if (QUEUE_EMPTY(emitter, emitter->events)) + return 1; + + switch (emitter->events.head->type) { + case YAML_DOCUMENT_START_EVENT: + accumulate = 1; + break; + case YAML_SEQUENCE_START_EVENT: + accumulate = 2; + break; + case YAML_MAPPING_START_EVENT: + accumulate = 3; + break; + default: + return 0; + } + + if (emitter->events.tail - emitter->events.head > accumulate) + return 0; + + for (event = emitter->events.head; event != emitter->events.tail; event ++) { + switch (event->type) { + case YAML_STREAM_START_EVENT: + case YAML_DOCUMENT_START_EVENT: + case YAML_SEQUENCE_START_EVENT: + case YAML_MAPPING_START_EVENT: + level += 1; + break; + case YAML_STREAM_END_EVENT: + case YAML_DOCUMENT_END_EVENT: + case YAML_SEQUENCE_END_EVENT: + case YAML_MAPPING_END_EVENT: + level -= 1; + break; + default: + break; + } + if (!level) + return 0; + } + + return 1; +} + +/* + * Append a directive to the directives stack. + */ + +static int +yaml_emitter_append_tag_directive(yaml_emitter_t *emitter, + yaml_tag_directive_t value, int allow_duplicates) +{ + yaml_tag_directive_t *tag_directive; + yaml_tag_directive_t copy = { NULL, NULL }; + + for (tag_directive = emitter->tag_directives.start; + tag_directive != emitter->tag_directives.top; tag_directive ++) { + if (strcmp((char *)value.handle, (char *)tag_directive->handle) == 0) { + if (allow_duplicates) + return 1; + return yaml_emitter_set_emitter_error(emitter, + "duplicate %TAG directive"); + } + } + + copy.handle = yaml_strdup(value.handle); + copy.prefix = yaml_strdup(value.prefix); + if (!copy.handle || !copy.prefix) { + emitter->error = YAML_MEMORY_ERROR; + goto error; + } + + if (!PUSH(emitter, emitter->tag_directives, copy)) + goto error; + + return 1; + +error: + yaml_free(copy.handle); + yaml_free(copy.prefix); + return 0; +} + +/* + * Increase the indentation level. + */ + +static int +yaml_emitter_increase_indent(yaml_emitter_t *emitter, + int flow, int indentless) +{ + if (!PUSH(emitter, emitter->indents, emitter->indent)) + return 0; + + if (emitter->indent < 0) { + emitter->indent = flow ? emitter->best_indent : 0; + } + else if (!indentless) { + emitter->indent += emitter->best_indent; + } + + return 1; +} + +/* + * State dispatcher. + */ + +static int +yaml_emitter_state_machine(yaml_emitter_t *emitter, yaml_event_t *event) +{ + switch (emitter->state) + { + case YAML_EMIT_STREAM_START_STATE: + return yaml_emitter_emit_stream_start(emitter, event); + + case YAML_EMIT_FIRST_DOCUMENT_START_STATE: + return yaml_emitter_emit_document_start(emitter, event, 1); + + case YAML_EMIT_DOCUMENT_START_STATE: + return yaml_emitter_emit_document_start(emitter, event, 0); + + case YAML_EMIT_DOCUMENT_CONTENT_STATE: + return yaml_emitter_emit_document_content(emitter, event); + + case YAML_EMIT_DOCUMENT_END_STATE: + return yaml_emitter_emit_document_end(emitter, event); + + case YAML_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE: + return yaml_emitter_emit_flow_sequence_item(emitter, event, 1); + + case YAML_EMIT_FLOW_SEQUENCE_ITEM_STATE: + return yaml_emitter_emit_flow_sequence_item(emitter, event, 0); + + case YAML_EMIT_FLOW_MAPPING_FIRST_KEY_STATE: + return yaml_emitter_emit_flow_mapping_key(emitter, event, 1); + + case YAML_EMIT_FLOW_MAPPING_KEY_STATE: + return yaml_emitter_emit_flow_mapping_key(emitter, event, 0); + + case YAML_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE: + return yaml_emitter_emit_flow_mapping_value(emitter, event, 1); + + case YAML_EMIT_FLOW_MAPPING_VALUE_STATE: + return yaml_emitter_emit_flow_mapping_value(emitter, event, 0); + + case YAML_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE: + return yaml_emitter_emit_block_sequence_item(emitter, event, 1); + + case YAML_EMIT_BLOCK_SEQUENCE_ITEM_STATE: + return yaml_emitter_emit_block_sequence_item(emitter, event, 0); + + case YAML_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE: + return yaml_emitter_emit_block_mapping_key(emitter, event, 1); + + case YAML_EMIT_BLOCK_MAPPING_KEY_STATE: + return yaml_emitter_emit_block_mapping_key(emitter, event, 0); + + case YAML_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE: + return yaml_emitter_emit_block_mapping_value(emitter, event, 1); + + case YAML_EMIT_BLOCK_MAPPING_VALUE_STATE: + return yaml_emitter_emit_block_mapping_value(emitter, event, 0); + + case YAML_EMIT_END_STATE: + return yaml_emitter_set_emitter_error(emitter, + "expected nothing after STREAM-END"); + + default: + assert(1); /* Invalid state. */ + } + + return 0; +} + +/* + * Expect STREAM-START. + */ + +static int +yaml_emitter_emit_stream_start(yaml_emitter_t *emitter, + yaml_event_t *event) +{ + if (event->type == YAML_STREAM_START_EVENT) + { + if (!emitter->encoding) { + emitter->encoding = event->data.stream_start.encoding; + } + + if (!emitter->encoding) { + emitter->encoding = YAML_UTF8_ENCODING; + } + + if (emitter->best_indent < 2 || emitter->best_indent > 9) { + emitter->best_indent = 2; + } + + if (emitter->best_width >= 0 + && emitter->best_width <= emitter->best_indent*2) { + emitter->best_width = 80; + } + + if (emitter->best_width < 0) { + emitter->best_width = INT_MAX; + } + + if (!emitter->line_break) { + emitter->line_break = YAML_LN_BREAK; + } + + emitter->indent = -1; + + emitter->line = 0; + emitter->column = 0; + emitter->whitespace = 1; + emitter->indention = 1; + + if (emitter->encoding != YAML_UTF8_ENCODING) { + if (!yaml_emitter_write_bom(emitter)) + return 0; + } + + emitter->state = YAML_EMIT_FIRST_DOCUMENT_START_STATE; + + return 1; + } + + return yaml_emitter_set_emitter_error(emitter, + "expected STREAM-START"); +} + +/* + * Expect DOCUMENT-START or STREAM-END. + */ + +static int +yaml_emitter_emit_document_start(yaml_emitter_t *emitter, + yaml_event_t *event, int first) +{ + if (event->type == YAML_DOCUMENT_START_EVENT) + { + yaml_tag_directive_t default_tag_directives[] = { + {(yaml_char_t *)"!", (yaml_char_t *)"!"}, + {(yaml_char_t *)"!!", (yaml_char_t *)"tag:yaml.org,2002:"}, + {NULL, NULL} + }; + yaml_tag_directive_t *tag_directive; + int implicit; + + if (event->data.document_start.version_directive) { + if (!yaml_emitter_analyze_version_directive(emitter, + *event->data.document_start.version_directive)) + return 0; + } + + for (tag_directive = event->data.document_start.tag_directives.start; + tag_directive != event->data.document_start.tag_directives.end; + tag_directive ++) { + if (!yaml_emitter_analyze_tag_directive(emitter, *tag_directive)) + return 0; + if (!yaml_emitter_append_tag_directive(emitter, *tag_directive, 0)) + return 0; + } + + for (tag_directive = default_tag_directives; + tag_directive->handle; tag_directive ++) { + if (!yaml_emitter_append_tag_directive(emitter, *tag_directive, 1)) + return 0; + } + + implicit = event->data.document_start.implicit; + if (!first || emitter->canonical) { + implicit = 0; + } + + if ((event->data.document_start.version_directive || + (event->data.document_start.tag_directives.start + != event->data.document_start.tag_directives.end)) && + emitter->open_ended) + { + if (!yaml_emitter_write_indicator(emitter, "...", 1, 0, 0)) + return 0; + if (!yaml_emitter_write_indent(emitter)) + return 0; + } + + if (event->data.document_start.version_directive) { + implicit = 0; + if (!yaml_emitter_write_indicator(emitter, "%YAML", 1, 0, 0)) + return 0; + if (!yaml_emitter_write_indicator(emitter, "1.1", 1, 0, 0)) + return 0; + if (!yaml_emitter_write_indent(emitter)) + return 0; + } + + if (event->data.document_start.tag_directives.start + != event->data.document_start.tag_directives.end) { + implicit = 0; + for (tag_directive = event->data.document_start.tag_directives.start; + tag_directive != event->data.document_start.tag_directives.end; + tag_directive ++) { + if (!yaml_emitter_write_indicator(emitter, "%TAG", 1, 0, 0)) + return 0; + if (!yaml_emitter_write_tag_handle(emitter, tag_directive->handle, + strlen((char *)tag_directive->handle))) + return 0; + if (!yaml_emitter_write_tag_content(emitter, tag_directive->prefix, + strlen((char *)tag_directive->prefix), 1)) + return 0; + if (!yaml_emitter_write_indent(emitter)) + return 0; + } + } + + if (yaml_emitter_check_empty_document(emitter)) { + implicit = 0; + } + + if (!implicit) { + if (!yaml_emitter_write_indent(emitter)) + return 0; + if (!yaml_emitter_write_indicator(emitter, "---", 1, 0, 0)) + return 0; + if (emitter->canonical) { + if (!yaml_emitter_write_indent(emitter)) + return 0; + } + } + + emitter->state = YAML_EMIT_DOCUMENT_CONTENT_STATE; + + return 1; + } + + else if (event->type == YAML_STREAM_END_EVENT) + { + if (emitter->open_ended) + { + if (!yaml_emitter_write_indicator(emitter, "...", 1, 0, 0)) + return 0; + if (!yaml_emitter_write_indent(emitter)) + return 0; + } + + if (!yaml_emitter_flush(emitter)) + return 0; + + emitter->state = YAML_EMIT_END_STATE; + + return 1; + } + + return yaml_emitter_set_emitter_error(emitter, + "expected DOCUMENT-START or STREAM-END"); +} + +/* + * Expect the root node. + */ + +static int +yaml_emitter_emit_document_content(yaml_emitter_t *emitter, + yaml_event_t *event) +{ + if (!PUSH(emitter, emitter->states, YAML_EMIT_DOCUMENT_END_STATE)) + return 0; + + return yaml_emitter_emit_node(emitter, event, 1, 0, 0, 0); +} + +/* + * Expect DOCUMENT-END. + */ + +static int +yaml_emitter_emit_document_end(yaml_emitter_t *emitter, + yaml_event_t *event) +{ + if (event->type == YAML_DOCUMENT_END_EVENT) + { + if (!yaml_emitter_write_indent(emitter)) + return 0; + if (!event->data.document_end.implicit) { + if (!yaml_emitter_write_indicator(emitter, "...", 1, 0, 0)) + return 0; + if (!yaml_emitter_write_indent(emitter)) + return 0; + } + if (!yaml_emitter_flush(emitter)) + return 0; + + emitter->state = YAML_EMIT_DOCUMENT_START_STATE; + + while (!STACK_EMPTY(emitter, emitter->tag_directives)) { + yaml_tag_directive_t tag_directive = POP(emitter, + emitter->tag_directives); + yaml_free(tag_directive.handle); + yaml_free(tag_directive.prefix); + } + + return 1; + } + + return yaml_emitter_set_emitter_error(emitter, + "expected DOCUMENT-END"); +} + +/* + * + * Expect a flow item node. + */ + +static int +yaml_emitter_emit_flow_sequence_item(yaml_emitter_t *emitter, + yaml_event_t *event, int first) +{ + if (first) + { + if (!yaml_emitter_write_indicator(emitter, "[", 1, 1, 0)) + return 0; + if (!yaml_emitter_increase_indent(emitter, 1, 0)) + return 0; + emitter->flow_level ++; + } + + if (event->type == YAML_SEQUENCE_END_EVENT) + { + emitter->flow_level --; + emitter->indent = POP(emitter, emitter->indents); + if (emitter->canonical && !first) { + if (!yaml_emitter_write_indicator(emitter, ",", 0, 0, 0)) + return 0; + if (!yaml_emitter_write_indent(emitter)) + return 0; + } + if (!yaml_emitter_write_indicator(emitter, "]", 0, 0, 0)) + return 0; + emitter->state = POP(emitter, emitter->states); + + return 1; + } + + if (!first) { + if (!yaml_emitter_write_indicator(emitter, ",", 0, 0, 0)) + return 0; + } + + if (emitter->canonical || emitter->column > emitter->best_width) { + if (!yaml_emitter_write_indent(emitter)) + return 0; + } + if (!PUSH(emitter, emitter->states, YAML_EMIT_FLOW_SEQUENCE_ITEM_STATE)) + return 0; + + return yaml_emitter_emit_node(emitter, event, 0, 1, 0, 0); +} + +/* + * Expect a flow key node. + */ + +static int +yaml_emitter_emit_flow_mapping_key(yaml_emitter_t *emitter, + yaml_event_t *event, int first) +{ + if (first) + { + if (!yaml_emitter_write_indicator(emitter, "{", 1, 1, 0)) + return 0; + if (!yaml_emitter_increase_indent(emitter, 1, 0)) + return 0; + emitter->flow_level ++; + } + + if (event->type == YAML_MAPPING_END_EVENT) + { + emitter->flow_level --; + emitter->indent = POP(emitter, emitter->indents); + if (emitter->canonical && !first) { + if (!yaml_emitter_write_indicator(emitter, ",", 0, 0, 0)) + return 0; + if (!yaml_emitter_write_indent(emitter)) + return 0; + } + if (!yaml_emitter_write_indicator(emitter, "}", 0, 0, 0)) + return 0; + emitter->state = POP(emitter, emitter->states); + + return 1; + } + + if (!first) { + if (!yaml_emitter_write_indicator(emitter, ",", 0, 0, 0)) + return 0; + } + if (emitter->canonical || emitter->column > emitter->best_width) { + if (!yaml_emitter_write_indent(emitter)) + return 0; + } + + if (!emitter->canonical && yaml_emitter_check_simple_key(emitter)) + { + if (!PUSH(emitter, emitter->states, + YAML_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE)) + return 0; + + return yaml_emitter_emit_node(emitter, event, 0, 0, 1, 1); + } + else + { + if (!yaml_emitter_write_indicator(emitter, "?", 1, 0, 0)) + return 0; + if (!PUSH(emitter, emitter->states, + YAML_EMIT_FLOW_MAPPING_VALUE_STATE)) + return 0; + + return yaml_emitter_emit_node(emitter, event, 0, 0, 1, 0); + } +} + +/* + * Expect a flow value node. + */ + +static int +yaml_emitter_emit_flow_mapping_value(yaml_emitter_t *emitter, + yaml_event_t *event, int simple) +{ + if (simple) { + if (!yaml_emitter_write_indicator(emitter, ":", 0, 0, 0)) + return 0; + } + else { + if (emitter->canonical || emitter->column > emitter->best_width) { + if (!yaml_emitter_write_indent(emitter)) + return 0; + } + if (!yaml_emitter_write_indicator(emitter, ":", 1, 0, 0)) + return 0; + } + if (!PUSH(emitter, emitter->states, YAML_EMIT_FLOW_MAPPING_KEY_STATE)) + return 0; + return yaml_emitter_emit_node(emitter, event, 0, 0, 1, 0); +} + +/* + * Expect a block item node. + */ + +static int +yaml_emitter_emit_block_sequence_item(yaml_emitter_t *emitter, + yaml_event_t *event, int first) +{ + if (first) + { + if (!yaml_emitter_increase_indent(emitter, 0, + (emitter->mapping_context && !emitter->indention))) + return 0; + } + + if (event->type == YAML_SEQUENCE_END_EVENT) + { + emitter->indent = POP(emitter, emitter->indents); + emitter->state = POP(emitter, emitter->states); + + return 1; + } + + if (!yaml_emitter_write_indent(emitter)) + return 0; + if (!yaml_emitter_write_indicator(emitter, "-", 1, 0, 1)) + return 0; + if (!PUSH(emitter, emitter->states, + YAML_EMIT_BLOCK_SEQUENCE_ITEM_STATE)) + return 0; + + return yaml_emitter_emit_node(emitter, event, 0, 1, 0, 0); +} + +/* + * Expect a block key node. + */ + +static int +yaml_emitter_emit_block_mapping_key(yaml_emitter_t *emitter, + yaml_event_t *event, int first) +{ + if (first) + { + if (!yaml_emitter_increase_indent(emitter, 0, 0)) + return 0; + } + + if (event->type == YAML_MAPPING_END_EVENT) + { + emitter->indent = POP(emitter, emitter->indents); + emitter->state = POP(emitter, emitter->states); + + return 1; + } + + if (!yaml_emitter_write_indent(emitter)) + return 0; + + if (yaml_emitter_check_simple_key(emitter)) + { + if (!PUSH(emitter, emitter->states, + YAML_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE)) + return 0; + + return yaml_emitter_emit_node(emitter, event, 0, 0, 1, 1); + } + else + { + if (!yaml_emitter_write_indicator(emitter, "?", 1, 0, 1)) + return 0; + if (!PUSH(emitter, emitter->states, + YAML_EMIT_BLOCK_MAPPING_VALUE_STATE)) + return 0; + + return yaml_emitter_emit_node(emitter, event, 0, 0, 1, 0); + } +} + +/* + * Expect a block value node. + */ + +static int +yaml_emitter_emit_block_mapping_value(yaml_emitter_t *emitter, + yaml_event_t *event, int simple) +{ + if (simple) { + if (!yaml_emitter_write_indicator(emitter, ":", 0, 0, 0)) + return 0; + } + else { + if (!yaml_emitter_write_indent(emitter)) + return 0; + if (!yaml_emitter_write_indicator(emitter, ":", 1, 0, 1)) + return 0; + } + if (!PUSH(emitter, emitter->states, + YAML_EMIT_BLOCK_MAPPING_KEY_STATE)) + return 0; + + return yaml_emitter_emit_node(emitter, event, 0, 0, 1, 0); +} + +/* + * Expect a node. + */ + +static int +yaml_emitter_emit_node(yaml_emitter_t *emitter, yaml_event_t *event, + int root, int sequence, int mapping, int simple_key) +{ + emitter->root_context = root; + emitter->sequence_context = sequence; + emitter->mapping_context = mapping; + emitter->simple_key_context = simple_key; + + switch (event->type) + { + case YAML_ALIAS_EVENT: + return yaml_emitter_emit_alias(emitter, event); + + case YAML_SCALAR_EVENT: + return yaml_emitter_emit_scalar(emitter, event); + + case YAML_SEQUENCE_START_EVENT: + return yaml_emitter_emit_sequence_start(emitter, event); + + case YAML_MAPPING_START_EVENT: + return yaml_emitter_emit_mapping_start(emitter, event); + + default: + return yaml_emitter_set_emitter_error(emitter, + "expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS"); + } + + return 0; +} + +/* + * Expect ALIAS. + */ + +static int +yaml_emitter_emit_alias(yaml_emitter_t *emitter, yaml_event_t *event) +{ + if (!yaml_emitter_process_anchor(emitter)) + return 0; + emitter->state = POP(emitter, emitter->states); + + return 1; +} + +/* + * Expect SCALAR. + */ + +static int +yaml_emitter_emit_scalar(yaml_emitter_t *emitter, yaml_event_t *event) +{ + if (!yaml_emitter_select_scalar_style(emitter, event)) + return 0; + if (!yaml_emitter_process_anchor(emitter)) + return 0; + if (!yaml_emitter_process_tag(emitter)) + return 0; + if (!yaml_emitter_increase_indent(emitter, 1, 0)) + return 0; + if (!yaml_emitter_process_scalar(emitter)) + return 0; + emitter->indent = POP(emitter, emitter->indents); + emitter->state = POP(emitter, emitter->states); + + return 1; +} + +/* + * Expect SEQUENCE-START. + */ + +static int +yaml_emitter_emit_sequence_start(yaml_emitter_t *emitter, yaml_event_t *event) +{ + if (!yaml_emitter_process_anchor(emitter)) + return 0; + if (!yaml_emitter_process_tag(emitter)) + return 0; + + if (emitter->flow_level || emitter->canonical + || event->data.sequence_start.style == YAML_FLOW_SEQUENCE_STYLE + || yaml_emitter_check_empty_sequence(emitter)) { + emitter->state = YAML_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE; + } + else { + emitter->state = YAML_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE; + } + + return 1; +} + +/* + * Expect MAPPING-START. + */ + +static int +yaml_emitter_emit_mapping_start(yaml_emitter_t *emitter, yaml_event_t *event) +{ + if (!yaml_emitter_process_anchor(emitter)) + return 0; + if (!yaml_emitter_process_tag(emitter)) + return 0; + + if (emitter->flow_level || emitter->canonical + || event->data.mapping_start.style == YAML_FLOW_MAPPING_STYLE + || yaml_emitter_check_empty_mapping(emitter)) { + emitter->state = YAML_EMIT_FLOW_MAPPING_FIRST_KEY_STATE; + } + else { + emitter->state = YAML_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE; + } + + return 1; +} + +/* + * Check if the document content is an empty scalar. + */ + +static int +yaml_emitter_check_empty_document(yaml_emitter_t *emitter) +{ + return 0; +} + +/* + * Check if the next events represent an empty sequence. + */ + +static int +yaml_emitter_check_empty_sequence(yaml_emitter_t *emitter) +{ + if (emitter->events.tail - emitter->events.head < 2) + return 0; + + return (emitter->events.head[0].type == YAML_SEQUENCE_START_EVENT + && emitter->events.head[1].type == YAML_SEQUENCE_END_EVENT); +} + +/* + * Check if the next events represent an empty mapping. + */ + +static int +yaml_emitter_check_empty_mapping(yaml_emitter_t *emitter) +{ + if (emitter->events.tail - emitter->events.head < 2) + return 0; + + return (emitter->events.head[0].type == YAML_MAPPING_START_EVENT + && emitter->events.head[1].type == YAML_MAPPING_END_EVENT); +} + +/* + * Check if the next node can be expressed as a simple key. + */ + +static int +yaml_emitter_check_simple_key(yaml_emitter_t *emitter) +{ + yaml_event_t *event = emitter->events.head; + size_t length = 0; + + switch (event->type) + { + case YAML_ALIAS_EVENT: + length += emitter->anchor_data.anchor_length; + break; + + case YAML_SCALAR_EVENT: + if (emitter->scalar_data.multiline) + return 0; + length += emitter->anchor_data.anchor_length + + emitter->tag_data.handle_length + + emitter->tag_data.suffix_length + + emitter->scalar_data.length; + break; + + case YAML_SEQUENCE_START_EVENT: + if (!yaml_emitter_check_empty_sequence(emitter)) + return 0; + length += emitter->anchor_data.anchor_length + + emitter->tag_data.handle_length + + emitter->tag_data.suffix_length; + break; + + case YAML_MAPPING_START_EVENT: + if (!yaml_emitter_check_empty_mapping(emitter)) + return 0; + length += emitter->anchor_data.anchor_length + + emitter->tag_data.handle_length + + emitter->tag_data.suffix_length; + break; + + default: + return 0; + } + + if (length > 128) + return 0; + + return 1; +} + +/* + * Determine an acceptable scalar style. + */ + +static int +yaml_emitter_select_scalar_style(yaml_emitter_t *emitter, yaml_event_t *event) +{ + yaml_scalar_style_t style = event->data.scalar.style; + int no_tag = (!emitter->tag_data.handle && !emitter->tag_data.suffix); + + if (no_tag && !event->data.scalar.plain_implicit + && !event->data.scalar.quoted_implicit) { + return yaml_emitter_set_emitter_error(emitter, + "neither tag nor implicit flags are specified"); + } + + if (style == YAML_ANY_SCALAR_STYLE) + style = YAML_PLAIN_SCALAR_STYLE; + + if (emitter->canonical) + style = YAML_DOUBLE_QUOTED_SCALAR_STYLE; + + if (emitter->simple_key_context && emitter->scalar_data.multiline) + style = YAML_DOUBLE_QUOTED_SCALAR_STYLE; + + if (style == YAML_PLAIN_SCALAR_STYLE) + { + if ((emitter->flow_level && !emitter->scalar_data.flow_plain_allowed) + || (!emitter->flow_level && !emitter->scalar_data.block_plain_allowed)) + style = YAML_SINGLE_QUOTED_SCALAR_STYLE; + if (!emitter->scalar_data.length + && (emitter->flow_level || emitter->simple_key_context)) + style = YAML_SINGLE_QUOTED_SCALAR_STYLE; + if (no_tag && !event->data.scalar.plain_implicit) + style = YAML_SINGLE_QUOTED_SCALAR_STYLE; + } + + if (style == YAML_SINGLE_QUOTED_SCALAR_STYLE) + { + if (!emitter->scalar_data.single_quoted_allowed) + style = YAML_DOUBLE_QUOTED_SCALAR_STYLE; + } + + if (style == YAML_LITERAL_SCALAR_STYLE || style == YAML_FOLDED_SCALAR_STYLE) + { + if (!emitter->scalar_data.block_allowed + || emitter->flow_level || emitter->simple_key_context) + style = YAML_DOUBLE_QUOTED_SCALAR_STYLE; + } + + if (no_tag && !event->data.scalar.quoted_implicit + && style != YAML_PLAIN_SCALAR_STYLE) + { + emitter->tag_data.handle = (yaml_char_t *)"!"; + emitter->tag_data.handle_length = 1; + } + + emitter->scalar_data.style = style; + + return 1; +} + +/* + * Write an achor. + */ + +static int +yaml_emitter_process_anchor(yaml_emitter_t *emitter) +{ + if (!emitter->anchor_data.anchor) + return 1; + + if (!yaml_emitter_write_indicator(emitter, + (emitter->anchor_data.alias ? "*" : "&"), 1, 0, 0)) + return 0; + + return yaml_emitter_write_anchor(emitter, + emitter->anchor_data.anchor, emitter->anchor_data.anchor_length); +} + +/* + * Write a tag. + */ + +static int +yaml_emitter_process_tag(yaml_emitter_t *emitter) +{ + if (!emitter->tag_data.handle && !emitter->tag_data.suffix) + return 1; + + if (emitter->tag_data.handle) + { + if (!yaml_emitter_write_tag_handle(emitter, emitter->tag_data.handle, + emitter->tag_data.handle_length)) + return 0; + if (emitter->tag_data.suffix) { + if (!yaml_emitter_write_tag_content(emitter, emitter->tag_data.suffix, + emitter->tag_data.suffix_length, 0)) + return 0; + } + } + else + { + if (!yaml_emitter_write_indicator(emitter, "!<", 1, 0, 0)) + return 0; + if (!yaml_emitter_write_tag_content(emitter, emitter->tag_data.suffix, + emitter->tag_data.suffix_length, 0)) + return 0; + if (!yaml_emitter_write_indicator(emitter, ">", 0, 0, 0)) + return 0; + } + + return 1; +} + +/* + * Write a scalar. + */ + +static int +yaml_emitter_process_scalar(yaml_emitter_t *emitter) +{ + switch (emitter->scalar_data.style) + { + case YAML_PLAIN_SCALAR_STYLE: + return yaml_emitter_write_plain_scalar(emitter, + emitter->scalar_data.value, emitter->scalar_data.length, + !emitter->simple_key_context); + + case YAML_SINGLE_QUOTED_SCALAR_STYLE: + return yaml_emitter_write_single_quoted_scalar(emitter, + emitter->scalar_data.value, emitter->scalar_data.length, + !emitter->simple_key_context); + + case YAML_DOUBLE_QUOTED_SCALAR_STYLE: + return yaml_emitter_write_double_quoted_scalar(emitter, + emitter->scalar_data.value, emitter->scalar_data.length, + !emitter->simple_key_context); + + case YAML_LITERAL_SCALAR_STYLE: + return yaml_emitter_write_literal_scalar(emitter, + emitter->scalar_data.value, emitter->scalar_data.length); + + case YAML_FOLDED_SCALAR_STYLE: + return yaml_emitter_write_folded_scalar(emitter, + emitter->scalar_data.value, emitter->scalar_data.length); + + default: + assert(1); /* Impossible. */ + } + + return 0; +} + +/* + * Check if a %YAML directive is valid. + */ + +static int +yaml_emitter_analyze_version_directive(yaml_emitter_t *emitter, + yaml_version_directive_t version_directive) +{ + if (version_directive.major != 1 || version_directive.minor != 1) { + return yaml_emitter_set_emitter_error(emitter, + "incompatible %YAML directive"); + } + + return 1; +} + +/* + * Check if a %TAG directive is valid. + */ + +static int +yaml_emitter_analyze_tag_directive(yaml_emitter_t *emitter, + yaml_tag_directive_t tag_directive) +{ + yaml_string_t handle; + yaml_string_t prefix; + size_t handle_length; + size_t prefix_length; + + handle_length = strlen((char *)tag_directive.handle); + prefix_length = strlen((char *)tag_directive.prefix); + STRING_ASSIGN(handle, tag_directive.handle, handle_length); + STRING_ASSIGN(prefix, tag_directive.prefix, prefix_length); + + if (handle.start == handle.end) { + return yaml_emitter_set_emitter_error(emitter, + "tag handle must not be empty"); + } + + if (handle.start[0] != '!') { + return yaml_emitter_set_emitter_error(emitter, + "tag handle must start with '!'"); + } + + if (handle.end[-1] != '!') { + return yaml_emitter_set_emitter_error(emitter, + "tag handle must end with '!'"); + } + + handle.pointer ++; + + while (handle.pointer < handle.end-1) { + if (!IS_ALPHA(handle)) { + return yaml_emitter_set_emitter_error(emitter, + "tag handle must contain alphanumerical characters only"); + } + MOVE(handle); + } + + if (prefix.start == prefix.end) { + return yaml_emitter_set_emitter_error(emitter, + "tag prefix must not be empty"); + } + + return 1; +} + +/* + * Check if an anchor is valid. + */ + +static int +yaml_emitter_analyze_anchor(yaml_emitter_t *emitter, + yaml_char_t *anchor, int alias) +{ + size_t anchor_length; + yaml_string_t string; + + anchor_length = strlen((char *)anchor); + STRING_ASSIGN(string, anchor, anchor_length); + + if (string.start == string.end) { + return yaml_emitter_set_emitter_error(emitter, alias ? + "alias value must not be empty" : + "anchor value must not be empty"); + } + + while (string.pointer != string.end) { + if (!IS_ALPHA(string)) { + return yaml_emitter_set_emitter_error(emitter, alias ? + "alias value must contain alphanumerical characters only" : + "anchor value must contain alphanumerical characters only"); + } + MOVE(string); + } + + emitter->anchor_data.anchor = string.start; + emitter->anchor_data.anchor_length = string.end - string.start; + emitter->anchor_data.alias = alias; + + return 1; +} + +/* + * Check if a tag is valid. + */ + +static int +yaml_emitter_analyze_tag(yaml_emitter_t *emitter, + yaml_char_t *tag) +{ + size_t tag_length; + yaml_string_t string; + yaml_tag_directive_t *tag_directive; + + tag_length = strlen((char *)tag); + STRING_ASSIGN(string, tag, tag_length); + + if (string.start == string.end) { + return yaml_emitter_set_emitter_error(emitter, + "tag value must not be empty"); + } + + for (tag_directive = emitter->tag_directives.start; + tag_directive != emitter->tag_directives.top; tag_directive ++) { + size_t prefix_length = strlen((char *)tag_directive->prefix); + if (prefix_length < (size_t)(string.end - string.start) + && strncmp((char *)tag_directive->prefix, (char *)string.start, + prefix_length) == 0) + { + emitter->tag_data.handle = tag_directive->handle; + emitter->tag_data.handle_length = + strlen((char *)tag_directive->handle); + emitter->tag_data.suffix = string.start + prefix_length; + emitter->tag_data.suffix_length = + (string.end - string.start) - prefix_length; + return 1; + } + } + + emitter->tag_data.suffix = string.start; + emitter->tag_data.suffix_length = string.end - string.start; + + return 1; +} + +/* + * Check if a scalar is valid. + */ + +static int +yaml_emitter_analyze_scalar(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length) +{ + yaml_string_t string; + + int block_indicators = 0; + int flow_indicators = 0; + int line_breaks = 0; + int special_characters = 0; + + int leading_space = 0; + int leading_break = 0; + int trailing_space = 0; + int trailing_break = 0; + int break_space = 0; + int space_break = 0; + + int preceeded_by_whitespace = 0; + int followed_by_whitespace = 0; + int previous_space = 0; + int previous_break = 0; + + STRING_ASSIGN(string, value, length); + + emitter->scalar_data.value = value; + emitter->scalar_data.length = length; + + if (string.start == string.end) + { + emitter->scalar_data.multiline = 0; + emitter->scalar_data.flow_plain_allowed = 0; + emitter->scalar_data.block_plain_allowed = 1; + emitter->scalar_data.single_quoted_allowed = 1; + emitter->scalar_data.block_allowed = 0; + + return 1; + } + + if ((CHECK_AT(string, '-', 0) + && CHECK_AT(string, '-', 1) + && CHECK_AT(string, '-', 2)) + || (CHECK_AT(string, '.', 0) + && CHECK_AT(string, '.', 1) + && CHECK_AT(string, '.', 2))) { + block_indicators = 1; + flow_indicators = 1; + } + + preceeded_by_whitespace = 1; + followed_by_whitespace = IS_BLANKZ_AT(string, WIDTH(string)); + + while (string.pointer != string.end) + { + if (string.start == string.pointer) + { + if (CHECK(string, '#') || CHECK(string, ',') + || CHECK(string, '[') || CHECK(string, ']') + || CHECK(string, '{') || CHECK(string, '}') + || CHECK(string, '&') || CHECK(string, '*') + || CHECK(string, '!') || CHECK(string, '|') + || CHECK(string, '>') || CHECK(string, '\'') + || CHECK(string, '"') || CHECK(string, '%') + || CHECK(string, '@') || CHECK(string, '`')) { + flow_indicators = 1; + block_indicators = 1; + } + + if (CHECK(string, '?') || CHECK(string, ':')) { + flow_indicators = 1; + if (followed_by_whitespace) { + block_indicators = 1; + } + } + + if (CHECK(string, '-') && followed_by_whitespace) { + flow_indicators = 1; + block_indicators = 1; + } + } + else + { + if (CHECK(string, ',') || CHECK(string, '?') + || CHECK(string, '[') || CHECK(string, ']') + || CHECK(string, '{') || CHECK(string, '}')) { + flow_indicators = 1; + } + + if (CHECK(string, ':')) { + flow_indicators = 1; + if (followed_by_whitespace) { + block_indicators = 1; + } + } + + if (CHECK(string, '#') && preceeded_by_whitespace) { + flow_indicators = 1; + block_indicators = 1; + } + } + + if (!IS_PRINTABLE(string) + || (!IS_ASCII(string) && !emitter->unicode)) { + special_characters = 1; + } + + if (IS_BREAK(string)) { + line_breaks = 1; + } + + if (IS_SPACE(string)) + { + if (string.start == string.pointer) { + leading_space = 1; + } + if (string.pointer+WIDTH(string) == string.end) { + trailing_space = 1; + } + if (previous_break) { + break_space = 1; + } + previous_space = 1; + previous_break = 0; + } + else if (IS_BREAK(string)) + { + if (string.start == string.pointer) { + leading_break = 1; + } + if (string.pointer+WIDTH(string) == string.end) { + trailing_break = 1; + } + if (previous_space) { + space_break = 1; + } + previous_space = 0; + previous_break = 1; + } + else + { + previous_space = 0; + previous_break = 0; + } + + preceeded_by_whitespace = IS_BLANKZ(string); + MOVE(string); + if (string.pointer != string.end) { + followed_by_whitespace = IS_BLANKZ_AT(string, WIDTH(string)); + } + } + + emitter->scalar_data.multiline = line_breaks; + + emitter->scalar_data.flow_plain_allowed = 1; + emitter->scalar_data.block_plain_allowed = 1; + emitter->scalar_data.single_quoted_allowed = 1; + emitter->scalar_data.block_allowed = 1; + + if (leading_space || leading_break || trailing_space || trailing_break) { + emitter->scalar_data.flow_plain_allowed = 0; + emitter->scalar_data.block_plain_allowed = 0; + } + + if (trailing_space) { + emitter->scalar_data.block_allowed = 0; + } + + if (break_space) { + emitter->scalar_data.flow_plain_allowed = 0; + emitter->scalar_data.block_plain_allowed = 0; + emitter->scalar_data.single_quoted_allowed = 0; + } + + if (space_break || special_characters) { + emitter->scalar_data.flow_plain_allowed = 0; + emitter->scalar_data.block_plain_allowed = 0; + emitter->scalar_data.single_quoted_allowed = 0; + emitter->scalar_data.block_allowed = 0; + } + + if (line_breaks) { + emitter->scalar_data.flow_plain_allowed = 0; + emitter->scalar_data.block_plain_allowed = 0; + } + + if (flow_indicators) { + emitter->scalar_data.flow_plain_allowed = 0; + } + + if (block_indicators) { + emitter->scalar_data.block_plain_allowed = 0; + } + + return 1; +} + +/* + * Check if the event data is valid. + */ + +static int +yaml_emitter_analyze_event(yaml_emitter_t *emitter, + yaml_event_t *event) +{ + emitter->anchor_data.anchor = NULL; + emitter->anchor_data.anchor_length = 0; + emitter->tag_data.handle = NULL; + emitter->tag_data.handle_length = 0; + emitter->tag_data.suffix = NULL; + emitter->tag_data.suffix_length = 0; + emitter->scalar_data.value = NULL; + emitter->scalar_data.length = 0; + + switch (event->type) + { + case YAML_ALIAS_EVENT: + if (!yaml_emitter_analyze_anchor(emitter, + event->data.alias.anchor, 1)) + return 0; + return 1; + + case YAML_SCALAR_EVENT: + if (event->data.scalar.anchor) { + if (!yaml_emitter_analyze_anchor(emitter, + event->data.scalar.anchor, 0)) + return 0; + } + if (event->data.scalar.tag && (emitter->canonical || + (!event->data.scalar.plain_implicit + && !event->data.scalar.quoted_implicit))) { + if (!yaml_emitter_analyze_tag(emitter, event->data.scalar.tag)) + return 0; + } + if (!yaml_emitter_analyze_scalar(emitter, + event->data.scalar.value, event->data.scalar.length)) + return 0; + return 1; + + case YAML_SEQUENCE_START_EVENT: + if (event->data.sequence_start.anchor) { + if (!yaml_emitter_analyze_anchor(emitter, + event->data.sequence_start.anchor, 0)) + return 0; + } + if (event->data.sequence_start.tag && (emitter->canonical || + !event->data.sequence_start.implicit)) { + if (!yaml_emitter_analyze_tag(emitter, + event->data.sequence_start.tag)) + return 0; + } + return 1; + + case YAML_MAPPING_START_EVENT: + if (event->data.mapping_start.anchor) { + if (!yaml_emitter_analyze_anchor(emitter, + event->data.mapping_start.anchor, 0)) + return 0; + } + if (event->data.mapping_start.tag && (emitter->canonical || + !event->data.mapping_start.implicit)) { + if (!yaml_emitter_analyze_tag(emitter, + event->data.mapping_start.tag)) + return 0; + } + return 1; + + default: + return 1; + } +} + +/* + * Write the BOM character. + */ + +static int +yaml_emitter_write_bom(yaml_emitter_t *emitter) +{ + if (!FLUSH(emitter)) return 0; + + *(emitter->buffer.pointer++) = (yaml_char_t) '\xEF'; + *(emitter->buffer.pointer++) = (yaml_char_t) '\xBB'; + *(emitter->buffer.pointer++) = (yaml_char_t) '\xBF'; + + return 1; +} + +static int +yaml_emitter_write_indent(yaml_emitter_t *emitter) +{ + int indent = (emitter->indent >= 0) ? emitter->indent : 0; + + if (!emitter->indention || emitter->column > indent + || (emitter->column == indent && !emitter->whitespace)) { + if (!PUT_BREAK(emitter)) return 0; + } + + while (emitter->column < indent) { + if (!PUT(emitter, ' ')) return 0; + } + + emitter->whitespace = 1; + emitter->indention = 1; + + return 1; +} + +static int +yaml_emitter_write_indicator(yaml_emitter_t *emitter, + char *indicator, int need_whitespace, + int is_whitespace, int is_indention) +{ + size_t indicator_length; + yaml_string_t string; + + indicator_length = strlen(indicator); + STRING_ASSIGN(string, (yaml_char_t *)indicator, indicator_length); + + if (need_whitespace && !emitter->whitespace) { + if (!PUT(emitter, ' ')) return 0; + } + + while (string.pointer != string.end) { + if (!WRITE(emitter, string)) return 0; + } + + emitter->whitespace = is_whitespace; + emitter->indention = (emitter->indention && is_indention); + emitter->open_ended = 0; + + return 1; +} + +static int +yaml_emitter_write_anchor(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length) +{ + yaml_string_t string; + STRING_ASSIGN(string, value, length); + + while (string.pointer != string.end) { + if (!WRITE(emitter, string)) return 0; + } + + emitter->whitespace = 0; + emitter->indention = 0; + + return 1; +} + +static int +yaml_emitter_write_tag_handle(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length) +{ + yaml_string_t string; + STRING_ASSIGN(string, value, length); + + if (!emitter->whitespace) { + if (!PUT(emitter, ' ')) return 0; + } + + while (string.pointer != string.end) { + if (!WRITE(emitter, string)) return 0; + } + + emitter->whitespace = 0; + emitter->indention = 0; + + return 1; +} + +static int +yaml_emitter_write_tag_content(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length, + int need_whitespace) +{ + yaml_string_t string; + STRING_ASSIGN(string, value, length); + + if (need_whitespace && !emitter->whitespace) { + if (!PUT(emitter, ' ')) return 0; + } + + while (string.pointer != string.end) { + if (IS_ALPHA(string) + || CHECK(string, ';') || CHECK(string, '/') + || CHECK(string, '?') || CHECK(string, ':') + || CHECK(string, '@') || CHECK(string, '&') + || CHECK(string, '=') || CHECK(string, '+') + || CHECK(string, '$') || CHECK(string, ',') + || CHECK(string, '_') || CHECK(string, '.') + || CHECK(string, '~') || CHECK(string, '*') + || CHECK(string, '\'') || CHECK(string, '(') + || CHECK(string, ')') || CHECK(string, '[') + || CHECK(string, ']')) { + if (!WRITE(emitter, string)) return 0; + } + else { + int width = WIDTH(string); + unsigned int value; + while (width --) { + value = *(string.pointer++); + if (!PUT(emitter, '%')) return 0; + if (!PUT(emitter, (value >> 4) + + ((value >> 4) < 10 ? '0' : 'A' - 10))) + return 0; + if (!PUT(emitter, (value & 0x0F) + + ((value & 0x0F) < 10 ? '0' : 'A' - 10))) + return 0; + } + } + } + + emitter->whitespace = 0; + emitter->indention = 0; + + return 1; +} + +static int +yaml_emitter_write_plain_scalar(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length, int allow_breaks) +{ + yaml_string_t string; + int spaces = 0; + int breaks = 0; + + STRING_ASSIGN(string, value, length); + + if (!emitter->whitespace) { + if (!PUT(emitter, ' ')) return 0; + } + + while (string.pointer != string.end) + { + if (IS_SPACE(string)) + { + if (allow_breaks && !spaces + && emitter->column > emitter->best_width + && !IS_SPACE_AT(string, 1)) { + if (!yaml_emitter_write_indent(emitter)) return 0; + MOVE(string); + } + else { + if (!WRITE(emitter, string)) return 0; + } + spaces = 1; + } + else if (IS_BREAK(string)) + { + if (!breaks && CHECK(string, '\n')) { + if (!PUT_BREAK(emitter)) return 0; + } + if (!WRITE_BREAK(emitter, string)) return 0; + emitter->indention = 1; + breaks = 1; + } + else + { + if (breaks) { + if (!yaml_emitter_write_indent(emitter)) return 0; + } + if (!WRITE(emitter, string)) return 0; + emitter->indention = 0; + spaces = 0; + breaks = 0; + } + } + + emitter->whitespace = 0; + emitter->indention = 0; + if (emitter->root_context) + { + emitter->open_ended = 1; + } + + return 1; +} + +static int +yaml_emitter_write_single_quoted_scalar(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length, int allow_breaks) +{ + yaml_string_t string; + int spaces = 0; + int breaks = 0; + + STRING_ASSIGN(string, value, length); + + if (!yaml_emitter_write_indicator(emitter, "'", 1, 0, 0)) + return 0; + + while (string.pointer != string.end) + { + if (IS_SPACE(string)) + { + if (allow_breaks && !spaces + && emitter->column > emitter->best_width + && string.pointer != string.start + && string.pointer != string.end - 1 + && !IS_SPACE_AT(string, 1)) { + if (!yaml_emitter_write_indent(emitter)) return 0; + MOVE(string); + } + else { + if (!WRITE(emitter, string)) return 0; + } + spaces = 1; + } + else if (IS_BREAK(string)) + { + if (!breaks && CHECK(string, '\n')) { + if (!PUT_BREAK(emitter)) return 0; + } + if (!WRITE_BREAK(emitter, string)) return 0; + emitter->indention = 1; + breaks = 1; + } + else + { + if (breaks) { + if (!yaml_emitter_write_indent(emitter)) return 0; + } + if (CHECK(string, '\'')) { + if (!PUT(emitter, '\'')) return 0; + } + if (!WRITE(emitter, string)) return 0; + emitter->indention = 0; + spaces = 0; + breaks = 0; + } + } + + if (!yaml_emitter_write_indicator(emitter, "'", 0, 0, 0)) + return 0; + + emitter->whitespace = 0; + emitter->indention = 0; + + return 1; +} + +static int +yaml_emitter_write_double_quoted_scalar(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length, int allow_breaks) +{ + yaml_string_t string; + int spaces = 0; + + STRING_ASSIGN(string, value, length); + + if (!yaml_emitter_write_indicator(emitter, "\"", 1, 0, 0)) + return 0; + + while (string.pointer != string.end) + { + if (!IS_PRINTABLE(string) || (!emitter->unicode && !IS_ASCII(string)) + || IS_BOM(string) || IS_BREAK(string) + || CHECK(string, '"') || CHECK(string, '\\')) + { + unsigned char octet; + unsigned int width; + unsigned int value; + int k; + + octet = string.pointer[0]; + width = (octet & 0x80) == 0x00 ? 1 : + (octet & 0xE0) == 0xC0 ? 2 : + (octet & 0xF0) == 0xE0 ? 3 : + (octet & 0xF8) == 0xF0 ? 4 : 0; + value = (octet & 0x80) == 0x00 ? octet & 0x7F : + (octet & 0xE0) == 0xC0 ? octet & 0x1F : + (octet & 0xF0) == 0xE0 ? octet & 0x0F : + (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0; + for (k = 1; k < (int)width; k ++) { + octet = string.pointer[k]; + value = (value << 6) + (octet & 0x3F); + } + string.pointer += width; + + if (!PUT(emitter, '\\')) return 0; + + switch (value) + { + case 0x00: + if (!PUT(emitter, '0')) return 0; + break; + + case 0x07: + if (!PUT(emitter, 'a')) return 0; + break; + + case 0x08: + if (!PUT(emitter, 'b')) return 0; + break; + + case 0x09: + if (!PUT(emitter, 't')) return 0; + break; + + case 0x0A: + if (!PUT(emitter, 'n')) return 0; + break; + + case 0x0B: + if (!PUT(emitter, 'v')) return 0; + break; + + case 0x0C: + if (!PUT(emitter, 'f')) return 0; + break; + + case 0x0D: + if (!PUT(emitter, 'r')) return 0; + break; + + case 0x1B: + if (!PUT(emitter, 'e')) return 0; + break; + + case 0x22: + if (!PUT(emitter, '\"')) return 0; + break; + + case 0x5C: + if (!PUT(emitter, '\\')) return 0; + break; + + case 0x85: + if (!PUT(emitter, 'N')) return 0; + break; + + case 0xA0: + if (!PUT(emitter, '_')) return 0; + break; + + case 0x2028: + if (!PUT(emitter, 'L')) return 0; + break; + + case 0x2029: + if (!PUT(emitter, 'P')) return 0; + break; + + default: + if (value <= 0xFF) { + if (!PUT(emitter, 'x')) return 0; + width = 2; + } + else if (value <= 0xFFFF) { + if (!PUT(emitter, 'u')) return 0; + width = 4; + } + else { + if (!PUT(emitter, 'U')) return 0; + width = 8; + } + for (k = (width-1)*4; k >= 0; k -= 4) { + int digit = (value >> k) & 0x0F; + if (!PUT(emitter, digit + (digit < 10 ? '0' : 'A'-10))) + return 0; + } + } + spaces = 0; + } + else if (IS_SPACE(string)) + { + if (allow_breaks && !spaces + && emitter->column > emitter->best_width + && string.pointer != string.start + && string.pointer != string.end - 1) { + if (!yaml_emitter_write_indent(emitter)) return 0; + if (IS_SPACE_AT(string, 1)) { + if (!PUT(emitter, '\\')) return 0; + } + MOVE(string); + } + else { + if (!WRITE(emitter, string)) return 0; + } + spaces = 1; + } + else + { + if (!WRITE(emitter, string)) return 0; + spaces = 0; + } + } + + if (!yaml_emitter_write_indicator(emitter, "\"", 0, 0, 0)) + return 0; + + emitter->whitespace = 0; + emitter->indention = 0; + + return 1; +} + +static int +yaml_emitter_write_block_scalar_hints(yaml_emitter_t *emitter, + yaml_string_t string) +{ + char indent_hint[2]; + char *chomp_hint = NULL; + + if (IS_SPACE(string) || IS_BREAK(string)) + { + indent_hint[0] = '0' + (char)emitter->best_indent; + indent_hint[1] = '\0'; + if (!yaml_emitter_write_indicator(emitter, indent_hint, 0, 0, 0)) + return 0; + } + + emitter->open_ended = 0; + + string.pointer = string.end; + if (string.start == string.pointer) + { + chomp_hint = "-"; + } + else + { + do { + string.pointer --; + } while ((*string.pointer & 0xC0) == 0x80); + if (!IS_BREAK(string)) + { + chomp_hint = "-"; + } + else if (string.start == string.pointer) + { + chomp_hint = "+"; + emitter->open_ended = 1; + } + else + { + do { + string.pointer --; + } while ((*string.pointer & 0xC0) == 0x80); + if (IS_BREAK(string)) + { + chomp_hint = "+"; + emitter->open_ended = 1; + } + } + } + + if (chomp_hint) + { + if (!yaml_emitter_write_indicator(emitter, chomp_hint, 0, 0, 0)) + return 0; + } + + return 1; +} + +static int +yaml_emitter_write_literal_scalar(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length) +{ + yaml_string_t string; + int breaks = 1; + + STRING_ASSIGN(string, value, length); + + if (!yaml_emitter_write_indicator(emitter, "|", 1, 0, 0)) + return 0; + if (!yaml_emitter_write_block_scalar_hints(emitter, string)) + return 0; + if (!PUT_BREAK(emitter)) return 0; + emitter->indention = 1; + emitter->whitespace = 1; + + while (string.pointer != string.end) + { + if (IS_BREAK(string)) + { + if (!WRITE_BREAK(emitter, string)) return 0; + emitter->indention = 1; + breaks = 1; + } + else + { + if (breaks) { + if (!yaml_emitter_write_indent(emitter)) return 0; + } + if (!WRITE(emitter, string)) return 0; + emitter->indention = 0; + breaks = 0; + } + } + + return 1; +} + +static int +yaml_emitter_write_folded_scalar(yaml_emitter_t *emitter, + yaml_char_t *value, size_t length) +{ + yaml_string_t string; + int breaks = 1; + int leading_spaces = 1; + + STRING_ASSIGN(string, value, length); + + if (!yaml_emitter_write_indicator(emitter, ">", 1, 0, 0)) + return 0; + if (!yaml_emitter_write_block_scalar_hints(emitter, string)) + return 0; + if (!PUT_BREAK(emitter)) return 0; + emitter->indention = 1; + emitter->whitespace = 1; + + while (string.pointer != string.end) + { + if (IS_BREAK(string)) + { + if (!breaks && !leading_spaces && CHECK(string, '\n')) { + int k = 0; + while (IS_BREAK_AT(string, k)) { + k += WIDTH_AT(string, k); + } + if (!IS_BLANKZ_AT(string, k)) { + if (!PUT_BREAK(emitter)) return 0; + } + } + if (!WRITE_BREAK(emitter, string)) return 0; + emitter->indention = 1; + breaks = 1; + } + else + { + if (breaks) { + if (!yaml_emitter_write_indent(emitter)) return 0; + leading_spaces = IS_BLANK(string); + } + if (!breaks && IS_SPACE(string) && !IS_SPACE_AT(string, 1) + && emitter->column > emitter->best_width) { + if (!yaml_emitter_write_indent(emitter)) return 0; + MOVE(string); + } + else { + if (!WRITE(emitter, string)) return 0; + } + emitter->indention = 0; + breaks = 0; + } + } + + return 1; +} + diff --git a/src/loader.c b/src/loader.c new file mode 100644 index 00000000000..9d3d912663c --- /dev/null +++ b/src/loader.c @@ -0,0 +1,432 @@ + +#include "yaml_private.h" + +/* + * API functions. + */ + +YAML_DECLARE(int) +yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document); + +/* + * Error handling. + */ + +static int +yaml_parser_set_composer_error(yaml_parser_t *parser, + const char *problem, yaml_mark_t problem_mark); + +static int +yaml_parser_set_composer_error_context(yaml_parser_t *parser, + const char *context, yaml_mark_t context_mark, + const char *problem, yaml_mark_t problem_mark); + + +/* + * Alias handling. + */ + +static int +yaml_parser_register_anchor(yaml_parser_t *parser, + int index, yaml_char_t *anchor); + +/* + * Clean up functions. + */ + +static void +yaml_parser_delete_aliases(yaml_parser_t *parser); + +/* + * Composer functions. + */ + +static int +yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *first_event); + +static int +yaml_parser_load_node(yaml_parser_t *parser, yaml_event_t *first_event); + +static int +yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *first_event); + +static int +yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *first_event); + +static int +yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *first_event); + +static int +yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event); + +/* + * Load the next document of the stream. + */ + +YAML_DECLARE(int) +yaml_parser_load(yaml_parser_t *parser, yaml_document_t *document) +{ + yaml_event_t event; + + assert(parser); /* Non-NULL parser object is expected. */ + assert(document); /* Non-NULL document object is expected. */ + + memset(document, 0, sizeof(yaml_document_t)); + if (!STACK_INIT(parser, document->nodes, INITIAL_STACK_SIZE)) + goto error; + + if (!parser->stream_start_produced) { + if (!yaml_parser_parse(parser, &event)) goto error; + assert(event.type == YAML_STREAM_START_EVENT); + /* STREAM-START is expected. */ + } + + if (parser->stream_end_produced) { + return 1; + } + + if (!yaml_parser_parse(parser, &event)) goto error; + if (event.type == YAML_STREAM_END_EVENT) { + return 1; + } + + if (!STACK_INIT(parser, parser->aliases, INITIAL_STACK_SIZE)) + goto error; + + parser->document = document; + + if (!yaml_parser_load_document(parser, &event)) goto error; + + yaml_parser_delete_aliases(parser); + parser->document = NULL; + + return 1; + +error: + + yaml_parser_delete_aliases(parser); + yaml_document_delete(document); + parser->document = NULL; + + return 0; +} + +/* + * Set composer error. + */ + +static int +yaml_parser_set_composer_error(yaml_parser_t *parser, + const char *problem, yaml_mark_t problem_mark) +{ + parser->error = YAML_COMPOSER_ERROR; + parser->problem = problem; + parser->problem_mark = problem_mark; + + return 0; +} + +/* + * Set composer error with context. + */ + +static int +yaml_parser_set_composer_error_context(yaml_parser_t *parser, + const char *context, yaml_mark_t context_mark, + const char *problem, yaml_mark_t problem_mark) +{ + parser->error = YAML_COMPOSER_ERROR; + parser->context = context; + parser->context_mark = context_mark; + parser->problem = problem; + parser->problem_mark = problem_mark; + + return 0; +} + +/* + * Delete the stack of aliases. + */ + +static void +yaml_parser_delete_aliases(yaml_parser_t *parser) +{ + while (!STACK_EMPTY(parser, parser->aliases)) { + yaml_free(POP(parser, parser->aliases).anchor); + } + STACK_DEL(parser, parser->aliases); +} + +/* + * Compose a document object. + */ + +static int +yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *first_event) +{ + yaml_event_t event; + + assert(first_event->type == YAML_DOCUMENT_START_EVENT); + /* DOCUMENT-START is expected. */ + + parser->document->version_directive + = first_event->data.document_start.version_directive; + parser->document->tag_directives.start + = first_event->data.document_start.tag_directives.start; + parser->document->tag_directives.end + = first_event->data.document_start.tag_directives.end; + parser->document->start_implicit + = first_event->data.document_start.implicit; + parser->document->start_mark = first_event->start_mark; + + if (!yaml_parser_parse(parser, &event)) return 0; + + if (!yaml_parser_load_node(parser, &event)) return 0; + + if (!yaml_parser_parse(parser, &event)) return 0; + assert(event.type == YAML_DOCUMENT_END_EVENT); + /* DOCUMENT-END is expected. */ + + parser->document->end_implicit = event.data.document_end.implicit; + parser->document->end_mark = event.end_mark; + + return 1; +} + +/* + * Compose a node. + */ + +static int +yaml_parser_load_node(yaml_parser_t *parser, yaml_event_t *first_event) +{ + switch (first_event->type) { + case YAML_ALIAS_EVENT: + return yaml_parser_load_alias(parser, first_event); + case YAML_SCALAR_EVENT: + return yaml_parser_load_scalar(parser, first_event); + case YAML_SEQUENCE_START_EVENT: + return yaml_parser_load_sequence(parser, first_event); + case YAML_MAPPING_START_EVENT: + return yaml_parser_load_mapping(parser, first_event); + default: + assert(0); /* Could not happen. */ + return 0; + } + + return 0; +} + +/* + * Add an anchor. + */ + +static int +yaml_parser_register_anchor(yaml_parser_t *parser, + int index, yaml_char_t *anchor) +{ + yaml_alias_data_t data; + yaml_alias_data_t *alias_data; + + if (!anchor) return 1; + + data.anchor = anchor; + data.index = index; + data.mark = parser->document->nodes.start[index-1].start_mark; + + for (alias_data = parser->aliases.start; + alias_data != parser->aliases.top; alias_data ++) { + if (strcmp((char *)alias_data->anchor, (char *)anchor) == 0) { + yaml_free(anchor); + return yaml_parser_set_composer_error_context(parser, + "found duplicate anchor; first occurence", + alias_data->mark, "second occurence", data.mark); + } + } + + if (!PUSH(parser, parser->aliases, data)) { + yaml_free(anchor); + return 0; + } + + return 1; +} + +/* + * Compose a node corresponding to an alias. + */ + +static int +yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *first_event) +{ + yaml_char_t *anchor = first_event->data.alias.anchor; + yaml_alias_data_t *alias_data; + + for (alias_data = parser->aliases.start; + alias_data != parser->aliases.top; alias_data ++) { + if (strcmp((char *)alias_data->anchor, (char *)anchor) == 0) { + yaml_free(anchor); + return alias_data->index; + } + } + + yaml_free(anchor); + return yaml_parser_set_composer_error(parser, "found undefined alias", + first_event->start_mark); +} + +/* + * Compose a scalar node. + */ + +static int +yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *first_event) +{ + yaml_node_t node; + int index; + yaml_char_t *tag = first_event->data.scalar.tag; + + if (!tag || strcmp((char *)tag, "!") == 0) { + yaml_free(tag); + tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SCALAR_TAG); + if (!tag) goto error; + } + + SCALAR_NODE_INIT(node, tag, first_event->data.scalar.value, + first_event->data.scalar.length, first_event->data.scalar.style, + first_event->start_mark, first_event->end_mark); + + if (!PUSH(parser, parser->document->nodes, node)) goto error; + + index = parser->document->nodes.top - parser->document->nodes.start; + + if (!yaml_parser_register_anchor(parser, index, + first_event->data.scalar.anchor)) return 0; + + return index; + +error: + yaml_free(tag); + yaml_free(first_event->data.scalar.anchor); + yaml_free(first_event->data.scalar.value); + return 0; +} + +/* + * Compose a sequence node. + */ + +static int +yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *first_event) +{ + yaml_event_t event; + yaml_node_t node; + struct { + yaml_node_item_t *start; + yaml_node_item_t *end; + yaml_node_item_t *top; + } items = { NULL, NULL, NULL }; + int index, item_index; + yaml_char_t *tag = first_event->data.sequence_start.tag; + + if (!tag || strcmp((char *)tag, "!") == 0) { + yaml_free(tag); + tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG); + if (!tag) goto error; + } + + if (!STACK_INIT(parser, items, INITIAL_STACK_SIZE)) goto error; + + SEQUENCE_NODE_INIT(node, tag, items.start, items.end, + first_event->data.sequence_start.style, + first_event->start_mark, first_event->end_mark); + + if (!PUSH(parser, parser->document->nodes, node)) goto error; + + index = parser->document->nodes.top - parser->document->nodes.start; + + if (!yaml_parser_register_anchor(parser, index, + first_event->data.sequence_start.anchor)) return 0; + + if (!yaml_parser_parse(parser, &event)) return 0; + + while (event.type != YAML_SEQUENCE_END_EVENT) { + item_index = yaml_parser_load_node(parser, &event); + if (!item_index) return 0; + if (!PUSH(parser, + parser->document->nodes.start[index-1].data.sequence.items, + item_index)) return 0; + if (!yaml_parser_parse(parser, &event)) return 0; + } + + parser->document->nodes.start[index-1].end_mark = event.end_mark; + + return index; + +error: + yaml_free(tag); + yaml_free(first_event->data.sequence_start.anchor); + return 0; +} + +/* + * Compose a mapping node. + */ + +static int +yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event) +{ + yaml_event_t event; + yaml_node_t node; + struct { + yaml_node_pair_t *start; + yaml_node_pair_t *end; + yaml_node_pair_t *top; + } pairs = { NULL, NULL, NULL }; + int index; + yaml_node_pair_t pair; + yaml_char_t *tag = first_event->data.mapping_start.tag; + + if (!tag || strcmp((char *)tag, "!") == 0) { + yaml_free(tag); + tag = yaml_strdup((yaml_char_t *)YAML_DEFAULT_MAPPING_TAG); + if (!tag) goto error; + } + + if (!STACK_INIT(parser, pairs, INITIAL_STACK_SIZE)) goto error; + + MAPPING_NODE_INIT(node, tag, pairs.start, pairs.end, + first_event->data.mapping_start.style, + first_event->start_mark, first_event->end_mark); + + if (!PUSH(parser, parser->document->nodes, node)) goto error; + + index = parser->document->nodes.top - parser->document->nodes.start; + + if (!yaml_parser_register_anchor(parser, index, + first_event->data.mapping_start.anchor)) return 0; + + if (!yaml_parser_parse(parser, &event)) return 0; + + while (event.type != YAML_MAPPING_END_EVENT) { + pair.key = yaml_parser_load_node(parser, &event); + if (!pair.key) return 0; + if (!yaml_parser_parse(parser, &event)) return 0; + pair.value = yaml_parser_load_node(parser, &event); + if (!pair.value) return 0; + if (!PUSH(parser, + parser->document->nodes.start[index-1].data.mapping.pairs, + pair)) return 0; + if (!yaml_parser_parse(parser, &event)) return 0; + } + + parser->document->nodes.start[index-1].end_mark = event.end_mark; + + return index; + +error: + yaml_free(tag); + yaml_free(first_event->data.mapping_start.anchor); + return 0; +} + diff --git a/src/parser.c b/src/parser.c new file mode 100644 index 00000000000..eb2a2c792b7 --- /dev/null +++ b/src/parser.c @@ -0,0 +1,1374 @@ + +/* + * The parser implements the following grammar: + * + * stream ::= STREAM-START implicit_document? explicit_document* STREAM-END + * implicit_document ::= block_node DOCUMENT-END* + * explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* + * block_node_or_indentless_sequence ::= + * ALIAS + * | properties (block_content | indentless_block_sequence)? + * | block_content + * | indentless_block_sequence + * block_node ::= ALIAS + * | properties block_content? + * | block_content + * flow_node ::= ALIAS + * | properties flow_content? + * | flow_content + * properties ::= TAG ANCHOR? | ANCHOR TAG? + * block_content ::= block_collection | flow_collection | SCALAR + * flow_content ::= flow_collection | SCALAR + * block_collection ::= block_sequence | block_mapping + * flow_collection ::= flow_sequence | flow_mapping + * block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END + * indentless_sequence ::= (BLOCK-ENTRY block_node?)+ + * block_mapping ::= BLOCK-MAPPING_START + * ((KEY block_node_or_indentless_sequence?)? + * (VALUE block_node_or_indentless_sequence?)?)* + * BLOCK-END + * flow_sequence ::= FLOW-SEQUENCE-START + * (flow_sequence_entry FLOW-ENTRY)* + * flow_sequence_entry? + * FLOW-SEQUENCE-END + * flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? + * flow_mapping ::= FLOW-MAPPING-START + * (flow_mapping_entry FLOW-ENTRY)* + * flow_mapping_entry? + * FLOW-MAPPING-END + * flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? + */ + +#include "yaml_private.h" + +/* + * Peek the next token in the token queue. + */ + +#define PEEK_TOKEN(parser) \ + ((parser->token_available || yaml_parser_fetch_more_tokens(parser)) ? \ + parser->tokens.head : NULL) + +/* + * Remove the next token from the queue (must be called after PEEK_TOKEN). + */ + +#define SKIP_TOKEN(parser) \ + (parser->token_available = 0, \ + parser->tokens_parsed ++, \ + parser->stream_end_produced = \ + (parser->tokens.head->type == YAML_STREAM_END_TOKEN), \ + parser->tokens.head ++) + +/* + * Public API declarations. + */ + +YAML_DECLARE(int) +yaml_parser_parse(yaml_parser_t *parser, yaml_event_t *event); + +/* + * Error handling. + */ + +static int +yaml_parser_set_parser_error(yaml_parser_t *parser, + const char *problem, yaml_mark_t problem_mark); + +static int +yaml_parser_set_parser_error_context(yaml_parser_t *parser, + const char *context, yaml_mark_t context_mark, + const char *problem, yaml_mark_t problem_mark); + +/* + * State functions. + */ + +static int +yaml_parser_state_machine(yaml_parser_t *parser, yaml_event_t *event); + +static int +yaml_parser_parse_stream_start(yaml_parser_t *parser, yaml_event_t *event); + +static int +yaml_parser_parse_document_start(yaml_parser_t *parser, yaml_event_t *event, + int implicit); + +static int +yaml_parser_parse_document_content(yaml_parser_t *parser, yaml_event_t *event); + +static int +yaml_parser_parse_document_end(yaml_parser_t *parser, yaml_event_t *event); + +static int +yaml_parser_parse_node(yaml_parser_t *parser, yaml_event_t *event, + int block, int indentless_sequence); + +static int +yaml_parser_parse_block_sequence_entry(yaml_parser_t *parser, + yaml_event_t *event, int first); + +static int +yaml_parser_parse_indentless_sequence_entry(yaml_parser_t *parser, + yaml_event_t *event); + +static int +yaml_parser_parse_block_mapping_key(yaml_parser_t *parser, + yaml_event_t *event, int first); + +static int +yaml_parser_parse_block_mapping_value(yaml_parser_t *parser, + yaml_event_t *event); + +static int +yaml_parser_parse_flow_sequence_entry(yaml_parser_t *parser, + yaml_event_t *event, int first); + +static int +yaml_parser_parse_flow_sequence_entry_mapping_key(yaml_parser_t *parser, + yaml_event_t *event); + +static int +yaml_parser_parse_flow_sequence_entry_mapping_value(yaml_parser_t *parser, + yaml_event_t *event); + +static int +yaml_parser_parse_flow_sequence_entry_mapping_end(yaml_parser_t *parser, + yaml_event_t *event); + +static int +yaml_parser_parse_flow_mapping_key(yaml_parser_t *parser, + yaml_event_t *event, int first); + +static int +yaml_parser_parse_flow_mapping_value(yaml_parser_t *parser, + yaml_event_t *event, int empty); + +/* + * Utility functions. + */ + +static int +yaml_parser_process_empty_scalar(yaml_parser_t *parser, + yaml_event_t *event, yaml_mark_t mark); + +static int +yaml_parser_process_directives(yaml_parser_t *parser, + yaml_version_directive_t **version_directive_ref, + yaml_tag_directive_t **tag_directives_start_ref, + yaml_tag_directive_t **tag_directives_end_ref); + +static int +yaml_parser_append_tag_directive(yaml_parser_t *parser, + yaml_tag_directive_t value, int allow_duplicates, yaml_mark_t mark); + +/* + * Get the next event. + */ + +YAML_DECLARE(int) +yaml_parser_parse(yaml_parser_t *parser, yaml_event_t *event) +{ + assert(parser); /* Non-NULL parser object is expected. */ + assert(event); /* Non-NULL event object is expected. */ + + /* Erase the event object. */ + + memset(event, 0, sizeof(yaml_event_t)); + + /* No events after the end of the stream or error. */ + + if (parser->stream_end_produced || parser->error || + parser->state == YAML_PARSE_END_STATE) { + return 1; + } + + /* Generate the next event. */ + + return yaml_parser_state_machine(parser, event); +} + +/* + * Set parser error. + */ + +static int +yaml_parser_set_parser_error(yaml_parser_t *parser, + const char *problem, yaml_mark_t problem_mark) +{ + parser->error = YAML_PARSER_ERROR; + parser->problem = problem; + parser->problem_mark = problem_mark; + + return 0; +} + +static int +yaml_parser_set_parser_error_context(yaml_parser_t *parser, + const char *context, yaml_mark_t context_mark, + const char *problem, yaml_mark_t problem_mark) +{ + parser->error = YAML_PARSER_ERROR; + parser->context = context; + parser->context_mark = context_mark; + parser->problem = problem; + parser->problem_mark = problem_mark; + + return 0; +} + + +/* + * State dispatcher. + */ + +static int +yaml_parser_state_machine(yaml_parser_t *parser, yaml_event_t *event) +{ + switch (parser->state) + { + case YAML_PARSE_STREAM_START_STATE: + return yaml_parser_parse_stream_start(parser, event); + + case YAML_PARSE_IMPLICIT_DOCUMENT_START_STATE: + return yaml_parser_parse_document_start(parser, event, 1); + + case YAML_PARSE_DOCUMENT_START_STATE: + return yaml_parser_parse_document_start(parser, event, 0); + + case YAML_PARSE_DOCUMENT_CONTENT_STATE: + return yaml_parser_parse_document_content(parser, event); + + case YAML_PARSE_DOCUMENT_END_STATE: + return yaml_parser_parse_document_end(parser, event); + + case YAML_PARSE_BLOCK_NODE_STATE: + return yaml_parser_parse_node(parser, event, 1, 0); + + case YAML_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE: + return yaml_parser_parse_node(parser, event, 1, 1); + + case YAML_PARSE_FLOW_NODE_STATE: + return yaml_parser_parse_node(parser, event, 0, 0); + + case YAML_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE: + return yaml_parser_parse_block_sequence_entry(parser, event, 1); + + case YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE: + return yaml_parser_parse_block_sequence_entry(parser, event, 0); + + case YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE: + return yaml_parser_parse_indentless_sequence_entry(parser, event); + + case YAML_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE: + return yaml_parser_parse_block_mapping_key(parser, event, 1); + + case YAML_PARSE_BLOCK_MAPPING_KEY_STATE: + return yaml_parser_parse_block_mapping_key(parser, event, 0); + + case YAML_PARSE_BLOCK_MAPPING_VALUE_STATE: + return yaml_parser_parse_block_mapping_value(parser, event); + + case YAML_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE: + return yaml_parser_parse_flow_sequence_entry(parser, event, 1); + + case YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE: + return yaml_parser_parse_flow_sequence_entry(parser, event, 0); + + case YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE: + return yaml_parser_parse_flow_sequence_entry_mapping_key(parser, event); + + case YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE: + return yaml_parser_parse_flow_sequence_entry_mapping_value(parser, event); + + case YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE: + return yaml_parser_parse_flow_sequence_entry_mapping_end(parser, event); + + case YAML_PARSE_FLOW_MAPPING_FIRST_KEY_STATE: + return yaml_parser_parse_flow_mapping_key(parser, event, 1); + + case YAML_PARSE_FLOW_MAPPING_KEY_STATE: + return yaml_parser_parse_flow_mapping_key(parser, event, 0); + + case YAML_PARSE_FLOW_MAPPING_VALUE_STATE: + return yaml_parser_parse_flow_mapping_value(parser, event, 0); + + case YAML_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE: + return yaml_parser_parse_flow_mapping_value(parser, event, 1); + + default: + assert(1); /* Invalid state. */ + } + + return 0; +} + +/* + * Parse the production: + * stream ::= STREAM-START implicit_document? explicit_document* STREAM-END + * ************ + */ + +static int +yaml_parser_parse_stream_start(yaml_parser_t *parser, yaml_event_t *event) +{ + yaml_token_t *token; + + token = PEEK_TOKEN(parser); + if (!token) return 0; + + if (token->type != YAML_STREAM_START_TOKEN) { + return yaml_parser_set_parser_error(parser, + "did not find expected ", token->start_mark); + } + + parser->state = YAML_PARSE_IMPLICIT_DOCUMENT_START_STATE; + STREAM_START_EVENT_INIT(*event, token->data.stream_start.encoding, + token->start_mark, token->start_mark); + SKIP_TOKEN(parser); + + return 1; +} + +/* + * Parse the productions: + * implicit_document ::= block_node DOCUMENT-END* + * * + * explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* + * ************************* + */ + +static int +yaml_parser_parse_document_start(yaml_parser_t *parser, yaml_event_t *event, + int implicit) +{ + yaml_token_t *token; + yaml_version_directive_t *version_directive = NULL; + struct { + yaml_tag_directive_t *start; + yaml_tag_directive_t *end; + } tag_directives = { NULL, NULL }; + + token = PEEK_TOKEN(parser); + if (!token) return 0; + + /* Parse extra document end indicators. */ + + if (!implicit) + { + while (token->type == YAML_DOCUMENT_END_TOKEN) { + SKIP_TOKEN(parser); + token = PEEK_TOKEN(parser); + if (!token) return 0; + } + } + + /* Parse an implicit document. */ + + if (implicit && token->type != YAML_VERSION_DIRECTIVE_TOKEN && + token->type != YAML_TAG_DIRECTIVE_TOKEN && + token->type != YAML_DOCUMENT_START_TOKEN && + token->type != YAML_STREAM_END_TOKEN) + { + if (!yaml_parser_process_directives(parser, NULL, NULL, NULL)) + return 0; + if (!PUSH(parser, parser->states, YAML_PARSE_DOCUMENT_END_STATE)) + return 0; + parser->state = YAML_PARSE_BLOCK_NODE_STATE; + DOCUMENT_START_EVENT_INIT(*event, NULL, NULL, NULL, 1, + token->start_mark, token->start_mark); + return 1; + } + + /* Parse an explicit document. */ + + else if (token->type != YAML_STREAM_END_TOKEN) + { + yaml_mark_t start_mark, end_mark; + start_mark = token->start_mark; + if (!yaml_parser_process_directives(parser, &version_directive, + &tag_directives.start, &tag_directives.end)) + return 0; + token = PEEK_TOKEN(parser); + if (!token) goto error; + if (token->type != YAML_DOCUMENT_START_TOKEN) { + yaml_parser_set_parser_error(parser, + "did not find expected ", token->start_mark); + goto error; + } + if (!PUSH(parser, parser->states, YAML_PARSE_DOCUMENT_END_STATE)) + goto error; + parser->state = YAML_PARSE_DOCUMENT_CONTENT_STATE; + end_mark = token->end_mark; + DOCUMENT_START_EVENT_INIT(*event, version_directive, + tag_directives.start, tag_directives.end, 0, + start_mark, end_mark); + SKIP_TOKEN(parser); + version_directive = NULL; + tag_directives.start = tag_directives.end = NULL; + return 1; + } + + /* Parse the stream end. */ + + else + { + parser->state = YAML_PARSE_END_STATE; + STREAM_END_EVENT_INIT(*event, token->start_mark, token->end_mark); + SKIP_TOKEN(parser); + return 1; + } + +error: + yaml_free(version_directive); + while (tag_directives.start != tag_directives.end) { + yaml_free(tag_directives.end[-1].handle); + yaml_free(tag_directives.end[-1].prefix); + tag_directives.end --; + } + yaml_free(tag_directives.start); + return 0; +} + +/* + * Parse the productions: + * explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* + * *********** + */ + +static int +yaml_parser_parse_document_content(yaml_parser_t *parser, yaml_event_t *event) +{ + yaml_token_t *token; + + token = PEEK_TOKEN(parser); + if (!token) return 0; + + if (token->type == YAML_VERSION_DIRECTIVE_TOKEN || + token->type == YAML_TAG_DIRECTIVE_TOKEN || + token->type == YAML_DOCUMENT_START_TOKEN || + token->type == YAML_DOCUMENT_END_TOKEN || + token->type == YAML_STREAM_END_TOKEN) { + parser->state = POP(parser, parser->states); + return yaml_parser_process_empty_scalar(parser, event, + token->start_mark); + } + else { + return yaml_parser_parse_node(parser, event, 1, 0); + } +} + +/* + * Parse the productions: + * implicit_document ::= block_node DOCUMENT-END* + * ************* + * explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* + * ************* + */ + +static int +yaml_parser_parse_document_end(yaml_parser_t *parser, yaml_event_t *event) +{ + yaml_token_t *token; + yaml_mark_t start_mark, end_mark; + int implicit = 1; + + token = PEEK_TOKEN(parser); + if (!token) return 0; + + start_mark = end_mark = token->start_mark; + + if (token->type == YAML_DOCUMENT_END_TOKEN) { + end_mark = token->end_mark; + SKIP_TOKEN(parser); + implicit = 0; + } + + while (!STACK_EMPTY(parser, parser->tag_directives)) { + yaml_tag_directive_t tag_directive = POP(parser, parser->tag_directives); + yaml_free(tag_directive.handle); + yaml_free(tag_directive.prefix); + } + + parser->state = YAML_PARSE_DOCUMENT_START_STATE; + DOCUMENT_END_EVENT_INIT(*event, implicit, start_mark, end_mark); + + return 1; +} + +/* + * Parse the productions: + * block_node_or_indentless_sequence ::= + * ALIAS + * ***** + * | properties (block_content | indentless_block_sequence)? + * ********** * + * | block_content | indentless_block_sequence + * * + * block_node ::= ALIAS + * ***** + * | properties block_content? + * ********** * + * | block_content + * * + * flow_node ::= ALIAS + * ***** + * | properties flow_content? + * ********** * + * | flow_content + * * + * properties ::= TAG ANCHOR? | ANCHOR TAG? + * ************************* + * block_content ::= block_collection | flow_collection | SCALAR + * ****** + * flow_content ::= flow_collection | SCALAR + * ****** + */ + +static int +yaml_parser_parse_node(yaml_parser_t *parser, yaml_event_t *event, + int block, int indentless_sequence) +{ + yaml_token_t *token; + yaml_char_t *anchor = NULL; + yaml_char_t *tag_handle = NULL; + yaml_char_t *tag_suffix = NULL; + yaml_char_t *tag = NULL; + yaml_mark_t start_mark, end_mark, tag_mark; + int implicit; + + token = PEEK_TOKEN(parser); + if (!token) return 0; + + if (token->type == YAML_ALIAS_TOKEN) + { + parser->state = POP(parser, parser->states); + ALIAS_EVENT_INIT(*event, token->data.alias.value, + token->start_mark, token->end_mark); + SKIP_TOKEN(parser); + return 1; + } + + else + { + start_mark = end_mark = token->start_mark; + + if (token->type == YAML_ANCHOR_TOKEN) + { + anchor = token->data.anchor.value; + start_mark = token->start_mark; + end_mark = token->end_mark; + SKIP_TOKEN(parser); + token = PEEK_TOKEN(parser); + if (!token) goto error; + if (token->type == YAML_TAG_TOKEN) + { + tag_handle = token->data.tag.handle; + tag_suffix = token->data.tag.suffix; + tag_mark = token->start_mark; + end_mark = token->end_mark; + SKIP_TOKEN(parser); + token = PEEK_TOKEN(parser); + if (!token) goto error; + } + } + else if (token->type == YAML_TAG_TOKEN) + { + tag_handle = token->data.tag.handle; + tag_suffix = token->data.tag.suffix; + start_mark = tag_mark = token->start_mark; + end_mark = token->end_mark; + SKIP_TOKEN(parser); + token = PEEK_TOKEN(parser); + if (!token) goto error; + if (token->type == YAML_ANCHOR_TOKEN) + { + anchor = token->data.anchor.value; + end_mark = token->end_mark; + SKIP_TOKEN(parser); + token = PEEK_TOKEN(parser); + if (!token) goto error; + } + } + + if (tag_handle) { + if (!*tag_handle) { + tag = tag_suffix; + yaml_free(tag_handle); + tag_handle = tag_suffix = NULL; + } + else { + yaml_tag_directive_t *tag_directive; + for (tag_directive = parser->tag_directives.start; + tag_directive != parser->tag_directives.top; + tag_directive ++) { + if (strcmp((char *)tag_directive->handle, (char *)tag_handle) == 0) { + size_t prefix_len = strlen((char *)tag_directive->prefix); + size_t suffix_len = strlen((char *)tag_suffix); + tag = yaml_malloc(prefix_len+suffix_len+1); + if (!tag) { + parser->error = YAML_MEMORY_ERROR; + goto error; + } + memcpy(tag, tag_directive->prefix, prefix_len); + memcpy(tag+prefix_len, tag_suffix, suffix_len); + tag[prefix_len+suffix_len] = '\0'; + yaml_free(tag_handle); + yaml_free(tag_suffix); + tag_handle = tag_suffix = NULL; + break; + } + } + if (!tag) { + yaml_parser_set_parser_error_context(parser, + "while parsing a node", start_mark, + "found undefined tag handle", tag_mark); + goto error; + } + } + } + + implicit = (!tag || !*tag); + if (indentless_sequence && token->type == YAML_BLOCK_ENTRY_TOKEN) { + end_mark = token->end_mark; + parser->state = YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE; + SEQUENCE_START_EVENT_INIT(*event, anchor, tag, implicit, + YAML_BLOCK_SEQUENCE_STYLE, start_mark, end_mark); + return 1; + } + else { + if (token->type == YAML_SCALAR_TOKEN) { + int plain_implicit = 0; + int quoted_implicit = 0; + end_mark = token->end_mark; + if ((token->data.scalar.style == YAML_PLAIN_SCALAR_STYLE && !tag) + || (tag && strcmp((char *)tag, "!") == 0)) { + plain_implicit = 1; + } + else if (!tag) { + quoted_implicit = 1; + } + parser->state = POP(parser, parser->states); + SCALAR_EVENT_INIT(*event, anchor, tag, + token->data.scalar.value, token->data.scalar.length, + plain_implicit, quoted_implicit, + token->data.scalar.style, start_mark, end_mark); + SKIP_TOKEN(parser); + return 1; + } + else if (token->type == YAML_FLOW_SEQUENCE_START_TOKEN) { + end_mark = token->end_mark; + parser->state = YAML_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE; + SEQUENCE_START_EVENT_INIT(*event, anchor, tag, implicit, + YAML_FLOW_SEQUENCE_STYLE, start_mark, end_mark); + return 1; + } + else if (token->type == YAML_FLOW_MAPPING_START_TOKEN) { + end_mark = token->end_mark; + parser->state = YAML_PARSE_FLOW_MAPPING_FIRST_KEY_STATE; + MAPPING_START_EVENT_INIT(*event, anchor, tag, implicit, + YAML_FLOW_MAPPING_STYLE, start_mark, end_mark); + return 1; + } + else if (block && token->type == YAML_BLOCK_SEQUENCE_START_TOKEN) { + end_mark = token->end_mark; + parser->state = YAML_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE; + SEQUENCE_START_EVENT_INIT(*event, anchor, tag, implicit, + YAML_BLOCK_SEQUENCE_STYLE, start_mark, end_mark); + return 1; + } + else if (block && token->type == YAML_BLOCK_MAPPING_START_TOKEN) { + end_mark = token->end_mark; + parser->state = YAML_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE; + MAPPING_START_EVENT_INIT(*event, anchor, tag, implicit, + YAML_BLOCK_MAPPING_STYLE, start_mark, end_mark); + return 1; + } + else if (anchor || tag) { + yaml_char_t *value = yaml_malloc(1); + if (!value) { + parser->error = YAML_MEMORY_ERROR; + goto error; + } + value[0] = '\0'; + parser->state = POP(parser, parser->states); + SCALAR_EVENT_INIT(*event, anchor, tag, value, 0, + implicit, 0, YAML_PLAIN_SCALAR_STYLE, + start_mark, end_mark); + return 1; + } + else { + yaml_parser_set_parser_error_context(parser, + (block ? "while parsing a block node" + : "while parsing a flow node"), start_mark, + "did not find expected node content", token->start_mark); + goto error; + } + } + } + +error: + yaml_free(anchor); + yaml_free(tag_handle); + yaml_free(tag_suffix); + yaml_free(tag); + + return 0; +} + +/* + * Parse the productions: + * block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END + * ******************** *********** * ********* + */ + +static int +yaml_parser_parse_block_sequence_entry(yaml_parser_t *parser, + yaml_event_t *event, int first) +{ + yaml_token_t *token; + + if (first) { + token = PEEK_TOKEN(parser); + if (!PUSH(parser, parser->marks, token->start_mark)) + return 0; + SKIP_TOKEN(parser); + } + + token = PEEK_TOKEN(parser); + if (!token) return 0; + + if (token->type == YAML_BLOCK_ENTRY_TOKEN) + { + yaml_mark_t mark = token->end_mark; + SKIP_TOKEN(parser); + token = PEEK_TOKEN(parser); + if (!token) return 0; + if (token->type != YAML_BLOCK_ENTRY_TOKEN && + token->type != YAML_BLOCK_END_TOKEN) { + if (!PUSH(parser, parser->states, + YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE)) + return 0; + return yaml_parser_parse_node(parser, event, 1, 0); + } + else { + parser->state = YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE; + return yaml_parser_process_empty_scalar(parser, event, mark); + } + } + + else if (token->type == YAML_BLOCK_END_TOKEN) + { + yaml_mark_t dummy_mark; /* Used to eliminate a compiler warning. */ + parser->state = POP(parser, parser->states); + dummy_mark = POP(parser, parser->marks); + SEQUENCE_END_EVENT_INIT(*event, token->start_mark, token->end_mark); + SKIP_TOKEN(parser); + return 1; + } + + else + { + return yaml_parser_set_parser_error_context(parser, + "while parsing a block collection", POP(parser, parser->marks), + "did not find expected '-' indicator", token->start_mark); + } +} + +/* + * Parse the productions: + * indentless_sequence ::= (BLOCK-ENTRY block_node?)+ + * *********** * + */ + +static int +yaml_parser_parse_indentless_sequence_entry(yaml_parser_t *parser, + yaml_event_t *event) +{ + yaml_token_t *token; + + token = PEEK_TOKEN(parser); + if (!token) return 0; + + if (token->type == YAML_BLOCK_ENTRY_TOKEN) + { + yaml_mark_t mark = token->end_mark; + SKIP_TOKEN(parser); + token = PEEK_TOKEN(parser); + if (!token) return 0; + if (token->type != YAML_BLOCK_ENTRY_TOKEN && + token->type != YAML_KEY_TOKEN && + token->type != YAML_VALUE_TOKEN && + token->type != YAML_BLOCK_END_TOKEN) { + if (!PUSH(parser, parser->states, + YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE)) + return 0; + return yaml_parser_parse_node(parser, event, 1, 0); + } + else { + parser->state = YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE; + return yaml_parser_process_empty_scalar(parser, event, mark); + } + } + + else + { + parser->state = POP(parser, parser->states); + SEQUENCE_END_EVENT_INIT(*event, token->start_mark, token->start_mark); + return 1; + } +} + +/* + * Parse the productions: + * block_mapping ::= BLOCK-MAPPING_START + * ******************* + * ((KEY block_node_or_indentless_sequence?)? + * *** * + * (VALUE block_node_or_indentless_sequence?)?)* + * + * BLOCK-END + * ********* + */ + +static int +yaml_parser_parse_block_mapping_key(yaml_parser_t *parser, + yaml_event_t *event, int first) +{ + yaml_token_t *token; + + if (first) { + token = PEEK_TOKEN(parser); + if (!PUSH(parser, parser->marks, token->start_mark)) + return 0; + SKIP_TOKEN(parser); + } + + token = PEEK_TOKEN(parser); + if (!token) return 0; + + if (token->type == YAML_KEY_TOKEN) + { + yaml_mark_t mark = token->end_mark; + SKIP_TOKEN(parser); + token = PEEK_TOKEN(parser); + if (!token) return 0; + if (token->type != YAML_KEY_TOKEN && + token->type != YAML_VALUE_TOKEN && + token->type != YAML_BLOCK_END_TOKEN) { + if (!PUSH(parser, parser->states, + YAML_PARSE_BLOCK_MAPPING_VALUE_STATE)) + return 0; + return yaml_parser_parse_node(parser, event, 1, 1); + } + else { + parser->state = YAML_PARSE_BLOCK_MAPPING_VALUE_STATE; + return yaml_parser_process_empty_scalar(parser, event, mark); + } + } + + else if (token->type == YAML_BLOCK_END_TOKEN) + { + yaml_mark_t dummy_mark; /* Used to eliminate a compiler warning. */ + parser->state = POP(parser, parser->states); + dummy_mark = POP(parser, parser->marks); + MAPPING_END_EVENT_INIT(*event, token->start_mark, token->end_mark); + SKIP_TOKEN(parser); + return 1; + } + + else + { + return yaml_parser_set_parser_error_context(parser, + "while parsing a block mapping", POP(parser, parser->marks), + "did not find expected key", token->start_mark); + } +} + +/* + * Parse the productions: + * block_mapping ::= BLOCK-MAPPING_START + * + * ((KEY block_node_or_indentless_sequence?)? + * + * (VALUE block_node_or_indentless_sequence?)?)* + * ***** * + * BLOCK-END + * + */ + +static int +yaml_parser_parse_block_mapping_value(yaml_parser_t *parser, + yaml_event_t *event) +{ + yaml_token_t *token; + + token = PEEK_TOKEN(parser); + if (!token) return 0; + + if (token->type == YAML_VALUE_TOKEN) + { + yaml_mark_t mark = token->end_mark; + SKIP_TOKEN(parser); + token = PEEK_TOKEN(parser); + if (!token) return 0; + if (token->type != YAML_KEY_TOKEN && + token->type != YAML_VALUE_TOKEN && + token->type != YAML_BLOCK_END_TOKEN) { + if (!PUSH(parser, parser->states, + YAML_PARSE_BLOCK_MAPPING_KEY_STATE)) + return 0; + return yaml_parser_parse_node(parser, event, 1, 1); + } + else { + parser->state = YAML_PARSE_BLOCK_MAPPING_KEY_STATE; + return yaml_parser_process_empty_scalar(parser, event, mark); + } + } + + else + { + parser->state = YAML_PARSE_BLOCK_MAPPING_KEY_STATE; + return yaml_parser_process_empty_scalar(parser, event, token->start_mark); + } +} + +/* + * Parse the productions: + * flow_sequence ::= FLOW-SEQUENCE-START + * ******************* + * (flow_sequence_entry FLOW-ENTRY)* + * * ********** + * flow_sequence_entry? + * * + * FLOW-SEQUENCE-END + * ***************** + * flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? + * * + */ + +static int +yaml_parser_parse_flow_sequence_entry(yaml_parser_t *parser, + yaml_event_t *event, int first) +{ + yaml_token_t *token; + yaml_mark_t dummy_mark; /* Used to eliminate a compiler warning. */ + + if (first) { + token = PEEK_TOKEN(parser); + if (!PUSH(parser, parser->marks, token->start_mark)) + return 0; + SKIP_TOKEN(parser); + } + + token = PEEK_TOKEN(parser); + if (!token) return 0; + + if (token->type != YAML_FLOW_SEQUENCE_END_TOKEN) + { + if (!first) { + if (token->type == YAML_FLOW_ENTRY_TOKEN) { + SKIP_TOKEN(parser); + token = PEEK_TOKEN(parser); + if (!token) return 0; + } + else { + return yaml_parser_set_parser_error_context(parser, + "while parsing a flow sequence", POP(parser, parser->marks), + "did not find expected ',' or ']'", token->start_mark); + } + } + + if (token->type == YAML_KEY_TOKEN) { + parser->state = YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE; + MAPPING_START_EVENT_INIT(*event, NULL, NULL, + 1, YAML_FLOW_MAPPING_STYLE, + token->start_mark, token->end_mark); + SKIP_TOKEN(parser); + return 1; + } + + else if (token->type != YAML_FLOW_SEQUENCE_END_TOKEN) { + if (!PUSH(parser, parser->states, + YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE)) + return 0; + return yaml_parser_parse_node(parser, event, 0, 0); + } + } + + parser->state = POP(parser, parser->states); + dummy_mark = POP(parser, parser->marks); + SEQUENCE_END_EVENT_INIT(*event, token->start_mark, token->end_mark); + SKIP_TOKEN(parser); + return 1; +} + +/* + * Parse the productions: + * flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? + * *** * + */ + +static int +yaml_parser_parse_flow_sequence_entry_mapping_key(yaml_parser_t *parser, + yaml_event_t *event) +{ + yaml_token_t *token; + + token = PEEK_TOKEN(parser); + if (!token) return 0; + + if (token->type != YAML_VALUE_TOKEN && token->type != YAML_FLOW_ENTRY_TOKEN + && token->type != YAML_FLOW_SEQUENCE_END_TOKEN) { + if (!PUSH(parser, parser->states, + YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE)) + return 0; + return yaml_parser_parse_node(parser, event, 0, 0); + } + else { + yaml_mark_t mark = token->end_mark; + SKIP_TOKEN(parser); + parser->state = YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE; + return yaml_parser_process_empty_scalar(parser, event, mark); + } +} + +/* + * Parse the productions: + * flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? + * ***** * + */ + +static int +yaml_parser_parse_flow_sequence_entry_mapping_value(yaml_parser_t *parser, + yaml_event_t *event) +{ + yaml_token_t *token; + + token = PEEK_TOKEN(parser); + if (!token) return 0; + + if (token->type == YAML_VALUE_TOKEN) { + SKIP_TOKEN(parser); + token = PEEK_TOKEN(parser); + if (!token) return 0; + if (token->type != YAML_FLOW_ENTRY_TOKEN + && token->type != YAML_FLOW_SEQUENCE_END_TOKEN) { + if (!PUSH(parser, parser->states, + YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE)) + return 0; + return yaml_parser_parse_node(parser, event, 0, 0); + } + } + parser->state = YAML_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE; + return yaml_parser_process_empty_scalar(parser, event, token->start_mark); +} + +/* + * Parse the productions: + * flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? + * * + */ + +static int +yaml_parser_parse_flow_sequence_entry_mapping_end(yaml_parser_t *parser, + yaml_event_t *event) +{ + yaml_token_t *token; + + token = PEEK_TOKEN(parser); + if (!token) return 0; + + parser->state = YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE; + + MAPPING_END_EVENT_INIT(*event, token->start_mark, token->start_mark); + return 1; +} + +/* + * Parse the productions: + * flow_mapping ::= FLOW-MAPPING-START + * ****************** + * (flow_mapping_entry FLOW-ENTRY)* + * * ********** + * flow_mapping_entry? + * ****************** + * FLOW-MAPPING-END + * **************** + * flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? + * * *** * + */ + +static int +yaml_parser_parse_flow_mapping_key(yaml_parser_t *parser, + yaml_event_t *event, int first) +{ + yaml_token_t *token; + yaml_mark_t dummy_mark; /* Used to eliminate a compiler warning. */ + + if (first) { + token = PEEK_TOKEN(parser); + if (!PUSH(parser, parser->marks, token->start_mark)) + return 0; + SKIP_TOKEN(parser); + } + + token = PEEK_TOKEN(parser); + if (!token) return 0; + + if (token->type != YAML_FLOW_MAPPING_END_TOKEN) + { + if (!first) { + if (token->type == YAML_FLOW_ENTRY_TOKEN) { + SKIP_TOKEN(parser); + token = PEEK_TOKEN(parser); + if (!token) return 0; + } + else { + return yaml_parser_set_parser_error_context(parser, + "while parsing a flow mapping", POP(parser, parser->marks), + "did not find expected ',' or '}'", token->start_mark); + } + } + + if (token->type == YAML_KEY_TOKEN) { + SKIP_TOKEN(parser); + token = PEEK_TOKEN(parser); + if (!token) return 0; + if (token->type != YAML_VALUE_TOKEN + && token->type != YAML_FLOW_ENTRY_TOKEN + && token->type != YAML_FLOW_MAPPING_END_TOKEN) { + if (!PUSH(parser, parser->states, + YAML_PARSE_FLOW_MAPPING_VALUE_STATE)) + return 0; + return yaml_parser_parse_node(parser, event, 0, 0); + } + else { + parser->state = YAML_PARSE_FLOW_MAPPING_VALUE_STATE; + return yaml_parser_process_empty_scalar(parser, event, + token->start_mark); + } + } + else if (token->type != YAML_FLOW_MAPPING_END_TOKEN) { + if (!PUSH(parser, parser->states, + YAML_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE)) + return 0; + return yaml_parser_parse_node(parser, event, 0, 0); + } + } + + parser->state = POP(parser, parser->states); + dummy_mark = POP(parser, parser->marks); + MAPPING_END_EVENT_INIT(*event, token->start_mark, token->end_mark); + SKIP_TOKEN(parser); + return 1; +} + +/* + * Parse the productions: + * flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? + * * ***** * + */ + +static int +yaml_parser_parse_flow_mapping_value(yaml_parser_t *parser, + yaml_event_t *event, int empty) +{ + yaml_token_t *token; + + token = PEEK_TOKEN(parser); + if (!token) return 0; + + if (empty) { + parser->state = YAML_PARSE_FLOW_MAPPING_KEY_STATE; + return yaml_parser_process_empty_scalar(parser, event, + token->start_mark); + } + + if (token->type == YAML_VALUE_TOKEN) { + SKIP_TOKEN(parser); + token = PEEK_TOKEN(parser); + if (!token) return 0; + if (token->type != YAML_FLOW_ENTRY_TOKEN + && token->type != YAML_FLOW_MAPPING_END_TOKEN) { + if (!PUSH(parser, parser->states, + YAML_PARSE_FLOW_MAPPING_KEY_STATE)) + return 0; + return yaml_parser_parse_node(parser, event, 0, 0); + } + } + + parser->state = YAML_PARSE_FLOW_MAPPING_KEY_STATE; + return yaml_parser_process_empty_scalar(parser, event, token->start_mark); +} + +/* + * Generate an empty scalar event. + */ + +static int +yaml_parser_process_empty_scalar(yaml_parser_t *parser, yaml_event_t *event, + yaml_mark_t mark) +{ + yaml_char_t *value; + + value = yaml_malloc(1); + if (!value) { + parser->error = YAML_MEMORY_ERROR; + return 0; + } + value[0] = '\0'; + + SCALAR_EVENT_INIT(*event, NULL, NULL, value, 0, + 1, 0, YAML_PLAIN_SCALAR_STYLE, mark, mark); + + return 1; +} + +/* + * Parse directives. + */ + +static int +yaml_parser_process_directives(yaml_parser_t *parser, + yaml_version_directive_t **version_directive_ref, + yaml_tag_directive_t **tag_directives_start_ref, + yaml_tag_directive_t **tag_directives_end_ref) +{ + yaml_tag_directive_t default_tag_directives[] = { + {(yaml_char_t *)"!", (yaml_char_t *)"!"}, + {(yaml_char_t *)"!!", (yaml_char_t *)"tag:yaml.org,2002:"}, + {NULL, NULL} + }; + yaml_tag_directive_t *default_tag_directive; + yaml_version_directive_t *version_directive = NULL; + struct { + yaml_tag_directive_t *start; + yaml_tag_directive_t *end; + yaml_tag_directive_t *top; + } tag_directives = { NULL, NULL, NULL }; + yaml_token_t *token; + + if (!STACK_INIT(parser, tag_directives, INITIAL_STACK_SIZE)) + goto error; + + token = PEEK_TOKEN(parser); + if (!token) goto error; + + while (token->type == YAML_VERSION_DIRECTIVE_TOKEN || + token->type == YAML_TAG_DIRECTIVE_TOKEN) + { + if (token->type == YAML_VERSION_DIRECTIVE_TOKEN) { + if (version_directive) { + yaml_parser_set_parser_error(parser, + "found duplicate %YAML directive", token->start_mark); + goto error; + } + if (token->data.version_directive.major != 1 + || token->data.version_directive.minor != 1) { + yaml_parser_set_parser_error(parser, + "found incompatible YAML document", token->start_mark); + goto error; + } + version_directive = yaml_malloc(sizeof(yaml_version_directive_t)); + if (!version_directive) { + parser->error = YAML_MEMORY_ERROR; + goto error; + } + version_directive->major = token->data.version_directive.major; + version_directive->minor = token->data.version_directive.minor; + } + + else if (token->type == YAML_TAG_DIRECTIVE_TOKEN) { + yaml_tag_directive_t value; + value.handle = token->data.tag_directive.handle; + value.prefix = token->data.tag_directive.prefix; + + if (!yaml_parser_append_tag_directive(parser, value, 0, + token->start_mark)) + goto error; + if (!PUSH(parser, tag_directives, value)) + goto error; + } + + SKIP_TOKEN(parser); + token = PEEK_TOKEN(parser); + if (!token) goto error; + } + + for (default_tag_directive = default_tag_directives; + default_tag_directive->handle; default_tag_directive++) { + if (!yaml_parser_append_tag_directive(parser, *default_tag_directive, 1, + token->start_mark)) + goto error; + } + + if (version_directive_ref) { + *version_directive_ref = version_directive; + } + if (tag_directives_start_ref) { + if (STACK_EMPTY(parser, tag_directives)) { + *tag_directives_start_ref = *tag_directives_end_ref = NULL; + STACK_DEL(parser, tag_directives); + } + else { + *tag_directives_start_ref = tag_directives.start; + *tag_directives_end_ref = tag_directives.top; + } + } + else { + STACK_DEL(parser, tag_directives); + } + + return 1; + +error: + yaml_free(version_directive); + while (!STACK_EMPTY(parser, tag_directives)) { + yaml_tag_directive_t tag_directive = POP(parser, tag_directives); + yaml_free(tag_directive.handle); + yaml_free(tag_directive.prefix); + } + STACK_DEL(parser, tag_directives); + return 0; +} + +/* + * Append a tag directive to the directives stack. + */ + +static int +yaml_parser_append_tag_directive(yaml_parser_t *parser, + yaml_tag_directive_t value, int allow_duplicates, yaml_mark_t mark) +{ + yaml_tag_directive_t *tag_directive; + yaml_tag_directive_t copy = { NULL, NULL }; + + for (tag_directive = parser->tag_directives.start; + tag_directive != parser->tag_directives.top; tag_directive ++) { + if (strcmp((char *)value.handle, (char *)tag_directive->handle) == 0) { + if (allow_duplicates) + return 1; + return yaml_parser_set_parser_error(parser, + "found duplicate %TAG directive", mark); + } + } + + copy.handle = yaml_strdup(value.handle); + copy.prefix = yaml_strdup(value.prefix); + if (!copy.handle || !copy.prefix) { + parser->error = YAML_MEMORY_ERROR; + goto error; + } + + if (!PUSH(parser, parser->tag_directives, copy)) + goto error; + + return 1; + +error: + yaml_free(copy.handle); + yaml_free(copy.prefix); + return 0; +} + diff --git a/src/reader.c b/src/reader.c new file mode 100644 index 00000000000..829e32da55c --- /dev/null +++ b/src/reader.c @@ -0,0 +1,465 @@ + +#include "yaml_private.h" + +/* + * Declarations. + */ + +static int +yaml_parser_set_reader_error(yaml_parser_t *parser, const char *problem, + size_t offset, int value); + +static int +yaml_parser_update_raw_buffer(yaml_parser_t *parser); + +static int +yaml_parser_determine_encoding(yaml_parser_t *parser); + +YAML_DECLARE(int) +yaml_parser_update_buffer(yaml_parser_t *parser, size_t length); + +/* + * Set the reader error and return 0. + */ + +static int +yaml_parser_set_reader_error(yaml_parser_t *parser, const char *problem, + size_t offset, int value) +{ + parser->error = YAML_READER_ERROR; + parser->problem = problem; + parser->problem_offset = offset; + parser->problem_value = value; + + return 0; +} + +/* + * Byte order marks. + */ + +#define BOM_UTF8 "\xef\xbb\xbf" +#define BOM_UTF16LE "\xff\xfe" +#define BOM_UTF16BE "\xfe\xff" + +/* + * Determine the input stream encoding by checking the BOM symbol. If no BOM is + * found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure. + */ + +static int +yaml_parser_determine_encoding(yaml_parser_t *parser) +{ + /* Ensure that we had enough bytes in the raw buffer. */ + + while (!parser->eof + && parser->raw_buffer.last - parser->raw_buffer.pointer < 3) { + if (!yaml_parser_update_raw_buffer(parser)) { + return 0; + } + } + + /* Determine the encoding. */ + + if (parser->raw_buffer.last - parser->raw_buffer.pointer >= 2 + && !memcmp(parser->raw_buffer.pointer, BOM_UTF16LE, 2)) { + parser->encoding = YAML_UTF16LE_ENCODING; + parser->raw_buffer.pointer += 2; + parser->offset += 2; + } + else if (parser->raw_buffer.last - parser->raw_buffer.pointer >= 2 + && !memcmp(parser->raw_buffer.pointer, BOM_UTF16BE, 2)) { + parser->encoding = YAML_UTF16BE_ENCODING; + parser->raw_buffer.pointer += 2; + parser->offset += 2; + } + else if (parser->raw_buffer.last - parser->raw_buffer.pointer >= 3 + && !memcmp(parser->raw_buffer.pointer, BOM_UTF8, 3)) { + parser->encoding = YAML_UTF8_ENCODING; + parser->raw_buffer.pointer += 3; + parser->offset += 3; + } + else { + parser->encoding = YAML_UTF8_ENCODING; + } + + return 1; +} + +/* + * Update the raw buffer. + */ + +static int +yaml_parser_update_raw_buffer(yaml_parser_t *parser) +{ + size_t size_read = 0; + + /* Return if the raw buffer is full. */ + + if (parser->raw_buffer.start == parser->raw_buffer.pointer + && parser->raw_buffer.last == parser->raw_buffer.end) + return 1; + + /* Return on EOF. */ + + if (parser->eof) return 1; + + /* Move the remaining bytes in the raw buffer to the beginning. */ + + if (parser->raw_buffer.start < parser->raw_buffer.pointer + && parser->raw_buffer.pointer < parser->raw_buffer.last) { + memmove(parser->raw_buffer.start, parser->raw_buffer.pointer, + parser->raw_buffer.last - parser->raw_buffer.pointer); + } + parser->raw_buffer.last -= + parser->raw_buffer.pointer - parser->raw_buffer.start; + parser->raw_buffer.pointer = parser->raw_buffer.start; + + /* Call the read handler to fill the buffer. */ + + if (!parser->read_handler(parser->read_handler_data, parser->raw_buffer.last, + parser->raw_buffer.end - parser->raw_buffer.last, &size_read)) { + return yaml_parser_set_reader_error(parser, "input error", + parser->offset, -1); + } + parser->raw_buffer.last += size_read; + if (!size_read) { + parser->eof = 1; + } + + return 1; +} + +/* + * Ensure that the buffer contains at least `length` characters. + * Return 1 on success, 0 on failure. + * + * The length is supposed to be significantly less that the buffer size. + */ + +YAML_DECLARE(int) +yaml_parser_update_buffer(yaml_parser_t *parser, size_t length) +{ + int first = 1; + + assert(parser->read_handler); /* Read handler must be set. */ + + /* If the EOF flag is set and the raw buffer is empty, do nothing. */ + + if (parser->eof && parser->raw_buffer.pointer == parser->raw_buffer.last) + return 1; + + /* Return if the buffer contains enough characters. */ + + if (parser->unread >= length) + return 1; + + /* Determine the input encoding if it is not known yet. */ + + if (!parser->encoding) { + if (!yaml_parser_determine_encoding(parser)) + return 0; + } + + /* Move the unread characters to the beginning of the buffer. */ + + if (parser->buffer.start < parser->buffer.pointer + && parser->buffer.pointer < parser->buffer.last) { + size_t size = parser->buffer.last - parser->buffer.pointer; + memmove(parser->buffer.start, parser->buffer.pointer, size); + parser->buffer.pointer = parser->buffer.start; + parser->buffer.last = parser->buffer.start + size; + } + else if (parser->buffer.pointer == parser->buffer.last) { + parser->buffer.pointer = parser->buffer.start; + parser->buffer.last = parser->buffer.start; + } + + /* Fill the buffer until it has enough characters. */ + + while (parser->unread < length) + { + /* Fill the raw buffer if necessary. */ + + if (!first || parser->raw_buffer.pointer == parser->raw_buffer.last) { + if (!yaml_parser_update_raw_buffer(parser)) return 0; + } + first = 0; + + /* Decode the raw buffer. */ + + while (parser->raw_buffer.pointer != parser->raw_buffer.last) + { + unsigned int value = 0, value2 = 0; + int incomplete = 0; + unsigned char octet; + unsigned int width = 0; + int low, high; + size_t k; + size_t raw_unread = parser->raw_buffer.last - parser->raw_buffer.pointer; + + /* Decode the next character. */ + + switch (parser->encoding) + { + case YAML_UTF8_ENCODING: + + /* + * Decode a UTF-8 character. Check RFC 3629 + * (http://www.ietf.org/rfc/rfc3629.txt) for more details. + * + * The following table (taken from the RFC) is used for + * decoding. + * + * Char. number range | UTF-8 octet sequence + * (hexadecimal) | (binary) + * --------------------+------------------------------------ + * 0000 0000-0000 007F | 0xxxxxxx + * 0000 0080-0000 07FF | 110xxxxx 10xxxxxx + * 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx + * 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + * + * Additionally, the characters in the range 0xD800-0xDFFF + * are prohibited as they are reserved for use with UTF-16 + * surrogate pairs. + */ + + /* Determine the length of the UTF-8 sequence. */ + + octet = parser->raw_buffer.pointer[0]; + width = (octet & 0x80) == 0x00 ? 1 : + (octet & 0xE0) == 0xC0 ? 2 : + (octet & 0xF0) == 0xE0 ? 3 : + (octet & 0xF8) == 0xF0 ? 4 : 0; + + /* Check if the leading octet is valid. */ + + if (!width) + return yaml_parser_set_reader_error(parser, + "invalid leading UTF-8 octet", + parser->offset, octet); + + /* Check if the raw buffer contains an incomplete character. */ + + if (width > raw_unread) { + if (parser->eof) { + return yaml_parser_set_reader_error(parser, + "incomplete UTF-8 octet sequence", + parser->offset, -1); + } + incomplete = 1; + break; + } + + /* Decode the leading octet. */ + + value = (octet & 0x80) == 0x00 ? octet & 0x7F : + (octet & 0xE0) == 0xC0 ? octet & 0x1F : + (octet & 0xF0) == 0xE0 ? octet & 0x0F : + (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0; + + /* Check and decode the trailing octets. */ + + for (k = 1; k < width; k ++) + { + octet = parser->raw_buffer.pointer[k]; + + /* Check if the octet is valid. */ + + if ((octet & 0xC0) != 0x80) + return yaml_parser_set_reader_error(parser, + "invalid trailing UTF-8 octet", + parser->offset+k, octet); + + /* Decode the octet. */ + + value = (value << 6) + (octet & 0x3F); + } + + /* Check the length of the sequence against the value. */ + + if (!((width == 1) || + (width == 2 && value >= 0x80) || + (width == 3 && value >= 0x800) || + (width == 4 && value >= 0x10000))) + return yaml_parser_set_reader_error(parser, + "invalid length of a UTF-8 sequence", + parser->offset, -1); + + /* Check the range of the value. */ + + if ((value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF) + return yaml_parser_set_reader_error(parser, + "invalid Unicode character", + parser->offset, value); + + break; + + case YAML_UTF16LE_ENCODING: + case YAML_UTF16BE_ENCODING: + + low = (parser->encoding == YAML_UTF16LE_ENCODING ? 0 : 1); + high = (parser->encoding == YAML_UTF16LE_ENCODING ? 1 : 0); + + /* + * The UTF-16 encoding is not as simple as one might + * naively think. Check RFC 2781 + * (http://www.ietf.org/rfc/rfc2781.txt). + * + * Normally, two subsequent bytes describe a Unicode + * character. However a special technique (called a + * surrogate pair) is used for specifying character + * values larger than 0xFFFF. + * + * A surrogate pair consists of two pseudo-characters: + * high surrogate area (0xD800-0xDBFF) + * low surrogate area (0xDC00-0xDFFF) + * + * The following formulas are used for decoding + * and encoding characters using surrogate pairs: + * + * U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF) + * U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF) + * W1 = 110110yyyyyyyyyy + * W2 = 110111xxxxxxxxxx + * + * where U is the character value, W1 is the high surrogate + * area, W2 is the low surrogate area. + */ + + /* Check for incomplete UTF-16 character. */ + + if (raw_unread < 2) { + if (parser->eof) { + return yaml_parser_set_reader_error(parser, + "incomplete UTF-16 character", + parser->offset, -1); + } + incomplete = 1; + break; + } + + /* Get the character. */ + + value = parser->raw_buffer.pointer[low] + + (parser->raw_buffer.pointer[high] << 8); + + /* Check for unexpected low surrogate area. */ + + if ((value & 0xFC00) == 0xDC00) + return yaml_parser_set_reader_error(parser, + "unexpected low surrogate area", + parser->offset, value); + + /* Check for a high surrogate area. */ + + if ((value & 0xFC00) == 0xD800) { + + width = 4; + + /* Check for incomplete surrogate pair. */ + + if (raw_unread < 4) { + if (parser->eof) { + return yaml_parser_set_reader_error(parser, + "incomplete UTF-16 surrogate pair", + parser->offset, -1); + } + incomplete = 1; + break; + } + + /* Get the next character. */ + + value2 = parser->raw_buffer.pointer[low+2] + + (parser->raw_buffer.pointer[high+2] << 8); + + /* Check for a low surrogate area. */ + + if ((value2 & 0xFC00) != 0xDC00) + return yaml_parser_set_reader_error(parser, + "expected low surrogate area", + parser->offset+2, value2); + + /* Generate the value of the surrogate pair. */ + + value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF); + } + + else { + width = 2; + } + + break; + + default: + assert(1); /* Impossible. */ + } + + /* Check if the raw buffer contains enough bytes to form a character. */ + + if (incomplete) break; + + /* + * Check if the character is in the allowed range: + * #x9 | #xA | #xD | [#x20-#x7E] (8 bit) + * | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD] (16 bit) + * | [#x10000-#x10FFFF] (32 bit) + */ + + if (! (value == 0x09 || value == 0x0A || value == 0x0D + || (value >= 0x20 && value <= 0x7E) + || (value == 0x85) || (value >= 0xA0 && value <= 0xD7FF) + || (value >= 0xE000 && value <= 0xFFFD) + || (value >= 0x10000 && value <= 0x10FFFF))) + return yaml_parser_set_reader_error(parser, + "control characters are not allowed", + parser->offset, value); + + /* Move the raw pointers. */ + + parser->raw_buffer.pointer += width; + parser->offset += width; + + /* Finally put the character into the buffer. */ + + /* 0000 0000-0000 007F -> 0xxxxxxx */ + if (value <= 0x7F) { + *(parser->buffer.last++) = value; + } + /* 0000 0080-0000 07FF -> 110xxxxx 10xxxxxx */ + else if (value <= 0x7FF) { + *(parser->buffer.last++) = 0xC0 + (value >> 6); + *(parser->buffer.last++) = 0x80 + (value & 0x3F); + } + /* 0000 0800-0000 FFFF -> 1110xxxx 10xxxxxx 10xxxxxx */ + else if (value <= 0xFFFF) { + *(parser->buffer.last++) = 0xE0 + (value >> 12); + *(parser->buffer.last++) = 0x80 + ((value >> 6) & 0x3F); + *(parser->buffer.last++) = 0x80 + (value & 0x3F); + } + /* 0001 0000-0010 FFFF -> 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ + else { + *(parser->buffer.last++) = 0xF0 + (value >> 18); + *(parser->buffer.last++) = 0x80 + ((value >> 12) & 0x3F); + *(parser->buffer.last++) = 0x80 + ((value >> 6) & 0x3F); + *(parser->buffer.last++) = 0x80 + (value & 0x3F); + } + + parser->unread ++; + } + + /* On EOF, put NUL into the buffer and return. */ + + if (parser->eof) { + *(parser->buffer.last++) = '\0'; + parser->unread ++; + return 1; + } + + } + + return 1; +} + diff --git a/src/scanner.c b/src/scanner.c new file mode 100644 index 00000000000..a2e86192647 --- /dev/null +++ b/src/scanner.c @@ -0,0 +1,3570 @@ + +/* + * Introduction + * ************ + * + * The following notes assume that you are familiar with the YAML specification + * (http://yaml.org/spec/cvs/current.html). We mostly follow it, although in + * some cases we are less restrictive that it requires. + * + * The process of transforming a YAML stream into a sequence of events is + * divided on two steps: Scanning and Parsing. + * + * The Scanner transforms the input stream into a sequence of tokens, while the + * parser transform the sequence of tokens produced by the Scanner into a + * sequence of parsing events. + * + * The Scanner is rather clever and complicated. The Parser, on the contrary, + * is a straightforward implementation of a recursive-descendant parser (or, + * LL(1) parser, as it is usually called). + * + * Actually there are two issues of Scanning that might be called "clever", the + * rest is quite straightforward. The issues are "block collection start" and + * "simple keys". Both issues are explained below in details. + * + * Here the Scanning step is explained and implemented. We start with the list + * of all the tokens produced by the Scanner together with short descriptions. + * + * Now, tokens: + * + * STREAM-START(encoding) # The stream start. + * STREAM-END # The stream end. + * VERSION-DIRECTIVE(major,minor) # The '%YAML' directive. + * TAG-DIRECTIVE(handle,prefix) # The '%TAG' directive. + * DOCUMENT-START # '---' + * DOCUMENT-END # '...' + * BLOCK-SEQUENCE-START # Indentation increase denoting a block + * BLOCK-MAPPING-START # sequence or a block mapping. + * BLOCK-END # Indentation decrease. + * FLOW-SEQUENCE-START # '[' + * FLOW-SEQUENCE-END # ']' + * BLOCK-SEQUENCE-START # '{' + * BLOCK-SEQUENCE-END # '}' + * BLOCK-ENTRY # '-' + * FLOW-ENTRY # ',' + * KEY # '?' or nothing (simple keys). + * VALUE # ':' + * ALIAS(anchor) # '*anchor' + * ANCHOR(anchor) # '&anchor' + * TAG(handle,suffix) # '!handle!suffix' + * SCALAR(value,style) # A scalar. + * + * The following two tokens are "virtual" tokens denoting the beginning and the + * end of the stream: + * + * STREAM-START(encoding) + * STREAM-END + * + * We pass the information about the input stream encoding with the + * STREAM-START token. + * + * The next two tokens are responsible for tags: + * + * VERSION-DIRECTIVE(major,minor) + * TAG-DIRECTIVE(handle,prefix) + * + * Example: + * + * %YAML 1.1 + * %TAG ! !foo + * %TAG !yaml! tag:yaml.org,2002: + * --- + * + * The correspoding sequence of tokens: + * + * STREAM-START(utf-8) + * VERSION-DIRECTIVE(1,1) + * TAG-DIRECTIVE("!","!foo") + * TAG-DIRECTIVE("!yaml","tag:yaml.org,2002:") + * DOCUMENT-START + * STREAM-END + * + * Note that the VERSION-DIRECTIVE and TAG-DIRECTIVE tokens occupy a whole + * line. + * + * The document start and end indicators are represented by: + * + * DOCUMENT-START + * DOCUMENT-END + * + * Note that if a YAML stream contains an implicit document (without '---' + * and '...' indicators), no DOCUMENT-START and DOCUMENT-END tokens will be + * produced. + * + * In the following examples, we present whole documents together with the + * produced tokens. + * + * 1. An implicit document: + * + * 'a scalar' + * + * Tokens: + * + * STREAM-START(utf-8) + * SCALAR("a scalar",single-quoted) + * STREAM-END + * + * 2. An explicit document: + * + * --- + * 'a scalar' + * ... + * + * Tokens: + * + * STREAM-START(utf-8) + * DOCUMENT-START + * SCALAR("a scalar",single-quoted) + * DOCUMENT-END + * STREAM-END + * + * 3. Several documents in a stream: + * + * 'a scalar' + * --- + * 'another scalar' + * --- + * 'yet another scalar' + * + * Tokens: + * + * STREAM-START(utf-8) + * SCALAR("a scalar",single-quoted) + * DOCUMENT-START + * SCALAR("another scalar",single-quoted) + * DOCUMENT-START + * SCALAR("yet another scalar",single-quoted) + * STREAM-END + * + * We have already introduced the SCALAR token above. The following tokens are + * used to describe aliases, anchors, tag, and scalars: + * + * ALIAS(anchor) + * ANCHOR(anchor) + * TAG(handle,suffix) + * SCALAR(value,style) + * + * The following series of examples illustrate the usage of these tokens: + * + * 1. A recursive sequence: + * + * &A [ *A ] + * + * Tokens: + * + * STREAM-START(utf-8) + * ANCHOR("A") + * FLOW-SEQUENCE-START + * ALIAS("A") + * FLOW-SEQUENCE-END + * STREAM-END + * + * 2. A tagged scalar: + * + * !!float "3.14" # A good approximation. + * + * Tokens: + * + * STREAM-START(utf-8) + * TAG("!!","float") + * SCALAR("3.14",double-quoted) + * STREAM-END + * + * 3. Various scalar styles: + * + * --- # Implicit empty plain scalars do not produce tokens. + * --- a plain scalar + * --- 'a single-quoted scalar' + * --- "a double-quoted scalar" + * --- |- + * a literal scalar + * --- >- + * a folded + * scalar + * + * Tokens: + * + * STREAM-START(utf-8) + * DOCUMENT-START + * DOCUMENT-START + * SCALAR("a plain scalar",plain) + * DOCUMENT-START + * SCALAR("a single-quoted scalar",single-quoted) + * DOCUMENT-START + * SCALAR("a double-quoted scalar",double-quoted) + * DOCUMENT-START + * SCALAR("a literal scalar",literal) + * DOCUMENT-START + * SCALAR("a folded scalar",folded) + * STREAM-END + * + * Now it's time to review collection-related tokens. We will start with + * flow collections: + * + * FLOW-SEQUENCE-START + * FLOW-SEQUENCE-END + * FLOW-MAPPING-START + * FLOW-MAPPING-END + * FLOW-ENTRY + * KEY + * VALUE + * + * The tokens FLOW-SEQUENCE-START, FLOW-SEQUENCE-END, FLOW-MAPPING-START, and + * FLOW-MAPPING-END represent the indicators '[', ']', '{', and '}' + * correspondingly. FLOW-ENTRY represent the ',' indicator. Finally the + * indicators '?' and ':', which are used for denoting mapping keys and values, + * are represented by the KEY and VALUE tokens. + * + * The following examples show flow collections: + * + * 1. A flow sequence: + * + * [item 1, item 2, item 3] + * + * Tokens: + * + * STREAM-START(utf-8) + * FLOW-SEQUENCE-START + * SCALAR("item 1",plain) + * FLOW-ENTRY + * SCALAR("item 2",plain) + * FLOW-ENTRY + * SCALAR("item 3",plain) + * FLOW-SEQUENCE-END + * STREAM-END + * + * 2. A flow mapping: + * + * { + * a simple key: a value, # Note that the KEY token is produced. + * ? a complex key: another value, + * } + * + * Tokens: + * + * STREAM-START(utf-8) + * FLOW-MAPPING-START + * KEY + * SCALAR("a simple key",plain) + * VALUE + * SCALAR("a value",plain) + * FLOW-ENTRY + * KEY + * SCALAR("a complex key",plain) + * VALUE + * SCALAR("another value",plain) + * FLOW-ENTRY + * FLOW-MAPPING-END + * STREAM-END + * + * A simple key is a key which is not denoted by the '?' indicator. Note that + * the Scanner still produce the KEY token whenever it encounters a simple key. + * + * For scanning block collections, the following tokens are used (note that we + * repeat KEY and VALUE here): + * + * BLOCK-SEQUENCE-START + * BLOCK-MAPPING-START + * BLOCK-END + * BLOCK-ENTRY + * KEY + * VALUE + * + * The tokens BLOCK-SEQUENCE-START and BLOCK-MAPPING-START denote indentation + * increase that precedes a block collection (cf. the INDENT token in Python). + * The token BLOCK-END denote indentation decrease that ends a block collection + * (cf. the DEDENT token in Python). However YAML has some syntax pecularities + * that makes detections of these tokens more complex. + * + * The tokens BLOCK-ENTRY, KEY, and VALUE are used to represent the indicators + * '-', '?', and ':' correspondingly. + * + * The following examples show how the tokens BLOCK-SEQUENCE-START, + * BLOCK-MAPPING-START, and BLOCK-END are emitted by the Scanner: + * + * 1. Block sequences: + * + * - item 1 + * - item 2 + * - + * - item 3.1 + * - item 3.2 + * - + * key 1: value 1 + * key 2: value 2 + * + * Tokens: + * + * STREAM-START(utf-8) + * BLOCK-SEQUENCE-START + * BLOCK-ENTRY + * SCALAR("item 1",plain) + * BLOCK-ENTRY + * SCALAR("item 2",plain) + * BLOCK-ENTRY + * BLOCK-SEQUENCE-START + * BLOCK-ENTRY + * SCALAR("item 3.1",plain) + * BLOCK-ENTRY + * SCALAR("item 3.2",plain) + * BLOCK-END + * BLOCK-ENTRY + * BLOCK-MAPPING-START + * KEY + * SCALAR("key 1",plain) + * VALUE + * SCALAR("value 1",plain) + * KEY + * SCALAR("key 2",plain) + * VALUE + * SCALAR("value 2",plain) + * BLOCK-END + * BLOCK-END + * STREAM-END + * + * 2. Block mappings: + * + * a simple key: a value # The KEY token is produced here. + * ? a complex key + * : another value + * a mapping: + * key 1: value 1 + * key 2: value 2 + * a sequence: + * - item 1 + * - item 2 + * + * Tokens: + * + * STREAM-START(utf-8) + * BLOCK-MAPPING-START + * KEY + * SCALAR("a simple key",plain) + * VALUE + * SCALAR("a value",plain) + * KEY + * SCALAR("a complex key",plain) + * VALUE + * SCALAR("another value",plain) + * KEY + * SCALAR("a mapping",plain) + * BLOCK-MAPPING-START + * KEY + * SCALAR("key 1",plain) + * VALUE + * SCALAR("value 1",plain) + * KEY + * SCALAR("key 2",plain) + * VALUE + * SCALAR("value 2",plain) + * BLOCK-END + * KEY + * SCALAR("a sequence",plain) + * VALUE + * BLOCK-SEQUENCE-START + * BLOCK-ENTRY + * SCALAR("item 1",plain) + * BLOCK-ENTRY + * SCALAR("item 2",plain) + * BLOCK-END + * BLOCK-END + * STREAM-END + * + * YAML does not always require to start a new block collection from a new + * line. If the current line contains only '-', '?', and ':' indicators, a new + * block collection may start at the current line. The following examples + * illustrate this case: + * + * 1. Collections in a sequence: + * + * - - item 1 + * - item 2 + * - key 1: value 1 + * key 2: value 2 + * - ? complex key + * : complex value + * + * Tokens: + * + * STREAM-START(utf-8) + * BLOCK-SEQUENCE-START + * BLOCK-ENTRY + * BLOCK-SEQUENCE-START + * BLOCK-ENTRY + * SCALAR("item 1",plain) + * BLOCK-ENTRY + * SCALAR("item 2",plain) + * BLOCK-END + * BLOCK-ENTRY + * BLOCK-MAPPING-START + * KEY + * SCALAR("key 1",plain) + * VALUE + * SCALAR("value 1",plain) + * KEY + * SCALAR("key 2",plain) + * VALUE + * SCALAR("value 2",plain) + * BLOCK-END + * BLOCK-ENTRY + * BLOCK-MAPPING-START + * KEY + * SCALAR("complex key") + * VALUE + * SCALAR("complex value") + * BLOCK-END + * BLOCK-END + * STREAM-END + * + * 2. Collections in a mapping: + * + * ? a sequence + * : - item 1 + * - item 2 + * ? a mapping + * : key 1: value 1 + * key 2: value 2 + * + * Tokens: + * + * STREAM-START(utf-8) + * BLOCK-MAPPING-START + * KEY + * SCALAR("a sequence",plain) + * VALUE + * BLOCK-SEQUENCE-START + * BLOCK-ENTRY + * SCALAR("item 1",plain) + * BLOCK-ENTRY + * SCALAR("item 2",plain) + * BLOCK-END + * KEY + * SCALAR("a mapping",plain) + * VALUE + * BLOCK-MAPPING-START + * KEY + * SCALAR("key 1",plain) + * VALUE + * SCALAR("value 1",plain) + * KEY + * SCALAR("key 2",plain) + * VALUE + * SCALAR("value 2",plain) + * BLOCK-END + * BLOCK-END + * STREAM-END + * + * YAML also permits non-indented sequences if they are included into a block + * mapping. In this case, the token BLOCK-SEQUENCE-START is not produced: + * + * key: + * - item 1 # BLOCK-SEQUENCE-START is NOT produced here. + * - item 2 + * + * Tokens: + * + * STREAM-START(utf-8) + * BLOCK-MAPPING-START + * KEY + * SCALAR("key",plain) + * VALUE + * BLOCK-ENTRY + * SCALAR("item 1",plain) + * BLOCK-ENTRY + * SCALAR("item 2",plain) + * BLOCK-END + */ + +#include "yaml_private.h" + +/* + * Ensure that the buffer contains the required number of characters. + * Return 1 on success, 0 on failure (reader error or memory error). + */ + +#define CACHE(parser,length) \ + (parser->unread >= (length) \ + ? 1 \ + : yaml_parser_update_buffer(parser, (length))) + +/* + * Advance the buffer pointer. + */ + +#define SKIP(parser) \ + (parser->mark.index ++, \ + parser->mark.column ++, \ + parser->unread --, \ + parser->buffer.pointer += WIDTH(parser->buffer)) + +#define SKIP_LINE(parser) \ + (IS_CRLF(parser->buffer) ? \ + (parser->mark.index += 2, \ + parser->mark.column = 0, \ + parser->mark.line ++, \ + parser->unread -= 2, \ + parser->buffer.pointer += 2) : \ + IS_BREAK(parser->buffer) ? \ + (parser->mark.index ++, \ + parser->mark.column = 0, \ + parser->mark.line ++, \ + parser->unread --, \ + parser->buffer.pointer += WIDTH(parser->buffer)) : 0) + +/* + * Copy a character to a string buffer and advance pointers. + */ + +#define READ(parser,string) \ + (STRING_EXTEND(parser,string) ? \ + (COPY(string,parser->buffer), \ + parser->mark.index ++, \ + parser->mark.column ++, \ + parser->unread --, \ + 1) : 0) + +/* + * Copy a line break character to a string buffer and advance pointers. + */ + +#define READ_LINE(parser,string) \ + (STRING_EXTEND(parser,string) ? \ + (((CHECK_AT(parser->buffer,'\r',0) \ + && CHECK_AT(parser->buffer,'\n',1)) ? /* CR LF -> LF */ \ + (*((string).pointer++) = (yaml_char_t) '\n', \ + parser->buffer.pointer += 2, \ + parser->mark.index += 2, \ + parser->mark.column = 0, \ + parser->mark.line ++, \ + parser->unread -= 2) : \ + (CHECK_AT(parser->buffer,'\r',0) \ + || CHECK_AT(parser->buffer,'\n',0)) ? /* CR|LF -> LF */ \ + (*((string).pointer++) = (yaml_char_t) '\n', \ + parser->buffer.pointer ++, \ + parser->mark.index ++, \ + parser->mark.column = 0, \ + parser->mark.line ++, \ + parser->unread --) : \ + (CHECK_AT(parser->buffer,'\xC2',0) \ + && CHECK_AT(parser->buffer,'\x85',1)) ? /* NEL -> LF */ \ + (*((string).pointer++) = (yaml_char_t) '\n', \ + parser->buffer.pointer += 2, \ + parser->mark.index ++, \ + parser->mark.column = 0, \ + parser->mark.line ++, \ + parser->unread --) : \ + (CHECK_AT(parser->buffer,'\xE2',0) && \ + CHECK_AT(parser->buffer,'\x80',1) && \ + (CHECK_AT(parser->buffer,'\xA8',2) || \ + CHECK_AT(parser->buffer,'\xA9',2))) ? /* LS|PS -> LS|PS */ \ + (*((string).pointer++) = *(parser->buffer.pointer++), \ + *((string).pointer++) = *(parser->buffer.pointer++), \ + *((string).pointer++) = *(parser->buffer.pointer++), \ + parser->mark.index ++, \ + parser->mark.column = 0, \ + parser->mark.line ++, \ + parser->unread --) : 0), \ + 1) : 0) + +/* + * Public API declarations. + */ + +YAML_DECLARE(int) +yaml_parser_scan(yaml_parser_t *parser, yaml_token_t *token); + +/* + * Error handling. + */ + +static int +yaml_parser_set_scanner_error(yaml_parser_t *parser, const char *context, + yaml_mark_t context_mark, const char *problem); + +/* + * High-level token API. + */ + +YAML_DECLARE(int) +yaml_parser_fetch_more_tokens(yaml_parser_t *parser); + +static int +yaml_parser_fetch_next_token(yaml_parser_t *parser); + +/* + * Potential simple keys. + */ + +static int +yaml_parser_stale_simple_keys(yaml_parser_t *parser); + +static int +yaml_parser_save_simple_key(yaml_parser_t *parser); + +static int +yaml_parser_remove_simple_key(yaml_parser_t *parser); + +static int +yaml_parser_increase_flow_level(yaml_parser_t *parser); + +static int +yaml_parser_decrease_flow_level(yaml_parser_t *parser); + +/* + * Indentation treatment. + */ + +static int +yaml_parser_roll_indent(yaml_parser_t *parser, int column, + int number, yaml_token_type_t type, yaml_mark_t mark); + +static int +yaml_parser_unroll_indent(yaml_parser_t *parser, int column); + +/* + * Token fetchers. + */ + +static int +yaml_parser_fetch_stream_start(yaml_parser_t *parser); + +static int +yaml_parser_fetch_stream_end(yaml_parser_t *parser); + +static int +yaml_parser_fetch_directive(yaml_parser_t *parser); + +static int +yaml_parser_fetch_document_indicator(yaml_parser_t *parser, + yaml_token_type_t type); + +static int +yaml_parser_fetch_flow_collection_start(yaml_parser_t *parser, + yaml_token_type_t type); + +static int +yaml_parser_fetch_flow_collection_end(yaml_parser_t *parser, + yaml_token_type_t type); + +static int +yaml_parser_fetch_flow_entry(yaml_parser_t *parser); + +static int +yaml_parser_fetch_block_entry(yaml_parser_t *parser); + +static int +yaml_parser_fetch_key(yaml_parser_t *parser); + +static int +yaml_parser_fetch_value(yaml_parser_t *parser); + +static int +yaml_parser_fetch_anchor(yaml_parser_t *parser, yaml_token_type_t type); + +static int +yaml_parser_fetch_tag(yaml_parser_t *parser); + +static int +yaml_parser_fetch_block_scalar(yaml_parser_t *parser, int literal); + +static int +yaml_parser_fetch_flow_scalar(yaml_parser_t *parser, int single); + +static int +yaml_parser_fetch_plain_scalar(yaml_parser_t *parser); + +/* + * Token scanners. + */ + +static int +yaml_parser_scan_to_next_token(yaml_parser_t *parser); + +static int +yaml_parser_scan_directive(yaml_parser_t *parser, yaml_token_t *token); + +static int +yaml_parser_scan_directive_name(yaml_parser_t *parser, + yaml_mark_t start_mark, yaml_char_t **name); + +static int +yaml_parser_scan_version_directive_value(yaml_parser_t *parser, + yaml_mark_t start_mark, int *major, int *minor); + +static int +yaml_parser_scan_version_directive_number(yaml_parser_t *parser, + yaml_mark_t start_mark, int *number); + +static int +yaml_parser_scan_tag_directive_value(yaml_parser_t *parser, + yaml_mark_t mark, yaml_char_t **handle, yaml_char_t **prefix); + +static int +yaml_parser_scan_anchor(yaml_parser_t *parser, yaml_token_t *token, + yaml_token_type_t type); + +static int +yaml_parser_scan_tag(yaml_parser_t *parser, yaml_token_t *token); + +static int +yaml_parser_scan_tag_handle(yaml_parser_t *parser, int directive, + yaml_mark_t start_mark, yaml_char_t **handle); + +static int +yaml_parser_scan_tag_uri(yaml_parser_t *parser, int directive, + yaml_char_t *head, yaml_mark_t start_mark, yaml_char_t **uri); + +static int +yaml_parser_scan_uri_escapes(yaml_parser_t *parser, int directive, + yaml_mark_t start_mark, yaml_string_t *string); + +static int +yaml_parser_scan_block_scalar(yaml_parser_t *parser, yaml_token_t *token, + int literal); + +static int +yaml_parser_scan_block_scalar_breaks(yaml_parser_t *parser, + int *indent, yaml_string_t *breaks, + yaml_mark_t start_mark, yaml_mark_t *end_mark); + +static int +yaml_parser_scan_flow_scalar(yaml_parser_t *parser, yaml_token_t *token, + int single); + +static int +yaml_parser_scan_plain_scalar(yaml_parser_t *parser, yaml_token_t *token); + +/* + * Get the next token. + */ + +YAML_DECLARE(int) +yaml_parser_scan(yaml_parser_t *parser, yaml_token_t *token) +{ + assert(parser); /* Non-NULL parser object is expected. */ + assert(token); /* Non-NULL token object is expected. */ + + /* Erase the token object. */ + + memset(token, 0, sizeof(yaml_token_t)); + + /* No tokens after STREAM-END or error. */ + + if (parser->stream_end_produced || parser->error) { + return 1; + } + + /* Ensure that the tokens queue contains enough tokens. */ + + if (!parser->token_available) { + if (!yaml_parser_fetch_more_tokens(parser)) + return 0; + } + + /* Fetch the next token from the queue. */ + + *token = DEQUEUE(parser, parser->tokens); + parser->token_available = 0; + parser->tokens_parsed ++; + + if (token->type == YAML_STREAM_END_TOKEN) { + parser->stream_end_produced = 1; + } + + return 1; +} + +/* + * Set the scanner error and return 0. + */ + +static int +yaml_parser_set_scanner_error(yaml_parser_t *parser, const char *context, + yaml_mark_t context_mark, const char *problem) +{ + parser->error = YAML_SCANNER_ERROR; + parser->context = context; + parser->context_mark = context_mark; + parser->problem = problem; + parser->problem_mark = parser->mark; + + return 0; +} + +/* + * Ensure that the tokens queue contains at least one token which can be + * returned to the Parser. + */ + +YAML_DECLARE(int) +yaml_parser_fetch_more_tokens(yaml_parser_t *parser) +{ + int need_more_tokens; + + /* While we need more tokens to fetch, do it. */ + + while (1) + { + /* + * Check if we really need to fetch more tokens. + */ + + need_more_tokens = 0; + + if (parser->tokens.head == parser->tokens.tail) + { + /* Queue is empty. */ + + need_more_tokens = 1; + } + else + { + yaml_simple_key_t *simple_key; + + /* Check if any potential simple key may occupy the head position. */ + + if (!yaml_parser_stale_simple_keys(parser)) + return 0; + + for (simple_key = parser->simple_keys.start; + simple_key != parser->simple_keys.top; simple_key++) { + if (simple_key->possible + && simple_key->token_number == parser->tokens_parsed) { + need_more_tokens = 1; + break; + } + } + } + + /* We are finished. */ + + if (!need_more_tokens) + break; + + /* Fetch the next token. */ + + if (!yaml_parser_fetch_next_token(parser)) + return 0; + } + + parser->token_available = 1; + + return 1; +} + +/* + * The dispatcher for token fetchers. + */ + +static int +yaml_parser_fetch_next_token(yaml_parser_t *parser) +{ + /* Ensure that the buffer is initialized. */ + + if (!CACHE(parser, 1)) + return 0; + + /* Check if we just started scanning. Fetch STREAM-START then. */ + + if (!parser->stream_start_produced) + return yaml_parser_fetch_stream_start(parser); + + /* Eat whitespaces and comments until we reach the next token. */ + + if (!yaml_parser_scan_to_next_token(parser)) + return 0; + + /* Remove obsolete potential simple keys. */ + + if (!yaml_parser_stale_simple_keys(parser)) + return 0; + + /* Check the indentation level against the current column. */ + + if (!yaml_parser_unroll_indent(parser, parser->mark.column)) + return 0; + + /* + * Ensure that the buffer contains at least 4 characters. 4 is the length + * of the longest indicators ('--- ' and '... '). + */ + + if (!CACHE(parser, 4)) + return 0; + + /* Is it the end of the stream? */ + + if (IS_Z(parser->buffer)) + return yaml_parser_fetch_stream_end(parser); + + /* Is it a directive? */ + + if (parser->mark.column == 0 && CHECK(parser->buffer, '%')) + return yaml_parser_fetch_directive(parser); + + /* Is it the document start indicator? */ + + if (parser->mark.column == 0 + && CHECK_AT(parser->buffer, '-', 0) + && CHECK_AT(parser->buffer, '-', 1) + && CHECK_AT(parser->buffer, '-', 2) + && IS_BLANKZ_AT(parser->buffer, 3)) + return yaml_parser_fetch_document_indicator(parser, + YAML_DOCUMENT_START_TOKEN); + + /* Is it the document end indicator? */ + + if (parser->mark.column == 0 + && CHECK_AT(parser->buffer, '.', 0) + && CHECK_AT(parser->buffer, '.', 1) + && CHECK_AT(parser->buffer, '.', 2) + && IS_BLANKZ_AT(parser->buffer, 3)) + return yaml_parser_fetch_document_indicator(parser, + YAML_DOCUMENT_END_TOKEN); + + /* Is it the flow sequence start indicator? */ + + if (CHECK(parser->buffer, '[')) + return yaml_parser_fetch_flow_collection_start(parser, + YAML_FLOW_SEQUENCE_START_TOKEN); + + /* Is it the flow mapping start indicator? */ + + if (CHECK(parser->buffer, '{')) + return yaml_parser_fetch_flow_collection_start(parser, + YAML_FLOW_MAPPING_START_TOKEN); + + /* Is it the flow sequence end indicator? */ + + if (CHECK(parser->buffer, ']')) + return yaml_parser_fetch_flow_collection_end(parser, + YAML_FLOW_SEQUENCE_END_TOKEN); + + /* Is it the flow mapping end indicator? */ + + if (CHECK(parser->buffer, '}')) + return yaml_parser_fetch_flow_collection_end(parser, + YAML_FLOW_MAPPING_END_TOKEN); + + /* Is it the flow entry indicator? */ + + if (CHECK(parser->buffer, ',')) + return yaml_parser_fetch_flow_entry(parser); + + /* Is it the block entry indicator? */ + + if (CHECK(parser->buffer, '-') && IS_BLANKZ_AT(parser->buffer, 1)) + return yaml_parser_fetch_block_entry(parser); + + /* Is it the key indicator? */ + + if (CHECK(parser->buffer, '?') + && (parser->flow_level || IS_BLANKZ_AT(parser->buffer, 1))) + return yaml_parser_fetch_key(parser); + + /* Is it the value indicator? */ + + if (CHECK(parser->buffer, ':') + && (parser->flow_level || IS_BLANKZ_AT(parser->buffer, 1))) + return yaml_parser_fetch_value(parser); + + /* Is it an alias? */ + + if (CHECK(parser->buffer, '*')) + return yaml_parser_fetch_anchor(parser, YAML_ALIAS_TOKEN); + + /* Is it an anchor? */ + + if (CHECK(parser->buffer, '&')) + return yaml_parser_fetch_anchor(parser, YAML_ANCHOR_TOKEN); + + /* Is it a tag? */ + + if (CHECK(parser->buffer, '!')) + return yaml_parser_fetch_tag(parser); + + /* Is it a literal scalar? */ + + if (CHECK(parser->buffer, '|') && !parser->flow_level) + return yaml_parser_fetch_block_scalar(parser, 1); + + /* Is it a folded scalar? */ + + if (CHECK(parser->buffer, '>') && !parser->flow_level) + return yaml_parser_fetch_block_scalar(parser, 0); + + /* Is it a single-quoted scalar? */ + + if (CHECK(parser->buffer, '\'')) + return yaml_parser_fetch_flow_scalar(parser, 1); + + /* Is it a double-quoted scalar? */ + + if (CHECK(parser->buffer, '"')) + return yaml_parser_fetch_flow_scalar(parser, 0); + + /* + * Is it a plain scalar? + * + * A plain scalar may start with any non-blank characters except + * + * '-', '?', ':', ',', '[', ']', '{', '}', + * '#', '&', '*', '!', '|', '>', '\'', '\"', + * '%', '@', '`'. + * + * In the block context (and, for the '-' indicator, in the flow context + * too), it may also start with the characters + * + * '-', '?', ':' + * + * if it is followed by a non-space character. + * + * The last rule is more restrictive than the specification requires. + */ + + if (!(IS_BLANKZ(parser->buffer) || CHECK(parser->buffer, '-') + || CHECK(parser->buffer, '?') || CHECK(parser->buffer, ':') + || CHECK(parser->buffer, ',') || CHECK(parser->buffer, '[') + || CHECK(parser->buffer, ']') || CHECK(parser->buffer, '{') + || CHECK(parser->buffer, '}') || CHECK(parser->buffer, '#') + || CHECK(parser->buffer, '&') || CHECK(parser->buffer, '*') + || CHECK(parser->buffer, '!') || CHECK(parser->buffer, '|') + || CHECK(parser->buffer, '>') || CHECK(parser->buffer, '\'') + || CHECK(parser->buffer, '"') || CHECK(parser->buffer, '%') + || CHECK(parser->buffer, '@') || CHECK(parser->buffer, '`')) || + (CHECK(parser->buffer, '-') && !IS_BLANK_AT(parser->buffer, 1)) || + (!parser->flow_level && + (CHECK(parser->buffer, '?') || CHECK(parser->buffer, ':')) + && !IS_BLANKZ_AT(parser->buffer, 1))) + return yaml_parser_fetch_plain_scalar(parser); + + /* + * If we don't determine the token type so far, it is an error. + */ + + return yaml_parser_set_scanner_error(parser, + "while scanning for the next token", parser->mark, + "found character that cannot start any token"); +} + +/* + * Check the list of potential simple keys and remove the positions that + * cannot contain simple keys anymore. + */ + +static int +yaml_parser_stale_simple_keys(yaml_parser_t *parser) +{ + yaml_simple_key_t *simple_key; + + /* Check for a potential simple key for each flow level. */ + + for (simple_key = parser->simple_keys.start; + simple_key != parser->simple_keys.top; simple_key ++) + { + /* + * The specification requires that a simple key + * + * - is limited to a single line, + * - is shorter than 1024 characters. + */ + + if (simple_key->possible + && (simple_key->mark.line < parser->mark.line + || simple_key->mark.index+1024 < parser->mark.index)) { + + /* Check if the potential simple key to be removed is required. */ + + if (simple_key->required) { + return yaml_parser_set_scanner_error(parser, + "while scanning a simple key", simple_key->mark, + "could not find expected ':'"); + } + + simple_key->possible = 0; + } + } + + return 1; +} + +/* + * Check if a simple key may start at the current position and add it if + * needed. + */ + +static int +yaml_parser_save_simple_key(yaml_parser_t *parser) +{ + /* + * A simple key is required at the current position if the scanner is in + * the block context and the current column coincides with the indentation + * level. + */ + + int required = (!parser->flow_level + && parser->indent == (int)parser->mark.column); + + /* + * A simple key is required only when it is the first token in the current + * line. Therefore it is always allowed. But we add a check anyway. + */ + + assert(parser->simple_key_allowed || !required); /* Impossible. */ + + /* + * If the current position may start a simple key, save it. + */ + + if (parser->simple_key_allowed) + { + yaml_simple_key_t simple_key; + simple_key.possible = 1; + simple_key.required = required; + simple_key.token_number = + parser->tokens_parsed + (parser->tokens.tail - parser->tokens.head); + simple_key.mark = parser->mark; + + if (!yaml_parser_remove_simple_key(parser)) return 0; + + *(parser->simple_keys.top-1) = simple_key; + } + + return 1; +} + +/* + * Remove a potential simple key at the current flow level. + */ + +static int +yaml_parser_remove_simple_key(yaml_parser_t *parser) +{ + yaml_simple_key_t *simple_key = parser->simple_keys.top-1; + + if (simple_key->possible) + { + /* If the key is required, it is an error. */ + + if (simple_key->required) { + return yaml_parser_set_scanner_error(parser, + "while scanning a simple key", simple_key->mark, + "could not find expected ':'"); + } + } + + /* Remove the key from the stack. */ + + simple_key->possible = 0; + + return 1; +} + +/* + * Increase the flow level and resize the simple key list if needed. + */ + +static int +yaml_parser_increase_flow_level(yaml_parser_t *parser) +{ + yaml_simple_key_t empty_simple_key = { 0, 0, 0, { 0, 0, 0 } }; + + /* Reset the simple key on the next level. */ + + if (!PUSH(parser, parser->simple_keys, empty_simple_key)) + return 0; + + /* Increase the flow level. */ + + parser->flow_level++; + + return 1; +} + +/* + * Decrease the flow level. + */ + +static int +yaml_parser_decrease_flow_level(yaml_parser_t *parser) +{ + yaml_simple_key_t dummy_key; /* Used to eliminate a compiler warning. */ + + if (parser->flow_level) { + parser->flow_level --; + dummy_key = POP(parser, parser->simple_keys); + } + + return 1; +} + +/* + * Push the current indentation level to the stack and set the new level + * the current column is greater than the indentation level. In this case, + * append or insert the specified token into the token queue. + * + */ + +static int +yaml_parser_roll_indent(yaml_parser_t *parser, int column, + int number, yaml_token_type_t type, yaml_mark_t mark) +{ + yaml_token_t token; + + /* In the flow context, do nothing. */ + + if (parser->flow_level) + return 1; + + if (parser->indent < column) + { + /* + * Push the current indentation level to the stack and set the new + * indentation level. + */ + + if (!PUSH(parser, parser->indents, parser->indent)) + return 0; + + parser->indent = column; + + /* Create a token and insert it into the queue. */ + + TOKEN_INIT(token, type, mark, mark); + + if (number == -1) { + if (!ENQUEUE(parser, parser->tokens, token)) + return 0; + } + else { + if (!QUEUE_INSERT(parser, + parser->tokens, number - parser->tokens_parsed, token)) + return 0; + } + } + + return 1; +} + +/* + * Pop indentation levels from the indents stack until the current level + * becomes less or equal to the column. For each intendation level, append + * the BLOCK-END token. + */ + + +static int +yaml_parser_unroll_indent(yaml_parser_t *parser, int column) +{ + yaml_token_t token; + + /* In the flow context, do nothing. */ + + if (parser->flow_level) + return 1; + + /* Loop through the intendation levels in the stack. */ + + while (parser->indent > column) + { + /* Create a token and append it to the queue. */ + + TOKEN_INIT(token, YAML_BLOCK_END_TOKEN, parser->mark, parser->mark); + + if (!ENQUEUE(parser, parser->tokens, token)) + return 0; + + /* Pop the indentation level. */ + + parser->indent = POP(parser, parser->indents); + } + + return 1; +} + +/* + * Initialize the scanner and produce the STREAM-START token. + */ + +static int +yaml_parser_fetch_stream_start(yaml_parser_t *parser) +{ + yaml_simple_key_t simple_key = { 0, 0, 0, { 0, 0, 0 } }; + yaml_token_t token; + + /* Set the initial indentation. */ + + parser->indent = -1; + + /* Initialize the simple key stack. */ + + if (!PUSH(parser, parser->simple_keys, simple_key)) + return 0; + + /* A simple key is allowed at the beginning of the stream. */ + + parser->simple_key_allowed = 1; + + /* We have started. */ + + parser->stream_start_produced = 1; + + /* Create the STREAM-START token and append it to the queue. */ + + STREAM_START_TOKEN_INIT(token, parser->encoding, + parser->mark, parser->mark); + + if (!ENQUEUE(parser, parser->tokens, token)) + return 0; + + return 1; +} + +/* + * Produce the STREAM-END token and shut down the scanner. + */ + +static int +yaml_parser_fetch_stream_end(yaml_parser_t *parser) +{ + yaml_token_t token; + + /* Force new line. */ + + if (parser->mark.column != 0) { + parser->mark.column = 0; + parser->mark.line ++; + } + + /* Reset the indentation level. */ + + if (!yaml_parser_unroll_indent(parser, -1)) + return 0; + + /* Reset simple keys. */ + + if (!yaml_parser_remove_simple_key(parser)) + return 0; + + parser->simple_key_allowed = 0; + + /* Create the STREAM-END token and append it to the queue. */ + + STREAM_END_TOKEN_INIT(token, parser->mark, parser->mark); + + if (!ENQUEUE(parser, parser->tokens, token)) + return 0; + + return 1; +} + +/* + * Produce a VERSION-DIRECTIVE or TAG-DIRECTIVE token. + */ + +static int +yaml_parser_fetch_directive(yaml_parser_t *parser) +{ + yaml_token_t token; + + /* Reset the indentation level. */ + + if (!yaml_parser_unroll_indent(parser, -1)) + return 0; + + /* Reset simple keys. */ + + if (!yaml_parser_remove_simple_key(parser)) + return 0; + + parser->simple_key_allowed = 0; + + /* Create the YAML-DIRECTIVE or TAG-DIRECTIVE token. */ + + if (!yaml_parser_scan_directive(parser, &token)) + return 0; + + /* Append the token to the queue. */ + + if (!ENQUEUE(parser, parser->tokens, token)) { + yaml_token_delete(&token); + return 0; + } + + return 1; +} + +/* + * Produce the DOCUMENT-START or DOCUMENT-END token. + */ + +static int +yaml_parser_fetch_document_indicator(yaml_parser_t *parser, + yaml_token_type_t type) +{ + yaml_mark_t start_mark, end_mark; + yaml_token_t token; + + /* Reset the indentation level. */ + + if (!yaml_parser_unroll_indent(parser, -1)) + return 0; + + /* Reset simple keys. */ + + if (!yaml_parser_remove_simple_key(parser)) + return 0; + + parser->simple_key_allowed = 0; + + /* Consume the token. */ + + start_mark = parser->mark; + + SKIP(parser); + SKIP(parser); + SKIP(parser); + + end_mark = parser->mark; + + /* Create the DOCUMENT-START or DOCUMENT-END token. */ + + TOKEN_INIT(token, type, start_mark, end_mark); + + /* Append the token to the queue. */ + + if (!ENQUEUE(parser, parser->tokens, token)) + return 0; + + return 1; +} + +/* + * Produce the FLOW-SEQUENCE-START or FLOW-MAPPING-START token. + */ + +static int +yaml_parser_fetch_flow_collection_start(yaml_parser_t *parser, + yaml_token_type_t type) +{ + yaml_mark_t start_mark, end_mark; + yaml_token_t token; + + /* The indicators '[' and '{' may start a simple key. */ + + if (!yaml_parser_save_simple_key(parser)) + return 0; + + /* Increase the flow level. */ + + if (!yaml_parser_increase_flow_level(parser)) + return 0; + + /* A simple key may follow the indicators '[' and '{'. */ + + parser->simple_key_allowed = 1; + + /* Consume the token. */ + + start_mark = parser->mark; + SKIP(parser); + end_mark = parser->mark; + + /* Create the FLOW-SEQUENCE-START of FLOW-MAPPING-START token. */ + + TOKEN_INIT(token, type, start_mark, end_mark); + + /* Append the token to the queue. */ + + if (!ENQUEUE(parser, parser->tokens, token)) + return 0; + + return 1; +} + +/* + * Produce the FLOW-SEQUENCE-END or FLOW-MAPPING-END token. + */ + +static int +yaml_parser_fetch_flow_collection_end(yaml_parser_t *parser, + yaml_token_type_t type) +{ + yaml_mark_t start_mark, end_mark; + yaml_token_t token; + + /* Reset any potential simple key on the current flow level. */ + + if (!yaml_parser_remove_simple_key(parser)) + return 0; + + /* Decrease the flow level. */ + + if (!yaml_parser_decrease_flow_level(parser)) + return 0; + + /* No simple keys after the indicators ']' and '}'. */ + + parser->simple_key_allowed = 0; + + /* Consume the token. */ + + start_mark = parser->mark; + SKIP(parser); + end_mark = parser->mark; + + /* Create the FLOW-SEQUENCE-END of FLOW-MAPPING-END token. */ + + TOKEN_INIT(token, type, start_mark, end_mark); + + /* Append the token to the queue. */ + + if (!ENQUEUE(parser, parser->tokens, token)) + return 0; + + return 1; +} + +/* + * Produce the FLOW-ENTRY token. + */ + +static int +yaml_parser_fetch_flow_entry(yaml_parser_t *parser) +{ + yaml_mark_t start_mark, end_mark; + yaml_token_t token; + + /* Reset any potential simple keys on the current flow level. */ + + if (!yaml_parser_remove_simple_key(parser)) + return 0; + + /* Simple keys are allowed after ','. */ + + parser->simple_key_allowed = 1; + + /* Consume the token. */ + + start_mark = parser->mark; + SKIP(parser); + end_mark = parser->mark; + + /* Create the FLOW-ENTRY token and append it to the queue. */ + + TOKEN_INIT(token, YAML_FLOW_ENTRY_TOKEN, start_mark, end_mark); + + if (!ENQUEUE(parser, parser->tokens, token)) + return 0; + + return 1; +} + +/* + * Produce the BLOCK-ENTRY token. + */ + +static int +yaml_parser_fetch_block_entry(yaml_parser_t *parser) +{ + yaml_mark_t start_mark, end_mark; + yaml_token_t token; + + /* Check if the scanner is in the block context. */ + + if (!parser->flow_level) + { + /* Check if we are allowed to start a new entry. */ + + if (!parser->simple_key_allowed) { + return yaml_parser_set_scanner_error(parser, NULL, parser->mark, + "block sequence entries are not allowed in this context"); + } + + /* Add the BLOCK-SEQUENCE-START token if needed. */ + + if (!yaml_parser_roll_indent(parser, parser->mark.column, -1, + YAML_BLOCK_SEQUENCE_START_TOKEN, parser->mark)) + return 0; + } + else + { + /* + * It is an error for the '-' indicator to occur in the flow context, + * but we let the Parser detect and report about it because the Parser + * is able to point to the context. + */ + } + + /* Reset any potential simple keys on the current flow level. */ + + if (!yaml_parser_remove_simple_key(parser)) + return 0; + + /* Simple keys are allowed after '-'. */ + + parser->simple_key_allowed = 1; + + /* Consume the token. */ + + start_mark = parser->mark; + SKIP(parser); + end_mark = parser->mark; + + /* Create the BLOCK-ENTRY token and append it to the queue. */ + + TOKEN_INIT(token, YAML_BLOCK_ENTRY_TOKEN, start_mark, end_mark); + + if (!ENQUEUE(parser, parser->tokens, token)) + return 0; + + return 1; +} + +/* + * Produce the KEY token. + */ + +static int +yaml_parser_fetch_key(yaml_parser_t *parser) +{ + yaml_mark_t start_mark, end_mark; + yaml_token_t token; + + /* In the block context, additional checks are required. */ + + if (!parser->flow_level) + { + /* Check if we are allowed to start a new key (not nessesary simple). */ + + if (!parser->simple_key_allowed) { + return yaml_parser_set_scanner_error(parser, NULL, parser->mark, + "mapping keys are not allowed in this context"); + } + + /* Add the BLOCK-MAPPING-START token if needed. */ + + if (!yaml_parser_roll_indent(parser, parser->mark.column, -1, + YAML_BLOCK_MAPPING_START_TOKEN, parser->mark)) + return 0; + } + + /* Reset any potential simple keys on the current flow level. */ + + if (!yaml_parser_remove_simple_key(parser)) + return 0; + + /* Simple keys are allowed after '?' in the block context. */ + + parser->simple_key_allowed = (!parser->flow_level); + + /* Consume the token. */ + + start_mark = parser->mark; + SKIP(parser); + end_mark = parser->mark; + + /* Create the KEY token and append it to the queue. */ + + TOKEN_INIT(token, YAML_KEY_TOKEN, start_mark, end_mark); + + if (!ENQUEUE(parser, parser->tokens, token)) + return 0; + + return 1; +} + +/* + * Produce the VALUE token. + */ + +static int +yaml_parser_fetch_value(yaml_parser_t *parser) +{ + yaml_mark_t start_mark, end_mark; + yaml_token_t token; + yaml_simple_key_t *simple_key = parser->simple_keys.top-1; + + /* Have we found a simple key? */ + + if (simple_key->possible) + { + + /* Create the KEY token and insert it into the queue. */ + + TOKEN_INIT(token, YAML_KEY_TOKEN, simple_key->mark, simple_key->mark); + + if (!QUEUE_INSERT(parser, parser->tokens, + simple_key->token_number - parser->tokens_parsed, token)) + return 0; + + /* In the block context, we may need to add the BLOCK-MAPPING-START token. */ + + if (!yaml_parser_roll_indent(parser, simple_key->mark.column, + simple_key->token_number, + YAML_BLOCK_MAPPING_START_TOKEN, simple_key->mark)) + return 0; + + /* Remove the simple key. */ + + simple_key->possible = 0; + + /* A simple key cannot follow another simple key. */ + + parser->simple_key_allowed = 0; + } + else + { + /* The ':' indicator follows a complex key. */ + + /* In the block context, extra checks are required. */ + + if (!parser->flow_level) + { + /* Check if we are allowed to start a complex value. */ + + if (!parser->simple_key_allowed) { + return yaml_parser_set_scanner_error(parser, NULL, parser->mark, + "mapping values are not allowed in this context"); + } + + /* Add the BLOCK-MAPPING-START token if needed. */ + + if (!yaml_parser_roll_indent(parser, parser->mark.column, -1, + YAML_BLOCK_MAPPING_START_TOKEN, parser->mark)) + return 0; + } + + /* Simple keys after ':' are allowed in the block context. */ + + parser->simple_key_allowed = (!parser->flow_level); + } + + /* Consume the token. */ + + start_mark = parser->mark; + SKIP(parser); + end_mark = parser->mark; + + /* Create the VALUE token and append it to the queue. */ + + TOKEN_INIT(token, YAML_VALUE_TOKEN, start_mark, end_mark); + + if (!ENQUEUE(parser, parser->tokens, token)) + return 0; + + return 1; +} + +/* + * Produce the ALIAS or ANCHOR token. + */ + +static int +yaml_parser_fetch_anchor(yaml_parser_t *parser, yaml_token_type_t type) +{ + yaml_token_t token; + + /* An anchor or an alias could be a simple key. */ + + if (!yaml_parser_save_simple_key(parser)) + return 0; + + /* A simple key cannot follow an anchor or an alias. */ + + parser->simple_key_allowed = 0; + + /* Create the ALIAS or ANCHOR token and append it to the queue. */ + + if (!yaml_parser_scan_anchor(parser, &token, type)) + return 0; + + if (!ENQUEUE(parser, parser->tokens, token)) { + yaml_token_delete(&token); + return 0; + } + return 1; +} + +/* + * Produce the TAG token. + */ + +static int +yaml_parser_fetch_tag(yaml_parser_t *parser) +{ + yaml_token_t token; + + /* A tag could be a simple key. */ + + if (!yaml_parser_save_simple_key(parser)) + return 0; + + /* A simple key cannot follow a tag. */ + + parser->simple_key_allowed = 0; + + /* Create the TAG token and append it to the queue. */ + + if (!yaml_parser_scan_tag(parser, &token)) + return 0; + + if (!ENQUEUE(parser, parser->tokens, token)) { + yaml_token_delete(&token); + return 0; + } + + return 1; +} + +/* + * Produce the SCALAR(...,literal) or SCALAR(...,folded) tokens. + */ + +static int +yaml_parser_fetch_block_scalar(yaml_parser_t *parser, int literal) +{ + yaml_token_t token; + + /* Remove any potential simple keys. */ + + if (!yaml_parser_remove_simple_key(parser)) + return 0; + + /* A simple key may follow a block scalar. */ + + parser->simple_key_allowed = 1; + + /* Create the SCALAR token and append it to the queue. */ + + if (!yaml_parser_scan_block_scalar(parser, &token, literal)) + return 0; + + if (!ENQUEUE(parser, parser->tokens, token)) { + yaml_token_delete(&token); + return 0; + } + + return 1; +} + +/* + * Produce the SCALAR(...,single-quoted) or SCALAR(...,double-quoted) tokens. + */ + +static int +yaml_parser_fetch_flow_scalar(yaml_parser_t *parser, int single) +{ + yaml_token_t token; + + /* A plain scalar could be a simple key. */ + + if (!yaml_parser_save_simple_key(parser)) + return 0; + + /* A simple key cannot follow a flow scalar. */ + + parser->simple_key_allowed = 0; + + /* Create the SCALAR token and append it to the queue. */ + + if (!yaml_parser_scan_flow_scalar(parser, &token, single)) + return 0; + + if (!ENQUEUE(parser, parser->tokens, token)) { + yaml_token_delete(&token); + return 0; + } + + return 1; +} + +/* + * Produce the SCALAR(...,plain) token. + */ + +static int +yaml_parser_fetch_plain_scalar(yaml_parser_t *parser) +{ + yaml_token_t token; + + /* A plain scalar could be a simple key. */ + + if (!yaml_parser_save_simple_key(parser)) + return 0; + + /* A simple key cannot follow a flow scalar. */ + + parser->simple_key_allowed = 0; + + /* Create the SCALAR token and append it to the queue. */ + + if (!yaml_parser_scan_plain_scalar(parser, &token)) + return 0; + + if (!ENQUEUE(parser, parser->tokens, token)) { + yaml_token_delete(&token); + return 0; + } + + return 1; +} + +/* + * Eat whitespaces and comments until the next token is found. + */ + +static int +yaml_parser_scan_to_next_token(yaml_parser_t *parser) +{ + /* Until the next token is not found. */ + + while (1) + { + /* Allow the BOM mark to start a line. */ + + if (!CACHE(parser, 1)) return 0; + + if (parser->mark.column == 0 && IS_BOM(parser->buffer)) + SKIP(parser); + + /* + * Eat whitespaces. + * + * Tabs are allowed: + * + * - in the flow context; + * - in the block context, but not at the beginning of the line or + * after '-', '?', or ':' (complex value). + */ + + if (!CACHE(parser, 1)) return 0; + + while (CHECK(parser->buffer,' ') || + ((parser->flow_level || !parser->simple_key_allowed) && + CHECK(parser->buffer, '\t'))) { + SKIP(parser); + if (!CACHE(parser, 1)) return 0; + } + + /* Eat a comment until a line break. */ + + if (CHECK(parser->buffer, '#')) { + while (!IS_BREAKZ(parser->buffer)) { + SKIP(parser); + if (!CACHE(parser, 1)) return 0; + } + } + + /* If it is a line break, eat it. */ + + if (IS_BREAK(parser->buffer)) + { + if (!CACHE(parser, 2)) return 0; + SKIP_LINE(parser); + + /* In the block context, a new line may start a simple key. */ + + if (!parser->flow_level) { + parser->simple_key_allowed = 1; + } + } + else + { + /* We have found a token. */ + + break; + } + } + + return 1; +} + +/* + * Scan a YAML-DIRECTIVE or TAG-DIRECTIVE token. + * + * Scope: + * %YAML 1.1 # a comment \n + * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + * %TAG !yaml! tag:yaml.org,2002: \n + * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + */ + +int +yaml_parser_scan_directive(yaml_parser_t *parser, yaml_token_t *token) +{ + yaml_mark_t start_mark, end_mark; + yaml_char_t *name = NULL; + int major, minor; + yaml_char_t *handle = NULL, *prefix = NULL; + + /* Eat '%'. */ + + start_mark = parser->mark; + + SKIP(parser); + + /* Scan the directive name. */ + + if (!yaml_parser_scan_directive_name(parser, start_mark, &name)) + goto error; + + /* Is it a YAML directive? */ + + if (strcmp((char *)name, "YAML") == 0) + { + /* Scan the VERSION directive value. */ + + if (!yaml_parser_scan_version_directive_value(parser, start_mark, + &major, &minor)) + goto error; + + end_mark = parser->mark; + + /* Create a VERSION-DIRECTIVE token. */ + + VERSION_DIRECTIVE_TOKEN_INIT(*token, major, minor, + start_mark, end_mark); + } + + /* Is it a TAG directive? */ + + else if (strcmp((char *)name, "TAG") == 0) + { + /* Scan the TAG directive value. */ + + if (!yaml_parser_scan_tag_directive_value(parser, start_mark, + &handle, &prefix)) + goto error; + + end_mark = parser->mark; + + /* Create a TAG-DIRECTIVE token. */ + + TAG_DIRECTIVE_TOKEN_INIT(*token, handle, prefix, + start_mark, end_mark); + } + + /* Unknown directive. */ + + else + { + yaml_parser_set_scanner_error(parser, "while scanning a directive", + start_mark, "found uknown directive name"); + goto error; + } + + /* Eat the rest of the line including any comments. */ + + if (!CACHE(parser, 1)) goto error; + + while (IS_BLANK(parser->buffer)) { + SKIP(parser); + if (!CACHE(parser, 1)) goto error; + } + + if (CHECK(parser->buffer, '#')) { + while (!IS_BREAKZ(parser->buffer)) { + SKIP(parser); + if (!CACHE(parser, 1)) goto error; + } + } + + /* Check if we are at the end of the line. */ + + if (!IS_BREAKZ(parser->buffer)) { + yaml_parser_set_scanner_error(parser, "while scanning a directive", + start_mark, "did not find expected comment or line break"); + goto error; + } + + /* Eat a line break. */ + + if (IS_BREAK(parser->buffer)) { + if (!CACHE(parser, 2)) goto error; + SKIP_LINE(parser); + } + + yaml_free(name); + + return 1; + +error: + yaml_free(prefix); + yaml_free(handle); + yaml_free(name); + return 0; +} + +/* + * Scan the directive name. + * + * Scope: + * %YAML 1.1 # a comment \n + * ^^^^ + * %TAG !yaml! tag:yaml.org,2002: \n + * ^^^ + */ + +static int +yaml_parser_scan_directive_name(yaml_parser_t *parser, + yaml_mark_t start_mark, yaml_char_t **name) +{ + yaml_string_t string = NULL_STRING; + + if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error; + + /* Consume the directive name. */ + + if (!CACHE(parser, 1)) goto error; + + while (IS_ALPHA(parser->buffer)) + { + if (!READ(parser, string)) goto error; + if (!CACHE(parser, 1)) goto error; + } + + /* Check if the name is empty. */ + + if (string.start == string.pointer) { + yaml_parser_set_scanner_error(parser, "while scanning a directive", + start_mark, "could not find expected directive name"); + goto error; + } + + /* Check for an blank character after the name. */ + + if (!IS_BLANKZ(parser->buffer)) { + yaml_parser_set_scanner_error(parser, "while scanning a directive", + start_mark, "found unexpected non-alphabetical character"); + goto error; + } + + *name = string.start; + + return 1; + +error: + STRING_DEL(parser, string); + return 0; +} + +/* + * Scan the value of VERSION-DIRECTIVE. + * + * Scope: + * %YAML 1.1 # a comment \n + * ^^^^^^ + */ + +static int +yaml_parser_scan_version_directive_value(yaml_parser_t *parser, + yaml_mark_t start_mark, int *major, int *minor) +{ + /* Eat whitespaces. */ + + if (!CACHE(parser, 1)) return 0; + + while (IS_BLANK(parser->buffer)) { + SKIP(parser); + if (!CACHE(parser, 1)) return 0; + } + + /* Consume the major version number. */ + + if (!yaml_parser_scan_version_directive_number(parser, start_mark, major)) + return 0; + + /* Eat '.'. */ + + if (!CHECK(parser->buffer, '.')) { + return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", + start_mark, "did not find expected digit or '.' character"); + } + + SKIP(parser); + + /* Consume the minor version number. */ + + if (!yaml_parser_scan_version_directive_number(parser, start_mark, minor)) + return 0; + + return 1; +} + +#define MAX_NUMBER_LENGTH 9 + +/* + * Scan the version number of VERSION-DIRECTIVE. + * + * Scope: + * %YAML 1.1 # a comment \n + * ^ + * %YAML 1.1 # a comment \n + * ^ + */ + +static int +yaml_parser_scan_version_directive_number(yaml_parser_t *parser, + yaml_mark_t start_mark, int *number) +{ + int value = 0; + size_t length = 0; + + /* Repeat while the next character is digit. */ + + if (!CACHE(parser, 1)) return 0; + + while (IS_DIGIT(parser->buffer)) + { + /* Check if the number is too long. */ + + if (++length > MAX_NUMBER_LENGTH) { + return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", + start_mark, "found extremely long version number"); + } + + value = value*10 + AS_DIGIT(parser->buffer); + + SKIP(parser); + + if (!CACHE(parser, 1)) return 0; + } + + /* Check if the number was present. */ + + if (!length) { + return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", + start_mark, "did not find expected version number"); + } + + *number = value; + + return 1; +} + +/* + * Scan the value of a TAG-DIRECTIVE token. + * + * Scope: + * %TAG !yaml! tag:yaml.org,2002: \n + * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + */ + +static int +yaml_parser_scan_tag_directive_value(yaml_parser_t *parser, + yaml_mark_t start_mark, yaml_char_t **handle, yaml_char_t **prefix) +{ + yaml_char_t *handle_value = NULL; + yaml_char_t *prefix_value = NULL; + + /* Eat whitespaces. */ + + if (!CACHE(parser, 1)) goto error; + + while (IS_BLANK(parser->buffer)) { + SKIP(parser); + if (!CACHE(parser, 1)) goto error; + } + + /* Scan a handle. */ + + if (!yaml_parser_scan_tag_handle(parser, 1, start_mark, &handle_value)) + goto error; + + /* Expect a whitespace. */ + + if (!CACHE(parser, 1)) goto error; + + if (!IS_BLANK(parser->buffer)) { + yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive", + start_mark, "did not find expected whitespace"); + goto error; + } + + /* Eat whitespaces. */ + + while (IS_BLANK(parser->buffer)) { + SKIP(parser); + if (!CACHE(parser, 1)) goto error; + } + + /* Scan a prefix. */ + + if (!yaml_parser_scan_tag_uri(parser, 1, NULL, start_mark, &prefix_value)) + goto error; + + /* Expect a whitespace or line break. */ + + if (!CACHE(parser, 1)) goto error; + + if (!IS_BLANKZ(parser->buffer)) { + yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive", + start_mark, "did not find expected whitespace or line break"); + goto error; + } + + *handle = handle_value; + *prefix = prefix_value; + + return 1; + +error: + yaml_free(handle_value); + yaml_free(prefix_value); + return 0; +} + +static int +yaml_parser_scan_anchor(yaml_parser_t *parser, yaml_token_t *token, + yaml_token_type_t type) +{ + int length = 0; + yaml_mark_t start_mark, end_mark; + yaml_string_t string = NULL_STRING; + + if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error; + + /* Eat the indicator character. */ + + start_mark = parser->mark; + + SKIP(parser); + + /* Consume the value. */ + + if (!CACHE(parser, 1)) goto error; + + while (IS_ALPHA(parser->buffer)) { + if (!READ(parser, string)) goto error; + if (!CACHE(parser, 1)) goto error; + length ++; + } + + end_mark = parser->mark; + + /* + * Check if length of the anchor is greater than 0 and it is followed by + * a whitespace character or one of the indicators: + * + * '?', ':', ',', ']', '}', '%', '@', '`'. + */ + + if (!length || !(IS_BLANKZ(parser->buffer) || CHECK(parser->buffer, '?') + || CHECK(parser->buffer, ':') || CHECK(parser->buffer, ',') + || CHECK(parser->buffer, ']') || CHECK(parser->buffer, '}') + || CHECK(parser->buffer, '%') || CHECK(parser->buffer, '@') + || CHECK(parser->buffer, '`'))) { + yaml_parser_set_scanner_error(parser, type == YAML_ANCHOR_TOKEN ? + "while scanning an anchor" : "while scanning an alias", start_mark, + "did not find expected alphabetic or numeric character"); + goto error; + } + + /* Create a token. */ + + if (type == YAML_ANCHOR_TOKEN) { + ANCHOR_TOKEN_INIT(*token, string.start, start_mark, end_mark); + } + else { + ALIAS_TOKEN_INIT(*token, string.start, start_mark, end_mark); + } + + return 1; + +error: + STRING_DEL(parser, string); + return 0; +} + +/* + * Scan a TAG token. + */ + +static int +yaml_parser_scan_tag(yaml_parser_t *parser, yaml_token_t *token) +{ + yaml_char_t *handle = NULL; + yaml_char_t *suffix = NULL; + yaml_mark_t start_mark, end_mark; + + start_mark = parser->mark; + + /* Check if the tag is in the canonical form. */ + + if (!CACHE(parser, 2)) goto error; + + if (CHECK_AT(parser->buffer, '<', 1)) + { + /* Set the handle to '' */ + + handle = yaml_malloc(1); + if (!handle) goto error; + handle[0] = '\0'; + + /* Eat '!<' */ + + SKIP(parser); + SKIP(parser); + + /* Consume the tag value. */ + + if (!yaml_parser_scan_tag_uri(parser, 0, NULL, start_mark, &suffix)) + goto error; + + /* Check for '>' and eat it. */ + + if (!CHECK(parser->buffer, '>')) { + yaml_parser_set_scanner_error(parser, "while scanning a tag", + start_mark, "did not find the expected '>'"); + goto error; + } + + SKIP(parser); + } + else + { + /* The tag has either the '!suffix' or the '!handle!suffix' form. */ + + /* First, try to scan a handle. */ + + if (!yaml_parser_scan_tag_handle(parser, 0, start_mark, &handle)) + goto error; + + /* Check if it is, indeed, handle. */ + + if (handle[0] == '!' && handle[1] != '\0' && handle[strlen((char *)handle)-1] == '!') + { + /* Scan the suffix now. */ + + if (!yaml_parser_scan_tag_uri(parser, 0, NULL, start_mark, &suffix)) + goto error; + } + else + { + /* It wasn't a handle after all. Scan the rest of the tag. */ + + if (!yaml_parser_scan_tag_uri(parser, 0, handle, start_mark, &suffix)) + goto error; + + /* Set the handle to '!'. */ + + yaml_free(handle); + handle = yaml_malloc(2); + if (!handle) goto error; + handle[0] = '!'; + handle[1] = '\0'; + + /* + * A special case: the '!' tag. Set the handle to '' and the + * suffix to '!'. + */ + + if (suffix[0] == '\0') { + yaml_char_t *tmp = handle; + handle = suffix; + suffix = tmp; + } + } + } + + /* Check the character which ends the tag. */ + + if (!CACHE(parser, 1)) goto error; + + if (!IS_BLANKZ(parser->buffer)) { + yaml_parser_set_scanner_error(parser, "while scanning a tag", + start_mark, "did not find expected whitespace or line break"); + goto error; + } + + end_mark = parser->mark; + + /* Create a token. */ + + TAG_TOKEN_INIT(*token, handle, suffix, start_mark, end_mark); + + return 1; + +error: + yaml_free(handle); + yaml_free(suffix); + return 0; +} + +/* + * Scan a tag handle. + */ + +static int +yaml_parser_scan_tag_handle(yaml_parser_t *parser, int directive, + yaml_mark_t start_mark, yaml_char_t **handle) +{ + yaml_string_t string = NULL_STRING; + + if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error; + + /* Check the initial '!' character. */ + + if (!CACHE(parser, 1)) goto error; + + if (!CHECK(parser->buffer, '!')) { + yaml_parser_set_scanner_error(parser, directive ? + "while scanning a tag directive" : "while scanning a tag", + start_mark, "did not find expected '!'"); + goto error; + } + + /* Copy the '!' character. */ + + if (!READ(parser, string)) goto error; + + /* Copy all subsequent alphabetical and numerical characters. */ + + if (!CACHE(parser, 1)) goto error; + + while (IS_ALPHA(parser->buffer)) + { + if (!READ(parser, string)) goto error; + if (!CACHE(parser, 1)) goto error; + } + + /* Check if the trailing character is '!' and copy it. */ + + if (CHECK(parser->buffer, '!')) + { + if (!READ(parser, string)) goto error; + } + else + { + /* + * It's either the '!' tag or not really a tag handle. If it's a %TAG + * directive, it's an error. If it's a tag token, it must be a part of + * URI. + */ + + if (directive && !(string.start[0] == '!' && string.start[1] == '\0')) { + yaml_parser_set_scanner_error(parser, "while parsing a tag directive", + start_mark, "did not find expected '!'"); + goto error; + } + } + + *handle = string.start; + + return 1; + +error: + STRING_DEL(parser, string); + return 0; +} + +/* + * Scan a tag. + */ + +static int +yaml_parser_scan_tag_uri(yaml_parser_t *parser, int directive, + yaml_char_t *head, yaml_mark_t start_mark, yaml_char_t **uri) +{ + size_t length = head ? strlen((char *)head) : 0; + yaml_string_t string = NULL_STRING; + + if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error; + + /* Resize the string to include the head. */ + + while (string.end - string.start <= (int)length) { + if (!yaml_string_extend(&string.start, &string.pointer, &string.end)) { + parser->error = YAML_MEMORY_ERROR; + goto error; + } + } + + /* + * Copy the head if needed. + * + * Note that we don't copy the leading '!' character. + */ + + if (length > 1) { + memcpy(string.start, head+1, length-1); + string.pointer += length-1; + } + + /* Scan the tag. */ + + if (!CACHE(parser, 1)) goto error; + + /* + * The set of characters that may appear in URI is as follows: + * + * '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&', + * '=', '+', '$', ',', '.', '!', '~', '*', '\'', '(', ')', '[', ']', + * '%'. + */ + + while (IS_ALPHA(parser->buffer) || CHECK(parser->buffer, ';') + || CHECK(parser->buffer, '/') || CHECK(parser->buffer, '?') + || CHECK(parser->buffer, ':') || CHECK(parser->buffer, '@') + || CHECK(parser->buffer, '&') || CHECK(parser->buffer, '=') + || CHECK(parser->buffer, '+') || CHECK(parser->buffer, '$') + || CHECK(parser->buffer, ',') || CHECK(parser->buffer, '.') + || CHECK(parser->buffer, '!') || CHECK(parser->buffer, '~') + || CHECK(parser->buffer, '*') || CHECK(parser->buffer, '\'') + || CHECK(parser->buffer, '(') || CHECK(parser->buffer, ')') + || CHECK(parser->buffer, '[') || CHECK(parser->buffer, ']') + || CHECK(parser->buffer, '%')) + { + /* Check if it is a URI-escape sequence. */ + + if (CHECK(parser->buffer, '%')) { + if (!yaml_parser_scan_uri_escapes(parser, + directive, start_mark, &string)) goto error; + } + else { + if (!READ(parser, string)) goto error; + } + + length ++; + if (!CACHE(parser, 1)) goto error; + } + + /* Check if the tag is non-empty. */ + + if (!length) { + if (!STRING_EXTEND(parser, string)) + goto error; + + yaml_parser_set_scanner_error(parser, directive ? + "while parsing a %TAG directive" : "while parsing a tag", + start_mark, "did not find expected tag URI"); + goto error; + } + + *uri = string.start; + + return 1; + +error: + STRING_DEL(parser, string); + return 0; +} + +/* + * Decode an URI-escape sequence corresponding to a single UTF-8 character. + */ + +static int +yaml_parser_scan_uri_escapes(yaml_parser_t *parser, int directive, + yaml_mark_t start_mark, yaml_string_t *string) +{ + int width = 0; + + /* Decode the required number of characters. */ + + do { + + unsigned char octet = 0; + + /* Check for a URI-escaped octet. */ + + if (!CACHE(parser, 3)) return 0; + + if (!(CHECK(parser->buffer, '%') + && IS_HEX_AT(parser->buffer, 1) + && IS_HEX_AT(parser->buffer, 2))) { + return yaml_parser_set_scanner_error(parser, directive ? + "while parsing a %TAG directive" : "while parsing a tag", + start_mark, "did not find URI escaped octet"); + } + + /* Get the octet. */ + + octet = (AS_HEX_AT(parser->buffer, 1) << 4) + AS_HEX_AT(parser->buffer, 2); + + /* If it is the leading octet, determine the length of the UTF-8 sequence. */ + + if (!width) + { + width = (octet & 0x80) == 0x00 ? 1 : + (octet & 0xE0) == 0xC0 ? 2 : + (octet & 0xF0) == 0xE0 ? 3 : + (octet & 0xF8) == 0xF0 ? 4 : 0; + if (!width) { + return yaml_parser_set_scanner_error(parser, directive ? + "while parsing a %TAG directive" : "while parsing a tag", + start_mark, "found an incorrect leading UTF-8 octet"); + } + } + else + { + /* Check if the trailing octet is correct. */ + + if ((octet & 0xC0) != 0x80) { + return yaml_parser_set_scanner_error(parser, directive ? + "while parsing a %TAG directive" : "while parsing a tag", + start_mark, "found an incorrect trailing UTF-8 octet"); + } + } + + /* Copy the octet and move the pointers. */ + + *(string->pointer++) = octet; + SKIP(parser); + SKIP(parser); + SKIP(parser); + + } while (--width); + + return 1; +} + +/* + * Scan a block scalar. + */ + +static int +yaml_parser_scan_block_scalar(yaml_parser_t *parser, yaml_token_t *token, + int literal) +{ + yaml_mark_t start_mark; + yaml_mark_t end_mark; + yaml_string_t string = NULL_STRING; + yaml_string_t leading_break = NULL_STRING; + yaml_string_t trailing_breaks = NULL_STRING; + int chomping = 0; + int increment = 0; + int indent = 0; + int leading_blank = 0; + int trailing_blank = 0; + + if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error; + if (!STRING_INIT(parser, leading_break, INITIAL_STRING_SIZE)) goto error; + if (!STRING_INIT(parser, trailing_breaks, INITIAL_STRING_SIZE)) goto error; + + /* Eat the indicator '|' or '>'. */ + + start_mark = parser->mark; + + SKIP(parser); + + /* Scan the additional block scalar indicators. */ + + if (!CACHE(parser, 1)) goto error; + + /* Check for a chomping indicator. */ + + if (CHECK(parser->buffer, '+') || CHECK(parser->buffer, '-')) + { + /* Set the chomping method and eat the indicator. */ + + chomping = CHECK(parser->buffer, '+') ? +1 : -1; + + SKIP(parser); + + /* Check for an indentation indicator. */ + + if (!CACHE(parser, 1)) goto error; + + if (IS_DIGIT(parser->buffer)) + { + /* Check that the intendation is greater than 0. */ + + if (CHECK(parser->buffer, '0')) { + yaml_parser_set_scanner_error(parser, "while scanning a block scalar", + start_mark, "found an intendation indicator equal to 0"); + goto error; + } + + /* Get the intendation level and eat the indicator. */ + + increment = AS_DIGIT(parser->buffer); + + SKIP(parser); + } + } + + /* Do the same as above, but in the opposite order. */ + + else if (IS_DIGIT(parser->buffer)) + { + if (CHECK(parser->buffer, '0')) { + yaml_parser_set_scanner_error(parser, "while scanning a block scalar", + start_mark, "found an intendation indicator equal to 0"); + goto error; + } + + increment = AS_DIGIT(parser->buffer); + + SKIP(parser); + + if (!CACHE(parser, 1)) goto error; + + if (CHECK(parser->buffer, '+') || CHECK(parser->buffer, '-')) { + chomping = CHECK(parser->buffer, '+') ? +1 : -1; + + SKIP(parser); + } + } + + /* Eat whitespaces and comments to the end of the line. */ + + if (!CACHE(parser, 1)) goto error; + + while (IS_BLANK(parser->buffer)) { + SKIP(parser); + if (!CACHE(parser, 1)) goto error; + } + + if (CHECK(parser->buffer, '#')) { + while (!IS_BREAKZ(parser->buffer)) { + SKIP(parser); + if (!CACHE(parser, 1)) goto error; + } + } + + /* Check if we are at the end of the line. */ + + if (!IS_BREAKZ(parser->buffer)) { + yaml_parser_set_scanner_error(parser, "while scanning a block scalar", + start_mark, "did not find expected comment or line break"); + goto error; + } + + /* Eat a line break. */ + + if (IS_BREAK(parser->buffer)) { + if (!CACHE(parser, 2)) goto error; + SKIP_LINE(parser); + } + + end_mark = parser->mark; + + /* Set the intendation level if it was specified. */ + + if (increment) { + indent = parser->indent >= 0 ? parser->indent+increment : increment; + } + + /* Scan the leading line breaks and determine the indentation level if needed. */ + + if (!yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, + start_mark, &end_mark)) goto error; + + /* Scan the block scalar content. */ + + if (!CACHE(parser, 1)) goto error; + + while ((int)parser->mark.column == indent && !IS_Z(parser->buffer)) + { + /* + * We are at the beginning of a non-empty line. + */ + + /* Is it a trailing whitespace? */ + + trailing_blank = IS_BLANK(parser->buffer); + + /* Check if we need to fold the leading line break. */ + + if (!literal && (*leading_break.start == '\n') + && !leading_blank && !trailing_blank) + { + /* Do we need to join the lines by space? */ + + if (*trailing_breaks.start == '\0') { + if (!STRING_EXTEND(parser, string)) goto error; + *(string.pointer ++) = ' '; + } + + CLEAR(parser, leading_break); + } + else { + if (!JOIN(parser, string, leading_break)) goto error; + CLEAR(parser, leading_break); + } + + /* Append the remaining line breaks. */ + + if (!JOIN(parser, string, trailing_breaks)) goto error; + CLEAR(parser, trailing_breaks); + + /* Is it a leading whitespace? */ + + leading_blank = IS_BLANK(parser->buffer); + + /* Consume the current line. */ + + while (!IS_BREAKZ(parser->buffer)) { + if (!READ(parser, string)) goto error; + if (!CACHE(parser, 1)) goto error; + } + + /* Consume the line break. */ + + if (!CACHE(parser, 2)) goto error; + + if (!READ_LINE(parser, leading_break)) goto error; + + /* Eat the following intendation spaces and line breaks. */ + + if (!yaml_parser_scan_block_scalar_breaks(parser, + &indent, &trailing_breaks, start_mark, &end_mark)) goto error; + } + + /* Chomp the tail. */ + + if (chomping != -1) { + if (!JOIN(parser, string, leading_break)) goto error; + } + if (chomping == 1) { + if (!JOIN(parser, string, trailing_breaks)) goto error; + } + + /* Create a token. */ + + SCALAR_TOKEN_INIT(*token, string.start, string.pointer-string.start, + literal ? YAML_LITERAL_SCALAR_STYLE : YAML_FOLDED_SCALAR_STYLE, + start_mark, end_mark); + + STRING_DEL(parser, leading_break); + STRING_DEL(parser, trailing_breaks); + + return 1; + +error: + STRING_DEL(parser, string); + STRING_DEL(parser, leading_break); + STRING_DEL(parser, trailing_breaks); + + return 0; +} + +/* + * Scan intendation spaces and line breaks for a block scalar. Determine the + * intendation level if needed. + */ + +static int +yaml_parser_scan_block_scalar_breaks(yaml_parser_t *parser, + int *indent, yaml_string_t *breaks, + yaml_mark_t start_mark, yaml_mark_t *end_mark) +{ + int max_indent = 0; + + *end_mark = parser->mark; + + /* Eat the intendation spaces and line breaks. */ + + while (1) + { + /* Eat the intendation spaces. */ + + if (!CACHE(parser, 1)) return 0; + + while ((!*indent || (int)parser->mark.column < *indent) + && IS_SPACE(parser->buffer)) { + SKIP(parser); + if (!CACHE(parser, 1)) return 0; + } + + if ((int)parser->mark.column > max_indent) + max_indent = (int)parser->mark.column; + + /* Check for a tab character messing the intendation. */ + + if ((!*indent || (int)parser->mark.column < *indent) + && IS_TAB(parser->buffer)) { + return yaml_parser_set_scanner_error(parser, "while scanning a block scalar", + start_mark, "found a tab character where an intendation space is expected"); + } + + /* Have we found a non-empty line? */ + + if (!IS_BREAK(parser->buffer)) break; + + /* Consume the line break. */ + + if (!CACHE(parser, 2)) return 0; + if (!READ_LINE(parser, *breaks)) return 0; + *end_mark = parser->mark; + } + + /* Determine the indentation level if needed. */ + + if (!*indent) { + *indent = max_indent; + if (*indent < parser->indent + 1) + *indent = parser->indent + 1; + if (*indent < 1) + *indent = 1; + } + + return 1; +} + +/* + * Scan a quoted scalar. + */ + +static int +yaml_parser_scan_flow_scalar(yaml_parser_t *parser, yaml_token_t *token, + int single) +{ + yaml_mark_t start_mark; + yaml_mark_t end_mark; + yaml_string_t string = NULL_STRING; + yaml_string_t leading_break = NULL_STRING; + yaml_string_t trailing_breaks = NULL_STRING; + yaml_string_t whitespaces = NULL_STRING; + int leading_blanks; + + if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error; + if (!STRING_INIT(parser, leading_break, INITIAL_STRING_SIZE)) goto error; + if (!STRING_INIT(parser, trailing_breaks, INITIAL_STRING_SIZE)) goto error; + if (!STRING_INIT(parser, whitespaces, INITIAL_STRING_SIZE)) goto error; + + /* Eat the left quote. */ + + start_mark = parser->mark; + + SKIP(parser); + + /* Consume the content of the quoted scalar. */ + + while (1) + { + /* Check that there are no document indicators at the beginning of the line. */ + + if (!CACHE(parser, 4)) goto error; + + if (parser->mark.column == 0 && + ((CHECK_AT(parser->buffer, '-', 0) && + CHECK_AT(parser->buffer, '-', 1) && + CHECK_AT(parser->buffer, '-', 2)) || + (CHECK_AT(parser->buffer, '.', 0) && + CHECK_AT(parser->buffer, '.', 1) && + CHECK_AT(parser->buffer, '.', 2))) && + IS_BLANKZ_AT(parser->buffer, 3)) + { + yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar", + start_mark, "found unexpected document indicator"); + goto error; + } + + /* Check for EOF. */ + + if (IS_Z(parser->buffer)) { + yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar", + start_mark, "found unexpected end of stream"); + goto error; + } + + /* Consume non-blank characters. */ + + if (!CACHE(parser, 2)) goto error; + + leading_blanks = 0; + + while (!IS_BLANKZ(parser->buffer)) + { + /* Check for an escaped single quote. */ + + if (single && CHECK_AT(parser->buffer, '\'', 0) + && CHECK_AT(parser->buffer, '\'', 1)) + { + if (!STRING_EXTEND(parser, string)) goto error; + *(string.pointer++) = '\''; + SKIP(parser); + SKIP(parser); + } + + /* Check for the right quote. */ + + else if (CHECK(parser->buffer, single ? '\'' : '"')) + { + break; + } + + /* Check for an escaped line break. */ + + else if (!single && CHECK(parser->buffer, '\\') + && IS_BREAK_AT(parser->buffer, 1)) + { + if (!CACHE(parser, 3)) goto error; + SKIP(parser); + SKIP_LINE(parser); + leading_blanks = 1; + break; + } + + /* Check for an escape sequence. */ + + else if (!single && CHECK(parser->buffer, '\\')) + { + size_t code_length = 0; + + if (!STRING_EXTEND(parser, string)) goto error; + + /* Check the escape character. */ + + switch (parser->buffer.pointer[1]) + { + case '0': + *(string.pointer++) = '\0'; + break; + + case 'a': + *(string.pointer++) = '\x07'; + break; + + case 'b': + *(string.pointer++) = '\x08'; + break; + + case 't': + case '\t': + *(string.pointer++) = '\x09'; + break; + + case 'n': + *(string.pointer++) = '\x0A'; + break; + + case 'v': + *(string.pointer++) = '\x0B'; + break; + + case 'f': + *(string.pointer++) = '\x0C'; + break; + + case 'r': + *(string.pointer++) = '\x0D'; + break; + + case 'e': + *(string.pointer++) = '\x1B'; + break; + + case ' ': + *(string.pointer++) = '\x20'; + break; + + case '"': + *(string.pointer++) = '"'; + break; + + case '\'': + *(string.pointer++) = '\''; + break; + + case '\\': + *(string.pointer++) = '\\'; + break; + + case 'N': /* NEL (#x85) */ + *(string.pointer++) = '\xC2'; + *(string.pointer++) = '\x85'; + break; + + case '_': /* #xA0 */ + *(string.pointer++) = '\xC2'; + *(string.pointer++) = '\xA0'; + break; + + case 'L': /* LS (#x2028) */ + *(string.pointer++) = '\xE2'; + *(string.pointer++) = '\x80'; + *(string.pointer++) = '\xA8'; + break; + + case 'P': /* PS (#x2029) */ + *(string.pointer++) = '\xE2'; + *(string.pointer++) = '\x80'; + *(string.pointer++) = '\xA9'; + break; + + case 'x': + code_length = 2; + break; + + case 'u': + code_length = 4; + break; + + case 'U': + code_length = 8; + break; + + default: + yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", + start_mark, "found unknown escape character"); + goto error; + } + + SKIP(parser); + SKIP(parser); + + /* Consume an arbitrary escape code. */ + + if (code_length) + { + unsigned int value = 0; + size_t k; + + /* Scan the character value. */ + + if (!CACHE(parser, code_length)) goto error; + + for (k = 0; k < code_length; k ++) { + if (!IS_HEX_AT(parser->buffer, k)) { + yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", + start_mark, "did not find expected hexdecimal number"); + goto error; + } + value = (value << 4) + AS_HEX_AT(parser->buffer, k); + } + + /* Check the value and write the character. */ + + if ((value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF) { + yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", + start_mark, "found invalid Unicode character escape code"); + goto error; + } + + if (value <= 0x7F) { + *(string.pointer++) = value; + } + else if (value <= 0x7FF) { + *(string.pointer++) = 0xC0 + (value >> 6); + *(string.pointer++) = 0x80 + (value & 0x3F); + } + else if (value <= 0xFFFF) { + *(string.pointer++) = 0xE0 + (value >> 12); + *(string.pointer++) = 0x80 + ((value >> 6) & 0x3F); + *(string.pointer++) = 0x80 + (value & 0x3F); + } + else { + *(string.pointer++) = 0xF0 + (value >> 18); + *(string.pointer++) = 0x80 + ((value >> 12) & 0x3F); + *(string.pointer++) = 0x80 + ((value >> 6) & 0x3F); + *(string.pointer++) = 0x80 + (value & 0x3F); + } + + /* Advance the pointer. */ + + for (k = 0; k < code_length; k ++) { + SKIP(parser); + } + } + } + + else + { + /* It is a non-escaped non-blank character. */ + + if (!READ(parser, string)) goto error; + } + + if (!CACHE(parser, 2)) goto error; + } + + /* Check if we are at the end of the scalar. */ + + if (CHECK(parser->buffer, single ? '\'' : '"')) + break; + + /* Consume blank characters. */ + + if (!CACHE(parser, 1)) goto error; + + while (IS_BLANK(parser->buffer) || IS_BREAK(parser->buffer)) + { + if (IS_BLANK(parser->buffer)) + { + /* Consume a space or a tab character. */ + + if (!leading_blanks) { + if (!READ(parser, whitespaces)) goto error; + } + else { + SKIP(parser); + } + } + else + { + if (!CACHE(parser, 2)) goto error; + + /* Check if it is a first line break. */ + + if (!leading_blanks) + { + CLEAR(parser, whitespaces); + if (!READ_LINE(parser, leading_break)) goto error; + leading_blanks = 1; + } + else + { + if (!READ_LINE(parser, trailing_breaks)) goto error; + } + } + if (!CACHE(parser, 1)) goto error; + } + + /* Join the whitespaces or fold line breaks. */ + + if (leading_blanks) + { + /* Do we need to fold line breaks? */ + + if (leading_break.start[0] == '\n') { + if (trailing_breaks.start[0] == '\0') { + if (!STRING_EXTEND(parser, string)) goto error; + *(string.pointer++) = ' '; + } + else { + if (!JOIN(parser, string, trailing_breaks)) goto error; + CLEAR(parser, trailing_breaks); + } + CLEAR(parser, leading_break); + } + else { + if (!JOIN(parser, string, leading_break)) goto error; + if (!JOIN(parser, string, trailing_breaks)) goto error; + CLEAR(parser, leading_break); + CLEAR(parser, trailing_breaks); + } + } + else + { + if (!JOIN(parser, string, whitespaces)) goto error; + CLEAR(parser, whitespaces); + } + } + + /* Eat the right quote. */ + + SKIP(parser); + + end_mark = parser->mark; + + /* Create a token. */ + + SCALAR_TOKEN_INIT(*token, string.start, string.pointer-string.start, + single ? YAML_SINGLE_QUOTED_SCALAR_STYLE : YAML_DOUBLE_QUOTED_SCALAR_STYLE, + start_mark, end_mark); + + STRING_DEL(parser, leading_break); + STRING_DEL(parser, trailing_breaks); + STRING_DEL(parser, whitespaces); + + return 1; + +error: + STRING_DEL(parser, string); + STRING_DEL(parser, leading_break); + STRING_DEL(parser, trailing_breaks); + STRING_DEL(parser, whitespaces); + + return 0; +} + +/* + * Scan a plain scalar. + */ + +static int +yaml_parser_scan_plain_scalar(yaml_parser_t *parser, yaml_token_t *token) +{ + yaml_mark_t start_mark; + yaml_mark_t end_mark; + yaml_string_t string = NULL_STRING; + yaml_string_t leading_break = NULL_STRING; + yaml_string_t trailing_breaks = NULL_STRING; + yaml_string_t whitespaces = NULL_STRING; + int leading_blanks = 0; + int indent = parser->indent+1; + + if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error; + if (!STRING_INIT(parser, leading_break, INITIAL_STRING_SIZE)) goto error; + if (!STRING_INIT(parser, trailing_breaks, INITIAL_STRING_SIZE)) goto error; + if (!STRING_INIT(parser, whitespaces, INITIAL_STRING_SIZE)) goto error; + + start_mark = end_mark = parser->mark; + + /* Consume the content of the plain scalar. */ + + while (1) + { + /* Check for a document indicator. */ + + if (!CACHE(parser, 4)) goto error; + + if (parser->mark.column == 0 && + ((CHECK_AT(parser->buffer, '-', 0) && + CHECK_AT(parser->buffer, '-', 1) && + CHECK_AT(parser->buffer, '-', 2)) || + (CHECK_AT(parser->buffer, '.', 0) && + CHECK_AT(parser->buffer, '.', 1) && + CHECK_AT(parser->buffer, '.', 2))) && + IS_BLANKZ_AT(parser->buffer, 3)) break; + + /* Check for a comment. */ + + if (CHECK(parser->buffer, '#')) + break; + + /* Consume non-blank characters. */ + + while (!IS_BLANKZ(parser->buffer)) + { + /* Check for 'x:x' in the flow context. TODO: Fix the test "spec-08-13". */ + + if (parser->flow_level + && CHECK(parser->buffer, ':') + && !IS_BLANKZ_AT(parser->buffer, 1)) { + yaml_parser_set_scanner_error(parser, "while scanning a plain scalar", + start_mark, "found unexpected ':'"); + goto error; + } + + /* Check for indicators that may end a plain scalar. */ + + if ((CHECK(parser->buffer, ':') && IS_BLANKZ_AT(parser->buffer, 1)) + || (parser->flow_level && + (CHECK(parser->buffer, ',') || CHECK(parser->buffer, ':') + || CHECK(parser->buffer, '?') || CHECK(parser->buffer, '[') + || CHECK(parser->buffer, ']') || CHECK(parser->buffer, '{') + || CHECK(parser->buffer, '}')))) + break; + + /* Check if we need to join whitespaces and breaks. */ + + if (leading_blanks || whitespaces.start != whitespaces.pointer) + { + if (leading_blanks) + { + /* Do we need to fold line breaks? */ + + if (leading_break.start[0] == '\n') { + if (trailing_breaks.start[0] == '\0') { + if (!STRING_EXTEND(parser, string)) goto error; + *(string.pointer++) = ' '; + } + else { + if (!JOIN(parser, string, trailing_breaks)) goto error; + CLEAR(parser, trailing_breaks); + } + CLEAR(parser, leading_break); + } + else { + if (!JOIN(parser, string, leading_break)) goto error; + if (!JOIN(parser, string, trailing_breaks)) goto error; + CLEAR(parser, leading_break); + CLEAR(parser, trailing_breaks); + } + + leading_blanks = 0; + } + else + { + if (!JOIN(parser, string, whitespaces)) goto error; + CLEAR(parser, whitespaces); + } + } + + /* Copy the character. */ + + if (!READ(parser, string)) goto error; + + end_mark = parser->mark; + + if (!CACHE(parser, 2)) goto error; + } + + /* Is it the end? */ + + if (!(IS_BLANK(parser->buffer) || IS_BREAK(parser->buffer))) + break; + + /* Consume blank characters. */ + + if (!CACHE(parser, 1)) goto error; + + while (IS_BLANK(parser->buffer) || IS_BREAK(parser->buffer)) + { + if (IS_BLANK(parser->buffer)) + { + /* Check for tab character that abuse intendation. */ + + if (leading_blanks && (int)parser->mark.column < indent + && IS_TAB(parser->buffer)) { + yaml_parser_set_scanner_error(parser, "while scanning a plain scalar", + start_mark, "found a tab character that violate intendation"); + goto error; + } + + /* Consume a space or a tab character. */ + + if (!leading_blanks) { + if (!READ(parser, whitespaces)) goto error; + } + else { + SKIP(parser); + } + } + else + { + if (!CACHE(parser, 2)) goto error; + + /* Check if it is a first line break. */ + + if (!leading_blanks) + { + CLEAR(parser, whitespaces); + if (!READ_LINE(parser, leading_break)) goto error; + leading_blanks = 1; + } + else + { + if (!READ_LINE(parser, trailing_breaks)) goto error; + } + } + if (!CACHE(parser, 1)) goto error; + } + + /* Check intendation level. */ + + if (!parser->flow_level && (int)parser->mark.column < indent) + break; + } + + /* Create a token. */ + + SCALAR_TOKEN_INIT(*token, string.start, string.pointer-string.start, + YAML_PLAIN_SCALAR_STYLE, start_mark, end_mark); + + /* Note that we change the 'simple_key_allowed' flag. */ + + if (leading_blanks) { + parser->simple_key_allowed = 1; + } + + STRING_DEL(parser, leading_break); + STRING_DEL(parser, trailing_breaks); + STRING_DEL(parser, whitespaces); + + return 1; + +error: + STRING_DEL(parser, string); + STRING_DEL(parser, leading_break); + STRING_DEL(parser, trailing_breaks); + STRING_DEL(parser, whitespaces); + + return 0; +} + diff --git a/src/writer.c b/src/writer.c new file mode 100644 index 00000000000..b90019f5cb7 --- /dev/null +++ b/src/writer.c @@ -0,0 +1,141 @@ + +#include "yaml_private.h" + +/* + * Declarations. + */ + +static int +yaml_emitter_set_writer_error(yaml_emitter_t *emitter, const char *problem); + +YAML_DECLARE(int) +yaml_emitter_flush(yaml_emitter_t *emitter); + +/* + * Set the writer error and return 0. + */ + +static int +yaml_emitter_set_writer_error(yaml_emitter_t *emitter, const char *problem) +{ + emitter->error = YAML_WRITER_ERROR; + emitter->problem = problem; + + return 0; +} + +/* + * Flush the output buffer. + */ + +YAML_DECLARE(int) +yaml_emitter_flush(yaml_emitter_t *emitter) +{ + int low, high; + + assert(emitter); /* Non-NULL emitter object is expected. */ + assert(emitter->write_handler); /* Write handler must be set. */ + assert(emitter->encoding); /* Output encoding must be set. */ + + emitter->buffer.last = emitter->buffer.pointer; + emitter->buffer.pointer = emitter->buffer.start; + + /* Check if the buffer is empty. */ + + if (emitter->buffer.start == emitter->buffer.last) { + return 1; + } + + /* If the output encoding is UTF-8, we don't need to recode the buffer. */ + + if (emitter->encoding == YAML_UTF8_ENCODING) + { + if (emitter->write_handler(emitter->write_handler_data, + emitter->buffer.start, + emitter->buffer.last - emitter->buffer.start)) { + emitter->buffer.last = emitter->buffer.start; + emitter->buffer.pointer = emitter->buffer.start; + return 1; + } + else { + return yaml_emitter_set_writer_error(emitter, "write error"); + } + } + + /* Recode the buffer into the raw buffer. */ + + low = (emitter->encoding == YAML_UTF16LE_ENCODING ? 0 : 1); + high = (emitter->encoding == YAML_UTF16LE_ENCODING ? 1 : 0); + + while (emitter->buffer.pointer != emitter->buffer.last) + { + unsigned char octet; + unsigned int width; + unsigned int value; + size_t k; + + /* + * See the "reader.c" code for more details on UTF-8 encoding. Note + * that we assume that the buffer contains a valid UTF-8 sequence. + */ + + /* Read the next UTF-8 character. */ + + octet = emitter->buffer.pointer[0]; + + width = (octet & 0x80) == 0x00 ? 1 : + (octet & 0xE0) == 0xC0 ? 2 : + (octet & 0xF0) == 0xE0 ? 3 : + (octet & 0xF8) == 0xF0 ? 4 : 0; + + value = (octet & 0x80) == 0x00 ? octet & 0x7F : + (octet & 0xE0) == 0xC0 ? octet & 0x1F : + (octet & 0xF0) == 0xE0 ? octet & 0x0F : + (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0; + + for (k = 1; k < width; k ++) { + octet = emitter->buffer.pointer[k]; + value = (value << 6) + (octet & 0x3F); + } + + emitter->buffer.pointer += width; + + /* Write the character. */ + + if (value < 0x10000) + { + emitter->raw_buffer.last[high] = value >> 8; + emitter->raw_buffer.last[low] = value & 0xFF; + + emitter->raw_buffer.last += 2; + } + else + { + /* Write the character using a surrogate pair (check "reader.c"). */ + + value -= 0x10000; + emitter->raw_buffer.last[high] = 0xD8 + (value >> 18); + emitter->raw_buffer.last[low] = (value >> 10) & 0xFF; + emitter->raw_buffer.last[high+2] = 0xDC + ((value >> 8) & 0xFF); + emitter->raw_buffer.last[low+2] = value & 0xFF; + + emitter->raw_buffer.last += 4; + } + } + + /* Write the raw buffer. */ + + if (emitter->write_handler(emitter->write_handler_data, + emitter->raw_buffer.start, + emitter->raw_buffer.last - emitter->raw_buffer.start)) { + emitter->buffer.last = emitter->buffer.start; + emitter->buffer.pointer = emitter->buffer.start; + emitter->raw_buffer.last = emitter->raw_buffer.start; + emitter->raw_buffer.pointer = emitter->raw_buffer.start; + return 1; + } + else { + return yaml_emitter_set_writer_error(emitter, "write error"); + } +} + diff --git a/src/yaml_private.h b/src/yaml_private.h new file mode 100644 index 00000000000..ed5ea66cc3f --- /dev/null +++ b/src/yaml_private.h @@ -0,0 +1,640 @@ + +#if HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include + +/* + * Memory management. + */ + +YAML_DECLARE(void *) +yaml_malloc(size_t size); + +YAML_DECLARE(void *) +yaml_realloc(void *ptr, size_t size); + +YAML_DECLARE(void) +yaml_free(void *ptr); + +YAML_DECLARE(yaml_char_t *) +yaml_strdup(const yaml_char_t *); + +/* + * Reader: Ensure that the buffer contains at least `length` characters. + */ + +YAML_DECLARE(int) +yaml_parser_update_buffer(yaml_parser_t *parser, size_t length); + +/* + * Scanner: Ensure that the token stack contains at least one token ready. + */ + +YAML_DECLARE(int) +yaml_parser_fetch_more_tokens(yaml_parser_t *parser); + +/* + * The size of the input raw buffer. + */ + +#define INPUT_RAW_BUFFER_SIZE 16384 + +/* + * The size of the input buffer. + * + * It should be possible to decode the whole raw buffer. + */ + +#define INPUT_BUFFER_SIZE (INPUT_RAW_BUFFER_SIZE*3) + +/* + * The size of the output buffer. + */ + +#define OUTPUT_BUFFER_SIZE 16384 + +/* + * The size of the output raw buffer. + * + * It should be possible to encode the whole output buffer. + */ + +#define OUTPUT_RAW_BUFFER_SIZE (OUTPUT_BUFFER_SIZE*2+2) + +/* + * The size of other stacks and queues. + */ + +#define INITIAL_STACK_SIZE 16 +#define INITIAL_QUEUE_SIZE 16 +#define INITIAL_STRING_SIZE 16 + +/* + * Buffer management. + */ + +#define BUFFER_INIT(context,buffer,size) \ + (((buffer).start = yaml_malloc(size)) ? \ + ((buffer).last = (buffer).pointer = (buffer).start, \ + (buffer).end = (buffer).start+(size), \ + 1) : \ + ((context)->error = YAML_MEMORY_ERROR, \ + 0)) + +#define BUFFER_DEL(context,buffer) \ + (yaml_free((buffer).start), \ + (buffer).start = (buffer).pointer = (buffer).end = 0) + +/* + * String management. + */ + +typedef struct { + yaml_char_t *start; + yaml_char_t *end; + yaml_char_t *pointer; +} yaml_string_t; + +YAML_DECLARE(int) +yaml_string_extend(yaml_char_t **start, + yaml_char_t **pointer, yaml_char_t **end); + +YAML_DECLARE(int) +yaml_string_join( + yaml_char_t **a_start, yaml_char_t **a_pointer, yaml_char_t **a_end, + yaml_char_t **b_start, yaml_char_t **b_pointer, yaml_char_t **b_end); + +#define NULL_STRING { NULL, NULL, NULL } + +#define STRING(string,length) { (string), (string)+(length), (string) } + +#define STRING_ASSIGN(value,string,length) \ + ((value).start = (string), \ + (value).end = (string)+(length), \ + (value).pointer = (string)) + +#define STRING_INIT(context,string,size) \ + (((string).start = yaml_malloc(size)) ? \ + ((string).pointer = (string).start, \ + (string).end = (string).start+(size), \ + memset((string).start, 0, (size)), \ + 1) : \ + ((context)->error = YAML_MEMORY_ERROR, \ + 0)) + +#define STRING_DEL(context,string) \ + (yaml_free((string).start), \ + (string).start = (string).pointer = (string).end = 0) + +#define STRING_EXTEND(context,string) \ + (((string).pointer+5 < (string).end) \ + || yaml_string_extend(&(string).start, \ + &(string).pointer, &(string).end)) + +#define CLEAR(context,string) \ + ((string).pointer = (string).start, \ + memset((string).start, 0, (string).end-(string).start)) + +#define JOIN(context,string_a,string_b) \ + ((yaml_string_join(&(string_a).start, &(string_a).pointer, \ + &(string_a).end, &(string_b).start, \ + &(string_b).pointer, &(string_b).end)) ? \ + ((string_b).pointer = (string_b).start, \ + 1) : \ + ((context)->error = YAML_MEMORY_ERROR, \ + 0)) + +/* + * String check operations. + */ + +/* + * Check the octet at the specified position. + */ + +#define CHECK_AT(string,octet,offset) \ + ((string).pointer[offset] == (yaml_char_t)(octet)) + +/* + * Check the current octet in the buffer. + */ + +#define CHECK(string,octet) CHECK_AT((string),(octet),0) + +/* + * Check if the character at the specified position is an alphabetical + * character, a digit, '_', or '-'. + */ + +#define IS_ALPHA_AT(string,offset) \ + (((string).pointer[offset] >= (yaml_char_t) '0' && \ + (string).pointer[offset] <= (yaml_char_t) '9') || \ + ((string).pointer[offset] >= (yaml_char_t) 'A' && \ + (string).pointer[offset] <= (yaml_char_t) 'Z') || \ + ((string).pointer[offset] >= (yaml_char_t) 'a' && \ + (string).pointer[offset] <= (yaml_char_t) 'z') || \ + (string).pointer[offset] == '_' || \ + (string).pointer[offset] == '-') + +#define IS_ALPHA(string) IS_ALPHA_AT((string),0) + +/* + * Check if the character at the specified position is a digit. + */ + +#define IS_DIGIT_AT(string,offset) \ + (((string).pointer[offset] >= (yaml_char_t) '0' && \ + (string).pointer[offset] <= (yaml_char_t) '9')) + +#define IS_DIGIT(string) IS_DIGIT_AT((string),0) + +/* + * Get the value of a digit. + */ + +#define AS_DIGIT_AT(string,offset) \ + ((string).pointer[offset] - (yaml_char_t) '0') + +#define AS_DIGIT(string) AS_DIGIT_AT((string),0) + +/* + * Check if the character at the specified position is a hex-digit. + */ + +#define IS_HEX_AT(string,offset) \ + (((string).pointer[offset] >= (yaml_char_t) '0' && \ + (string).pointer[offset] <= (yaml_char_t) '9') || \ + ((string).pointer[offset] >= (yaml_char_t) 'A' && \ + (string).pointer[offset] <= (yaml_char_t) 'F') || \ + ((string).pointer[offset] >= (yaml_char_t) 'a' && \ + (string).pointer[offset] <= (yaml_char_t) 'f')) + +#define IS_HEX(string) IS_HEX_AT((string),0) + +/* + * Get the value of a hex-digit. + */ + +#define AS_HEX_AT(string,offset) \ + (((string).pointer[offset] >= (yaml_char_t) 'A' && \ + (string).pointer[offset] <= (yaml_char_t) 'F') ? \ + ((string).pointer[offset] - (yaml_char_t) 'A' + 10) : \ + ((string).pointer[offset] >= (yaml_char_t) 'a' && \ + (string).pointer[offset] <= (yaml_char_t) 'f') ? \ + ((string).pointer[offset] - (yaml_char_t) 'a' + 10) : \ + ((string).pointer[offset] - (yaml_char_t) '0')) + +#define AS_HEX(string) AS_HEX_AT((string),0) + +/* + * Check if the character is ASCII. + */ + +#define IS_ASCII_AT(string,offset) \ + ((string).pointer[offset] <= (yaml_char_t) '\x7F') + +#define IS_ASCII(string) IS_ASCII_AT((string),0) + +/* + * Check if the character can be printed unescaped. + */ + +#define IS_PRINTABLE_AT(string,offset) \ + (((string).pointer[offset] == 0x0A) /* . == #x0A */ \ + || ((string).pointer[offset] >= 0x20 /* #x20 <= . <= #x7E */ \ + && (string).pointer[offset] <= 0x7E) \ + || ((string).pointer[offset] == 0xC2 /* #0xA0 <= . <= #xD7FF */ \ + && (string).pointer[offset+1] >= 0xA0) \ + || ((string).pointer[offset] > 0xC2 \ + && (string).pointer[offset] < 0xED) \ + || ((string).pointer[offset] == 0xED \ + && (string).pointer[offset+1] < 0xA0) \ + || ((string).pointer[offset] == 0xEE) \ + || ((string).pointer[offset] == 0xEF /* #xE000 <= . <= #xFFFD */ \ + && !((string).pointer[offset+1] == 0xBB /* && . != #xFEFF */ \ + && (string).pointer[offset+2] == 0xBF) \ + && !((string).pointer[offset+1] == 0xBF \ + && ((string).pointer[offset+2] == 0xBE \ + || (string).pointer[offset+2] == 0xBF)))) + +#define IS_PRINTABLE(string) IS_PRINTABLE_AT((string),0) + +/* + * Check if the character at the specified position is NUL. + */ + +#define IS_Z_AT(string,offset) CHECK_AT((string),'\0',(offset)) + +#define IS_Z(string) IS_Z_AT((string),0) + +/* + * Check if the character at the specified position is BOM. + */ + +#define IS_BOM_AT(string,offset) \ + (CHECK_AT((string),'\xEF',(offset)) \ + && CHECK_AT((string),'\xBB',(offset)+1) \ + && CHECK_AT((string),'\xBF',(offset)+2)) /* BOM (#xFEFF) */ + +#define IS_BOM(string) IS_BOM_AT(string,0) + +/* + * Check if the character at the specified position is space. + */ + +#define IS_SPACE_AT(string,offset) CHECK_AT((string),' ',(offset)) + +#define IS_SPACE(string) IS_SPACE_AT((string),0) + +/* + * Check if the character at the specified position is tab. + */ + +#define IS_TAB_AT(string,offset) CHECK_AT((string),'\t',(offset)) + +#define IS_TAB(string) IS_TAB_AT((string),0) + +/* + * Check if the character at the specified position is blank (space or tab). + */ + +#define IS_BLANK_AT(string,offset) \ + (IS_SPACE_AT((string),(offset)) || IS_TAB_AT((string),(offset))) + +#define IS_BLANK(string) IS_BLANK_AT((string),0) + +/* + * Check if the character at the specified position is a line break. + */ + +#define IS_BREAK_AT(string,offset) \ + (CHECK_AT((string),'\r',(offset)) /* CR (#xD)*/ \ + || CHECK_AT((string),'\n',(offset)) /* LF (#xA) */ \ + || (CHECK_AT((string),'\xC2',(offset)) \ + && CHECK_AT((string),'\x85',(offset)+1)) /* NEL (#x85) */ \ + || (CHECK_AT((string),'\xE2',(offset)) \ + && CHECK_AT((string),'\x80',(offset)+1) \ + && CHECK_AT((string),'\xA8',(offset)+2)) /* LS (#x2028) */ \ + || (CHECK_AT((string),'\xE2',(offset)) \ + && CHECK_AT((string),'\x80',(offset)+1) \ + && CHECK_AT((string),'\xA9',(offset)+2))) /* PS (#x2029) */ + +#define IS_BREAK(string) IS_BREAK_AT((string),0) + +#define IS_CRLF_AT(string,offset) \ + (CHECK_AT((string),'\r',(offset)) && CHECK_AT((string),'\n',(offset)+1)) + +#define IS_CRLF(string) IS_CRLF_AT((string),0) + +/* + * Check if the character is a line break or NUL. + */ + +#define IS_BREAKZ_AT(string,offset) \ + (IS_BREAK_AT((string),(offset)) || IS_Z_AT((string),(offset))) + +#define IS_BREAKZ(string) IS_BREAKZ_AT((string),0) + +/* + * Check if the character is a line break, space, or NUL. + */ + +#define IS_SPACEZ_AT(string,offset) \ + (IS_SPACE_AT((string),(offset)) || IS_BREAKZ_AT((string),(offset))) + +#define IS_SPACEZ(string) IS_SPACEZ_AT((string),0) + +/* + * Check if the character is a line break, space, tab, or NUL. + */ + +#define IS_BLANKZ_AT(string,offset) \ + (IS_BLANK_AT((string),(offset)) || IS_BREAKZ_AT((string),(offset))) + +#define IS_BLANKZ(string) IS_BLANKZ_AT((string),0) + +/* + * Determine the width of the character. + */ + +#define WIDTH_AT(string,offset) \ + (((string).pointer[offset] & 0x80) == 0x00 ? 1 : \ + ((string).pointer[offset] & 0xE0) == 0xC0 ? 2 : \ + ((string).pointer[offset] & 0xF0) == 0xE0 ? 3 : \ + ((string).pointer[offset] & 0xF8) == 0xF0 ? 4 : 0) + +#define WIDTH(string) WIDTH_AT((string),0) + +/* + * Move the string pointer to the next character. + */ + +#define MOVE(string) ((string).pointer += WIDTH((string))) + +/* + * Copy a character and move the pointers of both strings. + */ + +#define COPY(string_a,string_b) \ + ((*(string_b).pointer & 0x80) == 0x00 ? \ + (*((string_a).pointer++) = *((string_b).pointer++)) : \ + (*(string_b).pointer & 0xE0) == 0xC0 ? \ + (*((string_a).pointer++) = *((string_b).pointer++), \ + *((string_a).pointer++) = *((string_b).pointer++)) : \ + (*(string_b).pointer & 0xF0) == 0xE0 ? \ + (*((string_a).pointer++) = *((string_b).pointer++), \ + *((string_a).pointer++) = *((string_b).pointer++), \ + *((string_a).pointer++) = *((string_b).pointer++)) : \ + (*(string_b).pointer & 0xF8) == 0xF0 ? \ + (*((string_a).pointer++) = *((string_b).pointer++), \ + *((string_a).pointer++) = *((string_b).pointer++), \ + *((string_a).pointer++) = *((string_b).pointer++), \ + *((string_a).pointer++) = *((string_b).pointer++)) : 0) + +/* + * Stack and queue management. + */ + +YAML_DECLARE(int) +yaml_stack_extend(void **start, void **top, void **end); + +YAML_DECLARE(int) +yaml_queue_extend(void **start, void **head, void **tail, void **end); + +#define STACK_INIT(context,stack,size) \ + (((stack).start = yaml_malloc((size)*sizeof(*(stack).start))) ? \ + ((stack).top = (stack).start, \ + (stack).end = (stack).start+(size), \ + 1) : \ + ((context)->error = YAML_MEMORY_ERROR, \ + 0)) + +#define STACK_DEL(context,stack) \ + (yaml_free((stack).start), \ + (stack).start = (stack).top = (stack).end = 0) + +#define STACK_EMPTY(context,stack) \ + ((stack).start == (stack).top) + +#define PUSH(context,stack,value) \ + (((stack).top != (stack).end \ + || yaml_stack_extend((void **)&(stack).start, \ + (void **)&(stack).top, (void **)&(stack).end)) ? \ + (*((stack).top++) = value, \ + 1) : \ + ((context)->error = YAML_MEMORY_ERROR, \ + 0)) + +#define POP(context,stack) \ + (*(--(stack).top)) + +#define QUEUE_INIT(context,queue,size) \ + (((queue).start = yaml_malloc((size)*sizeof(*(queue).start))) ? \ + ((queue).head = (queue).tail = (queue).start, \ + (queue).end = (queue).start+(size), \ + 1) : \ + ((context)->error = YAML_MEMORY_ERROR, \ + 0)) + +#define QUEUE_DEL(context,queue) \ + (yaml_free((queue).start), \ + (queue).start = (queue).head = (queue).tail = (queue).end = 0) + +#define QUEUE_EMPTY(context,queue) \ + ((queue).head == (queue).tail) + +#define ENQUEUE(context,queue,value) \ + (((queue).tail != (queue).end \ + || yaml_queue_extend((void **)&(queue).start, (void **)&(queue).head, \ + (void **)&(queue).tail, (void **)&(queue).end)) ? \ + (*((queue).tail++) = value, \ + 1) : \ + ((context)->error = YAML_MEMORY_ERROR, \ + 0)) + +#define DEQUEUE(context,queue) \ + (*((queue).head++)) + +#define QUEUE_INSERT(context,queue,index,value) \ + (((queue).tail != (queue).end \ + || yaml_queue_extend((void **)&(queue).start, (void **)&(queue).head, \ + (void **)&(queue).tail, (void **)&(queue).end)) ? \ + (memmove((queue).head+(index)+1,(queue).head+(index), \ + ((queue).tail-(queue).head-(index))*sizeof(*(queue).start)), \ + *((queue).head+(index)) = value, \ + (queue).tail++, \ + 1) : \ + ((context)->error = YAML_MEMORY_ERROR, \ + 0)) + +/* + * Token initializers. + */ + +#define TOKEN_INIT(token,token_type,token_start_mark,token_end_mark) \ + (memset(&(token), 0, sizeof(yaml_token_t)), \ + (token).type = (token_type), \ + (token).start_mark = (token_start_mark), \ + (token).end_mark = (token_end_mark)) + +#define STREAM_START_TOKEN_INIT(token,token_encoding,start_mark,end_mark) \ + (TOKEN_INIT((token),YAML_STREAM_START_TOKEN,(start_mark),(end_mark)), \ + (token).data.stream_start.encoding = (token_encoding)) + +#define STREAM_END_TOKEN_INIT(token,start_mark,end_mark) \ + (TOKEN_INIT((token),YAML_STREAM_END_TOKEN,(start_mark),(end_mark))) + +#define ALIAS_TOKEN_INIT(token,token_value,start_mark,end_mark) \ + (TOKEN_INIT((token),YAML_ALIAS_TOKEN,(start_mark),(end_mark)), \ + (token).data.alias.value = (token_value)) + +#define ANCHOR_TOKEN_INIT(token,token_value,start_mark,end_mark) \ + (TOKEN_INIT((token),YAML_ANCHOR_TOKEN,(start_mark),(end_mark)), \ + (token).data.anchor.value = (token_value)) + +#define TAG_TOKEN_INIT(token,token_handle,token_suffix,start_mark,end_mark) \ + (TOKEN_INIT((token),YAML_TAG_TOKEN,(start_mark),(end_mark)), \ + (token).data.tag.handle = (token_handle), \ + (token).data.tag.suffix = (token_suffix)) + +#define SCALAR_TOKEN_INIT(token,token_value,token_length,token_style,start_mark,end_mark) \ + (TOKEN_INIT((token),YAML_SCALAR_TOKEN,(start_mark),(end_mark)), \ + (token).data.scalar.value = (token_value), \ + (token).data.scalar.length = (token_length), \ + (token).data.scalar.style = (token_style)) + +#define VERSION_DIRECTIVE_TOKEN_INIT(token,token_major,token_minor,start_mark,end_mark) \ + (TOKEN_INIT((token),YAML_VERSION_DIRECTIVE_TOKEN,(start_mark),(end_mark)), \ + (token).data.version_directive.major = (token_major), \ + (token).data.version_directive.minor = (token_minor)) + +#define TAG_DIRECTIVE_TOKEN_INIT(token,token_handle,token_prefix,start_mark,end_mark) \ + (TOKEN_INIT((token),YAML_TAG_DIRECTIVE_TOKEN,(start_mark),(end_mark)), \ + (token).data.tag_directive.handle = (token_handle), \ + (token).data.tag_directive.prefix = (token_prefix)) + +/* + * Event initializers. + */ + +#define EVENT_INIT(event,event_type,event_start_mark,event_end_mark) \ + (memset(&(event), 0, sizeof(yaml_event_t)), \ + (event).type = (event_type), \ + (event).start_mark = (event_start_mark), \ + (event).end_mark = (event_end_mark)) + +#define STREAM_START_EVENT_INIT(event,event_encoding,start_mark,end_mark) \ + (EVENT_INIT((event),YAML_STREAM_START_EVENT,(start_mark),(end_mark)), \ + (event).data.stream_start.encoding = (event_encoding)) + +#define STREAM_END_EVENT_INIT(event,start_mark,end_mark) \ + (EVENT_INIT((event),YAML_STREAM_END_EVENT,(start_mark),(end_mark))) + +#define DOCUMENT_START_EVENT_INIT(event,event_version_directive, \ + event_tag_directives_start,event_tag_directives_end,event_implicit,start_mark,end_mark) \ + (EVENT_INIT((event),YAML_DOCUMENT_START_EVENT,(start_mark),(end_mark)), \ + (event).data.document_start.version_directive = (event_version_directive), \ + (event).data.document_start.tag_directives.start = (event_tag_directives_start), \ + (event).data.document_start.tag_directives.end = (event_tag_directives_end), \ + (event).data.document_start.implicit = (event_implicit)) + +#define DOCUMENT_END_EVENT_INIT(event,event_implicit,start_mark,end_mark) \ + (EVENT_INIT((event),YAML_DOCUMENT_END_EVENT,(start_mark),(end_mark)), \ + (event).data.document_end.implicit = (event_implicit)) + +#define ALIAS_EVENT_INIT(event,event_anchor,start_mark,end_mark) \ + (EVENT_INIT((event),YAML_ALIAS_EVENT,(start_mark),(end_mark)), \ + (event).data.alias.anchor = (event_anchor)) + +#define SCALAR_EVENT_INIT(event,event_anchor,event_tag,event_value,event_length, \ + event_plain_implicit, event_quoted_implicit,event_style,start_mark,end_mark) \ + (EVENT_INIT((event),YAML_SCALAR_EVENT,(start_mark),(end_mark)), \ + (event).data.scalar.anchor = (event_anchor), \ + (event).data.scalar.tag = (event_tag), \ + (event).data.scalar.value = (event_value), \ + (event).data.scalar.length = (event_length), \ + (event).data.scalar.plain_implicit = (event_plain_implicit), \ + (event).data.scalar.quoted_implicit = (event_quoted_implicit), \ + (event).data.scalar.style = (event_style)) + +#define SEQUENCE_START_EVENT_INIT(event,event_anchor,event_tag, \ + event_implicit,event_style,start_mark,end_mark) \ + (EVENT_INIT((event),YAML_SEQUENCE_START_EVENT,(start_mark),(end_mark)), \ + (event).data.sequence_start.anchor = (event_anchor), \ + (event).data.sequence_start.tag = (event_tag), \ + (event).data.sequence_start.implicit = (event_implicit), \ + (event).data.sequence_start.style = (event_style)) + +#define SEQUENCE_END_EVENT_INIT(event,start_mark,end_mark) \ + (EVENT_INIT((event),YAML_SEQUENCE_END_EVENT,(start_mark),(end_mark))) + +#define MAPPING_START_EVENT_INIT(event,event_anchor,event_tag, \ + event_implicit,event_style,start_mark,end_mark) \ + (EVENT_INIT((event),YAML_MAPPING_START_EVENT,(start_mark),(end_mark)), \ + (event).data.mapping_start.anchor = (event_anchor), \ + (event).data.mapping_start.tag = (event_tag), \ + (event).data.mapping_start.implicit = (event_implicit), \ + (event).data.mapping_start.style = (event_style)) + +#define MAPPING_END_EVENT_INIT(event,start_mark,end_mark) \ + (EVENT_INIT((event),YAML_MAPPING_END_EVENT,(start_mark),(end_mark))) + +/* + * Document initializer. + */ + +#define DOCUMENT_INIT(document,document_nodes_start,document_nodes_end, \ + document_version_directive,document_tag_directives_start, \ + document_tag_directives_end,document_start_implicit, \ + document_end_implicit,document_start_mark,document_end_mark) \ + (memset(&(document), 0, sizeof(yaml_document_t)), \ + (document).nodes.start = (document_nodes_start), \ + (document).nodes.end = (document_nodes_end), \ + (document).nodes.top = (document_nodes_start), \ + (document).version_directive = (document_version_directive), \ + (document).tag_directives.start = (document_tag_directives_start), \ + (document).tag_directives.end = (document_tag_directives_end), \ + (document).start_implicit = (document_start_implicit), \ + (document).end_implicit = (document_end_implicit), \ + (document).start_mark = (document_start_mark), \ + (document).end_mark = (document_end_mark)) + +/* + * Node initializers. + */ + +#define NODE_INIT(node,node_type,node_tag,node_start_mark,node_end_mark) \ + (memset(&(node), 0, sizeof(yaml_node_t)), \ + (node).type = (node_type), \ + (node).tag = (node_tag), \ + (node).start_mark = (node_start_mark), \ + (node).end_mark = (node_end_mark)) + +#define SCALAR_NODE_INIT(node,node_tag,node_value,node_length, \ + node_style,start_mark,end_mark) \ + (NODE_INIT((node),YAML_SCALAR_NODE,(node_tag),(start_mark),(end_mark)), \ + (node).data.scalar.value = (node_value), \ + (node).data.scalar.length = (node_length), \ + (node).data.scalar.style = (node_style)) + +#define SEQUENCE_NODE_INIT(node,node_tag,node_items_start,node_items_end, \ + node_style,start_mark,end_mark) \ + (NODE_INIT((node),YAML_SEQUENCE_NODE,(node_tag),(start_mark),(end_mark)), \ + (node).data.sequence.items.start = (node_items_start), \ + (node).data.sequence.items.end = (node_items_end), \ + (node).data.sequence.items.top = (node_items_start), \ + (node).data.sequence.style = (node_style)) + +#define MAPPING_NODE_INIT(node,node_tag,node_pairs_start,node_pairs_end, \ + node_style,start_mark,end_mark) \ + (NODE_INIT((node),YAML_MAPPING_NODE,(node_tag),(start_mark),(end_mark)), \ + (node).data.mapping.pairs.start = (node_pairs_start), \ + (node).data.mapping.pairs.end = (node_pairs_end), \ + (node).data.mapping.pairs.top = (node_pairs_start), \ + (node).data.mapping.style = (node_style)) + diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 00000000000..72e84d2a221 --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,8 @@ +AM_CPPFLAGS = -I$(top_srcdir)/include +#AM_CFLAGS = -Wno-pointer-sign +LDADD = $(top_builddir)/src/libyaml.la +TESTS = test-version test-reader +check_PROGRAMS = test-version test-reader +noinst_PROGRAMS = run-scanner run-parser run-loader run-emitter run-dumper \ + example-reformatter example-reformatter-alt \ + example-deconstructor example-deconstructor-alt diff --git a/tests/Makefile.in b/tests/Makefile.in new file mode 100644 index 00000000000..2939d9fd2b6 --- /dev/null +++ b/tests/Makefile.in @@ -0,0 +1,672 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +TESTS = test-version$(EXEEXT) test-reader$(EXEEXT) +check_PROGRAMS = test-version$(EXEEXT) test-reader$(EXEEXT) +noinst_PROGRAMS = run-scanner$(EXEEXT) run-parser$(EXEEXT) \ + run-loader$(EXEEXT) run-emitter$(EXEEXT) run-dumper$(EXEEXT) \ + example-reformatter$(EXEEXT) example-reformatter-alt$(EXEEXT) \ + example-deconstructor$(EXEEXT) \ + example-deconstructor-alt$(EXEEXT) +subdir = tests +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +PROGRAMS = $(noinst_PROGRAMS) +example_deconstructor_SOURCES = example-deconstructor.c +example_deconstructor_OBJECTS = example-deconstructor.$(OBJEXT) +example_deconstructor_LDADD = $(LDADD) +example_deconstructor_DEPENDENCIES = $(top_builddir)/src/libyaml.la +example_deconstructor_alt_SOURCES = example-deconstructor-alt.c +example_deconstructor_alt_OBJECTS = \ + example-deconstructor-alt.$(OBJEXT) +example_deconstructor_alt_LDADD = $(LDADD) +example_deconstructor_alt_DEPENDENCIES = \ + $(top_builddir)/src/libyaml.la +example_reformatter_SOURCES = example-reformatter.c +example_reformatter_OBJECTS = example-reformatter.$(OBJEXT) +example_reformatter_LDADD = $(LDADD) +example_reformatter_DEPENDENCIES = $(top_builddir)/src/libyaml.la +example_reformatter_alt_SOURCES = example-reformatter-alt.c +example_reformatter_alt_OBJECTS = example-reformatter-alt.$(OBJEXT) +example_reformatter_alt_LDADD = $(LDADD) +example_reformatter_alt_DEPENDENCIES = $(top_builddir)/src/libyaml.la +run_dumper_SOURCES = run-dumper.c +run_dumper_OBJECTS = run-dumper.$(OBJEXT) +run_dumper_LDADD = $(LDADD) +run_dumper_DEPENDENCIES = $(top_builddir)/src/libyaml.la +run_emitter_SOURCES = run-emitter.c +run_emitter_OBJECTS = run-emitter.$(OBJEXT) +run_emitter_LDADD = $(LDADD) +run_emitter_DEPENDENCIES = $(top_builddir)/src/libyaml.la +run_loader_SOURCES = run-loader.c +run_loader_OBJECTS = run-loader.$(OBJEXT) +run_loader_LDADD = $(LDADD) +run_loader_DEPENDENCIES = $(top_builddir)/src/libyaml.la +run_parser_SOURCES = run-parser.c +run_parser_OBJECTS = run-parser.$(OBJEXT) +run_parser_LDADD = $(LDADD) +run_parser_DEPENDENCIES = $(top_builddir)/src/libyaml.la +run_scanner_SOURCES = run-scanner.c +run_scanner_OBJECTS = run-scanner.$(OBJEXT) +run_scanner_LDADD = $(LDADD) +run_scanner_DEPENDENCIES = $(top_builddir)/src/libyaml.la +test_reader_SOURCES = test-reader.c +test_reader_OBJECTS = test-reader.$(OBJEXT) +test_reader_LDADD = $(LDADD) +test_reader_DEPENDENCIES = $(top_builddir)/src/libyaml.la +test_version_SOURCES = test-version.c +test_version_OBJECTS = test-version.$(OBJEXT) +test_version_LDADD = $(LDADD) +test_version_DEPENDENCIES = $(top_builddir)/src/libyaml.la +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/config/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = example-deconstructor.c example-deconstructor-alt.c \ + example-reformatter.c example-reformatter-alt.c run-dumper.c \ + run-emitter.c run-loader.c run-parser.c run-scanner.c \ + test-reader.c test-version.c +DIST_SOURCES = example-deconstructor.c example-deconstructor-alt.c \ + example-reformatter.c example-reformatter-alt.c run-dumper.c \ + run-emitter.c run-loader.c run-parser.c run-scanner.c \ + test-reader.c test-version.c +ETAGS = etags +CTAGS = ctags +am__tty_colors = \ +red=; grn=; lgn=; blu=; std= +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YAML_LT_AGE = @YAML_LT_AGE@ +YAML_LT_CURRENT = @YAML_LT_CURRENT@ +YAML_LT_RELEASE = @YAML_LT_RELEASE@ +YAML_LT_REVISION = @YAML_LT_REVISION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_CPPFLAGS = -I$(top_srcdir)/include +#AM_CFLAGS = -Wno-pointer-sign +LDADD = $(top_builddir)/src/libyaml.la +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign tests/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +example-deconstructor$(EXEEXT): $(example_deconstructor_OBJECTS) $(example_deconstructor_DEPENDENCIES) + @rm -f example-deconstructor$(EXEEXT) + $(LINK) $(example_deconstructor_OBJECTS) $(example_deconstructor_LDADD) $(LIBS) +example-deconstructor-alt$(EXEEXT): $(example_deconstructor_alt_OBJECTS) $(example_deconstructor_alt_DEPENDENCIES) + @rm -f example-deconstructor-alt$(EXEEXT) + $(LINK) $(example_deconstructor_alt_OBJECTS) $(example_deconstructor_alt_LDADD) $(LIBS) +example-reformatter$(EXEEXT): $(example_reformatter_OBJECTS) $(example_reformatter_DEPENDENCIES) + @rm -f example-reformatter$(EXEEXT) + $(LINK) $(example_reformatter_OBJECTS) $(example_reformatter_LDADD) $(LIBS) +example-reformatter-alt$(EXEEXT): $(example_reformatter_alt_OBJECTS) $(example_reformatter_alt_DEPENDENCIES) + @rm -f example-reformatter-alt$(EXEEXT) + $(LINK) $(example_reformatter_alt_OBJECTS) $(example_reformatter_alt_LDADD) $(LIBS) +run-dumper$(EXEEXT): $(run_dumper_OBJECTS) $(run_dumper_DEPENDENCIES) + @rm -f run-dumper$(EXEEXT) + $(LINK) $(run_dumper_OBJECTS) $(run_dumper_LDADD) $(LIBS) +run-emitter$(EXEEXT): $(run_emitter_OBJECTS) $(run_emitter_DEPENDENCIES) + @rm -f run-emitter$(EXEEXT) + $(LINK) $(run_emitter_OBJECTS) $(run_emitter_LDADD) $(LIBS) +run-loader$(EXEEXT): $(run_loader_OBJECTS) $(run_loader_DEPENDENCIES) + @rm -f run-loader$(EXEEXT) + $(LINK) $(run_loader_OBJECTS) $(run_loader_LDADD) $(LIBS) +run-parser$(EXEEXT): $(run_parser_OBJECTS) $(run_parser_DEPENDENCIES) + @rm -f run-parser$(EXEEXT) + $(LINK) $(run_parser_OBJECTS) $(run_parser_LDADD) $(LIBS) +run-scanner$(EXEEXT): $(run_scanner_OBJECTS) $(run_scanner_DEPENDENCIES) + @rm -f run-scanner$(EXEEXT) + $(LINK) $(run_scanner_OBJECTS) $(run_scanner_LDADD) $(LIBS) +test-reader$(EXEEXT): $(test_reader_OBJECTS) $(test_reader_DEPENDENCIES) + @rm -f test-reader$(EXEEXT) + $(LINK) $(test_reader_OBJECTS) $(test_reader_LDADD) $(LIBS) +test-version$(EXEEXT): $(test_version_OBJECTS) $(test_version_DEPENDENCIES) + @rm -f test-version$(EXEEXT) + $(LINK) $(test_version_OBJECTS) $(test_version_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/example-deconstructor-alt.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/example-deconstructor.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/example-reformatter-alt.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/example-reformatter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-dumper.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-emitter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-loader.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-parser.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-scanner.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-reader.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-version.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +check-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list=' $(TESTS) '; \ + $(am__tty_colors); \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + col=$$red; res=XPASS; \ + ;; \ + *) \ + col=$$grn; res=PASS; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xfail=`expr $$xfail + 1`; \ + col=$$lgn; res=XFAIL; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + col=$$red; res=FAIL; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + col=$$blu; res=SKIP; \ + fi; \ + echo "$${col}$$res$${std}: $$tst"; \ + done; \ + if test "$$all" -eq 1; then \ + tests="test"; \ + All=""; \ + else \ + tests="tests"; \ + All="All "; \ + fi; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="$$All$$all $$tests passed"; \ + else \ + if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ + banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all $$tests failed"; \ + else \ + if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ + banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + if test "$$skip" -eq 1; then \ + skipped="($$skip test was not run)"; \ + else \ + skipped="($$skip tests were not run)"; \ + fi; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + if test "$$failed" -eq 0; then \ + echo "$$grn$$dashes"; \ + else \ + echo "$$red$$dashes"; \ + fi; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes$$std"; \ + test "$$failed" -eq 0; \ + else :; fi + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ + clean-noinstPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \ + clean-checkPROGRAMS clean-generic clean-libtool \ + clean-noinstPROGRAMS ctags distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/tests/example-deconstructor-alt.c b/tests/example-deconstructor-alt.c new file mode 100644 index 00000000000..7da194a659d --- /dev/null +++ b/tests/example-deconstructor-alt.c @@ -0,0 +1,800 @@ + +#include + +#include +#include + +int +main(int argc, char *argv[]) +{ + int help = 0; + int canonical = 0; + int unicode = 0; + int k; + int done = 0; + + yaml_parser_t parser; + yaml_emitter_t emitter; + yaml_event_t input_event; + yaml_document_t output_document; + + int root; + + /* Clear the objects. */ + + memset(&parser, 0, sizeof(parser)); + memset(&emitter, 0, sizeof(emitter)); + memset(&input_event, 0, sizeof(input_event)); + memset(&output_document, 0, sizeof(output_document)); + + /* Analyze command line options. */ + + for (k = 1; k < argc; k ++) + { + if (strcmp(argv[k], "-h") == 0 + || strcmp(argv[k], "--help") == 0) { + help = 1; + } + + else if (strcmp(argv[k], "-c") == 0 + || strcmp(argv[k], "--canonical") == 0) { + canonical = 1; + } + + else if (strcmp(argv[k], "-u") == 0 + || strcmp(argv[k], "--unicode") == 0) { + unicode = 1; + } + + else { + fprintf(stderr, "Unrecognized option: %s\n" + "Try `%s --help` for more information.\n", + argv[k], argv[0]); + return 1; + } + } + + /* Display the help string. */ + + if (help) + { + printf("%s . */ + + if (input_event.data.stream_start.encoding) + { + yaml_encoding_t encoding + = input_event.data.stream_start.encoding; + + key = yaml_document_add_scalar(&output_document, NULL, + "encoding", -1, YAML_PLAIN_SCALAR_STYLE); + if (!key) goto document_error; + value = yaml_document_add_scalar(&output_document, NULL, + (encoding == YAML_UTF8_ENCODING ? "utf-8" : + encoding == YAML_UTF16LE_ENCODING ? "utf-16-le" : + encoding == YAML_UTF16BE_ENCODING ? "utf-16-be" : + "unknown"), -1, YAML_PLAIN_SCALAR_STYLE); + if (!value) goto document_error; + if (!yaml_document_append_mapping_pair(&output_document, + properties, key, value)) goto document_error; + } + + break; + + case YAML_STREAM_END_EVENT: + + /* Add 'type': 'STREAM-END'. */ + + key = yaml_document_add_scalar(&output_document, NULL, + "type", -1, YAML_PLAIN_SCALAR_STYLE); + if (!key) goto document_error; + value = yaml_document_add_scalar(&output_document, NULL, + "STREAM-END", -1, YAML_PLAIN_SCALAR_STYLE); + if (!value) goto document_error; + if (!yaml_document_append_mapping_pair(&output_document, + properties, key, value)) goto document_error; + + break; + + case YAML_DOCUMENT_START_EVENT: + + /* Add 'type': 'DOCUMENT-START'. */ + + key = yaml_document_add_scalar(&output_document, NULL, + "type", -1, YAML_PLAIN_SCALAR_STYLE); + if (!key) goto document_error; + value = yaml_document_add_scalar(&output_document, NULL, + "DOCUMENT-START", -1, YAML_PLAIN_SCALAR_STYLE); + if (!value) goto document_error; + if (!yaml_document_append_mapping_pair(&output_document, + properties, key, value)) goto document_error; + + /* Display the output_document version numbers. */ + + if (input_event.data.document_start.version_directive) + { + yaml_version_directive_t *version + = input_event.data.document_start.version_directive; + char number[64]; + + /* Add 'version': {}. */ + + key = yaml_document_add_scalar(&output_document, NULL, + "version", -1, YAML_PLAIN_SCALAR_STYLE); + if (!key) goto document_error; + map = yaml_document_add_mapping(&output_document, NULL, + YAML_FLOW_MAPPING_STYLE); + if (!map) goto document_error; + if (!yaml_document_append_mapping_pair(&output_document, + properties, key, map)) goto document_error; + + /* Add 'major': . */ + + key = yaml_document_add_scalar(&output_document, NULL, + "major", -1, YAML_PLAIN_SCALAR_STYLE); + if (!key) goto document_error; + sprintf(number, "%d", version->major); + value = yaml_document_add_scalar(&output_document, YAML_INT_TAG, + number, -1, YAML_PLAIN_SCALAR_STYLE); + if (!value) goto document_error; + if (!yaml_document_append_mapping_pair(&output_document, + map, key, value)) goto document_error; + + /* Add 'minor': . */ + + key = yaml_document_add_scalar(&output_document, NULL, + "minor", -1, YAML_PLAIN_SCALAR_STYLE); + if (!key) goto document_error; + sprintf(number, "%d", version->minor); + value = yaml_document_add_scalar(&output_document, YAML_INT_TAG, + number, -1, YAML_PLAIN_SCALAR_STYLE); + if (!value) goto document_error; + if (!yaml_document_append_mapping_pair(&output_document, + map, key, value)) goto document_error; + } + + /* Display the output_document tag directives. */ + + if (input_event.data.document_start.tag_directives.start + != input_event.data.document_start.tag_directives.end) + { + yaml_tag_directive_t *tag; + + /* Add 'tags': []. */ + + key = yaml_document_add_scalar(&output_document, NULL, + "tags", -1, YAML_PLAIN_SCALAR_STYLE); + if (!key) goto document_error; + seq = yaml_document_add_sequence(&output_document, NULL, + YAML_BLOCK_SEQUENCE_STYLE); + if (!seq) goto document_error; + if (!yaml_document_append_mapping_pair(&output_document, + properties, key, seq)) goto document_error; + + for (tag = input_event.data.document_start.tag_directives.start; + tag != input_event.data.document_start.tag_directives.end; + tag ++) + { + /* Add {}. */ + + map = yaml_document_add_mapping(&output_document, NULL, + YAML_FLOW_MAPPING_STYLE); + if (!map) goto document_error; + if (!yaml_document_append_sequence_item(&output_document, + seq, map)) goto document_error; + + /* Add 'handle': . */ + + key = yaml_document_add_scalar(&output_document, NULL, + "handle", -1, YAML_PLAIN_SCALAR_STYLE); + if (!key) goto document_error; + value = yaml_document_add_scalar(&output_document, NULL, + tag->handle, -1, YAML_DOUBLE_QUOTED_SCALAR_STYLE); + if (!value) goto document_error; + if (!yaml_document_append_mapping_pair(&output_document, + map, key, value)) goto document_error; + + /* Add 'prefix': . */ + + key = yaml_document_add_scalar(&output_document, NULL, + "prefix", -1, YAML_PLAIN_SCALAR_STYLE); + if (!key) goto document_error; + value = yaml_document_add_scalar(&output_document, NULL, + tag->prefix, -1, YAML_DOUBLE_QUOTED_SCALAR_STYLE); + if (!value) goto document_error; + if (!yaml_document_append_mapping_pair(&output_document, + map, key, value)) goto document_error; + } + } + + /* Add 'implicit': . */ + + key = yaml_document_add_scalar(&output_document, NULL, + "implicit", -1, YAML_PLAIN_SCALAR_STYLE); + if (!key) goto document_error; + value = yaml_document_add_scalar(&output_document, YAML_BOOL_TAG, + (input_event.data.document_start.implicit ? + "true" : "false"), -1, YAML_PLAIN_SCALAR_STYLE); + if (!value) goto document_error; + if (!yaml_document_append_mapping_pair(&output_document, + properties, key, value)) goto document_error; + + break; + + case YAML_DOCUMENT_END_EVENT: + + /* Add 'type': 'DOCUMENT-END'. */ + + key = yaml_document_add_scalar(&output_document, NULL, + "type", -1, YAML_PLAIN_SCALAR_STYLE); + if (!key) goto document_error; + value = yaml_document_add_scalar(&output_document, NULL, + "DOCUMENT-END", -1, YAML_PLAIN_SCALAR_STYLE); + if (!value) goto document_error; + if (!yaml_document_append_mapping_pair(&output_document, + properties, key, value)) goto document_error; + + /* Add 'implicit': . */ + + key = yaml_document_add_scalar(&output_document, NULL, + "implicit", -1, YAML_PLAIN_SCALAR_STYLE); + if (!key) goto document_error; + value = yaml_document_add_scalar(&output_document, YAML_BOOL_TAG, + (input_event.data.document_end.implicit ? + "true" : "false"), -1, YAML_PLAIN_SCALAR_STYLE); + if (!value) goto document_error; + if (!yaml_document_append_mapping_pair(&output_document, + properties, key, value)) goto document_error; + + break; + + case YAML_ALIAS_EVENT: + + /* Add 'type': 'ALIAS'. */ + + key = yaml_document_add_scalar(&output_document, NULL, + "type", -1, YAML_PLAIN_SCALAR_STYLE); + if (!key) goto document_error; + value = yaml_document_add_scalar(&output_document, NULL, + "ALIAS", -1, YAML_PLAIN_SCALAR_STYLE); + if (!value) goto document_error; + if (!yaml_document_append_mapping_pair(&output_document, + properties, key, value)) goto document_error; + + /* Add 'anchor': . */ + + key = yaml_document_add_scalar(&output_document, NULL, + "anchor", -1, YAML_PLAIN_SCALAR_STYLE); + if (!key) goto document_error; + value = yaml_document_add_scalar(&output_document, NULL, + input_event.data.alias.anchor, -1, + YAML_DOUBLE_QUOTED_SCALAR_STYLE); + if (!value) goto document_error; + if (!yaml_document_append_mapping_pair(&output_document, + properties, key, value)) goto document_error; + + break; + + case YAML_SCALAR_EVENT: + + /* Add 'type': 'SCALAR'. */ + + key = yaml_document_add_scalar(&output_document, NULL, + "type", -1, YAML_PLAIN_SCALAR_STYLE); + if (!key) goto document_error; + value = yaml_document_add_scalar(&output_document, NULL, + "SCALAR", -1, YAML_PLAIN_SCALAR_STYLE); + if (!value) goto document_error; + if (!yaml_document_append_mapping_pair(&output_document, + properties, key, value)) goto document_error; + + /* Add 'anchor': . */ + + if (input_event.data.scalar.anchor) + { + key = yaml_document_add_scalar(&output_document, NULL, + "anchor", -1, YAML_PLAIN_SCALAR_STYLE); + if (!key) goto document_error; + value = yaml_document_add_scalar(&output_document, NULL, + input_event.data.scalar.anchor, -1, + YAML_DOUBLE_QUOTED_SCALAR_STYLE); + if (!value) goto document_error; + if (!yaml_document_append_mapping_pair(&output_document, + properties, key, value)) goto document_error; + } + + /* Add 'tag': . */ + + if (input_event.data.scalar.tag) + { + key = yaml_document_add_scalar(&output_document, NULL, + "tag", -1, YAML_PLAIN_SCALAR_STYLE); + if (!key) goto document_error; + value = yaml_document_add_scalar(&output_document, NULL, + input_event.data.scalar.tag, -1, + YAML_DOUBLE_QUOTED_SCALAR_STYLE); + if (!value) goto document_error; + if (!yaml_document_append_mapping_pair(&output_document, + properties, key, value)) goto document_error; + } + + /* Add 'value': . */ + + key = yaml_document_add_scalar(&output_document, NULL, + "value", -1, YAML_PLAIN_SCALAR_STYLE); + if (!key) goto document_error; + value = yaml_document_add_scalar(&output_document, NULL, + input_event.data.scalar.value, + input_event.data.scalar.length, + YAML_DOUBLE_QUOTED_SCALAR_STYLE); + if (!value) goto document_error; + if (!yaml_document_append_mapping_pair(&output_document, + properties, key, value)) goto document_error; + + /* Display if the scalar tag is implicit. */ + + /* Add 'implicit': {} */ + + key = yaml_document_add_scalar(&output_document, NULL, + "version", -1, YAML_PLAIN_SCALAR_STYLE); + if (!key) goto document_error; + map = yaml_document_add_mapping(&output_document, NULL, + YAML_FLOW_MAPPING_STYLE); + if (!map) goto document_error; + if (!yaml_document_append_mapping_pair(&output_document, + properties, key, map)) goto document_error; + + /* Add 'plain': . */ + + key = yaml_document_add_scalar(&output_document, NULL, + "plain", -1, YAML_PLAIN_SCALAR_STYLE); + if (!key) goto document_error; + value = yaml_document_add_scalar(&output_document, YAML_BOOL_TAG, + (input_event.data.scalar.plain_implicit ? + "true" : "false"), -1, YAML_PLAIN_SCALAR_STYLE); + if (!value) goto document_error; + if (!yaml_document_append_mapping_pair(&output_document, + map, key, value)) goto document_error; + + /* Add 'quoted': . */ + + key = yaml_document_add_scalar(&output_document, NULL, + "quoted", -1, YAML_PLAIN_SCALAR_STYLE); + if (!key) goto document_error; + value = yaml_document_add_scalar(&output_document, YAML_BOOL_TAG, + (input_event.data.scalar.quoted_implicit ? + "true" : "false"), -1, YAML_PLAIN_SCALAR_STYLE); + if (!value) goto document_error; + if (!yaml_document_append_mapping_pair(&output_document, + map, key, value)) goto document_error; + + /* Display the style information. */ + + if (input_event.data.scalar.style) + { + yaml_scalar_style_t style = input_event.data.scalar.style; + + /* Add 'style':